diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/boot/misc.c linux-libre-4.10-rc8-gnu/arch/alpha/boot/misc.c
--- linux-libre-4.9-gnu/arch/alpha/boot/misc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/boot/misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define memzero(s,n)	memset ((s),0,(n))
 #define puts		srm_printk
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/alpha/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/alpha/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/alpha/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/alpha/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,6 @@ unsigned long get_wchan(struct task_stru
   ((tsk) == current ? rdusp() : task_thread_info(tsk)->pcb.usp)
 
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/alpha/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/alpha/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -97,4 +97,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _UAPI_ASM_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/irq.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/bitops.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 volatile unsigned long irq_err_count;
 DEFINE_PER_CPU(unsigned long, irq_pmi_count);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/osf_sys.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/osf_sys.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/osf_sys.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/osf_sys.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@
 
 #include <asm/fpu.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sysinfo.h>
 #include <asm/thread_info.h>
 #include <asm/hwrpb.h>
@@ -1029,11 +1029,16 @@ SYSCALL_DEFINE2(osf_settimeofday, struct
 	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
+asmlinkage long sys_ni_posix_timers(void);
+
 SYSCALL_DEFINE2(osf_getitimer, int, which, struct itimerval32 __user *, it)
 {
 	struct itimerval kit;
 	int error;
 
+	if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
+		return sys_ni_posix_timers();
+
 	error = do_getitimer(which, &kit);
 	if (!error && put_it32(it, &kit))
 		error = -EFAULT;
@@ -1047,6 +1052,9 @@ SYSCALL_DEFINE3(osf_setitimer, int, whic
 	struct itimerval kin, kout;
 	int error;
 
+	if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
+		return sys_ni_posix_timers();
+
 	if (in) {
 		if (get_it32(&kin, in))
 			return -EFAULT;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/process.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/process.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/rcupdate.h>
 
 #include <asm/reg.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/hwrpb.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/tracehook.h>
 #include <linux/audit.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/fpu.h>
 
@@ -283,7 +283,7 @@ long arch_ptrace(struct task_struct *chi
 	/* When I and D space are separate, these will need to be fixed.  */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */
 	case PTRACE_PEEKDATA:
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp),
+		copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp),
 				FOLL_FORCE);
 		ret = -EIO;
 		if (copied != sizeof(tmp))
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/setup.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@ static struct notifier_block alpha_panic
         INT_MAX /* try to do it first */
 };
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/hwrpb.h>
 #include <asm/dma.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/signal.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/syscalls.h>
 #include <linux/tracehook.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sigcontext.h>
 #include <asm/ucontext.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/srmcons.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/srmcons.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/srmcons.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/srmcons.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/tty_flip.h>
 
 #include <asm/console.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 static DEFINE_SPINLOCK(srmcons_callback_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/srm_env.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/srm_env.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/srm_env.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/srm_env.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <asm/console.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/machvec.h>
 
 #define BASE_DIR	"srm_environment"	/* Subdir in /proc/		*/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/time.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/time.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/profile.h>
 #include <linux/irq_work.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/hwrpb.h>
 
@@ -133,7 +133,7 @@ init_rtc_clockevent(void)
  * The QEMU clock as a clocksource primitive.
  */
 
-static cycle_t
+static u64
 qemu_cs_read(struct clocksource *cs)
 {
 	return qemu_get_vmtime();
@@ -260,7 +260,7 @@ common_init_rtc(void)
  * use this method when WTINT is in use.
  */
 
-static cycle_t read_rpcc(struct clocksource *cs)
+static u64 read_rpcc(struct clocksource *cs)
 {
 	return rpcc();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/alpha/kernel/traps.c
--- linux-libre-4.9-gnu/arch/alpha/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/ratelimit.h>
 
 #include <asm/gentrap.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 #include <asm/sysinfo.h>
 #include <asm/hwrpb.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/lib/csum_partial_copy.c linux-libre-4.10-rc8-gnu/arch/alpha/lib/csum_partial_copy.c
--- linux-libre-4.9-gnu/arch/alpha/lib/csum_partial_copy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/lib/csum_partial_copy.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/string.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 #define ldq_u(x,y) \
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/math-emu/math.c linux-libre-4.10-rc8-gnu/arch/alpha/math-emu/math.c
--- linux-libre-4.9-gnu/arch/alpha/math-emu/math.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/math-emu/math.c	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "sfp-util.h"
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/alpha/mm/init.c linux-libre-4.10-rc8-gnu/arch/alpha/mm/init.c
--- linux-libre-4.9-gnu/arch/alpha/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/alpha/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/vmalloc.h>
 #include <linux/gfp.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/hwrpb.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi
--- linux-libre-4.9-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/abilis_tb10x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -129,6 +129,7 @@
 			data-width = <4>;
 			clocks = <&ahb_clk>;
 			clock-names = "hclk";
+			multi-block = <1 1 1 1 1 1>;
 		};
 
 		i2c0: i2c@FF120000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/boot/dts/axs101.dts linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/axs101.dts
--- linux-libre-4.9-gnu/arch/arc/boot/dts/axs101.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/axs101.dts	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,6 @@
 	compatible = "snps,axs101", "snps,arc-sdp";
 
 	chosen {
-		bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0";
+		bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0 video=1280x720@60";
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/boot/dts/axs103_idu.dts linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/axs103_idu.dts
--- linux-libre-4.9-gnu/arch/arc/boot/dts/axs103_idu.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/axs103_idu.dts	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,6 @@
 	compatible = "snps,axs103", "snps,arc-sdp";
 
 	chosen {
-		bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=ttyS3,115200n8 debug print-fatal-signals=1";
+		bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 print-fatal-signals=1 consoleblank=0 video=1280x720@60";
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/boot/dts/haps_hs.dts linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/haps_hs.dts
--- linux-libre-4.9-gnu/arch/arc/boot/dts/haps_hs.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/haps_hs.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016-2014 Synopsys, Inc. (www.synopsys.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/ "skeleton_hs.dtsi"
+
+/ {
+	model = "snps,zebu_hs";
+	compatible = "snps,zebu_hs";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&core_intc>;
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;	/* 512 */
+	};
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=ttyS0,115200n8 debug print-fatal-signals=1";
+	};
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	fpga {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* child and parent address space 1:1 mapped */
+		ranges;
+
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <50000000>;
+		};
+
+		core_intc: interrupt-controller {
+			compatible = "snps,archs-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+		};
+
+		uart0: serial@f0000000 {
+			compatible = "ns8250";
+			reg = <0xf0000000 0x2000>;
+			interrupts = <24>;
+			clock-frequency = <50000000>;
+			baud = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			no-loopback-test = <1>;
+		};
+
+		arcpct0: pct {
+			compatible = "snps,archs-pct";
+			#interrupt-cells = <1>;
+			interrupts = <20>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/boot/dts/haps_hs_idu.dts linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/haps_hs_idu.dts
--- linux-libre-4.9-gnu/arch/arc/boot/dts/haps_hs_idu.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/haps_hs_idu.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016-2014 Synopsys, Inc. (www.synopsys.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/ "skeleton_hs_idu.dtsi"
+
+/ {
+	model = "snps,zebu_hs-smp";
+	compatible = "snps,zebu_hs";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&core_intc>;
+
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>;	/* 512 */
+	};
+
+	chosen {
+		bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=ttyS0,115200n8 debug";
+	};
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	fpga {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		/* child and parent address space 1:1 mapped */
+		ranges;
+
+		core_clk: core_clk {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <50000000>;	/* 50 MHZ */
+		};
+
+		core_intc: interrupt-controller {
+			compatible = "snps,archs-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+/*			interrupts = <16 17 18 19 20 21 22 23 24 25>; */
+		};
+
+		idu_intc: idu-interrupt-controller {
+			compatible = "snps,archs-idu-intc";
+			interrupt-controller;
+			interrupt-parent = <&core_intc>;
+			/* <hwirq  distribution>
+			distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3 */
+			#interrupt-cells = <2>;
+			interrupts = <24 25 26 27 28 29 30 31>;
+
+		};
+
+		uart0: serial@f0000000 {
+			/* compatible = "ns8250"; Doesn't use FIFOs */
+			compatible = "ns16550a";
+			reg = <0xf0000000 0x2000>;
+			interrupt-parent = <&idu_intc>;
+			/* interrupts = <0 1>;  DEST=1*/
+			/* interrupts = <0 2>;  DEST=2*/
+			interrupts = <0 0>;  /* RR*/
+			clock-frequency = <50000000>;
+			baud = <115200>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			no-loopback-test = <1>;
+		};
+
+		arcpct0: pct {
+			compatible = "snps,archs-pct";
+			#interrupt-cells = <1>;
+			interrupts = <20>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/boot/dts/zebu_hs.dts linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/zebu_hs.dts
--- linux-libre-4.9-gnu/arch/arc/boot/dts/zebu_hs.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/zebu_hs.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2016-2014 Synopsys, Inc. (www.synopsys.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/ "skeleton_hs.dtsi"
-
-/ {
-	model = "snps,zebu_hs";
-	compatible = "snps,zebu_hs";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	interrupt-parent = <&core_intc>;
-
-	memory {
-		device_type = "memory";
-		reg = <0x80000000 0x20000000>;	/* 512 */
-	};
-
-	chosen {
-		bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=ttyS0,115200n8 debug print-fatal-signals=1";
-	};
-
-	aliases {
-		serial0 = &uart0;
-	};
-
-	fpga {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		/* child and parent address space 1:1 mapped */
-		ranges;
-
-		core_clk: core_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <50000000>;
-		};
-
-		core_intc: interrupt-controller {
-			compatible = "snps,archs-intc";
-			interrupt-controller;
-			#interrupt-cells = <1>;
-		};
-
-		uart0: serial@f0000000 {
-			compatible = "ns8250";
-			reg = <0xf0000000 0x2000>;
-			interrupts = <24>;
-			clock-frequency = <50000000>;
-			baud = <115200>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
-			no-loopback-test = <1>;
-		};
-
-		arcpct0: pct {
-			compatible = "snps,archs-pct";
-			#interrupt-cells = <1>;
-			interrupts = <20>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/boot/dts/zebu_hs_idu.dts linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/zebu_hs_idu.dts
--- linux-libre-4.9-gnu/arch/arc/boot/dts/zebu_hs_idu.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/boot/dts/zebu_hs_idu.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2016-2014 Synopsys, Inc. (www.synopsys.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/ "skeleton_hs_idu.dtsi"
-
-/ {
-	model = "snps,zebu_hs-smp";
-	compatible = "snps,zebu_hs";
-	#address-cells = <1>;
-	#size-cells = <1>;
-	interrupt-parent = <&core_intc>;
-
-	memory {
-		device_type = "memory";
-		reg = <0x80000000 0x20000000>;	/* 512 */
-	};
-
-	chosen {
-		bootargs = "earlycon=uart8250,mmio32,0xf0000000,115200n8 console=ttyS0,115200n8 debug";
-	};
-
-	aliases {
-		serial0 = &uart0;
-	};
-
-	fpga {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		/* child and parent address space 1:1 mapped */
-		ranges;
-
-		core_clk: core_clk {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <50000000>;	/* 50 MHZ */
-		};
-
-		core_intc: interrupt-controller {
-			compatible = "snps,archs-intc";
-			interrupt-controller;
-			#interrupt-cells = <1>;
-/*			interrupts = <16 17 18 19 20 21 22 23 24 25>; */
-		};
-
-		idu_intc: idu-interrupt-controller {
-			compatible = "snps,archs-idu-intc";
-			interrupt-controller;
-			interrupt-parent = <&core_intc>;
-			/* <hwirq  distribution>
-			distribution: 0=RR; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3 */
-			#interrupt-cells = <2>;
-			interrupts = <24 25 26 27 28 29 30 31>;
-
-		};
-
-		uart0: serial@f0000000 {
-			/* compatible = "ns8250"; Doesn't use FIFOs */
-			compatible = "ns16550a";
-			reg = <0xf0000000 0x2000>;
-			interrupt-parent = <&idu_intc>;
-			/* interrupts = <0 1>;  DEST=1*/
-			/* interrupts = <0 2>;  DEST=2*/
-			interrupts = <0 0>;  /* RR*/
-			clock-frequency = <50000000>;
-			baud = <115200>;
-			reg-shift = <2>;
-			reg-io-width = <4>;
-			no-loopback-test = <1>;
-		};
-
-		arcpct0: pct {
-			compatible = "snps,archs-pct";
-			#interrupt-cells = <1>;
-			interrupts = <20>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/axs101_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/axs101_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/axs101_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/axs101_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -75,9 +75,11 @@ CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
+CONFIG_DRM=m
+CONFIG_DRM_I2C_ADV7511=m
+CONFIG_DRM_ARCPGU=m
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/axs103_smp_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/axs103_smp_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/axs103_smp_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/axs103_smp_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -77,9 +77,11 @@ CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 # CONFIG_HWMON is not set
+CONFIG_DRM=m
+CONFIG_DRM_I2C_ADV7511=m
+CONFIG_DRM_ARCPGU=m
 CONFIG_FB=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/haps_hs_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/haps_hs_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/haps_hs_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/haps_hs_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,86 @@
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../../arc_initramfs_hs/"
+CONFIG_EXPERT=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=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_ARC_PLAT_SIM=y
+CONFIG_ISA_ARCV2=y
+CONFIG_ARC_BUILTIN_DTB_NAME="haps_hs"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NET_KEY=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_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_BLK_DEV is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_ARC_PS2=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_PREEMPT is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/haps_hs_smp_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/haps_hs_smp_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/haps_hs_smp_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/haps_hs_smp_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,89 @@
+CONFIG_DEFAULT_HOSTNAME="ARCLinux"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE="../../arc_initramfs_hs/"
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=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_ARC_PLAT_SIM=y
+CONFIG_ISA_ARCV2=y
+CONFIG_SMP=y
+CONFIG_ARC_BUILTIN_DTB_NAME="haps_hs_idu"
+CONFIG_PREEMPT=y
+# CONFIG_COMPACTION is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
+CONFIG_NET_KEY=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_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_DEVTMPFS=y
+# CONFIG_STANDALONE is not set
+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+# CONFIG_BLK_DEV is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_MOUSE_PS2_TOUCHKIT=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_ARC_PS2=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_8250_DW=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_HID is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_TMPFS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_DEBUG_PREEMPT is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/nsimosci_hs_smp_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/nsimosci_hs_smp_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/nsimosci_hs_smp_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/nsimosci_hs_smp_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@ CONFIG_MODULES=y
 CONFIG_ARC_PLAT_SIM=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
-# CONFIG_ARC_HAS_GFRC is not set
+# CONFIG_ARC_TIMERS_64BIT is not set
 CONFIG_ARC_BUILTIN_DTB_NAME="nsimosci_hs_idu"
 CONFIG_PREEMPT=y
 # CONFIG_COMPACTION is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/vdk_hs38_smp_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/vdk_hs38_smp_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/vdk_hs38_smp_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/vdk_hs38_smp_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@ CONFIG_ARC_PLAT_AXS10X=y
 CONFIG_AXS103=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
-# CONFIG_ARC_HAS_GFRC is not set
+# CONFIG_ARC_TIMERS_64BIT is not set
 CONFIG_ARC_UBOOT_SUPPORT=y
 CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp"
 CONFIG_PREEMPT=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/zebu_hs_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/zebu_hs_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/zebu_hs_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/zebu_hs_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-CONFIG_DEFAULT_HOSTNAME="ARCLinux"
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_CROSS_MEMORY_ATTACH is not set
-CONFIG_NO_HZ_IDLE=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_NAMESPACES=y
-# CONFIG_UTS_NS is not set
-# CONFIG_PID_NS is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE="../../arc_initramfs_hs/"
-CONFIG_EXPERT=y
-CONFIG_PERF_EVENTS=y
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-CONFIG_MODULES=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_ARC_PLAT_SIM=y
-CONFIG_ISA_ARCV2=y
-CONFIG_ARC_BUILTIN_DTB_NAME="zebu_hs"
-CONFIG_PREEMPT=y
-# CONFIG_COMPACTION is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_PACKET_DIAG=y
-CONFIG_UNIX=y
-CONFIG_UNIX_DIAG=y
-CONFIG_NET_KEY=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_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_DEVTMPFS=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-# CONFIG_BLK_DEV is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
-# CONFIG_WLAN is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_MOUSE_PS2_TOUCHKIT=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIO_ARC_PS2=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_8250_RUNTIME_UARTS=1
-CONFIG_SERIAL_8250_DW=y
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_HID is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_DEBUG_MEMORY_INIT=y
-# CONFIG_DEBUG_PREEMPT is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/configs/zebu_hs_smp_defconfig linux-libre-4.10-rc8-gnu/arch/arc/configs/zebu_hs_smp_defconfig
--- linux-libre-4.9-gnu/arch/arc/configs/zebu_hs_smp_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/configs/zebu_hs_smp_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,89 +0,0 @@
-CONFIG_DEFAULT_HOSTNAME="ARCLinux"
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_CROSS_MEMORY_ATTACH is not set
-CONFIG_NO_HZ_IDLE=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_NAMESPACES=y
-# CONFIG_UTS_NS is not set
-# CONFIG_PID_NS is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE="../../arc_initramfs_hs/"
-CONFIG_EMBEDDED=y
-CONFIG_PERF_EVENTS=y
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=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_ARC_PLAT_SIM=y
-CONFIG_ISA_ARCV2=y
-CONFIG_SMP=y
-CONFIG_ARC_BUILTIN_DTB_NAME="zebu_hs_idu"
-CONFIG_PREEMPT=y
-# CONFIG_COMPACTION is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_PACKET_DIAG=y
-CONFIG_UNIX=y
-CONFIG_UNIX_DIAG=y
-CONFIG_NET_KEY=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_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_DEVTMPFS=y
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_FIRMWARE_IN_KERNEL is not set
-# CONFIG_BLK_DEV is not set
-CONFIG_NETDEVICES=y
-# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_BROADCOM is not set
-# CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_MARVELL is not set
-# CONFIG_NET_VENDOR_MICREL is not set
-# CONFIG_NET_VENDOR_NATSEMI is not set
-# CONFIG_NET_VENDOR_SEEQ is not set
-# CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_VIA is not set
-# CONFIG_NET_VENDOR_WIZNET is not set
-# CONFIG_WLAN is not set
-CONFIG_INPUT_EVDEV=y
-CONFIG_MOUSE_PS2_TOUCHKIT=y
-# CONFIG_SERIO_SERPORT is not set
-CONFIG_SERIO_ARC_PS2=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=1
-CONFIG_SERIAL_8250_RUNTIME_UARTS=1
-CONFIG_SERIAL_8250_DW=y
-CONFIG_SERIAL_OF_PLATFORM=y
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-CONFIG_FB=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_LOGO=y
-# CONFIG_HID is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_IOMMU_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_TMPFS=y
-# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_NFS_FS=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_LOCKUP_DETECTOR=y
-# CONFIG_DEBUG_PREEMPT is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/arcregs.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/arcregs.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/arcregs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/arcregs.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,6 @@
 #define ARC_REG_FP_V2_BCR	0xc8	/* ARCv2 FPU */
 #define ARC_REG_SLC_BCR		0xce
 #define ARC_REG_DCCM_BUILD	0x74	/* DCCM size (common) */
-#define ARC_REG_TIMERS_BCR	0x75
 #define ARC_REG_AP_BCR		0x76
 #define ARC_REG_ICCM_BUILD	0x78	/* ICCM size (common) */
 #define ARC_REG_XY_MEM_BCR	0x79
@@ -112,90 +111,7 @@
 
 #ifndef __ASSEMBLY__
 
-/*
- ******************************************************************
- *      Inline ASM macros to read/write AUX Regs
- *      Essentially invocation of lr/sr insns from "C"
- */
-
-#if 1
-
-#define read_aux_reg(reg)	__builtin_arc_lr(reg)
-
-/* gcc builtin sr needs reg param to be long immediate */
-#define write_aux_reg(reg_immed, val)		\
-		__builtin_arc_sr((unsigned int)(val), reg_immed)
-
-#else
-
-#define read_aux_reg(reg)		\
-({					\
-	unsigned int __ret;		\
-	__asm__ __volatile__(		\
-	"	lr    %0, [%1]"		\
-	: "=r"(__ret)			\
-	: "i"(reg));			\
-	__ret;				\
-})
-
-/*
- * Aux Reg address is specified as long immediate by caller
- * e.g.
- *    write_aux_reg(0x69, some_val);
- * This generates tightest code.
- */
-#define write_aux_reg(reg_imm, val)	\
-({					\
-	__asm__ __volatile__(		\
-	"	sr   %0, [%1]	\n"	\
-	:				\
-	: "ir"(val), "i"(reg_imm));	\
-})
-
-/*
- * Aux Reg address is specified in a variable
- *  * e.g.
- *      reg_num = 0x69
- *      write_aux_reg2(reg_num, some_val);
- * This has to generate glue code to load the reg num from
- *  memory to a reg hence not recommended.
- */
-#define write_aux_reg2(reg_in_var, val)		\
-({						\
-	unsigned int tmp;			\
-						\
-	__asm__ __volatile__(			\
-	"	ld   %0, [%2]	\n\t"		\
-	"	sr   %1, [%0]	\n\t"		\
-	: "=&r"(tmp)				\
-	: "r"(val), "memory"(&reg_in_var));	\
-})
-
-#endif
-
-#define READ_BCR(reg, into)				\
-{							\
-	unsigned int tmp;				\
-	tmp = read_aux_reg(reg);			\
-	if (sizeof(tmp) == sizeof(into)) {		\
-		into = *((typeof(into) *)&tmp);		\
-	} else {					\
-		extern void bogus_undefined(void);	\
-		bogus_undefined();			\
-	}						\
-}
-
-#define WRITE_AUX(reg, into)				\
-{							\
-	unsigned int tmp;				\
-	if (sizeof(tmp) == sizeof(into)) {		\
-		tmp = (*(unsigned int *)&(into));	\
-		write_aux_reg(reg, tmp);		\
-	} else  {					\
-		extern void bogus_undefined(void);	\
-		bogus_undefined();			\
-	}						\
-}
+#include <soc/arc/aux.h>
 
 /* Helpers */
 #define TO_KB(bytes)		((bytes) >> 10)
@@ -291,13 +207,7 @@ struct bcr_fp_arcv2 {
 #endif
 };
 
-struct bcr_timer {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-	unsigned int pad2:15, rtsc:1, pad1:5, rtc:1, t1:1, t0:1, ver:8;
-#else
-	unsigned int ver:8, t0:1, t1:1, rtc:1, pad1:5, rtsc:1, pad2:15;
-#endif
-};
+#include <soc/arc/timers.h>
 
 struct bcr_bpu_arcompact {
 #ifdef CONFIG_CPU_BIG_ENDIAN
@@ -334,7 +244,7 @@ struct cpuinfo_arc_mmu {
 };
 
 struct cpuinfo_arc_cache {
-	unsigned int sz_k:14, line_len:8, assoc:4, ver:4, alias:1, vipt:1;
+	unsigned int sz_k:14, line_len:8, assoc:4, alias:1, vipt:1, pad:4;
 };
 
 struct cpuinfo_arc_bpu {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/cacheflush.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/cacheflush.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/cacheflush.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/cacheflush.h	2017-02-12 16:03:20.000000000 -0500
@@ -85,6 +85,10 @@ void flush_anon_page(struct vm_area_stru
  */
 #define PG_dc_clean	PG_arch_1
 
+#define CACHE_COLORS_NUM	4
+#define CACHE_COLORS_MSK	(CACHE_COLORS_NUM - 1)
+#define CACHE_COLOR(addr)	(((unsigned long)(addr) >> (PAGE_SHIFT)) & CACHE_COLORS_MSK)
+
 /*
  * Simple wrapper over config option
  * Bootup code ensures that hardware matches kernel configuration
@@ -94,8 +98,6 @@ static inline int cache_is_vipt_aliasing
 	return IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
 }
 
-#define CACHE_COLOR(addr)	(((unsigned long)(addr) >> (PAGE_SHIFT)) & 1)
-
 /*
  * checks if two addresses (after page aligning) index into same cache set
  */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/cache.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/cache.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/cache.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/cache.h	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@ extern unsigned long perip_base, perip_e
 #define ARC_REG_IC_PTAG_HI	0x1F
 
 /* Bit val in IC_CTRL */
-#define IC_CTRL_CACHE_DISABLE   0x1
+#define IC_CTRL_DIS		0x1
 
 /* Data cache related Auxiliary registers */
 #define ARC_REG_DC_BCR		0x72	/* Build Config reg */
@@ -80,8 +80,9 @@ extern unsigned long perip_base, perip_e
 #define ARC_REG_DC_PTAG_HI	0x5F
 
 /* Bit val in DC_CTRL */
-#define DC_CTRL_INV_MODE_FLUSH  0x40
-#define DC_CTRL_FLUSH_STATUS    0x100
+#define DC_CTRL_DIS		0x001
+#define DC_CTRL_INV_MODE_FLUSH	0x040
+#define DC_CTRL_FLUSH_STATUS	0x100
 
 /*System-level cache (L2 cache) related Auxiliary registers */
 #define ARC_REG_SLC_CFG		0x901
@@ -92,8 +93,8 @@ extern unsigned long perip_base, perip_e
 #define ARC_REG_SLC_RGN_END	0x916
 
 /* Bit val in SLC_CONTROL */
+#define SLC_CTRL_DIS		0x001
 #define SLC_CTRL_IM		0x040
-#define SLC_CTRL_DISABLE	0x001
 #define SLC_CTRL_BUSY		0x100
 #define SLC_CTRL_RGN_OP_INV	0x200
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/delay.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/delay.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/delay.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/delay.h	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,9 @@ static inline void __delay(unsigned long
 	"	lp  1f			\n"
 	"	nop			\n"
 	"1:				\n"
-	: : "r"(loops));
+	:
+        : "r"(loops)
+        : "lp_count");
 }
 
 extern void __bad_udelay(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/entry-arcv2.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/entry-arcv2.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/entry-arcv2.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/entry-arcv2.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 	;
 	; Now manually save: r12, sp, fp, gp, r25
 
+	PUSH	r30
 	PUSH	r12
 
 	; Saving pt_regs->sp correctly requires some extra work due to the way
@@ -72,6 +73,7 @@
 	POPAX	AUX_USER_SP
 1:
 	POP	r12
+	POP	r30
 
 .endm
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/irqflags-arcv2.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/irqflags-arcv2.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/irqflags-arcv2.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/irqflags-arcv2.h	2017-02-12 16:03:20.000000000 -0500
@@ -38,10 +38,10 @@
 #define AUX_IRQ_ACT_BIT_U	31
 
 /*
- * User space should be interruptable even by lowest prio interrupt
- * Safe even if actual interrupt priorities is fewer or even one
+ * Hardware supports 16 priorities (0 highest, 15 lowest)
+ * Linux by default runs at 1, priority 0 reserved for NMI style interrupts
  */
-#define ARCV2_IRQ_DEF_PRIO	15
+#define ARCV2_IRQ_DEF_PRIO	1
 
 /* seed value for status register */
 #define ISA_INIT_STATUS_BITS	(STATUS_IE_MASK | STATUS_AD_MASK | \
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/mcip.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/mcip.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/mcip.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/mcip.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/*
- * ARConnect IP Support (Multi core enabler: Cross core IPI, RTC ...)
- *
- * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.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_MCIP_H
-#define __ASM_MCIP_H
-
-#ifdef CONFIG_ISA_ARCV2
-
-#include <asm/arcregs.h>
-
-#define ARC_REG_MCIP_BCR	0x0d0
-#define ARC_REG_MCIP_CMD	0x600
-#define ARC_REG_MCIP_WDATA	0x601
-#define ARC_REG_MCIP_READBACK	0x602
-
-struct mcip_cmd {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-	unsigned int pad:8, param:16, cmd:8;
-#else
-	unsigned int cmd:8, param:16, pad:8;
-#endif
-
-#define CMD_INTRPT_GENERATE_IRQ		0x01
-#define CMD_INTRPT_GENERATE_ACK		0x02
-#define CMD_INTRPT_READ_STATUS		0x03
-#define CMD_INTRPT_CHECK_SOURCE		0x04
-
-/* Semaphore Commands */
-#define CMD_SEMA_CLAIM_AND_READ		0x11
-#define CMD_SEMA_RELEASE		0x12
-
-#define CMD_DEBUG_SET_MASK		0x34
-#define CMD_DEBUG_SET_SELECT		0x36
-
-#define CMD_GFRC_READ_LO		0x42
-#define CMD_GFRC_READ_HI		0x43
-
-#define CMD_IDU_ENABLE			0x71
-#define CMD_IDU_DISABLE			0x72
-#define CMD_IDU_SET_MODE		0x74
-#define CMD_IDU_SET_DEST		0x76
-#define CMD_IDU_SET_MASK		0x7C
-
-#define IDU_M_TRIG_LEVEL		0x0
-#define IDU_M_TRIG_EDGE			0x1
-
-#define IDU_M_DISTRI_RR			0x0
-#define IDU_M_DISTRI_DEST		0x2
-};
-
-struct mcip_bcr {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-		unsigned int pad3:8,
-			     idu:1, llm:1, num_cores:6,
-			     iocoh:1,  gfrc:1, dbg:1, pad2:1,
-			     msg:1, sem:1, ipi:1, pad:1,
-			     ver:8;
-#else
-		unsigned int ver:8,
-			     pad:1, ipi:1, sem:1, msg:1,
-			     pad2:1, dbg:1, gfrc:1, iocoh:1,
-			     num_cores:6, llm:1, idu:1,
-			     pad3:8;
-#endif
-};
-
-/*
- * MCIP programming model
- *
- * - Simple commands write {cmd:8,param:16} to MCIP_CMD aux reg
- *   (param could be irq, common_irq, core_id ...)
- * - More involved commands setup MCIP_WDATA with cmd specific data
- *   before invoking the simple command
- */
-static inline void __mcip_cmd(unsigned int cmd, unsigned int param)
-{
-	struct mcip_cmd buf;
-
-	buf.pad = 0;
-	buf.cmd = cmd;
-	buf.param = param;
-
-	WRITE_AUX(ARC_REG_MCIP_CMD, buf);
-}
-
-/*
- * Setup additional data for a cmd
- * Callers need to lock to ensure atomicity
- */
-static inline void __mcip_cmd_data(unsigned int cmd, unsigned int param,
-				   unsigned int data)
-{
-	write_aux_reg(ARC_REG_MCIP_WDATA, data);
-
-	__mcip_cmd(cmd, param);
-}
-
-#endif
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/module.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/module.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/module.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/module.h	2017-02-12 16:03:20.000000000 -0500
@@ -14,13 +14,13 @@
 
 #include <asm-generic/module.h>
 
-#ifdef CONFIG_ARC_DW2_UNWIND
 struct mod_arch_specific {
+#ifdef CONFIG_ARC_DW2_UNWIND
 	void *unw_info;
 	int unw_sec_idx;
+#endif
 	const char *secstr;
 };
-#endif
 
 #define MODULE_PROC_FAMILY "ARC700"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
- */
-
-/*
- * xchg() based mutex fast path maintains a state of 0 or 1, as opposed to
- * atomic dec based which can "count" any number of lock contenders.
- * This ideally needs to be fixed in core, but for now switching to dec ver.
- */
-#if defined(CONFIG_SMP) && (CONFIG_NR_CPUS > 2)
-#include <asm-generic/mutex-dec.h>
-#else
-#include <asm-generic/mutex-xchg.h>
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -60,15 +60,12 @@ struct task_struct;
 #ifndef CONFIG_EZNPS_MTM_EXT
 
 #define cpu_relax()		barrier()
-#define cpu_relax_lowlatency()	cpu_relax()
 
 #else
 
 #define cpu_relax()     \
 	__asm__ __volatile__ (".word %0" : : "i"(CTOP_INST_SCHD_RW) : "memory")
 
-#define cpu_relax_lowlatency()	barrier()
-
 #endif
 
 #define copy_segments(tsk, mm)      do { } while (0)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/ptrace.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/ptrace.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/ptrace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/ptrace.h	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,7 @@ struct pt_regs {
 	unsigned long fp;
 	unsigned long sp;	/* user/kernel sp depending on where we came from  */
 
-	unsigned long r12;
+	unsigned long r12, r30;
 
 	/*------- Below list auto saved by h/w -----------*/
 	unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/include/asm/setup.h linux-libre-4.10-rc8-gnu/arch/arc/include/asm/setup.h
--- linux-libre-4.9-gnu/arch/arc/include/asm/setup.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/include/asm/setup.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@ extern int root_mountflags, end_mem;
 
 void setup_processor(void);
 void __init setup_arch_memory(void);
+long __init arc_get_mem_sz(void);
 
 /* Helpers used in arc_*_mumbojumbo routines */
 #define IS_AVAIL1(v, s)		((v) ? s : "")
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/Kconfig linux-libre-4.10-rc8-gnu/arch/arc/Kconfig
--- linux-libre-4.9-gnu/arch/arc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -8,9 +8,10 @@
 
 config ARC
 	def_bool y
+	select ARC_TIMERS
+	select ARCH_HAS_SG_CHAIN
 	select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
 	select BUILDTIME_EXTABLE_SORT
-	select CLKSRC_OF
 	select CLONE_BACKWARDS
 	select COMMON_CLK
 	select GENERIC_ATOMIC64 if !ISA_ARCV2 || !(ARC_HAS_LL64 && ARC_HAS_LLSC)
@@ -28,7 +29,7 @@ config ARC
 	select HAVE_KPROBES
 	select HAVE_KRETPROBES
 	select HAVE_MEMBLOCK
-	select HAVE_MOD_ARCH_SPECIFIC if ARC_DW2_UNWIND
+	select HAVE_MOD_ARCH_SPECIFIC
 	select HAVE_OPROFILE
 	select HAVE_PERF_EVENTS
 	select HANDLE_DOMAIN_IRQ
@@ -115,6 +116,7 @@ config ISA_ARCOMPACT
 
 config ISA_ARCV2
 	bool "ARC ISA v2"
+	select ARC_TIMERS_64BIT
 	help
 	  ISA for the Next Generation ARC-HS cores
 
@@ -410,16 +412,6 @@ config ARC_HAS_DIV_REM
 	bool "Insn: div, divu, rem, remu"
 	default y
 
-config ARC_HAS_RTC
-	bool "Local 64-bit r/o cycle counter"
-	default n
-	depends on !SMP
-
-config ARC_HAS_GFRC
-	bool "SMP synchronized 64-bit cycle counter"
-	default y
-	depends on SMP
-
 config ARC_NUMBER_OF_INTERRUPTS
 	int "Number of interrupts"
 	range 8 240
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/entry-arcv2.S linux-libre-4.10-rc8-gnu/arch/arc/kernel/entry-arcv2.S
--- linux-libre-4.9-gnu/arch/arc/kernel/entry-arcv2.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/entry-arcv2.S	2017-02-12 16:03:20.000000000 -0500
@@ -67,12 +67,23 @@ ENTRY(handle_interrupt)
 
 	INTERRUPT_PROLOGUE  irq
 
-	clri		; To make status32.IE agree with CPU internal state
+	# irq control APIs local_irq_save/restore/disable/enable fiddle with
+	# global interrupt enable bits in STATUS32 (.IE for 1 prio, .E[] for 2 prio)
+	# However a taken interrupt doesn't clear these bits. Thus irqs_disabled()
+	# query in hard ISR path would return false (since .IE is set) which would
+	# trips genirq interrupt handling asserts.
+	#
+	# So do a "soft" disable of interrutps here.
+	#
+	# Note this disable is only for consistent book-keeping as further interrupts
+	# will be disabled anyways even w/o this. Hardware tracks active interrupts
+	# seperately in AUX_IRQ_ACTIVE.active and will not take new interrupts
+	# unless this one returns (or higher prio becomes pending in 2-prio scheme)
 
-#ifdef CONFIG_TRACE_IRQFLAGS
-	TRACE_ASM_IRQ_DISABLE
-#endif
+	IRQ_DISABLE
 
+	; icause is banked: one per priority level
+	; so a higher prio interrupt taken here won't clobber prev prio icause
 	lr  r0, [ICAUSE]
 	mov   blink, ret_from_exception
 
@@ -171,6 +182,7 @@ END(EV_TLBProtV)
 ; All 2 entry points to here already disable interrupts
 
 .Lrestore_regs:
+restore_regs:
 
 	# Interrpts are actually disabled from this point on, but will get
 	# reenabled after we return from interrupt/exception.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/entry-compact.S linux-libre-4.10-rc8-gnu/arch/arc/kernel/entry-compact.S
--- linux-libre-4.9-gnu/arch/arc/kernel/entry-compact.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/entry-compact.S	2017-02-12 16:03:20.000000000 -0500
@@ -259,7 +259,7 @@ ENTRY(EV_TLBProtV)
 
 	EXCEPTION_PROLOGUE
 
-	lr  r2, [ecr]
+	mov r2, r9	; ECR set into r9 already
 	lr  r0, [efa]	; Faulting Data address (not part of pt_regs saved above)
 
 	; Exception auto-disables further Intr/exceptions.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/head.S linux-libre-4.10-rc8-gnu/arch/arc/kernel/head.S
--- linux-libre-4.9-gnu/arch/arc/kernel/head.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/head.S	2017-02-12 16:03:20.000000000 -0500
@@ -71,14 +71,14 @@ ENTRY(stext)
 	GET_CPU_ID  r5
 	cmp	r5, 0
 	mov.nz	r0, r5
-#ifdef CONFIG_ARC_SMP_HALT_ON_RESET
-	; Non-Master can proceed as system would be booted sufficiently
-	jnz	first_lines_of_secondary
-#else
+	bz	.Lmaster_proceed
+
 	; Non-Masters wait for Master to boot enough and bring them up
-	jnz	arc_platform_smp_wait_to_boot
-#endif
-	; Master falls thru
+	; when they resume, tail-call to entry point
+	mov	blink, @first_lines_of_secondary
+	j	arc_platform_smp_wait_to_boot
+
+.Lmaster_proceed:
 #endif
 
 	; Clear BSS before updating any globals
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/intc-arcv2.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/intc-arcv2.c
--- linux-libre-4.9-gnu/arch/arc/kernel/intc-arcv2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/intc-arcv2.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,8 +14,6 @@
 #include <linux/irqchip.h>
 #include <asm/irq.h>
 
-static int irq_prio;
-
 /*
  * Early Hardware specific Interrupt setup
  * -Called very early (start_kernel -> setup_arch -> setup_processor)
@@ -24,7 +22,7 @@ static int irq_prio;
  */
 void arc_init_IRQ(void)
 {
-	unsigned int tmp;
+	unsigned int tmp, irq_prio;
 
 	struct irq_build {
 #ifdef CONFIG_CPU_BIG_ENDIAN
@@ -67,33 +65,33 @@ void arc_init_IRQ(void)
 
 	irq_prio = irq_bcr.prio;	/* Encoded as N-1 for N levels */
 	pr_info("archs-intc\t: %d priority levels (default %d)%s\n",
-		irq_prio + 1, irq_prio,
+		irq_prio + 1, ARCV2_IRQ_DEF_PRIO,
 		irq_bcr.firq ? " FIRQ (not used)":"");
 
 	/* setup status32, don't enable intr yet as kernel doesn't want */
 	tmp = read_aux_reg(0xa);
-	tmp |= STATUS_AD_MASK | (irq_prio << 1);
+	tmp |= STATUS_AD_MASK | (ARCV2_IRQ_DEF_PRIO << 1);
 	tmp &= ~STATUS_IE_MASK;
 	asm volatile("kflag %0	\n"::"r"(tmp));
 }
 
 static void arcv2_irq_mask(struct irq_data *data)
 {
-	write_aux_reg(AUX_IRQ_SELECT, data->irq);
+	write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
 	write_aux_reg(AUX_IRQ_ENABLE, 0);
 }
 
 static void arcv2_irq_unmask(struct irq_data *data)
 {
-	write_aux_reg(AUX_IRQ_SELECT, data->irq);
+	write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
 	write_aux_reg(AUX_IRQ_ENABLE, 1);
 }
 
 void arcv2_irq_enable(struct irq_data *data)
 {
 	/* set default priority */
-	write_aux_reg(AUX_IRQ_SELECT, data->irq);
-	write_aux_reg(AUX_IRQ_PRIORITY, irq_prio);
+	write_aux_reg(AUX_IRQ_SELECT, data->hwirq);
+	write_aux_reg(AUX_IRQ_PRIORITY, ARCV2_IRQ_DEF_PRIO);
 
 	/*
 	 * hw auto enables (linux unmask) all by default
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/intc-compact.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/intc-compact.c
--- linux-libre-4.9-gnu/arch/arc/kernel/intc-compact.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/intc-compact.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@ static void arc_irq_mask(struct irq_data
 	unsigned int ienb;
 
 	ienb = read_aux_reg(AUX_IENABLE);
-	ienb &= ~(1 << data->irq);
+	ienb &= ~(1 << data->hwirq);
 	write_aux_reg(AUX_IENABLE, ienb);
 }
 
@@ -66,7 +66,7 @@ static void arc_irq_unmask(struct irq_da
 	unsigned int ienb;
 
 	ienb = read_aux_reg(AUX_IENABLE);
-	ienb |= (1 << data->irq);
+	ienb |= (1 << data->hwirq);
 	write_aux_reg(AUX_IENABLE, ienb);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/Makefile linux-libre-4.10-rc8-gnu/arch/arc/kernel/Makefile
--- linux-libre-4.9-gnu/arch/arc/kernel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
 # Pass UTS_MACHINE for user_regset definition
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
-obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
+obj-y	:= arcksyms.o setup.o irq.o reset.o ptrace.o process.o devtree.o
 obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o
 obj-$(CONFIG_ISA_ARCOMPACT)		+= entry-compact.o intc-compact.o
 obj-$(CONFIG_ISA_ARCV2)			+= entry-arcv2.o intc-arcv2.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/mcip.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/mcip.c
--- linux-libre-4.9-gnu/arch/arc/kernel/mcip.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/mcip.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,9 +10,10 @@
 
 #include <linux/smp.h>
 #include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/spinlock.h>
+#include <soc/arc/mcip.h>
 #include <asm/irqflags-arcv2.h>
-#include <asm/mcip.h>
 #include <asm/setup.h>
 
 static DEFINE_RAW_SPINLOCK(mcip_lock);
@@ -92,11 +93,10 @@ static void mcip_probe_n_setup(void)
 	READ_BCR(ARC_REG_MCIP_BCR, mp);
 
 	sprintf(smp_cpuinfo_buf,
-		"Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s%s\n",
+		"Extn [SMP]\t: ARConnect (v%d): %d cores with %s%s%s%s\n",
 		mp.ver, mp.num_cores,
 		IS_AVAIL1(mp.ipi, "IPI "),
 		IS_AVAIL1(mp.idu, "IDU "),
-		IS_AVAIL1(mp.llm, "LLM "),
 		IS_AVAIL1(mp.dbg, "DEBUG "),
 		IS_AVAIL1(mp.gfrc, "GFRC"));
 
@@ -174,7 +174,6 @@ static void idu_irq_unmask(struct irq_da
 	raw_spin_unlock_irqrestore(&mcip_lock, flags);
 }
 
-#ifdef CONFIG_SMP
 static int
 idu_irq_set_affinity(struct irq_data *data, const struct cpumask *cpumask,
 		     bool force)
@@ -204,12 +203,27 @@ idu_irq_set_affinity(struct irq_data *da
 
 	return IRQ_SET_MASK_OK;
 }
-#endif
+
+static void idu_irq_enable(struct irq_data *data)
+{
+	/*
+	 * By default send all common interrupts to all available online CPUs.
+	 * The affinity of common interrupts in IDU must be set manually since
+	 * in some cases the kernel will not call irq_set_affinity() by itself:
+	 *   1. When the kernel is not configured with support of SMP.
+	 *   2. When the kernel is configured with support of SMP but upper
+	 *      interrupt controllers does not support setting of the affinity
+	 *      and cannot propagate it to IDU.
+	 */
+	idu_irq_set_affinity(data, cpu_online_mask, false);
+	idu_irq_unmask(data);
+}
 
 static struct irq_chip idu_irq_chip = {
 	.name			= "MCIP IDU Intc",
 	.irq_mask		= idu_irq_mask,
 	.irq_unmask		= idu_irq_unmask,
+	.irq_enable		= idu_irq_enable,
 #ifdef CONFIG_SMP
 	.irq_set_affinity       = idu_irq_set_affinity,
 #endif
@@ -221,10 +235,13 @@ static irq_hw_number_t idu_first_hwirq;
 static void idu_cascade_isr(struct irq_desc *desc)
 {
 	struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
+	struct irq_chip *core_chip = irq_desc_get_chip(desc);
 	irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
 	irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
 
+	chained_irq_enter(core_chip, desc);
 	generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
+	chained_irq_exit(core_chip, desc);
 }
 
 static int idu_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hwirq)
@@ -239,36 +256,14 @@ static int idu_irq_xlate(struct irq_doma
 			 const u32 *intspec, unsigned int intsize,
 			 irq_hw_number_t *out_hwirq, unsigned int *out_type)
 {
-	irq_hw_number_t hwirq = *out_hwirq = intspec[0];
-	int distri = intspec[1];
-	unsigned long flags;
-
+	/*
+	 * Ignore value of interrupt distribution mode for common interrupts in
+	 * IDU which resides in intspec[1] since setting an affinity using value
+	 * from Device Tree is deprecated in ARC.
+	 */
+	*out_hwirq = intspec[0];
 	*out_type = IRQ_TYPE_NONE;
 
-	/* XXX: validate distribution scheme again online cpu mask */
-	if (distri == 0) {
-		/* 0 - Round Robin to all cpus, otherwise 1 bit per core */
-		raw_spin_lock_irqsave(&mcip_lock, flags);
-		idu_set_dest(hwirq, BIT(num_online_cpus()) - 1);
-		idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_RR);
-		raw_spin_unlock_irqrestore(&mcip_lock, flags);
-	} else {
-		/*
-		 * DEST based distribution for Level Triggered intr can only
-		 * have 1 CPU, so generalize it to always contain 1 cpu
-		 */
-		int cpu = ffs(distri);
-
-		if (cpu != fls(distri))
-			pr_warn("IDU irq %lx distri mode set to cpu %x\n",
-				hwirq, cpu);
-
-		raw_spin_lock_irqsave(&mcip_lock, flags);
-		idu_set_dest(hwirq, cpu);
-		idu_set_mode(hwirq, IDU_M_TRIG_LEVEL, IDU_M_DISTRI_DEST);
-		raw_spin_unlock_irqrestore(&mcip_lock, flags);
-	}
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/module.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/module.c
--- linux-libre-4.9-gnu/arch/arc/kernel/module.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/module.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,8 +32,8 @@ int module_frob_arch_sections(Elf_Ehdr *
 #ifdef CONFIG_ARC_DW2_UNWIND
 	mod->arch.unw_sec_idx = 0;
 	mod->arch.unw_info = NULL;
-	mod->arch.secstr = secstr;
 #endif
+	mod->arch.secstr = secstr;
 	return 0;
 }
 
@@ -113,8 +113,10 @@ int apply_relocate_add(Elf32_Shdr *sechd
 
 	}
 
+#ifdef CONFIG_ARC_DW2_UNWIND
 	if (strcmp(module->arch.secstr+sechdrs[tgtsec].sh_name, ".eh_frame") == 0)
 		module->arch.unw_sec_idx = tgtsec;
+#endif
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/setup.c
--- linux-libre-4.9-gnu/arch/arc/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,8 @@
 #include <linux/fs.h>
 #include <linux/delay.h>
 #include <linux/root_dev.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/cpu.h>
@@ -234,11 +236,11 @@ static char *arc_cpu_mumbojumbo(int cpu_
 		       is_isa_arcompact() ? "ARCompact" : "ARCv2",
 		       IS_AVAIL1(cpu->isa.be, "[Big-Endian]"));
 
-	n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ",
+	n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s%s%s\nISA Extn\t: ",
 		       IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
 		       IS_AVAIL1(cpu->extn.timer1, "Timer1 "),
-		       IS_AVAIL2(cpu->extn.rtc, "Local-64-bit-Ctr ",
-				 CONFIG_ARC_HAS_RTC));
+		       IS_AVAIL2(cpu->extn.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_TIMERS_64BIT),
+		       IS_AVAIL2(cpu->extn.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_TIMERS_64BIT));
 
 	n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s",
 			   IS_AVAIL2(cpu->isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC),
@@ -449,6 +451,15 @@ void __init setup_arch(char **cmdline_p)
 	arc_unwind_init();
 }
 
+/*
+ * Called from start_kernel() - boot CPU only
+ */
+void __init time_init(void)
+{
+	of_clk_init(NULL);
+	clocksource_probe();
+}
+
 static int __init customize_machine(void)
 {
 	if (machine_desc->init_machine)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/smp.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/smp.c
--- linux-libre-4.9-gnu/arch/arc/kernel/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -90,22 +90,37 @@ void __init smp_cpus_done(unsigned int m
  */
 static volatile int wake_flag;
 
+#ifdef CONFIG_ISA_ARCOMPACT
+
+#define __boot_read(f)		f
+#define __boot_write(f, v)	f = v
+
+#else
+
+#define __boot_read(f)		arc_read_uncached_32(&f)
+#define __boot_write(f, v)	arc_write_uncached_32(&f, v)
+
+#endif
+
 static void arc_default_smp_cpu_kick(int cpu, unsigned long pc)
 {
 	BUG_ON(cpu == 0);
-	wake_flag = cpu;
+
+	__boot_write(wake_flag, cpu);
 }
 
 void arc_platform_smp_wait_to_boot(int cpu)
 {
-	while (wake_flag != cpu)
+	/* for halt-on-reset, we've waited already */
+	if (IS_ENABLED(CONFIG_ARC_SMP_HALT_ON_RESET))
+		return;
+
+	while (__boot_read(wake_flag) != cpu)
 		;
 
-	wake_flag = 0;
-	__asm__ __volatile__("j @first_lines_of_secondary	\n");
+	__boot_write(wake_flag, 0);
 }
 
-
 const char *arc_platform_smp_cpuinfo(void)
 {
 	return plat_smp_ops.info ? : "";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/time.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/time.c
--- linux-libre-4.9-gnu/arch/arc/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,382 +0,0 @@
-/*
- * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
- *
- * vineetg: Jan 1011
- *  -sched_clock( ) no longer jiffies based. Uses the same clocksource
- *   as gtod
- *
- * Rajeshwarr/Vineetg: Mar 2008
- *  -Implemented CONFIG_GENERIC_TIME (rather deleted arch specific code)
- *   for arch independent gettimeofday()
- *  -Implemented CONFIG_GENERIC_CLOCKEVENTS as base for hrtimers
- *
- * Vineetg: Mar 2008: Forked off from time.c which now is time-jiff.c
- */
-
-/* ARC700 has two 32bit independent prog Timers: TIMER0 and TIMER1
- * Each can programmed to go from @count to @limit and optionally
- * interrupt when that happens.
- * A write to Control Register clears the Interrupt
- *
- * We've designated TIMER0 for events (clockevents)
- * while TIMER1 for free running (clocksource)
- *
- * Newer ARC700 cores have 64bit clk fetching RTSC insn, preferred over TIMER1
- * which however is currently broken
- */
-
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/clocksource.h>
-#include <linux/clockchips.h>
-#include <linux/cpu.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <asm/irq.h>
-#include <asm/arcregs.h>
-
-#include <asm/mcip.h>
-
-/* Timer related Aux registers */
-#define ARC_REG_TIMER0_LIMIT	0x23	/* timer 0 limit */
-#define ARC_REG_TIMER0_CTRL	0x22	/* timer 0 control */
-#define ARC_REG_TIMER0_CNT	0x21	/* timer 0 count */
-#define ARC_REG_TIMER1_LIMIT	0x102	/* timer 1 limit */
-#define ARC_REG_TIMER1_CTRL	0x101	/* timer 1 control */
-#define ARC_REG_TIMER1_CNT	0x100	/* timer 1 count */
-
-#define TIMER_CTRL_IE	(1 << 0) /* Interrupt when Count reaches limit */
-#define TIMER_CTRL_NH	(1 << 1) /* Count only when CPU NOT halted */
-
-#define ARC_TIMER_MAX	0xFFFFFFFF
-
-static unsigned long arc_timer_freq;
-
-static int noinline arc_get_timer_clk(struct device_node *node)
-{
-	struct clk *clk;
-	int ret;
-
-	clk = of_clk_get(node, 0);
-	if (IS_ERR(clk)) {
-		pr_err("timer missing clk");
-		return PTR_ERR(clk);
-	}
-
-	ret = clk_prepare_enable(clk);
-	if (ret) {
-		pr_err("Couldn't enable parent clk\n");
-		return ret;
-	}
-
-	arc_timer_freq = clk_get_rate(clk);
-
-	return 0;
-}
-
-/********** Clock Source Device *********/
-
-#ifdef CONFIG_ARC_HAS_GFRC
-
-static cycle_t arc_read_gfrc(struct clocksource *cs)
-{
-	unsigned long flags;
-	union {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-		struct { u32 h, l; };
-#else
-		struct { u32 l, h; };
-#endif
-		cycle_t  full;
-	} stamp;
-
-	local_irq_save(flags);
-
-	__mcip_cmd(CMD_GFRC_READ_LO, 0);
-	stamp.l = read_aux_reg(ARC_REG_MCIP_READBACK);
-
-	__mcip_cmd(CMD_GFRC_READ_HI, 0);
-	stamp.h = read_aux_reg(ARC_REG_MCIP_READBACK);
-
-	local_irq_restore(flags);
-
-	return stamp.full;
-}
-
-static struct clocksource arc_counter_gfrc = {
-	.name   = "ARConnect GFRC",
-	.rating = 400,
-	.read   = arc_read_gfrc,
-	.mask   = CLOCKSOURCE_MASK(64),
-	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init arc_cs_setup_gfrc(struct device_node *node)
-{
-	int exists = cpuinfo_arc700[0].extn.gfrc;
-	int ret;
-
-	if (WARN(!exists, "Global-64-bit-Ctr clocksource not detected"))
-		return -ENXIO;
-
-	ret = arc_get_timer_clk(node);
-	if (ret)
-		return ret;
-
-	return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);
-}
-CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
-
-#endif
-
-#ifdef CONFIG_ARC_HAS_RTC
-
-#define AUX_RTC_CTRL	0x103
-#define AUX_RTC_LOW	0x104
-#define AUX_RTC_HIGH	0x105
-
-static cycle_t arc_read_rtc(struct clocksource *cs)
-{
-	unsigned long status;
-	union {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-		struct { u32 high, low; };
-#else
-		struct { u32 low, high; };
-#endif
-		cycle_t  full;
-	} stamp;
-
-	/*
-	 * hardware has an internal state machine which tracks readout of
-	 * low/high and updates the CTRL.status if
-	 *  - interrupt/exception taken between the two reads
-	 *  - high increments after low has been read
-	 */
-	do {
-		stamp.low = read_aux_reg(AUX_RTC_LOW);
-		stamp.high = read_aux_reg(AUX_RTC_HIGH);
-		status = read_aux_reg(AUX_RTC_CTRL);
-	} while (!(status & _BITUL(31)));
-
-	return stamp.full;
-}
-
-static struct clocksource arc_counter_rtc = {
-	.name   = "ARCv2 RTC",
-	.rating = 350,
-	.read   = arc_read_rtc,
-	.mask   = CLOCKSOURCE_MASK(64),
-	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init arc_cs_setup_rtc(struct device_node *node)
-{
-	int exists = cpuinfo_arc700[smp_processor_id()].extn.rtc;
-	int ret;
-
-	if (WARN(!exists, "Local-64-bit-Ctr clocksource not detected"))
-		return -ENXIO;
-
-	/* Local to CPU hence not usable in SMP */
-	if (WARN(IS_ENABLED(CONFIG_SMP), "Local-64-bit-Ctr not usable in SMP"))
-		return -EINVAL;
-
-	ret = arc_get_timer_clk(node);
-	if (ret)
-		return ret;
-
-	write_aux_reg(AUX_RTC_CTRL, 1);
-
-	return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
-}
-CLOCKSOURCE_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);
-
-#endif
-
-/*
- * 32bit TIMER1 to keep counting monotonically and wraparound
- */
-
-static cycle_t arc_read_timer1(struct clocksource *cs)
-{
-	return (cycle_t) read_aux_reg(ARC_REG_TIMER1_CNT);
-}
-
-static struct clocksource arc_counter_timer1 = {
-	.name   = "ARC Timer1",
-	.rating = 300,
-	.read   = arc_read_timer1,
-	.mask   = CLOCKSOURCE_MASK(32),
-	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init arc_cs_setup_timer1(struct device_node *node)
-{
-	int ret;
-
-	/* Local to CPU hence not usable in SMP */
-	if (IS_ENABLED(CONFIG_SMP))
-		return -EINVAL;
-
-	ret = arc_get_timer_clk(node);
-	if (ret)
-		return ret;
-
-	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMER_MAX);
-	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
-	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
-
-	return clocksource_register_hz(&arc_counter_timer1, arc_timer_freq);
-}
-
-/********** Clock Event Device *********/
-
-static int arc_timer_irq;
-
-/*
- * Arm the timer to interrupt after @cycles
- * The distinction for oneshot/periodic is done in arc_event_timer_ack() below
- */
-static void arc_timer_event_setup(unsigned int cycles)
-{
-	write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
-	write_aux_reg(ARC_REG_TIMER0_CNT, 0);	/* start from 0 */
-
-	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
-}
-
-
-static int arc_clkevent_set_next_event(unsigned long delta,
-				       struct clock_event_device *dev)
-{
-	arc_timer_event_setup(delta);
-	return 0;
-}
-
-static int arc_clkevent_set_periodic(struct clock_event_device *dev)
-{
-	/*
-	 * At X Hz, 1 sec = 1000ms -> X cycles;
-	 *		      10ms -> X / 100 cycles
-	 */
-	arc_timer_event_setup(arc_timer_freq / HZ);
-	return 0;
-}
-
-static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
-	.name			= "ARC Timer0",
-	.features		= CLOCK_EVT_FEAT_ONESHOT |
-				  CLOCK_EVT_FEAT_PERIODIC,
-	.rating			= 300,
-	.set_next_event		= arc_clkevent_set_next_event,
-	.set_state_periodic	= arc_clkevent_set_periodic,
-};
-
-static irqreturn_t timer_irq_handler(int irq, void *dev_id)
-{
-	/*
-	 * Note that generic IRQ core could have passed @evt for @dev_id if
-	 * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
-	 */
-	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
-	int irq_reenable = clockevent_state_periodic(evt);
-
-	/*
-	 * Any write to CTRL reg ACks the interrupt, we rewrite the
-	 * Count when [N]ot [H]alted bit.
-	 * And re-arm it if perioid by [I]nterrupt [E]nable bit
-	 */
-	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-
-static int arc_timer_starting_cpu(unsigned int cpu)
-{
-	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
-
-	evt->cpumask = cpumask_of(smp_processor_id());
-
-	clockevents_config_and_register(evt, arc_timer_freq, 0, ARC_TIMER_MAX);
-	enable_percpu_irq(arc_timer_irq, 0);
-	return 0;
-}
-
-static int arc_timer_dying_cpu(unsigned int cpu)
-{
-	disable_percpu_irq(arc_timer_irq);
-	return 0;
-}
-
-/*
- * clockevent setup for boot CPU
- */
-static int __init arc_clockevent_setup(struct device_node *node)
-{
-	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
-	int ret;
-
-	arc_timer_irq = irq_of_parse_and_map(node, 0);
-	if (arc_timer_irq <= 0) {
-		pr_err("clockevent: missing irq");
-		return -EINVAL;
-	}
-
-	ret = arc_get_timer_clk(node);
-	if (ret) {
-		pr_err("clockevent: missing clk");
-		return ret;
-	}
-
-	/* Needs apriori irq_set_percpu_devid() done in intc map function */
-	ret = request_percpu_irq(arc_timer_irq, timer_irq_handler,
-				 "Timer0 (per-cpu-tick)", evt);
-	if (ret) {
-		pr_err("clockevent: unable to request irq\n");
-		return ret;
-	}
-
-	ret = cpuhp_setup_state(CPUHP_AP_ARC_TIMER_STARTING,
-				"AP_ARC_TIMER_STARTING",
-				arc_timer_starting_cpu,
-				arc_timer_dying_cpu);
-	if (ret) {
-		pr_err("Failed to setup hotplug state");
-		return ret;
-	}
-	return 0;
-}
-
-static int __init arc_of_timer_init(struct device_node *np)
-{
-	static int init_count = 0;
-	int ret;
-
-	if (!init_count) {
-		init_count = 1;
-		ret = arc_clockevent_setup(np);
-	} else {
-		ret = arc_cs_setup_timer1(np);
-	}
-
-	return ret;
-}
-CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
-
-/*
- * Called from start_kernel() - boot CPU only
- */
-void __init time_init(void)
-{
-	of_clk_init(NULL);
-	clocksource_probe();
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/kernel/unaligned.c linux-libre-4.10-rc8-gnu/arch/arc/kernel/unaligned.c
--- linux-libre-4.9-gnu/arch/arc/kernel/unaligned.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/kernel/unaligned.c	2017-02-12 16:03:20.000000000 -0500
@@ -241,8 +241,9 @@ int misaligned_fixup(unsigned long addre
 	if (state.fault)
 		goto fault;
 
+	/* clear any remanants of delay slot */
 	if (delay_mode(regs)) {
-		regs->ret = regs->bta;
+		regs->ret = regs->bta & ~1U;
 		regs->status32 &= ~STATUS_DE_MASK;
 	} else {
 		regs->ret += state.instr_len;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/mm/cache.c linux-libre-4.10-rc8-gnu/arch/arc/mm/cache.c
--- linux-libre-4.9-gnu/arch/arc/mm/cache.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/mm/cache.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 
 static int l2_line_sz;
 static int ioc_exists;
-int slc_enable = 1, ioc_enable = 0;
+int slc_enable = 1, ioc_enable = 1;
 unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */
 unsigned long perip_end = 0xFFFFFFFF; /* legacy value */
 
@@ -40,7 +40,7 @@ char *arc_cache_mumbojumbo(int c, char *
 	struct cpuinfo_arc_cache *p;
 
 #define PR_CACHE(p, cfg, str)						\
-	if (!(p)->ver)							\
+	if (!(p)->line_len)						\
 		n += scnprintf(buf + n, len - n, str"\t\t: N/A\n");	\
 	else								\
 		n += scnprintf(buf + n, len - n,			\
@@ -54,7 +54,7 @@ char *arc_cache_mumbojumbo(int c, char *
 	PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache");
 
 	p = &cpuinfo_arc700[c].slc;
-	if (p->ver)
+	if (p->line_len)
 		n += scnprintf(buf + n, len - n,
 			       "SLC\t\t: %uK, %uB Line%s\n",
 			       p->sz_k, p->line_len, IS_USED_RUN(slc_enable));
@@ -104,7 +104,6 @@ static void read_decode_cache_bcr_arcv2(
 	READ_BCR(ARC_REG_SLC_BCR, sbcr);
 	if (sbcr.ver) {
 		READ_BCR(ARC_REG_SLC_CFG, slc_cfg);
-		p_slc->ver = sbcr.ver;
 		p_slc->sz_k = 128 << slc_cfg.sz;
 		l2_line_sz = p_slc->line_len = (slc_cfg.lsz == 0) ? 128 : 64;
 	}
@@ -152,7 +151,6 @@ void read_decode_cache_bcr(void)
 
 	p_ic->line_len = 8 << ibcr.line_len;
 	p_ic->sz_k = 1 << (ibcr.sz - 1);
-	p_ic->ver = ibcr.ver;
 	p_ic->vipt = 1;
 	p_ic->alias = p_ic->sz_k/p_ic->assoc/TO_KB(PAGE_SIZE) > 1;
 
@@ -176,7 +174,6 @@ dc_chk:
 
 	p_dc->line_len = 16 << dbcr.line_len;
 	p_dc->sz_k = 1 << (dbcr.sz - 1);
-	p_dc->ver = dbcr.ver;
 
 slc_chk:
 	if (is_isa_arcv2())
@@ -274,7 +271,11 @@ void __cache_line_loop_v2(phys_addr_t pa
 
 /*
  * For ARC700 MMUv3 I-cache and D-cache flushes
- * Also reused for HS38 aliasing I-cache configuration
+ *  - ARC700 programming model requires paddr and vaddr be passed in seperate
+ *    AUX registers (*_IV*L and *_PTAG respectively) irrespective of whether the
+ *    caches actually alias or not.
+ * -  For HS38, only the aliasing I-cache configuration uses the PTAG reg
+ *    (non aliasing I-cache version doesn't; while D-cache can't possibly alias)
  */
 static inline
 void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
@@ -461,6 +462,21 @@ static inline void __dc_entire_op(const
 	__after_dc_op(op);
 }
 
+static inline void __dc_disable(void)
+{
+	const int r = ARC_REG_DC_CTRL;
+
+	__dc_entire_op(OP_FLUSH_N_INV);
+	write_aux_reg(r, read_aux_reg(r) | DC_CTRL_DIS);
+}
+
+static void __dc_enable(void)
+{
+	const int r = ARC_REG_DC_CTRL;
+
+	write_aux_reg(r, read_aux_reg(r) & ~DC_CTRL_DIS);
+}
+
 /* For kernel mappings cache operation: index is same as paddr */
 #define __dc_line_op_k(p, sz, op)	__dc_line_op(p, p, sz, op)
 
@@ -486,6 +502,8 @@ static inline void __dc_line_op(phys_add
 #else
 
 #define __dc_entire_op(op)
+#define __dc_disable()
+#define __dc_enable()
 #define __dc_line_op(paddr, vaddr, sz, op)
 #define __dc_line_op_k(paddr, sz, op)
 
@@ -600,6 +618,40 @@ noinline void slc_op(phys_addr_t paddr,
 #endif
 }
 
+noinline static void slc_entire_op(const int op)
+{
+	unsigned int ctrl, r = ARC_REG_SLC_CTRL;
+
+	ctrl = read_aux_reg(r);
+
+	if (!(op & OP_FLUSH))		/* i.e. OP_INV */
+		ctrl &= ~SLC_CTRL_IM;	/* clear IM: Disable flush before Inv */
+	else
+		ctrl |= SLC_CTRL_IM;
+
+	write_aux_reg(r, ctrl);
+
+	write_aux_reg(ARC_REG_SLC_INVALIDATE, 1);
+
+	/* Important to wait for flush to complete */
+	while (read_aux_reg(r) & SLC_CTRL_BUSY);
+}
+
+static inline void arc_slc_disable(void)
+{
+	const int r = ARC_REG_SLC_CTRL;
+
+	slc_entire_op(OP_FLUSH_N_INV);
+	write_aux_reg(r, read_aux_reg(r) | SLC_CTRL_DIS);
+}
+
+static inline void arc_slc_enable(void)
+{
+	const int r = ARC_REG_SLC_CTRL;
+
+	write_aux_reg(r, read_aux_reg(r) & ~SLC_CTRL_DIS);
+}
+
 /***********************************************************
  * Exported APIs
  */
@@ -926,36 +978,65 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, st
 	return 0;
 }
 
-void arc_cache_init(void)
+/*
+ * IO-Coherency (IOC) setup rules:
+ *
+ * 1. Needs to be at system level, so only once by Master core
+ *    Non-Masters need not be accessing caches at that time
+ *    - They are either HALT_ON_RESET and kick started much later or
+ *    - if run on reset, need to ensure that arc_platform_smp_wait_to_boot()
+ *      doesn't perturb caches or coherency unit
+ *
+ * 2. caches (L1 and SLC) need to be purged (flush+inv) before setting up IOC,
+ *    otherwise any straggler data might behave strangely post IOC enabling
+ *
+ * 3. All Caches need to be disabled when setting up IOC to elide any in-flight
+ *    Coherency transactions
+ */
+noinline void __init arc_ioc_setup(void)
 {
-	unsigned int __maybe_unused cpu = smp_processor_id();
-	char str[256];
+	unsigned int ap_sz;
 
-	printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
+	/* Flush + invalidate + disable L1 dcache */
+	__dc_disable();
+
+	/* Flush + invalidate SLC */
+	if (read_aux_reg(ARC_REG_SLC_BCR))
+		slc_entire_op(OP_FLUSH_N_INV);
+
+	/* IOC Aperture start: TDB: handle non default CONFIG_LINUX_LINK_BASE */
+	write_aux_reg(ARC_REG_IO_COH_AP0_BASE, 0x80000);
 
 	/*
-	 * Only master CPU needs to execute rest of function:
-	 *  - Assume SMP so all cores will have same cache config so
-	 *    any geomtry checks will be same for all
-	 *  - IOC setup / dma callbacks only need to be setup once
+	 * IOC Aperture size:
+	 *   decoded as 2 ^ (SIZE + 2) KB: so setting 0x11 implies 512M
+	 * TBD: fix for PGU + 1GB of low mem
+	 * TBD: fix for PAE
 	 */
-	if (cpu)
-		return;
+	ap_sz = order_base_2(arc_get_mem_sz()/1024) - 2;
+	write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, ap_sz);
+
+	write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1);
+	write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
+
+	/* Re-enable L1 dcache */
+	__dc_enable();
+}
+
+void __init arc_cache_init_master(void)
+{
+	unsigned int __maybe_unused cpu = smp_processor_id();
 
 	if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) {
 		struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
 
-		if (!ic->ver)
+		if (!ic->line_len)
 			panic("cache support enabled but non-existent cache\n");
 
 		if (ic->line_len != L1_CACHE_BYTES)
 			panic("ICache line [%d] != kernel Config [%d]",
 			      ic->line_len, L1_CACHE_BYTES);
 
-		if (ic->ver != CONFIG_ARC_MMU_VER)
-			panic("Cache ver [%d] doesn't match MMU ver [%d]\n",
-			      ic->ver, CONFIG_ARC_MMU_VER);
-
 		/*
 		 * In MMU v4 (HS38x) the aliasing icache config uses IVIL/PTAG
 		 * pair to provide vaddr/paddr respectively, just as in MMU v3
@@ -969,7 +1050,7 @@ void arc_cache_init(void)
 	if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) {
 		struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache;
 
-		if (!dc->ver)
+		if (!dc->line_len)
 			panic("cache support enabled but non-existent cache\n");
 
 		if (dc->line_len != L1_CACHE_BYTES)
@@ -979,38 +1060,27 @@ void arc_cache_init(void)
 		/* check for D-Cache aliasing on ARCompact: ARCv2 has PIPT */
 		if (is_isa_arcompact()) {
 			int handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
+			int num_colors = dc->sz_k/dc->assoc/TO_KB(PAGE_SIZE);
 
-			if (dc->alias && !handled)
-				panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
-			else if (!dc->alias && handled)
+			if (dc->alias) {
+				if (!handled)
+					panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+				if (CACHE_COLORS_NUM != num_colors)
+					panic("CACHE_COLORS_NUM not optimized for config\n");
+			} else if (!dc->alias && handled) {
 				panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+			}
 		}
 	}
 
-	if (is_isa_arcv2() && l2_line_sz && !slc_enable) {
-
-		/* IM set : flush before invalidate */
-		write_aux_reg(ARC_REG_SLC_CTRL,
-			read_aux_reg(ARC_REG_SLC_CTRL) | SLC_CTRL_IM);
-
-		write_aux_reg(ARC_REG_SLC_INVALIDATE, 1);
+	/* Note that SLC disable not formally supported till HS 3.0 */
+	if (is_isa_arcv2() && l2_line_sz && !slc_enable)
+		arc_slc_disable();
 
-		/* Important to wait for flush to complete */
-		while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY);
-		write_aux_reg(ARC_REG_SLC_CTRL,
-			read_aux_reg(ARC_REG_SLC_CTRL) | SLC_CTRL_DISABLE);
-	}
+	if (is_isa_arcv2() && ioc_enable)
+		arc_ioc_setup();
 
 	if (is_isa_arcv2() && ioc_enable) {
-		/* IO coherency base - 0x8z */
-		write_aux_reg(ARC_REG_IO_COH_AP0_BASE, 0x80000);
-		/* IO coherency aperture size - 512Mb: 0x8z-0xAz */
-		write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, 0x11);
-		/* Enable partial writes */
-		write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1);
-		/* Enable IO coherency */
-		write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
-
 		__dma_cache_wback_inv = __dma_cache_wback_inv_ioc;
 		__dma_cache_inv = __dma_cache_inv_ioc;
 		__dma_cache_wback = __dma_cache_wback_ioc;
@@ -1024,3 +1094,20 @@ void arc_cache_init(void)
 		__dma_cache_wback = __dma_cache_wback_l1;
 	}
 }
+
+void __ref arc_cache_init(void)
+{
+	unsigned int __maybe_unused cpu = smp_processor_id();
+	char str[256];
+
+	printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
+
+	/*
+	 * Only master CPU needs to execute rest of function:
+	 *  - Assume SMP so all cores will have same cache config so
+	 *    any geomtry checks will be same for all
+	 *  - IOC setup / dma callbacks only need to be setup once
+	 */
+	if (!cpu)
+		arc_cache_init_master();
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/mm/dma.c linux-libre-4.10-rc8-gnu/arch/arc/mm/dma.c
--- linux-libre-4.9-gnu/arch/arc/mm/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/mm/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -158,7 +158,10 @@ static dma_addr_t arc_dma_map_page(struc
 		unsigned long attrs)
 {
 	phys_addr_t paddr = page_to_phys(page) + offset;
-	_dma_cache_sync(paddr, size, dir);
+
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		_dma_cache_sync(paddr, size, dir);
+
 	return plat_phys_to_dma(dev, paddr);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/mm/init.c linux-libre-4.10-rc8-gnu/arch/arc/mm/init.c
--- linux-libre-4.9-gnu/arch/arc/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,6 +40,11 @@ struct pglist_data node_data[MAX_NUMNODE
 EXPORT_SYMBOL(node_data);
 #endif
 
+long __init arc_get_mem_sz(void)
+{
+	return low_mem_sz;
+}
+
 /* User can over-ride above with "mem=nnn[KkMm]" in cmdline */
 static int __init setup_mem_sz(char *str)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/plat-axs10x/axs10x.c linux-libre-4.10-rc8-gnu/arch/arc/plat-axs10x/axs10x.c
--- linux-libre-4.9-gnu/arch/arc/plat-axs10x/axs10x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/plat-axs10x/axs10x.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/io.h>
 #include <asm/mach_desc.h>
-#include <asm/mcip.h>
+#include <soc/arc/mcip.h>
 
 #define AXS_MB_CGU		0xE0010000
 #define AXS_MB_CREG		0xE0011000
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arc/plat-eznps/include/plat/ctop.h linux-libre-4.10-rc8-gnu/arch/arc/plat-eznps/include/plat/ctop.h
--- linux-libre-4.9-gnu/arch/arc/plat-eznps/include/plat/ctop.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arc/plat-eznps/include/plat/ctop.h	2017-02-12 16:03:20.000000000 -0500
@@ -46,9 +46,7 @@
 #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
 
 /* EZchip core instructions */
-#define CTOP_INST_HWSCHD_OFF_R3			0x3B6F00BF
 #define CTOP_INST_HWSCHD_OFF_R4			0x3C6F00BF
-#define CTOP_INST_HWSCHD_RESTORE_R3		0x3E6F70C3
 #define CTOP_INST_HWSCHD_RESTORE_R4		0x3E6F7103
 #define CTOP_INST_SCHD_RW			0x3E6F7004
 #define CTOP_INST_SCHD_RD			0x3E6F7084
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -364,11 +364,14 @@
 };
 
 &davinci_mdio {
+	status = "okay";
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&davinci_mdio_default>;
 	pinctrl-1 = <&davinci_mdio_sleep>;
 
-	status = "okay";
+	phy1: ethernet-phy@1 {
+		reg = <7>;
+	};
 };
 
 &mmc1 {
@@ -406,3 +409,7 @@
 &gpio0 {
 	ti,no-reset-on-init;
 };
+
+&gpio3 {
+	ti,no-reset-on-init;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos-ir2110.dts	2017-02-12 16:03:20.000000000 -0500
@@ -54,16 +54,22 @@
 	dr_mode = "host";
 };
 
+&davinci_mdio {
+	phy0: ethernet-phy@0 {
+		reg = <1>;
+	};
+};
+
 &cpsw_emac0 {
-	phy_id = <&davinci_mdio>, <1>;
 	phy-mode = "rmii";
 	dual_emac_res_vlan = <1>;
+	phy-handle = <&phy0>;
 };
 
 &cpsw_emac1 {
-	phy_id = <&davinci_mdio>, <7>;
 	phy-mode = "rgmii-txid";
 	dual_emac_res_vlan = <2>;
+	phy-handle = <&phy1>;
 };
 
 &phy_sel {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos-ir3220.dts	2017-02-12 16:03:20.000000000 -0500
@@ -109,9 +109,9 @@
 };
 
 &cpsw_emac1 {
-	phy_id = <&davinci_mdio>, <7>;
 	phy-mode = "rgmii-txid";
 	dual_emac_res_vlan = <2>;
+	phy-handle = <&phy1>;
 };
 
 &phy_sel {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-baltos-ir5221.dts	2017-02-12 16:03:20.000000000 -0500
@@ -114,7 +114,7 @@
 
 &usb1 {
 	status = "okay";
-	dr_mode = "otg";
+	dr_mode = "host";
 };
 
 &cpsw_emac0 {
@@ -127,9 +127,9 @@
 };
 
 &cpsw_emac1 {
-	phy_id = <&davinci_mdio>, <7>;
 	phy-mode = "rgmii-txid";
 	dual_emac_res_vlan = <2>;
+	phy-handle = <&phy1>;
 };
 
 &phy_sel {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-boneblack.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-boneblack.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-boneblack.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-boneblack.dts	2017-02-12 16:03:20.000000000 -0500
@@ -79,6 +79,14 @@
 
 &lcdc {
 	status = "okay";
+
+	/* If you want to get 24 bit RGB and 16 BGR mode instead of
+	 * current 16 bit RGB and 24 BGR modes, set the propety
+	 * below to "crossed" and uncomment the video-ports -property
+	 * in tda19988 node.
+	 */
+	blue-and-red-wiring = "straight";
+
 	port {
 		lcdc_0: endpoint@0 {
 			remote-endpoint = <&hdmi_0>;
@@ -95,6 +103,9 @@
 		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
 		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
 
+		/* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */
+		/* video-ports = <0x234501>; */
+
 		#sound-dai-cells = <0>;
 		audio-ports = <	TDA998x_I2S	0x03>;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-bone-common.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-bone-common.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-bone-common.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-bone-common.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -310,8 +310,23 @@
 	 * by the hardware problems. (Tip: double-check by performing a current
 	 * measurement after shutdown: it should be less than 1 mA.)
 	 */
+
+	interrupts = <7>; /* NMI */
+	interrupt-parent = <&intc>;
+
 	ti,pmic-shutdown-controller;
 
+	charger {
+		interrupts = <0>, <1>;
+		interrupt-names = "USB", "AC";
+		status = "okay";
+	};
+
+	pwrbutton {
+		interrupts = <2>;
+		status = "okay";
+	};
+
 	regulators {
 		dcdc1_reg: regulator@0 {
 			regulator-name = "vdds_dpr";
@@ -393,3 +408,8 @@
 &sham {
 	status = "okay";
 };
+
+&rtc {
+	clocks = <&clk_32768_ck>, <&clkdiv32k_ick>;
+	clock-names = "ext-clk", "int-clk";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-evm.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-evm.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-evm.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-evm.dts	2017-02-12 16:03:20.000000000 -0500
@@ -783,3 +783,8 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&dcan1_pins_default>;
 };
+
+&rtc {
+	clocks = <&clk_32768_ck>, <&clkdiv32k_ick>;
+	clock-names = "ext-clk", "int-clk";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-evmsk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-evmsk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-evmsk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-evmsk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -715,3 +715,8 @@
 
 	blue-and-red-wiring = "crossed";
 };
+
+&rtc {
+	clocks = <&clk_32768_ck>, <&clkdiv32k_ick>;
+	clock-names = "ext-clk", "int-clk";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-icev2.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-icev2.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am335x-icev2.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am335x-icev2.dts	2017-02-12 16:03:20.000000000 -0500
@@ -43,52 +43,52 @@
 		enable-active-high;
 	};
 
-	leds0 {
+	leds-iio {
+		status = "disabled";
 		compatible = "gpio-leds";
-
-		led0 {
+		led-out0 {
 			label = "out0";
 			gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
 
-		led1 {
+		led-out1 {
 			label = "out1";
 			gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
 
-		led2 {
+		led-out2 {
 			label = "out2";
 			gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
 
-		led3 {
+		led-out3 {
 			label = "out3";
 			gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
 
-		led4 {
+		led-out4 {
 			label = "out4";
 			gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
 
-		led5 {
+		led-out5 {
 			label = "out5";
 			gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
 
-		led6 {
+		led-out6 {
 			label = "out6";
 			gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
 
-		led7 {
+		led-out7 {
 			label = "out7";
 			gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
@@ -170,7 +170,6 @@
 			AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
 			AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
 			AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
-			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE5) /* (C15) spi0_cs1.mmc0_sdcd */
 		>;
 	};
 
@@ -187,6 +186,8 @@
 			AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */
 			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */
 			AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */
+			AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE0) /* (C15) spi0_cs1.spi0_cs1 */
+			AM33XX_IOPAD(0x9a0, PIN_INPUT_PULLUP | MUX_MODE7) /* (B12) mcasp0_aclkr.gpio3[18] */
 		>;
 	};
 
@@ -224,6 +225,31 @@
 	};
 };
 
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins_default>;
+
+	sn65hvs882@1 {
+		compatible = "pisosr-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		load-gpios = <&gpio3 18 GPIO_ACTIVE_LOW>;
+
+		reg = <1>;
+		spi-max-frequency = <1000000>;
+		spi-cpol;
+	};
+};
+
+&tscadc {
+	status = "okay";
+	adc {
+		ti,adc-channels = <1 2 3 4 5 6 7>;
+	};
+};
+
 #include "tps65910.dtsi"
 
 &tps {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am33xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am33xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am33xx.dtsi	2016-12-11 18:00:49.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am33xx.dtsi	2017-02-12 17:53:42.000000000 -0500
@@ -16,6 +16,7 @@
 	interrupt-parent = <&intc>;
 	#address-cells = <1>;
 	#size-cells = <1>;
+	chosen { };
 
 	aliases {
 		i2c0 = &i2c0;
@@ -130,6 +131,7 @@
 				reg = <0x210000 0x2000>;
 				#address-cells = <1>;
 				#size-cells = <1>;
+				#pinctrl-cells = <1>;
 				ranges = <0 0x210000 0x2000>;
 
 				am33xx_pinmux: pinmux@800 {
@@ -137,6 +139,7 @@
 					reg = <0x800 0x238>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					pinctrl-single,register-width = <32>;
 					pinctrl-single,function-mask = <0x7f>;
 				};
@@ -505,6 +508,8 @@
 			interrupts = <75
 				      76>;
 			ti,hwmods = "rtc";
+			clocks = <&clkdiv32k_ick>;
+			clock-names = "int-clk";
 		};
 
 		spi0: spi@48030000 {
@@ -855,6 +860,8 @@
 			interrupts = <16>;
 			ti,hwmods = "adc_tsc";
 			status = "disabled";
+			dmas = <&edma 53 0>, <&edma 57 0>;
+			dma-names = "fifo0", "fifo1";
 
 			tsc {
 				compatible = "ti,am3359-tsc";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am3517.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am3517.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am3517.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am3517.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -66,6 +66,7 @@
 			reg = <0x480025d8 0x24>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#pinctrl-cells = <1>;
 			#interrupt-cells = <1>;
 			interrupt-controller;
 			pinctrl-single,register-width = <16>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am4372.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am4372.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am4372.dtsi	2016-12-11 18:00:52.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am4372.dtsi	2017-02-12 17:53:45.000000000 -0500
@@ -16,6 +16,7 @@
 	interrupt-parent = <&wakeupgen>;
 	#address-cells = <1>;
 	#size-cells = <1>;
+	chosen { };
 
 	memory@0 {
 		device_type = "memory";
@@ -189,6 +190,7 @@
 					reg = <0x800 0x31c>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					#interrupt-cells = <1>;
 					interrupt-controller;
 					pinctrl-single,register-width = <32>;
@@ -871,6 +873,8 @@
 			clocks = <&adc_tsc_fck>;
 			clock-names = "fck";
 			status = "disabled";
+			dmas = <&edma 53 0>, <&edma 57 0>;
+			dma-names = "fifo0", "fifo1";
 
 			tsc {
 				compatible = "ti,am3359-tsc";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am437x-idk-evm.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am437x-idk-evm.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am437x-idk-evm.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am437x-idk-evm.dts	2017-02-12 16:03:20.000000000 -0500
@@ -117,6 +117,58 @@
 		compatible = "fixed-clock";
 		clock-frequency = <32768>;
 	};
+
+	leds-iio {
+		status = "disabled";
+		compatible = "gpio-leds";
+		led-out0 {
+			label = "out0";
+			gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out1 {
+			label = "out1";
+			gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out2 {
+			label = "out2";
+			gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out3 {
+			label = "out3";
+			gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out4 {
+			label = "out4";
+			gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out5 {
+			label = "out5";
+			gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out6 {
+			label = "out6";
+			gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out7 {
+			label = "out7";
+			gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
 };
 
 &am43xx_pinmux {
@@ -178,6 +230,24 @@
 		>;
 	};
 
+	spi1_pins_default: spi1_pins_default {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x908, PIN_INPUT | MUX_MODE2)	/* mii1_col.spi1_sclk */
+			AM4372_IOPAD(0x910, PIN_INPUT | MUX_MODE2)	/* mii1_rx_er.spi1_d1 */
+			AM4372_IOPAD(0x944, PIN_OUTPUT | MUX_MODE2)	/* rmii1_ref_clk.spi1_cs0 */
+			AM4372_IOPAD(0x90c, PIN_OUTPUT | MUX_MODE7)	/* mii1_crs.gpio3_1 */
+		>;
+	};
+
+	spi1_pins_sleep: spi1_pins_sleep {
+		pinctrl-single,pins = <
+			AM4372_IOPAD(0x908, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x944, PIN_INPUT_PULLDOWN | MUX_MODE7)
+			AM4372_IOPAD(0x90c, PIN_INPUT_PULLDOWN | MUX_MODE7)
+		>;
+	};
+
 	ecap0_pins_default: backlight_pins_default {
 		pinctrl-single,pins = <
 			AM4372_IOPAD(0x964, PIN_OUTPUT | MUX_MODE0) /* ecap0_in_pwm0_out.ecap0_in_pwm0_out */
@@ -290,6 +360,33 @@
 	pinctrl-0 = <&i2c2_pins_default>;
 	pinctrl-1 = <&i2c2_pins_sleep>;
 	clock-frequency = <100000>;
+
+	tpic2810: tpic2810@60 {
+		compatible = "ti,tpic2810";
+		reg = <0x60>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&spi1 {
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&spi1_pins_default>;
+	pinctrl-1 = <&spi1_pins_sleep>;
+	ti,pindir-d0-out-d1-in;
+
+	sn65hvs882: sn65hvs882@0 {
+		compatible = "pisosr-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		load-gpios = <&gpio3 1 GPIO_ACTIVE_LOW>;
+
+		reg = <0>;
+		spi-max-frequency = <1000000>;
+		spi-cpol;
+	};
 };
 
 &epwmss0 {
@@ -310,6 +407,10 @@
 	status = "okay";
 };
 
+&gpio3 {
+	status = "okay";
+};
+
 &gpio4 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am571x-idk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am571x-idk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am571x-idk.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am571x-idk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015-2016 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 "dra72x.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "am57xx-idk-common.dtsi"
+
+/ {
+	model = "TI AM5718 IDK";
+	compatible = "ti,am5718-idk", "ti,am5718", "ti,dra7";
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x40000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		cpu0-led {
+			label = "status0:red:cpu0";
+			gpios = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "cpu0";
+		};
+
+		usr0-led {
+			label = "status0:green:usr";
+			gpios = <&gpio2 26 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		heartbeat-led {
+			label = "status0:blue:heartbeat";
+			gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+
+		usr1-led {
+			label = "status1:red:usr";
+			gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		usr2-led {
+			label = "status1:green:usr";
+			gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		mmc0-led {
+			label = "status1:blue:mmc0";
+			gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc0";
+		};
+	};
+};
+
+&mmc1 {
+	status = "okay";
+	vmmc-supply = <&ldo1_reg>;
+	bus-width = <4>;
+	cd-gpios = <&gpio6 27 0>; /* gpio 219 */
+};
+
+&omap_dwc3_2 {
+	extcon = <&extcon_usb2>;
+};
+
+&extcon_usb2 {
+	id-gpio = <&gpio5 7 GPIO_ACTIVE_HIGH>;
+	vbus-gpio = <&gpio7 22 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am572x-idk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am572x-idk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am572x-idk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am572x-idk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -23,11 +23,6 @@
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
 
-	extcon_usb2: extcon_usb2 {
-		compatible = "linux,extcon-usb-gpio";
-		id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
-	};
-
 	status-leds {
 		compatible = "gpio-leds";
 		cpu0-led {
@@ -76,6 +71,11 @@
 	extcon = <&extcon_usb2>;
 };
 
+&extcon_usb2 {
+	id-gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+	vbus-gpio = <&gpio3 26 GPIO_ACTIVE_HIGH>;
+};
+
 &mmc1 {
 	status = "okay";
 	vmmc-supply = <&v3_3d>;
@@ -83,3 +83,11 @@
 	bus-width = <4>;
 	cd-gpios = <&gpio6 27 0>; /* gpio 219 */
 };
+
+&sn65hvs882 {
+	load-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
+};
+
+&pcie1 {
+	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -204,6 +204,7 @@
 		interrupt-controller;
 
 		ti,system-power-controller;
+		ti,palmas-override-powerhold;
 
 		tps659038_pmic {
 			compatible = "ti,tps659038-pmic";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/am57xx-idk-common.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,58 @@
 		regulator-always-on;
 		regulator-boot-on;
 	};
+
+	leds-iio {
+		status = "disabled";
+		compatible = "gpio-leds";
+		led-out0 {
+			label = "out0";
+			gpios = <&tpic2810 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out1 {
+			label = "out1";
+			gpios = <&tpic2810 1 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out2 {
+			label = "out2";
+			gpios = <&tpic2810 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out3 {
+			label = "out3";
+			gpios = <&tpic2810 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out4 {
+			label = "out4";
+			gpios = <&tpic2810 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out5 {
+			label = "out5";
+			gpios = <&tpic2810 5 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out6 {
+			label = "out6";
+			gpios = <&tpic2810 6 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-out7 {
+			label = "out7";
+			gpios = <&tpic2810 7 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
 };
 
 &i2c1 {
@@ -57,6 +109,7 @@
 		#interrupt-cells = <2>;
 		interrupt-controller;
 		ti,system-power-controller;
+		ti,palmas-override-powerhold;
 
 		tps659038_pmic {
 			compatible = "ti,tps659038-pmic";
@@ -250,6 +303,35 @@
 			gpio-controller;
 			#gpio-cells = <2>;
 		};
+
+		extcon_usb2: tps659038_usb {
+			compatible = "ti,palmas-usb-vid";
+			ti,enable-vbus-detection;
+			ti,enable-id-detection;
+			/* ID & VBUS GPIOs provided in board dts */
+		};
+	};
+};
+
+&mcspi3 {
+	status = "okay";
+	ti,pindir-d0-out-d1-in;
+
+	sn65hvs882: sn65hvs882@0 {
+		compatible = "pisosr-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		reg = <0>;
+		spi-max-frequency = <1000000>;
+		spi-cpol;
+	};
+
+	tpic2810: tpic2810@60 {
+		compatible = "ti,tpic2810";
+		reg = <0x60>;
+		gpio-controller;
+		#gpio-cells = <2>;
 	};
 };
 
@@ -294,7 +376,7 @@
 };
 
 &usb2 {
-	dr_mode = "otg";
+	dr_mode = "peripheral";
 };
 
 &mmc2 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-db.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-db.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-db.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-db.dts	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x40000000>; /* 1 GB */
 	};
@@ -86,18 +86,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				pinctrl-0 = <&mdio_pins>;
-				pinctrl-names = "default";
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 {
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
 				pinctrl-0 = <&ge0_rgmii_pins>;
 				pinctrl-names = "default";
@@ -182,24 +170,6 @@
 				};
 			};
 		};
-
-		pcie-controller {
-			status = "okay";
-			/*
-			 * The two PCIe units are accessible through
-			 * both standard PCIe slots and mini-PCIe
-			 * slots on the board.
-			 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			pcie@2,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
 	};
 
 	sound {
@@ -261,6 +231,37 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+	/*
+	 * The two PCIe units are accessible through
+	 * both standard PCIe slots and mini-PCIe
+	 * slots on the board.
+	 */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	pcie@2,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+
 &spi0 {
 	pinctrl-0 = <&spi0_pins2>;
 	pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-dlink-dns327l.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-dlink-dns327l.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-dlink-dns327l.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-dlink-dns327l.dts	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,7 @@
 		stdout-path = &uart0;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MiB */
 	};
@@ -72,20 +72,6 @@
 			MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000
 			MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			pcie@2,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			sata@a0000 {
 				nr-ports = <2>;
@@ -262,6 +248,20 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	pcie@2,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
 &pinctrl {
 	sata_l_white_pin: sata-l-white-pin {
 		marvell,pins = "mpp57";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -50,9 +50,11 @@
  */
 
 #include "armada-370-xp.dtsi"
-/include/ "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	model = "Marvell Armada 370 family SoC";
 	compatible = "marvell,armada370", "marvell,armada-370-xp";
 
@@ -70,7 +72,7 @@
 			reg = <MBUS_ID(0x01, 0xe0) 0 0x100000>;
 		};
 
-		pcie-controller {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,armada-370-pcie";
 			status = "disabled";
 			device_type = "pci";
@@ -89,7 +91,7 @@
 				0x82000000 0x2 0     MBUS_ID(0x08, 0xe8) 0       1 0 /* Port 1.0 MEM */
 				0x81000000 0x2 0     MBUS_ID(0x08, 0xe0) 0       1 0 /* Port 1.0 IO  */>;
 
-			pcie@1,0 {
+			pcie0: pcie@1,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
 				reg = <0x0800 0 0 0 0>;
@@ -106,7 +108,7 @@
 				status = "disabled";
 			};
 
-			pcie@2,0 {
+			pcie2: pcie@2,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
@@ -125,7 +127,7 @@
 		};
 
 		internal-regs {
-			L2: l2-cache {
+			L2: l2-cache@8000 {
 				compatible = "marvell,aurora-outer-cache";
 				reg = <0x08000 0x1000>;
 				cache-id-part = <0x100>;
@@ -134,14 +136,6 @@
 				wt-override;
 			};
 
-			i2c0: i2c@11000 {
-				reg = <0x11000 0x20>;
-			};
-
-			i2c1: i2c@11100 {
-				reg = <0x11100 0x20>;
-			};
-
 			gpio0: gpio@18100 {
 				compatible = "marvell,orion-gpio";
 				reg = <0x18100 0x40>;
@@ -175,22 +169,8 @@
 				interrupts = <91>;
 			};
 
-			/*
-			 * Default UART pinctrl setting without RTS/CTS, can
-			 * be overwritten on board level if a different
-			 * configuration is used.
-			 */
-			uart0: serial@12000 {
-				pinctrl-0 = <&uart0_pins>;
-				pinctrl-names = "default";
-			};
-
-			uart1: serial@12100 {
-				pinctrl-0 = <&uart1_pins>;
-				pinctrl-names = "default";
-			};
 
-			system-controller@18200 {
+			systemc: system-controller@18200 {
 				compatible = "marvell,armada-370-xp-system-controller";
 				reg = <0x18200 0x100>;
 			};
@@ -208,37 +188,18 @@
 				#clock-cells = <1>;
 			};
 
-			thermal@18300 {
+			thermal: thermal@18300 {
 				compatible = "marvell,armada370-thermal";
 				reg = <0x18300 0x4
 					0x18304 0x4>;
 				status = "okay";
 			};
 
-			sscg@18330 {
+			sscg: sscg@18330 {
 				reg = <0x18330 0x4>;
 			};
 
-			interrupt-controller@20a00 {
-				reg = <0x20a00 0x1d0>, <0x21870 0x58>;
-			};
-
-			timer@20300 {
-				compatible = "marvell,armada-370-timer";
-				clocks = <&coreclk 2>;
-			};
-
-			watchdog@20300 {
-				compatible = "marvell,armada-370-wdt";
-				clocks = <&coreclk 2>;
-			};
-
-			cpurst@20800 {
-				compatible = "marvell,armada-370-cpu-reset";
-				reg = <0x20800 0x8>;
-			};
-
-			cpu-config@21000 {
+			cpuconf: cpu-config@21000 {
 				compatible = "marvell,armada-370-cpu-config";
 				reg = <0x21000 0x8>;
 			};
@@ -253,15 +214,7 @@
 				status = "disabled";
 			};
 
-			usb@50000 {
-				clocks = <&coreclk 0>;
-			};
-
-			usb@51000 {
-				clocks = <&coreclk 0>;
-			};
-
-			xor@60800 {
+			xor0: xor@60800 {
 				compatible = "marvell,orion-xor";
 				reg = <0x60800 0x100
 				       0x60A00 0x100>;
@@ -280,7 +233,7 @@
 				};
 			};
 
-			xor@60900 {
+			xor1: xor@60900 {
 				compatible = "marvell,orion-xor";
 				reg = <0x60900 0x100
 				       0x60b00 0x100>;
@@ -299,15 +252,7 @@
 				};
 			};
 
-			ethernet@70000 {
-				compatible = "marvell,armada-370-neta";
-			};
-
-			ethernet@74000 {
-				compatible = "marvell,armada-370-neta";
-			};
-
-			crypto@90000 {
+			cesa: crypto@90000 {
 				compatible = "marvell,armada-370-crypto";
 				reg = <0x90000 0x10000>;
 				reg-names = "regs";
@@ -342,6 +287,59 @@
 	};
 };
 
+/*
+ * Default UART pinctrl setting without RTS/CTS, can be overwritten on
+ * board level if a different configuration is used.
+ */
+
+&uart0 {
+	pinctrl-0 = <&uart0_pins>;
+	pinctrl-names = "default";
+};
+
+&uart1 {
+	pinctrl-0 = <&uart1_pins>;
+	pinctrl-names = "default";
+};
+
+&i2c0 {
+	reg = <0x11000 0x20>;
+};
+
+&i2c1 {
+	reg = <0x11100 0x20>;
+};
+
+&mpic {
+	reg = <0x20a00 0x1d0>, <0x21870 0x58>;
+};
+
+&timer {
+	compatible = "marvell,armada-370-timer";
+	clocks = <&coreclk 2>;
+};
+
+&watchdog {
+	compatible = "marvell,armada-370-wdt";
+	clocks = <&coreclk 2>;
+};
+
+&usb0 {
+	clocks = <&coreclk 0>;
+};
+
+&usb1 {
+	clocks = <&coreclk 0>;
+};
+
+&eth0 {
+	compatible = "marvell,armada-370-neta";
+};
+
+&eth1 {
+	compatible = "marvell,armada-370-neta";
+};
+
 &pinctrl {
 	compatible = "marvell,mv88f6710-pinctrl";
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-mirabox.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-mirabox.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-mirabox.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-mirabox.dts	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MB */
 	};
@@ -64,22 +64,6 @@
 			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000
 			  MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* Internal mini-PCIe connector */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* Connected on the PCB to a USB 3.0 XHCI controller */
-			pcie@2,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			serial@12000 {
 				status = "okay";
@@ -113,17 +97,6 @@
 				};
 			};
 
-			mdio {
-				pinctrl-0 = <&mdio_pins>;
-				pinctrl-names = "default";
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 {
-					reg = <1>;
-				};
-			};
 			ethernet@70000 {
 				pinctrl-0 = <&ge0_rgmii_pins>;
 				pinctrl-names = "default";
@@ -197,6 +170,34 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/* Internal mini-PCIe connector */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* Connected on the PCB to a USB 3.0 XHCI controller */
+	pcie@2,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
 &pinctrl {
 	pwr_led_pin: pwr-led-pin {
 		marvell,pins = "mpp63";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-netgear-rn102.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-netgear-rn102.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-netgear-rn102.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-netgear-rn102.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MB */
 	};
@@ -66,22 +66,6 @@
 			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000
 			  MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* Connected to Marvell 88SE9170 SATA controller */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* Connected to FL1009 USB 3.0 controller */
-			pcie@2,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 
 			/* RTC is provided by Intersil ISL12057 I2C RTC chip */
@@ -99,14 +83,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				pinctrl-0 = <&mdio_pins>;
-				pinctrl-names = "default";
-				phy0: ethernet-phy@0 { /* Marvell 88E1318 */
-					reg = <0>;
-				};
-			};
-
 			ethernet@74000 {
 				pinctrl-0 = <&ge1_rgmii_pins>;
 				pinctrl-names = "default";
@@ -120,8 +96,11 @@
 			};
 
 			i2c@11000 {
-				compatible = "marvell,mv64xxx-i2c";
 				clock-frequency = <100000>;
+
+				pinctrl-0 = <&i2c0_pins>;
+				pinctrl-names = "default";
+
 				status = "okay";
 
 				isl12057: isl12057@68 {
@@ -257,6 +236,30 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/* Connected to Marvell 88SE9170 SATA controller */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* Connected to FL1009 USB 3.0 controller */
+	pcie@2,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+	phy0: ethernet-phy@0 { /* Marvell 88E1318 */
+		reg = <0>;
+	};
+};
+
 &pinctrl {
 	power_led_pin: power-led-pin {
 		marvell,pins = "mpp57";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-netgear-rn104.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-netgear-rn104.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-netgear-rn104.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-netgear-rn104.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MB */
 	};
@@ -66,22 +66,6 @@
 			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000
 			  MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* Connected to FL1009 USB 3.0 controller */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* Connected to Marvell 88SE9215 SATA controller */
-			pcie@2,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 
 			/* RTC is provided by Intersil ISL12057 I2C RTC chip */
@@ -93,18 +77,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				pinctrl-0 = <&mdio_pins>;
-				pinctrl-names = "default";
-				phy0: ethernet-phy@0 { /* Marvell 88E1318 */
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 { /* Marvell 88E1318 */
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
 				pinctrl-0 = <&ge0_rgmii_pins>;
 				pinctrl-names = "default";
@@ -126,8 +98,11 @@
 			};
 
 			i2c@11000 {
-				compatible = "marvell,mv64xxx-i2c";
 				clock-frequency = <100000>;
+
+				pinctrl-0 = <&i2c0_pins>;
+				pinctrl-names = "default";
+
 				status = "okay";
 
 				isl12057: isl12057@68 {
@@ -279,6 +254,34 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/* Connected to FL1009 USB 3.0 controller */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* Connected to Marvell 88SE9215 SATA controller */
+	pcie@2,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+	phy0: ethernet-phy@0 { /* Marvell 88E1318 */
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 { /* Marvell 88E1318 */
+		reg = <1>;
+	};
+};
+
 &pinctrl {
 	poweroff: poweroff {
 		marvell,pins = "mpp60";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-rd.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-rd.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-rd.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-rd.dts	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MB */
 	};
@@ -77,22 +77,6 @@
 			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000
 			  MBUS_ID(0x09, 0x01) 0 0xf1100000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* Internal mini-PCIe connector */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* Internal mini-PCIe connector */
-			pcie@2,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			serial@12000 {
 				status = "okay";
@@ -102,14 +86,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				pinctrl-0 = <&mdio_pins>;
-				pinctrl-names = "default";
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				phy = <&phy0>;
@@ -146,7 +122,7 @@
 				compatible = "gpio-keys";
 				#address-cells = <1>;
 				#size-cells = <0>;
-				button@1 {
+				button {
 					label = "Software Button";
 					linux,code = <KEY_POWER>;
 					gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
@@ -196,7 +172,7 @@
 		};
 	};
 
-	dsa@0 {
+	dsa {
 		compatible = "marvell,dsa";
 		#address-cells = <2>;
 		#size-cells = <0>;
@@ -235,7 +211,32 @@
 			};
 		};
 	 };
- };
+};
+
+&pciec {
+	status = "okay";
+
+	/* Internal mini-PCIe connector */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* Internal mini-PCIe connector */
+	pcie@2,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
 
 &pinctrl {
 	fan_pins: fan-pins {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts	2017-02-12 16:03:20.000000000 -0500
@@ -28,20 +28,7 @@
 	compatible = "seagate,dart-4", "marvell,armada370", "marvell,armada-370-xp";
 
 	soc {
-		pcie-controller {
-			/* SATA AHCI controller 88SE9170 */
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-
 		internal-regs {
-			mdio {
-				phy1: ethernet-phy@1 {
-					reg = <1>;
-				};
-			};
-
 			ethernet@74000 {
 				status = "okay";
 				pinctrl-0 = <&ge1_rgmii_pins>;
@@ -131,3 +118,17 @@
 			  1300 0>;
 	};
 };
+
+&pciec {
+	/* SATA AHCI controller 88SE9170 */
+	pcie@1,0 {
+		status = "okay";
+	};
+};
+
+&mdio {
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MB */
 	};
@@ -32,15 +32,6 @@
 		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
 			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* USB 3.0 bridge ASM1042A */
-			pcie@2,0 {
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			serial@12000 {
 				status = "okay";
@@ -51,15 +42,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				pinctrl-0 = <&mdio_pins>;
-				pinctrl-names = "default";
-
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				pinctrl-0 = <&ge0_rgmii_pins>;
@@ -159,19 +141,19 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		button@1 {
+		power {
 			label = "Power button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
 			debounce-interval = <100>;
 		};
-		button@2 {
+		backup {
 			label = "Backup button";
 			linux,code = <KEY_OPTION>;
 			gpios = <&gpio0 31 GPIO_ACTIVE_LOW>;
 			debounce-interval = <100>;
 		};
-		button@3 {
+		reset {
 			label = "Reset Button";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
@@ -208,6 +190,25 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/* USB 3.0 bridge ASM1042A */
+	pcie@2,0 {
+		status = "okay";
+	};
+};
+
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
 &pinctrl {
 	pinctrl-0 = <&hdd0_led_sata_pin>, <&hdd1_led_sata_pin>;
 	pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MB */
 	};
@@ -33,15 +33,6 @@
 		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
 			  MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* USB 3.0 Bridge ASM1042A */
-			pcie@1,0 {
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			coherency-fabric@20200 {
 				broken-idle;
@@ -51,15 +42,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				pinctrl-0 = <&mdio_pins>;
-				pinctrl-names = "default";
-
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-			};
-
 			ethernet@74000 {
 				status = "okay";
 				pinctrl-0 = <&ge1_rgmii_pins>;
@@ -107,19 +89,19 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		button@1 {
+		power {
 			label = "Power button";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;
 			debounce-interval = <100>;
 		};
-		button@2 {
+		reset {
 			label = "Reset Button";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
 			debounce-interval = <100>;
 		};
-		button@3 {
+		button {
 			label = "USB VBUS error";
 			linux,code = <KEY_UNKNOWN>;
 			gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
@@ -143,6 +125,24 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/* USB 3.0 Bridge ASM1042A */
+	pcie@1,0 {
+		status = "okay";
+	};
+};
+
+&mdio {
+	pinctrl-0 = <&mdio_pins>;
+	pinctrl-names = "default";
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
 &pinctrl {
 	pinctrl-0 = <&sata_led_pin>;
 	pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-synology-ds213j.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-synology-ds213j.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-synology-ds213j.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-synology-ds213j.dts	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x20000000>; /* 512 MB */
 	};
@@ -127,12 +127,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy1: ethernet-phy@1 { /* Marvell 88E1512 */
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
 			       status = "okay";
 			       phy = <&phy1>;
@@ -192,7 +186,7 @@
 		pinctrl-0 = <&sata1_pwr_pin &sata2_pwr_pin>;
 		pinctrl-names = "default";
 
-		sata1_regulator: sata1-regulator {
+		sata1_regulator: sata1-regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
 			regulator-name = "SATA1 Power";
@@ -205,7 +199,7 @@
 			gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
 		};
 
-		sata2_regulator: sata2-regulator {
+		sata2_regulator: sata2-regulator@2 {
 			compatible = "regulator-fixed";
 			reg = <2>;
 			regulator-name = "SATA2 Power";
@@ -220,6 +214,12 @@
 	};
 };
 
+&mdio {
+	phy1: ethernet-phy@1 { /* Marvell 88E1512 */
+		reg = <1>;
+	};
+};
+
 &pinctrl {
 	disk1_led_pin: disk1-led-pin {
 		marvell,pins = "mpp31";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-xp.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-xp.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-370-xp.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-370-xp.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -50,8 +50,6 @@
  * 370 and Armada XP SoC.
  */
 
-/include/ "skeleton64.dtsi"
-
 #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
 
 / {
@@ -86,7 +84,7 @@
 		pcie-mem-aperture = <0xf8000000 0x7e00000>;
 		pcie-io-aperture  = <0xffe00000 0x100000>;
 
-		devbus-bootcs {
+		devbus_bootcs: devbus-bootcs {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
@@ -96,7 +94,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs0 {
+		devbus_cs0: devbus-cs0 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
@@ -106,7 +104,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs1 {
+		devbus_cs1: devbus-cs1 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
@@ -116,7 +114,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs2 {
+		devbus_cs2: devbus-cs2 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
@@ -126,7 +124,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs3 {
+		devbus_cs3: devbus-cs3 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
@@ -142,7 +140,7 @@
 			#size-cells = <1>;
 			ranges = <0 MBUS_ID(0xf0, 0x01) 0 0x100000>;
 
-			rtc@10300 {
+			rtc: rtc@10300 {
 				compatible = "marvell,orion-rtc";
 				reg = <0x10300 0x20>;
 				interrupts = <50>;
@@ -214,33 +212,38 @@
 				msi-controller;
 			};
 
-			coherency-fabric@20200 {
+			coherencyfab: coherency-fabric@20200 {
 				compatible = "marvell,coherency-fabric";
 				reg = <0x20200 0xb0>, <0x21010 0x1c>;
 			};
 
-			timer@20300 {
+			timer: timer@20300 {
 				reg = <0x20300 0x30>, <0x21040 0x30>;
 				interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
 			};
 
-			watchdog@20300 {
+			watchdog: watchdog@20300 {
 				reg = <0x20300 0x34>, <0x20704 0x4>;
 			};
 
-			pmsu@22000 {
+			cpurst: cpurst@20800 {
+				compatible = "marvell,armada-370-cpu-reset";
+				reg = <0x20800 0x8>;
+			};
+
+			pmsu: pmsu@22000 {
 				compatible = "marvell,armada-370-pmsu";
 				reg = <0x22000 0x1000>;
 			};
 
-			usb@50000 {
+			usb0: usb@50000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x50000 0x500>;
 				interrupts = <45>;
 				status = "disabled";
 			};
 
-			usb@51000 {
+			usb1: usb@51000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x51000 0x500>;
 				interrupts = <46>;
@@ -254,7 +257,7 @@
 				status = "disabled";
 			};
 
-			mdio: mdio {
+			mdio: mdio@72004 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "marvell,orion-mdio";
@@ -269,7 +272,7 @@
 				status = "disabled";
 			};
 
-			sata@a0000 {
+			sata: sata@a0000 {
 				compatible = "marvell,armada-370-sata";
 				reg = <0xa0000 0x5000>;
 				interrupts = <55>;
@@ -278,7 +281,7 @@
 				status = "disabled";
 			};
 
-			nand@d0000 {
+			nand: nand@d0000 {
 				compatible = "marvell,armada370-nand";
 				reg = <0xd0000 0x54>;
 				#address-cells = <1>;
@@ -288,7 +291,7 @@
 				status = "disabled";
 			};
 
-			mvsdio@d4000 {
+			sdio: mvsdio@d4000 {
 				compatible = "marvell,orion-sdio";
 				reg = <0xd4000 0x200>;
 				interrupts = <54>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-375-db.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-375-db.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-375-db.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-375-db.dts	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x40000000>; /* 1 GB */
 	};
@@ -69,138 +69,141 @@
 			  MBUS_ID(0x09, 0x09) 0 0xf1100000 0x10000
 			  MBUS_ID(0x09, 0x05) 0 0xf1110000 0x10000>;
 
-		internal-regs {
-			spi@10600 {
-				pinctrl-0 = <&spi0_pins>;
-				pinctrl-names = "default";
-				/*
-				 * SPI conflicts with NAND, so we disable it
-				 * here, and select NAND as the enabled device
-				 * by default.
-				 */
-				status = "disabled";
+	};
+};
+&pciec {
+	status = "okay";
+};
 
-				spi-flash@0 {
-					#address-cells = <1>;
-					#size-cells = <1>;
-					compatible = "n25q128a13", "jedec,spi-nor";
-					reg = <0>; /* Chip select 0 */
-					spi-max-frequency = <108000000>;
-				};
-			};
+/*
+ * The two PCIe units are accessible through
+ * standard PCIe slots on the board.
+ */
+&pcie0 {
+	/* Port 0, Lane 0 */
+	status = "okay";
+};
 
-			i2c@11000 {
-				status = "okay";
-				clock-frequency = <100000>;
-				pinctrl-0 = <&i2c0_pins>;
-				pinctrl-names = "default";
-			};
+&pcie1 {
+	/* Port 1, Lane 0 */
+	status = "okay";
+};
 
-			i2c@11100 {
-				status = "okay";
-				clock-frequency = <100000>;
-				pinctrl-0 = <&i2c1_pins>;
-				pinctrl-names = "default";
-			};
 
-			serial@12000 {
-				status = "okay";
-			};
+&spi0 {
+	pinctrl-0 = <&spi0_pins>;
+	pinctrl-names = "default";
 
-			pinctrl {
-				sdio_st_pins: sdio-st-pins {
-					marvell,pins = "mpp44", "mpp45";
-					marvell,function = "gpio";
-				};
-			};
+	/*
+	 * SPI conflicts with NAND, so we disable it here, and
+	 * select NAND as the enabled device by default.
+	 */
 
-			sata@a0000 {
-				status = "okay";
-				nr-ports = <2>;
-			};
+	status = "disabled";
 
-			nand: nand@d0000 {
-				pinctrl-0 = <&nand_pins>;
-				pinctrl-names = "default";
-				status = "okay";
-				num-cs = <1>;
-				marvell,nand-keep-config;
-				marvell,nand-enable-arbiter;
-				nand-on-flash-bbt;
-				nand-ecc-strength = <4>;
-				nand-ecc-step-size = <512>;
+	spi-flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q128a13", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <108000000>;
+	};
+};
 
-				partition@0 {
-					label = "U-Boot";
-					reg = <0 0x800000>;
-				};
-				partition@800000 {
-					label = "Linux";
-					reg = <0x800000 0x800000>;
-				};
-				partition@1000000 {
-					label = "Filesystem";
-					reg = <0x1000000 0x3f000000>;
-				};
-			};
+&i2c0 {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c0_pins>;
+	pinctrl-names = "default";
+};
 
-			usb@54000 {
-				status = "okay";
-			};
+&i2c1 {
+	status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "default";
+};
 
-			usb3@58000 {
-				status = "okay";
-			};
+&uart0 {
+	status = "okay";
+};
 
-			mvsdio@d4000 {
-				pinctrl-0 = <&sdio_pins &sdio_st_pins>;
-				pinctrl-names = "default";
-				status = "okay";
-				cd-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
-				wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
-			};
+&pinctrl {
+	sdio_st_pins: sdio-st-pins {
+		marvell,pins = "mpp44", "mpp45";
+		marvell,function = "gpio";
+	};
+};
 
-			mdio {
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
+&sata {
+	status = "okay";
+	nr-ports = <2>;
+};
 
-				phy3: ethernet-phy@3 {
-					reg = <3>;
-				};
-			};
+&nand {
+	pinctrl-0 = <&nand_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+	num-cs = <1>;
+	marvell,nand-keep-config;
+	marvell,nand-enable-arbiter;
+	nand-on-flash-bbt;
+	nand-ecc-strength = <4>;
+	nand-ecc-step-size = <512>;
 
-			ethernet@f0000 {
-				status = "okay";
+	partition@0 {
+		label = "U-Boot";
+		reg = <0 0x800000>;
+	};
+	partition@800000 {
+		label = "Linux";
+		reg = <0x800000 0x800000>;
+	};
+	partition@1000000 {
+		label = "Filesystem";
+		reg = <0x1000000 0x3f000000>;
+	};
+};
 
-				eth0@c4000 {
-					status = "okay";
-					phy = <&phy0>;
-					phy-mode = "rgmii-id";
-				};
+&usb1 {
+	status = "okay";
+};
 
-				eth1@c5000 {
-					status = "okay";
-					phy = <&phy3>;
-					phy-mode = "gmii";
-				};
-			};
-		};
+&usb2 {
+	status = "okay";
+};
 
-		pcie-controller {
-			status = "okay";
-			/*
-			 * The two PCIe units are accessible through
-			 * standard PCIe slots on the board.
-			 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-			pcie@2,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
+&sdio {
+	pinctrl-0 = <&sdio_pins &sdio_st_pins>;
+	pinctrl-names = "default";
+	status = "okay";
+	cd-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+	wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+};
+
+&mdio {
+	phy0: ethernet-phy@0 {
+		reg = <0>;
 	};
+
+	phy3: ethernet-phy@3 {
+		reg = <3>;
+	};
+};
+
+&ethernet {
+	status = "okay";
+};
+
+
+&eth0 {
+	status = "okay";
+	phy = <&phy0>;
+	phy-mode = "rgmii-id";
+};
+
+&eth1 {
+	status = "okay";
+	phy = <&phy3>;
+	phy-mode = "gmii";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-375.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-375.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-375.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-375.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,6 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "skeleton.dtsi"
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/phy/phy.h>
@@ -53,6 +52,9 @@
 #define MBUS_ID(target,attributes) (((target) << 24) | ((attributes) << 16))
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	model = "Marvell Armada 375 family SoC";
 	compatible = "marvell,armada375";
 
@@ -65,7 +67,7 @@
 	};
 
 	clocks {
-		/* 2 GHz fixed main PLL */
+		/* 1 GHz fixed main PLL */
 		mainpll: mainpll {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
@@ -84,12 +86,12 @@
 		#size-cells = <0>;
 		enable-method = "marvell,armada-375-smp";
 
-		cpu@0 {
+		cpu0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
 		};
-		cpu@1 {
+		cpu1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
@@ -115,7 +117,7 @@
 			reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
 		};
 
-		devbus-bootcs {
+		devbus_bootcs: devbus-bootcs {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
@@ -125,7 +127,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs0 {
+		devbus_cs0: devbus-cs0 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
@@ -135,7 +137,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs1 {
+		devbus_cs1: devbus-cs1 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
@@ -145,7 +147,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs2 {
+		devbus_cs2: devbus-cs2 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
@@ -155,7 +157,7 @@
 			status = "disabled";
 		};
 
-		devbus-cs3 {
+		devbus_cs3: devbus-cs3 {
 			compatible = "marvell,mvebu-devbus";
 			reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
 			ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
@@ -182,12 +184,12 @@
 				prefetch-data = <1>;
 			};
 
-			scu@c000 {
+			scu: scu@c000 {
 				compatible = "arm,cortex-a9-scu";
 				reg = <0xc000 0x58>;
 			};
 
-			timer@c600 {
+			timer0: timer@c600 {
 				compatible = "arm,cortex-a9-twd-timer";
 				reg = <0xc600 0x20>;
 				interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2))>;
@@ -203,7 +205,7 @@
 				      <0xc100 0x100>;
 			};
 
-			mdio {
+			mdio: mdio@c0054 {
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "marvell,orion-mdio";
@@ -212,7 +214,7 @@
 			};
 
 			/* Network controller */
-			ethernet@f0000 {
+			ethernet: ethernet@f0000 {
 				compatible = "marvell,armada-375-pp2";
 				reg = <0xf0000 0xa000>, /* Packet Processor regs */
 				      <0xc0000 0x3060>, /* LMS regs */
@@ -222,20 +224,20 @@
 				clock-names = "pp_clk", "gop_clk";
 				status = "disabled";
 
-				eth0: eth0@c4000 {
+				eth0: eth0 {
 					interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
 					port-id = <0>;
 					status = "disabled";
 				};
 
-				eth1: eth1@c5000 {
+				eth1: eth1 {
 					interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 					port-id = <1>;
 					status = "disabled";
 				};
 			};
 
-			rtc@10300 {
+			rtc: rtc@10300 {
 				compatible = "marvell,orion-rtc";
 				reg = <0x10300 0x20>;
 				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
@@ -307,7 +309,7 @@
 				status = "disabled";
 			};
 
-			pinctrl {
+			pinctrl: pinctrl@18000 {
 				compatible = "marvell,mv88f6720-pinctrl";
 				reg = <0x18000 0x24>;
 
@@ -382,7 +384,7 @@
 				interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
-			system-controller@18200 {
+			systemc: system-controller@18200 {
 				compatible = "marvell,armada-375-system-controller";
 				reg = <0x18200 0x100>;
 			};
@@ -415,7 +417,7 @@
 				interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
 			};
 
-			timer@20300 {
+			timer1: timer@20300 {
 				compatible = "marvell,armada-375-timer", "marvell,armada-370-timer";
 				reg = <0x20300 0x30>, <0x21040 0x30>;
 				interrupts-extended = <&gic  GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
@@ -428,24 +430,24 @@
 				clock-names = "nbclk", "fixed";
 			};
 
-			watchdog@20300 {
+			watchdog: watchdog@20300 {
 				compatible = "marvell,armada-375-wdt";
 				reg = <0x20300 0x34>, <0x20704 0x4>, <0x18254 0x4>;
 				clocks = <&coreclk 0>, <&refclk>;
 				clock-names = "nbclk", "fixed";
 			};
 
-			cpurst@20800 {
+			cpurst: cpurst@20800 {
 				compatible = "marvell,armada-370-cpu-reset";
 				reg = <0x20800 0x10>;
 			};
 
-			coherency-fabric@21010 {
+			coherencyfab: coherency-fabric@21010 {
 				compatible = "marvell,armada-375-coherency-fabric";
 				reg = <0x21010 0x1c>;
 			};
 
-			usb@50000 {
+			usb0: usb@50000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x50000 0x500>;
 				interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
@@ -455,7 +457,7 @@
 				status = "disabled";
 			};
 
-			usb@54000 {
+			usb1: usb@54000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x54000 0x500>;
 				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
@@ -463,7 +465,7 @@
 				status = "disabled";
 			};
 
-			usb3@58000 {
+			usb2: usb3@58000 {
 				compatible = "marvell,armada-375-xhci";
 				reg = <0x58000 0x20000>,<0x5b880 0x80>;
 				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
@@ -473,7 +475,7 @@
 				status = "disabled";
 			};
 
-			xor@60800 {
+			xor0: xor@60800 {
 				compatible = "marvell,orion-xor";
 				reg = <0x60800 0x100
 				       0x60A00 0x100>;
@@ -493,7 +495,7 @@
 				};
 			};
 
-			xor@60900 {
+			xor1: xor@60900 {
 				compatible = "marvell,orion-xor";
 				reg = <0x60900 0x100
 				       0x60b00 0x100>;
@@ -513,7 +515,7 @@
 				};
 			};
 
-			crypto@90000 {
+			cesa: crypto@90000 {
 				compatible = "marvell,armada-375-crypto";
 				reg = <0x90000 0x10000>;
 				reg-names = "regs";
@@ -528,7 +530,7 @@
 				marvell,crypto-sram-size = <0x800>;
 			};
 
-			sata@a0000 {
+			sata: sata@a0000 {
 				compatible = "marvell,armada-370-sata";
 				reg = <0xa0000 0x5000>;
 				interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
@@ -537,7 +539,7 @@
 				status = "disabled";
 			};
 
-			nand@d0000 {
+			nand: nand@d0000 {
 				compatible = "marvell,armada370-nand";
 				reg = <0xd0000 0x54>;
 				#address-cells = <1>;
@@ -547,7 +549,7 @@
 				status = "disabled";
 			};
 
-			mvsdio@d4000 {
+			sdio: mvsdio@d4000 {
 				compatible = "marvell,orion-sdio";
 				reg = <0xd4000 0x200>;
 				interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
@@ -559,7 +561,7 @@
 				status = "disabled";
 			};
 
-			thermal@e8078 {
+			thermal: thermal@e8078 {
 				compatible = "marvell,armada375-thermal";
 				reg = <0xe8078 0x4>, <0xe807c 0x8>;
 				status = "okay";
@@ -580,7 +582,7 @@
 			};
 		};
 
-		pcie-controller {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,armada-370-pcie";
 			status = "disabled";
 			device_type = "pci";
@@ -599,7 +601,7 @@
 				0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 1 MEM */
 				0x81000000 0x2 0       MBUS_ID(0x04, 0xd0) 0 1 0 /* Port 1 IO  */>;
 
-			pcie@1,0 {
+			pcie0: pcie@1,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
 				reg = <0x0800 0 0 0 0>;
@@ -616,7 +618,7 @@
 				status = "disabled";
 			};
 
-			pcie@2,0 {
+			pcie1: pcie@2,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-385-turris-omnia.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-385-turris-omnia.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-385-turris-omnia.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-385-turris-omnia.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,340 @@
+/*
+ * Device Tree file for the Turris Omnia
+ *
+ * Copyright (C) 2016 Uwe Kleine-König <uwe@kleine-koenig.org>
+ * Copyright (C) 2016 Tomas Hlavacek <tmshlvkc@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/*
+ * Schematic available at https://www.turris.cz/doc/_media/rtrom01-schema.pdf
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "armada-385.dtsi"
+
+/ {
+	model = "Turris Omnia";
+	compatible = "cznic,turris-omnia", "marvell,armada385", "marvell,armada380";
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x40000000>; /* 1024 MB */
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+			  MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
+			  MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+			  MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
+
+		internal-regs {
+
+			/* USB part of the PCIe2/USB 2.0 port */
+			usb@58000 {
+				status = "okay";
+			};
+
+			sata@a8000 {
+				status = "okay";
+			};
+
+			sdhci@d8000 {
+				pinctrl-names = "default";
+				pinctrl-0 = <&sdhci_pins>;
+				status = "okay";
+
+				bus-width = <8>;
+				no-1-8-v;
+				non-removable;
+			};
+
+			usb3@f0000 {
+				status = "okay";
+			};
+
+			usb3@f8000 {
+				status = "okay";
+			};
+		};
+
+		pcie-controller {
+			status = "okay";
+
+			pcie@1,0 {
+				/* Port 0, Lane 0 */
+				status = "okay";
+			};
+
+			pcie@2,0 {
+				/* Port 1, Lane 0 */
+				status = "okay";
+			};
+
+			pcie@3,0 {
+				/* Port 2, Lane 0 */
+				status = "okay";
+			};
+		};
+	};
+};
+
+/* Connected to 88E6176 switch, port 6 */
+&eth0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ge0_rgmii_pins>;
+	status = "okay";
+	phy-mode = "rgmii-id";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+/* Connected to 88E6176 switch, port 5 */
+&eth1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ge1_rgmii_pins>;
+	status = "okay";
+	phy-mode = "rgmii-id";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+/* WAN port */
+&eth2 {
+	status = "okay";
+	phy-mode = "sgmii";
+	phy = <&phy1>;
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins>;
+	status = "okay";
+
+	i2cmux@70 {
+		compatible = "nxp,pca9547";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+		status = "okay";
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			/* STM32F0 command interface at address 0x2a */
+			/* leds device (in STM32F0) at address 0x2b */
+
+			eeprom@54 {
+				compatible = "at,24c64";
+				reg = <0x54>;
+
+				/* The EEPROM contains data for bootloader.
+				 * Contents:
+				 * 	struct omnia_eeprom {
+				 * 		u32 magic; (=0x0341a034 in LE)
+				 *		u32 ramsize; (in GiB)
+				 * 		char regdomain[4];
+				 * 		u32 crc32;
+				 * 	};
+				 */
+			};
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			/* routed to PCIe0/mSATA connector (CN7A) */
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+
+			/* routed to PCIe1/USB2 connector (CN61A) */
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			/* routed to PCIe2 connector (CN62A) */
+		};
+
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+
+			/* routed to SFP+ */
+		};
+
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+
+			/* ATSHA204A at address 0x64 */
+		};
+
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+
+			/* exposed on pin header */
+		};
+
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+
+			pcawan: gpio@71 {
+				/*
+				 * GPIO expander for SFP+ signals and
+				 * and phy irq
+				 */
+				compatible = "nxp,pca9538";
+				reg = <0x71>;
+
+				pinctrl-names = "default";
+				pinctrl-0 = <&pcawan_pins>;
+
+				interrupt-parent = <&gpio1>;
+				interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
+
+				gpio-controller;
+				#gpio-cells = <2>;
+			};
+		};
+	};
+};
+
+&mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio_pins>;
+	status = "okay";
+
+	phy1: phy@1 {
+		status = "okay";
+		compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+
+		/* irq is connected to &pcawan pin 7 */
+	};
+
+	/* Switch MV88E7176 at address 0x10 */
+};
+
+&pinctrl {
+	pcawan_pins: pcawan-pins {
+		marvell,pins = "mpp46";
+		marvell,function = "gpio";
+	};
+
+	spi0cs0_pins: spi0cs0-pins {
+		marvell,pins = "mpp25";
+		marvell,function = "spi0";
+	};
+
+	spi0cs1_pins: spi0cs1-pins {
+		marvell,pins = "mpp26";
+		marvell,function = "spi0";
+	};
+};
+
+&spi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins &spi0cs0_pins>;
+	status = "okay";
+
+	spi-nor@0 {
+		compatible = "spansion,s25fl164k", "jedec,spi-nor";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				reg = <0x0 0x00100000>;
+				label = "U-Boot";
+			};
+
+			partition@100000 {
+				reg = <0x00100000 0x00700000>;
+				label = "Rescue system";
+			};
+		};
+	};
+
+	/* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */
+};
+
+&uart0 {
+	/* Pin header CN10 */
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins>;
+	status = "okay";
+};
+
+&uart1 {
+	/* Pin header CN11 */
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-38x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-38x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-38x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-38x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -661,7 +661,7 @@
 	};
 
 	clocks {
-		/* 2 GHz fixed main PLL */
+		/* 1 GHz fixed main PLL */
 		mainpll: mainpll {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-39x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-39x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-39x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-39x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -573,7 +573,7 @@
 	};
 
 	clocks {
-		/* 2 GHz fixed main PLL */
+		/* 1 GHz fixed main PLL */
 		mainpll: mainpll {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-axpwifiap.dts	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x00000000 0x00000000 0x40000000>; /* 1GB */
 	};
@@ -73,28 +73,6 @@
 			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
 			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* First mini-PCIe port */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* Second mini-PCIe port */
-			pcie@2,0 {
-				/* Port 0, Lane 1 */
-				status = "okay";
-			};
-
-			/* Renesas uPD720202 USB 3.0 controller */
-			pcie@3,0 {
-				/* Port 0, Lane 3 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			/* UART0 */
 			serial@12000 {
@@ -111,16 +89,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 {
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
 				pinctrl-0 = <&ge0_rgmii_pins>;
 				pinctrl-names = "default";
@@ -145,7 +113,7 @@
 		pinctrl-0 = <&keys_pin>;
 		pinctrl-names = "default";
 
-		button@1 {
+		reset {
 			label = "Factory Reset Button";
 			linux,code = <KEY_SETUP>;
 			gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
@@ -153,6 +121,38 @@
 	};
 };
 
+&mdio {
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+&pciec {
+	status = "okay";
+
+	/* First mini-PCIe port */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* Second mini-PCIe port */
+	pcie@2,0 {
+		/* Port 0, Lane 1 */
+		status = "okay";
+	};
+
+	/* Renesas uPD720202 USB 3.0 controller */
+	pcie@3,0 {
+		/* Port 0, Lane 3 */
+		status = "okay";
+	};
+};
+
 &pinctrl {
 	pinctrl-0 = <&phy_int_pin>;
 	pinctrl-names = "default";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-db.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-db.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-db.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-db.dts	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x00000000 0 0x80000000>; /* 2 GB */
 	};
@@ -108,39 +108,6 @@
 			};
 		};
 
-		pcie-controller {
-			status = "okay";
-
-			/*
-			 * All 6 slots are physically present as
-			 * standard PCIe slots on the board.
-			 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-			pcie@2,0 {
-				/* Port 0, Lane 1 */
-				status = "okay";
-			};
-			pcie@3,0 {
-				/* Port 0, Lane 2 */
-				status = "okay";
-			};
-			pcie@4,0 {
-				/* Port 0, Lane 3 */
-				status = "okay";
-			};
-			pcie@9,0 {
-				/* Port 2, Lane 0 */
-				status = "okay";
-			};
-			pcie@10,0 {
-				/* Port 3, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			serial@12000 {
 				status = "okay";
@@ -160,24 +127,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 {
-					reg = <1>;
-				};
-
-				phy2: ethernet-phy@2 {
-					reg = <25>;
-				};
-
-				phy3: ethernet-phy@3 {
-					reg = <27>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				phy = <&phy0>;
@@ -266,6 +215,57 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/*
+	 * All 6 slots are physically present as
+	 * standard PCIe slots on the board.
+	 */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+	pcie@2,0 {
+		/* Port 0, Lane 1 */
+		status = "okay";
+	};
+	pcie@3,0 {
+		/* Port 0, Lane 2 */
+		status = "okay";
+	};
+	pcie@4,0 {
+		/* Port 0, Lane 3 */
+		status = "okay";
+	};
+	pcie@9,0 {
+		/* Port 2, Lane 0 */
+		status = "okay";
+	};
+	pcie@10,0 {
+		/* Port 3, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+
+	phy2: ethernet-phy@2 {
+		reg = <25>;
+	};
+
+	phy3: ethernet-phy@3 {
+		reg = <27>;
+	};
+};
+
 &spi0 {
 	status = "okay";
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -53,6 +53,9 @@
 #include "armada-370-xp.dtsi"
 
 / {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
 	model = "Marvell Armada XP family SoC";
 	compatible = "marvell,armadaxp", "marvell,armada-370-xp";
 
@@ -75,7 +78,7 @@
 				reg = <0x1400 0x500>;
 			};
 
-			L2: l2-cache {
+			L2: l2-cache@8000 {
 				compatible = "marvell,aurora-system-cache";
 				reg = <0x08000 0x1000>;
 				cache-id-part = <0x100>;
@@ -84,16 +87,6 @@
 				wt-override;
 			};
 
-			i2c0: i2c@11000 {
-				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
-				reg = <0x11000 0x100>;
-			};
-
-			i2c1: i2c@11100 {
-				compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
-				reg = <0x11100 0x100>;
-			};
-
 			uart2: serial@12200 {
 				compatible = "snps,dw-apb-uart";
 				pinctrl-0 = <&uart2_pins>;
@@ -118,7 +111,7 @@
 				status = "disabled";
 			};
 
-			system-controller@18200 {
+			systemc: system-controller@18200 {
 				compatible = "marvell,armada-370-xp-system-controller";
 				reg = <0x18200 0x500>;
 			};
@@ -136,7 +129,7 @@
 				#clock-cells = <1>;
 			};
 
-			thermal@182b0 {
+			thermal: thermal@182b0 {
 				compatible = "marvell,armadaxp-thermal";
 				reg = <0x182b0 0x4
 					0x184d0 0x4>;
@@ -150,27 +143,6 @@
 				clocks = <&coreclk 1>;
 			};
 
-			interrupt-controller@20a00 {
-			      reg = <0x20a00 0x2d0>, <0x21070 0x58>;
-			};
-
-			timer@20300 {
-				compatible = "marvell,armada-xp-timer";
-				clocks = <&coreclk 2>, <&refclk>;
-				clock-names = "nbclk", "fixed";
-			};
-
-			watchdog@20300 {
-				compatible = "marvell,armada-xp-wdt";
-				clocks = <&coreclk 2>, <&refclk>;
-				clock-names = "nbclk", "fixed";
-			};
-
-			cpurst@20800 {
-				compatible = "marvell,armada-370-cpu-reset";
-				reg = <0x20800 0x20>;
-			};
-
 			cpu-config@21000 {
 				compatible = "marvell,armada-xp-cpu-config";
 				reg = <0x21000 0x8>;
@@ -184,15 +156,7 @@
 				status = "disabled";
 			};
 
-			usb@50000 {
-				clocks = <&gateclk 18>;
-			};
-
-			usb@51000 {
-				clocks = <&gateclk 19>;
-			};
-
-			usb@52000 {
+			usb2: usb@52000 {
 				compatible = "marvell,orion-ehci";
 				reg = <0x52000 0x500>;
 				interrupts = <47>;
@@ -200,7 +164,7 @@
 				status = "disabled";
 			};
 
-			xor@60900 {
+			xor1: xor@60900 {
 				compatible = "marvell,orion-xor";
 				reg = <0x60900 0x100
 				       0x60b00 0x100>;
@@ -228,7 +192,7 @@
 				compatible = "marvell,armada-xp-neta";
 			};
 
-			crypto@90000 {
+			cesa: crypto@90000 {
 				compatible = "marvell,armada-xp-crypto";
 				reg = <0x90000 0x10000>;
 				reg-names = "regs";
@@ -248,7 +212,7 @@
 				status = "disabled";
 			};
 
-			xor@f0900 {
+			xor0: xor@f0900 {
 				compatible = "marvell,orion-xor";
 				reg = <0xF0900 0x100
 				       0xF0B00 0x100>;
@@ -309,6 +273,44 @@
 	};
 };
 
+&i2c0 {
+	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+	reg = <0x11000 0x100>;
+};
+
+&i2c1 {
+	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+	reg = <0x11100 0x100>;
+};
+
+&mpic {
+	reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+};
+
+&timer {
+	compatible = "marvell,armada-xp-timer";
+	clocks = <&coreclk 2>, <&refclk>;
+	clock-names = "nbclk", "fixed";
+};
+
+&watchdog {
+	compatible = "marvell,armada-xp-wdt";
+	clocks = <&coreclk 2>, <&refclk>;
+	clock-names = "nbclk", "fixed";
+};
+
+&cpurst {
+	reg = <0x20800 0x20>;
+};
+
+&usb0 {
+	clocks = <&gateclk 18>;
+};
+
+&usb1 {
+	clocks = <&gateclk 19>;
+};
+
 &pinctrl {
 	ge0_gmii_pins: ge0-gmii-pins {
 		marvell,pins =
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-gp.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-gp.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-gp.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-gp.dts	2017-02-12 16:03:20.000000000 -0500
@@ -68,7 +68,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		/*
                  * 8 GB of plug-in RAM modules by default.The amount
@@ -127,27 +127,6 @@
 			};
 		};
 
-		pcie-controller {
-			status = "okay";
-
-			/*
-			 * The 3 slots are physically present as
-			 * standard PCIe slots on the board.
-			 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-			pcie@9,0 {
-				/* Port 2, Lane 0 */
-				status = "okay";
-			};
-			pcie@10,0 {
-				/* Port 3, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			serial@12000 {
 				status = "okay";
@@ -175,24 +154,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 {
-					reg = <16>;
-				};
-
-				phy1: ethernet-phy@1 {
-					reg = <17>;
-				};
-
-				phy2: ethernet-phy@2 {
-					reg = <18>;
-				};
-
-				phy3: ethernet-phy@3 {
-					reg = <19>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				phy = <&phy0>;
@@ -251,6 +212,45 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/*
+	 * The 3 slots are physically present as
+	 * standard PCIe slots on the board.
+	 */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+	pcie@9,0 {
+		/* Port 2, Lane 0 */
+		status = "okay";
+	};
+	pcie@10,0 {
+		/* Port 3, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	phy0: ethernet-phy@0 {
+		reg = <16>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <17>;
+	};
+
+	phy2: ethernet-phy@2 {
+		reg = <18>;
+	};
+
+	phy3: ethernet-phy@3 {
+		reg = <19>;
+	};
+};
+
 &spi0 {
 	status = "okay";
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x00000000 0 0x20000000>; /* 512MB */
 	};
@@ -68,37 +68,11 @@
 			MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
 			MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* Quad port sata: Marvell 88SX7042 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* USB 3.0 xHCI controller: NEC D720200F1 */
-			pcie@5,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			serial@12000 {
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 { /* Marvell 88E1318 */
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 { /* Marvell 88E1318 */
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
 				pinctrl-0 = <&ge0_rgmii_pins>;
 				pinctrl-names = "default";
@@ -295,6 +269,31 @@
 		gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>;
 	};
 };
+&pciec {
+	status = "okay";
+
+	/* Quad port sata: Marvell 88SX7042 */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* USB 3.0 xHCI controller: NEC D720200F1 */
+	pcie@5,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	phy0: ethernet-phy@0 { /* Marvell 88E1318 */
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 { /* Marvell 88E1318 */
+		reg = <1>;
+	};
+};
 
 &pinctrl {
 	poweroff_pin: poweroff-pin {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-linksys-mamba.dts	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,7 @@
 		stdout-path = &uart0;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x00000000 0x00000000 0x10000000>; /* 256MB */
 	};
@@ -73,28 +73,6 @@
 			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
 			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* Etron EJ168 USB 3.0 controller */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* First mini-PCIe port */
-			pcie@2,0 {
-				/* Port 0, Lane 1 */
-				status = "okay";
-			};
-
-			/* Second mini-PCIe port */
-			pcie@3,0 {
-				/* Port 0, Lane 3 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 
 			rtc@10300 {
@@ -289,13 +267,13 @@
 		pinctrl-0 = <&keys_pin>;
 		pinctrl-names = "default";
 
-		button@1 {
+		wps {
 			label = "WPS";
 			linux,code = <KEY_WPS_BUTTON>;
 			gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
 		};
 
-		button@2 {
+		reset {
 			label = "Factory Reset Button";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
@@ -323,7 +301,7 @@
 				      4500 1>;
 	};
 
-	dsa@0 {
+	dsa {
 		compatible = "marvell,dsa";
 		#address-cells = <2>;
 		#size-cells = <0>;
@@ -369,6 +347,28 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/* Etron EJ168 USB 3.0 controller */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* First mini-PCIe port */
+	pcie@2,0 {
+		/* Port 0, Lane 1 */
+		status = "okay";
+	};
+
+	/* Second mini-PCIe port */
+	pcie@3,0 {
+		/* Port 0, Lane 3 */
+		status = "okay";
+	};
+};
+
 &pinctrl {
 
 	keys_pin: keys-pin {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-matrix.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-matrix.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-matrix.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-matrix.dts	2017-02-12 16:03:20.000000000 -0500
@@ -55,7 +55,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		/*
 		 * This board has 4 GB of RAM, but the last 256 MB of
@@ -99,18 +99,18 @@
 				};
 			};
 
-			pcie-controller {
-				status = "okay";
-
-				pcie@1,0 {
-					/* Port 0, Lane 0 */
-					status = "okay";
-				};
-			};
-
 			usb@50000 {
 				status = "okay";
 			};
 		};
 	};
 };
+
+&pciec {
+	status = "okay";
+
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-mv78230.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -86,7 +86,7 @@
 		 * configured as x4 or quad x1 lanes. One unit is
 		 * x1 only.
 		 */
-		pcie-controller {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,armada-xp-pcie";
 			status = "disabled";
 			device_type = "pci";
@@ -114,7 +114,7 @@
 				0x82000000 0x5 0       MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
 				0x81000000 0x5 0       MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */>;
 
-			pcie@1,0 {
+			pcie1: pcie@1,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
 				reg = <0x0800 0 0 0 0>;
@@ -131,7 +131,7 @@
 				status = "disabled";
 			};
 
-			pcie@2,0 {
+			pcie2: pcie@2,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
@@ -148,7 +148,7 @@
 				status = "disabled";
 			};
 
-			pcie@3,0 {
+			pcie3: pcie@3,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
@@ -165,7 +165,7 @@
 				status = "disabled";
 			};
 
-			pcie@4,0 {
+			pcie4: pcie@4,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
 				reg = <0x2000 0 0 0 0>;
@@ -182,7 +182,7 @@
 				status = "disabled";
 			};
 
-			pcie@5,0 {
+			pcie5: pcie@5,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
 				reg = <0x2800 0 0 0 0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-mv78260.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -87,7 +87,7 @@
 		 * configured as x4 or quad x1 lanes. One unit is
 		 * x4 only.
 		 */
-		pcie-controller {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,armada-xp-pcie";
 			status = "disabled";
 			device_type = "pci";
@@ -129,7 +129,7 @@
 				0x82000000 0x9 0     MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
 				0x81000000 0x9 0     MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
 
-			pcie@1,0 {
+			pcie1: pcie@1,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
 				reg = <0x0800 0 0 0 0>;
@@ -146,7 +146,7 @@
 				status = "disabled";
 			};
 
-			pcie@2,0 {
+			pcie2: pcie@2,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
@@ -163,7 +163,7 @@
 				status = "disabled";
 			};
 
-			pcie@3,0 {
+			pcie3: pcie@3,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
@@ -180,7 +180,7 @@
 				status = "disabled";
 			};
 
-			pcie@4,0 {
+			pcie4: pcie@4,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
 				reg = <0x2000 0 0 0 0>;
@@ -197,7 +197,7 @@
 				status = "disabled";
 			};
 
-			pcie@5,0 {
+			pcie5: pcie@5,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
 				reg = <0x2800 0 0 0 0>;
@@ -214,7 +214,7 @@
 				status = "disabled";
 			};
 
-			pcie@6,0 {
+			pcie6: pcie@6,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
 				reg = <0x3000 0 0 0 0>;
@@ -231,7 +231,7 @@
 				status = "disabled";
 			};
 
-			pcie@7,0 {
+			pcie7: pcie@7,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
 				reg = <0x3800 0 0 0 0>;
@@ -248,7 +248,7 @@
 				status = "disabled";
 			};
 
-			pcie@8,0 {
+			pcie8: pcie@8,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
 				reg = <0x4000 0 0 0 0>;
@@ -265,7 +265,7 @@
 				status = "disabled";
 			};
 
-			pcie@9,0 {
+			pcie9: pcie@9,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
 				reg = <0x4800 0 0 0 0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-mv78460.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@
 		 * configured as x4 or quad x1 lanes. Two units are
 		 * x4/x1.
 		 */
-		pcie-controller {
+		pciec: pcie-controller@82000000 {
 			compatible = "marvell,armada-xp-pcie";
 			status = "disabled";
 			device_type = "pci";
@@ -150,7 +150,7 @@
 				0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
 				0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
 
-			pcie@1,0 {
+			pcie1: pcie@1,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
 				reg = <0x0800 0 0 0 0>;
@@ -167,7 +167,7 @@
 				status = "disabled";
 			};
 
-			pcie@2,0 {
+			pcie2: pcie@2,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
@@ -184,7 +184,7 @@
 				status = "disabled";
 			};
 
-			pcie@3,0 {
+			pcie3: pcie@3,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
@@ -201,7 +201,7 @@
 				status = "disabled";
 			};
 
-			pcie@4,0 {
+			pcie4: pcie@4,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
 				reg = <0x2000 0 0 0 0>;
@@ -218,7 +218,7 @@
 				status = "disabled";
 			};
 
-			pcie@5,0 {
+			pcie5: pcie@5,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
 				reg = <0x2800 0 0 0 0>;
@@ -235,7 +235,7 @@
 				status = "disabled";
 			};
 
-			pcie@6,0 {
+			pcie6: pcie@6,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
 				reg = <0x3000 0 0 0 0>;
@@ -252,7 +252,7 @@
 				status = "disabled";
 			};
 
-			pcie@7,0 {
+			pcie7: pcie@7,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82003800 0 0x88000 0 0x2000>;
 				reg = <0x3800 0 0 0 0>;
@@ -269,7 +269,7 @@
 				status = "disabled";
 			};
 
-			pcie@8,0 {
+			pcie8: pcie@8,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>;
 				reg = <0x4000 0 0 0 0>;
@@ -286,7 +286,7 @@
 				status = "disabled";
 			};
 
-			pcie@9,0 {
+			pcie9: pcie@9,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82004800 0 0x42000 0 0x2000>;
 				reg = <0x4800 0 0 0 0>;
@@ -303,7 +303,7 @@
 				status = "disabled";
 			};
 
-			pcie@10,0 {
+			pcie10: pcie@10,0 {
 				device_type = "pci";
 				assigned-addresses = <0x82005000 0 0x82000 0 0x2000>;
 				reg = <0x5000 0 0 0 0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x00000000 0 0x80000000>; /* 2GB */
 	};
@@ -67,28 +67,6 @@
 			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
 			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/* Connected to first Marvell 88SE9170 SATA controller */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/* Connected to second Marvell 88SE9170 SATA controller */
-			pcie@2,0 {
-				/* Port 0, Lane 1 */
-				status = "okay";
-			};
-
-			/* Connected to Fresco Logic FL1009 USB 3.0 controller */
-			pcie@5,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 
 			/* RTC is provided by Intersil ISL12057 I2C RTC chip */
@@ -97,7 +75,6 @@
 			};
 
 			i2c@11000 {
-				compatible = "marvell,mv64xxx-i2c";
 				clock-frequency = <400000>;
 				status = "okay";
 
@@ -154,23 +131,19 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 { /* Marvell 88E1318 */
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 { /* Marvell 88E1318 */
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
+				pinctrl-0 = <&ge0_rgmii_pins>;
+				pinctrl-names = "default";
+
 				status = "okay";
 				phy = <&phy0>;
 				phy-mode = "rgmii-id";
 			};
 
 			ethernet@74000 {
+				pinctrl-0 = <&ge1_rgmii_pins>;
+				pinctrl-names = "default";
+
 				status = "okay";
 				phy = <&phy1>;
 				phy-mode = "rgmii-id";
@@ -295,6 +268,39 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/* Connected to first Marvell 88SE9170 SATA controller */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/* Connected to second Marvell 88SE9170 SATA controller */
+	pcie@2,0 {
+		/* Port 0, Lane 1 */
+		status = "okay";
+	};
+
+	/* Connected to Fresco Logic FL1009 USB 3.0 controller */
+	pcie@5,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	phy0: ethernet-phy@0 { /* Marvell 88E1318 */
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 { /* Marvell 88E1318 */
+		reg = <1>;
+	};
+};
+
+
 &pinctrl {
 	poweroff: poweroff {
 		marvell,pins = "mpp42";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-openblocks-ax3-4.dts	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x00000000 0 0x40000000>; /* 1 GB soldered on */
 	};
@@ -98,15 +98,6 @@
 			};
 		};
 
-		pcie-controller {
-			status = "okay";
-			/* Internal mini-PCIe connector */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 			rtc@10300 {
 				/* No crystal connected to the internal RTC */
@@ -148,31 +139,13 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 
-				button@1 {
+				init {
 					label = "Init Button";
 					linux,code = <KEY_POWER>;
 					gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
 				};
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 {
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 {
-					reg = <1>;
-				};
-
-				phy2: ethernet-phy@2 {
-					reg = <2>;
-				};
-
-				phy3: ethernet-phy@3 {
-					reg = <3>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				phy = <&phy0>;
@@ -240,6 +213,33 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+	/* Internal mini-PCIe connector */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+};
+
+&mdio {
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+
+	phy2: ethernet-phy@2 {
+		reg = <2>;
+	};
+
+	phy3: ethernet-phy@3 {
+		reg = <3>;
+	};
+};
+
 &pinctrl {
 	led_pins: led-pins-0 {
 		marvell,pins = "mpp49", "mpp51", "mpp53";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/armada-xp-synology-ds414.dts	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x00000000 0 0x40000000>; /* 1GB */
 	};
@@ -81,28 +81,6 @@
 			  MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
 			  MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
 
-		pcie-controller {
-			status = "okay";
-
-			/*
-			 * Connected to Marvell 88SX7042 SATA-II controller
-			 * handling the four disks.
-			 */
-			pcie@1,0 {
-				/* Port 0, Lane 0 */
-				status = "okay";
-			};
-
-			/*
-			 * Connected to EtronTech EJ168A XHCI controller
-			 * providing the two rear USB 3.0 ports.
-			 */
-			pcie@5,0 {
-				/* Port 1, Lane 0 */
-				status = "okay";
-			};
-		};
-
 		internal-regs {
 
 			/* RTC is provided by Seiko S-35390A below */
@@ -150,16 +128,6 @@
 				status = "okay";
 			};
 
-			mdio {
-				phy0: ethernet-phy@0 { /* Marvell 88E1512 */
-					reg = <0>;
-				};
-
-				phy1: ethernet-phy@1 { /* Marvell 88E1512 */
-					reg = <1>;
-				};
-			};
-
 			ethernet@70000 {
 				status = "okay";
 				pinctrl-0 = <&ge0_rgmii_pins>;
@@ -186,7 +154,7 @@
 			     &sata3_pwr_pin &sata4_pwr_pin>;
 		pinctrl-names = "default";
 
-		sata1_regulator: sata1-regulator {
+		sata1_regulator: sata1-regulator@1 {
 			compatible = "regulator-fixed";
 			reg = <1>;
 			regulator-name = "SATA1 Power";
@@ -199,7 +167,7 @@
 			gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
 		};
 
-		sata2_regulator: sata2-regulator {
+		sata2_regulator: sata2-regulator@2 {
 			compatible = "regulator-fixed";
 			reg = <2>;
 			regulator-name = "SATA2 Power";
@@ -212,7 +180,7 @@
 			gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
 		};
 
-		sata3_regulator: sata3-regulator {
+		sata3_regulator: sata3-regulator@3 {
 			compatible = "regulator-fixed";
 			reg = <3>;
 			regulator-name = "SATA3 Power";
@@ -225,7 +193,7 @@
 			gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
 		};
 
-		sata4_regulator: sata4-regulator {
+		sata4_regulator: sata4-regulator@4 {
 			compatible = "regulator-fixed";
 			reg = <4>;
 			regulator-name = "SATA4 Power";
@@ -240,6 +208,39 @@
 	};
 };
 
+&pciec {
+	status = "okay";
+
+	/*
+	 * Connected to Marvell 88SX7042 SATA-II controller
+	 * handling the four disks.
+	 */
+	pcie@1,0 {
+		/* Port 0, Lane 0 */
+		status = "okay";
+	};
+
+	/*
+	 * Connected to EtronTech EJ168A XHCI controller
+	 * providing the two rear USB 3.0 ports.
+	 */
+	pcie@5,0 {
+		/* Port 1, Lane 0 */
+		status = "okay";
+	};
+};
+
+
+&mdio {
+	phy0: ethernet-phy@0 { /* Marvell 88E1512 */
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 { /* Marvell 88E1512 */
+		reg = <1>;
+	};
+};
+
 &pinctrl {
 	sata1_pwr_pin: sata1-pwr-pin {
 		marvell,pins = "mpp42";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/artpec6-devboard.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/artpec6-devboard.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/artpec6-devboard.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/artpec6-devboard.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,6 +46,10 @@
 	status = "okay";
 };
 
+&pcie {
+	status = "okay";
+};
+
 &ethernet {
 	status = "okay";
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/artpec6.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/artpec6.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/artpec6.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/artpec6.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@
 		};
 	};
 
-	syscon {
+	syscon: syscon@f8000000 {
 		compatible = "axis,artpec6-syscon", "syscon";
 		reg = <0xf8000000 0x48>;
 	};
@@ -154,6 +154,33 @@
 		interrupt-parent = <&intc>;
 	};
 
+	pcie: pcie@f8050000 {
+		compatible = "axis,artpec6-pcie", "snps,dw-pcie";
+		reg = <0xf8050000 0x2000
+		       0xf8040000 0x1000
+		       0xc0000000 0x2000>;
+		reg-names = "dbi", "phy", "config";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+			  /* downstream I/O */
+		ranges = <0x81000000 0 0 0xc0002000 0 0x00010000
+			  /* non-prefetchable memory */
+			  0x82000000 0 0xc0012000 0xc0012000 0 0x1ffee000>;
+		num-lanes = <2>;
+		bus-range = <0x00 0xff>;
+		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "msi";
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0x7>;
+		interrupt-map = <0 0 0 1 &intc GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &intc GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &intc GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &intc GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+		axis,syscon-pcie = <&syscon>;
+		status = "disabled";
+	};
+
 	amba@0 {
 		compatible = "simple-bus";
 		#address-cells = <0x1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91rm9200.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91rm9200.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91rm9200.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91rm9200.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -481,8 +481,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOA 30 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA30 periph A */
-							 AT91_PIOA 31 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PA31 periph with pullup */
+							<AT91_PIOA 30 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
+							 AT91_PIOA 31 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9260.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9260.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9260.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9260.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -412,8 +412,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOB 14 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB14 periph A */
-							 AT91_PIOB 15 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PB15 periph with pullup */
+							<AT91_PIOB 14 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
+							 AT91_PIOB 15 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9260ek.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9260ek.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9260ek.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9260ek.dts	2017-02-12 16:03:20.000000000 -0500
@@ -174,14 +174,14 @@
 			label = "Button 3";
 			gpios = <&pioA 30 GPIO_ACTIVE_LOW>;
 			linux,code = <0x103>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 
 		btn4 {
 			label = "Button 4";
 			gpios = <&pioA 31 GPIO_ACTIVE_LOW>;
 			linux,code = <0x104>;
-			gpio-key,wakeup;
+			wakeup-source;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9261.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9261.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9261.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9261.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -302,8 +302,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOA 9  AT91_PERIPH_A AT91_PINCTRL_NONE>,
-							<AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
+							<AT91_PIOA 9  AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
+							<AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9263.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9263.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9263.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9263.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -412,8 +412,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOC 30 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PC30 periph A */
-							 AT91_PIOC 31 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PC31 periph with pullup */
+							<AT91_PIOC 30 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
+							 AT91_PIOC 31 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9g45.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9g45.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9g45.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -478,8 +478,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB12 periph A */
-							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE>;	/* PB13 periph A */
+							<AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
+							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9n12.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9n12.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9n12.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9n12.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -500,8 +500,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA9 periph A */
-							 AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PA10 periph with pullup */
+							<AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
+							 AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9rl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9rl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9rl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9rl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -438,8 +438,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_NONE>,
-							<AT91_PIOA 22 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
+							<AT91_PIOA 21 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
+							<AT91_PIOA 22 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9x5.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9x5.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91sam9x5.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91sam9x5.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -460,8 +460,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PA9 periph A */
-							 AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PA10 periph A with pullup */
+							<AT91_PIOA 9 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
+							 AT91_PIOA 10 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -12,8 +12,8 @@
 #include "sama5d4.dtsi"
 
 / {
-	model = "DENX MA5D4";
-	compatible = "denx,ma5d4", "atmel,sama5d4", "atmel,sama5";
+	model = "Aries/DENX MA5D4";
+	compatible = "aries,ma5d4", "denx,ma5d4", "atmel,sama5d4", "atmel,sama5";
 
 	memory {
 		reg = <0x20000000 0x10000000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/at91-sama5d4_ma5d4evk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -13,8 +13,8 @@
 #include "at91-sama5d4_ma5d4.dtsi"
 
 / {
-	model = "DENX MA5D4EVK";
-	compatible = "denx,ma5d4evk", "atmel,sama5d4", "atmel,sama5";
+	model = "Aries/DENX MA5D4EVK";
+	compatible = "aries,ma5d4evk", "denx,ma5d4evk", "atmel,sama5d4", "atmel,sama5";
 
 	chosen {
 		stdout-path = "serial3:115200n8";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -23,3 +23,9 @@
 		};
 	};
 };
+
+/* enable thermal sensor with the correct compatible property set */
+&thermal {
+	compatible = "brcm,bcm2835-thermal";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-a.dts	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,74 @@
 };
 
 &gpio {
-	pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>;
+	/*
+	 * Taken from Raspberry-Pi-Rev-1.0-Model-AB-Schematics.pdf
+	 * RPI00021 sheet 02
+	 *
+	 * Legend:
+	 * "NC" = not connected (no rail from the SoC)
+	 * "FOO" = GPIO line named "FOO" on the schematic
+	 * "FOO_N" = GPIO line named "FOO" on schematic, active low
+	 */
+	gpio-line-names = "SDA0",
+			  "SCL0",
+			  "SDA1",
+			  "SCL1",
+			  "GPIO_GCLK",
+			  "CAM_GPIO1",
+			  "LAN_RUN",
+			  "SPI_CE1_N",
+			  "SPI_CE0_N",
+			  "SPI_MISO",
+			  "SPI_MOSI",
+			  "SPI_SCLK",
+			  "NC", /* GPIO12 */
+			  "NC", /* GPIO13 */
+			  /* Serial port */
+			  "TXD0",
+			  "RXD0",
+			  "STATUS_LED_N",
+			  "GPIO17",
+			  "GPIO18",
+			  "NC", /* GPIO19 */
+			  "NC", /* GPIO20 */
+			  "GPIO21",
+			  "GPIO22",
+			  "GPIO23",
+			  "GPIO24",
+			  "GPIO25",
+			  "NC", /* GPIO26 */
+			  "CAM_GPIO0",
+			  /* Binary number representing build/revision */
+			  "CONFIG0",
+			  "CONFIG1",
+			  "CONFIG2",
+			  "CONFIG3",
+			  "NC", /* GPIO32 */
+			  "NC", /* GPIO33 */
+			  "NC", /* GPIO34 */
+			  "NC", /* GPIO35 */
+			  "NC", /* GPIO36 */
+			  "NC", /* GPIO37 */
+			  "NC", /* GPIO38 */
+			  "NC", /* GPIO39 */
+			  "PWM0_OUT",
+			  "NC", /* GPIO41 */
+			  "NC", /* GPIO42 */
+			  "NC", /* GPIO43 */
+			  "NC", /* GPIO44 */
+			  "PWM1_OUT",
+			  "HDMI_HPD_P",
+			  "SD_CARD_DET",
+			  /* Used by SD Card */
+			  "SD_CLK_R",
+			  "SD_CMD_R",
+			  "SD_DATA0_R",
+			  "SD_DATA1_R",
+			  "SD_DATA2_R",
+			  "SD_DATA3_R";
+
+	pinctrl-0 = <&gpioout &alt0 &i2s_alt2>;
 
 	/* I2S interface */
 	i2s_alt2: i2s_alt2 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,72 @@
 };
 
 &gpio {
-	pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>;
+	/*
+	 * This is based on the unreleased schematic for the Model A+.
+	 *
+	 * Legend:
+	 * "NC" = not connected (no rail from the SoC)
+	 * "FOO" = GPIO line named "FOO" on the schematic
+	 * "FOO_N" = GPIO line named "FOO" on schematic, active low
+	 */
+	gpio-line-names = "SDA0",
+			  "SCL0",
+			  "SDA1",
+			  "SCL1",
+			  "GPIO_GCLK",
+			  "GPIO5",
+			  "GPIO6",
+			  "SPI_CE1_N",
+			  "SPI_CE0_N",
+			  "SPI_MISO",
+			  "SPI_MOSI",
+			  "SPI_SCLK",
+			  "GPIO12",
+			  "GPIO13",
+			  /* Serial port */
+			  "TXD0",
+			  "RXD0",
+			  "GPIO16",
+			  "GPIO17",
+			  "GPIO18",
+			  "GPIO19",
+			  "GPIO20",
+			  "GPIO21",
+			  "GPIO22",
+			  "GPIO23",
+			  "GPIO24",
+			  "GPIO25",
+			  "GPIO26",
+			  "GPIO27",
+			  "SDA0",
+			  "SCL0",
+			  "NC", /* GPIO30 */
+			  "NC", /* GPIO31 */
+			  "CAM_GPIO1", /* GPIO32 */
+			  "NC", /* GPIO33 */
+			  "NC", /* GPIO34 */
+			  "PWR_LOW_N", /* GPIO35 */
+			  "NC", /* GPIO36 */
+			  "NC", /* GPIO37 */
+			  "USB_LIMIT", /* GPIO38 */
+			  "NC", /* GPIO39 */
+			  "PWM0_OUT", /* GPIO40 */
+			  "CAM_GPIO0", /* GPIO41 */
+			  "NC", /* GPIO42 */
+			  "NC", /* GPIO43 */
+			  "NC", /* GPIO44 */
+			  "PWM1_OUT", /* GPIO45 */
+			  "HDMI_HPD_N",
+			  "STATUS_LED",
+			  /* Used by SD Card */
+			  "SD_CLK_R",
+			  "SD_CMD_R",
+			  "SD_DATA0_R",
+			  "SD_DATA1_R",
+			  "SD_DATA2_R",
+			  "SD_DATA3_R";
+
+	pinctrl-0 = <&gpioout &alt0 &i2s_alt0>;
 
 	/* I2S interface */
 	i2s_alt0: i2s_alt0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-b.dts	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,74 @@
 };
 
 &gpio {
-	pinctrl-0 = <&gpioout &alt0 &alt3>;
+	/*
+	 * Taken from Raspberry-Pi-Rev-1.0-Model-AB-Schematics.pdf
+	 * RPI00021 sheet 02
+	 *
+	 * Legend:
+	 * "NC" = not connected (no rail from the SoC)
+	 * "FOO" = GPIO line named "FOO" on the schematic
+	 * "FOO_N" = GPIO line named "FOO" on schematic, active low
+	 */
+	gpio-line-names = "SDA0",
+			  "SCL0",
+			  "SDA1",
+			  "SCL1",
+			  "GPIO_GCLK",
+			  "CAM_GPIO1",
+			  "LAN_RUN",
+			  "SPI_CE1_N",
+			  "SPI_CE0_N",
+			  "SPI_MISO",
+			  "SPI_MOSI",
+			  "SPI_SCLK",
+			  "NC", /* GPIO12 */
+			  "NC", /* GPIO13 */
+			  /* Serial port */
+			  "TXD0",
+			  "RXD0",
+			  "STATUS_LED_N",
+			  "GPIO17",
+			  "GPIO18",
+			  "NC", /* GPIO19 */
+			  "NC", /* GPIO20 */
+			  "GPIO21",
+			  "GPIO22",
+			  "GPIO23",
+			  "GPIO24",
+			  "GPIO25",
+			  "NC", /* GPIO26 */
+			  "CAM_GPIO0",
+			  /* Binary number representing build/revision */
+			  "CONFIG0",
+			  "CONFIG1",
+			  "CONFIG2",
+			  "CONFIG3",
+			  "NC", /* GPIO32 */
+			  "NC", /* GPIO33 */
+			  "NC", /* GPIO34 */
+			  "NC", /* GPIO35 */
+			  "NC", /* GPIO36 */
+			  "NC", /* GPIO37 */
+			  "NC", /* GPIO38 */
+			  "NC", /* GPIO39 */
+			  "PWM0_OUT",
+			  "NC", /* GPIO41 */
+			  "NC", /* GPIO42 */
+			  "NC", /* GPIO43 */
+			  "NC", /* GPIO44 */
+			  "PWM1_OUT",
+			  "HDMI_HPD_P",
+			  "SD_CARD_DET",
+			  /* Used by SD Card */
+			  "SD_CLK_R",
+			  "SD_CMD_R",
+			  "SD_DATA0_R",
+			  "SD_DATA1_R",
+			  "SD_DATA2_R",
+			  "SD_DATA3_R";
+
+	pinctrl-0 = <&gpioout &alt0>;
 };
 
 &hdmi {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,73 @@
 };
 
 &gpio {
-	pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>;
+	/*
+	 * Taken from Raspberry-Pi-B-Plus-V1.2-Schematics.pdf
+	 * RPI-BPLUS sheet 1
+	 *
+	 * Legend:
+	 * "NC" = not connected (no rail from the SoC)
+	 * "FOO" = GPIO line named "FOO" on the schematic
+	 * "FOO_N" = GPIO line named "FOO" on schematic, active low
+	 */
+	gpio-line-names = "SDA0",
+			  "SCL0",
+			  "SDA1",
+			  "SCL1",
+			  "GPIO_GCLK",
+			  "GPIO5",
+			  "GPIO6",
+			  "SPI_CE1_N",
+			  "SPI_CE0_N",
+			  "SPI_MISO",
+			  "SPI_MOSI",
+			  "SPI_SCLK",
+			  "GPIO12",
+			  "GPIO13",
+			  /* Serial port */
+			  "TXD0",
+			  "RXD0",
+			  "GPIO16",
+			  "GPIO17",
+			  "GPIO18",
+			  "GPIO19",
+			  "GPIO20",
+			  "GPIO21",
+			  "GPIO22",
+			  "GPIO23",
+			  "GPIO24",
+			  "GPIO25",
+			  "GPIO26",
+			  "GPIO27",
+			  "SDA0",
+			  "SCL0",
+			  "NC", /* GPIO30 */
+			  "LAN_RUN", /* GPIO31 */
+			  "CAM_GPIO1", /* GPIO32 */
+			  "NC", /* GPIO33 */
+			  "NC", /* GPIO34 */
+			  "PWR_LOW_N", /* GPIO35 */
+			  "NC", /* GPIO36 */
+			  "NC", /* GPIO37 */
+			  "USB_LIMIT", /* GPIO38 */
+			  "NC", /* GPIO39 */
+			  "PWM0_OUT", /* GPIO40 */
+			  "CAM_GPIO0", /* GPIO41 */
+			  "NC", /* GPIO42 */
+			  "NC", /* GPIO43 */
+			  "ETHCLK", /* GPIO44 */
+			  "PWM1_OUT", /* GPIO45 */
+			  "HDMI_HPD_N",
+			  "STATUS_LED",
+			  /* Used by SD Card */
+			  "SD_CLK_R",
+			  "SD_CMD_R",
+			  "SD_DATA0_R",
+			  "SD_DATA1_R",
+			  "SD_DATA2_R",
+			  "SD_DATA3_R";
+
+	pinctrl-0 = <&gpioout &alt0 &i2s_alt0>;
 
 	/* I2S interface */
 	i2s_alt0: i2s_alt0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,73 @@
 };
 
 &gpio {
-	pinctrl-0 = <&gpioout &alt0 &i2s_alt2 &alt3>;
+	/*
+	 * Taken from Raspberry-Pi-Rev-2.0-Model-AB-Schematics.pdf
+	 * RPI00022 sheet 02
+	 *
+	 * Legend:
+	 * "NC" = not connected (no rail from the SoC)
+	 * "FOO" = GPIO line named "FOO" on the schematic
+	 * "FOO_N" = GPIO line named "FOO" on schematic, active low
+	 */
+	gpio-line-names = "SDA0",
+			  "SCL0",
+			  "SDA1",
+			  "SCL1",
+			  "GPIO_GCLK",
+			  "CAM_CLK",
+			  "LAN_RUN",
+			  "SPI_CE1_N",
+			  "SPI_CE0_N",
+			  "SPI_MISO",
+			  "SPI_MOSI",
+			  "SPI_SCLK",
+			  "NC", /* GPIO12 */
+			  "NC", /* GPIO13 */
+			  /* Serial port */
+			  "TXD0",
+			  "RXD0",
+			  "STATUS_LED_N",
+			  "GPIO17",
+			  "GPIO18",
+			  "NC", /* GPIO19 */
+			  "NC", /* GPIO20 */
+			  "CAM_GPIO",
+			  "GPIO22",
+			  "GPIO23",
+			  "GPIO24",
+			  "GPIO25",
+			  "NC", /* GPIO26 */
+			  "GPIO27",
+			  "GPIO28",
+			  "GPIO29",
+			  "GPIO30",
+			  "GPIO31",
+			  "NC", /* GPIO32 */
+			  "NC", /* GPIO33 */
+			  "NC", /* GPIO34 */
+			  "NC", /* GPIO35 */
+			  "NC", /* GPIO36 */
+			  "NC", /* GPIO37 */
+			  "NC", /* GPIO38 */
+			  "NC", /* GPIO39 */
+			  "PWM0_OUT",
+			  "NC", /* GPIO41 */
+			  "NC", /* GPIO42 */
+			  "NC", /* GPIO43 */
+			  "NC", /* GPIO44 */
+			  "PWM1_OUT",
+			  "HDMI_HPD_P",
+			  "SD_CARD_DET",
+			  /* Used by SD Card */
+			  "SD_CLK_R",
+			  "SD_CMD_R",
+			  "SD_DATA0_R",
+			  "SD_DATA1_R",
+			  "SD_DATA2_R",
+			  "SD_DATA3_R";
+
+	pinctrl-0 = <&gpioout &alt0 &i2s_alt2>;
 
 	/* I2S interface */
 	i2s_alt2: i2s_alt2 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -39,22 +39,21 @@
 	};
 
 	alt0: alt0 {
-		brcm,pins = <0 1 2 3 4 5 7 8 9 10 11 14 15 40 45>;
+		brcm,pins = <4 5 7 8 9 10 11 14 15>;
 		brcm,function = <BCM2835_FSEL_ALT0>;
 	};
-
-	alt3: alt3 {
-		brcm,pins = <48 49 50 51 52 53>;
-		brcm,function = <BCM2835_FSEL_ALT3>;
-	};
 };
 
 &i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_gpio0>;
 	status = "okay";
 	clock-frequency = <100000>;
 };
 
 &i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_gpio2>;
 	status = "okay";
 	clock-frequency = <100000>;
 };
@@ -64,11 +63,15 @@
 };
 
 &sdhci {
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_gpio48>;
 	status = "okay";
 	bus-width = <4>;
 };
 
 &pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-zero.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-zero.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2835-rpi-zero.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2835-rpi-zero.dts	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,72 @@
 };
 
 &gpio {
-	pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>;
+	/*
+	 * This is based on the official GPU firmware DT blob.
+	 *
+	 * Legend:
+	 * "NC" = not connected (no rail from the SoC)
+	 * "FOO" = GPIO line named "FOO" on the schematic
+	 * "FOO_N" = GPIO line named "FOO" on schematic, active low
+	 */
+	gpio-line-names = "SDA0",
+			  "SCL0",
+			  "SDA1",
+			  "SCL1",
+			  "GPIO_GCLK",
+			  "GPIO5",
+			  "GPIO6",
+			  "SPI_CE1_N",
+			  "SPI_CE0_N",
+			  "SPI_MISO",
+			  "SPI_MOSI",
+			  "SPI_SCLK",
+			  "GPIO12",
+			  "GPIO13",
+			  /* Serial port */
+			  "TXD0",
+			  "RXD0",
+			  "GPIO16",
+			  "GPIO17",
+			  "GPIO18",
+			  "GPIO19",
+			  "GPIO20",
+			  "GPIO21",
+			  "GPIO22",
+			  "GPIO23",
+			  "GPIO24",
+			  "GPIO25",
+			  "GPIO26",
+			  "GPIO27",
+			  "SDA0",
+			  "SCL0",
+			  "NC", /* GPIO30 */
+			  "NC", /* GPIO31 */
+			  "CAM_GPIO1", /* GPIO32 */
+			  "NC", /* GPIO33 */
+			  "NC", /* GPIO34 */
+			  "NC", /* GPIO35 */
+			  "NC", /* GPIO36 */
+			  "NC", /* GPIO37 */
+			  "NC", /* GPIO38 */
+			  "NC", /* GPIO39 */
+			  "NC", /* GPIO40 */
+			  "CAM_GPIO0", /* GPIO41 */
+			  "NC", /* GPIO42 */
+			  "NC", /* GPIO43 */
+			  "NC", /* GPIO44 */
+			  "NC", /* GPIO45 */
+			  "HDMI_HPD_N",
+			  "STATUS_LED_N",
+			  /* Used by SD Card */
+			  "SD_CLK_R",
+			  "SD_CMD_R",
+			  "SD_DATA0_R",
+			  "SD_DATA1_R",
+			  "SD_DATA2_R",
+			  "SD_DATA3_R";
+
+	pinctrl-0 = <&gpioout &alt0 &i2s_alt0>;
 
 	/* I2S interface */
 	i2s_alt0: i2s_alt0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2836.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2836.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2836.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2836.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -76,3 +76,9 @@
 	interrupt-parent = <&local_intc>;
 	interrupts = <8>;
 };
+
+/* enable thermal sensor with the correct compatible property set */
+&thermal {
+	compatible = "brcm,bcm2836-thermal";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm2836-rpi-2-b.dts	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 };
 
 &gpio {
-	pinctrl-0 = <&gpioout &alt0 &i2s_alt0 &alt3>;
+	pinctrl-0 = <&gpioout &alt0 &i2s_alt0>;
 
 	/* I2S interface */
 	i2s_alt0: i2s_alt0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm283x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm283x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm283x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm283x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@
 			reg = <0x7e104000 0x10>;
 		};
 
-		mailbox: mailbox@7e00b800 {
+		mailbox: mailbox@7e00b880 {
 			compatible = "brcm,bcm2835-mbox";
 			reg = <0x7e00b880 0x40>;
 			interrupts = <0 1>;
@@ -132,6 +132,209 @@
 
 			interrupt-controller;
 			#interrupt-cells = <2>;
+
+			/* Defines pin muxing groups according to
+			 * BCM2835-ARM-Peripherals.pdf page 102.
+			 *
+			 * While each pin can have its mux selected
+			 * for various functions individually, some
+			 * groups only make sense to switch to a
+			 * particular function together.
+			 */
+			dpi_gpio0: dpi_gpio0 {
+				brcm,pins = <0 1 2 3 4 5 6 7 8 9 10 11
+					     12 13 14 15 16 17 18 19
+					     20 21 22 23 24 25 26 27>;
+				brcm,function = <BCM2835_FSEL_ALT2>;
+			};
+			emmc_gpio22: emmc_gpio22 {
+				brcm,pins = <22 23 24 25 26 27>;
+				brcm,function = <BCM2835_FSEL_ALT3>;
+			};
+			emmc_gpio34: emmc_gpio34 {
+				brcm,pins = <34 35 36 37 38 39>;
+				brcm,function = <BCM2835_FSEL_ALT3>;
+				brcm,pull = <BCM2835_PUD_OFF
+					     BCM2835_PUD_UP
+					     BCM2835_PUD_UP
+					     BCM2835_PUD_UP
+					     BCM2835_PUD_UP
+					     BCM2835_PUD_UP>;
+			};
+			emmc_gpio48: emmc_gpio48 {
+				brcm,pins = <48 49 50 51 52 53>;
+				brcm,function = <BCM2835_FSEL_ALT3>;
+			};
+
+			gpclk0_gpio4: gpclk0_gpio4 {
+				brcm,pins = <4>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			gpclk1_gpio5: gpclk1_gpio5 {
+				brcm,pins = <5>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			gpclk1_gpio42: gpclk1_gpio42 {
+				brcm,pins = <42>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			gpclk1_gpio44: gpclk1_gpio44 {
+				brcm,pins = <44>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			gpclk2_gpio6: gpclk2_gpio6 {
+				brcm,pins = <6>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			gpclk2_gpio43: gpclk2_gpio43 {
+				brcm,pins = <43>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+
+			i2c0_gpio0: i2c0_gpio0 {
+				brcm,pins = <0 1>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			i2c0_gpio32: i2c0_gpio32 {
+				brcm,pins = <32 34>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			i2c0_gpio44: i2c0_gpio44 {
+				brcm,pins = <44 45>;
+				brcm,function = <BCM2835_FSEL_ALT1>;
+			};
+			i2c1_gpio2: i2c1_gpio2 {
+				brcm,pins = <2 3>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			i2c1_gpio44: i2c1_gpio44 {
+				brcm,pins = <44 45>;
+				brcm,function = <BCM2835_FSEL_ALT2>;
+			};
+			i2c_slave_gpio18: i2c_slave_gpio18 {
+				brcm,pins = <18 19 20 21>;
+				brcm,function = <BCM2835_FSEL_ALT3>;
+			};
+
+			jtag_gpio4: jtag_gpio4 {
+				brcm,pins = <4 5 6 12 13>;
+				brcm,function = <BCM2835_FSEL_ALT4>;
+			};
+			jtag_gpio22: jtag_gpio22 {
+				brcm,pins = <22 23 24 25 26 27>;
+				brcm,function = <BCM2835_FSEL_ALT4>;
+			};
+
+			pcm_gpio18: pcm_gpio18 {
+				brcm,pins = <18 19 20 21>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			pcm_gpio28: pcm_gpio28 {
+				brcm,pins = <28 29 30 31>;
+				brcm,function = <BCM2835_FSEL_ALT2>;
+			};
+
+			pwm0_gpio12: pwm0_gpio12 {
+				brcm,pins = <12>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			pwm0_gpio18: pwm0_gpio18 {
+				brcm,pins = <18>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
+			pwm0_gpio40: pwm0_gpio40 {
+				brcm,pins = <40>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			pwm1_gpio13: pwm1_gpio13 {
+				brcm,pins = <13>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			pwm1_gpio19: pwm1_gpio19 {
+				brcm,pins = <19>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
+			pwm1_gpio41: pwm1_gpio41 {
+				brcm,pins = <41>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			pwm1_gpio45: pwm1_gpio45 {
+				brcm,pins = <45>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+
+			sdhost_gpio48: sdhost_gpio48 {
+				brcm,pins = <48 49 50 51 52 53>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+
+			spi0_gpio7: spi0_gpio7 {
+				brcm,pins = <7 8 9 10 11>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			spi0_gpio35: spi0_gpio35 {
+				brcm,pins = <35 36 37 38 39>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			spi1_gpio16: spi1_gpio16 {
+				brcm,pins = <16 17 18 19 20 21>;
+				brcm,function = <BCM2835_FSEL_ALT4>;
+			};
+			spi2_gpio40: spi2_gpio40 {
+				brcm,pins = <40 41 42 43 44 45>;
+				brcm,function = <BCM2835_FSEL_ALT4>;
+			};
+
+			uart0_gpio14: uart0_gpio14 {
+				brcm,pins = <14 15>;
+				brcm,function = <BCM2835_FSEL_ALT0>;
+			};
+			/* Separate from the uart0_gpio14 group
+			 * because it conflicts with spi1_gpio16, and
+			 * people often run uart0 on the two pins
+			 * without flow contrl.
+			 */
+			uart0_ctsrts_gpio16: uart0_ctsrts_gpio16 {
+				brcm,pins = <16 17>;
+				brcm,function = <BCM2835_FSEL_ALT3>;
+			};
+			uart0_gpio30: uart0_gpio30 {
+				brcm,pins = <30 31>;
+				brcm,function = <BCM2835_FSEL_ALT3>;
+			};
+			uart0_ctsrts_gpio32: uart0_ctsrts_gpio32 {
+				brcm,pins = <32 33>;
+				brcm,function = <BCM2835_FSEL_ALT3>;
+			};
+
+			uart1_gpio14: uart1_gpio14 {
+				brcm,pins = <14 15>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
+			uart1_ctsrts_gpio16: uart1_ctsrts_gpio16 {
+				brcm,pins = <16 17>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
+			uart1_gpio32: uart1_gpio32 {
+				brcm,pins = <32 33>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
+			uart1_ctsrts_gpio30: uart1_ctsrts_gpio30 {
+				brcm,pins = <30 31>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
+			uart1_gpio36: uart1_gpio36 {
+				brcm,pins = <36 37 38 39>;
+				brcm,function = <BCM2835_FSEL_ALT2>;
+			};
+			uart1_gpio40: uart1_gpio40 {
+				brcm,pins = <40 41>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
+			uart1_ctsrts_gpio42: uart1_ctsrts_gpio42 {
+				brcm,pins = <42 43>;
+				brcm,function = <BCM2835_FSEL_ALT5>;
+			};
 		};
 
 		uart0: serial@7e201000 {
@@ -187,6 +390,13 @@
 			interrupts = <2 14>; /* pwa1 */
 		};
 
+		thermal: thermal@7e212000 {
+			compatible = "brcm,bcm2835-thermal";
+			reg = <0x7e212000 0x8>;
+			clocks = <&clocks BCM2835_CLOCK_TSENS>;
+			status = "disabled";
+		};
+
 		aux: aux@0x7e215000 {
 			compatible = "brcm,bcm2835-aux";
 			#clock-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 Luxul Inc.
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm4708.dtsi"
+
+/ {
+	compatible = "luxul,xap-1510v1", "brcm,bcm4708";
+	model = "Luxul XAP-1510 V1";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlycon";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		5ghz {
+			label = "bcm53xx:blue:5ghz";
+			gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		2ghz {
+			label = "bcm53xx:blue:2ghz";
+			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "none";
+		};
+
+		status {
+			label = "bcm53xx:green:status";
+			gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "timer";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&spi_nor {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "bcm4708.dtsi"
+#include "bcm47094.dtsi"
 #include "bcm5301x-nand-cs0-bch1.dtsi"
 
 / {
@@ -107,7 +107,6 @@
 
 &uart0 {
 	status = "okay";
-	clock-frequency = <125000000>;
 };
 
 &usb3 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+#include "bcm4708.dtsi"
+
+/ {
+	usb3_phy: usb3-phy {
+		compatible = "brcm,ns-bx-usb3-phy";
+	};
+};
+
+&uart0 {
+	clock-frequency = <125000000>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2016 Luxul Inc.
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm47094.dtsi"
+#include "bcm5301x-nand-cs0-bch4.dtsi"
+
+/ {
+	compatible = "luxul,xwr-3100v1", "brcm,bcm47094", "brcm,bcm4708";
+	model = "Luxul XWR-3100 V1";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlycon";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		power	{
+			label = "bcm53xx:green:power";
+			gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-on";
+		};
+
+		lan3	{
+			label = "bcm53xx:green:lan1";
+			gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		lan4	{
+			label = "bcm53xx:green:lan0";
+			gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		wan	{
+			label = "bcm53xx:green:wan";
+			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		lan1	{
+			label = "bcm53xx:green:lan3";
+			gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		lan2	{
+			label = "bcm53xx:green:lan2";
+			gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		usb3	{
+			label = "bcm53xx:green:usb3";
+			gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		status	{
+			label = "bcm53xx:green:status";
+			gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "timer";
+		};
+
+		2ghz {
+			label = "bcm53xx:green:2ghz";
+			gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		5ghz {
+			label = "bcm53xx:green:5ghz";
+			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&usb3 {
+	vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
+};
+
+&spi_nor {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094-netgear-r8500.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47094-netgear-r8500.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47094-netgear-r8500.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm47094.dtsi"
+#include "bcm5301x-nand-cs0-bch8.dtsi"
+
+/ {
+	compatible = "netgear,r8500", "brcm,bcm47094", "brcm,bcm4708";
+	model = "Netgear R8500";
+
+	chosen {
+		bootargs = "console=ttyS0,115200";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		power0 {
+			label = "bcm53xx:white:power";
+			gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-on";
+		};
+
+		power1 {
+			label = "bcm53xx:amber:power";
+			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		5ghz-1 {
+			label = "bcm53xx:white:5ghz-1";
+			gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		5ghz-2 {
+			label = "bcm53xx:white:5ghz-2";
+			gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		2ghz {
+			label = "bcm53xx:white:2ghz";
+			gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		usb2 {
+			label = "bcm53xx:white:usb2";
+			gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+
+		usb3 {
+			label = "bcm53xx:white:usb3";
+			gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-off";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		brightness {
+			label = "Backlight";
+			linux,code = <KEY_BRIGHTNESS_ZERO>;
+			gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
+		};
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
+		};
+
+		wps {
+			label = "WPS";
+			linux,code = <KEY_WPS_BUTTON>;
+			gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+		};
+
+		rfkill {
+			label = "WiFi";
+			linux,code = <KEY_RFKILL>;
+			gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "bcm4708.dtsi"
+#include "bcm4709.dtsi"
 #include "bcm5301x-nand-cs0-bch8.dtsi"
 
 / {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "bcm4708.dtsi"
+#include "bcm4709.dtsi"
 #include "bcm5301x-nand-cs0-bch8.dtsi"
 
 / {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,11 @@
+/*
+ * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+#include "bcm4708.dtsi"
+
+&uart0 {
+	clock-frequency = <125000000>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-netgear-r7000.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-netgear-r7000.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-netgear-r7000.dts	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "bcm4708.dtsi"
+#include "bcm4709.dtsi"
 #include "bcm5301x-nand-cs0-bch8.dtsi"
 
 / {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-netgear-r8000.dts	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 
 /dts-v1/;
 
-#include "bcm4708.dtsi"
+#include "bcm4709.dtsi"
 #include "bcm5301x-nand-cs0-bch8.dtsi"
 
 / {
@@ -107,6 +107,10 @@
 	};
 };
 
+&uart0 {
+	status = "okay";
+};
+
 &usb2 {
 	vcc-gpio = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm4709.dtsi"
+
+/ {
+	compatible = "tplink,archer-c9-v1", "brcm,bcm4709", "brcm,bcm4708";
+	model = "TP-LINK Archer C9 V1";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlycon";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		lan {
+			label = "bcm53xx:blue:lan";
+			gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		wps {
+			label = "bcm53xx:blue:wps";
+			gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		2ghz {
+			label = "bcm53xx:blue:2ghz";
+			gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		5ghz {
+			label = "bcm53xx:blue:5ghz";
+			gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		usb3 {
+			label = "bcm53xx:blue:usb3";
+			gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		usb2 {
+			label = "bcm53xx:blue:usb2";
+			gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		wan-blue {
+			label = "bcm53xx:blue:wan";
+			gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		wan-amber {
+			label = "bcm53xx:amber:wan";
+			gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		power {
+			label = "bcm53xx:blue:power";
+			gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "default-on";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		wps {
+			label = "WPS";
+			linux,code = <KEY_WPS_BUTTON>;
+			gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+		};
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&usb2 {
+	vcc-gpio = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
+};
+
+&usb3 {
+	vcc-gpio = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
+};
+
+&spi_nor {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47189-tenda-ac9.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47189-tenda-ac9.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm47189-tenda-ac9.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm47189-tenda-ac9.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm53573.dtsi"
+
+/ {
+	compatible = "tenda,ac9", "brcm,bcm47189", "brcm,bcm53573";
+	model = "Tenda AC9";
+
+	chosen {
+		bootargs = "console=ttyS0,115200 earlycon";
+	};
+
+	memory {
+		reg = <0x00000000 0x08000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		usb {
+			label = "bcm53xx:blue:usb";
+			gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		wps {
+			label = "bcm53xx:blue:wps";
+			gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		5ghz {
+			label = "bcm53xx:blue:5ghz";
+			gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-off";
+		};
+
+		system {
+			label = "bcm53xx:blue:system";
+			gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "timer";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		rfkill {
+			label = "WiFi";
+			linux,code = <KEY_RFKILL>;
+			gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+		};
+
+		restart {
+			label = "Reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
+		};
+
+		wps {
+			label = "WPS";
+			linux,code = <KEY_WPS_BUTTON>;
+			gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm5301x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm5301x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm5301x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm5301x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -149,6 +149,13 @@
 		clock-names = "phy-ref-clk";
 	};
 
+	usb3_phy: usb3-phy {
+		compatible = "brcm,ns-ax-usb3-phy";
+		reg = <0x18105000 0x1000>, <0x18003000 0x1000>;
+		reg-names = "dmp", "ccb-mii";
+		#phy-cells = <0>;
+	};
+
 	axi@18000000 {
 		compatible = "brcm,bus-axi";
 		reg = <0x18000000 0x1000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2016 Luxul Inc.
+ *
+ * Licensed under the ISC license.
+ */
+
+#include "bcm5301x-nand-cs0.dtsi"
+
+&nandcs {
+	nand-ecc-algo = "bch";
+	nand-ecc-strength = <4>;
+	nand-ecc-step-size = <512>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm53573.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm53573.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm53573.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm53573.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "skeleton.dtsi"
+
+/ {
+	interrupt-parent = <&gic>;
+
+	chosen {
+		stdout-path = &uart0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+		};
+	};
+
+	mpcore {
+		compatible = "simple-bus";
+		ranges = <0x00000000 0x18310000 0x00008000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		gic: interrupt-controller@1000 {
+			compatible = "arm,cortex-a7-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0x1000 0x1000>,
+			      <0x2000 0x0100>;
+		};
+	};
+
+	clocks {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		alp: oscillator {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <40000000>;
+		};
+	};
+
+	axi@18000000 {
+		compatible = "brcm,bus-axi";
+		reg = <0x18000000 0x1000>;
+		ranges = <0x00000000 0x18000000 0x00100000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0x000fffff 0xffff>;
+		interrupt-map =
+			/* ChipCommon */
+			<0x00000000 0 &gic GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+
+			/* IEEE 802.11 0 */
+			<0x00001000 0 &gic GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+
+			/* PCIe Controller 0 */
+			<0x00002000 0 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			<0x00002000 1 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			<0x00002000 2 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			<0x00002000 3 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			<0x00002000 4 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			<0x00002000 5 &gic GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+
+			/* USB 2.0 Controller */
+			<0x00004000 0 &gic GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+
+			/* Ethernet Controller 0 */
+			<0x00005000 0 &gic GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+
+			/* IEEE 802.11 1 */
+			<0x0000a000 0 &gic GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+
+			/* Ethernet Controller 1 */
+			<0x0000b000 0 &gic GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+
+		chipcommon: chipcommon@0 {
+			compatible = "simple-bus";
+			reg = <0x00000000 0x1000>;
+			ranges;
+
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			uart0: serial@0300 {
+				compatible = "ns16550a";
+				reg = <0x0300 0x100>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_PPI 16 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&alp>;
+				status = "okay";
+			};
+		};
+
+		usb2: usb2@4000 {
+			reg = <0x4000 0x1000>;
+			ranges;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			ehci: ehci@4000 {
+				compatible = "generic-ehci";
+				reg = <0x4000 0x1000>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			ohci: ohci@d000 {
+				#usb-cells = <0>;
+
+				compatible = "generic-ohci";
+				reg = <0xd000 0x1000>;
+				interrupt-parent = <&gic>;
+				interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			};
+		};
+
+		gmac0: ethernet@5000 {
+			reg = <0x5000 0x1000>;
+		};
+
+		gmac1: ethernet@b000 {
+			reg = <0xb000 0x1000>;
+		};
+
+		pmu@12000 {
+			compatible = "simple-mfd", "syscon";
+			reg = <0x00012000 0x00001000>;
+
+			ilp: ilp {
+				compatible = "brcm,bcm53573-ilp";
+				clocks = <&alp>;
+				#clock-cells = <0>;
+				clock-output-names = "ilp";
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm958625k.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm958625k.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm958625k.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm958625k.dts	2017-02-12 16:03:20.000000000 -0500
@@ -139,3 +139,37 @@
 		groups = "nand_grp";
 	};
 };
+
+&qspi {
+	bspi-sel = <0>;
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "m25p80";
+		reg = <0x0>;
+		spi-max-frequency = <12500000>;
+		m25p,fast-read;
+		spi-cpol;
+		spi-cpha;
+
+		partition@0 {
+			label = "boot";
+			reg = <0x00000000 0x000a0000>;
+		};
+
+		partition@a0000 {
+			label = "env";
+			reg = <0x000a0000 0x00060000>;
+		};
+
+		partition@100000 {
+			label = "system";
+			reg = <0x00100000 0x00600000>;
+		};
+
+		partition@700000 {
+			label = "rootfs";
+			reg = <0x00700000 0x01900000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm-cygnus.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -91,6 +91,13 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
+		otp: otp@0301c800 {
+			compatible = "brcm,ocotp";
+			reg = <0x0301c800 0x2c>;
+			brcm,ocotp-size = <2048>;
+			status = "disabled";
+		};
+
 		pcie_phy: phy@0301d0a0 {
 			compatible = "brcm,cygnus-pcie-phy";
 			reg = <0x0301d0a0 0x14>;
@@ -108,12 +115,21 @@
 			};
 		};
 
-		pinctrl: pinctrl@0x0301d0c8 {
+		pinctrl: pinctrl@0301d0c8 {
 			compatible = "brcm,cygnus-pinmux";
 			reg = <0x0301d0c8 0x30>,
 			      <0x0301d24c 0x2c>;
 		};
 
+		mailbox: mailbox@03024024 {
+			compatible = "brcm,iproc-mailbox";
+			reg = <0x03024024 0x40>;
+			interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+			#interrupt-cells = <1>;
+			interrupt-controller;
+			#mbox-cells = <1>;
+		};
+
 		gpio_crmu: gpio@03024800 {
 			compatible = "brcm,cygnus-crmu-gpio";
 			reg = <0x03024800 0x50>,
@@ -121,6 +137,9 @@
 			ngpios = <6>;
 			#gpio-cells = <2>;
 			gpio-controller;
+			interrupt-controller;
+			interrupt-parent = <&mailbox>;
+			interrupts = <0>;
 		};
 
 		i2c0: i2c@18008000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/bcm-nsp.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm-nsp.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/bcm-nsp.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/bcm-nsp.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -160,7 +160,7 @@
 
 	axi {
 		compatible = "simple-bus";
-		ranges = <0x00000000 0x18000000 0x0011ba08>;
+		ranges = <0x00000000 0x18000000 0x0011c40c>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 
@@ -241,6 +241,16 @@
 			brcm,nand-has-wp;
 		};
 
+		gpiob: gpio@30000 {
+			compatible = "brcm,iproc-nsp-gpio", "brcm,iproc-gpio";
+			reg = <0x30000 0x50>;
+			#gpio-cells = <2>;
+			gpio-controller;
+			ngpios = <4>;
+			interrupt-controller;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
 		pwm: pwm@31000 {
 			compatible = "brcm,iproc-pwm";
 			reg = <0x31000 0x28>;
@@ -254,6 +264,35 @@
 			reg = <0x33000 0x14>;
 		};
 
+		qspi: qspi@27200 {
+			compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+			reg = <0x027200 0x184>,
+			      <0x027000 0x124>,
+			      <0x11c408 0x004>,
+			      <0x0273a0 0x01c>;
+			reg-names = "mspi", "bspi", "intr_regs",
+				    "intr_status_reg";
+			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "spi_lr_fullness_reached",
+					  "spi_lr_session_aborted",
+					  "spi_lr_impatient",
+					  "spi_lr_session_done",
+					  "spi_lr_overhead",
+					  "mspi_done",
+					  "mspi_halted";
+			clocks = <&iprocmed>;
+			clock-names = "iprocmed";
+			num-cs = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
 		ccbtimer0: timer@34000 {
 			compatible = "arm,sp804";
 			reg = <0x34000 0x1000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/berlin2q-marvell-dmp.dts	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 		reg = <0x00000000 0x80000000>;
 	};
 
-	choosen {
+	chosen {
 		bootargs = "earlyprintk";
 		stdout-path = "serial0:115200n8";
 	};
@@ -58,7 +58,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		reg_usb0_vbus: regulator@0 {
+		reg_usb0_vbus: regulator_usb0 {
 			compatible = "regulator-fixed";
 			regulator-name = "usb0_vbus";
 			regulator-min-microvolt = <5000000>;
@@ -67,7 +67,7 @@
 			enable-active-high;
 		};
 
-		reg_usb1_vbus: regulator@1 {
+		reg_usb1_vbus: regulator_usb1 {
 			compatible = "regulator-fixed";
 			regulator-name = "usb1_vbus";
 			regulator-min-microvolt = <5000000>;
@@ -76,7 +76,7 @@
 			enable-active-high;
 		};
 
-		reg_usb2_vbus: regulator@2 {
+		reg_usb2_vbus: regulator_usb2 {
 			compatible = "regulator-fixed";
 			regulator-name = "usb2_vbus";
 			regulator-min-microvolt = <5000000>;
@@ -85,7 +85,7 @@
 			enable-active-high;
 		};
 
-		reg_sdio1_vmmc: regulator@3 {
+		reg_sdio1_vmmc: regulator_sdio1_vmmc {
 			compatible = "regulator-fixed";
 			regulator-min-microvolt = <3300000>;
 			regulator-max-microvolt = <3300000>;
@@ -95,7 +95,7 @@
 			gpio = <&portb 21 GPIO_ACTIVE_HIGH>;
 		};
 
-		reg_sdio1_vqmmc: regulator@4 {
+		reg_sdio1_vqmmc: regulator_sido1_vqmmc {
 			compatible = "regulator-gpio";
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <3300000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/cloudengines-pogoplug-series-3.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,94 @@
+/*
+ * cloudengines-pogoplug-series-3.dtsi - Device tree file for Cloud Engines PogoPlug Series 3
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+#include "ox820.dtsi"
+
+/ {
+	model = "Cloud Engines PogoPlug Series 3";
+
+	compatible = "cloudengines,pogoplugv3", "oxsemi,ox820";
+
+	chosen {
+		bootargs = "earlyprintk";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		/* 128Mbytes DDR */
+		reg = <0x60000000 0x8000000>;
+	};
+
+	aliases {
+		serial0 = &uart0;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		blue {
+			label = "pogoplug:blue";
+			gpios = <&gpio0 2 0>;
+			default-state = "keep";
+		};
+
+		orange {
+			label = "pogoplug:orange";
+			gpios = <&gpio1 16 1>;
+			default-state = "keep";
+		};
+
+		green {
+			label = "pogoplug:green";
+			gpios = <&gpio1 17 1>;
+			default-state = "keep";
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0>;
+};
+
+&nandc {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nand>;
+
+	nand@0 {
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		nand-ecc-mode = "soft";
+		nand-ecc-algo = "hamming";
+
+		partition@0 {
+			label = "boot";
+			reg = <0x00000000 0x00e00000>;
+			read-only;
+		};
+
+		partition@e00000 {
+			label = "ubi";
+			reg = <0x00e00000 0x07200000>;
+		};
+	};
+};
+
+&etha {
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_etha_mdio>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/da850.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/da850.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/da850.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/da850.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,7 @@
 			reg = <0x14120 0x50>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#pinctrl-cells = <2>;
 			pinctrl-single,bit-per-mux;
 			pinctrl-single,register-width = <32>;
 			pinctrl-single,function-mask = <0xf>;
@@ -186,7 +187,43 @@
 					0xc 0x88888888 0xffffffff
 				>;
 			};
+			lcd_pins: pinmux_lcd_pins {
+				pinctrl-single,bits = <
+					/*
+					 * LCD_D[2], LCD_D[3], LCD_D[4], LCD_D[5],
+					 * LCD_D[6], LCD_D[7]
+					 */
+					0x40 0x22222200 0xffffff00
+					/*
+					 * LCD_D[10], LCD_D[11], LCD_D[12], LCD_D[13],
+					 * LCD_D[14], LCD_D[15], LCD_D[0], LCD_D[1]
+					 */
+					0x44 0x22222222 0xffffffff
+					/* LCD_D[8], LCD_D[9] */
+					0x48 0x00000022 0x000000ff
 
+					/* LCD_PCLK */
+					0x48 0x02000000 0x0f000000
+					/* LCD_AC_ENB_CS, LCD_VSYNC, LCD_HSYNC */
+					0x4c 0x02000022 0x0f0000ff
+				>;
+			};
+
+		};
+		prictrl: priority-controller@14110 {
+			compatible = "ti,da850-mstpri";
+			reg = <0x14110 0x0c>;
+			status = "disabled";
+		};
+		cfgchip: chip-controller@1417c {
+			compatible = "ti,da830-cfgchip", "syscon", "simple-mfd";
+			reg = <0x1417c 0x14>;
+
+			usb_phy: usb-phy {
+				compatible = "ti,da830-usb-phy";
+				#phy-cells = <1>;
+				status = "disabled";
+			};
 		};
 		edma0: edma@0 {
 			compatible = "ti,edma3-tpcc";
@@ -280,6 +317,8 @@
 		mmc0: mmc@40000 {
 			compatible = "ti,da830-mmc";
 			reg = <0x40000 0x1000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
 			interrupts = <16>;
 			dmas = <&edma0 16 0>, <&edma0 17 0>;
 			dma-names = "rx", "tx";
@@ -288,6 +327,8 @@
 		mmc1: mmc@21b000 {
 			compatible = "ti,da830-mmc";
 			reg = <0x21b000 0x1000>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
 			interrupts = <72>;
 			dmas = <&edma1 28 0>, <&edma1 29 0>;
 			dma-names = "rx", "tx";
@@ -336,6 +377,8 @@
 			num-cs = <6>;
 			ti,davinci-spi-intr-line = <1>;
 			interrupts = <20>;
+			dmas = <&edma0 14 0>, <&edma0 15 0>;
+			dma-names = "rx", "tx";
 			status = "disabled";
 		};
 		spi1: spi@30e000 {
@@ -350,6 +393,16 @@
 			dma-names = "rx", "tx";
 			status = "disabled";
 		};
+		usb0: usb@200000 {
+			compatible = "ti,da830-musb";
+			reg = <0x200000 0x10000>;
+			interrupts = <58>;
+			interrupt-names = "mc";
+			dr_mode = "otg";
+			phys = <&usb_phy 0>;
+			phy-names = "usb-phy";
+			status = "disabled";
+		};
 		mdio: mdio@224000 {
 			compatible = "ti,davinci_mdio";
 			#address-cells = <1>;
@@ -386,6 +439,11 @@
 			ti,davinci-gpio-unbanked = <0>;
 			status = "disabled";
 		};
+		pinconf: pin-controller@22c00c {
+			compatible = "ti,da850-pupd";
+			reg = <0x22c00c 0x8>;
+			status = "disabled";
+		};
 
 		mcasp0: mcasp@100000 {
 			compatible = "ti,da830-mcasp-audio";
@@ -399,6 +457,13 @@
 				<&edma0 0 1>;
 			dma-names = "tx", "rx";
 		};
+
+		display: display@213000 {
+			compatible = "ti,da850-tilcdc";
+			reg = <0x213000 0x1000>;
+			interrupts = <52>;
+			status = "disabled";
+		};
 	};
 	aemif: aemif@68000000 {
 		compatible = "ti,da850-aemif";
@@ -410,4 +475,9 @@
 			  1 0 0x68000000 0x00008000>;
 		status = "disabled";
 	};
+	memctrl: memory-controller@b0000000 {
+		compatible = "ti,da850-ddr-controller";
+		reg = <0xb0000000 0xe8>;
+		status = "disabled";
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/da850-evm.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/da850-evm.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/da850-evm.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/da850-evm.dts	2017-02-12 16:03:20.000000000 -0500
@@ -99,6 +99,7 @@
 				#size-cells = <1>;
 				compatible = "m25p64";
 				spi-max-frequency = <30000000>;
+				m25p,fast-read;
 				reg = <0>;
 				partition@0 {
 					label = "U-Boot-SPL";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/da850-lcdk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/da850-lcdk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/da850-lcdk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/da850-lcdk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@
 
 	aliases {
 		serial2 = &serial2;
+		ethernet0 = &eth0;
 	};
 
 	chosen {
@@ -122,7 +123,7 @@
 	bus-width = <4>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins>;
-	cd-gpios = <&gpio 64 GPIO_ACTIVE_HIGH>;
+	cd-gpios = <&gpio 64 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
 
@@ -158,6 +159,14 @@
 	rx-num-evt = <32>;
 };
 
+&usb_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
 &aemif {
 	pinctrl-names = "default";
 	pinctrl-0 = <&nand_pins>;
@@ -219,3 +228,11 @@
 		};
 	};
 };
+
+&prictrl {
+	status = "okay";
+};
+
+&memctrl {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dm814x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dm814x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dm814x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dm814x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@
 	interrupt-parent = <&intc>;
 	#address-cells = <1>;
 	#size-cells = <1>;
+	chosen { };
 
 	aliases {
 		i2c0 = &i2c1;
@@ -373,6 +374,7 @@
 					reg = <0x800 0x438>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					pinctrl-single,register-width = <32>;
 					pinctrl-single,function-mask = <0x307ff>;
 				};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dm816x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dm816x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dm816x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dm816x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@
 	interrupt-parent = <&intc>;
 	#address-cells = <1>;
 	#size-cells = <1>;
+	chosen { };
 
 	aliases {
 		i2c0 = &i2c1;
@@ -83,6 +84,7 @@
 			reg = <0x48140000 0x21000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#pinctrl-cells = <1>;
 			ranges = <0 0x48140000 0x21000>;
 
 			dm816x_pinmux: pinmux@800 {
@@ -90,6 +92,7 @@
 				reg = <0x800 0x50a>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				#pinctrl-cells = <1>;
 				pinctrl-single,register-width = <16>;
 				pinctrl-single,function-mask = <0xf>;
 			};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dra71-evm.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra71-evm.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dra71-evm.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra71-evm.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include "dra72-evm-common.dtsi"
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+	compatible = "ti,dra718-evm", "ti,dra718", "ti,dra722", "ti,dra72", "ti,dra7";
+	model = "TI DRA718 EVM";
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x0 0x80000000>; /* 2GB */
+	};
+
+	vpo_sd_1v8_3v3: gpio-regulator-TPS74801 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "vddshv8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3000000>;
+		regulator-boot-on;
+		vin-supply = <&evm_5v0>;
+
+		gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0
+			  3000000 0x1>;
+	};
+
+	poweroff: gpio-poweroff {
+		compatible = "gpio-poweroff";
+		gpios = <&gpio7 30 GPIO_ACTIVE_HIGH>;
+		input;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	lp8733: lp8733@60 {
+		compatible = "ti,lp8733";
+		reg = <0x60>;
+
+		buck0-in-supply =<&vsys_3v3>;
+		buck1-in-supply =<&vsys_3v3>;
+		ldo0-in-supply =<&evm_5v0>;
+		ldo1-in-supply =<&evm_5v0>;
+
+		lp8733_regulators: regulators {
+			lp8733_buck0_reg: buck0 {
+				/* FB_B0 -> LP8733-BUCK1 - VPO_S1_AVS - VDD_CORE_AVS (core, mpu, gpu) */
+				regulator-name = "lp8733-buck0";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			lp8733_buck1_reg: buck1 {
+				/* FB_B1 -> LP8733-BUCK2 - VPO_S2_AVS - VDD_DSP_AVS (DSP/eve/iva) */
+				regulator-name = "lp8733-buck1";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			lp8733_ldo0_reg: ldo0 {
+				/* LDO0 -> LP8733-LDO1 - VPO_L1_3V3 - VDDSHV8 (optional) */
+				regulator-name = "lp8733-ldo0";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			lp8733_ldo1_reg: ldo1 {
+				/* LDO1 -> LP8733-LDO2 - VPO_L2_3V3 - VDDA_USB3V3 */
+				regulator-name = "lp8733-ldo1";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+		};
+	};
+
+	lp8732: lp8732@61 {
+		compatible = "ti,lp8732";
+		reg = <0x61>;
+
+		buck0-in-supply =<&vsys_3v3>;
+		buck1-in-supply =<&vsys_3v3>;
+		ldo0-in-supply =<&vsys_3v3>;
+		ldo1-in-supply =<&vsys_3v3>;
+
+		lp8732_regulators: regulators {
+			lp8732_buck0_reg: buck0 {
+				/* FB_B0 -> LP8732-BUCK1 - VPO_S3_1V8 - VDDS_1V8 */
+				regulator-name = "lp8732-buck0";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			lp8732_buck1_reg: buck1 {
+				/* FB_B1 -> LP8732-BUCK2 - VPO_S4_DDR - VDD_DDR_1V35 */
+				regulator-name = "lp8732-buck1";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			lp8732_ldo0_reg: ldo0 {
+				/* LDO0 -> LP8732-LDO1 - VPO_L3_1V8 - VDA_1V8_PLL */
+				regulator-name = "lp8732-ldo0";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			lp8732_ldo1_reg: ldo1 {
+				/* LDO1 -> LP8732-LDO2 - VPO_L4_1V8 - VDA_1V8_PHY */
+				regulator-name = "lp8732-ldo1";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+		};
+	};
+};
+
+&pcf_gpio_21 {
+	interrupt-parent = <&gpio7>;
+	interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
+};
+
+&pcf_hdmi {
+	p0 {
+		/*
+		 * PM_OEn to High: Disable routing I2C3 to PM_I2C
+		 * With this PM_SEL(p3) should not matter
+		 */
+		gpio-hog;
+		gpios = <0 GPIO_ACTIVE_LOW>;
+		output-high;
+		line-name = "pm_oe_n";
+	};
+};
+
+&mmc1 {
+	vmmc_aux-supply = <&vpo_sd_1v8_3v3>;
+};
+
+&mac {
+	mode-gpios = <&pcf_gpio_21 4 GPIO_ACTIVE_LOW>,
+		     <&pcf_hdmi 9 GPIO_ACTIVE_LOW>,	/* P11 */
+		     <&pcf_hdmi 10 GPIO_ACTIVE_LOW>;	/* P12 */
+	dual_emac;
+};
+
+&cpsw_emac0 {
+	phy_id = <&davinci_mdio>, <2>;
+	phy-mode = "rgmii-id";
+	dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+	phy_id = <&davinci_mdio>, <3>;
+	phy-mode = "rgmii-id";
+	dual_emac_res_vlan = <2>;
+};
+
+&davinci_mdio {
+	dp83867_0: ethernet-phy@2 {
+		reg = <2>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+		ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+		ti,impedance-control = <0x1f>;
+	};
+
+	dp83867_1: ethernet-phy@3 {
+		reg = <3>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+		ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+		ti,impedance-control = <0x1f>;
+	};
+};
+
+/* No Sata on this device */
+&sata_phy {
+	status = "disabled";
+};
+
+&sata {
+	status = "disabled";
+};
+
+/* No RTC on this device */
+&rtc {
+	status = "disabled";
+};
+
+&usb2_phy1 {
+	phy-supply = <&lp8733_ldo1_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&lp8733_ldo1_reg>;
+};
+
+&dss {
+	/* Supplied by VDA_1V8_PLL */
+	vdda_video-supply = <&lp8732_ldo0_reg>;
+};
+
+&hdmi {
+	/* Supplied by VDA_1V8_PHY */
+	vdda_video-supply = <&lp8732_ldo1_reg>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm-common.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -18,11 +18,49 @@
 		display0 = &hdmi0;
 	};
 
+	evm_12v0: fixedregulator-evm12v0 {
+		/* main supply */
+		compatible = "regulator-fixed";
+		regulator-name = "evm_12v0";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	evm_5v0: fixedregulator-evm5v0 {
+		/* Output 1 of TPS43351QDAPRQ1 on dra72-evm */
+		/* Output 1 of LM5140QRWGTQ1 on dra71-evm */
+		compatible = "regulator-fixed";
+		regulator-name = "evm_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&evm_12v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_3v3: fixedregulator-vsys3v3 {
+		/* Output 2 of TPS43351QDAPRQ1 on dra72-evm */
+		/* Output 2 of LM5140QRWGTQ1 on dra71-evm */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&evm_12v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
 	evm_3v3_sw: fixedregulator-evm_3v3 {
+		/* TPS22965DSG */
 		compatible = "regulator-fixed";
 		regulator-name = "evm_3v3";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vsys_3v3>;
+		regulator-always-on;
+		regulator-boot-on;
 	};
 
 	aic_dvdd: fixedregulator-aic_dvdd {
@@ -39,6 +77,7 @@
 		regulator-name = "evm_3v3_sd";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
+		vin-supply = <&evm_3v3_sw>;
 		enable-active-high;
 		gpio = <&pcf_gpio_21 5 GPIO_ACTIVE_HIGH>;
 	};
@@ -69,9 +108,6 @@
 	tpd12s015: encoder {
 		compatible = "ti,tpd12s015";
 
-		pinctrl-names = "default";
-		pinctrl-0 = <&tpd12s015_pins>;
-
 		gpios = <&pcf_hdmi 4 GPIO_ACTIVE_HIGH>,	/* P4, CT CP HPD */
 			<&pcf_hdmi 5 GPIO_ACTIVE_HIGH>,	/* P5, LS OE */
 			<&gpio7 12 GPIO_ACTIVE_HIGH>;	/* gpio7_12/sp1_cs2, HPD */
@@ -134,72 +170,6 @@
 };
 
 &dra7_pmx_core {
-	i2c1_pins: pinmux_i2c1_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3800, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */
-			DRA7XX_CORE_IOPAD(0x3804, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */
-		>;
-	};
-
-	i2c5_pins: pinmux_i2c5_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */
-			DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */
-		>;
-	};
-
-	i2c5_pins: pinmux_i2c5_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x36b4, PIN_INPUT | MUX_MODE10) /* mcasp1_axr0.i2c5_sda */
-			DRA7XX_CORE_IOPAD(0x36b8, PIN_INPUT | MUX_MODE10) /* mcasp1_axr1.i2c5_scl */
-		>;
-	};
-
-	nand_default: nand_default {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3400, PIN_INPUT  | MUX_MODE0) /* gpmc_ad0 */
-			DRA7XX_CORE_IOPAD(0x3404, PIN_INPUT  | MUX_MODE0) /* gpmc_ad1 */
-			DRA7XX_CORE_IOPAD(0x3408, PIN_INPUT  | MUX_MODE0) /* gpmc_ad2 */
-			DRA7XX_CORE_IOPAD(0x340c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad3 */
-			DRA7XX_CORE_IOPAD(0x3410, PIN_INPUT  | MUX_MODE0) /* gpmc_ad4 */
-			DRA7XX_CORE_IOPAD(0x3414, PIN_INPUT  | MUX_MODE0) /* gpmc_ad5 */
-			DRA7XX_CORE_IOPAD(0x3418, PIN_INPUT  | MUX_MODE0) /* gpmc_ad6 */
-			DRA7XX_CORE_IOPAD(0x341c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad7 */
-			DRA7XX_CORE_IOPAD(0x3420, PIN_INPUT  | MUX_MODE0) /* gpmc_ad8 */
-			DRA7XX_CORE_IOPAD(0x3424, PIN_INPUT  | MUX_MODE0) /* gpmc_ad9 */
-			DRA7XX_CORE_IOPAD(0x3428, PIN_INPUT  | MUX_MODE0) /* gpmc_ad10 */
-			DRA7XX_CORE_IOPAD(0x342c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad11 */
-			DRA7XX_CORE_IOPAD(0x3430, PIN_INPUT  | MUX_MODE0) /* gpmc_ad12 */
-			DRA7XX_CORE_IOPAD(0x3434, PIN_INPUT  | MUX_MODE0) /* gpmc_ad13 */
-			DRA7XX_CORE_IOPAD(0x3438, PIN_INPUT  | MUX_MODE0) /* gpmc_ad14 */
-			DRA7XX_CORE_IOPAD(0x343c, PIN_INPUT  | MUX_MODE0) /* gpmc_ad15 */
-			DRA7XX_CORE_IOPAD(0x34b4, PIN_OUTPUT | MUX_MODE0) /* gpmc_cs0 */
-			DRA7XX_CORE_IOPAD(0x34c4, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale */
-			DRA7XX_CORE_IOPAD(0x34cc, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen */
-			DRA7XX_CORE_IOPAD(0x34c8, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren */
-			DRA7XX_CORE_IOPAD(0x34d0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ben0 */
-			DRA7XX_CORE_IOPAD(0x34d8, PIN_INPUT  | MUX_MODE0) /* gpmc_wait0 */
-		>;
-	};
-
-	usb1_pins: pinmux_usb1_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3680, PIN_INPUT_SLEW | MUX_MODE0) /* usb1_drvvbus */
-		>;
-	};
-
-	usb2_pins: pinmux_usb2_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3684, PIN_INPUT_SLEW | MUX_MODE0) /* usb2_drvvbus */
-		>;
-	};
-
-	tps65917_pins_default: tps65917_pins_default {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3824, PIN_INPUT_PULLUP | MUX_MODE1) /* wakeup3.sys_nirq1 */
-		>;
-	};
-
 	mmc1_pins_default: mmc1_pins_default {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14)	/* mmc1sdcd.gpio219 */
@@ -240,161 +210,12 @@
 			DRA7XX_CORE_IOPAD(0x3818, MUX_MODE15 | PULL_UP)	/* wakeup0.off */
 		>;
 	};
-
-	hdmi_pins: pinmux_hdmi_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* i2c2_sda.hdmi1_ddc_scl */
-			DRA7XX_CORE_IOPAD(0x380c, PIN_INPUT | MUX_MODE1) /* i2c2_scl.hdmi1_ddc_sda */
-		>;
-	};
-
-	tpd12s015_pins: pinmux_tpd12s015_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x37b8, PIN_INPUT_PULLDOWN | MUX_MODE14) /* gpio7_12 HPD */
-		>;
-	};
-
-	atl_pins: pinmux_atl_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3698, PIN_OUTPUT | MUX_MODE5)	/* xref_clk1.atl_clk1 */
-			DRA7XX_CORE_IOPAD(0x369c, PIN_OUTPUT | MUX_MODE5)	/* xref_clk2.atl_clk2 */
-		>;
-	};
-
-	mcasp3_pins: pinmux_mcasp3_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3724, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_aclkx */
-			DRA7XX_CORE_IOPAD(0x3728, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_fsx */
-			DRA7XX_CORE_IOPAD(0x372c, PIN_OUTPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_axr0 */
-			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* mcasp3_axr1 */
-		>;
-	};
-
-	mcasp3_sleep_pins: pinmux_mcasp3_sleep_pins {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x3724, PIN_INPUT_PULLDOWN | MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x3728, PIN_INPUT_PULLDOWN | MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x372c, PIN_INPUT_PULLDOWN | MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x3730, PIN_INPUT_PULLDOWN | MUX_MODE15)
-		>;
-	};
 };
 
 &i2c1 {
 	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c1_pins>;
 	clock-frequency = <400000>;
 
-	tps65917: tps65917@58 {
-		compatible = "ti,tps65917";
-		reg = <0x58>;
-
-		pinctrl-names = "default";
-		pinctrl-0 = <&tps65917_pins_default>;
-
-		interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
-		interrupt-controller;
-		#interrupt-cells = <2>;
-
-		ti,system-power-controller;
-
-		tps65917_pmic {
-			compatible = "ti,tps65917-pmic";
-
-			tps65917_regulators: regulators {
-				smps1_reg: smps1 {
-					/* VDD_MPU */
-					regulator-name = "smps1";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1250000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				smps2_reg: smps2 {
-					/* VDD_CORE */
-					regulator-name = "smps2";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1150000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				smps3_reg: smps3 {
-					/* VDD_GPU IVA DSPEVE */
-					regulator-name = "smps3";
-					regulator-min-microvolt = <850000>;
-					regulator-max-microvolt = <1250000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				smps4_reg: smps4 {
-					/* VDDS1V8 */
-					regulator-name = "smps4";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				smps5_reg: smps5 {
-					/* VDD_DDR */
-					regulator-name = "smps5";
-					regulator-min-microvolt = <1350000>;
-					regulator-max-microvolt = <1350000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				ldo1_reg: ldo1 {
-					/* LDO1_OUT --> SDIO  */
-					regulator-name = "ldo1";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-always-on;
-					regulator-boot-on;
-					regulator-allow-bypass;
-				};
-
-				ldo3_reg: ldo3 {
-					/* VDDA_1V8_PHY */
-					regulator-name = "ldo3";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-boot-on;
-					regulator-always-on;
-				};
-
-				ldo5_reg: ldo5 {
-					/* VDDA_1V8_PLL */
-					regulator-name = "ldo5";
-					regulator-min-microvolt = <1800000>;
-					regulator-max-microvolt = <1800000>;
-					regulator-always-on;
-					regulator-boot-on;
-				};
-
-				ldo4_reg: ldo4 {
-					/* VDDA_3V_USB: VDDA_USBHS33 */
-					regulator-name = "ldo4";
-					regulator-min-microvolt = <3300000>;
-					regulator-max-microvolt = <3300000>;
-					regulator-boot-on;
-				};
-			};
-		};
-
-		tps65917_power_button {
-			compatible = "ti,palmas-pwrbutton";
-			interrupt-parent = <&tps65917>;
-			interrupts = <1 IRQ_TYPE_NONE>;
-			wakeup-source;
-			ti,palmas-long-press-seconds = <6>;
-		};
-	};
-
 	pcf_gpio_21: gpio@21 {
 		compatible = "ti,pcf8575", "nxp,pcf8575";
 		reg = <0x21>;
@@ -423,8 +244,6 @@
 
 &i2c5 {
 	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&i2c5_pins>;
 	clock-frequency = <400000>;
 
 	pcf_hdmi: pcf8575@26 {
@@ -462,8 +281,6 @@
 
 &gpmc {
 	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&nand_default>;
 	ranges = <0 0 0x08000000 0x01000000>;	/* minimum GPMC partition = 16MB */
 	nand@0,0 {
 		/* To use NAND, DIP switch SW5 must be set like so:
@@ -548,14 +365,6 @@
 	};
 };
 
-&usb2_phy1 {
-	phy-supply = <&ldo4_reg>;
-};
-
-&usb2_phy2 {
-	phy-supply = <&ldo4_reg>;
-};
-
 &omap_dwc3_1 {
 	extcon = <&extcon_usb1>;
 };
@@ -566,14 +375,10 @@
 
 &usb1 {
 	dr_mode = "peripheral";
-	pinctrl-names = "default";
-	pinctrl-0 = <&usb1_pins>;
 };
 
 &usb2 {
 	dr_mode = "host";
-	pinctrl-names = "default";
-	pinctrl-0 = <&usb2_pins>;
 };
 
 &mmc1 {
@@ -581,7 +386,6 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc1_pins_default>;
 	vmmc-supply = <&evm_3v3_sd>;
-	vmmc_aux-supply = <&ldo1_reg>;
 	bus-width = <4>;
 	/*
 	 * SDCD signal is not being used here - using the fact that GPIO mode
@@ -603,71 +407,8 @@
 	max-frequency = <192000000>;
 };
 
-&dra7_pmx_core {
-	cpsw_default: cpsw_default {
-		pinctrl-single,pins = <
-			/* Slave 2 */
-			DRA7XX_CORE_IOPAD(0x3598, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d12.rgmii1_txc */
-			DRA7XX_CORE_IOPAD(0x359c, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d13.rgmii1_tctl */
-			DRA7XX_CORE_IOPAD(0x35a0, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d14.rgmii1_td3 */
-			DRA7XX_CORE_IOPAD(0x35a4, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d15.rgmii1_td2 */
-			DRA7XX_CORE_IOPAD(0x35a8, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d16.rgmii1_td1 */
-			DRA7XX_CORE_IOPAD(0x35ac, PIN_OUTPUT | MUX_MODE3)	/* vin2a_d17.rgmii1_td0 */
-			DRA7XX_CORE_IOPAD(0x35b0, PIN_INPUT | MUX_MODE3)	/* vin2a_d18.rgmii1_rclk */
-			DRA7XX_CORE_IOPAD(0x35b4, PIN_INPUT | MUX_MODE3)	/* vin2a_d19.rgmii1_rctl */
-			DRA7XX_CORE_IOPAD(0x35b8, PIN_INPUT | MUX_MODE3)	/* vin2a_d20.rgmii1_rd3 */
-			DRA7XX_CORE_IOPAD(0x35bc, PIN_INPUT | MUX_MODE3)	/* vin2a_d21.rgmii1_rd2 */
-			DRA7XX_CORE_IOPAD(0x35c0, PIN_INPUT | MUX_MODE3)	/* vin2a_d22.rgmii1_rd1 */
-			DRA7XX_CORE_IOPAD(0x35c4, PIN_INPUT | MUX_MODE3)	/* vin2a_d23.rgmii1_rd0 */
-		>;
-
-	};
-
-	cpsw_sleep: cpsw_sleep {
-		pinctrl-single,pins = <
-			/* Slave 2 */
-			DRA7XX_CORE_IOPAD(0x3598, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x359c, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35a0, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35a4, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35a8, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35ac, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35b0, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35b4, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35b8, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35bc, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35c0, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x35c4, MUX_MODE15)
-		>;
-	};
-
-	davinci_mdio_default: davinci_mdio_default {
-		pinctrl-single,pins = <
-			/* MDIO */
-			DRA7XX_CORE_IOPAD(0x363c, PIN_OUTPUT_PULLUP | MUX_MODE0)	/* mdio_d.mdio_d */
-			DRA7XX_CORE_IOPAD(0x3640, PIN_INPUT_PULLUP | MUX_MODE0)	/* mdio_clk.mdio_clk */
-		>;
-	};
-
-	davinci_mdio_sleep: davinci_mdio_sleep {
-		pinctrl-single,pins = <
-			DRA7XX_CORE_IOPAD(0x363c, MUX_MODE15)
-			DRA7XX_CORE_IOPAD(0x3640, MUX_MODE15)
-		>;
-	};
-};
-
 &mac {
 	status = "okay";
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&cpsw_default>;
-	pinctrl-1 = <&cpsw_sleep>;
-};
-
-&davinci_mdio {
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&davinci_mdio_default>;
-	pinctrl-1 = <&davinci_mdio_sleep>;
 };
 
 &dcan1 {
@@ -741,16 +482,11 @@
 
 &dss {
 	status = "ok";
-
-	vdda_video-supply = <&ldo5_reg>;
 };
 
 &hdmi {
 	status = "ok";
 
-	pinctrl-names = "default";
-	pinctrl-0 = <&hdmi_pins>;
-
 	port {
 		hdmi_out: endpoint {
 			remote-endpoint = <&tpd12s015_in>;
@@ -759,9 +495,6 @@
 };
 
 &atl {
-	pinctrl-names = "default";
-	pinctrl-0 = <&atl_pins>;
-
 	assigned-clocks = <&abe_dpll_sys_clk_mux>,
 			  <&atl_gfclk_mux>,
 			  <&dpll_abe_ck>,
@@ -780,9 +513,6 @@
 
 &mcasp3 {
 	#sound-dai-cells = <0>;
-	pinctrl-names = "default", "sleep";
-	pinctrl-0 = <&mcasp3_pins>;
-	pinctrl-1 = <&mcasp3_sleep_pins>;
 
 	assigned-clocks = <&mcasp3_ahclkx_mux>;
 	assigned-clock-parents = <&atl_clkin2_ck>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm.dts	2017-02-12 16:03:20.000000000 -0500
@@ -15,16 +15,16 @@
 	};
 };
 
-&tps65917_regulators {
-	ldo2_reg: ldo2 {
-		/* LDO2_OUT --> TP1017 (UNUSED)  */
-		regulator-name = "ldo2";
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <3300000>;
-		regulator-allow-bypass;
+&i2c1 {
+	tps65917: tps65917@58 {
+		reg = <0x58>;
+
+		interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
 	};
 };
 
+#include "dra72-evm-tps65917.dtsi"
+
 &hdmi {
 	vdda-supply = <&ldo3_reg>;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm-revc.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm-revc.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm-revc.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm-revc.dts	2017-02-12 16:03:20.000000000 -0500
@@ -17,17 +17,22 @@
 	};
 };
 
-&tps65917_regulators {
-	ldo2_reg: ldo2 {
-		/* LDO2_OUT --> VDDA_1V8_PHY2 */
-		regulator-name = "ldo2";
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-		regulator-always-on;
-		regulator-boot-on;
+&i2c1 {
+	tps65917: tps65917@58 {
+		reg = <0x58>;
+
+		interrupts = <GIC_SPI 2 IRQ_TYPE_NONE>;  /* IRQ_SYS_1N */
 	};
 };
 
+#include "dra72-evm-tps65917.dtsi"
+
+&ldo2_reg {
+	/* LDO2_OUT --> VDDA_1V8_PHY2 */
+	regulator-always-on;
+	regulator-boot-on;
+};
+
 &hdmi {
 	vdda-supply = <&ldo2_reg>;
 };
@@ -59,15 +64,17 @@
 &davinci_mdio {
 	dp83867_0: ethernet-phy@2 {
 		reg = <2>;
-		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-		ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+		ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+		ti,min-output-impedance;
 	};
 
 	dp83867_1: ethernet-phy@3 {
 		reg = <3>;
-		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-		ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+		ti,tx-internal-delay = <DP83867_RGMIIDCTL_250_PS>;
 		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
+		ti,min-output-impedance;
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm-tps65917.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm-tps65917.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dra72-evm-tps65917.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra72-evm-tps65917.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/*
+ * Integrated Power Management Chip
+ * http://www.ti.com/lit/ds/symlink/tps65917-q1.pdf
+ */
+
+&tps65917 {
+	compatible = "ti,tps65917";
+
+	interrupt-controller;
+	#interrupt-cells = <2>;
+
+	ti,system-power-controller;
+
+	tps65917_pmic {
+		compatible = "ti,tps65917-pmic";
+
+		smps1-in-supply = <&vsys_3v3>;
+		smps2-in-supply = <&vsys_3v3>;
+		smps3-in-supply = <&vsys_3v3>;
+		smps4-in-supply = <&vsys_3v3>;
+		smps5-in-supply = <&vsys_3v3>;
+		ldo1-in-supply = <&vsys_3v3>;
+		ldo2-in-supply = <&vsys_3v3>;
+		ldo3-in-supply = <&vsys_3v3>;
+		ldo4-in-supply = <&evm_5v0>;
+		ldo5-in-supply = <&vsys_3v3>;
+
+		tps65917_regulators: regulators {
+			smps1_reg: smps1 {
+				/* VDD_MPU */
+				regulator-name = "smps1";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			smps2_reg: smps2 {
+				/* VDD_CORE */
+				regulator-name = "smps2";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1150000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			smps3_reg: smps3 {
+				/* VDD_GPU IVA DSPEVE */
+				regulator-name = "smps3";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			smps4_reg: smps4 {
+				/* VDDS1V8 */
+				regulator-name = "smps4";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			smps5_reg: smps5 {
+				/* VDD_DDR */
+				regulator-name = "smps5";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1_reg: ldo1 {
+				/* LDO1_OUT --> SDIO  */
+				regulator-name = "ldo1";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-allow-bypass;
+			};
+
+			ldo2_reg: ldo2 {
+				regulator-name = "ldo2";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-allow-bypass;
+			};
+
+			ldo3_reg: ldo3 {
+				/* VDDA_1V8_PHY */
+				regulator-name = "ldo3";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo5_reg: ldo5 {
+				/* VDDA_1V8_PLL */
+				regulator-name = "ldo5";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			ldo4_reg: ldo4 {
+				/* VDDA_3V_USB: VDDA_USBHS33 */
+				regulator-name = "ldo4";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+			};
+		};
+	};
+
+	tps65917_power_button {
+		compatible = "ti,palmas-pwrbutton";
+		interrupt-parent = <&tps65917>;
+		interrupts = <1 IRQ_TYPE_NONE>;
+		wakeup-source;
+		ti,palmas-long-press-seconds = <6>;
+	};
+};
+
+&usb2_phy1 {
+	phy-supply = <&ldo4_reg>;
+};
+
+&usb2_phy2 {
+	phy-supply = <&ldo4_reg>;
+};
+
+&dss {
+	vdda_video-supply = <&ldo5_reg>;
+};
+
+&mmc1 {
+	vmmc_aux-supply = <&ldo1_reg>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/dra7.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra7.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/dra7.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/dra7.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 
 	compatible = "ti,dra7xx";
 	interrupt-parent = <&crossbar_mpu>;
+	chosen { };
 
 	aliases {
 		i2c0 = &i2c1;
@@ -171,6 +172,7 @@
 					reg = <0x1400 0x0468>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					#interrupt-cells = <1>;
 					interrupt-controller;
 					pinctrl-single,register-width = <32>;
@@ -1376,6 +1378,7 @@
 			phy-names = "sata-phy";
 			clocks = <&sata_ref_clk>;
 			ti,hwmods = "sata";
+			ports-implemented = <0x1>;
 		};
 
 		rtc: rtc@48838000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/emev2.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/emev2.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/emev2.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/emev2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -8,13 +8,14 @@
  * kind, whether express or implied.
  */
 
-#include "skeleton.dtsi"
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	compatible = "renesas,emev2";
 	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
 
 	aliases {
 		gpio0 = &gpio0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-artik5.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -310,7 +310,7 @@
 	card-detect-delay = <200>;
 	vmmc-supply = <&ldo12_reg>;
 	clock-frequency = <100000000>;
-	clock-freq-min-max = <400000 100000000>;
+	max-frequency = <100000000>;
 	samsung,dw-mshc-ciu-div = <1>;
 	samsung,dw-mshc-sdr-timing = <0 1>;
 	samsung,dw-mshc-ddr-timing = <1 2>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-artik5-eval.dts	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 	vqmmc-supply = <&ldo3_reg>;
 	card-detect-delay = <200>;
 	clock-frequency = <100000000>;
-	clock-freq-min-max = <400000 100000000>;
+	max-frequency = <100000000>;
 	samsung,dw-mshc-ciu-div = <1>;
 	samsung,dw-mshc-sdr-timing = <0 1>;
 	samsung,dw-mshc-ddr-timing = <1 2>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,8 @@
 #include "exynos4-cpu-thermal.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos3250.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	compatible = "samsung,exynos3250";
@@ -211,7 +213,8 @@
 		rtc: rtc@10070000 {
 			compatible = "samsung,s3c6410-rtc";
 			reg = <0x10070000 0x100>;
-			interrupts = <0 73 0>, <0 74 0>;
+			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-parent = <&pmu_system_controller>;
 			status = "disabled";
 		};
@@ -219,7 +222,7 @@
 		tmu: tmu@100C0000 {
 			compatible = "samsung,exynos3250-tmu";
 			reg = <0x100C0000 0x100>;
-			interrupts = <0 216 0>;
+			interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_TMU_APBIF>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -234,14 +237,21 @@
 			      <0x10482000 0x1000>,
 			      <0x10484000 0x2000>,
 			      <0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
 		mct@10050000 {
 			compatible = "samsung,exynos4210-mct";
 			reg = <0x10050000 0x800>;
-			interrupts = <0 218 0>, <0 219 0>, <0 220 0>, <0 221 0>,
-				     <0 223 0>, <0 226 0>, <0 227 0>, <0 228 0>;
+			interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_FIN_PLL>, <&cmu CLK_MCT>;
 			clock-names = "fin_pll", "mct";
 		};
@@ -249,24 +259,24 @@
 		pinctrl_1: pinctrl@11000000 {
 			compatible = "samsung,exynos3250-pinctrl";
 			reg = <0x11000000 0x1000>;
-			interrupts = <0 225 0>;
+			interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
 
 			wakeup-interrupt-controller {
 				compatible = "samsung,exynos4210-wakeup-eint";
-				interrupts = <0 48 0>;
+				interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
 		pinctrl_0: pinctrl@11400000 {
 			compatible = "samsung,exynos3250-pinctrl";
 			reg = <0x11400000 0x1000>;
-			interrupts = <0 240 0>;
+			interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		jpeg: codec@11830000 {
 			compatible = "samsung,exynos3250-jpeg";
 			reg = <0x11830000 0x1000>;
-			interrupts = <0 171 0>;
+			interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_JPEG>, <&cmu CLK_SCLK_JPEG>;
 			clock-names = "jpeg", "sclk";
 			power-domains = <&pd_cam>;
@@ -280,7 +290,8 @@
 		sysmmu_jpeg: sysmmu@11A60000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x11a60000 0x1000>;
-			interrupts = <0 156 0>, <0 161 0>;
+			interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "sysmmu", "master";
 			clocks = <&cmu CLK_SMMUJPEG>, <&cmu CLK_JPEG>;
 			power-domains = <&pd_cam>;
@@ -291,7 +302,9 @@
 			compatible = "samsung,exynos3250-fimd";
 			reg = <0x11c00000 0x30000>;
 			interrupt-names = "fifo", "vsync", "lcd_sys";
-			interrupts = <0 84 0>, <0 85 0>, <0 86 0>;
+			interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_SCLK_FIMD0>, <&cmu CLK_FIMD0>;
 			clock-names = "sclk_fimd", "fimd";
 			power-domains = <&pd_lcd0>;
@@ -303,7 +316,7 @@
 		dsi_0: dsi@11C80000 {
 			compatible = "samsung,exynos3250-mipi-dsi";
 			reg = <0x11C80000 0x10000>;
-			interrupts = <0 83 0>;
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
 			samsung,phy-type = <0>;
 			power-domains = <&pd_lcd0>;
 			phys = <&mipi_phy 1>;
@@ -318,7 +331,8 @@
 		sysmmu_fimd0: sysmmu@11E20000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x11e20000 0x1000>;
-			interrupts = <0 80 0>, <0 81 0>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "sysmmu", "master";
 			clocks = <&cmu CLK_SMMUFIMD0>, <&cmu CLK_FIMD0>;
 			power-domains = <&pd_lcd0>;
@@ -328,7 +342,7 @@
 		hsotg: hsotg@12480000 {
 			compatible = "snps,dwc2";
 			reg = <0x12480000 0x20000>;
-			interrupts = <0 141 0>;
+			interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_USBOTG>;
 			clock-names = "otg";
 			phys = <&exynos_usbphy 0>;
@@ -339,7 +353,7 @@
 		mshc_0: mshc@12510000 {
 			compatible = "samsung,exynos5420-dw-mshc";
 			reg = <0x12510000 0x1000>;
-			interrupts = <0 142 0>;
+			interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_SDMMC0>, <&cmu CLK_SCLK_MMC0>;
 			clock-names = "biu", "ciu";
 			fifo-depth = <0x80>;
@@ -351,7 +365,7 @@
 		mshc_1: mshc@12520000 {
 			compatible = "samsung,exynos5420-dw-mshc";
 			reg = <0x12520000 0x1000>;
-			interrupts = <0 143 0>;
+			interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_SDMMC1>, <&cmu CLK_SCLK_MMC1>;
 			clock-names = "biu", "ciu";
 			fifo-depth = <0x80>;
@@ -363,7 +377,7 @@
 		mshc_2: mshc@12530000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12530000 0x1000>;
-			interrupts = <0 144 0>;
+			interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_SDMMC2>, <&cmu CLK_SCLK_MMC2>;
 			clock-names = "biu", "ciu";
 			fifo-depth = <0x80>;
@@ -391,7 +405,7 @@
 			pdma0: pdma@12680000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x12680000 0x1000>;
-				interrupts = <0 138 0>;
+				interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&cmu CLK_PDMA0>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -402,7 +416,7 @@
 			pdma1: pdma@12690000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x12690000 0x1000>;
-				interrupts = <0 139 0>;
+				interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&cmu CLK_PDMA1>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -415,7 +429,7 @@
 			compatible = "samsung,exynos3250-adc",
 				     "samsung,exynos-adc-v2";
 			reg = <0x126C0000 0x100>;
-			interrupts = <0 137 0>;
+			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "adc", "sclk";
 			clocks = <&cmu CLK_TSADC>, <&cmu CLK_SCLK_TSADC>;
 			#io-channel-cells = <1>;
@@ -427,7 +441,7 @@
 		mfc: codec@13400000 {
 			compatible = "samsung,mfc-v7";
 			reg = <0x13400000 0x10000>;
-			interrupts = <0 102 0>;
+			interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "mfc", "sclk_mfc";
 			clocks = <&cmu CLK_MFC>, <&cmu CLK_SCLK_MFC>;
 			power-domains = <&pd_mfc>;
@@ -437,7 +451,8 @@
 		sysmmu_mfc: sysmmu@13620000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x13620000 0x1000>;
-			interrupts = <0 96 0>, <0 98 0>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "sysmmu", "master";
 			clocks = <&cmu CLK_SMMUMFC_L>, <&cmu CLK_MFC>;
 			power-domains = <&pd_mfc>;
@@ -447,7 +462,7 @@
 		serial_0: serial@13800000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x13800000 0x100>;
-			interrupts = <0 109 0>;
+			interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_UART0>, <&cmu CLK_SCLK_UART0>;
 			clock-names = "uart", "clk_uart_baud0";
 			pinctrl-names = "default";
@@ -458,7 +473,7 @@
 		serial_1: serial@13810000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x13810000 0x100>;
-			interrupts = <0 110 0>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_UART1>, <&cmu CLK_SCLK_UART1>;
 			clock-names = "uart", "clk_uart_baud0";
 			pinctrl-names = "default";
@@ -469,7 +484,7 @@
 		serial_2: serial@13820000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x13820000 0x100>;
-			interrupts = <0 111 0>;
+			interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_UART2>, <&cmu CLK_SCLK_UART2>;
 			clock-names = "uart", "clk_uart_baud0";
 			pinctrl-names = "default";
@@ -482,7 +497,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x13860000 0x100>;
-			interrupts = <0 113 0>;
+			interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C0>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -495,7 +510,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x13870000 0x100>;
-			interrupts = <0 114 0>;
+			interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C1>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -508,7 +523,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x13880000 0x100>;
-			interrupts = <0 115 0>;
+			interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C2>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -521,7 +536,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x13890000 0x100>;
-			interrupts = <0 116 0>;
+			interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C3>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -534,7 +549,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x138A0000 0x100>;
-			interrupts = <0 117 0>;
+			interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C4>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -547,7 +562,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x138B0000 0x100>;
-			interrupts = <0 118 0>;
+			interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C5>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -560,7 +575,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x138C0000 0x100>;
-			interrupts = <0 119 0>;
+			interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C6>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -573,7 +588,7 @@
 			#size-cells = <0>;
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x138D0000 0x100>;
-			interrupts = <0 120 0>;
+			interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2C7>;
 			clock-names = "i2c";
 			pinctrl-names = "default";
@@ -584,7 +599,7 @@
 		spi_0: spi@13920000 {
 			compatible = "samsung,exynos4210-spi";
 			reg = <0x13920000 0x100>;
-			interrupts = <0 121 0>;
+			interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma0 7>, <&pdma0 6>;
 			dma-names = "tx", "rx";
 			#address-cells = <1>;
@@ -600,7 +615,7 @@
 		spi_1: spi@13930000 {
 			compatible = "samsung,exynos4210-spi";
 			reg = <0x13930000 0x100>;
-			interrupts = <0 122 0>;
+			interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma1 7>, <&pdma1 6>;
 			dma-names = "tx", "rx";
 			#address-cells = <1>;
@@ -616,7 +631,7 @@
 		i2s2: i2s@13970000 {
 			compatible = "samsung,s3c6410-i2s";
 			reg = <0x13970000 0x100>;
-			interrupts = <0 126 0>;
+			interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cmu CLK_I2S>, <&cmu CLK_SCLK_I2S>;
 			clock-names = "iis", "i2s_opclk0";
 			dmas = <&pdma0 14>, <&pdma0 13>;
@@ -629,15 +644,19 @@
 		pwm: pwm@139D0000 {
 			compatible = "samsung,exynos4210-pwm";
 			reg = <0x139D0000 0x1000>;
-			interrupts = <0 104 0>, <0 105 0>, <0 106 0>,
-				     <0 107 0>, <0 108 0>;
+			interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 			#pwm-cells = <3>;
 			status = "disabled";
 		};
 
 		pmu {
 			compatible = "arm,cortex-a7-pmu";
-			interrupts = <0 18 0>, <0 19 0>;
+			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		ppmu_dmc0: ppmu_dmc0@106a0000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-monk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-monk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-monk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-monk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -435,7 +435,7 @@
 	card-detect-delay = <200>;
 	vmmc-supply = <&vemmc_reg>;
 	clock-frequency = <100000000>;
-	clock-freq-min-max = <400000 100000000>;
+	max-frequency = <100000000>;
 	samsung,dw-mshc-ciu-div = <1>;
 	samsung,dw-mshc-sdr-timing = <0 1>;
 	samsung,dw-mshc-ddr-timing = <1 2>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-pinctrl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -362,8 +362,14 @@
 
 		interrupt-controller;
 		interrupt-parent = <&gic>;
-		interrupts = <0 32 0>, <0 33 0>, <0 34 0>, <0 35 0>,
-				<0 36 0>, <0 37 0>, <0 38 0>, <0 39 0>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
 		#interrupt-cells = <2>;
 	};
 
@@ -373,8 +379,14 @@
 
 		interrupt-controller;
 		interrupt-parent = <&gic>;
-		interrupts = <0 40 0>, <0 41 0>, <0 42 0>, <0 43 0>,
-				<0 44 0>, <0 45 0>, <0 46 0>, <0 47 0>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
 		#interrupt-cells = <2>;
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-rinato.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-rinato.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos3250-rinato.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos3250-rinato.dts	2017-02-12 16:03:20.000000000 -0500
@@ -649,7 +649,7 @@
 	card-detect-delay = <200>;
 	vmmc-supply = <&ldo12_reg>;
 	clock-frequency = <100000000>;
-	clock-freq-min-max = <400000 100000000>;
+	max-frequency = <100000000>;
 	samsung,dw-mshc-ciu-div = <1>;
 	samsung,dw-mshc-sdr-timing = <0 1>;
 	samsung,dw-mshc-ddr-timing = <1 2>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4210.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4210.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4210.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4210.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -109,12 +109,12 @@
 			#interrupt-cells = <1>;
 			#address-cells = <0>;
 			#size-cells = <0>;
-			interrupt-map = <0 &gic 0 57 0>,
-					<1 &gic 0 69 0>,
+			interrupt-map = <0 &gic 0 57 IRQ_TYPE_LEVEL_HIGH>,
+					<1 &gic 0 69 IRQ_TYPE_LEVEL_HIGH>,
 					<2 &combiner 12 6>,
 					<3 &combiner 12 7>,
-					<4 &gic 0 42 0>,
-					<5 &gic 0 48 0>;
+					<4 &gic 0 42 IRQ_TYPE_LEVEL_HIGH>,
+					<5 &gic 0 48 IRQ_TYPE_LEVEL_HIGH>;
 		};
 	};
 
@@ -127,18 +127,18 @@
 	pinctrl_0: pinctrl@11400000 {
 		compatible = "samsung,exynos4210-pinctrl";
 		reg = <0x11400000 0x1000>;
-		interrupts = <0 47 0>;
+		interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	pinctrl_1: pinctrl@11000000 {
 		compatible = "samsung,exynos4210-pinctrl";
 		reg = <0x11000000 0x1000>;
-		interrupts = <0 46 0>;
+		interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
 
 		wakup_eint: wakeup-interrupt-controller {
 			compatible = "samsung,exynos4210-wakeup-eint";
 			interrupt-parent = <&gic>;
-			interrupts = <0 32 0>;
+			interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 		};
 	};
 
@@ -182,7 +182,7 @@
 	g2d: g2d@12800000 {
 		compatible = "samsung,s5pv210-g2d";
 		reg = <0x12800000 0x1000>;
-		interrupts = <0 89 0>;
+		interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SCLK_FIMG2D>, <&clock CLK_G2D>;
 		clock-names = "sclk_fimg2d", "fimg2d";
 		power-domains = <&pd_lcd0>;
@@ -424,10 +424,22 @@
 
 &combiner {
 	samsung,combiner-nr = <16>;
-	interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-		     <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-		     <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-		     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
+	interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &mdma1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4210-pinctrl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -537,8 +537,14 @@
 
 			interrupt-controller;
 			interrupt-parent = <&gic>;
-			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
 			#interrupt-cells = <2>;
 		};
 
@@ -548,8 +554,14 @@
 
 			interrupt-controller;
 			interrupt-parent = <&gic>;
-			interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 			#interrupt-cells = <2>;
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4412-itop-elite.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4412-itop-elite.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4412-itop-elite.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4412-itop-elite.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,240 @@
+/*
+ * TOPEET's Exynos4412 based itop board device tree source
+ *
+ * Copyright (c) 2016 SUMOMO Computer Association
+ *			https://www.sumomo.mobi
+ *			Randy Li <ayaka@soulik.info>
+ *
+ * Device tree source file for TOPEET iTop Exynos 4412 core board
+ * which is based on Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/sound/samsung-i2s.h>
+#include "exynos4412-itop-scp-core.dtsi"
+
+/ {
+	model = "TOPEET iTop 4412 Elite board based on Exynos4412";
+	compatible = "topeet,itop4412-elite", "samsung,exynos4412", "samsung,exynos4";
+
+	chosen {
+		bootargs = "root=/dev/mmcblk0p2 rw rootfstype=ext4 rootdelay=1 rootwait";
+		stdout-path = "serial2:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led2 {
+			label = "red:system";
+			gpios = <&gpx1 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "heartbeat";
+		};
+
+		led3 {
+			label = "red:user";
+			gpios = <&gpk1 1 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		home {
+			label = "GPIO Key Home";
+			linux,code = <KEY_HOME>;
+			gpios = <&gpx1 1 GPIO_ACTIVE_LOW>;
+		};
+
+		back {
+			label = "GPIO Key Back";
+			linux,code = <KEY_BACK>;
+			gpios = <&gpx1 2 GPIO_ACTIVE_LOW>;
+		};
+
+		sleep {
+			label = "GPIO Key Sleep";
+			linux,code = <KEY_POWER>;
+			gpios = <&gpx3 3 GPIO_ACTIVE_LOW>;
+		};
+
+		vol-up {
+			label = "GPIO Key Vol+";
+			linux,code = <KEY_UP>;
+			gpios = <&gpx2 1 GPIO_ACTIVE_LOW>;
+		};
+
+		vol-down {
+			label = "GPIO Key Vol-";
+			linux,code = <KEY_DOWN>;
+			gpios = <&gpx2 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "wm-sound";
+
+		assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
+				<&clock_audss EXYNOS_MOUT_I2S>,
+				<&clock_audss EXYNOS_DOUT_SRP>,
+				<&clock_audss EXYNOS_DOUT_AUD_BUS>;
+		assigned-clock-parents = <&clock CLK_FOUT_EPLL>,
+				<&clock_audss EXYNOS_MOUT_AUDSS>;
+		assigned-clock-rates = <0>,
+				<0>,
+				<112896000>,
+				<11289600>;
+
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&link0_codec>;
+		simple-audio-card,frame-master = <&link0_codec>;
+
+		simple-audio-card,widgets =
+			"Microphone", "Mic Jack",
+			"Line", "Line In",
+			"Line", "Line Out",
+			"Speaker", "Speaker",
+			"Headphone", "Headphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack", "HP_L",
+			"Headphone Jack", "HP_R",
+			"Speaker", "SPK_LP",
+			"Speaker", "SPK_LN",
+			"Speaker", "SPK_RP",
+			"Speaker", "SPK_RN",
+			"LINPUT1", "Mic Jack",
+			"LINPUT3", "Mic Jack",
+			"RINPUT1", "Mic Jack",
+			"RINPUT2", "Mic Jack";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		link0_codec: simple-audio-card,codec {
+			sound-dai = <&codec>;
+			clocks = <&i2s0 CLK_I2S_CDCLK>;
+			system-clock-frequency = <11289600>;
+		};
+	};
+
+	beep {
+		compatible = "pwm-beeper";
+		pwms = <&pwm 0 4000000 PWM_POLARITY_INVERTED>;
+	};
+
+	camera: camera {
+		pinctrl-0 = <&cam_port_a_clk_active>;
+		pinctrl-names = "default";
+		status = "okay";
+		assigned-clocks = <&clock CLK_MOUT_CAM0>;
+		assigned-clock-parents = <&clock CLK_XUSBXTI>;
+	};
+};
+
+&adc {
+	vdd-supply = <&ldo3_reg>;
+	status = "okay";
+};
+
+&ehci {
+	status = "okay";
+	/* In order to reset USB ethernet */
+	samsung,vbus-gpio = <&gpc0 1 GPIO_ACTIVE_HIGH>;
+
+	port@0 {
+		status = "okay";
+	};
+
+	port@2 {
+		status = "okay";
+	};
+};
+
+&exynos_usbphy {
+	status = "okay";
+};
+
+&fimc_0 {
+	status = "okay";
+	assigned-clocks = <&clock CLK_MOUT_FIMC0>,
+			<&clock CLK_SCLK_FIMC0>;
+	assigned-clock-parents = <&clock CLK_MOUT_MPLL_USER_T>;
+	assigned-clock-rates = <0>, <176000000>;
+};
+
+&hsotg {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&i2c_4 {
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-slave-addr = <0x10>;
+	samsung,i2c-max-bus-freq = <100000>;
+	pinctrl-0 = <&i2c4_bus>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	codec: wm8960@1a {
+		compatible = "wlf,wm8960";
+		reg = <0x1a>;
+		clocks = <&pmu_system_controller 0>;
+		clock-names = "MCLK1";
+		wlf,shared-lrclk;
+		#sound-dai-cells = <0>;
+	};
+};
+
+&i2s0 {
+	pinctrl-0 = <&i2s0_bus>;
+	pinctrl-names = "default";
+	status = "okay";
+	clocks = <&clock_audss EXYNOS_I2S_BUS>,
+		 <&clock_audss EXYNOS_DOUT_AUD_BUS>,
+		 <&clock_audss EXYNOS_SCLK_I2S>;
+	clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
+};
+
+&pinctrl_1 {
+	ether-reset {
+		samsung,pins = "gpc0-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
+	};
+};
+
+&pwm {
+	status = "okay";
+	pinctrl-0 = <&pwm0_out>;
+	pinctrl-names = "default";
+	samsung,pwm-outputs = <0>;
+};
+
+&sdhci_2 {
+	bus-width = <4>;
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4>;
+	pinctrl-names = "default";
+	cd-gpio = <&gpx0 7 GPIO_ACTIVE_LOW>;
+	cap-sd-highspeed;
+	vmmc-supply = <&ldo23_reg>;
+	vqmmc-supply = <&ldo17_reg>;
+	status = "okay";
+};
+
+&serial_1 {
+	status = "okay";
+};
+
+&serial_2 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,501 @@
+/*
+ * TOPEET's Exynos4412 based itop board device tree source
+ *
+ * Copyright (c) 2016 SUMOMO Computer Association
+ *			https://www.sumomo.mobi
+ *			Randy Li <ayaka@soulik.info>
+ *
+ * Device tree source file for TOPEET iTop Exynos 4412 SCP package core
+ * board which is based on Samsung's Exynos4412 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/clock/samsung,s2mps11.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "exynos4412.dtsi"
+#include "exynos4412-ppmu-common.dtsi"
+#include "exynos-mfc-reserved-memory.dtsi"
+
+/ {
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0x40000000 0x40000000>;
+	};
+
+	firmware@0203F000 {
+		compatible = "samsung,secure-firmware";
+		reg = <0x0203F000 0x1000>;
+	};
+
+	fixed-rate-clocks {
+		xxti {
+			compatible = "samsung,clock-xxti";
+			clock-frequency = <0>;
+		};
+
+		xusbxti {
+			compatible = "samsung,clock-xusbxti";
+			clock-frequency = <24000000>;
+		};
+	};
+
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			cooling-maps {
+				map0 {
+				     /* Corresponds to 800MHz at freq_table */
+				     cooling-device = <&cpu0 7 7>;
+				};
+				map1 {
+				     /* Corresponds to 200MHz at freq_table */
+				     cooling-device = <&cpu0 13 13>;
+			       };
+		       };
+		};
+	};
+
+	usb-hub {
+		compatible = "smsc,usb3503a";
+		reset-gpios = <&gpm2 4 GPIO_ACTIVE_LOW>;
+		connect-gpios = <&gpm3 3 GPIO_ACTIVE_HIGH>;
+		intn-gpios = <&gpx2 3 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hsic_reset>;
+	};
+};
+
+&bus_dmc {
+	devfreq-events = <&ppmu_dmc0_3>, <&ppmu_dmc1_3>;
+	vdd-supply = <&buck1_reg>;
+	status = "okay";
+};
+
+&bus_acp {
+	devfreq = <&bus_dmc>;
+	status = "okay";
+};
+
+&bus_c2c {
+	devfreq = <&bus_dmc>;
+	status = "okay";
+};
+
+&bus_leftbus {
+	devfreq-events = <&ppmu_leftbus_3>, <&ppmu_rightbus_3>;
+	vdd-supply = <&buck3_reg>;
+	status = "okay";
+};
+
+&bus_rightbus {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_fsys {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_peri {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&bus_mfc {
+	devfreq = <&bus_leftbus>;
+	status = "okay";
+};
+
+&cpu0 {
+	cpu0-supply = <&buck2_reg>;
+};
+
+&hsotg {
+	vusb_d-supply = <&ldo15_reg>;
+	vusb_a-supply = <&ldo12_reg>;
+};
+
+&i2c_1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	samsung,i2c-sda-delay = <100>;
+	samsung,i2c-max-bus-freq = <400000>;
+	pinctrl-0 = <&i2c1_bus>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	s5m8767: s5m8767-pmic@66 {
+		compatible = "samsung,s5m8767-pmic";
+		reg = <0x66>;
+
+		s5m8767,pmic-buck-default-dvs-idx = <3>;
+
+		s5m8767,pmic-buck-dvs-gpios = <&gpb 5 GPIO_ACTIVE_HIGH>,
+						 <&gpb 6 GPIO_ACTIVE_HIGH>,
+						 <&gpb 7 GPIO_ACTIVE_HIGH>;
+
+		s5m8767,pmic-buck-ds-gpios = <&gpm3 5 GPIO_ACTIVE_HIGH>,
+						<&gpm3 6 GPIO_ACTIVE_HIGH>,
+						<&gpm3 7 GPIO_ACTIVE_HIGH>;
+
+		/* VDD_ARM */
+		s5m8767,pmic-buck2-dvs-voltage = <1356250>, <1300000>,
+						 <1243750>, <1118750>,
+						 <1068750>, <1012500>,
+						 <956250>, <900000>;
+		/* VDD_INT */
+		s5m8767,pmic-buck3-dvs-voltage = <1000000>, <1000000>,
+						 <925000>, <925000>,
+						 <887500>, <887500>,
+						 <850000>, <850000>;
+		/* VDD_G3D */
+		s5m8767,pmic-buck4-dvs-voltage = <1081250>, <1081250>,
+						 <1025000>, <950000>,
+						 <918750>, <900000>,
+						 <875000>, <831250>;
+
+		regulators {
+			ldo1_reg: LDO1 {
+				regulator-name = "VDD_ALIVE";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			/* SCP uses 1.5v, POP uses 1.2v */
+			ldo2_reg: LDO2 {
+				regulator-name = "VDDQ_M12";
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo3_reg: LDO3 {
+				regulator-name = "VDDIOAP_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo4_reg: LDO4 {
+				regulator-name = "VDDQ_PRE";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo5_reg: LDO5 {
+				regulator-name = "VDD_LDO5";
+				op_mode = <0>; /* Always off Mode */
+			};
+
+			ldo6_reg: LDO6 {
+				regulator-name = "VDD10_MPLL";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo7_reg: LDO7 {
+				regulator-name = "VDD10_XPLL";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo8_reg: LDO8 {
+				regulator-name = "VDD10_MIPI";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo9_reg: LDO9 {
+				regulator-name = "VDD33_LCD";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo10_reg: LDO10 {
+				regulator-name = "VDD18_MIPI";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo11_reg: LDO11 {
+				regulator-name = "VDD18_ABB1";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo12_reg: LDO12 {
+				regulator-name = "VDD33_UOTG";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo13_reg: LDO13 {
+				regulator-name = "VDDIOPERI_18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo14_reg: LDO14 {
+				regulator-name = "VDD18_ABB02";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo15_reg: LDO15 {
+				regulator-name = "VDD10_USH";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo16_reg: LDO16 {
+				regulator-name = "VDD18_HSIC";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo17_reg: LDO17 {
+				regulator-name = "VDDIOAP_MMC012_28";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			/* Used by HSIC */
+			ldo18_reg: LDO18 {
+				regulator-name = "VDDIOPERI_28";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo19_reg: LDO19 {
+				regulator-name = "VDD_LDO19";
+				op_mode = <0>; /* Always off Mode */
+			};
+
+			ldo20_reg: LDO20 {
+				regulator-name = "VDD28_CAM";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <2800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo21_reg: LDO21 {
+				regulator-name = "VDD28_AF";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <2800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo22_reg: LDO22 {
+				regulator-name = "VDDA28_2M";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo23_reg: LDO23 {
+				regulator-name = "VDD28_TF";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo24_reg: LDO24 {
+				regulator-name = "VDD33_A31";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo25_reg: LDO25 {
+				regulator-name = "VDD18_CAM";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo26_reg: LDO26 {
+				regulator-name = "VDD18_A31";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo27_reg: LDO27 {
+				regulator-name = "GPS_1V8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			ldo28_reg: LDO28 {
+				regulator-name = "DVDD12";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck1_reg: BUCK1 {
+				regulator-name = "vdd_mif";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt	= <1100000>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "vdd_arm";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt	= <1456250>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck3_reg: BUCK3 {
+				regulator-name = "vdd_int";
+				regulator-min-microvolt = <875000>;
+				regulator-max-microvolt	= <1200000>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck4_reg: BUCK4 {
+				regulator-name = "vdd_g3d";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt	= <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck5_reg: BUCK5 {
+				regulator-name = "vdd_m12";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt	= <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck6_reg: BUCK6 {
+				regulator-name = "vdd12_5m";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt	= <1500000>;
+				regulator-always-on;
+				regulator-boot-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck7_reg: BUCK7 {
+				regulator-name = "pvdd_buck7";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt	= <2000000>;
+				regulator-boot-on;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck8_reg: BUCK8 {
+				regulator-name = "pvdd_buck8";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt	= <1500000>;
+				regulator-boot-on;
+				regulator-always-on;
+				op_mode = <1>; /* Normal Mode */
+			};
+
+			buck9_reg: BUCK9 {
+				regulator-name = "vddf28_emmc";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt	= <3000000>;
+				op_mode = <1>; /* Normal Mode */
+			};
+		};
+
+		s5m8767_osc: clocks {
+			#clock-cells = <1>;
+			clock-output-names = "s5m8767_ap",
+					"s5m8767_cp", "s5m8767_bt";
+		};
+
+	};
+};
+
+&mfc {
+	status = "okay";
+};
+
+&mshc_0 {
+	pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+	pinctrl-names = "default";
+	status = "okay";
+	vmmc-supply = <&buck9_reg>;
+	num-slots = <1>;
+	broken-cd;
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <2 3>;
+	samsung,dw-mshc-ddr-timing = <1 2>;
+	bus-width = <8>;
+	cap-mmc-highspeed;
+};
+
+&pinctrl_1 {
+	hsic_reset: hsic-reset {
+		samsung,pins = "gpm2-4";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
+		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
+	};
+};
+
+&rtc {
+	status = "okay";
+	clocks = <&clock CLK_RTC>, <&s5m8767_osc S2MPS11_CLK_AP>;
+	clock-names = "rtc", "rtc_src";
+};
+
+&tmu {
+	vtmu-supply = <&ldo16_reg>;
+	status = "okay";
+};
+
+&watchdog {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4412-odroidx.dts	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,11 @@
 	};
 };
 
+&adc {
+	vdd-supply = <&ldo10_reg>;
+	status = "okay";
+};
+
 /* VDDQ for MSHC (eMMC card) */
 &buck8_reg {
 	regulator-name = "BUCK8_VDDQ_MMC4_2.8V";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4415.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4415.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4415.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4415.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,650 +0,0 @@
-/*
- * Samsung's Exynos4415 SoC device tree source
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * Samsung's Exynos4415 SoC device nodes are listed in this file. Exynos4415
- * based board files can include this file and provide values for board
- * specific bindings.
- *
- * Note: This file does not include device nodes for all the controllers in
- * Exynos4415 SoC. As device tree coverage for Exynos4415 increases, additional
- * nodes can be added to this 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 <dt-bindings/clock/exynos4415.h>
-#include <dt-bindings/clock/exynos-audss-clk.h>
-
-/ {
-	compatible = "samsung,exynos4415";
-	interrupt-parent = <&gic>;
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	aliases {
-		pinctrl0 = &pinctrl_0;
-		pinctrl1 = &pinctrl_1;
-		pinctrl2 = &pinctrl_2;
-		mshc0 = &mshc_0;
-		mshc1 = &mshc_1;
-		mshc2 = &mshc_2;
-		spi0 = &spi_0;
-		spi1 = &spi_1;
-		spi2 = &spi_2;
-		i2c0 = &i2c_0;
-		i2c1 = &i2c_1;
-		i2c2 = &i2c_2;
-		i2c3 = &i2c_3;
-		i2c4 = &i2c_4;
-		i2c5 = &i2c_5;
-		i2c6 = &i2c_6;
-		i2c7 = &i2c_7;
-	};
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		cpu0: cpu@a00 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a9";
-			reg = <0xa00>;
-			clock-frequency = <1600000000>;
-		};
-
-		cpu1: cpu@a01 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a9";
-			reg = <0xa01>;
-			clock-frequency = <1600000000>;
-		};
-
-		cpu2: cpu@a02 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a9";
-			reg = <0xa02>;
-			clock-frequency = <1600000000>;
-		};
-
-		cpu3: cpu@a03 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a9";
-			reg = <0xa03>;
-			clock-frequency = <1600000000>;
-		};
-	};
-
-	soc: soc {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		sysram@02020000 {
-			compatible = "mmio-sram";
-			reg = <0x02020000 0x50000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x02020000 0x50000>;
-
-			smp-sysram@0 {
-				compatible = "samsung,exynos4210-sysram";
-				reg = <0x0 0x1000>;
-			};
-
-			smp-sysram@4f000 {
-				compatible = "samsung,exynos4210-sysram-ns";
-				reg = <0x4f000 0x1000>;
-			};
-		};
-
-		pinctrl_2: pinctrl@03860000 {
-			compatible = "samsung,exynos4415-pinctrl";
-			reg = <0x03860000 0x1000>;
-			interrupts = <0 242 0>;
-		};
-
-		chipid@10000000 {
-			compatible = "samsung,exynos4210-chipid";
-			reg = <0x10000000 0x100>;
-		};
-
-		sysreg_system_controller: syscon@10010000 {
-			compatible = "samsung,exynos4-sysreg", "syscon";
-			reg = <0x10010000 0x400>;
-		};
-
-		pmu_system_controller: system-controller@10020000 {
-			compatible = "samsung,exynos4415-pmu", "syscon";
-			reg = <0x10020000 0x4000>;
-		};
-
-		mipi_phy: video-phy@10020710 {
-			compatible = "samsung,s5pv210-mipi-video-phy";
-			#phy-cells = <1>;
-			syscon = <&pmu_system_controller>;
-		};
-
-		pd_cam: cam-power-domain@10024000 {
-			compatible = "samsung,exynos4210-pd";
-			reg = <0x10024000 0x20>;
-			#power-domain-cells = <0>;
-		};
-
-		pd_tv: tv-power-domain@10024020 {
-			compatible = "samsung,exynos4210-pd";
-			reg = <0x10024020 0x20>;
-			#power-domain-cells = <0>;
-		};
-
-		pd_mfc: mfc-power-domain@10024040 {
-			compatible = "samsung,exynos4210-pd";
-			reg = <0x10024040 0x20>;
-			#power-domain-cells = <0>;
-		};
-
-		pd_g3d: g3d-power-domain@10024060 {
-			compatible = "samsung,exynos4210-pd";
-			reg = <0x10024060 0x20>;
-			#power-domain-cells = <0>;
-		};
-
-		pd_lcd0: lcd0-power-domain@10024080 {
-			compatible = "samsung,exynos4210-pd";
-			reg = <0x10024080 0x20>;
-			#power-domain-cells = <0>;
-		};
-
-		pd_isp0: isp0-power-domain@100240A0 {
-			compatible = "samsung,exynos4210-pd";
-			reg = <0x100240A0 0x20>;
-			#power-domain-cells = <0>;
-		};
-
-		pd_isp1: isp1-power-domain@100240E0 {
-			compatible = "samsung,exynos4210-pd";
-			reg = <0x100240E0 0x20>;
-			#power-domain-cells = <0>;
-		};
-
-		cmu: clock-controller@10030000 {
-			compatible = "samsung,exynos4415-cmu";
-			reg = <0x10030000 0x18000>;
-			#clock-cells = <1>;
-		};
-
-		rtc: rtc@10070000 {
-			compatible = "samsung,s3c6410-rtc";
-			reg = <0x10070000 0x100>;
-			interrupts = <0 73 0>, <0 74 0>;
-			status = "disabled";
-		};
-
-		mct@10050000 {
-			compatible = "samsung,exynos4210-mct";
-			reg = <0x10050000 0x800>;
-			interrupts = <0 218 0>, <0 219 0>, <0 220 0>, <0 221 0>,
-				     <0 223 0>, <0 226 0>, <0 227 0>, <0 228 0>;
-			clocks = <&cmu CLK_FIN_PLL>, <&cmu CLK_MCT>;
-			clock-names = "fin_pll", "mct";
-		};
-
-		gic: interrupt-controller@10481000 {
-			compatible = "arm,cortex-a9-gic";
-			#interrupt-cells = <3>;
-			interrupt-controller;
-			reg = <0x10481000 0x1000>,
-			      <0x10482000 0x1000>,
-			      <0x10484000 0x2000>,
-			      <0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
-		};
-
-		l2c: l2-cache-controller@10502000 {
-			compatible = "arm,pl310-cache";
-			reg = <0x10502000 0x1000>;
-			cache-unified;
-			cache-level = <2>;
-			arm,tag-latency = <2 2 1>;
-			arm,data-latency = <3 2 1>;
-			arm,double-linefill = <1>;
-			arm,double-linefill-incr = <0>;
-			arm,double-linefill-wrap = <1>;
-			arm,prefetch-drop = <1>;
-			arm,prefetch-offset = <7>;
-		};
-
-		cmu_dmc: clock-controller@105C0000 {
-			compatible = "samsung,exynos4415-cmu-dmc";
-			reg = <0x105C0000 0x3000>;
-			#clock-cells = <1>;
-		};
-
-		pinctrl_1: pinctrl@11000000 {
-			compatible = "samsung,exynos4415-pinctrl";
-			reg = <0x11000000 0x1000>;
-			interrupts = <0 225 0>;
-
-			wakeup-interrupt-controller {
-				compatible = "samsung,exynos4210-wakeup-eint";
-				interrupt-parent = <&gic>;
-				interrupts = <0 48 0>;
-			};
-		};
-
-		pinctrl_0: pinctrl@11400000 {
-			compatible = "samsung,exynos4415-pinctrl";
-			reg = <0x11400000 0x1000>;
-			interrupts = <0 240 0>;
-		};
-
-		fimd: fimd@11C00000 {
-			compatible = "samsung,exynos4415-fimd";
-			reg = <0x11C00000 0x30000>;
-			interrupt-names = "fifo", "vsync", "lcd_sys";
-			interrupts = <0 84 0>, <0 85 0>, <0 86 0>;
-			clocks = <&cmu CLK_SCLK_FIMD0>, <&cmu CLK_FIMD0>;
-			clock-names = "sclk_fimd", "fimd";
-			samsung,power-domain = <&pd_lcd0>;
-			iommus = <&sysmmu_fimd0>;
-			samsung,sysreg = <&sysreg_system_controller>;
-			status = "disabled";
-		};
-
-		dsi_0: dsi@11C80000 {
-			compatible = "samsung,exynos4415-mipi-dsi";
-			reg = <0x11C80000 0x10000>;
-			interrupts = <0 83 0>;
-			samsung,phy-type = <0>;
-			samsung,power-domain = <&pd_lcd0>;
-			phys = <&mipi_phy 1>;
-			phy-names = "dsim";
-			clocks = <&cmu CLK_DSIM0>, <&cmu CLK_SCLK_MIPI0>;
-			clock-names = "bus_clk", "pll_clk";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
-		};
-
-		sysmmu_fimd0: sysmmu@11E20000 {
-			compatible = "samsung,exynos-sysmmu";
-			reg = <0x11e20000 0x1000>;
-			interrupts = <0 80 0>, <0 81 0>;
-			clock-names = "sysmmu", "master";
-			clocks = <&cmu CLK_SMMUFIMD0>, <&cmu CLK_FIMD0>;
-			power-domains = <&pd_lcd0>;
-			#iommu-cells = <0>;
-		};
-
-		hsotg: hsotg@12480000 {
-			compatible = "samsung,s3c6400-hsotg";
-			reg = <0x12480000 0x20000>;
-			interrupts = <0 141 0>;
-			clocks = <&cmu CLK_USBDEVICE>;
-			clock-names = "otg";
-			phys = <&exynos_usbphy 0>;
-			phy-names = "usb2-phy";
-			status = "disabled";
-		};
-
-		mshc_0: mshc@12510000 {
-			compatible = "samsung,exynos5250-dw-mshc";
-			reg = <0x12510000 0x1000>;
-			interrupts = <0 142 0>;
-			clocks = <&cmu CLK_SDMMC0>, <&cmu CLK_SCLK_MMC0>;
-			clock-names = "biu", "ciu";
-			fifo-depth = <0x80>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
-		};
-
-		mshc_1: mshc@12520000 {
-			compatible = "samsung,exynos5250-dw-mshc";
-			reg = <0x12520000 0x1000>;
-			interrupts = <0 143 0>;
-			clocks = <&cmu CLK_SDMMC1>, <&cmu CLK_SCLK_MMC1>;
-			clock-names = "biu", "ciu";
-			fifo-depth = <0x80>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
-		};
-
-		mshc_2: mshc@12530000 {
-			compatible = "samsung,exynos5250-dw-mshc";
-			reg = <0x12530000 0x1000>;
-			interrupts = <0 144 0>;
-			clocks = <&cmu CLK_SDMMC2>, <&cmu CLK_SCLK_MMC2>;
-			clock-names = "biu", "ciu";
-			fifo-depth = <0x80>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
-		};
-
-		ehci: ehci@12580000 {
-			compatible = "samsung,exynos4210-ehci";
-			reg = <0x12580000 0x100>;
-			interrupts = <0 140 0>;
-			clocks = <&cmu CLK_USBHOST>;
-			clock-names = "usbhost";
-			status = "disabled";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port@0 {
-				reg = <0>;
-				phys = <&exynos_usbphy 1>;
-				status = "disabled";
-			};
-			port@1 {
-				reg = <1>;
-				phys = <&exynos_usbphy 2>;
-				status = "disabled";
-			};
-			port@2 {
-				reg = <2>;
-				phys = <&exynos_usbphy 3>;
-				status = "disabled";
-			};
-		};
-
-		ohci: ohci@12590000 {
-			compatible = "samsung,exynos4210-ohci";
-			reg = <0x12590000 0x100>;
-			interrupts = <0 140 0>;
-			clocks = <&cmu CLK_USBHOST>;
-			clock-names = "usbhost";
-			status = "disabled";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			port@0 {
-				reg = <0>;
-				phys = <&exynos_usbphy 1>;
-				status = "disabled";
-			};
-		};
-
-		exynos_usbphy: exynos-usbphy@125B0000 {
-			compatible = "samsung,exynos4x12-usb2-phy";
-			reg = <0x125B0000 0x100>;
-			samsung,pmureg-phandle = <&pmu_system_controller>;
-			samsung,sysreg-phandle = <&sysreg_system_controller>;
-			clocks = <&cmu CLK_USBDEVICE>, <&xusbxti>;
-			clock-names = "phy", "ref";
-			#phy-cells = <1>;
-			status = "disabled";
-		};
-
-		amba {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			interrupt-parent = <&gic>;
-			ranges;
-
-			pdma0: pdma@12680000 {
-				compatible = "arm,pl330", "arm,primecell";
-				reg = <0x12680000 0x1000>;
-				interrupts = <0 138 0>;
-				clocks = <&cmu CLK_PDMA0>;
-				clock-names = "apb_pclk";
-				#dma-cells = <1>;
-				#dma-channels = <8>;
-				#dma-requests = <32>;
-			};
-
-			pdma1: pdma@12690000 {
-				compatible = "arm,pl330", "arm,primecell";
-				reg = <0x12690000 0x1000>;
-				interrupts = <0 139 0>;
-				clocks = <&cmu CLK_PDMA1>;
-				clock-names = "apb_pclk";
-				#dma-cells = <1>;
-				#dma-channels = <8>;
-				#dma-requests = <32>;
-			};
-		};
-
-		adc: adc@126C0000 {
-			compatible = "samsung,exynos3250-adc",
-				     "samsung,exynos-adc-v2";
-			reg = <0x126C0000 0x100>, <0x10020718 0x4>;
-			interrupts = <0 137 0>;
-			clock-names = "adc", "sclk";
-			clocks = <&cmu CLK_TSADC>, <&cmu CLK_SCLK_TSADC>;
-			#io-channel-cells = <1>;
-			io-channel-ranges;
-			status = "disabled";
-		};
-
-		serial_0: serial@13800000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x13800000 0x100>;
-			interrupts = <0 109 0>;
-			clocks = <&cmu CLK_UART0>, <&cmu CLK_SCLK_UART0>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-
-		serial_1: serial@13810000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x13810000 0x100>;
-			interrupts = <0 110 0>;
-			clocks = <&cmu CLK_UART1>, <&cmu CLK_SCLK_UART1>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-
-		serial_2: serial@13820000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x13820000 0x100>;
-			interrupts = <0 111 0>;
-			clocks = <&cmu CLK_UART2>, <&cmu CLK_SCLK_UART2>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-
-		serial_3: serial@13830000 {
-			compatible = "samsung,exynos4210-uart";
-			reg = <0x13830000 0x100>;
-			interrupts = <0 112 0>;
-			clocks = <&cmu CLK_UART3>, <&cmu CLK_SCLK_UART3>;
-			clock-names = "uart", "clk_uart_baud0";
-			status = "disabled";
-		};
-
-		i2c_0: i2c@13860000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x13860000 0x100>;
-			interrupts = <0 113 0>;
-			clocks = <&cmu CLK_I2C0>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c0_bus>;
-			status = "disabled";
-		};
-
-		i2c_1: i2c@13870000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x13870000 0x100>;
-			interrupts = <0 114 0>;
-			clocks = <&cmu CLK_I2C1>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c1_bus>;
-			status = "disabled";
-		};
-
-		i2c_2: i2c@13880000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x13880000 0x100>;
-			interrupts = <0 115 0>;
-			clocks = <&cmu CLK_I2C2>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c2_bus>;
-			status = "disabled";
-		};
-
-		i2c_3: i2c@13890000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x13890000 0x100>;
-			interrupts = <0 116 0>;
-			clocks = <&cmu CLK_I2C3>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c3_bus>;
-			status = "disabled";
-		};
-
-		i2c_4: i2c@138A0000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x138A0000 0x100>;
-			interrupts = <0 117 0>;
-			clocks = <&cmu CLK_I2C4>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c4_bus>;
-			status = "disabled";
-		};
-
-		i2c_5: i2c@138B0000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x138B0000 0x100>;
-			interrupts = <0 118 0>;
-			clocks = <&cmu CLK_I2C5>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c5_bus>;
-			status = "disabled";
-		};
-
-		i2c_6: i2c@138C0000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x138C0000 0x100>;
-			interrupts = <0 119 0>;
-			clocks = <&cmu CLK_I2C6>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c6_bus>;
-			status = "disabled";
-		};
-
-		i2c_7: i2c@138D0000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "samsung,s3c2440-i2c";
-			reg = <0x138D0000 0x100>;
-			interrupts = <0 120 0>;
-			clocks = <&cmu CLK_I2C7>;
-			clock-names = "i2c";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2c7_bus>;
-			status = "disabled";
-		};
-
-		spi_0: spi@13920000 {
-			compatible = "samsung,exynos4210-spi";
-			reg = <0x13920000 0x100>;
-			interrupts = <0 121 0>;
-			dmas = <&pdma0 7>, <&pdma0 6>;
-			dma-names = "tx", "rx";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			clocks = <&cmu CLK_SPI0>, <&cmu CLK_SCLK_SPI0>;
-			clock-names = "spi", "spi_busclk0";
-			samsung,spi-src-clk = <0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&spi0_bus>;
-			status = "disabled";
-		};
-
-		spi_1: spi@13930000 {
-			compatible = "samsung,exynos4210-spi";
-			reg = <0x13930000 0x100>;
-			interrupts = <0 122 0>;
-			dmas = <&pdma1 7>, <&pdma1 6>;
-			dma-names = "tx", "rx";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			clocks = <&cmu CLK_SPI1>, <&cmu CLK_SCLK_SPI1>;
-			clock-names = "spi", "spi_busclk0";
-			samsung,spi-src-clk = <0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&spi1_bus>;
-			status = "disabled";
-		};
-
-		spi_2: spi@13940000 {
-			compatible = "samsung,exynos4210-spi";
-			reg = <0x13940000 0x100>;
-			interrupts = <0 123 0>;
-			dmas = <&pdma0 9>, <&pdma0 8>;
-			dma-names = "tx", "rx";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			clocks = <&cmu CLK_SPI2>, <&cmu CLK_SCLK_SPI2>;
-			clock-names = "spi", "spi_busclk0";
-			samsung,spi-src-clk = <0>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&spi2_bus>;
-			status = "disabled";
-		};
-
-		clock_audss: clock-controller@03810000 {
-			compatible = "samsung,exynos4210-audss-clock";
-			reg = <0x03810000 0x0C>;
-			#clock-cells = <1>;
-		};
-
-		i2s0: i2s@3830000 {
-			compatible = "samsung,s5pv210-i2s";
-			reg = <0x03830000 0x100>;
-			interrupts = <0 124 0>;
-			clocks = <&clock_audss EXYNOS_I2S_BUS>,
-				<&clock_audss EXYNOS_SCLK_I2S>;
-			clock-names = "iis", "i2s_opclk0";
-			dmas = <&pdma1 10>, <&pdma1 9>, <&pdma1 8>;
-			dma-names = "tx", "rx", "tx-sec";
-			pinctrl-names = "default";
-			pinctrl-0 = <&i2s0_bus>;
-			samsung,idma-addr = <0x03000000>;
-			status = "disabled";
-		};
-
-		pwm: pwm@139D0000 {
-			compatible = "samsung,exynos4210-pwm";
-			reg = <0x139D0000 0x1000>;
-			interrupts = <0 104 0>, <0 105 0>, <0 106 0>,
-				     <0 107 0>, <0 108 0>;
-			#pwm-cells = <3>;
-			status = "disabled";
-		};
-
-		pmu {
-			compatible = "arm,cortex-a9-pmu";
-			interrupts = <0 18 0>, <0 19 0>, <0 20 0>, <0 21 0>;
-		};
-	};
-};
-
-#include "exynos4415-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4415-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4415-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4415-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4415-pinctrl.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,575 +0,0 @@
-/*
- * Samsung's Exynos4415 SoCs pin-mux and pin-config device tree source
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
- *
- * Samsung's Exynos4415 SoCs pin-mux and pin-config optiosn are listed as device
- * tree nodes are listed in this 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 <dt-bindings/pinctrl/samsung.h>
-
-&pinctrl_0 {
-	gpa0: gpa0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpa1: gpa1 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpb: gpb {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpc0: gpc0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpc1: gpc1 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpd0: gpd0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpd1: gpd1 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpf0: gpf0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpf1: gpf1 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpf2: gpf2 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	uart0_data: uart0-data {
-		samsung,pins = "gpa0-0", "gpa0-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	uart0_fctl: uart0-fctl {
-		samsung,pins = "gpa0-2", "gpa0-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	uart1_data: uart1-data {
-		samsung,pins = "gpa0-4", "gpa0-5";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	uart1_fctl: uart1-fctl {
-		samsung,pins = "gpa0-6", "gpa0-7";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	uart2_data: uart2-data {
-		samsung,pins = "gpa1-0", "gpa1-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	uart2_fctl: uart2-fctl {
-		samsung,pins = "gpa1-2", "gpa1-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	uart3_data: uart3-data {
-		samsung,pins = "gpa1-4", "gpa1-5";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c2_bus: i2c2-bus {
-		samsung,pins = "gpa0-6", "gpa0-7";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c3_bus: i2c3-bus {
-		samsung,pins = "gpa1-2", "gpa1-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	spi0_bus: spi0-bus {
-		samsung,pins = "gpb-0", "gpb-2", "gpb-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c4_bus: i2c4-bus {
-		samsung,pins = "gpb-0", "gpb-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	spi1_bus: spi1-bus {
-		samsung,pins = "gpb-4", "gpb-6", "gpb-7";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c5_bus: i2c5-bus {
-		samsung,pins = "gpb-2", "gpb-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2s1_bus: i2s1-bus {
-		samsung,pins = "gpc0-0", "gpc0-1", "gpc0-2", "gpc0-3",
-				"gpc0-4";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2s2_bus: i2s2-bus {
-		samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
-				"gpc1-4";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	pcm2_bus: pcm2-bus {
-		samsung,pins = "gpc1-0", "gpc1-1", "gpc1-2", "gpc1-3",
-				"gpc1-4";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c6_bus: i2c6-bus {
-		samsung,pins = "gpc1-3", "gpc1-4";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	spi2_bus: spi2-bus {
-		samsung,pins = "gpc1-1", "gpc1-3", "gpc1-4";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_5>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	pwm0_out: pwm0-out {
-		samsung,pins = "gpd0-0";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	pwm1_out: pwm1-out {
-		samsung,pins = "gpd0-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	pwm2_out: pwm2-out {
-		samsung,pins = "gpd0-2";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	pwm3_out: pwm3-out {
-		samsung,pins = "gpd0-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c7_bus: i2c7-bus {
-		samsung,pins = "gpd0-2", "gpd0-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c0_bus: i2c0-bus {
-		samsung,pins = "gpd1-0", "gpd1-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	i2c1_bus: i2c1-bus {
-		samsung,pins = "gpd1-2", "gpd1-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-};
-
-&pinctrl_1 {
-	gpk0: gpk0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpk1: gpk1 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpk2: gpk2 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpk3: gpk3 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpl0: gpl0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpm0: gpm0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpm1: gpm1 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpm2: gpm2 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpm3: gpm3 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpm4: gpm4 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpx0: gpx0 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		interrupt-parent = <&gic>;
-		interrupts = <0 32 0>, <0 33 0>, <0 34 0>, <0 35 0>,
-				<0 36 0>, <0 37 0>, <0 38 0>, <0 39 0>;
-		#interrupt-cells = <2>;
-	};
-
-	gpx1: gpx1 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		interrupt-parent = <&gic>;
-		interrupts = <0 40 0>, <0 41 0>, <0 42 0>, <0 43 0>,
-				<0 44 0>, <0 45 0>, <0 46 0>, <0 47 0>;
-		#interrupt-cells = <2>;
-	};
-
-	gpx2: gpx2 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	gpx3: gpx3 {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	sd0_clk: sd0-clk {
-		samsung,pins = "gpk0-0";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd0_cmd: sd0-cmd {
-		samsung,pins = "gpk0-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd0_cd: sd0-cd {
-		samsung,pins = "gpk0-2";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd0_rdqs: sd0-rdqs {
-		samsung,pins = "gpk0-7";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd0_bus1: sd0-bus-width1 {
-		samsung,pins = "gpk0-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd0_bus4: sd0-bus-width4 {
-		samsung,pins = "gpk0-4", "gpk0-5", "gpk0-6";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd0_bus8: sd0-bus-width8 {
-		samsung,pins = "gpl0-0", "gpl0-1", "gpl0-2", "gpl0-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd1_clk: sd1-clk {
-		samsung,pins = "gpk1-0";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd1_cmd: sd1-cmd {
-		samsung,pins = "gpk1-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd1_cd: sd1-cd {
-		samsung,pins = "gpk1-2";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd1_bus1: sd1-bus-width1 {
-		samsung,pins = "gpk1-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd1_bus4: sd1-bus-width4 {
-		samsung,pins = "gpk1-4", "gpk1-5", "gpk1-6";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd2_clk: sd2-clk {
-		samsung,pins = "gpk2-0";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd2_cmd: sd2-cmd {
-		samsung,pins = "gpk2-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd2_cd: sd2-cd {
-		samsung,pins = "gpk2-2";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd2_bus1: sd2-bus-width1 {
-		samsung,pins = "gpk2-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	sd2_bus4: sd2-bus-width4 {
-		samsung,pins = "gpk2-4", "gpk2-5", "gpk2-6";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	cam_port_b_io: cam-port-b-io {
-		samsung,pins = "gpm0-0", "gpm0-1", "gpm0-2", "gpm0-3",
-				"gpm0-4", "gpm0-5", "gpm0-6", "gpm0-7",
-				"gpm1-0", "gpm1-1", "gpm2-0", "gpm2-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	cam_port_b_clk_active: cam-port-b-clk-active {
-		samsung,pins = "gpm2-2";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV4>;
-	};
-
-	cam_port_b_clk_idle: cam-port-b-clk-idle {
-		samsung,pins = "gpm2-2";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	fimc_is_i2c0: fimc-is-i2c0 {
-		samsung,pins = "gpm4-0", "gpm4-1";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	fimc_is_i2c1: fimc-is-i2c1 {
-		samsung,pins = "gpm4-2", "gpm4-3";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-
-	fimc_is_uart: fimc-is-uart {
-		samsung,pins = "gpm3-5", "gpm3-7";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-};
-
-&pinctrl_2 {
-	gpz: gpz {
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		interrupt-controller;
-		#interrupt-cells = <2>;
-	};
-
-	i2s0_bus: i2s0-bus {
-		samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
-				"gpz-4", "gpz-5", "gpz-6";
-		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
-		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
-		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@
 
 #include <dt-bindings/clock/exynos4.h>
 #include <dt-bindings/clock/exynos-audss-clk.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "exynos-syscon-restart.dtsi"
 
 / {
@@ -78,6 +80,11 @@
 		reg = <0x10000000 0x100>;
 	};
 
+	scu: snoop-control-unit@10500000 {
+		compatible = "arm,cortex-a9-scu";
+		reg = <0x10500000 0x2000>;
+	};
+
 	memory-controller@12570000 {
 		compatible = "samsung,exynos4210-srom";
 		reg = <0x12570000 0x14>;
@@ -168,7 +175,7 @@
 	dsi_0: dsi@11C80000 {
 		compatible = "samsung,exynos4210-mipi-dsi";
 		reg = <0x11C80000 0x10000>;
-		interrupts = <0 79 0>;
+		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
 		power-domains = <&pd_lcd0>;
 		phys = <&mipi_phy 1>;
 		phy-names = "dsim";
@@ -191,7 +198,7 @@
 		fimc_0: fimc@11800000 {
 			compatible = "samsung,exynos4210-fimc";
 			reg = <0x11800000 0x1000>;
-			interrupts = <0 84 0>;
+			interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_FIMC0>, <&clock CLK_SCLK_FIMC0>;
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
@@ -203,7 +210,7 @@
 		fimc_1: fimc@11810000 {
 			compatible = "samsung,exynos4210-fimc";
 			reg = <0x11810000 0x1000>;
-			interrupts = <0 85 0>;
+			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_FIMC1>, <&clock CLK_SCLK_FIMC1>;
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
@@ -215,7 +222,7 @@
 		fimc_2: fimc@11820000 {
 			compatible = "samsung,exynos4210-fimc";
 			reg = <0x11820000 0x1000>;
-			interrupts = <0 86 0>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_FIMC2>, <&clock CLK_SCLK_FIMC2>;
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
@@ -227,7 +234,7 @@
 		fimc_3: fimc@11830000 {
 			compatible = "samsung,exynos4210-fimc";
 			reg = <0x11830000 0x1000>;
-			interrupts = <0 87 0>;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_FIMC3>, <&clock CLK_SCLK_FIMC3>;
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
@@ -239,7 +246,7 @@
 		csis_0: csis@11880000 {
 			compatible = "samsung,exynos4210-csis";
 			reg = <0x11880000 0x4000>;
-			interrupts = <0 78 0>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_CSIS0>, <&clock CLK_SCLK_CSIS0>;
 			clock-names = "csis", "sclk_csis";
 			bus-width = <4>;
@@ -254,7 +261,7 @@
 		csis_1: csis@11890000 {
 			compatible = "samsung,exynos4210-csis";
 			reg = <0x11890000 0x4000>;
-			interrupts = <0 80 0>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_CSIS1>, <&clock CLK_SCLK_CSIS1>;
 			clock-names = "csis", "sclk_csis";
 			bus-width = <2>;
@@ -270,7 +277,7 @@
 	watchdog: watchdog@10060000 {
 		compatible = "samsung,s3c2410-wdt";
 		reg = <0x10060000 0x100>;
-		interrupts = <0 43 0>;
+		interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_WDT>;
 		clock-names = "watchdog";
 		status = "disabled";
@@ -280,7 +287,8 @@
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x10070000 0x100>;
 		interrupt-parent = <&pmu_system_controller>;
-		interrupts = <0 44 0>, <0 45 0>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_RTC>;
 		clock-names = "rtc";
 		status = "disabled";
@@ -289,7 +297,7 @@
 	keypad: keypad@100A0000 {
 		compatible = "samsung,s5pv210-keypad";
 		reg = <0x100A0000 0x100>;
-		interrupts = <0 109 0>;
+		interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_KEYIF>;
 		clock-names = "keypad";
 		status = "disabled";
@@ -298,7 +306,7 @@
 	sdhci_0: sdhci@12510000 {
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12510000 0x100>;
-		interrupts = <0 73 0>;
+		interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SDMMC0>, <&clock CLK_SCLK_MMC0>;
 		clock-names = "hsmmc", "mmc_busclk.2";
 		status = "disabled";
@@ -307,7 +315,7 @@
 	sdhci_1: sdhci@12520000 {
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12520000 0x100>;
-		interrupts = <0 74 0>;
+		interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SDMMC1>, <&clock CLK_SCLK_MMC1>;
 		clock-names = "hsmmc", "mmc_busclk.2";
 		status = "disabled";
@@ -316,7 +324,7 @@
 	sdhci_2: sdhci@12530000 {
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12530000 0x100>;
-		interrupts = <0 75 0>;
+		interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SDMMC2>, <&clock CLK_SCLK_MMC2>;
 		clock-names = "hsmmc", "mmc_busclk.2";
 		status = "disabled";
@@ -325,7 +333,7 @@
 	sdhci_3: sdhci@12540000 {
 		compatible = "samsung,exynos4210-sdhci";
 		reg = <0x12540000 0x100>;
-		interrupts = <0 76 0>;
+		interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SDMMC3>, <&clock CLK_SCLK_MMC3>;
 		clock-names = "hsmmc", "mmc_busclk.2";
 		status = "disabled";
@@ -344,7 +352,7 @@
 	hsotg: hsotg@12480000 {
 		compatible = "samsung,s3c6400-hsotg";
 		reg = <0x12480000 0x20000>;
-		interrupts = <0 71 0>;
+		interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_USB_DEVICE>;
 		clock-names = "otg";
 		phys = <&exynos_usbphy 0>;
@@ -355,7 +363,7 @@
 	ehci: ehci@12580000 {
 		compatible = "samsung,exynos4210-ehci";
 		reg = <0x12580000 0x100>;
-		interrupts = <0 70 0>;
+		interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_USB_HOST>;
 		clock-names = "usbhost";
 		status = "disabled";
@@ -381,7 +389,7 @@
 	ohci: ohci@12590000 {
 		compatible = "samsung,exynos4210-ohci";
 		reg = <0x12590000 0x100>;
-		interrupts = <0 70 0>;
+		interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_USB_HOST>;
 		clock-names = "usbhost";
 		status = "disabled";
@@ -423,7 +431,7 @@
 	mfc: codec@13400000 {
 		compatible = "samsung,mfc-v5";
 		reg = <0x13400000 0x10000>;
-		interrupts = <0 94 0>;
+		interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
 		power-domains = <&pd_mfc>;
 		clocks = <&clock CLK_MFC>, <&clock CLK_SCLK_MFC>;
 		clock-names = "mfc", "sclk_mfc";
@@ -434,7 +442,7 @@
 	serial_0: serial@13800000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13800000 0x100>;
-		interrupts = <0 52 0>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
 		clock-names = "uart", "clk_uart_baud0";
 		dmas = <&pdma0 15>, <&pdma0 16>;
@@ -445,7 +453,7 @@
 	serial_1: serial@13810000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13810000 0x100>;
-		interrupts = <0 53 0>;
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
 		clock-names = "uart", "clk_uart_baud0";
 		dmas = <&pdma1 15>, <&pdma1 16>;
@@ -456,7 +464,7 @@
 	serial_2: serial@13820000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13820000 0x100>;
-		interrupts = <0 54 0>;
+		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
 		clock-names = "uart", "clk_uart_baud0";
 		dmas = <&pdma0 17>, <&pdma0 18>;
@@ -467,7 +475,7 @@
 	serial_3: serial@13830000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0x13830000 0x100>;
-		interrupts = <0 55 0>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_UART3>, <&clock CLK_SCLK_UART3>;
 		clock-names = "uart", "clk_uart_baud0";
 		dmas = <&pdma1 17>, <&pdma1 18>;
@@ -480,7 +488,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13860000 0x100>;
-		interrupts = <0 58 0>;
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C0>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -493,7 +501,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13870000 0x100>;
-		interrupts = <0 59 0>;
+		interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C1>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -506,7 +514,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13880000 0x100>;
-		interrupts = <0 60 0>;
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C2>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -519,7 +527,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x13890000 0x100>;
-		interrupts = <0 61 0>;
+		interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C3>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -532,7 +540,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138A0000 0x100>;
-		interrupts = <0 62 0>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C4>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -545,7 +553,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138B0000 0x100>;
-		interrupts = <0 63 0>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C5>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -558,7 +566,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138C0000 0x100>;
-		interrupts = <0 64 0>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C6>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -571,7 +579,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-i2c";
 		reg = <0x138D0000 0x100>;
-		interrupts = <0 65 0>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C7>;
 		clock-names = "i2c";
 		pinctrl-names = "default";
@@ -584,7 +592,7 @@
 		#size-cells = <0>;
 		compatible = "samsung,s3c2440-hdmiphy-i2c";
 		reg = <0x138E0000 0x100>;
-		interrupts = <0 93 0>;
+		interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_I2C_HDMI>;
 		clock-names = "i2c";
 		status = "disabled";
@@ -598,7 +606,7 @@
 	spi_0: spi@13920000 {
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x13920000 0x100>;
-		interrupts = <0 66 0>;
+		interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
 		dmas = <&pdma0 7>, <&pdma0 6>;
 		dma-names = "tx", "rx";
 		#address-cells = <1>;
@@ -613,7 +621,7 @@
 	spi_1: spi@13930000 {
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x13930000 0x100>;
-		interrupts = <0 67 0>;
+		interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
 		dmas = <&pdma1 7>, <&pdma1 6>;
 		dma-names = "tx", "rx";
 		#address-cells = <1>;
@@ -628,7 +636,7 @@
 	spi_2: spi@13940000 {
 		compatible = "samsung,exynos4210-spi";
 		reg = <0x13940000 0x100>;
-		interrupts = <0 68 0>;
+		interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
 		dmas = <&pdma0 9>, <&pdma0 8>;
 		dma-names = "tx", "rx";
 		#address-cells = <1>;
@@ -643,7 +651,11 @@
 	pwm: pwm@139D0000 {
 		compatible = "samsung,exynos4210-pwm";
 		reg = <0x139D0000 0x1000>;
-		interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, <0 41 0>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_PWM>;
 		clock-names = "timers";
 		#pwm-cells = <3>;
@@ -660,7 +672,7 @@
 		pdma0: pdma@12680000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x12680000 0x1000>;
-			interrupts = <0 35 0>;
+			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_PDMA0>;
 			clock-names = "apb_pclk";
 			#dma-cells = <1>;
@@ -671,7 +683,7 @@
 		pdma1: pdma@12690000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x12690000 0x1000>;
-			interrupts = <0 36 0>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_PDMA1>;
 			clock-names = "apb_pclk";
 			#dma-cells = <1>;
@@ -682,7 +694,7 @@
 		mdma1: mdma@12850000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x12850000 0x1000>;
-			interrupts = <0 34 0>;
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_MDMA>;
 			clock-names = "apb_pclk";
 			#dma-cells = <1>;
@@ -712,7 +724,7 @@
 	jpeg_codec: jpeg-codec@11840000 {
 		compatible = "samsung,exynos4210-jpeg";
 		reg = <0x11840000 0x1000>;
-		interrupts = <0 88 0>;
+		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_JPEG>;
 		clock-names = "jpeg";
 		power-domains = <&pd_cam>;
@@ -722,7 +734,7 @@
 	rotator: rotator@12810000 {
 		compatible = "samsung,exynos4210-rotator";
 		reg = <0x12810000 0x64>;
-		interrupts = <0 83 0>;
+		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_ROTATOR>;
 		clock-names = "rotator";
 		iommus = <&sysmmu_rotator>;
@@ -731,7 +743,7 @@
 	hdmi: hdmi@12D00000 {
 		compatible = "samsung,exynos4210-hdmi";
 		reg = <0x12D00000 0x70000>;
-		interrupts = <0 92 0>;
+		interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
 		clock-names = "hdmi", "sclk_hdmi", "sclk_pixel", "sclk_hdmiphy",
 			"mout_hdmi";
 		clocks = <&clock CLK_HDMI>, <&clock CLK_SCLK_HDMI>,
@@ -746,7 +758,7 @@
 	hdmicec: cec@100B0000 {
 		compatible = "samsung,s5p-cec";
 		reg = <0x100B0000 0x200>;
-		interrupts = <0 114 0>;
+		interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_HDMI_CEC>;
 		clock-names = "hdmicec";
 		samsung,syscon-phandle = <&pmu_system_controller>;
@@ -757,7 +769,7 @@
 
 	mixer: mixer@12C10000 {
 		compatible = "samsung,exynos4210-mixer";
-		interrupts = <0 91 0>;
+		interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
 		reg = <0x12C10000 0x2100>, <0x12c00000 0x300>;
 		power-domains = <&pd_tv>;
 		iommus = <&sysmmu_tv>;
@@ -984,7 +996,7 @@
 	sss: sss@10830000 {
 		compatible = "samsung,exynos4210-secss";
 		reg = <0x10830000 0x300>;
-		interrupts = <0 112 0>;
+		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SSS>;
 		clock-names = "secss";
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4x12.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4x12.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4x12.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4x12.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -88,11 +88,11 @@
 			#interrupt-cells = <1>;
 			#address-cells = <0>;
 			#size-cells = <0>;
-			interrupt-map = <0 &gic 0 57 0>,
+			interrupt-map = <0 &gic 0 57 IRQ_TYPE_LEVEL_HIGH>,
 					<1 &combiner 12 5>,
 					<2 &combiner 12 6>,
 					<3 &combiner 12 7>,
-					<4 &gic 1 12 0>;
+					<4 &gic 1 12 IRQ_TYPE_LEVEL_HIGH>;
 		};
 	};
 
@@ -112,7 +112,7 @@
 	g2d: g2d@10800000 {
 		compatible = "samsung,exynos4212-g2d";
 		reg = <0x10800000 0x1000>;
-		interrupts = <0 89 0>;
+		interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SCLK_FIMG2D>, <&clock CLK_G2D>;
 		clock-names = "sclk_fimg2d", "fimg2d";
 		iommus = <&sysmmu_g2d>;
@@ -127,7 +127,7 @@
 		fimc_lite_0: fimc-lite@12390000 {
 			compatible = "samsung,exynos4212-fimc-lite";
 			reg = <0x12390000 0x1000>;
-			interrupts = <0 105 0>;
+			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_isp>;
 			clocks = <&clock CLK_FIMC_LITE0>;
 			clock-names = "flite";
@@ -138,7 +138,7 @@
 		fimc_lite_1: fimc-lite@123A0000 {
 			compatible = "samsung,exynos4212-fimc-lite";
 			reg = <0x123A0000 0x1000>;
-			interrupts = <0 106 0>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_isp>;
 			clocks = <&clock CLK_FIMC_LITE1>;
 			clock-names = "flite";
@@ -147,9 +147,10 @@
 		};
 
 		fimc_is: fimc-is@12000000 {
-			compatible = "samsung,exynos4212-fimc-is", "simple-bus";
+			compatible = "samsung,exynos4212-fimc-is";
 			reg = <0x12000000 0x260000>;
-			interrupts = <0 90 0>, <0 95 0>;
+			interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_isp>;
 			clocks = <&clock CLK_FIMC_LITE0>,
 				 <&clock CLK_FIMC_LITE1>, <&clock CLK_PPMUISPX>,
@@ -200,7 +201,7 @@
 	mshc_0: mmc@12550000 {
 		compatible = "samsung,exynos4412-dw-mshc";
 		reg = <0x12550000 0x1000>;
-		interrupts = <0 77 0>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		fifo-depth = <0x80>;
@@ -461,11 +462,26 @@
 };
 
 &combiner {
-	interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-		     <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-		     <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-		     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
-		     <0 107 0>, <0 108 0>, <0 48 0>, <0 42 0>;
+	interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &exynos_usbphy {
@@ -529,18 +545,18 @@
 &pinctrl_0 {
 	compatible = "samsung,exynos4x12-pinctrl";
 	reg = <0x11400000 0x1000>;
-	interrupts = <0 47 0>;
+	interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &pinctrl_1 {
 	compatible = "samsung,exynos4x12-pinctrl";
 	reg = <0x11000000 0x1000>;
-	interrupts = <0 46 0>;
+	interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
 
 	wakup_eint: wakeup-interrupt-controller {
 		compatible = "samsung,exynos4210-wakeup-eint";
 		interrupt-parent = <&gic>;
-		interrupts = <0 32 0>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 	};
 };
 
@@ -554,7 +570,7 @@
 &pinctrl_3 {
 	compatible = "samsung,exynos4x12-pinctrl";
 	reg = <0x106E0000 0x1000>;
-	interrupts = <0 72 0>;
+	interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &pmu_system_controller {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos4x12-pinctrl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -572,8 +572,14 @@
 
 			interrupt-controller;
 			interrupt-parent = <&gic>;
-			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
 			#interrupt-cells = <2>;
 		};
 
@@ -583,8 +589,14 @@
 
 			interrupt-controller;
 			interrupt-parent = <&gic>;
-			interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 			#interrupt-cells = <2>;
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5250.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5250.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5250.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5250.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -181,8 +181,8 @@
 						<0x1 0 &combiner 23 4>,
 						<0x2 0 &combiner 25 2>,
 						<0x3 0 &combiner 25 3>,
-						<0x4 0 &gic 0 120 0>,
-						<0x5 0 &gic 0 121 0>;
+						<0x4 0 &gic 0 120 IRQ_TYPE_LEVEL_HIGH>,
+						<0x5 0 &gic 0 121 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
@@ -195,31 +195,31 @@
 		pinctrl_0: pinctrl@11400000 {
 			compatible = "samsung,exynos5250-pinctrl";
 			reg = <0x11400000 0x1000>;
-			interrupts = <0 46 0>;
+			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
 
 			wakup_eint: wakeup-interrupt-controller {
 				compatible = "samsung,exynos4210-wakeup-eint";
 				interrupt-parent = <&gic>;
-				interrupts = <0 32 0>;
+				interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
 		pinctrl_1: pinctrl@13400000 {
 			compatible = "samsung,exynos5250-pinctrl";
 			reg = <0x13400000 0x1000>;
-			interrupts = <0 45 0>;
+			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_2: pinctrl@10d10000 {
 			compatible = "samsung,exynos5250-pinctrl";
 			reg = <0x10d10000 0x1000>;
-			interrupts = <0 50 0>;
+			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_3: pinctrl@03860000 {
 			compatible = "samsung,exynos5250-pinctrl";
 			reg = <0x03860000 0x1000>;
-			interrupts = <0 47 0>;
+			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pmu_system_controller: system-controller@10040000 {
@@ -236,7 +236,7 @@
 		watchdog@101D0000 {
 			compatible = "samsung,exynos5250-wdt";
 			reg = <0x101D0000 0x100>;
-			interrupts = <0 42 0>;
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_WDT>;
 			clock-names = "watchdog";
 			samsung,syscon-phandle = <&pmu_system_controller>;
@@ -245,7 +245,7 @@
 		g2d@10850000 {
 			compatible = "samsung,exynos5250-g2d";
 			reg = <0x10850000 0x1000>;
-			interrupts = <0 91 0>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_G2D>;
 			clock-names = "fimg2d";
 			iommus = <&sysmmu_g2d>;
@@ -254,7 +254,7 @@
 		mfc: codec@11000000 {
 			compatible = "samsung,mfc-v6";
 			reg = <0x11000000 0x10000>;
-			interrupts = <0 96 0>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_mfc>;
 			clocks = <&clock CLK_MFC>;
 			clock-names = "mfc";
@@ -265,7 +265,7 @@
 		rotator: rotator@11C00000 {
 			compatible = "samsung,exynos5250-rotator";
 			reg = <0x11C00000 0x64>;
-			interrupts = <0 84 0>;
+			interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_ROTATOR>;
 			clock-names = "rotator";
 			iommus = <&sysmmu_rotator>;
@@ -274,7 +274,7 @@
 		tmu: tmu@10060000 {
 			compatible = "samsung,exynos5250-tmu";
 			reg = <0x10060000 0x100>;
-			interrupts = <0 65 0>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -284,7 +284,7 @@
 			compatible = "snps,dwc-ahci";
 			samsung,sata-freq = <66>;
 			reg = <0x122F0000 0x1ff>;
-			interrupts = <0 115 0>;
+			interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_SATA>, <&clock CLK_SCLK_SATA>;
 			clock-names = "sata", "sclk_sata";
 			phys = <&sata_phy>;
@@ -306,7 +306,7 @@
 		i2c_4: i2c@12CA0000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12CA0000 0x100>;
-			interrupts = <0 60 0>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_I2C4>;
@@ -319,7 +319,7 @@
 		i2c_5: i2c@12CB0000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12CB0000 0x100>;
-			interrupts = <0 61 0>;
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_I2C5>;
@@ -332,7 +332,7 @@
 		i2c_6: i2c@12CC0000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12CC0000 0x100>;
-			interrupts = <0 62 0>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_I2C6>;
@@ -345,7 +345,7 @@
 		i2c_7: i2c@12CD0000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12CD0000 0x100>;
-			interrupts = <0 63 0>;
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_I2C7>;
@@ -358,7 +358,7 @@
 		i2c_8: i2c@12CE0000 {
 			compatible = "samsung,s3c2440-hdmiphy-i2c";
 			reg = <0x12CE0000 0x1000>;
-			interrupts = <0 64 0>;
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_I2C_HDMI>;
@@ -380,7 +380,7 @@
 			compatible = "samsung,exynos4210-spi";
 			status = "disabled";
 			reg = <0x12d20000 0x100>;
-			interrupts = <0 66 0>;
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma0 5
 				&pdma0 4>;
 			dma-names = "tx", "rx";
@@ -396,7 +396,7 @@
 			compatible = "samsung,exynos4210-spi";
 			status = "disabled";
 			reg = <0x12d30000 0x100>;
-			interrupts = <0 67 0>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma1 5
 				&pdma1 4>;
 			dma-names = "tx", "rx";
@@ -412,7 +412,7 @@
 			compatible = "samsung,exynos4210-spi";
 			status = "disabled";
 			reg = <0x12d40000 0x100>;
-			interrupts = <0 68 0>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma0 7
 				&pdma0 6>;
 			dma-names = "tx", "rx";
@@ -426,7 +426,7 @@
 
 		mmc_0: mmc@12200000 {
 			compatible = "samsung,exynos5250-dw-mshc";
-			interrupts = <0 75 0>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x12200000 0x1000>;
@@ -438,7 +438,7 @@
 
 		mmc_1: mmc@12210000 {
 			compatible = "samsung,exynos5250-dw-mshc";
-			interrupts = <0 76 0>;
+			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x12210000 0x1000>;
@@ -450,7 +450,7 @@
 
 		mmc_2: mmc@12220000 {
 			compatible = "samsung,exynos5250-dw-mshc";
-			interrupts = <0 77 0>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x12220000 0x1000>;
@@ -463,7 +463,7 @@
 		mmc_3: mmc@12230000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12230000 0x1000>;
-			interrupts = <0 78 0>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_SDMMC3>, <&clock CLK_SCLK_MMC3>;
@@ -526,7 +526,7 @@
 			usbdrd_dwc3: dwc3@12000000 {
 				compatible = "synopsys,dwc3";
 				reg = <0x12000000 0x10000>;
-				interrupts = <0 72 0>;
+				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&usbdrd_phy 0>, <&usbdrd_phy 1>;
 				phy-names = "usb2-phy", "usb3-phy";
 			};
@@ -544,7 +544,7 @@
 		ehci: usb@12110000 {
 			compatible = "samsung,exynos4210-ehci";
 			reg = <0x12110000 0x100>;
-			interrupts = <0 71 0>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 
 			clocks = <&clock CLK_USB2>;
 			clock-names = "usbhost";
@@ -559,7 +559,7 @@
 		ohci: usb@12120000 {
 			compatible = "samsung,exynos4210-ohci";
 			reg = <0x12120000 0x100>;
-			interrupts = <0 71 0>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 
 			clocks = <&clock CLK_USB2>;
 			clock-names = "usbhost";
@@ -591,7 +591,7 @@
 			pdma0: pdma@121A0000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x121A0000 0x1000>;
-				interrupts = <0 34 0>;
+				interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_PDMA0>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -602,7 +602,7 @@
 			pdma1: pdma@121B0000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x121B0000 0x1000>;
-				interrupts = <0 35 0>;
+				interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_PDMA1>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -613,7 +613,7 @@
 			mdma0: mdma@10800000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x10800000 0x1000>;
-				interrupts = <0 33 0>;
+				interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_MDMA0>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -624,7 +624,7 @@
 			mdma1: mdma@11C10000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x11C10000 0x1000>;
-				interrupts = <0 124 0>;
+				interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_MDMA1>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -636,7 +636,7 @@
 		gsc_0:  gsc@13e00000 {
 			compatible = "samsung,exynos5-gsc";
 			reg = <0x13e00000 0x1000>;
-			interrupts = <0 85 0>;
+			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_gsc>;
 			clocks = <&clock CLK_GSCL0>;
 			clock-names = "gscl";
@@ -646,7 +646,7 @@
 		gsc_1:  gsc@13e10000 {
 			compatible = "samsung,exynos5-gsc";
 			reg = <0x13e10000 0x1000>;
-			interrupts = <0 86 0>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_gsc>;
 			clocks = <&clock CLK_GSCL1>;
 			clock-names = "gscl";
@@ -656,7 +656,7 @@
 		gsc_2:  gsc@13e20000 {
 			compatible = "samsung,exynos5-gsc";
 			reg = <0x13e20000 0x1000>;
-			interrupts = <0 87 0>;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_gsc>;
 			clocks = <&clock CLK_GSCL2>;
 			clock-names = "gscl";
@@ -666,7 +666,7 @@
 		gsc_3:  gsc@13e30000 {
 			compatible = "samsung,exynos5-gsc";
 			reg = <0x13e30000 0x1000>;
-			interrupts = <0 88 0>;
+			interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
 			power-domains = <&pd_gsc>;
 			clocks = <&clock CLK_GSCL3>;
 			clock-names = "gscl";
@@ -677,7 +677,7 @@
 			compatible = "samsung,exynos4212-hdmi";
 			reg = <0x14530000 0x70000>;
 			power-domains = <&pd_disp1>;
-			interrupts = <0 95 0>;
+			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_HDMI>, <&clock CLK_SCLK_HDMI>,
 				 <&clock CLK_SCLK_PIXEL>, <&clock CLK_SCLK_HDMIPHY>,
 				 <&clock CLK_MOUT_HDMI>;
@@ -690,7 +690,7 @@
 			compatible = "samsung,exynos5250-mixer";
 			reg = <0x14450000 0x10000>;
 			power-domains = <&pd_disp1>;
-			interrupts = <0 94 0>;
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_MIXER>, <&clock CLK_HDMI>,
 				 <&clock CLK_SCLK_HDMI>;
 			clock-names = "mixer", "hdmi", "sclk_hdmi";
@@ -706,7 +706,7 @@
 		adc: adc@12D10000 {
 			compatible = "samsung,exynos-adc-v1";
 			reg = <0x12D10000 0x100>;
-			interrupts = <0 106 0>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_ADC>;
 			clock-names = "adc";
 			#io-channel-cells = <1>;
@@ -718,7 +718,7 @@
 		sss@10830000 {
 			compatible = "samsung,exynos4210-secss";
 			reg = <0x10830000 0x300>;
-			interrupts = <0 112 0>;
+			interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_SSS>;
 			clock-names = "secss";
 		};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5250-snow-common.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -523,6 +523,7 @@
 	status = "okay";
 };
 
+/* eMMC flash */
 &mmc_0 {
 	status = "okay";
 	num-slots = <1>;
@@ -536,6 +537,7 @@
 	cap-mmc-highspeed;
 };
 
+/* uSD card */
 &mmc_2 {
 	status = "okay";
 	num-slots = <1>;
@@ -553,6 +555,8 @@
 /*
  * On Snow we've got SIP WiFi and so can keep drive strengths low to
  * reduce EMI.
+ *
+ * WiFi SDIO module
  */
 &mmc_3 {
 	status = "okay";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5260.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5260.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5260.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5260.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,8 @@
 */
 
 #include <dt-bindings/clock/exynos5260-clk.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	compatible = "samsung,exynos5260", "samsung,exynos5";
@@ -168,7 +170,8 @@
 				<0x10482000 0x1000>,
 				<0x10484000 0x2000>,
 				<0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
 		chipid: chipid@10000000 {
@@ -181,10 +184,18 @@
 			reg = <0x100B0000 0x1000>;
 			clocks = <&fin_pll>, <&clock_peri PERI_CLK_MCT>;
 			clock-names = "fin_pll", "mct";
-			interrupts = <0 104 0>, <0 105 0>, <0 106 0>,
-					<0 107 0>, <0 122 0>, <0 123 0>,
-					<0 124 0>, <0 125 0>, <0 126 0>,
-					<0 127 0>, <0 128 0>, <0 129 0>;
+			interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		cci: cci@10F00000 {
@@ -210,25 +221,25 @@
 		pinctrl_0: pinctrl@11600000 {
 			compatible = "samsung,exynos5260-pinctrl";
 			reg = <0x11600000 0x1000>;
-			interrupts = <0 79 0>;
+			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
 
 			wakeup-interrupt-controller {
 				compatible = "samsung,exynos4210-wakeup-eint";
 				interrupt-parent = <&gic>;
-				interrupts = <0 32 0>;
+				interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
 		pinctrl_1: pinctrl@12290000 {
 			compatible = "samsung,exynos5260-pinctrl";
 			reg = <0x12290000 0x1000>;
-			interrupts = <0 157 0>;
+			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_2: pinctrl@128B0000 {
 			compatible = "samsung,exynos5260-pinctrl";
 			reg = <0x128B0000 0x1000>;
-			interrupts = <0 243 0>;
+			interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pmu_system_controller: system-controller@10D50000 {
@@ -239,7 +250,7 @@
 		uart0: serial@12C00000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C00000 0x100>;
-			interrupts = <0 146 0>;
+			interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peri PERI_CLK_UART0>, <&clock_peri PERI_SCLK_UART0>;
 			clock-names = "uart", "clk_uart_baud0";
 			status = "disabled";
@@ -248,7 +259,7 @@
 		uart1: serial@12C10000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C10000 0x100>;
-			interrupts = <0 147 0>;
+			interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peri PERI_CLK_UART1>, <&clock_peri PERI_SCLK_UART1>;
 			clock-names = "uart", "clk_uart_baud0";
 			status = "disabled";
@@ -257,7 +268,7 @@
 		uart2: serial@12C20000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C20000 0x100>;
-			interrupts = <0 148 0>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peri PERI_CLK_UART2>, <&clock_peri PERI_SCLK_UART2>;
 			clock-names = "uart", "clk_uart_baud0";
 			status = "disabled";
@@ -266,7 +277,7 @@
 		uart3: serial@12860000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12860000 0x100>;
-			interrupts = <0 145 0>;
+			interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_aud AUD_CLK_AUD_UART>, <&clock_aud AUD_SCLK_AUD_UART>;
 			clock-names = "uart", "clk_uart_baud0";
 			status = "disabled";
@@ -275,7 +286,7 @@
 		mmc_0: mmc@12140000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12140000 0x2000>;
-			interrupts = <0 156 0>;
+			interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock_fsys FSYS_CLK_MMC0>, <&clock_top TOP_SCLK_MMC0>;
@@ -287,7 +298,7 @@
 		mmc_1: mmc@12150000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12150000 0x2000>;
-			interrupts = <0 158 0>;
+			interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock_fsys FSYS_CLK_MMC1>, <&clock_top TOP_SCLK_MMC1>;
@@ -299,7 +310,7 @@
 		mmc_2: mmc@12160000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12160000 0x2000>;
-			interrupts = <0 159 0>;
+			interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock_fsys FSYS_CLK_MMC2>, <&clock_top TOP_SCLK_MMC2>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5410.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5410.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5410.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5410.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 #include "exynos54xx.dtsi"
 #include "exynos-syscon-restart.dtsi"
 #include <dt-bindings/clock/exynos5410.h>
+#include <dt-bindings/clock/exynos-audss-clk.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
@@ -82,10 +83,18 @@
 			#clock-cells = <1>;
 		};
 
+		clock_audss: audss-clock-controller@3810000 {
+			compatible = "samsung,exynos5410-audss-clock";
+			reg = <0x03810000 0x0C>;
+			#clock-cells = <1>;
+			clocks = <&fin_pll>, <&clock CLK_FOUT_EPLL>;
+			clock-names = "pll_ref", "pll_in";
+		};
+
 		tmu_cpu0: tmu@10060000 {
 			compatible = "samsung,exynos5420-tmu";
 			reg = <0x10060000 0x100>;
-			interrupts = <GIC_SPI 65 0>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -94,7 +103,7 @@
 		tmu_cpu1: tmu@10064000 {
 			compatible = "samsung,exynos5420-tmu";
 			reg = <0x10064000 0x100>;
-			interrupts = <GIC_SPI 183 0>;
+			interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -103,7 +112,7 @@
 		tmu_cpu2: tmu@10068000 {
 			compatible = "samsung,exynos5420-tmu";
 			reg = <0x10068000 0x100>;
-			interrupts = <GIC_SPI 184 0>;
+			interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -112,7 +121,7 @@
 		tmu_cpu3: tmu@1006c000 {
 			compatible = "samsung,exynos5420-tmu";
 			reg = <0x1006c000 0x100>;
-			interrupts = <GIC_SPI 185 0>;
+			interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -121,7 +130,7 @@
 		mmc_0: mmc@12200000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12200000 0x1000>;
-			interrupts = <0 75 0>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_MMC0>, <&clock CLK_SCLK_MMC0>;
@@ -133,7 +142,7 @@
 		mmc_1: mmc@12210000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12210000 0x1000>;
-			interrupts = <0 76 0>;
+			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_MMC1>, <&clock CLK_SCLK_MMC1>;
@@ -145,7 +154,7 @@
 		mmc_2: mmc@12220000 {
 			compatible = "samsung,exynos5250-dw-mshc";
 			reg = <0x12220000 0x1000>;
-			interrupts = <0 77 0>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			clocks = <&clock CLK_MMC2>, <&clock CLK_SCLK_MMC2>;
@@ -157,31 +166,81 @@
 		pinctrl_0: pinctrl@13400000 {
 			compatible = "samsung,exynos5410-pinctrl";
 			reg = <0x13400000 0x1000>;
-			interrupts = <0 45 0>;
+			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
 
 			wakeup-interrupt-controller {
 				compatible = "samsung,exynos4210-wakeup-eint";
 				interrupt-parent = <&gic>;
-				interrupts = <0 32 0>;
+				interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
 		pinctrl_1: pinctrl@14000000 {
 			compatible = "samsung,exynos5410-pinctrl";
 			reg = <0x14000000 0x1000>;
-			interrupts = <0 46 0>;
+			interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_2: pinctrl@10d10000 {
 			compatible = "samsung,exynos5410-pinctrl";
 			reg = <0x10d10000 0x1000>;
-			interrupts = <0 50 0>;
+			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_3: pinctrl@03860000 {
 			compatible = "samsung,exynos5410-pinctrl";
 			reg = <0x03860000 0x1000>;
-			interrupts = <0 47 0>;
+			interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		amba {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			interrupt-parent = <&gic>;
+			ranges;
+
+			pdma0: pdma@12680000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0x121A0000 0x1000>;
+				interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clock CLK_PDMA0>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+
+			pdma1: pdma@12690000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0x121B0000 0x1000>;
+				interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clock CLK_PDMA1>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+		};
+
+		audi2s0: i2s@03830000 {
+			compatible = "samsung,exynos5420-i2s";
+			reg = <0x03830000 0x100>;
+			dmas = <&pdma0 10
+				&pdma0 9
+				&pdma0 8>;
+			dma-names = "tx", "rx", "tx-sec";
+			clocks = <&clock_audss EXYNOS_I2S_BUS>,
+				<&clock_audss EXYNOS_I2S_BUS>,
+				<&clock_audss EXYNOS_SCLK_I2S>;
+			clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
+			#clock-cells = <1>;
+			clock-output-names = "i2s_cdclk0";
+			#sound-dai-cells = <1>;
+			samsung,idma-addr = <0x03000000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&audi2s0_bus>;
+			status = "disabled";
 		};
 	};
 
@@ -329,7 +388,7 @@
 };
 
 &usbdrd_dwc3_1 {
-	interrupts = <GIC_SPI 200 0>;
+	interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &usbdrd_phy1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5410-odroidxu.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5410-odroidxu.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5410-odroidxu.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5410-odroidxu.dts	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include <dt-bindings/clock/maxim,max77802.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/sound/samsung-i2s.h>
 #include "exynos54xx-odroidxu-leds.dtsi"
 
 / {
@@ -57,6 +58,61 @@
 		compatible = "samsung,secure-firmware";
 		reg = <0x02073000 0x1000>;
 	};
+
+	sound: sound {
+		compatible = "simple-audio-card";
+
+		simple-audio-card,name = "Odroid-XU";
+		simple-audio-card,widgets =
+			"Headphone", "Headphone Jack",
+			"Speakers", "Speakers";
+		simple-audio-card,routing =
+			"Headphone Jack", "HPL",
+			"Headphone Jack", "HPR",
+			"Headphone Jack", "MICBIAS",
+			"IN1", "Headphone Jack",
+			"Speakers", "SPKL",
+			"Speakers", "SPKR";
+
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&link0_codec>;
+		simple-audio-card,frame-master = <&link0_codec>;
+
+		simple-audio-card,cpu {
+			sound-dai = <&audi2s0 0>;
+			system-clock-frequency = <19200000>;
+		};
+
+		link0_codec: simple-audio-card,codec {
+			sound-dai = <&max98090>;
+			clocks = <&audi2s0 CLK_I2S_CDCLK>;
+		};
+	};
+};
+
+&audi2s0 {
+	status = "okay";
+};
+
+&clock {
+	clocks = <&fin_pll>;
+	assigned-clocks = <&clock CLK_FOUT_EPLL>;
+	assigned-clock-rates = <192000000>;
+};
+
+&clock_audss {
+	assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
+			<&clock_audss EXYNOS_MOUT_I2S>,
+			<&clock_audss EXYNOS_DOUT_SRP>,
+			<&clock_audss EXYNOS_DOUT_AUD_BUS>;
+
+	assigned-clock-parents = <&clock CLK_FOUT_EPLL>,
+			<&clock_audss EXYNOS_MOUT_AUDSS>;
+
+	assigned-clock-rates =  <0>,
+				<0>,
+				<96000000>,
+				<19200000>;
 };
 
 &cpu0_thermal {
@@ -440,6 +496,19 @@
 	};
 };
 
+&i2c_1 {
+	status = "okay";
+	max98090: max98090@10 {
+		compatible = "maxim,max98090";
+		reg = <0x10>;
+		interrupt-parent = <&gpj3>;
+		interrupts = <0 IRQ_TYPE_NONE>;
+		clocks = <&audi2s0 CLK_I2S_CDCLK>;
+		clock-names = "mclk";
+		#sound-dai-cells = <0>;
+	};
+};
+
 &mmc_0 {
 	status = "okay";
 	mmc-pwrseq = <&emmc_pwrseq>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5410-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5410-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5410-pinctrl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -615,4 +615,13 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	audi2s0_bus: audi2s0-bus {
+		samsung,pins = "gpz-0", "gpz-1", "gpz-2", "gpz-3",
+				"gpz-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5420.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5420.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5420.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5420.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -193,7 +193,7 @@
 		mfc: codec@11000000 {
 			compatible = "samsung,mfc-v7";
 			reg = <0x11000000 0x10000>;
-			interrupts = <0 96 0>;
+			interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_MFC>;
 			clock-names = "mfc";
 			power-domains = <&mfc_pd>;
@@ -203,7 +203,7 @@
 
 		mmc_0: mmc@12200000 {
 			compatible = "samsung,exynos5420-dw-mshc-smu";
-			interrupts = <0 75 0>;
+			interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x12200000 0x2000>;
@@ -215,7 +215,7 @@
 
 		mmc_1: mmc@12210000 {
 			compatible = "samsung,exynos5420-dw-mshc-smu";
-			interrupts = <0 76 0>;
+			interrupts = <0 76 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x12210000 0x2000>;
@@ -227,7 +227,7 @@
 
 		mmc_2: mmc@12220000 {
 			compatible = "samsung,exynos5420-dw-mshc";
-			interrupts = <0 77 0>;
+			interrupts = <0 77 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x12220000 0x1000>;
@@ -320,37 +320,37 @@
 		pinctrl_0: pinctrl@13400000 {
 			compatible = "samsung,exynos5420-pinctrl";
 			reg = <0x13400000 0x1000>;
-			interrupts = <0 45 0>;
+			interrupts = <0 45 IRQ_TYPE_LEVEL_HIGH>;
 
 			wakeup-interrupt-controller {
 				compatible = "samsung,exynos4210-wakeup-eint";
 				interrupt-parent = <&gic>;
-				interrupts = <0 32 0>;
+				interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
 		pinctrl_1: pinctrl@13410000 {
 			compatible = "samsung,exynos5420-pinctrl";
 			reg = <0x13410000 0x1000>;
-			interrupts = <0 78 0>;
+			interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_2: pinctrl@14000000 {
 			compatible = "samsung,exynos5420-pinctrl";
 			reg = <0x14000000 0x1000>;
-			interrupts = <0 46 0>;
+			interrupts = <0 46 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_3: pinctrl@14010000 {
 			compatible = "samsung,exynos5420-pinctrl";
 			reg = <0x14010000 0x1000>;
-			interrupts = <0 50 0>;
+			interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_4: pinctrl@03860000 {
 			compatible = "samsung,exynos5420-pinctrl";
 			reg = <0x03860000 0x1000>;
-			interrupts = <0 47 0>;
+			interrupts = <0 47 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		amba {
@@ -363,7 +363,7 @@
 			adma: adma@03880000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x03880000 0x1000>;
-				interrupts = <0 110 0>;
+				interrupts = <0 110 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock_audss EXYNOS_ADMA>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -374,7 +374,7 @@
 			pdma0: pdma@121A0000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x121A0000 0x1000>;
-				interrupts = <0 34 0>;
+				interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_PDMA0>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -385,7 +385,7 @@
 			pdma1: pdma@121B0000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x121B0000 0x1000>;
-				interrupts = <0 35 0>;
+				interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_PDMA1>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -396,7 +396,7 @@
 			mdma0: mdma@10800000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x10800000 0x1000>;
-				interrupts = <0 33 0>;
+				interrupts = <0 33 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_MDMA0>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -407,7 +407,7 @@
 			mdma1: mdma@11C10000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x11C10000 0x1000>;
-				interrupts = <0 124 0>;
+				interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock CLK_MDMA1>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -479,7 +479,7 @@
 		spi_0: spi@12d20000 {
 			compatible = "samsung,exynos4210-spi";
 			reg = <0x12d20000 0x100>;
-			interrupts = <0 68 0>;
+			interrupts = <0 68 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma0 5
 				&pdma0 4>;
 			dma-names = "tx", "rx";
@@ -495,7 +495,7 @@
 		spi_1: spi@12d30000 {
 			compatible = "samsung,exynos4210-spi";
 			reg = <0x12d30000 0x100>;
-			interrupts = <0 69 0>;
+			interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma1 5
 				&pdma1 4>;
 			dma-names = "tx", "rx";
@@ -511,7 +511,7 @@
 		spi_2: spi@12d40000 {
 			compatible = "samsung,exynos4210-spi";
 			reg = <0x12d40000 0x100>;
-			interrupts = <0 70 0>;
+			interrupts = <0 70 IRQ_TYPE_LEVEL_HIGH>;
 			dmas = <&pdma0 7
 				&pdma0 6>;
 			dma-names = "tx", "rx";
@@ -539,7 +539,7 @@
 		dsi@14500000 {
 			compatible = "samsung,exynos5410-mipi-dsi";
 			reg = <0x14500000 0x10000>;
-			interrupts = <0 82 0>;
+			interrupts = <0 82 IRQ_TYPE_LEVEL_HIGH>;
 			phys = <&mipi_phy 1>;
 			phy-names = "dsim";
 			clocks = <&clock CLK_DSIM1>, <&clock CLK_SCLK_MIPI1>;
@@ -552,7 +552,7 @@
 		adc: adc@12D10000 {
 			compatible = "samsung,exynos-adc-v2";
 			reg = <0x12D10000 0x100>;
-			interrupts = <0 106 0>;
+			interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TSADC>;
 			clock-names = "adc";
 			#io-channel-cells = <1>;
@@ -564,7 +564,7 @@
 		hsi2c_8: i2c@12E00000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12E00000 0x1000>;
-			interrupts = <0 87 0>;
+			interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -577,7 +577,7 @@
 		hsi2c_9: i2c@12E10000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12E10000 0x1000>;
-			interrupts = <0 88 0>;
+			interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -590,7 +590,7 @@
 		hsi2c_10: i2c@12E20000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12E20000 0x1000>;
-			interrupts = <0 203 0>;
+			interrupts = <0 203 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -603,7 +603,7 @@
 		hdmi: hdmi@14530000 {
 			compatible = "samsung,exynos5420-hdmi";
 			reg = <0x14530000 0x70000>;
-			interrupts = <0 95 0>;
+			interrupts = <0 95 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_HDMI>, <&clock CLK_SCLK_HDMI>,
 				 <&clock CLK_DOUT_PIXEL>, <&clock CLK_SCLK_HDMIPHY>,
 				 <&clock CLK_MOUT_HDMI>;
@@ -622,7 +622,7 @@
 		mixer: mixer@14450000 {
 			compatible = "samsung,exynos5420-mixer";
 			reg = <0x14450000 0x10000>;
-			interrupts = <0 94 0>;
+			interrupts = <0 94 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_MIXER>, <&clock CLK_HDMI>,
 				 <&clock CLK_SCLK_HDMI>;
 			clock-names = "mixer", "hdmi", "sclk_hdmi";
@@ -633,7 +633,7 @@
 		rotator: rotator@11C00000 {
 			compatible = "samsung,exynos5250-rotator";
 			reg = <0x11C00000 0x64>;
-			interrupts = <0 84 0>;
+			interrupts = <0 84 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_ROTATOR>;
 			clock-names = "rotator";
 			iommus = <&sysmmu_rotator>;
@@ -642,7 +642,7 @@
 		gsc_0: video-scaler@13e00000 {
 			compatible = "samsung,exynos5-gsc";
 			reg = <0x13e00000 0x1000>;
-			interrupts = <0 85 0>;
+			interrupts = <0 85 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_GSCL0>;
 			clock-names = "gscl";
 			power-domains = <&gsc_pd>;
@@ -652,7 +652,7 @@
 		gsc_1: video-scaler@13e10000 {
 			compatible = "samsung,exynos5-gsc";
 			reg = <0x13e10000 0x1000>;
-			interrupts = <0 86 0>;
+			interrupts = <0 86 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_GSCL1>;
 			clock-names = "gscl";
 			power-domains = <&gsc_pd>;
@@ -662,7 +662,7 @@
 		jpeg_0: jpeg@11F50000 {
 			compatible = "samsung,exynos5420-jpeg";
 			reg = <0x11F50000 0x1000>;
-			interrupts = <0 89 0>;
+			interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "jpeg";
 			clocks = <&clock CLK_JPEG>;
 			iommus = <&sysmmu_jpeg0>;
@@ -671,7 +671,7 @@
 		jpeg_1: jpeg@11F60000 {
 			compatible = "samsung,exynos5420-jpeg";
 			reg = <0x11F60000 0x1000>;
-			interrupts = <0 168 0>;
+			interrupts = <0 168 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "jpeg";
 			clocks = <&clock CLK_JPEG2>;
 			iommus = <&sysmmu_jpeg1>;
@@ -691,7 +691,7 @@
 		tmu_cpu0: tmu@10060000 {
 			compatible = "samsung,exynos5420-tmu";
 			reg = <0x10060000 0x100>;
-			interrupts = <0 65 0>;
+			interrupts = <0 65 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -700,7 +700,7 @@
 		tmu_cpu1: tmu@10064000 {
 			compatible = "samsung,exynos5420-tmu";
 			reg = <0x10064000 0x100>;
-			interrupts = <0 183 0>;
+			interrupts = <0 183 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>;
 			clock-names = "tmu_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -709,7 +709,7 @@
 		tmu_cpu2: tmu@10068000 {
 			compatible = "samsung,exynos5420-tmu-ext-triminfo";
 			reg = <0x10068000 0x100>, <0x1006c000 0x4>;
-			interrupts = <0 184 0>;
+			interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>, <&clock CLK_TMU>;
 			clock-names = "tmu_apbif", "tmu_triminfo_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -718,7 +718,7 @@
 		tmu_cpu3: tmu@1006c000 {
 			compatible = "samsung,exynos5420-tmu-ext-triminfo";
 			reg = <0x1006c000 0x100>, <0x100a0000 0x4>;
-			interrupts = <0 185 0>;
+			interrupts = <0 185 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU>, <&clock CLK_TMU_GPU>;
 			clock-names = "tmu_apbif", "tmu_triminfo_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -727,7 +727,7 @@
 		tmu_gpu: tmu@100a0000 {
 			compatible = "samsung,exynos5420-tmu-ext-triminfo";
 			reg = <0x100a0000 0x100>, <0x10068000 0x4>;
-			interrupts = <0 215 0>;
+			interrupts = <0 215 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock CLK_TMU_GPU>, <&clock CLK_TMU>;
 			clock-names = "tmu_apbif", "tmu_triminfo_apbif";
 			#include "exynos4412-tmu-sensor-conf.dtsi"
@@ -799,7 +799,7 @@
 		sysmmu_scaler1r: sysmmu@0x12890000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x12890000 0x1000>;
-			interrupts = <0 186 0>;
+			interrupts = <0 186 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "sysmmu", "master";
 			clocks = <&clock CLK_SMMU_MSCL1>, <&clock CLK_MSCL1>;
 			#iommu-cells = <0>;
@@ -808,7 +808,7 @@
 		sysmmu_scaler2r: sysmmu@0x128A0000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x128A0000 0x1000>;
-			interrupts = <0 188 0>;
+			interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "sysmmu", "master";
 			clocks = <&clock CLK_SMMU_MSCL2>, <&clock CLK_MSCL2>;
 			#iommu-cells = <0>;
@@ -867,7 +867,7 @@
 		sysmmu_jpeg1: sysmmu@0x11F20000 {
 			compatible = "samsung,exynos-sysmmu";
 			reg = <0x11F20000 0x1000>;
-			interrupts = <0 169 0>;
+			interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "sysmmu", "master";
 			clocks = <&clock CLK_SMMU_JPEG2>, <&clock CLK_JPEG2>;
 			#iommu-cells = <0>;
@@ -1445,7 +1445,7 @@
 };
 
 &usbdrd_dwc3_1 {
-	interrupts = <GIC_SPI 73 0>;
+	interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &usbdrd_phy1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5420-peach-pit.dts	2017-02-12 16:03:20.000000000 -0500
@@ -697,6 +697,7 @@
 	status = "okay";
 };
 
+/* eMMC flash */
 &mmc_0 {
 	status = "okay";
 	num-slots = <1>;
@@ -714,6 +715,7 @@
 	bus-width = <8>;
 };
 
+/* WiFi SDIO module */
 &mmc_1 {
 	status = "okay";
 	num-slots = <1>;
@@ -733,6 +735,7 @@
 	vqmmc-supply = <&buck10_reg>;
 };
 
+/* uSD card */
 &mmc_2 {
 	status = "okay";
 	num-slots = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5422-odroidxu3-common.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -147,6 +147,11 @@
 	};
 };
 
+&adc {
+	vdd-supply = <&ldo4_reg>;
+	status = "okay";
+};
+
 &bus_wcore {
 	devfreq-events = <&nocp_mem0_0>, <&nocp_mem0_1>,
 			<&nocp_mem1_0>, <&nocp_mem1_1>;
@@ -293,6 +298,12 @@
 				regulator-max-microvolt = <1800000>;
 			};
 
+			ldo4_reg: LDO4 {
+				regulator-name = "vdd_adc";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
 			ldo5_reg: LDO5 {
 				regulator-name = "vdd_ldo5";
 				regulator-min-microvolt = <1800000>;
@@ -499,7 +510,6 @@
 &mmc_0 {
 	status = "okay";
 	mmc-pwrseq = <&emmc_pwrseq>;
-	cd-gpios = <&gpc0 2 GPIO_ACTIVE_LOW>;
 	card-detect-delay = <200>;
 	samsung,dw-mshc-ciu-div = <3>;
 	samsung,dw-mshc-sdr-timing = <0 4>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5440.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5440.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5440.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5440.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,8 @@
 */
 
 #include <dt-bindings/clock/exynos5440.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
 	compatible = "samsung,exynos5440", "samsung,exynos5";
@@ -41,7 +43,8 @@
 			<0x2E2000 0x1000>,
 			<0x2E4000 0x2000>,
 			<0x2E6000 0x2000>;
-		interrupts = <1 9 0xf04>;
+		interrupts = <GIC_PPI 9
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 	};
 
 	cpus {
@@ -72,26 +75,26 @@
 
 	arm-pmu {
 		compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu";
-		interrupts = <0 52 4>,
-			     <0 53 4>,
-			     <0 54 4>,
-			     <0 55 4>;
+		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	timer {
 		compatible = "arm,cortex-a15-timer",
 			     "arm,armv7-timer";
-		interrupts = <1 13 0xf08>,
-			     <1 14 0xf08>,
-			     <1 11 0xf08>,
-			     <1 10 0xf08>;
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
 		clock-frequency = <50000000>;
 	};
 
 	cpufreq@160000 {
 		compatible = "samsung,exynos5440-cpufreq";
 		reg = <0x160000 0x1000>;
-		interrupts = <0 57 0>;
+		interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
 		operating-points = <
 				/* KHz	  uV */
 				1500000 1100000
@@ -108,7 +111,7 @@
 	serial_0: serial@B0000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xB0000 0x1000>;
-		interrupts = <0 2 0>;
+		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_B_125>, <&clock CLK_B_125>;
 		clock-names = "uart", "clk_uart_baud0";
 	};
@@ -116,7 +119,7 @@
 	serial_1: serial@C0000 {
 		compatible = "samsung,exynos4210-uart";
 		reg = <0xC0000 0x1000>;
-		interrupts = <0 3 0>;
+		interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_B_125>, <&clock CLK_B_125>;
 		clock-names = "uart", "clk_uart_baud0";
 	};
@@ -124,7 +127,7 @@
 	spi_0: spi@D0000 {
 		compatible = "samsung,exynos5440-spi";
 		reg = <0xD0000 0x100>;
-		interrupts = <0 4 0>;
+		interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		samsung,spi-src-clk = <0>;
@@ -136,8 +139,14 @@
 	pin_ctrl: pinctrl@E0000 {
 		compatible = "samsung,exynos5440-pinctrl";
 		reg = <0xE0000 0x1000>;
-		interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>,
-			     <0 41 0>, <0 42 0>, <0 43 0>, <0 44 0>;
+		interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		#gpio-cells = <2>;
@@ -162,7 +171,7 @@
 	i2c@F0000 {
 		compatible = "samsung,exynos5440-i2c";
 		reg = <0xF0000 0x1000>;
-		interrupts = <0 5 0>;
+		interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&clock CLK_B_125>;
@@ -172,7 +181,7 @@
 	i2c@100000 {
 		compatible = "samsung,exynos5440-i2c";
 		reg = <0x100000 0x1000>;
-		interrupts = <0 6 0>;
+		interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clocks = <&clock CLK_B_125>;
@@ -182,16 +191,16 @@
 	watchdog@110000 {
 		compatible = "samsung,s3c2410-wdt";
 		reg = <0x110000 0x1000>;
-		interrupts = <0 1 0>;
+		interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_B_125>;
 		clock-names = "watchdog";
 	};
 
 	gmac: ethernet@00230000 {
-		compatible = "snps,dwmac-3.70a";
+		compatible = "snps,dwmac-3.70a", "snps,dwmac";
 		reg = <0x00230000 0x8000>;
 		interrupt-parent = <&gic>;
-		interrupts = <0 31 4>;
+		interrupts = <GIC_SPI 31 4>;
 		interrupt-names = "macirq";
 		phy-mode = "sgmii";
 		clocks = <&clock CLK_GMAC0>;
@@ -209,7 +218,8 @@
 	rtc@130000 {
 		compatible = "samsung,s3c6410-rtc";
 		reg = <0x130000 0x1000>;
-		interrupts = <0 17 0>, <0 16 0>;
+		interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_B_125>;
 		clock-names = "rtc";
 	};
@@ -217,7 +227,7 @@
 	tmuctrl_0: tmuctrl@160118 {
 		compatible = "samsung,exynos5440-tmu";
 		reg = <0x160118 0x230>, <0x160368 0x10>;
-		interrupts = <0 58 0>;
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_B_125>;
 		clock-names = "tmu_apbif";
 		#include "exynos5440-tmu-sensor-conf.dtsi"
@@ -226,7 +236,7 @@
 	tmuctrl_1: tmuctrl@16011C {
 		compatible = "samsung,exynos5440-tmu";
 		reg = <0x16011C 0x230>, <0x160368 0x10>;
-		interrupts = <0 58 0>;
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_B_125>;
 		clock-names = "tmu_apbif";
 		#include "exynos5440-tmu-sensor-conf.dtsi"
@@ -235,7 +245,7 @@
 	tmuctrl_2: tmuctrl@160120 {
 		compatible = "samsung,exynos5440-tmu";
 		reg = <0x160120 0x230>, <0x160368 0x10>;
-		interrupts = <0 58 0>;
+		interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_B_125>;
 		clock-names = "tmu_apbif";
 		#include "exynos5440-tmu-sensor-conf.dtsi"
@@ -259,7 +269,7 @@
 	sata@210000 {
 		compatible = "snps,exynos5440-ahci";
 		reg = <0x210000 0x10000>;
-		interrupts = <0 30 0>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_SATA>;
 		clock-names = "sata";
 	};
@@ -267,7 +277,7 @@
 	ohci@220000 {
 		compatible = "samsung,exynos5440-ohci";
 		reg = <0x220000 0x1000>;
-		interrupts = <0 29 0>;
+		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_USB>;
 		clock-names = "usbhost";
 	};
@@ -275,7 +285,7 @@
 	ehci@221000 {
 		compatible = "samsung,exynos5440-ehci";
 		reg = <0x221000 0x1000>;
-		interrupts = <0 29 0>;
+		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_USB>;
 		clock-names = "usbhost";
 	};
@@ -285,7 +295,9 @@
 		reg = <0x290000 0x1000
 			0x270000 0x1000
 			0x271000 0x40>;
-		interrupts = <0 20 0>, <0 21 0>, <0 22 0>;
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_PR0_250_O>, <&clock CLK_PB0_250_O>;
 		clock-names = "pcie", "pcie_bus";
 		#address-cells = <3>;
@@ -306,7 +318,9 @@
 		reg = <0x2a0000 0x1000
 			0x272000 0x1000
 			0x271040 0x40>;
-		interrupts = <0 23 0>, <0 24 0>, <0 25 0>;
+		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&clock CLK_PR1_250_O>, <&clock CLK_PB0_250_O>;
 		clock-names = "pcie", "pcie_bus";
 		#address-cells = <3>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos54xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos54xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos54xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos54xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -62,34 +62,34 @@
 						<1 &combiner 23 4>,
 						<2 &combiner 25 2>,
 						<3 &combiner 25 3>,
-						<4 &gic 0 120 0>,
-						<5 &gic 0 121 0>,
-						<6 &gic 0 122 0>,
-						<7 &gic 0 123 0>,
-						<8 &gic 0 128 0>,
-						<9 &gic 0 129 0>,
-						<10 &gic 0 130 0>,
-						<11 &gic 0 131 0>;
+						<4 &gic 0 120 IRQ_TYPE_LEVEL_HIGH>,
+						<5 &gic 0 121 IRQ_TYPE_LEVEL_HIGH>,
+						<6 &gic 0 122 IRQ_TYPE_LEVEL_HIGH>,
+						<7 &gic 0 123 IRQ_TYPE_LEVEL_HIGH>,
+						<8 &gic 0 128 IRQ_TYPE_LEVEL_HIGH>,
+						<9 &gic 0 129 IRQ_TYPE_LEVEL_HIGH>,
+						<10 &gic 0 130 IRQ_TYPE_LEVEL_HIGH>,
+						<11 &gic 0 131 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
 		watchdog: watchdog@101d0000 {
 			compatible = "samsung,exynos5420-wdt";
 			reg = <0x101d0000 0x100>;
-			interrupts = <0 42 0>;
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		sss: sss@10830000 {
 			compatible = "samsung,exynos4210-secss";
 			reg = <0x10830000 0x300>;
-			interrupts = <0 112 0>;
+			interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		/* i2c_0-3 are defined in exynos5.dtsi */
 		hsi2c_4: i2c@12ca0000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12ca0000 0x1000>;
-			interrupts = <0 60 0>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			status = "disabled";
@@ -98,7 +98,7 @@
 		hsi2c_5: i2c@12cb0000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12cb0000 0x1000>;
-			interrupts = <0 61 0>;
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			status = "disabled";
@@ -107,7 +107,7 @@
 		hsi2c_6: i2c@12cc0000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12cc0000 0x1000>;
-			interrupts = <0 62 0>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			status = "disabled";
@@ -116,7 +116,7 @@
 		hsi2c_7: i2c@12cd0000 {
 			compatible = "samsung,exynos5250-hsi2c";
 			reg = <0x12cd0000 0x1000>;
-			interrupts = <0 63 0>;
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			status = "disabled";
@@ -131,7 +131,7 @@
 			usbdrd_dwc3_0: dwc3@12000000 {
 				compatible = "snps,dwc3";
 				reg = <0x12000000 0x10000>;
-				interrupts = <0 72 0>;
+				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&usbdrd_phy0 0>, <&usbdrd_phy0 1>;
 				phy-names = "usb2-phy", "usb3-phy";
 			};
@@ -166,7 +166,7 @@
 		usbhost2: usb@12110000 {
 			compatible = "samsung,exynos4210-ehci";
 			reg = <0x12110000 0x100>;
-			interrupts = <0 71 0>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -179,7 +179,7 @@
 		usbhost1: usb@12120000 {
 			compatible = "samsung,exynos4210-ohci";
 			reg = <0x12120000 0x100>;
-			interrupts = <0 71 0>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 
 			#address-cells = <1>;
 			#size-cells = <0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5800-peach-pi.dts	2017-02-12 16:03:20.000000000 -0500
@@ -665,6 +665,7 @@
 	status = "okay";
 };
 
+/* eMMC flash */
 &mmc_0 {
 	status = "okay";
 	num-slots = <1>;
@@ -683,6 +684,7 @@
 	bus-width = <8>;
 };
 
+/* WiFi SDIO module */
 &mmc_1 {
 	status = "okay";
 	num-slots = <1>;
@@ -702,6 +704,7 @@
 	vqmmc-supply = <&buck10_reg>;
 };
 
+/* uSD card */
 &mmc_2 {
 	status = "okay";
 	num-slots = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/exynos5.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/exynos5.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 #include "exynos-syscon-restart.dtsi"
 
 / {
@@ -53,14 +55,38 @@
 			interrupt-controller;
 			samsung,combiner-nr = <32>;
 			reg = <0x10440000 0x1000>;
-			interrupts =	<0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-					<0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
-					<0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-					<0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
-					<0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
+			interrupts = <0 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 1 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 3 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 4 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 5 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 6 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 7 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 8 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 9 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 10 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 11 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 12 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 14 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 15 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 16 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 17 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 18 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 19 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 20 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 21 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 22 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 23 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 24 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 25 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 26 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 27 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 28 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 29 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 30 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 31 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		gic: interrupt-controller@10481000 {
@@ -71,7 +97,8 @@
 				<0x10482000 0x1000>,
 				<0x10484000 0x2000>,
 				<0x10486000 0x2000>;
-			interrupts = <1 9 0xf04>;
+			interrupts = <GIC_PPI 9
+					(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
 		sysreg_system_controller: syscon@10050000 {
@@ -82,31 +109,31 @@
 		serial_0: serial@12C00000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C00000 0x100>;
-			interrupts = <0 51 0>;
+			interrupts = <0 51 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		serial_1: serial@12C10000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C10000 0x100>;
-			interrupts = <0 52 0>;
+			interrupts = <0 52 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		serial_2: serial@12C20000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C20000 0x100>;
-			interrupts = <0 53 0>;
+			interrupts = <0 53 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		serial_3: serial@12C30000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x12C30000 0x100>;
-			interrupts = <0 54 0>;
+			interrupts = <0 54 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		i2c_0: i2c@12C60000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12C60000 0x100>;
-			interrupts = <0 56 0>;
+			interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			samsung,sysreg-phandle = <&sysreg_system_controller>;
@@ -116,7 +143,7 @@
 		i2c_1: i2c@12C70000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12C70000 0x100>;
-			interrupts = <0 57 0>;
+			interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			samsung,sysreg-phandle = <&sysreg_system_controller>;
@@ -126,7 +153,7 @@
 		i2c_2: i2c@12C80000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12C80000 0x100>;
-			interrupts = <0 58 0>;
+			interrupts = <0 58 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			samsung,sysreg-phandle = <&sysreg_system_controller>;
@@ -136,7 +163,7 @@
 		i2c_3: i2c@12C90000 {
 			compatible = "samsung,s3c2440-i2c";
 			reg = <0x12C90000 0x100>;
-			interrupts = <0 59 0>;
+			interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			samsung,sysreg-phandle = <&sysreg_system_controller>;
@@ -153,7 +180,8 @@
 		rtc: rtc@101E0000 {
 			compatible = "samsung,s3c6410-rtc";
 			reg = <0x101E0000 0x100>;
-			interrupts = <0 43 0>, <0 44 0>;
+			interrupts = <0 43 IRQ_TYPE_LEVEL_HIGH>,
+				     <0 44 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/hi3620.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/hi3620.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/hi3620.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/hi3620.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -11,10 +11,12 @@
  * publishhed by the Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
 #include <dt-bindings/clock/hi3620-clock.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	aliases {
 		serial0 = &uart0;
 		serial1 = &uart1;
@@ -537,6 +539,7 @@
 			reg = <0x803000 0x188>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#pinctrl-cells = <1>;
 			#gpio-range-cells = <3>;
 			ranges;
 
@@ -558,6 +561,7 @@
 			reg = <0x803800 0x2dc>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#pinctrl-cells = <1>;
 			ranges;
 
 			pinctrl-single,register-width = <32>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/hip01.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/hip01.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/hip01.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/hip01.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -11,8 +11,6 @@
  * published by the Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
-
 / {
 	interrupt-parent = <&gic>;
 	#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/hisi-x5hd2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -7,10 +7,12 @@
  * publishhed by the Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
 #include <dt-bindings/clock/hix5hd2-clock.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	aliases {
 		serial0 = &uart0;
 	};
@@ -436,18 +438,20 @@
 		};
 
 		gmac0: ethernet@1840000 {
-			compatible = "hisilicon,hix5hd2-gmac";
+			compatible = "hisilicon,hix5hd2-gmac", "hisilicon,hisi-gmac-v1";
 			reg = <0x1840000 0x1000>,<0x184300c 0x4>;
 			interrupts = <0 71 4>;
 			clocks = <&clock HIX5HD2_MAC0_CLK>;
+			clock-names = "mac_core";
 			status = "disabled";
 		};
 
 		gmac1: ethernet@1841000 {
-			compatible = "hisilicon,hix5hd2-gmac";
+			compatible = "hisilicon,hix5hd2-gmac", "hisilicon,hisi-gmac-v1";
 			reg = <0x1841000 0x1000>,<0x1843010 0x4>;
 			interrupts = <0 72 4>;
 			clocks = <&clock HIX5HD2_MAC1_CLK>;
+			clock-names = "mac_core";
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx1.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx1.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx1.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx1.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
 #include "imx1-pinfunc.h"
 
 #include <dt-bindings/clock/imx1-clock.h>
@@ -17,6 +16,17 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx23.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx23.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx23.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx23.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -9,11 +9,21 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
 #include "imx23-pinfunc.h"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	interrupt-parent = <&icoll>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
 
 	aliases {
 		gpio0 = &gpio0;
@@ -464,7 +474,7 @@
 				reg = <0x80038000 0x2000>;
 				status = "disabled";
 			};
-                };
+		};
 
 		apbx@80040000 {
 			compatible = "simple-bus";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx25.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx25.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx25.dtsi	2016-12-11 17:43:07.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx25.dtsi	2017-02-12 17:27:04.000000000 -0500
@@ -9,10 +9,20 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
 #include "imx25-pinfunc.h"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		gpio0 = &gpio1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx27.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx27.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx27.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx27.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
 #include "imx27-pinfunc.h"
 
 #include <dt-bindings/clock/imx27-clock.h>
@@ -18,6 +17,17 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		gpio0 = &gpio1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx28.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx28.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx28.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx28.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -10,11 +10,21 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
-#include "skeleton.dtsi"
 #include "imx28-pinfunc.h"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	interrupt-parent = <&icoll>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
 
 	aliases {
 		ethernet0 = &mac0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx28-m28.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx28-m28.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx28-m28.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx28-m28.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -12,8 +12,8 @@
 #include "imx28.dtsi"
 
 / {
-	model = "DENX M28";
-	compatible = "denx,m28", "fsl,imx28";
+	model = "Aries/DENX M28";
+	compatible = "aries,m28", "denx,m28", "fsl,imx28";
 
 	memory {
 		reg = <0x40000000 0x08000000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx28-m28evk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx28-m28evk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx28-m28evk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx28-m28evk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -13,8 +13,8 @@
 #include "imx28-m28.dtsi"
 
 / {
-	model = "DENX M28EVK";
-	compatible = "denx,m28evk", "fsl,imx28";
+	model = "Aries/DENX M28EVK";
+	compatible = "aries,m28evk", "denx,m28evk", "fsl,imx28";
 
 	apb@80000000 {
 		apbh@80000000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx31.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx31.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx31.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx31.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -9,9 +9,18 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
-
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		serial0 = &uart1;
 		serial1 = &uart2;
@@ -30,11 +39,11 @@
 		};
 	};
 
-	avic: avic-interrupt-controller@60000000 {
+	avic: interrupt-controller@68000000 {
 		compatible = "fsl,imx31-avic", "fsl,avic";
 		interrupt-controller;
 		#interrupt-cells = <1>;
-		reg = <0x60000000 0x100000>;
+		reg = <0x68000000 0x100000>;
 	};
 
 	soc {
@@ -118,13 +127,6 @@
 				interrupts = <19>;
 				clocks = <&clks 25>;
 			};
-
-			clks: ccm@53f80000{
-				compatible = "fsl,imx31-ccm";
-				reg = <0x53f80000 0x4000>;
-				interrupts = <0 31 0x04 0 53 0x04>;
-				#clock-cells = <1>;
-			};
 		};
 
 		aips@53f00000 { /* AIPS2 */
@@ -134,6 +136,13 @@
 			reg = <0x53f00000 0x100000>;
 			ranges;
 
+			clks: ccm@53f80000{
+				compatible = "fsl,imx31-ccm";
+				reg = <0x53f80000 0x4000>;
+				interrupts = <31>, <53>;
+				#clock-cells = <1>;
+			};
+
 			gpt: timer@53f90000 {
 				compatible = "fsl,imx31-gpt";
 				reg = <0x53f90000 0x4000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx35.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx35.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx35.dtsi	2016-12-11 17:43:10.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx35.dtsi	2017-02-12 17:27:07.000000000 -0500
@@ -8,10 +8,20 @@
  * Free Software Foundation.
  */
 
-#include "skeleton.dtsi"
 #include "imx35-pinfunc.h"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		gpio0 = &gpio1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx50.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx50.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx50.dtsi	2016-12-11 17:43:12.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx50.dtsi	2017-02-12 17:27:09.000000000 -0500
@@ -11,11 +11,21 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
 #include "imx50-pinfunc.h"
 #include <dt-bindings/clock/imx5-clock.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		gpio0 = &gpio1;
@@ -103,8 +113,8 @@
 					reg = <0x50004000 0x4000>;
 					interrupts = <1>;
 					clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC1_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC1_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -115,8 +125,8 @@
 					reg = <0x50008000 0x4000>;
 					interrupts = <2>;
 					clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC2_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC2_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -127,7 +137,7 @@
 					reg = <0x5000c000 0x4000>;
 					interrupts = <33>;
 					clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
-					         <&clks IMX5_CLK_UART3_PER_GATE>;
+						 <&clks IMX5_CLK_UART3_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -139,7 +149,7 @@
 					reg = <0x50010000 0x4000>;
 					interrupts = <36>;
 					clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
-					         <&clks IMX5_CLK_ECSPI1_PER_GATE>;
+						 <&clks IMX5_CLK_ECSPI1_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -164,8 +174,8 @@
 					reg = <0x50020000 0x4000>;
 					interrupts = <3>;
 					clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC3_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC3_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -176,8 +186,8 @@
 					reg = <0x50024000 0x4000>;
 					interrupts = <4>;
 					clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC4_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC4_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -279,7 +289,7 @@
 				reg = <0x53fa0000 0x4000>;
 				interrupts = <39>;
 				clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
-				         <&clks IMX5_CLK_GPT_HF_GATE>;
+					 <&clks IMX5_CLK_GPT_HF_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -298,7 +308,7 @@
 				compatible = "fsl,imx50-pwm", "fsl,imx27-pwm";
 				reg = <0x53fb4000 0x4000>;
 				clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
-				         <&clks IMX5_CLK_PWM1_HF_GATE>;
+					 <&clks IMX5_CLK_PWM1_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <61>;
 			};
@@ -308,7 +318,7 @@
 				compatible = "fsl,imx50-pwm", "fsl,imx27-pwm";
 				reg = <0x53fb8000 0x4000>;
 				clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
-				         <&clks IMX5_CLK_PWM2_HF_GATE>;
+					 <&clks IMX5_CLK_PWM2_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <94>;
 			};
@@ -318,7 +328,7 @@
 				reg = <0x53fbc000 0x4000>;
 				interrupts = <31>;
 				clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
-				         <&clks IMX5_CLK_UART1_PER_GATE>;
+					 <&clks IMX5_CLK_UART1_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -328,7 +338,7 @@
 				reg = <0x53fc0000 0x4000>;
 				interrupts = <32>;
 				clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
-				         <&clks IMX5_CLK_UART2_PER_GATE>;
+					 <&clks IMX5_CLK_UART2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -383,7 +393,7 @@
 				reg = <0x53ff0000 0x4000>;
 				interrupts = <13>;
 				clocks = <&clks IMX5_CLK_UART4_IPG_GATE>,
-				         <&clks IMX5_CLK_UART4_PER_GATE>;
+					 <&clks IMX5_CLK_UART4_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -401,7 +411,7 @@
 				reg = <0x63f90000 0x4000>;
 				interrupts = <86>;
 				clocks = <&clks IMX5_CLK_UART5_IPG_GATE>,
-				         <&clks IMX5_CLK_UART5_PER_GATE>;
+					 <&clks IMX5_CLK_UART5_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -420,7 +430,7 @@
 				reg = <0x63fac000 0x4000>;
 				interrupts = <37>;
 				clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
-				         <&clks IMX5_CLK_ECSPI2_PER_GATE>;
+					 <&clks IMX5_CLK_ECSPI2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -430,7 +440,7 @@
 				reg = <0x63fb0000 0x4000>;
 				interrupts = <6>;
 				clocks = <&clks IMX5_CLK_SDMA_GATE>,
-				         <&clks IMX5_CLK_SDMA_GATE>;
+					 <&clks IMX5_CLK_SDMA_GATE>;
 				clock-names = "ipg", "ahb";
 				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
 			};
@@ -442,7 +452,7 @@
 				reg = <0x63fc0000 0x4000>;
 				interrupts = <38>;
 				clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
-				         <&clks IMX5_CLK_CSPI_IPG_GATE>;
+					 <&clks IMX5_CLK_CSPI_IPG_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -492,8 +502,8 @@
 				reg = <0x63fec000 0x4000>;
 				interrupts = <87>;
 				clocks = <&clks IMX5_CLK_FEC_GATE>,
-				         <&clks IMX5_CLK_FEC_GATE>,
-				         <&clks IMX5_CLK_FEC_GATE>;
+					 <&clks IMX5_CLK_FEC_GATE>,
+					 <&clks IMX5_CLK_FEC_GATE>;
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx51.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx51.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx51.dtsi	2016-12-11 17:43:15.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx51.dtsi	2017-02-12 17:27:12.000000000 -0500
@@ -10,7 +10,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
 #include "imx51-pinfunc.h"
 #include <dt-bindings/clock/imx5-clock.h>
 #include <dt-bindings/gpio/gpio.h>
@@ -18,6 +17,17 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		gpio0 = &gpio1;
@@ -130,8 +140,8 @@
 			reg = <0x40000000 0x20000000>;
 			interrupts = <11 10>;
 			clocks = <&clks IMX5_CLK_IPU_GATE>,
-			         <&clks IMX5_CLK_IPU_DI0_GATE>,
-			         <&clks IMX5_CLK_IPU_DI1_GATE>;
+				 <&clks IMX5_CLK_IPU_DI0_GATE>,
+				 <&clks IMX5_CLK_IPU_DI1_GATE>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 2>;
 
@@ -169,8 +179,8 @@
 					reg = <0x70004000 0x4000>;
 					interrupts = <1>;
 					clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC1_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC1_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					status = "disabled";
 				};
@@ -180,8 +190,8 @@
 					reg = <0x70008000 0x4000>;
 					interrupts = <2>;
 					clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC2_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC2_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -192,7 +202,7 @@
 					reg = <0x7000c000 0x4000>;
 					interrupts = <33>;
 					clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
-					         <&clks IMX5_CLK_UART3_PER_GATE>;
+						 <&clks IMX5_CLK_UART3_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -204,7 +214,7 @@
 					reg = <0x70010000 0x4000>;
 					interrupts = <36>;
 					clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
-					         <&clks IMX5_CLK_ECSPI1_PER_GATE>;
+						 <&clks IMX5_CLK_ECSPI1_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -229,8 +239,8 @@
 					reg = <0x70020000 0x4000>;
 					interrupts = <3>;
 					clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC3_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC3_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -241,8 +251,8 @@
 					reg = <0x70024000 0x4000>;
 					interrupts = <4>;
 					clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC4_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC4_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -364,7 +374,7 @@
 				reg = <0x73fa0000 0x4000>;
 				interrupts = <39>;
 				clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
-				         <&clks IMX5_CLK_GPT_HF_GATE>;
+					 <&clks IMX5_CLK_GPT_HF_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -378,7 +388,7 @@
 				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
 				reg = <0x73fb4000 0x4000>;
 				clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
-				         <&clks IMX5_CLK_PWM1_HF_GATE>;
+					 <&clks IMX5_CLK_PWM1_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <61>;
 			};
@@ -388,7 +398,7 @@
 				compatible = "fsl,imx51-pwm", "fsl,imx27-pwm";
 				reg = <0x73fb8000 0x4000>;
 				clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
-				         <&clks IMX5_CLK_PWM2_HF_GATE>;
+					 <&clks IMX5_CLK_PWM2_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <94>;
 			};
@@ -398,7 +408,7 @@
 				reg = <0x73fbc000 0x4000>;
 				interrupts = <31>;
 				clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
-				         <&clks IMX5_CLK_UART1_PER_GATE>;
+					 <&clks IMX5_CLK_UART1_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -408,7 +418,7 @@
 				reg = <0x73fc0000 0x4000>;
 				interrupts = <32>;
 				clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
-				         <&clks IMX5_CLK_UART2_PER_GATE>;
+					 <&clks IMX5_CLK_UART2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -456,7 +466,7 @@
 				reg = <0x83fac000 0x4000>;
 				interrupts = <37>;
 				clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
-				         <&clks IMX5_CLK_ECSPI2_PER_GATE>;
+					 <&clks IMX5_CLK_ECSPI2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -466,7 +476,7 @@
 				reg = <0x83fb0000 0x4000>;
 				interrupts = <6>;
 				clocks = <&clks IMX5_CLK_SDMA_GATE>,
-				         <&clks IMX5_CLK_SDMA_GATE>;
+					 <&clks IMX5_CLK_SDMA_GATE>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
@@ -479,7 +489,7 @@
 				reg = <0x83fc0000 0x4000>;
 				interrupts = <38>;
 				clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
-				         <&clks IMX5_CLK_CSPI_IPG_GATE>;
+					 <&clks IMX5_CLK_CSPI_IPG_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -582,8 +592,8 @@
 				reg = <0x83fec000 0x4000>;
 				interrupts = <87>;
 				clocks = <&clks IMX5_CLK_FEC_GATE>,
-				         <&clks IMX5_CLK_FEC_GATE>,
-				         <&clks IMX5_CLK_FEC_GATE>;
+					 <&clks IMX5_CLK_FEC_GATE>,
+					 <&clks IMX5_CLK_FEC_GATE>;
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx53.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx53.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx53.dtsi	2016-12-11 17:43:17.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx53.dtsi	2017-02-12 17:27:15.000000000 -0500
@@ -10,7 +10,6 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include "skeleton.dtsi"
 #include "imx53-pinfunc.h"
 #include <dt-bindings/clock/imx5-clock.h>
 #include <dt-bindings/gpio/gpio.h>
@@ -18,6 +17,17 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		gpio0 = &gpio1;
@@ -131,8 +141,8 @@
 			reg = <0x18000000 0x08000000>;
 			interrupts = <11 10>;
 			clocks = <&clks IMX5_CLK_IPU_GATE>,
-			         <&clks IMX5_CLK_IPU_DI0_GATE>,
-			         <&clks IMX5_CLK_IPU_DI1_GATE>;
+				 <&clks IMX5_CLK_IPU_DI0_GATE>,
+				 <&clks IMX5_CLK_IPU_DI1_GATE>;
 			clock-names = "bus", "di0", "di1";
 			resets = <&src 2>;
 
@@ -199,8 +209,8 @@
 					reg = <0x50004000 0x4000>;
 					interrupts = <1>;
 					clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC1_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC1_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -211,8 +221,8 @@
 					reg = <0x50008000 0x4000>;
 					interrupts = <2>;
 					clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC2_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC2_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -223,7 +233,7 @@
 					reg = <0x5000c000 0x4000>;
 					interrupts = <33>;
 					clocks = <&clks IMX5_CLK_UART3_IPG_GATE>,
-					         <&clks IMX5_CLK_UART3_PER_GATE>;
+						 <&clks IMX5_CLK_UART3_PER_GATE>;
 					clock-names = "ipg", "per";
 					dmas = <&sdma 42 4 0>, <&sdma 43 4 0>;
 					dma-names = "rx", "tx";
@@ -237,7 +247,7 @@
 					reg = <0x50010000 0x4000>;
 					interrupts = <36>;
 					clocks = <&clks IMX5_CLK_ECSPI1_IPG_GATE>,
-					         <&clks IMX5_CLK_ECSPI1_PER_GATE>;
+						 <&clks IMX5_CLK_ECSPI1_PER_GATE>;
 					clock-names = "ipg", "per";
 					status = "disabled";
 				};
@@ -264,8 +274,8 @@
 					reg = <0x50020000 0x4000>;
 					interrupts = <3>;
 					clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC3_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC3_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -276,8 +286,8 @@
 					reg = <0x50024000 0x4000>;
 					interrupts = <4>;
 					clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
-					         <&clks IMX5_CLK_DUMMY>,
-					         <&clks IMX5_CLK_ESDHC4_PER_GATE>;
+						 <&clks IMX5_CLK_DUMMY>,
+						 <&clks IMX5_CLK_ESDHC4_PER_GATE>;
 					clock-names = "ipg", "ahb", "per";
 					bus-width = <4>;
 					status = "disabled";
@@ -419,7 +429,7 @@
 				reg = <0x53fa0000 0x4000>;
 				interrupts = <39>;
 				clocks = <&clks IMX5_CLK_GPT_IPG_GATE>,
-				         <&clks IMX5_CLK_GPT_HF_GATE>;
+					 <&clks IMX5_CLK_GPT_HF_GATE>;
 				clock-names = "ipg", "per";
 			};
 
@@ -440,11 +450,11 @@
 				reg = <0x53fa8008 0x4>;
 				gpr = <&gpr>;
 				clocks = <&clks IMX5_CLK_LDB_DI0_SEL>,
-				         <&clks IMX5_CLK_LDB_DI1_SEL>,
-				         <&clks IMX5_CLK_IPU_DI0_SEL>,
-				         <&clks IMX5_CLK_IPU_DI1_SEL>,
-				         <&clks IMX5_CLK_LDB_DI0_GATE>,
-				         <&clks IMX5_CLK_LDB_DI1_GATE>;
+					 <&clks IMX5_CLK_LDB_DI1_SEL>,
+					 <&clks IMX5_CLK_IPU_DI0_SEL>,
+					 <&clks IMX5_CLK_IPU_DI1_SEL>,
+					 <&clks IMX5_CLK_LDB_DI0_GATE>,
+					 <&clks IMX5_CLK_LDB_DI1_GATE>;
 				clock-names = "di0_pll", "di1_pll",
 					      "di0_sel", "di1_sel",
 					      "di0", "di1";
@@ -486,7 +496,7 @@
 				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
 				reg = <0x53fb4000 0x4000>;
 				clocks = <&clks IMX5_CLK_PWM1_IPG_GATE>,
-				         <&clks IMX5_CLK_PWM1_HF_GATE>;
+					 <&clks IMX5_CLK_PWM1_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <61>;
 			};
@@ -496,7 +506,7 @@
 				compatible = "fsl,imx53-pwm", "fsl,imx27-pwm";
 				reg = <0x53fb8000 0x4000>;
 				clocks = <&clks IMX5_CLK_PWM2_IPG_GATE>,
-				         <&clks IMX5_CLK_PWM2_HF_GATE>;
+					 <&clks IMX5_CLK_PWM2_HF_GATE>;
 				clock-names = "ipg", "per";
 				interrupts = <94>;
 			};
@@ -506,7 +516,7 @@
 				reg = <0x53fbc000 0x4000>;
 				interrupts = <31>;
 				clocks = <&clks IMX5_CLK_UART1_IPG_GATE>,
-				         <&clks IMX5_CLK_UART1_PER_GATE>;
+					 <&clks IMX5_CLK_UART1_PER_GATE>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 18 4 0>, <&sdma 19 4 0>;
 				dma-names = "rx", "tx";
@@ -518,7 +528,7 @@
 				reg = <0x53fc0000 0x4000>;
 				interrupts = <32>;
 				clocks = <&clks IMX5_CLK_UART2_IPG_GATE>,
-				         <&clks IMX5_CLK_UART2_PER_GATE>;
+					 <&clks IMX5_CLK_UART2_PER_GATE>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 12 4 0>, <&sdma 13 4 0>;
 				dma-names = "rx", "tx";
@@ -530,7 +540,7 @@
 				reg = <0x53fc8000 0x4000>;
 				interrupts = <82>;
 				clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>,
-				         <&clks IMX5_CLK_CAN1_SERIAL_GATE>;
+					 <&clks IMX5_CLK_CAN1_SERIAL_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -540,7 +550,7 @@
 				reg = <0x53fcc000 0x4000>;
 				interrupts = <83>;
 				clocks = <&clks IMX5_CLK_CAN2_IPG_GATE>,
-				         <&clks IMX5_CLK_CAN2_SERIAL_GATE>;
+					 <&clks IMX5_CLK_CAN2_SERIAL_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -603,7 +613,7 @@
 				reg = <0x53ff0000 0x4000>;
 				interrupts = <13>;
 				clocks = <&clks IMX5_CLK_UART4_IPG_GATE>,
-				         <&clks IMX5_CLK_UART4_PER_GATE>;
+					 <&clks IMX5_CLK_UART4_PER_GATE>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 2 4 0>, <&sdma 3 4 0>;
 				dma-names = "rx", "tx";
@@ -635,7 +645,7 @@
 				reg = <0x63f90000 0x4000>;
 				interrupts = <86>;
 				clocks = <&clks IMX5_CLK_UART5_IPG_GATE>,
-				         <&clks IMX5_CLK_UART5_PER_GATE>;
+					 <&clks IMX5_CLK_UART5_PER_GATE>;
 				clock-names = "ipg", "per";
 				dmas = <&sdma 16 4 0>, <&sdma 17 4 0>;
 				dma-names = "rx", "tx";
@@ -656,7 +666,7 @@
 				reg = <0x63fac000 0x4000>;
 				interrupts = <37>;
 				clocks = <&clks IMX5_CLK_ECSPI2_IPG_GATE>,
-				         <&clks IMX5_CLK_ECSPI2_PER_GATE>;
+					 <&clks IMX5_CLK_ECSPI2_PER_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -666,7 +676,7 @@
 				reg = <0x63fb0000 0x4000>;
 				interrupts = <6>;
 				clocks = <&clks IMX5_CLK_SDMA_GATE>,
-				         <&clks IMX5_CLK_SDMA_GATE>;
+					 <&clks IMX5_CLK_SDMA_GATE>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "/*(DEBLOBBED)*/";
@@ -679,7 +689,7 @@
 				reg = <0x63fc0000 0x4000>;
 				interrupts = <38>;
 				clocks = <&clks IMX5_CLK_CSPI_IPG_GATE>,
-				         <&clks IMX5_CLK_CSPI_IPG_GATE>;
+					 <&clks IMX5_CLK_CSPI_IPG_GATE>;
 				clock-names = "ipg", "per";
 				status = "disabled";
 			};
@@ -755,8 +765,8 @@
 				reg = <0x63fec000 0x4000>;
 				interrupts = <87>;
 				clocks = <&clks IMX5_CLK_FEC_GATE>,
-				         <&clks IMX5_CLK_FEC_GATE>,
-				         <&clks IMX5_CLK_FEC_GATE>;
+					 <&clks IMX5_CLK_FEC_GATE>,
+					 <&clks IMX5_CLK_FEC_GATE>;
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
@@ -766,7 +776,7 @@
 				reg = <0x63ff0000 0x1000>;
 				interrupts = <92>;
 				clocks = <&clks IMX5_CLK_TVE_GATE>,
-				         <&clks IMX5_CLK_IPU_DI1_SEL>;
+					 <&clks IMX5_CLK_IPU_DI1_SEL>;
 				clock-names = "tve", "di_sel";
 				status = "disabled";
 
@@ -782,7 +792,7 @@
 				reg = <0x63ff4000 0x1000>;
 				interrupts = <9>;
 				clocks = <&clks IMX5_CLK_VPU_REFERENCE_GATE>,
-				         <&clks IMX5_CLK_VPU_GATE>;
+					 <&clks IMX5_CLK_VPU_GATE>;
 				clock-names = "per", "ahb";
 				resets = <&src 1>;
 				iram = <&ocram>;
@@ -793,7 +803,7 @@
 				reg = <0x63ff8000 0x4000>;
 				interrupts = <19 20>;
 				clocks = <&clks IMX5_CLK_SAHARA_IPG_GATE>,
-				         <&clks IMX5_CLK_SAHARA_IPG_GATE>;
+					 <&clks IMX5_CLK_SAHARA_IPG_GATE>;
 				clock-names = "ipg", "ahb";
 			};
 		};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx53-m53.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx53-m53.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx53-m53.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx53-m53.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -12,8 +12,8 @@
 #include "imx53.dtsi"
 
 / {
-	model = "DENX M53";
-	compatible = "denx,imx53-m53", "fsl,imx53";
+	model = "Aries/DENX M53";
+	compatible = "aries,imx53-m53", "denx,imx53-m53", "fsl,imx53";
 
 	memory {
 		reg = <0x70000000 0x20000000>,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx53-m53evk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx53-m53evk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx53-m53evk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx53-m53evk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -13,8 +13,8 @@
 #include "imx53-m53.dtsi"
 
 / {
-	model = "DENX M53EVK";
-	compatible = "denx,imx53-m53evk", "fsl,imx53";
+	model = "Aries/DENX M53EVK";
+	compatible = "aries,imx53-m53evk", "denx,imx53-m53evk", "fsl,imx53";
 
 	display1: display@di1 {
 		compatible = "fsl,imx-parallel-display";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2014-2016 Toradex AG
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "imx6dl.dtsi"
+#include "imx6qdl-colibri.dtsi"
+
+/ {
+	model = "Toradex Colibri iMX6DL/S on Colibri Evaluation Board V3";
+	compatible = "toradex,colibri_imx6dl-eval-v3", "toradex,colibri_imx6dl",
+		     "fsl,imx6dl";
+
+	aliases {
+		i2c0 = &i2c2;
+		i2c1 = &i2c3;
+	};
+
+	aliases {
+		rtc0 = &rtc_i2c;
+		rtc1 = &snvs_rtc;
+	};
+
+	clocks {
+		/* Fixed crystal dedicated to mcp251x */
+		clk16m: clk@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <16000000>;
+			clock-output-names = "clk16m";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
+
+		wakeup {
+			label = "Wake-Up";
+			gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>; /* SODIMM 45 */
+			linux,code = <KEY_WAKEUP>;
+			debounce-interval = <10>;
+			wakeup-source;
+		};
+	};
+
+	lcd_display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interface-pix-fmt = "bgr666";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_ipu1_lcdif>;
+		status = "okay";
+
+		port@0 {
+			reg = <0>;
+
+			lcd_display_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			lcd_display_out: endpoint {
+				remote-endpoint = <&lcd_panel_in>;
+			};
+		};
+	};
+
+	panel: panel {
+		/*
+		 * edt,et057090dhu: EDT 5.7" LCD TFT
+		 * edt,et070080dh6: EDT 7.0" LCD TFT
+		 */
+		compatible = "edt,et057090dhu";
+		backlight = <&backlight>;
+
+		port {
+			lcd_panel_in: endpoint {
+				remote-endpoint = <&lcd_display_out>;
+			};
+		};
+	};
+};
+
+&backlight {
+	brightness-levels = <0 127 191 223 239 247 251 255>;
+	default-brightness-level = <1>;
+	status = "okay";
+};
+
+/* Colibri SSP */
+&ecspi4 {
+	status = "okay";
+
+	mcp251x0: mcp251x@1 {
+		compatible = "microchip,mcp2515";
+		reg = <0>;
+		clocks = <&clk16m>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <27 0x2>;
+		spi-max-frequency = <10000000>;
+		status = "okay";
+	};
+};
+
+&hdmi {
+	status = "okay";
+};
+
+/*
+ * Colibri I2C: I2C3_SDA/SCL on SODIMM 194/196 (e.g. RTC on carrier board)
+ */
+&i2c3 {
+	status = "okay";
+
+	/* M41T0M6 real time clock on carrier board */
+	rtc_i2c: rtc@68 {
+		compatible = "st,m41t00";
+		reg = <0x68>;
+	};
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&lcd_display_in>;
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&pwm3 {
+	status = "okay";
+};
+
+&pwm4 {
+	status = "okay";
+};
+
+&reg_usb_host_vbus {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_host_vbus>;
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+/* Colibri MMC */
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_mmc_cd>;
+	cd-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; /* MMCD */
+	status = "okay";
+};
+
+&weim {
+	status = "okay";
+
+	/* weim memory map: 32MB on CS0, 32MB on CS1, 32MB on CS2 */
+	ranges = <0 0 0x08000000 0x02000000
+		  1 0 0x0a000000 0x02000000
+		  2 0 0x0c000000 0x02000000>;
+
+	/* SRAM on Colibri nEXT_CS0 */
+	sram@0,0 {
+		compatible = "cypress,cy7c1019dv33-10zsxi, mtd-ram";
+		reg = <0 0 0x00010000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		bank-width = <2>;
+		fsl,weim-cs-timing = <0x00010081 0x00000000 0x04000000
+				      0x00000000 0x04000040 0x00000000>;
+	};
+
+	/* SRAM on Colibri nEXT_CS1 */
+	sram@1,0 {
+		compatible = "cypress,cy7c1019dv33-10zsxi, mtd-ram";
+		reg = <1 0 0x00010000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		bank-width = <2>;
+		fsl,weim-cs-timing = <0x00010081 0x00000000 0x04000000
+				      0x00000000 0x04000040 0x00000000>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -137,7 +137,7 @@
 &gpio4 {
 	gpio-ranges = <&iomuxc  5 136 1>, <&iomuxc  6 145 1>, <&iomuxc  7 150 1>,
 		      <&iomuxc  8 146 1>, <&iomuxc  9 151 1>, <&iomuxc 10 147 1>,
-		      <&iomuxc 11 151 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
+		      <&iomuxc 11 152 1>, <&iomuxc 12 148 1>, <&iomuxc 13 153 1>,
 		      <&iomuxc 14 149 1>, <&iomuxc 15 154 1>, <&iomuxc 16  39 7>,
 		      <&iomuxc 23  56 1>, <&iomuxc 24  61 7>, <&iomuxc 31  46 1>;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-icore.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-icore.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-icore.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-icore.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Amarula Solutions B.V.
+ * Copyright (C) 2016 Engicam S.r.l.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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.
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-icore.dtsi"
+
+/ {
+	model = "Engicam i.CoreM6 DualLite/Solo Starter Kit";
+	compatible = "engicam,imx6-icore", "fsl,imx6dl";
+};
+
+&can1 {
+	status = "okay";
+};
+
+&can2 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-riotboard.dts	2017-02-12 16:03:20.000000000 -0500
@@ -390,7 +390,7 @@
 				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030		/* AR8035 pin strapping: MODE#3: pull up */
 				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x130b0		/* AR8035 pin strapping: MODE#0: pull down */
 				MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8	/* GPIO16 -> AR8035 25MHz */
-			        MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x130b0		/* RGMII_nRST */
+				MX6QDL_PAD_EIM_D31__GPIO3_IO31		0x130b0		/* RGMII_nRST */
 				MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x180b0		/* AR8035 interrupt */
 				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
 			>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-tx6dl-comtft.dts	2017-02-12 16:03:20.000000000 -0500
@@ -105,7 +105,7 @@
 				pixelclk-active = <1>;
 			};
 		};
-        };
+	};
 };
 
 &can1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6dl-tx6u-801x.dts	2017-02-12 16:03:20.000000000 -0500
@@ -199,7 +199,7 @@
 				pixelclk-active = <0>;
 			};
 		};
-        };
+	};
 };
 
 &ipu1_di0_disp0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-apalis-ixora.dts	2017-02-12 16:03:20.000000000 -0500
@@ -147,28 +147,6 @@
 			gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
 		};
 	};
-
-	pwmleds {
-		compatible = "pwm-leds";
-
-		ledpwm1 {
-			label = "PWM1";
-			pwms = <&pwm1 0 50000>;
-			max-brightness = <255>;
-		};
-
-		ledpwm2 {
-			label = "PWM2";
-			pwms = <&pwm2 0 50000>;
-			max-brightness = <255>;
-		};
-
-		ledpwm3 {
-			label = "PWM3";
-			pwms = <&pwm3 0 50000>;
-			max-brightness = <255>;
-		};
-	};
 };
 
 &backlight {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-b650v3.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-b650v3.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-b650v3.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-b650v3.dts	2017-02-12 16:03:20.000000000 -0500
@@ -98,3 +98,9 @@
 		line-name = "PCA9539-P05";
 	};
 };
+
+&usbphy1 {
+	fsl,tx-cal-45-dn-ohms = <55>;
+	fsl,tx-cal-45-dp-ohms = <55>;
+	fsl,tx-d-cal = <100>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-cm-fx6.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-cm-fx6.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-cm-fx6.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-cm-fx6.dts	2017-02-12 16:03:20.000000000 -0500
@@ -183,7 +183,6 @@
 			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x1b0b0
 			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
 			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
-			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x4001b0a8
 		>;
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-apalis.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,10 @@
 
 	backlight: backlight {
 		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_bl_on>;
 		pwms = <&pwm4 0 5000000>;
+		enable-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
 		status = "disabled";
 	};
 
@@ -620,6 +623,12 @@
 		>;
 	};
 
+	pinctrl_gpio_bl_on: gpioblon {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x1b0b0
+		>;
+	};
+
 	pinctrl_gpio_keys: gpio1io04grp {
 		fsl,pins = <
 			/* Power button */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-apf6dev.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -347,13 +347,13 @@
 			fsl,pins = <
 				MX6QDL_PAD_DI0_PIN4__GPIO4_IO20		0x100b1
 				MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12	0x100b1
-				MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13 	0x100b1
-				MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14 	0x100b1
-				MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15 	0x100b1
-				MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16 	0x100b1
-				MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17 	0x100b1
-				MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 	0x100b1
-				MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21  	0x100b1
+				MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13	0x100b1
+				MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14	0x100b1
+				MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15	0x100b1
+				MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16	0x100b1
+				MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17	0x100b1
+				MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18	0x100b1
+				MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21	0x100b1
 			>;
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-colibri.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-colibri.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-colibri.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-colibri.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,890 @@
+/*
+ * Copyright 2014-2016 Toradex AG
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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 <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Toradex Colibri iMX6DL/S Module";
+	compatible = "toradex,colibri_imx6dl", "fsl,imx6dl";
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_bl_on>;
+		pwms = <&pwm3 0 5000000>;
+		enable-gpios = <&gpio3 26 GPIO_ACTIVE_HIGH>; /* Colibri BL_ON */
+		status = "disabled";
+	};
+
+	reg_1p8v: regulator-1p8v {
+		compatible = "regulator-fixed";
+		regulator-name = "1P8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	reg_2p5v: regulator-2p5v {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_usb_host_vbus: regulator-usb-host-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_regulator_usbh_pwr>;
+		regulator-name = "usb_host_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>; /* USBH_PEN */
+		status = "disabled";
+	};
+
+	sound {
+		compatible = "fsl,imx-audio-sgtl5000";
+		model = "imx6dl-colibri-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"Headphone Jack", "HP_OUT",
+			"LINE_IN", "Line In Jack",
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias";
+		mux-int-port = <1>;
+		mux-ext-port = <5>;
+	};
+
+	/* Optional S/PDIF in on SODIMM 88 and out on SODIMM 90, 137 or 168 */
+	sound_spdif: sound-spdif {
+		compatible = "fsl,imx-audio-spdif";
+		model = "imx-spdif";
+		spdif-controller = <&spdif>;
+		spdif-in;
+		spdif-out;
+		status = "disabled";
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux &pinctrl_mic_gnd>;
+	status = "okay";
+};
+
+/* Optional on SODIMM 55/63 */
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	status = "disabled";
+};
+
+/* Optional on SODIMM 178/188 */
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	status = "disabled";
+};
+
+/* Colibri SSP */
+&ecspi4 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi4>;
+	status = "disabled";
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rmii";
+	status = "okay";
+};
+
+&hdmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hdmi_ddc>;
+	status = "disabled";
+};
+
+/*
+ * PWR_I2C: power I2C to audio codec, PMIC, temperature sensor and
+ * touch screen controller
+ */
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic: pfuze100@08 {
+		compatible = "fsl,pfuze100";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1ab {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1c {
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1875000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw3a_reg: sw3a {
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1975000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* vgen1: unused */
+
+			vgen2_reg: vgen2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* vgen3: unused */
+
+			vgen4_reg: vgen4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vgen5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vgen6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	/* STMPE811 touch screen controller */
+	stmpe811@41 {
+		compatible = "st,stmpe811";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_touch_int>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x41>;
+		interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-parent = <&gpio6>;
+		interrupt-controller;
+		id = <0>;
+		blocks = <0x5>;
+		irq-trigger = <0x1>;
+
+		stmpe_touchscreen {
+			compatible = "st,stmpe-ts";
+			reg = <0>;
+			/* 3.25 MHz ADC clock speed */
+			st,adc-freq = <1>;
+			/* 8 sample average control */
+			st,ave-ctrl = <3>;
+			/* 7 length fractional part in z */
+			st,fraction-z = <7>;
+			/*
+			 * 50 mA typical 80 mA max touchscreen drivers
+			 * current limit value
+			 */
+			st,i-drive = <1>;
+			/* 12-bit ADC */
+			st,mod-12b = <1>;
+			/* internal ADC reference */
+			st,ref-sel = <0>;
+			/* ADC converstion time: 80 clocks */
+			st,sample-time = <4>;
+			/* 1 ms panel driver settling time */
+			st,settling = <3>;
+			/* 5 ms touch detect interrupt delay */
+			st,touch-det-delay = <5>;
+		};
+	};
+};
+
+/*
+ * I2C3_SDA/SCL on SODIMM 194/196 (e.g. RTC on carrier board)
+ */
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default", "recovery";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	pinctrl-1 = <&pinctrl_i2c3_recovery>;
+	scl-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+	status = "disabled";
+};
+
+/* Colibri PWM<B> */
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "disabled";
+};
+
+/* Colibri PWM<D> */
+&pwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm2>;
+	status = "disabled";
+};
+
+/* Colibri PWM<A> */
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "disabled";
+};
+
+/* Colibri PWM<C> */
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "disabled";
+};
+
+/* Optional S/PDIF out on SODIMM 137 */
+&spdif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spdif>;
+	status = "disabled";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+/* Colibri UART_A */
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_dte &pinctrl_uart1_ctrl>;
+	fsl,dte-mode;
+	uart-has-rtscts;
+	status = "disabled";
+};
+
+/* Colibri UART_B */
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2_dte>;
+	fsl,dte-mode;
+	uart-has-rtscts;
+	status = "disabled";
+};
+
+/* Colibri UART_C */
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3_dte>;
+	fsl,dte-mode;
+	status = "disabled";
+};
+
+&usbotg {
+	pinctrl-names = "default";
+	disable-over-current;
+	dr_mode = "peripheral";
+	status = "disabled";
+};
+
+/* Colibri MMC */
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	vqmmc-supply = <&reg_3p3v>;
+	bus-width = <4>;
+	voltage-ranges = <3300 3300>;
+	status = "disabled";
+};
+
+/* eMMC */
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	vqmmc-supply = <&reg_3p3v>;
+	bus-width = <8>;
+	voltage-ranges = <3300 3300>;
+	non-removable;
+	status = "okay";
+};
+
+&weim {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_weim_sram  &pinctrl_weim_cs0
+		     &pinctrl_weim_cs1   &pinctrl_weim_cs2
+		     &pinctrl_weim_rdnwr &pinctrl_weim_npwe>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__AUD5_TXC	0x130b0
+			MX6QDL_PAD_KEY_ROW0__AUD5_TXD	0x130b0
+			MX6QDL_PAD_KEY_COL1__AUD5_TXFS	0x130b0
+			MX6QDL_PAD_KEY_ROW1__AUD5_RXD	0x130b0
+			/* SGTL5000 sys_mclk */
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1	0x000b0
+		>;
+	};
+
+	pinctrl_cam_mclk: cammclkgrp {
+		fsl,pins = <
+			/* Parallel Camera CAM sys_mclk */
+			MX6QDL_PAD_NANDF_CS2__CCM_CLKO2	0x00b0
+		>;
+	};
+
+	pinctrl_ecspi4: ecspi4grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D22__ECSPI4_MISO	0x100b1
+			MX6QDL_PAD_EIM_D28__ECSPI4_MOSI	0x100b1
+			MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x100b1
+			/* SPI CS */
+			MX6QDL_PAD_EIM_A25__GPIO5_IO02	0x000b1
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0	0x1b0b0
+			MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1	0x1b0b0
+			MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER	0x1b0b0
+			MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN	0x1b0b0
+			MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0	0x1b0b0
+			MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1	0x1b0b0
+			MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN	0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK     ((1<<30) | 0x1b0b0)
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_7__FLEXCAN1_TX		0x1b0b0
+			MX6QDL_PAD_GPIO_8__FLEXCAN1_RX		0x1b0b0
+		>;
+	};
+
+	pinctrl_flexcan2: flexcan2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX	0x1b0b0
+			MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX	0x1b0b0
+		>;
+	};
+
+	pinctrl_gpio_bl_on: gpioblon {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__GPIO3_IO26		0x1b0b0
+		>;
+	};
+
+	pinctrl_gpio_keys: gpiokeys {
+		fsl,pins = <
+			/* Power button */
+			MX6QDL_PAD_EIM_A16__GPIO2_IO22		0x1b0b0
+		>;
+	};
+
+	pinctrl_hdmi_ddc: hdmiddcgrp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__HDMI_TX_DDC_SCL 0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA 0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__I2C2_SCL 0x4001b8b1
+			MX6QDL_PAD_EIM_D16__I2C2_SDA 0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+			MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3_recovery: i2c3recoverygrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x4001b8b1
+			MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x4001b8b1
+		>;
+	};
+
+	pinctrl_ipu1_csi0: ipu1csi0grp { /* Parallel Camera */
+		fsl,pins = <
+			MX6QDL_PAD_EIM_A17__IPU1_CSI1_DATA12	0xb0b1
+			MX6QDL_PAD_EIM_A18__IPU1_CSI1_DATA13	0xb0b1
+			MX6QDL_PAD_EIM_A19__IPU1_CSI1_DATA14	0xb0b1
+			MX6QDL_PAD_EIM_A20__IPU1_CSI1_DATA15	0xb0b1
+			MX6QDL_PAD_EIM_A21__IPU1_CSI1_DATA16	0xb0b1
+			MX6QDL_PAD_EIM_A22__IPU1_CSI1_DATA17	0xb0b1
+			MX6QDL_PAD_EIM_A23__IPU1_CSI1_DATA18	0xb0b1
+			MX6QDL_PAD_EIM_A24__IPU1_CSI1_DATA19	0xb0b1
+			MX6QDL_PAD_EIM_D17__IPU1_CSI1_PIXCLK	0xb0b1
+			MX6QDL_PAD_EIM_EB3__IPU1_CSI1_HSYNC	0xb0b1
+			MX6QDL_PAD_EIM_D29__IPU1_CSI1_VSYNC	0xb0b1
+			/* Disable PWM pins on camera interface */
+			MX6QDL_PAD_SD4_DAT1__GPIO2_IO09		0x40
+			MX6QDL_PAD_GPIO_1__GPIO1_IO01		0x40
+		>;
+	};
+
+	pinctrl_ipu1_lcdif: ipu1lcdifgrp {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK	0xa1
+			MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15		0xa1
+			MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02		0xa1
+			MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03		0xa1
+			MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00	0xa1
+			MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01	0xa1
+			MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02	0xa1
+			MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03	0xa1
+			MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04	0xa1
+			MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05	0xa1
+			MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06	0xa1
+			MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07	0xa1
+			MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08	0xa1
+			MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09	0xa1
+			MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10	0xa1
+			MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11	0xa1
+			MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12	0xa1
+			MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13	0xa1
+			MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14	0xa1
+			MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15	0xa1
+			MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16	0xa1
+			MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17	0xa1
+		>;
+	};
+
+	pinctrl_mic_gnd: gpiomicgnd {
+		fsl,pins = <
+			/* Controls Mic GND, PU or '1' pull Mic GND to GND */
+			MX6QDL_PAD_RGMII_TD1__GPIO6_IO21 0x1b0b0
+		>;
+	};
+
+	pinctrl_mmc_cd: gpiommccd {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_D5__GPIO2_IO05	0x80000000
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_9__PWM1_OUT	0x1b0b1
+		>;
+	};
+
+	pinctrl_pwm2: pwm2grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__PWM2_OUT	0x1b0b1
+			MX6QDL_PAD_EIM_A21__GPIO2_IO17	0x00040
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT1__PWM3_OUT	0x1b0b1
+			MX6QDL_PAD_EIM_A22__GPIO2_IO16	0x00040
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT2__PWM4_OUT	0x1b0b1
+		>;
+	};
+
+	pinctrl_regulator_usbh_pwr: gpioregusbhpwrgrp {
+		fsl,pins = <
+			/* USBH_EN */
+			MX6QDL_PAD_EIM_D31__GPIO3_IO31	0x0f058
+		>;
+	};
+
+	pinctrl_spdif: spdifgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x1b0b0
+		>;
+	};
+
+	pinctrl_touch_int: gpiotouchintgrp {
+		fsl,pins = <
+			/* STMPE811 interrupt */
+			MX6QDL_PAD_RGMII_TD0__GPIO6_IO20 0x1b0b0
+		>;
+	};
+
+	pinctrl_uart1_dce: uart1dcegrp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
+		>;
+	};
+
+	/* DTE mode */
+	pinctrl_uart1_dte: uart1dtegrp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT10__UART1_RX_DATA 0x1b0b1
+			MX6QDL_PAD_CSI0_DAT11__UART1_TX_DATA 0x1b0b1
+			MX6QDL_PAD_EIM_D19__UART1_RTS_B	0x1b0b1
+			MX6QDL_PAD_EIM_D20__UART1_CTS_B 0x1b0b1
+		>;
+	};
+
+	/* Additional DTR, DSR, DCD */
+	pinctrl_uart1_ctrl: uart1ctrlgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D23__UART1_DCD_B 0x1b0b0
+			MX6QDL_PAD_EIM_D24__UART1_DTR_B 0x1b0b0
+			MX6QDL_PAD_EIM_D25__UART1_DSR_B 0x1b0b0
+		>;
+	};
+
+	pinctrl_uart2_dte: uart2dtegrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_DAT4__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT7__UART2_RX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_DAT6__UART2_RTS_B	0x1b0b1
+			MX6QDL_PAD_SD4_DAT5__UART2_CTS_B	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3_dte: uart3dtegrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CLK__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD4_CMD__UART3_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_usbc_det: usbcdetgrp {
+		fsl,pins = <
+			/* USBC_DET */
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x1b0b0
+			/* USBC_DET_EN */
+			MX6QDL_PAD_RGMII_TX_CTL__GPIO6_IO26	0x0f058
+			/* USBC_DET_OVERWRITE */
+			MX6QDL_PAD_RGMII_RXC__GPIO6_IO30	0x0f058
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__SD1_CMD	0x17071
+			MX6QDL_PAD_SD1_CLK__SD1_CLK	0x10071
+			MX6QDL_PAD_SD1_DAT0__SD1_DATA0	0x17071
+			MX6QDL_PAD_SD1_DAT1__SD1_DATA1	0x17071
+			MX6QDL_PAD_SD1_DAT2__SD1_DATA2	0x17071
+			MX6QDL_PAD_SD1_DAT3__SD1_DATA3	0x17071
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD	0x17059
+			MX6QDL_PAD_SD3_CLK__SD3_CLK	0x10059
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0	0x17059
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1	0x17059
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2	0x17059
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3	0x17059
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4	0x17059
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5	0x17059
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6	0x17059
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7	0x17059
+			/* eMMC reset */
+			MX6QDL_PAD_SD3_RST__SD3_RESET	0x17059
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3100mhzgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD	0x170b9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK	0x100b9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0	0x170b9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1	0x170b9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2	0x170b9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3	0x170b9
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4	0x170b9
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5	0x170b9
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6	0x170b9
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7	0x170b9
+			/* eMMC reset */
+			MX6QDL_PAD_SD3_RST__SD3_RESET	0x170b9
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3200mhzgrp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CMD__SD3_CMD	0x170f9
+			MX6QDL_PAD_SD3_CLK__SD3_CLK	0x100f9
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0	0x170f9
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1	0x170f9
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2	0x170f9
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3	0x170f9
+			MX6QDL_PAD_SD3_DAT4__SD3_DATA4	0x170f9
+			MX6QDL_PAD_SD3_DAT5__SD3_DATA5	0x170f9
+			MX6QDL_PAD_SD3_DAT6__SD3_DATA6	0x170f9
+			MX6QDL_PAD_SD3_DAT7__SD3_DATA7	0x170f9
+			/* eMMC reset */
+			MX6QDL_PAD_SD3_RST__SD3_RESET	0x170f9
+		>;
+	};
+
+	pinctrl_weim_cs0: weimcs0grp {
+		fsl,pins = <
+			/* nEXT_CS0 */
+			MX6QDL_PAD_EIM_CS0__EIM_CS0_B	0xb0b1
+		>;
+	};
+
+	pinctrl_weim_cs1: weimcs1grp {
+		fsl,pins = <
+			/* nEXT_CS1 */
+			MX6QDL_PAD_EIM_CS1__EIM_CS1_B	0xb0b1
+		>;
+	};
+
+	pinctrl_weim_cs2: weimcs2grp {
+		fsl,pins = <
+			/* nEXT_CS2 */
+			MX6QDL_PAD_SD2_DAT1__EIM_CS2_B	0xb0b1
+		>;
+	};
+
+	pinctrl_weim_sram: weimsramgrp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_OE__EIM_OE_B		0xb0b1
+			MX6QDL_PAD_EIM_RW__EIM_RW		0xb0b1
+			/* Data */
+			MX6QDL_PAD_CSI0_DATA_EN__EIM_DATA00	0x1b0b0
+			MX6QDL_PAD_CSI0_VSYNC__EIM_DATA01	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT4__EIM_DATA02	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT5__EIM_DATA03	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT6__EIM_DATA04	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT7__EIM_DATA05	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT8__EIM_DATA06	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT9__EIM_DATA07	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT12__EIM_DATA08	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT13__EIM_DATA09	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT14__EIM_DATA10	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT15__EIM_DATA11	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT16__EIM_DATA12	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT17__EIM_DATA13	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT18__EIM_DATA14	0x1b0b0
+			MX6QDL_PAD_CSI0_DAT19__EIM_DATA15	0x1b0b0
+			/* Address */
+			MX6QDL_PAD_EIM_DA15__EIM_AD15		0xb0b1
+			MX6QDL_PAD_EIM_DA14__EIM_AD14		0xb0b1
+			MX6QDL_PAD_EIM_DA13__EIM_AD13		0xb0b1
+			MX6QDL_PAD_EIM_DA12__EIM_AD12		0xb0b1
+			MX6QDL_PAD_EIM_DA11__EIM_AD11		0xb0b1
+			MX6QDL_PAD_EIM_DA10__EIM_AD10		0xb0b1
+			MX6QDL_PAD_EIM_DA9__EIM_AD09		0xb0b1
+			MX6QDL_PAD_EIM_DA8__EIM_AD08		0xb0b1
+			MX6QDL_PAD_EIM_DA7__EIM_AD07		0xb0b1
+			MX6QDL_PAD_EIM_DA6__EIM_AD06		0xb0b1
+			MX6QDL_PAD_EIM_DA5__EIM_AD05		0xb0b1
+			MX6QDL_PAD_EIM_DA4__EIM_AD04		0xb0b1
+			MX6QDL_PAD_EIM_DA3__EIM_AD03		0xb0b1
+			MX6QDL_PAD_EIM_DA2__EIM_AD02		0xb0b1
+			MX6QDL_PAD_EIM_DA1__EIM_AD01		0xb0b1
+			MX6QDL_PAD_EIM_DA0__EIM_AD00		0xb0b1
+		>;
+	};
+
+	pinctrl_weim_rdnwr: weimrdnwr {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CLK__GPIO1_IO10		0x0040
+			MX6QDL_PAD_RGMII_TD3__GPIO6_IO23	0x130b0
+		>;
+	};
+
+	pinctrl_weim_npwe: weimnpwe {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_DAT3__GPIO1_IO12		0x0040
+			MX6QDL_PAD_RGMII_TD2__GPIO6_IO22	0x130b0
+		>;
+	};
+
+	/* ADDRESS[16:18] [25] used as GPIO */
+	pinctrl_weim_gpio_1: weimgpio-1 {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
+			MX6QDL_PAD_KEY_ROW2__GPIO4_IO11		0x1b0b0
+			MX6QDL_PAD_KEY_COL2__GPIO4_IO10		0x1b0b0
+			MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12	0x1b0b0
+			MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+		>;
+	};
+
+	/* ADDRESS[19:24] used as GPIO */
+	pinctrl_weim_gpio_2: weimgpio-2 {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__GPIO4_IO11		0x1b0b0
+			MX6QDL_PAD_KEY_COL2__GPIO4_IO10		0x1b0b0
+			MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT20__GPIO5_IO14	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT19__GPIO5_IO13	0x1b0b0
+			MX6QDL_PAD_DISP0_DAT18__GPIO5_IO12	0x1b0b0
+			MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+		>;
+	};
+
+	/* DATA[16:31] used as GPIO */
+	pinctrl_weim_gpio_3: weimgpio-3 {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_LBA__GPIO2_IO27		0x1b0b0
+			MX6QDL_PAD_EIM_BCLK__GPIO6_IO31		0x1b0b0
+			MX6QDL_PAD_NANDF_CS3__GPIO6_IO16	0x1b0b0
+			MX6QDL_PAD_NANDF_CS1__GPIO6_IO14	0x1b0b0
+			MX6QDL_PAD_NANDF_RB0__GPIO6_IO10	0x1b0b0
+			MX6QDL_PAD_NANDF_ALE__GPIO6_IO08	0x1b0b0
+			MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09	0x1b0b0
+			MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x1b0b0
+			MX6QDL_PAD_NANDF_CLE__GPIO6_IO07	0x1b0b0
+			MX6QDL_PAD_GPIO_19__GPIO4_IO05		0x1b0b0
+			MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19	0x1b0b0
+			MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18	0x1b0b0
+			MX6QDL_PAD_GPIO_4__GPIO1_IO04		0x1b0b0
+			MX6QDL_PAD_GPIO_5__GPIO1_IO05		0x1b0b0
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x1b0b0
+		>;
+	};
+
+	/* DQM[0:3] used as GPIO */
+	pinctrl_weim_gpio_4: weimgpio-4 {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB0__GPIO2_IO28		0x1b0b0
+			MX6QDL_PAD_EIM_EB1__GPIO2_IO29		0x1b0b0
+			MX6QDL_PAD_SD2_DAT2__GPIO1_IO13		0x1b0b0
+			MX6QDL_PAD_NANDF_D0__GPIO2_IO00		0x1b0b0
+		>;
+	};
+
+	/* RDY used as GPIO */
+	pinctrl_weim_gpio_5: weimgpio-5 {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_WAIT__GPIO5_IO00		0x1b0b0
+		>;
+	};
+
+	/* ADDRESS[16] DATA[30] used as GPIO */
+	pinctrl_weim_gpio_6: weimgpio-6 {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW4__GPIO4_IO15		0x1b0b0
+			MX6QDL_PAD_KEY_COL4__GPIO4_IO14		0x1b0b0
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl.dtsi	2016-12-11 17:43:23.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl.dtsi	2017-02-12 17:27:20.000000000 -0500
@@ -13,9 +13,18 @@
 #include <dt-bindings/clock/imx6qdl-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include "skeleton.dtsi"
-
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		can0 = &can1;
@@ -204,9 +213,9 @@
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0x7>;
 			interrupt-map = <0 0 0 1 &gpc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
-			                <0 0 0 2 &gpc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
-			                <0 0 0 3 &gpc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
-			                <0 0 0 4 &gpc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+					<0 0 0 2 &gpc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 3 &gpc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 4 &gpc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clks IMX6QDL_CLK_PCIE_AXI>,
 				 <&clks IMX6QDL_CLK_LVDS1_GATE>,
 				 <&clks IMX6QDL_CLK_PCIE_REF_125M>;
@@ -1092,10 +1101,14 @@
 			};
 
 			weim: weim@021b8000 {
+				#address-cells = <2>;
+				#size-cells = <1>;
 				compatible = "fsl,imx6q-weim";
 				reg = <0x021b8000 0x4000>;
 				interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6QDL_CLK_EIM_SLOW>;
+				fsl,weim-cs-gpr = <&gpr>;
+				status = "disabled";
 			};
 
 			ocotp: ocotp@021bc000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -153,9 +153,9 @@
 
 &clks {
 	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-	                  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
 	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
-	                  <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
 };
 
 &ecspi3 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -154,9 +154,9 @@
 
 &clks {
 	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-	                  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
 	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
-	                  <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
 };
 
 &fec {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -144,9 +144,9 @@
 
 &clks {
 	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-	                  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
 	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
-	                  <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
 };
 
 &fec {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw552x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw552x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-gw552x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-gw552x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -291,7 +291,7 @@
 				MX6QDL_PAD_KEY_COL1__UART5_TX_DATA	0x1b0b1
 				MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA	0x1b0b1
 			>;
-                };
+		};
 
 		pinctrl_wdog: wdoggrp {
 			fsl,pins = <
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-icore.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-icore.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-icore.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-icore.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2016 Amarula Solutions B.V.
+ * Copyright (C) 2016 Engicam S.r.l.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	memory {
+		reg = <0x10000000 0x80000000>;
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	rmii_clk: clock-rmii-clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;  /* 25MHz for example */
+	};
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan1>;
+	xceiver-supply = <&reg_3p3v>;
+};
+
+&can2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_flexcan2>;
+	xceiver-supply = <&reg_3p3v>;
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LVDS2_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_OSC>;
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-reset-gpios = <&gpio7 12 GPIO_ACTIVE_LOW>;
+	clocks = <&clks IMX6QDL_CLK_ENET>, <&clks IMX6QDL_CLK_ENET>, <&rmii_clk>;
+	phy-mode = "rmii";
+	status = "okay";
+};
+
+&gpmi {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpmi_nand>;
+	nand-on-flash-bbt;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+	no-1-8-v;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN	0x1b0b0
+			MX6QDL_PAD_GPIO_16__ENET_REF_CLK	0x1b0b1
+			MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN	0x1b0b0
+			MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1	0x1b0b0
+			MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0	0x1b0b0
+			MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1	0x1b0b0
+			MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0	0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23	0x1b0b0
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x1b0b0
+		>;
+	};
+
+	pinctrl_flexcan1: flexcan1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX 0x1b020
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b020
+		>;
+	};
+
+	pinctrl_flexcan2: flexcan2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b020
+			MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x1b020
+		>;
+	};
+
+	pinctrl_gpmi_nand: gpmi-nand {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE     0xb0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE     0xb0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
+			MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
+			MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
+			MX6QDL_PAD_SD4_DAT0__NAND_DQS      0x00b1
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB2__I2C2_SCL  0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__I2C3_SCL  0x4001b8b1
+			MX6QDL_PAD_EIM_D18__I2C3_SDA 0x4001b8b1
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1	0x130b0
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+			MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__SD1_CMD    0x17070
+			MX6QDL_PAD_SD1_CLK__SD1_CLK    0x10070
+			MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17070
+			MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17070
+			MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17070
+			MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17070
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nit6xlite.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -97,15 +97,6 @@
 		};
 	};
 
-	bt_rfkill {
-		compatible = "rfkill-gpio";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_bt_rfkill>;
-		gpios = <&gpio6 8 GPIO_ACTIVE_HIGH>;
-		name = "bt_rfkill";
-		type = <2>;
-	};
-
 	gpio-keys {
 		compatible = "gpio-keys";
 		pinctrl-names = "default";
@@ -160,7 +151,7 @@
 		};
 	};
 
-	backlight_lcd {
+	backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -169,7 +160,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds0: backlight_lvds0 {
+	backlight_lvds0: backlight-lvds0 {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -178,7 +169,7 @@
 		status = "okay";
 	};
 
-	panel_lvds0 {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds0>;
 
@@ -328,19 +319,6 @@
 			>;
 		};
 
-		pinctrl_bt_rfkill: bt_rfkillgrp {
-			fsl,pins = <
-				/* BT wake */
-				MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
-				/* BT reset */
-				MX6QDL_PAD_NANDF_ALE__GPIO6_IO08	0x0b0b0
-				/* BT reg en */
-				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x1b0b0
-				/* BT host wake irq */
-				MX6QDL_PAD_NANDF_CS3__GPIO6_IO16	0x100b0
-			>;
-		};
-
 		pinctrl_ecspi1: ecspi1grp {
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
@@ -374,7 +352,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Home Button: J14 pin 5 */
 				MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b0
@@ -457,7 +435,7 @@
 			>;
 		};
 
-		pinctrl_wlan_vmmc: wlan_vmmcgrp {
+		pinctrl_wlan_vmmc: wlan-vmmcgrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CLE__GPIO6_IO07	0x030b0
 			>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_max.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -229,7 +229,7 @@
 		};
 	};
 
-	backlight_lcd: backlight_lcd {
+	backlight_lcd: backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -238,7 +238,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds0: backlight_lvds0 {
+	backlight_lvds0: backlight-lvds0 {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -247,7 +247,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds1: backlight_lvds1 {
+	backlight_lvds1: backlight-lvds1 {
 		compatible = "pwm-backlight";
 		pwms = <&pwm2 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -282,7 +282,7 @@
 		};
 	};
 
-	panel_lcd {
+	panel-lcd {
 		compatible = "okaya,rs800480t-7x0gp";
 		backlight = <&backlight_lcd>;
 
@@ -293,7 +293,7 @@
 		};
 	};
 
-	panel_lvds0 {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds0>;
 
@@ -304,7 +304,7 @@
 		};
 	};
 
-	panel_lvds1 {
+	panel-lvds1 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds1>;
 
@@ -319,8 +319,6 @@
 		compatible = "fsl,imx6q-nitrogen6_max-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
 		model = "imx6q-nitrogen6_max-sgtl5000";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_sgtl5000>;
 		ssi-controller = <&ssi1>;
 		audio-codec = <&codec>;
 		audio-routing =
@@ -402,6 +400,8 @@
 
 	codec: sgtl5000@0a {
 		compatible = "fsl,sgtl5000";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sgtl5000>;
 		reg = <0x0a>;
 		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_2p5v>;
@@ -447,7 +447,7 @@
 };
 
 &iomuxc {
-	imx6q-nitrogen6_max {
+	imx6q-nitrogen6-max {
 		pinctrl_audmux: audmuxgrp {
 			fsl,pins = <
 				MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
@@ -504,7 +504,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Power Button */
 				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
@@ -720,7 +720,7 @@
 			>;
 		};
 
-		pinctrl_wlan_vmmc: wlan_vmmcgrp {
+		pinctrl_wlan_vmmc: wlan-vmmcgrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x100b0
 				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x000b0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6_som2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,770 @@
+/*
+ * Copyright 2016 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	memory {
+		reg = <0x10000000 0x40000000>;
+	};
+
+	backlight_lcd: backlight-lcd {
+		compatible = "pwm-backlight";
+		pwms = <&pwm1 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+
+	backlight_lvds0: backlight-lvds0 {
+		compatible = "pwm-backlight";
+		pwms = <&pwm4 0 5000000>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <7>;
+		power-supply = <&reg_3p3v>;
+		status = "okay";
+	};
+
+	backlight_lvds1: backlight-lvds1 {
+		compatible = "gpio-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_backlight_lvds1>;
+		gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;
+		default-on;
+		status = "okay";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpio_keys>;
+
+		power {
+			label = "Power Button";
+			gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			wakeup-source;
+		};
+
+		menu {
+			label = "Menu";
+			gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_MENU>;
+		};
+
+		home {
+			label = "Home";
+			gpios = <&gpio2 4 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_HOME>;
+		};
+
+		back {
+			label = "Back";
+			gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_BACK>;
+		};
+
+		volume-up {
+			label = "Volume Up";
+			gpios = <&gpio7 13 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+		};
+
+		volume-down {
+			label = "Volume Down";
+			gpios = <&gpio7 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+		};
+	};
+
+	lcd_display: display@di0 {
+		compatible = "fsl,imx-parallel-display";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interface-pix-fmt = "bgr666";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_j15>;
+		status = "okay";
+
+		port@0 {
+			reg = <0>;
+
+			lcd_display_in: endpoint {
+				remote-endpoint = <&ipu1_di0_disp0>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			lcd_display_out: endpoint {
+				remote-endpoint = <&lcd_panel_in>;
+			};
+		};
+	};
+
+	panel-lcd {
+		compatible = "okaya,rs800480t-7x0gp";
+		backlight = <&backlight_lcd>;
+
+		port {
+			lcd_panel_in: endpoint {
+				remote-endpoint = <&lcd_display_out>;
+			};
+		};
+	};
+
+	panel-lvds0 {
+		compatible = "hannstar,hsd100pxn1";
+		backlight = <&backlight_lvds0>;
+
+		port {
+			panel_in_lvds0: endpoint {
+				remote-endpoint = <&lvds0_out>;
+			};
+		};
+	};
+
+	panel-lvds1 {
+		compatible = "hannstar,hsd100pxn1";
+		backlight = <&backlight_lvds1>;
+
+		port {
+			panel_in_lvds1: endpoint {
+				remote-endpoint = <&lvds1_out>;
+			};
+		};
+	};
+
+	reg_1p8v: regulator-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "1P8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+	};
+
+	reg_2p5v: regulator-2v5 {
+		compatible = "regulator-fixed";
+		regulator-name = "2P5V";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_can_xcvr: regulator-can-xcvr {
+		compatible = "regulator-fixed";
+		regulator-name = "CAN XCVR";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_can_xcvr>;
+		gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
+	};
+
+	reg_usb_h1_vbus: regulator-usb-h1-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usbh1>;
+		regulator-name = "usb_h1_vbus";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-always-on;
+	};
+
+	reg_usb_otg_vbus: regulator-usb-otg-vbus {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_otg_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	reg_wlan_vmmc: regulator-wlan-vmmc {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_wlan_vmmc>;
+		regulator-name = "reg_wlan_vmmc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&gpio6 15 GPIO_ACTIVE_HIGH>;
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
+
+	sound {
+		compatible = "fsl,imx6q-nitrogen6_som2-sgtl5000",
+			     "fsl,imx-audio-sgtl5000";
+		model = "imx6q-nitrogen6_som2-sgtl5000";
+		ssi-controller = <&ssi1>;
+		audio-codec = <&codec>;
+		audio-routing =
+			"MIC_IN", "Mic Jack",
+			"Mic Jack", "Mic Bias",
+			"Headphone Jack", "HP_OUT";
+		mux-int-port = <1>;
+		mux-ext-port = <3>;
+	};
+};
+
+&audmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_audmux>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1>;
+	xceiver-supply = <&reg_can_xcvr>;
+	status = "okay";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&ecspi1 {
+	fsl,spi-num-chipselects = <1>;
+	cs-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ecspi1>;
+	status = "okay";
+
+	flash: m25p80@0 {
+		compatible = "microchip,sst25vf016b";
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
+
+&fec {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet>;
+	phy-mode = "rgmii";
+	interrupts-extended = <&gpio1 6 IRQ_TYPE_LEVEL_HIGH>,
+			      <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+	fsl,err006687-workaround-present;
+	status = "okay";
+};
+
+&hdmi {
+	ddc-i2c-bus = <&i2c2>;
+	status = "okay";
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	codec: sgtl5000@0a {
+		compatible = "fsl,sgtl5000";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sgtl5000>;
+		reg = <0x0a>;
+		clocks = <&clks IMX6QDL_CLK_CKO>;
+		VDDA-supply = <&reg_2p5v>;
+		VDDIO-supply = <&reg_3p3v>;
+	};
+
+	rtc@68 {
+		compatible = "st,rv4162";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_rv4162>;
+		reg = <0x68>;
+		interrupts-extended = <&gpio6 7 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+};
+
+&i2c3 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	touchscreen@04 {
+		compatible = "eeti,egalax_ts";
+		reg = <0x04>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+		wakeup-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+	};
+
+	touchscreen@38 {
+		compatible = "edt,edt-ft5x06";
+		reg = <0x38>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
+&iomuxc {
+	pinctrl_audmux: audmuxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_CSI0_DAT7__AUD3_RXD		0x130b0
+			MX6QDL_PAD_CSI0_DAT4__AUD3_TXC		0x130b0
+			MX6QDL_PAD_CSI0_DAT5__AUD3_TXD		0x110b0
+			MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS		0x130b0
+		>;
+	};
+
+	pinctrl_backlight_lvds1: backlight-lvds1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_EB3__GPIO2_IO31		0x0b0b0
+		>;
+	};
+
+	pinctrl_can1: can1grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX	0x1b0b0
+			MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX	0x1b0b0
+		>;
+	};
+
+	pinctrl_can_xcvr: can-xcvrgrp {
+		fsl,pins = <
+			/* Flexcan XCVR enable */
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02		0x0b0b0
+		>;
+	};
+
+	pinctrl_ecspi1: ecspi1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D17__ECSPI1_MISO		0x100b1
+			MX6QDL_PAD_EIM_D18__ECSPI1_MOSI		0x100b1
+			MX6QDL_PAD_EIM_D16__ECSPI1_SCLK		0x100b1
+			MX6QDL_PAD_EIM_D19__GPIO3_IO19		0x000b1
+		>;
+	};
+
+	pinctrl_enet: enetgrp {
+		fsl,pins = <
+			MX6QDL_PAD_ENET_MDIO__ENET_MDIO		0x1b0b0
+			MX6QDL_PAD_ENET_MDC__ENET_MDC		0x1b0b0
+			MX6QDL_PAD_RGMII_TXC__RGMII_TXC		0x100b0
+			MX6QDL_PAD_RGMII_TD0__RGMII_TD0		0x100b0
+			MX6QDL_PAD_RGMII_TD1__RGMII_TD1		0x100b0
+			MX6QDL_PAD_RGMII_TD2__RGMII_TD2		0x100b0
+			MX6QDL_PAD_RGMII_TD3__RGMII_TD3		0x100b0
+			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL	0x100b0
+			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK	0x100b0
+			MX6QDL_PAD_RGMII_RXC__RGMII_RXC		0x1b0b0
+			MX6QDL_PAD_RGMII_RD0__RGMII_RD0		0x130b0
+			MX6QDL_PAD_RGMII_RD1__RGMII_RD1		0x1b0b0
+			MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x130b0
+			MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b0b0
+			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x130b0
+			MX6QDL_PAD_ENET_RXD0__GPIO1_IO27	0x030b0
+			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28	0x1b0b0
+			MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
+		>;
+	};
+
+	pinctrl_gpio_keys: gpio-keysgrp {
+		fsl,pins = <
+			/* Power Button */
+			MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
+			/* Menu Button */
+			MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x1b0b0
+			/* Home Button */
+			MX6QDL_PAD_NANDF_D4__GPIO2_IO04		0x1b0b0
+			/* Back Button */
+			MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x1b0b0
+			/* Volume Up Button */
+			MX6QDL_PAD_GPIO_18__GPIO7_IO13		0x1b0b0
+			/* Volume Down Button */
+			MX6QDL_PAD_SD3_DAT4__GPIO7_IO01		0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__I2C1_SCL	0x4001b8b1
+			MX6QDL_PAD_EIM_D28__I2C1_SDA	0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__I2C2_SCL	0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__I2C2_SDA	0x4001b8b1
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__I2C3_SCL	0x4001b8b1
+			MX6QDL_PAD_GPIO_16__I2C3_SDA	0x4001b8b1
+			MX6QDL_PAD_GPIO_9__GPIO1_IO09	0x1b0b0
+		>;
+	};
+
+	pinctrl_i2c3mux: i2c3muxgrp {
+		fsl,pins = <
+			/* PCIe I2C enable */
+			MX6QDL_PAD_EIM_OE__GPIO2_IO25	0x000b0
+		>;
+	};
+
+	pinctrl_j15: j15grp {
+		fsl,pins = <
+			MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+			MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x10
+			MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x10
+			MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x10
+			MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x10
+			MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x10
+			MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x10
+			MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x10
+			MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x10
+			MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x10
+			MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x10
+			MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x10
+			MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x10
+			MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x10
+			MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x10
+			MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x10
+			MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x10
+			MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x10
+			MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x10
+			MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x10
+			MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x10
+			MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x10
+			MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x10
+			MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x10
+			MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x10
+			MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x10
+			MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x10
+			MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x10
+		>;
+	};
+
+	pinctrl_pcie: pciegrp {
+		fsl,pins = <
+			/* PCIe reset */
+			MX6QDL_PAD_EIM_BCLK__GPIO6_IO31	0x030b0
+			MX6QDL_PAD_EIM_DA4__GPIO3_IO04	0x030b0
+		>;
+	};
+
+	pinctrl_pwm1: pwm1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT3__PWM1_OUT	0x030b1
+		>;
+	};
+
+	pinctrl_pwm3: pwm3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_DAT1__PWM3_OUT	0x030b1
+		>;
+	};
+
+	pinctrl_pwm4: pwm4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD1_CMD__PWM4_OUT	0x030b1
+		>;
+	};
+
+	pinctrl_rv4162: rv4162grp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CLE__GPIO6_IO07	0x1b0b0
+		>;
+	};
+
+	pinctrl_sgtl5000: sgtl5000grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_0__CCM_CLKO1		0x000b0
+			MX6QDL_PAD_EIM_D29__GPIO3_IO29		0x130b0
+			MX6QDL_PAD_EIM_DA2__GPIO3_IO02		0x130b0
+			MX6QDL_PAD_ENET_RX_ER__GPIO1_IO24	0x130b0
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA	0x1b0b1
+			MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D26__UART2_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D27__UART2_RX_DATA	0x1b0b1
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
+			MX6QDL_PAD_EIM_D23__UART3_CTS_B		0x1b0b1
+			MX6QDL_PAD_EIM_D31__UART3_RTS_B		0x1b0b1
+		>;
+	};
+
+	pinctrl_usbh1: usbh1grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_17__GPIO7_IO12		0x030b0
+		>;
+	};
+
+	pinctrl_usbotg: usbotggrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_1__USB_OTG_ID		0x17059
+			MX6QDL_PAD_KEY_COL4__USB_OTG_OC		0x1b0b0
+			/* power enable, high active */
+			MX6QDL_PAD_EIM_D22__GPIO3_IO22		0x030b0
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD2_CLK__SD2_CLK		0x10071
+			MX6QDL_PAD_SD2_CMD__SD2_CMD		0x17071
+			MX6QDL_PAD_SD2_DAT0__SD2_DATA0		0x17071
+			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17071
+			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17071
+			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17071
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD3_CLK__SD3_CLK		0x10071
+			MX6QDL_PAD_SD3_CMD__SD3_CMD		0x17071
+			MX6QDL_PAD_SD3_DAT0__SD3_DATA0		0x17071
+			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17071
+			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17071
+			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17071
+			MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x1b0b0
+		>;
+	};
+
+	pinctrl_usdhc4: usdhc4grp {
+		fsl,pins = <
+			MX6QDL_PAD_SD4_CMD__SD4_CMD		0x17059
+			MX6QDL_PAD_SD4_CLK__SD4_CLK		0x10059
+			MX6QDL_PAD_SD4_DAT0__SD4_DATA0		0x17059
+			MX6QDL_PAD_SD4_DAT1__SD4_DATA1		0x17059
+			MX6QDL_PAD_SD4_DAT2__SD4_DATA2		0x17059
+			MX6QDL_PAD_SD4_DAT3__SD4_DATA3		0x17059
+			MX6QDL_PAD_SD4_DAT4__SD4_DATA4		0x17059
+			MX6QDL_PAD_SD4_DAT5__SD4_DATA5		0x17059
+			MX6QDL_PAD_SD4_DAT6__SD4_DATA6		0x17059
+			MX6QDL_PAD_SD4_DAT7__SD4_DATA7		0x17059
+		>;
+	};
+
+	pinctrl_wlan_vmmc: wlan-vmmcgrp {
+		fsl,pins = <
+			MX6QDL_PAD_NANDF_CS1__GPIO6_IO14	0x100b0
+			MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x030b0
+			MX6QDL_PAD_NANDF_CS3__GPIO6_IO16	0x030b0
+			MX6QDL_PAD_SD1_CLK__OSC32K_32K_OUT	0x000b0
+		>;
+	};
+};
+
+&ipu1_di0_disp0 {
+	remote-endpoint = <&lcd_display_in>;
+};
+
+&ldb {
+	status = "okay";
+
+	lvds-channel@0 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		port@4 {
+			reg = <4>;
+
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in_lvds0>;
+			};
+		};
+	};
+
+	lvds-channel@1 {
+		fsl,data-mapping = "spwg";
+		fsl,data-width = <18>;
+		status = "okay";
+
+		port@4 {
+			reg = <4>;
+
+			lvds1_out: endpoint {
+				remote-endpoint = <&panel_in_lvds1>;
+			};
+		};
+	};
+};
+
+&pcie {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pcie>;
+	reset-gpio = <&gpio6 31 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&pwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm1>;
+	status = "okay";
+};
+
+&pwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm3>;
+	status = "okay";
+};
+
+&pwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pwm4>;
+	status = "okay";
+};
+
+&ssi1 {
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>;
+	uart-has-rtscts;
+	status = "okay";
+};
+
+&usbh1 {
+	vbus-supply = <&reg_usb_h1_vbus>;
+	status = "okay";
+};
+
+&usbotg {
+	vbus-supply = <&reg_usb_otg_vbus>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbotg>;
+	disable-over-current;
+	status = "okay";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	bus-width = <4>;
+	non-removable;
+	vmmc-supply = <&reg_wlan_vmmc>;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1271";
+		reg = <2>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;
+		ref-clock-frequency = <38400000>;
+	};
+};
+
+&usdhc3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+&usdhc4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc4>;
+	bus-width = <8>;
+	non-removable;
+	vmmc-supply = <&reg_1p8v>;
+	keep-power-in-suspend;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -167,7 +167,7 @@
 		mux-ext-port = <3>;
 	};
 
-	backlight_lcd: backlight_lcd {
+	backlight_lcd: backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -176,7 +176,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds: backlight_lvds {
+	backlight_lvds: backlight-lvds {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -211,7 +211,7 @@
 		};
 	};
 
-	lcd_panel {
+	panel-lcd {
 		compatible = "okaya,rs800480t-7x0gp";
 		backlight = <&backlight_lcd>;
 
@@ -222,7 +222,7 @@
 		};
 	};
 
-	panel {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds>;
 
@@ -413,7 +413,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Power Button */
 				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
@@ -533,7 +533,6 @@
 				MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17071
 				MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17071
 				MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17071
-				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x000b0
 			>;
 		};
 
@@ -561,7 +560,7 @@
 			>;
 		};
 
-		pinctrl_wlan_vmmc: wlan_vmmcgrp {
+		pinctrl_wlan_vmmc: wlan-vmmcgrp {
 			fsl,pins = <
 				MX6QDL_PAD_NANDF_CS0__GPIO6_IO11	0x100b0
 				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x000b0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -427,10 +427,10 @@
 };
 
 &usdhc3 {
-        pinctrl-names = "default";
-        pinctrl-0 = <&pinctrl_usdhc3
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc3
 		     &pinctrl_usdhc3_cdwp>;
 	cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
-        status = "disabled";
+	status = "disabled";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -283,7 +283,7 @@
 		VD-supply = <&reg_audio>;
 		VLS-supply = <&reg_audio>;
 		VLC-supply = <&reg_audio>;
-        };
+	};
 
 };
 
@@ -613,8 +613,6 @@
 &weim {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_weim_nor &pinctrl_weim_cs0>;
-	#address-cells = <2>;
-	#size-cells = <1>;
 	ranges = <0 0 0x08000000 0x08000000>;
 	status = "disabled"; /* pin conflict with SPI NOR */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -153,7 +153,7 @@
 		mux-ext-port = <4>;
 	};
 
-	backlight_lcd: backlight_lcd {
+	backlight_lcd: backlight-lcd {
 		compatible = "pwm-backlight";
 		pwms = <&pwm1 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -162,7 +162,7 @@
 		status = "okay";
 	};
 
-	backlight_lvds: backlight_lvds {
+	backlight_lvds: backlight-lvds {
 		compatible = "pwm-backlight";
 		pwms = <&pwm4 0 5000000>;
 		brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -197,7 +197,7 @@
 		};
 	};
 
-	lcd_panel {
+	panel-lcd {
 		compatible = "okaya,rs800480t-7x0gp";
 		backlight = <&backlight_lcd>;
 
@@ -208,7 +208,7 @@
 		};
 	};
 
-	panel {
+	panel-lvds0 {
 		compatible = "hannstar,hsd100pxn1";
 		backlight = <&backlight_lvds>;
 
@@ -378,7 +378,7 @@
 			>;
 		};
 
-		pinctrl_gpio_keys: gpio_keysgrp {
+		pinctrl_gpio_keys: gpio-keysgrp {
 			fsl,pins = <
 				/* Power Button */
 				MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x1b0b0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-sabresd.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -129,8 +129,8 @@
 		pinctrl-0 = <&pinctrl_gpio_leds>;
 
 		red {
-		        gpios = <&gpio1 2 0>;
-		        default-state = "on";
+			gpios = <&gpio1 2 0>;
+			default-state = "on";
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-tx6.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -429,8 +429,8 @@
 	pinctrl_edt_ft5x06: edt-ft5x06grp {
 		fsl,pins = <
 			MX6QDL_PAD_NANDF_CS2__GPIO6_IO15	0x1b0b0 /* Interrupt */
-			MX6QDL_PAD_EIM_A16__GPIO2_IO22  	0x1b0b0 /* Reset */
-			MX6QDL_PAD_EIM_A17__GPIO2_IO21  	0x1b0b0 /* Wake */
+			MX6QDL_PAD_EIM_A16__GPIO2_IO22		0x1b0b0 /* Reset */
+			MX6QDL_PAD_EIM_A17__GPIO2_IO21		0x1b0b0 /* Wake */
 		>;
 	};
 
@@ -481,21 +481,21 @@
 
 	pinctrl_gpmi_nand: gpminandgrp {
 		fsl,pins = <
-			MX6QDL_PAD_NANDF_CLE__NAND_CLE    	0x0b0b1
-			MX6QDL_PAD_NANDF_ALE__NAND_ALE    	0x0b0b1
-			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B  	0x0b0b1
+			MX6QDL_PAD_NANDF_CLE__NAND_CLE		0x0b0b1
+			MX6QDL_PAD_NANDF_ALE__NAND_ALE		0x0b0b1
+			MX6QDL_PAD_NANDF_WP_B__NAND_WP_B	0x0b0b1
 			MX6QDL_PAD_NANDF_RB0__NAND_READY_B	0x0b000
-			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B  	0x0b0b1
-			MX6QDL_PAD_SD4_CMD__NAND_RE_B     	0x0b0b1
-			MX6QDL_PAD_SD4_CLK__NAND_WE_B     	0x0b0b1
-			MX6QDL_PAD_NANDF_D0__NAND_DATA00  	0x0b0b1
-			MX6QDL_PAD_NANDF_D1__NAND_DATA01  	0x0b0b1
-			MX6QDL_PAD_NANDF_D2__NAND_DATA02  	0x0b0b1
-			MX6QDL_PAD_NANDF_D3__NAND_DATA03  	0x0b0b1
-			MX6QDL_PAD_NANDF_D4__NAND_DATA04  	0x0b0b1
-			MX6QDL_PAD_NANDF_D5__NAND_DATA05  	0x0b0b1
-			MX6QDL_PAD_NANDF_D6__NAND_DATA06  	0x0b0b1
-			MX6QDL_PAD_NANDF_D7__NAND_DATA07  	0x0b0b1
+			MX6QDL_PAD_NANDF_CS0__NAND_CE0_B	0x0b0b1
+			MX6QDL_PAD_SD4_CMD__NAND_RE_B		0x0b0b1
+			MX6QDL_PAD_SD4_CLK__NAND_WE_B		0x0b0b1
+			MX6QDL_PAD_NANDF_D0__NAND_DATA00	0x0b0b1
+			MX6QDL_PAD_NANDF_D1__NAND_DATA01	0x0b0b1
+			MX6QDL_PAD_NANDF_D2__NAND_DATA02	0x0b0b1
+			MX6QDL_PAD_NANDF_D3__NAND_DATA03	0x0b0b1
+			MX6QDL_PAD_NANDF_D4__NAND_DATA04	0x0b0b1
+			MX6QDL_PAD_NANDF_D5__NAND_DATA05	0x0b0b1
+			MX6QDL_PAD_NANDF_D6__NAND_DATA06	0x0b0b1
+			MX6QDL_PAD_NANDF_D7__NAND_DATA07	0x0b0b1
 		>;
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-wandboard.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -129,8 +129,8 @@
 
 		pinctrl_i2c1: i2c1grp {
 			fsl,pins = <
-				MX6QDL_PAD_EIM_D21__I2C1_SCL 		0x4001b8b1
-				MX6QDL_PAD_EIM_D28__I2C1_SDA 		0x4001b8b1
+				MX6QDL_PAD_EIM_D21__I2C1_SCL		0x4001b8b1
+				MX6QDL_PAD_EIM_D28__I2C1_SDA		0x4001b8b1
 			>;
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 				MX6QDL_PAD_EIM_D29__GPIO3_IO29		0x80000000	/* RGMII_nRST */
 				MX6QDL_PAD_EIM_DA13__GPIO3_IO13		0x80000000	/* BT_ON */
 				MX6QDL_PAD_EIM_DA14__GPIO3_IO14		0x80000000	/* BT_WAKE */
-				MX6QDL_PAD_EIM_DA15__GPIO3_IO15		0x80000000	/* BT_HOST_WAKE */				
+				MX6QDL_PAD_EIM_DA15__GPIO3_IO15		0x80000000	/* BT_HOST_WAKE */
 			>;
 		};
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-evi.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-evi.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-evi.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-evi.dts	2017-02-12 16:03:20.000000000 -0500
@@ -232,10 +232,7 @@
 };
 
 &weim {
-	#address-cells = <2>;
-	#size-cells = <1>;
 	ranges = <0 0 0x08000000 0x08000000>;
-	fsl,weim-cs-gpr = <&gpr>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_weimfpga &pinctrl_weimcs>;
 	status = "okay";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-icore.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-icore.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-icore.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-icore.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Amarula Solutions B.V.
+ * Copyright (C) 2016 Engicam S.r.l.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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.
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-icore.dtsi"
+
+/ {
+	model = "Engicam i.CoreM6 Quad/Dual Starter Kit";
+	compatible = "engicam,imx6-icore", "fsl,imx6q";
+};
+
+&can1 {
+	status = "okay";
+};
+
+&can2 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-nitrogen6_som2.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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.
+ */
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-nitrogen6_som2.dtsi"
+
+/ {
+	model = "Boundary Devices i.MX6 Quad Nitrogen6_SOM2 Board";
+	compatible = "boundary,imx6q-nitrogen6_som2", "fsl,imx6q";
+};
+
+&sata {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-novena.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-novena.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-novena.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-novena.dts	2017-02-12 16:03:20.000000000 -0500
@@ -451,6 +451,10 @@
 	status = "okay";
 };
 
+&pwm1 {
+	status = "okay";
+};
+
 &sata {
 	target-supply = <&reg_sata>;
 	fsl,transmit-level-mV = <1025>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qp.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qp.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6qp.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6qp.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -85,5 +85,22 @@
 		pcie: pcie@0x01000000 {
 			compatible = "fsl,imx6qp-pcie", "snps,dw-pcie";
 		};
+
+		aips-bus@02100000 {
+			mmdc0: mmdc@021b0000 { /* MMDC0 */
+				compatible = "fsl,imx6qp-mmdc", "fsl,imx6q-mmdc";
+				reg = <0x021b0000 0x4000>;
+			};
+		};
 	};
 };
+
+&ldb {
+	clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+		 <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
+		 <&clks IMX6QDL_CLK_IPU2_DI0_SEL>, <&clks IMX6QDL_CLK_IPU2_DI1_SEL>,
+		 <&clks IMX6QDL_CLK_LDB_DI0_PODF>, <&clks IMX6QDL_CLK_LDB_DI1_PODF>;
+	clock-names = "di0_pll", "di1_pll",
+		      "di0_sel", "di1_sel", "di2_sel", "di3_sel",
+		      "di0", "di1";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-phytec-pbab01.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-phytec-pbab01.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-phytec-pbab01.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-phytec-pbab01.dts	2017-02-12 16:03:20.000000000 -0500
@@ -23,5 +23,5 @@
 };
 
 &sata {
-        status = "okay";
+	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1010-comtft.dts	2017-02-12 16:03:20.000000000 -0500
@@ -105,7 +105,7 @@
 				pixelclk-active = <1>;
 			};
 		};
-        };
+	};
 };
 
 &can1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1010.dts	2017-02-12 16:03:20.000000000 -0500
@@ -199,7 +199,7 @@
 				pixelclk-active = <0>;
 			};
 		};
-        };
+	};
 };
 
 &ipu1_di0_disp0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1020-comtft.dts	2017-02-12 16:03:20.000000000 -0500
@@ -105,7 +105,7 @@
 				pixelclk-active = <1>;
 			};
 		};
-        };
+	};
 };
 
 &can1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-tx6q-1020.dts	2017-02-12 16:03:20.000000000 -0500
@@ -199,7 +199,7 @@
 				pixelclk-active = <0>;
 			};
 		};
-        };
+	};
 };
 
 &ds1339 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-utilite-pro.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-utilite-pro.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6q-utilite-pro.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6q-utilite-pro.dts	2017-02-12 16:03:20.000000000 -0500
@@ -68,7 +68,41 @@
 			label = "Power Button";
 			gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
-			gpio-key,wakeup;
+			wakeup-source;
+		};
+	};
+
+	i2cmux {
+		compatible = "i2c-mux-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c1mux>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mux-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+		i2c-parent = <&i2c1>;
+
+		i2c@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			eeprom@50 {
+				compatible = "at24,24c02";
+				reg = <0x50>;
+				pagesize = <16>;
+			};
+
+			em3027: rtc@56 {
+				compatible = "emmicro,em3027";
+				reg = <0x56>;
+			};
+		};
+
+		i2c_dvi_ddc: i2c@1 {
+			reg = <1>;
+			#address-cells = <1>;
+			#size-cells = <0>;
 		};
 	};
 };
@@ -82,17 +116,6 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
-
-	eeprom@50 {
-		compatible = "at24,24c02";
-		reg = <0x50>;
-		pagesize = <16>;
-	};
-
-	em3027: rtc@56 {
-		compatible = "emmicro,em3027";
-		reg = <0x56>;
-	};
 };
 
 &i2c2 {
@@ -115,6 +138,12 @@
 		>;
 	};
 
+	pinctrl_i2c1mux: i2c1muxgrp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
+		>;
+	};
+
 	pinctrl_i2c2: i2c2grp {
 		fsl,pins = <
 			MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sl.dtsi	2016-12-11 17:43:25.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sl.dtsi	2017-02-12 17:27:23.000000000 -0500
@@ -8,11 +8,21 @@
  */
 
 #include <dt-bindings/interrupt-controller/irq.h>
-#include "skeleton.dtsi"
 #include "imx6sl-pinfunc.h"
 #include <dt-bindings/clock/imx6sl-clock.h>
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec;
 		gpio0 = &gpio1;
@@ -893,8 +903,12 @@
 			};
 
 			weim: weim@021b8000 {
+				#address-cells = <2>;
+				#size-cells = <1>;
 				reg = <0x021b8000 0x4000>;
 				interrupts = <0 14 IRQ_TYPE_LEVEL_HIGH>;
+				fsl,weim-cs-gpr = <&gpr>;
+				status = "disabled";
 			};
 
 			ocotp: ocotp@021bc000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx.dtsi	2016-12-11 17:43:28.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx.dtsi	2017-02-12 17:27:31.000000000 -0500
@@ -11,9 +11,19 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "imx6sx-pinfunc.h"
-#include "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		can0 = &flexcan1;
 		can1 = &flexcan2;
@@ -858,7 +868,7 @@
 				fsl,num-tx-queues=<3>;
 				fsl,num-rx-queues=<3>;
 				status = "disabled";
-                        };
+			};
 
 			mlb: mlb@0218c000 {
 				reg = <0x0218c000 0x4000>;
@@ -968,10 +978,14 @@
 			};
 
 			weim: weim@021b8000 {
+				#address-cells = <2>;
+				#size-cells = <1>;
 				compatible = "fsl,imx6sx-weim", "fsl,imx6q-weim";
 				reg = <0x021b8000 0x4000>;
 				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SX_CLK_EIM_SLOW>;
+				fsl,weim-cs-gpr = <&gpr>;
+				status = "disabled";
 			};
 
 			ocotp: ocotp@021bc000 {
@@ -1143,7 +1157,7 @@
 				lcdif1: lcdif@02220000 {
 					compatible = "fsl,imx6sx-lcdif", "fsl,imx28-lcdif";
 					reg = <0x02220000 0x4000>;
-					interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+					interrupts = <GIC_SPI 5 IRQ_TYPE_EDGE_RISING>;
 					clocks = <&clks IMX6SX_CLK_LCDIF1_PIX>,
 						 <&clks IMX6SX_CLK_LCDIF_APB>,
 						 <&clks IMX6SX_CLK_DISPLAY_AXI>;
@@ -1154,7 +1168,7 @@
 				lcdif2: lcdif@02224000 {
 					compatible = "fsl,imx6sx-lcdif", "fsl,imx28-lcdif";
 					reg = <0x02224000 0x4000>;
-					interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+					interrupts = <GIC_SPI 6 IRQ_TYPE_EDGE_RISING>;
 					clocks = <&clks IMX6SX_CLK_LCDIF2_PIX>,
 						 <&clks IMX6SX_CLK_LCDIF_APB>,
 						 <&clks IMX6SX_CLK_DISPLAY_AXI>;
@@ -1181,7 +1195,7 @@
 				fsl,adck-max-frequency = <30000000>, <40000000>,
 							 <20000000>;
 				status = "disabled";
-                        };
+			};
 
 			adc2: adc@02284000 {
 				compatible = "fsl,imx6sx-adc", "fsl,vf610-adc";
@@ -1192,7 +1206,7 @@
 				fsl,adck-max-frequency = <30000000>, <40000000>,
 							 <20000000>;
 				status = "disabled";
-                        };
+			};
 
 			wdog3: wdog@02288000 {
 				compatible = "fsl,imx6sx-wdt", "fsl,imx21-wdt";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-sdb.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -192,10 +192,10 @@
 };
 
 &i2c4 {
-        clock-frequency = <100000>;
-        pinctrl-names = "default";
-        pinctrl-0 = <&pinctrl_i2c4>;
-        status = "okay";
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c4>;
+	status = "okay";
 
 	codec: wm8962@1a {
 		compatible = "wlf,wm8962";
@@ -290,6 +290,14 @@
 	status = "okay";
 };
 
+&usbphy1 {
+	fsl,tx-d-cal = <106>;
+};
+
+&usbphy2 {
+	fsl,tx-d-cal = <106>;
+};
+
 &usdhc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc2>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-basic.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "imx6sx-udoo-neo.dtsi"
+
+/ {
+	model = "UDOO Neo Basic";
+	compatible = "udoo,neobasic", "fsl,imx6sx";
+
+	memory {
+		reg = <0x80000000 0x20000000>;
+	};
+};
+
+&fec1 {
+	phy-handle = <&ethphy1>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy1: ethernet-phy@0 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "imx6sx.dtsi"
+
+/ {
+	compatible = "fsl,imx6sx";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		red {
+			label = "udoo-neo:red:mmc";
+			gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "mmc0";
+		};
+
+		orange {
+			label = "udoo-neo:orange:user";
+			gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
+			default-state = "keep";
+		};
+	};
+
+	reg_sdio_pwr: regulator-sdio-pwr {
+		compatible = "regulator-fixed";
+		gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-name = "SDIO_PWR";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+	};
+};
+
+&cpu0 {
+	arm-supply = <&sw1a_reg>;
+	soc-supply = <&sw1c_reg>;
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rmii";
+	phy-reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	clock-frequency = <100000>;
+	status = "okay";
+
+	pmic: pmic@08 {
+		compatible = "fsl,pfuze3000";
+		reg = <0x08>;
+
+		regulators {
+			sw1a_reg: sw1a {
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1475000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw1c_reg: sw1b {
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1475000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <6250>;
+			};
+
+			sw2_reg: sw2 {
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <1850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			sw3a_reg: sw3 {
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1650000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			swbst_reg: swbst {
+				regulator-min-microvolt = <5000000>;
+				regulator-max-microvolt = <5150000>;
+			};
+
+			snvs_reg: vsnvs {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vref_reg: vrefddr {
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			vgen1_reg: vldo1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen2_reg: vldo2 {
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1550000>;
+			};
+
+			vgen3_reg: vccsd {
+				regulator-min-microvolt = <2850000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen4_reg: v33 {
+				regulator-min-microvolt = <2850000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen5_reg: vldo3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			vgen6_reg: vldo4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl_enet1: enet1grp {
+		fsl,pins =
+			<MX6SX_PAD_ENET1_CRS__GPIO2_IO_1	0xa0b1>,
+			<MX6SX_PAD_ENET1_MDC__ENET1_MDC		0xa0b1>,
+			<MX6SX_PAD_ENET1_MDIO__ENET1_MDIO	0xa0b1>,
+			<MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0	0xa0b1>,
+			<MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1	0xa0b1>,
+			<MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN	0xa0b1>,
+
+			<MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x3081>,
+			<MX6SX_PAD_ENET2_TX_CLK__GPIO2_IO_9	0x3081>,
+			<MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0	0x3081>,
+			<MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1	0x3081>,
+			<MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN	0x3081>,
+			<MX6SX_PAD_RGMII1_RXC__ENET1_RX_ER	0x3081>,
+
+			<MX6SX_PAD_ENET2_RX_CLK__ENET2_REF_CLK_25M	0x91>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins =
+			<MX6SX_PAD_GPIO1_IO00__I2C1_SCL		0x4001b8b1>,
+			<MX6SX_PAD_GPIO1_IO01__I2C1_SDA		0x4001b8b1>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins =
+			<MX6SX_PAD_GPIO1_IO04__UART1_TX		0x1b0b1>,
+			<MX6SX_PAD_GPIO1_IO05__UART1_RX		0x1b0b1>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins =
+			<MX6SX_PAD_GPIO1_IO06__UART2_TX		0x1b0b1>,
+			<MX6SX_PAD_GPIO1_IO07__UART2_RX		0x1b0b1>;
+	};
+
+	pinctrl_uart5: uart5grp {
+		fsl,pins =
+			<MX6SX_PAD_SD4_DATA4__UART5_RX		0x1b0b1>,
+			<MX6SX_PAD_SD4_DATA5__UART5_TX		0x1b0b1>;
+	};
+
+	pinctrl_uart6: uart6grp {
+		fsl,pins =
+			<MX6SX_PAD_CSI_DATA00__UART6_RI_B	0x1b0b1>,
+			<MX6SX_PAD_CSI_DATA01__UART6_DSR_B	0x1b0b1>,
+			<MX6SX_PAD_CSI_DATA02__UART6_DTR_B	0x1b0b1>,
+			<MX6SX_PAD_CSI_DATA03__UART6_DCD_B	0x1b0b1>,
+			<MX6SX_PAD_CSI_DATA04__UART6_RX		0x1b0b1>,
+			<MX6SX_PAD_CSI_DATA05__UART6_TX		0x1b0b1>,
+			<MX6SX_PAD_CSI_DATA06__UART6_RTS_B	0x1b0b1>,
+			<MX6SX_PAD_CSI_DATA07__UART6_CTS_B	0x1b0b1>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins =
+			<MX6SX_PAD_SD2_CMD__USDHC2_CMD		0x17059>,
+			<MX6SX_PAD_SD2_CLK__USDHC2_CLK		0x10059>,
+			<MX6SX_PAD_SD2_DATA0__USDHC2_DATA0	0x17059>,
+			<MX6SX_PAD_SD2_DATA1__USDHC2_DATA1	0x17059>,
+			<MX6SX_PAD_SD2_DATA2__USDHC2_DATA2	0x17059>,
+			<MX6SX_PAD_SD2_DATA3__USDHC2_DATA3	0x17059>,
+			<MX6SX_PAD_SD1_DATA0__GPIO6_IO_2	0x17059>; /* CD */
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+/* Cortex-M4 serial */
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "disabled";
+};
+
+/* Arduino serial */
+&uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart5>;
+	status = "disabled";
+};
+
+&uart6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart6>;
+	uart-has-rtscts;
+	status = "disabled";
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	vmmc-supply = <&reg_sdio_pwr>;
+	bus-width = <4>;
+	cd-gpios = <&gpio6 2 GPIO_ACTIVE_LOW>;
+	no-1-8-v;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-extended.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "imx6sx-udoo-neo.dtsi"
+
+/ {
+	model = "UDOO Neo Extended";
+	compatible = "udoo,neoextended", "fsl,imx6sx";
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6sx-udoo-neo-full.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "imx6sx-udoo-neo.dtsi"
+
+/ {
+	model = "UDOO Neo Full";
+	compatible = "udoo,neofull", "fsl,imx6sx";
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+};
+
+&fec1 {
+	phy-handle = <&ethphy1>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy1: ethernet-phy@0 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <0>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul-14x14-evk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -225,7 +225,7 @@
 };
 
 &usbotg1 {
-	dr_mode = "peripheral";
+	dr_mode = "otg";
 	status = "okay";
 };
 
@@ -235,6 +235,14 @@
 	status = "okay";
 };
 
+&usbphy1 {
+	fsl,tx-d-cal = <106>;
+};
+
+&usbphy2 {
+	fsl,tx-d-cal = <106>;
+};
+
 &usdhc1 {
 	pinctrl-names = "default", "state_100mhz", "state_200mhz";
 	pinctrl-0 = <&pinctrl_usdhc1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul.dtsi	2016-12-11 17:43:31.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul.dtsi	2017-02-12 17:27:42.000000000 -0500
@@ -11,9 +11,19 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "imx6ul-pinfunc.h"
-#include "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		ethernet0 = &fec1;
 		ethernet1 = &fec2;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ull-14x14-evk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ull-14x14-evk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ull-14x14-evk.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ull-14x14-evk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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 "imx6ul-14x14-evk.dts"
+
+/ {
+	model = "Freescale i.MX6 UlltraLite 14x14 EVK Board";
+	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
+};
+
+&clks {
+	assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>;
+	assigned-clock-rates = <320000000>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ull.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ull.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ull.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ull.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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 "imx6ul.dtsi"
+#include "imx6ull-pinfunc.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul-liteboard.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul-liteboard.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul-liteboard.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul-liteboard.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2016 Grinn
+ *
+ * Author: Marcin Niestroj <m.niestroj@grinn-global.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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.
+ */
+
+/dts-v1/;
+
+#include "imx6ul-litesom.dtsi"
+
+/ {
+	model = "Grinn i.MX6UL liteBoard";
+	compatible = "grinn,imx6ul-liteboard", "grinn,imx6ul-litesom",
+		     "fsl,imx6ul";
+
+	chosen {
+		stdout-path = &uart1;
+	};
+
+	reg_usb_otg1_vbus: regulator-usb-otg1-vbus {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_usb_otg1_vbus>;
+		regulator-name = "usb_otg1_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&gpio2 8 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&iomuxc {
+	pinctrl_enet1: enet1grp {
+		fsl,pins = <
+			MX6UL_PAD_GPIO1_IO07__ENET1_MDC		0x1b0b0
+			MX6UL_PAD_GPIO1_IO06__ENET1_MDIO	0x1b0b0
+			MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00 0x1b0b0
+			MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01 0x1b0b0
+			MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00 0x1b0b0
+			MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01 0x1b0b0
+			MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX	0x1b0b1
+			MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX	0x1b0b1
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059
+			MX6UL_PAD_SD1_CMD__USDHC1_CMD		0x17059
+			MX6UL_PAD_SD1_CLK__USDHC1_CLK		0x10071
+			MX6UL_PAD_SD1_DATA0__USDHC1_DATA0	0x17059
+			MX6UL_PAD_SD1_DATA1__USDHC1_DATA1	0x17059
+			MX6UL_PAD_SD1_DATA2__USDHC1_DATA2	0x17059
+			MX6UL_PAD_SD1_DATA3__USDHC1_DATA3	0x17059
+		>;
+	};
+
+	pinctrl_usb_otg1_vbus: usb-otg1-vbus {
+		fsl,pins = <
+			MX6UL_PAD_ENET2_RX_DATA0__GPIO2_IO08	0x79
+		>;
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_enet1>;
+	phy-mode = "rmii";
+	phy-handle = <&ethphy0>;
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy0: ethernet-phy@0 {
+			reg = <0>;
+		};
+	};
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>;
+	status = "okay";
+};
+
+&usbotg1 {
+	vbus-supply = <&reg_usb_otg1_vbus>;
+	dr_mode = "host";
+	status = "okay";
+};
+
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
+	no-1-8-v;
+	keep-power-in-suspend;
+	wakeup-source;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul-litesom.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul-litesom.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ul-litesom.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ul-litesom.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Grinn
+ *
+ * Author: Marcin Niestroj <m.niestroj@grinn-global.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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 "imx6ul.dtsi"
+
+/ {
+	model = "Grinn i.MX6UL liteSOM";
+	compatible = "grinn,imx6ul-litesom", "fsl,imx6ul";
+
+	memory {
+		reg = <0x80000000 0x20000000>;
+	};
+};
+
+&iomuxc {
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX6UL_PAD_NAND_RE_B__USDHC2_CLK	    0x10069
+			MX6UL_PAD_NAND_WE_B__USDHC2_CMD	    0x17059
+			MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
+			MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
+			MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
+			MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
+			MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
+			MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
+			MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
+			MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
+			MX6UL_PAD_NAND_ALE__USDHC2_RESET_B  0x17059
+		>;
+	};
+};
+
+&usdhc2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc2>;
+	no-1-8-v;
+	non-removable;
+	keep-power-in-suspend;
+	wakeup-source;
+	bus-width = <8>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ull-pinfunc.h linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ull-pinfunc.h
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx6ull-pinfunc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx6ull-pinfunc.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DTS_IMX6ULL_PINFUNC_H
+#define __DTS_IMX6ULL_PINFUNC_H
+
+#include "imx6ul-pinfunc.h"
+/*
+ * The pin function ID is a tuple of
+ * <mux_reg conf_reg input_reg mux_mode input_val>
+ */
+#define MX6ULL_PAD_ENET2_RX_DATA0__EPDC_SDDO08                    0x00E4 0x0370 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_RX_DATA1__EPDC_SDDO09                    0x00E8 0x0374 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_RX_EN__EPDC_SDDO10                       0x00EC 0x0378 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_DATA0__EPDC_SDDO11                    0x00F0 0x037C 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_DATA1__EPDC_SDDO12                    0x00F4 0x0380 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_EN__EPDC_SDDO13                       0x00F8 0x0384 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_TX_CLK__EPDC_SDDO14                      0x00FC 0x0388 0x0000 0x9 0x0
+#define MX6ULL_PAD_ENET2_RX_ER__EPDC_SDDO15                       0x0100 0x038C 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_CLK__EPDC_SDCLK                            0x0104 0x0390 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_ENABLE__EPDC_SDLE                          0x0108 0x0394 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_HSYNC__EPDC_SDOE                           0x010C 0x0398 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_VSYNC__EPDC_SDCE0                          0x0110 0x039C 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_RESET__EPDC_GDOE                           0x0114 0x03A0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA00__EPDC_SDDO00                        0x0118 0x03A4 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA01__EPDC_SDDO01                        0x011C 0x03A8 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA02__EPDC_SDDO02                        0x0120 0x03AC 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA03__EPDC_SDDO03                        0x0124 0x03B0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA04__EPDC_SDDO04                        0x0128 0x03B4 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA05__EPDC_SDDO05                        0x012C 0x03B8 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA06__EPDC_SDDO06                        0x0130 0x03BC 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA07__EPDC_SDDO07                        0x0134 0x03C0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA14__EPDC_SDSHR                         0x0150 0x03DC 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA15__EPDC_GDRL                          0x0154 0x03E0 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA16__EPDC_GDCLK                         0x0158 0x03E4 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA17__EPDC_GDSP                          0x015C 0x03E8 0x0000 0x9 0x0
+#define MX6ULL_PAD_LCD_DATA21__EPDC_SDCE1                         0x016C 0x03F8 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_MCLK__ESAI_TX3_RX2                         0x01D4 0x0460 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_PIXCLK__ESAI_TX2_RX3                       0x01D8 0x0464 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_VSYNC__ESAI_TX4_RX1                        0x01DC 0x0468 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_HSYNC__ESAI_TX1                            0x01E0 0x046C 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA00__ESAI_TX_HF_CLK                     0x01E4 0x0470 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA01__ESAI_RX_HF_CLK                     0x01E8 0x0474 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA02__ESAI_RX_FS                         0x01EC 0x0478 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA03__ESAI_RX_CLK                        0x01F0 0x047C 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS                         0x01F4 0x0480 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK                        0x01F8 0x0484 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA06__ESAI_TX5_RX0                       0x01FC 0x0488 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA07__ESAI_T0                            0x0200 0x048C 0x0000 0x9 0x0
+
+#endif /* __DTS_IMX6ULL_PINFUNC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx7d-pinfunc.h linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx7d-pinfunc.h
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx7d-pinfunc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx7d-pinfunc.h	2017-02-12 16:03:20.000000000 -0500
@@ -43,26 +43,30 @@
 #define MX7D_PAD_GPIO1_IO04__GPIO1_IO4                            0x0010 0x0040 0x0000 0x0 0x0
 #define MX7D_PAD_GPIO1_IO04__USB_OTG1_OC                          0x0010 0x0040 0x072C 0x1 0x1
 #define MX7D_PAD_GPIO1_IO04__FLEXTIMER1_CH4                       0x0010 0x0040 0x0594 0x2 0x1
-#define MX7D_PAD_GPIO1_IO04__UART5_CTS_B                          0x0010 0x0040 0x0710 0x3 0x4
+#define MX7D_PAD_GPIO1_IO04__UART5_DCE_CTS                        0x0010 0x0040 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO04__UART5_DTE_RTS                        0x0010 0x0040 0x0710 0x3 0x4
 #define MX7D_PAD_GPIO1_IO04__I2C1_SCL                             0x0010 0x0040 0x05D4 0x4 0x2
 #define MX7D_PAD_GPIO1_IO04__OBSERVE3_OUT                         0x0010 0x0040 0x0000 0x6 0x0
 #define MX7D_PAD_GPIO1_IO05__GPIO1_IO5                            0x0014 0x0044 0x0000 0x0 0x0
 #define MX7D_PAD_GPIO1_IO05__USB_OTG1_PWR                         0x0014 0x0044 0x0000 0x1 0x0
 #define MX7D_PAD_GPIO1_IO05__FLEXTIMER1_CH5                       0x0014 0x0044 0x0598 0x2 0x1
-#define MX7D_PAD_GPIO1_IO05__UART5_RTS_B                          0x0014 0x0044 0x0710 0x3 0x5
+#define MX7D_PAD_GPIO1_IO05__UART5_DCE_RTS                        0x0014 0x0044 0x0710 0x3 0x5
+#define MX7D_PAD_GPIO1_IO05__UART5_DTE_CTS                        0x0014 0x0044 0x0000 0x3 0x0
 #define MX7D_PAD_GPIO1_IO05__I2C1_SDA                             0x0014 0x0044 0x05D8 0x4 0x2
 #define MX7D_PAD_GPIO1_IO05__OBSERVE4_OUT                         0x0014 0x0044 0x0000 0x6 0x0
 #define MX7D_PAD_GPIO1_IO06__GPIO1_IO6                            0x0018 0x0048 0x0000 0x0 0x0
 #define MX7D_PAD_GPIO1_IO06__USB_OTG2_OC                          0x0018 0x0048 0x0728 0x1 0x1
 #define MX7D_PAD_GPIO1_IO06__FLEXTIMER1_CH6                       0x0018 0x0048 0x059C 0x2 0x1
-#define MX7D_PAD_GPIO1_IO06__UART5_RX_DATA                        0x0018 0x0048 0x0714 0x3 0x4
+#define MX7D_PAD_GPIO1_IO06__UART5_DCE_RX                         0x0018 0x0048 0x0714 0x3 0x4
+#define MX7D_PAD_GPIO1_IO06__UART5_DTE_TX                         0x0018 0x0048 0x0000 0x3 0x0
 #define MX7D_PAD_GPIO1_IO06__I2C2_SCL                             0x0018 0x0048 0x05DC 0x4 0x2
 #define MX7D_PAD_GPIO1_IO06__CCM_WAIT                             0x0018 0x0048 0x0000 0x5 0x0
 #define MX7D_PAD_GPIO1_IO06__KPP_ROW4                             0x0018 0x0048 0x0624 0x6 0x1
 #define MX7D_PAD_GPIO1_IO07__GPIO1_IO7                            0x001C 0x004C 0x0000 0x0 0x0
 #define MX7D_PAD_GPIO1_IO07__USB_OTG2_PWR                         0x001C 0x004C 0x0000 0x1 0x0
 #define MX7D_PAD_GPIO1_IO07__FLEXTIMER1_CH7                       0x001C 0x004C 0x05A0 0x2 0x1
-#define MX7D_PAD_GPIO1_IO07__UART5_TX_DATA                        0x001C 0x004C 0x0714 0x3 0x5
+#define MX7D_PAD_GPIO1_IO07__UART5_DCE_TX                         0x001C 0x004C 0x0000 0x3 0x0
+#define MX7D_PAD_GPIO1_IO07__UART5_DTE_RX                         0x001C 0x004C 0x0714 0x3 0x5
 #define MX7D_PAD_GPIO1_IO07__I2C2_SDA                             0x001C 0x004C 0x05E0 0x4 0x2
 #define MX7D_PAD_GPIO1_IO07__CCM_STOP                             0x001C 0x004C 0x0000 0x5 0x0
 #define MX7D_PAD_GPIO1_IO07__KPP_COL4                             0x001C 0x004C 0x0604 0x6 0x1
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/imx7s.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx7s.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/imx7s.dtsi	2016-12-11 17:43:34.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/imx7s.dtsi	2017-02-12 17:27:46.000000000 -0500
@@ -46,9 +46,19 @@
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include "imx7d-pinfunc.h"
-#include "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	/*
+	 * The decompressor and also some bootloaders rely on a
+	 * pre-existing /chosen node to be available to insert the
+	 * command line and merge other ATAGS info.
+	 * Also for U-Boot there must be a pre-existing /memory node.
+	 */
+	chosen {};
+	memory { device_type = "memory"; reg = <0 0>; };
+
 	aliases {
 		gpio0 = &gpio1;
 		gpio1 = &gpio2;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/integratorap.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/integratorap.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/integratorap.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/integratorap.dts	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,41 @@
 	compatible = "arm,integrator-ap";
 	dma-ranges = <0x80000000 0x0 0x80000000>;
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			/*
+			 * Since the board has pluggable CPU modules, we
+			 * cannot define a proper compatible here. Let the
+			 * boot loader fill in the apropriate compatible
+			 * string if necessary.
+			 */
+			/* compatible = "arm,arm926ej-s"; */
+			reg = <0>;
+			/*
+			 * The documentation in ARM DUI 0138E page 3-12 states
+			 * that the maximum frequency for this clock is 200 MHz
+			 * but painful trial-and-error has proved to me that it
+			 * is actually just hanging the system above 71 MHz.
+			 * Sad but true.
+			 */
+					 /* kHz     uV   */
+			operating-points = <71000  0
+					    66000  0
+					    60000  0
+					    48000  0
+					    36000  0
+					    24000  0
+					    12000  0>;
+			clocks = <&cmosc>;
+			clock-names = "cpu";
+			clock-latency = <1000000>; /* 1 ms */
+		};
+	};
+
 	aliases {
 		arm,timer-primary = &timer2;
 		arm,timer-secondary = &timer1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/integratorcp.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/integratorcp.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/integratorcp.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/integratorcp.dts	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,32 @@
 		bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			/*
+			 * Since the board has pluggable CPU modules, we
+			 * cannot define a proper compatible here. Let the
+			 * boot loader fill in the apropriate compatible
+			 * string if necessary.
+			 */
+			/* compatible = "arm,arm920t"; */
+			reg = <0>;
+			/*
+			 * TBD comment.
+			 */
+					 /* kHz     uV   */
+			operating-points = <50000  0
+					    48000  0>;
+			clocks = <&cmcore>;
+			clock-names = "cpu";
+			clock-latency = <1000000>; /* 1 ms */
+		};
+	};
+
 	/*
 	 * The Integrator/CP overall clocking architecture can be found in
 	 * ARM DUI 0184B page 7-28 "Integrator/CP922T system clocks" which
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/keystone-k2g.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/keystone-k2g.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/keystone-k2g.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/keystone-k2g.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -72,6 +72,7 @@
 	soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
+		#pinctrl-cells = <1>;
 		compatible = "ti,keystone","simple-bus";
 		ranges = <0x0 0x0 0x0 0xc0000000>;
 		dma-ranges = <0x80000000 0x8 0x00000000 0x80000000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/keystone-k2l.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/keystone-k2l.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/keystone-k2l.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/keystone-k2l.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -59,6 +59,7 @@
 			reg = <0x02620690 0xc>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#pinctrl-cells = <2>;
 			pinctrl-single,bit-per-mux;
 			pinctrl-single,register-width = <32>;
 			pinctrl-single,function-mask = <0x1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/kirkwood-topkick.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/kirkwood-topkick.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/kirkwood-topkick.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/kirkwood-topkick.dts	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
 #include "kirkwood-6282.dtsi"
 
 / {
-	model = "Univeral Scientific Industrial Co. Topkick-1281P2";
+	model = "Universal Scientific Industrial Co. Topkick-1281P2";
 	compatible = "usi,topkick-1281P2", "usi,topkick", "marvell,kirkwood-88f6282", "marvell,kirkwood";
 
 	memory {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts	2017-02-12 16:03:20.000000000 -0500
@@ -158,7 +158,7 @@
 &mmc1 {
 	interrupts-extended = <&intc 83 &omap3_pmx_core 0x11a>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&mmc1_pins &mmc1_cd>;
+	pinctrl-0 = <&mmc1_pins>;
 	wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>;		/* gpio_126 */
 	cd-gpios = <&gpio4 14 IRQ_TYPE_LEVEL_LOW>;		/* gpio_110 */
 	vmmc-supply = <&vmmc1>;
@@ -193,7 +193,8 @@
 			OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT | MUX_MODE0)	/* sdmmc1_dat1.sdmmc1_dat1 */
 			OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT | MUX_MODE0)	/* sdmmc1_dat2.sdmmc1_dat2 */
 			OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT | MUX_MODE0)	/* sdmmc1_dat3.sdmmc1_dat3 */
-			OMAP3_CORE1_IOPAD(0x2132, PIN_INPUT_PULLUP | MUX_MODE4)	/* cam_strobe.gpio_126 sdmmc1_wp*/
+			OMAP3_CORE1_IOPAD(0x2132, PIN_INPUT_PULLUP | MUX_MODE4)	/* cam_strobe.gpio_126 */
+			OMAP3_CORE1_IOPAD(0x212c, PIN_INPUT_PULLUP | MUX_MODE4)	/* cam_d11.gpio_110 */
 		>;
 	};
 
@@ -242,12 +243,6 @@
 			OMAP3_WKUP_IOPAD(0x2a16, PIN_OUTPUT | PIN_OFF_OUTPUT_LOW | MUX_MODE4)       /* sys_boot6.gpio_8 */
 		>;
 	};
-
-	mmc1_cd: pinmux_mmc1_cd {
-		pinctrl-single,pins = <
-			OMAP3_WKUP_IOPAD(0x212c, PIN_INPUT_PULLUP | MUX_MODE4)	/* cam_d11.gpio_110 */
-		>;
-	};
 };
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/lpc32xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/lpc32xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/lpc32xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/lpc32xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -479,6 +479,8 @@
 				compatible = "nxp,lpc3220-pwm";
 				reg = <0x4005C000 0x4>;
 				clocks = <&clk LPC32XX_CLK_PWM1>;
+				assigned-clocks = <&clk LPC32XX_CLK_PWM1>;
+				assigned-clock-parents = <&clk LPC32XX_CLK_PERIPH>;
 				status = "disabled";
 			};
 
@@ -486,6 +488,8 @@
 				compatible = "nxp,lpc3220-pwm";
 				reg = <0x4005C004 0x4>;
 				clocks = <&clk LPC32XX_CLK_PWM2>;
+				assigned-clocks = <&clk LPC32XX_CLK_PWM2>;
+				assigned-clock-parents = <&clk LPC32XX_CLK_PERIPH>;
 				status = "disabled";
 			};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/ls1021a.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/ls1021a.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/ls1021a.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/ls1021a.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,7 @@
 
 #include "skeleton64.dtsi"
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
 	compatible = "fsl,ls1021a";
@@ -70,14 +71,15 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu@f00 {
+		cpu0: cpu@f00 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <0xf00>;
 			clocks = <&cluster1_clk>;
+			#cooling-cells = <2>;
 		};
 
-		cpu@f01 {
+		cpu1: cpu@f01 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <0xf01>;
@@ -251,6 +253,84 @@
 			};
 		};
 
+		tmu: tmu@1f00000 {
+			compatible = "fsl,qoriq-tmu";
+			reg = <0x0 0x1f00000 0x0 0x10000>;
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x30061>;
+			fsl,tmu-calibration = <0x00000000 0x0000000f
+					       0x00000001 0x00000017
+					       0x00000002 0x0000001e
+					       0x00000003 0x00000026
+					       0x00000004 0x0000002e
+					       0x00000005 0x00000035
+					       0x00000006 0x0000003d
+					       0x00000007 0x00000044
+					       0x00000008 0x0000004c
+					       0x00000009 0x00000053
+					       0x0000000a 0x0000005b
+					       0x0000000b 0x00000064
+
+					       0x00010000 0x00000011
+					       0x00010001 0x0000001c
+					       0x00010002 0x00000024
+					       0x00010003 0x0000002b
+					       0x00010004 0x00000034
+					       0x00010005 0x00000039
+					       0x00010006 0x00000042
+					       0x00010007 0x0000004c
+					       0x00010008 0x00000051
+					       0x00010009 0x0000005a
+					       0x0001000a 0x00000063
+
+					       0x00020000 0x00000013
+					       0x00020001 0x00000019
+					       0x00020002 0x00000024
+					       0x00020003 0x0000002c
+					       0x00020004 0x00000035
+					       0x00020005 0x0000003d
+					       0x00020006 0x00000046
+					       0x00020007 0x00000050
+					       0x00020008 0x00000059
+
+					       0x00030000 0x00000002
+					       0x00030001 0x0000000d
+					       0x00030002 0x00000019
+					       0x00030003 0x00000024>;
+			#thermal-sensor-cells = <1>;
+		};
+
+		thermal-zones {
+			cpu_thermal: cpu-thermal {
+				polling-delay-passive = <1000>;
+				polling-delay = <5000>;
+
+				thermal-sensors = <&tmu 0>;
+
+				trips {
+					cpu_alert: cpu-alert {
+						temperature = <85000>;
+						hysteresis = <2000>;
+						type = "passive";
+					};
+					cpu_crit: cpu-crit {
+						temperature = <95000>;
+						hysteresis = <2000>;
+						type = "critical";
+					};
+				};
+
+				cooling-maps {
+					map0 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu0 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+				};
+			};
+		};
+
 		dspi0: dspi@2100000 {
 			compatible = "fsl,ls1021a-v1.0-dspi";
 			#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/Makefile linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/Makefile
--- linux-libre-4.9-gnu/arch/arm/boot/dts/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -75,6 +75,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm4708-asus-rt-ac56u.dtb \
 	bcm4708-asus-rt-ac68u.dtb \
 	bcm4708-buffalo-wzr-1750dhp.dtb \
+	bcm4708-luxul-xap-1510.dtb \
 	bcm4708-luxul-xwc-1000.dtb \
 	bcm4708-netgear-r6250.dtb \
 	bcm4708-netgear-r6300-v2.dtb \
@@ -86,11 +87,16 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
 	bcm4709-buffalo-wxr-1900dhp.dtb \
 	bcm4709-netgear-r7000.dtb \
 	bcm4709-netgear-r8000.dtb \
+	bcm4709-tplink-archer-c9-v1.dtb \
 	bcm47094-dlink-dir-885l.dtb \
+	bcm47094-luxul-xwr-3100.dtb \
+	bcm47094-netgear-r8500.dtb \
 	bcm94708.dtb \
 	bcm94709.dtb \
 	bcm953012er.dtb \
 	bcm953012k.dtb
+dtb-$(CONFIG_ARCH_BCM_53573) += \
+	bcm47189-tenda-ac9.dtb
 dtb-$(CONFIG_ARCH_BCM_63XX) += \
 	bcm963138dvt.dtb
 dtb-$(CONFIG_ARCH_BCM_CYGNUS) += \
@@ -136,6 +142,7 @@ dtb-$(CONFIG_ARCH_EXYNOS4) += \
 	exynos4210-smdkv310.dtb \
 	exynos4210-trats.dtb \
 	exynos4210-universal_c210.dtb \
+	exynos4412-itop-elite.dtb \
 	exynos4412-odroidu3.dtb \
 	exynos4412-odroidx.dtb \
 	exynos4412-odroidx2.dtb \
@@ -330,6 +337,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6dl-aristainetos_7.dtb \
 	imx6dl-aristainetos2_4.dtb \
 	imx6dl-aristainetos2_7.dtb \
+	imx6dl-colibri-eval-v3.dtb \
 	imx6dl-cubox-i.dtb \
 	imx6dl-dfi-fs700-m60.dtb \
 	imx6dl-gw51xx.dtb \
@@ -340,6 +348,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6dl-gw552x.dtb \
 	imx6dl-gw553x.dtb \
 	imx6dl-hummingboard.dtb \
+	imx6dl-icore.dtb \
 	imx6dl-nit6xlite.dtb \
 	imx6dl-nitrogen6x.dtb \
 	imx6dl-phytec-pbab01.dtb \
@@ -381,10 +390,12 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
 	imx6q-gw553x.dtb \
 	imx6q-h100.dtb \
 	imx6q-hummingboard.dtb \
+	imx6q-icore.dtb \
 	imx6q-icore-rqs.dtb \
 	imx6q-marsboard.dtb \
 	imx6q-nitrogen6x.dtb \
 	imx6q-nitrogen6_max.dtb \
+	imx6q-nitrogen6_som2.dtb \
 	imx6q-novena.dtb \
 	imx6q-phytec-pbab01.dtb \
 	imx6q-rex-pro.dtb \
@@ -416,14 +427,19 @@ dtb-$(CONFIG_SOC_IMX6SX) += \
 	imx6sx-sabreauto.dtb \
 	imx6sx-sdb-reva.dtb \
 	imx6sx-sdb-sai.dtb \
-	imx6sx-sdb.dtb
+	imx6sx-sdb.dtb \
+	imx6sx-udoo-neo-basic.dtb \
+	imx6sx-udoo-neo-extended.dtb \
+	imx6sx-udoo-neo-full.dtb
 dtb-$(CONFIG_SOC_IMX6UL) += \
 	imx6ul-14x14-evk.dtb \
 	imx6ul-geam-kit.dtb \
+	imx6ul-liteboard.dtb \
 	imx6ul-pico-hobbit.dtb \
 	imx6ul-tx6ul-0010.dtb \
 	imx6ul-tx6ul-0011.dtb \
-	imx6ul-tx6ul-mainboard.dtb
+	imx6ul-tx6ul-mainboard.dtb \
+	imx6ull-14x14-evk.dtb
 dtb-$(CONFIG_SOC_IMX7D) += \
 	imx7d-cl-som-imx7.dtb \
 	imx7d-colibri-eval-v3.dtb \
@@ -485,6 +501,7 @@ dtb-$(CONFIG_ARCH_OMAP3) += \
 	am3517-evm.dtb \
 	am3517_mt_ventoux.dtb \
 	logicpd-torpedo-37xx-devkit.dtb \
+	logicpd-som-lv-37xx-devkit.dtb \
 	omap3430-sdp.dtb \
 	omap3-beagle.dtb \
 	omap3-beagle-xm.dtb \
@@ -561,6 +578,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
 	am335x-sl50.dtb \
 	am335x-wega-rdk.dtb
 dtb-$(CONFIG_ARCH_OMAP4) += \
+	omap4-droid4-xt894.dtb \
 	omap4-duovero-parlor.dtb \
 	omap4-kc1.dtb \
 	omap4-panda.dtb \
@@ -588,15 +606,18 @@ dtb-$(CONFIG_SOC_DRA7XX) += \
 	am57xx-cl-som-am57x.dtb \
 	am57xx-sbc-am57x.dtb \
 	am572x-idk.dtb \
+	am571x-idk.dtb \
 	dra7-evm.dtb \
 	dra72-evm.dtb \
-	dra72-evm-revc.dtb
+	dra72-evm-revc.dtb \
+	dra71-evm.dtb
 dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-kuroboxpro.dtb \
 	orion5x-lacie-d2-network.dtb \
 	orion5x-lacie-ethernet-disk-mini-v2.dtb \
 	orion5x-linkstation-lsgl.dtb \
 	orion5x-linkstation-lswtgl.dtb \
+	orion5x-linkstation-lschl.dtb \
 	orion5x-lswsgl.dtb \
 	orion5x-maxtor-shared-storage-2.dtb \
 	orion5x-netgear-wnr854t.dtb \
@@ -604,7 +625,8 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
 dtb-$(CONFIG_ARCH_OXNAS) += \
-	wd-mbwe.dtb
+	wd-mbwe.dtb \
+	cloudengines-pogoplug-series-3.dtb
 dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-apq8060-dragonboard.dtb \
 	qcom-apq8064-arrow-sd-600eval.dtb \
@@ -620,7 +642,8 @@ dtb-$(CONFIG_ARCH_QCOM) += \
 	qcom-msm8660-surf.dtb \
 	qcom-msm8960-cdp.dtb \
 	qcom-msm8974-lge-nexus5-hammerhead.dtb \
-	qcom-msm8974-sony-xperia-honami.dtb
+	qcom-msm8974-sony-xperia-honami.dtb \
+	qcom-mdm9615-wp8548-mangoh-green.dtb
 dtb-$(CONFIG_ARCH_REALVIEW) += \
 	arm-realview-pb1176.dtb \
 	arm-realview-pb11mp.dtb \
@@ -635,11 +658,14 @@ dtb-$(CONFIG_ARCH_REALVIEW) += \
 	arm-realview-pba8.dtb \
 	arm-realview-pbx-a9.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
+	rk1108-evb.dtb \
 	rk3036-evb.dtb \
 	rk3036-kylin.dtb \
 	rk3066a-bqcurie2.dtb \
 	rk3066a-marsboard.dtb \
+	rk3066a-mk808.dtb \
 	rk3066a-rayeager.dtb \
+	rk3188-px3-evb.dtb \
 	rk3188-radxarock.dtb \
 	rk3228-evb.dtb \
 	rk3229-evb.dtb \
@@ -677,6 +703,8 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
 	r7s72100-rskrza1.dtb \
 	r8a73a4-ape6evm.dtb \
 	r8a7740-armadillo800eva.dtb \
+	r8a7743-sk-rzg1m.dtb \
+	r8a7745-sk-rzg1e.dtb \
 	r8a7778-bockw.dtb \
 	r8a7779-marzen.dtb \
 	r8a7790-lager.dtb \
@@ -690,12 +718,14 @@ dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
 	sh73a0-kzm9g.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += \
 	socfpga_arria5_socdk.dtb \
+	socfpga_arria10_socdk_qspi.dtb \
 	socfpga_arria10_socdk_sdmmc.dtb \
 	socfpga_cyclone5_mcvevk.dtb \
 	socfpga_cyclone5_socdk.dtb \
 	socfpga_cyclone5_de0_sockit.dtb \
 	socfpga_cyclone5_sockit.dtb \
 	socfpga_cyclone5_socrates.dtb \
+	socfpga_cyclone5_sodia.dtb \
 	socfpga_cyclone5_vining_fpga.dtb \
 	socfpga_vt.dtb
 dtb-$(CONFIG_ARCH_SPEAR13XX) += \
@@ -712,16 +742,12 @@ dtb-$(CONFIG_ARCH_STI) += \
 	stih407-b2120.dtb \
 	stih410-b2120.dtb \
 	stih410-b2260.dtb \
-	stih415-b2000.dtb \
-	stih415-b2020.dtb \
-	stih416-b2000.dtb \
-	stih416-b2020.dtb \
-	stih416-b2020e.dtb \
 	stih418-b2199.dtb
 dtb-$(CONFIG_ARCH_STM32)+= \
 	stm32f429-disco.dtb \
 	stm32f469-disco.dtb \
-	stm32429i-eval.dtb
+	stm32429i-eval.dtb \
+	stm32746g-eval.dtb
 dtb-$(CONFIG_MACH_SUN4I) += \
 	sun4i-a10-a1000.dtb \
 	sun4i-a10-ba10-tvbox.dtb \
@@ -760,6 +786,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \
 	sun5i-a13-olinuxino-micro.dtb \
 	sun5i-a13-q8-tablet.dtb \
 	sun5i-a13-utoo-p66.dtb \
+	sun5i-gr8-chip-pro.dtb \
 	sun5i-gr8-evb.dtb \
 	sun5i-r8-chip.dtb
 dtb-$(CONFIG_MACH_SUN6I) += \
@@ -819,6 +846,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
 	sun8i-a83t-allwinner-h8homlet-v2.dtb \
 	sun8i-a83t-cubietruck-plus.dtb \
 	sun8i-h3-bananapi-m2-plus.dtb \
+	sun8i-h3-nanopi-m1.dtb	\
 	sun8i-h3-nanopi-neo.dtb \
 	sun8i-h3-orangepi-2.dtb \
 	sun8i-h3-orangepi-lite.dtb \
@@ -897,6 +925,7 @@ dtb-$(CONFIG_ARCH_VT8500) += \
 	wm8750-apc8750.dtb \
 	wm8850-w70v2.dtb
 dtb-$(CONFIG_ARCH_ZYNQ) += \
+	zynq-microzed.dtb \
 	zynq-parallella.dtb \
 	zynq-zc702.dtb \
 	zynq-zc706.dtb \
@@ -920,6 +949,7 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \
 	armada-385-db-ap.dtb \
 	armada-385-linksys-caiman.dtb \
 	armada-385-linksys-cobra.dtb \
+	armada-385-turris-omnia.dtb \
 	armada-388-clearfog.dtb \
 	armada-388-db.dtb \
 	armada-388-gp.dtb \
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/mps2-an385.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mps2-an385.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/mps2-an385.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mps2-an385.dts	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@
 		stdout-path = "serial0:9600n8";
 	};
 
-	memory {
+	memory@21000000 {
 		device_type = "memory";
 		reg = <0x21000000 0x1000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/mps2-an399.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mps2-an399.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/mps2-an399.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mps2-an399.dts	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@
 		stdout-path = "serial0:9600n8";
 	};
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x1000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/mps2.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mps2.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/mps2.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mps2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -42,10 +42,12 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "skeleton.dtsi"
 #include "armv7-m.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	oscclk0: clk-osc0 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/mt2701.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mt2701.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/mt2701.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/mt2701.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -12,8 +12,10 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/clock/mt2701-clk.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/mt2701-resets.h>
 #include "skeleton64.dtsi"
 #include "mt2701-pinfunc.h"
 
@@ -71,10 +73,18 @@
 		#clock-cells = <0>;
 	};
 
-	uart_clk: dummy26m {
+	clk26m: oscillator@0 {
 		compatible = "fixed-clock";
+		#clock-cells = <0>;
 		clock-frequency = <26000000>;
+		clock-output-names = "clk26m";
+	};
+
+	rtc32k: oscillator@1 {
+		compatible = "fixed-clock";
 		#clock-cells = <0>;
+		clock-frequency = <32000>;
+		clock-output-names = "rtc32k";
 	};
 
 	timer {
@@ -104,6 +114,26 @@
 		reg = <0 0x10005000 0 0x1000>;
 	};
 
+	topckgen: syscon@10000000 {
+		compatible = "mediatek,mt2701-topckgen", "syscon";
+		reg = <0 0x10000000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	infracfg: syscon@10001000 {
+		compatible = "mediatek,mt2701-infracfg", "syscon";
+		reg = <0 0x10001000 0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	pericfg: syscon@10003000 {
+		compatible = "mediatek,mt2701-pericfg", "syscon";
+		reg = <0 0x10003000 0 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
 	watchdog: watchdog@10007000 {
 		compatible = "mediatek,mt2701-wdt",
 			     "mediatek,mt6589-wdt";
@@ -128,6 +158,12 @@
 		reg = <0 0x10200100 0 0x1c>;
 	};
 
+	apmixedsys: syscon@10209000 {
+		compatible = "mediatek,mt2701-apmixedsys", "syscon";
+		reg = <0 0x10209000 0 0x1000>;
+		#clock-cells = <1>;
+	};
+
 	gic: interrupt-controller@10211000 {
 		compatible = "arm,cortex-a7-gic";
 		interrupt-controller;
@@ -144,7 +180,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11002000 0 0x400>;
 		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -153,7 +190,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11003000 0 0x400>;
 		interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART1_SEL>, <&pericfg CLK_PERI_UART1>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -162,7 +200,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11004000 0 0x400>;
 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART2_SEL>, <&pericfg CLK_PERI_UART2>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 
@@ -171,7 +210,8 @@
 			     "mediatek,mt6577-uart";
 		reg = <0 0x11005000 0 0x400>;
 		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_LOW>;
-		clocks = <&uart_clk>;
+		clocks = <&pericfg CLK_PERI_UART3_SEL>, <&pericfg CLK_PERI_UART3>;
+		clock-names = "baud", "bus";
 		status = "disabled";
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap2420.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap2420.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap2420.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap2420.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,7 @@
 				reg = <0x0 0x1000>;
 				#address-cells = <1>;
 				#size-cells = <1>;
+				#pinctrl-cells = <1>;
 				ranges = <0 0x0 0x1000>;
 
 				omap2420_pmx: pinmux@30 {
@@ -46,6 +47,7 @@
 					reg = <0x30 0x0113>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					pinctrl-single,register-width = <8>;
 					pinctrl-single,function-mask = <0x3f>;
 				};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap2430.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap2430.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap2430.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap2430.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,7 @@
 				reg = <0x2000 0x1000>;
 				#address-cells = <1>;
 				#size-cells = <1>;
+				#pinctrl-cells = <1>;
 				ranges = <0 0x2000 0x1000>;
 
 				omap2430_pmx: pinmux@30 {
@@ -46,6 +47,7 @@
 					reg = <0x30 0x0154>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					pinctrl-single,register-width = <8>;
 					pinctrl-single,function-mask = <0x3f>;
 				};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap2.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap2.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap2.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 	interrupt-parent = <&intc>;
 	#address-cells = <1>;
 	#size-cells = <1>;
+	chosen { };
 
 	aliases {
 		serial0 = &uart1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap34xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap34xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap34xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap34xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,7 @@
 			reg = <0x480025d8 0x24>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#pinctrl-cells = <1>;
 			#interrupt-cells = <1>;
 			interrupt-controller;
 			pinctrl-single,register-width = <16>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap36xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap36xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap36xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap36xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -66,6 +66,7 @@
 			reg = <0x480025a0 0x5c>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#pinctrl-cells = <1>;
 			#interrupt-cells = <1>;
 			interrupt-controller;
 			pinctrl-single,register-width = <16>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap3.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap3.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap3.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap3.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 	interrupt-parent = <&intc>;
 	#address-cells = <1>;
 	#size-cells = <1>;
+	chosen { };
 
 	aliases {
 		i2c0 = &i2c1;
@@ -106,6 +107,7 @@
 					reg = <0x30 0x238>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					#interrupt-cells = <1>;
 					interrupt-controller;
 					pinctrl-single,register-width = <16>;
@@ -145,6 +147,7 @@
 					reg = <0xa00 0x5c>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					#interrupt-cells = <1>;
 					interrupt-controller;
 					pinctrl-single,register-width = <16>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap3-n900.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap3-n900.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap3-n900.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap3-n900.dts	2017-02-12 16:03:20.000000000 -0500
@@ -734,6 +734,8 @@
 	vmmc_aux-supply = <&vsim>;
 	bus-width = <8>;
 	non-removable;
+	no-sdio;
+	no-sd;
 };
 
 &mmc3 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap4-droid4-xt894.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap4-droid4-xt894.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap4-droid4-xt894.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap4-droid4-xt894.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,188 @@
+/*
+ * This program is free software; you can 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 "omap443x.dtsi"
+
+/ {
+	model = "Motorola Droid 4 XT894";
+	compatible = "motorola,droid4", "ti,omap4430", "ti,omap4";
+
+	chosen {
+		stdout-path = &uart3;
+	};
+
+	/*
+	 * We seem to have only 1021 MB accessible, 1021 - 1022 is locked,
+	 * then 1023 - 1024 seems to contain mbm. For SRAM, see the notes
+	 * below about SRAM and L3_ICLK2 being unused by default,
+	 */
+	memory {
+		device_type = "memory";
+		reg = <0x80000000 0x3fd00000>;	/* 1021 MB */
+	};
+
+	/* CPCAP really supports 1650000 to 3400000 range */
+	vmmc: regulator-mmc {
+		compatible = "regulator-fixed";
+		regulator-name = "vmmc";
+		regulator-min-microvolt = <3000000>;
+		regulator-max-microvolt = <3000000>;
+		regulator-always-on;
+	};
+
+	/* CPCAP really supports 3000000 to 3100000 range */
+	vemmc: regulator-emmc {
+		compatible = "regulator-fixed";
+		regulator-name = "vemmc";
+		regulator-min-microvolt = <3000000>;
+		regulator-max-microvolt = <3000000>;
+		regulator-always-on;
+	};
+
+	/* CPCAP really supports 1650000 to 1950000 range */
+	wl12xx_vmmc: regulator-wl12xx {
+		compatible = "regulator-fixed";
+		regulator-name = "vwl1271";
+		regulator-min-microvolt = <1650000>;
+		regulator-max-microvolt = <1650000>;
+		gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;	/* gpio94 */
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
+};
+
+/* L3_2 interconnect is unused, SRAM, GPMC and L3_ICLK2 disabled */
+&gpmc {
+	status = "disabled";
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmc>;
+	bus-width = <4>;
+	cd-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;	/* gpio106 */
+};
+
+&mmc2 {
+	vmmc-supply = <&vemmc>;
+	bus-width = <8>;
+	non-removable;
+};
+
+&mmc3 {
+	vmmc-supply = <&wl12xx_vmmc>;
+	interrupts-extended = <&wakeupgen GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH
+			       &omap4_pmx_core 0xde>;
+
+	non-removable;
+	bus-width = <4>;
+	cap-power-off-card;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1283";
+		reg = <2>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <4 IRQ_TYPE_LEVEL_HIGH>; /* gpio100 */
+		ref-clock-frequency = <26000000>;
+		tcxo-clock-frequency = <26000000>;
+	};
+};
+
+/* L3_2 interconnect is unused, SRAM, GPMC and L3_ICLK2 disabled */
+&ocmcram {
+	status = "disabled";
+};
+
+&omap4_pmx_core {
+	usb_gpio_mux_sel1: pinmux_usb_gpio_mux_sel1_pins {
+		/* gpio_60 */
+		pinctrl-single,pins = <
+		OMAP4_IOPAD(0x088, PIN_OUTPUT | MUX_MODE3)
+		>;
+	};
+
+	usb_ulpi_pins: pinmux_usb_ulpi_pins {
+		pinctrl-single,pins = <
+		OMAP4_IOPAD(0x196, MUX_MODE7)
+		OMAP4_IOPAD(0x198, MUX_MODE7)
+		OMAP4_IOPAD(0x1b2, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1b4, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1b6, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1b8, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1ba, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1bc, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1be, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1c0, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1c2, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1c4, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1c6, PIN_INPUT_PULLUP | MUX_MODE0)
+		OMAP4_IOPAD(0x1c8, PIN_INPUT_PULLUP | MUX_MODE0)
+		>;
+	};
+
+	/* usb0_otg_dp and usb0_otg_dm */
+	usb_utmi_pins: pinmux_usb_utmi_pins {
+		pinctrl-single,pins = <
+		OMAP4_IOPAD(0x196, PIN_INPUT | MUX_MODE0)
+		OMAP4_IOPAD(0x198, PIN_INPUT | MUX_MODE0)
+		OMAP4_IOPAD(0x1b2, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1b4, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1b6, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1b8, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1ba, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1bc, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1be, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c0, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c2, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c4, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c6, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c8, PIN_INPUT_PULLUP | MUX_MODE7)
+		>;
+	};
+
+	/* uart3_tx_irtx and uart3_rx_irrx */
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+		OMAP4_IOPAD(0x196, MUX_MODE7)
+		OMAP4_IOPAD(0x198, MUX_MODE7)
+		OMAP4_IOPAD(0x1b2, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1b4, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1b6, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1b8, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1ba, MUX_MODE2)
+		OMAP4_IOPAD(0x1bc, PIN_INPUT | MUX_MODE2)
+		OMAP4_IOPAD(0x1be, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c0, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c2, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c4, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c6, PIN_INPUT_PULLUP | MUX_MODE7)
+		OMAP4_IOPAD(0x1c8, PIN_INPUT_PULLUP | MUX_MODE7)
+		>;
+	};
+};
+
+&omap4_pmx_wkup {
+	usb_gpio_mux_sel2: pinmux_usb_gpio_mux_sel2_pins {
+		/* gpio_wk0 */
+		pinctrl-single,pins = <
+		OMAP4_IOPAD(0x040, PIN_OUTPUT_PULLDOWN | MUX_MODE3)
+		>;
+	};
+};
+
+&uart3 {
+	interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+			       &omap4_pmx_core 0x17c>;
+};
+
+/* Internal UTMI+ PHY used for OTG, CPCAP ULPI PHY for detection and charger */
+&usb_otg_hs {
+	interface-type = <1>;
+	mode = <3>;
+	power = <50>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap4.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 	interrupt-parent = <&wakeupgen>;
 	#address-cells = <1>;
 	#size-cells = <1>;
+	chosen { };
 
 	aliases {
 		i2c0 = &i2c1;
@@ -184,6 +185,7 @@
 					reg = <0x40 0x0196>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					#interrupt-cells = <1>;
 					interrupt-controller;
 					pinctrl-single,register-width = <16>;
@@ -256,6 +258,7 @@
 					reg = <0x1e040 0x0038>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					#interrupt-cells = <1>;
 					interrupt-controller;
 					pinctrl-single,register-width = <16>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap5.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap5.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap5.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap5.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 
 	compatible = "ti,omap5";
 	interrupt-parent = <&wakeupgen>;
+	chosen { };
 
 	aliases {
 		i2c0 = &i2c1;
@@ -171,6 +172,7 @@
 					reg = <0x40 0x01b6>;
 					#address-cells = <1>;
 					#size-cells = <0>;
+					#pinctrl-cells = <1>;
 					#interrupt-cells = <1>;
 					interrupt-controller;
 					pinctrl-single,register-width = <16>;
@@ -270,6 +272,7 @@
 				reg = <0xc840 0x003c>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				#pinctrl-cells = <1>;
 				#interrupt-cells = <1>;
 				interrupt-controller;
 				pinctrl-single,register-width = <16>;
@@ -985,6 +988,7 @@
 			phy-names = "sata-phy";
 			clocks = <&sata_ref_clk>;
 			ti,hwmods = "sata";
+			ports-implemented = <0x1>;
 		};
 
 		dss: dss@58000000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/omap5-uevm.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap5-uevm.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/omap5-uevm.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/omap5-uevm.dts	2017-02-12 16:03:20.000000000 -0500
@@ -27,12 +27,98 @@
 			default-state = "off";
 		};
 	};
+
+	evm_keys {
+		compatible = "gpio-keys";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&evm_keys_pins>;
+
+		#address-cells = <7>;
+		#size-cells = <0>;
+
+		btn1 {
+			label = "BTN1";
+			linux,code = <169>;
+			gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;	/* gpio3_83 */
+			wakeup-source;
+			autorepeat;
+			debounce_interval = <50>;
+		};
+	};
+
+	evm_leds {
+		compatible = "gpio-leds";
+
+		led1 {
+			label = "omap5:red:led";
+			gpios = <&gpio9 17 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led2 {
+			label = "omap5:green:led";
+			gpios = <&gpio9 18 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+
+		led3 {
+			label = "omap5:blue:led";
+			gpios = <&gpio9 19 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc2";
+			default-state = "off";
+		};
+
+		led4 {
+			label = "omap5:green:led1";
+			gpios = <&gpio9 2 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led5 {
+			label = "omap5:green:led2";
+			gpios = <&gpio9 3 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-on";
+			default-state = "off";
+		};
+
+		led6 {
+			label = "omap5:green:led3";
+			gpios = <&gpio9 4 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led7 {
+			label = "omap5:green:led4";
+			gpios = <&gpio9 5 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "default-on";
+			default-state = "off";
+		};
+
+		led8 {
+			label = "omap5:green:led5";
+			gpios = <&gpio9 6 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
 };
 
 &hdmi {
 	vdda-supply = <&ldo4_reg>;
 };
 
+&i2c1 {
+	eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+	};
+};
+
 &i2c5 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c5_pins>;
@@ -48,6 +134,12 @@
 };
 
 &omap5_pmx_core {
+	evm_keys_pins: pinmux_evm_keys_gpio_pins {
+		pinctrl-single,pins = <
+			OMAP5_IOPAD(0x0b6, PIN_INPUT | MUX_MODE6)	/* gpio3_83 */
+		>;
+	};
+
 	i2c5_pins: pinmux_i2c5_pins {
 		pinctrl-single,pins = <
 			OMAP5_IOPAD(0x1c6, PIN_INPUT | MUX_MODE0)		/* i2c5_scl */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/orion5x-linkstation-lschl.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/orion5x-linkstation-lschl.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/orion5x-linkstation-lschl.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/orion5x-linkstation-lschl.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,171 @@
+/*
+ * Device Tree file for Buffalo Linkstation LS-CHLv3
+ *
+ * Copyright (C) 2016 Ash Hughes <ashley.hughes@blueyonder.co.uk>
+ * Copyright (C) 2015-2017
+ * Roger Shimizu <rogershimizu@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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.
+ */
+
+/dts-v1/;
+
+#include "orion5x-linkstation.dtsi"
+#include "mvebu-linkstation-gpio-simple.dtsi"
+#include "mvebu-linkstation-fan.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "Buffalo Linkstation LiveV3 (LS-CHL)";
+	compatible = "buffalo,lschl", "marvell,orion5x-88f5182", "marvell,orion5x";
+
+	memory { /* 128 MB */
+		device_type = "memory";
+		reg = <0x00000000 0x8000000>;
+	};
+
+	gpio_keys {
+		func {
+			label = "Function Button";
+			linux,code = <KEY_OPTION>;
+			gpios = <&gpio0 15 GPIO_ACTIVE_LOW>;
+		};
+
+		power-on-switch {
+			gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
+		};
+
+		power-auto-switch {
+			gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio_leds {
+		pinctrl-0 = <&pmx_led_power &pmx_led_alarm &pmx_led_info &pmx_led_func>;
+		blue-power-led {
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+
+		red-alarm-led {
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+		};
+
+		amber-info-led {
+			gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+		};
+
+		func {
+			label = "lschl:func:blue:top";
+			gpios = <&gpio0 17 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio_fan {
+		gpios = <&gpio0 14 GPIO_ACTIVE_LOW
+			 &gpio0 16 GPIO_ACTIVE_LOW>;
+
+		alarm-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&pinctrl {
+	pmx_led_power: pmx-leds {
+		marvell,pins = "mpp0";
+		marvell,function = "gpio";
+	};
+
+	pmx_power_hdd: pmx-power-hdd {
+		marvell,pins = "mpp1";
+		marvell,function = "gpio";
+	};
+
+	pmx_led_alarm: pmx-leds {
+		marvell,pins = "mpp2";
+		marvell,function = "gpio";
+	};
+
+	pmx_led_info: pmx-leds {
+		marvell,pins = "mpp3";
+		marvell,function = "gpio";
+	};
+
+	pmx_fan_lock: pmx-fan-lock {
+		marvell,pins = "mpp6";
+		marvell,function = "gpio";
+	};
+
+	pmx_power_switch: pmx-power-switch {
+		marvell,pins = "mpp8", "mpp10", "mpp15";
+		marvell,function = "gpio";
+	};
+
+	pmx_power_usb: pmx-power-usb {
+		marvell,pins = "mpp9";
+		marvell,function = "gpio";
+	};
+
+	pmx_fan_high: pmx-fan-high {
+		marvell,pins = "mpp14";
+		marvell,function = "gpio";
+	};
+
+	pmx_fan_low: pmx-fan-low {
+		marvell,pins = "mpp16";
+		marvell,function = "gpio";
+	};
+
+	pmx_led_func: pmx-leds {
+		marvell,pins = "mpp17";
+		marvell,function = "gpio";
+	};
+
+	pmx_sw_init: pmx-sw-init {
+		marvell,pins = "mpp7";
+		marvell,function = "gpio";
+	};
+};
+
+&hdd_power {
+	gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+};
+
+&usb_power {
+	gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
+};
+
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/ox820.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/ox820.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/ox820.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/ox820.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,296 @@
+/*
+ * ox820.dtsi - Device tree file for Oxford Semiconductor OX820 SoC
+ *
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "oxsemi,ox820";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		enable-method = "oxsemi,ox820-smp";
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,arm11mpcore";
+			clocks = <&armclk>;
+			reg = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,arm11mpcore";
+			clocks = <&armclk>;
+			reg = <1>;
+		};
+	};
+
+	memory {
+		/* Max 512MB @ 0x60000000 */
+		reg = <0x60000000 0x20000000>;
+	};
+
+	clocks {
+		osc: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
+		gmacclk: gmacclk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <125000000>;
+		};
+
+		sysclk: sysclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <4>;
+			clock-mult = <1>;
+			clocks = <&osc>;
+		};
+
+		plla: plla {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <850000000>;
+		};
+
+		armclk: armclk {
+			compatible = "fixed-factor-clock";
+			#clock-cells = <0>;
+			clock-div = <2>;
+			clock-mult = <1>;
+			clocks = <&plla>;
+		};
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&gic>;
+
+		nandc: nand-controller@41000000 {
+			compatible = "oxsemi,ox820-nand";
+			reg = <0x41000000 0x100000>;
+			clocks = <&stdclk 11>;
+			resets = <&reset 15>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		etha: ethernet@40400000 {
+			compatible = "oxsemi,ox820-dwmac", "snps,dwmac";
+			reg = <0x40400000 0x2000>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq", "eth_wake_irq";
+			mac-address = [000000000000]; /* Filled in by U-Boot */
+			phy-mode = "rgmii";
+
+			clocks = <&stdclk 9>, <&gmacclk>;
+			clock-names = "gmac", "stmmaceth";
+			resets = <&reset 6>;
+
+			/* Regmap for sys registers */
+			oxsemi,sys-ctrl = <&sys>;
+
+			status = "disabled";
+		};
+
+		apb-bridge@44000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x44000000 0x1000000>;
+
+			pinctrl: pinctrl {
+				compatible = "oxsemi,ox820-pinctrl";
+
+				/* Regmap for sys registers */
+				oxsemi,sys-ctrl = <&sys>;
+
+				pinctrl_uart0: uart0 {
+					uart0 {
+						pins = "gpio30", "gpio31";
+						function = "fct5";
+					};
+				};
+
+				pinctrl_uart0_modem: uart0_modem {
+					uart0_modem_a {
+						pins = "gpio24", "gpio24", "gpio26", "gpio27";
+						function = "fct4";
+					};
+					uart0_modem_b {
+						pins = "gpio28", "gpio29";
+						function = "fct5";
+					};
+				};
+
+				pinctrl_uart1: uart1 {
+					uart1 {
+						pins = "gpio7", "gpio8";
+						function = "fct4";
+					};
+				};
+
+				pinctrl_uart1_modem: uart1_modem {
+					uart1_modem {
+						pins = "gpio5", "gpio6", "gpio40", "gpio41", "gpio42", "gpio43";
+						function = "fct4";
+					};
+				};
+
+				pinctrl_etha_mdio: etha_mdio {
+					etha_mdio {
+						pins = "gpio3", "gpio4";
+						function = "fct1";
+					};
+				};
+
+				pinctrl_nand: nand {
+					nand {
+						pins = "gpio12", "gpio13", "gpio14", "gpio15",
+						     "gpio16", "gpio17", "gpio18", "gpio19",
+						     "gpio20", "gpio21", "gpio22", "gpio23",
+						     "gpio24";
+						function = "fct1";
+					};
+				};
+			};
+
+			gpio0: gpio@000000 {
+				compatible = "oxsemi,ox820-gpio";
+				reg = <0x000000 0x100000>;
+				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				ngpios = <32>;
+				oxsemi,gpio-bank = <0>;
+				gpio-ranges = <&pinctrl 0 0 32>;
+			};
+
+			gpio1: gpio@100000 {
+				compatible = "oxsemi,ox820-gpio";
+				reg = <0x100000 0x100000>;
+				interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+				#gpio-cells = <2>;
+				gpio-controller;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				ngpios = <18>;
+				oxsemi,gpio-bank = <1>;
+				gpio-ranges = <&pinctrl 0 32 18>;
+			};
+
+			uart0: serial@200000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       clocks = <&sysclk>;
+			       resets = <&reset 17>;
+			};
+
+			uart1: serial@300000 {
+			       compatible = "ns16550a";
+			       reg = <0x200000 0x100000>;
+			       interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+			       reg-shift = <0>;
+			       fifo-size = <16>;
+			       reg-io-width = <1>;
+			       current-speed = <115200>;
+			       no-loopback-test;
+			       status = "disabled";
+			       clocks = <&sysclk>;
+			       resets = <&reset 18>;
+			};
+
+			rps@400000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "simple-bus";
+				ranges = <0 0x400000 0x100000>;
+
+				intc: interrupt-controller@0 {
+					compatible = "oxsemi,ox820-rps-irq", "oxsemi,ox810se-rps-irq";
+					interrupt-controller;
+					reg = <0 0x200>;
+					interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+					#interrupt-cells = <1>;
+					valid-mask = <0xFFFFFFFF>;
+					clear-mask = <0>;
+				};
+
+				timer0: timer@200 {
+					compatible = "oxsemi,ox820-rps-timer";
+					reg = <0x200 0x40>;
+					clocks = <&sysclk>;
+					interrupt-parent = <&intc>;
+					interrupts = <4>;
+				};
+			};
+
+			sys: sys-ctrl@e00000 {
+				compatible = "oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd";
+				reg = <0xe00000 0x200000>;
+
+				reset: reset-controller {
+					compatible = "oxsemi,ox820-reset", "oxsemi,ox810se-reset";
+					#reset-cells = <1>;
+				};
+
+				stdclk: stdclk {
+					compatible = "oxsemi,ox820-stdclk", "oxsemi,ox810se-stdclk";
+					#clock-cells = <1>;
+				};
+			};
+		};
+
+		apb-bridge@47000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			ranges = <0 0x47000000 0x1000000>;
+
+			scu: scu@0 {
+				compatible = "arm,arm11mp-scu";
+				reg = <0x0 0x100>;
+			};
+
+			local-timer@600 {
+				compatible = "arm,arm11mp-twd-timer";
+				reg = <0x600 0x20>;
+				interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(3)|IRQ_TYPE_LEVEL_HIGH)>;
+				clocks = <&armclk>;
+			};
+
+			gic: gic@1000 {
+				compatible = "arm,arm11mp-gic";
+				interrupt-controller;
+				#interrupt-cells = <3>;
+				reg = <0x1000 0x1000>,
+				      <0x100 0x500>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/pxa25x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa25x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/pxa25x.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa25x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 Robert Jarzmik <robert.jarzmik@free.fr>
+ *
+ * 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 "pxa2xx.dtsi"
+#include "dt-bindings/clock/pxa-clock.h"
+
+/ {
+	model = "Marvell PXA25x family SoC";
+	compatible = "marvell,pxa250";
+
+	clocks {
+	       /*
+		* The muxing of external clocks/internal dividers for osc* clock
+		* sources has been hidden under the carpet by now.
+		*/
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		clks: pxa2xx_clks@41300004 {
+			compatible = "marvell,pxa250-core-clocks";
+			#clock-cells = <1>;
+			status = "okay";
+		};
+
+		/* timer oscillator */
+		clktimer: oscillator {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency  = <3686400>;
+			clock-output-names = "ostimer";
+		};
+	};
+
+	pxabus {
+		pdma: dma-controller@40000000 {
+			compatible = "marvell,pdma-1.0";
+			reg = <0x40000000 0x10000>;
+			interrupts = <25>;
+			#dma-channels = <16>;
+			#dma-cells = <2>;
+			#dma-requests = <40>;
+			status = "okay";
+		};
+
+		pxairq: interrupt-controller@40d00000 {
+			marvell,intc-priority;
+			marvell,intc-nr-irqs = <32>;
+		};
+
+		pinctrl: pinctrl@40e00000 {
+			reg = <0x40e00054 0x20 0x40e0000c 0xc 0x40e0010c 4
+			       0x40f00020 0x10>;
+			compatible = "marvell,pxa25x-pinctrl";
+		};
+
+		gpio: gpio@40e00000 {
+			compatible = "intel,pxa25x-gpio";
+			gpio-ranges = <&pinctrl 0 0 84>;
+			clocks = <&clks CLK_NONE>;
+		};
+
+		pwm0: pwm@40b00000 {
+			compatible = "marvell,pxa250-pwm";
+			reg = <0x40b00000 0x10>;
+			#pwm-cells = <1>;
+			clocks = <&clks CLK_PWM0>;
+		};
+
+		pwm1: pwm@40b00010 {
+			compatible = "marvell,pxa250-pwm";
+			reg = <0x40b00010 0x10>;
+			#pwm-cells = <1>;
+			clocks = <&clks CLK_PWM1>;
+		};
+	};
+
+	timer@40a00000 {
+		compatible = "marvell,pxa-timer";
+		reg = <0x40a00000 0x20>;
+		interrupts = <26>;
+		clocks = <&clktimer>;
+		status = "okay";
+	};
+
+	pxa250_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+
+		opp@99532800 {
+			opp-hz = /bits/ 64 <99532800>;
+			opp-microvolt = <1000000 950000 1650000>;
+			clock-latency-ns = <20>;
+		};
+		opp@199065600 {
+			opp-hz = /bits/ 64 <199065600>;
+			opp-microvolt = <1000000 950000 1650000>;
+			clock-latency-ns = <20>;
+		};
+		opp@298598400 {
+			opp-hz = /bits/ 64 <298598400>;
+			opp-microvolt = <1100000 1045000 1650000>;
+			clock-latency-ns = <20>;
+		};
+		opp@398131200 {
+			opp-hz = /bits/ 64 <398131200>;
+			opp-microvolt = <1300000 1235000 1650000>;
+			clock-latency-ns = <20>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/pxa27x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa27x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/pxa27x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa27x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -137,4 +137,44 @@
 		clocks = <&clks CLK_OSTIMER>;
 		status = "okay";
 	};
+
+	pxa270_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+
+		opp@104000000 {
+			opp-hz = /bits/ 64 <104000000>;
+			opp-microvolt = <900000 900000 1705000>;
+			clock-latency-ns = <20>;
+		};
+		opp@156000000 {
+			opp-hz = /bits/ 64 <156000000>;
+			opp-microvolt = <1000000 1000000 1705000>;
+			clock-latency-ns = <20>;
+		};
+		opp@208000000 {
+			opp-hz = /bits/ 64 <208000000>;
+			opp-microvolt = <1180000 1180000 1705000>;
+			clock-latency-ns = <20>;
+		};
+		opp@312000000 {
+			opp-hz = /bits/ 64 <312000000>;
+			opp-microvolt = <1250000 1250000 1705000>;
+			clock-latency-ns = <20>;
+		};
+		opp@416000000 {
+			opp-hz = /bits/ 64 <416000000>;
+			opp-microvolt = <1350000 1350000 1705000>;
+			clock-latency-ns = <20>;
+		};
+		opp@520000000 {
+			opp-hz = /bits/ 64 <520000000>;
+			opp-microvolt = <1450000 1450000 1705000>;
+			clock-latency-ns = <20>;
+		};
+		opp@624000000 {
+			opp-hz = /bits/ 64 <624000000>;
+			opp-microvolt = <1550000 1550000 1705000>;
+			clock-latency-ns = <20>;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/pxa2xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa2xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/pxa2xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa2xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -54,8 +54,8 @@
 			reg = <0x40e00000 0x10000>;
 			gpio-controller;
 			#gpio-cells = <0x2>;
-			interrupts = <10>;
-			interrupt-names = "gpio_mux";
+			interrupts = <8>, <9>, <10>;
+			interrupt-names = "gpio0", "gpio1", "gpio_mux";
 			interrupt-controller;
 			#interrupt-cells = <0x2>;
 			ranges;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/pxa3xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa3xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/pxa3xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/pxa3xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -138,6 +138,7 @@
 			reg = <0x40e10000 0xffff>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#pinctrl-cells = <1>;
 			pinctrl-single,register-width = <32>;
 			pinctrl-single,function-mask = <0x7>;
 		};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts	2017-02-12 16:03:20.000000000 -0500
@@ -51,6 +51,29 @@
 			regulator-boot-on;
 		};
 
+		/* GPIO controlled ethernet power regulator */
+		dragon_veth: xc622a331mrg {
+			compatible = "regulator-fixed";
+			regulator-name = "XC6222A331MR-G";
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			vin-supply = <&vph>;
+			gpio = <&pm8058_gpio 40 GPIO_ACTIVE_HIGH>;
+			enable-active-high;
+			pinctrl-names = "default";
+			pinctrl-0 = <&dragon_veth_gpios>;
+			regulator-always-on;
+		};
+
+		/* VDDvario fixed regulator */
+		dragon_vario: nds332p {
+			compatible = "regulator-fixed";
+			regulator-name = "NDS332P";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			vin-supply = <&pm8058_s3>;
+		};
+
 		/* This is a levelshifter for SDCC5 */
 		dragon_vio_txb: txb0104rgyr {
 			compatible = "regulator-fixed";
@@ -167,6 +190,36 @@
 					bias-pull-up;
 				};
 			};
+
+			dragon_ebi2_pins: ebi2 {
+				/*
+				 * Pins used by EBI2 on the Dragonboard, actually only
+				 * CS2 is used by a real peripheral. CS0 is just
+				 * routed to a test point.
+				 */
+				mux0 {
+					pins =
+					    /* "gpio39", CS1A_N this is not good to mux */
+					    "gpio40", /* CS2A_N */
+					    "gpio134"; /* CS0_N testpoint TP29 */
+					function = "ebi2cs";
+				};
+				mux1 {
+					pins =
+					    /* EBI2_ADDR_7 downto EBI2_ADDR_0 address bus */
+					    "gpio123", "gpio124", "gpio125", "gpio126",
+					    "gpio127", "gpio128", "gpio129", "gpio130",
+					    /* EBI2_DATA_15 downto EBI2_DATA_0 data bus */
+					    "gpio135", "gpio136", "gpio137", "gpio138",
+					    "gpio139", "gpio140", "gpio141", "gpio142",
+					    "gpio143", "gpio144", "gpio145", "gpio146",
+					    "gpio147", "gpio148", "gpio149", "gpio150",
+					    "gpio151", /* EBI2_OE_N */
+					    "gpio153", /* EBI2_ADV */
+					    "gpio157"; /* EBI2_WE_N */
+					function = "ebi2";
+				};
+			};
 		};
 
 		qcom,ssbi@500000 {
@@ -201,6 +254,15 @@
 				};
 
 				gpio@150 {
+					dragon_ethernet_gpios: ethernet-gpios {
+						pinconf {
+							pins = "gpio7";
+							function = "normal";
+							input-enable;
+							bias-disable;
+							power-source = <PM8058_GPIO_S3>;
+						};
+					};
 					dragon_bmp085_gpios: bmp085-gpios {
 						pinconf {
 							pins = "gpio16";
@@ -238,6 +300,14 @@
 							power-source = <PM8058_GPIO_S3>;
 						};
 					};
+					dragon_veth_gpios: veth-gpios {
+						pinconf {
+							pins = "gpio40";
+							function = "normal";
+							bias-disable;
+							drive-push-pull;
+						};
+					};
 				};
 
 				led@48 {
@@ -322,6 +392,55 @@
 			};
 		};
 
+		external-bus@1a100000 {
+			/* The EBI2 will instantiate first, then populate its children */
+			status = "ok";
+			pinctrl-names = "default";
+			pinctrl-0 = <&dragon_ebi2_pins>;
+
+			/*
+			 * An on-board SMSC LAN9221 chip for "debug ethernet",
+			 * which is actually just an ordinary ethernet on the
+			 * EBI2. This has a 25MHz chrystal next to it, so no
+			 * clocking is needed.
+			 */
+			ethernet-ebi2@2,0 {
+				compatible = "smsc,lan9221", "smsc,lan9115";
+				reg = <2 0x0 0x100>;
+				/*
+				 * GPIO7 has interrupt 198 on the PM8058
+				 * The second interrupt is the PME interrupt
+				 * for network wakeup, connected to the TLMM.
+				 */
+				interrupts-extended = <&pmicintc 198 IRQ_TYPE_EDGE_FALLING>,
+						    <&tlmm 29 IRQ_TYPE_EDGE_RISING>;
+				reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>;
+				vdd33a-supply = <&dragon_veth>;
+				vddvario-supply = <&dragon_vario>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&dragon_ethernet_gpios>;
+				phy-mode = "mii";
+				reg-io-width = <2>;
+				smsc,force-external-phy;
+				/* IRQ on edge falling = active low */
+				smsc,irq-active-low;
+				smsc,irq-push-pull;
+
+				/*
+				 * SLOW chipselect config
+				 * Delay 9 cycles (140ns@64MHz) between SMSC
+				 * LAN9221 Ethernet controller reads and writes
+				 * on CS2.
+				 */
+				qcom,xmem-recovery-cycles = <0>;
+				qcom,xmem-write-hold-cycles = <3>;
+				qcom,xmem-write-delta-cycles = <31>;
+				qcom,xmem-read-delta-cycles = <28>;
+				qcom,xmem-write-wait-cycles = <9>;
+				qcom,xmem-read-wait-cycles = <9>;
+			};
+		};
+
 		rpm@104000 {
 			/*
 			 * Set up of the PMIC RPM regulators for this board
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,20 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		ramoops@88d00000{
+			compatible = "ramoops";
+			reg = <0x88d00000 0x100000>;
+			record-size     = <0x00020000>;
+			console-size    = <0x00020000>;
+			ftrace-size     = <0x00020000>;
+		};
+	};
+
 	ext_3p3v: regulator-fixed@1 {
 		compatible = "regulator-fixed";
 		regulator-min-microvolt = <3300000>;
@@ -99,6 +113,7 @@
 				l2 {
 					regulator-min-microvolt = <1200000>;
 					regulator-max-microvolt = <1200000>;
+					regulator-always-on;
 				};
 
 				/* msm_otg-HSUSB_3p3 */
@@ -133,13 +148,14 @@
 					regulator-min-microvolt = <3000000>;
 					regulator-max-microvolt = <3000000>;
 					bias-pull-down;
+					regulator-always-on;
 				};
 
 				/* pwm_power for backlight */
 				l17 {
 					regulator-min-microvolt = <3000000>;
-					regulator-max-microvolt = <3600000>;
-					bias-pull-down;
+					regulator-max-microvolt = <3000000>;
+					regulator-always-on;
 				};
 
 				/* camera, qdsp6 */
@@ -184,6 +200,63 @@
 			};
 		};
 
+		mdp@5100000 {
+			status = "okay";
+			ports {
+				port@1 {
+					mdp_dsi1_out: endpoint {
+						remote-endpoint = <&dsi0_in>;
+					};
+				};
+			};
+		};
+
+		dsi0: mdss_dsi@4700000 {
+			status = "okay";
+			vdda-supply = <&pm8921_l2>;/*VDD_MIPI1 to 4*/
+			vdd-supply = <&pm8921_l8>;
+			vddio-supply = <&pm8921_lvs7>;
+			avdd-supply = <&pm8921_l11>;
+			vcss-supply = <&ext_3p3v>;
+
+			panel@0 {
+				reg = <0>;
+				compatible = "jdi,lt070me05000";
+
+				vddp-supply = <&pm8921_l17>;
+				iovcc-supply = <&pm8921_lvs7>;
+
+				enable-gpios = <&pm8921_gpio 36 GPIO_ACTIVE_HIGH>;
+				reset-gpios = <&tlmm_pinmux 54 GPIO_ACTIVE_LOW>;
+				dcdc-en-gpios = <&pm8921_gpio 23 GPIO_ACTIVE_HIGH>;
+
+				port {
+					panel_in: endpoint {
+						remote-endpoint = <&dsi0_out>;
+					};
+				};
+			};
+			ports {
+				port@0 {
+					dsi0_in: endpoint {
+						remote-endpoint = <&mdp_dsi1_out>;
+					};
+				};
+
+				port@1 {
+					dsi0_out: endpoint {
+						remote-endpoint = <&panel_in>;
+						data-lanes = <0 1 2 3>;
+					};
+				};
+			};
+		};
+
+		dsi-phy@4700200 {
+			status = "okay";
+			vddio-supply = <&pm8921_lvs7>;/*VDD_PLL2_1 to 7*/
+		};
+
 		gsbi@16200000 {
 			status = "okay";
 			qcom,mode = <GSBI_PROT_I2C>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8064.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -4,6 +4,7 @@
 #include <dt-bindings/clock/qcom,gcc-msm8960.h>
 #include <dt-bindings/reset/qcom,gcc-msm8960.h>
 #include <dt-bindings/clock/qcom,mmcc-msm8960.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
 #include <dt-bindings/soc/qcom,gsbi.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -303,6 +304,9 @@
 	firmware {
 		scm {
 			compatible = "qcom,scm-apq8064";
+
+			clocks = <&rpmcc RPM_DAYTONA_FABRIC_CLK>;
+			clock-names = "core";
 		};
 	};
 
@@ -1060,6 +1064,231 @@
 			reg = <0x1a400000 0x100>;
 		};
 
+		gpu: adreno-3xx@4300000 {
+			compatible = "qcom,adreno-3xx";
+			reg = <0x04300000 0x20000>;
+			reg-names = "kgsl_3d0_reg_memory";
+			interrupts = <GIC_SPI 80 0>;
+			interrupt-names = "kgsl_3d0_irq";
+			clock-names =
+			    "core_clk",
+			    "iface_clk",
+			    "mem_clk",
+			    "mem_iface_clk";
+			clocks =
+			    <&mmcc GFX3D_CLK>,
+			    <&mmcc GFX3D_AHB_CLK>,
+			    <&mmcc GFX3D_AXI_CLK>,
+			    <&mmcc MMSS_IMEM_AHB_CLK>;
+			qcom,chipid = <0x03020002>;
+
+			iommus = <&gfx3d 0
+				  &gfx3d 1
+				  &gfx3d 2
+				  &gfx3d 3
+				  &gfx3d 4
+				  &gfx3d 5
+				  &gfx3d 6
+				  &gfx3d 7
+				  &gfx3d 8
+				  &gfx3d 9
+				  &gfx3d 10
+				  &gfx3d 11
+				  &gfx3d 12
+				  &gfx3d 13
+				  &gfx3d 14
+				  &gfx3d 15
+				  &gfx3d 16
+				  &gfx3d 17
+				  &gfx3d 18
+				  &gfx3d 19
+				  &gfx3d 20
+				  &gfx3d 21
+				  &gfx3d 22
+				  &gfx3d 23
+				  &gfx3d 24
+				  &gfx3d 25
+				  &gfx3d 26
+				  &gfx3d 27
+				  &gfx3d 28
+				  &gfx3d 29
+				  &gfx3d 30
+				  &gfx3d 31
+				  &gfx3d1 0
+				  &gfx3d1 1
+				  &gfx3d1 2
+				  &gfx3d1 3
+				  &gfx3d1 4
+				  &gfx3d1 5
+				  &gfx3d1 6
+				  &gfx3d1 7
+				  &gfx3d1 8
+				  &gfx3d1 9
+				  &gfx3d1 10
+				  &gfx3d1 11
+				  &gfx3d1 12
+				  &gfx3d1 13
+				  &gfx3d1 14
+				  &gfx3d1 15
+				  &gfx3d1 16
+				  &gfx3d1 17
+				  &gfx3d1 18
+				  &gfx3d1 19
+				  &gfx3d1 20
+				  &gfx3d1 21
+				  &gfx3d1 22
+				  &gfx3d1 23
+				  &gfx3d1 24
+				  &gfx3d1 25
+				  &gfx3d1 26
+				  &gfx3d1 27
+				  &gfx3d1 28
+				  &gfx3d1 29
+				  &gfx3d1 30
+				  &gfx3d1 31>;
+
+			qcom,gpu-pwrlevels {
+				compatible = "qcom,gpu-pwrlevels";
+				qcom,gpu-pwrlevel@0 {
+					qcom,gpu-freq = <450000000>;
+				};
+				qcom,gpu-pwrlevel@1 {
+					qcom,gpu-freq = <27000000>;
+				};
+			};
+		};
+
+		mmss_sfpb: syscon@5700000 {
+			compatible = "syscon";
+			reg = <0x5700000 0x70>;
+		};
+
+		dsi0: mdss_dsi@4700000 {
+			compatible = "qcom,mdss-dsi-ctrl";
+			label = "MDSS DSI CTRL->0";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <GIC_SPI 82 0>;
+			reg = <0x04700000 0x200>;
+			reg-names = "dsi_ctrl";
+
+			clocks = <&mmcc DSI_M_AHB_CLK>,
+				<&mmcc DSI_S_AHB_CLK>,
+				<&mmcc AMP_AHB_CLK>,
+				<&mmcc DSI_CLK>,
+				<&mmcc DSI1_BYTE_CLK>,
+				<&mmcc DSI_PIXEL_CLK>,
+				<&mmcc DSI1_ESC_CLK>;
+			clock-names = "iface_clk", "bus_clk", "core_mmss_clk",
+					"src_clk", "byte_clk", "pixel_clk",
+					"core_clk";
+
+			assigned-clocks = <&mmcc DSI1_BYTE_SRC>,
+					<&mmcc DSI1_ESC_SRC>,
+					<&mmcc DSI_SRC>,
+					<&mmcc DSI_PIXEL_SRC>;
+			assigned-clock-parents = <&dsi0_phy 0>,
+						<&dsi0_phy 0>,
+						<&dsi0_phy 1>,
+						<&dsi0_phy 1>;
+			syscon-sfpb = <&mmss_sfpb>;
+			phys = <&dsi0_phy>;
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					dsi0_in: endpoint {
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					dsi0_out: endpoint {
+					};
+				};
+			};
+		};
+
+
+		dsi0_phy: dsi-phy@4700200 {
+			compatible = "qcom,dsi-phy-28nm-8960";
+			#clock-cells = <1>;
+
+			reg = <0x04700200 0x100>,
+				<0x04700300 0x200>,
+				<0x04700500 0x5c>;
+			reg-names = "dsi_pll", "dsi_phy", "dsi_phy_regulator";
+			clock-names = "iface_clk";
+			clocks = <&mmcc DSI_M_AHB_CLK>;
+		};
+
+
+		mdp_port0: iommu@7500000 {
+			compatible = "qcom,apq8064-iommu";
+			#iommu-cells = <1>;
+			clock-names =
+			    "smmu_pclk",
+			    "iommu_clk";
+			clocks =
+			    <&mmcc SMMU_AHB_CLK>,
+			    <&mmcc MDP_AXI_CLK>;
+			reg = <0x07500000 0x100000>;
+			interrupts =
+			    <GIC_SPI 63 0>,
+			    <GIC_SPI 64 0>;
+			qcom,ncb = <2>;
+		};
+
+		mdp_port1: iommu@7600000 {
+			compatible = "qcom,apq8064-iommu";
+			#iommu-cells = <1>;
+			clock-names =
+			    "smmu_pclk",
+			    "iommu_clk";
+			clocks =
+			    <&mmcc SMMU_AHB_CLK>,
+			    <&mmcc MDP_AXI_CLK>;
+			reg = <0x07600000 0x100000>;
+			interrupts =
+			    <GIC_SPI 61 0>,
+			    <GIC_SPI 62 0>;
+			qcom,ncb = <2>;
+		};
+
+		gfx3d: iommu@7c00000 {
+			compatible = "qcom,apq8064-iommu";
+			#iommu-cells = <1>;
+			clock-names =
+			    "smmu_pclk",
+			    "iommu_clk";
+			clocks =
+			    <&mmcc SMMU_AHB_CLK>,
+			    <&mmcc GFX3D_AXI_CLK>;
+			reg = <0x07c00000 0x100000>;
+			interrupts =
+			    <GIC_SPI 69 0>,
+			    <GIC_SPI 70 0>;
+			qcom,ncb = <3>;
+		};
+
+		gfx3d1: iommu@7d00000 {
+			compatible = "qcom,apq8064-iommu";
+			#iommu-cells = <1>;
+			clock-names =
+			    "smmu_pclk",
+			    "iommu_clk";
+			clocks =
+			    <&mmcc SMMU_AHB_CLK>,
+			    <&mmcc GFX3D_AXI_CLK>;
+			reg = <0x07d00000 0x100000>;
+			interrupts =
+			    <GIC_SPI 210 0>,
+			    <GIC_SPI 211 0>;
+			qcom,ncb = <3>;
+		};
+
 		pcie: pci@1b500000 {
 			compatible = "qcom,pcie-apq8064", "snps,dw-pcie";
 			reg = <0x1b500000 0x1000
@@ -1095,6 +1324,102 @@
 			reset-names = "axi", "ahb", "por", "pci", "phy";
 			status = "disabled";
 		};
+
+		hdmi: hdmi-tx@4a00000 {
+			compatible = "qcom,hdmi-tx-8960";
+			reg = <0x04a00000 0x2f0>;
+			reg-names = "core_physical";
+			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&mmcc HDMI_APP_CLK>,
+				 <&mmcc HDMI_M_AHB_CLK>,
+				 <&mmcc HDMI_S_AHB_CLK>;
+			clock-names = "core_clk",
+				      "master_iface_clk",
+				      "slave_iface_clk";
+
+			phys = <&hdmi_phy>;
+			phy-names = "hdmi-phy";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					hdmi_in: endpoint {
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					hdmi_out: endpoint {
+					};
+				};
+			};
+		};
+
+		hdmi_phy: hdmi-phy@4a00400 {
+			compatible = "qcom,hdmi-phy-8960";
+			reg = <0x4a00400 0x60>,
+			      <0x4a00500 0x100>;
+			reg-names = "hdmi_phy",
+				    "hdmi_pll";
+
+			clocks = <&mmcc HDMI_S_AHB_CLK>;
+			clock-names = "slave_iface_clk";
+		};
+
+		mdp: mdp@5100000 {
+			compatible = "qcom,mdp4";
+			reg = <0x05100000 0xf0000>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&mmcc MDP_CLK>,
+				 <&mmcc MDP_AHB_CLK>,
+				 <&mmcc MDP_AXI_CLK>,
+				 <&mmcc MDP_LUT_CLK>,
+				 <&mmcc HDMI_TV_CLK>,
+				 <&mmcc MDP_TV_CLK>;
+			clock-names = "core_clk",
+				      "iface_clk",
+				      "bus_clk",
+				      "lut_clk",
+				      "hdmi_clk",
+				      "tv_clk";
+
+			iommus = <&mdp_port0 0
+				  &mdp_port0 2
+				  &mdp_port1 0
+				  &mdp_port1 2>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					mdp_lvds_out: endpoint {
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					mdp_dsi1_out: endpoint {
+					};
+				};
+
+				port@2 {
+					reg = <2>;
+					mdp_dsi2_out: endpoint {
+					};
+				};
+
+				port@3 {
+					reg = <3>;
+					mdp_dtv_out: endpoint {
+					};
+				};
+			};
+		};
 	};
 };
 #include "qcom-apq8064-pins.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,17 @@
 		};
 	};
 
+	hdmi-out {
+		compatible = "hdmi-connector";
+		type = "d";
+
+		port {
+			hdmi_con: endpoint {
+				remote-endpoint = <&hdmi_out>;
+			};
+		};
+	};
+
 	soc {
 		pinctrl@800000 {
 			card_detect: card_detect {
@@ -64,6 +75,25 @@
 					bias-disable;
 				};
 			};
+
+			hdmi_pinctrl: hdmi-pinctrl {
+				mux {
+					pins = "gpio70", "gpio71", "gpio72";
+					function = "hdmi";
+				};
+
+				pinconf_ddc {
+					pins = "gpio70", "gpio71";
+					bias-pull-up;
+					drive-strength = <2>;
+				};
+
+				pinconf_hpd {
+					pins = "gpio72";
+					bias-pull-down;
+					drive-strength = <16>;
+				};
+			};
 		};
 
 		rpm@108000 {
@@ -329,5 +359,49 @@
 				mmc-pwrseq = <&sdcc4_pwrseq>;
 			};
 		};
+
+		hdmi-tx@4a00000 {
+			status = "okay";
+
+			core-vdda-supply = <&pm8921_hdmi_switch>;
+			hdmi-mux-supply = <&ext_3p3v>;
+
+			hpd-gpios = <&tlmm_pinmux 72 GPIO_ACTIVE_HIGH>;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&hdmi_pinctrl>;
+
+			ports {
+				port@0 {
+					endpoint {
+						remote-endpoint = <&mdp_dtv_out>;
+					};
+				};
+
+				port@1 {
+					endpoint {
+						remote-endpoint = <&hdmi_con>;
+					};
+				};
+			};
+		};
+
+		hdmi-phy@4a00400 {
+			status = "okay";
+
+			core-vdda-supply = <&pm8921_hdmi_switch>;
+		};
+
+		mdp@5100000 {
+			status = "okay";
+
+			ports {
+				port@3 {
+					endpoint {
+						remote-endpoint = <&hdmi_in>;
+					};
+				};
+			};
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8084.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8084.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-apq8084.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-apq8084.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -182,13 +182,13 @@
 	};
 
 	clocks {
-		xo_board {
+		xo_board: xo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <19200000>;
 		};
 
-		sleep_clk {
+		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
@@ -416,8 +416,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 123 0>, <0 138 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC1_APPS_CLK>,
+				 <&gcc GCC_SDCC1_AHB_CLK>,
+				 <&xo_board>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
@@ -427,8 +429,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 125 0>, <0 221 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC2_APPS_CLK>,
+				 <&gcc GCC_SDCC2_AHB_CLK>,
+				 <&xo_board>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-mdm9615.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-mdm9615.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-mdm9615.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-mdm9615.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,557 @@
+/*
+ * Device Tree Source for Qualcomm MDM9615 SoC
+ *
+ * Copyright (C) 2016 BayLibre, SAS.
+ * Author : Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/qcom,gcc-mdm9615.h>
+#include <dt-bindings/reset/qcom,gcc-mdm9615.h>
+#include <dt-bindings/mfd/qcom-rpm.h>
+#include <dt-bindings/soc/qcom,gsbi.h>
+
+/ {
+	model = "Qualcomm MDM9615";
+	compatible = "qcom,mdm9615";
+	interrupt-parent = <&intc>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a5";
+			device_type = "cpu";
+			next-level-cache = <&L2>;
+		};
+	};
+
+	cpu-pmu {
+		compatible = "arm,cortex-a5-pmu";
+		interrupts = <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	clocks {
+		cxo_board {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <19200000>;
+		};
+	};
+
+	regulators {
+		vsdcc_fixed: vsdcc-regulator {
+			compatible = "regulator-fixed";
+			regulator-name = "SDCC Power";
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			regulator-always-on;
+		};
+	};
+
+	soc: soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "simple-bus";
+
+		L2: l2-cache@2040000 {
+			compatible = "arm,pl310-cache";
+			reg = <0x02040000 0x1000>;
+			arm,data-latency = <2 2 0>;
+			cache-unified;
+			cache-level = <2>;
+		};
+
+		intc: interrupt-controller@2000000 {
+			compatible = "qcom,msm-qgic2";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			reg = <0x02000000 0x1000>,
+			      <0x02002000 0x1000>;
+		};
+
+		timer@200a000 {
+			compatible = "qcom,kpss-timer", "qcom,msm-timer";
+			interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_EDGE_RISING)>,
+				     <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_EDGE_RISING)>,
+				     <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_EDGE_RISING)>;
+			reg = <0x0200a000 0x100>;
+			clock-frequency = <27000000>,
+					  <32768>;
+			cpu-offset = <0x80000>;
+		};
+
+		msmgpio: pinctrl@800000 {
+			compatible = "qcom,mdm9615-pinctrl";
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x800000 0x4000>;
+		};
+
+		gcc: clock-controller@900000 {
+			compatible = "qcom,gcc-mdm9615";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			reg = <0x900000 0x4000>;
+		};
+
+		lcc: clock-controller@28000000 {
+			compatible = "qcom,lcc-mdm9615";
+			reg = <0x28000000 0x1000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		l2cc: clock-controller@2011000 {
+			compatible = "syscon";
+			reg = <0x02011000 0x1000>;
+		};
+
+		rng@1a500000 {
+			compatible = "qcom,prng";
+			reg = <0x1a500000 0x200>;
+			clocks = <&gcc PRNG_CLK>;
+			clock-names = "core";
+			assigned-clocks = <&gcc PRNG_CLK>;
+			assigned-clock-rates = <32000000>;
+		};
+
+		gsbi2: gsbi@16100000 {
+			compatible = "qcom,gsbi-v1.0.0";
+			cell-index = <2>;
+			reg = <0x16100000 0x100>;
+			clocks = <&gcc GSBI2_H_CLK>;
+			clock-names = "iface";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			gsbi2_i2c: i2c@16180000 {
+				compatible = "qcom,i2c-qup-v1.1.1";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x16180000 0x1000>;
+				interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+
+				clocks = <&gcc GSBI2_QUP_CLK>, <&gcc GSBI2_H_CLK>;
+				clock-names = "core", "iface";
+				status = "disabled";
+			};
+		};
+
+		gsbi3: gsbi@16200000 {
+			compatible = "qcom,gsbi-v1.0.0";
+			cell-index = <3>;
+			reg = <0x16200000 0x100>;
+			clocks = <&gcc GSBI3_H_CLK>;
+			clock-names = "iface";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			gsbi3_spi: spi@16280000 {
+				compatible = "qcom,spi-qup-v1.1.1";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x16280000 0x1000>;
+				interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+				spi-max-frequency = <24000000>;
+
+				clocks = <&gcc GSBI3_QUP_CLK>, <&gcc GSBI3_H_CLK>;
+				clock-names = "core", "iface";
+				status = "disabled";
+			};
+		};
+
+		gsbi4: gsbi@16300000 {
+			compatible = "qcom,gsbi-v1.0.0";
+			cell-index = <4>;
+			reg = <0x16300000 0x100>;
+			clocks = <&gcc GSBI4_H_CLK>;
+			clock-names = "iface";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			syscon-tcsr = <&tcsr>;
+
+			gsbi4_serial: serial@16340000 {
+				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+				reg = <0x16340000 0x1000>,
+				      <0x16300000 0x1000>;
+				interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gcc GSBI4_UART_CLK>, <&gcc GSBI4_H_CLK>;
+				clock-names = "core", "iface";
+				status = "disabled";
+			};
+		};
+
+		gsbi5: gsbi@16400000 {
+			compatible = "qcom,gsbi-v1.0.0";
+			cell-index = <5>;
+			reg = <0x16400000 0x100>;
+			clocks = <&gcc GSBI5_H_CLK>;
+			clock-names = "iface";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			syscon-tcsr = <&tcsr>;
+
+			gsbi5_i2c: i2c@16480000 {
+				compatible = "qcom,i2c-qup-v1.1.1";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x16480000 0x1000>;
+				interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+
+				/* QUP clock is not initialized, set rate */
+				assigned-clocks = <&gcc GSBI5_QUP_CLK>;
+				assigned-clock-rates = <24000000>;
+
+				clocks = <&gcc GSBI5_QUP_CLK>, <&gcc GSBI5_H_CLK>;
+				clock-names = "core", "iface";
+				status = "disabled";
+			};
+
+			gsbi5_serial: serial@16440000 {
+				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
+				reg = <0x16440000 0x1000>,
+				      <0x16400000 0x1000>;
+				interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
+				clock-names = "core", "iface";
+				status = "disabled";
+			};
+		};
+
+		qcom,ssbi@500000 {
+			compatible = "qcom,ssbi";
+			reg = <0x500000 0x1000>;
+			qcom,controller-type = "pmic-arbiter";
+
+			pmicintc: pmic@0 {
+				compatible = "qcom,pm8018", "qcom,pm8921";
+				interrupts = <GIC_PPI 226 IRQ_TYPE_LEVEL_HIGH>;
+				#interrupt-cells = <2>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pwrkey@1c {
+					compatible = "qcom,pm8018-pwrkey", "qcom,pm8921-pwrkey";
+					reg = <0x1c>;
+					interrupt-parent = <&pmicintc>;
+					interrupts = <50 IRQ_TYPE_EDGE_RISING>,
+						     <51 IRQ_TYPE_EDGE_RISING>;
+					debounce = <15625>;
+					pull-up;
+				};
+
+				pmicmpp: mpp@50 {
+					compatible = "qcom,pm8018-mpp", "qcom,ssbi-mpp";
+					interrupt-parent = <&pmicintc>;
+					interrupts = <24 IRQ_TYPE_NONE>,
+						     <25 IRQ_TYPE_NONE>,
+						     <26 IRQ_TYPE_NONE>,
+						     <27 IRQ_TYPE_NONE>,
+						     <28 IRQ_TYPE_NONE>,
+						     <29 IRQ_TYPE_NONE>;
+					reg = <0x50>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+
+				rtc@11d {
+					compatible = "qcom,pm8018-rtc", "qcom,pm8921-rtc";
+					interrupt-parent = <&pmicintc>;
+					interrupts = <39 IRQ_TYPE_EDGE_RISING>;
+					reg = <0x11d>;
+					allow-set-time;
+				};
+
+				pmicgpio: gpio@150 {
+					compatible = "qcom,pm8018-gpio", "qcom,ssbi-gpio";
+					interrupt-parent = <&pmicintc>;
+					interrupts = <24 IRQ_TYPE_NONE>,
+						     <25 IRQ_TYPE_NONE>,
+						     <26 IRQ_TYPE_NONE>,
+						     <27 IRQ_TYPE_NONE>,
+						     <28 IRQ_TYPE_NONE>,
+						     <29 IRQ_TYPE_NONE>;
+					gpio-controller;
+					#gpio-cells = <2>;
+				};
+			};
+		};
+
+		sdcc1bam: dma@12182000{
+			compatible = "qcom,bam-v1.3.0";
+			reg = <0x12182000 0x8000>;
+			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gcc SDC1_H_CLK>;
+			clock-names = "bam_clk";
+			#dma-cells = <1>;
+			qcom,ee = <0>;
+		};
+
+		sdcc2bam: dma@12142000{
+			compatible = "qcom,bam-v1.3.0";
+			reg = <0x12142000 0x8000>;
+			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gcc SDC2_H_CLK>;
+			clock-names = "bam_clk";
+			#dma-cells = <1>;
+			qcom,ee = <0>;
+		};
+
+		amba {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			sdcc1: sdcc@12180000 {
+				status = "disabled";
+				compatible = "arm,pl18x", "arm,primecell";
+				arm,primecell-periphid = <0x00051180>;
+				reg = <0x12180000 0x2000>;
+				interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names	= "cmd_irq";
+				clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
+				clock-names = "mclk", "apb_pclk";
+				bus-width = <8>;
+				max-frequency = <48000000>;
+				cap-sd-highspeed;
+				cap-mmc-highspeed;
+				vmmc-supply = <&vsdcc_fixed>;
+				dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
+				dma-names = "tx", "rx";
+				assigned-clocks = <&gcc SDC1_CLK>;
+				assigned-clock-rates = <400000>;
+			};
+
+			sdcc2: sdcc@12140000 {
+				compatible = "arm,pl18x", "arm,primecell";
+				arm,primecell-periphid = <0x00051180>;
+				status = "disabled";
+				reg = <0x12140000 0x2000>;
+				interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names	= "cmd_irq";
+				clocks = <&gcc SDC2_CLK>, <&gcc SDC2_H_CLK>;
+				clock-names = "mclk", "apb_pclk";
+				bus-width = <4>;
+				cap-sd-highspeed;
+				cap-mmc-highspeed;
+				max-frequency = <48000000>;
+				no-1-8-v;
+				vmmc-supply = <&vsdcc_fixed>;
+				dmas = <&sdcc2bam 2>, <&sdcc2bam 1>;
+				dma-names = "tx", "rx";
+				assigned-clocks = <&gcc SDC2_CLK>;
+				assigned-clock-rates = <400000>;
+			};
+		};
+
+		tcsr: syscon@1a400000 {
+			compatible = "qcom,tcsr-mdm9615", "syscon";
+			reg = <0x1a400000 0x100>;
+		};
+
+		rpm: rpm@108000 {
+			compatible = "qcom,rpm-mdm9615";
+			reg = <0x108000 0x1000>;
+
+			qcom,ipc = <&l2cc 0x8 2>;
+
+			interrupts = <GIC_SPI 19 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 22 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names	= "ack", "err", "wakeup";
+
+			regulators {
+				compatible = "qcom,rpm-pm8018-regulators";
+
+				vin_lvs1-supply = <&pm8018_s3>;
+
+				vdd_l7-supply = <&pm8018_s4>;
+				vdd_l8-supply = <&pm8018_s3>;
+				vdd_l9_l10_l11_l12-supply = <&pm8018_s5>;
+
+				/* Buck SMPS */
+				pm8018_s1: s1 {
+					regulator-min-microvolt = <500000>;
+					regulator-max-microvolt = <1150000>;
+					qcom,switch-mode-frequency = <1600000>;
+					bias-pull-down;
+				};
+
+				pm8018_s2: s2 {
+					regulator-min-microvolt = <1225000>;
+					regulator-max-microvolt = <1300000>;
+					qcom,switch-mode-frequency = <1600000>;
+					bias-pull-down;
+				};
+
+				pm8018_s3: s3 {
+					regulator-always-on;
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					qcom,switch-mode-frequency = <1600000>;
+					bias-pull-down;
+				};
+
+				pm8018_s4: s4 {
+					regulator-min-microvolt = <2100000>;
+					regulator-max-microvolt = <2200000>;
+					qcom,switch-mode-frequency = <1600000>;
+					bias-pull-down;
+				};
+
+				pm8018_s5: s5 {
+					regulator-always-on;
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					qcom,switch-mode-frequency = <1600000>;
+					bias-pull-down;
+				};
+
+				/* PMOS LDO */
+				pm8018_l2: l2 {
+					regulator-always-on;
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					bias-pull-down;
+				};
+
+				pm8018_l3: l3 {
+					regulator-always-on;
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					bias-pull-down;
+				};
+
+				pm8018_l4: l4 {
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					bias-pull-down;
+				};
+
+				pm8018_l5: l5 {
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					bias-pull-down;
+				};
+
+				pm8018_l6: l6 {
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <2850000>;
+					bias-pull-down;
+				};
+
+				pm8018_l7: l7 {
+					regulator-min-microvolt = <1850000>;
+					regulator-max-microvolt = <1900000>;
+					bias-pull-down;
+				};
+
+				pm8018_l8: l8 {
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <1200000>;
+					bias-pull-down;
+				};
+
+				pm8018_l9: l9 {
+					regulator-min-microvolt = <750000>;
+					regulator-max-microvolt = <1150000>;
+					bias-pull-down;
+				};
+
+				pm8018_l10: l10 {
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					bias-pull-down;
+				};
+
+				pm8018_l11: l11 {
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					bias-pull-down;
+				};
+
+				pm8018_l12: l12 {
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1050000>;
+					bias-pull-down;
+				};
+
+				pm8018_l13: l13 {
+					regulator-min-microvolt = <1850000>;
+					regulator-max-microvolt = <2950000>;
+					bias-pull-down;
+				};
+
+				pm8018_l14: l14 {
+					regulator-min-microvolt = <2850000>;
+					regulator-max-microvolt = <2850000>;
+					bias-pull-down;
+				};
+
+				/* Low Voltage Switch */
+				pm8018_lvs1: lvs1 {
+					bias-pull-down;
+				};
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,170 @@
+/*
+ * Device Tree Source for Sierra Wireless WP8548 Module
+ *
+ * Copyright (C) 2016 BayLibre, SAS.
+ * Author : Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "qcom-mdm9615.dtsi"
+
+/ {
+	model = "Sierra Wireless WP8548 Module";
+	compatible = "swir,wp8548", "qcom,mdm9615";
+
+	memory {
+		reg = <0x48000000 0x7F00000>;
+	};
+};
+
+&msmgpio {
+	pinctrl-0 = <&reset_out_pins>;
+	pinctrl-names = "default";
+
+	gsbi3_pins: gsbi3_pins {
+		mux {
+			pins = "gpio8", "gpio9", "gpio10", "gpio11";
+			function = "gsbi3";
+			drive-strength = <8>;
+			bias-disable;
+		};
+	};
+
+	gsbi4_pins: gsbi4_pins {
+		mux {
+			pins = "gpio12", "gpio13", "gpio14", "gpio15";
+			function = "gsbi4";
+			drive-strength = <8>;
+			bias-disable;
+		};
+	};
+
+	gsbi5_i2c_pins: gsbi5_i2c_pins {
+		pin16 {
+			pins = "gpio16";
+			function = "gsbi5_i2c";
+			drive-strength = <8>;
+			bias-disable;
+		};
+
+		pin17 {
+			pins = "gpio17";
+			function = "gsbi5_i2c";
+			drive-strength = <2>;
+			bias-disable;
+		};
+	};
+
+	gsbi5_uart_pins: gsbi5_uart_pins {
+		mux {
+			pins = "gpio18", "gpio19";
+			function = "gsbi5_uart";
+			drive-strength = <8>;
+			bias-disable;
+		};
+	};
+
+	reset_out_pins: reset_out_pins {
+		pins {
+			pins = "gpio66";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-pull-up;
+			output-high;
+		};
+	};
+};
+
+&pmicgpio {
+	usb_vbus_5v_pins: usb_vbus_5v_pins {
+		pins = "gpio4";
+		function = "normal";
+		output-high;
+		bias-disable;
+		qcom,drive-strength = <1>;
+		power-source = <2>;
+	};
+};
+
+&gsbi3 {
+	status = "ok";
+	qcom,mode = <GSBI_PROT_SPI>;
+};
+
+&gsbi3_spi {
+	status = "ok";
+	pinctrl-0 = <&gsbi3_pins>;
+	pinctrl-names = "default";
+	assigned-clocks = <&gcc GSBI3_QUP_CLK>;
+	assigned-clock-rates = <24000000>;
+};
+
+&gsbi4 {
+	status = "ok";
+	qcom,mode = <GSBI_PROT_UART_W_FC>;
+};
+
+&gsbi4_serial {
+	status = "ok";
+	pinctrl-0 = <&gsbi4_pins>;
+	pinctrl-names = "default";
+};
+
+&gsbi5 {
+	status = "ok";
+	qcom,mode = <GSBI_PROT_I2C_UART>;
+};
+
+&gsbi5_i2c {
+	status = "ok";
+	clock-frequency = <200000>;
+	pinctrl-0 = <&gsbi5_i2c_pins>;
+	pinctrl-names = "default";
+};
+
+&gsbi5_serial {
+	status = "ok";
+	pinctrl-0 = <&gsbi5_uart_pins>;
+	pinctrl-names = "default";
+};
+
+&sdcc1 {
+	status = "ok";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,281 @@
+/*
+ * Device Tree Source for mangOH Green Board with WP8548 Module
+ *
+ * Copyright (C) 2016 BayLibre, SAS.
+ * Author : Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 <dt-bindings/input/input.h>
+
+#include "qcom-mdm9615-wp8548.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	model = "MangOH Green with WP8548 Module";
+	compatible = "swir,mangoh-green-wp8548", "swir,wp8548", "qcom,mdm9615";
+
+	aliases {
+		spi0 = &gsbi3_spi;
+		serial0 = &gsbi4_serial;
+		serial1 = &gsbi5_serial;
+		i2c0 = &gsbi5_i2c;
+		mmc0 = &sdcc1;
+	};
+
+	chosen {
+		stdout-path = "serial1:115200n8";
+	};
+};
+
+&msmgpio {
+	/* MangOH GPIO Mapping :
+	 * - 2 : GPIOEXP_INT2
+	 * - 7 : IOT1_GPIO2
+	 * - 8 : IOT0_GPIO4
+	 * - 13: IOT0_GPIO3
+	 * - 21: IOT1_GPIO4
+	 * - 22: IOT2_GPIO1
+	 * - 23: IOT2_GPIO2
+	 * - 24: IOT2_GPIO3
+	 * - 25: IOT1_GPIO1
+	 * - 32: IOT1_GPIO3
+	 * - 33: IOT0_GPIO2
+	 * - 42: IOT0_GPIO1 and SD Card Detect
+	 */
+
+	gpioext1_pins: gpioext1_pins {
+		pins {
+			pins = "gpio2";
+			function = "gpio";
+			input-enable;
+			bias-disable;
+		};
+	};
+
+	sdc_cd_pins: sdc_cd_pins {
+		pins {
+			pins = "gpio42";
+			function = "gpio";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+	};
+};
+
+&gsbi3_spi {
+	spi@0 {
+		compatible = "swir,mangoh-iotport-spi", "spidev";
+		spi-max-frequency = <24000000>;
+		reg = <0>;
+	};
+};
+
+&gsbi5_i2c {
+	mux@71 {
+		compatible = "nxp,pca9548";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+
+		i2c_iot0: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		i2c_iot1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		i2c_iot2: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			usbhub: hub@8 {
+				compatible = "smsc,usb3503a";
+				reg = <0x8>;
+				connect-gpios = <&gpioext2 1 GPIO_ACTIVE_HIGH>;
+				intn-gpios = <&gpioext2 0 GPIO_ACTIVE_LOW>;
+				initial-mode = <1>;
+			};
+		};
+
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+
+			gpioext0: gpio@3e {
+				/* GPIO Expander 0 Mapping :
+				 * - 0: ARDUINO_RESET_Level shift
+				 * - 1: BattChrgr_PG_N
+				 * - 2: BattGauge_GPIO
+				 * - 3: LED_ON (out active high)
+				 * - 4: ATmega_reset_GPIO
+				 * - 5: X
+				 * - 6: PCM_ANALOG_SELECT (out active high)
+				 * - 7: X
+				 * - 8: Board_rev_res1 (in)
+				 * - 9: Board_rev_res2 (in)
+				 * - 10: UART_EXP1_ENn (out active low / pull-down)
+				 * - 11: UART_EXP1_IN (out pull-down)
+				 * - 12: UART_EXP2_IN (out pull-down)
+				 * - 13: SDIO_SEL (out pull-down)
+				 * - 14: SPI_EXP1_ENn (out active low / pull-down)
+				 * - 15: SPI_EXP1_IN (out pull-down)
+				 */
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				compatible = "semtech,sx1509q";
+				reg = <0x3e>;
+				interrupt-parent = <&gpioext1>;
+				interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+
+				probe-reset;
+
+				gpio-controller;
+				interrupt-controller;
+			};
+		};
+
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+
+			gpioext1: gpio@3f {
+				/* GPIO Expander 1 Mapping :
+				 * - 0: GPIOEXP_INT1
+				 * - 1: Battery detect
+				 * - 2: GPIO_SCF3_RESET
+				 * - 3: LED_CARD_DETECT_IOT0 (in)
+				 * - 4: LED_CARD_DETECT_IOT1 (in)
+				 * - 5: LED_CARD_DETECT_IOT2 (in)
+				 * - 6: UIM2_PWM_SELECT
+				 * - 7: UIM2_M2_S_SELECT
+				 * - 8: TP900
+				 * - 9: SENSOR_INT1 (in)
+				 * - 10: SENSOR_INT2 (in)
+				 * - 11: CARD_DETECT_IOT0 (in pull-up)
+				 * - 12: CARD_DETECT_IOT2 (in pull-up)
+				 * - 13: CARD_DETECT_IOT1 (in pull-up)
+				 * - 14: GPIOEXP_INT3 (in active low / pull-up)
+				 * - 15: BattChrgr_INT_N
+				 */
+				pinctrl-0 = <&gpioext1_pins>;
+				pinctrl-names = "default";
+
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				compatible = "semtech,sx1509q";
+				reg = <0x3f>;
+				interrupt-parent = <&msmgpio>;
+				interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+
+				probe-reset;
+
+				gpio-controller;
+				interrupt-controller;
+			};
+		};
+
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+
+			gpioext2: gpio@70 {
+				/* GPIO Expander 2 Mapping :
+				 * - 0: USB_HUB_INTn
+				 * - 1: HUB_CONNECT
+				 * - 2: GPIO_IOT2_RESET (out active low / pull-up)
+				 * - 3: GPIO_IOT1_RESET (out active low / pull-up)
+				 * - 4: GPIO_IOT0_RESET (out active low / pull-up)
+				 * - 5: TP901
+				 * - 6: TP902
+				 * - 7: TP903
+				 * - 8: UART_EXP2_ENn (out active low / pull-down)
+				 * - 9: PCM_EXP1_ENn (out active low)
+				 * - 10: PCM_EXP1_SEL (out)
+				 * - 11: ARD_FTDI
+				 * - 12: TP904
+				 * - 13: TP905
+				 * - 14: TP906
+				 * - 15: RS232_Enable (out active high / pull-up)
+				 */
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				compatible = "semtech,sx1509q";
+				reg = <0x70>;
+				interrupt-parent = <&gpioext1>;
+				interrupts = <14 IRQ_TYPE_EDGE_FALLING>;
+
+				probe-reset;
+
+				gpio-controller;
+				interrupt-controller;
+			};
+		};
+
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+		};
+	};
+};
+
+&sdcc1 {
+	pinctrl-0 = <&sdc_cd_pins>;
+	pinctrl-names = "default";
+	disable-wp;
+	cd-gpios = <&msmgpio 42 GPIO_ACTIVE_LOW>; /* Active low CD */
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-msm8660.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-msm8660.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-msm8660.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-msm8660.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -141,6 +141,23 @@
 			};
 		};
 
+		external-bus@1a100000 {
+			compatible = "qcom,msm8660-ebi2";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			ranges = <0 0x0 0x1a800000 0x00800000>,
+				 <1 0x0 0x1b000000 0x00800000>,
+				 <2 0x0 0x1b800000 0x00800000>,
+				 <3 0x0 0x1d000000 0x08000000>,
+				 <4 0x0 0x1c800000 0x00800000>,
+				 <5 0x0 0x1c000000 0x00800000>;
+			reg = <0x1a100000 0x1000>, <0x1a110000 0x1000>;
+			reg-names = "ebi2", "xmem";
+			clocks = <&gcc EBI2_2X_CLK>, <&gcc EBI2_CLK>;
+			clock-names = "ebi2x", "ebi2";
+			status = "disabled";
+		};
+
 		qcom,ssbi@500000 {
 			compatible = "qcom,ssbi";
 			reg = <0x500000 0x1000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-msm8974.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -220,13 +220,13 @@
 	};
 
 	clocks {
-		xo_board {
+		xo_board: xo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <19200000>;
 		};
 
-		sleep_clk {
+		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32768>;
@@ -558,8 +558,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 123 0>, <0 138 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC1_APPS_CLK>, <&gcc GCC_SDCC1_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC1_APPS_CLK>,
+				 <&gcc GCC_SDCC1_AHB_CLK>,
+				 <&xo_board>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
@@ -569,8 +571,10 @@
 			reg-names = "hc_mem", "core_mem";
 			interrupts = <0 125 0>, <0 221 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
-			clocks = <&gcc GCC_SDCC2_APPS_CLK>, <&gcc GCC_SDCC2_AHB_CLK>;
-			clock-names = "core", "iface";
+			clocks = <&gcc GCC_SDCC2_APPS_CLK>,
+				 <&gcc GCC_SDCC2_AHB_CLK>,
+				 <&xo_board>;
+			clock-names = "core", "iface", "xo";
 			status = "disabled";
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts	2017-02-12 16:03:20.000000000 -0500
@@ -224,6 +224,35 @@
 		status = "ok";
 	};
 
+	pinctrl@fd510000 {
+		sdhc1_pin_a: sdhc1-pin-active {
+			clk {
+				pins = "sdc1_clk";
+				drive-strength = <16>;
+				bias-disable;
+			};
+
+			cmd-data {
+				pins = "sdc1_cmd", "sdc1_data";
+				drive-strength = <10>;
+				bias-pull-up;
+			};
+		};
+	};
+
+	sdhci@f9824900 {
+		status = "ok";
+
+		vmmc-supply = <&pm8941_l20>;
+		vqmmc-supply = <&pm8941_s3>;
+
+		bus-width = <8>;
+		non-removable;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdhc1_pin_a>;
+	};
+
 	gpio-keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r7s72100.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r7s72100.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r7s72100.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r7s72100.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -117,6 +117,15 @@
 			clock-output-names = "ether";
 		};
 
+		mstp8_clks: mstp8_clks@fcfe0434 {
+			#clock-cells = <1>;
+			compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0xfcfe0434 4>;
+			clocks = <&p1_clk>;
+			clock-indices = <R7S72100_CLK_MMCIF>;
+			clock-output-names = "mmcif";
+		};
+
 		mstp9_clks: mstp9_clks@fcfe0438 {
 			#clock-cells = <1>;
 			compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
@@ -140,6 +149,14 @@
 			>;
 			clock-output-names = "spi0", "spi1", "spi2", "spi3", "spi4";
 		};
+		mstp12_clks: mstp12_clks@fcfe0444 {
+			#clock-cells = <1>;
+			compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
+			reg = <0xfcfe0444 4>;
+			clocks = <&p1_clk>, <&p1_clk>;
+			clock-indices = <R7S72100_CLK_SDHI1 R7S72100_CLK_SDHI0>;
+			clock-output-names = "sdhi1", "sdhi0";
+		};
 	};
 
 	cpus {
@@ -441,4 +458,42 @@
 		#size-cells = <0>;
 		status = "disabled";
 	};
+
+	mmcif: mmc@e804c800 {
+		compatible = "renesas,mmcif-r7s72100", "renesas,sh-mmcif";
+		reg = <0xe804c800 0x80>;
+		interrupts = <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R7S72100_CLK_MMCIF>;
+		reg-io-width = <4>;
+		bus-width = <8>;
+		status = "disabled";
+	};
+
+	sdhi0: sd@e804e000 {
+		compatible = "renesas,sdhi-r7s72100";
+		reg = <0xe804e000 0x100>;
+		interrupts = <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+
+		clocks = <&mstp12_clks R7S72100_CLK_SDHI0>;
+		cap-sd-highspeed;
+		cap-sdio-irq;
+		status = "disabled";
+	};
+
+	sdhi1: sd@e804e800 {
+		compatible = "renesas,sdhi-r7s72100";
+		reg = <0xe804e800 0x100>;
+		interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>;
+
+		clocks = <&mstp12_clks R7S72100_CLK_SDHI1>;
+		cap-sd-highspeed;
+		cap-sdio-irq;
+		status = "disabled";
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r7s72100-rskrza1.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r7s72100-rskrza1.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r7s72100-rskrza1.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r7s72100-rskrza1.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,6 +56,11 @@
 	};
 };
 
+&sdhi1 {
+	bus-width = <4>;
+	status = "okay";
+};
+
 &scif2 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a73a4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a73a4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a73a4.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a73a4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -751,6 +751,11 @@
 		};
 	};
 
+	prr: chipid@ff000044 {
+		compatible = "renesas,prr";
+		reg = <0 0xff000044 0 4>;
+	};
+
 	sysc: system-controller@e6180000 {
 		compatible = "renesas,sysc-r8a73a4", "renesas,sysc-rmobile";
 		reg = <0 0xe6180000 0 0x8000>, <0 0xe6188000 0 0x8000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7740.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7740.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7740.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7740.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -8,8 +8,6 @@
  * kind, whether express or implied.
  */
 
-/include/ "skeleton.dtsi"
-
 #include <dt-bindings/clock/r8a7740-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -17,6 +15,8 @@
 / {
 	compatible = "renesas,r8a7740";
 	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
 
 	cpus {
 		#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7743.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7743.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7743.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7743.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,476 @@
+/*
+ * Device Tree Source for the r8a7743 SoC
+ *
+ * Copyright (C) 2016 Cogent Embedded 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 <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/r8a7743-cpg-mssr.h>
+#include <dt-bindings/power/r8a7743-sysc.h>
+
+/ {
+	compatible = "renesas,r8a7743";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+			clock-frequency = <1500000000>;
+			clocks = <&cpg CPG_CORE R8A7743_CLK_Z>;
+			power-domains = <&sysc R8A7743_PD_CA15_CPU0>;
+			next-level-cache = <&L2_CA15>;
+		};
+
+		L2_CA15: cache-controller@0 {
+			compatible = "cache";
+			reg = <0>;
+			cache-unified;
+			cache-level = <2>;
+			power-domains = <&sysc R8A7743_PD_CA15_SCU>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller@f1001000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0 0xf1001000 0 0x1000>,
+			      <0 0xf1002000 0 0x1000>,
+			      <0 0xf1004000 0 0x2000>,
+			      <0 0xf1006000 0 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) |
+						 IRQ_TYPE_LEVEL_HIGH)>;
+		};
+
+		irqc: interrupt-controller@e61c0000 {
+			compatible = "renesas,irqc-r8a7743", "renesas,irqc";
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			reg = <0 0xe61c0000 0 0x200>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 407>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+		};
+
+		timer {
+			compatible = "arm,armv7-timer";
+			interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>;
+		};
+
+		cpg: clock-controller@e6150000 {
+			compatible = "renesas,r8a7743-cpg-mssr";
+			reg = <0 0xe6150000 0 0x1000>;
+			clocks = <&extal_clk>, <&usb_extal_clk>;
+			clock-names = "extal", "usb_extal";
+			#clock-cells = <2>;
+			#power-domain-cells = <0>;
+		};
+
+		sysc: system-controller@e6180000 {
+			compatible = "renesas,r8a7743-sysc";
+			reg = <0 0xe6180000 0 0x200>;
+			#power-domain-cells = <1>;
+		};
+
+		rst: reset-controller@e6160000 {
+			compatible = "renesas,r8a7743-rst";
+			reg = <0 0xe6160000 0 0x100>;
+		};
+
+		dmac0: dma-controller@e6700000 {
+			compatible = "renesas,dmac-r8a7743",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe6700000 0 0x20000>;
+			interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14";
+			clocks = <&cpg CPG_MOD 219>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			#dma-cells = <1>;
+			dma-channels = <15>;
+		};
+
+		dmac1: dma-controller@e6720000 {
+			compatible = "renesas,dmac-r8a7743",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe6720000 0 0x20000>;
+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14";
+			clocks = <&cpg CPG_MOD 218>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			#dma-cells = <1>;
+			dma-channels = <15>;
+		};
+
+		scifa0: serial@e6c40000 {
+			compatible = "renesas,scifa-r8a7743",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c40000 0 0x40>;
+			interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 204>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+			       <&dmac1 0x21>, <&dmac1 0x22>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa1: serial@e6c50000 {
+			compatible = "renesas,scifa-r8a7743",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c50000 0 0x40>;
+			interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 203>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+			       <&dmac1 0x25>, <&dmac1 0x26>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa2: serial@e6c60000 {
+			compatible = "renesas,scifa-r8a7743",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c60000 0 0x40>;
+			interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 202>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+			       <&dmac1 0x27>, <&dmac1 0x28>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa3: serial@e6c70000 {
+			compatible = "renesas,scifa-r8a7743",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c70000 0 0x40>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1106>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+			       <&dmac1 0x1b>, <&dmac1 0x1c>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa4: serial@e6c78000 {
+			compatible = "renesas,scifa-r8a7743",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c78000 0 0x40>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1107>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+			       <&dmac1 0x1f>, <&dmac1 0x20>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa5: serial@e6c80000 {
+			compatible = "renesas,scifa-r8a7743",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c80000 0 0x40>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1108>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+			       <&dmac1 0x23>, <&dmac1 0x24>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifb0: serial@e6c20000 {
+			compatible = "renesas,scifb-r8a7743",
+				     "renesas,rcar-gen2-scifb", "renesas,scifb";
+			reg = <0 0xe6c20000 0 0x100>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 206>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifb1: serial@e6c30000 {
+			compatible = "renesas,scifb-r8a7743",
+				     "renesas,rcar-gen2-scifb", "renesas,scifb";
+			reg = <0 0xe6c30000 0 0x100>;
+			interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 207>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+			       <&dmac1 0x19>, <&dmac1 0x1a>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifb2: serial@e6ce0000 {
+			compatible = "renesas,scifb-r8a7743",
+				     "renesas,rcar-gen2-scifb", "renesas,scifb";
+			reg = <0 0xe6ce0000 0 0x100>;
+			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 216>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+			       <&dmac1 0x1d>, <&dmac1 0x1e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif0: serial@e6e60000 {
+			compatible = "renesas,scif-r8a7743",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6e60000 0 0x40>;
+			interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 721>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+			       <&dmac1 0x29>, <&dmac1 0x2a>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif1: serial@e6e68000 {
+			compatible = "renesas,scif-r8a7743",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6e68000 0 0x40>;
+			interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 720>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+			       <&dmac1 0x2d>, <&dmac1 0x2e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif2: serial@e6e58000 {
+			compatible = "renesas,scif-r8a7743",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6e58000 0 0x40>;
+			interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 719>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+			       <&dmac1 0x2b>, <&dmac1 0x2c>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif3: serial@e6ea8000 {
+			compatible = "renesas,scif-r8a7743",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6ea8000 0 0x40>;
+			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 718>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+			       <&dmac1 0x2f>, <&dmac1 0x30>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif4: serial@e6ee0000 {
+			compatible = "renesas,scif-r8a7743",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6ee0000 0 0x40>;
+			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 715>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+			       <&dmac1 0xfb>, <&dmac1 0xfc>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif5: serial@e6ee8000 {
+			compatible = "renesas,scif-r8a7743",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6ee8000 0 0x40>;
+			interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 714>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+			       <&dmac1 0xfd>, <&dmac1 0xfe>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		hscif0: serial@e62c0000 {
+			compatible = "renesas,hscif-r8a7743",
+				     "renesas,rcar-gen2-hscif", "renesas,hscif";
+			reg = <0 0xe62c0000 0 0x60>;
+			interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 717>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+			       <&dmac1 0x39>, <&dmac1 0x3a>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		hscif1: serial@e62c8000 {
+			compatible = "renesas,hscif-r8a7743",
+				     "renesas,rcar-gen2-hscif", "renesas,hscif";
+			reg = <0 0xe62c8000 0 0x60>;
+			interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 716>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+			       <&dmac1 0x4d>, <&dmac1 0x4e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		hscif2: serial@e62d0000 {
+			compatible = "renesas,hscif-r8a7743",
+				     "renesas,rcar-gen2-hscif", "renesas,hscif";
+			reg = <0 0xe62d0000 0 0x60>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 713>,
+				 <&cpg CPG_CORE R8A7743_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+			       <&dmac1 0x3b>, <&dmac1 0x3c>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		ether: ethernet@ee700000 {
+			compatible = "renesas,ether-r8a7743";
+			reg = <0 0xee700000 0 0x400>;
+			interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 813>;
+			power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+			phy-mode = "rmii";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+
+	/* External root clock */
+	extal_clk: extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board. */
+		clock-frequency = <0>;
+	};
+
+	/* External USB clock - can be overridden by the board */
+	usb_extal_clk: usb_extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
+
+	/* External SCIF clock */
+	scif_clk: scif {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board. */
+		clock-frequency = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7743-sk-rzg1m.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,57 @@
+/*
+ * Device Tree Source for the SK-RZG1M board
+ *
+ * Copyright (C) 2016 Cogent Embedded, 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.
+ */
+
+/dts-v1/;
+#include "r8a7743.dtsi"
+
+/ {
+	model = "SK-RZG1M";
+	compatible = "renesas,sk-rzg1m", "renesas,r8a7743";
+
+	aliases {
+		serial0 = &scif0;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x40000000>;
+	};
+
+	memory@200000000 {
+		device_type = "memory";
+		reg = <2 0x00000000 0 0x40000000>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <20000000>;
+};
+
+&scif0 {
+	status = "okay";
+};
+
+&ether {
+	phy-handle = <&phy1>;
+	renesas,ether-link-active-low;
+	status = "okay";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+		interrupt-parent = <&irqc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		micrel,led-mode = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7745.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7745.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7745.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7745.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,476 @@
+/*
+ * Device Tree Source for the r8a7745 SoC
+ *
+ * Copyright (C) 2016 Cogent Embedded 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 <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/r8a7745-cpg-mssr.h>
+#include <dt-bindings/power/r8a7745-sysc.h>
+
+/ {
+	compatible = "renesas,r8a7745";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0>;
+			clock-frequency = <1000000000>;
+			clocks = <&cpg CPG_CORE R8A7745_CLK_Z2>;
+			power-domains = <&sysc R8A7745_PD_CA7_CPU0>;
+			next-level-cache = <&L2_CA7>;
+		};
+
+		L2_CA7: cache-controller@0 {
+			compatible = "cache";
+			reg = <0>;
+			cache-unified;
+			cache-level = <2>;
+			power-domains = <&sysc R8A7745_PD_CA7_SCU>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		interrupt-parent = <&gic>;
+
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gic: interrupt-controller@f1001000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0 0xf1001000 0 0x1000>,
+			      <0 0xf1002000 0 0x1000>,
+			      <0 0xf1004000 0 0x2000>,
+			      <0 0xf1006000 0 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) |
+						 IRQ_TYPE_LEVEL_HIGH)>;
+		};
+
+		irqc: interrupt-controller@e61c0000 {
+			compatible = "renesas,irqc-r8a7745", "renesas,irqc";
+			#interrupt-cells = <2>;
+			interrupt-controller;
+			reg = <0 0xe61c0000 0 0x200>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 407>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+		};
+
+		timer {
+			compatible = "arm,armv7-timer";
+			interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>,
+				     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) |
+						  IRQ_TYPE_LEVEL_LOW)>;
+		};
+
+		cpg: clock-controller@e6150000 {
+			compatible = "renesas,r8a7745-cpg-mssr";
+			reg = <0 0xe6150000 0 0x1000>;
+			clocks = <&extal_clk>, <&usb_extal_clk>;
+			clock-names = "extal", "usb_extal";
+			#clock-cells = <2>;
+			#power-domain-cells = <0>;
+		};
+
+		sysc: system-controller@e6180000 {
+			compatible = "renesas,r8a7745-sysc";
+			reg = <0 0xe6180000 0 0x200>;
+			#power-domain-cells = <1>;
+		};
+
+		rst: reset-controller@e6160000 {
+			compatible = "renesas,r8a7745-rst";
+			reg = <0 0xe6160000 0 0x100>;
+		};
+
+		dmac0: dma-controller@e6700000 {
+			compatible = "renesas,dmac-r8a7745",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe6700000 0 0x20000>;
+			interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14";
+			clocks = <&cpg CPG_MOD 219>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			#dma-cells = <1>;
+			dma-channels = <15>;
+		};
+
+		dmac1: dma-controller@e6720000 {
+			compatible = "renesas,dmac-r8a7745",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe6720000 0 0x20000>;
+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14";
+			clocks = <&cpg CPG_MOD 218>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			#dma-cells = <1>;
+			dma-channels = <15>;
+		};
+
+		scifa0: serial@e6c40000 {
+			compatible = "renesas,scifa-r8a7745",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c40000 0 0x40>;
+			interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 204>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x21>, <&dmac0 0x22>,
+			       <&dmac1 0x21>, <&dmac1 0x22>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa1: serial@e6c50000 {
+			compatible = "renesas,scifa-r8a7745",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c50000 0 0x40>;
+			interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 203>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x25>, <&dmac0 0x26>,
+			       <&dmac1 0x25>, <&dmac1 0x26>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa2: serial@e6c60000 {
+			compatible = "renesas,scifa-r8a7745",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c60000 0 0x40>;
+			interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 202>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x27>, <&dmac0 0x28>,
+			       <&dmac1 0x27>, <&dmac1 0x28>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa3: serial@e6c70000 {
+			compatible = "renesas,scifa-r8a7745",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c70000 0 0x40>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1106>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x1b>, <&dmac0 0x1c>,
+			       <&dmac1 0x1b>, <&dmac1 0x1c>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa4: serial@e6c78000 {
+			compatible = "renesas,scifa-r8a7745",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c78000 0 0x40>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1107>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x1f>, <&dmac0 0x20>,
+			       <&dmac1 0x1f>, <&dmac1 0x20>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifa5: serial@e6c80000 {
+			compatible = "renesas,scifa-r8a7745",
+				     "renesas,rcar-gen2-scifa", "renesas,scifa";
+			reg = <0 0xe6c80000 0 0x40>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 1108>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x23>, <&dmac0 0x24>,
+			       <&dmac1 0x23>, <&dmac1 0x24>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifb0: serial@e6c20000 {
+			compatible = "renesas,scifb-r8a7745",
+				     "renesas,rcar-gen2-scifb", "renesas,scifb";
+			reg = <0 0xe6c20000 0 0x100>;
+			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 206>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
+		       <&dmac1 0x3d>, <&dmac1 0x3e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifb1: serial@e6c30000 {
+			compatible = "renesas,scifb-r8a7745",
+				     "renesas,rcar-gen2-scifb", "renesas,scifb";
+			reg = <0 0xe6c30000 0 0x100>;
+			interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 207>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x19>, <&dmac0 0x1a>,
+			       <&dmac1 0x19>, <&dmac1 0x1a>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scifb2: serial@e6ce0000 {
+			compatible = "renesas,scifb-r8a7745",
+				     "renesas,rcar-gen2-scifb", "renesas,scifb";
+			reg = <0 0xe6ce0000 0 0x100>;
+			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 216>;
+			clock-names = "fck";
+			dmas = <&dmac0 0x1d>, <&dmac0 0x1e>,
+			       <&dmac1 0x1d>, <&dmac1 0x1e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif0: serial@e6e60000 {
+			compatible = "renesas,scif-r8a7745",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6e60000 0 0x40>;
+			interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 721>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+			       <&dmac1 0x29>, <&dmac1 0x2a>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif1: serial@e6e68000 {
+			compatible = "renesas,scif-r8a7745",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6e68000 0 0x40>;
+			interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 720>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+			       <&dmac1 0x2d>, <&dmac1 0x2e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif2: serial@e6e58000 {
+			compatible = "renesas,scif-r8a7745",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6e58000 0 0x40>;
+			interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 719>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+			       <&dmac1 0x2b>, <&dmac1 0x2c>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif3: serial@e6ea8000 {
+			compatible = "renesas,scif-r8a7745",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6ea8000 0 0x40>;
+			interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 718>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+			       <&dmac1 0x2f>, <&dmac1 0x30>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif4: serial@e6ee0000 {
+			compatible = "renesas,scif-r8a7745",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6ee0000 0 0x40>;
+			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 715>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+			       <&dmac1 0xfb>, <&dmac1 0xfc>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		scif5: serial@e6ee8000 {
+			compatible = "renesas,scif-r8a7745",
+				     "renesas,rcar-gen2-scif", "renesas,scif";
+			reg = <0 0xe6ee8000 0 0x40>;
+			interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 714>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+			       <&dmac1 0xfd>, <&dmac1 0xfe>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		hscif0: serial@e62c0000 {
+			compatible = "renesas,hscif-r8a7745",
+				     "renesas,rcar-gen2-hscif", "renesas,hscif";
+			reg = <0 0xe62c0000 0 0x60>;
+			interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 717>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x39>, <&dmac0 0x3a>,
+			       <&dmac1 0x39>, <&dmac1 0x3a>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		hscif1: serial@e62c8000 {
+			compatible = "renesas,hscif-r8a7745",
+				     "renesas,rcar-gen2-hscif", "renesas,hscif";
+			reg = <0 0xe62c8000 0 0x60>;
+			interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 716>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x4d>, <&dmac0 0x4e>,
+			       <&dmac1 0x4d>, <&dmac1 0x4e>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		hscif2: serial@e62d0000 {
+			compatible = "renesas,hscif-r8a7745",
+				     "renesas,rcar-gen2-hscif", "renesas,hscif";
+			reg = <0 0xe62d0000 0 0x60>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 713>,
+				 <&cpg CPG_CORE R8A7745_CLK_ZS>, <&scif_clk>;
+			clock-names = "fck", "brg_int", "scif_clk";
+			dmas = <&dmac0 0x3b>, <&dmac0 0x3c>,
+			       <&dmac1 0x3b>, <&dmac1 0x3c>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		ether: ethernet@ee700000 {
+			compatible = "renesas,ether-r8a7745";
+			reg = <0 0xee700000 0 0x400>;
+			interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 813>;
+			power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+			phy-mode = "rmii";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+
+	/* External root clock */
+	extal_clk: extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board. */
+		clock-frequency = <0>;
+	};
+
+	/* External USB clock - can be overridden by the board */
+	usb_extal_clk: usb_extal {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
+
+	/* External SCIF clock */
+	scif_clk: scif {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		/* This value must be overridden by the board. */
+		clock-frequency = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7745-sk-rzg1e.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * Device Tree Source for the SK-RZG1E board
+ *
+ * Copyright (C) 2016 Cogent Embedded, 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.
+ */
+
+/dts-v1/;
+#include "r8a7745.dtsi"
+
+/ {
+	model = "SK-RZG1E";
+	compatible = "renesas,sk-rzg1e", "renesas,r8a7745";
+
+	aliases {
+		serial0 = &scif2;
+	};
+
+	chosen {
+		bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0 0x40000000 0 0x40000000>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <20000000>;
+};
+
+&scif2 {
+	status = "okay";
+};
+
+&ether {
+	phy-handle = <&phy1>;
+	renesas,ether-link-active-low;
+	status = "okay";
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+		interrupt-parent = <&irqc>;
+		interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+		micrel,led-mode = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7778.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7778.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7778.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7778.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -14,8 +14,6 @@
  * kind, whether express or implied.
  */
 
-/include/ "skeleton.dtsi"
-
 #include <dt-bindings/clock/r8a7778-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -23,6 +21,8 @@
 / {
 	compatible = "renesas,r8a7778";
 	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
 
 	cpus {
 		#address-cells = <1>;
@@ -626,4 +626,9 @@
 				"sru-src6", "sru-src7", "sru-src8";
 		};
 	};
+
+	rst: reset-controller@ffcc0000 {
+		compatible = "renesas,r8a7778-reset-wdt";
+		reg = <0xffcc0000 0x40>;
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7779.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7779.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7779.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7779.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -9,8 +9,6 @@
  * kind, whether express or implied.
  */
 
-/include/ "skeleton.dtsi"
-
 #include <dt-bindings/clock/r8a7779-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -19,6 +17,8 @@
 / {
 	compatible = "renesas,r8a7779";
 	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
 
 	cpus {
 		#address-cells = <1>;
@@ -420,7 +420,7 @@
 
 	du: display@fff80000 {
 		compatible = "renesas,du-r8a7779";
-		reg = <0 0xfff80000 0 0x40000>;
+		reg = <0xfff80000 0x40000>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7779_CLK_DU>;
 		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
@@ -590,6 +590,16 @@
 		};
 	};
 
+	prr: chipid@ff000044 {
+		compatible = "renesas,prr";
+		reg = <0xff000044 4>;
+	};
+
+	rst: reset-controller@ffcc0000 {
+		compatible = "renesas,r8a7779-reset-wdt";
+		reg = <0xffcc0000 0x48>;
+	};
+
 	sysc: system-controller@ffd85000 {
 		compatible = "renesas,r8a7779-sysc";
 		reg = <0xffd85000 0x0200>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7779-marzen.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7779-marzen.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7779-marzen.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7779-marzen.dts	2017-02-12 16:03:20.000000000 -0500
@@ -170,7 +170,7 @@
 
 	du_pins: du {
 		du0 {
-			groups = "du0_rgb888", "du0_sync_1", "du0_clk_out_0";
+			groups = "du0_rgb888", "du0_sync_1", "du0_clk_out_0", "du0_clk_in";
 			function = "du0";
 		};
 		du1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7790.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7790.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7790.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7790.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -711,7 +711,7 @@
 	scifb0: serial@e6c20000 {
 		compatible = "renesas,scifb-r8a7790",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c20000 0 64>;
+		reg = <0 0xe6c20000 0 0x100>;
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB0>;
 		clock-names = "fck";
@@ -725,7 +725,7 @@
 	scifb1: serial@e6c30000 {
 		compatible = "renesas,scifb-r8a7790",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c30000 0 64>;
+		reg = <0 0xe6c30000 0 0x100>;
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB1>;
 		clock-names = "fck";
@@ -739,7 +739,7 @@
 	scifb2: serial@e6ce0000 {
 		compatible = "renesas,scifb-r8a7790",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6ce0000 0 64>;
+		reg = <0 0xe6ce0000 0 0x100>;
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7790_CLK_SCIFB2>;
 		clock-names = "fck";
@@ -1471,6 +1471,16 @@
 		};
 	};
 
+	prr: chipid@ff000044 {
+		compatible = "renesas,prr";
+		reg = <0 0xff000044 0 4>;
+	};
+
+	rst: reset-controller@e6160000 {
+		compatible = "renesas,r8a7790-rst";
+		reg = <0 0xe6160000 0 0x0100>;
+	};
+
 	sysc: system-controller@e6180000 {
 		compatible = "renesas,r8a7790-sysc";
 		reg = <0 0xe6180000 0 0x0200>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7790-lager.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7790-lager.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7790-lager.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7790-lager.dts	2017-02-12 16:03:20.000000000 -0500
@@ -50,7 +50,9 @@
 	aliases {
 		serial0 = &scif0;
 		serial1 = &scifa1;
-		i2c8 = "i2cexio";
+		i2c8 = &gpioi2c1;
+		i2c10 = &i2cexio0;
+		i2c11 = &i2cexio1;
 	};
 
 	chosen {
@@ -231,12 +233,23 @@
 		};
 	};
 
+	hdmi-in {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&adv7612_in>;
+			};
+		};
+	};
+
 	hdmi-out {
 		compatible = "hdmi-connector";
 		type = "a";
 
 		port {
-			hdmi_con: endpoint {
+			hdmi_con_out: endpoint {
 				remote-endpoint = <&adv7511_out>;
 			};
 		};
@@ -254,6 +267,17 @@
 		clock-frequency = <148500000>;
 	};
 
+	gpioi2c1: i2c-8 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		status = "disabled";
+		gpios = <&gpio1 17 GPIO_ACTIVE_HIGH /* sda */
+			 &gpio1 16 GPIO_ACTIVE_HIGH /* scl */
+			>;
+		i2c-gpio,delay-us = <5>;
+	};
+
 	/*
 	 * IIC0/I2C0 is routed to EXIO connector A, pins 114 (SCL) + 116 (SDA) only.
 	 * We use the I2C demuxer, so the desired IP core can be selected at runtime
@@ -262,11 +286,26 @@
 	 * bus with IIC3 on pins 110 (SCL) + 112 (SDA), select I2C0 at runtime, and
 	 * instantiate the slave device at runtime according to the documentation.
 	 * You can then communicate with the slave via IIC3.
+	 *
+	 * IIC0/I2C0 does not appear to support fallback to GPIO.
 	 */
-	i2cexio: i2c-8 {
+	i2cexio0: i2c-10 {
 		compatible = "i2c-demux-pinctrl";
 		i2c-parent = <&iic0>, <&i2c0>;
-		i2c-bus-name = "i2c-exio";
+		i2c-bus-name = "i2c-exio0";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	/*
+	 * IIC1/I2C1 is routed to EXIO connector A, pins 78 (SCL) + 80 (SDA).
+	 * This is similar to the arangement described for i2cexio0 (above)
+	 * with a fallback to GPIO also provided.
+	 */
+	i2cexio1: i2c-11 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&iic1>, <&i2c1>, <&gpioi2c1>;
+		i2c-bus-name = "i2c-exio1";
 		#address-cells = <1>;
 		#size-cells = <0>;
 	};
@@ -392,6 +431,11 @@
 		function = "iic0";
 	};
 
+	i2c1_pins: i2c1 {
+		groups = "i2c1";
+		function = "i2c1";
+	};
+
 	iic1_pins: iic1 {
 		groups = "iic1";
 		function = "iic1";
@@ -427,6 +471,11 @@
 		function = "usb2";
 	};
 
+	vin0_pins: vin0 {
+		groups = "vin0_data24", "vin0_sync", "vin0_clkenb", "vin0_clk";
+		function = "vin0";
+	};
+
 	vin1_pins: vin1 {
 		groups = "vin1_data8", "vin1_clk";
 		function = "vin1";
@@ -559,6 +608,7 @@
 	vqmmc-supply = <&vccq_sdhi0>;
 	cd-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
 	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
 };
 
@@ -580,18 +630,22 @@
 
 &i2c0	{
 	pinctrl-0 = <&i2c0_pins>;
-	pinctrl-names = "i2c-exio";
+	pinctrl-names = "i2c-exio0";
 };
 
 &iic0	{
 	pinctrl-0 = <&iic0_pins>;
-	pinctrl-names = "i2c-exio";
+	pinctrl-names = "i2c-exio0";
+};
+
+&i2c1	{
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "i2c-exio1";
 };
 
 &iic1	{
-	status = "okay";
 	pinctrl-0 = <&iic1_pins>;
-	pinctrl-names = "default";
+	pinctrl-names = "i2c-exio1";
 };
 
 &iic2	{
@@ -646,7 +700,34 @@
 			port@1 {
 				reg = <1>;
 				adv7511_out: endpoint {
-					remote-endpoint = <&hdmi_con>;
+					remote-endpoint = <&hdmi_con_out>;
+				};
+			};
+		};
+	};
+
+	hdmi-in@4c {
+		compatible = "adi,adv7612";
+		reg = <0x4c>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+		default-input = <0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7612_in: endpoint {
+					remote-endpoint = <&hdmi_con_in>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				adv7612_out: endpoint {
+					remote-endpoint = <&vin0ep2>;
 				};
 			};
 		};
@@ -722,6 +803,25 @@
 	status = "okay";
 };
 
+/* HDMI video input */
+&vin0 {
+	pinctrl-0 = <&vin0_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+
+	port {
+		vin0ep2: endpoint {
+			remote-endpoint = <&adv7612_out>;
+			bus-width = <24>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			pclk-sample = <1>;
+			data-active = <1>;
+		};
+	};
+};
+
 /* composite video input */
 &vin1 {
 	pinctrl-0 = <&vin1_pins>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7791.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7791.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7791.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7791.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -584,6 +584,7 @@
 		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
 		       <&dmac1 0xcd>, <&dmac1 0xce>;
 		dma-names = "tx", "rx", "tx", "rx";
+		max-frequency = <195000000>;
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -596,6 +597,7 @@
 		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
 		       <&dmac1 0xc1>, <&dmac1 0xc2>;
 		dma-names = "tx", "rx", "tx", "rx";
+		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -608,6 +610,7 @@
 		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
 		       <&dmac1 0xd3>, <&dmac1 0xd4>;
 		dma-names = "tx", "rx", "tx", "rx";
+		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -699,7 +702,7 @@
 	scifb0: serial@e6c20000 {
 		compatible = "renesas,scifb-r8a7791",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c20000 0 64>;
+		reg = <0 0xe6c20000 0 0x100>;
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB0>;
 		clock-names = "fck";
@@ -713,7 +716,7 @@
 	scifb1: serial@e6c30000 {
 		compatible = "renesas,scifb-r8a7791",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c30000 0 64>;
+		reg = <0 0xe6c30000 0 0x100>;
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB1>;
 		clock-names = "fck";
@@ -727,7 +730,7 @@
 	scifb2: serial@e6ce0000 {
 		compatible = "renesas,scifb-r8a7791",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6ce0000 0 64>;
+		reg = <0 0xe6ce0000 0 0x100>;
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7791_CLK_SCIFB2>;
 		clock-names = "fck";
@@ -1482,6 +1485,16 @@
 		};
 	};
 
+	rst: reset-controller@e6160000 {
+		compatible = "renesas,r8a7791-rst";
+		reg = <0 0xe6160000 0 0x0100>;
+	};
+
+	prr: chipid@ff000044 {
+		compatible = "renesas,prr";
+		reg = <0 0xff000044 0 4>;
+	};
+
 	sysc: system-controller@e6180000 {
 		compatible = "renesas,r8a7791-sysc";
 		reg = <0 0xe6180000 0 0x0200>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7791-koelsch.dts	2017-02-12 16:03:20.000000000 -0500
@@ -50,6 +50,8 @@
 	aliases {
 		serial0 = &scif0;
 		serial1 = &scif1;
+		i2c9 = &gpioi2c1;
+		i2c12 = &i2cexio1;
 	};
 
 	chosen {
@@ -265,12 +267,23 @@
 		};
 	};
 
+	hdmi-in {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con_in: endpoint {
+				remote-endpoint = <&adv7612_in>;
+			};
+		};
+	};
+
 	hdmi-out {
 		compatible = "hdmi-connector";
 		type = "a";
 
 		port {
-			hdmi_con: endpoint {
+			hdmi_con_out: endpoint {
 				remote-endpoint = <&adv7511_out>;
 			};
 		};
@@ -287,6 +300,29 @@
 		#clock-cells = <0>;
 		clock-frequency = <148500000>;
 	};
+
+	gpioi2c1: i2c-9 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		status = "disabled";
+		gpios = <&gpio7 16 GPIO_ACTIVE_HIGH /* sda */
+			 &gpio7 15 GPIO_ACTIVE_HIGH /* scl */
+			>;
+		i2c-gpio,delay-us = <5>;
+	};
+
+	/*
+	 * I2C1 is routed to EXIO connector B, pins 64 (SCL) + 66 (SDA).
+	 * A fallback to GPIO is provided.
+	 */
+	i2cexio1: i2c-12 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&i2c1>, <&gpioi2c1>;
+		i2c-bus-name = "i2c-exio1";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
 };
 
 &du {
@@ -322,6 +358,11 @@
 	pinctrl-0 = <&scif_clk_pins>;
 	pinctrl-names = "default";
 
+	i2c1_pins: i2c1 {
+		groups = "i2c1";
+		function = "i2c1";
+	};
+
 	i2c2_pins: i2c2 {
 		groups = "i2c2";
 		function = "i2c2";
@@ -360,16 +401,37 @@
 	sdhi0_pins: sd0 {
 		groups = "sdhi0_data4", "sdhi0_ctrl";
 		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
 	};
 
 	sdhi1_pins: sd1 {
 		groups = "sdhi1_data4", "sdhi1_ctrl";
 		function = "sdhi1";
+		power-source = <3300>;
+	};
+
+	sdhi1_pins_uhs: sd1_uhs {
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
+		power-source = <1800>;
 	};
 
 	sdhi2_pins: sd2 {
 		groups = "sdhi2_data4", "sdhi2_ctrl";
 		function = "sdhi2";
+		power-source = <3300>;
+	};
+
+	sdhi2_pins_uhs: sd2_uhs {
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
 	};
 
 	qspi_pins: qspi {
@@ -393,6 +455,11 @@
 		function = "usb1";
 	};
 
+	vin0_pins: vin0 {
+		groups = "vin0_data24", "vin0_sync", "vin0_clkenb", "vin0_clk";
+		function = "vin0";
+	};
+
 	vin1_pins: vin1 {
 		groups = "vin1_data8", "vin1_clk";
 		function = "vin1";
@@ -454,33 +521,40 @@
 
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi0>;
 	vqmmc-supply = <&vccq_sdhi0>;
 	cd-gpios = <&gpio6 6 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
 };
 
 &sdhi1 {
 	pinctrl-0 = <&sdhi1_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi1_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi1>;
 	vqmmc-supply = <&vccq_sdhi1>;
 	cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio6 15 GPIO_ACTIVE_HIGH>;
+	sd-uhs-sdr50;
 	status = "okay";
 };
 
 &sdhi2 {
 	pinctrl-0 = <&sdhi2_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi2_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi2>;
 	vqmmc-supply = <&vccq_sdhi2>;
 	cd-gpios = <&gpio6 22 GPIO_ACTIVE_LOW>;
+	sd-uhs-sdr50;
 	status = "okay";
 };
 
@@ -538,6 +612,11 @@
 	};
 };
 
+&i2c1 {
+	pinctrl-0 = <&i2c1_pins>;
+	pinctrl-names = "i2c-exio1";
+};
+
 &i2c2 {
 	pinctrl-0 = <&i2c2_pins>;
 	pinctrl-names = "default";
@@ -590,7 +669,34 @@
 			port@1 {
 				reg = <1>;
 				adv7511_out: endpoint {
-					remote-endpoint = <&hdmi_con>;
+					remote-endpoint = <&hdmi_con_out>;
+				};
+			};
+		};
+	};
+
+	hdmi-in@4c {
+		compatible = "adi,adv7612";
+		reg = <0x4c>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+		default-input = <0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7612_in: endpoint {
+					remote-endpoint = <&hdmi_con_in>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				adv7612_out: endpoint {
+					remote-endpoint = <&vin0ep2>;
 				};
 			};
 		};
@@ -672,6 +778,27 @@
 	cpu0-supply = <&vdd_dvfs>;
 };
 
+/* HDMI video input */
+&vin0 {
+	status = "okay";
+	pinctrl-0 = <&vin0_pins>;
+	pinctrl-names = "default";
+
+	port {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		vin0ep2: endpoint {
+			remote-endpoint = <&adv7612_out>;
+			bus-width = <24>;
+			hsync-active = <0>;
+			vsync-active = <0>;
+			pclk-sample = <1>;
+			data-active = <1>;
+		};
+	};
+};
+
 /* composite video input */
 &vin1 {
 	status = "okay";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7792.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7792.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7792.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7792.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,8 @@
 		i2c4 = &i2c4;
 		i2c5 = &i2c5;
 		spi0 = &qspi;
+		spi1 = &msiof0;
+		spi2 = &msiof1;
 		vin0 = &vin0;
 		vin1 = &vin1;
 		vin2 = &vin2;
@@ -118,6 +120,16 @@
 				      IRQ_TYPE_LEVEL_LOW)>;
 		};
 
+		rst: reset-controller@e6160000 {
+			compatible = "renesas,r8a7792-rst";
+			reg = <0 0xe6160000 0 0x0100>;
+		};
+
+		prr: chipid@ff000044 {
+			compatible = "renesas,prr";
+			reg = <0 0xff000044 0 4>;
+		};
+
 		sysc: system-controller@e6180000 {
 			compatible = "renesas,r8a7792-sysc";
 			reg = <0 0xe6180000 0 0x0200>;
@@ -572,6 +584,34 @@
 			status = "disabled";
 		};
 
+		msiof0: spi@e6e20000 {
+			compatible = "renesas,msiof-r8a7792";
+			reg = <0 0xe6e20000 0 0x0064>;
+			interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&mstp0_clks R8A7792_CLK_MSIOF0>;
+			dmas = <&dmac0 0x51>, <&dmac0 0x52>,
+			       <&dmac1 0x51>, <&dmac1 0x52>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		msiof1: spi@e6e10000 {
+			compatible = "renesas,msiof-r8a7792";
+			reg = <0 0xe6e10000 0 0x0064>;
+			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&mstp2_clks R8A7792_CLK_MSIOF1>;
+			dmas = <&dmac0 0x55>, <&dmac0 0x56>,
+			       <&dmac1 0x55>, <&dmac1 0x56>;
+			dma-names = "tx", "rx", "tx", "rx";
+			power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		du: display@feb00000 {
 			compatible = "renesas,du-r8a7792";
 			reg = <0 0xfeb00000 0 0x40000>;
@@ -763,6 +803,13 @@
 			clock-div = <48>;
 			clock-mult = <1>;
 		};
+		mp_clk: mp {
+			compatible = "fixed-factor-clock";
+			clocks = <&pll1_div2_clk>;
+			#clock-cells = <0>;
+			clock-div = <15>;
+			clock-mult = <1>;
+		};
 		m2_clk: m2 {
 			compatible = "fixed-factor-clock";
 			clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
@@ -793,6 +840,15 @@
 		};
 
 		/* Gate clocks */
+		mstp0_clks: mstp0_clks@e6150130 {
+			compatible = "renesas,r8a7792-mstp-clocks",
+				     "renesas,cpg-mstp-clocks";
+			reg = <0 0xe6150130 0 4>, <0 0xe6150030 0 4>;
+			clocks = <&mp_clk>;
+			#clock-cells = <1>;
+			clock-indices = <R8A7792_CLK_MSIOF0>;
+			clock-output-names = "msiof0";
+		};
 		mstp1_clks: mstp1_clks@e6150134 {
 			compatible = "renesas,r8a7792-mstp-clocks",
 				     "renesas,cpg-mstp-clocks";
@@ -811,12 +867,13 @@
 			compatible = "renesas,r8a7792-mstp-clocks",
 				     "renesas,cpg-mstp-clocks";
 			reg = <0 0xe6150138 0 4>, <0 0xe6150040 0 4>;
-			clocks = <&zs_clk>, <&zs_clk>;
+			clocks = <&mp_clk>, <&zs_clk>, <&zs_clk>;
 			#clock-cells = <1>;
 			clock-indices = <
+				R8A7792_CLK_MSIOF1
 				R8A7792_CLK_SYS_DMAC1 R8A7792_CLK_SYS_DMAC0
 			>;
-			clock-output-names = "sys-dmac1", "sys-dmac0";
+			clock-output-names = "msiof1", "sys-dmac1", "sys-dmac0";
 		};
 		mstp3_clks: mstp3_clks@e615013c {
 			compatible = "renesas,r8a7792-mstp-clocks",
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7792-wheat.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7792-wheat.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7792-wheat.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7792-wheat.dts	2017-02-12 16:03:20.000000000 -0500
@@ -86,6 +86,34 @@
 		gpio = <&gpio11 12 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	hdmi-out0 {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con0: endpoint {
+				remote-endpoint = <&adv7513_0_out>;
+			};
+		};
+	};
+
+	hdmi-out1 {
+		compatible = "hdmi-connector";
+		type = "a";
+
+		port {
+			hdmi_con1: endpoint {
+				remote-endpoint = <&adv7513_1_out>;
+			};
+		};
+	};
+
+	osc2_clk: osc2 {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <74250000>;
+	};
 };
 
 &extal_clk {
@@ -128,6 +156,16 @@
 		groups = "qspi_ctrl", "qspi_data4";
 		function = "qspi";
 	};
+
+	du0_pins: du0 {
+		groups = "du0_rgb888", "du0_sync", "du0_disp";
+		function = "du0";
+	};
+
+	du1_pins: du1 {
+		groups = "du1_rgb666", "du1_sync", "du1_disp";
+		function = "du1";
+	};
 };
 
 &scif0 {
@@ -196,4 +234,92 @@
 			};
 		};
 	};
+};
+
+&i2c4 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	hdmi@3d {
+		compatible = "adi,adv7513";
+		reg = <0x3d>;
+
+		adi,input-depth = <8>;
+		adi,input-colorspace = "rgb";
+		adi,input-clock = "1x";
+		adi,input-style = <1>;
+		adi,input-justification = "evenly";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7513_0_in: endpoint {
+					remote-endpoint = <&du_out_rgb0>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7513_0_out: endpoint {
+					remote-endpoint = <&hdmi_con0>;
+				};
+			};
+		};
+	};
+
+	hdmi@39 {
+		compatible = "adi,adv7513";
+		reg = <0x39>;
+
+		adi,input-depth = <8>;
+		adi,input-colorspace = "rgb";
+		adi,input-clock = "1x";
+		adi,input-style = <1>;
+		adi,input-justification = "evenly";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7513_1_in: endpoint {
+					remote-endpoint = <&du_out_rgb1>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				adv7513_1_out: endpoint {
+					remote-endpoint = <&hdmi_con1>;
+				};
+			};
+		};
+	};
+};
+
+&du {
+	pinctrl-0 = <&du0_pins &du1_pins>;
+	pinctrl-names = "default";
+
+	clocks = <&mstp7_clks R8A7792_CLK_DU0>, <&mstp7_clks R8A7792_CLK_DU1>,
+		 <&osc2_clk>;
+	clock-names = "du.0", "du.1", "dclkin.0";
+	status = "okay";
+
+	ports {
+		port@0 {
+			endpoint {
+				remote-endpoint = <&adv7513_0_in>;
+			};
+		};
+		port@1 {
+			endpoint {
+				remote-endpoint = <&adv7513_1_in>;
+			};
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7793.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7793.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7793.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7793.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -666,7 +666,7 @@
 	scifb0: serial@e6c20000 {
 		compatible = "renesas,scifb-r8a7793",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c20000 0 64>;
+		reg = <0 0xe6c20000 0 0x100>;
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB0>;
 		clock-names = "fck";
@@ -680,7 +680,7 @@
 	scifb1: serial@e6c30000 {
 		compatible = "renesas,scifb-r8a7793",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c30000 0 64>;
+		reg = <0 0xe6c30000 0 0x100>;
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB1>;
 		clock-names = "fck";
@@ -694,7 +694,7 @@
 	scifb2: serial@e6ce0000 {
 		compatible = "renesas,scifb-r8a7793",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6ce0000 0 64>;
+		reg = <0 0xe6ce0000 0 0x100>;
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7793_CLK_SCIFB2>;
 		clock-names = "fck";
@@ -852,6 +852,33 @@
 		status = "disabled";
 	};
 
+	vin0: video@e6ef0000 {
+		compatible = "renesas,vin-r8a7793", "renesas,rcar-gen2-vin";
+		reg = <0 0xe6ef0000 0 0x1000>;
+		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7793_CLK_VIN0>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	vin1: video@e6ef1000 {
+		compatible = "renesas,vin-r8a7793", "renesas,rcar-gen2-vin";
+		reg = <0 0xe6ef1000 0 0x1000>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7793_CLK_VIN1>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
+	vin2: video@e6ef2000 {
+		compatible = "renesas,vin-r8a7793", "renesas,rcar-gen2-vin";
+		reg = <0 0xe6ef2000 0 0x1000>;
+		interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&mstp8_clks R8A7793_CLK_VIN2>;
+		power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+		status = "disabled";
+	};
+
 	qspi: spi@e6b10000 {
 		compatible = "renesas,qspi-r8a7793", "renesas,qspi";
 		reg = <0 0xe6b10000 0 0x2c>;
@@ -1279,6 +1306,16 @@
 		};
 	};
 
+	rst: reset-controller@e6160000 {
+		compatible = "renesas,r8a7793-rst";
+		reg = <0 0xe6160000 0 0x0100>;
+	};
+
+	prr: chipid@ff000044 {
+		compatible = "renesas,prr";
+		reg = <0 0xff000044 0 4>;
+	};
+
 	sysc: system-controller@e6180000 {
 		compatible = "renesas,r8a7793-sysc";
 		reg = <0 0xe6180000 0 0x0200>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7793-gose.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7793-gose.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7793-gose.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7793-gose.dts	2017-02-12 16:03:20.000000000 -0500
@@ -346,18 +346,18 @@
 	};
 
 	sdhi0_pins: sd0 {
-		renesas,groups = "sdhi0_data4", "sdhi0_ctrl";
-		renesas,function = "sdhi0";
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
 	};
 
 	sdhi1_pins: sd1 {
-		renesas,groups = "sdhi1_data4", "sdhi1_ctrl";
-		renesas,function = "sdhi1";
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
 	};
 
 	sdhi2_pins: sd2 {
-		renesas,groups = "sdhi2_data4", "sdhi2_ctrl";
-		renesas,function = "sdhi2";
+		groups = "sdhi2_data4", "sdhi2_ctrl";
+		function = "sdhi2";
 	};
 
 	qspi_pins: qspi {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7794-alt.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7794-alt.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7794-alt.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7794-alt.dts	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@
 
 	aliases {
 		serial0 = &scif2;
+		i2c10 = &gpioi2c4;
+		i2c12 = &i2cexio4;
 	};
 
 	chosen {
@@ -135,6 +137,29 @@
 		#clock-cells = <0>;
 		clock-frequency = <148500000>;
 	};
+
+	gpioi2c4: i2c-10 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "i2c-gpio";
+		status = "disabled";
+		gpios = <&gpio4 9 GPIO_ACTIVE_HIGH /* sda */
+			 &gpio4 8 GPIO_ACTIVE_HIGH /* scl */
+			>;
+		i2c-gpio,delay-us = <5>;
+	};
+
+	/*
+	 * I2C4 is routed to EXIO connector B, pins 73 (SCL) + 74 (SDA).
+	 * A fallback to GPIO is provided.
+	 */
+	i2cexio4: i2c-14 {
+		compatible = "i2c-demux-pinctrl";
+		i2c-parent = <&i2c4>, <&gpioi2c4>;
+		i2c-bus-name = "i2c-exio4";
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
 };
 
 &du {
@@ -165,8 +190,8 @@
 	pinctrl-names = "default";
 
 	du_pins: du {
-		groups = "du1_rgb666", "du1_sync", "du1_disp", "du1_dotclkout0";
-		function = "du";
+		groups = "du1_rgb666", "du1_sync", "du1_disp", "du1_clk0_out";
+		function = "du1";
 	};
 
 	scif2_pins: scif2 {
@@ -194,6 +219,11 @@
 		function = "i2c1";
 	};
 
+	i2c4_pins: i2c4 {
+		groups = "i2c4";
+		function = "i2c4";
+	};
+
 	vin0_pins: vin0 {
 		groups = "vin0_data8", "vin0_clk";
 		function = "vin0";
@@ -207,11 +237,25 @@
 	sdhi0_pins: sd0 {
 		groups = "sdhi0_data4", "sdhi0_ctrl";
 		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
 	};
 
 	sdhi1_pins: sd1 {
 		groups = "sdhi1_data4", "sdhi1_ctrl";
 		function = "sdhi1";
+		power-source = <3300>;
+	};
+
+	sdhi1_pins_uhs: sd1_uhs {
+		groups = "sdhi1_data4", "sdhi1_ctrl";
+		function = "sdhi1";
+		power-source = <1800>;
 	};
 };
 
@@ -255,23 +299,28 @@
 
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi0>;
 	vqmmc-supply = <&vccq_sdhi0>;
 	cd-gpios = <&gpio6 6 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	status = "okay";
 };
 
 &sdhi1 {
 	pinctrl-0 = <&sdhi1_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi1_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi1>;
 	vqmmc-supply = <&vccq_sdhi1>;
 	cd-gpios = <&gpio6 14 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+	sd-uhs-sdr50;
 	status = "okay";
 };
 
@@ -296,6 +345,11 @@
 	};
 };
 
+&i2c4 {
+	pinctrl-0 = <&i2c4_pins>;
+	pinctrl-names = "i2c-exio4";
+};
+
 &vin0 {
 	status = "okay";
 	pinctrl-0 = <&vin0_pins>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7794.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7794.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/r8a7794.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/r8a7794.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -319,7 +319,7 @@
 				  "ch12";
 		clocks = <&mstp5_clks R8A7794_CLK_AUDIO_DMAC0>;
 		clock-names = "fck";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		#dma-cells = <1>;
 		dma-channels = <13>;
 	};
@@ -411,7 +411,7 @@
 	scifb0: serial@e6c20000 {
 		compatible = "renesas,scifb-r8a7794",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c20000 0 64>;
+		reg = <0 0xe6c20000 0 0x100>;
 		interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB0>;
 		clock-names = "fck";
@@ -425,7 +425,7 @@
 	scifb1: serial@e6c30000 {
 		compatible = "renesas,scifb-r8a7794",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6c30000 0 64>;
+		reg = <0 0xe6c30000 0 0x100>;
 		interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB1>;
 		clock-names = "fck";
@@ -439,7 +439,7 @@
 	scifb2: serial@e6ce0000 {
 		compatible = "renesas,scifb-r8a7794",
 			     "renesas,rcar-gen2-scifb", "renesas,scifb";
-		reg = <0 0xe6ce0000 0 64>;
+		reg = <0 0xe6ce0000 0 0x100>;
 		interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp2_clks R8A7794_CLK_SCIFB2>;
 		clock-names = "fck";
@@ -731,6 +731,7 @@
 		dmas = <&dmac0 0xcd>, <&dmac0 0xce>,
 		       <&dmac1 0xcd>, <&dmac1 0xce>;
 		dma-names = "tx", "rx", "tx", "rx";
+		max-frequency = <195000000>;
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -743,6 +744,7 @@
 		dmas = <&dmac0 0xc1>, <&dmac0 0xc2>,
 		       <&dmac1 0xc1>, <&dmac1 0xc2>;
 		dma-names = "tx", "rx", "tx", "rx";
+		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -755,6 +757,7 @@
 		dmas = <&dmac0 0xd3>, <&dmac0 0xd4>,
 		       <&dmac1 0xd3>, <&dmac1 0xd4>;
 		dma-names = "tx", "rx", "tx", "rx";
+		max-frequency = <97500000>;
 		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 		status = "disabled";
 	};
@@ -1025,8 +1028,7 @@
 			clocks = <&extal_clk &usb_extal_clk>;
 			#clock-cells = <1>;
 			clock-output-names = "main", "pll0", "pll1", "pll3",
-					     "lb", "qspi", "sdh", "sd0", "z",
-					     "rcan";
+					     "lb", "qspi", "sdh", "sd0", "rcan";
 			#power-domain-cells = <0>;
 		};
 		/* Variable factor clocks */
@@ -1260,7 +1262,7 @@
 		mstp7_clks: mstp7_clks@e615014c {
 			compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0 0xe615014c 0 4>, <0 0xe61501c4 0 4>;
-			clocks = <&mp_clk>, <&mp_clk>,
+			clocks = <&mp_clk>, <&hp_clk>,
 				 <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
 				 <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
 				 <&zx_clk>;
@@ -1375,6 +1377,16 @@
 		};
 	};
 
+	rst: reset-controller@e6160000 {
+		compatible = "renesas,r8a7794-rst";
+		reg = <0 0xe6160000 0 0x0100>;
+	};
+
+	prr: chipid@ff000044 {
+		compatible = "renesas,prr";
+		reg = <0 0xff000044 0 4>;
+	};
+
 	sysc: system-controller@e6180000 {
 		compatible = "renesas,r8a7794-sysc";
 		reg = <0 0xe6180000 0 0x0200>;
@@ -1483,67 +1495,67 @@
 			      "mix.0", "mix.1",
 			      "dvc.0", "dvc.1",
 			      "clk_a", "clk_b", "clk_c", "clk_i";
-		power-domains = <&cpg_clocks>;
+		power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
 
 		status = "disabled";
 
 		rcar_sound,dvc {
-			dvc0: dvc@0 {
+			dvc0: dvc-0 {
 				dmas = <&audma0 0xbc>;
 				dma-names = "tx";
 			};
-			dvc1: dvc@1 {
+			dvc1: dvc-1 {
 				dmas = <&audma0 0xbe>;
 				dma-names = "tx";
 			};
 		};
 
 		rcar_sound,mix {
-			mix0: mix@0 { };
-			mix1: mix@1 { };
+			mix0: mix-0 { };
+			mix1: mix-1 { };
 		};
 
 		rcar_sound,ctu {
-			ctu00: ctu@0 { };
-			ctu01: ctu@1 { };
-			ctu02: ctu@2 { };
-			ctu03: ctu@3 { };
-			ctu10: ctu@4 { };
-			ctu11: ctu@5 { };
-			ctu12: ctu@6 { };
-			ctu13: ctu@7 { };
+			ctu00: ctu-0 { };
+			ctu01: ctu-1 { };
+			ctu02: ctu-2 { };
+			ctu03: ctu-3 { };
+			ctu10: ctu-4 { };
+			ctu11: ctu-5 { };
+			ctu12: ctu-6 { };
+			ctu13: ctu-7 { };
 		};
 
 		rcar_sound,src {
-			src@0 {
+			src-0 {
 				status = "disabled";
 			};
-			src1: src@1 {
+			src1: src-1 {
 				interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x87>, <&audma0 0x9c>;
 				dma-names = "rx", "tx";
 			};
-			src2: src@2 {
+			src2: src-2 {
 				interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x89>, <&audma0 0x9e>;
 				dma-names = "rx", "tx";
 			};
-			src3: src@3 {
+			src3: src-3 {
 				interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x8b>, <&audma0 0xa0>;
 				dma-names = "rx", "tx";
 			};
-			src4: src@4 {
+			src4: src-4 {
 				interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x8d>, <&audma0 0xb0>;
 				dma-names = "rx", "tx";
 			};
-			src5: src@5 {
+			src5: src-5 {
 				interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x8f>, <&audma0 0xb2>;
 				dma-names = "rx", "tx";
 			};
-			src6: src@6 {
+			src6: src-6 {
 				interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x91>, <&audma0 0xb4>;
 				dma-names = "rx", "tx";
@@ -1551,61 +1563,61 @@
 		};
 
 		rcar_sound,ssi {
-			ssi0: ssi@0 {
+			ssi0: ssi-0 {
 				interrupts = <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x01>, <&audma0 0x02>,
 				       <&audma0 0x15>, <&audma0 0x16>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi1: ssi@1 {
+			ssi1: ssi-1 {
 				interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x03>, <&audma0 0x04>,
 				       <&audma0 0x49>, <&audma0 0x4a>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi2: ssi@2 {
+			ssi2: ssi-2 {
 				interrupts = <GIC_SPI 372 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x05>, <&audma0 0x06>,
 				       <&audma0 0x63>, <&audma0 0x64>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi3: ssi@3 {
+			ssi3: ssi-3 {
 				interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x07>, <&audma0 0x08>,
 				       <&audma0 0x6f>, <&audma0 0x70>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi4: ssi@4 {
+			ssi4: ssi-4 {
 				interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x09>, <&audma0 0x0a>,
 				       <&audma0 0x71>, <&audma0 0x72>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi5: ssi@5 {
+			ssi5: ssi-5 {
 				interrupts = <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x0b>, <&audma0 0x0c>,
 				       <&audma0 0x73>, <&audma0 0x74>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi6: ssi@6 {
+			ssi6: ssi-6 {
 				interrupts = <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x0d>, <&audma0 0x0e>,
 				       <&audma0 0x75>, <&audma0 0x76>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi7: ssi@7 {
+			ssi7: ssi-7 {
 				interrupts = <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x0f>, <&audma0 0x10>,
 				       <&audma0 0x79>, <&audma0 0x7a>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi8: ssi@8 {
+			ssi8: ssi-8 {
 				interrupts = <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x11>, <&audma0 0x12>,
 				       <&audma0 0x7b>, <&audma0 0x7c>;
 				dma-names = "rx", "tx", "rxu", "txu";
 			};
-			ssi9: ssi@9 {
+			ssi9: ssi-9 {
 				interrupts = <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
 				dmas = <&audma0 0x13>, <&audma0 0x14>,
 				       <&audma0 0x7d>, <&audma0 0x7e>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk1108.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk1108.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk1108.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk1108.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,452 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/rk1108-cru.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+/ {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	compatible = "rockchip,rk1108";
+
+	interrupt-parent = <&gic>;
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@f00 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0xf00>;
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a7-pmu";
+		interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+		clock-frequency = <24000000>;
+	};
+
+	xin24m: oscillator {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xin24m";
+		#clock-cells = <0>;
+	};
+
+	amba {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		pdma: pdma@102a0000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0x102a0000 0x4000>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			arm,pl330-broken-no-flushp;
+			clocks = <&cru ACLK_DMAC>;
+			clock-names = "apb_pclk";
+		};
+	};
+
+	bus_intmem@10080000 {
+		compatible = "mmio-sram";
+		reg = <0x10080000 0x2000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x10080000 0x2000>;
+	};
+
+	uart2: serial@10210000 {
+		compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+		reg = <0x10210000 0x100>;
+		interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart2m0_xfer>;
+		status = "disabled";
+	};
+
+	uart1: serial@10220000 {
+		compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+		reg = <0x10220000 0x100>;
+		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart1_xfer>;
+		status = "disabled";
+	};
+
+	uart0: serial@10230000 {
+		compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+		reg = <0x10230000 0x100>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clock-frequency = <24000000>;
+		clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+		clock-names = "baudclk", "apb_pclk";
+		pinctrl-names = "default";
+		pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+		status = "disabled";
+	};
+
+	grf: syscon@10300000 {
+		compatible = "rockchip,rk1108-grf", "syscon";
+		reg = <0x10300000 0x1000>;
+	};
+
+	pmugrf: syscon@20060000 {
+		compatible = "rockchip,rk1108-pmugrf", "syscon";
+		reg = <0x20060000 0x1000>;
+	};
+
+	cru: clock-controller@20200000 {
+		compatible = "rockchip,rk1108-cru";
+		reg = <0x20200000 0x1000>;
+		rockchip,grf = <&grf>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+	emmc: dwmmc@30110000 {
+		compatible = "rockchip,rk1108-dw-mshc", "rockchip,rk3288-dw-mshc";
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
+			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+		reg = <0x30110000 0x4000>;
+		status = "disabled";
+	};
+
+	sdio: dwmmc@30120000 {
+		compatible = "rockchip,rk1108-dw-mshc", "rockchip,rk3288-dw-mshc";
+		clock-freq-min-max = <400000 150000000>;
+		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
+			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+		reg = <0x30120000 0x4000>;
+		status = "disabled";
+	};
+
+	sdmmc: dwmmc@30130000 {
+		compatible = "rockchip,rk1108-dw-mshc", "rockchip,rk3288-dw-mshc";
+		clock-freq-min-max = <400000 100000000>;
+		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
+		fifo-depth = <0x100>;
+		interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		reg = <0x30130000 0x4000>;
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@32010000 {
+		compatible = "arm,gic-400";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		#address-cells = <0>;
+
+		reg = <0x32011000 0x1000>,
+		      <0x32012000 0x1000>,
+		      <0x32014000 0x2000>,
+		      <0x32016000 0x2000>;
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	pinctrl: pinctrl {
+		compatible = "rockchip,rk1108-pinctrl";
+		rockchip,grf = <&grf>;
+		rockchip,pmu = <&pmugrf>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		gpio0: gpio0@20030000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x20030000 0x100>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&xin24m>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio1@10310000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x10310000 0x100>;
+			interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&xin24m>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio2@10320000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x10320000 0x100>;
+			interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&xin24m>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio3@10330000 {
+			compatible = "rockchip,gpio-bank";
+			reg = <0x10330000 0x100>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&xin24m>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		pcfg_pull_up: pcfg-pull-up {
+			bias-pull-up;
+		};
+
+		pcfg_pull_down: pcfg-pull-down {
+			bias-pull-down;
+		};
+
+		pcfg_pull_none: pcfg-pull-none {
+			bias-disable;
+		};
+
+		pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_none_drv_12ma: pcfg-pull-none-drv-12ma {
+			drive-strength = <12>;
+		};
+
+		pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
+			bias-pull-up;
+			drive-strength = <8>;
+		};
+
+		pcfg_pull_none_drv_4ma: pcfg-pull-none-drv-4ma {
+			drive-strength = <4>;
+		};
+
+		pcfg_pull_up_drv_4ma: pcfg-pull-up-drv-4ma {
+			bias-pull-up;
+			drive-strength = <4>;
+		};
+
+		pcfg_output_high: pcfg-output-high {
+			output-high;
+		};
+
+		pcfg_output_low: pcfg-output-low {
+			output-low;
+		};
+
+		pcfg_input_high: pcfg-input-high {
+			bias-pull-up;
+			input-enable;
+		};
+
+		i2c1 {
+			i2c1_xfer: i2c1-xfer {
+				rockchip,pins = <2 RK_PD3 RK_FUNC_1 &pcfg_pull_up>,
+						<2 RK_PD4 RK_FUNC_1 &pcfg_pull_up>;
+			};
+		};
+
+		i2c2m1 {
+			i2c2m1_xfer: i2c2m1-xfer {
+				rockchip,pins = <0 RK_PC2 RK_FUNC_2 &pcfg_pull_none>,
+						<0 RK_PC6 RK_FUNC_3 &pcfg_pull_none>;
+			};
+
+			i2c2m1_gpio: i2c2m1-gpio {
+				rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>,
+						<0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+		};
+
+		i2c2m05v {
+			i2c2m05v_xfer: i2c2m05v-xfer {
+				rockchip,pins = <1 RK_PD5 RK_FUNC_2 &pcfg_pull_none>,
+						<1 RK_PD4 RK_FUNC_2 &pcfg_pull_none>;
+			};
+
+			i2c2m05v_gpio: i2c2m05v-gpio {
+				rockchip,pins = <1 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>,
+						<1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+		};
+
+		i2c3 {
+			i2c3_xfer: i2c3-xfer {
+				rockchip,pins = <0 RK_PB6 RK_FUNC_1 &pcfg_pull_none>,
+						<0 RK_PC4 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		sdmmc {
+			sdmmc_clk: sdmmc-clk {
+				rockchip,pins = <3 RK_PC4 RK_FUNC_1 &pcfg_pull_none_drv_4ma>;
+			};
+
+			sdmmc_cmd: sdmmc-cmd {
+				rockchip,pins = <3 RK_PC5 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+			};
+
+			sdmmc_cd: sdmmc-cd {
+				rockchip,pins = <0 RK_PA1 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+			};
+
+			sdmmc_bus1: sdmmc-bus1 {
+				rockchip,pins = <3 RK_PC3 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+			};
+
+			sdmmc_bus4: sdmmc-bus4 {
+				rockchip,pins = <3 RK_PC3 RK_FUNC_1 &pcfg_pull_up_drv_4ma>,
+						<3 RK_PC2 RK_FUNC_1 &pcfg_pull_up_drv_4ma>,
+						<3 RK_PC1 RK_FUNC_1 &pcfg_pull_up_drv_4ma>,
+						<3 RK_PC0 RK_FUNC_1 &pcfg_pull_up_drv_4ma>;
+			};
+		};
+
+		uart0 {
+			uart0_xfer: uart0-xfer {
+				rockchip,pins = <3 RK_PA6 RK_FUNC_1 &pcfg_pull_up>,
+						<3 RK_PA5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_cts: uart0-cts {
+				rockchip,pins = <3 RK_PA4 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts: uart0-rts {
+				rockchip,pins = <3 RK_PA3 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart0_rts_gpio: uart0-rts-gpio {
+				rockchip,pins = <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+		};
+
+		uart1 {
+			uart1_xfer: uart1-xfer {
+				rockchip,pins = <1 RK_PD3 RK_FUNC_1 &pcfg_pull_up>,
+						<1 RK_PD2 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart1_cts: uart1-cts {
+				rockchip,pins = <1 RK_PD0 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart1_rts: uart1-rts {
+				rockchip,pins = <1 RK_PD1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart2m0 {
+			uart2m0_xfer: uart2m0-xfer {
+				rockchip,pins = <2 RK_PD2 RK_FUNC_1 &pcfg_pull_up>,
+						<2 RK_PD1 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+
+		uart2m1 {
+			uart2m1_xfer: uart2m1-xfer {
+				rockchip,pins = <3 RK_PC3 RK_FUNC_2 &pcfg_pull_up>,
+						<3 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
+			};
+		};
+
+		uart2_5v {
+			uart2_5v_cts: uart2_5v-cts {
+				rockchip,pins = <1 RK_PD4 RK_FUNC_1 &pcfg_pull_none>;
+			};
+
+			uart2_5v_rts: uart2_5v-rts {
+				rockchip,pins = <1 RK_PD5 RK_FUNC_1 &pcfg_pull_none>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk1108-evb.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk1108-evb.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk1108-evb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk1108-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+/*
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *  Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "rk1108.dtsi"
+
+/ {
+	model = "Rockchip RK1108 Evaluation board";
+	compatible = "rockchip,rk1108-evb", "rockchip,rk1108";
+
+	memory@60000000 {
+		device_type = "memory";
+		reg = <0x60000000 0x08000000>;
+	};
+
+	chosen {
+		stdout-path = "serial2:1500000n8";
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3036.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3036.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3036.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3036.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -44,9 +44,11 @@
 #include <dt-bindings/pinctrl/rockchip.h>
 #include <dt-bindings/clock/rk3036-cru.h>
 #include <dt-bindings/soc/rockchip,boot-mode.h>
-#include "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	compatible = "rockchip,rk3036";
 
 	interrupt-parent = <&gic>;
@@ -204,7 +206,6 @@
 		g-np-tx-fifo-size = <16>;
 		g-rx-fifo-size = <275>;
 		g-tx-fifo-size = <256 128 128 64 64 32>;
-		g-use-dma;
 		status = "disabled";
 	};
 
@@ -244,7 +245,7 @@
 		compatible = "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x10214000 0x4000>;
 		clock-frequency = <37500000>;
-		clock-freq-min-max = <400000 37500000>;
+		max-frequency = <37500000>;
 		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
 		clock-names = "biu", "ciu";
 		fifo-depth = <0x100>;
@@ -255,7 +256,7 @@
 	sdio: dwmmc@10218000 {
 		compatible = "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x10218000 0x4000>;
-		clock-freq-min-max = <400000 37500000>;
+		max-frequency = <37500000>;
 		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
 			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
@@ -271,7 +272,7 @@
 		bus-width = <8>;
 		cap-mmc-highspeed;
 		clock-frequency = <37500000>;
-		clock-freq-min-max = <400000 37500000>;
+		max-frequency = <37500000>;
 		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
 			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3036-evb.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3036-evb.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3036-evb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3036-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 	model = "Rockchip RK3036 Evaluation board";
 	compatible = "rockchip,rk3036-evb", "rockchip,rk3036";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3036-kylin.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3036-kylin.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3036-kylin.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3036-kylin.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 	model = "Rockchip RK3036 KylinBoard";
 	compatible = "rockchip,rk3036-kylin", "rockchip,rk3036";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x20000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-bqcurie2.dts	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,7 @@
 	model = "bq Curie 2";
 	compatible = "mundoreader,bq-curie2", "rockchip,rk3066a";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -151,6 +151,14 @@
 
 		#clock-cells = <1>;
 		#reset-cells = <1>;
+		assigned-clocks = <&cru PLL_CPLL>, <&cru PLL_GPLL>,
+				  <&cru ACLK_CPU>, <&cru HCLK_CPU>,
+				  <&cru PCLK_CPU>, <&cru ACLK_PERI>,
+				  <&cru HCLK_PERI>, <&cru PCLK_PERI>;
+		assigned-clock-rates = <400000000>, <594000000>,
+				       <300000000>, <150000000>,
+				       <75000000>, <300000000>,
+				       <150000000>, <75000000>;
 	};
 
 	timer@2000e000 {
@@ -162,7 +170,7 @@
 	};
 
 	efuse: efuse@20010000 {
-		compatible = "rockchip,rockchip-efuse";
+		compatible = "rockchip,rk3066a-efuse";
 		reg = <0x20010000 0x4000>;
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -197,7 +205,7 @@
 		clock-names = "saradc", "apb_pclk";
 		interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
 		#io-channel-cells = <1>;
-		resets = <&cru SRST_SARADC>;
+		resets = <&cru SRST_TSADC>;
 		reset-names = "saradc-apb";
 		status = "disabled";
 	};
@@ -628,15 +636,26 @@
 };
 
 &mmc0 {
+	clock-frequency = <50000000>;
+	dmas = <&dmac2 1>;
+	dma-names = "rx-tx";
+	max-frequency = <50000000>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_bus4>;
 };
 
 &mmc1 {
+	dmas = <&dmac2 3>;
+	dma-names = "rx-tx";
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_cd &sd1_bus4>;
 };
 
+&emmc {
+	dmas = <&dmac2 4>;
+	dma-names = "rx-tx";
+};
+
 &pwm0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pwm0_out>;
@@ -668,21 +687,29 @@
 };
 
 &uart0 {
+	dmas = <&dmac1_s 0>, <&dmac1_s 1>;
+	dma-names = "tx", "rx";
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_xfer>;
 };
 
 &uart1 {
+	dmas = <&dmac1_s 2>, <&dmac1_s 3>;
+	dma-names = "tx", "rx";
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart1_xfer>;
 };
 
 &uart2 {
+	dmas = <&dmac2 6>, <&dmac2 7>;
+	dma-names = "tx", "rx";
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart2_xfer>;
 };
 
 &uart3 {
+	dmas = <&dmac2 8>, <&dmac2 9>;
+	dma-names = "tx", "rx";
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart3_xfer>;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-marsboard.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-marsboard.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-marsboard.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-marsboard.dts	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@
 	model = "MarsBoard RK3066";
 	compatible = "haoyu,marsboard-rk3066", "rockchip,rk3066a";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-mk808.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-mk808.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-mk808.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-mk808.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2016 Paweł Jarosz <paweljarosz3691@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+#include "rk3066a.dtsi"
+
+/ {
+	model = "Rikomagic MK808";
+	compatible = "rikomagic,mk808", "rockchip,rk3066a";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory@60000000 {
+		reg = <0x60000000 0x40000000>;
+		device_type = "memory";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		blue {
+			label = "mk808:blue:power";
+			gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "default-on";
+		};
+	};
+
+	vcc_io: vcc-io {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_io";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_host: usb-host-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&host_drv>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-name = "host-pwr";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_otg: usb-otg-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&otg_drv>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-name = "vcc_otg";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_sd: sdmmc-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio3 7 GPIO_ACTIVE_LOW>;
+		pinctrl-0 = <&sdmmc_pwr>;
+		pinctrl-names = "default";
+		regulator-name = "vcc_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_wifi: sdio-regulator {
+		compatible = "regulator-fixed";
+		enable-active-high;
+		gpio = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&wifi_pwr>;
+		pinctrl-names = "default";
+		regulator-name = "vcc_wifi";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+};
+
+&mmc0 {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	num-slots = <1>;
+	vmmc-supply = <&vcc_sd>;
+	status = "okay";
+};
+
+&mmc1 {
+	bus-width = <4>;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
+	pinctrl-names = "default";
+	vmmc-supply = <&vcc_wifi>;
+	status = "okay";
+};
+
+&pinctrl {
+	usb-host {
+		host_drv: host-drv {
+			rockchip,pins = <RK_GPIO0 6 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	usb-otg {
+		otg_drv: otg-drv {
+			rockchip,pins = <RK_GPIO0 5 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <RK_GPIO3 7 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	sdio {
+		wifi_pwr: wifi-pwr {
+			rockchip,pins = <RK_GPIO3 24 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3066a-rayeager.dts	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 	model = "Rayeager PX2";
 	compatible = "chipspark,rayeager-px2", "rockchip,rk3066a";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3188.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3188.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3188.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3188.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -147,7 +147,7 @@
 	};
 
 	efuse: efuse@20010000 {
-		compatible = "rockchip,rockchip-efuse";
+		compatible = "rockchip,rk3188-efuse";
 		reg = <0x20010000 0x4000>;
 		#address-cells = <1>;
 		#size-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3188-px3-evb.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3188-px3-evb.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3188-px3-evb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3188-px3-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2016 Andy Yan <andy.yan@rock-chips.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "rk3188.dtsi"
+
+/ {
+	model = "Rockchip PX3-EVB";
+	compatible = "rockchip,px3-evb", "rockchip,px3", "rockchip,rk3188";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory@60000000 {
+		reg = <0x60000000 0x80000000>;
+		device_type = "memory";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		power {
+			gpios = <&gpio0 4 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			label = "GPIO Key Power";
+			linux,input-type = <1>;
+			wakeup-source;
+			debounce-interval = <100>;
+		};
+	};
+
+	vcc_sys: vsys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-boot-on;
+	};
+};
+
+&cpu0 {
+	cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	disable-wp;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_rst>;
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	accelerometer@18 {
+		compatible = "bosch,bma250";
+		reg = <0x18>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	rk808: pmic@1c {
+		compatible = "rockchip,rk818";
+		reg = <0x1c>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+		rockchip,system-power-controller;
+		wakeup-source;
+		#clock-cells = <1>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_io>;
+		vcc9-supply = <&vcc_io>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-name = "vdd_arm";
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			vdd_gpu: DCDC_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <1250000>;
+				regulator-name = "vdd_gpu";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_ddr";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+				};
+			};
+
+			vcc_io: DCDC_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_io";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			vcc_cif: LDO_REG1 {
+				 regulator-min-microvolt = <3300000>;
+				 regulator-max-microvolt = <3300000>;
+				 regulator-name = "vcc_cif";
+			};
+
+			vcc_jetta33: LDO_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_jetta33";
+			};
+
+			vdd_10: LDO_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd_10";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <1000000>;
+				};
+			};
+
+			lvds_12: LDO_REG4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "lvds_12";
+			};
+
+			lvds_25: LDO_REG5 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "lvds_25";
+			};
+
+			cif_18: LDO_REG6 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "cif_18";
+			};
+
+			vcc_sd: LDO_REG7 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_sd";
+				regulator-state-mem {
+					regulator-on-in-suspend;
+					regulator-suspend-microvolt = <3300000>;
+				};
+			};
+
+			wl_18: LDO_REG8 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "wl_18";
+			};
+
+			lcd_33: SWITCH_REG1 {
+				regulator-name = "lcd_33";
+			};
+		};
+	};
+
+};
+
+&i2c2 {
+	gsl1680: touchscreen@40 {
+		compatible = "silead,gsl1680";
+		reg = <0x40>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
+		power-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+		touchscreen-size-x = <800>;
+		touchscreen-size-y = <1280>;
+		silead,max-fingers = <5>;
+	};
+};
+
+&mmc0 {
+	num-slots = <1>;
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
+	vmmc-supply = <&vcc_sd>;
+
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	disable-wp;
+};
+
+&pinctrl {
+	pcfg_output_low: pcfg-output-low {
+		output-low;
+	};
+
+	usb {
+		host_vbus_drv: host-vbus-drv {
+			rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+		otg_vbus_drv: otg-vbus-drv {
+			rockchip,pins = <2 31 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&pwm1 {
+	status = "okay";
+};
+
+&pwm2 {
+	status = "okay";
+};
+
+&pwm3 {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&uart3 {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&usb_host {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3188-radxarock.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3188-radxarock.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3188-radxarock.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3188-radxarock.dts	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 	model = "Radxa Rock";
 	compatible = "radxa,rock", "rockchip,rk3188";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3228-evb.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3228-evb.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3228-evb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3228-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 	model = "Rockchip RK3228 Evaluation board";
 	compatible = "rockchip,rk3228-evb", "rockchip,rk3228";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3229-evb.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3229-evb.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3229-evb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3229-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 	model = "Rockchip RK3229 Evaluation board";
 	compatible = "rockchip,rk3229-evb", "rockchip,rk3229";
 
-	memory {
+	memory@60000000 {
 		device_type = "memory";
 		reg = <0x60000000 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk322x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk322x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk322x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk322x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -44,9 +44,11 @@
 #include <dt-bindings/pinctrl/rockchip.h>
 #include <dt-bindings/clock/rk3228-cru.h>
 #include <dt-bindings/thermal/thermal.h>
-#include "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	interrupt-parent = <&gic>;
 
 	aliases {
@@ -402,7 +404,7 @@
 		reg = <0x30020000 0x4000>;
 		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
 		clock-frequency = <37500000>;
-		clock-freq-min-max = <400000 37500000>;
+		max-frequency = <37500000>;
 		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
 			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -46,9 +46,11 @@
 #include <dt-bindings/thermal/thermal.h>
 #include <dt-bindings/power/rk3288-power.h>
 #include <dt-bindings/soc/rockchip,boot-mode.h>
-#include "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	compatible = "rockchip,rk3288";
 
 	interrupt-parent = <&gic>;
@@ -227,7 +229,7 @@
 
 	sdmmc: dwmmc@ff0c0000 {
 		compatible = "rockchip,rk3288-dw-mshc";
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
 			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -239,7 +241,7 @@
 
 	sdio0: dwmmc@ff0d0000 {
 		compatible = "rockchip,rk3288-dw-mshc";
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
 			 <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -251,7 +253,7 @@
 
 	sdio1: dwmmc@ff0e0000 {
 		compatible = "rockchip,rk3288-dw-mshc";
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDIO1>, <&cru SCLK_SDIO1>,
 			 <&cru SCLK_SDIO1_DRV>, <&cru SCLK_SDIO1_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -263,7 +265,7 @@
 
 	emmc: dwmmc@ff0f0000 {
 		compatible = "rockchip,rk3288-dw-mshc";
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
 			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -596,7 +598,6 @@
 		g-np-tx-fifo-size = <16>;
 		g-rx-fifo-size = <275>;
 		g-tx-fifo-size = <256 128 128 64 64 32>;
-		g-use-dma;
 		phys = <&usbphy0>;
 		phy-names = "usb2-phy";
 		status = "disabled";
@@ -1116,7 +1117,7 @@
 	};
 
 	efuse: efuse@ffb40000 {
-		compatible = "rockchip,rockchip-efuse";
+		compatible = "rockchip,rk3288-efuse";
 		reg = <0xffb40000 0x20>;
 		#address-cells = <1>;
 		#size-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-evb.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-evb.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-evb.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-evb.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
 #include "rk3288.dtsi"
 
 / {
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-fennec.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-fennec.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-fennec.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-fennec.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 	model = "Rockchip RK3288 Fennec Board";
 	compatible = "rockchip,rk3288-fennec", "rockchip,rk3288";
 
-	memory {
+	memory@0 {
 		reg = <0x0 0x80000000>;
 		device_type = "memory";
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-firefly.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 #include "rk3288.dtsi"
 
 / {
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-firefly-reload-core.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-firefly-reload-core.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-firefly-reload-core.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-firefly-reload-core.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
 #include "rk3288.dtsi"
 
 / {
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-miqi.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-miqi.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-miqi.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-miqi.dts	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@
 		stdout-path = "serial2:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-popmetal.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-popmetal.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-popmetal.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-popmetal.dts	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 	model = "PopMetal-RK3288";
 	compatible = "chipspark,popmetal-rk3288", "rockchip,rk3288";
 
-	memory{
+	memory@0 {
 		device_type = "memory";
 		reg = <0 0x80000000>;
 	};
@@ -68,7 +68,7 @@
 		pinctrl-0 = <&pwrbtn>;
 
 		power {
-			gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+			gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
 			linux,code = <KEY_POWER>;
 			label = "GPIO Key Power";
 			linux,input-type = <1>;
@@ -79,7 +79,7 @@
 
 	ir: ir-receiver {
 		compatible = "gpio-ir-receiver";
-		gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+		gpios = <&gpio0 RK_PA6 GPIO_ACTIVE_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&ir_int>;
 	};
@@ -94,7 +94,7 @@
 
 	vcc_sd: sdmmc-regulator {
 		compatible = "regulator-fixed";
-		gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
+		gpio = <&gpio7 RK_PB3 GPIO_ACTIVE_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&sdmmc_pwr>;
 		regulator-name = "vcc_sd";
@@ -128,7 +128,7 @@
 	vcc28_dvp: vcc28-dvp-regulator {
 		compatible = "regulator-fixed";
 		enable-active-high;
-		gpio = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+		gpio = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&dvp_pwr>;
 		regulator-name = "vcc28_dvp";
@@ -147,6 +147,8 @@
 	bus-width = <8>;
 	cap-mmc-highspeed;
 	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
 	non-removable;
 	num-slots = <1>;
 	pinctrl-names = "default";
@@ -165,6 +167,10 @@
 	num-slots = <1>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
+	sd-uhs-sdr50;
+	sd-uhs-sdr104;
 	vmmc-supply = <&vcc_sd>;
 	vqmmc-supply = <&vccio_sd>;
 	status = "okay";
@@ -174,7 +180,7 @@
 	phy-supply = <&vcc_lan>;
 	phy-mode = "rgmii";
 	clock_in_out = "input";
-	snps,reset-gpio = <&gpio4 7 0>;
+	snps,reset-gpio = <&gpio4 RK_PB0 0>;
 	snps,reset-active-low;
 	snps,reset-delays-us = <0 10000 1000000>;
 	assigned-clocks = <&cru SCLK_MAC>;
@@ -280,7 +286,7 @@
 			vccio_sd: LDO_REG2 {
 				regulator-always-on;
 				regulator-boot-on;
-				regulator-min-microvolt = <3300000>;
+				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-name = "vccio_sd";
 				regulator-state-mem {
@@ -443,43 +449,43 @@
 &pinctrl {
 	ak8963 {
 		comp_int: comp-int {
-			rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_up>;
+			rockchip,pins = <8 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
 		};
 	};
 
 	buttons {
 		pwrbtn: pwrbtn {
-			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+			rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>;
 		};
 	};
 
 	dvp {
 		dvp_pwr: dvp-pwr {
-			rockchip,pins = <0 17 RK_FUNC_GPIO &pcfg_pull_none>;
+			rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
 	};
 
 	ir {
 		ir_int: ir-int {
-			rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_up>;
+			rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
 		};
 	};
 
 	mma8452 {
 		gsensor_int: gsensor-int {
-			rockchip,pins = <8 0 RK_FUNC_GPIO &pcfg_pull_up>;
+			rockchip,pins = <8 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>;
 		};
 	};
 
 	pmic {
 		pmic_int: pmic-int {
-			rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+			rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
 		};
 	};
 
 	sdmmc {
 		sdmmc_pwr: sdmmc-pwr {
-			rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+			rockchip,pins = <7 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
 		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-r89.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-r89.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-r89.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-r89.dts	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 / {
 	compatible = "netxeon,r89", "rockchip,rk3288";
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-rock2-som.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-rock2-som.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-rock2-som.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-rock2-som.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@
 #include "rk3288.dtsi"
 
 / {
-	memory {
+	memory@0 {
 		reg = <0x0 0x80000000>;
 		device_type = "memory";
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3288-veyron.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@
 #include "rk3288.dtsi"
 
 / {
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x80000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/rk3xxx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3xxx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/rk3xxx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/rk3xxx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -44,9 +44,11 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/soc/rockchip,boot-mode.h>
-#include "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
+
 	interrupt-parent = <&gic>;
 
 	aliases {
@@ -181,7 +183,6 @@
 		g-np-tx-fifo-size = <16>;
 		g-rx-fifo-size = <275>;
 		g-tx-fifo-size = <256 128 128 64 64 32>;
-		g-use-dma;
 		phys = <&usbphy0>;
 		phy-names = "usb2-phy";
 		status = "disabled";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sama5d2.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sama5d2.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sama5d2.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sama5d2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -735,6 +735,11 @@
 						atmel,clk-output-range = <0 83000000>;
 					};
 
+					securam_clk: securam_clk {
+						#clock-cells = <0>;
+						reg = <51>;
+					};
+
 					i2s0_clk: i2s0_clk {
 						#clock-cells = <0>;
 						reg = <54>;
@@ -1030,6 +1035,7 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				clocks = <&twi0_clk>;
+				atmel,fifo-size = <16>;
 				status = "disabled";
 			};
 
@@ -1058,6 +1064,15 @@
 				status = "disabled";
 			};
 
+			securam: sram@f8044000 {
+				compatible = "atmel,sama5d2-securam", "mmio-sram";
+				reg = <0xf8044000 0x1420>;
+				clocks = <&securam_clk>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0xf8044000 0x1420>;
+			};
+
 			rstc@f8048000 {
 				compatible = "atmel,sama5d3-rstc";
 				reg = <0xf8048000 0x10>;
@@ -1088,30 +1103,12 @@
 				status = "disabled";
 			};
 
-			sckc@f8048050 {
-				compatible = "atmel,at91sam9x5-sckc";
+			clk32k: sckc@f8048050 {
+				compatible = "atmel,sama5d4-sckc";
 				reg = <0xf8048050 0x4>;
 
-				slow_rc_osc: slow_rc_osc {
-					compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
-					#clock-cells = <0>;
-					clock-frequency = <32768>;
-					clock-accuracy = <250000000>;
-					atmel,startup-time-usec = <75>;
-				};
-
-				slow_osc: slow_osc {
-					compatible = "atmel,at91sam9x5-clk-slow-osc";
-					#clock-cells = <0>;
-					clocks = <&slow_xtal>;
-					atmel,startup-time-usec = <1200000>;
-				};
-
-				clk32k: slowck {
-					compatible = "atmel,at91sam9x5-clk-slow";
-					#clock-cells = <0>;
-					clocks = <&slow_rc_osc &slow_osc>;
-				};
+				clocks = <&slow_xtal>;
+				#clock-cells = <0>;
 			};
 
 			rtc@f80480b0 {
@@ -1231,6 +1228,7 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				clocks = <&twi1_clk>;
+				atmel,fifo-size = <16>;
 				status = "disabled";
 			};
 
@@ -1260,6 +1258,11 @@
 				clocks = <&pioA_clk>;
 			};
 
+			secumod@fc040000 {
+				compatible = "atmel,sama5d2-secumod", "syscon";
+				reg = <0xfc040000 0x100>;
+			};
+
 			tdes@fc044000 {
 				compatible = "atmel,at91sam9g46-tdes";
 				reg = <0xfc044000 0x100>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sama5d3.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sama5d3.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sama5d3.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sama5d3.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -549,8 +549,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOB 30 AT91_PERIPH_A AT91_PINCTRL_NONE	/* PB30 periph A */
-							 AT91_PIOB 31 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;	/* PB31 periph A with pullup */
+							<AT91_PIOB 30 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
+							 AT91_PIOB 31 AT91_PERIPH_A AT91_PINCTRL_NONE>;
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sama5d4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sama5d4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sama5d4.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sama5d4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -1314,30 +1314,11 @@
 				status = "disabled";
 			};
 
-			sckc@fc068650 {
-				compatible = "atmel,at91sam9x5-sckc";
+			clk32k: sckc@fc068650 {
+				compatible = "atmel,sama5d4-sckc";
 				reg = <0xfc068650 0x4>;
-
-				slow_rc_osc: slow_rc_osc {
-					compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
-					#clock-cells = <0>;
-					clock-frequency = <32768>;
-					clock-accuracy = <250000000>;
-					atmel,startup-time-usec = <75>;
-				};
-
-				slow_osc: slow_osc {
-					compatible = "atmel,at91sam9x5-clk-slow-osc";
-					#clock-cells = <0>;
-					clocks = <&slow_xtal>;
-					atmel,startup-time-usec = <1200000>;
-				};
-
-				clk32k: slowck {
-					compatible = "atmel,at91sam9x5-clk-slow";
-					#clock-cells = <0>;
-					clocks = <&slow_rc_osc &slow_osc>;
-				};
+				#clock-cells = <0>;
+				clocks = <&slow_xtal>;
 			};
 
 			rtc@fc0686b0 {
@@ -1461,8 +1442,8 @@
 				dbgu {
 					pinctrl_dbgu: dbgu-0 {
 						atmel,pins =
-							<AT91_PIOB 24 AT91_PERIPH_A AT91_PINCTRL_NONE>,     /* conflicts with D14 and TDI */
-							<AT91_PIOB 25 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;  /* conflicts with D15 and TDO */
+							<AT91_PIOB 24 AT91_PERIPH_A AT91_PINCTRL_PULL_UP	/* conflicts with D14 and TDI */
+							 AT91_PIOB 25 AT91_PERIPH_A AT91_PINCTRL_NONE>;		/* conflicts with D15 and TDO */
 					};
 				};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sh73a0.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sh73a0.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sh73a0.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sh73a0.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -8,8 +8,6 @@
  * kind, whether express or implied.
  */
 
-/include/ "skeleton.dtsi"
-
 #include <dt-bindings/clock/sh73a0-clock.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/interrupt-controller/irq.h>
@@ -17,6 +15,8 @@
 / {
 	compatible = "renesas,sh73a0";
 	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
 
 	cpus {
 		#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria10.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -562,6 +562,21 @@
 			status = "disabled";
 		};
 
+		spi1: spi@ffda5000 {
+			compatible = "snps,dw-apb-ssi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xffda5000 0x100>;
+			interrupts = <0 102 4>;
+			num-chipselect = <4>;
+			bus-num = <0>;
+			/*32bit_access;*/
+			tx-dma-channel = <&pdma 16>;
+			rx-dma-channel = <&pdma 17>;
+			clocks = <&spi_m_clk>;
+			status = "disabled";
+		};
+
 		sdr: sdr@ffc25000 {
 			compatible = "syscon";
 			reg = <0xffcfb100 0x80>;
@@ -573,6 +588,9 @@
 			interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
 			cache-unified;
 			cache-level = <2>;
+			prefetch-data = <1>;
+			prefetch-instr = <1>;
+			arm,shared-override;
 		};
 
 		mmc: dwmmc0@ff808000 {
@@ -657,6 +675,20 @@
 			};
 		};
 
+		qspi: spi@ff809000 {
+			compatible = "cdns,qspi-nor";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xff809000 0x100>,
+			      <0xffa00000 0x100000>;
+			interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
+			cdns,fifo-depth = <128>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x00000000>;
+			clocks = <&qspi_clk>;
+			status = "disabled";
+		};
+
 		rst: rstmgr@ffd05000 {
 			#reset-cells = <1>;
 			compatible = "altr,rst-mgr";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria10_socdk.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,30 @@
 		reg = <0x0 0x40000000>; /* 1GB */
 	};
 
+	a10leds {
+		compatible = "gpio-leds";
+
+		a10sr_led0 {
+			label = "a10sr-led0";
+			gpios = <&a10sr_gpio 0 1>;
+		};
+
+		a10sr_led1 {
+			label = "a10sr-led1";
+			gpios = <&a10sr_gpio 1 1>;
+		};
+
+		a10sr_led2 {
+			label = "a10sr-led2";
+			gpios = <&a10sr_gpio 2 1>;
+		};
+
+		a10sr_led3 {
+			label = "a10sr-led3";
+			gpios = <&a10sr_gpio 3 1>;
+		};
+	};
+
 	soc {
 		clkmgr@ffd04000 {
 			clocks {
@@ -75,6 +99,31 @@
 	status = "okay";
 };
 
+&gpio1 {
+	status = "okay";
+};
+
+&spi1 {
+	status = "okay";
+
+	resource-manager@0 {
+		compatible = "altr,a10sr";
+		reg = <0>;
+		spi-max-frequency = <100000>;
+		/* low-level active IRQ at GPIO1_5 */
+		interrupt-parent = <&portb>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		a10sr_gpio: gpio-controller {
+			compatible = "altr,a10sr-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
+};
+
 &i2c1 {
 	speed-mode = <0>;
 	status = "okay";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Intel. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+#include "socfpga_arria10_socdk.dtsi"
+
+&qspi {
+	status = "okay";
+
+	flash0: n25q00@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q00aa";
+		reg = <0>;
+		spi-max-frequency = <100000000>;
+
+		m25p,fast-read;
+		cdns,page-size = <256>;
+		cdns,block-size = <16>;
+		cdns,read-delay = <4>;
+		cdns,tshsl-ns = <50>;
+		cdns,tsd2d-ns = <50>;
+		cdns,tchsh-ns = <4>;
+		cdns,tslch-ns = <4>;
+
+		partition@qspi-boot {
+			label = "Boot and fpga data";
+			reg = <0x0 0x2720000>;
+		};
+
+		partition@qspi-rootfs {
+			label = "Root Filesystem - JFFS2";
+			reg = <0x2720000 0x58E0000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria5_socdk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria5_socdk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_arria5_socdk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_arria5_socdk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -82,6 +82,39 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+
+	flash: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q256a";
+		reg = <0>;
+		spi-max-frequency = <100000000>;
+
+		m25p,fast-read;
+		cdns,page-size = <256>;
+		cdns,block-size = <16>;
+		cdns,read-delay = <4>;
+		cdns,tshsl-ns = <50>;
+		cdns,tsd2d-ns = <50>;
+		cdns,tchsh-ns = <4>;
+		cdns,tslch-ns = <4>;
+
+		partition@qspi-boot {
+			/* 8MB for raw data. */
+			label = "Flash 0 Raw Data";
+			reg = <0x0 0x800000>;
+		};
+
+		partition@qspi-rootfs {
+			/* 120MB for jffs2 data. */
+			label = "Flash 0 jffs2 Filesystem";
+			reg = <0x800000 0x7800000>;
+		};
+	};
+};
+
 &usb1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 
 / {
 	model = "Terasic DE-0(Atlas)";
-	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+	compatible = "terasic,de0-atlas", "altr,socfpga-cyclone5", "altr,socfpga";
 
 	chosen {
 		bootargs = "earlyprintk";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include "socfpga_cyclone5.dtsi"
 
 / {
-	model = "DENX MCV";
+	model = "Aries/DENX MCV";
 	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
 
 	memory {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -18,8 +18,8 @@
 #include "socfpga_cyclone5_mcv.dtsi"
 
 / {
-	model = "DENX MCV EVK";
-	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+	model = "Aries/DENX MCV EVK";
+	compatible = "denx,mcvevk", "altr,socfpga-cyclone5", "altr,socfpga";
 
 	aliases {
 		ethernet0 = &gmac0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 / {
 	model = "Altera SOCFPGA Cyclone V SoC Development Kit";
-	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+	compatible = "altr,socfpga-cyclone5-socdk", "altr,socfpga-cyclone5", "altr,socfpga";
 
 	chosen {
 		bootargs = "earlyprintk";
@@ -87,6 +87,39 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+
+	flash0: n25q00@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q00";
+		reg = <0>;	/* chip select */
+		spi-max-frequency = <100000000>;
+
+		m25p,fast-read;
+		cdns,page-size = <256>;
+		cdns,block-size = <16>;
+		cdns,read-delay = <4>;
+		cdns,tshsl-ns = <50>;
+		cdns,tsd2d-ns = <50>;
+		cdns,tchsh-ns = <4>;
+		cdns,tslch-ns = <4>;
+
+		partition@qspi-boot {
+			/* 8MB for raw data. */
+			label = "Flash 0 Raw Data";
+			reg = <0x0 0x800000>;
+		};
+
+		partition@qspi-rootfs {
+			/* 120MB for jffs2 data. */
+			label = "Flash 0 jffs2 Filesystem";
+			reg = <0x800000 0x7800000>;
+		};
+	};
+};
+
 &usb1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 / {
 	model = "Terasic SoCkit";
-	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+	compatible = "terasic,socfpga-cyclone5-sockit", "altr,socfpga-cyclone5", "altr,socfpga";
 
 	chosen {
 		bootargs = "earlyprintk";
@@ -175,6 +175,27 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+
+	flash: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q00";
+		reg = <0>;
+		spi-max-frequency = <100000000>;
+
+		m25p,fast-read;
+		cdns,page-size = <256>;
+		cdns,block-size = <16>;
+		cdns,read-delay = <4>;
+		cdns,tshsl-ns = <50>;
+		cdns,tsd2d-ns = <50>;
+		cdns,tchsh-ns = <4>;
+		cdns,tslch-ns = <4>;
+	};
+};
+
 &usb1 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts	2017-02-12 16:03:20.000000000 -0500
@@ -80,3 +80,22 @@
 &mmc {
 	status = "okay";
 };
+
+&qspi {
+	status = "okay";
+
+	flash: flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q256a";
+		reg = <0>;
+		spi-max-frequency = <100000000>;
+		m25p,fast-read;
+		cdns,read-delay = <4>;
+		cdns,tshsl-ns = <50>;
+		cdns,tsd2d-ns = <50>;
+		cdns,tchsh-ns = <4>;
+		cdns,tslch-ns = <4>;
+		status = "okay";
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ *  Copyright (C) 2016 Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "socfpga_cyclone5.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Altera SOCFPGA Cyclone V SoC Macnica Sodia board";
+	compatible = "macnica,sodia", "altr,socfpga-cyclone5", "altr,socfpga";
+
+	chosen {
+		bootargs = "earlyprintk";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		name = "memory";
+		device_type = "memory";
+		reg = <0x0 0x40000000>;
+	};
+
+	aliases {
+		ethernet0 = &gmac1;
+	};
+
+	regulator_3_3v: 3-3-v-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	leds: gpio-leds {
+		compatible = "gpio-leds";
+
+		hps_led0 {
+			label = "hps:green:led0";
+			gpios = <&portb 12 GPIO_ACTIVE_LOW>;
+		};
+
+		hps_led1 {
+			label = "hps:green:led1";
+			gpios = <&portb 13 GPIO_ACTIVE_LOW>;
+		};
+
+		hps_led2 {
+			label = "hps:green:led2";
+			gpios = <&portb 14 GPIO_ACTIVE_LOW>;
+		};
+
+		hps_led3 {
+			label = "hps:green:led3";
+			gpios = <&portb 15 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&gmac1 {
+	status = "okay";
+	phy-mode = "rgmii";
+	phy = <&phy0>;
+
+	mdio0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy0: ethernet-phy@0 {
+			reg = <0>;
+			rxd0-skew-ps = <0>;
+			rxd1-skew-ps = <0>;
+			rxd2-skew-ps = <0>;
+			rxd3-skew-ps = <0>;
+			rxdv-skew-ps = <0>;
+			rxc-skew-ps = <3000>;
+			txen-skew-ps = <0>;
+			txc-skew-ps = <3000>;
+		};
+	};
+};
+
+&gpio1 {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	eeprom@51 {
+		compatible = "atmel,24c32";
+		reg = <0x51>;
+		pagesize = <32>;
+	};
+
+	rtc@68 {
+		compatible = "dallas,ds1339";
+		reg = <0x68>;
+	};
+};
+
+&mmc0 {
+	cd-gpios = <&portb 18 0>;
+	vmmc-supply = <&regulator_3_3v>;
+	vqmmc-supply = <&regulator_3_3v>;
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts	2017-02-12 16:03:20.000000000 -0500
@@ -51,7 +51,7 @@
 
 / {
 	model = "samtec VIN|ING FPGA";
-	compatible = "altr,socfpga-cyclone5", "altr,socfpga";
+	compatible = "samtec,vining", "altr,socfpga-cyclone5", "altr,socfpga";
 
 	chosen {
 		bootargs = "console=ttyS0,115200";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/socfpga.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/socfpga.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -686,6 +686,12 @@
 			arm,data-latency = <2 1 1>;
 			prefetch-data = <1>;
 			prefetch-instr = <1>;
+			arm,shared-override;
+			arm,double-linefill = <1>;
+			arm,double-linefill-incr = <0>;
+			arm,double-linefill-wrap = <1>;
+			arm,prefetch-drop = <0>;
+			arm,prefetch-offset = <7>;
 		};
 
 		mmc: dwmmc0@ff704000 {
@@ -700,11 +706,38 @@
 			status = "disabled";
 		};
 
+		nand0: nand@ff900000 {
+			#address-cells = <0x1>;
+			#size-cells = <0x1>;
+			compatible = "denali,denali-nand-dt";
+			reg = <0xff900000 0x100000>,
+			      <0xffb80000 0x10000>;
+			reg-names = "nand_data", "denali_reg";
+			interrupts = <0x0 0x90 0x4>;
+			dma-mask = <0xffffffff>;
+			clocks = <&nand_clk>;
+			status = "disabled";
+		};
+
 		ocram: sram@ffff0000 {
 			compatible = "mmio-sram";
 			reg = <0xffff0000 0x10000>;
 		};
 
+		qspi: spi@ff705000 {
+			compatible = "cdns,qspi-nor";
+                        #address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xff705000 0x1000>,
+			      <0xffa00000 0x1000>;
+			interrupts = <0 151 4>;
+			cdns,fifo-depth = <128>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x00000000>;
+			clocks = <&qspi_clk>;
+			status = "disabled";
+		};
+
 		rst: rstmgr@ffd05000 {
 			#reset-cells = <1>;
 			compatible = "altr,rst-mgr";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/spear13xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/spear13xx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/spear13xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/spear13xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -118,6 +118,7 @@
 			block_size = <0xfff>;
 			dma-masters = <2>;
 			data-width = <8 8>;
+			multi-block = <1 1 1 1 1 1 1 1>;
 		};
 
 		dma@eb000000 {
@@ -134,6 +135,7 @@
 			chan_priority = <1>;
 			block_size = <0xfff>;
 			data-width = <8 8>;
+			multi-block = <1 1 1 1 1 1 1 1>;
 		};
 
 		fsmc: flash@b0000000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih407-clock.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407-clock.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih407-clock.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407-clock.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -101,6 +101,7 @@
 				clocks = <&clk_sysin>;
 
 				clock-output-names = "clk-s-a0-pll-ofd-0";
+				clock-critical = <0>; /* clk-s-a0-pll-ofd-0 */
 			};
 
 			clk_s_a0_flexgen: clk-s-a0-flexgen {
@@ -112,6 +113,7 @@
 					 <&clk_sysin>;
 
 				clock-output-names = "clk-ic-lmi0";
+				clock-critical = <CLK_IC_LMI0>;
 			};
 		};
 
@@ -126,6 +128,7 @@
 					     "clk-s-c0-fs0-ch1",
 					     "clk-s-c0-fs0-ch2",
 					     "clk-s-c0-fs0-ch3";
+			clock-critical = <0>; /* clk-s-c0-fs0-ch0 */
 		};
 
 		clk_s_c0: clockgen-c@09103000 {
@@ -139,6 +142,7 @@
 				clocks = <&clk_sysin>;
 
 				clock-output-names = "clk-s-c0-pll0-odf-0";
+				clock-critical = <0>; /* clk-s-c0-pll0-odf-0 */
 			};
 
 			clk_s_c0_pll1: clk-s-c0-pll1 {
@@ -194,6 +198,12 @@
 						     "clk-main-disp",
 						     "clk-aux-disp",
 						     "clk-compo-dvp";
+				clock-critical = <CLK_PROC_STFE>,
+						 <CLK_ICN_CPU>,
+						 <CLK_TX_ICN_DMU>,
+						 <CLK_EXT2F_A9>,
+						 <CLK_ICN_LMI>,
+						 <CLK_ICN_SBC>;
 			};
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih407.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih407.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,7 @@
 							 <&clk_s_d2_quadfs 0>;
 			};
 
-			sti-hdmi@8d04000 {
+			sti_hdmi: sti-hdmi@8d04000 {
 				compatible = "st,stih407-hdmi";
 				reg = <0x8d04000 0x1000>;
 				reg-names = "hdmi-reg";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih407-family.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407-family.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih407-family.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407-family.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -680,6 +680,7 @@
 				phy-names	= "usb2-phy", "usb3-phy";
 				phys		= <&usb2_picophy0>,
 						  <&phy_port2 PHY_TYPE_USB3>;
+				snps,dis_u3_susphy_quirk;
 			};
 		};
 
@@ -916,7 +917,7 @@
 		};
 
 		sti_uni_player0: sti-uni-player@8d80000 {
-			compatible = "st,sti-uni-player";
+			compatible = "st,stih407-uni-player-hdmi";
 			#sound-dai-cells = <0>;
 			st,syscfg = <&syscfg_core>;
 			clocks = <&clk_s_d0_flexgen CLK_PCM_0>;
@@ -926,17 +927,13 @@
 			reg = <0x8d80000 0x158>;
 			interrupts = <GIC_SPI 84 IRQ_TYPE_NONE>;
 			dmas = <&fdma0 2 0 1>;
-			dai-name = "Uni Player #0 (HDMI)";
 			dma-names = "tx";
-			st,uniperiph-id = <0>;
-			st,version = <5>;
-			st,mode = "HDMI";
 
 			status		= "disabled";
 		};
 
 		sti_uni_player1: sti-uni-player@8d81000 {
-			compatible = "st,sti-uni-player";
+			compatible = "st,stih407-uni-player-pcm-out";
 			#sound-dai-cells = <0>;
 			st,syscfg = <&syscfg_core>;
 			clocks = <&clk_s_d0_flexgen CLK_PCM_1>;
@@ -946,17 +943,13 @@
 			reg = <0x8d81000 0x158>;
 			interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
 			dmas = <&fdma0 3 0 1>;
-			dai-name = "Uni Player #1 (PIO)";
 			dma-names = "tx";
-			st,uniperiph-id = <1>;
-			st,version = <5>;
-			st,mode = "PCM";
 
 			status = "disabled";
 		};
 
 		sti_uni_player2: sti-uni-player@8d82000 {
-			compatible = "st,sti-uni-player";
+			compatible = "st,stih407-uni-player-dac";
 			#sound-dai-cells = <0>;
 			st,syscfg = <&syscfg_core>;
 			clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
@@ -966,17 +959,13 @@
 			reg = <0x8d82000 0x158>;
 			interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
 			dmas = <&fdma0 4 0 1>;
-			dai-name = "Uni Player #1 (DAC)";
 			dma-names = "tx";
-			st,uniperiph-id = <2>;
-			st,version = <5>;
-			st,mode = "PCM";
 
 			status = "disabled";
 		};
 
 		sti_uni_player3: sti-uni-player@8d85000 {
-			compatible = "st,sti-uni-player";
+			compatible = "st,stih407-uni-player-spdif";
 			#sound-dai-cells = <0>;
 			st,syscfg = <&syscfg_core>;
 			clocks = <&clk_s_d0_flexgen CLK_SPDIFF>;
@@ -987,38 +976,30 @@
 			interrupts = <GIC_SPI 89 IRQ_TYPE_NONE>;
 			dmas = <&fdma0 7 0 1>;
 			dma-names = "tx";
-			dai-name = "Uni Player #1 (PIO)";
-			st,uniperiph-id = <3>;
-			st,version = <5>;
-			st,mode = "SPDIF";
 
 			status = "disabled";
 		};
 
 		sti_uni_reader0: sti-uni-reader@8d83000 {
-			compatible = "st,sti-uni-reader";
+			compatible = "st,stih407-uni-reader-pcm_in";
 			#sound-dai-cells = <0>;
 			st,syscfg = <&syscfg_core>;
 			reg = <0x8d83000 0x158>;
 			interrupts = <GIC_SPI 87 IRQ_TYPE_NONE>;
 			dmas = <&fdma0 5 0 1>;
 			dma-names = "rx";
-			dai-name = "Uni Reader #0 (PCM IN)";
-			st,version = <3>;
 
 			status = "disabled";
 		};
 
 		sti_uni_reader1: sti-uni-reader@8d84000 {
-			compatible = "st,sti-uni-reader";
+			compatible = "st,stih407-uni-reader-hdmi";
 			#sound-dai-cells = <0>;
 			st,syscfg = <&syscfg_core>;
 			reg = <0x8d84000 0x158>;
 			interrupts = <GIC_SPI 88 IRQ_TYPE_NONE>;
 			dmas = <&fdma0 6 0 1>;
 			dma-names = "rx";
-			dai-name = "Uni Reader #1 (HDMI RX)";
-			st,version = <3>;
 
 			status = "disabled";
 		};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih407-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih407-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih407-pinctrl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -1157,7 +1157,7 @@
 			reg = <0x0923f080 0x4>;
 			reg-names = "irqmux";
 			interrupts = <GIC_SPI 192 IRQ_TYPE_NONE>;
-			interrupts-names = "irqmux";
+			interrupt-names = "irqmux";
 			ranges = <0 0x09230000 0x3000>;
 
 			pio40: gpio@09230000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih410-b2260.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih410-b2260.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih410-b2260.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih410-b2260.dts	2017-02-12 16:03:20.000000000 -0500
@@ -165,6 +165,9 @@
 			status = "okay";
 		};
 
+		sti_uni_player0: sti-uni-player@8d80000 {
+			status = "okay";
+		};
 		/* SSC11 to HDMI */
 		hdmiddc: i2c@9541000 {
 			/* HDMI V1.3a supports Standard mode only */
@@ -174,9 +177,22 @@
 			status = "okay";
 		};
 
-		sti-display-subsystem {
-			sti_hdmi: sti-hdmi@8d04000 {
-				status = "okay";
+		sound {
+			compatible = "simple-audio-card";
+			simple-audio-card,name = "STI-B2260";
+			status = "okay";
+
+			simple-audio-card,dai-link@0 {
+				/* DAC */
+				format = "i2s";
+				mclk-fs = <128>;
+				cpu {
+					sound-dai = <&sti_uni_player0>;
+				};
+
+				codec {
+					sound-dai = <&sti_hdmi>;
+				};
 			};
 		};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih410-clock.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih410-clock.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih410-clock.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih410-clock.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -208,7 +208,8 @@
 						     "clk-clust-hades",
 						     "clk-hwpe-hades",
 						     "clk-fc-hades";
-				clock-critical = <CLK_ICN_CPU>,
+				clock-critical = <CLK_PROC_STFE>,
+						 <CLK_ICN_CPU>,
 						 <CLK_TX_ICN_DMU>,
 						 <CLK_EXT2F_A9>,
 						 <CLK_ICN_LMI>,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih410.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih410.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih410.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih410.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -193,7 +193,7 @@
 							 <&clk_s_d2_quadfs 0>;
 			};
 
-			sti-hdmi@8d04000 {
+			sti_hdmi: sti-hdmi@8d04000 {
 				compatible = "st,stih407-hdmi";
 				reg = <0x8d04000 0x1000>;
 				reg-names = "hdmi-reg";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-b2000.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-b2000.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-b2000.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-b2000.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-/dts-v1/;
-#include "stih415.dtsi"
-#include "stih41x-b2000.dtsi"
-/ {
-	model = "STiH415 B2000 Board";
-	compatible = "st,stih415-b2000", "st,stih415";
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-b2020.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-b2020.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-b2020.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-b2020.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-/dts-v1/;
-#include "stih415.dtsi"
-#include "stih41x-b2020.dtsi"
-/ {
-	model = "STiH415 B2020 Board";
-	compatible = "st,stih415-b2020", "st,stih415";
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-clock.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-clock.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-clock.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-clock.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,533 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <dt-bindings/clock/stih415-clks.h>
-
-/ {
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		/*
-		 * Fixed 30MHz oscillator input to SoC
-		 */
-		clk_sysin: clk-sysin {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <30000000>;
-		};
-
-		/*
-		 * ClockGenAs on SASG1
-		 */
-		clockgen-a@fee62000 {
-			reg = <0xfee62000 0xb48>;
-
-			clk_s_a0_pll: clk-s-a0-pll {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-plls-c65";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a0-pll0-hs",
-						     "clk-s-a0-pll0-ls",
-						     "clk-s-a0-pll1";
-			};
-
-			clk_s_a0_osc_prediv: clk-s-a0-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c65",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a0-osc-prediv";
-			};
-
-			clk_s_a0_hs: clk-s-a0-hs {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-hs",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a0_osc_prediv>,
-					 <&clk_s_a0_pll 0>, /* PLL0 HS */
-					 <&clk_s_a0_pll 2>; /* PLL1 */
-
-				clock-output-names = "clk-s-fdma-0",
-						     "clk-s-fdma-1",
-						     ""; /* clk-s-jit-sense */
-						     /* Fourth output unused */
-			};
-
-			clk_s_a0_ls: clk-s-a0-ls {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-ls",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a0_osc_prediv>,
-					 <&clk_s_a0_pll 1>, /* PLL0 LS */
-					 <&clk_s_a0_pll 2>; /* PLL1 */
-
-				clock-output-names = "clk-s-icn-reg-0",
-						     "clk-s-icn-if-0",
-						     "clk-s-icn-reg-lp-0",
-						     "clk-s-emiss",
-						     "clk-s-eth1-phy",
-						     "clk-s-mii-ref-out";
-						 /* Remaining outputs unused */
-			};
-		};
-
-		clockgen-a@fee81000 {
-			reg = <0xfee81000 0xb48>;
-
-			clk_s_a1_pll: clk-s-a1-pll {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-plls-c65";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a1-pll0-hs",
-						     "clk-s-a1-pll0-ls",
-						     "clk-s-a1-pll1";
-			};
-
-			clk_s_a1_osc_prediv: clk-s-a1-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c65",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a1-osc-prediv";
-			};
-
-			clk_s_a1_hs: clk-s-a1-hs {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-hs",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a1_osc_prediv>,
-					 <&clk_s_a1_pll 0>, /* PLL0 HS */
-					 <&clk_s_a1_pll 2>; /* PLL1 */
-
-				clock-output-names = "", /* Reserved */
-						     "", /* Reserved */
-						     "clk-s-stac-phy",
-						     "clk-s-vtac-tx-phy";
-			};
-
-			clk_s_a1_ls: clk-s-a1-ls {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-ls",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a1_osc_prediv>,
-					 <&clk_s_a1_pll 1>, /* PLL0 LS */
-					 <&clk_s_a1_pll 2>; /* PLL1 */
-
-				clock-output-names = "clk-s-icn-if-2",
-						     "clk-s-card-mmc",
-						     "clk-s-icn-if-1",
-						     "clk-s-gmac0-phy",
-						     "clk-s-nand-ctrl",
-						     "", /* Reserved */
-						     "clk-s-mii0-ref-out",
-						     ""; /* clk-s-stac-sys */
-						 /* Remaining outputs unused */
-			};
-		};
-
-		/*
-		 * ClockGenAs on MPE41
-		 */
-		clockgen-a@fde12000 {
-			reg = <0xfde12000 0xb50>;
-
-			clk_m_a0_pll0: clk-m-a0-pll0 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a0-pll0-phi0",
-						     "clk-m-a0-pll0-phi1",
-						     "clk-m-a0-pll0-phi2",
-						     "clk-m-a0-pll0-phi3";
-			};
-
-			clk_m_a0_pll1: clk-m-a0-pll1 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a0-pll1-phi0",
-						     "clk-m-a0-pll1-phi1",
-						     "clk-m-a0-pll1-phi2",
-						     "clk-m-a0-pll1-phi3";
-			};
-
-			clk_m_a0_osc_prediv: clk-m-a0-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c32",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a0-osc-prediv";
-			};
-
-			clk_m_a0_div0: clk-m-a0-div0 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf0",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 0>, /* PLL0 PHI0 */
-					 <&clk_m_a0_pll1 0>; /* PLL1 PHI0 */
-
-				clock-output-names = "clk-m-apb-pm", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "clk-m-pp-dmu-0",
-						     "clk-m-pp-dmu-1",
-						     "clk-m-icm-disp",
-						     ""; /* Unused */
-			};
-
-			clk_m_a0_div1: clk-m-a0-div1 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf1",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 1>, /* PLL0 PHI1 */
-					 <&clk_m_a0_pll1 1>; /* PLL1 PHI1 */
-
-				clock-output-names = "", /* Unused */
-						     "", /* Unused */
-						     "clk-m-a9-ext2f",
-						     "clk-m-st40rt",
-						     "clk-m-st231-dmu-0",
-						     "clk-m-st231-dmu-1",
-						     "clk-m-st231-aud",
-						     "clk-m-st231-gp-0";
-			};
-
-			clk_m_a0_div2: clk-m-a0-div2 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf2",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 2>, /* PLL0 PHI2 */
-					 <&clk_m_a0_pll1 2>; /* PLL1 PHI2 */
-
-				clock-output-names = "clk-m-st231-gp-1",
-						     "clk-m-icn-cpu",
-						     "clk-m-icn-stac",
-						     "clk-m-icn-dmu-0",
-						     "clk-m-icn-dmu-1",
-						     "", /* Unused */
-						     "", /* Unused */
-						     ""; /* Unused */
-			};
-
-			clk_m_a0_div3: clk-m-a0-div3 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf3",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 3>, /* PLL0 PHI3 */
-					 <&clk_m_a0_pll1 3>; /* PLL1 PHI3 */
-
-				clock-output-names = "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "clk-m-icn-eram",
-						     "clk-m-a9-trace";
-			};
-		};
-
-		clockgen-a@fd6db000 {
-			reg = <0xfd6db000 0xb50>;
-
-			clk_m_a1_pll0: clk-m-a1-pll0 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a1-pll0-phi0",
-						     "clk-m-a1-pll0-phi1",
-						     "clk-m-a1-pll0-phi2",
-						     "clk-m-a1-pll0-phi3";
-			};
-
-			clk_m_a1_pll1: clk-m-a1-pll1 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a1-pll1-phi0",
-						     "clk-m-a1-pll1-phi1",
-						     "clk-m-a1-pll1-phi2",
-						     "clk-m-a1-pll1-phi3";
-			};
-
-			clk_m_a1_osc_prediv: clk-m-a1-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c32",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a1-osc-prediv";
-			};
-
-			clk_m_a1_div0: clk-m-a1-div0 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf0",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 0>, /* PLL0 PHI0 */
-					 <&clk_m_a1_pll1 0>; /* PLL1 PHI0 */
-
-				clock-output-names = "clk-m-fdma-12",
-						     "clk-m-fdma-10",
-						     "clk-m-fdma-11",
-						     "clk-m-hva-lmi",
-						     "clk-m-proc-sc",
-						     "clk-m-tp",
-						     "clk-m-icn-gpu",
-						     "clk-m-icn-vdp-0";
-			};
-
-			clk_m_a1_div1: clk-m-a1-div1 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf1",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 1>, /* PLL0 PHI1 */
-					 <&clk_m_a1_pll1 1>; /* PLL1 PHI1 */
-
-				clock-output-names = "clk-m-icn-vdp-1",
-						     "clk-m-icn-vdp-2",
-						     "clk-m-icn-vdp-3",
-						     "clk-m-prv-t1-bus",
-						     "clk-m-icn-vdp-4",
-						     "clk-m-icn-reg-10",
-						     "", /* Unused */
-						     ""; /* clk-m-icn-st231 */
-			};
-
-			clk_m_a1_div2: clk-m-a1-div2 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf2",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 2>, /* PLL0 PHI2 */
-					 <&clk_m_a1_pll1 2>; /* PLL1 PHI2 */
-
-				clock-output-names = "clk-m-fvdp-proc-alt",
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     ""; /* Unused */
-			};
-
-			clk_m_a1_div3: clk-m-a1-div3 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf3",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 3>, /* PLL0 PHI3 */
-					 <&clk_m_a1_pll1 3>; /* PLL1 PHI3 */
-
-				clock-output-names = "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     ""; /* Unused */
-			};
-		};
-
-		clk_m_a9_ext2f_div2: clk-m-a9-ext2f-div2 {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clocks = <&clk_m_a0_div1 2>;
-			clock-div = <2>;
-			clock-mult = <1>;
-		};
-
-		clockgen-a@fd345000 {
-			reg = <0xfd345000 0xb50>;
-
-			clk_m_a2_pll0: clk-m-a2-pll0 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a2-pll0-phi0",
-						     "clk-m-a2-pll0-phi1",
-						     "clk-m-a2-pll0-phi2",
-						     "clk-m-a2-pll0-phi3";
-			};
-
-			clk_m_a2_pll1: clk-m-a2-pll1 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a2-pll1-phi0",
-						     "clk-m-a2-pll1-phi1",
-						     "clk-m-a2-pll1-phi2",
-						     "clk-m-a2-pll1-phi3";
-			};
-
-			clk_m_a2_osc_prediv: clk-m-a2-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c32",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a2-osc-prediv";
-			};
-
-			clk_m_a2_div0: clk-m-a2-div0 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf0",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 0>, /* PLL0 PHI0 */
-					 <&clk_m_a2_pll1 0>; /* PLL1 PHI0 */
-
-				clock-output-names = "clk-m-vtac-main-phy",
-						     "clk-m-vtac-aux-phy",
-						     "clk-m-stac-phy",
-						     "clk-m-stac-sys",
-						     "", /* clk-m-mpestac-pg */
-						     "", /* clk-m-mpestac-wc */
-						     "", /* clk-m-mpevtacaux-pg*/
-						     ""; /* clk-m-mpevtacmain-pg*/
-			};
-
-			clk_m_a2_div1: clk-m-a2-div1 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf1",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 1>, /* PLL0 PHI1 */
-					 <&clk_m_a2_pll1 1>; /* PLL1 PHI1 */
-
-				clock-output-names = "", /* clk-m-mpevtacrx0-wc */
-						     "", /* clk-m-mpevtacrx1-wc */
-						     "clk-m-compo-main",
-						     "clk-m-compo-aux",
-						     "clk-m-bdisp-0",
-						     "clk-m-bdisp-1",
-						     "clk-m-icn-bdisp-0",
-						     "clk-m-icn-bdisp-1";
-			};
-
-			clk_m_a2_div2: clk-m-a2-div2 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf2",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 2>, /* PLL0 PHI2 */
-					 <&clk_m_a2_pll1 2>; /* PLL1 PHI2 */
-
-				clock-output-names = "", /* clk-m-icn-hqvdp0 */
-						     "", /* clk-m-icn-hqvdp1 */
-						     "clk-m-icn-compo",
-						     "", /* clk-m-icn-vdpaux */
-						     "clk-m-icn-ts",
-						     "clk-m-icn-reg-lp-10",
-						     "clk-m-dcephy-impctrl",
-						     ""; /* Unused */
-			};
-
-			clk_m_a2_div3: clk-m-a2-div3 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf3",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 3>, /* PLL0 PHI3 */
-					 <&clk_m_a2_pll1 3>; /* PLL1 PHI3 */
-
-				clock-output-names = ""; /* Unused */
-						/* Remaining outputs unused */
-			};
-		};
-
-		/*
-		 * A9 PLL
-		 */
-		clockgen-a9@fdde00d8 {
-			reg = <0xfdde00d8 0x70>;
-
-			clockgen_a9_pll: clockgen-a9-pll {
-				#clock-cells = <1>;
-				compatible = "st,stih415-plls-c32-a9", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-				clock-output-names = "clockgen-a9-pll-odf";
-			};
-		};
-
-		/*
-		 * ARM CPU related clocks
-		 */
-		clk_m_a9: clk-m-a9@fdde00d8 {
-			#clock-cells = <0>;
-			compatible = "st,stih415-clkgen-a9-mux", "st,clkgen-mux";
-			reg = <0xfdde00d8 0x4>;
-			clocks = <&clockgen_a9_pll 0>,
-				 <&clockgen_a9_pll 0>,
-				 <&clk_m_a0_div1 2>,
-				 <&clk_m_a9_ext2f_div2>;
-		};
-
-		/*
-		 * ARM Peripheral clock for timers
-		 */
-		arm_periph_clk: clk-m-a9-periphs {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clocks = <&clk_m_a9>;
-			clock-div = <2>;
-			clock-mult = <1>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih415.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih415.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-#include "stih41x.dtsi"
-#include "stih415-clock.dtsi"
-#include "stih415-pinctrl.dtsi"
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/reset/stih415-resets.h>
-/ {
-
-	L2: cache-controller {
-		compatible = "arm,pl310-cache";
-		reg = <0xfffe2000 0x1000>;
-		arm,data-latency = <3 2 2>;
-		arm,tag-latency = <1 1 1>;
-		cache-unified;
-		cache-level = <2>;
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		interrupt-parent = <&intc>;
-		ranges;
-		compatible	= "simple-bus";
-
-		powerdown: powerdown-controller {
-			#reset-cells = <1>;
-			compatible = "st,stih415-powerdown";
-		};
-
-		softreset: softreset-controller {
-			#reset-cells = <1>;
-			compatible = "st,stih415-softreset";
-		};
-
-		syscfg_sbc: sbc-syscfg@fe600000{
-			compatible      = "st,stih415-sbc-syscfg", "syscon";
-			reg		= <0xfe600000 0xb4>;
-		};
-
-		syscfg_front: front-syscfg@fee10000{
-			compatible      = "st,stih415-front-syscfg", "syscon";
-			reg		= <0xfee10000 0x194>;
-		};
-
-		syscfg_rear: rear-syscfg@fe830000{
-			compatible      = "st,stih415-rear-syscfg", "syscon";
-			reg		= <0xfe830000 0x190>;
-		};
-
-		/* MPE syscfgs */
-		syscfg_left: left-syscfg@fd690000{
-			compatible      = "st,stih415-left-syscfg", "syscon";
-			reg		= <0xfd690000 0x78>;
-		};
-
-		syscfg_right: right-syscfg@fd320000{
-			compatible      = "st,stih415-right-syscfg", "syscon";
-			reg		= <0xfd320000 0x180>;
-		};
-
-		syscfg_system: system-syscfg@fdde0000  {
-			compatible      = "st,stih415-system-syscfg", "syscon";
-			reg		= <0xfdde0000 0x15c>;
-		};
-
-		syscfg_lpm: lpm-syscfg@fe4b5100{
-			compatible      = "st,stih415-lpm-syscfg", "syscon";
-			reg		= <0xfe4b5100 0x08>;
-		};
-
-		serial2: serial@fed32000 {
-			compatible	= "st,asc";
-			status 		= "disabled";
-			reg		= <0xfed32000 0x2c>;
-			interrupts	= <0 197 0>;
-			pinctrl-names 	= "default";
-			pinctrl-0 	= <&pinctrl_serial2>;
-			clocks		= <&clk_s_a0_ls CLK_ICN_REG>;
-		};
-
-		/* SBC comms block ASCs in SASG1 */
-		sbc_serial1: serial@fe531000 {
-			compatible	= "st,asc";
-			status 		= "disabled";
-			reg		= <0xfe531000 0x2c>;
-			interrupts	= <0 210 0>;
-			clocks		= <&clk_sysin>;
-			pinctrl-names 	= "default";
-			pinctrl-0	= <&pinctrl_sbc_serial1>;
-		};
-
-		i2c@fed40000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfed40000 0x110>;
-			interrupts	= <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&clk_s_a0_ls CLK_ICN_REG>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_i2c0_default>;
-
-			status		= "disabled";
-		};
-
-		i2c@fed41000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfed41000 0x110>;
-			interrupts	= <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&clk_s_a0_ls CLK_ICN_REG>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_i2c1_default>;
-
-			status		= "disabled";
-		};
-
-		i2c@fe540000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfe540000 0x110>;
-			interrupts	= <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&clk_sysin>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_sbc_i2c0_default>;
-
-			status		= "disabled";
-		};
-
-		i2c@fe541000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfe541000 0x110>;
-			interrupts	= <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&clk_sysin>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_sbc_i2c1_default>;
-
-			status		= "disabled";
-		};
-
-		ethernet0: dwmac@fe810000 {
-			device_type 	= "network";
-			compatible	= "st,stih415-dwmac", "snps,dwmac", "snps,dwmac-3.610";
-			status 		= "disabled";
-
-			reg		= <0xfe810000 0x8000>;
-			reg-names	= "stmmaceth";
-
-			interrupts 	= <0 147 0>, <0 148 0>, <0 149 0>;
-			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
-			resets			= <&softreset STIH415_ETH0_SOFTRESET>;
-			reset-names		= "stmmaceth";
-
-			snps,pbl 	= <32>;
-			snps,mixed-burst;
-			snps,force_sf_dma_mode;
-
-			st,syscon	= <&syscfg_rear 0x148>;
-
-			pinctrl-names 	= "default";
-			pinctrl-0	= <&pinctrl_mii0>;
-			clock-names	= "stmmaceth", "sti-ethclk";
-			clocks		= <&clk_s_a1_ls CLK_ICN_IF_2>, <&clk_s_a1_ls CLK_GMAC0_PHY>;
-		};
-
-		ethernet1: dwmac@fef08000 {
-			device_type = "network";
-			compatible	= "st,stih415-dwmac", "snps,dwmac", "snps,dwmac-3.610";
-			status 		= "disabled";
-			reg		= <0xfef08000 0x8000>;
-			reg-names	= "stmmaceth";
-			interrupts 	= <0 150 0>, <0 151 0>, <0 152 0>;
-			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
-
-			snps,pbl	= <32>;
-			snps,mixed-burst;
-			snps,force_sf_dma_mode;
-
-			st,syscon		= <&syscfg_sbc 0x74>;
-
-			resets			= <&softreset STIH415_ETH1_SOFTRESET>;
-			reset-names		= "stmmaceth";
-			pinctrl-names 	= "default";
-			pinctrl-0	= <&pinctrl_mii1>;
-			clock-names	= "stmmaceth", "sti-ethclk";
-			clocks		= <&clk_s_a0_ls CLK_ICN_REG>, <&clk_s_a0_ls CLK_ETH1_PHY>;
-		};
-
-		rc: rc@fe518000 {
-			compatible	= "st,comms-irb";
-			reg		= <0xfe518000 0x234>;
-			interrupts	=  <0 203 0>;
-			clocks		= <&clk_sysin>;
-			rx-mode		= "infrared";
-			pinctrl-names 	= "default";
-			pinctrl-0	= <&pinctrl_ir>;
-			resets		= <&softreset STIH415_IRB_SOFTRESET>;
-		};
-
-		keyscan: keyscan@fe4b0000 {
-			compatible = "st,sti-keyscan";
-			status = "disabled";
-			reg = <0xfe4b0000 0x2000>;
-			interrupts = <GIC_SPI 212 IRQ_TYPE_NONE>;
-			clocks = <&clk_sysin>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_keyscan>;
-			resets	= <&powerdown STIH415_KEYSCAN_POWERDOWN>,
-				  <&softreset STIH415_KEYSCAN_SOFTRESET>;
-		};
-
-		mmc0: sdhci@fe81e000 {
-			compatible      = "st,sdhci";
-			status          = "disabled";
-			reg             = <0xfe81e000 0x1000>;
-			interrupts      = <GIC_SPI 145 IRQ_TYPE_NONE>;
-			interrupt-names = "mmcirq";
-			pinctrl-names   = "default";
-			pinctrl-0       = <&pinctrl_mmc0>;
-			clock-names     = "mmc";
-			clocks          = <&clk_s_a1_ls 1>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih415-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih415-pinctrl.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,545 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-#include "st-pincfg.h"
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-/ {
-
-	aliases {
-		gpio0	= &pio0;
-		gpio1	= &pio1;
-		gpio2	= &pio2;
-		gpio3	= &pio3;
-		gpio4	= &pio4;
-		gpio5	= &pio5;
-		gpio6	= &pio6;
-		gpio7	= &pio7;
-		gpio8	= &pio8;
-		gpio9	= &pio9;
-		gpio10	= &pio10;
-		gpio11	= &pio11;
-		gpio12	= &pio12;
-		gpio13	= &pio13;
-		gpio14	= &pio14;
-		gpio15	= &pio15;
-		gpio16	= &pio16;
-		gpio17	= &pio17;
-		gpio18	= &pio18;
-		gpio19	= &pio100;
-		gpio20	= &pio101;
-		gpio21	= &pio102;
-		gpio22	= &pio103;
-		gpio23	= &pio104;
-		gpio24	= &pio105;
-		gpio25	= &pio106;
-		gpio26	= &pio107;
-	};
-
-	soc {
-		pin-controller-sbc {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih415-sbc-pinctrl";
-			st,syscfg	= <&syscfg_sbc>;
-			reg 		= <0xfe61f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges 		= <0 0xfe610000 0x5000>;
-
-			pio0: gpio@fe610000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO0";
-			};
-			pio1: gpio@fe611000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO1";
-			};
-			pio2: gpio@fe612000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO2";
-			};
-			pio3: gpio@fe613000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO3";
-			};
-			pio4: gpio@fe614000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO4";
-			};
-
-			sbc_serial1 {
-				pinctrl_sbc_serial1:sbc_serial1 {
-					st,pins {
-						tx	= <&pio2 6 ALT3 OUT>;
-						rx	= <&pio2 7 ALT3 IN>;
-					};
-				};
-			};
-
-			keyscan {
-				pinctrl_keyscan: keyscan {
-					st,pins {
-						keyin0 = <&pio0 2 ALT2 IN>;
-						keyin1 = <&pio0 3 ALT2 IN>;
-						keyin2 = <&pio0 4 ALT2 IN>;
-						keyin3 = <&pio2 6 ALT2 IN>;
-
-						keyout0 = <&pio1 6 ALT2 OUT>;
-						keyout1 = <&pio1 7 ALT2 OUT>;
-						keyout2 = <&pio0 6 ALT2 OUT>;
-						keyout3 = <&pio2 7 ALT2 OUT>;
-					};
-				};
-			};
-
-			sbc_i2c0 {
-				pinctrl_sbc_i2c0_default: sbc_i2c0-default {
-					st,pins {
-						sda = <&pio4 6 ALT1 BIDIR>;
-						scl = <&pio4 5 ALT1 BIDIR>;
-					};
-				};
-			};
-
-			sbc_i2c1 {
-				pinctrl_sbc_i2c1_default: sbc_i2c1-default {
-					st,pins {
-						sda = <&pio3 2 ALT2 BIDIR>;
-						scl = <&pio3 1 ALT2 BIDIR>;
-					};
-				};
-			};
-
-			rc{
-				pinctrl_ir: ir0 {
-					st,pins {
-						ir = <&pio4 0 ALT2 IN>;
-					};
-				};
-			};
-
-			gmac1 {
-				pinctrl_mii1: mii1 {
-						st,pins {
-						 txd0   = <&pio0 0 ALT1 OUT  SE_NICLK_IO	0	CLK_A>;
-						 txd1   = <&pio0 1 ALT1 OUT  SE_NICLK_IO	0	CLK_A>;
-						 txd2   = <&pio0 2 ALT1 OUT  SE_NICLK_IO	0	CLK_A>;
-						 txd3   = <&pio0 3 ALT1 OUT  SE_NICLK_IO	0	CLK_A>;
-						 txer   = <&pio0 4 ALT1 OUT  SE_NICLK_IO	0	CLK_A>;
-						 txen   = <&pio0 5 ALT1 OUT  SE_NICLK_IO	0	CLK_A>;
-						 txclk  = <&pio0 6 ALT1 IN   NICLK	0	CLK_A>;
-						 col    = <&pio0 7 ALT1 IN   BYPASS	1000>;
-						 mdio   = <&pio1 0 ALT1 OUT  BYPASS	0>;
-						 mdc    = <&pio1 1 ALT1 OUT  NICLK	0	CLK_A>;
-						 crs    = <&pio1 2 ALT1 IN   BYPASS	1000>;
-						 mdint  = <&pio1 3 ALT1 IN   BYPASS	0>;
-						 rxd0   = <&pio1 4 ALT1 IN   SE_NICLK_IO	0	CLK_A>;
-						 rxd1   = <&pio1 5 ALT1 IN   SE_NICLK_IO	0	CLK_A>;
-						 rxd2   = <&pio1 6 ALT1 IN   SE_NICLK_IO	0	CLK_A>;
-						 rxd3   = <&pio1 7 ALT1 IN   SE_NICLK_IO	0	CLK_A>;
-						 rxdv   = <&pio2 0 ALT1 IN   SE_NICLK_IO	0	CLK_A>;
-						 rx_er  = <&pio2 1 ALT1 IN   SE_NICLK_IO	0	CLK_A>;
-						 rxclk  = <&pio2 2 ALT1 IN   NICLK	0	CLK_A>;
-						 phyclk = <&pio2 3 ALT1 IN   NICLK	1000	CLK_A>;
-					};
-				};
-
-				pinctrl_rgmii1: rgmii1-0 {
-					st,pins {
-						 txd0 =	 <&pio0 0 ALT1 OUT DE_IO	1000	CLK_A>;
-						 txd1 =	 <&pio0 1 ALT1 OUT DE_IO	1000	CLK_A>;
-						 txd2 =	 <&pio0 2 ALT1 OUT DE_IO	1000	CLK_A>;
-						 txd3 =	 <&pio0 3 ALT1 OUT DE_IO	1000	CLK_A>;
-						 txen =	 <&pio0 5 ALT1 OUT DE_IO	0	CLK_A>;
-						 txclk = <&pio0 6 ALT1 IN	NICLK	0	CLK_A>;
-						 mdio =	 <&pio1 0 ALT1 OUT	BYPASS	0>;
-						 mdc =	 <&pio1 1 ALT1 OUT	NICLK	0	CLK_A>;
-						 rxd0 =	 <&pio1 4 ALT1 IN DE_IO	0	CLK_A>;
-						 rxd1 =	 <&pio1 5 ALT1 IN DE_IO	0	CLK_A>;
-						 rxd2 =	 <&pio1 6 ALT1 IN DE_IO	0	CLK_A>;
-						 rxd3 =	 <&pio1 7 ALT1 IN DE_IO	0	CLK_A>;
-
-						 rxdv =	  <&pio2 0 ALT1 IN DE_IO	500	CLK_A>;
-						 rxclk =  <&pio2 2 ALT1 IN	NICLK	0	CLK_A>;
-						 phyclk = <&pio2 3 ALT4 OUT	NICLK	0	CLK_B>;
-
-						 clk125= <&pio3 7 ALT4 IN 	NICLK	0	CLK_A>;
-					};
-				};
-			};
-		};
-
-		pin-controller-front {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih415-front-pinctrl";
-			st,syscfg	= <&syscfg_front>;
-			reg 		= <0xfee0f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges		= <0 0xfee00000 0x8000>;
-
-			pio5: gpio@fee00000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO5";
-			};
-			pio6: gpio@fee01000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO6";
-			};
-			pio7: gpio@fee02000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO7";
-			};
-			pio8: gpio@fee03000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO8";
-			};
-			pio9: gpio@fee04000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO9";
-			};
-			pio10: gpio@fee05000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x5000 0x100>;
-				st,bank-name	= "PIO10";
-			};
-			pio11: gpio@fee06000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x6000 0x100>;
-				st,bank-name	= "PIO11";
-			};
-			pio12: gpio@fee07000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x7000 0x100>;
-				st,bank-name	= "PIO12";
-			};
-
-			i2c0 {
-				pinctrl_i2c0_default: i2c0-default {
-					st,pins {
-						sda = <&pio9 3 ALT1 BIDIR>;
-						scl = <&pio9 2 ALT1 BIDIR>;
-					};
-				};
-			};
-
-			i2c1 {
-				pinctrl_i2c1_default: i2c1-default {
-					st,pins {
-						sda = <&pio12 1 ALT1 BIDIR>;
-						scl = <&pio12 0 ALT1 BIDIR>;
-					};
-				};
-			};
-		};
-
-		pin-controller-rear {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih415-rear-pinctrl";
-			st,syscfg	= <&syscfg_rear>;
-			reg 		= <0xfe82f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges		= <0 0xfe820000 0x8000>;
-
-			pio13: gpio@fe820000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO13";
-			};
-			pio14: gpio@fe821000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO14";
-			};
-			pio15: gpio@fe822000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO15";
-			};
-			pio16: gpio@fe823000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO16";
-			};
-			pio17: gpio@fe824000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO17";
-			};
-			pio18: gpio@fe825000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x5000 0x100>;
-				st,bank-name	= "PIO18";
-			};
-
-			serial2 {
-				pinctrl_serial2: serial2-0 {
-					st,pins {
-						tx	= <&pio17 4 ALT2 OUT>;
-						rx	= <&pio17 5 ALT2 IN>;
-					};
-				};
-			};
-
-			gmac0{
-				pinctrl_mii0: mii0 {
-					st,pins {
-					 mdint =	<&pio13 6 ALT2	IN	BYPASS		0>;
-					 txen =		<&pio13 7 ALT2	OUT	SE_NICLK_IO	0	CLK_A>;
-
-					 txd0 =		<&pio14 0 ALT2	OUT	SE_NICLK_IO	0	CLK_A>;
-					 txd1 =		<&pio14 1 ALT2	OUT	SE_NICLK_IO	0	CLK_A>;
-					 txd2 =		<&pio14 2 ALT2	OUT	SE_NICLK_IO	0	CLK_B>;
-					 txd3 =		<&pio14 3 ALT2	OUT	SE_NICLK_IO	0	CLK_B>;
-
-					 txclk =	<&pio15 0 ALT2	IN	NICLK		0	CLK_A>;
-					 txer =		<&pio15 1 ALT2	OUT	SE_NICLK_IO	0	CLK_A>;
-					 crs =		<&pio15 2 ALT2	IN	BYPASS		1000>;
-					 col =		<&pio15 3 ALT2	IN	BYPASS		1000>;
-					 mdio  =        <&pio15 4 ALT2	OUT	BYPASS 	3000>;
-					 mdc   =        <&pio15 5 ALT2	OUT     NICLK  	0    	CLK_B>;
-
-					 rxd0 =		<&pio16 0 ALT2	IN	SE_NICLK_IO	0	CLK_A>;
-					 rxd1 =		<&pio16 1 ALT2	IN	SE_NICLK_IO	0	CLK_A>;
-					 rxd2 =		<&pio16 2 ALT2	IN	SE_NICLK_IO	0	CLK_A>;
-					 rxd3 =		<&pio16 3 ALT2	IN	SE_NICLK_IO	0	CLK_A>;
-					 rxdv =		<&pio15 6 ALT2	IN	SE_NICLK_IO	0	CLK_A>;
-					 rx_er =	<&pio15 7 ALT2	IN	SE_NICLK_IO	0	CLK_A>;
-					 rxclk =	<&pio17 0 ALT2	IN	NICLK		0	CLK_A>;
-					 phyclk =	<&pio13 5 ALT2	OUT	NICLK	1000	CLK_A>;
-
-					};
-				};
-
-			pinctrl_gmii0: gmii0 {
-				st,pins {
-					 mdint =	<&pio13 6	ALT2 IN		BYPASS	0>;
-					 mdio  =        <&pio15 4 	ALT2 OUT	BYPASS 	3000>;
-					 mdc   =        <&pio15 5 	ALT2 OUT    	NICLK  	0    	CLK_B>;
-					 txen =		<&pio13 7	ALT2 OUT	SE_NICLK_IO	3000	CLK_A>;
-
-					 txd0 =		<&pio14 0	ALT2 OUT	SE_NICLK_IO	3000	CLK_A>;
-					 txd1 =		<&pio14 1	ALT2 OUT	SE_NICLK_IO	3000	CLK_A>;
-					 txd2 =		<&pio14 2	ALT2 OUT	SE_NICLK_IO	3000	CLK_B>;
-					 txd3 =		<&pio14 3	ALT2 OUT	SE_NICLK_IO	3000	CLK_B>;
-					 txd4 =		<&pio14 4	ALT2 OUT	SE_NICLK_IO	3000	CLK_B>;
-					 txd5 =		<&pio14 5	ALT2 OUT	SE_NICLK_IO	3000	CLK_B>;
-					 txd6 =		<&pio14 6	ALT2 OUT	SE_NICLK_IO	3000	CLK_B>;
-					 txd7 =		<&pio14 7	ALT2 OUT	SE_NICLK_IO	3000	CLK_B>;
-
-					 txclk =	<&pio15 0	ALT2 IN		NICLK	0	CLK_A>;
-					 txer =		<&pio15 1	ALT2 OUT 	SE_NICLK_IO	3000	CLK_A>;
-					 crs =		<&pio15 2	ALT2 IN		BYPASS	1000>;
-					 col =		<&pio15 3	ALT2 IN		BYPASS	1000>;
-					 rxdv =		<&pio15 6	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rx_er =	<&pio15 7	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-
-					 rxd0 =		<&pio16 0	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rxd1 =		<&pio16 1	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rxd2 =		<&pio16 2	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rxd3 =		<&pio16 3	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rxd4 =		<&pio16 4	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rxd5 =		<&pio16 5	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rxd6 =		<&pio16 6	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-					 rxd7 =		<&pio16 7	ALT2 IN		SE_NICLK_IO	1500	CLK_A>;
-
-					 rxclk =	<&pio17 0	ALT2 IN	NICLK	0	CLK_A>;
-					 clk125 =	<&pio17 6	ALT1 IN	NICLK	0	CLK_A>;
-                                         phyclk =       <&pio13 5       ALT4 OUT NICLK   0       CLK_B>;
-
-
-					};
-				};
-			};
-
-			mmc0 {
-				pinctrl_mmc0: mmc0 {
-					st,pins {
-						mmcclk = <&pio13 4 ALT4 BIDIR_PU NICLK 0 CLK_B>;
-						data0  = <&pio14 4 ALT4 BIDIR_PU BYPASS 0>;
-						data1  = <&pio14 5 ALT4 BIDIR_PU BYPASS 0>;
-						data2  = <&pio14 6 ALT4 BIDIR_PU BYPASS 0>;
-						data3  = <&pio14 7 ALT4 BIDIR_PU BYPASS 0>;
-						cmd    = <&pio15 1 ALT4 BIDIR_PU BYPASS 0>;
-						wp     = <&pio15 3 ALT4 IN>;
-						data4  = <&pio16 4 ALT4 BIDIR_PU BYPASS 0>;
-						data5  = <&pio16 5 ALT4 BIDIR_PU BYPASS 0>;
-						data6  = <&pio16 6 ALT4 BIDIR_PU BYPASS 0>;
-						data7  = <&pio16 7 ALT4 BIDIR_PU BYPASS 0>;
-						pwr    = <&pio17 1 ALT4 OUT>;
-						cd     = <&pio17 2 ALT4 IN>;
-						led    = <&pio17 3 ALT4 OUT>;
-					};
-				};
-			};
-		};
-
-		pin-controller-left {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih415-left-pinctrl";
-			st,syscfg	= <&syscfg_left>;
-			reg 		= <0xfd6bf080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges		= <0 0xfd6b0000 0x3000>;
-
-			pio100: gpio@fd6b0000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO100";
-			};
-			pio101: gpio@fd6b1000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO101";
-			};
-			pio102: gpio@fd6b2000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO102";
-			};
-		};
-
-		pin-controller-right {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih415-right-pinctrl";
-			st,syscfg	= <&syscfg_right>;
-			reg 		= <0xfd33f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges		= <0 0xfd330000 0x5000>;
-
-			pio103: gpio@fd330000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO103";
-			};
-			pio104: gpio@fd331000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO104";
-			};
-			pio105: gpio@fd332000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO105";
-			};
-			pio106: gpio@fd333000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO106";
-			};
-			pio107: gpio@fd334000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO107";
-			};
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-b2000.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-b2000.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-b2000.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-b2000.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-/dts-v1/;
-#include "stih416.dtsi"
-#include "stih41x-b2000.dtsi"
-/ {
-	model = "STiH416 B2000";
-	compatible = "st,stih416-b2000", "st,stih416";
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-b2020.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-b2020.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-b2020.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-b2020.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-/dts-v1/;
-#include "stih416.dtsi"
-#include "stih41x-b2020.dtsi"
-/ {
-	model = "STiH416 B2020";
-	compatible = "st,stih416-b2020", "st,stih416";
-
-	soc {
-		mmc1: sdhci@fe81f000 {
-			status       = "okay";
-			bus-width    = <8>;
-			non-removable;
-		};
-
-		miphy365x_phy: phy@fe382000 {
-			phy_port0: port@fe382000 {
-				st,sata-gen = <3>;
-			};
-
-			phy_port1: port@fe38a000 {
-				st,pcie-tx-pol-inv;
-			};
-		};
-
-		sata0: sata@fe380000{
-			status = "okay";
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-b2020e.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-b2020e.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-b2020e.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-b2020e.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics (R&D) Limited.
- * Author: Lee Jones <lee.jones@linaro.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
- * publishhed by the Free Software Foundation.
- */
-/dts-v1/;
-#include "stih416.dtsi"
-#include "stih41x-b2020.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-/ {
-	model = "STiH416 B2020 REV-E";
-	compatible = "st,stih416-b2020", "st,stih416";
-
-	soc {
-		leds {
-			compatible = "gpio-leds";
-			red {
-				label			= "Front Panel LED";
-				gpios			= <&pio4 1 GPIO_ACTIVE_HIGH>;
-				linux,default-trigger	= "heartbeat";
-			};
-			green {
-				gpios			= <&pio1 3 GPIO_ACTIVE_HIGH>;
-				default-state 		= "off";
-			};
-		};
-
-		ethernet1: dwmac@fef08000 {
-			snps,reset-gpio = <&pio0 7>;
-		};
-
-		mmc1: sdhci@fe81f000 {
-			status       = "okay";
-			bus-width    = <8>;
-			non-removable;
-		};
-
-		miphy365x_phy: phy@fe382000 {
-			phy_port0: port@fe382000 {
-				st,sata-gen = <3>;
-			};
-
-			phy_port1: port@fe38a000 {
-				st,pcie-tx-pol-inv;
-			};
-		};
-
-		sata0: sata@fe380000{
-			status = "okay";
-		};
-
-		/* SAS PWM Module */
-		pwm0: pwm@fed10000 {
-			status		= "okay";
-		};
-
-		/* SBC PWM Module */
-		pwm1: pwm@fe510000 {
-			status		= "okay";
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-clock.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-clock.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-clock.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-clock.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,756 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics R&D Limited
- * <stlinux-devel@stlinux.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 <dt-bindings/clock/stih416-clks.h>
-
-/ {
-	clocks {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-
-		/*
-		 * Fixed 30MHz oscillator inputs to SoC
-		 */
-		clk_sysin: clk-sysin {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <30000000>;
-		};
-
-		/*
-		 * ClockGenAs on SASG2
-		 */
-		clockgen-a@fee62000 {
-			reg = <0xfee62000 0xb48>;
-
-			clk_s_a0_pll: clk-s-a0-pll {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-plls-c65";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a0-pll0-hs",
-						     "clk-s-a0-pll0-ls",
-						     "clk-s-a0-pll1";
-			};
-
-			clk_s_a0_osc_prediv: clk-s-a0-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c65",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a0-osc-prediv";
-			};
-
-			clk_s_a0_hs: clk-s-a0-hs {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-hs",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a0_osc_prediv>,
-					 <&clk_s_a0_pll 0>, /* PLL0 HS */
-					 <&clk_s_a0_pll 2>; /* PLL1 */
-
-				clock-output-names = "clk-s-fdma-0",
-						     "clk-s-fdma-1",
-						     ""; /* clk-s-jit-sense */
-						     /* Fourth output unused */
-			};
-
-			clk_s_a0_ls: clk-s-a0-ls {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-ls",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a0_osc_prediv>,
-					 <&clk_s_a0_pll 1>, /* PLL0 LS */
-					 <&clk_s_a0_pll 2>; /* PLL1 */
-
-				clock-output-names = "clk-s-icn-reg-0",
-						     "clk-s-icn-if-0",
-						     "clk-s-icn-reg-lp-0",
-						     "clk-s-emiss",
-						     "clk-s-eth1-phy",
-						     "clk-s-mii-ref-out";
-						     /* Remaining outputs unused */
-			};
-		};
-
-		clockgen-a@fee81000 {
-			reg = <0xfee81000 0xb48>;
-
-			clk_s_a1_pll: clk-s-a1-pll {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-plls-c65";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a1-pll0-hs",
-						     "clk-s-a1-pll0-ls",
-						     "clk-s-a1-pll1";
-			};
-
-			clk_s_a1_osc_prediv: clk-s-a1-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c65",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-s-a1-osc-prediv";
-			};
-
-			clk_s_a1_hs: clk-s-a1-hs {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-hs",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a1_osc_prediv>,
-					 <&clk_s_a1_pll 0>, /* PLL0 HS */
-					 <&clk_s_a1_pll 2>; /* PLL1 */
-
-				clock-output-names = "", /* Reserved */
-						     "", /* Reserved */
-						     "clk-s-stac-phy",
-						     "clk-s-vtac-tx-phy";
-			};
-
-			clk_s_a1_ls: clk-s-a1-ls {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c65-ls",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_s_a1_osc_prediv>,
-					 <&clk_s_a1_pll 1>, /* PLL0 LS */
-					 <&clk_s_a1_pll 2>; /* PLL1 */
-
-				clock-output-names = "clk-s-icn-if-2",
-						     "clk-s-card-mmc-0",
-						     "clk-s-icn-if-1",
-						     "clk-s-gmac0-phy",
-						     "clk-s-nand-ctrl",
-						     "", /* Reserved */
-						     "clk-s-mii0-ref-out",
-						     "clk-s-stac-sys",
-						     "clk-s-card-mmc-1";
-						     /* Remaining outputs unused */
-			};
-		};
-
-		/*
-		 * ClockGenAs on MPE42
-		 */
-		clockgen-a@fde12000 {
-			reg = <0xfde12000 0xb50>;
-
-			clk_m_a0_pll0: clk-m-a0-pll0 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a0-pll0-phi0",
-						     "clk-m-a0-pll0-phi1",
-						     "clk-m-a0-pll0-phi2",
-						     "clk-m-a0-pll0-phi3";
-			};
-
-			clk_m_a0_pll1: clk-m-a0-pll1 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a0-pll1-phi0",
-						     "clk-m-a0-pll1-phi1",
-						     "clk-m-a0-pll1-phi2",
-						     "clk-m-a0-pll1-phi3";
-			};
-
-			clk_m_a0_osc_prediv: clk-m-a0-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c32",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a0-osc-prediv";
-			};
-
-			clk_m_a0_div0: clk-m-a0-div0 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf0",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 0>, /* PLL0 PHI0 */
-					 <&clk_m_a0_pll1 0>; /* PLL1 PHI0 */
-
-				clock-output-names = "", /* Unused */
-						     "", /* Unused */
-						     "clk-m-fdma-12",
-						     "", /* Unused */
-						     "clk-m-pp-dmu-0",
-						     "clk-m-pp-dmu-1",
-						     "clk-m-icm-lmi",
-						     "clk-m-vid-dmu-0";
-			};
-
-			clk_m_a0_div1: clk-m-a0-div1 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf1",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 1>, /* PLL0 PHI1 */
-					 <&clk_m_a0_pll1 1>; /* PLL1 PHI1 */
-
-				clock-output-names = "clk-m-vid-dmu-1",
-						     "", /* Unused */
-						     "clk-m-a9-ext2f",
-						     "clk-m-st40rt",
-						     "clk-m-st231-dmu-0",
-						     "clk-m-st231-dmu-1",
-						     "clk-m-st231-aud",
-						     "clk-m-st231-gp-0";
-			};
-
-			clk_m_a0_div2: clk-m-a0-div2 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf2",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 2>, /* PLL0 PHI2 */
-					 <&clk_m_a0_pll1 2>; /* PLL1 PHI2 */
-
-				clock-output-names = "clk-m-st231-gp-1",
-						     "clk-m-icn-cpu",
-						     "clk-m-icn-stac",
-						     "clk-m-tx-icn-dmu-0",
-						     "clk-m-tx-icn-dmu-1",
-						     "clk-m-tx-icn-ts",
-						     "clk-m-icn-vdp-0",
-						     "clk-m-icn-vdp-1";
-			};
-
-			clk_m_a0_div3: clk-m-a0-div3 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf3",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a0_osc_prediv>,
-					 <&clk_m_a0_pll0 3>, /* PLL0 PHI3 */
-					 <&clk_m_a0_pll1 3>; /* PLL1 PHI3 */
-
-				clock-output-names = "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "clk-m-icn-vp8",
-						     "", /* Unused */
-						     "clk-m-icn-reg-11",
-						     "clk-m-a9-trace";
-			};
-		};
-
-		clockgen-a@fd6db000 {
-			reg = <0xfd6db000 0xb50>;
-
-			clk_m_a1_pll0: clk-m-a1-pll0 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a1-pll0-phi0",
-						     "clk-m-a1-pll0-phi1",
-						     "clk-m-a1-pll0-phi2",
-						     "clk-m-a1-pll0-phi3";
-			};
-
-			clk_m_a1_pll1: clk-m-a1-pll1 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a1-pll1-phi0",
-						     "clk-m-a1-pll1-phi1",
-						     "clk-m-a1-pll1-phi2",
-						     "clk-m-a1-pll1-phi3";
-			};
-
-			clk_m_a1_osc_prediv: clk-m-a1-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c32",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a1-osc-prediv";
-			};
-
-			clk_m_a1_div0: clk-m-a1-div0 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf0",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 0>, /* PLL0 PHI0 */
-					 <&clk_m_a1_pll1 0>; /* PLL1 PHI0 */
-
-				clock-output-names = "", /* Unused */
-						     "clk-m-fdma-10",
-						     "clk-m-fdma-11",
-						     "clk-m-hva-alt",
-						     "clk-m-proc-sc",
-						     "clk-m-tp",
-						     "clk-m-rx-icn-dmu-0",
-						     "clk-m-rx-icn-dmu-1";
-			};
-
-			clk_m_a1_div1: clk-m-a1-div1 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf1",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 1>, /* PLL0 PHI1 */
-					 <&clk_m_a1_pll1 1>; /* PLL1 PHI1 */
-
-				clock-output-names = "clk-m-rx-icn-ts",
-						     "clk-m-rx-icn-vdp-0",
-						     "", /* Unused */
-						     "clk-m-prv-t1-bus",
-						     "clk-m-icn-reg-12",
-						     "clk-m-icn-reg-10",
-						     "", /* Unused */
-						     "clk-m-icn-st231";
-			};
-
-			clk_m_a1_div2: clk-m-a1-div2 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf2",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 2>, /* PLL0 PHI2 */
-					 <&clk_m_a1_pll1 2>; /* PLL1 PHI2 */
-
-				clock-output-names = "clk-m-fvdp-proc-alt",
-						     "clk-m-icn-reg-13",
-						     "clk-m-tx-icn-gpu",
-						     "clk-m-rx-icn-gpu",
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* clk-m-apb-pm-12 */
-						     ""; /* Unused */
-			};
-
-			clk_m_a1_div3: clk-m-a1-div3 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf3",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a1_osc_prediv>,
-					 <&clk_m_a1_pll0 3>, /* PLL0 PHI3 */
-					 <&clk_m_a1_pll1 3>; /* PLL1 PHI3 */
-
-				clock-output-names = "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     "", /* Unused */
-						     ""; /* clk-m-gpu-alt */
-			};
-		};
-
-		clk_m_a9_ext2f_div2: clk-m-a9-ext2f-div2 {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clocks = <&clk_m_a0_div1 2>;
-			clock-div = <2>;
-			clock-mult = <1>;
-		};
-
-		clockgen-a@fd345000 {
-			reg = <0xfd345000 0xb50>;
-
-			clk_m_a2_pll0: clk-m-a2-pll0 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-0", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a2-pll0-phi0",
-						     "clk-m-a2-pll0-phi1",
-						     "clk-m-a2-pll0-phi2",
-						     "clk-m-a2-pll0-phi3";
-			};
-
-			clk_m_a2_pll1: clk-m-a2-pll1 {
-				#clock-cells = <1>;
-				compatible = "st,plls-c32-a1x-1", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a2-pll1-phi0",
-						     "clk-m-a2-pll1-phi1",
-						     "clk-m-a2-pll1-phi2",
-						     "clk-m-a2-pll1-phi3";
-			};
-
-			clk_m_a2_osc_prediv: clk-m-a2-osc-prediv {
-				#clock-cells = <0>;
-				compatible = "st,clkgena-prediv-c32",
-					     "st,clkgena-prediv";
-
-				clocks = <&clk_sysin>;
-
-				clock-output-names = "clk-m-a2-osc-prediv";
-			};
-
-			clk_m_a2_div0: clk-m-a2-div0 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf0",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 0>, /* PLL0 PHI0 */
-					 <&clk_m_a2_pll1 0>; /* PLL1 PHI0 */
-
-				clock-output-names = "clk-m-vtac-main-phy",
-						     "clk-m-vtac-aux-phy",
-						     "clk-m-stac-phy",
-						     "clk-m-stac-sys",
-						     "", /* clk-m-mpestac-pg */
-						     "", /* clk-m-mpestac-wc */
-						     "", /* clk-m-mpevtacaux-pg*/
-						     ""; /* clk-m-mpevtacmain-pg*/
-			};
-
-			clk_m_a2_div1: clk-m-a2-div1 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf1",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 1>, /* PLL0 PHI1 */
-					 <&clk_m_a2_pll1 1>; /* PLL1 PHI1 */
-
-				clock-output-names = "", /* clk-m-mpevtacrx0-wc */
-						     "", /* clk-m-mpevtacrx1-wc */
-						     "clk-m-compo-main",
-						     "clk-m-compo-aux",
-						     "clk-m-bdisp-0",
-						     "clk-m-bdisp-1",
-						     "clk-m-icn-bdisp",
-						     "clk-m-icn-compo";
-			};
-
-			clk_m_a2_div2: clk-m-a2-div2 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf2",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 2>, /* PLL0 PHI2 */
-					 <&clk_m_a2_pll1 2>; /* PLL1 PHI2 */
-
-				clock-output-names = "clk-m-icn-vdp-2",
-						     "", /* Unused */
-						     "clk-m-icn-reg-14",
-						     "clk-m-mdtp",
-						     "clk-m-jpegdec",
-						     "", /* Unused */
-						     "clk-m-dcephy-impctrl",
-						     ""; /* Unused */
-			};
-
-			clk_m_a2_div3: clk-m-a2-div3 {
-				#clock-cells = <1>;
-				compatible = "st,clkgena-divmux-c32-odf3",
-					     "st,clkgena-divmux";
-
-				clocks = <&clk_m_a2_osc_prediv>,
-					 <&clk_m_a2_pll0 3>, /* PLL0 PHI3 */
-					 <&clk_m_a2_pll1 3>; /* PLL1 PHI3 */
-
-				clock-output-names = "", /* Unused */
-						     ""; /* clk-m-apb-pm-11 */
-						     /* Remaining outputs unused */
-			};
-		};
-
-		/*
-		 * A9 PLL
-		 */
-		clockgen-a9@fdde08b0 {
-			reg = <0xfdde08b0 0x70>;
-
-			clockgen_a9_pll: clockgen-a9-pll {
-				#clock-cells = <1>;
-				compatible = "st,stih416-plls-c32-a9", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-				clock-output-names = "clockgen-a9-pll-odf";
-			};
-		};
-
-		/*
-		 * ARM CPU related clocks
-		 */
-		clk_m_a9: clk-m-a9@fdde08ac {
-			#clock-cells = <0>;
-			compatible = "st,stih416-clkgen-a9-mux", "st,clkgen-mux";
-			reg = <0xfdde08ac 0x4>;
-			clocks = <&clockgen_a9_pll 0>,
-				 <&clockgen_a9_pll 0>,
-				 <&clk_m_a0_div1 2>,
-				 <&clk_m_a9_ext2f_div2>;
-		};
-
-		/*
-		 * ARM Peripheral clock for timers
-		 */
-		arm_periph_clk: clk-m-a9-periphs {
-			#clock-cells = <0>;
-			compatible = "fixed-factor-clock";
-			clocks = <&clk_m_a9>;
-			clock-div = <2>;
-			clock-mult = <1>;
-		};
-
-		/*
-		 * Frequency synthesizers on the SASG2
-		 */
-		clockgen_b0: clockgen-b0@fee108b4 {
-			#clock-cells = <1>;
-			compatible = "st,stih416-quadfs216", "st,quadfs";
-			reg = <0xfee108b4 0x44>;
-
-			clocks = <&clk_sysin>;
-			clock-output-names = "clk-s-usb48",
-					     "clk-s-dss",
-					     "clk-s-stfe-frc-2",
-					     "clk-s-thsens-scard";
-		};
-
-		clockgen_b1: clockgen-b1@fe8308c4 {
-			#clock-cells = <1>;
-			compatible = "st,stih416-quadfs216", "st,quadfs";
-			reg = <0xfe8308c4 0x44>;
-
-			clocks = <&clk_sysin>;
-			clock-output-names = "clk-s-pcm-0",
-					     "clk-s-pcm-1",
-					     "clk-s-pcm-2",
-					     "clk-s-pcm-3";
-		};
-
-		clockgen_c: clockgen-c@fe8307d0 {
-			#clock-cells = <1>;
-			compatible = "st,stih416-quadfs432", "st,quadfs";
-			reg = <0xfe8307d0 0x44>;
-
-			clocks = <&clk_sysin>;
-			clock-output-names = "clk-s-c-fs0-ch0",
-					     "clk-s-c-vcc-sd",
-					     "clk-s-c-fs0-ch2";
-		};
-
-		clk_s_vcc_hd: clk-s-vcc-hd@fe8308b8 {
-			#clock-cells = <0>;
-			compatible = "st,stih416-clkgenc-vcc-hd", "st,clkgen-mux";
-			reg = <0xfe8308b8 0x4>; /* SYSCFG2558 */
-
-			clocks = <&clk_sysin>,
-				 <&clockgen_c 0>;
-		};
-
-		/*
-		 * Add a dummy clock for the HDMI PHY for the VCC input mux
-		 */
-		clk_s_tmds_fromphy: clk-s-tmds-fromphy {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
-		};
-
-		clockgen_c_vcc: clockgen-c-vcc@fe8308ac {
-			#clock-cells = <1>;
-			compatible = "st,stih416-clkgenc", "st,clkgen-vcc";
-			reg = <0xfe8308ac 0xc>; /* SYSCFG2555,2556,2557 */
-
-			clocks = <&clk_s_vcc_hd>,
-				 <&clockgen_c 1>,
-				 <&clk_s_tmds_fromphy>,
-				 <&clockgen_c 2>;
-
-			clock-output-names  = "clk-s-pix-hdmi",
-					      "clk-s-pix-dvo",
-					      "clk-s-out-dvo",
-					      "clk-s-pix-hd",
-					      "clk-s-hddac",
-					      "clk-s-denc",
-					      "clk-s-sddac",
-					      "clk-s-pix-main",
-					      "clk-s-pix-aux",
-					      "clk-s-stfe-frc-0",
-					      "clk-s-ref-mcru",
-					      "clk-s-slave-mcru",
-					      "clk-s-tmds-hdmi",
-					      "clk-s-hdmi-reject-pll",
-					      "clk-s-thsens";
-		};
-
-		clockgen_d: clockgen-d@fee107e0 {
-			#clock-cells = <1>;
-			compatible = "st,stih416-quadfs216", "st,quadfs";
-			reg = <0xfee107e0 0x44>;
-
-			clocks = <&clk_sysin>;
-			clock-output-names = "clk-s-ccsc",
-					     "clk-s-stfe-frc-1",
-					     "clk-s-tsout-1",
-					     "clk-s-mchi";
-		};
-
-		/*
-		 * Frequency synthesizers on the MPE42
-		 */
-		clockgen_e: clockgen-e@fd3208bc {
-			#clock-cells = <1>;
-			compatible = "st,stih416-quadfs660-E", "st,quadfs";
-			reg = <0xfd3208bc 0xb0>;
-
-			clocks = <&clk_sysin>;
-			clock-output-names = "clk-m-pix-mdtp-0",
-					     "clk-m-pix-mdtp-1",
-					     "clk-m-pix-mdtp-2",
-					     "clk-m-mpelpc";
-		};
-
-		clockgen_f: clockgen-f@fd320878 {
-			#clock-cells = <1>;
-			compatible = "st,stih416-quadfs660-F", "st,quadfs";
-			reg = <0xfd320878 0xf0>;
-
-			clocks = <&clk_sysin>;
-			clock-output-names = "clk-m-main-vidfs",
-					     "clk-m-hva-fs",
-					     "clk-m-fvdp-vcpu",
-					     "clk-m-fvdp-proc-fs";
-		};
-
-		clk_m_fvdp_proc: clk-m-fvdp-proc@fd320910 {
-			#clock-cells = <0>;
-			compatible = "st,stih416-clkgenf-vcc-fvdp", "st,clkgen-mux";
-			reg = <0xfd320910 0x4>; /* SYSCFG8580 */
-
-			clocks = <&clk_m_a1_div2 0>,
-				 <&clockgen_f 3>;
-		};
-
-		clk_m_hva: clk-m-hva@fd690868 {
-			#clock-cells = <0>;
-			compatible = "st,stih416-clkgenf-vcc-hva", "st,clkgen-mux";
-			reg = <0xfd690868 0x4>; /* SYSCFG9538 */
-
-			clocks = <&clockgen_f 1>,
-				 <&clk_m_a1_div0 3>;
-		};
-
-		clk_m_f_vcc_hd: clk-m-f-vcc-hd@fd32086c {
-			#clock-cells = <0>;
-			compatible = "st,stih416-clkgenf-vcc-hd", "st,clkgen-mux";
-			reg = <0xfd32086c 0x4>; /* SYSCFG8539 */
-
-			clocks = <&clockgen_c_vcc 7>,
-				 <&clockgen_f 0>;
-		};
-
-		clk_m_f_vcc_sd: clk-m-f-vcc-sd@fd32086c {
-			#clock-cells = <0>;
-			compatible = "st,stih416-clkgenf-vcc-sd", "st,clkgen-mux";
-			reg = <0xfd32086c 0x4>; /* SYSCFG8539 */
-
-			clocks = <&clockgen_c_vcc 8>,
-				 <&clockgen_f 1>;
-		};
-
-		/*
-		 * Add a dummy clock for the HDMIRx external signal clock
-		 */
-		clk_m_pix_hdmirx_sas: clk-m-pix-hdmirx-sas {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-			clock-frequency = <0>;
-		};
-
-		clockgen_f_vcc: clockgen-f-vcc@fd32086c {
-			#clock-cells = <1>;
-			compatible = "st,stih416-clkgenf", "st,clkgen-vcc";
-			reg = <0xfd32086c 0xc>; /* SYSCFG8539,8540,8541 */
-
-			clocks = <&clk_m_f_vcc_hd>,
-				 <&clk_m_f_vcc_sd>,
-				 <&clockgen_f 0>,
-				 <&clk_m_pix_hdmirx_sas>;
-
-			clock-output-names  = "clk-m-pix-main-pipe",
-					      "clk-m-pix-aux-pipe",
-					      "clk-m-pix-main-cru",
-					      "clk-m-pix-aux-cru",
-					      "clk-m-xfer-be-compo",
-					      "clk-m-xfer-pip-compo",
-					      "clk-m-xfer-aux-compo",
-					      "clk-m-vsens",
-					      "clk-m-pix-hdmirx-0",
-					      "clk-m-pix-hdmirx-1";
-		};
-
-		/*
-		 * DDR PLL
-		 */
-		clockgen-ddr@0xfdde07d8 {
-			reg = <0xfdde07d8 0x110>;
-
-			clockgen_ddr_pll: clockgen-ddr-pll {
-				#clock-cells = <1>;
-				compatible = "st,stih416-plls-c32-ddr", "st,clkgen-plls-c32";
-
-				clocks = <&clk_sysin>;
-				clock-output-names = "clockgen-ddr0",
-						     "clockgen-ddr1";
-			};
-		};
-
-		/*
-		 * GPU PLL
-		 */
-		clockgen-gpu@fd68ff00 {
-			reg = <0xfd68ff00 0x910>;
-
-			clockgen_gpu_pll: clockgen-gpu-pll {
-				#clock-cells = <1>;
-				compatible = "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32";
-
-				clocks = <&clk_sysin>;
-				clock-output-names = "clockgen-gpu-pll";
-			};
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih416.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih416.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,517 +0,0 @@
-/*
- * Copyright (C) 2012 STMicroelectronics Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-#include "stih41x.dtsi"
-#include "stih416-clock.dtsi"
-#include "stih416-pinctrl.dtsi"
-
-#include <dt-bindings/phy/phy.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/reset/stih416-resets.h>
-#include <dt-bindings/interrupt-controller/irq-st.h>
-/ {
-	L2: cache-controller {
-		compatible = "arm,pl310-cache";
-		reg = <0xfffe2000 0x1000>;
-		arm,data-latency = <3 3 3>;
-		arm,tag-latency = <2 2 2>;
-		cache-unified;
-		cache-level = <2>;
-	};
-
-	arm-pmu {
-		compatible = "arm,cortex-a9-pmu";
-		interrupt-parent = <&intc>;
-		interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
-	};
-
-	soc {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		interrupt-parent = <&intc>;
-		ranges;
-		compatible	= "simple-bus";
-
-		restart {
-			compatible = "st,stih416-restart";
-			st,syscfg = <&syscfg_sbc>;
-			status = "okay";
-		};
-
-		powerdown: powerdown-controller {
-			#reset-cells = <1>;
-			compatible = "st,stih416-powerdown";
-		};
-
-		softreset: softreset-controller {
-			#reset-cells = <1>;
-			compatible = "st,stih416-softreset";
-		};
-
-		syscfg_sbc:sbc-syscfg@fe600000{
-			compatible	= "st,stih416-sbc-syscfg", "syscon";
-			reg		= <0xfe600000 0x1000>;
-		};
-
-		syscfg_front:front-syscfg@fee10000{
-			compatible	= "st,stih416-front-syscfg", "syscon";
-			reg		= <0xfee10000 0x1000>;
-		};
-
-		syscfg_rear:rear-syscfg@fe830000{
-			compatible	= "st,stih416-rear-syscfg", "syscon";
-			reg		= <0xfe830000 0x1000>;
-		};
-
-		/* MPE */
-		syscfg_fvdp_fe:fvdp-fe-syscfg@fddf0000{
-			compatible	= "st,stih416-fvdp-fe-syscfg", "syscon";
-			reg		= <0xfddf0000 0x1000>;
-		};
-
-		syscfg_fvdp_lite:fvdp-lite-syscfg@fd6a0000{
-			compatible	= "st,stih416-fvdp-lite-syscfg", "syscon";
-			reg		= <0xfd6a0000 0x1000>;
-		};
-
-		syscfg_cpu:cpu-syscfg@fdde0000{
-			compatible	= "st,stih416-cpu-syscfg", "syscon";
-			reg		= <0xfdde0000 0x1000>;
-		};
-
-		syscfg_compo:compo-syscfg@fd320000{
-			compatible	= "st,stih416-compo-syscfg", "syscon";
-			reg		= <0xfd320000 0x1000>;
-		};
-
-		syscfg_transport:transport-syscfg@fd690000{
-			compatible	= "st,stih416-transport-syscfg", "syscon";
-			reg		= <0xfd690000 0x1000>;
-		};
-
-		syscfg_lpm:lpm-syscfg@fe4b5100{
-			compatible	= "st,stih416-lpm-syscfg", "syscon";
-			reg		= <0xfe4b5100 0x8>;
-		};
-
-		irq-syscfg {
-			compatible    = "st,stih416-irq-syscfg";
-			st,syscfg     = <&syscfg_cpu>;
-			st,irq-device = <ST_IRQ_SYSCFG_PMU_0>,
-					<ST_IRQ_SYSCFG_PMU_1>;
-			st,fiq-device = <ST_IRQ_SYSCFG_DISABLED>,
-					<ST_IRQ_SYSCFG_DISABLED>;
-		};
-
-		serial2: serial@fed32000{
-			compatible	= "st,asc";
-			status 		= "disabled";
-			reg		= <0xfed32000 0x2c>;
-			interrupts	= <0 197 0>;
-			clocks 		= <&clk_s_a0_ls CLK_ICN_REG>;
-			pinctrl-names 	= "default";
-			pinctrl-0 	= <&pinctrl_serial2 &pinctrl_serial2_oe>;
-		};
-
-		/* SBC_UART1 */
-		sbc_serial1: serial@fe531000 {
-			compatible	= "st,asc";
-			status 		= "disabled";
-			reg		= <0xfe531000 0x2c>;
-			interrupts	= <0 210 0>;
-			pinctrl-names 	= "default";
-			pinctrl-0 	= <&pinctrl_sbc_serial1>;
-			clocks		= <&clk_sysin>;
-		};
-
-		i2c@fed40000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfed40000 0x110>;
-			interrupts	= <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
-			clocks 		= <&clk_s_a0_ls CLK_ICN_REG>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_i2c0_default>;
-
-			status		= "disabled";
-		};
-
-		i2c@fed41000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfed41000 0x110>;
-			interrupts	= <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
-			clocks 		= <&clk_s_a0_ls CLK_ICN_REG>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_i2c1_default>;
-
-			status		= "disabled";
-		};
-
-		i2c@fe540000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfe540000 0x110>;
-			interrupts	= <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&clk_sysin>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_sbc_i2c0_default>;
-
-			status		= "disabled";
-		};
-
-		i2c@fe541000 {
-			compatible	= "st,comms-ssc4-i2c";
-			reg		= <0xfe541000 0x110>;
-			interrupts	= <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
-			clocks		= <&clk_sysin>;
-			clock-names	= "ssc";
-			clock-frequency = <400000>;
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_sbc_i2c1_default>;
-
-			status		= "disabled";
-		};
-
-		ethernet0: dwmac@fe810000 {
-			device_type 	= "network";
-			compatible	= "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710";
-			status 		= "disabled";
-			reg		= <0xfe810000 0x8000>;
-			reg-names	= "stmmaceth";
-
-			interrupts = <0 133 0>, <0 134 0>, <0 135 0>;
-			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
-
-			snps,pbl 	= <32>;
-			snps,mixed-burst;
-
-			st,syscon		= <&syscfg_rear 0x8bc>;
-			resets			= <&softreset STIH416_ETH0_SOFTRESET>;
-			reset-names		= "stmmaceth";
-			pinctrl-names 	= "default";
-			pinctrl-0	= <&pinctrl_mii0>;
-			clock-names	= "stmmaceth", "sti-ethclk";
-			clocks		= <&clk_s_a1_ls CLK_ICN_IF_2>, <&clk_s_a1_ls CLK_GMAC0_PHY>;
-		};
-
-		ethernet1: dwmac@fef08000 {
-			device_type = "network";
-			compatible		= "st,stih416-dwmac", "snps,dwmac", "snps,dwmac-3.710";
-			status 		= "disabled";
-			reg		= <0xfef08000 0x8000>;
-			reg-names	= "stmmaceth";
-			interrupts = <0 136 0>, <0 137 0>, <0 138 0>;
-			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
-
-			snps,pbl	= <32>;
-			snps,mixed-burst;
-
-			st,syscon	= <&syscfg_sbc 0x7f0>;
-
-			resets		= <&softreset STIH416_ETH1_SOFTRESET>;
-			reset-names	= "stmmaceth";
-			pinctrl-names 	= "default";
-			pinctrl-0	= <&pinctrl_mii1>;
-			clock-names	= "stmmaceth", "sti-ethclk";
-			clocks		= <&clk_s_a0_ls CLK_ICN_REG>, <&clk_s_a0_ls CLK_ETH1_PHY>;
-		};
-
-		rc: rc@fe518000 {
-			compatible	= "st,comms-irb";
-			reg		= <0xfe518000 0x234>;
-			interrupts	=  <0 203 0>;
-			rx-mode         = "infrared";
-			clocks		= <&clk_sysin>;
-			pinctrl-names 	= "default";
-			pinctrl-0	= <&pinctrl_ir>;
-			resets		= <&softreset STIH416_IRB_SOFTRESET>;
-		};
-
-		/* FSM */
-		spifsm: spifsm@fe902000 {
-			compatible	   = "st,spi-fsm";
-			reg		   = <0xfe902000 0x1000>;
-			pinctrl-0	   = <&pinctrl_fsm>;
-
-			st,syscfg	   = <&syscfg_rear>;
-			st,boot-device-reg = <0x958>;
-			st,boot-device-spi = <0x1a>;
-
-			status = "disabled";
-		};
-
-		keyscan: keyscan@fe4b0000 {
-			compatible = "st,sti-keyscan";
-			status = "disabled";
-			reg = <0xfe4b0000 0x2000>;
-			interrupts = <GIC_SPI 212 IRQ_TYPE_NONE>;
-			clocks = <&clk_sysin>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_keyscan>;
-			resets	= <&powerdown STIH416_KEYSCAN_POWERDOWN>,
-				  <&softreset STIH416_KEYSCAN_SOFTRESET>;
-		};
-
-		temp0 {
-			compatible = "st,stih416-sas-thermal";
-			clock-names = "thermal";
-			clocks = <&clockgen_c_vcc 14>;
-
-			status = "okay";
-		};
-
-		temp1@fdfe8000 {
-			compatible = "st,stih416-mpe-thermal";
-			reg = <0xfdfe8000 0x10>;
-			clocks = <&clockgen_e 3>;
-			clock-names = "thermal";
-			interrupts = <GIC_SPI 23 IRQ_TYPE_EDGE_RISING>;
-
-			status = "okay";
-		};
-
-		mmc0: sdhci@fe81e000 {
-			compatible	= "st,sdhci";
-			status		= "disabled";
-			reg		= <0xfe81e000 0x1000>;
-			interrupts	= <GIC_SPI 127 IRQ_TYPE_NONE>;
-			interrupt-names	= "mmcirq";
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_mmc0>;
-			clock-names	= "mmc";
-			clocks		= <&clk_s_a1_ls 1>;
-		};
-
-		mmc1: sdhci@fe81f000 {
-			compatible	= "st,sdhci";
-			status		= "disabled";
-			reg		= <0xfe81f000 0x1000>;
-			interrupts	= <GIC_SPI 128 IRQ_TYPE_NONE>;
-			interrupt-names	= "mmcirq";
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_mmc1>;
-			clock-names	= "mmc";
-			clocks		= <&clk_s_a1_ls 8>;
-		};
-
-		miphy365x_phy: phy@fe382000 {
-			compatible      = "st,miphy365x-phy";
-			st,syscfg	= <&syscfg_rear 0x824 0x828>;
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			ranges;
-
-			phy_port0: port@fe382000 {
-				#phy-cells = <1>;
-				reg = <0xfe382000 0x100>, <0xfe394000 0x100>;
-				reg-names = "sata", "pcie";
-			};
-
-			phy_port1: port@fe38a000 {
-				#phy-cells = <1>;
-				reg = <0xfe38a000 0x100>, <0xfe804000 0x100>;
-				reg-names = "sata", "pcie";
-			};
-		};
-
-		sata0: sata@fe380000 {
-			compatible      = "st,sti-ahci";
-			reg             = <0xfe380000 0x1000>;
-			interrupts      = <GIC_SPI 157 IRQ_TYPE_NONE>;
-			interrupt-names = "hostc";
-			phys	        = <&phy_port0 PHY_TYPE_SATA>;
-			phy-names       = "sata-phy";
-			resets	        = <&powerdown STIH416_SATA0_POWERDOWN>,
-					  <&softreset STIH416_SATA0_SOFTRESET>;
-			reset-names     = "pwr-dwn", "sw-rst";
-			clock-names     = "ahci_clk";
-			clocks	        = <&clk_s_a0_ls CLK_ICN_REG>;
-
-			status	        = "disabled";
-		};
-
-		usb2_phy: phy@0 {
-			compatible = "st,stih416-usb-phy";
-			#phy-cells = <0>;
-			st,syscfg = <&syscfg_rear>;
-			clocks = <&clk_sysin>;
-			clock-names = "osc_phy";
-		};
-
-		ehci0: usb@fe1ffe00 {
-			compatible = "st,st-ehci-300x";
-			reg = <0xfe1ffe00 0x100>;
-			interrupts = <GIC_SPI 148 IRQ_TYPE_NONE>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usb0>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			resets = <&powerdown STIH416_USB0_POWERDOWN>,
-				 <&softreset STIH416_USB0_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		ohci0: usb@fe1ffc00 {
-			compatible = "st,st-ohci-300x";
-			reg = <0xfe1ffc00 0x100>;
-			interrupts = <GIC_SPI 149 IRQ_TYPE_NONE>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			status = "okay";
-			resets = <&powerdown STIH416_USB0_POWERDOWN>,
-				 <&softreset STIH416_USB0_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		ehci1: usb@fe203e00 {
-			compatible = "st,st-ehci-300x";
-			reg = <0xfe203e00 0x100>;
-			interrupts = <GIC_SPI 150 IRQ_TYPE_NONE>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usb1>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			resets = <&powerdown STIH416_USB1_POWERDOWN>,
-				 <&softreset STIH416_USB1_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		ohci1: usb@fe203c00 {
-			compatible = "st,st-ohci-300x";
-			reg = <0xfe203c00 0x100>;
-			interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			resets = <&powerdown STIH416_USB1_POWERDOWN>,
-				 <&softreset STIH416_USB1_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		ehci2: usb@fe303e00 {
-			compatible = "st,st-ehci-300x";
-			reg = <0xfe303e00 0x100>;
-			interrupts = <GIC_SPI 152 IRQ_TYPE_NONE>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usb2>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			resets = <&powerdown STIH416_USB2_POWERDOWN>,
-				 <&softreset STIH416_USB2_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		ohci2: usb@fe303c00 {
-			compatible = "st,st-ohci-300x";
-			reg = <0xfe303c00 0x100>;
-			interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			resets = <&powerdown STIH416_USB2_POWERDOWN>,
-				 <&softreset STIH416_USB2_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		ehci3: usb@fe343e00 {
-			compatible = "st,st-ehci-300x";
-			reg = <0xfe343e00 0x100>;
-			interrupts = <GIC_SPI 154 IRQ_TYPE_NONE>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_usb3>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			resets = <&powerdown STIH416_USB3_POWERDOWN>,
-				 <&softreset STIH416_USB3_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		ohci3: usb@fe343c00 {
-			compatible = "st,st-ohci-300x";
-			reg = <0xfe343c00 0x100>;
-			interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>;
-			clocks = <&clk_s_a1_ls 0>,
-				 <&clockgen_b0 0>;
-			clock-names = "ic", "clk48";
-			phys = <&usb2_phy>;
-			phy-names = "usb";
-			resets = <&powerdown STIH416_USB3_POWERDOWN>,
-				 <&softreset STIH416_USB3_SOFTRESET>;
-			reset-names = "power", "softreset";
-		};
-
-		/* SAS PWM Module */
-		pwm0: pwm@fed10000 {
-			compatible	= "st,sti-pwm";
-			status		= "disabled";
-			#pwm-cells	= <2>;
-			reg		= <0xfed10000 0x68>;
-			interrupts      = <GIC_SPI 200 IRQ_TYPE_NONE>;
-
-			pinctrl-names	= "default";
-			pinctrl-0 = 	<&pinctrl_pwm0_chan0_default
-					&pinctrl_pwm0_chan1_default
-					&pinctrl_pwm0_chan2_default
-					&pinctrl_pwm0_chan3_default>;
-
-			clock-names	= "pwm", "capture";
-			clocks		= <&clk_sysin>, <&clk_s_a0_ls CLK_ICN_REG>;
-
-			st,pwm-num-chan = <4>;
-			st,capture-num-chan = <2>;
-		};
-
-		/* SBC PWM Module */
-		pwm1: pwm@fe510000 {
-			compatible	= "st,sti-pwm";
-			status		= "disabled";
-			#pwm-cells	= <2>;
-			reg		= <0xfe510000 0x68>;
-			interrupts      = <GIC_SPI 202 IRQ_TYPE_NONE>;
-
-			pinctrl-names	= "default";
-			pinctrl-0	= <&pinctrl_pwm1_chan0_default
-					/*
-					 * Shared with SBC_OBS_NOTRST.  Don't
-					 * enable unless you really know what
-					 * you're doing.
-					 *
-					 * &pinctrl_pwm1_chan1_default
-					 */
-					&pinctrl_pwm1_chan2_default
-					&pinctrl_pwm1_chan3_default>;
-
-			clock-names	= "pwm";
-			clocks		= <&clk_sysin>;
-			st,pwm-num-chan = <3>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih416-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih416-pinctrl.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,692 +0,0 @@
-
-/*
- * Copyright (C) 2013 STMicroelectronics Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-#include "st-pincfg.h"
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-/ {
-
-	aliases {
-		gpio0	= &pio0;
-		gpio1	= &pio1;
-		gpio2	= &pio2;
-		gpio3	= &pio3;
-		gpio4	= &pio4;
-		gpio5	= &pio40;
-		gpio6	= &pio5;
-		gpio7	= &pio6;
-		gpio8	= &pio7;
-		gpio9	= &pio8;
-		gpio10	= &pio9;
-		gpio11	= &pio10;
-		gpio12	= &pio11;
-		gpio13	= &pio12;
-		gpio14	= &pio30;
-		gpio15	= &pio31;
-		gpio16	= &pio13;
-		gpio17	= &pio14;
-		gpio18	= &pio15;
-		gpio19	= &pio16;
-		gpio20	= &pio17;
-		gpio21	= &pio18;
-		gpio22	= &pio100;
-		gpio23	= &pio101;
-		gpio24	= &pio102;
-		gpio25	= &pio103;
-		gpio26	= &pio104;
-		gpio27	= &pio105;
-		gpio28	= &pio106;
-		gpio29	= &pio107;
-	};
-
-	soc {
-		pin-controller-sbc {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih416-sbc-pinctrl";
-			st,syscfg	= <&syscfg_sbc>;
-			reg 		= <0xfe61f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges		= <0 0xfe610000 0x6000>;
-
-			pio0: gpio@fe610000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO0";
-			};
-			pio1: gpio@fe611000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO1";
-			};
-			pio2: gpio@fe612000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO2";
-			};
-			pio3: gpio@fe613000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO3";
-			};
-			pio4: gpio@fe614000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO4";
-			};
-			pio40: gpio@fe615000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x5000 0x100>;
-				st,bank-name	= "PIO40";
-				st,retime-pin-mask = <0x7f>;
-			};
-
-			rc{
-				pinctrl_ir: ir0 {
-					st,pins {
-						ir = <&pio4 0 ALT2 IN>;
-					};
-				};
-			};
-			sbc_serial1 {
-				pinctrl_sbc_serial1: sbc_serial1 {
-					st,pins {
-						tx	= <&pio2 6 ALT3 OUT>;
-						rx	= <&pio2 7 ALT3 IN>;
-					};
-				};
-			};
-
-			keyscan {
-				pinctrl_keyscan: keyscan {
-					st,pins {
-						keyin0 = <&pio0 2 ALT2 IN>;
-						keyin1 = <&pio0 3 ALT2 IN>;
-						keyin2 = <&pio0 4 ALT2 IN>;
-						keyin3 = <&pio2 6 ALT2 IN>;
-
-						keyout0 = <&pio1 6 ALT2 OUT>;
-						keyout1 = <&pio1 7 ALT2 OUT>;
-						keyout2 = <&pio0 6 ALT2 OUT>;
-						keyout3 = <&pio2 7 ALT2 OUT>;
-					};
-				};
-			};
-
-			sbc_i2c0 {
-				pinctrl_sbc_i2c0_default: sbc_i2c0-default {
-					st,pins {
-						sda = <&pio4 6 ALT1 BIDIR>;
-						scl = <&pio4 5 ALT1 BIDIR>;
-					};
-				};
-			};
-
-			usb {
-				pinctrl_usb3: usb3 {
-					st,pins {
-						oc-detect = <&pio40 0 ALT1 IN>;
-						pwr-enable = <&pio40 1 ALT1 OUT>;
-					};
-				};
-			};
-
-			sbc_i2c1 {
-				pinctrl_sbc_i2c1_default: sbc_i2c1-default {
-					st,pins {
-						sda = <&pio3 2 ALT2 BIDIR>;
-						scl = <&pio3 1 ALT2 BIDIR>;
-					};
-				};
-			};
-
-			gmac1 {
-				pinctrl_mii1: mii1 {
-					st,pins {
-						txd0 = <&pio0 0 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-						txd1 = <&pio0 1 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-						txd2 = <&pio0 2 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-						txd3 = <&pio0 3 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-						txer = <&pio0 4 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-						txen = <&pio0 5 ALT1 OUT SE_NICLK_IO 0 CLK_A>;
-						txclk = <&pio0 6 ALT1 IN NICLK 0 CLK_A>;
-						col =   <&pio0 7 ALT1 IN BYPASS 1000>;
-
-						mdio =  <&pio1 0 ALT1 OUT BYPASS 1500>;
-						mdc =   <&pio1 1 ALT1 OUT NICLK 0 CLK_A>;
-						crs =   <&pio1 2 ALT1 IN BYPASS 1000>;
-						mdint = <&pio1 3 ALT1 IN BYPASS 0>;
-						rxd0 =  <&pio1 4 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-						rxd1 =  <&pio1 5 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-						rxd2 =  <&pio1 6 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-						rxd3 =  <&pio1 7 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-
-						rxdv =  <&pio2 0 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-						rx_er = <&pio2 1 ALT1 IN SE_NICLK_IO 0 CLK_A>;
-						rxclk = <&pio2 2 ALT1 IN NICLK 0 CLK_A>;
-						phyclk = <&pio2 3 ALT1 OUT NICLK 0 CLK_A>;
-					};
-				};
-				pinctrl_rgmii1: rgmii1-0 {
-					st,pins {
-						txd0 =  <&pio0 0 ALT1 OUT DE_IO 500 CLK_A>;
-						txd1 =  <&pio0 1 ALT1 OUT DE_IO 500 CLK_A>;
-						txd2 =  <&pio0 2 ALT1 OUT DE_IO 500 CLK_A>;
-						txd3 =  <&pio0 3 ALT1 OUT DE_IO 500 CLK_A>;
-						txen =  <&pio0 5 ALT1 OUT DE_IO 0   CLK_A>;
-						txclk = <&pio0 6 ALT1 IN  NICLK 0   CLK_A>;
-
-						mdio = <&pio1 0 ALT1 OUT BYPASS 0>;
-						mdc  = <&pio1 1 ALT1 OUT NICLK  0 CLK_A>;
-						rxd0 = <&pio1 4 ALT1 IN DE_IO 500 CLK_A>;
-						rxd1 = <&pio1 5 ALT1 IN DE_IO 500 CLK_A>;
-						rxd2 = <&pio1 6 ALT1 IN DE_IO 500 CLK_A>;
-						rxd3 = <&pio1 7 ALT1 IN DE_IO 500 CLK_A>;
-
-						rxdv   = <&pio2 0 ALT1 IN  DE_IO 500 CLK_A>;
-						rxclk  = <&pio2 2 ALT1 IN  NICLK 0   CLK_A>;
-						phyclk = <&pio2 3 ALT4 OUT NICLK 0   CLK_B>;
-
-						clk125= <&pio3 7 ALT4 IN NICLK 0 CLK_A>;
-					};
-				};
-			};
-
-			pwm1 {
-				pinctrl_pwm1_chan0_default: pwm1-0-default {
-					st,pins {
-						pwm-out    = <&pio3 0 ALT1 OUT>;
-						pwm-capturein = <&pio3 2 ALT1 IN>;
-
-					};
-				};
-				pinctrl_pwm1_chan1_default: pwm1-1-default {
-					st,pins {
-						pwm-out    = <&pio4 4 ALT1 OUT>;
-						pwm-capturein = <&pio4 3 ALT1 IN>;
-					};
-				};
-				pinctrl_pwm1_chan2_default: pwm1-2-default {
-					st,pins {
-						pwm-out    = <&pio4 6 ALT3 OUT>;
-					};
-				};
-				pinctrl_pwm1_chan3_default: pwm1-3-default {
-					st,pins {
-						pwm-out    = <&pio4 7 ALT3 OUT>;
-					};
-				};
-			};
-		};
-
-		pin-controller-front {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih416-front-pinctrl";
-			st,syscfg	= <&syscfg_front>;
-			reg 		= <0xfee0f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges		= <0 0xfee00000 0x10000>;
-
-			pio5: gpio@fee00000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO5";
-			};
-			pio6: gpio@fee01000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO6";
-			};
-			pio7: gpio@fee02000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO7";
-			};
-			pio8: gpio@fee03000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO8";
-			};
-			pio9: gpio@fee04000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO9";
-			};
-			pio10: gpio@fee05000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x5000 0x100>;
-				st,bank-name	= "PIO10";
-			};
-			pio11: gpio@fee06000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x6000 0x100>;
-				st,bank-name	= "PIO11";
-			};
-			pio12: gpio@fee07000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x7000 0x100>;
-				st,bank-name	= "PIO12";
-			};
-			pio30: gpio@fee08000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x8000 0x100>;
-				st,bank-name	= "PIO30";
-			};
-			pio31: gpio@fee09000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x9000 0x100>;
-				st,bank-name	= "PIO31";
-			};
-
-			pwm0 {
-				pinctrl_pwm0_chan0_default: pwm0-0-default {
-					st,pins {
-						pwm-out    = <&pio9 7 ALT2 OUT>;
-						pwm-capturein = <&pio9 6 ALT2 IN>;
-					};
-				};
-			};
-
-			serial2-oe {
-				pinctrl_serial2_oe: serial2-1 {
-					st,pins {
-						output-enable	= <&pio11 3 ALT2 OUT>;
-					};
-				};
-			};
-
-			i2c0 {
-				pinctrl_i2c0_default: i2c0-default {
-					st,pins {
-						sda = <&pio9 3 ALT1 BIDIR>;
-						scl = <&pio9 2 ALT1 BIDIR>;
-					};
-				};
-			};
-
-			usb {
-				pinctrl_usb0: usb0 {
-					st,pins {
-						oc-detect = <&pio9 4 ALT1 IN>;
-						pwr-enable = <&pio9 5 ALT1 OUT>;
-					};
-				};
-			};
-
-
-			i2c1 {
-				pinctrl_i2c1_default: i2c1-default {
-					st,pins {
-						sda = <&pio12 1 ALT1 BIDIR>;
-						scl = <&pio12 0 ALT1 BIDIR>;
-					};
-				};
-			};
-
-			fsm {
-				pinctrl_fsm: fsm {
-					st,pins {
-						spi-fsm-clk  = <&pio12 2 ALT1 OUT>;
-						spi-fsm-cs   = <&pio12 3 ALT1 OUT>;
-						spi-fsm-mosi = <&pio12 4 ALT1 OUT>;
-						spi-fsm-miso = <&pio12 5 ALT1 IN>;
-						spi-fsm-hol  = <&pio12 6 ALT1 OUT>;
-						spi-fsm-wp   = <&pio12 7 ALT1 OUT>;
-					};
-				};
-			};
-		};
-
-		pin-controller-rear {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih416-rear-pinctrl";
-			st,syscfg	= <&syscfg_rear>;
-			reg 		= <0xfe82f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges 		= <0 0xfe820000 0x6000>;
-
-			pio13: gpio@fe820000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO13";
-			};
-			pio14: gpio@fe821000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO14";
-			};
-			pio15: gpio@fe822000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO15";
-			};
-			pio16: gpio@fe823000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO16";
-			};
-			pio17: gpio@fe824000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO17";
-			};
-			pio18: gpio@fe825000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x5000 0x100>;
-				st,bank-name	= "PIO18";
-				st,retime-pin-mask = <0xf>;
-			};
-
-			serial2 {
-				pinctrl_serial2: serial2-0 {
-					st,pins {
-						tx	= <&pio17 4 ALT2 OUT>;
-						rx	= <&pio17 5 ALT2 IN>;
-					};
-				};
-			};
-
-			gmac0 {
-				pinctrl_mii0: mii0 {
-					st,pins {
-						mdint = <&pio13 6 ALT2 IN  BYPASS      0>;
-						txen =  <&pio13 7 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-						txd0 =  <&pio14 0 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-						txd1 =  <&pio14 1 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-						txd2 =  <&pio14 2 ALT2 OUT SE_NICLK_IO 0 CLK_B>;
-						txd3 =  <&pio14 3 ALT2 OUT SE_NICLK_IO 0 CLK_B>;
-
-						txclk = <&pio15 0 ALT2 IN  NICLK       0 CLK_A>;
-						txer =  <&pio15 1 ALT2 OUT SE_NICLK_IO 0 CLK_A>;
-						crs = <&pio15 2 ALT2 IN  BYPASS 1000>;
-						col = <&pio15 3 ALT2 IN  BYPASS 1000>;
-						mdio= <&pio15 4 ALT2 OUT BYPASS 1500>;
-						mdc = <&pio15 5 ALT2 OUT NICLK  0    CLK_B>;
-
-						rxd0 =  <&pio16 0 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-						rxd1 =  <&pio16 1 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-						rxd2 =  <&pio16 2 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-						rxd3 =  <&pio16 3 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-						rxdv =  <&pio15 6 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-						rx_er = <&pio15 7 ALT2 IN SE_NICLK_IO 0 CLK_A>;
-						rxclk = <&pio17 0 ALT2 IN NICLK 0 CLK_A>;
-						phyclk = <&pio13 5 ALT2 OUT NICLK 0 CLK_B>;
-					};
-				};
-
-				pinctrl_gmii0: gmii0 {
-					st,pins {
-						};
-				};
-				pinctrl_rgmii0: rgmii0 {
-					st,pins {
-						 phyclk = <&pio13  5 ALT4 OUT NICLK 0 CLK_B>;
-						 txen = <&pio13 7 ALT2 OUT DE_IO 0 CLK_A>;
-						 txd0  = <&pio14 0 ALT2 OUT DE_IO 500 CLK_A>;
-						 txd1  = <&pio14 1 ALT2 OUT DE_IO 500 CLK_A>;
-						 txd2  = <&pio14 2 ALT2 OUT DE_IO 500 CLK_B>;
-						 txd3  = <&pio14 3 ALT2 OUT DE_IO 500 CLK_B>;
-						 txclk = <&pio15 0 ALT2 IN NICLK 0 CLK_A>;
-
-						 mdio = <&pio15 4 ALT2 OUT BYPASS 0>;
-						 mdc = <&pio15 5 ALT2 OUT NICLK 0 CLK_B>;
-
-						 rxdv = <&pio15 6 ALT2 IN DE_IO 500 CLK_A>;
-						 rxd0 =<&pio16 0 ALT2 IN DE_IO	500 CLK_A>;
-						 rxd1 =<&pio16 1 ALT2 IN DE_IO	500 CLK_A>;
-						 rxd2 =<&pio16 2 ALT2 IN DE_IO	500 CLK_A>;
-						 rxd3  =<&pio16 3 ALT2 IN DE_IO 500 CLK_A>;
-						 rxclk =<&pio17 0 ALT2 IN NICLK 0 CLK_A>;
-
-						 clk125=<&pio17 6 ALT1 IN NICLK 0 CLK_A>;
-					};
-				};
-			};
-
-			mmc0 {
-				pinctrl_mmc0: mmc0 {
-					st,pins {
-						mmcclk  = <&pio13 4 ALT4 BIDIR_PU NICLK 0 CLK_B>;
-						data0   = <&pio14 4 ALT4 BIDIR_PU BYPASS 0>;
-						data1   = <&pio14 5 ALT4 BIDIR_PU BYPASS 0>;
-						data2   = <&pio14 6 ALT4 BIDIR_PU BYPASS 0>;
-						data3   = <&pio14 7 ALT4 BIDIR_PU BYPASS 0>;
-						cmd     = <&pio15 1 ALT4 BIDIR_PU BYPASS 0>;
-						wp      = <&pio15 3 ALT4 IN>;
-						data4   = <&pio16 4 ALT4 BIDIR_PU BYPASS 0>;
-						data5   = <&pio16 5 ALT4 BIDIR_PU BYPASS 0>;
-						data6   = <&pio16 6 ALT4 BIDIR_PU BYPASS 0>;
-						data7   = <&pio16 7 ALT4 BIDIR_PU BYPASS 0>;
-						pwr     = <&pio17 1 ALT4 OUT>;
-						cd      = <&pio17 2 ALT4 IN>;
-						led     = <&pio17 3 ALT4 OUT>;
-					};
-				};
-			};
-			mmc1 {
-				pinctrl_mmc1: mmc1 {
-					st,pins {
-						mmcclk  = <&pio15 0 ALT3 BIDIR_PU NICLK 0 CLK_B>;
-						data0   = <&pio13 7 ALT3 BIDIR_PU BYPASS 0>;
-						data1   = <&pio14 1 ALT3 BIDIR_PU BYPASS 0>;
-						data2   = <&pio14 2 ALT3 BIDIR_PU BYPASS 0>;
-						data3   = <&pio14 3 ALT3 BIDIR_PU BYPASS 0>;
-						cmd     = <&pio15 4 ALT3 BIDIR_PU BYPASS 0>;
-						data4   = <&pio15 6 ALT3 BIDIR_PU BYPASS 0>;
-						data5   = <&pio15 7 ALT3 BIDIR_PU BYPASS 0>;
-						data6   = <&pio16 0 ALT3 BIDIR_PU BYPASS 0>;
-						data7   = <&pio16 1 ALT3 BIDIR_PU BYPASS 0>;
-						pwr     = <&pio16 2 ALT3 OUT>;
-						nreset  = <&pio13 6 ALT3 OUT>;
-					};
-				};
-			};
-
-			usb {
-				pinctrl_usb1: usb1 {
-					st,pins {
-						oc-detect = <&pio18 0 ALT1 IN>;
-						pwr-enable = <&pio18 1 ALT1 OUT>;
-					};
-				};
-				pinctrl_usb2: usb2 {
-					st,pins {
-						oc-detect = <&pio18 2 ALT1 IN>;
-						pwr-enable = <&pio18 3 ALT1 OUT>;
-					};
-				};
-			};
-
-			pwm0 {
-				pinctrl_pwm0_chan1_default: pwm0-1-default {
-					st,pins {
-						pwm-out    = <&pio13 2 ALT2 OUT>;
-						pwm-capturein = <&pio13 1 ALT2 IN>;
-					};
-				};
-				pinctrl_pwm0_chan2_default: pwm0-2-default {
-					st,pins {
-						pwm-out    = <&pio15 2 ALT4 OUT>;
-					};
-				};
-				pinctrl_pwm0_chan3_default: pwm0-3-default {
-					st,pins {
-						pwm-out    = <&pio17 4 ALT1 OUT>;
-					};
-				};
-			};
-
-		};
-
-		pin-controller-fvdp-fe {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih416-fvdp-fe-pinctrl";
-			st,syscfg	= <&syscfg_fvdp_fe>;
-			reg 		= <0xfd6bf080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges		= <0 0xfd6b0000 0x3000>;
-
-			pio100: gpio@fd6b0000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO100";
-			};
-			pio101: gpio@fd6b1000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO101";
-			};
-			pio102: gpio@fd6b2000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO102";
-			};
-		};
-
-		pin-controller-fvdp-lite {
-			#address-cells	= <1>;
-			#size-cells	= <1>;
-			compatible	= "st,stih416-fvdp-lite-pinctrl";
-			st,syscfg		= <&syscfg_fvdp_lite>;
-			reg 		= <0xfd33f080 0x4>;
-			reg-names	= "irqmux";
-			interrupts 	= <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names	= "irqmux";
-			ranges			= <0 0xfd330000 0x5000>;
-
-			pio103: gpio@fd330000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0 0x100>;
-				st,bank-name	= "PIO103";
-			};
-			pio104: gpio@fd331000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x1000 0x100>;
-				st,bank-name	= "PIO104";
-			};
-			pio105: gpio@fd332000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x2000 0x100>;
-				st,bank-name	= "PIO105";
-			};
-			pio106: gpio@fd333000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x3000 0x100>;
-				st,bank-name	= "PIO106";
-			};
-
-			pio107: gpio@fd334000 {
-				gpio-controller;
-				#gpio-cells	= <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg		= <0x4000 0x100>;
-				st,bank-name	= "PIO107";
-				st,retime-pin-mask = <0xf>;
-			};
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x-b2000.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x-b2000.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x-b2000.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x-b2000.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/gpio/gpio.h>
-
-/ {
-
-	memory{
-		device_type = "memory";
-		reg = <0x60000000 0x40000000>;
-	};
-
-	chosen {
-		bootargs = "console=ttyAS0,115200 clk_ignore_unused";
-		linux,stdout-path = &serial2;
-	};
-
-	aliases {
-		ttyAS0 = &serial2;
-		ethernet0 = &ethernet0;
-		ethernet1 = &ethernet1;
-	};
-
-	soc {
-		serial2: serial@fed32000 {
-			status = "okay";
-		};
-
-		leds {
-			compatible	= "gpio-leds";
-			fp_led {
-				label	= "Front Panel LED";
-				gpios	= <&pio105 7 GPIO_ACTIVE_HIGH>;
-				linux,default-trigger	= "heartbeat";
-			};
-		};
-
-		/* HDMI Tx I2C */
-		i2c@fed41000 {
-			/* HDMI V1.3a supports Standard mode only */
-			clock-frequency = <100000>;
-			i2c-min-scl-pulse-width-us = <0>;
-			i2c-min-sda-pulse-width-us = <5>;
-
-			status = "okay";
-		};
-
-		ethernet0: dwmac@fe810000 {
-			status			= "okay";
-			phy-mode		= "mii";
-			pinctrl-0		= <&pinctrl_mii0>;
-
-			snps,reset-gpio 	= <&pio106 2>;
-			snps,reset-active-low;
-			snps,reset-delays-us 	= <0 10000 10000>;
-		};
-
-		ethernet1: dwmac@fef08000 {
-			status			= "disabled";
-			phy-mode		= "mii";
-			st,tx-retime-src	= "txclk";
-
-			snps,reset-gpio 	= <&pio4 7>;
-			snps,reset-active-low;
-			snps,reset-delays-us 	= <0 10000 10000>;
-		};
-
-		keyscan: keyscan@fe4b0000 {
-			keypad,num-rows = <4>;
-			keypad,num-columns = <4>;
-			st,debounce-us = <5000>;
-			linux,keymap = < MATRIX_KEY(0x00, 0x00, KEY_F13)
-					 MATRIX_KEY(0x00, 0x01, KEY_F9)
-					 MATRIX_KEY(0x00, 0x02, KEY_F5)
-					 MATRIX_KEY(0x00, 0x03, KEY_F1)
-					 MATRIX_KEY(0x01, 0x00, KEY_F14)
-					 MATRIX_KEY(0x01, 0x01, KEY_F10)
-					 MATRIX_KEY(0x01, 0x02, KEY_F6)
-					 MATRIX_KEY(0x01, 0x03, KEY_F2)
-					 MATRIX_KEY(0x02, 0x00, KEY_F15)
-					 MATRIX_KEY(0x02, 0x01, KEY_F11)
-					 MATRIX_KEY(0x02, 0x02, KEY_F7)
-					 MATRIX_KEY(0x02, 0x03, KEY_F3)
-					 MATRIX_KEY(0x03, 0x00, KEY_F16)
-					 MATRIX_KEY(0x03, 0x01, KEY_F12)
-					 MATRIX_KEY(0x03, 0x02, KEY_F8)
-					 MATRIX_KEY(0x03, 0x03, KEY_F4) >;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x-b2020.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x-b2020.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x-b2020.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x-b2020.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Srinivas Kandagatla <srinivas.kandagatla@st.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
- * publishhed by the Free Software Foundation.
- */
-#include "stih41x-b2020x.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-/ {
-	memory{
-		device_type = "memory";
-		reg = <0x40000000 0x80000000>;
-	};
-
-	chosen {
-		bootargs = "console=ttyAS0,115200 clk_ignore_unused";
-		linux,stdout-path = &sbc_serial1;
-	};
-
-	aliases {
-		ttyAS0 = &sbc_serial1;
-		ethernet1 = &ethernet1;
-	};
-	soc {
-		sbc_serial1: serial@fe531000 {
-			status = "okay";
-		};
-
-		leds {
-			compatible	= "gpio-leds";
-			red {
-				label	= "Front Panel LED";
-				gpios	= <&pio4 1 GPIO_ACTIVE_HIGH>;
-				linux,default-trigger	= "heartbeat";
-			};
-			green {
-				gpios	= <&pio4 7 GPIO_ACTIVE_HIGH>;
-				default-state = "off";
-			};
-		};
-
-		i2c@fed40000 {
-			status = "okay";
-		};
-
-		/* HDMI Tx I2C */
-		i2c@fed41000 {
-			/* HDMI V1.3a supports Standard mode only */
-			clock-frequency = <100000>;
-			i2c-min-scl-pulse-width-us = <0>;
-			i2c-min-sda-pulse-width-us = <5>;
-
-			status = "okay";
-		};
-
-		i2c@fe540000 {
-			status = "okay";
-		};
-
-		i2c@fe541000 {
-			status = "okay";
-		};
-
-		ethernet1: dwmac@fef08000 {
-			status			= "okay";
-			phy-mode		= "rgmii-id";
-			max-speed		= <1000>;
-			st,tx-retime-src	= "clk_125";
-			snps,reset-gpio 	= <&pio3 0>;
-			snps,reset-active-low;
-			snps,reset-delays-us 	= <0 10000 10000>;
-
-			pinctrl-0	= <&pinctrl_rgmii1>;
-		};
-
-		mmc0: sdhci@fe81e000 {
-			bus-width = <8>;
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x-b2020x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x-b2020x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x-b2020x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x-b2020x.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013 STMicroelectronics (R&D) Limited.
- * Author: Lee Jones <lee.jones@linaro.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
- * publishhed by the Free Software Foundation.
- */
-/ {
-	soc {
-		mmc0: sdhci@fe81e000 {
-			status = "okay";
-		};
-
-		spifsm: spifsm@fe902000 {
-			#address-cells = <1>;
-			#size-cells    = <1>;
-
-			status = "okay";
-
-			partition@0 {
-				label = "SerialFlash1";
-				reg   = <0x00000000 0x00500000>;
-			};
-
-			partition@500000 {
-				label = "SerialFlash2";
-				reg   = <0x00500000 0x00b00000>;
-			};
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stih41x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stih41x.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2014 STMicroelectronics Limited.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * publishhed by the Free Software Foundation.
- */
-/ {
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a9";
-			reg = <0>;
-		};
-		cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a9";
-			reg = <1>;
-		};
-	};
-
-	intc: interrupt-controller@fffe1000 {
-		compatible = "arm,cortex-a9-gic";
-		#interrupt-cells = <3>;
-		interrupt-controller;
-		reg = <0xfffe1000 0x1000>,
-		      <0xfffe0100 0x100>;
-	};
-
-	scu@fffe0000 {
-		compatible = "arm,cortex-a9-scu";
-		reg = <0xfffe0000 0x1000>;
-	};
-
-	timer@fffe0200 {
-		interrupt-parent = <&intc>;
-		compatible = "arm,cortex-a9-global-timer";
-		reg = <0xfffe0200 0x100>;
-		interrupts = <1 11 0x04>;
-		clocks = <&arm_periph_clk>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stihxxx-b2120.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stihxxx-b2120.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stihxxx-b2120.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stihxxx-b2120.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -135,6 +135,10 @@
 			};
 		};
 
+		sti_uni_player0: sti-uni-player@8d80000 {
+			status = "okay";
+		};
+
 		sti_uni_player2: sti-uni-player@8d82000 {
 			status = "okay";
 		};
@@ -151,13 +155,26 @@
 
 		sound {
 			compatible = "simple-audio-card";
-			simple-audio-card,name = "sti audio card";
+			simple-audio-card,name = "STI-B2120";
 			status = "okay";
 
 			simple-audio-card,dai-link@0 {
+				/* HDMI */
+				format = "i2s";
+				mclk-fs = <128>;
+				cpu {
+					sound-dai = <&sti_uni_player0>;
+				};
+
+				codec {
+					sound-dai = <&sti_hdmi>;
+				};
+			};
+			simple-audio-card,dai-link@1 {
 				/* DAC */
 				format = "i2s";
 				mclk-fs = <256>;
+				frame-inversion = <1>;
 				cpu {
 					sound-dai = <&sti_uni_player2>;
 				};
@@ -166,7 +183,7 @@
 					sound-dai = <&sti_sasg_codec 1>;
 				};
 			};
-			simple-audio-card,dai-link@1 {
+			simple-audio-card,dai-link@2 {
 				/* SPDIF */
 				format = "left_j";
 				mclk-fs = <128>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stm32429i-eval.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32429i-eval.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stm32429i-eval.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32429i-eval.dts	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,7 @@
 
 /dts-v1/;
 #include "stm32f429.dtsi"
+#include <dt-bindings/input/input.h>
 
 / {
 	model = "STMicroelectronics STM32429i-EVAL board";
@@ -65,6 +66,10 @@
 		serial0 = &usart1;
 	};
 
+	soc {
+		dma-ranges = <0xc0000000 0x0 0x10000000>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		green {
@@ -82,6 +87,23 @@
 		};
 	};
 
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+		button@0 {
+			label = "Wake up";
+			linux,code = <KEY_WAKEUP>;
+			gpios = <&gpioa 0 0>;
+		};
+		button@1 {
+			label = "Tamper";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpioc 13 0>;
+		};
+	};
+
 	usbotg_hs_phy: usbphy {
 		#phy-cells = <0>;
 		compatible = "usb-nop-xceiv";
@@ -94,11 +116,12 @@
 	clock-frequency = <25000000>;
 };
 
-&ethernet0 {
+&mac {
 	status = "okay";
-	pinctrl-0	= <&ethernet0_mii>;
+	pinctrl-0	= <&ethernet_mii>;
 	pinctrl-names	= "default";
-	phy-mode	= "mii-id";
+	phy-mode	= "mii";
+	phy-handle	= <&phy1>;
 	mdio0 {
 		#address-cells = <1>;
 		#size-cells = <0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stm32746g-eval.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32746g-eval.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stm32746g-eval.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32746g-eval.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2015 - Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+#include "stm32f746.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "STMicroelectronics STM32746g-EVAL board";
+	compatible = "st,stm32746g-eval", "st,stm32f746";
+
+	chosen {
+		bootargs = "root=/dev/ram";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		reg = <0xc0000000 0x2000000>;
+	};
+
+	aliases {
+		serial0 = &usart1;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		green {
+			gpios = <&gpiof 10 1>;
+			linux,default-trigger = "heartbeat";
+		};
+		red {
+			gpios = <&gpiob 7 1>;
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+		button@0 {
+			label = "Wake up";
+			linux,code = <KEY_WAKEUP>;
+			gpios = <&gpioc 13 0>;
+		};
+	};
+};
+
+&clk_hse {
+	clock-frequency = <25000000>;
+};
+
+&usart1 {
+	pinctrl-0 = <&usart1_pins_a>;
+	pinctrl-names = "default";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f429-disco.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f429-disco.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f429-disco.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f429-disco.dts	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,7 @@
 
 /dts-v1/;
 #include "stm32f429.dtsi"
+#include <dt-bindings/input/input.h>
 
 / {
 	model = "STMicroelectronics STM32F429i-DISCO board";
@@ -75,6 +76,18 @@
 			linux,default-trigger = "heartbeat";
 		};
 	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		autorepeat;
+		button@0 {
+			label = "User";
+			linux,code = <KEY_HOME>;
+			gpios = <&gpioa 0 0>;
+		};
+	};
 };
 
 &clk_hse {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f429.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f429.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f429.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f429.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -56,11 +56,21 @@
 			compatible = "fixed-clock";
 			clock-frequency = <0>;
 		};
+
+		clk-lse {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32768>;
+		};
+
+		clk-lsi {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <32000>;
+		};
 	};
 
 	soc {
-		dma-ranges = <0xc0000000 0x0 0x10000000>;
-
 		timer2: timer@40000000 {
 			compatible = "st,stm32-timer";
 			reg = <0x40000000 0x400>;
@@ -122,6 +132,9 @@
 			interrupts = <39>;
 			clocks = <&rcc 0 146>;
 			status = "disabled";
+			dmas = <&dma1 1 4 0x400 0x0>,
+			       <&dma1 3 4 0x400 0x0>;
+			dma-names = "rx", "tx";
 		};
 
 		usart4: serial@40004c00 {
@@ -162,6 +175,9 @@
 			interrupts = <37>;
 			clocks = <&rcc 0 164>;
 			status = "disabled";
+			dmas = <&dma2 2 4 0x400 0x0>,
+			       <&dma2 7 4 0x400 0x0>;
+			dma-names = "rx", "tx";
 		};
 
 		usart6: serial@40011400 {
@@ -185,11 +201,18 @@
 			interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
 		};
 
+		pwrcfg: power-config@40007000 {
+			compatible = "syscon";
+			reg = <0x40007000 0x400>;
+		};
+
 		pin-controller {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "st,stm32f429-pinctrl";
 			ranges = <0 0x40020000 0x3000>;
+			interrupt-parent = <&exti>;
+			st,syscfg = <&syscfg 0x8>;
 			pins-are-numbered;
 
 			gpioa: gpio@40020000 {
@@ -313,7 +336,7 @@
 				};
 			};
 
-			ethernet0_mii: mii@0 {
+			ethernet_mii: mii@0 {
 				pins {
 					pinmux = <STM32F429_PG13_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0>,
 						 <STM32F429_PG14_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1>,
@@ -340,6 +363,7 @@
 			compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
 			reg = <0x40023800 0x400>;
 			clocks = <&clk_hse>;
+			st,syscfg = <&pwrcfg>;
 		};
 
 		dma1: dma-controller@40026000 {
@@ -373,24 +397,22 @@
 			st,mem2mem;
 		};
 
-		ethernet0: dwmac@40028000 {
+		mac: ethernet@40028000 {
 			compatible = "st,stm32-dwmac", "snps,dwmac-3.50a";
 			reg = <0x40028000 0x8000>;
 			reg-names = "stmmaceth";
-			interrupts = <61>, <62>;
-			interrupt-names = "macirq", "eth_wake_irq";
-			clock-names = "stmmaceth", "tx-clk", "rx-clk";
+			interrupts = <61>;
+			interrupt-names = "macirq";
+			clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
 			clocks = <&rcc 0 25>, <&rcc 0 26>, <&rcc 0 27>;
 			st,syscon = <&syscfg 0x4>;
 			snps,pbl = <8>;
 			snps,mixed-burst;
-			dma-ranges;
 			status = "disabled";
 		};
 
 		usbotg_hs: usb@40040000 {
 			compatible = "snps,dwc2";
-			dma-ranges;
 			reg = <0x40040000 0x40000>;
 			interrupts = <77>;
 			clocks = <&rcc 0 29>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f469-disco.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f469-disco.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f469-disco.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f469-disco.dts	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,14 @@
 	aliases {
 		serial0 = &usart3;
 	};
+
+	soc {
+		dma-ranges = <0xc0000000 0x0 0x10000000>;
+	};
+};
+
+&rcc {
+	compatible = "st,stm32f469-rcc", "st,stm32f42xx-rcc", "st,stm32-rcc";
 };
 
 &clk_hse {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f746.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f746.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/stm32f746.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/stm32f746.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2015 - Maxime Coquelin <mcoquelin.stm32@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "skeleton.dtsi"
+#include "armv7-m.dtsi"
+#include <dt-bindings/pinctrl/stm32f746-pinfunc.h>
+
+/ {
+	clocks {
+		clk_hse: clk-hse {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <0>;
+		};
+	};
+
+	soc {
+		timer2: timer@40000000 {
+			compatible = "st,stm32-timer";
+			reg = <0x40000000 0x400>;
+			interrupts = <28>;
+			clocks = <&rcc 0 128>;
+			status = "disabled";
+		};
+
+		timer3: timer@40000400 {
+			compatible = "st,stm32-timer";
+			reg = <0x40000400 0x400>;
+			interrupts = <29>;
+			clocks = <&rcc 0 129>;
+			status = "disabled";
+		};
+
+		timer4: timer@40000800 {
+			compatible = "st,stm32-timer";
+			reg = <0x40000800 0x400>;
+			interrupts = <30>;
+			clocks = <&rcc 0 130>;
+			status = "disabled";
+		};
+
+		timer5: timer@40000c00 {
+			compatible = "st,stm32-timer";
+			reg = <0x40000c00 0x400>;
+			interrupts = <50>;
+			clocks = <&rcc 0 131>;
+		};
+
+		timer6: timer@40001000 {
+			compatible = "st,stm32-timer";
+			reg = <0x40001000 0x400>;
+			interrupts = <54>;
+			clocks = <&rcc 0 132>;
+			status = "disabled";
+		};
+
+		timer7: timer@40001400 {
+			compatible = "st,stm32-timer";
+			reg = <0x40001400 0x400>;
+			interrupts = <55>;
+			clocks = <&rcc 0 133>;
+			status = "disabled";
+		};
+
+		usart2: serial@40004400 {
+			compatible = "st,stm32f7-usart", "st,stm32f7-uart";
+			reg = <0x40004400 0x400>;
+			interrupts = <38>;
+			clocks =  <&rcc 0 145>;
+			status = "disabled";
+		};
+
+		usart3: serial@40004800 {
+			compatible = "st,stm32f7-usart", "st,stm32f7-uart";
+			reg = <0x40004800 0x400>;
+			interrupts = <39>;
+			clocks = <&rcc 0 146>;
+			status = "disabled";
+		};
+
+		usart4: serial@40004c00 {
+			compatible = "st,stm32f7-uart";
+			reg = <0x40004c00 0x400>;
+			interrupts = <52>;
+			clocks = <&rcc 0 147>;
+			status = "disabled";
+		};
+
+		usart5: serial@40005000 {
+			compatible = "st,stm32f7-uart";
+			reg = <0x40005000 0x400>;
+			interrupts = <53>;
+			clocks = <&rcc 0 148>;
+			status = "disabled";
+		};
+
+		usart7: serial@40007800 {
+			compatible = "st,stm32f7-usart", "st,stm32f7-uart";
+			reg = <0x40007800 0x400>;
+			interrupts = <82>;
+			clocks = <&rcc 0 158>;
+			status = "disabled";
+		};
+
+		usart8: serial@40007c00 {
+			compatible = "st,stm32f7-usart", "st,stm32f7-uart";
+			reg = <0x40007c00 0x400>;
+			interrupts = <83>;
+			clocks = <&rcc 0 159>;
+			status = "disabled";
+		};
+
+		usart1: serial@40011000 {
+			compatible = "st,stm32f7-usart", "st,stm32f7-uart";
+			reg = <0x40011000 0x400>;
+			interrupts = <37>;
+			clocks = <&rcc 0 164>;
+			status = "disabled";
+		};
+
+		usart6: serial@40011400 {
+			compatible = "st,stm32f7-usart", "st,stm32f7-uart";
+			reg = <0x40011400 0x400>;
+			interrupts = <71>;
+			clocks = <&rcc 0 165>;
+			status = "disabled";
+		};
+
+		syscfg: system-config@40013800 {
+			compatible = "syscon";
+			reg = <0x40013800 0x400>;
+		};
+
+		exti: interrupt-controller@40013c00 {
+			compatible = "st,stm32-exti";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x40013C00 0x400>;
+			interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
+		};
+
+		pin-controller {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "st,stm32f746-pinctrl";
+			ranges = <0 0x40020000 0x3000>;
+			interrupt-parent = <&exti>;
+			st,syscfg = <&syscfg 0x8>;
+			pins-are-numbered;
+
+			gpioa: gpio@40020000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x0 0x400>;
+				clocks = <&rcc 0 256>;
+				st,bank-name = "GPIOA";
+			};
+
+			gpiob: gpio@40020400 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x400 0x400>;
+				clocks = <&rcc 0 257>;
+				st,bank-name = "GPIOB";
+			};
+
+			gpioc: gpio@40020800 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x800 0x400>;
+				clocks = <&rcc 0 258>;
+				st,bank-name = "GPIOC";
+			};
+
+			gpiod: gpio@40020c00 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0xc00 0x400>;
+				clocks = <&rcc 0 259>;
+				st,bank-name = "GPIOD";
+			};
+
+			gpioe: gpio@40021000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x1000 0x400>;
+				clocks = <&rcc 0 260>;
+				st,bank-name = "GPIOE";
+			};
+
+			gpiof: gpio@40021400 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x1400 0x400>;
+				clocks = <&rcc 0 261>;
+				st,bank-name = "GPIOF";
+			};
+
+			gpiog: gpio@40021800 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x1800 0x400>;
+				clocks = <&rcc 0 262>;
+				st,bank-name = "GPIOG";
+			};
+
+			gpioh: gpio@40021c00 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x1c00 0x400>;
+				clocks = <&rcc 0 263>;
+				st,bank-name = "GPIOH";
+			};
+
+			gpioi: gpio@40022000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x2000 0x400>;
+				clocks = <&rcc 0 264>;
+				st,bank-name = "GPIOI";
+			};
+
+			gpioj: gpio@40022400 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x2400 0x400>;
+				clocks = <&rcc 0 265>;
+				st,bank-name = "GPIOJ";
+			};
+
+			gpiok: gpio@40022800 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				reg = <0x2800 0x400>;
+				clocks = <&rcc 0 266>;
+				st,bank-name = "GPIOK";
+			};
+
+			usart1_pins_a: usart1@0 {
+				pins1 {
+					pinmux = <STM32F746_PA9_FUNC_USART1_TX>;
+					bias-disable;
+					drive-push-pull;
+					slew-rate = <0>;
+				};
+				pins2 {
+					pinmux = <STM32F746_PA10_FUNC_USART1_RX>;
+					bias-disable;
+				};
+			};
+		};
+
+		rcc: rcc@40023800 {
+			#clock-cells = <2>;
+			compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
+			reg = <0x40023800 0x400>;
+			clocks = <&clk_hse>;
+		};
+	};
+};
+
+&systick {
+	clocks = <&rcc 1 0>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun4i-a10.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun4i-a10.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun4i-a10.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun4i-a10.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -967,7 +967,8 @@
 			compatible = "allwinner,sun4i-a10-pinctrl";
 			reg = <0x01c20800 0x400>;
 			interrupts = <28>;
-			clocks = <&apb0_gates 5>;
+			clocks = <&apb0_gates 5>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			interrupt-controller;
 			#interrupt-cells = <3>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a10s.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -243,14 +243,14 @@
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
 
-	spi2_pins_a: spi2@0 {
+	spi2_pins_b: spi2@1 {
 		allwinner,pins = "PB12", "PB13", "PB14";
 		allwinner,function = "spi2";
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
 
-	spi2_cs0_pins_a: spi2_cs0@0 {
+	spi2_cs0_pins_b: spi2_cs0@1 {
 		allwinner,pins = "PB11";
 		allwinner,function = "spi2";
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts	2017-02-12 16:03:20.000000000 -0500
@@ -250,8 +250,8 @@
 
 &spi2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&spi2_pins_a>,
-		    <&spi2_cs0_pins_a>;
+	pinctrl-0 = <&spi2_pins_b>,
+		    <&spi2_cs0_pins_b>;
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a13-olinuxino.dts	2017-02-12 16:03:20.000000000 -0500
@@ -72,6 +72,47 @@
 			default-state = "on";
 		};
 	};
+
+	bridge {
+		compatible = "dumb-vga-dac";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				vga_bridge_in: endpoint {
+					remote-endpoint = <&tcon0_out_vga>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				vga_bridge_out: endpoint {
+					remote-endpoint = <&vga_con_in>;
+				};
+			};
+		};
+	};
+
+	vga {
+		compatible = "vga-connector";
+
+		port {
+			vga_con_in: endpoint {
+				remote-endpoint = <&vga_bridge_out>;
+			};
+		};
+	};
+};
+
+&be0 {
+	status = "okay";
 };
 
 &ehci0 {
@@ -211,6 +252,19 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd_rgb666_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_vga: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&vga_bridge_in>;
+	};
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart1_pins_b>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-a13-utoo-p66.dts	2017-02-12 16:03:20.000000000 -0500
@@ -83,22 +83,6 @@
 	allwinner,pins = "PG3";
 };
 
-&i2c1 {
-	icn8318: touchscreen@40 {
-		compatible = "chipone,icn8318";
-		reg = <0x40>;
-		interrupt-parent = <&pio>;
-		interrupts = <6 9 IRQ_TYPE_EDGE_FALLING>; /* EINT9 (PG9) */
-		pinctrl-names = "default";
-		pinctrl-0 = <&ts_wake_pin_p66>;
-		wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
-		touchscreen-size-x = <800>;
-		touchscreen-size-y = <480>;
-		touchscreen-inverted-x;
-		touchscreen-swapped-x-y;
-	};
-};
-
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_pins_a>;
@@ -121,20 +105,26 @@
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 	};
-
-	ts_wake_pin_p66: ts_wake_pin@0 {
-		allwinner,pins = "PB3";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
-
 };
 
 &reg_usb0_vbus {
 	gpio = <&pio 1 4 GPIO_ACTIVE_HIGH>; /* PB4 */
 };
 
+&touchscreen {
+	compatible = "chipone,icn8318";
+	reg = <0x40>;
+	/* The P66 uses a different EINT then the reference design */
+	interrupts = <6 9 IRQ_TYPE_EDGE_FALLING>; /* EINT9 (PG9) */
+	/* The icn8318 binding expects wake-gpios instead of power-gpios */
+	wake-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
+	touchscreen-size-x = <800>;
+	touchscreen-size-y = <480>;
+	touchscreen-inverted-x;
+	touchscreen-swapped-x-y;
+	status = "okay";
+};
+
 &uart1 {
 	/* The P66 uses the uart pins as gpios */
 	status = "disabled";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -547,7 +547,8 @@
 		pio: pinctrl@01c20800 {
 			reg = <0x01c20800 0x400>;
 			interrupts = <28>;
-			clocks = <&apb0_gates 5>;
+			clocks = <&apb0_gates 5>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			interrupt-controller;
 			#interrupt-cells = <3>;
@@ -574,6 +575,16 @@
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
 
+			lcd_rgb565_pins: lcd_rgb565@0 {
+				allwinner,pins = "PD3", "PD4", "PD5", "PD6", "PD7",
+						 "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
+						 "PD19", "PD20", "PD21", "PD22", "PD23",
+						 "PD24", "PD25", "PD26", "PD27";
+				allwinner,function = "lcd0";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			mmc0_pins_a: mmc0@0 {
 				allwinner,pins = "PF0", "PF1", "PF2", "PF3",
 						 "PF4", "PF5";
@@ -591,6 +602,20 @@
 				allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 			};
 
+			spi2_pins_a: spi2@0 {
+				allwinner,pins = "PE1", "PE2", "PE3";
+				allwinner,function = "spi2";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
+			spi2_cs0_pins_a: spi2-cs0@0 {
+				allwinner,pins = "PE0";
+				allwinner,function = "spi2";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			uart3_pins_a: uart3@0 {
 				allwinner,pins = "PG9", "PG10";
 				allwinner,function = "uart3";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-gr8-chip-pro.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-gr8-chip-pro.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-gr8-chip-pro.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-gr8-chip-pro.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2016 Free Electrons
+ * Copyright 2016 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+#include "sun5i-gr8.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "NextThing C.H.I.P. Pro";
+	compatible = "nextthing,chip-pro", "nextthing,gr8";
+
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		serial0 = &uart1;
+		serial1 = &uart2;
+		serial2 = &uart3;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		status {
+			label = "chip-pro:white:status";
+			gpios = <&axp_gpio 2 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+	};
+
+	mmc0_pwrseq: mmc0_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_reg_on_pin_chip_pro>;
+		reset-gpios = <&pio 1 10 GPIO_ACTIVE_LOW>; /* PB10 */
+	};
+};
+
+&codec {
+	status = "okay";
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c0_pins_a>;
+	status = "okay";
+
+	axp209: pmic@34 {
+		reg = <0x34>;
+
+		/*
+		* The interrupt is routed through the "External Fast
+		* Interrupt Request" pin (ball G13 of the module)
+		* directly to the main interrupt controller, without
+		* any other controller interfering.
+		*/
+		interrupts = <0>;
+	};
+};
+
+#include "axp209.dtsi"
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_a>;
+	status = "disabled";
+};
+
+&i2s0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2s0_mclk_pins_a>, <&i2s0_data_pins_a>;
+	status = "disabled";
+};
+
+&mmc0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>;
+	vmmc-supply = <&reg_vcc3v3>;
+	mmc-pwrseq = <&mmc0_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>;
+	status = "okay";
+
+	nand@0 {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0>;
+		allwinner,rb = <0>;
+		nand-ecc-mode = "hw";
+	};
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&otg_sram {
+	status = "okay";
+};
+
+&pio {
+	usb0_id_pin_chip_pro: usb0-id-pin@0 {
+		allwinner,pins = "PG2";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	wifi_reg_on_pin_chip_pro: wifi-reg-on-pin@0 {
+		allwinner,pins = "PB10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_pins_a>, <&pwm1_pins>;
+	status = "disabled";
+};
+
+&reg_dcdc2 {
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+	regulator-always-on;
+};
+
+&reg_dcdc3 {
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1300000>;
+	regulator-name = "vdd-sys";
+	regulator-always-on;
+};
+
+&reg_ldo1 {
+	regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+	regulator-min-microvolt = <2700000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "avcc";
+	regulator-always-on;
+};
+
+/*
+ * Both LDO3 and LDO4 are used in parallel to power up the
+ * WiFi/BT chip.
+ */
+&reg_ldo3 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi-1";
+	regulator-always-on;
+};
+
+&reg_ldo4 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi-2";
+	regulator-always-on;
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart1_pins_a>, <&uart1_cts_rts_pins_a>;
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_pins_a>, <&uart2_cts_rts_pins_a>;
+	status = "disabled";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins_a>, <&uart3_cts_rts_pins_a>;
+	status = "okay";
+};
+
+&usb_otg {
+	/*
+	 * The CHIP Pro doesn't have a controllable VBUS, nor does it
+	 * have any 5v rail on the board itself.
+	 *
+	 * If one wants to use it as a true OTG port, it should be
+	 * done in the baseboard, and its DT / overlay will add it.
+	 */
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usb_power_supply {
+	status = "okay";
+};
+
+&usbphy {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_id_pin_chip_pro>;
+	usb0_id_det-gpio = <&pio 6 2 GPIO_ACTIVE_HIGH>; /* PG2 */
+	usb0_vbus_power-supply = <&usb_power_supply>;
+	usb1_vbus-supply = <&reg_vcc5v0>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-gr8.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-gr8.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-gr8.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-gr8.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -792,7 +792,7 @@
 			};
 
 			i2s0_mclk_pins_a: i2s0-mclk@0 {
-				allwinner,pins = "PB6", "PB7", "PB8", "PB9";
+				allwinner,pins = "PB5";
 				allwinner,function = "i2s0";
 				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
@@ -854,6 +854,13 @@
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
 
+			pwm1_pins: pwm1 {
+				allwinner,pins = "PG13";
+				allwinner,function = "pwm1";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			spdif_tx_pins_a: spdif@0 {
 				allwinner,pins = "PB10";
 				allwinner,function = "spdif";
@@ -874,6 +881,34 @@
 				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
+
+			uart2_pins_a: uart2@1 {
+				allwinner,pins = "PD2", "PD3";
+				allwinner,function = "uart2";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
+			uart2_cts_rts_pins_a: uart2-cts-rts@0 {
+				allwinner,pins = "PD4", "PD5";
+				allwinner,function = "uart2";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
+			uart3_pins_a: uart3@1 {
+				allwinner,pins = "PG9", "PG10";
+				allwinner,function = "uart3";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
+			uart3_cts_rts_pins_a: uart3-cts-rts@0 {
+				allwinner,pins = "PG11", "PG12";
+				allwinner,function = "uart3";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
 		};
 
 		pwm: pwm@01c20e00 {
@@ -978,6 +1013,16 @@
 			status = "disabled";
 		};
 
+		uart3: serial@01c28c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28c00 0x400>;
+			interrupts = <4>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&apb1_gates 19>;
+			status = "disabled";
+		};
+
 		i2c0: i2c@01c2ac00 {
 			compatible = "allwinner,sun4i-a10-i2c";
 			reg = <0x01c2ac00 0x400>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-gr8-evb.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-gr8-evb.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-gr8-evb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-gr8-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -75,6 +75,39 @@
 		brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
 		default-brightness-level = <8>;
 	};
+
+	sound-analog {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "gr8-evb-wm8978";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,mclk-fs = <512>;
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&wm8978>;
+		};
+	};
+
+	sound-spdif {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "On-board SPDIF";
+
+		simple-audio-card,cpu {
+			sound-dai = <&spdif>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&spdif_out>;
+		};
+	};
+
+	spdif_out: spdif-out {
+		#sound-dai-cells = <0>;
+		compatible = "linux,spdif-dit";
+	};
 };
 
 &be0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-r8-chip.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,9 +56,11 @@
 
 	aliases {
 		i2c0 = &i2c0;
+		i2c1 = &i2c1;
 		i2c2 = &i2c2;
 		serial0 = &uart1;
 		serial1 = &uart3;
+		spi0 = &spi2;
 	};
 
 	chosen {
@@ -74,6 +76,20 @@
 			default-state = "on";
 		};
 	};
+
+	mmc0_pwrseq: mmc0_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&chip_wifi_reg_on_pin>;
+		reset-gpios = <&pio 2 19 GPIO_ACTIVE_LOW>; /* PC19 */
+	};
+
+	onewire {
+		compatible = "w1-gpio";
+		gpios = <&pio 3 2 GPIO_ACTIVE_HIGH>; /* PD2 */
+		pinctrl-names = "default";
+		pinctrl-0 = <&chip_w1_pin>;
+	};
 };
 
 &be0 {
@@ -112,6 +128,12 @@
 
 #include "axp209.dtsi"
 
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins_a>;
+	status = "disabled";
+};
+
 &i2c2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c2_pins_a>;
@@ -131,10 +153,15 @@
 	};
 };
 
+&mmc0_pins_a {
+	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+};
+
 &mmc0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins_a>;
 	vmmc-supply = <&reg_vcc3v3>;
+	mmc-pwrseq = <&mmc0_pwrseq>;
 	bus-width = <4>;
 	non-removable;
 	status = "okay";
@@ -156,12 +183,26 @@
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
 
+	chip_wifi_reg_on_pin: chip_wifi_reg_on_pin@0 {
+	        allwinner,pins = "PC19";
+	        allwinner,function = "gpio_out";
+	        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+	        allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	chip_id_det_pin: chip_id_det_pin@0 {
 		allwinner,pins = "PG2";
 		allwinner,function = "gpio_in";
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
+
+	chip_w1_pin: chip_w1_pin@0 {
+		allwinner,pins = "PD2";
+		allwinner,function = "gpio_in";
+	        allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+	        allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+	};
 };
 
 &reg_dcdc2 {
@@ -189,6 +230,28 @@
 	regulator-always-on;
 };
 
+/*
+ * Both LDO3 and LDO4 are used in parallel to power up the WiFi/BT
+ * Chip.
+ *
+ * If those are not enabled, the SDIO part will not enumerate, and
+ * since there's no way currently to pass DT infos to an SDIO device,
+ * we cannot really do better than this ugly hack for now.
+ */
+&reg_ldo3 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi-1";
+	regulator-always-on;
+};
+
+&reg_ldo4 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-wifi-2";
+	regulator-always-on;
+};
+
 &reg_ldo5 {
 	regulator-min-microvolt = <1800000>;
 	regulator-max-microvolt = <1800000>;
@@ -202,6 +265,12 @@
 	status = "okay";
 };
 
+&spi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi2_pins_a>;
+	status = "disabled";
+};
+
 &tcon0 {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun5i-reference-design-tablet.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,7 @@
  */
 #include "sunxi-reference-design-tablet.dtsi"
 
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
@@ -84,6 +85,23 @@
 };
 
 &i2c1 {
+	/*
+	 * The gsl1680 is rated at 400KHz and it will not work reliable at
+	 * 100KHz, this has been confirmed on multiple different q8 tablets.
+	 * All other devices on this bus are also rated for 400KHz.
+	 */
+	clock-frequency = <400000>;
+
+	touchscreen: touchscreen {
+		interrupt-parent = <&pio>;
+		interrupts = <6 11 IRQ_TYPE_EDGE_FALLING>; /* EINT11 (PG11) */
+		pinctrl-names = "default";
+		pinctrl-0 = <&ts_power_pin>;
+		power-gpios = <&pio 1 3 GPIO_ACTIVE_HIGH>; /* PB3 */
+		/* Tablet dts must provide reg and compatible */
+		status = "disabled";
+	};
+
 	pcf8563: rtc@51 {
 		compatible = "nxp,pcf8563";
 		reg = <0x51>;
@@ -125,6 +143,13 @@
 		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 	};
 
+	ts_power_pin: ts_power_pin {
+		pins = "PB3";
+		function = "gpio_out";
+		drive-strength = <10>;
+		bias-disable;
+	};
+
 	usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 {
 		allwinner,pins = "PG1";
 		allwinner,function = "gpio_in";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -231,6 +231,12 @@
 		};
 	};
 
+	de: display-engine {
+		compatible = "allwinner,sun6i-a31-display-engine";
+		allwinner,pipelines = <&fe0>;
+		status = "disabled";
+	};
+
 	soc@01c00000 {
 		compatible = "simple-bus";
 		#address-cells = <1>;
@@ -246,6 +252,44 @@
 			#dma-cells = <1>;
 		};
 
+		tcon0: lcd-controller@01c0c000 {
+			compatible = "allwinner,sun6i-a31-tcon";
+			reg = <0x01c0c000 0x1000>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&ccu RST_AHB1_LCD0>;
+			reset-names = "lcd";
+			clocks = <&ccu CLK_AHB1_LCD0>,
+				 <&ccu CLK_LCD0_CH0>,
+				 <&ccu CLK_LCD0_CH1>;
+			clock-names = "ahb",
+				      "tcon-ch0",
+				      "tcon-ch1";
+			clock-output-names = "tcon0-pixel-clock";
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				tcon0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					tcon0_in_drc0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&drc0_out_tcon0>;
+					};
+				};
+
+				tcon0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+			};
+		};
+
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun7i-a20-mmc";
 			reg = <0x01c0f000 0x1000>;
@@ -428,19 +472,55 @@
 				     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&ccu CLK_APB1_PIO>;
+			clocks = <&ccu CLK_APB1_PIO>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			interrupt-controller;
 			#interrupt-cells = <3>;
 			#gpio-cells = <3>;
 
-			uart0_pins_a: uart0@0 {
-				allwinner,pins = "PH20", "PH21";
-				allwinner,function = "uart0";
+			gmac_pins_gmii_a: gmac_gmii@0 {
+				allwinner,pins = "PA0", "PA1", "PA2", "PA3",
+						"PA4", "PA5", "PA6", "PA7",
+						"PA8", "PA9", "PA10", "PA11",
+						"PA12", "PA13", "PA14",	"PA15",
+						"PA16", "PA17", "PA18", "PA19",
+						"PA20", "PA21", "PA22", "PA23",
+						"PA24", "PA25", "PA26", "PA27";
+				allwinner,function = "gmac";
+				/*
+				 * data lines in GMII mode run at 125MHz and
+				 * might need a higher signal drive strength
+				 */
+				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
+			gmac_pins_mii_a: gmac_mii@0 {
+				allwinner,pins = "PA0", "PA1", "PA2", "PA3",
+						"PA8", "PA9", "PA11",
+						"PA12", "PA13", "PA14", "PA19",
+						"PA20", "PA21", "PA22", "PA23",
+						"PA24", "PA26", "PA27";
+				allwinner,function = "gmac";
 				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
 
+			gmac_pins_rgmii_a: gmac_rgmii@0 {
+				allwinner,pins = "PA0", "PA1", "PA2", "PA3",
+						"PA9", "PA10", "PA11",
+						"PA12", "PA13", "PA14", "PA19",
+						"PA20", "PA25", "PA26", "PA27";
+				allwinner,function = "gmac";
+				/*
+				 * data lines in RGMII mode use DDR mode
+				 * and need a higher signal drive strength
+				 */
+				allwinner,drive = <SUN4I_PINCTRL_40_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			i2c0_pins_a: i2c0@0 {
 				allwinner,pins = "PH14", "PH15";
 				allwinner,function = "i2c0";
@@ -462,6 +542,19 @@
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
 
+			lcd0_rgb888_pins: lcd0_rgb888 {
+				allwinner,pins = "PD0", "PD1", "PD2", "PD3",
+						 "PD4", "PD5", "PD6", "PD7",
+						 "PD8", "PD9", "PD10", "PD11",
+						 "PD12", "PD13", "PD14", "PD15",
+						 "PD16", "PD17", "PD18", "PD19",
+						 "PD20", "PD21", "PD22", "PD23",
+						 "PD24", "PD25", "PD26", "PD27";
+				allwinner,function = "lcd0";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			mmc0_pins_a: mmc0@0 {
 				allwinner,pins = "PF0", "PF1", "PF2",
 						 "PF3", "PF4", "PF5";
@@ -506,47 +599,12 @@
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
 
-			gmac_pins_mii_a: gmac_mii@0 {
-				allwinner,pins = "PA0", "PA1", "PA2", "PA3",
-						"PA8", "PA9", "PA11",
-						"PA12", "PA13", "PA14", "PA19",
-						"PA20", "PA21", "PA22", "PA23",
-						"PA24", "PA26", "PA27";
-				allwinner,function = "gmac";
+			uart0_pins_a: uart0@0 {
+				allwinner,pins = "PH20", "PH21";
+				allwinner,function = "uart0";
 				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
-
-			gmac_pins_gmii_a: gmac_gmii@0 {
-				allwinner,pins = "PA0", "PA1", "PA2", "PA3",
-						"PA4", "PA5", "PA6", "PA7",
-						"PA8", "PA9", "PA10", "PA11",
-						"PA12", "PA13", "PA14",	"PA15",
-						"PA16", "PA17", "PA18", "PA19",
-						"PA20", "PA21", "PA22", "PA23",
-						"PA24", "PA25", "PA26", "PA27";
-				allwinner,function = "gmac";
-				/*
-				 * data lines in GMII mode run at 125MHz and
-				 * might need a higher signal drive strength
-				 */
-				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
-
-			gmac_pins_rgmii_a: gmac_rgmii@0 {
-				allwinner,pins = "PA0", "PA1", "PA2", "PA3",
-						"PA9", "PA10", "PA11",
-						"PA12", "PA13", "PA14", "PA19",
-						"PA20", "PA25", "PA26", "PA27";
-				allwinner,function = "gmac";
-				/*
-				 * data lines in RGMII mode use DDR mode
-				 * and need a higher signal drive strength
-				 */
-				allwinner,drive = <SUN4I_PINCTRL_40_MA>;
-				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-			};
 		};
 
 		timer@01c20c00 {
@@ -728,6 +786,19 @@
 			reset-names = "ahb";
 		};
 
+		codec: codec@01c22c00 {
+			#sound-dai-cells = <0>;
+			compatible = "allwinner,sun6i-a31-codec";
+			reg = <0x01c22c00 0x400>;
+			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_APB1_CODEC>, <&ccu CLK_CODEC>;
+			clock-names = "apb", "codec";
+			resets = <&ccu RST_APB1_CODEC>;
+			dmas = <&dma 15>, <&dma 15>;
+			dma-names = "rx", "tx";
+			status = "disabled";
+		};
+
 		timer@01c60000 {
 			compatible = "allwinner,sun6i-a31-hstimer",
 				     "allwinner,sun7i-a20-hstimer";
@@ -799,6 +870,115 @@
 			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
 		};
 
+		fe0: display-frontend@01e00000 {
+			compatible = "allwinner,sun6i-a31-display-frontend";
+			reg = <0x01e00000 0x20000>;
+			interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_AHB1_FE0>, <&ccu CLK_FE0>,
+				 <&ccu CLK_DRAM_FE0>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&ccu RST_AHB1_FE0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				fe0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					fe0_out_be0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be0_in_fe0>;
+					};
+				};
+			};
+		};
+
+		be0: display-backend@01e60000 {
+			compatible = "allwinner,sun6i-a31-display-backend";
+			reg = <0x01e60000 0x10000>;
+			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_AHB1_BE0>, <&ccu CLK_BE0>,
+				 <&ccu CLK_DRAM_BE0>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&ccu RST_AHB1_BE0>;
+
+			assigned-clocks = <&ccu CLK_BE0>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				be0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					be0_in_fe0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&fe0_out_be0>;
+					};
+				};
+
+				be0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					be0_out_drc0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&drc0_in_be0>;
+					};
+				};
+			};
+		};
+
+		drc0: drc@01e70000 {
+			compatible = "allwinner,sun6i-a31-drc";
+			reg = <0x01e70000 0x10000>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_AHB1_DRC0>, <&ccu CLK_IEP_DRC0>,
+				 <&ccu CLK_DRAM_DRC0>;
+			clock-names = "ahb", "mod",
+				      "ram";
+			resets = <&ccu RST_AHB1_DRC0>;
+
+			assigned-clocks = <&ccu CLK_IEP_DRC0>;
+			assigned-clock-rates = <300000000>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				drc0_in: port@0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+
+					drc0_in_be0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&be0_out_drc0>;
+					};
+				};
+
+				drc0_out: port@1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+
+					drc0_out_tcon0: endpoint@0 {
+						reg = <0>;
+						remote-endpoint = <&tcon0_in_drc0>;
+					};
+				};
+			};
+		};
+
 		rtc: rtc@01f00000 {
 			compatible = "allwinner,sun6i-a31-rtc";
 			reg = <0x01f00000 0x54>;
@@ -886,7 +1066,8 @@
 			reg = <0x01f02c00 0x400>;
 			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb0_gates 0>;
+			clocks = <&apb0_gates 0>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			resets = <&apb0_rst 0>;
 			gpio-controller;
 			interrupt-controller;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31-hummingbird.dts	2017-02-12 16:03:20.000000000 -0500
@@ -63,16 +63,87 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	vga-connector {
+		compatible = "vga-connector";
+
+		port {
+			vga_con_in: endpoint {
+				remote-endpoint = <&vga_dac_out>;
+			};
+		};
+	};
+
+	vga-dac {
+		compatible = "dumb-vga-dac";
+		vdd-supply = <&reg_vga_3v3>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>;
+
+				vga_dac_in: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&tcon0_out_vga>;
+				};
+			};
+
+			port@1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>;
+
+				vga_dac_out: endpoint@0 {
+					reg = <0>;
+					remote-endpoint = <&vga_con_in>;
+				};
+			};
+		};
+	};
+
+	reg_vga_3v3: vga_3v3_regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vga-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&pio 7 25 GPIO_ACTIVE_HIGH>; /* PH25 */
+	};
+
 	wifi_pwrseq: wifi_pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */
 	};
 };
 
+&codec {
+	allwinner,audio-routing =
+		"Headphone", "HP",
+		"Speaker", "LINEOUT",
+		"LINEIN", "Line In",
+		"MIC1", "Mic",
+		"MIC2", "Headset Mic",
+		"Mic",	"MBIAS",
+		"Headset Mic", "HBIAS";
+	allwinner,pa-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */
+	status = "okay";
+};
+
 &cpu0 {
 	cpu-supply = <&reg_dcdc3>;
 };
 
+&de {
+	status = "okay";
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -245,6 +316,19 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd0_rgb888_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_vga: endpoint@0 {
+		reg = <0>;
+		remote-endpoint = <&vga_dac_in>;
+	};
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31s.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31s.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31s.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31s.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,14 @@
 
 #include "sun6i-a31.dtsi"
 
+&de {
+	compatible = "allwinner,sun6i-a31s-display-engine";
+};
+
 &pio {
 	compatible = "allwinner,sun6i-a31s-pinctrl";
 };
+
+&tcon0 {
+	compatible = "allwinner,sun6i-a31s-tcon";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31s-sina31s.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31s-sina31s.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun6i-a31s-sina31s.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun6i-a31s-sina31s.dts	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,14 @@
 	};
 };
 
+&codec {
+	allwinner,audio-routing =
+		"Line Out", "LINEOUT",
+		"MIC1", "Mic",
+		"Mic",	"MBIAS";
+	status = "okay";
+};
+
 &ehci0 {
 	/* USB 2.0 4 port hub IC */
 	status = "okay";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts	2017-02-12 16:03:20.000000000 -0500
@@ -105,6 +105,10 @@
 	status = "okay";
 };
 
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -132,16 +136,14 @@
 	status = "okay";
 
 	axp209: pmic@34 {
-		compatible = "x-powers,axp209";
 		reg = <0x34>;
 		interrupt-parent = <&nmi_intc>;
 		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
-
-		interrupt-controller;
-		#interrupt-cells = <1>;
 	};
 };
 
+#include "axp209.dtsi"
+
 &ir0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&ir0_rx_pins_a>;
@@ -167,7 +169,7 @@
 	mmc-pwrseq = <&mmc3_pwrseq>;
 	bus-width = <4>;
 	non-removable;
-	enable-sdio-wakeup;
+	wakeup-source;
 	status = "okay";
 
 	brcmf: bcrmf@1 {
@@ -192,6 +194,10 @@
 	status = "okay";
 };
 
+&otg_sram {
+	status = "okay";
+};
+
 &pio {
 	gmac_power_pin_bpi_m1p: gmac_power_pin@0 {
 		allwinner,pins = "PH23";
@@ -222,8 +228,54 @@
 	};
 };
 
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo1 {
+	regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "avcc";
+};
+
+&reg_usb0_vbus {
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
 	status = "okay";
 };
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usb_power_supply {
+	status = "okay";
+};
+
+&usbphy {
+	usb0_id_det-gpios = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+	usb0_vbus_power-supply = <&usb_power_supply>;
+	usb0_vbus-supply = <&reg_usb0_vbus>;
+	/* VBUS on usb host ports are tied to DC5V and therefore always on */
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -1085,7 +1085,8 @@
 			compatible = "allwinner,sun7i-a20-pinctrl";
 			reg = <0x01c20800 0x400>;
 			interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb0_gates 5>;
+			clocks = <&apb0_gates 5>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			interrupt-controller;
 			#interrupt-cells = <3>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20-olimex-som-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -88,6 +88,10 @@
 	status = "okay";
 };
 
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
 &codec {
 	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2-emmc.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@
 };
 
 &pio {
-	mmc2_pins_nrst: mmc2@0 {
+	mmc2_pins_nrst: mmc2-rst-pin {
 		allwinner,pins = "PC16";
 		allwinner,function = "gpio_out";
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-a23-a33.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-a23-a33.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-a23-a33.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-a23-a33.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -266,7 +266,8 @@
 			/* compatible gets set in SoC specific dtsi file */
 			reg = <0x01c20800 0x400>;
 			/* interrupts get set in SoC specific dtsi file */
-			clocks = <&ccu CLK_BUS_PIO>;
+			clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			interrupt-controller;
 			#interrupt-cells = <3>;
@@ -575,7 +576,8 @@
 			compatible = "allwinner,sun8i-a23-r-pinctrl";
 			reg = <0x01f02c00 0x400>;
 			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb0_gates 0>;
+			clocks = <&apb0_gates 0>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			resets = <&apb0_rst 0>;
 			gpio-controller;
 			interrupt-controller;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts	2016-12-11 17:39:44.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-a23-polaroid-mid2407pxe03.dts	2017-02-12 17:22:06.000000000 -0500
@@ -98,13 +98,6 @@
 	};
 };
 
-&reg_ldo_io1 {
-	regulator-min-microvolt = <3300000>;
-	regulator-max-microvolt = <3300000>;
-	regulator-name = "vcc-touchscreen";
-	status = "okay";
-};
-
 &touchscreen {
 	reg = <0x40>;
 	compatible = "silead,gsl1680";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts	2017-02-12 16:03:20.000000000 -0500
@@ -213,6 +213,11 @@
 	status = "okay";
 };
 
+&usb_otg {
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
 &usbphy {
 	status = "okay";
 	usb1_vbus-supply = <&reg_vcc5v0>; /* USB1 VBUS is always on */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -321,7 +321,8 @@
 			reg = <0x01c20800 0x400>;
 			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&ccu CLK_BUS_PIO>;
+			clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			#gpio-cells = <3>;
 			interrupt-controller;
@@ -381,6 +382,20 @@
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
 
+			spi0_pins: spi0 {
+				allwinner,pins = "PC0", "PC1", "PC2", "PC3";
+				allwinner,function = "spi0";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
+			spi1_pins: spi1 {
+				allwinner,pins = "PA15", "PA16", "PA14", "PA13";
+				allwinner,function = "spi1";
+				allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			uart0_pins_a: uart0@0 {
 				allwinner,pins = "PA4", "PA5";
 				allwinner,function = "uart0";
@@ -425,6 +440,38 @@
 			clocks = <&osc24M>;
 		};
 
+		spi0: spi@01c68000 {
+			compatible = "allwinner,sun8i-h3-spi";
+			reg = <0x01c68000 0x1000>;
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+			clock-names = "ahb", "mod";
+			dmas = <&dma 23>, <&dma 23>;
+			dma-names = "rx", "tx";
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi0_pins>;
+			resets = <&ccu RST_BUS_SPI0>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		spi1: spi@01c69000 {
+			compatible = "allwinner,sun8i-h3-spi";
+			reg = <0x01c69000 0x1000>;
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+			clock-names = "ahb", "mod";
+			dmas = <&dma 24>, <&dma 24>;
+			dma-names = "rx", "tx";
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi1_pins>;
+			resets = <&ccu RST_BUS_SPI1>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
 		wdt0: watchdog@01c20ca0 {
 			compatible = "allwinner,sun6i-a31-wdt";
 			reg = <0x01c20ca0 0x20>;
@@ -568,7 +615,8 @@
 			compatible = "allwinner,sun8i-h3-r-pinctrl";
 			reg = <0x01f02c00 0x400>;
 			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb0_gates 0>;
+			clocks = <&apb0_gates 0>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			resets = <&apb0_reset 0>;
 			gpio-controller;
 			#gpio-cells = <3>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 James Pettigrew <james@innovum.com.au>
+ * Copyright (C) 2016 Milo Kim <woogyom.kim@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&leds_npi>, <&leds_r_npi>;
+
+		status {
+			label = "nanopi:blue:status";
+			gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+
+		pwr {
+			label = "nanopi:green:pwr";
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+			default-state = "on";
+		};
+	};
+
+	r_gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "k1";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sw_r_npi>;
+
+		k1@0 {
+			label = "k1";
+			linux,code = <KEY_POWER>;
+			gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+};
+
+&ehci3 {
+	status = "okay";
+};
+
+&mmc0 {
+	bus-width = <4>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+	status = "okay";
+	vmmc-supply = <&reg_vcc3v3>;
+};
+
+&ohci3 {
+	status = "okay";
+};
+
+&pio {
+	leds_npi: led_pins@0 {
+		allwinner,pins = "PA10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&r_pio {
+	leds_r_npi: led_pins@0 {
+		allwinner,pins = "PL10";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	sw_r_npi: key_pins@0 {
+		allwinner,pins = "PL3";
+		allwinner,function = "gpio_in";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-m1.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 Milo Kim <woogyom.kim@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "sun8i-h3-nanopi.dtsi"
+
+/ {
+	model = "FriendlyArm NanoPi M1";
+	compatible = "friendlyarm,nanopi-m1", "allwinner,sun8i-h3";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&ehci2 {
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&ohci2 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts	2017-02-12 16:03:20.000000000 -0500
@@ -40,86 +40,9 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/dts-v1/;
-#include "sun8i-h3.dtsi"
-#include "sunxi-common-regulators.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
+#include "sun8i-h3-nanopi.dtsi"
 
 / {
 	model = "FriendlyARM NanoPi NEO";
 	compatible = "friendlyarm,nanopi-neo", "allwinner,sun8i-h3";
-
-	aliases {
-		serial0 = &uart0;
-	};
-
-	chosen {
-		stdout-path = "serial0:115200n8";
-	};
-
-	leds {
-		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&leds_opc>, <&leds_r_opc>;
-
-		pwr {
-			label = "nanopi:green:pwr";
-			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
-			default-state = "on";
-		};
-
-		status {
-			label = "nanopi:blue:status";
-			gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */
-		};
-	};
-};
-
-&ehci3 {
-	status = "okay";
-};
-
-&mmc0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
-	vmmc-supply = <&reg_vcc3v3>;
-	bus-width = <4>;
-	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
-	cd-inverted;
-	status = "okay";
-};
-
-&ohci3 {
-	status = "okay";
-};
-
-&pio {
-	leds_opc: led-pins {
-		allwinner,pins = "PA10";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
-};
-
-&r_pio {
-	leds_r_opc: led-pins {
-		allwinner,pins = "PL10";
-		allwinner,function = "gpio_out";
-		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-	};
-};
-
-&uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins_a>;
-	status = "okay";
-};
-
-&usbphy {
-	/* USB VBUS is always on */
-	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun8i-reference-design-tablet.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -209,6 +209,13 @@
 	status = "okay";
 };
 
+&reg_ldo_io1 {
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-touchscreen";
+	status = "okay";
+};
+
 &reg_rtc_ldo {
 	regulator-name = "vcc-rtc";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts	2017-02-12 16:03:20.000000000 -0500
@@ -76,6 +76,14 @@
 			gpios = <&pio 7 6 GPIO_ACTIVE_HIGH>; /* PH6 */
 		};
 	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&ac100_rtc 1>;
+		clock-names = "ext_clock";
+		/* enables internal regulator and de-asserts reset */
+		reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 WL-PMU-EN */
+	};
 };
 
 &mmc0 {
@@ -88,6 +96,21 @@
 	status = "okay";
 };
 
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>, <&wifi_en_pin_cubieboard4>;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_cldo3>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&mmc1_pins {
+	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+};
+
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_8bit_pins>;
@@ -128,6 +151,15 @@
 	status = "okay";
 };
 
+&r_pio {
+	wifi_en_pin_cubieboard4: wifi_en_pin@0 {
+		allwinner,pins = "PL2";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+};
+
 &r_rsb {
 	status = "okay";
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun9i-a80.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun9i-a80.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun9i-a80.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun9i-a80.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -678,7 +678,8 @@
 				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apb0_gates 5>;
+			clocks = <&apb0_gates 5>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			gpio-controller;
 			interrupt-controller;
 			#interrupt-cells = <3>;
@@ -700,6 +701,14 @@
 				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 			};
 
+			mmc1_pins: mmc1 {
+				allwinner,pins = "PG0", "PG1" ,"PG2", "PG3",
+						 "PG4", "PG5";
+				allwinner,function = "mmc1";
+				allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+				allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+			};
+
 			mmc2_8bit_pins: mmc2_8bit {
 				allwinner,pins = "PC6", "PC7", "PC8", "PC9",
 						 "PC10", "PC11", "PC12",
@@ -894,7 +903,8 @@
 			reg = <0x08002c00 0x400>;
 			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&apbs_gates 0>;
+			clocks = <&apbs_gates 0>, <&osc24M>, <&osc32k>;
+			clock-names = "apb", "hosc", "losc";
 			resets = <&apbs_rst 0>;
 			gpio-controller;
 			interrupt-controller;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/sun9i-a80-optimus.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun9i-a80-optimus.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/sun9i-a80-optimus.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/sun9i-a80-optimus.dts	2017-02-12 16:03:20.000000000 -0500
@@ -105,6 +105,14 @@
 		enable-active-high;
 		gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
 	};
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		clocks = <&ac100_rtc 1>;
+		clock-names = "ext_clock";
+		/* enables internal regulator and de-asserts reset */
+		reset-gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 WL-PMU-EN */
+	};
 };
 
 &ehci0 {
@@ -130,6 +138,21 @@
 	status = "okay";
 };
 
+&mmc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc1_pins>, <&wifi_en_pin_optimus>;
+	vmmc-supply = <&reg_dldo1>;
+	vqmmc-supply = <&reg_cldo3>;
+	mmc-pwrseq = <&wifi_pwrseq>;
+	bus-width = <4>;
+	non-removable;
+	status = "okay";
+};
+
+&mmc1_pins {
+	allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+};
+
 &mmc2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_8bit_pins>;
@@ -198,6 +221,13 @@
 		allwinner,function = "gpio_out";
 		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
 		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
+	wifi_en_pin_optimus: wifi_en_pin@0 {
+		allwinner,pins = "PL2";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/tegra124-apalis.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra124-apalis.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/tegra124-apalis.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra124-apalis.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -1595,7 +1595,7 @@
 		clock-frequency = <400000>;
 
 		/* SGTL5000 audio codec */
-		sgtl5000: codec@0a {
+		sgtl5000: codec@a {
 			compatible = "fsl,sgtl5000";
 			reg = <0x0a>;
 			VDDA-supply = <&reg_3v3>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra124-nyan.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,12 @@
 		};
 	};
 
+	gpu@0,57000000 {
+		status = "okay";
+
+		vdd-supply = <&vdd_gpu>;
+	};
+
 	serial@70006000 {
 		/* Debug connector on the bottom of the board near SD card. */
 		status = "okay";
@@ -214,7 +220,7 @@
 					regulator-always-on;
 				};
 
-				sd6 {
+				vdd_gpu: sd6 {
 					regulator-name = "+VDD_GPU_AP";
 					regulator-min-microvolt = <650000>;
 					regulator-max-microvolt = <1200000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/tegra20.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra20.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/tegra20.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra20.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -376,6 +376,19 @@
 		status = "disabled";
 	};
 
+	gmi@70009000 {
+		compatible = "nvidia,tegra20-gmi";
+		reg = <0x70009000 0x1000>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0xd0000000 0xfffffff>;
+		clocks = <&tegra_car TEGRA20_CLK_NOR>;
+		clock-names = "gmi";
+		resets = <&tegra_car 42>;
+		reset-names = "gmi";
+		status = "disabled";
+	};
+
 	pwm: pwm@7000a000 {
 		compatible = "nvidia,tegra20-pwm";
 		reg = <0x7000a000 0x100>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra30-apalis.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,24 @@
 		pinctrl-0 = <&state_default>;
 
 		state_default: pinmux {
+			/* Analogue Audio (On-module) */
+			clk1_out_pw4 {
+				nvidia,pins = "clk1_out_pw4";
+				nvidia,function = "extperiph1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap3_fs_pp0 {
+				nvidia,pins =	"dap3_fs_pp0",
+						"dap3_sclk_pp3",
+						"dap3_din_pp1",
+						"dap3_dout_pp2";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
 			/* Apalis BKL1_ON */
 			pv2 {
 				nvidia,pins = "pv2";
@@ -429,6 +447,15 @@
 		status = "okay";
 		clock-frequency = <100000>;
 
+		/* SGTL5000 audio codec */
+		sgtl5000: codec@a {
+			compatible = "fsl,sgtl5000";
+			reg = <0x0a>;
+			VDDA-supply = <&sys_3v3_reg>;
+			VDDIO-supply = <&sys_3v3_reg>;
+			clocks = <&tegra_car TEGRA30_CLK_EXTERN1>;
+		};
+
 		pmic: tps65911@2d {
 			compatible = "ti,tps65911";
 			reg = <0x2d>;
@@ -660,6 +687,12 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
+	ahub@70080000 {
+		i2s@70080500 {
+			status = "okay";
+		};
+	};
+
 	/* eMMC */
 	sdhci@78000600 {
 		status = "okay";
@@ -733,4 +766,20 @@
 			regulator-always-on;
 		};
 	};
+
+	sound {
+		compatible = "toradex,tegra-audio-sgtl5000-apalis_t30",
+			     "nvidia,tegra-audio-sgtl5000";
+		nvidia,model = "Toradex Apalis T30";
+		nvidia,audio-routing =
+			"Headphone Jack", "HP_OUT",
+			"LINE_IN", "Line In Jack",
+			"MIC_IN", "Mic Jack";
+		nvidia,i2s-controller = <&tegra_i2s2>;
+		nvidia,audio-codec = <&sgtl5000>;
+		clocks = <&tegra_car TEGRA30_CLK_PLL_A>,
+			 <&tegra_car TEGRA30_CLK_PLL_A_OUT0>,
+			 <&tegra_car TEGRA30_CLK_EXTERN1>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra30-colibri.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,24 @@
 		pinctrl-0 = <&state_default>;
 
 		state_default: pinmux {
+			/* Analogue Audio (On-module) */
+			clk1_out_pw4 {
+				nvidia,pins = "clk1_out_pw4";
+				nvidia,function = "extperiph1";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+				nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+			};
+			dap3_fs_pp0 {
+				nvidia,pins =	"dap3_fs_pp0",
+						"dap3_sclk_pp3",
+						"dap3_din_pp1",
+						"dap3_dout_pp2";
+				nvidia,function = "i2s2";
+				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+				nvidia,tristate = <TEGRA_PIN_DISABLE>;
+			};
+
 			/* Colibri BL_ON */
 			pv2 {
 				nvidia,pins = "pv2";
@@ -207,6 +225,15 @@
 		status = "okay";
 		clock-frequency = <100000>;
 
+		/* SGTL5000 audio codec */
+		sgtl5000: codec@a {
+			compatible = "fsl,sgtl5000";
+			reg = <0x0a>;
+			VDDA-supply = <&sys_3v3_reg>;
+			VDDIO-supply = <&sys_3v3_reg>;
+			clocks = <&tegra_car TEGRA30_CLK_EXTERN1>;
+		};
+
 		pmic: tps65911@2d {
 			compatible = "ti,tps65911";
 			reg = <0x2d>;
@@ -396,6 +423,12 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
+	ahub@70080000 {
+		i2s@70080500 {
+			status = "okay";
+		};
+	};
+
 	/* eMMC */
 	sdhci@78000600 {
 		status = "okay";
@@ -471,4 +504,20 @@
 			regulator-always-on;
 		};
 	};
+
+	sound {
+		compatible = "toradex,tegra-audio-sgtl5000-colibri_t30",
+			     "nvidia,tegra-audio-sgtl5000";
+		nvidia,model = "Toradex Colibri T30";
+		nvidia,audio-routing =
+			"Headphone Jack", "HP_OUT",
+			"LINE_IN", "Line In Jack",
+			"MIC_IN", "Mic Jack";
+		nvidia,i2s-controller = <&tegra_i2s2>;
+		nvidia,audio-codec = <&sgtl5000>;
+		clocks = <&tegra_car TEGRA30_CLK_PLL_A>,
+			 <&tegra_car TEGRA30_CLK_PLL_A_OUT0>,
+			 <&tegra_car TEGRA30_CLK_EXTERN1>;
+		clock-names = "pll_a", "pll_a_out0", "mclk";
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/tegra30.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra30.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/tegra30.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tegra30.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -439,6 +439,19 @@
 		status = "disabled";
 	};
 
+	gmi@70009000 {
+		compatible = "nvidia,tegra30-gmi";
+		reg = <0x70009000 0x1000>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <0 0 0x48000000 0x7ffffff>;
+		clocks = <&tegra_car TEGRA30_CLK_NOR>;
+		clock-names = "gmi";
+		resets = <&tegra_car 42>;
+		reset-names = "gmi";
+		status = "disabled";
+	};
+
 	pwm: pwm@7000a000 {
 		compatible = "nvidia,tegra30-pwm", "nvidia,tegra20-pwm";
 		reg = <0x7000a000 0x100>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/tps65217.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tps65217.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/tps65217.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/tps65217.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,18 @@
 
 &tps {
 	compatible = "ti,tps65217";
+	interrupt-controller;
+	#interrupt-cells = <1>;
+
+	charger {
+		compatible = "ti,tps65217-charger";
+		status = "disabled";
+	};
+
+	pwrbutton {
+		compatible = "ti,tps65217-pwrbutton";
+		status = "disabled";
+	};
 
 	regulators {
 		#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-common32.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-common32.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-common32.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-common32.dtsi	1969-12-31 19:00:00.000000000 -0500
@@ -1,199 +0,0 @@
-/*
- * Device Tree Source commonly used by UniPhier ARM SoCs
- *
- * Copyright (C) 2015-2016 Socionext Inc.
- *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) 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 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/ "skeleton.dtsi"
-
-/ {
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
-	};
-
-	clocks {
-		refclk: ref {
-			#clock-cells = <0>;
-			compatible = "fixed-clock";
-		};
-	};
-
-	soc: soc {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges;
-		interrupt-parent = <&intc>;
-
-		serial0: serial@54006800 {
-			compatible = "socionext,uniphier-uart";
-			status = "disabled";
-			reg = <0x54006800 0x40>;
-			interrupts = <0 33 4>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_uart0>;
-			clocks = <&peri_clk 0>;
-		};
-
-		serial1: serial@54006900 {
-			compatible = "socionext,uniphier-uart";
-			status = "disabled";
-			reg = <0x54006900 0x40>;
-			interrupts = <0 35 4>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_uart1>;
-			clocks = <&peri_clk 1>;
-		};
-
-		serial2: serial@54006a00 {
-			compatible = "socionext,uniphier-uart";
-			status = "disabled";
-			reg = <0x54006a00 0x40>;
-			interrupts = <0 37 4>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_uart2>;
-			clocks = <&peri_clk 2>;
-		};
-
-		serial3: serial@54006b00 {
-			compatible = "socionext,uniphier-uart";
-			status = "disabled";
-			reg = <0x54006b00 0x40>;
-			interrupts = <0 177 4>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_uart3>;
-			clocks = <&peri_clk 3>;
-		};
-
-		system_bus: system-bus@58c00000 {
-			compatible = "socionext,uniphier-system-bus";
-			status = "disabled";
-			reg = <0x58c00000 0x400>;
-			#address-cells = <2>;
-			#size-cells = <1>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&pinctrl_system_bus>;
-		};
-
-		smpctrl@59800000 {
-			compatible = "socionext,uniphier-smpctrl";
-			reg = <0x59801000 0x400>;
-		};
-
-		mioctrl@59810000 {
-			compatible = "socionext,uniphier-mioctrl",
-				     "simple-mfd", "syscon";
-			reg = <0x59810000 0x800>;
-
-			mio_clk: clock {
-				#clock-cells = <1>;
-			};
-
-			mio_rst: reset {
-				#reset-cells = <1>;
-			};
-		};
-
-		perictrl@59820000 {
-			compatible = "socionext,uniphier-perictrl",
-				     "simple-mfd", "syscon";
-			reg = <0x59820000 0x200>;
-
-			peri_clk: clock {
-				#clock-cells = <1>;
-			};
-
-			peri_rst: reset {
-				#reset-cells = <1>;
-			};
-		};
-
-		timer@60000200 {
-			compatible = "arm,cortex-a9-global-timer";
-			reg = <0x60000200 0x20>;
-			interrupts = <1 11 0x104>;
-			clocks = <&arm_timer_clk>;
-		};
-
-		timer@60000600 {
-			compatible = "arm,cortex-a9-twd-timer";
-			reg = <0x60000600 0x20>;
-			interrupts = <1 13 0x104>;
-			clocks = <&arm_timer_clk>;
-		};
-
-		intc: interrupt-controller@60001000 {
-			compatible = "arm,cortex-a9-gic";
-			reg = <0x60001000 0x1000>,
-			      <0x60000100 0x100>;
-			#interrupt-cells = <3>;
-			interrupt-controller;
-		};
-
-		soc-glue@5f800000 {
-			compatible = "socionext,uniphier-soc-glue",
-				     "simple-mfd", "syscon";
-			reg = <0x5f800000 0x2000>;
-
-			pinctrl: pinctrl {
-				/* specify compatible in each SoC DTSI */
-			};
-		};
-
-		sysctrl@61840000 {
-			compatible = "socionext,uniphier-sysctrl",
-				     "simple-mfd", "syscon";
-			reg = <0x61840000 0x4000>;
-
-			sys_clk: clock {
-				#clock-cells = <1>;
-			};
-
-			sys_rst: reset {
-				#reset-cells = <1>;
-			};
-		};
-	};
-};
-
-/include/ "uniphier-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-ld4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-ld4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-ld4.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-ld4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "uniphier-common32.dtsi"
+/include/ "skeleton.dtsi"
 
 / {
 	compatible = "socionext,uniphier-ld4";
@@ -61,147 +61,267 @@
 		};
 	};
 
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
 	clocks {
+		refclk: ref {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <24576000>;
+		};
+
 		arm_timer_clk: arm_timer_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <50000000>;
 		};
 	};
-};
 
-&soc {
-	l2: l2-cache@500c0000 {
-		compatible = "socionext,uniphier-system-cache";
-		reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>;
-		interrupts = <0 174 4>, <0 175 4>;
-		cache-unified;
-		cache-size = <(512 * 1024)>;
-		cache-sets = <256>;
-		cache-line-size = <128>;
-		cache-level = <2>;
-	};
-
-	i2c0: i2c@58400000 {
-		compatible = "socionext,uniphier-i2c";
-		status = "disabled";
-		reg = <0x58400000 0x40>;
+	soc {
+		compatible = "simple-bus";
 		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 41 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c0>;
-		clocks = <&peri_clk 4>;
-		clock-frequency = <100000>;
-	};
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&intc>;
 
-	i2c1: i2c@58480000 {
-		compatible = "socionext,uniphier-i2c";
-		status = "disabled";
-		reg = <0x58480000 0x40>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 42 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c1>;
-		clocks = <&peri_clk 5>;
-		clock-frequency = <100000>;
-	};
+		l2: l2-cache@500c0000 {
+			compatible = "socionext,uniphier-system-cache";
+			reg = <0x500c0000 0x2000>, <0x503c0100 0x4>,
+			      <0x506c0000 0x400>;
+			interrupts = <0 174 4>, <0 175 4>;
+			cache-unified;
+			cache-size = <(512 * 1024)>;
+			cache-sets = <256>;
+			cache-line-size = <128>;
+			cache-level = <2>;
+		};
 
-	/* chip-internal connection for DMD */
-	i2c2: i2c@58500000 {
-		compatible = "socionext,uniphier-i2c";
-		reg = <0x58500000 0x40>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 43 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c2>;
-		clocks = <&peri_clk 6>;
-		clock-frequency = <400000>;
-	};
+		serial0: serial@54006800 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x40>;
+			interrupts = <0 33 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart0>;
+			clocks = <&peri_clk 0>;
+		};
 
-	i2c3: i2c@58580000 {
-		compatible = "socionext,uniphier-i2c";
-		status = "disabled";
-		reg = <0x58580000 0x40>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 44 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c3>;
-		clocks = <&peri_clk 7>;
-		clock-frequency = <100000>;
-	};
+		serial1: serial@54006900 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x40>;
+			interrupts = <0 35 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart1>;
+			clocks = <&peri_clk 1>;
+		};
 
-	usb0: usb@5a800100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a800100 0x100>;
-		interrupts = <0 80 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb0>;
-		clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
-		resets = <&mio_rst 7>, <&mio_rst 8>, <&mio_rst 12>, <&sys_rst 8>;
-	};
+		serial2: serial@54006a00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x40>;
+			interrupts = <0 37 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart2>;
+			clocks = <&peri_clk 2>;
+		};
 
-	usb1: usb@5a810100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a810100 0x100>;
-		interrupts = <0 81 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb1>;
-		clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
-		resets = <&mio_rst 7>, <&mio_rst 9>, <&mio_rst 13>, <&sys_rst 8>;
-	};
+		serial3: serial@54006b00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x40>;
+			interrupts = <0 29 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart3>;
+			clocks = <&peri_clk 3>;
+		};
 
-	usb2: usb@5a820100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a820100 0x100>;
-		interrupts = <0 82 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb2>;
-		clocks = <&mio_clk 7>, <&mio_clk 10>, <&mio_clk 14>;
-		resets = <&mio_rst 7>, <&mio_rst 10>, <&mio_rst 14>, <&sys_rst 8>;
-	};
+		i2c0: i2c@58400000 {
+			compatible = "socionext,uniphier-i2c";
+			status = "disabled";
+			reg = <0x58400000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 41 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c0>;
+			clocks = <&peri_clk 4>;
+			clock-frequency = <100000>;
+		};
 
-};
+		i2c1: i2c@58480000 {
+			compatible = "socionext,uniphier-i2c";
+			status = "disabled";
+			reg = <0x58480000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 42 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c1>;
+			clocks = <&peri_clk 5>;
+			clock-frequency = <100000>;
+		};
 
-&refclk {
-	clock-frequency = <24576000>;
-};
+		/* chip-internal connection for DMD */
+		i2c2: i2c@58500000 {
+			compatible = "socionext,uniphier-i2c";
+			reg = <0x58500000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 43 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c2>;
+			clocks = <&peri_clk 6>;
+			clock-frequency = <400000>;
+		};
 
-&serial3 {
-	interrupts = <0 29 4>;
-};
+		i2c3: i2c@58580000 {
+			compatible = "socionext,uniphier-i2c";
+			status = "disabled";
+			reg = <0x58580000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 44 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c3>;
+			clocks = <&peri_clk 7>;
+			clock-frequency = <100000>;
+		};
 
-&mio_clk {
-	compatible = "socionext,uniphier-ld4-mio-clock";
-};
+		system_bus: system-bus@58c00000 {
+			compatible = "socionext,uniphier-system-bus";
+			status = "disabled";
+			reg = <0x58c00000 0x400>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_system_bus>;
+		};
 
-&mio_rst {
-	compatible = "socionext,uniphier-ld4-mio-reset";
-	resets = <&sys_rst 7>;
-};
+		smpctrl@59800000 {
+			compatible = "socionext,uniphier-smpctrl";
+			reg = <0x59801000 0x400>;
+		};
 
-&peri_clk {
-	compatible = "socionext,uniphier-ld4-peri-clock";
-};
+		mioctrl@59810000 {
+			compatible = "socionext,uniphier-ld4-mioctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59810000 0x800>;
 
-&peri_rst {
-	compatible = "socionext,uniphier-ld4-peri-reset";
-};
+			mio_clk: clock {
+				compatible = "socionext,uniphier-ld4-mio-clock";
+				#clock-cells = <1>;
+			};
 
-&pinctrl {
-	compatible = "socionext,uniphier-ld4-pinctrl";
-};
+			mio_rst: reset {
+				compatible = "socionext,uniphier-ld4-mio-reset";
+				#reset-cells = <1>;
+			};
+		};
 
-&sys_clk {
-	compatible = "socionext,uniphier-ld4-clock";
-};
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-ld4-perictrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59820000 0x200>;
 
-&sys_rst {
-	compatible = "socionext,uniphier-ld4-reset";
+			peri_clk: clock {
+				compatible = "socionext,uniphier-ld4-peri-clock";
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				compatible = "socionext,uniphier-ld4-peri-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		usb0: usb@5a800100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a800100 0x100>;
+			interrupts = <0 80 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb0>;
+			clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 8>,
+				 <&mio_rst 12>;
+		};
+
+		usb1: usb@5a810100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a810100 0x100>;
+			interrupts = <0 81 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb1>;
+			clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 9>,
+				 <&mio_rst 13>;
+		};
+
+		usb2: usb@5a820100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a820100 0x100>;
+			interrupts = <0 82 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb2>;
+			clocks = <&mio_clk 7>, <&mio_clk 10>, <&mio_clk 14>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 10>,
+				 <&mio_rst 14>;
+		};
+
+		soc-glue@5f800000 {
+			compatible = "socionext,uniphier-ld4-soc-glue",
+				     "simple-mfd", "syscon";
+			reg = <0x5f800000 0x2000>;
+
+			pinctrl: pinctrl {
+				compatible = "socionext,uniphier-ld4-pinctrl";
+			};
+		};
+
+		timer@60000200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0x60000200 0x20>;
+			interrupts = <1 11 0x104>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		timer@60000600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x60000600 0x20>;
+			interrupts = <1 13 0x104>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		intc: interrupt-controller@60001000 {
+			compatible = "arm,cortex-a9-gic";
+			reg = <0x60001000 0x1000>,
+			      <0x60000100 0x100>;
+			#interrupt-cells = <3>;
+			interrupt-controller;
+		};
+
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-ld4-sysctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x61840000 0x10000>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-ld4-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-ld4-reset";
+				#reset-cells = <1>;
+			};
+		};
+	};
 };
+
+/include/ "uniphier-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-pro4.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-pro4.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-pro4.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-pro4.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "uniphier-common32.dtsi"
+/include/ "skeleton.dtsi"
 
 / {
 	compatible = "socionext,uniphier-pro4";
@@ -69,155 +69,279 @@
 		};
 	};
 
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
 	clocks {
+		refclk: ref {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
 		arm_timer_clk: arm_timer_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <50000000>;
 		};
 	};
-};
-
-&soc {
-	l2: l2-cache@500c0000 {
-		compatible = "socionext,uniphier-system-cache";
-		reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>;
-		interrupts = <0 174 4>, <0 175 4>;
-		cache-unified;
-		cache-size = <(768 * 1024)>;
-		cache-sets = <256>;
-		cache-line-size = <128>;
-		cache-level = <2>;
-	};
 
-	i2c0: i2c@58780000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58780000 0x80>;
+	soc {
+		compatible = "simple-bus";
 		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 41 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c0>;
-		clocks = <&peri_clk 4>;
-		clock-frequency = <100000>;
-	};
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&intc>;
 
-	i2c1: i2c@58781000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58781000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 42 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c1>;
-		clocks = <&peri_clk 5>;
-		clock-frequency = <100000>;
-	};
+		l2: l2-cache@500c0000 {
+			compatible = "socionext,uniphier-system-cache";
+			reg = <0x500c0000 0x2000>, <0x503c0100 0x4>,
+			      <0x506c0000 0x400>;
+			interrupts = <0 174 4>, <0 175 4>;
+			cache-unified;
+			cache-size = <(768 * 1024)>;
+			cache-sets = <256>;
+			cache-line-size = <128>;
+			cache-level = <2>;
+		};
 
-	i2c2: i2c@58782000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58782000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 43 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c2>;
-		clocks = <&peri_clk 6>;
-		clock-frequency = <100000>;
-	};
+		serial0: serial@54006800 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x40>;
+			interrupts = <0 33 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart0>;
+			clocks = <&peri_clk 0>;
+		};
 
-	i2c3: i2c@58783000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58783000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 44 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c3>;
-		clocks = <&peri_clk 7>;
-		clock-frequency = <100000>;
-	};
+		serial1: serial@54006900 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x40>;
+			interrupts = <0 35 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart1>;
+			clocks = <&peri_clk 1>;
+		};
 
-	/* i2c4 does not exist */
+		serial2: serial@54006a00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x40>;
+			interrupts = <0 37 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart2>;
+			clocks = <&peri_clk 2>;
+		};
 
-	/* chip-internal connection for DMD */
-	i2c5: i2c@58785000 {
-		compatible = "socionext,uniphier-fi2c";
-		reg = <0x58785000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 25 4>;
-		clocks = <&peri_clk 9>;
-		clock-frequency = <400000>;
-	};
+		serial3: serial@54006b00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x40>;
+			interrupts = <0 177 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart3>;
+			clocks = <&peri_clk 3>;
+		};
 
-	/* chip-internal connection for HDMI */
-	i2c6: i2c@58786000 {
-		compatible = "socionext,uniphier-fi2c";
-		reg = <0x58786000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 26 4>;
-		clocks = <&peri_clk 10>;
-		clock-frequency = <400000>;
-	};
+		i2c0: i2c@58780000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58780000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 41 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c0>;
+			clocks = <&peri_clk 4>;
+			clock-frequency = <100000>;
+		};
 
-	usb2: usb@5a800100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a800100 0x100>;
-		interrupts = <0 80 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb2>;
-		clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
-		resets = <&mio_rst 7>, <&mio_rst 8>, <&mio_rst 12>, <&sys_rst 8>;
-	};
+		i2c1: i2c@58781000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58781000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 42 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c1>;
+			clocks = <&peri_clk 5>;
+			clock-frequency = <100000>;
+		};
 
-	usb3: usb@5a810100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a810100 0x100>;
-		interrupts = <0 81 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb3>;
-		clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
-		resets = <&mio_rst 7>, <&mio_rst 9>, <&mio_rst 13>, <&sys_rst 8>;
-	};
-};
+		i2c2: i2c@58782000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58782000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 43 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c2>;
+			clocks = <&peri_clk 6>;
+			clock-frequency = <100000>;
+		};
 
-&refclk {
-	clock-frequency = <25000000>;
-};
+		i2c3: i2c@58783000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58783000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 44 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c3>;
+			clocks = <&peri_clk 7>;
+			clock-frequency = <100000>;
+		};
 
-&mio_clk {
-	compatible = "socionext,uniphier-pro4-mio-clock";
-};
+		/* i2c4 does not exist */
 
-&mio_rst {
-	compatible = "socionext,uniphier-pro4-mio-reset";
-	resets = <&sys_rst 7>;
-};
+		/* chip-internal connection for DMD */
+		i2c5: i2c@58785000 {
+			compatible = "socionext,uniphier-fi2c";
+			reg = <0x58785000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 25 4>;
+			clocks = <&peri_clk 9>;
+			clock-frequency = <400000>;
+		};
 
-&peri_clk {
-	compatible = "socionext,uniphier-pro4-peri-clock";
-};
+		/* chip-internal connection for HDMI */
+		i2c6: i2c@58786000 {
+			compatible = "socionext,uniphier-fi2c";
+			reg = <0x58786000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 26 4>;
+			clocks = <&peri_clk 10>;
+			clock-frequency = <400000>;
+		};
 
-&peri_rst {
-	compatible = "socionext,uniphier-pro4-peri-reset";
-};
+		system_bus: system-bus@58c00000 {
+			compatible = "socionext,uniphier-system-bus";
+			status = "disabled";
+			reg = <0x58c00000 0x400>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_system_bus>;
+		};
 
-&pinctrl {
-	compatible = "socionext,uniphier-pro4-pinctrl";
-};
+		smpctrl@59800000 {
+			compatible = "socionext,uniphier-smpctrl";
+			reg = <0x59801000 0x400>;
+		};
 
-&sys_clk {
-	compatible = "socionext,uniphier-pro4-clock";
-};
+		mioctrl@59810000 {
+			compatible = "socionext,uniphier-pro4-mioctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59810000 0x800>;
 
-&sys_rst {
-	compatible = "socionext,uniphier-pro4-reset";
+			mio_clk: clock {
+				compatible = "socionext,uniphier-pro4-mio-clock";
+				#clock-cells = <1>;
+			};
+
+			mio_rst: reset {
+				compatible = "socionext,uniphier-pro4-mio-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-pro4-perictrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59820000 0x200>;
+
+			peri_clk: clock {
+				compatible = "socionext,uniphier-pro4-peri-clock";
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				compatible = "socionext,uniphier-pro4-peri-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		usb2: usb@5a800100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a800100 0x100>;
+			interrupts = <0 80 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb2>;
+			clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 8>,
+				 <&mio_rst 12>;
+		};
+
+		usb3: usb@5a810100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a810100 0x100>;
+			interrupts = <0 81 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb3>;
+			clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 9>,
+				 <&mio_rst 13>;
+		};
+
+		soc-glue@5f800000 {
+			compatible = "socionext,uniphier-pro4-soc-glue",
+				     "simple-mfd", "syscon";
+			reg = <0x5f800000 0x2000>;
+
+			pinctrl: pinctrl {
+				compatible = "socionext,uniphier-pro4-pinctrl";
+			};
+		};
+
+		timer@60000200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0x60000200 0x20>;
+			interrupts = <1 11 0x304>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		timer@60000600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x60000600 0x20>;
+			interrupts = <1 13 0x304>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		intc: interrupt-controller@60001000 {
+			compatible = "arm,cortex-a9-gic";
+			reg = <0x60001000 0x1000>,
+			      <0x60000100 0x100>;
+			#interrupt-cells = <3>;
+			interrupt-controller;
+		};
+
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-pro4-sysctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x61840000 0x10000>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-pro4-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-pro4-reset";
+				#reset-cells = <1>;
+			};
+		};
+	};
 };
+
+/include/ "uniphier-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-pro5.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-pro5.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-pro5.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-pro5.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "uniphier-common32.dtsi"
+/include/ "skeleton.dtsi"
 
 / {
 	compatible = "socionext,uniphier-pro5";
@@ -56,157 +56,355 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+			clocks = <&sys_clk 32>;
 			enable-method = "psci";
 			next-level-cache = <&l2>;
+			operating-points-v2 = <&cpu_opp>;
 		};
 
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
+			clocks = <&sys_clk 32>;
 			enable-method = "psci";
 			next-level-cache = <&l2>;
+			operating-points-v2 = <&cpu_opp>;
+		};
+	};
+
+	cpu_opp: opp_table {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@116667000 {
+			opp-hz = /bits/ 64 <116667000>;
+			clock-latency-ns = <300>;
+		};
+		opp@150000000 {
+			opp-hz = /bits/ 64 <150000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@175000000 {
+			opp-hz = /bits/ 64 <175000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@233334000 {
+			opp-hz = /bits/ 64 <233334000>;
+			clock-latency-ns = <300>;
+		};
+		opp@300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@350000000 {
+			opp-hz = /bits/ 64 <350000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@466667000 {
+			opp-hz = /bits/ 64 <466667000>;
+			clock-latency-ns = <300>;
+		};
+		opp@600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@700000000 {
+			opp-hz = /bits/ 64 <700000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@933334000 {
+			opp-hz = /bits/ 64 <933334000>;
+			clock-latency-ns = <300>;
 		};
+		opp@1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@1400000000 {
+			opp-hz = /bits/ 64 <1400000000>;
+			clock-latency-ns = <300>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
 	};
 
 	clocks {
+		refclk: ref {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <20000000>;
+		};
+
 		arm_timer_clk: arm_timer_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <50000000>;
 		};
 	};
-};
 
-&soc {
-	l2: l2-cache@500c0000 {
-		compatible = "socionext,uniphier-system-cache";
-		reg = <0x500c0000 0x2000>, <0x503c0100 0x8>, <0x506c0000 0x400>;
-		interrupts = <0 190 4>, <0 191 4>;
-		cache-unified;
-		cache-size = <(2 * 1024 * 1024)>;
-		cache-sets = <512>;
-		cache-line-size = <128>;
-		cache-level = <2>;
-		next-level-cache = <&l3>;
-	};
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&intc>;
 
-	l3: l3-cache@500c8000 {
-		compatible = "socionext,uniphier-system-cache";
-		reg = <0x500c8000 0x2000>, <0x503c8100 0x8>, <0x506c8000 0x400>;
-		interrupts = <0 174 4>, <0 175 4>;
-		cache-unified;
-		cache-size = <(2 * 1024 * 1024)>;
-		cache-sets = <512>;
-		cache-line-size = <256>;
-		cache-level = <3>;
-	};
+		l2: l2-cache@500c0000 {
+			compatible = "socionext,uniphier-system-cache";
+			reg = <0x500c0000 0x2000>, <0x503c0100 0x8>,
+			      <0x506c0000 0x400>;
+			interrupts = <0 190 4>, <0 191 4>;
+			cache-unified;
+			cache-size = <(2 * 1024 * 1024)>;
+			cache-sets = <512>;
+			cache-line-size = <128>;
+			cache-level = <2>;
+			next-level-cache = <&l3>;
+		};
 
-	i2c0: i2c@58780000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58780000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 41 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c0>;
-		clocks = <&peri_clk 4>;
-		clock-frequency = <100000>;
-	};
+		l3: l3-cache@500c8000 {
+			compatible = "socionext,uniphier-system-cache";
+			reg = <0x500c8000 0x2000>, <0x503c8100 0x8>,
+			      <0x506c8000 0x400>;
+			interrupts = <0 174 4>, <0 175 4>;
+			cache-unified;
+			cache-size = <(2 * 1024 * 1024)>;
+			cache-sets = <512>;
+			cache-line-size = <256>;
+			cache-level = <3>;
+		};
 
-	i2c1: i2c@58781000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58781000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 42 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c1>;
-		clocks = <&peri_clk 5>;
-		clock-frequency = <100000>;
-	};
+		serial0: serial@54006800 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x40>;
+			interrupts = <0 33 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart0>;
+			clocks = <&peri_clk 0>;
+		};
 
-	i2c2: i2c@58782000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58782000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 43 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c2>;
-		clocks = <&peri_clk 6>;
-		clock-frequency = <100000>;
-	};
+		serial1: serial@54006900 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x40>;
+			interrupts = <0 35 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart1>;
+			clocks = <&peri_clk 1>;
+		};
 
-	i2c3: i2c@58783000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58783000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 44 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c3>;
-		clocks = <&peri_clk 7>;
-		clock-frequency = <100000>;
-	};
+		serial2: serial@54006a00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x40>;
+			interrupts = <0 37 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart2>;
+			clocks = <&peri_clk 2>;
+		};
 
-	/* i2c4 does not exist */
+		serial3: serial@54006b00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x40>;
+			interrupts = <0 177 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart3>;
+			clocks = <&peri_clk 3>;
+		};
 
-	/* chip-internal connection for DMD */
-	i2c5: i2c@58785000 {
-		compatible = "socionext,uniphier-fi2c";
-		reg = <0x58785000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 25 4>;
-		clocks = <&peri_clk 9>;
-		clock-frequency = <400000>;
-	};
+		i2c0: i2c@58780000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58780000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 41 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c0>;
+			clocks = <&peri_clk 4>;
+			clock-frequency = <100000>;
+		};
 
-	/* chip-internal connection for HDMI */
-	i2c6: i2c@58786000 {
-		compatible = "socionext,uniphier-fi2c";
-		reg = <0x58786000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 26 4>;
-		clocks = <&peri_clk 10>;
-		clock-frequency = <400000>;
-	};
-};
+		i2c1: i2c@58781000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58781000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 42 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c1>;
+			clocks = <&peri_clk 5>;
+			clock-frequency = <100000>;
+		};
 
-&refclk {
-	clock-frequency = <20000000>;
-};
+		i2c2: i2c@58782000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58782000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 43 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c2>;
+			clocks = <&peri_clk 6>;
+			clock-frequency = <100000>;
+		};
 
-&mio_clk {
-	compatible = "socionext,uniphier-pro5-sd-clock";
-};
+		i2c3: i2c@58783000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58783000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 44 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c3>;
+			clocks = <&peri_clk 7>;
+			clock-frequency = <100000>;
+		};
 
-&mio_rst {
-	compatible = "socionext,uniphier-pro5-sd-reset";
-};
+		/* i2c4 does not exist */
 
-&peri_clk {
-	compatible = "socionext,uniphier-pro5-peri-clock";
-};
+		/* chip-internal connection for DMD */
+		i2c5: i2c@58785000 {
+			compatible = "socionext,uniphier-fi2c";
+			reg = <0x58785000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 25 4>;
+			clocks = <&peri_clk 9>;
+			clock-frequency = <400000>;
+		};
 
-&peri_rst {
-	compatible = "socionext,uniphier-pro5-peri-reset";
-};
+		/* chip-internal connection for HDMI */
+		i2c6: i2c@58786000 {
+			compatible = "socionext,uniphier-fi2c";
+			reg = <0x58786000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 26 4>;
+			clocks = <&peri_clk 10>;
+			clock-frequency = <400000>;
+		};
 
-&pinctrl {
-	compatible = "socionext,uniphier-pro5-pinctrl";
-};
+		system_bus: system-bus@58c00000 {
+			compatible = "socionext,uniphier-system-bus";
+			status = "disabled";
+			reg = <0x58c00000 0x400>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_system_bus>;
+		};
 
-&sys_clk {
-	compatible = "socionext,uniphier-pro5-clock";
-};
+		smpctrl@59800000 {
+			compatible = "socionext,uniphier-smpctrl";
+			reg = <0x59801000 0x400>;
+		};
 
-&sys_rst {
-	compatible = "socionext,uniphier-pro5-reset";
+		sdctrl@59810000 {
+			compatible = "socionext,uniphier-pro5-sdctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59810000 0x800>;
+
+			sd_clk: clock {
+				compatible = "socionext,uniphier-pro5-sd-clock";
+				#clock-cells = <1>;
+			};
+
+			sd_rst: reset {
+				compatible = "socionext,uniphier-pro5-sd-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-pro5-perictrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59820000 0x200>;
+
+			peri_clk: clock {
+				compatible = "socionext,uniphier-pro5-peri-clock";
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				compatible = "socionext,uniphier-pro5-peri-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		soc-glue@5f800000 {
+			compatible = "socionext,uniphier-pro5-soc-glue",
+				     "simple-mfd", "syscon";
+			reg = <0x5f800000 0x2000>;
+
+			pinctrl: pinctrl {
+				compatible = "socionext,uniphier-pro5-pinctrl";
+			};
+		};
+
+		timer@60000200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0x60000200 0x20>;
+			interrupts = <1 11 0x304>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		timer@60000600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x60000600 0x20>;
+			interrupts = <1 13 0x304>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		intc: interrupt-controller@60001000 {
+			compatible = "arm,cortex-a9-gic";
+			reg = <0x60001000 0x1000>,
+			      <0x60000100 0x100>;
+			#interrupt-cells = <3>;
+			interrupt-controller;
+		};
+
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-pro5-sysctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x61840000 0x10000>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-pro5-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-pro5-reset";
+				#reset-cells = <1>;
+			};
+		};
+	};
 };
+
+/include/ "uniphier-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-pxs2.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-pxs2.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-pxs2.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-pxs2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "uniphier-common32.dtsi"
+/include/ "skeleton.dtsi"
 
 / {
 	compatible = "socionext,uniphier-pxs2";
@@ -56,170 +56,339 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <0>;
+			clocks = <&sys_clk 32>;
 			enable-method = "psci";
 			next-level-cache = <&l2>;
+			operating-points-v2 = <&cpu_opp>;
 		};
 
 		cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <1>;
+			clocks = <&sys_clk 32>;
 			enable-method = "psci";
 			next-level-cache = <&l2>;
+			operating-points-v2 = <&cpu_opp>;
 		};
 
 		cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <2>;
+			clocks = <&sys_clk 32>;
 			enable-method = "psci";
 			next-level-cache = <&l2>;
+			operating-points-v2 = <&cpu_opp>;
 		};
 
 		cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a9";
 			reg = <3>;
+			clocks = <&sys_clk 32>;
 			enable-method = "psci";
 			next-level-cache = <&l2>;
+			operating-points-v2 = <&cpu_opp>;
+		};
+	};
+
+	cpu_opp: opp_table {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@100000000 {
+			opp-hz = /bits/ 64 <100000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@150000000 {
+			opp-hz = /bits/ 64 <150000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@300000000 {
+			opp-hz = /bits/ 64 <300000000>;
+			clock-latency-ns = <300>;
 		};
+		opp@400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
+			clock-latency-ns = <300>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
 	};
 
 	clocks {
+		refclk: ref {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
 		arm_timer_clk: arm_timer_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <50000000>;
 		};
 	};
-};
 
-&soc {
-	l2: l2-cache@500c0000 {
-		compatible = "socionext,uniphier-system-cache";
-		reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>;
-		interrupts = <0 174 4>, <0 175 4>, <0 190 4>, <0 191 4>;
-		cache-unified;
-		cache-size = <(1280 * 1024)>;
-		cache-sets = <512>;
-		cache-line-size = <128>;
-		cache-level = <2>;
-	};
-
-	i2c0: i2c@58780000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58780000 0x80>;
+	soc {
+		compatible = "simple-bus";
 		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 41 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c0>;
-		clocks = <&peri_clk 4>;
-		clock-frequency = <100000>;
-	};
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&intc>;
 
-	i2c1: i2c@58781000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58781000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 42 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c1>;
-		clocks = <&peri_clk 5>;
-		clock-frequency = <100000>;
-	};
+		l2: l2-cache@500c0000 {
+			compatible = "socionext,uniphier-system-cache";
+			reg = <0x500c0000 0x2000>, <0x503c0100 0x8>,
+			      <0x506c0000 0x400>;
+			interrupts = <0 174 4>, <0 175 4>, <0 190 4>, <0 191 4>;
+			cache-unified;
+			cache-size = <(1280 * 1024)>;
+			cache-sets = <512>;
+			cache-line-size = <128>;
+			cache-level = <2>;
+		};
 
-	i2c2: i2c@58782000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58782000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c2>;
-		interrupts = <0 43 4>;
-		clocks = <&peri_clk 6>;
-		clock-frequency = <100000>;
-	};
+		serial0: serial@54006800 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x40>;
+			interrupts = <0 33 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart0>;
+			clocks = <&peri_clk 0>;
+		};
 
-	i2c3: i2c@58783000 {
-		compatible = "socionext,uniphier-fi2c";
-		status = "disabled";
-		reg = <0x58783000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 44 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c3>;
-		clocks = <&peri_clk 7>;
-		clock-frequency = <100000>;
-	};
+		serial1: serial@54006900 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x40>;
+			interrupts = <0 35 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart1>;
+			clocks = <&peri_clk 1>;
+		};
 
-	/* chip-internal connection for DMD */
-	i2c4: i2c@58784000 {
-		compatible = "socionext,uniphier-fi2c";
-		reg = <0x58784000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 45 4>;
-		clocks = <&peri_clk 8>;
-		clock-frequency = <400000>;
-	};
+		serial2: serial@54006a00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x40>;
+			interrupts = <0 37 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart2>;
+			clocks = <&peri_clk 2>;
+		};
 
-	/* chip-internal connection for STM */
-	i2c5: i2c@58785000 {
-		compatible = "socionext,uniphier-fi2c";
-		reg = <0x58785000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 25 4>;
-		clocks = <&peri_clk 9>;
-		clock-frequency = <400000>;
-	};
+		serial3: serial@54006b00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x40>;
+			interrupts = <0 177 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart3>;
+			clocks = <&peri_clk 3>;
+		};
 
-	/* chip-internal connection for HDMI */
-	i2c6: i2c@58786000 {
-		compatible = "socionext,uniphier-fi2c";
-		reg = <0x58786000 0x80>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 26 4>;
-		clocks = <&peri_clk 10>;
-		clock-frequency = <400000>;
-	};
-};
+		i2c0: i2c@58780000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58780000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 41 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c0>;
+			clocks = <&peri_clk 4>;
+			clock-frequency = <100000>;
+		};
 
-&refclk {
-	clock-frequency = <25000000>;
-};
+		i2c1: i2c@58781000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58781000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 42 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c1>;
+			clocks = <&peri_clk 5>;
+			clock-frequency = <100000>;
+		};
 
-&mio_clk {
-	compatible = "socionext,uniphier-pxs2-sd-clock";
-};
+		i2c2: i2c@58782000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58782000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 43 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c2>;
+			clocks = <&peri_clk 6>;
+			clock-frequency = <100000>;
+		};
 
-&mio_rst {
-	compatible = "socionext,uniphier-pxs2-sd-reset";
-};
+		i2c3: i2c@58783000 {
+			compatible = "socionext,uniphier-fi2c";
+			status = "disabled";
+			reg = <0x58783000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 44 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c3>;
+			clocks = <&peri_clk 7>;
+			clock-frequency = <100000>;
+		};
 
-&peri_clk {
-	compatible = "socionext,uniphier-pxs2-peri-clock";
-};
+		/* chip-internal connection for DMD */
+		i2c4: i2c@58784000 {
+			compatible = "socionext,uniphier-fi2c";
+			reg = <0x58784000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 45 4>;
+			clocks = <&peri_clk 8>;
+			clock-frequency = <400000>;
+		};
 
-&peri_rst {
-	compatible = "socionext,uniphier-pxs2-peri-reset";
-};
+		/* chip-internal connection for STM */
+		i2c5: i2c@58785000 {
+			compatible = "socionext,uniphier-fi2c";
+			reg = <0x58785000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 25 4>;
+			clocks = <&peri_clk 9>;
+			clock-frequency = <400000>;
+		};
 
-&pinctrl {
-	compatible = "socionext,uniphier-pxs2-pinctrl";
-};
+		/* chip-internal connection for HDMI */
+		i2c6: i2c@58786000 {
+			compatible = "socionext,uniphier-fi2c";
+			reg = <0x58786000 0x80>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 26 4>;
+			clocks = <&peri_clk 10>;
+			clock-frequency = <400000>;
+		};
 
-&sys_clk {
-	compatible = "socionext,uniphier-pxs2-clock";
-};
+		system_bus: system-bus@58c00000 {
+			compatible = "socionext,uniphier-system-bus";
+			status = "disabled";
+			reg = <0x58c00000 0x400>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_system_bus>;
+		};
 
-&sys_rst {
-	compatible = "socionext,uniphier-pxs2-reset";
+		smpctrl@59800000 {
+			compatible = "socionext,uniphier-smpctrl";
+			reg = <0x59801000 0x400>;
+		};
+
+		sdctrl@59810000 {
+			compatible = "socionext,uniphier-pxs2-sdctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59810000 0x800>;
+
+			sd_clk: clock {
+				compatible = "socionext,uniphier-pxs2-sd-clock";
+				#clock-cells = <1>;
+			};
+
+			sd_rst: reset {
+				compatible = "socionext,uniphier-pxs2-sd-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-pxs2-perictrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59820000 0x200>;
+
+			peri_clk: clock {
+				compatible = "socionext,uniphier-pxs2-peri-clock";
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				compatible = "socionext,uniphier-pxs2-peri-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		soc-glue@5f800000 {
+			compatible = "socionext,uniphier-pxs2-soc-glue",
+				     "simple-mfd", "syscon";
+			reg = <0x5f800000 0x2000>;
+
+			pinctrl: pinctrl {
+				compatible = "socionext,uniphier-pxs2-pinctrl";
+			};
+		};
+
+		timer@60000200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0x60000200 0x20>;
+			interrupts = <1 11 0xf04>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		timer@60000600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x60000600 0x20>;
+			interrupts = <1 13 0xf04>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		intc: interrupt-controller@60001000 {
+			compatible = "arm,cortex-a9-gic";
+			reg = <0x60001000 0x1000>,
+			      <0x60000100 0x100>;
+			#interrupt-cells = <3>;
+			interrupt-controller;
+		};
+
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-pxs2-sysctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x61840000 0x10000>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-pxs2-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-pxs2-reset";
+				#reset-cells = <1>;
+			};
+		};
+	};
 };
+
+/include/ "uniphier-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-sld3.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-sld3.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-sld3.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-sld3.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -135,7 +135,6 @@
 			reg = <0x54006800 0x40>;
 			interrupts = <0 33 4>;
 			clocks = <&sys_clk 0>;
-			fifo-size = <64>;
 		};
 
 		serial1: serial@54006900 {
@@ -144,7 +143,6 @@
 			reg = <0x54006900 0x40>;
 			interrupts = <0 35 4>;
 			clocks = <&sys_clk 0>;
-			fifo-size = <64>;
 		};
 
 		serial2: serial@54006a00 {
@@ -153,7 +151,6 @@
 			reg = <0x54006a00 0x40>;
 			interrupts = <0 37 4>;
 			clocks = <&sys_clk 0>;
-			fifo-size = <64>;
 		};
 
 		i2c0: i2c@58400000 {
@@ -225,7 +222,7 @@
 		};
 
 		mioctrl@59810000 {
-			compatible = "socionext,uniphier-mioctrl",
+			compatible = "socionext,uniphier-sld3-mioctrl",
 				     "simple-mfd", "syscon";
 			reg = <0x59810000 0x800>;
 
@@ -245,6 +242,9 @@
 			status = "disabled";
 			reg = <0x5a800100 0x100>;
 			interrupts = <0 80 4>;
+			clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 8>,
+				 <&mio_rst 12>;
 		};
 
 		usb1: usb@5a810100 {
@@ -252,6 +252,9 @@
 			status = "disabled";
 			reg = <0x5a810100 0x100>;
 			interrupts = <0 81 4>;
+			clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 9>,
+				 <&mio_rst 13>;
 		};
 
 		usb2: usb@5a820100 {
@@ -259,6 +262,9 @@
 			status = "disabled";
 			reg = <0x5a820100 0x100>;
 			interrupts = <0 82 4>;
+			clocks = <&mio_clk 7>, <&mio_clk 10>, <&mio_clk 14>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 10>,
+				 <&mio_rst 14>;
 		};
 
 		usb3: usb@5a830100 {
@@ -266,12 +272,15 @@
 			status = "disabled";
 			reg = <0x5a830100 0x100>;
 			interrupts = <0 83 4>;
+			clocks = <&mio_clk 7>, <&mio_clk 11>, <&mio_clk 15>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 11>,
+				 <&mio_rst 15>;
 		};
 
 		sysctrl@f1840000 {
-			compatible = "socionext,uniphier-sysctrl",
+			compatible = "socionext,uniphier-sld3-sysctrl",
 				     "simple-mfd", "syscon";
-			reg = <0xf1840000 0x4000>;
+			reg = <0xf1840000 0x10000>;
 
 			sys_clk: clock {
 				compatible = "socionext,uniphier-sld3-clock";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-sld8.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-sld8.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/uniphier-sld8.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/uniphier-sld8.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "uniphier-common32.dtsi"
+/include/ "skeleton.dtsi"
 
 / {
 	compatible = "socionext,uniphier-sld8";
@@ -61,146 +61,267 @@
 		};
 	};
 
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
 	clocks {
+		refclk: ref {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <25000000>;
+		};
+
 		arm_timer_clk: arm_timer_clk {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <50000000>;
 		};
 	};
-};
 
-&soc {
-	l2: l2-cache@500c0000 {
-		compatible = "socionext,uniphier-system-cache";
-		reg = <0x500c0000 0x2000>, <0x503c0100 0x4>, <0x506c0000 0x400>;
-		interrupts = <0 174 4>, <0 175 4>;
-		cache-unified;
-		cache-size = <(256 * 1024)>;
-		cache-sets = <256>;
-		cache-line-size = <128>;
-		cache-level = <2>;
-	};
-
-	i2c0: i2c@58400000 {
-		compatible = "socionext,uniphier-i2c";
-		status = "disabled";
-		reg = <0x58400000 0x40>;
+	soc {
+		compatible = "simple-bus";
 		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 41 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c0>;
-		clocks = <&peri_clk 4>;
-		clock-frequency = <100000>;
-	};
+		#size-cells = <1>;
+		ranges;
+		interrupt-parent = <&intc>;
 
-	i2c1: i2c@58480000 {
-		compatible = "socionext,uniphier-i2c";
-		status = "disabled";
-		reg = <0x58480000 0x40>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 42 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c1>;
-		clocks = <&peri_clk 5>;
-		clock-frequency = <100000>;
-	};
+		l2: l2-cache@500c0000 {
+			compatible = "socionext,uniphier-system-cache";
+			reg = <0x500c0000 0x2000>, <0x503c0100 0x4>,
+			      <0x506c0000 0x400>;
+			interrupts = <0 174 4>, <0 175 4>;
+			cache-unified;
+			cache-size = <(256 * 1024)>;
+			cache-sets = <256>;
+			cache-line-size = <128>;
+			cache-level = <2>;
+		};
 
-	/* chip-internal connection for DMD */
-	i2c2: i2c@58500000 {
-		compatible = "socionext,uniphier-i2c";
-		reg = <0x58500000 0x40>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 43 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c2>;
-		clocks = <&peri_clk 6>;
-		clock-frequency = <400000>;
-	};
+		serial0: serial@54006800 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006800 0x40>;
+			interrupts = <0 33 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart0>;
+			clocks = <&peri_clk 0>;
+		};
 
-	i2c3: i2c@58580000 {
-		compatible = "socionext,uniphier-i2c";
-		status = "disabled";
-		reg = <0x58580000 0x40>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		interrupts = <0 44 1>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c3>;
-		clocks = <&peri_clk 7>;
-		clock-frequency = <100000>;
-	};
+		serial1: serial@54006900 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006900 0x40>;
+			interrupts = <0 35 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart1>;
+			clocks = <&peri_clk 1>;
+		};
 
-	usb0: usb@5a800100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a800100 0x100>;
-		interrupts = <0 80 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb0>;
-		clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
-		resets = <&mio_rst 7>, <&mio_rst 8>, <&mio_rst 12>, <&sys_rst 8>;
-	};
+		serial2: serial@54006a00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006a00 0x40>;
+			interrupts = <0 37 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart2>;
+			clocks = <&peri_clk 2>;
+		};
 
-	usb1: usb@5a810100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a810100 0x100>;
-		interrupts = <0 81 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb1>;
-		clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
-		resets = <&mio_rst 7>, <&mio_rst 9>, <&mio_rst 13>, <&sys_rst 8>;
-	};
+		serial3: serial@54006b00 {
+			compatible = "socionext,uniphier-uart";
+			status = "disabled";
+			reg = <0x54006b00 0x40>;
+			interrupts = <0 29 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_uart3>;
+			clocks = <&peri_clk 3>;
+		};
 
-	usb2: usb@5a820100 {
-		compatible = "socionext,uniphier-ehci", "generic-ehci";
-		status = "disabled";
-		reg = <0x5a820100 0x100>;
-		interrupts = <0 82 4>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_usb2>;
-		clocks = <&mio_clk 7>, <&mio_clk 10>, <&mio_clk 14>;
-		resets = <&mio_rst 7>, <&mio_rst 10>, <&mio_rst 14>, <&sys_rst 8>;
-	};
-};
+		i2c0: i2c@58400000 {
+			compatible = "socionext,uniphier-i2c";
+			status = "disabled";
+			reg = <0x58400000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 41 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c0>;
+			clocks = <&peri_clk 4>;
+			clock-frequency = <100000>;
+		};
 
-&refclk {
-	clock-frequency = <25000000>;
-};
+		i2c1: i2c@58480000 {
+			compatible = "socionext,uniphier-i2c";
+			status = "disabled";
+			reg = <0x58480000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 42 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c1>;
+			clocks = <&peri_clk 5>;
+			clock-frequency = <100000>;
+		};
 
-&serial3 {
-	interrupts = <0 29 4>;
-};
+		/* chip-internal connection for DMD */
+		i2c2: i2c@58500000 {
+			compatible = "socionext,uniphier-i2c";
+			reg = <0x58500000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 43 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c2>;
+			clocks = <&peri_clk 6>;
+			clock-frequency = <400000>;
+		};
 
-&mio_clk {
-	compatible = "socionext,uniphier-sld8-mio-clock";
-};
+		i2c3: i2c@58580000 {
+			compatible = "socionext,uniphier-i2c";
+			status = "disabled";
+			reg = <0x58580000 0x40>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0 44 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_i2c3>;
+			clocks = <&peri_clk 7>;
+			clock-frequency = <100000>;
+		};
 
-&mio_rst {
-	compatible = "socionext,uniphier-sld8-mio-reset";
-	resets = <&sys_rst 7>;
-};
+		system_bus: system-bus@58c00000 {
+			compatible = "socionext,uniphier-system-bus";
+			status = "disabled";
+			reg = <0x58c00000 0x400>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_system_bus>;
+		};
 
-&peri_clk {
-	compatible = "socionext,uniphier-sld8-peri-clock";
-};
+		smpctrl@59800000 {
+			compatible = "socionext,uniphier-smpctrl";
+			reg = <0x59801000 0x400>;
+		};
 
-&peri_rst {
-	compatible = "socionext,uniphier-sld8-peri-reset";
-};
+		mioctrl@59810000 {
+			compatible = "socionext,uniphier-sld8-mioctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59810000 0x800>;
 
-&pinctrl {
-	compatible = "socionext,uniphier-sld8-pinctrl";
-};
+			mio_clk: clock {
+				compatible = "socionext,uniphier-sld8-mio-clock";
+				#clock-cells = <1>;
+			};
 
-&sys_clk {
-	compatible = "socionext,uniphier-sld8-clock";
-};
+			mio_rst: reset {
+				compatible = "socionext,uniphier-sld8-mio-reset";
+				#reset-cells = <1>;
+			};
+		};
 
-&sys_rst {
-	compatible = "socionext,uniphier-sld8-reset";
+		perictrl@59820000 {
+			compatible = "socionext,uniphier-sld8-perictrl",
+				     "simple-mfd", "syscon";
+			reg = <0x59820000 0x200>;
+
+			peri_clk: clock {
+				compatible = "socionext,uniphier-sld8-peri-clock";
+				#clock-cells = <1>;
+			};
+
+			peri_rst: reset {
+				compatible = "socionext,uniphier-sld8-peri-reset";
+				#reset-cells = <1>;
+			};
+		};
+
+		usb0: usb@5a800100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a800100 0x100>;
+			interrupts = <0 80 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb0>;
+			clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 8>,
+				 <&mio_rst 12>;
+		};
+
+		usb1: usb@5a810100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a810100 0x100>;
+			interrupts = <0 81 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb1>;
+			clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 9>,
+				 <&mio_rst 13>;
+		};
+
+		usb2: usb@5a820100 {
+			compatible = "socionext,uniphier-ehci", "generic-ehci";
+			status = "disabled";
+			reg = <0x5a820100 0x100>;
+			interrupts = <0 82 4>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb2>;
+			clocks = <&mio_clk 7>, <&mio_clk 10>, <&mio_clk 14>;
+			resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 10>,
+				 <&mio_rst 14>;
+		};
+
+		soc-glue@5f800000 {
+			compatible = "socionext,uniphier-sld8-soc-glue",
+				     "simple-mfd", "syscon";
+			reg = <0x5f800000 0x2000>;
+
+			pinctrl: pinctrl {
+				compatible = "socionext,uniphier-sld8-pinctrl";
+			};
+		};
+
+		timer@60000200 {
+			compatible = "arm,cortex-a9-global-timer";
+			reg = <0x60000200 0x20>;
+			interrupts = <1 11 0x104>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		timer@60000600 {
+			compatible = "arm,cortex-a9-twd-timer";
+			reg = <0x60000600 0x20>;
+			interrupts = <1 13 0x104>;
+			clocks = <&arm_timer_clk>;
+		};
+
+		intc: interrupt-controller@60001000 {
+			compatible = "arm,cortex-a9-gic";
+			reg = <0x60001000 0x1000>,
+			      <0x60000100 0x100>;
+			#interrupt-cells = <3>;
+			interrupt-controller;
+		};
+
+		sysctrl@61840000 {
+			compatible = "socionext,uniphier-sld8-sysctrl",
+				     "simple-mfd", "syscon";
+			reg = <0x61840000 0x10000>;
+
+			sys_clk: clock {
+				compatible = "socionext,uniphier-sld8-clock";
+				#clock-cells = <1>;
+			};
+
+			sys_rst: reset {
+				compatible = "socionext,uniphier-sld8-reset";
+				#reset-cells = <1>;
+			};
+		};
+	};
 };
+
+/include/ "uniphier-pinctrl.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,7 @@
 			reg = <0>;
 			cci-control-port = <&cci_control1>;
 			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		cpu1: cpu@1 {
@@ -47,6 +48,7 @@
 			reg = <1>;
 			cci-control-port = <&cci_control1>;
 			cpu-idle-states = <&CLUSTER_SLEEP_BIG>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		cpu2: cpu@2 {
@@ -55,6 +57,7 @@
 			reg = <0x100>;
 			cci-control-port = <&cci_control2>;
 			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
+			capacity-dmips-mhz = <516>;
 		};
 
 		cpu3: cpu@3 {
@@ -63,6 +66,7 @@
 			reg = <0x101>;
 			cci-control-port = <&cci_control2>;
 			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
+			capacity-dmips-mhz = <516>;
 		};
 
 		cpu4: cpu@4 {
@@ -71,6 +75,7 @@
 			reg = <0x102>;
 			cci-control-port = <&cci_control2>;
 			cpu-idle-states = <&CLUSTER_SLEEP_LITTLE>;
+			capacity-dmips-mhz = <516>;
 		};
 
 		idle-states {
@@ -126,7 +131,7 @@
 		#address-cells = <0>;
 		interrupt-controller;
 		reg = <0 0x2c001000 0 0x1000>,
-		      <0 0x2c002000 0 0x1000>,
+		      <0 0x2c002000 0 0x2000>,
 		      <0 0x2c004000 0 0x2000>,
 		      <0 0x2c006000 0 0x2000>;
 		interrupts = <1 9 0xf04>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts	2017-02-12 16:03:20.000000000 -0500
@@ -81,7 +81,7 @@
 		#address-cells = <0>;
 		interrupt-controller;
 		reg = <0 0x2c001000 0 0x1000>,
-		      <0 0x2c002000 0 0x1000>,
+		      <0 0x2c002000 0 0x2000>,
 		      <0 0x2c004000 0 0x2000>,
 		      <0 0x2c006000 0 0x2000>;
 		interrupts = <1 9 0xf04>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts	2017-02-12 16:03:20.000000000 -0500
@@ -88,10 +88,16 @@
 
 			switch0: switch0@0 {
 				compatible = "marvell,mv88e6085";
+				pinctrl-0 = <&pinctrl_gpio_switch0>;
+				pinctrl-names = "default";
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0>;
 				dsa,member = <0 0>;
+				interrupt-parent = <&gpio0>;
+				interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
 
 				ports {
 					#address-cells = <1>;
@@ -99,16 +105,19 @@
 					port@0 {
 						reg = <0>;
 						label = "lan0";
+						phy-handle = <&switch0phy0>;
 					};
 
 					port@1 {
 						reg = <1>;
 						label = "lan1";
+						phy-handle = <&switch0phy1>;
 					};
 
 					port@2 {
 						reg = <2>;
 						label = "lan2";
+						phy-handle = <&switch0phy2>;
 					};
 
 					switch0port5: port@5 {
@@ -133,6 +142,25 @@
 						};
 					};
 				};
+				mdio {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					switch0phy0: switch0phy0@0 {
+						reg = <0>;
+						interrupt-parent = <&switch0>;
+						interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+					};
+					switch0phy1: switch1phy0@1 {
+						reg = <1>;
+						interrupt-parent = <&switch0>;
+						interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+					};
+					switch0phy2: switch1phy0@2 {
+						reg = <2>;
+						interrupt-parent = <&switch0>;
+						interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+					};
+				};
 			};
 		};
 
@@ -143,10 +171,16 @@
 
 			switch1: switch1@0 {
 				compatible = "marvell,mv88e6085";
+				pinctrl-0 = <&pinctrl_gpio_switch1>;
+				pinctrl-names = "default";
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0>;
 				dsa,member = <0 1>;
+				interrupt-parent = <&gpio0>;
+				interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
 
 				ports {
 					#address-cells = <1>;
@@ -196,12 +230,18 @@
 					#size-cells = <0>;
 					switch1phy0: switch1phy0@0 {
 						reg = <0>;
+						interrupt-parent = <&switch1>;
+						interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
 					};
 					switch1phy1: switch1phy0@1 {
 						reg = <1>;
+						interrupt-parent = <&switch1>;
+						interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
 					};
 					switch1phy2: switch1phy0@2 {
 						reg = <2>;
+						interrupt-parent = <&switch1>;
+						interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
 					};
 				};
 			};
@@ -499,13 +539,6 @@
 	};
 };
 
-&i2c3 {
-	clock-frequency = <100000>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c3>;
-	status = "okay";
-};
-
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart0>;
@@ -636,6 +669,18 @@
 		>;
 	};
 
+	pinctrl_gpio_switch0: pinctrl-gpio-switch0 {
+		fsl,pins = <
+			VF610_PAD_PTB5__GPIO_27		0x219d
+		>;
+	};
+
+	pinctrl_gpio_switch1: pinctrl-gpio-switch1 {
+		fsl,pins = <
+			VF610_PAD_PTB4__GPIO_26		0x219d
+		>;
+	};
+
 	pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset {
 		fsl,pins = <
 			 VF610_PAD_PTE14__GPIO_119	0x31c2
@@ -663,13 +708,6 @@
 		>;
 	};
 
-	pinctrl_i2c3: i2c3grp {
-		fsl,pins = <
-			VF610_PAD_PTA30__I2C3_SCL	0x37ff
-			VF610_PAD_PTA31__I2C3_SDA	0x37ff
-		>;
-	};
-
 	pinctrl_leds_debug: pinctrl-leds-debug {
 		fsl,pins = <
 			 VF610_PAD_PTD20__GPIO_74	0x31c2
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/vf-colibri.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vf-colibri.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/vf-colibri.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vf-colibri.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -108,6 +108,10 @@
 	status = "okay";
 };
 
+&edma1 {
+	status = "okay";
+};
+
 &esdhc1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_esdhc1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/vfxxx.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vfxxx.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/vfxxx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/vfxxx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -194,6 +194,9 @@
 				clocks = <&clks VF610_CLK_DSPI0>;
 				clock-names = "dspi";
 				spi-num-chipselects = <6>;
+				dmas = <&edma1 1 12>,
+					<&edma1 1 13>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -206,6 +209,9 @@
 				clocks = <&clks VF610_CLK_DSPI1>;
 				clock-names = "dspi";
 				spi-num-chipselects = <4>;
+				dmas = <&edma1 1 14>,
+					<&edma1 1 15>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -520,6 +526,12 @@
 				status = "disabled";
 			};
 
+			ocotp: ocotp@400a5000 {
+				compatible = "fsl,vf610-ocotp";
+				reg = <0x400a5000 0x1000>;
+				clocks = <&clks VF610_CLK_OCOTP>;
+			};
+
 			snvs0: snvs@400a7000 {
 			    compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
 				reg = <0x400a7000 0x2000>;
@@ -561,6 +573,9 @@
 				clocks = <&clks VF610_CLK_DSPI2>;
 				clock-names = "dspi";
 				spi-num-chipselects = <2>;
+				dmas = <&edma1 0 10>,
+					<&edma1 0 11>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
@@ -573,6 +588,9 @@
 				clocks = <&clks VF610_CLK_DSPI3>;
 				clock-names = "dspi";
 				spi-num-chipselects = <2>;
+				dmas = <&edma1 0 12>,
+					<&edma1 0 13>;
+				dma-names = "rx", "tx";
 				status = "disabled";
 			};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-7000.dtsi linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-7000.dtsi
--- linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-7000.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-7000.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -10,9 +10,10 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-/include/ "skeleton.dtsi"
 
 / {
+	#address-cells = <1>;
+	#size-cells = <1>;
 	compatible = "xlnx,zynq-7000";
 
 	cpus {
@@ -41,14 +42,15 @@
 		};
 	};
 
-	pmu {
+	pmu@f8891000 {
 		compatible = "arm,cortex-a9-pmu";
 		interrupts = <0 5 4>, <0 6 4>;
 		interrupt-parent = <&intc>;
-		reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
+		reg = <0xf8891000 0x1000>,
+		      <0xf8893000 0x1000>;
 	};
 
-	regulator_vccpint: fixedregulator@0 {
+	regulator_vccpint: fixedregulator {
 		compatible = "regulator-fixed";
 		regulator-name = "VCCPINT";
 		regulator-min-microvolt = <1000000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-microzed.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-microzed.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-microzed.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-microzed.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 - 2014 Xilinx
+ * Copyright (C) 2016 Jagan Teki <jteki@openedev.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.
+ */
+/dts-v1/;
+/include/ "zynq-7000.dtsi"
+
+/ {
+	model = "Zynq MicroZED Development Board";
+	compatible = "xlnx,zynq-microzed", "xlnx,zynq-7000";
+
+	aliases {
+		ethernet0 = &gem0;
+		serial0 = &uart1;
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	usb_phy0: phy0 {
+		compatible = "usb-nop-xceiv";
+		#phy-cells = <0>;
+	};
+};
+
+&clkc {
+	ps-clk-frequency = <33333333>;
+};
+
+&gem0 {
+	status = "okay";
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy>;
+
+	ethernet_phy: ethernet-phy@0 {
+		reg = <0>;
+	};
+};
+
+&sdhci0 {
+	status = "okay";
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+	usb-phy = <&usb_phy0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&pinctrl0 {
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <0>;
+			io-standard = <1>;
+		};
+
+		conf-rx {
+			pins = "MIO29", "MIO31", "MIO36";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO28", "MIO30", "MIO32", "MIO33", "MIO34",
+			       "MIO35", "MIO37", "MIO38", "MIO39";
+			bias-disable;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-parallella.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-parallella.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-parallella.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-parallella.dts	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zc702.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zc702.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zc702.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zc702.dts	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zc706.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zc706.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zc706.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zc706.dts	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zed.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zed.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zed.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zed.dts	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x20000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zybo.dts linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zybo.dts
--- linux-libre-4.9-gnu/arch/arm/boot/dts/zynq-zybo.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/boot/dts/zynq-zybo.dts	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 		serial0 = &uart1;
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x20000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/common/bL_switcher.c linux-libre-4.10-rc8-gnu/arch/arm/common/bL_switcher.c
--- linux-libre-4.9-gnu/arch/arm/common/bL_switcher.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/common/bL_switcher.c	2017-02-12 16:03:20.000000000 -0500
@@ -757,19 +757,18 @@ EXPORT_SYMBOL_GPL(bL_switcher_put_enable
  * while the switcher is active.
  * We're just not ready to deal with that given the trickery involved.
  */
-static int bL_switcher_hotplug_callback(struct notifier_block *nfb,
-					unsigned long action, void *hcpu)
+static int bL_switcher_cpu_pre(unsigned int cpu)
 {
-	if (bL_switcher_active) {
-		int pairing = bL_switcher_cpu_pairing[(unsigned long)hcpu];
-		switch (action & 0xf) {
-		case CPU_UP_PREPARE:
-		case CPU_DOWN_PREPARE:
-			if (pairing == -1)
-				return NOTIFY_BAD;
-		}
-	}
-	return NOTIFY_DONE;
+	int pairing;
+
+	if (!bL_switcher_active)
+		return 0;
+
+	pairing = bL_switcher_cpu_pairing[cpu];
+
+	if (pairing == -1)
+		return -EINVAL;
+	return 0;
 }
 
 static bool no_bL_switcher;
@@ -782,8 +781,15 @@ static int __init bL_switcher_init(void)
 	if (!mcpm_is_available())
 		return -ENODEV;
 
-	cpu_notifier(bL_switcher_hotplug_callback, 0);
-
+	cpuhp_setup_state_nocalls(CPUHP_ARM_BL_PREPARE, "arm/bl:prepare",
+				  bL_switcher_cpu_pre, NULL);
+	ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "arm/bl:predown",
+					NULL, bL_switcher_cpu_pre);
+	if (ret < 0) {
+		cpuhp_remove_state_nocalls(CPUHP_ARM_BL_PREPARE);
+		pr_err("bL_switcher: Failed to allocate a hotplug state\n");
+		return ret;
+	}
 	if (!no_bL_switcher) {
 		ret = bL_switcher_enable();
 		if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/common/bL_switcher_dummy_if.c linux-libre-4.10-rc8-gnu/arch/arm/common/bL_switcher_dummy_if.c
--- linux-libre-4.9-gnu/arch/arm/common/bL_switcher_dummy_if.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/common/bL_switcher_dummy_if.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/bL_switcher.h>
 
 static ssize_t bL_switcher_write(struct file *file, const char __user *buf,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/common/dmabounce.c linux-libre-4.10-rc8-gnu/arch/arm/common/dmabounce.c
--- linux-libre-4.9-gnu/arch/arm/common/dmabounce.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/common/dmabounce.c	2017-02-12 16:03:20.000000000 -0500
@@ -243,7 +243,8 @@ static int needs_bounce(struct device *d
 }
 
 static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
-		enum dma_data_direction dir)
+				    enum dma_data_direction dir,
+				    unsigned long attrs)
 {
 	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
 	struct safe_buffer *buf;
@@ -262,7 +263,8 @@ static inline dma_addr_t map_single(stru
 		__func__, buf->ptr, virt_to_dma(dev, buf->ptr),
 		buf->safe, buf->safe_dma_addr);
 
-	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) {
+	if ((dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) &&
+	    !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
 		dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
 			__func__, ptr, buf->safe, size);
 		memcpy(buf->safe, ptr, size);
@@ -272,7 +274,8 @@ static inline dma_addr_t map_single(stru
 }
 
 static inline void unmap_single(struct device *dev, struct safe_buffer *buf,
-		size_t size, enum dma_data_direction dir)
+				size_t size, enum dma_data_direction dir,
+				unsigned long attrs)
 {
 	BUG_ON(buf->size != size);
 	BUG_ON(buf->direction != dir);
@@ -283,7 +286,8 @@ static inline void unmap_single(struct d
 
 	DO_STATS(dev->archdata.dmabounce->bounce_count++);
 
-	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+	if ((dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) &&
+	    !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
 		void *ptr = buf->ptr;
 
 		dev_dbg(dev, "%s: copy back safe %p to unsafe %p size %d\n",
@@ -334,7 +338,7 @@ static dma_addr_t dmabounce_map_page(str
 		return DMA_ERROR_CODE;
 	}
 
-	return map_single(dev, page_address(page) + offset, size, dir);
+	return map_single(dev, page_address(page) + offset, size, dir, attrs);
 }
 
 /*
@@ -357,7 +361,7 @@ static void dmabounce_unmap_page(struct
 		return;
 	}
 
-	unmap_single(dev, buf, size, dir);
+	unmap_single(dev, buf, size, dir, attrs);
 }
 
 static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/am200epdkit_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/am200epdkit_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/am200epdkit_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/am200epdkit_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -55,8 +55,9 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_PXA2XX=y
 CONFIG_BLK_DEV_LOOP=m
-CONFIG_IDE=m
-CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_SD=m
+CONFIG_ATA=m
+CONFIG_PATA_PCMCIA=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/assabet_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/assabet_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/assabet_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/assabet_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_SA1100=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCMCIA=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/badge4_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/badge4_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/badge4_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/badge4_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -42,8 +42,6 @@ CONFIG_MTD_SA1100=y
 CONFIG_PARPORT=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
-CONFIG_IDE=m
-CONFIG_BLK_DEV_IDECD=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/bcm2835_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/bcm2835_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/bcm2835_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/bcm2835_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -73,6 +73,8 @@ CONFIG_SPI_BCM2835=y
 CONFIG_SPI_BCM2835AUX=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_BCM2835_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
 CONFIG_DRM=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/cerfcube_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/cerfcube_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/cerfcube_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/cerfcube_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,6 @@ CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_SA1100=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_RAM=m
-CONFIG_IDE=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCI=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/collie_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/collie_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/collie_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/collie_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -43,8 +43,9 @@ CONFIG_MTD_SA1100=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=1024
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_PCMCIA=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/corgi_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/corgi_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/corgi_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/corgi_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -99,15 +99,14 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_SHARPSL=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_PATA_PCMCIA=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_USB_CATC=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/davinci_all_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/davinci_all_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/davinci_all_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/davinci_all_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -7,13 +7,13 @@ CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CGROUPS=y
+CONFIG_CHECKPOINT_RESTORE=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
-# CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
@@ -34,6 +34,7 @@ CONFIG_DAVINCI_MUX_WARNINGS=y
 CONFIG_DAVINCI_RESET_CLOCKS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
+CONFIG_SECCOMP=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -52,10 +53,10 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_NETFILTER=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
+CONFIG_DA8XX_MSTPRI=y
 CONFIG_MTD=m
 CONFIG_MTD_BLOCK=m
 CONFIG_MTD_CFI=m
@@ -116,6 +117,8 @@ CONFIG_SPI_DAVINCI=m
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PCA953X=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
 CONFIG_WATCHDOG=y
 CONFIG_DAVINCI_WATCHDOG=m
 CONFIG_MFD_DM355EVM_MSP=y
@@ -123,6 +126,8 @@ CONFIG_TPS6507X=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_TPS6507X=y
+CONFIG_DRM=m
+CONFIG_DRM_TILCDC=m
 CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_DA8XX=y
@@ -153,10 +158,13 @@ CONFIG_HID_SONY=m
 CONFIG_HID_SUNPLUS=m
 CONFIG_USB=m
 CONFIG_USB_MON=m
+CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_STORAGE=m
 CONFIG_USB_MUSB_HDRC=m
+CONFIG_USB_MUSB_DA8XX=m
 CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_TEST=m
+CONFIG_NOP_USB_XCEIV=m
 CONFIG_USB_GADGET=m
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
@@ -167,28 +175,32 @@ CONFIG_USB_MASS_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_USB_CDC_COMPOSITE=m
-CONFIG_MMC=m
+CONFIG_MMC=y
 # CONFIG_MMC_BLOCK_BOUNCE is not set
-CONFIG_MMC_DAVINCI=m
+CONFIG_MMC_DAVINCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=m
 CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_OMAP=m
 CONFIG_DMADEVICES=y
 CONFIG_TI_EDMA=y
 CONFIG_MEMORY=y
 CONFIG_TI_AEMIF=m
+CONFIG_DA8XX_DDRCTL=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
 CONFIG_AUTOFS4_FS=m
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
 CONFIG_JFFS2_FS=m
 CONFIG_UBIFS_FS=m
 CONFIG_CRAMFS=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/dram_0xc0000000.config linux-libre-4.10-rc8-gnu/arch/arm/configs/dram_0xc0000000.config
--- linux-libre-4.9-gnu/arch/arm/configs/dram_0xc0000000.config	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/dram_0xc0000000.config	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1 @@
+CONFIG_DRAM_BASE=0xc0000000
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/exynos_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/exynos_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/exynos_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/exynos_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -155,6 +155,7 @@ CONFIG_VIDEO_EXYNOS4_FIMC_IS=m
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
 CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
+CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
 CONFIG_V4L_TEST_DRIVERS=y
 CONFIG_DRM=y
 CONFIG_DRM_EXYNOS=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/ezx_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/ezx_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/ezx_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/ezx_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -64,8 +64,8 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/h3600_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/h3600_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/h3600_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/h3600_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -39,8 +39,9 @@ CONFIG_MTD_SA1100=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_PCMCIA=y
 CONFIG_NETDEVICES=y
 CONFIG_PCMCIA_PCNET=y
 CONFIG_PPP=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/imote2_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/imote2_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/imote2_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/imote2_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -56,8 +56,8 @@ CONFIG_NETFILTER=y
 CONFIG_NETFILTER_NETLINK_QUEUE=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/imx_v6_v7_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/imx_v6_v7_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/imx_v6_v7_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/imx_v6_v7_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -86,6 +86,7 @@ CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
 CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_IMX_WEIM=y
 CONFIG_CONNECTOR=y
 CONFIG_MTD=y
@@ -256,6 +257,7 @@ CONFIG_SND_IMX_SOC=y
 CONFIG_SND_SOC_PHYCORE_AC97=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
 CONFIG_SND_SOC_IMX_WM8962=y
+CONFIG_SND_SOC_IMX_ES8328=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
 CONFIG_SND_SOC_IMX_SPDIF=y
 CONFIG_SND_SOC_IMX_MC13783=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/integrator_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/integrator_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/integrator_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/integrator_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPUFREQ_DT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/ixp4xx_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/ixp4xx_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/ixp4xx_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/ixp4xx_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -127,16 +127,17 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_EEPROM_LEGACY=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_CMD64X=y
-CONFIG_BLK_DEV_HPT366=y
-CONFIG_BLK_DEV_PDC202XX_NEW=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=y
 CONFIG_SATA_VIA=y
 CONFIG_PATA_ARTOP=y
+CONFIG_PATA_CMD64X=y
+CONFIG_PATA_HPT366=y
+CONFIG_PATA_HPT37X=y
+CONFIG_PATA_HPT3X2N=y
+CONFIG_PATA_PDC2027X=y
 CONFIG_PATA_IXP4XX_CF=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/jornada720_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/jornada720_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/jornada720_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/jornada720_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -29,8 +29,9 @@ CONFIG_SA1100_FIR=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_PCMCIA=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_NET_ETHERNET=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/lart_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/lart_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/lart_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/lart_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -36,8 +36,6 @@ CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_LART=y
 CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=m
-CONFIG_BLK_DEV_IDECD=m
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=m
 CONFIG_NET_ETHERNET=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/mainstone_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/mainstone_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/mainstone_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/mainstone_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,6 @@ CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 # CONFIG_MTD_CFI_I1 is not set
 CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_IDE=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/multi_v5_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/multi_v5_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/multi_v5_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/multi_v5_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -150,7 +150,6 @@ CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 CONFIG_SPI_IMX=y
 CONFIG_SPI_ORION=y
-CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_QNAP=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/multi_v7_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/multi_v7_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/multi_v7_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/multi_v7_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -173,6 +173,11 @@ CONFIG_CAN_RCAR=m
 CONFIG_CAN_XILINXCAN=y
 CONFIG_CAN_MCP251X=y
 CONFIG_NET_DSA_BCM_SF2=m
+CONFIG_B53=m
+CONFIG_B53_SPI_DRIVER=m
+CONFIG_B53_MDIO_DRIVER=m
+CONFIG_B53_MMAP_DRIVER=m
+CONFIG_B53_SRAB_DRIVER=m
 CONFIG_CAN_SUN4I=y
 CONFIG_BT=m
 CONFIG_BT_MRVL=m
@@ -235,6 +240,7 @@ CONFIG_HIX5HD2_GMAC=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_MACB=y
 CONFIG_BCMGENET=m
+CONFIG_BGMAC_BCMA=y
 CONFIG_SYSTEMPORT=m
 CONFIG_NET_CALXEDA_XGMAC=y
 CONFIG_GIANFAR=y
@@ -404,7 +410,6 @@ CONFIG_PINCTRL_MSM8X74=y
 CONFIG_PINCTRL_MSM8916=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_PINCTRL_QCOM_SSBI_PMIC=y
-CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_GENERIC_PLATFORM=y
 CONFIG_GPIO_DAVINCI=y
 CONFIG_GPIO_DWAPB=y
@@ -450,7 +455,6 @@ CONFIG_RCAR_THERMAL=y
 CONFIG_ARMADA_THERMAL=y
 CONFIG_DAVINCI_WATCHDOG=m
 CONFIG_EXYNOS_THERMAL=m
-CONFIG_ST_THERMAL_SYSCFG=y
 CONFIG_ST_THERMAL_MEMMAP=y
 CONFIG_WATCHDOG=y
 CONFIG_DA9063_WATCHDOG=m
@@ -467,6 +471,7 @@ CONFIG_MESON_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
 CONFIG_DIGICOLOR_WATCHDOG=y
 CONFIG_BCM2835_WDT=y
+CONFIG_BCM47XX_WDT=y
 CONFIG_BCM7038_WDT=m
 CONFIG_BCM_KONA_WDT=y
 CONFIG_MFD_ACT8945A=y
@@ -489,7 +494,7 @@ CONFIG_MFD_MAX8907=y
 CONFIG_MFD_MAX8997=y
 CONFIG_MFD_MAX8998=y
 CONFIG_MFD_RK808=y
-CONFIG_MFD_PM8921_CORE=y
+CONFIG_MFD_PM8XXX=y
 CONFIG_MFD_QCOM_RPM=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_MFD_SEC_CORE=y
@@ -561,7 +566,9 @@ CONFIG_VIDEO_EXYNOS4_FIMC_IS=m
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
 CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
+CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
 CONFIG_VIDEO_STI_BDISP=m
+CONFIG_VIDEO_STI_HVA=m
 CONFIG_VIDEO_RENESAS_JPU=m
 CONFIG_VIDEO_RENESAS_VSP1=m
 CONFIG_V4L_TEST_DRIVERS=y
@@ -572,6 +579,7 @@ CONFIG_DRM=y
 CONFIG_DRM_I2C_ADV7511=m
 # CONFIG_DRM_I2C_CH7006 is not set
 # CONFIG_DRM_I2C_SIL164 is not set
+CONFIG_DRM_DUMB_VGA_DAC=m
 CONFIG_DRM_NXP_PTN3460=m
 CONFIG_DRM_PARADE_PS8622=m
 CONFIG_DRM_NOUVEAU=m
@@ -649,6 +657,9 @@ CONFIG_SND_SOC_AK4642=m
 CONFIG_SND_SOC_SGTL5000=m
 CONFIG_SND_SOC_SPDIF=m
 CONFIG_SND_SOC_WM8978=m
+CONFIG_SND_SOC_STI=m
+CONFIG_SND_SOC_STI_SAS=m
+CONFIG_SND_SIMPLE_CARD=m
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_MVEBU=y
@@ -790,6 +801,7 @@ CONFIG_DMA_OMAP=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_XILINX_DMA=y
 CONFIG_DMA_SUN6I=y
+CONFIG_ST_FDMA=m
 CONFIG_STAGING=y
 CONFIG_SENSORS_ISL29018=y
 CONFIG_SENSORS_ISL29028=y
@@ -798,6 +810,10 @@ CONFIG_KEYBOARD_NVEC=y
 CONFIG_SERIO_NVEC_PS2=y
 CONFIG_NVEC_POWER=y
 CONFIG_NVEC_PAZ00=y
+CONFIG_BCMA=y
+CONFIG_BCMA_HOST_SOC=y
+CONFIG_BCMA_DRIVER_GMAC_CMN=y
+CONFIG_BCMA_DRIVER_GPIO=y
 CONFIG_QCOM_GSBI=y
 CONFIG_QCOM_PM=y
 CONFIG_QCOM_SMEM=y
@@ -823,6 +839,8 @@ CONFIG_HWSPINLOCK_QCOM=y
 CONFIG_ROCKCHIP_IOMMU=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_REMOTEPROC=m
+CONFIG_ST_REMOTEPROC=m
 CONFIG_PM_DEVFREQ=y
 CONFIG_ARM_TEGRA_DEVFREQ=m
 CONFIG_MEMORY=y
@@ -862,9 +880,7 @@ CONFIG_PHY_ROCKCHIP_DP=m
 CONFIG_PHY_ROCKCHIP_USB=m
 CONFIG_PHY_QCOM_APQ8064_SATA=m
 CONFIG_PHY_MIPHY28LP=y
-CONFIG_PHY_MIPHY365X=y
 CONFIG_PHY_RCAR_GEN2=m
-CONFIG_PHY_STIH41X_USB=y
 CONFIG_PHY_STIH407_USB=y
 CONFIG_PHY_SUN4I_USB=y
 CONFIG_PHY_SUN9I_USB=y
@@ -877,6 +893,8 @@ CONFIG_BCM2835_MBOX=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
 CONFIG_EFI_VARS=m
 CONFIG_EFI_CAPSULE_LOADER=m
+CONFIG_BCM47XX_NVRAM=y
+CONFIG_BCM47XX_SPROM=y
 CONFIG_EXT4_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/netwinder_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/netwinder_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/netwinder_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/netwinder_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@ CONFIG_LEDS_CPU=y
 CONFIG_DEPRECATED_PARAM_STRUCT=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=0x301"
+CONFIG_CMDLINE="root=0x801"
 CONFIG_FPE_NWFPE=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_NET=y
@@ -27,8 +27,9 @@ CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 CONFIG_PARPORT_PC_SUPERIO=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_PATA_WINBOND=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/omap1_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/omap1_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/omap1_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/omap1_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -96,14 +96,14 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=2
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_IDE=m
-CONFIG_BLK_DEV_IDECS=m
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_CHR_DEV_SG=y
+CONFIG_ATA=m
+CONFIG_PATA_PCMCIA=m
 CONFIG_NETDEVICES=y
 CONFIG_TUN=y
 CONFIG_PHYLIB=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/omap2plus_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/omap2plus_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/omap2plus_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/omap2plus_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,6 @@
 CONFIG_KERNEL_LZMA=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -40,7 +39,6 @@ CONFIG_ARCH_MULTI_V6=y
 CONFIG_POWER_AVS_OMAP=y
 CONFIG_POWER_AVS_OMAP_CLASS3=y
 CONFIG_OMAP_RESET_CLOCKS=y
-CONFIG_OMAP_MUX_DEBUG=y
 CONFIG_ARCH_OMAP2=y
 CONFIG_ARCH_OMAP3=y
 CONFIG_ARCH_OMAP4=y
@@ -50,7 +48,6 @@ CONFIG_SOC_AM43XX=y
 CONFIG_SOC_DRA7XX=y
 CONFIG_ARM_THUMBEE=y
 CONFIG_ARM_ERRATA_411920=y
-CONFIG_ARM_ERRATA_430973=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_CMA=y
@@ -62,7 +59,6 @@ CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
 CONFIG_KEXEC=y
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -205,6 +201,7 @@ CONFIG_TOUCHSCREEN_ADS7846=m
 CONFIG_TOUCHSCREEN_EDT_FT5X06=m
 CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
 CONFIG_TOUCHSCREEN_PIXCIR=m
+CONFIG_TOUCHSCREEN_TSC2004=m
 CONFIG_TOUCHSCREEN_TSC2005=m
 CONFIG_TOUCHSCREEN_TSC2007=m
 CONFIG_INPUT_MISC=y
@@ -240,14 +237,14 @@ CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TWL4030=y
 CONFIG_W1=m
 CONFIG_HDQ_MASTER_OMAP=m
+CONFIG_POWER_AVS=y
+CONFIG_POWER_RESET=y
 CONFIG_BATTERY_BQ27XXX=m
 CONFIG_CHARGER_ISP1704=m
 CONFIG_CHARGER_TWL4030=m
 CONFIG_CHARGER_BQ2415X=m
 CONFIG_CHARGER_BQ24190=m
 CONFIG_CHARGER_BQ24735=m
-CONFIG_POWER_RESET=y
-CONFIG_POWER_AVS=y
 CONFIG_HWMON=m
 CONFIG_SENSORS_GPIO_FAN=m
 CONFIG_SENSORS_LM75=m
@@ -267,10 +264,13 @@ CONFIG_TWL4030_WATCHDOG=m
 CONFIG_MFD_TI_AM335X_TSCADC=m
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
+CONFIG_MFD_TI_LP873X=y
 CONFIG_MFD_TPS65218=y
 CONFIG_MFD_TPS65910=y
 CONFIG_TWL6040_CORE=y
+CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_LP872X=y
+CONFIG_REGULATOR_LP873X=y
 CONFIG_REGULATOR_PALMAS=y
 CONFIG_REGULATOR_PBIAS=y
 CONFIG_REGULATOR_TI_ABB=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/pxa_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/pxa_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/pxa_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/pxa_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -411,7 +411,6 @@ CONFIG_MFD_MAX77693=y
 CONFIG_MFD_MAX8907=m
 CONFIG_EZX_PCAP=y
 CONFIG_UCB1400_CORE=m
-CONFIG_MFD_PM8921_CORE=m
 CONFIG_MFD_SEC_CORE=y
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65090=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/qcom_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/qcom_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/qcom_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/qcom_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -119,7 +119,6 @@ CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_MSM=y
 CONFIG_THERMAL=y
 CONFIG_MFD_PM8XXX=y
-CONFIG_MFD_PM8921_CORE=y
 CONFIG_MFD_QCOM_RPM=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR=y
@@ -162,8 +161,8 @@ CONFIG_APQ_MMCC_8084=y
 CONFIG_IPQ_LCC_806X=y
 CONFIG_MSM_GCC_8660=y
 CONFIG_MSM_LCC_8960=y
-CONFIG_MSM_GCC_9615=y
-CONFIG_MSM_LCC_9615=y
+CONFIG_MDM_GCC_9615=y
+CONFIG_MDM_LCC_9615=y
 CONFIG_MSM_MMCC_8960=y
 CONFIG_MSM_MMCC_8974=y
 CONFIG_HWSPINLOCK_QCOM=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/s3c2410_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/s3c2410_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/s3c2410_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/s3c2410_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -86,9 +86,9 @@ CONFIG_IPV6_TUNNEL=m
 CONFIG_NETFILTER=y
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
@@ -219,20 +219,16 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_UB=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_ATA_OVER_ETH=m
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_IDETAPE=m
-CONFIG_BLK_DEV_PLATFORM=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
-CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_ATA=y
+CONFIG_PATA_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_DM9000=y
 CONFIG_INPUT_EVDEV=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/shannon_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/shannon_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/shannon_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/shannon_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,6 @@ CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_SA1100=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_IDE=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCMCIA=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/shmobile_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/shmobile_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/shmobile_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/shmobile_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,7 @@ CONFIG_SYSVIPC=y
 CONFIG_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL_SYSCALL=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/socfpga_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/socfpga_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/socfpga_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/socfpga_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -25,6 +25,7 @@ CONFIG_PCIE_ALTERA_MSI=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_VFP=y
@@ -50,6 +51,10 @@ CONFIG_CAN_DEBUG_DEVICES=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_SPI_CADENCE_QUADSPI=y
+CONFIG_OF_OVERLAY=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=2
 CONFIG_BLK_DEV_RAM_SIZE=8192
@@ -101,18 +106,28 @@ CONFIG_DMADEVICES=y
 CONFIG_PL330_DMA=y
 CONFIG_DMATEST=m
 CONFIG_FPGA=y
+CONFIG_FPGA_REGION=y
 CONFIG_FPGA_MGR_SOCFPGA=y
+CONFIG_FPGA_MGR_SOCFPGA_A10=y
+CONFIG_FPGA_BRIDGE=y
+CONFIG_SOCFPGA_FPGA_BRIDGE=y
+CONFIG_ALTERA_FREEZE_BRIDGE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT3_FS=y
+CONFIG_AUTOFS4_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_NTFS_RW=y
 CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/spitz_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/spitz_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/spitz_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/spitz_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -96,15 +96,13 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_SHARPSL=y
 CONFIG_BLK_DEV_LOOP=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=y
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_MULTI_LUN=y
+CONFIG_ATA=y
+CONFIG_PATA_PCMCIA=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_USB_CATC=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/stm32_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/stm32_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/stm32_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/stm32_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -38,8 +38,7 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_BLK_DEV is not set
 CONFIG_EEPROM_93CX6=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_VT is not set
 # CONFIG_UNIX98_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/sunxi_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/sunxi_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/sunxi_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/sunxi_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -98,6 +98,7 @@ CONFIG_MEDIA_RC_SUPPORT=y
 CONFIG_RC_DEVICES=y
 CONFIG_IR_SUNXI=y
 CONFIG_DRM=y
+CONFIG_DRM_DUMB_VGA_DAC=y
 CONFIG_DRM_SUN4I=y
 CONFIG_FB=y
 CONFIG_FB_SIMPLE=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/tegra_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/tegra_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/tegra_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/tegra_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,16 +1,15 @@
 CONFIG_SYSVIPC=y
-CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
-CONFIG_CGROUP_DEBUG=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEBUG=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_ELF_CORE is not set
 CONFIG_EMBEDDED=y
@@ -24,14 +23,10 @@ CONFIG_PARTITION_ADVANCED=y
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 CONFIG_ARCH_TEGRA=y
-CONFIG_ARCH_TEGRA_2x_SOC=y
-CONFIG_ARCH_TEGRA_3x_SOC=y
-CONFIG_ARCH_TEGRA_114_SOC=y
-CONFIG_ARCH_TEGRA_124_SOC=y
 CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
 CONFIG_PCI_MSI=y
 CONFIG_PCI_TEGRA=y
-CONFIG_PCIEPORTBUS=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
@@ -41,7 +36,6 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_KEXEC=y
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_CPUFREQ_DT=y
 CONFIG_CPU_IDLE=y
@@ -59,7 +53,6 @@ CONFIG_IP_PNP_RARP=y
 CONFIG_INET_ESP=y
 # CONFIG_INET_XFRM_MODE_TUNNEL is not set
 # CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -86,6 +79,7 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=64
+CONFIG_TEGRA_GMI=y
 CONFIG_MTD=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SPI_NOR=y
@@ -131,8 +125,8 @@ CONFIG_INPUT_MPU3050=y
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_TEGRA=y
 # CONFIG_HW_RANDOM is not set
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
@@ -151,11 +145,11 @@ CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_PALMAS=y
 CONFIG_GPIO_TPS6586X=y
 CONFIG_GPIO_TPS65910=y
-CONFIG_BATTERY_SBS=y
-CONFIG_CHARGER_TPS65090=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_AS3722=y
 CONFIG_POWER_RESET_GPIO=y
+CONFIG_BATTERY_SBS=y
+CONFIG_CHARGER_TPS65090=y
 CONFIG_SENSORS_LM90=y
 CONFIG_SENSORS_LM95245=y
 CONFIG_WATCHDOG=y
@@ -216,6 +210,7 @@ CONFIG_SND_SOC_TEGRA_WM9712=y
 CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
 CONFIG_SND_SOC_TEGRA_ALC5632=y
 CONFIG_SND_SOC_TEGRA_MAX98090=y
+CONFIG_SND_SOC_TEGRA_SGTL5000=y
 CONFIG_USB=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_TEGRA=y
@@ -262,6 +257,10 @@ CONFIG_NVEC_POWER=y
 CONFIG_NVEC_PAZ00=y
 CONFIG_TEGRA_IOMMU_GART=y
 CONFIG_TEGRA_IOMMU_SMMU=y
+CONFIG_ARCH_TEGRA_2x_SOC=y
+CONFIG_ARCH_TEGRA_3x_SOC=y
+CONFIG_ARCH_TEGRA_114_SOC=y
+CONFIG_ARCH_TEGRA_124_SOC=y
 CONFIG_MEMORY=y
 CONFIG_IIO=y
 CONFIG_AK8975=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/configs/u8500_defconfig linux-libre-4.10-rc8-gnu/arch/arm/configs/u8500_defconfig
--- linux-libre-4.9-gnu/arch/arm/configs/u8500_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/configs/u8500_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,6 @@ CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
-CONFIG_PERF_EVENTS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -26,7 +25,6 @@ CONFIG_CPU_IDLE=y
 CONFIG_ARM_U8500_CPUIDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
-CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -108,18 +106,19 @@ CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
 CONFIG_HSEM_U8500=y
 CONFIG_IIO=y
-CONFIG_IIO_BUFFER=y
+CONFIG_IIO_SW_TRIGGER=y
 CONFIG_IIO_ST_ACCEL_3AXIS=y
 CONFIG_IIO_ST_GYRO_3AXIS=y
 CONFIG_BH1780=y
+CONFIG_AK8974=y
 CONFIG_IIO_ST_MAGN_3AXIS=y
+CONFIG_IIO_HRTIMER_TRIGGER=y
 CONFIG_IIO_ST_PRESS=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_EXT4_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/aesbs-glue.c linux-libre-4.10-rc8-gnu/arch/arm/crypto/aesbs-glue.c
--- linux-libre-4.9-gnu/arch/arm/crypto/aesbs-glue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/aesbs-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,8 +10,9 @@
 
 #include <asm/neon.h>
 #include <crypto/aes.h>
-#include <crypto/ablk_helper.h>
-#include <crypto/algapi.h>
+#include <crypto/cbc.h>
+#include <crypto/internal/simd.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/module.h>
 #include <crypto/xts.h>
 
@@ -55,14 +56,14 @@ struct aesbs_xts_ctx {
 	struct AES_KEY	twkey;
 };
 
-static int aesbs_cbc_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+static int aesbs_cbc_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
 			     unsigned int key_len)
 {
-	struct aesbs_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int bits = key_len * 8;
 
 	if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc)) {
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 	ctx->dec.rk = ctx->enc;
@@ -71,33 +72,33 @@ static int aesbs_cbc_set_key(struct cryp
 	return 0;
 }
 
-static int aesbs_ctr_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+static int aesbs_ctr_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
 			     unsigned int key_len)
 {
-	struct aesbs_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int bits = key_len * 8;
 
 	if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) {
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 	ctx->enc.converted = 0;
 	return 0;
 }
 
-static int aesbs_xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+static int aesbs_xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
 			     unsigned int key_len)
 {
-	struct aesbs_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int bits = key_len * 4;
 	int err;
 
-	err = xts_check_key(tfm, in_key, key_len);
+	err = xts_verify_key(tfm, in_key, key_len);
 	if (err)
 		return err;
 
 	if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) {
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 	ctx->dec.rk = ctx->enc.rk;
@@ -107,88 +108,52 @@ static int aesbs_xts_set_key(struct cryp
 	return 0;
 }
 
-static int aesbs_cbc_encrypt(struct blkcipher_desc *desc,
-			     struct scatterlist *dst,
-			     struct scatterlist *src, unsigned int nbytes)
+static inline void aesbs_encrypt_one(struct crypto_skcipher *tfm,
+				     const u8 *src, u8 *dst)
 {
-	struct aesbs_cbc_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
-	int err;
-
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	while (walk.nbytes) {
-		u32 blocks = walk.nbytes / AES_BLOCK_SIZE;
-		u8 *src = walk.src.virt.addr;
+	AES_encrypt(src, dst, &ctx->enc);
+}
 
-		if (walk.dst.virt.addr == walk.src.virt.addr) {
-			u8 *iv = walk.iv;
+static int aesbs_cbc_encrypt(struct skcipher_request *req)
+{
+	return crypto_cbc_encrypt_walk(req, aesbs_encrypt_one);
+}
 
-			do {
-				crypto_xor(src, iv, AES_BLOCK_SIZE);
-				AES_encrypt(src, src, &ctx->enc);
-				iv = src;
-				src += AES_BLOCK_SIZE;
-			} while (--blocks);
-			memcpy(walk.iv, iv, AES_BLOCK_SIZE);
-		} else {
-			u8 *dst = walk.dst.virt.addr;
+static inline void aesbs_decrypt_one(struct crypto_skcipher *tfm,
+				     const u8 *src, u8 *dst)
+{
+	struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-			do {
-				crypto_xor(walk.iv, src, AES_BLOCK_SIZE);
-				AES_encrypt(walk.iv, dst, &ctx->enc);
-				memcpy(walk.iv, dst, AES_BLOCK_SIZE);
-				src += AES_BLOCK_SIZE;
-				dst += AES_BLOCK_SIZE;
-			} while (--blocks);
-		}
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
-	}
-	return err;
+	AES_decrypt(src, dst, &ctx->dec.rk);
 }
 
-static int aesbs_cbc_decrypt(struct blkcipher_desc *desc,
-			     struct scatterlist *dst,
-			     struct scatterlist *src, unsigned int nbytes)
+static int aesbs_cbc_decrypt(struct skcipher_request *req)
 {
-	struct aesbs_cbc_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
-
-	while ((walk.nbytes / AES_BLOCK_SIZE) >= 8) {
-		kernel_neon_begin();
-		bsaes_cbc_encrypt(walk.src.virt.addr, walk.dst.virt.addr,
-				  walk.nbytes, &ctx->dec, walk.iv);
-		kernel_neon_end();
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
-	}
-	while (walk.nbytes) {
-		u32 blocks = walk.nbytes / AES_BLOCK_SIZE;
+	for (err = skcipher_walk_virt(&walk, req, false);
+	     (nbytes = walk.nbytes); err = skcipher_walk_done(&walk, nbytes)) {
+		u32 blocks = nbytes / AES_BLOCK_SIZE;
 		u8 *dst = walk.dst.virt.addr;
 		u8 *src = walk.src.virt.addr;
-		u8 bk[2][AES_BLOCK_SIZE];
 		u8 *iv = walk.iv;
 
-		do {
-			if (walk.dst.virt.addr == walk.src.virt.addr)
-				memcpy(bk[blocks & 1], src, AES_BLOCK_SIZE);
-
-			AES_decrypt(src, dst, &ctx->dec.rk);
-			crypto_xor(dst, iv, AES_BLOCK_SIZE);
-
-			if (walk.dst.virt.addr == walk.src.virt.addr)
-				iv = bk[blocks & 1];
-			else
-				iv = src;
+		if (blocks >= 8) {
+			kernel_neon_begin();
+			bsaes_cbc_encrypt(src, dst, nbytes, &ctx->dec, iv);
+			kernel_neon_end();
+			nbytes %= AES_BLOCK_SIZE;
+			continue;
+		}
 
-			dst += AES_BLOCK_SIZE;
-			src += AES_BLOCK_SIZE;
-		} while (--blocks);
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		nbytes = crypto_cbc_decrypt_blocks(&walk, tfm,
+						   aesbs_decrypt_one);
 	}
 	return err;
 }
@@ -206,17 +171,15 @@ static void inc_be128_ctr(__be32 ctr[],
 	}
 }
 
-static int aesbs_ctr_encrypt(struct blkcipher_desc *desc,
-			     struct scatterlist *dst, struct scatterlist *src,
-			     unsigned int nbytes)
+static int aesbs_ctr_encrypt(struct skcipher_request *req)
 {
-	struct aesbs_ctr_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	u32 blocks;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
+	err = skcipher_walk_virt(&walk, req, false);
 
 	while ((blocks = walk.nbytes / AES_BLOCK_SIZE)) {
 		u32 tail = walk.nbytes % AES_BLOCK_SIZE;
@@ -235,11 +198,7 @@ static int aesbs_ctr_encrypt(struct blkc
 		kernel_neon_end();
 		inc_be128_ctr(ctr, blocks);
 
-		nbytes -= blocks * AES_BLOCK_SIZE;
-		if (nbytes && nbytes == tail && nbytes <= AES_BLOCK_SIZE)
-			break;
-
-		err = blkcipher_walk_done(desc, &walk, tail);
+		err = skcipher_walk_done(&walk, tail);
 	}
 	if (walk.nbytes) {
 		u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
@@ -248,23 +207,21 @@ static int aesbs_ctr_encrypt(struct blkc
 
 		AES_encrypt(walk.iv, ks, &ctx->enc.rk);
 		if (tdst != tsrc)
-			memcpy(tdst, tsrc, nbytes);
-		crypto_xor(tdst, ks, nbytes);
-		err = blkcipher_walk_done(desc, &walk, 0);
+			memcpy(tdst, tsrc, walk.nbytes);
+		crypto_xor(tdst, ks, walk.nbytes);
+		err = skcipher_walk_done(&walk, 0);
 	}
 	return err;
 }
 
-static int aesbs_xts_encrypt(struct blkcipher_desc *desc,
-			     struct scatterlist *dst,
-			     struct scatterlist *src, unsigned int nbytes)
+static int aesbs_xts_encrypt(struct skcipher_request *req)
 {
-	struct aesbs_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
+	err = skcipher_walk_virt(&walk, req, false);
 
 	/* generate the initial tweak */
 	AES_encrypt(walk.iv, walk.iv, &ctx->twkey);
@@ -274,21 +231,19 @@ static int aesbs_xts_encrypt(struct blkc
 		bsaes_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr,
 				  walk.nbytes, &ctx->enc, walk.iv);
 		kernel_neon_end();
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	return err;
 }
 
-static int aesbs_xts_decrypt(struct blkcipher_desc *desc,
-			     struct scatterlist *dst,
-			     struct scatterlist *src, unsigned int nbytes)
+static int aesbs_xts_decrypt(struct skcipher_request *req)
 {
-	struct aesbs_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt_block(desc, &walk, 8 * AES_BLOCK_SIZE);
+	err = skcipher_walk_virt(&walk, req, false);
 
 	/* generate the initial tweak */
 	AES_encrypt(walk.iv, walk.iv, &ctx->twkey);
@@ -298,141 +253,110 @@ static int aesbs_xts_decrypt(struct blkc
 		bsaes_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr,
 				  walk.nbytes, &ctx->dec, walk.iv);
 		kernel_neon_end();
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	return err;
 }
 
-static struct crypto_alg aesbs_algs[] = { {
-	.cra_name		= "__cbc-aes-neonbs",
-	.cra_driver_name	= "__driver-cbc-aes-neonbs",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct aesbs_cbc_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= aesbs_cbc_set_key,
-		.encrypt	= aesbs_cbc_encrypt,
-		.decrypt	= aesbs_cbc_decrypt,
+static struct skcipher_alg aesbs_algs[] = { {
+	.base = {
+		.cra_name		= "__cbc(aes)",
+		.cra_driver_name	= "__cbc-aes-neonbs",
+		.cra_priority		= 300,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct aesbs_cbc_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.setkey		= aesbs_cbc_set_key,
+	.encrypt	= aesbs_cbc_encrypt,
+	.decrypt	= aesbs_cbc_decrypt,
 }, {
-	.cra_name		= "__ctr-aes-neonbs",
-	.cra_driver_name	= "__driver-ctr-aes-neonbs",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct aesbs_ctr_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= aesbs_ctr_set_key,
-		.encrypt	= aesbs_ctr_encrypt,
-		.decrypt	= aesbs_ctr_encrypt,
+	.base = {
+		.cra_name		= "__ctr(aes)",
+		.cra_driver_name	= "__ctr-aes-neonbs",
+		.cra_priority		= 300,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= 1,
+		.cra_ctxsize		= sizeof(struct aesbs_ctr_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.chunksize	= AES_BLOCK_SIZE,
+	.setkey		= aesbs_ctr_set_key,
+	.encrypt	= aesbs_ctr_encrypt,
+	.decrypt	= aesbs_ctr_encrypt,
 }, {
-	.cra_name		= "__xts-aes-neonbs",
-	.cra_driver_name	= "__driver-xts-aes-neonbs",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct aesbs_xts_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= aesbs_xts_set_key,
-		.encrypt	= aesbs_xts_encrypt,
-		.decrypt	= aesbs_xts_decrypt,
+	.base = {
+		.cra_name		= "__xts(aes)",
+		.cra_driver_name	= "__xts-aes-neonbs",
+		.cra_priority		= 300,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct aesbs_xts_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
-}, {
-	.cra_name		= "cbc(aes)",
-	.cra_driver_name	= "cbc-aes-neonbs",
-	.cra_priority		= 300,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= __ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "ctr(aes)",
-	.cra_driver_name	= "ctr-aes-neonbs",
-	.cra_priority		= 300,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "xts(aes)",
-	.cra_driver_name	= "xts-aes-neonbs",
-	.cra_priority		= 300,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
+	.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+	.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.setkey		= aesbs_xts_set_key,
+	.encrypt	= aesbs_xts_encrypt,
+	.decrypt	= aesbs_xts_decrypt,
 } };
 
+struct simd_skcipher_alg *aesbs_simd_algs[ARRAY_SIZE(aesbs_algs)];
+
+static void aesbs_mod_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(aesbs_simd_algs) && aesbs_simd_algs[i]; i++)
+		simd_skcipher_free(aesbs_simd_algs[i]);
+
+	crypto_unregister_skciphers(aesbs_algs, ARRAY_SIZE(aesbs_algs));
+}
+
 static int __init aesbs_mod_init(void)
 {
+	struct simd_skcipher_alg *simd;
+	const char *basename;
+	const char *algname;
+	const char *drvname;
+	int err;
+	int i;
+
 	if (!cpu_has_neon())
 		return -ENODEV;
 
-	return crypto_register_algs(aesbs_algs, ARRAY_SIZE(aesbs_algs));
-}
+	err = crypto_register_skciphers(aesbs_algs, ARRAY_SIZE(aesbs_algs));
+	if (err)
+		return err;
 
-static void __exit aesbs_mod_exit(void)
-{
-	crypto_unregister_algs(aesbs_algs, ARRAY_SIZE(aesbs_algs));
+	for (i = 0; i < ARRAY_SIZE(aesbs_algs); i++) {
+		algname = aesbs_algs[i].base.cra_name + 2;
+		drvname = aesbs_algs[i].base.cra_driver_name + 2;
+		basename = aesbs_algs[i].base.cra_driver_name;
+		simd = simd_skcipher_create_compat(algname, drvname, basename);
+		err = PTR_ERR(simd);
+		if (IS_ERR(simd))
+			goto unregister_simds;
+
+		aesbs_simd_algs[i] = simd;
+	}
+
+	return 0;
+
+unregister_simds:
+	aesbs_mod_exit();
+	return err;
 }
 
 module_init(aesbs_mod_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/aes-ce-glue.c linux-libre-4.10-rc8-gnu/arch/arm/crypto/aes-ce-glue.c
--- linux-libre-4.9-gnu/arch/arm/crypto/aes-ce-glue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/aes-ce-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,8 +12,8 @@
 #include <asm/neon.h>
 #include <asm/hwcap.h>
 #include <crypto/aes.h>
-#include <crypto/ablk_helper.h>
-#include <crypto/algapi.h>
+#include <crypto/internal/simd.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/module.h>
 #include <crypto/xts.h>
 
@@ -88,8 +88,13 @@ static int ce_aes_expandkey(struct crypt
 		u32 *rki = ctx->key_enc + (i * kwords);
 		u32 *rko = rki + kwords;
 
+#ifndef CONFIG_CPU_BIG_ENDIAN
 		rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8);
 		rko[0] = rko[0] ^ rki[0] ^ rcon[i];
+#else
+		rko[0] = rol32(ce_aes_sub(rki[kwords - 1]), 8);
+		rko[0] = rko[0] ^ rki[0] ^ (rcon[i] << 24);
+#endif
 		rko[1] = rko[0] ^ rki[1];
 		rko[2] = rko[1] ^ rki[2];
 		rko[3] = rko[2] ^ rki[3];
@@ -128,17 +133,17 @@ static int ce_aes_expandkey(struct crypt
 	return 0;
 }
 
-static int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+static int ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
 			 unsigned int key_len)
 {
-	struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int ret;
 
 	ret = ce_aes_expandkey(ctx, in_key, key_len);
 	if (!ret)
 		return 0;
 
-	tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+	crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 	return -EINVAL;
 }
 
@@ -147,13 +152,13 @@ struct crypto_aes_xts_ctx {
 	struct crypto_aes_ctx __aligned(8) key2;
 };
 
-static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+static int xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
 		       unsigned int key_len)
 {
-	struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int ret;
 
-	ret = xts_check_key(tfm, in_key, key_len);
+	ret = xts_verify_key(tfm, in_key, key_len);
 	if (ret)
 		return ret;
 
@@ -164,130 +169,113 @@ static int xts_set_key(struct crypto_tfm
 	if (!ret)
 		return 0;
 
-	tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+	crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 	return -EINVAL;
 }
 
-static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int ecb_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	unsigned int blocks;
 	int err;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
 		ce_aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   (u8 *)ctx->key_enc, num_rounds(ctx), blocks);
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int ecb_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	unsigned int blocks;
 	int err;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
 		ce_aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   (u8 *)ctx->key_dec, num_rounds(ctx), blocks);
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int cbc_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	unsigned int blocks;
 	int err;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
 		ce_aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   (u8 *)ctx->key_enc, num_rounds(ctx), blocks,
 				   walk.iv);
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int cbc_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	unsigned int blocks;
 	int err;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
 		ce_aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   (u8 *)ctx->key_dec, num_rounds(ctx), blocks,
 				   walk.iv);
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int ctr_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
 	int err, blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) {
 		ce_aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   (u8 *)ctx->key_enc, num_rounds(ctx), blocks,
 				   walk.iv);
-		nbytes -= blocks * AES_BLOCK_SIZE;
-		if (nbytes && nbytes == walk.nbytes % AES_BLOCK_SIZE)
-			break;
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
-	if (walk.nbytes % AES_BLOCK_SIZE) {
-		u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
-		u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
+	if (walk.nbytes) {
 		u8 __aligned(8) tail[AES_BLOCK_SIZE];
+		unsigned int nbytes = walk.nbytes;
+		u8 *tdst = walk.dst.virt.addr;
+		u8 *tsrc = walk.src.virt.addr;
 
 		/*
 		 * Minimum alignment is 8 bytes, so if nbytes is <= 8, we need
@@ -298,231 +286,172 @@ static int ctr_encrypt(struct blkcipher_
 		ce_aes_ctr_encrypt(tail, tsrc, (u8 *)ctx->key_enc,
 				   num_rounds(ctx), blocks, walk.iv);
 		memcpy(tdst, tail, nbytes);
-		err = blkcipher_walk_done(desc, &walk, 0);
+		err = skcipher_walk_done(&walk, 0);
 	}
 	kernel_neon_end();
 
 	return err;
 }
 
-static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int xts_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = num_rounds(&ctx->key1);
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		ce_aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   (u8 *)ctx->key1.key_enc, rounds, blocks,
 				   walk.iv, (u8 *)ctx->key2.key_enc, first);
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 
 	return err;
 }
 
-static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int xts_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = num_rounds(&ctx->key1);
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		ce_aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   (u8 *)ctx->key1.key_dec, rounds, blocks,
 				   walk.iv, (u8 *)ctx->key2.key_enc, first);
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 
 	return err;
 }
 
-static struct crypto_alg aes_algs[] = { {
-	.cra_name		= "__ecb-aes-ce",
-	.cra_driver_name	= "__driver-ecb-aes-ce",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= 0,
-		.setkey		= ce_aes_setkey,
-		.encrypt	= ecb_encrypt,
-		.decrypt	= ecb_decrypt,
+static struct skcipher_alg aes_algs[] = { {
+	.base = {
+		.cra_name		= "__ecb(aes)",
+		.cra_driver_name	= "__ecb-aes-ce",
+		.cra_priority		= 300,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.setkey		= ce_aes_setkey,
+	.encrypt	= ecb_encrypt,
+	.decrypt	= ecb_decrypt,
 }, {
-	.cra_name		= "__cbc-aes-ce",
-	.cra_driver_name	= "__driver-cbc-aes-ce",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ce_aes_setkey,
-		.encrypt	= cbc_encrypt,
-		.decrypt	= cbc_decrypt,
+	.base = {
+		.cra_name		= "__cbc(aes)",
+		.cra_driver_name	= "__cbc-aes-ce",
+		.cra_priority		= 300,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.setkey		= ce_aes_setkey,
+	.encrypt	= cbc_encrypt,
+	.decrypt	= cbc_decrypt,
 }, {
-	.cra_name		= "__ctr-aes-ce",
-	.cra_driver_name	= "__driver-ctr-aes-ce",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ce_aes_setkey,
-		.encrypt	= ctr_encrypt,
-		.decrypt	= ctr_encrypt,
+	.base = {
+		.cra_name		= "__ctr(aes)",
+		.cra_driver_name	= "__ctr-aes-ce",
+		.cra_priority		= 300,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= 1,
+		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.chunksize	= AES_BLOCK_SIZE,
+	.setkey		= ce_aes_setkey,
+	.encrypt	= ctr_encrypt,
+	.decrypt	= ctr_encrypt,
 }, {
-	.cra_name		= "__xts-aes-ce",
-	.cra_driver_name	= "__driver-xts-aes-ce",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_xts_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= xts_set_key,
-		.encrypt	= xts_encrypt,
-		.decrypt	= xts_decrypt,
+	.base = {
+		.cra_name		= "__xts(aes)",
+		.cra_driver_name	= "__xts-aes-ce",
+		.cra_priority		= 300,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct crypto_aes_xts_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
-}, {
-	.cra_name		= "ecb(aes)",
-	.cra_driver_name	= "ecb-aes-ce",
-	.cra_priority		= 300,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= 0,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "cbc(aes)",
-	.cra_driver_name	= "cbc-aes-ce",
-	.cra_priority		= 300,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "ctr(aes)",
-	.cra_driver_name	= "ctr-aes-ce",
-	.cra_priority		= 300,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "xts(aes)",
-	.cra_driver_name	= "xts-aes-ce",
-	.cra_priority		= 300,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
+	.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+	.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.setkey		= xts_set_key,
+	.encrypt	= xts_encrypt,
+	.decrypt	= xts_decrypt,
 } };
 
+static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)];
+
+static void aes_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(aes_simd_algs) && aes_simd_algs[i]; i++)
+		simd_skcipher_free(aes_simd_algs[i]);
+
+	crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
+}
+
 static int __init aes_init(void)
 {
+	struct simd_skcipher_alg *simd;
+	const char *basename;
+	const char *algname;
+	const char *drvname;
+	int err;
+	int i;
+
 	if (!(elf_hwcap2 & HWCAP2_AES))
 		return -ENODEV;
-	return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs));
-}
 
-static void __exit aes_exit(void)
-{
-	crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
+	err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
+	if (err)
+		return err;
+
+	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
+		algname = aes_algs[i].base.cra_name + 2;
+		drvname = aes_algs[i].base.cra_driver_name + 2;
+		basename = aes_algs[i].base.cra_driver_name;
+		simd = simd_skcipher_create_compat(algname, drvname, basename);
+		err = PTR_ERR(simd);
+		if (IS_ERR(simd))
+			goto unregister_simds;
+
+		aes_simd_algs[i] = simd;
+	}
+
+	return 0;
+
+unregister_simds:
+	aes_exit();
+	return err;
 }
 
 module_init(aes_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/crc32-ce-core.S linux-libre-4.10-rc8-gnu/arch/arm/crypto/crc32-ce-core.S
--- linux-libre-4.9-gnu/arch/arm/crypto/crc32-ce-core.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/crc32-ce-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,306 @@
+/*
+ * Accelerated CRC32(C) using ARM CRC, NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+ */
+
+/* GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE 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 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see http://www.gnu.org/licenses
+ *
+ * Please  visit http://www.xyratex.com/contact if you need additional
+ * information or have any questions.
+ *
+ * GPL HEADER END
+ */
+
+/*
+ * Copyright 2012 Xyratex Technology Limited
+ *
+ * Using hardware provided PCLMULQDQ instruction to accelerate the CRC32
+ * calculation.
+ * CRC32 polynomial:0x04c11db7(BE)/0xEDB88320(LE)
+ * PCLMULQDQ is a new instruction in Intel SSE4.2, the reference can be found
+ * at:
+ * http://www.intel.com/products/processor/manuals/
+ * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 2B: Instruction Set Reference, N-Z
+ *
+ * Authors:   Gregory Prestas <Gregory_Prestas@us.xyratex.com>
+ *	      Alexander Boyko <Alexander_Boyko@xyratex.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+	.text
+	.align		6
+	.arch		armv8-a
+	.arch_extension	crc
+	.fpu		crypto-neon-fp-armv8
+
+.Lcrc32_constants:
+	/*
+	 * [x4*128+32 mod P(x) << 32)]'  << 1   = 0x154442bd4
+	 * #define CONSTANT_R1  0x154442bd4LL
+	 *
+	 * [(x4*128-32 mod P(x) << 32)]' << 1   = 0x1c6e41596
+	 * #define CONSTANT_R2  0x1c6e41596LL
+	 */
+	.quad		0x0000000154442bd4
+	.quad		0x00000001c6e41596
+
+	/*
+	 * [(x128+32 mod P(x) << 32)]'   << 1   = 0x1751997d0
+	 * #define CONSTANT_R3  0x1751997d0LL
+	 *
+	 * [(x128-32 mod P(x) << 32)]'   << 1   = 0x0ccaa009e
+	 * #define CONSTANT_R4  0x0ccaa009eLL
+	 */
+	.quad		0x00000001751997d0
+	.quad		0x00000000ccaa009e
+
+	/*
+	 * [(x64 mod P(x) << 32)]'       << 1   = 0x163cd6124
+	 * #define CONSTANT_R5  0x163cd6124LL
+	 */
+	.quad		0x0000000163cd6124
+	.quad		0x00000000FFFFFFFF
+
+	/*
+	 * #define CRCPOLY_TRUE_LE_FULL 0x1DB710641LL
+	 *
+	 * Barrett Reduction constant (u64`) = u` = (x**64 / P(x))`
+	 *                                                      = 0x1F7011641LL
+	 * #define CONSTANT_RU  0x1F7011641LL
+	 */
+	.quad		0x00000001DB710641
+	.quad		0x00000001F7011641
+
+.Lcrc32c_constants:
+	.quad		0x00000000740eef02
+	.quad		0x000000009e4addf8
+	.quad		0x00000000f20c0dfe
+	.quad		0x000000014cd00bd6
+	.quad		0x00000000dd45aab8
+	.quad		0x00000000FFFFFFFF
+	.quad		0x0000000105ec76f0
+	.quad		0x00000000dea713f1
+
+	dCONSTANTl	.req	d0
+	dCONSTANTh	.req	d1
+	qCONSTANT	.req	q0
+
+	BUF		.req	r0
+	LEN		.req	r1
+	CRC		.req	r2
+
+	qzr		.req	q9
+
+	/**
+	 * Calculate crc32
+	 * BUF - buffer
+	 * LEN - sizeof buffer (multiple of 16 bytes), LEN should be > 63
+	 * CRC - initial crc32
+	 * return %eax crc32
+	 * uint crc32_pmull_le(unsigned char const *buffer,
+	 *                     size_t len, uint crc32)
+	 */
+ENTRY(crc32_pmull_le)
+	adr		r3, .Lcrc32_constants
+	b		0f
+
+ENTRY(crc32c_pmull_le)
+	adr		r3, .Lcrc32c_constants
+
+0:	bic		LEN, LEN, #15
+	vld1.8		{q1-q2}, [BUF, :128]!
+	vld1.8		{q3-q4}, [BUF, :128]!
+	vmov.i8		qzr, #0
+	vmov.i8		qCONSTANT, #0
+	vmov		dCONSTANTl[0], CRC
+	veor.8		d2, d2, dCONSTANTl
+	sub		LEN, LEN, #0x40
+	cmp		LEN, #0x40
+	blt		less_64
+
+	vld1.64		{qCONSTANT}, [r3]
+
+loop_64:		/* 64 bytes Full cache line folding */
+	sub		LEN, LEN, #0x40
+
+	vmull.p64	q5, d3, dCONSTANTh
+	vmull.p64	q6, d5, dCONSTANTh
+	vmull.p64	q7, d7, dCONSTANTh
+	vmull.p64	q8, d9, dCONSTANTh
+
+	vmull.p64	q1, d2, dCONSTANTl
+	vmull.p64	q2, d4, dCONSTANTl
+	vmull.p64	q3, d6, dCONSTANTl
+	vmull.p64	q4, d8, dCONSTANTl
+
+	veor.8		q1, q1, q5
+	vld1.8		{q5}, [BUF, :128]!
+	veor.8		q2, q2, q6
+	vld1.8		{q6}, [BUF, :128]!
+	veor.8		q3, q3, q7
+	vld1.8		{q7}, [BUF, :128]!
+	veor.8		q4, q4, q8
+	vld1.8		{q8}, [BUF, :128]!
+
+	veor.8		q1, q1, q5
+	veor.8		q2, q2, q6
+	veor.8		q3, q3, q7
+	veor.8		q4, q4, q8
+
+	cmp		LEN, #0x40
+	bge		loop_64
+
+less_64:		/* Folding cache line into 128bit */
+	vldr		dCONSTANTl, [r3, #16]
+	vldr		dCONSTANTh, [r3, #24]
+
+	vmull.p64	q5, d3, dCONSTANTh
+	vmull.p64	q1, d2, dCONSTANTl
+	veor.8		q1, q1, q5
+	veor.8		q1, q1, q2
+
+	vmull.p64	q5, d3, dCONSTANTh
+	vmull.p64	q1, d2, dCONSTANTl
+	veor.8		q1, q1, q5
+	veor.8		q1, q1, q3
+
+	vmull.p64	q5, d3, dCONSTANTh
+	vmull.p64	q1, d2, dCONSTANTl
+	veor.8		q1, q1, q5
+	veor.8		q1, q1, q4
+
+	teq		LEN, #0
+	beq		fold_64
+
+loop_16:		/* Folding rest buffer into 128bit */
+	subs		LEN, LEN, #0x10
+
+	vld1.8		{q2}, [BUF, :128]!
+	vmull.p64	q5, d3, dCONSTANTh
+	vmull.p64	q1, d2, dCONSTANTl
+	veor.8		q1, q1, q5
+	veor.8		q1, q1, q2
+
+	bne		loop_16
+
+fold_64:
+	/* perform the last 64 bit fold, also adds 32 zeroes
+	 * to the input stream */
+	vmull.p64	q2, d2, dCONSTANTh
+	vext.8		q1, q1, qzr, #8
+	veor.8		q1, q1, q2
+
+	/* final 32-bit fold */
+	vldr		dCONSTANTl, [r3, #32]
+	vldr		d6, [r3, #40]
+	vmov.i8		d7, #0
+
+	vext.8		q2, q1, qzr, #4
+	vand.8		d2, d2, d6
+	vmull.p64	q1, d2, dCONSTANTl
+	veor.8		q1, q1, q2
+
+	/* Finish up with the bit-reversed barrett reduction 64 ==> 32 bits */
+	vldr		dCONSTANTl, [r3, #48]
+	vldr		dCONSTANTh, [r3, #56]
+
+	vand.8		q2, q1, q3
+	vext.8		q2, qzr, q2, #8
+	vmull.p64	q2, d5, dCONSTANTh
+	vand.8		q2, q2, q3
+	vmull.p64	q2, d4, dCONSTANTl
+	veor.8		q1, q1, q2
+	vmov		r0, s5
+
+	bx		lr
+ENDPROC(crc32_pmull_le)
+ENDPROC(crc32c_pmull_le)
+
+	.macro		__crc32, c
+	subs		ip, r2, #8
+	bmi		.Ltail\c
+
+	tst		r1, #3
+	bne		.Lunaligned\c
+
+	teq		ip, #0
+.Laligned8\c:
+	ldrd		r2, r3, [r1], #8
+ARM_BE8(rev		r2, r2		)
+ARM_BE8(rev		r3, r3		)
+	crc32\c\()w	r0, r0, r2
+	crc32\c\()w	r0, r0, r3
+	bxeq		lr
+	subs		ip, ip, #8
+	bpl		.Laligned8\c
+
+.Ltail\c:
+	tst		ip, #4
+	beq		2f
+	ldr		r3, [r1], #4
+ARM_BE8(rev		r3, r3		)
+	crc32\c\()w	r0, r0, r3
+
+2:	tst		ip, #2
+	beq		1f
+	ldrh		r3, [r1], #2
+ARM_BE8(rev16		r3, r3		)
+	crc32\c\()h	r0, r0, r3
+
+1:	tst		ip, #1
+	bxeq		lr
+	ldrb		r3, [r1]
+	crc32\c\()b	r0, r0, r3
+	bx		lr
+
+.Lunaligned\c:
+	tst		r1, #1
+	beq		2f
+	ldrb		r3, [r1], #1
+	subs		r2, r2, #1
+	crc32\c\()b	r0, r0, r3
+
+	tst		r1, #2
+	beq		0f
+2:	ldrh		r3, [r1], #2
+	subs		r2, r2, #2
+ARM_BE8(rev16		r3, r3		)
+	crc32\c\()h	r0, r0, r3
+
+0:	subs		ip, r2, #8
+	bpl		.Laligned8\c
+	b		.Ltail\c
+	.endm
+
+	.align		5
+ENTRY(crc32_armv8_le)
+	__crc32
+ENDPROC(crc32_armv8_le)
+
+	.align		5
+ENTRY(crc32c_armv8_le)
+	__crc32		c
+ENDPROC(crc32c_armv8_le)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/crc32-ce-glue.c linux-libre-4.10-rc8-gnu/arch/arm/crypto/crc32-ce-glue.c
--- linux-libre-4.9-gnu/arch/arm/crypto/crc32-ce-glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/crc32-ce-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,242 @@
+/*
+ * Accelerated CRC32(C) using ARM CRC, NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+ */
+
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <asm/unaligned.h>
+
+#define PMULL_MIN_LEN		64L	/* minimum size of buffer
+					 * for crc32_pmull_le_16 */
+#define SCALE_F			16L	/* size of NEON register */
+
+asmlinkage u32 crc32_pmull_le(const u8 buf[], u32 len, u32 init_crc);
+asmlinkage u32 crc32_armv8_le(u32 init_crc, const u8 buf[], u32 len);
+
+asmlinkage u32 crc32c_pmull_le(const u8 buf[], u32 len, u32 init_crc);
+asmlinkage u32 crc32c_armv8_le(u32 init_crc, const u8 buf[], u32 len);
+
+static u32 (*fallback_crc32)(u32 init_crc, const u8 buf[], u32 len);
+static u32 (*fallback_crc32c)(u32 init_crc, const u8 buf[], u32 len);
+
+static int crc32_cra_init(struct crypto_tfm *tfm)
+{
+	u32 *key = crypto_tfm_ctx(tfm);
+
+	*key = 0;
+	return 0;
+}
+
+static int crc32c_cra_init(struct crypto_tfm *tfm)
+{
+	u32 *key = crypto_tfm_ctx(tfm);
+
+	*key = ~0;
+	return 0;
+}
+
+static int crc32_setkey(struct crypto_shash *hash, const u8 *key,
+			unsigned int keylen)
+{
+	u32 *mctx = crypto_shash_ctx(hash);
+
+	if (keylen != sizeof(u32)) {
+		crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	*mctx = le32_to_cpup((__le32 *)key);
+	return 0;
+}
+
+static int crc32_init(struct shash_desc *desc)
+{
+	u32 *mctx = crypto_shash_ctx(desc->tfm);
+	u32 *crc = shash_desc_ctx(desc);
+
+	*crc = *mctx;
+	return 0;
+}
+
+static int crc32_update(struct shash_desc *desc, const u8 *data,
+			unsigned int length)
+{
+	u32 *crc = shash_desc_ctx(desc);
+
+	*crc = crc32_armv8_le(*crc, data, length);
+	return 0;
+}
+
+static int crc32c_update(struct shash_desc *desc, const u8 *data,
+			 unsigned int length)
+{
+	u32 *crc = shash_desc_ctx(desc);
+
+	*crc = crc32c_armv8_le(*crc, data, length);
+	return 0;
+}
+
+static int crc32_final(struct shash_desc *desc, u8 *out)
+{
+	u32 *crc = shash_desc_ctx(desc);
+
+	put_unaligned_le32(*crc, out);
+	return 0;
+}
+
+static int crc32c_final(struct shash_desc *desc, u8 *out)
+{
+	u32 *crc = shash_desc_ctx(desc);
+
+	put_unaligned_le32(~*crc, out);
+	return 0;
+}
+
+static int crc32_pmull_update(struct shash_desc *desc, const u8 *data,
+			      unsigned int length)
+{
+	u32 *crc = shash_desc_ctx(desc);
+	unsigned int l;
+
+	if (may_use_simd()) {
+		if ((u32)data % SCALE_F) {
+			l = min_t(u32, length, SCALE_F - ((u32)data % SCALE_F));
+
+			*crc = fallback_crc32(*crc, data, l);
+
+			data += l;
+			length -= l;
+		}
+
+		if (length >= PMULL_MIN_LEN) {
+			l = round_down(length, SCALE_F);
+
+			kernel_neon_begin();
+			*crc = crc32_pmull_le(data, l, *crc);
+			kernel_neon_end();
+
+			data += l;
+			length -= l;
+		}
+	}
+
+	if (length > 0)
+		*crc = fallback_crc32(*crc, data, length);
+
+	return 0;
+}
+
+static int crc32c_pmull_update(struct shash_desc *desc, const u8 *data,
+			       unsigned int length)
+{
+	u32 *crc = shash_desc_ctx(desc);
+	unsigned int l;
+
+	if (may_use_simd()) {
+		if ((u32)data % SCALE_F) {
+			l = min_t(u32, length, SCALE_F - ((u32)data % SCALE_F));
+
+			*crc = fallback_crc32c(*crc, data, l);
+
+			data += l;
+			length -= l;
+		}
+
+		if (length >= PMULL_MIN_LEN) {
+			l = round_down(length, SCALE_F);
+
+			kernel_neon_begin();
+			*crc = crc32c_pmull_le(data, l, *crc);
+			kernel_neon_end();
+
+			data += l;
+			length -= l;
+		}
+	}
+
+	if (length > 0)
+		*crc = fallback_crc32c(*crc, data, length);
+
+	return 0;
+}
+
+static struct shash_alg crc32_pmull_algs[] = { {
+	.setkey			= crc32_setkey,
+	.init			= crc32_init,
+	.update			= crc32_update,
+	.final			= crc32_final,
+	.descsize		= sizeof(u32),
+	.digestsize		= sizeof(u32),
+
+	.base.cra_ctxsize	= sizeof(u32),
+	.base.cra_init		= crc32_cra_init,
+	.base.cra_name		= "crc32",
+	.base.cra_driver_name	= "crc32-arm-ce",
+	.base.cra_priority	= 200,
+	.base.cra_blocksize	= 1,
+	.base.cra_module	= THIS_MODULE,
+}, {
+	.setkey			= crc32_setkey,
+	.init			= crc32_init,
+	.update			= crc32c_update,
+	.final			= crc32c_final,
+	.descsize		= sizeof(u32),
+	.digestsize		= sizeof(u32),
+
+	.base.cra_ctxsize	= sizeof(u32),
+	.base.cra_init		= crc32c_cra_init,
+	.base.cra_name		= "crc32c",
+	.base.cra_driver_name	= "crc32c-arm-ce",
+	.base.cra_priority	= 200,
+	.base.cra_blocksize	= 1,
+	.base.cra_module	= THIS_MODULE,
+} };
+
+static int __init crc32_pmull_mod_init(void)
+{
+	if (elf_hwcap2 & HWCAP2_PMULL) {
+		crc32_pmull_algs[0].update = crc32_pmull_update;
+		crc32_pmull_algs[1].update = crc32c_pmull_update;
+
+		if (elf_hwcap2 & HWCAP2_CRC32) {
+			fallback_crc32 = crc32_armv8_le;
+			fallback_crc32c = crc32c_armv8_le;
+		} else {
+			fallback_crc32 = crc32_le;
+			fallback_crc32c = __crc32c_le;
+		}
+	} else if (!(elf_hwcap2 & HWCAP2_CRC32)) {
+		return -ENODEV;
+	}
+
+	return crypto_register_shashes(crc32_pmull_algs,
+				       ARRAY_SIZE(crc32_pmull_algs));
+}
+
+static void __exit crc32_pmull_mod_exit(void)
+{
+	crypto_unregister_shashes(crc32_pmull_algs,
+				  ARRAY_SIZE(crc32_pmull_algs));
+}
+
+module_init(crc32_pmull_mod_init);
+module_exit(crc32_pmull_mod_exit);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("crc32");
+MODULE_ALIAS_CRYPTO("crc32c");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/crct10dif-ce-core.S linux-libre-4.10-rc8-gnu/arch/arm/crypto/crct10dif-ce-core.S
--- linux-libre-4.9-gnu/arch/arm/crypto/crct10dif-ce-core.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/crct10dif-ce-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,427 @@
+//
+// Accelerated CRC-T10DIF using ARM NEON and Crypto Extensions instructions
+//
+// Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+//
+
+//
+// Implement fast CRC-T10DIF computation with SSE and PCLMULQDQ instructions
+//
+// Copyright (c) 2013, Intel Corporation
+//
+// Authors:
+//     Erdinc Ozturk <erdinc.ozturk@intel.com>
+//     Vinodh Gopal <vinodh.gopal@intel.com>
+//     James Guilford <james.guilford@intel.com>
+//     Tim Chen <tim.c.chen@linux.intel.com>
+//
+// 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.
+//
+// * Neither the name of the Intel Corporation nor the names of its
+//   contributors may be used to endorse or promote products derived from
+//   this software without specific prior written permission.
+//
+//
+// THIS SOFTWARE IS PROVIDED BY INTEL 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 INTEL CORPORATION 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.
+//
+//       Function API:
+//       UINT16 crc_t10dif_pcl(
+//               UINT16 init_crc, //initial CRC value, 16 bits
+//               const unsigned char *buf, //buffer pointer to calculate CRC on
+//               UINT64 len //buffer length in bytes (64-bit data)
+//       );
+//
+//       Reference paper titled "Fast CRC Computation for Generic
+//	Polynomials Using PCLMULQDQ Instruction"
+//       URL: http://www.intel.com/content/dam/www/public/us/en/documents
+//  /white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
+//
+//
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+#ifdef CONFIG_CPU_ENDIAN_BE8
+#define CPU_LE(code...)
+#else
+#define CPU_LE(code...)		code
+#endif
+
+	.text
+	.fpu		crypto-neon-fp-armv8
+
+	arg1_low32	.req	r0
+	arg2		.req	r1
+	arg3		.req	r2
+
+	qzr		.req	q13
+
+	q0l		.req	d0
+	q0h		.req	d1
+	q1l		.req	d2
+	q1h		.req	d3
+	q2l		.req	d4
+	q2h		.req	d5
+	q3l		.req	d6
+	q3h		.req	d7
+	q4l		.req	d8
+	q4h		.req	d9
+	q5l		.req	d10
+	q5h		.req	d11
+	q6l		.req	d12
+	q6h		.req	d13
+	q7l		.req	d14
+	q7h		.req	d15
+
+ENTRY(crc_t10dif_pmull)
+	vmov.i8		qzr, #0			// init zero register
+
+	// adjust the 16-bit initial_crc value, scale it to 32 bits
+	lsl		arg1_low32, arg1_low32, #16
+
+	// check if smaller than 256
+	cmp		arg3, #256
+
+	// for sizes less than 128, we can't fold 64B at a time...
+	blt		_less_than_128
+
+	// load the initial crc value
+	// crc value does not need to be byte-reflected, but it needs
+	// to be moved to the high part of the register.
+	// because data will be byte-reflected and will align with
+	// initial crc at correct place.
+	vmov		s0, arg1_low32		// initial crc
+	vext.8		q10, qzr, q0, #4
+
+	// receive the initial 64B data, xor the initial crc value
+	vld1.64		{q0-q1}, [arg2, :128]!
+	vld1.64		{q2-q3}, [arg2, :128]!
+	vld1.64		{q4-q5}, [arg2, :128]!
+	vld1.64		{q6-q7}, [arg2, :128]!
+CPU_LE(	vrev64.8	q0, q0			)
+CPU_LE(	vrev64.8	q1, q1			)
+CPU_LE(	vrev64.8	q2, q2			)
+CPU_LE(	vrev64.8	q3, q3			)
+CPU_LE(	vrev64.8	q4, q4			)
+CPU_LE(	vrev64.8	q5, q5			)
+CPU_LE(	vrev64.8	q6, q6			)
+CPU_LE(	vrev64.8	q7, q7			)
+
+	vswp		d0, d1
+	vswp		d2, d3
+	vswp		d4, d5
+	vswp		d6, d7
+	vswp		d8, d9
+	vswp		d10, d11
+	vswp		d12, d13
+	vswp		d14, d15
+
+	// XOR the initial_crc value
+	veor.8		q0, q0, q10
+
+	adr		ip, rk3
+	vld1.64		{q10}, [ip, :128]	// xmm10 has rk3 and rk4
+
+	//
+	// we subtract 256 instead of 128 to save one instruction from the loop
+	//
+	sub		arg3, arg3, #256
+
+	// at this section of the code, there is 64*x+y (0<=y<64) bytes of
+	// buffer. The _fold_64_B_loop will fold 64B at a time
+	// until we have 64+y Bytes of buffer
+
+
+	// fold 64B at a time. This section of the code folds 4 vector
+	// registers in parallel
+_fold_64_B_loop:
+
+	.macro		fold64, reg1, reg2
+	vld1.64		{q11-q12}, [arg2, :128]!
+
+	vmull.p64	q8, \reg1\()h, d21
+	vmull.p64	\reg1, \reg1\()l, d20
+	vmull.p64	q9, \reg2\()h, d21
+	vmull.p64	\reg2, \reg2\()l, d20
+
+CPU_LE(	vrev64.8	q11, q11		)
+CPU_LE(	vrev64.8	q12, q12		)
+	vswp		d22, d23
+	vswp		d24, d25
+
+	veor.8		\reg1, \reg1, q8
+	veor.8		\reg2, \reg2, q9
+	veor.8		\reg1, \reg1, q11
+	veor.8		\reg2, \reg2, q12
+	.endm
+
+	fold64		q0, q1
+	fold64		q2, q3
+	fold64		q4, q5
+	fold64		q6, q7
+
+	subs		arg3, arg3, #128
+
+	// check if there is another 64B in the buffer to be able to fold
+	bge		_fold_64_B_loop
+
+	// at this point, the buffer pointer is pointing at the last y Bytes
+	// of the buffer the 64B of folded data is in 4 of the vector
+	// registers: v0, v1, v2, v3
+
+	// fold the 8 vector registers to 1 vector register with different
+	// constants
+
+	adr		ip, rk9
+	vld1.64		{q10}, [ip, :128]!
+
+	.macro		fold16, reg, rk
+	vmull.p64	q8, \reg\()l, d20
+	vmull.p64	\reg, \reg\()h, d21
+	.ifnb		\rk
+	vld1.64		{q10}, [ip, :128]!
+	.endif
+	veor.8		q7, q7, q8
+	veor.8		q7, q7, \reg
+	.endm
+
+	fold16		q0, rk11
+	fold16		q1, rk13
+	fold16		q2, rk15
+	fold16		q3, rk17
+	fold16		q4, rk19
+	fold16		q5, rk1
+	fold16		q6
+
+	// instead of 64, we add 48 to the loop counter to save 1 instruction
+	// from the loop instead of a cmp instruction, we use the negative
+	// flag with the jl instruction
+	adds		arg3, arg3, #(128-16)
+	blt		_final_reduction_for_128
+
+	// now we have 16+y bytes left to reduce. 16 Bytes is in register v7
+	// and the rest is in memory. We can fold 16 bytes at a time if y>=16
+	// continue folding 16B at a time
+
+_16B_reduction_loop:
+	vmull.p64	q8, d14, d20
+	vmull.p64	q7, d15, d21
+	veor.8		q7, q7, q8
+
+	vld1.64		{q0}, [arg2, :128]!
+CPU_LE(	vrev64.8	q0, q0		)
+	vswp		d0, d1
+	veor.8		q7, q7, q0
+	subs		arg3, arg3, #16
+
+	// instead of a cmp instruction, we utilize the flags with the
+	// jge instruction equivalent of: cmp arg3, 16-16
+	// check if there is any more 16B in the buffer to be able to fold
+	bge		_16B_reduction_loop
+
+	// now we have 16+z bytes left to reduce, where 0<= z < 16.
+	// first, we reduce the data in the xmm7 register
+
+_final_reduction_for_128:
+	// check if any more data to fold. If not, compute the CRC of
+	// the final 128 bits
+	adds		arg3, arg3, #16
+	beq		_128_done
+
+	// here we are getting data that is less than 16 bytes.
+	// since we know that there was data before the pointer, we can
+	// offset the input pointer before the actual point, to receive
+	// exactly 16 bytes. after that the registers need to be adjusted.
+_get_last_two_regs:
+	add		arg2, arg2, arg3
+	sub		arg2, arg2, #16
+	vld1.64		{q1}, [arg2]
+CPU_LE(	vrev64.8	q1, q1			)
+	vswp		d2, d3
+
+	// get rid of the extra data that was loaded before
+	// load the shift constant
+	adr		ip, tbl_shf_table + 16
+	sub		ip, ip, arg3
+	vld1.8		{q0}, [ip]
+
+	// shift v2 to the left by arg3 bytes
+	vtbl.8		d4, {d14-d15}, d0
+	vtbl.8		d5, {d14-d15}, d1
+
+	// shift v7 to the right by 16-arg3 bytes
+	vmov.i8		q9, #0x80
+	veor.8		q0, q0, q9
+	vtbl.8		d18, {d14-d15}, d0
+	vtbl.8		d19, {d14-d15}, d1
+
+	// blend
+	vshr.s8		q0, q0, #7		// convert to 8-bit mask
+	vbsl.8		q0, q2, q1
+
+	// fold 16 Bytes
+	vmull.p64	q8, d18, d20
+	vmull.p64	q7, d19, d21
+	veor.8		q7, q7, q8
+	veor.8		q7, q7, q0
+
+_128_done:
+	// compute crc of a 128-bit value
+	vldr		d20, rk5
+	vldr		d21, rk6		// rk5 and rk6 in xmm10
+
+	// 64b fold
+	vext.8		q0, qzr, q7, #8
+	vmull.p64	q7, d15, d20
+	veor.8		q7, q7, q0
+
+	// 32b fold
+	vext.8		q0, q7, qzr, #12
+	vmov		s31, s3
+	vmull.p64	q0, d0, d21
+	veor.8		q7, q0, q7
+
+	// barrett reduction
+_barrett:
+	vldr		d20, rk7
+	vldr		d21, rk8
+
+	vmull.p64	q0, d15, d20
+	vext.8		q0, qzr, q0, #12
+	vmull.p64	q0, d1, d21
+	vext.8		q0, qzr, q0, #12
+	veor.8		q7, q7, q0
+	vmov		r0, s29
+
+_cleanup:
+	// scale the result back to 16 bits
+	lsr		r0, r0, #16
+	bx		lr
+
+_less_than_128:
+	teq		arg3, #0
+	beq		_cleanup
+
+	vmov.i8		q0, #0
+	vmov		s3, arg1_low32		// get the initial crc value
+
+	vld1.64		{q7}, [arg2, :128]!
+CPU_LE(	vrev64.8	q7, q7		)
+	vswp		d14, d15
+	veor.8		q7, q7, q0
+
+	cmp		arg3, #16
+	beq		_128_done		// exactly 16 left
+	blt		_less_than_16_left
+
+	// now if there is, load the constants
+	vldr		d20, rk1
+	vldr		d21, rk2		// rk1 and rk2 in xmm10
+
+	// check if there is enough buffer to be able to fold 16B at a time
+	subs		arg3, arg3, #32
+	addlt		arg3, arg3, #16
+	blt		_get_last_two_regs
+	b		_16B_reduction_loop
+
+_less_than_16_left:
+	// shl r9, 4
+	adr		ip, tbl_shf_table + 16
+	sub		ip, ip, arg3
+	vld1.8		{q0}, [ip]
+	vmov.i8		q9, #0x80
+	veor.8		q0, q0, q9
+	vtbl.8		d18, {d14-d15}, d0
+	vtbl.8		d15, {d14-d15}, d1
+	vmov		d14, d18
+	b		_128_done
+ENDPROC(crc_t10dif_pmull)
+
+// precomputed constants
+// these constants are precomputed from the poly:
+// 0x8bb70000 (0x8bb7 scaled to 32 bits)
+	.align		4
+// Q = 0x18BB70000
+// rk1 = 2^(32*3) mod Q << 32
+// rk2 = 2^(32*5) mod Q << 32
+// rk3 = 2^(32*15) mod Q << 32
+// rk4 = 2^(32*17) mod Q << 32
+// rk5 = 2^(32*3) mod Q << 32
+// rk6 = 2^(32*2) mod Q << 32
+// rk7 = floor(2^64/Q)
+// rk8 = Q
+
+rk3:	.quad		0x9d9d000000000000
+rk4:	.quad		0x7cf5000000000000
+rk5:	.quad		0x2d56000000000000
+rk6:	.quad		0x1368000000000000
+rk7:	.quad		0x00000001f65a57f8
+rk8:	.quad		0x000000018bb70000
+rk9:	.quad		0xceae000000000000
+rk10:	.quad		0xbfd6000000000000
+rk11:	.quad		0x1e16000000000000
+rk12:	.quad		0x713c000000000000
+rk13:	.quad		0xf7f9000000000000
+rk14:	.quad		0x80a6000000000000
+rk15:	.quad		0x044c000000000000
+rk16:	.quad		0xe658000000000000
+rk17:	.quad		0xad18000000000000
+rk18:	.quad		0xa497000000000000
+rk19:	.quad		0x6ee3000000000000
+rk20:	.quad		0xe7b5000000000000
+rk1:	.quad		0x2d56000000000000
+rk2:	.quad		0x06df000000000000
+
+tbl_shf_table:
+// use these values for shift constants for the tbl/tbx instruction
+// different alignments result in values as shown:
+//	DDQ 0x008f8e8d8c8b8a898887868584838281 # shl 15 (16-1) / shr1
+//	DDQ 0x01008f8e8d8c8b8a8988878685848382 # shl 14 (16-3) / shr2
+//	DDQ 0x0201008f8e8d8c8b8a89888786858483 # shl 13 (16-4) / shr3
+//	DDQ 0x030201008f8e8d8c8b8a898887868584 # shl 12 (16-4) / shr4
+//	DDQ 0x04030201008f8e8d8c8b8a8988878685 # shl 11 (16-5) / shr5
+//	DDQ 0x0504030201008f8e8d8c8b8a89888786 # shl 10 (16-6) / shr6
+//	DDQ 0x060504030201008f8e8d8c8b8a898887 # shl 9  (16-7) / shr7
+//	DDQ 0x07060504030201008f8e8d8c8b8a8988 # shl 8  (16-8) / shr8
+//	DDQ 0x0807060504030201008f8e8d8c8b8a89 # shl 7  (16-9) / shr9
+//	DDQ 0x090807060504030201008f8e8d8c8b8a # shl 6  (16-10) / shr10
+//	DDQ 0x0a090807060504030201008f8e8d8c8b # shl 5  (16-11) / shr11
+//	DDQ 0x0b0a090807060504030201008f8e8d8c # shl 4  (16-12) / shr12
+//	DDQ 0x0c0b0a090807060504030201008f8e8d # shl 3  (16-13) / shr13
+//	DDQ 0x0d0c0b0a090807060504030201008f8e # shl 2  (16-14) / shr14
+//	DDQ 0x0e0d0c0b0a090807060504030201008f # shl 1  (16-15) / shr15
+
+	.byte		 0x0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
+	.byte		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f
+	.byte		 0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7
+	.byte		 0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe , 0x0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/crct10dif-ce-glue.c linux-libre-4.10-rc8-gnu/arch/arm/crypto/crct10dif-ce-glue.c
--- linux-libre-4.9-gnu/arch/arm/crypto/crct10dif-ce-glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/crct10dif-ce-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * Accelerated CRC-T10DIF using ARM NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+ */
+
+#include <linux/crc-t10dif.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/neon.h>
+#include <asm/simd.h>
+
+#define CRC_T10DIF_PMULL_CHUNK_SIZE	16U
+
+asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 buf[], u32 len);
+
+static int crct10dif_init(struct shash_desc *desc)
+{
+	u16 *crc = shash_desc_ctx(desc);
+
+	*crc = 0;
+	return 0;
+}
+
+static int crct10dif_update(struct shash_desc *desc, const u8 *data,
+			    unsigned int length)
+{
+	u16 *crc = shash_desc_ctx(desc);
+	unsigned int l;
+
+	if (!may_use_simd()) {
+		*crc = crc_t10dif_generic(*crc, data, length);
+	} else {
+		if (unlikely((u32)data % CRC_T10DIF_PMULL_CHUNK_SIZE)) {
+			l = min_t(u32, length, CRC_T10DIF_PMULL_CHUNK_SIZE -
+				  ((u32)data % CRC_T10DIF_PMULL_CHUNK_SIZE));
+
+			*crc = crc_t10dif_generic(*crc, data, l);
+
+			length -= l;
+			data += l;
+		}
+		if (length > 0) {
+			kernel_neon_begin();
+			*crc = crc_t10dif_pmull(*crc, data, length);
+			kernel_neon_end();
+		}
+	}
+	return 0;
+}
+
+static int crct10dif_final(struct shash_desc *desc, u8 *out)
+{
+	u16 *crc = shash_desc_ctx(desc);
+
+	*(u16 *)out = *crc;
+	return 0;
+}
+
+static struct shash_alg crc_t10dif_alg = {
+	.digestsize		= CRC_T10DIF_DIGEST_SIZE,
+	.init			= crct10dif_init,
+	.update			= crct10dif_update,
+	.final			= crct10dif_final,
+	.descsize		= CRC_T10DIF_DIGEST_SIZE,
+
+	.base.cra_name		= "crct10dif",
+	.base.cra_driver_name	= "crct10dif-arm-ce",
+	.base.cra_priority	= 200,
+	.base.cra_blocksize	= CRC_T10DIF_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+};
+
+static int __init crc_t10dif_mod_init(void)
+{
+	if (!(elf_hwcap2 & HWCAP2_PMULL))
+		return -ENODEV;
+
+	return crypto_register_shash(&crc_t10dif_alg);
+}
+
+static void __exit crc_t10dif_mod_exit(void)
+{
+	crypto_unregister_shash(&crc_t10dif_alg);
+}
+
+module_init(crc_t10dif_mod_init);
+module_exit(crc_t10dif_mod_exit);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("crct10dif");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/crypto/Kconfig
--- linux-libre-4.9-gnu/arch/arm/crypto/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -88,9 +88,9 @@ config CRYPTO_AES_ARM
 config CRYPTO_AES_ARM_BS
 	tristate "Bit sliced AES using NEON instructions"
 	depends on KERNEL_MODE_NEON
-	select CRYPTO_ALGAPI
 	select CRYPTO_AES_ARM
-	select CRYPTO_ABLK_HELPER
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_SIMD
 	help
 	  Use a faster and more secure NEON based implementation of AES in CBC,
 	  CTR and XTS modes
@@ -104,8 +104,8 @@ config CRYPTO_AES_ARM_BS
 config CRYPTO_AES_ARM_CE
 	tristate "Accelerated AES using ARMv8 Crypto Extensions"
 	depends on KERNEL_MODE_NEON
-	select CRYPTO_ALGAPI
-	select CRYPTO_ABLK_HELPER
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_SIMD
 	help
 	  Use an implementation of AES in CBC, CTR and XTS modes that uses
 	  ARMv8 Crypto Extensions
@@ -120,4 +120,14 @@ config CRYPTO_GHASH_ARM_CE
 	  that uses the 64x64 to 128 bit polynomial multiplication (vmull.p64)
 	  that is part of the ARMv8 Crypto Extensions
 
+config CRYPTO_CRCT10DIF_ARM_CE
+	tristate "CRCT10DIF digest algorithm using PMULL instructions"
+	depends on KERNEL_MODE_NEON && CRC_T10DIF
+	select CRYPTO_HASH
+
+config CRYPTO_CRC32_ARM_CE
+	tristate "CRC32(C) digest algorithm using CRC and/or PMULL instructions"
+	depends on KERNEL_MODE_NEON && CRC32
+	select CRYPTO_HASH
+
 endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/crypto/Makefile linux-libre-4.10-rc8-gnu/arch/arm/crypto/Makefile
--- linux-libre-4.9-gnu/arch/arm/crypto/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/crypto/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,8 @@ ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += ae
 ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
 ce-obj-$(CONFIG_CRYPTO_SHA2_ARM_CE) += sha2-arm-ce.o
 ce-obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
+ce-obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM_CE) += crct10dif-arm-ce.o
+ce-obj-$(CONFIG_CRYPTO_CRC32_ARM_CE) += crc32-arm-ce.o
 
 ifneq ($(ce-obj-y)$(ce-obj-m),)
 ifeq ($(call as-instr,.fpu crypto-neon-fp-armv8,y,n),y)
@@ -36,6 +38,8 @@ sha1-arm-ce-y	:= sha1-ce-core.o sha1-ce-
 sha2-arm-ce-y	:= sha2-ce-core.o sha2-ce-glue.o
 aes-arm-ce-y	:= aes-ce-core.o aes-ce-glue.o
 ghash-arm-ce-y	:= ghash-ce-core.o ghash-ce-glue.o
+crct10dif-arm-ce-y	:= crct10dif-ce-core.o crct10dif-ce-glue.o
+crc32-arm-ce-y:= crc32-ce-core.o crc32-ce-glue.o
 
 quiet_cmd_perl = PERL    $@
       cmd_perl = $(PERL) $(<) > $(@)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/arch_gicv3.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/arch_gicv3.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/arch_gicv3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/arch_gicv3.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@
 
 #include <linux/io.h>
 #include <asm/barrier.h>
+#include <asm/cacheflush.h>
 #include <asm/cp15.h>
 
 #define ICC_EOIR1			__ACCESS_CP15(c12, 0, c12, 1)
@@ -230,19 +231,14 @@ static inline void gic_write_bpr1(u32 va
  * AArch32, since the syndrome register doesn't provide any information for
  * them.
  * Consequently, the following IO helpers use 32bit accesses.
- *
- * There are only two registers that need 64bit accesses in this driver:
- * - GICD_IROUTERn, contain the affinity values associated to each interrupt.
- *   The upper-word (aff3) will always be 0, so there is no need for a lock.
- * - GICR_TYPER is an ID register and doesn't need atomicity.
  */
-static inline void gic_write_irouter(u64 val, volatile void __iomem *addr)
+static inline void __gic_writeq_nonatomic(u64 val, volatile void __iomem *addr)
 {
 	writel_relaxed((u32)val, addr);
 	writel_relaxed((u32)(val >> 32), addr + 4);
 }
 
-static inline u64 gic_read_typer(const volatile void __iomem *addr)
+static inline u64 __gic_readq_nonatomic(const volatile void __iomem *addr)
 {
 	u64 val;
 
@@ -251,5 +247,49 @@ static inline u64 gic_read_typer(const v
 	return val;
 }
 
+#define gic_flush_dcache_to_poc(a,l)    __cpuc_flush_dcache_area((a), (l))
+
+/*
+ *  GICD_IROUTERn, contain the affinity values associated to each interrupt.
+ *  The upper-word (aff3) will always be 0, so there is no need for a lock.
+ */
+#define gic_write_irouter(v, c)		__gic_writeq_nonatomic(v, c)
+
+/*
+ * GICR_TYPER is an ID register and doesn't need atomicity.
+ */
+#define gic_read_typer(c)		__gic_readq_nonatomic(c)
+
+/*
+ * GITS_BASER - hi and lo bits may be accessed independently.
+ */
+#define gits_read_baser(c)		__gic_readq_nonatomic(c)
+#define gits_write_baser(v, c)		__gic_writeq_nonatomic(v, c)
+
+/*
+ * GICR_PENDBASER and GICR_PROPBASE are changed with LPIs disabled, so they
+ * won't be being used during any updates and can be changed non-atomically
+ */
+#define gicr_read_propbaser(c)		__gic_readq_nonatomic(c)
+#define gicr_write_propbaser(v, c)	__gic_writeq_nonatomic(v, c)
+#define gicr_read_pendbaser(c)		__gic_readq_nonatomic(c)
+#define gicr_write_pendbaser(v, c)	__gic_writeq_nonatomic(v, c)
+
+/*
+ * GITS_TYPER is an ID register and doesn't need atomicity.
+ */
+#define gits_read_typer(c)		__gic_readq_nonatomic(c)
+
+/*
+ * GITS_CBASER - hi and lo bits may be accessed independently.
+ */
+#define gits_read_cbaser(c)		__gic_readq_nonatomic(c)
+#define gits_write_cbaser(v, c)		__gic_writeq_nonatomic(v, c)
+
+/*
+ * GITS_CWRITER - hi and lo bits may be accessed independently.
+ */
+#define gits_write_cwriter(v, c)	__gic_writeq_nonatomic(v, c)
+
 #endif /* !__ASSEMBLY__ */
 #endif /* !__ASM_ARCH_GICV3_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/cputype.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/cputype.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/cputype.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/cputype.h	2017-02-12 16:03:20.000000000 -0500
@@ -94,6 +94,9 @@
 #define ARM_CPU_XSCALE_ARCH_V2		0x4000
 #define ARM_CPU_XSCALE_ARCH_V3		0x6000
 
+/* Qualcomm implemented cores */
+#define ARM_CPU_PART_SCORPION		0x510002d0
+
 extern unsigned int processor_id;
 
 #ifdef CONFIG_CPU_CP15
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/delay.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/delay.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/delay.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/delay.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,33 @@
 #include <asm/memory.h>
 #include <asm/param.h>	/* HZ */
 
+/*
+ * Loop (or tick) based delay:
+ *
+ * loops = loops_per_jiffy * jiffies_per_sec * delay_us / us_per_sec
+ *
+ * where:
+ *
+ * jiffies_per_sec = HZ
+ * us_per_sec = 1000000
+ *
+ * Therefore the constant part is HZ / 1000000 which is a small
+ * fractional number. To make this usable with integer math, we
+ * scale up this constant by 2^31, perform the actual multiplication,
+ * and scale the result back down by 2^31 with a simple shift:
+ *
+ * loops = (loops_per_jiffy * delay_us * UDELAY_MULT) >> 31
+ *
+ * where:
+ *
+ * UDELAY_MULT = 2^31 * HZ / 1000000
+ *             = (2^31 / 1000000) * HZ
+ *             = 2147.483648 * HZ
+ *             = 2147 * HZ + 483648 * HZ / 1000000
+ *
+ * 31 is the biggest scale shift value that won't overflow 32 bits for
+ * delay_us * UDELAY_MULT assuming HZ <= 1000 and delay_us <= 2000.
+ */
 #define MAX_UDELAY_MS	2
 #define UDELAY_MULT	UL(2147 * HZ + 483648 * HZ / 1000000)
 #define UDELAY_SHIFT	31
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/efi.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/efi.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/efi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/efi.h	2017-02-12 16:03:20.000000000 -0500
@@ -57,6 +57,9 @@ void efi_virtmap_unload(void);
 #define __efi_call_early(f, ...)	f(__VA_ARGS__)
 #define efi_is_64bit()			(false)
 
+#define efi_call_proto(protocol, f, instance, ...)			\
+	((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
+
 struct screen_info *alloc_screen_info(efi_system_table_t *sys_table_arg);
 void free_screen_info(efi_system_table_t *sys_table, struct screen_info *si);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/ftrace.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/ftrace.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/ftrace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/ftrace.h	2017-02-12 16:03:20.000000000 -0500
@@ -54,6 +54,24 @@ static inline void *return_address(unsig
 
 #define ftrace_return_address(n) return_address(n)
 
+#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+
+static inline bool arch_syscall_match_sym_name(const char *sym,
+					       const char *name)
+{
+	if (!strcmp(sym, "sys_mmap2"))
+		sym = "sys_mmap_pgoff";
+	else if (!strcmp(sym, "sys_statfs64_wrapper"))
+		sym = "sys_statfs64";
+	else if (!strcmp(sym, "sys_fstatfs64_wrapper"))
+		sym = "sys_fstatfs64";
+	else if (!strcmp(sym, "sys_arm_fadvise64_64"))
+		sym = "sys_fadvise64_64";
+
+	/* Ignore case since sym may start with "SyS" instead of "sys" */
+	return !strcasecmp(sym, name);
+}
+
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* _ASM_ARM_FTRACE */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/io.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/io.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/io.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/io.h	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,6 @@
 
 #include <linux/string.h>
 #include <linux/types.h>
-#include <linux/blk_types.h>
 #include <asm/byteorder.h>
 #include <asm/memory.h>
 #include <asm-generic/pci_iomap.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/arm/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/arm/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -38,3 +38,6 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
+
+generated-y += mach-types.h
+generated-y += unistd-nr.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/mach-types.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/mach-types.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/mach-types.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/mach-types.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <generated/mach-types.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- * arch/arm/include/asm/mutex.h
- *
- * ARM optimized mutex locking primitives
- *
- * Please look into asm-generic/mutex-xchg.h for a formal definition.
- */
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
-/*
- * On pre-ARMv6 hardware this results in a swp-based implementation,
- * which is the most efficient. For ARMv6+, we have exclusive memory
- * accessors and use atomic_dec to avoid the extra xchg operations
- * on the locking slowpaths.
- */
-#if __LINUX_ARM_ARCH__ < 6
-#include <asm-generic/mutex-xchg.h>
-#else
-#include <asm-generic/mutex-dec.h>
-#endif
-#endif	/* _ASM_MUTEX_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -82,8 +82,6 @@ unsigned long get_wchan(struct task_stru
 #define cpu_relax()			barrier()
 #endif
 
-#define cpu_relax_lowlatency()                cpu_relax()
-
 #define task_pt_regs(p) \
 	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/tlb.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/tlb.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/tlb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/tlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -186,6 +186,8 @@ tlb_remove_tlb_entry(struct mmu_gather *
 	tlb_add_flush(tlb, addr);
 }
 
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	\
+	tlb_remove_tlb_entry(tlb, ptep, address)
 /*
  * In the case of tlb vma handling, we can optimise these away in the
  * case where we're doing a full MM flush.  When we're doing a munmap,
@@ -211,18 +213,17 @@ tlb_end_vma(struct mmu_gather *tlb, stru
 
 static inline bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
+	tlb->pages[tlb->nr++] = page;
+	VM_WARN_ON(tlb->nr > tlb->max);
 	if (tlb->nr == tlb->max)
 		return true;
-	tlb->pages[tlb->nr++] = page;
 	return false;
 }
 
 static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
-	if (__tlb_remove_page(tlb, page)) {
+	if (__tlb_remove_page(tlb, page))
 		tlb_flush_mmu(tlb);
-		__tlb_remove_page(tlb, page);
-	}
 }
 
 static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
@@ -231,12 +232,6 @@ static inline bool __tlb_remove_page_siz
 	return __tlb_remove_page(tlb, page);
 }
 
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
-					 struct page *page)
-{
-	return __tlb_remove_page(tlb, page);
-}
-
 static inline void tlb_remove_page_size(struct mmu_gather *tlb,
 					struct page *page, int page_size)
 {
@@ -284,5 +279,11 @@ tlb_remove_pmd_tlb_entry(struct mmu_gath
 
 #define tlb_migrate_finish(mm)		do { } while (0)
 
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+						     unsigned int page_size)
+{
+}
+
 #endif /* CONFIG_MMU */
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/types.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/types.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/types.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/types.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-#ifndef _ASM_TYPES_H
-#define _ASM_TYPES_H
-
-#include <asm-generic/int-ll64.h>
-
-/*
- * The C99 types uintXX_t that are usually defined in 'stdint.h' are not as
- * unambiguous on ARM as you would expect. For the types below, there is a
- * difference on ARM between GCC built for bare metal ARM, GCC built for glibc
- * and the kernel itself, which results in build errors if you try to build with
- * -ffreestanding and include 'stdint.h' (such as when you include 'arm_neon.h'
- * in order to use NEON intrinsics)
- *
- * As the typedefs for these types in 'stdint.h' are based on builtin defines
- * supplied by GCC, we can tweak these to align with the kernel's idea of those
- * types, so 'linux/types.h' and 'stdint.h' can be safely included from the same
- * source file (provided that -ffreestanding is used).
- *
- *                    int32_t         uint32_t               uintptr_t
- * bare metal GCC     long            unsigned long          unsigned int
- * glibc GCC          int             unsigned int           unsigned int
- * kernel             int             unsigned int           unsigned long
- */
-
-#ifdef __INT32_TYPE__
-#undef __INT32_TYPE__
-#define __INT32_TYPE__		int
-#endif
-
-#ifdef __UINT32_TYPE__
-#undef __UINT32_TYPE__
-#define __UINT32_TYPE__	unsigned int
-#endif
-
-#ifdef __UINTPTR_TYPE__
-#undef __UINTPTR_TYPE__
-#define __UINTPTR_TYPE__	unsigned long
-#endif
-
-#endif /* _ASM_TYPES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/unistd.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/unistd.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/unistd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/unistd.h	2017-02-12 16:03:20.000000000 -0500
@@ -14,12 +14,7 @@
 #define __ASM_ARM_UNISTD_H
 
 #include <uapi/asm/unistd.h>
-
-/*
- * This may need to be greater than __NR_last_syscall+1 in order to
- * account for the padding in the syscall table
- */
-#define __NR_syscalls  (400)
+#include <asm/unistd-nr.h>
 
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
@@ -52,4 +47,23 @@
 #define __IGNORE_fadvise64_64
 #define __IGNORE_migrate_pages
 
+#ifdef __ARM_EABI__
+/*
+ * The following syscalls are obsolete and no longer available for EABI:
+ *  __NR_time
+ *  __NR_umount
+ *  __NR_stime
+ *  __NR_alarm
+ *  __NR_utime
+ *  __NR_getrlimit
+ *  __NR_select
+ *  __NR_readdir
+ *  __NR_mmap
+ *  __NR_socketcall
+ *  __NR_syscall
+ *  __NR_ipc
+ */
+#define __IGNORE_getrlimit
+#endif
+
 #endif /* __ASM_ARM_UNISTD_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/virt.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/virt.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/virt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/virt.h	2017-02-12 16:03:20.000000000 -0500
@@ -80,6 +80,11 @@ static inline bool is_kernel_in_hyp_mode
 	return false;
 }
 
+static inline bool has_vhe(void)
+{
+	return false;
+}
+
 /* The section containing the hypervisor idmap text */
 extern char __hyp_idmap_text_start[];
 extern char __hyp_idmap_text_end[];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/xen/hypercall.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/hypercall.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/xen/hypercall.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/hypercall.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,87 +1 @@
-/******************************************************************************
- * hypercall.h
- *
- * Linux-specific hypervisor handling.
- *
- * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation; or, when distributed
- * separately from the Linux kernel or incorporated into other
- * software packages, subject to the following license:
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this source file (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef _ASM_ARM_XEN_HYPERCALL_H
-#define _ASM_ARM_XEN_HYPERCALL_H
-
-#include <linux/bug.h>
-
-#include <xen/interface/xen.h>
-#include <xen/interface/sched.h>
-#include <xen/interface/platform.h>
-
-long privcmd_call(unsigned call, unsigned long a1,
-		unsigned long a2, unsigned long a3,
-		unsigned long a4, unsigned long a5);
-int HYPERVISOR_xen_version(int cmd, void *arg);
-int HYPERVISOR_console_io(int cmd, int count, char *str);
-int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
-int HYPERVISOR_sched_op(int cmd, void *arg);
-int HYPERVISOR_event_channel_op(int cmd, void *arg);
-unsigned long HYPERVISOR_hvm_op(int op, void *arg);
-int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
-int HYPERVISOR_physdev_op(int cmd, void *arg);
-int HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args);
-int HYPERVISOR_tmem_op(void *arg);
-int HYPERVISOR_vm_assist(unsigned int cmd, unsigned int type);
-int HYPERVISOR_platform_op_raw(void *arg);
-static inline int HYPERVISOR_platform_op(struct xen_platform_op *op)
-{
-	op->interface_version = XENPF_INTERFACE_VERSION;
-	return HYPERVISOR_platform_op_raw(op);
-}
-int HYPERVISOR_multicall(struct multicall_entry *calls, uint32_t nr);
-
-static inline int
-HYPERVISOR_suspend(unsigned long start_info_mfn)
-{
-	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
-
-	/* start_info_mfn is unused on ARM */
-	return HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
-}
-
-static inline void
-MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
-			unsigned int new_val, unsigned long flags)
-{
-	BUG();
-}
-
-static inline void
-MULTI_mmu_update(struct multicall_entry *mcl, struct mmu_update *req,
-		 int count, int *success_count, domid_t domid)
-{
-	BUG();
-}
-
-#endif /* _ASM_ARM_XEN_HYPERCALL_H */
+#include <xen/arm/hypercall.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/xen/hypervisor.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/hypervisor.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/xen/hypervisor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/hypervisor.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,39 +1 @@
-#ifndef _ASM_ARM_XEN_HYPERVISOR_H
-#define _ASM_ARM_XEN_HYPERVISOR_H
-
-#include <linux/init.h>
-
-extern struct shared_info *HYPERVISOR_shared_info;
-extern struct start_info *xen_start_info;
-
-/* Lazy mode for batching updates / context switch */
-enum paravirt_lazy_mode {
-	PARAVIRT_LAZY_NONE,
-	PARAVIRT_LAZY_MMU,
-	PARAVIRT_LAZY_CPU,
-};
-
-static inline enum paravirt_lazy_mode paravirt_get_lazy_mode(void)
-{
-	return PARAVIRT_LAZY_NONE;
-}
-
-extern struct dma_map_ops *xen_dma_ops;
-
-#ifdef CONFIG_XEN
-void __init xen_early_init(void);
-#else
-static inline void xen_early_init(void) { return; }
-#endif
-
-#ifdef CONFIG_HOTPLUG_CPU
-static inline void xen_arch_register_cpu(int num)
-{
-}
-
-static inline void xen_arch_unregister_cpu(int num)
-{
-}
-#endif
-
-#endif /* _ASM_ARM_XEN_HYPERVISOR_H */
+#include <xen/arm/hypervisor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/xen/interface.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/interface.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/xen/interface.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/interface.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,85 +1 @@
-/******************************************************************************
- * Guest OS interface to ARM Xen.
- *
- * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
- */
-
-#ifndef _ASM_ARM_XEN_INTERFACE_H
-#define _ASM_ARM_XEN_INTERFACE_H
-
-#include <linux/types.h>
-
-#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
-
-#define __DEFINE_GUEST_HANDLE(name, type) \
-	typedef struct { union { type *p; uint64_aligned_t q; }; }  \
-        __guest_handle_ ## name
-
-#define DEFINE_GUEST_HANDLE_STRUCT(name) \
-	__DEFINE_GUEST_HANDLE(name, struct name)
-#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
-#define GUEST_HANDLE(name)        __guest_handle_ ## name
-
-#define set_xen_guest_handle(hnd, val)			\
-	do {						\
-		if (sizeof(hnd) == 8)			\
-			*(uint64_t *)&(hnd) = 0;	\
-		(hnd).p = val;				\
-	} while (0)
-
-#define __HYPERVISOR_platform_op_raw __HYPERVISOR_platform_op
-
-#ifndef __ASSEMBLY__
-/* Explicitly size integers that represent pfns in the interface with
- * Xen so that we can have one ABI that works for 32 and 64 bit guests.
- * Note that this means that the xen_pfn_t type may be capable of
- * representing pfn's which the guest cannot represent in its own pfn
- * type. However since pfn space is controlled by the guest this is
- * fine since it simply wouldn't be able to create any sure pfns in
- * the first place.
- */
-typedef uint64_t xen_pfn_t;
-#define PRI_xen_pfn "llx"
-typedef uint64_t xen_ulong_t;
-#define PRI_xen_ulong "llx"
-typedef int64_t xen_long_t;
-#define PRI_xen_long "llx"
-/* Guest handles for primitive C types. */
-__DEFINE_GUEST_HANDLE(uchar, unsigned char);
-__DEFINE_GUEST_HANDLE(uint,  unsigned int);
-DEFINE_GUEST_HANDLE(char);
-DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(void);
-DEFINE_GUEST_HANDLE(uint64_t);
-DEFINE_GUEST_HANDLE(uint32_t);
-DEFINE_GUEST_HANDLE(xen_pfn_t);
-DEFINE_GUEST_HANDLE(xen_ulong_t);
-
-/* Maximum number of virtual CPUs in multi-processor guests. */
-#define MAX_VIRT_CPUS 1
-
-struct arch_vcpu_info { };
-struct arch_shared_info { };
-
-/* TODO: Move pvclock definitions some place arch independent */
-struct pvclock_vcpu_time_info {
-	u32   version;
-	u32   pad0;
-	u64   tsc_timestamp;
-	u64   system_time;
-	u32   tsc_to_system_mul;
-	s8    tsc_shift;
-	u8    flags;
-	u8    pad[2];
-} __attribute__((__packed__)); /* 32 bytes */
-
-/* It is OK to have a 12 bytes struct with no padding because it is packed */
-struct pvclock_wall_clock {
-	u32   version;
-	u32   sec;
-	u32   nsec;
-	u32   sec_hi;
-} __attribute__((__packed__));
-#endif
-
-#endif /* _ASM_ARM_XEN_INTERFACE_H */
+#include <xen/arm/interface.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/xen/page-coherent.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/page-coherent.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/xen/page-coherent.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/page-coherent.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,98 +1 @@
-#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
-#define _ASM_ARM_XEN_PAGE_COHERENT_H
-
-#include <asm/page.h>
-#include <linux/dma-mapping.h>
-
-void __xen_dma_map_page(struct device *hwdev, struct page *page,
-	     dma_addr_t dev_addr, unsigned long offset, size_t size,
-	     enum dma_data_direction dir, unsigned long attrs);
-void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
-		size_t size, enum dma_data_direction dir,
-		unsigned long attrs);
-void __xen_dma_sync_single_for_cpu(struct device *hwdev,
-		dma_addr_t handle, size_t size, enum dma_data_direction dir);
-
-void __xen_dma_sync_single_for_device(struct device *hwdev,
-		dma_addr_t handle, size_t size, enum dma_data_direction dir);
-
-static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
-		dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
-{
-	return __generic_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
-}
-
-static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
-		void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
-{
-	__generic_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
-}
-
-static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
-	     dma_addr_t dev_addr, unsigned long offset, size_t size,
-	     enum dma_data_direction dir, unsigned long attrs)
-{
-	unsigned long page_pfn = page_to_xen_pfn(page);
-	unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
-	unsigned long compound_pages =
-		(1<<compound_order(page)) * XEN_PFN_PER_PAGE;
-	bool local = (page_pfn <= dev_pfn) &&
-		(dev_pfn - page_pfn < compound_pages);
-
-	/*
-	 * Dom0 is mapped 1:1, while the Linux page can span across
-	 * multiple Xen pages, it's not possible for it to contain a
-	 * mix of local and foreign Xen pages. So if the first xen_pfn
-	 * == mfn the page is local otherwise it's a foreign page
-	 * grant-mapped in dom0. If the page is local we can safely
-	 * call the native dma_ops function, otherwise we call the xen
-	 * specific function.
-	 */
-	if (local)
-		__generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
-	else
-		__xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
-}
-
-static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
-		size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-	unsigned long pfn = PFN_DOWN(handle);
-	/*
-	 * Dom0 is mapped 1:1, while the Linux page can be spanned accross
-	 * multiple Xen page, it's not possible to have a mix of local and
-	 * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
-	 * foreign mfn will always return false. If the page is local we can
-	 * safely call the native dma_ops function, otherwise we call the xen
-	 * specific function.
-	 */
-	if (pfn_valid(pfn)) {
-		if (__generic_dma_ops(hwdev)->unmap_page)
-			__generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
-	} else
-		__xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
-}
-
-static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
-		dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-	unsigned long pfn = PFN_DOWN(handle);
-	if (pfn_valid(pfn)) {
-		if (__generic_dma_ops(hwdev)->sync_single_for_cpu)
-			__generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
-	} else
-		__xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
-}
-
-static inline void xen_dma_sync_single_for_device(struct device *hwdev,
-		dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-	unsigned long pfn = PFN_DOWN(handle);
-	if (pfn_valid(pfn)) {
-		if (__generic_dma_ops(hwdev)->sync_single_for_device)
-			__generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
-	} else
-		__xen_dma_sync_single_for_device(hwdev, handle, size, dir);
-}
-
-#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
+#include <xen/arm/page-coherent.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/asm/xen/page.h linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/page.h
--- linux-libre-4.9-gnu/arch/arm/include/asm/xen/page.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/asm/xen/page.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,122 +1 @@
-#ifndef _ASM_ARM_XEN_PAGE_H
-#define _ASM_ARM_XEN_PAGE_H
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-#include <linux/pfn.h>
-#include <linux/types.h>
-#include <linux/dma-mapping.h>
-
-#include <xen/xen.h>
-#include <xen/interface/grant_table.h>
-
-#define phys_to_machine_mapping_valid(pfn) (1)
-
-/* Xen machine address */
-typedef struct xmaddr {
-	phys_addr_t maddr;
-} xmaddr_t;
-
-/* Xen pseudo-physical address */
-typedef struct xpaddr {
-	phys_addr_t paddr;
-} xpaddr_t;
-
-#define XMADDR(x)	((xmaddr_t) { .maddr = (x) })
-#define XPADDR(x)	((xpaddr_t) { .paddr = (x) })
-
-#define INVALID_P2M_ENTRY      (~0UL)
-
-/*
- * The pseudo-physical frame (pfn) used in all the helpers is always based
- * on Xen page granularity (i.e 4KB).
- *
- * A Linux page may be split across multiple non-contiguous Xen page so we
- * have to keep track with frame based on 4KB page granularity.
- *
- * PV drivers should never make a direct usage of those helpers (particularly
- * pfn_to_gfn and gfn_to_pfn).
- */
-
-unsigned long __pfn_to_mfn(unsigned long pfn);
-extern struct rb_root phys_to_mach;
-
-/* Pseudo-physical <-> Guest conversion */
-static inline unsigned long pfn_to_gfn(unsigned long pfn)
-{
-	return pfn;
-}
-
-static inline unsigned long gfn_to_pfn(unsigned long gfn)
-{
-	return gfn;
-}
-
-/* Pseudo-physical <-> BUS conversion */
-static inline unsigned long pfn_to_bfn(unsigned long pfn)
-{
-	unsigned long mfn;
-
-	if (phys_to_mach.rb_node != NULL) {
-		mfn = __pfn_to_mfn(pfn);
-		if (mfn != INVALID_P2M_ENTRY)
-			return mfn;
-	}
-
-	return pfn;
-}
-
-static inline unsigned long bfn_to_pfn(unsigned long bfn)
-{
-	return bfn;
-}
-
-#define bfn_to_local_pfn(bfn)	bfn_to_pfn(bfn)
-
-/* VIRT <-> GUEST conversion */
-#define virt_to_gfn(v)		(pfn_to_gfn(virt_to_phys(v) >> XEN_PAGE_SHIFT))
-#define gfn_to_virt(m)		(__va(gfn_to_pfn(m) << XEN_PAGE_SHIFT))
-
-/* Only used in PV code. But ARM guests are always HVM. */
-static inline xmaddr_t arbitrary_virt_to_machine(void *vaddr)
-{
-	BUG();
-}
-
-/* TODO: this shouldn't be here but it is because the frontend drivers
- * are using it (its rolled in headers) even though we won't hit the code path.
- * So for right now just punt with this.
- */
-static inline pte_t *lookup_address(unsigned long address, unsigned int *level)
-{
-	BUG();
-	return NULL;
-}
-
-extern int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
-				   struct gnttab_map_grant_ref *kmap_ops,
-				   struct page **pages, unsigned int count);
-
-extern int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops,
-				     struct gnttab_unmap_grant_ref *kunmap_ops,
-				     struct page **pages, unsigned int count);
-
-bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
-bool __set_phys_to_machine_multi(unsigned long pfn, unsigned long mfn,
-		unsigned long nr_pages);
-
-static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
-{
-	return __set_phys_to_machine(pfn, mfn);
-}
-
-#define xen_remap(cookie, size) ioremap_cache((cookie), (size))
-#define xen_unmap(cookie) iounmap((cookie))
-
-bool xen_arch_need_swiotlb(struct device *dev,
-			   phys_addr_t phys,
-			   dma_addr_t dev_addr);
-unsigned long xen_get_swiotlb_free_pages(unsigned int order);
-
-#endif /* _ASM_ARM_XEN_PAGE_H */
+#include <xen/arm/page.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/uapi/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/Kbuild
--- linux-libre-4.9-gnu/arch/arm/include/uapi/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -18,3 +18,6 @@ header-y += stat.h
 header-y += statfs.h
 header-y += swab.h
 header-y += unistd.h
+genhdr-y += unistd-common.h
+genhdr-y += unistd-oabi.h
+genhdr-y += unistd-eabi.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/uapi/asm/kvm.h linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/kvm.h
--- linux-libre-4.9-gnu/arch/arm/include/uapi/asm/kvm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/kvm.h	2017-02-12 16:03:20.000000000 -0500
@@ -87,9 +87,11 @@ struct kvm_regs {
 /* Supported VGICv3 address types  */
 #define KVM_VGIC_V3_ADDR_TYPE_DIST	2
 #define KVM_VGIC_V3_ADDR_TYPE_REDIST	3
+#define KVM_VGIC_ITS_ADDR_TYPE		4
 
 #define KVM_VGIC_V3_DIST_SIZE		SZ_64K
 #define KVM_VGIC_V3_REDIST_SIZE		(2 * SZ_64K)
+#define KVM_VGIC_V3_ITS_SIZE		(2 * SZ_64K)
 
 #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
 #define KVM_ARM_VCPU_PSCI_0_2		1 /* CPU uses PSCI v0.2 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/uapi/asm/types.h linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/types.h
--- linux-libre-4.9-gnu/arch/arm/include/uapi/asm/types.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/types.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,40 @@
+#ifndef _UAPI_ASM_TYPES_H
+#define _UAPI_ASM_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+/*
+ * The C99 types uintXX_t that are usually defined in 'stdint.h' are not as
+ * unambiguous on ARM as you would expect. For the types below, there is a
+ * difference on ARM between GCC built for bare metal ARM, GCC built for glibc
+ * and the kernel itself, which results in build errors if you try to build with
+ * -ffreestanding and include 'stdint.h' (such as when you include 'arm_neon.h'
+ * in order to use NEON intrinsics)
+ *
+ * As the typedefs for these types in 'stdint.h' are based on builtin defines
+ * supplied by GCC, we can tweak these to align with the kernel's idea of those
+ * types, so 'linux/types.h' and 'stdint.h' can be safely included from the same
+ * source file (provided that -ffreestanding is used).
+ *
+ *                    int32_t         uint32_t               uintptr_t
+ * bare metal GCC     long            unsigned long          unsigned int
+ * glibc GCC          int             unsigned int           unsigned int
+ * kernel             int             unsigned int           unsigned long
+ */
+
+#ifdef __INT32_TYPE__
+#undef __INT32_TYPE__
+#define __INT32_TYPE__		int
+#endif
+
+#ifdef __UINT32_TYPE__
+#undef __UINT32_TYPE__
+#define __UINT32_TYPE__	unsigned int
+#endif
+
+#ifdef __UINTPTR_TYPE__
+#undef __UINTPTR_TYPE__
+#define __UINTPTR_TYPE__	unsigned long
+#endif
+
+#endif /* _UAPI_ASM_TYPES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/include/uapi/asm/unistd.h linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/unistd.h
--- linux-libre-4.9-gnu/arch/arm/include/uapi/asm/unistd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/include/uapi/asm/unistd.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,412 +17,14 @@
 
 #if defined(__thumb__) || defined(__ARM_EABI__)
 #define __NR_SYSCALL_BASE	0
+#include <asm/unistd-eabi.h>
 #else
 #define __NR_SYSCALL_BASE	__NR_OABI_SYSCALL_BASE
+#include <asm/unistd-oabi.h>
 #endif
 
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall		(__NR_SYSCALL_BASE+  0)
-#define __NR_exit			(__NR_SYSCALL_BASE+  1)
-#define __NR_fork			(__NR_SYSCALL_BASE+  2)
-#define __NR_read			(__NR_SYSCALL_BASE+  3)
-#define __NR_write			(__NR_SYSCALL_BASE+  4)
-#define __NR_open			(__NR_SYSCALL_BASE+  5)
-#define __NR_close			(__NR_SYSCALL_BASE+  6)
-					/* 7 was sys_waitpid */
-#define __NR_creat			(__NR_SYSCALL_BASE+  8)
-#define __NR_link			(__NR_SYSCALL_BASE+  9)
-#define __NR_unlink			(__NR_SYSCALL_BASE+ 10)
-#define __NR_execve			(__NR_SYSCALL_BASE+ 11)
-#define __NR_chdir			(__NR_SYSCALL_BASE+ 12)
-#define __NR_time			(__NR_SYSCALL_BASE+ 13)
-#define __NR_mknod			(__NR_SYSCALL_BASE+ 14)
-#define __NR_chmod			(__NR_SYSCALL_BASE+ 15)
-#define __NR_lchown			(__NR_SYSCALL_BASE+ 16)
-					/* 17 was sys_break */
-					/* 18 was sys_stat */
-#define __NR_lseek			(__NR_SYSCALL_BASE+ 19)
-#define __NR_getpid			(__NR_SYSCALL_BASE+ 20)
-#define __NR_mount			(__NR_SYSCALL_BASE+ 21)
-#define __NR_umount			(__NR_SYSCALL_BASE+ 22)
-#define __NR_setuid			(__NR_SYSCALL_BASE+ 23)
-#define __NR_getuid			(__NR_SYSCALL_BASE+ 24)
-#define __NR_stime			(__NR_SYSCALL_BASE+ 25)
-#define __NR_ptrace			(__NR_SYSCALL_BASE+ 26)
-#define __NR_alarm			(__NR_SYSCALL_BASE+ 27)
-					/* 28 was sys_fstat */
-#define __NR_pause			(__NR_SYSCALL_BASE+ 29)
-#define __NR_utime			(__NR_SYSCALL_BASE+ 30)
-					/* 31 was sys_stty */
-					/* 32 was sys_gtty */
-#define __NR_access			(__NR_SYSCALL_BASE+ 33)
-#define __NR_nice			(__NR_SYSCALL_BASE+ 34)
-					/* 35 was sys_ftime */
-#define __NR_sync			(__NR_SYSCALL_BASE+ 36)
-#define __NR_kill			(__NR_SYSCALL_BASE+ 37)
-#define __NR_rename			(__NR_SYSCALL_BASE+ 38)
-#define __NR_mkdir			(__NR_SYSCALL_BASE+ 39)
-#define __NR_rmdir			(__NR_SYSCALL_BASE+ 40)
-#define __NR_dup			(__NR_SYSCALL_BASE+ 41)
-#define __NR_pipe			(__NR_SYSCALL_BASE+ 42)
-#define __NR_times			(__NR_SYSCALL_BASE+ 43)
-					/* 44 was sys_prof */
-#define __NR_brk			(__NR_SYSCALL_BASE+ 45)
-#define __NR_setgid			(__NR_SYSCALL_BASE+ 46)
-#define __NR_getgid			(__NR_SYSCALL_BASE+ 47)
-					/* 48 was sys_signal */
-#define __NR_geteuid			(__NR_SYSCALL_BASE+ 49)
-#define __NR_getegid			(__NR_SYSCALL_BASE+ 50)
-#define __NR_acct			(__NR_SYSCALL_BASE+ 51)
-#define __NR_umount2			(__NR_SYSCALL_BASE+ 52)
-					/* 53 was sys_lock */
-#define __NR_ioctl			(__NR_SYSCALL_BASE+ 54)
-#define __NR_fcntl			(__NR_SYSCALL_BASE+ 55)
-					/* 56 was sys_mpx */
-#define __NR_setpgid			(__NR_SYSCALL_BASE+ 57)
-					/* 58 was sys_ulimit */
-					/* 59 was sys_olduname */
-#define __NR_umask			(__NR_SYSCALL_BASE+ 60)
-#define __NR_chroot			(__NR_SYSCALL_BASE+ 61)
-#define __NR_ustat			(__NR_SYSCALL_BASE+ 62)
-#define __NR_dup2			(__NR_SYSCALL_BASE+ 63)
-#define __NR_getppid			(__NR_SYSCALL_BASE+ 64)
-#define __NR_getpgrp			(__NR_SYSCALL_BASE+ 65)
-#define __NR_setsid			(__NR_SYSCALL_BASE+ 66)
-#define __NR_sigaction			(__NR_SYSCALL_BASE+ 67)
-					/* 68 was sys_sgetmask */
-					/* 69 was sys_ssetmask */
-#define __NR_setreuid			(__NR_SYSCALL_BASE+ 70)
-#define __NR_setregid			(__NR_SYSCALL_BASE+ 71)
-#define __NR_sigsuspend			(__NR_SYSCALL_BASE+ 72)
-#define __NR_sigpending			(__NR_SYSCALL_BASE+ 73)
-#define __NR_sethostname		(__NR_SYSCALL_BASE+ 74)
-#define __NR_setrlimit			(__NR_SYSCALL_BASE+ 75)
-#define __NR_getrlimit			(__NR_SYSCALL_BASE+ 76)	/* Back compat 2GB limited rlimit */
-#define __NR_getrusage			(__NR_SYSCALL_BASE+ 77)
-#define __NR_gettimeofday		(__NR_SYSCALL_BASE+ 78)
-#define __NR_settimeofday		(__NR_SYSCALL_BASE+ 79)
-#define __NR_getgroups			(__NR_SYSCALL_BASE+ 80)
-#define __NR_setgroups			(__NR_SYSCALL_BASE+ 81)
-#define __NR_select			(__NR_SYSCALL_BASE+ 82)
-#define __NR_symlink			(__NR_SYSCALL_BASE+ 83)
-					/* 84 was sys_lstat */
-#define __NR_readlink			(__NR_SYSCALL_BASE+ 85)
-#define __NR_uselib			(__NR_SYSCALL_BASE+ 86)
-#define __NR_swapon			(__NR_SYSCALL_BASE+ 87)
-#define __NR_reboot			(__NR_SYSCALL_BASE+ 88)
-#define __NR_readdir			(__NR_SYSCALL_BASE+ 89)
-#define __NR_mmap			(__NR_SYSCALL_BASE+ 90)
-#define __NR_munmap			(__NR_SYSCALL_BASE+ 91)
-#define __NR_truncate			(__NR_SYSCALL_BASE+ 92)
-#define __NR_ftruncate			(__NR_SYSCALL_BASE+ 93)
-#define __NR_fchmod			(__NR_SYSCALL_BASE+ 94)
-#define __NR_fchown			(__NR_SYSCALL_BASE+ 95)
-#define __NR_getpriority		(__NR_SYSCALL_BASE+ 96)
-#define __NR_setpriority		(__NR_SYSCALL_BASE+ 97)
-					/* 98 was sys_profil */
-#define __NR_statfs			(__NR_SYSCALL_BASE+ 99)
-#define __NR_fstatfs			(__NR_SYSCALL_BASE+100)
-					/* 101 was sys_ioperm */
-#define __NR_socketcall			(__NR_SYSCALL_BASE+102)
-#define __NR_syslog			(__NR_SYSCALL_BASE+103)
-#define __NR_setitimer			(__NR_SYSCALL_BASE+104)
-#define __NR_getitimer			(__NR_SYSCALL_BASE+105)
-#define __NR_stat			(__NR_SYSCALL_BASE+106)
-#define __NR_lstat			(__NR_SYSCALL_BASE+107)
-#define __NR_fstat			(__NR_SYSCALL_BASE+108)
-					/* 109 was sys_uname */
-					/* 110 was sys_iopl */
-#define __NR_vhangup			(__NR_SYSCALL_BASE+111)
-					/* 112 was sys_idle */
-#define __NR_syscall			(__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
-#define __NR_wait4			(__NR_SYSCALL_BASE+114)
-#define __NR_swapoff			(__NR_SYSCALL_BASE+115)
-#define __NR_sysinfo			(__NR_SYSCALL_BASE+116)
-#define __NR_ipc			(__NR_SYSCALL_BASE+117)
-#define __NR_fsync			(__NR_SYSCALL_BASE+118)
-#define __NR_sigreturn			(__NR_SYSCALL_BASE+119)
-#define __NR_clone			(__NR_SYSCALL_BASE+120)
-#define __NR_setdomainname		(__NR_SYSCALL_BASE+121)
-#define __NR_uname			(__NR_SYSCALL_BASE+122)
-					/* 123 was sys_modify_ldt */
-#define __NR_adjtimex			(__NR_SYSCALL_BASE+124)
-#define __NR_mprotect			(__NR_SYSCALL_BASE+125)
-#define __NR_sigprocmask		(__NR_SYSCALL_BASE+126)
-					/* 127 was sys_create_module */
-#define __NR_init_module		(__NR_SYSCALL_BASE+128)
-#define __NR_delete_module		(__NR_SYSCALL_BASE+129)
-					/* 130 was sys_get_kernel_syms */
-#define __NR_quotactl			(__NR_SYSCALL_BASE+131)
-#define __NR_getpgid			(__NR_SYSCALL_BASE+132)
-#define __NR_fchdir			(__NR_SYSCALL_BASE+133)
-#define __NR_bdflush			(__NR_SYSCALL_BASE+134)
-#define __NR_sysfs			(__NR_SYSCALL_BASE+135)
-#define __NR_personality		(__NR_SYSCALL_BASE+136)
-					/* 137 was sys_afs_syscall */
-#define __NR_setfsuid			(__NR_SYSCALL_BASE+138)
-#define __NR_setfsgid			(__NR_SYSCALL_BASE+139)
-#define __NR__llseek			(__NR_SYSCALL_BASE+140)
-#define __NR_getdents			(__NR_SYSCALL_BASE+141)
-#define __NR__newselect			(__NR_SYSCALL_BASE+142)
-#define __NR_flock			(__NR_SYSCALL_BASE+143)
-#define __NR_msync			(__NR_SYSCALL_BASE+144)
-#define __NR_readv			(__NR_SYSCALL_BASE+145)
-#define __NR_writev			(__NR_SYSCALL_BASE+146)
-#define __NR_getsid			(__NR_SYSCALL_BASE+147)
-#define __NR_fdatasync			(__NR_SYSCALL_BASE+148)
-#define __NR__sysctl			(__NR_SYSCALL_BASE+149)
-#define __NR_mlock			(__NR_SYSCALL_BASE+150)
-#define __NR_munlock			(__NR_SYSCALL_BASE+151)
-#define __NR_mlockall			(__NR_SYSCALL_BASE+152)
-#define __NR_munlockall			(__NR_SYSCALL_BASE+153)
-#define __NR_sched_setparam		(__NR_SYSCALL_BASE+154)
-#define __NR_sched_getparam		(__NR_SYSCALL_BASE+155)
-#define __NR_sched_setscheduler		(__NR_SYSCALL_BASE+156)
-#define __NR_sched_getscheduler		(__NR_SYSCALL_BASE+157)
-#define __NR_sched_yield		(__NR_SYSCALL_BASE+158)
-#define __NR_sched_get_priority_max	(__NR_SYSCALL_BASE+159)
-#define __NR_sched_get_priority_min	(__NR_SYSCALL_BASE+160)
-#define __NR_sched_rr_get_interval	(__NR_SYSCALL_BASE+161)
-#define __NR_nanosleep			(__NR_SYSCALL_BASE+162)
-#define __NR_mremap			(__NR_SYSCALL_BASE+163)
-#define __NR_setresuid			(__NR_SYSCALL_BASE+164)
-#define __NR_getresuid			(__NR_SYSCALL_BASE+165)
-					/* 166 was sys_vm86 */
-					/* 167 was sys_query_module */
-#define __NR_poll			(__NR_SYSCALL_BASE+168)
-#define __NR_nfsservctl			(__NR_SYSCALL_BASE+169)
-#define __NR_setresgid			(__NR_SYSCALL_BASE+170)
-#define __NR_getresgid			(__NR_SYSCALL_BASE+171)
-#define __NR_prctl			(__NR_SYSCALL_BASE+172)
-#define __NR_rt_sigreturn		(__NR_SYSCALL_BASE+173)
-#define __NR_rt_sigaction		(__NR_SYSCALL_BASE+174)
-#define __NR_rt_sigprocmask		(__NR_SYSCALL_BASE+175)
-#define __NR_rt_sigpending		(__NR_SYSCALL_BASE+176)
-#define __NR_rt_sigtimedwait		(__NR_SYSCALL_BASE+177)
-#define __NR_rt_sigqueueinfo		(__NR_SYSCALL_BASE+178)
-#define __NR_rt_sigsuspend		(__NR_SYSCALL_BASE+179)
-#define __NR_pread64			(__NR_SYSCALL_BASE+180)
-#define __NR_pwrite64			(__NR_SYSCALL_BASE+181)
-#define __NR_chown			(__NR_SYSCALL_BASE+182)
-#define __NR_getcwd			(__NR_SYSCALL_BASE+183)
-#define __NR_capget			(__NR_SYSCALL_BASE+184)
-#define __NR_capset			(__NR_SYSCALL_BASE+185)
-#define __NR_sigaltstack		(__NR_SYSCALL_BASE+186)
-#define __NR_sendfile			(__NR_SYSCALL_BASE+187)
-					/* 188 reserved */
-					/* 189 reserved */
-#define __NR_vfork			(__NR_SYSCALL_BASE+190)
-#define __NR_ugetrlimit			(__NR_SYSCALL_BASE+191)	/* SuS compliant getrlimit */
-#define __NR_mmap2			(__NR_SYSCALL_BASE+192)
-#define __NR_truncate64			(__NR_SYSCALL_BASE+193)
-#define __NR_ftruncate64		(__NR_SYSCALL_BASE+194)
-#define __NR_stat64			(__NR_SYSCALL_BASE+195)
-#define __NR_lstat64			(__NR_SYSCALL_BASE+196)
-#define __NR_fstat64			(__NR_SYSCALL_BASE+197)
-#define __NR_lchown32			(__NR_SYSCALL_BASE+198)
-#define __NR_getuid32			(__NR_SYSCALL_BASE+199)
-#define __NR_getgid32			(__NR_SYSCALL_BASE+200)
-#define __NR_geteuid32			(__NR_SYSCALL_BASE+201)
-#define __NR_getegid32			(__NR_SYSCALL_BASE+202)
-#define __NR_setreuid32			(__NR_SYSCALL_BASE+203)
-#define __NR_setregid32			(__NR_SYSCALL_BASE+204)
-#define __NR_getgroups32		(__NR_SYSCALL_BASE+205)
-#define __NR_setgroups32		(__NR_SYSCALL_BASE+206)
-#define __NR_fchown32			(__NR_SYSCALL_BASE+207)
-#define __NR_setresuid32		(__NR_SYSCALL_BASE+208)
-#define __NR_getresuid32		(__NR_SYSCALL_BASE+209)
-#define __NR_setresgid32		(__NR_SYSCALL_BASE+210)
-#define __NR_getresgid32		(__NR_SYSCALL_BASE+211)
-#define __NR_chown32			(__NR_SYSCALL_BASE+212)
-#define __NR_setuid32			(__NR_SYSCALL_BASE+213)
-#define __NR_setgid32			(__NR_SYSCALL_BASE+214)
-#define __NR_setfsuid32			(__NR_SYSCALL_BASE+215)
-#define __NR_setfsgid32			(__NR_SYSCALL_BASE+216)
-#define __NR_getdents64			(__NR_SYSCALL_BASE+217)
-#define __NR_pivot_root			(__NR_SYSCALL_BASE+218)
-#define __NR_mincore			(__NR_SYSCALL_BASE+219)
-#define __NR_madvise			(__NR_SYSCALL_BASE+220)
-#define __NR_fcntl64			(__NR_SYSCALL_BASE+221)
-					/* 222 for tux */
-					/* 223 is unused */
-#define __NR_gettid			(__NR_SYSCALL_BASE+224)
-#define __NR_readahead			(__NR_SYSCALL_BASE+225)
-#define __NR_setxattr			(__NR_SYSCALL_BASE+226)
-#define __NR_lsetxattr			(__NR_SYSCALL_BASE+227)
-#define __NR_fsetxattr			(__NR_SYSCALL_BASE+228)
-#define __NR_getxattr			(__NR_SYSCALL_BASE+229)
-#define __NR_lgetxattr			(__NR_SYSCALL_BASE+230)
-#define __NR_fgetxattr			(__NR_SYSCALL_BASE+231)
-#define __NR_listxattr			(__NR_SYSCALL_BASE+232)
-#define __NR_llistxattr			(__NR_SYSCALL_BASE+233)
-#define __NR_flistxattr			(__NR_SYSCALL_BASE+234)
-#define __NR_removexattr		(__NR_SYSCALL_BASE+235)
-#define __NR_lremovexattr		(__NR_SYSCALL_BASE+236)
-#define __NR_fremovexattr		(__NR_SYSCALL_BASE+237)
-#define __NR_tkill			(__NR_SYSCALL_BASE+238)
-#define __NR_sendfile64			(__NR_SYSCALL_BASE+239)
-#define __NR_futex			(__NR_SYSCALL_BASE+240)
-#define __NR_sched_setaffinity		(__NR_SYSCALL_BASE+241)
-#define __NR_sched_getaffinity		(__NR_SYSCALL_BASE+242)
-#define __NR_io_setup			(__NR_SYSCALL_BASE+243)
-#define __NR_io_destroy			(__NR_SYSCALL_BASE+244)
-#define __NR_io_getevents		(__NR_SYSCALL_BASE+245)
-#define __NR_io_submit			(__NR_SYSCALL_BASE+246)
-#define __NR_io_cancel			(__NR_SYSCALL_BASE+247)
-#define __NR_exit_group			(__NR_SYSCALL_BASE+248)
-#define __NR_lookup_dcookie		(__NR_SYSCALL_BASE+249)
-#define __NR_epoll_create		(__NR_SYSCALL_BASE+250)
-#define __NR_epoll_ctl			(__NR_SYSCALL_BASE+251)
-#define __NR_epoll_wait			(__NR_SYSCALL_BASE+252)
-#define __NR_remap_file_pages		(__NR_SYSCALL_BASE+253)
-					/* 254 for set_thread_area */
-					/* 255 for get_thread_area */
-#define __NR_set_tid_address		(__NR_SYSCALL_BASE+256)
-#define __NR_timer_create		(__NR_SYSCALL_BASE+257)
-#define __NR_timer_settime		(__NR_SYSCALL_BASE+258)
-#define __NR_timer_gettime		(__NR_SYSCALL_BASE+259)
-#define __NR_timer_getoverrun		(__NR_SYSCALL_BASE+260)
-#define __NR_timer_delete		(__NR_SYSCALL_BASE+261)
-#define __NR_clock_settime		(__NR_SYSCALL_BASE+262)
-#define __NR_clock_gettime		(__NR_SYSCALL_BASE+263)
-#define __NR_clock_getres		(__NR_SYSCALL_BASE+264)
-#define __NR_clock_nanosleep		(__NR_SYSCALL_BASE+265)
-#define __NR_statfs64			(__NR_SYSCALL_BASE+266)
-#define __NR_fstatfs64			(__NR_SYSCALL_BASE+267)
-#define __NR_tgkill			(__NR_SYSCALL_BASE+268)
-#define __NR_utimes			(__NR_SYSCALL_BASE+269)
-#define __NR_arm_fadvise64_64		(__NR_SYSCALL_BASE+270)
-#define __NR_pciconfig_iobase		(__NR_SYSCALL_BASE+271)
-#define __NR_pciconfig_read		(__NR_SYSCALL_BASE+272)
-#define __NR_pciconfig_write		(__NR_SYSCALL_BASE+273)
-#define __NR_mq_open			(__NR_SYSCALL_BASE+274)
-#define __NR_mq_unlink			(__NR_SYSCALL_BASE+275)
-#define __NR_mq_timedsend		(__NR_SYSCALL_BASE+276)
-#define __NR_mq_timedreceive		(__NR_SYSCALL_BASE+277)
-#define __NR_mq_notify			(__NR_SYSCALL_BASE+278)
-#define __NR_mq_getsetattr		(__NR_SYSCALL_BASE+279)
-#define __NR_waitid			(__NR_SYSCALL_BASE+280)
-#define __NR_socket			(__NR_SYSCALL_BASE+281)
-#define __NR_bind			(__NR_SYSCALL_BASE+282)
-#define __NR_connect			(__NR_SYSCALL_BASE+283)
-#define __NR_listen			(__NR_SYSCALL_BASE+284)
-#define __NR_accept			(__NR_SYSCALL_BASE+285)
-#define __NR_getsockname		(__NR_SYSCALL_BASE+286)
-#define __NR_getpeername		(__NR_SYSCALL_BASE+287)
-#define __NR_socketpair			(__NR_SYSCALL_BASE+288)
-#define __NR_send			(__NR_SYSCALL_BASE+289)
-#define __NR_sendto			(__NR_SYSCALL_BASE+290)
-#define __NR_recv			(__NR_SYSCALL_BASE+291)
-#define __NR_recvfrom			(__NR_SYSCALL_BASE+292)
-#define __NR_shutdown			(__NR_SYSCALL_BASE+293)
-#define __NR_setsockopt			(__NR_SYSCALL_BASE+294)
-#define __NR_getsockopt			(__NR_SYSCALL_BASE+295)
-#define __NR_sendmsg			(__NR_SYSCALL_BASE+296)
-#define __NR_recvmsg			(__NR_SYSCALL_BASE+297)
-#define __NR_semop			(__NR_SYSCALL_BASE+298)
-#define __NR_semget			(__NR_SYSCALL_BASE+299)
-#define __NR_semctl			(__NR_SYSCALL_BASE+300)
-#define __NR_msgsnd			(__NR_SYSCALL_BASE+301)
-#define __NR_msgrcv			(__NR_SYSCALL_BASE+302)
-#define __NR_msgget			(__NR_SYSCALL_BASE+303)
-#define __NR_msgctl			(__NR_SYSCALL_BASE+304)
-#define __NR_shmat			(__NR_SYSCALL_BASE+305)
-#define __NR_shmdt			(__NR_SYSCALL_BASE+306)
-#define __NR_shmget			(__NR_SYSCALL_BASE+307)
-#define __NR_shmctl			(__NR_SYSCALL_BASE+308)
-#define __NR_add_key			(__NR_SYSCALL_BASE+309)
-#define __NR_request_key		(__NR_SYSCALL_BASE+310)
-#define __NR_keyctl			(__NR_SYSCALL_BASE+311)
-#define __NR_semtimedop			(__NR_SYSCALL_BASE+312)
-#define __NR_vserver			(__NR_SYSCALL_BASE+313)
-#define __NR_ioprio_set			(__NR_SYSCALL_BASE+314)
-#define __NR_ioprio_get			(__NR_SYSCALL_BASE+315)
-#define __NR_inotify_init		(__NR_SYSCALL_BASE+316)
-#define __NR_inotify_add_watch		(__NR_SYSCALL_BASE+317)
-#define __NR_inotify_rm_watch		(__NR_SYSCALL_BASE+318)
-#define __NR_mbind			(__NR_SYSCALL_BASE+319)
-#define __NR_get_mempolicy		(__NR_SYSCALL_BASE+320)
-#define __NR_set_mempolicy		(__NR_SYSCALL_BASE+321)
-#define __NR_openat			(__NR_SYSCALL_BASE+322)
-#define __NR_mkdirat			(__NR_SYSCALL_BASE+323)
-#define __NR_mknodat			(__NR_SYSCALL_BASE+324)
-#define __NR_fchownat			(__NR_SYSCALL_BASE+325)
-#define __NR_futimesat			(__NR_SYSCALL_BASE+326)
-#define __NR_fstatat64			(__NR_SYSCALL_BASE+327)
-#define __NR_unlinkat			(__NR_SYSCALL_BASE+328)
-#define __NR_renameat			(__NR_SYSCALL_BASE+329)
-#define __NR_linkat			(__NR_SYSCALL_BASE+330)
-#define __NR_symlinkat			(__NR_SYSCALL_BASE+331)
-#define __NR_readlinkat			(__NR_SYSCALL_BASE+332)
-#define __NR_fchmodat			(__NR_SYSCALL_BASE+333)
-#define __NR_faccessat			(__NR_SYSCALL_BASE+334)
-#define __NR_pselect6			(__NR_SYSCALL_BASE+335)
-#define __NR_ppoll			(__NR_SYSCALL_BASE+336)
-#define __NR_unshare			(__NR_SYSCALL_BASE+337)
-#define __NR_set_robust_list		(__NR_SYSCALL_BASE+338)
-#define __NR_get_robust_list		(__NR_SYSCALL_BASE+339)
-#define __NR_splice			(__NR_SYSCALL_BASE+340)
-#define __NR_arm_sync_file_range	(__NR_SYSCALL_BASE+341)
+#include <asm/unistd-common.h>
 #define __NR_sync_file_range2		__NR_arm_sync_file_range
-#define __NR_tee			(__NR_SYSCALL_BASE+342)
-#define __NR_vmsplice			(__NR_SYSCALL_BASE+343)
-#define __NR_move_pages			(__NR_SYSCALL_BASE+344)
-#define __NR_getcpu			(__NR_SYSCALL_BASE+345)
-#define __NR_epoll_pwait		(__NR_SYSCALL_BASE+346)
-#define __NR_kexec_load			(__NR_SYSCALL_BASE+347)
-#define __NR_utimensat			(__NR_SYSCALL_BASE+348)
-#define __NR_signalfd			(__NR_SYSCALL_BASE+349)
-#define __NR_timerfd_create		(__NR_SYSCALL_BASE+350)
-#define __NR_eventfd			(__NR_SYSCALL_BASE+351)
-#define __NR_fallocate			(__NR_SYSCALL_BASE+352)
-#define __NR_timerfd_settime		(__NR_SYSCALL_BASE+353)
-#define __NR_timerfd_gettime		(__NR_SYSCALL_BASE+354)
-#define __NR_signalfd4			(__NR_SYSCALL_BASE+355)
-#define __NR_eventfd2			(__NR_SYSCALL_BASE+356)
-#define __NR_epoll_create1		(__NR_SYSCALL_BASE+357)
-#define __NR_dup3			(__NR_SYSCALL_BASE+358)
-#define __NR_pipe2			(__NR_SYSCALL_BASE+359)
-#define __NR_inotify_init1		(__NR_SYSCALL_BASE+360)
-#define __NR_preadv			(__NR_SYSCALL_BASE+361)
-#define __NR_pwritev			(__NR_SYSCALL_BASE+362)
-#define __NR_rt_tgsigqueueinfo		(__NR_SYSCALL_BASE+363)
-#define __NR_perf_event_open		(__NR_SYSCALL_BASE+364)
-#define __NR_recvmmsg			(__NR_SYSCALL_BASE+365)
-#define __NR_accept4			(__NR_SYSCALL_BASE+366)
-#define __NR_fanotify_init		(__NR_SYSCALL_BASE+367)
-#define __NR_fanotify_mark		(__NR_SYSCALL_BASE+368)
-#define __NR_prlimit64			(__NR_SYSCALL_BASE+369)
-#define __NR_name_to_handle_at		(__NR_SYSCALL_BASE+370)
-#define __NR_open_by_handle_at		(__NR_SYSCALL_BASE+371)
-#define __NR_clock_adjtime		(__NR_SYSCALL_BASE+372)
-#define __NR_syncfs			(__NR_SYSCALL_BASE+373)
-#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)
-#define __NR_kcmp			(__NR_SYSCALL_BASE+378)
-#define __NR_finit_module		(__NR_SYSCALL_BASE+379)
-#define __NR_sched_setattr		(__NR_SYSCALL_BASE+380)
-#define __NR_sched_getattr		(__NR_SYSCALL_BASE+381)
-#define __NR_renameat2			(__NR_SYSCALL_BASE+382)
-#define __NR_seccomp			(__NR_SYSCALL_BASE+383)
-#define __NR_getrandom			(__NR_SYSCALL_BASE+384)
-#define __NR_memfd_create		(__NR_SYSCALL_BASE+385)
-#define __NR_bpf			(__NR_SYSCALL_BASE+386)
-#define __NR_execveat			(__NR_SYSCALL_BASE+387)
-#define __NR_userfaultfd		(__NR_SYSCALL_BASE+388)
-#define __NR_membarrier			(__NR_SYSCALL_BASE+389)
-#define __NR_mlock2			(__NR_SYSCALL_BASE+390)
-#define __NR_copy_file_range		(__NR_SYSCALL_BASE+391)
-#define __NR_preadv2			(__NR_SYSCALL_BASE+392)
-#define __NR_pwritev2			(__NR_SYSCALL_BASE+393)
-#define __NR_pkey_mprotect		(__NR_SYSCALL_BASE+394)
-#define __NR_pkey_alloc			(__NR_SYSCALL_BASE+395)
-#define __NR_pkey_free			(__NR_SYSCALL_BASE+396)
 
 /*
  * The following SWIs are ARM private.
@@ -434,24 +36,4 @@
 #define __ARM_NR_usr32			(__ARM_NR_BASE+4)
 #define __ARM_NR_set_tls		(__ARM_NR_BASE+5)
 
-/*
- * The following syscalls are obsolete and no longer available for EABI.
- */
-#if !defined(__KERNEL__)
-#if defined(__ARM_EABI__)
-#undef __NR_time
-#undef __NR_umount
-#undef __NR_stime
-#undef __NR_alarm
-#undef __NR_utime
-#undef __NR_getrlimit
-#undef __NR_select
-#undef __NR_readdir
-#undef __NR_mmap
-#undef __NR_socketcall
-#undef __NR_syscall
-#undef __NR_ipc
-#endif
-#endif
-
 #endif /* _UAPI__ASM_ARM_UNISTD_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/Kconfig
--- linux-libre-4.9-gnu/arch/arm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -703,6 +703,7 @@ config ARCH_VIRT
 	select ARM_GIC
 	select ARM_GIC_V2M if PCI
 	select ARM_GIC_V3
+	select ARM_GIC_V3_ITS if PCI
 	select ARM_PSCI
 	select HAVE_ARM_ARCH_TIMER
 
@@ -887,6 +888,11 @@ config MACH_STM32F429
 	depends on ARCH_STM32
 	default y
 
+config MACH_STM32F746
+	bool "STMicrolectronics STM32F746"
+	depends on ARCH_STM32
+	default y
+
 config ARCH_MPS2
 	bool "ARM MPS2 platform"
 	depends on ARM_SINGLE_ARMV7M
@@ -1496,8 +1502,7 @@ source kernel/Kconfig.preempt
 
 config HZ_FIXED
 	int
-	default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \
-		ARCH_S5PV210 || ARCH_EXYNOS4
+	default 200 if ARCH_EBSA110
 	default 128 if SOC_AT91RM9200
 	default 0
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/calls.S linux-libre-4.10-rc8-gnu/arch/arm/kernel/calls.S
--- linux-libre-4.9-gnu/arch/arm/kernel/calls.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/calls.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,415 +0,0 @@
-/*
- *  linux/arch/arm/kernel/calls.S
- *
- *  Copyright (C) 1995-2005 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 file is included thrice in entry-common.S
- */
-/* 0 */		CALL(sys_restart_syscall)
-		CALL(sys_exit)
-		CALL(sys_fork)
-		CALL(sys_read)
-		CALL(sys_write)
-/* 5 */		CALL(sys_open)
-		CALL(sys_close)
-		CALL(sys_ni_syscall)		/* was sys_waitpid */
-		CALL(sys_creat)
-		CALL(sys_link)
-/* 10 */	CALL(sys_unlink)
-		CALL(sys_execve)
-		CALL(sys_chdir)
-		CALL(OBSOLETE(sys_time))	/* used by libc4 */
-		CALL(sys_mknod)
-/* 15 */	CALL(sys_chmod)
-		CALL(sys_lchown16)
-		CALL(sys_ni_syscall)		/* was sys_break */
-		CALL(sys_ni_syscall)		/* was sys_stat */
-		CALL(sys_lseek)
-/* 20 */	CALL(sys_getpid)
-		CALL(sys_mount)
-		CALL(OBSOLETE(sys_oldumount))	/* used by libc4 */
-		CALL(sys_setuid16)
-		CALL(sys_getuid16)
-/* 25 */	CALL(OBSOLETE(sys_stime))
-		CALL(sys_ptrace)
-		CALL(OBSOLETE(sys_alarm))	/* used by libc4 */
-		CALL(sys_ni_syscall)		/* was sys_fstat */
-		CALL(sys_pause)
-/* 30 */	CALL(OBSOLETE(sys_utime))	/* used by libc4 */
-		CALL(sys_ni_syscall)		/* was sys_stty */
-		CALL(sys_ni_syscall)		/* was sys_getty */
-		CALL(sys_access)
-		CALL(sys_nice)
-/* 35 */	CALL(sys_ni_syscall)		/* was sys_ftime */
-		CALL(sys_sync)
-		CALL(sys_kill)
-		CALL(sys_rename)
-		CALL(sys_mkdir)
-/* 40 */	CALL(sys_rmdir)
-		CALL(sys_dup)
-		CALL(sys_pipe)
-		CALL(sys_times)
-		CALL(sys_ni_syscall)		/* was sys_prof */
-/* 45 */	CALL(sys_brk)
-		CALL(sys_setgid16)
-		CALL(sys_getgid16)
-		CALL(sys_ni_syscall)		/* was sys_signal */
-		CALL(sys_geteuid16)
-/* 50 */	CALL(sys_getegid16)
-		CALL(sys_acct)
-		CALL(sys_umount)
-		CALL(sys_ni_syscall)		/* was sys_lock */
-		CALL(sys_ioctl)
-/* 55 */	CALL(sys_fcntl)
-		CALL(sys_ni_syscall)		/* was sys_mpx */
-		CALL(sys_setpgid)
-		CALL(sys_ni_syscall)		/* was sys_ulimit */
-		CALL(sys_ni_syscall)		/* was sys_olduname */
-/* 60 */	CALL(sys_umask)
-		CALL(sys_chroot)
-		CALL(sys_ustat)
-		CALL(sys_dup2)
-		CALL(sys_getppid)
-/* 65 */	CALL(sys_getpgrp)
-		CALL(sys_setsid)
-		CALL(sys_sigaction)
-		CALL(sys_ni_syscall)		/* was sys_sgetmask */
-		CALL(sys_ni_syscall)		/* was sys_ssetmask */
-/* 70 */	CALL(sys_setreuid16)
-		CALL(sys_setregid16)
-		CALL(sys_sigsuspend)
-		CALL(sys_sigpending)
-		CALL(sys_sethostname)
-/* 75 */	CALL(sys_setrlimit)
-		CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */
-		CALL(sys_getrusage)
-		CALL(sys_gettimeofday)
-		CALL(sys_settimeofday)
-/* 80 */	CALL(sys_getgroups16)
-		CALL(sys_setgroups16)
-		CALL(OBSOLETE(sys_old_select))	/* used by libc4 */
-		CALL(sys_symlink)
-		CALL(sys_ni_syscall)		/* was sys_lstat */
-/* 85 */	CALL(sys_readlink)
-		CALL(sys_uselib)
-		CALL(sys_swapon)
-		CALL(sys_reboot)
-		CALL(OBSOLETE(sys_old_readdir))	/* used by libc4 */
-/* 90 */	CALL(OBSOLETE(sys_old_mmap))	/* used by libc4 */
-		CALL(sys_munmap)
-		CALL(sys_truncate)
-		CALL(sys_ftruncate)
-		CALL(sys_fchmod)
-/* 95 */	CALL(sys_fchown16)
-		CALL(sys_getpriority)
-		CALL(sys_setpriority)
-		CALL(sys_ni_syscall)		/* was sys_profil */
-		CALL(sys_statfs)
-/* 100 */	CALL(sys_fstatfs)
-		CALL(sys_ni_syscall)		/* sys_ioperm */
-		CALL(OBSOLETE(ABI(sys_socketcall, sys_oabi_socketcall)))
-		CALL(sys_syslog)
-		CALL(sys_setitimer)
-/* 105 */	CALL(sys_getitimer)
-		CALL(sys_newstat)
-		CALL(sys_newlstat)
-		CALL(sys_newfstat)
-		CALL(sys_ni_syscall)		/* was sys_uname */
-/* 110 */	CALL(sys_ni_syscall)		/* was sys_iopl */
-		CALL(sys_vhangup)
-		CALL(sys_ni_syscall)
-		CALL(OBSOLETE(sys_syscall))	/* call a syscall */
-		CALL(sys_wait4)
-/* 115 */	CALL(sys_swapoff)
-		CALL(sys_sysinfo)
-		CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
-		CALL(sys_fsync)
-		CALL(sys_sigreturn_wrapper)
-/* 120 */	CALL(sys_clone)
-		CALL(sys_setdomainname)
-		CALL(sys_newuname)
-		CALL(sys_ni_syscall)		/* modify_ldt */
-		CALL(sys_adjtimex)
-/* 125 */	CALL(sys_mprotect)
-		CALL(sys_sigprocmask)
-		CALL(sys_ni_syscall)		/* was sys_create_module */
-		CALL(sys_init_module)
-		CALL(sys_delete_module)
-/* 130 */	CALL(sys_ni_syscall)		/* was sys_get_kernel_syms */
-		CALL(sys_quotactl)
-		CALL(sys_getpgid)
-		CALL(sys_fchdir)
-		CALL(sys_bdflush)
-/* 135 */	CALL(sys_sysfs)
-		CALL(sys_personality)
-		CALL(sys_ni_syscall)		/* reserved for afs_syscall */
-		CALL(sys_setfsuid16)
-		CALL(sys_setfsgid16)
-/* 140 */	CALL(sys_llseek)
-		CALL(sys_getdents)
-		CALL(sys_select)
-		CALL(sys_flock)
-		CALL(sys_msync)
-/* 145 */	CALL(sys_readv)
-		CALL(sys_writev)
-		CALL(sys_getsid)
-		CALL(sys_fdatasync)
-		CALL(sys_sysctl)
-/* 150 */	CALL(sys_mlock)
-		CALL(sys_munlock)
-		CALL(sys_mlockall)
-		CALL(sys_munlockall)
-		CALL(sys_sched_setparam)
-/* 155 */	CALL(sys_sched_getparam)
-		CALL(sys_sched_setscheduler)
-		CALL(sys_sched_getscheduler)
-		CALL(sys_sched_yield)
-		CALL(sys_sched_get_priority_max)
-/* 160 */	CALL(sys_sched_get_priority_min)
-		CALL(sys_sched_rr_get_interval)
-		CALL(sys_nanosleep)
-		CALL(sys_mremap)
-		CALL(sys_setresuid16)
-/* 165 */	CALL(sys_getresuid16)
-		CALL(sys_ni_syscall)		/* vm86 */
-		CALL(sys_ni_syscall)		/* was sys_query_module */
-		CALL(sys_poll)
-		CALL(sys_ni_syscall)		/* was nfsservctl */
-/* 170 */	CALL(sys_setresgid16)
-		CALL(sys_getresgid16)
-		CALL(sys_prctl)
-		CALL(sys_rt_sigreturn_wrapper)
-		CALL(sys_rt_sigaction)
-/* 175 */	CALL(sys_rt_sigprocmask)
-		CALL(sys_rt_sigpending)
-		CALL(sys_rt_sigtimedwait)
-		CALL(sys_rt_sigqueueinfo)
-		CALL(sys_rt_sigsuspend)
-/* 180 */	CALL(ABI(sys_pread64, sys_oabi_pread64))
-		CALL(ABI(sys_pwrite64, sys_oabi_pwrite64))
-		CALL(sys_chown16)
-		CALL(sys_getcwd)
-		CALL(sys_capget)
-/* 185 */	CALL(sys_capset)
-		CALL(sys_sigaltstack)
-		CALL(sys_sendfile)
-		CALL(sys_ni_syscall)		/* getpmsg */
-		CALL(sys_ni_syscall)		/* putpmsg */
-/* 190 */	CALL(sys_vfork)
-		CALL(sys_getrlimit)
-		CALL(sys_mmap2)
-		CALL(ABI(sys_truncate64, sys_oabi_truncate64))
-		CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64))
-/* 195 */	CALL(ABI(sys_stat64, sys_oabi_stat64))
-		CALL(ABI(sys_lstat64, sys_oabi_lstat64))
-		CALL(ABI(sys_fstat64, sys_oabi_fstat64))
-		CALL(sys_lchown)
-		CALL(sys_getuid)
-/* 200 */	CALL(sys_getgid)
-		CALL(sys_geteuid)
-		CALL(sys_getegid)
-		CALL(sys_setreuid)
-		CALL(sys_setregid)
-/* 205 */	CALL(sys_getgroups)
-		CALL(sys_setgroups)
-		CALL(sys_fchown)
-		CALL(sys_setresuid)
-		CALL(sys_getresuid)
-/* 210 */	CALL(sys_setresgid)
-		CALL(sys_getresgid)
-		CALL(sys_chown)
-		CALL(sys_setuid)
-		CALL(sys_setgid)
-/* 215 */	CALL(sys_setfsuid)
-		CALL(sys_setfsgid)
-		CALL(sys_getdents64)
-		CALL(sys_pivot_root)
-		CALL(sys_mincore)
-/* 220 */	CALL(sys_madvise)
-		CALL(ABI(sys_fcntl64, sys_oabi_fcntl64))
-		CALL(sys_ni_syscall) /* TUX */
-		CALL(sys_ni_syscall)
-		CALL(sys_gettid)
-/* 225 */	CALL(ABI(sys_readahead, sys_oabi_readahead))
-		CALL(sys_setxattr)
-		CALL(sys_lsetxattr)
-		CALL(sys_fsetxattr)
-		CALL(sys_getxattr)
-/* 230 */	CALL(sys_lgetxattr)
-		CALL(sys_fgetxattr)
-		CALL(sys_listxattr)
-		CALL(sys_llistxattr)
-		CALL(sys_flistxattr)
-/* 235 */	CALL(sys_removexattr)
-		CALL(sys_lremovexattr)
-		CALL(sys_fremovexattr)
-		CALL(sys_tkill)
-		CALL(sys_sendfile64)
-/* 240 */	CALL(sys_futex)
-		CALL(sys_sched_setaffinity)
-		CALL(sys_sched_getaffinity)
-		CALL(sys_io_setup)
-		CALL(sys_io_destroy)
-/* 245 */	CALL(sys_io_getevents)
-		CALL(sys_io_submit)
-		CALL(sys_io_cancel)
-		CALL(sys_exit_group)
-		CALL(sys_lookup_dcookie)
-/* 250 */	CALL(sys_epoll_create)
-		CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl))
-		CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait))
-		CALL(sys_remap_file_pages)
-		CALL(sys_ni_syscall)	/* sys_set_thread_area */
-/* 255 */	CALL(sys_ni_syscall)	/* sys_get_thread_area */
-		CALL(sys_set_tid_address)
-		CALL(sys_timer_create)
-		CALL(sys_timer_settime)
-		CALL(sys_timer_gettime)
-/* 260 */	CALL(sys_timer_getoverrun)
-		CALL(sys_timer_delete)
-		CALL(sys_clock_settime)
-		CALL(sys_clock_gettime)
-		CALL(sys_clock_getres)
-/* 265 */	CALL(sys_clock_nanosleep)
-		CALL(sys_statfs64_wrapper)
-		CALL(sys_fstatfs64_wrapper)
-		CALL(sys_tgkill)
-		CALL(sys_utimes)
-/* 270 */	CALL(sys_arm_fadvise64_64)
-		CALL(sys_pciconfig_iobase)
-		CALL(sys_pciconfig_read)
-		CALL(sys_pciconfig_write)
-		CALL(sys_mq_open)
-/* 275 */	CALL(sys_mq_unlink)
-		CALL(sys_mq_timedsend)
-		CALL(sys_mq_timedreceive)
-		CALL(sys_mq_notify)
-		CALL(sys_mq_getsetattr)
-/* 280 */	CALL(sys_waitid)
-		CALL(sys_socket)
-		CALL(ABI(sys_bind, sys_oabi_bind))
-		CALL(ABI(sys_connect, sys_oabi_connect))
-		CALL(sys_listen)
-/* 285 */	CALL(sys_accept)
-		CALL(sys_getsockname)
-		CALL(sys_getpeername)
-		CALL(sys_socketpair)
-		CALL(sys_send)
-/* 290 */	CALL(ABI(sys_sendto, sys_oabi_sendto))
-		CALL(sys_recv)
-		CALL(sys_recvfrom)
-		CALL(sys_shutdown)
-		CALL(sys_setsockopt)
-/* 295 */	CALL(sys_getsockopt)
-		CALL(ABI(sys_sendmsg, sys_oabi_sendmsg))
-		CALL(sys_recvmsg)
-		CALL(ABI(sys_semop, sys_oabi_semop))
-		CALL(sys_semget)
-/* 300 */	CALL(sys_semctl)
-		CALL(sys_msgsnd)
-		CALL(sys_msgrcv)
-		CALL(sys_msgget)
-		CALL(sys_msgctl)
-/* 305 */	CALL(sys_shmat)
-		CALL(sys_shmdt)
-		CALL(sys_shmget)
-		CALL(sys_shmctl)
-		CALL(sys_add_key)
-/* 310 */	CALL(sys_request_key)
-		CALL(sys_keyctl)
-		CALL(ABI(sys_semtimedop, sys_oabi_semtimedop))
-/* vserver */	CALL(sys_ni_syscall)
-		CALL(sys_ioprio_set)
-/* 315 */	CALL(sys_ioprio_get)
-		CALL(sys_inotify_init)
-		CALL(sys_inotify_add_watch)
-		CALL(sys_inotify_rm_watch)
-		CALL(sys_mbind)
-/* 320 */	CALL(sys_get_mempolicy)
-		CALL(sys_set_mempolicy)
-		CALL(sys_openat)
-		CALL(sys_mkdirat)
-		CALL(sys_mknodat)
-/* 325 */	CALL(sys_fchownat)
-		CALL(sys_futimesat)
-		CALL(ABI(sys_fstatat64,  sys_oabi_fstatat64))
-		CALL(sys_unlinkat)
-		CALL(sys_renameat)
-/* 330 */	CALL(sys_linkat)
-		CALL(sys_symlinkat)
-		CALL(sys_readlinkat)
-		CALL(sys_fchmodat)
-		CALL(sys_faccessat)
-/* 335 */	CALL(sys_pselect6)
-		CALL(sys_ppoll)
-		CALL(sys_unshare)
-		CALL(sys_set_robust_list)
-		CALL(sys_get_robust_list)
-/* 340 */	CALL(sys_splice)
-		CALL(sys_sync_file_range2)
-		CALL(sys_tee)
-		CALL(sys_vmsplice)
-		CALL(sys_move_pages)
-/* 345 */	CALL(sys_getcpu)
-		CALL(sys_epoll_pwait)
-		CALL(sys_kexec_load)
-		CALL(sys_utimensat)
-		CALL(sys_signalfd)
-/* 350 */	CALL(sys_timerfd_create)
-		CALL(sys_eventfd)
-		CALL(sys_fallocate)
-		CALL(sys_timerfd_settime)
-		CALL(sys_timerfd_gettime)
-/* 355 */	CALL(sys_signalfd4)
-		CALL(sys_eventfd2)
-		CALL(sys_epoll_create1)
-		CALL(sys_dup3)
-		CALL(sys_pipe2)
-/* 360 */	CALL(sys_inotify_init1)
-		CALL(sys_preadv)
-		CALL(sys_pwritev)
-		CALL(sys_rt_tgsigqueueinfo)
-		CALL(sys_perf_event_open)
-/* 365 */	CALL(sys_recvmmsg)
-		CALL(sys_accept4)
-		CALL(sys_fanotify_init)
-		CALL(sys_fanotify_mark)
-		CALL(sys_prlimit64)
-/* 370 */	CALL(sys_name_to_handle_at)
-		CALL(sys_open_by_handle_at)
-		CALL(sys_clock_adjtime)
-		CALL(sys_syncfs)
-		CALL(sys_sendmmsg)
-/* 375 */	CALL(sys_setns)
-		CALL(sys_process_vm_readv)
-		CALL(sys_process_vm_writev)
-		CALL(sys_kcmp)
-		CALL(sys_finit_module)
-/* 380 */	CALL(sys_sched_setattr)
-		CALL(sys_sched_getattr)
-		CALL(sys_renameat2)
-		CALL(sys_seccomp)
-		CALL(sys_getrandom)
-/* 385 */	CALL(sys_memfd_create)
-		CALL(sys_bpf)
-		CALL(sys_execveat)
-		CALL(sys_userfaultfd)
-		CALL(sys_membarrier)
-/* 390 */	CALL(sys_mlock2)
-		CALL(sys_copy_file_range)
-		CALL(sys_preadv2)
-		CALL(sys_pwritev2)
-		CALL(sys_pkey_mprotect)
-/* 395 */	CALL(sys_pkey_alloc)
-		CALL(sys_pkey_free)
-#ifndef syscalls_counted
-.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
-#define syscalls_counted
-#endif
-.rept syscalls_padding
-		CALL(sys_ni_syscall)
-.endr
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/entry-common.S linux-libre-4.10-rc8-gnu/arch/arm/kernel/entry-common.S
--- linux-libre-4.9-gnu/arch/arm/kernel/entry-common.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/entry-common.S	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,11 @@
 #include <asm/unistd.h>
 #include <asm/ftrace.h>
 #include <asm/unwind.h>
+#ifdef CONFIG_AEABI
+#include <asm/unistd-oabi.h>
+#endif
+
+	.equ	NR_syscalls, __NR_syscalls
 
 #ifdef CONFIG_NEED_RET_TO_USER
 #include <mach/entry-macro.S>
@@ -120,21 +125,6 @@ ENTRY(ret_from_fork)
 	b	ret_slow_syscall
 ENDPROC(ret_from_fork)
 
-	.equ NR_syscalls,0
-#define CALL(x) .equ NR_syscalls,NR_syscalls+1
-#include "calls.S"
-
-/*
- * Ensure that the system call table is equal to __NR_syscalls,
- * which is the value the rest of the system sees
- */
-.ifne NR_syscalls - __NR_syscalls
-.error "__NR_syscalls is not equal to the size of the syscall table"
-.endif
-
-#undef CALL
-#define CALL(x) .long x
-
 /*=============================================================================
  * SWI handler
  *-----------------------------------------------------------------------------
@@ -291,22 +281,48 @@ __cr_alignment:
 #endif
 	.ltorg
 
+	.macro	syscall_table_start, sym
+	.equ	__sys_nr, 0
+	.type	\sym, #object
+ENTRY(\sym)
+	.endm
+
+	.macro	syscall, nr, func
+	.ifgt	__sys_nr - \nr
+	.error	"Duplicated/unorded system call entry"
+	.endif
+	.rept	\nr - __sys_nr
+	.long	sys_ni_syscall
+	.endr
+	.long	\func
+	.equ	__sys_nr, \nr + 1
+	.endm
+
+	.macro	syscall_table_end, sym
+	.ifgt	__sys_nr - __NR_syscalls
+	.error	"System call table too big"
+	.endif
+	.rept	__NR_syscalls - __sys_nr
+	.long	sys_ni_syscall
+	.endr
+	.size	\sym, . - \sym
+	.endm
+
+#define NATIVE(nr, func) syscall nr, func
+
 /*
  * This is the syscall table declaration for native ABI syscalls.
  * With EABI a couple syscalls are obsolete and defined as sys_ni_syscall.
  */
-#define ABI(native, compat) native
+	syscall_table_start sys_call_table
+#define COMPAT(nr, native, compat) syscall nr, native
 #ifdef CONFIG_AEABI
-#define OBSOLETE(syscall) sys_ni_syscall
+#include <calls-eabi.S>
 #else
-#define OBSOLETE(syscall) syscall
+#include <calls-oabi.S>
 #endif
-
-	.type	sys_call_table, #object
-ENTRY(sys_call_table)
-#include "calls.S"
-#undef ABI
-#undef OBSOLETE
+#undef COMPAT
+	syscall_table_end sys_call_table
 
 /*============================================================================
  * Special system call wrappers
@@ -407,14 +423,10 @@ ENDPROC(sys_oabi_readahead)
  * Let's declare a second syscall table for old ABI binaries
  * using the compatibility syscall entries.
  */
-#define ABI(native, compat) compat
-#define OBSOLETE(syscall) syscall
-
-	.type	sys_oabi_call_table, #object
-ENTRY(sys_oabi_call_table)
-#include "calls.S"
-#undef ABI
-#undef OBSOLETE
+	syscall_table_start sys_oabi_call_table
+#define COMPAT(nr, native, compat) syscall nr, compat
+#include <calls-oabi.S>
+	syscall_table_end sys_oabi_call_table
 
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/hw_breakpoint.c linux-libre-4.10-rc8-gnu/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-4.9-gnu/arch/arm/kernel/hw_breakpoint.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/hw_breakpoint.c	2017-02-12 16:03:20.000000000 -0500
@@ -925,9 +925,9 @@ static bool core_has_os_save_restore(voi
 	}
 }
 
-static void reset_ctrl_regs(void *unused)
+static void reset_ctrl_regs(unsigned int cpu)
 {
-	int i, raw_num_brps, err = 0, cpu = smp_processor_id();
+	int i, raw_num_brps, err = 0;
 	u32 val;
 
 	/*
@@ -1020,25 +1020,20 @@ out_mdbgen:
 		cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
 }
 
-static int dbg_reset_notify(struct notifier_block *self,
-				      unsigned long action, void *cpu)
+static int dbg_reset_online(unsigned int cpu)
 {
-	if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
-		smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
-
-	return NOTIFY_OK;
+	local_irq_disable();
+	reset_ctrl_regs(cpu);
+	local_irq_enable();
+	return 0;
 }
 
-static struct notifier_block dbg_reset_nb = {
-	.notifier_call = dbg_reset_notify,
-};
-
 #ifdef CONFIG_CPU_PM
 static int dbg_cpu_pm_notify(struct notifier_block *self, unsigned long action,
 			     void *v)
 {
 	if (action == CPU_PM_EXIT)
-		reset_ctrl_regs(NULL);
+		reset_ctrl_regs(smp_processor_id());
 
 	return NOTIFY_OK;
 }
@@ -1059,6 +1054,8 @@ static inline void pm_init(void)
 
 static int __init arch_hw_breakpoint_init(void)
 {
+	int ret;
+
 	debug_arch = get_debug_arch();
 
 	if (!debug_arch_supported()) {
@@ -1066,31 +1063,50 @@ static int __init arch_hw_breakpoint_ini
 		return 0;
 	}
 
+	/*
+	 * Scorpion CPUs (at least those in APQ8060) seem to set DBGPRSR.SPD
+	 * whenever a WFI is issued, even if the core is not powered down, in
+	 * violation of the architecture.  When DBGPRSR.SPD is set, accesses to
+	 * breakpoint and watchpoint registers are treated as undefined, so
+	 * this results in boot time and runtime failures when these are
+	 * accessed and we unexpectedly take a trap.
+	 *
+	 * It's not clear if/how this can be worked around, so we blacklist
+	 * Scorpion CPUs to avoid these issues.
+	*/
+	if (read_cpuid_part() == ARM_CPU_PART_SCORPION) {
+		pr_info("Scorpion CPU detected. Hardware breakpoints and watchpoints disabled\n");
+		return 0;
+	}
+
 	has_ossr = core_has_os_save_restore();
 
 	/* Determine how many BRPs/WRPs are available. */
 	core_num_brps = get_num_brps();
 	core_num_wrps = get_num_wrps();
 
-	cpu_notifier_register_begin();
-
 	/*
 	 * 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.
 	 */
+	get_online_cpus();
 	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.
+	 * Register CPU notifier which resets 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, NULL, 1);
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm/hw_breakpoint:online",
+				dbg_reset_online, NULL);
 	unregister_undef_hook(&debug_reg_hook);
-	if (!cpumask_empty(&debug_err_mask)) {
+	if (WARN_ON(ret < 0) || !cpumask_empty(&debug_err_mask)) {
 		core_num_brps = 0;
 		core_num_wrps = 0;
-		cpu_notifier_register_done();
+		if (ret > 0)
+			cpuhp_remove_state_nocalls(ret);
+		put_online_cpus();
 		return 0;
 	}
 
@@ -1108,12 +1124,9 @@ static int __init arch_hw_breakpoint_ini
 			TRAP_HWBKPT, "watchpoint debug exception");
 	hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
 			TRAP_HWBKPT, "breakpoint debug exception");
+	put_online_cpus();
 
-	/* Register hotplug and PM notifiers. */
-	__register_cpu_notifier(&dbg_reset_nb);
-
-	cpu_notifier_register_done();
-
+	/* Register PM notifiers. */
 	pm_init();
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/arm/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/arm/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -600,7 +600,7 @@ static int gpr_set(struct task_struct *t
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct pt_regs newregs;
+	struct pt_regs newregs = *task_pt_regs(target);
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 &newregs,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/smp_tlb.c linux-libre-4.10-rc8-gnu/arch/arm/kernel/smp_tlb.c
--- linux-libre-4.9-gnu/arch/arm/kernel/smp_tlb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/smp_tlb.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,7 @@
  */
 #include <linux/preempt.h>
 #include <linux/smp.h>
+#include <linux/uaccess.h>
 
 #include <asm/smp_plat.h>
 #include <asm/tlbflush.h>
@@ -40,8 +41,11 @@ static inline void ipi_flush_tlb_mm(void
 static inline void ipi_flush_tlb_page(void *arg)
 {
 	struct tlb_args *ta = (struct tlb_args *)arg;
+	unsigned int __ua_flags = uaccess_save_and_enable();
 
 	local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+
+	uaccess_restore(__ua_flags);
 }
 
 static inline void ipi_flush_tlb_kernel_page(void *arg)
@@ -54,8 +58,11 @@ static inline void ipi_flush_tlb_kernel_
 static inline void ipi_flush_tlb_range(void *arg)
 {
 	struct tlb_args *ta = (struct tlb_args *)arg;
+	unsigned int __ua_flags = uaccess_save_and_enable();
 
 	local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+
+	uaccess_restore(__ua_flags);
 }
 
 static inline void ipi_flush_tlb_kernel_range(void *arg)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/smp_twd.c linux-libre-4.10-rc8-gnu/arch/arm/kernel/smp_twd.c
--- linux-libre-4.9-gnu/arch/arm/kernel/smp_twd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/smp_twd.c	2017-02-12 16:03:20.000000000 -0500
@@ -339,7 +339,7 @@ static int __init twd_local_timer_common
 	}
 
 	cpuhp_setup_state_nocalls(CPUHP_AP_ARM_TWD_STARTING,
-				  "AP_ARM_TWD_STARTING",
+				  "arm/timer/twd:starting",
 				  twd_timer_starting_cpu, twd_timer_dying_cpu);
 
 	twd_get_clock(np);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/swp_emulate.c linux-libre-4.10-rc8-gnu/arch/arm/kernel/swp_emulate.c
--- linux-libre-4.9-gnu/arch/arm/kernel/swp_emulate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/swp_emulate.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/opcodes.h>
 #include <asm/system_info.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * Error-checking SWP macros implemented using ldrex{b}/strex{b}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kernel/topology.c linux-libre-4.10-rc8-gnu/arch/arm/kernel/topology.c
--- linux-libre-4.9-gnu/arch/arm/kernel/topology.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kernel/topology.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@
  */
 
 #include <linux/cpu.h>
+#include <linux/cpufreq.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
 #include <linux/init.h>
@@ -21,7 +22,9 @@
 #include <linux/of.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
@@ -41,6 +44,7 @@
  * updated during this sequence.
  */
 static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
+static DEFINE_MUTEX(cpu_scale_mutex);
 
 unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
 {
@@ -52,6 +56,65 @@ static void set_capacity_scale(unsigned
 	per_cpu(cpu_scale, cpu) = capacity;
 }
 
+#ifdef CONFIG_PROC_SYSCTL
+static ssize_t cpu_capacity_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+
+	return sprintf(buf, "%lu\n",
+			arch_scale_cpu_capacity(NULL, cpu->dev.id));
+}
+
+static ssize_t cpu_capacity_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf,
+				  size_t count)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+	int this_cpu = cpu->dev.id, i;
+	unsigned long new_capacity;
+	ssize_t ret;
+
+	if (count) {
+		ret = kstrtoul(buf, 0, &new_capacity);
+		if (ret)
+			return ret;
+		if (new_capacity > SCHED_CAPACITY_SCALE)
+			return -EINVAL;
+
+		mutex_lock(&cpu_scale_mutex);
+		for_each_cpu(i, &cpu_topology[this_cpu].core_sibling)
+			set_capacity_scale(i, new_capacity);
+		mutex_unlock(&cpu_scale_mutex);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(cpu_capacity);
+
+static int register_cpu_capacity_sysctl(void)
+{
+	int i;
+	struct device *cpu;
+
+	for_each_possible_cpu(i) {
+		cpu = get_cpu_device(i);
+		if (!cpu) {
+			pr_err("%s: too early to get CPU%d device!\n",
+			       __func__, i);
+			continue;
+		}
+		device_create_file(cpu, &dev_attr_cpu_capacity);
+	}
+
+	return 0;
+}
+subsys_initcall(register_cpu_capacity_sysctl);
+#endif
+
 #ifdef CONFIG_OF
 struct cpu_efficiency {
 	const char *compatible;
@@ -78,6 +141,146 @@ static unsigned long *__cpu_capacity;
 #define cpu_capacity(cpu)	__cpu_capacity[cpu]
 
 static unsigned long middle_capacity = 1;
+static bool cap_from_dt = true;
+static u32 *raw_capacity;
+static bool cap_parsing_failed;
+static u32 capacity_scale;
+
+static int __init parse_cpu_capacity(struct device_node *cpu_node, int cpu)
+{
+	int ret = 1;
+	u32 cpu_capacity;
+
+	if (cap_parsing_failed)
+		return !ret;
+
+	ret = of_property_read_u32(cpu_node,
+				   "capacity-dmips-mhz",
+				   &cpu_capacity);
+	if (!ret) {
+		if (!raw_capacity) {
+			raw_capacity = kcalloc(num_possible_cpus(),
+					       sizeof(*raw_capacity),
+					       GFP_KERNEL);
+			if (!raw_capacity) {
+				pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
+				cap_parsing_failed = true;
+				return !ret;
+			}
+		}
+		capacity_scale = max(cpu_capacity, capacity_scale);
+		raw_capacity[cpu] = cpu_capacity;
+		pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n",
+			cpu_node->full_name, raw_capacity[cpu]);
+	} else {
+		if (raw_capacity) {
+			pr_err("cpu_capacity: missing %s raw capacity\n",
+				cpu_node->full_name);
+			pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n");
+		}
+		cap_parsing_failed = true;
+		kfree(raw_capacity);
+	}
+
+	return !ret;
+}
+
+static void normalize_cpu_capacity(void)
+{
+	u64 capacity;
+	int cpu;
+
+	if (!raw_capacity || cap_parsing_failed)
+		return;
+
+	pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale);
+	mutex_lock(&cpu_scale_mutex);
+	for_each_possible_cpu(cpu) {
+		capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT)
+			/ capacity_scale;
+		set_capacity_scale(cpu, capacity);
+		pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n",
+			cpu, arch_scale_cpu_capacity(NULL, cpu));
+	}
+	mutex_unlock(&cpu_scale_mutex);
+}
+
+#ifdef CONFIG_CPU_FREQ
+static cpumask_var_t cpus_to_visit;
+static bool cap_parsing_done;
+static void parsing_done_workfn(struct work_struct *work);
+static DECLARE_WORK(parsing_done_work, parsing_done_workfn);
+
+static int
+init_cpu_capacity_callback(struct notifier_block *nb,
+			   unsigned long val,
+			   void *data)
+{
+	struct cpufreq_policy *policy = data;
+	int cpu;
+
+	if (cap_parsing_failed || cap_parsing_done)
+		return 0;
+
+	switch (val) {
+	case CPUFREQ_NOTIFY:
+		pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n",
+				cpumask_pr_args(policy->related_cpus),
+				cpumask_pr_args(cpus_to_visit));
+		cpumask_andnot(cpus_to_visit,
+			       cpus_to_visit,
+			       policy->related_cpus);
+		for_each_cpu(cpu, policy->related_cpus) {
+			raw_capacity[cpu] = arch_scale_cpu_capacity(NULL, cpu) *
+					    policy->cpuinfo.max_freq / 1000UL;
+			capacity_scale = max(raw_capacity[cpu], capacity_scale);
+		}
+		if (cpumask_empty(cpus_to_visit)) {
+			normalize_cpu_capacity();
+			kfree(raw_capacity);
+			pr_debug("cpu_capacity: parsing done\n");
+			cap_parsing_done = true;
+			schedule_work(&parsing_done_work);
+		}
+	}
+	return 0;
+}
+
+static struct notifier_block init_cpu_capacity_notifier = {
+	.notifier_call = init_cpu_capacity_callback,
+};
+
+static int __init register_cpufreq_notifier(void)
+{
+	if (cap_parsing_failed)
+		return -EINVAL;
+
+	if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) {
+		pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n");
+		return -ENOMEM;
+	}
+	cpumask_copy(cpus_to_visit, cpu_possible_mask);
+
+	return cpufreq_register_notifier(&init_cpu_capacity_notifier,
+					 CPUFREQ_POLICY_NOTIFIER);
+}
+core_initcall(register_cpufreq_notifier);
+
+static void parsing_done_workfn(struct work_struct *work)
+{
+	cpufreq_unregister_notifier(&init_cpu_capacity_notifier,
+					 CPUFREQ_POLICY_NOTIFIER);
+}
+
+#else
+static int __init free_raw_capacity(void)
+{
+	kfree(raw_capacity);
+
+	return 0;
+}
+core_initcall(free_raw_capacity);
+#endif
 
 /*
  * Iterate all CPUs' descriptor in DT and compute the efficiency
@@ -99,6 +302,12 @@ static void __init parse_dt_topology(voi
 	__cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity),
 				 GFP_NOWAIT);
 
+	cn = of_find_node_by_path("/cpus");
+	if (!cn) {
+		pr_err("No CPU information found in DT\n");
+		return;
+	}
+
 	for_each_possible_cpu(cpu) {
 		const u32 *rate;
 		int len;
@@ -110,6 +319,13 @@ static void __init parse_dt_topology(voi
 			continue;
 		}
 
+		if (parse_cpu_capacity(cn, cpu)) {
+			of_node_put(cn);
+			continue;
+		}
+
+		cap_from_dt = false;
+
 		for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
 			if (of_device_is_compatible(cn, cpu_eff->compatible))
 				break;
@@ -151,6 +367,8 @@ static void __init parse_dt_topology(voi
 		middle_capacity = ((max_capacity / 3)
 				>> (SCHED_CAPACITY_SHIFT-1)) + 1;
 
+	if (cap_from_dt && !cap_parsing_failed)
+		normalize_cpu_capacity();
 }
 
 /*
@@ -160,7 +378,7 @@ static void __init parse_dt_topology(voi
  */
 static void update_cpu_capacity(unsigned int cpu)
 {
-	if (!cpu_capacity(cpu))
+	if (!cpu_capacity(cpu) || cap_from_dt)
 		return;
 
 	set_capacity_scale(cpu, cpu_capacity(cpu) / middle_capacity);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kvm/arm.c linux-libre-4.10-rc8-gnu/arch/arm/kvm/arm.c
--- linux-libre-4.9-gnu/arch/arm/kvm/arm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kvm/arm.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/mman.h>
 #include <asm/tlbflush.h>
@@ -221,6 +221,12 @@ int kvm_vm_ioctl_check_extension(struct
 	case KVM_CAP_MAX_VCPUS:
 		r = KVM_MAX_VCPUS;
 		break;
+	case KVM_CAP_MSI_DEVID:
+		if (!kvm)
+			r = -EINVAL;
+		else
+			r = kvm->arch.vgic.msis_require_devid;
+		break;
 	default:
 		r = kvm_arch_dev_ioctl_check_extension(kvm, ext);
 		break;
@@ -1093,6 +1099,9 @@ static void cpu_init_hyp_mode(void *dumm
 	__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
 	__cpu_init_stage2();
 
+	if (is_kernel_in_hyp_mode())
+		kvm_timer_init_vhe();
+
 	kvm_arm_init_debug();
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kvm/guest.c linux-libre-4.10-rc8-gnu/arch/arm/kvm/guest.c
--- linux-libre-4.9-gnu/arch/arm/kvm/guest.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kvm/guest.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <asm/cputype.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/kvm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kvm/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/kvm/Kconfig
--- linux-libre-4.9-gnu/arch/arm/kvm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kvm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,7 @@ config KVM
 	select HAVE_KVM_IRQFD
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_IRQ_ROUTING
+	select HAVE_KVM_MSI
 	depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
 	---help---
 	  Support hosting virtualized guest machines.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/kvm/Makefile linux-libre-4.10-rc8-gnu/arch/arm/kvm/Makefile
--- linux-libre-4.9-gnu/arch/arm/kvm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/kvm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -32,5 +32,6 @@ obj-y += $(KVM)/arm/vgic/vgic-mmio.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
 obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o
+obj-y += $(KVM)/arm/vgic/vgic-its.o
 obj-y += $(KVM)/irqchip.o
 obj-y += $(KVM)/arm/arch_timer.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/lib/delay-loop.S linux-libre-4.10-rc8-gnu/arch/arm/lib/delay-loop.S
--- linux-libre-4.9-gnu/arch/arm/lib/delay-loop.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/lib/delay-loop.S	2017-02-12 16:03:20.000000000 -0500
@@ -17,24 +17,23 @@
 .LC1:		.word	UDELAY_MULT
 
 /*
+ * loops = r0 * HZ * loops_per_jiffy / 1000000
+ *
  * r0  <= 2000
  * HZ  <= 1000
  */
 
 ENTRY(__loop_udelay)
 		ldr	r2, .LC1
-		mul	r0, r2, r0
-ENTRY(__loop_const_udelay)			@ 0 <= r0 <= 0x7fffff06
+		mul	r0, r2, r0		@ r0 = delay_us * UDELAY_MULT
+ENTRY(__loop_const_udelay)			@ 0 <= r0 <= 0xfffffaf0
 		ldr	r2, .LC0
 		ldr	r2, [r2]
-		umull	r1, r0, r2, r0
-		adds	r1, r1, #0xffffffff
-		adcs	r0, r0, r0
+		umull	r1, r0, r2, r0		@ r0-r1 = r0 * loops_per_jiffy
+		adds	r1, r1, #0xffffffff	@ rounding up ...
+		adcs	r0, r0, r0		@ and right shift by 31
 		reteq	lr
 
-/*
- * loops = r0 * HZ * loops_per_jiffy / 1000000
- */
 		.align 3
 
 @ Delay routine
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-artpec/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mach-artpec/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mach-artpec/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-artpec/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@ config MACH_ARTPEC6
 	select HAVE_ARM_ARCH_TIMER
 	select HAVE_ARM_SCU
 	select HAVE_ARM_TWD if SMP
+	select MFD_SYSCON
 	help
 	  Support for Axis ARTPEC-6 ARM Cortex A9 Platform
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-bcm/bcm_5301x.c linux-libre-4.10-rc8-gnu/arch/arm/mach-bcm/bcm_5301x.c
--- linux-libre-4.9-gnu/arch/arm/mach-bcm/bcm_5301x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-bcm/bcm_5301x.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,14 +9,42 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include <asm/mach/arch.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+
+#define FSR_EXTERNAL		(1 << 12)
+#define FSR_READ		(0 << 10)
+#define FSR_IMPRECISE		0x0406
 
 static const char *const bcm5301x_dt_compat[] __initconst = {
 	"brcm,bcm4708",
 	NULL,
 };
 
+static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr,
+				  struct pt_regs *regs)
+{
+	/*
+	 * We want to ignore aborts forwarded from the PCIe bus that are
+	 * expected and shouldn't really be passed by the PCIe controller.
+	 * The biggest disadvantage is the same FSR code may be reported when
+	 * reading non-existing APB register and we shouldn't ignore that.
+	 */
+	if (fsr == (FSR_EXTERNAL | FSR_READ | FSR_IMPRECISE))
+		return 0;
+
+	return 1;
+}
+
+static void __init bcm5301x_init_early(void)
+{
+	hook_fault_code(16 + 6, bcm5301x_abort_handler, SIGBUS, BUS_OBJERR,
+			"imprecise external abort");
+}
+
 DT_MACHINE_START(BCM5301X, "BCM5301X")
 	.l2c_aux_val	= 0,
 	.l2c_aux_mask	= ~0,
 	.dt_compat	= bcm5301x_dt_compat,
+	.init_early	= bcm5301x_init_early,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/board-da830-evm.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-da830-evm.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/board-da830-evm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-da830-evm.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/console.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
@@ -27,6 +28,7 @@
 #include <linux/platform_data/mtd-davinci-aemif.h>
 #include <linux/platform_data/spi-davinci.h>
 #include <linux/platform_data/usb-davinci.h>
+#include <linux/regulator/machine.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -106,43 +108,24 @@ static irqreturn_t da830_evm_usb_ocic_ir
 
 static __init void da830_evm_usb_init(void)
 {
-	u32 cfgchip2;
 	int ret;
 
-	/*
-	 * Set up USB clock/mode in the CFGCHIP2 register.
-	 * FYI:  CFGCHIP2 is 0x0000ef00 initially.
-	 */
-	cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-
-	/* USB2.0 PHY reference clock is 24 MHz */
-	cfgchip2 &= ~CFGCHIP2_REFFREQ;
-	cfgchip2 |=  CFGCHIP2_REFFREQ_24MHZ;
-
-	/*
-	 * Select internal reference clock for USB 2.0 PHY
-	 * and use it as a clock source for USB 1.1 PHY
-	 * (this is the default setting anyway).
-	 */
-	cfgchip2 &= ~CFGCHIP2_USB1PHYCLKMUX;
-	cfgchip2 |=  CFGCHIP2_USB2PHYCLKMUX;
+	/* USB_REFCLKIN is not used. */
+	ret = da8xx_register_usb20_phy_clk(false);
+	if (ret)
+		pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
+			__func__, ret);
 
-	/*
-	 * We have to override VBUS/ID signals when MUSB is configured into the
-	 * host-only mode -- ID pin will float if no cable is connected, so the
-	 * controller won't be able to drive VBUS thinking that it's a B-device.
-	 * Otherwise, we want to use the OTG mode and enable VBUS comparators.
-	 */
-	cfgchip2 &= ~CFGCHIP2_OTGMODE;
-#ifdef	CONFIG_USB_MUSB_HOST
-	cfgchip2 |=  CFGCHIP2_FORCE_HOST;
-#else
-	cfgchip2 |=  CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN;
-#endif
+	ret = da8xx_register_usb11_phy_clk(false);
+	if (ret)
+		pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
+			__func__, ret);
 
-	__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+	ret = da8xx_register_usb_phy();
+	if (ret)
+		pr_warn("%s: USB PHY registration failed: %d\n",
+			__func__, ret);
 
-	/* USB_REFCLKIN is not used. */
 	ret = davinci_cfg_reg(DA830_USB0_DRVVBUS);
 	if (ret)
 		pr_warn("%s: USB 2.0 PinMux setup failed: %d\n", __func__, ret);
@@ -222,22 +205,16 @@ static const short da830_evm_mmc_sd_pins
 	-1
 };
 
-#define DA830_MMCSD_WP_PIN		GPIO_TO_PIN(2, 1)
-#define DA830_MMCSD_CD_PIN		GPIO_TO_PIN(2, 2)
-
-static int da830_evm_mmc_get_ro(int index)
-{
-	return gpio_get_value(DA830_MMCSD_WP_PIN);
-}
-
-static int da830_evm_mmc_get_cd(int index)
-{
-	return !gpio_get_value(DA830_MMCSD_CD_PIN);
-}
+static struct gpiod_lookup_table mmc_gpios_table = {
+	.dev_id = "da830-mmc.0",
+	.table = {
+		/* gpio chip 1 contains gpio range 32-63 */
+		GPIO_LOOKUP("davinci_gpio.1", 2, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("davinci_gpio.1", 1, "wp", GPIO_ACTIVE_LOW),
+	},
+};
 
 static struct davinci_mmc_config da830_evm_mmc_config = {
-	.get_ro			= da830_evm_mmc_get_ro,
-	.get_cd			= da830_evm_mmc_get_cd,
 	.wires			= 8,
 	.max_freq		= 50000000,
 	.caps			= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
@@ -253,26 +230,12 @@ static inline void da830_evm_init_mmc(vo
 		return;
 	}
 
-	ret = gpio_request(DA830_MMCSD_WP_PIN, "MMC WP");
-	if (ret) {
-		pr_warn("%s: can not open GPIO %d\n",
-			__func__, DA830_MMCSD_WP_PIN);
-		return;
-	}
-	gpio_direction_input(DA830_MMCSD_WP_PIN);
-
-	ret = gpio_request(DA830_MMCSD_CD_PIN, "MMC CD\n");
-	if (ret) {
-		pr_warn("%s: can not open GPIO %d\n",
-			__func__, DA830_MMCSD_CD_PIN);
-		return;
-	}
-	gpio_direction_input(DA830_MMCSD_CD_PIN);
+	gpiod_add_lookup_table(&mmc_gpios_table);
 
 	ret = da8xx_register_mmcsd0(&da830_evm_mmc_config);
 	if (ret) {
 		pr_warn("%s: mmc/sd registration failed: %d\n", __func__, ret);
-		gpio_free(DA830_MMCSD_WP_PIN);
+		gpiod_remove_lookup_table(&mmc_gpios_table);
 	}
 }
 
@@ -588,6 +551,10 @@ static __init void da830_evm_init(void)
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 	int ret;
 
+	ret = da8xx_register_cfgchip();
+	if (ret)
+		pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
+
 	ret = da830_register_gpio();
 	if (ret)
 		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
@@ -647,6 +614,8 @@ static __init void da830_evm_init(void)
 	ret = da8xx_register_spi_bus(0, ARRAY_SIZE(da830evm_spi_info));
 	if (ret)
 		pr_warn("%s: spi 0 registration failed: %d\n", __func__, ret);
+
+	regulator_has_full_constraints();
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/board-da850-evm.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-da850-evm.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/board-da850-evm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-da850-evm.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
+#include <linux/gpio/machine.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
@@ -56,9 +57,6 @@
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN		GPIO_TO_PIN(2, 15)
 
-#define DA850_MMCSD_CD_PIN		GPIO_TO_PIN(4, 0)
-#define DA850_MMCSD_WP_PIN		GPIO_TO_PIN(4, 1)
-
 #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
 
 static struct mtd_partition da850evm_spiflash_part[] = {
@@ -196,18 +194,6 @@ static struct platform_device da850_evm_
 	.resource	= da850_evm_norflash_resource,
 };
 
-static struct davinci_pm_config da850_pm_pdata = {
-	.sleepcount = 128,
-};
-
-static struct platform_device da850_pm_device = {
-	.name           = "pm-davinci",
-	.dev = {
-		.platform_data	= &da850_pm_pdata,
-	},
-	.id             = -1,
-};
-
 /* DA850/OMAP-L138 EVM includes a 512 MByte large-page NAND flash
  * (128K blocks). It may be used instead of the (default) SPI flash
  * to boot, using TI's tools to install the secondary boot loader
@@ -776,19 +762,16 @@ static const short da850_evm_mcasp_pins[
 	-1
 };
 
-static int da850_evm_mmc_get_ro(int index)
-{
-	return gpio_get_value(DA850_MMCSD_WP_PIN);
-}
-
-static int da850_evm_mmc_get_cd(int index)
-{
-	return !gpio_get_value(DA850_MMCSD_CD_PIN);
-}
+static struct gpiod_lookup_table mmc_gpios_table = {
+	.dev_id = "da830-mmc.0",
+	.table = {
+		/* gpio chip 2 contains gpio range 64-95 */
+		GPIO_LOOKUP("davinci_gpio.2", 0, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("davinci_gpio.2", 1, "wp", GPIO_ACTIVE_LOW),
+	},
+};
 
 static struct davinci_mmc_config da850_mmc_config = {
-	.get_ro		= da850_evm_mmc_get_ro,
-	.get_cd		= da850_evm_mmc_get_cd,
 	.wires		= 4,
 	.max_freq	= 50000000,
 	.caps		= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
@@ -1345,6 +1328,10 @@ static __init void da850_evm_init(void)
 {
 	int ret;
 
+	ret = da8xx_register_cfgchip();
+	if (ret)
+		pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
+
 	ret = da850_register_gpio();
 	if (ret)
 		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
@@ -1379,17 +1366,7 @@ static __init void da850_evm_init(void)
 			pr_warn("%s: MMCSD0 mux setup failed: %d\n",
 				__func__, ret);
 
-		ret = gpio_request(DA850_MMCSD_CD_PIN, "MMC CD\n");
-		if (ret)
-			pr_warn("%s: can not open GPIO %d\n",
-				__func__, DA850_MMCSD_CD_PIN);
-		gpio_direction_input(DA850_MMCSD_CD_PIN);
-
-		ret = gpio_request(DA850_MMCSD_WP_PIN, "MMC WP\n");
-		if (ret)
-			pr_warn("%s: can not open GPIO %d\n",
-				__func__, DA850_MMCSD_WP_PIN);
-		gpio_direction_input(DA850_MMCSD_WP_PIN);
+		gpiod_add_lookup_table(&mmc_gpios_table);
 
 		ret = da8xx_register_mmcsd0(&da850_mmc_config);
 		if (ret)
@@ -1453,10 +1430,7 @@ static __init void da850_evm_init(void)
 	if (ret)
 		pr_warn("%s: cpuidle registration failed: %d\n", __func__, ret);
 
-	ret = da850_register_pm(&da850_pm_device);
-	if (ret)
-		pr_warn("%s: suspend registration failed: %d\n", __func__, ret);
-
+	davinci_pm_init();
 	da850_vpif_init();
 
 	ret = spi_register_board_info(da850evm_spi_info,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/board-mityomapl138.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-mityomapl138.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/board-mityomapl138.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-mityomapl138.c	2017-02-12 16:03:20.000000000 -0500
@@ -498,22 +498,14 @@ static void __init mityomapl138_config_e
 		pr_warn("emac registration failed: %d\n", ret);
 }
 
-static struct davinci_pm_config da850_pm_pdata = {
-	.sleepcount = 128,
-};
-
-static struct platform_device da850_pm_device = {
-	.name	= "pm-davinci",
-	.dev = {
-		.platform_data  = &da850_pm_pdata,
-	},
-	.id	= -1,
-};
-
 static void __init mityomapl138_init(void)
 {
 	int ret;
 
+	ret = da8xx_register_cfgchip();
+	if (ret)
+		pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
+
 	/* for now, no special EDMA channels are reserved */
 	ret = da850_register_edma(NULL);
 	if (ret)
@@ -555,9 +547,7 @@ static void __init mityomapl138_init(voi
 	if (ret)
 		pr_warn("cpuidle registration failed: %d\n", ret);
 
-	ret = da850_register_pm(&da850_pm_device);
-	if (ret)
-		pr_warn("suspend registration failed: %d\n", ret);
+	davinci_pm_init();
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,9 @@
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/gpio.h>
+#include <linux/gpio/machine.h>
 #include <linux/platform_data/gpio-davinci.h>
+#include <linux/regulator/machine.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -24,8 +26,6 @@
 #include <mach/mux.h>
 
 #define HAWKBOARD_PHY_ID		"davinci_mdio-0:07"
-#define DA850_HAWK_MMCSD_CD_PIN		GPIO_TO_PIN(3, 12)
-#define DA850_HAWK_MMCSD_WP_PIN		GPIO_TO_PIN(3, 13)
 
 #define DA850_USB1_VBUS_PIN		GPIO_TO_PIN(2, 4)
 #define DA850_USB1_OC_PIN		GPIO_TO_PIN(6, 13)
@@ -122,19 +122,16 @@ static const short hawk_mmcsd0_pins[] =
 	-1
 };
 
-static int da850_hawk_mmc_get_ro(int index)
-{
-	return gpio_get_value(DA850_HAWK_MMCSD_WP_PIN);
-}
-
-static int da850_hawk_mmc_get_cd(int index)
-{
-	return !gpio_get_value(DA850_HAWK_MMCSD_CD_PIN);
-}
+static struct gpiod_lookup_table mmc_gpios_table = {
+	.dev_id = "da830-mmc.0",
+	.table = {
+		/* CD: gpio3_12: gpio60: chip 1 contains gpio range 32-63*/
+		GPIO_LOOKUP("davinci_gpio.1", 28, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("davinci_gpio.1", 29, "wp", GPIO_ACTIVE_LOW),
+	},
+};
 
 static struct davinci_mmc_config da850_mmc_config = {
-	.get_ro		= da850_hawk_mmc_get_ro,
-	.get_cd		= da850_hawk_mmc_get_cd,
 	.wires		= 4,
 	.max_freq	= 50000000,
 	.caps		= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
@@ -150,21 +147,7 @@ static __init void omapl138_hawk_mmc_ini
 		return;
 	}
 
-	ret = gpio_request_one(DA850_HAWK_MMCSD_CD_PIN,
-			GPIOF_DIR_IN, "MMC CD");
-	if (ret < 0) {
-		pr_warn("%s: can not open GPIO %d\n",
-			__func__, DA850_HAWK_MMCSD_CD_PIN);
-		return;
-	}
-
-	ret = gpio_request_one(DA850_HAWK_MMCSD_WP_PIN,
-			GPIOF_DIR_IN, "MMC WP");
-	if (ret < 0) {
-		pr_warn("%s: can not open GPIO %d\n",
-			__func__, DA850_HAWK_MMCSD_WP_PIN);
-		goto mmc_setup_wp_fail;
-	}
+	gpiod_add_lookup_table(&mmc_gpios_table);
 
 	ret = da8xx_register_mmcsd0(&da850_mmc_config);
 	if (ret) {
@@ -175,9 +158,7 @@ static __init void omapl138_hawk_mmc_ini
 	return;
 
 mmc_setup_mmcsd_fail:
-	gpio_free(DA850_HAWK_MMCSD_WP_PIN);
-mmc_setup_wp_fail:
-	gpio_free(DA850_HAWK_MMCSD_CD_PIN);
+	gpiod_remove_lookup_table(&mmc_gpios_table);
 }
 
 static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id);
@@ -243,7 +224,6 @@ static irqreturn_t omapl138_hawk_usb_oci
 static __init void omapl138_hawk_usb_init(void)
 {
 	int ret;
-	u32 cfgchip2;
 
 	ret = davinci_cfg_reg_list(da850_hawk_usb11_pins);
 	if (ret) {
@@ -251,12 +231,20 @@ static __init void omapl138_hawk_usb_ini
 		return;
 	}
 
-	/* Setup the Ref. clock frequency for the HAWK at 24 MHz. */
+	ret = da8xx_register_usb20_phy_clk(false);
+	if (ret)
+		pr_warn("%s: USB 2.0 PHY CLK registration failed: %d\n",
+			__func__, ret);
 
-	cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
-	cfgchip2 &= ~CFGCHIP2_REFFREQ;
-	cfgchip2 |=  CFGCHIP2_REFFREQ_24MHZ;
-	__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+	ret = da8xx_register_usb11_phy_clk(false);
+	if (ret)
+		pr_warn("%s: USB 1.1 PHY CLK registration failed: %d\n",
+			__func__, ret);
+
+	ret = da8xx_register_usb_phy();
+	if (ret)
+		pr_warn("%s: USB PHY registration failed: %d\n",
+			__func__, ret);
 
 	ret = gpio_request_one(DA850_USB1_VBUS_PIN,
 			GPIOF_DIR_OUT, "USB1 VBUS");
@@ -292,6 +280,10 @@ static __init void omapl138_hawk_init(vo
 {
 	int ret;
 
+	ret = da8xx_register_cfgchip();
+	if (ret)
+		pr_warn("%s: CFGCHIP registration failed: %d\n", __func__, ret);
+
 	ret = da850_register_gpio();
 	if (ret)
 		pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
@@ -317,6 +309,8 @@ static __init void omapl138_hawk_init(vo
 	if (ret)
 		pr_warn("%s: dsp/rproc registration failed: %d\n",
 			__func__, ret);
+
+	regulator_has_full_constraints();
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/clock.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/clock.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/clock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/clock.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,10 +31,10 @@ static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clockfw_lock);
 
-static void __clk_enable(struct clk *clk)
+void davinci_clk_enable(struct clk *clk)
 {
 	if (clk->parent)
-		__clk_enable(clk->parent);
+		davinci_clk_enable(clk->parent);
 	if (clk->usecount++ == 0) {
 		if (clk->flags & CLK_PSC)
 			davinci_psc_config(clk->domain, clk->gpsc, clk->lpsc,
@@ -44,7 +44,7 @@ static void __clk_enable(struct clk *clk
 	}
 }
 
-static void __clk_disable(struct clk *clk)
+void davinci_clk_disable(struct clk *clk)
 {
 	if (WARN_ON(clk->usecount == 0))
 		return;
@@ -56,7 +56,7 @@ static void __clk_disable(struct clk *cl
 			clk->clk_disable(clk);
 	}
 	if (clk->parent)
-		__clk_disable(clk->parent);
+		davinci_clk_disable(clk->parent);
 }
 
 int davinci_clk_reset(struct clk *clk, bool reset)
@@ -103,7 +103,7 @@ int clk_enable(struct clk *clk)
 		return -EINVAL;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	__clk_enable(clk);
+	davinci_clk_enable(clk);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return 0;
@@ -118,7 +118,7 @@ void clk_disable(struct clk *clk)
 		return;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	__clk_disable(clk);
+	davinci_clk_disable(clk);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/clock.h linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/clock.h
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/clock.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/clock.h	2017-02-12 16:03:20.000000000 -0500
@@ -132,6 +132,8 @@ int davinci_set_sysclk_rate(struct clk *
 int davinci_set_refclk_rate(unsigned long rate);
 int davinci_simple_set_rate(struct clk *clk, unsigned long rate);
 int davinci_clk_reset(struct clk *clk, bool reset);
+void davinci_clk_enable(struct clk *clk);
+void davinci_clk_disable(struct clk *clk);
 
 extern struct platform_device davinci_wdt_device;
 extern void davinci_watchdog_reset(struct platform_device *);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/common.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/common.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/common.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,6 +118,5 @@ err:
 void __init davinci_init_late(void)
 {
 	davinci_cpufreq_init();
-	davinci_pm_init();
 	davinci_clk_disable_unused();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/da830.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/da830.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/da830.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/da830.c	2017-02-12 16:03:20.000000000 -0500
@@ -412,7 +412,7 @@ static struct clk_lookup da830_clks[] =
 	CLK("davinci-mcasp.0",	NULL,		&mcasp0_clk),
 	CLK("davinci-mcasp.1",	NULL,		&mcasp1_clk),
 	CLK("davinci-mcasp.2",	NULL,		&mcasp2_clk),
-	CLK(NULL,		"usb20",	&usb20_clk),
+	CLK("musb-da8xx",	"usb20",	&usb20_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),
 	CLK(NULL,		"aintc",	&aintc_clk),
 	CLK(NULL,		"secu_mgr",	&secu_mgr_clk),
@@ -420,7 +420,7 @@ static struct clk_lookup da830_clks[] =
 	CLK("davinci_mdio.0",   "fck",          &emac_clk),
 	CLK(NULL,		"gpio",		&gpio_clk),
 	CLK("i2c_davinci.2",	NULL,		&i2c1_clk),
-	CLK(NULL,		"usb11",	&usb11_clk),
+	CLK("ohci-da8xx",	"usb11",	&usb11_clk),
 	CLK(NULL,		"emif3",	&emif3_clk),
 	CLK(NULL,		"arm",		&arm_clk),
 	CLK(NULL,		"rmii",		&rmii_clk),
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/da850.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/da850.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/da850.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/da850.c	2017-02-12 16:03:20.000000000 -0500
@@ -319,6 +319,16 @@ static struct clk emac_clk = {
 	.gpsc		= 1,
 };
 
+/*
+ * In order to avoid adding the emac_clk to the clock lookup table twice (and
+ * screwing up the linked list in the process) create a separate clock for
+ * mdio inheriting the rate from emac_clk.
+ */
+static struct clk mdio_clk = {
+	.name		= "mdio",
+	.parent		= &emac_clk,
+};
+
 static struct clk mcasp_clk = {
 	.name		= "mcasp",
 	.parent		= &async3_clk,
@@ -367,6 +377,16 @@ static struct clk aemif_clk = {
 	.flags		= ALWAYS_ENABLED,
 };
 
+/*
+ * In order to avoid adding the aemif_clk to the clock lookup table twice (and
+ * screwing up the linked list in the process) create a separate clock for
+ * nand inheriting the rate from aemif_clk.
+ */
+static struct clk aemif_nand_clk = {
+	.name		= "nand",
+	.parent		= &aemif_clk,
+};
+
 static struct clk usb11_clk = {
 	.name		= "usb11",
 	.parent		= &pll0_sysclk4,
@@ -424,6 +444,16 @@ static struct clk ehrpwm_clk = {
 	.gpsc		= 1,
 };
 
+static struct clk ehrpwm0_clk = {
+	.name		= "ehrpwm0",
+	.parent		= &ehrpwm_clk,
+};
+
+static struct clk ehrpwm1_clk = {
+	.name		= "ehrpwm1",
+	.parent		= &ehrpwm_clk,
+};
+
 #define DA8XX_EHRPWM_TBCLKSYNC	BIT(12)
 
 static void ehrpwm_tblck_enable(struct clk *clk)
@@ -451,6 +481,16 @@ static struct clk ehrpwm_tbclk = {
 	.clk_disable	= ehrpwm_tblck_disable,
 };
 
+static struct clk ehrpwm0_tbclk = {
+	.name		= "ehrpwm0_tbclk",
+	.parent		= &ehrpwm_tbclk,
+};
+
+static struct clk ehrpwm1_tbclk = {
+	.name		= "ehrpwm1_tbclk",
+	.parent		= &ehrpwm_tbclk,
+};
+
 static struct clk ecap_clk = {
 	.name		= "ecap",
 	.parent		= &async3_clk,
@@ -458,6 +498,21 @@ static struct clk ecap_clk = {
 	.gpsc		= 1,
 };
 
+static struct clk ecap0_clk = {
+	.name		= "ecap0_clk",
+	.parent		= &ecap_clk,
+};
+
+static struct clk ecap1_clk = {
+	.name		= "ecap1_clk",
+	.parent		= &ecap_clk,
+};
+
+static struct clk ecap2_clk = {
+	.name		= "ecap2_clk",
+	.parent		= &ecap_clk,
+};
+
 static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"ref",		&ref_clk),
 	CLK(NULL,		"pll0",		&pll0_clk),
@@ -494,7 +549,7 @@ static struct clk_lookup da850_clks[] =
 	CLK(NULL,		"arm",		&arm_clk),
 	CLK(NULL,		"rmii",		&rmii_clk),
 	CLK("davinci_emac.1",	NULL,		&emac_clk),
-	CLK("davinci_mdio.0",	"fck",		&emac_clk),
+	CLK("davinci_mdio.0",	"fck",		&mdio_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp_clk),
 	CLK("davinci-mcbsp.0",	NULL,		&mcbsp0_clk),
 	CLK("davinci-mcbsp.1",	NULL,		&mcbsp1_clk),
@@ -502,17 +557,32 @@ static struct clk_lookup da850_clks[] =
 	CLK("da830-mmc.0",	NULL,		&mmcsd0_clk),
 	CLK("da830-mmc.1",	NULL,		&mmcsd1_clk),
 	CLK("ti-aemif",		NULL,		&aemif_clk),
-	CLK(NULL,		"aemif",	&aemif_clk),
-	CLK(NULL,		"usb11",	&usb11_clk),
-	CLK(NULL,		"usb20",	&usb20_clk),
+	/*
+	 * The only user of this clock is davinci_nand and it get's it through
+	 * con_id. The nand node itself is created from within the aemif
+	 * driver to guarantee that it's probed after the aemif timing
+	 * parameters are configured. of_dev_auxdata is not accessible from
+	 * the aemif driver and can't be passed to of_platform_populate(). For
+	 * that reason we're leaving the dev_id here as NULL.
+	 */
+	CLK(NULL,		"aemif",	&aemif_nand_clk),
+	CLK("ohci-da8xx",	"usb11",	&usb11_clk),
+	CLK("musb-da8xx",	"usb20",	&usb20_clk),
 	CLK("spi_davinci.0",	NULL,		&spi0_clk),
 	CLK("spi_davinci.1",	NULL,		&spi1_clk),
 	CLK("vpif",		NULL,		&vpif_clk),
 	CLK("ahci_da850",		NULL,		&sata_clk),
 	CLK("davinci-rproc.0",	NULL,		&dsp_clk),
-	CLK("ehrpwm",		"fck",		&ehrpwm_clk),
-	CLK("ehrpwm",		"tbclk",	&ehrpwm_tbclk),
-	CLK("ecap",		"fck",		&ecap_clk),
+	CLK(NULL,		NULL,		&ehrpwm_clk),
+	CLK("ehrpwm.0",		"fck",		&ehrpwm0_clk),
+	CLK("ehrpwm.1",		"fck",		&ehrpwm1_clk),
+	CLK(NULL,		NULL,		&ehrpwm_tbclk),
+	CLK("ehrpwm.0",		"tbclk",	&ehrpwm0_tbclk),
+	CLK("ehrpwm.1",		"tbclk",	&ehrpwm1_tbclk),
+	CLK(NULL,		NULL,		&ecap_clk),
+	CLK("ecap.0",		"fck",		&ecap0_clk),
+	CLK("ecap.1",		"fck",		&ecap1_clk),
+	CLK("ecap.2",		"fck",		&ecap2_clk),
 	CLK(NULL,		NULL,		NULL),
 };
 
@@ -1172,44 +1242,6 @@ static int da850_round_armrate(struct cl
 }
 #endif
 
-int __init da850_register_pm(struct platform_device *pdev)
-{
-	int ret;
-	struct davinci_pm_config *pdata = pdev->dev.platform_data;
-
-	ret = davinci_cfg_reg(DA850_RTC_ALARM);
-	if (ret)
-		return ret;
-
-	pdata->ddr2_ctlr_base = da8xx_get_mem_ctlr();
-	pdata->deepsleep_reg = DA8XX_SYSCFG1_VIRT(DA8XX_DEEPSLEEP_REG);
-	pdata->ddrpsc_num = DA8XX_LPSC1_EMIF3C;
-
-	pdata->cpupll_reg_base = ioremap(DA8XX_PLL0_BASE, SZ_4K);
-	if (!pdata->cpupll_reg_base)
-		return -ENOMEM;
-
-	pdata->ddrpll_reg_base = ioremap(DA850_PLL1_BASE, SZ_4K);
-	if (!pdata->ddrpll_reg_base) {
-		ret = -ENOMEM;
-		goto no_ddrpll_mem;
-	}
-
-	pdata->ddrpsc_reg_base = ioremap(DA8XX_PSC1_BASE, SZ_4K);
-	if (!pdata->ddrpsc_reg_base) {
-		ret = -ENOMEM;
-		goto no_ddrpsc_mem;
-	}
-
-	return platform_device_register(pdev);
-
-no_ddrpsc_mem:
-	iounmap(pdata->ddrpll_reg_base);
-no_ddrpll_mem:
-	iounmap(pdata->cpupll_reg_base);
-	return ret;
-}
-
 /* VPIF resource, platform data */
 static u64 da850_vpif_dma_mask = DMA_BIT_MASK(32);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/da8xx-dt.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/da8xx-dt.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/da8xx-dt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/da8xx-dt.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,11 +23,11 @@ static struct of_dev_auxdata da850_auxda
 	OF_DEV_AUXDATA("ti,davinci-i2c", 0x01e28000, "i2c_davinci.2", NULL),
 	OF_DEV_AUXDATA("ti,davinci-wdt", 0x01c21000, "davinci-wdt", NULL),
 	OF_DEV_AUXDATA("ti,da830-mmc", 0x01c40000, "da830-mmc.0", NULL),
-	OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f00000, "ehrpwm", NULL),
-	OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f02000, "ehrpwm", NULL),
-	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f06000, "ecap", NULL),
-	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f07000, "ecap", NULL),
-	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f08000, "ecap", NULL),
+	OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f00000, "ehrpwm.0", NULL),
+	OF_DEV_AUXDATA("ti,da850-ehrpwm", 0x01f02000, "ehrpwm.1", NULL),
+	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f06000, "ecap.0", NULL),
+	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f07000, "ecap.1", NULL),
+	OF_DEV_AUXDATA("ti,da850-ecap", 0x01f08000, "ecap.2", NULL),
 	OF_DEV_AUXDATA("ti,da830-spi", 0x01c41000, "spi_davinci.0", NULL),
 	OF_DEV_AUXDATA("ti,da830-spi", 0x01f0e000, "spi_davinci.1", NULL),
 	OF_DEV_AUXDATA("ns16550a", 0x01c42000, "serial8250.0", NULL),
@@ -38,6 +38,10 @@ static struct of_dev_auxdata da850_auxda
 		       NULL),
 	OF_DEV_AUXDATA("ti,da830-mcasp-audio", 0x01d00000, "davinci-mcasp.0", NULL),
 	OF_DEV_AUXDATA("ti,da850-aemif", 0x68000000, "ti-aemif", NULL),
+	OF_DEV_AUXDATA("ti,da850-tilcdc", 0x01e13000, "da8xx_lcdc.0", NULL),
+	OF_DEV_AUXDATA("ti,da830-ohci", 0x01e25000, "ohci-da8xx", NULL),
+	OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
+	OF_DEV_AUXDATA("ti,da830-usb-phy", 0x01c1417c, "da8xx-usb-phy", NULL),
 	{}
 };
 
@@ -45,7 +49,19 @@ static struct of_dev_auxdata da850_auxda
 
 static void __init da850_init_machine(void)
 {
+	int ret;
+
+	ret = da8xx_register_usb20_phy_clk(false);
+	if (ret)
+		pr_warn("%s: registering USB 2.0 PHY clock failed: %d",
+			__func__, ret);
+	ret = da8xx_register_usb11_phy_clk(false);
+	if (ret)
+		pr_warn("%s: registering USB 1.1 PHY clock failed: %d",
+			__func__, ret);
+
 	of_platform_default_populate(NULL, da850_auxdata_lookup, NULL);
+	davinci_pm_init();
 }
 
 static const char *const da850_boards_compat[] __initconst = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/devices.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/devices.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/devices.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/devices.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,9 +36,6 @@
 #define DM365_MMCSD0_BASE	     0x01D11000
 #define DM365_MMCSD1_BASE	     0x01D00000
 
-#define DAVINCI_DMA_MMCRXEVT	26
-#define DAVINCI_DMA_MMCTXEVT	27
-
 void __iomem  *davinci_sysmod_base;
 
 void davinci_map_sysmod(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/devices-da8xx.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/devices-da8xx.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/devices-da8xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/devices-da8xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@
  * (at your option) any later version.
  */
 #include <linux/init.h>
+#include <linux/platform_data/syscon.h>
 #include <linux/platform_device.h>
 #include <linux/dma-contiguous.h>
 #include <linux/serial_8250.h>
@@ -57,15 +58,6 @@
 #define DA8XX_EMAC_RAM_OFFSET		0x0000
 #define DA8XX_EMAC_CTRL_RAM_SIZE	SZ_8K
 
-#define DA8XX_DMA_SPI0_RX	EDMA_CTLR_CHAN(0, 14)
-#define DA8XX_DMA_SPI0_TX	EDMA_CTLR_CHAN(0, 15)
-#define DA8XX_DMA_MMCSD0_RX	EDMA_CTLR_CHAN(0, 16)
-#define DA8XX_DMA_MMCSD0_TX	EDMA_CTLR_CHAN(0, 17)
-#define DA8XX_DMA_SPI1_RX	EDMA_CTLR_CHAN(0, 18)
-#define DA8XX_DMA_SPI1_TX	EDMA_CTLR_CHAN(0, 19)
-#define DA850_DMA_MMCSD1_RX	EDMA_CTLR_CHAN(1, 28)
-#define DA850_DMA_MMCSD1_TX	EDMA_CTLR_CHAN(1, 29)
-
 void __iomem *da8xx_syscfg0_base;
 void __iomem *da8xx_syscfg1_base;
 
@@ -964,16 +956,6 @@ static struct resource da8xx_spi0_resour
 		.end	= IRQ_DA8XX_SPINT0,
 		.flags	= IORESOURCE_IRQ,
 	},
-	[2] = {
-		.start	= DA8XX_DMA_SPI0_RX,
-		.end	= DA8XX_DMA_SPI0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DA8XX_DMA_SPI0_TX,
-		.end	= DA8XX_DMA_SPI0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
 };
 
 static struct resource da8xx_spi1_resources[] = {
@@ -987,16 +969,6 @@ static struct resource da8xx_spi1_resour
 		.end	= IRQ_DA8XX_SPINT1,
 		.flags	= IORESOURCE_IRQ,
 	},
-	[2] = {
-		.start	= DA8XX_DMA_SPI1_RX,
-		.end	= DA8XX_DMA_SPI1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DA8XX_DMA_SPI1_TX,
-		.end	= DA8XX_DMA_SPI1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
 };
 
 static struct davinci_spi_platform_data da8xx_spi_pdata[] = {
@@ -1089,3 +1061,30 @@ int __init da850_register_sata(unsigned
 	return platform_device_register(&da850_sata_device);
 }
 #endif
+
+static struct syscon_platform_data da8xx_cfgchip_platform_data = {
+	.label	= "cfgchip",
+};
+
+static struct resource da8xx_cfgchip_resources[] = {
+	{
+		.start	= DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP0_REG,
+		.end	= DA8XX_SYSCFG0_BASE + DA8XX_CFGCHIP4_REG + 3,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device da8xx_cfgchip_device = {
+	.name	= "syscon",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &da8xx_cfgchip_platform_data,
+	},
+	.num_resources	= ARRAY_SIZE(da8xx_cfgchip_resources),
+	.resource	= da8xx_cfgchip_resources,
+};
+
+int __init da8xx_register_cfgchip(void)
+{
+	return platform_device_register(&da8xx_cfgchip_device);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/dm355.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/dm355.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/dm355.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/dm355.c	2017-02-12 16:03:20.000000000 -0500
@@ -397,14 +397,6 @@ static struct resource dm355_spi0_resour
 		.start = IRQ_DM355_SPINT0_0,
 		.flags = IORESOURCE_IRQ,
 	},
-	{
-		.start = 17,
-		.flags = IORESOURCE_DMA,
-	},
-	{
-		.start = 16,
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct davinci_spi_platform_data dm355_spi0_pdata = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/dm365.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/dm365.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/dm365.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/dm365.c	2017-02-12 16:03:20.000000000 -0500
@@ -660,14 +660,6 @@ static struct resource dm365_spi0_resour
 		.start = IRQ_DM365_SPIINT0_0,
 		.flags = IORESOURCE_IRQ,
 	},
-	{
-		.start = 17,
-		.flags = IORESOURCE_DMA,
-	},
-	{
-		.start = 16,
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct platform_device dm365_spi0_device = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/include/mach/da8xx.h linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/include/mach/da8xx.h
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/include/mach/da8xx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/include/mach/da8xx.h	2017-02-12 16:03:20.000000000 -0500
@@ -61,6 +61,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_CFGCHIP1_REG	0x180
 #define DA8XX_CFGCHIP2_REG	0x184
 #define DA8XX_CFGCHIP3_REG	0x188
+#define DA8XX_CFGCHIP4_REG	0x18c
 
 #define DA8XX_SYSCFG1_BASE	(IO_PHYS + 0x22C000)
 #define DA8XX_SYSCFG1_VIRT(x)	(da8xx_syscfg1_base + (x))
@@ -88,8 +89,12 @@ int da850_register_edma(struct edma_rsv_
 int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata);
 int da8xx_register_spi_bus(int instance, unsigned num_chipselect);
 int da8xx_register_watchdog(void);
+int da8xx_register_usb_phy(void);
 int da8xx_register_usb20(unsigned mA, unsigned potpgt);
 int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
+int da8xx_register_usb_refclkin(int rate);
+int da8xx_register_usb20_phy_clk(bool use_usb_refclkin);
+int da8xx_register_usb11_phy_clk(bool use_usb_refclkin);
 int da8xx_register_emac(void);
 int da8xx_register_uio_pruss(void);
 int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
@@ -101,7 +106,6 @@ int da8xx_register_gpio(void *pdata);
 int da850_register_cpufreq(char *async_clk);
 int da8xx_register_cpuidle(void);
 void __iomem *da8xx_get_mem_ctlr(void);
-int da850_register_pm(struct platform_device *pdev);
 int da850_register_sata(unsigned long refclkpn);
 int da850_register_vpif(void);
 int da850_register_vpif_display
@@ -113,6 +117,7 @@ void da8xx_rproc_reserve_cma(void);
 int da8xx_register_rproc(void);
 int da850_register_gpio(void);
 int da830_register_gpio(void);
+int da8xx_register_cfgchip(void);
 
 extern struct platform_device da8xx_serial_device[];
 extern struct emac_platform_data da8xx_emac_pdata;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/Makefile linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/Makefile
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -36,5 +36,7 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD)	+=
 
 # Power Management
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
-obj-$(CONFIG_SUSPEND)			+= pm.o sleep.o
 obj-$(CONFIG_HAVE_CLK)			+= pm_domain.o
+ifeq ($(CONFIG_SUSPEND),y)
+obj-$(CONFIG_ARCH_DAVINCI_DA850)	+= pm.o sleep.o
+endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/pm.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/pm.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,15 +21,22 @@
 
 #include <mach/common.h>
 #include <mach/da8xx.h>
-#include "sram.h"
+#include <mach/mux.h>
 #include <mach/pm.h>
 
 #include "clock.h"
+#include "psc.h"
+#include "sram.h"
 
+#define DA850_PLL1_BASE		0x01e1a000
 #define DEEPSLEEP_SLEEPCOUNT_MASK	0xFFFF
+#define DEEPSLEEP_SLEEPCOUNT		128
 
 static void (*davinci_sram_suspend) (struct davinci_pm_config *);
-static struct davinci_pm_config *pdata;
+static struct davinci_pm_config pm_config = {
+	.sleepcount = DEEPSLEEP_SLEEPCOUNT,
+	.ddrpsc_num = DA8XX_LPSC1_EMIF3C,
+};
 
 static void davinci_sram_push(void *dest, void *src, unsigned int size)
 {
@@ -41,58 +48,58 @@ static void davinci_pm_suspend(void)
 {
 	unsigned val;
 
-	if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
+	if (pm_config.cpupll_reg_base != pm_config.ddrpll_reg_base) {
 
 		/* Switch CPU PLL to bypass mode */
-		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
 		val &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
-		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
 
 		udelay(PLL_BYPASS_TIME);
 
 		/* Powerdown CPU PLL */
-		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
 		val |= PLLCTL_PLLPWRDN;
-		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
 	}
 
 	/* Configure sleep count in deep sleep register */
-	val = __raw_readl(pdata->deepsleep_reg);
+	val = __raw_readl(pm_config.deepsleep_reg);
 	val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
-	val |= pdata->sleepcount;
-	__raw_writel(val, pdata->deepsleep_reg);
+	val |= pm_config.sleepcount;
+	__raw_writel(val, pm_config.deepsleep_reg);
 
 	/* System goes to sleep in this call */
-	davinci_sram_suspend(pdata);
+	davinci_sram_suspend(&pm_config);
 
-	if (pdata->cpupll_reg_base != pdata->ddrpll_reg_base) {
+	if (pm_config.cpupll_reg_base != pm_config.ddrpll_reg_base) {
 
 		/* put CPU PLL in reset */
-		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
 		val &= ~PLLCTL_PLLRST;
-		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
 
 		/* put CPU PLL in power down */
-		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
 		val &= ~PLLCTL_PLLPWRDN;
-		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
 
 		/* wait for CPU PLL reset */
 		udelay(PLL_RESET_TIME);
 
 		/* bring CPU PLL out of reset */
-		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
 		val |= PLLCTL_PLLRST;
-		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
 
 		/* Wait for CPU PLL to lock */
 		udelay(PLL_LOCK_TIME);
 
 		/* Remove CPU PLL from bypass mode */
-		val = __raw_readl(pdata->cpupll_reg_base + PLLCTL);
+		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
 		val &= ~PLLCTL_PLLENSRC;
 		val |= PLLCTL_PLLEN;
-		__raw_writel(val, pdata->cpupll_reg_base + PLLCTL);
+		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
 	}
 }
 
@@ -117,17 +124,36 @@ static const struct platform_suspend_ops
 	.valid		= suspend_valid_only_mem,
 };
 
-static int __init davinci_pm_probe(struct platform_device *pdev)
+int __init davinci_pm_init(void)
 {
-	pdata = pdev->dev.platform_data;
-	if (!pdata) {
-		dev_err(&pdev->dev, "cannot get platform data\n");
-		return -ENOENT;
+	int ret;
+
+	ret = davinci_cfg_reg(DA850_RTC_ALARM);
+	if (ret)
+		return ret;
+
+	pm_config.ddr2_ctlr_base = da8xx_get_mem_ctlr();
+	pm_config.deepsleep_reg = DA8XX_SYSCFG1_VIRT(DA8XX_DEEPSLEEP_REG);
+
+	pm_config.cpupll_reg_base = ioremap(DA8XX_PLL0_BASE, SZ_4K);
+	if (!pm_config.cpupll_reg_base)
+		return -ENOMEM;
+
+	pm_config.ddrpll_reg_base = ioremap(DA850_PLL1_BASE, SZ_4K);
+	if (!pm_config.ddrpll_reg_base) {
+		ret = -ENOMEM;
+		goto no_ddrpll_mem;
+	}
+
+	pm_config.ddrpsc_reg_base = ioremap(DA8XX_PSC1_BASE, SZ_4K);
+	if (!pm_config.ddrpsc_reg_base) {
+		ret = -ENOMEM;
+		goto no_ddrpsc_mem;
 	}
 
 	davinci_sram_suspend = sram_alloc(davinci_cpu_suspend_sz, NULL);
 	if (!davinci_sram_suspend) {
-		dev_err(&pdev->dev, "cannot allocate SRAM memory\n");
+		pr_err("PM: cannot allocate SRAM memory\n");
 		return -ENOMEM;
 	}
 
@@ -136,23 +162,9 @@ static int __init davinci_pm_probe(struc
 
 	suspend_set_ops(&davinci_pm_ops);
 
-	return 0;
-}
-
-static int __exit davinci_pm_remove(struct platform_device *pdev)
-{
-	sram_free(davinci_sram_suspend, davinci_cpu_suspend_sz);
-	return 0;
-}
-
-static struct platform_driver davinci_pm_driver = {
-	.driver = {
-		.name	 = "pm-davinci",
-	},
-	.remove = __exit_p(davinci_pm_remove),
-};
-
-int __init davinci_pm_init(void)
-{
-	return platform_driver_probe(&davinci_pm_driver, davinci_pm_probe);
+no_ddrpsc_mem:
+	iounmap(pm_config.ddrpll_reg_base);
+no_ddrpll_mem:
+	iounmap(pm_config.cpupll_reg_base);
+	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/time.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/time.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -268,7 +268,7 @@ static void __init timer_init(void)
 /*
  * clocksource
  */
-static cycle_t read_cycles(struct clocksource *cs)
+static u64 read_cycles(struct clocksource *cs)
 {
 	struct timer_s *t = &timers[TID_CLOCKSOURCE];
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-davinci/usb-da8xx.c linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/usb-da8xx.c
--- linux-libre-4.9-gnu/arch/arm/mach-davinci/usb-da8xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-davinci/usb-da8xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,21 +1,46 @@
 /*
  * DA8xx USB
  */
+#include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/init.h>
+#include <linux/mfd/da8xx-cfgchip.h>
+#include <linux/phy/phy.h>
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_device.h>
 #include <linux/usb/musb.h>
 
+#include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/cputype.h>
 #include <mach/da8xx.h>
 #include <mach/irqs.h>
 
+#include "clock.h"
+
 #define DA8XX_USB0_BASE		0x01e00000
 #define DA8XX_USB1_BASE		0x01e25000
 
-#if IS_ENABLED(CONFIG_USB_MUSB_HDRC)
+static struct clk *usb20_clk;
+
+static struct platform_device da8xx_usb_phy = {
+	.name		= "da8xx-usb-phy",
+	.id		= -1,
+	.dev		= {
+		/*
+		 * Setting init_name so that clock lookup will work in
+		 * da8xx_register_usb11_phy_clk() even if this device is not
+		 * registered yet.
+		 */
+		.init_name	= "da8xx-usb-phy",
+	},
+};
+
+int __init da8xx_register_usb_phy(void)
+{
+	return platform_device_register(&da8xx_usb_phy);
+}
 
 static struct musb_hdrc_config musb_config = {
 	.multipoint	= true,
@@ -45,10 +70,15 @@ static struct resource da8xx_usb20_resou
 
 static u64 usb_dmamask = DMA_BIT_MASK(32);
 
-static struct platform_device usb_dev = {
+static struct platform_device da8xx_usb20_dev = {
 	.name		= "musb-da8xx",
 	.id             = -1,
 	.dev = {
+		/*
+		 * Setting init_name so that clock lookup will work in
+		 * usb20_phy_clk_enable() even if this device is not registered.
+		 */
+		.init_name		= "musb-da8xx",
 		.platform_data		= &usb_data,
 		.dma_mask		= &usb_dmamask,
 		.coherent_dma_mask      = DMA_BIT_MASK(32),
@@ -62,18 +92,9 @@ int __init da8xx_register_usb20(unsigned
 	usb_data.power	= mA > 510 ? 255 : mA / 2;
 	usb_data.potpgt = (potpgt + 1) / 2;
 
-	return platform_device_register(&usb_dev);
-}
-
-#else
-
-int __init da8xx_register_usb20(unsigned int mA, unsigned int potpgt)
-{
-	return 0;
+	return platform_device_register(&da8xx_usb20_dev);
 }
 
-#endif  /* CONFIG_USB_MUSB_HDRC */
-
 static struct resource da8xx_usb11_resources[] = {
 	[0] = {
 		.start	= DA8XX_USB1_BASE,
@@ -90,8 +111,8 @@ static struct resource da8xx_usb11_resou
 static u64 da8xx_usb11_dma_mask = DMA_BIT_MASK(32);
 
 static struct platform_device da8xx_usb11_device = {
-	.name		= "ohci",
-	.id		= 0,
+	.name		= "ohci-da8xx",
+	.id		= -1,
 	.dev = {
 		.dma_mask		= &da8xx_usb11_dma_mask,
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
@@ -105,3 +126,230 @@ int __init da8xx_register_usb11(struct d
 	da8xx_usb11_device.dev.platform_data = pdata;
 	return platform_device_register(&da8xx_usb11_device);
 }
+
+static struct clk usb_refclkin = {
+	.name		= "usb_refclkin",
+	.set_rate	= davinci_simple_set_rate,
+};
+
+static struct clk_lookup usb_refclkin_lookup =
+	CLK(NULL, "usb_refclkin", &usb_refclkin);
+
+/**
+ * da8xx_register_usb_refclkin - register USB_REFCLKIN clock
+ *
+ * @rate: The clock rate in Hz
+ *
+ * This clock is only needed if the board provides an external USB_REFCLKIN
+ * signal, in which case it will be used as the parent of usb20_phy_clk and/or
+ * usb11_phy_clk.
+ */
+int __init da8xx_register_usb_refclkin(int rate)
+{
+	int ret;
+
+	usb_refclkin.rate = rate;
+	ret = clk_register(&usb_refclkin);
+	if (ret)
+		return ret;
+
+	clkdev_add(&usb_refclkin_lookup);
+
+	return 0;
+}
+
+static void usb20_phy_clk_enable(struct clk *clk)
+{
+	u32 val;
+	u32 timeout = 500000; /* 500 msec */
+
+	val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	/* The USB 2.O PLL requires that the USB 2.O PSC is enabled as well. */
+	davinci_clk_enable(usb20_clk);
+
+	/*
+	 * Turn on the USB 2.0 PHY, but just the PLL, and not OTG. The USB 1.1
+	 * host may use the PLL clock without USB 2.0 OTG being used.
+	 */
+	val &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
+	val |= CFGCHIP2_PHY_PLLON;
+
+	writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	while (--timeout) {
+		val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+		if (val & CFGCHIP2_PHYCLKGD)
+			goto done;
+		udelay(1);
+	}
+
+	pr_err("Timeout waiting for USB 2.0 PHY clock good\n");
+done:
+	davinci_clk_disable(usb20_clk);
+}
+
+static void usb20_phy_clk_disable(struct clk *clk)
+{
+	u32 val;
+
+	val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+	val |= CFGCHIP2_PHYPWRDN;
+	writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+}
+
+static int usb20_phy_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 val;
+
+	val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	/* Set the mux depending on the parent clock. */
+	if (parent == &usb_refclkin) {
+		val &= ~CFGCHIP2_USB2PHYCLKMUX;
+	} else if (strcmp(parent->name, "pll0_aux_clk") == 0) {
+		val |= CFGCHIP2_USB2PHYCLKMUX;
+	} else {
+		pr_err("Bad parent on USB 2.0 PHY clock\n");
+		return -EINVAL;
+	}
+
+	/* reference frequency also comes from parent clock */
+	val &= ~CFGCHIP2_REFFREQ_MASK;
+	switch (clk_get_rate(parent)) {
+	case 12000000:
+		val |= CFGCHIP2_REFFREQ_12MHZ;
+		break;
+	case 13000000:
+		val |= CFGCHIP2_REFFREQ_13MHZ;
+		break;
+	case 19200000:
+		val |= CFGCHIP2_REFFREQ_19_2MHZ;
+		break;
+	case 20000000:
+		val |= CFGCHIP2_REFFREQ_20MHZ;
+		break;
+	case 24000000:
+		val |= CFGCHIP2_REFFREQ_24MHZ;
+		break;
+	case 26000000:
+		val |= CFGCHIP2_REFFREQ_26MHZ;
+		break;
+	case 38400000:
+		val |= CFGCHIP2_REFFREQ_38_4MHZ;
+		break;
+	case 40000000:
+		val |= CFGCHIP2_REFFREQ_40MHZ;
+		break;
+	case 48000000:
+		val |= CFGCHIP2_REFFREQ_48MHZ;
+		break;
+	default:
+		pr_err("Bad parent clock rate on USB 2.0 PHY clock\n");
+		return -EINVAL;
+	}
+
+	writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	return 0;
+}
+
+static struct clk usb20_phy_clk = {
+	.name		= "usb20_phy",
+	.clk_enable	= usb20_phy_clk_enable,
+	.clk_disable	= usb20_phy_clk_disable,
+	.set_parent	= usb20_phy_clk_set_parent,
+};
+
+static struct clk_lookup usb20_phy_clk_lookup =
+	CLK("da8xx-usb-phy", "usb20_phy", &usb20_phy_clk);
+
+/**
+ * da8xx_register_usb20_phy_clk - register USB0PHYCLKMUX clock
+ *
+ * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
+ *	or "pll0_aux" if false.
+ */
+int __init da8xx_register_usb20_phy_clk(bool use_usb_refclkin)
+{
+	struct clk *parent;
+	int ret;
+
+	usb20_clk = clk_get(&da8xx_usb20_dev.dev, "usb20");
+	ret = PTR_ERR_OR_ZERO(usb20_clk);
+	if (ret)
+		return ret;
+
+	parent = clk_get(NULL, use_usb_refclkin ? "usb_refclkin" : "pll0_aux");
+	ret = PTR_ERR_OR_ZERO(parent);
+	if (ret) {
+		clk_put(usb20_clk);
+		return ret;
+	}
+
+	usb20_phy_clk.parent = parent;
+	ret = clk_register(&usb20_phy_clk);
+	if (!ret)
+		clkdev_add(&usb20_phy_clk_lookup);
+
+	clk_put(parent);
+
+	return ret;
+}
+
+static int usb11_phy_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 val;
+
+	val = readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	/* Set the USB 1.1 PHY clock mux based on the parent clock. */
+	if (parent == &usb20_phy_clk) {
+		val &= ~CFGCHIP2_USB1PHYCLKMUX;
+	} else if (parent == &usb_refclkin) {
+		val |= CFGCHIP2_USB1PHYCLKMUX;
+	} else {
+		pr_err("Bad parent on USB 1.1 PHY clock\n");
+		return -EINVAL;
+	}
+
+	writel(val, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	return 0;
+}
+
+static struct clk usb11_phy_clk = {
+	.name		= "usb11_phy",
+	.set_parent	= usb11_phy_clk_set_parent,
+};
+
+static struct clk_lookup usb11_phy_clk_lookup =
+	CLK("da8xx-usb-phy", "usb11_phy", &usb11_phy_clk);
+
+/**
+ * da8xx_register_usb11_phy_clk - register USB1PHYCLKMUX clock
+ *
+ * @use_usb_refclkin: Selects the parent clock - either "usb_refclkin" if true
+ *	or "usb20_phy" if false.
+ */
+int __init da8xx_register_usb11_phy_clk(bool use_usb_refclkin)
+{
+	struct clk *parent;
+	int ret = 0;
+
+	if (use_usb_refclkin)
+		parent = clk_get(NULL, "usb_refclkin");
+	else
+		parent = clk_get(&da8xx_usb_phy.dev, "usb20_phy");
+	if (IS_ERR(parent))
+		return PTR_ERR(parent);
+
+	usb11_phy_clk.parent = parent;
+	ret = clk_register(&usb11_phy_clk);
+	if (!ret)
+		clkdev_add(&usb11_phy_clk_lookup);
+
+	clk_put(parent);
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-ep93xx/timer-ep93xx.c linux-libre-4.10-rc8-gnu/arch/arm/mach-ep93xx/timer-ep93xx.c
--- linux-libre-4.9-gnu/arch/arm/mach-ep93xx/timer-ep93xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-ep93xx/timer-ep93xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,13 +59,13 @@ static u64 notrace ep93xx_read_sched_clo
 	return ret;
 }
 
-cycle_t ep93xx_clocksource_read(struct clocksource *c)
+u64 ep93xx_clocksource_read(struct clocksource *c)
 {
 	u64 ret;
 
 	ret = readl(EP93XX_TIMER4_VALUE_LOW);
 	ret |= ((u64) (readl(EP93XX_TIMER4_VALUE_HIGH) & 0xff) << 32);
-	return (cycle_t) ret;
+	return (u64) ret;
 }
 
 static int ep93xx_clkevt_set_next_event(unsigned long next,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-exynos/platsmp.c linux-libre-4.10-rc8-gnu/arch/arm/mach-exynos/platsmp.c
--- linux-libre-4.9-gnu/arch/arm/mach-exynos/platsmp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-exynos/platsmp.c	2017-02-12 16:03:20.000000000 -0500
@@ -385,36 +385,6 @@ fail:
 	return pen_release != -1 ? ret : 0;
 }
 
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-
-static void __init exynos_smp_init_cpus(void)
-{
-	void __iomem *scu_base = scu_base_addr();
-	unsigned int i, ncores;
-
-	if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
-		ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-	else
-		/*
-		 * CPU Nodes are passed thru DT and set_cpu_possible
-		 * is set by "arm_dt_init_cpu_maps".
-		 */
-		return;
-
-	/* 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);
-}
-
 static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
 {
 	int i;
@@ -479,7 +449,6 @@ static void exynos_cpu_die(unsigned int
 #endif /* CONFIG_HOTPLUG_CPU */
 
 const struct smp_operations exynos_smp_ops __initconst = {
-	.smp_init_cpus		= exynos_smp_init_cpus,
 	.smp_prepare_cpus	= exynos_smp_prepare_cpus,
 	.smp_secondary_init	= exynos_secondary_init,
 	.smp_boot_secondary	= exynos_boot_secondary,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-footbridge/dc21285-timer.c linux-libre-4.10-rc8-gnu/arch/arm/mach-footbridge/dc21285-timer.c
--- linux-libre-4.9-gnu/arch/arm/mach-footbridge/dc21285-timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-footbridge/dc21285-timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 #include "common.h"
 
-static cycle_t cksrc_dc21285_read(struct clocksource *cs)
+static u64 cksrc_dc21285_read(struct clocksource *cs)
 {
 	return cs->mask - *CSR_TIMER2_VALUE;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-imx/common.h linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/common.h
--- linux-libre-4.9-gnu/arch/arm/mach-imx/common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/common.h	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,6 @@ int mx21_clocks_init(unsigned long lref,
 int mx27_clocks_init(unsigned long fref);
 int mx31_clocks_init(unsigned long fref);
 int mx35_clocks_init(void);
-int mx31_clocks_init_dt(void);
 struct platform_device *mxc_register_gpio(char *name, int id,
 	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
 void mxc_set_cpu_type(unsigned int type);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-imx/gpc.c linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/gpc.c
--- linux-libre-4.9-gnu/arch/arm/mach-imx/gpc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/gpc.c	2017-02-12 16:03:20.000000000 -0500
@@ -380,13 +380,6 @@ static struct pu_domain imx6q_pu_domain
 		.name = "PU",
 		.power_off = imx6q_pm_pu_power_off,
 		.power_on = imx6q_pm_pu_power_on,
-		.states = {
-			[0] = {
-				.power_off_latency_ns = 25000,
-				.power_on_latency_ns = 2000000,
-			},
-		},
-		.state_count = 1,
 	},
 };
 
@@ -430,6 +423,16 @@ static int imx_gpc_genpd_init(struct dev
 	if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
 		return 0;
 
+	imx6q_pu_domain.base.states = devm_kzalloc(dev,
+					sizeof(*imx6q_pu_domain.base.states),
+					GFP_KERNEL);
+	if (!imx6q_pu_domain.base.states)
+		return -ENOMEM;
+
+	imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
+	imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
+	imx6q_pu_domain.base.state_count = 1;
+
 	for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
 		pm_genpd_init(imx_gpc_domains[i], NULL, false);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-imx/imx31-dt.c linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/imx31-dt.c
--- linux-libre-4.9-gnu/arch/arm/mach-imx/imx31-dt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/imx31-dt.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,11 +23,6 @@ static const char * const imx31_dt_board
 	NULL
 };
 
-static void __init imx31_dt_timer_init(void)
-{
-	mx31_clocks_init_dt();
-}
-
 /* FIXME: replace with DT binding */
 static const struct resource imx31_rnga_res[] __initconst = {
 	DEFINE_RES_MEM(MX31_RNGA_BASE_ADDR, SZ_16K),
@@ -43,7 +38,6 @@ DT_MACHINE_START(IMX31_DT, "Freescale i.
 	.map_io		= mx31_map_io,
 	.init_early	= imx31_init_early,
 	.init_irq	= mx31_init_irq,
-	.init_time	= imx31_dt_timer_init,
 	.init_machine	= imx31_dt_mach_init,
 	.dt_compat	= imx31_dt_board_compat,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-imx/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mach-imx/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -557,7 +557,6 @@ config SOC_VF610
 	bool "Vybrid Family VF610 support"
 	select ARM_GIC if ARCH_MULTI_V7
 	select PINCTRL_VF610
-	select PL310_ERRATA_769419 if CACHE_L2X0
 
 	help
 	  This enables support for Freescale Vybrid VF610 processor.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-imx/mach-imx1.c linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/mach-imx1.c
--- linux-libre-4.9-gnu/arch/arm/mach-imx/mach-imx1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/mach-imx1.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,6 @@ static const char * const imx1_dt_board_
 };
 
 DT_MACHINE_START(IMX1_DT, "Freescale i.MX1 (Device Tree Support)")
-	.map_io		= debug_ll_io_init,
 	.init_early	= imx1_init_early,
 	.init_irq	= imx1_init_irq,
 	.dt_compat	= imx1_dt_board_compat,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-imx/mach-imx6ul.c linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/mach-imx6ul.c
--- linux-libre-4.9-gnu/arch/arm/mach-imx/mach-imx6ul.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/mach-imx6ul.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,6 +89,7 @@ static void __init imx6ul_init_late(void
 
 static const char * const imx6ul_dt_compat[] __initconst = {
 	"fsl,imx6ul",
+	"fsl,imx6ull",
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-imx/mmdc.c linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/mmdc.c
--- linux-libre-4.9-gnu/arch/arm/mach-imx/mmdc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-imx/mmdc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011,2016 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
  *
  * The code contained herein is licensed under the GNU General Public
@@ -10,12 +10,16 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <linux/hrtimer.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/perf_event.h>
+#include <linux/slab.h>
 
 #include "common.h"
 
@@ -27,8 +31,499 @@
 #define BM_MMDC_MDMISC_DDR_TYPE	0x18
 #define BP_MMDC_MDMISC_DDR_TYPE	0x3
 
+#define TOTAL_CYCLES		0x0
+#define BUSY_CYCLES		0x1
+#define READ_ACCESSES		0x2
+#define WRITE_ACCESSES		0x3
+#define READ_BYTES		0x4
+#define WRITE_BYTES		0x5
+
+/* Enables, resets, freezes, overflow profiling*/
+#define DBG_DIS			0x0
+#define DBG_EN			0x1
+#define DBG_RST			0x2
+#define PRF_FRZ			0x4
+#define CYC_OVF			0x8
+#define PROFILE_SEL		0x10
+
+#define MMDC_MADPCR0	0x410
+#define MMDC_MADPSR0	0x418
+#define MMDC_MADPSR1	0x41C
+#define MMDC_MADPSR2	0x420
+#define MMDC_MADPSR3	0x424
+#define MMDC_MADPSR4	0x428
+#define MMDC_MADPSR5	0x42C
+
+#define MMDC_NUM_COUNTERS	6
+
+#define MMDC_FLAG_PROFILE_SEL	0x1
+
+#define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu)
+
 static int ddr_type;
 
+struct fsl_mmdc_devtype_data {
+	unsigned int flags;
+};
+
+static const struct fsl_mmdc_devtype_data imx6q_data = {
+};
+
+static const struct fsl_mmdc_devtype_data imx6qp_data = {
+	.flags = MMDC_FLAG_PROFILE_SEL,
+};
+
+static const struct of_device_id imx_mmdc_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-mmdc", .data = (void *)&imx6q_data},
+	{ .compatible = "fsl,imx6qp-mmdc", .data = (void *)&imx6qp_data},
+	{ /* sentinel */ }
+};
+
+#ifdef CONFIG_PERF_EVENTS
+
+static enum cpuhp_state cpuhp_mmdc_state;
+static DEFINE_IDA(mmdc_ida);
+
+PMU_EVENT_ATTR_STRING(total-cycles, mmdc_pmu_total_cycles, "event=0x00")
+PMU_EVENT_ATTR_STRING(busy-cycles, mmdc_pmu_busy_cycles, "event=0x01")
+PMU_EVENT_ATTR_STRING(read-accesses, mmdc_pmu_read_accesses, "event=0x02")
+PMU_EVENT_ATTR_STRING(write-accesses, mmdc_pmu_write_accesses, "config=0x03")
+PMU_EVENT_ATTR_STRING(read-bytes, mmdc_pmu_read_bytes, "event=0x04")
+PMU_EVENT_ATTR_STRING(read-bytes.unit, mmdc_pmu_read_bytes_unit, "MB");
+PMU_EVENT_ATTR_STRING(read-bytes.scale, mmdc_pmu_read_bytes_scale, "0.000001");
+PMU_EVENT_ATTR_STRING(write-bytes, mmdc_pmu_write_bytes, "event=0x05")
+PMU_EVENT_ATTR_STRING(write-bytes.unit, mmdc_pmu_write_bytes_unit, "MB");
+PMU_EVENT_ATTR_STRING(write-bytes.scale, mmdc_pmu_write_bytes_scale, "0.000001");
+
+struct mmdc_pmu {
+	struct pmu pmu;
+	void __iomem *mmdc_base;
+	cpumask_t cpu;
+	struct hrtimer hrtimer;
+	unsigned int active_events;
+	struct device *dev;
+	struct perf_event *mmdc_events[MMDC_NUM_COUNTERS];
+	struct hlist_node node;
+	struct fsl_mmdc_devtype_data *devtype_data;
+};
+
+/*
+ * Polling period is set to one second, overflow of total-cycles (the fastest
+ * increasing counter) takes ten seconds so one second is safe
+ */
+static unsigned int mmdc_pmu_poll_period_us = 1000000;
+
+module_param_named(pmu_pmu_poll_period_us, mmdc_pmu_poll_period_us, uint,
+		S_IRUGO | S_IWUSR);
+
+static ktime_t mmdc_pmu_timer_period(void)
+{
+	return ns_to_ktime((u64)mmdc_pmu_poll_period_us * 1000);
+}
+
+static ssize_t mmdc_pmu_cpumask_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mmdc_pmu *pmu_mmdc = dev_get_drvdata(dev);
+
+	return cpumap_print_to_pagebuf(true, buf, &pmu_mmdc->cpu);
+}
+
+static struct device_attribute mmdc_pmu_cpumask_attr =
+	__ATTR(cpumask, S_IRUGO, mmdc_pmu_cpumask_show, NULL);
+
+static struct attribute *mmdc_pmu_cpumask_attrs[] = {
+	&mmdc_pmu_cpumask_attr.attr,
+	NULL,
+};
+
+static struct attribute_group mmdc_pmu_cpumask_attr_group = {
+	.attrs = mmdc_pmu_cpumask_attrs,
+};
+
+static struct attribute *mmdc_pmu_events_attrs[] = {
+	&mmdc_pmu_total_cycles.attr.attr,
+	&mmdc_pmu_busy_cycles.attr.attr,
+	&mmdc_pmu_read_accesses.attr.attr,
+	&mmdc_pmu_write_accesses.attr.attr,
+	&mmdc_pmu_read_bytes.attr.attr,
+	&mmdc_pmu_read_bytes_unit.attr.attr,
+	&mmdc_pmu_read_bytes_scale.attr.attr,
+	&mmdc_pmu_write_bytes.attr.attr,
+	&mmdc_pmu_write_bytes_unit.attr.attr,
+	&mmdc_pmu_write_bytes_scale.attr.attr,
+	NULL,
+};
+
+static struct attribute_group mmdc_pmu_events_attr_group = {
+	.name = "events",
+	.attrs = mmdc_pmu_events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-63");
+static struct attribute *mmdc_pmu_format_attrs[] = {
+	&format_attr_event.attr,
+	NULL,
+};
+
+static struct attribute_group mmdc_pmu_format_attr_group = {
+	.name = "format",
+	.attrs = mmdc_pmu_format_attrs,
+};
+
+static const struct attribute_group *attr_groups[] = {
+	&mmdc_pmu_events_attr_group,
+	&mmdc_pmu_format_attr_group,
+	&mmdc_pmu_cpumask_attr_group,
+	NULL,
+};
+
+static u32 mmdc_pmu_read_counter(struct mmdc_pmu *pmu_mmdc, int cfg)
+{
+	void __iomem *mmdc_base, *reg;
+
+	mmdc_base = pmu_mmdc->mmdc_base;
+
+	switch (cfg) {
+	case TOTAL_CYCLES:
+		reg = mmdc_base + MMDC_MADPSR0;
+		break;
+	case BUSY_CYCLES:
+		reg = mmdc_base + MMDC_MADPSR1;
+		break;
+	case READ_ACCESSES:
+		reg = mmdc_base + MMDC_MADPSR2;
+		break;
+	case WRITE_ACCESSES:
+		reg = mmdc_base + MMDC_MADPSR3;
+		break;
+	case READ_BYTES:
+		reg = mmdc_base + MMDC_MADPSR4;
+		break;
+	case WRITE_BYTES:
+		reg = mmdc_base + MMDC_MADPSR5;
+		break;
+	default:
+		return WARN_ONCE(1,
+			"invalid configuration %d for mmdc counter", cfg);
+	}
+	return readl(reg);
+}
+
+static int mmdc_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+	struct mmdc_pmu *pmu_mmdc = hlist_entry_safe(node, struct mmdc_pmu, node);
+	int target;
+
+	if (!cpumask_test_and_clear_cpu(cpu, &pmu_mmdc->cpu))
+		return 0;
+
+	target = cpumask_any_but(cpu_online_mask, cpu);
+	if (target >= nr_cpu_ids)
+		return 0;
+
+	perf_pmu_migrate_context(&pmu_mmdc->pmu, cpu, target);
+	cpumask_set_cpu(target, &pmu_mmdc->cpu);
+
+	return 0;
+}
+
+static bool mmdc_pmu_group_event_is_valid(struct perf_event *event,
+					  struct pmu *pmu,
+					  unsigned long *used_counters)
+{
+	int cfg = event->attr.config;
+
+	if (is_software_event(event))
+		return true;
+
+	if (event->pmu != pmu)
+		return false;
+
+	return !test_and_set_bit(cfg, used_counters);
+}
+
+/*
+ * Each event has a single fixed-purpose counter, so we can only have a
+ * single active event for each at any point in time. Here we just check
+ * for duplicates, and rely on mmdc_pmu_event_init to verify that the HW
+ * event numbers are valid.
+ */
+static bool mmdc_pmu_group_is_valid(struct perf_event *event)
+{
+	struct pmu *pmu = event->pmu;
+	struct perf_event *leader = event->group_leader;
+	struct perf_event *sibling;
+	unsigned long counter_mask = 0;
+
+	set_bit(leader->attr.config, &counter_mask);
+
+	if (event != leader) {
+		if (!mmdc_pmu_group_event_is_valid(event, pmu, &counter_mask))
+			return false;
+	}
+
+	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+		if (!mmdc_pmu_group_event_is_valid(sibling, pmu, &counter_mask))
+			return false;
+	}
+
+	return true;
+}
+
+static int mmdc_pmu_event_init(struct perf_event *event)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	int cfg = event->attr.config;
+
+	if (event->attr.type != event->pmu->type)
+		return -ENOENT;
+
+	if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+		return -EOPNOTSUPP;
+
+	if (event->cpu < 0) {
+		dev_warn(pmu_mmdc->dev, "Can't provide per-task data!\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (event->attr.exclude_user		||
+			event->attr.exclude_kernel	||
+			event->attr.exclude_hv		||
+			event->attr.exclude_idle	||
+			event->attr.exclude_host	||
+			event->attr.exclude_guest	||
+			event->attr.sample_period)
+		return -EINVAL;
+
+	if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS)
+		return -EINVAL;
+
+	if (!mmdc_pmu_group_is_valid(event))
+		return -EINVAL;
+
+	event->cpu = cpumask_first(&pmu_mmdc->cpu);
+	return 0;
+}
+
+static void mmdc_pmu_event_update(struct perf_event *event)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	u64 delta, prev_raw_count, new_raw_count;
+
+	do {
+		prev_raw_count = local64_read(&hwc->prev_count);
+		new_raw_count = mmdc_pmu_read_counter(pmu_mmdc,
+						      event->attr.config);
+	} while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+		new_raw_count) != prev_raw_count);
+
+	delta = (new_raw_count - prev_raw_count) & 0xFFFFFFFF;
+
+	local64_add(delta, &event->count);
+}
+
+static void mmdc_pmu_event_start(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	void __iomem *mmdc_base, *reg;
+	u32 val;
+
+	mmdc_base = pmu_mmdc->mmdc_base;
+	reg = mmdc_base + MMDC_MADPCR0;
+
+	/*
+	 * hrtimer is required because mmdc does not provide an interrupt so
+	 * polling is necessary
+	 */
+	hrtimer_start(&pmu_mmdc->hrtimer, mmdc_pmu_timer_period(),
+			HRTIMER_MODE_REL_PINNED);
+
+	local64_set(&hwc->prev_count, 0);
+
+	writel(DBG_RST, reg);
+
+	val = DBG_EN;
+	if (pmu_mmdc->devtype_data->flags & MMDC_FLAG_PROFILE_SEL)
+		val |= PROFILE_SEL;
+
+	writel(val, reg);
+}
+
+static int mmdc_pmu_event_add(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+
+	int cfg = event->attr.config;
+
+	if (flags & PERF_EF_START)
+		mmdc_pmu_event_start(event, flags);
+
+	if (pmu_mmdc->mmdc_events[cfg] != NULL)
+		return -EAGAIN;
+
+	pmu_mmdc->mmdc_events[cfg] = event;
+	pmu_mmdc->active_events++;
+
+	local64_set(&hwc->prev_count, mmdc_pmu_read_counter(pmu_mmdc, cfg));
+
+	return 0;
+}
+
+static void mmdc_pmu_event_stop(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	void __iomem *mmdc_base, *reg;
+
+	mmdc_base = pmu_mmdc->mmdc_base;
+	reg = mmdc_base + MMDC_MADPCR0;
+
+	writel(PRF_FRZ, reg);
+	mmdc_pmu_event_update(event);
+}
+
+static void mmdc_pmu_event_del(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	int cfg = event->attr.config;
+
+	pmu_mmdc->mmdc_events[cfg] = NULL;
+	pmu_mmdc->active_events--;
+
+	if (pmu_mmdc->active_events == 0)
+		hrtimer_cancel(&pmu_mmdc->hrtimer);
+
+	mmdc_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static void mmdc_pmu_overflow_handler(struct mmdc_pmu *pmu_mmdc)
+{
+	int i;
+
+	for (i = 0; i < MMDC_NUM_COUNTERS; i++) {
+		struct perf_event *event = pmu_mmdc->mmdc_events[i];
+
+		if (event)
+			mmdc_pmu_event_update(event);
+	}
+}
+
+static enum hrtimer_restart mmdc_pmu_timer_handler(struct hrtimer *hrtimer)
+{
+	struct mmdc_pmu *pmu_mmdc = container_of(hrtimer, struct mmdc_pmu,
+			hrtimer);
+
+	mmdc_pmu_overflow_handler(pmu_mmdc);
+	hrtimer_forward_now(hrtimer, mmdc_pmu_timer_period());
+
+	return HRTIMER_RESTART;
+}
+
+static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc,
+		void __iomem *mmdc_base, struct device *dev)
+{
+	int mmdc_num;
+
+	*pmu_mmdc = (struct mmdc_pmu) {
+		.pmu = (struct pmu) {
+			.task_ctx_nr    = perf_invalid_context,
+			.attr_groups    = attr_groups,
+			.event_init     = mmdc_pmu_event_init,
+			.add            = mmdc_pmu_event_add,
+			.del            = mmdc_pmu_event_del,
+			.start          = mmdc_pmu_event_start,
+			.stop           = mmdc_pmu_event_stop,
+			.read           = mmdc_pmu_event_update,
+		},
+		.mmdc_base = mmdc_base,
+		.dev = dev,
+		.active_events = 0,
+	};
+
+	mmdc_num = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL);
+
+	return mmdc_num;
+}
+
+static int imx_mmdc_remove(struct platform_device *pdev)
+{
+	struct mmdc_pmu *pmu_mmdc = platform_get_drvdata(pdev);
+
+	cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
+	perf_pmu_unregister(&pmu_mmdc->pmu);
+	kfree(pmu_mmdc);
+	return 0;
+}
+
+static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base)
+{
+	struct mmdc_pmu *pmu_mmdc;
+	char *name;
+	int mmdc_num;
+	int ret;
+	const struct of_device_id *of_id =
+		of_match_device(imx_mmdc_dt_ids, &pdev->dev);
+
+	pmu_mmdc = kzalloc(sizeof(*pmu_mmdc), GFP_KERNEL);
+	if (!pmu_mmdc) {
+		pr_err("failed to allocate PMU device!\n");
+		return -ENOMEM;
+	}
+
+	/* The first instance registers the hotplug state */
+	if (!cpuhp_mmdc_state) {
+		ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
+					      "perf/arm/mmdc:online", NULL,
+					      mmdc_pmu_offline_cpu);
+		if (ret < 0) {
+			pr_err("cpuhp_setup_state_multi failed\n");
+			goto pmu_free;
+		}
+		cpuhp_mmdc_state = ret;
+	}
+
+	mmdc_num = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev);
+	if (mmdc_num == 0)
+		name = "mmdc";
+	else
+		name = devm_kasprintf(&pdev->dev,
+				GFP_KERNEL, "mmdc%d", mmdc_num);
+
+	pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data;
+
+	hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC,
+			HRTIMER_MODE_REL);
+	pmu_mmdc->hrtimer.function = mmdc_pmu_timer_handler;
+
+	cpumask_set_cpu(raw_smp_processor_id(), &pmu_mmdc->cpu);
+
+	/* Register the pmu instance for cpu hotplug */
+	cpuhp_state_add_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
+
+	ret = perf_pmu_register(&(pmu_mmdc->pmu), name, -1);
+	if (ret)
+		goto pmu_register_err;
+
+	platform_set_drvdata(pdev, pmu_mmdc);
+	return 0;
+
+pmu_register_err:
+	pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret);
+	cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
+	hrtimer_cancel(&pmu_mmdc->hrtimer);
+pmu_free:
+	kfree(pmu_mmdc);
+	return ret;
+}
+
+#else
+#define imx_mmdc_remove NULL
+#define imx_mmdc_perf_init(pdev, mmdc_base) 0
+#endif
+
 static int imx_mmdc_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -62,7 +557,7 @@ static int imx_mmdc_probe(struct platfor
 		return -EBUSY;
 	}
 
-	return 0;
+	return imx_mmdc_perf_init(pdev, mmdc_base);
 }
 
 int imx_mmdc_get_ddr_type(void)
@@ -70,17 +565,13 @@ int imx_mmdc_get_ddr_type(void)
 	return ddr_type;
 }
 
-static const struct of_device_id imx_mmdc_dt_ids[] = {
-	{ .compatible = "fsl,imx6q-mmdc", },
-	{ /* sentinel */ }
-};
-
 static struct platform_driver imx_mmdc_driver = {
 	.driver		= {
 		.name	= "imx-mmdc",
 		.of_match_table = imx_mmdc_dt_ids,
 	},
 	.probe		= imx_mmdc_probe,
+	.remove		= imx_mmdc_remove,
 };
 
 static int __init imx_mmdc_init(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-integrator/impd1.c linux-libre-4.10-rc8-gnu/arch/arm/mach-integrator/impd1.c
--- linux-libre-4.9-gnu/arch/arm/mach-integrator/impd1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-integrator/impd1.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,6 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/amba/mmci.h>
-#include <linux/amba/pl061.h>
 #include <linux/io.h>
 #include <linux/platform_data/clk-integrator.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-integrator/integrator_ap.c linux-libre-4.10-rc8-gnu/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-4.9-gnu/arch/arm/mach-integrator/integrator_ap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-integrator/integrator_ap.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,8 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <linux/termios.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -37,11 +39,8 @@
 #include "pci_v3.h"
 #include "lm.h"
 
-/* Base address to the AP system controller */
-void __iomem *ap_syscon_base;
-/* Base address to the external bus interface */
-static void __iomem *ebi_base;
-
+/* Regmap to the AP system controller */
+static struct regmap *ap_syscon_map;
 
 /*
  * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
@@ -125,6 +124,7 @@ static void integrator_uart_set_mctrl(st
 {
 	unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
 	u32 phybase = dev->res.start;
+	int ret;
 
 	if (phybase == INTEGRATOR_UART0_BASE) {
 		/* UART0 */
@@ -146,8 +146,17 @@ static void integrator_uart_set_mctrl(st
 	else
 		ctrls |= dtr_mask;
 
-	__raw_writel(ctrls, ap_syscon_base + INTEGRATOR_SC_CTRLS_OFFSET);
-	__raw_writel(ctrlc, ap_syscon_base + INTEGRATOR_SC_CTRLC_OFFSET);
+	ret = regmap_write(ap_syscon_map,
+			   INTEGRATOR_SC_CTRLS_OFFSET,
+			   ctrls);
+	if (ret)
+		pr_err("MODEM: unable to write PL010 UART CTRLS\n");
+
+	ret = regmap_write(ap_syscon_map,
+			   INTEGRATOR_SC_CTRLC_OFFSET,
+			   ctrlc);
+	if (ret)
+		pr_err("MODEM: unable to write PL010 UART CRTLC\n");
 }
 
 struct amba_pl010_data ap_uart_data = {
@@ -178,35 +187,32 @@ static const struct of_device_id ap_sysc
 	{ },
 };
 
-static const struct of_device_id ebi_match[] = {
-	{ .compatible = "arm,external-bus-interface"},
-	{ },
-};
-
 static void __init ap_init_of(void)
 {
-	unsigned long sc_dec;
+	u32 sc_dec;
 	struct device_node *syscon;
-	struct device_node *ebi;
+	int ret;
 	int i;
 
+	of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
+
 	syscon = of_find_matching_node(NULL, ap_syscon_match);
 	if (!syscon)
 		return;
-	ebi = of_find_matching_node(NULL, ebi_match);
-	if (!ebi)
+	ap_syscon_map = syscon_node_to_regmap(syscon);
+	if (IS_ERR(ap_syscon_map)) {
+		pr_crit("could not find Integrator/AP system controller\n");
 		return;
+	}
 
-	ap_syscon_base = of_iomap(syscon, 0);
-	if (!ap_syscon_base)
-		return;
-	ebi_base = of_iomap(ebi, 0);
-	if (!ebi_base)
+	ret = regmap_read(ap_syscon_map,
+			  INTEGRATOR_SC_DEC_OFFSET,
+			  &sc_dec);
+	if (ret) {
+		pr_crit("could not read from Integrator/AP syscon\n");
 		return;
+	}
 
-	of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
-
-	sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
 	for (i = 0; i < 4; i++) {
 		struct lm_device *lmdev;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-iop13xx/irq.c linux-libre-4.10-rc8-gnu/arch/arm/mach-iop13xx/irq.c
--- linux-libre-4.9-gnu/arch/arm/mach-iop13xx/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-iop13xx/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/sysctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mach/irq.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-ixp4xx/common.c linux-libre-4.10-rc8-gnu/arch/arm/mach-ixp4xx/common.c
--- linux-libre-4.9-gnu/arch/arm/mach-ixp4xx/common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-ixp4xx/common.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <mach/udc.h>
 #include <mach/hardware.h>
 #include <mach/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/irq.h>
@@ -493,7 +493,7 @@ static u64 notrace ixp4xx_read_sched_clo
  * clocksource
  */
 
-static cycle_t ixp4xx_clocksource_read(struct clocksource *c)
+static u64 ixp4xx_clocksource_read(struct clocksource *c)
 {
 	return *IXP4XX_OSTS;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c linux-libre-4.10-rc8-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c
--- linux-libre-4.9-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-ixp4xx/dsmg600-setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,6 @@
 #include <linux/reboot.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
-#include <linux/gpio.h>
 
 #include <mach/hardware.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/clock.h linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/clock.h
--- linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/clock.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/clock.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 __LPC32XX_CLOCK_H
-#define __LPC32XX_CLOCK_H
-
-struct clk {
-	struct list_head node;
-	struct clk *parent;
-	u32 rate;
-	u32 usecount;
-
-	int (*set_rate) (struct clk *, unsigned long);
-	unsigned long (*round_rate) (struct clk *, unsigned long);
-	unsigned long (*get_rate) (struct clk *clk);
-	int (*enable) (struct clk *, int);
-
-	/* Register address and bit mask for simple clocks */
-	void __iomem *enable_reg;
-	u32 enable_mask;
-};
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/common.h linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/common.h
--- linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/common.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,6 @@
 /*
  * Other arch specific structures and functions
  */
-extern void __init lpc32xx_init_irq(void);
 extern void __init lpc32xx_map_io(void);
 extern void __init lpc32xx_serial_init(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h
--- linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,117 +0,0 @@
-/*
- * arch/arm/mach-lpc32xx/include/mach/irqs.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_ARM_ARCH_IRQS_H
-#define __ASM_ARM_ARCH_IRQS_H
-
-#define LPC32XX_SIC1_IRQ(n)		(32 + (n))
-#define LPC32XX_SIC2_IRQ(n)		(64 + (n))
-
-/*
- * MIC interrupts
- */
-#define IRQ_LPC32XX_SUB1IRQ		0
-#define IRQ_LPC32XX_SUB2IRQ		1
-#define IRQ_LPC32XX_PWM3		3
-#define IRQ_LPC32XX_PWM4		4
-#define IRQ_LPC32XX_HSTIMER		5
-#define IRQ_LPC32XX_WATCH		6
-#define IRQ_LPC32XX_UART_IIR3		7
-#define IRQ_LPC32XX_UART_IIR4		8
-#define IRQ_LPC32XX_UART_IIR5		9
-#define IRQ_LPC32XX_UART_IIR6		10
-#define IRQ_LPC32XX_FLASH		11
-#define IRQ_LPC32XX_SD1			13
-#define IRQ_LPC32XX_LCD			14
-#define IRQ_LPC32XX_SD0			15
-#define IRQ_LPC32XX_TIMER0		16
-#define IRQ_LPC32XX_TIMER1		17
-#define IRQ_LPC32XX_TIMER2		18
-#define IRQ_LPC32XX_TIMER3		19
-#define IRQ_LPC32XX_SSP0		20
-#define IRQ_LPC32XX_SSP1		21
-#define IRQ_LPC32XX_I2S0		22
-#define IRQ_LPC32XX_I2S1		23
-#define IRQ_LPC32XX_UART_IIR7		24
-#define IRQ_LPC32XX_UART_IIR2		25
-#define IRQ_LPC32XX_UART_IIR1		26
-#define IRQ_LPC32XX_MSTIMER		27
-#define IRQ_LPC32XX_DMA			28
-#define IRQ_LPC32XX_ETHERNET		29
-#define IRQ_LPC32XX_SUB1FIQ		30
-#define IRQ_LPC32XX_SUB2FIQ		31
-
-/*
- * SIC1 interrupts start at offset 32
- */
-#define IRQ_LPC32XX_JTAG_COMM_TX	LPC32XX_SIC1_IRQ(1)
-#define IRQ_LPC32XX_JTAG_COMM_RX	LPC32XX_SIC1_IRQ(2)
-#define IRQ_LPC32XX_GPI_28		LPC32XX_SIC1_IRQ(4)
-#define IRQ_LPC32XX_TS_P		LPC32XX_SIC1_IRQ(6)
-#define IRQ_LPC32XX_TS_IRQ		LPC32XX_SIC1_IRQ(7)
-#define IRQ_LPC32XX_TS_AUX		LPC32XX_SIC1_IRQ(8)
-#define IRQ_LPC32XX_SPI2		LPC32XX_SIC1_IRQ(12)
-#define IRQ_LPC32XX_PLLUSB		LPC32XX_SIC1_IRQ(13)
-#define IRQ_LPC32XX_PLLHCLK		LPC32XX_SIC1_IRQ(14)
-#define IRQ_LPC32XX_PLL397		LPC32XX_SIC1_IRQ(17)
-#define IRQ_LPC32XX_I2C_2		LPC32XX_SIC1_IRQ(18)
-#define IRQ_LPC32XX_I2C_1		LPC32XX_SIC1_IRQ(19)
-#define IRQ_LPC32XX_RTC			LPC32XX_SIC1_IRQ(20)
-#define IRQ_LPC32XX_KEY			LPC32XX_SIC1_IRQ(22)
-#define IRQ_LPC32XX_SPI1		LPC32XX_SIC1_IRQ(23)
-#define IRQ_LPC32XX_SW			LPC32XX_SIC1_IRQ(24)
-#define IRQ_LPC32XX_USB_OTG_TIMER	LPC32XX_SIC1_IRQ(25)
-#define IRQ_LPC32XX_USB_OTG_ATX		LPC32XX_SIC1_IRQ(26)
-#define IRQ_LPC32XX_USB_HOST		LPC32XX_SIC1_IRQ(27)
-#define IRQ_LPC32XX_USB_DEV_DMA		LPC32XX_SIC1_IRQ(28)
-#define IRQ_LPC32XX_USB_DEV_LP		LPC32XX_SIC1_IRQ(29)
-#define IRQ_LPC32XX_USB_DEV_HP		LPC32XX_SIC1_IRQ(30)
-#define IRQ_LPC32XX_USB_I2C		LPC32XX_SIC1_IRQ(31)
-
-/*
- * SIC2 interrupts start at offset 64
- */
-#define IRQ_LPC32XX_GPIO_00		LPC32XX_SIC2_IRQ(0)
-#define IRQ_LPC32XX_GPIO_01		LPC32XX_SIC2_IRQ(1)
-#define IRQ_LPC32XX_GPIO_02		LPC32XX_SIC2_IRQ(2)
-#define IRQ_LPC32XX_GPIO_03		LPC32XX_SIC2_IRQ(3)
-#define IRQ_LPC32XX_GPIO_04		LPC32XX_SIC2_IRQ(4)
-#define IRQ_LPC32XX_GPIO_05		LPC32XX_SIC2_IRQ(5)
-#define IRQ_LPC32XX_SPI2_DATAIN		LPC32XX_SIC2_IRQ(6)
-#define IRQ_LPC32XX_U2_HCTS		LPC32XX_SIC2_IRQ(7)
-#define IRQ_LPC32XX_P0_P1_IRQ		LPC32XX_SIC2_IRQ(8)
-#define IRQ_LPC32XX_GPI_08		LPC32XX_SIC2_IRQ(9)
-#define IRQ_LPC32XX_GPI_09		LPC32XX_SIC2_IRQ(10)
-#define IRQ_LPC32XX_GPI_19		LPC32XX_SIC2_IRQ(11)
-#define IRQ_LPC32XX_U7_HCTS		LPC32XX_SIC2_IRQ(12)
-#define IRQ_LPC32XX_GPI_07		LPC32XX_SIC2_IRQ(15)
-#define IRQ_LPC32XX_SDIO		LPC32XX_SIC2_IRQ(18)
-#define IRQ_LPC32XX_U5_RX		LPC32XX_SIC2_IRQ(19)
-#define IRQ_LPC32XX_SPI1_DATAIN		LPC32XX_SIC2_IRQ(20)
-#define IRQ_LPC32XX_GPI_00		LPC32XX_SIC2_IRQ(22)
-#define IRQ_LPC32XX_GPI_01		LPC32XX_SIC2_IRQ(23)
-#define IRQ_LPC32XX_GPI_02		LPC32XX_SIC2_IRQ(24)
-#define IRQ_LPC32XX_GPI_03		LPC32XX_SIC2_IRQ(25)
-#define IRQ_LPC32XX_GPI_04		LPC32XX_SIC2_IRQ(26)
-#define IRQ_LPC32XX_GPI_05		LPC32XX_SIC2_IRQ(27)
-#define IRQ_LPC32XX_GPI_06		LPC32XX_SIC2_IRQ(28)
-#define IRQ_LPC32XX_SYSCLK		LPC32XX_SIC2_IRQ(31)
-
-#define LPC32XX_NR_IRQS			96
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/phy3250.c linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/phy3250.c
--- linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/phy3250.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/phy3250.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
-#include <linux/device.h>
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/pm.c linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/pm.c
--- linux-libre-4.9-gnu/arch/arm/mach-lpc32xx/pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-lpc32xx/pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -73,7 +73,6 @@
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include "common.h"
-#include "clock.h"
 
 #define TEMP_IRAM_AREA  IO_ADDRESS(LPC32XX_IRAM_BASE)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-mediatek/Makefile linux-libre-4.10-rc8-gnu/arch/arm/mach-mediatek/Makefile
--- linux-libre-4.9-gnu/arch/arm/mach-mediatek/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-mediatek/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,2 @@
-ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_ARCH_MEDIATEK) += platsmp.o
-endif
-obj-$(CONFIG_ARCH_MEDIATEK) += mediatek.o
+obj-$(CONFIG_SMP)	+= platsmp.o
+obj-y			+= mediatek.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-mmp/time.c linux-libre-4.10-rc8-gnu/arch/arm/mach-mmp/time.c
--- linux-libre-4.9-gnu/arch/arm/mach-mmp/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-mmp/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -144,7 +144,7 @@ static struct clock_event_device ckevt =
 	.set_state_oneshot	= timer_set_shutdown,
 };
 
-static cycle_t clksrc_read(struct clocksource *cs)
+static u64 clksrc_read(struct clocksource *cs)
 {
 	return timer_read();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-mvebu/coherency.c linux-libre-4.10-rc8-gnu/arch/arm/mach-mvebu/coherency.c
--- linux-libre-4.9-gnu/arch/arm/mach-mvebu/coherency.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-mvebu/coherency.c	2017-02-12 16:03:20.000000000 -0500
@@ -148,7 +148,7 @@ static void __init armada_370_coherency_
 	of_node_put(cpu_config_np);
 
 	cpuhp_setup_state_nocalls(CPUHP_AP_ARM_MVEBU_COHERENCY,
-				  "AP_ARM_MVEBU_COHERENCY",
+				  "arm/mvebu/coherency:starting",
 				  armada_xp_clear_l2_starting, NULL);
 exit:
 	set_cpu_coherent();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap1/dma.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap1/dma.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap1/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap1/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,6 @@
 #include "soc.h"
 
 #define OMAP1_DMA_BASE			(0xfffed800)
-#define OMAP1_LOGICAL_DMA_CH_COUNT	17
 
 static u32 enable_1510_mode;
 
@@ -348,8 +347,6 @@ static int __init omap1_system_dma_init(
 		goto exit_iounmap;
 	}
 
-	d->lch_count		= OMAP1_LOGICAL_DMA_CH_COUNT;
-
 	/* Valid attributes for omap1 plus processors */
 	if (cpu_is_omap15xx())
 		d->dev_caps = ENABLE_1510_MODE;
@@ -366,13 +363,14 @@ static int __init omap1_system_dma_init(
 	d->dev_caps		|= CLEAR_CSR_ON_READ;
 	d->dev_caps		|= IS_WORD_16;
 
-	if (cpu_is_omap15xx())
-		d->chan_count = 9;
-	else if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
-		if (!(d->dev_caps & ENABLE_1510_MODE))
-			d->chan_count = 16;
+	/* available logical channels */
+	if (cpu_is_omap15xx()) {
+		d->lch_count = 9;
+	} else {
+		if (d->dev_caps & ENABLE_1510_MODE)
+			d->lch_count = 9;
 		else
-			d->chan_count = 9;
+			d->lch_count = 16;
 	}
 
 	p = dma_plat_info;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap1/i2c.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap1/i2c.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap1/i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap1/i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/i2c.h>
 #include <linux/i2c-omap.h>
 #include <mach/mux.h>
 #include "soc.h"
@@ -91,6 +92,88 @@ int __init omap_i2c_add_bus(struct omap_
 	return platform_device_register(pdev);
 }
 
+#define OMAP_I2C_MAX_CONTROLLERS 4
+static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS];
+
+#define OMAP_I2C_CMDLINE_SETUP	(BIT(31))
+
+/**
+ * omap_i2c_bus_setup - Process command line options for the I2C bus speed
+ * @str: String of options
+ *
+ * This function allow to override the default I2C bus speed for given I2C
+ * bus with a command line option.
+ *
+ * Format: i2c_bus=bus_id,clkrate (in kHz)
+ *
+ * Returns 1 on success, 0 otherwise.
+ */
+static int __init omap_i2c_bus_setup(char *str)
+{
+	int ints[3];
+
+	get_options(str, 3, ints);
+	if (ints[0] < 2 || ints[1] < 1 ||
+			ints[1] > OMAP_I2C_MAX_CONTROLLERS)
+		return 0;
+	i2c_pdata[ints[1] - 1].clkrate = ints[2];
+	i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP;
+
+	return 1;
+}
+__setup("i2c_bus=", omap_i2c_bus_setup);
+
+/*
+ * Register busses defined in command line but that are not registered with
+ * omap_register_i2c_bus from board initialization code.
+ */
+int __init omap_register_i2c_bus_cmdline(void)
+{
+	int i, err = 0;
+
+	for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++)
+		if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) {
+			i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
+			err = omap_i2c_add_bus(&i2c_pdata[i], i + 1);
+			if (err)
+				goto out;
+		}
+
+out:
+	return err;
+}
+
+/**
+ * omap_register_i2c_bus - register I2C bus with device descriptors
+ * @bus_id: bus id counting from number 1
+ * @clkrate: clock rate of the bus in kHz
+ * @info: pointer into I2C device descriptor table or NULL
+ * @len: number of descriptors in the table
+ *
+ * Returns 0 on success or an error code.
+ */
+int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
+			  struct i2c_board_info const *info,
+			  unsigned len)
+{
+	int err;
+
+	BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS);
+
+	if (info) {
+		err = i2c_register_board_info(bus_id, info, len);
+		if (err)
+			return err;
+	}
+
+	if (!i2c_pdata[bus_id - 1].clkrate)
+		i2c_pdata[bus_id - 1].clkrate = clkrate;
+
+	i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
+
+	return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id);
+}
+
 static  int __init omap_i2c_cmdline(void)
 {
 	return omap_register_i2c_bus_cmdline();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap1/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mach-omap1/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mach-omap1/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap1/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,32 @@ config ARCH_OMAP16XX
 	select ARCH_OMAP_OTG
 	select CPU_ARM926T
 
+config OMAP_MUX
+	bool "OMAP multiplexing support"
+	depends on ARCH_OMAP
+	default y
+	help
+	  Pin multiplexing support for OMAP boards. If your bootloader
+	  sets the multiplexing correctly, say N. Otherwise, or if unsure,
+	  say Y.
+
+config OMAP_MUX_DEBUG
+	bool "Multiplexing debug output"
+	depends on OMAP_MUX
+	help
+	  Makes the multiplexing functions print out a lot of debug info.
+	  This is useful if you want to find out the correct values of the
+	  multiplexing registers.
+
+config OMAP_MUX_WARNINGS
+	bool "Warn about pins the bootloader didn't set up"
+	depends on OMAP_MUX
+	default y
+	help
+	  Choose Y here to warn whenever driver initialization logic needs
+	  to change the pin multiplexing setup.	 When there are no warnings
+	  printed, it's safe to deselect OMAP_MUX for your product.
+
 comment "OMAP Board Type"
 	depends on ARCH_OMAP1
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/board-flash.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/board-flash.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/board-flash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/board-flash.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,242 +0,0 @@
-/*
- * board-flash.c
- * Modified from mach-omap2/board-3430sdp-flash.c
- *
- * Copyright (C) 2009 Nokia Corporation
- * Copyright (C) 2009 Texas Instruments
- *
- * Vimal Singh <vimalsingh@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/omap-gpmc.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/io.h>
-
-#include <linux/platform_data/mtd-nand-omap2.h>
-#include <linux/platform_data/mtd-onenand-omap2.h>
-
-#include "soc.h"
-#include "common.h"
-#include "board-flash.h"
-
-#define REG_FPGA_REV			0x10
-#define REG_FPGA_DIP_SWITCH_INPUT2	0x60
-#define MAX_SUPPORTED_GPMC_CONFIG	3
-
-#define DEBUG_BASE		0x08000000 /* debug board */
-
-/* various memory sizes */
-#define FLASH_SIZE_SDPV1	SZ_64M	/* NOR flash (64 Meg aligned) */
-#define FLASH_SIZE_SDPV2	SZ_128M	/* NOR flash (256 Meg aligned) */
-
-static struct physmap_flash_data board_nor_data = {
-	.width		= 2,
-};
-
-static struct resource board_nor_resource = {
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device board_nor_device = {
-	.name		= "physmap-flash",
-	.id		= 0,
-	.dev		= {
-			.platform_data = &board_nor_data,
-	},
-	.num_resources	= 1,
-	.resource	= &board_nor_resource,
-};
-
-static void
-__init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
-{
-	int err;
-
-	board_nor_data.parts	= nor_parts;
-	board_nor_data.nr_parts	= nr_parts;
-
-	/* Configure start address and size of NOR device */
-	if (omap_rev() >= OMAP3430_REV_ES1_0) {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV2 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV2 - 1;
-	} else {
-		err = gpmc_cs_request(cs, FLASH_SIZE_SDPV1 - 1,
-				(unsigned long *)&board_nor_resource.start);
-		board_nor_resource.end = board_nor_resource.start
-					+ FLASH_SIZE_SDPV1 - 1;
-	}
-	if (err < 0) {
-		pr_err("NOR: Can't request GPMC CS\n");
-		return;
-	}
-	if (platform_device_register(&board_nor_device) < 0)
-		pr_err("Unable to register NOR device\n");
-}
-
-#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
-static struct omap_onenand_platform_data board_onenand_data = {
-	.dma_channel	= -1,   /* disable DMA in OMAP OneNAND driver */
-};
-
-void
-__init board_onenand_init(struct mtd_partition *onenand_parts,
-				u8 nr_parts, u8 cs)
-{
-	board_onenand_data.cs		= cs;
-	board_onenand_data.parts	= onenand_parts;
-	board_onenand_data.nr_parts	= nr_parts;
-
-	gpmc_onenand_init(&board_onenand_data);
-}
-#endif /* IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) */
-
-#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
-
-/* Note that all values in this struct are in nanoseconds */
-struct gpmc_timings nand_default_timings[1] = {
-	{
-		.sync_clk = 0,
-
-		.cs_on = 0,
-		.cs_rd_off = 36,
-		.cs_wr_off = 36,
-
-		.we_on = 6,
-		.oe_on = 6,
-
-		.adv_on = 6,
-		.adv_rd_off = 24,
-		.adv_wr_off = 36,
-
-		.we_off = 30,
-		.oe_off = 48,
-
-		.access = 54,
-		.rd_cycle = 72,
-		.wr_cycle = 72,
-
-		.wr_access = 30,
-		.wr_data_mux_bus = 0,
-	},
-};
-
-static struct omap_nand_platform_data board_nand_data;
-
-void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
-				int nand_type, struct gpmc_timings *gpmc_t)
-{
-	board_nand_data.cs		= cs;
-	board_nand_data.parts		= nand_parts;
-	board_nand_data.nr_parts	= nr_parts;
-	board_nand_data.devsize		= nand_type;
-
-	board_nand_data.ecc_opt = OMAP_ECC_HAM1_CODE_SW;
-	gpmc_nand_init(&board_nand_data, gpmc_t);
-}
-#endif /* IS_ENABLED(CONFIG_MTD_NAND_OMAP2) */
-
-/**
- * get_gpmc0_type - Reads the FPGA DIP_SWITCH_INPUT_REGISTER2 to get
- * the various cs values.
- */
-static u8 get_gpmc0_type(void)
-{
-	u8 cs = 0;
-	void __iomem *fpga_map_addr;
-
-	fpga_map_addr = ioremap(DEBUG_BASE, 4096);
-	if (!fpga_map_addr)
-		return -ENOMEM;
-
-	if (!(readw_relaxed(fpga_map_addr + REG_FPGA_REV)))
-		/* we dont have an DEBUG FPGA??? */
-		/* Depend on #defines!! default to strata boot return param */
-		goto unmap;
-
-	/* S8-DIP-OFF = 1, S8-DIP-ON = 0 */
-	cs = readw_relaxed(fpga_map_addr + REG_FPGA_DIP_SWITCH_INPUT2) & 0xf;
-
-	/* ES2.0 SDP's onwards 4 dip switches are provided for CS */
-	if (omap_rev() >= OMAP3430_REV_ES1_0)
-		/* change (S8-1:4=DS-2:0) to (S8-4:1=DS-2:0) */
-		cs = ((cs & 8) >> 3) | ((cs & 4) >> 1) |
-			((cs & 2) << 1) | ((cs & 1) << 3);
-	else
-		/* change (S8-1:3=DS-2:0) to (S8-3:1=DS-2:0) */
-		cs = ((cs & 4) >> 2) | (cs & 2) | ((cs & 1) << 2);
-unmap:
-	iounmap(fpga_map_addr);
-	return cs;
-}
-
-/**
- * board_flash_init - Identify devices connected to GPMC and register.
- *
- * @return - void.
- */
-void __init board_flash_init(struct flash_partitions partition_info[],
-			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
-{
-	u8		cs = 0;
-	u8		norcs = GPMC_CS_NUM + 1;
-	u8		nandcs = GPMC_CS_NUM + 1;
-	u8		onenandcs = GPMC_CS_NUM + 1;
-	u8		idx;
-	unsigned char	*config_sel = NULL;
-
-	/* REVISIT: Is this return correct idx for 2430 SDP?
-	 * for which cs configuration matches for 2430 SDP?
-	 */
-	idx = get_gpmc0_type();
-	if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
-		pr_err("%s: Invalid chip select: %d\n", __func__, cs);
-		return;
-	}
-	config_sel = (unsigned char *)(chip_sel_board[idx]);
-
-	while (cs < GPMC_CS_NUM) {
-		switch (config_sel[cs]) {
-		case PDC_NOR:
-			if (norcs > GPMC_CS_NUM)
-				norcs = cs;
-			break;
-		case PDC_NAND:
-			if (nandcs > GPMC_CS_NUM)
-				nandcs = cs;
-			break;
-		case PDC_ONENAND:
-			if (onenandcs > GPMC_CS_NUM)
-				onenandcs = cs;
-			break;
-		}
-		cs++;
-	}
-
-	if (norcs > GPMC_CS_NUM)
-		pr_err("NOR: Unable to find configuration in GPMC\n");
-	else
-		board_nor_init(partition_info[0].parts,
-				partition_info[0].nr_parts, norcs);
-
-	if (onenandcs > GPMC_CS_NUM)
-		pr_err("OneNAND: Unable to find configuration in GPMC\n");
-	else
-		board_onenand_init(partition_info[1].parts,
-					partition_info[1].nr_parts, onenandcs);
-
-	if (nandcs > GPMC_CS_NUM)
-		pr_err("NAND: Unable to find configuration in GPMC\n");
-	else
-		board_nand_init(partition_info[2].parts,
-			partition_info[2].nr_parts, nandcs,
-			nand_type, nand_default_timings);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/board-flash.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/board-flash.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/board-flash.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/board-flash.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- *  board-sdp.h
- *
- *  Information structures for SDP-specific board config data
- *
- *  Copyright (C) 2009 Nokia Corporation
- *  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 version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
-#define PDC_NOR		1
-#define PDC_NAND	2
-#define PDC_ONENAND	3
-#define DBG_MPDB	4
-
-struct flash_partitions {
-	struct mtd_partition *parts;
-	int nr_parts;
-};
-
-#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2) || IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
-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 IS_ENABLED(CONFIG_MTD_NAND_OMAP2)
-extern void board_nand_init(struct mtd_partition *nand_parts,
-		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t);
-extern struct gpmc_timings nand_default_timings[];
-#else
-static inline void board_nand_init(struct mtd_partition *nand_parts,
-		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t)
-{
-}
-#define	nand_default_timings	NULL
-#endif
-
-#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2)
-extern void board_onenand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs);
-#else
-static inline void board_onenand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs)
-{
-}
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/board-generic.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/board-generic.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/board-generic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/board-generic.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,8 +30,6 @@ static const struct of_device_id omap_dt
 
 static void __init omap_generic_init(void)
 {
-	omapdss_early_init_of();
-
 	pdata_quirks_init(omap_dt_match_table);
 
 	omapdss_init_of();
@@ -306,7 +304,7 @@ DT_MACHINE_START(AM43_DT, "Generic AM43
 	.init_late	= am43xx_init_late,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
-	.init_time	= omap4_local_timer_init,
+	.init_time	= omap3_gptimer_timer_init,
 	.dt_compat	= am43_boards_compat,
 	.restart	= omap44xx_restart,
 MACHINE_END
@@ -341,6 +339,7 @@ static const char *const dra72x_boards_c
 	"ti,am5718",
 	"ti,am5716",
 	"ti,dra722",
+	"ti,dra718",
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/clockdomains7xx_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/clockdomains7xx_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/clockdomains7xx_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/clockdomains7xx_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -409,7 +409,7 @@ static struct clockdomain l4sec_7xx_clkd
 	.dep_bit	  = DRA7XX_L4SEC_STATDEP_SHIFT,
 	.wkdep_srcs	  = l4sec_wkup_sleep_deps,
 	.sleepdep_srcs	  = l4sec_wkup_sleep_deps,
-	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
+	.flags		  = CLKDM_CAN_SWSUP,
 };
 
 static struct clockdomain l3main1_7xx_clkdm = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/common-board-devices.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/common-board-devices.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/common-board-devices.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/common-board-devices.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- * common-board-devices.c
- *
- * Copyright (C) 2011 CompuLab, Ltd.
- * Author: Mike Rapoport <mike@compulab.co.il>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/gpio.h>
-#include <linux/spi/spi.h>
-#include <linux/spi/ads7846.h>
-
-#include <linux/platform_data/spi-omap2-mcspi.h>
-
-#include "common.h"
-#include "common-board-devices.h"
-
-#if IS_ENABLED(CONFIG_TOUCHSCREEN_ADS7846)
-static struct omap2_mcspi_device_config ads7846_mcspi_config = {
-	.turbo_mode	= 0,
-};
-
-static struct ads7846_platform_data ads7846_config = {
-	.x_max			= 0x0fff,
-	.y_max			= 0x0fff,
-	.x_plate_ohms		= 180,
-	.pressure_max		= 255,
-	.debounce_max		= 10,
-	.debounce_tol		= 3,
-	.debounce_rep		= 1,
-	.gpio_pendown		= -EINVAL,
-	.keep_vref_on		= 1,
-};
-
-static struct spi_board_info ads7846_spi_board_info __initdata = {
-	.modalias		= "ads7846",
-	.bus_num		= -EINVAL,
-	.chip_select		= 0,
-	.max_speed_hz		= 1500000,
-	.controller_data	= &ads7846_mcspi_config,
-	.irq			= -EINVAL,
-	.platform_data		= &ads7846_config,
-};
-
-void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
-			      struct ads7846_platform_data *board_pdata)
-{
-	struct spi_board_info *spi_bi = &ads7846_spi_board_info;
-	int err;
-
-	/*
-	 * If a board defines get_pendown_state() function, request the pendown
-	 * GPIO and set the GPIO debounce time.
-	 * If a board does not define the get_pendown_state() function, then
-	 * the ads7846 driver will setup the pendown GPIO itself.
-	 */
-	if (board_pdata && board_pdata->get_pendown_state) {
-		err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
-		if (err) {
-			pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
-			return;
-		}
-
-		if (gpio_debounce)
-			gpio_set_debounce(gpio_pendown, gpio_debounce);
-
-		gpio_export(gpio_pendown, 0);
-	}
-
-	spi_bi->bus_num	= bus_num;
-	spi_bi->irq	= gpio_to_irq(gpio_pendown);
-
-	ads7846_config.gpio_pendown = gpio_pendown;
-
-	if (board_pdata) {
-		board_pdata->gpio_pendown = gpio_pendown;
-		board_pdata->gpio_pendown_debounce = gpio_debounce;
-		spi_bi->platform_data = board_pdata;
-	}
-
-	spi_register_board_info(&ads7846_spi_board_info, 1);
-}
-#else
-void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
-			      struct ads7846_platform_data *board_pdata)
-{
-}
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/common-board-devices.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/common-board-devices.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/common-board-devices.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/common-board-devices.h	2017-02-12 16:03:20.000000000 -0500
@@ -3,15 +3,7 @@
 
 #include <sound/tlv320aic3x.h>
 #include <linux/mfd/menelaus.h>
-#include "twl-common.h"
-
-#define NAND_BLOCK_SIZE	SZ_128K
-
-struct mtd_partition;
-struct ads7846_platform_data;
 
-void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
-		       struct ads7846_platform_data *board_pdata);
 void *n8x0_legacy_init(void);
 
 extern struct menelaus_platform_data n8x0_menelaus_platform_data;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/common.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/common.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/common.h	2017-02-12 16:03:20.000000000 -0500
@@ -77,15 +77,6 @@ static inline int omap4_pm_init_early(vo
 }
 #endif
 
-#ifdef CONFIG_OMAP_MUX
-int omap_mux_late_init(void);
-#else
-static inline int omap_mux_late_init(void)
-{
-	return 0;
-}
-#endif
-
 extern void omap2_init_common_infrastructure(void);
 
 extern void omap_init_time(void);
@@ -262,8 +253,6 @@ extern void __iomem *omap4_get_sar_ram_b
 extern void omap4_mpuss_early_init(void);
 extern void omap_do_wfi(void);
 
-extern void omap4_secondary_startup(void);
-extern void omap4460_secondary_startup(void);
 
 #ifdef CONFIG_SMP
 /* Needed for secondary core boot */
@@ -275,16 +264,11 @@ extern void omap4_cpu_die(unsigned int c
 extern int omap4_cpu_kill(unsigned int cpu);
 
 extern const struct smp_operations omap4_smp_ops;
-
-extern void omap5_secondary_startup(void);
-extern void omap5_secondary_hyp_startup(void);
 #endif
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
 extern int omap4_mpuss_init(void);
 extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
-extern int omap4_finish_suspend(unsigned long cpu_state);
-extern void omap4_cpu_resume(void);
 extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
 #else
 static inline int omap4_enter_lowpower(unsigned int cpu,
@@ -305,14 +289,41 @@ static inline int omap4_mpuss_init(void)
 	return 0;
 }
 
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+void omap4_secondary_startup(void);
+void omap4460_secondary_startup(void);
+int omap4_finish_suspend(unsigned long cpu_state);
+void omap4_cpu_resume(void);
+#else
+static inline void omap4_secondary_startup(void)
+{
+}
+
+static inline void omap4460_secondary_startup(void)
+{
+}
 static inline int omap4_finish_suspend(unsigned long cpu_state)
 {
 	return 0;
 }
-
 static inline void omap4_cpu_resume(void)
-{}
+{
+}
+#endif
 
+#if defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX)
+void omap5_secondary_startup(void);
+void omap5_secondary_hyp_startup(void);
+#else
+static inline void omap5_secondary_startup(void)
+{
+}
+
+static inline void omap5_secondary_hyp_startup(void)
+{
+}
 #endif
 
 void pdata_quirks_init(const struct of_device_id *);
@@ -332,7 +343,6 @@ extern int omap_dss_reset(struct omap_hw
 int omap_clk_init(void);
 
 int __init omapdss_init_of(void);
-void __init omapdss_early_init_of(void);
 
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/cpuidle44xx.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/cpuidle44xx.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/cpuidle44xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/cpuidle44xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,7 @@
 #include "common.h"
 #include "pm.h"
 #include "prm.h"
+#include "soc.h"
 #include "clockdomain.h"
 
 #define MAX_CPUS	2
@@ -30,6 +31,7 @@ struct idle_statedata {
 	u32 cpu_state;
 	u32 mpu_logic_state;
 	u32 mpu_state;
+	u32 mpu_state_vote;
 };
 
 static struct idle_statedata omap4_idle_data[] = {
@@ -50,12 +52,26 @@ static struct idle_statedata omap4_idle_
 	},
 };
 
+static struct idle_statedata omap5_idle_data[] = {
+	{
+		.cpu_state = PWRDM_POWER_ON,
+		.mpu_state = PWRDM_POWER_ON,
+		.mpu_logic_state = PWRDM_POWER_ON,
+	},
+	{
+		.cpu_state = PWRDM_POWER_RET,
+		.mpu_state = PWRDM_POWER_RET,
+		.mpu_logic_state = PWRDM_POWER_RET,
+	},
+};
+
 static struct powerdomain *mpu_pd, *cpu_pd[MAX_CPUS];
 static struct clockdomain *cpu_clkdm[MAX_CPUS];
 
 static atomic_t abort_barrier;
 static bool cpu_done[MAX_CPUS];
 static struct idle_statedata *state_ptr = &omap4_idle_data[0];
+static DEFINE_RAW_SPINLOCK(mpu_lock);
 
 /* Private functions */
 
@@ -77,6 +93,32 @@ static int omap_enter_idle_simple(struct
 	return index;
 }
 
+static int omap_enter_idle_smp(struct cpuidle_device *dev,
+			       struct cpuidle_driver *drv,
+			       int index)
+{
+	struct idle_statedata *cx = state_ptr + index;
+	unsigned long flag;
+
+	raw_spin_lock_irqsave(&mpu_lock, flag);
+	cx->mpu_state_vote++;
+	if (cx->mpu_state_vote == num_online_cpus()) {
+		pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
+		omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
+	}
+	raw_spin_unlock_irqrestore(&mpu_lock, flag);
+
+	omap4_enter_lowpower(dev->cpu, cx->cpu_state);
+
+	raw_spin_lock_irqsave(&mpu_lock, flag);
+	if (cx->mpu_state_vote == num_online_cpus())
+		omap_set_pwrdm_state(mpu_pd, PWRDM_POWER_ON);
+	cx->mpu_state_vote--;
+	raw_spin_unlock_irqrestore(&mpu_lock, flag);
+
+	return index;
+}
+
 static int omap_enter_idle_coupled(struct cpuidle_device *dev,
 			struct cpuidle_driver *drv,
 			int index)
@@ -220,6 +262,32 @@ static struct cpuidle_driver omap4_idle_
 	.safe_state_index = 0,
 };
 
+static struct cpuidle_driver omap5_idle_driver = {
+	.name				= "omap5_idle",
+	.owner				= THIS_MODULE,
+	.states = {
+		{
+			/* C1 - CPU0 ON + CPU1 ON + MPU ON */
+			.exit_latency = 2 + 2,
+			.target_residency = 5,
+			.enter = omap_enter_idle_simple,
+			.name = "C1",
+			.desc = "CPUx WFI, MPUSS ON"
+		},
+		{
+			/* C2 - CPU0 RET + CPU1 RET + MPU CSWR */
+			.exit_latency = 48 + 60,
+			.target_residency = 100,
+			.flags = CPUIDLE_FLAG_TIMER_STOP,
+			.enter = omap_enter_idle_smp,
+			.name = "C2",
+			.desc = "CPUx CSWR, MPUSS CSWR",
+		},
+	},
+	.state_count = ARRAY_SIZE(omap5_idle_data),
+	.safe_state_index = 0,
+};
+
 /* Public functions */
 
 /**
@@ -230,6 +298,16 @@ static struct cpuidle_driver omap4_idle_
  */
 int __init omap4_idle_init(void)
 {
+	struct cpuidle_driver *idle_driver;
+
+	if (soc_is_omap54xx()) {
+		state_ptr = &omap5_idle_data[0];
+		idle_driver = &omap5_idle_driver;
+	} else {
+		state_ptr = &omap4_idle_data[0];
+		idle_driver = &omap4_idle_driver;
+	}
+
 	mpu_pd = pwrdm_lookup("mpu_pwrdm");
 	cpu_pd[0] = pwrdm_lookup("cpu0_pwrdm");
 	cpu_pd[1] = pwrdm_lookup("cpu1_pwrdm");
@@ -244,5 +322,5 @@ int __init omap4_idle_init(void)
 	/* Configure the broadcast timer on each cpu */
 	on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
 
-	return cpuidle_register(&omap4_idle_driver, cpu_online_mask);
+	return cpuidle_register(idle_driver, cpu_online_mask);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/devices.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/devices.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/devices.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/devices.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,6 @@
 
 #include "soc.h"
 #include "common.h"
-#include "mux.h"
 #include "control.h"
 #include "display.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/display.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/display.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/display.c	2017-02-12 16:03:20.000000000 -0500
@@ -565,11 +565,6 @@ int omap_dss_reset(struct omap_hwmod *oh
 	return r;
 }
 
-void __init omapdss_early_init_of(void)
-{
-
-}
-
 static const char * const omapdss_compat_names[] __initconst = {
 	"ti,omap2-dss",
 	"ti,omap3-dss",
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/dss-common.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/dss-common.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/dss-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/dss-common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2012 Texas Instruments, Inc..
- * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-/*
- * NOTE: this is a transitional file to help with DT adaptation.
- * This file will be removed when DSS supports DT.
- */
-
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-
-#include <linux/platform_data/omapdss.h>
-#include <video/omap-panel-data.h>
-
-#include "soc.h"
-#include "dss-common.h"
-#include "mux.h"
-#include "display.h"
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/dss-common.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/dss-common.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/dss-common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/dss-common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,13 +0,0 @@
-#ifndef __OMAP_DSS_COMMON__
-#define __OMAP_DSS_COMMON__
-
-/*
- * NOTE: this is a transitional file to help with DT adaptation.
- * This file will be removed when DSS supports DT.
- */
-
-void __init omap4_panda_display_init_of(void);
-void __init omap_4430sdp_display_init_of(void);
-void __init omap3_igep2_display_init_of(void);
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/gpio.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/gpio.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,160 +0,0 @@
-/*
- * OMAP2+ specific gpio initialization
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Author:
- *	Charulatha V <charu@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/gpio.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/of.h>
-#include <linux/platform_data/gpio-omap.h>
-
-#include "soc.h"
-#include "omap_hwmod.h"
-#include "omap_device.h"
-#include "omap-pm.h"
-
-#include "powerdomain.h"
-
-static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused)
-{
-	struct platform_device *pdev;
-	struct omap_gpio_platform_data *pdata;
-	struct omap_gpio_dev_attr *dev_attr;
-	char *name = "omap_gpio";
-	int id;
-	struct powerdomain *pwrdm;
-
-	/*
-	 * extract the device id from name field available in the
-	 * hwmod database and use the same for constructing ids for
-	 * gpio devices.
-	 * CAUTION: Make sure the name in the hwmod database does
-	 * not change. If changed, make corresponding change here
-	 * or make use of static variable mechanism to handle this.
-	 */
-	sscanf(oh->name, "gpio%d", &id);
-
-	pdata = kzalloc(sizeof(struct omap_gpio_platform_data), GFP_KERNEL);
-	if (!pdata) {
-		pr_err("gpio%d: Memory allocation failed\n", id);
-		return -ENOMEM;
-	}
-
-	dev_attr = (struct omap_gpio_dev_attr *)oh->dev_attr;
-	pdata->bank_width = dev_attr->bank_width;
-	pdata->dbck_flag = dev_attr->dbck_flag;
-	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
-	pdata->regs = kzalloc(sizeof(struct omap_gpio_reg_offs), GFP_KERNEL);
-	if (!pdata->regs) {
-		pr_err("gpio%d: Memory allocation failed\n", id);
-		kfree(pdata);
-		return -ENOMEM;
-	}
-
-	switch (oh->class->rev) {
-	case 0:
-		if (id == 1)
-			/* non-wakeup GPIO pins for OMAP2 Bank1 */
-			pdata->non_wakeup_gpios = 0xe203ffc0;
-		else if (id == 2)
-			/* non-wakeup GPIO pins for OMAP2 Bank2 */
-			pdata->non_wakeup_gpios = 0x08700040;
-		/* fall through */
-
-	case 1:
-		pdata->regs->revision = OMAP24XX_GPIO_REVISION;
-		pdata->regs->direction = OMAP24XX_GPIO_OE;
-		pdata->regs->datain = OMAP24XX_GPIO_DATAIN;
-		pdata->regs->dataout = OMAP24XX_GPIO_DATAOUT;
-		pdata->regs->set_dataout = OMAP24XX_GPIO_SETDATAOUT;
-		pdata->regs->clr_dataout = OMAP24XX_GPIO_CLEARDATAOUT;
-		pdata->regs->irqstatus = OMAP24XX_GPIO_IRQSTATUS1;
-		pdata->regs->irqstatus2 = OMAP24XX_GPIO_IRQSTATUS2;
-		pdata->regs->irqenable = OMAP24XX_GPIO_IRQENABLE1;
-		pdata->regs->irqenable2 = OMAP24XX_GPIO_IRQENABLE2;
-		pdata->regs->set_irqenable = OMAP24XX_GPIO_SETIRQENABLE1;
-		pdata->regs->clr_irqenable = OMAP24XX_GPIO_CLEARIRQENABLE1;
-		pdata->regs->debounce = OMAP24XX_GPIO_DEBOUNCE_VAL;
-		pdata->regs->debounce_en = OMAP24XX_GPIO_DEBOUNCE_EN;
-		pdata->regs->ctrl = OMAP24XX_GPIO_CTRL;
-		pdata->regs->wkup_en = OMAP24XX_GPIO_WAKE_EN;
-		pdata->regs->leveldetect0 = OMAP24XX_GPIO_LEVELDETECT0;
-		pdata->regs->leveldetect1 = OMAP24XX_GPIO_LEVELDETECT1;
-		pdata->regs->risingdetect = OMAP24XX_GPIO_RISINGDETECT;
-		pdata->regs->fallingdetect = OMAP24XX_GPIO_FALLINGDETECT;
-		break;
-	case 2:
-		pdata->regs->revision = OMAP4_GPIO_REVISION;
-		pdata->regs->direction = OMAP4_GPIO_OE;
-		pdata->regs->datain = OMAP4_GPIO_DATAIN;
-		pdata->regs->dataout = OMAP4_GPIO_DATAOUT;
-		pdata->regs->set_dataout = OMAP4_GPIO_SETDATAOUT;
-		pdata->regs->clr_dataout = OMAP4_GPIO_CLEARDATAOUT;
-		pdata->regs->irqstatus_raw0 = OMAP4_GPIO_IRQSTATUSRAW0;
-		pdata->regs->irqstatus_raw1 = OMAP4_GPIO_IRQSTATUSRAW1;
-		pdata->regs->irqstatus = OMAP4_GPIO_IRQSTATUS0;
-		pdata->regs->irqstatus2 = OMAP4_GPIO_IRQSTATUS1;
-		pdata->regs->irqenable = OMAP4_GPIO_IRQSTATUSSET0;
-		pdata->regs->irqenable2 = OMAP4_GPIO_IRQSTATUSSET1;
-		pdata->regs->set_irqenable = OMAP4_GPIO_IRQSTATUSSET0;
-		pdata->regs->clr_irqenable = OMAP4_GPIO_IRQSTATUSCLR0;
-		pdata->regs->debounce = OMAP4_GPIO_DEBOUNCINGTIME;
-		pdata->regs->debounce_en = OMAP4_GPIO_DEBOUNCENABLE;
-		pdata->regs->ctrl = OMAP4_GPIO_CTRL;
-		pdata->regs->wkup_en = OMAP4_GPIO_IRQWAKEN0;
-		pdata->regs->leveldetect0 = OMAP4_GPIO_LEVELDETECT0;
-		pdata->regs->leveldetect1 = OMAP4_GPIO_LEVELDETECT1;
-		pdata->regs->risingdetect = OMAP4_GPIO_RISINGDETECT;
-		pdata->regs->fallingdetect = OMAP4_GPIO_FALLINGDETECT;
-		break;
-	default:
-		WARN(1, "Invalid gpio bank_type\n");
-		kfree(pdata->regs);
-		kfree(pdata);
-		return -EINVAL;
-	}
-
-	pwrdm = omap_hwmod_get_pwrdm(oh);
-	pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
-
-	pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata));
-	kfree(pdata);
-
-	if (IS_ERR(pdev)) {
-		WARN(1, "Can't build omap_device for %s:%s.\n",
-					name, oh->name);
-		return PTR_ERR(pdev);
-	}
-
-	return 0;
-}
-
-/*
- * gpio_init needs to be done before
- * machine_init functions access gpio APIs.
- * Hence gpio_init is a omap_postcore_initcall.
- */
-static int __init omap2_gpio_init(void)
-{
-	/* If dtb is there, the devices will be created dynamically */
-	if (of_have_populated_dt())
-		return -ENODEV;
-
-	return omap_hwmod_for_each_by_class("gpio", omap2_gpio_dev_init, NULL);
-}
-omap_postcore_initcall(omap2_gpio_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/gpmc-smsc911x.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/gpmc-smsc911x.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/gpmc-smsc911x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/gpmc-smsc911x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/gpmc-smsc911x.c
- *
- * Copyright (C) 2009 Li-Pro.Net
- * Stephan Linz <linz@li-pro.net>
- *
- * Modified from linux/arch/arm/mach-omap2/gpmc-smc91x.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.
- */
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/smsc911x.h>
-
-#include "gpmc.h"
-#include "gpmc-smsc911x.h"
-
-static struct resource gpmc_smsc911x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
-};
-
-static struct smsc911x_platform_config gpmc_smsc911x_config = {
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
-	.irq_type	= SMSC911X_IRQ_TYPE_OPEN_DRAIN,
-};
-
-/*
- * Initialize smsc911x device connected to the GPMC. Note that we
- * assume that pin multiplexing is done in the board-*.c file,
- * or in the bootloader.
- */
-void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
-{
-	struct platform_device *pdev;
-	unsigned long cs_mem_base;
-	int ret;
-
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		pr_err("Failed to request GPMC mem region\n");
-		return;
-	}
-
-	gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
-	gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
-
-	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) {
-		pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq);
-		goto free1;
-	}
-
-	gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
-
-	if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
-		ret = gpio_request_one(gpmc_cfg->gpio_reset,
-				       GPIOF_OUT_INIT_HIGH, "smsc911x reset");
-		if (ret) {
-			pr_err("Failed to request reset GPIO%d\n",
-			       gpmc_cfg->gpio_reset);
-			goto free2;
-		}
-
-		gpio_set_value(gpmc_cfg->gpio_reset, 0);
-		msleep(100);
-		gpio_set_value(gpmc_cfg->gpio_reset, 1);
-	}
-
-	gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
-
-	pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
-		 gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
-		 &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config));
-	if (IS_ERR(pdev)) {
-		pr_err("Unable to register platform device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free2;
-	}
-
-	return;
-
-free2:
-	gpio_free(gpmc_cfg->gpio_irq);
-free1:
-	gpmc_cs_free(gpmc_cfg->cs);
-
-	pr_err("Could not initialize smsc911x device\n");
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/gpmc-smsc911x.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/gpmc-smsc911x.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/gpmc-smsc911x.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/gpmc-smsc911x.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*
- * arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
- *
- * Copyright (C) 2009 Li-Pro.Net
- * Stephan Linz <linz@li-pro.net>
- *
- * Modified from arch/arm/plat-omap/include/plat/gpmc-smc91x.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_OMAP_GPMC_SMSC911X_H__
-
-struct omap_smsc911x_platform_data {
-	int	id;
-	int	cs;
-	int	gpio_irq;
-	int	gpio_reset;
-	u32	flags;
-};
-
-#if IS_ENABLED(CONFIG_SMSC911X)
-
-extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
-
-#else
-
-static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
-{
-}
-
-#endif
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/hsmmc.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/hsmmc.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/hsmmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/hsmmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
 #include "omap_device.h"
 #include "omap-pm.h"
 
-#include "mux.h"
 #include "hsmmc.h"
 #include "control.h"
 
@@ -147,91 +146,6 @@ static int nop_mmc_set_power(struct devi
 	return 0;
 }
 
-static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data
-				  *mmc_controller, int controller_nr)
-{
-	if (gpio_is_valid(mmc_controller->gpio_cd) &&
-	    (mmc_controller->gpio_cd < OMAP_MAX_GPIO_LINES))
-		omap_mux_init_gpio(mmc_controller->gpio_cd,
-				   OMAP_PIN_INPUT_PULLUP);
-	if (gpio_is_valid(mmc_controller->gpio_cod) &&
-	    (mmc_controller->gpio_cod < OMAP_MAX_GPIO_LINES))
-		omap_mux_init_gpio(mmc_controller->gpio_cod,
-				   OMAP_PIN_INPUT_PULLUP);
-	if (gpio_is_valid(mmc_controller->gpio_wp) &&
-	    (mmc_controller->gpio_wp < OMAP_MAX_GPIO_LINES))
-		omap_mux_init_gpio(mmc_controller->gpio_wp,
-				   OMAP_PIN_INPUT_PULLUP);
-	if (cpu_is_omap34xx()) {
-		if (controller_nr == 0) {
-			omap_mux_init_signal("sdmmc1_clk",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc1_cmd",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc1_dat0",
-				OMAP_PIN_INPUT_PULLUP);
-			if (mmc_controller->caps &
-				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
-				omap_mux_init_signal("sdmmc1_dat1",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat2",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat3",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-			if (mmc_controller->caps &
-						MMC_CAP_8_BIT_DATA) {
-				omap_mux_init_signal("sdmmc1_dat4",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat5",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat6",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat7",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-		}
-		if (controller_nr == 1) {
-			/* MMC2 */
-			omap_mux_init_signal("sdmmc2_clk",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc2_cmd",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc2_dat0",
-				OMAP_PIN_INPUT_PULLUP);
-
-			/*
-			 * For 8 wire configurations, Lines DAT4, 5, 6 and 7
-			 * need to be muxed in the board-*.c files
-			 */
-			if (mmc_controller->caps &
-				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
-				omap_mux_init_signal("sdmmc2_dat1",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat2",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat3",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-			if (mmc_controller->caps &
-							MMC_CAP_8_BIT_DATA) {
-				omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat6.sdmmc2_dat6",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat7.sdmmc2_dat7",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-		}
-
-		/*
-		 * For MMC3 the pins need to be muxed in the board-*.c files
-		 */
-	}
-}
-
 static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
 					struct omap_hsmmc_platform_data *mmc)
 {
@@ -410,8 +324,6 @@ static void __init omap_hsmmc_init_one(s
 	if (res < 0)
 		goto free_mmc;
 
-	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
-
 	name = "omap_hsmmc";
 	res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
 		     "mmc%d", ctrl_nr);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/i2c.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/i2c.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,6 @@
 
 #include "prm.h"
 #include "common.h"
-#include "mux.h"
 #include "i2c.h"
 
 /* In register I2C_CON, Bit 15 is the I2C enable bit */
@@ -36,20 +35,6 @@
 
 #define MAX_OMAP_I2C_HWMOD_NAME_LEN	16
 
-static void __init omap2_i2c_mux_pins(int bus_id)
-{
-	char mux_name[sizeof("i2c2_scl.i2c2_scl")];
-
-	/* First I2C bus is not muxable */
-	if (bus_id == 1)
-		return;
-
-	sprintf(mux_name, "i2c%i_scl.i2c%i_scl", bus_id, bus_id);
-	omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
-	sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id);
-	omap_mux_init_signal(mux_name, OMAP_PIN_INPUT);
-}
-
 /**
  * omap_i2c_reset - reset the omap i2c module.
  * @oh: struct omap_hwmod *
@@ -107,85 +92,3 @@ int omap_i2c_reset(struct omap_hwmod *oh
 
 	return 0;
 }
-
-static int __init omap_i2c_nr_ports(void)
-{
-	int ports = 0;
-
-	if (cpu_is_omap24xx())
-		ports = 2;
-	else if (cpu_is_omap34xx())
-		ports = 3;
-	else if (cpu_is_omap44xx())
-		ports = 4;
-	return ports;
-}
-
-/*
- * XXX This function is a temporary compatibility wrapper - only
- * needed until the I2C driver can be converted to call
- * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
- */
-static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
-{
-	omap_pm_set_max_mpu_wakeup_lat(dev, t);
-}
-
-static const char name[] = "omap_i2c";
-
-int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
-				int bus_id)
-{
-	int l;
-	struct omap_hwmod *oh;
-	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;
-
-	if (bus_id > omap_i2c_nr_ports())
-		return -EINVAL;
-
-	omap2_i2c_mux_pins(bus_id);
-
-	l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id);
-	WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN,
-		"String buffer overflow in I2C%d device setup\n", bus_id);
-	oh = omap_hwmod_lookup(oh_name);
-	if (!oh) {
-			pr_err("Could not look up %s\n", oh_name);
-			return -EEXIST;
-	}
-
-	pdata = i2c_pdata;
-	/*
-	 * 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
-	 * completes.
-	 * Only omap3 has support for constraints
-	 */
-	if (cpu_is_omap34xx())
-		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
-	pdev = omap_device_build(name, bus_id, oh, pdata,
-				 sizeof(struct omap_i2c_bus_platform_data));
-	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
-
-	return PTR_ERR_OR_ZERO(pdev);
-}
-
-static  int __init omap_i2c_cmdline(void)
-{
-	return omap_register_i2c_bus_cmdline();
-}
-omap_subsys_initcall(omap_i2c_cmdline);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/io.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/io.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/io.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/io.c	2017-02-12 16:03:20.000000000 -0500
@@ -427,7 +427,6 @@ static void __init omap_hwmod_init_posts
 
 static void __init __maybe_unused omap_common_late_init(void)
 {
-	omap_mux_late_init();
 	omap2_common_pm_late_init();
 	omap_soc_device_init();
 }
@@ -717,10 +716,11 @@ void __init omap5_init_early(void)
 			      OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE));
 	omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE));
 	omap2_control_base_init();
-	omap4_pm_init_early();
 	omap2_prcm_base_init();
 	omap5xxx_check_revision();
 	omap4_sar_ram_init();
+	omap4_mpuss_early_init();
+	omap4_pm_init_early();
 	omap54xx_voltagedomains_init();
 	omap54xx_powerdomains_init();
 	omap54xx_clockdomains_init();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/Makefile linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/Makefile
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -6,8 +6,8 @@ ccflags-y := -I$(srctree)/$(src)/include
 	-I$(srctree)/arch/arm/plat-omap/include
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o timer.o pm.o \
-	 common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
+obj-y := id.o io.o control.o devices.o fb.o timer.o pm.o \
+	 common.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \
 	 omap_device.o omap-headsmp.o sram.o drm.o
 
 hwmod-common				= omap_hwmod.o omap_hwmod_reset.o \
@@ -63,9 +63,6 @@ obj-$(CONFIG_ARCH_OMAP4)		+= omap4-resta
 obj-$(CONFIG_SOC_OMAP5)			+= omap4-restart.o
 obj-$(CONFIG_SOC_DRA7XX)		+= omap4-restart.o
 
-# Pin multiplexing
-obj-$(CONFIG_ARCH_OMAP3)		+= mux34xx.o
-
 # SMS/SDRC
 obj-$(CONFIG_ARCH_OMAP2)		+= sdrc2xxx.o
 # obj-$(CONFIG_ARCH_OMAP3)		+= sdrc3xxx.o
@@ -80,7 +77,7 @@ endif
 # Power Management
 omap-4-5-pm-common			= omap-mpuss-lowpower.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(omap-4-5-pm-common)
-obj-$(CONFIG_ARCH_OMAP5)		+= $(omap-4-5-pm-common)
+obj-$(CONFIG_SOC_OMAP5)			+= $(omap-4-5-pm-common)
 obj-$(CONFIG_OMAP_PM_NOOP)		+= omap-pm-noop.o
 
 ifeq ($(CONFIG_PM),y)
@@ -235,26 +232,15 @@ obj-$(CONFIG_MACH_NOKIA_N8X0)		+= board-
 
 # 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)
 
-obj-y					+= usb-musb.o
 obj-y					+= omap_phy_internal.o
 
 obj-$(CONFIG_MACH_OMAP2_TUSB6010)	+= usb-tusb6010.o
-obj-y					+= usb-host.o
 
 onenand-$(CONFIG_MTD_ONENAND_OMAP2)	:= gpmc-onenand.o
 obj-y					+= $(onenand-m) $(onenand-y)
 
 nand-$(CONFIG_MTD_NAND_OMAP2)		:= gpmc-nand.o
 obj-y					+= $(nand-m) $(nand-y)
-
-smsc911x-$(CONFIG_SMSC911X)		:= gpmc-smsc911x.o
-obj-y					+= $(smsc911x-m) $(smsc911x-y)
-
-obj-y					+= common-board-devices.o twl-common.o dss-common.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/msdi.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/msdi.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/msdi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/msdi.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,6 @@
 #include "control.h"
 #include "omap_hwmod.h"
 #include "omap_device.h"
-#include "mux.h"
 #include "mmc.h"
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/mux34xx.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux34xx.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/mux34xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux34xx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2061 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia
- * 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include "mux.h"
-
-#ifdef CONFIG_OMAP_MUX
-
-#define _OMAP3_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)		\
-{									\
-	.reg_offset	= (OMAP3_CONTROL_PADCONF_##M0##_OFFSET),	\
-	.gpio		= (g),						\
-	.muxnames	= { m0, m1, m2, m3, m4, m5, m6, m7 },		\
-}
-
-#else
-
-#define _OMAP3_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)		\
-{									\
-	.reg_offset	= (OMAP3_CONTROL_PADCONF_##M0##_OFFSET),	\
-	.gpio		= (g),						\
-}
-
-#endif
-
-#define _OMAP3_BALLENTRY(M0, bb, bt)					\
-{									\
-	.reg_offset	= (OMAP3_CONTROL_PADCONF_##M0##_OFFSET),	\
-	.balls		= { bb, bt },					\
-}
-
-/*
- * Superset of all mux modes for omap3
- */
-static struct omap_mux __initdata omap3_muxmodes[] = {
-	_OMAP3_MUXENTRY(CAM_D0, 99,
-		"cam_d0", NULL, NULL, NULL,
-		"gpio_99", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D1, 100,
-		"cam_d1", NULL, NULL, NULL,
-		"gpio_100", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D10, 109,
-		"cam_d10", NULL, NULL, NULL,
-		"gpio_109", "hw_dbg8", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D11, 110,
-		"cam_d11", NULL, NULL, NULL,
-		"gpio_110", "hw_dbg9", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D2, 101,
-		"cam_d2", NULL, NULL, NULL,
-		"gpio_101", "hw_dbg4", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D3, 102,
-		"cam_d3", NULL, NULL, NULL,
-		"gpio_102", "hw_dbg5", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D4, 103,
-		"cam_d4", NULL, NULL, NULL,
-		"gpio_103", "hw_dbg6", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D5, 104,
-		"cam_d5", NULL, NULL, NULL,
-		"gpio_104", "hw_dbg7", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D6, 105,
-		"cam_d6", NULL, NULL, NULL,
-		"gpio_105", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D7, 106,
-		"cam_d7", NULL, NULL, NULL,
-		"gpio_106", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D8, 107,
-		"cam_d8", NULL, NULL, NULL,
-		"gpio_107", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D9, 108,
-		"cam_d9", NULL, NULL, NULL,
-		"gpio_108", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_FLD, 98,
-		"cam_fld", NULL, "cam_global_reset", NULL,
-		"gpio_98", "hw_dbg3", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_HS, 94,
-		"cam_hs", NULL, NULL, NULL,
-		"gpio_94", "hw_dbg0", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_PCLK, 97,
-		"cam_pclk", NULL, NULL, NULL,
-		"gpio_97", "hw_dbg2", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_STROBE, 126,
-		"cam_strobe", NULL, NULL, NULL,
-		"gpio_126", "hw_dbg11", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_VS, 95,
-		"cam_vs", NULL, NULL, NULL,
-		"gpio_95", "hw_dbg1", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_WEN, 167,
-		"cam_wen", NULL, "cam_shutter", NULL,
-		"gpio_167", "hw_dbg10", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_XCLKA, 96,
-		"cam_xclka", NULL, NULL, NULL,
-		"gpio_96", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_XCLKB, 111,
-		"cam_xclkb", NULL, NULL, NULL,
-		"gpio_111", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CSI2_DX0, 112,
-		"csi2_dx0", NULL, NULL, NULL,
-		"gpio_112", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CSI2_DX1, 114,
-		"csi2_dx1", NULL, NULL, NULL,
-		"gpio_114", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CSI2_DY0, 113,
-		"csi2_dy0", NULL, NULL, NULL,
-		"gpio_113", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CSI2_DY1, 115,
-		"csi2_dy1", NULL, NULL, NULL,
-		"gpio_115", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_ACBIAS, 69,
-		"dss_acbias", NULL, NULL, NULL,
-		"gpio_69", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA0, 70,
-		"dss_data0", NULL, "uart1_cts", NULL,
-		"gpio_70", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA1, 71,
-		"dss_data1", NULL, "uart1_rts", NULL,
-		"gpio_71", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA10, 80,
-		"dss_data10", NULL, NULL, NULL,
-		"gpio_80", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA11, 81,
-		"dss_data11", NULL, NULL, NULL,
-		"gpio_81", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA12, 82,
-		"dss_data12", NULL, NULL, NULL,
-		"gpio_82", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA13, 83,
-		"dss_data13", NULL, NULL, NULL,
-		"gpio_83", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA14, 84,
-		"dss_data14", NULL, NULL, NULL,
-		"gpio_84", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA15, 85,
-		"dss_data15", NULL, NULL, NULL,
-		"gpio_85", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA16, 86,
-		"dss_data16", NULL, NULL, NULL,
-		"gpio_86", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA17, 87,
-		"dss_data17", NULL, NULL, NULL,
-		"gpio_87", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA18, 88,
-		"dss_data18", NULL, "mcspi3_clk", "dss_data0",
-		"gpio_88", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA19, 89,
-		"dss_data19", NULL, "mcspi3_simo", "dss_data1",
-		"gpio_89", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA20, 90,
-		"dss_data20", NULL, "mcspi3_somi", "dss_data2",
-		"gpio_90", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA21, 91,
-		"dss_data21", NULL, "mcspi3_cs0", "dss_data3",
-		"gpio_91", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA22, 92,
-		"dss_data22", NULL, "mcspi3_cs1", "dss_data4",
-		"gpio_92", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA23, 93,
-		"dss_data23", NULL, NULL, "dss_data5",
-		"gpio_93", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA2, 72,
-		"dss_data2", NULL, NULL, NULL,
-		"gpio_72", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA3, 73,
-		"dss_data3", NULL, NULL, NULL,
-		"gpio_73", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA4, 74,
-		"dss_data4", NULL, "uart3_rx_irrx", NULL,
-		"gpio_74", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA5, 75,
-		"dss_data5", NULL, "uart3_tx_irtx", NULL,
-		"gpio_75", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA6, 76,
-		"dss_data6", NULL, "uart1_tx", NULL,
-		"gpio_76", "hw_dbg14", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA7, 77,
-		"dss_data7", NULL, "uart1_rx", NULL,
-		"gpio_77", "hw_dbg15", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA8, 78,
-		"dss_data8", NULL, NULL, NULL,
-		"gpio_78", "hw_dbg16", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA9, 79,
-		"dss_data9", NULL, NULL, NULL,
-		"gpio_79", "hw_dbg17", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_HSYNC, 67,
-		"dss_hsync", NULL, NULL, NULL,
-		"gpio_67", "hw_dbg13", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_PCLK, 66,
-		"dss_pclk", NULL, NULL, NULL,
-		"gpio_66", "hw_dbg12", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_VSYNC, 68,
-		"dss_vsync", NULL, NULL, NULL,
-		"gpio_68", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(ETK_CLK, 12,
-		"etk_clk", "mcbsp5_clkx", "sdmmc3_clk", "hsusb1_stp",
-		"gpio_12", "mm1_rxdp", "hsusb1_tll_stp", "hw_dbg0"),
-	_OMAP3_MUXENTRY(ETK_CTL, 13,
-		"etk_ctl", NULL, "sdmmc3_cmd", "hsusb1_clk",
-		"gpio_13", NULL, "hsusb1_tll_clk", "hw_dbg1"),
-	_OMAP3_MUXENTRY(ETK_D0, 14,
-		"etk_d0", "mcspi3_simo", "sdmmc3_dat4", "hsusb1_data0",
-		"gpio_14", "mm1_rxrcv", "hsusb1_tll_data0", "hw_dbg2"),
-	_OMAP3_MUXENTRY(ETK_D1, 15,
-		"etk_d1", "mcspi3_somi", NULL, "hsusb1_data1",
-		"gpio_15", "mm1_txse0", "hsusb1_tll_data1", "hw_dbg3"),
-	_OMAP3_MUXENTRY(ETK_D10, 24,
-		"etk_d10", NULL, "uart1_rx", "hsusb2_clk",
-		"gpio_24", NULL, "hsusb2_tll_clk", "hw_dbg12"),
-	_OMAP3_MUXENTRY(ETK_D11, 25,
-		"etk_d11", NULL, NULL, "hsusb2_stp",
-		"gpio_25", "mm2_rxdp", "hsusb2_tll_stp", "hw_dbg13"),
-	_OMAP3_MUXENTRY(ETK_D12, 26,
-		"etk_d12", NULL, NULL, "hsusb2_dir",
-		"gpio_26", NULL, "hsusb2_tll_dir", "hw_dbg14"),
-	_OMAP3_MUXENTRY(ETK_D13, 27,
-		"etk_d13", NULL, NULL, "hsusb2_nxt",
-		"gpio_27", "mm2_rxdm", "hsusb2_tll_nxt", "hw_dbg15"),
-	_OMAP3_MUXENTRY(ETK_D14, 28,
-		"etk_d14", NULL, NULL, "hsusb2_data0",
-		"gpio_28", "mm2_rxrcv", "hsusb2_tll_data0", "hw_dbg16"),
-	_OMAP3_MUXENTRY(ETK_D15, 29,
-		"etk_d15", NULL, NULL, "hsusb2_data1",
-		"gpio_29", "mm2_txse0", "hsusb2_tll_data1", "hw_dbg17"),
-	_OMAP3_MUXENTRY(ETK_D2, 16,
-		"etk_d2", "mcspi3_cs0", NULL, "hsusb1_data2",
-		"gpio_16", "mm1_txdat", "hsusb1_tll_data2", "hw_dbg4"),
-	_OMAP3_MUXENTRY(ETK_D3, 17,
-		"etk_d3", "mcspi3_clk", "sdmmc3_dat3", "hsusb1_data7",
-		"gpio_17", NULL, "hsusb1_tll_data7", "hw_dbg5"),
-	_OMAP3_MUXENTRY(ETK_D4, 18,
-		"etk_d4", "mcbsp5_dr", "sdmmc3_dat0", "hsusb1_data4",
-		"gpio_18", NULL, "hsusb1_tll_data4", "hw_dbg6"),
-	_OMAP3_MUXENTRY(ETK_D5, 19,
-		"etk_d5", "mcbsp5_fsx", "sdmmc3_dat1", "hsusb1_data5",
-		"gpio_19", NULL, "hsusb1_tll_data5", "hw_dbg7"),
-	_OMAP3_MUXENTRY(ETK_D6, 20,
-		"etk_d6", "mcbsp5_dx", "sdmmc3_dat2", "hsusb1_data6",
-		"gpio_20", NULL, "hsusb1_tll_data6", "hw_dbg8"),
-	_OMAP3_MUXENTRY(ETK_D7, 21,
-		"etk_d7", "mcspi3_cs1", "sdmmc3_dat7", "hsusb1_data3",
-		"gpio_21", "mm1_txen_n", "hsusb1_tll_data3", "hw_dbg9"),
-	_OMAP3_MUXENTRY(ETK_D8, 22,
-		"etk_d8", "sys_drm_msecure", "sdmmc3_dat6", "hsusb1_dir",
-		"gpio_22", NULL, "hsusb1_tll_dir", "hw_dbg10"),
-	_OMAP3_MUXENTRY(ETK_D9, 23,
-		"etk_d9", "sys_secure_indicator", "sdmmc3_dat5", "hsusb1_nxt",
-		"gpio_23", "mm1_rxdm", "hsusb1_tll_nxt", "hw_dbg11"),
-	_OMAP3_MUXENTRY(GPMC_A1, 34,
-		"gpmc_a1", NULL, NULL, NULL,
-		"gpio_34", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A10, 43,
-		"gpmc_a10", "sys_ndmareq3", NULL, NULL,
-		"gpio_43", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A2, 35,
-		"gpmc_a2", NULL, NULL, NULL,
-		"gpio_35", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A3, 36,
-		"gpmc_a3", NULL, NULL, NULL,
-		"gpio_36", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A4, 37,
-		"gpmc_a4", NULL, NULL, NULL,
-		"gpio_37", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A5, 38,
-		"gpmc_a5", NULL, NULL, NULL,
-		"gpio_38", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A6, 39,
-		"gpmc_a6", NULL, NULL, NULL,
-		"gpio_39", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A7, 40,
-		"gpmc_a7", NULL, NULL, NULL,
-		"gpio_40", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A8, 41,
-		"gpmc_a8", NULL, NULL, NULL,
-		"gpio_41", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_A9, 42,
-		"gpmc_a9", "sys_ndmareq2", NULL, NULL,
-		"gpio_42", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_CLK, 59,
-		"gpmc_clk", NULL, NULL, NULL,
-		"gpio_59", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D10, 46,
-		"gpmc_d10", NULL, NULL, NULL,
-		"gpio_46", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D11, 47,
-		"gpmc_d11", NULL, NULL, NULL,
-		"gpio_47", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D12, 48,
-		"gpmc_d12", NULL, NULL, NULL,
-		"gpio_48", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D13, 49,
-		"gpmc_d13", NULL, NULL, NULL,
-		"gpio_49", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D14, 50,
-		"gpmc_d14", NULL, NULL, NULL,
-		"gpio_50", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D15, 51,
-		"gpmc_d15", NULL, NULL, NULL,
-		"gpio_51", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D8, 44,
-		"gpmc_d8", NULL, NULL, NULL,
-		"gpio_44", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_D9, 45,
-		"gpmc_d9", NULL, NULL, NULL,
-		"gpio_45", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NBE0_CLE, 60,
-		"gpmc_nbe0_cle", NULL, NULL, NULL,
-		"gpio_60", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NBE1, 61,
-		"gpmc_nbe1", NULL, NULL, NULL,
-		"gpio_61", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NCS1, 52,
-		"gpmc_ncs1", NULL, NULL, NULL,
-		"gpio_52", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NCS2, 53,
-		"gpmc_ncs2", NULL, NULL, NULL,
-		"gpio_53", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NCS3, 54,
-		"gpmc_ncs3", "sys_ndmareq0", NULL, NULL,
-		"gpio_54", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NCS4, 55,
-		"gpmc_ncs4", "sys_ndmareq1", "mcbsp4_clkx", "gpt9_pwm_evt",
-		"gpio_55", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NCS5, 56,
-		"gpmc_ncs5", "sys_ndmareq2", "mcbsp4_dr", "gpt10_pwm_evt",
-		"gpio_56", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NCS6, 57,
-		"gpmc_ncs6", "sys_ndmareq3", "mcbsp4_dx", "gpt11_pwm_evt",
-		"gpio_57", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NCS7, 58,
-		"gpmc_ncs7", "gpmc_io_dir", "mcbsp4_fsx", "gpt8_pwm_evt",
-		"gpio_58", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_NWP, 62,
-		"gpmc_nwp", NULL, NULL, NULL,
-		"gpio_62", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_WAIT1, 63,
-		"gpmc_wait1", NULL, NULL, NULL,
-		"gpio_63", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_WAIT2, 64,
-		"gpmc_wait2", NULL, NULL, NULL,
-		"gpio_64", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_WAIT3, 65,
-		"gpmc_wait3", "sys_ndmareq1", NULL, NULL,
-		"gpio_65", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HDQ_SIO, 170,
-		"hdq_sio", "sys_altclk", "i2c2_sccbe", "i2c3_sccbe",
-		"gpio_170", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_CLK, 120,
-		"hsusb0_clk", NULL, NULL, NULL,
-		"gpio_120", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA0, 125,
-		"hsusb0_data0", NULL, "uart3_tx_irtx", NULL,
-		"gpio_125", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA1, 130,
-		"hsusb0_data1", NULL, "uart3_rx_irrx", NULL,
-		"gpio_130", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA2, 131,
-		"hsusb0_data2", NULL, "uart3_rts_sd", NULL,
-		"gpio_131", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA3, 169,
-		"hsusb0_data3", NULL, "uart3_cts_rctx", NULL,
-		"gpio_169", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA4, 188,
-		"hsusb0_data4", NULL, NULL, NULL,
-		"gpio_188", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA5, 189,
-		"hsusb0_data5", NULL, NULL, NULL,
-		"gpio_189", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA6, 190,
-		"hsusb0_data6", NULL, NULL, NULL,
-		"gpio_190", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA7, 191,
-		"hsusb0_data7", NULL, NULL, NULL,
-		"gpio_191", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DIR, 122,
-		"hsusb0_dir", NULL, NULL, NULL,
-		"gpio_122", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_NXT, 124,
-		"hsusb0_nxt", NULL, NULL, NULL,
-		"gpio_124", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_STP, 121,
-		"hsusb0_stp", NULL, NULL, NULL,
-		"gpio_121", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(I2C2_SCL, 168,
-		"i2c2_scl", NULL, NULL, NULL,
-		"gpio_168", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(I2C2_SDA, 183,
-		"i2c2_sda", NULL, NULL, NULL,
-		"gpio_183", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(I2C3_SCL, 184,
-		"i2c3_scl", NULL, NULL, NULL,
-		"gpio_184", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(I2C3_SDA, 185,
-		"i2c3_sda", NULL, NULL, NULL,
-		"gpio_185", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(I2C4_SCL, 0,
-		"i2c4_scl", "sys_nvmode1", NULL, NULL,
-		NULL, NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(I2C4_SDA, 0,
-		"i2c4_sda", "sys_nvmode2", NULL, NULL,
-		NULL, NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(JTAG_EMU0, 11,
-		"jtag_emu0", NULL, NULL, NULL,
-		"gpio_11", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(JTAG_EMU1, 31,
-		"jtag_emu1", NULL, NULL, NULL,
-		"gpio_31", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_CLKR, 156,
-		"mcbsp1_clkr", "mcspi4_clk", NULL, NULL,
-		"gpio_156", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_CLKX, 162,
-		"mcbsp1_clkx", NULL, "mcbsp3_clkx", NULL,
-		"gpio_162", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_DR, 159,
-		"mcbsp1_dr", "mcspi4_somi", "mcbsp3_dr", NULL,
-		"gpio_159", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_DX, 158,
-		"mcbsp1_dx", "mcspi4_simo", "mcbsp3_dx", NULL,
-		"gpio_158", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_FSR, 157,
-		"mcbsp1_fsr", NULL, "cam_global_reset", NULL,
-		"gpio_157", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_FSX, 161,
-		"mcbsp1_fsx", "mcspi4_cs0", "mcbsp3_fsx", NULL,
-		"gpio_161", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP2_CLKX, 117,
-		"mcbsp2_clkx", NULL, NULL, NULL,
-		"gpio_117", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP2_DR, 118,
-		"mcbsp2_dr", NULL, NULL, NULL,
-		"gpio_118", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP2_DX, 119,
-		"mcbsp2_dx", NULL, NULL, NULL,
-		"gpio_119", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP2_FSX, 116,
-		"mcbsp2_fsx", NULL, NULL, NULL,
-		"gpio_116", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP3_CLKX, 142,
-		"mcbsp3_clkx", "uart2_tx", NULL, NULL,
-		"gpio_142", "hsusb3_tll_data6", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP3_DR, 141,
-		"mcbsp3_dr", "uart2_rts", NULL, NULL,
-		"gpio_141", "hsusb3_tll_data5", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP3_DX, 140,
-		"mcbsp3_dx", "uart2_cts", NULL, NULL,
-		"gpio_140", "hsusb3_tll_data4", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP3_FSX, 143,
-		"mcbsp3_fsx", "uart2_rx", NULL, NULL,
-		"gpio_143", "hsusb3_tll_data7", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_CLKX, 152,
-		"mcbsp4_clkx", NULL, NULL, NULL,
-		"gpio_152", "hsusb3_tll_data1", "mm3_txse0", "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_DR, 153,
-		"mcbsp4_dr", NULL, NULL, NULL,
-		"gpio_153", "hsusb3_tll_data0", "mm3_rxrcv", "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_DX, 154,
-		"mcbsp4_dx", NULL, NULL, NULL,
-		"gpio_154", "hsusb3_tll_data2", "mm3_txdat", "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_FSX, 155,
-		"mcbsp4_fsx", NULL, NULL, NULL,
-		"gpio_155", "hsusb3_tll_data3", "mm3_txen_n", "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP_CLKS, 160,
-		"mcbsp_clks", NULL, "cam_shutter", NULL,
-		"gpio_160", "uart1_cts", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_CLK, 171,
-		"mcspi1_clk", "sdmmc2_dat4", NULL, NULL,
-		"gpio_171", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_CS0, 174,
-		"mcspi1_cs0", "sdmmc2_dat7", NULL, NULL,
-		"gpio_174", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_CS1, 175,
-		"mcspi1_cs1", NULL, NULL, "sdmmc3_cmd",
-		"gpio_175", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_CS2, 176,
-		"mcspi1_cs2", NULL, NULL, "sdmmc3_clk",
-		"gpio_176", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_CS3, 177,
-		"mcspi1_cs3", NULL, "hsusb2_tll_data2", "hsusb2_data2",
-		"gpio_177", "mm2_txdat", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_SIMO, 172,
-		"mcspi1_simo", "sdmmc2_dat5", NULL, NULL,
-		"gpio_172", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_SOMI, 173,
-		"mcspi1_somi", "sdmmc2_dat6", NULL, NULL,
-		"gpio_173", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI2_CLK, 178,
-		"mcspi2_clk", NULL, "hsusb2_tll_data7", "hsusb2_data7",
-		"gpio_178", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI2_CS0, 181,
-		"mcspi2_cs0", "gpt11_pwm_evt",
-		"hsusb2_tll_data6", "hsusb2_data6",
-		"gpio_181", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI2_CS1, 182,
-		"mcspi2_cs1", "gpt8_pwm_evt",
-		"hsusb2_tll_data3", "hsusb2_data3",
-		"gpio_182", "mm2_txen_n", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI2_SIMO, 179,
-		"mcspi2_simo", "gpt9_pwm_evt",
-		"hsusb2_tll_data4", "hsusb2_data4",
-		"gpio_179", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI2_SOMI, 180,
-		"mcspi2_somi", "gpt10_pwm_evt",
-		"hsusb2_tll_data5", "hsusb2_data5",
-		"gpio_180", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_CLK, 120,
-		"sdmmc1_clk", NULL, NULL, NULL,
-		"gpio_120", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_CMD, 121,
-		"sdmmc1_cmd", NULL, NULL, NULL,
-		"gpio_121", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT0, 122,
-		"sdmmc1_dat0", NULL, NULL, NULL,
-		"gpio_122", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT1, 123,
-		"sdmmc1_dat1", NULL, NULL, NULL,
-		"gpio_123", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT2, 124,
-		"sdmmc1_dat2", NULL, NULL, NULL,
-		"gpio_124", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT3, 125,
-		"sdmmc1_dat3", NULL, NULL, NULL,
-		"gpio_125", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT4, 126,
-		"sdmmc1_dat4", NULL, "sim_io", NULL,
-		"gpio_126", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT5, 127,
-		"sdmmc1_dat5", NULL, "sim_clk", NULL,
-		"gpio_127", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT6, 128,
-		"sdmmc1_dat6", NULL, "sim_pwrctrl", NULL,
-		"gpio_128", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT7, 129,
-		"sdmmc1_dat7", NULL, "sim_rst", NULL,
-		"gpio_129", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_CLK, 130,
-		"sdmmc2_clk", "mcspi3_clk", NULL, NULL,
-		"gpio_130", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_CMD, 131,
-		"sdmmc2_cmd", "mcspi3_simo", NULL, NULL,
-		"gpio_131", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT0, 132,
-		"sdmmc2_dat0", "mcspi3_somi", NULL, NULL,
-		"gpio_132", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT1, 133,
-		"sdmmc2_dat1", NULL, NULL, NULL,
-		"gpio_133", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT2, 134,
-		"sdmmc2_dat2", "mcspi3_cs1", NULL, NULL,
-		"gpio_134", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT3, 135,
-		"sdmmc2_dat3", "mcspi3_cs0", NULL, NULL,
-		"gpio_135", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT4, 136,
-		"sdmmc2_dat4", "sdmmc2_dir_dat0", NULL, "sdmmc3_dat0",
-		"gpio_136", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT5, 137,
-		"sdmmc2_dat5", "sdmmc2_dir_dat1",
-		"cam_global_reset", "sdmmc3_dat1",
-		"gpio_137", "hsusb3_tll_stp", "mm3_rxdp", "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT6, 138,
-		"sdmmc2_dat6", "sdmmc2_dir_cmd", "cam_shutter", "sdmmc3_dat2",
-		"gpio_138", "hsusb3_tll_dir", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT7, 139,
-		"sdmmc2_dat7", "sdmmc2_clkin", NULL, "sdmmc3_dat3",
-		"gpio_139", "hsusb3_tll_nxt", "mm3_rxdm", "safe_mode"),
-	_OMAP3_MUXENTRY(SDRC_CKE0, 0,
-		"sdrc_cke0", NULL, NULL, NULL,
-		NULL, NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDRC_CKE1, 0,
-		"sdrc_cke1", NULL, NULL, NULL,
-		NULL, NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT0, 2,
-		"sys_boot0", NULL, NULL, NULL,
-		"gpio_2", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT1, 3,
-		"sys_boot1", NULL, NULL, NULL,
-		"gpio_3", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT2, 4,
-		"sys_boot2", NULL, NULL, NULL,
-		"gpio_4", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT3, 5,
-		"sys_boot3", NULL, NULL, NULL,
-		"gpio_5", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT4, 6,
-		"sys_boot4", "sdmmc2_dir_dat2", NULL, NULL,
-		"gpio_6", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT5, 7,
-		"sys_boot5", "sdmmc2_dir_dat3", NULL, NULL,
-		"gpio_7", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT6, 8,
-		"sys_boot6", NULL, NULL, NULL,
-		"gpio_8", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_CLKOUT1, 10,
-		"sys_clkout1", NULL, NULL, NULL,
-		"gpio_10", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_CLKOUT2, 186,
-		"sys_clkout2", NULL, NULL, NULL,
-		"gpio_186", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_CLKREQ, 1,
-		"sys_clkreq", NULL, NULL, NULL,
-		"gpio_1", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_NIRQ, 0,
-		"sys_nirq", NULL, NULL, NULL,
-		"gpio_0", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_NRESWARM, 30,
-		"sys_nreswarm", NULL, NULL, NULL,
-		"gpio_30", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_OFF_MODE, 9,
-		"sys_off_mode", NULL, NULL, NULL,
-		"gpio_9", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_CTS, 150,
-		"uart1_cts", "ssi1_rdy_tx", NULL, NULL,
-		"gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_RTS, 149,
-		"uart1_rts", "ssi1_flag_tx", NULL, NULL,
-		"gpio_149", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_RX, 151,
-		"uart1_rx", "ssi1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",
-		"gpio_151", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_TX, 148,
-		"uart1_tx", "ssi1_dat_tx", NULL, NULL,
-		"gpio_148", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART2_CTS, 144,
-		"uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL,
-		"gpio_144", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART2_RTS, 145,
-		"uart2_rts", "mcbsp3_dr", "gpt10_pwm_evt", NULL,
-		"gpio_145", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART2_RX, 147,
-		"uart2_rx", "mcbsp3_fsx", "gpt8_pwm_evt", NULL,
-		"gpio_147", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART2_TX, 146,
-		"uart2_tx", "mcbsp3_clkx", "gpt11_pwm_evt", NULL,
-		"gpio_146", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART3_CTS_RCTX, 163,
-		"uart3_cts_rctx", NULL, NULL, NULL,
-		"gpio_163", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART3_RTS_SD, 164,
-		"uart3_rts_sd", NULL, NULL, NULL,
-		"gpio_164", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART3_RX_IRRX, 165,
-		"uart3_rx_irrx", NULL, NULL, NULL,
-		"gpio_165", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART3_TX_IRTX, 166,
-		"uart3_tx_irtx", NULL, NULL, NULL,
-		"gpio_166", NULL, NULL, "safe_mode"),
-
-	/* Only on 3630, see omap36xx_cbp_subset for the signals */
-	_OMAP3_MUXENTRY(GPMC_A11, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MBUSFLAG, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MREAD, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MWRITE, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_SBUSFLAG, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_SREAD, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_SWRITE, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(GPMC_A11, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD28, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD29, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD32, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD33, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD34, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD35, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD36, 0,
-		NULL, NULL, NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-
-/*
- * Signals different on CBC package compared to the superset
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBC)
-static struct omap_mux __initdata omap3_cbc_subset[] = {
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap3_cbc_subset	NULL
-#endif
-
-/*
- * Balls for CBC package
- * 515-pin s-PBGA Package, 0.65mm Ball Pitch (Top), 0.50mm Ball Pitch (Bottom)
- *
- * FIXME: What's up with the outdated TI documentation? See:
- *
- * http://wiki.davincidsp.com/index.php/Datasheet_Errata_for_OMAP35x_CBC_Package
- * http://community.ti.com/forums/t/10982.aspx
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)	\
-		&& defined(CONFIG_OMAP_PACKAGE_CBC)
-static struct omap_ball __initdata omap3_cbc_ball[] = {
-	_OMAP3_BALLENTRY(CAM_D0, "ae16", NULL),
-	_OMAP3_BALLENTRY(CAM_D1, "ae15", NULL),
-	_OMAP3_BALLENTRY(CAM_D10, "d25", NULL),
-	_OMAP3_BALLENTRY(CAM_D11, "e26", NULL),
-	_OMAP3_BALLENTRY(CAM_D2, "a24", NULL),
-	_OMAP3_BALLENTRY(CAM_D3, "b24", NULL),
-	_OMAP3_BALLENTRY(CAM_D4, "d24", NULL),
-	_OMAP3_BALLENTRY(CAM_D5, "c24", NULL),
-	_OMAP3_BALLENTRY(CAM_D6, "p25", NULL),
-	_OMAP3_BALLENTRY(CAM_D7, "p26", NULL),
-	_OMAP3_BALLENTRY(CAM_D8, "n25", NULL),
-	_OMAP3_BALLENTRY(CAM_D9, "n26", NULL),
-	_OMAP3_BALLENTRY(CAM_FLD, "b23", NULL),
-	_OMAP3_BALLENTRY(CAM_HS, "c23", NULL),
-	_OMAP3_BALLENTRY(CAM_PCLK, "c26", NULL),
-	_OMAP3_BALLENTRY(CAM_STROBE, "d26", NULL),
-	_OMAP3_BALLENTRY(CAM_VS, "d23", NULL),
-	_OMAP3_BALLENTRY(CAM_WEN, "a23", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKA, "c25", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKB, "e25", NULL),
-	_OMAP3_BALLENTRY(CSI2_DX0, "ad17", NULL),
-	_OMAP3_BALLENTRY(CSI2_DX1, "ae18", NULL),
-	_OMAP3_BALLENTRY(CSI2_DY0, "ad16", NULL),
-	_OMAP3_BALLENTRY(CSI2_DY1, "ae17", NULL),
-	_OMAP3_BALLENTRY(DSS_ACBIAS, "f26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA0, "ae21", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA1, "ae22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA10, "ac26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA11, "ad26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA12, "aa25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA13, "y25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA14, "aa26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA15, "ab26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA16, "l25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA17, "l26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA18, "m24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA19, "m26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA2, "ae23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA20, "f25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA21, "n24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA22, "ac25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA23, "ab25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA3, "ae24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA4, "ad23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA5, "ad24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA6, "g26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA7, "h25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA8, "h26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA9, "j26", NULL),
-	_OMAP3_BALLENTRY(DSS_HSYNC, "k24", NULL),
-	_OMAP3_BALLENTRY(DSS_PCLK, "g25", NULL),
-	_OMAP3_BALLENTRY(DSS_VSYNC, "m25", NULL),
-	_OMAP3_BALLENTRY(ETK_CLK, "ab2", NULL),
-	_OMAP3_BALLENTRY(ETK_CTL, "ab3", NULL),
-	_OMAP3_BALLENTRY(ETK_D0, "ac3", NULL),
-	_OMAP3_BALLENTRY(ETK_D1, "ad4", NULL),
-	_OMAP3_BALLENTRY(ETK_D10, "ae4", NULL),
-	_OMAP3_BALLENTRY(ETK_D11, "af6", NULL),
-	_OMAP3_BALLENTRY(ETK_D12, "ae6", NULL),
-	_OMAP3_BALLENTRY(ETK_D13, "af7", NULL),
-	_OMAP3_BALLENTRY(ETK_D14, "af9", NULL),
-	_OMAP3_BALLENTRY(ETK_D15, "ae9", NULL),
-	_OMAP3_BALLENTRY(ETK_D2, "ad3", NULL),
-	_OMAP3_BALLENTRY(ETK_D3, "aa3", NULL),
-	_OMAP3_BALLENTRY(ETK_D4, "y3", NULL),
-	_OMAP3_BALLENTRY(ETK_D5, "ab1", NULL),
-	_OMAP3_BALLENTRY(ETK_D6, "ae3", NULL),
-	_OMAP3_BALLENTRY(ETK_D7, "ad2", NULL),
-	_OMAP3_BALLENTRY(ETK_D8, "aa4", NULL),
-	_OMAP3_BALLENTRY(ETK_D9, "v2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A1, "j2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A10, "d2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A2, "h1", NULL),
-	_OMAP3_BALLENTRY(GPMC_A3, "h2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A4, "g2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A5, "f1", NULL),
-	_OMAP3_BALLENTRY(GPMC_A6, "f2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A7, "e1", NULL),
-	_OMAP3_BALLENTRY(GPMC_A8, "e2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A9, "d1", NULL),
-	_OMAP3_BALLENTRY(GPMC_CLK, "n1", "l1"),
-	_OMAP3_BALLENTRY(GPMC_D10, "t1", "n1"),
-	_OMAP3_BALLENTRY(GPMC_D11, "u2", "p2"),
-	_OMAP3_BALLENTRY(GPMC_D12, "u1", "p1"),
-	_OMAP3_BALLENTRY(GPMC_D13, "p1", "m1"),
-	_OMAP3_BALLENTRY(GPMC_D14, "l2", "j2"),
-	_OMAP3_BALLENTRY(GPMC_D15, "m2", "k2"),
-	_OMAP3_BALLENTRY(GPMC_D8, "v1", "r1"),
-	_OMAP3_BALLENTRY(GPMC_D9, "y1", "t1"),
-	_OMAP3_BALLENTRY(GPMC_NBE0_CLE, "k2", NULL),
-	_OMAP3_BALLENTRY(GPMC_NBE1, "j1", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS1, "ad1", "w1"),
-	_OMAP3_BALLENTRY(GPMC_NCS2, "a3", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS3, "b6", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS4, "b4", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS5, "c4", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS6, "b5", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS7, "c5", NULL),
-	_OMAP3_BALLENTRY(GPMC_NWP, "ac6", "y5"),
-	_OMAP3_BALLENTRY(GPMC_WAIT1, "ac8", "y8"),
-	_OMAP3_BALLENTRY(GPMC_WAIT2, "b3", NULL),
-	_OMAP3_BALLENTRY(GPMC_WAIT3, "c6", NULL),
-	_OMAP3_BALLENTRY(HDQ_SIO, "j23", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_CLK, "w19", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA0, "v20", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA1, "y20", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA2, "v18", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA3, "w20", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA4, "w17", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA5, "y18", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA6, "y19", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA7, "y17", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DIR, "v19", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_NXT, "w18", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_STP, "u20", NULL),
-	_OMAP3_BALLENTRY(I2C2_SCL, "c2", NULL),
-	_OMAP3_BALLENTRY(I2C2_SDA, "c1", NULL),
-	_OMAP3_BALLENTRY(I2C3_SCL, "ab4", NULL),
-	_OMAP3_BALLENTRY(I2C3_SDA, "ac4", NULL),
-	_OMAP3_BALLENTRY(I2C4_SCL, "ad15", NULL),
-	_OMAP3_BALLENTRY(I2C4_SDA, "w16", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU0, "y15", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU1, "y14", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKR, "u19", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKX, "t17", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DR, "t20", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DX, "u17", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSR, "v17", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSX, "p20", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_CLKX, "r18", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DR, "t18", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DX, "r19", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_FSX, "u18", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_CLKX, "u3", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DR, "n3", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DX, "p3", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_FSX, "w3", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_CLKX, "v3", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_DR, "u4", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_DX, "r3", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_FSX, "t3", NULL),
-	_OMAP3_BALLENTRY(MCBSP_CLKS, "t19", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CLK, "p9", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS0, "r7", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS1, "r8", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS2, "r9", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS3, "t8", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SIMO, "p8", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SOMI, "p7", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CLK, "w7", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS0, "v8", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS1, "v9", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SIMO, "w8", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SOMI, "u8", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CLK, "n19", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CMD, "l18", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT0, "m19", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT1, "m18", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT2, "k18", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT3, "n20", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT4, "m20", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT5, "p17", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT6, "p18", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT7, "p19", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CLK, "w10", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CMD, "r10", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT0, "t10", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT1, "t9", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT2, "u10", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT3, "u9", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT4, "v10", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT5, "m3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT6, "l3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT7, "k3", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT0, "f3", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT1, "d3", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT2, "c3", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT3, "e3", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT4, "e4", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT5, "g3", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT6, "d4", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT1, "ae14", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT2, "w11", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKREQ, "w15", NULL),
-	_OMAP3_BALLENTRY(SYS_NIRQ, "v16", NULL),
-	_OMAP3_BALLENTRY(SYS_NRESWARM, "ad7", "aa5"),
-	_OMAP3_BALLENTRY(SYS_OFF_MODE, "v12", NULL),
-	_OMAP3_BALLENTRY(UART1_CTS, "w2", NULL),
-	_OMAP3_BALLENTRY(UART1_RTS, "r2", NULL),
-	_OMAP3_BALLENTRY(UART1_RX, "h3", NULL),
-	_OMAP3_BALLENTRY(UART1_TX, "l4", NULL),
-	_OMAP3_BALLENTRY(UART2_CTS, "y24", NULL),
-	_OMAP3_BALLENTRY(UART2_RTS, "aa24", NULL),
-	_OMAP3_BALLENTRY(UART2_RX, "ad21", NULL),
-	_OMAP3_BALLENTRY(UART2_TX, "ad22", NULL),
-	_OMAP3_BALLENTRY(UART3_CTS_RCTX, "f23", NULL),
-	_OMAP3_BALLENTRY(UART3_RTS_SD, "f24", NULL),
-	_OMAP3_BALLENTRY(UART3_RX_IRRX, "h24", NULL),
-	_OMAP3_BALLENTRY(UART3_TX_IRTX, "g24", NULL),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap3_cbc_ball	 NULL
-#endif
-
-/*
- * Signals different on CUS package compared to superset
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CUS)
-static struct omap_mux __initdata omap3_cus_subset[] = {
-	_OMAP3_MUXENTRY(CAM_D10, 109,
-		"cam_d10", NULL, NULL, NULL,
-		"gpio_109", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D11, 110,
-		"cam_d11", NULL, NULL, NULL,
-		"gpio_110", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D2, 101,
-		"cam_d2", NULL, NULL, NULL,
-		"gpio_101", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D3, 102,
-		"cam_d3", NULL, NULL, NULL,
-		"gpio_102", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D4, 103,
-		"cam_d4", NULL, NULL, NULL,
-		"gpio_103", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D5, 104,
-		"cam_d5", NULL, NULL, NULL,
-		"gpio_104", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_FLD, 98,
-		"cam_fld", NULL, "cam_global_reset", NULL,
-		"gpio_98", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_HS, 94,
-		"cam_hs", NULL, NULL, NULL,
-		"gpio_94", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_PCLK, 97,
-		"cam_pclk", NULL, NULL, NULL,
-		"gpio_97", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_STROBE, 126,
-		"cam_strobe", NULL, NULL, NULL,
-		"gpio_126", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_VS, 95,
-		"cam_vs", NULL, NULL, NULL,
-		"gpio_95", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_WEN, 167,
-		"cam_wen", NULL, "cam_shutter", NULL,
-		"gpio_167", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA6, 76,
-		"dss_data6", NULL, "uart1_tx", NULL,
-		"gpio_76", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA7, 77,
-		"dss_data7", NULL, "uart1_rx", NULL,
-		"gpio_77", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA8, 78,
-		"dss_data8", NULL, NULL, NULL,
-		"gpio_78", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA9, 79,
-		"dss_data9", NULL, NULL, NULL,
-		"gpio_79", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_HSYNC, 67,
-		"dss_hsync", NULL, NULL, NULL,
-		"gpio_67", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_PCLK, 66,
-		"dss_pclk", NULL, NULL, NULL,
-		"gpio_66", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(ETK_CLK, 12,
-		"etk_clk", "mcbsp5_clkx", "sdmmc3_clk", "hsusb1_stp",
-		"gpio_12", "mm1_rxdp", "hsusb1_tll_stp", NULL),
-	_OMAP3_MUXENTRY(ETK_CTL, 13,
-		"etk_ctl", NULL, "sdmmc3_cmd", "hsusb1_clk",
-		"gpio_13", NULL, "hsusb1_tll_clk", NULL),
-	_OMAP3_MUXENTRY(ETK_D0, 14,
-		"etk_d0", "mcspi3_simo", "sdmmc3_dat4", "hsusb1_data0",
-		"gpio_14", "mm1_rxrcv", "hsusb1_tll_data0", NULL),
-	_OMAP3_MUXENTRY(ETK_D1, 15,
-		"etk_d1", "mcspi3_somi", NULL, "hsusb1_data1",
-		"gpio_15", "mm1_txse0", "hsusb1_tll_data1", NULL),
-	_OMAP3_MUXENTRY(ETK_D10, 24,
-		"etk_d10", NULL, "uart1_rx", "hsusb2_clk",
-		"gpio_24", NULL, "hsusb2_tll_clk", NULL),
-	_OMAP3_MUXENTRY(ETK_D11, 25,
-		"etk_d11", NULL, NULL, "hsusb2_stp",
-		"gpio_25", "mm2_rxdp", "hsusb2_tll_stp", NULL),
-	_OMAP3_MUXENTRY(ETK_D12, 26,
-		"etk_d12", NULL, NULL, "hsusb2_dir",
-		"gpio_26", NULL, "hsusb2_tll_dir", NULL),
-	_OMAP3_MUXENTRY(ETK_D13, 27,
-		"etk_d13", NULL, NULL, "hsusb2_nxt",
-		"gpio_27", "mm2_rxdm", "hsusb2_tll_nxt", NULL),
-	_OMAP3_MUXENTRY(ETK_D14, 28,
-		"etk_d14", NULL, NULL, "hsusb2_data0",
-		"gpio_28", "mm2_rxrcv", "hsusb2_tll_data0", NULL),
-	_OMAP3_MUXENTRY(ETK_D15, 29,
-		"etk_d15", NULL, NULL, "hsusb2_data1",
-		"gpio_29", "mm2_txse0", "hsusb2_tll_data1", NULL),
-	_OMAP3_MUXENTRY(ETK_D2, 16,
-		"etk_d2", "mcspi3_cs0", NULL, "hsusb1_data2",
-		"gpio_16", "mm1_txdat", "hsusb1_tll_data2", NULL),
-	_OMAP3_MUXENTRY(ETK_D3, 17,
-		"etk_d3", "mcspi3_clk", "sdmmc3_dat3", "hsusb1_data7",
-		"gpio_17", NULL, "hsusb1_tll_data7", NULL),
-	_OMAP3_MUXENTRY(ETK_D4, 18,
-		"etk_d4", "mcbsp5_dr", "sdmmc3_dat0", "hsusb1_data4",
-		"gpio_18", NULL, "hsusb1_tll_data4", NULL),
-	_OMAP3_MUXENTRY(ETK_D5, 19,
-		"etk_d5", "mcbsp5_fsx", "sdmmc3_dat1", "hsusb1_data5",
-		"gpio_19", NULL, "hsusb1_tll_data5", NULL),
-	_OMAP3_MUXENTRY(ETK_D6, 20,
-		"etk_d6", "mcbsp5_dx", "sdmmc3_dat2", "hsusb1_data6",
-		"gpio_20", NULL, "hsusb1_tll_data6", NULL),
-	_OMAP3_MUXENTRY(ETK_D7, 21,
-		"etk_d7", "mcspi3_cs1", "sdmmc3_dat7", "hsusb1_data3",
-		"gpio_21", "mm1_txen_n", "hsusb1_tll_data3", NULL),
-	_OMAP3_MUXENTRY(ETK_D8, 22,
-		"etk_d8", "sys_drm_msecure", "sdmmc3_dat6", "hsusb1_dir",
-		"gpio_22", NULL, "hsusb1_tll_dir", NULL),
-	_OMAP3_MUXENTRY(ETK_D9, 23,
-		"etk_d9", "sys_secure_indicator", "sdmmc3_dat5", "hsusb1_nxt",
-		"gpio_23", "mm1_rxdm", "hsusb1_tll_nxt", NULL),
-	_OMAP3_MUXENTRY(MCBSP3_CLKX, 142,
-		"mcbsp3_clkx", "uart2_tx", NULL, NULL,
-		"gpio_142", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP3_DR, 141,
-		"mcbsp3_dr", "uart2_rts", NULL, NULL,
-		"gpio_141", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP3_DX, 140,
-		"mcbsp3_dx", "uart2_cts", NULL, NULL,
-		"gpio_140", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP3_FSX, 143,
-		"mcbsp3_fsx", "uart2_rx", NULL, NULL,
-		"gpio_143", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT5, 137,
-		"sdmmc2_dat5", "sdmmc2_dir_dat1",
-		"cam_global_reset", "sdmmc3_dat1",
-		"gpio_137", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT6, 138,
-		"sdmmc2_dat6", "sdmmc2_dir_cmd", "cam_shutter", "sdmmc3_dat2",
-		"gpio_138", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC2_DAT7, 139,
-		"sdmmc2_dat7", "sdmmc2_clkin", NULL, "sdmmc3_dat3",
-		"gpio_139", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_CTS, 150,
-		"uart1_cts", NULL, NULL, NULL,
-		"gpio_150", NULL, NULL, "safe_mode"),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap3_cus_subset	NULL
-#endif
-
-/*
- * Balls for CUS package
- * 423-pin s-PBGA Package, 0.65mm Ball Pitch (Bottom)
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
-		&& defined(CONFIG_OMAP_PACKAGE_CUS)
-static struct omap_ball __initdata omap3_cus_ball[] = {
-	_OMAP3_BALLENTRY(CAM_D0, "ab18", NULL),
-	_OMAP3_BALLENTRY(CAM_D1, "ac18", NULL),
-	_OMAP3_BALLENTRY(CAM_D10, "f21", NULL),
-	_OMAP3_BALLENTRY(CAM_D11, "g21", NULL),
-	_OMAP3_BALLENTRY(CAM_D2, "g19", NULL),
-	_OMAP3_BALLENTRY(CAM_D3, "f19", NULL),
-	_OMAP3_BALLENTRY(CAM_D4, "g20", NULL),
-	_OMAP3_BALLENTRY(CAM_D5, "b21", NULL),
-	_OMAP3_BALLENTRY(CAM_D6, "l24", NULL),
-	_OMAP3_BALLENTRY(CAM_D7, "k24", NULL),
-	_OMAP3_BALLENTRY(CAM_D8, "j23", NULL),
-	_OMAP3_BALLENTRY(CAM_D9, "k23", NULL),
-	_OMAP3_BALLENTRY(CAM_FLD, "h24", NULL),
-	_OMAP3_BALLENTRY(CAM_HS, "a22", NULL),
-	_OMAP3_BALLENTRY(CAM_PCLK, "j19", NULL),
-	_OMAP3_BALLENTRY(CAM_STROBE, "j20", NULL),
-	_OMAP3_BALLENTRY(CAM_VS, "e18", NULL),
-	_OMAP3_BALLENTRY(CAM_WEN, "f18", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKA, "b22", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKB, "c22", NULL),
-	_OMAP3_BALLENTRY(DSS_ACBIAS, "j21", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA0, "ac19", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA1, "ab19", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA10, "ac22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA11, "ac23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA12, "ab22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA13, "y22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA14, "w22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA15, "v22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA16, "j22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA17, "g23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA18, "g24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA19, "h23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA2, "ad20", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA20, "d23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA21, "k22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA22, "v21", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA23, "w21", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA3, "ac20", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA4, "ad21", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA5, "ac21", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA6, "d24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA7, "e23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA8, "e24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA9, "f23", NULL),
-	_OMAP3_BALLENTRY(DSS_HSYNC, "e22", NULL),
-	_OMAP3_BALLENTRY(DSS_PCLK, "g22", NULL),
-	_OMAP3_BALLENTRY(DSS_VSYNC, "f22", NULL),
-	_OMAP3_BALLENTRY(ETK_CLK, "ac1", NULL),
-	_OMAP3_BALLENTRY(ETK_CTL, "ad3", NULL),
-	_OMAP3_BALLENTRY(ETK_D0, "ad6", NULL),
-	_OMAP3_BALLENTRY(ETK_D1, "ac6", NULL),
-	_OMAP3_BALLENTRY(ETK_D10, "ac3", NULL),
-	_OMAP3_BALLENTRY(ETK_D11, "ac9", NULL),
-	_OMAP3_BALLENTRY(ETK_D12, "ac10", NULL),
-	_OMAP3_BALLENTRY(ETK_D13, "ad11", NULL),
-	_OMAP3_BALLENTRY(ETK_D14, "ac11", NULL),
-	_OMAP3_BALLENTRY(ETK_D15, "ad12", NULL),
-	_OMAP3_BALLENTRY(ETK_D2, "ac7", NULL),
-	_OMAP3_BALLENTRY(ETK_D3, "ad8", NULL),
-	_OMAP3_BALLENTRY(ETK_D4, "ac5", NULL),
-	_OMAP3_BALLENTRY(ETK_D5, "ad2", NULL),
-	_OMAP3_BALLENTRY(ETK_D6, "ac8", NULL),
-	_OMAP3_BALLENTRY(ETK_D7, "ad9", NULL),
-	_OMAP3_BALLENTRY(ETK_D8, "ac4", NULL),
-	_OMAP3_BALLENTRY(ETK_D9, "ad5", NULL),
-	_OMAP3_BALLENTRY(GPMC_A1, "k4", NULL),
-	_OMAP3_BALLENTRY(GPMC_A10, "g2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A2, "k3", NULL),
-	_OMAP3_BALLENTRY(GPMC_A3, "k2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A4, "j4", NULL),
-	_OMAP3_BALLENTRY(GPMC_A5, "j3", NULL),
-	_OMAP3_BALLENTRY(GPMC_A6, "j2", NULL),
-	_OMAP3_BALLENTRY(GPMC_A7, "j1", NULL),
-	_OMAP3_BALLENTRY(GPMC_A8, "h1", NULL),
-	_OMAP3_BALLENTRY(GPMC_A9, "h2", NULL),
-	_OMAP3_BALLENTRY(GPMC_CLK, "w2", NULL),
-	_OMAP3_BALLENTRY(GPMC_D10, "u1", NULL),
-	_OMAP3_BALLENTRY(GPMC_D11, "r3", NULL),
-	_OMAP3_BALLENTRY(GPMC_D12, "t3", NULL),
-	_OMAP3_BALLENTRY(GPMC_D13, "u2", NULL),
-	_OMAP3_BALLENTRY(GPMC_D14, "v1", NULL),
-	_OMAP3_BALLENTRY(GPMC_D15, "v2", NULL),
-	_OMAP3_BALLENTRY(GPMC_D8, "r2", NULL),
-	_OMAP3_BALLENTRY(GPMC_D9, "t2", NULL),
-	_OMAP3_BALLENTRY(GPMC_NBE0_CLE, "k5", NULL),
-	_OMAP3_BALLENTRY(GPMC_NBE1, "l1", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS3, "d2", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS4, "f4", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS5, "g5", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS6, "f3", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS7, "g4", NULL),
-	_OMAP3_BALLENTRY(GPMC_NWP, "e1", NULL),
-	_OMAP3_BALLENTRY(GPMC_WAIT3, "c2", NULL),
-	_OMAP3_BALLENTRY(HDQ_SIO, "a24", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_CLK, "r21", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA0, "t24", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA1, "t23", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA2, "u24", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA3, "u23", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA4, "w24", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA5, "v23", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA6, "w23", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA7, "t22", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DIR, "p23", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_NXT, "r22", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_STP, "r23", NULL),
-	_OMAP3_BALLENTRY(I2C2_SCL, "ac15", NULL),
-	_OMAP3_BALLENTRY(I2C2_SDA, "ac14", NULL),
-	_OMAP3_BALLENTRY(I2C3_SCL, "ac13", NULL),
-	_OMAP3_BALLENTRY(I2C3_SDA, "ac12", NULL),
-	_OMAP3_BALLENTRY(I2C4_SCL, "y16", NULL),
-	_OMAP3_BALLENTRY(I2C4_SDA, "y15", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU0, "ac24", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU1, "ad24", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKR, "w19", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKX, "v18", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DR, "y18", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DX, "w18", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSR, "ab20", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSX, "aa19", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_CLKX, "t21", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DR, "v19", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DX, "r20", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_FSX, "v20", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_CLKX, "w4", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DR, "v5", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DX, "v6", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_FSX, "v4", NULL),
-	_OMAP3_BALLENTRY(MCBSP_CLKS, "aa18", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CLK, "t5", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS0, "t6", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS3, "r5", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SIMO, "r4", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SOMI, "t4", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CLK, "n5", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS0, "m5", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS1, "m4", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SIMO, "n4", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SOMI, "n3", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CLK, "m23", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CMD, "l23", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT0, "m22", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT1, "m21", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT2, "m20", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT3, "n23", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT4, "n22", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT5, "n21", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT6, "n20", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT7, "p24", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CLK, "y1", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CMD, "ab5", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT0, "ab3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT1, "y3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT2, "w3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT3, "v3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT4, "ab2", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT5, "aa2", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT6, "y2", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT7, "aa1", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT0, "ab12", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT1, "ac16", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT2, "ad17", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT3, "ad18", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT4, "ac17", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT5, "ab16", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT6, "aa15", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT1, "y7", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT2, "aa6", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKREQ, "y13", NULL),
-	_OMAP3_BALLENTRY(SYS_NIRQ, "w16", NULL),
-	_OMAP3_BALLENTRY(SYS_NRESWARM, "y10", NULL),
-	_OMAP3_BALLENTRY(SYS_OFF_MODE, "ad23", NULL),
-	_OMAP3_BALLENTRY(UART1_CTS, "ac2", NULL),
-	_OMAP3_BALLENTRY(UART1_RTS, "w6", NULL),
-	_OMAP3_BALLENTRY(UART1_RX, "v7", NULL),
-	_OMAP3_BALLENTRY(UART1_TX, "w7", NULL),
-	_OMAP3_BALLENTRY(UART3_CTS_RCTX, "a23", NULL),
-	_OMAP3_BALLENTRY(UART3_RTS_SD, "b23", NULL),
-	_OMAP3_BALLENTRY(UART3_RX_IRRX, "b24", NULL),
-	_OMAP3_BALLENTRY(UART3_TX_IRTX, "c23", NULL),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap3_cus_ball	 NULL
-#endif
-
-/*
- * Signals different on CBB package compared to superset
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBB)
-static struct omap_mux __initdata omap3_cbb_subset[] = {
-	_OMAP3_MUXENTRY(CAM_D10, 109,
-		"cam_d10", NULL, NULL, NULL,
-		"gpio_109", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D11, 110,
-		"cam_d11", NULL, NULL, NULL,
-		"gpio_110", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D2, 101,
-		"cam_d2", NULL, NULL, NULL,
-		"gpio_101", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D3, 102,
-		"cam_d3", NULL, NULL, NULL,
-		"gpio_102", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D4, 103,
-		"cam_d4", NULL, NULL, NULL,
-		"gpio_103", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D5, 104,
-		"cam_d5", NULL, NULL, NULL,
-		"gpio_104", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_FLD, 98,
-		"cam_fld", NULL, "cam_global_reset", NULL,
-		"gpio_98", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_HS, 94,
-		"cam_hs", NULL, NULL, NULL,
-		"gpio_94", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_PCLK, 97,
-		"cam_pclk", NULL, NULL, NULL,
-		"gpio_97", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_STROBE, 126,
-		"cam_strobe", NULL, NULL, NULL,
-		"gpio_126", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_VS, 95,
-		"cam_vs", NULL, NULL, NULL,
-		"gpio_95", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_WEN, 167,
-		"cam_wen", NULL, "cam_shutter", NULL,
-		"gpio_167", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA6, 76,
-		"dss_data6", NULL, "uart1_tx", NULL,
-		"gpio_76", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA7, 77,
-		"dss_data7", NULL, "uart1_rx", NULL,
-		"gpio_77", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA8, 78,
-		"dss_data8", NULL, NULL, NULL,
-		"gpio_78", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA9, 79,
-		"dss_data9", NULL, NULL, NULL,
-		"gpio_79", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_HSYNC, 67,
-		"dss_hsync", NULL, NULL, NULL,
-		"gpio_67", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_PCLK, 66,
-		"dss_pclk", NULL, NULL, NULL,
-		"gpio_66", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(ETK_CLK, 12,
-		"etk_clk", "mcbsp5_clkx", "sdmmc3_clk", "hsusb1_stp",
-		"gpio_12", "mm1_rxdp", "hsusb1_tll_stp", NULL),
-	_OMAP3_MUXENTRY(ETK_CTL, 13,
-		"etk_ctl", NULL, "sdmmc3_cmd", "hsusb1_clk",
-		"gpio_13", NULL, "hsusb1_tll_clk", NULL),
-	_OMAP3_MUXENTRY(ETK_D0, 14,
-		"etk_d0", "mcspi3_simo", "sdmmc3_dat4", "hsusb1_data0",
-		"gpio_14", "mm1_rxrcv", "hsusb1_tll_data0", NULL),
-	_OMAP3_MUXENTRY(ETK_D1, 15,
-		"etk_d1", "mcspi3_somi", NULL, "hsusb1_data1",
-		"gpio_15", "mm1_txse0", "hsusb1_tll_data1", NULL),
-	_OMAP3_MUXENTRY(ETK_D10, 24,
-		"etk_d10", NULL, "uart1_rx", "hsusb2_clk",
-		"gpio_24", NULL, "hsusb2_tll_clk", NULL),
-	_OMAP3_MUXENTRY(ETK_D11, 25,
-		"etk_d11", NULL, NULL, "hsusb2_stp",
-		"gpio_25", "mm2_rxdp", "hsusb2_tll_stp", NULL),
-	_OMAP3_MUXENTRY(ETK_D12, 26,
-		"etk_d12", NULL, NULL, "hsusb2_dir",
-		"gpio_26", NULL, "hsusb2_tll_dir", NULL),
-	_OMAP3_MUXENTRY(ETK_D13, 27,
-		"etk_d13", NULL, NULL, "hsusb2_nxt",
-		"gpio_27", "mm2_rxdm", "hsusb2_tll_nxt", NULL),
-	_OMAP3_MUXENTRY(ETK_D14, 28,
-		"etk_d14", NULL, NULL, "hsusb2_data0",
-		"gpio_28", "mm2_rxrcv", "hsusb2_tll_data0", NULL),
-	_OMAP3_MUXENTRY(ETK_D15, 29,
-		"etk_d15", NULL, NULL, "hsusb2_data1",
-		"gpio_29", "mm2_txse0", "hsusb2_tll_data1", NULL),
-	_OMAP3_MUXENTRY(ETK_D2, 16,
-		"etk_d2", "mcspi3_cs0", NULL, "hsusb1_data2",
-		"gpio_16", "mm1_txdat", "hsusb1_tll_data2", NULL),
-	_OMAP3_MUXENTRY(ETK_D3, 17,
-		"etk_d3", "mcspi3_clk", "sdmmc3_dat3", "hsusb1_data7",
-		"gpio_17", NULL, "hsusb1_tll_data7", NULL),
-	_OMAP3_MUXENTRY(ETK_D4, 18,
-		"etk_d4", "mcbsp5_dr", "sdmmc3_dat0", "hsusb1_data4",
-		"gpio_18", NULL, "hsusb1_tll_data4", NULL),
-	_OMAP3_MUXENTRY(ETK_D5, 19,
-		"etk_d5", "mcbsp5_fsx", "sdmmc3_dat1", "hsusb1_data5",
-		"gpio_19", NULL, "hsusb1_tll_data5", NULL),
-	_OMAP3_MUXENTRY(ETK_D6, 20,
-		"etk_d6", "mcbsp5_dx", "sdmmc3_dat2", "hsusb1_data6",
-		"gpio_20", NULL, "hsusb1_tll_data6", NULL),
-	_OMAP3_MUXENTRY(ETK_D7, 21,
-		"etk_d7", "mcspi3_cs1", "sdmmc3_dat7", "hsusb1_data3",
-		"gpio_21", "mm1_txen_n", "hsusb1_tll_data3", NULL),
-	_OMAP3_MUXENTRY(ETK_D8, 22,
-		"etk_d8", "sys_drm_msecure", "sdmmc3_dat6", "hsusb1_dir",
-		"gpio_22", NULL, "hsusb1_tll_dir", NULL),
-	_OMAP3_MUXENTRY(ETK_D9, 23,
-		"etk_d9", "sys_secure_indicator", "sdmmc3_dat5", "hsusb1_nxt",
-		"gpio_23", "mm1_rxdm", "hsusb1_tll_nxt", NULL),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap3_cbb_subset	NULL
-#endif
-
-/*
- * Balls for CBB package
- * 515-pin s-PBGA Package, 0.50mm Ball Pitch (Top), 0.40mm Ball Pitch (Bottom)
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
-		&& defined(CONFIG_OMAP_PACKAGE_CBB)
-static struct omap_ball __initdata omap3_cbb_ball[] = {
-	_OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
-	_OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
-	_OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
-	_OMAP3_BALLENTRY(CAM_D11, "c26", NULL),
-	_OMAP3_BALLENTRY(CAM_D2, "b24", NULL),
-	_OMAP3_BALLENTRY(CAM_D3, "c24", NULL),
-	_OMAP3_BALLENTRY(CAM_D4, "d24", NULL),
-	_OMAP3_BALLENTRY(CAM_D5, "a25", NULL),
-	_OMAP3_BALLENTRY(CAM_D6, "k28", NULL),
-	_OMAP3_BALLENTRY(CAM_D7, "l28", NULL),
-	_OMAP3_BALLENTRY(CAM_D8, "k27", NULL),
-	_OMAP3_BALLENTRY(CAM_D9, "l27", NULL),
-	_OMAP3_BALLENTRY(CAM_FLD, "c23", NULL),
-	_OMAP3_BALLENTRY(CAM_HS, "a24", NULL),
-	_OMAP3_BALLENTRY(CAM_PCLK, "c27", NULL),
-	_OMAP3_BALLENTRY(CAM_STROBE, "d25", NULL),
-	_OMAP3_BALLENTRY(CAM_VS, "a23", NULL),
-	_OMAP3_BALLENTRY(CAM_WEN, "b23", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKA, "c25", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKB, "b26", NULL),
-	_OMAP3_BALLENTRY(CSI2_DX0, "ag19", NULL),
-	_OMAP3_BALLENTRY(CSI2_DX1, "ag18", NULL),
-	_OMAP3_BALLENTRY(CSI2_DY0, "ah19", NULL),
-	_OMAP3_BALLENTRY(CSI2_DY1, "ah18", NULL),
-	_OMAP3_BALLENTRY(DSS_ACBIAS, "e27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA0, "ag22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA1, "ah22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA10, "ad28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA11, "ad27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA12, "ab28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA13, "ab27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA14, "aa28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA15, "aa27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA16, "g25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA17, "h27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA18, "h26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA19, "h25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA2, "ag23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA20, "e28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA21, "j26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA22, "ac27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA23, "ac28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA3, "ah23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA4, "ag24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA5, "ah24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA6, "e26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA7, "f28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA8, "f27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA9, "g26", NULL),
-	_OMAP3_BALLENTRY(DSS_HSYNC, "d26", NULL),
-	_OMAP3_BALLENTRY(DSS_PCLK, "d28", NULL),
-	_OMAP3_BALLENTRY(DSS_VSYNC, "d27", NULL),
-	_OMAP3_BALLENTRY(ETK_CLK, "af10", NULL),
-	_OMAP3_BALLENTRY(ETK_CTL, "ae10", NULL),
-	_OMAP3_BALLENTRY(ETK_D0, "af11", NULL),
-	_OMAP3_BALLENTRY(ETK_D1, "ag12", NULL),
-	_OMAP3_BALLENTRY(ETK_D10, "ae7", NULL),
-	_OMAP3_BALLENTRY(ETK_D11, "af7", NULL),
-	_OMAP3_BALLENTRY(ETK_D12, "ag7", NULL),
-	_OMAP3_BALLENTRY(ETK_D13, "ah7", NULL),
-	_OMAP3_BALLENTRY(ETK_D14, "ag8", NULL),
-	_OMAP3_BALLENTRY(ETK_D15, "ah8", NULL),
-	_OMAP3_BALLENTRY(ETK_D2, "ah12", NULL),
-	_OMAP3_BALLENTRY(ETK_D3, "ae13", NULL),
-	_OMAP3_BALLENTRY(ETK_D4, "ae11", NULL),
-	_OMAP3_BALLENTRY(ETK_D5, "ah9", NULL),
-	_OMAP3_BALLENTRY(ETK_D6, "af13", NULL),
-	_OMAP3_BALLENTRY(ETK_D7, "ah14", NULL),
-	_OMAP3_BALLENTRY(ETK_D8, "af9", NULL),
-	_OMAP3_BALLENTRY(ETK_D9, "ag9", NULL),
-	_OMAP3_BALLENTRY(GPMC_A1, "n4", "ac15"),
-	_OMAP3_BALLENTRY(GPMC_A10, "k3", "ab19"),
-	_OMAP3_BALLENTRY(GPMC_A2, "m4", "ab15"),
-	_OMAP3_BALLENTRY(GPMC_A3, "l4", "ac16"),
-	_OMAP3_BALLENTRY(GPMC_A4, "k4", "ab16"),
-	_OMAP3_BALLENTRY(GPMC_A5, "t3", "ac17"),
-	_OMAP3_BALLENTRY(GPMC_A6, "r3", "ab17"),
-	_OMAP3_BALLENTRY(GPMC_A7, "n3", "ac18"),
-	_OMAP3_BALLENTRY(GPMC_A8, "m3", "ab18"),
-	_OMAP3_BALLENTRY(GPMC_A9, "l3", "ac19"),
-	_OMAP3_BALLENTRY(GPMC_CLK, "t4", "w2"),
-	_OMAP3_BALLENTRY(GPMC_D10, "p1", "ab4"),
-	_OMAP3_BALLENTRY(GPMC_D11, "r1", "ac4"),
-	_OMAP3_BALLENTRY(GPMC_D12, "r2", "ab6"),
-	_OMAP3_BALLENTRY(GPMC_D13, "t2", "ac6"),
-	_OMAP3_BALLENTRY(GPMC_D14, "w1", "ab7"),
-	_OMAP3_BALLENTRY(GPMC_D15, "y1", "ac7"),
-	_OMAP3_BALLENTRY(GPMC_D8, "h2", "ab3"),
-	_OMAP3_BALLENTRY(GPMC_D9, "k2", "ac3"),
-	_OMAP3_BALLENTRY(GPMC_NBE0_CLE, "g3", "ac12"),
-	_OMAP3_BALLENTRY(GPMC_NBE1, "u3", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS1, "h3", "y1"),
-	_OMAP3_BALLENTRY(GPMC_NCS2, "v8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS3, "u8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS4, "t8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS5, "r8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS6, "p8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS7, "n8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NWP, "h1", "ab10"),
-	_OMAP3_BALLENTRY(GPMC_WAIT1, "l8", "ac10"),
-	_OMAP3_BALLENTRY(GPMC_WAIT2, "k8", NULL),
-	_OMAP3_BALLENTRY(GPMC_WAIT3, "j8", NULL),
-	_OMAP3_BALLENTRY(HDQ_SIO, "j25", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_CLK, "t28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA0, "t27", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA1, "u28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA2, "u27", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA3, "u26", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA4, "u25", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA5, "v28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA6, "v27", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA7, "v26", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DIR, "r28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_NXT, "t26", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_STP, "t25", NULL),
-	_OMAP3_BALLENTRY(I2C2_SCL, "af15", NULL),
-	_OMAP3_BALLENTRY(I2C2_SDA, "ae15", NULL),
-	_OMAP3_BALLENTRY(I2C3_SCL, "af14", NULL),
-	_OMAP3_BALLENTRY(I2C3_SDA, "ag14", NULL),
-	_OMAP3_BALLENTRY(I2C4_SCL, "ad26", NULL),
-	_OMAP3_BALLENTRY(I2C4_SDA, "ae26", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU0, "aa11", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU1, "aa10", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKR, "y21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKX, "w21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DR, "u21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DX, "v21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSR, "aa21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSX, "k26", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_CLKX, "n21", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DR, "r21", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DX, "m21", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_FSX, "p21", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_CLKX, "af5", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DR, "ae6", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DX, "af6", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_FSX, "ae5", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_CLKX, "ae1", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_DR, "ad1", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_DX, "ad2", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_FSX, "ac1", NULL),
-	_OMAP3_BALLENTRY(MCBSP_CLKS, "t21", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CLK, "ab3", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS0, "ac2", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS1, "ac3", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS2, "ab1", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS3, "ab2", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SIMO, "ab4", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SOMI, "aa4", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CLK, "aa3", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS0, "y4", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS1, "v3", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SIMO, "y2", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SOMI, "y3", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CLK, "n28", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CMD, "m27", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT0, "n27", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT1, "n26", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT2, "n25", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT3, "p28", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT4, "p27", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT5, "p26", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT6, "r27", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT7, "r25", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CLK, "ae2", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CMD, "ag5", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT0, "ah5", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT1, "ah4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT2, "ag4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT3, "af4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT4, "ae4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT5, "ah3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT6, "af3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT7, "ae3", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT0, "ah26", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT1, "ag26", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT2, "ae14", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT3, "af18", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT4, "af19", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT5, "ae21", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT6, "af21", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT1, "ag25", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT2, "ae22", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKREQ, "af25", NULL),
-	_OMAP3_BALLENTRY(SYS_NIRQ, "af26", NULL),
-	_OMAP3_BALLENTRY(SYS_NRESWARM, "af24", NULL),
-	_OMAP3_BALLENTRY(SYS_OFF_MODE, "af22", NULL),
-	_OMAP3_BALLENTRY(UART1_CTS, "w8", NULL),
-	_OMAP3_BALLENTRY(UART1_RTS, "aa9", NULL),
-	_OMAP3_BALLENTRY(UART1_RX, "y8", NULL),
-	_OMAP3_BALLENTRY(UART1_TX, "aa8", NULL),
-	_OMAP3_BALLENTRY(UART2_CTS, "ab26", NULL),
-	_OMAP3_BALLENTRY(UART2_RTS, "ab25", NULL),
-	_OMAP3_BALLENTRY(UART2_RX, "ad25", NULL),
-	_OMAP3_BALLENTRY(UART2_TX, "aa25", NULL),
-	_OMAP3_BALLENTRY(UART3_CTS_RCTX, "h18", NULL),
-	_OMAP3_BALLENTRY(UART3_RTS_SD, "h19", NULL),
-	_OMAP3_BALLENTRY(UART3_RX_IRRX, "h20", NULL),
-	_OMAP3_BALLENTRY(UART3_TX_IRTX, "h21", NULL),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap3_cbb_ball	 NULL
-#endif
-
-/*
- * Signals different on 36XX CBP package compared to 34XX CBC package
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBP)
-static struct omap_mux __initdata omap36xx_cbp_subset[] = {
-	_OMAP3_MUXENTRY(CAM_D0, 99,
-		"cam_d0", NULL, "csi2_dx2", NULL,
-		"gpio_99", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D1, 100,
-		"cam_d1", NULL, "csi2_dy2", NULL,
-		"gpio_100", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D10, 109,
-		"cam_d10", "ssi2_wake", NULL, NULL,
-		"gpio_109", "hw_dbg8", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D2, 101,
-		"cam_d2", "ssi2_rdy_tx", NULL, NULL,
-		"gpio_101", "hw_dbg4", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D3, 102,
-		"cam_d3", "ssi2_dat_rx", NULL, NULL,
-		"gpio_102", "hw_dbg5", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D4, 103,
-		"cam_d4", "ssi2_flag_rx", NULL, NULL,
-		"gpio_103", "hw_dbg6", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_D5, 104,
-		"cam_d5", "ssi2_rdy_rx", NULL, NULL,
-		"gpio_104", "hw_dbg7", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_HS, 94,
-		"cam_hs", "ssi2_dat_tx", NULL, NULL,
-		"gpio_94", "hw_dbg0", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(CAM_VS, 95,
-		"cam_vs", "ssi2_flag_tx", NULL, NULL,
-		"gpio_95", "hw_dbg1", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA0, 70,
-		"dss_data0", "dsi_dx0", "uart1_cts", NULL,
-		"gpio_70", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA1, 71,
-		"dss_data1", "dsi_dy0", "uart1_rts", NULL,
-		"gpio_71", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA2, 72,
-		"dss_data2", "dsi_dx1", NULL, NULL,
-		"gpio_72", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA3, 73,
-		"dss_data3", "dsi_dy1", NULL, NULL,
-		"gpio_73", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA4, 74,
-		"dss_data4", "dsi_dx2", "uart3_rx_irrx", NULL,
-		"gpio_74", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA5, 75,
-		"dss_data5", "dsi_dy2", "uart3_tx_irtx", NULL,
-		"gpio_75", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA6, 76,
-		"dss_data6", NULL, "uart1_tx", "dssvenc656_data6",
-		"gpio_76", "hw_dbg14", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA7, 77,
-		"dss_data7", NULL, "uart1_rx", "dssvenc656_data7",
-		"gpio_77", "hw_dbg15", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA8, 78,
-		"dss_data8", NULL, "uart3_rx_irrx", NULL,
-		"gpio_78", "hw_dbg16", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(DSS_DATA9, 79,
-		"dss_data9", NULL, "uart3_tx_irtx", NULL,
-		"gpio_79", "hw_dbg17", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(ETK_D12, 26,
-		"etk_d12", "sys_drm_msecure", NULL, "hsusb2_dir",
-		"gpio_26", NULL, "hsusb2_tll_dir", "hw_dbg14"),
-	_OMAP3_MUXENTRY(GPMC_A11, 0,
-		"gpmc_a11", NULL, NULL, NULL,
-		NULL, NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_WAIT2, 64,
-		"gpmc_wait2", NULL, "uart4_tx", NULL,
-		"gpio_64", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(GPMC_WAIT3, 65,
-		"gpmc_wait3", "sys_ndmareq1", "uart4_rx", NULL,
-		"gpio_65", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA0, 125,
-		"hsusb0_data0", NULL, "uart3_tx_irtx", NULL,
-		"gpio_125", "uart2_tx", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA1, 130,
-		"hsusb0_data1", NULL, "uart3_rx_irrx", NULL,
-		"gpio_130", "uart2_rx", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA2, 131,
-		"hsusb0_data2", NULL, "uart3_rts_sd", NULL,
-		"gpio_131", "uart2_rts", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(HSUSB0_DATA3, 169,
-		"hsusb0_data3", NULL, "uart3_cts_rctx", NULL,
-		"gpio_169", "uart2_cts", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_CLKR, 156,
-		"mcbsp1_clkr", "mcspi4_clk", "sim_cd", NULL,
-		"gpio_156", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP1_FSR, 157,
-		"mcbsp1_fsr", "adpllv2d_dithering_en1",
-		"cam_global_reset", NULL,
-		"gpio_157", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_CLKX, 152,
-		"mcbsp4_clkx", "ssi1_dat_rx", NULL, NULL,
-		"gpio_152", "hsusb3_tll_data1", "mm3_txse0", "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_DR, 153,
-		"mcbsp4_dr", "ssi1_flag_rx", NULL, NULL,
-		"gpio_153", "hsusb3_tll_data0", "mm3_rxrcv", "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_DX, 154,
-		"mcbsp4_dx", "ssi1_rdy_rx", NULL, NULL,
-		"gpio_154", "hsusb3_tll_data2", "mm3_txdat", "safe_mode"),
-	_OMAP3_MUXENTRY(MCBSP4_FSX, 155,
-		"mcbsp4_fsx", "ssi1_wake", NULL, NULL,
-		"gpio_155", "hsusb3_tll_data3", "mm3_txen_n", "safe_mode"),
-	_OMAP3_MUXENTRY(MCSPI1_CS1, 175,
-		"mcspi1_cs1", "adpllv2d_dithering_en2", NULL, "sdmmc3_cmd",
-		"gpio_175", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SAD2D_MBUSFLAG, 0,
-		"sad2d_mbusflag", "mad2d_sbusflag", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD28, 0,
-		"sad2d_mcad28", "mad2d_mcad28", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD29, 0,
-		"sad2d_mcad29", "mad2d_mcad29", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD32, 0,
-		"sad2d_mcad32", "mad2d_mcad32", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD33, 0,
-		"sad2d_mcad33", "mad2d_mcad33", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD34, 0,
-		"sad2d_mcad34", "mad2d_mcad34", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD35, 0,
-		"sad2d_mcad35", "mad2d_mcad35", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MCAD36, 0,
-		"sad2d_mcad36", "mad2d_mcad36", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MREAD, 0,
-		"sad2d_mread", "mad2d_sread", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_MWRITE, 0,
-		"sad2d_mwrite", "mad2d_swrite", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_SBUSFLAG, 0,
-		"sad2d_sbusflag", "mad2d_mbusflag", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_SREAD, 0,
-		"sad2d_sread", "mad2d_mread", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SAD2D_SWRITE, 0,
-		"sad2d_swrite", "mad2d_mwrite", NULL, NULL,
-		NULL, NULL, NULL, NULL),
-	_OMAP3_MUXENTRY(SDMMC1_CLK, 120,
-		"sdmmc1_clk", "ms_clk", NULL, NULL,
-		"gpio_120", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_CMD, 121,
-		"sdmmc1_cmd", "ms_bs", NULL, NULL,
-		"gpio_121", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT0, 122,
-		"sdmmc1_dat0", "ms_dat0", NULL, NULL,
-		"gpio_122", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT1, 123,
-		"sdmmc1_dat1", "ms_dat1", NULL, NULL,
-		"gpio_123", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT2, 124,
-		"sdmmc1_dat2", "ms_dat2", NULL, NULL,
-		"gpio_124", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDMMC1_DAT3, 125,
-		"sdmmc1_dat3", "ms_dat3", NULL, NULL,
-		"gpio_125", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SDRC_CKE0, 0,
-		"sdrc_cke0", NULL, NULL, NULL,
-		NULL, NULL, NULL, "safe_mode_out1"),
-	_OMAP3_MUXENTRY(SDRC_CKE1, 0,
-		"sdrc_cke1", NULL, NULL, NULL,
-		NULL, NULL, NULL, "safe_mode_out1"),
-	_OMAP3_MUXENTRY(SIM_IO, 126,
-		"sim_io", "sim_io_low_impedance", NULL, NULL,
-		"gpio_126", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SIM_CLK, 127,
-		"sim_clk", NULL, NULL, NULL,
-		"gpio_127", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SIM_PWRCTRL, 128,
-		"sim_pwrctrl", NULL, NULL, NULL,
-		"gpio_128", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SIM_RST, 129,
-		"sim_rst", NULL, NULL, NULL,
-		"gpio_129", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT0, 2,
-		"sys_boot0", NULL, NULL, "dss_data18",
-		"gpio_2", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT1, 3,
-		"sys_boot1", NULL, NULL, "dss_data19",
-		"gpio_3", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT3, 5,
-		"sys_boot3", NULL, NULL, "dss_data20",
-		"gpio_5", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT4, 6,
-		"sys_boot4", "sdmmc2_dir_dat2", NULL, "dss_data21",
-		"gpio_6", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT5, 7,
-		"sys_boot5", "sdmmc2_dir_dat3", NULL, "dss_data22",
-		"gpio_7", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(SYS_BOOT6, 8,
-		"sys_boot6", NULL, NULL, "dss_data23",
-		"gpio_8", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_CTS, 150,
-		"uart1_cts", "ssi1_rdy_tx", NULL, NULL,
-		"gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_RTS, 149,
-		"uart1_rts", "ssi1_flag_tx", NULL, NULL,
-		"gpio_149", NULL, NULL, "safe_mode"),
-	_OMAP3_MUXENTRY(UART1_TX, 148,
-		"uart1_tx", "ssi1_dat_tx", NULL, NULL,
-		"gpio_148", NULL, NULL, "safe_mode"),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap36xx_cbp_subset	NULL
-#endif
-
-/*
- * Balls for 36XX CBP package
- * 515-pin s-PBGA Package, 0.50mm Ball Pitch (Top), 0.40mm Ball Pitch (Bottom)
- */
-#if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)		\
-		&& defined (CONFIG_OMAP_PACKAGE_CBP)
-static struct omap_ball __initdata omap36xx_cbp_ball[] = {
-	_OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
-	_OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
-	_OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
-	_OMAP3_BALLENTRY(CAM_D11, "c26", NULL),
-	_OMAP3_BALLENTRY(CAM_D2, "b24", NULL),
-	_OMAP3_BALLENTRY(CAM_D3, "c24", NULL),
-	_OMAP3_BALLENTRY(CAM_D4, "d24", NULL),
-	_OMAP3_BALLENTRY(CAM_D5, "a25", NULL),
-	_OMAP3_BALLENTRY(CAM_D6, "k28", NULL),
-	_OMAP3_BALLENTRY(CAM_D7, "l28", NULL),
-	_OMAP3_BALLENTRY(CAM_D8, "k27", NULL),
-	_OMAP3_BALLENTRY(CAM_D9, "l27", NULL),
-	_OMAP3_BALLENTRY(CAM_FLD, "c23", NULL),
-	_OMAP3_BALLENTRY(CAM_HS, "a24", NULL),
-	_OMAP3_BALLENTRY(CAM_PCLK, "c27", NULL),
-	_OMAP3_BALLENTRY(CAM_STROBE, "d25", NULL),
-	_OMAP3_BALLENTRY(CAM_VS, "a23", NULL),
-	_OMAP3_BALLENTRY(CAM_WEN, "b23", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKA, "c25", NULL),
-	_OMAP3_BALLENTRY(CAM_XCLKB, "b26", NULL),
-	_OMAP3_BALLENTRY(CSI2_DX0, "ag19", NULL),
-	_OMAP3_BALLENTRY(CSI2_DX1, "ag18", NULL),
-	_OMAP3_BALLENTRY(CSI2_DY0, "ah19", NULL),
-	_OMAP3_BALLENTRY(CSI2_DY1, "ah18", NULL),
-	_OMAP3_BALLENTRY(DSS_ACBIAS, "e27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA0, "ag22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA1, "ah22", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA10, "ad28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA11, "ad27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA12, "ab28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA13, "ab27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA14, "aa28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA15, "aa27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA16, "g25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA17, "h27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA18, "h26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA19, "h25", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA2, "ag23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA20, "e28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA21, "j26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA22, "ac27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA23, "ac28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA3, "ah23", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA4, "ag24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA5, "ah24", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA6, "e26", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA7, "f28", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA8, "f27", NULL),
-	_OMAP3_BALLENTRY(DSS_DATA9, "g26", NULL),
-	_OMAP3_BALLENTRY(DSS_HSYNC, "d26", NULL),
-	_OMAP3_BALLENTRY(DSS_PCLK, "d28", NULL),
-	_OMAP3_BALLENTRY(DSS_VSYNC, "d27", NULL),
-	_OMAP3_BALLENTRY(ETK_CLK, "af10", NULL),
-	_OMAP3_BALLENTRY(ETK_CTL, "ae10", NULL),
-	_OMAP3_BALLENTRY(ETK_D0, "af11", NULL),
-	_OMAP3_BALLENTRY(ETK_D1, "ag12", NULL),
-	_OMAP3_BALLENTRY(ETK_D10, "ae7", NULL),
-	_OMAP3_BALLENTRY(ETK_D11, "af7", NULL),
-	_OMAP3_BALLENTRY(ETK_D12, "ag7", NULL),
-	_OMAP3_BALLENTRY(ETK_D13, "ah7", NULL),
-	_OMAP3_BALLENTRY(ETK_D14, "ag8", NULL),
-	_OMAP3_BALLENTRY(ETK_D15, "ah8", NULL),
-	_OMAP3_BALLENTRY(ETK_D2, "ah12", NULL),
-	_OMAP3_BALLENTRY(ETK_D3, "ae13", NULL),
-	_OMAP3_BALLENTRY(ETK_D4, "ae11", NULL),
-	_OMAP3_BALLENTRY(ETK_D5, "ah9", NULL),
-	_OMAP3_BALLENTRY(ETK_D6, "af13", NULL),
-	_OMAP3_BALLENTRY(ETK_D7, "ah14", NULL),
-	_OMAP3_BALLENTRY(ETK_D8, "af9", NULL),
-	_OMAP3_BALLENTRY(ETK_D9, "ag9", NULL),
-	_OMAP3_BALLENTRY(GPMC_A1, "n4", "ac15"),
-	_OMAP3_BALLENTRY(GPMC_A10, "k3", "ab19"),
-	_OMAP3_BALLENTRY(GPMC_A11, NULL, "ac20"),
-	_OMAP3_BALLENTRY(GPMC_A2, "m4", "ab15"),
-	_OMAP3_BALLENTRY(GPMC_A3, "l4", "ac16"),
-	_OMAP3_BALLENTRY(GPMC_A4, "k4", "ab16"),
-	_OMAP3_BALLENTRY(GPMC_A5, "t3", "ac17"),
-	_OMAP3_BALLENTRY(GPMC_A6, "r3", "ab17"),
-	_OMAP3_BALLENTRY(GPMC_A7, "n3", "ac18"),
-	_OMAP3_BALLENTRY(GPMC_A8, "m3", "ab18"),
-	_OMAP3_BALLENTRY(GPMC_A9, "l3", "ac19"),
-	_OMAP3_BALLENTRY(GPMC_CLK, "t4", "w2"),
-	_OMAP3_BALLENTRY(GPMC_D10, "p1", "ab4"),
-	_OMAP3_BALLENTRY(GPMC_D11, "r1", "ac4"),
-	_OMAP3_BALLENTRY(GPMC_D12, "r2", "ab6"),
-	_OMAP3_BALLENTRY(GPMC_D13, "t2", "ac6"),
-	_OMAP3_BALLENTRY(GPMC_D14, "w1", "ab7"),
-	_OMAP3_BALLENTRY(GPMC_D15, "y1", "ac7"),
-	_OMAP3_BALLENTRY(GPMC_D9, "k2", "ac3"),
-	_OMAP3_BALLENTRY(GPMC_NBE0_CLE, "g3", "ac12"),
-	_OMAP3_BALLENTRY(GPMC_NBE1, "u3", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS1, "h3", "y1"),
-	_OMAP3_BALLENTRY(GPMC_NCS2, "v8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS3, "u8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS4, "t8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS5, "r8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS6, "p8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NCS7, "n8", NULL),
-	_OMAP3_BALLENTRY(GPMC_NWP, "h1", "ab10"),
-	_OMAP3_BALLENTRY(GPMC_WAIT1, "l8", "ac10"),
-	_OMAP3_BALLENTRY(GPMC_WAIT2, "k8", NULL),
-	_OMAP3_BALLENTRY(GPMC_WAIT3, "j8", NULL),
-	_OMAP3_BALLENTRY(HDQ_SIO, "j25", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_CLK, "t28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA0, "t27", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA1, "u28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA2, "u27", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA3, "u26", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA4, "u25", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA5, "v28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA6, "v27", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DATA7, "v26", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_DIR, "r28", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_NXT, "t26", NULL),
-	_OMAP3_BALLENTRY(HSUSB0_STP, "t25", NULL),
-	_OMAP3_BALLENTRY(I2C2_SCL, "af15", NULL),
-	_OMAP3_BALLENTRY(I2C2_SDA, "ae15", NULL),
-	_OMAP3_BALLENTRY(I2C3_SCL, "af14", NULL),
-	_OMAP3_BALLENTRY(I2C3_SDA, "ag14", NULL),
-	_OMAP3_BALLENTRY(I2C4_SCL, "ad26", NULL),
-	_OMAP3_BALLENTRY(I2C4_SDA, "ae26", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU0, "aa11", NULL),
-	_OMAP3_BALLENTRY(JTAG_EMU1, "aa10", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKR, "y21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_CLKX, "w21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DR, "u21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_DX, "v21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSR, "aa21", NULL),
-	_OMAP3_BALLENTRY(MCBSP1_FSX, "k26", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_CLKX, "n21", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DR, "r21", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_DX, "m21", NULL),
-	_OMAP3_BALLENTRY(MCBSP2_FSX, "p21", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_CLKX, "af5", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DR, "ae6", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_DX, "af6", NULL),
-	_OMAP3_BALLENTRY(MCBSP3_FSX, "ae5", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_CLKX, "ae1", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_DR, "ad1", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_DX, "ad2", NULL),
-	_OMAP3_BALLENTRY(MCBSP4_FSX, "ac1", NULL),
-	_OMAP3_BALLENTRY(MCBSP_CLKS, "t21", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CLK, "ab3", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS0, "ac2", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS1, "ac3", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS2, "ab1", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_CS3, "ab2", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SIMO, "ab4", NULL),
-	_OMAP3_BALLENTRY(MCSPI1_SOMI, "aa4", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CLK, "aa3", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS0, "y4", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_CS1, "v3", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SIMO, "y2", NULL),
-	_OMAP3_BALLENTRY(MCSPI2_SOMI, "y3", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CLK, "n28", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_CMD, "m27", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT0, "n27", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT1, "n26", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT2, "n25", NULL),
-	_OMAP3_BALLENTRY(SDMMC1_DAT3, "p28", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CLK, "ae2", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_CMD, "ag5", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT0, "ah5", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT1, "ah4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT2, "ag4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT3, "af4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT4, "ae4", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT5, "ah3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT6, "af3", NULL),
-	_OMAP3_BALLENTRY(SDMMC2_DAT7, "ae3", NULL),
-	_OMAP3_BALLENTRY(SDRC_CKE0, "h16", "j22"),
-	_OMAP3_BALLENTRY(SDRC_CKE1, "h17", "j23"),
-	_OMAP3_BALLENTRY(SIM_CLK, "p26", NULL),
-	_OMAP3_BALLENTRY(SIM_IO, "p27", NULL),
-	_OMAP3_BALLENTRY(SIM_PWRCTRL, "r27", NULL),
-	_OMAP3_BALLENTRY(SIM_RST, "r25", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT0, "ah26", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT1, "ag26", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT2, "ae14", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT3, "af18", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT4, "af19", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT5, "ae21", NULL),
-	_OMAP3_BALLENTRY(SYS_BOOT6, "af21", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT1, "ag25", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKOUT2, "ae22", NULL),
-	_OMAP3_BALLENTRY(SYS_CLKREQ, "af25", NULL),
-	_OMAP3_BALLENTRY(SYS_NIRQ, "af26", NULL),
-	_OMAP3_BALLENTRY(SYS_NRESWARM, "af24", NULL),
-	_OMAP3_BALLENTRY(SYS_OFF_MODE, "af22", NULL),
-	_OMAP3_BALLENTRY(UART1_CTS, "w8", NULL),
-	_OMAP3_BALLENTRY(UART1_RTS, "aa9", NULL),
-	_OMAP3_BALLENTRY(UART1_RX, "y8", NULL),
-	_OMAP3_BALLENTRY(UART1_TX, "aa8", NULL),
-	_OMAP3_BALLENTRY(UART2_CTS, "ab26", NULL),
-	_OMAP3_BALLENTRY(UART2_RTS, "ab25", NULL),
-	_OMAP3_BALLENTRY(UART2_RX, "ad25", NULL),
-	_OMAP3_BALLENTRY(UART2_TX, "aa25", NULL),
-	_OMAP3_BALLENTRY(UART3_CTS_RCTX, "h18", NULL),
-	_OMAP3_BALLENTRY(UART3_RTS_SD, "h19", NULL),
-	_OMAP3_BALLENTRY(UART3_RX_IRRX, "h20", NULL),
-	_OMAP3_BALLENTRY(UART3_TX_IRTX, "h21", NULL),
-	{ .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#else
-#define omap36xx_cbp_ball	 NULL
-#endif
-
-int __init omap3_mux_init(struct omap_board_mux *board_subset, int flags)
-{
-	struct omap_mux *package_subset;
-	struct omap_ball *package_balls;
-
-	switch (flags & OMAP_PACKAGE_MASK) {
-	case OMAP_PACKAGE_CBC:
-		package_subset = omap3_cbc_subset;
-		package_balls = omap3_cbc_ball;
-		break;
-	case OMAP_PACKAGE_CBB:
-		package_subset = omap3_cbb_subset;
-		package_balls = omap3_cbb_ball;
-		break;
-	case OMAP_PACKAGE_CUS:
-		package_subset = omap3_cus_subset;
-		package_balls = omap3_cus_ball;
-		break;
-	case OMAP_PACKAGE_CBP:
-		package_subset = omap36xx_cbp_subset;
-		package_balls = omap36xx_cbp_ball;
-		break;
-	default:
-		pr_err("%s Unknown omap package, mux disabled\n", __func__);
-		return -EINVAL;
-	}
-
-	return omap_mux_init("core", OMAP_MUX_GPIO_IN_MODE4,
-			     OMAP3_CONTROL_PADCONF_MUX_PBASE,
-			     OMAP3_CONTROL_PADCONF_MUX_SIZE,
-			     omap3_muxmodes, package_subset, board_subset,
-			     package_balls);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/mux34xx.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux34xx.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/mux34xx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux34xx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,402 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia
- * 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#define OMAP3_CONTROL_PADCONF_MUX_PBASE				0x48002030LU
-
-#define OMAP3_MUX(mode0, mux_value)					\
-{									\
-	.reg_offset	= (OMAP3_CONTROL_PADCONF_##mode0##_OFFSET),	\
-	.value		= (mux_value),					\
-}
-
-/*
- * OMAP3 CONTROL_PADCONF* register offsets for pin-muxing
- *
- * Extracted from the TRM.  Add 0x48002030 to these values to get the
- * absolute addresses.  The name in the macro is the mode-0 name of
- * the pin.  NOTE: These registers are 16-bits wide.
- *
- * Note that 34XX TRM uses MMC instead of SDMMC and SAD2D instead
- * of CHASSIS for some registers. For the defines, we follow the
- * 36XX naming, and use SDMMC and CHASSIS.
- */
-#define OMAP3_CONTROL_PADCONF_SDRC_D0_OFFSET			0x000
-#define OMAP3_CONTROL_PADCONF_SDRC_D1_OFFSET			0x002
-#define OMAP3_CONTROL_PADCONF_SDRC_D2_OFFSET			0x004
-#define OMAP3_CONTROL_PADCONF_SDRC_D3_OFFSET			0x006
-#define OMAP3_CONTROL_PADCONF_SDRC_D4_OFFSET			0x008
-#define OMAP3_CONTROL_PADCONF_SDRC_D5_OFFSET			0x00a
-#define OMAP3_CONTROL_PADCONF_SDRC_D6_OFFSET			0x00c
-#define OMAP3_CONTROL_PADCONF_SDRC_D7_OFFSET			0x00e
-#define OMAP3_CONTROL_PADCONF_SDRC_D8_OFFSET			0x010
-#define OMAP3_CONTROL_PADCONF_SDRC_D9_OFFSET			0x012
-#define OMAP3_CONTROL_PADCONF_SDRC_D10_OFFSET			0x014
-#define OMAP3_CONTROL_PADCONF_SDRC_D11_OFFSET			0x016
-#define OMAP3_CONTROL_PADCONF_SDRC_D12_OFFSET			0x018
-#define OMAP3_CONTROL_PADCONF_SDRC_D13_OFFSET			0x01a
-#define OMAP3_CONTROL_PADCONF_SDRC_D14_OFFSET			0x01c
-#define OMAP3_CONTROL_PADCONF_SDRC_D15_OFFSET			0x01e
-#define OMAP3_CONTROL_PADCONF_SDRC_D16_OFFSET			0x020
-#define OMAP3_CONTROL_PADCONF_SDRC_D17_OFFSET			0x022
-#define OMAP3_CONTROL_PADCONF_SDRC_D18_OFFSET			0x024
-#define OMAP3_CONTROL_PADCONF_SDRC_D19_OFFSET			0x026
-#define OMAP3_CONTROL_PADCONF_SDRC_D20_OFFSET			0x028
-#define OMAP3_CONTROL_PADCONF_SDRC_D21_OFFSET			0x02a
-#define OMAP3_CONTROL_PADCONF_SDRC_D22_OFFSET			0x02c
-#define OMAP3_CONTROL_PADCONF_SDRC_D23_OFFSET			0x02e
-#define OMAP3_CONTROL_PADCONF_SDRC_D24_OFFSET			0x030
-#define OMAP3_CONTROL_PADCONF_SDRC_D25_OFFSET			0x032
-#define OMAP3_CONTROL_PADCONF_SDRC_D26_OFFSET			0x034
-#define OMAP3_CONTROL_PADCONF_SDRC_D27_OFFSET			0x036
-#define OMAP3_CONTROL_PADCONF_SDRC_D28_OFFSET			0x038
-#define OMAP3_CONTROL_PADCONF_SDRC_D29_OFFSET			0x03a
-#define OMAP3_CONTROL_PADCONF_SDRC_D30_OFFSET			0x03c
-#define OMAP3_CONTROL_PADCONF_SDRC_D31_OFFSET			0x03e
-#define OMAP3_CONTROL_PADCONF_SDRC_CLK_OFFSET			0x040
-#define OMAP3_CONTROL_PADCONF_SDRC_DQS0_OFFSET			0x042
-#define OMAP3_CONTROL_PADCONF_SDRC_DQS1_OFFSET			0x044
-#define OMAP3_CONTROL_PADCONF_SDRC_DQS2_OFFSET			0x046
-#define OMAP3_CONTROL_PADCONF_SDRC_DQS3_OFFSET			0x048
-#define OMAP3_CONTROL_PADCONF_GPMC_A1_OFFSET			0x04a
-#define OMAP3_CONTROL_PADCONF_GPMC_A2_OFFSET			0x04c
-#define OMAP3_CONTROL_PADCONF_GPMC_A3_OFFSET			0x04e
-#define OMAP3_CONTROL_PADCONF_GPMC_A4_OFFSET			0x050
-#define OMAP3_CONTROL_PADCONF_GPMC_A5_OFFSET			0x052
-#define OMAP3_CONTROL_PADCONF_GPMC_A6_OFFSET			0x054
-#define OMAP3_CONTROL_PADCONF_GPMC_A7_OFFSET			0x056
-#define OMAP3_CONTROL_PADCONF_GPMC_A8_OFFSET			0x058
-#define OMAP3_CONTROL_PADCONF_GPMC_A9_OFFSET			0x05a
-#define OMAP3_CONTROL_PADCONF_GPMC_A10_OFFSET			0x05c
-#define OMAP3_CONTROL_PADCONF_GPMC_D0_OFFSET			0x05e
-#define OMAP3_CONTROL_PADCONF_GPMC_D1_OFFSET			0x060
-#define OMAP3_CONTROL_PADCONF_GPMC_D2_OFFSET			0x062
-#define OMAP3_CONTROL_PADCONF_GPMC_D3_OFFSET			0x064
-#define OMAP3_CONTROL_PADCONF_GPMC_D4_OFFSET			0x066
-#define OMAP3_CONTROL_PADCONF_GPMC_D5_OFFSET			0x068
-#define OMAP3_CONTROL_PADCONF_GPMC_D6_OFFSET			0x06a
-#define OMAP3_CONTROL_PADCONF_GPMC_D7_OFFSET			0x06c
-#define OMAP3_CONTROL_PADCONF_GPMC_D8_OFFSET			0x06e
-#define OMAP3_CONTROL_PADCONF_GPMC_D9_OFFSET			0x070
-#define OMAP3_CONTROL_PADCONF_GPMC_D10_OFFSET			0x072
-#define OMAP3_CONTROL_PADCONF_GPMC_D11_OFFSET			0x074
-#define OMAP3_CONTROL_PADCONF_GPMC_D12_OFFSET			0x076
-#define OMAP3_CONTROL_PADCONF_GPMC_D13_OFFSET			0x078
-#define OMAP3_CONTROL_PADCONF_GPMC_D14_OFFSET			0x07a
-#define OMAP3_CONTROL_PADCONF_GPMC_D15_OFFSET			0x07c
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS0_OFFSET			0x07e
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS1_OFFSET			0x080
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS2_OFFSET			0x082
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS3_OFFSET			0x084
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS4_OFFSET			0x086
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS5_OFFSET			0x088
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS6_OFFSET			0x08a
-#define OMAP3_CONTROL_PADCONF_GPMC_NCS7_OFFSET			0x08c
-#define OMAP3_CONTROL_PADCONF_GPMC_CLK_OFFSET			0x08e
-#define OMAP3_CONTROL_PADCONF_GPMC_NADV_ALE_OFFSET		0x090
-#define OMAP3_CONTROL_PADCONF_GPMC_NOE_OFFSET			0x092
-#define OMAP3_CONTROL_PADCONF_GPMC_NWE_OFFSET			0x094
-#define OMAP3_CONTROL_PADCONF_GPMC_NBE0_CLE_OFFSET		0x096
-#define OMAP3_CONTROL_PADCONF_GPMC_NBE1_OFFSET			0x098
-#define OMAP3_CONTROL_PADCONF_GPMC_NWP_OFFSET			0x09a
-#define OMAP3_CONTROL_PADCONF_GPMC_WAIT0_OFFSET			0x09c
-#define OMAP3_CONTROL_PADCONF_GPMC_WAIT1_OFFSET			0x09e
-#define OMAP3_CONTROL_PADCONF_GPMC_WAIT2_OFFSET			0x0a0
-#define OMAP3_CONTROL_PADCONF_GPMC_WAIT3_OFFSET			0x0a2
-#define OMAP3_CONTROL_PADCONF_DSS_PCLK_OFFSET			0x0a4
-#define OMAP3_CONTROL_PADCONF_DSS_HSYNC_OFFSET			0x0a6
-#define OMAP3_CONTROL_PADCONF_DSS_VSYNC_OFFSET			0x0a8
-#define OMAP3_CONTROL_PADCONF_DSS_ACBIAS_OFFSET			0x0aa
-#define OMAP3_CONTROL_PADCONF_DSS_DATA0_OFFSET			0x0ac
-#define OMAP3_CONTROL_PADCONF_DSS_DATA1_OFFSET			0x0ae
-#define OMAP3_CONTROL_PADCONF_DSS_DATA2_OFFSET			0x0b0
-#define OMAP3_CONTROL_PADCONF_DSS_DATA3_OFFSET			0x0b2
-#define OMAP3_CONTROL_PADCONF_DSS_DATA4_OFFSET			0x0b4
-#define OMAP3_CONTROL_PADCONF_DSS_DATA5_OFFSET			0x0b6
-#define OMAP3_CONTROL_PADCONF_DSS_DATA6_OFFSET			0x0b8
-#define OMAP3_CONTROL_PADCONF_DSS_DATA7_OFFSET			0x0ba
-#define OMAP3_CONTROL_PADCONF_DSS_DATA8_OFFSET			0x0bc
-#define OMAP3_CONTROL_PADCONF_DSS_DATA9_OFFSET			0x0be
-#define OMAP3_CONTROL_PADCONF_DSS_DATA10_OFFSET			0x0c0
-#define OMAP3_CONTROL_PADCONF_DSS_DATA11_OFFSET			0x0c2
-#define OMAP3_CONTROL_PADCONF_DSS_DATA12_OFFSET			0x0c4
-#define OMAP3_CONTROL_PADCONF_DSS_DATA13_OFFSET			0x0c6
-#define OMAP3_CONTROL_PADCONF_DSS_DATA14_OFFSET			0x0c8
-#define OMAP3_CONTROL_PADCONF_DSS_DATA15_OFFSET			0x0ca
-#define OMAP3_CONTROL_PADCONF_DSS_DATA16_OFFSET			0x0cc
-#define OMAP3_CONTROL_PADCONF_DSS_DATA17_OFFSET			0x0ce
-#define OMAP3_CONTROL_PADCONF_DSS_DATA18_OFFSET			0x0d0
-#define OMAP3_CONTROL_PADCONF_DSS_DATA19_OFFSET			0x0d2
-#define OMAP3_CONTROL_PADCONF_DSS_DATA20_OFFSET			0x0d4
-#define OMAP3_CONTROL_PADCONF_DSS_DATA21_OFFSET			0x0d6
-#define OMAP3_CONTROL_PADCONF_DSS_DATA22_OFFSET			0x0d8
-#define OMAP3_CONTROL_PADCONF_DSS_DATA23_OFFSET			0x0da
-#define OMAP3_CONTROL_PADCONF_CAM_HS_OFFSET			0x0dc
-#define OMAP3_CONTROL_PADCONF_CAM_VS_OFFSET			0x0de
-#define OMAP3_CONTROL_PADCONF_CAM_XCLKA_OFFSET			0x0e0
-#define OMAP3_CONTROL_PADCONF_CAM_PCLK_OFFSET			0x0e2
-#define OMAP3_CONTROL_PADCONF_CAM_FLD_OFFSET			0x0e4
-#define OMAP3_CONTROL_PADCONF_CAM_D0_OFFSET			0x0e6
-#define OMAP3_CONTROL_PADCONF_CAM_D1_OFFSET			0x0e8
-#define OMAP3_CONTROL_PADCONF_CAM_D2_OFFSET			0x0ea
-#define OMAP3_CONTROL_PADCONF_CAM_D3_OFFSET			0x0ec
-#define OMAP3_CONTROL_PADCONF_CAM_D4_OFFSET			0x0ee
-#define OMAP3_CONTROL_PADCONF_CAM_D5_OFFSET			0x0f0
-#define OMAP3_CONTROL_PADCONF_CAM_D6_OFFSET			0x0f2
-#define OMAP3_CONTROL_PADCONF_CAM_D7_OFFSET			0x0f4
-#define OMAP3_CONTROL_PADCONF_CAM_D8_OFFSET			0x0f6
-#define OMAP3_CONTROL_PADCONF_CAM_D9_OFFSET			0x0f8
-#define OMAP3_CONTROL_PADCONF_CAM_D10_OFFSET			0x0fa
-#define OMAP3_CONTROL_PADCONF_CAM_D11_OFFSET			0x0fc
-#define OMAP3_CONTROL_PADCONF_CAM_XCLKB_OFFSET			0x0fe
-#define OMAP3_CONTROL_PADCONF_CAM_WEN_OFFSET			0x100
-#define OMAP3_CONTROL_PADCONF_CAM_STROBE_OFFSET			0x102
-#define OMAP3_CONTROL_PADCONF_CSI2_DX0_OFFSET			0x104
-#define OMAP3_CONTROL_PADCONF_CSI2_DY0_OFFSET			0x106
-#define OMAP3_CONTROL_PADCONF_CSI2_DX1_OFFSET			0x108
-#define OMAP3_CONTROL_PADCONF_CSI2_DY1_OFFSET			0x10a
-#define OMAP3_CONTROL_PADCONF_MCBSP2_FSX_OFFSET			0x10c
-#define OMAP3_CONTROL_PADCONF_MCBSP2_CLKX_OFFSET		0x10e
-#define OMAP3_CONTROL_PADCONF_MCBSP2_DR_OFFSET			0x110
-#define OMAP3_CONTROL_PADCONF_MCBSP2_DX_OFFSET			0x112
-#define OMAP3_CONTROL_PADCONF_SDMMC1_CLK_OFFSET			0x114
-#define OMAP3_CONTROL_PADCONF_SDMMC1_CMD_OFFSET			0x116
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT0_OFFSET		0x118
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT1_OFFSET		0x11a
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT2_OFFSET		0x11c
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT3_OFFSET		0x11e
-
-/* SDMMC1_DAT4 - DAT7 are SIM_IO SIM_CLK SIM_PWRCTRL and SIM_RST on 36xx */
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT4_OFFSET		0x120
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT5_OFFSET		0x122
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT6_OFFSET		0x124
-#define OMAP3_CONTROL_PADCONF_SDMMC1_DAT7_OFFSET		0x126
-
-#define OMAP3_CONTROL_PADCONF_SDMMC2_CLK_OFFSET			0x128
-#define OMAP3_CONTROL_PADCONF_SDMMC2_CMD_OFFSET			0x12a
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT0_OFFSET		0x12c
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT1_OFFSET		0x12e
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT2_OFFSET		0x130
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT3_OFFSET		0x132
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT4_OFFSET		0x134
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT5_OFFSET		0x136
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT6_OFFSET		0x138
-#define OMAP3_CONTROL_PADCONF_SDMMC2_DAT7_OFFSET		0x13a
-#define OMAP3_CONTROL_PADCONF_MCBSP3_DX_OFFSET			0x13c
-#define OMAP3_CONTROL_PADCONF_MCBSP3_DR_OFFSET			0x13e
-#define OMAP3_CONTROL_PADCONF_MCBSP3_CLKX_OFFSET		0x140
-#define OMAP3_CONTROL_PADCONF_MCBSP3_FSX_OFFSET			0x142
-#define OMAP3_CONTROL_PADCONF_UART2_CTS_OFFSET			0x144
-#define OMAP3_CONTROL_PADCONF_UART2_RTS_OFFSET			0x146
-#define OMAP3_CONTROL_PADCONF_UART2_TX_OFFSET			0x148
-#define OMAP3_CONTROL_PADCONF_UART2_RX_OFFSET			0x14a
-#define OMAP3_CONTROL_PADCONF_UART1_TX_OFFSET			0x14c
-#define OMAP3_CONTROL_PADCONF_UART1_RTS_OFFSET			0x14e
-#define OMAP3_CONTROL_PADCONF_UART1_CTS_OFFSET			0x150
-#define OMAP3_CONTROL_PADCONF_UART1_RX_OFFSET			0x152
-#define OMAP3_CONTROL_PADCONF_MCBSP4_CLKX_OFFSET		0x154
-#define OMAP3_CONTROL_PADCONF_MCBSP4_DR_OFFSET			0x156
-#define OMAP3_CONTROL_PADCONF_MCBSP4_DX_OFFSET			0x158
-#define OMAP3_CONTROL_PADCONF_MCBSP4_FSX_OFFSET			0x15a
-#define OMAP3_CONTROL_PADCONF_MCBSP1_CLKR_OFFSET		0x15c
-#define OMAP3_CONTROL_PADCONF_MCBSP1_FSR_OFFSET			0x15e
-#define OMAP3_CONTROL_PADCONF_MCBSP1_DX_OFFSET			0x160
-#define OMAP3_CONTROL_PADCONF_MCBSP1_DR_OFFSET			0x162
-#define OMAP3_CONTROL_PADCONF_MCBSP_CLKS_OFFSET			0x164
-#define OMAP3_CONTROL_PADCONF_MCBSP1_FSX_OFFSET			0x166
-#define OMAP3_CONTROL_PADCONF_MCBSP1_CLKX_OFFSET		0x168
-#define OMAP3_CONTROL_PADCONF_UART3_CTS_RCTX_OFFSET		0x16a
-#define OMAP3_CONTROL_PADCONF_UART3_RTS_SD_OFFSET		0x16c
-#define OMAP3_CONTROL_PADCONF_UART3_RX_IRRX_OFFSET		0x16e
-#define OMAP3_CONTROL_PADCONF_UART3_TX_IRTX_OFFSET		0x170
-#define OMAP3_CONTROL_PADCONF_HSUSB0_CLK_OFFSET			0x172
-#define OMAP3_CONTROL_PADCONF_HSUSB0_STP_OFFSET			0x174
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DIR_OFFSET			0x176
-#define OMAP3_CONTROL_PADCONF_HSUSB0_NXT_OFFSET			0x178
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA0_OFFSET		0x17a
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA1_OFFSET		0x17c
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA2_OFFSET		0x17e
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA3_OFFSET		0x180
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA4_OFFSET		0x182
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA5_OFFSET		0x184
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA6_OFFSET		0x186
-#define OMAP3_CONTROL_PADCONF_HSUSB0_DATA7_OFFSET		0x188
-#define OMAP3_CONTROL_PADCONF_I2C1_SCL_OFFSET			0x18a
-#define OMAP3_CONTROL_PADCONF_I2C1_SDA_OFFSET			0x18c
-#define OMAP3_CONTROL_PADCONF_I2C2_SCL_OFFSET			0x18e
-#define OMAP3_CONTROL_PADCONF_I2C2_SDA_OFFSET			0x190
-#define OMAP3_CONTROL_PADCONF_I2C3_SCL_OFFSET			0x192
-#define OMAP3_CONTROL_PADCONF_I2C3_SDA_OFFSET			0x194
-#define OMAP3_CONTROL_PADCONF_HDQ_SIO_OFFSET			0x196
-#define OMAP3_CONTROL_PADCONF_MCSPI1_CLK_OFFSET			0x198
-#define OMAP3_CONTROL_PADCONF_MCSPI1_SIMO_OFFSET		0x19a
-#define OMAP3_CONTROL_PADCONF_MCSPI1_SOMI_OFFSET		0x19c
-#define OMAP3_CONTROL_PADCONF_MCSPI1_CS0_OFFSET			0x19e
-#define OMAP3_CONTROL_PADCONF_MCSPI1_CS1_OFFSET			0x1a0
-#define OMAP3_CONTROL_PADCONF_MCSPI1_CS2_OFFSET			0x1a2
-#define OMAP3_CONTROL_PADCONF_MCSPI1_CS3_OFFSET			0x1a4
-#define OMAP3_CONTROL_PADCONF_MCSPI2_CLK_OFFSET			0x1a6
-#define OMAP3_CONTROL_PADCONF_MCSPI2_SIMO_OFFSET		0x1a8
-#define OMAP3_CONTROL_PADCONF_MCSPI2_SOMI_OFFSET		0x1aa
-#define OMAP3_CONTROL_PADCONF_MCSPI2_CS0_OFFSET			0x1ac
-#define OMAP3_CONTROL_PADCONF_MCSPI2_CS1_OFFSET			0x1ae
-#define OMAP3_CONTROL_PADCONF_SYS_NIRQ_OFFSET			0x1b0
-#define OMAP3_CONTROL_PADCONF_SYS_CLKOUT2_OFFSET		0x1b2
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD0_OFFSET		0x1b4
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD1_OFFSET		0x1b6
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD2_OFFSET		0x1b8
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD3_OFFSET		0x1ba
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD4_OFFSET		0x1bc
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD5_OFFSET		0x1be
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD6_OFFSET		0x1c0
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD7_OFFSET		0x1c2
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD8_OFFSET		0x1c4
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD9_OFFSET		0x1c6
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD10_OFFSET		0x1c8
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD11_OFFSET		0x1ca
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD12_OFFSET		0x1cc
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD13_OFFSET		0x1ce
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD14_OFFSET		0x1d0
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD15_OFFSET		0x1d2
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD16_OFFSET		0x1d4
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD17_OFFSET		0x1d6
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD18_OFFSET		0x1d8
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD19_OFFSET		0x1da
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD20_OFFSET		0x1dc
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD21_OFFSET		0x1de
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD22_OFFSET		0x1e0
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD23_OFFSET		0x1e2
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD24_OFFSET		0x1e4
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD25_OFFSET		0x1e6
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD26_OFFSET		0x1e8
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD27_OFFSET		0x1ea
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD28_OFFSET		0x1ec
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD29_OFFSET		0x1ee
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD30_OFFSET		0x1f0
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD31_OFFSET		0x1f2
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD32_OFFSET		0x1f4
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD33_OFFSET		0x1f6
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD34_OFFSET		0x1f8
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD35_OFFSET		0x1fa
-#define OMAP3_CONTROL_PADCONF_SAD2D_MCAD36_OFFSET		0x1fc
-
-/* Note that 34xx TRM has SAD2D instead of CHASSIS for these */
-#define OMAP3_CONTROL_PADCONF_CHASSIS_CLK26MI_OFFSET		0x1fe
-#define OMAP3_CONTROL_PADCONF_CHASSIS_NRESPWRON_OFFSET		0x200
-#define OMAP3_CONTROL_PADCONF_CHASSIS_NRESWARW_OFFSET		0x202
-#define OMAP3_CONTROL_PADCONF_CHASSIS_NIRQ_OFFSET		0x204
-#define OMAP3_CONTROL_PADCONF_CHASSIS_FIQ_OFFSET		0x206
-#define OMAP3_CONTROL_PADCONF_CHASSIS_ARMIRQ_OFFSET		0x208
-#define OMAP3_CONTROL_PADCONF_CHASSIS_IVAIRQ_OFFSET		0x20a
-#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ0_OFFSET		0x20c
-#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ1_OFFSET		0x20e
-#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ2_OFFSET		0x210
-#define OMAP3_CONTROL_PADCONF_CHASSIS_DMAREQ3_OFFSET		0x212
-#define OMAP3_CONTROL_PADCONF_CHASSIS_NTRST_OFFSET		0x214
-#define OMAP3_CONTROL_PADCONF_CHASSIS_TDI_OFFSET		0x216
-#define OMAP3_CONTROL_PADCONF_CHASSIS_TDO_OFFSET		0x218
-#define OMAP3_CONTROL_PADCONF_CHASSIS_TMS_OFFSET		0x21a
-#define OMAP3_CONTROL_PADCONF_CHASSIS_TCK_OFFSET		0x21c
-#define OMAP3_CONTROL_PADCONF_CHASSIS_RTCK_OFFSET		0x21e
-#define OMAP3_CONTROL_PADCONF_CHASSIS_MSTDBY_OFFSET		0x220
-#define OMAP3_CONTROL_PADCONF_CHASSIS_IDLEREQ_OFFSET		0x222
-#define OMAP3_CONTROL_PADCONF_CHASSIS_IDLEACK_OFFSET		0x224
-
-#define OMAP3_CONTROL_PADCONF_SAD2D_MWRITE_OFFSET		0x226
-#define OMAP3_CONTROL_PADCONF_SAD2D_SWRITE_OFFSET		0x228
-#define OMAP3_CONTROL_PADCONF_SAD2D_MREAD_OFFSET		0x22a
-#define OMAP3_CONTROL_PADCONF_SAD2D_SREAD_OFFSET		0x22c
-#define OMAP3_CONTROL_PADCONF_SAD2D_MBUSFLAG_OFFSET		0x22e
-#define OMAP3_CONTROL_PADCONF_SAD2D_SBUSFLAG_OFFSET		0x230
-#define OMAP3_CONTROL_PADCONF_SDRC_CKE0_OFFSET			0x232
-#define OMAP3_CONTROL_PADCONF_SDRC_CKE1_OFFSET			0x234
-
-/* 36xx only */
-#define OMAP3_CONTROL_PADCONF_GPMC_A11_OFFSET			0x236
-#define OMAP3_CONTROL_PADCONF_SDRC_BA0_OFFSET			0x570
-#define OMAP3_CONTROL_PADCONF_SDRC_BA1_OFFSET			0x572
-#define OMAP3_CONTROL_PADCONF_SDRC_A0_OFFSET			0x574
-#define OMAP3_CONTROL_PADCONF_SDRC_A1_OFFSET			0x576
-#define OMAP3_CONTROL_PADCONF_SDRC_A2_OFFSET			0x578
-#define OMAP3_CONTROL_PADCONF_SDRC_A3_OFFSET			0x57a
-#define OMAP3_CONTROL_PADCONF_SDRC_A4_OFFSET			0x57c
-#define OMAP3_CONTROL_PADCONF_SDRC_A5_OFFSET			0x57e
-#define OMAP3_CONTROL_PADCONF_SDRC_A6_OFFSET			0x580
-#define OMAP3_CONTROL_PADCONF_SDRC_A7_OFFSET			0x582
-#define OMAP3_CONTROL_PADCONF_SDRC_A8_OFFSET			0x584
-#define OMAP3_CONTROL_PADCONF_SDRC_A9_OFFSET			0x586
-#define OMAP3_CONTROL_PADCONF_SDRC_A10_OFFSET			0x588
-#define OMAP3_CONTROL_PADCONF_SDRC_A11_OFFSET			0x58a
-#define OMAP3_CONTROL_PADCONF_SDRC_A12_OFFSET			0x58c
-#define OMAP3_CONTROL_PADCONF_SDRC_A13_OFFSET			0x58e
-#define OMAP3_CONTROL_PADCONF_SDRC_A14_OFFSET			0x590
-#define OMAP3_CONTROL_PADCONF_SDRC_NCS0_OFFSET			0x592
-#define OMAP3_CONTROL_PADCONF_SDRC_NCS1_OFFSET			0x594
-#define OMAP3_CONTROL_PADCONF_SDRC_NCLK_OFFSET			0x596
-#define OMAP3_CONTROL_PADCONF_SDRC_NRAS_OFFSET			0x598
-#define OMAP3_CONTROL_PADCONF_SDRC_NCAS_OFFSET			0x59a
-#define OMAP3_CONTROL_PADCONF_SDRC_NWE_OFFSET			0x59c
-#define OMAP3_CONTROL_PADCONF_SDRC_DM0_OFFSET			0x59e
-#define OMAP3_CONTROL_PADCONF_SDRC_DM1_OFFSET			0x5a0
-#define OMAP3_CONTROL_PADCONF_SDRC_DM2_OFFSET			0x5a2
-#define OMAP3_CONTROL_PADCONF_SDRC_DM3_OFFSET			0x5a4
-
-/* 36xx only, these are SDMMC1_DAT4 - DAT7 on 34xx */
-#define OMAP3_CONTROL_PADCONF_SIM_IO_OFFSET			0x120
-#define OMAP3_CONTROL_PADCONF_SIM_CLK_OFFSET			0x122
-#define OMAP3_CONTROL_PADCONF_SIM_PWRCTRL_OFFSET		0x124
-#define OMAP3_CONTROL_PADCONF_SIM_RST_OFFSET			0x126
-
-#define OMAP3_CONTROL_PADCONF_ETK_CLK_OFFSET			0x5a8
-#define OMAP3_CONTROL_PADCONF_ETK_CTL_OFFSET			0x5aa
-#define OMAP3_CONTROL_PADCONF_ETK_D0_OFFSET			0x5ac
-#define OMAP3_CONTROL_PADCONF_ETK_D1_OFFSET			0x5ae
-#define OMAP3_CONTROL_PADCONF_ETK_D2_OFFSET			0x5b0
-#define OMAP3_CONTROL_PADCONF_ETK_D3_OFFSET			0x5b2
-#define OMAP3_CONTROL_PADCONF_ETK_D4_OFFSET			0x5b4
-#define OMAP3_CONTROL_PADCONF_ETK_D5_OFFSET			0x5b6
-#define OMAP3_CONTROL_PADCONF_ETK_D6_OFFSET			0x5b8
-#define OMAP3_CONTROL_PADCONF_ETK_D7_OFFSET			0x5ba
-#define OMAP3_CONTROL_PADCONF_ETK_D8_OFFSET			0x5bc
-#define OMAP3_CONTROL_PADCONF_ETK_D9_OFFSET			0x5be
-#define OMAP3_CONTROL_PADCONF_ETK_D10_OFFSET			0x5c0
-#define OMAP3_CONTROL_PADCONF_ETK_D11_OFFSET			0x5c2
-#define OMAP3_CONTROL_PADCONF_ETK_D12_OFFSET			0x5c4
-#define OMAP3_CONTROL_PADCONF_ETK_D13_OFFSET			0x5c6
-#define OMAP3_CONTROL_PADCONF_ETK_D14_OFFSET			0x5c8
-#define OMAP3_CONTROL_PADCONF_ETK_D15_OFFSET			0x5ca
-#define OMAP3_CONTROL_PADCONF_I2C4_SCL_OFFSET			0x9d0
-#define OMAP3_CONTROL_PADCONF_I2C4_SDA_OFFSET			0x9d2
-#define OMAP3_CONTROL_PADCONF_SYS_32K_OFFSET			0x9d4
-#define OMAP3_CONTROL_PADCONF_SYS_CLKREQ_OFFSET			0x9d6
-#define OMAP3_CONTROL_PADCONF_SYS_NRESWARM_OFFSET		0x9d8
-#define OMAP3_CONTROL_PADCONF_SYS_BOOT0_OFFSET			0x9da
-#define OMAP3_CONTROL_PADCONF_SYS_BOOT1_OFFSET			0x9dc
-#define OMAP3_CONTROL_PADCONF_SYS_BOOT2_OFFSET			0x9de
-#define OMAP3_CONTROL_PADCONF_SYS_BOOT3_OFFSET			0x9e0
-#define OMAP3_CONTROL_PADCONF_SYS_BOOT4_OFFSET			0x9e2
-#define OMAP3_CONTROL_PADCONF_SYS_BOOT5_OFFSET			0x9e4
-#define OMAP3_CONTROL_PADCONF_SYS_BOOT6_OFFSET			0x9e6
-#define OMAP3_CONTROL_PADCONF_SYS_OFF_MODE_OFFSET		0x9e8
-#define OMAP3_CONTROL_PADCONF_SYS_CLKOUT1_OFFSET		0x9ea
-#define OMAP3_CONTROL_PADCONF_JTAG_NTRST_OFFSET			0x9ec
-#define OMAP3_CONTROL_PADCONF_JTAG_TCK_OFFSET			0x9ee
-#define OMAP3_CONTROL_PADCONF_JTAG_TMS_TMSC_OFFSET		0x9f0
-#define OMAP3_CONTROL_PADCONF_JTAG_TDI_OFFSET			0x9f2
-#define OMAP3_CONTROL_PADCONF_JTAG_EMU0_OFFSET			0x9f4
-#define OMAP3_CONTROL_PADCONF_JTAG_EMU1_OFFSET			0x9f6
-#define OMAP3_CONTROL_PADCONF_SAD2D_SWAKEUP_OFFSET		0xa1c
-#define OMAP3_CONTROL_PADCONF_JTAG_RTCK_OFFSET			0xa1e
-#define OMAP3_CONTROL_PADCONF_JTAG_TDO_OFFSET			0xa20
-#define OMAP3_CONTROL_PADCONF_GPIO_127				0xa24
-#define OMAP3_CONTROL_PADCONF_GPIO_126				0xa26
-#define OMAP3_CONTROL_PADCONF_GPIO_128				0xa28
-#define OMAP3_CONTROL_PADCONF_GPIO_129				0xa2a
-
-#define OMAP3_CONTROL_PADCONF_MUX_SIZE				\
-		(OMAP3_CONTROL_PADCONF_GPIO_129 + 0x2)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/mux.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/mux.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1153 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/mux.c
- *
- * OMAP2, OMAP3 and OMAP4 pin multiplexing configurations
- *
- * Copyright (C) 2004 - 2010 Texas Instruments Inc.
- * Copyright (C) 2003 - 2008 Nokia Corporation
- *
- * Written by Tony Lindgren
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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/io.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-
-
-#include "omap_hwmod.h"
-
-#include "soc.h"
-#include "control.h"
-#include "mux.h"
-#include "prm.h"
-#include "common.h"
-
-#define OMAP_MUX_BASE_OFFSET		0x30	/* Offset from CTRL_BASE */
-#define OMAP_MUX_BASE_SZ		0x5ca
-
-struct omap_mux_entry {
-	struct omap_mux		mux;
-	struct list_head	node;
-};
-
-static LIST_HEAD(mux_partitions);
-static DEFINE_MUTEX(muxmode_mutex);
-
-struct omap_mux_partition *omap_mux_get(const char *name)
-{
-	struct omap_mux_partition *partition;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		if (!strcmp(name, partition->name))
-			return partition;
-	}
-
-	return NULL;
-}
-
-u16 omap_mux_read(struct omap_mux_partition *partition, u16 reg)
-{
-	if (partition->flags & OMAP_MUX_REG_8BIT)
-		return readb_relaxed(partition->base + reg);
-	else
-		return readw_relaxed(partition->base + reg);
-}
-
-void omap_mux_write(struct omap_mux_partition *partition, u16 val,
-			   u16 reg)
-{
-	if (partition->flags & OMAP_MUX_REG_8BIT)
-		writeb_relaxed(val, partition->base + reg);
-	else
-		writew_relaxed(val, partition->base + reg);
-}
-
-void omap_mux_write_array(struct omap_mux_partition *partition,
-				 struct omap_board_mux *board_mux)
-{
-	if (!board_mux)
-		return;
-
-	while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {
-		omap_mux_write(partition, board_mux->value,
-			       board_mux->reg_offset);
-		board_mux++;
-	}
-}
-
-#ifdef CONFIG_OMAP_MUX
-
-static char *omap_mux_options;
-
-static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition,
-				      int gpio, int val)
-{
-	struct omap_mux_entry *e;
-	struct omap_mux *gpio_mux = NULL;
-	u16 old_mode;
-	u16 mux_mode;
-	int found = 0;
-	struct list_head *muxmodes = &partition->muxmodes;
-
-	if (!gpio)
-		return -EINVAL;
-
-	list_for_each_entry(e, muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-		if (gpio == m->gpio) {
-			gpio_mux = m;
-			found++;
-		}
-	}
-
-	if (found == 0) {
-		pr_err("%s: Could not set gpio%i\n", __func__, gpio);
-		return -ENODEV;
-	}
-
-	if (found > 1) {
-		pr_info("%s: Multiple gpio paths (%d) for gpio%i\n", __func__,
-			found, gpio);
-		return -EINVAL;
-	}
-
-	old_mode = omap_mux_read(partition, gpio_mux->reg_offset);
-	mux_mode = val & ~(OMAP_MUX_NR_MODES - 1);
-	mux_mode |= partition->gpio;
-	pr_debug("%s: Setting signal %s.gpio%i 0x%04x -> 0x%04x\n", __func__,
-		 gpio_mux->muxnames[0], gpio, old_mode, mux_mode);
-	omap_mux_write(partition, mux_mode, gpio_mux->reg_offset);
-
-	return 0;
-}
-
-int __init omap_mux_init_gpio(int gpio, int val)
-{
-	struct omap_mux_partition *partition;
-	int ret;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		ret = _omap_mux_init_gpio(partition, gpio, val);
-		if (!ret)
-			return ret;
-	}
-
-	return -ENODEV;
-}
-
-static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
-					const char *muxname,
-					struct omap_mux **found_mux)
-{
-	struct omap_mux *mux = NULL;
-	struct omap_mux_entry *e;
-	const char *mode_name;
-	int found = 0, found_mode = 0, mode0_len = 0;
-	struct list_head *muxmodes = &partition->muxmodes;
-
-	mode_name = strchr(muxname, '.');
-	if (mode_name) {
-		mode0_len = strlen(muxname) - strlen(mode_name);
-		mode_name++;
-	} else {
-		mode_name = muxname;
-	}
-
-	list_for_each_entry(e, muxmodes, node) {
-		char *m0_entry;
-		int i;
-
-		mux = &e->mux;
-		m0_entry = mux->muxnames[0];
-
-		/* First check for full name in mode0.muxmode format */
-		if (mode0_len)
-			if (strncmp(muxname, m0_entry, mode0_len) ||
-			    (strlen(m0_entry) != mode0_len))
-				continue;
-
-		/* Then check for muxmode only */
-		for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
-			char *mode_cur = mux->muxnames[i];
-
-			if (!mode_cur)
-				continue;
-
-			if (!strcmp(mode_name, mode_cur)) {
-				*found_mux = mux;
-				found++;
-				found_mode = i;
-			}
-		}
-	}
-
-	if (found == 1) {
-		return found_mode;
-	}
-
-	if (found > 1) {
-		pr_err("%s: Multiple signal paths (%i) for %s\n", __func__,
-		       found, muxname);
-		return -EINVAL;
-	}
-
-	return -ENODEV;
-}
-
-int __init omap_mux_get_by_name(const char *muxname,
-			struct omap_mux_partition **found_partition,
-			struct omap_mux **found_mux)
-{
-	struct omap_mux_partition *partition;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		struct omap_mux *mux = NULL;
-		int mux_mode = _omap_mux_get_by_name(partition, muxname, &mux);
-		if (mux_mode < 0)
-			continue;
-
-		*found_partition = partition;
-		*found_mux = mux;
-
-		return mux_mode;
-	}
-
-	pr_err("%s: Could not find signal %s\n", __func__, muxname);
-
-	return -ENODEV;
-}
-
-int __init omap_mux_init_signal(const char *muxname, int val)
-{
-	struct omap_mux_partition *partition = NULL;
-	struct omap_mux *mux = NULL;
-	u16 old_mode;
-	int mux_mode;
-
-	mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);
-	if (mux_mode < 0 || !mux)
-		return mux_mode;
-
-	old_mode = omap_mux_read(partition, mux->reg_offset);
-	mux_mode |= val;
-	pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",
-			 __func__, muxname, old_mode, mux_mode);
-	omap_mux_write(partition, mux_mode, mux->reg_offset);
-
-	return 0;
-}
-
-struct omap_hwmod_mux_info * __init
-omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
-{
-	struct omap_hwmod_mux_info *hmux;
-	int i, nr_pads_dynamic = 0;
-
-	if (!bpads || nr_pads < 1)
-		return NULL;
-
-	hmux = kzalloc(sizeof(struct omap_hwmod_mux_info), GFP_KERNEL);
-	if (!hmux)
-		goto err1;
-
-	hmux->nr_pads = nr_pads;
-
-	hmux->pads = kzalloc(sizeof(struct omap_device_pad) *
-				nr_pads, GFP_KERNEL);
-	if (!hmux->pads)
-		goto err2;
-
-	for (i = 0; i < hmux->nr_pads; i++) {
-		struct omap_mux_partition *partition;
-		struct omap_device_pad *bpad = &bpads[i], *pad = &hmux->pads[i];
-		struct omap_mux *mux;
-		int mux_mode;
-
-		mux_mode = omap_mux_get_by_name(bpad->name, &partition, &mux);
-		if (mux_mode < 0)
-			goto err3;
-		if (!pad->partition)
-			pad->partition = partition;
-		if (!pad->mux)
-			pad->mux = mux;
-
-		pad->name = kzalloc(strlen(bpad->name) + 1, GFP_KERNEL);
-		if (!pad->name) {
-			int j;
-
-			for (j = i - 1; j >= 0; j--)
-				kfree(hmux->pads[j].name);
-			goto err3;
-		}
-		strcpy(pad->name, bpad->name);
-
-		pad->flags = bpad->flags;
-		pad->enable = bpad->enable;
-		pad->idle = bpad->idle;
-		pad->off = bpad->off;
-
-		if (pad->flags &
-		    (OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP))
-			nr_pads_dynamic++;
-
-		pr_debug("%s: Initialized %s\n", __func__, pad->name);
-	}
-
-	if (!nr_pads_dynamic)
-		return hmux;
-
-	/*
-	 * Add pads that need dynamic muxing into a separate list
-	 */
-
-	hmux->nr_pads_dynamic = nr_pads_dynamic;
-	hmux->pads_dynamic = kzalloc(sizeof(struct omap_device_pad *) *
-					nr_pads_dynamic, GFP_KERNEL);
-	if (!hmux->pads_dynamic) {
-		pr_err("%s: Could not allocate dynamic pads\n", __func__);
-		return hmux;
-	}
-
-	nr_pads_dynamic = 0;
-	for (i = 0; i < hmux->nr_pads; i++) {
-		struct omap_device_pad *pad = &hmux->pads[i];
-
-		if (pad->flags &
-		    (OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP)) {
-			pr_debug("%s: pad %s tagged dynamic\n",
-					__func__, pad->name);
-			hmux->pads_dynamic[nr_pads_dynamic] = pad;
-			nr_pads_dynamic++;
-		}
-	}
-
-	return hmux;
-
-err3:
-	kfree(hmux->pads);
-err2:
-	kfree(hmux);
-err1:
-	pr_err("%s: Could not allocate device mux entry\n", __func__);
-
-	return NULL;
-}
-
-/**
- * omap_hwmod_mux_scan_wakeups - omap hwmod scan wakeup pads
- * @hmux: Pads for a hwmod
- * @mpu_irqs: MPU irq array for a hwmod
- *
- * Scans the wakeup status of pads for a single hwmod.  If an irq
- * array is defined for this mux, the parser will call the registered
- * ISRs for corresponding pads, otherwise the parser will stop at the
- * first wakeup active pad and return.  Returns true if there is a
- * pending and non-served wakeup event for the mux, otherwise false.
- */
-static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,
-		struct omap_hwmod_irq_info *mpu_irqs)
-{
-	int i, irq;
-	unsigned int val;
-	u32 handled_irqs = 0;
-
-	for (i = 0; i < hmux->nr_pads_dynamic; i++) {
-		struct omap_device_pad *pad = hmux->pads_dynamic[i];
-
-		if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP) ||
-		    !(pad->idle & OMAP_WAKEUP_EN))
-			continue;
-
-		val = omap_mux_read(pad->partition, pad->mux->reg_offset);
-		if (!(val & OMAP_WAKEUP_EVENT))
-			continue;
-
-		if (!hmux->irqs)
-			return true;
-
-		irq = hmux->irqs[i];
-		/* make sure we only handle each irq once */
-		if (handled_irqs & 1 << irq)
-			continue;
-
-		handled_irqs |= 1 << irq;
-
-		generic_handle_irq(mpu_irqs[irq].irq);
-	}
-
-	return false;
-}
-
-/**
- * _omap_hwmod_mux_handle_irq - Process wakeup events for a single hwmod
- *
- * Checks a single hwmod for every wakeup capable pad to see if there is an
- * active wakeup event. If this is the case, call the corresponding ISR.
- */
-static int _omap_hwmod_mux_handle_irq(struct omap_hwmod *oh, void *data)
-{
-	if (!oh->mux || !oh->mux->enabled)
-		return 0;
-	if (omap_hwmod_mux_scan_wakeups(oh->mux, oh->mpu_irqs))
-		generic_handle_irq(oh->mpu_irqs[0].irq);
-	return 0;
-}
-
-/**
- * omap_hwmod_mux_handle_irq - Process pad wakeup irqs.
- *
- * Calls a function for each registered omap_hwmod to check
- * pad wakeup statuses.
- */
-static irqreturn_t omap_hwmod_mux_handle_irq(int irq, void *unused)
-{
-	omap_hwmod_for_each(_omap_hwmod_mux_handle_irq, NULL);
-	return IRQ_HANDLED;
-}
-
-/* Assumes the calling function takes care of locking */
-void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
-{
-	int i;
-
-	/* Runtime idling of dynamic pads */
-	if (state == _HWMOD_STATE_IDLE && hmux->enabled) {
-		for (i = 0; i < hmux->nr_pads_dynamic; i++) {
-			struct omap_device_pad *pad = hmux->pads_dynamic[i];
-			int val = -EINVAL;
-
-			val = pad->idle;
-			omap_mux_write(pad->partition, val,
-					pad->mux->reg_offset);
-		}
-
-		return;
-	}
-
-	/* Runtime enabling of dynamic pads */
-	if ((state == _HWMOD_STATE_ENABLED) && hmux->pads_dynamic
-					&& hmux->enabled) {
-		for (i = 0; i < hmux->nr_pads_dynamic; i++) {
-			struct omap_device_pad *pad = hmux->pads_dynamic[i];
-			int val = -EINVAL;
-
-			val = pad->enable;
-			omap_mux_write(pad->partition, val,
-					pad->mux->reg_offset);
-		}
-
-		return;
-	}
-
-	/* Enabling or disabling of all pads */
-	for (i = 0; i < hmux->nr_pads; i++) {
-		struct omap_device_pad *pad = &hmux->pads[i];
-		int flags, val = -EINVAL;
-
-		flags = pad->flags;
-
-		switch (state) {
-		case _HWMOD_STATE_ENABLED:
-			val = pad->enable;
-			pr_debug("%s: Enabling %s %x\n", __func__,
-					pad->name, val);
-			break;
-		case _HWMOD_STATE_DISABLED:
-			/* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
-			if (flags & OMAP_DEVICE_PAD_REMUX)
-				val = pad->off;
-			else
-				val = OMAP_MUX_MODE7;
-			pr_debug("%s: Disabling %s %x\n", __func__,
-					pad->name, val);
-			break;
-		default:
-			/* Nothing to be done */
-			break;
-		}
-
-		if (val >= 0) {
-			omap_mux_write(pad->partition, val,
-					pad->mux->reg_offset);
-			pad->flags = flags;
-		}
-	}
-
-	if (state == _HWMOD_STATE_ENABLED)
-		hmux->enabled = true;
-	else
-		hmux->enabled = false;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-#define OMAP_MUX_MAX_NR_FLAGS	10
-#define OMAP_MUX_TEST_FLAG(val, mask)				\
-	if (((val) & (mask)) == (mask)) {			\
-		i++;						\
-		flags[i] =  #mask;				\
-	}
-
-/* REVISIT: Add checking for non-optimal mux settings */
-static inline void omap_mux_decode(struct seq_file *s, u16 val)
-{
-	char *flags[OMAP_MUX_MAX_NR_FLAGS];
-	char mode[sizeof("OMAP_MUX_MODE") + 1];
-	int i = -1;
-
-	sprintf(mode, "OMAP_MUX_MODE%d", val & 0x7);
-	i++;
-	flags[i] = mode;
-
-	OMAP_MUX_TEST_FLAG(val, OMAP_PIN_OFF_WAKEUPENABLE);
-	if (val & OMAP_OFF_EN) {
-		if (!(val & OMAP_OFFOUT_EN)) {
-			if (!(val & OMAP_OFF_PULL_UP)) {
-				OMAP_MUX_TEST_FLAG(val,
-					OMAP_PIN_OFF_INPUT_PULLDOWN);
-			} else {
-				OMAP_MUX_TEST_FLAG(val,
-					OMAP_PIN_OFF_INPUT_PULLUP);
-			}
-		} else {
-			if (!(val & OMAP_OFFOUT_VAL)) {
-				OMAP_MUX_TEST_FLAG(val,
-					OMAP_PIN_OFF_OUTPUT_LOW);
-			} else {
-				OMAP_MUX_TEST_FLAG(val,
-					OMAP_PIN_OFF_OUTPUT_HIGH);
-			}
-		}
-	}
-
-	if (val & OMAP_INPUT_EN) {
-		if (val & OMAP_PULL_ENA) {
-			if (!(val & OMAP_PULL_UP)) {
-				OMAP_MUX_TEST_FLAG(val,
-					OMAP_PIN_INPUT_PULLDOWN);
-			} else {
-				OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT_PULLUP);
-			}
-		} else {
-			OMAP_MUX_TEST_FLAG(val, OMAP_PIN_INPUT);
-		}
-	} else {
-		i++;
-		flags[i] = "OMAP_PIN_OUTPUT";
-	}
-
-	do {
-		seq_printf(s, "%s", flags[i]);
-		if (i > 0)
-			seq_printf(s, " | ");
-	} while (i-- > 0);
-}
-
-#define OMAP_MUX_DEFNAME_LEN	32
-
-static int omap_mux_dbg_board_show(struct seq_file *s, void *unused)
-{
-	struct omap_mux_partition *partition = s->private;
-	struct omap_mux_entry *e;
-	u8 omap_gen = omap_rev() >> 28;
-
-	list_for_each_entry(e, &partition->muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-		char m0_def[OMAP_MUX_DEFNAME_LEN];
-		char *m0_name = m->muxnames[0];
-		u16 val;
-		int i, mode;
-
-		if (!m0_name)
-			continue;
-
-		/* REVISIT: Needs to be updated if mode0 names get longer */
-		for (i = 0; i < OMAP_MUX_DEFNAME_LEN; i++) {
-			if (m0_name[i] == '\0') {
-				m0_def[i] = m0_name[i];
-				break;
-			}
-			m0_def[i] = toupper(m0_name[i]);
-		}
-		val = omap_mux_read(partition, m->reg_offset);
-		mode = val & OMAP_MUX_MODE7;
-		if (mode != 0)
-			seq_printf(s, "/* %s */\n", m->muxnames[mode]);
-
-		/*
-		 * XXX: Might be revisited to support differences across
-		 * same OMAP generation.
-		 */
-		seq_printf(s, "OMAP%d_MUX(%s, ", omap_gen, m0_def);
-		omap_mux_decode(s, val);
-		seq_printf(s, "),\n");
-	}
-
-	return 0;
-}
-
-static int omap_mux_dbg_board_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, omap_mux_dbg_board_show, inode->i_private);
-}
-
-static const struct file_operations omap_mux_dbg_board_fops = {
-	.open		= omap_mux_dbg_board_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static struct omap_mux_partition *omap_mux_get_partition(struct omap_mux *mux)
-{
-	struct omap_mux_partition *partition;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		struct list_head *muxmodes = &partition->muxmodes;
-		struct omap_mux_entry *e;
-
-		list_for_each_entry(e, muxmodes, node) {
-			struct omap_mux *m = &e->mux;
-
-			if (m == mux)
-				return partition;
-		}
-	}
-
-	return NULL;
-}
-
-static int omap_mux_dbg_signal_show(struct seq_file *s, void *unused)
-{
-	struct omap_mux *m = s->private;
-	struct omap_mux_partition *partition;
-	const char *none = "NA";
-	u16 val;
-	int mode;
-
-	partition = omap_mux_get_partition(m);
-	if (!partition)
-		return 0;
-
-	val = omap_mux_read(partition, m->reg_offset);
-	mode = val & OMAP_MUX_MODE7;
-
-	seq_printf(s, "name: %s.%s (0x%08x/0x%03x = 0x%04x), b %s, t %s\n",
-			m->muxnames[0], m->muxnames[mode],
-			partition->phys + m->reg_offset, m->reg_offset, val,
-			m->balls[0] ? m->balls[0] : none,
-			m->balls[1] ? m->balls[1] : none);
-	seq_printf(s, "mode: ");
-	omap_mux_decode(s, val);
-	seq_printf(s, "\n");
-	seq_printf(s, "signals: %s | %s | %s | %s | %s | %s | %s | %s\n",
-			m->muxnames[0] ? m->muxnames[0] : none,
-			m->muxnames[1] ? m->muxnames[1] : none,
-			m->muxnames[2] ? m->muxnames[2] : none,
-			m->muxnames[3] ? m->muxnames[3] : none,
-			m->muxnames[4] ? m->muxnames[4] : none,
-			m->muxnames[5] ? m->muxnames[5] : none,
-			m->muxnames[6] ? m->muxnames[6] : none,
-			m->muxnames[7] ? m->muxnames[7] : none);
-
-	return 0;
-}
-
-#define OMAP_MUX_MAX_ARG_CHAR  7
-
-static ssize_t omap_mux_dbg_signal_write(struct file *file,
-					 const char __user *user_buf,
-					 size_t count, loff_t *ppos)
-{
-	struct seq_file *seqf;
-	struct omap_mux *m;
-	u16 val;
-	int ret;
-	struct omap_mux_partition *partition;
-
-	if (count > OMAP_MUX_MAX_ARG_CHAR)
-		return -EINVAL;
-
-	ret = kstrtou16_from_user(user_buf, count, 0x10, &val);
-	if (ret < 0)
-		return ret;
-
-	seqf = file->private_data;
-	m = seqf->private;
-
-	partition = omap_mux_get_partition(m);
-	if (!partition)
-		return -ENODEV;
-
-	omap_mux_write(partition, val, m->reg_offset);
-	*ppos += count;
-
-	return count;
-}
-
-static int omap_mux_dbg_signal_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, omap_mux_dbg_signal_show, inode->i_private);
-}
-
-static const struct file_operations omap_mux_dbg_signal_fops = {
-	.open		= omap_mux_dbg_signal_open,
-	.read		= seq_read,
-	.write		= omap_mux_dbg_signal_write,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static struct dentry *mux_dbg_dir;
-
-static void __init omap_mux_dbg_create_entry(
-				struct omap_mux_partition *partition,
-				struct dentry *mux_dbg_dir)
-{
-	struct omap_mux_entry *e;
-
-	list_for_each_entry(e, &partition->muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-
-		(void)debugfs_create_file(m->muxnames[0], S_IWUSR | S_IRUGO,
-					  mux_dbg_dir, m,
-					  &omap_mux_dbg_signal_fops);
-	}
-}
-
-static void __init omap_mux_dbg_init(void)
-{
-	struct omap_mux_partition *partition;
-	static struct dentry *mux_dbg_board_dir;
-
-	mux_dbg_dir = debugfs_create_dir("omap_mux", NULL);
-	if (!mux_dbg_dir)
-		return;
-
-	mux_dbg_board_dir = debugfs_create_dir("board", mux_dbg_dir);
-	if (!mux_dbg_board_dir)
-		return;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		omap_mux_dbg_create_entry(partition, mux_dbg_dir);
-		(void)debugfs_create_file(partition->name, S_IRUGO,
-					  mux_dbg_board_dir, partition,
-					  &omap_mux_dbg_board_fops);
-	}
-}
-
-#else
-static inline void omap_mux_dbg_init(void)
-{
-}
-#endif	/* CONFIG_DEBUG_FS */
-
-static void __init omap_mux_free_names(struct omap_mux *m)
-{
-	int i;
-
-	for (i = 0; i < OMAP_MUX_NR_MODES; i++)
-		kfree(m->muxnames[i]);
-
-#ifdef CONFIG_DEBUG_FS
-	for (i = 0; i < OMAP_MUX_NR_SIDES; i++)
-		kfree(m->balls[i]);
-#endif
-
-}
-
-/* Free all data except for GPIO pins unless CONFIG_DEBUG_FS is set */
-int __init omap_mux_late_init(void)
-{
-	struct omap_mux_partition *partition;
-	int ret;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		struct omap_mux_entry *e, *tmp;
-		list_for_each_entry_safe(e, tmp, &partition->muxmodes, node) {
-			struct omap_mux *m = &e->mux;
-			u16 mode = omap_mux_read(partition, m->reg_offset);
-
-			if (OMAP_MODE_GPIO(partition, mode))
-				continue;
-
-#ifndef CONFIG_DEBUG_FS
-			mutex_lock(&muxmode_mutex);
-			list_del(&e->node);
-			mutex_unlock(&muxmode_mutex);
-			omap_mux_free_names(m);
-			kfree(m);
-#endif
-		}
-	}
-
-	omap_mux_dbg_init();
-
-	/* see pinctrl-single-omap for the wake-up interrupt handling */
-	if (of_have_populated_dt())
-		return 0;
-
-	ret = request_irq(omap_prcm_event_to_irq("io"),
-		omap_hwmod_mux_handle_irq, IRQF_SHARED | IRQF_NO_SUSPEND,
-			"hwmod_io", omap_mux_late_init);
-
-	if (ret)
-		pr_warn("mux: Failed to setup hwmod io irq %d\n", ret);
-
-	return 0;
-}
-
-static void __init omap_mux_package_fixup(struct omap_mux *p,
-					struct omap_mux *superset)
-{
-	while (p->reg_offset !=  OMAP_MUX_TERMINATOR) {
-		struct omap_mux *s = superset;
-		int found = 0;
-
-		while (s->reg_offset != OMAP_MUX_TERMINATOR) {
-			if (s->reg_offset == p->reg_offset) {
-				*s = *p;
-				found++;
-				break;
-			}
-			s++;
-		}
-		if (!found)
-			pr_err("%s: Unknown entry offset 0x%x\n", __func__,
-			       p->reg_offset);
-		p++;
-	}
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-static void __init omap_mux_package_init_balls(struct omap_ball *b,
-				struct omap_mux *superset)
-{
-	while (b->reg_offset != OMAP_MUX_TERMINATOR) {
-		struct omap_mux *s = superset;
-		int found = 0;
-
-		while (s->reg_offset != OMAP_MUX_TERMINATOR) {
-			if (s->reg_offset == b->reg_offset) {
-				s->balls[0] = b->balls[0];
-				s->balls[1] = b->balls[1];
-				found++;
-				break;
-			}
-			s++;
-		}
-		if (!found)
-			pr_err("%s: Unknown ball offset 0x%x\n", __func__,
-			       b->reg_offset);
-		b++;
-	}
-}
-
-#else	/* CONFIG_DEBUG_FS */
-
-static inline void omap_mux_package_init_balls(struct omap_ball *b,
-					struct omap_mux *superset)
-{
-}
-
-#endif	/* CONFIG_DEBUG_FS */
-
-static int __init omap_mux_setup(char *options)
-{
-	if (!options)
-		return 0;
-
-	omap_mux_options = options;
-
-	return 1;
-}
-__setup("omap_mux=", omap_mux_setup);
-
-/*
- * Note that the omap_mux=some.signal1=0x1234,some.signal2=0x1234
- * cmdline options only override the bootloader values.
- * During development, please enable CONFIG_DEBUG_FS, and use the
- * signal specific entries under debugfs.
- */
-static void __init omap_mux_set_cmdline_signals(void)
-{
-	char *options, *next_opt, *token;
-
-	if (!omap_mux_options)
-		return;
-
-	options = kstrdup(omap_mux_options, GFP_KERNEL);
-	if (!options)
-		return;
-
-	next_opt = options;
-
-	while ((token = strsep(&next_opt, ",")) != NULL) {
-		char *keyval, *name;
-		u16 val;
-
-		keyval = token;
-		name = strsep(&keyval, "=");
-		if (name) {
-			int res;
-
-			res = kstrtou16(keyval, 0x10, &val);
-			if (res < 0)
-				continue;
-
-			omap_mux_init_signal(name, (u16)val);
-		}
-	}
-
-	kfree(options);
-}
-
-static int __init omap_mux_copy_names(struct omap_mux *src,
-				      struct omap_mux *dst)
-{
-	int i;
-
-	for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
-		if (src->muxnames[i]) {
-			dst->muxnames[i] = kstrdup(src->muxnames[i],
-						   GFP_KERNEL);
-			if (!dst->muxnames[i])
-				goto free;
-		}
-	}
-
-#ifdef CONFIG_DEBUG_FS
-	for (i = 0; i < OMAP_MUX_NR_SIDES; i++) {
-		if (src->balls[i]) {
-			dst->balls[i] = kstrdup(src->balls[i], GFP_KERNEL);
-			if (!dst->balls[i])
-				goto free;
-		}
-	}
-#endif
-
-	return 0;
-
-free:
-	omap_mux_free_names(dst);
-	return -ENOMEM;
-
-}
-
-#endif	/* CONFIG_OMAP_MUX */
-
-static struct omap_mux *omap_mux_get_by_gpio(
-				struct omap_mux_partition *partition,
-				int gpio)
-{
-	struct omap_mux_entry *e;
-	struct omap_mux *ret = NULL;
-
-	list_for_each_entry(e, &partition->muxmodes, node) {
-		struct omap_mux *m = &e->mux;
-		if (m->gpio == gpio) {
-			ret = m;
-			break;
-		}
-	}
-
-	return ret;
-}
-
-/* Needed for dynamic muxing of GPIO pins for off-idle */
-u16 omap_mux_get_gpio(int gpio)
-{
-	struct omap_mux_partition *partition;
-	struct omap_mux *m = NULL;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		m = omap_mux_get_by_gpio(partition, gpio);
-		if (m)
-			return omap_mux_read(partition, m->reg_offset);
-	}
-
-	if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
-		pr_err("%s: Could not get gpio%i\n", __func__, gpio);
-
-	return OMAP_MUX_TERMINATOR;
-}
-
-/* Needed for dynamic muxing of GPIO pins for off-idle */
-void omap_mux_set_gpio(u16 val, int gpio)
-{
-	struct omap_mux_partition *partition;
-	struct omap_mux *m = NULL;
-
-	list_for_each_entry(partition, &mux_partitions, node) {
-		m = omap_mux_get_by_gpio(partition, gpio);
-		if (m) {
-			omap_mux_write(partition, val, m->reg_offset);
-			return;
-		}
-	}
-
-	if (!m || m->reg_offset == OMAP_MUX_TERMINATOR)
-		pr_err("%s: Could not set gpio%i\n", __func__, gpio);
-}
-
-static struct omap_mux * __init omap_mux_list_add(
-					struct omap_mux_partition *partition,
-					struct omap_mux *src)
-{
-	struct omap_mux_entry *entry;
-	struct omap_mux *m;
-
-	entry = kzalloc(sizeof(struct omap_mux_entry), GFP_KERNEL);
-	if (!entry)
-		return NULL;
-
-	m = &entry->mux;
-	entry->mux = *src;
-
-#ifdef CONFIG_OMAP_MUX
-	if (omap_mux_copy_names(src, m)) {
-		kfree(entry);
-		return NULL;
-	}
-#endif
-
-	mutex_lock(&muxmode_mutex);
-	list_add_tail(&entry->node, &partition->muxmodes);
-	mutex_unlock(&muxmode_mutex);
-
-	return m;
-}
-
-/*
- * Note if CONFIG_OMAP_MUX is not selected, we will only initialize
- * the GPIO to mux offset mapping that is needed for dynamic muxing
- * of GPIO pins for off-idle.
- */
-static void __init omap_mux_init_list(struct omap_mux_partition *partition,
-				      struct omap_mux *superset)
-{
-	while (superset->reg_offset !=  OMAP_MUX_TERMINATOR) {
-		struct omap_mux *entry;
-
-#ifdef CONFIG_OMAP_MUX
-		if (!superset->muxnames[0]) {
-			superset++;
-			continue;
-		}
-#else
-		/* Skip pins that are not muxed as GPIO by bootloader */
-		if (!OMAP_MODE_GPIO(partition, omap_mux_read(partition,
-				    superset->reg_offset))) {
-			superset++;
-			continue;
-		}
-#endif
-
-		entry = omap_mux_list_add(partition, superset);
-		if (!entry) {
-			pr_err("%s: Could not add entry\n", __func__);
-			return;
-		}
-		superset++;
-	}
-}
-
-#ifdef CONFIG_OMAP_MUX
-
-static void omap_mux_init_package(struct omap_mux *superset,
-				  struct omap_mux *package_subset,
-				  struct omap_ball *package_balls)
-{
-	if (package_subset)
-		omap_mux_package_fixup(package_subset, superset);
-	if (package_balls)
-		omap_mux_package_init_balls(package_balls, superset);
-}
-
-static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
-					 struct omap_board_mux *board_mux)
-{
-	omap_mux_set_cmdline_signals();
-	omap_mux_write_array(partition, board_mux);
-}
-
-#else
-
-static void omap_mux_init_package(struct omap_mux *superset,
-				  struct omap_mux *package_subset,
-				  struct omap_ball *package_balls)
-{
-}
-
-static void __init omap_mux_init_signals(struct omap_mux_partition *partition,
-					 struct omap_board_mux *board_mux)
-{
-}
-
-#endif
-
-static u32 mux_partitions_cnt;
-
-int __init omap_mux_init(const char *name, u32 flags,
-			 u32 mux_pbase, u32 mux_size,
-			 struct omap_mux *superset,
-			 struct omap_mux *package_subset,
-			 struct omap_board_mux *board_mux,
-			 struct omap_ball *package_balls)
-{
-	struct omap_mux_partition *partition;
-
-	partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);
-	if (!partition)
-		return -ENOMEM;
-
-	partition->name = name;
-	partition->flags = flags;
-	partition->gpio = flags & OMAP_MUX_MODE7;
-	partition->size = mux_size;
-	partition->phys = mux_pbase;
-	partition->base = ioremap(mux_pbase, mux_size);
-	if (!partition->base) {
-		pr_err("%s: Could not ioremap mux partition at 0x%08x\n",
-			__func__, partition->phys);
-		kfree(partition);
-		return -ENODEV;
-	}
-
-	INIT_LIST_HEAD(&partition->muxmodes);
-
-	list_add_tail(&partition->node, &mux_partitions);
-	mux_partitions_cnt++;
-	pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,
-		mux_partitions_cnt, partition->name, partition->flags);
-
-	omap_mux_init_package(superset, package_subset, package_balls);
-	omap_mux_init_list(partition, superset);
-	omap_mux_init_signals(partition, board_mux);
-
-	return 0;
-}
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/mux.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/mux.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/mux.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia
- * Copyright (C) 2009-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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "mux34xx.h"
-
-#define OMAP_MUX_TERMINATOR	0xffff
-
-/* 34xx mux mode options for each pin. See TRM for options */
-#define OMAP_MUX_MODE0      0
-#define OMAP_MUX_MODE1      1
-#define OMAP_MUX_MODE2      2
-#define OMAP_MUX_MODE3      3
-#define OMAP_MUX_MODE4      4
-#define OMAP_MUX_MODE5      5
-#define OMAP_MUX_MODE6      6
-#define OMAP_MUX_MODE7      7
-
-/* 24xx/34xx mux bit defines */
-#define OMAP_PULL_ENA			(1 << 3)
-#define OMAP_PULL_UP			(1 << 4)
-#define OMAP_ALTELECTRICALSEL		(1 << 5)
-
-/* omap3/4/5 specific mux bit defines */
-#define OMAP_INPUT_EN			(1 << 8)
-#define OMAP_OFF_EN			(1 << 9)
-#define OMAP_OFFOUT_EN			(1 << 10)
-#define OMAP_OFFOUT_VAL			(1 << 11)
-#define OMAP_OFF_PULL_EN		(1 << 12)
-#define OMAP_OFF_PULL_UP		(1 << 13)
-#define OMAP_WAKEUP_EN			(1 << 14)
-#define OMAP_WAKEUP_EVENT		(1 << 15)
-
-/* Active pin states */
-#define OMAP_PIN_OUTPUT			0
-#define OMAP_PIN_INPUT			OMAP_INPUT_EN
-#define OMAP_PIN_INPUT_PULLUP		(OMAP_PULL_ENA | OMAP_INPUT_EN \
-						| OMAP_PULL_UP)
-#define OMAP_PIN_INPUT_PULLDOWN		(OMAP_PULL_ENA | OMAP_INPUT_EN)
-
-/* Off mode states */
-#define OMAP_PIN_OFF_NONE		0
-#define OMAP_PIN_OFF_OUTPUT_HIGH	(OMAP_OFF_EN | OMAP_OFFOUT_EN \
-						| OMAP_OFFOUT_VAL)
-#define OMAP_PIN_OFF_OUTPUT_LOW		(OMAP_OFF_EN | OMAP_OFFOUT_EN)
-#define OMAP_PIN_OFF_INPUT_PULLUP	(OMAP_OFF_EN | OMAP_OFF_PULL_EN \
-						| OMAP_OFF_PULL_UP)
-#define OMAP_PIN_OFF_INPUT_PULLDOWN	(OMAP_OFF_EN | OMAP_OFF_PULL_EN)
-#define OMAP_PIN_OFF_WAKEUPENABLE	OMAP_WAKEUP_EN
-
-#define OMAP_MODE_GPIO(partition, x)	(((x) & OMAP_MUX_MODE7) == \
-					  partition->gpio)
-#define OMAP_MODE_UART(x)	(((x) & OMAP_MUX_MODE7) == OMAP_MUX_MODE0)
-
-/* Flags for omapX_mux_init */
-#define OMAP_PACKAGE_MASK		0xffff
-#define OMAP_PACKAGE_CBP		6		/* 515-pin 0.40 0.50 */
-#define OMAP_PACKAGE_CUS		5		/* 423-pin 0.65 */
-#define OMAP_PACKAGE_CBB		4		/* 515-pin 0.40 0.50 */
-#define OMAP_PACKAGE_CBC		3		/* 515-pin 0.50 0.65 */
-
-#define OMAP_MUX_NR_MODES		8		/* Available modes */
-#define OMAP_MUX_NR_SIDES		2		/* Bottom & top */
-
-/*
- * omap_mux_init flags definition:
- *
- * OMAP_GPIO_MUX_MODE, bits 0-2: gpio muxing mode, same like pad control
- *      register which includes values from 0-7.
- * OMAP_MUX_REG_8BIT: Ensure that access to padconf is done in 8 bits.
- * The default value is 16 bits.
- */
-#define OMAP_MUX_GPIO_IN_MODE0		OMAP_MUX_MODE0
-#define OMAP_MUX_GPIO_IN_MODE1		OMAP_MUX_MODE1
-#define OMAP_MUX_GPIO_IN_MODE2		OMAP_MUX_MODE2
-#define OMAP_MUX_GPIO_IN_MODE3		OMAP_MUX_MODE3
-#define OMAP_MUX_GPIO_IN_MODE4		OMAP_MUX_MODE4
-#define OMAP_MUX_GPIO_IN_MODE5		OMAP_MUX_MODE5
-#define OMAP_MUX_GPIO_IN_MODE6		OMAP_MUX_MODE6
-#define OMAP_MUX_GPIO_IN_MODE7		OMAP_MUX_MODE7
-#define OMAP_MUX_REG_8BIT		(1 << 3)
-
-/**
- * struct omap_board_data - board specific device data
- * @id: instance id
- * @flags: additional flags for platform init code
- * @pads: array of device specific pads
- * @pads_cnt: ARRAY_SIZE() of pads
- */
-struct omap_board_data {
-	int			id;
-	u32			flags;
-	struct omap_device_pad	*pads;
-	int			pads_cnt;
-};
-
-/**
- * struct mux_partition - contain partition related information
- * @name: name of the current partition
- * @flags: flags specific to this partition
- * @gpio: gpio mux mode
- * @phys: physical address
- * @size: partition size
- * @base: virtual address after ioremap
- * @muxmodes: list of nodes that belong to a partition
- * @node: list node for the partitions linked list
- */
-struct omap_mux_partition {
-	const char		*name;
-	u32			flags;
-	u32			gpio;
-	u32			phys;
-	u32			size;
-	void __iomem		*base;
-	struct list_head	muxmodes;
-	struct list_head	node;
-};
-
-/**
- * struct omap_mux - data for omap mux register offset and it's value
- * @reg_offset:	mux register offset from the mux base
- * @gpio:	GPIO number
- * @muxnames:	available signal modes for a ball
- * @balls:	available balls on the package
- */
-struct omap_mux {
-	u16	reg_offset;
-	u16	gpio;
-#ifdef CONFIG_OMAP_MUX
-	char	*muxnames[OMAP_MUX_NR_MODES];
-#ifdef CONFIG_DEBUG_FS
-	char	*balls[OMAP_MUX_NR_SIDES];
-#endif
-#endif
-};
-
-/**
- * struct omap_ball - data for balls on omap package
- * @reg_offset:	mux register offset from the mux base
- * @balls:	available balls on the package
- */
-struct omap_ball {
-	u16	reg_offset;
-	char	*balls[OMAP_MUX_NR_SIDES];
-};
-
-/**
- * struct omap_board_mux - data for initializing mux registers
- * @reg_offset:	mux register offset from the mux base
- * @mux_value:	desired mux value to set
- */
-struct omap_board_mux {
-	u16	reg_offset;
-	u16	value;
-};
-
-#define OMAP_DEVICE_PAD_REMUX		BIT(1)	/* Dynamically remux a pad,
-						   needs enable, idle and off
-						   values */
-#define OMAP_DEVICE_PAD_WAKEUP		BIT(0)	/* Pad is wake-up capable */
-
-/**
- * struct omap_device_pad - device specific pad configuration
- * @name:		signal name
- * @flags:		pad specific runtime flags
- * @enable:		runtime value for a pad
- * @idle:		idle value for a pad
- * @off:		off value for a pad, defaults to safe mode
- * @partition:		mux partition
- * @mux:		mux register
- */
-struct omap_device_pad {
-	char				*name;
-	u8				flags;
-	u16				enable;
-	u16				idle;
-	u16				off;
-	struct omap_mux_partition	*partition;
-	struct omap_mux			*mux;
-};
-
-struct omap_hwmod_mux_info;
-
-#define OMAP_MUX_STATIC(signal, mode)					\
-{									\
-	.name	= (signal),						\
-	.enable	= (mode),						\
-}
-
-#if defined(CONFIG_OMAP_MUX)
-
-/**
- * omap_mux_init_gpio - initialize a signal based on the GPIO number
- * @gpio:		GPIO number
- * @val:		Options for the mux register value
- */
-int omap_mux_init_gpio(int gpio, int val);
-
-/**
- * omap_mux_init_signal - initialize a signal based on the signal name
- * @muxname:		Mux name in mode0_name.signal_name format
- * @val:		Options for the mux register value
- */
-int omap_mux_init_signal(const char *muxname, int val);
-
-/**
- * omap_hwmod_mux_init - initialize hwmod specific mux data
- * @bpads:		Board specific device signal names
- * @nr_pads:		Number of signal names for the device
- */
-extern struct omap_hwmod_mux_info *
-omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
-
-/**
- * omap_hwmod_mux - omap hwmod specific pin muxing
- * @hmux:		Pads for a hwmod
- * @state:		Desired _HWMOD_STATE
- *
- * Called only from omap_hwmod.c, do not use.
- */
-void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
-
-int omap_mux_get_by_name(const char *muxname,
-		struct omap_mux_partition **found_partition,
-		struct omap_mux **found_mux);
-#else
-
-static inline int omap_mux_get_by_name(const char *muxname,
-		struct omap_mux_partition **found_partition,
-		struct omap_mux **found_mux)
-{
-	return 0;
-}
-
-static inline int omap_mux_init_gpio(int gpio, int val)
-{
-	return 0;
-}
-static inline int omap_mux_init_signal(char *muxname, int val)
-{
-	return 0;
-}
-
-static inline struct omap_hwmod_mux_info *
-omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
-{
-	return NULL;
-}
-
-static inline void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
-{
-}
-
-static struct omap_board_mux *board_mux __maybe_unused;
-
-#endif
-
-/**
- * omap_mux_get_gpio() - get mux register value based on GPIO number
- * @gpio:		GPIO number
- *
- */
-u16 omap_mux_get_gpio(int gpio);
-
-/**
- * omap_mux_set_gpio() - set mux register value based on GPIO number
- * @val:		New mux register value
- * @gpio:		GPIO number
- *
- */
-void omap_mux_set_gpio(u16 val, int gpio);
-
-/**
- * omap_mux_get() - get a mux partition by name
- * @name:		Name of the mux partition
- *
- */
-struct omap_mux_partition *omap_mux_get(const char *name);
-
-/**
- * omap_mux_read() - read mux register
- * @partition:		Mux partition
- * @mux_offset:		Offset of the mux register
- *
- */
-u16 omap_mux_read(struct omap_mux_partition *p, u16 mux_offset);
-
-/**
- * omap_mux_write() - write mux register
- * @partition:		Mux partition
- * @val:		New mux register value
- * @mux_offset:		Offset of the mux register
- *
- * This should be only needed for dynamic remuxing of non-gpio signals.
- */
-void omap_mux_write(struct omap_mux_partition *p, u16 val, u16 mux_offset);
-
-/**
- * omap_mux_write_array() - write an array of mux registers
- * @partition:		Mux partition
- * @board_mux:		Array of mux registers terminated by MAP_MUX_TERMINATOR
- *
- * This should be only needed for dynamic remuxing of non-gpio signals.
- */
-void omap_mux_write_array(struct omap_mux_partition *p,
-			  struct omap_board_mux *board_mux);
-
-/**
- * omap2420_mux_init() - initialize mux system with board specific set
- * @board_mux:		Board specific mux table
- * @flags:		OMAP package type used for the board
- */
-int omap2420_mux_init(struct omap_board_mux *board_mux, int flags);
-
-/**
- * omap2430_mux_init() - initialize mux system with board specific set
- * @board_mux:		Board specific mux table
- * @flags:		OMAP package type used for the board
- */
-int omap2430_mux_init(struct omap_board_mux *board_mux, int flags);
-
-/**
- * omap3_mux_init() - initialize mux system with board specific set
- * @board_mux:		Board specific mux table
- * @flags:		OMAP package type used for the board
- */
-int omap3_mux_init(struct omap_board_mux *board_mux, int flags);
-
-/**
- * omap4_mux_init() - initialize mux system with board specific set
- * @board_subset:	Board specific mux table
- * @board_wkup_subset:	Board specific mux table for wakeup instance
- * @flags:		OMAP package type used for the board
- */
-int omap4_mux_init(struct omap_board_mux *board_subset,
-	struct omap_board_mux *board_wkup_subset, int flags);
-
-/**
- * omap_mux_init - private mux init function, do not call
- */
-int omap_mux_init(const char *name, u32 flags,
-		  u32 mux_pbase, u32 mux_size,
-		  struct omap_mux *superset,
-		  struct omap_mux *package_subset,
-		  struct omap_board_mux *board_mux,
-		  struct omap_ball *package_balls);
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap4-sar-layout.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap4-sar-layout.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap4-sar-layout.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap4-sar-layout.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,8 @@
 /* CPUx Wakeup Non-Secure Physical Address offsets in SAR_BANK3 */
 #define CPU0_WAKEUP_NS_PA_ADDR_OFFSET		0xa04
 #define CPU1_WAKEUP_NS_PA_ADDR_OFFSET		0xa08
+#define OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET	0xe00
+#define OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET	0xe04
 
 #define SAR_BACKUP_STATUS_OFFSET		(SAR_BANK3_OFFSET + 0x500)
 #define SAR_SECURE_RAM_SIZE_OFFSET		(SAR_BANK3_OFFSET + 0x504)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_interconnect_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,156 +17,11 @@
 
 #include "omap_hwmod_common_data.h"
 
-struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
-	{
-		.pa_start	= 0x4809c000,
-		.pa_end		= 0x4809c1ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
-	{
-		.pa_start	= 0x480b4000,
-		.pa_end		= 0x480b41ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_i2c1_addr_space[] = {
-	{
-		.pa_start	= 0x48070000,
-		.pa_end		= 0x48070000 + SZ_128 - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_i2c2_addr_space[] = {
-	{
-		.pa_start	= 0x48072000,
-		.pa_end		= 0x48072000 + SZ_128 - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_dss_addrs[] = {
-	{
-		.pa_start	= 0x48050000,
-		.pa_end		= 0x48050000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_dss_dispc_addrs[] = {
-	{
-		.pa_start	= 0x48050400,
-		.pa_end		= 0x48050400 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_dss_rfbi_addrs[] = {
-	{
-		.pa_start	= 0x48050800,
-		.pa_end		= 0x48050800 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_dss_venc_addrs[] = {
-	{
-		.pa_start	= 0x48050C00,
-		.pa_end		= 0x48050C00 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_timer10_addrs[] = {
-	{
-		.pa_start	= 0x48086000,
-		.pa_end		= 0x48086000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_timer11_addrs[] = {
-	{
-		.pa_start	= 0x48088000,
-		.pa_end		= 0x48088000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2xxx_timer12_addrs[] = {
-	{
-		.pa_start	= 0x4808a000,
-		.pa_end		= 0x4808a000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_mcspi1_addr_space[] = {
-	{
-		.pa_start	= 0x48098000,
-		.pa_end		= 0x48098000 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_mcspi2_addr_space[] = {
-	{
-		.pa_start	= 0x4809a000,
-		.pa_end		= 0x4809a000 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
-	{
-		.pa_start	= 0x480b8000,
-		.pa_end		= 0x480b8000 + SZ_256 - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
-
 struct omap_hwmod_addr_space omap2_dma_system_addrs[] = {
 	{
 		.pa_start	= 0x48056000,
 		.pa_end		= 0x48056000 + SZ_4K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_mcbsp1_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x48074000,
-		.pa_end		= 0x480740ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
-struct omap_hwmod_addr_space omap2_hdq1w_addr_space[] = {
-	{
-		.pa_start       = 0x480b2000,
-		.pa_end         = 0x480b2fff,
-		.flags          = ADDR_TYPE_RT,
+		.flags		= ADDR_TYPE_RT,
 	},
-	{ }
+	{ },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,204 +45,31 @@ struct omap_hwmod_class omap2_venc_hwmod
 	.name = "venc",
 };
 
-
-/* Common DMA request line data */
-struct omap_hwmod_dma_info omap2_uart1_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 50, },
-	{ .name = "tx", .dma_req = 49, },
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_uart2_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 52, },
-	{ .name = "tx", .dma_req = 51, },
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_uart3_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 54, },
-	{ .name = "tx", .dma_req = 53, },
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_i2c1_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 27 },
-	{ .name = "rx", .dma_req = 28 },
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_i2c2_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 29 },
-	{ .name = "rx", .dma_req = 30 },
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_mcspi1_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
-	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
-	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
-	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
-	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
-	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
-	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
-	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_mcspi2_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
-	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
-	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
-	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_mcbsp1_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 32 },
-	{ .name = "tx", .dma_req = 31 },
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_mcbsp2_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 34 },
-	{ .name = "tx", .dma_req = 33 },
-	{ .dma_req = -1 }
-};
-
-struct omap_hwmod_dma_info omap2_mcbsp3_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 18 },
-	{ .name = "tx", .dma_req = 17 },
-	{ .dma_req = -1 }
-};
-
-/* Other IP block data */
-
-
 /*
  * omap_hwmod class data
  */
 
 struct omap_hwmod_class l3_hwmod_class = {
-	.name = "l3"
+	.name = "l3",
 };
 
 struct omap_hwmod_class l4_hwmod_class = {
-	.name = "l4"
+	.name = "l4",
 };
 
 struct omap_hwmod_class mpu_hwmod_class = {
-	.name = "mpu"
+	.name = "mpu",
 };
 
 struct omap_hwmod_class iva_hwmod_class = {
-	.name = "iva"
+	.name = "iva",
 };
 
 /* Common MPU IRQ line data */
 
-struct omap_hwmod_irq_info omap2_timer1_mpu_irqs[] = {
-	{ .irq = 37 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer2_mpu_irqs[] = {
-	{ .irq = 38 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer3_mpu_irqs[] = {
-	{ .irq = 39 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer4_mpu_irqs[] = {
-	{ .irq = 40 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer5_mpu_irqs[] = {
-	{ .irq = 41 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer6_mpu_irqs[] = {
-	{ .irq = 42 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer7_mpu_irqs[] = {
-	{ .irq = 43 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer8_mpu_irqs[] = {
-	{ .irq = 44 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer9_mpu_irqs[] = {
-	{ .irq = 45 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer10_mpu_irqs[] = {
-	{ .irq = 46 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_timer11_mpu_irqs[] = {
-	{ .irq = 47 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_uart1_mpu_irqs[] = {
-	{ .irq = 72 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_uart2_mpu_irqs[] = {
-	{ .irq = 73 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_uart3_mpu_irqs[] = {
-	{ .irq = 74 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
 struct omap_hwmod_irq_info omap2_dispc_irqs[] = {
 	{ .irq = 25 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[] = {
-	{ .irq = 56 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[] = {
-	{ .irq = 57 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_gpio1_irqs[] = {
-	{ .irq = 29 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK1 */
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_gpio2_irqs[] = {
-	{ .irq = 30 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK2 */
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_gpio3_irqs[] = {
-	{ .irq = 31 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK3 */
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_gpio4_irqs[] = {
-	{ .irq = 32 + OMAP_INTC_START, }, /* INT_24XX_GPIO_BANK4 */
-	{ .irq = -1 },
+	{ .irq = -1, },
 };
 
 struct omap_hwmod_irq_info omap2_dma_system_irqs[] = {
@@ -250,17 +77,7 @@ struct omap_hwmod_irq_info omap2_dma_sys
 	{ .name = "1", .irq = 13 + OMAP_INTC_START, }, /* INT_24XX_SDMA_IRQ1 */
 	{ .name = "2", .irq = 14 + OMAP_INTC_START, }, /* INT_24XX_SDMA_IRQ2 */
 	{ .name = "3", .irq = 15 + OMAP_INTC_START, }, /* INT_24XX_SDMA_IRQ3 */
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[] = {
-	{ .irq = 65 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
-struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[] = {
-	{ .irq = 66 + OMAP_INTC_START, },
-	{ .irq = -1 },
+	{ .irq = -1, },
 };
 
 struct omap_hwmod_class_sysconfig omap2_hdq1w_sysc = {
@@ -277,9 +94,3 @@ struct omap_hwmod_class omap2_hdq1w_clas
 	.sysc	= &omap2_hdq1w_sysc,
 	.reset	= &omap_hdq1w_reset,
 };
-
-struct omap_hwmod_irq_info omap2_hdq1w_mpu_irqs[] = {
-	{ .irq = 58 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_interconnect_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -191,7 +191,6 @@ struct omap_hwmod_ocp_if omap2xxx_l4_cor
 	.master		= &omap2xxx_l4_core_hwmod,
 	.slave		= &omap2xxx_dss_core_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
@@ -206,7 +205,6 @@ struct omap_hwmod_ocp_if omap2xxx_l4_cor
 	.master		= &omap2xxx_l4_core_hwmod,
 	.slave		= &omap2xxx_dss_dispc_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_dispc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION,
@@ -221,7 +219,6 @@ struct omap_hwmod_ocp_if omap2xxx_l4_cor
 	.master		= &omap2xxx_l4_core_hwmod,
 	.slave		= &omap2xxx_dss_rfbi_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_rfbi_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
@@ -236,7 +233,6 @@ struct omap_hwmod_ocp_if omap2xxx_l4_cor
 	.master		= &omap2xxx_l4_core_hwmod,
 	.slave		= &omap2xxx_dss_venc_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_VENC_REGION,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -569,7 +569,6 @@ struct omap_hwmod omap2xxx_dss_core_hwmo
 struct omap_hwmod omap2xxx_dss_dispc_hwmod = {
 	.name		= "dss_dispc",
 	.class		= &omap2_dispc_hwmod_class,
-	.mpu_irqs	= omap2_dispc_irqs,
 	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_common_data.h	2017-02-12 16:03:20.000000000 -0500
@@ -68,6 +68,7 @@ extern struct omap_hwmod_ocp_if am33xx_l
 extern struct omap_hwmod_ocp_if am33xx_l3_main__ocmc;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__sha0;
 extern struct omap_hwmod_ocp_if am33xx_l3_main__aes0;
+extern struct omap_hwmod_ocp_if am33xx_l4_per__rng;
 
 extern struct omap_hwmod am33xx_l3_main_hwmod;
 extern struct omap_hwmod am33xx_l3_s_hwmod;
@@ -80,6 +81,7 @@ extern struct omap_hwmod am33xx_gfx_hwmo
 extern struct omap_hwmod am33xx_prcm_hwmod;
 extern struct omap_hwmod am33xx_aes0_hwmod;
 extern struct omap_hwmod am33xx_sha0_hwmod;
+extern struct omap_hwmod am33xx_rng_hwmod;
 extern struct omap_hwmod am33xx_ocmcram_hwmod;
 extern struct omap_hwmod am33xx_smartreflex0_hwmod;
 extern struct omap_hwmod am33xx_smartreflex1_hwmod;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_interconnect_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -547,3 +547,11 @@ struct omap_hwmod_ocp_if am33xx_l3_main_
 	.addr		= am33xx_aes0_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
+
+/* l4 per -> rng */
+struct omap_hwmod_ocp_if am33xx_l4_per__rng = {
+	.master		= &am33xx_l4_ls_hwmod,
+	.slave		= &am33xx_rng_hwmod,
+	.clk		= "rng_fck",
+	.user		= OCP_USER_MPU,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -268,6 +268,33 @@ struct omap_hwmod am33xx_sha0_hwmod = {
 	},
 };
 
+/* rng */
+static struct omap_hwmod_class_sysconfig am33xx_rng_sysc = {
+	.rev_offs	= 0x1fe0,
+	.sysc_offs	= 0x1fe4,
+	.sysc_flags	= SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE,
+	.idlemodes	= SIDLE_FORCE | SIDLE_NO,
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class am33xx_rng_hwmod_class = {
+	.name		= "rng",
+	.sysc		= &am33xx_rng_sysc,
+};
+
+struct omap_hwmod am33xx_rng_hwmod = {
+	.name		= "rng",
+	.class		= &am33xx_rng_hwmod_class,
+	.clkdm_name	= "l4ls_clkdm",
+	.flags		= HWMOD_SWSUP_SIDLE,
+	.main_clk	= "rng_fck",
+	.prcm		= {
+		.omap4	= {
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
 /* ocmcram */
 static struct omap_hwmod_class am33xx_ocmcram_hwmod_class = {
 	.name = "ocmcram",
@@ -1315,6 +1342,7 @@ static void omap_hwmod_am33xx_clkctrl(vo
 	CLKCTRL(am33xx_ocmcram_hwmod , AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET);
 	CLKCTRL(am33xx_sha0_hwmod , AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET);
 	CLKCTRL(am33xx_aes0_hwmod , AM33XX_CM_PER_AES0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_rng_hwmod, AM33XX_CM_PER_RNG_CLKCTRL_OFFSET);
 }
 
 static void omap_hwmod_am33xx_rst(void)
@@ -1388,6 +1416,7 @@ static void omap_hwmod_am43xx_clkctrl(vo
 	CLKCTRL(am33xx_ocmcram_hwmod , AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET);
 	CLKCTRL(am33xx_sha0_hwmod , AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET);
 	CLKCTRL(am33xx_aes0_hwmod , AM43XX_CM_PER_AES0_CLKCTRL_OFFSET);
+	CLKCTRL(am33xx_rng_hwmod, AM43XX_CM_PER_RNG_CLKCTRL_OFFSET);
 }
 
 static void omap_hwmod_am43xx_rst(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_33xx_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -503,41 +503,6 @@ static struct omap_hwmod_ocp_if am33xx_l
 	.flags		= OCPIF_SWSUP_IDLE,
 };
 
-/* rng */
-static struct omap_hwmod_class_sysconfig am33xx_rng_sysc = {
-	.rev_offs	= 0x1fe0,
-	.sysc_offs	= 0x1fe4,
-	.sysc_flags	= SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE,
-	.idlemodes	= SIDLE_FORCE | SIDLE_NO,
-	.sysc_fields	= &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class am33xx_rng_hwmod_class = {
-	.name		= "rng",
-	.sysc		= &am33xx_rng_sysc,
-};
-
-static struct omap_hwmod am33xx_rng_hwmod = {
-	.name		= "rng",
-	.class		= &am33xx_rng_hwmod_class,
-	.clkdm_name	= "l4ls_clkdm",
-	.flags		= HWMOD_SWSUP_SIDLE,
-	.main_clk	= "rng_fck",
-	.prcm		= {
-		.omap4	= {
-			.clkctrl_offs	= AM33XX_CM_PER_RNG_CLKCTRL_OFFSET,
-			.modulemode	= MODULEMODE_SWCTRL,
-		},
-	},
-};
-
-static struct omap_hwmod_ocp_if am33xx_l4_per__rng = {
-	.master		= &am33xx_l4_ls_hwmod,
-	.slave		= &am33xx_rng_hwmod,
-	.clk		= "rng_fck",
-	.user		= OCP_USER_MPU,
-};
-
 static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l3_main__emif,
 	&am33xx_mpu__l3_main,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,16 +53,10 @@
  */
 
 /* L3 */
-static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
-	{ .irq = 9 + OMAP_INTC_START, },
-	{ .irq = 10 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 	.name		= "l3_main",
 	.class		= &l3_hwmod_class,
-	.mpu_irqs	= omap3xxx_l3_main_irqs,
 	.flags		= HWMOD_NO_IDLEST,
 };
 
@@ -95,14 +89,9 @@ static struct omap_hwmod omap3xxx_l4_sec
 };
 
 /* MPU */
-static struct omap_hwmod_irq_info omap3xxx_mpu_irqs[] = {
-	{ .name = "pmu", .irq = 3 + OMAP_INTC_START },
-	{ .irq = -1 }
-};
 
 static struct omap_hwmod omap3xxx_mpu_hwmod = {
 	.name		= "mpu",
-	.mpu_irqs	= omap3xxx_mpu_irqs,
 	.class		= &mpu_hwmod_class,
 	.main_clk	= "arm_fck",
 };
@@ -128,7 +117,7 @@ static struct omap_hwmod omap3xxx_iva_hw
 			.module_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
 			.idlest_reg_id = 1,
 			.idlest_idle_bit = OMAP3430_ST_IVA2_SHIFT,
-		}
+		},
 	},
 };
 
@@ -197,7 +186,6 @@ static struct omap_timer_capability_dev_
 /* timer1 */
 static struct omap_hwmod omap3xxx_timer1_hwmod = {
 	.name		= "timer1",
-	.mpu_irqs	= omap2_timer1_mpu_irqs,
 	.main_clk	= "gpt1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -216,7 +204,6 @@ static struct omap_hwmod omap3xxx_timer1
 /* timer2 */
 static struct omap_hwmod omap3xxx_timer2_hwmod = {
 	.name		= "timer2",
-	.mpu_irqs	= omap2_timer2_mpu_irqs,
 	.main_clk	= "gpt2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -234,7 +221,6 @@ static struct omap_hwmod omap3xxx_timer2
 /* timer3 */
 static struct omap_hwmod omap3xxx_timer3_hwmod = {
 	.name		= "timer3",
-	.mpu_irqs	= omap2_timer3_mpu_irqs,
 	.main_clk	= "gpt3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -252,7 +238,6 @@ static struct omap_hwmod omap3xxx_timer3
 /* timer4 */
 static struct omap_hwmod omap3xxx_timer4_hwmod = {
 	.name		= "timer4",
-	.mpu_irqs	= omap2_timer4_mpu_irqs,
 	.main_clk	= "gpt4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -270,7 +255,6 @@ static struct omap_hwmod omap3xxx_timer4
 /* timer5 */
 static struct omap_hwmod omap3xxx_timer5_hwmod = {
 	.name		= "timer5",
-	.mpu_irqs	= omap2_timer5_mpu_irqs,
 	.main_clk	= "gpt5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -289,7 +273,6 @@ static struct omap_hwmod omap3xxx_timer5
 /* timer6 */
 static struct omap_hwmod omap3xxx_timer6_hwmod = {
 	.name		= "timer6",
-	.mpu_irqs	= omap2_timer6_mpu_irqs,
 	.main_clk	= "gpt6_fck",
 	.prcm		= {
 		.omap2 = {
@@ -308,7 +291,6 @@ static struct omap_hwmod omap3xxx_timer6
 /* timer7 */
 static struct omap_hwmod omap3xxx_timer7_hwmod = {
 	.name		= "timer7",
-	.mpu_irqs	= omap2_timer7_mpu_irqs,
 	.main_clk	= "gpt7_fck",
 	.prcm		= {
 		.omap2 = {
@@ -327,7 +309,6 @@ static struct omap_hwmod omap3xxx_timer7
 /* timer8 */
 static struct omap_hwmod omap3xxx_timer8_hwmod = {
 	.name		= "timer8",
-	.mpu_irqs	= omap2_timer8_mpu_irqs,
 	.main_clk	= "gpt8_fck",
 	.prcm		= {
 		.omap2 = {
@@ -346,7 +327,6 @@ static struct omap_hwmod omap3xxx_timer8
 /* timer9 */
 static struct omap_hwmod omap3xxx_timer9_hwmod = {
 	.name		= "timer9",
-	.mpu_irqs	= omap2_timer9_mpu_irqs,
 	.main_clk	= "gpt9_fck",
 	.prcm		= {
 		.omap2 = {
@@ -365,7 +345,6 @@ static struct omap_hwmod omap3xxx_timer9
 /* timer10 */
 static struct omap_hwmod omap3xxx_timer10_hwmod = {
 	.name		= "timer10",
-	.mpu_irqs	= omap2_timer10_mpu_irqs,
 	.main_clk	= "gpt10_fck",
 	.prcm		= {
 		.omap2 = {
@@ -384,7 +363,6 @@ static struct omap_hwmod omap3xxx_timer1
 /* timer11 */
 static struct omap_hwmod omap3xxx_timer11_hwmod = {
 	.name		= "timer11",
-	.mpu_irqs	= omap2_timer11_mpu_irqs,
 	.main_clk	= "gpt11_fck",
 	.prcm		= {
 		.omap2 = {
@@ -401,14 +379,9 @@ static struct omap_hwmod omap3xxx_timer1
 };
 
 /* timer12 */
-static struct omap_hwmod_irq_info omap3xxx_timer12_mpu_irqs[] = {
-	{ .irq = 95 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_timer12_hwmod = {
 	.name		= "timer12",
-	.mpu_irqs	= omap3xxx_timer12_mpu_irqs,
 	.main_clk	= "gpt12_fck",
 	.prcm		= {
 		.omap2 = {
@@ -485,8 +458,6 @@ static struct omap_hwmod omap3xxx_wd_tim
 /* UART1 */
 static struct omap_hwmod omap3xxx_uart1_hwmod = {
 	.name		= "uart1",
-	.mpu_irqs	= omap2_uart1_mpu_irqs,
-	.sdma_reqs	= omap2_uart1_sdma_reqs,
 	.main_clk	= "uart1_fck",
 	.flags		= DEBUG_TI81XXUART1_FLAGS | HWMOD_SWSUP_SIDLE,
 	.prcm		= {
@@ -504,8 +475,6 @@ static struct omap_hwmod omap3xxx_uart1_
 /* UART2 */
 static struct omap_hwmod omap3xxx_uart2_hwmod = {
 	.name		= "uart2",
-	.mpu_irqs	= omap2_uart2_mpu_irqs,
-	.sdma_reqs	= omap2_uart2_sdma_reqs,
 	.main_clk	= "uart2_fck",
 	.flags		= DEBUG_TI81XXUART2_FLAGS | HWMOD_SWSUP_SIDLE,
 	.prcm		= {
@@ -523,8 +492,6 @@ static struct omap_hwmod omap3xxx_uart2_
 /* UART3 */
 static struct omap_hwmod omap3xxx_uart3_hwmod = {
 	.name		= "uart3",
-	.mpu_irqs	= omap2_uart3_mpu_irqs,
-	.sdma_reqs	= omap2_uart3_sdma_reqs,
 	.main_clk	= "uart3_fck",
 	.flags		= DEBUG_OMAP3UART3_FLAGS | DEBUG_TI81XXUART3_FLAGS |
 				HWMOD_SWSUP_SIDLE,
@@ -541,21 +508,10 @@ static struct omap_hwmod omap3xxx_uart3_
 };
 
 /* UART4 */
-static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
-	{ .irq = 80 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = 82, },
-	{ .name = "tx",	.dma_req = 81, },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod omap36xx_uart4_hwmod = {
 	.name		= "uart4",
-	.mpu_irqs	= uart4_mpu_irqs,
-	.sdma_reqs	= uart4_sdma_reqs,
 	.main_clk	= "uart4_fck",
 	.flags		= DEBUG_OMAP3UART4_FLAGS | HWMOD_SWSUP_SIDLE,
 	.prcm		= {
@@ -570,16 +526,7 @@ static struct omap_hwmod omap36xx_uart4_
 	.class		= &omap2_uart_class,
 };
 
-static struct omap_hwmod_irq_info am35xx_uart4_mpu_irqs[] = {
-	{ .irq = 84 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 55, },
-	{ .name = "tx", .dma_req = 54, },
-	{ .dma_req = -1 }
-};
 
 /*
  * XXX AM35xx UART4 cannot complete its softreset without uart1_fck or
@@ -597,8 +544,6 @@ static struct omap_hwmod_opt_clk am35xx_
 
 static struct omap_hwmod am35xx_uart4_hwmod = {
 	.name		= "uart4",
-	.mpu_irqs	= am35xx_uart4_mpu_irqs,
-	.sdma_reqs	= am35xx_uart4_sdma_reqs,
 	.main_clk	= "uart4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -625,7 +570,7 @@ static struct omap_hwmod_class i2c_class
 static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
 	{ .name = "dispc", .dma_req = 5 },
 	{ .name = "dsi1", .dma_req = 74 },
-	{ .dma_req = -1 }
+	{ .dma_req = -1, },
 };
 
 /* dss */
@@ -714,7 +659,7 @@ static struct omap_hwmod omap3xxx_dss_di
 		},
 	},
 	.flags		= HWMOD_NO_IDLEST,
-	.dev_attr	= &omap2_3_dss_dispc_dev_attr
+	.dev_attr	= &omap2_3_dss_dispc_dev_attr,
 };
 
 /*
@@ -738,11 +683,6 @@ static struct omap_hwmod_class omap3xxx_
 	.sysc	= &omap3xxx_dsi_sysc,
 };
 
-static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
-	{ .irq = 25 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
-
 /* dss_dsi1 */
 static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
 	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
@@ -751,7 +691,6 @@ static struct omap_hwmod_opt_clk dss_dsi
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
 	.name		= "dss_dsi1",
 	.class		= &omap3xxx_dsi_hwmod_class,
-	.mpu_irqs	= omap3xxx_dsi1_irqs,
 	.main_clk	= "dss1_alwon_fck",
 	.prcm		= {
 		.omap2 = {
@@ -815,8 +754,6 @@ static struct omap_i2c_dev_attr i2c1_dev
 static struct omap_hwmod omap3xxx_i2c1_hwmod = {
 	.name		= "i2c1",
 	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-	.mpu_irqs	= omap2_i2c1_mpu_irqs,
-	.sdma_reqs	= omap2_i2c1_sdma_reqs,
 	.main_clk	= "i2c1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -840,8 +777,6 @@ static struct omap_i2c_dev_attr i2c2_dev
 static struct omap_hwmod omap3xxx_i2c2_hwmod = {
 	.name		= "i2c2",
 	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-	.mpu_irqs	= omap2_i2c2_mpu_irqs,
-	.sdma_reqs	= omap2_i2c2_sdma_reqs,
 	.main_clk	= "i2c2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -862,22 +797,11 @@ static struct omap_i2c_dev_attr i2c3_dev
 	.flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
 };
 
-static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
-	{ .irq = 61 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 25 },
-	{ .name = "rx", .dma_req = 26 },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod omap3xxx_i2c3_hwmod = {
 	.name		= "i2c3",
 	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
-	.mpu_irqs	= i2c3_mpu_irqs,
-	.sdma_reqs	= i2c3_sdma_reqs,
 	.main_clk	= "i2c3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -928,7 +852,6 @@ static struct omap_hwmod_opt_clk gpio1_o
 static struct omap_hwmod omap3xxx_gpio1_hwmod = {
 	.name		= "gpio1",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap2_gpio1_irqs,
 	.main_clk	= "gpio1_ick",
 	.opt_clks	= gpio1_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
@@ -953,7 +876,6 @@ static struct omap_hwmod_opt_clk gpio2_o
 static struct omap_hwmod omap3xxx_gpio2_hwmod = {
 	.name		= "gpio2",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap2_gpio2_irqs,
 	.main_clk	= "gpio2_ick",
 	.opt_clks	= gpio2_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
@@ -978,7 +900,6 @@ static struct omap_hwmod_opt_clk gpio3_o
 static struct omap_hwmod omap3xxx_gpio3_hwmod = {
 	.name		= "gpio3",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap2_gpio3_irqs,
 	.main_clk	= "gpio3_ick",
 	.opt_clks	= gpio3_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
@@ -1003,7 +924,6 @@ static struct omap_hwmod_opt_clk gpio4_o
 static struct omap_hwmod omap3xxx_gpio4_hwmod = {
 	.name		= "gpio4",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap2_gpio4_irqs,
 	.main_clk	= "gpio4_ick",
 	.opt_clks	= gpio4_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
@@ -1021,10 +941,6 @@ static struct omap_hwmod omap3xxx_gpio4_
 };
 
 /* gpio5 */
-static struct omap_hwmod_irq_info omap3xxx_gpio5_irqs[] = {
-	{ .irq = 33 + OMAP_INTC_START, }, /* INT_34XX_GPIO_BANK5 */
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
 	{ .role = "dbclk", .clk = "gpio5_dbck", },
@@ -1033,7 +949,6 @@ static struct omap_hwmod_opt_clk gpio5_o
 static struct omap_hwmod omap3xxx_gpio5_hwmod = {
 	.name		= "gpio5",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap3xxx_gpio5_irqs,
 	.main_clk	= "gpio5_ick",
 	.opt_clks	= gpio5_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
@@ -1051,10 +966,6 @@ static struct omap_hwmod omap3xxx_gpio5_
 };
 
 /* gpio6 */
-static struct omap_hwmod_irq_info omap3xxx_gpio6_irqs[] = {
-	{ .irq = 34 + OMAP_INTC_START, }, /* INT_34XX_GPIO_BANK6 */
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
 	{ .role = "dbclk", .clk = "gpio6_dbck", },
@@ -1063,7 +974,6 @@ static struct omap_hwmod_opt_clk gpio6_o
 static struct omap_hwmod omap3xxx_gpio6_hwmod = {
 	.name		= "gpio6",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap3xxx_gpio6_irqs,
 	.main_clk	= "gpio6_ick",
 	.opt_clks	= gpio6_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
@@ -1156,18 +1066,10 @@ static struct omap_hwmod_opt_clk mcbsp23
 };
 
 /* mcbsp1 */
-static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
-	{ .name = "common", .irq = 16 + OMAP_INTC_START, },
-	{ .name = "tx", .irq = 59 + OMAP_INTC_START, },
-	{ .name = "rx", .irq = 60 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
 	.name		= "mcbsp1",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
-	.mpu_irqs	= omap3xxx_mcbsp1_irqs,
-	.sdma_reqs	= omap2_mcbsp1_sdma_reqs,
 	.main_clk	= "mcbsp1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1183,12 +1085,6 @@ static struct omap_hwmod omap3xxx_mcbsp1
 };
 
 /* mcbsp2 */
-static struct omap_hwmod_irq_info omap3xxx_mcbsp2_irqs[] = {
-	{ .name = "common", .irq = 17 + OMAP_INTC_START, },
-	{ .name = "tx", .irq = 62 + OMAP_INTC_START, },
-	{ .name = "rx", .irq = 63 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_mcbsp_dev_attr omap34xx_mcbsp2_dev_attr = {
 	.sidetone	= "mcbsp2_sidetone",
@@ -1197,8 +1093,6 @@ static struct omap_mcbsp_dev_attr omap34
 static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
 	.name		= "mcbsp2",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
-	.mpu_irqs	= omap3xxx_mcbsp2_irqs,
-	.sdma_reqs	= omap2_mcbsp2_sdma_reqs,
 	.main_clk	= "mcbsp2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1215,12 +1109,6 @@ static struct omap_hwmod omap3xxx_mcbsp2
 };
 
 /* mcbsp3 */
-static struct omap_hwmod_irq_info omap3xxx_mcbsp3_irqs[] = {
-	{ .name = "common", .irq = 22 + OMAP_INTC_START, },
-	{ .name = "tx", .irq = 89 + OMAP_INTC_START, },
-	{ .name = "rx", .irq = 90 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_mcbsp_dev_attr omap34xx_mcbsp3_dev_attr = {
 	.sidetone	= "mcbsp3_sidetone",
@@ -1229,8 +1117,6 @@ static struct omap_mcbsp_dev_attr omap34
 static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
 	.name		= "mcbsp3",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
-	.mpu_irqs	= omap3xxx_mcbsp3_irqs,
-	.sdma_reqs	= omap2_mcbsp3_sdma_reqs,
 	.main_clk	= "mcbsp3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1247,24 +1133,11 @@ static struct omap_hwmod omap3xxx_mcbsp3
 };
 
 /* mcbsp4 */
-static struct omap_hwmod_irq_info omap3xxx_mcbsp4_irqs[] = {
-	{ .name = "common", .irq = 23 + OMAP_INTC_START, },
-	{ .name = "tx", .irq = 54 + OMAP_INTC_START, },
-	{ .name = "rx", .irq = 55 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info omap3xxx_mcbsp4_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 20 },
-	{ .name = "tx", .dma_req = 19 },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
 	.name		= "mcbsp4",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
-	.mpu_irqs	= omap3xxx_mcbsp4_irqs,
-	.sdma_reqs	= omap3xxx_mcbsp4_sdma_chs,
 	.main_clk	= "mcbsp4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1280,24 +1153,11 @@ static struct omap_hwmod omap3xxx_mcbsp4
 };
 
 /* mcbsp5 */
-static struct omap_hwmod_irq_info omap3xxx_mcbsp5_irqs[] = {
-	{ .name = "common", .irq = 27 + OMAP_INTC_START, },
-	{ .name = "tx", .irq = 81 + OMAP_INTC_START, },
-	{ .name = "rx", .irq = 82 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info omap3xxx_mcbsp5_sdma_chs[] = {
-	{ .name = "rx", .dma_req = 22 },
-	{ .name = "tx", .dma_req = 21 },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
 	.name		= "mcbsp5",
 	.class		= &omap3xxx_mcbsp_hwmod_class,
-	.mpu_irqs	= omap3xxx_mcbsp5_irqs,
-	.sdma_reqs	= omap3xxx_mcbsp5_sdma_chs,
 	.main_clk	= "mcbsp5_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1325,29 +1185,19 @@ static struct omap_hwmod_class omap3xxx_
 };
 
 /* mcbsp2_sidetone */
-static struct omap_hwmod_irq_info omap3xxx_mcbsp2_sidetone_irqs[] = {
-	{ .name = "irq", .irq = 4 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
 	.name		= "mcbsp2_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
-	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
 	.main_clk	= "mcbsp2_ick",
 	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* mcbsp3_sidetone */
-static struct omap_hwmod_irq_info omap3xxx_mcbsp3_sidetone_irqs[] = {
-	{ .name = "irq", .irq = 5 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
 	.name		= "mcbsp3_sidetone",
 	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
-	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
 	.main_clk	= "mcbsp3_ick",
 	.flags		= HWMOD_NO_IDLEST,
 };
@@ -1394,10 +1244,6 @@ static struct omap_smartreflex_dev_attr
 	.sensor_voltdm_name   = "mpu_iva",
 };
 
-static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
-	{ .irq = 18 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap34xx_sr1_hwmod = {
 	.name		= "smartreflex_mpu_iva",
@@ -1413,7 +1259,6 @@ static struct omap_hwmod omap34xx_sr1_hw
 		},
 	},
 	.dev_attr	= &sr1_dev_attr,
-	.mpu_irqs	= omap3_smartreflex_mpu_irqs,
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -1431,7 +1276,6 @@ static struct omap_hwmod omap36xx_sr1_hw
 		},
 	},
 	.dev_attr	= &sr1_dev_attr,
-	.mpu_irqs	= omap3_smartreflex_mpu_irqs,
 };
 
 /* SR2 */
@@ -1439,10 +1283,6 @@ static struct omap_smartreflex_dev_attr
 	.sensor_voltdm_name	= "core",
 };
 
-static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
-	{ .irq = 19 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap34xx_sr2_hwmod = {
 	.name		= "smartreflex_core",
@@ -1458,7 +1298,6 @@ static struct omap_hwmod omap34xx_sr2_hw
 		},
 	},
 	.dev_attr	= &sr2_dev_attr,
-	.mpu_irqs	= omap3_smartreflex_core_irqs,
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 };
 
@@ -1476,7 +1315,6 @@ static struct omap_hwmod omap36xx_sr2_hw
 		},
 	},
 	.dev_attr	= &sr2_dev_attr,
-	.mpu_irqs	= omap3_smartreflex_core_irqs,
 };
 
 /*
@@ -1545,8 +1383,6 @@ static struct omap2_mcspi_dev_attr omap_
 
 static struct omap_hwmod omap34xx_mcspi1 = {
 	.name		= "mcspi1",
-	.mpu_irqs	= omap2_mcspi1_mpu_irqs,
-	.sdma_reqs	= omap2_mcspi1_sdma_reqs,
 	.main_clk	= "mcspi1_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1568,8 +1404,6 @@ static struct omap2_mcspi_dev_attr omap_
 
 static struct omap_hwmod omap34xx_mcspi2 = {
 	.name		= "mcspi2",
-	.mpu_irqs	= omap2_mcspi2_mpu_irqs,
-	.sdma_reqs	= omap2_mcspi2_sdma_reqs,
 	.main_clk	= "mcspi2_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1585,18 +1419,7 @@ static struct omap_hwmod omap34xx_mcspi2
 };
 
 /* mcspi3 */
-static struct omap_hwmod_irq_info omap34xx_mcspi3_mpu_irqs[] = {
-	{ .name = "irq", .irq = 91 + OMAP_INTC_START, }, /* 91 */
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 15 },
-	{ .name = "rx0", .dma_req = 16 },
-	{ .name = "tx1", .dma_req = 23 },
-	{ .name = "rx1", .dma_req = 24 },
-	{ .dma_req = -1 }
-};
 
 static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
 	.num_chipselect = 2,
@@ -1604,8 +1427,6 @@ static struct omap2_mcspi_dev_attr omap_
 
 static struct omap_hwmod omap34xx_mcspi3 = {
 	.name		= "mcspi3",
-	.mpu_irqs	= omap34xx_mcspi3_mpu_irqs,
-	.sdma_reqs	= omap34xx_mcspi3_sdma_reqs,
 	.main_clk	= "mcspi3_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1621,16 +1442,7 @@ static struct omap_hwmod omap34xx_mcspi3
 };
 
 /* mcspi4 */
-static struct omap_hwmod_irq_info omap34xx_mcspi4_mpu_irqs[] = {
-	{ .name = "irq", .irq = 48 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info omap34xx_mcspi4_sdma_reqs[] = {
-	{ .name = "tx0", .dma_req = 70 }, /* DMA_SPI4_TX0 */
-	{ .name = "rx0", .dma_req = 71 }, /* DMA_SPI4_RX0 */
-	{ .dma_req = -1 }
-};
 
 static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
 	.num_chipselect = 1,
@@ -1638,8 +1450,6 @@ static struct omap2_mcspi_dev_attr omap_
 
 static struct omap_hwmod omap34xx_mcspi4 = {
 	.name		= "mcspi4",
-	.mpu_irqs	= omap34xx_mcspi4_mpu_irqs,
-	.sdma_reqs	= omap34xx_mcspi4_sdma_reqs,
 	.main_clk	= "mcspi4_fck",
 	.prcm		= {
 		.omap2 = {
@@ -1673,16 +1483,9 @@ static struct omap_hwmod_class usbotg_cl
 };
 
 /* usb_otg_hs */
-static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
-
-	{ .name = "mc", .irq = 92 + OMAP_INTC_START, },
-	{ .name = "dma", .irq = 93 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 	.name		= "usb_otg_hs",
-	.mpu_irqs	= omap3xxx_usbhsotg_mpu_irqs,
 	.main_clk	= "hsotgusb_ick",
 	.prcm		= {
 		.omap2 = {
@@ -1691,7 +1494,7 @@ static struct omap_hwmod omap3xxx_usbhso
 			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
 			.idlest_idle_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT,
-			.idlest_stdby_bit = OMAP3430ES2_ST_HSOTGUSB_STDBY_SHIFT
+			.idlest_stdby_bit = OMAP3430ES2_ST_HSOTGUSB_STDBY_SHIFT,
 		},
 	},
 	.class		= &usbotg_class,
@@ -1711,10 +1514,6 @@ static struct omap_hwmod omap3xxx_usbhso
 };
 
 /* usb_otg_hs */
-static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
-	{ .name = "mc", .irq = 71 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod_class am35xx_usbotg_class = {
 	.name = "am35xx_usbotg",
@@ -1722,7 +1521,6 @@ static struct omap_hwmod_class am35xx_us
 
 static struct omap_hwmod am35xx_usbhsotg_hwmod = {
 	.name		= "am35x_otg_hs",
-	.mpu_irqs	= am35xx_usbhsotg_mpu_irqs,
 	.main_clk	= "hsotgusb_fck",
 	.class		= &am35xx_usbotg_class,
 	.flags		= HWMOD_NO_IDLEST,
@@ -1747,16 +1545,7 @@ static struct omap_hwmod_class omap34xx_
 
 /* MMC/SD/SDIO1 */
 
-static struct omap_hwmod_irq_info omap34xx_mmc1_mpu_irqs[] = {
-	{ .irq = 83 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info omap34xx_mmc1_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = 61, },
-	{ .name = "rx",	.dma_req = 62, },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = {
 	{ .role = "dbck", .clk = "omap_32k_fck", },
@@ -1774,8 +1563,6 @@ static struct omap_hsmmc_dev_attr mmc1_p
 
 static struct omap_hwmod omap3xxx_pre_es3_mmc1_hwmod = {
 	.name		= "mmc1",
-	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
-	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
 	.opt_clks	= omap34xx_mmc1_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc1_opt_clks),
 	.main_clk	= "mmchs1_fck",
@@ -1794,8 +1581,6 @@ static struct omap_hwmod omap3xxx_pre_es
 
 static struct omap_hwmod omap3xxx_es3plus_mmc1_hwmod = {
 	.name		= "mmc1",
-	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
-	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
 	.opt_clks	= omap34xx_mmc1_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc1_opt_clks),
 	.main_clk	= "mmchs1_fck",
@@ -1814,16 +1599,7 @@ static struct omap_hwmod omap3xxx_es3plu
 
 /* MMC/SD/SDIO2 */
 
-static struct omap_hwmod_irq_info omap34xx_mmc2_mpu_irqs[] = {
-	{ .irq = 86 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info omap34xx_mmc2_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = 47, },
-	{ .name = "rx",	.dma_req = 48, },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = {
 	{ .role = "dbck", .clk = "omap_32k_fck", },
@@ -1836,8 +1612,6 @@ static struct omap_hsmmc_dev_attr mmc2_p
 
 static struct omap_hwmod omap3xxx_pre_es3_mmc2_hwmod = {
 	.name		= "mmc2",
-	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
-	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
 	.opt_clks	= omap34xx_mmc2_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc2_opt_clks),
 	.main_clk	= "mmchs2_fck",
@@ -1856,8 +1630,6 @@ static struct omap_hwmod omap3xxx_pre_es
 
 static struct omap_hwmod omap3xxx_es3plus_mmc2_hwmod = {
 	.name		= "mmc2",
-	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
-	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
 	.opt_clks	= omap34xx_mmc2_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc2_opt_clks),
 	.main_clk	= "mmchs2_fck",
@@ -1875,16 +1647,7 @@ static struct omap_hwmod omap3xxx_es3plu
 
 /* MMC/SD/SDIO3 */
 
-static struct omap_hwmod_irq_info omap34xx_mmc3_mpu_irqs[] = {
-	{ .irq = 94 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
-static struct omap_hwmod_dma_info omap34xx_mmc3_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = 77, },
-	{ .name = "rx",	.dma_req = 78, },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod_opt_clk omap34xx_mmc3_opt_clks[] = {
 	{ .role = "dbck", .clk = "omap_32k_fck", },
@@ -1892,8 +1655,6 @@ static struct omap_hwmod_opt_clk omap34x
 
 static struct omap_hwmod omap3xxx_mmc3_hwmod = {
 	.name		= "mmc3",
-	.mpu_irqs	= omap34xx_mmc3_mpu_irqs,
-	.sdma_reqs	= omap34xx_mmc3_sdma_reqs,
 	.opt_clks	= omap34xx_mmc3_opt_clks,
 	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc3_opt_clks),
 	.main_clk	= "mmchs3_fck",
@@ -1931,17 +1692,11 @@ static struct omap_hwmod_class omap3xxx_
 	.sysc = &omap3xxx_usb_host_hs_sysc,
 };
 
-static struct omap_hwmod_irq_info omap3xxx_usb_host_hs_irqs[] = {
-	{ .name = "ohci-irq", .irq = 76 + OMAP_INTC_START, },
-	{ .name = "ehci-irq", .irq = 77 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = {
 	.name		= "usb_host_hs",
 	.class		= &omap3xxx_usb_host_hs_hwmod_class,
 	.clkdm_name	= "usbhost_clkdm",
-	.mpu_irqs	= omap3xxx_usb_host_hs_irqs,
 	.main_clk	= "usbhost_48m_fck",
 	.prcm = {
 		.omap2 = {
@@ -2015,16 +1770,11 @@ static struct omap_hwmod_class omap3xxx_
 	.sysc = &omap3xxx_usb_tll_hs_sysc,
 };
 
-static struct omap_hwmod_irq_info omap3xxx_usb_tll_hs_irqs[] = {
-	{ .name = "tll-irq", .irq = 78 + OMAP_INTC_START, },
-	{ .irq = -1 },
-};
 
 static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
 	.name		= "usb_tll_hs",
 	.class		= &omap3xxx_usb_tll_hs_hwmod_class,
 	.clkdm_name	= "core_l4_clkdm",
-	.mpu_irqs	= omap3xxx_usb_tll_hs_irqs,
 	.main_clk	= "usbtll_fck",
 	.prcm = {
 		.omap2 = {
@@ -2039,7 +1789,6 @@ static struct omap_hwmod omap3xxx_usb_tl
 
 static struct omap_hwmod omap3xxx_hdq1w_hwmod = {
 	.name		= "hdq1w",
-	.mpu_irqs	= omap2_hdq1w_mpu_irqs,
 	.main_clk	= "hdq_fck",
 	.prcm		= {
 		.omap2 = {
@@ -2134,16 +1883,10 @@ static struct omap_hwmod_class omap3xxx_
 	.sysc	= &omap3xxx_gpmc_sysc,
 };
 
-static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
-	{ .irq = 20 + OMAP_INTC_START, },
-	{ .irq = -1 }
-};
-
 static struct omap_hwmod omap3xxx_gpmc_hwmod = {
 	.name		= "gpmc",
 	.class		= &omap3xxx_gpmc_hwmod_class,
 	.clkdm_name	= "core_l3_clkdm",
-	.mpu_irqs	= omap3xxx_gpmc_irqs,
 	.main_clk	= "gpmc_fck",
 	/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
 	.flags		= HWMOD_NO_IDLEST | DEBUG_OMAP_GPMC_HWMOD_FLAGS,
@@ -2167,37 +1910,19 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
-	{
-		.pa_start	= 0x68000000,
-		.pa_end		= 0x6800ffff,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 /* MPU -> L3 interface */
 static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
 	.master   = &omap3xxx_mpu_hwmod,
 	.slave    = &omap3xxx_l3_main_hwmod,
-	.addr     = omap3xxx_l3_main_addrs,
 	.user	= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_l4_emu_addrs[] = {
-	{
-		.pa_start	= 0x54000000,
-		.pa_end		= 0x547fffff,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 /* l3 -> debugss */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_debugss = {
 	.master		= &omap3xxx_l3_main_hwmod,
 	.slave		= &omap3xxx_debugss_hwmod,
-	.addr		= omap3xxx_l4_emu_addrs,
 	.user		= OCP_USER_MPU,
 };
 
@@ -2215,7 +1940,7 @@ static struct omap_hwmod_ocp_if omap3xxx
 		.omap2 = {
 			.l3_perm_bit  = OMAP3_L3_CORE_FW_INIT_ID_DSS,
 			.flags	= OMAP_FIREWALL_L3,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -2256,18 +1981,16 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_pre_es3_mmc1_hwmod,
 	.clk		= "mmchs1_ick",
-	.addr		= omap2430_mmc1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-	.flags		= OMAP_FIREWALL_L4
+	.flags		= OMAP_FIREWALL_L4,
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__es3plus_mmc1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_es3plus_mmc1_hwmod,
 	.clk		= "mmchs1_ick",
-	.addr		= omap2430_mmc1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-	.flags		= OMAP_FIREWALL_L4
+	.flags		= OMAP_FIREWALL_L4,
 };
 
 /* L4 CORE -> MMC2 interface */
@@ -2275,126 +1998,70 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_pre_es3_mmc2_hwmod,
 	.clk		= "mmchs2_ick",
-	.addr		= omap2430_mmc2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-	.flags		= OMAP_FIREWALL_L4
+	.flags		= OMAP_FIREWALL_L4,
 };
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__es3plus_mmc2 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_es3plus_mmc2_hwmod,
 	.clk		= "mmchs2_ick",
-	.addr		= omap2430_mmc2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-	.flags		= OMAP_FIREWALL_L4
+	.flags		= OMAP_FIREWALL_L4,
 };
 
 /* L4 CORE -> MMC3 interface */
-static struct omap_hwmod_addr_space omap3xxx_mmc3_addr_space[] = {
-	{
-		.pa_start	= 0x480ad000,
-		.pa_end		= 0x480ad1ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_mmc3_hwmod,
 	.clk		= "mmchs3_ick",
-	.addr		= omap3xxx_mmc3_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-	.flags		= OMAP_FIREWALL_L4
+	.flags		= OMAP_FIREWALL_L4,
 };
 
 /* L4 CORE -> UART1 interface */
-static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
-	{
-		.pa_start	= OMAP3_UART1_BASE,
-		.pa_end		= OMAP3_UART1_BASE + SZ_8K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_uart1_hwmod,
 	.clk		= "uart1_ick",
-	.addr		= omap3xxx_uart1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> UART2 interface */
-static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
-	{
-		.pa_start	= OMAP3_UART2_BASE,
-		.pa_end		= OMAP3_UART2_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_uart2_hwmod,
 	.clk		= "uart2_ick",
-	.addr		= omap3xxx_uart2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 PER -> UART3 interface */
-static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
-	{
-		.pa_start	= OMAP3_UART3_BASE,
-		.pa_end		= OMAP3_UART3_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_uart3_hwmod,
 	.clk		= "uart3_ick",
-	.addr		= omap3xxx_uart3_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 PER -> UART4 interface */
-static struct omap_hwmod_addr_space omap36xx_uart4_addr_space[] = {
-	{
-		.pa_start	= OMAP3_UART4_BASE,
-		.pa_end		= OMAP3_UART4_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap36xx_l4_per__uart4 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap36xx_uart4_hwmod,
 	.clk		= "uart4_ick",
-	.addr		= omap36xx_uart4_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* AM35xx: L4 CORE -> UART4 interface */
-static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = {
-	{
-		.pa_start	= OMAP3_UART4_AM35XX_BASE,
-		.pa_end		= OMAP3_UART4_AM35XX_BASE + SZ_1K - 1,
-		.flags		= ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &am35xx_uart4_hwmod,
 	.clk		= "uart4_ick",
-	.addr		= am35xx_uart4_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2403,13 +2070,12 @@ static struct omap_hwmod_ocp_if omap3_l4
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_i2c1_hwmod,
 	.clk		= "i2c1_ick",
-	.addr		= omap2_i2c1_addr_space,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C1_REGION,
 			.l4_prot_group = 7,
 			.flags	= OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -2419,57 +2085,38 @@ static struct omap_hwmod_ocp_if omap3_l4
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_i2c2_hwmod,
 	.clk		= "i2c2_ick",
-	.addr		= omap2_i2c2_addr_space,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C2_REGION,
 			.l4_prot_group = 7,
 			.flags = OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> I2C3 interface */
-static struct omap_hwmod_addr_space omap3xxx_i2c3_addr_space[] = {
-	{
-		.pa_start	= 0x48060000,
-		.pa_end		= 0x48060000 + SZ_128 - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_i2c3_hwmod,
 	.clk		= "i2c3_ick",
-	.addr		= omap3xxx_i2c3_addr_space,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_I2C3_REGION,
 			.l4_prot_group = 7,
 			.flags = OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* L4 CORE -> SR1 interface */
-static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = {
-	{
-		.pa_start	= OMAP34XX_SR1_BASE,
-		.pa_end		= OMAP34XX_SR1_BASE + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap34xx_l4_core__sr1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_sr1_hwmod,
 	.clk		= "sr_l4_ick",
-	.addr		= omap3_sr1_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
@@ -2477,25 +2124,15 @@ static struct omap_hwmod_ocp_if omap36xx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap36xx_sr1_hwmod,
 	.clk		= "sr_l4_ick",
-	.addr		= omap3_sr1_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
 /* L4 CORE -> SR1 interface */
-static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = {
-	{
-		.pa_start	= OMAP34XX_SR2_BASE,
-		.pa_end		= OMAP34XX_SR2_BASE + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap34xx_l4_core__sr2 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_sr2_hwmod,
 	.clk		= "sr_l4_ick",
-	.addr		= omap3_sr2_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
@@ -2503,43 +2140,24 @@ static struct omap_hwmod_ocp_if omap36xx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap36xx_sr2_hwmod,
 	.clk		= "sr_l4_ick",
-	.addr		= omap3_sr2_addr_space,
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_usbhsotg_addrs[] = {
-	{
-		.pa_start	= OMAP34XX_HSUSB_OTG_BASE,
-		.pa_end		= OMAP34XX_HSUSB_OTG_BASE + SZ_4K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_core -> usbhsotg  */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_usbhsotg_hwmod,
 	.clk		= "l4_ick",
-	.addr		= omap3xxx_usbhsotg_addrs,
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
-	{
-		.pa_start	= AM35XX_IPSS_USBOTGSS_BASE,
-		.pa_end		= AM35XX_IPSS_USBOTGSS_BASE + SZ_4K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_core -> usbhsotg  */
 static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &am35xx_usbhsotg_hwmod,
 	.clk		= "hsotgusb_ick",
-	.addr		= am35xx_usbhsotg_addrs,
 	.user		= OCP_USER_MPU,
 };
 
@@ -2558,165 +2176,84 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
-	{
-		.pa_start	= 0x48318000,
-		.pa_end		= 0x48318000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_wkup -> timer1 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__timer1 = {
 	.master		= &omap3xxx_l4_wkup_hwmod,
 	.slave		= &omap3xxx_timer1_hwmod,
 	.clk		= "gpt1_ick",
-	.addr		= omap3xxx_timer1_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
-	{
-		.pa_start	= 0x49032000,
-		.pa_end		= 0x49032000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer2 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer2 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer2_hwmod,
 	.clk		= "gpt2_ick",
-	.addr		= omap3xxx_timer2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
-	{
-		.pa_start	= 0x49034000,
-		.pa_end		= 0x49034000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer3 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer3 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer3_hwmod,
 	.clk		= "gpt3_ick",
-	.addr		= omap3xxx_timer3_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
-	{
-		.pa_start	= 0x49036000,
-		.pa_end		= 0x49036000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer4 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer4 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer4_hwmod,
 	.clk		= "gpt4_ick",
-	.addr		= omap3xxx_timer4_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
-	{
-		.pa_start	= 0x49038000,
-		.pa_end		= 0x49038000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer5 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer5 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer5_hwmod,
 	.clk		= "gpt5_ick",
-	.addr		= omap3xxx_timer5_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
-	{
-		.pa_start	= 0x4903A000,
-		.pa_end		= 0x4903A000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer6 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer6 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer6_hwmod,
 	.clk		= "gpt6_ick",
-	.addr		= omap3xxx_timer6_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
-	{
-		.pa_start	= 0x4903C000,
-		.pa_end		= 0x4903C000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer7 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer7 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer7_hwmod,
 	.clk		= "gpt7_ick",
-	.addr		= omap3xxx_timer7_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
-	{
-		.pa_start	= 0x4903E000,
-		.pa_end		= 0x4903E000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer8 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer8 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer8_hwmod,
 	.clk		= "gpt8_ick",
-	.addr		= omap3xxx_timer8_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
-	{
-		.pa_start	= 0x49040000,
-		.pa_end		= 0x49040000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> timer9 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer9 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_timer9_hwmod,
 	.clk		= "gpt9_ick",
-	.addr		= omap3xxx_timer9_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2725,7 +2262,6 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_timer10_hwmod,
 	.clk		= "gpt10_ick",
-	.addr		= omap2_timer10_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2734,43 +2270,24 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_timer11_hwmod,
 	.clk		= "gpt11_ick",
-	.addr		= omap2_timer11_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
-	{
-		.pa_start	= 0x48304000,
-		.pa_end		= 0x48304000 + SZ_1K - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_core -> timer12 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_sec__timer12 = {
 	.master		= &omap3xxx_l4_sec_hwmod,
 	.slave		= &omap3xxx_timer12_hwmod,
 	.clk		= "gpt12_ick",
-	.addr		= omap3xxx_timer12_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4_wkup -> wd_timer2 */
-static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
-	{
-		.pa_start	= 0x48314000,
-		.pa_end		= 0x4831407f,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
 	.master		= &omap3xxx_l4_wkup_hwmod,
 	.slave		= &omap3xxx_wd_timer2_hwmod,
 	.clk		= "wdt2_ick",
-	.addr		= omap3xxx_wd_timer2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -2779,13 +2296,12 @@ static struct omap_hwmod_ocp_if omap3430
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3430es1_dss_core_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION,
 			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
 			.flags	= OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -2794,13 +2310,12 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_core_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_CORE_REGION,
 			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
 			.flags	= OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -2810,38 +2325,27 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_dispc_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_dispc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DISPC_REGION,
 			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
 			.flags	= OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
-	{
-		.pa_start	= 0x4804FC00,
-		.pa_end		= 0x4804FFFF,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
-
 /* l4_core -> dss_dsi1 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_dsi1_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap3xxx_dss_dsi1_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DSI_REGION,
 			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
 			.flags	= OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -2851,13 +2355,12 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_rfbi_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_rfbi_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_RFBI_REGION,
 			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP ,
 			.flags	= OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
@@ -2867,66 +2370,38 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_dss_venc_hwmod,
 	.clk		= "dss_ick",
-	.addr		= omap2_dss_venc_addrs,
 	.fw = {
 		.omap2 = {
 			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_VENC_REGION,
 			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
 			.flags	= OMAP_FIREWALL_L4,
-		}
+		},
 	},
 	.flags		= OCPIF_SWSUP_IDLE,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4_wkup -> gpio1 */
-static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
-	{
-		.pa_start	= 0x48310000,
-		.pa_end		= 0x483101ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
 	.master		= &omap3xxx_l4_wkup_hwmod,
 	.slave		= &omap3xxx_gpio1_hwmod,
-	.addr		= omap3xxx_gpio1_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4_per -> gpio2 */
-static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
-	{
-		.pa_start	= 0x49050000,
-		.pa_end		= 0x490501ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio2_hwmod,
-	.addr		= omap3xxx_gpio2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4_per -> gpio3 */
-static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
-	{
-		.pa_start	= 0x49052000,
-		.pa_end		= 0x490521ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio3_hwmod,
-	.addr		= omap3xxx_gpio3_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3002,53 +2477,26 @@ static struct omap_hwmod omap3xxx_mmu_iv
 };
 
 /* l4_per -> gpio4 */
-static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
-	{
-		.pa_start	= 0x49054000,
-		.pa_end		= 0x490541ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio4_hwmod,
-	.addr		= omap3xxx_gpio4_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4_per -> gpio5 */
-static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
-	{
-		.pa_start	= 0x49056000,
-		.pa_end		= 0x490561ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio5_hwmod,
-	.addr		= omap3xxx_gpio5_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4_per -> gpio6 */
-static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
-	{
-		.pa_start	= 0x49058000,
-		.pa_end		= 0x490581ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_gpio6_hwmod,
-	.addr		= omap3xxx_gpio6_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3064,9 +2512,9 @@ static struct omap_hwmod_addr_space omap
 	{
 		.pa_start	= 0x48056000,
 		.pa_end		= 0x48056fff,
-		.flags		= ADDR_TYPE_RT
+		.flags		= ADDR_TYPE_RT,
 	},
-	{ }
+	{ },
 };
 
 /* l4_cfg -> dma_system */
@@ -3078,136 +2526,66 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x48074000,
-		.pa_end		= 0x480740ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_core -> mcbsp1 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp1 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_mcbsp1_hwmod,
 	.clk		= "mcbsp1_ick",
-	.addr		= omap3xxx_mcbsp1_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x49022000,
-		.pa_end		= 0x490220ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> mcbsp2 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_mcbsp2_hwmod,
 	.clk		= "mcbsp2_ick",
-	.addr		= omap3xxx_mcbsp2_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x49024000,
-		.pa_end		= 0x490240ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> mcbsp3 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_mcbsp3_hwmod,
 	.clk		= "mcbsp3_ick",
-	.addr		= omap3xxx_mcbsp3_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x49026000,
-		.pa_end		= 0x490260ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> mcbsp4 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp4 = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_mcbsp4_hwmod,
 	.clk		= "mcbsp4_ick",
-	.addr		= omap3xxx_mcbsp4_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
-	{
-		.name		= "mpu",
-		.pa_start	= 0x48096000,
-		.pa_end		= 0x480960ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_core -> mcbsp5 */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp5 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_mcbsp5_hwmod,
 	.clk		= "mcbsp5_ick",
-	.addr		= omap3xxx_mcbsp5_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
-	{
-		.name		= "sidetone",
-		.pa_start	= 0x49028000,
-		.pa_end		= 0x490280ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> mcbsp2_sidetone */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2_sidetone = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_mcbsp2_sidetone_hwmod,
 	.clk		= "mcbsp2_ick",
-	.addr		= omap3xxx_mcbsp2_sidetone_addrs,
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
-	{
-		.name		= "sidetone",
-		.pa_start	= 0x4902A000,
-		.pa_end		= 0x4902A0ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 /* l4_per -> mcbsp3_sidetone */
 static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3_sidetone = {
 	.master		= &omap3xxx_l4_per_hwmod,
 	.slave		= &omap3xxx_mcbsp3_sidetone_hwmod,
 	.clk		= "mcbsp3_ick",
-	.addr		= omap3xxx_mcbsp3_sidetone_addrs,
 	.user		= OCP_USER_MPU,
 };
 
@@ -3223,7 +2601,6 @@ static struct omap_hwmod_ocp_if omap34xx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_mcspi1,
 	.clk		= "mcspi1_ick",
-	.addr		= omap2_mcspi1_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3232,7 +2609,6 @@ static struct omap_hwmod_ocp_if omap34xx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_mcspi2,
 	.clk		= "mcspi2_ick",
-	.addr		= omap2_mcspi2_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3241,25 +2617,15 @@ static struct omap_hwmod_ocp_if omap34xx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_mcspi3,
 	.clk		= "mcspi3_ick",
-	.addr		= omap2430_mcspi3_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l4 core -> mcspi4 interface */
-static struct omap_hwmod_addr_space omap34xx_mcspi4_addr_space[] = {
-	{
-		.pa_start	= 0x480ba000,
-		.pa_end		= 0x480ba0ff,
-		.flags		= ADDR_TYPE_RT,
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap34xx_mcspi4,
 	.clk		= "mcspi4_ick",
-	.addr		= omap34xx_mcspi4_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3270,49 +2636,19 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_usb_host_hs_addrs[] = {
-	{
-		.name		= "uhh",
-		.pa_start	= 0x48064000,
-		.pa_end		= 0x480643ff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{
-		.name		= "ohci",
-		.pa_start	= 0x48064400,
-		.pa_end		= 0x480647ff,
-	},
-	{
-		.name		= "ehci",
-		.pa_start	= 0x48064800,
-		.pa_end		= 0x48064cff,
-	},
-	{}
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_host_hs = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_usb_host_hs_hwmod,
 	.clk		= "usbhost_ick",
-	.addr		= omap3xxx_usb_host_hs_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_usb_tll_hs_addrs[] = {
-	{
-		.name		= "tll",
-		.pa_start	= 0x48062000,
-		.pa_end		= 0x48062fff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{}
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_usb_tll_hs_hwmod,
 	.clk		= "usbtll_ick",
-	.addr		= omap3xxx_usb_tll_hs_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3321,35 +2657,17 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_hdq1w_hwmod,
 	.clk		= "hdq_ick",
-	.addr		= omap2_hdq1w_addr_space,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 	.flags		= OMAP_FIREWALL_L4 | OCPIF_SWSUP_IDLE,
 };
 
 /* l4_wkup -> 32ksync_counter */
-static struct omap_hwmod_addr_space omap3xxx_counter_32k_addrs[] = {
-	{
-		.pa_start	= 0x48320000,
-		.pa_end		= 0x4832001f,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
-static struct omap_hwmod_addr_space omap3xxx_gpmc_addrs[] = {
-	{
-		.pa_start	= 0x6e000000,
-		.pa_end		= 0x6e000fff,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = {
 	.master		= &omap3xxx_l4_wkup_hwmod,
 	.slave		= &omap3xxx_counter_32k_hwmod,
 	.clk		= "omap_32ksync_ick",
-	.addr		= omap3xxx_counter_32k_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3434,7 +2752,6 @@ static struct omap_hwmod_ocp_if omap3xxx
 	.master		= &omap3xxx_l3_main_hwmod,
 	.slave		= &omap3xxx_gpmc_hwmod,
 	.clk		= "core_l3_ick",
-	.addr		= omap3xxx_gpmc_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3459,20 +2776,10 @@ static struct omap_hwmod_class omap3xxx_
 	.sysc	= &omap3_sham_sysc,
 };
 
-static struct omap_hwmod_irq_info omap3_sham_mpu_irqs[] = {
-	{ .irq = 49 + OMAP_INTC_START, },
-	{ .irq = -1 }
-};
 
-static struct omap_hwmod_dma_info omap3_sham_sdma_reqs[] = {
-	{ .name = "rx", .dma_req = 69, },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod omap3xxx_sham_hwmod = {
 	.name		= "sham",
-	.mpu_irqs	= omap3_sham_mpu_irqs,
-	.sdma_reqs	= omap3_sham_sdma_reqs,
 	.main_clk	= "sha12_ick",
 	.prcm		= {
 		.omap2 = {
@@ -3486,20 +2793,11 @@ static struct omap_hwmod omap3xxx_sham_h
 	.class		= &omap3xxx_sham_class,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_sham_addrs[] = {
-	{
-		.pa_start	= 0x480c3000,
-		.pa_end		= 0x480c3000 + 0x64 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__sham = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_sham_hwmod,
 	.clk		= "sha12_ick",
-	.addr		= omap3xxx_sham_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3525,15 +2823,9 @@ static struct omap_hwmod_class omap3xxx_
 	.sysc	= &omap3_aes_sysc,
 };
 
-static struct omap_hwmod_dma_info omap3_aes_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 65, },
-	{ .name = "rx", .dma_req = 66, },
-	{ .dma_req = -1 }
-};
 
 static struct omap_hwmod omap3xxx_aes_hwmod = {
 	.name		= "aes",
-	.sdma_reqs	= omap3_aes_sdma_reqs,
 	.main_clk	= "aes2_ick",
 	.prcm		= {
 		.omap2 = {
@@ -3547,20 +2839,11 @@ static struct omap_hwmod omap3xxx_aes_hw
 	.class		= &omap3xxx_aes_class,
 };
 
-static struct omap_hwmod_addr_space omap3xxx_aes_addrs[] = {
-	{
-		.pa_start	= 0x480c5000,
-		.pa_end		= 0x480c5000 + 0x50 - 1,
-		.flags		= ADDR_TYPE_RT
-	},
-	{ }
-};
 
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__aes = {
 	.master		= &omap3xxx_l4_core_hwmod,
 	.slave		= &omap3xxx_aes_hwmod,
 	.clk		= "aes2_ick",
-	.addr		= omap3xxx_aes_addrs,
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -3661,28 +2944,28 @@ static struct omap_hwmod_ocp_if *omap3xx
 /* GP-only hwmod links */
 static struct omap_hwmod_ocp_if *omap34xx_gp_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_sec__timer12,
-	NULL
+	NULL,
 };
 
 static struct omap_hwmod_ocp_if *omap36xx_gp_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_sec__timer12,
-	NULL
+	NULL,
 };
 
 static struct omap_hwmod_ocp_if *am35xx_gp_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_sec__timer12,
-	NULL
+	NULL,
 };
 
 /* crypto hwmod links */
 static struct omap_hwmod_ocp_if *omap34xx_sham_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_core__sham,
-	NULL
+	NULL,
 };
 
 static struct omap_hwmod_ocp_if *omap34xx_aes_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_core__aes,
-	NULL
+	NULL,
 };
 
 static struct omap_hwmod_ocp_if *omap36xx_sham_hwmod_ocp_ifs[] __initdata = {
@@ -3710,14 +2993,14 @@ static struct omap_hwmod_ocp_if *am35xx_
 
 static struct omap_hwmod_ocp_if *am35xx_aes_hwmod_ocp_ifs[] __initdata = {
 	/* &omap3xxx_l4_core__aes, */
-	NULL
+	NULL,
 };
 
 /* 3430ES1-only hwmod links */
 static struct omap_hwmod_ocp_if *omap3430es1_hwmod_ocp_ifs[] __initdata = {
 	&omap3430es1_dss__l3,
 	&omap3430es1_l4_core__dss,
-	NULL
+	NULL,
 };
 
 /* 3430ES2+-only hwmod links */
@@ -3729,21 +3012,21 @@ static struct omap_hwmod_ocp_if *omap343
 	&omap3xxx_usb_host_hs__l3_main_2,
 	&omap3xxx_l4_core__usb_host_hs,
 	&omap3xxx_l4_core__usb_tll_hs,
-	NULL
+	NULL,
 };
 
 /* <= 3430ES3-only hwmod links */
 static struct omap_hwmod_ocp_if *omap3430_pre_es3_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_core__pre_es3_mmc1,
 	&omap3xxx_l4_core__pre_es3_mmc2,
-	NULL
+	NULL,
 };
 
 /* 3430ES3+-only hwmod links */
 static struct omap_hwmod_ocp_if *omap3430_es3plus_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l4_core__es3plus_mmc1,
 	&omap3xxx_l4_core__es3plus_mmc2,
-	NULL
+	NULL,
 };
 
 /* 34xx-only hwmod links (all ES revisions) */
@@ -3757,7 +3040,7 @@ static struct omap_hwmod_ocp_if *omap34x
 	&omap3xxx_l4_core__mmu_isp,
 	&omap3xxx_l3_main__mmu_iva,
 	&omap3xxx_l4_core__ssi,
-	NULL
+	NULL,
 };
 
 /* 36xx-only hwmod links (all ES revisions) */
@@ -3781,7 +3064,7 @@ static struct omap_hwmod_ocp_if *omap36x
 	&omap3xxx_l4_core__mmu_isp,
 	&omap3xxx_l3_main__mmu_iva,
 	&omap3xxx_l4_core__ssi,
-	NULL
+	NULL,
 };
 
 static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = {
@@ -3800,7 +3083,7 @@ static struct omap_hwmod_ocp_if *am35xx_
 	&am35xx_l4_core__mdio,
 	&am35xx_emac__l3,
 	&am35xx_l4_core__emac,
-	NULL
+	NULL,
 };
 
 static struct omap_hwmod_ocp_if *omap3xxx_dss_hwmod_ocp_ifs[] __initdata = {
@@ -3808,7 +3091,7 @@ static struct omap_hwmod_ocp_if *omap3xx
 	&omap3xxx_l4_core__dss_dsi1,
 	&omap3xxx_l4_core__dss_rfbi,
 	&omap3xxx_l4_core__dss_venc,
-	NULL
+	NULL,
 };
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_43xx_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -442,6 +442,31 @@ static struct omap_hwmod am43xx_adc_tsc_
 	},
 };
 
+static struct omap_hwmod_class_sysconfig am43xx_des_sysc = {
+	.rev_offs	= 0x30,
+	.sysc_offs	= 0x34,
+	.syss_offs	= 0x38,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class am43xx_des_hwmod_class = {
+	.name		= "des",
+	.sysc		= &am43xx_des_sysc,
+};
+
+static struct omap_hwmod am43xx_des_hwmod = {
+	.name		= "des",
+	.class		= &am43xx_des_hwmod_class,
+	.clkdm_name	= "l3_clkdm",
+	.main_clk	= "l3_gclk",
+	.prcm		= {
+		.omap4	= {
+			.clkctrl_offs	= AM43XX_CM_PER_DES_CLKCTRL_OFFSET,
+			.modulemode	= MODULEMODE_SWCTRL,
+		},
+	},
+};
+
 /* dss */
 
 static struct omap_hwmod am43xx_dss_core_hwmod = {
@@ -870,6 +895,13 @@ static struct omap_hwmod_ocp_if am43xx_l
 	.user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_ocp_if am43xx_l3_main__des = {
+	.master		= &am33xx_l3_main_hwmod,
+	.slave		= &am43xx_des_hwmod,
+	.clk		= "l3_gclk",
+	.user		= OCP_USER_MPU,
+};
+
 static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
 	&am33xx_l4_wkup__synctimer,
 	&am43xx_l4_ls__timer8,
@@ -917,6 +949,7 @@ static struct omap_hwmod_ocp_if *am43xx_
 	&am33xx_l4_per__i2c2,
 	&am33xx_l4_per__i2c3,
 	&am33xx_l4_per__mailbox,
+	&am33xx_l4_per__rng,
 	&am33xx_l4_ls__mcasp0,
 	&am33xx_l4_ls__mcasp1,
 	&am33xx_l4_ls__mmc0,
@@ -950,6 +983,7 @@ static struct omap_hwmod_ocp_if *am43xx_
 	&am33xx_cpgmac0__mdio,
 	&am33xx_l3_main__sha0,
 	&am33xx_l3_main__aes0,
+	&am43xx_l3_main__des,
 	&am43xx_l4_ls__ocp2scp0,
 	&am43xx_l4_ls__ocp2scp1,
 	&am43xx_l3_s__usbotgss0,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_7xx_data.c	2017-02-12 16:03:20.000000000 -0500
@@ -690,6 +690,78 @@ static struct omap_hwmod dra7xx_dss_hdmi
 	.parent_hwmod	= &dra7xx_dss_hwmod,
 };
 
+/* AES (the 'P' (public) device) */
+static struct omap_hwmod_class_sysconfig dra7xx_aes_sysc = {
+	.rev_offs	= 0x0080,
+	.sysc_offs	= 0x0084,
+	.syss_offs	= 0x0088,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class dra7xx_aes_hwmod_class = {
+	.name	= "aes",
+	.sysc	= &dra7xx_aes_sysc,
+	.rev	= 2,
+};
+
+/* AES1 */
+static struct omap_hwmod dra7xx_aes1_hwmod = {
+	.name		= "aes1",
+	.class		= &dra7xx_aes_hwmod_class,
+	.clkdm_name	= "l4sec_clkdm",
+	.main_clk	= "l3_iclk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4SEC_AES1_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4SEC_AES1_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
+/* AES2 */
+static struct omap_hwmod dra7xx_aes2_hwmod = {
+	.name		= "aes2",
+	.class		= &dra7xx_aes_hwmod_class,
+	.clkdm_name	= "l4sec_clkdm",
+	.main_clk	= "l3_iclk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4SEC_AES2_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4SEC_AES2_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
+/* sha0 HIB2 (the 'P' (public) device) */
+static struct omap_hwmod_class_sysconfig dra7xx_sha0_sysc = {
+	.rev_offs	= 0x100,
+	.sysc_offs	= 0x110,
+	.syss_offs	= 0x114,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class dra7xx_sha0_hwmod_class = {
+	.name		= "sham",
+	.sysc		= &dra7xx_sha0_sysc,
+	.rev		= 2,
+};
+
+struct omap_hwmod dra7xx_sha0_hwmod = {
+	.name		= "sham",
+	.class		= &dra7xx_sha0_hwmod_class,
+	.clkdm_name	= "l4sec_clkdm",
+	.main_clk	= "l3_iclk_div",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4SEC_SHA2MD51_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4SEC_SHA2MD51_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
 /*
  * 'elm' class
  *
@@ -2541,6 +2613,62 @@ static struct omap_hwmod dra7xx_uart10_h
 	},
 };
 
+/* DES (the 'P' (public) device) */
+static struct omap_hwmod_class_sysconfig dra7xx_des_sysc = {
+	.rev_offs	= 0x0030,
+	.sysc_offs	= 0x0034,
+	.syss_offs	= 0x0038,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class dra7xx_des_hwmod_class = {
+	.name	= "des",
+	.sysc	= &dra7xx_des_sysc,
+};
+
+/* DES */
+static struct omap_hwmod dra7xx_des_hwmod = {
+	.name		= "des",
+	.class		= &dra7xx_des_hwmod_class,
+	.clkdm_name	= "l4sec_clkdm",
+	.main_clk	= "l3_iclk_div",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4SEC_DES3DES_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4SEC_DES3DES_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
+/* rng */
+static struct omap_hwmod_class_sysconfig dra7xx_rng_sysc = {
+	.rev_offs       = 0x1fe0,
+	.sysc_offs      = 0x1fe4,
+	.sysc_flags     = SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE,
+	.idlemodes      = SIDLE_FORCE | SIDLE_NO,
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class dra7xx_rng_hwmod_class = {
+	.name           = "rng",
+	.sysc           = &dra7xx_rng_sysc,
+};
+
+static struct omap_hwmod dra7xx_rng_hwmod = {
+	.name           = "rng",
+	.class          = &dra7xx_rng_hwmod_class,
+	.flags		= HWMOD_SWSUP_SIDLE,
+	.clkdm_name     = "l4sec_clkdm",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_offs = DRA7XX_CM_L4SEC_RNG_CLKCTRL_OFFSET,
+			.context_offs = DRA7XX_RM_L4SEC_RNG_CONTEXT_OFFSET,
+			.modulemode   = MODULEMODE_HWCTRL,
+		},
+	},
+};
+
 /*
  * 'usb_otg_ss' class
  *
@@ -2929,6 +3057,30 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l3_main_1 -> aes1 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes1 = {
+	.master		= &dra7xx_l3_main_1_hwmod,
+	.slave		= &dra7xx_aes1_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> aes2 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__aes2 = {
+	.master		= &dra7xx_l3_main_1_hwmod,
+	.slave		= &dra7xx_aes2_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 -> sha0 */
+static struct omap_hwmod_ocp_if dra7xx_l3_main_1__sha0 = {
+	.master		= &dra7xx_l3_main_1_hwmod,
+	.slave		= &dra7xx_sha0_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per2 -> mcasp1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per2__mcasp1 = {
 	.master		= &dra7xx_l4_per2_hwmod,
@@ -3642,6 +3794,14 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per1 -> des */
+static struct omap_hwmod_ocp_if dra7xx_l4_per1__des = {
+	.master		= &dra7xx_l4_per1_hwmod,
+	.slave		= &dra7xx_des_hwmod,
+	.clk		= "l3_iclk_div",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l4_per2 -> uart8 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per2__uart8 = {
 	.master		= &dra7xx_l4_per2_hwmod,
@@ -3666,6 +3826,13 @@ static struct omap_hwmod_ocp_if dra7xx_l
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* l4_per1 -> rng */
+static struct omap_hwmod_ocp_if dra7xx_l4_per1__rng = {
+	.master         = &dra7xx_l4_per1_hwmod,
+	.slave          = &dra7xx_rng_hwmod,
+	.user           = OCP_USER_MPU,
+};
+
 /* l4_per3 -> usb_otg_ss1 */
 static struct omap_hwmod_ocp_if dra7xx_l4_per3__usb_otg_ss1 = {
 	.master		= &dra7xx_l4_per3_hwmod,
@@ -3800,6 +3967,9 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l3_main_1__dss,
 	&dra7xx_l3_main_1__dispc,
 	&dra7xx_l3_main_1__hdmi,
+	&dra7xx_l3_main_1__aes1,
+	&dra7xx_l3_main_1__aes2,
+	&dra7xx_l3_main_1__sha0,
 	&dra7xx_l4_per1__elm,
 	&dra7xx_l4_wkup__gpio1,
 	&dra7xx_l4_per1__gpio2,
@@ -3845,7 +4015,6 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l3_main_1__pciess2,
 	&dra7xx_l4_cfg__pciess2,
 	&dra7xx_l3_main_1__qspi,
-	&dra7xx_l4_per3__rtcss,
 	&dra7xx_l4_cfg__sata,
 	&dra7xx_l4_cfg__smartreflex_core,
 	&dra7xx_l4_cfg__smartreflex_mpu,
@@ -3875,6 +4044,7 @@ static struct omap_hwmod_ocp_if *dra7xx_
 	&dra7xx_l4_per2__uart8,
 	&dra7xx_l4_per2__uart9,
 	&dra7xx_l4_wkup__uart10,
+	&dra7xx_l4_per1__des,
 	&dra7xx_l4_per3__usb_otg_ss1,
 	&dra7xx_l4_per3__usb_otg_ss2,
 	&dra7xx_l4_per3__usb_otg_ss3,
@@ -3892,6 +4062,7 @@ static struct omap_hwmod_ocp_if *dra7xx_
 /* GP-only hwmod links */
 static struct omap_hwmod_ocp_if *dra7xx_gp_hwmod_ocp_ifs[] __initdata = {
 	&dra7xx_l4_wkup__timer12,
+	&dra7xx_l4_per1__rng,
 	NULL,
 };
 
@@ -3905,6 +4076,11 @@ static struct omap_hwmod_ocp_if *dra72x_
 	NULL,
 };
 
+static struct omap_hwmod_ocp_if *dra74x_dra72x_hwmod_ocp_ifs[] __initdata = {
+	&dra7xx_l4_per3__rtcss,
+	NULL,
+};
+
 int __init dra7xx_hwmod_init(void)
 {
 	int ret;
@@ -3920,5 +4096,9 @@ int __init dra7xx_hwmod_init(void)
 	if (!ret && omap_type() == OMAP2_DEVICE_TYPE_GP)
 		ret = omap_hwmod_register_links(dra7xx_gp_hwmod_ocp_ifs);
 
+	/* now for the IPs *NOT* in dra71 */
+	if (!ret && !of_machine_is_compatible("ti,dra718"))
+		ret = omap_hwmod_register_links(dra74x_dra72x_hwmod_ocp_ifs);
+
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod.c	2017-02-12 16:03:20.000000000 -0500
@@ -160,7 +160,6 @@
 #include "prm44xx.h"
 #include "prm33xx.h"
 #include "prminst44xx.h"
-#include "mux.h"
 #include "pm.h"
 
 /* Name of the OMAP hwmod for the MPU */
@@ -217,9 +216,6 @@ static LIST_HEAD(omap_hwmod_list);
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
 
-/* io_chain_lock: used to serialize reconfigurations of the I/O chain */
-static DEFINE_SPINLOCK(io_chain_lock);
-
 /*
  * linkspace: ptr to a buffer that struct omap_hwmod_link records are
  * allocated from - used to reduce the number of small memory
@@ -594,51 +590,6 @@ static int _set_module_autoidle(struct o
 }
 
 /**
- * _set_idle_ioring_wakeup - enable/disable IO pad wakeup on hwmod idle for mux
- * @oh: struct omap_hwmod *
- * @set_wake: bool value indicating to set (true) or clear (false) wakeup enable
- *
- * Set or clear the I/O pad wakeup flag in the mux entries for the
- * hwmod @oh.  This function changes the @oh->mux->pads_dynamic array
- * in memory.  If the hwmod is currently idled, and the new idle
- * values don't match the previous ones, this function will also
- * update the SCM PADCTRL registers.  Otherwise, if the hwmod is not
- * currently idled, this function won't touch the hardware: the new
- * mux settings are written to the SCM PADCTRL registers when the
- * hwmod is idled.  No return value.
- */
-static void _set_idle_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
-{
-	struct omap_device_pad *pad;
-	bool change = false;
-	u16 prev_idle;
-	int j;
-
-	if (!oh->mux || !oh->mux->enabled)
-		return;
-
-	for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
-		pad = oh->mux->pads_dynamic[j];
-
-		if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP))
-			continue;
-
-		prev_idle = pad->idle;
-
-		if (set_wake)
-			pad->idle |= OMAP_WAKEUP_EN;
-		else
-			pad->idle &= ~OMAP_WAKEUP_EN;
-
-		if (prev_idle != pad->idle)
-			change = true;
-	}
-
-	if (change && oh->_state == _HWMOD_STATE_IDLE)
-		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
-}
-
-/**
  * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
  * @oh: struct omap_hwmod *
  *
@@ -790,14 +741,14 @@ static int _init_main_clk(struct omap_hw
 	int ret = 0;
 	char name[MOD_CLK_MAX_NAME_LEN];
 	struct clk *clk;
+	static const char modck[] = "_mod_ck";
 
-	/* +7 magic comes from '_mod_ck' suffix */
-	if (strlen(oh->name) + 7 > MOD_CLK_MAX_NAME_LEN)
+	if (strlen(oh->name) >= MOD_CLK_MAX_NAME_LEN - strlen(modck))
 		pr_warn("%s: warning: cropping name for %s\n", __func__,
 			oh->name);
 
-	strncpy(name, oh->name, MOD_CLK_MAX_NAME_LEN - 7);
-	strcat(name, "_mod_ck");
+	strlcpy(name, oh->name, MOD_CLK_MAX_NAME_LEN - strlen(modck));
+	strlcat(name, modck, MOD_CLK_MAX_NAME_LEN);
 
 	clk = clk_get(NULL, name);
 	if (!IS_ERR(clk)) {
@@ -2018,29 +1969,6 @@ static int _reset(struct omap_hwmod *oh)
 }
 
 /**
- * _reconfigure_io_chain - clear any I/O chain wakeups and reconfigure chain
- *
- * Call the appropriate PRM function to clear any logged I/O chain
- * wakeups and to reconfigure the chain.  This apparently needs to be
- * done upon every mux change.  Since hwmods can be concurrently
- * enabled and idled, hold a spinlock around the I/O chain
- * reconfiguration sequence.  No return value.
- *
- * XXX When the PRM code is moved to drivers, this function can be removed,
- * as the PRM infrastructure should abstract this.
- */
-static void _reconfigure_io_chain(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_chain_lock, flags);
-
-	omap_prm_reconfigure_io_chain();
-
-	spin_unlock_irqrestore(&io_chain_lock, flags);
-}
-
-/**
  * _omap4_update_context_lost - increment hwmod context loss counter if
  * hwmod context was lost, and clear hardware context loss reg
  * @oh: hwmod to check for context loss
@@ -2109,18 +2037,9 @@ static int _enable(struct omap_hwmod *oh
 
 	/*
 	 * hwmods with HWMOD_INIT_NO_IDLE flag set are left in enabled
-	 * state at init.  Now that someone is really trying to enable
-	 * them, just ensure that the hwmod mux is set.
+	 * state at init.
 	 */
 	if (oh->_int_flags & _HWMOD_SKIP_ENABLE) {
-		/*
-		 * If the caller has mux data populated, do the mux'ing
-		 * which wouldn't have been done as part of the _enable()
-		 * done during setup.
-		 */
-		if (oh->mux)
-			omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
-
 		oh->_int_flags &= ~_HWMOD_SKIP_ENABLE;
 		return 0;
 	}
@@ -2145,16 +2064,6 @@ static int _enable(struct omap_hwmod *oh
 	if (_are_all_hardreset_lines_asserted(oh))
 		return 0;
 
-	/* Mux pins for device runtime if populated */
-	if (oh->mux && (!oh->mux->enabled ||
-			((oh->_state == _HWMOD_STATE_IDLE) &&
-			 oh->mux->pads_dynamic))) {
-		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
-		_reconfigure_io_chain();
-	} else if (oh->flags & HWMOD_RECONFIG_IO_CHAIN) {
-		_reconfigure_io_chain();
-	}
-
 	_add_initiator_dep(oh, mpu_oh);
 
 	if (oh->clkdm) {
@@ -2260,14 +2169,6 @@ static int _idle(struct omap_hwmod *oh)
 		clkdm_hwmod_disable(oh->clkdm, oh);
 	}
 
-	/* Mux pins for device idle if populated */
-	if (oh->mux && oh->mux->pads_dynamic) {
-		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
-		_reconfigure_io_chain();
-	} else if (oh->flags & HWMOD_RECONFIG_IO_CHAIN) {
-		_reconfigure_io_chain();
-	}
-
 	oh->_state = _HWMOD_STATE_IDLE;
 
 	return 0;
@@ -2334,10 +2235,6 @@ static int _shutdown(struct omap_hwmod *
 	for (i = 0; i < oh->rst_lines_cnt; i++)
 		_assert_hardreset(oh, oh->rst_lines[i].name);
 
-	/* Mux pins to safe mode or use populated off mode values */
-	if (oh->mux)
-		omap_hwmod_mux(oh->mux, _HWMOD_STATE_DISABLED);
-
 	oh->_state = _HWMOD_STATE_DISABLED;
 
 	return 0;
@@ -3729,7 +3626,6 @@ int omap_hwmod_enable_wakeup(struct omap
 		_write_sysconfig(v, oh);
 	}
 
-	_set_idle_ioring_wakeup(oh, true);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -3762,7 +3658,6 @@ int omap_hwmod_disable_wakeup(struct oma
 		_write_sysconfig(v, oh);
 	}
 
-	_set_idle_ioring_wakeup(oh, false);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap_hwmod_common_data.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,22 +19,7 @@
 #include "display.h"
 
 /* Common address space across OMAP2xxx/3xxx */
-extern struct omap_hwmod_addr_space omap2_i2c1_addr_space[];
-extern struct omap_hwmod_addr_space omap2_i2c2_addr_space[];
-extern struct omap_hwmod_addr_space omap2_dss_addrs[];
-extern struct omap_hwmod_addr_space omap2_dss_dispc_addrs[];
-extern struct omap_hwmod_addr_space omap2_dss_rfbi_addrs[];
-extern struct omap_hwmod_addr_space omap2_dss_venc_addrs[];
-extern struct omap_hwmod_addr_space omap2_timer10_addrs[];
-extern struct omap_hwmod_addr_space omap2_timer11_addrs[];
-extern struct omap_hwmod_addr_space omap2430_mmc1_addr_space[];
-extern struct omap_hwmod_addr_space omap2430_mmc2_addr_space[];
-extern struct omap_hwmod_addr_space omap2_mcspi1_addr_space[];
-extern struct omap_hwmod_addr_space omap2_mcspi2_addr_space[];
-extern struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[];
 extern struct omap_hwmod_addr_space omap2_dma_system_addrs[];
-extern struct omap_hwmod_addr_space omap2_mcbsp1_addrs[];
-extern struct omap_hwmod_addr_space omap2_hdq1w_addr_space[];
 
 /* Common IP block data across OMAP2xxx */
 extern struct omap_gpio_dev_attr omap2xxx_gpio_dev_attr;
@@ -136,10 +121,6 @@ extern struct omap_hwmod_irq_info omap2_
 extern struct omap_hwmod_irq_info omap2_dispc_irqs[];
 extern struct omap_hwmod_irq_info omap2_i2c1_mpu_irqs[];
 extern struct omap_hwmod_irq_info omap2_i2c2_mpu_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio1_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio2_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio3_irqs[];
-extern struct omap_hwmod_irq_info omap2_gpio4_irqs[];
 extern struct omap_hwmod_irq_info omap2_dma_system_irqs[];
 extern struct omap_hwmod_irq_info omap2_mcspi1_mpu_irqs[];
 extern struct omap_hwmod_irq_info omap2_mcspi2_mpu_irqs[];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/omap-mpuss-lowpower.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,7 @@
 #include <asm/smp_scu.h>
 #include <asm/pgalloc.h>
 #include <asm/suspend.h>
+#include <asm/virt.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include "soc.h"
@@ -244,10 +245,9 @@ int omap4_enter_lowpower(unsigned int cp
 		save_state = 1;
 		break;
 	case PWRDM_POWER_RET:
-		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) {
+		if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE))
 			save_state = 0;
-			break;
-		}
+		break;
 	default:
 		/*
 		 * CPUx CSWR is invalid hardware state. Also CPUx OSWR
@@ -371,8 +371,12 @@ int __init omap4_mpuss_init(void)
 	pm_info = &per_cpu(omap4_pm_info, 0x0);
 	if (sar_base) {
 		pm_info->scu_sar_addr = sar_base + SCU_OFFSET0;
-		pm_info->wkup_sar_addr = sar_base +
-					CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
+		if (cpu_is_omap44xx())
+			pm_info->wkup_sar_addr = sar_base +
+				CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
+		else
+			pm_info->wkup_sar_addr = sar_base +
+				OMAP5_CPU0_WAKEUP_NS_PA_ADDR_OFFSET;
 		pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0;
 	}
 	pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm");
@@ -391,8 +395,12 @@ int __init omap4_mpuss_init(void)
 	pm_info = &per_cpu(omap4_pm_info, 0x1);
 	if (sar_base) {
 		pm_info->scu_sar_addr = sar_base + SCU_OFFSET1;
-		pm_info->wkup_sar_addr = sar_base +
-					CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
+		if (cpu_is_omap44xx())
+			pm_info->wkup_sar_addr = sar_base +
+				CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
+		else
+			pm_info->wkup_sar_addr = sar_base +
+				OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET;
 		pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1;
 	}
 
@@ -453,15 +461,24 @@ void __init omap4_mpuss_early_init(void)
 {
 	unsigned long startup_pa;
 
-	if (!cpu_is_omap44xx())
+	if (!(cpu_is_omap44xx() || soc_is_omap54xx()))
 		return;
 
 	sar_base = omap4_get_sar_ram_base();
 
 	if (cpu_is_omap443x())
 		startup_pa = virt_to_phys(omap4_secondary_startup);
-	else
+	else if (cpu_is_omap446x())
 		startup_pa = virt_to_phys(omap4460_secondary_startup);
+	else if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE)
+		startup_pa = virt_to_phys(omap5_secondary_hyp_startup);
+	else
+		startup_pa = virt_to_phys(omap5_secondary_startup);
 
-	writel_relaxed(startup_pa, sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
+	if (cpu_is_omap44xx())
+		writel_relaxed(startup_pa, sar_base +
+			       CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
+	else
+		writel_relaxed(startup_pa, sar_base +
+			       OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/pdata-quirks.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pdata-quirks.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/pdata-quirks.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pdata-quirks.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,6 @@
 
 #include "common.h"
 #include "common-board-devices.h"
-#include "dss-common.h"
 #include "control.h"
 #include "omap_device.h"
 #include "omap-pm.h"
@@ -162,7 +161,7 @@ static struct ti_st_plat_data wilink7_pd
 	.nshutdown_gpio = 162,
 	.dev_name = "/dev/ttyO1",
 	.flow_cntrl = 1,
-	.baud_rate = 300000,
+	.baud_rate = 3000000,
 };
 
 static struct platform_device wl128x_device = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/pm44xx.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pm44xx.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/pm44xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pm44xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -287,7 +287,7 @@ int __init omap4_pm_init(void)
 	/* Overwrite the default cpu_do_idle() */
 	arm_pm_idle = omap_default_idle;
 
-	if (cpu_is_omap44xx())
+	if (cpu_is_omap44xx() || soc_is_omap54xx())
 		omap4_idle_init();
 
 err2:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/pm.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pm.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,6 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "pm.h"
-#include "twl-common.h"
 
 #ifdef CONFIG_SUSPEND
 /*
@@ -72,42 +71,6 @@ void omap_pm_get_oscillator(u32 *tstart,
 }
 #endif
 
-static int __init _init_omap_device(char *name)
-{
-	struct omap_hwmod *oh;
-	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;
-
-	pdev = omap_device_build(oh->name, 0, oh, NULL, 0);
-	if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n",
-		 __func__, name))
-		return -ENODEV;
-
-	return 0;
-}
-
-/*
- * Build omap_devices for processors and bus.
- */
-static void __init omap2_init_processor_devices(void)
-{
-	_init_omap_device("mpu");
-	if (omap3_has_iva())
-		_init_omap_device("iva");
-
-	if (cpu_is_omap44xx()) {
-		_init_omap_device("l3_main_1");
-		_init_omap_device("dsp");
-		_init_omap_device("iva");
-	} else {
-		_init_omap_device("l3_main");
-	}
-}
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	clkdm_allow_idle(clkdm);
@@ -215,7 +178,7 @@ static int omap_pm_enter(suspend_state_t
 static int omap_pm_begin(suspend_state_t state)
 {
 	cpu_idle_poll_ctrl(true);
-	if (cpu_is_omap34xx())
+	if (soc_is_omap34xx())
 		omap_prcm_irq_prepare();
 	return 0;
 }
@@ -227,7 +190,7 @@ static void omap_pm_end(void)
 
 static void omap_pm_finish(void)
 {
-	if (cpu_is_omap34xx())
+	if (soc_is_omap34xx())
 		omap_prcm_irq_complete();
 }
 
@@ -252,7 +215,7 @@ void omap_common_suspend_init(void *pm_s
 
 static void __init omap3_init_voltages(void)
 {
-	if (!cpu_is_omap34xx())
+	if (!soc_is_omap34xx())
 		return;
 
 	omap2_set_init_voltage("mpu_iva", "dpll1_ck", "mpu");
@@ -261,7 +224,7 @@ static void __init omap3_init_voltages(v
 
 static void __init omap4_init_voltages(void)
 {
-	if (!cpu_is_omap44xx())
+	if (!soc_is_omap44xx())
 		return;
 
 	omap2_set_init_voltage("mpu", "dpll_mpu_ck", "mpu");
@@ -269,18 +232,8 @@ static void __init omap4_init_voltages(v
 	omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
 }
 
-static inline void omap_init_cpufreq(void)
-{
-	struct platform_device_info devinfo = { .name = "omap-cpufreq" };
-
-	if (!of_have_populated_dt())
-		platform_device_register_full(&devinfo);
-}
-
 static int __init omap2_common_pm_init(void)
 {
-	if (!of_have_populated_dt())
-		omap2_init_processor_devices();
 	omap_pm_if_init();
 
 	return 0;
@@ -289,13 +242,9 @@ omap_postcore_initcall(omap2_common_pm_i
 
 int __init omap2_common_pm_late_init(void)
 {
-	if (of_have_populated_dt()) {
-		omap3_twl_init();
-		omap4_twl_init();
-	}
-
 	/* Init the voltage layer */
-	omap_pmic_late_init();
+	omap3_twl_init();
+	omap4_twl_init();
 	omap_voltage_late_init();
 
 	/* Initialize the voltages */
@@ -305,8 +254,5 @@ int __init omap2_common_pm_late_init(voi
 	/* Smartreflex device init */
 	omap_devinit_smartreflex();
 
-	/* cpufreq dummy device instantiation */
-	omap_init_cpufreq();
-
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/pm-debug.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pm-debug.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/pm-debug.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/pm-debug.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,8 +114,7 @@ static int pwrdm_dbg_show_counter(struct
 		seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
 				pwrdm->ret_mem_off_counter[i]);
 
-	seq_printf(s, "\n");
-
+	seq_putc(s, '\n');
 	return 0;
 }
 
@@ -138,7 +137,7 @@ static int pwrdm_dbg_show_timer(struct p
 		seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
 			pwrdm->state_timer[i]);
 
-	seq_printf(s, "\n");
+	seq_putc(s, '\n');
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/prcm43xx.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/prcm43xx.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/prcm43xx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/prcm43xx.h	2017-02-12 16:03:20.000000000 -0500
@@ -92,6 +92,7 @@
 #define AM43XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET		0x04b8
 #define AM43XX_CM_PER_MMC0_CLKCTRL_OFFSET		0x04c0
 #define AM43XX_CM_PER_MMC1_CLKCTRL_OFFSET		0x04c8
+#define AM43XX_CM_PER_RNG_CLKCTRL_OFFSET		0x04e0
 #define AM43XX_CM_PER_SPI0_CLKCTRL_OFFSET		0x0500
 #define AM43XX_CM_PER_SPI1_CLKCTRL_OFFSET		0x0508
 #define AM43XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET		0x0528
@@ -133,6 +134,7 @@
 #define AM43XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET		0x0050
 #define AM43XX_CM_PER_SHA0_CLKCTRL_OFFSET		0x0058
 #define AM43XX_CM_PER_AES0_CLKCTRL_OFFSET		0x0028
+#define AM43XX_CM_PER_DES_CLKCTRL_OFFSET		0x0030
 #define AM43XX_CM_PER_TIMER8_CLKCTRL_OFFSET		0x0560
 #define AM43XX_CM_PER_TIMER9_CLKCTRL_OFFSET		0x0568
 #define AM43XX_CM_PER_TIMER10_CLKCTRL_OFFSET		0x0570
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/prm_common.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/prm_common.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/prm_common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/prm_common.c	2017-02-12 16:03:20.000000000 -0500
@@ -295,10 +295,8 @@ int omap_prcm_register_chain_handler(str
 		GFP_KERNEL);
 
 	if (!prcm_irq_chips || !prcm_irq_setup->saved_mask ||
-	    !prcm_irq_setup->priority_mask) {
-		pr_err("PRCM: kzalloc failed\n");
+	    !prcm_irq_setup->priority_mask)
 		goto err;
-	}
 
 	memset(mask, 0, sizeof(mask));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-hynix-h8mbx00u0mer-0em.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/*
- * SDRC register values for the Hynix H8MBX00U0MER-0EM
- *
- * Copyright (C) 2009 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_MACH_OMAP2_SDRAM_HYNIX_H8MBX00U0MER0EM
-#define __ARCH_ARM_MACH_OMAP2_SDRAM_HYNIX_H8MBX00U0MER0EM
-
-#include "sdrc.h"
-
-/* Hynix H8MBX00U0MER-0EM */
-static struct omap_sdrc_params h8mbx00u0mer0em_sdrc_params[] = {
-	[0] = {
-		.rate        = 200000000,
-		.actim_ctrla = 0xa2e1b4c6,
-		.actim_ctrlb = 0x0002131c,
-		.rfr_ctrl    = 0x0005e601,
-		.mr          = 0x00000032,
-	},
-	[1] = {
-		.rate        = 166000000,
-		.actim_ctrla = 0x629db4c6,
-		.actim_ctrlb = 0x00012214,
-		.rfr_ctrl    = 0x0004dc01,
-		.mr          = 0x00000032,
-	},
-	[2] = {
-		.rate        = 100000000,
-		.actim_ctrla = 0x51912284,
-		.actim_ctrlb = 0x0002120e,
-		.rfr_ctrl    = 0x0002d101,
-		.mr          = 0x00000022,
-	},
-	[3] = {
-		.rate        = 83000000,
-		.actim_ctrla = 0x31512283,
-		.actim_ctrlb = 0x0001220a,
-		.rfr_ctrl    = 0x00025501,
-		.mr          = 0x00000022,
-	},
-	[4] = {
-		.rate        = 0
-	},
-};
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-micron-mt46h32m32lf-6.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/*
- * SDRC register values for the Micron MT46H32M32LF-6
- *
- * Copyright (C) 2008 Texas Instruments, Inc.
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
-#define ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT46H32M32LF
-
-#include "sdrc.h"
-
-/* Micron MT46H32M32LF-6 */
-/* XXX Using ARE = 0x1 (no autorefresh burst) -- can this be changed? */
-static struct omap_sdrc_params mt46h32m32lf6_sdrc_params[] = {
-	[0] = {
-		.rate	     = 166000000,
-		.actim_ctrla = 0x9a9db4c6,
-		.actim_ctrlb = 0x00011217,
-		.rfr_ctrl    = 0x0004dc01,
-		.mr	     = 0x00000032,
-	},
-	[1] = {
-		.rate	     = 165941176,
-		.actim_ctrla = 0x9a9db4c6,
-		.actim_ctrlb = 0x00011217,
-		.rfr_ctrl    = 0x0004dc01,
-		.mr	     = 0x00000032,
-	},
-	[2] = {
-		.rate	     = 83000000,
-		.actim_ctrla = 0x51512283,
-		.actim_ctrlb = 0x0001120c,
-		.rfr_ctrl    = 0x00025501,
-		.mr	     = 0x00000032,
-	},
-	[3] = {
-		.rate	     = 82970588,
-		.actim_ctrla = 0x51512283,
-		.actim_ctrlb = 0x0001120c,
-		.rfr_ctrl    = 0x00025501,
-		.mr	     = 0x00000032,
-	},
-	[4] = {
-		.rate	     = 0
-	},
-};
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-nokia.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-nokia.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-nokia.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-nokia.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,299 +0,0 @@
-/*
- * SDRC register values for Nokia boards
- *
- * Copyright (C) 2008, 2010-2011 Nokia Corporation
- *
- * Lauri Leukkunen <lauri.leukkunen@nokia.com>
- *
- * Original code by Juha Yrjola <juha.yrjola@solidboot.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/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include "common.h"
-#include "sdram-nokia.h"
-#include "sdrc.h"
-
-/* In picoseconds, except for tREF (ns), tXP, tCKE, tWTR (clks) */
-struct sdram_timings {
-	u32 casl;
-	u32 tDAL;
-	u32 tDPL;
-	u32 tRRD;
-	u32 tRCD;
-	u32 tRP;
-	u32 tRAS;
-	u32 tRC;
-	u32 tRFC;
-	u32 tXSR;
-
-	u32 tREF; /* in ns */
-
-	u32 tXP;
-	u32 tCKE;
-	u32 tWTR;
-};
-
-static const struct sdram_timings nokia_97dot6mhz_timings[] = {
-	{
-		.casl = 3,
-		.tDAL = 30725,
-		.tDPL = 15362,
-		.tRRD = 10241,
-		.tRCD = 20483,
-		.tRP = 15362,
-		.tRAS = 40967,
-		.tRC = 56330,
-		.tRFC = 138266,
-		.tXSR = 204839,
-
-		.tREF = 7798,
-
-		.tXP = 2,
-		.tCKE = 4,
-		.tWTR = 2,
-	},
-};
-
-static const struct sdram_timings nokia_166mhz_timings[] = {
-	{
-		.casl = 3,
-		.tDAL = 33000,
-		.tDPL = 15000,
-		.tRRD = 12000,
-		.tRCD = 22500,
-		.tRP = 18000,
-		.tRAS = 42000,
-		.tRC = 66000,
-		.tRFC = 138000,
-		.tXSR = 200000,
-
-		.tREF = 7800,
-
-		.tXP = 2,
-		.tCKE = 2,
-		.tWTR = 2
-	},
-};
-
-static const struct sdram_timings nokia_195dot2mhz_timings[] = {
-	{
-		.casl = 3,
-		.tDAL = 30725,
-		.tDPL = 15362,
-		.tRRD = 10241,
-		.tRCD = 20483,
-		.tRP = 15362,
-		.tRAS = 40967,
-		.tRC = 56330,
-		.tRFC = 138266,
-		.tXSR = 204839,
-
-		.tREF = 7752,
-
-		.tXP = 2,
-		.tCKE = 4,
-		.tWTR = 2,
-	},
-};
-
-static const struct sdram_timings nokia_200mhz_timings[] = {
-	{
-		.casl = 3,
-		.tDAL = 30000,
-		.tDPL = 15000,
-		.tRRD = 10000,
-		.tRCD = 20000,
-		.tRP = 15000,
-		.tRAS = 40000,
-		.tRC = 55000,
-		.tRFC = 140000,
-		.tXSR = 200000,
-
-		.tREF = 7800,
-
-		.tXP = 2,
-		.tCKE = 4,
-		.tWTR = 2
-	},
-};
-
-static const struct {
-	long rate;
-	struct sdram_timings const *data;
-} nokia_timings[] = {
-	{ 83000000, nokia_166mhz_timings },
-	{ 97600000, nokia_97dot6mhz_timings },
-	{ 100000000, nokia_200mhz_timings },
-	{ 166000000, nokia_166mhz_timings },
-	{ 195200000, nokia_195dot2mhz_timings },
-	{ 200000000, nokia_200mhz_timings },
-};
-static struct omap_sdrc_params nokia_sdrc_params[ARRAY_SIZE(nokia_timings) + 1];
-
-static unsigned long sdrc_get_fclk_period(long rate)
-{
-	/* In picoseconds */
-	return 1000000000 / rate;
-}
-
-static unsigned int sdrc_ps_to_ticks(unsigned int time_ps, long rate)
-{
-	unsigned long tick_ps;
-
-	/* Calculate in picosecs to yield more exact results */
-	tick_ps = sdrc_get_fclk_period(rate);
-
-	return (time_ps + tick_ps - 1) / tick_ps;
-}
-#undef DEBUG
-#ifdef DEBUG
-static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-				int ticks, long rate, const char *name)
-#else
-static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit,
-			       int ticks)
-#endif
-{
-	int mask, nr_bits;
-
-	nr_bits = end_bit - st_bit + 1;
-	if (ticks >= 1 << nr_bits)
-		return -1;
-	mask = (1 << nr_bits) - 1;
-	*regval &= ~(mask << st_bit);
-	*regval |= ticks << st_bit;
-#ifdef DEBUG
-	printk(KERN_INFO "SDRC %s: %i ticks %i ns\n", name, ticks,
-			(unsigned int)sdrc_get_fclk_period(rate) * ticks /
-			1000);
-#endif
-
-	return 0;
-}
-
-#ifdef DEBUG
-#define SDRC_SET_ONE(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval((reg), (st), (end), \
-			memory_timings->field, (rate), #field) < 0) \
-		err = -1;
-#else
-#define SDRC_SET_ONE(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval((reg), (st), (end), \
-			memory_timings->field) < 0) \
-		err = -1;
-#endif
-
-#ifdef DEBUG
-static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
-				int time, long rate, const char *name)
-#else
-static int set_sdrc_timing_regval_ps(u32 *regval, int st_bit, int end_bit,
-				int time, long rate)
-#endif
-{
-	int ticks, ret;
-	ret = 0;
-
-	if (time == 0)
-		ticks = 0;
-	else
-		ticks = sdrc_ps_to_ticks(time, rate);
-
-#ifdef DEBUG
-	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks,
-				     rate, name);
-#else
-	ret = set_sdrc_timing_regval(regval, st_bit, end_bit, ticks);
-#endif
-
-	return ret;
-}
-
-#ifdef DEBUG
-#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
-			memory_timings->field, \
-			(rate), #field) < 0) \
-		err = -1;
-
-#else
-#define SDRC_SET_ONE_PS(reg, st, end, field, rate) \
-	if (set_sdrc_timing_regval_ps((reg), (st), (end), \
-			memory_timings->field, (rate)) < 0) \
-		err = -1;
-#endif
-
-static int sdrc_timings(int id, long rate,
-			const struct sdram_timings *memory_timings)
-{
-	u32 ticks_per_ms;
-	u32 rfr, l;
-	u32 actim_ctrla = 0, actim_ctrlb = 0;
-	u32 rfr_ctrl;
-	int err = 0;
-	long l3_rate = rate / 1000;
-
-	SDRC_SET_ONE_PS(&actim_ctrla,  0,  4, tDAL, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla,  6,  8, tDPL, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla,  9, 11, tRRD, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 12, 14, tRCD, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 15, 17, tRP, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 18, 21, tRAS, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 22, 26, tRC, l3_rate);
-	SDRC_SET_ONE_PS(&actim_ctrla, 27, 31, tRFC, l3_rate);
-
-	SDRC_SET_ONE_PS(&actim_ctrlb,  0,  7, tXSR, l3_rate);
-
-	SDRC_SET_ONE(&actim_ctrlb,  8, 10, tXP, l3_rate);
-	SDRC_SET_ONE(&actim_ctrlb, 12, 14, tCKE, l3_rate);
-	SDRC_SET_ONE(&actim_ctrlb, 16, 17, tWTR, l3_rate);
-
-	ticks_per_ms = l3_rate;
-	rfr = memory_timings[0].tREF * ticks_per_ms / 1000000;
-	if (rfr > 65535 + 50)
-		rfr = 65535;
-	else
-		rfr -= 50;
-
-#ifdef DEBUG
-	printk(KERN_INFO "SDRC tREF: %i ticks\n", rfr);
-#endif
-
-	l = rfr << 8;
-	rfr_ctrl = l | 0x1; /* autorefresh, reload counter with 1xARCV */
-
-	nokia_sdrc_params[id].rate = rate;
-	nokia_sdrc_params[id].actim_ctrla = actim_ctrla;
-	nokia_sdrc_params[id].actim_ctrlb = actim_ctrlb;
-	nokia_sdrc_params[id].rfr_ctrl = rfr_ctrl;
-	nokia_sdrc_params[id].mr = 0x32;
-
-	nokia_sdrc_params[id + 1].rate = 0;
-
-	return err;
-}
-
-struct omap_sdrc_params *nokia_get_sdram_timings(void)
-{
-	int err = 0;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(nokia_timings); i++) {
-		err |= sdrc_timings(i, nokia_timings[i].rate,
-				       nokia_timings[i].data);
-		if (err)
-			pr_err("%s: error with rate %ld: %d\n", __func__,
-			       nokia_timings[i].rate, err);
-	}
-
-	return err ? NULL : nokia_sdrc_params;
-}
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-nokia.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-nokia.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-nokia.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-nokia.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * SDRC register values for Nokia boards
- *
- * Copyright (C) 2010 Nokia
- *
- * This program is free software; you can 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 omap_sdrc_params *nokia_get_sdram_timings(void);
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-numonyx-m65kxxxxam.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/*
- * SDRC register values for the Numonyx M65KXXXXAM
- *
- * Copyright (C) 2009 Integration Software and Electronic Engineering.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ARCH_ARM_MACH_OMAP2_SDRAM_NUMONYX_M65KXXXXAM
-#define __ARCH_ARM_MACH_OMAP2_SDRAM_NUMONYX_M65KXXXXAM
-
-#include "sdrc.h"
-
-/* Numonyx  M65KXXXXAM */
-static struct omap_sdrc_params m65kxxxxam_sdrc_params[] = {
-	[0] = {
-		.rate		= 200000000,
-		.actim_ctrla	= 0xe321d4c6,
-		.actim_ctrlb	= 0x00022328,
-		.rfr_ctrl	= 0x0005e601,
-		.mr		= 0x00000032,
-	},
-	[1] = {
-		.rate		= 166000000,
-		.actim_ctrla	= 0xba9dc485,
-		.actim_ctrlb	= 0x00022321,
-		.rfr_ctrl	= 0x0004dc01,
-		.mr		= 0x00000032,
-	},
-	[2] = {
-		.rate		= 133000000,
-		.actim_ctrla	= 0x9a19b485,
-		.actim_ctrlb	= 0x0002231b,
-		.rfr_ctrl	= 0x0003de01,
-		.mr		= 0x00000032,
-	},
-	[3] = {
-		.rate		= 83000000,
-		.actim_ctrla	= 0x594ca242,
-		.actim_ctrlb	= 0x00022310,
-		.rfr_ctrl	= 0x00025501,
-		.mr		= 0x00000032,
-	},
-	[4] = {
-		.rate			= 0
-	},
-};
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/sdram-qimonda-hyb18m512160af-6.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/*
- * SDRC register values for the Qimonda HYB18M512160AF-6
- *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Paul Walmsley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
-#define ARCH_ARM_MACH_OMAP2_SDRAM_QIMONDA_HYB18M512160AF6
-
-#include "sdrc.h"
-
-/* Qimonda HYB18M512160AF-6 */
-static struct omap_sdrc_params hyb18m512160af6_sdrc_params[] = {
-	[0] = {
-		.rate	     = 166000000,
-		.actim_ctrla = 0x629db4c6,
-		.actim_ctrlb = 0x00012214,
-		.rfr_ctrl    = 0x0004dc01,
-		.mr	     = 0x00000032,
-	},
-	[1] = {
-		.rate	     = 165941176,
-		.actim_ctrla = 0x629db4c6,
-		.actim_ctrlb = 0x00012214,
-		.rfr_ctrl    = 0x0004dc01,
-		.mr	     = 0x00000032,
-	},
-	[2] = {
-		.rate	     = 83000000,
-		.actim_ctrla = 0x31512283,
-		.actim_ctrlb = 0x0001220a,
-		.rfr_ctrl    = 0x00025501,
-		.mr	     = 0x00000022,
-	},
-	[3] = {
-		.rate	     = 82970588,
-		.actim_ctrla = 0x31512283,
-		.actim_ctrlb = 0x0001220a,
-		.rfr_ctrl    = 0x00025501,
-		.mr	     = 0x00000022,
-	},
-	[4] = {
-		.rate	     = 0
-	},
-};
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/serial.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/serial.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/serial.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/serial.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,332 +0,0 @@
-/*
- * arch/arm/mach-omap2/serial.c
- *
- * OMAP2 serial support.
- *
- * Copyright (C) 2005-2008 Nokia Corporation
- * Author: Paul Mundt <paul.mundt@nokia.com>
- *
- * Major rework for PM support by Kevin Hilman
- *
- * Based off of arch/arm/mach-omap/omap1/serial.c
- *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/console.h>
-#include <linux/omap-dma.h>
-#include <linux/platform_data/serial-omap.h>
-
-#include "common.h"
-#include "omap_hwmod.h"
-#include "omap_device.h"
-#include "omap-pm.h"
-#include "soc.h"
-#include "prm2xxx_3xxx.h"
-#include "pm.h"
-#include "cm2xxx_3xxx.h"
-#include "prm-regbits-34xx.h"
-#include "control.h"
-#include "mux.h"
-#include "serial.h"
-
-/*
- * NOTE: By default the serial auto_suspend timeout is disabled as it causes
- * lost characters over the serial ports. This means that the UART clocks will
- * stay on until power/autosuspend_delay is set for the uart from sysfs.
- * This also causes that any deeper omap sleep states are blocked.
- */
-#define DEFAULT_AUTOSUSPEND_DELAY	-1
-
-#define MAX_UART_HWMOD_NAME_LEN		16
-
-struct omap_uart_state {
-	int num;
-
-	struct list_head node;
-	struct omap_hwmod *oh;
-	struct omap_device_pad default_omap_uart_pads[2];
-};
-
-static LIST_HEAD(uart_list);
-static u8 num_uarts;
-static u8 console_uart_id = -1;
-static u8 uart_debug;
-
-#define DEFAULT_RXDMA_POLLRATE		1	/* RX DMA polling rate (us) */
-#define DEFAULT_RXDMA_BUFSIZE		4096	/* RX DMA buffer size */
-#define DEFAULT_RXDMA_TIMEOUT		(3 * HZ)/* RX DMA timeout (jiffies) */
-
-static struct omap_uart_port_info omap_serial_default_info[] __initdata = {
-	{
-		.dma_enabled	= false,
-		.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
-		.dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
-		.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
-		.autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY,
-	},
-};
-
-#ifdef CONFIG_PM
-static void omap_uart_enable_wakeup(struct device *dev, bool enable)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct omap_device *od = to_omap_device(pdev);
-
-	if (!od)
-		return;
-
-	if (enable)
-		omap_hwmod_enable_wakeup(od->hwmods[0]);
-	else
-		omap_hwmod_disable_wakeup(od->hwmods[0]);
-}
-
-#else
-static void omap_uart_enable_wakeup(struct device *dev, bool enable)
-{}
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_OMAP_MUX
-
-#define OMAP_UART_DEFAULT_PAD_NAME_LEN	28
-static char rx_pad_name[OMAP_UART_DEFAULT_PAD_NAME_LEN],
-		tx_pad_name[OMAP_UART_DEFAULT_PAD_NAME_LEN] __initdata;
-
-static void  __init
-omap_serial_fill_uart_tx_rx_pads(struct omap_board_data *bdata,
-				struct omap_uart_state *uart)
-{
-	uart->default_omap_uart_pads[0].name = rx_pad_name;
-	uart->default_omap_uart_pads[0].flags = OMAP_DEVICE_PAD_REMUX |
-							OMAP_DEVICE_PAD_WAKEUP;
-	uart->default_omap_uart_pads[0].enable = OMAP_PIN_INPUT |
-							OMAP_MUX_MODE0;
-	uart->default_omap_uart_pads[0].idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0;
-	uart->default_omap_uart_pads[1].name = tx_pad_name;
-	uart->default_omap_uart_pads[1].enable = OMAP_PIN_OUTPUT |
-							OMAP_MUX_MODE0;
-	bdata->pads = uart->default_omap_uart_pads;
-	bdata->pads_cnt = ARRAY_SIZE(uart->default_omap_uart_pads);
-}
-
-static void  __init omap_serial_check_wakeup(struct omap_board_data *bdata,
-						struct omap_uart_state *uart)
-{
-	struct omap_mux_partition *tx_partition = NULL, *rx_partition = NULL;
-	struct omap_mux *rx_mux = NULL, *tx_mux = NULL;
-	char *rx_fmt, *tx_fmt;
-	int uart_nr = bdata->id + 1;
-
-	if (bdata->id != 2) {
-		rx_fmt = "uart%d_rx.uart%d_rx";
-		tx_fmt = "uart%d_tx.uart%d_tx";
-	} else {
-		rx_fmt = "uart%d_rx_irrx.uart%d_rx_irrx";
-		tx_fmt = "uart%d_tx_irtx.uart%d_tx_irtx";
-	}
-
-	snprintf(rx_pad_name, OMAP_UART_DEFAULT_PAD_NAME_LEN, rx_fmt,
-			uart_nr, uart_nr);
-	snprintf(tx_pad_name, OMAP_UART_DEFAULT_PAD_NAME_LEN, tx_fmt,
-			uart_nr, uart_nr);
-
-	if (omap_mux_get_by_name(rx_pad_name, &rx_partition, &rx_mux) >= 0 &&
-			omap_mux_get_by_name
-				(tx_pad_name, &tx_partition, &tx_mux) >= 0) {
-		u16 tx_mode, rx_mode;
-
-		tx_mode = omap_mux_read(tx_partition, tx_mux->reg_offset);
-		rx_mode = omap_mux_read(rx_partition, rx_mux->reg_offset);
-
-		/*
-		 * Check if uart is used in default tx/rx mode i.e. in mux mode0
-		 * if yes then configure rx pin for wake up capability
-		 */
-		if (OMAP_MODE_UART(rx_mode) && OMAP_MODE_UART(tx_mode))
-			omap_serial_fill_uart_tx_rx_pads(bdata, uart);
-	}
-}
-#else
-static void __init omap_serial_check_wakeup(struct omap_board_data *bdata,
-		struct omap_uart_state *uart)
-{
-}
-#endif
-
-static char *cmdline_find_option(char *str)
-{
-	extern char *saved_command_line;
-
-	return strstr(saved_command_line, str);
-}
-
-static int __init omap_serial_early_init(void)
-{
-	if (of_have_populated_dt())
-		return -ENODEV;
-
-	do {
-		char oh_name[MAX_UART_HWMOD_NAME_LEN];
-		struct omap_hwmod *oh;
-		struct omap_uart_state *uart;
-		char uart_name[MAX_UART_HWMOD_NAME_LEN];
-
-		snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
-			 "uart%d", num_uarts + 1);
-		oh = omap_hwmod_lookup(oh_name);
-		if (!oh)
-			break;
-
-		uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
-		if (WARN_ON(!uart))
-			return -ENODEV;
-
-		uart->oh = oh;
-		uart->num = num_uarts++;
-		list_add_tail(&uart->node, &uart_list);
-		snprintf(uart_name, MAX_UART_HWMOD_NAME_LEN,
-				"%s%d", OMAP_SERIAL_NAME, uart->num);
-
-		if (cmdline_find_option(uart_name)) {
-			console_uart_id = uart->num;
-
-			if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG) {
-				uart_debug = true;
-				pr_info("%s used as console in debug mode: uart%d clocks will not be gated",
-					uart_name, uart->num);
-			}
-		}
-	} while (1);
-
-	return 0;
-}
-omap_postcore_initcall(omap_serial_early_init);
-
-/**
- * omap_serial_init_port() - initialize single serial port
- * @bdata: port specific board data pointer
- * @info: platform specific data pointer
- *
- * This function initialies serial driver for given port only.
- * Platforms can call this function instead of omap_serial_init()
- * if they don't plan to use all available UARTs as serial ports.
- *
- * Don't mix calls to omap_serial_init_port() and omap_serial_init(),
- * use only one of the two.
- */
-void __init omap_serial_init_port(struct omap_board_data *bdata,
-			struct omap_uart_port_info *info)
-{
-	struct omap_uart_state *uart;
-	struct omap_hwmod *oh;
-	struct platform_device *pdev;
-	void *pdata = NULL;
-	u32 pdata_size = 0;
-	char *name;
-	struct omap_uart_port_info omap_up;
-
-	if (WARN_ON(!bdata))
-		return;
-	if (WARN_ON(bdata->id < 0))
-		return;
-	if (WARN_ON(bdata->id >= num_uarts))
-		return;
-
-	list_for_each_entry(uart, &uart_list, node)
-		if (bdata->id == uart->num)
-			break;
-	if (!info)
-		info = omap_serial_default_info;
-
-	oh = uart->oh;
-	name = OMAP_SERIAL_DRIVER_NAME;
-
-	omap_up.dma_enabled = info->dma_enabled;
-	omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
-	omap_up.flags = UPF_BOOT_AUTOCONF;
-	omap_up.get_context_loss_count = omap_pm_get_dev_context_loss_count;
-	omap_up.enable_wakeup = omap_uart_enable_wakeup;
-	omap_up.dma_rx_buf_size = info->dma_rx_buf_size;
-	omap_up.dma_rx_timeout = info->dma_rx_timeout;
-	omap_up.dma_rx_poll_rate = info->dma_rx_poll_rate;
-	omap_up.autosuspend_timeout = info->autosuspend_timeout;
-
-	pdata = &omap_up;
-	pdata_size = sizeof(struct omap_uart_port_info);
-
-	if (WARN_ON(!oh))
-		return;
-
-	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size);
-	if (IS_ERR(pdev)) {
-		WARN(1, "Could not build omap_device for %s: %s.\n", name,
-		     oh->name);
-		return;
-	}
-
-	oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
-
-	if (console_uart_id == bdata->id) {
-		omap_device_enable(pdev);
-		pm_runtime_set_active(&pdev->dev);
-	}
-
-	oh->dev_attr = uart;
-
-	if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
-			&& !uart_debug)
-		device_init_wakeup(&pdev->dev, true);
-}
-
-/**
- * omap_serial_board_init() - initialize all supported serial ports
- * @info: platform specific data pointer
- *
- * Initializes all available UARTs as serial ports. Platforms
- * can call this function when they want to have default behaviour
- * for serial ports (e.g initialize them all as serial ports).
- */
-void __init omap_serial_board_init(struct omap_uart_port_info *info)
-{
-	struct omap_uart_state *uart;
-	struct omap_board_data bdata;
-
-	list_for_each_entry(uart, &uart_list, node) {
-		bdata.id = uart->num;
-		bdata.flags = 0;
-		bdata.pads = NULL;
-		bdata.pads_cnt = 0;
-
-		omap_serial_check_wakeup(&bdata, uart);
-
-		if (!info)
-			omap_serial_init_port(&bdata, NULL);
-		else
-			omap_serial_init_port(&bdata, &info[uart->num]);
-	}
-}
-
-/**
- * omap_serial_init() - initialize all supported serial ports
- *
- * Initializes all available UARTs.
- * Platforms can call this function when they want to have default behaviour
- * for serial ports (e.g initialize them all as serial ports).
- */
-void __init omap_serial_init(void)
-{
-	omap_serial_board_init(NULL);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/timer.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/timer.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -369,9 +369,9 @@ static bool use_gptimer_clksrc __initdat
 /*
  * clocksource
  */
-static cycle_t clocksource_read_cycles(struct clocksource *cs)
+static u64 clocksource_read_cycles(struct clocksource *cs)
 {
-	return (cycle_t)__omap_dm_timer_read_counter(&clksrc,
+	return (u64)__omap_dm_timer_read_counter(&clksrc,
 						     OMAP_TIMER_NONPOSTED);
 }
 
@@ -510,18 +510,19 @@ void __init omap3_secure_sync32k_timer_i
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
+	defined(CONFIG_SOC_AM43XX)
 void __init omap3_gptimer_timer_init(void)
 {
 	__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
 			1, "timer_sys_ck", "ti,timer-alwon", true);
-
-	clocksource_probe();
+	if (of_have_populated_dt())
+		clocksource_probe();
 }
 #endif
 
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) ||		\
-	defined(CONFIG_SOC_DRA7XX) || defined(CONFIG_SOC_AM43XX)
+	defined(CONFIG_SOC_DRA7XX)
 static void __init omap4_sync32k_timer_init(void)
 {
 	__omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/twl-common.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/twl-common.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/twl-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/twl-common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,564 +0,0 @@
-/*
- * twl-common.c
- *
- * Copyright (C) 2011 Texas Instruments, Inc..
- * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/i2c.h>
-#include <linux/i2c/twl.h>
-#include <linux/gpio.h>
-#include <linux/string.h>
-#include <linux/phy/phy.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-
-#include "soc.h"
-#include "twl-common.h"
-#include "pm.h"
-#include "voltage.h"
-#include "mux.h"
-
-static struct i2c_board_info __initdata pmic_i2c_board_info = {
-	.addr		= 0x48,
-	.flags		= I2C_CLIENT_WAKE,
-};
-
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static int twl_set_voltage(void *data, int target_uV)
-{
-	struct voltagedomain *voltdm = (struct voltagedomain *)data;
-	return voltdm_scale(voltdm, target_uV);
-}
-
-static int twl_get_voltage(void *data)
-{
-	struct voltagedomain *voltdm = (struct voltagedomain *)data;
-	return voltdm_get_voltage(voltdm);
-}
-#endif
-
-void __init omap_pmic_init(int bus, u32 clkrate,
-			   const char *pmic_type, int pmic_irq,
-			   struct twl4030_platform_data *pmic_data)
-{
-	omap_mux_init_signal("sys_nirq", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
-	strlcpy(pmic_i2c_board_info.type, pmic_type,
-		sizeof(pmic_i2c_board_info.type));
-	pmic_i2c_board_info.irq = pmic_irq;
-	pmic_i2c_board_info.platform_data = pmic_data;
-
-	omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
-}
-
-#ifdef CONFIG_ARCH_OMAP4
-void __init omap4_pmic_init(const char *pmic_type,
-		    struct twl4030_platform_data *pmic_data,
-		    struct i2c_board_info *devices, int nr_devices)
-{
-	/* PMIC part*/
-	unsigned int irq;
-
-	omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
-	omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT);
-	irq = omap4_xlate_irq(7 + OMAP44XX_IRQ_GIC_START);
-	omap_pmic_init(1, 400, pmic_type, irq, pmic_data);
-
-	/* Register additional devices on i2c1 bus if needed */
-	if (devices)
-		i2c_register_board_info(1, devices, nr_devices);
-}
-#endif
-
-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,
-};
-
-static int omap3_batt_table[] = {
-/* 0 C */
-30800, 29500, 28300, 27100,
-26000, 24900, 23900, 22900, 22000, 21100, 20300, 19400, 18700, 17900,
-17200, 16500, 15900, 15300, 14700, 14100, 13600, 13100, 12600, 12100,
-11600, 11200, 10800, 10400, 10000, 9630,  9280,  8950,  8620,  8310,
-8020,  7730,  7460,  7200,  6950,  6710,  6470,  6250,  6040,  5830,
-5640,  5450,  5260,  5090,  4920,  4760,  4600,  4450,  4310,  4170,
-4040,  3910,  3790,  3670,  3550
-};
-
-static struct twl4030_bci_platform_data omap3_bci_pdata = {
-	.battery_tmp_tbl	= omap3_batt_table,
-	.tblsize		= ARRAY_SIZE(omap3_batt_table),
-};
-
-static struct twl4030_madc_platform_data omap3_madc_pdata = {
-	.irq_line	= 1,
-};
-
-static struct twl4030_codec_data omap3_codec;
-
-static struct twl4030_audio_data omap3_audio_pdata = {
-	.audio_mclk = 26000000,
-	.codec = &omap3_codec,
-};
-
-static struct regulator_consumer_supply omap3_vdda_dac_supplies[] = {
-	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
-};
-
-static struct regulator_init_data omap3_vdac_idata = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap3_vdda_dac_supplies),
-	.consumer_supplies	= omap3_vdda_dac_supplies,
-};
-
-static struct regulator_consumer_supply omap3_vpll2_supplies[] = {
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dpi.0"),
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi.0"),
-};
-
-static struct regulator_init_data omap3_vpll2_idata = {
-	.constraints = {
-		.min_uV                 = 1800000,
-		.max_uV                 = 1800000,
-		.valid_modes_mask       = REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask         = REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(omap3_vpll2_supplies),
-	.consumer_supplies		= omap3_vpll2_supplies,
-};
-
-static struct regulator_consumer_supply omap3_vdd1_supply[] = {
-	REGULATOR_SUPPLY("vcc", "cpu0"),
-};
-
-static struct regulator_consumer_supply omap3_vdd2_supply[] = {
-	REGULATOR_SUPPLY("vcc", "l3_main.0"),
-};
-
-static struct regulator_init_data omap3_vdd1 = {
-	.constraints = {
-		.name			= "vdd_mpu_iva",
-		.min_uV			= 600000,
-		.max_uV			= 1450000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(omap3_vdd1_supply),
-	.consumer_supplies		= omap3_vdd1_supply,
-};
-
-static struct regulator_init_data omap3_vdd2 = {
-	.constraints = {
-		.name			= "vdd_core",
-		.min_uV			= 600000,
-		.max_uV			= 1450000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(omap3_vdd2_supply),
-	.consumer_supplies		= omap3_vdd2_supply,
-};
-
-static struct twl_regulator_driver_data omap3_vdd1_drvdata = {
-	.get_voltage = twl_get_voltage,
-	.set_voltage = twl_set_voltage,
-};
-
-static struct twl_regulator_driver_data omap3_vdd2_drvdata = {
-	.get_voltage = twl_get_voltage,
-	.set_voltage = twl_set_voltage,
-};
-
-void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
-				  u32 pdata_flags, u32 regulators_flags)
-{
-	if (!pmic_data->vdd1) {
-		omap3_vdd1.driver_data = &omap3_vdd1_drvdata;
-		omap3_vdd1_drvdata.data = voltdm_lookup("mpu_iva");
-		pmic_data->vdd1 = &omap3_vdd1;
-	}
-	if (!pmic_data->vdd2) {
-		omap3_vdd2.driver_data = &omap3_vdd2_drvdata;
-		omap3_vdd2_drvdata.data = voltdm_lookup("core");
-		pmic_data->vdd2 = &omap3_vdd2;
-	}
-
-	/* Common platform data configurations */
-	if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
-		pmic_data->usb = &omap3_usb_pdata;
-
-	if (pdata_flags & TWL_COMMON_PDATA_BCI && !pmic_data->bci)
-		pmic_data->bci = &omap3_bci_pdata;
-
-	if (pdata_flags & TWL_COMMON_PDATA_MADC && !pmic_data->madc)
-		pmic_data->madc = &omap3_madc_pdata;
-
-	if (pdata_flags & TWL_COMMON_PDATA_AUDIO && !pmic_data->audio)
-		pmic_data->audio = &omap3_audio_pdata;
-
-	/* Common regulator configurations */
-	if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
-		pmic_data->vdac = &omap3_vdac_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VPLL2 && !pmic_data->vpll2)
-		pmic_data->vpll2 = &omap3_vpll2_idata;
-}
-#endif /* CONFIG_ARCH_OMAP3 */
-
-#if defined(CONFIG_ARCH_OMAP4)
-static struct twl4030_usb_data omap4_usb_pdata = {
-};
-
-static struct regulator_consumer_supply omap4_vdda_hdmi_dac_supplies[] = {
-	REGULATOR_SUPPLY("vdda_hdmi_dac", "omapdss_hdmi"),
-};
-
-static struct regulator_init_data omap4_vdac_idata = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap4_vdda_hdmi_dac_supplies),
-	.consumer_supplies	= omap4_vdda_hdmi_dac_supplies,
-	.supply_regulator	= "V2V1",
-};
-
-static struct regulator_init_data omap4_vaux2_idata = {
-	.constraints = {
-		.min_uV			= 1200000,
-		.max_uV			= 2800000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_vaux3_idata = {
-	.constraints = {
-		.min_uV			= 1000000,
-		.max_uV			= 3000000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_consumer_supply omap4_vmmc_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
-};
-
-/* VMMC1 for MMC1 card */
-static struct regulator_init_data omap4_vmmc_idata = {
-	.constraints = {
-		.min_uV			= 1200000,
-		.max_uV			= 3000000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies  = ARRAY_SIZE(omap4_vmmc_supply),
-	.consumer_supplies      = omap4_vmmc_supply,
-};
-
-static struct regulator_init_data omap4_vpp_idata = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 2500000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_vana_idata = {
-	.constraints = {
-		.min_uV			= 2100000,
-		.max_uV			= 2100000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-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,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| 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,
-	.supply_regulator	= "V2V1",
-};
-
-static struct regulator_init_data omap4_vusb_idata = {
-	.constraints = {
-		.min_uV			= 3300000,
-		.max_uV			= 3300000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_init_data omap4_clk32kg_idata = {
-	.constraints = {
-		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
-	},
-};
-
-static struct regulator_consumer_supply omap4_vdd1_supply[] = {
-	REGULATOR_SUPPLY("vcc", "cpu0"),
-};
-
-static struct regulator_consumer_supply omap4_vdd2_supply[] = {
-	REGULATOR_SUPPLY("vcc", "iva.0"),
-};
-
-static struct regulator_consumer_supply omap4_vdd3_supply[] = {
-	REGULATOR_SUPPLY("vcc", "l3_main.0"),
-};
-
-static struct regulator_init_data omap4_vdd1 = {
-	.constraints = {
-		.name			= "vdd_mpu",
-		.min_uV			= 500000,
-		.max_uV			= 1500000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(omap4_vdd1_supply),
-	.consumer_supplies		= omap4_vdd1_supply,
-};
-
-static struct regulator_init_data omap4_vdd2 = {
-	.constraints = {
-		.name			= "vdd_iva",
-		.min_uV			= 500000,
-		.max_uV			= 1500000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(omap4_vdd2_supply),
-	.consumer_supplies		= omap4_vdd2_supply,
-};
-
-static struct regulator_init_data omap4_vdd3 = {
-	.constraints = {
-		.name			= "vdd_core",
-		.min_uV			= 500000,
-		.max_uV			= 1500000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL,
-		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE,
-	},
-	.num_consumer_supplies		= ARRAY_SIZE(omap4_vdd3_supply),
-	.consumer_supplies		= omap4_vdd3_supply,
-};
-
-
-static struct twl_regulator_driver_data omap4_vdd1_drvdata = {
-	.get_voltage = twl_get_voltage,
-	.set_voltage = twl_set_voltage,
-};
-
-static struct twl_regulator_driver_data omap4_vdd2_drvdata = {
-	.get_voltage = twl_get_voltage,
-	.set_voltage = twl_set_voltage,
-};
-
-static struct twl_regulator_driver_data omap4_vdd3_drvdata = {
-	.get_voltage = twl_get_voltage,
-	.set_voltage = twl_set_voltage,
-};
-
-static struct regulator_consumer_supply omap4_v1v8_supply[] = {
-	REGULATOR_SUPPLY("vio", "1-004b"),
-};
-
-static struct regulator_init_data omap4_v1v8_idata = {
-	.constraints = {
-		.min_uV			= 1800000,
-		.max_uV			= 1800000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-		.always_on		= true,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap4_v1v8_supply),
-	.consumer_supplies	= omap4_v1v8_supply,
-};
-
-static struct regulator_consumer_supply omap4_v2v1_supply[] = {
-	REGULATOR_SUPPLY("v2v1", "1-004b"),
-};
-
-static struct regulator_init_data omap4_v2v1_idata = {
-	.constraints = {
-		.min_uV			= 2100000,
-		.max_uV			= 2100000,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask		= REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(omap4_v2v1_supply),
-	.consumer_supplies	= omap4_v2v1_supply,
-};
-
-void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
-				  u32 pdata_flags, u32 regulators_flags)
-{
-	if (!pmic_data->vdd1) {
-		omap4_vdd1.driver_data = &omap4_vdd1_drvdata;
-		omap4_vdd1_drvdata.data = voltdm_lookup("mpu");
-		pmic_data->vdd1 = &omap4_vdd1;
-	}
-
-	if (!pmic_data->vdd2) {
-		omap4_vdd2.driver_data = &omap4_vdd2_drvdata;
-		omap4_vdd2_drvdata.data = voltdm_lookup("iva");
-		pmic_data->vdd2 = &omap4_vdd2;
-	}
-
-	if (!pmic_data->vdd3) {
-		omap4_vdd3.driver_data = &omap4_vdd3_drvdata;
-		omap4_vdd3_drvdata.data = voltdm_lookup("core");
-		pmic_data->vdd3 = &omap4_vdd3;
-	}
-
-	/* Common platform data configurations */
-	if (pdata_flags & TWL_COMMON_PDATA_USB && !pmic_data->usb)
-		pmic_data->usb = &omap4_usb_pdata;
-
-	/* Common regulator configurations */
-	if (regulators_flags & TWL_COMMON_REGULATOR_VDAC && !pmic_data->vdac)
-		pmic_data->vdac = &omap4_vdac_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VAUX2 && !pmic_data->vaux2)
-		pmic_data->vaux2 = &omap4_vaux2_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VAUX3 && !pmic_data->vaux3)
-		pmic_data->vaux3 = &omap4_vaux3_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VMMC && !pmic_data->vmmc)
-		pmic_data->vmmc = &omap4_vmmc_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VPP && !pmic_data->vpp)
-		pmic_data->vpp = &omap4_vpp_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VANA && !pmic_data->vana)
-		pmic_data->vana = &omap4_vana_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VCXIO && !pmic_data->vcxio)
-		pmic_data->vcxio = &omap4_vcxio_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_VUSB && !pmic_data->vusb)
-		pmic_data->vusb = &omap4_vusb_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_CLK32KG &&
-	    !pmic_data->clk32kg)
-		pmic_data->clk32kg = &omap4_clk32kg_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_V1V8 && !pmic_data->v1v8)
-		pmic_data->v1v8 = &omap4_v1v8_idata;
-
-	if (regulators_flags & TWL_COMMON_REGULATOR_V2V1 && !pmic_data->v2v1)
-		pmic_data->v2v1 = &omap4_v2v1_idata;
-}
-#endif /* CONFIG_ARCH_OMAP4 */
-
-#if IS_ENABLED(CONFIG_SND_OMAP_SOC_OMAP_TWL4030)
-#include <linux/platform_data/omap-twl4030.h>
-
-/* Commonly used configuration */
-static struct omap_tw4030_pdata omap_twl4030_audio_data;
-
-static struct platform_device audio_device = {
-	.name		= "omap-twl4030",
-	.id		= -1,
-};
-
-void omap_twl4030_audio_init(char *card_name,
-				    struct omap_tw4030_pdata *pdata)
-{
-	if (!pdata)
-		pdata = &omap_twl4030_audio_data;
-
-	pdata->card_name = card_name;
-
-	audio_device.dev.platform_data = pdata;
-	platform_device_register(&audio_device);
-}
-
-#else /* SOC_OMAP_TWL4030 */
-void omap_twl4030_audio_init(char *card_name,
-				    struct omap_tw4030_pdata *pdata)
-{
-	return;
-}
-#endif /* SOC_OMAP_TWL4030 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/twl-common.h linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/twl-common.h
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/twl-common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/twl-common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-#ifndef __OMAP_PMIC_COMMON__
-#define __OMAP_PMIC_COMMON__
-
-#include "common.h"
-
-#define TWL_COMMON_PDATA_USB		(1 << 0)
-#define TWL_COMMON_PDATA_BCI		(1 << 1)
-#define TWL_COMMON_PDATA_MADC		(1 << 2)
-#define TWL_COMMON_PDATA_AUDIO		(1 << 3)
-
-/* Common LDO regulators for TWL4030/TWL6030 */
-#define TWL_COMMON_REGULATOR_VDAC	(1 << 0)
-#define TWL_COMMON_REGULATOR_VAUX1	(1 << 1)
-#define TWL_COMMON_REGULATOR_VAUX2	(1 << 2)
-#define TWL_COMMON_REGULATOR_VAUX3	(1 << 3)
-
-/* TWL6030 LDO regulators */
-#define TWL_COMMON_REGULATOR_VMMC	(1 << 4)
-#define TWL_COMMON_REGULATOR_VPP	(1 << 5)
-#define TWL_COMMON_REGULATOR_VUSIM	(1 << 6)
-#define TWL_COMMON_REGULATOR_VANA	(1 << 7)
-#define TWL_COMMON_REGULATOR_VCXIO	(1 << 8)
-#define TWL_COMMON_REGULATOR_VUSB	(1 << 9)
-#define TWL_COMMON_REGULATOR_CLK32KG	(1 << 10)
-#define TWL_COMMON_REGULATOR_V1V8	(1 << 11)
-#define TWL_COMMON_REGULATOR_V2V1	(1 << 12)
-
-/* TWL4030 LDO regulators */
-#define TWL_COMMON_REGULATOR_VPLL1	(1 << 4)
-#define TWL_COMMON_REGULATOR_VPLL2	(1 << 5)
-
-
-struct twl4030_platform_data;
-struct twl6040_platform_data;
-struct omap_tw4030_pdata;
-struct i2c_board_info;
-
-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)
-{
-	omap_pmic_init(2, 2600, pmic_type, 7 + OMAP_INTC_START, pmic_data);
-}
-
-static inline void omap3_pmic_init(const char *pmic_type,
-				   struct twl4030_platform_data *pmic_data)
-{
-	omap_pmic_init(1, 2600, pmic_type, 7 + OMAP_INTC_START, pmic_data);
-}
-
-void omap4_pmic_init(const char *pmic_type,
-		    struct twl4030_platform_data *pmic_data,
-		    struct i2c_board_info *devices, int nr_devices);
-
-void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
-			   u32 pdata_flags, u32 regulators_flags);
-
-void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
-			   u32 pdata_flags, u32 regulators_flags);
-
-void omap_twl4030_audio_init(char *card_name, struct omap_tw4030_pdata *pdata);
-
-#endif /* __OMAP_PMIC_COMMON__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/usb-host.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/usb-host.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/usb-host.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/usb-host.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,496 +0,0 @@
-/*
- * usb-host.c - OMAP USB Host
- *
- * This file will contain the board specific details for the
- * Synopsys EHCI/OHCI host controller on OMAP3430 and onwards
- *
- * Copyright (C) 2007-2011 Texas Instruments
- * Author: Vikram Pandita <vikram.pandita@ti.com>
- * Author: Keshava Munegowda <keshava_mgowda@ti.com>
- *
- * Generalization by:
- * Felipe Balbi <balbi@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/string.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/usb/phy.h>
-#include <linux/usb/usb_phy_generic.h>
-
-#include "soc.h"
-#include "omap_device.h"
-#include "mux.h"
-#include "usb.h"
-
-#ifdef CONFIG_MFD_OMAP_USB_HOST
-
-#define OMAP_USBHS_DEVICE	"usbhs_omap"
-#define OMAP_USBTLL_DEVICE	"usbhs_tll"
-#define	USBHS_UHH_HWMODNAME	"usb_host_hs"
-#define USBHS_TLL_HWMODNAME	"usb_tll_hs"
-
-/* MUX settings for EHCI pins */
-/*
- * setup_ehci_io_mux - initialize IO pad mux for USBHOST
- */
-static void __init setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case OMAP_EHCI_PORT_MODE_PHY:
-		omap_mux_init_signal("hsusb1_stp", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb1_clk", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb1_dir", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_nxt", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data0", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data1", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data2", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data3", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data4", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data5", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data6", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data7", OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_EHCI_PORT_MODE_TLL:
-		omap_mux_init_signal("hsusb1_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb1_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_USBHS_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	switch (port_mode[1]) {
-	case OMAP_EHCI_PORT_MODE_PHY:
-		omap_mux_init_signal("hsusb2_stp", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb2_clk", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb2_dir", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_nxt", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_EHCI_PORT_MODE_TLL:
-		omap_mux_init_signal("hsusb2_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb2_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_USBHS_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	switch (port_mode[2]) {
-	case OMAP_EHCI_PORT_MODE_PHY:
-		printk(KERN_WARNING "Port3 can't be used in PHY mode\n");
-		break;
-	case OMAP_EHCI_PORT_MODE_TLL:
-		omap_mux_init_signal("hsusb3_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb3_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_USBHS_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	return;
-}
-
-static void __init setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm1_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm1_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm1_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm1_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm1_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm1_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_USBHS_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-	switch (port_mode[1]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm2_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm2_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm2_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm2_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm2_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm2_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_USBHS_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-	switch (port_mode[2]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm3_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm3_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm3_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm3_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm3_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm3_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_USBHS_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-}
-
-void __init usbhs_init(struct usbhs_omap_platform_data *pdata)
-{
-	struct omap_hwmod	*uhh_hwm, *tll_hwm;
-	struct platform_device	*pdev;
-	int			bus_id = -1;
-
-	if (cpu_is_omap34xx()) {
-		setup_ehci_io_mux(pdata->port_mode);
-		setup_ohci_io_mux(pdata->port_mode);
-
-		if (omap_rev() <= OMAP3430_REV_ES2_1)
-			pdata->single_ulpi_bypass = true;
-
-	}
-
-	uhh_hwm = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
-	if (!uhh_hwm) {
-		pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
-		return;
-	}
-
-	tll_hwm = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
-	if (!tll_hwm) {
-		pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
-		return;
-	}
-
-	pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm,
-				pdata, sizeof(*pdata));
-	if (IS_ERR(pdev)) {
-		pr_err("Could not build hwmod device %s\n",
-		       USBHS_TLL_HWMODNAME);
-		return;
-	}
-
-	pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm,
-				pdata, sizeof(*pdata));
-	if (IS_ERR(pdev)) {
-		pr_err("Could not build hwmod devices %s\n",
-		       USBHS_UHH_HWMODNAME);
-		return;
-	}
-}
-
-#else
-
-void __init usbhs_init(struct usbhs_omap_platform_data *pdata)
-{
-}
-
-#endif
-
-/* Template for PHY regulators */
-static struct fixed_voltage_config hsusb_reg_config = {
-	/* .supply_name filled later */
-	.microvolts = 3300000,
-	.gpio = -1,		/* updated later */
-	.startup_delay = 70000, /* 70msec */
-	.enable_high = 1,	/* updated later */
-	.enabled_at_boot = 0,	/* keep in RESET */
-	/* .init_data filled later */
-};
-
-static const char *nop_name = "usb_phy_generic"; /* NOP PHY driver */
-static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */
-
-/**
- * usbhs_add_regulator - Add a gpio based fixed voltage regulator device
- * @name: name for the regulator
- * @dev_id: device id of the device this regulator supplies power to
- * @dev_supply: supply name that the device expects
- * @gpio: GPIO number
- * @polarity: 1 - Active high, 0 - Active low
- */
-static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply,
-						int gpio, int polarity)
-{
-	struct regulator_consumer_supply *supplies;
-	struct regulator_init_data *reg_data;
-	struct fixed_voltage_config *config;
-	struct platform_device *pdev;
-	struct platform_device_info pdevinfo;
-	int ret = -ENOMEM;
-
-	supplies = kzalloc(sizeof(*supplies), GFP_KERNEL);
-	if (!supplies)
-		return -ENOMEM;
-
-	supplies->supply = dev_supply;
-	supplies->dev_name = dev_id;
-
-	reg_data = kzalloc(sizeof(*reg_data), GFP_KERNEL);
-	if (!reg_data)
-		goto err_data;
-
-	reg_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
-	reg_data->consumer_supplies = supplies;
-	reg_data->num_consumer_supplies = 1;
-
-	config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config),
-			GFP_KERNEL);
-	if (!config)
-		goto err_config;
-
-	config->supply_name = kstrdup(name, GFP_KERNEL);
-	if (!config->supply_name)
-		goto err_supplyname;
-
-	config->gpio = gpio;
-	config->enable_high = polarity;
-	config->init_data = reg_data;
-
-	/* create a regulator device */
-	memset(&pdevinfo, 0, sizeof(pdevinfo));
-	pdevinfo.name = reg_name;
-	pdevinfo.id = PLATFORM_DEVID_AUTO;
-	pdevinfo.data = config;
-	pdevinfo.size_data = sizeof(*config);
-
-	pdev = platform_device_register_full(&pdevinfo);
-	if (IS_ERR(pdev)) {
-		ret = PTR_ERR(pdev);
-		pr_err("%s: Failed registering regulator %s for %s : %d\n",
-				__func__, name, dev_id, ret);
-		goto err_register;
-	}
-
-	return 0;
-
-err_register:
-	kfree(config->supply_name);
-err_supplyname:
-	kfree(config);
-err_config:
-	kfree(reg_data);
-err_data:
-	kfree(supplies);
-	return ret;
-}
-
-#define MAX_STR 20
-
-int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
-{
-	char rail_name[MAX_STR];
-	int i;
-	struct platform_device *pdev;
-	char *phy_id;
-	struct platform_device_info pdevinfo;
-	struct usb_phy_generic_platform_data nop_pdata;
-
-	for (i = 0; i < num_phys; i++) {
-
-		if (!phy->port) {
-			pr_err("%s: Invalid port 0. Must start from 1\n",
-						__func__);
-			continue;
-		}
-
-		/* do we need a NOP PHY device ? */
-		if (!gpio_is_valid(phy->reset_gpio) &&
-			!gpio_is_valid(phy->vcc_gpio))
-			continue;
-
-		phy_id = kmalloc(MAX_STR, GFP_KERNEL);
-		if (!phy_id) {
-			pr_err("%s: kmalloc() failed\n", __func__);
-			return -ENOMEM;
-		}
-
-		/* set platform data */
-		memset(&nop_pdata, 0, sizeof(nop_pdata));
-		if (gpio_is_valid(phy->vcc_gpio))
-			nop_pdata.needs_vcc = true;
-		nop_pdata.gpio_reset = phy->reset_gpio;
-		nop_pdata.type = USB_PHY_TYPE_USB2;
-
-		/* create a NOP PHY device */
-		memset(&pdevinfo, 0, sizeof(pdevinfo));
-		pdevinfo.name = nop_name;
-		pdevinfo.id = phy->port;
-		pdevinfo.data = &nop_pdata;
-		pdevinfo.size_data =
-			sizeof(struct usb_phy_generic_platform_data);
-		scnprintf(phy_id, MAX_STR, "usb_phy_generic.%d",
-					phy->port);
-		pdev = platform_device_register_full(&pdevinfo);
-		if (IS_ERR(pdev)) {
-			pr_err("%s: Failed to register device %s : %ld\n",
-				__func__,  phy_id, PTR_ERR(pdev));
-			kfree(phy_id);
-			continue;
-		}
-
-		usb_bind_phy("ehci-omap.0", phy->port - 1, phy_id);
-
-		/* Do we need VCC regulator ? */
-		if (gpio_is_valid(phy->vcc_gpio)) {
-			scnprintf(rail_name, MAX_STR, "hsusb%d_vcc", phy->port);
-			usbhs_add_regulator(rail_name, phy_id, "vcc",
-					phy->vcc_gpio, phy->vcc_polarity);
-		}
-
-		phy++;
-	}
-
-	return 0;
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/usb-musb.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/usb-musb.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/usb-musb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/usb-musb.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,106 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/usb-musb.c
- *
- * This file will contain the board specific details for the
- * MENTOR USB OTG controller on OMAP3430
- *
- * Copyright (C) 2007-2008 Texas Instruments
- * Copyright (C) 2008 Nokia Corporation
- * Author: Vikram Pandita
- *
- * Generalization by:
- * Felipe Balbi <felipe.balbi@nokia.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/io.h>
-#include <linux/usb/musb.h>
-
-#include "omap_device.h"
-#include "soc.h"
-#include "mux.h"
-#include "usb.h"
-
-static struct musb_hdrc_config musb_config = {
-	.multipoint	= 1,
-	.dyn_fifo	= 1,
-	.num_eps	= 16,
-	.ram_bits	= 12,
-};
-
-static struct musb_hdrc_platform_data musb_plat = {
-	.mode		= MUSB_OTG,
-
-	/* .clock is set dynamically */
-	.config		= &musb_config,
-
-	/* REVISIT charge pump on TWL4030 can supply up to
-	 * 100 mA ... but this value is board-specific, like
-	 * "mode", and should be passed to usb_musb_init().
-	 */
-	.power		= 50,			/* up to 100 mA */
-};
-
-static u64 musb_dmamask = DMA_BIT_MASK(32);
-
-static struct omap_musb_board_data musb_default_board_data = {
-	.interface_type		= MUSB_INTERFACE_ULPI,
-	.mode			= MUSB_OTG,
-	.power			= 100,
-};
-
-void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
-{
-	struct omap_hwmod		*oh;
-	struct platform_device		*pdev;
-	struct device			*dev;
-	int				bus_id = -1;
-	const char			*oh_name, *name;
-	struct omap_musb_board_data	*board_data;
-
-	if (musb_board_data)
-		board_data = musb_board_data;
-	else
-		board_data = &musb_default_board_data;
-
-	/*
-	 * REVISIT: This line can be removed once all the platforms using
-	 * musb_core.c have been converted to use use clkdev.
-	 */
-	musb_plat.clock = "ick";
-	musb_plat.board_data = board_data;
-	musb_plat.power = board_data->power >> 1;
-	musb_plat.mode = board_data->mode;
-	musb_plat.extvbus = board_data->extvbus;
-
-	oh_name = "usb_otg_hs";
-	name = "musb-omap2430";
-
-        oh = omap_hwmod_lookup(oh_name);
-        if (WARN(!oh, "%s: could not find omap_hwmod for %s\n",
-                 __func__, oh_name))
-                return;
-
-	pdev = omap_device_build(name, bus_id, oh, &musb_plat,
-				 sizeof(musb_plat));
-	if (IS_ERR(pdev)) {
-		pr_err("Could not build omap_device for %s %s\n",
-						name, oh_name);
-		return;
-	}
-
-	dev = &pdev->dev;
-	get_device(dev);
-	dev->dma_mask = &musb_dmamask;
-	dev->coherent_dma_mask = musb_dmamask;
-	put_device(dev);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-omap2/usb-tusb6010.c linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/usb-tusb6010.c
--- linux-libre-4.9-gnu/arch/arm/mach-omap2/usb-tusb6010.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-omap2/usb-tusb6010.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,8 +22,6 @@
 
 #include "gpmc.h"
 
-#include "mux.h"
-
 static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
@@ -226,25 +224,6 @@ tusb6010_setup_interface(struct musb_hdr
 	}
 	tusb_device.dev.platform_data = data;
 
-	/* REVISIT let the driver know what DMA channels work */
-	if (!dmachan)
-		tusb_device.dev.dma_mask = NULL;
-	else {
-		/* assume OMAP 2420 ES2.0 and later */
-		if (dmachan & (1 << 0))
-			omap_mux_init_signal("sys_ndmareq0", 0);
-		if (dmachan & (1 << 1))
-			omap_mux_init_signal("sys_ndmareq1", 0);
-		if (dmachan & (1 << 2))
-			omap_mux_init_signal("sys_ndmareq2", 0);
-		if (dmachan & (1 << 3))
-			omap_mux_init_signal("sys_ndmareq3", 0);
-		if (dmachan & (1 << 4))
-			omap_mux_init_signal("sys_ndmareq4", 0);
-		if (dmachan & (1 << 5))
-			omap_mux_init_signal("sys_ndmareq5", 0);
-	}
-
 	/* so far so good ... register the device */
 	status = platform_device_register(&tusb_device);
 	if (status < 0) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-orion5x/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mach-orion5x/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mach-orion5x/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-orion5x/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -84,13 +84,6 @@ config MACH_LINKSTATION_PRO
 	  Buffalo Linkstation Pro/Live platform. Both v1 and
 	  v2 devices are supported.
 
-config MACH_LINKSTATION_LSCHL
-	bool "Buffalo Linkstation Live v3 (LS-CHL)"
-	select I2C_BOARDINFO if I2C
-	help
-	  Say 'Y' here if you want your kernel to support the
-	  Buffalo Linkstation Live v3 (LS-CHL) platform.
-
 config MACH_LINKSTATION_MINI
 	bool "Buffalo Linkstation Mini (Flattened Device Tree)"
 	select ARCH_ORION5X_DT
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-orion5x/ls-chl-setup.c linux-libre-4.10-rc8-gnu/arch/arm/mach-orion5x/ls-chl-setup.c
--- linux-libre-4.9-gnu/arch/arm/mach-orion5x/ls-chl-setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-orion5x/ls-chl-setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,331 +0,0 @@
-/*
- * arch/arm/mach-orion5x/ls-chl-setup.c
- *
- * Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/physmap.h>
-#include <linux/mv643xx_eth.h>
-#include <linux/leds.h>
-#include <linux/gpio_keys.h>
-#include <linux/gpio-fan.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-#include <linux/ata_platform.h>
-#include <linux/gpio.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include "common.h"
-#include "mpp.h"
-#include "orion5x.h"
-
-/*****************************************************************************
- * Linkstation LS-CHL Info
- ****************************************************************************/
-
-/*
- * 256K NOR flash Device bus boot chip select
- */
-
-#define LSCHL_NOR_BOOT_BASE	0xf4000000
-#define LSCHL_NOR_BOOT_SIZE	SZ_256K
-
-/*****************************************************************************
- * 256KB NOR Flash on BOOT Device
- ****************************************************************************/
-
-static struct physmap_flash_data lschl_nor_flash_data = {
-	.width = 1,
-};
-
-static struct resource lschl_nor_flash_resource = {
-	.flags	= IORESOURCE_MEM,
-	.start	= LSCHL_NOR_BOOT_BASE,
-	.end	= LSCHL_NOR_BOOT_BASE + LSCHL_NOR_BOOT_SIZE - 1,
-};
-
-static struct platform_device lschl_nor_flash = {
-	.name = "physmap-flash",
-	.id = 0,
-	.dev = {
-		.platform_data	= &lschl_nor_flash_data,
-	},
-	.num_resources = 1,
-	.resource = &lschl_nor_flash_resource,
-};
-
-/*****************************************************************************
- * Ethernet
- ****************************************************************************/
-
-static struct mv643xx_eth_platform_data lschl_eth_data = {
-	.phy_addr = MV643XX_ETH_PHY_ADDR(8),
-};
-
-/*****************************************************************************
- * RTC 5C372a on I2C bus
- ****************************************************************************/
-
-static struct i2c_board_info __initdata lschl_i2c_rtc = {
-	I2C_BOARD_INFO("rs5c372a", 0x32),
-};
-
-/*****************************************************************************
- * LEDs attached to GPIO
- ****************************************************************************/
-
-#define LSCHL_GPIO_LED_ALARM	2
-#define LSCHL_GPIO_LED_INFO	3
-#define LSCHL_GPIO_LED_FUNC	17
-#define LSCHL_GPIO_LED_PWR	0
-
-static struct gpio_led lschl_led_pins[] = {
-	{
-		.name = "alarm:red",
-		.gpio = LSCHL_GPIO_LED_ALARM,
-		.active_low = 1,
-	}, {
-		.name = "info:amber",
-		.gpio = LSCHL_GPIO_LED_INFO,
-		.active_low = 1,
-	}, {
-		.name = "func:blue:top",
-		.gpio = LSCHL_GPIO_LED_FUNC,
-		.active_low = 1,
-	}, {
-		.name = "power:blue:bottom",
-		.gpio = LSCHL_GPIO_LED_PWR,
-	},
-};
-
-static struct gpio_led_platform_data lschl_led_data = {
-	.leds = lschl_led_pins,
-	.num_leds = ARRAY_SIZE(lschl_led_pins),
-};
-
-static struct platform_device lschl_leds = {
-	.name = "leds-gpio",
-	.id = -1,
-	.dev = {
-		.platform_data = &lschl_led_data,
-	},
-};
-
-/*****************************************************************************
- * SATA
- ****************************************************************************/
-static struct mv_sata_platform_data lschl_sata_data = {
-	.n_ports = 2,
-};
-
-/*****************************************************************************
- * LS-CHL specific power off method: reboot
- ****************************************************************************/
-/*
- * On the LS-CHL, the shutdown process is following:
- * - Userland monitors key events until the power switch goes to off position
- * - The board reboots
- * - U-boot starts and goes into an idle mode waiting for the user
- *   to move the switch to ON position
- *
- */
-
-static void lschl_power_off(void)
-{
-	orion5x_restart(REBOOT_HARD, NULL);
-}
-
-/*****************************************************************************
- * General Setup
- ****************************************************************************/
-#define LSCHL_GPIO_USB_POWER	9
-#define LSCHL_GPIO_AUTO_POWER	17
-#define LSCHL_GPIO_POWER	18
-
-/****************************************************************************
- * GPIO Attached Keys
- ****************************************************************************/
-#define LSCHL_GPIO_KEY_FUNC		15
-#define LSCHL_GPIO_KEY_POWER		8
-#define LSCHL_GPIO_KEY_AUTOPOWER	10
-#define LSCHL_SW_POWER		0x00
-#define LSCHL_SW_AUTOPOWER	0x01
-#define LSCHL_SW_FUNC		0x02
-
-static struct gpio_keys_button lschl_buttons[] = {
-	{
-		.type = EV_SW,
-		.code = LSCHL_SW_POWER,
-		.gpio = LSCHL_GPIO_KEY_POWER,
-		.desc = "Power-on Switch",
-		.active_low = 1,
-	}, {
-		.type = EV_SW,
-		.code = LSCHL_SW_AUTOPOWER,
-		.gpio = LSCHL_GPIO_KEY_AUTOPOWER,
-		.desc = "Power-auto Switch",
-		.active_low = 1,
-	}, {
-		.type = EV_SW,
-		.code = LSCHL_SW_FUNC,
-		.gpio = LSCHL_GPIO_KEY_FUNC,
-		.desc = "Function Switch",
-		.active_low = 1,
-	},
-};
-
-static struct gpio_keys_platform_data lschl_button_data = {
-	.buttons = lschl_buttons,
-	.nbuttons = ARRAY_SIZE(lschl_buttons),
-};
-
-static struct platform_device lschl_button_device = {
-	.name = "gpio-keys",
-	.id = -1,
-	.num_resources = 0,
-	.dev = {
-		.platform_data = &lschl_button_data,
-	},
-};
-
-#define LSCHL_GPIO_HDD_POWER	1
-
-/****************************************************************************
- * GPIO Fan
- ****************************************************************************/
-
-#define LSCHL_GPIO_FAN_LOW	16
-#define LSCHL_GPIO_FAN_HIGH	14
-#define LSCHL_GPIO_FAN_LOCK	6
-
-static struct gpio_fan_alarm lschl_alarm = {
-	.gpio = LSCHL_GPIO_FAN_LOCK,
-};
-
-static struct gpio_fan_speed lschl_speeds[] = {
-	{
-		.rpm = 0,
-		.ctrl_val = 3,
-	}, {
-		.rpm = 1500,
-		.ctrl_val = 2,
-	}, {
-		.rpm = 3250,
-		.ctrl_val = 1,
-	}, {
-		.rpm = 5000,
-		.ctrl_val = 0,
-	},
-};
-
-static int lschl_gpio_list[] = {
-	LSCHL_GPIO_FAN_HIGH, LSCHL_GPIO_FAN_LOW,
-};
-
-static struct gpio_fan_platform_data lschl_fan_data = {
-	.num_ctrl = ARRAY_SIZE(lschl_gpio_list),
-	.ctrl = lschl_gpio_list,
-	.alarm = &lschl_alarm,
-	.num_speed = ARRAY_SIZE(lschl_speeds),
-	.speed = lschl_speeds,
-};
-
-static struct platform_device lschl_fan_device = {
-	.name = "gpio-fan",
-	.id = -1,
-	.num_resources = 0,
-	.dev = {
-		.platform_data = &lschl_fan_data,
-	},
-};
-
-/****************************************************************************
- * GPIO Data
- ****************************************************************************/
-
-static unsigned int lschl_mpp_modes[] __initdata = {
-	MPP0_GPIO, /* LED POWER */
-	MPP1_GPIO, /* HDD POWER */
-	MPP2_GPIO, /* LED ALARM */
-	MPP3_GPIO, /* LED INFO */
-	MPP4_UNUSED,
-	MPP5_UNUSED,
-	MPP6_GPIO, /* FAN LOCK */
-	MPP7_GPIO, /* SW INIT */
-	MPP8_GPIO, /* SW POWER */
-	MPP9_GPIO, /* USB POWER */
-	MPP10_GPIO, /* SW AUTO POWER */
-	MPP11_UNUSED,
-	MPP12_UNUSED,
-	MPP13_UNUSED,
-	MPP14_GPIO, /* FAN HIGH */
-	MPP15_GPIO, /* SW FUNC */
-	MPP16_GPIO, /* FAN LOW */
-	MPP17_GPIO, /* LED FUNC */
-	MPP18_UNUSED,
-	MPP19_UNUSED,
-	0,
-};
-
-static void __init lschl_init(void)
-{
-	/*
-	 * Setup basic Orion functions. Needs to be called early.
-	 */
-	orion5x_init();
-
-	orion5x_mpp_conf(lschl_mpp_modes);
-
-	/*
-	 * Configure peripherals.
-	 */
-	orion5x_ehci0_init();
-	orion5x_ehci1_init();
-	orion5x_eth_init(&lschl_eth_data);
-	orion5x_i2c_init();
-	orion5x_sata_init(&lschl_sata_data);
-	orion5x_uart0_init();
-	orion5x_xor_init();
-
-	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
-				    ORION_MBUS_DEVBUS_BOOT_ATTR,
-				    LSCHL_NOR_BOOT_BASE,
-				    LSCHL_NOR_BOOT_SIZE);
-	platform_device_register(&lschl_nor_flash);
-
-	platform_device_register(&lschl_leds);
-
-	platform_device_register(&lschl_button_device);
-
-	platform_device_register(&lschl_fan_device);
-
-	i2c_register_board_info(0, &lschl_i2c_rtc, 1);
-
-	/* usb power on */
-	gpio_set_value(LSCHL_GPIO_USB_POWER, 1);
-
-	/* register power-off method */
-	pm_power_off = lschl_power_off;
-
-	pr_info("%s: finished\n", __func__);
-}
-
-MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
-	/* Maintainer: Ash Hughes <ashley.hughes@blueyonder.co.uk> */
-	.atag_offset	= 0x100,
-	.nr_irqs	= ORION5X_NR_IRQS,
-	.init_machine	= lschl_init,
-	.map_io		= orion5x_map_io,
-	.init_early	= orion5x_init_early,
-	.init_irq	= orion5x_init_irq,
-	.init_time	= orion5x_timer_init,
-	.fixup		= tag_fixup_mem32,
-	.restart	= orion5x_restart,
-MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-orion5x/Makefile linux-libre-4.10-rc8-gnu/arch/arm/mach-orion5x/Makefile
--- linux-libre-4.9-gnu/arch/arm/mach-orion5x/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-orion5x/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,6 @@ obj-$(CONFIG_MACH_WNR854T)	+= wnr854t-se
 obj-$(CONFIG_MACH_RD88F5181L_GE)	+= rd88f5181l-ge-setup.o
 obj-$(CONFIG_MACH_RD88F5181L_FXO)	+= rd88f5181l-fxo-setup.o
 obj-$(CONFIG_MACH_RD88F6183AP_GE)	+= rd88f6183ap-ge-setup.o
-obj-$(CONFIG_MACH_LINKSTATION_LSCHL)	+= ls-chl-setup.o
 
 obj-$(CONFIG_ARCH_ORION5X_DT)		+= board-dt.o
 obj-$(CONFIG_MACH_D2NET_DT)	+= board-d2net.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-oxnas/headsmp.S linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/headsmp.S
--- linux-libre-4.9-gnu/arch/arm/mach-oxnas/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/headsmp.S	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (c) 2003 ARM Limited
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * OX820 specific entry point for secondary CPUs.
+ */
+ENTRY(ox820_secondary_startup)
+	mov r4, #0
+	/* invalidate both caches and branch target cache */
+	mcr p15, 0, r4, c7, c7, 0
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-oxnas/hotplug.c linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/hotplug.c
--- linux-libre-4.9-gnu/arch/arm/mach-oxnas/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/hotplug.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/cp15.h>
+#include <asm/smp_plat.h>
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	mcr	p15, 0, %1, c7, c10, 4\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0), "Ir" (CR_C)
+	  : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(	"mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, %1\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, #0x20\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  : "Ir" (CR_C)
+	  : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+	/*
+	 * there is no power-control hardware on this platform, so all
+	 * we can do is put the core into WFI; this is safe as the calling
+	 * code will have already disabled interrupts
+	 */
+	for (;;) {
+		/*
+		 * here's the WFI
+		 */
+		asm(".word	0xe320f003\n"
+		    :
+		    :
+		    : "memory", "cc");
+
+		if (pen_release == cpu_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)++;
+	}
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void ox820_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);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-oxnas/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mach-oxnas/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,9 +1,16 @@
 menuconfig ARCH_OXNAS
 	bool "Oxford Semiconductor OXNAS Family SoCs"
 	select ARCH_HAS_RESET_CONTROLLER
+	select COMMON_CLK_OXNAS
 	select GPIOLIB
+	select MFD_SYSCON
+	select OXNAS_RPS_TIMER
+	select PINCTRL_OXNAS
+	select RESET_CONTROLLER
+	select RESET_OXNAS
+	select VERSATILE_FPGA_IRQ
 	select PINCTRL
-	depends on ARCH_MULTI_V5
+	depends on ARCH_MULTI_V5 || ARCH_MULTI_V6
 	help
 	  Support for OxNas SoC family developed by Oxford Semiconductor.
 
@@ -11,16 +18,21 @@ if ARCH_OXNAS
 
 config MACH_OX810SE
 	bool "Support OX810SE Based Products"
-	select ARCH_HAS_RESET_CONTROLLER
-	select COMMON_CLK_OXNAS
+	depends on ARCH_MULTI_V5
 	select CPU_ARM926T
-	select MFD_SYSCON
-	select OXNAS_RPS_TIMER
-	select PINCTRL_OXNAS
-	select RESET_CONTROLLER
-	select RESET_OXNAS
-	select VERSATILE_FPGA_IRQ
 	help
 	  Include Support for the Oxford Semiconductor OX810SE SoC Based Products.
 
+config MACH_OX820
+	bool "Support OX820 Based Products"
+	depends on ARCH_MULTI_V6
+	select ARM_GIC
+	select DMA_CACHE_RWFO if SMP
+	select CPU_V6K
+	select HAVE_SMP
+	select HAVE_ARM_SCU if SMP
+	select HAVE_ARM_TWD if SMP
+	help
+	  Include Support for the Oxford Semiconductor OX820 SoC Based Products.
+
 endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-oxnas/Makefile linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/Makefile
--- linux-libre-4.9-gnu/arch/arm/mach-oxnas/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) 	+= hotplug.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-oxnas/platsmp.c linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/platsmp.c
--- linux-libre-4.9-gnu/arch/arm/mach-oxnas/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-oxnas/platsmp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * 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/io.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cp15.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+
+extern void ox820_secondary_startup(void);
+extern void ox820_cpu_die(unsigned int cpu);
+
+static void __iomem *cpu_ctrl;
+static void __iomem *gic_cpu_ctrl;
+
+#define HOLDINGPEN_CPU_OFFSET		0xc8
+#define HOLDINGPEN_LOCATION_OFFSET	0xc4
+
+#define GIC_NCPU_OFFSET(cpu)		(0x100 + (cpu)*0x100)
+#define GIC_CPU_CTRL			0x00
+#define GIC_CPU_CTRL_ENABLE		1
+
+int __init ox820_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	/*
+	 * Write the address of secondary startup into the
+	 * system-wide flags register. The BootMonitor waits
+	 * until it receives a soft interrupt, and then the
+	 * secondary CPU branches to this address.
+	 */
+	writel(virt_to_phys(ox820_secondary_startup),
+			cpu_ctrl + HOLDINGPEN_LOCATION_OFFSET);
+
+	writel(cpu, cpu_ctrl + HOLDINGPEN_CPU_OFFSET);
+
+	/*
+	 * Enable GIC cpu interface in CPU Interface Control Register
+	 */
+	writel(GIC_CPU_CTRL_ENABLE,
+		gic_cpu_ctrl + GIC_NCPU_OFFSET(cpu) + GIC_CPU_CTRL);
+
+	/*
+	 * 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.
+	 */
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+	return 0;
+}
+
+static void __init ox820_smp_prepare_cpus(unsigned int max_cpus)
+{
+	struct device_node *np;
+	void __iomem *scu_base;
+
+	np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-scu");
+	scu_base = of_iomap(np, 0);
+	of_node_put(np);
+	if (!scu_base)
+		return;
+
+	/* Remap CPU Interrupt Interface Registers */
+	np = of_find_compatible_node(NULL, NULL, "arm,arm11mp-gic");
+	gic_cpu_ctrl = of_iomap(np, 1);
+	of_node_put(np);
+	if (!gic_cpu_ctrl)
+		goto unmap_scu;
+
+	np = of_find_compatible_node(NULL, NULL, "oxsemi,ox820-sys-ctrl");
+	cpu_ctrl = of_iomap(np, 0);
+	of_node_put(np);
+	if (!cpu_ctrl)
+		goto unmap_scu;
+
+	scu_enable(scu_base);
+	flush_cache_all();
+
+unmap_scu:
+	iounmap(scu_base);
+}
+
+static const struct smp_operations ox820_smp_ops __initconst = {
+	.smp_prepare_cpus	= ox820_smp_prepare_cpus,
+	.smp_boot_secondary	= ox820_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= ox820_cpu_die,
+#endif
+};
+
+CPU_METHOD_OF_DECLARE(ox820_smp, "oxsemi,ox820-smp", &ox820_smp_ops);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/corgi.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/corgi.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/corgi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/corgi.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,6 @@
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/gpio_keys.h>
-#include <linux/module.h>
 #include <linux/memblock.h>
 #include <video/w100fb.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/em-x270.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/em-x270.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/em-x270.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/em-x270.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/mfd/da903x.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
 #include <linux/spi/libertas_spi.h>
@@ -34,8 +35,6 @@
 #include <linux/i2c/pxa-i2c.h>
 #include <linux/regulator/userspace-consumer.h>
 
-#include <media/soc_camera.h>
-
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -958,8 +957,6 @@ static inline void em_x270_init_gpio_key
 
 /* Quick Capture Interface and sensor setup */
 #if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
-static struct regulator *em_x270_camera_ldo;
-
 static int em_x270_sensor_init(void)
 {
 	int ret;
@@ -969,81 +966,53 @@ static int em_x270_sensor_init(void)
 		return ret;
 
 	gpio_direction_output(cam_reset, 0);
-
-	em_x270_camera_ldo = regulator_get(NULL, "vcc cam");
-	if (em_x270_camera_ldo == NULL) {
-		gpio_free(cam_reset);
-		return -ENODEV;
-	}
-
-	ret = regulator_enable(em_x270_camera_ldo);
-	if (ret) {
-		regulator_put(em_x270_camera_ldo);
-		gpio_free(cam_reset);
-		return ret;
-	}
-
 	gpio_set_value(cam_reset, 1);
 
 	return 0;
 }
 
-struct pxacamera_platform_data em_x270_camera_platform_data = {
-	.flags  = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
-		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
-	.mclk_10khz = 2600,
+static struct regulator_consumer_supply camera_dummy_supplies[] = {
+	REGULATOR_SUPPLY("vdd", "0-005d"),
 };
 
-static int em_x270_sensor_power(struct device *dev, int on)
-{
-	int ret;
-	int is_on = regulator_is_enabled(em_x270_camera_ldo);
-
-	if (on == is_on)
-		return 0;
-
-	gpio_set_value(cam_reset, !on);
-
-	if (on)
-		ret = regulator_enable(em_x270_camera_ldo);
-	else
-		ret = regulator_disable(em_x270_camera_ldo);
-
-	if (ret)
-		return ret;
-
-	gpio_set_value(cam_reset, on);
-
-	return 0;
-}
-
-static struct i2c_board_info em_x270_i2c_cam_info[] = {
-	{
-		I2C_BOARD_INFO("mt9m111", 0x48),
+static struct regulator_init_data camera_dummy_initdata = {
+	.consumer_supplies = camera_dummy_supplies,
+	.num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies),
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 	},
 };
 
-static struct soc_camera_link iclink = {
-	.bus_id		= 0,
-	.power		= em_x270_sensor_power,
-	.board_info	= &em_x270_i2c_cam_info[0],
-	.i2c_adapter_id	= 0,
+static struct fixed_voltage_config camera_dummy_config = {
+	.supply_name		= "camera_vdd",
+	.input_supply		= "vcc cam",
+	.microvolts		= 2800000,
+	.gpio			= -1,
+	.enable_high		= 0,
+	.init_data		= &camera_dummy_initdata,
 };
 
-static struct platform_device em_x270_camera = {
-	.name	= "soc-camera-pdrv",
-	.id	= -1,
+static struct platform_device camera_supply_dummy_device = {
+	.name	= "reg-fixed-voltage",
+	.id	= 1,
 	.dev	= {
-		.platform_data = &iclink,
+		.platform_data = &camera_dummy_config,
 	},
 };
 
+struct pxacamera_platform_data em_x270_camera_platform_data = {
+	.flags  = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
+		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
+	.mclk_10khz = 2600,
+	.sensor_i2c_adapter_id = 0,
+	.sensor_i2c_address = 0x5d,
+};
+
 static void  __init em_x270_init_camera(void)
 {
-	if (em_x270_sensor_init() == 0) {
+	if (em_x270_sensor_init() == 0)
 		pxa_set_camera_info(&em_x270_camera_platform_data);
-		platform_device_register(&em_x270_camera);
-	}
+	platform_device_register(&camera_supply_dummy_device);
 }
 #else
 static inline void em_x270_init_camera(void) {}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/ezx.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/ezx.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/ezx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/ezx.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,14 +17,14 @@
 #include <linux/delay.h>
 #include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds-lp3944.h>
 #include <linux/i2c/pxa-i2c.h>
 
-#include <media/soc_camera.h>
-
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -723,6 +723,42 @@ static struct platform_device a780_gpio_
 };
 
 /* camera */
+static struct regulator_consumer_supply camera_dummy_supplies[] = {
+	REGULATOR_SUPPLY("vdd", "0-005d"),
+};
+
+static struct regulator_init_data camera_dummy_initdata = {
+	.consumer_supplies = camera_dummy_supplies,
+	.num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies),
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+};
+
+static struct fixed_voltage_config camera_dummy_config = {
+	.supply_name		= "camera_vdd",
+	.microvolts		= 2800000,
+	.gpio			= GPIO50_nCAM_EN,
+	.enable_high		= 0,
+	.init_data		= &camera_dummy_initdata,
+};
+
+static struct platform_device camera_supply_dummy_device = {
+	.name	= "reg-fixed-voltage",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &camera_dummy_config,
+	},
+};
+static int a780_camera_reset(struct device *dev)
+{
+	gpio_set_value(GPIO19_GEN1_CAM_RST, 0);
+	msleep(10);
+	gpio_set_value(GPIO19_GEN1_CAM_RST, 1);
+
+	return 0;
+}
+
 static int a780_camera_init(void)
 {
 	int err;
@@ -731,73 +767,36 @@ static int a780_camera_init(void)
 	 * GPIO50_nCAM_EN is active low
 	 * GPIO19_GEN1_CAM_RST is active on rising edge
 	 */
-	err = gpio_request(GPIO50_nCAM_EN, "nCAM_EN");
-	if (err) {
-		pr_err("%s: Failed to request nCAM_EN\n", __func__);
-		goto fail;
-	}
-
 	err = gpio_request(GPIO19_GEN1_CAM_RST, "CAM_RST");
 	if (err) {
 		pr_err("%s: Failed to request CAM_RST\n", __func__);
-		goto fail_gpio_cam_rst;
+		return err;
 	}
 
-	gpio_direction_output(GPIO50_nCAM_EN, 1);
 	gpio_direction_output(GPIO19_GEN1_CAM_RST, 0);
-
-	return 0;
-
-fail_gpio_cam_rst:
-	gpio_free(GPIO50_nCAM_EN);
-fail:
-	return err;
-}
-
-static int a780_camera_power(struct device *dev, int on)
-{
-	gpio_set_value(GPIO50_nCAM_EN, !on);
-	return 0;
-}
-
-static int a780_camera_reset(struct device *dev)
-{
-	gpio_set_value(GPIO19_GEN1_CAM_RST, 0);
-	msleep(10);
-	gpio_set_value(GPIO19_GEN1_CAM_RST, 1);
+	a780_camera_reset(NULL);
 
 	return 0;
 }
 
 struct pxacamera_platform_data a780_pxacamera_platform_data = {
 	.flags  = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
-		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
+		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN |
+		PXA_CAMERA_PCP,
 	.mclk_10khz = 5000,
+	.sensor_i2c_adapter_id = 0,
+	.sensor_i2c_address = 0x5d,
 };
 
-static struct i2c_board_info a780_camera_i2c_board_info = {
-	I2C_BOARD_INFO("mt9m111", 0x5d),
-};
-
-static struct soc_camera_link a780_iclink = {
-	.bus_id         = 0,
-	.flags          = SOCAM_SENSOR_INVERT_PCLK,
-	.i2c_adapter_id = 0,
-	.board_info     = &a780_camera_i2c_board_info,
-	.power          = a780_camera_power,
-	.reset          = a780_camera_reset,
-};
-
-static struct platform_device a780_camera = {
-	.name   = "soc-camera-pdrv",
-	.id     = 0,
-	.dev    = {
-		.platform_data = &a780_iclink,
+static struct i2c_board_info a780_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("mt9m111", 0x5d),
 	},
 };
 
 static struct platform_device *a780_devices[] __initdata = {
 	&a780_gpio_keys,
+	&camera_supply_dummy_device,
 };
 
 static void __init a780_init(void)
@@ -811,19 +810,19 @@ static void __init a780_init(void)
 	pxa_set_stuart_info(NULL);
 
 	pxa_set_i2c_info(NULL);
+	i2c_register_board_info(0, ARRAY_AND_SIZE(a780_i2c_board_info));
 
 	pxa_set_fb_info(NULL, &ezx_fb_info_1);
 
 	pxa_set_keypad_info(&a780_keypad_platform_data);
 
-	if (a780_camera_init() == 0) {
+	if (a780_camera_init() == 0)
 		pxa_set_camera_info(&a780_pxacamera_platform_data);
-		platform_device_register(&a780_camera);
-	}
 
 	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(a780_devices));
+	regulator_has_full_constraints();
 }
 
 MACHINE_START(EZX_A780, "Motorola EZX A780")
@@ -1001,6 +1000,15 @@ static struct platform_device a910_gpio_
 };
 
 /* camera */
+static int a910_camera_reset(struct device *dev)
+{
+	gpio_set_value(GPIO28_GEN2_CAM_RST, 0);
+	msleep(10);
+	gpio_set_value(GPIO28_GEN2_CAM_RST, 1);
+
+	return 0;
+}
+
 static int a910_camera_init(void)
 {
 	int err;
@@ -1009,68 +1017,25 @@ static int a910_camera_init(void)
 	 * GPIO50_nCAM_EN is active low
 	 * GPIO28_GEN2_CAM_RST is active on rising edge
 	 */
-	err = gpio_request(GPIO50_nCAM_EN, "nCAM_EN");
-	if (err) {
-		pr_err("%s: Failed to request nCAM_EN\n", __func__);
-		goto fail;
-	}
-
 	err = gpio_request(GPIO28_GEN2_CAM_RST, "CAM_RST");
 	if (err) {
 		pr_err("%s: Failed to request CAM_RST\n", __func__);
-		goto fail_gpio_cam_rst;
+		return err;
 	}
 
-	gpio_direction_output(GPIO50_nCAM_EN, 1);
 	gpio_direction_output(GPIO28_GEN2_CAM_RST, 0);
-
-	return 0;
-
-fail_gpio_cam_rst:
-	gpio_free(GPIO50_nCAM_EN);
-fail:
-	return err;
-}
-
-static int a910_camera_power(struct device *dev, int on)
-{
-	gpio_set_value(GPIO50_nCAM_EN, !on);
-	return 0;
-}
-
-static int a910_camera_reset(struct device *dev)
-{
-	gpio_set_value(GPIO28_GEN2_CAM_RST, 0);
-	msleep(10);
-	gpio_set_value(GPIO28_GEN2_CAM_RST, 1);
+	a910_camera_reset(NULL);
 
 	return 0;
 }
 
 struct pxacamera_platform_data a910_pxacamera_platform_data = {
 	.flags  = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
-		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
+		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN |
+		PXA_CAMERA_PCP,
 	.mclk_10khz = 5000,
-};
-
-static struct i2c_board_info a910_camera_i2c_board_info = {
-	I2C_BOARD_INFO("mt9m111", 0x5d),
-};
-
-static struct soc_camera_link a910_iclink = {
-	.bus_id         = 0,
-	.i2c_adapter_id = 0,
-	.board_info     = &a910_camera_i2c_board_info,
-	.power          = a910_camera_power,
-	.reset          = a910_camera_reset,
-};
-
-static struct platform_device a910_camera = {
-	.name   = "soc-camera-pdrv",
-	.id     = 0,
-	.dev    = {
-		.platform_data = &a910_iclink,
-	},
+	.sensor_i2c_adapter_id = 0,
+	.sensor_i2c_address = 0x5d,
 };
 
 /* leds-lp3944 */
@@ -1122,10 +1087,14 @@ static struct i2c_board_info __initdata
 		I2C_BOARD_INFO("lp3944", 0x60),
 		.platform_data = &a910_lp3944_leds,
 	},
+	{
+		I2C_BOARD_INFO("mt9m111", 0x5d),
+	},
 };
 
 static struct platform_device *a910_devices[] __initdata = {
 	&a910_gpio_keys,
+	&camera_supply_dummy_device,
 };
 
 static void __init a910_init(void)
@@ -1145,14 +1114,13 @@ static void __init a910_init(void)
 
 	pxa_set_keypad_info(&a910_keypad_platform_data);
 
-	if (a910_camera_init() == 0) {
+	if (a910_camera_init() == 0)
 		pxa_set_camera_info(&a910_pxacamera_platform_data);
-		platform_device_register(&a910_camera);
-	}
 
 	pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
 	platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
 	platform_add_devices(ARRAY_AND_SIZE(a910_devices));
+	regulator_has_full_constraints();
 }
 
 MACHINE_START(EZX_A910, "Motorola EZX A910")
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/generic.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/generic.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/generic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/generic.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,21 +43,6 @@ void clear_reset_status(unsigned int mas
 	}
 }
 
-unsigned long get_clock_tick_rate(void)
-{
-	unsigned long clock_tick_rate;
-
-	if (cpu_is_pxa25x())
-		clock_tick_rate = 3686400;
-	else if (machine_is_mainstone())
-		clock_tick_rate = 3249600;
-	else
-		clock_tick_rate = 3250000;
-
-	return clock_tick_rate;
-}
-EXPORT_SYMBOL(get_clock_tick_rate);
-
 /*
  * For non device-tree builds, keep legacy timer init
  */
@@ -69,8 +54,7 @@ void __init pxa_timer_init(void)
 		pxa27x_clocks_init();
 	if (cpu_is_pxa3xx())
 		pxa3xx_clocks_init();
-	pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000),
-			    get_clock_tick_rate());
+	pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x40a00000));
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/idp.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/idp.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/idp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/idp.c	2017-02-12 16:03:20.000000000 -0500
@@ -85,6 +85,7 @@ static struct resource smc91x_resources[
 static struct smc91x_platdata smc91x_platdata = {
 	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
 		 SMC91X_USE_DMA | SMC91X_NOWAIT,
+	.pxa_u16_align4 = true,
 };
 
 static struct platform_device smc91x_device = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/include/mach/hardware.h linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/include/mach/hardware.h
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/include/mach/hardware.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/include/mach/hardware.h	2017-02-12 16:03:20.000000000 -0500
@@ -303,8 +303,6 @@
  */
 extern unsigned int get_memclk_frequency_10khz(void);
 
-/* return the clock tick rate of the OS timer */
-extern unsigned long get_clock_tick_rate(void);
 #endif
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/mainstone.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/mainstone.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/mainstone.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/mainstone.c	2017-02-12 16:03:20.000000000 -0500
@@ -140,6 +140,7 @@ static struct resource smc91x_resources[
 static struct smc91x_platdata mainstone_smc91x_info = {
 	.flags	= SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT |
 		  SMC91X_NOWAIT | SMC91X_USE_DMA,
+	.pxa_u16_align4 = true,
 };
 
 static struct platform_device smc91x_device = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/mioa701.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/mioa701.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/mioa701.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/mioa701.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,6 @@
 #include <linux/platform_data/media/camera-pxa.h>
 #include <mach/audio.h>
 #include <mach/smemc.h>
-#include <media/soc_camera.h>
 
 #include "mioa701.h"
 
@@ -627,6 +626,8 @@ struct pxacamera_platform_data mioa701_p
 	.flags  = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
 		PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
 	.mclk_10khz = 5000,
+	.sensor_i2c_adapter_id = 0,
+	.sensor_i2c_address = 0x5d,
 };
 
 static struct i2c_board_info __initdata mioa701_pi2c_devices[] = {
@@ -643,12 +644,6 @@ static struct i2c_board_info mioa701_i2c
 	},
 };
 
-static struct soc_camera_link iclink = {
-	.bus_id		= 0, /* Match id in pxa27x_device_camera in device.c */
-	.board_info	= &mioa701_i2c_devices[0],
-	.i2c_adapter_id	= 0,
-};
-
 struct i2c_pxa_platform_data i2c_pdata = {
 	.fast_mode = 1,
 };
@@ -684,7 +679,6 @@ MIO_SIMPLE_DEV(mioa701_sound,	  "mioa701
 MIO_SIMPLE_DEV(mioa701_board,	  "mioa701-board",  NULL)
 MIO_SIMPLE_DEV(wm9713_acodec,	  "wm9713-codec",   NULL);
 MIO_SIMPLE_DEV(gpio_vbus,	  "gpio-vbus",      &gpio_vbus_data);
-MIO_SIMPLE_DEV(mioa701_camera,	  "soc-camera-pdrv",&iclink);
 
 static struct platform_device *devices[] __initdata = {
 	&mioa701_gpio_keys,
@@ -696,7 +690,6 @@ static struct platform_device *devices[]
 	&power_dev,
 	&docg3,
 	&gpio_vbus,
-	&mioa701_camera,
 	&mioa701_board,
 };
 
@@ -761,6 +754,7 @@ static void __init mioa701_machine_init(
 	platform_add_devices(devices, ARRAY_SIZE(devices));
 	gsm_init();
 
+	i2c_register_board_info(0, ARRAY_AND_SIZE(mioa701_i2c_devices));
 	i2c_register_board_info(1, ARRAY_AND_SIZE(mioa701_pi2c_devices));
 	pxa_set_i2c_info(&i2c_pdata);
 	pxa27x_set_i2c_power_info(NULL);
@@ -769,6 +763,7 @@ static void __init mioa701_machine_init(
 	regulator_register_always_on(0, "fixed-5.0V", fixed_5v0_consumers,
 				     ARRAY_SIZE(fixed_5v0_consumers),
 				     5000000);
+	regulator_has_full_constraints();
 }
 
 static void mioa701_machine_exit(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/pxa25x.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/pxa25x.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/pxa25x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/pxa25x.c	2017-02-12 16:03:20.000000000 -0500
@@ -156,7 +156,7 @@ static int __init __init
 pxa25x_dt_init_irq(struct device_node *node, struct device_node *parent)
 {
 	pxa_dt_irq_init(pxa25x_set_wake);
-	set_handle_irq(ichp_handle_irq);
+	set_handle_irq(icip_handle_irq);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/pxa_cplds_irqs.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/pxa_cplds_irqs.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/pxa_cplds_irqs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/pxa_cplds_irqs.c	2017-02-12 16:03:20.000000000 -0500
@@ -120,13 +120,9 @@ static int cplds_probe(struct platform_d
 	if (!fpga)
 		return -ENOMEM;
 
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res) {
-		fpga->irq = (unsigned int)res->start;
-		irqflags = res->flags;
-	}
-	if (!fpga->irq)
-		return -ENODEV;
+	fpga->irq = platform_get_irq(pdev, 0);
+	if (fpga->irq <= 0)
+		return fpga->irq;
 
 	base_irq = platform_get_irq(pdev, 1);
 	if (base_irq < 0)
@@ -142,6 +138,7 @@ static int cplds_probe(struct platform_d
 	writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN);
 	writel(0, fpga->base + FPGA_IRQ_SET_CLR);
 
+	irqflags = irq_get_trigger_type(fpga->irq);
 	ret = devm_request_irq(&pdev->dev, fpga->irq, cplds_irq_handler,
 			       irqflags, dev_name(&pdev->dev), fpga);
 	if (ret == -ENOSYS)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/spitz.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/spitz.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/spitz.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/spitz.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,6 @@
 #include <linux/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
 #include <linux/io.h>
-#include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/memblock.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-pxa/stargate2.c linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/stargate2.c
--- linux-libre-4.9-gnu/arch/arm/mach-pxa/stargate2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-pxa/stargate2.c	2017-02-12 16:03:20.000000000 -0500
@@ -673,6 +673,7 @@ static struct resource smc91x_resources[
 static struct smc91x_platdata stargate2_smc91x_info = {
 	.flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT
 	| SMC91X_NOWAIT | SMC91X_USE_DMA,
+	.pxa_u16_align4 = true,
 };
 
 static struct platform_device smc91x_device = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-rpc/dma.c linux-libre-4.10-rc8-gnu/arch/arm/mach-rpc/dma.c
--- linux-libre-4.9-gnu/arch/arm/mach-rpc/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-rpc/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <asm/fiq.h>
 #include <asm/irq.h>
 #include <mach/hardware.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/mach/dma.h>
 #include <asm/hardware/iomd.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/common.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/common.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/common.c	2017-02-12 16:03:20.000000000 -0500
@@ -345,10 +345,40 @@ static struct s3c24xx_dma_channel s3c241
 	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, S3C24XX_DMA_CHANREQ(4, 3), },
 };
 
+static const struct dma_slave_map s3c2410_dma_slave_map[] = {
+	{ "s3c2410-sdi", "rx-tx", (void *)DMACH_SDI },
+	{ "s3c2410-spi.0", "rx", (void *)DMACH_SPI0_RX },
+	{ "s3c2410-spi.0", "tx", (void *)DMACH_SPI0_TX },
+	{ "s3c2410-spi.1", "rx", (void *)DMACH_SPI1_RX },
+	{ "s3c2410-spi.1", "tx", (void *)DMACH_SPI1_TX },
+	/*
+	 * The DMA request source[1] (DMACH_UARTx_SRC2) are
+	 * not used in the UART driver.
+	 */
+	{ "s3c2410-uart.0", "rx", (void *)DMACH_UART0 },
+	{ "s3c2410-uart.0", "tx", (void *)DMACH_UART0 },
+	{ "s3c2410-uart.1", "rx", (void *)DMACH_UART1 },
+	{ "s3c2410-uart.1", "tx", (void *)DMACH_UART1 },
+	{ "s3c2410-uart.2", "rx", (void *)DMACH_UART2 },
+	{ "s3c2410-uart.2", "tx", (void *)DMACH_UART2 },
+	{ "s3c24xx-iis", "rx", (void *)DMACH_I2S_IN },
+	{ "s3c24xx-iis", "tx", (void *)DMACH_I2S_OUT },
+	{ "s3c-hsudc", "rx0", (void *)DMACH_USB_EP1 },
+	{ "s3c-hsudc", "tx0", (void *)DMACH_USB_EP1 },
+	{ "s3c-hsudc", "rx1", (void *)DMACH_USB_EP2 },
+	{ "s3c-hsudc", "tx1", (void *)DMACH_USB_EP2 },
+	{ "s3c-hsudc", "rx2", (void *)DMACH_USB_EP3 },
+	{ "s3c-hsudc", "tx2", (void *)DMACH_USB_EP3 },
+	{ "s3c-hsudc", "rx3", (void *)DMACH_USB_EP4 },
+	{ "s3c-hsudc", "tx3", (void *)DMACH_USB_EP4 }
+};
+
 static struct s3c24xx_dma_platdata s3c2410_dma_platdata = {
 	.num_phy_channels = 4,
 	.channels = s3c2410_dma_channels,
 	.num_channels = DMACH_MAX,
+	.slave_map = s3c2410_dma_slave_map,
+	.slavecnt = ARRAY_SIZE(s3c2410_dma_slave_map),
 };
 
 struct platform_device s3c2410_device_dma = {
@@ -388,10 +418,36 @@ static struct s3c24xx_dma_channel s3c241
 	[DMACH_USB_EP4] = { S3C24XX_DMA_APB, true, 16 },
 };
 
+static const struct dma_slave_map s3c2412_dma_slave_map[] = {
+	{ "s3c2412-sdi", "rx-tx", (void *)DMACH_SDI },
+	{ "s3c2412-spi.0", "rx", (void *)DMACH_SPI0_RX },
+	{ "s3c2412-spi.0", "tx", (void *)DMACH_SPI0_TX },
+	{ "s3c2412-spi.1", "rx", (void *)DMACH_SPI1_RX },
+	{ "s3c2412-spi.1", "tx", (void *)DMACH_SPI1_TX },
+	{ "s3c2440-uart.0", "rx", (void *)DMACH_UART0 },
+	{ "s3c2440-uart.0", "tx", (void *)DMACH_UART0 },
+	{ "s3c2440-uart.1", "rx", (void *)DMACH_UART1 },
+	{ "s3c2440-uart.1", "tx", (void *)DMACH_UART1 },
+	{ "s3c2440-uart.2", "rx", (void *)DMACH_UART2 },
+	{ "s3c2440-uart.2", "tx", (void *)DMACH_UART2 },
+	{ "s3c2412-iis", "rx", (void *)DMACH_I2S_IN },
+	{ "s3c2412-iis", "tx", (void *)DMACH_I2S_OUT },
+	{ "s3c-hsudc", "rx0", (void *)DMACH_USB_EP1 },
+	{ "s3c-hsudc", "tx0", (void *)DMACH_USB_EP1 },
+	{ "s3c-hsudc", "rx1", (void *)DMACH_USB_EP2 },
+	{ "s3c-hsudc", "tx1", (void *)DMACH_USB_EP2 },
+	{ "s3c-hsudc", "rx2", (void *)DMACH_USB_EP3 },
+	{ "s3c-hsudc", "tx2", (void *)DMACH_USB_EP3 },
+	{ "s3c-hsudc", "rx3", (void *)DMACH_USB_EP4 },
+	{ "s3c-hsudc", "tx3", (void *)DMACH_USB_EP4 }
+};
+
 static struct s3c24xx_dma_platdata s3c2412_dma_platdata = {
 	.num_phy_channels = 4,
 	.channels = s3c2412_dma_channels,
 	.num_channels = DMACH_MAX,
+	.slave_map = s3c2412_dma_slave_map,
+	.slavecnt = ARRAY_SIZE(s3c2412_dma_slave_map),
 };
 
 struct platform_device s3c2412_device_dma = {
@@ -534,10 +590,30 @@ static struct s3c24xx_dma_channel s3c244
 	[DMACH_MIC_IN] = { S3C24XX_DMA_APB, true, 29 },
 };
 
+static const struct dma_slave_map s3c2443_dma_slave_map[] = {
+	{ "s3c2440-sdi", "rx-tx", (void *)DMACH_SDI },
+	{ "s3c2443-spi.0", "rx", (void *)DMACH_SPI0_RX },
+	{ "s3c2443-spi.0", "tx", (void *)DMACH_SPI0_TX },
+	{ "s3c2443-spi.1", "rx", (void *)DMACH_SPI1_RX },
+	{ "s3c2443-spi.1", "tx", (void *)DMACH_SPI1_TX },
+	{ "s3c2440-uart.0", "rx", (void *)DMACH_UART0 },
+	{ "s3c2440-uart.0", "tx", (void *)DMACH_UART0 },
+	{ "s3c2440-uart.1", "rx", (void *)DMACH_UART1 },
+	{ "s3c2440-uart.1", "tx", (void *)DMACH_UART1 },
+	{ "s3c2440-uart.2", "rx", (void *)DMACH_UART2 },
+	{ "s3c2440-uart.2", "tx", (void *)DMACH_UART2 },
+	{ "s3c2440-uart.3", "rx", (void *)DMACH_UART3 },
+	{ "s3c2440-uart.3", "tx", (void *)DMACH_UART3 },
+	{ "s3c24xx-iis", "rx", (void *)DMACH_I2S_IN },
+	{ "s3c24xx-iis", "tx", (void *)DMACH_I2S_OUT },
+};
+
 static struct s3c24xx_dma_platdata s3c2443_dma_platdata = {
 	.num_phy_channels = 6,
 	.channels = s3c2443_dma_channels,
 	.num_channels = DMACH_MAX,
+	.slave_map = s3c2443_dma_slave_map,
+	.slavecnt = ARRAY_SIZE(s3c2443_dma_slave_map),
 };
 
 struct platform_device s3c2443_device_dma = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/common-smdk.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/common-smdk.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/common-smdk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/common-smdk.c	2017-02-12 16:03:20.000000000 -0500
@@ -171,6 +171,7 @@ static struct s3c2410_platform_nand smdk
 	.twrph1		= 20,
 	.nr_sets	= ARRAY_SIZE(smdk_nand_sets),
 	.sets		= smdk_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* devices we initialise */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-anubis.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-anubis.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-anubis.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-anubis.c	2017-02-12 16:03:20.000000000 -0500
@@ -223,6 +223,7 @@ static struct s3c2410_platform_nand __in
 	.nr_sets	= ARRAY_SIZE(anubis_nand_sets),
 	.sets		= anubis_nand_sets,
 	.select_chip	= anubis_nand_select,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* IDE channels */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-at2440evb.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-at2440evb.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-at2440evb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-at2440evb.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,6 +114,7 @@ static struct s3c2410_platform_nand __in
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(at2440evb_nand_sets),
 	.sets		= at2440evb_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000AEP 10/100 ethernet controller */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-bast.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-bast.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-bast.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-bast.c	2017-02-12 16:03:20.000000000 -0500
@@ -299,6 +299,7 @@ static struct s3c2410_platform_nand __in
 	.nr_sets	= ARRAY_SIZE(bast_nand_sets),
 	.sets		= bast_nand_sets,
 	.select_chip	= bast_nand_select,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-gta02.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-gta02.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-gta02.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-gta02.c	2017-02-12 16:03:20.000000000 -0500
@@ -443,6 +443,7 @@ static struct s3c2410_platform_nand __in
 	.twrph1		= 15,
 	.nr_sets	= ARRAY_SIZE(gta02_nand_sets),
 	.sets		= gta02_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-jive.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-jive.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-jive.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-jive.c	2017-02-12 16:03:20.000000000 -0500
@@ -232,6 +232,7 @@ static struct s3c2410_platform_nand __in
 	.twrph1		= 40,
 	.sets		= jive_nand_sets,
 	.nr_sets	= ARRAY_SIZE(jive_nand_sets),
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static int __init jive_mtdset(char *options)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-mini2440.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-mini2440.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-mini2440.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-mini2440.c	2017-02-12 16:03:20.000000000 -0500
@@ -287,6 +287,7 @@ static struct s3c2410_platform_nand mini
 	.nr_sets	= ARRAY_SIZE(mini2440_nand_sets),
 	.sets		= mini2440_nand_sets,
 	.ignore_unset_ecc = 1,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* DM9000AEP 10/100 ethernet controller */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-osiris.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-osiris.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-osiris.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-osiris.c	2017-02-12 16:03:20.000000000 -0500
@@ -238,6 +238,7 @@ static struct s3c2410_platform_nand __in
 	.nr_sets	= ARRAY_SIZE(osiris_nand_sets),
 	.sets		= osiris_nand_sets,
 	.select_chip	= osiris_nand_select,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* PCMCIA control and configuration */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-qt2410.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-qt2410.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-qt2410.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-qt2410.c	2017-02-12 16:03:20.000000000 -0500
@@ -284,6 +284,7 @@ static struct s3c2410_platform_nand __in
 	.twrph1		= 20,
 	.nr_sets	= ARRAY_SIZE(qt2410_nand_sets),
 	.sets		= qt2410_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 /* UDC */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-rx1950.c	2017-02-12 16:03:20.000000000 -0500
@@ -611,6 +611,7 @@ static struct s3c2410_platform_nand rx19
 	.twrph1 = 15,
 	.nr_sets = ARRAY_SIZE(rx1950_nand_sets),
 	.sets = rx1950_nand_sets,
+	.ecc_mode = NAND_ECC_SOFT,
 };
 
 static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-rx3715.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-rx3715.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-rx3715.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-rx3715.c	2017-02-12 16:03:20.000000000 -0500
@@ -164,6 +164,7 @@ static struct s3c2410_platform_nand __in
 	.twrph1		= 15,
 	.nr_sets	= ARRAY_SIZE(rx3715_nand_sets),
 	.sets		= rx3715_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *rx3715_devices[] __initdata = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-vstms.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-vstms.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c24xx/mach-vstms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c24xx/mach-vstms.c	2017-02-12 16:03:20.000000000 -0500
@@ -117,6 +117,7 @@ static struct s3c2410_platform_nand __in
 	.twrph1		= 20,
 	.nr_sets	= ARRAY_SIZE(vstms_nand_sets),
 	.sets		= vstms_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *vstms_devices[] __initdata = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/mach-hmt.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/mach-hmt.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/mach-hmt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/mach-hmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -204,6 +204,7 @@ static struct s3c2410_platform_nand hmt_
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(hmt_nand_sets),
 	.sets		= hmt_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct gpio_led hmt_leds[] = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/mach-mini6410.c	2017-02-12 16:03:20.000000000 -0500
@@ -142,6 +142,7 @@ static struct s3c2410_platform_nand mini
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(mini6410_nand_sets),
 	.sets		= mini6410_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/mach-real6410.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/mach-real6410.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/mach-real6410.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/mach-real6410.c	2017-02-12 16:03:20.000000000 -0500
@@ -194,6 +194,7 @@ static struct s3c2410_platform_nand real
 	.twrph1		= 40,
 	.nr_sets	= ARRAY_SIZE(real6410_nand_sets),
 	.sets		= real6410_nand_sets,
+	.ecc_mode       = NAND_ECC_SOFT,
 };
 
 static struct platform_device *real6410_devices[] __initdata = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/pl080.c linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/pl080.c
--- linux-libre-4.9-gnu/arch/arm/mach-s3c64xx/pl080.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-s3c64xx/pl080.c	2017-02-12 16:03:20.000000000 -0500
@@ -117,6 +117,25 @@ static struct pl08x_channel_data s3c64xx
 	}
 };
 
+static const struct dma_slave_map s3c64xx_dma0_slave_map[] = {
+	{ "s3c6400-uart.0", "tx", &s3c64xx_dma0_info[0] },
+	{ "s3c6400-uart.0", "rx", &s3c64xx_dma0_info[1] },
+	{ "s3c6400-uart.1", "tx", &s3c64xx_dma0_info[2] },
+	{ "s3c6400-uart.1", "rx", &s3c64xx_dma0_info[3] },
+	{ "s3c6400-uart.2", "tx", &s3c64xx_dma0_info[4] },
+	{ "s3c6400-uart.2", "rx", &s3c64xx_dma0_info[5] },
+	{ "s3c6400-uart.3", "tx", &s3c64xx_dma0_info[6] },
+	{ "s3c6400-uart.3", "rx", &s3c64xx_dma0_info[7] },
+	{ "samsung-pcm.0", "tx", &s3c64xx_dma0_info[8] },
+	{ "samsung-pcm.0", "rx", &s3c64xx_dma0_info[9] },
+	{ "samsung-i2s.0", "tx", &s3c64xx_dma0_info[10] },
+	{ "samsung-i2s.0", "rx", &s3c64xx_dma0_info[11] },
+	{ "s3c6410-spi.0", "tx", &s3c64xx_dma0_info[12] },
+	{ "s3c6410-spi.0", "rx", &s3c64xx_dma0_info[13] },
+	{ "samsung-i2s.2", "tx", &s3c64xx_dma0_info[14] },
+	{ "samsung-i2s.2", "rx", &s3c64xx_dma0_info[15] },
+};
+
 struct pl08x_platform_data s3c64xx_dma0_plat_data = {
 	.memcpy_channel = {
 		.bus_id = "memcpy",
@@ -134,6 +153,8 @@ struct pl08x_platform_data s3c64xx_dma0_
 	.put_xfer_signal = pl08x_put_xfer_signal,
 	.slave_channels = s3c64xx_dma0_info,
 	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma0_info),
+	.slave_map = s3c64xx_dma0_slave_map,
+	.slave_map_len = ARRAY_SIZE(s3c64xx_dma0_slave_map),
 };
 
 static AMBA_AHB_DEVICE(s3c64xx_dma0, "dma-pl080s.0", 0,
@@ -207,6 +228,15 @@ static struct pl08x_channel_data s3c64xx
 	},
 };
 
+static const struct dma_slave_map s3c64xx_dma1_slave_map[] = {
+	{ "samsung-pcm.1", "tx", &s3c64xx_dma1_info[0] },
+	{ "samsung-pcm.1", "rx", &s3c64xx_dma1_info[1] },
+	{ "samsung-i2s.1", "tx", &s3c64xx_dma1_info[2] },
+	{ "samsung-i2s.1", "rx", &s3c64xx_dma1_info[3] },
+	{ "s3c6410-spi.1", "tx", &s3c64xx_dma1_info[4] },
+	{ "s3c6410-spi.1", "rx", &s3c64xx_dma1_info[5] },
+};
+
 struct pl08x_platform_data s3c64xx_dma1_plat_data = {
 	.memcpy_channel = {
 		.bus_id = "memcpy",
@@ -224,6 +254,8 @@ struct pl08x_platform_data s3c64xx_dma1_
 	.put_xfer_signal = pl08x_put_xfer_signal,
 	.slave_channels = s3c64xx_dma1_info,
 	.num_slave_channels = ARRAY_SIZE(s3c64xx_dma1_info),
+	.slave_map = s3c64xx_dma1_slave_map,
+	.slave_map_len = ARRAY_SIZE(s3c64xx_dma1_slave_map),
 };
 
 static AMBA_AHB_DEVICE(s3c64xx_dma1, "dma-pl080s.1", 0,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-sa1100/generic.c linux-libre-4.10-rc8-gnu/arch/arm/mach-sa1100/generic.c
--- linux-libre-4.9-gnu/arch/arm/mach-sa1100/generic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-sa1100/generic.c	2017-02-12 16:03:20.000000000 -0500
@@ -378,7 +378,7 @@ void __init sa1100_map_io(void)
 
 void __init sa1100_timer_init(void)
 {
-	pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000), 3686400);
+	pxa_timer_nodt_init(IRQ_OST0, io_p2v(0x90000000));
 }
 
 static struct resource irq_resource =
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-sa1100/include/mach/hardware.h linux-libre-4.10-rc8-gnu/arch/arm/mach-sa1100/include/mach/hardware.h
--- linux-libre-4.9-gnu/arch/arm/mach-sa1100/include/mach/hardware.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-sa1100/include/mach/hardware.h	2017-02-12 16:03:20.000000000 -0500
@@ -43,10 +43,6 @@
 # define __REG(x)	(*((volatile unsigned long __iomem *)io_p2v(x)))
 # define __PREG(x)	(io_v2p((unsigned long)&(x)))
 
-static inline unsigned long get_clock_tick_rate(void)
-{
-	return 3686400;
-}
 #else
 
 # define __REG(x)	io_p2v(x)
@@ -56,8 +52,4 @@ static inline unsigned long get_clock_ti
 
 #include "SA-1100.h"
 
-#ifdef CONFIG_SA1101
-#include "SA-1101.h"
-#endif
-
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-sa1100/include/mach/SA-1101.h linux-libre-4.10-rc8-gnu/arch/arm/mach-sa1100/include/mach/SA-1101.h
--- linux-libre-4.9-gnu/arch/arm/mach-sa1100/include/mach/SA-1101.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-sa1100/include/mach/SA-1101.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,925 +0,0 @@
-/*
- * SA-1101.h
- *
- * Copyright (c) Peter Danielsson 1999
- *
- * Definition of constants related to the sa1101
- * support chip for the sa1100
- *
- */
-
-
-/* Be sure that virtual mapping is defined right */
-#ifndef __ASM_ARCH_HARDWARE_H
-#error You must include hardware.h not SA-1101.h
-#endif
-
-#ifndef SA1101_BASE
-#error You must define SA-1101 physical base address
-#endif
-
-#ifndef LANGUAGE
-# ifdef __ASSEMBLY__
-#  define LANGUAGE Assembly
-# else
-#  define LANGUAGE C
-# endif
-#endif
-
-/*
- * We have mapped the sa1101 depending on the value of SA1101_BASE.
- * It then appears from 0xf4000000.
- */
-
-#define SA1101_p2v( x )         ((x) - SA1101_BASE + 0xf4000000)
-#define SA1101_v2p( x )         ((x) - 0xf4000000  + SA1101_BASE)
-
-#ifndef SA1101_p2v
-#define SA1101_p2v(PhAdd)  (PhAdd)
-#endif
-
-#include <mach/bitfield.h>
-
-#define C               0
-#define Assembly        1
-
-
-/*
- * Memory map
- */
-
-#define __SHMEM_CONTROL0	0x00000000
-#define __SYSTEM_CONTROL1	0x00000400
-#define __ARBITER		0x00020000
-#define __SYSTEM_CONTROL2	0x00040000
-#define __SYSTEM_CONTROL3	0x00060000
-#define __PARALLEL_PORT		0x00080000
-#define __VIDMEM_CONTROL	0x00100000
-#define __UPDATE_FIFO		0x00120000
-#define __SHMEM_CONTROL1	0x00140000
-#define __INTERRUPT_CONTROL	0x00160000
-#define __USB_CONTROL		0x00180000
-#define __TRACK_INTERFACE	0x001a0000
-#define __MOUSE_INTERFACE	0x001b0000
-#define __KEYPAD_INTERFACE	0x001c0000
-#define __PCMCIA_INTERFACE	0x001e0000
-#define	__VGA_CONTROL		0x00200000
-#define __GPIO_INTERFACE	0x00300000
-
-/*
- * Macro that calculates real address for registers in the SA-1101
- */
-
-#define _SA1101( x )    ((x) + SA1101_BASE)
-
-/*
- * Interface and shared memory controller registers
- *
- * Registers
- *	SKCR		SA-1101 control register (read/write)
- *	SMCR		Shared Memory Controller Register
- *	SNPR		Snoop Register
- */
-
-#define _SKCR		_SA1101( 0x00000000 ) /* SA-1101 Control Reg. */
-#define _SMCR		_SA1101( 0x00140000 ) /* Shared Mem. Control Reg. */
-#define _SNPR		_SA1101( 0x00140400 ) /* Snoop Reg. */
-
-#if LANGUAGE == C
-#define SKCR		(*((volatile Word *) SA1101_p2v (_SKCR)))
-#define SMCR		(*((volatile Word *) SA1101_p2v (_SMCR)))
-#define SNPR		(*((volatile Word *) SA1101_p2v (_SNPR)))
-
-#define SKCR_PLLEn	  0x0001	  /* Enable On-Chip PLL */
-#define SKCR_BCLKEn	  0x0002	  /* Enables BCLK */
-#define SKCR_Sleep	  0x0004	  /* Sleep Mode */
-#define SKCR_IRefEn	  0x0008	  /* DAC Iref input enable */
-#define SKCR_VCOON	  0x0010	  /* VCO bias */
-#define SKCR_ScanTestEn	  0x0020	  /* Enables scan test */
-#define SKCR_ClockTestEn  0x0040	  /* Enables clock test */
-
-#define SMCR_DCAC	  Fld(2,0)	  /* Number of column address bits */
-#define SMCR_DRAC	  Fld(2,2)	  /* Number of row address bits */
-#define SMCR_ArbiterBias  0x0008	  /* favor video or USB */
-#define SMCR_TopVidMem	  Fld(4,5)	  /* Top 4 bits of vidmem addr. */
-
-#define SMCR_ColAdrBits( x )		  /* col. addr bits 8..11 */ \
-	(( (x) - 8 ) << FShft (SMCR_DCAC))
-#define SMCR_RowAdrBits( x )		  /* row addr bits 9..12 */\
-	(( (x) - 9 ) << FShft (SMCR_DRAC))
-
-#define SNPR_VFBstart	  Fld(12,0)	/* Video frame buffer addr */
-#define SNPR_VFBsize	  Fld(11,12)	/* Video frame buffer size */
-#define SNPR_WholeBank	  (1 << 23)	/* Whole bank bit */
-#define SNPR_BankSelect	  Fld(2,27)	/* Bank select */
-#define SNPR_SnoopEn	  (1 << 31)	/* Enable snoop operation */
-
-#define SNPR_Set_VFBsize( x )   /* set frame buffer size (in kb) */ \
-	( (x) << FShft (SNPR_VFBsize))
-#define SNPR_Select_Bank(x)     /* select bank 0 or 1 */  \
-	(( (x) + 1 ) << FShft (SNPR_BankSelect ))
-
-#endif /* LANGUAGE == C */
-
-/*
- * Video Memory Controller
- *
- * Registers
- *    VMCCR	Configuration register
- *    VMCAR	VMC address register
- *    VMCDR	VMC data register
- *
- */
-
-#define _VMCCR		_SA1101( 0x00100000 )	/* Configuration register */
-#define _VMCAR		_SA1101( 0x00101000 )	/* VMC address register */
-#define _VMCDR		_SA1101( 0x00101400 )	/* VMC data register */
-
-#if LANGUAGE == C
-#define VMCCR		(*((volatile Word *) SA1101_p2v (_VMCCR)))
-#define VMCAR		(*((volatile Word *) SA1101_p2v (_VMCAR)))
-#define VMCDR		(*((volatile Word *) SA1101_p2v (_VMCDR)))
-
-#define VMCCR_RefreshEn	    0x0000	  /* Enable memory refresh */
-#define VMCCR_Config	    0x0001	  /* DRAM size */
-#define VMCCR_RefPeriod	    Fld(2,3)	  /* Refresh period */
-#define VMCCR_StaleDataWait Fld(4,5)	  /* Stale FIFO data timeout counter */
-#define VMCCR_SleepState    (1<<9)	  /* State of interface pins in sleep*/
-#define VMCCR_RefTest	    (1<<10)	  /* refresh test */
-#define VMCCR_RefLow	    Fld(6,11)	  /* refresh low counter */
-#define VMCCR_RefHigh	    Fld(7,17)	  /* refresh high counter */
-#define VMCCR_SDTCTest	    Fld(7,24)	  /* stale data timeout counter */
-#define VMCCR_ForceSelfRef  (1<<31)	  /* Force self refresh */
-
-#endif LANGUAGE == C
-
-
-/* Update FIFO
- *
- * Registers
- *    UFCR	Update FIFO Control Register
- *    UFSR	Update FIFO Status Register
- *    UFLVLR	update FIFO level register
- *    UFDR	update FIFO data register
- */
-
-#define _UFCR	_SA1101(0x00120000)   /* Update FIFO Control Reg. */
-#define _UFSR	_SA1101(0x00120400)   /* Update FIFO Status Reg. */	
-#define _UFLVLR	_SA1101(0x00120800)   /* Update FIFO level reg. */
-#define _UFDR	_SA1101(0x00120c00)   /* Update FIFO data reg. */
-
-#if LANGUAGE == C
-
-#define UFCR 	(*((volatile Word *) SA1101_p2v (_UFCR)))
-#define UFSR	(*((volatile Word *) SA1101_p2v (_UFSR)))
-#define UFLVLR	(*((volatile Word *) SA1101_p2v (_UFLVLR))) 
-#define UFDR	(*((volatile Word *) SA1101_p2v (_UFDR)))
-
-
-#define UFCR_FifoThreshhold	Fld(7,0)	/* Level for FifoGTn flag */
-
-#define UFSR_FifoGTnFlag	0x01		/* FifoGTn flag */#define UFSR_FifoEmpty		0x80		/* FIFO is empty */
-
-#endif /* LANGUAGE == C */
-
-/* System Controller
- *
- * Registers
- *    SKPCR	Power Control Register
- *    SKCDR	Clock Divider Register
- *    DACDR1	DAC1 Data register
- *    DACDR2	DAC2 Data register
- */
-
-#define _SKPCR		_SA1101(0x00000400)
-#define _SKCDR		_SA1101(0x00040000)
-#define _DACDR1		_SA1101(0x00060000)
-#define _DACDR2		_SA1101(0x00060400)
-
-#if LANGUAGE == C
-#define SKPCR 	(*((volatile Word *) SA1101_p2v (_SKPCR)))
-#define SKCDR	(*((volatile Word *) SA1101_p2v (_SKCDR)))
-#define DACDR1	(*((volatile Word *) SA1101_p2v (_DACDR1)))
-#define DACDR2	(*((volatile Word *) SA1101_p2v (_DACDR2)))
-
-#define SKPCR_UCLKEn	     0x01    /* USB Enable */
-#define SKPCR_PCLKEn	     0x02    /* PS/2 Enable */
-#define SKPCR_ICLKEn	     0x04    /* Interrupt Controller Enable */
-#define SKPCR_VCLKEn	     0x08    /* Video Controller Enable */
-#define SKPCR_PICLKEn	     0x10    /* parallel port Enable */
-#define SKPCR_DCLKEn	     0x20    /* DACs Enable */
-#define SKPCR_nKPADEn	     0x40    /* Multiplexer */
-
-#define SKCDR_PLLMul	     Fld(7,0)	/* PLL Multiplier */
-#define SKCDR_VCLKEn	     Fld(2,7)	/* Video controller clock divider */
-#define SKDCR_BCLKEn	     (1<<9)	/* BCLK Divider */
-#define SKDCR_UTESTCLKEn     (1<<10)	/* Route USB clock during test mode */
-#define SKDCR_DivRValue	     Fld(6,11)	/* Input clock divider for PLL */
-#define SKDCR_DivNValue	     Fld(5,17)	/* Output clock divider for PLL */
-#define SKDCR_PLLRSH	     Fld(3,22)	/* PLL bandwidth control */
-#define SKDCR_ChargePump     (1<<25)	/* Charge pump control */
-#define SKDCR_ClkTestMode    (1<<26)	/* Clock output test mode */
-#define SKDCR_ClkTestEn	     (1<<27)	/* Test clock generator */
-#define SKDCR_ClkJitterCntl  Fld(3,28)	/* video clock jitter compensation */
-
-#define DACDR_DACCount	     Fld(8,0)	/* Count value */
-#define DACDR1_DACCount	     DACDR_DACCount
-#define DACDR2_DACCount	     DACDR_DACCount
-
-#endif /* LANGUAGE == C */
-
-/*
- * Parallel Port Interface
- *
- * Registers
- *    IEEE_Config	IEEE mode selection and programmable attributes
- *    IEEE_Control	Controls the states of IEEE port control outputs
- *    IEEE_Data		Forward transfer data register
- *    IEEE_Addr		Forward transfer address register
- *    IEEE_Status	Port IO signal status register
- *    IEEE_IntStatus	Port interrupts status register
- *    IEEE_FifoLevels   Rx and Tx FIFO interrupt generation levels
- *    IEEE_InitTime	Forward timeout counter initial value
- *    IEEE_TimerStatus	Forward timeout counter current value
- *    IEEE_FifoReset	Reset forward transfer FIFO
- *    IEEE_ReloadValue	Counter reload value
- *    IEEE_TestControl	Control testmode
- *    IEEE_TestDataIn	Test data register
- *    IEEE_TestDataInEn	Enable test data
- *    IEEE_TestCtrlIn	Test control signals
- *    IEEE_TestCtrlInEn	Enable test control signals
- *    IEEE_TestDataStat	Current data bus value
- *
- */
-
-/*
- * The control registers are defined as offsets from a base address 
- */
- 
-#define _IEEE( x ) _SA1101( (x) + __PARALLEL_PORT )
-
-#define _IEEE_Config	    _IEEE( 0x0000 )
-#define _IEEE_Control	    _IEEE( 0x0400 )
-#define _IEEE_Data	    _IEEE( 0x4000 )
-#define _IEEE_Addr	    _IEEE( 0x0800 )
-#define _IEEE_Status	    _IEEE( 0x0c00 )
-#define _IEEE_IntStatus	    _IEEE( 0x1000 )
-#define _IEEE_FifoLevels    _IEEE( 0x1400 )
-#define _IEEE_InitTime	    _IEEE( 0x1800 )
-#define _IEEE_TimerStatus   _IEEE( 0x1c00 )
-#define _IEEE_FifoReset	    _IEEE( 0x2000 )
-#define _IEEE_ReloadValue   _IEEE( 0x3c00 )
-#define _IEEE_TestControl   _IEEE( 0x2400 )
-#define _IEEE_TestDataIn    _IEEE( 0x2800 )
-#define _IEEE_TestDataInEn  _IEEE( 0x2c00 )
-#define _IEEE_TestCtrlIn    _IEEE( 0x3000 )
-#define _IEEE_TestCtrlInEn  _IEEE( 0x3400 )
-#define _IEEE_TestDataStat  _IEEE( 0x3800 )
- 
-
-#if LANGUAGE == C
-#define IEEE_Config	    (*((volatile Word *) SA1101_p2v (_IEEE_Config)))
-#define IEEE_Control	    (*((volatile Word *) SA1101_p2v (_IEEE_Control)))
-#define IEEE_Data	    (*((volatile Word *) SA1101_p2v (_IEEE_Data)))
-#define IEEE_Addr	    (*((volatile Word *) SA1101_p2v (_IEEE_Addr)))
-#define IEEE_Status	    (*((volatile Word *) SA1101_p2v (_IEEE_Status)))
-#define IEEE_IntStatus	    (*((volatile Word *) SA1101_p2v (_IEEE_IntStatus)))
-#define IEEE_FifoLevels	    (*((volatile Word *) SA1101_p2v (_IEEE_FifoLevels)))
-#define IEEE_InitTime	    (*((volatile Word *) SA1101_p2v (_IEEE_InitTime)))
-#define IEEE_TimerStatus    (*((volatile Word *) SA1101_p2v (_IEEE_TimerStatus)))
-#define IEEE_FifoReset	    (*((volatile Word *) SA1101_p2v (_IEEE_FifoReset)))
-#define IEEE_ReloadValue    (*((volatile Word *) SA1101_p2v (_IEEE_ReloadValue)))
-#define IEEE_TestControl    (*((volatile Word *) SA1101_p2v (_IEEE_TestControl)))
-#define IEEE_TestDataIn     (*((volatile Word *) SA1101_p2v (_IEEE_TestDataIn)))
-#define IEEE_TestDataInEn   (*((volatile Word *) SA1101_p2v (_IEEE_TestDataInEn)))
-#define IEEE_TestCtrlIn     (*((volatile Word *) SA1101_p2v (_IEEE_TestCtrlIn)))
-#define IEEE_TestCtrlInEn   (*((volatile Word *) SA1101_p2v (_IEEE_TestCtrlInEn)))
-#define IEEE_TestDataStat   (*((volatile Word *) SA1101_p2v (_IEEE_TestDataStat)))
-
-
-#define IEEE_Config_M	    Fld(3,0)	 /* Mode select */
-#define IEEE_Config_D	    0x04	 /* FIFO access enable */
-#define IEEE_Config_B	    0x08	 /* 9-bit word enable */
-#define IEEE_Config_T	    0x10	 /* Data transfer enable */
-#define IEEE_Config_A	    0x20	 /* Data transfer direction */
-#define IEEE_Config_E	    0x40	 /* Timer enable */
-#define IEEE_Control_A	    0x08	 /* AutoFd output */
-#define IEEE_Control_E	    0x04	 /* Selectin output */
-#define IEEE_Control_T	    0x02	 /* Strobe output */
-#define IEEE_Control_I	    0x01	 /* Port init output */
-#define IEEE_Data_C	    (1<<31)	 /* Byte count */
-#define IEEE_Data_Db	    Fld(9,16)	 /* Data byte 2 */
-#define IEEE_Data_Da	    Fld(9,0)	 /* Data byte 1 */
-#define IEEE_Addr_A	    Fld(8,0)	 /* forward address transfer byte */
-#define IEEE_Status_A	    0x0100	 /* nAutoFd port output status */
-#define IEEE_Status_E	    0x0080	 /* nSelectIn port output status */
-#define IEEE_Status_T	    0x0040	 /* nStrobe port output status */
-#define IEEE_Status_I	    0x0020	 /* nInit port output status */
-#define IEEE_Status_B	    0x0010	 /* Busy port inout status */
-#define IEEE_Status_S	    0x0008	 /* Select port input status */
-#define IEEE_Status_K	    0x0004	 /* nAck port input status */
-#define IEEE_Status_F	    0x0002	 /* nFault port input status */
-#define IEEE_Status_R	    0x0001	 /* pError port input status */
-
-#define IEEE_IntStatus_IntReqDat	 0x0100
-#define IEEE_IntStatus_IntReqEmp	 0x0080
-#define IEEE_IntStatus_IntReqInt	 0x0040
-#define IEEE_IntStatus_IntReqRav	 0x0020
-#define IEEE_IntStatus_IntReqTim	 0x0010
-#define IEEE_IntStatus_RevAddrComp	 0x0008
-#define IEEE_IntStatus_RevDataComp	 0x0004
-#define IEEE_IntStatus_FwdAddrComp	 0x0002
-#define IEEE_IntStatus_FwdDataComp	 0x0001
-#define IEEE_FifoLevels_RevFifoLevel	 2
-#define IEEE_FifoLevels_FwdFifoLevel	 1
-#define IEEE_InitTime_TimValInit	 Fld(22,0)
-#define IEEE_TimerStatus_TimValStat	 Fld(22,0)
-#define IEEE_ReloadValue_Reload		 Fld(4,0)
-
-#define IEEE_TestControl_RegClk		 0x04
-#define IEEE_TestControl_ClockSelect	 Fld(2,1)
-#define IEEE_TestControl_TimerTestModeEn 0x01
-#define IEEE_TestCtrlIn_PError		 0x10
-#define IEEE_TestCtrlIn_nFault		 0x08
-#define IEEE_TestCtrlIn_nAck		 0x04
-#define IEEE_TestCtrlIn_PSel		 0x02
-#define IEEE_TestCtrlIn_Busy		 0x01
-
-#endif /* LANGUAGE == C */
-
-/*
- * VGA Controller
- *
- * Registers
- *    VideoControl	Video Control Register
- *    VgaTiming0	VGA Timing Register 0
- *    VgaTiming1	VGA Timing Register 1
- *    VgaTiming2	VGA Timing Register 2
- *    VgaTiming3	VGA Timing Register 3
- *    VgaBorder		VGA Border Color Register
- *    VgaDBAR		VGADMA Base Address Register
- *    VgaDCAR		VGADMA Channel Current Address Register
- *    VgaStatus		VGA Status Register
- *    VgaInterruptMask	VGA Interrupt Mask Register
- *    VgaPalette	VGA Palette Registers
- *    DacControl	DAC Control Register
- *    VgaTest		VGA Controller Test Register
- */
-
-#define _VGA( x )	_SA1101( ( x ) + __VGA_CONTROL )
-
-#define _VideoControl	    _VGA( 0x0000 )
-#define _VgaTiming0	    _VGA( 0x0400 )
-#define _VgaTiming1	    _VGA( 0x0800 )
-#define _VgaTiming2	    _VGA( 0x0c00 )
-#define _VgaTiming3	    _VGA( 0x1000 )
-#define _VgaBorder	    _VGA( 0x1400 )
-#define _VgaDBAR	    _VGA( 0x1800 )
-#define _VgaDCAR	    _VGA( 0x1c00 )
-#define _VgaStatus	    _VGA( 0x2000 )
-#define _VgaInterruptMask   _VGA( 0x2400 )
-#define _VgaPalette	    _VGA( 0x40000 )
-#define _DacControl	    _VGA( 0x3000 )
-#define _VgaTest	    _VGA( 0x2c00 )
-
-#if (LANGUAGE == C)
-#define VideoControl   (*((volatile Word *) SA1101_p2v (_VideoControl)))
-#define VgaTiming0     (*((volatile Word *) SA1101_p2v (_VgaTiming0)))
-#define VgaTiming1     (*((volatile Word *) SA1101_p2v (_VgaTiming1)))
-#define VgaTiming2     (*((volatile Word *) SA1101_p2v (_VgaTiming2)))
-#define VgaTiming3     (*((volatile Word *) SA1101_p2v (_VgaTiming3)))
-#define VgaBorder      (*((volatile Word *) SA1101_p2v (_VgaBorder)))
-#define VgaDBAR	       (*((volatile Word *) SA1101_p2v (_VgaDBAR)))
-#define VgaDCAR	       (*((volatile Word *) SA1101_p2v (_VgaDCAR)))
-#define VgaStatus      (*((volatile Word *) SA1101_p2v (_VgaStatus)))
-#define VgaInterruptMask (*((volatile Word *) SA1101_p2v (_VgaInterruptMask)))
-#define VgaPalette     (*((volatile Word *) SA1101_p2v (_VgaPalette)))
-#define DacControl     (*((volatile Word *) SA1101_p2v (_DacControl)))
-#define VgaTest        (*((volatile Word *) SA1101_p2v (_VgaTest)))
-
-#define VideoControl_VgaEn    0x00000000
-#define VideoControl_BGR      0x00000001
-#define VideoControl_VCompVal Fld(2,2)
-#define VideoControl_VgaReq   Fld(4,4)
-#define VideoControl_VBurstL  Fld(4,8)
-#define VideoControl_VMode    (1<<12)
-#define VideoControl_PalRead  (1<<13)
-
-#define VgaTiming0_PPL	      Fld(6,2)
-#define VgaTiming0_HSW	      Fld(8,8)
-#define VgaTiming0_HFP	      Fld(8,16)
-#define VgaTiming0_HBP	      Fld(8,24)
-
-#define VgaTiming1_LPS	      Fld(10,0)
-#define VgaTiming1_VSW	      Fld(6,10)
-#define VgaTiming1_VFP	      Fld(8,16)
-#define VgaTiming1_VBP	      Fld(8,24)
-
-#define VgaTiming2_IVS	      0x01
-#define VgaTiming2_IHS	      0x02
-#define VgaTiming2_CVS	      0x04
-#define VgaTiming2_CHS	      0x08
-
-#define VgaTiming3_HBS	      Fld(8,0)
-#define VgaTiming3_HBE	      Fld(8,8)
-#define VgaTiming3_VBS	      Fld(8,16)
-#define VgaTiming3_VBE	      Fld(8,24)
-
-#define VgaBorder_BCOL	      Fld(24,0)
-
-#define VgaStatus_VFUF	      0x01
-#define VgaStatus_VNext	      0x02
-#define VgaStatus_VComp	      0x04
-
-#define VgaInterruptMask_VFUFMask   0x00
-#define VgaInterruptMask_VNextMask  0x01
-#define VgaInterruptMask_VCompMask  0x02
-
-#define VgaPalette_R	      Fld(8,0)
-#define VgaPalette_G	      Fld(8,8)
-#define VgaPalette_B	      Fld(8,16)
-
-#define DacControl_DACON      0x0001
-#define DacControl_COMPON     0x0002
-#define DacControl_PEDON      0x0004
-#define DacControl_RTrim      Fld(5,4)
-#define DacControl_GTrim      Fld(5,9)
-#define DacControl_BTrim      Fld(5,14)
-
-#define VgaTest_TDAC	      0x00
-#define VgaTest_Datatest      Fld(4,1)
-#define VgaTest_DACTESTDAC    0x10
-#define VgaTest_DACTESTOUT    Fld(3,5)
-
-#endif /* LANGUAGE == C */
-
-/*
- * USB Host Interface Controller
- *
- * Registers
- *    Revision
- *    Control
- *    CommandStatus
- *    InterruptStatus
- *    InterruptEnable
- *    HCCA
- *    PeriodCurrentED
- *    ControlHeadED
- *    BulkHeadED
- *    BulkCurrentED
- *    DoneHead
- *    FmInterval
- *    FmRemaining
- *    FmNumber
- *    PeriodicStart
- *    LSThreshold
- *    RhDescriptorA
- *    RhDescriptorB
- *    RhStatus
- *    RhPortStatus
- *    USBStatus
- *    USBReset
- *    USTAR
- *    USWER
- *    USRFR
- *    USNFR
- *    USTCSR
- *    USSR
- *    
- */
-
-#define _USB( x )	_SA1101( ( x ) + __USB_CONTROL )
-
-
-#define _Revision	  _USB( 0x0000 )
-#define _Control	  _USB( 0x0888 )
-#define _CommandStatus	  _USB( 0x0c00 )
-#define _InterruptStatus  _USB( 0x1000 )
-#define _InterruptEnable  _USB( 0x1400 )
-#define _HCCA		  _USB( 0x1800 )
-#define _PeriodCurrentED  _USB( 0x1c00 )
-#define _ControlHeadED	  _USB( 0x2000 )
-#define _BulkHeadED	  _USB( 0x2800 )
-#define _BulkCurrentED	  _USB( 0x2c00 )
-#define _DoneHead	  _USB( 0x3000 )
-#define _FmInterval	  _USB( 0x3400 )
-#define _FmRemaining	  _USB( 0x3800 )
-#define _FmNumber	  _USB( 0x3c00 )
-#define _PeriodicStart	  _USB( 0x4000 )
-#define _LSThreshold	  _USB( 0x4400 )
-#define _RhDescriptorA	  _USB( 0x4800 )
-#define _RhDescriptorB	  _USB( 0x4c00 )
-#define _RhStatus	  _USB( 0x5000 )
-#define _RhPortStatus	  _USB( 0x5400 )
-#define _USBStatus	  _USB( 0x11800 )
-#define _USBReset	  _USB( 0x11c00 )
-
-#define _USTAR		  _USB( 0x10400 )
-#define _USWER		  _USB( 0x10800 )
-#define _USRFR		  _USB( 0x10c00 )
-#define _USNFR		  _USB( 0x11000 )
-#define _USTCSR		  _USB( 0x11400 )
-#define _USSR		  _USB( 0x11800 )
-
-
-#if (LANGUAGE == C)
-
-#define Revision	(*((volatile Word *) SA1101_p2v (_Revision)))
-#define Control		(*((volatile Word *) SA1101_p2v (_Control)))
-#define CommandStatus	(*((volatile Word *) SA1101_p2v (_CommandStatus)))
-#define InterruptStatus	(*((volatile Word *) SA1101_p2v (_InterruptStatus)))
-#define InterruptEnable	(*((volatile Word *) SA1101_p2v (_InterruptEnable)))
-#define HCCA		(*((volatile Word *) SA1101_p2v (_HCCA)))
-#define PeriodCurrentED	(*((volatile Word *) SA1101_p2v (_PeriodCurrentED)))
-#define ControlHeadED	(*((volatile Word *) SA1101_p2v (_ControlHeadED)))
-#define BulkHeadED	(*((volatile Word *) SA1101_p2v (_BulkHeadED)))
-#define BulkCurrentED	(*((volatile Word *) SA1101_p2v (_BulkCurrentED)))
-#define DoneHead	(*((volatile Word *) SA1101_p2v (_DoneHead)))
-#define FmInterval	(*((volatile Word *) SA1101_p2v (_FmInterval)))
-#define FmRemaining	(*((volatile Word *) SA1101_p2v (_FmRemaining)))
-#define FmNumber	(*((volatile Word *) SA1101_p2v (_FmNumber)))
-#define PeriodicStart	(*((volatile Word *) SA1101_p2v (_PeriodicStart)))
-#define LSThreshold	(*((volatile Word *) SA1101_p2v (_LSThreshold)))
-#define RhDescriptorA	(*((volatile Word *) SA1101_p2v (_RhDescriptorA)))
-#define RhDescriptorB	(*((volatile Word *) SA1101_p2v (_RhDescriptorB)))
-#define RhStatus	(*((volatile Word *) SA1101_p2v (_RhStatus)))
-#define RhPortStatus	(*((volatile Word *) SA1101_p2v (_RhPortStatus)))
-#define USBStatus	(*((volatile Word *) SA1101_p2v (_USBStatus)))
-#define USBReset	(*((volatile Word *) SA1101_p2v (_USBReset)))
-#define USTAR		(*((volatile Word *) SA1101_p2v (_USTAR)))
-#define USWER		(*((volatile Word *) SA1101_p2v (_USWER)))
-#define USRFR		(*((volatile Word *) SA1101_p2v (_USRFR)))
-#define USNFR		(*((volatile Word *) SA1101_p2v (_USNFR)))
-#define USTCSR		(*((volatile Word *) SA1101_p2v (_USTCSR)))
-#define USSR		(*((volatile Word *) SA1101_p2v (_USSR)))
-
-
-#define USBStatus_IrqHciRmtWkp	     (1<<7)
-#define USBStatus_IrqHciBuffAcc	     (1<<8)
-#define USBStatus_nIrqHciM	     (1<<9)
-#define USBStatus_nHciMFClr	     (1<<10)
-
-#define USBReset_ForceIfReset	     0x01
-#define USBReset_ForceHcReset	     0x02
-#define USBReset_ClkGenReset	     0x04
-
-#define USTCR_RdBstCntrl	     Fld(3,0)
-#define USTCR_ByteEnable	     Fld(4,3)
-#define USTCR_WriteEn		     (1<<7)
-#define USTCR_FifoCir		     (1<<8)
-#define USTCR_TestXferSel	     (1<<9)
-#define USTCR_FifoCirAtEnd	     (1<<10)
-#define USTCR_nSimScaleDownClk	     (1<<11)
-
-#define USSR_nAppMDEmpty	     0x01
-#define USSR_nAppMDFirst	     0x02
-#define USSR_nAppMDLast		     0x04
-#define USSR_nAppMDFull		     0x08
-#define USSR_nAppMAFull		     0x10
-#define USSR_XferReq		     0x20
-#define USSR_XferEnd		     0x40
-
-#endif /* LANGUAGE == C */
-
-
-/*
- * Interrupt Controller
- *
- * Registers
- *    INTTEST0		Test register 0
- *    INTTEST1		Test register 1
- *    INTENABLE0	Interrupt Enable register 0
- *    INTENABLE1	Interrupt Enable register 1
- *    INTPOL0		Interrupt Polarity selection 0
- *    INTPOL1		Interrupt Polarity selection 1
- *    INTTSTSEL		Interrupt source selection
- *    INTSTATCLR0	Interrupt Status 0
- *    INTSTATCLR1	Interrupt Status 1
- *    INTSET0		Interrupt Set 0
- *    INTSET1		Interrupt Set 1
- */
-
-#define _INT( x )	_SA1101( ( x ) + __INTERRUPT_CONTROL)
-
-#define _INTTEST0	_INT( 0x1000 )
-#define _INTTEST1	_INT( 0x1400 )
-#define _INTENABLE0	_INT( 0x2000 )
-#define _INTENABLE1	_INT( 0x2400 )
-#define _INTPOL0	_INT( 0x3000 )
-#define _INTPOL1	_INT( 0x3400 )
-#define _INTTSTSEL     	_INT( 0x5000 )
-#define _INTSTATCLR0	_INT( 0x6000 )
-#define _INTSTATCLR1	_INT( 0x6400 )
-#define _INTSET0	_INT( 0x7000 )
-#define _INTSET1	_INT( 0x7400 )
-
-#if ( LANGUAGE == C )
-#define INTTEST0	(*((volatile Word *) SA1101_p2v (_INTTEST0)))
-#define INTTEST1	(*((volatile Word *) SA1101_p2v (_INTTEST1)))
-#define INTENABLE0	(*((volatile Word *) SA1101_p2v (_INTENABLE0)))
-#define INTENABLE1	(*((volatile Word *) SA1101_p2v (_INTENABLE1)))
-#define INTPOL0		(*((volatile Word *) SA1101_p2v (_INTPOL0)))
-#define INTPOL1		(*((volatile Word *) SA1101_p2v (_INTPOL1)))
-#define INTTSTSEL	(*((volatile Word *) SA1101_p2v (_INTTSTSEL)))
-#define INTSTATCLR0	(*((volatile Word *) SA1101_p2v (_INTSTATCLR0)))
-#define INTSTATCLR1	(*((volatile Word *) SA1101_p2v (_INTSTATCLR1)))
-#define INTSET0		(*((volatile Word *) SA1101_p2v (_INTSET0)))
-#define INTSET1		(*((volatile Word *) SA1101_p2v (_INTSET1)))
-
-#endif /* LANGUAGE == C */
-
-/*
- * PS/2 Trackpad and Mouse Interfaces
- *
- * Registers   (prefix kbd applies to trackpad interface, mse to mouse)
- *    KBDCR		Control Register
- *    KBDSTAT		Status Register
- *    KBDDATA		Transmit/Receive Data register
- *    KBDCLKDIV		Clock Division Register
- *    KBDPRECNT		Clock Precount Register
- *    KBDTEST1		Test register 1
- *    KBDTEST2		Test register 2
- *    KBDTEST3		Test register 3
- *    KBDTEST4		Test register 4
- *    MSECR	
- *    MSESTAT
- *    MSEDATA
- *    MSECLKDIV
- *    MSEPRECNT
- *    MSETEST1
- *    MSETEST2
- *    MSETEST3
- *    MSETEST4
- *     
- */
-
-#define _KBD( x )	_SA1101( ( x ) + __TRACK_INTERFACE )
-#define _MSE( x )	_SA1101( ( x ) + __MOUSE_INTERFACE )
-
-#define _KBDCR		_KBD( 0x0000 )
-#define _KBDSTAT	_KBD( 0x0400 )
-#define _KBDDATA	_KBD( 0x0800 )
-#define _KBDCLKDIV	_KBD( 0x0c00 )
-#define _KBDPRECNT	_KBD( 0x1000 )
-#define	_KBDTEST1	_KBD( 0x2000 )
-#define _KBDTEST2	_KBD( 0x2400 )
-#define _KBDTEST3	_KBD( 0x2800 )
-#define _KBDTEST4	_KBD( 0x2c00 )
-#define _MSECR		_MSE( 0x0000 )
-#define _MSESTAT	_MSE( 0x0400 )
-#define _MSEDATA	_MSE( 0x0800 )
-#define _MSECLKDIV	_MSE( 0x0c00 )
-#define _MSEPRECNT	_MSE( 0x1000 )
-#define	_MSETEST1	_MSE( 0x2000 )
-#define _MSETEST2	_MSE( 0x2400 )
-#define _MSETEST3	_MSE( 0x2800 )
-#define _MSETEST4	_MSE( 0x2c00 )
-
-#if ( LANGUAGE == C )
-
-#define KBDCR	    (*((volatile Word *) SA1101_p2v (_KBDCR)))
-#define KBDSTAT	    (*((volatile Word *) SA1101_p2v (_KBDSTAT)))
-#define KBDDATA	    (*((volatile Word *) SA1101_p2v (_KBDDATA)))
-#define KBDCLKDIV   (*((volatile Word *) SA1101_p2v (_KBDCLKDIV)))
-#define KBDPRECNT   (*((volatile Word *) SA1101_p2v (_KBDPRECNT)))
-#define KBDTEST1    (*((volatile Word *) SA1101_p2v (_KBDTEST1)))
-#define KBDTEST2    (*((volatile Word *) SA1101_p2v (_KBDTEST2)))
-#define KBDTEST3    (*((volatile Word *) SA1101_p2v (_KBDTEST3)))
-#define KBDTEST4    (*((volatile Word *) SA1101_p2v (_KBDTEST4)))
-#define MSECR	    (*((volatile Word *) SA1101_p2v (_MSECR)))
-#define MSESTAT	    (*((volatile Word *) SA1101_p2v (_MSESTAT)))
-#define MSEDATA	    (*((volatile Word *) SA1101_p2v (_MSEDATA)))
-#define MSECLKDIV   (*((volatile Word *) SA1101_p2v (_MSECLKDIV)))
-#define MSEPRECNT   (*((volatile Word *) SA1101_p2v (_MSEPRECNT)))
-#define MSETEST1    (*((volatile Word *) SA1101_p2v (_MSETEST1)))
-#define MSETEST2    (*((volatile Word *) SA1101_p2v (_MSETEST2)))
-#define MSETEST3    (*((volatile Word *) SA1101_p2v (_MSETEST3)))
-#define MSETEST4    (*((volatile Word *) SA1101_p2v (_MSETEST4)))
-
-
-#define KBDCR_ENA		 0x08
-#define KBDCR_FKD		 0x02
-#define KBDCR_FKC		 0x01
-
-#define KBDSTAT_TXE		 0x80
-#define KBDSTAT_TXB		 0x40
-#define KBDSTAT_RXF		 0x20
-#define KBDSTAT_RXB		 0x10
-#define KBDSTAT_ENA		 0x08
-#define KBDSTAT_RXP		 0x04
-#define KBDSTAT_KBD		 0x02
-#define KBDSTAT_KBC		 0x01
-
-#define KBDCLKDIV_DivVal	 Fld(4,0)
-
-#define MSECR_ENA		 0x08
-#define MSECR_FKD		 0x02
-#define MSECR_FKC		 0x01
-
-#define MSESTAT_TXE		 0x80
-#define MSESTAT_TXB		 0x40
-#define MSESTAT_RXF		 0x20
-#define MSESTAT_RXB		 0x10
-#define MSESTAT_ENA		 0x08
-#define MSESTAT_RXP		 0x04	
-#define MSESTAT_MSD		 0x02
-#define MSESTAT_MSC		 0x01
-
-#define MSECLKDIV_DivVal	 Fld(4,0)
-
-#define KBDTEST1_CD		 0x80
-#define KBDTEST1_RC1		 0x40
-#define KBDTEST1_MC		 0x20
-#define KBDTEST1_C		 Fld(2,3)
-#define KBDTEST1_T2		 0x40
-#define KBDTEST1_T1		 0x20
-#define KBDTEST1_T0		 0x10
-#define KBDTEST2_TICBnRES	 0x08
-#define KBDTEST2_RKC		 0x04
-#define KBDTEST2_RKD		 0x02
-#define KBDTEST2_SEL		 0x01
-#define KBDTEST3_ms_16		 0x80
-#define KBDTEST3_us_64		 0x40
-#define KBDTEST3_us_16		 0x20
-#define KBDTEST3_DIV8		 0x10
-#define KBDTEST3_DIn		 0x08
-#define KBDTEST3_CIn		 0x04
-#define KBDTEST3_KD		 0x02
-#define KBDTEST3_KC		 0x01
-#define KBDTEST4_BC12		 0x80
-#define KBDTEST4_BC11		 0x40
-#define KBDTEST4_TRES		 0x20
-#define KBDTEST4_CLKOE		 0x10
-#define KBDTEST4_CRES		 0x08
-#define KBDTEST4_RXB		 0x04
-#define KBDTEST4_TXB		 0x02
-#define KBDTEST4_SRX		 0x01
-
-#define MSETEST1_CD		 0x80
-#define MSETEST1_RC1		 0x40
-#define MSETEST1_MC		 0x20
-#define MSETEST1_C		 Fld(2,3)
-#define MSETEST1_T2		 0x40
-#define MSETEST1_T1		 0x20
-#define MSETEST1_T0		 0x10
-#define MSETEST2_TICBnRES	 0x08
-#define MSETEST2_RKC		 0x04
-#define MSETEST2_RKD		 0x02
-#define MSETEST2_SEL		 0x01
-#define MSETEST3_ms_16		 0x80
-#define MSETEST3_us_64		 0x40
-#define MSETEST3_us_16		 0x20
-#define MSETEST3_DIV8		 0x10
-#define MSETEST3_DIn		 0x08
-#define MSETEST3_CIn		 0x04
-#define MSETEST3_KD		 0x02
-#define MSETEST3_KC		 0x01
-#define MSETEST4_BC12		 0x80
-#define MSETEST4_BC11		 0x40
-#define MSETEST4_TRES		 0x20
-#define MSETEST4_CLKOE		 0x10
-#define MSETEST4_CRES		 0x08
-#define MSETEST4_RXB		 0x04
-#define MSETEST4_TXB		 0x02
-#define MSETEST4_SRX		 0x01
-
-#endif  /* LANGUAGE == C */
-
-
-/*
- * General-Purpose I/O Interface
- *
- * Registers
- *    PADWR	Port A Data Write Register
- *    PBDWR	Port B Data Write Register
- *    PADRR	Port A Data Read Register
- *    PBDRR	Port B Data Read Register
- *    PADDR	Port A Data Direction Register
- *    PBDDR	Port B Data Direction Register
- *    PASSR	Port A Sleep State Register
- *    PBSSR	Port B Sleep State Register
- *
- */
-
-#define _PIO( x )      _SA1101( ( x ) + __GPIO_INTERFACE )
-
-#define _PADWR	       _PIO( 0x0000 )
-#define _PBDWR	       _PIO( 0x0400 )
-#define _PADRR	       _PIO( 0x0000 )
-#define _PBDRR	       _PIO( 0x0400 )
-#define _PADDR	       _PIO( 0x0800 )
-#define _PBDDR	       _PIO( 0x0c00 )
-#define _PASSR	       _PIO( 0x1000 )
-#define _PBSSR	       _PIO( 0x1400 )
-
-
-#if ( LANGUAGE == C )
-
-
-#define PADWR	    (*((volatile Word *) SA1101_p2v (_PADWR)))
-#define PBDWR	    (*((volatile Word *) SA1101_p2v (_PBDWR)))
-#define PADRR	    (*((volatile Word *) SA1101_p2v (_PADRR)))
-#define PBDRR	    (*((volatile Word *) SA1101_p2v (_PBDRR)))
-#define PADDR	    (*((volatile Word *) SA1101_p2v (_PADDR)))
-#define PBDDR	    (*((volatile Word *) SA1101_p2v (_PBDDR)))
-#define PASSR	    (*((volatile Word *) SA1101_p2v (_PASSR)))
-#define PBSSR	    (*((volatile Word *) SA1101_p2v (_PBSSR)))
-
-#endif
-
-
-
-/*
- * Keypad Interface
- *
- * Registers
- *    PXDWR
- *    PXDRR
- *    PYDWR
- *    PYDRR
- *
- */
-
-#define _KEYPAD( x )	_SA1101( ( x ) + __KEYPAD_INTERFACE ) 
-
-#define _PXDWR	   _KEYPAD( 0x0000 )
-#define _PXDRR	   _KEYPAD( 0x0000 )
-#define _PYDWR	   _KEYPAD( 0x0400 )
-#define _PYDRR	   _KEYPAD( 0x0400 )
-
-#if ( LANGUAGE == C )
-
-
-#define PXDWR	    (*((volatile Word *) SA1101_p2v (_PXDWR)))
-#define PXDRR	    (*((volatile Word *) SA1101_p2v (_PXDRR)))
-#define PYDWR	    (*((volatile Word *) SA1101_p2v (_PYDWR)))
-#define PYDRR	    (*((volatile Word *) SA1101_p2v (_PYDRR)))
-
-#endif
-
-
-
-/*
- * PCMCIA Interface
- *
- * Registers
- *    PCSR	Status Register
- *    PCCR	Control Register
- *    PCSSR	Sleep State Register
- *
- */
-
-#define _CARD( x )	_SA1101( ( x ) + __PCMCIA_INTERFACE )
-
-#define _PCSR	   _CARD( 0x0000 )
-#define _PCCR	   _CARD( 0x0400 )
-#define _PCSSR	   _CARD( 0x0800 )
-
-#if ( LANGUAGE == C )
-#define PCSR    (*((volatile Word *) SA1101_p2v (_PCSR)))
-#define PCCR	(*((volatile Word *) SA1101_p2v (_PCCR)))
-#define PCSSR	(*((volatile Word *) SA1101_p2v (_PCSSR)))
-
-#define PCSR_S0_ready		0x0001
-#define PCSR_S1_ready		0x0002
-#define PCSR_S0_detected	0x0004
-#define PCSR_S1_detected	0x0008
-#define PCSR_S0_VS1		0x0010
-#define PCSR_S0_VS2		0x0020
-#define PCSR_S1_VS1		0x0040
-#define PCSR_S1_VS2		0x0080
-#define PCSR_S0_WP		0x0100
-#define PCSR_S1_WP		0x0200
-#define PCSR_S0_BVD1_nSTSCHG	0x0400
-#define PCSR_S0_BVD2_nSPKR	0x0800
-#define PCSR_S1_BVD1_nSTSCHG	0x1000
-#define PCSR_S1_BVD2_nSPKR	0x2000
-
-#define PCCR_S0_VPP0		0x0001
-#define PCCR_S0_VPP1		0x0002
-#define PCCR_S0_VCC0		0x0004
-#define PCCR_S0_VCC1		0x0008
-#define PCCR_S1_VPP0		0x0010
-#define PCCR_S1_VPP1		0x0020
-#define PCCR_S1_VCC0		0x0040
-#define PCCR_S1_VCC1		0x0080
-#define PCCR_S0_reset		0x0100
-#define PCCR_S1_reset		0x0200
-#define PCCR_S0_float		0x0400
-#define PCCR_S1_float		0x0800
-
-#define PCSSR_S0_VCC0		0x0001
-#define PCSSR_S0_VCC1		0x0002
-#define PCSSR_S0_VPP0		0x0004
-#define PCSSR_S0_VPP1		0x0008
-#define PCSSR_S0_control	0x0010
-#define PCSSR_S1_VCC0		0x0020
-#define PCSSR_S1_VCC1		0x0040
-#define PCSSR_S1_VPP0		0x0080
-#define PCSSR_S1_VPP1		0x0100
-#define PCSSR_S1_control	0x0200
-
-#endif
-
-#undef C
-#undef Assembly
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -32,15 +32,16 @@ config ARCH_RMOBILE
 menuconfig ARCH_RENESAS
 	bool "Renesas ARM SoCs"
 	depends on ARCH_MULTI_V7 && MMU
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 	select ARCH_SHMOBILE
 	select ARCH_SHMOBILE_MULTI
+	select ARM_GIC
+	select GPIOLIB
 	select HAVE_ARM_SCU if SMP
 	select HAVE_ARM_TWD if SMP
-	select ARM_GIC
-	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 	select NO_IOPORT_MAP
 	select PINCTRL
-	select GPIOLIB
+	select SOC_BUS
 	select ZONE_DMA if ARM_LPAE
 
 if ARCH_RENESAS
@@ -60,6 +61,7 @@ config ARCH_R7S72100
 config ARCH_R8A73A4
 	bool "R-Mobile APE6 (R8A73A40)"
 	select ARCH_RMOBILE
+	select ARM_ERRATA_798181 if SMP
 	select RENESAS_IRQC
 
 config ARCH_R8A7740
@@ -67,6 +69,15 @@ config ARCH_R8A7740
 	select ARCH_RMOBILE
 	select RENESAS_INTC_IRQPIN
 
+config ARCH_R8A7743
+	bool "RZ/G1M (R8A77430)"
+	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
+
+config ARCH_R8A7745
+	bool "RZ/G1E (R8A77450)"
+	select ARCH_RCAR_GEN2
+
 config ARCH_R8A7778
 	bool "R-Car M1A (R8A77781)"
 	select ARCH_RCAR_GEN1
@@ -78,20 +89,24 @@ config ARCH_R8A7779
 config ARCH_R8A7790
 	bool "R-Car H2 (R8A77900)"
 	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
 	select I2C
 
 config ARCH_R8A7791
 	bool "R-Car M2-W (R8A77910)"
 	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
 	select I2C
 
 config ARCH_R8A7792
 	bool "R-Car V2H (R8A77920)"
 	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
 
 config ARCH_R8A7793
 	bool "R-Car M2-N (R8A7793)"
 	select ARCH_RCAR_GEN2
+	select ARM_ERRATA_798181 if SMP
 	select I2C
 
 config ARCH_R8A7794
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/Makefile linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/Makefile
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -13,9 +13,6 @@ obj-$(CONFIG_ARCH_R8A7778)	+= setup-r8a7
 obj-$(CONFIG_ARCH_R8A7779)	+= setup-r8a7779.o pm-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)	+= setup-r8a7790.o
 obj-$(CONFIG_ARCH_R8A7791)	+= setup-r8a7791.o
-obj-$(CONFIG_ARCH_R8A7792)	+= setup-r8a7792.o
-obj-$(CONFIG_ARCH_R8A7793)	+= setup-r8a7793.o
-obj-$(CONFIG_ARCH_R8A7794)	+= setup-r8a7794.o
 obj-$(CONFIG_ARCH_EMEV2)	+= setup-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)	+= setup-r7s72100.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7778.c linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7778.c
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7778.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7778.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,6 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/clk/renesas.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
 
@@ -23,19 +22,6 @@
 
 #include "common.h"
 
-#define MODEMR 0xffcc0020
-
-static void __init r8a7778_timer_init(void)
-{
-	u32 mode;
-	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
-
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
-	r8a7778_clocks_init(mode);
-}
-
 #define INT2SMSKCR0	0x82288 /* 0xfe782288 */
 #define INT2SMSKCR1	0x8228c /* 0xfe78228c */
 
@@ -70,6 +56,5 @@ DT_MACHINE_START(R8A7778_DT, "Generic R8
 	.init_early	= shmobile_init_delay,
 	.init_irq	= r8a7778_init_irq_dt,
 	.init_late	= shmobile_init_late,
-	.init_time	= r8a7778_timer_init,
 	.dt_compat	= r8a7778_compat_dt,
 MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7779.c linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7779.c
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7779.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7779.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,8 +14,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include <linux/clk/renesas.h>
-#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
@@ -76,30 +74,6 @@ static void __init r8a7779_init_irq_dt(v
 	__raw_writel(0x003fee3f, INT2SMSKCR4);
 }
 
-#define MODEMR		0xffcc0020
-
-static u32 __init r8a7779_read_mode_pins(void)
-{
-	static u32 mode;
-	static bool mode_valid;
-
-	if (!mode_valid) {
-		void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
-		BUG_ON(!modemr);
-		mode = ioread32(modemr);
-		iounmap(modemr);
-		mode_valid = true;
-	}
-
-	return mode;
-}
-
-static void __init r8a7779_init_time(void)
-{
-	r8a7779_clocks_init(r8a7779_read_mode_pins());
-	clocksource_probe();
-}
-
 static const char *const r8a7779_compat_dt[] __initconst = {
 	"renesas,r8a7779",
 	NULL,
@@ -109,7 +83,6 @@ DT_MACHINE_START(R8A7779_DT, "Generic R8
 	.smp		= smp_ops(r8a7779_smp_ops),
 	.map_io		= r8a7779_map_io,
 	.init_early	= shmobile_init_delay,
-	.init_time	= r8a7779_init_time,
 	.init_irq	= r8a7779_init_irq_dt,
 	.init_late	= shmobile_init_late,
 	.dt_compat	= r8a7779_compat_dt,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7792.c linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7792.c
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7792.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7792.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*
- * r8a7792 processor support
- *
- * Copyright (C) 2014 Renesas Electronics Corporation
- * Copyright (C) 2016 Cogent  Embedded, 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; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/of_platform.h>
-
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "rcar-gen2.h"
-
-static const char * const r8a7792_boards_compat_dt[] __initconst = {
-	"renesas,r8a7792",
-	NULL,
-};
-
-DT_MACHINE_START(R8A7792_DT, "Generic R8A7792 (Flattened Device Tree)")
-	.init_early	= shmobile_init_delay,
-	.init_late	= shmobile_init_late,
-	.init_time	= rcar_gen2_timer_init,
-	.reserve	= rcar_gen2_reserve,
-	.dt_compat	= r8a7792_boards_compat_dt,
-MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7793.c linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7793.c
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7793.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7793.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * r8a7793 processor support
- *
- * Copyright (C) 2015  Ulrich Hecht
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/init.h>
-#include <asm/mach/arch.h>
-
-#include "common.h"
-#include "rcar-gen2.h"
-
-static const char * const r8a7793_boards_compat_dt[] __initconst = {
-	"renesas,r8a7793",
-	NULL,
-};
-
-DT_MACHINE_START(R8A7793_DT, "Generic R8A7793 (Flattened Device Tree)")
-	.init_early	= shmobile_init_delay,
-	.init_time	= rcar_gen2_timer_init,
-	.init_late	= shmobile_init_late,
-	.reserve	= rcar_gen2_reserve,
-	.dt_compat	= r8a7793_boards_compat_dt,
-MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7794.c linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7794.c
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-r8a7794.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-r8a7794.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- * r8a7794 processor support
- *
- * Copyright (C) 2014  Renesas Electronics Corporation
- * Copyright (C) 2014  Ulrich Hecht
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/of_platform.h>
-#include "common.h"
-#include "rcar-gen2.h"
-#include <asm/mach/arch.h>
-
-static const char * const r8a7794_boards_compat_dt[] __initconst = {
-	"renesas,r8a7794",
-	NULL,
-};
-
-DT_MACHINE_START(R8A7794_DT, "Generic R8A7794 (Flattened Device Tree)")
-	.init_early	= shmobile_init_delay,
-	.init_late	= shmobile_init_late,
-	.init_time	= rcar_gen2_timer_init,
-	.reserve	= rcar_gen2_reserve,
-	.dt_compat	= r8a7794_boards_compat_dt,
-MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c
--- linux-libre-4.9-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-shmobile/setup-rcar-gen2.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/clk/renesas.h>
+#include <linux/clk-provider.h>
 #include <linux/clocksource.h>
 #include <linux/device.h>
 #include <linux/dma-contiguous.h>
@@ -24,6 +24,7 @@
 #include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
+#include <linux/of_platform.h>
 #include <asm/mach/arch.h>
 #include "common.h"
 #include "rcar-gen2.h"
@@ -71,7 +72,6 @@ static unsigned int __init get_extal_fre
 
 void __init rcar_gen2_timer_init(void)
 {
-	u32 mode = rcar_gen2_read_mode_pins();
 #ifdef CONFIG_ARM_ARCH_TIMER
 	void __iomem *base;
 	u32 freq;
@@ -130,7 +130,7 @@ void __init rcar_gen2_timer_init(void)
 	iounmap(base);
 #endif /* CONFIG_ARM_ARCH_TIMER */
 
-	rcar_gen2_clocks_init(mode);
+	of_clk_init(NULL);
 	clocksource_probe();
 }
 
@@ -203,3 +203,36 @@ void __init rcar_gen2_reserve(void)
 	}
 #endif
 }
+
+static const char * const rcar_gen2_boards_compat_dt[] __initconst = {
+	/*
+	 * R8A7790 and R8A7791 can't be handled here as long as they need SMP
+	 * initialization fallback.
+	 */
+	"renesas,r8a7792",
+	"renesas,r8a7793",
+	"renesas,r8a7794",
+	NULL,
+};
+
+DT_MACHINE_START(RCAR_GEN2_DT, "Generic R-Car Gen2 (Flattened Device Tree)")
+	.init_early	= shmobile_init_delay,
+	.init_late	= shmobile_init_late,
+	.init_time	= rcar_gen2_timer_init,
+	.reserve	= rcar_gen2_reserve,
+	.dt_compat	= rcar_gen2_boards_compat_dt,
+MACHINE_END
+
+static const char * const rz_g1_boards_compat_dt[] __initconst = {
+	"renesas,r8a7743",
+	"renesas,r8a7745",
+	NULL,
+};
+
+DT_MACHINE_START(RZ_G1_DT, "Generic RZ/G1 (Flattened Device Tree)")
+	.init_early	= shmobile_init_delay,
+	.init_late	= shmobile_init_late,
+	.init_time	= rcar_gen2_timer_init,
+	.reserve	= rcar_gen2_reserve,
+	.dt_compat	= rz_g1_boards_compat_dt,
+MACHINE_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-socfpga/l2_cache.c linux-libre-4.10-rc8-gnu/arch/arm/mach-socfpga/l2_cache.c
--- linux-libre-4.9-gnu/arch/arm/mach-socfpga/l2_cache.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-socfpga/l2_cache.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,7 +74,7 @@ void socfpga_init_arria10_l2_ecc(void)
 	}
 
 	if (!sys_manager_base_addr) {
-		pr_err("System Mananger not mapped for L2 ECC\n");
+		pr_err("System Manager not mapped for L2 ECC\n");
 		goto exit;
 	}
 	/* Clear any pending IRQs */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-spear/time.c linux-libre-4.10-rc8-gnu/arch/arm/mach-spear/time.c
--- linux-libre-4.9-gnu/arch/arm/mach-spear/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-spear/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -233,7 +233,7 @@ void __init spear_setup_of_timer(void)
 	}
 
 	gpt_clk = clk_get_sys("gpt0", NULL);
-	if (!gpt_clk) {
+	if (IS_ERR(gpt_clk)) {
 		pr_err("%s:couldn't get clk for gpt\n", __func__);
 		goto err_iomap;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-sti/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mach-sti/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mach-sti/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-sti/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,6 @@ if ARCH_STI
 config SOC_STIH415
 	bool "STiH415 STMicroelectronics Consumer Electronics family"
 	default y
-	select STIH415_RESET
 	help
 	  This enables support for STMicroelectronics Digital Consumer
 	  Electronics family StiH415 parts, primarily targeted at set-top-box
@@ -38,7 +37,6 @@ config SOC_STIH415
 config SOC_STIH416
 	bool "STiH416 STMicroelectronics Consumer Electronics family"
 	default y
-	select STIH416_RESET
 	help
 	  This enables support for STMicroelectronics Digital Consumer
 	  Electronics family StiH416 parts, primarily targeted at set-top-box
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-stm32/board-dt.c linux-libre-4.10-rc8-gnu/arch/arm/mach-stm32/board-dt.c
--- linux-libre-4.9-gnu/arch/arm/mach-stm32/board-dt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-stm32/board-dt.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@
 static const char *const stm32_compat[] __initconst = {
 	"st,stm32f429",
 	"st,stm32f469",
+	"st,stm32f746",
 	NULL
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-ux500/pm.c linux-libre-4.10-rc8-gnu/arch/arm/mach-ux500/pm.c
--- linux-libre-4.9-gnu/arch/arm/mach-ux500/pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-ux500/pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -134,8 +134,8 @@ bool prcmu_pending_irq(void)
  */
 bool prcmu_is_cpu_in_wfi(int cpu)
 {
-	return readl(PRCM_ARM_WFI_STANDBY) & cpu ? PRCM_ARM_WFI_STANDBY_WFI1 :
-		     PRCM_ARM_WFI_STANDBY_WFI0;
+	return readl(PRCM_ARM_WFI_STANDBY) &
+		(cpu ? PRCM_ARM_WFI_STANDBY_WFI1 : PRCM_ARM_WFI_STANDBY_WFI0);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-vexpress/platsmp.c linux-libre-4.10-rc8-gnu/arch/arm/mach-vexpress/platsmp.c
--- linux-libre-4.9-gnu/arch/arm/mach-vexpress/platsmp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-vexpress/platsmp.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,19 +26,37 @@
 bool __init vexpress_smp_init_ops(void)
 {
 #ifdef CONFIG_MCPM
+	int cpu;
+	struct device_node *cpu_node, *cci_node;
+
 	/*
-	 * The best way to detect a multi-cluster configuration at the moment
-	 * is to look for the presence of a CCI in the system.
+	 * The best way to detect a multi-cluster configuration
+	 * is to detect if the kernel can take over CCI ports
+	 * control. Loop over possible CPUs and check if CCI
+	 * port control is available.
 	 * Override the default vexpress_smp_ops if so.
 	 */
-	struct device_node *node;
-	node = of_find_compatible_node(NULL, NULL, "arm,cci-400");
-	if (node && of_device_is_available(node)) {
-		mcpm_smp_set_ops();
-		return true;
+	for_each_possible_cpu(cpu) {
+		bool available;
+
+		cpu_node = of_get_cpu_node(cpu, NULL);
+		if (WARN(!cpu_node, "Missing cpu device node!"))
+			return false;
+
+		cci_node = of_parse_phandle(cpu_node, "cci-control-port", 0);
+		available = cci_node && of_device_is_available(cci_node);
+		of_node_put(cci_node);
+		of_node_put(cpu_node);
+
+		if (!available)
+			return false;
 	}
-#endif
+
+	mcpm_smp_set_ops();
+	return true;
+#else
 	return false;
+#endif
 }
 
 static const struct of_device_id vexpress_smp_dt_scu_match[] __initconst = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-zx/zx296702-pm-domain.c linux-libre-4.10-rc8-gnu/arch/arm/mach-zx/zx296702-pm-domain.c
--- linux-libre-4.9-gnu/arch/arm/mach-zx/zx296702-pm-domain.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-zx/zx296702-pm-domain.c	2017-02-12 16:03:20.000000000 -0500
@@ -169,7 +169,7 @@ static int zx296702_pd_probe(struct plat
 	}
 
 	pcubase = devm_ioremap_resource(&pdev->dev, res);
-	if (!pcubase) {
+	if (IS_ERR(pcubase)) {
 		dev_err(&pdev->dev, "ioremap fail.\n");
 		return -EIO;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mach-zynq/common.c linux-libre-4.10-rc8-gnu/arch/arm/mach-zynq/common.c
--- linux-libre-4.9-gnu/arch/arm/mach-zynq/common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mach-zynq/common.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@ void __iomem *zynq_scu_base;
 static void __init zynq_memory_init(void)
 {
 	if (!__pa(PAGE_OFFSET))
-		memblock_reserve(__pa(PAGE_OFFSET), __pa(swapper_pg_dir));
+		memblock_reserve(__pa(PAGE_OFFSET), 0x80000);
 }
 
 static struct platform_device zynq_cpuidle_device = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/Makefile linux-libre-4.10-rc8-gnu/arch/arm/Makefile
--- linux-libre-4.9-gnu/arch/arm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -191,6 +191,7 @@ machine-$(CONFIG_ARCH_MXS)		+= mxs
 machine-$(CONFIG_ARCH_NETX)		+= netx
 machine-$(CONFIG_ARCH_NOMADIK)		+= nomadik
 machine-$(CONFIG_ARCH_NSPIRE)		+= nspire
+machine-$(CONFIG_ARCH_OXNAS)		+= oxnas
 machine-$(CONFIG_ARCH_OMAP1)		+= omap1
 machine-$(CONFIG_ARCH_OMAP2PLUS)	+= omap2
 machine-$(CONFIG_ARCH_ORION5X)		+= orion5x
@@ -311,8 +312,11 @@ all:	$(KBUILD_IMAGE) $(KBUILD_DTBS)
 
 boot := arch/arm/boot
 
+archheaders:
+	$(Q)$(MAKE) $(build)=arch/arm/tools uapi
+
 archprepare:
-	$(Q)$(MAKE) $(build)=arch/arm/tools include/generated/mach-types.h
+	$(Q)$(MAKE) $(build)=arch/arm/tools kapi
 
 # Convert bzImage to zImage
 bzImage: zImage
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mm/cache-l2x0.c linux-libre-4.10-rc8-gnu/arch/arm/mm/cache-l2x0.c
--- linux-libre-4.9-gnu/arch/arm/mm/cache-l2x0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mm/cache-l2x0.c	2017-02-12 16:03:20.000000000 -0500
@@ -683,7 +683,7 @@ static void __init l2c310_enable(void __
 
 	if (aux & L310_AUX_CTRL_FULL_LINE_ZERO)
 		cpuhp_setup_state(CPUHP_AP_ARM_L2X0_STARTING,
-				  "AP_ARM_L2X0_STARTING", l2c310_starting_cpu,
+				  "arm/l2x0:starting", l2c310_starting_cpu,
 				  l2c310_dying_cpu);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mm/cache-l2x0-pmu.c linux-libre-4.10-rc8-gnu/arch/arm/mm/cache-l2x0-pmu.c
--- linux-libre-4.9-gnu/arch/arm/mm/cache-l2x0-pmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mm/cache-l2x0-pmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -563,7 +563,7 @@ static __init int l2x0_pmu_init(void)
 
 	cpumask_set_cpu(0, &pmu_cpu);
 	ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_L2X0_ONLINE,
-					"AP_PERF_ARM_L2X0_ONLINE", NULL,
+					"perf/arm/l2x0:online", NULL,
 					l2x0_pmu_offline_cpu);
 	if (ret)
 		goto out_pmu;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mm/fault.c linux-libre-4.10-rc8-gnu/arch/arm/mm/fault.c
--- linux-libre-4.9-gnu/arch/arm/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -610,9 +610,9 @@ static int __init early_abort_handler(un
 
 void __init early_abt_enable(void)
 {
-	fsr_info[22].fn = early_abort_handler;
+	fsr_info[FSR_FS_AEA].fn = early_abort_handler;
 	local_abt_enable();
-	fsr_info[22].fn = do_bad;
+	fsr_info[FSR_FS_AEA].fn = do_bad;
 }
 
 #ifndef CONFIG_ARM_LPAE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mm/fault.h linux-libre-4.10-rc8-gnu/arch/arm/mm/fault.h
--- linux-libre-4.9-gnu/arch/arm/mm/fault.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mm/fault.h	2017-02-12 16:03:20.000000000 -0500
@@ -11,11 +11,15 @@
 #define FSR_FS5_0		(0x3f)
 
 #ifdef CONFIG_ARM_LPAE
+#define FSR_FS_AEA		17
+
 static inline int fsr_fs(unsigned int fsr)
 {
 	return fsr & FSR_FS5_0;
 }
 #else
+#define FSR_FS_AEA		22
+
 static inline int fsr_fs(unsigned int fsr)
 {
 	return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mm/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/mm/Kconfig
--- linux-libre-4.9-gnu/arch/arm/mm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -991,7 +991,7 @@ config CACHE_TAUROS2
 config CACHE_UNIPHIER
 	bool "Enable the UniPhier outer cache controller"
 	depends on ARCH_UNIPHIER
-	default y
+	select ARM_L1_CACHE_SHIFT_7
 	select OUTER_CACHE
 	select OUTER_CACHE_SYNC
 	help
@@ -1012,8 +1012,14 @@ config ARM_L1_CACHE_SHIFT_6
 	help
 	  Setting ARM L1 cache line size to 64 Bytes.
 
+config ARM_L1_CACHE_SHIFT_7
+	bool
+	help
+	  Setting ARM L1 cache line size to 128 Bytes.
+
 config ARM_L1_CACHE_SHIFT
 	int
+	default 7 if ARM_L1_CACHE_SHIFT_7
 	default 6 if ARM_L1_CACHE_SHIFT_6
 	default 5
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/mm/pageattr.c linux-libre-4.10-rc8-gnu/arch/arm/mm/pageattr.c
--- linux-libre-4.9-gnu/arch/arm/mm/pageattr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/mm/pageattr.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,28 +34,29 @@ static int change_page_range(pte_t *ptep
 	return 0;
 }
 
+static bool in_range(unsigned long start, unsigned long size,
+	unsigned long range_start, unsigned long range_end)
+{
+	return start >= range_start && start < range_end &&
+		size <= range_end - start;
+}
+
 static int change_memory_common(unsigned long addr, int numpages,
 				pgprot_t set_mask, pgprot_t clear_mask)
 {
-	unsigned long start = addr;
-	unsigned long size = PAGE_SIZE*numpages;
-	unsigned long end = start + size;
+	unsigned long start = addr & PAGE_MASK;
+	unsigned long end = PAGE_ALIGN(addr) + numpages * PAGE_SIZE;
+	unsigned long size = end - start;
 	int ret;
 	struct page_change_data data;
 
-	if (!IS_ALIGNED(addr, PAGE_SIZE)) {
-		start &= PAGE_MASK;
-		end = start + size;
-		WARN_ON_ONCE(1);
-	}
+	WARN_ON_ONCE(start != addr);
 
-	if (!numpages)
+	if (!size)
 		return 0;
 
-	if (start < MODULES_VADDR || start >= MODULES_END)
-		return -EINVAL;
-
-	if (end < MODULES_VADDR || start >= MODULES_END)
+	if (!in_range(start, size, MODULES_VADDR, MODULES_END) &&
+	    !in_range(start, size, VMALLOC_START, VMALLOC_END))
 		return -EINVAL;
 
 	data.set_mask = set_mask;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/plat-iop/time.c linux-libre-4.10-rc8-gnu/arch/arm/plat-iop/time.c
--- linux-libre-4.9-gnu/arch/arm/plat-iop/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/plat-iop/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/sched_clock.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <mach/time.h>
@@ -38,7 +38,7 @@
 /*
  * IOP clocksource (free-running timer 1).
  */
-static cycle_t notrace iop_clocksource_read(struct clocksource *unused)
+static u64 notrace iop_clocksource_read(struct clocksource *unused)
 {
 	return 0xffffffffu - read_tcr1();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/plat-omap/i2c.c linux-libre-4.10-rc8-gnu/arch/arm/plat-omap/i2c.c
--- linux-libre-4.9-gnu/arch/arm/plat-omap/i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/plat-omap/i2c.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,116 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/i2c.c
- *
- * Helper module for board specific I2C bus registration
- *
- * Copyright (C) 2007 Nokia Corporation.
- *
- * Contact: Jarkko Nikula <jhnikula@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/i2c-omap.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-
-#include <plat/i2c.h>
-
-#define OMAP_I2C_MAX_CONTROLLERS 4
-static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS];
-
-#define OMAP_I2C_CMDLINE_SETUP	(BIT(31))
-
-/**
- * omap_i2c_bus_setup - Process command line options for the I2C bus speed
- * @str: String of options
- *
- * This function allow to override the default I2C bus speed for given I2C
- * bus with a command line option.
- *
- * Format: i2c_bus=bus_id,clkrate (in kHz)
- *
- * Returns 1 on success, 0 otherwise.
- */
-static int __init omap_i2c_bus_setup(char *str)
-{
-	int ints[3];
-
-	get_options(str, 3, ints);
-	if (ints[0] < 2 || ints[1] < 1 ||
-			ints[1] > OMAP_I2C_MAX_CONTROLLERS)
-		return 0;
-	i2c_pdata[ints[1] - 1].clkrate = ints[2];
-	i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP;
-
-	return 1;
-}
-__setup("i2c_bus=", omap_i2c_bus_setup);
-
-/*
- * Register busses defined in command line but that are not registered with
- * omap_register_i2c_bus from board initialization code.
- */
-int __init omap_register_i2c_bus_cmdline(void)
-{
-	int i, err = 0;
-
-	for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++)
-		if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) {
-			i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
-			err = omap_i2c_add_bus(&i2c_pdata[i], i + 1);
-			if (err)
-				goto out;
-		}
-
-out:
-	return err;
-}
-
-/**
- * omap_register_i2c_bus - register I2C bus with device descriptors
- * @bus_id: bus id counting from number 1
- * @clkrate: clock rate of the bus in kHz
- * @info: pointer into I2C device descriptor table or NULL
- * @len: number of descriptors in the table
- *
- * Returns 0 on success or an error code.
- */
-int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
-			  struct i2c_board_info const *info,
-			  unsigned len)
-{
-	int err;
-
-	BUG_ON(bus_id < 1 || bus_id > OMAP_I2C_MAX_CONTROLLERS);
-
-	if (info) {
-		err = i2c_register_board_info(bus_id, info, len);
-		if (err)
-			return err;
-	}
-
-	if (!i2c_pdata[bus_id - 1].clkrate)
-		i2c_pdata[bus_id - 1].clkrate = clkrate;
-
-	i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
-
-	return omap_i2c_add_bus(&i2c_pdata[bus_id - 1], bus_id);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/plat-omap/Kconfig linux-libre-4.10-rc8-gnu/arch/arm/plat-omap/Kconfig
--- linux-libre-4.9-gnu/arch/arm/plat-omap/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/plat-omap/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -63,32 +63,6 @@ config OMAP_RESET_CLOCKS
 	  probably do not want this option enabled until your
 	  device drivers work properly.
 
-config OMAP_MUX
-	bool "OMAP multiplexing support"
-	depends on ARCH_OMAP
-	default y
-	help
-	  Pin multiplexing support for OMAP boards. If your bootloader
-	  sets the multiplexing correctly, say N. Otherwise, or if unsure,
-	  say Y.
-
-config OMAP_MUX_DEBUG
-	bool "Multiplexing debug output"
-	depends on OMAP_MUX
-	help
-	  Makes the multiplexing functions print out a lot of debug info.
-	  This is useful if you want to find out the correct values of the
-	  multiplexing registers.
-
-config OMAP_MUX_WARNINGS
-	bool "Warn about pins the bootloader didn't set up"
-	depends on OMAP_MUX
-	default y
-	help
-	  Choose Y here to warn whenever driver initialization logic needs
-	  to change the pin multiplexing setup.	 When there are no warnings
-	  printed, it's safe to deselect OMAP_MUX for your product.
-
 config OMAP_MPU_TIMER
 	bool "Use mpu timer"
 	depends on ARCH_OMAP1
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/plat-omap/Makefile linux-libre-4.10-rc8-gnu/arch/arm/plat-omap/Makefile
--- linux-libre-4.9-gnu/arch/arm/plat-omap/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/plat-omap/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,3 @@ obj-y := sram.o dma.o counter_32k.o
 
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
 obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
-i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
-obj-y += $(i2c-omap-m) $(i2c-omap-y)
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/plat-orion/gpio.c linux-libre-4.10-rc8-gnu/arch/arm/plat-orion/gpio.c
--- linux-libre-4.9-gnu/arch/arm/plat-orion/gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/plat-orion/gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -478,13 +478,13 @@ static void orion_gpio_dbg_show(struct s
 			   (data_in ^ in_pol) & msk  ? "hi" : "lo",
 			   in_pol & msk ? "lo" : "hi");
 		if (!((edg_msk | lvl_msk) & msk)) {
-			seq_printf(s, " disabled\n");
+			seq_puts(s, " disabled\n");
 			continue;
 		}
 		if (edg_msk & msk)
-			seq_printf(s, " edge ");
+			seq_puts(s, " edge ");
 		if (lvl_msk & msk)
-			seq_printf(s, " level");
+			seq_puts(s, " level");
 		seq_printf(s, " (%s)\n", cause & msk ? "pending" : "clear  ");
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/plat-samsung/devs.c linux-libre-4.10-rc8-gnu/arch/arm/plat-samsung/devs.c
--- linux-libre-4.9-gnu/arch/arm/plat-samsung/devs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/plat-samsung/devs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1124,15 +1124,6 @@ void __init s3c64xx_spi0_set_platdata(in
 	pd.num_cs = num_cs;
 	pd.src_clk_nr = src_clk_nr;
 	pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
-	pd.dma_tx = (void *)DMACH_SPI0_TX;
-	pd.dma_rx = (void *)DMACH_SPI0_RX;
-#if defined(CONFIG_PL330_DMA)
-	pd.filter = pl330_filter;
-#elif defined(CONFIG_S3C64XX_PL080)
-	pd.filter = pl08x_filter_id;
-#elif defined(CONFIG_S3C24XX_DMAC)
-	pd.filter = s3c24xx_dma_filter;
-#endif
 
 	s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
 }
@@ -1169,14 +1160,6 @@ void __init s3c64xx_spi1_set_platdata(in
 	pd.num_cs = num_cs;
 	pd.src_clk_nr = src_clk_nr;
 	pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
-	pd.dma_tx = (void *)DMACH_SPI1_TX;
-	pd.dma_rx = (void *)DMACH_SPI1_RX;
-#if defined(CONFIG_PL330_DMA)
-	pd.filter = pl330_filter;
-#elif defined(CONFIG_S3C64XX_PL080)
-	pd.filter = pl08x_filter_id;
-#endif
-
 
 	s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
 }
@@ -1213,13 +1196,6 @@ void __init s3c64xx_spi2_set_platdata(in
 	pd.num_cs = num_cs;
 	pd.src_clk_nr = src_clk_nr;
 	pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
-	pd.dma_tx = (void *)DMACH_SPI2_TX;
-	pd.dma_rx = (void *)DMACH_SPI2_RX;
-#if defined(CONFIG_PL330_DMA)
-	pd.filter = pl330_filter;
-#elif defined(CONFIG_S3C64XX_PL080)
-	pd.filter = pl08x_filter_id;
-#endif
 
 	s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h linux-libre-4.10-rc8-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h
--- linux-libre-4.9-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 
 #include <linux/types.h>
 
-typedef unsigned int __bitwise__ samsung_gpio_pull_t;
+typedef unsigned int __bitwise samsung_gpio_pull_t;
 
 /* forward declaration if gpio-core.h hasn't been included */
 struct samsung_gpio_chip;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/tools/mach-types linux-libre-4.10-rc8-gnu/arch/arm/tools/mach-types
--- linux-libre-4.9-gnu/arch/arm/tools/mach-types	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/tools/mach-types	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 # 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: Fri Mar 22 17:24:50 2013
+# Last update: Sun Oct 30 20:21:01 2016
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -152,7 +152,6 @@ colibri			MACH_COLIBRI		COLIBRI			729
 gateway7001		MACH_GATEWAY7001	GATEWAY7001		731
 pcm027			MACH_PCM027		PCM027			732
 anubis			MACH_ANUBIS		ANUBIS			734
-xboardgp8		MACH_XBOARDGP8		XBOARDGP8		742
 akita			MACH_AKITA		AKITA			744
 e330			MACH_E330		E330			753
 nokia770		MACH_NOKIA770		NOKIA770		755
@@ -393,7 +392,6 @@ anw6410			MACH_ANW6410		ANW6410			2183
 imx27_visstrim_m10	MACH_IMX27_VISSTRIM_M10	IMX27_VISSTRIM_M10	2187
 portuxg20		MACH_PORTUXG20		PORTUXG20		2191
 smdkc110		MACH_SMDKC110		SMDKC110		2193
-cabespresso		MACH_CABESPRESSO	CABESPRESSO		2194
 omap3517evm		MACH_OMAP3517EVM	OMAP3517EVM		2200
 netspace_v2		MACH_NETSPACE_V2	NETSPACE_V2		2201
 netspace_max_v2		MACH_NETSPACE_MAX_V2	NETSPACE_MAX_V2		2202
@@ -412,7 +410,6 @@ bigdisk			MACH_BIGDISK		BIGDISK			2283
 at91sam9g20ek_2mmc	MACH_AT91SAM9G20EK_2MMC	AT91SAM9G20EK_2MMC	2288
 bcmring			MACH_BCMRING		BCMRING			2289
 mahimahi		MACH_MAHIMAHI		MAHIMAHI		2304
-cerebric		MACH_CEREBRIC		CEREBRIC		2311
 smdk6442		MACH_SMDK6442		SMDK6442		2324
 openrd_base		MACH_OPENRD_BASE	OPENRD_BASE		2325
 devkit8000		MACH_DEVKIT8000		DEVKIT8000		2330
@@ -435,9 +432,7 @@ tnetv107x		MACH_TNETV107X		TNETV107X		24
 smdkv210		MACH_SMDKV210		SMDKV210		2456
 omap_zoom3		MACH_OMAP_ZOOM3		OMAP_ZOOM3		2464
 omap_3630sdp		MACH_OMAP_3630SDP	OMAP_3630SDP		2465
-cybook2440		MACH_CYBOOK2440		CYBOOK2440		2466
 smartq7			MACH_SMARTQ7		SMARTQ7			2479
-watson_efm_plugin	MACH_WATSON_EFM_PLUGIN	WATSON_EFM_PLUGIN	2491
 g4evm			MACH_G4EVM		G4EVM			2493
 omapl138_hawkboard	MACH_OMAPL138_HAWKBOARD	OMAPL138_HAWKBOARD	2495
 ts41x			MACH_TS41X		TS41X			2502
@@ -472,7 +467,6 @@ igep0030		MACH_IGEP0030		IGEP0030		2717
 sbc3530			MACH_SBC3530		SBC3530			2722
 saarb			MACH_SAARB		SAARB			2727
 harmony			MACH_HARMONY		HARMONY			2731
-cybook_orizon		MACH_CYBOOK_ORIZON	CYBOOK_ORIZON		2733
 msm7x30_fluid		MACH_MSM7X30_FLUID	MSM7X30_FLUID		2741
 cm_t3517		MACH_CM_T3517		CM_T3517		2750
 wbd222			MACH_WBD222		WBD222			2753
@@ -490,6 +484,7 @@ eukrea_cpuimx51		MACH_EUKREA_CPUIMX51	EU
 smdkc210		MACH_SMDKC210		SMDKC210		2838
 t5325			MACH_T5325		T5325			2846
 income			MACH_INCOME		INCOME			2849
+meson			MACH_MESON		MESON			2853
 goni			MACH_GONI		GONI			2862
 bv07			MACH_BV07		BV07			2882
 openrd_ultimate		MACH_OPENRD_ULTIMATE	OPENRD_ULTIMATE		2884
@@ -523,9 +518,9 @@ prima2_evb		MACH_PRIMA2_EVB		PRIMA2_EVB
 paz00			MACH_PAZ00		PAZ00			3128
 acmenetusfoxg20		MACH_ACMENETUSFOXG20	ACMENETUSFOXG20		3129
 ag5evm			MACH_AG5EVM		AG5EVM			3189
-ics_if_voip		MACH_ICS_IF_VOIP	ICS_IF_VOIP		3206
 wlf_cragg_6410		MACH_WLF_CRAGG_6410	WLF_CRAGG_6410		3207
 trimslice		MACH_TRIMSLICE		TRIMSLICE		3209
+mackerel		MACH_MACKEREL		MACKEREL		3211
 kaen			MACH_KAEN		KAEN			3217
 nokia_rm680		MACH_NOKIA_RM680	NOKIA_RM680		3220
 msm8960_sim		MACH_MSM8960_SIM	MSM8960_SIM		3230
@@ -540,469 +535,66 @@ snowball		MACH_SNOWBALL		SNOWBALL		3363
 xilinx_ep107		MACH_XILINX_EP107	XILINX_EP107		3378
 nuri			MACH_NURI		NURI			3379
 origen			MACH_ORIGEN		ORIGEN			3455
+xarina			MACH_XARINA		XARINA			3476
 nspire			MACH_NSPIRE		NSPIRE			3503
 nokia_rm696		MACH_NOKIA_RM696	NOKIA_RM696		3522
-mikrap_x168		MACH_MIKRAP_X168	MIKRAP_X168		3543
-deto_macarm9		MACH_DETO_MACARM9	DETO_MACARM9		3568
 m28evk			MACH_M28EVK		M28EVK			3613
 kota2			MACH_KOTA2		KOTA2			3616
 bonito			MACH_BONITO		BONITO			3623
-omap3_egf		MACH_OMAP3_EGF		OMAP3_EGF		3637
 smdk4212		MACH_SMDK4212		SMDK4212		3638
 apx4devkit		MACH_APX4DEVKIT		APX4DEVKIT		3712
 smdk4412		MACH_SMDK4412		SMDK4412		3765
 marzen			MACH_MARZEN		MARZEN			3790
-krome			MACH_KROME		KROME			3797
-armadillo800eva		MACH_ARMADILLO800EVA	ARMADILLO800EVA		3863
-mx53_umobo		MACH_MX53_UMOBO		MX53_UMOBO		3927
-mt4			MACH_MT4		MT4			3981
+empc_a500		MACH_EMPC_A500		EMPC_A500		3848
 u8520			MACH_U8520		U8520			3990
-chupacabra		MACH_CHUPACABRA		CHUPACABRA		4098
-scorpion		MACH_SCORPION		SCORPION		4099
-davinci_he_hmi10	MACH_DAVINCI_HE_HMI10	DAVINCI_HE_HMI10	4100
-topkick			MACH_TOPKICK		TOPKICK			4101
-m3_auguestrush		MACH_M3_AUGUESTRUSH	M3_AUGUESTRUSH		4102
-ipc335x			MACH_IPC335X		IPC335X			4103
-sun4i			MACH_SUN4I		SUN4I			4104
-imx233_olinuxino	MACH_IMX233_OLINUXINO	IMX233_OLINUXINO	4105
-k2_wl			MACH_K2_WL		K2_WL			4106
-k2_ul			MACH_K2_UL		K2_UL			4107
-k2_cl			MACH_K2_CL		K2_CL			4108
-minbari_w		MACH_MINBARI_W		MINBARI_W		4109
-minbari_m		MACH_MINBARI_M		MINBARI_M		4110
-k035			MACH_K035		K035			4111
-ariel			MACH_ARIEL		ARIEL			4112
-arielsaarc		MACH_ARIELSAARC		ARIELSAARC		4113
-arieldkb		MACH_ARIELDKB		ARIELDKB		4114
-armadillo810		MACH_ARMADILLO810	ARMADILLO810		4115
-tam335x			MACH_TAM335X		TAM335X			4116
-grouper			MACH_GROUPER		GROUPER			4117
-mpcsa21_9g20		MACH_MPCSA21_9G20	MPCSA21_9G20		4118
-m6u_cpu			MACH_M6U_CPU		M6U_CPU			4119
-ginkgo			MACH_GINKGO		GINKGO			4121
-cgt_qmx6		MACH_CGT_QMX6		CGT_QMX6		4122
-profpga			MACH_PROFPGA		PROFPGA			4123
-acfx100oc		MACH_ACFX100OC		ACFX100OC		4124
-acfx100nb		MACH_ACFX100NB		ACFX100NB		4125
-capricorn		MACH_CAPRICORN		CAPRICORN		4126
-pisces			MACH_PISCES		PISCES			4127
-aries			MACH_ARIES		ARIES			4128
-cancer			MACH_CANCER		CANCER			4129
-leo			MACH_LEO		LEO			4130
-virgo			MACH_VIRGO		VIRGO			4131
-sagittarius		MACH_SAGITTARIUS	SAGITTARIUS		4132
-devil			MACH_DEVIL		DEVIL			4133
-ballantines		MACH_BALLANTINES	BALLANTINES		4134
-omap3_procerusvpu	MACH_OMAP3_PROCERUSVPU	OMAP3_PROCERUSVPU	4135
-my27			MACH_MY27		MY27			4136
-sun6i			MACH_SUN6I		SUN6I			4137
-sun5i			MACH_SUN5I		SUN5I			4138
-mx512_mx		MACH_MX512_MX		MX512_MX		4139
-kzm9g			MACH_KZM9G		KZM9G			4140
-vdstbn			MACH_VDSTBN		VDSTBN			4141
-cfa10036		MACH_CFA10036		CFA10036		4142
-cfa10049		MACH_CFA10049		CFA10049		4143
-pcm051			MACH_PCM051		PCM051			4144
-vybrid_vf7xx		MACH_VYBRID_VF7XX	VYBRID_VF7XX		4145
-vybrid_vf6xx		MACH_VYBRID_VF6XX	VYBRID_VF6XX		4146
-vybrid_vf5xx		MACH_VYBRID_VF5XX	VYBRID_VF5XX		4147
-vybrid_vf4xx		MACH_VYBRID_VF4XX	VYBRID_VF4XX		4148
-aria_g25		MACH_ARIA_G25		ARIA_G25		4149
-bcm21553		MACH_BCM21553		BCM21553		4150
-smdk5410		MACH_SMDK5410		SMDK5410		4151
-lpc18xx			MACH_LPC18XX		LPC18XX			4152
-oratisparty		MACH_ORATISPARTY	ORATISPARTY		4153
-qseven			MACH_QSEVEN		QSEVEN			4154
-gmv_generic		MACH_GMV_GENERIC	GMV_GENERIC		4155
-th_link_eth		MACH_TH_LINK_ETH	TH_LINK_ETH		4156
-tn_muninn		MACH_TN_MUNINN		TN_MUNINN		4157
-rampage			MACH_RAMPAGE		RAMPAGE			4158
-visstrim_mv10		MACH_VISSTRIM_MV10	VISSTRIM_MV10		4159
-mx28_wilma		MACH_MX28_WILMA		MX28_WILMA		4164
-msm8625_ffa		MACH_MSM8625_FFA	MSM8625_FFA		4166
-vpu101			MACH_VPU101		VPU101			4167
-baileys			MACH_BAILEYS		BAILEYS			4169
-familybox		MACH_FAMILYBOX		FAMILYBOX		4170
-ensemble_mx35		MACH_ENSEMBLE_MX35	ENSEMBLE_MX35		4171
-sc_sps_1		MACH_SC_SPS_1		SC_SPS_1		4172
-ucsimply_sam9260	MACH_UCSIMPLY_SAM9260	UCSIMPLY_SAM9260	4173
-unicorn			MACH_UNICORN		UNICORN			4174
-m9g45a			MACH_M9G45A		M9G45A			4175
-mtwebif			MACH_MTWEBIF		MTWEBIF			4176
-playstone		MACH_PLAYSTONE		PLAYSTONE		4177
-chelsea			MACH_CHELSEA		CHELSEA			4178
-bayern			MACH_BAYERN		BAYERN			4179
-mitwo			MACH_MITWO		MITWO			4180
-mx25_noah		MACH_MX25_NOAH		MX25_NOAH		4181
-stm_b2020		MACH_STM_B2020		STM_B2020		4182
-annax_src		MACH_ANNAX_SRC		ANNAX_SRC		4183
-ionics_stratus		MACH_IONICS_STRATUS	IONICS_STRATUS		4184
-hugo			MACH_HUGO		HUGO			4185
-em300			MACH_EM300		EM300			4186
-mmp3_qseven		MACH_MMP3_QSEVEN	MMP3_QSEVEN		4187
-bosphorus2		MACH_BOSPHORUS2		BOSPHORUS2		4188
-tt2200			MACH_TT2200		TT2200			4189
-ocelot3			MACH_OCELOT3		OCELOT3			4190
-tek_cobra		MACH_TEK_COBRA		TEK_COBRA		4191
-protou			MACH_PROTOU		PROTOU			4192
-msm8625_evt		MACH_MSM8625_EVT	MSM8625_EVT		4193
-mx53_sellwood		MACH_MX53_SELLWOOD	MX53_SELLWOOD		4194
-somiq_am35		MACH_SOMIQ_AM35		SOMIQ_AM35		4195
-somiq_am37		MACH_SOMIQ_AM37		SOMIQ_AM37		4196
-k2_plc_cl		MACH_K2_PLC_CL		K2_PLC_CL		4197
-tc2			MACH_TC2		TC2			4198
-dulex_j			MACH_DULEX_J		DULEX_J			4199
-stm_b2044		MACH_STM_B2044		STM_B2044		4200
-deluxe_j		MACH_DELUXE_J		DELUXE_J		4201
-mango2443		MACH_MANGO2443		MANGO2443		4202
-cp2dcg			MACH_CP2DCG		CP2DCG			4203
-cp2dtg			MACH_CP2DTG		CP2DTG			4204
-cp2dug			MACH_CP2DUG		CP2DUG			4205
-var_som_am33		MACH_VAR_SOM_AM33	VAR_SOM_AM33		4206
-pepper			MACH_PEPPER		PEPPER			4207
-mango2450		MACH_MANGO2450		MANGO2450		4208
-valente_wx_c9		MACH_VALENTE_WX_C9	VALENTE_WX_C9		4209
-minitv			MACH_MINITV		MINITV			4210
-u8540			MACH_U8540		U8540			4211
-iv_atlas_i_z7e		MACH_IV_ATLAS_I_Z7E	IV_ATLAS_I_Z7E		4212
-mach_type_sky		MACH_MACH_TYPE_SKY	MACH_TYPE_SKY		4214
-bluesky			MACH_BLUESKY		BLUESKY			4215
-ngrouter		MACH_NGROUTER		NGROUTER		4216
-mx53_denetim		MACH_MX53_DENETIM	MX53_DENETIM		4217
-opal			MACH_OPAL		OPAL			4218
-gnet_us3gref		MACH_GNET_US3GREF	GNET_US3GREF		4219
-gnet_nc3g		MACH_GNET_NC3G		GNET_NC3G		4220
-gnet_ge3g		MACH_GNET_GE3G		GNET_GE3G		4221
-adp2			MACH_ADP2		ADP2			4222
-tqma28			MACH_TQMA28		TQMA28			4223
-kacom3			MACH_KACOM3		KACOM3			4224
-rrhdemo			MACH_RRHDEMO		RRHDEMO			4225
-protodug		MACH_PROTODUG		PROTODUG		4226
-lago			MACH_LAGO		LAGO			4227
-ktt30			MACH_KTT30		KTT30			4228
-ts43xx			MACH_TS43XX		TS43XX			4229
-mx6q_denso		MACH_MX6Q_DENSO		MX6Q_DENSO		4230
-comsat_gsmumts8		MACH_COMSAT_GSMUMTS8	COMSAT_GSMUMTS8		4231
-dreamx			MACH_DREAMX		DREAMX			4232
-thunderstonem		MACH_THUNDERSTONEM	THUNDERSTONEM		4233
-yoyopad			MACH_YOYOPAD		YOYOPAD			4234
-yoyopatient		MACH_YOYOPATIENT	YOYOPATIENT		4235
-a10l			MACH_A10L		A10L			4236
-mq60			MACH_MQ60		MQ60			4237
-linkstation_lsql	MACH_LINKSTATION_LSQL	LINKSTATION_LSQL	4238
-am3703gateway		MACH_AM3703GATEWAY	AM3703GATEWAY		4239
-accipiter		MACH_ACCIPITER		ACCIPITER		4240
-magnidug		MACH_MAGNIDUG		MAGNIDUG		4242
-hydra			MACH_HYDRA		HYDRA			4243
-sun3i			MACH_SUN3I		SUN3I			4244
-stm_b2078		MACH_STM_B2078		STM_B2078		4245
-at91sam9263deskv2	MACH_AT91SAM9263DESKV2	AT91SAM9263DESKV2	4246
-deluxe_r		MACH_DELUXE_R		DELUXE_R		4247
-p_98_v			MACH_P_98_V		P_98_V			4248
-p_98_c			MACH_P_98_C		P_98_C			4249
-davinci_am18xx_omn	MACH_DAVINCI_AM18XX_OMN	DAVINCI_AM18XX_OMN	4250
-socfpga_cyclone5	MACH_SOCFPGA_CYCLONE5	SOCFPGA_CYCLONE5	4251
-cabatuin		MACH_CABATUIN		CABATUIN		4252
-yoyopad_ft		MACH_YOYOPAD_FT		YOYOPAD_FT		4253
-dan2400evb		MACH_DAN2400EVB		DAN2400EVB		4254
-dan3400evb		MACH_DAN3400EVB		DAN3400EVB		4255
-edm_sf_imx6		MACH_EDM_SF_IMX6	EDM_SF_IMX6		4256
-edm_cf_imx6		MACH_EDM_CF_IMX6	EDM_CF_IMX6		4257
-vpos3xx			MACH_VPOS3XX		VPOS3XX			4258
-vulcano_9x5		MACH_VULCANO_9X5	VULCANO_9X5		4259
-spmp8000		MACH_SPMP8000		SPMP8000		4260
-catalina		MACH_CATALINA		CATALINA		4261
-rd88f5181l_fe		MACH_RD88F5181L_FE	RD88F5181L_FE		4262
-mx535_mx		MACH_MX535_MX		MX535_MX		4263
-armadillo840		MACH_ARMADILLO840	ARMADILLO840		4264
-spc9000baseboard	MACH_SPC9000BASEBOARD	SPC9000BASEBOARD	4265
-iris			MACH_IRIS		IRIS			4266
-protodcg		MACH_PROTODCG		PROTODCG		4267
-palmtree		MACH_PALMTREE		PALMTREE		4268
-novena			MACH_NOVENA		NOVENA			4269
-ma_um			MACH_MA_UM		MA_UM			4270
-ma_am			MACH_MA_AM		MA_AM			4271
-ems348			MACH_EMS348		EMS348			4272
-cm_fx6			MACH_CM_FX6		CM_FX6			4273
-arndale			MACH_ARNDALE		ARNDALE			4274
-q5xr5			MACH_Q5XR5		Q5XR5			4275
-willow			MACH_WILLOW		WILLOW			4276
-omap3621_odyv3		MACH_OMAP3621_ODYV3	OMAP3621_ODYV3		4277
-omapl138_presonus	MACH_OMAPL138_PRESONUS	OMAPL138_PRESONUS	4278
-dvf99			MACH_DVF99		DVF99			4279
-impression_j		MACH_IMPRESSION_J	IMPRESSION_J		4280
-qblissa9		MACH_QBLISSA9		QBLISSA9		4281
-robin_heliview10	MACH_ROBIN_HELIVIEW10	ROBIN_HELIVIEW10	4282
-sun7i			MACH_SUN7I		SUN7I			4283
-mx6q_hdmidongle		MACH_MX6Q_HDMIDONGLE	MX6Q_HDMIDONGLE		4284
-mx6_sid2		MACH_MX6_SID2		MX6_SID2		4285
-helios_v3		MACH_HELIOS_V3		HELIOS_V3		4286
-helios_v4		MACH_HELIOS_V4		HELIOS_V4		4287
-q7_imx6			MACH_Q7_IMX6		Q7_IMX6			4288
-odroidx			MACH_ODROIDX		ODROIDX			4289
-robpro			MACH_ROBPRO		ROBPRO			4290
-research59if_mk1	MACH_RESEARCH59IF_MK1	RESEARCH59IF_MK1	4291
-bobsleigh		MACH_BOBSLEIGH		BOBSLEIGH		4292
-dcshgwt3		MACH_DCSHGWT3		DCSHGWT3		4293
-gld1018			MACH_GLD1018		GLD1018			4294
-ev10			MACH_EV10		EV10			4295
-nitrogen6x		MACH_NITROGEN6X		NITROGEN6X		4296
-p_107_bb		MACH_P_107_BB		P_107_BB		4297
-evita_utl		MACH_EVITA_UTL		EVITA_UTL		4298
-falconwing		MACH_FALCONWING		FALCONWING		4299
-dct3			MACH_DCT3		DCT3			4300
-cpx2e_cell		MACH_CPX2E_CELL		CPX2E_CELL		4301
-amiro			MACH_AMIRO		AMIRO			4302
-mx6q_brassboard		MACH_MX6Q_BRASSBOARD	MX6Q_BRASSBOARD		4303
-dalmore			MACH_DALMORE		DALMORE			4304
-omap3_portal7cp		MACH_OMAP3_PORTAL7CP	OMAP3_PORTAL7CP		4305
-tegra_pluto		MACH_TEGRA_PLUTO	TEGRA_PLUTO		4306
-mx6sl_evk		MACH_MX6SL_EVK		MX6SL_EVK		4307
-m7			MACH_M7			M7			4308
-pxm2			MACH_PXM2		PXM2			4309
-haba_knx_lite		MACH_HABA_KNX_LITE	HABA_KNX_LITE		4310
-tai			MACH_TAI		TAI			4311
-prototd			MACH_PROTOTD		PROTOTD			4312
-dst_tonto		MACH_DST_TONTO		DST_TONTO		4313
-draco			MACH_DRACO		DRACO			4314
-dxr2			MACH_DXR2		DXR2			4315
-rut			MACH_RUT		RUT			4316
-am180x_wsc		MACH_AM180X_WSC		AM180X_WSC		4317
-deluxe_u		MACH_DELUXE_U		DELUXE_U		4318
-deluxe_ul		MACH_DELUXE_UL		DELUXE_UL		4319
-at91sam9260medths	MACH_AT91SAM9260MEDTHS	AT91SAM9260MEDTHS	4320
-matrix516		MACH_MATRIX516		MATRIX516		4321
-vid401x			MACH_VID401X		VID401X			4322
-helios_v5		MACH_HELIOS_V5		HELIOS_V5		4323
-playpaq2		MACH_PLAYPAQ2		PLAYPAQ2		4324
-igam			MACH_IGAM		IGAM			4325
-amico_i			MACH_AMICO_I		AMICO_I			4326
-amico_e			MACH_AMICO_E		AMICO_E			4327
-sentient_mm3_ck		MACH_SENTIENT_MM3_CK	SENTIENT_MM3_CK		4328
-smx6			MACH_SMX6		SMX6			4329
-pango			MACH_PANGO		PANGO			4330
-ns115_stick		MACH_NS115_STICK	NS115_STICK		4331
-bctrm3			MACH_BCTRM3		BCTRM3			4332
-doctorws		MACH_DOCTORWS		DOCTORWS		4333
-m2601			MACH_M2601		M2601			4334
-vgg1111			MACH_VGG1111		VGG1111			4337
-countach		MACH_COUNTACH		COUNTACH		4338
-visstrim_sm20		MACH_VISSTRIM_SM20	VISSTRIM_SM20		4339
-a639			MACH_A639		A639			4340
-spacemonkey		MACH_SPACEMONKEY	SPACEMONKEY		4341
-zpdu_stamp		MACH_ZPDU_STAMP		ZPDU_STAMP		4342
-htc_g7_clone		MACH_HTC_G7_CLONE	HTC_G7_CLONE		4343
-ft2080_corvus		MACH_FT2080_CORVUS	FT2080_CORVUS		4344
-fisland			MACH_FISLAND		FISLAND			4345
-zpdu			MACH_ZPDU		ZPDU			4346
 urt			MACH_URT		URT			4347
-conti_ovip		MACH_CONTI_OVIP		CONTI_OVIP		4348
-omapl138_nagra		MACH_OMAPL138_NAGRA	OMAPL138_NAGRA		4349
-da850_at3kp1		MACH_DA850_AT3KP1	DA850_AT3KP1		4350
-da850_at3kp2		MACH_DA850_AT3KP2	DA850_AT3KP2		4351
-surma			MACH_SURMA		SURMA			4352
-stm_b2092		MACH_STM_B2092		STM_B2092		4353
-mx535_ycr		MACH_MX535_YCR		MX535_YCR		4354
-m7_wl			MACH_M7_WL		M7_WL			4355
-m7_u			MACH_M7_U		M7_U			4356
-omap3_stndt_evm		MACH_OMAP3_STNDT_EVM	OMAP3_STNDT_EVM		4357
-m7_wlv			MACH_M7_WLV		M7_WLV			4358
-xam3517			MACH_XAM3517		XAM3517			4359
-a220			MACH_A220		A220			4360
-aclima_odie		MACH_ACLIMA_ODIE	ACLIMA_ODIE		4361
-vibble			MACH_VIBBLE		VIBBLE			4362
-k2_u			MACH_K2_U		K2_U			4363
-mx53_egf		MACH_MX53_EGF		MX53_EGF		4364
-novpek_imx53		MACH_NOVPEK_IMX53	NOVPEK_IMX53		4365
-novpek_imx6x		MACH_NOVPEK_IMX6X	NOVPEK_IMX6X		4366
-mx25_smartbox		MACH_MX25_SMARTBOX	MX25_SMARTBOX		4367
-eicg6410		MACH_EICG6410		EICG6410		4368
-picasso_e3		MACH_PICASSO_E3		PICASSO_E3		4369
-motonavigator		MACH_MOTONAVIGATOR	MOTONAVIGATOR		4370
-varioconnect2		MACH_VARIOCONNECT2	VARIOCONNECT2		4371
-deluxe_tw		MACH_DELUXE_TW		DELUXE_TW		4372
-kore3			MACH_KORE3		KORE3			4374
-mx6s_drs		MACH_MX6S_DRS		MX6S_DRS		4375
-cmimx6			MACH_CMIMX6		CMIMX6			4376
-roth			MACH_ROTH		ROTH			4377
-eq4ux			MACH_EQ4UX		EQ4UX			4378
-x1plus			MACH_X1PLUS		X1PLUS			4379
-modimx27		MACH_MODIMX27		MODIMX27		4380
-videon_hduac		MACH_VIDEON_HDUAC	VIDEON_HDUAC		4381
-blackbird		MACH_BLACKBIRD		BLACKBIRD		4382
-runmaster		MACH_RUNMASTER		RUNMASTER		4383
-ceres			MACH_CERES		CERES			4384
-nad435			MACH_NAD435		NAD435			4385
-ns115_proto_type	MACH_NS115_PROTO_TYPE	NS115_PROTO_TYPE	4386
-fs20_vcc		MACH_FS20_VCC		FS20_VCC		4387
-meson6tv_skt		MACH_MESON6TV_SKT	MESON6TV_SKT		4389
 keystone		MACH_KEYSTONE		KEYSTONE		4390
-pcm052			MACH_PCM052		PCM052			4391
-qrd_skud_prime		MACH_QRD_SKUD_PRIME	QRD_SKUD_PRIME		4393
-guf_santaro		MACH_GUF_SANTARO	GUF_SANTARO		4395
-sheepshead		MACH_SHEEPSHEAD		SHEEPSHEAD		4396
-mx6_iwg15m_mxm		MACH_MX6_IWG15M_MXM	MX6_IWG15M_MXM		4397
-mx6_iwg15m_q7		MACH_MX6_IWG15M_Q7	MX6_IWG15M_Q7		4398
-at91sam9263if8mic	MACH_AT91SAM9263IF8MIC	AT91SAM9263IF8MIC	4399
-marcopolo		MACH_MARCOPOLO		MARCOPOLO		4401
-mx535_sdcr		MACH_MX535_SDCR		MX535_SDCR		4402
-mx53_csb2733		MACH_MX53_CSB2733	MX53_CSB2733		4403
-diva			MACH_DIVA		DIVA			4404
-ncr_7744		MACH_NCR_7744		NCR_7744		4405
-macallan		MACH_MACALLAN		MACALLAN		4406
-wnr3500			MACH_WNR3500		WNR3500			4407
-pgavrf			MACH_PGAVRF		PGAVRF			4408
-helios_v6		MACH_HELIOS_V6		HELIOS_V6		4409
-lcct			MACH_LCCT		LCCT			4410
-csndug			MACH_CSNDUG		CSNDUG			4411
-wandboard_imx6		MACH_WANDBOARD_IMX6	WANDBOARD_IMX6		4412
-omap4_jet		MACH_OMAP4_JET		OMAP4_JET		4413
-tegra_roth		MACH_TEGRA_ROTH		TEGRA_ROTH		4414
-m7dcg			MACH_M7DCG		M7DCG			4415
-m7dug			MACH_M7DUG		M7DUG			4416
-m7dtg			MACH_M7DTG		M7DTG			4417
-ap42x			MACH_AP42X		AP42X			4418
-var_som_mx6		MACH_VAR_SOM_MX6	VAR_SOM_MX6		4419
-pdlu			MACH_PDLU		PDLU			4420
-hydrogen		MACH_HYDROGEN		HYDROGEN		4421
-npa211e			MACH_NPA211E		NPA211E			4422
-arcadia			MACH_ARCADIA		ARCADIA			4423
-arcadia_l		MACH_ARCADIA_L		ARCADIA_L		4424
-msm8930dt		MACH_MSM8930DT		MSM8930DT		4425
-ktam3874		MACH_KTAM3874		KTAM3874		4426
-cec4			MACH_CEC4		CEC4			4427
-ape6evm			MACH_APE6EVM		APE6EVM			4428
-tx6			MACH_TX6		TX6			4429
-cfa10037		MACH_CFA10037		CFA10037		4431
-ezp1000			MACH_EZP1000		EZP1000			4433
-wgr826v			MACH_WGR826V		WGR826V			4434
-exuma			MACH_EXUMA		EXUMA			4435
-fregate			MACH_FREGATE		FREGATE			4436
-osirisimx508		MACH_OSIRISIMX508	OSIRISIMX508		4437
-st_exigo		MACH_ST_EXIGO		ST_EXIGO		4438
-pismo			MACH_PISMO		PISMO			4439
-atc7			MACH_ATC7		ATC7			4440
-nspireclp		MACH_NSPIRECLP		NSPIRECLP		4441
-nspiretp		MACH_NSPIRETP		NSPIRETP		4442
-nspirecx		MACH_NSPIRECX		NSPIRECX		4443
-maya			MACH_MAYA		MAYA			4444
-wecct			MACH_WECCT		WECCT			4445
-m2s			MACH_M2S		M2S			4446
-msm8625q_evbd		MACH_MSM8625Q_EVBD	MSM8625Q_EVBD		4447
-tiny210			MACH_TINY210		TINY210			4448
-g3			MACH_G3			G3			4449
-hurricane		MACH_HURRICANE		HURRICANE		4450
-mx6_pod			MACH_MX6_POD		MX6_POD			4451
-elondcn			MACH_ELONDCN		ELONDCN			4452
-cwmx535			MACH_CWMX535		CWMX535			4453
-m7_wlj			MACH_M7_WLJ		M7_WLJ			4454
-qsp_arm			MACH_QSP_ARM		QSP_ARM			4455
-msm8625q_skud		MACH_MSM8625Q_SKUD	MSM8625Q_SKUD		4456
-htcmondrian		MACH_HTCMONDRIAN	HTCMONDRIAN		4457
-watson_ead		MACH_WATSON_EAD		WATSON_EAD		4458
-mitwoa			MACH_MITWOA		MITWOA			4459
-omap3_wolverine		MACH_OMAP3_WOLVERINE	OMAP3_WOLVERINE		4460
-mapletree		MACH_MAPLETREE		MAPLETREE		4461
-msm8625_fih_sae		MACH_MSM8625_FIH_SAE	MSM8625_FIH_SAE		4462
-epc35			MACH_EPC35		EPC35			4463
-smartrtu		MACH_SMARTRTU		SMARTRTU		4464
-rcm101			MACH_RCM101		RCM101			4465
-amx_imx53_mxx		MACH_AMX_IMX53_MXX	AMX_IMX53_MXX		4466
-acer_a12		MACH_ACER_A12		ACER_A12		4470
-sbc6x			MACH_SBC6X		SBC6X			4471
-u2			MACH_U2			U2			4472
-smdk4270		MACH_SMDK4270		SMDK4270		4473
-priscillag		MACH_PRISCILLAG		PRISCILLAG		4474
-priscillac		MACH_PRISCILLAC		PRISCILLAC		4475
-priscilla		MACH_PRISCILLA		PRISCILLA		4476
-innova_shpu_v2		MACH_INNOVA_SHPU_V2	INNOVA_SHPU_V2		4477
-mach_type_dep2410	MACH_MACH_TYPE_DEP2410	MACH_TYPE_DEP2410	4479
-bctre3			MACH_BCTRE3		BCTRE3			4480
-omap_m100		MACH_OMAP_M100		OMAP_M100		4481
-flo			MACH_FLO		FLO			4482
-nanobone		MACH_NANOBONE		NANOBONE		4483
-stm_b2105		MACH_STM_B2105		STM_B2105		4484
-omap4_bsc_bap_v3	MACH_OMAP4_BSC_BAP_V3	OMAP4_BSC_BAP_V3	4485
-ss1pam			MACH_SS1PAM		SS1PAM			4486
-primominiu		MACH_PRIMOMINIU		PRIMOMINIU		4488
-mrt_35hd_dualnas_e	MACH_MRT_35HD_DUALNAS_E	MRT_35HD_DUALNAS_E	4489
-kiwi			MACH_KIWI		KIWI			4490
-hw90496			MACH_HW90496		HW90496			4491
-mep2440			MACH_MEP2440		MEP2440			4492
-colibri_t30		MACH_COLIBRI_T30	COLIBRI_T30		4493
-cwv1			MACH_CWV1		CWV1			4494
-nsa325			MACH_NSA325		NSA325			4495
-dpxmtc			MACH_DPXMTC		DPXMTC			4497
-tt_stuttgart		MACH_TT_STUTTGART	TT_STUTTGART		4498
-miranda_apcii		MACH_MIRANDA_APCII	MIRANDA_APCII		4499
-mx6q_moderox		MACH_MX6Q_MODEROX	MX6Q_MODEROX		4500
-mudskipper		MACH_MUDSKIPPER		MUDSKIPPER		4501
-urania			MACH_URANIA		URANIA			4502
-stm_b2112		MACH_STM_B2112		STM_B2112		4503
-mx6q_ats_phoenix	MACH_MX6Q_ATS_PHOENIX	MX6Q_ATS_PHOENIX	4505
-stm_b2116		MACH_STM_B2116		STM_B2116		4506
-mythology		MACH_MYTHOLOGY		MYTHOLOGY		4507
-fc360v1			MACH_FC360V1		FC360V1			4508
-gps_sensor		MACH_GPS_SENSOR		GPS_SENSOR		4509
-gazelle			MACH_GAZELLE		GAZELLE			4510
-mpq8064_dma		MACH_MPQ8064_DMA	MPQ8064_DMA		4511
-wems_asd01		MACH_WEMS_ASD01		WEMS_ASD01		4512
-apalis_t30		MACH_APALIS_T30		APALIS_T30		4513
-armstonea9		MACH_ARMSTONEA9		ARMSTONEA9		4515
-omap_blazetablet	MACH_OMAP_BLAZETABLET	OMAP_BLAZETABLET	4516
-ar6mxq			MACH_AR6MXQ		AR6MXQ			4517
-ar6mxs			MACH_AR6MXS		AR6MXS			4518
-gwventana		MACH_GWVENTANA		GWVENTANA		4520
-igep0033		MACH_IGEP0033		IGEP0033		4521
-h52c1_concerto		MACH_H52C1_CONCERTO	H52C1_CONCERTO		4524
-fcmbrd			MACH_FCMBRD		FCMBRD			4525
-pcaaxs1			MACH_PCAAXS1		PCAAXS1			4526
-ls_orca			MACH_LS_ORCA		LS_ORCA			4527
-pcm051lb		MACH_PCM051LB		PCM051LB		4528
-mx6s_lp507_gvci		MACH_MX6S_LP507_GVCI	MX6S_LP507_GVCI		4529
-dido			MACH_DIDO		DIDO			4530
-swarco_itc3_9g20	MACH_SWARCO_ITC3_9G20	SWARCO_ITC3_9G20	4531
-robo_roady		MACH_ROBO_ROADY		ROBO_ROADY		4532
-rskrza1			MACH_RSKRZA1		RSKRZA1			4533
-swarco_sid		MACH_SWARCO_SID		SWARCO_SID		4534
-mx6_iwg15s_sbc		MACH_MX6_IWG15S_SBC	MX6_IWG15S_SBC		4535
-mx6q_camaro		MACH_MX6Q_CAMARO	MX6Q_CAMARO		4536
-hb6mxs			MACH_HB6MXS		HB6MXS			4537
-lager			MACH_LAGER		LAGER			4538
-lp8x4x			MACH_LP8X4X		LP8X4X			4539
-tegratab7		MACH_TEGRATAB7		TEGRATAB7		4540
-andromeda		MACH_ANDROMEDA		ANDROMEDA		4541
-bootes			MACH_BOOTES		BOOTES			4542
-nethmi			MACH_NETHMI		NETHMI			4543
-tegratab		MACH_TEGRATAB		TEGRATAB		4544
-som5_evb		MACH_SOM5_EVB		SOM5_EVB		4545
-venaticorum		MACH_VENATICORUM	VENATICORUM		4546
-stm_b2110		MACH_STM_B2110		STM_B2110		4547
-elux_hathor		MACH_ELUX_HATHOR	ELUX_HATHOR		4548
-helios_v7		MACH_HELIOS_V7		HELIOS_V7		4549
-xc10v1			MACH_XC10V1		XC10V1			4550
-cp2u			MACH_CP2U		CP2U			4551
-iap_f			MACH_IAP_F		IAP_F			4552
-iap_g			MACH_IAP_G		IAP_G			4553
-aae			MACH_AAE		AAE			4554
-pegasus			MACH_PEGASUS		PEGASUS			4555
-cygnus			MACH_CYGNUS		CYGNUS			4556
-centaurus		MACH_CENTAURUS		CENTAURUS		4557
-msm8930_qrd8930		MACH_MSM8930_QRD8930	MSM8930_QRD8930		4558
-quby_tim		MACH_QUBY_TIM		QUBY_TIM		4559
-zedi3250a		MACH_ZEDI3250A		ZEDI3250A		4560
-grus			MACH_GRUS		GRUS			4561
-apollo3			MACH_APOLLO3		APOLLO3			4562
-cowon_r7		MACH_COWON_R7		COWON_R7		4563
-tonga3			MACH_TONGA3		TONGA3			4564
-p535			MACH_P535		P535			4565
-sa3874i			MACH_SA3874I		SA3874I			4566
-mx6_navico_com		MACH_MX6_NAVICO_COM	MX6_NAVICO_COM		4567
-proxmobil2		MACH_PROXMOBIL2		PROXMOBIL2		4568
-ubinux1			MACH_UBINUX1		UBINUX1			4569
-istos			MACH_ISTOS		ISTOS			4570
-benvolio4		MACH_BENVOLIO4		BENVOLIO4		4571
-eco5_bx2		MACH_ECO5_BX2		ECO5_BX2		4572
-eukrea_cpuimx28sd	MACH_EUKREA_CPUIMX28SD	EUKREA_CPUIMX28SD	4573
-domotab			MACH_DOMOTAB		DOMOTAB			4574
-pfla03			MACH_PFLA03		PFLA03			4575
+ckb_rza1h		MACH_CKB_RZA1H		CKB_RZA1H		4780
+bcm2835			MACH_BCM2835		BCM2835			4828
+cm_3g			MACH_CM_3G		CM_3G			4943
+empc_aimx6		MACH_EMPC_AIMX6		EMPC_AIMX6		4958
+diyefis6410		MACH_DIYEFIS6410	DIYEFIS6410		5063
+mx53_turing		MACH_MX53_TURING	MX53_TURING		5064
+mx6dl_turing		MACH_MX6DL_TURING	MX6DL_TURING		5066
+mx53_indash		MACH_MX53_INDASH	MX53_INDASH		5067
+mx6q_indash		MACH_MX6Q_INDASH	MX6Q_INDASH		5068
+mx6dl_indash		MACH_MX6DL_INDASH	MX6DL_INDASH		5069
+rts_g6			MACH_RTS_G6		RTS_G6			5070
+ka_titan		MACH_KA_TITAN		KA_TITAN		5071
+cl_som_imx7		MACH_CL_SOM_IMX7	CL_SOM_IMX7		5072
+vvdn_mgsi_vsis		MACH_VVDN_MGSI_VSIS	VVDN_MGSI_VSIS		5073
+mx6q_nano		MACH_MX6Q_NANO		MX6Q_NANO		5074
+pdu001			MACH_PDU001		PDU001			5075
+cab_proyk		MACH_CAB_PROYK		CAB_PROYK		5076
+klin			MACH_KLIN		KLIN			5077
+enman_steuerbox		MACH_ENMAN_STEUERBOX	ENMAN_STEUERBOX		5078
+ls_stingray		MACH_LS_STINGRAY	LS_STINGRAY		5079
+ipdu			MACH_IPDU		IPDU			5080
+linda			MACH_LINDA		LINDA			5081
+mx6q_openrex		MACH_MX6Q_OPENREX	MX6Q_OPENREX		5082
+on100			MACH_ON100		ON100			5083
+eminds_rtu12		MACH_EMINDS_RTU12	EMINDS_RTU12		5084
+eminds_avl10		MACH_EMINDS_AVL10	EMINDS_AVL10		5085
+main_plc_lme		MACH_MAIN_PLC_LME	MAIN_PLC_LME		5086
+mspx			MACH_MSPX		MSPX			5087
+cgw_300			MACH_CGW_300		CGW_300			5088
+mx7d_cicada		MACH_MX7D_CICADA	MX7D_CICADA		5089
+virt2real_dm365		MACH_VIRT2REAL_DM365	VIRT2REAL_DM365		5090
+dm365_virt2real		MACH_DM365_VIRT2REAL	DM365_VIRT2REAL		5091
+h6073			MACH_H6073		H6073			5092
+gtgateway		MACH_GTGATEWAY		GTGATEWAY		5093
+xarina_standard		MACH_XARINA_STANDARD	XARINA_STANDARD		5094
+novasoms		MACH_NOVASOMS		NOVASOMS		5095
+novasomp		MACH_NOVASOMP		NOVASOMP		5096
+novasomu		MACH_NOVASOMU		NOVASOMU		5097
+mx6q_mpbd		MACH_MX6Q_MPBD		MX6Q_MPBD		5098
+ncr_1930		MACH_NCR_1930		NCR_1930		5099
+uap301			MACH_UAP301		UAP301			5100
+urt02			MACH_URT02		URT02			5101
+atc8			MACH_ATC8		ATC8			5102
+iot_gateway		MACH_IOT_GATEWAY	IOT_GATEWAY		5103
+hsm_phoenix		MACH_HSM_PHOENIX	HSM_PHOENIX		5104
+missouri		MACH_MISSOURI		MISSOURI		5105
+remarkable		MACH_REMARKABLE		REMARKABLE		5106
+fa0113			MACH_FA0113		FA0113			5107
+innova_statnettawm	MACH_INNOVA_STATNETTAWM	INNOVA_STATNETTAWM	5108
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/tools/Makefile linux-libre-4.10-rc8-gnu/arch/arm/tools/Makefile
--- linux-libre-4.9-gnu/arch/arm/tools/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/tools/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -4,10 +4,76 @@
 # Copyright (C) 2001 Russell King
 #
 
+gen := arch/$(ARCH)/include/generated
+kapi := $(gen)/asm
+uapi := $(gen)/uapi/asm
+syshdr := $(srctree)/$(src)/syscallhdr.sh
+sysnr := $(srctree)/$(src)/syscallnr.sh
+systbl := $(srctree)/$(src)/syscalltbl.sh
+syscall := $(srctree)/$(src)/syscall.tbl
+
+gen-y := $(gen)/calls-oabi.S
+gen-y += $(gen)/calls-eabi.S
+kapi-hdrs-y := $(kapi)/unistd-nr.h
+kapi-hdrs-y += $(kapi)/mach-types.h
+uapi-hdrs-y := $(uapi)/unistd-common.h
+uapi-hdrs-y += $(uapi)/unistd-oabi.h
+uapi-hdrs-y += $(uapi)/unistd-eabi.h
+
+targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y))
+
+PHONY += kapi uapi
+
+kapi:	$(kapi-hdrs-y) $(gen-y)
+
+uapi:	$(uapi-hdrs-y)
+
+# Create output directory if not already present
+_dummy := $(shell [ -d '$(kapi)' ] || mkdir -p '$(kapi)') \
+          $(shell [ -d '$(uapi)' ] || mkdir -p '$(uapi)')
+
 quiet_cmd_gen_mach = GEN     $@
       cmd_gen_mach = mkdir -p $(dir $@) && \
 		     $(AWK) -f $(filter-out $(PHONY),$^) > $@ || \
 		     { rm -f $@; /bin/false; }
 
-include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types FORCE
+$(kapi)/mach-types.h: $(src)/gen-mach-types $(src)/mach-types FORCE
 	$(call if_changed,gen_mach)
+
+quiet_cmd_syshdr = SYSHDR  $@
+      cmd_syshdr = $(CONFIG_SHELL) '$(syshdr)' '$<' '$@' \
+		   '$(syshdr_abi_$(basetarget))' \
+		   '$(syshdr_pfx_$(basetarget))' \
+		   '__NR_SYSCALL_BASE'
+
+quiet_cmd_systbl = SYSTBL  $@
+      cmd_systbl = $(CONFIG_SHELL) '$(systbl)' '$<' '$@' \
+		   '$(systbl_abi_$(basetarget))'
+
+quiet_cmd_sysnr  = SYSNR   $@
+      cmd_sysnr  = $(CONFIG_SHELL) '$(sysnr)' '$<' '$@' \
+		   '$(syshdr_abi_$(basetarget))'
+
+syshdr_abi_unistd-common := common
+$(uapi)/unistd-common.h: $(syscall) $(syshdr) FORCE
+	$(call if_changed,syshdr)
+
+syshdr_abi_unistd-oabi := oabi
+$(uapi)/unistd-oabi.h: $(syscall) $(syshdr) FORCE
+	$(call if_changed,syshdr)
+
+syshdr_abi_unistd-eabi := eabi
+$(uapi)/unistd-eabi.h: $(syscall) $(syshdr) FORCE
+	$(call if_changed,syshdr)
+
+sysnr_abi_unistd-nr := common,oabi,eabi,compat
+$(kapi)/unistd-nr.h: $(syscall) $(sysnr) FORCE
+	$(call if_changed,sysnr)
+
+systbl_abi_calls-oabi := common,oabi
+$(gen)/calls-oabi.S: $(syscall) $(systbl) FORCE
+	$(call if_changed,systbl)
+
+systbl_abi_calls-eabi := common,eabi
+$(gen)/calls-eabi.S: $(syscall) $(systbl) FORCE
+	$(call if_changed,systbl)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/tools/syscallhdr.sh linux-libre-4.10-rc8-gnu/arch/arm/tools/syscallhdr.sh
--- linux-libre-4.9-gnu/arch/arm/tools/syscallhdr.sh	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/tools/syscallhdr.sh	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+prefix="$4"
+offset="$5"
+
+fileguard=_ASM_ARM_`basename "$out" | sed \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+    -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'`
+if echo $out | grep -q uapi; then
+    fileguard="_UAPI$fileguard"
+fi
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | (
+    echo "#ifndef ${fileguard}"
+    echo "#define ${fileguard} 1"
+    echo ""
+
+    while read nr abi name entry ; do
+	if [ -z "$offset" ]; then
+	    echo "#define __NR_${prefix}${name} $nr"
+	else
+	    echo "#define __NR_${prefix}${name} ($offset + $nr)"
+        fi
+    done
+
+    echo ""
+    echo "#endif /* ${fileguard} */"
+) > "$out"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/tools/syscallnr.sh linux-libre-4.10-rc8-gnu/arch/arm/tools/syscallnr.sh
--- linux-libre-4.9-gnu/arch/arm/tools/syscallnr.sh	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/tools/syscallnr.sh	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,33 @@
+#!/bin/sh
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+align=1
+
+fileguard=_ASM_ARM_`basename "$out" | sed \
+    -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+    -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'`
+
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | tail -n1 | (
+    echo "#ifndef ${fileguard}
+#define ${fileguard} 1
+
+/*
+ * This needs to be greater than __NR_last_syscall+1 in order to account
+ * for the padding in the syscall table.
+ */
+"
+
+    while read nr abi name entry; do
+        nr=$(($nr + 1))
+        while [ "$(($nr / (256 * $align) ))" -gt 0 ]; do
+            align=$(( $align * 4 ))
+        done
+        nr=$(( ($nr + $align - 1) & ~($align - 1) ))
+        echo "/* aligned to $align */"
+        echo "#define __NR_syscalls $nr"
+    done
+
+    echo ""
+    echo "#endif /* ${fileguard} */"
+) > "$out"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/tools/syscall.tbl linux-libre-4.10-rc8-gnu/arch/arm/tools/syscall.tbl
--- linux-libre-4.9-gnu/arch/arm/tools/syscall.tbl	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/tools/syscall.tbl	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,413 @@
+#
+# Linux system call numbers and entry vectors
+#
+# The format is:
+# <num>	<abi>	<name>			[<entry point>			[<oabi compat entry point>]]
+#
+# Where abi is:
+#  common - for system calls shared between oabi and eabi (may have compat)
+#  oabi   - for oabi-only system calls (may have compat)
+#  eabi   - for eabi-only system calls
+#
+# For each syscall number, "common" is mutually exclusive with oabi and eabi
+#
+0	common	restart_syscall		sys_restart_syscall
+1	common	exit			sys_exit
+2	common	fork			sys_fork
+3	common	read			sys_read
+4	common	write			sys_write
+5	common	open			sys_open
+6	common	close			sys_close
+# 7 was sys_waitpid
+8	common	creat			sys_creat
+9	common	link			sys_link
+10	common	unlink			sys_unlink
+11	common	execve			sys_execve
+12	common	chdir			sys_chdir
+13	oabi	time			sys_time
+14	common	mknod			sys_mknod
+15	common	chmod			sys_chmod
+16	common	lchown			sys_lchown16
+# 17 was sys_break
+# 18 was sys_stat
+19	common	lseek			sys_lseek
+20	common	getpid			sys_getpid
+21	common	mount			sys_mount
+22	oabi	umount			sys_oldumount
+23	common	setuid			sys_setuid16
+24	common	getuid			sys_getuid16
+25	oabi	stime			sys_stime
+26	common	ptrace			sys_ptrace
+27	oabi	alarm			sys_alarm
+# 28 was sys_fstat
+29	common	pause			sys_pause
+30	oabi	utime			sys_utime
+# 31 was sys_stty
+# 32 was sys_gtty
+33	common	access			sys_access
+34	common	nice			sys_nice
+# 35 was sys_ftime
+36	common	sync			sys_sync
+37	common	kill			sys_kill
+38	common	rename			sys_rename
+39	common	mkdir			sys_mkdir
+40	common	rmdir			sys_rmdir
+41	common	dup			sys_dup
+42	common	pipe			sys_pipe
+43	common	times			sys_times
+# 44 was sys_prof
+45	common	brk			sys_brk
+46	common	setgid			sys_setgid16
+47	common	getgid			sys_getgid16
+# 48 was sys_signal
+49	common	geteuid			sys_geteuid16
+50	common	getegid			sys_getegid16
+51	common	acct			sys_acct
+52	common	umount2			sys_umount
+# 53 was sys_lock
+54	common	ioctl			sys_ioctl
+55	common	fcntl			sys_fcntl
+# 56 was sys_mpx
+57	common	setpgid			sys_setpgid
+# 58 was sys_ulimit
+# 59 was sys_olduname
+60	common	umask			sys_umask
+61	common	chroot			sys_chroot
+62	common	ustat			sys_ustat
+63	common	dup2			sys_dup2
+64	common	getppid			sys_getppid
+65	common	getpgrp			sys_getpgrp
+66	common	setsid			sys_setsid
+67	common	sigaction		sys_sigaction
+# 68 was sys_sgetmask
+# 69 was sys_ssetmask
+70	common	setreuid		sys_setreuid16
+71	common	setregid		sys_setregid16
+72	common	sigsuspend		sys_sigsuspend
+73	common	sigpending		sys_sigpending
+74	common	sethostname		sys_sethostname
+75	common	setrlimit		sys_setrlimit
+# Back compat 2GB limited rlimit
+76	oabi	getrlimit		sys_old_getrlimit
+77	common	getrusage		sys_getrusage
+78	common	gettimeofday		sys_gettimeofday
+79	common	settimeofday		sys_settimeofday
+80	common	getgroups		sys_getgroups16
+81	common	setgroups		sys_setgroups16
+82	oabi	select			sys_old_select
+83	common	symlink			sys_symlink
+# 84 was sys_lstat
+85	common	readlink		sys_readlink
+86	common	uselib			sys_uselib
+87	common	swapon			sys_swapon
+88	common	reboot			sys_reboot
+89	oabi	readdir			sys_old_readdir
+90	oabi	mmap			sys_old_mmap
+91	common	munmap			sys_munmap
+92	common	truncate		sys_truncate
+93	common	ftruncate		sys_ftruncate
+94	common	fchmod			sys_fchmod
+95	common	fchown			sys_fchown16
+96	common	getpriority		sys_getpriority
+97	common	setpriority		sys_setpriority
+# 98 was sys_profil
+99	common	statfs			sys_statfs
+100	common	fstatfs			sys_fstatfs
+# 101 was sys_ioperm
+102	oabi	socketcall		sys_socketcall		sys_oabi_socketcall
+103	common	syslog			sys_syslog
+104	common	setitimer		sys_setitimer
+105	common	getitimer		sys_getitimer
+106	common	stat			sys_newstat
+107	common	lstat			sys_newlstat
+108	common	fstat			sys_newfstat
+# 109 was sys_uname
+# 110 was sys_iopl
+111	common	vhangup			sys_vhangup
+# 112 was sys_idle
+# syscall to call a syscall!
+113	oabi	syscall			sys_syscall
+114	common	wait4			sys_wait4
+115	common	swapoff			sys_swapoff
+116	common	sysinfo			sys_sysinfo
+117	oabi	ipc			sys_ipc			sys_oabi_ipc
+118	common	fsync			sys_fsync
+119	common	sigreturn		sys_sigreturn_wrapper
+120	common	clone			sys_clone
+121	common	setdomainname		sys_setdomainname
+122	common	uname			sys_newuname
+# 123 was sys_modify_ldt
+124	common	adjtimex		sys_adjtimex
+125	common	mprotect		sys_mprotect
+126	common	sigprocmask		sys_sigprocmask
+# 127 was sys_create_module
+128	common	init_module		sys_init_module
+129	common	delete_module		sys_delete_module
+# 130 was sys_get_kernel_syms
+131	common	quotactl		sys_quotactl
+132	common	getpgid			sys_getpgid
+133	common	fchdir			sys_fchdir
+134	common	bdflush			sys_bdflush
+135	common	sysfs			sys_sysfs
+136	common	personality		sys_personality
+# 137 was sys_afs_syscall
+138	common	setfsuid		sys_setfsuid16
+139	common	setfsgid		sys_setfsgid16
+140	common	_llseek			sys_llseek
+141	common	getdents		sys_getdents
+142	common	_newselect		sys_select
+143	common	flock			sys_flock
+144	common	msync			sys_msync
+145	common	readv			sys_readv
+146	common	writev			sys_writev
+147	common	getsid			sys_getsid
+148	common	fdatasync		sys_fdatasync
+149	common	_sysctl			sys_sysctl
+150	common	mlock			sys_mlock
+151	common	munlock			sys_munlock
+152	common	mlockall		sys_mlockall
+153	common	munlockall		sys_munlockall
+154	common	sched_setparam		sys_sched_setparam
+155	common	sched_getparam		sys_sched_getparam
+156	common	sched_setscheduler	sys_sched_setscheduler
+157	common	sched_getscheduler	sys_sched_getscheduler
+158	common	sched_yield		sys_sched_yield
+159	common	sched_get_priority_max	sys_sched_get_priority_max
+160	common	sched_get_priority_min	sys_sched_get_priority_min
+161	common	sched_rr_get_interval	sys_sched_rr_get_interval
+162	common	nanosleep		sys_nanosleep
+163	common	mremap			sys_mremap
+164	common	setresuid		sys_setresuid16
+165	common	getresuid		sys_getresuid16
+# 166 was sys_vm86
+# 167 was sys_query_module
+168	common	poll			sys_poll
+169	common	nfsservctl
+170	common	setresgid		sys_setresgid16
+171	common	getresgid		sys_getresgid16
+172	common	prctl			sys_prctl
+173	common	rt_sigreturn		sys_rt_sigreturn_wrapper
+174	common	rt_sigaction		sys_rt_sigaction
+175	common	rt_sigprocmask		sys_rt_sigprocmask
+176	common	rt_sigpending		sys_rt_sigpending
+177	common	rt_sigtimedwait		sys_rt_sigtimedwait
+178	common	rt_sigqueueinfo		sys_rt_sigqueueinfo
+179	common	rt_sigsuspend		sys_rt_sigsuspend
+180	common	pread64			sys_pread64		sys_oabi_pread64
+181	common	pwrite64		sys_pwrite64		sys_oabi_pwrite64
+182	common	chown			sys_chown16
+183	common	getcwd			sys_getcwd
+184	common	capget			sys_capget
+185	common	capset			sys_capset
+186	common	sigaltstack		sys_sigaltstack
+187	common	sendfile		sys_sendfile
+# 188 reserved
+# 189 reserved
+190	common	vfork			sys_vfork
+# SuS compliant getrlimit
+191	common	ugetrlimit		sys_getrlimit
+192	common	mmap2			sys_mmap2
+193	common	truncate64		sys_truncate64		sys_oabi_truncate64
+194	common	ftruncate64		sys_ftruncate64		sys_oabi_ftruncate64
+195	common	stat64			sys_stat64		sys_oabi_stat64
+196	common	lstat64			sys_lstat64		sys_oabi_lstat64
+197	common	fstat64			sys_fstat64		sys_oabi_fstat64
+198	common	lchown32		sys_lchown
+199	common	getuid32		sys_getuid
+200	common	getgid32		sys_getgid
+201	common	geteuid32		sys_geteuid
+202	common	getegid32		sys_getegid
+203	common	setreuid32		sys_setreuid
+204	common	setregid32		sys_setregid
+205	common	getgroups32		sys_getgroups
+206	common	setgroups32		sys_setgroups
+207	common	fchown32		sys_fchown
+208	common	setresuid32		sys_setresuid
+209	common	getresuid32		sys_getresuid
+210	common	setresgid32		sys_setresgid
+211	common	getresgid32		sys_getresgid
+212	common	chown32			sys_chown
+213	common	setuid32		sys_setuid
+214	common	setgid32		sys_setgid
+215	common	setfsuid32		sys_setfsuid
+216	common	setfsgid32		sys_setfsgid
+217	common	getdents64		sys_getdents64
+218	common	pivot_root		sys_pivot_root
+219	common	mincore			sys_mincore
+220	common	madvise			sys_madvise
+221	common	fcntl64			sys_fcntl64		sys_oabi_fcntl64
+# 222 for tux
+# 223 is unused
+224	common	gettid			sys_gettid
+225	common	readahead		sys_readahead		sys_oabi_readahead
+226	common	setxattr		sys_setxattr
+227	common	lsetxattr		sys_lsetxattr
+228	common	fsetxattr		sys_fsetxattr
+229	common	getxattr		sys_getxattr
+230	common	lgetxattr		sys_lgetxattr
+231	common	fgetxattr		sys_fgetxattr
+232	common	listxattr		sys_listxattr
+233	common	llistxattr		sys_llistxattr
+234	common	flistxattr		sys_flistxattr
+235	common	removexattr		sys_removexattr
+236	common	lremovexattr		sys_lremovexattr
+237	common	fremovexattr		sys_fremovexattr
+238	common	tkill			sys_tkill
+239	common	sendfile64		sys_sendfile64
+240	common	futex			sys_futex
+241	common	sched_setaffinity	sys_sched_setaffinity
+242	common	sched_getaffinity	sys_sched_getaffinity
+243	common	io_setup		sys_io_setup
+244	common	io_destroy		sys_io_destroy
+245	common	io_getevents		sys_io_getevents
+246	common	io_submit		sys_io_submit
+247	common	io_cancel		sys_io_cancel
+248	common	exit_group		sys_exit_group
+249	common	lookup_dcookie		sys_lookup_dcookie
+250	common	epoll_create		sys_epoll_create
+251	common	epoll_ctl		sys_epoll_ctl		sys_oabi_epoll_ctl
+252	common	epoll_wait		sys_epoll_wait		sys_oabi_epoll_wait
+253	common	remap_file_pages	sys_remap_file_pages
+# 254 for set_thread_area
+# 255 for get_thread_area
+256	common	set_tid_address		sys_set_tid_address
+257	common	timer_create		sys_timer_create
+258	common	timer_settime		sys_timer_settime
+259	common	timer_gettime		sys_timer_gettime
+260	common	timer_getoverrun	sys_timer_getoverrun
+261	common	timer_delete		sys_timer_delete
+262	common	clock_settime		sys_clock_settime
+263	common	clock_gettime		sys_clock_gettime
+264	common	clock_getres		sys_clock_getres
+265	common	clock_nanosleep		sys_clock_nanosleep
+266	common	statfs64		sys_statfs64_wrapper
+267	common	fstatfs64		sys_fstatfs64_wrapper
+268	common	tgkill			sys_tgkill
+269	common	utimes			sys_utimes
+270	common	arm_fadvise64_64	sys_arm_fadvise64_64
+271	common	pciconfig_iobase	sys_pciconfig_iobase
+272	common	pciconfig_read		sys_pciconfig_read
+273	common	pciconfig_write		sys_pciconfig_write
+274	common	mq_open			sys_mq_open
+275	common	mq_unlink		sys_mq_unlink
+276	common	mq_timedsend		sys_mq_timedsend
+277	common	mq_timedreceive		sys_mq_timedreceive
+278	common	mq_notify		sys_mq_notify
+279	common	mq_getsetattr		sys_mq_getsetattr
+280	common	waitid			sys_waitid
+281	common	socket			sys_socket
+282	common	bind			sys_bind		sys_oabi_bind
+283	common	connect			sys_connect		sys_oabi_connect
+284	common	listen			sys_listen
+285	common	accept			sys_accept
+286	common	getsockname		sys_getsockname
+287	common	getpeername		sys_getpeername
+288	common	socketpair		sys_socketpair
+289	common	send			sys_send
+290	common	sendto			sys_sendto		sys_oabi_sendto
+291	common	recv			sys_recv
+292	common	recvfrom		sys_recvfrom
+293	common	shutdown		sys_shutdown
+294	common	setsockopt		sys_setsockopt
+295	common	getsockopt		sys_getsockopt
+296	common	sendmsg			sys_sendmsg		sys_oabi_sendmsg
+297	common	recvmsg			sys_recvmsg
+298	common	semop			sys_semop		sys_oabi_semop
+299	common	semget			sys_semget
+300	common	semctl			sys_semctl
+301	common	msgsnd			sys_msgsnd
+302	common	msgrcv			sys_msgrcv
+303	common	msgget			sys_msgget
+304	common	msgctl			sys_msgctl
+305	common	shmat			sys_shmat
+306	common	shmdt			sys_shmdt
+307	common	shmget			sys_shmget
+308	common	shmctl			sys_shmctl
+309	common	add_key			sys_add_key
+310	common	request_key		sys_request_key
+311	common	keyctl			sys_keyctl
+312	common	semtimedop		sys_semtimedop		sys_oabi_semtimedop
+313	common	vserver
+314	common	ioprio_set		sys_ioprio_set
+315	common	ioprio_get		sys_ioprio_get
+316	common	inotify_init		sys_inotify_init
+317	common	inotify_add_watch	sys_inotify_add_watch
+318	common	inotify_rm_watch	sys_inotify_rm_watch
+319	common	mbind			sys_mbind
+320	common	get_mempolicy		sys_get_mempolicy
+321	common	set_mempolicy		sys_set_mempolicy
+322	common	openat			sys_openat
+323	common	mkdirat			sys_mkdirat
+324	common	mknodat			sys_mknodat
+325	common	fchownat		sys_fchownat
+326	common	futimesat		sys_futimesat
+327	common	fstatat64		sys_fstatat64		sys_oabi_fstatat64
+328	common	unlinkat		sys_unlinkat
+329	common	renameat		sys_renameat
+330	common	linkat			sys_linkat
+331	common	symlinkat		sys_symlinkat
+332	common	readlinkat		sys_readlinkat
+333	common	fchmodat		sys_fchmodat
+334	common	faccessat		sys_faccessat
+335	common	pselect6		sys_pselect6
+336	common	ppoll			sys_ppoll
+337	common	unshare			sys_unshare
+338	common	set_robust_list		sys_set_robust_list
+339	common	get_robust_list		sys_get_robust_list
+340	common	splice			sys_splice
+341	common	arm_sync_file_range	sys_sync_file_range2
+342	common	tee			sys_tee
+343	common	vmsplice		sys_vmsplice
+344	common	move_pages		sys_move_pages
+345	common	getcpu			sys_getcpu
+346	common	epoll_pwait		sys_epoll_pwait
+347	common	kexec_load		sys_kexec_load
+348	common	utimensat		sys_utimensat
+349	common	signalfd		sys_signalfd
+350	common	timerfd_create		sys_timerfd_create
+351	common	eventfd			sys_eventfd
+352	common	fallocate		sys_fallocate
+353	common	timerfd_settime		sys_timerfd_settime
+354	common	timerfd_gettime		sys_timerfd_gettime
+355	common	signalfd4		sys_signalfd4
+356	common	eventfd2		sys_eventfd2
+357	common	epoll_create1		sys_epoll_create1
+358	common	dup3			sys_dup3
+359	common	pipe2			sys_pipe2
+360	common	inotify_init1		sys_inotify_init1
+361	common	preadv			sys_preadv
+362	common	pwritev			sys_pwritev
+363	common	rt_tgsigqueueinfo	sys_rt_tgsigqueueinfo
+364	common	perf_event_open		sys_perf_event_open
+365	common	recvmmsg		sys_recvmmsg
+366	common	accept4			sys_accept4
+367	common	fanotify_init		sys_fanotify_init
+368	common	fanotify_mark		sys_fanotify_mark
+369	common	prlimit64		sys_prlimit64
+370	common	name_to_handle_at	sys_name_to_handle_at
+371	common	open_by_handle_at	sys_open_by_handle_at
+372	common	clock_adjtime		sys_clock_adjtime
+373	common	syncfs			sys_syncfs
+374	common	sendmmsg		sys_sendmmsg
+375	common	setns			sys_setns
+376	common	process_vm_readv	sys_process_vm_readv
+377	common	process_vm_writev	sys_process_vm_writev
+378	common	kcmp			sys_kcmp
+379	common	finit_module		sys_finit_module
+380	common	sched_setattr		sys_sched_setattr
+381	common	sched_getattr		sys_sched_getattr
+382	common	renameat2		sys_renameat2
+383	common	seccomp			sys_seccomp
+384	common	getrandom		sys_getrandom
+385	common	memfd_create		sys_memfd_create
+386	common	bpf			sys_bpf
+387	common	execveat		sys_execveat
+388	common	userfaultfd		sys_userfaultfd
+389	common	membarrier		sys_membarrier
+390	common	mlock2			sys_mlock2
+391	common	copy_file_range		sys_copy_file_range
+392	common	preadv2			sys_preadv2
+393	common	pwritev2		sys_pwritev2
+394	common	pkey_mprotect		sys_pkey_mprotect
+395	common	pkey_alloc		sys_pkey_alloc
+396	common	pkey_free		sys_pkey_free
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/tools/syscalltbl.sh linux-libre-4.10-rc8-gnu/arch/arm/tools/syscalltbl.sh
--- linux-libre-4.9-gnu/arch/arm/tools/syscalltbl.sh	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/tools/syscalltbl.sh	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,21 @@
+#!/bin/sh
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | (
+    while read nr abi name entry compat; do
+        if [ "$abi" = "eabi" -a -n "$compat" ]; then
+            echo "$in: error: a compat entry for an EABI syscall ($name) makes no sense" >&2
+            exit 1
+        fi
+
+	if [ -n "$entry" ]; then
+            if [ -z "$compat" ]; then
+                echo "NATIVE($nr, $entry)"
+            else
+                echo "COMPAT($nr, $entry, $compat)"
+            fi
+        fi
+    done
+) > "$out"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/vfp/vfp.h linux-libre-4.10-rc8-gnu/arch/arm/vfp/vfp.h
--- linux-libre-4.9-gnu/arch/arm/vfp/vfp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/vfp/vfp.h	2017-02-12 16:03:20.000000000 -0500
@@ -155,8 +155,8 @@ struct vfp_single {
 	u32	significand;
 };
 
-extern s32 vfp_get_float(unsigned int reg);
-extern void vfp_put_float(s32 val, unsigned int reg);
+asmlinkage s32 vfp_get_float(unsigned int reg);
+asmlinkage void vfp_put_float(s32 val, unsigned int reg);
 
 /*
  * VFP_SINGLE_MANTISSA_BITS - number of bits in the mantissa
@@ -270,8 +270,8 @@ struct vfp_double {
 #else
 #define VFP_REG_ZERO	16
 #endif
-extern u64 vfp_get_double(unsigned int reg);
-extern void vfp_put_double(u64 val, unsigned int reg);
+asmlinkage u64 vfp_get_double(unsigned int reg);
+asmlinkage void vfp_put_double(u64 val, unsigned int reg);
 
 #define VFP_DOUBLE_MANTISSA_BITS	(52)
 #define VFP_DOUBLE_EXPONENT_BITS	(11)
@@ -377,4 +377,4 @@ struct op {
 	u32 flags;
 };
 
-extern void vfp_save_state(void *location, u32 fpexc);
+asmlinkage void vfp_save_state(void *location, u32 fpexc);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/vfp/vfpmodule.c linux-libre-4.10-rc8-gnu/arch/arm/vfp/vfpmodule.c
--- linux-libre-4.9-gnu/arch/arm/vfp/vfpmodule.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/vfp/vfpmodule.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,11 +34,11 @@
 /*
  * Our undef handlers (in entry.S)
  */
-void vfp_testing_entry(void);
-void vfp_support_entry(void);
-void vfp_null_entry(void);
+asmlinkage void vfp_testing_entry(void);
+asmlinkage void vfp_support_entry(void);
+asmlinkage void vfp_null_entry(void);
 
-void (*vfp_vector)(void) = vfp_null_entry;
+asmlinkage void (*vfp_vector)(void) = vfp_null_entry;
 
 /*
  * Dual-use variable.
@@ -799,7 +799,7 @@ static int __init vfp_init(void)
 	}
 
 	cpuhp_setup_state_nocalls(CPUHP_AP_ARM_VFP_STARTING,
-				  "AP_ARM_VFP_STARTING", vfp_starting_cpu,
+				  "arm/vfp:starting", vfp_starting_cpu,
 				  vfp_dying_cpu);
 
 	vfp_vector = vfp_support_entry;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/xen/enlighten.c linux-libre-4.10-rc8-gnu/arch/arm/xen/enlighten.c
--- linux-libre-4.9-gnu/arch/arm/xen/enlighten.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/xen/enlighten.c	2017-02-12 16:03:20.000000000 -0500
@@ -372,8 +372,7 @@ static int __init xen_guest_init(void)
 	 * for secondary CPUs as they are brought up.
 	 * For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
 	 */
-	xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
-			                       sizeof(struct vcpu_info));
+	xen_vcpu_info = alloc_percpu(struct vcpu_info);
 	if (xen_vcpu_info == NULL)
 		return -ENOMEM;
 
@@ -413,7 +412,7 @@ static int __init xen_guest_init(void)
 		pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);
 
 	return cpuhp_setup_state(CPUHP_AP_ARM_XEN_STARTING,
-				 "AP_ARM_XEN_STARTING", xen_starting_cpu,
+				 "arm/xen:starting", xen_starting_cpu,
 				 xen_dying_cpu);
 }
 early_initcall(xen_guest_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm/xen/mm.c linux-libre-4.10-rc8-gnu/arch/arm/xen/mm.c
--- linux-libre-4.9-gnu/arch/arm/xen/mm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm/xen/mm.c	2017-02-12 16:03:20.000000000 -0500
@@ -186,7 +186,6 @@ struct dma_map_ops *xen_dma_ops;
 EXPORT_SYMBOL(xen_dma_ops);
 
 static struct dma_map_ops xen_swiotlb_dma_ops = {
-	.mapping_error = xen_swiotlb_dma_mapping_error,
 	.alloc = xen_swiotlb_alloc_coherent,
 	.free = xen_swiotlb_free_coherent,
 	.sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,5 @@
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb
+
+always		:= $(dtb-y)
+subdir-y	:= $(dts-dirs)
+clean-files	:= *.dtb
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ * based on the Allwinner H3 dtsi:
+ *    Copyright (C) 2015 Jens Kuske <jenskuske@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <0>;
+			enable-method = "psci";
+		};
+
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <1>;
+			enable-method = "psci";
+		};
+
+		cpu2: cpu@2 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <2>;
+			enable-method = "psci";
+		};
+
+		cpu3: cpu@3 {
+			compatible = "arm,cortex-a53", "arm,armv8";
+			device_type = "cpu";
+			reg = <3>;
+			enable-method = "psci";
+		};
+	};
+
+	osc24M: osc24M_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "osc24M";
+	};
+
+	osc32k: osc32k_clk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		clock-output-names = "osc32k";
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		ccu: clock@01c20000 {
+			compatible = "allwinner,sun50i-a64-ccu";
+			reg = <0x01c20000 0x400>;
+			clocks = <&osc24M>, <&osc32k>;
+			clock-names = "hosc", "losc";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+		};
+
+		pio: pinctrl@1c20800 {
+			compatible = "allwinner,sun50i-a64-pinctrl";
+			reg = <0x01c20800 0x400>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu 58>;
+			gpio-controller;
+			#gpio-cells = <3>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+
+			i2c1_pins: i2c1_pins {
+				pins = "PH2", "PH3";
+				function = "i2c1";
+			};
+
+			uart0_pins_a: uart0@0 {
+				pins = "PB8", "PB9";
+				function = "uart0";
+			};
+		};
+
+		uart0: serial@1c28000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28000 0x400>;
+			interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu 67>;
+			resets = <&ccu 46>;
+			status = "disabled";
+		};
+
+		uart1: serial@1c28400 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28400 0x400>;
+			interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu 68>;
+			resets = <&ccu 47>;
+			status = "disabled";
+		};
+
+		uart2: serial@1c28800 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28800 0x400>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu 69>;
+			resets = <&ccu 48>;
+			status = "disabled";
+		};
+
+		uart3: serial@1c28c00 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c28c00 0x400>;
+			interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu 70>;
+			resets = <&ccu 49>;
+			status = "disabled";
+		};
+
+		uart4: serial@1c29000 {
+			compatible = "snps,dw-apb-uart";
+			reg = <0x01c29000 0x400>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			reg-shift = <2>;
+			reg-io-width = <4>;
+			clocks = <&ccu 71>;
+			resets = <&ccu 50>;
+			status = "disabled";
+		};
+
+		i2c0: i2c@1c2ac00 {
+			compatible = "allwinner,sun6i-a31-i2c";
+			reg = <0x01c2ac00 0x400>;
+			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu 63>;
+			resets = <&ccu 42>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c1: i2c@1c2b000 {
+			compatible = "allwinner,sun6i-a31-i2c";
+			reg = <0x01c2b000 0x400>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu 64>;
+			resets = <&ccu 43>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		i2c2: i2c@1c2b400 {
+			compatible = "allwinner,sun6i-a31-i2c";
+			reg = <0x01c2b400 0x400>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu 65>;
+			resets = <&ccu 44>;
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		gic: interrupt-controller@1c81000 {
+			compatible = "arm,gic-400";
+			reg = <0x01c81000 0x1000>,
+			      <0x01c82000 0x2000>,
+			      <0x01c84000 0x2000>,
+			      <0x01c86000 0x2000>;
+			interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+		};
+
+		rtc: rtc@1f00000 {
+			compatible = "allwinner,sun6i-a31-rtc";
+			reg = <0x01f00000 0x54>;
+			interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2016 ARM Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "sun50i-a64.dtsi"
+
+/ {
+	model = "Pine64";
+	compatible = "pine64,pine64", "allwinner,sun50i-a64";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pins_a>;
+	status = "okay";
+};
+
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
+	status = "okay";
+};
+
+&i2c1_pins {
+	bias-pull-up;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 ARM Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "sun50i-a64-pine64.dts"
+
+/ {
+	model = "Pine64+";
+	compatible = "pine64,pine64-plus", "allwinner,sun50i-a64";
+
+	/* TODO: Camera, Ethernet PHY, touchscreen, etc. */
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,9 +1,17 @@
+dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-nexbox-a95x.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-odroidc2.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p200.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-p201.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-pro.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-nexbox-a95x.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-q200.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxm-s912-q201.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxm-nexbox-a1.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -40,9 +40,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "meson-gx.dtsi"
 #include <dt-bindings/gpio/meson-gxbb-gpio.h>
 #include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 #include <dt-bindings/clock/gxbb-clkc.h>
@@ -51,106 +49,30 @@
 
 / {
 	compatible = "amlogic,meson-gxbb";
-	interrupt-parent = <&gic>;
-	#address-cells = <2>;
-	#size-cells = <2>;
-
-	cpus {
-		#address-cells = <0x2>;
-		#size-cells = <0x0>;
-
-		cpu0: cpu@0 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x0>;
-			enable-method = "psci";
-		};
-
-		cpu1: cpu@1 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x1>;
-			enable-method = "psci";
-		};
-
-		cpu2: cpu@2 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x2>;
-			enable-method = "psci";
-		};
-
-		cpu3: cpu@3 {
-			device_type = "cpu";
-			compatible = "arm,cortex-a53", "arm,armv8";
-			reg = <0x0 0x3>;
-			enable-method = "psci";
-		};
-	};
-
-	arm-pmu {
-		compatible = "arm,cortex-a53-pmu";
-		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
-	};
-
-	psci {
-		compatible = "arm,psci-0.2";
-		method = "smc";
-	};
-
-	firmware {
-		sm: secure-monitor {
-			compatible = "amlogic,meson-gxbb-sm";
-		};
-	};
 
-	efuse: efuse {
-		compatible = "amlogic,meson-gxbb-efuse";
-		#address-cells = <1>;
-		#size-cells = <1>;
+	scpi {
+		compatible = "amlogic,meson-gxbb-scpi", "arm,scpi-pre-1.0";
+		mboxes = <&mailbox 1 &mailbox 2>;
+		shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
 
-		sn: sn@14 {
-			reg = <0x14 0x10>;
-		};
+		scpi_clocks: clocks {
+			compatible = "arm,scpi-clocks";
 
-		eth_mac: eth_mac@34 {
-			reg = <0x34 0x10>;
+			scpi_dvfs: scpi_clocks@0 {
+				compatible = "arm,scpi-dvfs-clocks";
+				#clock-cells = <1>;
+				clock-indices = <0>;
+				clock-output-names = "vcpu";
+			};
 		};
 
-		bid: bid@46 {
-			reg = <0x46 0x30>;
+		scpi_sensors: sensors {
+			compatible = "arm,scpi-sensors";
+			#thermal-sensor-cells = <1>;
 		};
 	};
 
-	timer {
-		compatible = "arm,armv8-timer";
-		interrupts = <GIC_PPI 13
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
-			     <GIC_PPI 14
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
-			     <GIC_PPI 11
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
-			     <GIC_PPI 10
-			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
-	};
-
-	xtal: xtal-clk {
-		compatible = "fixed-clock";
-		clock-frequency = <24000000>;
-		clock-output-names = "xtal";
-		#clock-cells = <0>;
-	};
-
 	soc {
-		compatible = "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
-
 		usb0_phy: phy@c0000000 {
 			compatible = "amlogic,meson-gxbb-usb2-phy";
 			#phy-cells = <0>;
@@ -165,505 +87,426 @@
 			compatible = "amlogic,meson-gxbb-usb2-phy";
 			#phy-cells = <0>;
 			reg = <0x0 0xc0000020 0x0 0x20>;
+			resets = <&reset RESET_USB_OTG>;
 			clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB1>;
 			clock-names = "usb_general", "usb";
 			status = "disabled";
 		};
 
-		cbus: cbus@c1100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc1100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
-
-			reset: reset-controller@4404 {
-				compatible = "amlogic,meson-gxbb-reset";
-				reg = <0x0 0x04404 0x0 0x20>;
-				#reset-cells = <1>;
-			};
-
-			uart_A: serial@84c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x84c0 0x0 0x14>;
-				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			uart_B: serial@84dc {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x84dc 0x0 0x14>;
-				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			pwm_ab: pwm@8550 {
-				compatible = "amlogic,meson-gxbb-pwm";
-				reg = <0x0 0x08550 0x0 0x10>;
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			pwm_cd: pwm@8650 {
-				compatible = "amlogic,meson-gxbb-pwm";
-				reg = <0x0 0x08650 0x0 0x10>;
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			pwm_ef: pwm@86c0 {
-				compatible = "amlogic,meson-gxbb-pwm";
-				reg = <0x0 0x086c0 0x0 0x10>;
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			uart_C: serial@8700 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x8700 0x0 0x14>;
-				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
-			};
-
-			watchdog@98d0 {
-				compatible = "amlogic,meson-gxbb-wdt";
-				reg = <0x0 0x098d0 0x0 0x10>;
-				clocks = <&xtal>;
-			};
-
-			spifc: spi@8c80 {
-				compatible = "amlogic,meson-gxbb-spifc";
-				reg = <0x0 0x08c80 0x0 0x80>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-				clocks = <&clkc CLKID_SPI>;
-				status = "disabled";
-			};
+		sram: sram@c8000000 {
+			compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
+			reg = <0x0 0xc8000000 0x0 0x14000>;
 
-			i2c_A: i2c@8500 {
-				compatible = "amlogic,meson-gxbb-i2c";
-				reg = <0x0 0x08500 0x0 0x20>;
-				interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&clkc CLKID_I2C>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-				status = "disabled";
-			};
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x0 0xc8000000 0x14000>;
 
-			i2c_B: i2c@87c0 {
-				compatible = "amlogic,meson-gxbb-i2c";
-				reg = <0x0 0x087c0 0x0 0x20>;
-				interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&clkc CLKID_I2C>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-				status = "disabled";
+			cpu_scp_lpri: scp-shmem@0 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13000 0x400>;
 			};
 
-			i2c_C: i2c@87e0 {
-				compatible = "amlogic,meson-gxbb-i2c";
-				reg = <0x0 0x087e0 0x0 0x20>;
-				interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&clkc CLKID_I2C>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-				status = "disabled";
+			cpu_scp_hpri: scp-shmem@200 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
+				reg = <0x13400 0x400>;
 			};
 		};
 
-		gic: interrupt-controller@c4301000 {
-			compatible = "arm,gic-400";
-			reg = <0x0 0xc4301000 0 0x1000>,
-			      <0x0 0xc4302000 0 0x2000>,
-			      <0x0 0xc4304000 0 0x2000>,
-			      <0x0 0xc4306000 0 0x2000>;
-			interrupt-controller;
-			interrupts = <GIC_PPI 9
-				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
-			#interrupt-cells = <3>;
-			#address-cells = <0>;
+		usb0: usb@c9000000 {
+			compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
+			reg = <0x0 0xc9000000 0x0 0x40000>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clkc CLKID_USB0_DDR_BRIDGE>;
+			clock-names = "otg";
+			phys = <&usb0_phy>;
+			phy-names = "usb2-phy";
+			dr_mode = "host";
+			status = "disabled";
 		};
 
-		aobus: aobus@c8100000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc8100000 0x0 0x100000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
+		usb1: usb@c9100000 {
+			compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
+			reg = <0x0 0xc9100000 0x0 0x40000>;
+			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
+			clock-names = "otg";
+			phys = <&usb1_phy>;
+			phy-names = "usb2-phy";
+			dr_mode = "host";
+			status = "disabled";
+		};
+	};
+};
 
-			pinctrl_aobus: pinctrl@14 {
-				compatible = "amlogic,meson-gxbb-aobus-pinctrl";
-				#address-cells = <2>;
-				#size-cells = <2>;
-				ranges;
+&cpu0 {
+	clocks = <&scpi_dvfs 0>;
+};
 
-				gpio_ao: bank@14 {
-					reg = <0x0 0x00014 0x0 0x8>,
-					      <0x0 0x0002c 0x0 0x4>,
-					      <0x0 0x00024 0x0 0x8>;
-					reg-names = "mux", "pull", "gpio";
-					gpio-controller;
-					#gpio-cells = <2>;
-				};
+&cpu1 {
+	clocks = <&scpi_dvfs 0>;
+};
 
-				uart_ao_a_pins: uart_ao_a {
-					mux {
-						groups = "uart_tx_ao_a", "uart_rx_ao_a";
-						function = "uart_ao";
-					};
-				};
+&cpu2 {
+	clocks = <&scpi_dvfs 0>;
+};
 
-				remote_input_ao_pins: remote_input_ao {
-					mux {
-						groups = "remote_input_ao";
-						function = "remote_input_ao";
-					};
-				};
+&cpu3 {
+	clocks = <&scpi_dvfs 0>;
+};
 
-				i2c_ao_pins: i2c_ao {
-					mux {
-						groups = "i2c_sck_ao",
-						       "i2c_sda_ao";
-						function = "i2c_ao";
-					};
-				};
+&cbus {
+	spifc: spi@8c80 {
+		compatible = "amlogic,meson-gxbb-spifc";
+		reg = <0x0 0x08c80 0x0 0x80>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&clkc CLKID_SPI>;
+		status = "disabled";
+	};
+};
 
-				pwm_ao_a_3_pins: pwm_ao_a_3 {
-					mux {
-						groups = "pwm_ao_a_3";
-						function = "pwm_ao_a_3";
-					};
-				};
+&ethmac {
+	clocks = <&clkc CLKID_ETH>,
+		 <&clkc CLKID_FCLK_DIV2>,
+		 <&clkc CLKID_MPLL2>;
+	clock-names = "stmmaceth", "clkin0", "clkin1";
+};
 
-				pwm_ao_a_6_pins: pwm_ao_a_6 {
-					mux {
-						groups = "pwm_ao_a_6";
-						function = "pwm_ao_a_6";
-					};
-				};
+&aobus {
+	pinctrl_aobus: pinctrl@14 {
+		compatible = "amlogic,meson-gxbb-aobus-pinctrl";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
 
-				pwm_ao_a_12_pins: pwm_ao_a_12 {
-					mux {
-						groups = "pwm_ao_a_12";
-						function = "pwm_ao_a_12";
-					};
-				};
+		gpio_ao: bank@14 {
+			reg = <0x0 0x00014 0x0 0x8>,
+			      <0x0 0x0002c 0x0 0x4>,
+			      <0x0 0x00024 0x0 0x8>;
+			reg-names = "mux", "pull", "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
 
-				pwm_ao_b_pins: pwm_ao_b {
-					mux {
-						groups = "pwm_ao_b";
-						function = "pwm_ao_b";
-					};
-				};
+		uart_ao_a_pins: uart_ao_a {
+			mux {
+				groups = "uart_tx_ao_a", "uart_rx_ao_a";
+				function = "uart_ao";
 			};
+		};
 
-			clkc_AO: clock-controller@040 {
-				compatible = "amlogic,gxbb-aoclkc";
-				reg = <0x0 0x00040 0x0 0x4>;
-				#clock-cells = <1>;
-				#reset-cells = <1>;
+		remote_input_ao_pins: remote_input_ao {
+			mux {
+				groups = "remote_input_ao";
+				function = "remote_input_ao";
 			};
+		};
 
-			uart_AO: serial@4c0 {
-				compatible = "amlogic,meson-uart";
-				reg = <0x0 0x004c0 0x0 0x14>;
-				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&xtal>;
-				status = "disabled";
+		i2c_ao_pins: i2c_ao {
+			mux {
+				groups = "i2c_sck_ao",
+				       "i2c_sda_ao";
+				function = "i2c_ao";
 			};
+		};
 
-			ir: ir@580 {
-				compatible = "amlogic,meson-gxbb-ir";
-				reg = <0x0 0x00580 0x0 0x40>;
-				interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
-				status = "disabled";
+		pwm_ao_a_3_pins: pwm_ao_a_3 {
+			mux {
+				groups = "pwm_ao_a_3";
+				function = "pwm_ao_a_3";
 			};
+		};
 
-			pwm_ab_AO: pwm@550 {
-				compatible = "amlogic,meson-gxbb-pwm";
-				reg = <0x0 0x0550 0x0 0x10>;
-				#pwm-cells = <3>;
-				status = "disabled";
+		pwm_ao_a_6_pins: pwm_ao_a_6 {
+			mux {
+				groups = "pwm_ao_a_6";
+				function = "pwm_ao_a_6";
 			};
+		};
 
-			i2c_AO: i2c@500 {
-				compatible = "amlogic,meson-gxbb-i2c";
-				reg = <0x0 0x500 0x0 0x20>;
-				interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
-				clocks = <&clkc CLKID_AO_I2C>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-				status = "disabled";
+		pwm_ao_a_12_pins: pwm_ao_a_12 {
+			mux {
+				groups = "pwm_ao_a_12";
+				function = "pwm_ao_a_12";
 			};
 		};
 
-		periphs: periphs@c8834000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc8834000 0x0 0x2000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
-
-			rng {
-				compatible = "amlogic,meson-rng";
-				reg = <0x0 0x0 0x0 0x4>;
+		pwm_ao_b_pins: pwm_ao_b {
+			mux {
+				groups = "pwm_ao_b";
+				function = "pwm_ao_b";
 			};
+		};
+	};
 
-			pinctrl_periphs: pinctrl@4b0 {
-				compatible = "amlogic,meson-gxbb-periphs-pinctrl";
-				#address-cells = <2>;
-				#size-cells = <2>;
-				ranges;
-
-				gpio: bank@4b0 {
-					reg = <0x0 0x004b0 0x0 0x28>,
-					      <0x0 0x004e8 0x0 0x14>,
-					      <0x0 0x00120 0x0 0x14>,
-					      <0x0 0x00430 0x0 0x40>;
-					reg-names = "mux", "pull", "pull-enable", "gpio";
-					gpio-controller;
-					#gpio-cells = <2>;
-				};
-
-				emmc_pins: emmc {
-					mux {
-						groups = "emmc_nand_d07",
-						       "emmc_cmd",
-						       "emmc_clk";
-						function = "emmc";
-					};
-				};
-
-				nor_pins: nor {
-					mux {
-						groups = "nor_d",
-						       "nor_q",
-						       "nor_c",
-						       "nor_cs";
-						function = "nor";
-					};
-				};
+	clkc_AO: clock-controller@040 {
+		compatible = "amlogic,gxbb-aoclkc";
+		reg = <0x0 0x00040 0x0 0x4>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
 
-				sdcard_pins: sdcard {
-					mux {
-						groups = "sdcard_d0",
-						       "sdcard_d1",
-						       "sdcard_d2",
-						       "sdcard_d3",
-						       "sdcard_cmd",
-						       "sdcard_clk";
-						function = "sdcard";
-					};
-				};
+	pwm_ab_AO: pwm@550 {
+		compatible = "amlogic,meson-gxbb-pwm";
+		reg = <0x0 0x0550 0x0 0x10>;
+		#pwm-cells = <3>;
+		status = "disabled";
+	};
 
-				sdio_pins: sdio {
-					mux {
-						groups = "sdio_d0",
-						       "sdio_d1",
-						       "sdio_d2",
-						       "sdio_d3",
-						       "sdio_cmd",
-						       "sdio_clk";
-						function = "sdio";
-					};
-				};
+	i2c_AO: i2c@500 {
+		compatible = "amlogic,meson-gxbb-i2c";
+		reg = <0x0 0x500 0x0 0x20>;
+		interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_AO_I2C>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+};
 
-				sdio_irq_pins: sdio_irq {
-					mux {
-						groups = "sdio_irq";
-						function = "sdio";
-					};
-				};
+&periphs {
+	pinctrl_periphs: pinctrl@4b0 {
+		compatible = "amlogic,meson-gxbb-periphs-pinctrl";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
 
-				uart_a_pins: uart_a {
-					mux {
-						groups = "uart_tx_a",
-						       "uart_rx_a";
-						function = "uart_a";
-					};
-				};
+		gpio: bank@4b0 {
+			reg = <0x0 0x004b0 0x0 0x28>,
+			      <0x0 0x004e8 0x0 0x14>,
+			      <0x0 0x00120 0x0 0x14>,
+			      <0x0 0x00430 0x0 0x40>;
+			reg-names = "mux", "pull", "pull-enable", "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
 
-				uart_b_pins: uart_b {
-					mux {
-						groups = "uart_tx_b",
-						       "uart_rx_b";
-						function = "uart_b";
-					};
-				};
+		emmc_pins: emmc {
+			mux {
+				groups = "emmc_nand_d07",
+				       "emmc_cmd",
+				       "emmc_clk",
+				       "emmc_ds";
+				function = "emmc";
+			};
+		};
 
-				uart_c_pins: uart_c {
-					mux {
-						groups = "uart_tx_c",
-						       "uart_rx_c";
-						function = "uart_c";
-					};
-				};
+		nor_pins: nor {
+			mux {
+				groups = "nor_d",
+				       "nor_q",
+				       "nor_c",
+				       "nor_cs";
+				function = "nor";
+			};
+		};
 
-				i2c_a_pins: i2c_a {
-					mux {
-						groups = "i2c_sck_a",
-						       "i2c_sda_a";
-						function = "i2c_a";
-					};
-				};
+		sdcard_pins: sdcard {
+			mux {
+				groups = "sdcard_d0",
+				       "sdcard_d1",
+				       "sdcard_d2",
+				       "sdcard_d3",
+				       "sdcard_cmd",
+				       "sdcard_clk";
+				function = "sdcard";
+			};
+		};
 
-				i2c_b_pins: i2c_b {
-					mux {
-						groups = "i2c_sck_b",
-						       "i2c_sda_b";
-						function = "i2c_b";
-					};
-				};
+		sdio_pins: sdio {
+			mux {
+				groups = "sdio_d0",
+				       "sdio_d1",
+				       "sdio_d2",
+				       "sdio_d3",
+				       "sdio_cmd",
+				       "sdio_clk";
+				function = "sdio";
+			};
+		};
 
-				i2c_c_pins: i2c_c {
-					mux {
-						groups = "i2c_sck_c",
-						       "i2c_sda_c";
-						function = "i2c_c";
-					};
-				};
+		sdio_irq_pins: sdio_irq {
+			mux {
+				groups = "sdio_irq";
+				function = "sdio";
+			};
+		};
 
-				eth_pins: eth_c {
-					mux {
-						groups = "eth_mdio",
-						       "eth_mdc",
-						       "eth_clk_rx_clk",
-						       "eth_rx_dv",
-						       "eth_rxd0",
-						       "eth_rxd1",
-						       "eth_rxd2",
-						       "eth_rxd3",
-						       "eth_rgmii_tx_clk",
-						       "eth_tx_en",
-						       "eth_txd0",
-						       "eth_txd1",
-						       "eth_txd2",
-						       "eth_txd3";
-						function = "eth";
-					};
-				};
+		uart_a_pins: uart_a {
+			mux {
+				groups = "uart_tx_a",
+				       "uart_rx_a";
+				function = "uart_a";
+			};
+		};
 
-				pwm_a_x_pins: pwm_a_x {
-					mux {
-						groups = "pwm_a_x";
-						function = "pwm_a_x";
-					};
-				};
+		uart_b_pins: uart_b {
+			mux {
+				groups = "uart_tx_b",
+				       "uart_rx_b";
+				function = "uart_b";
+			};
+		};
 
-				pwm_a_y_pins: pwm_a_y {
-					mux {
-						groups = "pwm_a_y";
-						function = "pwm_a_y";
-					};
-				};
+		uart_c_pins: uart_c {
+			mux {
+				groups = "uart_tx_c",
+				       "uart_rx_c";
+				function = "uart_c";
+			};
+		};
 
-				pwm_b_pins: pwm_b {
-					mux {
-						groups = "pwm_b";
-						function = "pwm_b";
-					};
-				};
+		i2c_a_pins: i2c_a {
+			mux {
+				groups = "i2c_sck_a",
+				       "i2c_sda_a";
+				function = "i2c_a";
+			};
+		};
 
-				pwm_d_pins: pwm_d {
-					mux {
-						groups = "pwm_d";
-						function = "pwm_d";
-					};
-				};
+		i2c_b_pins: i2c_b {
+			mux {
+				groups = "i2c_sck_b",
+				       "i2c_sda_b";
+				function = "i2c_b";
+			};
+		};
 
-				pwm_e_pins: pwm_e {
-					mux {
-						groups = "pwm_e";
-						function = "pwm_e";
-					};
-				};
+		i2c_c_pins: i2c_c {
+			mux {
+				groups = "i2c_sck_c",
+				       "i2c_sda_c";
+				function = "i2c_c";
+			};
+		};
 
-				pwm_f_x_pins: pwm_f_x {
-					mux {
-						groups = "pwm_f_x";
-						function = "pwm_f_x";
-					};
-				};
+		eth_rgmii_pins: eth-rgmii {
+			mux {
+				groups = "eth_mdio",
+				       "eth_mdc",
+				       "eth_clk_rx_clk",
+				       "eth_rx_dv",
+				       "eth_rxd0",
+				       "eth_rxd1",
+				       "eth_rxd2",
+				       "eth_rxd3",
+				       "eth_rgmii_tx_clk",
+				       "eth_tx_en",
+				       "eth_txd0",
+				       "eth_txd1",
+				       "eth_txd2",
+				       "eth_txd3";
+				function = "eth";
+			};
+		};
 
-				pwm_f_y_pins: pwm_f_y {
-					mux {
-						groups = "pwm_f_y";
-						function = "pwm_f_y";
-					};
-				};
+		eth_rmii_pins: eth-rmii {
+			mux {
+				groups = "eth_mdio",
+				       "eth_mdc",
+				       "eth_clk_rx_clk",
+				       "eth_rx_dv",
+				       "eth_rxd0",
+				       "eth_rxd1",
+				       "eth_tx_en",
+				       "eth_txd0",
+				       "eth_txd1";
+				function = "eth";
 			};
 		};
 
-		hiubus: hiubus@c883c000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xc883c000 0x0 0x2000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
+		pwm_a_x_pins: pwm_a_x {
+			mux {
+				groups = "pwm_a_x";
+				function = "pwm_a_x";
+			};
+		};
 
-			clkc: clock-controller@0 {
-				compatible = "amlogic,gxbb-clkc";
-				#clock-cells = <1>;
-				reg = <0x0 0x0 0x0 0x3db>;
+		pwm_a_y_pins: pwm_a_y {
+			mux {
+				groups = "pwm_a_y";
+				function = "pwm_a_y";
 			};
+		};
 
-			mailbox: mailbox@404 {
-				compatible = "amlogic,meson-gxbb-mhu";
-				reg = <0 0x404 0 0x4c>;
-				interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
-					     <0 209 IRQ_TYPE_EDGE_RISING>,
-					     <0 210 IRQ_TYPE_EDGE_RISING>;
-				#mbox-cells = <1>;
+		pwm_b_pins: pwm_b {
+			mux {
+				groups = "pwm_b";
+				function = "pwm_b";
 			};
 		};
 
-		apb: apb@d0000000 {
-			compatible = "simple-bus";
-			reg = <0x0 0xd0000000 0x0 0x200000>;
-			#address-cells = <2>;
-			#size-cells = <2>;
-			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+		pwm_d_pins: pwm_d {
+			mux {
+				groups = "pwm_d";
+				function = "pwm_d";
+			};
 		};
 
-		usb0: usb@c9000000 {
-			compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
-			reg = <0x0 0xc9000000 0x0 0x40000>;
-			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clkc CLKID_USB0_DDR_BRIDGE>;
-			clock-names = "otg";
-			phys = <&usb0_phy>;
-			phy-names = "usb2-phy";
-			dr_mode = "host";
-			status = "disabled";
+		pwm_e_pins: pwm_e {
+			mux {
+				groups = "pwm_e";
+				function = "pwm_e";
+			};
 		};
 
-		usb1: usb@c9100000 {
-			compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
-			reg = <0x0 0xc9100000 0x0 0x40000>;
-			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
-			clock-names = "otg";
-			phys = <&usb1_phy>;
-			phy-names = "usb2-phy";
-			dr_mode = "host";
-			status = "disabled";
+		pwm_f_x_pins: pwm_f_x {
+			mux {
+				groups = "pwm_f_x";
+				function = "pwm_f_x";
+			};
 		};
 
-		ethmac: ethernet@c9410000 {
-			compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
-			reg = <0x0 0xc9410000 0x0 0x10000
-			       0x0 0xc8834540 0x0 0x4>;
-			interrupts = <0 8 1>;
-			interrupt-names = "macirq";
-			clocks = <&clkc CLKID_ETH>,
-				 <&clkc CLKID_FCLK_DIV2>,
-				 <&clkc CLKID_MPLL2>;
-			clock-names = "stmmaceth", "clkin0", "clkin1";
-			phy-mode = "rgmii";
-			status = "disabled";
+		pwm_f_y_pins: pwm_f_y {
+			mux {
+				groups = "pwm_f_y";
+				function = "pwm_f_y";
+			};
 		};
 	};
 };
+
+&hiubus {
+	clkc: clock-controller@0 {
+		compatible = "amlogic,gxbb-clkc";
+		#clock-cells = <1>;
+		reg = <0x0 0x0 0x0 0x3db>;
+	};
+};
+
+&i2c_A {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&i2c_B {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&i2c_C {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&sd_emmc_a {
+	clocks = <&clkc CLKID_SD_EMMC_A>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_b {
+	clocks = <&clkc CLKID_SD_EMMC_B>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_c {
+	clocks = <&clkc CLKID_SD_EMMC_C>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&vpu {
+	compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Neil Armstrong <narmstrong@kernel.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxbb.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	compatible = "nexbox,a95x", "amlogic,meson-gxbb";
+	model = "NEXBOX A95X";
+	
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x40000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		blue {
+			label = "a95x:system-status";
+			gpios = <&gpio_ao GPIOAO_13 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <100>;
+
+		button@0 {
+			label = "reset";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	vddio_card: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "VDDIO_CARD";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+
+		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+		states = <1800000 0
+			  3300000 1>;
+	};
+
+	vddio_boot: regulator-vddio_boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_3v3: regulator-vcc_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
+
+	cvbs-connector {
+		compatible = "composite-video-connector";
+
+		port {
+			cvbs_connector_in: endpoint {
+				remote-endpoint = <&cvbs_vdac_out>;
+			};
+		};
+	};
+};
+
+&uart_AO {
+	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&ethmac {
+	status = "okay";
+	pinctrl-0 = <&eth_rmii_pins>;
+	pinctrl-names = "default";
+	phy-mode = "rmii";
+};
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
+	pinctrl-names = "default";
+};
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&sdio_pwrseq>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_card>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+	clocks = <&clkc CLKID_FCLK_DIV4>;
+	clock-names = "clkin0";
+};
+
+&cvbs_vdac_port {
+	cvbs_vdac_out: endpoint {
+		remote-endpoint = <&cvbs_connector_in>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,18 @@
 		reg = <0x0 0x0 0x0 0x80000000>;
 	};
 
+	usb_otg_pwr: regulator-usb-pwrs {
+		compatible = "regulator-fixed";
+
+		regulator-name = "USB_OTG_PWR";
+
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+
+		gpio = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		blue {
@@ -73,6 +85,60 @@
 			default-state = "off";
 		};
 	};
+
+	tflash_vdd: regulator-tflash_vdd {
+		/*
+		 * signal name from schematics: TFLASH_VDD_EN
+		 */
+		compatible = "regulator-fixed";
+
+		regulator-name = "TFLASH_VDD";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio_ao GPIOAO_12 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	tf_io: gpio-regulator-tf_io {
+		compatible = "regulator-gpio";
+
+		regulator-name = "TF_IO";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		/*
+		 * signal name from schematics: TF_3V3N_1V8_EN
+		 */
+		gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_HIGH>;
+		gpios-states = <0>;
+
+		states = <3300000 0
+			  1800000 1>;
+	};
+
+	vcc1v8: regulator-vcc1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vcc3v3: regulator-vcc3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+};
+
+&scpi_clocks {
+	status = "disabled";
 };
 
 &uart_AO {
@@ -83,8 +149,20 @@
 
 &ethmac {
 	status = "okay";
-	pinctrl-0 = <&eth_pins>;
+	pinctrl-0 = <&eth_rgmii_pins>;
 	pinctrl-names = "default";
+	phy-handle = <&eth_phy0>;
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		eth_phy0: ethernet-phy@0 {
+			reg = <0>;
+			eee-broken-1000t;
+		};
+	};
 };
 
 &ir {
@@ -98,3 +176,58 @@
 	pinctrl-0 = <&i2c_a_pins>;
 	pinctrl-names = "default";
 };
+
+&usb0_phy {
+	status = "okay";
+	phy-supply = <&usb_otg_pwr>;
+};
+
+&usb1_phy {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+};
+
+&usb1 {
+	status = "okay";
+};
+
+/* SD */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&tflash_vdd>;
+	vqmmc-supply = <&tf_io>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	cap-mmc-highspeed;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc3v3>;
+	vqmmc-supply = <&vcc1v8>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -70,6 +70,71 @@
 		gpio = <&gpio GPIODV_24 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	vddio_card: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "VDDIO_CARD";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+
+		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+		states = <1800000 0
+			  3300000 1>;
+	};
+
+	vddio_boot: regulator-vddio_boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_3v3: regulator-vcc_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
+
+	cvbs-connector {
+		compatible = "composite-video-connector";
+
+		port {
+			cvbs_connector_in: endpoint {
+				remote-endpoint = <&cvbs_vdac_out>;
+			};
+		};
+	};
 };
 
 /* This UART is brought out to the DB9 connector */
@@ -81,7 +146,7 @@
 
 &ethmac {
 	status = "okay";
-	pinctrl-0 = <&eth_pins>;
+	pinctrl-0 = <&eth_rgmii_pins>;
 	pinctrl-names = "default";
 };
 
@@ -107,3 +172,81 @@
 &usb1 {
 	status = "okay";
 };
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&sdio_pwrseq>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+
+	brcmf: bcrmf@1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+	};
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_card>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+	clocks = <&clkc CLKID_FCLK_DIV4>;
+	clock-names = "clkin0";
+};
+
+&cvbs_vdac_port {
+	cvbs_vdac_out: endpoint {
+		remote-endpoint = <&cvbs_connector_in>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,39 @@
 		enable-active-high;
 	};
 
+	vcc_3v3: regulator-vcc_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_1v8: regulator-vcc_1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_1V8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>,
+				<&gpio GPIOX_20 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
 };
 
 &uart_AO {
@@ -82,7 +115,7 @@
 
 &ethmac {
 	status = "okay";
-	pinctrl-0 = <&eth_pins>;
+	pinctrl-0 = <&eth_rgmii_pins>;
 	pinctrl-names = "default";
 };
 
@@ -102,3 +135,74 @@
 &usb1 {
 	status = "okay";
 };
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins &sdio_irq_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&sdio_pwrseq>;
+
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vcc_1v8>;
+
+	brcmf: bcrmf@1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+	};
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vcc_3v3>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vmmcq-sumpply = <&vcc_1v8>;
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+	clocks = <&clkc CLKID_FCLK_DIV4>;
+	clock-names = "clkin0";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gx.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gx.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* 16 MiB reserved for Hardware ROM Firmware */
+		hwrom_reserved: hwrom@0 {
+			reg = <0x0 0x0 0x0 0x1000000>;
+			no-map;
+		};
+
+		/* 2 MiB reserved for ARM Trusted Firmware (BL31) */
+		secmon_reserved: secmon@10000000 {
+			reg = <0x0 0x10000000 0x0 0x200000>;
+			no-map;
+		};
+	};
+
+	cpus {
+		#address-cells = <0x2>;
+		#size-cells = <0x0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x1>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x2>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x3>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+
+		l2: l2-cache0 {
+			compatible = "cache";
+		};
+	};
+
+	arm-pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_RAW(0xff) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	xtal: xtal-clk {
+		compatible = "fixed-clock";
+		clock-frequency = <24000000>;
+		clock-output-names = "xtal";
+		#clock-cells = <0>;
+	};
+
+	firmware {
+		sm: secure-monitor {
+			compatible = "amlogic,meson-gx-sm", "amlogic,meson-gxbb-sm";
+		};
+	};
+
+	efuse: efuse {
+		compatible = "amlogic,meson-gx-efuse", "amlogic,meson-gxbb-efuse";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		sn: sn@14 {
+			reg = <0x14 0x10>;
+		};
+
+		eth_mac: eth_mac@34 {
+			reg = <0x34 0x10>;
+		};
+
+		bid: bid@46 {
+			reg = <0x46 0x30>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cbus: cbus@c1100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc1100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc1100000 0x0 0x100000>;
+
+			reset: reset-controller@4404 {
+				compatible = "amlogic,meson-gx-reset", "amlogic,meson-gxbb-reset";
+				reg = <0x0 0x04404 0x0 0x20>;
+				#reset-cells = <1>;
+			};
+
+			uart_A: serial@84c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84c0 0x0 0x14>;
+				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			uart_B: serial@84dc {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x84dc 0x0 0x14>;
+				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			i2c_A: i2c@8500 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x08500 0x0 0x20>;
+				interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			pwm_ab: pwm@8550 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08550 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_cd: pwm@8650 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x08650 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			pwm_ef: pwm@86c0 {
+				compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
+				reg = <0x0 0x086c0 0x0 0x10>;
+				#pwm-cells = <3>;
+				status = "disabled";
+			};
+
+			uart_C: serial@8700 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x8700 0x0 0x14>;
+				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			i2c_B: i2c@87c0 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x087c0 0x0 0x20>;
+				interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c_C: i2c@87e0 {
+				compatible = "amlogic,meson-gxbb-i2c";
+				reg = <0x0 0x087e0 0x0 0x20>;
+				interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			watchdog@98d0 {
+				compatible = "amlogic,meson-gx-wdt", "amlogic,meson-gxbb-wdt";
+				reg = <0x0 0x098d0 0x0 0x10>;
+				clocks = <&xtal>;
+			};
+		};
+
+		gic: interrupt-controller@c4301000 {
+			compatible = "arm,gic-400";
+			reg = <0x0 0xc4301000 0 0x1000>,
+			      <0x0 0xc4302000 0 0x2000>,
+			      <0x0 0xc4304000 0 0x2000>,
+			      <0x0 0xc4306000 0 0x2000>;
+			interrupt-controller;
+			interrupts = <GIC_PPI 9
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+		};
+
+		aobus: aobus@c8100000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8100000 0x0 0x100000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
+
+			uart_AO: serial@4c0 {
+				compatible = "amlogic,meson-uart";
+				reg = <0x0 0x004c0 0x0 0x14>;
+				interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&xtal>;
+				status = "disabled";
+			};
+
+			ir: ir@580 {
+				compatible = "amlogic,meson-gxbb-ir";
+				reg = <0x0 0x00580 0x0 0x40>;
+				interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+		};
+
+		periphs: periphs@c8834000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc8834000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
+
+			rng {
+				compatible = "amlogic,meson-rng";
+				reg = <0x0 0x0 0x0 0x4>;
+			};
+		};
+
+
+		hiubus: hiubus@c883c000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xc883c000 0x0 0x2000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xc883c000 0x0 0x2000>;
+
+			mailbox: mailbox@404 {
+				compatible = "amlogic,meson-gx-mhu", "amlogic,meson-gxbb-mhu";
+				reg = <0 0x404 0 0x4c>;
+				interrupts = <0 208 IRQ_TYPE_EDGE_RISING>,
+					     <0 209 IRQ_TYPE_EDGE_RISING>,
+					     <0 210 IRQ_TYPE_EDGE_RISING>;
+				#mbox-cells = <1>;
+			};
+		};
+
+		ethmac: ethernet@c9410000 {
+			compatible = "amlogic,meson-gx-dwmac", "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+			reg = <0x0 0xc9410000 0x0 0x10000
+			       0x0 0xc8834540 0x0 0x4>;
+			interrupts = <0 8 1>;
+			interrupt-names = "macirq";
+			phy-mode = "rgmii";
+			status = "disabled";
+		};
+
+		apb: apb@d0000000 {
+			compatible = "simple-bus";
+			reg = <0x0 0xd0000000 0x0 0x200000>;
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x0 0x0 0x0 0xd0000000 0x0 0x200000>;
+
+			sd_emmc_a: mmc@70000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x70000 0x0 0x2000>;
+				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_b: mmc@72000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x72000 0x0 0x2000>;
+				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+
+			sd_emmc_c: mmc@74000 {
+				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
+				reg = <0x0 0x74000 0x0 0x2000>;
+				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+				status = "disabled";
+			};
+		};
+
+		vpu: vpu@d0100000 {
+			compatible = "amlogic,meson-gx-vpu";
+			reg = <0x0 0xd0100000 0x0 0x100000>,
+			      <0x0 0xc883c000 0x0 0x1000>,
+			      <0x0 0xc8838000 0x0 0x1000>;
+			reg-names = "vpu", "hhi", "dmc";
+			interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* CVBS VDAC output port */
+			cvbs_vdac_port: port@0 {
+				reg = <0>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "meson-gx.dtsi"
+#include <dt-bindings/clock/gxbb-clkc.h>
+#include <dt-bindings/gpio/meson-gxl-gpio.h>
+
+/ {
+	compatible = "amlogic,meson-gxl";
+};
+
+&ethmac {
+	reg = <0x0 0xc9410000 0x0 0x10000
+	       0x0 0xc8834540 0x0 0x4>;
+
+	clocks = <&clkc CLKID_ETH>,
+		 <&clkc CLKID_FCLK_DIV2>,
+		 <&clkc CLKID_MPLL2>;
+	clock-names = "stmmaceth", "clkin0", "clkin1";
+
+	mdio0: mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,dwmac-mdio";
+	};
+};
+
+&aobus {
+	pinctrl_aobus: pinctrl@14 {
+		compatible = "amlogic,meson-gxl-aobus-pinctrl";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gpio_ao: bank@14 {
+			reg = <0x0 0x00014 0x0 0x8>,
+			      <0x0 0x0002c 0x0 0x4>,
+			      <0x0 0x00024 0x0 0x8>;
+			reg-names = "mux", "pull", "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		uart_ao_a_pins: uart_ao_a {
+			mux {
+				groups = "uart_tx_ao_a", "uart_rx_ao_a";
+				function = "uart_ao";
+			};
+		};
+
+		remote_input_ao_pins: remote_input_ao {
+			mux {
+				groups = "remote_input_ao";
+				function = "remote_input_ao";
+			};
+		};
+	};
+};
+
+&periphs {
+	pinctrl_periphs: pinctrl@4b0 {
+		compatible = "amlogic,meson-gxl-periphs-pinctrl";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		gpio: bank@4b0 {
+			reg = <0x0 0x004b0 0x0 0x28>,
+			      <0x0 0x004e8 0x0 0x14>,
+			      <0x0 0x00120 0x0 0x14>,
+			      <0x0 0x00430 0x0 0x40>;
+			reg-names = "mux", "pull", "pull-enable", "gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		emmc_pins: emmc {
+			mux {
+				groups = "emmc_nand_d07",
+				       "emmc_cmd",
+				       "emmc_clk",
+				       "emmc_ds";
+				function = "emmc";
+			};
+		};
+
+		sdcard_pins: sdcard {
+			mux {
+				groups = "sdcard_d0",
+				       "sdcard_d1",
+				       "sdcard_d2",
+				       "sdcard_d3",
+				       "sdcard_cmd",
+				       "sdcard_clk";
+				function = "sdcard";
+			};
+		};
+
+		sdio_pins: sdio {
+			mux {
+				groups = "sdio_d0",
+				       "sdio_d1",
+				       "sdio_d2",
+				       "sdio_d3",
+				       "sdio_cmd",
+				       "sdio_clk";
+				function = "sdio";
+			};
+		};
+
+		sdio_irq_pins: sdio_irq {
+			mux {
+				groups = "sdio_irq";
+				function = "sdio";
+			};
+		};
+
+		uart_a_pins: uart_a {
+			mux {
+				groups = "uart_tx_a",
+				       "uart_rx_a";
+				function = "uart_a";
+			};
+		};
+
+		uart_b_pins: uart_b {
+			mux {
+				groups = "uart_tx_b",
+				       "uart_rx_b";
+				function = "uart_b";
+			};
+		};
+
+		uart_c_pins: uart_c {
+			mux {
+				groups = "uart_tx_c",
+				       "uart_rx_c";
+				function = "uart_c";
+			};
+		};
+
+		i2c_a_pins: i2c_a {
+			mux {
+				groups = "i2c_sck_a",
+				     "i2c_sda_a";
+				function = "i2c_a";
+			};
+		};
+
+		i2c_b_pins: i2c_b {
+			mux {
+				groups = "i2c_sck_b",
+				      "i2c_sda_b";
+				function = "i2c_b";
+			};
+		};
+
+		i2c_c_pins: i2c_c {
+			mux {
+				groups = "i2c_sck_c",
+				      "i2c_sda_c";
+				function = "i2c_c";
+			};
+		};
+
+		eth_pins: eth_c {
+			mux {
+				groups = "eth_mdio",
+				       "eth_mdc",
+				       "eth_clk_rx_clk",
+				       "eth_rx_dv",
+				       "eth_rxd0",
+				       "eth_rxd1",
+				       "eth_rxd2",
+				       "eth_rxd3",
+				       "eth_rgmii_tx_clk",
+				       "eth_tx_en",
+				       "eth_txd0",
+				       "eth_txd1",
+				       "eth_txd2",
+				       "eth_txd3";
+				function = "eth";
+			};
+		};
+
+		pwm_e_pins: pwm_e {
+			mux {
+				groups = "pwm_e";
+				function = "pwm_e";
+			};
+		};
+	};
+
+	eth-phy-mux {
+		compatible = "mdio-mux-mmioreg", "mdio-mux";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x0 0x55c 0x0 0x4>;
+		mux-mask = <0xffffffff>;
+		mdio-parent-bus = <&mdio0>;
+
+		internal_mdio: mdio@e40908ff {
+			reg = <0xe40908ff>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			internal_phy: ethernet-phy@8 {
+				compatible = "ethernet-phy-id0181.4400", "ethernet-phy-ieee802.3-c22";
+				reg = <8>;
+				max-speed = <100>;
+			};
+		};
+
+		external_mdio: mdio@2009087f {
+			reg = <0x2009087f>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+};
+
+&hiubus {
+	clkc: clock-controller@0 {
+		compatible = "amlogic,gxl-clkc", "amlogic,gxbb-clkc";
+		#clock-cells = <1>;
+		reg = <0x0 0x0 0x0 0x3db>;
+	};
+};
+
+&i2c_A {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&i2c_B {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&i2c_C {
+	clocks = <&clkc CLKID_I2C>;
+};
+
+&sd_emmc_a {
+	clocks = <&clkc CLKID_SD_EMMC_A>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_b {
+	clocks = <&clkc CLKID_SD_EMMC_B>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+       clock-names = "core", "clkin0", "clkin1";
+};
+
+&sd_emmc_c {
+	clocks = <&clkc CLKID_SD_EMMC_C>,
+		 <&xtal>,
+		 <&clkc CLKID_FCLK_DIV2>;
+	clock-names = "core", "clkin0", "clkin1";
+};
+
+&vpu {
+	compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-nexbox-a95x.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2016 Andreas Färber
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Neil Armstrong <narmstrong@kernel.org>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905x.dtsi"
+
+/ {
+	compatible = "nexbox,a95x", "amlogic,s905x", "amlogic,meson-gxl";
+	model = "NEXBOX A95X (S905X)";
+
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	vddio_card: gpio-regulator {
+		compatible = "regulator-gpio";
+
+		regulator-name = "VDDIO_CARD";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+
+		/* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+		states = <1800000 0
+			  3300000 1>;
+	};
+
+	vddio_boot: regulator-vddio_boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_3v3: regulator-vcc_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
+
+	cvbs-connector {
+		compatible = "composite-video-connector";
+
+		port {
+			cvbs_connector_in: endpoint {
+				remote-endpoint = <&cvbs_vdac_out>;
+			};
+		};
+	};
+};
+
+&uart_AO {
+	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&ethmac {
+	status = "okay";
+	phy-mode = "rmii";
+	phy-handle = <&internal_phy>;
+};
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
+	pinctrl-names = "default";
+};
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&sdio_pwrseq>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_card>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+	clocks = <&clkc CLKID_FCLK_DIV4>;
+	clock-names = "clkin0";
+};
+
+&cvbs_vdac_port {
+	cvbs_vdac_out: endpoint {
+		remote-endpoint = <&cvbs_connector_in>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "meson-gxl.dtsi"
+
+/ {
+	compatible = "amlogic,s905d", "amlogic,meson-gxl";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905d.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+	compatible = "amlogic,p230", "amlogic,s905d", "amlogic,meson-gxl";
+	model = "Amlogic Meson GXL (S905D) P230 Development Board";
+};
+
+/* P230 has exclusive choice between internal or external PHY */
+&ethmac {
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+
+	/* Select external PHY by default */
+	phy-handle = <&external_phy>;
+
+	/* External PHY reset is shared with internal PHY Led signals */
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	/* External PHY is in RGMII */
+	phy-mode = "rgmii";
+};
+
+&external_mdio {
+	external_phy: ethernet-phy@0 {
+		compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+		max-speed = <1000>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p231.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905d.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+	compatible = "amlogic,p231", "amlogic,s905d", "amlogic,meson-gxl";
+	model = "Amlogic Meson GXL (S905D) P231 Development Board";
+};
+
+/* P231 has only internal PHY port */
+&ethmac {
+	phy-mode = "rmii";
+	phy-handle = <&internal_phy>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "meson-gxl.dtsi"
+
+/ {
+	compatible = "amlogic,s905x", "amlogic,meson-gxl";
+};
+
+/* S905X Only has access to its internal PHY */
+&ethmac {
+	phy-mode = "rmii";
+	phy-handle = <&internal_phy>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905x.dtsi"
+
+/ {
+	compatible = "amlogic,p212", "amlogic,s905x", "amlogic,meson-gxl";
+	model = "Amlogic Meson GXL (S905X) P212 Development Board";
+
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+/* This UART is brought out to the DB9 connector */
+&uart_AO {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 "meson-gxl.dtsi"
+
+/ {
+	compatible = "amlogic,meson-gxm";
+
+	cpus {
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu4>;
+				};
+				core1 {
+					cpu = <&cpu5>;
+				};
+				core2 {
+					cpu = <&cpu6>;
+				};
+				core3 {
+					cpu = <&cpu7>;
+				};
+			};
+		};
+
+		cpu4: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x100>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+
+		cpu5: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x101>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+
+		cpu6: cpu@102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x102>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+
+		cpu7: cpu@103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x103>;
+			enable-method = "psci";
+			next-level-cache = <&l2>;
+		};
+	};
+};
+
+&vpu {
+	compatible = "amlogic,meson-gxm-vpu", "amlogic,meson-gx-vpu";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxm.dtsi"
+
+/ {
+	compatible = "nexbox,a1", "amlogic,s912", "amlogic,meson-gxm";
+	model = "NEXBOX A1";
+
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	vddio_boot: regulator-vddio-boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_3v3: regulator-vcc-3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	cvbs-connector {
+		compatible = "composite-video-connector";
+
+		port {
+			cvbs_connector_in: endpoint {
+				remote-endpoint = <&cvbs_vdac_out>;
+			};
+		};
+	};
+};
+
+/* This UART is brought out to the DB9 connector */
+&uart_AO {
+	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
+	pinctrl-names = "default";
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+&ethmac {
+	status = "okay";
+
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+
+	/* Select external PHY by default */
+	phy-handle = <&external_phy>;
+
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	/* External PHY is in RGMII */
+	phy-mode = "rgmii";
+};
+
+&external_mdio {
+	external_phy: ethernet-phy@0 {
+		compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+		max-speed = <1000>;
+	};
+};
+
+&cvbs_vdac_port {
+	cvbs_vdac_out: endpoint {
+		remote-endpoint = <&cvbs_connector_in>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q200.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxm.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+	compatible = "amlogic,q200", "amlogic,s912", "amlogic,meson-gxm";
+	model = "Amlogic Meson GXM (S912) Q200 Development Board";
+};
+
+/* Q200 has exclusive choice between internal or external PHY */
+&ethmac {
+	pinctrl-0 = <&eth_pins>;
+	pinctrl-names = "default";
+
+	/* Select external PHY by default */
+	phy-handle = <&external_phy>;
+
+	/* External PHY reset is shared with internal PHY Led signals */
+	snps,reset-gpio = <&gpio GPIOZ_14 0>;
+	snps,reset-delays-us = <0 10000 1000000>;
+	snps,reset-active-low;
+
+	/* External PHY is in RGMII */
+	phy-mode = "rgmii";
+};
+
+&external_mdio {
+	external_phy: ethernet-phy@0 {
+		compatible = "ethernet-phy-id001c.c916", "ethernet-phy-ieee802.3-c22";
+		reg = <0>;
+		max-speed = <1000>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q201.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q201.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q201.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gxm-s912-q201.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "meson-gxm.dtsi"
+#include "meson-gx-p23x-q20x.dtsi"
+
+/ {
+	compatible = "amlogic,q201", "amlogic,s912", "amlogic,meson-gxm";
+	model = "Amlogic Meson GXM (S912) Q201 Development Board";
+};
+
+/* Q201 has only internal PHY port */
+&ethmac {
+	phy-mode = "rmii";
+	phy-handle = <&internal_phy>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2016 Endless Computers, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/* Common DTSI for same Amlogic Q200/Q201 and P230/P231 boards using either
+ * the pin-compatible S912 (GXM) or S905D (GXL) SoCs.
+ */
+
+/ {
+	aliases {
+		serial0 = &uart_AO;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	vddio_boot: regulator-vddio_boot {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDIO_BOOT";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	vddao_3v3: regulator-vddao_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VDDAO_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	vcc_3v3: regulator-vcc_3v3 {
+		compatible = "regulator-fixed";
+		regulator-name = "VCC_3V3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	emmc_pwrseq: emmc-pwrseq {
+		compatible = "mmc-pwrseq-emmc";
+		reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+	};
+
+	wifi32k: wifi32k {
+		compatible = "pwm-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+		pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+		clocks = <&wifi32k>;
+		clock-names = "ext_clock";
+	};
+};
+
+/* This UART is brought out to the DB9 connector */
+&uart_AO {
+	status = "okay";
+	pinctrl-0 = <&uart_ao_a_pins>;
+	pinctrl-names = "default";
+};
+
+&ir {
+	status = "okay";
+	pinctrl-0 = <&remote_input_ao_pins>;
+	pinctrl-names = "default";
+};
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+	status = "okay";
+	pinctrl-0 = <&sdio_pins>;
+	pinctrl-names = "default";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+
+	non-removable;
+	disable-wp;
+
+	mmc-pwrseq = <&sdio_pwrseq>;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+
+	brcmf: bcrmf@1 {
+		reg = <1>;
+		compatible = "brcm,bcm4329-fmac";
+	};
+};
+
+/* SD card */
+&sd_emmc_b {
+	status = "okay";
+	pinctrl-0 = <&sdcard_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <4>;
+	cap-sd-highspeed;
+	max-frequency = <100000000>;
+	disable-wp;
+
+	cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+
+	vmmc-supply = <&vddao_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	pinctrl-names = "default";
+
+	bus-width = <8>;
+	cap-sd-highspeed;
+	cap-mmc-highspeed;
+	max-frequency = <200000000>;
+	non-removable;
+	disable-wp;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+
+	mmc-pwrseq = <&emmc_pwrseq>;
+	vmmc-supply = <&vcc_3v3>;
+	vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+	status = "okay";
+	pinctrl-0 = <&pwm_e_pins>;
+	pinctrl-names = "default";
+	clocks = <&clkc CLKID_FCLK_DIV4>;
+	clock-names = "clkin0";
+};
+
+&ethmac {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno-base.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,28 @@
 		clock-names = "apb_pclk";
 	};
 
+	smmu_pcie: iommu@2b500000 {
+		compatible = "arm,mmu-401", "arm,smmu-v1";
+		reg = <0x0 0x2b500000 0x0 0x10000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+		#iommu-cells = <1>;
+		#global-interrupts = <1>;
+		dma-coherent;
+		status = "disabled";
+	};
+
+	smmu_etr: iommu@2b600000 {
+		compatible = "arm,mmu-401", "arm,smmu-v1";
+		reg = <0x0 0x2b600000 0x0 0x10000>;
+		interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+		#iommu-cells = <1>;
+		#global-interrupts = <1>;
+		dma-coherent;
+		status = "disabled";
+	};
+
 	gic: interrupt-controller@2c010000 {
 		compatible = "arm,gic-400", "arm,cortex-a15-gic";
 		reg = <0x0 0x2c010000 0 0x1000>,
@@ -146,6 +168,7 @@
 	etr@20070000 {
 		compatible = "arm,coresight-tmc", "arm,primecell";
 		reg = <0 0x20070000 0 0x1000>;
+		iommus = <&smmu_etr 0>;
 
 		clocks = <&soc_smc50mhz>;
 		clock-names = "apb_pclk";
@@ -404,6 +427,8 @@
 				<0 0 0 4 &gic 0 0 0 139 4>;
 		msi-parent = <&v2m_0>;
 		status = "disabled";
+		iommu-map-mask = <0x0>;	/* RC has no means to output PCI RID */
+		iommu-map = <0x0 &smmu_pcie 0x0 0x1>;
 	};
 
 	scpi {
@@ -484,6 +509,48 @@
 
 	/include/ "juno-clocks.dtsi"
 
+	smmu_dma: iommu@7fb00000 {
+		compatible = "arm,mmu-401", "arm,smmu-v1";
+		reg = <0x0 0x7fb00000 0x0 0x10000>;
+		interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+		#iommu-cells = <1>;
+		#global-interrupts = <1>;
+		dma-coherent;
+		status = "disabled";
+	};
+
+	smmu_hdlcd1: iommu@7fb10000 {
+		compatible = "arm,mmu-401", "arm,smmu-v1";
+		reg = <0x0 0x7fb10000 0x0 0x10000>;
+		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+		#iommu-cells = <1>;
+		#global-interrupts = <1>;
+		status = "disabled";
+	};
+
+	smmu_hdlcd0: iommu@7fb20000 {
+		compatible = "arm,mmu-401", "arm,smmu-v1";
+		reg = <0x0 0x7fb20000 0x0 0x10000>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		#iommu-cells = <1>;
+		#global-interrupts = <1>;
+		status = "disabled";
+	};
+
+	smmu_usb: iommu@7fb30000 {
+		compatible = "arm,mmu-401", "arm,smmu-v1";
+		reg = <0x0 0x7fb30000 0x0 0x10000>;
+		interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+		#iommu-cells = <1>;
+		#global-interrupts = <1>;
+		dma-coherent;
+		status = "disabled";
+	};
+
 	dma@7ff00000 {
 		compatible = "arm,pl330", "arm,primecell";
 		reg = <0x0 0x7ff00000 0 0x1000>;
@@ -499,6 +566,15 @@
 			     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+		iommus = <&smmu_dma 0>,
+			 <&smmu_dma 1>,
+			 <&smmu_dma 2>,
+			 <&smmu_dma 3>,
+			 <&smmu_dma 4>,
+			 <&smmu_dma 5>,
+			 <&smmu_dma 6>,
+			 <&smmu_dma 7>,
+			 <&smmu_dma 8>;
 		clocks = <&soc_faxiclk>;
 		clock-names = "apb_pclk";
 	};
@@ -507,6 +583,7 @@
 		compatible = "arm,hdlcd";
 		reg = <0 0x7ff50000 0 0x1000>;
 		interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+		iommus = <&smmu_hdlcd1 0>;
 		clocks = <&scpi_clk 3>;
 		clock-names = "pxlclk";
 
@@ -521,6 +598,7 @@
 		compatible = "arm,hdlcd";
 		reg = <0 0x7ff60000 0 0x1000>;
 		interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+		iommus = <&smmu_hdlcd0 0>;
 		clocks = <&scpi_clk 3>;
 		clock-names = "pxlclk";
 
@@ -574,6 +652,7 @@
 		compatible = "generic-ohci";
 		reg = <0x0 0x7ffb0000 0x0 0x10000>;
 		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+		iommus = <&smmu_usb 0>;
 		clocks = <&soc_usb48mhz>;
 	};
 
@@ -581,6 +660,7 @@
 		compatible = "generic-ehci";
 		reg = <0x0 0x7ffc0000 0x0 0x10000>;
 		interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		iommus = <&smmu_usb 0>;
 		clocks = <&soc_usb48mhz>;
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno.dts	2017-02-12 16:03:20.000000000 -0500
@@ -90,6 +90,7 @@
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		A57_1: cpu@1 {
@@ -100,6 +101,7 @@
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		A53_0: cpu@100 {
@@ -110,6 +112,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A53_1: cpu@101 {
@@ -120,6 +123,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A53_2: cpu@102 {
@@ -130,6 +134,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A53_3: cpu@103 {
@@ -140,6 +145,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A57_L2: l2-cache0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno-r1.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno-r1.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno-r1.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno-r1.dts	2017-02-12 16:03:20.000000000 -0500
@@ -90,6 +90,7 @@
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		A57_1: cpu@1 {
@@ -100,6 +101,7 @@
 			next-level-cache = <&A57_L2>;
 			clocks = <&scpi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		A53_0: cpu@100 {
@@ -110,6 +112,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A53_1: cpu@101 {
@@ -120,6 +123,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A53_2: cpu@102 {
@@ -130,6 +134,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A53_3: cpu@103 {
@@ -140,6 +145,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <578>;
 		};
 
 		A57_L2: l2-cache0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno-r2.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno-r2.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/juno-r2.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/juno-r2.dts	2017-02-12 16:03:20.000000000 -0500
@@ -90,6 +90,7 @@
 			next-level-cache = <&A72_L2>;
 			clocks = <&scpi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		A72_1: cpu@1 {
@@ -100,6 +101,7 @@
 			next-level-cache = <&A72_L2>;
 			clocks = <&scpi_dvfs 0>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		A53_0: cpu@100 {
@@ -110,6 +112,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <485>;
 		};
 
 		A53_1: cpu@101 {
@@ -120,6 +123,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <485>;
 		};
 
 		A53_2: cpu@102 {
@@ -130,6 +134,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <485>;
 		};
 
 		A53_3: cpu@103 {
@@ -140,6 +145,7 @@
 			next-level-cache = <&A53_L2>;
 			clocks = <&scpi_dvfs 1>;
 			cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <485>;
 		};
 
 		A72_L2: l2-cache0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts	2017-02-12 16:03:20.000000000 -0500
@@ -81,7 +81,7 @@
 		#address-cells = <0>;
 		interrupt-controller;
 		reg = <0x0 0x2c001000 0 0x1000>,
-		      <0x0 0x2c002000 0 0x1000>,
+		      <0x0 0x2c002000 0 0x2000>,
 		      <0x0 0x2c004000 0 0x2000>,
 		      <0x0 0x2c006000 0 0x2000>;
 		interrupts = <1 9 0xf04>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/bcm2837.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 #include "bcm283x.dtsi"
 
 / {
-	compatible = "brcm,bcm2836";
+	compatible = "brcm,bcm2837";
 
 	soc {
 		ranges = <0x7e000000 0x3f000000 0x1000000>,
@@ -74,3 +74,9 @@
 	interrupt-parent = <&local_intc>;
 	interrupts = <8>;
 };
+
+/* enable thermal sensor with the correct compatible property set */
+&thermal {
+	compatible = "brcm,bcm2837-thermal";
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,7 @@
 #include "bcm2837.dtsi"
 #include "bcm2835-rpi.dtsi"
 #include "bcm283x-rpi-smsc9514.dtsi"
+#include "bcm283x-rpi-usb-host.dtsi"
 
 / {
 	compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
@@ -15,13 +16,6 @@
 		act {
 			gpios = <&gpio 47 0>;
 		};
-
-		pwr {
-			label = "PWR";
-			gpios = <&gpio 35 0>;
-			default-state = "keep";
-			linux,default-trigger = "default-on";
-		};
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/ns2.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -133,6 +133,9 @@
 
 		status = "disabled";
 
+		phys = <&pci_phy0>;
+		phy-names = "pcie-phy";
+
 		msi-parent = <&msi0>;
 		msi0: msi@20020000 {
 			compatible = "brcm,iproc-msi";
@@ -171,6 +174,9 @@
 
 		status = "disabled";
 
+		phys = <&pci_phy1>;
+		phy-names = "pcie-phy";
+
 		msi-parent = <&msi4>;
 		msi4: msi@50020000 {
 			compatible = "brcm,iproc-msi";
@@ -191,6 +197,54 @@
 
 		#include "ns2-clock.dtsi"
 
+		enet: ethernet@61000000 {
+			compatible = "brcm,ns2-amac";
+			reg = <0x61000000 0x1000>,
+			      <0x61090000 0x1000>,
+			      <0x61030000 0x100>;
+			reg-names = "amac_base", "idm_base", "nicpm_base";
+			interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+			phy-handle = <&gphy0>;
+			phy-mode = "rgmii";
+			status = "disabled";
+		};
+
+		pdc0: iproc-pdc0@612c0000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x612c0000 0x445>;  /* PDC FS0 regs */
+			interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
+		pdc1: iproc-pdc1@612e0000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x612e0000 0x445>;  /* PDC FS1 regs */
+			interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
+		pdc2: iproc-pdc2@61300000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x61300000 0x445>;  /* PDC FS2 regs */
+			interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
+		pdc3: iproc-pdc3@61320000 {
+			compatible = "brcm,iproc-pdc-mbox";
+			reg = <0x61320000 0x445>;  /* PDC FS3 regs */
+			interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+			#mbox-cells = <1>;
+			brcm,rx-status-len = <32>;
+			brcm,use-bcm-hdr;
+		};
+
 		dma0: dma@61360000 {
 			compatible = "arm,pl330", "arm,primecell";
 			reg = <0x61360000 0x1000>;
@@ -248,7 +302,7 @@
 				     <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
-			mmu-masters;
+			#iommu-cells = <1>;
 		};
 
 		pinctrl: pinctrl@6501d130 {
@@ -565,5 +619,23 @@
 
 			brcm,nand-has-wp;
 		};
+
+		qspi: spi@66470200 {
+			compatible = "brcm,spi-bcm-qspi", "brcm,spi-ns2-qspi";
+			reg = <0x66470200 0x184>,
+				<0x66470000 0x124>,
+				<0x67017408 0x004>,
+				<0x664703a0 0x01c>;
+			reg-names = "mspi", "bspi", "intr_regs",
+				"intr_status_reg";
+			interrupts = <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "spi_l1_intr";
+			clocks = <&iprocmed>;
+			clock-names = "iprocmed";
+			num-cs = <2>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/broadcom/ns2-svk.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,6 +56,10 @@
 	};
 };
 
+&enet {
+	status = "ok";
+};
+
 &pci_phy0 {
 	status = "ok";
 };
@@ -157,6 +161,10 @@
 	status = "ok";
 };
 
+&sdio1 {
+	status = "ok";
+};
+
 &nand {
 	nandcs@0 {
 		compatible = "brcm,nandcs";
@@ -174,6 +182,7 @@
 &mdio_mux_iproc {
 	mdio@10 {
 		gphy0: eth-phy@10 {
+			enet-phy-lane-swap;
 			reg = <0x10>;
 		};
 	};
@@ -187,3 +196,37 @@
 		groups = "nand_grp";
 	};
 };
+
+&qspi {
+	bspi-sel = <0>;
+	flash: m25p80@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "m25p80";
+		reg = <0x0>;
+		spi-max-frequency = <12500000>;
+		m25p,fast-read;
+		spi-cpol;
+		spi-cpha;
+
+		partition@0 {
+			label = "boot";
+			reg = <0x00000000 0x000a0000>;
+		};
+
+		partition@a0000 {
+			label = "env";
+			reg = <0x000a0000 0x00060000>;
+		};
+
+		partition@100000 {
+			label = "system";
+			reg = <0x00100000 0x00600000>;
+		};
+
+		partition@700000 {
+			label = "rootfs";
+			reg = <0x00700000 0x01900000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1462 @@
+/*
+ * Samsung's Exynos5433 SoC device tree source
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Samsung's Exynos5433 SoC device nodes are listed in this file.
+ * Exynos5433 based board files can include this file and provide
+ * values for board specific bindings.
+ *
+ * Note: This file does not include device nodes for all the controllers in
+ * Exynos5433 SoC. As device tree coverage for Exynos5433 increases,
+ * additional nodes can be added to this 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 <dt-bindings/clock/exynos5433.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "samsung,exynos5433";
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x100>;
+			clock-frequency = <1300000000>;
+			clocks = <&cmu_apollo CLK_SCLK_APOLLO>;
+			clock-names = "apolloclk";
+			operating-points-v2 = <&cluster_a53_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu1: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x101>;
+			clock-frequency = <1300000000>;
+			operating-points-v2 = <&cluster_a53_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu2: cpu@102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x102>;
+			clock-frequency = <1300000000>;
+			operating-points-v2 = <&cluster_a53_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu3: cpu@103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x103>;
+			clock-frequency = <1300000000>;
+			operating-points-v2 = <&cluster_a53_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu4: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x0>;
+			clock-frequency = <1900000000>;
+			clocks = <&cmu_atlas CLK_SCLK_ATLAS>;
+			clock-names = "atlasclk";
+			operating-points-v2 = <&cluster_a57_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu5: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x1>;
+			clock-frequency = <1900000000>;
+			operating-points-v2 = <&cluster_a57_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu6: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x2>;
+			clock-frequency = <1900000000>;
+			operating-points-v2 = <&cluster_a57_opp_table>;
+			#cooling-cells = <2>;
+		};
+
+		cpu7: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a57", "arm,armv8";
+			enable-method = "psci";
+			reg = <0x3>;
+			clock-frequency = <1900000000>;
+			operating-points-v2 = <&cluster_a57_opp_table>;
+			#cooling-cells = <2>;
+		};
+	};
+
+	cluster_a53_opp_table: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			opp-microvolt = <925000>;
+		};
+		opp@600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <950000>;
+		};
+		opp@700000000 {
+			opp-hz = /bits/ 64 <700000000>;
+			opp-microvolt = <975000>;
+		};
+		opp@800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1000000>;
+		};
+		opp@900000000 {
+			opp-hz = /bits/ 64 <900000000>;
+			opp-microvolt = <1050000>;
+		};
+		opp@1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <1075000>;
+		};
+		opp@1100000000 {
+			opp-hz = /bits/ 64 <1100000000>;
+			opp-microvolt = <1112500>;
+		};
+		opp@1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <1112500>;
+		};
+		opp@1300000000 {
+			opp-hz = /bits/ 64 <1300000000>;
+			opp-microvolt = <1150000>;
+		};
+	};
+
+	cluster_a57_opp_table: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <900000>;
+		};
+		opp@700000000 {
+			opp-hz = /bits/ 64 <700000000>;
+			opp-microvolt = <912500>;
+		};
+		opp@800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <912500>;
+		};
+		opp@900000000 {
+			opp-hz = /bits/ 64 <900000000>;
+			opp-microvolt = <937500>;
+		};
+		opp@1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-microvolt = <975000>;
+		};
+		opp@1100000000 {
+			opp-hz = /bits/ 64 <1100000000>;
+			opp-microvolt = <1012500>;
+		};
+		opp@1200000000 {
+			opp-hz = /bits/ 64 <1200000000>;
+			opp-microvolt = <1037500>;
+		};
+		opp@1300000000 {
+			opp-hz = /bits/ 64 <1300000000>;
+			opp-microvolt = <1062500>;
+		};
+		opp@1400000000 {
+			opp-hz = /bits/ 64 <1400000000>;
+			opp-microvolt = <1087500>;
+		};
+		opp@1500000000 {
+			opp-hz = /bits/ 64 <1500000000>;
+			opp-microvolt = <1125000>;
+		};
+		opp@1600000000 {
+			opp-hz = /bits/ 64 <1600000000>;
+			opp-microvolt = <1137500>;
+		};
+		opp@1700000000 {
+			opp-hz = /bits/ 64 <1700000000>;
+			opp-microvolt = <1175000>;
+		};
+		opp@1800000000 {
+			opp-hz = /bits/ 64 <1800000000>;
+			opp-microvolt = <1212500>;
+		};
+		opp@1900000000 {
+			opp-hz = /bits/ 64 <1900000000>;
+			opp-microvolt = <1262500>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci";
+		method = "smc";
+		cpu_off = <0x84000002>;
+		cpu_on = <0xC4000003>;
+	};
+
+	reboot: syscon-reboot {
+		compatible = "syscon-reboot";
+		regmap = <&pmu_system_controller>;
+		offset = <0x400>; /* SWRESET */
+		mask = <0x1>;
+	};
+
+	soc: soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x0 0x0 0x18000000>;
+
+		chipid@10000000 {
+			compatible = "samsung,exynos4210-chipid";
+			reg = <0x10000000 0x100>;
+		};
+
+		xxti: xxti {
+			compatible = "fixed-clock";
+			clock-output-names = "oscclk";
+			#clock-cells = <0>;
+		};
+
+		cmu_top: clock-controller@10030000 {
+			compatible = "samsung,exynos5433-cmu-top";
+			reg = <0x10030000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"sclk_mphy_pll",
+				"sclk_mfc_pll",
+				"sclk_bus_pll";
+			clocks = <&xxti>,
+				<&cmu_cpif CLK_SCLK_MPHY_PLL>,
+				<&cmu_mif CLK_SCLK_MFC_PLL>,
+				<&cmu_mif CLK_SCLK_BUS_PLL>;
+		};
+
+		cmu_cpif: clock-controller@10fc0000 {
+			compatible = "samsung,exynos5433-cmu-cpif";
+			reg = <0x10fc0000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk";
+			clocks = <&xxti>;
+		};
+
+		cmu_mif: clock-controller@105b0000 {
+			compatible = "samsung,exynos5433-cmu-mif";
+			reg = <0x105b0000 0x2000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"sclk_mphy_pll";
+			clocks = <&xxti>,
+				<&cmu_cpif CLK_SCLK_MPHY_PLL>;
+		};
+
+		cmu_peric: clock-controller@14c80000 {
+			compatible = "samsung,exynos5433-cmu-peric";
+			reg = <0x14c80000 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		cmu_peris: clock-controller@0x10040000 {
+			compatible = "samsung,exynos5433-cmu-peris";
+			reg = <0x10040000 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		cmu_fsys: clock-controller@156e0000 {
+			compatible = "samsung,exynos5433-cmu-fsys";
+			reg = <0x156e0000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"sclk_ufs_mphy",
+				"aclk_fsys_200",
+				"sclk_pcie_100_fsys",
+				"sclk_ufsunipro_fsys",
+				"sclk_mmc2_fsys",
+				"sclk_mmc1_fsys",
+				"sclk_mmc0_fsys",
+				"sclk_usbhost30_fsys",
+				"sclk_usbdrd30_fsys";
+			clocks = <&xxti>,
+				<&cmu_cpif CLK_SCLK_UFS_MPHY>,
+				<&cmu_top CLK_ACLK_FSYS_200>,
+				<&cmu_top CLK_SCLK_PCIE_100_FSYS>,
+				<&cmu_top CLK_SCLK_UFSUNIPRO_FSYS>,
+				<&cmu_top CLK_SCLK_MMC2_FSYS>,
+				<&cmu_top CLK_SCLK_MMC1_FSYS>,
+				<&cmu_top CLK_SCLK_MMC0_FSYS>,
+				<&cmu_top CLK_SCLK_USBHOST30_FSYS>,
+				<&cmu_top CLK_SCLK_USBDRD30_FSYS>;
+		};
+
+		cmu_g2d: clock-controller@12460000 {
+			compatible = "samsung,exynos5433-cmu-g2d";
+			reg = <0x12460000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"aclk_g2d_266",
+				"aclk_g2d_400";
+			clocks = <&xxti>,
+				<&cmu_top CLK_ACLK_G2D_266>,
+				<&cmu_top CLK_ACLK_G2D_400>;
+		};
+
+		cmu_disp: clock-controller@13b90000 {
+			compatible = "samsung,exynos5433-cmu-disp";
+			reg = <0x13b90000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"sclk_dsim1_disp",
+				"sclk_dsim0_disp",
+				"sclk_dsd_disp",
+				"sclk_decon_tv_eclk_disp",
+				"sclk_decon_vclk_disp",
+				"sclk_decon_eclk_disp",
+				"sclk_decon_tv_vclk_disp",
+				"aclk_disp_333";
+			clocks = <&xxti>,
+				<&cmu_mif CLK_SCLK_DSIM1_DISP>,
+				<&cmu_mif CLK_SCLK_DSIM0_DISP>,
+				<&cmu_mif CLK_SCLK_DSD_DISP>,
+				<&cmu_mif CLK_SCLK_DECON_TV_ECLK_DISP>,
+				<&cmu_mif CLK_SCLK_DECON_VCLK_DISP>,
+				<&cmu_mif CLK_SCLK_DECON_ECLK_DISP>,
+				<&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>,
+				<&cmu_mif CLK_ACLK_DISP_333>;
+		};
+
+		cmu_aud: clock-controller@114c0000 {
+			compatible = "samsung,exynos5433-cmu-aud";
+			reg = <0x114c0000 0x1000>;
+			#clock-cells = <1>;
+			clock-names = "oscclk", "fout_aud_pll";
+			clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>;
+		};
+
+		cmu_bus0: clock-controller@13600000 {
+			compatible = "samsung,exynos5433-cmu-bus0";
+			reg = <0x13600000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "aclk_bus0_400";
+			clocks = <&cmu_top CLK_ACLK_BUS0_400>;
+		};
+
+		cmu_bus1: clock-controller@14800000 {
+			compatible = "samsung,exynos5433-cmu-bus1";
+			reg = <0x14800000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "aclk_bus1_400";
+			clocks = <&cmu_top CLK_ACLK_BUS1_400>;
+		};
+
+		cmu_bus2: clock-controller@13400000 {
+			compatible = "samsung,exynos5433-cmu-bus2";
+			reg = <0x13400000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk", "aclk_bus2_400";
+			clocks = <&xxti>, <&cmu_mif CLK_ACLK_BUS2_400>;
+		};
+
+		cmu_g3d: clock-controller@14aa0000 {
+			compatible = "samsung,exynos5433-cmu-g3d";
+			reg = <0x14aa0000 0x2000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk", "aclk_g3d_400";
+			clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>;
+		};
+
+		cmu_gscl: clock-controller@13cf0000 {
+			compatible = "samsung,exynos5433-cmu-gscl";
+			reg = <0x13cf0000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"aclk_gscl_111",
+				"aclk_gscl_333";
+			clocks = <&xxti>,
+				<&cmu_top CLK_ACLK_GSCL_111>,
+				<&cmu_top CLK_ACLK_GSCL_333>;
+		};
+
+		cmu_apollo: clock-controller@11900000 {
+			compatible = "samsung,exynos5433-cmu-apollo";
+			reg = <0x11900000 0x2000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk", "sclk_bus_pll_apollo";
+			clocks = <&xxti>, <&cmu_mif CLK_SCLK_BUS_PLL_APOLLO>;
+		};
+
+		cmu_atlas: clock-controller@11800000 {
+			compatible = "samsung,exynos5433-cmu-atlas";
+			reg = <0x11800000 0x2000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk", "sclk_bus_pll_atlas";
+			clocks = <&xxti>, <&cmu_mif CLK_SCLK_BUS_PLL_ATLAS>;
+		};
+
+		cmu_mscl: clock-controller@105d0000 {
+			compatible = "samsung,exynos5433-cmu-mscl";
+			reg = <0x150d0000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"sclk_jpeg_mscl",
+				"aclk_mscl_400";
+			clocks = <&xxti>,
+				<&cmu_top CLK_SCLK_JPEG_MSCL>,
+				<&cmu_top CLK_ACLK_MSCL_400>;
+		};
+
+		cmu_mfc: clock-controller@15280000 {
+			compatible = "samsung,exynos5433-cmu-mfc";
+			reg = <0x15280000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk", "aclk_mfc_400";
+			clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>;
+		};
+
+		cmu_hevc: clock-controller@14f80000 {
+			compatible = "samsung,exynos5433-cmu-hevc";
+			reg = <0x14f80000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk", "aclk_hevc_400";
+			clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>;
+		};
+
+		cmu_isp: clock-controller@146d0000 {
+			compatible = "samsung,exynos5433-cmu-isp";
+			reg = <0x146d0000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"aclk_isp_dis_400",
+				"aclk_isp_400";
+			clocks = <&xxti>,
+				<&cmu_top CLK_ACLK_ISP_DIS_400>,
+				<&cmu_top CLK_ACLK_ISP_400>;
+		};
+
+		cmu_cam0: clock-controller@120d0000 {
+			compatible = "samsung,exynos5433-cmu-cam0";
+			reg = <0x120d0000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"aclk_cam0_333",
+				"aclk_cam0_400",
+				"aclk_cam0_552";
+			clocks = <&xxti>,
+				<&cmu_top CLK_ACLK_CAM0_333>,
+				<&cmu_top CLK_ACLK_CAM0_400>,
+				<&cmu_top CLK_ACLK_CAM0_552>;
+		};
+
+		cmu_cam1: clock-controller@145d0000 {
+			compatible = "samsung,exynos5433-cmu-cam1";
+			reg = <0x145d0000 0x1000>;
+			#clock-cells = <1>;
+
+			clock-names = "oscclk",
+				"sclk_isp_uart_cam1",
+				"sclk_isp_spi1_cam1",
+				"sclk_isp_spi0_cam1",
+				"aclk_cam1_333",
+				"aclk_cam1_400",
+				"aclk_cam1_552";
+			clocks = <&xxti>,
+				<&cmu_top CLK_SCLK_ISP_UART_CAM1>,
+				<&cmu_top CLK_SCLK_ISP_SPI1_CAM1>,
+				<&cmu_top CLK_SCLK_ISP_SPI0_CAM1>,
+				<&cmu_top CLK_ACLK_CAM1_333>,
+				<&cmu_top CLK_ACLK_CAM1_400>,
+				<&cmu_top CLK_ACLK_CAM1_552>;
+		};
+
+		tmu_atlas0: tmu@10060000 {
+			compatible = "samsung,exynos5433-tmu";
+			reg = <0x10060000 0x200>;
+			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peris CLK_PCLK_TMU0_APBIF>,
+				<&cmu_peris CLK_SCLK_TMU0>;
+			clock-names = "tmu_apbif", "tmu_sclk";
+			#include "exynos5433-tmu-sensor-conf.dtsi"
+			status = "disabled";
+		};
+
+		tmu_atlas1: tmu@10068000 {
+			compatible = "samsung,exynos5433-tmu";
+			reg = <0x10068000 0x200>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peris CLK_PCLK_TMU0_APBIF>,
+				<&cmu_peris CLK_SCLK_TMU0>;
+			clock-names = "tmu_apbif", "tmu_sclk";
+			#include "exynos5433-tmu-sensor-conf.dtsi"
+			status = "disabled";
+		};
+
+		tmu_g3d: tmu@10070000 {
+			compatible = "samsung,exynos5433-tmu";
+			reg = <0x10070000 0x200>;
+			interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>,
+				<&cmu_peris CLK_SCLK_TMU1>;
+			clock-names = "tmu_apbif", "tmu_sclk";
+			#include "exynos5433-tmu-g3d-sensor-conf.dtsi"
+			status = "disabled";
+		};
+
+		tmu_apollo: tmu@10078000 {
+			compatible = "samsung,exynos5433-tmu";
+			reg = <0x10078000 0x200>;
+			interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>,
+				<&cmu_peris CLK_SCLK_TMU1>;
+			clock-names = "tmu_apbif", "tmu_sclk";
+			#include "exynos5433-tmu-sensor-conf.dtsi"
+			status = "disabled";
+		};
+
+		tmu_isp: tmu@1007c000 {
+			compatible = "samsung,exynos5433-tmu";
+			reg = <0x1007c000 0x200>;
+			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peris CLK_PCLK_TMU1_APBIF>,
+				<&cmu_peris CLK_SCLK_TMU1>;
+			clock-names = "tmu_apbif", "tmu_sclk";
+			#include "exynos5433-tmu-sensor-conf.dtsi"
+			status = "disabled";
+		};
+
+		mct@101c0000 {
+			compatible = "samsung,exynos4210-mct";
+			reg = <0x101c0000 0x800>;
+			interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&xxti>, <&cmu_peris CLK_PCLK_MCT>;
+			clock-names = "fin_pll", "mct";
+		};
+
+		pinctrl_alive: pinctrl@10580000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x10580000 0x1a20>, <0x11090000 0x100>;
+
+			wakeup-interrupt-controller {
+				compatible = "samsung,exynos7-wakeup-eint";
+				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			};
+		};
+
+		pinctrl_aud: pinctrl@114b0000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x114b0000 0x1000>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_cpif: pinctrl@10fe0000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x10fe0000 0x1000>;
+			interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_ese: pinctrl@14ca0000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x14ca0000 0x1000>;
+			interrupts = <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_finger: pinctrl@14cb0000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x14cb0000 0x1000>;
+			interrupts = <GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_fsys: pinctrl@15690000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x15690000 0x1000>;
+			interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_imem: pinctrl@11090000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x11090000 0x1000>;
+			interrupts = <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_nfc: pinctrl@14cd0000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x14cd0000 0x1000>;
+			interrupts = <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_peric: pinctrl@14cc0000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x14cc0000 0x1100>;
+			interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pinctrl_touch: pinctrl@14ce0000 {
+			compatible = "samsung,exynos5433-pinctrl";
+			reg = <0x14ce0000 0x1100>;
+			interrupts = <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		pmu_system_controller: system-controller@105c0000 {
+			compatible = "samsung,exynos5433-pmu", "syscon";
+			reg = <0x105c0000 0x5008>;
+			#clock-cells = <1>;
+			clock-names = "clkout16";
+			clocks = <&xxti>;
+		};
+
+		gic: interrupt-controller@11001000 {
+			compatible = "arm,gic-400";
+			#interrupt-cells = <3>;
+			interrupt-controller;
+			reg = <0x11001000 0x1000>,
+				<0x11002000 0x2000>,
+				<0x11004000 0x2000>,
+				<0x11006000 0x2000>;
+			interrupts = <GIC_PPI 9 0xf04>;
+		};
+
+		mipi_phy: video-phy@105c0710 {
+			compatible = "samsung,exynos5433-mipi-video-phy";
+			#phy-cells = <1>;
+			samsung,pmu-syscon = <&pmu_system_controller>;
+			samsung,cam0-sysreg = <&syscon_cam0>;
+			samsung,cam1-sysreg = <&syscon_cam1>;
+			samsung,disp-sysreg = <&syscon_disp>;
+		};
+
+		decon: decon@13800000 {
+			compatible = "samsung,exynos5433-decon";
+			reg = <0x13800000 0x2104>;
+			clocks = <&cmu_disp CLK_PCLK_DECON>,
+				<&cmu_disp CLK_ACLK_DECON>,
+				<&cmu_disp CLK_ACLK_SMMU_DECON0X>,
+				<&cmu_disp CLK_ACLK_XIU_DECON0X>,
+				<&cmu_disp CLK_PCLK_SMMU_DECON0X>,
+				<&cmu_disp CLK_SCLK_DECON_VCLK>,
+				<&cmu_disp CLK_SCLK_DECON_ECLK>;
+			clock-names = "pclk", "aclk_decon", "aclk_smmu_decon0x",
+				"aclk_xiu_decon0x", "pclk_smmu_decon0x",
+				"sclk_decon_vclk", "sclk_decon_eclk";
+			interrupt-names = "fifo", "vsync", "lcd_sys";
+			interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
+			samsung,disp-sysreg = <&syscon_disp>;
+			status = "disabled";
+			iommus = <&sysmmu_decon0x>, <&sysmmu_decon1x>;
+			iommu-names = "m0", "m1";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					decon_to_mic: endpoint {
+						remote-endpoint =
+							<&mic_to_decon>;
+					};
+				};
+			};
+		};
+
+		dsi: dsi@13900000 {
+			compatible = "samsung,exynos5433-mipi-dsi";
+			reg = <0x13900000 0xC0>;
+			interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+			phys = <&mipi_phy 1>;
+			phy-names = "dsim";
+			clocks = <&cmu_disp CLK_PCLK_DSIM0>,
+				<&cmu_disp CLK_PHYCLK_MIPIDPHY0_BITCLKDIV8>,
+				<&cmu_disp CLK_PHYCLK_MIPIDPHY0_RXCLKESC0>,
+				<&cmu_disp CLK_SCLK_RGB_VCLK_TO_DSIM0>,
+				<&cmu_disp CLK_SCLK_DSIM0>;
+			clock-names = "bus_clk",
+					"phyclk_mipidphy0_bitclkdiv8",
+					"phyclk_mipidphy0_rxclkesc0",
+					"sclk_rgb_vclk_to_dsim0",
+					"sclk_mipi";
+			status = "disabled";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					dsi_to_mic: endpoint {
+						remote-endpoint = <&mic_to_dsi>;
+					};
+				};
+			};
+		};
+
+		mic: mic@13930000 {
+			compatible = "samsung,exynos5433-mic";
+			reg = <0x13930000 0x48>;
+			clocks = <&cmu_disp CLK_PCLK_MIC0>,
+				<&cmu_disp CLK_SCLK_RGB_VCLK_TO_MIC0>;
+			clock-names = "pclk_mic0", "sclk_rgb_vclk_to_mic0";
+			samsung,disp-syscon = <&syscon_disp>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					mic_to_decon: endpoint {
+						remote-endpoint =
+							<&decon_to_mic>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					mic_to_dsi: endpoint {
+						remote-endpoint = <&dsi_to_mic>;
+					};
+				};
+			};
+		};
+
+		syscon_disp: syscon@13b80000 {
+			compatible = "syscon";
+			reg = <0x13b80000 0x1010>;
+		};
+
+		syscon_cam0: syscon@120f0000 {
+			compatible = "syscon";
+			reg = <0x120f0000 0x1020>;
+		};
+
+		syscon_cam1: syscon@145f0000 {
+			compatible = "syscon";
+			reg = <0x145f0000 0x1038>;
+		};
+
+		gsc_0: video-scaler@13C00000 {
+			compatible = "samsung,exynos5433-gsc";
+			reg = <0x13c00000 0x1000>;
+			interrupts = <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk", "aclk_xiu",
+				      "aclk_gsclbend";
+			clocks = <&cmu_gscl CLK_PCLK_GSCL0>,
+				 <&cmu_gscl CLK_ACLK_GSCL0>,
+				 <&cmu_gscl CLK_ACLK_XIU_GSCLX>,
+				 <&cmu_gscl CLK_ACLK_GSCLBEND_333>;
+			iommus = <&sysmmu_gscl0>;
+		};
+
+		gsc_1: video-scaler@13C10000 {
+			compatible = "samsung,exynos5433-gsc";
+			reg = <0x13c10000 0x1000>;
+			interrupts = <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk", "aclk_xiu",
+				      "aclk_gsclbend";
+			clocks = <&cmu_gscl CLK_PCLK_GSCL1>,
+				 <&cmu_gscl CLK_ACLK_GSCL1>,
+				 <&cmu_gscl CLK_ACLK_XIU_GSCLX>,
+				 <&cmu_gscl CLK_ACLK_GSCLBEND_333>;
+			iommus = <&sysmmu_gscl1>;
+		};
+
+		gsc_2: video-scaler@13C20000 {
+			compatible = "samsung,exynos5433-gsc";
+			reg = <0x13c20000 0x1000>;
+			interrupts = <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk", "aclk_xiu",
+				      "aclk_gsclbend";
+			clocks = <&cmu_gscl CLK_PCLK_GSCL2>,
+				 <&cmu_gscl CLK_ACLK_GSCL2>,
+				 <&cmu_gscl CLK_ACLK_XIU_GSCLX>,
+				 <&cmu_gscl CLK_ACLK_GSCLBEND_333>;
+			iommus = <&sysmmu_gscl2>;
+		};
+
+		jpeg: codec@15020000 {
+			compatible = "samsung,exynos5433-jpeg";
+			reg = <0x15020000 0x10000>;
+			interrupts = <GIC_SPI 411 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk", "aclk_xiu", "sclk";
+			clocks = <&cmu_mscl CLK_PCLK_JPEG>,
+				 <&cmu_mscl CLK_ACLK_JPEG>,
+				 <&cmu_mscl CLK_ACLK_XIU_MSCLX>,
+				 <&cmu_mscl CLK_SCLK_JPEG>;
+			iommus = <&sysmmu_jpeg>;
+		};
+
+		mfc: codec@152E0000 {
+			compatible = "samsung,exynos5433-mfc";
+			reg = <0x152E0000 0x10000>;
+			interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk", "aclk_xiu";
+			clocks = <&cmu_mfc CLK_PCLK_MFC>,
+				 <&cmu_mfc CLK_ACLK_MFC>,
+				 <&cmu_mfc CLK_ACLK_XIU_MFCX>;
+			iommus = <&sysmmu_mfc_0>, <&sysmmu_mfc_1>;
+			iommu-names = "left", "right";
+		};
+
+		sysmmu_decon0x: sysmmu@0x13a00000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x13a00000 0x1000>;
+			interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk";
+			clocks = <&cmu_disp CLK_PCLK_SMMU_DECON0X>,
+				<&cmu_disp CLK_ACLK_SMMU_DECON0X>;
+			#iommu-cells = <0>;
+		};
+
+		sysmmu_decon1x: sysmmu@0x13a10000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x13a10000 0x1000>;
+			interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk";
+			clocks = <&cmu_disp CLK_PCLK_SMMU_DECON1X>,
+				<&cmu_disp CLK_ACLK_SMMU_DECON1X>;
+			#iommu-cells = <0>;
+		};
+
+		sysmmu_gscl0: sysmmu@0x13C80000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x13C80000 0x1000>;
+			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "aclk", "pclk";
+			clocks = <&cmu_gscl CLK_ACLK_SMMU_GSCL0>,
+				 <&cmu_gscl CLK_PCLK_SMMU_GSCL0>;
+			#iommu-cells = <0>;
+		};
+
+		sysmmu_gscl1: sysmmu@0x13C90000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x13C90000 0x1000>;
+			interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "aclk", "pclk";
+			clocks = <&cmu_gscl CLK_ACLK_SMMU_GSCL1>,
+				 <&cmu_gscl CLK_PCLK_SMMU_GSCL1>;
+			#iommu-cells = <0>;
+		};
+
+		sysmmu_gscl2: sysmmu@0x13CA0000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x13CA0000 0x1000>;
+			interrupts = <GIC_SPI 292 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "aclk", "pclk";
+			clocks = <&cmu_gscl CLK_ACLK_SMMU_GSCL2>,
+				 <&cmu_gscl CLK_PCLK_SMMU_GSCL2>;
+			#iommu-cells = <0>;
+		};
+
+		sysmmu_jpeg: sysmmu@0x15060000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x15060000 0x1000>;
+			interrupts = <GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk";
+			clocks = <&cmu_mscl CLK_PCLK_SMMU_JPEG>,
+				 <&cmu_mscl CLK_ACLK_SMMU_JPEG>;
+			#iommu-cells = <0>;
+		};
+
+		sysmmu_mfc_0: sysmmu@0x15200000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x15200000 0x1000>;
+			interrupts = <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk";
+			clocks = <&cmu_mfc CLK_PCLK_SMMU_MFC_0>,
+				 <&cmu_mfc CLK_ACLK_SMMU_MFC_0>;
+			#iommu-cells = <0>;
+		};
+
+		sysmmu_mfc_1: sysmmu@0x15210000 {
+			compatible = "samsung,exynos-sysmmu";
+			reg = <0x15210000 0x1000>;
+			interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "pclk", "aclk";
+			clocks = <&cmu_mfc CLK_PCLK_SMMU_MFC_1>,
+				 <&cmu_mfc CLK_ACLK_SMMU_MFC_1>;
+			#iommu-cells = <0>;
+		};
+
+		serial_0: serial@14c10000 {
+			compatible = "samsung,exynos5433-uart";
+			reg = <0x14c10000 0x100>;
+			interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peric CLK_PCLK_UART0>,
+				<&cmu_peric CLK_SCLK_UART0>;
+			clock-names = "uart", "clk_uart_baud0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_bus>;
+			status = "disabled";
+		};
+
+		serial_1: serial@14c20000 {
+			compatible = "samsung,exynos5433-uart";
+			reg = <0x14c20000 0x100>;
+			interrupts = <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peric CLK_PCLK_UART1>,
+				<&cmu_peric CLK_SCLK_UART1>;
+			clock-names = "uart", "clk_uart_baud0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart1_bus>;
+			status = "disabled";
+		};
+
+		serial_2: serial@14c30000 {
+			compatible = "samsung,exynos5433-uart";
+			reg = <0x14c30000 0x100>;
+			interrupts = <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cmu_peric CLK_PCLK_UART2>,
+				<&cmu_peric CLK_SCLK_UART2>;
+			clock-names = "uart", "clk_uart_baud0";
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2_bus>;
+			status = "disabled";
+		};
+
+		spi_0: spi@14d20000 {
+			compatible = "samsung,exynos5433-spi";
+			reg = <0x14d20000 0x100>;
+			interrupts = <GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&pdma0 9>, <&pdma0 8>;
+			dma-names = "tx", "rx";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&cmu_peric CLK_PCLK_SPI0>,
+				<&cmu_peric CLK_SCLK_SPI0>,
+				<&cmu_peric CLK_SCLK_IOCLK_SPI0>;
+			clock-names = "spi", "spi_busclk0", "spi_ioclk";
+			samsung,spi-src-clk = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi0_bus>;
+			num-cs = <1>;
+			status = "disabled";
+		};
+
+		spi_1: spi@14d30000 {
+			compatible = "samsung,exynos5433-spi";
+			reg = <0x14d30000 0x100>;
+			interrupts = <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&pdma0 11>, <&pdma0 10>;
+			dma-names = "tx", "rx";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&cmu_peric CLK_PCLK_SPI1>,
+				<&cmu_peric CLK_SCLK_SPI1>,
+				<&cmu_peric CLK_SCLK_IOCLK_SPI1>;
+			clock-names = "spi", "spi_busclk0", "spi_ioclk";
+			samsung,spi-src-clk = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi1_bus>;
+			num-cs = <1>;
+			status = "disabled";
+		};
+
+		spi_2: spi@14d40000 {
+			compatible = "samsung,exynos5433-spi";
+			reg = <0x14d40000 0x100>;
+			interrupts = <GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&pdma0 13>, <&pdma0 12>;
+			dma-names = "tx", "rx";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&cmu_peric CLK_PCLK_SPI2>,
+				<&cmu_peric CLK_SCLK_SPI2>,
+				<&cmu_peric CLK_SCLK_IOCLK_SPI2>;
+			clock-names = "spi", "spi_busclk0", "spi_ioclk";
+			samsung,spi-src-clk = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi2_bus>;
+			num-cs = <1>;
+			status = "disabled";
+		};
+
+		spi_3: spi@14d50000 {
+			compatible = "samsung,exynos5433-spi";
+			reg = <0x14d50000 0x100>;
+			interrupts = <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&pdma0 23>, <&pdma0 22>;
+			dma-names = "tx", "rx";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&cmu_peric CLK_PCLK_SPI3>,
+				<&cmu_peric CLK_SCLK_SPI3>,
+				<&cmu_peric CLK_SCLK_IOCLK_SPI3>;
+			clock-names = "spi", "spi_busclk0", "spi_ioclk";
+			samsung,spi-src-clk = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi3_bus>;
+			num-cs = <1>;
+			status = "disabled";
+		};
+
+		spi_4: spi@14d00000 {
+			compatible = "samsung,exynos5433-spi";
+			reg = <0x14d00000 0x100>;
+			interrupts = <GIC_SPI 412 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&pdma0 25>, <&pdma0 24>;
+			dma-names = "tx", "rx";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&cmu_peric CLK_PCLK_SPI4>,
+				<&cmu_peric CLK_SCLK_SPI4>,
+				<&cmu_peric CLK_SCLK_IOCLK_SPI4>;
+			clock-names = "spi", "spi_busclk0", "spi_ioclk";
+			samsung,spi-src-clk = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi4_bus>;
+			num-cs = <1>;
+			status = "disabled";
+		};
+
+		adc: adc@14d10000 {
+			compatible = "samsung,exynos7-adc";
+			reg = <0x14d10000 0x100>;
+			interrupts = <GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "adc";
+			clocks = <&cmu_peric CLK_PCLK_ADCIF>;
+			#io-channel-cells = <1>;
+			io-channel-ranges;
+			status = "disabled";
+		};
+
+		pwm: pwm@14dd0000 {
+			compatible = "samsung,exynos4210-pwm";
+			reg = <0x14dd0000 0x100>;
+			interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>;
+			samsung,pwm-outputs = <0>, <1>, <2>, <3>;
+			clocks = <&cmu_peric CLK_PCLK_PWM>;
+			clock-names = "timers";
+			#pwm-cells = <3>;
+			status = "disabled";
+		};
+
+		hsi2c_0: hsi2c@14e40000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14e40000 0x1000>;
+			interrupts = <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c0_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C0>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_1: hsi2c@14e50000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14e50000 0x1000>;
+			interrupts = <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c1_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C1>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_2: hsi2c@14e60000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14e60000 0x1000>;
+			interrupts = <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c2_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C2>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_3: hsi2c@14e70000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14e70000 0x1000>;
+			interrupts = <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c3_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C3>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_4: hsi2c@14ec0000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14ec0000 0x1000>;
+			interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c4_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C4>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_5: hsi2c@14ed0000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14ed0000 0x1000>;
+			interrupts = <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c5_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C5>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_6: hsi2c@14ee0000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14ee0000 0x1000>;
+			interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c6_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C6>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_7: hsi2c@14ef0000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14ef0000 0x1000>;
+			interrupts = <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c7_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C7>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_8: hsi2c@14d90000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14d90000 0x1000>;
+			interrupts = <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c8_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C8>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_9: hsi2c@14da0000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14da0000 0x1000>;
+			interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c9_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C9>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_10: hsi2c@14de0000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14de0000 0x1000>;
+			interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c10_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C10>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		hsi2c_11: hsi2c@14df0000 {
+			compatible = "samsung,exynos7-hsi2c";
+			reg = <0x14df0000 0x1000>;
+			interrupts = <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&hs_i2c11_bus>;
+			clocks = <&cmu_peric CLK_PCLK_HSI2C11>;
+			clock-names = "hsi2c";
+			status = "disabled";
+		};
+
+		usbdrd30: usb@15400000  {
+			compatible = "samsung,exynos5250-dwusb3";
+			clocks = <&cmu_fsys CLK_ACLK_USBDRD30>,
+				<&cmu_fsys CLK_SCLK_USBDRD30>;
+			clock-names = "usbdrd30", "usbdrd30_susp_clk";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			status = "disabled";
+
+			dwc3@15400000 {
+				compatible = "snps,dwc3";
+				reg = <0x15400000 0x10000>;
+				interrupts = <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>;
+				phys = <&usbdrd30_phy 0>, <&usbdrd30_phy 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		usbdrd30_phy: phy@15500000 {
+			compatible = "samsung,exynos5433-usbdrd-phy";
+			reg = <0x15500000 0x100>;
+			clocks = <&cmu_fsys CLK_ACLK_USBDRD30>, <&xxti>,
+				<&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK>,
+				<&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK>,
+				<&cmu_fsys CLK_SCLK_USBDRD30>;
+			clock-names = "phy", "ref", "phy_utmi", "phy_pipe",
+					"itp";
+			#phy-cells = <1>;
+			samsung,pmu-syscon = <&pmu_system_controller>;
+			status = "disabled";
+		};
+
+		usbhost30_phy: phy@15580000 {
+			compatible = "samsung,exynos5433-usbdrd-phy";
+			reg = <0x15580000 0x100>;
+			clocks = <&cmu_fsys CLK_ACLK_USBHOST30>, <&xxti>,
+				<&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK>,
+				<&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK>,
+				<&cmu_fsys CLK_SCLK_USBHOST30>;
+			clock-names = "phy", "ref", "phy_utmi", "phy_pipe",
+					"itp";
+			#phy-cells = <1>;
+			samsung,pmu-syscon = <&pmu_system_controller>;
+			status = "disabled";
+		};
+
+		usbhost30: usb@15a00000 {
+			compatible = "samsung,exynos5250-dwusb3";
+			clocks = <&cmu_fsys CLK_ACLK_USBHOST30>,
+				<&cmu_fsys CLK_SCLK_USBHOST30>;
+			clock-names = "usbdrd30", "usbdrd30_susp_clk";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			status = "disabled";
+
+			usbdrd_dwc3_0: dwc3@15a00000 {
+				compatible = "snps,dwc3";
+				reg = <0x15a00000 0x10000>;
+				interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>;
+				phys = <&usbhost30_phy 0>, <&usbhost30_phy 1>;
+				phy-names = "usb2-phy", "usb3-phy";
+			};
+		};
+
+		mshc_0: mshc@15540000 {
+			compatible = "samsung,exynos7-dw-mshc-smu";
+			interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x15540000 0x2000>;
+			clocks = <&cmu_fsys CLK_ACLK_MMC0>,
+				<&cmu_fsys CLK_SCLK_MMC0>;
+			clock-names = "biu", "ciu";
+			fifo-depth = <0x40>;
+			status = "disabled";
+		};
+
+		mshc_1: mshc@15550000 {
+			compatible = "samsung,exynos7-dw-mshc-smu";
+			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x15550000 0x2000>;
+			clocks = <&cmu_fsys CLK_ACLK_MMC1>,
+				<&cmu_fsys CLK_SCLK_MMC1>;
+			clock-names = "biu", "ciu";
+			fifo-depth = <0x40>;
+			status = "disabled";
+		};
+
+		mshc_2: mshc@15560000 {
+			compatible = "samsung,exynos7-dw-mshc-smu";
+			interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x15560000 0x2000>;
+			clocks = <&cmu_fsys CLK_ACLK_MMC2>,
+				<&cmu_fsys CLK_SCLK_MMC2>;
+			clock-names = "biu", "ciu";
+			fifo-depth = <0x40>;
+			status = "disabled";
+		};
+
+		amba {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			pdma0: pdma@15610000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0x15610000 0x1000>;
+				interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cmu_fsys CLK_PDMA0>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+
+			pdma1: pdma@15600000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0x15600000 0x1000>;
+				interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cmu_fsys CLK_PDMA1>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+		};
+
+		audio-subsystem@11400000 {
+			compatible = "samsung,exynos5433-lpass";
+			reg = <0x11400000 0x100>, <0x11500000 0x08>;
+			samsung,pmu-syscon = <&pmu_system_controller>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			adma: adma@11420000 {
+				compatible = "arm,pl330", "arm,primecell";
+				reg = <0x11420000 0x1000>;
+				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cmu_aud CLK_ACLK_DMAC>;
+				clock-names = "apb_pclk";
+				#dma-cells = <1>;
+				#dma-channels = <8>;
+				#dma-requests = <32>;
+			};
+
+			i2s0: i2s0@11440000 {
+				compatible = "samsung,exynos7-i2s";
+				reg = <0x11440000 0x100>;
+				dmas = <&adma 0 &adma 2>;
+				dma-names = "tx", "rx";
+				interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&cmu_aud CLK_PCLK_AUD_I2S>,
+					<&cmu_aud CLK_SCLK_AUD_I2S>,
+					<&cmu_aud CLK_SCLK_I2S_BCLK>;
+				clock-names = "iis", "i2s_opclk0", "i2s_opclk1";
+				pinctrl-names = "default";
+				pinctrl-0 = <&i2s0_bus>;
+				status = "disabled";
+			};
+
+			serial_3: serial@11460000 {
+				compatible = "samsung,exynos5433-uart";
+				reg = <0x11460000 0x100>;
+				interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cmu_aud CLK_PCLK_AUD_UART>,
+					<&cmu_aud CLK_SCLK_AUD_UART>;
+				clock-names = "uart", "clk_uart_baud0";
+				pinctrl-names = "default";
+				pinctrl-0 = <&uart_aud_bus>;
+				status = "disabled";
+			};
+		};
+	};
+
+	timer: timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			<GIC_PPI 14
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			<GIC_PPI 11
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>,
+			<GIC_PPI 10
+				(GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+};
+
+#include "exynos5433-pinctrl.dtsi"
+#include "exynos5433-tmu.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-pinctrl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,804 @@
+/*
+ * Samsung's Exynos5433 SoC pin-mux and pin-config device tree source
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ * Chanwoo Choi <cw00.choi@samsung.com>
+ *
+ * Samsung's Exynos5433 SoC pin-mux and pin-config options are listed as device
+ * tree nodes are listed in this 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.
+ */
+
+#define PIN_PULL_NONE		0
+#define PIN_PULL_DOWN		1
+#define PIN_PULL_UP		3
+
+#define PIN_DRV_LV1		0
+#define PIN_DRV_LV2		2
+#define PIN_DRV_LV3		1
+#define PIN_DRV_LV4		3
+
+#define PIN_IN			0
+#define PIN_OUT			1
+#define PIN_FUNC1		2
+
+#define PIN(_func, _pin, _pull, _drv)			\
+	_pin {						\
+		samsung,pins = #_pin;			\
+		samsung,pin-function = <PIN_ ##_func>;	\
+		samsung,pin-pud = <PIN_PULL_ ##_pull>;	\
+		samsung,pin-drv = <PIN_DRV_ ##_drv>;	\
+	}
+
+&pinctrl_alive {
+	gpa0: gpa0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <2>;
+	};
+
+	gpa1: gpa1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		interrupt-parent = <&gic>;
+		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <2>;
+	};
+
+	gpa2: gpa2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpa3: gpa3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpf1: gpf1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpf2: gpf2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpf3: gpf3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpf4: gpf4 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpf5: gpf5 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
+
+&pinctrl_aud {
+	gpz0: gpz0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpz1: gpz1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	i2s0_bus: i2s0-bus {
+		samsung,pins = "gpz0-0", "gpz0-1", "gpz0-2", "gpz0-3",
+				"gpz0-4", "gpz0-5", "gpz0-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
+	};
+
+	pcm0_bus: pcm0-bus {
+		samsung,pins = "gpz1-0", "gpz1-1", "gpz1-2", "gpz1-3";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart_aud_bus: uart-aud-bus {
+		samsung,pins = "gpz1-3", "gpz1-2", "gpz1-1", "gpz1-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&pinctrl_cpif {
+	gpv6: gpv6 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
+
+&pinctrl_ese {
+	gpj2: gpj2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
+
+&pinctrl_finger {
+	gpd5: gpd5 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	spi2_bus: spi2-bus {
+		samsung,pins = "gpd5-0", "gpd5-2", "gpd5-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hs_i2c6_bus: hs-i2c6-bus {
+		samsung,pins = "gpd5-3", "gpd5-2";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&pinctrl_fsys {
+	gph1: gph1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpr4: gpr4 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpr0: gpr0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpr1: gpr1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpr2: gpr2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpr3: gpr3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	sd0_clk: sd0-clk {
+		samsung,pins = "gpr0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_cmd: sd0-cmd {
+		samsung,pins = "gpr0-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_rdqs: sd0-rdqs {
+		samsung,pins = "gpr0-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_qrdy: sd0-qrdy {
+		samsung,pins = "gpr0-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus1: sd0-bus-width1 {
+		samsung,pins = "gpr1-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus4: sd0-bus-width4 {
+		samsung,pins = "gpr1-1", "gpr1-2", "gpr1-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd0_bus8: sd0-bus-width8 {
+		samsung,pins = "gpr1-4", "gpr1-5", "gpr1-6", "gpr1-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_clk: sd1-clk {
+		samsung,pins = "gpr2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_cmd: sd1-cmd {
+		samsung,pins = "gpr2-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_bus1: sd1-bus-width1 {
+		samsung,pins = "gpr3-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_bus4: sd1-bus-width4 {
+		samsung,pins = "gpr3-1", "gpr3-2", "gpr3-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd1_bus8: sd1-bus-width8 {
+		samsung,pins = "gpr3-4", "gpr3-5", "gpr3-6", "gpr3-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	pcie_bus: pcie_bus {
+		samsung,pins = "gpr3-4", "gpr3-5", "gpr3-6", "gpr3-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+	};
+
+	sd2_clk: sd2-clk {
+		samsung,pins = "gpr4-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cmd: sd2-cmd {
+		samsung,pins = "gpr4-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_cd: sd2-cd {
+		samsung,pins = "gpr4-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus1: sd2-bus-width1 {
+		samsung,pins = "gpr4-3";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_bus4: sd2-bus-width4 {
+		samsung,pins = "gpr4-4", "gpr4-5", "gpr4-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <3>;
+	};
+
+	sd2_clk_output: sd2-clk-output {
+		samsung,pins = "gpr4-0";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <2>;
+	};
+
+	sd2_cmd_output: sd2-cmd-output {
+		samsung,pins = "gpr4-1";
+		samsung,pin-function = <1>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <2>;
+	};
+};
+
+&pinctrl_imem {
+	gpf0: gpf0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
+
+&pinctrl_nfc {
+	gpj0: gpj0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	hs_i2c4_bus: hs-i2c4-bus {
+		samsung,pins = "gpj0-1", "gpj0-0";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&pinctrl_peric {
+	gpv7: gpv7 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpb0: gpb0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc0: gpc0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc1: gpc1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc2: gpc2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpc3: gpc3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg0: gpg0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd0: gpd0 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd1: gpd1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd2: gpd2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd4: gpd4 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd8: gpd8 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd6: gpd6 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpd7: gpd7 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg1: gpg1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg2: gpg2 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	gpg3: gpg3 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	hs_i2c8_bus: hs-i2c8-bus {
+		samsung,pins = "gpb0-1", "gpb0-0";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hs_i2c9_bus: hs-i2c9-bus {
+		samsung,pins = "gpb0-3", "gpb0-2";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	i2s1_bus: i2s1-bus {
+		samsung,pins = "gpd4-0", "gpd4-1", "gpd4-2",
+				"gpd4-3", "gpd4-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
+	};
+
+	pcm1_bus: pcm1-bus {
+		samsung,pins = "gpd4-0", "gpd4-1", "gpd4-2",
+				"gpd4-3", "gpd4-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
+	};
+
+	spdif_bus: spdif-bus {
+		samsung,pins = "gpd4-3", "gpd4-4";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <1>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_spi_pin0: fimc-is-spi-pin0 {
+		samsung,pins = "gpc3-3", "gpc3-2", "gpc3-1", "gpc3-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_spi_pin1: fimc-is-spi-pin1 {
+		samsung,pins = "gpc3-7", "gpc3-6", "gpc3-5", "gpc3-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart0_bus: uart0-bus {
+		samsung,pins = "gpd0-3", "gpd0-2", "gpd0-1", "gpd0-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+	};
+
+	hs_i2c2_bus: hs-i2c2-bus {
+		samsung,pins = "gpd0-3", "gpd0-2";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	uart2_bus: uart2-bus {
+		samsung,pins = "gpd1-5", "gpd1-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+	};
+
+	uart1_bus: uart1-bus {
+		samsung,pins = "gpd1-3", "gpd1-2", "gpd1-1", "gpd1-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+	};
+
+	hs_i2c3_bus: hs-i2c3-bus {
+		samsung,pins = "gpd1-3", "gpd1-2";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hs_i2c0_bus: hs-i2c0-bus {
+		samsung,pins = "gpd2-1", "gpd2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hs_i2c1_bus: hs-i2c1-bus {
+		samsung,pins = "gpd2-3", "gpd2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm0_out: pwm0-out {
+		samsung,pins = "gpd2-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm1_out: pwm1-out {
+		samsung,pins = "gpd2-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm2_out: pwm2-out {
+		samsung,pins = "gpd2-6";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	pwm3_out: pwm3-out {
+		samsung,pins = "gpd2-7";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	spi1_bus: spi1-bus {
+		samsung,pins = "gpd6-2", "gpd6-4", "gpd6-5";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hs_i2c7_bus: hs-i2c7-bus {
+		samsung,pins = "gpd2-7", "gpd2-6";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	spi0_bus: spi0-bus {
+		samsung,pins = "gpd8-0", "gpd6-0", "gpd6-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hs_i2c10_bus: hs-i2c10-bus {
+		samsung,pins = "gpg3-1", "gpg3-0";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	hs_i2c11_bus: hs-i2c11-bus {
+		samsung,pins = "gpg3-3", "gpg3-2";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	spi3_bus: spi3-bus {
+		samsung,pins = "gpg3-4", "gpg3-6", "gpg3-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	spi4_bus: spi4-bus {
+		samsung,pins = "gpv7-1", "gpv7-3", "gpv7-4";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_uart: fimc-is-uart {
+		samsung,pins = "gpc1-1", "gpc0-7";
+		samsung,pin-function = <3>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_ch0_i2c: fimc-is-ch0_i2c {
+		samsung,pins = "gpc2-1", "gpc2-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_ch0_mclk: fimc-is-ch0_mclk {
+		samsung,pins = "gpd7-0";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_ch1_i2c: fimc-is-ch1-i2c {
+		samsung,pins = "gpc2-3", "gpc2-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_ch1_mclk: fimc-is-ch1-mclk {
+		samsung,pins = "gpd7-1";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_ch2_i2c: fimc-is-ch2-i2c {
+		samsung,pins = "gpc2-5", "gpc2-4";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+
+	fimc_is_ch2_mclk: fimc-is-ch2-mclk {
+		samsung,pins = "gpd7-2";
+		samsung,pin-function = <2>;
+		samsung,pin-pud = <0>;
+		samsung,pin-drv = <0>;
+	};
+};
+
+&pinctrl_touch {
+	gpj1: gpj1 {
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	hs_i2c5_bus: hs-i2c5-bus {
+		samsung,pins = "gpj1-1", "gpj1-0";
+		samsung,pin-function = <4>;
+		samsung,pin-pud = <3>;
+		samsung,pin-drv = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1049 @@
+/*
+ * SAMSUNG Exynos5433 TM2 board device tree source
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Device tree source file for Samsung's TM2 board which is based on
+ * Samsung Exynos5433 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/dts-v1/;
+#include "exynos5433.dtsi"
+#include <dt-bindings/clock/samsung,s2mps11.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "Samsung TM2 board";
+	compatible = "samsung,tm2", "samsung,exynos5433";
+
+	aliases {
+		gsc0 = &gsc_0;
+		gsc1 = &gsc_1;
+		gsc2 = &gsc_2;
+		pinctrl0 = &pinctrl_alive;
+		pinctrl1 = &pinctrl_aud;
+		pinctrl2 = &pinctrl_cpif;
+		pinctrl3 = &pinctrl_ese;
+		pinctrl4 = &pinctrl_finger;
+		pinctrl5 = &pinctrl_fsys;
+		pinctrl6 = &pinctrl_imem;
+		pinctrl7 = &pinctrl_nfc;
+		pinctrl8 = &pinctrl_peric;
+		pinctrl9 = &pinctrl_touch;
+		serial0 = &serial_0;
+		serial1 = &serial_1;
+		serial2 = &serial_2;
+		serial3 = &serial_3;
+		spi0 = &spi_0;
+		spi1 = &spi_1;
+		spi2 = &spi_2;
+		spi3 = &spi_3;
+		spi4 = &spi_4;
+		mshc0 = &mshc_0;
+		mshc2 = &mshc_2;
+	};
+
+	chosen {
+		stdout-path = &serial_1;
+	};
+
+	memory@20000000 {
+		device_type = "memory";
+		reg = <0x0 0x20000000 0x0 0xc0000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		power-key {
+			gpios = <&gpa2 7 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_POWER>;
+			label = "power key";
+			debounce-interval = <10>;
+		};
+
+		volume-up-key {
+			gpios = <&gpa2 0 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEUP>;
+			label = "volume-up key";
+			debounce-interval = <10>;
+		};
+
+		volume-down-key {
+			gpios = <&gpa2 1 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_VOLUMEDOWN>;
+			label = "volume-down key";
+			debounce-interval = <10>;
+		};
+
+		homepage-key {
+			gpios = <&gpa0 3 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_MENU>;
+			label = "homepage key";
+			debounce-interval = <10>;
+		};
+	};
+
+	i2c_max98504: i2c-gpio-0 {
+		compatible = "i2c-gpio";
+		gpios = <&gpd0 1 GPIO_ACTIVE_HIGH /* SPK_AMP_SDA */
+			 &gpd0 0 GPIO_ACTIVE_HIGH /* SPK_AMP_SCL */ >;
+		i2c-gpio,delay-us = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "okay";
+
+		max98504: max98504@31 {
+			compatible = "maxim,max98504";
+			reg = <0x31>;
+			maxim,rx-path = <1>;
+			maxim,tx-path = <1>;
+			maxim,tx-channel-mask = <3>;
+			maxim,tx-channel-source = <2>;
+		};
+	};
+
+	sound {
+		compatible = "samsung,tm2-audio";
+		audio-codec = <&wm5110>;
+		i2s-controller = <&i2s0>;
+		audio-amplifier = <&max98504>;
+		mic-bias-gpios = <&gpr3 2 GPIO_ACTIVE_HIGH>;
+		model = "wm5110";
+		samsung,audio-routing =
+			/* Headphone */
+			"HP", "HPOUT1L",
+			"HP", "HPOUT1R",
+
+			/* Speaker */
+			"SPK", "SPKOUT",
+			"SPKOUT", "HPOUT2L",
+			"SPKOUT", "HPOUT2R",
+
+			/* Receiver */
+			"RCV", "HPOUT3L",
+			"RCV", "HPOUT3R";
+		status = "okay";
+	};
+};
+
+&adc {
+	vdd-supply = <&ldo3_reg>;
+	status = "okay";
+
+	thermistor-ap {
+		compatible = "murata,ncp03wf104";
+		pullup-uv = <1800000>;
+		pullup-ohm = <100000>;
+		pulldown-ohm = <0>;
+		io-channels = <&adc 0>;
+	};
+
+	thermistor-battery {
+		compatible = "murata,ncp03wf104";
+		pullup-uv = <1800000>;
+		pullup-ohm = <100000>;
+		pulldown-ohm = <0>;
+		io-channels = <&adc 1>;
+		#thermal-sensor-cells = <0>;
+	};
+
+	thermistor-charger {
+		compatible = "murata,ncp03wf104";
+		pullup-uv = <1800000>;
+		pullup-ohm = <100000>;
+		pulldown-ohm = <0>;
+		io-channels = <&adc 2>;
+	};
+};
+
+&cmu_aud {
+	assigned-clocks = <&cmu_aud CLK_MOUT_AUD_PLL_USER>;
+	assigned-clock-parents = <&cmu_top CLK_FOUT_AUD_PLL>;
+};
+
+&cmu_fsys {
+	assigned-clocks = <&cmu_top CLK_MOUT_SCLK_USBDRD30>,
+		<&cmu_top CLK_MOUT_SCLK_USBHOST30>,
+		<&cmu_fsys CLK_MOUT_SCLK_USBDRD30_USER>,
+		<&cmu_fsys CLK_MOUT_SCLK_USBHOST30_USER>,
+		<&cmu_fsys CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_USER>,
+		<&cmu_fsys CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_USER>,
+		<&cmu_fsys CLK_MOUT_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_USER>,
+		<&cmu_fsys CLK_MOUT_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_USER>,
+		<&cmu_top CLK_DIV_SCLK_USBDRD30>,
+		<&cmu_top CLK_DIV_SCLK_USBHOST30>;
+	assigned-clock-parents = <&cmu_top CLK_MOUT_BUS_PLL_USER>,
+		<&cmu_top CLK_MOUT_BUS_PLL_USER>,
+		<&cmu_top CLK_SCLK_USBDRD30_FSYS>,
+		<&cmu_top CLK_SCLK_USBHOST30_FSYS>,
+		<&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PIPE_PCLK_PHY>,
+		<&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PIPE_PCLK_PHY>,
+		<&cmu_fsys CLK_PHYCLK_USBDRD30_UDRD30_PHYCLOCK_PHY>,
+		<&cmu_fsys CLK_PHYCLK_USBHOST30_UHOST30_PHYCLOCK_PHY>;
+	assigned-clock-rates = <0>, <0>, <0>, <0>, <0>, <0>, <0>, <0>,
+			       <66700000>, <66700000>;
+};
+
+&cmu_gscl {
+	assigned-clocks = <&cmu_gscl CLK_MOUT_ACLK_GSCL_111_USER>,
+			  <&cmu_gscl CLK_MOUT_ACLK_GSCL_333_USER>;
+	assigned-clock-parents = <&cmu_top CLK_ACLK_GSCL_111>,
+				 <&cmu_top CLK_ACLK_GSCL_333>;
+};
+
+&cmu_mfc {
+	assigned-clocks = <&cmu_mfc CLK_MOUT_ACLK_MFC_400_USER>;
+	assigned-clock-parents = <&cmu_top CLK_ACLK_MFC_400>;
+};
+
+&cmu_mscl {
+	assigned-clocks = <&cmu_mscl CLK_MOUT_ACLK_MSCL_400_USER>,
+			  <&cmu_mscl CLK_MOUT_SCLK_JPEG_USER>,
+			  <&cmu_mscl CLK_MOUT_SCLK_JPEG>,
+			  <&cmu_top CLK_MOUT_SCLK_JPEG_A>;
+	assigned-clock-parents = <&cmu_top CLK_ACLK_MSCL_400>,
+				 <&cmu_top CLK_SCLK_JPEG_MSCL>,
+				 <&cmu_mscl CLK_MOUT_SCLK_JPEG_USER>,
+				 <&cmu_top CLK_MOUT_BUS_PLL_USER>;
+};
+
+&cpu0 {
+	cpu-supply = <&buck3_reg>;
+};
+
+&cpu4 {
+	cpu-supply = <&buck2_reg>;
+};
+
+&decon {
+	status = "okay";
+
+	i80-if-timings {
+	};
+};
+
+&dsi {
+	status = "okay";
+	vddcore-supply = <&ldo6_reg>;
+	vddio-supply = <&ldo7_reg>;
+	samsung,pll-clock-frequency = <24000000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&te_irq>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@1 {
+			reg = <1>;
+
+			dsi_out: endpoint {
+				samsung,burst-clock-frequency = <512000000>;
+				samsung,esc-clock-frequency = <16000000>;
+			};
+		};
+	};
+};
+
+&hsi2c_0 {
+	status = "okay";
+	clock-frequency = <2500000>;
+
+	s2mps13-pmic@66 {
+		compatible = "samsung,s2mps13-pmic";
+		interrupt-parent = <&gpa0>;
+		interrupts = <7 IRQ_TYPE_NONE>;
+		reg = <0x66>;
+		samsung,s2mps11-wrstbi-ground;
+
+		s2mps13_osc: clocks {
+			compatible = "samsung,s2mps13-clk";
+			#clock-cells = <1>;
+			clock-output-names = "s2mps13_ap", "s2mps13_cp",
+				"s2mps13_bt";
+		};
+
+		regulators {
+			ldo1_reg: LDO1 {
+				regulator-name = "VDD_ALIVE_0.9V_AP";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <900000>;
+				regulator-always-on;
+			};
+
+			ldo2_reg: LDO2 {
+				regulator-name = "VDDQ_MMC2_2.8V_AP";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo3_reg: LDO3 {
+				regulator-name = "VDD1_E_1.8V_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo4_reg: LDO4 {
+				regulator-name = "VDD10_MIF_PLL_1.0V_AP";
+				regulator-min-microvolt = <1300000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo5_reg: LDO5 {
+				regulator-name = "VDD10_DPLL_1.0V_AP";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo6_reg: LDO6 {
+				regulator-name = "VDD10_MIPI2L_1.0V_AP";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo7_reg: LDO7 {
+				regulator-name = "VDD18_MIPI2L_1.8V_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo8_reg: LDO8 {
+				regulator-name = "VDD18_LLI_1.8V_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo9_reg: LDO9 {
+				regulator-name = "VDD18_ABB_ETC_1.8V_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo10_reg: LDO10 {
+				regulator-name = "VDD33_USB30_3.0V_AP";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo11_reg: LDO11 {
+				regulator-name = "VDD_INT_M_1.0V_AP";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo12_reg: LDO12 {
+				regulator-name = "VDD_KFC_M_1.1V_AP";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-always-on;
+			};
+
+			ldo13_reg: LDO13 {
+				regulator-name = "VDD_G3D_M_0.95V_AP";
+				regulator-min-microvolt = <950000>;
+				regulator-max-microvolt = <950000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo14_reg: LDO14 {
+				regulator-name = "VDDQ_M1_LDO_1.2V_AP";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo15_reg: LDO15 {
+				regulator-name = "VDDQ_M2_LDO_1.2V_AP";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo16_reg: LDO16 {
+				regulator-name = "VDDQ_EFUSE";
+				regulator-min-microvolt = <1400000>;
+				regulator-max-microvolt = <3400000>;
+				regulator-always-on;
+			};
+
+			ldo17_reg: LDO17 {
+				regulator-name = "V_TFLASH_2.8V_AP";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			ldo18_reg: LDO18 {
+				regulator-name = "V_CODEC_1.8V_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo19_reg: LDO19 {
+				regulator-name = "VDDA_1.8V_COMP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+			};
+
+			ldo20_reg: LDO20 {
+				regulator-name = "VCC_2.8V_AP";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+				regulator-always-on;
+			};
+
+			ldo21_reg: LDO21 {
+				regulator-name = "VT_CAM_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo22_reg: LDO22 {
+				regulator-name = "CAM_IO_1.8V_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo23_reg: LDO23 {
+				regulator-name = "CAM_SEN_CORE_1.2V_AP";
+				regulator-min-microvolt = <1050000>;
+				regulator-max-microvolt = <1200000>;
+			};
+
+			ldo24_reg: LDO24 {
+				regulator-name = "VT_CAM_1.2V";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+			};
+
+			ldo25_reg: LDO25 {
+				regulator-name = "CAM_SEN_A2.8V_AP";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			ldo26_reg: LDO26 {
+				regulator-name = "CAM_AF_2.8V_AP";
+				regulator-min-microvolt = <2800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			ldo27_reg: LDO27 {
+				regulator-name = "VCC_3.0V_LCD_AP";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldo28_reg: LDO28 {
+				regulator-name = "VCC_1.8V_LCD_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo29_reg: LDO29 {
+				regulator-name = "VT_CAM_2.8V";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldo30_reg: LDO30 {
+				regulator-name = "TSP_AVDD_3.3V_AP";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo31_reg: LDO31 {
+				regulator-name = "TSP_VDD_1.85V_AP";
+				regulator-min-microvolt = <1850000>;
+				regulator-max-microvolt = <1850000>;
+			};
+
+			ldo32_reg: LDO32 {
+				regulator-name = "VTOUCH_1.8V_AP";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo33_reg: LDO33 {
+				regulator-name = "VTOUCH_LED_3.3V";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-ramp-delay = <12500>;
+			};
+
+			ldo34_reg: LDO34 {
+				regulator-name = "VCC_1.8V_MHL_AP";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <2100000>;
+			};
+
+			ldo35_reg: LDO35 {
+				regulator-name = "OIS_VM_2.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <2800000>;
+			};
+
+			ldo36_reg: LDO36 {
+				regulator-name = "VSIL_1.0V";
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+			};
+
+			ldo37_reg: LDO37 {
+				regulator-name = "VF_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo38_reg: LDO38 {
+				regulator-name = "VCC_3.0V_MOTOR_AP";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldo39_reg: LDO39 {
+				regulator-name = "V_HRM_1.8V";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+			};
+
+			ldo40_reg: LDO40 {
+				regulator-name = "V_HRM_3.3V";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			buck1_reg: BUCK1 {
+				regulator-name = "VDD_MIF_0.9V_AP";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			buck2_reg: BUCK2 {
+				regulator-name = "VDD_EGL_1.0V_AP";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			buck3_reg: BUCK3 {
+				regulator-name = "VDD_KFC_1.0V_AP";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			buck4_reg: BUCK4 {
+				regulator-name = "VDD_INT_0.95V_AP";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			buck5_reg: BUCK5 {
+				regulator-name = "VDD_DISP_CAM0_0.9V_AP";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			buck6_reg: BUCK6 {
+				regulator-name = "VDD_G3D_0.9V_AP";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			buck7_reg: BUCK7 {
+				regulator-name = "VDD_MEM1_1.2V_AP";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-always-on;
+			};
+
+			buck8_reg: BUCK8 {
+				regulator-name = "VDD_LLDO_1.35V_AP";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			buck9_reg: BUCK9 {
+				regulator-name = "VDD_MLDO_2.0V_AP";
+				regulator-min-microvolt = <1350000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-always-on;
+			};
+
+			buck10_reg: BUCK10 {
+				regulator-name = "vdd_mem2";
+				regulator-min-microvolt = <550000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&hsi2c_8 {
+	status = "okay";
+
+	max77843@66 {
+		compatible = "maxim,max77843";
+		interrupt-parent = <&gpa1>;
+		interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+		reg = <0x66>;
+
+		muic: max77843-muic {
+			compatible = "maxim,max77843-muic";
+		};
+
+		regulators {
+			compatible = "maxim,max77843-regulator";
+			safeout1_reg: SAFEOUT1 {
+				regulator-name = "SAFEOUT1";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <4950000>;
+			};
+
+			safeout2_reg: SAFEOUT2 {
+				regulator-name = "SAFEOUT2";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <4950000>;
+			};
+
+			charger_reg: CHARGER {
+				regulator-name = "CHARGER";
+				regulator-min-microamp = <100000>;
+				regulator-max-microamp = <3150000>;
+			};
+		};
+
+		haptic: max77843-haptic {
+			compatible = "maxim,max77843-haptic";
+			haptic-supply = <&ldo38_reg>;
+			pwms = <&pwm 0 33670 0>;
+			pwm-names = "haptic";
+		};
+	};
+};
+
+&i2s0 {
+	status = "okay";
+};
+
+&mshc_0 {
+	status = "okay";
+	num-slots = <1>;
+	mmc-hs200-1_8v;
+	mmc-hs400-1_8v;
+	cap-mmc-highspeed;
+	non-removable;
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	samsung,dw-mshc-hs400-timing = <0 3>;
+	samsung,read-strobe-delay = <90>;
+	fifo-depth = <0x80>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_qrdy &sd0_bus1 &sd0_bus4
+			&sd0_bus8 &sd0_rdqs>;
+	bus-width = <8>;
+	assigned-clocks = <&cmu_top CLK_SCLK_MMC0_FSYS>;
+	assigned-clock-rates = <800000000>;
+};
+
+&mshc_2 {
+	status = "okay";
+	num-slots = <1>;
+	cap-sd-highspeed;
+	disable-wp;
+	cd-gpios = <&gpa2 4 GPIO_ACTIVE_HIGH>;
+	cd-inverted;
+	card-detect-delay = <200>;
+	samsung,dw-mshc-ciu-div = <3>;
+	samsung,dw-mshc-sdr-timing = <0 4>;
+	samsung,dw-mshc-ddr-timing = <0 2>;
+	fifo-depth = <0x80>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus1 &sd2_bus4>;
+	bus-width = <4>;
+};
+
+&pinctrl_alive {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_alive>;
+
+	initial_alive: initial-state {
+		PIN(IN, gpa0-0, DOWN, LV1);
+		PIN(IN, gpa0-1, NONE, LV1);
+		PIN(IN, gpa0-2, DOWN, LV1);
+		PIN(IN, gpa0-3, NONE, LV1);
+		PIN(IN, gpa0-4, NONE, LV1);
+		PIN(IN, gpa0-5, DOWN, LV1);
+		PIN(IN, gpa0-6, NONE, LV1);
+		PIN(IN, gpa0-7, NONE, LV1);
+
+		PIN(IN, gpa1-0, UP, LV1);
+		PIN(IN, gpa1-1, NONE, LV1);
+		PIN(IN, gpa1-2, NONE, LV1);
+		PIN(IN, gpa1-3, DOWN, LV1);
+		PIN(IN, gpa1-4, DOWN, LV1);
+		PIN(IN, gpa1-5, NONE, LV1);
+		PIN(IN, gpa1-6, NONE, LV1);
+		PIN(IN, gpa1-7, NONE, LV1);
+
+		PIN(IN, gpa2-0, NONE, LV1);
+		PIN(IN, gpa2-1, NONE, LV1);
+		PIN(IN, gpa2-2, NONE, LV1);
+		PIN(IN, gpa2-3, DOWN, LV1);
+		PIN(IN, gpa2-4, NONE, LV1);
+		PIN(IN, gpa2-5, DOWN, LV1);
+		PIN(IN, gpa2-6, DOWN, LV1);
+		PIN(IN, gpa2-7, NONE, LV1);
+
+		PIN(IN, gpa3-0, DOWN, LV1);
+		PIN(IN, gpa3-1, DOWN, LV1);
+		PIN(IN, gpa3-2, NONE, LV1);
+		PIN(IN, gpa3-3, DOWN, LV1);
+		PIN(IN, gpa3-4, NONE, LV1);
+		PIN(IN, gpa3-5, DOWN, LV1);
+		PIN(IN, gpa3-6, DOWN, LV1);
+		PIN(IN, gpa3-7, DOWN, LV1);
+
+		PIN(IN, gpf1-0, NONE, LV1);
+		PIN(IN, gpf1-1, NONE, LV1);
+		PIN(IN, gpf1-2, DOWN, LV1);
+		PIN(IN, gpf1-4, UP, LV1);
+		PIN(OUT, gpf1-5, NONE, LV1);
+		PIN(IN, gpf1-6, DOWN, LV1);
+		PIN(IN, gpf1-7, DOWN, LV1);
+
+		PIN(IN, gpf2-0, DOWN, LV1);
+		PIN(IN, gpf2-1, DOWN, LV1);
+		PIN(IN, gpf2-2, DOWN, LV1);
+		PIN(IN, gpf2-3, DOWN, LV1);
+
+		PIN(IN, gpf3-0, DOWN, LV1);
+		PIN(IN, gpf3-1, DOWN, LV1);
+		PIN(IN, gpf3-2, NONE, LV1);
+		PIN(IN, gpf3-3, DOWN, LV1);
+
+		PIN(IN, gpf4-0, DOWN, LV1);
+		PIN(IN, gpf4-1, DOWN, LV1);
+		PIN(IN, gpf4-2, DOWN, LV1);
+		PIN(IN, gpf4-3, DOWN, LV1);
+		PIN(IN, gpf4-4, DOWN, LV1);
+		PIN(IN, gpf4-5, DOWN, LV1);
+		PIN(IN, gpf4-6, DOWN, LV1);
+		PIN(IN, gpf4-7, DOWN, LV1);
+
+		PIN(IN, gpf5-0, DOWN, LV1);
+		PIN(IN, gpf5-1, DOWN, LV1);
+		PIN(IN, gpf5-2, DOWN, LV1);
+		PIN(IN, gpf5-3, DOWN, LV1);
+		PIN(OUT, gpf5-4, NONE, LV1);
+		PIN(IN, gpf5-5, DOWN, LV1);
+		PIN(IN, gpf5-6, DOWN, LV1);
+		PIN(IN, gpf5-7, DOWN, LV1);
+	};
+
+	te_irq: te_irq {
+		samsung,pins = "gpf1-3";
+		samsung,pin-function = <0xf>;
+	};
+};
+
+&pinctrl_cpif {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_cpif>;
+
+	initial_cpif: initial-state {
+		PIN(IN, gpv6-0, DOWN, LV1);
+		PIN(IN, gpv6-1, DOWN, LV1);
+	};
+};
+
+&pinctrl_ese {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_ese>;
+
+	initial_ese: initial-state {
+		PIN(IN, gpj2-0, DOWN, LV1);
+		PIN(IN, gpj2-1, DOWN, LV1);
+		PIN(IN, gpj2-2, DOWN, LV1);
+	};
+};
+
+&pinctrl_fsys {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_fsys>;
+
+	initial_fsys: initial-state {
+		PIN(IN, gpr3-0, NONE, LV1);
+		PIN(IN, gpr3-1, DOWN, LV1);
+		PIN(IN, gpr3-2, DOWN, LV1);
+		PIN(IN, gpr3-3, DOWN, LV1);
+		PIN(IN, gpr3-7, NONE, LV1);
+	};
+};
+
+&pinctrl_imem {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_imem>;
+
+	initial_imem: initial-state {
+		PIN(IN, gpf0-0, UP, LV1);
+		PIN(IN, gpf0-1, UP, LV1);
+		PIN(IN, gpf0-2, DOWN, LV1);
+		PIN(IN, gpf0-3, UP, LV1);
+		PIN(IN, gpf0-4, DOWN, LV1);
+		PIN(IN, gpf0-5, NONE, LV1);
+		PIN(IN, gpf0-6, DOWN, LV1);
+		PIN(IN, gpf0-7, UP, LV1);
+	};
+};
+
+&pinctrl_nfc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_nfc>;
+
+	initial_nfc: initial-state {
+		PIN(IN, gpj0-2, DOWN, LV1);
+	};
+};
+
+&pinctrl_peric {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_peric>;
+
+	initial_peric: initial-state {
+		PIN(IN, gpv7-0, DOWN, LV1);
+		PIN(IN, gpv7-1, DOWN, LV1);
+		PIN(IN, gpv7-2, NONE, LV1);
+		PIN(IN, gpv7-3, DOWN, LV1);
+		PIN(IN, gpv7-4, DOWN, LV1);
+		PIN(IN, gpv7-5, DOWN, LV1);
+
+		PIN(IN, gpb0-4, DOWN, LV1);
+
+		PIN(IN, gpc0-2, DOWN, LV1);
+		PIN(IN, gpc0-5, DOWN, LV1);
+		PIN(IN, gpc0-7, DOWN, LV1);
+
+		PIN(IN, gpc1-1, DOWN, LV1);
+
+		PIN(IN, gpc3-4, NONE, LV1);
+		PIN(IN, gpc3-5, NONE, LV1);
+		PIN(IN, gpc3-6, NONE, LV1);
+		PIN(IN, gpc3-7, NONE, LV1);
+
+		PIN(OUT, gpg0-0, NONE, LV1);
+		PIN(FUNC1, gpg0-1, DOWN, LV1);
+
+		PIN(IN, gpd2-5, DOWN, LV1);
+
+		PIN(IN, gpd4-0, NONE, LV1);
+		PIN(IN, gpd4-1, DOWN, LV1);
+		PIN(IN, gpd4-2, DOWN, LV1);
+		PIN(IN, gpd4-3, DOWN, LV1);
+		PIN(IN, gpd4-4, DOWN, LV1);
+
+		PIN(IN, gpd6-3, DOWN, LV1);
+
+		PIN(IN, gpd8-1, UP, LV1);
+
+		PIN(IN, gpg1-0, DOWN, LV1);
+		PIN(IN, gpg1-1, DOWN, LV1);
+		PIN(IN, gpg1-2, DOWN, LV1);
+		PIN(IN, gpg1-3, DOWN, LV1);
+		PIN(IN, gpg1-4, DOWN, LV1);
+
+		PIN(IN, gpg2-0, DOWN, LV1);
+		PIN(IN, gpg2-1, DOWN, LV1);
+
+		PIN(IN, gpg3-0, DOWN, LV1);
+		PIN(IN, gpg3-1, DOWN, LV1);
+		PIN(IN, gpg3-5, DOWN, LV1);
+		PIN(IN, gpg3-7, DOWN, LV1);
+	};
+};
+
+&pinctrl_touch {
+	pinctrl-names = "default";
+	pinctrl-0 = <&initial_touch>;
+
+	initial_touch: initial-state {
+		PIN(IN, gpj1-2, DOWN, LV1);
+	};
+};
+
+&pwm {
+	pinctrl-0 = <&pwm0_out>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&mic {
+	status = "okay";
+
+	i80-if-timings {
+	};
+};
+
+&pmu_system_controller {
+	assigned-clocks = <&pmu_system_controller 0>;
+	assigned-clock-parents = <&xxti>;
+};
+
+&serial_1 {
+	status = "okay";
+};
+
+&spi_1 {
+	cs-gpios = <&gpd6 3 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+
+	wm5110: wm5110-codec@0 {
+		compatible = "wlf,wm5110";
+		reg = <0x0>;
+		spi-max-frequency = <20000000>;
+		interrupt-parent = <&gpa0>;
+		interrupts = <4 IRQ_TYPE_NONE>;
+		clocks = <&pmu_system_controller 0>,
+			<&s2mps13_osc S2MPS11_CLK_BT>;
+		clock-names = "mclk1", "mclk2";
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		wlf,micd-detect-debounce = <300>;
+		wlf,micd-bias-start-time = <0x1>;
+		wlf,micd-rate = <0x7>;
+		wlf,micd-dbtime = <0x1>;
+		wlf,micd-force-micbias;
+		wlf,micd-configs = <0x0 1 0>;
+		wlf,hpdet-channel = <1>;
+		wlf,gpsw = <0x1>;
+		wlf,inmode = <2 0 2 0>;
+
+		wlf,reset = <&gpc0 7 GPIO_ACTIVE_HIGH>;
+		wlf,ldoena = <&gpf0 0 GPIO_ACTIVE_HIGH>;
+
+		/* core supplies */
+		AVDD-supply = <&ldo18_reg>;
+		DBVDD1-supply = <&ldo18_reg>;
+		CPVDD-supply = <&ldo18_reg>;
+		DBVDD2-supply = <&ldo18_reg>;
+		DBVDD3-supply = <&ldo18_reg>;
+
+		controller-data {
+			samsung,spi-feedback-delay = <0>;
+		};
+	};
+};
+
+&timer {
+	clock-frequency = <24000000>;
+};
+
+&tmu_atlas0 {
+	vtmu-supply = <&ldo3_reg>;
+	status = "okay";
+};
+
+&tmu_apollo {
+	vtmu-supply = <&ldo3_reg>;
+	status = "okay";
+};
+
+&tmu_g3d {
+	vtmu-supply = <&ldo3_reg>;
+	status = "okay";
+};
+
+&usbdrd30 {
+	vdd33-supply = <&ldo10_reg>;
+	vdd10-supply = <&ldo6_reg>;
+	status = "okay";
+};
+
+&usbdrd_dwc3_0 {
+	dr_mode = "otg";
+};
+
+&usbdrd30_phy {
+	vbus-supply = <&safeout1_reg>;
+	status = "okay";
+};
+
+&xxti {
+	clock-frequency = <24000000>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * SAMSUNG Exynos5433 TM2E board device tree source
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Device tree source file for Samsung's TM2E(TM2 EDGE) board which is based on
+ * Samsung Exynos5433 SoC.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "exynos5433-tm2.dts"
+
+/ {
+	model = "Samsung TM2E board";
+	compatible = "samsung,tm2e", "samsung,exynos5433";
+};
+
+&ldo23_reg {
+	regulator-name = "CAM_SEN_CORE_1.025V_AP";
+	regulator-max-microvolt = <1050000>;
+};
+
+&ldo25_reg {
+	regulator-name = "UNUSED_LDO25";
+	regulator-always-off;
+};
+
+&ldo31_reg {
+	regulator-name = "TSP_VDD_1.8V_AP";
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+};
+
+&ldo38_reg {
+	regulator-name = "VCC_3.3V_MOTOR_AP";
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,296 @@
+/*
+ * Device tree sources for Exynos5433 thermal zone
+ *
+ * Copyright (c) 2016 Chanwoo Choi <cw00.choi@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 <dt-bindings/thermal/thermal.h>
+
+/ {
+thermal-zones {
+	atlas0_thermal: atlas0-thermal {
+		thermal-sensors = <&tmu_atlas0>;
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		trips {
+			atlas0_alert_0: atlas0-alert-0 {
+				temperature = <65000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas0_alert_1: atlas0-alert-1 {
+				temperature = <70000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas0_alert_2: atlas0-alert-2 {
+				temperature = <75000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas0_alert_3: atlas0-alert-3 {
+				temperature = <80000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas0_alert_4: atlas0-alert-4 {
+				temperature = <85000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas0_alert_5: atlas0-alert-5 {
+				temperature = <90000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas0_alert_6: atlas0-alert-6 {
+				temperature = <95000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+		};
+
+		cooling-maps {
+			map0 {
+				/* Set maximum frequency as 1800MHz  */
+				trip = <&atlas0_alert_0>;
+				cooling-device = <&cpu4 1 2>;
+			};
+			map1 {
+				/* Set maximum frequency as 1700MHz  */
+				trip = <&atlas0_alert_1>;
+				cooling-device = <&cpu4 2 3>;
+			};
+			map2 {
+				/* Set maximum frequency as 1600MHz  */
+				trip = <&atlas0_alert_2>;
+				cooling-device = <&cpu4 3 4>;
+			};
+			map3 {
+				/* Set maximum frequency as 1500MHz  */
+				trip = <&atlas0_alert_3>;
+				cooling-device = <&cpu4 4 5>;
+			};
+			map4 {
+				/* Set maximum frequency as 1400MHz  */
+				trip = <&atlas0_alert_4>;
+				cooling-device = <&cpu4 5 7>;
+			};
+			map5 {
+				/* Set maximum frequencyas 1200MHz  */
+				trip = <&atlas0_alert_5>;
+				cooling-device = <&cpu4 7 9>;
+			};
+			map6 {
+				/* Set maximum frequency as 1000MHz  */
+				trip = <&atlas0_alert_6>;
+				cooling-device = <&cpu4 9 14>;
+			};
+		};
+	};
+
+	atlas1_thermal: atlas1-thermal {
+		thermal-sensors = <&tmu_atlas1>;
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		trips {
+			atlas1_alert_0: atlas1-alert-0 {
+				temperature = <65000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas1_alert_1: atlas1-alert-1 {
+				temperature = <70000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas1_alert_2: atlas1-alert-2 {
+				temperature = <75000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas1_alert_3: atlas1-alert-3 {
+				temperature = <80000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas1_alert_4: atlas1-alert-4 {
+				temperature = <85000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas1_alert_5: atlas1-alert-5 {
+				temperature = <90000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			atlas1_alert_6: atlas1-alert-6 {
+				temperature = <95000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+		};
+	};
+
+	g3d_thermal: g3d-thermal {
+		thermal-sensors = <&tmu_g3d>;
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		trips {
+			g3d_alert_0: g3d-alert-0 {
+				temperature = <70000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			g3d_alert_1: g3d-alert-1 {
+				temperature = <75000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			g3d_alert_2: g3d-alert-2 {
+				temperature = <80000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			g3d_alert_3: g3d-alert-3 {
+				temperature = <85000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			g3d_alert_4: g3d-alert-4 {
+				temperature = <90000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			g3d_alert_5: g3d-alert-5 {
+				temperature = <95000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			g3d_alert_6: g3d-alert-6 {
+				temperature = <100000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+		};
+	};
+
+	apollo_thermal: apollo-thermal {
+		thermal-sensors = <&tmu_apollo>;
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		trips {
+			apollo_alert_0: apollo-alert-0 {
+				temperature = <65000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			apollo_alert_1: apollo-alert-1 {
+				temperature = <70000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			apollo_alert_2: apollo-alert-2 {
+				temperature = <75000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			apollo_alert_3: apollo-alert-3 {
+				temperature = <80000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			apollo_alert_4: apollo-alert-4 {
+				temperature = <85000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			apollo_alert_5: apollo-alert-5 {
+				temperature = <90000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			apollo_alert_6: apollo-alert-6 {
+				temperature = <95000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+		};
+
+		cooling-maps {
+			map0 {
+				/* Set maximum frequency as 1200MHz  */
+				trip = <&apollo_alert_2>;
+				cooling-device = <&cpu0 1 2>;
+			};
+			map1 {
+				/* Set maximum frequency as 1100MHz  */
+				trip = <&apollo_alert_3>;
+				cooling-device = <&cpu0 2 3>;
+			};
+			map2 {
+				/* Set maximum frequency as 1000MHz  */
+				trip = <&apollo_alert_4>;
+				cooling-device = <&cpu0 3 4>;
+			};
+			map3 {
+				/* Set maximum frequency as 900MHz  */
+				trip = <&apollo_alert_5>;
+				cooling-device = <&cpu0 4 5>;
+			};
+			map4 {
+				/* Set maximum frequency as 800MHz  */
+				trip = <&apollo_alert_6>;
+				cooling-device = <&cpu0 5 9>;
+			};
+		};
+	};
+
+	isp_thermal: isp-thermal {
+		thermal-sensors = <&tmu_isp>;
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		trips {
+			isp_alert_0: isp-alert-0 {
+				temperature = <80000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			isp_alert_1: isp-alert-1 {
+				temperature = <85000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			isp_alert_2: isp-alert-2 {
+				temperature = <90000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			isp_alert_3: isp-alert-3 {
+				temperature = <95000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			isp_alert_4: isp-alert-4 {
+				temperature = <100000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			isp_alert_5: isp-alert-5 {
+				temperature = <105000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+			isp_alert_6: isp-alert-6 {
+				temperature = <110000>;	/* millicelsius */
+				hysteresis = <1000>;	/* millicelsius */
+				type = "active";
+			};
+		};
+	};
+};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-g3d-sensor-conf.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,23 @@
+/*
+ * Device tree sources for Exynos5433 TMU sensor configuration
+ *
+ * Copyright (c) 2016 Jonghwa Lee <jonghwa3.lee@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 <dt-bindings/thermal/thermal_exynos.h>
+
+#thermal-sensor-cells = <0>;
+samsung,tmu_gain = <8>;
+samsung,tmu_reference_voltage = <23>;
+samsung,tmu_noise_cancel_mode = <4>;
+samsung,tmu_efuse_value = <75>;
+samsung,tmu_min_efuse_value = <40>;
+samsung,tmu_max_efuse_value = <150>;
+samsung,tmu_first_point_trim = <25>;
+samsung,tmu_second_point_trim = <85>;
+samsung,tmu_default_temp_offset = <50>;
+samsung,tmu_mux_addr = <6>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos5433-tmu-sensor-conf.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Device tree sources for Exynos5433 TMU sensor configuration
+ *
+ * Copyright (c) 2016 Chanwoo Choi <cw00.choi@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 <dt-bindings/thermal/thermal_exynos.h>
+
+#thermal-sensor-cells = <0>;
+samsung,tmu_gain = <8>;
+samsung,tmu_reference_voltage = <16>;
+samsung,tmu_noise_cancel_mode = <4>;
+samsung,tmu_efuse_value = <75>;
+samsung,tmu_min_efuse_value = <40>;
+samsung,tmu_max_efuse_value = <150>;
+samsung,tmu_first_point_trim = <25>;
+samsung,tmu_second_point_trim = <85>;
+samsung,tmu_default_temp_offset = <50>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos7.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -35,28 +35,28 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu@0 {
+		cpu_atlas0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0x0>;
 			enable-method = "psci";
 		};
 
-		cpu@1 {
+		cpu_atlas1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0x1>;
 			enable-method = "psci";
 		};
 
-		cpu@2 {
+		cpu_atlas2: cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0x2>;
 			enable-method = "psci";
 		};
 
-		cpu@3 {
+		cpu_atlas3: cpu@3 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57", "arm,armv8";
 			reg = <0x3>;
@@ -106,7 +106,7 @@
 			pdma0: pdma@10E10000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x10E10000 0x1000>;
-				interrupts = <0 225 0>;
+				interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock_fsys0 ACLK_PDMA0>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -117,7 +117,7 @@
 			pdma1: pdma@10EB0000 {
 				compatible = "arm,pl330", "arm,primecell";
 				reg = <0x10EB0000 0x1000>;
-				interrupts = <0 226 0>;
+				interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clock_fsys0 ACLK_PDMA1>;
 				clock-names = "apb_pclk";
 				#dma-cells = <1>;
@@ -220,7 +220,7 @@
 		serial_0: serial@13630000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x13630000 0x100>;
-			interrupts = <0 440 0>;
+			interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peric0 PCLK_UART0>,
 				 <&clock_peric0 SCLK_UART0>;
 			clock-names = "uart", "clk_uart_baud0";
@@ -230,7 +230,7 @@
 		serial_1: serial@14c20000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x14c20000 0x100>;
-			interrupts = <0 456 0>;
+			interrupts = <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peric1 PCLK_UART1>,
 				 <&clock_peric1 SCLK_UART1>;
 			clock-names = "uart", "clk_uart_baud0";
@@ -240,7 +240,7 @@
 		serial_2: serial@14c30000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x14c30000 0x100>;
-			interrupts = <0 457 0>;
+			interrupts = <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peric1 PCLK_UART2>,
 				 <&clock_peric1 SCLK_UART2>;
 			clock-names = "uart", "clk_uart_baud0";
@@ -250,7 +250,7 @@
 		serial_3: serial@14c40000 {
 			compatible = "samsung,exynos4210-uart";
 			reg = <0x14c40000 0x100>;
-			interrupts = <0 458 0>;
+			interrupts = <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peric1 PCLK_UART3>,
 				 <&clock_peric1 SCLK_UART3>;
 			clock-names = "uart", "clk_uart_baud0";
@@ -264,62 +264,62 @@
 			wakeup-interrupt-controller {
 				compatible = "samsung,exynos7-wakeup-eint";
 				interrupt-parent = <&gic>;
-				interrupts = <0 16 0>;
+				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
 		pinctrl_bus0: pinctrl@13470000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x13470000 0x1000>;
-			interrupts = <0 383 0>;
+			interrupts = <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_nfc: pinctrl@14cd0000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x14cd0000 0x1000>;
-			interrupts = <0 473 0>;
+			interrupts = <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_touch: pinctrl@14ce0000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x14ce0000 0x1000>;
-			interrupts = <0 474 0>;
+			interrupts = <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_ff: pinctrl@14c90000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x14c90000 0x1000>;
-			interrupts = <0 475 0>;
+			interrupts = <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_ese: pinctrl@14ca0000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x14ca0000 0x1000>;
-			interrupts = <0 476 0>;
+			interrupts = <GIC_SPI 476 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_fsys0: pinctrl@10e60000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x10e60000 0x1000>;
-			interrupts = <0 221 0>;
+			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_fsys1: pinctrl@15690000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x15690000 0x1000>;
-			interrupts = <0 203 0>;
+			interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		pinctrl_bus1: pinctrl@14870000 {
 			compatible = "samsung,exynos7-pinctrl";
 			reg = <0x14870000 0x1000>;
-			interrupts = <0 384 0>;
+			interrupts = <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		hsi2c_0: hsi2c@13640000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x13640000 0x1000>;
-			interrupts = <0 441 0>;
+			interrupts = <GIC_SPI 441 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -332,7 +332,7 @@
 		hsi2c_1: hsi2c@13650000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x13650000 0x1000>;
-			interrupts = <0 442 0>;
+			interrupts = <GIC_SPI 442 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -345,7 +345,7 @@
 		hsi2c_2: hsi2c@14e60000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x14e60000 0x1000>;
-			interrupts = <0 459 0>;
+			interrupts = <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -358,7 +358,7 @@
 		hsi2c_3: hsi2c@14e70000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x14e70000 0x1000>;
-			interrupts = <0 460 0>;
+			interrupts = <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -371,7 +371,7 @@
 		hsi2c_4: hsi2c@13660000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x13660000 0x1000>;
-			interrupts = <0 443 0>;
+			interrupts = <GIC_SPI 443 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -384,7 +384,7 @@
 		hsi2c_5: hsi2c@13670000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x13670000 0x1000>;
-			interrupts = <0 444 0>;
+			interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -397,7 +397,7 @@
 		hsi2c_6: hsi2c@14e00000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x14e00000 0x1000>;
-			interrupts = <0 461 0>;
+			interrupts = <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -410,7 +410,7 @@
 		hsi2c_7: hsi2c@13e10000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x13e10000 0x1000>;
-			interrupts = <0 462 0>;
+			interrupts = <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -423,7 +423,7 @@
 		hsi2c_8: hsi2c@14e20000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x14e20000 0x1000>;
-			interrupts = <0 463 0>;
+			interrupts = <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -436,7 +436,7 @@
 		hsi2c_9: hsi2c@13680000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x13680000 0x1000>;
-			interrupts = <0 445 0>;
+			interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -449,7 +449,7 @@
 		hsi2c_10: hsi2c@13690000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x13690000 0x1000>;
-			interrupts = <0 446 0>;
+			interrupts = <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -462,7 +462,7 @@
 		hsi2c_11: hsi2c@136a0000 {
 			compatible = "samsung,exynos7-hsi2c";
 			reg = <0x136a0000 0x1000>;
-			interrupts = <0 447 0>;
+			interrupts = <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			pinctrl-names = "default";
@@ -472,6 +472,16 @@
 			status = "disabled";
 		};
 
+		arm-pmu {
+			compatible = "arm,cortex-a57-pmu", "arm,armv8-pmuv3";
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-affinity = <&cpu_atlas0>, <&cpu_atlas1>,
+					     <&cpu_atlas2>, <&cpu_atlas3>;
+		};
+
 		timer {
 			compatible = "arm,armv8-timer";
 			interrupts = <GIC_PPI 13
@@ -499,7 +509,8 @@
 		rtc: rtc@10590000 {
 			compatible = "samsung,s3c6410-rtc";
 			reg = <0x10590000 0x100>;
-			interrupts = <0 355 0>, <0 356 0>;
+			interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_ccore PCLK_RTC>;
 			clock-names = "rtc";
 			status = "disabled";
@@ -508,7 +519,7 @@
 		watchdog: watchdog@101d0000 {
 			compatible = "samsung,exynos7-wdt";
 			reg = <0x101d0000 0x100>;
-			interrupts = <0 110 0>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peris PCLK_WDT>;
 			clock-names = "watchdog";
 			samsung,syscon-phandle = <&pmu_system_controller>;
@@ -517,7 +528,7 @@
 
 		mmc_0: mmc@15740000 {
 			compatible = "samsung,exynos7-dw-mshc-smu";
-			interrupts = <0 201 0>;
+			interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x15740000 0x2000>;
@@ -530,7 +541,7 @@
 
 		mmc_1: mmc@15750000 {
 			compatible = "samsung,exynos7-dw-mshc";
-			interrupts = <0 202 0>;
+			interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x15750000 0x2000>;
@@ -543,7 +554,7 @@
 
 		mmc_2: mmc@15560000 {
 			compatible = "samsung,exynos7-dw-mshc-smu";
-			interrupts = <0 216 0>;
+			interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x15560000 0x2000>;
@@ -557,7 +568,7 @@
 		adc: adc@13620000 {
 			compatible = "samsung,exynos7-adc";
 			reg = <0x13620000 0x100>;
-			interrupts = <0 448 0>;
+			interrupts = <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peric0 PCLK_ADCIF>;
 			clock-names = "adc";
 			#io-channel-cells = <1>;
@@ -577,7 +588,7 @@
 		tmuctrl_0: tmu@10060000 {
 			compatible = "samsung,exynos7-tmu";
 			reg = <0x10060000 0x200>;
-			interrupts = <0 108 0>;
+			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clock_peris PCLK_TMU>,
 				 <&clock_peris SCLK_TMU>;
 			clock-names = "tmu_apbif", "tmu_sclk";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/exynos7-pinctrl.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -20,8 +20,14 @@
 		interrupt-controller;
 		interrupt-parent = <&gic>;
 		#interrupt-cells = <2>;
-		interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
-			     <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>;
+		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	gpa1: gpa1 {
@@ -31,8 +37,14 @@
 		interrupt-controller;
 		interrupt-parent = <&gic>;
 		#interrupt-cells = <2>;
-		interrupts = <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
-			     <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
+		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	gpa2: gpa2 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/exynos/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/exynos/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,7 @@
-dtb-$(CONFIG_ARCH_EXYNOS) += exynos7-espresso.dtb
+dtb-$(CONFIG_ARCH_EXYNOS) += \
+	exynos5433-tm2.dtb	\
+	exynos5433-tm2e.dtb	\
+	exynos7-espresso.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,8 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/thermal/thermal.h>
+
 / {
 	compatible = "fsl,ls1043a";
 	interrupt-parent = <&gic>;
@@ -66,6 +68,7 @@
 			reg = <0x0>;
 			clocks = <&clockgen 1 0>;
 			next-level-cache = <&l2>;
+			#cooling-cells = <2>;
 		};
 
 		cpu1: cpu@1 {
@@ -255,6 +258,81 @@
 			big-endian;
 		};
 
+		tmu: tmu@1f00000 {
+			compatible = "fsl,qoriq-tmu";
+			reg = <0x0 0x1f00000 0x0 0x10000>;
+			interrupts = <0 33 0x4>;
+			fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+			fsl,tmu-calibration = <0x00000000 0x00000026
+					       0x00000001 0x0000002d
+					       0x00000002 0x00000032
+					       0x00000003 0x00000039
+					       0x00000004 0x0000003f
+					       0x00000005 0x00000046
+					       0x00000006 0x0000004d
+					       0x00000007 0x00000054
+					       0x00000008 0x0000005a
+					       0x00000009 0x00000061
+					       0x0000000a 0x0000006a
+					       0x0000000b 0x00000071
+
+					       0x00010000 0x00000025
+					       0x00010001 0x0000002c
+					       0x00010002 0x00000035
+					       0x00010003 0x0000003d
+					       0x00010004 0x00000045
+					       0x00010005 0x0000004e
+					       0x00010006 0x00000057
+					       0x00010007 0x00000061
+					       0x00010008 0x0000006b
+					       0x00010009 0x00000076
+
+					       0x00020000 0x00000029
+					       0x00020001 0x00000033
+					       0x00020002 0x0000003d
+					       0x00020003 0x00000049
+					       0x00020004 0x00000056
+					       0x00020005 0x00000061
+					       0x00020006 0x0000006d
+
+					       0x00030000 0x00000021
+					       0x00030001 0x0000002a
+					       0x00030002 0x0000003c
+					       0x00030003 0x0000004e>;
+			#thermal-sensor-cells = <1>;
+		};
+
+		thermal-zones {
+			cpu_thermal: cpu-thermal {
+				polling-delay-passive = <1000>;
+				polling-delay = <5000>;
+
+				thermal-sensors = <&tmu 3>;
+
+				trips {
+					cpu_alert: cpu-alert {
+						temperature = <85000>;
+						hysteresis = <2000>;
+						type = "passive";
+					};
+					cpu_crit: cpu-crit {
+						temperature = <95000>;
+						hysteresis = <2000>;
+						type = "critical";
+					};
+				};
+
+				cooling-maps {
+					map0 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu0 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+				};
+			};
+		};
+
 		dspi0: dspi@2100000 {
 			compatible = "fsl,ls1043a-dspi", "fsl,ls1021a-v1.0-dspi";
 			#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-qds.dts	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
  */
 
 /dts-v1/;
-/include/ "fsl-ls1043a.dtsi"
+#include "fsl-ls1043a.dtsi"
 
 / {
 	model = "LS1043A QDS Board";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
  */
 
 /dts-v1/;
-/include/ "fsl-ls1043a.dtsi"
+#include "fsl-ls1043a.dtsi"
 
 / {
 	model = "LS1043A RDB Board";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,515 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-1046A family SoC.
+ *
+ * Copyright 2016, Freescale Semiconductor, Inc.
+ *
+ * Mingkai Hu <mingkai.hu@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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 <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "fsl,ls1046a";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		crypto = &crypto;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72";
+			reg = <0x0>;
+			clocks = <&clockgen 1 0>;
+			next-level-cache = <&l2>;
+			cpu-idle-states = <&CPU_PH20>;
+		};
+
+		cpu1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72";
+			reg = <0x1>;
+			clocks = <&clockgen 1 0>;
+			next-level-cache = <&l2>;
+			cpu-idle-states = <&CPU_PH20>;
+		};
+
+		cpu2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72";
+			reg = <0x2>;
+			clocks = <&clockgen 1 0>;
+			next-level-cache = <&l2>;
+			cpu-idle-states = <&CPU_PH20>;
+		};
+
+		cpu3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72";
+			reg = <0x3>;
+			clocks = <&clockgen 1 0>;
+			next-level-cache = <&l2>;
+			cpu-idle-states = <&CPU_PH20>;
+		};
+
+		l2: l2-cache {
+			compatible = "cache";
+		};
+	};
+
+	idle-states {
+		/*
+		 * PSCI node is not added default, U-boot will add missing
+		 * parts if it determines to use PSCI.
+		 */
+		entry-method = "arm,psci";
+
+		CPU_PH20: cpu-ph20 {
+			compatible = "arm,idle-state";
+			idle-state-name = "PH20";
+			arm,psci-suspend-param = <0x00010000>;
+			entry-latency-us = <1000>;
+			exit-latency-us = <1000>;
+			min-residency-us = <3000>;
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+	};
+
+	sysclk: sysclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-output-names = "sysclk";
+	};
+
+	reboot {
+		compatible ="syscon-reboot";
+		regmap = <&dcfg>;
+		offset = <0xb0>;
+		mask = <0x02>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_RAW(0xf) |
+					  IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14 (GIC_CPU_MASK_RAW(0xf) |
+					  IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11 (GIC_CPU_MASK_RAW(0xf) |
+					  IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10 (GIC_CPU_MASK_RAW(0xf) |
+					  IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a72-pmu";
+		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>,
+				     <&cpu1>,
+				     <&cpu2>,
+				     <&cpu3>;
+	};
+
+	gic: interrupt-controller@1400000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x0 0x1410000 0 0x10000>, /* GICD */
+		      <0x0 0x1420000 0 0x20000>, /* GICC */
+		      <0x0 0x1440000 0 0x20000>, /* GICH */
+		      <0x0 0x1460000 0 0x20000>; /* GICV */
+		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_RAW(0xf) |
+					 IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ddr: memory-controller@1080000 {
+			compatible = "fsl,qoriq-memory-controller";
+			reg = <0x0 0x1080000 0x0 0x1000>;
+			interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+			big-endian;
+		};
+
+		ifc: ifc@1530000 {
+			compatible = "fsl,ifc", "simple-bus";
+			reg = <0x0 0x1530000 0x0 0x10000>;
+			interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		qspi: quadspi@1550000 {
+			compatible = "fsl,ls1021a-qspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x1550000 0x0 0x10000>,
+				<0x0 0x40000000 0x0 0x10000000>;
+			reg-names = "QuadSPI", "QuadSPI-memory";
+			interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "qspi_en", "qspi";
+			clocks = <&clockgen 4 1>, <&clockgen 4 1>;
+			big-endian;
+			fsl,qspi-has-second-chip;
+			status = "disabled";
+		};
+
+		esdhc: esdhc@1560000 {
+			compatible = "fsl,esdhc";
+			reg = <0x0 0x1560000 0x0 0x10000>;
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+			clock-frequency = <0>;
+			voltage-ranges = <1800 1800 3300 3300>;
+			sdhci,auto-cmd12;
+			big-endian;
+			bus-width = <4>;
+		};
+
+		scfg: scfg@1570000 {
+			compatible = "fsl,ls1046a-scfg", "syscon";
+			reg = <0x0 0x1570000 0x0 0x10000>;
+			big-endian;
+		};
+
+		crypto: crypto@1700000 {
+			compatible = "fsl,sec-v5.4", "fsl,sec-v5.0",
+				     "fsl,sec-v4.0";
+			fsl,sec-era = <8>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0x00 0x1700000 0x100000>;
+			reg = <0x00 0x1700000 0x0 0x100000>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+
+			sec_jr0: jr@10000 {
+				compatible = "fsl,sec-v5.4-job-ring",
+					     "fsl,sec-v5.0-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg	   = <0x10000 0x10000>;
+				interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			sec_jr1: jr@20000 {
+				compatible = "fsl,sec-v5.4-job-ring",
+					     "fsl,sec-v5.0-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg	   = <0x20000 0x10000>;
+				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			sec_jr2: jr@30000 {
+				compatible = "fsl,sec-v5.4-job-ring",
+					     "fsl,sec-v5.0-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg	   = <0x30000 0x10000>;
+				interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+			};
+
+			sec_jr3: jr@40000 {
+				compatible = "fsl,sec-v5.4-job-ring",
+					     "fsl,sec-v5.0-job-ring",
+					     "fsl,sec-v4.0-job-ring";
+				reg	   = <0x40000 0x10000>;
+				interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+			};
+		};
+
+		dcfg: dcfg@1ee0000 {
+			compatible = "fsl,ls1046a-dcfg", "syscon";
+			reg = <0x0 0x1ee0000 0x0 0x10000>;
+			big-endian;
+		};
+
+		clockgen: clocking@1ee1000 {
+			compatible = "fsl,ls1046a-clockgen";
+			reg = <0x0 0x1ee1000 0x0 0x1000>;
+			#clock-cells = <2>;
+			clocks = <&sysclk>;
+		};
+
+		dspi: dspi@2100000 {
+			compatible = "fsl,ls1021a-v1.0-dspi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x2100000 0x0 0x10000>;
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "dspi";
+			clocks = <&clockgen 4 1>;
+			spi-num-chipselects = <5>;
+			big-endian;
+			status = "disabled";
+		};
+
+		i2c0: i2c@2180000 {
+			compatible = "fsl,vf610-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x2180000 0x0 0x10000>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			dmas = <&edma0 1 39>,
+			       <&edma0 1 38>;
+			dma-names = "tx", "rx";
+			status = "disabled";
+		};
+
+		i2c1: i2c@2190000 {
+			compatible = "fsl,vf610-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x2190000 0x0 0x10000>;
+			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@21a0000 {
+			compatible = "fsl,vf610-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x21a0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@21b0000 {
+			compatible = "fsl,vf610-i2c";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x0 0x21b0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			status = "disabled";
+		};
+
+		duart0: serial@21c0500 {
+			compatible = "fsl,ns16550", "ns16550a";
+			reg = <0x00 0x21c0500 0x0 0x100>;
+			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+		};
+
+		duart1: serial@21c0600 {
+			compatible = "fsl,ns16550", "ns16550a";
+			reg = <0x00 0x21c0600 0x0 0x100>;
+			interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+		};
+
+		duart2: serial@21d0500 {
+			compatible = "fsl,ns16550", "ns16550a";
+			reg = <0x0 0x21d0500 0x0 0x100>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+		};
+
+		duart3: serial@21d0600 {
+			compatible = "fsl,ns16550", "ns16550a";
+			reg = <0x0 0x21d0600 0x0 0x100>;
+			interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+		};
+
+		gpio0: gpio@2300000 {
+			compatible = "fsl,qoriq-gpio";
+			reg = <0x0 0x2300000 0x0 0x10000>;
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio1: gpio@2310000 {
+			compatible = "fsl,qoriq-gpio";
+			reg = <0x0 0x2310000 0x0 0x10000>;
+			interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio2: gpio@2320000 {
+			compatible = "fsl,qoriq-gpio";
+			reg = <0x0 0x2320000 0x0 0x10000>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		gpio3: gpio@2330000 {
+			compatible = "fsl,qoriq-gpio";
+			reg = <0x0 0x2330000 0x0 0x10000>;
+			interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		lpuart0: serial@2950000 {
+			compatible = "fsl,ls1021a-lpuart";
+			reg = <0x0 0x2950000 0x0 0x1000>;
+			interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 0>;
+			clock-names = "ipg";
+			status = "disabled";
+		};
+
+		lpuart1: serial@2960000 {
+			compatible = "fsl,ls1021a-lpuart";
+			reg = <0x0 0x2960000 0x0 0x1000>;
+			interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			clock-names = "ipg";
+			status = "disabled";
+		};
+
+		lpuart2: serial@2970000 {
+			compatible = "fsl,ls1021a-lpuart";
+			reg = <0x0 0x2970000 0x0 0x1000>;
+			interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			clock-names = "ipg";
+			status = "disabled";
+		};
+
+		lpuart3: serial@2980000 {
+			compatible = "fsl,ls1021a-lpuart";
+			reg = <0x0 0x2980000 0x0 0x1000>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			clock-names = "ipg";
+			status = "disabled";
+		};
+
+		lpuart4: serial@2990000 {
+			compatible = "fsl,ls1021a-lpuart";
+			reg = <0x0 0x2990000 0x0 0x1000>;
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			clock-names = "ipg";
+			status = "disabled";
+		};
+
+		lpuart5: serial@29a0000 {
+			compatible = "fsl,ls1021a-lpuart";
+			reg = <0x0 0x29a0000 0x0 0x1000>;
+			interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			clock-names = "ipg";
+			status = "disabled";
+		};
+
+		wdog0: watchdog@2ad0000 {
+			compatible = "fsl,imx21-wdt";
+			reg = <0x0 0x2ad0000 0x0 0x10000>;
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+			big-endian;
+		};
+
+		edma0: edma@2c00000 {
+			#dma-cells = <2>;
+			compatible = "fsl,vf610-edma";
+			reg = <0x0 0x2c00000 0x0 0x10000>,
+			      <0x0 0x2c10000 0x0 0x10000>,
+			      <0x0 0x2c20000 0x0 0x10000>;
+			interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "edma-tx", "edma-err";
+			dma-channels = <32>;
+			big-endian;
+			clock-names = "dmamux0", "dmamux1";
+			clocks = <&clockgen 4 1>,
+				 <&clockgen 4 1>;
+		};
+
+		usb0: usb@2f00000 {
+			compatible = "snps,dwc3";
+			reg = <0x0 0x2f00000 0x0 0x10000>;
+			interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+			dr_mode = "host";
+			snps,quirk-frame-length-adjustment = <0x20>;
+		};
+
+		usb1: usb@3000000 {
+			compatible = "snps,dwc3";
+			reg = <0x0 0x3000000 0x0 0x10000>;
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+			dr_mode = "host";
+			snps,quirk-frame-length-adjustment = <0x20>;
+		};
+
+		usb2: usb@3100000 {
+			compatible = "snps,dwc3";
+			reg = <0x0 0x3100000 0x0 0x10000>;
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+			dr_mode = "host";
+			snps,quirk-frame-length-adjustment = <0x20>;
+		};
+
+		sata: sata@3200000 {
+			compatible = "fsl,ls1046a-ahci";
+			reg = <0x0 0x3200000 0x0 0x10000>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clockgen 4 1>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,212 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-1046A family SoC.
+ *
+ * Copyright 2016, Freescale Semiconductor, Inc.
+ *
+ * Shaohui Xie <Shaohui.Xie@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls1046a.dtsi"
+
+/ {
+	model = "LS1046A QDS Board";
+	compatible = "fsl,ls1046a-qds", "fsl,ls1046a";
+
+	aliases {
+		gpio0 = &gpio0;
+		gpio1 = &gpio1;
+		gpio2 = &gpio2;
+		gpio3 = &gpio3;
+		serial0 = &duart0;
+		serial1 = &duart1;
+		serial2 = &duart2;
+		serial3 = &duart3;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&dspi {
+	bus-num = <0>;
+	status = "okay";
+
+	flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "n25q128a11", "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+	};
+
+	flash@1 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "sst25wf040b", "jedec,spi-nor";
+		spi-cpol;
+		spi-cpha;
+		reg = <1>;
+		spi-max-frequency = <10000000>;
+	};
+
+	flash@2 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "en25s64", "jedec,spi-nor";
+		spi-cpol;
+		spi-cpha;
+		reg = <2>;
+		spi-max-frequency = <10000000>;
+	};
+};
+
+&duart0 {
+	status = "okay";
+};
+
+&duart1 {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	pca9547@77 {
+		compatible = "nxp,pca9547";
+		reg = <0x77>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x2>;
+
+			ina220@40 {
+				compatible = "ti,ina220";
+				reg = <0x40>;
+				shunt-resistor = <1000>;
+			};
+
+			ina220@41 {
+				compatible = "ti,ina220";
+				reg = <0x41>;
+				shunt-resistor = <1000>;
+			};
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x3>;
+
+			rtc@51 {
+				compatible = "nxp,pcf2129";
+				reg = <0x51>;
+				/* IRQ10_B */
+				interrupts = <0 150 0x4>;
+			};
+
+			eeprom@56 {
+				compatible = "atmel,24c512";
+				reg = <0x56>;
+			};
+
+			eeprom@57 {
+				compatible = "atmel,24c512";
+				reg = <0x57>;
+			};
+
+			temp-sensor@4c {
+				compatible = "adi,adt7461a";
+				reg = <0x4c>;
+			};
+		};
+	};
+};
+
+&ifc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	/* NOR, NAND Flashes and FPGA on board */
+	ranges = <0x0 0x0 0x0 0x60000000 0x08000000
+		  0x1 0x0 0x0 0x7e800000 0x00010000
+		  0x2 0x0 0x0 0x7fb00000 0x00000100>;
+	status = "okay";
+
+	nor@0,0 {
+		compatible = "cfi-flash";
+		reg = <0x0 0x0 0x8000000>;
+		bank-width = <2>;
+		device-width = <1>;
+	};
+
+	nand@1,0 {
+		compatible = "fsl,ifc-nand";
+		reg = <0x1 0x0 0x10000>;
+	};
+
+	fpga: board-control@2,0 {
+		compatible = "fsl,ls1046aqds-fpga", "fsl,fpga-qixis";
+		reg = <0x2 0x0 0x0000100>;
+	};
+};
+
+&lpuart0 {
+	status = "okay";
+};
+
+&qspi {
+	num-cs = <2>;
+	bus-num = <0>;
+	status = "okay";
+
+	qflash0: s25fl128s@0 {
+		compatible = "spansion,m25p80";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,150 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-1046A family SoC.
+ *
+ * Copyright 2016, Freescale Semiconductor, Inc.
+ *
+ * Mingkai Hu <mingkai.hu@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls1046a.dtsi"
+
+/ {
+	model = "LS1046A RDB Board";
+	compatible = "fsl,ls1046a-rdb", "fsl,ls1046a";
+
+	aliases {
+		serial0 = &duart0;
+		serial1 = &duart1;
+		serial2 = &duart2;
+		serial3 = &duart3;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&duart0 {
+	status = "okay";
+};
+
+&duart1 {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	ina220@40 {
+		compatible = "ti,ina220";
+		reg = <0x40>;
+		shunt-resistor = <1000>;
+	};
+
+	temp-sensor@4c {
+		compatible = "adi,adt7461";
+		reg = <0x4c>;
+	};
+
+	eeprom@56 {
+		compatible = "atmel,24c512";
+		reg = <0x52>;
+	};
+
+	eeprom@57 {
+		compatible = "atmel,24c512";
+		reg = <0x53>;
+	};
+};
+
+&i2c3 {
+	status = "okay";
+
+	rtc@51 {
+		compatible = "nxp,pcf2129";
+		reg = <0x51>;
+	};
+};
+
+&ifc {
+	#address-cells = <2>;
+	#size-cells = <1>;
+	/* NAND Flashe and CPLD on board */
+	ranges = <0x0 0x0 0x0 0x7e800000 0x00010000
+		  0x2 0x0 0x0 0x7fb00000 0x00000100>;
+	status = "okay";
+
+	nand@0,0 {
+		compatible = "fsl,ifc-nand";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0 0x0 0x10000>;
+	};
+
+	cpld: board-control@2,0 {
+		compatible = "fsl,ls1046ardb-cpld";
+		reg = <0x2 0x0 0x0000100>;
+	};
+};
+
+&qspi {
+	num-cs = <2>;
+	bus-num = <0>;
+	status = "okay";
+
+	qflash0: s25fs512s@0 {
+		compatible = "spansion,m25p80";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+		reg = <0>;
+	};
+
+	qflash1: s25fs512s@1 {
+		compatible = "spansion,m25p80";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		spi-max-frequency = <20000000>;
+		reg = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,8 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <dt-bindings/thermal/thermal.h>
+
 / {
 	compatible = "fsl,ls2080a";
 	interrupt-parent = <&gic>;
@@ -62,15 +64,16 @@
 		 */
 
 		/* We have 4 clusters having 2 Cortex-A57 cores each */
-		cpu@0 {
+		cpu0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x0>;
 			clocks = <&clockgen 1 0>;
 			next-level-cache = <&cluster0_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu@1 {
+		cpu1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x1>;
@@ -78,15 +81,16 @@
 			next-level-cache = <&cluster0_l2>;
 		};
 
-		cpu@100 {
+		cpu2: cpu@100 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x100>;
 			clocks = <&clockgen 1 1>;
 			next-level-cache = <&cluster1_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu@101 {
+		cpu3: cpu@101 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x101>;
@@ -94,15 +98,16 @@
 			next-level-cache = <&cluster1_l2>;
 		};
 
-		cpu@200 {
+		cpu4: cpu@200 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x200>;
 			clocks = <&clockgen 1 2>;
 			next-level-cache = <&cluster2_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu@201 {
+		cpu5: cpu@201 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x201>;
@@ -110,15 +115,16 @@
 			next-level-cache = <&cluster2_l2>;
 		};
 
-		cpu@300 {
+		cpu6: cpu@300 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x300>;
 			clocks = <&clockgen 1 3>;
 			next-level-cache = <&cluster3_l2>;
+			#cooling-cells = <2>;
 		};
 
-		cpu@301 {
+		cpu7: cpu@301 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a57";
 			reg = <0x301>;
@@ -216,6 +222,106 @@
 			clocks = <&sysclk>;
 		};
 
+		dcfg: dcfg@1e00000 {
+			compatible = "fsl,ls2080a-dcfg", "syscon";
+			reg = <0x0 0x1e00000 0x0 0x10000>;
+			little-endian;
+		};
+
+		tmu: tmu@1f80000 {
+			compatible = "fsl,qoriq-tmu";
+			reg = <0x0 0x1f80000 0x0 0x10000>;
+			interrupts = <0 23 0x4>;
+			fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+			fsl,tmu-calibration = <0x00000000 0x00000026
+					       0x00000001 0x0000002d
+					       0x00000002 0x00000032
+					       0x00000003 0x00000039
+					       0x00000004 0x0000003f
+					       0x00000005 0x00000046
+					       0x00000006 0x0000004d
+					       0x00000007 0x00000054
+					       0x00000008 0x0000005a
+					       0x00000009 0x00000061
+					       0x0000000a 0x0000006a
+					       0x0000000b 0x00000071
+
+					       0x00010000 0x00000025
+					       0x00010001 0x0000002c
+					       0x00010002 0x00000035
+					       0x00010003 0x0000003d
+					       0x00010004 0x00000045
+					       0x00010005 0x0000004e
+					       0x00010006 0x00000057
+					       0x00010007 0x00000061
+					       0x00010008 0x0000006b
+					       0x00010009 0x00000076
+
+					       0x00020000 0x00000029
+					       0x00020001 0x00000033
+					       0x00020002 0x0000003d
+					       0x00020003 0x00000049
+					       0x00020004 0x00000056
+					       0x00020005 0x00000061
+					       0x00020006 0x0000006d
+
+					       0x00030000 0x00000021
+					       0x00030001 0x0000002a
+					       0x00030002 0x0000003c
+					       0x00030003 0x0000004e>;
+			little-endian;
+			#thermal-sensor-cells = <1>;
+		};
+
+		thermal-zones {
+			cpu_thermal: cpu-thermal {
+				polling-delay-passive = <1000>;
+				polling-delay = <5000>;
+
+				thermal-sensors = <&tmu 4>;
+
+				trips {
+					cpu_alert: cpu-alert {
+						temperature = <75000>;
+						hysteresis = <2000>;
+						type = "passive";
+					};
+					cpu_crit: cpu-crit {
+						temperature = <85000>;
+						hysteresis = <2000>;
+						type = "critical";
+					};
+				};
+
+				cooling-maps {
+					map0 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu0 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+					map1 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu2 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+					map2 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu4 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+					map3 {
+						trip = <&cpu_alert>;
+						cooling-device =
+							<&cpu6 THERMAL_NO_LIMIT
+							THERMAL_NO_LIMIT>;
+					};
+				};
+			};
+		};
+
 		serial0: serial@21c0500 {
 			compatible = "fsl,ns16550", "ns16550a";
 			reg = <0x0 0x21c0500 0x0 0x100>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 
 /dts-v1/;
 
-/include/ "fsl-ls2080a.dtsi"
+#include "fsl-ls2080a.dtsi"
 
 / {
 	model = "Freescale Layerscape 2080a QDS Board";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 
 /dts-v1/;
 
-/include/ "fsl-ls2080a.dtsi"
+#include "fsl-ls2080a.dtsi"
 
 / {
 	model = "Freescale Layerscape 2080a RDB Board";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/fsl-ls2080a-simu.dts	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 
 /dts-v1/;
 
-/include/ "fsl-ls2080a.dtsi"
+#include "fsl-ls2080a.dtsi"
 
 / {
 	model = "Freescale Layerscape 2080a software Simulator model";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/freescale/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/freescale/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,7 @@
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-qds.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1046a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hi6220.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -364,6 +364,7 @@
 			reg = <0x0 0xf7010000  0x0 0x27c>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#pinctrl-cells = <1>;
 			#gpio-range-cells = <3>;
 			pinctrl-single,register-width = <32>;
 			pinctrl-single,function-mask = <7>;
@@ -402,6 +403,7 @@
 			reg = <0x0 0xf7010800 0x0 0x28c>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#pinctrl-cells = <1>;
 			pinctrl-single,register-width = <32>;
 		};
 
@@ -410,6 +412,7 @@
 			reg = <0x0 0xf8001800 0x0 0x78>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#pinctrl-cells = <1>;
 			pinctrl-single,register-width = <32>;
 		};
 
@@ -747,7 +750,6 @@
 			clocks = <&sys_ctrl HI6220_USBOTG_HCLK>;
 			clock-names = "otg";
 			dr_mode = "otg";
-			g-use-dma;
 			g-rx-fifo-size = <512>;
 			g-np-tx-fifo-size = <128>;
 			g-tx-fifo-size = <128 128 128 128 128 128>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip06-d03.dts	2017-02-12 16:03:20.000000000 -0500
@@ -41,18 +41,10 @@
 	status = "ok";
 };
 
-&sas0 {
-	status = "ok";
-};
-
 &sas1 {
 	status = "ok";
 };
 
-&sas2 {
-	status = "ok";
-};
-
 &usb_ohci {
 	status = "ok";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip06.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -318,11 +318,17 @@
 		#size-cells = <2>;
 		ranges;
 
+		refclk: refclk {
+			compatible = "fixed-clock";
+			clock-frequency = <50000000>;
+			#clock-cells = <0>;
+		};
+
 		usb_ohci: ohci@a7030000 {
 			compatible = "generic-ohci";
 			reg = <0x0 0xa7030000 0x0 0x10000>;
 			interrupt-parent = <&mbigen_usb>;
-			interrupts = <64 4>;
+			interrupts = <640 4>;
 			dma-coherent;
 			status = "disabled";
 		};
@@ -331,7 +337,7 @@
 			compatible = "generic-ehci";
 			reg = <0x0 0xa7020000 0x0 0x10000>;
 			interrupt-parent = <&mbigen_usb>;
-			interrupts = <65 4>;
+			interrupts = <641 4>;
 			dma-coherent;
 			status = "disabled";
 		};
@@ -508,7 +514,7 @@
 			};
 		};
 
-		eth0: ethernet@4{
+		eth0: ethernet-4{
 			compatible = "hisilicon,hns-nic-v2";
 			ae-handle = <&dsaf0>;
 			port-idx-in-ae = <4>;
@@ -517,7 +523,7 @@
 			dma-coherent;
 		};
 
-		eth1: ethernet@5{
+		eth1: ethernet-5{
 			compatible = "hisilicon,hns-nic-v2";
 			ae-handle = <&dsaf0>;
 			port-idx-in-ae = <5>;
@@ -526,7 +532,7 @@
 			dma-coherent;
 		};
 
-		eth2: ethernet@0{
+		eth2: ethernet-0{
 			compatible = "hisilicon,hns-nic-v2";
 			ae-handle = <&dsaf0>;
 			port-idx-in-ae = <0>;
@@ -535,7 +541,7 @@
 			dma-coherent;
 		};
 
-		eth3: ethernet@1{
+		eth3: ethernet-1{
 			compatible = "hisilicon,hns-nic-v2";
 			ae-handle = <&dsaf0>;
 			port-idx-in-ae = <1>;
@@ -552,6 +558,7 @@
 			ctrl-reset-reg = <0xa60>;
 			ctrl-reset-sts-reg = <0x5a30>;
 			ctrl-clock-ena-reg = <0x338>;
+			clocks = <&refclk 0>;
 			queue-count = <16>;
 			phy-count = <8>;
 			dma-coherent;
@@ -590,10 +597,11 @@
 			reg = <0 0xa2000000 0 0x10000>;
 			sas-addr = [50 01 88 20 16 00 00 00];
 			hisilicon,sas-syscon = <&pcie_subctl>;
-			am-max-trans;
+			hip06-sas-v2-quirk-amt;
 			ctrl-reset-reg = <0xa18>;
 			ctrl-reset-sts-reg = <0x5a0c>;
 			ctrl-clock-ena-reg = <0x318>;
+			clocks = <&refclk 0>;
 			queue-count = <16>;
 			phy-count = <8>;
 			dma-coherent;
@@ -635,6 +643,7 @@
 			ctrl-reset-reg = <0xae0>;
 			ctrl-reset-sts-reg = <0x5a70>;
 			ctrl-clock-ena-reg = <0x3a8>;
+			clocks = <&refclk 0>;
 			queue-count = <16>;
 			phy-count = <9>;
 			dma-coherent;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip07-d05.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip07-d05.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip07-d05.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip07-d05.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,66 @@
+/**
+ * dts file for Hisilicon D05 Development Board
+ *
+ * Copyright (C) 2016 Hisilicon 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
+ * publishhed by the Free Software Foundation.
+ *
+ */
+
+/dts-v1/;
+
+#include "hip07.dtsi"
+
+/ {
+	model = "Hisilicon Hip07 D05 Development Board";
+	compatible = "hisilicon,hip07-d05";
+
+	/* the mem node will be updated by UEFI. */
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x00000000 0x0 0x40000000>;
+		numa-node-id = <0>;
+	};
+
+	distance-map {
+		compatible = "numa-distance-map-v1";
+		distance-matrix = <0 0 10>,
+				  <0 1 15>,
+				  <0 2 20>,
+				  <0 3 25>,
+				  <1 0 15>,
+				  <1 1 10>,
+				  <1 2 25>,
+				  <1 3 30>,
+				  <2 0 20>,
+				  <2 1 25>,
+				  <2 2 10>,
+				  <2 3 15>,
+				  <3 0 25>,
+				  <3 1 30>,
+				  <3 2 15>,
+				  <3 3 10>;
+	};
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&uart0 {
+	status = "ok";
+};
+
+&usb_ohci {
+	status = "ok";
+};
+
+&usb_ehci {
+	status = "ok";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip07.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip07.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/hip07.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/hip07.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1059 @@
+/**
+ * dts file for Hisilicon D05 Development Board
+ *
+ * Copyright (C) 2016 Hisilicon 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
+ * publishhed by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "hisilicon,hip07-d05";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+				core1 {
+					cpu = <&cpu1>;
+				};
+				core2 {
+					cpu = <&cpu2>;
+				};
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&cpu4>;
+				};
+				core1 {
+					cpu = <&cpu5>;
+				};
+				core2 {
+					cpu = <&cpu6>;
+				};
+				core3 {
+					cpu = <&cpu7>;
+				};
+			};
+
+			cluster2 {
+				core0 {
+					cpu = <&cpu8>;
+				};
+				core1 {
+					cpu = <&cpu9>;
+				};
+				core2 {
+					cpu = <&cpu10>;
+				};
+				core3 {
+					cpu = <&cpu11>;
+				};
+			};
+
+			cluster3 {
+				core0 {
+					cpu = <&cpu12>;
+				};
+				core1 {
+					cpu = <&cpu13>;
+				};
+				core2 {
+					cpu = <&cpu14>;
+				};
+				core3 {
+					cpu = <&cpu15>;
+				};
+			};
+
+			cluster4 {
+				core0 {
+					cpu = <&cpu16>;
+				};
+				core1 {
+					cpu = <&cpu17>;
+				};
+				core2 {
+					cpu = <&cpu18>;
+				};
+				core3 {
+					cpu = <&cpu19>;
+				};
+			};
+
+			cluster5 {
+				core0 {
+					cpu = <&cpu20>;
+				};
+				core1 {
+					cpu = <&cpu21>;
+				};
+				core2 {
+					cpu = <&cpu22>;
+				};
+				core3 {
+					cpu = <&cpu23>;
+				};
+			};
+
+			cluster6 {
+				core0 {
+					cpu = <&cpu24>;
+				};
+				core1 {
+					cpu = <&cpu25>;
+				};
+				core2 {
+					cpu = <&cpu26>;
+				};
+				core3 {
+					cpu = <&cpu27>;
+				};
+			};
+
+			cluster7 {
+				core0 {
+					cpu = <&cpu28>;
+				};
+				core1 {
+					cpu = <&cpu29>;
+				};
+				core2 {
+					cpu = <&cpu30>;
+				};
+				core3 {
+					cpu = <&cpu31>;
+				};
+			};
+
+			cluster8 {
+				core0 {
+					cpu = <&cpu32>;
+				};
+				core1 {
+					cpu = <&cpu33>;
+				};
+				core2 {
+					cpu = <&cpu34>;
+				};
+				core3 {
+					cpu = <&cpu35>;
+				};
+			};
+
+			cluster9 {
+				core0 {
+					cpu = <&cpu36>;
+				};
+				core1 {
+					cpu = <&cpu37>;
+				};
+				core2 {
+					cpu = <&cpu38>;
+				};
+				core3 {
+					cpu = <&cpu39>;
+				};
+			};
+
+			cluster10 {
+				core0 {
+					cpu = <&cpu40>;
+				};
+				core1 {
+					cpu = <&cpu41>;
+				};
+				core2 {
+					cpu = <&cpu42>;
+				};
+				core3 {
+					cpu = <&cpu43>;
+				};
+			};
+
+			cluster11 {
+				core0 {
+					cpu = <&cpu44>;
+				};
+				core1 {
+					cpu = <&cpu45>;
+				};
+				core2 {
+					cpu = <&cpu46>;
+				};
+				core3 {
+					cpu = <&cpu47>;
+				};
+			};
+
+			cluster12 {
+				core0 {
+					cpu = <&cpu48>;
+				};
+				core1 {
+					cpu = <&cpu49>;
+				};
+				core2 {
+					cpu = <&cpu50>;
+				};
+				core3 {
+					cpu = <&cpu51>;
+				};
+			};
+
+			cluster13 {
+				core0 {
+					cpu = <&cpu52>;
+				};
+				core1 {
+					cpu = <&cpu53>;
+				};
+				core2 {
+					cpu = <&cpu54>;
+				};
+				core3 {
+					cpu = <&cpu55>;
+				};
+			};
+
+			cluster14 {
+				core0 {
+					cpu = <&cpu56>;
+				};
+				core1 {
+					cpu = <&cpu57>;
+				};
+				core2 {
+					cpu = <&cpu58>;
+				};
+				core3 {
+					cpu = <&cpu59>;
+				};
+			};
+
+			cluster15 {
+				core0 {
+					cpu = <&cpu60>;
+				};
+				core1 {
+					cpu = <&cpu61>;
+				};
+				core2 {
+					cpu = <&cpu62>;
+				};
+				core3 {
+					cpu = <&cpu63>;
+				};
+			};
+		};
+
+		cpu0: cpu@10000 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10000>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu1: cpu@10001 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10001>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu2: cpu@10002 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10002>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu3: cpu@10003 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10003>;
+			enable-method = "psci";
+			next-level-cache = <&cluster0_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu4: cpu@10100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10100>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu5: cpu@10101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10101>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu6: cpu@10102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10102>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu7: cpu@10103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10103>;
+			enable-method = "psci";
+			next-level-cache = <&cluster1_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu8: cpu@10200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10200>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu9: cpu@10201 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10201>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu10: cpu@10202 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10202>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu11: cpu@10203 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10203>;
+			enable-method = "psci";
+			next-level-cache = <&cluster2_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu12: cpu@10300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10300>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu13: cpu@10301 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10301>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu14: cpu@10302 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10302>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu15: cpu@10303 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x10303>;
+			enable-method = "psci";
+			next-level-cache = <&cluster3_l2>;
+			numa-node-id = <0>;
+		};
+
+		cpu16: cpu@30000 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30000>;
+			enable-method = "psci";
+			next-level-cache = <&cluster4_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu17: cpu@30001 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30001>;
+			enable-method = "psci";
+			next-level-cache = <&cluster4_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu18: cpu@30002 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30002>;
+			enable-method = "psci";
+			next-level-cache = <&cluster4_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu19: cpu@30003 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30003>;
+			enable-method = "psci";
+			next-level-cache = <&cluster4_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu20: cpu@30100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30100>;
+			enable-method = "psci";
+			next-level-cache = <&cluster5_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu21: cpu@30101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30101>;
+			enable-method = "psci";
+			next-level-cache = <&cluster5_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu22: cpu@30102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30102>;
+			enable-method = "psci";
+			next-level-cache = <&cluster5_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu23: cpu@30103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30103>;
+			enable-method = "psci";
+			next-level-cache = <&cluster5_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu24: cpu@30200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30200>;
+			enable-method = "psci";
+			next-level-cache = <&cluster6_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu25: cpu@30201 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30201>;
+			enable-method = "psci";
+			next-level-cache = <&cluster6_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu26: cpu@30202 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30202>;
+			enable-method = "psci";
+			next-level-cache = <&cluster6_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu27: cpu@30203 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30203>;
+			enable-method = "psci";
+			next-level-cache = <&cluster6_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu28: cpu@30300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30300>;
+			enable-method = "psci";
+			next-level-cache = <&cluster7_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu29: cpu@30301 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30301>;
+			enable-method = "psci";
+			next-level-cache = <&cluster7_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu30: cpu@30302 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30302>;
+			enable-method = "psci";
+			next-level-cache = <&cluster7_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu31: cpu@30303 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x30303>;
+			enable-method = "psci";
+			next-level-cache = <&cluster7_l2>;
+			numa-node-id = <1>;
+		};
+
+		cpu32: cpu@50000 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50000>;
+			enable-method = "psci";
+			next-level-cache = <&cluster8_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu33: cpu@50001 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50001>;
+			enable-method = "psci";
+			next-level-cache = <&cluster8_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu34: cpu@50002 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50002>;
+			enable-method = "psci";
+			next-level-cache = <&cluster8_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu35: cpu@50003 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50003>;
+			enable-method = "psci";
+			next-level-cache = <&cluster8_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu36: cpu@50100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50100>;
+			enable-method = "psci";
+			next-level-cache = <&cluster9_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu37: cpu@50101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50101>;
+			enable-method = "psci";
+			next-level-cache = <&cluster9_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu38: cpu@50102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50102>;
+			enable-method = "psci";
+			next-level-cache = <&cluster9_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu39: cpu@50103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50103>;
+			enable-method = "psci";
+			next-level-cache = <&cluster9_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu40: cpu@50200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50200>;
+			enable-method = "psci";
+			next-level-cache = <&cluster10_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu41: cpu@50201 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50201>;
+			enable-method = "psci";
+			next-level-cache = <&cluster10_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu42: cpu@50202 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50202>;
+			enable-method = "psci";
+			next-level-cache = <&cluster10_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu43: cpu@50203 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50203>;
+			enable-method = "psci";
+			next-level-cache = <&cluster10_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu44: cpu@50300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50300>;
+			enable-method = "psci";
+			next-level-cache = <&cluster11_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu45: cpu@50301 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50301>;
+			enable-method = "psci";
+			next-level-cache = <&cluster11_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu46: cpu@50302 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50302>;
+			enable-method = "psci";
+			next-level-cache = <&cluster11_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu47: cpu@50303 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x50303>;
+			enable-method = "psci";
+			next-level-cache = <&cluster11_l2>;
+			numa-node-id = <2>;
+		};
+
+		cpu48: cpu@70000 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70000>;
+			enable-method = "psci";
+			next-level-cache = <&cluster12_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu49: cpu@70001 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70001>;
+			enable-method = "psci";
+			next-level-cache = <&cluster12_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu50: cpu@70002 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70002>;
+			enable-method = "psci";
+			next-level-cache = <&cluster12_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu51: cpu@70003 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70003>;
+			enable-method = "psci";
+			next-level-cache = <&cluster12_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu52: cpu@70100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70100>;
+			enable-method = "psci";
+			next-level-cache = <&cluster13_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu53: cpu@70101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70101>;
+			enable-method = "psci";
+			next-level-cache = <&cluster13_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu54: cpu@70102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70102>;
+			enable-method = "psci";
+			next-level-cache = <&cluster13_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu55: cpu@70103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70103>;
+			enable-method = "psci";
+			next-level-cache = <&cluster13_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu56: cpu@70200 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70200>;
+			enable-method = "psci";
+			next-level-cache = <&cluster14_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu57: cpu@70201 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70201>;
+			enable-method = "psci";
+			next-level-cache = <&cluster14_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu58: cpu@70202 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70202>;
+			enable-method = "psci";
+			next-level-cache = <&cluster14_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu59: cpu@70203 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70203>;
+			enable-method = "psci";
+			next-level-cache = <&cluster14_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu60: cpu@70300 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70300>;
+			enable-method = "psci";
+			next-level-cache = <&cluster15_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu61: cpu@70301 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70301>;
+			enable-method = "psci";
+			next-level-cache = <&cluster15_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu62: cpu@70302 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70302>;
+			enable-method = "psci";
+			next-level-cache = <&cluster15_l2>;
+			numa-node-id = <3>;
+		};
+
+		cpu63: cpu@70303 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a72", "arm,armv8";
+			reg = <0x70303>;
+			enable-method = "psci";
+			next-level-cache = <&cluster15_l2>;
+			numa-node-id = <3>;
+		};
+
+		cluster0_l2: l2-cache0 {
+			compatible = "cache";
+		};
+
+		cluster1_l2: l2-cache1 {
+			compatible = "cache";
+		};
+
+		cluster2_l2: l2-cache2 {
+			compatible = "cache";
+		};
+
+		cluster3_l2: l2-cache3 {
+			compatible = "cache";
+		};
+
+		cluster4_l2: l2-cache4 {
+			compatible = "cache";
+		};
+
+		cluster5_l2: l2-cache5 {
+			compatible = "cache";
+		};
+
+		cluster6_l2: l2-cache6 {
+			compatible = "cache";
+		};
+
+		cluster7_l2: l2-cache7 {
+			compatible = "cache";
+		};
+
+		cluster8_l2: l2-cache8 {
+			compatible = "cache";
+		};
+
+		cluster9_l2: l2-cache9 {
+			compatible = "cache";
+		};
+
+		cluster10_l2: l2-cache10 {
+			compatible = "cache";
+		};
+
+		cluster11_l2: l2-cache11 {
+			compatible = "cache";
+		};
+
+		cluster12_l2: l2-cache12 {
+			compatible = "cache";
+		};
+
+		cluster13_l2: l2-cache13 {
+			compatible = "cache";
+		};
+
+		cluster14_l2: l2-cache14 {
+			compatible = "cache";
+		};
+
+		cluster15_l2: l2-cache15 {
+			compatible = "cache";
+		};
+	};
+
+	gic: interrupt-controller@4d000000 {
+		compatible = "arm,gic-v3";
+		#interrupt-cells = <3>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		interrupt-controller;
+		#redistributor-regions = <4>;
+		redistributor-stride = <0x0 0x40000>;
+		reg = <0x0 0x4d000000 0x0 0x10000>,	/* GICD */
+		      <0x0 0x4d100000 0x0 0x400000>,	/* p0 GICR node 0 */
+		      <0x0 0x6d100000 0x0 0x400000>,	/* p0 GICR node 1 */
+		      <0x400 0x4d100000 0x0 0x400000>,	/* p1 GICR node 2 */
+		      <0x400 0x6d100000 0x0 0x400000>,	/* p1 GICR node 3 */
+		      <0x0 0xfe000000 0x0 0x10000>,	/* GICC */
+		      <0x0 0xfe010000 0x0 0x10000>,	/* GICH */
+		      <0x0 0xfe020000 0x0 0x10000>;	/* GICV */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+		p0_its_peri_a: interrupt-controller@4c000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x0 0x4c000000 0x0 0x40000>;
+		};
+
+		p0_its_peri_b: interrupt-controller@6c000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x0 0x6c000000 0x0 0x40000>;
+		};
+
+		p0_its_dsa_a: interrupt-controller@c6000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x0 0xc6000000 0x0 0x40000>;
+		};
+
+		p0_its_dsa_b: interrupt-controller@8,c6000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x8 0xc6000000 0x0 0x40000>;
+		};
+
+		p1_its_peri_a: interrupt-controller@400,4c000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x400 0x4c000000 0x0 0x40000>;
+		};
+
+		p1_its_peri_b: interrupt-controller@400,6c000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x400 0x6c000000 0x0 0x40000>;
+		};
+
+		p1_its_dsa_a: interrupt-controller@400,c6000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x400 0xc6000000 0x0 0x40000>;
+		};
+
+		p1_its_dsa_b: interrupt-controller@408,c6000000 {
+			compatible = "arm,gic-v3-its";
+			msi-controller;
+			#msi-cells = <1>;
+			reg = <0x408 0xc6000000 0x0 0x40000>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+	};
+
+	pmu {
+		compatible = "arm,cortex-a72-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	p0_mbigen_peri_b: interrupt-controller@60080000 {
+		compatible = "hisilicon,mbigen-v2";
+		reg = <0x0 0x60080000 0x0 0x10000>;
+
+		mbigen_uart: uart_intc {
+			msi-parent = <&p0_its_peri_b 0x120c7>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			num-pins = <1>;
+		};
+	};
+
+	p0_mbigen_pcie_a: interrupt-controller@a0080000 {
+		compatible = "hisilicon,mbigen-v2";
+		reg = <0x0 0xa0080000 0x0 0x10000>;
+
+		mbigen_usb: intc_usb {
+			msi-parent = <&p0_its_dsa_a 0x40080>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			num-pins = <2>;
+		};
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		uart0: uart@602b0000 {
+			compatible = "arm,sbsa-uart";
+			reg = <0x0 0x602b0000 0x0 0x1000>;
+			interrupt-parent = <&mbigen_uart>;
+			interrupts = <807 4>;
+			current-speed = <115200>;
+			reg-io-width = <4>;
+			status = "disabled";
+		};
+
+		usb_ohci: ohci@a7030000 {
+			compatible = "generic-ohci";
+			reg = <0x0 0xa7030000 0x0 0x10000>;
+			interrupt-parent = <&mbigen_usb>;
+			interrupts = <640 4>;
+			dma-coherent;
+			status = "disabled";
+		};
+
+		usb_ehci: ehci@a7020000 {
+			compatible = "generic-ehci";
+			reg = <0x0 0xa7020000 0x0 0x10000>;
+			interrupt-parent = <&mbigen_usb>;
+			interrupts = <641 4>;
+			dma-coherent;
+			status = "disabled";
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/hisilicon/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/hisilicon/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,7 @@
 dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
 dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb
 dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb
+dtb-$(CONFIG_ARCH_HISI) += hip07-d05.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,5 @@
 dts-dirs += al
+dts-dirs += allwinner
 dts-dirs += altera
 dts-dirs += amd
 dts-dirs += amlogic
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-3720-db.dts	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
 	};
@@ -81,3 +81,26 @@
 &pcie0 {
 	status = "okay";
 };
+
+&mdio {
+	status = "okay";
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+	};
+
+	phy1: ethernet-phy@1 {
+		reg = <1>;
+	};
+};
+
+&eth0 {
+	phy-mode = "rgmii-id";
+	phy = <&phy0>;
+	status = "okay";
+};
+
+&eth1 {
+	phy-mode = "sgmii";
+	phy = <&phy1>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,82 @@
+/*
+ * Device Tree file for Globalscale Marvell ESPRESSOBin Board
+ * Copyright (C) 2016 Marvell
+ *
+ * Romain Perier <romain.perier@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) 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 , 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.
+ */
+
+/dts-v1/;
+
+#include "armada-372x.dtsi"
+
+/ {
+	model = "Globalscale Marvell ESPRESSOBin Board";
+	compatible = "globalscale,espressobin", "marvell,armada3720", "marvell,armada3710";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+	};
+};
+
+/* J9 */
+&pcie0 {
+	status = "okay";
+};
+
+/* J6 */
+&sata {
+	status = "okay";
+};
+
+/* Exported on the micro USB connector J5 through an FTDI */
+&uart0 {
+	status = "okay";
+};
+
+/* J7 */
+&usb3 {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-37xx.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -91,7 +91,7 @@
 		#size-cells = <2>;
 		ranges;
 
-		internal-regs {
+		internal-regs@d0000000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "simple-bus";
@@ -140,6 +140,29 @@
 				};
 			};
 
+			eth0: ethernet@30000 {
+				   compatible = "marvell,armada-3700-neta";
+				   reg = <0x30000 0x4000>;
+				   interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+				   clocks = <&sb_periph_clk 8>;
+				   status = "disabled";
+			};
+
+			mdio: mdio@32004 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "marvell,orion-mdio";
+				reg = <0x32004 0x4>;
+			};
+
+			eth1: ethernet@40000 {
+				compatible = "marvell,armada-3700-neta";
+				reg = <0x40000 0x4000>;
+				interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&sb_periph_clk 7>;
+				status = "disabled";
+			};
+
 			usb3: usb@58000 {
 				compatible = "marvell,armada3700-xhci",
 				"generic-xhci";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-ap806.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,7 @@
 		interrupt-parent = <&gic>;
 		ranges;
 
-		config-space {
+		config-space@f0000000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "simple-bus";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@
 		interrupt-parent = <&gic>;
 		ranges;
 
-		config-space {
+		config-space@f2000000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "simple-bus";
@@ -164,6 +164,14 @@
 				clocks = <&cpm_syscon0 1 21>;
 				status = "disabled";
 			};
+
+			cpm_trng: trng@760000 {
+				compatible = "marvell,armada-8k-rng", "inside-secure,safexcel-eip76";
+				reg = <0x760000 0x7d>;
+				interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cpm_syscon0 1 25>;
+				status = "okay";
+			};
 		};
 
 		cpm_pcie0: pcie@f2600000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@
 		interrupt-parent = <&gic>;
 		ranges;
 
-		config-space {
+		config-space@f4000000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "simple-bus";
@@ -164,6 +164,14 @@
 				clocks = <&cps_syscon0 1 21>;
 				status = "disabled";
 			};
+
+			cps_trng: trng@760000 {
+				compatible = "marvell,armada-8k-rng", "inside-secure,safexcel-eip76";
+				reg = <0x760000 0x7d>;
+				interrupts = <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&cps_syscon0 1 25>;
+				status = "okay";
+			};
 		};
 
 		cps_pcie0: pcie@f4600000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@1000000 {
 		device_type = "memory";
 		/* the first 16MB is for firmwares' usage */
 		reg = <0 0x01000000 0 0x7f000000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/berlin4ct.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/berlin4ct.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/berlin4ct.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/berlin4ct.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -142,7 +142,7 @@
 			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
 	};
 
-	soc {
+	soc@f7000000 {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@1000000 {
 		device_type = "memory";
 		/* the first 16MB is for firmwares' usage */
 		reg = <0 0x01000000 0 0x7f000000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/marvell/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/marvell/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -4,6 +4,7 @@ dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-s
 
 # Mvebu SoC Family
 dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-db.dtb
+dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-espressobin.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-7040-db.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-8040-db.dtb
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/mediatek/mt8173.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,14 @@
 		dpi0 = &dpi0;
 		dsi0 = &dsi0;
 		dsi1 = &dsi1;
+		mdp_rdma0 = &mdp_rdma0;
+		mdp_rdma1 = &mdp_rdma1;
+		mdp_rsz0 = &mdp_rsz0;
+		mdp_rsz1 = &mdp_rsz1;
+		mdp_rsz2 = &mdp_rsz2;
+		mdp_wdma0 = &mdp_wdma0;
+		mdp_wrot0 = &mdp_wrot0;
+		mdp_wrot1 = &mdp_wrot1;
 	};
 
 	cpus {
@@ -450,6 +458,9 @@
 		auxadc: auxadc@11001000 {
 			compatible = "mediatek,mt8173-auxadc";
 			reg = <0 0x11001000 0 0x1000>;
+			clocks = <&pericfg CLK_PERI_AUXADC>;
+			clock-names = "main";
+			#io-channel-cells = <1>;
 		};
 
 		uart0: serial@11002000 {
@@ -707,11 +718,14 @@
 			status = "disabled";
 		};
 
-		usb30: usb@11270000 {
-			compatible = "mediatek,mt8173-xhci";
-			reg = <0 0x11270000 0 0x1000>,
+		ssusb: usb@11271000 {
+			compatible = "mediatek,mt8173-mtu3";
+			reg = <0 0x11271000 0 0x3000>,
 			      <0 0x11280700 0 0x0100>;
-			interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+			reg-names = "mac", "ippc";
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
+			phys = <&phy_port0 PHY_TYPE_USB3>,
+			       <&phy_port1 PHY_TYPE_USB2>;
 			power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
 			clocks = <&topckgen CLK_TOP_USB30_SEL>,
 				 <&pericfg CLK_PERI_USB0>,
@@ -719,10 +733,22 @@
 			clock-names = "sys_ck",
 				      "wakeup_deb_p0",
 				      "wakeup_deb_p1";
-			phys = <&phy_port0 PHY_TYPE_USB3>,
-			       <&phy_port1 PHY_TYPE_USB2>;
 			mediatek,syscon-wakeup = <&pericfg>;
-			status = "okay";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			status = "disabled";
+
+			usb_host: xhci@11270000 {
+				compatible = "mediatek,mt8173-xhci";
+				reg = <0 0x11270000 0 0x1000>;
+				reg-names = "mac";
+				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+				clocks = <&topckgen CLK_TOP_USB30_SEL>;
+				clock-names = "sys_ck";
+				status = "disabled";
+			};
 		};
 
 		u3phy: usb-phy@11290000 {
@@ -755,6 +781,82 @@
 			#clock-cells = <1>;
 		};
 
+		mdp {
+			compatible = "mediatek,mt8173-mdp";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			mediatek,vpu = <&vpu>;
+
+			mdp_rdma0: rdma@14001000 {
+				compatible = "mediatek,mt8173-mdp-rdma";
+				reg = <0 0x14001000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_RDMA0>,
+					 <&mmsys CLK_MM_MUTEX_32K>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+				iommus = <&iommu M4U_PORT_MDP_RDMA0>;
+				mediatek,larb = <&larb0>;
+			};
+
+			mdp_rdma1: rdma@14002000 {
+				compatible = "mediatek,mt8173-mdp-rdma";
+				reg = <0 0x14002000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_RDMA1>,
+					 <&mmsys CLK_MM_MUTEX_32K>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+				iommus = <&iommu M4U_PORT_MDP_RDMA1>;
+				mediatek,larb = <&larb4>;
+			};
+
+			mdp_rsz0: rsz@14003000 {
+				compatible = "mediatek,mt8173-mdp-rsz";
+				reg = <0 0x14003000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_RSZ0>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+			};
+
+			mdp_rsz1: rsz@14004000 {
+				compatible = "mediatek,mt8173-mdp-rsz";
+				reg = <0 0x14004000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_RSZ1>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+			};
+
+			mdp_rsz2: rsz@14005000 {
+				compatible = "mediatek,mt8173-mdp-rsz";
+				reg = <0 0x14005000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_RSZ2>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+			};
+
+			mdp_wdma0: wdma@14006000 {
+				compatible = "mediatek,mt8173-mdp-wdma";
+				reg = <0 0x14006000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_WDMA>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+				iommus = <&iommu M4U_PORT_MDP_WDMA>;
+				mediatek,larb = <&larb0>;
+			};
+
+			mdp_wrot0: wrot@14007000 {
+				compatible = "mediatek,mt8173-mdp-wrot";
+				reg = <0 0x14007000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_WROT0>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+				iommus = <&iommu M4U_PORT_MDP_WROT0>;
+				mediatek,larb = <&larb0>;
+			};
+
+			mdp_wrot1: wrot@14008000 {
+				compatible = "mediatek,mt8173-mdp-wrot";
+				reg = <0 0x14008000 0 0x1000>;
+				clocks = <&mmsys CLK_MM_MDP_WROT1>;
+				power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+				iommus = <&iommu M4U_PORT_MDP_WROT1>;
+				mediatek,larb = <&larb4>;
+			};
+		};
+
 		ovl0: ovl@1400c000 {
 			compatible = "mediatek,mt8173-disp-ovl";
 			reg = <0 0x1400c000 0 0x1000>;
@@ -1051,6 +1153,50 @@
 			#clock-cells = <1>;
 		};
 
+		vcodec_dec: vcodec@16000000 {
+			compatible = "mediatek,mt8173-vcodec-dec";
+			reg = <0 0x16000000 0 0x100>,	/* VDEC_SYS */
+			      <0 0x16020000 0 0x1000>,	/* VDEC_MISC */
+			      <0 0x16021000 0 0x800>,	/* VDEC_LD */
+			      <0 0x16021800 0 0x800>,	/* VDEC_TOP */
+			      <0 0x16022000 0 0x1000>,	/* VDEC_CM */
+			      <0 0x16023000 0 0x1000>,	/* VDEC_AD */
+			      <0 0x16024000 0 0x1000>,	/* VDEC_AV */
+			      <0 0x16025000 0 0x1000>,	/* VDEC_PP */
+			      <0 0x16026800 0 0x800>,	/* VDEC_HWD */
+			      <0 0x16027000 0 0x800>,	/* VDEC_HWQ */
+			      <0 0x16027800 0 0x800>,	/* VDEC_HWB */
+			      <0 0x16028400 0 0x400>;	/* VDEC_HWG */
+			interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_LOW>;
+			mediatek,larb = <&larb1>;
+			iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_UFO_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+				 <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
+			mediatek,vpu = <&vpu>;
+			power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
+			clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
+				 <&topckgen CLK_TOP_UNIVPLL_D2>,
+				 <&topckgen CLK_TOP_CCI400_SEL>,
+				 <&topckgen CLK_TOP_VDEC_SEL>,
+				 <&topckgen CLK_TOP_VCODECPLL>,
+				 <&apmixedsys CLK_APMIXED_VENCPLL>,
+				 <&topckgen CLK_TOP_VENC_LT_SEL>,
+				 <&topckgen CLK_TOP_VCODECPLL_370P5>;
+			clock-names = "vcodecpll",
+				      "univpll_d2",
+				      "clk_cci400_sel",
+				      "vdec_sel",
+				      "vdecpll",
+				      "vencpll",
+				      "venc_lt_sel",
+				      "vdec_bus_clk_src";
+		};
+
 		larb1: larb@16010000 {
 			compatible = "mediatek,mt8173-smi-larb";
 			reg = <0 0x16010000 0 0x1000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/mediatek/mt8173-evb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/mediatek/mt8173-evb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/mediatek/mt8173-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -34,15 +34,6 @@
 
 	chosen { };
 
-	usb_p1_vbus: regulator@0 {
-		compatible = "regulator-fixed";
-		regulator-name = "usb_vbus";
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
-		gpio = <&pio 130 GPIO_ACTIVE_HIGH>;
-		enable-active-high;
-	};
-
 	connector {
 		compatible = "hdmi-connector";
 		label = "hdmi";
@@ -54,6 +45,29 @@
 			};
 		};
 	};
+
+	extcon_usb: extcon_iddig {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&pio 16 GPIO_ACTIVE_HIGH>;
+	};
+
+	usb_p1_vbus: regulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "usb_vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 130 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	usb_p0_vbus: regulator@1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vbus";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		gpio = <&pio 9 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
 };
 
 &cec {
@@ -243,6 +257,20 @@
 			bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
 		};
 	};
+
+	usb_id_pins_float: usb_iddig_pull_up {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-up;
+		};
+	};
+
+	usb_id_pins_ground: usb_iddig_pull_down {
+		pins_iddig {
+			pinmux = <MT8173_PIN_16_IDDIG__FUNC_IDDIG>;
+			bias-pull-down;
+		};
+	};
 };
 
 &pwm0 {
@@ -469,12 +497,25 @@
 	status = "okay";
 };
 
+&ssusb {
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p0_vbus>;
+	extcon = <&extcon_usb>;
+	dr_mode = "otg";
+	mediatek,enable-wakeup;
+	pinctrl-names = "default", "id_float", "id_ground";
+	pinctrl-0 = <&usb_id_pins_float>;
+	pinctrl-1 = <&usb_id_pins_float>;
+	pinctrl-2 = <&usb_id_pins_ground>;
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
 };
 
-&usb30 {
+&usb_host {
 	vusb33-supply = <&mt6397_vusb_reg>;
 	vbus-supply = <&usb_p1_vbus>;
-	mediatek,wakeup-src = <1>;
+	status = "okay";
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegr
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2371-2180.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-p2571.dtb
 dtb-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210-smaug.dtb
+dtb-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186-p2771-0000.dtb
 
 always		:= $(dtb-y)
 clean-files	:= *.dtb
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra186.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra186.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra186.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra186.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,398 @@
+#include <dt-bindings/gpio/tegra186-gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	compatible = "nvidia,tegra186";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	gpio: gpio@2200000 {
+		compatible = "nvidia,tegra186-gpio";
+		reg-names = "security", "gpio";
+		reg = <0x0 0x2200000 0x0 0x10000>,
+		      <0x0 0x2210000 0x0 0x10000>;
+		interrupts = <GIC_SPI  47 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  50 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  53 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  56 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI  59 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+		#gpio-cells = <2>;
+		gpio-controller;
+	};
+
+	uarta: serial@3100000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03100000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 55>;
+		clock-names = "serial";
+		resets = <&bpmp 47>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartb: serial@3110000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03110000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 56>;
+		clock-names = "serial";
+		resets = <&bpmp 48>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartd: serial@3130000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03130000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 77>;
+		clock-names = "serial";
+		resets = <&bpmp 50>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uarte: serial@3140000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03140000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 194>;
+		clock-names = "serial";
+		resets = <&bpmp 132>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartf: serial@3150000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x03150000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 195>;
+		clock-names = "serial";
+		resets = <&bpmp 111>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	gen1_i2c: i2c@3160000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x03160000 0x0 0x10000>;
+		interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 47>;
+		clock-names = "div-clk";
+		resets = <&bpmp 19>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	cam_i2c: i2c@3180000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x03180000 0x0 0x10000>;
+		interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 75>;
+		clock-names = "div-clk";
+		resets = <&bpmp 21>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	/* shares pads with dpaux1 */
+	dp_aux_ch1_i2c: i2c@3190000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x03190000 0x0 0x10000>;
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 86>;
+		clock-names = "div-clk";
+		resets = <&bpmp 22>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	/* controlled by BPMP, should not be enabled */
+	pwr_i2c: i2c@31a0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031a0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 48>;
+		clock-names = "div-clk";
+		resets = <&bpmp 23>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	/* shares pads with dpaux0 */
+	dp_aux_ch0_i2c: i2c@31b0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031b0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 125>;
+		clock-names = "div-clk";
+		resets = <&bpmp 24>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen7_i2c: i2c@31c0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031c0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 182>;
+		clock-names = "div-clk";
+		resets = <&bpmp 81>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen9_i2c: i2c@31e0000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x031e0000 0x0 0x10000>;
+		interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 183>;
+		clock-names = "div-clk";
+		resets = <&bpmp 83>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	sdmmc1: sdhci@3400000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03400000 0x0 0x10000>;
+		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 52>;
+		clock-names = "sdhci";
+		resets = <&bpmp 33>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
+	sdmmc2: sdhci@3420000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03420000 0x0 0x10000>;
+		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 53>;
+		clock-names = "sdhci";
+		resets = <&bpmp 34>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
+	sdmmc3: sdhci@3440000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03440000 0x0 0x10000>;
+		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 76>;
+		clock-names = "sdhci";
+		resets = <&bpmp 35>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
+	sdmmc4: sdhci@3460000 {
+		compatible = "nvidia,tegra186-sdhci";
+		reg = <0x0 0x03460000 0x0 0x10000>;
+		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 54>;
+		clock-names = "sdhci";
+		resets = <&bpmp 36>;
+		reset-names = "sdhci";
+		status = "disabled";
+	};
+
+	gic: interrupt-controller@3881000 {
+		compatible = "arm,gic-400";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x0 0x03881000 0x0 0x1000>,
+		      <0x0 0x03882000 0x0 0x2000>;
+		interrupts = <GIC_PPI 9
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+		interrupt-parent = <&gic>;
+	};
+
+	hsp_top0: hsp@3c00000 {
+		compatible = "nvidia,tegra186-hsp";
+		reg = <0x0 0x03c00000 0x0 0xa0000>;
+		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "doorbell";
+		#mbox-cells = <2>;
+		status = "disabled";
+	};
+
+	gen2_i2c: i2c@c240000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x0c240000 0x0 0x10000>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 218>;
+		clock-names = "div-clk";
+		resets = <&bpmp 20>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	gen8_i2c: i2c@c250000 {
+		compatible = "nvidia,tegra186-i2c", "nvidia,tegra114-i2c";
+		reg = <0x0 0x0c250000 0x0 0x10000>;
+		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&bpmp 219>;
+		clock-names = "div-clk";
+		resets = <&bpmp 82>;
+		reset-names = "i2c";
+		status = "disabled";
+	};
+
+	uartc: serial@c280000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x0c280000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 215>;
+		clock-names = "serial";
+		resets = <&bpmp 49>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	uartg: serial@c290000 {
+		compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
+		reg = <0x0 0x0c290000 0x0 0x40>;
+		reg-shift = <2>;
+		interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&bpmp 216>;
+		clock-names = "serial";
+		resets = <&bpmp 112>;
+		reset-names = "serial";
+		status = "disabled";
+	};
+
+	gpio_aon: gpio@c2f0000 {
+		compatible = "nvidia,tegra186-gpio-aon";
+		reg-names = "security", "gpio";
+		reg = <0x0 0xc2f0000 0x0 0x1000>,
+		      <0x0 0xc2f1000 0x0 0x1000>;
+		interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	sysram@30000000 {
+		compatible = "nvidia,tegra186-sysram", "mmio-sram";
+		reg = <0x0 0x30000000 0x0 0x50000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
+
+		cpu_bpmp_tx: shmem@4e000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4e000 0x0 0x1000>;
+			label = "cpu-bpmp-tx";
+			pool;
+		};
+
+		cpu_bpmp_rx: shmem@4f000 {
+			compatible = "nvidia,tegra186-bpmp-shmem";
+			reg = <0x0 0x4f000 0x0 0x1000>;
+			label = "cpu-bpmp-rx";
+			pool;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			compatible = "nvidia,tegra186-denver", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x000>;
+		};
+
+		cpu@1 {
+			compatible = "nvidia,tegra186-denver", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x001>;
+		};
+
+		cpu@2 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x100>;
+		};
+
+		cpu@3 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x101>;
+		};
+
+		cpu@4 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x102>;
+		};
+
+		cpu@5 {
+			compatible = "arm,cortex-a57", "arm,armv8";
+			device_type = "cpu";
+			reg = <0x103>;
+		};
+	};
+
+	bpmp: bpmp {
+		compatible = "nvidia,tegra186-bpmp";
+		mboxes = <&hsp_top0 0 19>;
+		shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+
+		bpmp_i2c: i2c {
+			compatible = "nvidia,tegra186-bpmp-i2c";
+			nvidia,bpmp-bus-id = <5>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 14
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 11
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 10
+				(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+		interrupt-parent = <&gic>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+/dts-v1/;
+
+#include "tegra186-p3310.dtsi"
+
+/ {
+	model = "NVIDIA Tegra186 P2771-0000 Development Board";
+	compatible = "nvidia,p2771-0000", "nvidia,tegra186";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+#include "tegra186.dtsi"
+
+/ {
+	model = "NVIDIA Tegra186 P3310 Processor Module";
+	compatible = "nvidia,p3310", "nvidia,tegra186";
+
+	aliases {
+		serial0 = &uarta;
+	};
+
+	chosen {
+		bootargs = "earlycon console=ttyS0,115200n8";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x0 0x80000000 0x2 0x00000000>;
+	};
+
+	serial@3100000 {
+		status = "okay";
+	};
+
+	hsp@3c00000 {
+		status = "okay";
+	};
+
+	cpus {
+		cpu@0 {
+			enable-method = "psci";
+		};
+
+		cpu@1 {
+			enable-method = "psci";
+		};
+
+		cpu@2 {
+			enable-method = "psci";
+		};
+
+		cpu@3 {
+			enable-method = "psci";
+		};
+
+		cpu@4 {
+			enable-method = "psci";
+		};
+
+		cpu@5 {
+			enable-method = "psci";
+		};
+	};
+
+	bpmp {
+		status = "okay";
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		status = "okay";
+		method = "smc";
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,69 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	pcie-controller@01003000 {
+		compatible = "nvidia,tegra210-pcie";
+		device_type = "pci";
+		reg = <0x0 0x01003000 0x0 0x00000800   /* PADS registers */
+		       0x0 0x01003800 0x0 0x00000800   /* AFI registers */
+		       0x0 0x02000000 0x0 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
+			     <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x01000000 0x0 0x01000000 0 0x00001000   /* port 0 configuration space */
+			  0x82000000 0 0x01001000 0x0 0x01001000 0 0x00001000   /* port 1 configuration space */
+			  0x81000000 0 0x0        0x0 0x12000000 0 0x00010000   /* downstream I/O (64 KiB) */
+			  0x82000000 0 0x13000000 0x0 0x13000000 0 0x0d000000   /* non-prefetchable memory (208 MiB) */
+			  0xc2000000 0 0x20000000 0x0 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */
+
+		clocks = <&tegra_car TEGRA210_CLK_PCIE>,
+			 <&tegra_car TEGRA210_CLK_AFI>,
+			 <&tegra_car TEGRA210_CLK_PLL_E>,
+			 <&tegra_car TEGRA210_CLK_CML0>;
+		clock-names = "pex", "afi", "pll_e", "cml";
+		resets = <&tegra_car 70>,
+			 <&tegra_car 72>,
+			 <&tegra_car 74>;
+		reset-names = "pex", "afi", "pcie_x";
+		status = "disabled";
+
+		pci@1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <4>;
+		};
+
+		pci@2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <1>;
+		};
+	};
+
 	host1x@50000000 {
 		compatible = "nvidia,tegra210-host1x", "simple-bus";
 		reg = <0x0 0x50000000 0x0 0x00034000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2180.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,10 @@
 		reg = <0x0 0x80000000 0x1 0x0>;
 	};
 
+	gpu@57000000 {
+		vdd-supply = <&vdd_gpu>;
+	};
+
 	/* debug port */
 	serial@70006000 {
 		status = "okay";
@@ -291,4 +295,18 @@
 			clock-frequency = <32768>;
 		};
 	};
+
+	regulators {
+		vdd_gpu: regulator@100 {
+			compatible = "pwm-regulator";
+			reg = <100>;
+			pwms = <&pwm 1 4880>;
+			regulator-name = "VDD_GPU";
+			regulator-min-microvolt = <710000>;
+			regulator-max-microvolt = <1320000>;
+			enable-gpios = <&pmic 6 GPIO_ACTIVE_HIGH>;
+			regulator-ramp-delay = <80>;
+			regulator-enable-ramp-delay = <1000>;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210-p2371-2180.dts	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,32 @@
 	model = "NVIDIA Jetson TX1 Developer Kit";
 	compatible = "nvidia,p2371-2180", "nvidia,tegra210";
 
+	pcie-controller@01003000 {
+		status = "okay";
+
+		avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
+		hvddio-pex-supply = <&vdd_1v8>;
+		dvddio-pex-supply = <&vdd_pex_1v05>;
+		dvdd-pex-pll-supply = <&vdd_pex_1v05>;
+		hvdd-pex-pll-e-supply = <&vdd_1v8>;
+		vddio-pex-ctl-supply = <&vdd_1v8>;
+
+		pci@1,0 {
+			phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>,
+			       <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
+			       <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>,
+			       <&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>;
+			phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3";
+			status = "okay";
+		};
+
+		pci@2,0 {
+			phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
+			phy-names = "pcie-0";
+			status = "okay";
+		};
+	};
+
 	host1x@50000000 {
 		dsi@54300000 {
 			status = "okay";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/nvidia/tegra210-smaug.dts	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,8 @@
 	compatible = "google,smaug-rev8", "google,smaug-rev7",
 		     "google,smaug-rev6", "google,smaug-rev5",
 		     "google,smaug-rev4", "google,smaug-rev3",
-		     "google,smaug-rev1", "google,smaug", "nvidia,tegra210";
+		     "google,smaug-rev2", "google,smaug-rev1",
+		     "google,smaug", "nvidia,tegra210";
 
 	aliases {
 		serial0 = &uarta;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include "pm8916.dtsi"
 #include "apq8016-sbc-soc-pins.dtsi"
 #include "apq8016-sbc-pmic-pins.dtsi"
+#include <dt-bindings/sound/apq8016-lpass.h>
 
 / {
 	aliases {
@@ -251,6 +252,60 @@
 				vddio-supply = <&pm8916_l6>;
 			};
 		};
+
+		lpass_codec: codec{
+			status = "okay";
+		};
+
+		/*
+		Internal Codec
+			playback - Primary MI2S
+			capture - Ter MI2S
+
+		External Primary:
+			playback - secondary MI2S
+			capture - Quat MI2S
+
+		External Secondary:
+			playback - Quat MI2S
+			capture - Quat MI2S
+
+		*/
+
+                sound: sound {
+                        compatible = "qcom,apq8016-sbc-sndcard";
+                        reg = <0x07702000 0x4>, <0x07702004 0x4>;
+                        reg-names = "mic-iomux", "spkr-iomux";
+
+                        status = "okay";
+                        pinctrl-0 = <&cdc_pdm_lines_act &ext_sec_tlmm_lines_act &ext_mclk_tlmm_lines_act>;
+                        pinctrl-1 = <&cdc_pdm_lines_sus &ext_sec_tlmm_lines_sus &ext_mclk_tlmm_lines_sus>;
+                        pinctrl-names = "default", "sleep";
+                        qcom,model = "DB410c";
+                        qcom,audio-routing =
+                                "AMIC2", "MIC BIAS Internal2",
+                                "AMIC3", "MIC BIAS External1";
+
+                        internal-codec-playback-dai-link@0 {            /* I2S - Internal codec */
+                                link-name = "WCD";
+                                cpu { /* PRIMARY */
+                                        sound-dai = <&lpass MI2S_PRIMARY>;
+                                };
+                                codec {
+                                        sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
+                                };
+                        };
+
+                        internal-codec-capture-dai-link@0 {             /* I2S - Internal codec */
+                                link-name = "WCD-Capture";
+                                cpu { /* PRIMARY */
+                                        sound-dai = <&lpass MI2S_TERTIARY>;
+                                };
+                                codec {
+                                        sound-dai = <&lpass_codec 1>, <&wcd_codec 1>;
+                                };
+                        };
+                };
 	};
 
 	usb2513 {
@@ -278,6 +333,12 @@
 	};
 };
 
+&wcd_codec {
+        status = "okay";
+        clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
+        clock-names = "mclk";
+};
+
 &smd_rpm_regulators {
 	vdd_l1_l2_l3-supply = <&pm8916_s3>;
 	vdd_l5-supply = <&pm8916_s3>;
@@ -308,8 +369,8 @@
 	};
 
 	l2 {
-		regulator-min-microvolt = <375000>;
-		regulator-max-microvolt = <1525000>;
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
 	};
 
 	l3 {
@@ -328,8 +389,8 @@
 	};
 
 	l6 {
-		regulator-min-microvolt = <1750000>;
-		regulator-max-microvolt = <3337000>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
 	};
 
 	l7 {
@@ -388,8 +449,8 @@
 	};
 
 	l17 {
-		regulator-min-microvolt = <1750000>;
-		regulator-max-microvolt = <3337000>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
 	};
 
 	l18 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,9 @@
  */
 
 #include "msm8996.dtsi"
+#include "pm8994.dtsi"
 #include "apq8096-db820c-pins.dtsi"
+#include "apq8096-db820c-pmic-pins.dtsi"
 
 / {
 	aliases {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,15 @@
+
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+&pm8994_gpios {
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&ls_exp_gpio_f>;
+
+	ls_exp_gpio_f: pm8916_mpp4 {
+		pinconf {
+			pins = "gpio5";
+			output-low;
+			power-source = <2>; // PM8994_GPIO_S4, 1.8V
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,9 @@
-dtb-$(CONFIG_ARCH_QCOM)	+= apq8016-sbc.dtb msm8916-mtp.dtb
-dtb-$(CONFIG_ARCH_QCOM)	+= msm8996-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM)	+= apq8016-sbc.dtb
 dtb-$(CONFIG_ARCH_QCOM)	+= apq8096-db820c.dtb
+dtb-$(CONFIG_ARCH_QCOM)	+= msm8916-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM)	+= msm8992-bullhead-rev-101.dtb
+dtb-$(CONFIG_ARCH_QCOM)	+= msm8994-angler-rev-101.dtb
+dtb-$(CONFIG_ARCH_QCOM)	+= msm8996-mtp.dtb
 
 always		:= $(dtb-y)
 subdir-y	:= $(dts-dirs)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8916.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8916.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8916.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8916.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -77,7 +77,7 @@
 			no-map;
 		};
 
-		mpss@86800000 {
+		mpss_mem: mpss@86800000 {
 			reg = <0x0 0x86800000 0x0 0x2b00000>;
 			no-map;
 		};
@@ -504,6 +504,15 @@
 			reg-names = "lpass-lpaif";
 		};
 
+                lpass_codec: codec{
+			compatible = "qcom,msm8916-wcd-digital-codec";
+			reg = <0x0771c000 0x400>;
+			clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>,
+				 <&gcc GCC_CODEC_DIGCODEC_CLK>;
+			clock-names = "ahbix-clk", "mclk";
+			#sound-dai-cells = <1>;
+                };
+
 		sdhc_1: sdhci@07824000 {
 			compatible = "qcom,sdhci-msm-v4";
 			reg = <0x07824900 0x11c>, <0x07824000 0x800>;
@@ -512,8 +521,10 @@
 			interrupts = <0 123 0>, <0 138 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
 			clocks = <&gcc GCC_SDCC1_APPS_CLK>,
-				 <&gcc GCC_SDCC1_AHB_CLK>;
-			clock-names = "core", "iface";
+				 <&gcc GCC_SDCC1_AHB_CLK>,
+				 <&xo_board>;
+			clock-names = "core", "iface", "xo";
+			mmc-ddr-1_8v;
 			bus-width = <8>;
 			non-removable;
 			status = "disabled";
@@ -527,8 +538,9 @@
 			interrupts = <0 125 0>, <0 221 0>;
 			interrupt-names = "hc_irq", "pwr_irq";
 			clocks = <&gcc GCC_SDCC2_APPS_CLK>,
-				 <&gcc GCC_SDCC2_AHB_CLK>;
-			clock-names = "core", "iface";
+				 <&gcc GCC_SDCC2_AHB_CLK>,
+				 <&xo_board>;
+			clock-names = "core", "iface", "xo";
 			bus-width = <4>;
 			status = "disabled";
 		};
@@ -801,6 +813,49 @@
 				clock-names = "iface_clk";
 			};
 		};
+
+
+		hexagon@4080000 {
+			compatible = "qcom,q6v5-pil";
+			reg = <0x04080000 0x100>,
+			      <0x04020000 0x040>;
+
+			reg-names = "qdsp6", "rmb";
+
+			interrupts-extended = <&intc 0 24 1>,
+					      <&hexagon_smp2p_in 0 0>,
+					      <&hexagon_smp2p_in 1 0>,
+					      <&hexagon_smp2p_in 2 0>,
+					      <&hexagon_smp2p_in 3 0>;
+			interrupt-names = "wdog", "fatal", "ready",
+					  "handover", "stop-ack";
+
+			clocks = <&gcc GCC_MSS_CFG_AHB_CLK>,
+				 <&gcc GCC_MSS_Q6_BIMC_AXI_CLK>,
+				 <&gcc GCC_BOOT_ROM_AHB_CLK>;
+			clock-names = "iface", "bus", "mem";
+
+			qcom,smem-states = <&hexagon_smp2p_out 0>;
+			qcom,smem-state-names = "stop";
+
+			resets = <&scm 0>;
+			reset-names = "mss_restart";
+
+			mx-supply = <&pm8916_l3>;
+			pll-supply = <&pm8916_l7>;
+
+			qcom,halt-regs = <&tcsr 0x18000 0x19000 0x1a000>;
+
+			status = "disabled";
+
+			mba {
+				memory-region = <&mba_mem>;
+			};
+
+			mpss {
+				memory-region = <&mpss_mem>;
+			};
+		};
 	};
 
 	smd {
@@ -848,6 +903,14 @@
 				};
 			};
 		};
+
+		hexagon {
+			interrupts = <0 25 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,smd-edge = <0>;
+			qcom,ipc = <&apcs 8 12>;
+			qcom,remote-pid = <1>;
+		};
 	};
 
 	hexagon-smp2p {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+/* Copyright (c) 2015, LGE Inc. All rights reserved.
+ * Copyright (c) 2016, The Linux Foundation. All 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.
+ */
+
+/dts-v1/;
+
+#include "msm8992.dtsi"
+
+/ {
+	model = "LG Nexus 5X";
+	compatible = "lg,bullhead", "qcom,msm8992";
+	/* required for bootloader to select correct board */
+	qcom,board-id = <0xb64 0>;
+	qcom,pmic-id = <0x10009 0x1000A 0x0 0x0>;
+
+	aliases {
+		serial0 = &blsp1_uart2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	soc {
+		serial@f991e000 {
+			status = "okay";
+			pinctrl-names = "default", "sleep";
+			pinctrl-0 = <&blsp1_uart2_default>;
+			pinctrl-1 = <&blsp1_uart2_sleep>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8992.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8992.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8992.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8992.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,184 @@
+/* Copyright (c) 2013-2016, The Linux Foundation. All 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 <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/qcom,gcc-msm8994.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM 8992";
+	compatible = "qcom,msm8992";
+	// msm-id needed by bootloader for selecting correct blob
+	qcom,msm-id = <251 0>, <252 0>;
+	interrupt-parent = <&intc>;
+
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	chosen { };
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+			};
+		};
+
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0 0x0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+				compatible = "cache";
+				cache-level = <2>;
+			};
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+			     <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+	};
+
+	xo_board: xo_board {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <19200000>;
+	};
+
+	sleep_clk: sleep_clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0xffffffff>;
+		compatible = "simple-bus";
+
+		intc: interrupt-controller@f9000000 {
+			compatible = "qcom,msm-qgic2";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			reg = <0xf9000000 0x1000>,
+				<0xf9002000 0x1000>;
+		};
+
+		timer@f9020000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			compatible = "arm,armv7-timer-mem";
+			reg = <0xf9020000 0x1000>;
+
+			frame@f9021000 {
+				frame-number = <0>;
+				interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+						<GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9021000 0x1000>,
+					<0xf9022000 0x1000>;
+			};
+
+			frame@f9023000 {
+				frame-number = <1>;
+				interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9023000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9024000 {
+				frame-number = <2>;
+				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9024000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9025000 {
+				frame-number = <3>;
+				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9025000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9026000 {
+				frame-number = <4>;
+				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9026000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9027000 {
+				frame-number = <5>;
+				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9027000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9028000 {
+				frame-number = <6>;
+				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9028000 0x1000>;
+				status = "disabled";
+			};
+		};
+
+		restart@fc4ab000 {
+			compatible = "qcom,pshold";
+			reg = <0xfc4ab000 0x4>;
+		};
+
+		msmgpio: pinctrl@fd510000 {
+			compatible = "qcom,msm8994-pinctrl";
+			reg = <0xfd510000 0x4000>;
+			interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		blsp1_uart2: serial@f991e000 {
+			compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+			reg = <0xf991e000 0x1000>;
+			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_LOW>;
+			status = "disabled";
+			clock-names = "core", "iface";
+			clocks = <&clock_gcc GCC_BLSP1_UART2_APPS_CLK>,
+				<&clock_gcc GCC_BLSP1_AHB_CLK>;
+		};
+
+		clock_gcc: clock-controller@fc400000 {
+			compatible = "qcom,gcc-msm8994";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			#power-domain-cells = <1>;
+			reg = <0xfc400000 0x2000>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0 0 0 0>; // bootloader will update
+	};
+};
+
+
+#include "msm8992-pins.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All 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.
+ */
+
+&msmgpio {
+	blsp1_uart2_default: blsp1_uart2_default {
+		pinmux {
+			function = "blsp_uart2";
+			pins = "gpio4", "gpio5";
+		};
+		pinconf {
+			pins = "gpio4", "gpio5";
+			drive-strength = <16>;
+			bias-disable;
+		};
+	};
+
+	blsp1_uart2_sleep: blsp1_uart2_sleep {
+		pinmux {
+			function = "gpio";
+			pins = "gpio4", "gpio5";
+		};
+		pinconf {
+			pins = "gpio4", "gpio5";
+			drive-strength = <2>;
+			bias-pull-down;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,40 @@
+/* Copyright (c) 2015, Huawei Inc. All rights reserved.
+ * Copyright (c) 2016, The Linux Foundation. All 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.
+ */
+
+/dts-v1/;
+
+#include "msm8994.dtsi"
+
+/ {
+	model = "Huawei Nexus 6P";
+	compatible = "huawei,angler", "qcom,msm8994";
+	/* required for bootloader to select correct board */
+	qcom,board-id = <8026 0>;
+
+	aliases {
+		serial0 = &blsp1_uart2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	soc {
+		serial@f991e000 {
+			status = "okay";
+			pinctrl-names = "default", "sleep";
+			pinctrl-0 = <&blsp1_uart2_default>;
+			pinctrl-1 = <&blsp1_uart2_sleep>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8994.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8994.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8994.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8994.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,216 @@
+/* Copyright (c) 2013-2016, The Linux Foundation. All 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 <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/qcom,gcc-msm8994.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM 8994";
+	compatible = "qcom,msm8994";
+	// msm-id and pmic-id are required by bootloader for
+	// proper selection of dt blob
+	qcom,msm-id = <207 0x20000>;
+	qcom,pmic-id = <0x10009 0x1000A 0x0 0x0>;
+	interrupt-parent = <&intc>;
+
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	chosen { };
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+			};
+		};
+
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0x0>;
+			next-level-cache = <&L2_0>;
+			L2_0: l2-cache {
+			      compatible = "cache";
+			      cache-level = <2>;
+			};
+		};
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <1 2 0xff08>,
+			     <1 3 0xff08>,
+			     <1 4 0xff08>,
+			     <1 1 0xff08>;
+	};
+
+	soc: soc {
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0xffffffff>;
+		compatible = "simple-bus";
+
+		intc: interrupt-controller@f9000000 {
+			compatible = "qcom,msm-qgic2";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			reg = <0xf9000000 0x1000>,
+				  <0xf9002000 0x1000>;
+		};
+
+		timer@f9020000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			compatible = "arm,armv7-timer-mem";
+			reg = <0xf9020000 0x1000>;
+
+			frame@f9021000 {
+				frame-number = <0>;
+				interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9021000 0x1000>,
+				      <0xf9022000 0x1000>;
+			};
+
+			frame@f9023000 {
+				frame-number = <1>;
+				interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9023000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9024000 {
+				frame-number = <2>;
+				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9024000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9025000 {
+				frame-number = <3>;
+				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9025000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9026000 {
+				frame-number = <4>;
+				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9026000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9027000 {
+				frame-number = <5>;
+				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9027000 0x1000>;
+				status = "disabled";
+			};
+
+			frame@f9028000 {
+				frame-number = <6>;
+				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+				reg = <0xf9028000 0x1000>;
+				status = "disabled";
+			};
+		};
+
+		restart@fc4ab000 {
+			compatible = "qcom,pshold";
+			reg = <0xfc4ab000 0x4>;
+		};
+
+		msmgpio: pinctrl@fd510000 {
+			compatible = "qcom,msm8994-pinctrl";
+			reg = <0xfd510000 0x4000>;
+			interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		blsp1_uart2: serial@f991e000 {
+			compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+			reg = <0xf991e000 0x1000>;
+			interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+			status = "disabled";
+			clock-names = "core", "iface";
+			clocks = <&clock_gcc GCC_BLSP1_UART2_APPS_CLK>,
+				 <&clock_gcc GCC_BLSP1_AHB_CLK>;
+		};
+
+		tcsr_mutex_regs: syscon@fd484000 {
+			compatible = "syscon";
+			reg = <0xfd484000 0x2000>;
+		};
+
+		clock_gcc: clock-controller@fc400000 {
+			compatible = "qcom,gcc-msm8994";
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			#power-domain-cells = <1>;
+			reg = <0xfc400000 0x2000>;
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		// We expect the bootloader to fill in the reg
+		reg = <0 0 0 0>;
+	};
+
+	xo_board: xo_board {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <19200000>;
+	};
+
+	sleep_clk: sleep_clk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		smem_mem: smem_region@6a00000 {
+			reg = <0x0 0x6a00000 0x0 0x200000>;
+			no-map;
+		};
+	};
+
+	tcsr_mutex: hwlock {
+		compatible = "qcom,tcsr-mutex";
+		syscon = <&tcsr_mutex_regs 0 0x80>;
+		#hwlock-cells = <1>;
+	};
+
+	qcom,smem@6a00000 {
+		compatible = "qcom,smem";
+		memory-region = <&smem_mem>;
+		hwlocks = <&tcsr_mutex 3>;
+	};
+};
+
+
+#include "msm8994-pins.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8994-pins.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8994-pins.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8994-pins.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8994-pins.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013-2016, The Linux Foundation. All 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.
+ */
+
+&msmgpio {
+	blsp1_uart2_default: blsp1_uart2_default {
+		pinmux {
+			function = "blsp_uart2";
+			pins = "gpio4", "gpio5";
+		};
+		pinconf {
+			pins = "gpio4", "gpio5";
+			drive-strength = <16>;
+			bias-disable;
+		};
+	};
+
+	blsp1_uart2_sleep: blsp1_uart2_sleep {
+		pinmux {
+			function = "gpio";
+			pins = "gpio4", "gpio5";
+		};
+		pinconf {
+			pins = "gpio4", "gpio5";
+			drive-strength = <2>;
+			bias-pull-down;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8996.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8996.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/msm8996.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/msm8996.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,52 @@
 		reg = <0 0 0 0>;
 	};
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		mba_region: mba@91500000 {
+			reg = <0x0 0x91500000 0x0 0x200000>;
+			no-map;
+		};
+
+		slpi_region: slpi@90b00000 {
+			reg = <0x0 0x90b00000 0x0 0xa00000>;
+			no-map;
+		};
+
+		venus_region: venus@90400000 {
+			reg = <0x0 0x90400000 0x0 0x700000>;
+			no-map;
+		};
+
+		adsp_region: adsp@8ea00000 {
+			reg = <0x0 0x8ea00000 0x0 0x1a00000>;
+			no-map;
+		};
+
+		mpss_region: mpss@88800000 {
+			reg = <0x0 0x88800000 0x0 0x6200000>;
+			no-map;
+		};
+
+		smem_mem: smem-mem@86000000 {
+			reg = <0x0 0x86000000 0x0 0x200000>;
+			no-map;
+		};
+
+		memory@85800000 {
+			reg = <0x0 0x85800000 0x0 0x800000>;
+			no-map;
+		};
+
+		memory@86200000 {
+			reg = <0x0 0x86200000 0x0 0x2600000>;
+			no-map;
+		};
+	};
+
 	cpus {
 		#address-cells = <2>;
 		#size-cells = <0>;
@@ -192,14 +238,14 @@
 	};
 
 	clocks {
-		xo_board {
+		xo_board: xo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <19200000>;
 			clock-output-names = "xo_board";
 		};
 
-		sleep_clk {
+		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <32764>;
@@ -212,12 +258,29 @@
 		method = "smc";
 	};
 
+	tcsr_mutex: hwlock {
+		compatible = "qcom,tcsr-mutex";
+		syscon = <&tcsr_mutex_regs 0 0x1000>;
+		#hwlock-cells = <1>;
+	};
+
+	smem {
+		compatible = "qcom,smem";
+		memory-region = <&smem_mem>;
+		hwlocks = <&tcsr_mutex 3>;
+	};
+
 	soc: soc {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0 0 0 0xffffffff>;
 		compatible = "simple-bus";
 
+		tcsr_mutex_regs: syscon@740000 {
+			compatible = "syscon";
+			reg = <0x740000 0x20000>;
+		};
+
 		intc: interrupt-controller@9bc0000 {
 			compatible = "arm,gic-v3";
 			#interrupt-cells = <3>;
@@ -229,6 +292,11 @@
 			interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		apcs: syscon@9820000 {
+			compatible = "syscon";
+			reg = <0x9820000 0x1000>;
+		};
+
 		gcc: clock-controller@300000 {
 			compatible = "qcom,gcc-msm8996";
 			#clock-cells = <1>;
@@ -347,9 +415,10 @@
 			 interrupts = <0 125 0>, <0 221 0>;
 			 interrupt-names = "hc_irq", "pwr_irq";
 
-			 clock-names = "iface", "core";
+			 clock-names = "iface", "core", "xo";
 			 clocks = <&gcc GCC_SDCC2_AHB_CLK>,
-			 <&gcc GCC_SDCC2_APPS_CLK>;
+			 <&gcc GCC_SDCC2_APPS_CLK>,
+			 <&xo_board>;
 			 bus-width = <4>;
 		 };
 
@@ -458,5 +527,29 @@
 					       <825000000>;
 		};
 	};
+
+	adsp-smp2p {
+		compatible = "qcom,smp2p";
+		qcom,smem = <443>, <429>;
+
+		interrupts = <0 158 IRQ_TYPE_EDGE_RISING>;
+
+		qcom,ipc = <&apcs 16 10>;
+
+		qcom,local-pid = <0>;
+		qcom,remote-pid = <2>;
+
+		adsp_smp2p_out: master-kernel {
+			qcom,entry-name = "master-kernel";
+			#qcom,state-cells = <1>;
+		};
+
+		adsp_smp2p_in: slave-kernel {
+			qcom,entry-name = "slave-kernel";
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+	};
 };
 #include "msm8996-pins.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/pm8916.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/pm8916.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/pm8916.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/pm8916.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -91,9 +91,52 @@
 	};
 
 	pm8916_1: pm8916@1 {
-		compatible = "qcom,spmi-pmic";
+		compatible = "qcom,pm8916", "qcom,spmi-pmic";
 		reg = <0x1 SPMI_USID>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+
+                wcd_codec: codec@f000 {
+                       compatible = "qcom,pm8916-wcd-analog-codec";
+	               reg = <0xf000 0x200>;
+	               reg-names = "pmic-codec-core";
+	               clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
+	               clock-names = "mclk";
+	               interrupt-parent = <&spmi_bus>;
+	               interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+	                            <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+	                            <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+	                            <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+	                            <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+	                            <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+	                            <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+	                            <0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+	                            <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+	                            <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+	                            <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+	                            <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+	                            <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+	                            <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+	               interrupt-names = "cdc_spk_cnp_int",
+	                                 "cdc_spk_clip_int",
+	                                 "cdc_spk_ocp_int",
+	                                 "mbhc_ins_rem_det1",
+	                                 "mbhc_but_rel_det",
+	                                 "mbhc_but_press_det",
+	                                 "mbhc_ins_rem_det",
+	                                 "mbhc_switch_int",
+	                                 "cdc_ear_ocp_int",
+	                                 "cdc_hphr_ocp_int",
+	                                 "cdc_hphl_ocp_det",
+	                                 "cdc_ear_cnp_int",
+	                                 "cdc_hphr_cnp_int",
+	                                 "cdc_hphl_cnp_int";
+	               vdd-cdc-io-supply = <&pm8916_l5>;
+	               vdd-cdc-tx-rx-cx-supply = <&pm8916_l5>;
+	               vdd-micbias-supply = <&pm8916_l13>;
+	               #sound-dai-cells = <1>;
+
+                };
+
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/pm8994.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/pm8994.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/qcom/pm8994.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/qcom/pm8994.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,7 @@
 				     <0 0xcc 0 IRQ_TYPE_NONE>,
 				     <0 0xcd 0 IRQ_TYPE_NONE>,
 				     <0 0xce 0 IRQ_TYPE_NONE>,
+				     <0 0xcf 0 IRQ_TYPE_NONE>,
 				     <0 0xd0 0 IRQ_TYPE_NONE>,
 				     <0 0xd1 0 IRQ_TYPE_NONE>,
 				     <0 0xd2 0 IRQ_TYPE_NONE>,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 dtb-$(CONFIG_ARCH_R8A7795) += r8a7795-salvator-x.dtb r8a7795-h3ulcb.dtb
-dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb
+dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-x.dtb r8a7796-m3ulcb.dtb
 
 always		:= $(dtb-y)
 clean-files	:= *.dtb
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7795.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -321,6 +321,16 @@
 			#power-domain-cells = <0>;
 		};
 
+		rst: reset-controller@e6160000 {
+			compatible = "renesas,r8a7795-rst";
+			reg = <0 0xe6160000 0 0x0200>;
+		};
+
+		prr: chipid@fff00044 {
+			compatible = "renesas,prr";
+			reg = <0 0xfff00044 0 4>;
+		};
+
 		sysc: system-controller@e6180000 {
 			compatible = "renesas,r8a7795-sysc";
 			reg = <0 0xe6180000 0 0x0400>;
@@ -1306,28 +1316,28 @@
 		};
 
 		fcpvb1: fcp@fe92f000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfe92f000 0 0x200>;
 			clocks = <&cpg CPG_MOD 606>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
 		};
 
 		fcpf0: fcp@fe950000 {
-			compatible = "renesas,r8a7795-fcpf", "renesas,fcpf";
+			compatible = "renesas,fcpf";
 			reg = <0 0xfe950000 0 0x200>;
 			clocks = <&cpg CPG_MOD 615>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
 		};
 
 		fcpf1: fcp@fe951000 {
-			compatible = "renesas,r8a7795-fcpf", "renesas,fcpf";
+			compatible = "renesas,fcpf";
 			reg = <0 0xfe951000 0 0x200>;
 			clocks = <&cpg CPG_MOD 614>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
 		};
 
 		fcpf2: fcp@fe952000 {
-			compatible = "renesas,r8a7795-fcpf", "renesas,fcpf";
+			compatible = "renesas,fcpf";
 			reg = <0 0xfe952000 0 0x200>;
 			clocks = <&cpg CPG_MOD 613>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
@@ -1344,7 +1354,7 @@
 		};
 
 		fcpvb0: fcp@fe96f000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfe96f000 0 0x200>;
 			clocks = <&cpg CPG_MOD 607>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
@@ -1361,7 +1371,7 @@
 		};
 
 		fcpvi0: fcp@fe9af000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfe9af000 0 0x200>;
 			clocks = <&cpg CPG_MOD 611>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
@@ -1378,7 +1388,7 @@
 		};
 
 		fcpvi1: fcp@fe9bf000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfe9bf000 0 0x200>;
 			clocks = <&cpg CPG_MOD 610>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
@@ -1395,7 +1405,7 @@
 		};
 
 		fcpvi2: fcp@fe9cf000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfe9cf000 0 0x200>;
 			clocks = <&cpg CPG_MOD 609>;
 			power-domains = <&sysc R8A7795_PD_A3VP>;
@@ -1412,7 +1422,7 @@
 		};
 
 		fcpvd0: fcp@fea27000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfea27000 0 0x200>;
 			clocks = <&cpg CPG_MOD 603>;
 			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
@@ -1429,7 +1439,7 @@
 		};
 
 		fcpvd1: fcp@fea2f000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfea2f000 0 0x200>;
 			clocks = <&cpg CPG_MOD 602>;
 			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
@@ -1446,7 +1456,7 @@
 		};
 
 		fcpvd2: fcp@fea37000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfea37000 0 0x200>;
 			clocks = <&cpg CPG_MOD 601>;
 			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
@@ -1463,7 +1473,7 @@
 		};
 
 		fcpvd3: fcp@fea3f000 {
-			compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+			compatible = "renesas,fcpv";
 			reg = <0 0xfea3f000 0 0x200>;
 			clocks = <&cpg CPG_MOD 600>;
 			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Device Tree Source for the H3ULCB board
+ * Device Tree Source for the H3ULCB (R-Car Starter Kit Premier) board
  *
  * Copyright (C) 2016 Renesas Electronics Corp.
  * Copyright (C) 2016 Cogent Embedded, Inc.
@@ -62,6 +62,24 @@
 		clock-frequency = <24576000>;
 	};
 
+	reg_1p8v: regulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
 	vcc_sdhi0: regulator-vcc-sdhi0 {
 		compatible = "regulator-fixed";
 
@@ -145,18 +163,30 @@
 		function = "avb";
 	};
 
-	sdhi0_pins_3v3: sd0_3v3 {
+	sdhi0_pins: sd0 {
 		groups = "sdhi0_data4", "sdhi0_ctrl";
 		function = "sdhi0";
 		power-source = <3300>;
 	};
 
-	sdhi0_pins_1v8: sd0_1v8 {
+	sdhi0_pins_uhs: sd0_uhs {
 		groups = "sdhi0_data4", "sdhi0_ctrl";
 		function = "sdhi0";
 		power-source = <1800>;
 	};
 
+	sdhi2_pins: sd2 {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <3300>;
+	};
+
+	sdhi2_pins_uhs: sd2_uhs {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
+	};
+
 	sound_pins: sound {
 		groups = "ssi01239_ctrl", "ssi0_data", "ssi1_data_a";
 		function = "ssi";
@@ -261,8 +291,8 @@
 };
 
 &sdhi0 {
-	pinctrl-0 = <&sdhi0_pins_3v3>;
-	pinctrl-1 = <&sdhi0_pins_1v8>;
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-1 = <&sdhi0_pins_uhs>;
 	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi0>;
@@ -273,6 +303,19 @@
 	status = "okay";
 };
 
+&sdhi2 {
+	/* used for on-board 8bit eMMC */
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-1 = <&sdhi2_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
 &ssi1 {
 	shared-pin;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts	2017-02-12 16:03:20.000000000 -0500
@@ -62,6 +62,24 @@
 		clock-frequency = <24576000>;
 	};
 
+	reg_1p8v: regulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
 	vcc_sdhi0: regulator-vcc-sdhi0 {
 		compatible = "regulator-fixed";
 
@@ -191,6 +209,10 @@
 				remote-endpoint = <&adv7123_in>;
 			};
 		};
+		port@3 {
+			lvds_connector: endpoint {
+			};
+		};
 	};
 };
 
@@ -237,11 +259,37 @@
 	sdhi0_pins: sd0 {
 		groups = "sdhi0_data4", "sdhi0_ctrl";
 		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
+	};
+
+	sdhi2_pins: sd2 {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <3300>;
+	};
+
+	sdhi2_pins_uhs: sd2_uhs {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
 	};
 
 	sdhi3_pins: sd3 {
 		groups = "sdhi3_data4", "sdhi3_ctrl";
 		function = "sdhi3";
+		power-source = <3300>;
+	};
+
+	sdhi3_pins_uhs: sd3_uhs {
+		groups = "sdhi3_data4", "sdhi3_ctrl";
+		function = "sdhi3";
+		power-source = <1800>;
 	};
 
 	sound_pins: sound {
@@ -261,8 +309,20 @@
 	};
 
 	usb1_pins: usb1 {
-		groups = "usb1";
-		function = "usb1";
+		mux {
+			groups = "usb1";
+			function = "usb1";
+		};
+
+		ovc {
+			pins = "GP_6_27";
+			bias-pull-up;
+		};
+
+		pwen {
+			pins = "GP_6_26";
+			bias-pull-down;
+		};
 	};
 
 	usb2_pins: usb2 {
@@ -371,25 +431,42 @@
 
 &sdhi0 {
 	pinctrl-0 = <&sdhi0_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi0>;
 	vqmmc-supply = <&vccq_sdhi0>;
 	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
 	bus-width = <4>;
+	sd-uhs-sdr50;
+	status = "okay";
+};
+
+&sdhi2 {
+	/* used for on-board 8bit eMMC */
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-1 = <&sdhi2_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	bus-width = <8>;
+	non-removable;
 	status = "okay";
 };
 
 &sdhi3 {
 	pinctrl-0 = <&sdhi3_pins>;
-	pinctrl-names = "default";
+	pinctrl-1 = <&sdhi3_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
 
 	vmmc-supply = <&vcc_sdhi3>;
 	vqmmc-supply = <&vccq_sdhi3>;
 	cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
 	bus-width = <4>;
+	sd-uhs-sdr50;
 	status = "okay";
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7796.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7796.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7796.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7796.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,16 @@
 	#address-cells = <2>;
 	#size-cells = <2>;
 
+	aliases {
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		i2c3 = &i2c3;
+		i2c4 = &i2c4;
+		i2c5 = &i2c5;
+		i2c6 = &i2c6;
+	};
+
 	psci {
 		compatible = "arm,psci-0.2";
 		method = "smc";
@@ -233,12 +243,123 @@
 			#power-domain-cells = <0>;
 		};
 
+		rst: reset-controller@e6160000 {
+			compatible = "renesas,r8a7796-rst";
+			reg = <0 0xe6160000 0 0x0200>;
+		};
+
+		prr: chipid@fff00044 {
+			compatible = "renesas,prr";
+			reg = <0 0xfff00044 0 4>;
+		};
+
 		sysc: system-controller@e6180000 {
 			compatible = "renesas,r8a7796-sysc";
 			reg = <0 0xe6180000 0 0x0400>;
 			#power-domain-cells = <1>;
 		};
 
+		i2c0: i2c@e6500000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a7796";
+			reg = <0 0xe6500000 0 0x40>;
+			interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 931>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			dmas = <&dmac1 0x91>, <&dmac1 0x90>,
+			       <&dmac2 0x91>, <&dmac2 0x90>;
+			dma-names = "tx", "rx", "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c1: i2c@e6508000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a7796";
+			reg = <0 0xe6508000 0 0x40>;
+			interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 930>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			dmas = <&dmac1 0x93>, <&dmac1 0x92>,
+			       <&dmac2 0x93>, <&dmac2 0x92>;
+			dma-names = "tx", "rx", "tx", "rx";
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c2: i2c@e6510000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a7796";
+			reg = <0 0xe6510000 0 0x40>;
+			interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 929>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			dmas = <&dmac1 0x95>, <&dmac1 0x94>,
+			       <&dmac2 0x95>, <&dmac2 0x94>;
+			dma-names = "tx", "rx", "tx", "rx";
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
+		i2c3: i2c@e66d0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a7796";
+			reg = <0 0xe66d0000 0 0x40>;
+			interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 928>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			dmas = <&dmac0 0x97>, <&dmac0 0x96>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c4: i2c@e66d8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a7796";
+			reg = <0 0xe66d8000 0 0x40>;
+			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 927>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			dmas = <&dmac0 0x99>, <&dmac0 0x98>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c5: i2c@e66e0000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a7796";
+			reg = <0 0xe66e0000 0 0x40>;
+			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 919>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			dmas = <&dmac0 0x9b>, <&dmac0 0x9a>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <110>;
+			status = "disabled";
+		};
+
+		i2c6: i2c@e66e8000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "renesas,i2c-r8a7796";
+			reg = <0 0xe66e8000 0 0x40>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 918>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			dmas = <&dmac0 0x9d>, <&dmac0 0x9c>;
+			dma-names = "tx", "rx";
+			i2c-scl-internal-delay-ns = <6>;
+			status = "disabled";
+		};
+
 		scif2: serial@e6e88000 {
 			compatible = "renesas,scif-r8a7796",
 				     "renesas,rcar-gen3-scif", "renesas,scif";
@@ -251,5 +372,144 @@
 			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
 			status = "disabled";
 		};
+
+		dmac0: dma-controller@e6700000 {
+			compatible = "renesas,dmac-r8a7796",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe6700000 0 0x10000>;
+			interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 219>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+		};
+
+		dmac1: dma-controller@e7300000 {
+			compatible = "renesas,dmac-r8a7796",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe7300000 0 0x10000>;
+			interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 218>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+		};
+
+		dmac2: dma-controller@e7310000 {
+			compatible = "renesas,dmac-r8a7796",
+				     "renesas,rcar-dmac";
+			reg = <0 0xe7310000 0 0x10000>;
+			interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "error",
+					"ch0", "ch1", "ch2", "ch3",
+					"ch4", "ch5", "ch6", "ch7",
+					"ch8", "ch9", "ch10", "ch11",
+					"ch12", "ch13", "ch14", "ch15";
+			clocks = <&cpg CPG_MOD 217>;
+			clock-names = "fck";
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			#dma-cells = <1>;
+			dma-channels = <16>;
+		};
+
+		sdhi0: sd@ee100000 {
+			compatible = "renesas,sdhi-r8a7796";
+			reg = <0 0xee100000 0 0x2000>;
+			interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 314>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		sdhi1: sd@ee120000 {
+			compatible = "renesas,sdhi-r8a7796";
+			reg = <0 0xee120000 0 0x2000>;
+			interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 313>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		sdhi2: sd@ee140000 {
+			compatible = "renesas,sdhi-r8a7796";
+			reg = <0 0xee140000 0 0x2000>;
+			interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 312>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
+
+		sdhi3: sd@ee160000 {
+			compatible = "renesas,sdhi-r8a7796";
+			reg = <0 0xee160000 0 0x2000>;
+			interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&cpg CPG_MOD 311>;
+			max-frequency = <200000000>;
+			power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+			status = "disabled";
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,189 @@
+/*
+ * Device Tree Source for the M3ULCB (R-Car Starter Kit Pro) board
+ *
+ * Copyright (C) 2016 Renesas Electronics Corp.
+ * Copyright (C) 2016 Cogent Embedded, 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.
+ */
+
+/dts-v1/;
+#include "r8a7796.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Renesas M3ULCB board based on r8a7796";
+	compatible = "renesas,m3ulcb", "renesas,r8a7796";
+
+	aliases {
+		serial0 = &scif2;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@48000000 {
+		device_type = "memory";
+		/* first 128MB is reserved for secure area. */
+		reg = <0x0 0x48000000 0x0 0x38000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led5 {
+			gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
+		};
+		led6 {
+			gpios = <&gpio6 13 GPIO_ACTIVE_HIGH>;
+		};
+	};
+
+	keyboard {
+		compatible = "gpio-keys";
+
+		key-1 {
+			linux,code = <KEY_1>;
+			label = "SW3";
+			wakeup-source;
+			debounce-interval = <20>;
+			gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	reg_1p8v: regulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	vcc_sdhi0: regulator-vcc-sdhi0 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi0: regulator-vccq-sdhi0 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+};
+
+&extal_clk {
+	clock-frequency = <16666666>;
+};
+
+&extalr_clk {
+	clock-frequency = <32768>;
+};
+
+&pfc {
+	pinctrl-0 = <&scif_clk_pins>;
+	pinctrl-names = "default";
+
+	scif2_pins: scif2 {
+		groups = "scif2_data_a";
+		function = "scif2";
+	};
+
+	scif_clk_pins: scif_clk {
+		groups = "scif_clk_a";
+		function = "scif_clk";
+	};
+
+	sdhi0_pins: sd0 {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
+	};
+
+	sdhi2_pins: sd2 {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <3300>;
+	};
+
+	sdhi2_pins_uhs: sd2_uhs {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
+	};
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	sd-uhs-sdr50;
+	status = "okay";
+};
+
+&sdhi2 {
+	/* used for on-board 8bit eMMC */
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-1 = <&sdhi2_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
+&scif2 {
+	pinctrl-0 = <&scif2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
+&scif_clk {
+	clock-frequency = <14745600>;
+	status = "okay";
+};
+
+&wdt0 {
+	timeout-sec = <60>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@
 
 /dts-v1/;
 #include "r8a7796.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	model = "Renesas Salvator-X board based on r8a7796";
@@ -29,6 +30,72 @@
 		/* first 128MB is reserved for secure area. */
 		reg = <0x0 0x48000000 0x0 0x78000000>;
 	};
+
+	reg_1p8v: regulator0 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-1.8V";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	reg_3p3v: regulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "fixed-3.3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	vcc_sdhi0: regulator-vcc-sdhi0 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI0 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi0: regulator-vccq-sdhi0 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI0 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
+
+	vcc_sdhi3: regulator-vcc-sdhi3 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "SDHI3 Vcc";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpio = <&gpio3 15 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	vccq_sdhi3: regulator-vccq-sdhi3 {
+		compatible = "regulator-gpio";
+
+		regulator-name = "SDHI3 VccQ";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+
+		gpios = <&gpio3 14 GPIO_ACTIVE_HIGH>;
+		gpios-states = <1>;
+		states = <3300000 1
+			  1800000 0>;
+	};
 };
 
 &pfc {
@@ -43,12 +110,98 @@
 		groups = "scif_clk_a";
 		function = "scif_clk";
 	};
+
+	i2c2_pins: i2c2 {
+		groups = "i2c2_a";
+		function = "i2c2";
+	};
+
+	sdhi0_pins: sd0 {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <3300>;
+	};
+
+	sdhi0_pins_uhs: sd0_uhs {
+		groups = "sdhi0_data4", "sdhi0_ctrl";
+		function = "sdhi0";
+		power-source = <1800>;
+	};
+
+	sdhi2_pins: sd2 {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <3300>;
+	};
+
+	sdhi2_pins_uhs: sd2_uhs {
+		groups = "sdhi2_data8", "sdhi2_ctrl";
+		function = "sdhi2";
+		power-source = <1800>;
+	};
+
+	sdhi3_pins: sd3 {
+		groups = "sdhi3_data4", "sdhi3_ctrl";
+		function = "sdhi3";
+		power-source = <3300>;
+	};
+
+	sdhi3_pins_uhs: sd3_uhs {
+		groups = "sdhi3_data4", "sdhi3_ctrl";
+		function = "sdhi3";
+		power-source = <1800>;
+	};
 };
 
 &extal_clk {
 	clock-frequency = <16666666>;
 };
 
+&extalr_clk {
+	clock-frequency = <32768>;
+};
+
+&sdhi0 {
+	pinctrl-0 = <&sdhi0_pins>;
+	pinctrl-1 = <&sdhi0_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&vcc_sdhi0>;
+	vqmmc-supply = <&vccq_sdhi0>;
+	cd-gpios = <&gpio3 12 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+	bus-width = <4>;
+	sd-uhs-sdr50;
+	status = "okay";
+};
+
+&sdhi2 {
+	/* used for on-board 8bit eMMC */
+	pinctrl-0 = <&sdhi2_pins>;
+	pinctrl-1 = <&sdhi2_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&reg_3p3v>;
+	vqmmc-supply = <&reg_1p8v>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
+&sdhi3 {
+	pinctrl-0 = <&sdhi3_pins>;
+	pinctrl-1 = <&sdhi3_pins_uhs>;
+	pinctrl-names = "default", "state_uhs";
+
+	vmmc-supply = <&vcc_sdhi3>;
+	vqmmc-supply = <&vccq_sdhi3>;
+	cd-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
+	wp-gpios = <&gpio4 16 GPIO_ACTIVE_HIGH>;
+	bus-width = <4>;
+	sd-uhs-sdr50;
+	status = "okay";
+};
+
 &scif2 {
 	pinctrl-0 = <&scif2_pins>;
 	pinctrl-names = "default";
@@ -60,6 +213,13 @@
 	status = "okay";
 };
 
+&i2c2 {
+	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-names = "default";
+
+	status = "okay";
+};
+
 &wdt0 {
 	timeout-sec = <60>;
 	status = "okay";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/Makefile
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,7 @@
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-orion-r68-meta.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-px5-evb.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-evb.dtb
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3368.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -231,7 +231,7 @@
 	sdmmc: dwmmc@ff0c0000 {
 		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xff0c0000 0x0 0x4000>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
 			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -243,7 +243,7 @@
 	sdio0: dwmmc@ff0d0000 {
 		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xff0d0000 0x0 0x4000>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
 			 <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
@@ -255,7 +255,7 @@
 	emmc: dwmmc@ff0f0000 {
 		compatible = "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xff0f0000 0x0 0x4000>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
 			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -315,16 +315,16 @@
 		status = "disabled";
 	};
 
-	i2c1: i2c@ff140000 {
+	i2c2: i2c@ff140000 {
 		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
 		reg = <0x0 0xff140000 0x0 0x1000>;
 		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clock-names = "i2c";
-		clocks = <&cru PCLK_I2C1>;
+		clocks = <&cru PCLK_I2C2>;
 		pinctrl-names = "default";
-		pinctrl-0 = <&i2c1_xfer>;
+		pinctrl-0 = <&i2c2_xfer>;
 		status = "disabled";
 	};
 
@@ -537,7 +537,6 @@
 		g-np-tx-fifo-size = <16>;
 		g-rx-fifo-size = <275>;
 		g-tx-fifo-size = <256 128 128 64 64 32>;
-		g-use-dma;
 		status = "disabled";
 	};
 
@@ -554,16 +553,16 @@
 		status = "disabled";
 	};
 
-	i2c2: i2c@ff660000 {
+	i2c1: i2c@ff660000 {
 		compatible = "rockchip,rk3368-i2c", "rockchip,rk3288-i2c";
 		reg = <0x0 0xff660000 0x0 0x1000>;
 		interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clock-names = "i2c";
-		clocks = <&cru PCLK_I2C2>;
+		clocks = <&cru PCLK_I2C1>;
 		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_xfer>;
+		pinctrl-0 = <&i2c1_xfer>;
 		status = "disabled";
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3368-orion-r68-meta.dts	2017-02-12 16:03:20.000000000 -0500
@@ -344,7 +344,7 @@
 &sdmmc {
 	bus-width = <4>;
 	clock-frequency = <50000000>;
-	clock-freq-min-max = <400000 50000000>;
+	max-frequency = <50000000>;
 	cap-sd-highspeed;
 	card-detect-delay = <200>;
 	num-slots = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2016 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) 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 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.
+ */
+
+/dts-v1/;
+#include "rk3368.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Rockchip PX5 EVB";
+	compatible = "rockchip,px5-evb", "rockchip,px5", "rockchip,rk3368";
+
+	chosen {
+		stdout-path = "serial4:115200n8";
+	};
+
+	memory@0 {
+		reg = <0x0 0x0 0x0 0x80000000>;
+		device_type = "memory";
+	};
+
+	keys: gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwr_key>;
+
+		power {
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+			label = "GPIO Power";
+			linux,code = <KEY_POWER>;
+			wakeup-source;
+		};
+	};
+
+	vcc_sys: vcc-sys-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_sys";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+};
+
+&emmc {
+	status = "okay";
+	bus-width = <8>;
+	cap-mmc-highspeed;
+	clock-frequency = <150000000>;
+	disable-wp;
+	keep-power-in-suspend;
+	mmc-hs200-1_8v;
+	no-sdio;
+	no-sd;
+	non-removable;
+	num-slots = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_bus8>;
+	vmmc-supply = <&vcc_io>;
+	vqmmc-supply = <&vcc18_flash>;
+};
+
+&i2c0 {
+	status = "okay";
+
+	rk808: pmic@1b {
+		compatible = "rockchip,rk808";
+		reg = <0x1b>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_int>, <&pmic_sleep>;
+		rockchip,system-power-controller;
+		vcc1-supply = <&vcc_sys>;
+		vcc2-supply = <&vcc_sys>;
+		vcc3-supply = <&vcc_sys>;
+		vcc4-supply = <&vcc_sys>;
+		vcc6-supply = <&vcc_sys>;
+		vcc7-supply = <&vcc_sys>;
+		vcc8-supply = <&vcc_io>;
+		vcc9-supply = <&vcc_sys>;
+		vcc10-supply = <&vcc_sys>;
+		vcc11-supply = <&vcc_sys>;
+		vcc12-supply = <&vcc_io>;
+		clock-output-names = "xin32k", "rk808-clkout2";
+		#clock-cells = <1>;
+
+		regulators {
+			vdd_cpu: DCDC_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd_cpu";
+			};
+
+			vdd_log: DCDC_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1500000>;
+				regulator-name = "vdd_log";
+			};
+
+			vcc_ddr: DCDC_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc_ddr";
+			};
+
+			vcc_io: DCDC_REG4 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcc_io";
+			};
+
+			vcc18_flash: LDO_REG1 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_flash";
+			};
+
+			vcca_33: LDO_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vcca_33";
+			};
+
+			vdd_10: LDO_REG3 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd_10";
+			};
+
+			avdd_33: LDO_REG4 {
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "avdd_33";
+			};
+
+			vccio_sd: LDO_REG5 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-name = "vccio_sd";
+			};
+
+			vdd10_lcd: LDO_REG6 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <1000000>;
+				regulator-name = "vdd10_lcd";
+			};
+
+			vcc_18: LDO_REG7 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc_18";
+			};
+
+			vcc18_lcd: LDO_REG8 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-name = "vcc18_lcd";
+			};
+
+			vcc_sd: SWITCH_REG1 {
+				regulator-name = "vcc_sd";
+			};
+
+			vcc33_lcd: SWITCH_REG2 {
+				regulator-always-on;
+				regulator-boot-on;
+				regulator-name = "vcc33_lcd";
+			};
+		};
+	};
+};
+
+&i2c1 {
+	status = "okay";
+
+	accelerometer@18 {
+		compatible = "bosch,bma250";
+		reg = <0x18>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2c2 {
+	status = "okay";
+
+	gsl1680: touchscreen@40 {
+		compatible = "silead,gsl1680";
+		reg = <0x40>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
+		power-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>;
+		touchscreen-size-x = <800>;
+		touchscreen-size-y = <1280>;
+		silead,max-fingers = <5>;
+	};
+};
+
+&pinctrl {
+	keys {
+		pwr_key: pwr-key {
+			rockchip,pins = <0 2 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+
+	pmic {
+		pmic_sleep: pmic-sleep {
+			rockchip,pins = <0 0 RK_FUNC_2 &pcfg_pull_none>;
+		};
+
+		pmic_int: pmic-int {
+			rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+};
+
+&sdmmc {
+	status = "okay";
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	card-detect-delay = <200>;
+	no-emmc;
+	no-sdio;
+	num-slots = <1>;
+	sd-uhs-sdr12;
+	sd-uhs-sdr25;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_bus4>, <&sdmmc_cd>;
+	rockchip,default-sample-phase = <90>;
+	vmmc-supply = <&vcc_sd>;
+	vqmmc-supply = <&vccio_sd>;
+};
+
+&tsadc {
+	status = "okay";
+	rockchip,hw-tshut-mode = <0>; /* CRU */
+	rockchip,hw-tshut-polarity = <1>; /* high */
+};
+
+&uart4 {
+	status = "okay";
+};
+
+&usb_host0_ehci {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3399.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -174,6 +174,7 @@
 			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW 0>,
 			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW 0>,
 			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW 0>;
+		arm,no-tick-in-suspend;
 	};
 
 	xin24m: xin24m {
@@ -235,7 +236,7 @@
 			     "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xfe310000 0x0 0x4000>;
 		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH 0>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
 			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -248,11 +249,12 @@
 			     "rockchip,rk3288-dw-mshc";
 		reg = <0x0 0xfe320000 0x0 0x4000>;
 		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
-		clock-freq-min-max = <400000 150000000>;
+		max-frequency = <150000000>;
 		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
 			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
 		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
+		power-domains = <&power RK3399_PD_SD>;
 		status = "disabled";
 	};
 
@@ -269,6 +271,7 @@
 		#clock-cells = <0>;
 		phys = <&emmc_phy>;
 		phy-names = "phy_arasan";
+		power-domains = <&power RK3399_PD_EMMC>;
 		status = "disabled";
 	};
 
@@ -693,6 +696,16 @@
 		status = "disabled";
 	};
 
+	qos_sd: qos@ffa74000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa74000 0x0 0x20>;
+	};
+
+	qos_emmc: qos@ffa58000 {
+		compatible = "syscon";
+		reg = <0x0 0xffa58000 0x0 0x20>;
+	};
+
 	qos_gmac: qos@ffa5c000 {
 		compatible = "syscon";
 		reg = <0x0 0xffa5c000 0x0 0x20>;
@@ -826,11 +839,23 @@
 			};
 
 			/* These power domains are grouped by VD_LOGIC */
+			pd_emmc@RK3399_PD_EMMC {
+				reg = <RK3399_PD_EMMC>;
+				clocks = <&cru ACLK_EMMC>;
+				pm_qos = <&qos_emmc>;
+			};
 			pd_gmac@RK3399_PD_GMAC {
 				reg = <RK3399_PD_GMAC>;
-				clocks = <&cru ACLK_GMAC>;
+				clocks = <&cru ACLK_GMAC>,
+					 <&cru PCLK_GMAC>;
 				pm_qos = <&qos_gmac>;
 			};
+			pd_sd@RK3399_PD_SD {
+				reg = <RK3399_PD_SD>;
+				clocks = <&cru HCLK_SDMMC>,
+					 <&cru SCLK_SDMMC>;
+				pm_qos = <&qos_sd>;
+			};
 			pd_vio@RK3399_PD_VIO {
 				reg = <RK3399_PD_VIO>;
 				#address-cells = <1>;
@@ -1026,6 +1051,9 @@
 		clock-names = "pclk_efuse";
 
 		/* Data cells */
+		cpu_id: cpu-id@7 {
+			reg = <0x07 0x10>;
+		};
 		cpub_leakage: cpu-leakage@17 {
 			reg = <0x17 0x1>;
 		};
@@ -1104,6 +1132,16 @@
 				interrupt-names = "linestate";
 				status = "disabled";
 			};
+
+			u2phy0_otg: otg-port {
+				#phy-cells = <0>;
+				interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "otg-bvalid", "otg-id",
+						  "linestate";
+				status = "disabled";
+			};
 		};
 
 		u2phy1: usb2-phy@e460 {
@@ -1121,6 +1159,16 @@
 				interrupt-names = "linestate";
 				status = "disabled";
 			};
+
+			u2phy1_otg: otg-port {
+				#phy-cells = <0>;
+				interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH 0>,
+					     <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH 0>;
+				interrupt-names = "otg-bvalid", "otg-id",
+						  "linestate";
+				status = "disabled";
+			};
 		};
 
 		emmc_phy: phy@f780 {
@@ -1151,6 +1199,7 @@
 		clock-names = "tcpdcore", "tcpdphy-ref";
 		assigned-clocks = <&cru SCLK_UPHY0_TCPDCORE>;
 		assigned-clock-rates = <50000000>;
+		power-domains = <&power RK3399_PD_TCPD0>;
 		resets = <&cru SRST_UPHY0>,
 			 <&cru SRST_UPHY0_PIPE_L00>,
 			 <&cru SRST_P_UPHY0_TCPHY>;
@@ -1179,6 +1228,7 @@
 		clock-names = "tcpdcore", "tcpdphy-ref";
 		assigned-clocks = <&cru SCLK_UPHY1_TCPDCORE>;
 		assigned-clock-rates = <50000000>;
+		power-domains = <&power RK3399_PD_TCPD1>;
 		resets = <&cru SRST_UPHY1>,
 			 <&cru SRST_UPHY1_PIPE_L00>,
 			 <&cru SRST_P_UPHY1_TCPHY>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/rockchip/rk3399-evb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,46 @@
 	compatible = "rockchip,rk3399-evb", "rockchip,rk3399",
 		     "google,rk3399evb-rev2";
 
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <
+			  0   1   2   3   4   5   6   7
+			  8   9  10  11  12  13  14  15
+			 16  17  18  19  20  21  22  23
+			 24  25  26  27  28  29  30  31
+			 32  33  34  35  36  37  38  39
+			 40  41  42  43  44  45  46  47
+			 48  49  50  51  52  53  54  55
+			 56  57  58  59  60  61  62  63
+			 64  65  66  67  68  69  70  71
+			 72  73  74  75  76  77  78  79
+			 80  81  82  83  84  85  86  87
+			 88  89  90  91  92  93  94  95
+			 96  97  98  99 100 101 102 103
+			104 105 106 107 108 109 110 111
+			112 113 114 115 116 117 118 119
+			120 121 122 123 124 125 126 127
+			128 129 130 131 132 133 134 135
+			136 137 138 139 140 141 142 143
+			144 145 146 147 148 149 150 151
+			152 153 154 155 156 157 158 159
+			160 161 162 163 164 165 166 167
+			168 169 170 171 172 173 174 175
+			176 177 178 179 180 181 182 183
+			184 185 186 187 188 189 190 191
+			192 193 194 195 196 197 198 199
+			200 201 202 203 204 205 206 207
+			208 209 210 211 212 213 214 215
+			216 217 218 219 220 221 222 223
+			224 225 226 227 228 229 230 231
+			232 233 234 235 236 237 238 239
+			240 241 242 243 244 245 246 247
+			248 249 250 251 252 253 254 255>;
+		default-brightness-level = <200>;
+		enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+		pwms = <&pwm0 0 25000 0>;
+	};
+
 	clkin_gmac: external-gmac-clock {
 		compatible = "fixed-clock";
 		clock-frequency = <125000000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/memreserve/ 0x80000000 0x00000008;	/* cpu-release-addr */
+/memreserve/ 0x80000000 0x00080000;
 
 / {
 	compatible = "socionext,uniphier-ld11";
@@ -70,19 +70,60 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0 0x000>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x80000000>;
+			clocks = <&sys_clk 33>;
+			enable-method = "psci";
+			operating-points-v2 = <&cluster0_opp>;
 		};
 
 		cpu1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0 0x001>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x80000000>;
+			clocks = <&sys_clk 33>;
+			enable-method = "psci";
+			operating-points-v2 = <&cluster0_opp>;
 		};
 	};
 
+	cluster0_opp: opp_table {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@245000000 {
+			opp-hz = /bits/ 64 <245000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@250000000 {
+			opp-hz = /bits/ 64 <250000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@490000000 {
+			opp-hz = /bits/ 64 <490000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@653334000 {
+			opp-hz = /bits/ 64 <653334000>;
+			clock-latency-ns = <300>;
+		};
+		opp@666667000 {
+			opp-hz = /bits/ 64 <666667000>;
+			clock-latency-ns = <300>;
+		};
+		opp@980000000 {
+			opp-hz = /bits/ 64 <980000000>;
+			clock-latency-ns = <300>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
 	clocks {
 		refclk: ref {
 			compatible = "fixed-clock";
@@ -233,7 +274,7 @@
 		};
 
 		perictrl@59820000 {
-			compatible = "socionext,uniphier-perictrl",
+			compatible = "socionext,uniphier-ld11-perictrl",
 				     "simple-mfd", "syscon";
 			reg = <0x59820000 0x200>;
 
@@ -282,7 +323,7 @@
 		};
 
 		mioctrl@5b3e0000 {
-			compatible = "socionext,uniphier-mioctrl",
+			compatible = "socionext,uniphier-ld11-mioctrl",
 				     "simple-mfd", "syscon";
 			reg = <0x5b3e0000 0x800>;
 
@@ -299,7 +340,7 @@
 		};
 
 		soc-glue@5f800000 {
-			compatible = "socionext,uniphier-soc-glue",
+			compatible = "socionext,uniphier-ld11-soc-glue",
 				     "simple-mfd", "syscon";
 			reg = <0x5f800000 0x2000>;
 
@@ -320,7 +361,7 @@
 		sysctrl@61840000 {
 			compatible = "socionext,uniphier-ld11-sysctrl",
 				     "simple-mfd", "syscon";
-			reg = <0x61840000 0x4000>;
+			reg = <0x61840000 0x10000>;
 
 			sys_clk: clock {
 				compatible = "socionext,uniphier-ld11-clock";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/memreserve/ 0x80000000 0x00000008;	/* cpu-release-addr */
+/memreserve/ 0x80000000 0x00080000;
 
 / {
 	compatible = "socionext,uniphier-ld20";
@@ -79,35 +79,120 @@
 			device_type = "cpu";
 			compatible = "arm,cortex-a72", "arm,armv8";
 			reg = <0 0x000>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x80000000>;
+			clocks = <&sys_clk 32>;
+			enable-method = "psci";
+			operating-points-v2 = <&cluster0_opp>;
 		};
 
 		cpu1: cpu@1 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a72", "arm,armv8";
 			reg = <0 0x001>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x80000000>;
+			clocks = <&sys_clk 32>;
+			enable-method = "psci";
+			operating-points-v2 = <&cluster0_opp>;
 		};
 
 		cpu2: cpu@100 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0 0x100>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x80000000>;
+			clocks = <&sys_clk 33>;
+			enable-method = "psci";
+			operating-points-v2 = <&cluster1_opp>;
 		};
 
 		cpu3: cpu@101 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53", "arm,armv8";
 			reg = <0 0x101>;
-			enable-method = "spin-table";
-			cpu-release-addr = <0 0x80000000>;
+			clocks = <&sys_clk 33>;
+			enable-method = "psci";
+			operating-points-v2 = <&cluster1_opp>;
 		};
 	};
 
+	cluster0_opp: opp_table0 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@250000000 {
+			opp-hz = /bits/ 64 <250000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@275000000 {
+			opp-hz = /bits/ 64 <275000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@550000000 {
+			opp-hz = /bits/ 64 <550000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@666667000 {
+			opp-hz = /bits/ 64 <666667000>;
+			clock-latency-ns = <300>;
+		};
+		opp@733334000 {
+			opp-hz = /bits/ 64 <733334000>;
+			clock-latency-ns = <300>;
+		};
+		opp@1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@1100000000 {
+			opp-hz = /bits/ 64 <1100000000>;
+			clock-latency-ns = <300>;
+		};
+	};
+
+	cluster1_opp: opp_table1 {
+		compatible = "operating-points-v2";
+		opp-shared;
+
+		opp@250000000 {
+			opp-hz = /bits/ 64 <250000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@275000000 {
+			opp-hz = /bits/ 64 <275000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@500000000 {
+			opp-hz = /bits/ 64 <500000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@550000000 {
+			opp-hz = /bits/ 64 <550000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@666667000 {
+			opp-hz = /bits/ 64 <666667000>;
+			clock-latency-ns = <300>;
+		};
+		opp@733334000 {
+			opp-hz = /bits/ 64 <733334000>;
+			clock-latency-ns = <300>;
+		};
+		opp@1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			clock-latency-ns = <300>;
+		};
+		opp@1100000000 {
+			opp-hz = /bits/ 64 <1100000000>;
+			clock-latency-ns = <300>;
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
 	clocks {
 		refclk: ref {
 			compatible = "fixed-clock";
@@ -274,7 +359,7 @@
 		};
 
 		perictrl@59820000 {
-			compatible = "socionext,uniphier-perictrl",
+			compatible = "socionext,uniphier-ld20-perictrl",
 				     "simple-mfd", "syscon";
 			reg = <0x59820000 0x200>;
 
@@ -290,7 +375,7 @@
 		};
 
 		soc-glue@5f800000 {
-			compatible = "socionext,uniphier-soc-glue",
+			compatible = "socionext,uniphier-ld20-soc-glue",
 				     "simple-mfd", "syscon";
 			reg = <0x5f800000 0x2000>;
 
@@ -309,9 +394,9 @@
 		};
 
 		sysctrl@61840000 {
-			compatible = "socionext,uniphier-sysctrl",
+			compatible = "socionext,uniphier-ld20-sysctrl",
 				     "simple-mfd", "syscon";
-			reg = <0x61840000 0x4000>;
+			reg = <0x61840000 0x10000>;
 
 			sys_clk: clock {
 				compatible = "socionext,uniphier-ld20-clock";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/xilinx/zynqmp.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/xilinx/zynqmp.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/xilinx/zynqmp.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,7 @@
 			     <1 10 0xf08>;
 	};
 
-	amba_apu {
+	amba_apu: amba_apu@0 {
 		compatible = "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <1>;
@@ -175,7 +175,7 @@
 		};
 
 		i2c0: i2c@ff020000 {
-			compatible = "cdns,i2c-r1p10";
+			compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 17 4>;
@@ -185,7 +185,7 @@
 		};
 
 		i2c1: i2c@ff030000 {
-			compatible = "cdns,i2c-r1p10";
+			compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 18 4>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x0 0x0 0x0 0x40000000>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/boot/dts/zte/zx296718.dtsi linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/zte/zx296718.dtsi
--- linux-libre-4.9-gnu/arch/arm64/boot/dts/zte/zx296718.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/boot/dts/zte/zx296718.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -239,16 +239,9 @@
 		compatible = "arm,gic-v3";
 		#interrupt-cells = <3>;
 		#address-cells = <0>;
-		#redistributor-regions = <6>;
-		redistributor-stride = <0x0 0x40000>;
 		interrupt-controller;
 		reg = <0x02a00000 0x10000>,
-		      <0x02b00000 0x20000>,
-		      <0x02b20000 0x20000>,
-		      <0x02b40000 0x20000>,
-		      <0x02b60000 0x20000>,
-		      <0x02b80000 0x20000>,
-		      <0x02ba0000 0x20000>;
+		      <0x02b00000 0xc0000>;
 		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
@@ -284,9 +277,33 @@
 			dma-requests = <32>;
 		};
 
+		lsp0crm: clock-controller@1420000 {
+			compatible = "zte,zx296718-lsp0crm";
+			reg = <0x01420000 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		lsp1crm: clock-controller@1430000 {
+			compatible = "zte,zx296718-lsp1crm";
+			reg = <0x01430000 0x1000>;
+			#clock-cells = <1>;
+		};
+
+		topcrm: clock-controller@1461000 {
+			compatible = "zte,zx296718-topcrm";
+			reg = <0x01461000 0x1000>;
+			#clock-cells = <1>;
+		};
+
 		sysctrl: sysctrl@1463000 {
 			compatible = "zte,zx296718-sysctrl", "syscon";
 			reg = <0x1463000 0x1000>;
 		};
+
+		audiocrm: clock-controller@1480000 {
+			compatible = "zte,zx296718-audiocrm";
+			reg = <0x01480000 0x1000>;
+			#clock-cells = <1>;
+		};
 	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/configs/defconfig linux-libre-4.10-rc8-gnu/arch/arm64/configs/defconfig
--- linux-libre-4.9-gnu/arch/arm64/configs/defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/configs/defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,6 @@ CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_BLK_CGROUP=y
@@ -34,6 +33,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_SUNXI=y
 CONFIG_ARCH_ALPINE=y
+CONFIG_ARCH_BCM2835=y
 CONFIG_ARCH_BCM_IPROC=y
 CONFIG_ARCH_BERLIN=y
 CONFIG_ARCH_EXYNOS=y
@@ -82,6 +82,7 @@ CONFIG_KEXEC=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
 CONFIG_CPU_IDLE=y
+CONFIG_HIBERNATION=y
 CONFIG_ARM_CPUIDLE=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPUFREQ_DT=y
@@ -147,6 +148,7 @@ CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
 CONFIG_VIRTIO_BLK=y
+CONFIG_EEPROM_AT25=m
 CONFIG_SRAM=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
@@ -183,7 +185,10 @@ CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=m
 CONFIG_REALTEK_PHY=m
+CONFIG_MESON_GXL_PHY=m
 CONFIG_MICREL_PHY=y
+CONFIG_MDIO_BUS_MUX=y
+CONFIG_MDIO_BUS_MUX_MMIOREG=y
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_RTL8152=m
@@ -194,6 +199,7 @@ CONFIG_USB_NET_SMSC75XX=m
 CONFIG_USB_NET_SMSC95XX=m
 CONFIG_USB_NET_PLUSB=m
 CONFIG_USB_NET_MCS7830=m
+CONFIG_BRCMFMAC=m
 CONFIG_WL18XX=m
 CONFIG_WLCORE_SDIO=m
 CONFIG_INPUT_EVDEV=y
@@ -206,6 +212,9 @@ CONFIG_SERIO_AMBAKMI=y
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_BCM2835AUX=y
 CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_8250_MT6577=y
 CONFIG_SERIAL_8250_UNIPHIER=y
@@ -229,17 +238,21 @@ CONFIG_VIRTIO_CONSOLE=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MUX=y
 CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_BCM2835=m
 CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_I2C_IMX=y
 CONFIG_I2C_MESON=y
 CONFIG_I2C_MV64XXX=y
 CONFIG_I2C_QUP=y
+CONFIG_I2C_RK3X=y
 CONFIG_I2C_TEGRA=y
 CONFIG_I2C_UNIPHIER_F=y
 CONFIG_I2C_RCAR=y
 CONFIG_I2C_CROS_EC_TUNNEL=y
 CONFIG_SPI=y
 CONFIG_SPI_MESON_SPIFC=m
+CONFIG_SPI_BCM2835=m
+CONFIG_SPI_BCM2835AUX=m
 CONFIG_SPI_ORION=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_QUP=y
@@ -249,14 +262,15 @@ CONFIG_SPMI=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_PINCTRL_MAX77620=y
 CONFIG_PINCTRL_MSM8916=y
+CONFIG_PINCTRL_MSM8994=y
 CONFIG_PINCTRL_MSM8996=y
 CONFIG_PINCTRL_QDF2XXX=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
-CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_DWAPB=y
 CONFIG_GPIO_PL061=y
 CONFIG_GPIO_RCAR=y
 CONFIG_GPIO_XGENE=y
+CONFIG_GPIO_XGENE_SB=y
 CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_MAX77620=y
@@ -271,13 +285,16 @@ CONFIG_THERMAL=y
 CONFIG_THERMAL_EMULATION=y
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
 CONFIG_CPU_THERMAL=y
+CONFIG_BCM2835_THERMAL=y
 CONFIG_EXYNOS_THERMAL=y
 CONFIG_WATCHDOG=y
+CONFIG_BCM2835_WDT=y
 CONFIG_RENESAS_WDT=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_MESON_GXBB_WATCHDOG=m
 CONFIG_MESON_WATCHDOG=m
 CONFIG_MFD_MAX77620=y
+CONFIG_MFD_RK808=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_MFD_SEC_CORE=y
 CONFIG_MFD_HI655X_PMIC=y
@@ -291,13 +308,30 @@ CONFIG_REGULATOR_MAX77620=y
 CONFIG_REGULATOR_PWM=y
 CONFIG_REGULATOR_QCOM_SMD_RPM=y
 CONFIG_REGULATOR_QCOM_SPMI=y
+CONFIG_REGULATOR_RK808=y
 CONFIG_REGULATOR_S2MPS11=y
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+# CONFIG_DVB_NET is not set
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_RENESAS_FCP=m
+CONFIG_VIDEO_RENESAS_VSP1=m
 CONFIG_DRM=m
 CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_RCAR_DU=m
+CONFIG_DRM_RCAR_HDMI=y
+CONFIG_DRM_RCAR_LVDS=y
+CONFIG_DRM_RCAR_VSP=y
 CONFIG_DRM_TEGRA=m
+CONFIG_DRM_VC4=m
 CONFIG_DRM_PANEL_SIMPLE=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_HISI_KIRIN=m
+CONFIG_DRM_MESON=m
 CONFIG_FB=y
 CONFIG_FB_ARMCLCD=y
 CONFIG_BACKLIGHT_GENERIC=m
@@ -309,6 +343,7 @@ CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
+CONFIG_SND_BCM2835_SOC_I2S=m
 CONFIG_SND_SOC_RCAR=y
 CONFIG_SND_SOC_SAMSUNG=y
 CONFIG_SND_SOC_AK4613=y
@@ -341,9 +376,11 @@ CONFIG_USB_RENESAS_USBHS_UDC=m
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_ARMMMCI=y
+CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ACPI=y
 CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
 CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_MMC_SDHCI_TEGRA=y
 CONFIG_MMC_SDHCI_MSM=y
@@ -352,6 +389,7 @@ CONFIG_MMC_SDHI=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_EXYNOS=y
 CONFIG_MMC_DW_K3=y
+CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SUNXI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -367,11 +405,13 @@ CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_EFI=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_RTC_DRV_SUN6I=y
+CONFIG_RTC_DRV_RK808=m
 CONFIG_RTC_DRV_TEGRA=y
 CONFIG_RTC_DRV_XGENE=y
 CONFIG_RTC_DRV_S3C=y
 CONFIG_DMADEVICES=y
 CONFIG_PL330_DMA=y
+CONFIG_DMA_BCM2835=m
 CONFIG_TEGRA20_APB_DMA=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_QCOM_HIDMA_MGMT=y
@@ -387,26 +427,39 @@ CONFIG_XEN_GRANT_DEV_ALLOC=y
 CONFIG_COMMON_CLK_SCPI=y
 CONFIG_COMMON_CLK_CS2000_CP=y
 CONFIG_COMMON_CLK_S2MPS11=y
+CONFIG_COMMON_CLK_PWM=y
+CONFIG_COMMON_CLK_RK808=y
 CONFIG_CLK_QORIQ=y
 CONFIG_COMMON_CLK_QCOM=y
 CONFIG_MSM_GCC_8916=y
+CONFIG_MSM_GCC_8994=y
 CONFIG_MSM_MMCC_8996=y
 CONFIG_HWSPINLOCK_QCOM=y
 CONFIG_MAILBOX=y
 CONFIG_ARM_MHU=y
+CONFIG_PLATFORM_MHU=y
+CONFIG_BCM2835_MBOX=y
 CONFIG_HI6220_MBOX=y
 CONFIG_ARM_SMMU=y
+CONFIG_RASPBERRYPI_POWER=y
 CONFIG_QCOM_SMEM=y
 CONFIG_QCOM_SMD=y
 CONFIG_QCOM_SMD_RPM=y
+CONFIG_ROCKCHIP_PM_DOMAINS=y
 CONFIG_ARCH_TEGRA_132_SOC=y
 CONFIG_ARCH_TEGRA_210_SOC=y
+CONFIG_ARCH_TEGRA_186_SOC=y
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_PWM=y
+CONFIG_PWM_BCM2835=m
+CONFIG_PWM_ROCKCHIP=y
 CONFIG_PWM_TEGRA=m
+CONFIG_PWM_MESON=m
 CONFIG_COMMON_RESET_HI6220=y
 CONFIG_PHY_RCAR_GEN3_USB2=y
 CONFIG_PHY_HI6220_USB=y
+CONFIG_PHY_ROCKCHIP_INNO_USB2=y
+CONFIG_PHY_ROCKCHIP_EMMC=y
 CONFIG_PHY_XGENE=y
 CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_ARM_SCPI_PROTOCOL=y
@@ -414,6 +467,7 @@ CONFIG_ACPI=y
 CONFIG_IIO=y
 CONFIG_EXYNOS_ADC=y
 CONFIG_PWM_SAMSUNG=y
+CONFIG_RASPBERRYPI_FIRMWARE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce-ccm-core.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce-ccm-core.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce-ccm-core.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce-ccm-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 	.text
 	.arch	armv8-a+crypto
@@ -19,7 +20,7 @@
 	 */
 ENTRY(ce_aes_ccm_auth_data)
 	ldr	w8, [x3]			/* leftover from prev round? */
-	ld1	{v0.2d}, [x0]			/* load mac */
+	ld1	{v0.16b}, [x0]			/* load mac */
 	cbz	w8, 1f
 	sub	w8, w8, #16
 	eor	v1.16b, v1.16b, v1.16b
@@ -31,7 +32,7 @@ ENTRY(ce_aes_ccm_auth_data)
 	beq	8f				/* out of input? */
 	cbnz	w8, 0b
 	eor	v0.16b, v0.16b, v1.16b
-1:	ld1	{v3.2d}, [x4]			/* load first round key */
+1:	ld1	{v3.16b}, [x4]			/* load first round key */
 	prfm	pldl1strm, [x1]
 	cmp	w5, #12				/* which key size? */
 	add	x6, x4, #16
@@ -41,17 +42,17 @@ ENTRY(ce_aes_ccm_auth_data)
 	mov	v5.16b, v3.16b
 	b	4f
 2:	mov	v4.16b, v3.16b
-	ld1	{v5.2d}, [x6], #16		/* load 2nd round key */
+	ld1	{v5.16b}, [x6], #16		/* load 2nd round key */
 3:	aese	v0.16b, v4.16b
 	aesmc	v0.16b, v0.16b
-4:	ld1	{v3.2d}, [x6], #16		/* load next round key */
+4:	ld1	{v3.16b}, [x6], #16		/* load next round key */
 	aese	v0.16b, v5.16b
 	aesmc	v0.16b, v0.16b
-5:	ld1	{v4.2d}, [x6], #16		/* load next round key */
+5:	ld1	{v4.16b}, [x6], #16		/* load next round key */
 	subs	w7, w7, #3
 	aese	v0.16b, v3.16b
 	aesmc	v0.16b, v0.16b
-	ld1	{v5.2d}, [x6], #16		/* load next round key */
+	ld1	{v5.16b}, [x6], #16		/* load next round key */
 	bpl	3b
 	aese	v0.16b, v4.16b
 	subs	w2, w2, #16			/* last data? */
@@ -60,7 +61,7 @@ ENTRY(ce_aes_ccm_auth_data)
 	ld1	{v1.16b}, [x1], #16		/* load next input block */
 	eor	v0.16b, v0.16b, v1.16b		/* xor with mac */
 	bne	1b
-6:	st1	{v0.2d}, [x0]			/* store mac */
+6:	st1	{v0.16b}, [x0]			/* store mac */
 	beq	10f
 	adds	w2, w2, #16
 	beq	10f
@@ -79,7 +80,7 @@ ENTRY(ce_aes_ccm_auth_data)
 	adds	w7, w7, #1
 	bne	9b
 	eor	v0.16b, v0.16b, v1.16b
-	st1	{v0.2d}, [x0]
+	st1	{v0.16b}, [x0]
 10:	str	w8, [x3]
 	ret
 ENDPROC(ce_aes_ccm_auth_data)
@@ -89,27 +90,27 @@ ENDPROC(ce_aes_ccm_auth_data)
 	 * 			 u32 rounds);
 	 */
 ENTRY(ce_aes_ccm_final)
-	ld1	{v3.2d}, [x2], #16		/* load first round key */
-	ld1	{v0.2d}, [x0]			/* load mac */
+	ld1	{v3.16b}, [x2], #16		/* load first round key */
+	ld1	{v0.16b}, [x0]			/* load mac */
 	cmp	w3, #12				/* which key size? */
 	sub	w3, w3, #2			/* modified # of rounds */
-	ld1	{v1.2d}, [x1]			/* load 1st ctriv */
+	ld1	{v1.16b}, [x1]			/* load 1st ctriv */
 	bmi	0f
 	bne	3f
 	mov	v5.16b, v3.16b
 	b	2f
 0:	mov	v4.16b, v3.16b
-1:	ld1	{v5.2d}, [x2], #16		/* load next round key */
+1:	ld1	{v5.16b}, [x2], #16		/* load next round key */
 	aese	v0.16b, v4.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v4.16b
 	aesmc	v1.16b, v1.16b
-2:	ld1	{v3.2d}, [x2], #16		/* load next round key */
+2:	ld1	{v3.16b}, [x2], #16		/* load next round key */
 	aese	v0.16b, v5.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v5.16b
 	aesmc	v1.16b, v1.16b
-3:	ld1	{v4.2d}, [x2], #16		/* load next round key */
+3:	ld1	{v4.16b}, [x2], #16		/* load next round key */
 	subs	w3, w3, #3
 	aese	v0.16b, v3.16b
 	aesmc	v0.16b, v0.16b
@@ -120,47 +121,47 @@ ENTRY(ce_aes_ccm_final)
 	aese	v1.16b, v4.16b
 	/* final round key cancels out */
 	eor	v0.16b, v0.16b, v1.16b		/* en-/decrypt the mac */
-	st1	{v0.2d}, [x0]			/* store result */
+	st1	{v0.16b}, [x0]			/* store result */
 	ret
 ENDPROC(ce_aes_ccm_final)
 
 	.macro	aes_ccm_do_crypt,enc
 	ldr	x8, [x6, #8]			/* load lower ctr */
-	ld1	{v0.2d}, [x5]			/* load mac */
-	rev	x8, x8				/* keep swabbed ctr in reg */
+	ld1	{v0.16b}, [x5]			/* load mac */
+CPU_LE(	rev	x8, x8			)	/* keep swabbed ctr in reg */
 0:	/* outer loop */
-	ld1	{v1.1d}, [x6]			/* load upper ctr */
+	ld1	{v1.8b}, [x6]			/* load upper ctr */
 	prfm	pldl1strm, [x1]
 	add	x8, x8, #1
 	rev	x9, x8
 	cmp	w4, #12				/* which key size? */
 	sub	w7, w4, #2			/* get modified # of rounds */
 	ins	v1.d[1], x9			/* no carry in lower ctr */
-	ld1	{v3.2d}, [x3]			/* load first round key */
+	ld1	{v3.16b}, [x3]			/* load first round key */
 	add	x10, x3, #16
 	bmi	1f
 	bne	4f
 	mov	v5.16b, v3.16b
 	b	3f
 1:	mov	v4.16b, v3.16b
-	ld1	{v5.2d}, [x10], #16		/* load 2nd round key */
+	ld1	{v5.16b}, [x10], #16		/* load 2nd round key */
 2:	/* inner loop: 3 rounds, 2x interleaved */
 	aese	v0.16b, v4.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v4.16b
 	aesmc	v1.16b, v1.16b
-3:	ld1	{v3.2d}, [x10], #16		/* load next round key */
+3:	ld1	{v3.16b}, [x10], #16		/* load next round key */
 	aese	v0.16b, v5.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v5.16b
 	aesmc	v1.16b, v1.16b
-4:	ld1	{v4.2d}, [x10], #16		/* load next round key */
+4:	ld1	{v4.16b}, [x10], #16		/* load next round key */
 	subs	w7, w7, #3
 	aese	v0.16b, v3.16b
 	aesmc	v0.16b, v0.16b
 	aese	v1.16b, v3.16b
 	aesmc	v1.16b, v1.16b
-	ld1	{v5.2d}, [x10], #16		/* load next round key */
+	ld1	{v5.16b}, [x10], #16		/* load next round key */
 	bpl	2b
 	aese	v0.16b, v4.16b
 	aese	v1.16b, v4.16b
@@ -177,14 +178,14 @@ ENDPROC(ce_aes_ccm_final)
 	eor	v0.16b, v0.16b, v2.16b		/* xor mac with pt ^ rk[last] */
 	st1	{v1.16b}, [x0], #16		/* write output block */
 	bne	0b
-	rev	x8, x8
-	st1	{v0.2d}, [x5]			/* store mac */
+CPU_LE(	rev	x8, x8			)
+	st1	{v0.16b}, [x5]			/* store mac */
 	str	x8, [x6, #8]			/* store lsb end of ctr (BE) */
 5:	ret
 
 6:	eor	v0.16b, v0.16b, v5.16b		/* final round mac */
 	eor	v1.16b, v1.16b, v5.16b		/* final round enc */
-	st1	{v0.2d}, [x5]			/* store mac */
+	st1	{v0.16b}, [x5]			/* store mac */
 	add	w2, w2, #16			/* process partial tail block */
 7:	ldrb	w9, [x1], #1			/* get 1 byte of input */
 	umov	w6, v1.b[0]			/* get top crypted ctr byte */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce-ccm-glue.c linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce-ccm-glue.c
--- linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce-ccm-glue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce-ccm-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,9 +11,9 @@
 #include <asm/neon.h>
 #include <asm/unaligned.h>
 #include <crypto/aes.h>
-#include <crypto/algapi.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/module.h>
 
 #include "aes-ce-setkey.h"
@@ -149,12 +149,7 @@ static int ccm_encrypt(struct aead_reque
 {
 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead);
-	struct blkcipher_desc desc = { .info = req->iv };
-	struct blkcipher_walk walk;
-	struct scatterlist srcbuf[2];
-	struct scatterlist dstbuf[2];
-	struct scatterlist *src;
-	struct scatterlist *dst;
+	struct skcipher_walk walk;
 	u8 __aligned(8) mac[AES_BLOCK_SIZE];
 	u8 buf[AES_BLOCK_SIZE];
 	u32 len = req->cryptlen;
@@ -172,27 +167,19 @@ static int ccm_encrypt(struct aead_reque
 	/* preserve the original iv for the final round */
 	memcpy(buf, req->iv, AES_BLOCK_SIZE);
 
-	src = scatterwalk_ffwd(srcbuf, req->src, req->assoclen);
-	dst = src;
-	if (req->src != req->dst)
-		dst = scatterwalk_ffwd(dstbuf, req->dst, req->assoclen);
-
-	blkcipher_walk_init(&walk, dst, src, len);
-	err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
-					     AES_BLOCK_SIZE);
+	err = skcipher_walk_aead_encrypt(&walk, req, true);
 
 	while (walk.nbytes) {
 		u32 tail = walk.nbytes % AES_BLOCK_SIZE;
 
-		if (walk.nbytes == len)
+		if (walk.nbytes == walk.total)
 			tail = 0;
 
 		ce_aes_ccm_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   walk.nbytes - tail, ctx->key_enc,
 				   num_rounds(ctx), mac, walk.iv);
 
-		len -= walk.nbytes - tail;
-		err = blkcipher_walk_done(&desc, &walk, tail);
+		err = skcipher_walk_done(&walk, tail);
 	}
 	if (!err)
 		ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx));
@@ -203,7 +190,7 @@ static int ccm_encrypt(struct aead_reque
 		return err;
 
 	/* copy authtag to end of dst */
-	scatterwalk_map_and_copy(mac, dst, req->cryptlen,
+	scatterwalk_map_and_copy(mac, req->dst, req->assoclen + req->cryptlen,
 				 crypto_aead_authsize(aead), 1);
 
 	return 0;
@@ -214,12 +201,7 @@ static int ccm_decrypt(struct aead_reque
 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct crypto_aes_ctx *ctx = crypto_aead_ctx(aead);
 	unsigned int authsize = crypto_aead_authsize(aead);
-	struct blkcipher_desc desc = { .info = req->iv };
-	struct blkcipher_walk walk;
-	struct scatterlist srcbuf[2];
-	struct scatterlist dstbuf[2];
-	struct scatterlist *src;
-	struct scatterlist *dst;
+	struct skcipher_walk walk;
 	u8 __aligned(8) mac[AES_BLOCK_SIZE];
 	u8 buf[AES_BLOCK_SIZE];
 	u32 len = req->cryptlen - authsize;
@@ -237,27 +219,19 @@ static int ccm_decrypt(struct aead_reque
 	/* preserve the original iv for the final round */
 	memcpy(buf, req->iv, AES_BLOCK_SIZE);
 
-	src = scatterwalk_ffwd(srcbuf, req->src, req->assoclen);
-	dst = src;
-	if (req->src != req->dst)
-		dst = scatterwalk_ffwd(dstbuf, req->dst, req->assoclen);
-
-	blkcipher_walk_init(&walk, dst, src, len);
-	err = blkcipher_aead_walk_virt_block(&desc, &walk, aead,
-					     AES_BLOCK_SIZE);
+	err = skcipher_walk_aead_decrypt(&walk, req, true);
 
 	while (walk.nbytes) {
 		u32 tail = walk.nbytes % AES_BLOCK_SIZE;
 
-		if (walk.nbytes == len)
+		if (walk.nbytes == walk.total)
 			tail = 0;
 
 		ce_aes_ccm_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				   walk.nbytes - tail, ctx->key_enc,
 				   num_rounds(ctx), mac, walk.iv);
 
-		len -= walk.nbytes - tail;
-		err = blkcipher_walk_done(&desc, &walk, tail);
+		err = skcipher_walk_done(&walk, tail);
 	}
 	if (!err)
 		ce_aes_ccm_final(mac, buf, ctx->key_enc, num_rounds(ctx));
@@ -268,7 +242,8 @@ static int ccm_decrypt(struct aead_reque
 		return err;
 
 	/* compare calculated auth tag with the stored one */
-	scatterwalk_map_and_copy(buf, src, req->cryptlen - authsize,
+	scatterwalk_map_and_copy(buf, req->src,
+				 req->assoclen + req->cryptlen - authsize,
 				 authsize, 0);
 
 	if (crypto_memneq(mac, buf, authsize))
@@ -287,6 +262,7 @@ static struct aead_alg ccm_aes_alg = {
 		.cra_module		= THIS_MODULE,
 	},
 	.ivsize		= AES_BLOCK_SIZE,
+	.chunksize	= AES_BLOCK_SIZE,
 	.maxauthsize	= AES_BLOCK_SIZE,
 	.setkey		= ccm_setkey,
 	.setauthsize	= ccm_setauthsize,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce-cipher.c linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce-cipher.c
--- linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce-cipher.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce-cipher.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,24 +47,24 @@ static void aes_cipher_encrypt(struct cr
 	kernel_neon_begin_partial(4);
 
 	__asm__("	ld1	{v0.16b}, %[in]			;"
-		"	ld1	{v1.2d}, [%[key]], #16		;"
+		"	ld1	{v1.16b}, [%[key]], #16		;"
 		"	cmp	%w[rounds], #10			;"
 		"	bmi	0f				;"
 		"	bne	3f				;"
 		"	mov	v3.16b, v1.16b			;"
 		"	b	2f				;"
 		"0:	mov	v2.16b, v1.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"1:	aese	v0.16b, v2.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"2:	ld1	{v1.2d}, [%[key]], #16		;"
+		"2:	ld1	{v1.16b}, [%[key]], #16		;"
 		"	aese	v0.16b, v3.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"3:	ld1	{v2.2d}, [%[key]], #16		;"
+		"3:	ld1	{v2.16b}, [%[key]], #16		;"
 		"	subs	%w[rounds], %w[rounds], #3	;"
 		"	aese	v0.16b, v1.16b			;"
 		"	aesmc	v0.16b, v0.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"	bpl	1b				;"
 		"	aese	v0.16b, v2.16b			;"
 		"	eor	v0.16b, v0.16b, v3.16b		;"
@@ -92,24 +92,24 @@ static void aes_cipher_decrypt(struct cr
 	kernel_neon_begin_partial(4);
 
 	__asm__("	ld1	{v0.16b}, %[in]			;"
-		"	ld1	{v1.2d}, [%[key]], #16		;"
+		"	ld1	{v1.16b}, [%[key]], #16		;"
 		"	cmp	%w[rounds], #10			;"
 		"	bmi	0f				;"
 		"	bne	3f				;"
 		"	mov	v3.16b, v1.16b			;"
 		"	b	2f				;"
 		"0:	mov	v2.16b, v1.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"1:	aesd	v0.16b, v2.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"2:	ld1	{v1.2d}, [%[key]], #16		;"
+		"2:	ld1	{v1.16b}, [%[key]], #16		;"
 		"	aesd	v0.16b, v3.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"3:	ld1	{v2.2d}, [%[key]], #16		;"
+		"3:	ld1	{v2.16b}, [%[key]], #16		;"
 		"	subs	%w[rounds], %w[rounds], #3	;"
 		"	aesd	v0.16b, v1.16b			;"
 		"	aesimc	v0.16b, v0.16b			;"
-		"	ld1	{v3.2d}, [%[key]], #16		;"
+		"	ld1	{v3.16b}, [%[key]], #16		;"
 		"	bpl	1b				;"
 		"	aesd	v0.16b, v2.16b			;"
 		"	eor	v0.16b, v0.16b, v3.16b		;"
@@ -173,7 +173,12 @@ int ce_aes_expandkey(struct crypto_aes_c
 		u32 *rki = ctx->key_enc + (i * kwords);
 		u32 *rko = rki + kwords;
 
+#ifndef CONFIG_CPU_BIG_ENDIAN
 		rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0];
+#else
+		rko[0] = rol32(aes_sub(rki[kwords - 1]), 8) ^ (rcon[i] << 24) ^
+			 rki[0];
+#endif
 		rko[1] = rko[0] ^ rki[1];
 		rko[2] = rko[1] ^ rki[2];
 		rko[3] = rko[2] ^ rki[3];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/aes-ce.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-ce.S	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #define AES_ENTRY(func)		ENTRY(ce_ ## func)
 #define AES_ENDPROC(func)	ENDPROC(ce_ ## func)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/aes-glue.c linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-glue.c
--- linux-libre-4.9-gnu/arch/arm64/crypto/aes-glue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,8 +11,8 @@
 #include <asm/neon.h>
 #include <asm/hwcap.h>
 #include <crypto/aes.h>
-#include <crypto/ablk_helper.h>
-#include <crypto/algapi.h>
+#include <crypto/internal/simd.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/module.h>
 #include <linux/cpufeature.h>
 #include <crypto/xts.h>
@@ -80,13 +80,19 @@ struct crypto_aes_xts_ctx {
 	struct crypto_aes_ctx __aligned(8) key2;
 };
 
-static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+static int skcipher_aes_setkey(struct crypto_skcipher *tfm, const u8 *in_key,
+			       unsigned int key_len)
+{
+	return aes_setkey(crypto_skcipher_tfm(tfm), in_key, key_len);
+}
+
+static int xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key,
 		       unsigned int key_len)
 {
-	struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int ret;
 
-	ret = xts_check_key(tfm, in_key, key_len);
+	ret = xts_verify_key(tfm, in_key, key_len);
 	if (ret)
 		return ret;
 
@@ -97,111 +103,101 @@ static int xts_set_key(struct crypto_tfm
 	if (!ret)
 		return 0;
 
-	tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+	crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 	return -EINVAL;
 }
 
-static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int ecb_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = 6 + ctx->key_length / 4;
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				(u8 *)ctx->key_enc, rounds, blocks, first);
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int ecb_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = 6 + ctx->key_length / 4;
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				(u8 *)ctx->key_dec, rounds, blocks, first);
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int cbc_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = 6 + ctx->key_length / 4;
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				(u8 *)ctx->key_enc, rounds, blocks, walk.iv,
 				first);
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int cbc_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = 6 + ctx->key_length / 4;
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				(u8 *)ctx->key_dec, rounds, blocks, walk.iv,
 				first);
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 	return err;
 }
 
-static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int ctr_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = 6 + ctx->key_length / 4;
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	first = 1;
 	kernel_neon_begin();
@@ -209,17 +205,14 @@ static int ctr_encrypt(struct blkcipher_
 		aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				(u8 *)ctx->key_enc, rounds, blocks, walk.iv,
 				first);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 		first = 0;
-		nbytes -= blocks * AES_BLOCK_SIZE;
-		if (nbytes && nbytes == walk.nbytes % AES_BLOCK_SIZE)
-			break;
-		err = blkcipher_walk_done(desc, &walk,
-					  walk.nbytes % AES_BLOCK_SIZE);
 	}
-	if (walk.nbytes % AES_BLOCK_SIZE) {
-		u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE;
-		u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE;
+	if (walk.nbytes) {
 		u8 __aligned(8) tail[AES_BLOCK_SIZE];
+		unsigned int nbytes = walk.nbytes;
+		u8 *tdst = walk.dst.virt.addr;
+		u8 *tsrc = walk.src.virt.addr;
 
 		/*
 		 * Minimum alignment is 8 bytes, so if nbytes is <= 8, we need
@@ -230,227 +223,169 @@ static int ctr_encrypt(struct blkcipher_
 		aes_ctr_encrypt(tail, tsrc, (u8 *)ctx->key_enc, rounds,
 				blocks, walk.iv, first);
 		memcpy(tdst, tail, nbytes);
-		err = blkcipher_walk_done(desc, &walk, 0);
+		err = skcipher_walk_done(&walk, 0);
 	}
 	kernel_neon_end();
 
 	return err;
 }
 
-static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int xts_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = 6 + ctx->key1.key_length / 4;
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				(u8 *)ctx->key1.key_enc, rounds, blocks,
 				(u8 *)ctx->key2.key_enc, walk.iv, first);
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 
 	return err;
 }
 
-static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int xts_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err, first, rounds = 6 + ctx->key1.key_length / 4;
-	struct blkcipher_walk walk;
+	struct skcipher_walk walk;
 	unsigned int blocks;
 
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_neon_begin();
 	for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) {
 		aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
 				(u8 *)ctx->key1.key_dec, rounds, blocks,
 				(u8 *)ctx->key2.key_enc, walk.iv, first);
-		err = blkcipher_walk_done(desc, &walk, walk.nbytes % AES_BLOCK_SIZE);
+		err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
 	}
 	kernel_neon_end();
 
 	return err;
 }
 
-static struct crypto_alg aes_algs[] = { {
-	.cra_name		= "__ecb-aes-" MODE,
-	.cra_driver_name	= "__driver-ecb-aes-" MODE,
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= 0,
-		.setkey		= aes_setkey,
-		.encrypt	= ecb_encrypt,
-		.decrypt	= ecb_decrypt,
+static struct skcipher_alg aes_algs[] = { {
+	.base = {
+		.cra_name		= "__ecb(aes)",
+		.cra_driver_name	= "__ecb-aes-" MODE,
+		.cra_priority		= PRIO,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.setkey		= skcipher_aes_setkey,
+	.encrypt	= ecb_encrypt,
+	.decrypt	= ecb_decrypt,
 }, {
-	.cra_name		= "__cbc-aes-" MODE,
-	.cra_driver_name	= "__driver-cbc-aes-" MODE,
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= aes_setkey,
-		.encrypt	= cbc_encrypt,
-		.decrypt	= cbc_decrypt,
+	.base = {
+		.cra_name		= "__cbc(aes)",
+		.cra_driver_name	= "__cbc-aes-" MODE,
+		.cra_priority		= PRIO,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.setkey		= skcipher_aes_setkey,
+	.encrypt	= cbc_encrypt,
+	.decrypt	= cbc_decrypt,
 }, {
-	.cra_name		= "__ctr-aes-" MODE,
-	.cra_driver_name	= "__driver-ctr-aes-" MODE,
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= aes_setkey,
-		.encrypt	= ctr_encrypt,
-		.decrypt	= ctr_encrypt,
+	.base = {
+		.cra_name		= "__ctr(aes)",
+		.cra_driver_name	= "__ctr-aes-" MODE,
+		.cra_priority		= PRIO,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= 1,
+		.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
+	.min_keysize	= AES_MIN_KEY_SIZE,
+	.max_keysize	= AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.chunksize	= AES_BLOCK_SIZE,
+	.setkey		= skcipher_aes_setkey,
+	.encrypt	= ctr_encrypt,
+	.decrypt	= ctr_encrypt,
 }, {
-	.cra_name		= "__xts-aes-" MODE,
-	.cra_driver_name	= "__driver-xts-aes-" MODE,
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_xts_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_blkcipher = {
-		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= xts_set_key,
-		.encrypt	= xts_encrypt,
-		.decrypt	= xts_decrypt,
+	.base = {
+		.cra_name		= "__xts(aes)",
+		.cra_driver_name	= "__xts-aes-" MODE,
+		.cra_priority		= PRIO,
+		.cra_flags		= CRYPTO_ALG_INTERNAL,
+		.cra_blocksize		= AES_BLOCK_SIZE,
+		.cra_ctxsize		= sizeof(struct crypto_aes_xts_ctx),
+		.cra_alignmask		= 7,
+		.cra_module		= THIS_MODULE,
 	},
-}, {
-	.cra_name		= "ecb(aes)",
-	.cra_driver_name	= "ecb-aes-" MODE,
-	.cra_priority		= PRIO,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= 0,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "cbc(aes)",
-	.cra_driver_name	= "cbc-aes-" MODE,
-	.cra_priority		= PRIO,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "ctr(aes)",
-	.cra_driver_name	= "ctr-aes-" MODE,
-	.cra_priority		= PRIO,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= AES_MIN_KEY_SIZE,
-		.max_keysize	= AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
-}, {
-	.cra_name		= "xts(aes)",
-	.cra_driver_name	= "xts-aes-" MODE,
-	.cra_priority		= PRIO,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 7,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_ablkcipher = {
-		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-		.ivsize		= AES_BLOCK_SIZE,
-		.setkey		= ablk_set_key,
-		.encrypt	= ablk_encrypt,
-		.decrypt	= ablk_decrypt,
-	}
+	.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+	.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+	.ivsize		= AES_BLOCK_SIZE,
+	.setkey		= xts_set_key,
+	.encrypt	= xts_encrypt,
+	.decrypt	= xts_decrypt,
 } };
 
-static int __init aes_init(void)
+static struct simd_skcipher_alg *aes_simd_algs[ARRAY_SIZE(aes_algs)];
+
+static void aes_exit(void)
 {
-	return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs));
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(aes_simd_algs) && aes_simd_algs[i]; i++)
+		simd_skcipher_free(aes_simd_algs[i]);
+
+	crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
 }
 
-static void __exit aes_exit(void)
+static int __init aes_init(void)
 {
-	crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
+	struct simd_skcipher_alg *simd;
+	const char *basename;
+	const char *algname;
+	const char *drvname;
+	int err;
+	int i;
+
+	err = crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs));
+	if (err)
+		return err;
+
+	for (i = 0; i < ARRAY_SIZE(aes_algs); i++) {
+		algname = aes_algs[i].base.cra_name + 2;
+		drvname = aes_algs[i].base.cra_driver_name + 2;
+		basename = aes_algs[i].base.cra_driver_name;
+		simd = simd_skcipher_create_compat(algname, drvname, basename);
+		err = PTR_ERR(simd);
+		if (IS_ERR(simd))
+			goto unregister_simds;
+
+		aes_simd_algs[i] = simd;
+	}
+
+	return 0;
+
+unregister_simds:
+	aes_exit();
+	return err;
 }
 
 #ifdef USE_V8_CRYPTO_EXTENSIONS
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/aes-modes.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-modes.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/aes-modes.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-modes.S	2017-02-12 16:03:20.000000000 -0500
@@ -193,15 +193,16 @@ AES_ENTRY(aes_cbc_encrypt)
 	cbz		w6, .Lcbcencloop
 
 	ld1		{v0.16b}, [x5]			/* get iv */
-	enc_prepare	w3, x2, x5
+	enc_prepare	w3, x2, x6
 
 .Lcbcencloop:
 	ld1		{v1.16b}, [x1], #16		/* get next pt block */
 	eor		v0.16b, v0.16b, v1.16b		/* ..and xor with iv */
-	encrypt_block	v0, w3, x2, x5, w6
+	encrypt_block	v0, w3, x2, x6, w7
 	st1		{v0.16b}, [x0], #16
 	subs		w4, w4, #1
 	bne		.Lcbcencloop
+	st1		{v0.16b}, [x5]			/* return iv */
 	ret
 AES_ENDPROC(aes_cbc_encrypt)
 
@@ -211,7 +212,7 @@ AES_ENTRY(aes_cbc_decrypt)
 	cbz		w6, .LcbcdecloopNx
 
 	ld1		{v7.16b}, [x5]			/* get iv */
-	dec_prepare	w3, x2, x5
+	dec_prepare	w3, x2, x6
 
 .LcbcdecloopNx:
 #if INTERLEAVE >= 2
@@ -248,7 +249,7 @@ AES_ENTRY(aes_cbc_decrypt)
 .Lcbcdecloop:
 	ld1		{v1.16b}, [x1], #16		/* get next ct block */
 	mov		v0.16b, v1.16b			/* ...and copy to v0 */
-	decrypt_block	v0, w3, x2, x5, w6
+	decrypt_block	v0, w3, x2, x6, w7
 	eor		v0.16b, v0.16b, v7.16b		/* xor with iv => pt */
 	mov		v7.16b, v1.16b			/* ct is next iv */
 	st1		{v0.16b}, [x0], #16
@@ -256,6 +257,7 @@ AES_ENTRY(aes_cbc_decrypt)
 	bne		.Lcbcdecloop
 .Lcbcdecout:
 	FRAME_POP
+	st1		{v7.16b}, [x5]			/* return iv */
 	ret
 AES_ENDPROC(aes_cbc_decrypt)
 
@@ -267,24 +269,15 @@ AES_ENDPROC(aes_cbc_decrypt)
 
 AES_ENTRY(aes_ctr_encrypt)
 	FRAME_PUSH
-	cbnz		w6, .Lctrfirst		/* 1st time around? */
-	umov		x5, v4.d[1]		/* keep swabbed ctr in reg */
-	rev		x5, x5
-#if INTERLEAVE >= 2
-	cmn		w5, w4			/* 32 bit overflow? */
-	bcs		.Lctrinc
-	add		x5, x5, #1		/* increment BE ctr */
-	b		.LctrincNx
-#else
-	b		.Lctrinc
-#endif
-.Lctrfirst:
+	cbz		w6, .Lctrnotfirst	/* 1st time around? */
 	enc_prepare	w3, x2, x6
 	ld1		{v4.16b}, [x5]
-	umov		x5, v4.d[1]		/* keep swabbed ctr in reg */
-	rev		x5, x5
+
+.Lctrnotfirst:
+	umov		x8, v4.d[1]		/* keep swabbed ctr in reg */
+	rev		x8, x8
 #if INTERLEAVE >= 2
-	cmn		w5, w4			/* 32 bit overflow? */
+	cmn		w8, w4			/* 32 bit overflow? */
 	bcs		.Lctrloop
 .LctrloopNx:
 	subs		w4, w4, #INTERLEAVE
@@ -292,11 +285,11 @@ AES_ENTRY(aes_ctr_encrypt)
 #if INTERLEAVE == 2
 	mov		v0.8b, v4.8b
 	mov		v1.8b, v4.8b
-	rev		x7, x5
-	add		x5, x5, #1
+	rev		x7, x8
+	add		x8, x8, #1
 	ins		v0.d[1], x7
-	rev		x7, x5
-	add		x5, x5, #1
+	rev		x7, x8
+	add		x8, x8, #1
 	ins		v1.d[1], x7
 	ld1		{v2.16b-v3.16b}, [x1], #32	/* get 2 input blocks */
 	do_encrypt_block2x
@@ -305,7 +298,7 @@ AES_ENTRY(aes_ctr_encrypt)
 	st1		{v0.16b-v1.16b}, [x0], #32
 #else
 	ldr		q8, =0x30000000200000001	/* addends 1,2,3[,0] */
-	dup		v7.4s, w5
+	dup		v7.4s, w8
 	mov		v0.16b, v4.16b
 	add		v7.4s, v7.4s, v8.4s
 	mov		v1.16b, v4.16b
@@ -323,18 +316,12 @@ AES_ENTRY(aes_ctr_encrypt)
 	eor		v2.16b, v7.16b, v2.16b
 	eor		v3.16b, v5.16b, v3.16b
 	st1		{v0.16b-v3.16b}, [x0], #64
-	add		x5, x5, #INTERLEAVE
+	add		x8, x8, #INTERLEAVE
 #endif
-	cbz		w4, .LctroutNx
-.LctrincNx:
-	rev		x7, x5
+	rev		x7, x8
 	ins		v4.d[1], x7
+	cbz		w4, .Lctrout
 	b		.LctrloopNx
-.LctroutNx:
-	sub		x5, x5, #1
-	rev		x7, x5
-	ins		v4.d[1], x7
-	b		.Lctrout
 .Lctr1x:
 	adds		w4, w4, #INTERLEAVE
 	beq		.Lctrout
@@ -342,30 +329,39 @@ AES_ENTRY(aes_ctr_encrypt)
 .Lctrloop:
 	mov		v0.16b, v4.16b
 	encrypt_block	v0, w3, x2, x6, w7
+
+	adds		x8, x8, #1		/* increment BE ctr */
+	rev		x7, x8
+	ins		v4.d[1], x7
+	bcs		.Lctrcarry		/* overflow? */
+
+.Lctrcarrydone:
 	subs		w4, w4, #1
 	bmi		.Lctrhalfblock		/* blocks < 0 means 1/2 block */
 	ld1		{v3.16b}, [x1], #16
 	eor		v3.16b, v0.16b, v3.16b
 	st1		{v3.16b}, [x0], #16
-	beq		.Lctrout
-.Lctrinc:
-	adds		x5, x5, #1		/* increment BE ctr */
-	rev		x7, x5
-	ins		v4.d[1], x7
-	bcc		.Lctrloop		/* no overflow? */
-	umov		x7, v4.d[0]		/* load upper word of ctr  */
-	rev		x7, x7			/* ... to handle the carry */
-	add		x7, x7, #1
-	rev		x7, x7
-	ins		v4.d[0], x7
-	b		.Lctrloop
+	bne		.Lctrloop
+
+.Lctrout:
+	st1		{v4.16b}, [x5]		/* return next CTR value */
+	FRAME_POP
+	ret
+
 .Lctrhalfblock:
 	ld1		{v3.8b}, [x1]
 	eor		v3.8b, v0.8b, v3.8b
 	st1		{v3.8b}, [x0]
-.Lctrout:
 	FRAME_POP
 	ret
+
+.Lctrcarry:
+	umov		x7, v4.d[0]		/* load upper word of ctr  */
+	rev		x7, x7			/* ... to handle the carry */
+	add		x7, x7, #1
+	rev		x7, x7
+	ins		v4.d[0], x7
+	b		.Lctrcarrydone
 AES_ENDPROC(aes_ctr_encrypt)
 	.ltorg
 
@@ -386,7 +382,8 @@ AES_ENDPROC(aes_ctr_encrypt)
 	.endm
 
 .Lxts_mul_x:
-	.word		1, 0, 0x87, 0
+CPU_LE(	.quad		1, 0x87		)
+CPU_BE(	.quad		0x87, 1		)
 
 AES_ENTRY(aes_xts_encrypt)
 	FRAME_PUSH
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/aes-neon.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-neon.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/aes-neon.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/aes-neon.S	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 
 #define AES_ENTRY(func)		ENTRY(neon_ ## func)
 #define AES_ENDPROC(func)	ENDPROC(neon_ ## func)
@@ -83,13 +84,13 @@
 	.endm
 
 	.macro		do_block, enc, in, rounds, rk, rkp, i
-	ld1		{v15.16b}, [\rk]
+	ld1		{v15.4s}, [\rk]
 	add		\rkp, \rk, #16
 	mov		\i, \rounds
 1111:	eor		\in\().16b, \in\().16b, v15.16b		/* ^round key */
 	tbl		\in\().16b, {\in\().16b}, v13.16b	/* ShiftRows */
 	sub_bytes	\in
-	ld1		{v15.16b}, [\rkp], #16
+	ld1		{v15.4s}, [\rkp], #16
 	subs		\i, \i, #1
 	beq		2222f
 	.if		\enc == 1
@@ -229,7 +230,7 @@
 	.endm
 
 	.macro		do_block_2x, enc, in0, in1 rounds, rk, rkp, i
-	ld1		{v15.16b}, [\rk]
+	ld1		{v15.4s}, [\rk]
 	add		\rkp, \rk, #16
 	mov		\i, \rounds
 1111:	eor		\in0\().16b, \in0\().16b, v15.16b	/* ^round key */
@@ -237,7 +238,7 @@
 	sub_bytes_2x	\in0, \in1
 	tbl		\in0\().16b, {\in0\().16b}, v13.16b	/* ShiftRows */
 	tbl		\in1\().16b, {\in1\().16b}, v13.16b	/* ShiftRows */
-	ld1		{v15.16b}, [\rkp], #16
+	ld1		{v15.4s}, [\rkp], #16
 	subs		\i, \i, #1
 	beq		2222f
 	.if		\enc == 1
@@ -254,7 +255,7 @@
 	.endm
 
 	.macro		do_block_4x, enc, in0, in1, in2, in3, rounds, rk, rkp, i
-	ld1		{v15.16b}, [\rk]
+	ld1		{v15.4s}, [\rk]
 	add		\rkp, \rk, #16
 	mov		\i, \rounds
 1111:	eor		\in0\().16b, \in0\().16b, v15.16b	/* ^round key */
@@ -266,7 +267,7 @@
 	tbl		\in1\().16b, {\in1\().16b}, v13.16b	/* ShiftRows */
 	tbl		\in2\().16b, {\in2\().16b}, v13.16b	/* ShiftRows */
 	tbl		\in3\().16b, {\in3\().16b}, v13.16b	/* ShiftRows */
-	ld1		{v15.16b}, [\rkp], #16
+	ld1		{v15.4s}, [\rkp], #16
 	subs		\i, \i, #1
 	beq		2222f
 	.if		\enc == 1
@@ -306,12 +307,16 @@
 	.text
 	.align		4
 .LForward_ShiftRows:
-	.byte		0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3
-	.byte		0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb
+CPU_LE(	.byte		0x0, 0x5, 0xa, 0xf, 0x4, 0x9, 0xe, 0x3	)
+CPU_LE(	.byte		0x8, 0xd, 0x2, 0x7, 0xc, 0x1, 0x6, 0xb	)
+CPU_BE(	.byte		0xb, 0x6, 0x1, 0xc, 0x7, 0x2, 0xd, 0x8	)
+CPU_BE(	.byte		0x3, 0xe, 0x9, 0x4, 0xf, 0xa, 0x5, 0x0	)
 
 .LReverse_ShiftRows:
-	.byte		0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb
-	.byte		0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3
+CPU_LE(	.byte		0x0, 0xd, 0xa, 0x7, 0x4, 0x1, 0xe, 0xb	)
+CPU_LE(	.byte		0x8, 0x5, 0x2, 0xf, 0xc, 0x9, 0x6, 0x3	)
+CPU_BE(	.byte		0x3, 0x6, 0x9, 0xc, 0xf, 0x2, 0x5, 0x8	)
+CPU_BE(	.byte		0xb, 0xe, 0x1, 0x4, 0x7, 0xa, 0xd, 0x0	)
 
 .LForward_Sbox:
 	.byte		0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/crc32-ce-core.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crc32-ce-core.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/crc32-ce-core.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crc32-ce-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,266 @@
+/*
+ * Accelerated CRC32(C) using arm64 CRC, NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+ */
+
+/* GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE 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 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see http://www.gnu.org/licenses
+ *
+ * Please  visit http://www.xyratex.com/contact if you need additional
+ * information or have any questions.
+ *
+ * GPL HEADER END
+ */
+
+/*
+ * Copyright 2012 Xyratex Technology Limited
+ *
+ * Using hardware provided PCLMULQDQ instruction to accelerate the CRC32
+ * calculation.
+ * CRC32 polynomial:0x04c11db7(BE)/0xEDB88320(LE)
+ * PCLMULQDQ is a new instruction in Intel SSE4.2, the reference can be found
+ * at:
+ * http://www.intel.com/products/processor/manuals/
+ * Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 2B: Instruction Set Reference, N-Z
+ *
+ * Authors:   Gregory Prestas <Gregory_Prestas@us.xyratex.com>
+ *	      Alexander Boyko <Alexander_Boyko@xyratex.com>
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+	.text
+	.align		6
+	.cpu		generic+crypto+crc
+
+.Lcrc32_constants:
+	/*
+	 * [x4*128+32 mod P(x) << 32)]'  << 1   = 0x154442bd4
+	 * #define CONSTANT_R1  0x154442bd4LL
+	 *
+	 * [(x4*128-32 mod P(x) << 32)]' << 1   = 0x1c6e41596
+	 * #define CONSTANT_R2  0x1c6e41596LL
+	 */
+	.octa		0x00000001c6e415960000000154442bd4
+
+	/*
+	 * [(x128+32 mod P(x) << 32)]'   << 1   = 0x1751997d0
+	 * #define CONSTANT_R3  0x1751997d0LL
+	 *
+	 * [(x128-32 mod P(x) << 32)]'   << 1   = 0x0ccaa009e
+	 * #define CONSTANT_R4  0x0ccaa009eLL
+	 */
+	.octa		0x00000000ccaa009e00000001751997d0
+
+	/*
+	 * [(x64 mod P(x) << 32)]'       << 1   = 0x163cd6124
+	 * #define CONSTANT_R5  0x163cd6124LL
+	 */
+	.quad		0x0000000163cd6124
+	.quad		0x00000000FFFFFFFF
+
+	/*
+	 * #define CRCPOLY_TRUE_LE_FULL 0x1DB710641LL
+	 *
+	 * Barrett Reduction constant (u64`) = u` = (x**64 / P(x))`
+	 *                                                      = 0x1F7011641LL
+	 * #define CONSTANT_RU  0x1F7011641LL
+	 */
+	.octa		0x00000001F701164100000001DB710641
+
+.Lcrc32c_constants:
+	.octa		0x000000009e4addf800000000740eef02
+	.octa		0x000000014cd00bd600000000f20c0dfe
+	.quad		0x00000000dd45aab8
+	.quad		0x00000000FFFFFFFF
+	.octa		0x00000000dea713f10000000105ec76f0
+
+	vCONSTANT	.req	v0
+	dCONSTANT	.req	d0
+	qCONSTANT	.req	q0
+
+	BUF		.req	x0
+	LEN		.req	x1
+	CRC		.req	x2
+
+	vzr		.req	v9
+
+	/**
+	 * Calculate crc32
+	 * BUF - buffer
+	 * LEN - sizeof buffer (multiple of 16 bytes), LEN should be > 63
+	 * CRC - initial crc32
+	 * return %eax crc32
+	 * uint crc32_pmull_le(unsigned char const *buffer,
+	 *                     size_t len, uint crc32)
+	 */
+ENTRY(crc32_pmull_le)
+	adr		x3, .Lcrc32_constants
+	b		0f
+
+ENTRY(crc32c_pmull_le)
+	adr		x3, .Lcrc32c_constants
+
+0:	bic		LEN, LEN, #15
+	ld1		{v1.16b-v4.16b}, [BUF], #0x40
+	movi		vzr.16b, #0
+	fmov		dCONSTANT, CRC
+	eor		v1.16b, v1.16b, vCONSTANT.16b
+	sub		LEN, LEN, #0x40
+	cmp		LEN, #0x40
+	b.lt		less_64
+
+	ldr		qCONSTANT, [x3]
+
+loop_64:		/* 64 bytes Full cache line folding */
+	sub		LEN, LEN, #0x40
+
+	pmull2		v5.1q, v1.2d, vCONSTANT.2d
+	pmull2		v6.1q, v2.2d, vCONSTANT.2d
+	pmull2		v7.1q, v3.2d, vCONSTANT.2d
+	pmull2		v8.1q, v4.2d, vCONSTANT.2d
+
+	pmull		v1.1q, v1.1d, vCONSTANT.1d
+	pmull		v2.1q, v2.1d, vCONSTANT.1d
+	pmull		v3.1q, v3.1d, vCONSTANT.1d
+	pmull		v4.1q, v4.1d, vCONSTANT.1d
+
+	eor		v1.16b, v1.16b, v5.16b
+	ld1		{v5.16b}, [BUF], #0x10
+	eor		v2.16b, v2.16b, v6.16b
+	ld1		{v6.16b}, [BUF], #0x10
+	eor		v3.16b, v3.16b, v7.16b
+	ld1		{v7.16b}, [BUF], #0x10
+	eor		v4.16b, v4.16b, v8.16b
+	ld1		{v8.16b}, [BUF], #0x10
+
+	eor		v1.16b, v1.16b, v5.16b
+	eor		v2.16b, v2.16b, v6.16b
+	eor		v3.16b, v3.16b, v7.16b
+	eor		v4.16b, v4.16b, v8.16b
+
+	cmp		LEN, #0x40
+	b.ge		loop_64
+
+less_64:		/* Folding cache line into 128bit */
+	ldr		qCONSTANT, [x3, #16]
+
+	pmull2		v5.1q, v1.2d, vCONSTANT.2d
+	pmull		v1.1q, v1.1d, vCONSTANT.1d
+	eor		v1.16b, v1.16b, v5.16b
+	eor		v1.16b, v1.16b, v2.16b
+
+	pmull2		v5.1q, v1.2d, vCONSTANT.2d
+	pmull		v1.1q, v1.1d, vCONSTANT.1d
+	eor		v1.16b, v1.16b, v5.16b
+	eor		v1.16b, v1.16b, v3.16b
+
+	pmull2		v5.1q, v1.2d, vCONSTANT.2d
+	pmull		v1.1q, v1.1d, vCONSTANT.1d
+	eor		v1.16b, v1.16b, v5.16b
+	eor		v1.16b, v1.16b, v4.16b
+
+	cbz		LEN, fold_64
+
+loop_16:		/* Folding rest buffer into 128bit */
+	subs		LEN, LEN, #0x10
+
+	ld1		{v2.16b}, [BUF], #0x10
+	pmull2		v5.1q, v1.2d, vCONSTANT.2d
+	pmull		v1.1q, v1.1d, vCONSTANT.1d
+	eor		v1.16b, v1.16b, v5.16b
+	eor		v1.16b, v1.16b, v2.16b
+
+	b.ne		loop_16
+
+fold_64:
+	/* perform the last 64 bit fold, also adds 32 zeroes
+	 * to the input stream */
+	ext		v2.16b, v1.16b, v1.16b, #8
+	pmull2		v2.1q, v2.2d, vCONSTANT.2d
+	ext		v1.16b, v1.16b, vzr.16b, #8
+	eor		v1.16b, v1.16b, v2.16b
+
+	/* final 32-bit fold */
+	ldr		dCONSTANT, [x3, #32]
+	ldr		d3, [x3, #40]
+
+	ext		v2.16b, v1.16b, vzr.16b, #4
+	and		v1.16b, v1.16b, v3.16b
+	pmull		v1.1q, v1.1d, vCONSTANT.1d
+	eor		v1.16b, v1.16b, v2.16b
+
+	/* Finish up with the bit-reversed barrett reduction 64 ==> 32 bits */
+	ldr		qCONSTANT, [x3, #48]
+
+	and		v2.16b, v1.16b, v3.16b
+	ext		v2.16b, vzr.16b, v2.16b, #8
+	pmull2		v2.1q, v2.2d, vCONSTANT.2d
+	and		v2.16b, v2.16b, v3.16b
+	pmull		v2.1q, v2.1d, vCONSTANT.1d
+	eor		v1.16b, v1.16b, v2.16b
+	mov		w0, v1.s[1]
+
+	ret
+ENDPROC(crc32_pmull_le)
+ENDPROC(crc32c_pmull_le)
+
+	.macro		__crc32, c
+0:	subs		x2, x2, #16
+	b.mi		8f
+	ldp		x3, x4, [x1], #16
+CPU_BE(	rev		x3, x3		)
+CPU_BE(	rev		x4, x4		)
+	crc32\c\()x	w0, w0, x3
+	crc32\c\()x	w0, w0, x4
+	b.ne		0b
+	ret
+
+8:	tbz		x2, #3, 4f
+	ldr		x3, [x1], #8
+CPU_BE(	rev		x3, x3		)
+	crc32\c\()x	w0, w0, x3
+4:	tbz		x2, #2, 2f
+	ldr		w3, [x1], #4
+CPU_BE(	rev		w3, w3		)
+	crc32\c\()w	w0, w0, w3
+2:	tbz		x2, #1, 1f
+	ldrh		w3, [x1], #2
+CPU_BE(	rev16		w3, w3		)
+	crc32\c\()h	w0, w0, w3
+1:	tbz		x2, #0, 0f
+	ldrb		w3, [x1]
+	crc32\c\()b	w0, w0, w3
+0:	ret
+	.endm
+
+	.align		5
+ENTRY(crc32_armv8_le)
+	__crc32
+ENDPROC(crc32_armv8_le)
+
+	.align		5
+ENTRY(crc32c_armv8_le)
+	__crc32		c
+ENDPROC(crc32c_armv8_le)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/crc32-ce-glue.c linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crc32-ce-glue.c
--- linux-libre-4.9-gnu/arch/arm64/crypto/crc32-ce-glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crc32-ce-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,212 @@
+/*
+ * Accelerated CRC32(C) using arm64 NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+ */
+
+#include <linux/cpufeature.h>
+#include <linux/crc32.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/unaligned.h>
+
+#define PMULL_MIN_LEN		64L	/* minimum size of buffer
+					 * for crc32_pmull_le_16 */
+#define SCALE_F			16L	/* size of NEON register */
+
+asmlinkage u32 crc32_pmull_le(const u8 buf[], u64 len, u32 init_crc);
+asmlinkage u32 crc32_armv8_le(u32 init_crc, const u8 buf[], size_t len);
+
+asmlinkage u32 crc32c_pmull_le(const u8 buf[], u64 len, u32 init_crc);
+asmlinkage u32 crc32c_armv8_le(u32 init_crc, const u8 buf[], size_t len);
+
+static u32 (*fallback_crc32)(u32 init_crc, const u8 buf[], size_t len);
+static u32 (*fallback_crc32c)(u32 init_crc, const u8 buf[], size_t len);
+
+static int crc32_pmull_cra_init(struct crypto_tfm *tfm)
+{
+	u32 *key = crypto_tfm_ctx(tfm);
+
+	*key = 0;
+	return 0;
+}
+
+static int crc32c_pmull_cra_init(struct crypto_tfm *tfm)
+{
+	u32 *key = crypto_tfm_ctx(tfm);
+
+	*key = ~0;
+	return 0;
+}
+
+static int crc32_pmull_setkey(struct crypto_shash *hash, const u8 *key,
+			      unsigned int keylen)
+{
+	u32 *mctx = crypto_shash_ctx(hash);
+
+	if (keylen != sizeof(u32)) {
+		crypto_shash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	*mctx = le32_to_cpup((__le32 *)key);
+	return 0;
+}
+
+static int crc32_pmull_init(struct shash_desc *desc)
+{
+	u32 *mctx = crypto_shash_ctx(desc->tfm);
+	u32 *crc = shash_desc_ctx(desc);
+
+	*crc = *mctx;
+	return 0;
+}
+
+static int crc32_pmull_update(struct shash_desc *desc, const u8 *data,
+			 unsigned int length)
+{
+	u32 *crc = shash_desc_ctx(desc);
+	unsigned int l;
+
+	if ((u64)data % SCALE_F) {
+		l = min_t(u32, length, SCALE_F - ((u64)data % SCALE_F));
+
+		*crc = fallback_crc32(*crc, data, l);
+
+		data += l;
+		length -= l;
+	}
+
+	if (length >= PMULL_MIN_LEN) {
+		l = round_down(length, SCALE_F);
+
+		kernel_neon_begin_partial(10);
+		*crc = crc32_pmull_le(data, l, *crc);
+		kernel_neon_end();
+
+		data += l;
+		length -= l;
+	}
+
+	if (length > 0)
+		*crc = fallback_crc32(*crc, data, length);
+
+	return 0;
+}
+
+static int crc32c_pmull_update(struct shash_desc *desc, const u8 *data,
+			 unsigned int length)
+{
+	u32 *crc = shash_desc_ctx(desc);
+	unsigned int l;
+
+	if ((u64)data % SCALE_F) {
+		l = min_t(u32, length, SCALE_F - ((u64)data % SCALE_F));
+
+		*crc = fallback_crc32c(*crc, data, l);
+
+		data += l;
+		length -= l;
+	}
+
+	if (length >= PMULL_MIN_LEN) {
+		l = round_down(length, SCALE_F);
+
+		kernel_neon_begin_partial(10);
+		*crc = crc32c_pmull_le(data, l, *crc);
+		kernel_neon_end();
+
+		data += l;
+		length -= l;
+	}
+
+	if (length > 0) {
+		*crc = fallback_crc32c(*crc, data, length);
+	}
+
+	return 0;
+}
+
+static int crc32_pmull_final(struct shash_desc *desc, u8 *out)
+{
+	u32 *crc = shash_desc_ctx(desc);
+
+	put_unaligned_le32(*crc, out);
+	return 0;
+}
+
+static int crc32c_pmull_final(struct shash_desc *desc, u8 *out)
+{
+	u32 *crc = shash_desc_ctx(desc);
+
+	put_unaligned_le32(~*crc, out);
+	return 0;
+}
+
+static struct shash_alg crc32_pmull_algs[] = { {
+	.setkey			= crc32_pmull_setkey,
+	.init			= crc32_pmull_init,
+	.update			= crc32_pmull_update,
+	.final			= crc32_pmull_final,
+	.descsize		= sizeof(u32),
+	.digestsize		= sizeof(u32),
+
+	.base.cra_ctxsize	= sizeof(u32),
+	.base.cra_init		= crc32_pmull_cra_init,
+	.base.cra_name		= "crc32",
+	.base.cra_driver_name	= "crc32-arm64-ce",
+	.base.cra_priority	= 200,
+	.base.cra_blocksize	= 1,
+	.base.cra_module	= THIS_MODULE,
+}, {
+	.setkey			= crc32_pmull_setkey,
+	.init			= crc32_pmull_init,
+	.update			= crc32c_pmull_update,
+	.final			= crc32c_pmull_final,
+	.descsize		= sizeof(u32),
+	.digestsize		= sizeof(u32),
+
+	.base.cra_ctxsize	= sizeof(u32),
+	.base.cra_init		= crc32c_pmull_cra_init,
+	.base.cra_name		= "crc32c",
+	.base.cra_driver_name	= "crc32c-arm64-ce",
+	.base.cra_priority	= 200,
+	.base.cra_blocksize	= 1,
+	.base.cra_module	= THIS_MODULE,
+} };
+
+static int __init crc32_pmull_mod_init(void)
+{
+	if (elf_hwcap & HWCAP_CRC32) {
+		fallback_crc32 = crc32_armv8_le;
+		fallback_crc32c = crc32c_armv8_le;
+	} else {
+		fallback_crc32 = crc32_le;
+		fallback_crc32c = __crc32c_le;
+	}
+
+	return crypto_register_shashes(crc32_pmull_algs,
+				       ARRAY_SIZE(crc32_pmull_algs));
+}
+
+static void __exit crc32_pmull_mod_exit(void)
+{
+	crypto_unregister_shashes(crc32_pmull_algs,
+				  ARRAY_SIZE(crc32_pmull_algs));
+}
+
+module_cpu_feature_match(PMULL, crc32_pmull_mod_init);
+module_exit(crc32_pmull_mod_exit);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/crct10dif-ce-core.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crct10dif-ce-core.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/crct10dif-ce-core.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crct10dif-ce-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,392 @@
+//
+// Accelerated CRC-T10DIF using arm64 NEON and Crypto Extensions instructions
+//
+// Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+//
+
+//
+// Implement fast CRC-T10DIF computation with SSE and PCLMULQDQ instructions
+//
+// Copyright (c) 2013, Intel Corporation
+//
+// Authors:
+//     Erdinc Ozturk <erdinc.ozturk@intel.com>
+//     Vinodh Gopal <vinodh.gopal@intel.com>
+//     James Guilford <james.guilford@intel.com>
+//     Tim Chen <tim.c.chen@linux.intel.com>
+//
+// 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.
+//
+// * Neither the name of the Intel Corporation nor the names of its
+//   contributors may be used to endorse or promote products derived from
+//   this software without specific prior written permission.
+//
+//
+// THIS SOFTWARE IS PROVIDED BY INTEL 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 INTEL CORPORATION 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.
+//
+//       Function API:
+//       UINT16 crc_t10dif_pcl(
+//               UINT16 init_crc, //initial CRC value, 16 bits
+//               const unsigned char *buf, //buffer pointer to calculate CRC on
+//               UINT64 len //buffer length in bytes (64-bit data)
+//       );
+//
+//       Reference paper titled "Fast CRC Computation for Generic
+//	Polynomials Using PCLMULQDQ Instruction"
+//       URL: http://www.intel.com/content/dam/www/public/us/en/documents
+//  /white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
+//
+//
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+	.text
+	.cpu		generic+crypto
+
+	arg1_low32	.req	w0
+	arg2		.req	x1
+	arg3		.req	x2
+
+	vzr		.req	v13
+
+ENTRY(crc_t10dif_pmull)
+	movi		vzr.16b, #0		// init zero register
+
+	// adjust the 16-bit initial_crc value, scale it to 32 bits
+	lsl		arg1_low32, arg1_low32, #16
+
+	// check if smaller than 256
+	cmp		arg3, #256
+
+	// for sizes less than 128, we can't fold 64B at a time...
+	b.lt		_less_than_128
+
+	// load the initial crc value
+	// crc value does not need to be byte-reflected, but it needs
+	// to be moved to the high part of the register.
+	// because data will be byte-reflected and will align with
+	// initial crc at correct place.
+	movi		v10.16b, #0
+	mov		v10.s[3], arg1_low32		// initial crc
+
+	// receive the initial 64B data, xor the initial crc value
+	ldp		q0, q1, [arg2]
+	ldp		q2, q3, [arg2, #0x20]
+	ldp		q4, q5, [arg2, #0x40]
+	ldp		q6, q7, [arg2, #0x60]
+	add		arg2, arg2, #0x80
+
+CPU_LE(	rev64		v0.16b, v0.16b			)
+CPU_LE(	rev64		v1.16b, v1.16b			)
+CPU_LE(	rev64		v2.16b, v2.16b			)
+CPU_LE(	rev64		v3.16b, v3.16b			)
+CPU_LE(	rev64		v4.16b, v4.16b			)
+CPU_LE(	rev64		v5.16b, v5.16b			)
+CPU_LE(	rev64		v6.16b, v6.16b			)
+CPU_LE(	rev64		v7.16b, v7.16b			)
+
+CPU_LE(	ext		v0.16b, v0.16b, v0.16b, #8	)
+CPU_LE(	ext		v1.16b, v1.16b, v1.16b, #8	)
+CPU_LE(	ext		v2.16b, v2.16b, v2.16b, #8	)
+CPU_LE(	ext		v3.16b, v3.16b, v3.16b, #8	)
+CPU_LE(	ext		v4.16b, v4.16b, v4.16b, #8	)
+CPU_LE(	ext		v5.16b, v5.16b, v5.16b, #8	)
+CPU_LE(	ext		v6.16b, v6.16b, v6.16b, #8	)
+CPU_LE(	ext		v7.16b, v7.16b, v7.16b, #8	)
+
+	// XOR the initial_crc value
+	eor		v0.16b, v0.16b, v10.16b
+
+	ldr		q10, rk3	// xmm10 has rk3 and rk4
+					// type of pmull instruction
+					// will determine which constant to use
+
+	//
+	// we subtract 256 instead of 128 to save one instruction from the loop
+	//
+	sub		arg3, arg3, #256
+
+	// at this section of the code, there is 64*x+y (0<=y<64) bytes of
+	// buffer. The _fold_64_B_loop will fold 64B at a time
+	// until we have 64+y Bytes of buffer
+
+
+	// fold 64B at a time. This section of the code folds 4 vector
+	// registers in parallel
+_fold_64_B_loop:
+
+	.macro		fold64, reg1, reg2
+	ldp		q11, q12, [arg2], #0x20
+
+	pmull2		v8.1q, \reg1\().2d, v10.2d
+	pmull		\reg1\().1q, \reg1\().1d, v10.1d
+
+CPU_LE(	rev64		v11.16b, v11.16b		)
+CPU_LE(	rev64		v12.16b, v12.16b		)
+
+	pmull2		v9.1q, \reg2\().2d, v10.2d
+	pmull		\reg2\().1q, \reg2\().1d, v10.1d
+
+CPU_LE(	ext		v11.16b, v11.16b, v11.16b, #8	)
+CPU_LE(	ext		v12.16b, v12.16b, v12.16b, #8	)
+
+	eor		\reg1\().16b, \reg1\().16b, v8.16b
+	eor		\reg2\().16b, \reg2\().16b, v9.16b
+	eor		\reg1\().16b, \reg1\().16b, v11.16b
+	eor		\reg2\().16b, \reg2\().16b, v12.16b
+	.endm
+
+	fold64		v0, v1
+	fold64		v2, v3
+	fold64		v4, v5
+	fold64		v6, v7
+
+	subs		arg3, arg3, #128
+
+	// check if there is another 64B in the buffer to be able to fold
+	b.ge		_fold_64_B_loop
+
+	// at this point, the buffer pointer is pointing at the last y Bytes
+	// of the buffer the 64B of folded data is in 4 of the vector
+	// registers: v0, v1, v2, v3
+
+	// fold the 8 vector registers to 1 vector register with different
+	// constants
+
+	ldr		q10, rk9
+
+	.macro		fold16, reg, rk
+	pmull		v8.1q, \reg\().1d, v10.1d
+	pmull2		\reg\().1q, \reg\().2d, v10.2d
+	.ifnb		\rk
+	ldr		q10, \rk
+	.endif
+	eor		v7.16b, v7.16b, v8.16b
+	eor		v7.16b, v7.16b, \reg\().16b
+	.endm
+
+	fold16		v0, rk11
+	fold16		v1, rk13
+	fold16		v2, rk15
+	fold16		v3, rk17
+	fold16		v4, rk19
+	fold16		v5, rk1
+	fold16		v6
+
+	// instead of 64, we add 48 to the loop counter to save 1 instruction
+	// from the loop instead of a cmp instruction, we use the negative
+	// flag with the jl instruction
+	adds		arg3, arg3, #(128-16)
+	b.lt		_final_reduction_for_128
+
+	// now we have 16+y bytes left to reduce. 16 Bytes is in register v7
+	// and the rest is in memory. We can fold 16 bytes at a time if y>=16
+	// continue folding 16B at a time
+
+_16B_reduction_loop:
+	pmull		v8.1q, v7.1d, v10.1d
+	pmull2		v7.1q, v7.2d, v10.2d
+	eor		v7.16b, v7.16b, v8.16b
+
+	ldr		q0, [arg2], #16
+CPU_LE(	rev64		v0.16b, v0.16b			)
+CPU_LE(	ext		v0.16b, v0.16b, v0.16b, #8	)
+	eor		v7.16b, v7.16b, v0.16b
+	subs		arg3, arg3, #16
+
+	// instead of a cmp instruction, we utilize the flags with the
+	// jge instruction equivalent of: cmp arg3, 16-16
+	// check if there is any more 16B in the buffer to be able to fold
+	b.ge		_16B_reduction_loop
+
+	// now we have 16+z bytes left to reduce, where 0<= z < 16.
+	// first, we reduce the data in the xmm7 register
+
+_final_reduction_for_128:
+	// check if any more data to fold. If not, compute the CRC of
+	// the final 128 bits
+	adds		arg3, arg3, #16
+	b.eq		_128_done
+
+	// here we are getting data that is less than 16 bytes.
+	// since we know that there was data before the pointer, we can
+	// offset the input pointer before the actual point, to receive
+	// exactly 16 bytes. after that the registers need to be adjusted.
+_get_last_two_regs:
+	add		arg2, arg2, arg3
+	ldr		q1, [arg2, #-16]
+CPU_LE(	rev64		v1.16b, v1.16b			)
+CPU_LE(	ext		v1.16b, v1.16b, v1.16b, #8	)
+
+	// get rid of the extra data that was loaded before
+	// load the shift constant
+	adr		x4, tbl_shf_table + 16
+	sub		x4, x4, arg3
+	ld1		{v0.16b}, [x4]
+
+	// shift v2 to the left by arg3 bytes
+	tbl		v2.16b, {v7.16b}, v0.16b
+
+	// shift v7 to the right by 16-arg3 bytes
+	movi		v9.16b, #0x80
+	eor		v0.16b, v0.16b, v9.16b
+	tbl		v7.16b, {v7.16b}, v0.16b
+
+	// blend
+	sshr		v0.16b, v0.16b, #7	// convert to 8-bit mask
+	bsl		v0.16b, v2.16b, v1.16b
+
+	// fold 16 Bytes
+	pmull		v8.1q, v7.1d, v10.1d
+	pmull2		v7.1q, v7.2d, v10.2d
+	eor		v7.16b, v7.16b, v8.16b
+	eor		v7.16b, v7.16b, v0.16b
+
+_128_done:
+	// compute crc of a 128-bit value
+	ldr		q10, rk5		// rk5 and rk6 in xmm10
+
+	// 64b fold
+	ext		v0.16b, vzr.16b, v7.16b, #8
+	mov		v7.d[0], v7.d[1]
+	pmull		v7.1q, v7.1d, v10.1d
+	eor		v7.16b, v7.16b, v0.16b
+
+	// 32b fold
+	ext		v0.16b, v7.16b, vzr.16b, #4
+	mov		v7.s[3], vzr.s[0]
+	pmull2		v0.1q, v0.2d, v10.2d
+	eor		v7.16b, v7.16b, v0.16b
+
+	// barrett reduction
+_barrett:
+	ldr		q10, rk7
+	mov		v0.d[0], v7.d[1]
+
+	pmull		v0.1q, v0.1d, v10.1d
+	ext		v0.16b, vzr.16b, v0.16b, #12
+	pmull2		v0.1q, v0.2d, v10.2d
+	ext		v0.16b, vzr.16b, v0.16b, #12
+	eor		v7.16b, v7.16b, v0.16b
+	mov		w0, v7.s[1]
+
+_cleanup:
+	// scale the result back to 16 bits
+	lsr		x0, x0, #16
+	ret
+
+_less_than_128:
+	cbz		arg3, _cleanup
+
+	movi		v0.16b, #0
+	mov		v0.s[3], arg1_low32	// get the initial crc value
+
+	ldr		q7, [arg2], #0x10
+CPU_LE(	rev64		v7.16b, v7.16b			)
+CPU_LE(	ext		v7.16b, v7.16b, v7.16b, #8	)
+	eor		v7.16b, v7.16b, v0.16b	// xor the initial crc value
+
+	cmp		arg3, #16
+	b.eq		_128_done		// exactly 16 left
+	b.lt		_less_than_16_left
+
+	ldr		q10, rk1		// rk1 and rk2 in xmm10
+
+	// update the counter. subtract 32 instead of 16 to save one
+	// instruction from the loop
+	subs		arg3, arg3, #32
+	b.ge		_16B_reduction_loop
+
+	add		arg3, arg3, #16
+	b		_get_last_two_regs
+
+_less_than_16_left:
+	// shl r9, 4
+	adr		x0, tbl_shf_table + 16
+	sub		x0, x0, arg3
+	ld1		{v0.16b}, [x0]
+	movi		v9.16b, #0x80
+	eor		v0.16b, v0.16b, v9.16b
+	tbl		v7.16b, {v7.16b}, v0.16b
+	b		_128_done
+ENDPROC(crc_t10dif_pmull)
+
+// precomputed constants
+// these constants are precomputed from the poly:
+// 0x8bb70000 (0x8bb7 scaled to 32 bits)
+	.align		4
+// Q = 0x18BB70000
+// rk1 = 2^(32*3) mod Q << 32
+// rk2 = 2^(32*5) mod Q << 32
+// rk3 = 2^(32*15) mod Q << 32
+// rk4 = 2^(32*17) mod Q << 32
+// rk5 = 2^(32*3) mod Q << 32
+// rk6 = 2^(32*2) mod Q << 32
+// rk7 = floor(2^64/Q)
+// rk8 = Q
+
+rk1:	.octa		0x06df0000000000002d56000000000000
+rk3:	.octa		0x7cf50000000000009d9d000000000000
+rk5:	.octa		0x13680000000000002d56000000000000
+rk7:	.octa		0x000000018bb7000000000001f65a57f8
+rk9:	.octa		0xbfd6000000000000ceae000000000000
+rk11:	.octa		0x713c0000000000001e16000000000000
+rk13:	.octa		0x80a6000000000000f7f9000000000000
+rk15:	.octa		0xe658000000000000044c000000000000
+rk17:	.octa		0xa497000000000000ad18000000000000
+rk19:	.octa		0xe7b50000000000006ee3000000000000
+
+tbl_shf_table:
+// use these values for shift constants for the tbl/tbx instruction
+// different alignments result in values as shown:
+//	DDQ 0x008f8e8d8c8b8a898887868584838281 # shl 15 (16-1) / shr1
+//	DDQ 0x01008f8e8d8c8b8a8988878685848382 # shl 14 (16-3) / shr2
+//	DDQ 0x0201008f8e8d8c8b8a89888786858483 # shl 13 (16-4) / shr3
+//	DDQ 0x030201008f8e8d8c8b8a898887868584 # shl 12 (16-4) / shr4
+//	DDQ 0x04030201008f8e8d8c8b8a8988878685 # shl 11 (16-5) / shr5
+//	DDQ 0x0504030201008f8e8d8c8b8a89888786 # shl 10 (16-6) / shr6
+//	DDQ 0x060504030201008f8e8d8c8b8a898887 # shl 9  (16-7) / shr7
+//	DDQ 0x07060504030201008f8e8d8c8b8a8988 # shl 8  (16-8) / shr8
+//	DDQ 0x0807060504030201008f8e8d8c8b8a89 # shl 7  (16-9) / shr9
+//	DDQ 0x090807060504030201008f8e8d8c8b8a # shl 6  (16-10) / shr10
+//	DDQ 0x0a090807060504030201008f8e8d8c8b # shl 5  (16-11) / shr11
+//	DDQ 0x0b0a090807060504030201008f8e8d8c # shl 4  (16-12) / shr12
+//	DDQ 0x0c0b0a090807060504030201008f8e8d # shl 3  (16-13) / shr13
+//	DDQ 0x0d0c0b0a090807060504030201008f8e # shl 2  (16-14) / shr14
+//	DDQ 0x0e0d0c0b0a090807060504030201008f # shl 1  (16-15) / shr15
+
+	.byte		 0x0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
+	.byte		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f
+	.byte		 0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7
+	.byte		 0x8,  0x9,  0xa,  0xb,  0xc,  0xd,  0xe , 0x0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/crct10dif-ce-glue.c linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crct10dif-ce-glue.c
--- linux-libre-4.9-gnu/arch/arm64/crypto/crct10dif-ce-glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/crct10dif-ce-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,95 @@
+/*
+ * Accelerated CRC-T10DIF using arm64 NEON and Crypto Extensions instructions
+ *
+ * Copyright (C) 2016 Linaro Ltd <ard.biesheuvel@linaro.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.
+ */
+
+#include <linux/cpufeature.h>
+#include <linux/crc-t10dif.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/neon.h>
+
+#define CRC_T10DIF_PMULL_CHUNK_SIZE	16U
+
+asmlinkage u16 crc_t10dif_pmull(u16 init_crc, const u8 buf[], u64 len);
+
+static int crct10dif_init(struct shash_desc *desc)
+{
+	u16 *crc = shash_desc_ctx(desc);
+
+	*crc = 0;
+	return 0;
+}
+
+static int crct10dif_update(struct shash_desc *desc, const u8 *data,
+			    unsigned int length)
+{
+	u16 *crc = shash_desc_ctx(desc);
+	unsigned int l;
+
+	if (unlikely((u64)data % CRC_T10DIF_PMULL_CHUNK_SIZE)) {
+		l = min_t(u32, length, CRC_T10DIF_PMULL_CHUNK_SIZE -
+			  ((u64)data % CRC_T10DIF_PMULL_CHUNK_SIZE));
+
+		*crc = crc_t10dif_generic(*crc, data, l);
+
+		length -= l;
+		data += l;
+	}
+
+	if (length > 0) {
+		kernel_neon_begin_partial(14);
+		*crc = crc_t10dif_pmull(*crc, data, length);
+		kernel_neon_end();
+	}
+
+	return 0;
+}
+
+static int crct10dif_final(struct shash_desc *desc, u8 *out)
+{
+	u16 *crc = shash_desc_ctx(desc);
+
+	*(u16 *)out = *crc;
+	return 0;
+}
+
+static struct shash_alg crc_t10dif_alg = {
+	.digestsize		= CRC_T10DIF_DIGEST_SIZE,
+	.init			= crct10dif_init,
+	.update			= crct10dif_update,
+	.final			= crct10dif_final,
+	.descsize		= CRC_T10DIF_DIGEST_SIZE,
+
+	.base.cra_name		= "crct10dif",
+	.base.cra_driver_name	= "crct10dif-arm64-ce",
+	.base.cra_priority	= 200,
+	.base.cra_blocksize	= CRC_T10DIF_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+};
+
+static int __init crc_t10dif_mod_init(void)
+{
+	return crypto_register_shash(&crc_t10dif_alg);
+}
+
+static void __exit crc_t10dif_mod_exit(void)
+{
+	crypto_unregister_shash(&crc_t10dif_alg);
+}
+
+module_cpu_feature_match(PMULL, crc_t10dif_mod_init);
+module_exit(crc_t10dif_mod_exit);
+
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/ghash-ce-core.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/ghash-ce-core.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/ghash-ce-core.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/ghash-ce-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -29,8 +29,8 @@
 	 *			   struct ghash_key const *k, const char *head)
 	 */
 ENTRY(pmull_ghash_update)
-	ld1		{SHASH.16b}, [x3]
-	ld1		{XL.16b}, [x1]
+	ld1		{SHASH.2d}, [x3]
+	ld1		{XL.2d}, [x1]
 	movi		MASK.16b, #0xe1
 	ext		SHASH2.16b, SHASH.16b, SHASH.16b, #8
 	shl		MASK.2d, MASK.2d, #57
@@ -74,6 +74,6 @@ CPU_LE(	rev64		T1.16b, T1.16b	)
 
 	cbnz		w0, 0b
 
-	st1		{XL.16b}, [x1]
+	st1		{XL.2d}, [x1]
 	ret
 ENDPROC(pmull_ghash_update)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/.gitignore linux-libre-4.10-rc8-gnu/arch/arm64/crypto/.gitignore
--- linux-libre-4.9-gnu/arch/arm64/crypto/.gitignore	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/.gitignore	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2 @@
+sha256-core.S
+sha512-core.S
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/Kconfig linux-libre-4.10-rc8-gnu/arch/arm64/crypto/Kconfig
--- linux-libre-4.9-gnu/arch/arm64/crypto/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,14 @@ menuconfig ARM64_CRYPTO
 
 if ARM64_CRYPTO
 
+config CRYPTO_SHA256_ARM64
+	tristate "SHA-224/SHA-256 digest algorithm for arm64"
+	select CRYPTO_HASH
+
+config CRYPTO_SHA512_ARM64
+	tristate "SHA-384/SHA-512 digest algorithm for arm64"
+	select CRYPTO_HASH
+
 config CRYPTO_SHA1_ARM64_CE
 	tristate "SHA-1 digest algorithm (ARMv8 Crypto Extensions)"
 	depends on ARM64 && KERNEL_MODE_NEON
@@ -23,6 +31,16 @@ config CRYPTO_GHASH_ARM64_CE
 	depends on ARM64 && KERNEL_MODE_NEON
 	select CRYPTO_HASH
 
+config CRYPTO_CRCT10DIF_ARM64_CE
+	tristate "CRCT10DIF digest algorithm using PMULL instructions"
+	depends on KERNEL_MODE_NEON && CRC_T10DIF
+	select CRYPTO_HASH
+
+config CRYPTO_CRC32_ARM64_CE
+	tristate "CRC32 and CRC32C digest algorithms using PMULL instructions"
+	depends on KERNEL_MODE_NEON && CRC32
+	select CRYPTO_HASH
+
 config CRYPTO_AES_ARM64_CE
 	tristate "AES core cipher using ARMv8 Crypto Extensions"
 	depends on ARM64 && KERNEL_MODE_NEON
@@ -40,17 +58,18 @@ config CRYPTO_AES_ARM64_CE_BLK
 	depends on ARM64 && KERNEL_MODE_NEON
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_AES_ARM64_CE
-	select CRYPTO_ABLK_HELPER
+	select CRYPTO_SIMD
 
 config CRYPTO_AES_ARM64_NEON_BLK
 	tristate "AES in ECB/CBC/CTR/XTS modes using NEON instructions"
 	depends on ARM64 && KERNEL_MODE_NEON
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_AES
-	select CRYPTO_ABLK_HELPER
+	select CRYPTO_SIMD
 
 config CRYPTO_CRC32_ARM64
 	tristate "CRC32 and CRC32C using optional ARMv8 instructions"
 	depends on ARM64
 	select CRYPTO_HASH
+
 endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/crypto/Makefile
--- linux-libre-4.9-gnu/arch/arm64/crypto/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,12 @@ sha2-ce-y := sha2-ce-glue.o sha2-ce-core
 obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o
 ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
 
+obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM64_CE) += crct10dif-ce.o
+crct10dif-ce-y := crct10dif-ce-core.o crct10dif-ce-glue.o
+
+obj-$(CONFIG_CRYPTO_CRC32_ARM64_CE) += crc32-ce.o
+crc32-ce-y:= crc32-ce-core.o crc32-ce-glue.o
+
 obj-$(CONFIG_CRYPTO_AES_ARM64_CE) += aes-ce-cipher.o
 CFLAGS_aes-ce-cipher.o += -march=armv8-a+crypto
 
@@ -29,6 +35,12 @@ aes-ce-blk-y := aes-glue-ce.o aes-ce.o
 obj-$(CONFIG_CRYPTO_AES_ARM64_NEON_BLK) += aes-neon-blk.o
 aes-neon-blk-y := aes-glue-neon.o aes-neon.o
 
+obj-$(CONFIG_CRYPTO_SHA256_ARM64) += sha256-arm64.o
+sha256-arm64-y := sha256-glue.o sha256-core.o
+
+obj-$(CONFIG_CRYPTO_SHA512_ARM64) += sha512-arm64.o
+sha512-arm64-y := sha512-glue.o sha512-core.o
+
 AFLAGS_aes-ce.o		:= -DINTERLEAVE=4
 AFLAGS_aes-neon.o	:= -DINTERLEAVE=4
 
@@ -40,3 +52,14 @@ CFLAGS_crc32-arm64.o	:= -mcpu=generic+cr
 
 $(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
 	$(call if_changed_rule,cc_o_c)
+
+quiet_cmd_perlasm = PERLASM $@
+      cmd_perlasm = $(PERL) $(<) void $(@)
+
+$(src)/sha256-core.S_shipped: $(src)/sha512-armv8.pl
+	$(call cmd,perlasm)
+
+$(src)/sha512-core.S_shipped: $(src)/sha512-armv8.pl
+	$(call cmd,perlasm)
+
+.PRECIOUS: $(obj)/sha256-core.S $(obj)/sha512-core.S
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/sha1-ce-core.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha1-ce-core.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/sha1-ce-core.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha1-ce-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -78,7 +78,7 @@ ENTRY(sha1_ce_transform)
 	ld1r		{k3.4s}, [x6]
 
 	/* load state */
-	ldr		dga, [x0]
+	ld1		{dgav.4s}, [x0]
 	ldr		dgb, [x0, #16]
 
 	/* load sha1_ce_state::finalize */
@@ -144,7 +144,7 @@ CPU_LE(	rev32		v11.16b, v11.16b	)
 	b		1b
 
 	/* store new state */
-3:	str		dga, [x0]
+3:	st1		{dgav.4s}, [x0]
 	str		dgb, [x0, #16]
 	ret
 ENDPROC(sha1_ce_transform)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/sha256-core.S_shipped linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha256-core.S_shipped
--- linux-libre-4.9-gnu/arch/arm64/crypto/sha256-core.S_shipped	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha256-core.S_shipped	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2061 @@
+// Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+//
+// Licensed under the OpenSSL license (the "License").  You may not use
+// this file except in compliance with the License.  You can obtain a copy
+// in the file LICENSE in the source distribution or at
+// https://www.openssl.org/source/license.html
+
+// ====================================================================
+// Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+// project. The module is, however, dual licensed under OpenSSL and
+// CRYPTOGAMS licenses depending on where you obtain it. For further
+// details see http://www.openssl.org/~appro/cryptogams/.
+//
+// Permission to use under GPLv2 terms is granted.
+// ====================================================================
+//
+// SHA256/512 for ARMv8.
+//
+// Performance in cycles per processed byte and improvement coefficient
+// over code generated with "default" compiler:
+//
+//		SHA256-hw	SHA256(*)	SHA512
+// Apple A7	1.97		10.5 (+33%)	6.73 (-1%(**))
+// Cortex-A53	2.38		15.5 (+115%)	10.0 (+150%(***))
+// Cortex-A57	2.31		11.6 (+86%)	7.51 (+260%(***))
+// Denver	2.01		10.5 (+26%)	6.70 (+8%)
+// X-Gene			20.0 (+100%)	12.8 (+300%(***))
+// Mongoose	2.36		13.0 (+50%)	8.36 (+33%)
+//
+// (*)	Software SHA256 results are of lesser relevance, presented
+//	mostly for informational purposes.
+// (**)	The result is a trade-off: it's possible to improve it by
+//	10% (or by 1 cycle per round), but at the cost of 20% loss
+//	on Cortex-A53 (or by 4 cycles per round).
+// (***)	Super-impressive coefficients over gcc-generated code are
+//	indication of some compiler "pathology", most notably code
+//	generated with -mgeneral-regs-only is significanty faster
+//	and the gap is only 40-90%.
+//
+// October 2016.
+//
+// Originally it was reckoned that it makes no sense to implement NEON
+// version of SHA256 for 64-bit processors. This is because performance
+// improvement on most wide-spread Cortex-A5x processors was observed
+// to be marginal, same on Cortex-A53 and ~10% on A57. But then it was
+// observed that 32-bit NEON SHA256 performs significantly better than
+// 64-bit scalar version on *some* of the more recent processors. As
+// result 64-bit NEON version of SHA256 was added to provide best
+// all-round performance. For example it executes ~30% faster on X-Gene
+// and Mongoose. [For reference, NEON version of SHA512 is bound to
+// deliver much less improvement, likely *negative* on Cortex-A5x.
+// Which is why NEON support is limited to SHA256.]
+
+#ifndef	__KERNEL__
+# include "arm_arch.h"
+#endif
+
+.text
+
+.extern	OPENSSL_armcap_P
+.globl	sha256_block_data_order
+.type	sha256_block_data_order,%function
+.align	6
+sha256_block_data_order:
+#ifndef	__KERNEL__
+# ifdef	__ILP32__
+	ldrsw	x16,.LOPENSSL_armcap_P
+# else
+	ldr	x16,.LOPENSSL_armcap_P
+# endif
+	adr	x17,.LOPENSSL_armcap_P
+	add	x16,x16,x17
+	ldr	w16,[x16]
+	tst	w16,#ARMV8_SHA256
+	b.ne	.Lv8_entry
+	tst	w16,#ARMV7_NEON
+	b.ne	.Lneon_entry
+#endif
+	stp	x29,x30,[sp,#-128]!
+	add	x29,sp,#0
+
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#4*4
+
+	ldp	w20,w21,[x0]				// load context
+	ldp	w22,w23,[x0,#2*4]
+	ldp	w24,w25,[x0,#4*4]
+	add	x2,x1,x2,lsl#6	// end of input
+	ldp	w26,w27,[x0,#6*4]
+	adr	x30,.LK256
+	stp	x0,x2,[x29,#96]
+
+.Loop:
+	ldp	w3,w4,[x1],#2*4
+	ldr	w19,[x30],#4			// *K++
+	eor	w28,w21,w22				// magic seed
+	str	x1,[x29,#112]
+#ifndef	__AARCH64EB__
+	rev	w3,w3			// 0
+#endif
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	eor	w6,w24,w24,ror#14
+	and	w17,w25,w24
+	bic	w19,w26,w24
+	add	w27,w27,w3			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w6,ror#11	// Sigma1(e)
+	ror	w6,w20,#2
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	eor	w17,w20,w20,ror#9
+	add	w27,w27,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w23,w23,w27			// d+=h
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w6,w17,ror#13	// Sigma0(a)
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w27,w27,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w4,w4			// 1
+#endif
+	ldp	w5,w6,[x1],#2*4
+	add	w27,w27,w17			// h+=Sigma0(a)
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	eor	w7,w23,w23,ror#14
+	and	w17,w24,w23
+	bic	w28,w25,w23
+	add	w26,w26,w4			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w7,ror#11	// Sigma1(e)
+	ror	w7,w27,#2
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	eor	w17,w27,w27,ror#9
+	add	w26,w26,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w22,w22,w26			// d+=h
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w7,w17,ror#13	// Sigma0(a)
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w26,w26,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w5,w5			// 2
+#endif
+	add	w26,w26,w17			// h+=Sigma0(a)
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	eor	w8,w22,w22,ror#14
+	and	w17,w23,w22
+	bic	w19,w24,w22
+	add	w25,w25,w5			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w8,ror#11	// Sigma1(e)
+	ror	w8,w26,#2
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	eor	w17,w26,w26,ror#9
+	add	w25,w25,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w21,w21,w25			// d+=h
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w8,w17,ror#13	// Sigma0(a)
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w25,w25,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w6,w6			// 3
+#endif
+	ldp	w7,w8,[x1],#2*4
+	add	w25,w25,w17			// h+=Sigma0(a)
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	eor	w9,w21,w21,ror#14
+	and	w17,w22,w21
+	bic	w28,w23,w21
+	add	w24,w24,w6			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w9,ror#11	// Sigma1(e)
+	ror	w9,w25,#2
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	eor	w17,w25,w25,ror#9
+	add	w24,w24,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w20,w20,w24			// d+=h
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w9,w17,ror#13	// Sigma0(a)
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w24,w24,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w7,w7			// 4
+#endif
+	add	w24,w24,w17			// h+=Sigma0(a)
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	eor	w10,w20,w20,ror#14
+	and	w17,w21,w20
+	bic	w19,w22,w20
+	add	w23,w23,w7			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w10,ror#11	// Sigma1(e)
+	ror	w10,w24,#2
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	eor	w17,w24,w24,ror#9
+	add	w23,w23,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w27,w27,w23			// d+=h
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w10,w17,ror#13	// Sigma0(a)
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w23,w23,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w8,w8			// 5
+#endif
+	ldp	w9,w10,[x1],#2*4
+	add	w23,w23,w17			// h+=Sigma0(a)
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	eor	w11,w27,w27,ror#14
+	and	w17,w20,w27
+	bic	w28,w21,w27
+	add	w22,w22,w8			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w11,ror#11	// Sigma1(e)
+	ror	w11,w23,#2
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	eor	w17,w23,w23,ror#9
+	add	w22,w22,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w26,w26,w22			// d+=h
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w11,w17,ror#13	// Sigma0(a)
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w22,w22,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w9,w9			// 6
+#endif
+	add	w22,w22,w17			// h+=Sigma0(a)
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	eor	w12,w26,w26,ror#14
+	and	w17,w27,w26
+	bic	w19,w20,w26
+	add	w21,w21,w9			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w12,ror#11	// Sigma1(e)
+	ror	w12,w22,#2
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	eor	w17,w22,w22,ror#9
+	add	w21,w21,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w25,w25,w21			// d+=h
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w12,w17,ror#13	// Sigma0(a)
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w21,w21,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w10,w10			// 7
+#endif
+	ldp	w11,w12,[x1],#2*4
+	add	w21,w21,w17			// h+=Sigma0(a)
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	eor	w13,w25,w25,ror#14
+	and	w17,w26,w25
+	bic	w28,w27,w25
+	add	w20,w20,w10			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w13,ror#11	// Sigma1(e)
+	ror	w13,w21,#2
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	eor	w17,w21,w21,ror#9
+	add	w20,w20,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w24,w24,w20			// d+=h
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w13,w17,ror#13	// Sigma0(a)
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w20,w20,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w11,w11			// 8
+#endif
+	add	w20,w20,w17			// h+=Sigma0(a)
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	eor	w14,w24,w24,ror#14
+	and	w17,w25,w24
+	bic	w19,w26,w24
+	add	w27,w27,w11			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w14,ror#11	// Sigma1(e)
+	ror	w14,w20,#2
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	eor	w17,w20,w20,ror#9
+	add	w27,w27,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w23,w23,w27			// d+=h
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w14,w17,ror#13	// Sigma0(a)
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w27,w27,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w12,w12			// 9
+#endif
+	ldp	w13,w14,[x1],#2*4
+	add	w27,w27,w17			// h+=Sigma0(a)
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	eor	w15,w23,w23,ror#14
+	and	w17,w24,w23
+	bic	w28,w25,w23
+	add	w26,w26,w12			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w15,ror#11	// Sigma1(e)
+	ror	w15,w27,#2
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	eor	w17,w27,w27,ror#9
+	add	w26,w26,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w22,w22,w26			// d+=h
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w15,w17,ror#13	// Sigma0(a)
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w26,w26,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w13,w13			// 10
+#endif
+	add	w26,w26,w17			// h+=Sigma0(a)
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	eor	w0,w22,w22,ror#14
+	and	w17,w23,w22
+	bic	w19,w24,w22
+	add	w25,w25,w13			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w0,ror#11	// Sigma1(e)
+	ror	w0,w26,#2
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	eor	w17,w26,w26,ror#9
+	add	w25,w25,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w21,w21,w25			// d+=h
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w0,w17,ror#13	// Sigma0(a)
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w25,w25,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w14,w14			// 11
+#endif
+	ldp	w15,w0,[x1],#2*4
+	add	w25,w25,w17			// h+=Sigma0(a)
+	str	w6,[sp,#12]
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	eor	w6,w21,w21,ror#14
+	and	w17,w22,w21
+	bic	w28,w23,w21
+	add	w24,w24,w14			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w6,ror#11	// Sigma1(e)
+	ror	w6,w25,#2
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	eor	w17,w25,w25,ror#9
+	add	w24,w24,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w20,w20,w24			// d+=h
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w6,w17,ror#13	// Sigma0(a)
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w24,w24,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w15,w15			// 12
+#endif
+	add	w24,w24,w17			// h+=Sigma0(a)
+	str	w7,[sp,#0]
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	eor	w7,w20,w20,ror#14
+	and	w17,w21,w20
+	bic	w19,w22,w20
+	add	w23,w23,w15			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w7,ror#11	// Sigma1(e)
+	ror	w7,w24,#2
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	eor	w17,w24,w24,ror#9
+	add	w23,w23,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w27,w27,w23			// d+=h
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w7,w17,ror#13	// Sigma0(a)
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w23,w23,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w0,w0			// 13
+#endif
+	ldp	w1,w2,[x1]
+	add	w23,w23,w17			// h+=Sigma0(a)
+	str	w8,[sp,#4]
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	eor	w8,w27,w27,ror#14
+	and	w17,w20,w27
+	bic	w28,w21,w27
+	add	w22,w22,w0			// h+=X[i]
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w8,ror#11	// Sigma1(e)
+	ror	w8,w23,#2
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	eor	w17,w23,w23,ror#9
+	add	w22,w22,w16			// h+=Sigma1(e)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	add	w26,w26,w22			// d+=h
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w8,w17,ror#13	// Sigma0(a)
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	//add	w22,w22,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w1,w1			// 14
+#endif
+	ldr	w6,[sp,#12]
+	add	w22,w22,w17			// h+=Sigma0(a)
+	str	w9,[sp,#8]
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	eor	w9,w26,w26,ror#14
+	and	w17,w27,w26
+	bic	w19,w20,w26
+	add	w21,w21,w1			// h+=X[i]
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w9,ror#11	// Sigma1(e)
+	ror	w9,w22,#2
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	eor	w17,w22,w22,ror#9
+	add	w21,w21,w16			// h+=Sigma1(e)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	add	w25,w25,w21			// d+=h
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w9,w17,ror#13	// Sigma0(a)
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	//add	w21,w21,w17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	w2,w2			// 15
+#endif
+	ldr	w7,[sp,#0]
+	add	w21,w21,w17			// h+=Sigma0(a)
+	str	w10,[sp,#12]
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	ror	w9,w4,#7
+	and	w17,w26,w25
+	ror	w8,w1,#17
+	bic	w28,w27,w25
+	ror	w10,w21,#2
+	add	w20,w20,w2			// h+=X[i]
+	eor	w16,w16,w25,ror#11
+	eor	w9,w9,w4,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w25,ror#25	// Sigma1(e)
+	eor	w10,w10,w21,ror#13
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w8,w8,w1,ror#19
+	eor	w9,w9,w4,lsr#3	// sigma0(X[i+1])
+	add	w20,w20,w16			// h+=Sigma1(e)
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w10,w21,ror#22	// Sigma0(a)
+	eor	w8,w8,w1,lsr#10	// sigma1(X[i+14])
+	add	w3,w3,w12
+	add	w24,w24,w20			// d+=h
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w3,w3,w9
+	add	w20,w20,w17			// h+=Sigma0(a)
+	add	w3,w3,w8
+.Loop_16_xx:
+	ldr	w8,[sp,#4]
+	str	w11,[sp,#0]
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	ror	w10,w5,#7
+	and	w17,w25,w24
+	ror	w9,w2,#17
+	bic	w19,w26,w24
+	ror	w11,w20,#2
+	add	w27,w27,w3			// h+=X[i]
+	eor	w16,w16,w24,ror#11
+	eor	w10,w10,w5,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w24,ror#25	// Sigma1(e)
+	eor	w11,w11,w20,ror#13
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w9,w9,w2,ror#19
+	eor	w10,w10,w5,lsr#3	// sigma0(X[i+1])
+	add	w27,w27,w16			// h+=Sigma1(e)
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w11,w20,ror#22	// Sigma0(a)
+	eor	w9,w9,w2,lsr#10	// sigma1(X[i+14])
+	add	w4,w4,w13
+	add	w23,w23,w27			// d+=h
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w4,w4,w10
+	add	w27,w27,w17			// h+=Sigma0(a)
+	add	w4,w4,w9
+	ldr	w9,[sp,#8]
+	str	w12,[sp,#4]
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	ror	w11,w6,#7
+	and	w17,w24,w23
+	ror	w10,w3,#17
+	bic	w28,w25,w23
+	ror	w12,w27,#2
+	add	w26,w26,w4			// h+=X[i]
+	eor	w16,w16,w23,ror#11
+	eor	w11,w11,w6,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w23,ror#25	// Sigma1(e)
+	eor	w12,w12,w27,ror#13
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w10,w10,w3,ror#19
+	eor	w11,w11,w6,lsr#3	// sigma0(X[i+1])
+	add	w26,w26,w16			// h+=Sigma1(e)
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w12,w27,ror#22	// Sigma0(a)
+	eor	w10,w10,w3,lsr#10	// sigma1(X[i+14])
+	add	w5,w5,w14
+	add	w22,w22,w26			// d+=h
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w5,w5,w11
+	add	w26,w26,w17			// h+=Sigma0(a)
+	add	w5,w5,w10
+	ldr	w10,[sp,#12]
+	str	w13,[sp,#8]
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	ror	w12,w7,#7
+	and	w17,w23,w22
+	ror	w11,w4,#17
+	bic	w19,w24,w22
+	ror	w13,w26,#2
+	add	w25,w25,w5			// h+=X[i]
+	eor	w16,w16,w22,ror#11
+	eor	w12,w12,w7,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w22,ror#25	// Sigma1(e)
+	eor	w13,w13,w26,ror#13
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w11,w11,w4,ror#19
+	eor	w12,w12,w7,lsr#3	// sigma0(X[i+1])
+	add	w25,w25,w16			// h+=Sigma1(e)
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w13,w26,ror#22	// Sigma0(a)
+	eor	w11,w11,w4,lsr#10	// sigma1(X[i+14])
+	add	w6,w6,w15
+	add	w21,w21,w25			// d+=h
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w6,w6,w12
+	add	w25,w25,w17			// h+=Sigma0(a)
+	add	w6,w6,w11
+	ldr	w11,[sp,#0]
+	str	w14,[sp,#12]
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	ror	w13,w8,#7
+	and	w17,w22,w21
+	ror	w12,w5,#17
+	bic	w28,w23,w21
+	ror	w14,w25,#2
+	add	w24,w24,w6			// h+=X[i]
+	eor	w16,w16,w21,ror#11
+	eor	w13,w13,w8,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w21,ror#25	// Sigma1(e)
+	eor	w14,w14,w25,ror#13
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w12,w12,w5,ror#19
+	eor	w13,w13,w8,lsr#3	// sigma0(X[i+1])
+	add	w24,w24,w16			// h+=Sigma1(e)
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w14,w25,ror#22	// Sigma0(a)
+	eor	w12,w12,w5,lsr#10	// sigma1(X[i+14])
+	add	w7,w7,w0
+	add	w20,w20,w24			// d+=h
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w7,w7,w13
+	add	w24,w24,w17			// h+=Sigma0(a)
+	add	w7,w7,w12
+	ldr	w12,[sp,#4]
+	str	w15,[sp,#0]
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	ror	w14,w9,#7
+	and	w17,w21,w20
+	ror	w13,w6,#17
+	bic	w19,w22,w20
+	ror	w15,w24,#2
+	add	w23,w23,w7			// h+=X[i]
+	eor	w16,w16,w20,ror#11
+	eor	w14,w14,w9,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w20,ror#25	// Sigma1(e)
+	eor	w15,w15,w24,ror#13
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w13,w13,w6,ror#19
+	eor	w14,w14,w9,lsr#3	// sigma0(X[i+1])
+	add	w23,w23,w16			// h+=Sigma1(e)
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w15,w24,ror#22	// Sigma0(a)
+	eor	w13,w13,w6,lsr#10	// sigma1(X[i+14])
+	add	w8,w8,w1
+	add	w27,w27,w23			// d+=h
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w8,w8,w14
+	add	w23,w23,w17			// h+=Sigma0(a)
+	add	w8,w8,w13
+	ldr	w13,[sp,#8]
+	str	w0,[sp,#4]
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	ror	w15,w10,#7
+	and	w17,w20,w27
+	ror	w14,w7,#17
+	bic	w28,w21,w27
+	ror	w0,w23,#2
+	add	w22,w22,w8			// h+=X[i]
+	eor	w16,w16,w27,ror#11
+	eor	w15,w15,w10,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w27,ror#25	// Sigma1(e)
+	eor	w0,w0,w23,ror#13
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w14,w14,w7,ror#19
+	eor	w15,w15,w10,lsr#3	// sigma0(X[i+1])
+	add	w22,w22,w16			// h+=Sigma1(e)
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w0,w23,ror#22	// Sigma0(a)
+	eor	w14,w14,w7,lsr#10	// sigma1(X[i+14])
+	add	w9,w9,w2
+	add	w26,w26,w22			// d+=h
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w9,w9,w15
+	add	w22,w22,w17			// h+=Sigma0(a)
+	add	w9,w9,w14
+	ldr	w14,[sp,#12]
+	str	w1,[sp,#8]
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	ror	w0,w11,#7
+	and	w17,w27,w26
+	ror	w15,w8,#17
+	bic	w19,w20,w26
+	ror	w1,w22,#2
+	add	w21,w21,w9			// h+=X[i]
+	eor	w16,w16,w26,ror#11
+	eor	w0,w0,w11,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w26,ror#25	// Sigma1(e)
+	eor	w1,w1,w22,ror#13
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w15,w15,w8,ror#19
+	eor	w0,w0,w11,lsr#3	// sigma0(X[i+1])
+	add	w21,w21,w16			// h+=Sigma1(e)
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w1,w22,ror#22	// Sigma0(a)
+	eor	w15,w15,w8,lsr#10	// sigma1(X[i+14])
+	add	w10,w10,w3
+	add	w25,w25,w21			// d+=h
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w10,w10,w0
+	add	w21,w21,w17			// h+=Sigma0(a)
+	add	w10,w10,w15
+	ldr	w15,[sp,#0]
+	str	w2,[sp,#12]
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	ror	w1,w12,#7
+	and	w17,w26,w25
+	ror	w0,w9,#17
+	bic	w28,w27,w25
+	ror	w2,w21,#2
+	add	w20,w20,w10			// h+=X[i]
+	eor	w16,w16,w25,ror#11
+	eor	w1,w1,w12,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w25,ror#25	// Sigma1(e)
+	eor	w2,w2,w21,ror#13
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w0,w0,w9,ror#19
+	eor	w1,w1,w12,lsr#3	// sigma0(X[i+1])
+	add	w20,w20,w16			// h+=Sigma1(e)
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w2,w21,ror#22	// Sigma0(a)
+	eor	w0,w0,w9,lsr#10	// sigma1(X[i+14])
+	add	w11,w11,w4
+	add	w24,w24,w20			// d+=h
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w11,w11,w1
+	add	w20,w20,w17			// h+=Sigma0(a)
+	add	w11,w11,w0
+	ldr	w0,[sp,#4]
+	str	w3,[sp,#0]
+	ror	w16,w24,#6
+	add	w27,w27,w19			// h+=K[i]
+	ror	w2,w13,#7
+	and	w17,w25,w24
+	ror	w1,w10,#17
+	bic	w19,w26,w24
+	ror	w3,w20,#2
+	add	w27,w27,w11			// h+=X[i]
+	eor	w16,w16,w24,ror#11
+	eor	w2,w2,w13,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w20,w21			// a^b, b^c in next round
+	eor	w16,w16,w24,ror#25	// Sigma1(e)
+	eor	w3,w3,w20,ror#13
+	add	w27,w27,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w1,w1,w10,ror#19
+	eor	w2,w2,w13,lsr#3	// sigma0(X[i+1])
+	add	w27,w27,w16			// h+=Sigma1(e)
+	eor	w28,w28,w21			// Maj(a,b,c)
+	eor	w17,w3,w20,ror#22	// Sigma0(a)
+	eor	w1,w1,w10,lsr#10	// sigma1(X[i+14])
+	add	w12,w12,w5
+	add	w23,w23,w27			// d+=h
+	add	w27,w27,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w12,w12,w2
+	add	w27,w27,w17			// h+=Sigma0(a)
+	add	w12,w12,w1
+	ldr	w1,[sp,#8]
+	str	w4,[sp,#4]
+	ror	w16,w23,#6
+	add	w26,w26,w28			// h+=K[i]
+	ror	w3,w14,#7
+	and	w17,w24,w23
+	ror	w2,w11,#17
+	bic	w28,w25,w23
+	ror	w4,w27,#2
+	add	w26,w26,w12			// h+=X[i]
+	eor	w16,w16,w23,ror#11
+	eor	w3,w3,w14,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w27,w20			// a^b, b^c in next round
+	eor	w16,w16,w23,ror#25	// Sigma1(e)
+	eor	w4,w4,w27,ror#13
+	add	w26,w26,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w2,w2,w11,ror#19
+	eor	w3,w3,w14,lsr#3	// sigma0(X[i+1])
+	add	w26,w26,w16			// h+=Sigma1(e)
+	eor	w19,w19,w20			// Maj(a,b,c)
+	eor	w17,w4,w27,ror#22	// Sigma0(a)
+	eor	w2,w2,w11,lsr#10	// sigma1(X[i+14])
+	add	w13,w13,w6
+	add	w22,w22,w26			// d+=h
+	add	w26,w26,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w13,w13,w3
+	add	w26,w26,w17			// h+=Sigma0(a)
+	add	w13,w13,w2
+	ldr	w2,[sp,#12]
+	str	w5,[sp,#8]
+	ror	w16,w22,#6
+	add	w25,w25,w19			// h+=K[i]
+	ror	w4,w15,#7
+	and	w17,w23,w22
+	ror	w3,w12,#17
+	bic	w19,w24,w22
+	ror	w5,w26,#2
+	add	w25,w25,w13			// h+=X[i]
+	eor	w16,w16,w22,ror#11
+	eor	w4,w4,w15,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w26,w27			// a^b, b^c in next round
+	eor	w16,w16,w22,ror#25	// Sigma1(e)
+	eor	w5,w5,w26,ror#13
+	add	w25,w25,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w3,w3,w12,ror#19
+	eor	w4,w4,w15,lsr#3	// sigma0(X[i+1])
+	add	w25,w25,w16			// h+=Sigma1(e)
+	eor	w28,w28,w27			// Maj(a,b,c)
+	eor	w17,w5,w26,ror#22	// Sigma0(a)
+	eor	w3,w3,w12,lsr#10	// sigma1(X[i+14])
+	add	w14,w14,w7
+	add	w21,w21,w25			// d+=h
+	add	w25,w25,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w14,w14,w4
+	add	w25,w25,w17			// h+=Sigma0(a)
+	add	w14,w14,w3
+	ldr	w3,[sp,#0]
+	str	w6,[sp,#12]
+	ror	w16,w21,#6
+	add	w24,w24,w28			// h+=K[i]
+	ror	w5,w0,#7
+	and	w17,w22,w21
+	ror	w4,w13,#17
+	bic	w28,w23,w21
+	ror	w6,w25,#2
+	add	w24,w24,w14			// h+=X[i]
+	eor	w16,w16,w21,ror#11
+	eor	w5,w5,w0,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w25,w26			// a^b, b^c in next round
+	eor	w16,w16,w21,ror#25	// Sigma1(e)
+	eor	w6,w6,w25,ror#13
+	add	w24,w24,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w4,w4,w13,ror#19
+	eor	w5,w5,w0,lsr#3	// sigma0(X[i+1])
+	add	w24,w24,w16			// h+=Sigma1(e)
+	eor	w19,w19,w26			// Maj(a,b,c)
+	eor	w17,w6,w25,ror#22	// Sigma0(a)
+	eor	w4,w4,w13,lsr#10	// sigma1(X[i+14])
+	add	w15,w15,w8
+	add	w20,w20,w24			// d+=h
+	add	w24,w24,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w15,w15,w5
+	add	w24,w24,w17			// h+=Sigma0(a)
+	add	w15,w15,w4
+	ldr	w4,[sp,#4]
+	str	w7,[sp,#0]
+	ror	w16,w20,#6
+	add	w23,w23,w19			// h+=K[i]
+	ror	w6,w1,#7
+	and	w17,w21,w20
+	ror	w5,w14,#17
+	bic	w19,w22,w20
+	ror	w7,w24,#2
+	add	w23,w23,w15			// h+=X[i]
+	eor	w16,w16,w20,ror#11
+	eor	w6,w6,w1,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w24,w25			// a^b, b^c in next round
+	eor	w16,w16,w20,ror#25	// Sigma1(e)
+	eor	w7,w7,w24,ror#13
+	add	w23,w23,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w5,w5,w14,ror#19
+	eor	w6,w6,w1,lsr#3	// sigma0(X[i+1])
+	add	w23,w23,w16			// h+=Sigma1(e)
+	eor	w28,w28,w25			// Maj(a,b,c)
+	eor	w17,w7,w24,ror#22	// Sigma0(a)
+	eor	w5,w5,w14,lsr#10	// sigma1(X[i+14])
+	add	w0,w0,w9
+	add	w27,w27,w23			// d+=h
+	add	w23,w23,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w0,w0,w6
+	add	w23,w23,w17			// h+=Sigma0(a)
+	add	w0,w0,w5
+	ldr	w5,[sp,#8]
+	str	w8,[sp,#4]
+	ror	w16,w27,#6
+	add	w22,w22,w28			// h+=K[i]
+	ror	w7,w2,#7
+	and	w17,w20,w27
+	ror	w6,w15,#17
+	bic	w28,w21,w27
+	ror	w8,w23,#2
+	add	w22,w22,w0			// h+=X[i]
+	eor	w16,w16,w27,ror#11
+	eor	w7,w7,w2,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w23,w24			// a^b, b^c in next round
+	eor	w16,w16,w27,ror#25	// Sigma1(e)
+	eor	w8,w8,w23,ror#13
+	add	w22,w22,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w6,w6,w15,ror#19
+	eor	w7,w7,w2,lsr#3	// sigma0(X[i+1])
+	add	w22,w22,w16			// h+=Sigma1(e)
+	eor	w19,w19,w24			// Maj(a,b,c)
+	eor	w17,w8,w23,ror#22	// Sigma0(a)
+	eor	w6,w6,w15,lsr#10	// sigma1(X[i+14])
+	add	w1,w1,w10
+	add	w26,w26,w22			// d+=h
+	add	w22,w22,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w1,w1,w7
+	add	w22,w22,w17			// h+=Sigma0(a)
+	add	w1,w1,w6
+	ldr	w6,[sp,#12]
+	str	w9,[sp,#8]
+	ror	w16,w26,#6
+	add	w21,w21,w19			// h+=K[i]
+	ror	w8,w3,#7
+	and	w17,w27,w26
+	ror	w7,w0,#17
+	bic	w19,w20,w26
+	ror	w9,w22,#2
+	add	w21,w21,w1			// h+=X[i]
+	eor	w16,w16,w26,ror#11
+	eor	w8,w8,w3,ror#18
+	orr	w17,w17,w19			// Ch(e,f,g)
+	eor	w19,w22,w23			// a^b, b^c in next round
+	eor	w16,w16,w26,ror#25	// Sigma1(e)
+	eor	w9,w9,w22,ror#13
+	add	w21,w21,w17			// h+=Ch(e,f,g)
+	and	w28,w28,w19			// (b^c)&=(a^b)
+	eor	w7,w7,w0,ror#19
+	eor	w8,w8,w3,lsr#3	// sigma0(X[i+1])
+	add	w21,w21,w16			// h+=Sigma1(e)
+	eor	w28,w28,w23			// Maj(a,b,c)
+	eor	w17,w9,w22,ror#22	// Sigma0(a)
+	eor	w7,w7,w0,lsr#10	// sigma1(X[i+14])
+	add	w2,w2,w11
+	add	w25,w25,w21			// d+=h
+	add	w21,w21,w28			// h+=Maj(a,b,c)
+	ldr	w28,[x30],#4		// *K++, w19 in next round
+	add	w2,w2,w8
+	add	w21,w21,w17			// h+=Sigma0(a)
+	add	w2,w2,w7
+	ldr	w7,[sp,#0]
+	str	w10,[sp,#12]
+	ror	w16,w25,#6
+	add	w20,w20,w28			// h+=K[i]
+	ror	w9,w4,#7
+	and	w17,w26,w25
+	ror	w8,w1,#17
+	bic	w28,w27,w25
+	ror	w10,w21,#2
+	add	w20,w20,w2			// h+=X[i]
+	eor	w16,w16,w25,ror#11
+	eor	w9,w9,w4,ror#18
+	orr	w17,w17,w28			// Ch(e,f,g)
+	eor	w28,w21,w22			// a^b, b^c in next round
+	eor	w16,w16,w25,ror#25	// Sigma1(e)
+	eor	w10,w10,w21,ror#13
+	add	w20,w20,w17			// h+=Ch(e,f,g)
+	and	w19,w19,w28			// (b^c)&=(a^b)
+	eor	w8,w8,w1,ror#19
+	eor	w9,w9,w4,lsr#3	// sigma0(X[i+1])
+	add	w20,w20,w16			// h+=Sigma1(e)
+	eor	w19,w19,w22			// Maj(a,b,c)
+	eor	w17,w10,w21,ror#22	// Sigma0(a)
+	eor	w8,w8,w1,lsr#10	// sigma1(X[i+14])
+	add	w3,w3,w12
+	add	w24,w24,w20			// d+=h
+	add	w20,w20,w19			// h+=Maj(a,b,c)
+	ldr	w19,[x30],#4		// *K++, w28 in next round
+	add	w3,w3,w9
+	add	w20,w20,w17			// h+=Sigma0(a)
+	add	w3,w3,w8
+	cbnz	w19,.Loop_16_xx
+
+	ldp	x0,x2,[x29,#96]
+	ldr	x1,[x29,#112]
+	sub	x30,x30,#260		// rewind
+
+	ldp	w3,w4,[x0]
+	ldp	w5,w6,[x0,#2*4]
+	add	x1,x1,#14*4			// advance input pointer
+	ldp	w7,w8,[x0,#4*4]
+	add	w20,w20,w3
+	ldp	w9,w10,[x0,#6*4]
+	add	w21,w21,w4
+	add	w22,w22,w5
+	add	w23,w23,w6
+	stp	w20,w21,[x0]
+	add	w24,w24,w7
+	add	w25,w25,w8
+	stp	w22,w23,[x0,#2*4]
+	add	w26,w26,w9
+	add	w27,w27,w10
+	cmp	x1,x2
+	stp	w24,w25,[x0,#4*4]
+	stp	w26,w27,[x0,#6*4]
+	b.ne	.Loop
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#4*4
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#128
+	ret
+.size	sha256_block_data_order,.-sha256_block_data_order
+
+.align	6
+.type	.LK256,%object
+.LK256:
+	.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+	.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+	.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+	.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+	.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+	.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+	.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+	.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+	.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+	.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+	.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+	.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+	.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+	.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+	.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+	.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+	.long	0	//terminator
+.size	.LK256,.-.LK256
+#ifndef	__KERNEL__
+.align	3
+.LOPENSSL_armcap_P:
+# ifdef	__ILP32__
+	.long	OPENSSL_armcap_P-.
+# else
+	.quad	OPENSSL_armcap_P-.
+# endif
+#endif
+.asciz	"SHA256 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align	2
+#ifndef	__KERNEL__
+.type	sha256_block_armv8,%function
+.align	6
+sha256_block_armv8:
+.Lv8_entry:
+	stp		x29,x30,[sp,#-16]!
+	add		x29,sp,#0
+
+	ld1		{v0.4s,v1.4s},[x0]
+	adr		x3,.LK256
+
+.Loop_hw:
+	ld1		{v4.16b-v7.16b},[x1],#64
+	sub		x2,x2,#1
+	ld1		{v16.4s},[x3],#16
+	rev32		v4.16b,v4.16b
+	rev32		v5.16b,v5.16b
+	rev32		v6.16b,v6.16b
+	rev32		v7.16b,v7.16b
+	orr		v18.16b,v0.16b,v0.16b		// offload
+	orr		v19.16b,v1.16b,v1.16b
+	ld1		{v17.4s},[x3],#16
+	add		v16.4s,v16.4s,v4.4s
+	.inst	0x5e2828a4	//sha256su0 v4.16b,v5.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+	.inst	0x5e0760c4	//sha256su1 v4.16b,v6.16b,v7.16b
+	ld1		{v16.4s},[x3],#16
+	add		v17.4s,v17.4s,v5.4s
+	.inst	0x5e2828c5	//sha256su0 v5.16b,v6.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+	.inst	0x5e0460e5	//sha256su1 v5.16b,v7.16b,v4.16b
+	ld1		{v17.4s},[x3],#16
+	add		v16.4s,v16.4s,v6.4s
+	.inst	0x5e2828e6	//sha256su0 v6.16b,v7.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+	.inst	0x5e056086	//sha256su1 v6.16b,v4.16b,v5.16b
+	ld1		{v16.4s},[x3],#16
+	add		v17.4s,v17.4s,v7.4s
+	.inst	0x5e282887	//sha256su0 v7.16b,v4.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+	.inst	0x5e0660a7	//sha256su1 v7.16b,v5.16b,v6.16b
+	ld1		{v17.4s},[x3],#16
+	add		v16.4s,v16.4s,v4.4s
+	.inst	0x5e2828a4	//sha256su0 v4.16b,v5.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+	.inst	0x5e0760c4	//sha256su1 v4.16b,v6.16b,v7.16b
+	ld1		{v16.4s},[x3],#16
+	add		v17.4s,v17.4s,v5.4s
+	.inst	0x5e2828c5	//sha256su0 v5.16b,v6.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+	.inst	0x5e0460e5	//sha256su1 v5.16b,v7.16b,v4.16b
+	ld1		{v17.4s},[x3],#16
+	add		v16.4s,v16.4s,v6.4s
+	.inst	0x5e2828e6	//sha256su0 v6.16b,v7.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+	.inst	0x5e056086	//sha256su1 v6.16b,v4.16b,v5.16b
+	ld1		{v16.4s},[x3],#16
+	add		v17.4s,v17.4s,v7.4s
+	.inst	0x5e282887	//sha256su0 v7.16b,v4.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+	.inst	0x5e0660a7	//sha256su1 v7.16b,v5.16b,v6.16b
+	ld1		{v17.4s},[x3],#16
+	add		v16.4s,v16.4s,v4.4s
+	.inst	0x5e2828a4	//sha256su0 v4.16b,v5.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+	.inst	0x5e0760c4	//sha256su1 v4.16b,v6.16b,v7.16b
+	ld1		{v16.4s},[x3],#16
+	add		v17.4s,v17.4s,v5.4s
+	.inst	0x5e2828c5	//sha256su0 v5.16b,v6.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+	.inst	0x5e0460e5	//sha256su1 v5.16b,v7.16b,v4.16b
+	ld1		{v17.4s},[x3],#16
+	add		v16.4s,v16.4s,v6.4s
+	.inst	0x5e2828e6	//sha256su0 v6.16b,v7.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+	.inst	0x5e056086	//sha256su1 v6.16b,v4.16b,v5.16b
+	ld1		{v16.4s},[x3],#16
+	add		v17.4s,v17.4s,v7.4s
+	.inst	0x5e282887	//sha256su0 v7.16b,v4.16b
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+	.inst	0x5e0660a7	//sha256su1 v7.16b,v5.16b,v6.16b
+	ld1		{v17.4s},[x3],#16
+	add		v16.4s,v16.4s,v4.4s
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+
+	ld1		{v16.4s},[x3],#16
+	add		v17.4s,v17.4s,v5.4s
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+
+	ld1		{v17.4s},[x3]
+	add		v16.4s,v16.4s,v6.4s
+	sub		x3,x3,#64*4-16	// rewind
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e104020	//sha256h v0.16b,v1.16b,v16.4s
+	.inst	0x5e105041	//sha256h2 v1.16b,v2.16b,v16.4s
+
+	add		v17.4s,v17.4s,v7.4s
+	orr		v2.16b,v0.16b,v0.16b
+	.inst	0x5e114020	//sha256h v0.16b,v1.16b,v17.4s
+	.inst	0x5e115041	//sha256h2 v1.16b,v2.16b,v17.4s
+
+	add		v0.4s,v0.4s,v18.4s
+	add		v1.4s,v1.4s,v19.4s
+
+	cbnz		x2,.Loop_hw
+
+	st1		{v0.4s,v1.4s},[x0]
+
+	ldr		x29,[sp],#16
+	ret
+.size	sha256_block_armv8,.-sha256_block_armv8
+#endif
+#ifdef	__KERNEL__
+.globl	sha256_block_neon
+#endif
+.type	sha256_block_neon,%function
+.align	4
+sha256_block_neon:
+.Lneon_entry:
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	sub	sp,sp,#16*4
+
+	adr	x16,.LK256
+	add	x2,x1,x2,lsl#6	// len to point at the end of inp
+
+	ld1	{v0.16b},[x1], #16
+	ld1	{v1.16b},[x1], #16
+	ld1	{v2.16b},[x1], #16
+	ld1	{v3.16b},[x1], #16
+	ld1	{v4.4s},[x16], #16
+	ld1	{v5.4s},[x16], #16
+	ld1	{v6.4s},[x16], #16
+	ld1	{v7.4s},[x16], #16
+	rev32	v0.16b,v0.16b		// yes, even on
+	rev32	v1.16b,v1.16b		// big-endian
+	rev32	v2.16b,v2.16b
+	rev32	v3.16b,v3.16b
+	mov	x17,sp
+	add	v4.4s,v4.4s,v0.4s
+	add	v5.4s,v5.4s,v1.4s
+	add	v6.4s,v6.4s,v2.4s
+	st1	{v4.4s-v5.4s},[x17], #32
+	add	v7.4s,v7.4s,v3.4s
+	st1	{v6.4s-v7.4s},[x17]
+	sub	x17,x17,#32
+
+	ldp	w3,w4,[x0]
+	ldp	w5,w6,[x0,#8]
+	ldp	w7,w8,[x0,#16]
+	ldp	w9,w10,[x0,#24]
+	ldr	w12,[sp,#0]
+	mov	w13,wzr
+	eor	w14,w4,w5
+	mov	w15,wzr
+	b	.L_00_48
+
+.align	4
+.L_00_48:
+	ext	v4.16b,v0.16b,v1.16b,#4
+	add	w10,w10,w12
+	add	w3,w3,w15
+	and	w12,w8,w7
+	bic	w15,w9,w7
+	ext	v7.16b,v2.16b,v3.16b,#4
+	eor	w11,w7,w7,ror#5
+	add	w3,w3,w13
+	mov	d19,v3.d[1]
+	orr	w12,w12,w15
+	eor	w11,w11,w7,ror#19
+	ushr	v6.4s,v4.4s,#7
+	eor	w15,w3,w3,ror#11
+	ushr	v5.4s,v4.4s,#3
+	add	w10,w10,w12
+	add	v0.4s,v0.4s,v7.4s
+	ror	w11,w11,#6
+	sli	v6.4s,v4.4s,#25
+	eor	w13,w3,w4
+	eor	w15,w15,w3,ror#20
+	ushr	v7.4s,v4.4s,#18
+	add	w10,w10,w11
+	ldr	w12,[sp,#4]
+	and	w14,w14,w13
+	eor	v5.16b,v5.16b,v6.16b
+	ror	w15,w15,#2
+	add	w6,w6,w10
+	sli	v7.4s,v4.4s,#14
+	eor	w14,w14,w4
+	ushr	v16.4s,v19.4s,#17
+	add	w9,w9,w12
+	add	w10,w10,w15
+	and	w12,w7,w6
+	eor	v5.16b,v5.16b,v7.16b
+	bic	w15,w8,w6
+	eor	w11,w6,w6,ror#5
+	sli	v16.4s,v19.4s,#15
+	add	w10,w10,w14
+	orr	w12,w12,w15
+	ushr	v17.4s,v19.4s,#10
+	eor	w11,w11,w6,ror#19
+	eor	w15,w10,w10,ror#11
+	ushr	v7.4s,v19.4s,#19
+	add	w9,w9,w12
+	ror	w11,w11,#6
+	add	v0.4s,v0.4s,v5.4s
+	eor	w14,w10,w3
+	eor	w15,w15,w10,ror#20
+	sli	v7.4s,v19.4s,#13
+	add	w9,w9,w11
+	ldr	w12,[sp,#8]
+	and	w13,w13,w14
+	eor	v17.16b,v17.16b,v16.16b
+	ror	w15,w15,#2
+	add	w5,w5,w9
+	eor	w13,w13,w3
+	eor	v17.16b,v17.16b,v7.16b
+	add	w8,w8,w12
+	add	w9,w9,w15
+	and	w12,w6,w5
+	add	v0.4s,v0.4s,v17.4s
+	bic	w15,w7,w5
+	eor	w11,w5,w5,ror#5
+	add	w9,w9,w13
+	ushr	v18.4s,v0.4s,#17
+	orr	w12,w12,w15
+	ushr	v19.4s,v0.4s,#10
+	eor	w11,w11,w5,ror#19
+	eor	w15,w9,w9,ror#11
+	sli	v18.4s,v0.4s,#15
+	add	w8,w8,w12
+	ushr	v17.4s,v0.4s,#19
+	ror	w11,w11,#6
+	eor	w13,w9,w10
+	eor	v19.16b,v19.16b,v18.16b
+	eor	w15,w15,w9,ror#20
+	add	w8,w8,w11
+	sli	v17.4s,v0.4s,#13
+	ldr	w12,[sp,#12]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	ld1	{v4.4s},[x16], #16
+	add	w4,w4,w8
+	eor	v19.16b,v19.16b,v17.16b
+	eor	w14,w14,w10
+	eor	v17.16b,v17.16b,v17.16b
+	add	w7,w7,w12
+	add	w8,w8,w15
+	and	w12,w5,w4
+	mov	v17.d[1],v19.d[0]
+	bic	w15,w6,w4
+	eor	w11,w4,w4,ror#5
+	add	w8,w8,w14
+	add	v0.4s,v0.4s,v17.4s
+	orr	w12,w12,w15
+	eor	w11,w11,w4,ror#19
+	eor	w15,w8,w8,ror#11
+	add	v4.4s,v4.4s,v0.4s
+	add	w7,w7,w12
+	ror	w11,w11,#6
+	eor	w14,w8,w9
+	eor	w15,w15,w8,ror#20
+	add	w7,w7,w11
+	ldr	w12,[sp,#16]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w3,w3,w7
+	eor	w13,w13,w9
+	st1	{v4.4s},[x17], #16
+	ext	v4.16b,v1.16b,v2.16b,#4
+	add	w6,w6,w12
+	add	w7,w7,w15
+	and	w12,w4,w3
+	bic	w15,w5,w3
+	ext	v7.16b,v3.16b,v0.16b,#4
+	eor	w11,w3,w3,ror#5
+	add	w7,w7,w13
+	mov	d19,v0.d[1]
+	orr	w12,w12,w15
+	eor	w11,w11,w3,ror#19
+	ushr	v6.4s,v4.4s,#7
+	eor	w15,w7,w7,ror#11
+	ushr	v5.4s,v4.4s,#3
+	add	w6,w6,w12
+	add	v1.4s,v1.4s,v7.4s
+	ror	w11,w11,#6
+	sli	v6.4s,v4.4s,#25
+	eor	w13,w7,w8
+	eor	w15,w15,w7,ror#20
+	ushr	v7.4s,v4.4s,#18
+	add	w6,w6,w11
+	ldr	w12,[sp,#20]
+	and	w14,w14,w13
+	eor	v5.16b,v5.16b,v6.16b
+	ror	w15,w15,#2
+	add	w10,w10,w6
+	sli	v7.4s,v4.4s,#14
+	eor	w14,w14,w8
+	ushr	v16.4s,v19.4s,#17
+	add	w5,w5,w12
+	add	w6,w6,w15
+	and	w12,w3,w10
+	eor	v5.16b,v5.16b,v7.16b
+	bic	w15,w4,w10
+	eor	w11,w10,w10,ror#5
+	sli	v16.4s,v19.4s,#15
+	add	w6,w6,w14
+	orr	w12,w12,w15
+	ushr	v17.4s,v19.4s,#10
+	eor	w11,w11,w10,ror#19
+	eor	w15,w6,w6,ror#11
+	ushr	v7.4s,v19.4s,#19
+	add	w5,w5,w12
+	ror	w11,w11,#6
+	add	v1.4s,v1.4s,v5.4s
+	eor	w14,w6,w7
+	eor	w15,w15,w6,ror#20
+	sli	v7.4s,v19.4s,#13
+	add	w5,w5,w11
+	ldr	w12,[sp,#24]
+	and	w13,w13,w14
+	eor	v17.16b,v17.16b,v16.16b
+	ror	w15,w15,#2
+	add	w9,w9,w5
+	eor	w13,w13,w7
+	eor	v17.16b,v17.16b,v7.16b
+	add	w4,w4,w12
+	add	w5,w5,w15
+	and	w12,w10,w9
+	add	v1.4s,v1.4s,v17.4s
+	bic	w15,w3,w9
+	eor	w11,w9,w9,ror#5
+	add	w5,w5,w13
+	ushr	v18.4s,v1.4s,#17
+	orr	w12,w12,w15
+	ushr	v19.4s,v1.4s,#10
+	eor	w11,w11,w9,ror#19
+	eor	w15,w5,w5,ror#11
+	sli	v18.4s,v1.4s,#15
+	add	w4,w4,w12
+	ushr	v17.4s,v1.4s,#19
+	ror	w11,w11,#6
+	eor	w13,w5,w6
+	eor	v19.16b,v19.16b,v18.16b
+	eor	w15,w15,w5,ror#20
+	add	w4,w4,w11
+	sli	v17.4s,v1.4s,#13
+	ldr	w12,[sp,#28]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	ld1	{v4.4s},[x16], #16
+	add	w8,w8,w4
+	eor	v19.16b,v19.16b,v17.16b
+	eor	w14,w14,w6
+	eor	v17.16b,v17.16b,v17.16b
+	add	w3,w3,w12
+	add	w4,w4,w15
+	and	w12,w9,w8
+	mov	v17.d[1],v19.d[0]
+	bic	w15,w10,w8
+	eor	w11,w8,w8,ror#5
+	add	w4,w4,w14
+	add	v1.4s,v1.4s,v17.4s
+	orr	w12,w12,w15
+	eor	w11,w11,w8,ror#19
+	eor	w15,w4,w4,ror#11
+	add	v4.4s,v4.4s,v1.4s
+	add	w3,w3,w12
+	ror	w11,w11,#6
+	eor	w14,w4,w5
+	eor	w15,w15,w4,ror#20
+	add	w3,w3,w11
+	ldr	w12,[sp,#32]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w7,w7,w3
+	eor	w13,w13,w5
+	st1	{v4.4s},[x17], #16
+	ext	v4.16b,v2.16b,v3.16b,#4
+	add	w10,w10,w12
+	add	w3,w3,w15
+	and	w12,w8,w7
+	bic	w15,w9,w7
+	ext	v7.16b,v0.16b,v1.16b,#4
+	eor	w11,w7,w7,ror#5
+	add	w3,w3,w13
+	mov	d19,v1.d[1]
+	orr	w12,w12,w15
+	eor	w11,w11,w7,ror#19
+	ushr	v6.4s,v4.4s,#7
+	eor	w15,w3,w3,ror#11
+	ushr	v5.4s,v4.4s,#3
+	add	w10,w10,w12
+	add	v2.4s,v2.4s,v7.4s
+	ror	w11,w11,#6
+	sli	v6.4s,v4.4s,#25
+	eor	w13,w3,w4
+	eor	w15,w15,w3,ror#20
+	ushr	v7.4s,v4.4s,#18
+	add	w10,w10,w11
+	ldr	w12,[sp,#36]
+	and	w14,w14,w13
+	eor	v5.16b,v5.16b,v6.16b
+	ror	w15,w15,#2
+	add	w6,w6,w10
+	sli	v7.4s,v4.4s,#14
+	eor	w14,w14,w4
+	ushr	v16.4s,v19.4s,#17
+	add	w9,w9,w12
+	add	w10,w10,w15
+	and	w12,w7,w6
+	eor	v5.16b,v5.16b,v7.16b
+	bic	w15,w8,w6
+	eor	w11,w6,w6,ror#5
+	sli	v16.4s,v19.4s,#15
+	add	w10,w10,w14
+	orr	w12,w12,w15
+	ushr	v17.4s,v19.4s,#10
+	eor	w11,w11,w6,ror#19
+	eor	w15,w10,w10,ror#11
+	ushr	v7.4s,v19.4s,#19
+	add	w9,w9,w12
+	ror	w11,w11,#6
+	add	v2.4s,v2.4s,v5.4s
+	eor	w14,w10,w3
+	eor	w15,w15,w10,ror#20
+	sli	v7.4s,v19.4s,#13
+	add	w9,w9,w11
+	ldr	w12,[sp,#40]
+	and	w13,w13,w14
+	eor	v17.16b,v17.16b,v16.16b
+	ror	w15,w15,#2
+	add	w5,w5,w9
+	eor	w13,w13,w3
+	eor	v17.16b,v17.16b,v7.16b
+	add	w8,w8,w12
+	add	w9,w9,w15
+	and	w12,w6,w5
+	add	v2.4s,v2.4s,v17.4s
+	bic	w15,w7,w5
+	eor	w11,w5,w5,ror#5
+	add	w9,w9,w13
+	ushr	v18.4s,v2.4s,#17
+	orr	w12,w12,w15
+	ushr	v19.4s,v2.4s,#10
+	eor	w11,w11,w5,ror#19
+	eor	w15,w9,w9,ror#11
+	sli	v18.4s,v2.4s,#15
+	add	w8,w8,w12
+	ushr	v17.4s,v2.4s,#19
+	ror	w11,w11,#6
+	eor	w13,w9,w10
+	eor	v19.16b,v19.16b,v18.16b
+	eor	w15,w15,w9,ror#20
+	add	w8,w8,w11
+	sli	v17.4s,v2.4s,#13
+	ldr	w12,[sp,#44]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	ld1	{v4.4s},[x16], #16
+	add	w4,w4,w8
+	eor	v19.16b,v19.16b,v17.16b
+	eor	w14,w14,w10
+	eor	v17.16b,v17.16b,v17.16b
+	add	w7,w7,w12
+	add	w8,w8,w15
+	and	w12,w5,w4
+	mov	v17.d[1],v19.d[0]
+	bic	w15,w6,w4
+	eor	w11,w4,w4,ror#5
+	add	w8,w8,w14
+	add	v2.4s,v2.4s,v17.4s
+	orr	w12,w12,w15
+	eor	w11,w11,w4,ror#19
+	eor	w15,w8,w8,ror#11
+	add	v4.4s,v4.4s,v2.4s
+	add	w7,w7,w12
+	ror	w11,w11,#6
+	eor	w14,w8,w9
+	eor	w15,w15,w8,ror#20
+	add	w7,w7,w11
+	ldr	w12,[sp,#48]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w3,w3,w7
+	eor	w13,w13,w9
+	st1	{v4.4s},[x17], #16
+	ext	v4.16b,v3.16b,v0.16b,#4
+	add	w6,w6,w12
+	add	w7,w7,w15
+	and	w12,w4,w3
+	bic	w15,w5,w3
+	ext	v7.16b,v1.16b,v2.16b,#4
+	eor	w11,w3,w3,ror#5
+	add	w7,w7,w13
+	mov	d19,v2.d[1]
+	orr	w12,w12,w15
+	eor	w11,w11,w3,ror#19
+	ushr	v6.4s,v4.4s,#7
+	eor	w15,w7,w7,ror#11
+	ushr	v5.4s,v4.4s,#3
+	add	w6,w6,w12
+	add	v3.4s,v3.4s,v7.4s
+	ror	w11,w11,#6
+	sli	v6.4s,v4.4s,#25
+	eor	w13,w7,w8
+	eor	w15,w15,w7,ror#20
+	ushr	v7.4s,v4.4s,#18
+	add	w6,w6,w11
+	ldr	w12,[sp,#52]
+	and	w14,w14,w13
+	eor	v5.16b,v5.16b,v6.16b
+	ror	w15,w15,#2
+	add	w10,w10,w6
+	sli	v7.4s,v4.4s,#14
+	eor	w14,w14,w8
+	ushr	v16.4s,v19.4s,#17
+	add	w5,w5,w12
+	add	w6,w6,w15
+	and	w12,w3,w10
+	eor	v5.16b,v5.16b,v7.16b
+	bic	w15,w4,w10
+	eor	w11,w10,w10,ror#5
+	sli	v16.4s,v19.4s,#15
+	add	w6,w6,w14
+	orr	w12,w12,w15
+	ushr	v17.4s,v19.4s,#10
+	eor	w11,w11,w10,ror#19
+	eor	w15,w6,w6,ror#11
+	ushr	v7.4s,v19.4s,#19
+	add	w5,w5,w12
+	ror	w11,w11,#6
+	add	v3.4s,v3.4s,v5.4s
+	eor	w14,w6,w7
+	eor	w15,w15,w6,ror#20
+	sli	v7.4s,v19.4s,#13
+	add	w5,w5,w11
+	ldr	w12,[sp,#56]
+	and	w13,w13,w14
+	eor	v17.16b,v17.16b,v16.16b
+	ror	w15,w15,#2
+	add	w9,w9,w5
+	eor	w13,w13,w7
+	eor	v17.16b,v17.16b,v7.16b
+	add	w4,w4,w12
+	add	w5,w5,w15
+	and	w12,w10,w9
+	add	v3.4s,v3.4s,v17.4s
+	bic	w15,w3,w9
+	eor	w11,w9,w9,ror#5
+	add	w5,w5,w13
+	ushr	v18.4s,v3.4s,#17
+	orr	w12,w12,w15
+	ushr	v19.4s,v3.4s,#10
+	eor	w11,w11,w9,ror#19
+	eor	w15,w5,w5,ror#11
+	sli	v18.4s,v3.4s,#15
+	add	w4,w4,w12
+	ushr	v17.4s,v3.4s,#19
+	ror	w11,w11,#6
+	eor	w13,w5,w6
+	eor	v19.16b,v19.16b,v18.16b
+	eor	w15,w15,w5,ror#20
+	add	w4,w4,w11
+	sli	v17.4s,v3.4s,#13
+	ldr	w12,[sp,#60]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	ld1	{v4.4s},[x16], #16
+	add	w8,w8,w4
+	eor	v19.16b,v19.16b,v17.16b
+	eor	w14,w14,w6
+	eor	v17.16b,v17.16b,v17.16b
+	add	w3,w3,w12
+	add	w4,w4,w15
+	and	w12,w9,w8
+	mov	v17.d[1],v19.d[0]
+	bic	w15,w10,w8
+	eor	w11,w8,w8,ror#5
+	add	w4,w4,w14
+	add	v3.4s,v3.4s,v17.4s
+	orr	w12,w12,w15
+	eor	w11,w11,w8,ror#19
+	eor	w15,w4,w4,ror#11
+	add	v4.4s,v4.4s,v3.4s
+	add	w3,w3,w12
+	ror	w11,w11,#6
+	eor	w14,w4,w5
+	eor	w15,w15,w4,ror#20
+	add	w3,w3,w11
+	ldr	w12,[x16]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w7,w7,w3
+	eor	w13,w13,w5
+	st1	{v4.4s},[x17], #16
+	cmp	w12,#0				// check for K256 terminator
+	ldr	w12,[sp,#0]
+	sub	x17,x17,#64
+	bne	.L_00_48
+
+	sub	x16,x16,#256		// rewind x16
+	cmp	x1,x2
+	mov	x17, #64
+	csel	x17, x17, xzr, eq
+	sub	x1,x1,x17			// avoid SEGV
+	mov	x17,sp
+	add	w10,w10,w12
+	add	w3,w3,w15
+	and	w12,w8,w7
+	ld1	{v0.16b},[x1],#16
+	bic	w15,w9,w7
+	eor	w11,w7,w7,ror#5
+	ld1	{v4.4s},[x16],#16
+	add	w3,w3,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w7,ror#19
+	eor	w15,w3,w3,ror#11
+	rev32	v0.16b,v0.16b
+	add	w10,w10,w12
+	ror	w11,w11,#6
+	eor	w13,w3,w4
+	eor	w15,w15,w3,ror#20
+	add	v4.4s,v4.4s,v0.4s
+	add	w10,w10,w11
+	ldr	w12,[sp,#4]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w6,w6,w10
+	eor	w14,w14,w4
+	add	w9,w9,w12
+	add	w10,w10,w15
+	and	w12,w7,w6
+	bic	w15,w8,w6
+	eor	w11,w6,w6,ror#5
+	add	w10,w10,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w6,ror#19
+	eor	w15,w10,w10,ror#11
+	add	w9,w9,w12
+	ror	w11,w11,#6
+	eor	w14,w10,w3
+	eor	w15,w15,w10,ror#20
+	add	w9,w9,w11
+	ldr	w12,[sp,#8]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w5,w5,w9
+	eor	w13,w13,w3
+	add	w8,w8,w12
+	add	w9,w9,w15
+	and	w12,w6,w5
+	bic	w15,w7,w5
+	eor	w11,w5,w5,ror#5
+	add	w9,w9,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w5,ror#19
+	eor	w15,w9,w9,ror#11
+	add	w8,w8,w12
+	ror	w11,w11,#6
+	eor	w13,w9,w10
+	eor	w15,w15,w9,ror#20
+	add	w8,w8,w11
+	ldr	w12,[sp,#12]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w4,w4,w8
+	eor	w14,w14,w10
+	add	w7,w7,w12
+	add	w8,w8,w15
+	and	w12,w5,w4
+	bic	w15,w6,w4
+	eor	w11,w4,w4,ror#5
+	add	w8,w8,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w4,ror#19
+	eor	w15,w8,w8,ror#11
+	add	w7,w7,w12
+	ror	w11,w11,#6
+	eor	w14,w8,w9
+	eor	w15,w15,w8,ror#20
+	add	w7,w7,w11
+	ldr	w12,[sp,#16]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w3,w3,w7
+	eor	w13,w13,w9
+	st1	{v4.4s},[x17], #16
+	add	w6,w6,w12
+	add	w7,w7,w15
+	and	w12,w4,w3
+	ld1	{v1.16b},[x1],#16
+	bic	w15,w5,w3
+	eor	w11,w3,w3,ror#5
+	ld1	{v4.4s},[x16],#16
+	add	w7,w7,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w3,ror#19
+	eor	w15,w7,w7,ror#11
+	rev32	v1.16b,v1.16b
+	add	w6,w6,w12
+	ror	w11,w11,#6
+	eor	w13,w7,w8
+	eor	w15,w15,w7,ror#20
+	add	v4.4s,v4.4s,v1.4s
+	add	w6,w6,w11
+	ldr	w12,[sp,#20]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w10,w10,w6
+	eor	w14,w14,w8
+	add	w5,w5,w12
+	add	w6,w6,w15
+	and	w12,w3,w10
+	bic	w15,w4,w10
+	eor	w11,w10,w10,ror#5
+	add	w6,w6,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w10,ror#19
+	eor	w15,w6,w6,ror#11
+	add	w5,w5,w12
+	ror	w11,w11,#6
+	eor	w14,w6,w7
+	eor	w15,w15,w6,ror#20
+	add	w5,w5,w11
+	ldr	w12,[sp,#24]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w9,w9,w5
+	eor	w13,w13,w7
+	add	w4,w4,w12
+	add	w5,w5,w15
+	and	w12,w10,w9
+	bic	w15,w3,w9
+	eor	w11,w9,w9,ror#5
+	add	w5,w5,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w9,ror#19
+	eor	w15,w5,w5,ror#11
+	add	w4,w4,w12
+	ror	w11,w11,#6
+	eor	w13,w5,w6
+	eor	w15,w15,w5,ror#20
+	add	w4,w4,w11
+	ldr	w12,[sp,#28]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w8,w8,w4
+	eor	w14,w14,w6
+	add	w3,w3,w12
+	add	w4,w4,w15
+	and	w12,w9,w8
+	bic	w15,w10,w8
+	eor	w11,w8,w8,ror#5
+	add	w4,w4,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w8,ror#19
+	eor	w15,w4,w4,ror#11
+	add	w3,w3,w12
+	ror	w11,w11,#6
+	eor	w14,w4,w5
+	eor	w15,w15,w4,ror#20
+	add	w3,w3,w11
+	ldr	w12,[sp,#32]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w7,w7,w3
+	eor	w13,w13,w5
+	st1	{v4.4s},[x17], #16
+	add	w10,w10,w12
+	add	w3,w3,w15
+	and	w12,w8,w7
+	ld1	{v2.16b},[x1],#16
+	bic	w15,w9,w7
+	eor	w11,w7,w7,ror#5
+	ld1	{v4.4s},[x16],#16
+	add	w3,w3,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w7,ror#19
+	eor	w15,w3,w3,ror#11
+	rev32	v2.16b,v2.16b
+	add	w10,w10,w12
+	ror	w11,w11,#6
+	eor	w13,w3,w4
+	eor	w15,w15,w3,ror#20
+	add	v4.4s,v4.4s,v2.4s
+	add	w10,w10,w11
+	ldr	w12,[sp,#36]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w6,w6,w10
+	eor	w14,w14,w4
+	add	w9,w9,w12
+	add	w10,w10,w15
+	and	w12,w7,w6
+	bic	w15,w8,w6
+	eor	w11,w6,w6,ror#5
+	add	w10,w10,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w6,ror#19
+	eor	w15,w10,w10,ror#11
+	add	w9,w9,w12
+	ror	w11,w11,#6
+	eor	w14,w10,w3
+	eor	w15,w15,w10,ror#20
+	add	w9,w9,w11
+	ldr	w12,[sp,#40]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w5,w5,w9
+	eor	w13,w13,w3
+	add	w8,w8,w12
+	add	w9,w9,w15
+	and	w12,w6,w5
+	bic	w15,w7,w5
+	eor	w11,w5,w5,ror#5
+	add	w9,w9,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w5,ror#19
+	eor	w15,w9,w9,ror#11
+	add	w8,w8,w12
+	ror	w11,w11,#6
+	eor	w13,w9,w10
+	eor	w15,w15,w9,ror#20
+	add	w8,w8,w11
+	ldr	w12,[sp,#44]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w4,w4,w8
+	eor	w14,w14,w10
+	add	w7,w7,w12
+	add	w8,w8,w15
+	and	w12,w5,w4
+	bic	w15,w6,w4
+	eor	w11,w4,w4,ror#5
+	add	w8,w8,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w4,ror#19
+	eor	w15,w8,w8,ror#11
+	add	w7,w7,w12
+	ror	w11,w11,#6
+	eor	w14,w8,w9
+	eor	w15,w15,w8,ror#20
+	add	w7,w7,w11
+	ldr	w12,[sp,#48]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w3,w3,w7
+	eor	w13,w13,w9
+	st1	{v4.4s},[x17], #16
+	add	w6,w6,w12
+	add	w7,w7,w15
+	and	w12,w4,w3
+	ld1	{v3.16b},[x1],#16
+	bic	w15,w5,w3
+	eor	w11,w3,w3,ror#5
+	ld1	{v4.4s},[x16],#16
+	add	w7,w7,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w3,ror#19
+	eor	w15,w7,w7,ror#11
+	rev32	v3.16b,v3.16b
+	add	w6,w6,w12
+	ror	w11,w11,#6
+	eor	w13,w7,w8
+	eor	w15,w15,w7,ror#20
+	add	v4.4s,v4.4s,v3.4s
+	add	w6,w6,w11
+	ldr	w12,[sp,#52]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w10,w10,w6
+	eor	w14,w14,w8
+	add	w5,w5,w12
+	add	w6,w6,w15
+	and	w12,w3,w10
+	bic	w15,w4,w10
+	eor	w11,w10,w10,ror#5
+	add	w6,w6,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w10,ror#19
+	eor	w15,w6,w6,ror#11
+	add	w5,w5,w12
+	ror	w11,w11,#6
+	eor	w14,w6,w7
+	eor	w15,w15,w6,ror#20
+	add	w5,w5,w11
+	ldr	w12,[sp,#56]
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w9,w9,w5
+	eor	w13,w13,w7
+	add	w4,w4,w12
+	add	w5,w5,w15
+	and	w12,w10,w9
+	bic	w15,w3,w9
+	eor	w11,w9,w9,ror#5
+	add	w5,w5,w13
+	orr	w12,w12,w15
+	eor	w11,w11,w9,ror#19
+	eor	w15,w5,w5,ror#11
+	add	w4,w4,w12
+	ror	w11,w11,#6
+	eor	w13,w5,w6
+	eor	w15,w15,w5,ror#20
+	add	w4,w4,w11
+	ldr	w12,[sp,#60]
+	and	w14,w14,w13
+	ror	w15,w15,#2
+	add	w8,w8,w4
+	eor	w14,w14,w6
+	add	w3,w3,w12
+	add	w4,w4,w15
+	and	w12,w9,w8
+	bic	w15,w10,w8
+	eor	w11,w8,w8,ror#5
+	add	w4,w4,w14
+	orr	w12,w12,w15
+	eor	w11,w11,w8,ror#19
+	eor	w15,w4,w4,ror#11
+	add	w3,w3,w12
+	ror	w11,w11,#6
+	eor	w14,w4,w5
+	eor	w15,w15,w4,ror#20
+	add	w3,w3,w11
+	and	w13,w13,w14
+	ror	w15,w15,#2
+	add	w7,w7,w3
+	eor	w13,w13,w5
+	st1	{v4.4s},[x17], #16
+	add	w3,w3,w15			// h+=Sigma0(a) from the past
+	ldp	w11,w12,[x0,#0]
+	add	w3,w3,w13			// h+=Maj(a,b,c) from the past
+	ldp	w13,w14,[x0,#8]
+	add	w3,w3,w11			// accumulate
+	add	w4,w4,w12
+	ldp	w11,w12,[x0,#16]
+	add	w5,w5,w13
+	add	w6,w6,w14
+	ldp	w13,w14,[x0,#24]
+	add	w7,w7,w11
+	add	w8,w8,w12
+	 ldr	w12,[sp,#0]
+	stp	w3,w4,[x0,#0]
+	add	w9,w9,w13
+	 mov	w13,wzr
+	stp	w5,w6,[x0,#8]
+	add	w10,w10,w14
+	stp	w7,w8,[x0,#16]
+	 eor	w14,w4,w5
+	stp	w9,w10,[x0,#24]
+	 mov	w15,wzr
+	 mov	x17,sp
+	b.ne	.L_00_48
+
+	ldr	x29,[x29]
+	add	sp,sp,#16*4+16
+	ret
+.size	sha256_block_neon,.-sha256_block_neon
+#ifndef	__KERNEL__
+.comm	OPENSSL_armcap_P,4,4
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/sha256-glue.c linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha256-glue.c
--- linux-libre-4.9-gnu/arch/arm64/crypto/sha256-glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha256-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,185 @@
+/*
+ * Linux/arm64 port of the OpenSSL SHA256 implementation for AArch64
+ *
+ * Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha.h>
+#include <crypto/sha256_base.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash for arm64");
+MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha224");
+MODULE_ALIAS_CRYPTO("sha256");
+
+asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
+					unsigned int num_blks);
+
+asmlinkage void sha256_block_neon(u32 *digest, const void *data,
+				  unsigned int num_blks);
+
+static int sha256_update(struct shash_desc *desc, const u8 *data,
+			 unsigned int len)
+{
+	return sha256_base_do_update(desc, data, len,
+				(sha256_block_fn *)sha256_block_data_order);
+}
+
+static int sha256_finup(struct shash_desc *desc, const u8 *data,
+			unsigned int len, u8 *out)
+{
+	if (len)
+		sha256_base_do_update(desc, data, len,
+				(sha256_block_fn *)sha256_block_data_order);
+	sha256_base_do_finalize(desc,
+				(sha256_block_fn *)sha256_block_data_order);
+
+	return sha256_base_finish(desc, out);
+}
+
+static int sha256_final(struct shash_desc *desc, u8 *out)
+{
+	return sha256_finup(desc, NULL, 0, out);
+}
+
+static struct shash_alg algs[] = { {
+	.digestsize		= SHA256_DIGEST_SIZE,
+	.init			= sha256_base_init,
+	.update			= sha256_update,
+	.final			= sha256_final,
+	.finup			= sha256_finup,
+	.descsize		= sizeof(struct sha256_state),
+	.base.cra_name		= "sha256",
+	.base.cra_driver_name	= "sha256-arm64",
+	.base.cra_priority	= 100,
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA256_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+}, {
+	.digestsize		= SHA224_DIGEST_SIZE,
+	.init			= sha224_base_init,
+	.update			= sha256_update,
+	.final			= sha256_final,
+	.finup			= sha256_finup,
+	.descsize		= sizeof(struct sha256_state),
+	.base.cra_name		= "sha224",
+	.base.cra_driver_name	= "sha224-arm64",
+	.base.cra_priority	= 100,
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA224_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+} };
+
+static int sha256_update_neon(struct shash_desc *desc, const u8 *data,
+			      unsigned int len)
+{
+	/*
+	 * Stacking and unstacking a substantial slice of the NEON register
+	 * file may significantly affect performance for small updates when
+	 * executing in interrupt context, so fall back to the scalar code
+	 * in that case.
+	 */
+	if (!may_use_simd())
+		return sha256_base_do_update(desc, data, len,
+				(sha256_block_fn *)sha256_block_data_order);
+
+	kernel_neon_begin();
+	sha256_base_do_update(desc, data, len,
+				(sha256_block_fn *)sha256_block_neon);
+	kernel_neon_end();
+
+	return 0;
+}
+
+static int sha256_finup_neon(struct shash_desc *desc, const u8 *data,
+			     unsigned int len, u8 *out)
+{
+	if (!may_use_simd()) {
+		if (len)
+			sha256_base_do_update(desc, data, len,
+				(sha256_block_fn *)sha256_block_data_order);
+		sha256_base_do_finalize(desc,
+				(sha256_block_fn *)sha256_block_data_order);
+	} else {
+		kernel_neon_begin();
+		if (len)
+			sha256_base_do_update(desc, data, len,
+				(sha256_block_fn *)sha256_block_neon);
+		sha256_base_do_finalize(desc,
+				(sha256_block_fn *)sha256_block_neon);
+		kernel_neon_end();
+	}
+	return sha256_base_finish(desc, out);
+}
+
+static int sha256_final_neon(struct shash_desc *desc, u8 *out)
+{
+	return sha256_finup_neon(desc, NULL, 0, out);
+}
+
+static struct shash_alg neon_algs[] = { {
+	.digestsize		= SHA256_DIGEST_SIZE,
+	.init			= sha256_base_init,
+	.update			= sha256_update_neon,
+	.final			= sha256_final_neon,
+	.finup			= sha256_finup_neon,
+	.descsize		= sizeof(struct sha256_state),
+	.base.cra_name		= "sha256",
+	.base.cra_driver_name	= "sha256-arm64-neon",
+	.base.cra_priority	= 150,
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA256_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+}, {
+	.digestsize		= SHA224_DIGEST_SIZE,
+	.init			= sha224_base_init,
+	.update			= sha256_update_neon,
+	.final			= sha256_final_neon,
+	.finup			= sha256_finup_neon,
+	.descsize		= sizeof(struct sha256_state),
+	.base.cra_name		= "sha224",
+	.base.cra_driver_name	= "sha224-arm64-neon",
+	.base.cra_priority	= 150,
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA224_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+} };
+
+static int __init sha256_mod_init(void)
+{
+	int ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
+	if (ret)
+		return ret;
+
+	if (elf_hwcap & HWCAP_ASIMD) {
+		ret = crypto_register_shashes(neon_algs, ARRAY_SIZE(neon_algs));
+		if (ret)
+			crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+	}
+	return ret;
+}
+
+static void __exit sha256_mod_fini(void)
+{
+	if (elf_hwcap & HWCAP_ASIMD)
+		crypto_unregister_shashes(neon_algs, ARRAY_SIZE(neon_algs));
+	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+
+module_init(sha256_mod_init);
+module_exit(sha256_mod_fini);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/sha2-ce-core.S linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha2-ce-core.S
--- linux-libre-4.9-gnu/arch/arm64/crypto/sha2-ce-core.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha2-ce-core.S	2017-02-12 16:03:20.000000000 -0500
@@ -85,7 +85,7 @@ ENTRY(sha2_ce_transform)
 	ld1		{v12.4s-v15.4s}, [x8]
 
 	/* load state */
-	ldp		dga, dgb, [x0]
+	ld1		{dgav.4s, dgbv.4s}, [x0]
 
 	/* load sha256_ce_state::finalize */
 	ldr		w4, [x0, #:lo12:sha256_ce_offsetof_finalize]
@@ -148,6 +148,6 @@ CPU_LE(	rev32		v19.16b, v19.16b	)
 	b		1b
 
 	/* store new state */
-3:	stp		dga, dgb, [x0]
+3:	st1		{dgav.4s, dgbv.4s}, [x0]
 	ret
 ENDPROC(sha2_ce_transform)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/sha512-armv8.pl linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha512-armv8.pl
--- linux-libre-4.9-gnu/arch/arm64/crypto/sha512-armv8.pl	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha512-armv8.pl	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,778 @@
+#! /usr/bin/env perl
+# Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+#
+# Permission to use under GPLv2 terms is granted.
+# ====================================================================
+#
+# SHA256/512 for ARMv8.
+#
+# Performance in cycles per processed byte and improvement coefficient
+# over code generated with "default" compiler:
+#
+#		SHA256-hw	SHA256(*)	SHA512
+# Apple A7	1.97		10.5 (+33%)	6.73 (-1%(**))
+# Cortex-A53	2.38		15.5 (+115%)	10.0 (+150%(***))
+# Cortex-A57	2.31		11.6 (+86%)	7.51 (+260%(***))
+# Denver	2.01		10.5 (+26%)	6.70 (+8%)
+# X-Gene			20.0 (+100%)	12.8 (+300%(***))
+# Mongoose	2.36		13.0 (+50%)	8.36 (+33%)
+#
+# (*)	Software SHA256 results are of lesser relevance, presented
+#	mostly for informational purposes.
+# (**)	The result is a trade-off: it's possible to improve it by
+#	10% (or by 1 cycle per round), but at the cost of 20% loss
+#	on Cortex-A53 (or by 4 cycles per round).
+# (***)	Super-impressive coefficients over gcc-generated code are
+#	indication of some compiler "pathology", most notably code
+#	generated with -mgeneral-regs-only is significanty faster
+#	and the gap is only 40-90%.
+#
+# October 2016.
+#
+# Originally it was reckoned that it makes no sense to implement NEON
+# version of SHA256 for 64-bit processors. This is because performance
+# improvement on most wide-spread Cortex-A5x processors was observed
+# to be marginal, same on Cortex-A53 and ~10% on A57. But then it was
+# observed that 32-bit NEON SHA256 performs significantly better than
+# 64-bit scalar version on *some* of the more recent processors. As
+# result 64-bit NEON version of SHA256 was added to provide best
+# all-round performance. For example it executes ~30% faster on X-Gene
+# and Mongoose. [For reference, NEON version of SHA512 is bound to
+# deliver much less improvement, likely *negative* on Cortex-A5x.
+# Which is why NEON support is limited to SHA256.]
+
+$output=pop;
+$flavour=pop;
+
+if ($flavour && $flavour ne "void") {
+    $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+    ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+    ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+    die "can't locate arm-xlate.pl";
+
+    open OUT,"| \"$^X\" $xlate $flavour $output";
+    *STDOUT=*OUT;
+} else {
+    open STDOUT,">$output";
+}
+
+if ($output =~ /512/) {
+	$BITS=512;
+	$SZ=8;
+	@Sigma0=(28,34,39);
+	@Sigma1=(14,18,41);
+	@sigma0=(1,  8, 7);
+	@sigma1=(19,61, 6);
+	$rounds=80;
+	$reg_t="x";
+} else {
+	$BITS=256;
+	$SZ=4;
+	@Sigma0=( 2,13,22);
+	@Sigma1=( 6,11,25);
+	@sigma0=( 7,18, 3);
+	@sigma1=(17,19,10);
+	$rounds=64;
+	$reg_t="w";
+}
+
+$func="sha${BITS}_block_data_order";
+
+($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30));
+
+@X=map("$reg_t$_",(3..15,0..2));
+@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("$reg_t$_",(20..27));
+($t0,$t1,$t2,$t3)=map("$reg_t$_",(16,17,19,28));
+
+sub BODY_00_xx {
+my ($i,$a,$b,$c,$d,$e,$f,$g,$h)=@_;
+my $j=($i+1)&15;
+my ($T0,$T1,$T2)=(@X[($i-8)&15],@X[($i-9)&15],@X[($i-10)&15]);
+   $T0=@X[$i+3] if ($i<11);
+
+$code.=<<___	if ($i<16);
+#ifndef	__AARCH64EB__
+	rev	@X[$i],@X[$i]			// $i
+#endif
+___
+$code.=<<___	if ($i<13 && ($i&1));
+	ldp	@X[$i+1],@X[$i+2],[$inp],#2*$SZ
+___
+$code.=<<___	if ($i==13);
+	ldp	@X[14],@X[15],[$inp]
+___
+$code.=<<___	if ($i>=14);
+	ldr	@X[($i-11)&15],[sp,#`$SZ*(($i-11)%4)`]
+___
+$code.=<<___	if ($i>0 && $i<16);
+	add	$a,$a,$t1			// h+=Sigma0(a)
+___
+$code.=<<___	if ($i>=11);
+	str	@X[($i-8)&15],[sp,#`$SZ*(($i-8)%4)`]
+___
+# While ARMv8 specifies merged rotate-n-logical operation such as
+# 'eor x,y,z,ror#n', it was found to negatively affect performance
+# on Apple A7. The reason seems to be that it requires even 'y' to
+# be available earlier. This means that such merged instruction is
+# not necessarily best choice on critical path... On the other hand
+# Cortex-A5x handles merged instructions much better than disjoint
+# rotate and logical... See (**) footnote above.
+$code.=<<___	if ($i<15);
+	ror	$t0,$e,#$Sigma1[0]
+	add	$h,$h,$t2			// h+=K[i]
+	eor	$T0,$e,$e,ror#`$Sigma1[2]-$Sigma1[1]`
+	and	$t1,$f,$e
+	bic	$t2,$g,$e
+	add	$h,$h,@X[$i&15]			// h+=X[i]
+	orr	$t1,$t1,$t2			// Ch(e,f,g)
+	eor	$t2,$a,$b			// a^b, b^c in next round
+	eor	$t0,$t0,$T0,ror#$Sigma1[1]	// Sigma1(e)
+	ror	$T0,$a,#$Sigma0[0]
+	add	$h,$h,$t1			// h+=Ch(e,f,g)
+	eor	$t1,$a,$a,ror#`$Sigma0[2]-$Sigma0[1]`
+	add	$h,$h,$t0			// h+=Sigma1(e)
+	and	$t3,$t3,$t2			// (b^c)&=(a^b)
+	add	$d,$d,$h			// d+=h
+	eor	$t3,$t3,$b			// Maj(a,b,c)
+	eor	$t1,$T0,$t1,ror#$Sigma0[1]	// Sigma0(a)
+	add	$h,$h,$t3			// h+=Maj(a,b,c)
+	ldr	$t3,[$Ktbl],#$SZ		// *K++, $t2 in next round
+	//add	$h,$h,$t1			// h+=Sigma0(a)
+___
+$code.=<<___	if ($i>=15);
+	ror	$t0,$e,#$Sigma1[0]
+	add	$h,$h,$t2			// h+=K[i]
+	ror	$T1,@X[($j+1)&15],#$sigma0[0]
+	and	$t1,$f,$e
+	ror	$T2,@X[($j+14)&15],#$sigma1[0]
+	bic	$t2,$g,$e
+	ror	$T0,$a,#$Sigma0[0]
+	add	$h,$h,@X[$i&15]			// h+=X[i]
+	eor	$t0,$t0,$e,ror#$Sigma1[1]
+	eor	$T1,$T1,@X[($j+1)&15],ror#$sigma0[1]
+	orr	$t1,$t1,$t2			// Ch(e,f,g)
+	eor	$t2,$a,$b			// a^b, b^c in next round
+	eor	$t0,$t0,$e,ror#$Sigma1[2]	// Sigma1(e)
+	eor	$T0,$T0,$a,ror#$Sigma0[1]
+	add	$h,$h,$t1			// h+=Ch(e,f,g)
+	and	$t3,$t3,$t2			// (b^c)&=(a^b)
+	eor	$T2,$T2,@X[($j+14)&15],ror#$sigma1[1]
+	eor	$T1,$T1,@X[($j+1)&15],lsr#$sigma0[2]	// sigma0(X[i+1])
+	add	$h,$h,$t0			// h+=Sigma1(e)
+	eor	$t3,$t3,$b			// Maj(a,b,c)
+	eor	$t1,$T0,$a,ror#$Sigma0[2]	// Sigma0(a)
+	eor	$T2,$T2,@X[($j+14)&15],lsr#$sigma1[2]	// sigma1(X[i+14])
+	add	@X[$j],@X[$j],@X[($j+9)&15]
+	add	$d,$d,$h			// d+=h
+	add	$h,$h,$t3			// h+=Maj(a,b,c)
+	ldr	$t3,[$Ktbl],#$SZ		// *K++, $t2 in next round
+	add	@X[$j],@X[$j],$T1
+	add	$h,$h,$t1			// h+=Sigma0(a)
+	add	@X[$j],@X[$j],$T2
+___
+	($t2,$t3)=($t3,$t2);
+}
+
+$code.=<<___;
+#ifndef	__KERNEL__
+# include "arm_arch.h"
+#endif
+
+.text
+
+.extern	OPENSSL_armcap_P
+.globl	$func
+.type	$func,%function
+.align	6
+$func:
+___
+$code.=<<___	if ($SZ==4);
+#ifndef	__KERNEL__
+# ifdef	__ILP32__
+	ldrsw	x16,.LOPENSSL_armcap_P
+# else
+	ldr	x16,.LOPENSSL_armcap_P
+# endif
+	adr	x17,.LOPENSSL_armcap_P
+	add	x16,x16,x17
+	ldr	w16,[x16]
+	tst	w16,#ARMV8_SHA256
+	b.ne	.Lv8_entry
+	tst	w16,#ARMV7_NEON
+	b.ne	.Lneon_entry
+#endif
+___
+$code.=<<___;
+	stp	x29,x30,[sp,#-128]!
+	add	x29,sp,#0
+
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#4*$SZ
+
+	ldp	$A,$B,[$ctx]				// load context
+	ldp	$C,$D,[$ctx,#2*$SZ]
+	ldp	$E,$F,[$ctx,#4*$SZ]
+	add	$num,$inp,$num,lsl#`log(16*$SZ)/log(2)`	// end of input
+	ldp	$G,$H,[$ctx,#6*$SZ]
+	adr	$Ktbl,.LK$BITS
+	stp	$ctx,$num,[x29,#96]
+
+.Loop:
+	ldp	@X[0],@X[1],[$inp],#2*$SZ
+	ldr	$t2,[$Ktbl],#$SZ			// *K++
+	eor	$t3,$B,$C				// magic seed
+	str	$inp,[x29,#112]
+___
+for ($i=0;$i<16;$i++)	{ &BODY_00_xx($i,@V); unshift(@V,pop(@V)); }
+$code.=".Loop_16_xx:\n";
+for (;$i<32;$i++)	{ &BODY_00_xx($i,@V); unshift(@V,pop(@V)); }
+$code.=<<___;
+	cbnz	$t2,.Loop_16_xx
+
+	ldp	$ctx,$num,[x29,#96]
+	ldr	$inp,[x29,#112]
+	sub	$Ktbl,$Ktbl,#`$SZ*($rounds+1)`		// rewind
+
+	ldp	@X[0],@X[1],[$ctx]
+	ldp	@X[2],@X[3],[$ctx,#2*$SZ]
+	add	$inp,$inp,#14*$SZ			// advance input pointer
+	ldp	@X[4],@X[5],[$ctx,#4*$SZ]
+	add	$A,$A,@X[0]
+	ldp	@X[6],@X[7],[$ctx,#6*$SZ]
+	add	$B,$B,@X[1]
+	add	$C,$C,@X[2]
+	add	$D,$D,@X[3]
+	stp	$A,$B,[$ctx]
+	add	$E,$E,@X[4]
+	add	$F,$F,@X[5]
+	stp	$C,$D,[$ctx,#2*$SZ]
+	add	$G,$G,@X[6]
+	add	$H,$H,@X[7]
+	cmp	$inp,$num
+	stp	$E,$F,[$ctx,#4*$SZ]
+	stp	$G,$H,[$ctx,#6*$SZ]
+	b.ne	.Loop
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#4*$SZ
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#128
+	ret
+.size	$func,.-$func
+
+.align	6
+.type	.LK$BITS,%object
+.LK$BITS:
+___
+$code.=<<___ if ($SZ==8);
+	.quad	0x428a2f98d728ae22,0x7137449123ef65cd
+	.quad	0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+	.quad	0x3956c25bf348b538,0x59f111f1b605d019
+	.quad	0x923f82a4af194f9b,0xab1c5ed5da6d8118
+	.quad	0xd807aa98a3030242,0x12835b0145706fbe
+	.quad	0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+	.quad	0x72be5d74f27b896f,0x80deb1fe3b1696b1
+	.quad	0x9bdc06a725c71235,0xc19bf174cf692694
+	.quad	0xe49b69c19ef14ad2,0xefbe4786384f25e3
+	.quad	0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+	.quad	0x2de92c6f592b0275,0x4a7484aa6ea6e483
+	.quad	0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+	.quad	0x983e5152ee66dfab,0xa831c66d2db43210
+	.quad	0xb00327c898fb213f,0xbf597fc7beef0ee4
+	.quad	0xc6e00bf33da88fc2,0xd5a79147930aa725
+	.quad	0x06ca6351e003826f,0x142929670a0e6e70
+	.quad	0x27b70a8546d22ffc,0x2e1b21385c26c926
+	.quad	0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+	.quad	0x650a73548baf63de,0x766a0abb3c77b2a8
+	.quad	0x81c2c92e47edaee6,0x92722c851482353b
+	.quad	0xa2bfe8a14cf10364,0xa81a664bbc423001
+	.quad	0xc24b8b70d0f89791,0xc76c51a30654be30
+	.quad	0xd192e819d6ef5218,0xd69906245565a910
+	.quad	0xf40e35855771202a,0x106aa07032bbd1b8
+	.quad	0x19a4c116b8d2d0c8,0x1e376c085141ab53
+	.quad	0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+	.quad	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+	.quad	0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+	.quad	0x748f82ee5defb2fc,0x78a5636f43172f60
+	.quad	0x84c87814a1f0ab72,0x8cc702081a6439ec
+	.quad	0x90befffa23631e28,0xa4506cebde82bde9
+	.quad	0xbef9a3f7b2c67915,0xc67178f2e372532b
+	.quad	0xca273eceea26619c,0xd186b8c721c0c207
+	.quad	0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+	.quad	0x06f067aa72176fba,0x0a637dc5a2c898a6
+	.quad	0x113f9804bef90dae,0x1b710b35131c471b
+	.quad	0x28db77f523047d84,0x32caab7b40c72493
+	.quad	0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+	.quad	0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+	.quad	0x5fcb6fab3ad6faec,0x6c44198c4a475817
+	.quad	0	// terminator
+___
+$code.=<<___ if ($SZ==4);
+	.long	0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
+	.long	0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
+	.long	0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
+	.long	0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
+	.long	0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
+	.long	0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
+	.long	0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
+	.long	0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
+	.long	0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
+	.long	0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
+	.long	0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
+	.long	0xd192e819,0xd6990624,0xf40e3585,0x106aa070
+	.long	0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
+	.long	0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
+	.long	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
+	.long	0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
+	.long	0	//terminator
+___
+$code.=<<___;
+.size	.LK$BITS,.-.LK$BITS
+#ifndef	__KERNEL__
+.align	3
+.LOPENSSL_armcap_P:
+# ifdef	__ILP32__
+	.long	OPENSSL_armcap_P-.
+# else
+	.quad	OPENSSL_armcap_P-.
+# endif
+#endif
+.asciz	"SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+.align	2
+___
+
+if ($SZ==4) {
+my $Ktbl="x3";
+
+my ($ABCD,$EFGH,$abcd)=map("v$_.16b",(0..2));
+my @MSG=map("v$_.16b",(4..7));
+my ($W0,$W1)=("v16.4s","v17.4s");
+my ($ABCD_SAVE,$EFGH_SAVE)=("v18.16b","v19.16b");
+
+$code.=<<___;
+#ifndef	__KERNEL__
+.type	sha256_block_armv8,%function
+.align	6
+sha256_block_armv8:
+.Lv8_entry:
+	stp		x29,x30,[sp,#-16]!
+	add		x29,sp,#0
+
+	ld1.32		{$ABCD,$EFGH},[$ctx]
+	adr		$Ktbl,.LK256
+
+.Loop_hw:
+	ld1		{@MSG[0]-@MSG[3]},[$inp],#64
+	sub		$num,$num,#1
+	ld1.32		{$W0},[$Ktbl],#16
+	rev32		@MSG[0],@MSG[0]
+	rev32		@MSG[1],@MSG[1]
+	rev32		@MSG[2],@MSG[2]
+	rev32		@MSG[3],@MSG[3]
+	orr		$ABCD_SAVE,$ABCD,$ABCD		// offload
+	orr		$EFGH_SAVE,$EFGH,$EFGH
+___
+for($i=0;$i<12;$i++) {
+$code.=<<___;
+	ld1.32		{$W1},[$Ktbl],#16
+	add.i32		$W0,$W0,@MSG[0]
+	sha256su0	@MSG[0],@MSG[1]
+	orr		$abcd,$ABCD,$ABCD
+	sha256h		$ABCD,$EFGH,$W0
+	sha256h2	$EFGH,$abcd,$W0
+	sha256su1	@MSG[0],@MSG[2],@MSG[3]
+___
+	($W0,$W1)=($W1,$W0);	push(@MSG,shift(@MSG));
+}
+$code.=<<___;
+	ld1.32		{$W1},[$Ktbl],#16
+	add.i32		$W0,$W0,@MSG[0]
+	orr		$abcd,$ABCD,$ABCD
+	sha256h		$ABCD,$EFGH,$W0
+	sha256h2	$EFGH,$abcd,$W0
+
+	ld1.32		{$W0},[$Ktbl],#16
+	add.i32		$W1,$W1,@MSG[1]
+	orr		$abcd,$ABCD,$ABCD
+	sha256h		$ABCD,$EFGH,$W1
+	sha256h2	$EFGH,$abcd,$W1
+
+	ld1.32		{$W1},[$Ktbl]
+	add.i32		$W0,$W0,@MSG[2]
+	sub		$Ktbl,$Ktbl,#$rounds*$SZ-16	// rewind
+	orr		$abcd,$ABCD,$ABCD
+	sha256h		$ABCD,$EFGH,$W0
+	sha256h2	$EFGH,$abcd,$W0
+
+	add.i32		$W1,$W1,@MSG[3]
+	orr		$abcd,$ABCD,$ABCD
+	sha256h		$ABCD,$EFGH,$W1
+	sha256h2	$EFGH,$abcd,$W1
+
+	add.i32		$ABCD,$ABCD,$ABCD_SAVE
+	add.i32		$EFGH,$EFGH,$EFGH_SAVE
+
+	cbnz		$num,.Loop_hw
+
+	st1.32		{$ABCD,$EFGH},[$ctx]
+
+	ldr		x29,[sp],#16
+	ret
+.size	sha256_block_armv8,.-sha256_block_armv8
+#endif
+___
+}
+
+if ($SZ==4) {	######################################### NEON stuff #
+# You'll surely note a lot of similarities with sha256-armv4 module,
+# and of course it's not a coincidence. sha256-armv4 was used as
+# initial template, but was adapted for ARMv8 instruction set and
+# extensively re-tuned for all-round performance.
+
+my @V = ($A,$B,$C,$D,$E,$F,$G,$H) = map("w$_",(3..10));
+my ($t0,$t1,$t2,$t3,$t4) = map("w$_",(11..15));
+my $Ktbl="x16";
+my $Xfer="x17";
+my @X = map("q$_",(0..3));
+my ($T0,$T1,$T2,$T3,$T4,$T5,$T6,$T7) = map("q$_",(4..7,16..19));
+my $j=0;
+
+sub AUTOLOAD()          # thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+  my $arg = pop;
+    $arg = "#$arg" if ($arg*1 eq $arg);
+    $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+sub Dscalar { shift =~ m|[qv]([0-9]+)|?"d$1":""; }
+sub Dlo     { shift =~ m|[qv]([0-9]+)|?"v$1.d[0]":""; }
+sub Dhi     { shift =~ m|[qv]([0-9]+)|?"v$1.d[1]":""; }
+
+sub Xupdate()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);
+  my ($a,$b,$c,$d,$e,$f,$g,$h);
+
+	&ext_8		($T0,@X[0],@X[1],4);	# X[1..4]
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&ext_8		($T3,@X[2],@X[3],4);	# X[9..12]
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&mov		(&Dscalar($T7),&Dhi(@X[3]));	# X[14..15]
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&ushr_32	($T2,$T0,$sigma0[0]);
+	 eval(shift(@insns));
+	&ushr_32	($T1,$T0,$sigma0[2]);
+	 eval(shift(@insns));
+	&add_32 	(@X[0],@X[0],$T3);	# X[0..3] += X[9..12]
+	 eval(shift(@insns));
+	&sli_32		($T2,$T0,32-$sigma0[0]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&ushr_32	($T3,$T0,$sigma0[1]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&eor_8		($T1,$T1,$T2);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&sli_32		($T3,$T0,32-$sigma0[1]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &ushr_32	($T4,$T7,$sigma1[0]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&eor_8		($T1,$T1,$T3);		# sigma0(X[1..4])
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &sli_32	($T4,$T7,32-$sigma1[0]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &ushr_32	($T5,$T7,$sigma1[2]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &ushr_32	($T3,$T7,$sigma1[1]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&add_32		(@X[0],@X[0],$T1);	# X[0..3] += sigma0(X[1..4])
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &sli_u32	($T3,$T7,32-$sigma1[1]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &eor_8	($T5,$T5,$T4);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &eor_8	($T5,$T5,$T3);		# sigma1(X[14..15])
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&add_32		(@X[0],@X[0],$T5);	# X[0..1] += sigma1(X[14..15])
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &ushr_32	($T6,@X[0],$sigma1[0]);
+	 eval(shift(@insns));
+	  &ushr_32	($T7,@X[0],$sigma1[2]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &sli_32	($T6,@X[0],32-$sigma1[0]);
+	 eval(shift(@insns));
+	  &ushr_32	($T5,@X[0],$sigma1[1]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &eor_8	($T7,$T7,$T6);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	  &sli_32	($T5,@X[0],32-$sigma1[1]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&ld1_32		("{$T0}","[$Ktbl], #16");
+	 eval(shift(@insns));
+	  &eor_8	($T7,$T7,$T5);		# sigma1(X[16..17])
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&eor_8		($T5,$T5,$T5);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&mov		(&Dhi($T5), &Dlo($T7));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&add_32		(@X[0],@X[0],$T5);	# X[2..3] += sigma1(X[16..17])
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&add_32		($T0,$T0,@X[0]);
+	 while($#insns>=1) { eval(shift(@insns)); }
+	&st1_32		("{$T0}","[$Xfer], #16");
+	 eval(shift(@insns));
+
+	push(@X,shift(@X));		# "rotate" X[]
+}
+
+sub Xpreload()
+{ use integer;
+  my $body = shift;
+  my @insns = (&$body,&$body,&$body,&$body);
+  my ($a,$b,$c,$d,$e,$f,$g,$h);
+
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&ld1_8		("{@X[0]}","[$inp],#16");
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&ld1_32		("{$T0}","[$Ktbl],#16");
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&rev32		(@X[0],@X[0]);
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	 eval(shift(@insns));
+	&add_32		($T0,$T0,@X[0]);
+	 foreach (@insns) { eval; }	# remaining instructions
+	&st1_32		("{$T0}","[$Xfer], #16");
+
+	push(@X,shift(@X));		# "rotate" X[]
+}
+
+sub body_00_15 () {
+	(
+	'($a,$b,$c,$d,$e,$f,$g,$h)=@V;'.
+	'&add	($h,$h,$t1)',			# h+=X[i]+K[i]
+	'&add	($a,$a,$t4);'.			# h+=Sigma0(a) from the past
+	'&and	($t1,$f,$e)',
+	'&bic	($t4,$g,$e)',
+	'&eor	($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))',
+	'&add	($a,$a,$t2)',			# h+=Maj(a,b,c) from the past
+	'&orr	($t1,$t1,$t4)',			# Ch(e,f,g)
+	'&eor	($t0,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))',	# Sigma1(e)
+	'&eor	($t4,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))',
+	'&add	($h,$h,$t1)',			# h+=Ch(e,f,g)
+	'&ror	($t0,$t0,"#$Sigma1[0]")',
+	'&eor	($t2,$a,$b)',			# a^b, b^c in next round
+	'&eor	($t4,$t4,$a,"ror#".($Sigma0[2]-$Sigma0[0]))',	# Sigma0(a)
+	'&add	($h,$h,$t0)',			# h+=Sigma1(e)
+	'&ldr	($t1,sprintf "[sp,#%d]",4*(($j+1)&15))	if (($j&15)!=15);'.
+	'&ldr	($t1,"[$Ktbl]")				if ($j==15);'.
+	'&and	($t3,$t3,$t2)',			# (b^c)&=(a^b)
+	'&ror	($t4,$t4,"#$Sigma0[0]")',
+	'&add	($d,$d,$h)',			# d+=h
+	'&eor	($t3,$t3,$b)',			# Maj(a,b,c)
+	'$j++;	unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);'
+	)
+}
+
+$code.=<<___;
+#ifdef	__KERNEL__
+.globl	sha256_block_neon
+#endif
+.type	sha256_block_neon,%function
+.align	4
+sha256_block_neon:
+.Lneon_entry:
+	stp	x29, x30, [sp, #-16]!
+	mov	x29, sp
+	sub	sp,sp,#16*4
+
+	adr	$Ktbl,.LK256
+	add	$num,$inp,$num,lsl#6	// len to point at the end of inp
+
+	ld1.8	{@X[0]},[$inp], #16
+	ld1.8	{@X[1]},[$inp], #16
+	ld1.8	{@X[2]},[$inp], #16
+	ld1.8	{@X[3]},[$inp], #16
+	ld1.32	{$T0},[$Ktbl], #16
+	ld1.32	{$T1},[$Ktbl], #16
+	ld1.32	{$T2},[$Ktbl], #16
+	ld1.32	{$T3},[$Ktbl], #16
+	rev32	@X[0],@X[0]		// yes, even on
+	rev32	@X[1],@X[1]		// big-endian
+	rev32	@X[2],@X[2]
+	rev32	@X[3],@X[3]
+	mov	$Xfer,sp
+	add.32	$T0,$T0,@X[0]
+	add.32	$T1,$T1,@X[1]
+	add.32	$T2,$T2,@X[2]
+	st1.32	{$T0-$T1},[$Xfer], #32
+	add.32	$T3,$T3,@X[3]
+	st1.32	{$T2-$T3},[$Xfer]
+	sub	$Xfer,$Xfer,#32
+
+	ldp	$A,$B,[$ctx]
+	ldp	$C,$D,[$ctx,#8]
+	ldp	$E,$F,[$ctx,#16]
+	ldp	$G,$H,[$ctx,#24]
+	ldr	$t1,[sp,#0]
+	mov	$t2,wzr
+	eor	$t3,$B,$C
+	mov	$t4,wzr
+	b	.L_00_48
+
+.align	4
+.L_00_48:
+___
+	&Xupdate(\&body_00_15);
+	&Xupdate(\&body_00_15);
+	&Xupdate(\&body_00_15);
+	&Xupdate(\&body_00_15);
+$code.=<<___;
+	cmp	$t1,#0				// check for K256 terminator
+	ldr	$t1,[sp,#0]
+	sub	$Xfer,$Xfer,#64
+	bne	.L_00_48
+
+	sub	$Ktbl,$Ktbl,#256		// rewind $Ktbl
+	cmp	$inp,$num
+	mov	$Xfer, #64
+	csel	$Xfer, $Xfer, xzr, eq
+	sub	$inp,$inp,$Xfer			// avoid SEGV
+	mov	$Xfer,sp
+___
+	&Xpreload(\&body_00_15);
+	&Xpreload(\&body_00_15);
+	&Xpreload(\&body_00_15);
+	&Xpreload(\&body_00_15);
+$code.=<<___;
+	add	$A,$A,$t4			// h+=Sigma0(a) from the past
+	ldp	$t0,$t1,[$ctx,#0]
+	add	$A,$A,$t2			// h+=Maj(a,b,c) from the past
+	ldp	$t2,$t3,[$ctx,#8]
+	add	$A,$A,$t0			// accumulate
+	add	$B,$B,$t1
+	ldp	$t0,$t1,[$ctx,#16]
+	add	$C,$C,$t2
+	add	$D,$D,$t3
+	ldp	$t2,$t3,[$ctx,#24]
+	add	$E,$E,$t0
+	add	$F,$F,$t1
+	 ldr	$t1,[sp,#0]
+	stp	$A,$B,[$ctx,#0]
+	add	$G,$G,$t2
+	 mov	$t2,wzr
+	stp	$C,$D,[$ctx,#8]
+	add	$H,$H,$t3
+	stp	$E,$F,[$ctx,#16]
+	 eor	$t3,$B,$C
+	stp	$G,$H,[$ctx,#24]
+	 mov	$t4,wzr
+	 mov	$Xfer,sp
+	b.ne	.L_00_48
+
+	ldr	x29,[x29]
+	add	sp,sp,#16*4+16
+	ret
+.size	sha256_block_neon,.-sha256_block_neon
+___
+}
+
+$code.=<<___;
+#ifndef	__KERNEL__
+.comm	OPENSSL_armcap_P,4,4
+#endif
+___
+
+{   my  %opcode = (
+	"sha256h"	=> 0x5e004000,	"sha256h2"	=> 0x5e005000,
+	"sha256su0"	=> 0x5e282800,	"sha256su1"	=> 0x5e006000	);
+
+    sub unsha256 {
+	my ($mnemonic,$arg)=@_;
+
+	$arg =~ m/[qv]([0-9]+)[^,]*,\s*[qv]([0-9]+)[^,]*(?:,\s*[qv]([0-9]+))?/o
+	&&
+	sprintf ".inst\t0x%08x\t//%s %s",
+			$opcode{$mnemonic}|$1|($2<<5)|($3<<16),
+			$mnemonic,$arg;
+    }
+}
+
+open SELF,$0;
+while(<SELF>) {
+        next if (/^#!/);
+        last if (!s/^#/\/\// and !/^$/);
+        print;
+}
+close SELF;
+
+foreach(split("\n",$code)) {
+
+	s/\`([^\`]*)\`/eval($1)/ge;
+
+	s/\b(sha256\w+)\s+([qv].*)/unsha256($1,$2)/ge;
+
+	s/\bq([0-9]+)\b/v$1.16b/g;		# old->new registers
+
+	s/\.[ui]?8(\s)/$1/;
+	s/\.\w?32\b//		and s/\.16b/\.4s/g;
+	m/(ld|st)1[^\[]+\[0\]/	and s/\.4s/\.s/g;
+
+	print $_,"\n";
+}
+
+close STDOUT;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/sha512-core.S_shipped linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha512-core.S_shipped
--- linux-libre-4.9-gnu/arch/arm64/crypto/sha512-core.S_shipped	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha512-core.S_shipped	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1085 @@
+// Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+//
+// Licensed under the OpenSSL license (the "License").  You may not use
+// this file except in compliance with the License.  You can obtain a copy
+// in the file LICENSE in the source distribution or at
+// https://www.openssl.org/source/license.html
+
+// ====================================================================
+// Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+// project. The module is, however, dual licensed under OpenSSL and
+// CRYPTOGAMS licenses depending on where you obtain it. For further
+// details see http://www.openssl.org/~appro/cryptogams/.
+//
+// Permission to use under GPLv2 terms is granted.
+// ====================================================================
+//
+// SHA256/512 for ARMv8.
+//
+// Performance in cycles per processed byte and improvement coefficient
+// over code generated with "default" compiler:
+//
+//		SHA256-hw	SHA256(*)	SHA512
+// Apple A7	1.97		10.5 (+33%)	6.73 (-1%(**))
+// Cortex-A53	2.38		15.5 (+115%)	10.0 (+150%(***))
+// Cortex-A57	2.31		11.6 (+86%)	7.51 (+260%(***))
+// Denver	2.01		10.5 (+26%)	6.70 (+8%)
+// X-Gene			20.0 (+100%)	12.8 (+300%(***))
+// Mongoose	2.36		13.0 (+50%)	8.36 (+33%)
+//
+// (*)	Software SHA256 results are of lesser relevance, presented
+//	mostly for informational purposes.
+// (**)	The result is a trade-off: it's possible to improve it by
+//	10% (or by 1 cycle per round), but at the cost of 20% loss
+//	on Cortex-A53 (or by 4 cycles per round).
+// (***)	Super-impressive coefficients over gcc-generated code are
+//	indication of some compiler "pathology", most notably code
+//	generated with -mgeneral-regs-only is significanty faster
+//	and the gap is only 40-90%.
+//
+// October 2016.
+//
+// Originally it was reckoned that it makes no sense to implement NEON
+// version of SHA256 for 64-bit processors. This is because performance
+// improvement on most wide-spread Cortex-A5x processors was observed
+// to be marginal, same on Cortex-A53 and ~10% on A57. But then it was
+// observed that 32-bit NEON SHA256 performs significantly better than
+// 64-bit scalar version on *some* of the more recent processors. As
+// result 64-bit NEON version of SHA256 was added to provide best
+// all-round performance. For example it executes ~30% faster on X-Gene
+// and Mongoose. [For reference, NEON version of SHA512 is bound to
+// deliver much less improvement, likely *negative* on Cortex-A5x.
+// Which is why NEON support is limited to SHA256.]
+
+#ifndef	__KERNEL__
+# include "arm_arch.h"
+#endif
+
+.text
+
+.extern	OPENSSL_armcap_P
+.globl	sha512_block_data_order
+.type	sha512_block_data_order,%function
+.align	6
+sha512_block_data_order:
+	stp	x29,x30,[sp,#-128]!
+	add	x29,sp,#0
+
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#4*8
+
+	ldp	x20,x21,[x0]				// load context
+	ldp	x22,x23,[x0,#2*8]
+	ldp	x24,x25,[x0,#4*8]
+	add	x2,x1,x2,lsl#7	// end of input
+	ldp	x26,x27,[x0,#6*8]
+	adr	x30,.LK512
+	stp	x0,x2,[x29,#96]
+
+.Loop:
+	ldp	x3,x4,[x1],#2*8
+	ldr	x19,[x30],#8			// *K++
+	eor	x28,x21,x22				// magic seed
+	str	x1,[x29,#112]
+#ifndef	__AARCH64EB__
+	rev	x3,x3			// 0
+#endif
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	eor	x6,x24,x24,ror#23
+	and	x17,x25,x24
+	bic	x19,x26,x24
+	add	x27,x27,x3			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x6,ror#18	// Sigma1(e)
+	ror	x6,x20,#28
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	eor	x17,x20,x20,ror#5
+	add	x27,x27,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x23,x23,x27			// d+=h
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x6,x17,ror#34	// Sigma0(a)
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x27,x27,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x4,x4			// 1
+#endif
+	ldp	x5,x6,[x1],#2*8
+	add	x27,x27,x17			// h+=Sigma0(a)
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	eor	x7,x23,x23,ror#23
+	and	x17,x24,x23
+	bic	x28,x25,x23
+	add	x26,x26,x4			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x7,ror#18	// Sigma1(e)
+	ror	x7,x27,#28
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	eor	x17,x27,x27,ror#5
+	add	x26,x26,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x22,x22,x26			// d+=h
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x7,x17,ror#34	// Sigma0(a)
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x26,x26,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x5,x5			// 2
+#endif
+	add	x26,x26,x17			// h+=Sigma0(a)
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	eor	x8,x22,x22,ror#23
+	and	x17,x23,x22
+	bic	x19,x24,x22
+	add	x25,x25,x5			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x8,ror#18	// Sigma1(e)
+	ror	x8,x26,#28
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	eor	x17,x26,x26,ror#5
+	add	x25,x25,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x21,x21,x25			// d+=h
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x8,x17,ror#34	// Sigma0(a)
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x25,x25,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x6,x6			// 3
+#endif
+	ldp	x7,x8,[x1],#2*8
+	add	x25,x25,x17			// h+=Sigma0(a)
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	eor	x9,x21,x21,ror#23
+	and	x17,x22,x21
+	bic	x28,x23,x21
+	add	x24,x24,x6			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x9,ror#18	// Sigma1(e)
+	ror	x9,x25,#28
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	eor	x17,x25,x25,ror#5
+	add	x24,x24,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x20,x20,x24			// d+=h
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x9,x17,ror#34	// Sigma0(a)
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x24,x24,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x7,x7			// 4
+#endif
+	add	x24,x24,x17			// h+=Sigma0(a)
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	eor	x10,x20,x20,ror#23
+	and	x17,x21,x20
+	bic	x19,x22,x20
+	add	x23,x23,x7			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x10,ror#18	// Sigma1(e)
+	ror	x10,x24,#28
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	eor	x17,x24,x24,ror#5
+	add	x23,x23,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x27,x27,x23			// d+=h
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x10,x17,ror#34	// Sigma0(a)
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x23,x23,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x8,x8			// 5
+#endif
+	ldp	x9,x10,[x1],#2*8
+	add	x23,x23,x17			// h+=Sigma0(a)
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	eor	x11,x27,x27,ror#23
+	and	x17,x20,x27
+	bic	x28,x21,x27
+	add	x22,x22,x8			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x11,ror#18	// Sigma1(e)
+	ror	x11,x23,#28
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	eor	x17,x23,x23,ror#5
+	add	x22,x22,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x26,x26,x22			// d+=h
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x11,x17,ror#34	// Sigma0(a)
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x22,x22,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x9,x9			// 6
+#endif
+	add	x22,x22,x17			// h+=Sigma0(a)
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	eor	x12,x26,x26,ror#23
+	and	x17,x27,x26
+	bic	x19,x20,x26
+	add	x21,x21,x9			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x12,ror#18	// Sigma1(e)
+	ror	x12,x22,#28
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	eor	x17,x22,x22,ror#5
+	add	x21,x21,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x25,x25,x21			// d+=h
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x12,x17,ror#34	// Sigma0(a)
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x21,x21,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x10,x10			// 7
+#endif
+	ldp	x11,x12,[x1],#2*8
+	add	x21,x21,x17			// h+=Sigma0(a)
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	eor	x13,x25,x25,ror#23
+	and	x17,x26,x25
+	bic	x28,x27,x25
+	add	x20,x20,x10			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x13,ror#18	// Sigma1(e)
+	ror	x13,x21,#28
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	eor	x17,x21,x21,ror#5
+	add	x20,x20,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x24,x24,x20			// d+=h
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x13,x17,ror#34	// Sigma0(a)
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x20,x20,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x11,x11			// 8
+#endif
+	add	x20,x20,x17			// h+=Sigma0(a)
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	eor	x14,x24,x24,ror#23
+	and	x17,x25,x24
+	bic	x19,x26,x24
+	add	x27,x27,x11			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x14,ror#18	// Sigma1(e)
+	ror	x14,x20,#28
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	eor	x17,x20,x20,ror#5
+	add	x27,x27,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x23,x23,x27			// d+=h
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x14,x17,ror#34	// Sigma0(a)
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x27,x27,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x12,x12			// 9
+#endif
+	ldp	x13,x14,[x1],#2*8
+	add	x27,x27,x17			// h+=Sigma0(a)
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	eor	x15,x23,x23,ror#23
+	and	x17,x24,x23
+	bic	x28,x25,x23
+	add	x26,x26,x12			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x15,ror#18	// Sigma1(e)
+	ror	x15,x27,#28
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	eor	x17,x27,x27,ror#5
+	add	x26,x26,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x22,x22,x26			// d+=h
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x15,x17,ror#34	// Sigma0(a)
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x26,x26,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x13,x13			// 10
+#endif
+	add	x26,x26,x17			// h+=Sigma0(a)
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	eor	x0,x22,x22,ror#23
+	and	x17,x23,x22
+	bic	x19,x24,x22
+	add	x25,x25,x13			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x0,ror#18	// Sigma1(e)
+	ror	x0,x26,#28
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	eor	x17,x26,x26,ror#5
+	add	x25,x25,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x21,x21,x25			// d+=h
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x0,x17,ror#34	// Sigma0(a)
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x25,x25,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x14,x14			// 11
+#endif
+	ldp	x15,x0,[x1],#2*8
+	add	x25,x25,x17			// h+=Sigma0(a)
+	str	x6,[sp,#24]
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	eor	x6,x21,x21,ror#23
+	and	x17,x22,x21
+	bic	x28,x23,x21
+	add	x24,x24,x14			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x6,ror#18	// Sigma1(e)
+	ror	x6,x25,#28
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	eor	x17,x25,x25,ror#5
+	add	x24,x24,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x20,x20,x24			// d+=h
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x6,x17,ror#34	// Sigma0(a)
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x24,x24,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x15,x15			// 12
+#endif
+	add	x24,x24,x17			// h+=Sigma0(a)
+	str	x7,[sp,#0]
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	eor	x7,x20,x20,ror#23
+	and	x17,x21,x20
+	bic	x19,x22,x20
+	add	x23,x23,x15			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x7,ror#18	// Sigma1(e)
+	ror	x7,x24,#28
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	eor	x17,x24,x24,ror#5
+	add	x23,x23,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x27,x27,x23			// d+=h
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x7,x17,ror#34	// Sigma0(a)
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x23,x23,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x0,x0			// 13
+#endif
+	ldp	x1,x2,[x1]
+	add	x23,x23,x17			// h+=Sigma0(a)
+	str	x8,[sp,#8]
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	eor	x8,x27,x27,ror#23
+	and	x17,x20,x27
+	bic	x28,x21,x27
+	add	x22,x22,x0			// h+=X[i]
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x8,ror#18	// Sigma1(e)
+	ror	x8,x23,#28
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	eor	x17,x23,x23,ror#5
+	add	x22,x22,x16			// h+=Sigma1(e)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	add	x26,x26,x22			// d+=h
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x8,x17,ror#34	// Sigma0(a)
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	//add	x22,x22,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x1,x1			// 14
+#endif
+	ldr	x6,[sp,#24]
+	add	x22,x22,x17			// h+=Sigma0(a)
+	str	x9,[sp,#16]
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	eor	x9,x26,x26,ror#23
+	and	x17,x27,x26
+	bic	x19,x20,x26
+	add	x21,x21,x1			// h+=X[i]
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x9,ror#18	// Sigma1(e)
+	ror	x9,x22,#28
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	eor	x17,x22,x22,ror#5
+	add	x21,x21,x16			// h+=Sigma1(e)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	add	x25,x25,x21			// d+=h
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x9,x17,ror#34	// Sigma0(a)
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	//add	x21,x21,x17			// h+=Sigma0(a)
+#ifndef	__AARCH64EB__
+	rev	x2,x2			// 15
+#endif
+	ldr	x7,[sp,#0]
+	add	x21,x21,x17			// h+=Sigma0(a)
+	str	x10,[sp,#24]
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	ror	x9,x4,#1
+	and	x17,x26,x25
+	ror	x8,x1,#19
+	bic	x28,x27,x25
+	ror	x10,x21,#28
+	add	x20,x20,x2			// h+=X[i]
+	eor	x16,x16,x25,ror#18
+	eor	x9,x9,x4,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x25,ror#41	// Sigma1(e)
+	eor	x10,x10,x21,ror#34
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x8,x8,x1,ror#61
+	eor	x9,x9,x4,lsr#7	// sigma0(X[i+1])
+	add	x20,x20,x16			// h+=Sigma1(e)
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x10,x21,ror#39	// Sigma0(a)
+	eor	x8,x8,x1,lsr#6	// sigma1(X[i+14])
+	add	x3,x3,x12
+	add	x24,x24,x20			// d+=h
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x3,x3,x9
+	add	x20,x20,x17			// h+=Sigma0(a)
+	add	x3,x3,x8
+.Loop_16_xx:
+	ldr	x8,[sp,#8]
+	str	x11,[sp,#0]
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	ror	x10,x5,#1
+	and	x17,x25,x24
+	ror	x9,x2,#19
+	bic	x19,x26,x24
+	ror	x11,x20,#28
+	add	x27,x27,x3			// h+=X[i]
+	eor	x16,x16,x24,ror#18
+	eor	x10,x10,x5,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x24,ror#41	// Sigma1(e)
+	eor	x11,x11,x20,ror#34
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x9,x9,x2,ror#61
+	eor	x10,x10,x5,lsr#7	// sigma0(X[i+1])
+	add	x27,x27,x16			// h+=Sigma1(e)
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x11,x20,ror#39	// Sigma0(a)
+	eor	x9,x9,x2,lsr#6	// sigma1(X[i+14])
+	add	x4,x4,x13
+	add	x23,x23,x27			// d+=h
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x4,x4,x10
+	add	x27,x27,x17			// h+=Sigma0(a)
+	add	x4,x4,x9
+	ldr	x9,[sp,#16]
+	str	x12,[sp,#8]
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	ror	x11,x6,#1
+	and	x17,x24,x23
+	ror	x10,x3,#19
+	bic	x28,x25,x23
+	ror	x12,x27,#28
+	add	x26,x26,x4			// h+=X[i]
+	eor	x16,x16,x23,ror#18
+	eor	x11,x11,x6,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x23,ror#41	// Sigma1(e)
+	eor	x12,x12,x27,ror#34
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x10,x10,x3,ror#61
+	eor	x11,x11,x6,lsr#7	// sigma0(X[i+1])
+	add	x26,x26,x16			// h+=Sigma1(e)
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x12,x27,ror#39	// Sigma0(a)
+	eor	x10,x10,x3,lsr#6	// sigma1(X[i+14])
+	add	x5,x5,x14
+	add	x22,x22,x26			// d+=h
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x5,x5,x11
+	add	x26,x26,x17			// h+=Sigma0(a)
+	add	x5,x5,x10
+	ldr	x10,[sp,#24]
+	str	x13,[sp,#16]
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	ror	x12,x7,#1
+	and	x17,x23,x22
+	ror	x11,x4,#19
+	bic	x19,x24,x22
+	ror	x13,x26,#28
+	add	x25,x25,x5			// h+=X[i]
+	eor	x16,x16,x22,ror#18
+	eor	x12,x12,x7,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x22,ror#41	// Sigma1(e)
+	eor	x13,x13,x26,ror#34
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x11,x11,x4,ror#61
+	eor	x12,x12,x7,lsr#7	// sigma0(X[i+1])
+	add	x25,x25,x16			// h+=Sigma1(e)
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x13,x26,ror#39	// Sigma0(a)
+	eor	x11,x11,x4,lsr#6	// sigma1(X[i+14])
+	add	x6,x6,x15
+	add	x21,x21,x25			// d+=h
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x6,x6,x12
+	add	x25,x25,x17			// h+=Sigma0(a)
+	add	x6,x6,x11
+	ldr	x11,[sp,#0]
+	str	x14,[sp,#24]
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	ror	x13,x8,#1
+	and	x17,x22,x21
+	ror	x12,x5,#19
+	bic	x28,x23,x21
+	ror	x14,x25,#28
+	add	x24,x24,x6			// h+=X[i]
+	eor	x16,x16,x21,ror#18
+	eor	x13,x13,x8,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x21,ror#41	// Sigma1(e)
+	eor	x14,x14,x25,ror#34
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x12,x12,x5,ror#61
+	eor	x13,x13,x8,lsr#7	// sigma0(X[i+1])
+	add	x24,x24,x16			// h+=Sigma1(e)
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x14,x25,ror#39	// Sigma0(a)
+	eor	x12,x12,x5,lsr#6	// sigma1(X[i+14])
+	add	x7,x7,x0
+	add	x20,x20,x24			// d+=h
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x7,x7,x13
+	add	x24,x24,x17			// h+=Sigma0(a)
+	add	x7,x7,x12
+	ldr	x12,[sp,#8]
+	str	x15,[sp,#0]
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	ror	x14,x9,#1
+	and	x17,x21,x20
+	ror	x13,x6,#19
+	bic	x19,x22,x20
+	ror	x15,x24,#28
+	add	x23,x23,x7			// h+=X[i]
+	eor	x16,x16,x20,ror#18
+	eor	x14,x14,x9,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x20,ror#41	// Sigma1(e)
+	eor	x15,x15,x24,ror#34
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x13,x13,x6,ror#61
+	eor	x14,x14,x9,lsr#7	// sigma0(X[i+1])
+	add	x23,x23,x16			// h+=Sigma1(e)
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x15,x24,ror#39	// Sigma0(a)
+	eor	x13,x13,x6,lsr#6	// sigma1(X[i+14])
+	add	x8,x8,x1
+	add	x27,x27,x23			// d+=h
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x8,x8,x14
+	add	x23,x23,x17			// h+=Sigma0(a)
+	add	x8,x8,x13
+	ldr	x13,[sp,#16]
+	str	x0,[sp,#8]
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	ror	x15,x10,#1
+	and	x17,x20,x27
+	ror	x14,x7,#19
+	bic	x28,x21,x27
+	ror	x0,x23,#28
+	add	x22,x22,x8			// h+=X[i]
+	eor	x16,x16,x27,ror#18
+	eor	x15,x15,x10,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x27,ror#41	// Sigma1(e)
+	eor	x0,x0,x23,ror#34
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x14,x14,x7,ror#61
+	eor	x15,x15,x10,lsr#7	// sigma0(X[i+1])
+	add	x22,x22,x16			// h+=Sigma1(e)
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x0,x23,ror#39	// Sigma0(a)
+	eor	x14,x14,x7,lsr#6	// sigma1(X[i+14])
+	add	x9,x9,x2
+	add	x26,x26,x22			// d+=h
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x9,x9,x15
+	add	x22,x22,x17			// h+=Sigma0(a)
+	add	x9,x9,x14
+	ldr	x14,[sp,#24]
+	str	x1,[sp,#16]
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	ror	x0,x11,#1
+	and	x17,x27,x26
+	ror	x15,x8,#19
+	bic	x19,x20,x26
+	ror	x1,x22,#28
+	add	x21,x21,x9			// h+=X[i]
+	eor	x16,x16,x26,ror#18
+	eor	x0,x0,x11,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x26,ror#41	// Sigma1(e)
+	eor	x1,x1,x22,ror#34
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x15,x15,x8,ror#61
+	eor	x0,x0,x11,lsr#7	// sigma0(X[i+1])
+	add	x21,x21,x16			// h+=Sigma1(e)
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x1,x22,ror#39	// Sigma0(a)
+	eor	x15,x15,x8,lsr#6	// sigma1(X[i+14])
+	add	x10,x10,x3
+	add	x25,x25,x21			// d+=h
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x10,x10,x0
+	add	x21,x21,x17			// h+=Sigma0(a)
+	add	x10,x10,x15
+	ldr	x15,[sp,#0]
+	str	x2,[sp,#24]
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	ror	x1,x12,#1
+	and	x17,x26,x25
+	ror	x0,x9,#19
+	bic	x28,x27,x25
+	ror	x2,x21,#28
+	add	x20,x20,x10			// h+=X[i]
+	eor	x16,x16,x25,ror#18
+	eor	x1,x1,x12,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x25,ror#41	// Sigma1(e)
+	eor	x2,x2,x21,ror#34
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x0,x0,x9,ror#61
+	eor	x1,x1,x12,lsr#7	// sigma0(X[i+1])
+	add	x20,x20,x16			// h+=Sigma1(e)
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x2,x21,ror#39	// Sigma0(a)
+	eor	x0,x0,x9,lsr#6	// sigma1(X[i+14])
+	add	x11,x11,x4
+	add	x24,x24,x20			// d+=h
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x11,x11,x1
+	add	x20,x20,x17			// h+=Sigma0(a)
+	add	x11,x11,x0
+	ldr	x0,[sp,#8]
+	str	x3,[sp,#0]
+	ror	x16,x24,#14
+	add	x27,x27,x19			// h+=K[i]
+	ror	x2,x13,#1
+	and	x17,x25,x24
+	ror	x1,x10,#19
+	bic	x19,x26,x24
+	ror	x3,x20,#28
+	add	x27,x27,x11			// h+=X[i]
+	eor	x16,x16,x24,ror#18
+	eor	x2,x2,x13,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x20,x21			// a^b, b^c in next round
+	eor	x16,x16,x24,ror#41	// Sigma1(e)
+	eor	x3,x3,x20,ror#34
+	add	x27,x27,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x1,x1,x10,ror#61
+	eor	x2,x2,x13,lsr#7	// sigma0(X[i+1])
+	add	x27,x27,x16			// h+=Sigma1(e)
+	eor	x28,x28,x21			// Maj(a,b,c)
+	eor	x17,x3,x20,ror#39	// Sigma0(a)
+	eor	x1,x1,x10,lsr#6	// sigma1(X[i+14])
+	add	x12,x12,x5
+	add	x23,x23,x27			// d+=h
+	add	x27,x27,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x12,x12,x2
+	add	x27,x27,x17			// h+=Sigma0(a)
+	add	x12,x12,x1
+	ldr	x1,[sp,#16]
+	str	x4,[sp,#8]
+	ror	x16,x23,#14
+	add	x26,x26,x28			// h+=K[i]
+	ror	x3,x14,#1
+	and	x17,x24,x23
+	ror	x2,x11,#19
+	bic	x28,x25,x23
+	ror	x4,x27,#28
+	add	x26,x26,x12			// h+=X[i]
+	eor	x16,x16,x23,ror#18
+	eor	x3,x3,x14,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x27,x20			// a^b, b^c in next round
+	eor	x16,x16,x23,ror#41	// Sigma1(e)
+	eor	x4,x4,x27,ror#34
+	add	x26,x26,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x2,x2,x11,ror#61
+	eor	x3,x3,x14,lsr#7	// sigma0(X[i+1])
+	add	x26,x26,x16			// h+=Sigma1(e)
+	eor	x19,x19,x20			// Maj(a,b,c)
+	eor	x17,x4,x27,ror#39	// Sigma0(a)
+	eor	x2,x2,x11,lsr#6	// sigma1(X[i+14])
+	add	x13,x13,x6
+	add	x22,x22,x26			// d+=h
+	add	x26,x26,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x13,x13,x3
+	add	x26,x26,x17			// h+=Sigma0(a)
+	add	x13,x13,x2
+	ldr	x2,[sp,#24]
+	str	x5,[sp,#16]
+	ror	x16,x22,#14
+	add	x25,x25,x19			// h+=K[i]
+	ror	x4,x15,#1
+	and	x17,x23,x22
+	ror	x3,x12,#19
+	bic	x19,x24,x22
+	ror	x5,x26,#28
+	add	x25,x25,x13			// h+=X[i]
+	eor	x16,x16,x22,ror#18
+	eor	x4,x4,x15,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x26,x27			// a^b, b^c in next round
+	eor	x16,x16,x22,ror#41	// Sigma1(e)
+	eor	x5,x5,x26,ror#34
+	add	x25,x25,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x3,x3,x12,ror#61
+	eor	x4,x4,x15,lsr#7	// sigma0(X[i+1])
+	add	x25,x25,x16			// h+=Sigma1(e)
+	eor	x28,x28,x27			// Maj(a,b,c)
+	eor	x17,x5,x26,ror#39	// Sigma0(a)
+	eor	x3,x3,x12,lsr#6	// sigma1(X[i+14])
+	add	x14,x14,x7
+	add	x21,x21,x25			// d+=h
+	add	x25,x25,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x14,x14,x4
+	add	x25,x25,x17			// h+=Sigma0(a)
+	add	x14,x14,x3
+	ldr	x3,[sp,#0]
+	str	x6,[sp,#24]
+	ror	x16,x21,#14
+	add	x24,x24,x28			// h+=K[i]
+	ror	x5,x0,#1
+	and	x17,x22,x21
+	ror	x4,x13,#19
+	bic	x28,x23,x21
+	ror	x6,x25,#28
+	add	x24,x24,x14			// h+=X[i]
+	eor	x16,x16,x21,ror#18
+	eor	x5,x5,x0,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x25,x26			// a^b, b^c in next round
+	eor	x16,x16,x21,ror#41	// Sigma1(e)
+	eor	x6,x6,x25,ror#34
+	add	x24,x24,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x4,x4,x13,ror#61
+	eor	x5,x5,x0,lsr#7	// sigma0(X[i+1])
+	add	x24,x24,x16			// h+=Sigma1(e)
+	eor	x19,x19,x26			// Maj(a,b,c)
+	eor	x17,x6,x25,ror#39	// Sigma0(a)
+	eor	x4,x4,x13,lsr#6	// sigma1(X[i+14])
+	add	x15,x15,x8
+	add	x20,x20,x24			// d+=h
+	add	x24,x24,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x15,x15,x5
+	add	x24,x24,x17			// h+=Sigma0(a)
+	add	x15,x15,x4
+	ldr	x4,[sp,#8]
+	str	x7,[sp,#0]
+	ror	x16,x20,#14
+	add	x23,x23,x19			// h+=K[i]
+	ror	x6,x1,#1
+	and	x17,x21,x20
+	ror	x5,x14,#19
+	bic	x19,x22,x20
+	ror	x7,x24,#28
+	add	x23,x23,x15			// h+=X[i]
+	eor	x16,x16,x20,ror#18
+	eor	x6,x6,x1,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x24,x25			// a^b, b^c in next round
+	eor	x16,x16,x20,ror#41	// Sigma1(e)
+	eor	x7,x7,x24,ror#34
+	add	x23,x23,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x5,x5,x14,ror#61
+	eor	x6,x6,x1,lsr#7	// sigma0(X[i+1])
+	add	x23,x23,x16			// h+=Sigma1(e)
+	eor	x28,x28,x25			// Maj(a,b,c)
+	eor	x17,x7,x24,ror#39	// Sigma0(a)
+	eor	x5,x5,x14,lsr#6	// sigma1(X[i+14])
+	add	x0,x0,x9
+	add	x27,x27,x23			// d+=h
+	add	x23,x23,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x0,x0,x6
+	add	x23,x23,x17			// h+=Sigma0(a)
+	add	x0,x0,x5
+	ldr	x5,[sp,#16]
+	str	x8,[sp,#8]
+	ror	x16,x27,#14
+	add	x22,x22,x28			// h+=K[i]
+	ror	x7,x2,#1
+	and	x17,x20,x27
+	ror	x6,x15,#19
+	bic	x28,x21,x27
+	ror	x8,x23,#28
+	add	x22,x22,x0			// h+=X[i]
+	eor	x16,x16,x27,ror#18
+	eor	x7,x7,x2,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x23,x24			// a^b, b^c in next round
+	eor	x16,x16,x27,ror#41	// Sigma1(e)
+	eor	x8,x8,x23,ror#34
+	add	x22,x22,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x6,x6,x15,ror#61
+	eor	x7,x7,x2,lsr#7	// sigma0(X[i+1])
+	add	x22,x22,x16			// h+=Sigma1(e)
+	eor	x19,x19,x24			// Maj(a,b,c)
+	eor	x17,x8,x23,ror#39	// Sigma0(a)
+	eor	x6,x6,x15,lsr#6	// sigma1(X[i+14])
+	add	x1,x1,x10
+	add	x26,x26,x22			// d+=h
+	add	x22,x22,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x1,x1,x7
+	add	x22,x22,x17			// h+=Sigma0(a)
+	add	x1,x1,x6
+	ldr	x6,[sp,#24]
+	str	x9,[sp,#16]
+	ror	x16,x26,#14
+	add	x21,x21,x19			// h+=K[i]
+	ror	x8,x3,#1
+	and	x17,x27,x26
+	ror	x7,x0,#19
+	bic	x19,x20,x26
+	ror	x9,x22,#28
+	add	x21,x21,x1			// h+=X[i]
+	eor	x16,x16,x26,ror#18
+	eor	x8,x8,x3,ror#8
+	orr	x17,x17,x19			// Ch(e,f,g)
+	eor	x19,x22,x23			// a^b, b^c in next round
+	eor	x16,x16,x26,ror#41	// Sigma1(e)
+	eor	x9,x9,x22,ror#34
+	add	x21,x21,x17			// h+=Ch(e,f,g)
+	and	x28,x28,x19			// (b^c)&=(a^b)
+	eor	x7,x7,x0,ror#61
+	eor	x8,x8,x3,lsr#7	// sigma0(X[i+1])
+	add	x21,x21,x16			// h+=Sigma1(e)
+	eor	x28,x28,x23			// Maj(a,b,c)
+	eor	x17,x9,x22,ror#39	// Sigma0(a)
+	eor	x7,x7,x0,lsr#6	// sigma1(X[i+14])
+	add	x2,x2,x11
+	add	x25,x25,x21			// d+=h
+	add	x21,x21,x28			// h+=Maj(a,b,c)
+	ldr	x28,[x30],#8		// *K++, x19 in next round
+	add	x2,x2,x8
+	add	x21,x21,x17			// h+=Sigma0(a)
+	add	x2,x2,x7
+	ldr	x7,[sp,#0]
+	str	x10,[sp,#24]
+	ror	x16,x25,#14
+	add	x20,x20,x28			// h+=K[i]
+	ror	x9,x4,#1
+	and	x17,x26,x25
+	ror	x8,x1,#19
+	bic	x28,x27,x25
+	ror	x10,x21,#28
+	add	x20,x20,x2			// h+=X[i]
+	eor	x16,x16,x25,ror#18
+	eor	x9,x9,x4,ror#8
+	orr	x17,x17,x28			// Ch(e,f,g)
+	eor	x28,x21,x22			// a^b, b^c in next round
+	eor	x16,x16,x25,ror#41	// Sigma1(e)
+	eor	x10,x10,x21,ror#34
+	add	x20,x20,x17			// h+=Ch(e,f,g)
+	and	x19,x19,x28			// (b^c)&=(a^b)
+	eor	x8,x8,x1,ror#61
+	eor	x9,x9,x4,lsr#7	// sigma0(X[i+1])
+	add	x20,x20,x16			// h+=Sigma1(e)
+	eor	x19,x19,x22			// Maj(a,b,c)
+	eor	x17,x10,x21,ror#39	// Sigma0(a)
+	eor	x8,x8,x1,lsr#6	// sigma1(X[i+14])
+	add	x3,x3,x12
+	add	x24,x24,x20			// d+=h
+	add	x20,x20,x19			// h+=Maj(a,b,c)
+	ldr	x19,[x30],#8		// *K++, x28 in next round
+	add	x3,x3,x9
+	add	x20,x20,x17			// h+=Sigma0(a)
+	add	x3,x3,x8
+	cbnz	x19,.Loop_16_xx
+
+	ldp	x0,x2,[x29,#96]
+	ldr	x1,[x29,#112]
+	sub	x30,x30,#648		// rewind
+
+	ldp	x3,x4,[x0]
+	ldp	x5,x6,[x0,#2*8]
+	add	x1,x1,#14*8			// advance input pointer
+	ldp	x7,x8,[x0,#4*8]
+	add	x20,x20,x3
+	ldp	x9,x10,[x0,#6*8]
+	add	x21,x21,x4
+	add	x22,x22,x5
+	add	x23,x23,x6
+	stp	x20,x21,[x0]
+	add	x24,x24,x7
+	add	x25,x25,x8
+	stp	x22,x23,[x0,#2*8]
+	add	x26,x26,x9
+	add	x27,x27,x10
+	cmp	x1,x2
+	stp	x24,x25,[x0,#4*8]
+	stp	x26,x27,[x0,#6*8]
+	b.ne	.Loop
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#4*8
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#128
+	ret
+.size	sha512_block_data_order,.-sha512_block_data_order
+
+.align	6
+.type	.LK512,%object
+.LK512:
+	.quad	0x428a2f98d728ae22,0x7137449123ef65cd
+	.quad	0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc
+	.quad	0x3956c25bf348b538,0x59f111f1b605d019
+	.quad	0x923f82a4af194f9b,0xab1c5ed5da6d8118
+	.quad	0xd807aa98a3030242,0x12835b0145706fbe
+	.quad	0x243185be4ee4b28c,0x550c7dc3d5ffb4e2
+	.quad	0x72be5d74f27b896f,0x80deb1fe3b1696b1
+	.quad	0x9bdc06a725c71235,0xc19bf174cf692694
+	.quad	0xe49b69c19ef14ad2,0xefbe4786384f25e3
+	.quad	0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65
+	.quad	0x2de92c6f592b0275,0x4a7484aa6ea6e483
+	.quad	0x5cb0a9dcbd41fbd4,0x76f988da831153b5
+	.quad	0x983e5152ee66dfab,0xa831c66d2db43210
+	.quad	0xb00327c898fb213f,0xbf597fc7beef0ee4
+	.quad	0xc6e00bf33da88fc2,0xd5a79147930aa725
+	.quad	0x06ca6351e003826f,0x142929670a0e6e70
+	.quad	0x27b70a8546d22ffc,0x2e1b21385c26c926
+	.quad	0x4d2c6dfc5ac42aed,0x53380d139d95b3df
+	.quad	0x650a73548baf63de,0x766a0abb3c77b2a8
+	.quad	0x81c2c92e47edaee6,0x92722c851482353b
+	.quad	0xa2bfe8a14cf10364,0xa81a664bbc423001
+	.quad	0xc24b8b70d0f89791,0xc76c51a30654be30
+	.quad	0xd192e819d6ef5218,0xd69906245565a910
+	.quad	0xf40e35855771202a,0x106aa07032bbd1b8
+	.quad	0x19a4c116b8d2d0c8,0x1e376c085141ab53
+	.quad	0x2748774cdf8eeb99,0x34b0bcb5e19b48a8
+	.quad	0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb
+	.quad	0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3
+	.quad	0x748f82ee5defb2fc,0x78a5636f43172f60
+	.quad	0x84c87814a1f0ab72,0x8cc702081a6439ec
+	.quad	0x90befffa23631e28,0xa4506cebde82bde9
+	.quad	0xbef9a3f7b2c67915,0xc67178f2e372532b
+	.quad	0xca273eceea26619c,0xd186b8c721c0c207
+	.quad	0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178
+	.quad	0x06f067aa72176fba,0x0a637dc5a2c898a6
+	.quad	0x113f9804bef90dae,0x1b710b35131c471b
+	.quad	0x28db77f523047d84,0x32caab7b40c72493
+	.quad	0x3c9ebe0a15c9bebc,0x431d67c49c100d4c
+	.quad	0x4cc5d4becb3e42b6,0x597f299cfc657e2a
+	.quad	0x5fcb6fab3ad6faec,0x6c44198c4a475817
+	.quad	0	// terminator
+.size	.LK512,.-.LK512
+#ifndef	__KERNEL__
+.align	3
+.LOPENSSL_armcap_P:
+# ifdef	__ILP32__
+	.long	OPENSSL_armcap_P-.
+# else
+	.quad	OPENSSL_armcap_P-.
+# endif
+#endif
+.asciz	"SHA512 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>"
+.align	2
+#ifndef	__KERNEL__
+.comm	OPENSSL_armcap_P,4,4
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/crypto/sha512-glue.c linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha512-glue.c
--- linux-libre-4.9-gnu/arch/arm64/crypto/sha512-glue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/crypto/sha512-glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,94 @@
+/*
+ * Linux/arm64 port of the OpenSSL SHA512 implementation for AArch64
+ *
+ * Copyright (c) 2016 Linaro Ltd. <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+
+#include <crypto/internal/hash.h>
+#include <linux/cryptohash.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <crypto/sha.h>
+#include <crypto/sha512_base.h>
+#include <asm/neon.h>
+
+MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash for arm64");
+MODULE_AUTHOR("Andy Polyakov <appro@openssl.org>");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha384");
+MODULE_ALIAS_CRYPTO("sha512");
+
+asmlinkage void sha512_block_data_order(u32 *digest, const void *data,
+					unsigned int num_blks);
+
+static int sha512_update(struct shash_desc *desc, const u8 *data,
+			 unsigned int len)
+{
+	return sha512_base_do_update(desc, data, len,
+			(sha512_block_fn *)sha512_block_data_order);
+}
+
+static int sha512_finup(struct shash_desc *desc, const u8 *data,
+			unsigned int len, u8 *out)
+{
+	if (len)
+		sha512_base_do_update(desc, data, len,
+			(sha512_block_fn *)sha512_block_data_order);
+	sha512_base_do_finalize(desc,
+			(sha512_block_fn *)sha512_block_data_order);
+
+	return sha512_base_finish(desc, out);
+}
+
+static int sha512_final(struct shash_desc *desc, u8 *out)
+{
+	return sha512_finup(desc, NULL, 0, out);
+}
+
+static struct shash_alg algs[] = { {
+	.digestsize		= SHA512_DIGEST_SIZE,
+	.init			= sha512_base_init,
+	.update			= sha512_update,
+	.final			= sha512_final,
+	.finup			= sha512_finup,
+	.descsize		= sizeof(struct sha512_state),
+	.base.cra_name		= "sha512",
+	.base.cra_driver_name	= "sha512-arm64",
+	.base.cra_priority	= 150,
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA512_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+}, {
+	.digestsize		= SHA384_DIGEST_SIZE,
+	.init			= sha384_base_init,
+	.update			= sha512_update,
+	.final			= sha512_final,
+	.finup			= sha512_finup,
+	.descsize		= sizeof(struct sha512_state),
+	.base.cra_name		= "sha384",
+	.base.cra_driver_name	= "sha384-arm64",
+	.base.cra_priority	= 150,
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA384_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+} };
+
+static int __init sha512_mod_init(void)
+{
+	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+}
+
+static void __exit sha512_mod_fini(void)
+{
+	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+
+module_init(sha512_mod_init);
+module_exit(sha512_mod_fini);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/acpi.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/acpi.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/acpi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/acpi.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 
 #include <asm/cputype.h>
 #include <asm/smp_plat.h>
+#include <asm/tlbflush.h>
 
 /* Macros for consistency checks of the GICC subtable of MADT */
 #define ACPI_MADT_GICC_LENGTH	\
@@ -28,7 +29,7 @@
 
 /* Basic configuration for ACPI */
 #ifdef	CONFIG_ACPI
-/* ACPI table mapping after acpi_gbl_permanent_mmap is set */
+/* ACPI table mapping after acpi_permanent_mmap is set */
 static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
 					    acpi_size size)
 {
@@ -114,8 +115,28 @@ static inline const char *acpi_get_enabl
 }
 
 #ifdef	CONFIG_ACPI_APEI
+/*
+ * acpi_disable_cmcff is used in drivers/acpi/apei/hest.c for disabling
+ * IA-32 Architecture Corrected Machine Check (CMC) Firmware-First mode
+ * with a kernel command line parameter "acpi=nocmcoff". But we don't
+ * have this IA-32 specific feature on ARM64, this definition is only
+ * for compatibility.
+ */
+#define acpi_disable_cmcff 1
 pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr);
-#endif
+
+/*
+ * Despite its name, this function must still broadcast the TLB
+ * invalidation in order to ensure other CPUs don't end up with junk
+ * entries as a result of speculation. Unusually, its also called in
+ * IRQ context (ghes_iounmap_irq) so if we ever need to use IPIs for
+ * TLB broadcasting, then we're in trouble here.
+ */
+static inline void arch_apei_flush_tlb_one(unsigned long addr)
+{
+	flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+}
+#endif /* CONFIG_ACPI_APEI */
 
 #ifdef CONFIG_ACPI_NUMA
 int arm64_acpi_numa_init(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/arch_gicv3.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/arch_gicv3.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/arch_gicv3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/arch_gicv3.h	2017-02-12 16:03:20.000000000 -0500
@@ -79,19 +79,10 @@
 
 #include <linux/stringify.h>
 #include <asm/barrier.h>
+#include <asm/cacheflush.h>
 
-#define read_gicreg(r)							\
-	({								\
-		u64 reg;						\
-		asm volatile("mrs_s %0, " __stringify(r) : "=r" (reg));	\
-		reg;							\
-	})
-
-#define write_gicreg(v,r)						\
-	do {								\
-		u64 __val = (v);					\
-		asm volatile("msr_s " __stringify(r) ", %0" : : "r" (__val));\
-	} while (0)
+#define read_gicreg			read_sysreg_s
+#define write_gicreg			write_sysreg_s
 
 /*
  * Low-level accessors
@@ -102,13 +93,13 @@
 
 static inline void gic_write_eoir(u32 irq)
 {
-	asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq));
+	write_sysreg_s(irq, ICC_EOIR1_EL1);
 	isb();
 }
 
 static inline void gic_write_dir(u32 irq)
 {
-	asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" ((u64)irq));
+	write_sysreg_s(irq, ICC_DIR_EL1);
 	isb();
 }
 
@@ -116,7 +107,7 @@ static inline u64 gic_read_iar_common(vo
 {
 	u64 irqstat;
 
-	asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+	irqstat = read_sysreg_s(ICC_IAR1_EL1);
 	dsb(sy);
 	return irqstat;
 }
@@ -132,12 +123,9 @@ static inline u64 gic_read_iar_cavium_th
 {
 	u64 irqstat;
 
-	asm volatile(
-		"nop;nop;nop;nop\n\t"
-		"nop;nop;nop;nop\n\t"
-		"mrs_s %0, " __stringify(ICC_IAR1_EL1) "\n\t"
-		"nop;nop;nop;nop"
-		: "=r" (irqstat));
+	nops(8);
+	irqstat = read_sysreg_s(ICC_IAR1_EL1);
+	nops(4);
 	mb();
 
 	return irqstat;
@@ -145,37 +133,34 @@ static inline u64 gic_read_iar_cavium_th
 
 static inline void gic_write_pmr(u32 val)
 {
-	asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));
+	write_sysreg_s(val, ICC_PMR_EL1);
 }
 
 static inline void gic_write_ctlr(u32 val)
 {
-	asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" ((u64)val));
+	write_sysreg_s(val, ICC_CTLR_EL1);
 	isb();
 }
 
 static inline void gic_write_grpen1(u32 val)
 {
-	asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));
+	write_sysreg_s(val, ICC_GRPEN1_EL1);
 	isb();
 }
 
 static inline void gic_write_sgi1r(u64 val)
 {
-	asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
+	write_sysreg_s(val, ICC_SGI1R_EL1);
 }
 
 static inline u32 gic_read_sre(void)
 {
-	u64 val;
-
-	asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
-	return val;
+	return read_sysreg_s(ICC_SRE_EL1);
 }
 
 static inline void gic_write_sre(u32 val)
 {
-	asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" ((u64)val));
+	write_sysreg_s(val, ICC_SRE_EL1);
 	isb();
 }
 
@@ -187,5 +172,21 @@ static inline void gic_write_bpr1(u32 va
 #define gic_read_typer(c)		readq_relaxed(c)
 #define gic_write_irouter(v, c)		writeq_relaxed(v, c)
 
+#define gic_flush_dcache_to_poc(a,l)	__flush_dcache_area((a), (l))
+
+#define gits_read_baser(c)		readq_relaxed(c)
+#define gits_write_baser(v, c)		writeq_relaxed(v, c)
+
+#define gits_read_cbaser(c)		readq_relaxed(c)
+#define gits_write_cbaser(v, c)		writeq_relaxed(v, c)
+
+#define gits_write_cwriter(v, c)	writeq_relaxed(v, c)
+
+#define gicr_read_propbaser(c)		readq_relaxed(c)
+#define gicr_write_propbaser(v, c)	writeq_relaxed(v, c)
+
+#define gicr_write_pendbaser(v, c)	writeq_relaxed(v, c)
+#define gicr_read_pendbaser(c)		readq_relaxed(c)
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_ARCH_GICV3_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/asm-uaccess.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/asm-uaccess.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/asm-uaccess.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/asm-uaccess.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,65 @@
+#ifndef __ASM_ASM_UACCESS_H
+#define __ASM_ASM_UACCESS_H
+
+#include <asm/alternative.h>
+#include <asm/kernel-pgtable.h>
+#include <asm/sysreg.h>
+#include <asm/assembler.h>
+
+/*
+ * User access enabling/disabling macros.
+ */
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	.macro	__uaccess_ttbr0_disable, tmp1
+	mrs	\tmp1, ttbr1_el1		// swapper_pg_dir
+	add	\tmp1, \tmp1, #SWAPPER_DIR_SIZE	// reserved_ttbr0 at the end of swapper_pg_dir
+	msr	ttbr0_el1, \tmp1		// set reserved TTBR0_EL1
+	isb
+	.endm
+
+	.macro	__uaccess_ttbr0_enable, tmp1
+	get_thread_info \tmp1
+	ldr	\tmp1, [\tmp1, #TSK_TI_TTBR0]	// load saved TTBR0_EL1
+	msr	ttbr0_el1, \tmp1		// set the non-PAN TTBR0_EL1
+	isb
+	.endm
+
+	.macro	uaccess_ttbr0_disable, tmp1
+alternative_if_not ARM64_HAS_PAN
+	__uaccess_ttbr0_disable \tmp1
+alternative_else_nop_endif
+	.endm
+
+	.macro	uaccess_ttbr0_enable, tmp1, tmp2
+alternative_if_not ARM64_HAS_PAN
+	save_and_disable_irq \tmp2		// avoid preemption
+	__uaccess_ttbr0_enable \tmp1
+	restore_irq \tmp2
+alternative_else_nop_endif
+	.endm
+#else
+	.macro	uaccess_ttbr0_disable, tmp1
+	.endm
+
+	.macro	uaccess_ttbr0_enable, tmp1, tmp2
+	.endm
+#endif
+
+/*
+ * These macros are no-ops when UAO is present.
+ */
+	.macro	uaccess_disable_not_uao, tmp1
+	uaccess_ttbr0_disable \tmp1
+alternative_if ARM64_ALT_PAN_NOT_UAO
+	SET_PSTATE_PAN(1)
+alternative_else_nop_endif
+	.endm
+
+	.macro	uaccess_enable_not_uao, tmp1, tmp2
+	uaccess_ttbr0_enable \tmp1, \tmp2
+alternative_if ARM64_ALT_PAN_NOT_UAO
+	SET_PSTATE_PAN(0)
+alternative_else_nop_endif
+	.endm
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/assembler.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/assembler.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/assembler.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/assembler.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,15 @@
 	msr	daifclr, #2
 	.endm
 
+	.macro	save_and_disable_irq, flags
+	mrs	\flags, daif
+	msr	daifset, #2
+	.endm
+
+	.macro	restore_irq, flags
+	msr	daif, \flags
+	.endm
+
 /*
  * Enable and disable debug exceptions.
  */
@@ -155,22 +164,25 @@ lr	.req	x30		// link register
 
 /*
  * Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
- * <symbol> is within the range +/- 4 GB of the PC.
+ * <symbol> is within the range +/- 4 GB of the PC when running
+ * in core kernel context. In module context, a movz/movk sequence
+ * is used, since modules may be loaded far away from the kernel
+ * when KASLR is in effect.
  */
 	/*
 	 * @dst: destination register (64 bit wide)
 	 * @sym: name of the symbol
-	 * @tmp: optional scratch register to be used if <dst> == sp, which
-	 *       is not allowed in an adrp instruction
 	 */
-	.macro	adr_l, dst, sym, tmp=
-	.ifb	\tmp
+	.macro	adr_l, dst, sym
+#ifndef MODULE
 	adrp	\dst, \sym
 	add	\dst, \dst, :lo12:\sym
-	.else
-	adrp	\tmp, \sym
-	add	\dst, \tmp, :lo12:\sym
-	.endif
+#else
+	movz	\dst, #:abs_g3:\sym
+	movk	\dst, #:abs_g2_nc:\sym
+	movk	\dst, #:abs_g1_nc:\sym
+	movk	\dst, #:abs_g0_nc:\sym
+#endif
 	.endm
 
 	/*
@@ -181,6 +193,7 @@ lr	.req	x30		// link register
 	 *       the address
 	 */
 	.macro	ldr_l, dst, sym, tmp=
+#ifndef MODULE
 	.ifb	\tmp
 	adrp	\dst, \sym
 	ldr	\dst, [\dst, :lo12:\sym]
@@ -188,6 +201,15 @@ lr	.req	x30		// link register
 	adrp	\tmp, \sym
 	ldr	\dst, [\tmp, :lo12:\sym]
 	.endif
+#else
+	.ifb	\tmp
+	adr_l	\dst, \sym
+	ldr	\dst, [\dst]
+	.else
+	adr_l	\tmp, \sym
+	ldr	\dst, [\tmp]
+	.endif
+#endif
 	.endm
 
 	/*
@@ -197,19 +219,35 @@ lr	.req	x30		// link register
 	 *       while <src> needs to be preserved.
 	 */
 	.macro	str_l, src, sym, tmp
+#ifndef MODULE
 	adrp	\tmp, \sym
 	str	\src, [\tmp, :lo12:\sym]
+#else
+	adr_l	\tmp, \sym
+	str	\src, [\tmp]
+#endif
 	.endm
 
 	/*
+	 * @dst: Result of per_cpu(sym, smp_processor_id())
 	 * @sym: The name of the per-cpu variable
-	 * @reg: Result of per_cpu(sym, smp_processor_id())
 	 * @tmp: scratch register
 	 */
-	.macro this_cpu_ptr, sym, reg, tmp
-	adr_l	\reg, \sym
+	.macro adr_this_cpu, dst, sym, tmp
+	adr_l	\dst, \sym
 	mrs	\tmp, tpidr_el1
-	add	\reg, \reg, \tmp
+	add	\dst, \dst, \tmp
+	.endm
+
+	/*
+	 * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id()))
+	 * @sym: The name of the per-cpu variable
+	 * @tmp: scratch register
+	 */
+	.macro ldr_this_cpu dst, sym, tmp
+	adr_l	\dst, \sym
+	mrs	\tmp, tpidr_el1
+	ldr	\dst, [\dst, \tmp]
 	.endm
 
 /*
@@ -395,4 +433,24 @@ alternative_endif
 	movk	\reg, :abs_g0_nc:\val
 	.endm
 
+/*
+ * Return the current thread_info.
+ */
+	.macro	get_thread_info, rd
+	mrs	\rd, sp_el0
+	.endm
+
+/*
+ * Errata workaround post TTBR0_EL1 update.
+ */
+	.macro	post_ttbr0_update_workaround
+#ifdef CONFIG_CAVIUM_ERRATUM_27456
+alternative_if ARM64_WORKAROUND_CAVIUM_27456
+	ic	iallu
+	dsb	nsh
+	isb
+alternative_else_nop_endif
+#endif
+	.endm
+
 #endif	/* __ASM_ASSEMBLER_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/cacheflush.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/cacheflush.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/cacheflush.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/cacheflush.h	2017-02-12 16:03:20.000000000 -0500
@@ -65,12 +65,12 @@
  *		- kaddr  - page address
  *		- size   - region size
  */
-extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void __flush_dcache_area(void *addr, size_t len);
 extern void __clean_dcache_area_poc(void *addr, size_t len);
 extern void __clean_dcache_area_pou(void *addr, size_t len);
 extern long __flush_cache_user_range(unsigned long start, unsigned long end);
+extern void sync_icache_aliases(void *kaddr, unsigned long len);
 
 static inline void flush_cache_mm(struct mm_struct *mm)
 {
@@ -81,6 +81,11 @@ static inline void flush_cache_page(stru
 {
 }
 
+static inline void flush_cache_range(struct vm_area_struct *vma,
+				     unsigned long start, unsigned long end)
+{
+}
+
 /*
  * Cache maintenance functions used by the DMA API. No to be used directly.
  */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/cpucaps.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/cpucaps.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/cpucaps.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/cpucaps.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,8 @@
 #define ARM64_HAS_32BIT_EL0			13
 #define ARM64_HYP_OFFSET_LOW			14
 #define ARM64_MISMATCHED_CACHE_LINE_SIZE	15
+#define ARM64_HAS_NO_FPSIMD			16
 
-#define ARM64_NCAPS				16
+#define ARM64_NCAPS				17
 
 #endif /* __ASM_CPUCAPS_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/cpufeature.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/cpufeature.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/cpufeature.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/cpufeature.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,8 +9,6 @@
 #ifndef __ASM_CPUFEATURE_H
 #define __ASM_CPUFEATURE_H
 
-#include <linux/jump_label.h>
-
 #include <asm/cpucaps.h>
 #include <asm/hwcap.h>
 #include <asm/sysreg.h>
@@ -27,6 +25,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/bug.h>
+#include <linux/jump_label.h>
 #include <linux/kernel.h>
 
 /* CPU feature register tracking */
@@ -104,14 +104,19 @@ static inline bool cpu_have_feature(unsi
 	return elf_hwcap & (1UL << num);
 }
 
+/* System capability check for constant caps */
+static inline bool cpus_have_const_cap(int num)
+{
+	if (num >= ARM64_NCAPS)
+		return false;
+	return static_branch_unlikely(&cpu_hwcap_keys[num]);
+}
+
 static inline bool cpus_have_cap(unsigned int num)
 {
 	if (num >= ARM64_NCAPS)
 		return false;
-	if (__builtin_constant_p(num))
-		return static_branch_unlikely(&cpu_hwcap_keys[num]);
-	else
-		return test_bit(num, cpu_hwcaps);
+	return test_bit(num, cpu_hwcaps);
 }
 
 static inline void cpus_set_cap(unsigned int num)
@@ -200,7 +205,7 @@ static inline bool cpu_supports_mixed_en
 
 static inline bool system_supports_32bit_el0(void)
 {
-	return cpus_have_cap(ARM64_HAS_32BIT_EL0);
+	return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);
 }
 
 static inline bool system_supports_mixed_endian_el0(void)
@@ -208,6 +213,17 @@ static inline bool system_supports_mixed
 	return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
 }
 
+static inline bool system_supports_fpsimd(void)
+{
+	return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
+}
+
+static inline bool system_uses_ttbr0_pan(void)
+{
+	return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
+		!cpus_have_cap(ARM64_HAS_PAN);
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/current.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/current.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/current.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/current.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,30 @@
+#ifndef __ASM_CURRENT_H
+#define __ASM_CURRENT_H
+
+#include <linux/compiler.h>
+
+#include <asm/sysreg.h>
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/*
+ * We don't use read_sysreg() as we want the compiler to cache the value where
+ * possible.
+ */
+static __always_inline struct task_struct *get_current(void)
+{
+	unsigned long sp_el0;
+
+	asm ("mrs %0, sp_el0" : "=r" (sp_el0));
+
+	return (struct task_struct *)sp_el0;
+}
+
+#define current get_current()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CURRENT_H */
+
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/debug-monitors.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/debug-monitors.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/debug-monitors.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/debug-monitors.h	2017-02-12 16:03:20.000000000 -0500
@@ -68,6 +68,9 @@
 #define BRK64_ESR_MASK		0xFFFF
 #define BRK64_ESR_KPROBES	0x0004
 #define BRK64_OPCODE_KPROBES	(AARCH64_BREAK_MON | (BRK64_ESR_KPROBES << 5))
+/* uprobes BRK opcodes with ESR encoding  */
+#define BRK64_ESR_UPROBES	0x0005
+#define BRK64_OPCODE_UPROBES	(AARCH64_BREAK_MON | (BRK64_ESR_UPROBES << 5))
 
 /* AArch32 */
 #define DBG_ESR_EVT_BKPT	0x4
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/efi.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/efi.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/efi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/efi.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,7 @@
 #ifndef _ASM_EFI_H
 #define _ASM_EFI_H
 
+#include <asm/cpufeature.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/neon.h>
@@ -51,6 +52,9 @@ int efi_set_mapping_permissions(struct m
 #define __efi_call_early(f, ...)	f(__VA_ARGS__)
 #define efi_is_64bit()			(true)
 
+#define efi_call_proto(protocol, f, instance, ...)			\
+	((protocol##_t *)instance)->f(instance, ##__VA_ARGS__)
+
 #define alloc_screen_info(x...)		&screen_info
 #define free_screen_info(x...)
 
@@ -75,7 +79,30 @@ static inline void efifb_setup_from_dmi(
 
 static inline void efi_set_pgd(struct mm_struct *mm)
 {
-	switch_mm(NULL, mm, NULL);
+	__switch_mm(mm);
+
+	if (system_uses_ttbr0_pan()) {
+		if (mm != current->active_mm) {
+			/*
+			 * Update the current thread's saved ttbr0 since it is
+			 * restored as part of a return from exception. Set
+			 * the hardware TTBR0_EL1 using cpu_switch_mm()
+			 * directly to enable potential errata workarounds.
+			 */
+			update_saved_ttbr0(current, mm);
+			cpu_switch_mm(mm->pgd, mm);
+		} else {
+			/*
+			 * Defer the switch to the current thread's TTBR0_EL1
+			 * until uaccess_enable(). Restore the current
+			 * thread's saved ttbr0 corresponding to its active_mm
+			 * (if different from init_mm).
+			 */
+			cpu_set_reserved_ttbr0();
+			if (current->active_mm != &init_mm)
+				update_saved_ttbr0(current, current->active_mm);
+		}
+	}
 }
 
 void efi_virtmap_load(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/elf.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/elf.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/elf.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/elf.h	2017-02-12 16:03:20.000000000 -0500
@@ -138,7 +138,11 @@ typedef struct user_fpsimd_state elf_fpr
  */
 #define ELF_PLAT_INIT(_r, load_addr)	(_r)->regs[0] = 0
 
-#define SET_PERSONALITY(ex)		clear_thread_flag(TIF_32BIT);
+#define SET_PERSONALITY(ex)						\
+({									\
+	clear_bit(TIF_32BIT, &current->mm->context.flags);		\
+	clear_thread_flag(TIF_32BIT);					\
+})
 
 /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
 #define ARCH_DLINFO							\
@@ -183,7 +187,11 @@ typedef compat_elf_greg_t		compat_elf_gr
 					 ((x)->e_flags & EF_ARM_EABI_MASK))
 
 #define compat_start_thread		compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex)	set_thread_flag(TIF_32BIT);
+#define COMPAT_SET_PERSONALITY(ex)					\
+({									\
+	set_bit(TIF_32BIT, &current->mm->context.flags);		\
+	set_thread_flag(TIF_32BIT);					\
+ })
 #define COMPAT_ARCH_DLINFO
 extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
 				      int uses_interp);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/futex.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/futex.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/futex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/futex.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,15 +21,12 @@
 #include <linux/futex.h>
 #include <linux/uaccess.h>
 
-#include <asm/alternative.h>
-#include <asm/cpufeature.h>
 #include <asm/errno.h>
-#include <asm/sysreg.h>
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, tmp, oparg)		\
+do {									\
+	uaccess_enable();						\
 	asm volatile(							\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,		\
-		    CONFIG_ARM64_PAN)					\
 "	prfm	pstl1strm, %2\n"					\
 "1:	ldxr	%w1, %2\n"						\
 	insn "\n"							\
@@ -44,11 +41,11 @@
 "	.popsection\n"							\
 	_ASM_EXTABLE(1b, 4b)						\
 	_ASM_EXTABLE(2b, 4b)						\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,		\
-		    CONFIG_ARM64_PAN)					\
 	: "=&r" (ret), "=&r" (oldval), "+Q" (*uaddr), "=&r" (tmp)	\
 	: "r" (oparg), "Ir" (-EFAULT)					\
-	: "memory")
+	: "memory");							\
+	uaccess_disable();						\
+} while (0)
 
 static inline int
 futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
@@ -118,8 +115,8 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
+	uaccess_enable();
 	asm volatile("// futex_atomic_cmpxchg_inatomic\n"
-ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
 "	prfm	pstl1strm, %2\n"
 "1:	ldxr	%w1, %2\n"
 "	sub	%w3, %w1, %w4\n"
@@ -134,10 +131,10 @@ ALTERNATIVE("nop", SET_PSTATE_PAN(0), AR
 "	.popsection\n"
 	_ASM_EXTABLE(1b, 4b)
 	_ASM_EXTABLE(2b, 4b)
-ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
 	: "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
 	: "r" (oldval), "r" (newval), "Ir" (-EFAULT)
 	: "memory");
+	uaccess_disable();
 
 	*uval = val;
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/hw_breakpoint.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/hw_breakpoint.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/hw_breakpoint.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/hw_breakpoint.h	2017-02-12 16:03:20.000000000 -0500
@@ -77,7 +77,11 @@ static inline void decode_ctrl_reg(u32 r
 /* Lengths */
 #define ARM_BREAKPOINT_LEN_1	0x1
 #define ARM_BREAKPOINT_LEN_2	0x3
+#define ARM_BREAKPOINT_LEN_3	0x7
 #define ARM_BREAKPOINT_LEN_4	0xf
+#define ARM_BREAKPOINT_LEN_5	0x1f
+#define ARM_BREAKPOINT_LEN_6	0x3f
+#define ARM_BREAKPOINT_LEN_7	0x7f
 #define ARM_BREAKPOINT_LEN_8	0xff
 
 /* Kernel stepping */
@@ -119,7 +123,7 @@ struct perf_event;
 struct pmu;
 
 extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
-				  int *gen_len, int *gen_type);
+				  int *gen_len, int *gen_type, int *offset);
 extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
 extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
 extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/io.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/io.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/io.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/io.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/blk_types.h>
 
 #include <asm/byteorder.h>
 #include <asm/barrier.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/arm64/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,6 @@
 generic-y += bugs.h
 generic-y += clkdev.h
 generic-y += cputime.h
-generic-y += current.h
 generic-y += delay.h
 generic-y += div64.h
 generic-y += dma.h
@@ -24,7 +23,6 @@ generic-y += mm-arch-hooks.h
 generic-y += mman.h
 generic-y += msgbuf.h
 generic-y += msi.h
-generic-y += mutex.h
 generic-y += poll.h
 generic-y += preempt.h
 generic-y += resource.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/kernel-pgtable.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/kernel-pgtable.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/kernel-pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/kernel-pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
 #ifndef __ASM_KERNEL_PGTABLE_H
 #define __ASM_KERNEL_PGTABLE_H
 
+#include <asm/pgtable.h>
 #include <asm/sparsemem.h>
 
 /*
@@ -54,6 +55,12 @@
 #define SWAPPER_DIR_SIZE	(SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
 #define IDMAP_DIR_SIZE		(IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
 
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+#define RESERVED_TTBR0_SIZE	(PAGE_SIZE)
+#else
+#define RESERVED_TTBR0_SIZE	(0)
+#endif
+
 /* Initial memory map size */
 #if ARM64_SWAPPER_USES_SECTION_MAPS
 #define SWAPPER_BLOCK_SHIFT	SECTION_SHIFT
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/memory.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/memory.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/memory.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/memory.h	2017-02-12 16:03:20.000000000 -0500
@@ -165,6 +165,11 @@ extern u64			kimage_vaddr;
 /* the offset between the kernel virtual and physical mappings */
 extern u64			kimage_voffset;
 
+static inline unsigned long kaslr_offset(void)
+{
+	return kimage_vaddr - KIMAGE_VADDR;
+}
+
 /*
  * Allow all memory at the discovery stage. We will clip it later.
  */
@@ -217,7 +222,7 @@ static inline void *phys_to_virt(phys_ad
 #define _virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 #else
 #define __virt_to_pgoff(kaddr)	(((u64)(kaddr) & ~PAGE_OFFSET) / PAGE_SIZE * sizeof(struct page))
-#define __page_to_voff(page)	(((u64)(page) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
+#define __page_to_voff(kaddr)	(((u64)(kaddr) & ~VMEMMAP_START) * PAGE_SIZE / sizeof(struct page))
 
 #define page_to_virt(page)	((void *)((__page_to_voff(page)) | PAGE_OFFSET))
 #define virt_to_page(vaddr)	((struct page *)((__virt_to_pgoff(vaddr)) | VMEMMAP_START))
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/mmu_context.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/mmu_context.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/mmu_context.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/mmu_context.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/sched.h>
 
 #include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
 #include <asm/proc-fns.h>
 #include <asm-generic/mm_hooks.h>
 #include <asm/cputype.h>
@@ -103,7 +104,7 @@ static inline void cpu_uninstall_idmap(v
 	local_flush_tlb_all();
 	cpu_set_default_tcr_t0sz();
 
-	if (mm != &init_mm)
+	if (mm != &init_mm && !system_uses_ttbr0_pan())
 		cpu_switch_mm(mm->pgd, mm);
 }
 
@@ -163,20 +164,26 @@ enter_lazy_tlb(struct mm_struct *mm, str
 {
 }
 
-/*
- * This is the actual mm switch as far as the scheduler
- * is concerned.  No registers are touched.  We avoid
- * calling the CPU specific function when the mm hasn't
- * actually changed.
- */
-static inline void
-switch_mm(struct mm_struct *prev, struct mm_struct *next,
-	  struct task_struct *tsk)
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+static inline void update_saved_ttbr0(struct task_struct *tsk,
+				      struct mm_struct *mm)
 {
-	unsigned int cpu = smp_processor_id();
+	if (system_uses_ttbr0_pan()) {
+		BUG_ON(mm->pgd == swapper_pg_dir);
+		task_thread_info(tsk)->ttbr0 =
+			virt_to_phys(mm->pgd) | ASID(mm) << 48;
+	}
+}
+#else
+static inline void update_saved_ttbr0(struct task_struct *tsk,
+				      struct mm_struct *mm)
+{
+}
+#endif
 
-	if (prev == next)
-		return;
+static inline void __switch_mm(struct mm_struct *next)
+{
+	unsigned int cpu = smp_processor_id();
 
 	/*
 	 * init_mm.pgd does not contain any user mappings and it is always
@@ -190,8 +197,26 @@ switch_mm(struct mm_struct *prev, struct
 	check_and_switch_context(next, cpu);
 }
 
+static inline void
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	  struct task_struct *tsk)
+{
+	if (prev != next)
+		__switch_mm(next);
+
+	/*
+	 * Update the saved TTBR0_EL1 of the scheduled-in task as the previous
+	 * value may have not been initialised yet (activate_mm caller) or the
+	 * ASID has changed since the last run (following the context switch
+	 * of another thread of the same process). Avoid setting the reserved
+	 * TTBR0_EL1 to swapper_pg_dir (init_mm; e.g. via idle_task_exit).
+	 */
+	if (next != &init_mm)
+		update_saved_ttbr0(tsk, next);
+}
+
 #define deactivate_mm(tsk,mm)	do { } while (0)
-#define activate_mm(prev,next)	switch_mm(prev, next, NULL)
+#define activate_mm(prev,next)	switch_mm(prev, next, current)
 
 void verify_cpu_asid_bits(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/mmu.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/mmu.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/mmu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/mmu.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
 typedef struct {
 	atomic64_t	id;
 	void		*vdso;
+	unsigned long	flags;
 } mm_context_t;
 
 /*
@@ -34,7 +35,7 @@ extern void __iomem *early_io_map(phys_a
 extern void init_mem_pgprot(void);
 extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
 			       unsigned long virt, phys_addr_t size,
-			       pgprot_t prot, bool allow_block_mappings);
+			       pgprot_t prot, bool page_mappings_only);
 extern void *fixmap_remap_fdt(phys_addr_t dt_phys);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/neon.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/neon.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/neon.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/neon.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,8 +9,9 @@
  */
 
 #include <linux/types.h>
+#include <asm/fpsimd.h>
 
-#define cpu_has_neon()		(1)
+#define cpu_has_neon()		system_supports_fpsimd()
 
 #define kernel_neon_begin()	kernel_neon_begin_partial(32)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/numa.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/numa.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/numa.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/numa.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,8 @@ int __node_distance(int from, int to);
 
 extern nodemask_t numa_nodes_parsed __initdata;
 
+extern bool numa_off;
+
 /* Mappings between node number and cpus on that node. */
 extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
 void numa_clear_node(unsigned int cpu);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/opcodes.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/opcodes.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/opcodes.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/opcodes.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-#ifdef CONFIG_CPU_BIG_ENDIAN
-#define CONFIG_CPU_ENDIAN_BE8 CONFIG_CPU_BIG_ENDIAN
-#endif
-
-#include <../../arm/include/asm/opcodes.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/percpu.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/percpu.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/percpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/percpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,8 @@
 #ifndef __ASM_PERCPU_H
 #define __ASM_PERCPU_H
 
+#include <asm/stack_pointer.h>
+
 static inline void set_my_cpu_offset(unsigned long off)
 {
 	asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
@@ -101,16 +103,16 @@ static inline unsigned long __percpu_rea
 
 	switch (size) {
 	case 1:
-		ret = ACCESS_ONCE(*(u8 *)ptr);
+		ret = READ_ONCE(*(u8 *)ptr);
 		break;
 	case 2:
-		ret = ACCESS_ONCE(*(u16 *)ptr);
+		ret = READ_ONCE(*(u16 *)ptr);
 		break;
 	case 4:
-		ret = ACCESS_ONCE(*(u32 *)ptr);
+		ret = READ_ONCE(*(u32 *)ptr);
 		break;
 	case 8:
-		ret = ACCESS_ONCE(*(u64 *)ptr);
+		ret = READ_ONCE(*(u64 *)ptr);
 		break;
 	default:
 		BUILD_BUG();
@@ -123,16 +125,16 @@ static inline void __percpu_write(void *
 {
 	switch (size) {
 	case 1:
-		ACCESS_ONCE(*(u8 *)ptr) = (u8)val;
+		WRITE_ONCE(*(u8 *)ptr, (u8)val);
 		break;
 	case 2:
-		ACCESS_ONCE(*(u16 *)ptr) = (u16)val;
+		WRITE_ONCE(*(u16 *)ptr, (u16)val);
 		break;
 	case 4:
-		ACCESS_ONCE(*(u32 *)ptr) = (u32)val;
+		WRITE_ONCE(*(u32 *)ptr, (u32)val);
 		break;
 	case 8:
-		ACCESS_ONCE(*(u64 *)ptr) = (u64)val;
+		WRITE_ONCE(*(u64 *)ptr, (u64)val);
 		break;
 	default:
 		BUILD_BUG();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/perf_event.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/perf_event.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/perf_event.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/perf_event.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,8 @@
 #ifndef __ASM_PERF_EVENT_H
 #define __ASM_PERF_EVENT_H
 
+#include <asm/stack_pointer.h>
+
 #define	ARMV8_PMU_MAX_COUNTERS	32
 #define	ARMV8_PMU_COUNTER_MASK	(ARMV8_PMU_MAX_COUNTERS - 1)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/probes.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/probes.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/probes.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/probes.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,21 +15,22 @@
 #ifndef _ARM_PROBES_H
 #define _ARM_PROBES_H
 
-#include <asm/opcodes.h>
-
-struct kprobe;
-struct arch_specific_insn;
-
-typedef u32 kprobe_opcode_t;
-typedef void (kprobes_handler_t) (u32 opcode, long addr, struct pt_regs *);
+typedef u32 probe_opcode_t;
+typedef void (probes_handler_t) (u32 opcode, long addr, struct pt_regs *);
 
 /* architecture specific copy of original instruction */
-struct arch_specific_insn {
-	kprobe_opcode_t *insn;
+struct arch_probe_insn {
+	probe_opcode_t *insn;
 	pstate_check_t *pstate_cc;
-	kprobes_handler_t *handler;
+	probes_handler_t *handler;
 	/* restore address after step xol */
 	unsigned long restore;
 };
+#ifdef CONFIG_KPROBES
+typedef u32 kprobe_opcode_t;
+struct arch_specific_insn {
+	struct arch_probe_insn api;
+};
+#endif
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -149,8 +149,6 @@ static inline void cpu_relax(void)
 	asm volatile("yield" ::: "memory");
 }
 
-#define cpu_relax_lowlatency()                cpu_relax()
-
 /* Thread switching */
 extern struct task_struct *cpu_switch_to(struct task_struct *prev,
 					 struct task_struct *next);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/ptdump.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/ptdump.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/ptdump.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/ptdump.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,9 +16,10 @@
 #ifndef __ASM_PTDUMP_H
 #define __ASM_PTDUMP_H
 
-#ifdef CONFIG_ARM64_PTDUMP
+#ifdef CONFIG_ARM64_PTDUMP_CORE
 
 #include <linux/mm_types.h>
+#include <linux/seq_file.h>
 
 struct addr_marker {
 	unsigned long start_address;
@@ -29,16 +30,25 @@ struct ptdump_info {
 	struct mm_struct		*mm;
 	const struct addr_marker	*markers;
 	unsigned long			base_addr;
-	unsigned long			max_addr;
 };
 
-int ptdump_register(struct ptdump_info *info, const char *name);
-
+void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info);
+#ifdef CONFIG_ARM64_PTDUMP_DEBUGFS
+int ptdump_debugfs_register(struct ptdump_info *info, const char *name);
 #else
-static inline int ptdump_register(struct ptdump_info *info, const char *name)
+static inline int ptdump_debugfs_register(struct ptdump_info *info,
+					const char *name)
 {
 	return 0;
 }
-#endif /* CONFIG_ARM64_PTDUMP */
+#endif
+void ptdump_check_wx(void);
+#endif /* CONFIG_ARM64_PTDUMP_CORE */
+
+#ifdef CONFIG_DEBUG_WX
+#define debug_checkwx()	ptdump_check_wx()
+#else
+#define debug_checkwx()	do { } while (0)
+#endif
 
 #endif /* __ASM_PTDUMP_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/ptrace.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/ptrace.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/ptrace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/ptrace.h	2017-02-12 16:03:20.000000000 -0500
@@ -217,6 +217,14 @@ int valid_user_regs(struct user_pt_regs
 
 #include <asm-generic/ptrace.h>
 
+#define procedure_link_pointer(regs)	((regs)->regs[30])
+
+static inline void procedure_link_pointer_set(struct pt_regs *regs,
+					   unsigned long val)
+{
+	procedure_link_pointer(regs) = val;
+}
+
 #undef profile_pc
 extern unsigned long profile_pc(struct pt_regs *regs);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/smp.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/smp.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/smp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/smp.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,11 +29,22 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/percpu.h>
+
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/thread_info.h>
 
-#define raw_smp_processor_id() (current_thread_info()->cpu)
+DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
+
+/*
+ * We don't use this_cpu_read(cpu_number) as that has implicit writes to
+ * preempt_count, and associated (compiler) barriers, that we'd like to avoid
+ * the expense of. If we're preemptible, the value can be stale at use anyway.
+ * And we can't use this_cpu_ptr() either, as that winds up recursing back
+ * here under CONFIG_DEBUG_PREEMPT=y.
+ */
+#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
 
 struct seq_file;
 
@@ -73,6 +84,7 @@ asmlinkage void secondary_start_kernel(v
  */
 struct secondary_data {
 	void *stack;
+	struct task_struct *task;
 	long status;
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/stack_pointer.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/stack_pointer.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/stack_pointer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/stack_pointer.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,9 @@
+#ifndef __ASM_STACK_POINTER_H
+#define __ASM_STACK_POINTER_H
+
+/*
+ * how to get the current stack pointer from C
+ */
+register unsigned long current_stack_pointer asm ("sp");
+
+#endif /* __ASM_STACK_POINTER_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/suspend.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/suspend.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/suspend.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/suspend.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 #ifndef __ASM_SUSPEND_H
 #define __ASM_SUSPEND_H
 
-#define NR_CTX_REGS 10
+#define NR_CTX_REGS 12
 #define NR_CALLEE_SAVED_REGS 12
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/sysreg.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/sysreg.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/sysreg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/sysreg.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,8 +22,6 @@
 
 #include <linux/stringify.h>
 
-#include <asm/opcodes.h>
-
 /*
  * ARMv8 ARM reserves the following encoding for system registers:
  * (Ref: ARMv8 ARM, Section: "System instruction class encoding overview",
@@ -37,6 +35,33 @@
 #define sys_reg(op0, op1, crn, crm, op2) \
 	((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
 
+#ifndef CONFIG_BROKEN_GAS_INST
+
+#ifdef __ASSEMBLY__
+#define __emit_inst(x)			.inst (x)
+#else
+#define __emit_inst(x)			".inst " __stringify((x)) "\n\t"
+#endif
+
+#else  /* CONFIG_BROKEN_GAS_INST */
+
+#ifndef CONFIG_CPU_BIG_ENDIAN
+#define __INSTR_BSWAP(x)		(x)
+#else  /* CONFIG_CPU_BIG_ENDIAN */
+#define __INSTR_BSWAP(x)		((((x) << 24) & 0xff000000)	| \
+					 (((x) <<  8) & 0x00ff0000)	| \
+					 (((x) >>  8) & 0x0000ff00)	| \
+					 (((x) >> 24) & 0x000000ff))
+#endif	/* CONFIG_CPU_BIG_ENDIAN */
+
+#ifdef __ASSEMBLY__
+#define __emit_inst(x)			.long __INSTR_BSWAP(x)
+#else  /* __ASSEMBLY__ */
+#define __emit_inst(x)			".long " __stringify(__INSTR_BSWAP(x)) "\n\t"
+#endif	/* __ASSEMBLY__ */
+
+#endif	/* CONFIG_BROKEN_GAS_INST */
+
 #define SYS_MIDR_EL1			sys_reg(3, 0, 0, 0, 0)
 #define SYS_MPIDR_EL1			sys_reg(3, 0, 0, 0, 5)
 #define SYS_REVIDR_EL1			sys_reg(3, 0, 0, 0, 6)
@@ -81,10 +106,10 @@
 #define REG_PSTATE_PAN_IMM		sys_reg(0, 0, 4, 0, 4)
 #define REG_PSTATE_UAO_IMM		sys_reg(0, 0, 4, 0, 3)
 
-#define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM |\
-				     (!!x)<<8 | 0x1f)
-#define SET_PSTATE_UAO(x) __inst_arm(0xd5000000 | REG_PSTATE_UAO_IMM |\
-				     (!!x)<<8 | 0x1f)
+#define SET_PSTATE_PAN(x) __emit_inst(0xd5000000 | REG_PSTATE_PAN_IMM |	\
+				      (!!x)<<8 | 0x1f)
+#define SET_PSTATE_UAO(x) __emit_inst(0xd5000000 | REG_PSTATE_UAO_IMM |	\
+				      (!!x)<<8 | 0x1f)
 
 /* Common SCTLR_ELx flags. */
 #define SCTLR_ELx_EE    (1 << 25)
@@ -228,11 +253,11 @@
 	.equ	.L__reg_num_xzr, 31
 
 	.macro	mrs_s, rt, sreg
-	.inst	0xd5200000|(\sreg)|(.L__reg_num_\rt)
+	 __emit_inst(0xd5200000|(\sreg)|(.L__reg_num_\rt))
 	.endm
 
 	.macro	msr_s, sreg, rt
-	.inst	0xd5000000|(\sreg)|(.L__reg_num_\rt)
+	__emit_inst(0xd5000000|(\sreg)|(.L__reg_num_\rt))
 	.endm
 
 #else
@@ -246,11 +271,11 @@ asm(
 "	.equ	.L__reg_num_xzr, 31\n"
 "\n"
 "	.macro	mrs_s, rt, sreg\n"
-"	.inst	0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n"
+	__emit_inst(0xd5200000|(\\sreg)|(.L__reg_num_\\rt))
 "	.endm\n"
 "\n"
 "	.macro	msr_s, sreg, rt\n"
-"	.inst	0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"
+	__emit_inst(0xd5000000|(\\sreg)|(.L__reg_num_\\rt))
 "	.endm\n"
 );
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/thread_info.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/thread_info.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/thread_info.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/thread_info.h	2017-02-12 16:03:20.000000000 -0500
@@ -36,58 +36,31 @@
 
 struct task_struct;
 
+#include <asm/stack_pointer.h>
 #include <asm/types.h>
 
 typedef unsigned long mm_segment_t;
 
 /*
  * low level task data that entry.S needs immediate access to.
- * __switch_to() assumes cpu_context follows immediately after cpu_domain.
  */
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
 	mm_segment_t		addr_limit;	/* address limit */
-	struct task_struct	*task;		/* main task structure */
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	u64			ttbr0;		/* saved TTBR0_EL1 */
+#endif
 	int			preempt_count;	/* 0 => preemptable, <0 => bug */
-	int			cpu;		/* cpu */
 };
 
 #define INIT_THREAD_INFO(tsk)						\
 {									\
-	.task		= &tsk,						\
-	.flags		= 0,						\
 	.preempt_count	= INIT_PREEMPT_COUNT,				\
 	.addr_limit	= KERNEL_DS,					\
 }
 
-#define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
-/*
- * how to get the current stack pointer from C
- */
-register unsigned long current_stack_pointer asm ("sp");
-
-/*
- * how to get the thread information struct from C
- */
-static inline struct thread_info *current_thread_info(void) __attribute_const__;
-
-/*
- * struct thread_info can be accessed directly via sp_el0.
- *
- * We don't use read_sysreg() as we want the compiler to cache the value where
- * possible.
- */
-static inline struct thread_info *current_thread_info(void)
-{
-	unsigned long sp_el0;
-
-	asm ("mrs %0, sp_el0" : "=r" (sp_el0));
-
-	return (struct thread_info *)sp_el0;
-}
-
 #define thread_saved_pc(tsk)	\
 	((unsigned long)(tsk->thread.cpu_context.pc))
 #define thread_saved_sp(tsk)	\
@@ -112,6 +85,7 @@ static inline struct thread_info *curren
 #define TIF_NEED_RESCHED	1
 #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
 #define TIF_FOREIGN_FPSTATE	3	/* CPU's FP state is not current's */
+#define TIF_UPROBE		4	/* uprobe breakpoint or singlestep */
 #define TIF_NOHZ		7
 #define TIF_SYSCALL_TRACE	8
 #define TIF_SYSCALL_AUDIT	9
@@ -132,10 +106,12 @@ static inline struct thread_info *curren
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
+#define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_32BIT		(1 << TIF_32BIT)
 
 #define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
-				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
+				 _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
+				 _TIF_UPROBE)
 
 #define _TIF_SYSCALL_WORK	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
 				 _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/uaccess.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/uaccess.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/uaccess.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/uaccess.h	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,10 @@
 #ifndef __ASM_UACCESS_H
 #define __ASM_UACCESS_H
 
+#include <asm/alternative.h>
+#include <asm/kernel-pgtable.h>
+#include <asm/sysreg.h>
+
 /*
  * User space memory access functions
  */
@@ -26,10 +30,8 @@
 #include <linux/string.h>
 #include <linux/thread_info.h>
 
-#include <asm/alternative.h>
 #include <asm/cpufeature.h>
 #include <asm/ptrace.h>
-#include <asm/sysreg.h>
 #include <asm/errno.h>
 #include <asm/memory.h>
 #include <asm/compiler.h>
@@ -120,6 +122,99 @@ static inline void set_fs(mm_segment_t f
 	"	.popsection\n"
 
 /*
+ * User access enabling/disabling.
+ */
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+static inline void __uaccess_ttbr0_disable(void)
+{
+	unsigned long ttbr;
+
+	/* reserved_ttbr0 placed at the end of swapper_pg_dir */
+	ttbr = read_sysreg(ttbr1_el1) + SWAPPER_DIR_SIZE;
+	write_sysreg(ttbr, ttbr0_el1);
+	isb();
+}
+
+static inline void __uaccess_ttbr0_enable(void)
+{
+	unsigned long flags;
+
+	/*
+	 * Disable interrupts to avoid preemption between reading the 'ttbr0'
+	 * variable and the MSR. A context switch could trigger an ASID
+	 * roll-over and an update of 'ttbr0'.
+	 */
+	local_irq_save(flags);
+	write_sysreg(current_thread_info()->ttbr0, ttbr0_el1);
+	isb();
+	local_irq_restore(flags);
+}
+
+static inline bool uaccess_ttbr0_disable(void)
+{
+	if (!system_uses_ttbr0_pan())
+		return false;
+	__uaccess_ttbr0_disable();
+	return true;
+}
+
+static inline bool uaccess_ttbr0_enable(void)
+{
+	if (!system_uses_ttbr0_pan())
+		return false;
+	__uaccess_ttbr0_enable();
+	return true;
+}
+#else
+static inline bool uaccess_ttbr0_disable(void)
+{
+	return false;
+}
+
+static inline bool uaccess_ttbr0_enable(void)
+{
+	return false;
+}
+#endif
+
+#define __uaccess_disable(alt)						\
+do {									\
+	if (!uaccess_ttbr0_disable())					\
+		asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), alt,		\
+				CONFIG_ARM64_PAN));			\
+} while (0)
+
+#define __uaccess_enable(alt)						\
+do {									\
+	if (!uaccess_ttbr0_enable())					\
+		asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), alt,		\
+				CONFIG_ARM64_PAN));			\
+} while (0)
+
+static inline void uaccess_disable(void)
+{
+	__uaccess_disable(ARM64_HAS_PAN);
+}
+
+static inline void uaccess_enable(void)
+{
+	__uaccess_enable(ARM64_HAS_PAN);
+}
+
+/*
+ * These functions are no-ops when UAO is present.
+ */
+static inline void uaccess_disable_not_uao(void)
+{
+	__uaccess_disable(ARM64_ALT_PAN_NOT_UAO);
+}
+
+static inline void uaccess_enable_not_uao(void)
+{
+	__uaccess_enable(ARM64_ALT_PAN_NOT_UAO);
+}
+
+/*
  * The "__xxx" versions of the user access functions do not verify the address
  * space - it must have been done previously with a separate "access_ok()"
  * call.
@@ -146,8 +241,7 @@ static inline void set_fs(mm_segment_t f
 do {									\
 	unsigned long __gu_val;						\
 	__chk_user_ptr(ptr);						\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
-			CONFIG_ARM64_PAN));				\
+	uaccess_enable_not_uao();					\
 	switch (sizeof(*(ptr))) {					\
 	case 1:								\
 		__get_user_asm("ldrb", "ldtrb", "%w", __gu_val, (ptr),  \
@@ -168,9 +262,8 @@ do {									\
 	default:							\
 		BUILD_BUG();						\
 	}								\
+	uaccess_disable_not_uao();					\
 	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
-			CONFIG_ARM64_PAN));				\
 } while (0)
 
 #define __get_user(x, ptr)						\
@@ -215,8 +308,7 @@ do {									\
 do {									\
 	__typeof__(*(ptr)) __pu_val = (x);				\
 	__chk_user_ptr(ptr);						\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
-			CONFIG_ARM64_PAN));				\
+	uaccess_enable_not_uao();					\
 	switch (sizeof(*(ptr))) {					\
 	case 1:								\
 		__put_user_asm("strb", "sttrb", "%w", __pu_val, (ptr),	\
@@ -237,8 +329,7 @@ do {									\
 	default:							\
 		BUILD_BUG();						\
 	}								\
-	asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
-			CONFIG_ARM64_PAN));				\
+	uaccess_disable_not_uao();					\
 } while (0)
 
 #define __put_user(x, ptr)						\
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/uprobes.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/uprobes.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/uprobes.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/uprobes.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014-2016 Pratyush Anand <panand@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+
+#include <asm/debug-monitors.h>
+#include <asm/insn.h>
+#include <asm/probes.h>
+
+#define MAX_UINSN_BYTES		AARCH64_INSN_SIZE
+
+#define UPROBE_SWBP_INSN	BRK64_OPCODE_UPROBES
+#define UPROBE_SWBP_INSN_SIZE	AARCH64_INSN_SIZE
+#define UPROBE_XOL_SLOT_BYTES	MAX_UINSN_BYTES
+
+typedef u32 uprobe_opcode_t;
+
+struct arch_uprobe_task {
+};
+
+struct arch_uprobe {
+	union {
+		u8 insn[MAX_UINSN_BYTES];
+		u8 ixol[MAX_UINSN_BYTES];
+	};
+	struct arch_probe_insn api;
+	bool simulate;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/virt.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/virt.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/virt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/virt.h	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,7 @@
 #include <asm/ptrace.h>
 #include <asm/sections.h>
 #include <asm/sysreg.h>
+#include <asm/cpufeature.h>
 
 /*
  * __boot_cpu_mode records what mode CPUs were booted in.
@@ -80,6 +81,14 @@ static inline bool is_kernel_in_hyp_mode
 	return read_sysreg(CurrentEL) == CurrentEL_EL2;
 }
 
+static inline bool has_vhe(void)
+{
+	if (cpus_have_const_cap(ARM64_HAS_VIRT_HOST_EXTN))
+		return true;
+
+	return false;
+}
+
 #ifdef CONFIG_ARM64_VHE
 extern void verify_cpu_run_el(void);
 #else
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/word-at-a-time.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/word-at-a-time.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/word-at-a-time.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/word-at-a-time.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #ifndef __ASM_WORD_AT_A_TIME_H
 #define __ASM_WORD_AT_A_TIME_H
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifndef __AARCH64EB__
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/xen/hypercall.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/hypercall.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/xen/hypercall.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/hypercall.h	2017-02-12 16:03:20.000000000 -0500
@@ -1 +1 @@
-#include <../../arm/include/asm/xen/hypercall.h>
+#include <xen/arm/hypercall.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/xen/hypervisor.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/hypervisor.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/xen/hypervisor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/hypervisor.h	2017-02-12 16:03:20.000000000 -0500
@@ -1 +1 @@
-#include <../../arm/include/asm/xen/hypervisor.h>
+#include <xen/arm/hypervisor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/xen/interface.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/interface.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/xen/interface.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/interface.h	2017-02-12 16:03:20.000000000 -0500
@@ -1 +1 @@
-#include <../../arm/include/asm/xen/interface.h>
+#include <xen/arm/interface.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/xen/page-coherent.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/page-coherent.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/xen/page-coherent.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/page-coherent.h	2017-02-12 16:03:20.000000000 -0500
@@ -1 +1 @@
-#include <../../arm/include/asm/xen/page-coherent.h>
+#include <xen/arm/page-coherent.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/asm/xen/page.h linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/page.h
--- linux-libre-4.9-gnu/arch/arm64/include/asm/xen/page.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/asm/xen/page.h	2017-02-12 16:03:20.000000000 -0500
@@ -1 +1 @@
-#include <../../arm/include/asm/xen/page.h>
+#include <xen/arm/page.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/include/uapi/asm/ptrace.h linux-libre-4.10-rc8-gnu/arch/arm64/include/uapi/asm/ptrace.h
--- linux-libre-4.9-gnu/arch/arm64/include/uapi/asm/ptrace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/include/uapi/asm/ptrace.h	2017-02-12 16:03:20.000000000 -0500
@@ -77,6 +77,7 @@ struct user_fpsimd_state {
 	__uint128_t	vregs[32];
 	__u32		fpsr;
 	__u32		fpcr;
+	__u32		__reserved[2];
 };
 
 struct user_hwdebug_state {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/Kconfig linux-libre-4.10-rc8-gnu/arch/arm64/Kconfig
--- linux-libre-4.9-gnu/arch/arm64/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -52,6 +52,7 @@ config ARM64
 	select GENERIC_TIME_VSYSCALL
 	select HANDLE_DOMAIN_IRQ
 	select HARDIRQS_SW_RESEND
+	select HAVE_ACPI_APEI if (ACPI && EFI)
 	select HAVE_ALIGNED_STRUCT_PAGE if SLUB
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_BITREVERSE
@@ -109,6 +110,7 @@ config ARM64
 	select POWER_SUPPLY
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
+	select THREAD_INFO_IN_TASK
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -238,6 +240,9 @@ config PGTABLE_LEVELS
 	default 3 if ARM64_16K_PAGES && ARM64_VA_BITS_47
 	default 4 if !ARM64_64K_PAGES && ARM64_VA_BITS_48
 
+config ARCH_SUPPORTS_UPROBES
+	def_bool y
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -790,6 +795,14 @@ config SETEND_EMULATION
 	  If unsure, say Y
 endif
 
+config ARM64_SW_TTBR0_PAN
+	bool "Emulate Privileged Access Never using TTBR0_EL1 switching"
+	help
+	  Enabling this option prevents the kernel from accessing
+	  user-space memory directly by pointing TTBR0_EL1 to a reserved
+	  zeroed area and reserved ASID. The user access routines
+	  restore the valid TTBR0_EL1 temporarily.
+
 menu "ARMv8.1 architectural features"
 
 config ARM64_HW_AFDBM
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/Kconfig.debug linux-libre-4.10-rc8-gnu/arch/arm64/Kconfig.debug
--- linux-libre-4.9-gnu/arch/arm64/Kconfig.debug	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/Kconfig.debug	2017-02-12 16:03:20.000000000 -0500
@@ -2,9 +2,13 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
-config ARM64_PTDUMP
+config ARM64_PTDUMP_CORE
+	def_bool n
+
+config ARM64_PTDUMP_DEBUGFS
 	bool "Export kernel pagetable layout to userspace via debugfs"
 	depends on DEBUG_KERNEL
+	select ARM64_PTDUMP_CORE
 	select DEBUG_FS
         help
 	  Say Y here if you want to show the kernel pagetable layout in a
@@ -38,6 +42,35 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
 	  of TEXT_OFFSET and platforms must not require a specific
 	  value.
 
+config DEBUG_WX
+	bool "Warn on W+X mappings at boot"
+	select ARM64_PTDUMP_CORE
+	---help---
+	  Generate a warning if any W+X mappings are found at boot.
+
+	  This is useful for discovering cases where the kernel is leaving
+	  W+X mappings after applying NX, as such mappings are a security risk.
+	  This check also includes UXN, which should be set on all kernel
+	  mappings.
+
+	  Look for a message in dmesg output like this:
+
+	    arm64/mm: Checked W+X mappings: passed, no W+X pages found.
+
+	  or like this, if the check failed:
+
+	    arm64/mm: Checked W+X mappings: FAILED, <N> W+X pages found.
+
+	  Note that even if the check fails, your kernel is possibly
+	  still fine, as W+X mappings are not a security hole in
+	  themselves, what they do is that they make the exploitation
+	  of other unfixed kernel bugs easier.
+
+	  There is no runtime or memory usage effect of this option
+	  once the kernel has booted up - it's a one time check.
+
+	  If in doubt, say "Y".
+
 config DEBUG_SET_MODULE_RONX
 	bool "Set loadable kernel module data as NX and text as RO"
 	depends on MODULES
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/Kconfig.platforms linux-libre-4.10-rc8-gnu/arch/arm64/Kconfig.platforms
--- linux-libre-4.9-gnu/arch/arm64/Kconfig.platforms	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/Kconfig.platforms	2017-02-12 16:03:20.000000000 -0500
@@ -113,6 +113,7 @@ config ARCH_MVEBU
 
 config ARCH_QCOM
 	bool "Qualcomm Platforms"
+	select GPIOLIB
 	select PINCTRL
 	help
 	  This enables support for the ARMv8 based Qualcomm chipsets.
@@ -143,6 +144,7 @@ config ARCH_RENESAS
 	select PM
 	select PM_GENERIC_DOMAINS
 	select RENESAS_IRQC
+	select SOC_BUS
 	help
 	  This enables support for the ARMv8 based Renesas SoCs.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/acpi.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/acpi.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/acpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/acpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -132,14 +132,13 @@ static int __init acpi_fadt_sanity_check
 	struct acpi_table_header *table;
 	struct acpi_table_fadt *fadt;
 	acpi_status status;
-	acpi_size tbl_size;
 	int ret = 0;
 
 	/*
 	 * FADT is required on arm64; retrieve it to check its presence
 	 * and carry out revision and ACPI HW reduced compliancy tests
 	 */
-	status = acpi_get_table_with_size(ACPI_SIG_FADT, 0, &table, &tbl_size);
+	status = acpi_get_table(ACPI_SIG_FADT, 0, &table);
 	if (ACPI_FAILURE(status)) {
 		const char *msg = acpi_format_exception(status);
 
@@ -170,10 +169,10 @@ static int __init acpi_fadt_sanity_check
 
 out:
 	/*
-	 * acpi_get_table_with_size() creates FADT table mapping that
+	 * acpi_get_table() creates FADT table mapping that
 	 * should be released after parsing and before resuming boot
 	 */
-	early_acpi_os_unmap_memory(table, tbl_size);
+	acpi_put_table(table);
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/armv8_deprecated.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/armv8_deprecated.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/armv8_deprecated.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/armv8_deprecated.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,14 +14,12 @@
 #include <linux/slab.h>
 #include <linux/sysctl.h>
 
-#include <asm/alternative.h>
 #include <asm/cpufeature.h>
 #include <asm/insn.h>
-#include <asm/opcodes.h>
 #include <asm/sysreg.h>
 #include <asm/system_misc.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cpufeature.h>
 
 #define CREATE_TRACE_POINTS
@@ -285,10 +283,10 @@ static void __init register_insn_emulati
 #define __SWP_LL_SC_LOOPS	4
 
 #define __user_swpX_asm(data, addr, res, temp, temp2, B)	\
+do {								\
+	uaccess_enable();					\
 	__asm__ __volatile__(					\
 	"	mov		%w3, %w7\n"			\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,	\
-		    CONFIG_ARM64_PAN)				\
 	"0:	ldxr"B"		%w2, [%4]\n"			\
 	"1:	stxr"B"		%w0, %w1, [%4]\n"		\
 	"	cbz		%w0, 2f\n"			\
@@ -306,12 +304,12 @@ static void __init register_insn_emulati
 	"	.popsection"					\
 	_ASM_EXTABLE(0b, 4b)					\
 	_ASM_EXTABLE(1b, 4b)					\
-	ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,	\
-		CONFIG_ARM64_PAN)				\
 	: "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2)	\
 	: "r" (addr), "i" (-EAGAIN), "i" (-EFAULT),		\
 	  "i" (__SWP_LL_SC_LOOPS)				\
-	: "memory")
+	: "memory");						\
+	uaccess_disable();					\
+} while (0)
 
 #define __user_swp_asm(data, addr, res, temp, temp2) \
 	__user_swpX_asm(data, addr, res, temp, temp2, "")
@@ -352,6 +350,10 @@ static int emulate_swpX(unsigned int add
 	return res;
 }
 
+#define ARM_OPCODE_CONDTEST_FAIL   0
+#define ARM_OPCODE_CONDTEST_PASS   1
+#define ARM_OPCODE_CONDTEST_UNCOND 2
+
 #define	ARM_OPCODE_CONDITION_UNCOND	0xf
 
 static unsigned int __kprobes aarch32_check_condition(u32 opcode, u32 psr)
@@ -638,7 +640,7 @@ static int __init armv8_deprecated_init(
 	}
 
 	cpuhp_setup_state_nocalls(CPUHP_AP_ARM64_ISNDEP_STARTING,
-				  "AP_ARM64_ISNDEP_STARTING",
+				  "arm64/isndep:starting",
 				  run_all_insn_set_hw_mode, NULL);
 	register_insn_emulation_sysctl(ctl_abi);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/asm-offsets.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/asm-offsets.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/asm-offsets.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/asm-offsets.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,11 +36,13 @@ int main(void)
 {
   DEFINE(TSK_ACTIVE_MM,		offsetof(struct task_struct, active_mm));
   BLANK();
-  DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
-  DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
-  DEFINE(TI_ADDR_LIMIT,		offsetof(struct thread_info, addr_limit));
-  DEFINE(TI_TASK,		offsetof(struct thread_info, task));
-  DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+  DEFINE(TSK_TI_FLAGS,		offsetof(struct task_struct, thread_info.flags));
+  DEFINE(TSK_TI_PREEMPT,	offsetof(struct task_struct, thread_info.preempt_count));
+  DEFINE(TSK_TI_ADDR_LIMIT,	offsetof(struct task_struct, thread_info.addr_limit));
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+  DEFINE(TSK_TI_TTBR0,		offsetof(struct task_struct, thread_info.ttbr0));
+#endif
+  DEFINE(TSK_STACK,		offsetof(struct task_struct, stack));
   BLANK();
   DEFINE(THREAD_CPU_CONTEXT,	offsetof(struct task_struct, thread.cpu_context));
   BLANK();
@@ -123,6 +125,7 @@ int main(void)
   DEFINE(TZ_DSTTIME,		offsetof(struct timezone, tz_dsttime));
   BLANK();
   DEFINE(CPU_BOOT_STACK,	offsetof(struct secondary_data, stack));
+  DEFINE(CPU_BOOT_TASK,		offsetof(struct secondary_data, task));
   BLANK();
 #ifdef CONFIG_KVM_ARM_HOST
   DEFINE(VCPU_CONTEXT,		offsetof(struct kvm_vcpu, arch.ctxt));
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/cpufeature.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/cpufeature.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/cpufeature.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/cpufeature.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,7 @@ unsigned int compat_elf_hwcap2 __read_mo
 #endif
 
 DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
+EXPORT_SYMBOL(cpu_hwcaps);
 
 DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, ARM64_NCAPS);
 EXPORT_SYMBOL(cpu_hwcap_keys);
@@ -746,6 +747,14 @@ static bool hyp_offset_low(const struct
 	return idmap_addr > GENMASK(VA_BITS - 2, 0) && !is_kernel_in_hyp_mode();
 }
 
+static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unused)
+{
+	u64 pfr0 = read_system_reg(SYS_ID_AA64PFR0_EL1);
+
+	return cpuid_feature_extract_signed_field(pfr0,
+					ID_AA64PFR0_FP_SHIFT) < 0;
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
@@ -829,6 +838,13 @@ static const struct arm64_cpu_capabiliti
 		.def_scope = SCOPE_SYSTEM,
 		.matches = hyp_offset_low,
 	},
+	{
+		/* FP/SIMD is not implemented */
+		.capability = ARM64_HAS_NO_FPSIMD,
+		.def_scope = SCOPE_SYSTEM,
+		.min_field_value = 0,
+		.matches = has_no_fpsimd,
+	},
 	{},
 };
 
@@ -1102,5 +1118,5 @@ void __init setup_cpu_features(void)
 static bool __maybe_unused
 cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused)
 {
-	return (cpus_have_cap(ARM64_HAS_PAN) && !cpus_have_cap(ARM64_HAS_UAO));
+	return (cpus_have_const_cap(ARM64_HAS_PAN) && !cpus_have_const_cap(ARM64_HAS_UAO));
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/cpuinfo.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/cpuinfo.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/cpuinfo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/cpuinfo.c	2017-02-12 16:03:20.000000000 -0500
@@ -227,7 +227,7 @@ static struct attribute_group cpuregs_at
 	.name = "identification"
 };
 
-static int cpuid_add_regs(int cpu)
+static int cpuid_cpu_online(unsigned int cpu)
 {
 	int rc;
 	struct device *dev;
@@ -248,7 +248,7 @@ out:
 	return rc;
 }
 
-static int cpuid_remove_regs(int cpu)
+static int cpuid_cpu_offline(unsigned int cpu)
 {
 	struct device *dev;
 	struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
@@ -264,40 +264,22 @@ static int cpuid_remove_regs(int cpu)
 	return 0;
 }
 
-static int cpuid_callback(struct notifier_block *nb,
-			 unsigned long action, void *hcpu)
-{
-	int rc = 0;
-	unsigned long cpu = (unsigned long)hcpu;
-
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_ONLINE:
-		rc = cpuid_add_regs(cpu);
-		break;
-	case CPU_DEAD:
-		rc = cpuid_remove_regs(cpu);
-		break;
-	}
-
-	return notifier_from_errno(rc);
-}
-
 static int __init cpuinfo_regs_init(void)
 {
-	int cpu;
-
-	cpu_notifier_register_begin();
+	int cpu, ret;
 
 	for_each_possible_cpu(cpu) {
 		struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
 
 		kobject_init(&info->kobj, &cpuregs_kobj_type);
-		if (cpu_online(cpu))
-			cpuid_add_regs(cpu);
 	}
-	__hotcpu_notifier(cpuid_callback, 0);
 
-	cpu_notifier_register_done();
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/cpuinfo:online",
+				cpuid_cpu_online, cpuid_cpu_offline);
+	if (ret < 0) {
+		pr_err("cpuinfo: failed to register hotplug callbacks.\n");
+		return ret;
+	}
 	return 0;
 }
 static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/debug-monitors.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/debug-monitors.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/debug-monitors.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/debug-monitors.c	2017-02-12 16:03:20.000000000 -0500
@@ -140,7 +140,7 @@ static int clear_os_lock(unsigned int cp
 static int debug_monitors_init(void)
 {
 	return cpuhp_setup_state(CPUHP_AP_ARM64_DEBUG_MONITORS_STARTING,
-				 "CPUHP_AP_ARM64_DEBUG_MONITORS_STARTING",
+				 "arm64/debug_monitors:starting",
 				 clear_os_lock, NULL);
 }
 postcore_initcall(debug_monitors_init);
@@ -226,6 +226,8 @@ static void send_user_sigtrap(int si_cod
 static int single_step_handler(unsigned long addr, unsigned int esr,
 			       struct pt_regs *regs)
 {
+	bool handler_found = false;
+
 	/*
 	 * If we are stepping a pending breakpoint, call the hw_breakpoint
 	 * handler first.
@@ -233,7 +235,14 @@ static int single_step_handler(unsigned
 	if (!reinstall_suspended_bps(regs))
 		return 0;
 
-	if (user_mode(regs)) {
+#ifdef	CONFIG_KPROBES
+	if (kprobe_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
+		handler_found = true;
+#endif
+	if (!handler_found && call_step_hook(regs, esr) == DBG_HOOK_HANDLED)
+		handler_found = true;
+
+	if (!handler_found && user_mode(regs)) {
 		send_user_sigtrap(TRAP_TRACE);
 
 		/*
@@ -243,15 +252,8 @@ static int single_step_handler(unsigned
 		 * to the active-not-pending state).
 		 */
 		user_rewind_single_step(current);
-	} else {
-#ifdef	CONFIG_KPROBES
-		if (kprobe_single_step_handler(regs, esr) == DBG_HOOK_HANDLED)
-			return 0;
-#endif
-		if (call_step_hook(regs, esr) == DBG_HOOK_HANDLED)
-			return 0;
-
-		pr_warning("Unexpected kernel single-step exception at EL1\n");
+	} else if (!handler_found) {
+		pr_warn("Unexpected kernel single-step exception at EL1\n");
 		/*
 		 * Re-enable stepping since we know that we will be
 		 * returning to regs.
@@ -304,16 +306,20 @@ NOKPROBE_SYMBOL(call_break_hook);
 static int brk_handler(unsigned long addr, unsigned int esr,
 		       struct pt_regs *regs)
 {
-	if (user_mode(regs)) {
-		send_user_sigtrap(TRAP_BRKPT);
-	}
+	bool handler_found = false;
+
 #ifdef	CONFIG_KPROBES
-	else if ((esr & BRK64_ESR_MASK) == BRK64_ESR_KPROBES) {
-		if (kprobe_breakpoint_handler(regs, esr) != DBG_HOOK_HANDLED)
-			return -EFAULT;
+	if ((esr & BRK64_ESR_MASK) == BRK64_ESR_KPROBES) {
+		if (kprobe_breakpoint_handler(regs, esr) == DBG_HOOK_HANDLED)
+			handler_found = true;
 	}
 #endif
-	else if (call_break_hook(regs, esr) != DBG_HOOK_HANDLED) {
+	if (!handler_found && call_break_hook(regs, esr) == DBG_HOOK_HANDLED)
+		handler_found = true;
+
+	if (!handler_found && user_mode(regs)) {
+		send_user_sigtrap(TRAP_BRKPT);
+	} else if (!handler_found) {
 		pr_warn("Unexpected kernel BRK exception at EL1\n");
 		return -EFAULT;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/efi.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/efi.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/efi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/efi.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,8 +62,8 @@ struct screen_info screen_info __section
 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
 {
 	pteval_t prot_val = create_mapping_protection(md);
-	bool allow_block_mappings = (md->type != EFI_RUNTIME_SERVICES_CODE &&
-				     md->type != EFI_RUNTIME_SERVICES_DATA);
+	bool page_mappings_only = (md->type == EFI_RUNTIME_SERVICES_CODE ||
+				   md->type == EFI_RUNTIME_SERVICES_DATA);
 
 	if (!PAGE_ALIGNED(md->phys_addr) ||
 	    !PAGE_ALIGNED(md->num_pages << EFI_PAGE_SHIFT)) {
@@ -76,12 +76,12 @@ int __init efi_create_mapping(struct mm_
 		 * from the MMU routines. So avoid block mappings altogether in
 		 * that case.
 		 */
-		allow_block_mappings = false;
+		page_mappings_only = true;
 	}
 
 	create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
 			   md->num_pages << EFI_PAGE_SHIFT,
-			   __pgprot(prot_val | PTE_NG), allow_block_mappings);
+			   __pgprot(prot_val | PTE_NG), page_mappings_only);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/entry.S linux-libre-4.10-rc8-gnu/arch/arm64/kernel/entry.S
--- linux-libre-4.9-gnu/arch/arm64/kernel/entry.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/entry.S	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,9 @@
 #include <asm/esr.h>
 #include <asm/irq.h>
 #include <asm/memory.h>
+#include <asm/ptrace.h>
 #include <asm/thread_info.h>
+#include <asm/asm-uaccess.h>
 #include <asm/unistd.h>
 
 /*
@@ -90,9 +92,8 @@
 
 	.if	\el == 0
 	mrs	x21, sp_el0
-	mov	tsk, sp
-	and	tsk, tsk, #~(THREAD_SIZE - 1)	// Ensure MDSCR_EL1.SS is clear,
-	ldr	x19, [tsk, #TI_FLAGS]		// since we can unmask debug
+	ldr_this_cpu	tsk, __entry_task, x20	// Ensure MDSCR_EL1.SS is clear,
+	ldr	x19, [tsk, #TSK_TI_FLAGS]	// since we can unmask debug
 	disable_step_tsk x19, x20		// exceptions when scheduling.
 
 	mov	x29, xzr			// fp pointed to user-space
@@ -100,15 +101,41 @@
 	add	x21, sp, #S_FRAME_SIZE
 	get_thread_info tsk
 	/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
-	ldr	x20, [tsk, #TI_ADDR_LIMIT]
+	ldr	x20, [tsk, #TSK_TI_ADDR_LIMIT]
 	str	x20, [sp, #S_ORIG_ADDR_LIMIT]
 	mov	x20, #TASK_SIZE_64
-	str	x20, [tsk, #TI_ADDR_LIMIT]
+	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
 	/* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
 	.endif /* \el == 0 */
 	mrs	x22, elr_el1
 	mrs	x23, spsr_el1
 	stp	lr, x21, [sp, #S_LR]
+
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	/*
+	 * Set the TTBR0 PAN bit in SPSR. When the exception is taken from
+	 * EL0, there is no need to check the state of TTBR0_EL1 since
+	 * accesses are always enabled.
+	 * Note that the meaning of this bit differs from the ARMv8.1 PAN
+	 * feature as all TTBR0_EL1 accesses are disabled, not just those to
+	 * user mappings.
+	 */
+alternative_if ARM64_HAS_PAN
+	b	1f				// skip TTBR0 PAN
+alternative_else_nop_endif
+
+	.if	\el != 0
+	mrs	x21, ttbr0_el1
+	tst	x21, #0xffff << 48		// Check for the reserved ASID
+	orr	x23, x23, #PSR_PAN_BIT		// Set the emulated PAN in the saved SPSR
+	b.eq	1f				// TTBR0 access already disabled
+	and	x23, x23, #~PSR_PAN_BIT		// Clear the emulated PAN in the saved SPSR
+	.endif
+
+	__uaccess_ttbr0_disable x21
+1:
+#endif
+
 	stp	x22, x23, [sp, #S_PC]
 
 	/*
@@ -139,7 +166,7 @@
 	.if	\el != 0
 	/* Restore the task's original addr_limit. */
 	ldr	x20, [sp, #S_ORIG_ADDR_LIMIT]
-	str	x20, [tsk, #TI_ADDR_LIMIT]
+	str	x20, [tsk, #TSK_TI_ADDR_LIMIT]
 
 	/* No need to restore UAO, it will be restored from SPSR_EL1 */
 	.endif
@@ -147,6 +174,40 @@
 	ldp	x21, x22, [sp, #S_PC]		// load ELR, SPSR
 	.if	\el == 0
 	ct_user_enter
+	.endif
+
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	/*
+	 * Restore access to TTBR0_EL1. If returning to EL0, no need for SPSR
+	 * PAN bit checking.
+	 */
+alternative_if ARM64_HAS_PAN
+	b	2f				// skip TTBR0 PAN
+alternative_else_nop_endif
+
+	.if	\el != 0
+	tbnz	x22, #22, 1f			// Skip re-enabling TTBR0 access if the PSR_PAN_BIT is set
+	.endif
+
+	__uaccess_ttbr0_enable x0
+
+	.if	\el == 0
+	/*
+	 * Enable errata workarounds only if returning to user. The only
+	 * workaround currently required for TTBR0_EL1 changes are for the
+	 * Cavium erratum 27456 (broadcast TLBI instructions may cause I-cache
+	 * corruption).
+	 */
+	post_ttbr0_update_workaround
+	.endif
+1:
+	.if	\el != 0
+	and	x22, x22, #~PSR_PAN_BIT		// ARMv8.0 CPUs do not understand this bit
+	.endif
+2:
+#endif
+
+	.if	\el == 0
 	ldr	x23, [sp, #S_SP]		// load return stack pointer
 	msr	sp_el0, x23
 #ifdef CONFIG_ARM64_ERRATUM_845719
@@ -162,6 +223,7 @@ alternative_if ARM64_WORKAROUND_845719
 alternative_else_nop_endif
 #endif
 	.endif
+
 	msr	elr_el1, x21			// set up the return data
 	msr	spsr_el1, x22
 	ldp	x0, x1, [sp, #16 * 0]
@@ -184,23 +246,20 @@ alternative_else_nop_endif
 	eret					// return to kernel
 	.endm
 
-	.macro	get_thread_info, rd
-	mrs	\rd, sp_el0
-	.endm
-
 	.macro	irq_stack_entry
 	mov	x19, sp			// preserve the original sp
 
 	/*
-	 * Compare sp with the current thread_info, if the top
-	 * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and
-	 * should switch to the irq stack.
+	 * Compare sp with the base of the task stack.
+	 * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
+	 * and should switch to the irq stack.
 	 */
-	and	x25, x19, #~(THREAD_SIZE - 1)
-	cmp	x25, tsk
-	b.ne	9998f
+	ldr	x25, [tsk, TSK_STACK]
+	eor	x25, x25, x19
+	and	x25, x25, #~(THREAD_SIZE - 1)
+	cbnz	x25, 9998f
 
-	this_cpu_ptr irq_stack, x25, x26
+	adr_this_cpu x25, irq_stack, x26
 	mov	x26, #IRQ_STACK_START_SP
 	add	x26, x25, x26
 
@@ -427,9 +486,9 @@ el1_irq:
 	irq_handler
 
 #ifdef CONFIG_PREEMPT
-	ldr	w24, [tsk, #TI_PREEMPT]		// get preempt count
+	ldr	w24, [tsk, #TSK_TI_PREEMPT]	// get preempt count
 	cbnz	w24, 1f				// preempt count != 0
-	ldr	x0, [tsk, #TI_FLAGS]		// get flags
+	ldr	x0, [tsk, #TSK_TI_FLAGS]	// get flags
 	tbz	x0, #TIF_NEED_RESCHED, 1f	// needs rescheduling?
 	bl	el1_preempt
 1:
@@ -444,7 +503,7 @@ ENDPROC(el1_irq)
 el1_preempt:
 	mov	x24, lr
 1:	bl	preempt_schedule_irq		// irq en/disable is done inside
-	ldr	x0, [tsk, #TI_FLAGS]		// get new tasks TI_FLAGS
+	ldr	x0, [tsk, #TSK_TI_FLAGS]	// get new tasks TI_FLAGS
 	tbnz	x0, #TIF_NEED_RESCHED, 1b	// needs rescheduling?
 	ret	x24
 #endif
@@ -624,7 +683,7 @@ el0_inv:
 	mov	x0, sp
 	mov	x1, #BAD_SYNC
 	mov	x2, x25
-	bl	bad_mode
+	bl	bad_el0_sync
 	b	ret_to_user
 ENDPROC(el0_sync)
 
@@ -674,8 +733,7 @@ ENTRY(cpu_switch_to)
 	ldp	x29, x9, [x8], #16
 	ldr	lr, [x8]
 	mov	sp, x9
-	and	x9, x9, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x9
+	msr	sp_el0, x1
 	ret
 ENDPROC(cpu_switch_to)
 
@@ -686,7 +744,7 @@ ENDPROC(cpu_switch_to)
 ret_fast_syscall:
 	disable_irq				// disable interrupts
 	str	x0, [sp, #S_X0]			// returned x0
-	ldr	x1, [tsk, #TI_FLAGS]		// re-check for syscall tracing
+	ldr	x1, [tsk, #TSK_TI_FLAGS]	// re-check for syscall tracing
 	and	x2, x1, #_TIF_SYSCALL_WORK
 	cbnz	x2, ret_fast_syscall_trace
 	and	x2, x1, #_TIF_WORK_MASK
@@ -706,14 +764,14 @@ work_pending:
 #ifdef CONFIG_TRACE_IRQFLAGS
 	bl	trace_hardirqs_on		// enabled while in userspace
 #endif
-	ldr	x1, [tsk, #TI_FLAGS]		// re-check for single-step
+	ldr	x1, [tsk, #TSK_TI_FLAGS]	// re-check for single-step
 	b	finish_ret_to_user
 /*
  * "slow" syscall return path.
  */
 ret_to_user:
 	disable_irq				// disable interrupts
-	ldr	x1, [tsk, #TI_FLAGS]
+	ldr	x1, [tsk, #TSK_TI_FLAGS]
 	and	x2, x1, #_TIF_WORK_MASK
 	cbnz	x2, work_pending
 finish_ret_to_user:
@@ -746,7 +804,7 @@ el0_svc_naked:					// compat entry point
 	enable_dbg_and_irq
 	ct_user_exit 1
 
-	ldr	x16, [tsk, #TI_FLAGS]		// check for syscall hooks
+	ldr	x16, [tsk, #TSK_TI_FLAGS]	// check for syscall hooks
 	tst	x16, #_TIF_SYSCALL_WORK
 	b.ne	__sys_trace
 	cmp     scno, sc_nr                     // check upper syscall limit
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/fpsimd.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/fpsimd.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/fpsimd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/fpsimd.c	2017-02-12 16:03:20.000000000 -0500
@@ -127,6 +127,8 @@ void do_fpsimd_exc(unsigned int esr, str
 
 void fpsimd_thread_switch(struct task_struct *next)
 {
+	if (!system_supports_fpsimd())
+		return;
 	/*
 	 * Save the current FPSIMD state to memory, but only if whatever is in
 	 * the registers is in fact the most recent userland FPSIMD state of
@@ -157,6 +159,8 @@ void fpsimd_thread_switch(struct task_st
 
 void fpsimd_flush_thread(void)
 {
+	if (!system_supports_fpsimd())
+		return;
 	memset(&current->thread.fpsimd_state, 0, sizeof(struct fpsimd_state));
 	fpsimd_flush_task_state(current);
 	set_thread_flag(TIF_FOREIGN_FPSTATE);
@@ -168,6 +172,8 @@ void fpsimd_flush_thread(void)
  */
 void fpsimd_preserve_current_state(void)
 {
+	if (!system_supports_fpsimd())
+		return;
 	preempt_disable();
 	if (!test_thread_flag(TIF_FOREIGN_FPSTATE))
 		fpsimd_save_state(&current->thread.fpsimd_state);
@@ -181,6 +187,8 @@ void fpsimd_preserve_current_state(void)
  */
 void fpsimd_restore_current_state(void)
 {
+	if (!system_supports_fpsimd())
+		return;
 	preempt_disable();
 	if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) {
 		struct fpsimd_state *st = &current->thread.fpsimd_state;
@@ -199,6 +207,8 @@ void fpsimd_restore_current_state(void)
  */
 void fpsimd_update_current_state(struct fpsimd_state *state)
 {
+	if (!system_supports_fpsimd())
+		return;
 	preempt_disable();
 	fpsimd_load_state(state);
 	if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) {
@@ -228,6 +238,8 @@ static DEFINE_PER_CPU(struct fpsimd_part
  */
 void kernel_neon_begin_partial(u32 num_regs)
 {
+	if (WARN_ON(!system_supports_fpsimd()))
+		return;
 	if (in_interrupt()) {
 		struct fpsimd_partial_state *s = this_cpu_ptr(
 			in_irq() ? &hardirq_fpsimdstate : &softirq_fpsimdstate);
@@ -252,6 +264,8 @@ EXPORT_SYMBOL(kernel_neon_begin_partial)
 
 void kernel_neon_end(void)
 {
+	if (!system_supports_fpsimd())
+		return;
 	if (in_interrupt()) {
 		struct fpsimd_partial_state *s = this_cpu_ptr(
 			in_irq() ? &hardirq_fpsimdstate : &softirq_fpsimdstate);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/head.S linux-libre-4.10-rc8-gnu/arch/arm64/kernel/head.S
--- linux-libre-4.9-gnu/arch/arm64/kernel/head.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/head.S	2017-02-12 16:03:20.000000000 -0500
@@ -326,14 +326,14 @@ __create_page_tables:
 	 * dirty cache lines being evicted.
 	 */
 	adrp	x0, idmap_pg_dir
-	adrp	x1, swapper_pg_dir + SWAPPER_DIR_SIZE
+	adrp	x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
 	bl	__inval_cache_range
 
 	/*
 	 * Clear the idmap and swapper page tables.
 	 */
 	adrp	x0, idmap_pg_dir
-	adrp	x6, swapper_pg_dir + SWAPPER_DIR_SIZE
+	adrp	x6, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
 1:	stp	xzr, xzr, [x0], #16
 	stp	xzr, xzr, [x0], #16
 	stp	xzr, xzr, [x0], #16
@@ -412,7 +412,7 @@ __create_page_tables:
 	 * tables again to remove any speculatively loaded cache lines.
 	 */
 	adrp	x0, idmap_pg_dir
-	adrp	x1, swapper_pg_dir + SWAPPER_DIR_SIZE
+	adrp	x1, swapper_pg_dir + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE
 	dmb	sy
 	bl	__inval_cache_range
 
@@ -428,7 +428,8 @@ ENDPROC(__create_page_tables)
 __primary_switched:
 	adrp	x4, init_thread_union
 	add	sp, x4, #THREAD_SIZE
-	msr	sp_el0, x4			// Save thread_info
+	adr_l	x5, init_task
+	msr	sp_el0, x5			// Save thread_info
 
 	adr_l	x8, vectors			// load VBAR_EL1 with virtual
 	msr	vbar_el1, x8			// vector table address
@@ -524,10 +525,21 @@ set_hcr:
 	msr	hcr_el2, x0
 	isb
 
-	/* Generic timers. */
+	/*
+	 * Allow Non-secure EL1 and EL0 to access physical timer and counter.
+	 * This is not necessary for VHE, since the host kernel runs in EL2,
+	 * and EL0 accesses are configured in the later stage of boot process.
+	 * Note that when HCR_EL2.E2H == 1, CNTHCTL_EL2 has the same bit layout
+	 * as CNTKCTL_EL1, and CNTKCTL_EL1 accessing instructions are redefined
+	 * to access CNTHCTL_EL2. This allows the kernel designed to run at EL1
+	 * to transparently mess with the EL0 bits via CNTKCTL_EL1 access in
+	 * EL2.
+	 */
+	cbnz	x2, 1f
 	mrs	x0, cnthctl_el2
 	orr	x0, x0, #3			// Enable EL1 physical timers
 	msr	cnthctl_el2, x0
+1:
 	msr	cntvoff_el2, xzr		// Clear virtual offset
 
 #ifdef CONFIG_ARM_GIC_V3
@@ -699,10 +711,10 @@ __secondary_switched:
 	isb
 
 	adr_l	x0, secondary_data
-	ldr	x0, [x0, #CPU_BOOT_STACK]	// get secondary_data.stack
-	mov	sp, x0
-	and	x0, x0, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x0			// save thread_info
+	ldr	x1, [x0, #CPU_BOOT_STACK]	// get secondary_data.stack
+	mov	sp, x1
+	ldr	x2, [x0, #CPU_BOOT_TASK]
+	msr	sp_el0, x2
 	mov	x29, #0
 	b	secondary_start_kernel
 ENDPROC(__secondary_switched)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/hibernate.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/hibernate.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/hibernate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/hibernate.c	2017-02-12 16:03:20.000000000 -0500
@@ -136,7 +136,7 @@ int arch_hibernation_header_save(void *a
 
 	/* Save the mpidr of the cpu we called cpu_suspend() on... */
 	if (sleep_cpu < 0) {
-		pr_err("Failing to hibernate on an unkown CPU.\n");
+		pr_err("Failing to hibernate on an unknown CPU.\n");
 		return -ENODEV;
 	}
 	hdr->sleep_cpu_mpidr = cpu_logical_map(sleep_cpu);
@@ -547,7 +547,7 @@ out:
 int hibernate_resume_nonboot_cpu_disable(void)
 {
 	if (sleep_cpu < 0) {
-		pr_err("Failing to resume from hibernate on an unkown CPU.\n");
+		pr_err("Failing to resume from hibernate on an unknown CPU.\n");
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/hw_breakpoint.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/hw_breakpoint.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/hw_breakpoint.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/hw_breakpoint.c	2017-02-12 16:03:20.000000000 -0500
@@ -317,9 +317,21 @@ static int get_hbp_len(u8 hbp_len)
 	case ARM_BREAKPOINT_LEN_2:
 		len_in_bytes = 2;
 		break;
+	case ARM_BREAKPOINT_LEN_3:
+		len_in_bytes = 3;
+		break;
 	case ARM_BREAKPOINT_LEN_4:
 		len_in_bytes = 4;
 		break;
+	case ARM_BREAKPOINT_LEN_5:
+		len_in_bytes = 5;
+		break;
+	case ARM_BREAKPOINT_LEN_6:
+		len_in_bytes = 6;
+		break;
+	case ARM_BREAKPOINT_LEN_7:
+		len_in_bytes = 7;
+		break;
 	case ARM_BREAKPOINT_LEN_8:
 		len_in_bytes = 8;
 		break;
@@ -349,7 +361,7 @@ int arch_check_bp_in_kernelspace(struct
  * to generic breakpoint descriptions.
  */
 int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
-			   int *gen_len, int *gen_type)
+			   int *gen_len, int *gen_type, int *offset)
 {
 	/* Type */
 	switch (ctrl.type) {
@@ -369,17 +381,33 @@ int arch_bp_generic_fields(struct arch_h
 		return -EINVAL;
 	}
 
+	if (!ctrl.len)
+		return -EINVAL;
+	*offset = __ffs(ctrl.len);
+
 	/* Len */
-	switch (ctrl.len) {
+	switch (ctrl.len >> *offset) {
 	case ARM_BREAKPOINT_LEN_1:
 		*gen_len = HW_BREAKPOINT_LEN_1;
 		break;
 	case ARM_BREAKPOINT_LEN_2:
 		*gen_len = HW_BREAKPOINT_LEN_2;
 		break;
+	case ARM_BREAKPOINT_LEN_3:
+		*gen_len = HW_BREAKPOINT_LEN_3;
+		break;
 	case ARM_BREAKPOINT_LEN_4:
 		*gen_len = HW_BREAKPOINT_LEN_4;
 		break;
+	case ARM_BREAKPOINT_LEN_5:
+		*gen_len = HW_BREAKPOINT_LEN_5;
+		break;
+	case ARM_BREAKPOINT_LEN_6:
+		*gen_len = HW_BREAKPOINT_LEN_6;
+		break;
+	case ARM_BREAKPOINT_LEN_7:
+		*gen_len = HW_BREAKPOINT_LEN_7;
+		break;
 	case ARM_BREAKPOINT_LEN_8:
 		*gen_len = HW_BREAKPOINT_LEN_8;
 		break;
@@ -423,9 +451,21 @@ static int arch_build_bp_info(struct per
 	case HW_BREAKPOINT_LEN_2:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_2;
 		break;
+	case HW_BREAKPOINT_LEN_3:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_3;
+		break;
 	case HW_BREAKPOINT_LEN_4:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_4;
 		break;
+	case HW_BREAKPOINT_LEN_5:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_5;
+		break;
+	case HW_BREAKPOINT_LEN_6:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_6;
+		break;
+	case HW_BREAKPOINT_LEN_7:
+		info->ctrl.len = ARM_BREAKPOINT_LEN_7;
+		break;
 	case HW_BREAKPOINT_LEN_8:
 		info->ctrl.len = ARM_BREAKPOINT_LEN_8;
 		break;
@@ -517,18 +557,17 @@ int arch_validate_hwbkpt_settings(struct
 		default:
 			return -EINVAL;
 		}
-
-		info->address &= ~alignment_mask;
-		info->ctrl.len <<= offset;
 	} else {
 		if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE)
 			alignment_mask = 0x3;
 		else
 			alignment_mask = 0x7;
-		if (info->address & alignment_mask)
-			return -EINVAL;
+		offset = info->address & alignment_mask;
 	}
 
+	info->address &= ~alignment_mask;
+	info->ctrl.len <<= offset;
+
 	/*
 	 * Disallow per-task kernel breakpoints since these would
 	 * complicate the stepping code.
@@ -661,12 +700,47 @@ unlock:
 }
 NOKPROBE_SYMBOL(breakpoint_handler);
 
+/*
+ * Arm64 hardware does not always report a watchpoint hit address that matches
+ * one of the watchpoints set. It can also report an address "near" the
+ * watchpoint if a single instruction access both watched and unwatched
+ * addresses. There is no straight-forward way, short of disassembling the
+ * offending instruction, to map that address back to the watchpoint. This
+ * function computes the distance of the memory access from the watchpoint as a
+ * heuristic for the likelyhood that a given access triggered the watchpoint.
+ *
+ * See Section D2.10.5 "Determining the memory location that caused a Watchpoint
+ * exception" of ARMv8 Architecture Reference Manual for details.
+ *
+ * The function returns the distance of the address from the bytes watched by
+ * the watchpoint. In case of an exact match, it returns 0.
+ */
+static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
+					struct arch_hw_breakpoint_ctrl *ctrl)
+{
+	u64 wp_low, wp_high;
+	u32 lens, lene;
+
+	lens = __ffs(ctrl->len);
+	lene = __fls(ctrl->len);
+
+	wp_low = val + lens;
+	wp_high = val + lene;
+	if (addr < wp_low)
+		return wp_low - addr;
+	else if (addr > wp_high)
+		return addr - wp_high;
+	else
+		return 0;
+}
+
 static int watchpoint_handler(unsigned long addr, unsigned int esr,
 			      struct pt_regs *regs)
 {
-	int i, step = 0, *kernel_step, access;
+	int i, step = 0, *kernel_step, access, closest_match = 0;
+	u64 min_dist = -1, dist;
 	u32 ctrl_reg;
-	u64 val, alignment_mask;
+	u64 val;
 	struct perf_event *wp, **slots;
 	struct debug_info *debug_info;
 	struct arch_hw_breakpoint *info;
@@ -675,35 +749,15 @@ static int watchpoint_handler(unsigned l
 	slots = this_cpu_ptr(wp_on_reg);
 	debug_info = &current->thread.debug;
 
+	/*
+	 * Find all watchpoints that match the reported address. If no exact
+	 * match is found. Attribute the hit to the closest watchpoint.
+	 */
+	rcu_read_lock();
 	for (i = 0; i < core_num_wrps; ++i) {
-		rcu_read_lock();
-
 		wp = slots[i];
-
 		if (wp == NULL)
-			goto unlock;
-
-		info = counter_arch_bp(wp);
-		/* AArch32 watchpoints are either 4 or 8 bytes aligned. */
-		if (is_compat_task()) {
-			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
-				alignment_mask = 0x7;
-			else
-				alignment_mask = 0x3;
-		} else {
-			alignment_mask = 0x7;
-		}
-
-		/* Check if the watchpoint value matches. */
-		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
-		if (val != (addr & ~alignment_mask))
-			goto unlock;
-
-		/* Possible match, check the byte address select to confirm. */
-		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
-		decode_ctrl_reg(ctrl_reg, &ctrl);
-		if (!((1 << (addr & alignment_mask)) & ctrl.len))
-			goto unlock;
+			continue;
 
 		/*
 		 * Check that the access type matches.
@@ -712,18 +766,41 @@ static int watchpoint_handler(unsigned l
 		access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W :
 			 HW_BREAKPOINT_R;
 		if (!(access & hw_breakpoint_type(wp)))
-			goto unlock;
+			continue;
+
+		/* Check if the watchpoint value and byte select match. */
+		val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
+		ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
+		decode_ctrl_reg(ctrl_reg, &ctrl);
+		dist = get_distance_from_watchpoint(addr, val, &ctrl);
+		if (dist < min_dist) {
+			min_dist = dist;
+			closest_match = i;
+		}
+		/* Is this an exact match? */
+		if (dist != 0)
+			continue;
 
+		info = counter_arch_bp(wp);
 		info->trigger = addr;
 		perf_bp_event(wp, regs);
 
 		/* Do we need to handle the stepping? */
 		if (is_default_overflow_handler(wp))
 			step = 1;
+	}
+	if (min_dist > 0 && min_dist != -1) {
+		/* No exact match found. */
+		wp = slots[closest_match];
+		info = counter_arch_bp(wp);
+		info->trigger = addr;
+		perf_bp_event(wp, regs);
 
-unlock:
-		rcu_read_unlock();
+		/* Do we need to handle the stepping? */
+		if (is_default_overflow_handler(wp))
+			step = 1;
 	}
+	rcu_read_unlock();
 
 	if (!step)
 		return 0;
@@ -924,7 +1001,7 @@ static int __init arch_hw_breakpoint_ini
 	 * debugger will leave the world in a nice state for us.
 	 */
 	ret = cpuhp_setup_state(CPUHP_AP_PERF_ARM_HW_BREAKPOINT_STARTING,
-			  "CPUHP_AP_PERF_ARM_HW_BREAKPOINT_STARTING",
+			  "perf/arm64/hw_breakpoint:starting",
 			  hw_breakpoint_reset, NULL);
 	if (ret)
 		pr_err("failed to register CPU hotplug notifier: %d\n", ret);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/insn.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/insn.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/insn.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/insn.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,6 @@
 #include <asm/cacheflush.h>
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
-#include <asm/opcodes.h>
 #include <asm/insn.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/kgdb.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/kgdb.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/kgdb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/kgdb.c	2017-02-12 16:03:20.000000000 -0500
@@ -247,6 +247,9 @@ NOKPROBE_SYMBOL(kgdb_compiled_brk_fn);
 
 static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
 {
+	if (!kgdb_single_step)
+		return DBG_HOOK_ERROR;
+
 	kgdb_handle_exception(1, SIGTRAP, 0, regs);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/pci.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/pci.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,6 +114,19 @@ int pcibios_root_bridge_prepare(struct p
 	return 0;
 }
 
+static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
+{
+	struct resource_entry *entry, *tmp;
+	int status;
+
+	status = acpi_pci_probe_root_resources(ci);
+	resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
+		if (!(entry->res->flags & IORESOURCE_WINDOW))
+			resource_list_destroy_entry(entry);
+	}
+	return status;
+}
+
 /*
  * Lookup the bus range for the domain in MCFG, and set up config space
  * mapping.
@@ -121,31 +134,33 @@ int pcibios_root_bridge_prepare(struct p
 static struct pci_config_window *
 pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
 {
+	struct device *dev = &root->device->dev;
 	struct resource *bus_res = &root->secondary;
 	u16 seg = root->segment;
-	struct pci_config_window *cfg;
+	struct pci_ecam_ops *ecam_ops;
 	struct resource cfgres;
-	unsigned int bsz;
-
-	/* Use address from _CBA if present, otherwise lookup MCFG */
-	if (!root->mcfg_addr)
-		root->mcfg_addr = pci_mcfg_lookup(seg, bus_res);
+	struct acpi_device *adev;
+	struct pci_config_window *cfg;
+	int ret;
 
-	if (!root->mcfg_addr) {
-		dev_err(&root->device->dev, "%04x:%pR ECAM region not found\n",
-			seg, bus_res);
+	ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops);
+	if (ret) {
+		dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res);
 		return NULL;
 	}
 
-	bsz = 1 << pci_generic_ecam_ops.bus_shift;
-	cfgres.start = root->mcfg_addr + bus_res->start * bsz;
-	cfgres.end = cfgres.start + resource_size(bus_res) * bsz - 1;
-	cfgres.flags = IORESOURCE_MEM;
-	cfg = pci_ecam_create(&root->device->dev, &cfgres, bus_res,
-			      &pci_generic_ecam_ops);
+	adev = acpi_resource_consumer(&cfgres);
+	if (adev)
+		dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres,
+			 dev_name(&adev->dev));
+	else
+		dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n",
+			 &cfgres);
+
+	cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops);
 	if (IS_ERR(cfg)) {
-		dev_err(&root->device->dev, "%04x:%pR error %ld mapping ECAM\n",
-			seg, bus_res, PTR_ERR(cfg));
+		dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res,
+			PTR_ERR(cfg));
 		return NULL;
 	}
 
@@ -159,33 +174,37 @@ static void pci_acpi_generic_release_inf
 
 	ri = container_of(ci, struct acpi_pci_generic_root_info, common);
 	pci_ecam_free(ri->cfg);
+	kfree(ci->ops);
 	kfree(ri);
 }
 
-static struct acpi_pci_root_ops acpi_pci_root_ops = {
-	.release_info = pci_acpi_generic_release_info,
-};
-
 /* Interface called from ACPI code to setup PCI host controller */
 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
 {
 	int node = acpi_get_node(root->device->handle);
 	struct acpi_pci_generic_root_info *ri;
 	struct pci_bus *bus, *child;
+	struct acpi_pci_root_ops *root_ops;
 
 	ri = kzalloc_node(sizeof(*ri), GFP_KERNEL, node);
 	if (!ri)
 		return NULL;
 
+	root_ops = kzalloc_node(sizeof(*root_ops), GFP_KERNEL, node);
+	if (!root_ops)
+		return NULL;
+
 	ri->cfg = pci_acpi_setup_ecam_mapping(root);
 	if (!ri->cfg) {
 		kfree(ri);
+		kfree(root_ops);
 		return NULL;
 	}
 
-	acpi_pci_root_ops.pci_ops = &ri->cfg->ops->pci_ops;
-	bus = acpi_pci_root_create(root, &acpi_pci_root_ops, &ri->common,
-				   ri->cfg);
+	root_ops->release_info = pci_acpi_generic_release_info;
+	root_ops->prepare_resources = pci_acpi_root_prepare_resources;
+	root_ops->pci_ops = &ri->cfg->ops->pci_ops;
+	bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg);
 	if (!bus)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/probes/decode-insn.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/decode-insn.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/probes/decode-insn.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/decode-insn.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,6 @@
 #include <linux/kprobes.h>
 #include <linux/module.h>
 #include <linux/kallsyms.h>
-#include <asm/kprobes.h>
 #include <asm/insn.h>
 #include <asm/sections.h>
 
@@ -78,8 +77,8 @@ static bool __kprobes aarch64_insn_is_st
  *   INSN_GOOD         If instruction is supported and uses instruction slot,
  *   INSN_GOOD_NO_SLOT If instruction is supported but doesn't use its slot.
  */
-static enum kprobe_insn __kprobes
-arm_probe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+enum probe_insn __kprobes
+arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *api)
 {
 	/*
 	 * Instructions reading or modifying the PC won't work from the XOL
@@ -89,26 +88,26 @@ arm_probe_decode_insn(kprobe_opcode_t in
 		return INSN_GOOD;
 
 	if (aarch64_insn_is_bcond(insn)) {
-		asi->handler = simulate_b_cond;
+		api->handler = simulate_b_cond;
 	} else if (aarch64_insn_is_cbz(insn) ||
 	    aarch64_insn_is_cbnz(insn)) {
-		asi->handler = simulate_cbz_cbnz;
+		api->handler = simulate_cbz_cbnz;
 	} else if (aarch64_insn_is_tbz(insn) ||
 	    aarch64_insn_is_tbnz(insn)) {
-		asi->handler = simulate_tbz_tbnz;
+		api->handler = simulate_tbz_tbnz;
 	} else if (aarch64_insn_is_adr_adrp(insn)) {
-		asi->handler = simulate_adr_adrp;
+		api->handler = simulate_adr_adrp;
 	} else if (aarch64_insn_is_b(insn) ||
 	    aarch64_insn_is_bl(insn)) {
-		asi->handler = simulate_b_bl;
+		api->handler = simulate_b_bl;
 	} else if (aarch64_insn_is_br(insn) ||
 	    aarch64_insn_is_blr(insn) ||
 	    aarch64_insn_is_ret(insn)) {
-		asi->handler = simulate_br_blr_ret;
+		api->handler = simulate_br_blr_ret;
 	} else if (aarch64_insn_is_ldr_lit(insn)) {
-		asi->handler = simulate_ldr_literal;
+		api->handler = simulate_ldr_literal;
 	} else if (aarch64_insn_is_ldrsw_lit(insn)) {
-		asi->handler = simulate_ldrsw_literal;
+		api->handler = simulate_ldrsw_literal;
 	} else {
 		/*
 		 * Instruction cannot be stepped out-of-line and we don't
@@ -120,6 +119,7 @@ arm_probe_decode_insn(kprobe_opcode_t in
 	return INSN_GOOD_NO_SLOT;
 }
 
+#ifdef CONFIG_KPROBES
 static bool __kprobes
 is_probed_address_atomic(kprobe_opcode_t *scan_start, kprobe_opcode_t *scan_end)
 {
@@ -138,12 +138,12 @@ is_probed_address_atomic(kprobe_opcode_t
 	return false;
 }
 
-enum kprobe_insn __kprobes
+enum probe_insn __kprobes
 arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi)
 {
-	enum kprobe_insn decoded;
-	kprobe_opcode_t insn = le32_to_cpu(*addr);
-	kprobe_opcode_t *scan_end = NULL;
+	enum probe_insn decoded;
+	probe_opcode_t insn = le32_to_cpu(*addr);
+	probe_opcode_t *scan_end = NULL;
 	unsigned long size = 0, offset = 0;
 
 	/*
@@ -162,7 +162,7 @@ arm_kprobe_decode_insn(kprobe_opcode_t *
 		else
 			scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE;
 	}
-	decoded = arm_probe_decode_insn(insn, asi);
+	decoded = arm_probe_decode_insn(insn, &asi->api);
 
 	if (decoded != INSN_REJECTED && scan_end)
 		if (is_probed_address_atomic(addr - 1, scan_end))
@@ -170,3 +170,4 @@ arm_kprobe_decode_insn(kprobe_opcode_t *
 
 	return decoded;
 }
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/probes/decode-insn.h linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/decode-insn.h
--- linux-libre-4.9-gnu/arch/arm64/kernel/probes/decode-insn.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/decode-insn.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,13 +23,17 @@
  */
 #define MAX_ATOMIC_CONTEXT_SIZE	(128 / sizeof(kprobe_opcode_t))
 
-enum kprobe_insn {
+enum probe_insn {
 	INSN_REJECTED,
 	INSN_GOOD_NO_SLOT,
 	INSN_GOOD,
 };
 
-enum kprobe_insn __kprobes
+#ifdef CONFIG_KPROBES
+enum probe_insn __kprobes
 arm_kprobe_decode_insn(kprobe_opcode_t *addr, struct arch_specific_insn *asi);
+#endif
+enum probe_insn __kprobes
+arm_probe_decode_insn(probe_opcode_t insn, struct arch_probe_insn *asi);
 
 #endif /* _ARM_KERNEL_KPROBES_ARM64_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/probes/kprobes.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/kprobes.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/probes/kprobes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/kprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/system_misc.h>
 #include <asm/insn.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 #include <asm/sections.h>
 
@@ -44,31 +44,31 @@ post_kprobe_handler(struct kprobe_ctlblk
 static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
 {
 	/* prepare insn slot */
-	p->ainsn.insn[0] = cpu_to_le32(p->opcode);
+	p->ainsn.api.insn[0] = cpu_to_le32(p->opcode);
 
-	flush_icache_range((uintptr_t) (p->ainsn.insn),
-			   (uintptr_t) (p->ainsn.insn) +
+	flush_icache_range((uintptr_t) (p->ainsn.api.insn),
+			   (uintptr_t) (p->ainsn.api.insn) +
 			   MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 
 	/*
 	 * Needs restoring of return address after stepping xol.
 	 */
-	p->ainsn.restore = (unsigned long) p->addr +
+	p->ainsn.api.restore = (unsigned long) p->addr +
 	  sizeof(kprobe_opcode_t);
 }
 
 static void __kprobes arch_prepare_simulate(struct kprobe *p)
 {
 	/* This instructions is not executed xol. No need to adjust the PC */
-	p->ainsn.restore = 0;
+	p->ainsn.api.restore = 0;
 }
 
 static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	if (p->ainsn.handler)
-		p->ainsn.handler((u32)p->opcode, (long)p->addr, regs);
+	if (p->ainsn.api.handler)
+		p->ainsn.api.handler((u32)p->opcode, (long)p->addr, regs);
 
 	/* single step simulated, now go for post processing */
 	post_kprobe_handler(kcb, regs);
@@ -98,18 +98,18 @@ int __kprobes arch_prepare_kprobe(struct
 		return -EINVAL;
 
 	case INSN_GOOD_NO_SLOT:	/* insn need simulation */
-		p->ainsn.insn = NULL;
+		p->ainsn.api.insn = NULL;
 		break;
 
 	case INSN_GOOD:	/* instruction uses slot */
-		p->ainsn.insn = get_insn_slot();
-		if (!p->ainsn.insn)
+		p->ainsn.api.insn = get_insn_slot();
+		if (!p->ainsn.api.insn)
 			return -ENOMEM;
 		break;
 	};
 
 	/* prepare the instruction */
-	if (p->ainsn.insn)
+	if (p->ainsn.api.insn)
 		arch_prepare_ss_slot(p);
 	else
 		arch_prepare_simulate(p);
@@ -142,9 +142,9 @@ void __kprobes arch_disarm_kprobe(struct
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-	if (p->ainsn.insn) {
-		free_insn_slot(p->ainsn.insn, 0);
-		p->ainsn.insn = NULL;
+	if (p->ainsn.api.insn) {
+		free_insn_slot(p->ainsn.api.insn, 0);
+		p->ainsn.api.insn = NULL;
 	}
 }
 
@@ -244,9 +244,9 @@ static void __kprobes setup_singlestep(s
 	}
 
 
-	if (p->ainsn.insn) {
+	if (p->ainsn.api.insn) {
 		/* prepare for single stepping */
-		slot = (unsigned long)p->ainsn.insn;
+		slot = (unsigned long)p->ainsn.api.insn;
 
 		set_ss_context(kcb, slot);	/* mark pending ss */
 
@@ -295,8 +295,8 @@ post_kprobe_handler(struct kprobe_ctlblk
 		return;
 
 	/* return addr restore if non-branching insn */
-	if (cur->ainsn.restore != 0)
-		instruction_pointer_set(regs, cur->ainsn.restore);
+	if (cur->ainsn.api.restore != 0)
+		instruction_pointer_set(regs, cur->ainsn.api.restore);
 
 	/* restore back original saved kprobe variables and continue */
 	if (kcb->kprobe_status == KPROBE_REENTER) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/probes/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/Makefile
--- linux-libre-4.9-gnu/arch/arm64/kernel/probes/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,5 @@
 obj-$(CONFIG_KPROBES)		+= kprobes.o decode-insn.o	\
 				   kprobes_trampoline.o		\
 				   simulate-insn.o
+obj-$(CONFIG_UPROBES)		+= uprobes.o decode-insn.o	\
+				   simulate-insn.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/probes/simulate-insn.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/simulate-insn.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/probes/simulate-insn.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/simulate-insn.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,28 +13,26 @@
  * General Public License for more details.
  */
 
+#include <linux/bitops.h>
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
 
 #include "simulate-insn.h"
 
-#define sign_extend(x, signbit)		\
-	((x) | (0 - ((x) & (1 << (signbit)))))
-
 #define bbl_displacement(insn)		\
-	sign_extend(((insn) & 0x3ffffff) << 2, 27)
+	sign_extend32(((insn) & 0x3ffffff) << 2, 27)
 
 #define bcond_displacement(insn)	\
-	sign_extend(((insn >> 5) & 0x7ffff) << 2, 20)
+	sign_extend32(((insn >> 5) & 0x7ffff) << 2, 20)
 
 #define cbz_displacement(insn)	\
-	sign_extend(((insn >> 5) & 0x7ffff) << 2, 20)
+	sign_extend32(((insn >> 5) & 0x7ffff) << 2, 20)
 
 #define tbz_displacement(insn)	\
-	sign_extend(((insn >> 5) & 0x3fff) << 2, 15)
+	sign_extend32(((insn >> 5) & 0x3fff) << 2, 15)
 
 #define ldr_displacement(insn)	\
-	sign_extend(((insn >> 5) & 0x7ffff) << 2, 20)
+	sign_extend32(((insn >> 5) & 0x7ffff) << 2, 20)
 
 static inline void set_x_reg(struct pt_regs *regs, int reg, u64 val)
 {
@@ -106,7 +104,7 @@ simulate_adr_adrp(u32 opcode, long addr,
 
 	xn = opcode & 0x1f;
 	imm = ((opcode >> 3) & 0x1ffffc) | ((opcode >> 29) & 0x3);
-	imm = sign_extend(imm, 20);
+	imm = sign_extend64(imm, 20);
 	if (opcode & 0x80000000)
 		val = (imm<<12) + (addr & 0xfffffffffffff000);
 	else
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/probes/uprobes.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/uprobes.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/probes/uprobes.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/probes/uprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2014-2016 Pratyush Anand <panand@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/highmem.h>
+#include <linux/ptrace.h>
+#include <linux/uprobes.h>
+#include <asm/cacheflush.h>
+
+#include "decode-insn.h"
+
+#define UPROBE_INV_FAULT_CODE	UINT_MAX
+
+void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
+		void *src, unsigned long len)
+{
+	void *xol_page_kaddr = kmap_atomic(page);
+	void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK);
+
+	/* Initialize the slot */
+	memcpy(dst, src, len);
+
+	/* flush caches (dcache/icache) */
+	sync_icache_aliases(dst, len);
+
+	kunmap_atomic(xol_page_kaddr);
+}
+
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+	return instruction_pointer(regs);
+}
+
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
+		unsigned long addr)
+{
+	probe_opcode_t insn;
+
+	/* TODO: Currently we do not support AARCH32 instruction probing */
+	if (test_bit(TIF_32BIT, &mm->context.flags))
+		return -ENOTSUPP;
+	else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE))
+		return -EINVAL;
+
+	insn = *(probe_opcode_t *)(&auprobe->insn[0]);
+
+	switch (arm_probe_decode_insn(insn, &auprobe->api)) {
+	case INSN_REJECTED:
+		return -EINVAL;
+
+	case INSN_GOOD_NO_SLOT:
+		auprobe->simulate = true;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+
+	/* Initialize with an invalid fault code to detect if ol insn trapped */
+	current->thread.fault_code = UPROBE_INV_FAULT_CODE;
+
+	/* Instruction points to execute ol */
+	instruction_pointer_set(regs, utask->xol_vaddr);
+
+	user_enable_single_step(current);
+
+	return 0;
+}
+
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+
+	WARN_ON_ONCE(current->thread.fault_code != UPROBE_INV_FAULT_CODE);
+
+	/* Instruction points to execute next to breakpoint address */
+	instruction_pointer_set(regs, utask->vaddr + 4);
+
+	user_disable_single_step(current);
+
+	return 0;
+}
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+	/*
+	 * Between arch_uprobe_pre_xol and arch_uprobe_post_xol, if an xol
+	 * insn itself is trapped, then detect the case with the help of
+	 * invalid fault code which is being set in arch_uprobe_pre_xol
+	 */
+	if (t->thread.fault_code != UPROBE_INV_FAULT_CODE)
+		return true;
+
+	return false;
+}
+
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	probe_opcode_t insn;
+	unsigned long addr;
+
+	if (!auprobe->simulate)
+		return false;
+
+	insn = *(probe_opcode_t *)(&auprobe->insn[0]);
+	addr = instruction_pointer(regs);
+
+	if (auprobe->api.handler)
+		auprobe->api.handler(insn, addr, regs);
+
+	return true;
+}
+
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+
+	/*
+	 * Task has received a fatal signal, so reset back to probbed
+	 * address.
+	 */
+	instruction_pointer_set(regs, utask->vaddr);
+
+	user_disable_single_step(current);
+}
+
+bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
+		struct pt_regs *regs)
+{
+	/*
+	 * If a simple branch instruction (B) was called for retprobed
+	 * assembly label then return true even when regs->sp and ret->stack
+	 * are same. It will ensure that cleanup and reporting of return
+	 * instances corresponding to callee label is done when
+	 * handle_trampoline for called function is executed.
+	 */
+	if (ctx == RP_CHECK_CHAIN_CALL)
+		return regs->sp <= ret->stack;
+	else
+		return regs->sp < ret->stack;
+}
+
+unsigned long
+arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
+				  struct pt_regs *regs)
+{
+	unsigned long orig_ret_vaddr;
+
+	orig_ret_vaddr = procedure_link_pointer(regs);
+	/* Replace the return addr with trampoline addr */
+	procedure_link_pointer_set(regs, trampoline_vaddr);
+
+	return orig_ret_vaddr;
+}
+
+int arch_uprobe_exception_notify(struct notifier_block *self,
+				 unsigned long val, void *data)
+{
+	return NOTIFY_DONE;
+}
+
+static int uprobe_breakpoint_handler(struct pt_regs *regs,
+		unsigned int esr)
+{
+	if (user_mode(regs) && uprobe_pre_sstep_notifier(regs))
+		return DBG_HOOK_HANDLED;
+
+	return DBG_HOOK_ERROR;
+}
+
+static int uprobe_single_step_handler(struct pt_regs *regs,
+		unsigned int esr)
+{
+	struct uprobe_task *utask = current->utask;
+
+	if (user_mode(regs)) {
+		WARN_ON(utask &&
+			(instruction_pointer(regs) != utask->xol_vaddr + 4));
+
+		if (uprobe_post_sstep_notifier(regs))
+			return DBG_HOOK_HANDLED;
+	}
+
+	return DBG_HOOK_ERROR;
+}
+
+/* uprobe breakpoint handler hook */
+static struct break_hook uprobes_break_hook = {
+	.esr_mask = BRK64_ESR_MASK,
+	.esr_val = BRK64_ESR_UPROBES,
+	.fn = uprobe_breakpoint_handler,
+};
+
+/* uprobe single step handler hook */
+static struct step_hook uprobes_step_hook = {
+	.fn = uprobe_single_step_handler,
+};
+
+static int __init arch_init_uprobes(void)
+{
+	register_break_hook(&uprobes_break_hook);
+	register_step_hook(&uprobes_step_hook);
+
+	return 0;
+}
+
+device_initcall(arch_init_uprobes);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/process.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/process.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/personality.h>
 #include <linux/notifier.h>
 #include <trace/events/power.h>
+#include <linux/percpu.h>
 
 #include <asm/alternative.h>
 #include <asm/compat.h>
@@ -282,7 +283,7 @@ int copy_thread(unsigned long clone_flag
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->pstate = PSR_MODE_EL1h;
 		if (IS_ENABLED(CONFIG_ARM64_UAO) &&
-		    cpus_have_cap(ARM64_HAS_UAO))
+		    cpus_have_const_cap(ARM64_HAS_UAO))
 			childregs->pstate |= PSR_UAO_BIT;
 		p->thread.cpu_context.x19 = stack_start;
 		p->thread.cpu_context.x20 = stk_sz;
@@ -322,6 +323,20 @@ void uao_thread_switch(struct task_struc
 }
 
 /*
+ * We store our current task in sp_el0, which is clobbered by userspace. Keep a
+ * shadow copy so that we can restore this upon entry from userspace.
+ *
+ * This is *only* for exception entry from EL0, and is not valid until we
+ * __switch_to() a user task.
+ */
+DEFINE_PER_CPU(struct task_struct *, __entry_task);
+
+static void entry_task_switch(struct task_struct *next)
+{
+	__this_cpu_write(__entry_task, next);
+}
+
+/*
  * Thread switching.
  */
 struct task_struct *__switch_to(struct task_struct *prev,
@@ -333,6 +348,7 @@ struct task_struct *__switch_to(struct t
 	tls_thread_switch(next);
 	hw_breakpoint_thread_switch(next);
 	contextidr_thread_switch(next);
+	entry_task_switch(next);
 	uao_thread_switch(next);
 
 	/*
@@ -350,27 +366,35 @@ struct task_struct *__switch_to(struct t
 unsigned long get_wchan(struct task_struct *p)
 {
 	struct stackframe frame;
-	unsigned long stack_page;
+	unsigned long stack_page, ret = 0;
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
+	stack_page = (unsigned long)try_get_task_stack(p);
+	if (!stack_page)
+		return 0;
+
 	frame.fp = thread_saved_fp(p);
 	frame.sp = thread_saved_sp(p);
 	frame.pc = thread_saved_pc(p);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	frame.graph = p->curr_ret_stack;
 #endif
-	stack_page = (unsigned long)task_stack_page(p);
 	do {
 		if (frame.sp < stack_page ||
 		    frame.sp >= stack_page + THREAD_SIZE ||
 		    unwind_frame(p, &frame))
-			return 0;
-		if (!in_sched_functions(frame.pc))
-			return frame.pc;
+			goto out;
+		if (!in_sched_functions(frame.pc)) {
+			ret = frame.pc;
+			goto out;
+		}
 	} while (count ++ < 16);
-	return 0;
+
+out:
+	put_task_stack(p);
+	return ret;
 }
 
 unsigned long arch_align_stack(unsigned long sp)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -327,13 +327,13 @@ static int ptrace_hbp_fill_attr_ctrl(uns
 				     struct arch_hw_breakpoint_ctrl ctrl,
 				     struct perf_event_attr *attr)
 {
-	int err, len, type, disabled = !ctrl.enabled;
+	int err, len, type, offset, disabled = !ctrl.enabled;
 
 	attr->disabled = disabled;
 	if (disabled)
 		return 0;
 
-	err = arch_bp_generic_fields(ctrl, &len, &type);
+	err = arch_bp_generic_fields(ctrl, &len, &type, &offset);
 	if (err)
 		return err;
 
@@ -352,6 +352,7 @@ static int ptrace_hbp_fill_attr_ctrl(uns
 
 	attr->bp_len	= len;
 	attr->bp_type	= type;
+	attr->bp_addr	+= offset;
 
 	return 0;
 }
@@ -404,7 +405,7 @@ static int ptrace_hbp_get_addr(unsigned
 	if (IS_ERR(bp))
 		return PTR_ERR(bp);
 
-	*addr = bp ? bp->attr.bp_addr : 0;
+	*addr = bp ? counter_arch_bp(bp)->address : 0;
 	return 0;
 }
 
@@ -550,6 +551,8 @@ static int hw_break_set(struct task_stru
 	/* (address, ctrl) registers */
 	limit = regset->n * regset->size;
 	while (count && offset < limit) {
+		if (count < PTRACE_HBP_ADDR_SZ)
+			return -EINVAL;
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,
 					 offset, offset + PTRACE_HBP_ADDR_SZ);
 		if (ret)
@@ -559,6 +562,8 @@ static int hw_break_set(struct task_stru
 			return ret;
 		offset += PTRACE_HBP_ADDR_SZ;
 
+		if (!count)
+			break;
 		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,
 					 offset, offset + PTRACE_HBP_CTRL_SZ);
 		if (ret)
@@ -595,7 +600,7 @@ static int gpr_set(struct task_struct *t
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct user_pt_regs newregs;
+	struct user_pt_regs newregs = task_pt_regs(target)->user_regs;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
 	if (ret)
@@ -625,7 +630,8 @@ static int fpr_set(struct task_struct *t
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct user_fpsimd_state newstate;
+	struct user_fpsimd_state newstate =
+		target->thread.fpsimd_state.user_fpsimd;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);
 	if (ret)
@@ -649,7 +655,7 @@ static int tls_set(struct task_struct *t
 		   const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	unsigned long tls;
+	unsigned long tls = target->thread.tp_value;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
 	if (ret)
@@ -675,7 +681,8 @@ static int system_call_set(struct task_s
 			   unsigned int pos, unsigned int count,
 			   const void *kbuf, const void __user *ubuf)
 {
-	int syscallno, ret;
+	int syscallno = task_pt_regs(target)->syscallno;
+	int ret;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);
 	if (ret)
@@ -947,7 +954,7 @@ static int compat_tls_set(struct task_st
 			  const void __user *ubuf)
 {
 	int ret;
-	compat_ulong_t tls;
+	compat_ulong_t tls = target->thread.tp_value;
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/return_address.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/return_address.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/return_address.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/return_address.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/ftrace.h>
 
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
 struct return_address_data {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/setup.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -291,6 +291,15 @@ void __init setup_arch(char **cmdline_p)
 	smp_init_cpus();
 	smp_build_mpidr_hash();
 
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	/*
+	 * Make sure init_thread_info.ttbr0 always generates translation
+	 * faults in case uaccess_enable() is inadvertently called by the init
+	 * thread.
+	 */
+	init_task.thread_info.ttbr0 = virt_to_phys(empty_zero_page);
+#endif
+
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
@@ -329,11 +338,11 @@ subsys_initcall(topology_init);
 static int dump_kernel_offset(struct notifier_block *self, unsigned long v,
 			      void *p)
 {
-	u64 const kaslr_offset = kimage_vaddr - KIMAGE_VADDR;
+	const unsigned long offset = kaslr_offset();
 
-	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset > 0) {
-		pr_emerg("Kernel Offset: 0x%llx from 0x%lx\n",
-			 kaslr_offset, KIMAGE_VADDR);
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0) {
+		pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",
+			 offset, KIMAGE_VADDR);
 	} else {
 		pr_emerg("Kernel Offset: disabled\n");
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/signal32.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/signal32.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/signal32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/signal32.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <asm/esr.h>
 #include <asm/fpsimd.h>
 #include <asm/signal32.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 
 struct compat_sigcontext {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/signal.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -414,6 +414,9 @@ asmlinkage void do_notify_resume(struct
 		} else {
 			local_irq_enable();
 
+			if (thread_flags & _TIF_UPROBE)
+				uprobe_notify_resume(regs);
+
 			if (thread_flags & _TIF_SIGPENDING)
 				do_signal(regs);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/sleep.S linux-libre-4.10-rc8-gnu/arch/arm64/kernel/sleep.S
--- linux-libre-4.9-gnu/arch/arm64/kernel/sleep.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/sleep.S	2017-02-12 16:03:20.000000000 -0500
@@ -125,9 +125,6 @@ ENTRY(_cpu_resume)
 	/* load sp from context */
 	ldr	x2, [x0, #CPU_CTX_SP]
 	mov	sp, x2
-	/* save thread_info */
-	and	x2, x2, #~(THREAD_SIZE - 1)
-	msr	sp_el0, x2
 	/*
 	 * cpu_do_resume expects x0 to contain context address pointer
 	 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/smp.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/smp.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,6 +58,9 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/ipi.h>
 
+DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
+EXPORT_PER_CPU_SYMBOL(cpu_number);
+
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
  * so we need some other way of telling a new secondary core
@@ -146,6 +149,7 @@ int __cpu_up(unsigned int cpu, struct ta
 	 * We need to tell the secondary core where to find its stack and the
 	 * page tables.
 	 */
+	secondary_data.task = idle;
 	secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
 	update_cpu_boot_status(CPU_MMU_OFF);
 	__flush_dcache_area(&secondary_data, sizeof(secondary_data));
@@ -170,6 +174,7 @@ int __cpu_up(unsigned int cpu, struct ta
 		pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
 	}
 
+	secondary_data.task = NULL;
 	secondary_data.stack = NULL;
 	status = READ_ONCE(secondary_data.status);
 	if (ret && status) {
@@ -208,7 +213,10 @@ int __cpu_up(unsigned int cpu, struct ta
 asmlinkage void secondary_start_kernel(void)
 {
 	struct mm_struct *mm = &init_mm;
-	unsigned int cpu = smp_processor_id();
+	unsigned int cpu;
+
+	cpu = task_cpu(current);
+	set_my_cpu_offset(per_cpu_offset(cpu));
 
 	/*
 	 * All kernel threads share the same mm context; grab a
@@ -217,8 +225,6 @@ asmlinkage void secondary_start_kernel(v
 	atomic_inc(&mm->mm_count);
 	current->active_mm = mm;
 
-	set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
-
 	/*
 	 * TTBR0 is only used for the identity mapping at this stage. Make it
 	 * point to zero page to avoid speculatively fetching new entries.
@@ -718,6 +724,8 @@ void __init smp_prepare_cpus(unsigned in
 	 */
 	for_each_possible_cpu(cpu) {
 
+		per_cpu(cpu_number, cpu) = cpu;
+
 		if (cpu == smp_processor_id())
 			continue;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/stacktrace.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/stacktrace.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/stacktrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/stacktrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/stacktrace.h>
 
 #include <asm/irq.h>
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 
 /*
@@ -128,7 +129,6 @@ void notrace walk_stackframe(struct task
 			break;
 	}
 }
-EXPORT_SYMBOL(walk_stackframe);
 
 #ifdef CONFIG_STACKTRACE
 struct stack_trace_data {
@@ -181,6 +181,9 @@ void save_stack_trace_tsk(struct task_st
 	struct stack_trace_data data;
 	struct stackframe frame;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	data.trace = trace;
 	data.skip = trace->skip;
 
@@ -202,6 +205,8 @@ void save_stack_trace_tsk(struct task_st
 	walk_stackframe(tsk, &frame, save_trace, &data);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
+
+	put_task_stack(tsk);
 }
 
 void save_stack_trace(struct stack_trace *trace)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/suspend.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/suspend.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/suspend.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/suspend.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,12 +47,6 @@ void notrace __cpu_suspend_exit(void)
 	cpu_uninstall_idmap();
 
 	/*
-	 * Restore per-cpu offset before any kernel
-	 * subsystem relying on it has a chance to run.
-	 */
-	set_my_cpu_offset(per_cpu_offset(cpu));
-
-	/*
 	 * PSTATE was not saved over suspend/resume, re-enable any detected
 	 * features that might not have been set correctly.
 	 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/topology.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/topology.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/topology.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/topology.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@
  * for more details.
  */
 
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/init.h>
@@ -19,10 +20,231 @@
 #include <linux/nodemask.h>
 #include <linux/of.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/cpufreq.h>
 
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
+static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
+static DEFINE_MUTEX(cpu_scale_mutex);
+
+unsigned long arch_scale_cpu_capacity(struct sched_domain *sd, int cpu)
+{
+	return per_cpu(cpu_scale, cpu);
+}
+
+static void set_capacity_scale(unsigned int cpu, unsigned long capacity)
+{
+	per_cpu(cpu_scale, cpu) = capacity;
+}
+
+#ifdef CONFIG_PROC_SYSCTL
+static ssize_t cpu_capacity_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+
+	return sprintf(buf, "%lu\n",
+			arch_scale_cpu_capacity(NULL, cpu->dev.id));
+}
+
+static ssize_t cpu_capacity_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf,
+				  size_t count)
+{
+	struct cpu *cpu = container_of(dev, struct cpu, dev);
+	int this_cpu = cpu->dev.id, i;
+	unsigned long new_capacity;
+	ssize_t ret;
+
+	if (count) {
+		ret = kstrtoul(buf, 0, &new_capacity);
+		if (ret)
+			return ret;
+		if (new_capacity > SCHED_CAPACITY_SCALE)
+			return -EINVAL;
+
+		mutex_lock(&cpu_scale_mutex);
+		for_each_cpu(i, &cpu_topology[this_cpu].core_sibling)
+			set_capacity_scale(i, new_capacity);
+		mutex_unlock(&cpu_scale_mutex);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(cpu_capacity);
+
+static int register_cpu_capacity_sysctl(void)
+{
+	int i;
+	struct device *cpu;
+
+	for_each_possible_cpu(i) {
+		cpu = get_cpu_device(i);
+		if (!cpu) {
+			pr_err("%s: too early to get CPU%d device!\n",
+			       __func__, i);
+			continue;
+		}
+		device_create_file(cpu, &dev_attr_cpu_capacity);
+	}
+
+	return 0;
+}
+subsys_initcall(register_cpu_capacity_sysctl);
+#endif
+
+static u32 capacity_scale;
+static u32 *raw_capacity;
+static bool cap_parsing_failed;
+
+static void __init parse_cpu_capacity(struct device_node *cpu_node, int cpu)
+{
+	int ret;
+	u32 cpu_capacity;
+
+	if (cap_parsing_failed)
+		return;
+
+	ret = of_property_read_u32(cpu_node,
+				   "capacity-dmips-mhz",
+				   &cpu_capacity);
+	if (!ret) {
+		if (!raw_capacity) {
+			raw_capacity = kcalloc(num_possible_cpus(),
+					       sizeof(*raw_capacity),
+					       GFP_KERNEL);
+			if (!raw_capacity) {
+				pr_err("cpu_capacity: failed to allocate memory for raw capacities\n");
+				cap_parsing_failed = true;
+				return;
+			}
+		}
+		capacity_scale = max(cpu_capacity, capacity_scale);
+		raw_capacity[cpu] = cpu_capacity;
+		pr_debug("cpu_capacity: %s cpu_capacity=%u (raw)\n",
+			cpu_node->full_name, raw_capacity[cpu]);
+	} else {
+		if (raw_capacity) {
+			pr_err("cpu_capacity: missing %s raw capacity\n",
+				cpu_node->full_name);
+			pr_err("cpu_capacity: partial information: fallback to 1024 for all CPUs\n");
+		}
+		cap_parsing_failed = true;
+		kfree(raw_capacity);
+	}
+}
+
+static void normalize_cpu_capacity(void)
+{
+	u64 capacity;
+	int cpu;
+
+	if (!raw_capacity || cap_parsing_failed)
+		return;
+
+	pr_debug("cpu_capacity: capacity_scale=%u\n", capacity_scale);
+	mutex_lock(&cpu_scale_mutex);
+	for_each_possible_cpu(cpu) {
+		pr_debug("cpu_capacity: cpu=%d raw_capacity=%u\n",
+			 cpu, raw_capacity[cpu]);
+		capacity = (raw_capacity[cpu] << SCHED_CAPACITY_SHIFT)
+			/ capacity_scale;
+		set_capacity_scale(cpu, capacity);
+		pr_debug("cpu_capacity: CPU%d cpu_capacity=%lu\n",
+			cpu, arch_scale_cpu_capacity(NULL, cpu));
+	}
+	mutex_unlock(&cpu_scale_mutex);
+}
+
+#ifdef CONFIG_CPU_FREQ
+static cpumask_var_t cpus_to_visit;
+static bool cap_parsing_done;
+static void parsing_done_workfn(struct work_struct *work);
+static DECLARE_WORK(parsing_done_work, parsing_done_workfn);
+
+static int
+init_cpu_capacity_callback(struct notifier_block *nb,
+			   unsigned long val,
+			   void *data)
+{
+	struct cpufreq_policy *policy = data;
+	int cpu;
+
+	if (cap_parsing_failed || cap_parsing_done)
+		return 0;
+
+	switch (val) {
+	case CPUFREQ_NOTIFY:
+		pr_debug("cpu_capacity: init cpu capacity for CPUs [%*pbl] (to_visit=%*pbl)\n",
+				cpumask_pr_args(policy->related_cpus),
+				cpumask_pr_args(cpus_to_visit));
+		cpumask_andnot(cpus_to_visit,
+			       cpus_to_visit,
+			       policy->related_cpus);
+		for_each_cpu(cpu, policy->related_cpus) {
+			raw_capacity[cpu] = arch_scale_cpu_capacity(NULL, cpu) *
+					    policy->cpuinfo.max_freq / 1000UL;
+			capacity_scale = max(raw_capacity[cpu], capacity_scale);
+		}
+		if (cpumask_empty(cpus_to_visit)) {
+			normalize_cpu_capacity();
+			kfree(raw_capacity);
+			pr_debug("cpu_capacity: parsing done\n");
+			cap_parsing_done = true;
+			schedule_work(&parsing_done_work);
+		}
+	}
+	return 0;
+}
+
+static struct notifier_block init_cpu_capacity_notifier = {
+	.notifier_call = init_cpu_capacity_callback,
+};
+
+static int __init register_cpufreq_notifier(void)
+{
+	/*
+	 * on ACPI-based systems we need to use the default cpu capacity
+	 * until we have the necessary code to parse the cpu capacity, so
+	 * skip registering cpufreq notifier.
+	 */
+	if (!acpi_disabled || cap_parsing_failed)
+		return -EINVAL;
+
+	if (!alloc_cpumask_var(&cpus_to_visit, GFP_KERNEL)) {
+		pr_err("cpu_capacity: failed to allocate memory for cpus_to_visit\n");
+		return -ENOMEM;
+	}
+	cpumask_copy(cpus_to_visit, cpu_possible_mask);
+
+	return cpufreq_register_notifier(&init_cpu_capacity_notifier,
+					 CPUFREQ_POLICY_NOTIFIER);
+}
+core_initcall(register_cpufreq_notifier);
+
+static void parsing_done_workfn(struct work_struct *work)
+{
+	cpufreq_unregister_notifier(&init_cpu_capacity_notifier,
+					 CPUFREQ_POLICY_NOTIFIER);
+}
+
+#else
+static int __init free_raw_capacity(void)
+{
+	kfree(raw_capacity);
+
+	return 0;
+}
+core_initcall(free_raw_capacity);
+#endif
+
 static int __init get_cpu_for_node(struct device_node *node)
 {
 	struct device_node *cpu_node;
@@ -34,6 +256,7 @@ static int __init get_cpu_for_node(struc
 
 	for_each_possible_cpu(cpu) {
 		if (of_get_cpu_node(cpu, NULL) == cpu_node) {
+			parse_cpu_capacity(cpu_node, cpu);
 			of_node_put(cpu_node);
 			return cpu;
 		}
@@ -178,13 +401,17 @@ static int __init parse_dt_topology(void
 	 * cluster with restricted subnodes.
 	 */
 	map = of_get_child_by_name(cn, "cpu-map");
-	if (!map)
+	if (!map) {
+		cap_parsing_failed = true;
 		goto out;
+	}
 
 	ret = parse_cluster(map, 0);
 	if (ret != 0)
 		goto out_map;
 
+	normalize_cpu_capacity();
+
 	/*
 	 * Check that all cores are in the topology; the SMP code will
 	 * only mark cores described in the DT as possible.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/arm64/kernel/traps.c
--- linux-libre-4.9-gnu/arch/arm64/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,7 @@
 #include <asm/esr.h>
 #include <asm/insn.h>
 #include <asm/traps.h>
+#include <asm/stack_pointer.h>
 #include <asm/stacktrace.h>
 #include <asm/exception.h>
 #include <asm/system_misc.h>
@@ -147,6 +148,9 @@ static void dump_backtrace(struct pt_reg
 	if (!tsk)
 		tsk = current;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	/*
 	 * Switching between stacks is valid when tracing current and in
 	 * non-preemptible context.
@@ -212,6 +216,8 @@ static void dump_backtrace(struct pt_reg
 				 stack + sizeof(struct pt_regs));
 		}
 	}
+
+	put_task_stack(tsk);
 }
 
 void show_stack(struct task_struct *tsk, unsigned long *sp)
@@ -227,10 +233,9 @@ void show_stack(struct task_struct *tsk,
 #endif
 #define S_SMP " SMP"
 
-static int __die(const char *str, int err, struct thread_info *thread,
-		 struct pt_regs *regs)
+static int __die(const char *str, int err, struct pt_regs *regs)
 {
-	struct task_struct *tsk = thread->task;
+	struct task_struct *tsk = current;
 	static int die_counter;
 	int ret;
 
@@ -245,7 +250,8 @@ static int __die(const char *str, int er
 	print_modules();
 	__show_regs(regs);
 	pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
-		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
+		 TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk),
+		 end_of_stack(tsk));
 
 	if (!user_mode(regs)) {
 		dump_mem(KERN_EMERG, "Stack: ", regs->sp,
@@ -264,7 +270,6 @@ static DEFINE_RAW_SPINLOCK(die_lock);
  */
 void die(const char *str, struct pt_regs *regs, int err)
 {
-	struct thread_info *thread = current_thread_info();
 	int ret;
 
 	oops_enter();
@@ -272,9 +277,9 @@ void die(const char *str, struct pt_regs
 	raw_spin_lock_irq(&die_lock);
 	console_verbose();
 	bust_spinlocks(1);
-	ret = __die(str, err, thread, regs);
+	ret = __die(str, err, regs);
 
-	if (regs && kexec_should_crash(thread->task))
+	if (regs && kexec_should_crash(current))
 		crash_kexec(regs);
 
 	bust_spinlocks(0);
@@ -435,9 +440,10 @@ int cpu_enable_cache_maint_trap(void *__
 }
 
 #define __user_cache_maint(insn, address, res)			\
-	if (untagged_addr(address) >= user_addr_max())		\
+	if (untagged_addr(address) >= user_addr_max()) {	\
 		res = -EFAULT;					\
-	else							\
+	} else {						\
+		uaccess_ttbr0_enable();				\
 		asm volatile (					\
 			"1:	" insn ", %1\n"			\
 			"	mov	%w0, #0\n"		\
@@ -449,7 +455,9 @@ int cpu_enable_cache_maint_trap(void *__
 			"	.popsection\n"			\
 			_ASM_EXTABLE(1b, 3b)			\
 			: "=r" (res)				\
-			: "r" (address), "i" (-EFAULT) )
+			: "r" (address), "i" (-EFAULT));	\
+		uaccess_ttbr0_disable();			\
+	}
 
 static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 {
@@ -596,17 +604,34 @@ const char *esr_get_class_string(u32 esr
 }
 
 /*
- * bad_mode handles the impossible case in the exception vector.
+ * bad_mode handles the impossible case in the exception vector. This is always
+ * fatal.
  */
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
 {
-	siginfo_t info;
-	void __user *pc = (void __user *)instruction_pointer(regs);
 	console_verbose();
 
 	pr_crit("Bad mode in %s handler detected on CPU%d, code 0x%08x -- %s\n",
 		handler[reason], smp_processor_id(), esr,
 		esr_get_class_string(esr));
+
+	die("Oops - bad mode", regs, 0);
+	local_irq_disable();
+	panic("bad mode");
+}
+
+/*
+ * bad_el0_sync handles unexpected, but potentially recoverable synchronous
+ * exceptions taken from EL0. Unlike bad_mode, this returns.
+ */
+asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
+{
+	siginfo_t info;
+	void __user *pc = (void __user *)instruction_pointer(regs);
+	console_verbose();
+
+	pr_crit("Bad EL0 synchronous exception detected on CPU%d, code 0x%08x -- %s\n",
+		smp_processor_id(), esr, esr_get_class_string(esr));
 	__show_regs(regs);
 
 	info.si_signo = SIGILL;
@@ -614,7 +639,10 @@ asmlinkage void bad_mode(struct pt_regs
 	info.si_code  = ILL_ILLOPC;
 	info.si_addr  = pc;
 
-	arm64_notify_die("Oops - bad mode", regs, &info, 0);
+	current->thread.fault_address = 0;
+	current->thread.fault_code = 0;
+
+	force_sig_info(info.si_signo, &info, current);
 }
 
 void __pte_error(const char *file, int line, unsigned long val)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kernel/vmlinux.lds.S linux-libre-4.10-rc8-gnu/arch/arm64/kernel/vmlinux.lds.S
--- linux-libre-4.9-gnu/arch/arm64/kernel/vmlinux.lds.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kernel/vmlinux.lds.S	2017-02-12 16:03:20.000000000 -0500
@@ -216,6 +216,11 @@ SECTIONS
 	swapper_pg_dir = .;
 	. += SWAPPER_DIR_SIZE;
 
+#ifdef CONFIG_ARM64_SW_TTBR0_PAN
+	reserved_ttbr0 = .;
+	. += RESERVED_TTBR0_SIZE;
+#endif
+
 	_end = .;
 
 	STABS_DEBUG
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kvm/guest.c linux-libre-4.10-rc8-gnu/arch/arm64/kvm/guest.c
--- linux-libre-4.9-gnu/arch/arm64/kvm/guest.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kvm/guest.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <asm/cputype.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/kvm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kvm/handle_exit.c linux-libre-4.10-rc8-gnu/arch/arm64/kvm/handle_exit.c
--- linux-libre-4.9-gnu/arch/arm64/kvm/handle_exit.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kvm/handle_exit.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,6 +57,16 @@ static int handle_smc(struct kvm_vcpu *v
 	return 1;
 }
 
+/*
+ * Guest access to FP/ASIMD registers are routed to this handler only
+ * when the system doesn't support FP/ASIMD.
+ */
+static int handle_no_fpsimd(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+	kvm_inject_undefined(vcpu);
+	return 1;
+}
+
 /**
  * kvm_handle_wfx - handle a wait-for-interrupts or wait-for-event
  *		    instruction executed by a guest
@@ -144,6 +154,7 @@ static exit_handle_fn arm_exit_handlers[
 	[ESR_ELx_EC_BREAKPT_LOW]= kvm_handle_guest_debug,
 	[ESR_ELx_EC_BKPT32]	= kvm_handle_guest_debug,
 	[ESR_ELx_EC_BRK64]	= kvm_handle_guest_debug,
+	[ESR_ELx_EC_FP_ASIMD]	= handle_no_fpsimd,
 };
 
 static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kvm/hyp/hyp-entry.S linux-libre-4.10-rc8-gnu/arch/arm64/kvm/hyp/hyp-entry.S
--- linux-libre-4.9-gnu/arch/arm64/kvm/hyp/hyp-entry.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kvm/hyp/hyp-entry.S	2017-02-12 16:03:20.000000000 -0500
@@ -106,9 +106,16 @@ el1_trap:
 	 * x0: ESR_EC
 	 */
 
-	/* Guest accessed VFP/SIMD registers, save host, restore Guest */
+	/*
+	 * We trap the first access to the FP/SIMD to save the host context
+	 * and restore the guest context lazily.
+	 * If FP/SIMD is not implemented, handle the trap and inject an
+	 * undefined instruction exception to the guest.
+	 */
+alternative_if_not ARM64_HAS_NO_FPSIMD
 	cmp	x0, #ESR_ELx_EC_FP_ASIMD
 	b.eq	__fpsimd_guest_restore
+alternative_else_nop_endif
 
 	mrs	x1, tpidr_el2
 	mov	x0, #ARM_EXCEPTION_TRAP
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kvm/hyp/switch.c linux-libre-4.10-rc8-gnu/arch/arm64/kvm/hyp/switch.c
--- linux-libre-4.9-gnu/arch/arm64/kvm/hyp/switch.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kvm/hyp/switch.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
+#include <asm/fpsimd.h>
 
 static bool __hyp_text __fpsimd_enabled_nvhe(void)
 {
@@ -76,16 +77,24 @@ static void __hyp_text __activate_traps(
 	 * traps are only taken to EL2 if the operation would not otherwise
 	 * trap to EL1.  Therefore, always make sure that for 32-bit guests,
 	 * we set FPEXC.EN to prevent traps to EL1, when setting the TFP bit.
+	 * If FP/ASIMD is not implemented, FPEXC is UNDEFINED and any access to
+	 * it will cause an exception.
 	 */
 	val = vcpu->arch.hcr_el2;
-	if (!(val & HCR_RW)) {
+	if (!(val & HCR_RW) && system_supports_fpsimd()) {
 		write_sysreg(1 << 30, fpexc32_el2);
 		isb();
 	}
 	write_sysreg(val, hcr_el2);
 	/* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */
 	write_sysreg(1 << 15, hstr_el2);
-	/* Make sure we trap PMU access from EL0 to EL2 */
+	/*
+	 * Make sure we trap PMU access from EL0 to EL2. Also sanitize
+	 * PMSELR_EL0 to make sure it never contains the cycle
+	 * counter, which could make a PMXEVCNTR_EL0 access UNDEF at
+	 * EL1 instead of being trapped to EL2.
+	 */
+	write_sysreg(0, pmselr_el0);
 	write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);
 	write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
 	__activate_traps_arch()();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kvm/Kconfig linux-libre-4.10-rc8-gnu/arch/arm64/kvm/Kconfig
--- linux-libre-4.9-gnu/arch/arm64/kvm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kvm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -16,9 +16,6 @@ menuconfig VIRTUALIZATION
 
 if VIRTUALIZATION
 
-config KVM_ARM_VGIC_V3_ITS
-	bool
-
 config KVM
 	bool "Kernel-based Virtual Machine (KVM) support"
 	depends on OF
@@ -34,7 +31,6 @@ config KVM
 	select KVM_VFIO
 	select HAVE_KVM_EVENTFD
 	select HAVE_KVM_IRQFD
-	select KVM_ARM_VGIC_V3_ITS
 	select KVM_ARM_PMU if HW_PERF_EVENTS
 	select HAVE_KVM_MSI
 	select HAVE_KVM_IRQCHIP
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/kvm/reset.c linux-libre-4.10-rc8-gnu/arch/arm64/kvm/reset.c
--- linux-libre-4.9-gnu/arch/arm64/kvm/reset.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/kvm/reset.c	2017-02-12 16:03:20.000000000 -0500
@@ -86,12 +86,6 @@ int kvm_arch_dev_ioctl_check_extension(s
 	case KVM_CAP_VCPU_ATTRIBUTES:
 		r = 1;
 		break;
-	case KVM_CAP_MSI_DEVID:
-		if (!kvm)
-			r = -EINVAL;
-		else
-			r = kvm->arch.vgic.msis_require_devid;
-		break;
 	default:
 		r = 0;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/lib/clear_user.S linux-libre-4.10-rc8-gnu/arch/arm64/lib/clear_user.S
--- linux-libre-4.9-gnu/arch/arm64/lib/clear_user.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/lib/clear_user.S	2017-02-12 16:03:20.000000000 -0500
@@ -17,10 +17,7 @@
  */
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/asm-uaccess.h>
 
 	.text
 
@@ -33,8 +30,7 @@
  * Alignment fixed up by hardware.
  */
 ENTRY(__clear_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_enable_not_uao x2, x3
 	mov	x2, x1			// save the size for fixup return
 	subs	x1, x1, #8
 	b.mi	2f
@@ -54,8 +50,7 @@ uao_user_alternative 9f, strh, sttrh, wz
 	b.mi	5f
 uao_user_alternative 9f, strb, sttrb, wzr, x0, 0
 5:	mov	x0, #0
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x2
 	ret
 ENDPROC(__clear_user)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/lib/copy_from_user.S linux-libre-4.10-rc8-gnu/arch/arm64/lib/copy_from_user.S
--- linux-libre-4.9-gnu/arch/arm64/lib/copy_from_user.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/lib/copy_from_user.S	2017-02-12 16:03:20.000000000 -0500
@@ -16,11 +16,8 @@
 
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
 #include <asm/cache.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/asm-uaccess.h>
 
 /*
  * Copy from user space to a kernel buffer (alignment handled by the hardware)
@@ -67,12 +64,10 @@
 
 end	.req	x5
 ENTRY(__arch_copy_from_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_enable_not_uao x3, x4
 	add	end, x0, x2
 #include "copy_template.S"
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x3
 	mov	x0, #0				// Nothing to copy
 	ret
 ENDPROC(__arch_copy_from_user)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/lib/copy_in_user.S linux-libre-4.10-rc8-gnu/arch/arm64/lib/copy_in_user.S
--- linux-libre-4.9-gnu/arch/arm64/lib/copy_in_user.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/lib/copy_in_user.S	2017-02-12 16:03:20.000000000 -0500
@@ -18,11 +18,8 @@
 
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
 #include <asm/cache.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/asm-uaccess.h>
 
 /*
  * Copy from user space to user space (alignment handled by the hardware)
@@ -68,12 +65,10 @@
 
 end	.req	x5
 ENTRY(__copy_in_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_enable_not_uao x3, x4
 	add	end, x0, x2
 #include "copy_template.S"
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x3
 	mov	x0, #0
 	ret
 ENDPROC(__copy_in_user)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/lib/copy_to_user.S linux-libre-4.10-rc8-gnu/arch/arm64/lib/copy_to_user.S
--- linux-libre-4.9-gnu/arch/arm64/lib/copy_to_user.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/lib/copy_to_user.S	2017-02-12 16:03:20.000000000 -0500
@@ -16,11 +16,8 @@
 
 #include <linux/linkage.h>
 
-#include <asm/alternative.h>
-#include <asm/assembler.h>
 #include <asm/cache.h>
-#include <asm/cpufeature.h>
-#include <asm/sysreg.h>
+#include <asm/asm-uaccess.h>
 
 /*
  * Copy to user space from a kernel buffer (alignment handled by the hardware)
@@ -66,12 +63,10 @@
 
 end	.req	x5
 ENTRY(__arch_copy_to_user)
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_enable_not_uao x3, x4
 	add	end, x0, x2
 #include "copy_template.S"
-ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_ALT_PAN_NOT_UAO, \
-	    CONFIG_ARM64_PAN)
+	uaccess_disable_not_uao x3
 	mov	x0, #0
 	ret
 ENDPROC(__arch_copy_to_user)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/Makefile
--- linux-libre-4.9-gnu/arch/arm64/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -37,10 +37,16 @@ $(warning LSE atomics not supported by b
   endif
 endif
 
-KBUILD_CFLAGS	+= -mgeneral-regs-only $(lseinstr)
+brokengasinst := $(call as-instr,1:\n.inst 0\n.rept . - 1b\n\nnop\n.endr\n,,-DCONFIG_BROKEN_GAS_INST=1)
+
+ifneq ($(brokengasinst),)
+$(warning Detected assembler with broken .inst; disassembly will be unreliable)
+endif
+
+KBUILD_CFLAGS	+= -mgeneral-regs-only $(lseinstr) $(brokengasinst)
 KBUILD_CFLAGS	+= -fno-asynchronous-unwind-tables
 KBUILD_CFLAGS	+= $(call cc-option, -mpc-relative-literal-loads)
-KBUILD_AFLAGS	+= $(lseinstr)
+KBUILD_AFLAGS	+= $(lseinstr) $(brokengasinst)
 
 ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
 KBUILD_CPPFLAGS	+= -mbig-endian
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/cache.S linux-libre-4.10-rc8-gnu/arch/arm64/mm/cache.S
--- linux-libre-4.9-gnu/arch/arm64/mm/cache.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/cache.S	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,7 @@
 #include <asm/assembler.h>
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
+#include <asm/asm-uaccess.h>
 
 /*
  *	flush_icache_range(start,end)
@@ -48,6 +49,7 @@ ENTRY(flush_icache_range)
  *	- end     - virtual end address of region
  */
 ENTRY(__flush_cache_user_range)
+	uaccess_ttbr0_enable x2, x3
 	dcache_line_size x2, x3
 	sub	x3, x2, #1
 	bic	x4, x0, x3
@@ -69,10 +71,12 @@ USER(9f, ic	ivau, x4	)		// invalidate I
 	dsb	ish
 	isb
 	mov	x0, #0
+1:
+	uaccess_ttbr0_disable x1
 	ret
 9:
 	mov	x0, #-EFAULT
-	ret
+	b	1b
 ENDPROC(flush_icache_range)
 ENDPROC(__flush_cache_user_range)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/context.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/context.c
--- linux-libre-4.9-gnu/arch/arm64/mm/context.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/context.c	2017-02-12 16:03:20.000000000 -0500
@@ -221,7 +221,12 @@ void check_and_switch_context(struct mm_
 	raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
 
 switch_mm_fastpath:
-	cpu_switch_mm(mm->pgd, mm);
+	/*
+	 * Defer TTBR0_EL1 setting for user threads to uaccess_enable() when
+	 * emulating PAN.
+	 */
+	if (!system_uses_ttbr0_pan())
+		cpu_switch_mm(mm->pgd, mm);
 }
 
 static int asids_init(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/dma-mapping.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/dma-mapping.c
--- linux-libre-4.9-gnu/arch/arm64/mm/dma-mapping.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/dma-mapping.c	2017-02-12 16:03:20.000000000 -0500
@@ -524,7 +524,8 @@ EXPORT_SYMBOL(dummy_dma_ops);
 
 static int __init arm64_dma_init(void)
 {
-	if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
+	if (swiotlb_force == SWIOTLB_FORCE ||
+	    max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
 		swiotlb = 1;
 
 	return atomic_pool_init();
@@ -796,6 +797,8 @@ static struct dma_map_ops iommu_dma_ops
 	.sync_single_for_device = __iommu_sync_single_for_device,
 	.sync_sg_for_cpu = __iommu_sync_sg_for_cpu,
 	.sync_sg_for_device = __iommu_sync_sg_for_device,
+	.map_resource = iommu_dma_map_resource,
+	.unmap_resource = iommu_dma_unmap_resource,
 	.dma_supported = iommu_dma_supported,
 	.mapping_error = iommu_dma_mapping_error,
 };
@@ -938,11 +941,6 @@ static void __iommu_setup_dma_ops(struct
 
 void arch_teardown_dma_ops(struct device *dev)
 {
-	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-
-	if (WARN_ON(domain))
-		iommu_detach_device(domain, dev);
-
 	dev->archdata.dma_ops = NULL;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/dump.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/dump.c
--- linux-libre-4.9-gnu/arch/arm64/mm/dump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/dump.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,6 +50,18 @@ static const struct addr_marker address_
 	{ -1,				NULL },
 };
 
+#define pt_dump_seq_printf(m, fmt, args...)	\
+({						\
+	if (m)					\
+		seq_printf(m, fmt, ##args);	\
+})
+
+#define pt_dump_seq_puts(m, fmt)	\
+({					\
+	if (m)				\
+		seq_printf(m, fmt);	\
+})
+
 /*
  * The page dumper groups page table entries of the same type into a single
  * description. It uses pg_state to track the range information while
@@ -62,6 +74,9 @@ struct pg_state {
 	unsigned long start_address;
 	unsigned level;
 	u64 current_prot;
+	bool check_wx;
+	unsigned long wx_pages;
+	unsigned long uxn_pages;
 };
 
 struct prot_bits {
@@ -186,10 +201,39 @@ static void dump_prot(struct pg_state *s
 			s = bits->clear;
 
 		if (s)
-			seq_printf(st->seq, " %s", s);
+			pt_dump_seq_printf(st->seq, " %s", s);
 	}
 }
 
+static void note_prot_uxn(struct pg_state *st, unsigned long addr)
+{
+	if (!st->check_wx)
+		return;
+
+	if ((st->current_prot & PTE_UXN) == PTE_UXN)
+		return;
+
+	WARN_ONCE(1, "arm64/mm: Found non-UXN mapping at address %p/%pS\n",
+		  (void *)st->start_address, (void *)st->start_address);
+
+	st->uxn_pages += (addr - st->start_address) / PAGE_SIZE;
+}
+
+static void note_prot_wx(struct pg_state *st, unsigned long addr)
+{
+	if (!st->check_wx)
+		return;
+	if ((st->current_prot & PTE_RDONLY) == PTE_RDONLY)
+		return;
+	if ((st->current_prot & PTE_PXN) == PTE_PXN)
+		return;
+
+	WARN_ONCE(1, "arm64/mm: Found insecure W+X mapping at address %p/%pS\n",
+		  (void *)st->start_address, (void *)st->start_address);
+
+	st->wx_pages += (addr - st->start_address) / PAGE_SIZE;
+}
+
 static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
 				u64 val)
 {
@@ -200,14 +244,16 @@ static void note_page(struct pg_state *s
 		st->level = level;
 		st->current_prot = prot;
 		st->start_address = addr;
-		seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+		pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
 	} else if (prot != st->current_prot || level != st->level ||
 		   addr >= st->marker[1].start_address) {
 		const char *unit = units;
 		unsigned long delta;
 
 		if (st->current_prot) {
-			seq_printf(st->seq, "0x%016lx-0x%016lx   ",
+			note_prot_uxn(st, addr);
+			note_prot_wx(st, addr);
+			pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx   ",
 				   st->start_address, addr);
 
 			delta = (addr - st->start_address) >> 10;
@@ -215,17 +261,17 @@ static void note_page(struct pg_state *s
 				delta >>= 10;
 				unit++;
 			}
-			seq_printf(st->seq, "%9lu%c %s", delta, *unit,
+			pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit,
 				   pg_level[st->level].name);
 			if (pg_level[st->level].bits)
 				dump_prot(st, pg_level[st->level].bits,
 					  pg_level[st->level].num);
-			seq_puts(st->seq, "\n");
+			pt_dump_seq_puts(st->seq, "\n");
 		}
 
 		if (addr >= st->marker[1].start_address) {
 			st->marker++;
-			seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+			pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
 		}
 
 		st->start_address = addr;
@@ -235,7 +281,7 @@ static void note_page(struct pg_state *s
 
 	if (addr >= st->marker[1].start_address) {
 		st->marker++;
-		seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+		pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
 	}
 
 }
@@ -304,9 +350,8 @@ static void walk_pgd(struct pg_state *st
 	}
 }
 
-static int ptdump_show(struct seq_file *m, void *v)
+void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
 {
-	struct ptdump_info *info = m->private;
 	struct pg_state st = {
 		.seq = m,
 		.marker = info->markers,
@@ -315,33 +360,16 @@ static int ptdump_show(struct seq_file *
 	walk_pgd(&st, info->mm, info->base_addr);
 
 	note_page(&st, 0, 0, 0);
-	return 0;
 }
 
-static int ptdump_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ptdump_show, inode->i_private);
-}
-
-static const struct file_operations ptdump_fops = {
-	.open		= ptdump_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-int ptdump_register(struct ptdump_info *info, const char *name)
+static void ptdump_initialize(void)
 {
-	struct dentry *pe;
 	unsigned i, j;
 
 	for (i = 0; i < ARRAY_SIZE(pg_level); i++)
 		if (pg_level[i].bits)
 			for (j = 0; j < pg_level[i].num; j++)
 				pg_level[i].mask |= pg_level[i].bits[j].mask;
-
-	pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
-	return pe ? 0 : -ENOMEM;
 }
 
 static struct ptdump_info kernel_ptdump_info = {
@@ -350,8 +378,30 @@ static struct ptdump_info kernel_ptdump_
 	.base_addr	= VA_START,
 };
 
+void ptdump_check_wx(void)
+{
+	struct pg_state st = {
+		.seq = NULL,
+		.marker = (struct addr_marker[]) {
+			{ 0, NULL},
+			{ -1, NULL},
+		},
+		.check_wx = true,
+	};
+
+	walk_pgd(&st, &init_mm, 0);
+	note_page(&st, 0, 0, 0);
+	if (st.wx_pages || st.uxn_pages)
+		pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n",
+			st.wx_pages, st.uxn_pages);
+	else
+		pr_info("Checked W+X mappings: passed, no W+X pages found\n");
+}
+
 static int ptdump_init(void)
 {
-	return ptdump_register(&kernel_ptdump_info, "kernel_page_tables");
+	ptdump_initialize();
+	return ptdump_debugfs_register(&kernel_ptdump_info,
+					"kernel_page_tables");
 }
 device_initcall(ptdump_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/fault.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/fault.c
--- linux-libre-4.9-gnu/arch/arm64/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,21 +88,21 @@ void show_pte(struct mm_struct *mm, unsi
 			break;
 
 		pud = pud_offset(pgd, addr);
-		printk(", *pud=%016llx", pud_val(*pud));
+		pr_cont(", *pud=%016llx", pud_val(*pud));
 		if (pud_none(*pud) || pud_bad(*pud))
 			break;
 
 		pmd = pmd_offset(pud, addr);
-		printk(", *pmd=%016llx", pmd_val(*pmd));
+		pr_cont(", *pmd=%016llx", pmd_val(*pmd));
 		if (pmd_none(*pmd) || pmd_bad(*pmd))
 			break;
 
 		pte = pte_offset_map(pmd, addr);
-		printk(", *pte=%016llx", pte_val(*pte));
+		pr_cont(", *pte=%016llx", pte_val(*pte));
 		pte_unmap(pte);
 	} while(0);
 
-	printk("\n");
+	pr_cont("\n");
 }
 
 #ifdef CONFIG_ARM64_HW_AFDBM
@@ -269,13 +269,19 @@ out:
 	return fault;
 }
 
-static inline bool is_permission_fault(unsigned int esr)
+static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs)
 {
 	unsigned int ec       = ESR_ELx_EC(esr);
 	unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE;
 
-	return (ec == ESR_ELx_EC_DABT_CUR && fsc_type == ESR_ELx_FSC_PERM) ||
-	       (ec == ESR_ELx_EC_IABT_CUR && fsc_type == ESR_ELx_FSC_PERM);
+	if (ec != ESR_ELx_EC_DABT_CUR && ec != ESR_ELx_EC_IABT_CUR)
+		return false;
+
+	if (system_uses_ttbr0_pan())
+		return fsc_type == ESR_ELx_FSC_FAULT &&
+			(regs->pstate & PSR_PAN_BIT);
+	else
+		return fsc_type == ESR_ELx_FSC_PERM;
 }
 
 static bool is_el0_instruction_abort(unsigned int esr)
@@ -315,7 +321,7 @@ static int __kprobes do_page_fault(unsig
 		mm_flags |= FAULT_FLAG_WRITE;
 	}
 
-	if (is_permission_fault(esr) && (addr < USER_DS)) {
+	if (addr < USER_DS && is_permission_fault(esr, regs)) {
 		/* regs->orig_addr_limit may be 0 if we entered from EL0 */
 		if (regs->orig_addr_limit == KERNEL_DS)
 			die("Accessing user space memory with fs=KERNEL_DS", regs, esr);
@@ -507,10 +513,10 @@ static const struct fault_info {
 	{ do_bad,		SIGBUS,  0,		"unknown 17"			},
 	{ do_bad,		SIGBUS,  0,		"unknown 18"			},
 	{ do_bad,		SIGBUS,  0,		"unknown 19"			},
-	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
-	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
-	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
-	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous external abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous external abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous external abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous external abort (translation table walk)" },
 	{ do_bad,		SIGBUS,  0,		"synchronous parity error"	},
 	{ do_bad,		SIGBUS,  0,		"unknown 25"			},
 	{ do_bad,		SIGBUS,  0,		"unknown 26"			},
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/flush.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/flush.c
--- linux-libre-4.9-gnu/arch/arm64/mm/flush.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/flush.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,14 +25,7 @@
 #include <asm/cachetype.h>
 #include <asm/tlbflush.h>
 
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-		       unsigned long end)
-{
-	if (vma->vm_flags & VM_EXEC)
-		__flush_icache_all();
-}
-
-static void sync_icache_aliases(void *kaddr, unsigned long len)
+void sync_icache_aliases(void *kaddr, unsigned long len)
 {
 	unsigned long addr = (unsigned long)kaddr;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/hugetlbpage.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/hugetlbpage.c
--- linux-libre-4.9-gnu/arch/arm64/mm/hugetlbpage.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/hugetlbpage.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,20 +51,8 @@ static int find_num_contig(struct mm_str
 	*pgsize = PAGE_SIZE;
 	if (!pte_cont(pte))
 		return 1;
-	if (!pgd_present(*pgd)) {
-		VM_BUG_ON(!pgd_present(*pgd));
-		return 1;
-	}
 	pud = pud_offset(pgd, addr);
-	if (!pud_present(*pud)) {
-		VM_BUG_ON(!pud_present(*pud));
-		return 1;
-	}
 	pmd = pmd_offset(pud, addr);
-	if (!pmd_present(*pmd)) {
-		VM_BUG_ON(!pmd_present(*pmd));
-		return 1;
-	}
 	if ((pte_t *)pmd == ptep) {
 		*pgsize = PMD_SIZE;
 		return CONT_PMDS;
@@ -212,7 +200,7 @@ pte_t huge_ptep_get_and_clear(struct mm_
 		ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize);
 		/* save the 1st pte to return */
 		pte = ptep_get_and_clear(mm, addr, cpte);
-		for (i = 1; i < ncontig; ++i) {
+		for (i = 1, addr += pgsize; i < ncontig; ++i, addr += pgsize) {
 			/*
 			 * If HW_AFDBM is enabled, then the HW could
 			 * turn on the dirty bit for any of the page
@@ -250,8 +238,8 @@ int huge_ptep_set_access_flags(struct vm
 		pfn = pte_pfn(*cpte);
 		ncontig = find_num_contig(vma->vm_mm, addr, cpte,
 					  *cpte, &pgsize);
-		for (i = 0; i < ncontig; ++i, ++cpte) {
-			changed = ptep_set_access_flags(vma, addr, cpte,
+		for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize) {
+			changed |= ptep_set_access_flags(vma, addr, cpte,
 							pfn_pte(pfn,
 								hugeprot),
 							dirty);
@@ -273,7 +261,7 @@ void huge_ptep_set_wrprotect(struct mm_s
 
 		cpte = huge_pte_offset(mm, addr);
 		ncontig = find_num_contig(mm, addr, cpte, *cpte, &pgsize);
-		for (i = 0; i < ncontig; ++i, ++cpte)
+		for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize)
 			ptep_set_wrprotect(mm, addr, cpte);
 	} else {
 		ptep_set_wrprotect(mm, addr, ptep);
@@ -291,7 +279,7 @@ void huge_ptep_clear_flush(struct vm_are
 		cpte = huge_pte_offset(vma->vm_mm, addr);
 		ncontig = find_num_contig(vma->vm_mm, addr, cpte,
 					  *cpte, &pgsize);
-		for (i = 0; i < ncontig; ++i, ++cpte)
+		for (i = 0; i < ncontig; ++i, ++cpte, addr += pgsize)
 			ptep_clear_flush(vma, addr, cpte);
 	} else {
 		ptep_clear_flush(vma, addr, ptep);
@@ -323,7 +311,7 @@ __setup("hugepagesz=", setup_hugepagesz)
 static __init int add_default_hugepagesz(void)
 {
 	if (size_to_hstate(CONT_PTES * PAGE_SIZE) == NULL)
-		hugetlb_add_hstate(CONT_PMD_SHIFT);
+		hugetlb_add_hstate(CONT_PTE_SHIFT);
 	return 0;
 }
 arch_initcall(add_default_hugepagesz);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/init.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/init.c
--- linux-libre-4.9-gnu/arch/arm64/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -401,8 +401,11 @@ static void __init free_unused_memmap(vo
  */
 void __init mem_init(void)
 {
-	if (swiotlb_force || max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
+	if (swiotlb_force == SWIOTLB_FORCE ||
+	    max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
 		swiotlb_init(1);
+	else
+		swiotlb_force = SWIOTLB_NO_FORCE;
 
 	set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/Makefile linux-libre-4.10-rc8-gnu/arch/arm64/mm/Makefile
--- linux-libre-4.9-gnu/arch/arm64/mm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,8 @@ obj-y				:= dma-mapping.o extable.o faul
 				   ioremap.o mmap.o pgd.o mmu.o \
 				   context.o proc.o pageattr.o
 obj-$(CONFIG_HUGETLB_PAGE)	+= hugetlbpage.o
-obj-$(CONFIG_ARM64_PTDUMP)	+= dump.o
+obj-$(CONFIG_ARM64_PTDUMP_CORE)	+= dump.o
+obj-$(CONFIG_ARM64_PTDUMP_DEBUGFS)	+= ptdump_debugfs.o
 obj-$(CONFIG_NUMA)		+= numa.o
 
 obj-$(CONFIG_KASAN)		+= kasan_init.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/mmu.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/mmu.c
--- linux-libre-4.9-gnu/arch/arm64/mm/mmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/mmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,8 +28,6 @@
 #include <linux/memblock.h>
 #include <linux/fs.h>
 #include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/stop_machine.h>
 
 #include <asm/barrier.h>
 #include <asm/cputype.h>
@@ -42,6 +40,7 @@
 #include <asm/tlb.h>
 #include <asm/memblock.h>
 #include <asm/mmu_context.h>
+#include <asm/ptdump.h>
 
 u64 idmap_t0sz = TCR_T0SZ(VA_BITS);
 
@@ -95,11 +94,24 @@ static phys_addr_t __init early_pgtable_
 	return phys;
 }
 
+static bool pgattr_change_is_safe(u64 old, u64 new)
+{
+	/*
+	 * The following mapping attributes may be updated in live
+	 * kernel mappings without the need for break-before-make.
+	 */
+	static const pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE;
+
+	return old  == 0 || new  == 0 || ((old ^ new) & ~mask) == 0;
+}
+
 static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
 				  unsigned long end, unsigned long pfn,
 				  pgprot_t prot,
-				  phys_addr_t (*pgtable_alloc)(void))
+				  phys_addr_t (*pgtable_alloc)(void),
+				  bool page_mappings_only)
 {
+	pgprot_t __prot = prot;
 	pte_t *pte;
 
 	BUG_ON(pmd_sect(*pmd));
@@ -115,8 +127,28 @@ static void alloc_init_pte(pmd_t *pmd, u
 
 	pte = pte_set_fixmap_offset(pmd, addr);
 	do {
-		set_pte(pte, pfn_pte(pfn, prot));
+		pte_t old_pte = *pte;
+
+		/*
+		 * Set the contiguous bit for the subsequent group of PTEs if
+		 * its size and alignment are appropriate.
+		 */
+		if (((addr | PFN_PHYS(pfn)) & ~CONT_PTE_MASK) == 0) {
+			if (end - addr >= CONT_PTE_SIZE && !page_mappings_only)
+				__prot = __pgprot(pgprot_val(prot) | PTE_CONT);
+			else
+				__prot = prot;
+		}
+
+		set_pte(pte, pfn_pte(pfn, __prot));
 		pfn++;
+
+		/*
+		 * After the PTE entry has been populated once, we
+		 * only allow updates to the permission attributes.
+		 */
+		BUG_ON(!pgattr_change_is_safe(pte_val(old_pte), pte_val(*pte)));
+
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 
 	pte_clear_fixmap();
@@ -125,8 +157,9 @@ static void alloc_init_pte(pmd_t *pmd, u
 static void alloc_init_pmd(pud_t *pud, unsigned long addr, unsigned long end,
 				  phys_addr_t phys, pgprot_t prot,
 				  phys_addr_t (*pgtable_alloc)(void),
-				  bool allow_block_mappings)
+				  bool page_mappings_only)
 {
+	pgprot_t __prot = prot;
 	pmd_t *pmd;
 	unsigned long next;
 
@@ -146,27 +179,39 @@ static void alloc_init_pmd(pud_t *pud, u
 
 	pmd = pmd_set_fixmap_offset(pud, addr);
 	do {
+		pmd_t old_pmd = *pmd;
+
 		next = pmd_addr_end(addr, end);
+
 		/* try section mapping first */
 		if (((addr | next | phys) & ~SECTION_MASK) == 0 &&
-		      allow_block_mappings) {
-			pmd_t old_pmd =*pmd;
-			pmd_set_huge(pmd, phys, prot);
+		      !page_mappings_only) {
 			/*
-			 * Check for previous table entries created during
-			 * boot (__create_page_tables) and flush them.
+			 * Set the contiguous bit for the subsequent group of
+			 * PMDs if its size and alignment are appropriate.
 			 */
-			if (!pmd_none(old_pmd)) {
-				flush_tlb_all();
-				if (pmd_table(old_pmd)) {
-					phys_addr_t table = pmd_page_paddr(old_pmd);
-					if (!WARN_ON_ONCE(slab_is_available()))
-						memblock_free(table, PAGE_SIZE);
-				}
+			if (((addr | phys) & ~CONT_PMD_MASK) == 0) {
+				if (end - addr >= CONT_PMD_SIZE)
+					__prot = __pgprot(pgprot_val(prot) |
+							  PTE_CONT);
+				else
+					__prot = prot;
 			}
+			pmd_set_huge(pmd, phys, __prot);
+
+			/*
+			 * After the PMD entry has been populated once, we
+			 * only allow updates to the permission attributes.
+			 */
+			BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd),
+						      pmd_val(*pmd)));
 		} else {
 			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
-				       prot, pgtable_alloc);
+				       prot, pgtable_alloc,
+				       page_mappings_only);
+
+			BUG_ON(pmd_val(old_pmd) != 0 &&
+			       pmd_val(old_pmd) != pmd_val(*pmd));
 		}
 		phys += next - addr;
 	} while (pmd++, addr = next, addr != end);
@@ -189,7 +234,7 @@ static inline bool use_1G_block(unsigned
 static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
 				  phys_addr_t phys, pgprot_t prot,
 				  phys_addr_t (*pgtable_alloc)(void),
-				  bool allow_block_mappings)
+				  bool page_mappings_only)
 {
 	pud_t *pud;
 	unsigned long next;
@@ -204,33 +249,28 @@ static void alloc_init_pud(pgd_t *pgd, u
 
 	pud = pud_set_fixmap_offset(pgd, addr);
 	do {
+		pud_t old_pud = *pud;
+
 		next = pud_addr_end(addr, end);
 
 		/*
 		 * For 4K granule only, attempt to put down a 1GB block
 		 */
-		if (use_1G_block(addr, next, phys) && allow_block_mappings) {
-			pud_t old_pud = *pud;
+		if (use_1G_block(addr, next, phys) && !page_mappings_only) {
 			pud_set_huge(pud, phys, prot);
 
 			/*
-			 * If we have an old value for a pud, it will
-			 * be pointing to a pmd table that we no longer
-			 * need (from swapper_pg_dir).
-			 *
-			 * Look up the old pmd table and free it.
+			 * After the PUD entry has been populated once, we
+			 * only allow updates to the permission attributes.
 			 */
-			if (!pud_none(old_pud)) {
-				flush_tlb_all();
-				if (pud_table(old_pud)) {
-					phys_addr_t table = pud_page_paddr(old_pud);
-					if (!WARN_ON_ONCE(slab_is_available()))
-						memblock_free(table, PAGE_SIZE);
-				}
-			}
+			BUG_ON(!pgattr_change_is_safe(pud_val(old_pud),
+						      pud_val(*pud)));
 		} else {
 			alloc_init_pmd(pud, addr, next, phys, prot,
-				       pgtable_alloc, allow_block_mappings);
+				       pgtable_alloc, page_mappings_only);
+
+			BUG_ON(pud_val(old_pud) != 0 &&
+			       pud_val(old_pud) != pud_val(*pud));
 		}
 		phys += next - addr;
 	} while (pud++, addr = next, addr != end);
@@ -242,7 +282,7 @@ static void __create_pgd_mapping(pgd_t *
 				 unsigned long virt, phys_addr_t size,
 				 pgprot_t prot,
 				 phys_addr_t (*pgtable_alloc)(void),
-				 bool allow_block_mappings)
+				 bool page_mappings_only)
 {
 	unsigned long addr, length, end, next;
 	pgd_t *pgd = pgd_offset_raw(pgdir, virt);
@@ -262,7 +302,7 @@ static void __create_pgd_mapping(pgd_t *
 	do {
 		next = pgd_addr_end(addr, end);
 		alloc_init_pud(pgd, addr, next, phys, prot, pgtable_alloc,
-			       allow_block_mappings);
+			       page_mappings_only);
 		phys += next - addr;
 	} while (pgd++, addr = next, addr != end);
 }
@@ -291,17 +331,17 @@ static void __init create_mapping_noallo
 			&phys, virt);
 		return;
 	}
-	__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, true);
+	__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, false);
 }
 
 void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
 			       unsigned long virt, phys_addr_t size,
-			       pgprot_t prot, bool allow_block_mappings)
+			       pgprot_t prot, bool page_mappings_only)
 {
 	BUG_ON(mm == &init_mm);
 
 	__create_pgd_mapping(mm->pgd, phys, virt, size, prot,
-			     pgd_pgtable_alloc, allow_block_mappings);
+			     pgd_pgtable_alloc, page_mappings_only);
 }
 
 static void create_mapping_late(phys_addr_t phys, unsigned long virt,
@@ -314,7 +354,7 @@ static void create_mapping_late(phys_add
 	}
 
 	__create_pgd_mapping(init_mm.pgd, phys, virt, size, prot,
-			     NULL, !debug_pagealloc_enabled());
+			     NULL, debug_pagealloc_enabled());
 }
 
 static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
@@ -332,7 +372,7 @@ static void __init __map_memblock(pgd_t
 		__create_pgd_mapping(pgd, start, __phys_to_virt(start),
 				     end - start, PAGE_KERNEL,
 				     early_pgtable_alloc,
-				     !debug_pagealloc_enabled());
+				     debug_pagealloc_enabled());
 		return;
 	}
 
@@ -345,13 +385,13 @@ static void __init __map_memblock(pgd_t
 				     __phys_to_virt(start),
 				     kernel_start - start, PAGE_KERNEL,
 				     early_pgtable_alloc,
-				     !debug_pagealloc_enabled());
+				     debug_pagealloc_enabled());
 	if (kernel_end < end)
 		__create_pgd_mapping(pgd, kernel_end,
 				     __phys_to_virt(kernel_end),
 				     end - kernel_end, PAGE_KERNEL,
 				     early_pgtable_alloc,
-				     !debug_pagealloc_enabled());
+				     debug_pagealloc_enabled());
 
 	/*
 	 * Map the linear alias of the [_text, __init_begin) interval as
@@ -361,7 +401,7 @@ static void __init __map_memblock(pgd_t
 	 */
 	__create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start),
 			     kernel_end - kernel_start, PAGE_KERNEL_RO,
-			     early_pgtable_alloc, !debug_pagealloc_enabled());
+			     early_pgtable_alloc, debug_pagealloc_enabled());
 }
 
 static void __init map_mem(pgd_t *pgd)
@@ -396,6 +436,11 @@ void mark_rodata_ro(void)
 	section_size = (unsigned long)__init_begin - (unsigned long)__start_rodata;
 	create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
 			    section_size, PAGE_KERNEL_RO);
+
+	/* flush the TLBs after updating live kernel mappings */
+	flush_tlb_all();
+
+	debug_checkwx();
 }
 
 static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
@@ -408,7 +453,7 @@ static void __init map_kernel_segment(pg
 	BUG_ON(!PAGE_ALIGNED(size));
 
 	__create_pgd_mapping(pgd, pa_start, (unsigned long)va_start, size, prot,
-			     early_pgtable_alloc, !debug_pagealloc_enabled());
+			     early_pgtable_alloc, debug_pagealloc_enabled());
 
 	vma->addr	= va_start;
 	vma->phys_addr	= pa_start;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/numa.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/numa.c
--- linux-libre-4.9-gnu/arch/arm64/mm/numa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/numa.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@ static int cpu_to_node_map[NR_CPUS] = {
 
 static int numa_distance_cnt;
 static u8 *numa_distance;
-static bool numa_off;
+bool numa_off;
 
 static __init int numa_parse_early_param(char *opt)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/proc.S linux-libre-4.10-rc8-gnu/arch/arm64/mm/proc.S
--- linux-libre-4.9-gnu/arch/arm64/mm/proc.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/proc.S	2017-02-12 16:03:20.000000000 -0500
@@ -70,11 +70,14 @@ ENTRY(cpu_do_suspend)
 	mrs	x8, mdscr_el1
 	mrs	x9, oslsr_el1
 	mrs	x10, sctlr_el1
+	mrs	x11, tpidr_el1
+	mrs	x12, sp_el0
 	stp	x2, x3, [x0]
 	stp	x4, xzr, [x0, #16]
 	stp	x5, x6, [x0, #32]
 	stp	x7, x8, [x0, #48]
 	stp	x9, x10, [x0, #64]
+	stp	x11, x12, [x0, #80]
 	ret
 ENDPROC(cpu_do_suspend)
 
@@ -90,6 +93,7 @@ ENTRY(cpu_do_resume)
 	ldp	x6, x8, [x0, #32]
 	ldp	x9, x10, [x0, #48]
 	ldp	x11, x12, [x0, #64]
+	ldp	x13, x14, [x0, #80]
 	msr	tpidr_el0, x2
 	msr	tpidrro_el0, x3
 	msr	contextidr_el1, x4
@@ -112,6 +116,8 @@ ENTRY(cpu_do_resume)
 	msr	mdscr_el1, x10
 
 	msr	sctlr_el1, x12
+	msr	tpidr_el1, x13
+	msr	sp_el0, x14
 	/*
 	 * Restore oslsr_el1 by writing oslar_el1
 	 */
@@ -136,11 +142,7 @@ ENTRY(cpu_do_switch_mm)
 	bfi	x0, x1, #48, #16		// set the ASID
 	msr	ttbr0_el1, x0			// set TTBR0
 	isb
-alternative_if ARM64_WORKAROUND_CAVIUM_27456
-	ic	iallu
-	dsb	nsh
-	isb
-alternative_else_nop_endif
+	post_ttbr0_update_workaround
 	ret
 ENDPROC(cpu_do_switch_mm)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/mm/ptdump_debugfs.c linux-libre-4.10-rc8-gnu/arch/arm64/mm/ptdump_debugfs.c
--- linux-libre-4.9-gnu/arch/arm64/mm/ptdump_debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/mm/ptdump_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,31 @@
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <asm/ptdump.h>
+
+static int ptdump_show(struct seq_file *m, void *v)
+{
+	struct ptdump_info *info = m->private;
+	ptdump_walk_pgd(m, info);
+	return 0;
+}
+
+static int ptdump_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ptdump_show, inode->i_private);
+}
+
+static const struct file_operations ptdump_fops = {
+	.open		= ptdump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+int ptdump_debugfs_register(struct ptdump_info *info, const char *name)
+{
+	struct dentry *pe;
+	pe = debugfs_create_file(name, 0400, NULL, info, &ptdump_fops);
+	return pe ? 0 : -ENOMEM;
+
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/arm64/xen/hypercall.S linux-libre-4.10-rc8-gnu/arch/arm64/xen/hypercall.S
--- linux-libre-4.9-gnu/arch/arm64/xen/hypercall.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/arm64/xen/hypercall.S	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,7 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/asm-uaccess.h>
 #include <xen/interface/xen.h>
 
 
@@ -91,6 +92,20 @@ ENTRY(privcmd_call)
 	mov x2, x3
 	mov x3, x4
 	mov x4, x5
+	/*
+	 * Privcmd calls are issued by the userspace. The kernel needs to
+	 * enable access to TTBR0_EL1 as the hypervisor would issue stage 1
+	 * translations to user memory via AT instructions. Since AT
+	 * instructions are not affected by the PAN bit (ARMv8.1), we only
+	 * need the explicit uaccess_enable/disable if the TTBR0 PAN emulation
+	 * is enabled (it implies that hardware UAO and PAN disabled).
+	 */
+	uaccess_ttbr0_enable x6, x7
 	hvc XEN_IMM
+
+	/*
+	 * Disable userspace access from kernel once the hyp call completed.
+	 */
+	uaccess_ttbr0_disable x6
 	ret
 ENDPROC(privcmd_call);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/avr32/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/avr32/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/avr32/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/avr32/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -92,7 +92,6 @@ extern struct avr32_cpuinfo boot_cpu_dat
 #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
 
 #define cpu_relax()		barrier()
-#define cpu_relax_lowlatency()        cpu_relax()
 #define cpu_sync_pipeline()	asm volatile("sub pc, -2" : : : "memory")
 
 struct cpu_context {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/avr32/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/avr32/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,4 +90,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _UAPI__ASM_AVR32_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/include/uapi/asm/unistd.h linux-libre-4.10-rc8-gnu/arch/avr32/include/uapi/asm/unistd.h
--- linux-libre-4.9-gnu/arch/avr32/include/uapi/asm/unistd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/include/uapi/asm/unistd.h	2017-02-12 16:03:20.000000000 -0500
@@ -340,5 +340,8 @@
 #define __NR_copy_file_range    325
 #define __NR_preadv2            326
 #define __NR_pwritev2           327
+#define __NR_pkey_mprotect      328
+#define __NR_pkey_alloc         329
+#define __NR_pkey_free          330
 
 #endif /* _UAPI__ASM_AVR32_UNISTD_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/kernel/avr32_ksyms.c linux-libre-4.10-rc8-gnu/arch/avr32/kernel/avr32_ksyms.c
--- linux-libre-4.9-gnu/arch/avr32/kernel/avr32_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/kernel/avr32_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/module.h>
 
 #include <asm/checksum.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * GCC functions
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/avr32/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/avr32/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/notifier.h>
 
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ocd.h>
 #include <asm/mmu_context.h>
 #include <linux/kdebug.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/avr32/kernel/signal.c
--- linux-libre-4.9-gnu/arch/avr32/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/unistd.h>
 #include <linux/tracehook.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ucontext.h>
 #include <asm/syscalls.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/kernel/syscall_table.S linux-libre-4.10-rc8-gnu/arch/avr32/kernel/syscall_table.S
--- linux-libre-4.9-gnu/arch/avr32/kernel/syscall_table.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/kernel/syscall_table.S	2017-02-12 16:03:20.000000000 -0500
@@ -341,4 +341,7 @@ sys_call_table:
 	.long __sys_copy_file_range
 	.long __sys_preadv2
 	.long __sys_pwritev2
+	.long sys_pkey_mprotect
+	.long sys_pkey_alloc
+	.long sys_pkey_free /* 330 */
 	.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/kernel/time.c linux-libre-4.10-rc8-gnu/arch/avr32/kernel/time.c
--- linux-libre-4.9-gnu/arch/avr32/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,9 +20,9 @@
 
 static bool disable_cpu_idle_poll;
 
-static cycle_t read_cycle_count(struct clocksource *cs)
+static u64 read_cycle_count(struct clocksource *cs)
 {
-	return (cycle_t)sysreg_read(COUNT);
+	return (u64)sysreg_read(COUNT);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/mach-at32ap/clock.c linux-libre-4.10-rc8-gnu/arch/avr32/mach-at32ap/clock.c
--- linux-libre-4.9-gnu/arch/avr32/mach-at32ap/clock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/mach-at32ap/clock.c	2017-02-12 16:03:20.000000000 -0500
@@ -242,7 +242,7 @@ dump_clock(struct clk *parent, struct cl
 		clk_get_rate(parent));
 	if (parent->dev)
 		seq_printf(r->s, ", for %s", dev_name(parent->dev));
-	seq_printf(r->s, "\n");
+	seq_putc(r->s, '\n');
 
 	/* cost of this scan is small, but not linear... */
 	r->nest = nest + NEST_DELTA;
@@ -261,23 +261,32 @@ static int clk_show(struct seq_file *s,
 	struct clk 	*clk;
 
 	/* show all the power manager registers */
-	seq_printf(s, "MCCTRL  = %8x\n", pm_readl(MCCTRL));
-	seq_printf(s, "CKSEL   = %8x\n", pm_readl(CKSEL));
-	seq_printf(s, "CPUMASK = %8x\n", pm_readl(CPU_MASK));
-	seq_printf(s, "HSBMASK = %8x\n", pm_readl(HSB_MASK));
-	seq_printf(s, "PBAMASK = %8x\n", pm_readl(PBA_MASK));
-	seq_printf(s, "PBBMASK = %8x\n", pm_readl(PBB_MASK));
-	seq_printf(s, "PLL0    = %8x\n", pm_readl(PLL0));
-	seq_printf(s, "PLL1    = %8x\n", pm_readl(PLL1));
-	seq_printf(s, "IMR     = %8x\n", pm_readl(IMR));
+	seq_printf(s,
+		   "MCCTRL  = %8x\n"
+		   "CKSEL   = %8x\n"
+		   "CPUMASK = %8x\n"
+		   "HSBMASK = %8x\n"
+		   "PBAMASK = %8x\n"
+		   "PBBMASK = %8x\n"
+		   "PLL0    = %8x\n"
+		   "PLL1    = %8x\n"
+		   "IMR     = %8x\n",
+		   pm_readl(MCCTRL),
+		   pm_readl(CKSEL),
+		   pm_readl(CPU_MASK),
+		   pm_readl(HSB_MASK),
+		   pm_readl(PBA_MASK),
+		   pm_readl(PBB_MASK),
+		   pm_readl(PLL0),
+		   pm_readl(PLL1),
+		   pm_readl(IMR));
 	for (i = 0; i < 8; i++) {
 		if (i == 5)
 			continue;
 		seq_printf(s, "GCCTRL%d = %8x\n", i, pm_readl(GCCTRL(i)));
 	}
 
-	seq_printf(s, "\n");
-
+	seq_putc(s, '\n');
 	r.s = s;
 	r.nest = 0;
 	/* protected from changes on the list while dumping */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/mach-at32ap/pio.c linux-libre-4.10-rc8-gnu/arch/avr32/mach-at32ap/pio.c
--- linux-libre-4.9-gnu/arch/avr32/mach-at32ap/pio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/mach-at32ap/pio.c	2017-02-12 16:03:20.000000000 -0500
@@ -367,13 +367,13 @@ static void pio_bank_show(struct seq_fil
 			(mask & pdsr) ? "hi" : "lo",
 			(mask & pusr) ? "  " : "up");
 		if (ifsr & mask)
-			seq_printf(s, " deglitch");
+			seq_puts(s, " deglitch");
 		if ((osr & mdsr) & mask)
-			seq_printf(s, " open-drain");
+			seq_puts(s, " open-drain");
 		if (imr & mask)
 			seq_printf(s, " irq-%d edge-both",
 				gpio_to_irq(chip->base + i));
-		seq_printf(s, "\n");
+		seq_putc(s, '\n');
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/mm/cache.c linux-libre-4.10-rc8-gnu/arch/avr32/mm/cache.c
--- linux-libre-4.9-gnu/arch/avr32/mm/cache.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/mm/cache.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <asm/cacheflush.h>
 #include <asm/cachectl.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/syscalls.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/avr32/mm/dma-coherent.c linux-libre-4.10-rc8-gnu/arch/avr32/mm/dma-coherent.c
--- linux-libre-4.9-gnu/arch/avr32/mm/dma-coherent.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/avr32/mm/dma-coherent.c	2017-02-12 16:03:20.000000000 -0500
@@ -146,7 +146,8 @@ static dma_addr_t avr32_dma_map_page(str
 {
 	void *cpu_addr = page_address(page) + offset;
 
-	dma_cache_sync(dev, cpu_addr, size, direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		dma_cache_sync(dev, cpu_addr, size, direction);
 	return virt_to_bus(cpu_addr);
 }
 
@@ -162,6 +163,10 @@ static int avr32_dma_map_sg(struct devic
 
 		sg->dma_address = page_to_bus(sg_page(sg)) + sg->offset;
 		virt = sg_virt(sg);
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		dma_cache_sync(dev, virt, sg->length, direction);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/blackfin/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/blackfin/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,6 @@ generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.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 -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/blackfin/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/blackfin/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -92,7 +92,6 @@ unsigned long get_wchan(struct task_stru
 #define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
 
 #define cpu_relax()    	smp_mb()
-#define cpu_relax_lowlatency() cpu_relax()
 
 /* Get the Silicon Revision of the chip */
 static inline uint32_t __pure bfin_revid(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/kernel/bfin_dma.c linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/bfin_dma.c
--- linux-libre-4.9-gnu/arch/blackfin/kernel/bfin_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/bfin_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <asm/blackfin.h>
 #include <asm/cacheflush.h>
 #include <asm/dma.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/early_printk.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/kernel/dma-mapping.c linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/dma-mapping.c
--- linux-libre-4.9-gnu/arch/blackfin/kernel/dma-mapping.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/dma-mapping.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,6 +118,10 @@ static int bfin_dma_map_sg(struct device
 
 	for_each_sg(sg_list, sg, nents, i) {
 		sg->dma_address = (dma_addr_t) sg_virt(sg);
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		__dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction);
 	}
 
@@ -143,7 +147,9 @@ static dma_addr_t bfin_dma_map_page(stru
 {
 	dma_addr_t handle = (dma_addr_t)(page_address(page) + offset);
 
-	_dma_sync(handle, size, dir);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		_dma_sync(handle, size, dir);
+
 	return handle;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/kernel/kgdb_test.c linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/kgdb_test.c
--- linux-libre-4.9-gnu/arch/blackfin/kernel/kgdb_test.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/kgdb_test.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/proc_fs.h>
 
 #include <asm/current.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/blackfin.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/kernel/module.c linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/module.c
--- linux-libre-4.9-gnu/arch/blackfin/kernel/module.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/module.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/kernel.h>
 #include <asm/dma.h>
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Transfer the section to the L1 memory */
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/kernel/perf_event.c linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/perf_event.c
--- linux-libre-4.9-gnu/arch/blackfin/kernel/perf_event.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/perf_event.c	2017-02-12 16:03:20.000000000 -0500
@@ -475,7 +475,7 @@ static int __init bfin_pmu_init(void)
 
 	ret = perf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
 	if (!ret)
-		cpuhp_setup_state(CPUHP_PERF_BFIN, "PERF_BFIN",
+		cpuhp_setup_state(CPUHP_PERF_BFIN,"perf/bfin:starting",
 				  bfin_pmu_prepare_cpu, NULL);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/blackfin/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -270,7 +270,7 @@ long arch_ptrace(struct task_struct *chi
 			switch (bfin_mem_access_type(addr, to_copy)) {
 			case BFIN_MEM_ACCESS_CORE:
 			case BFIN_MEM_ACCESS_CORE_ONLY:
-				copied = access_process_vm(child, addr, &tmp,
+				copied = ptrace_access_vm(child, addr, &tmp,
 							   to_copy, FOLL_FORCE);
 				if (copied)
 					break;
@@ -323,7 +323,7 @@ long arch_ptrace(struct task_struct *chi
 			switch (bfin_mem_access_type(addr, to_copy)) {
 			case BFIN_MEM_ACCESS_CORE:
 			case BFIN_MEM_ACCESS_CORE_ONLY:
-				copied = access_process_vm(child, addr, &data,
+				copied = ptrace_access_vm(child, addr, &data,
 				                           to_copy,
 							   FOLL_FORCE | FOLL_WRITE);
 				break;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/kernel/time-ts.c linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/time-ts.c
--- linux-libre-4.9-gnu/arch/blackfin/kernel/time-ts.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/kernel/time-ts.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 
 #if defined(CONFIG_CYCLES_CLOCKSOURCE)
 
-static notrace cycle_t bfin_read_cycles(struct clocksource *cs)
+static notrace u64 bfin_read_cycles(struct clocksource *cs)
 {
 #ifdef CONFIG_CPU_FREQ
 	return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
@@ -80,7 +80,7 @@ void __init setup_gptimer0(void)
 	enable_gptimers(TIMER0bit);
 }
 
-static cycle_t bfin_read_gptimer0(struct clocksource *cs)
+static u64 bfin_read_gptimer0(struct clocksource *cs)
 {
 	return bfin_read_TIMER0_COUNTER();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/blackfin/mach-bf561/coreb.c linux-libre-4.10-rc8-gnu/arch/blackfin/mach-bf561/coreb.c
--- linux-libre-4.9-gnu/arch/blackfin/mach-bf561/coreb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/blackfin/mach-bf561/coreb.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,7 @@
 /* Load firmware into Core B on a BF561
  *
+ * Author: Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
+ *
  * Copyright 2004-2009 Analog Devices Inc.
  * Licensed under the GPL-2 or later.
  */
@@ -14,9 +16,9 @@
 
 #include <linux/device.h>
 #include <linux/fs.h>
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/miscdevice.h>
-#include <linux/module.h>
 
 #define CMD_COREB_START		_IO('b', 0)
 #define CMD_COREB_STOP		_IO('b', 1)
@@ -59,8 +61,4 @@ static struct miscdevice coreb_dev = {
 	.name  = "coreb",
 	.fops  = &coreb_fops,
 };
-module_misc_device(coreb_dev);
-
-MODULE_AUTHOR("Bas Vermeulen <bvermeul@blackstar.xs4all.nl>");
-MODULE_DESCRIPTION("BF561 Core B Support");
-MODULE_LICENSE("GPL");
+builtin_misc_device(coreb_dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/c6x/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/c6x/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/c6x/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/c6x/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_C6X_MUTEX_H
-#define _ASM_C6X_MUTEX_H
-
-#include <asm-generic/mutex-null.h>
-
-#endif /* _ASM_C6X_MUTEX_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/c6x/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/c6x/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/c6x/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/c6x/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -121,7 +121,6 @@ extern unsigned long get_wchan(struct ta
 #define KSTK_ESP(task)	(task_pt_regs(task)->sp)
 
 #define cpu_relax()		do { } while (0)
-#define cpu_relax_lowlatency()        cpu_relax()
 
 extern const struct seq_operations cpuinfo_op;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/c6x/kernel/dma.c linux-libre-4.10-rc8-gnu/arch/c6x/kernel/dma.c
--- linux-libre-4.9-gnu/arch/c6x/kernel/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/c6x/kernel/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,14 +42,17 @@ static dma_addr_t c6x_dma_map_page(struc
 {
 	dma_addr_t handle = virt_to_phys(page_address(page) + offset);
 
-	c6x_dma_sync(handle, size, dir);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		c6x_dma_sync(handle, size, dir);
+
 	return handle;
 }
 
 static void c6x_dma_unmap_page(struct device *dev, dma_addr_t handle,
 		size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
-	c6x_dma_sync(handle, size, dir);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		c6x_dma_sync(handle, size, dir);
 }
 
 static int c6x_dma_map_sg(struct device *dev, struct scatterlist *sglist,
@@ -60,7 +63,8 @@ static int c6x_dma_map_sg(struct device
 
 	for_each_sg(sglist, sg, nents, i) {
 		sg->dma_address = sg_phys(sg);
-		c6x_dma_sync(sg->dma_address, sg->length, dir);
+		if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+			c6x_dma_sync(sg->dma_address, sg->length, dir);
 	}
 
 	return nents;
@@ -72,9 +76,11 @@ static void c6x_dma_unmap_sg(struct devi
 	struct scatterlist *sg;
 	int i;
 
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return;
+
 	for_each_sg(sglist, sg, nents, i)
 		c6x_dma_sync(sg_dma_address(sg), sg->length, dir);
-
 }
 
 static void c6x_dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/c6x/kernel/time.c linux-libre-4.10-rc8-gnu/arch/c6x/kernel/time.c
--- linux-libre-4.9-gnu/arch/c6x/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/c6x/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 static u32 sched_clock_multiplier;
 #define SCHED_CLOCK_SHIFT 16
 
-static cycle_t tsc_read(struct clocksource *cs)
+static u64 tsc_read(struct clocksource *cs)
 {
 	return get_cycles();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/c6x/mm/init.c linux-libre-4.10-rc8-gnu/arch/c6x/mm/init.c
--- linux-libre-4.9-gnu/arch/c6x/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/c6x/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/initrd.h>
 
 #include <asm/sections.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * ZERO_PAGE is a special page that is used for zero-initialized
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v10/drivers/eeprom.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/drivers/eeprom.c
--- linux-libre-4.9-gnu/arch/cris/arch-v10/drivers/eeprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/drivers/eeprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "i2c.h"
 
 #define D(x)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v10/drivers/sync_serial.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/drivers/sync_serial.c
--- linux-libre-4.9-gnu/arch/cris/arch-v10/drivers/sync_serial.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/drivers/sync_serial.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <arch/svinto.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sync_serial.h>
 #include <arch/io_interface_mux.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v10/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/cris/arch-v10/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/signal.h>
 #include <linux/security.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v10/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/kernel/signal.c
--- linux-libre-4.9-gnu/arch/cris/arch-v10/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 
 #include <asm/processor.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <arch/system.h>
 
 #define DEBUG_SIG 0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v10/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/kernel/traps.c
--- linux-libre-4.9-gnu/arch/cris/arch-v10/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <arch/sv_addr_ag.h>
 #include <arch/system.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v10/lib/usercopy.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/lib/usercopy.c
--- linux-libre-4.9-gnu/arch/cris/arch-v10/lib/usercopy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/lib/usercopy.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
  * Pieces used from memcpy, originally by Kenny Ranerup long time ago.
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Asm:s have been tweaked (within the domain of correctness) to give
    satisfactory results for "gcc version 2.96 20000427 (experimental)".
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v10/mm/fault.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/mm/fault.c
--- linux-libre-4.9-gnu/arch/cris/arch-v10/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v10/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
  */
 
 #include <linux/mm.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <arch/svinto.h>
 #include <asm/mmu_context.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v32/drivers/cryptocop.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/drivers/cryptocop.c
--- linux-libre-4.9-gnu/arch/cris/arch-v32/drivers/cryptocop.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/drivers/cryptocop.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v32/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/cris/arch-v32/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/signal.h>
 #include <linux/security.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -147,7 +147,7 @@ long arch_ptrace(struct task_struct *chi
 				/* The trampoline page is globally mapped, no page table to traverse.*/
 				tmp = *(unsigned long*)addr;
 			} else {
-				copied = access_process_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE);
+				copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE);
 
 				if (copied != sizeof(tmp))
 					break;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v32/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/kernel/signal.c
--- linux-libre-4.9-gnu/arch/cris/arch-v32/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <arch/hwregs/cpu_vect.h>
 
 extern unsigned long cris_signal_return_page;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v32/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/kernel/traps.c
--- linux-libre-4.9-gnu/arch/cris/arch-v32/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
 
 #include <linux/ptrace.h>
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <hwregs/supp_reg.h>
 #include <hwregs/intr_vect_defs.h>
 #include <asm/irq.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/arch-v32/lib/usercopy.c linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/lib/usercopy.c
--- linux-libre-4.9-gnu/arch/cris/arch-v32/lib/usercopy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/arch-v32/lib/usercopy.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
  * Pieces used from memcpy, originally by Kenny Ranerup long time ago.
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Asm:s have been tweaked (within the domain of correctness) to give
    satisfactory results for "gcc version 3.2.1 Axis release R53/1.53-v32".
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/boot/compressed/Makefile linux-libre-4.10-rc8-gnu/arch/cris/boot/compressed/Makefile
--- linux-libre-4.9-gnu/arch/cris/boot/compressed/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/boot/compressed/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,9 +2,6 @@
 # arch/cris/boot/compressed/Makefile
 #
 
-asflags-y += $(LINUXINCLUDE)
-ccflags-y += -O2 $(LINUXINCLUDE)
-
 # asflags-$(CONFIG_ETRAX_ARCH_V32) += -I$(srctree)/include/asm/mach \
 # 				    -I$(srctree)/include/asm/arch
 # ccflags-$(CONFIG_ETRAX_ARCH_V32) += -O2 -I$(srctree)/include/asm/mach
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/boot/rescue/Makefile linux-libre-4.10-rc8-gnu/arch/cris/boot/rescue/Makefile
--- linux-libre-4.9-gnu/arch/cris/boot/rescue/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/boot/rescue/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -8,8 +8,8 @@
 # asflags-y += -I $(srctree)/include/asm/arch/mach/ -I $(srctree)/include/asm/arch
 # LD = gcc-cris -mlinux -march=v32 -nostdlib
 
-asflags-y += $(LINUXINCLUDE)
-ccflags-y += -O2 $(LINUXINCLUDE)
+ifdef CONFIG_ETRAX_AXISFLASHMAP
+
 arch-$(CONFIG_ETRAX_ARCH_V10) = v10
 arch-$(CONFIG_ETRAX_ARCH_V32) = v32
 
@@ -28,6 +28,11 @@ $(obj)/rescue.bin: $(obj)/rescue.o FORCE
 	$(call if_changed,objcopy)
 	cp -p $(obj)/rescue.bin $(objtree)
 
+else
+$(obj)/rescue.bin:
+
+endif
+
 $(obj)/testrescue.bin: $(obj)/testrescue.o
 	$(OBJCOPY) $(OBJCOPYFLAGS) $(obj)/testrescue.o tr.bin
 # Pad it to 784 bytes
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/cris/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/cris/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/cris/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/cris/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -63,7 +63,6 @@ static inline void release_thread(struct
 #define init_stack      (init_thread_union.stack)
 
 #define cpu_relax()     barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 void default_idle(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/kernel/crisksyms.c linux-libre-4.10-rc8-gnu/arch/cris/kernel/crisksyms.c
--- linux-libre-4.9-gnu/arch/cris/kernel/crisksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/kernel/crisksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/tty.h>
 
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
 #include <asm/delay.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/kernel/process.c linux-libre-4.10-rc8-gnu/arch/cris/kernel/process.c
--- linux-libre-4.9-gnu/arch/cris/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <linux/atomic.h>
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/kernel/profile.c linux-libre-4.10-rc8-gnu/arch/cris/kernel/profile.c
--- linux-libre-4.9-gnu/arch/cris/kernel/profile.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/kernel/profile.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define SAMPLE_BUFFER_SIZE 8192
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/cris/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/cris/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/user.h>
 #include <linux/tracehook.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/kernel/sys_cris.c linux-libre-4.10-rc8-gnu/arch/cris/kernel/sys_cris.c
--- linux-libre-4.9-gnu/arch/cris/kernel/sys_cris.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/kernel/sys_cris.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/file.h>
 #include <linux/ipc.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/segment.h>
 
 asmlinkage long
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/cris/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/cris/kernel/traps.c
--- linux-libre-4.9-gnu/arch/cris/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/cris/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #endif
 
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <arch/system.h>
 
 extern void arch_enable_nmi(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/include/asm/atomic.h linux-libre-4.10-rc8-gnu/arch/frv/include/asm/atomic.h
--- linux-libre-4.9-gnu/arch/frv/include/asm/atomic.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/include/asm/atomic.h	2017-02-12 16:03:20.000000000 -0500
@@ -139,7 +139,7 @@ static inline void atomic64_dec(atomic64
 #define atomic64_sub_and_test(i,v)	(atomic64_sub_return((i), (v)) == 0)
 #define atomic64_dec_and_test(v)	(atomic64_dec_return((v)) == 0)
 #define atomic64_inc_and_test(v)	(atomic64_inc_return((v)) == 0)
-
+#define atomic64_inc_not_zero(v)	atomic64_add_unless((v), 1, 0)
 
 #define atomic_cmpxchg(v, old, new)	(cmpxchg(&(v)->counter, old, new))
 #define atomic_xchg(v, new)		(xchg(&(v)->counter, new))
@@ -161,6 +161,39 @@ static __inline__ int __atomic_add_unles
 	return c;
 }
 
+static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)
+{
+	long long c, old;
+
+	c = atomic64_read(v);
+	for (;;) {
+		if (unlikely(c == u))
+			break;
+		old = atomic64_cmpxchg(v, c, c + i);
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+	return c != u;
+}
+
+static inline long long atomic64_dec_if_positive(atomic64_t *v)
+{
+	long long c, old, dec;
+
+	c = atomic64_read(v);
+	for (;;) {
+		dec = c - 1;
+		if (unlikely(dec < 0))
+			break;
+		old = atomic64_cmpxchg((v), c, dec);
+		if (likely(old == c))
+			break;
+		c = old;
+	}
+		return dec;
+}
+
 #define ATOMIC_OP(op)							\
 static inline int atomic_fetch_##op(int i, atomic_t *v)			\
 {									\
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/include/asm/futex.h linux-libre-4.10-rc8-gnu/arch/frv/include/asm/futex.h
--- linux-libre-4.9-gnu/arch/frv/include/asm/futex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/include/asm/futex.h	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 
 #include <linux/futex.h>
 #include <asm/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/frv/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/frv/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/frv/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/frv/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -107,7 +107,6 @@ unsigned long get_wchan(struct task_stru
 #define	KSTK_ESP(tsk)	((tsk)->thread.frame0->sp)
 
 #define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 /* data cache prefetch */
 #define ARCH_HAS_PREFETCH
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/frv/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/frv/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,5 +90,7 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _ASM_SOCKET_H */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/irq.c
--- linux-libre-4.9-gnu/arch/frv/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm/smp.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/delay.h>
 #include <asm/irq.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/pm.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/pm.c
--- linux-libre-4.9-gnu/arch/frv/kernel/pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/sysctl.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/mb86943a.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/pm-mb93093.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/pm-mb93093.c
--- linux-libre-4.9-gnu/arch/frv/kernel/pm-mb93093.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/pm-mb93093.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/sysctl.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/mb86943a.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/process.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/process.c
--- linux-libre-4.9-gnu/arch/frv/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/rcupdate.h>
 
 #include <asm/asm-offsets.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/frv/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/elf.h>
 #include <linux/tracehook.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/signal.c
--- linux-libre-4.9-gnu/arch/frv/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/personality.h>
 #include <linux/tracehook.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 
 #define DEBUG_SIG 0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/sysctl.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/sysctl.c
--- linux-libre-4.9-gnu/arch/frv/kernel/sysctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/sysctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static const char frv_cache_wback[] = "wback";
 static const char frv_cache_wthru[] = "wthru";
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/sys_frv.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/sys_frv.c
--- linux-libre-4.9-gnu/arch/frv/kernel/sys_frv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/sys_frv.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/ipc.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
 			  unsigned long prot, unsigned long flags,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/traps.c
--- linux-libre-4.9-gnu/arch/frv/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/siginfo.h>
 #include <asm/unaligned.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/kernel/uaccess.c linux-libre-4.10-rc8-gnu/arch/frv/kernel/uaccess.c
--- linux-libre-4.9-gnu/arch/frv/kernel/uaccess.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/kernel/uaccess.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 
 #include <linux/mm.h>
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*****************************************************************************/
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/mb93090-mb00/pci-dma.c linux-libre-4.10-rc8-gnu/arch/frv/mb93090-mb00/pci-dma.c
--- linux-libre-4.9-gnu/arch/frv/mb93090-mb00/pci-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/mb93090-mb00/pci-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,13 +40,16 @@ static int frv_dma_map_sg(struct device
 		int nents, enum dma_data_direction direction,
 		unsigned long attrs)
 {
+	struct scatterlist *sg;
 	unsigned long dampr2;
 	void *vaddr;
 	int i;
-	struct scatterlist *sg;
 
 	BUG_ON(direction == DMA_NONE);
 
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return nents;
+
 	dampr2 = __get_DAMPR(2);
 
 	for_each_sg(sglist, sg, nents, i) {
@@ -70,7 +73,9 @@ static dma_addr_t frv_dma_map_page(struc
 		unsigned long offset, size_t size,
 		enum dma_data_direction direction, unsigned long attrs)
 {
-	flush_dcache_page(page);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		flush_dcache_page(page);
+
 	return (dma_addr_t) page_to_phys(page) + offset;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c linux-libre-4.10-rc8-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c
--- linux-libre-4.9-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/mb93090-mb00/pci-dma-nommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -109,16 +109,19 @@ static int frv_dma_map_sg(struct device
 		int nents, enum dma_data_direction direction,
 		unsigned long attrs)
 {
-	int i;
 	struct scatterlist *sg;
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return nents;
 
 	for_each_sg(sglist, sg, nents, i) {
 		frv_cache_wback_inv(sg_dma_address(sg),
 				    sg_dma_address(sg) + sg_dma_len(sg));
 	}
 
-	BUG_ON(direction == DMA_NONE);
-
 	return nents;
 }
 
@@ -127,7 +130,10 @@ static dma_addr_t frv_dma_map_page(struc
 		enum dma_data_direction direction, unsigned long attrs)
 {
 	BUG_ON(direction == DMA_NONE);
-	flush_dcache_page(page);
+
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		flush_dcache_page(page);
+
 	return (dma_addr_t) page_to_phys(page) + offset;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/mm/dma-alloc.c linux-libre-4.10-rc8-gnu/arch/frv/mm/dma-alloc.c
--- linux-libre-4.9-gnu/arch/frv/mm/dma-alloc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/mm/dma-alloc.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/smp.h>
 
 static int map_page(unsigned long va, unsigned long pa, pgprot_t prot)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/frv/mm/extable.c linux-libre-4.10-rc8-gnu/arch/frv/mm/extable.c
--- linux-libre-4.9-gnu/arch/frv/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/frv/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
 
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler;
 extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/h8300/boot/compressed/misc.c linux-libre-4.10-rc8-gnu/arch/h8300/boot/compressed/misc.c
--- linux-libre-4.9-gnu/arch/h8300/boot/compressed/misc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/h8300/boot/compressed/misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
  * Adapted for h8300 by Yoshinori Sato 2006
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * gzip declarations
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/h8300/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/h8300/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/h8300/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/h8300/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/h8300/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/h8300/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/h8300/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/h8300/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -127,7 +127,6 @@ unsigned long get_wchan(struct task_stru
 #define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
 
 #define cpu_relax()    barrier()
-#define cpu_relax_lowlatency()	cpu_relax()
 
 #define HARD_RESET_NOW() ({		\
 	local_irq_disable();		\
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/h8300/kernel/process.c linux-libre-4.10-rc8-gnu/arch/h8300/kernel/process.c
--- linux-libre-4.9-gnu/arch/h8300/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/h8300/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <linux/slab.h>
 #include <linux/rcupdate.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/traps.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/h8300/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/h8300/kernel/signal.c
--- linux-libre-4.9-gnu/arch/h8300/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/h8300/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@
 #include <linux/tracehook.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/traps.h>
 #include <asm/ucontext.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/hexagon/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/hexagon/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-/*
- * 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 -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/hexagon/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/hexagon/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,6 @@ struct thread_struct {
 }
 
 #define cpu_relax() __vmyield()
-#define cpu_relax_lowlatency() cpu_relax()
 
 /*
  * Decides where the kernel will search for a free chunk of vm space during
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/kernel/dma.c linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/dma.c
--- linux-libre-4.9-gnu/arch/hexagon/kernel/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -119,6 +119,9 @@ static int hexagon_map_sg(struct device
 
 		s->dma_length = s->length;
 
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		flush_dcache_range(dma_addr_to_virt(s->dma_address),
 				   dma_addr_to_virt(s->dma_address + s->length));
 	}
@@ -180,7 +183,8 @@ static dma_addr_t hexagon_map_page(struc
 	if (!check_addr("map_single", dev, bus, size))
 		return bad_dma_address;
 
-	dma_sync(dma_addr_to_virt(bus), size, dir);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		dma_sync(dma_addr_to_virt(bus), size, dir);
 
 	return bus;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/kernel/hexagon_ksyms.c linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/hexagon_ksyms.c
--- linux-libre-4.9-gnu/arch/hexagon/kernel/hexagon_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/hexagon_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/dma-mapping.h>
 #include <asm/hexagon_vm.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Additional functions */
 EXPORT_SYMBOL(__clear_user_hexagon);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/signal.c
--- linux-libre-4.9-gnu/arch/hexagon/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <asm/registers.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ucontext.h>
 #include <asm/cacheflush.h>
 #include <asm/signal.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/kernel/time.c linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/time.c
--- linux-libre-4.9-gnu/arch/hexagon/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,9 +72,9 @@ struct adsp_hw_timer_struct {
 /*  Look for "TCX0" for related constants.  */
 static __iomem struct adsp_hw_timer_struct *rtos_timer;
 
-static cycle_t timer_get_cycles(struct clocksource *cs)
+static u64 timer_get_cycles(struct clocksource *cs)
 {
-	return (cycle_t) __vmgettime();
+	return (u64) __vmgettime();
 }
 
 static struct clocksource hexagon_clocksource = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/mm/uaccess.c linux-libre-4.10-rc8-gnu/arch/hexagon/mm/uaccess.c
--- linux-libre-4.9-gnu/arch/hexagon/mm/uaccess.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/mm/uaccess.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
  * we implement here as subroutines.
  */
 #include <linux/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/hexagon/mm/vm_fault.c linux-libre-4.10-rc8-gnu/arch/hexagon/mm/vm_fault.c
--- linux-libre-4.9-gnu/arch/hexagon/mm/vm_fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/hexagon/mm/vm_fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/mm.h>
 #include <linux/signal.h>
 #include <linux/module.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/ia64/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,90 +0,0 @@
-/*
- * ia64 implementation of the mutex fastpath.
- *
- * Copyright (C) 2006 Ken Chen <kenneth.w.chen@intel.com>
- *
- */
-
-#ifndef _ASM_MUTEX_H
-#define _ASM_MUTEX_H
-
-/**
- *  __mutex_fastpath_lock - try to take the lock by moving the count
- *                          from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if
- * it wasn't 1 originally. This function MUST leave the value lower than
- * 1 even when the "1" assertion wasn't true.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
-		fail_fn(count);
-}
-
-/**
- *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
- *                                 from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
-	if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
-		return -1;
-	return 0;
-}
-
-/**
- *  __mutex_fastpath_unlock - try to promote the count from 0 to 1
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 0
- *
- * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value to
- * 1, or to set it to a value lower than 1.
- *
- * If the implementation sets it to a value of lower than 1, then the
- * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
- * to return 0 otherwise.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	int ret = ia64_fetchadd4_rel(count, 1);
-	if (unlikely(ret < 0))
-		fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock()		1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- *  @count: pointer of type atomic_t
- *  @fail_fn: fallback function
- *
- * Change the count from 1 to a value lower than 1, and return 0 (failure)
- * if it wasn't 1 originally, or return 1 (success) otherwise. This function
- * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
- * Additionally, if the value was < 0 originally, this function must not leave
- * it to 0 on failure.
- *
- * If the architecture has no effective trylock variant, it should call the
- * <fail_fn> spinlock-based trylock variant unconditionally.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
-	if (atomic_read(count) == 1 && cmpxchg_acq(count, 1, 0) == 1)
-		return 1;
-	return 0;
-}
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/include/asm/numa.h linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/numa.h
--- linux-libre-4.9-gnu/arch/ia64/include/asm/numa.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/numa.h	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,8 @@ extern int paddr_to_nid(unsigned long pa
 
 #define local_nodeid (cpu_to_node_map[smp_processor_id()])
 
+#define numa_off     0
+
 extern void map_cpu_to_node(int cpu, int nid);
 extern void unmap_cpu_from_node(int cpu, int nid);
 extern void numa_clear_node(int cpu);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/ia64/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -547,7 +547,6 @@ ia64_eoi (void)
 }
 
 #define cpu_relax()	ia64_hint(ia64_hint_pause)
-#define cpu_relax_lowlatency() cpu_relax()
 
 static inline int
 ia64_get_irr(unsigned int vector)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/include/asm/tlb.h linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/tlb.h
--- linux-libre-4.9-gnu/arch/ia64/include/asm/tlb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/include/asm/tlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -207,15 +207,15 @@ tlb_finish_mmu(struct mmu_gather *tlb, u
  */
 static inline bool __tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
-	if (tlb->nr == tlb->max)
-		return true;
-
 	tlb->need_flush = 1;
 
 	if (!tlb->nr && tlb->pages == tlb->local)
 		__tlb_alloc_page(tlb);
 
 	tlb->pages[tlb->nr++] = page;
+	VM_WARN_ON(tlb->nr > tlb->max);
+	if (tlb->nr == tlb->max)
+		return true;
 	return false;
 }
 
@@ -236,10 +236,8 @@ static inline void tlb_flush_mmu(struct
 
 static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 {
-	if (__tlb_remove_page(tlb, page)) {
+	if (__tlb_remove_page(tlb, page))
 		tlb_flush_mmu(tlb);
-		__tlb_remove_page(tlb, page);
-	}
 }
 
 static inline bool __tlb_remove_page_size(struct mmu_gather *tlb,
@@ -248,12 +246,6 @@ static inline bool __tlb_remove_page_siz
 	return __tlb_remove_page(tlb, page);
 }
 
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
-					 struct page *page)
-{
-	return __tlb_remove_page(tlb, page);
-}
-
 static inline void tlb_remove_page_size(struct mmu_gather *tlb,
 					struct page *page, int page_size)
 {
@@ -283,6 +275,15 @@ do {							\
 	__tlb_remove_tlb_entry(tlb, ptep, addr);	\
 } while (0)
 
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	\
+	tlb_remove_tlb_entry(tlb, ptep, address)
+
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+						     unsigned int page_size)
+{
+}
+
 #define pte_free_tlb(tlb, ptep, address)		\
 do {							\
 	tlb->need_flush = 1;				\
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/ia64/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/ia64/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -99,4 +99,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _ASM_IA64_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/brl_emu.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/brl_emu.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/brl_emu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/brl_emu.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/processor.h>
 
 extern char ia64_set_b1, ia64_set_b2, ia64_set_b3, ia64_set_b4, ia64_set_b5;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/crash_dump.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/crash_dump.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/crash_dump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/crash_dump.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/crash_dump.h>
 
 #include <asm/page.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /**
  * copy_oldmem_page - copy one page from "oldmem"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/cyclone.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/cyclone.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/cyclone.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/cyclone.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,9 +21,9 @@ void __init cyclone_setup(void)
 
 static void __iomem *cyclone_mc;
 
-static cycle_t read_cyclone(struct clocksource *cs)
+static u64 read_cyclone(struct clocksource *cs)
 {
-	return (cycle_t)readq((void __iomem *)cyclone_mc);
+	return (u64)readq((void __iomem *)cyclone_mc);
 }
 
 static struct clocksource clocksource_cyclone = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/err_inject.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/err_inject.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/err_inject.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/err_inject.c	2017-02-12 16:03:20.000000000 -0500
@@ -224,85 +224,45 @@ static struct attribute_group err_inject
 	.name = "err_inject"
 };
 /* Add/Remove err_inject interface for CPU device */
-static int err_inject_add_dev(struct device *sys_dev)
+static int err_inject_add_dev(unsigned int cpu)
 {
+	struct device *sys_dev = get_cpu_device(cpu);
+
 	return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group);
 }
 
-static int err_inject_remove_dev(struct device *sys_dev)
+static int err_inject_remove_dev(unsigned int cpu)
 {
+	struct device *sys_dev = get_cpu_device(cpu);
+
 	sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
 	return 0;
 }
-static int err_inject_cpu_callback(struct notifier_block *nfb,
-		unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long)hcpu;
-	struct device *sys_dev;
 
-	sys_dev = get_cpu_device(cpu);
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		err_inject_add_dev(sys_dev);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		err_inject_remove_dev(sys_dev);
-		break;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block err_inject_cpu_notifier =
-{
-	.notifier_call = err_inject_cpu_callback,
-};
+static enum cpuhp_state hp_online;
 
-static int __init
-err_inject_init(void)
+static int __init err_inject_init(void)
 {
-	int i;
-
+	int ret;
 #ifdef ERR_INJ_DEBUG
 	printk(KERN_INFO "Enter error injection driver.\n");
 #endif
 
-	cpu_notifier_register_begin();
-
-	for_each_online_cpu(i) {
-		err_inject_cpu_callback(&err_inject_cpu_notifier, CPU_ONLINE,
-				(void *)(long)i);
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/err_inj:online",
+				err_inject_add_dev, err_inject_remove_dev);
+	if (ret >= 0) {
+		hp_online = ret;
+		ret = 0;
 	}
-
-	__register_hotcpu_notifier(&err_inject_cpu_notifier);
-
-	cpu_notifier_register_done();
-
-	return 0;
+	return ret;
 }
 
-static void __exit
-err_inject_exit(void)
+static void __exit err_inject_exit(void)
 {
-	int i;
-	struct device *sys_dev;
-
 #ifdef ERR_INJ_DEBUG
 	printk(KERN_INFO "Exit error injection driver.\n");
 #endif
-
-	cpu_notifier_register_begin();
-
-	for_each_online_cpu(i) {
-		sys_dev = get_cpu_device(i);
-		sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group);
-	}
-
-	__unregister_hotcpu_notifier(&err_inject_cpu_notifier);
-
-	cpu_notifier_register_done();
+	cpuhp_remove_state(hp_online);
 }
 
 module_init(err_inject_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/fsyscall_gtod_data.h linux-libre-4.10-rc8-gnu/arch/ia64/kernel/fsyscall_gtod_data.h
--- linux-libre-4.9-gnu/arch/ia64/kernel/fsyscall_gtod_data.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/fsyscall_gtod_data.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,15 +9,15 @@ struct fsyscall_gtod_data_t {
 	seqcount_t	seq;
 	struct timespec	wall_time;
 	struct timespec monotonic_time;
-	cycle_t		clk_mask;
+	u64		clk_mask;
 	u32		clk_mult;
 	u32		clk_shift;
 	void		*clk_fsys_mmio;
-	cycle_t		clk_cycle_last;
+	u64		clk_cycle_last;
 } ____cacheline_aligned;
 
 struct itc_jitter_data_t {
 	int		itc_jitter;
-	cycle_t		itc_lastcycle;
+	u64		itc_lastcycle;
 } ____cacheline_aligned;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/init_task.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/init_task.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/init_task.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/init_task.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/init_task.h>
 #include <linux/mqueue.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 
 static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/irq.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
  */
 
 #include <asm/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/kprobes.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/kprobes.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/kprobes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/kprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/sections.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 extern void jprobe_inst_return(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/palinfo.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/palinfo.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/palinfo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/palinfo.c	2017-02-12 16:03:20.000000000 -0500
@@ -932,8 +932,7 @@ static const struct file_operations proc
 	.release	= single_release,
 };
 
-static void
-create_palinfo_proc_entries(unsigned int cpu)
+static int palinfo_add_proc(unsigned int cpu)
 {
 	pal_func_cpu_u_t f;
 	struct proc_dir_entry *cpu_dir;
@@ -943,7 +942,7 @@ create_palinfo_proc_entries(unsigned int
 
 	cpu_dir = proc_mkdir(cpustr, palinfo_dir);
 	if (!cpu_dir)
-		return;
+		return -EINVAL;
 
 	f.req_cpu = cpu;
 
@@ -952,42 +951,21 @@ create_palinfo_proc_entries(unsigned int
 		proc_create_data(palinfo_entries[j].name, 0, cpu_dir,
 				 &proc_palinfo_fops, (void *)f.value);
 	}
+	return 0;
 }
 
-static void
-remove_palinfo_proc_entries(unsigned int hcpu)
+static int palinfo_del_proc(unsigned int hcpu)
 {
 	char cpustr[3+4+1];	/* cpu numbers are up to 4095 on itanic */
+
 	sprintf(cpustr, "cpu%d", hcpu);
 	remove_proc_subtree(cpustr, palinfo_dir);
+	return 0;
 }
 
-static int palinfo_cpu_callback(struct notifier_block *nfb,
-					unsigned long action, void *hcpu)
-{
-	unsigned int hotcpu = (unsigned long)hcpu;
-
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		create_palinfo_proc_entries(hotcpu);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		remove_palinfo_proc_entries(hotcpu);
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata palinfo_cpu_notifier =
-{
-	.notifier_call = palinfo_cpu_callback,
-	.priority = 0,
-};
+static enum cpuhp_state hp_online;
 
-static int __init
-palinfo_init(void)
+static int __init palinfo_init(void)
 {
 	int i = 0;
 
@@ -996,25 +974,19 @@ palinfo_init(void)
 	if (!palinfo_dir)
 		return -ENOMEM;
 
-	cpu_notifier_register_begin();
-
-	/* Create palinfo dirs in /proc for all online cpus */
-	for_each_online_cpu(i) {
-		create_palinfo_proc_entries(i);
+	i = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/palinfo:online",
+			      palinfo_add_proc, palinfo_del_proc);
+	if (i < 0) {
+		remove_proc_subtree("pal", NULL);
+		return i;
 	}
-
-	/* Register for future delivery via notify registration */
-	__register_hotcpu_notifier(&palinfo_cpu_notifier);
-
-	cpu_notifier_register_done();
-
+	hp_online = i;
 	return 0;
 }
 
-static void __exit
-palinfo_exit(void)
+static void __exit palinfo_exit(void)
 {
-	unregister_hotcpu_notifier(&palinfo_cpu_notifier);
+	cpuhp_remove_state(hp_online);
 	remove_proc_subtree("pal", NULL);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/perfmon.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/perfmon.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/perfmon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/perfmon.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,7 +50,7 @@
 #include <asm/perfmon.h>
 #include <asm/processor.h>
 #include <asm/signal.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/delay.h>
 
 #ifdef CONFIG_PERFMON
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/process.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/process.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@
 #include <asm/sal.h>
 #include <asm/switch_to.h>
 #include <asm/tlbflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unwind.h>
 #include <asm/user.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <asm/processor.h>
 #include <asm/ptrace_offsets.h>
 #include <asm/rse.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unwind.h>
 #ifdef CONFIG_PERFMON
 #include <asm/perfmon.h>
@@ -1159,7 +1159,7 @@ arch_ptrace (struct task_struct *child,
 	case PTRACE_PEEKTEXT:
 	case PTRACE_PEEKDATA:
 		/* read word at location addr */
-		if (access_process_vm(child, addr, &data, sizeof(data),
+		if (ptrace_access_vm(child, addr, &data, sizeof(data),
 				FOLL_FORCE)
 		    != sizeof(data))
 			return -EIO;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/salinfo.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/salinfo.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/salinfo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/salinfo.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 #include <linux/semaphore.h>
 
 #include <asm/sal.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 MODULE_AUTHOR("Jesse Barnes <jbarnes@sgi.com>");
 MODULE_DESCRIPTION("/proc interface to IA-64 SAL features");
@@ -550,52 +550,40 @@ static const struct file_operations sali
 	.llseek  = default_llseek,
 };
 
-static int
-salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+static int salinfo_cpu_online(unsigned int cpu)
 {
-	unsigned int i, cpu = (unsigned long)hcpu;
-	unsigned long flags;
+	unsigned int i, end = ARRAY_SIZE(salinfo_data);
 	struct salinfo_data *data;
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		spin_lock_irqsave(&data_saved_lock, flags);
-		for (i = 0, data = salinfo_data;
-		     i < ARRAY_SIZE(salinfo_data);
-		     ++i, ++data) {
-			cpumask_set_cpu(cpu, &data->cpu_event);
-			wake_up_interruptible(&data->read_wait);
-		}
-		spin_unlock_irqrestore(&data_saved_lock, flags);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		spin_lock_irqsave(&data_saved_lock, flags);
-		for (i = 0, data = salinfo_data;
-		     i < ARRAY_SIZE(salinfo_data);
-		     ++i, ++data) {
-			struct salinfo_data_saved *data_saved;
-			int j;
-			for (j = ARRAY_SIZE(data->data_saved) - 1, data_saved = data->data_saved + j;
-			     j >= 0;
-			     --j, --data_saved) {
-				if (data_saved->buffer && data_saved->cpu == cpu) {
-					shift1_data_saved(data, j);
-				}
-			}
-			cpumask_clear_cpu(cpu, &data->cpu_event);
-		}
-		spin_unlock_irqrestore(&data_saved_lock, flags);
-		break;
+
+	spin_lock_irq(&data_saved_lock);
+	for (i = 0, data = salinfo_data; i < end; ++i, ++data) {
+		cpumask_set_cpu(cpu, &data->cpu_event);
+		wake_up_interruptible(&data->read_wait);
 	}
-	return NOTIFY_OK;
+	spin_unlock_irq(&data_saved_lock);
+	return 0;
 }
 
-static struct notifier_block salinfo_cpu_notifier =
+static int salinfo_cpu_pre_down(unsigned int cpu)
 {
-	.notifier_call = salinfo_cpu_callback,
-	.priority = 0,
-};
+	unsigned int i, end = ARRAY_SIZE(salinfo_data);
+	struct salinfo_data *data;
+
+	spin_lock_irq(&data_saved_lock);
+	for (i = 0, data = salinfo_data; i < end; ++i, ++data) {
+		struct salinfo_data_saved *data_saved;
+		int j = ARRAY_SIZE(data->data_saved) - 1;
+
+		for (data_saved = data->data_saved + j; j >= 0;
+		     --j, --data_saved) {
+			if (data_saved->buffer && data_saved->cpu == cpu)
+				shift1_data_saved(data, j);
+		}
+		cpumask_clear_cpu(cpu, &data->cpu_event);
+	}
+	spin_unlock_irq(&data_saved_lock);
+	return 0;
+}
 
 static int __init
 salinfo_init(void)
@@ -604,7 +592,7 @@ salinfo_init(void)
 	struct proc_dir_entry **sdir = salinfo_proc_entries; /* keeps track of every entry */
 	struct proc_dir_entry *dir, *entry;
 	struct salinfo_data *data;
-	int i, j;
+	int i;
 
 	salinfo_dir = proc_mkdir("sal", NULL);
 	if (!salinfo_dir)
@@ -617,8 +605,6 @@ salinfo_init(void)
 					   (void *)salinfo_entries[i].feature);
 	}
 
-	cpu_notifier_register_begin();
-
 	for (i = 0; i < ARRAY_SIZE(salinfo_log_name); i++) {
 		data = salinfo_data + i;
 		data->type = i;
@@ -639,10 +625,6 @@ salinfo_init(void)
 			continue;
 		*sdir++ = entry;
 
-		/* we missed any events before now */
-		for_each_online_cpu(j)
-			cpumask_set_cpu(j, &data->cpu_event);
-
 		*sdir++ = dir;
 	}
 
@@ -653,10 +635,9 @@ salinfo_init(void)
 	salinfo_timer.function = &salinfo_timeout;
 	add_timer(&salinfo_timer);
 
-	__register_hotcpu_notifier(&salinfo_cpu_notifier);
-
-	cpu_notifier_register_done();
-
+	i = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/salinfo:online",
+			      salinfo_cpu_online, salinfo_cpu_pre_down);
+	WARN_ON(i < 0);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/signal.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/wait.h>
 
 #include <asm/intrinsics.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/rse.h>
 #include <asm/sigcontext.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/sys_ia64.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/sys_ia64.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/sys_ia64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/sys_ia64.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/hugetlb.h>
 
 #include <asm/shmparam.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 unsigned long
 arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/time.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/time.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 
 #include "fsyscall_gtod_data.h"
 
-static cycle_t itc_get_cycles(struct clocksource *cs);
+static u64 itc_get_cycles(struct clocksource *cs);
 
 struct fsyscall_gtod_data_t fsyscall_gtod_data;
 
@@ -68,7 +68,7 @@ void vtime_account_user(struct task_stru
 
 	if (ti->ac_utime) {
 		delta_utime = cycle_to_cputime(ti->ac_utime);
-		account_user_time(tsk, delta_utime, delta_utime);
+		account_user_time(tsk, delta_utime);
 		ti->ac_utime = 0;
 	}
 }
@@ -112,7 +112,7 @@ void vtime_account_system(struct task_st
 {
 	cputime_t delta = vtime_delta(tsk);
 
-	account_system_time(tsk, 0, delta, delta);
+	account_system_time(tsk, 0, delta);
 }
 EXPORT_SYMBOL_GPL(vtime_account_system);
 
@@ -323,7 +323,7 @@ void ia64_init_itm(void)
 	}
 }
 
-static cycle_t itc_get_cycles(struct clocksource *cs)
+static u64 itc_get_cycles(struct clocksource *cs)
 {
 	unsigned long lcycle, now, ret;
 
@@ -397,7 +397,7 @@ void update_vsyscall_tz(void)
 }
 
 void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
-			 struct clocksource *c, u32 mult, cycle_t cycle_last)
+			 struct clocksource *c, u32 mult, u64 cycle_last)
 {
 	write_seqcount_begin(&fsyscall_gtod_data.seq);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/topology.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/topology.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/topology.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/topology.c	2017-02-12 16:03:20.000000000 -0500
@@ -349,9 +349,9 @@ static int cpu_cache_sysfs_init(unsigned
 }
 
 /* Add cache interface for CPU device */
-static int cache_add_dev(struct device *sys_dev)
+static int cache_add_dev(unsigned int cpu)
 {
-	unsigned int cpu = sys_dev->id;
+	struct device *sys_dev = get_cpu_device(cpu);
 	unsigned long i, j;
 	struct cache_info *this_object;
 	int retval = 0;
@@ -399,9 +399,8 @@ static int cache_add_dev(struct device *
 }
 
 /* Remove cache interface for CPU device */
-static int cache_remove_dev(struct device *sys_dev)
+static int cache_remove_dev(unsigned int cpu)
 {
-	unsigned int cpu = sys_dev->id;
 	unsigned long i;
 
 	for (i = 0; i < all_cpu_cache_info[cpu].num_cache_leaves; i++)
@@ -419,52 +418,13 @@ static int cache_remove_dev(struct devic
 	return 0;
 }
 
-/*
- * When a cpu is hot-plugged, do a check and initiate
- * cache kobject if necessary
- */
-static int cache_cpu_callback(struct notifier_block *nfb,
-		unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long)hcpu;
-	struct device *sys_dev;
-
-	sys_dev = get_cpu_device(cpu);
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		cache_add_dev(sys_dev);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		cache_remove_dev(sys_dev);
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block cache_cpu_notifier =
-{
-	.notifier_call = cache_cpu_callback
-};
-
 static int __init cache_sysfs_init(void)
 {
-	int i;
-
-	cpu_notifier_register_begin();
-
-	for_each_online_cpu(i) {
-		struct device *sys_dev = get_cpu_device((unsigned int)i);
-		cache_add_dev(sys_dev);
-	}
-
-	__register_hotcpu_notifier(&cache_cpu_notifier);
-
-	cpu_notifier_register_done();
+	int ret;
 
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ia64/topology:online",
+				cache_add_dev, cache_remove_dev);
+	WARN_ON(ret < 0);
 	return 0;
 }
-
 device_initcall(cache_sysfs_init);
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/traps.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <asm/fpswa.h>
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/setup.h>
 
 fpswa_interface_t *fpswa_interface;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/unaligned.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/unaligned.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/unaligned.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/unaligned.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
 #include <asm/rse.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
 extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/kernel/unwind.c linux-libre-4.10-rc8-gnu/arch/ia64/kernel/unwind.c
--- linux-libre-4.9-gnu/arch/ia64/kernel/unwind.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/kernel/unwind.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@
 #include <asm/ptrace_offsets.h>
 #include <asm/rse.h>
 #include <asm/sections.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "entry.h"
 #include "unwind_i.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/lib/csum_partial_copy.c linux-libre-4.10-rc8-gnu/arch/ia64/lib/csum_partial_copy.c
--- linux-libre-4.9-gnu/arch/ia64/lib/csum_partial_copy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/lib/csum_partial_copy.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * XXX Fixme: those 2 inlines are meant for debugging and will go away
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/mm/extable.c linux-libre-4.10-rc8-gnu/arch/ia64/mm/extable.c
--- linux-libre-4.9-gnu/arch/ia64/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 void
 ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/mm/init.c linux-libre-4.10-rc8-gnu/arch/ia64/mm/init.c
--- linux-libre-4.9-gnu/arch/ia64/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <asm/sal.h>
 #include <asm/sections.h>
 #include <asm/tlb.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/mca.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c
--- linux-libre-4.9-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/sn2/sn_hwperf.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@
 
 #include <asm/processor.h>
 #include <asm/topology.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sal.h>
 #include <asm/sn/io.h>
 #include <asm/sn/sn_sal.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- linux-libre-4.9-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sn/sn_sal.h>
 
 static int partition_id_show(struct seq_file *s, void *p)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/sn/kernel/sn2/timer.c linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/sn2/timer.c
--- linux-libre-4.9-gnu/arch/ia64/sn/kernel/sn2/timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/sn2/timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,9 +22,9 @@
 
 extern unsigned long sn_rtc_cycles_per_second;
 
-static cycle_t read_sn2(struct clocksource *cs)
+static u64 read_sn2(struct clocksource *cs)
 {
-	return (cycle_t)readq(RTC_COUNTER_ADDR);
+	return (u64)readq(RTC_COUNTER_ADDR);
 }
 
 static struct clocksource clocksource_sn2 = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/ia64/sn/kernel/tiocx.c linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/tiocx.c
--- linux-libre-4.9-gnu/arch/ia64/sn/kernel/tiocx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/ia64/sn/kernel/tiocx.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/capability.h>
 #include <linux/device.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/io.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/Kconfig linux-libre-4.10-rc8-gnu/arch/Kconfig
--- linux-libre-4.9-gnu/arch/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -5,6 +5,9 @@
 config KEXEC_CORE
 	bool
 
+config HAVE_IMA_KEXEC
+	bool
+
 config OPROFILE
 	tristate "OProfile system profiling"
 	depends on PROFILING
@@ -96,6 +99,7 @@ config KPROBES_ON_FTRACE
 
 config UPROBES
 	def_bool n
+	depends on ARCH_SUPPORTS_UPROBES
 	help
 	  Uprobes is the user-space counterpart to kprobes: they
 	  enable instrumentation applications (such as 'perf probe')
@@ -363,8 +367,9 @@ menuconfig GCC_PLUGINS
 	  See Documentation/gcc-plugins.txt for details.
 
 config GCC_PLUGIN_CYC_COMPLEXITY
-	bool "Compute the cyclomatic complexity of a function"
+	bool "Compute the cyclomatic complexity of a function" if EXPERT
 	depends on GCC_PLUGINS
+	depends on !COMPILE_TEST
 	help
 	  The complexity M of a function's control flow graph is defined as:
 	   M = E - N + 2P
@@ -374,6 +379,10 @@ config GCC_PLUGIN_CYC_COMPLEXITY
 	  N = the number of nodes
 	  P = the number of connected components (exit nodes).
 
+	  Enabling this plugin reports the complexity to stderr during the
+	  build. It mainly serves as a simple example of how to create a
+	  gcc plugin for the kernel.
+
 config GCC_PLUGIN_SANCOV
 	bool
 	depends on GCC_PLUGINS
@@ -512,6 +521,9 @@ config HAVE_CONTEXT_TRACKING
 config HAVE_VIRT_CPU_ACCOUNTING
 	bool
 
+config ARCH_HAS_SCALED_CPUTIME
+	bool
+
 config HAVE_VIRT_CPU_ACCOUNTING_GEN
 	bool
 	default y if 64BIT
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/include/asm/device.h linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/device.h
--- linux-libre-4.9-gnu/arch/m32r/include/asm/device.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/device.h	2017-02-12 16:03:20.000000000 -0500
@@ -3,5 +3,9 @@
  *
  * This file is released under the GPLv2
  */
-#include <asm-generic/device.h>
+struct dev_archdata {
+	struct dma_map_ops *dma_ops;
+};
 
+struct pdev_archdata {
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/include/asm/dma-mapping.h linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/dma-mapping.h
--- linux-libre-4.9-gnu/arch/m32r/include/asm/dma-mapping.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/dma-mapping.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,32 @@
+#ifndef _ASM_M32R_DMA_MAPPING_H
+#define _ASM_M32R_DMA_MAPPING_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
+#include <linux/io.h>
+
+#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	if (dev && dev->archdata.dma_ops)
+		return dev->archdata.dma_ops;
+	return &dma_noop_ops;
+}
+
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+				  enum dma_data_direction direction)
+{
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (!dev->dma_mask)
+		return false;
+	return addr + size - 1 <= *dev->dma_mask;
+}
+
+#endif /* _ASM_M32R_DMA_MAPPING_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/m32r/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/m32r/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -133,6 +133,5 @@ unsigned long get_wchan(struct task_stru
 #define KSTK_ESP(tsk)  ((tsk)->thread.sp)
 
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 #endif /* _ASM_M32R_PROCESSOR_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/m32r/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/m32r/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,4 +90,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _ASM_M32R_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/Kconfig linux-libre-4.10-rc8-gnu/arch/m32r/Kconfig
--- linux-libre-4.9-gnu/arch/m32r/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@ config NO_IOPORT_MAP
 	def_bool y
 
 config NO_DMA
-	def_bool y
+	def_bool n
 
 config HZ
 	int
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/align.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/align.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/align.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/align.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
  */
 
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static int get_reg(struct pt_regs *regs, int nr)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/irq.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * do_IRQ handles all normal device IRQs (the special
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/m32r_ksyms.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/m32r_ksyms.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/m32r_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/m32r_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
 #include <linux/string.h>
 
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
 #include <asm/delay.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/process.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/process.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/rcupdate.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/elf.h>
 #include <asm/m32r.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/signal.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/tracehook.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define DEBUG_SIG 0
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/sys_m32r.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/sys_m32r.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/sys_m32r.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/sys_m32r.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/utsname.h>
 #include <linux/ipc.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cachectl.h>
 #include <asm/cacheflush.h>
 #include <asm/syscall.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/m32r/kernel/traps.c
--- linux-libre-4.9-gnu/arch/m32r/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/lib/csum_partial_copy.c linux-libre-4.10-rc8-gnu/arch/m32r/lib/csum_partial_copy.c
--- linux-libre-4.9-gnu/arch/m32r/lib/csum_partial_copy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/lib/csum_partial_copy.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 
 #include <net/checksum.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * Copy while checksumming, otherwise like csum_partial
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/lib/usercopy.c linux-libre-4.10-rc8-gnu/arch/m32r/lib/usercopy.c
--- linux-libre-4.9-gnu/arch/m32r/lib/usercopy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/lib/usercopy.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 #include <linux/prefetch.h>
 #include <linux/string.h>
 #include <linux/thread_info.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 unsigned long
 __generic_copy_to_user(void __user *to, const void *from, unsigned long n)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/mm/extable.c linux-libre-4.10-rc8-gnu/arch/m32r/mm/extable.c
--- linux-libre-4.9-gnu/arch/m32r/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/mm/fault-nommu.c linux-libre-4.10-rc8-gnu/arch/m32r/mm/fault-nommu.c
--- linux-libre-4.9-gnu/arch/m32r/mm/fault-nommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/mm/fault-nommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/vt_kern.h>              /* For unblank_screen() */
 
 #include <asm/m32r.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/hardirq.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m32r/platforms/m32700ut/setup.c linux-libre-4.10-rc8-gnu/arch/m32r/platforms/m32700ut/setup.c
--- linux-libre-4.9-gnu/arch/m32r/platforms/m32700ut/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m32r/platforms/m32700ut/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -201,6 +201,7 @@ static struct irq_chip m32700ut_lanpld_i
 #define lcdpldirq2port(x)	(unsigned long)((int)M32700UT_LCD_ICUCR1 + \
 				 (((x) - 1) * sizeof(unsigned short)))
 
+#ifdef CONFIG_USB
 static pld_icu_data_t lcdpld_icu_data[M32700UT_NUM_LCD_PLD_IRQ];
 
 static void disable_m32700ut_lcdpld_irq(unsigned int irq)
@@ -253,6 +254,7 @@ static struct irq_chip m32700ut_lcdpld_i
 	.irq_mask	= mask_m32700ut_lcdpld,
 	.irq_unmask	= unmask_m32700ut_lcdpld,
 };
+#endif
 
 void __init init_IRQ(void)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/68000/timers.c linux-libre-4.10-rc8-gnu/arch/m68k/68000/timers.c
--- linux-libre-4.9-gnu/arch/m68k/68000/timers.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/68000/timers.c	2017-02-12 16:03:20.000000000 -0500
@@ -76,7 +76,7 @@ static struct irqaction m68328_timer_irq
 
 /***************************************************************************/
 
-static cycle_t m68328_read_clk(struct clocksource *cs)
+static u64 m68328_read_clk(struct clocksource *cs)
 {
 	unsigned long flags;
 	u32 cycles;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/amiga/config.c linux-libre-4.10-rc8-gnu/arch/m68k/amiga/config.c
--- linux-libre-4.9-gnu/arch/m68k/amiga/config.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/amiga/config.c	2017-02-12 16:03:20.000000000 -0500
@@ -786,8 +786,7 @@ static void amiga_get_hardware_list(stru
 	if (AMIGAHW_PRESENT(name))			\
 		seq_printf (m, "\t%s\n", str)
 
-	seq_printf (m, "Detected hardware:\n");
-
+	seq_puts(m, "Detected hardware:\n");
 	AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
 	AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
 	AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/atari/config.c linux-libre-4.10-rc8-gnu/arch/m68k/atari/config.c
--- linux-libre-4.9-gnu/arch/m68k/atari/config.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/atari/config.c	2017-02-12 16:03:20.000000000 -0500
@@ -629,7 +629,7 @@ static void atari_get_hardware_list(stru
 	if (ATARIHW_PRESENT(name))			\
 		seq_printf(m, "\t%s\n", str)
 
-	seq_printf(m, "Detected hardware:\n");
+	seq_puts(m, "Detected hardware:\n");
 	ATARIHW_ANNOUNCE(STND_SHIFTER, "ST Shifter");
 	ATARIHW_ANNOUNCE(EXTD_SHIFTER, "STe Shifter");
 	ATARIHW_ANNOUNCE(TT_SHIFTER, "TT Shifter");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/bvme6000/rtc.c linux-libre-4.10-rc8-gnu/arch/m68k/bvme6000/rtc.c
--- linux-libre-4.9-gnu/arch/m68k/bvme6000/rtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/bvme6000/rtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <asm/bvme6000hw.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/setup.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/amcore.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/amcore.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/amcore.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/amcore.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,156 @@
+/*
+ * amcore.c -- Support for Sysam AMCORE open board
+ *
+ * (C) Copyright 2016, Angelo Dureghello <angelo@sysam.it>
+ *
+ * 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/device.h>
+#include <linux/platform_device.h>
+#include <linux/dm9000.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/i2c.h>
+
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/io.h>
+
+#if IS_ENABLED(CONFIG_DM9000)
+
+#define DM9000_IRQ	25
+#define DM9000_ADDR	0x30000000
+
+/*
+ * DEVICES and related device RESOURCES
+ */
+static struct resource dm9000_resources[] = {
+	/* physical address of the address register (CMD [A2] to 0)*/
+	[0] = {
+		.start  = DM9000_ADDR,
+		.end    = DM9000_ADDR,
+		.flags  = IORESOURCE_MEM,
+	},
+	/*
+	 * physical address of the data register (CMD [A2] to 1),
+	 * driver wants a range >=4 to assume a 32bit data bus
+	 */
+	[1] = {
+		.start  = DM9000_ADDR + 4,
+		.end    = DM9000_ADDR + 7,
+		.flags  = IORESOURCE_MEM,
+	},
+	/* IRQ line the device's interrupt pin is connected to */
+	[2] = {
+		.start  = DM9000_IRQ,
+		.end    = DM9000_IRQ,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct dm9000_plat_data dm9000_platdata = {
+	.flags		= DM9000_PLATF_32BITONLY,
+};
+
+static struct platform_device dm9000_device = {
+	.name           = "dm9000",
+	.id             = 0,
+	.num_resources  = ARRAY_SIZE(dm9000_resources),
+	.resource       = dm9000_resources,
+	.dev = {
+		.platform_data = &dm9000_platdata,
+	}
+};
+#endif
+
+static void __init dm9000_pre_init(void)
+{
+	/* Set the dm9000 interrupt to be auto-vectored */
+	mcf_autovector(DM9000_IRQ);
+}
+
+/*
+ * Partitioning of parallel NOR flash (39VF3201B)
+ */
+static struct mtd_partition amcore_partitions[] = {
+	{
+		.name	= "U-Boot (128K)",
+		.size	= 0x20000,
+		.offset	= 0x0
+	},
+	{
+		.name	= "Kernel+ROMfs (2994K)",
+		.size	= 0x2E0000,
+		.offset	= MTDPART_OFS_APPEND
+	},
+	{
+		.name	= "Flash Free Space (1024K)",
+		.size	= MTDPART_SIZ_FULL,
+		.offset	= MTDPART_OFS_APPEND
+	}
+};
+
+static struct physmap_flash_data flash_data = {
+	.parts		= amcore_partitions,
+	.nr_parts	= ARRAY_SIZE(amcore_partitions),
+	.width		= 2,
+};
+
+static struct resource flash_resource = {
+	.start		= 0xffc00000,
+	.end		= 0xffffffff,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device flash_device = {
+	.name		= "physmap-flash",
+	.id		= -1,
+	.resource	= &flash_resource,
+	.num_resources	= 1,
+	.dev		= {
+		.platform_data	= &flash_data,
+	},
+};
+
+static struct platform_device rtc_device = {
+	.name	= "rtc-ds1307",
+	.id	= -1,
+};
+
+static struct i2c_board_info amcore_i2c_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("ds1338", 0x68),
+	},
+};
+
+static struct platform_device *amcore_devices[] __initdata = {
+#if IS_ENABLED(CONFIG_DM9000)
+	&dm9000_device,
+#endif
+	&flash_device,
+	&rtc_device,
+};
+
+static int __init init_amcore(void)
+{
+#if IS_ENABLED(CONFIG_DM9000)
+	dm9000_pre_init();
+#endif
+
+	/* Add i2c RTC Dallas chip supprt */
+	i2c_register_board_info(0, amcore_i2c_info,
+				ARRAY_SIZE(amcore_i2c_info));
+
+	platform_add_devices(amcore_devices, ARRAY_SIZE(amcore_devices));
+
+	return 0;
+}
+
+arch_initcall(init_amcore);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/device.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/device.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/device.c	2017-02-12 16:03:20.000000000 -0500
@@ -327,6 +327,147 @@ static struct platform_device mcf_qspi =
 };
 #endif /* IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI) */
 
+#if IS_ENABLED(CONFIG_I2C_IMX)
+static struct resource mcf_i2c0_resources[] = {
+	{
+		.start          = MCFI2C_BASE0,
+		.end            = MCFI2C_BASE0 + MCFI2C_SIZE0 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		.start          = MCF_IRQ_I2C0,
+		.end            = MCF_IRQ_I2C0,
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mcf_i2c0 = {
+	.name                   = "imx1-i2c",
+	.id                     = 0,
+	.num_resources          = ARRAY_SIZE(mcf_i2c0_resources),
+	.resource               = mcf_i2c0_resources,
+};
+#ifdef MCFI2C_BASE1
+
+static struct resource mcf_i2c1_resources[] = {
+	{
+		.start          = MCFI2C_BASE1,
+		.end            = MCFI2C_BASE1 + MCFI2C_SIZE1 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		.start          = MCF_IRQ_I2C1,
+		.end            = MCF_IRQ_I2C1,
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mcf_i2c1 = {
+	.name                   = "imx1-i2c",
+	.id                     = 1,
+	.num_resources          = ARRAY_SIZE(mcf_i2c1_resources),
+	.resource               = mcf_i2c1_resources,
+};
+
+#endif /* MCFI2C_BASE1 */
+
+#ifdef MCFI2C_BASE2
+
+static struct resource mcf_i2c2_resources[] = {
+	{
+		.start          = MCFI2C_BASE2,
+		.end            = MCFI2C_BASE2 + MCFI2C_SIZE2 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		.start          = MCF_IRQ_I2C2,
+		.end            = MCF_IRQ_I2C2,
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mcf_i2c2 = {
+	.name                   = "imx1-i2c",
+	.id                     = 2,
+	.num_resources          = ARRAY_SIZE(mcf_i2c2_resources),
+	.resource               = mcf_i2c2_resources,
+};
+
+#endif /* MCFI2C_BASE2 */
+
+#ifdef MCFI2C_BASE3
+
+static struct resource mcf_i2c3_resources[] = {
+	{
+		.start          = MCFI2C_BASE3,
+		.end            = MCFI2C_BASE3 + MCFI2C_SIZE3 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		.start          = MCF_IRQ_I2C3,
+		.end            = MCF_IRQ_I2C3,
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mcf_i2c3 = {
+	.name                   = "imx1-i2c",
+	.id                     = 3,
+	.num_resources          = ARRAY_SIZE(mcf_i2c3_resources),
+	.resource               = mcf_i2c3_resources,
+};
+
+#endif /* MCFI2C_BASE3 */
+
+#ifdef MCFI2C_BASE4
+
+static struct resource mcf_i2c4_resources[] = {
+	{
+		.start          = MCFI2C_BASE4,
+		.end            = MCFI2C_BASE4 + MCFI2C_SIZE4 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		.start          = MCF_IRQ_I2C4,
+		.end            = MCF_IRQ_I2C4,
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mcf_i2c4 = {
+	.name                   = "imx1-i2c",
+	.id                     = 4,
+	.num_resources          = ARRAY_SIZE(mcf_i2c4_resources),
+	.resource               = mcf_i2c4_resources,
+};
+
+#endif /* MCFI2C_BASE4 */
+
+#ifdef MCFI2C_BASE5
+
+static struct resource mcf_i2c5_resources[] = {
+	{
+		.start          = MCFI2C_BASE5,
+		.end            = MCFI2C_BASE5 + MCFI2C_SIZE5 - 1,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		.start          = MCF_IRQ_I2C5,
+		.end            = MCF_IRQ_I2C5,
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mcf_i2c5 = {
+	.name                   = "imx1-i2c",
+	.id                     = 5,
+	.num_resources          = ARRAY_SIZE(mcf_i2c5_resources),
+	.resource               = mcf_i2c5_resources,
+};
+
+#endif /* MCFI2C_BASE5 */
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+
 static struct platform_device *mcf_devices[] __initdata = {
 	&mcf_uart,
 #if IS_ENABLED(CONFIG_FEC)
@@ -338,6 +479,24 @@ static struct platform_device *mcf_devic
 #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
 	&mcf_qspi,
 #endif
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	&mcf_i2c0,
+#ifdef MCFI2C_BASE1
+	&mcf_i2c1,
+#endif
+#ifdef MCFI2C_BASE2
+	&mcf_i2c2,
+#endif
+#ifdef MCFI2C_BASE3
+	&mcf_i2c3,
+#endif
+#ifdef MCFI2C_BASE4
+	&mcf_i2c4,
+#endif
+#ifdef MCFI2C_BASE5
+	&mcf_i2c5,
+#endif
+#endif
 };
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/dma_timer.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/dma_timer.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/dma_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/dma_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #define DMA_DTMR_CLK_DIV_16	(2 << 1)
 #define DMA_DTMR_ENABLE		(1 << 0)
 
-static cycle_t cf_dt_get_cycles(struct clocksource *cs)
+static u64 cf_dt_get_cycles(struct clocksource *cs)
 {
 	return __raw_readl(DTCN0);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m5206.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5206.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m5206.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5206.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSC
 DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
 DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
 DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -34,11 +35,21 @@ struct clk *mcf_clks[] = {
 	&clk_mcftmr1,
 	&clk_mcfuart0,
 	&clk_mcfuart1,
+	&clk_mcfi2c0,
 	NULL
 };
 
 /***************************************************************************/
 
+static void __init m5206_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+	       MCFSIM_I2CICR);
+	mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
 void __init config_BSP(char *commandp, int size)
 {
 #if defined(CONFIG_NETtel)
@@ -53,6 +64,7 @@ void __init config_BSP(char *commandp, i
 	mcf_mapirq2imr(25, MCFINTC_EINT1);
 	mcf_mapirq2imr(28, MCFINTC_EINT4);
 	mcf_mapirq2imr(31, MCFINTC_EINT7);
+	m5206_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m520x.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m520x.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m520x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m520x.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@ DEFINE_CLK(0, "fec.0", 12, MCF_CLK);
 DEFINE_CLK(0, "edma", 17, MCF_CLK);
 DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
 DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
 DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
 DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
 DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
@@ -53,7 +53,7 @@ struct clk *mcf_clks[] = {
 	&__clk_0_17, /* edma */
 	&__clk_0_18, /* intc.0 */
 	&__clk_0_21, /* iack.0 */
-	&__clk_0_22, /* mcfi2c.0 */
+	&__clk_0_22, /* imx1-i2c.0 */
 	&__clk_0_23, /* mcfqspi.0 */
 	&__clk_0_24, /* mcfuart.0 */
 	&__clk_0_25, /* mcfuart.1 */
@@ -71,7 +71,7 @@ struct clk *mcf_clks[] = {
 	&__clk_0_40, /* sys.0 */
 	&__clk_0_41, /* gpio.0 */
 	&__clk_0_42, /* sdram.0 */
-NULL,
+	NULL,
 };
 
 static struct clk * const enable_clks[] __initconst = {
@@ -94,7 +94,7 @@ static struct clk * const enable_clks[]
 static struct clk * const disable_clks[] __initconst = {
 	&__clk_0_12, /* fec.0 */
 	&__clk_0_17, /* edma */
-	&__clk_0_22, /* mcfi2c.0 */
+	&__clk_0_22, /* imx1-i2c.0 */
 	&__clk_0_23, /* mcfqspi.0 */
 	&__clk_0_28, /* mcftmr.0 */
 	&__clk_0_29, /* mcftmr.1 */
@@ -133,6 +133,21 @@ static void __init m520x_qspi_init(void)
 
 /***************************************************************************/
 
+static void __init m520x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	u8 par;
+
+	/* setup Port FECI2C Pin Assignment Register for I2C */
+	/*  set PAR_SCL to SCL and PAR_SDA to SDA */
+	par = readb(MCF_GPIO_PAR_FECI2C);
+	par |= 0x0f;
+	writeb(par, MCF_GPIO_PAR_FECI2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 static void __init m520x_uarts_init(void)
 {
 	u16 par;
@@ -175,6 +190,7 @@ void __init config_BSP(char *commandp, i
 	m520x_uarts_init();
 	m520x_fec_init();
 	m520x_qspi_init();
+	m520x_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m523x.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m523x.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m523x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m523x.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,7 @@ DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BU
 DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
 DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
 DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -47,6 +48,7 @@ struct clk *mcf_clks[] = {
 	&clk_mcfuart2,
 	&clk_mcfqspi0,
 	&clk_fec0,
+	&clk_mcfi2c0,
 	NULL
 };
 
@@ -68,6 +70,21 @@ static void __init m523x_qspi_init(void)
 
 /***************************************************************************/
 
+static void __init m523x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	u8 par;
+
+	/* setup Port AS Pin Assignment Register for I2C */
+	/*  set PASPA0 to SCL and PASPA1 to SDA */
+	par = readb(MCFGPIO_PAR_FECI2C);
+	par |= 0x0f;
+	writeb(par, MCFGPIO_PAR_FECI2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 static void __init m523x_fec_init(void)
 {
 	/* Set multi-function pins to ethernet use */
@@ -81,6 +98,7 @@ void __init config_BSP(char *commandp, i
 	mach_sched_init = hw_timer_init;
 	m523x_fec_init();
 	m523x_qspi_init();
+	m523x_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m5249.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5249.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m5249.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5249.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,8 @@ DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSC
 DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
 DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
 DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c1, "imx1-i2c.1", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -36,6 +38,8 @@ struct clk *mcf_clks[] = {
 	&clk_mcfuart0,
 	&clk_mcfuart1,
 	&clk_mcfqspi0,
+	&clk_mcfi2c0,
+	&clk_mcfi2c1,
 	NULL
 };
 
@@ -85,6 +89,26 @@ static void __init m5249_qspi_init(void)
 
 /***************************************************************************/
 
+static void __init m5249_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	u32 r;
+
+	/* first I2C controller uses regular irq setup */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+	       MCFSIM_I2CICR);
+	mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+
+	/* second I2C controller is completely different */
+	r = readl(MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1));
+	r &= ~MCFINTC2_INTPRI_BITS(0xf, MCF_IRQ_I2C1);
+	r |= MCFINTC2_INTPRI_BITS(0x5, MCF_IRQ_I2C1);
+	writel(r, MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1));
+#endif /* CONFIG_I2C_IMX */
+}
+
+/***************************************************************************/
+
 #ifdef CONFIG_M5249C3
 
 static void __init m5249_smc91x_init(void)
@@ -111,6 +135,7 @@ void __init config_BSP(char *commandp, i
 	m5249_smc91x_init();
 #endif
 	m5249_qspi_init();
+	m5249_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m525x.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m525x.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m525x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m525x.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,8 @@ DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSC
 DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
 DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
 DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c1, "imx1-i2c.1", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -36,6 +38,8 @@ struct clk *mcf_clks[] = {
 	&clk_mcfuart0,
 	&clk_mcfuart1,
 	&clk_mcfqspi0,
+	&clk_mcfi2c0,
+	&clk_mcfi2c1,
 	NULL
 };
 
@@ -59,12 +63,12 @@ static void __init m525x_qspi_init(void)
 
 static void __init m525x_i2c_init(void)
 {
-#if IS_ENABLED(CONFIG_I2C_COLDFIRE)
+#if IS_ENABLED(CONFIG_I2C_IMX)
 	u32 r;
 
 	/* first I2C controller uses regular irq setup */
 	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
-		MCFSIM_I2CICR);
+	       MCFSIM_I2CICR);
 	mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
 
 	/* second I2C controller is completely different */
@@ -72,7 +76,7 @@ static void __init m525x_i2c_init(void)
 	r &= ~MCFINTC2_INTPRI_BITS(0xf, MCF_IRQ_I2C1);
 	r |= MCFINTC2_INTPRI_BITS(0x5, MCF_IRQ_I2C1);
 	writel(r, MCFINTC2_INTPRI_REG(MCF_IRQ_I2C1));
-#endif /* IS_ENABLED(CONFIG_I2C_COLDFIRE) */
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m527x.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m527x.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m527x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m527x.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,7 @@ DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BU
 DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
 DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
 DEFINE_CLK(fec1, "fec.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -50,6 +51,7 @@ struct clk *mcf_clks[] = {
 	&clk_mcfqspi0,
 	&clk_fec0,
 	&clk_fec1,
+	&clk_mcfi2c0,
 	NULL
 };
 
@@ -76,6 +78,31 @@ static void __init m527x_qspi_init(void)
 
 /***************************************************************************/
 
+static void __init m527x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+#if defined(CONFIG_M5271)
+	u8 par;
+
+	/* setup Port FECI2C Pin Assignment Register for I2C */
+	/*  set PAR_SCL to SCL and PAR_SDA to SDA */
+	par = readb(MCFGPIO_PAR_FECI2C);
+	par |= 0x0f;
+	writeb(par, MCFGPIO_PAR_FECI2C);
+#elif defined(CONFIG_M5275)
+	u16 par;
+
+	/* setup Port FECI2C Pin Assignment Register for I2C */
+	/*  set PAR_SCL to SCL and PAR_SDA to SDA */
+	par = readw(MCFGPIO_PAR_FECI2C);
+	par |= 0x0f;
+	writew(par, MCFGPIO_PAR_FECI2C);
+#endif
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 static void __init m527x_uarts_init(void)
 {
 	u16 sepmask;
@@ -122,6 +149,7 @@ void __init config_BSP(char *commandp, i
 	m527x_uarts_init();
 	m527x_fec_init();
 	m527x_qspi_init();
+	m527x_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m528x.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m528x.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m528x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m528x.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,7 @@ DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BU
 DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
 DEFINE_CLK(mcfqspi0, "mcfqspi.0", MCF_BUSCLK);
 DEFINE_CLK(fec0, "fec.0", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -49,6 +50,7 @@ struct clk *mcf_clks[] = {
 	&clk_mcfuart2,
 	&clk_mcfqspi0,
 	&clk_fec0,
+	&clk_mcfi2c0,
 	NULL
 };
 
@@ -64,6 +66,21 @@ static void __init m528x_qspi_init(void)
 
 /***************************************************************************/
 
+static void __init m528x_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	u16 paspar;
+
+	/* setup Port AS Pin Assignment Register for I2C */
+	/*  set PASPA0 to SCL and PASPA1 to SDA */
+	paspar = readw(MCFGPIO_PASPAR);
+	paspar |= 0xF;
+	writew(paspar, MCFGPIO_PASPAR);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 static void __init m528x_uarts_init(void)
 {
 	u8 port;
@@ -127,6 +144,7 @@ void __init config_BSP(char *commandp, i
 	m528x_uarts_init();
 	m528x_fec_init();
 	m528x_qspi_init();
+	m528x_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m5307.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5307.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m5307.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5307.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSC
 DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
 DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
 DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -43,11 +44,23 @@ struct clk *mcf_clks[] = {
 	&clk_mcftmr1,
 	&clk_mcfuart0,
 	&clk_mcfuart1,
+	&clk_mcfi2c0,
 	NULL
 };
 
 /***************************************************************************/
 
+static void __init m5307_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+	       MCFSIM_I2CICR);
+	mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 #if defined(CONFIG_NETtel) || \
@@ -73,6 +86,7 @@ void __init config_BSP(char *commandp, i
 	 */
 	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
 #endif
+	m5307_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m53xx.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m53xx.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m53xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m53xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@ DEFINE_CLK(0, "edma", 17, MCF_CLK);
 DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
 DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
 DEFINE_CLK(0, "iack.0", 21, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
 DEFINE_CLK(0, "mcfqspi.0", 23, MCF_CLK);
 DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
 DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
@@ -77,7 +77,7 @@ struct clk *mcf_clks[] = {
 	&__clk_0_18,	/* intc.0 */
 	&__clk_0_19,	/* intc.1 */
 	&__clk_0_21,	/* iack.0 */
-	&__clk_0_22,	/* mcfi2c.0 */
+	&__clk_0_22,	/* imx1-i2c.0 */
 	&__clk_0_23,	/* mcfqspi.0 */
 	&__clk_0_24,	/* mcfuart.0 */
 	&__clk_0_25,	/* mcfuart.1 */
@@ -133,7 +133,7 @@ static struct clk * const disable_clks[]
 	&__clk_0_8,	/* mcfcan.0 */
 	&__clk_0_12,	/* fec.0 */
 	&__clk_0_17,	/* edma */
-	&__clk_0_22,	/* mcfi2c.0 */
+	&__clk_0_22,	/* imx1-i2c.0 */
 	&__clk_0_23,	/* mcfqspi.0 */
 	&__clk_0_30,	/* mcftmr.2 */
 	&__clk_0_31,	/* mcftmr.3 */
@@ -176,6 +176,19 @@ static void __init m53xx_qspi_init(void)
 
 /***************************************************************************/
 
+static void __init m53xx_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	/* setup Port AS Pin Assignment Register for I2C */
+	/*  set PASPA0 to SCL and PASPA1 to SDA */
+	u8 r = readb(MCFGPIO_PAR_FECI2C);
+	r |= 0x0f;
+	writeb(r, MCFGPIO_PAR_FECI2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 static void __init m53xx_uarts_init(void)
 {
 	/* UART GPIO initialization */
@@ -218,6 +231,7 @@ void __init config_BSP(char *commandp, i
 	m53xx_uarts_init();
 	m53xx_fec_init();
 	m53xx_qspi_init();
+	m53xx_i2c_init();
 
 #ifdef CONFIG_BDM_DISABLE
 	/*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m5407.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5407.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m5407.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5407.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@ DEFINE_CLK(mcftmr0, "mcftmr.0", MCF_BUSC
 DEFINE_CLK(mcftmr1, "mcftmr.1", MCF_BUSCLK);
 DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BUSCLK);
 DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -34,11 +35,23 @@ struct clk *mcf_clks[] = {
 	&clk_mcftmr1,
 	&clk_mcfuart0,
 	&clk_mcfuart1,
+	&clk_mcfi2c0,
 	NULL
 };
 
 /***************************************************************************/
 
+static void __init m5407_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI0,
+	       MCFSIM_I2CICR);
+	mcf_mapirq2imr(MCF_IRQ_I2C0, MCFINTC_I2C);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 void __init config_BSP(char *commandp, int size)
 {
 	mach_sched_init = hw_timer_init;
@@ -48,6 +61,7 @@ void __init config_BSP(char *commandp, i
 	mcf_mapirq2imr(27, MCFINTC_EINT3);
 	mcf_mapirq2imr(29, MCFINTC_EINT5);
 	mcf_mapirq2imr(31, MCFINTC_EINT7);
+	m5407_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m5441x.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5441x.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m5441x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m5441x.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,13 +19,13 @@
 DEFINE_CLK(0, "flexbus", 2, MCF_CLK);
 DEFINE_CLK(0, "mcfcan.0", 8, MCF_CLK);
 DEFINE_CLK(0, "mcfcan.1", 9, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.1", 14, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.1", 14, MCF_CLK);
 DEFINE_CLK(0, "mcfdspi.1", 15, MCF_CLK);
 DEFINE_CLK(0, "edma", 17, MCF_CLK);
 DEFINE_CLK(0, "intc.0", 18, MCF_CLK);
 DEFINE_CLK(0, "intc.1", 19, MCF_CLK);
 DEFINE_CLK(0, "intc.2", 20, MCF_CLK);
-DEFINE_CLK(0, "mcfi2c.0", 22, MCF_CLK);
+DEFINE_CLK(0, "imx1-i2c.0", 22, MCF_CLK);
 DEFINE_CLK(0, "mcfdspi.0", 23, MCF_CLK);
 DEFINE_CLK(0, "mcfuart.0", 24, MCF_BUSCLK);
 DEFINE_CLK(0, "mcfuart.1", 25, MCF_BUSCLK);
@@ -59,10 +59,10 @@ DEFINE_CLK(0, "switch.1", 56, MCF_CLK);
 DEFINE_CLK(0, "nand.0", 63, MCF_CLK);
 
 DEFINE_CLK(1, "mcfow.0", 2, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.2", 4, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.3", 5, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.4", 6, MCF_CLK);
-DEFINE_CLK(1, "mcfi2c.5", 7, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.2", 4, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.3", 5, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.4", 6, MCF_CLK);
+DEFINE_CLK(1, "imx1-i2c.5", 7, MCF_CLK);
 DEFINE_CLK(1, "mcfuart.4", 24, MCF_BUSCLK);
 DEFINE_CLK(1, "mcfuart.5", 25, MCF_BUSCLK);
 DEFINE_CLK(1, "mcfuart.6", 26, MCF_BUSCLK);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/m54xx.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m54xx.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/m54xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/m54xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@ DEFINE_CLK(mcfuart0, "mcfuart.0", MCF_BU
 DEFINE_CLK(mcfuart1, "mcfuart.1", MCF_BUSCLK);
 DEFINE_CLK(mcfuart2, "mcfuart.2", MCF_BUSCLK);
 DEFINE_CLK(mcfuart3, "mcfuart.3", MCF_BUSCLK);
+DEFINE_CLK(mcfi2c0, "imx1-i2c.0", MCF_BUSCLK);
 
 struct clk *mcf_clks[] = {
 	&clk_pll,
@@ -47,6 +48,7 @@ struct clk *mcf_clks[] = {
 	&clk_mcfuart1,
 	&clk_mcfuart2,
 	&clk_mcfuart3,
+	&clk_mcfi2c0,
 	NULL
 };
 
@@ -65,6 +67,20 @@ static void __init m54xx_uarts_init(void
 
 /***************************************************************************/
 
+static void __init m54xx_i2c_init(void)
+{
+#if IS_ENABLED(CONFIG_I2C_IMX)
+	u32 r;
+
+	/* set the fec/i2c/irq pin assignment register for i2c */
+	r = readl(MCF_PAR_FECI2CIRQ);
+	r |= MCF_PAR_FECI2CIRQ_SDA | MCF_PAR_FECI2CIRQ_SCL;
+	writel(r, MCF_PAR_FECI2CIRQ);
+#endif /* IS_ENABLED(CONFIG_I2C_IMX) */
+}
+
+/***************************************************************************/
+
 static void mcf54xx_reset(void)
 {
 	/* disable interrupts and enable the watchdog */
@@ -86,6 +102,7 @@ void __init config_BSP(char *commandp, i
 	mach_reset = mcf54xx_reset;
 	mach_sched_init = hw_timer_init;
 	m54xx_uarts_init();
+	m54xx_i2c_init();
 }
 
 /***************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/Makefile linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/Makefile
--- linux-libre-4.9-gnu/arch/m68k/coldfire/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,7 @@ obj-$(CONFIG_NETtel)	+= nettel.o
 obj-$(CONFIG_CLEOPATRA)	+= nettel.o
 obj-$(CONFIG_FIREBEE)	+= firebee.o
 obj-$(CONFIG_MCF8390)	+= mcf8390.o
+obj-$(CONFIG_AMCORE)    += amcore.o
 
 obj-$(CONFIG_PCI)	+= pci.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/pit.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/pit.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/pit.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/pit.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,7 +118,7 @@ static struct irqaction pit_irq = {
 
 /***************************************************************************/
 
-static cycle_t pit_read_clk(struct clocksource *cs)
+static u64 pit_read_clk(struct clocksource *cs)
 {
 	unsigned long flags;
 	u32 cycles;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/sltimers.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/sltimers.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/sltimers.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/sltimers.c	2017-02-12 16:03:20.000000000 -0500
@@ -97,7 +97,7 @@ static struct irqaction mcfslt_timer_irq
 	.handler = mcfslt_tick,
 };
 
-static cycle_t mcfslt_read_clk(struct clocksource *cs)
+static u64 mcfslt_read_clk(struct clocksource *cs)
 {
 	unsigned long flags;
 	u32 cycles, scnt;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/coldfire/timers.c linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/timers.c
--- linux-libre-4.9-gnu/arch/m68k/coldfire/timers.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/coldfire/timers.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,7 @@ static struct irqaction mcftmr_timer_irq
 
 /***************************************************************************/
 
-static cycle_t mcftmr_read_clk(struct clocksource *cs)
+static u64 mcftmr_read_clk(struct clocksource *cs)
 {
 	unsigned long flags;
 	u32 cycles;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/configs/amcore_defconfig linux-libre-4.10-rc8-gnu/arch/m68k/configs/amcore_defconfig
--- linux-libre-4.9-gnu/arch/m68k/configs/amcore_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/configs/amcore_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,118 @@
+CONFIG_LOCALVERSION="amcore-001"
+CONFIG_DEFAULT_HOSTNAME="amcore"
+CONFIG_SYSVIPC=y
+# CONFIG_FHANDLE is not set
+# CONFIG_USELIB is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_AIO is not set
+# CONFIG_ADVISE_SYSCALLS is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_MMU is not set
+CONFIG_M5307=y
+CONFIG_AMCORE=y
+CONFIG_UBOOT=y
+CONFIG_RAMSIZE=0x1000000
+CONFIG_KERNELBASE=0x20000
+CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
+CONFIG_BINFMT_FLAT=y
+# CONFIG_COREDUMP 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_IPV6 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_UEVENT_HELPER is not set
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+# CONFIG_ALLOW_DEV_COREDUMP is not set
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_LE_BYTE_SWAP=y
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_CFI_I2 is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_MTD_PLATRAM=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+CONFIG_DM9000=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=115200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_IMX=y
+CONFIG_PPS=y
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_SYSTOHC is not set
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_FSCACHE=y
+# CONFIG_PROC_SYSCTL is not set
+CONFIG_JFFS2_FS=y
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+CONFIG_PANIC_ON_OOPS=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+CONFIG_CRYPTO_ANSI_CPRNG=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC16=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/emu/nfeth.c linux-libre-4.10-rc8-gnu/arch/m68k/emu/nfeth.c
--- linux-libre-4.9-gnu/arch/m68k/emu/nfeth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/emu/nfeth.c	2017-02-12 16:03:20.000000000 -0500
@@ -184,7 +184,6 @@ static const struct net_device_ops nfeth
 	.ndo_start_xmit		= nfeth_xmit,
 	.ndo_tx_timeout		= nfeth_tx_timeout,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= eth_mac_addr,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/m68k/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,6 @@ generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += mman.h
-generic-y += mutex.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += resource.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m5206sim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m5206sim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m5206sim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m5206sim.h	2017-02-12 16:03:20.000000000 -0500
@@ -110,6 +110,7 @@
 /*
  *	Define system peripheral IRQ usage.
  */
+#define	MCF_IRQ_I2C0		29		/* I2C, Level 5 */
 #define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
 #define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 #define	MCF_IRQ_UART0		73		/* UART0 */
@@ -138,6 +139,7 @@
 #define	MCFSIM_SWDICR		MCFSIM_ICR8	/* Watchdog timer ICR */
 #define	MCFSIM_TIMER1ICR	MCFSIM_ICR9	/* Timer 1 ICR */
 #define	MCFSIM_TIMER2ICR	MCFSIM_ICR10	/* Timer 2 ICR */
+#define	MCFSIM_I2CICR		MCFSIM_ICR11	/* I2C ICR */
 #define	MCFSIM_UART1ICR		MCFSIM_ICR12	/* UART 1 ICR */
 #define	MCFSIM_UART2ICR		MCFSIM_ICR13	/* UART 2 ICR */
 #ifdef CONFIG_M5206e
@@ -145,5 +147,11 @@
 #define	MCFSIM_DMA2ICR		MCFSIM_ICR15	/* DMA 2 ICR */
 #endif
 
+/*
+ * I2C Controller
+*/
+#define MCFI2C_BASE0		(MCF_MBAR + 0x1e0)
+#define MCFI2C_SIZE0		0x40
+
 /****************************************************************************/
 #endif	/* m5206sim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m520xsim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m520xsim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m520xsim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m520xsim.h	2017-02-12 16:03:20.000000000 -0500
@@ -50,6 +50,7 @@
 #define MCFINT_UART0        26          /* Interrupt number for UART0 */
 #define MCFINT_UART1        27          /* Interrupt number for UART1 */
 #define MCFINT_UART2        28          /* Interrupt number for UART2 */
+#define MCFINT_I2C0         30          /* Interrupt number for I2C */
 #define MCFINT_QSPI         31          /* Interrupt number for QSPI */
 #define MCFINT_FECRX0	    36		/* Interrupt number for FEC RX */
 #define MCFINT_FECTX0	    40		/* Interrupt number for FEC RX */
@@ -67,6 +68,7 @@
 #define	MCF_IRQ_QSPI	    (MCFINT_VECBASE + MCFINT_QSPI)
 #define MCF_IRQ_PIT1        (MCFINT_VECBASE + MCFINT_PIT1)
 
+#define MCF_IRQ_I2C0        (MCFINT_VECBASE + MCFINT_I2C0)
 /*
  *  SDRAM configuration registers.
  */
@@ -200,5 +202,11 @@
 #define MCFPM_PPMLR0		0xfc040034
 #define MCFPM_LPCR		0xfc0a0007
 
+/*
+ * I2C module.
+ */
+#define MCFI2C_BASE0		0xFC058000
+#define MCFI2C_SIZE0		0x40
+
 /****************************************************************************/
 #endif  /* m520xsim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m523xsim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m523xsim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m523xsim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m523xsim.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,8 @@
 #define	MCFINT_UART0		13		/* Interrupt number for UART0 */
 #define	MCFINT_UART1		14		/* Interrupt number for UART1 */
 #define	MCFINT_UART2		15		/* Interrupt number for UART2 */
-#define MCFINT_QSPI		18		/* Interrupt number for QSPI */
+#define	MCFINT_I2C0		17		/* Interrupt number for I2C */
+#define	MCFINT_QSPI		18		/* Interrupt number for QSPI */
 #define	MCFINT_FECRX0		23		/* Interrupt number for FEC */
 #define	MCFINT_FECTX0		27		/* Interrupt number for FEC */
 #define	MCFINT_FECENTC0		29		/* Interrupt number for FEC */
@@ -53,6 +54,7 @@
 
 #define	MCF_IRQ_QSPI		(MCFINT_VECBASE + MCFINT_QSPI)
 #define MCF_IRQ_PIT1		(MCFINT_VECBASE + MCFINT_PIT1)
+#define	MCF_IRQ_I2C0		(MCFINT_VECBASE + MCFINT_I2C0)
 
 /*
  *	SDRAM configuration registers.
@@ -208,5 +210,11 @@
 #define	MCFDMA_BASE2		(MCF_IPSBAR + 0x180)
 #define	MCFDMA_BASE3		(MCF_IPSBAR + 0x1C0)
 
+/*
+ * I2C module.
+ */
+#define	MCFI2C_BASE0		(MCF_IPSBAR + 0x300)
+#define	MCFI2C_SIZE0		0x40
+
 /****************************************************************************/
 #endif	/* m523xsim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m527xsim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m527xsim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m527xsim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m527xsim.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@
 #define	MCFINT_UART0		13		/* Interrupt number for UART0 */
 #define	MCFINT_UART1		14		/* Interrupt number for UART1 */
 #define	MCFINT_UART2		15		/* Interrupt number for UART2 */
+#define	MCFINT_I2C0		17		/* Interrupt number for I2C */
 #define	MCFINT_QSPI		18		/* Interrupt number for QSPI */
 #define	MCFINT_FECRX0		23		/* Interrupt number for FEC0 */
 #define	MCFINT_FECTX0		27		/* Interrupt number for FEC0 */
@@ -61,6 +62,7 @@
 
 #define	MCF_IRQ_QSPI		(MCFINT_VECBASE + MCFINT_QSPI)
 #define MCF_IRQ_PIT1		(MCFINT_VECBASE + MCFINT_PIT1)
+#define	MCF_IRQ_I2C0		(MCFINT_VECBASE + MCFINT_I2C0)
 
 /*
  *	SDRAM configuration registers.
@@ -353,5 +355,11 @@
 #define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
 #define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
 
+/*
+ * I2C module.
+ */
+#define	MCFI2C_BASE0		(MCF_IPSBAR + 0x300)
+#define	MCFI2C_SIZE0		0x40
+
 /****************************************************************************/
 #endif	/* m527xsim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m528xsim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m528xsim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m528xsim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m528xsim.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@
 #define	MCFINT_UART0		13		/* Interrupt number for UART0 */
 #define	MCFINT_UART1		14		/* Interrupt number for UART1 */
 #define	MCFINT_UART2		15		/* Interrupt number for UART2 */
+#define	MCFINT_I2C0		17		/* Interrupt number for I2C */
 #define	MCFINT_QSPI		18		/* Interrupt number for QSPI */
 #define	MCFINT_FECRX0		23		/* Interrupt number for FEC */
 #define	MCFINT_FECTX0		27		/* Interrupt number for FEC */
@@ -53,6 +54,8 @@
 
 #define	MCF_IRQ_QSPI		(MCFINT_VECBASE + MCFINT_QSPI)
 #define MCF_IRQ_PIT1		(MCFINT_VECBASE + MCFINT_PIT1)
+#define	MCF_IRQ_I2C0		(MCFINT_VECBASE + MCFINT_I2C0)
+
 /*
  *	SDRAM configuration registers.
  */
@@ -242,5 +245,11 @@
 #define	MCF_RCR_SWRESET		0x80		/* Software reset bit */
 #define	MCF_RCR_FRCSTOUT	0x40		/* Force external reset */
 
+/*
+ * I2C module
+ */
+#define	MCFI2C_BASE0		(MCF_IPSBAR + 0x300)
+#define	MCFI2C_SIZE0		0x40
+
 /****************************************************************************/
 #endif	/* m528xsim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m5307sim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m5307sim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m5307sim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m5307sim.h	2017-02-12 16:03:20.000000000 -0500
@@ -148,6 +148,7 @@
 #define	MCFSIM_SWDICR		MCFSIM_ICR0	/* Watchdog timer ICR */
 #define	MCFSIM_TIMER1ICR	MCFSIM_ICR1	/* Timer 1 ICR */
 #define	MCFSIM_TIMER2ICR	MCFSIM_ICR2	/* Timer 2 ICR */
+#define	MCFSIM_I2CICR		MCFSIM_ICR3	/* I2C ICR */
 #define	MCFSIM_UART1ICR		MCFSIM_ICR4	/* UART 1 ICR */
 #define	MCFSIM_UART2ICR		MCFSIM_ICR5	/* UART 2 ICR */
 #define	MCFSIM_DMA0ICR		MCFSIM_ICR6	/* DMA 0 ICR */
@@ -155,7 +156,6 @@
 #define	MCFSIM_DMA2ICR		MCFSIM_ICR8	/* DMA 2 ICR */
 #define	MCFSIM_DMA3ICR		MCFSIM_ICR9	/* DMA 3 ICR */
 
-
 /*
  *	Some symbol defines for the Parallel Port Pin Assignment Register
  */
@@ -174,10 +174,17 @@
 /*
  *	Define system peripheral IRQ usage.
  */
+#define	MCF_IRQ_I2C0		29		/* I2C, Level 5 */
 #define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
 #define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 #define	MCF_IRQ_UART0		73		/* UART0 */
 #define	MCF_IRQ_UART1		74		/* UART1 */
 
+/*
+ * I2C module
+ */
+#define	MCFI2C_BASE0		(MCF_MBAR + 0x280)
+#define	MCFI2C_SIZE0		0x40
+
 /****************************************************************************/
 #endif	/* m5307sim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m53xxsim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m53xxsim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m53xxsim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m53xxsim.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
 #define MCFINT_UART0        26          /* Interrupt number for UART0 */
 #define MCFINT_UART1        27          /* Interrupt number for UART1 */
 #define MCFINT_UART2        28          /* Interrupt number for UART2 */
+#define MCFINT_I2C0         30		/* Interrupt number for I2C */
 #define MCFINT_QSPI         31          /* Interrupt number for QSPI */
 #define MCFINT_FECRX0	    36		/* Interrupt number for FEC */
 #define MCFINT_FECTX0	    40		/* Interrupt number for FEC */
@@ -32,6 +33,7 @@
 #define MCF_IRQ_FECTX0	    (MCFINT_VECBASE + MCFINT_FECTX0)
 #define MCF_IRQ_FECENTC0    (MCFINT_VECBASE + MCFINT_FECENTC0)
 
+#define	MCF_IRQ_I2C0	    (MCFINT_VECBASE + MCFINT_I2C0)
 #define	MCF_IRQ_QSPI	    (MCFINT_VECBASE + MCFINT_QSPI)
 
 #define MCF_WTM_WCR		0xFC098000
@@ -1237,5 +1239,11 @@
 #define MCFEPORT_EPPDR                (0xFC094005)
 #define MCFEPORT_EPFR                 (0xFC094006)
 
+/*
+ * I2C Module
+ */
+#define	MCFI2C_BASE0			(0xFc058000)
+#define	MCFI2C_SIZE0			0x40
+
 /********************************************************************/
 #endif	/* m53xxsim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m5407sim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m5407sim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m5407sim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m5407sim.h	2017-02-12 16:03:20.000000000 -0500
@@ -112,6 +112,7 @@
 #define	MCFSIM_SWDICR		MCFSIM_ICR0	/* Watchdog timer ICR */
 #define	MCFSIM_TIMER1ICR	MCFSIM_ICR1	/* Timer 1 ICR */
 #define	MCFSIM_TIMER2ICR	MCFSIM_ICR2	/* Timer 2 ICR */
+#define	MCFSIM_I2CICR		MCFSIM_ICR3	/* I2C ICR */
 #define	MCFSIM_UART1ICR		MCFSIM_ICR4	/* UART 1 ICR */
 #define	MCFSIM_UART2ICR		MCFSIM_ICR5	/* UART 2 ICR */
 #define	MCFSIM_DMA0ICR		MCFSIM_ICR6	/* DMA 0 ICR */
@@ -137,10 +138,17 @@
 /*
  *	Define system peripheral IRQ usage.
  */
+#define	MCF_IRQ_I2C0		29		/* I2C, Level 5 */
 #define	MCF_IRQ_TIMER		30		/* Timer0, Level 6 */
 #define	MCF_IRQ_PROFILER	31		/* Timer1, Level 7 */
 #define	MCF_IRQ_UART0		73		/* UART0 */
 #define	MCF_IRQ_UART1		74		/* UART1 */
 
+/*
+ * I2C module
+ */
+#define	MCFI2C_BASE0		(MCF_MBAR + 0x280)
+#define	MCFI2C_SIZE0		0x40
+
 /****************************************************************************/
 #endif	/* m5407sim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/m54xxsim.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m54xxsim.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/m54xxsim.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/m54xxsim.h	2017-02-12 16:03:20.000000000 -0500
@@ -45,6 +45,7 @@
  */
 #define MCF_IRQ_TIMER		(MCFINT_VECBASE + 54)	/* Slice Timer 0 */
 #define MCF_IRQ_PROFILER	(MCFINT_VECBASE + 53)	/* Slice Timer 1 */
+#define MCF_IRQ_I2C0		(MCFINT_VECBASE + 40)
 #define MCF_IRQ_UART0		(MCFINT_VECBASE + 35)
 #define MCF_IRQ_UART1		(MCFINT_VECBASE + 34)
 #define MCF_IRQ_UART2		(MCFINT_VECBASE + 33)
@@ -107,4 +108,14 @@
 #define MCF_PAR_PSC_RTS_RTS	(0x30)
 #define MCF_PAR_PSC_CANRX	(0x40)
 
+#define MCF_PAR_FECI2CIRQ	(MCF_MBAR + 0x00000a44)	/* FEC/I2C/IRQ */
+#define MCF_PAR_FECI2CIRQ_SDA	(1 << 3)
+#define MCF_PAR_FECI2CIRQ_SCL	(1 << 2)
+
+/*
+ * I2C module.
+ */
+#define MCFI2C_BASE0		(MCF_MBAR + 0x8f00)
+#define MCFI2C_SIZE0		0x40
+
 #endif	/* m54xxsim_h */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/m68k/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -156,6 +156,5 @@ unsigned long get_wchan(struct task_stru
 #define task_pt_regs(tsk)	((struct pt_regs *) ((tsk)->thread.esp0))
 
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/Kconfig.machine linux-libre-4.10-rc8-gnu/arch/m68k/Kconfig.machine
--- linux-libre-4.9-gnu/arch/m68k/Kconfig.machine	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/Kconfig.machine	2017-02-12 16:03:20.000000000 -0500
@@ -259,6 +259,12 @@ config M5407C3
 	help
 	  Support for the Motorola M5407C3 board.
 
+config AMCORE
+	bool "Sysam AMCORE board support"
+	depends on M5307
+	help
+	  Support for the Sysam AMCORE open-hardware generic board.
+
 config FIREBEE
 	bool "FireBee board support"
 	depends on M547x
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/kernel/dma.c linux-libre-4.10-rc8-gnu/arch/m68k/kernel/dma.c
--- linux-libre-4.9-gnu/arch/m68k/kernel/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/kernel/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -134,7 +134,9 @@ static dma_addr_t m68k_dma_map_page(stru
 {
 	dma_addr_t handle = page_to_phys(page) + offset;
 
-	dma_sync_single_for_device(dev, handle, size, dir);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		dma_sync_single_for_device(dev, handle, size, dir);
+
 	return handle;
 }
 
@@ -146,6 +148,10 @@ static int m68k_dma_map_sg(struct device
 
 	for_each_sg(sglist, sg, nents, i) {
 		sg->dma_address = sg_phys(sg);
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		dma_sync_single_for_device(dev, sg->dma_address, sg->length,
 					   dir);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/kernel/process.c linux-libre-4.10-rc8-gnu/arch/m68k/kernel/process.c
--- linux-libre-4.9-gnu/arch/m68k/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/mqueue.h>
 #include <linux/rcupdate.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/m68k/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/m68k/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/signal.h>
 #include <linux/tracehook.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/m68k/kernel/signal.c
--- linux-libre-4.9-gnu/arch/m68k/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 #include <linux/tracehook.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/traps.h>
 #include <asm/ucontext.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/kernel/sys_m68k.c linux-libre-4.10-rc8-gnu/arch/m68k/kernel/sys_m68k.c
--- linux-libre-4.9-gnu/arch/m68k/kernel/sys_m68k.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/kernel/sys_m68k.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/ipc.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cachectl.h>
 #include <asm/traps.h>
 #include <asm/page.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/m68k/kernel/traps.c
--- linux-libre-4.9-gnu/arch/m68k/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/traps.h>
 #include <asm/pgalloc.h>
 #include <asm/machdep.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/lib/uaccess.c linux-libre-4.10-rc8-gnu/arch/m68k/lib/uaccess.c
--- linux-libre-4.9-gnu/arch/m68k/lib/uaccess.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/lib/uaccess.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 unsigned long __generic_copy_from_user(void *to, const void __user *from,
 				       unsigned long n)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/mac/misc.c linux-libre-4.10-rc8-gnu/arch/m68k/mac/misc.c
--- linux-libre-4.9-gnu/arch/m68k/mac/misc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/mac/misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/cuda.h>
 #include <linux/pmu.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/setup.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/mm/init.c linux-libre-4.10-rc8-gnu/arch/m68k/mm/init.c
--- linux-libre-4.9-gnu/arch/m68k/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/gfp.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/traps.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/mm/motorola.c linux-libre-4.10-rc8-gnu/arch/m68k/mm/motorola.c
--- linux-libre-4.9-gnu/arch/m68k/mm/motorola.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/mm/motorola.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/gfp.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/machdep.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/mm/sun3mmu.c linux-libre-4.10-rc8-gnu/arch/m68k/mm/sun3mmu.c
--- linux-libre-4.9-gnu/arch/m68k/mm/sun3mmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/mm/sun3mmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/bootmem.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/mvme16x/rtc.c linux-libre-4.10-rc8-gnu/arch/m68k/mvme16x/rtc.c
--- linux-libre-4.9-gnu/arch/m68k/mvme16x/rtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/mvme16x/rtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <asm/mvme16xhw.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/setup.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/m68k/sun3/mmu_emu.c linux-libre-4.10-rc8-gnu/arch/m68k/sun3/mmu_emu.c
--- linux-libre-4.9-gnu/arch/m68k/sun3/mmu_emu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/m68k/sun3/mmu_emu.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 
 #include <asm/setup.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/sun3mmu.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/metag/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/metag/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/metag/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/metag/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,6 @@ generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += msgbuf.h
-generic-y += mutex.h
 generic-y += param.h
 generic-y += pci.h
 generic-y += percpu.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/metag/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/metag/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/metag/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/metag/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -152,7 +152,6 @@ unsigned long get_wchan(struct task_stru
 #define user_stack_pointer(regs)        ((regs)->ctx.AX[0].U0)
 
 #define cpu_relax()     barrier()
-#define cpu_relax_lowlatency()  cpu_relax()
 
 extern void setup_priv(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/metag/kernel/dma.c linux-libre-4.10-rc8-gnu/arch/metag/kernel/dma.c
--- linux-libre-4.9-gnu/arch/metag/kernel/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/metag/kernel/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -484,8 +484,9 @@ static dma_addr_t metag_dma_map_page(str
 		unsigned long offset, size_t size,
 		enum dma_data_direction direction, unsigned long attrs)
 {
-	dma_sync_for_device((void *)(page_to_phys(page) + offset), size,
-			    direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		dma_sync_for_device((void *)(page_to_phys(page) + offset),
+				    size, direction);
 	return page_to_phys(page) + offset;
 }
 
@@ -493,7 +494,8 @@ static void metag_dma_unmap_page(struct
 		size_t size, enum dma_data_direction direction,
 		unsigned long attrs)
 {
-	dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
 }
 
 static int metag_dma_map_sg(struct device *dev, struct scatterlist *sglist,
@@ -507,6 +509,10 @@ static int metag_dma_map_sg(struct devic
 		BUG_ON(!sg_page(sg));
 
 		sg->dma_address = sg_phys(sg);
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		dma_sync_for_device(sg_virt(sg), sg->length, direction);
 	}
 
@@ -525,6 +531,10 @@ static void metag_dma_unmap_sg(struct de
 		BUG_ON(!sg_page(sg));
 
 		sg->dma_address = sg_phys(sg);
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		dma_sync_for_cpu(sg_virt(sg), sg->length, direction);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/metag/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/metag/kernel/irq.c
--- linux-libre-4.9-gnu/arch/metag/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/metag/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include <asm/core_reg.h>
 #include <asm/mach/arch.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_4KSTACKS
 union irq_ctx {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/metag/kernel/perf/perf_event.c linux-libre-4.10-rc8-gnu/arch/metag/kernel/perf/perf_event.c
--- linux-libre-4.9-gnu/arch/metag/kernel/perf/perf_event.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/metag/kernel/perf/perf_event.c	2017-02-12 16:03:20.000000000 -0500
@@ -868,7 +868,7 @@ static int __init init_hw_perf_events(vo
 	metag_out32(0, PERF_COUNT(1));
 
 	cpuhp_setup_state(CPUHP_AP_PERF_METAG_STARTING,
-			  "AP_PERF_METAG_STARTING", metag_pmu_starting_cpu,
+			  "perf/metag:starting", metag_pmu_starting_cpu,
 			  NULL);
 
 	ret = perf_pmu_register(&pmu, metag_pmu->name, PERF_TYPE_RAW);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/include/asm/irq.h linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/irq.h
--- linux-libre-4.9-gnu/arch/microblaze/include/asm/irq.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/irq.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,6 @@ struct pt_regs;
 extern void do_IRQ(struct pt_regs *regs);
 
 /* should be defined in each interrupt controller driver */
-extern unsigned int get_irq(void);
+extern unsigned int xintc_get_irq(void);
 
 #endif /* _ASM_MICROBLAZE_IRQ_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/microblaze/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/microblaze/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
 extern const struct seq_operations cpuinfo_op;
 
 # define cpu_relax()		barrier()
-# define cpu_relax_lowlatency()	cpu_relax()
 
 #define task_pt_regs(tsk) \
 		(((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/include/asm/unistd.h linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/unistd.h
--- linux-libre-4.9-gnu/arch/microblaze/include/asm/unistd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/include/asm/unistd.h	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#define __NR_syscalls         392
+#define __NR_syscalls         398
 
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/include/uapi/asm/unistd.h linux-libre-4.10-rc8-gnu/arch/microblaze/include/uapi/asm/unistd.h
--- linux-libre-4.9-gnu/arch/microblaze/include/uapi/asm/unistd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/include/uapi/asm/unistd.h	2017-02-12 16:03:20.000000000 -0500
@@ -407,5 +407,11 @@
 #define __NR_userfaultfd	389
 #define __NR_membarrier		390
 #define __NR_mlock2		391
+#define __NR_copy_file_range	392
+#define __NR_preadv2		393
+#define __NR_pwritev2		394
+#define __NR_pkey_mprotect	395
+#define __NR_pkey_alloc		396
+#define __NR_pkey_free		397
 
 #endif /* _UAPI_ASM_MICROBLAZE_UNISTD_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/Kconfig linux-libre-4.10-rc8-gnu/arch/microblaze/Kconfig
--- linux-libre-4.9-gnu/arch/microblaze/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@ config MICROBLAZE
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_OPROFILE
 	select IRQ_DOMAIN
+	select XILINX_INTC
 	select MODULES_USE_ELF_RELA
 	select OF
 	select OF_EARLY_FLATTREE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/kernel/cpu/cpuinfo.c linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/cpu/cpuinfo.c
--- linux-libre-4.9-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,8 @@ const struct cpu_ver_key cpu_ver_lookup[
 	{"9.3", 0x20},
 	{"9.4", 0x21},
 	{"9.5", 0x22},
+	{"9.6", 0x23},
+	{"10.0", 0x24},
 	{NULL, 0},
 };
 
@@ -75,6 +77,10 @@ const struct family_string_key family_st
 	{"zynq7000", 0x12},
 	{"UltraScale Virtex", 0x13},
 	{"UltraScale Kintex", 0x14},
+	{"UltraScale+ Zynq", 0x15},
+	{"UltraScale+ Virtex", 0x16},
+	{"UltraScale+ Kintex", 0x17},
+	{"Spartan7", 0x18},
 	{NULL, 0},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/kernel/dma.c linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/dma.c
--- linux-libre-4.9-gnu/arch/microblaze/kernel/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,6 +61,10 @@ static int dma_direct_map_sg(struct devi
 	/* FIXME this part of code is untested */
 	for_each_sg(sgl, sg, nents, i) {
 		sg->dma_address = sg_phys(sg);
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		__dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
 							sg->length, direction);
 	}
@@ -80,7 +84,8 @@ static inline dma_addr_t dma_direct_map_
 					     enum dma_data_direction direction,
 					     unsigned long attrs)
 {
-	__dma_sync(page_to_phys(page) + offset, size, direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		__dma_sync(page_to_phys(page) + offset, size, direction);
 	return page_to_phys(page) + offset;
 }
 
@@ -95,7 +100,8 @@ static inline void dma_direct_unmap_page
  * phys_to_virt is here because in __dma_sync_page is __virt_to_phys and
  * dma_address is physical address
  */
-	__dma_sync(dma_address, size, direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		__dma_sync(dma_address, size, direction);
 }
 
 static inline void
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/kernel/intc.c linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/intc.c
--- linux-libre-4.9-gnu/arch/microblaze/kernel/intc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/intc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
- * Copyright (C) 2012-2013 Xilinx, Inc.
- * Copyright (C) 2007-2009 PetaLogix
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/irqdomain.h>
-#include <linux/irq.h>
-#include <linux/irqchip.h>
-#include <linux/of_address.h>
-#include <linux/io.h>
-#include <linux/bug.h>
-
-static void __iomem *intc_baseaddr;
-
-/* No one else should require these constants, so define them locally here. */
-#define ISR 0x00			/* Interrupt Status Register */
-#define IPR 0x04			/* Interrupt Pending Register */
-#define IER 0x08			/* Interrupt Enable Register */
-#define IAR 0x0c			/* Interrupt Acknowledge Register */
-#define SIE 0x10			/* Set Interrupt Enable bits */
-#define CIE 0x14			/* Clear Interrupt Enable bits */
-#define IVR 0x18			/* Interrupt Vector Register */
-#define MER 0x1c			/* Master Enable Register */
-
-#define MER_ME (1<<0)
-#define MER_HIE (1<<1)
-
-static unsigned int (*read_fn)(void __iomem *);
-static void (*write_fn)(u32, void __iomem *);
-
-static void intc_write32(u32 val, void __iomem *addr)
-{
-	iowrite32(val, addr);
-}
-
-static unsigned int intc_read32(void __iomem *addr)
-{
-	return ioread32(addr);
-}
-
-static void intc_write32_be(u32 val, void __iomem *addr)
-{
-	iowrite32be(val, addr);
-}
-
-static unsigned int intc_read32_be(void __iomem *addr)
-{
-	return ioread32be(addr);
-}
-
-static void intc_enable_or_unmask(struct irq_data *d)
-{
-	unsigned long mask = 1 << d->hwirq;
-
-	pr_debug("enable_or_unmask: %ld\n", d->hwirq);
-
-	/* ack level irqs because they can't be acked during
-	 * ack function since the handle_level_irq function
-	 * acks the irq before calling the interrupt handler
-	 */
-	if (irqd_is_level_type(d))
-		write_fn(mask, intc_baseaddr + IAR);
-
-	write_fn(mask, intc_baseaddr + SIE);
-}
-
-static void intc_disable_or_mask(struct irq_data *d)
-{
-	pr_debug("disable: %ld\n", d->hwirq);
-	write_fn(1 << d->hwirq, intc_baseaddr + CIE);
-}
-
-static void intc_ack(struct irq_data *d)
-{
-	pr_debug("ack: %ld\n", d->hwirq);
-	write_fn(1 << d->hwirq, intc_baseaddr + IAR);
-}
-
-static void intc_mask_ack(struct irq_data *d)
-{
-	unsigned long mask = 1 << d->hwirq;
-
-	pr_debug("disable_and_ack: %ld\n", d->hwirq);
-	write_fn(mask, intc_baseaddr + CIE);
-	write_fn(mask, intc_baseaddr + IAR);
-}
-
-static struct irq_chip intc_dev = {
-	.name = "Xilinx INTC",
-	.irq_unmask = intc_enable_or_unmask,
-	.irq_mask = intc_disable_or_mask,
-	.irq_ack = intc_ack,
-	.irq_mask_ack = intc_mask_ack,
-};
-
-static struct irq_domain *root_domain;
-
-unsigned int get_irq(void)
-{
-	unsigned int hwirq, irq = -1;
-
-	hwirq = read_fn(intc_baseaddr + IVR);
-	if (hwirq != -1U)
-		irq = irq_find_mapping(root_domain, hwirq);
-
-	pr_debug("get_irq: hwirq=%d, irq=%d\n", hwirq, irq);
-
-	return irq;
-}
-
-static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
-{
-	u32 intr_mask = (u32)d->host_data;
-
-	if (intr_mask & (1 << hw)) {
-		irq_set_chip_and_handler_name(irq, &intc_dev,
-						handle_edge_irq, "edge");
-		irq_clear_status_flags(irq, IRQ_LEVEL);
-	} else {
-		irq_set_chip_and_handler_name(irq, &intc_dev,
-						handle_level_irq, "level");
-		irq_set_status_flags(irq, IRQ_LEVEL);
-	}
-	return 0;
-}
-
-static const struct irq_domain_ops xintc_irq_domain_ops = {
-	.xlate = irq_domain_xlate_onetwocell,
-	.map = xintc_map,
-};
-
-static int __init xilinx_intc_of_init(struct device_node *intc,
-					     struct device_node *parent)
-{
-	u32 nr_irq, intr_mask;
-	int ret;
-
-	intc_baseaddr = of_iomap(intc, 0);
-	BUG_ON(!intc_baseaddr);
-
-	ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
-	if (ret < 0) {
-		pr_err("%s: unable to read xlnx,num-intr-inputs\n", __func__);
-		return ret;
-	}
-
-	ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &intr_mask);
-	if (ret < 0) {
-		pr_err("%s: unable to read xlnx,kind-of-intr\n", __func__);
-		return ret;
-	}
-
-	if (intr_mask >> nr_irq)
-		pr_warn("%s: mismatch in kind-of-intr param\n", __func__);
-
-	pr_info("%s: num_irq=%d, edge=0x%x\n",
-		intc->full_name, nr_irq, intr_mask);
-
-	write_fn = intc_write32;
-	read_fn = intc_read32;
-
-	/*
-	 * Disable all external interrupts until they are
-	 * explicity requested.
-	 */
-	write_fn(0, intc_baseaddr + IER);
-
-	/* Acknowledge any pending interrupts just in case. */
-	write_fn(0xffffffff, intc_baseaddr + IAR);
-
-	/* Turn on the Master Enable. */
-	write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
-	if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) {
-		write_fn = intc_write32_be;
-		read_fn = intc_read32_be;
-		write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
-	}
-
-	/* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
-	 * lazy and Michal can clean it up to something nicer when he tests
-	 * and commits this patch.  ~~gcl */
-	root_domain = irq_domain_add_linear(intc, nr_irq, &xintc_irq_domain_ops,
-							(void *)intr_mask);
-
-	irq_set_default_host(root_domain);
-
-	return 0;
-}
-
-IRQCHIP_DECLARE(xilinx_intc, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/irq.c
--- linux-libre-4.9-gnu/arch/microblaze/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,12 +29,12 @@ void __irq_entry do_IRQ(struct pt_regs *
 	trace_hardirqs_off();
 
 	irq_enter();
-	irq = get_irq();
+	irq = xintc_get_irq();
 next_irq:
 	BUG_ON(!irq);
 	generic_handle_irq(irq);
 
-	irq = get_irq();
+	irq = xintc_get_irq();
 	if (irq != -1U) {
 		pr_debug("next irq: %d\n", irq);
 		++concurrent_irq;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/kernel/Makefile linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/Makefile
--- linux-libre-4.9-gnu/arch/microblaze/kernel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@ endif
 extra-y := head.o vmlinux.lds
 
 obj-y += dma.o exceptions.o \
-	hw_exception_handler.o intc.o irq.o \
+	hw_exception_handler.o irq.o \
 	platform.o process.o prom.o ptrace.o \
 	reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/kernel/syscall_table.S linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/syscall_table.S
--- linux-libre-4.9-gnu/arch/microblaze/kernel/syscall_table.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/syscall_table.S	2017-02-12 16:03:20.000000000 -0500
@@ -392,3 +392,9 @@ ENTRY(sys_call_table)
 	.long sys_userfaultfd
 	.long sys_membarrier		/* 390 */
 	.long sys_mlock2
+	.long sys_copy_file_range
+	.long sys_preadv2
+	.long sys_pwritev2
+	.long sys_pkey_mprotect		/* 395 */
+	.long sys_pkey_alloc
+	.long sys_pkey_free
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/microblaze/kernel/timer.c linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/timer.c
--- linux-libre-4.9-gnu/arch/microblaze/kernel/timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/microblaze/kernel/timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -190,17 +190,17 @@ static u64 xilinx_clock_read(void)
 	return read_fn(timer_baseaddr + TCR1);
 }
 
-static cycle_t xilinx_read(struct clocksource *cs)
+static u64 xilinx_read(struct clocksource *cs)
 {
 	/* reading actual value of timer 1 */
-	return (cycle_t)xilinx_clock_read();
+	return (u64)xilinx_clock_read();
 }
 
 static struct timecounter xilinx_tc = {
 	.cc = NULL,
 };
 
-static cycle_t xilinx_cc_read(const struct cyclecounter *cc)
+static u64 xilinx_cc_read(const struct cyclecounter *cc)
 {
 	return xilinx_read(NULL);
 }
@@ -259,7 +259,7 @@ static int __init xilinx_timer_init(stru
 	int ret;
 
 	if (initialized)
-		return;
+		return -EINVAL;
 
 	initialized = 1;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/alchemy/common/power.c linux-libre-4.10-rc8-gnu/arch/mips/alchemy/common/power.c
--- linux-libre-4.9-gnu/arch/mips/alchemy/common/power.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/alchemy/common/power.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <linux/sysctl.h>
 #include <linux/jiffies.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mach-au1x00/au1000.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/alchemy/common/time.c linux-libre-4.10-rc8-gnu/arch/mips/alchemy/common/time.c
--- linux-libre-4.9-gnu/arch/mips/alchemy/common/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/alchemy/common/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 /* 32kHz clock enabled and detected */
 #define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
 
-static cycle_t au1x_counter1_read(struct clocksource *cs)
+static u64 au1x_counter1_read(struct clocksource *cs)
 {
 	return alchemy_rdsys(AU1000_SYS_RTCREAD);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi linux-libre-4.10-rc8-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi
--- linux-libre-4.9-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/boot/dts/ingenic/jz4740.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,17 @@
 		#clock-cells = <1>;
 	};
 
+	rtc_dev: rtc@10003000 {
+		compatible = "ingenic,jz4740-rtc";
+		reg = <0x10003000 0x40>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <15>;
+
+		clocks = <&cgu JZ4740_CLK_RTC>;
+		clock-names = "rtc";
+	};
+
 	uart0: serial@10030000 {
 		compatible = "ingenic,jz4740-uart";
 		reg = <0x10030000 0x100>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/boot/dts/ingenic/qi_lb60.dts linux-libre-4.10-rc8-gnu/arch/mips/boot/dts/ingenic/qi_lb60.dts
--- linux-libre-4.9-gnu/arch/mips/boot/dts/ingenic/qi_lb60.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/boot/dts/ingenic/qi_lb60.dts	2017-02-12 16:03:20.000000000 -0500
@@ -13,3 +13,7 @@
 &ext {
 	clock-frequency = <12000000>;
 };
+
+&rtc_dev {
+	system-power-controller;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/cavium-octeon/csrc-octeon.c linux-libre-4.10-rc8-gnu/arch/mips/cavium-octeon/csrc-octeon.c
--- linux-libre-4.9-gnu/arch/mips/cavium-octeon/csrc-octeon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/cavium-octeon/csrc-octeon.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,7 +98,7 @@ void octeon_init_cvmcount(void)
 	local_irq_restore(flags);
 }
 
-static cycle_t octeon_cvmcount_read(struct clocksource *cs)
+static u64 octeon_cvmcount_read(struct clocksource *cs)
 {
 	return read_c0_cvmcount();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/dec/kn01-berr.c linux-libre-4.10-rc8-gnu/arch/mips/dec/kn01-berr.c
--- linux-libre-4.9-gnu/arch/mips/dec/kn01-berr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/dec/kn01-berr.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/dec/kn01.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/asm/checksum.h linux-libre-4.10-rc8-gnu/arch/mips/include/asm/checksum.h
--- linux-libre-4.9-gnu/arch/mips/include/asm/checksum.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/asm/checksum.h	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 
 #include <linux/in6.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * computes the checksum of a memory block at buff, length len,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/asm/compat-signal.h linux-libre-4.10-rc8-gnu/arch/mips/include/asm/compat-signal.h
--- linux-libre-4.9-gnu/arch/mips/include/asm/compat-signal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/asm/compat-signal.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
 #include <asm/signal.h>
 #include <asm/siginfo.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
 	const sigset_t *s)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/mips/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/mips/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,6 @@ generic-y += irq_work.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
-generic-y += mutex.h
 generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/asm/mach-jz4740/platform.h linux-libre-4.10-rc8-gnu/arch/mips/include/asm/mach-jz4740/platform.h
--- linux-libre-4.9-gnu/arch/mips/include/asm/mach-jz4740/platform.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/asm/mach-jz4740/platform.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
 extern struct platform_device jz4740_udc_device;
 extern struct platform_device jz4740_udc_xceiv_device;
 extern struct platform_device jz4740_mmc_device;
-extern struct platform_device jz4740_rtc_device;
 extern struct platform_device jz4740_i2c_device;
 extern struct platform_device jz4740_nand_device;
 extern struct platform_device jz4740_framebuffer_device;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/mips/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/mips/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -389,7 +389,6 @@ unsigned long get_wchan(struct task_stru
 #define KSTK_STATUS(tsk) (task_pt_regs(tsk)->cp0_status)
 
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 /*
  * Return_address is a replacement for __builtin_return_address(count)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/asm/r4kcache.h linux-libre-4.10-rc8-gnu/arch/mips/include/asm/r4kcache.h
--- linux-libre-4.9-gnu/arch/mips/include/asm/r4kcache.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/asm/r4kcache.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <asm/cpu-features.h>
 #include <asm/cpu-type.h>
 #include <asm/mipsmtregs.h>
-#include <asm/uaccess.h> /* for segment_eq() */
+#include <linux/uaccess.h> /* for segment_eq() */
 
 extern void (*r4k_blast_dcache)(void);
 extern void (*r4k_blast_icache)(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/asm/termios.h linux-libre-4.10-rc8-gnu/arch/mips/include/asm/termios.h
--- linux-libre-4.9-gnu/arch/mips/include/asm/termios.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/asm/termios.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 #ifndef _ASM_TERMIOS_H
 #define _ASM_TERMIOS_H
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <uapi/asm/termios.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/mips/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/mips/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -108,4 +108,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _UAPI_ASM_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/jazz/jazzdma.c linux-libre-4.10-rc8-gnu/arch/mips/jazz/jazzdma.c
--- linux-libre-4.9-gnu/arch/mips/jazz/jazzdma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/jazz/jazzdma.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <asm/mipsregs.h>
 #include <asm/jazz.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/dma.h>
 #include <asm/jazzdma.h>
 #include <asm/pgtable.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/jz4740/board-qi_lb60.c linux-libre-4.10-rc8-gnu/arch/mips/jz4740/board-qi_lb60.c
--- linux-libre-4.9-gnu/arch/mips/jz4740/board-qi_lb60.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/jz4740/board-qi_lb60.c	2017-02-12 16:03:20.000000000 -0500
@@ -438,7 +438,6 @@ static struct platform_device *jz_platfo
 	&jz4740_pcm_device,
 	&jz4740_i2s_device,
 	&jz4740_codec_device,
-	&jz4740_rtc_device,
 	&jz4740_adc_device,
 	&jz4740_pwm_device,
 	&jz4740_dma_device,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/jz4740/platform.c linux-libre-4.10-rc8-gnu/arch/mips/jz4740/platform.c
--- linux-libre-4.9-gnu/arch/mips/jz4740/platform.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/jz4740/platform.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,27 +88,6 @@ struct platform_device jz4740_mmc_device
 	.resource	= jz4740_mmc_resources,
 };
 
-/* RTC controller */
-static struct resource jz4740_rtc_resources[] = {
-	{
-		.start	= JZ4740_RTC_BASE_ADDR,
-		.end	= JZ4740_RTC_BASE_ADDR + 0x38 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= JZ4740_IRQ_RTC,
-		.end	= JZ4740_IRQ_RTC,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device jz4740_rtc_device = {
-	.name		= "jz4740-rtc",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(jz4740_rtc_resources),
-	.resource	= jz4740_rtc_resources,
-};
-
 /* I2C controller */
 static struct resource jz4740_i2c_resources[] = {
 	{
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/jz4740/reset.c linux-libre-4.10-rc8-gnu/arch/mips/jz4740/reset.c
--- linux-libre-4.9-gnu/arch/mips/jz4740/reset.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/jz4740/reset.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,71 +57,8 @@ static void jz4740_restart(char *command
 	jz4740_halt();
 }
 
-#define JZ_REG_RTC_CTRL			0x00
-#define JZ_REG_RTC_HIBERNATE		0x20
-#define JZ_REG_RTC_WAKEUP_FILTER	0x24
-#define JZ_REG_RTC_RESET_COUNTER	0x28
-
-#define JZ_RTC_CTRL_WRDY		BIT(7)
-#define JZ_RTC_WAKEUP_FILTER_MASK	0x0000FFE0
-#define JZ_RTC_RESET_COUNTER_MASK	0x00000FE0
-
-static inline void jz4740_rtc_wait_ready(void __iomem *rtc_base)
-{
-	uint32_t ctrl;
-
-	do {
-		ctrl = readl(rtc_base + JZ_REG_RTC_CTRL);
-	} while (!(ctrl & JZ_RTC_CTRL_WRDY));
-}
-
-static void jz4740_power_off(void)
-{
-	void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38);
-	unsigned long wakeup_filter_ticks;
-	unsigned long reset_counter_ticks;
-	struct clk *rtc_clk;
-	unsigned long rtc_rate;
-
-	rtc_clk = clk_get(NULL, "rtc");
-	if (IS_ERR(rtc_clk))
-		panic("unable to get RTC clock");
-	rtc_rate = clk_get_rate(rtc_clk);
-	clk_put(rtc_clk);
-
-	/*
-	 * Set minimum wakeup pin assertion time: 100 ms.
-	 * Range is 0 to 2 sec if RTC is clocked at 32 kHz.
-	 */
-	wakeup_filter_ticks = (100 * rtc_rate) / 1000;
-	if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
-		wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
-	else
-		wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
-	jz4740_rtc_wait_ready(rtc_base);
-	writel(wakeup_filter_ticks, rtc_base + JZ_REG_RTC_WAKEUP_FILTER);
-
-	/*
-	 * Set reset pin low-level assertion time after wakeup: 60 ms.
-	 * Range is 0 to 125 ms if RTC is clocked at 32 kHz.
-	 */
-	reset_counter_ticks = (60 * rtc_rate) / 1000;
-	if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
-		reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
-	else
-		reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK;
-	jz4740_rtc_wait_ready(rtc_base);
-	writel(reset_counter_ticks, rtc_base + JZ_REG_RTC_RESET_COUNTER);
-
-	jz4740_rtc_wait_ready(rtc_base);
-	writel(1, rtc_base + JZ_REG_RTC_HIBERNATE);
-
-	jz4740_halt();
-}
-
 void jz4740_reset_init(void)
 {
 	_machine_restart = jz4740_restart;
 	_machine_halt = jz4740_halt;
-	pm_power_off = jz4740_power_off;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/jz4740/time.c linux-libre-4.10-rc8-gnu/arch/mips/jz4740/time.c
--- linux-libre-4.9-gnu/arch/mips/jz4740/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/jz4740/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 
 static uint16_t jz4740_jiffies_per_tick;
 
-static cycle_t jz4740_clocksource_read(struct clocksource *cs)
+static u64 jz4740_clocksource_read(struct clocksource *cs)
 {
 	return jz4740_timer_get_count(TIMER_CLOCKSOURCE);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/asm-offsets.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/asm-offsets.c
--- linux-libre-4.9-gnu/arch/mips/kernel/asm-offsets.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/asm-offsets.c	2017-02-12 16:03:20.000000000 -0500
@@ -341,7 +341,7 @@ void output_pm_defines(void)
 
 void output_kvm_defines(void)
 {
-	COMMENT(" KVM/MIPS Specfic offsets. ");
+	COMMENT(" KVM/MIPS Specific offsets. ");
 
 	OFFSET(VCPU_FPR0, kvm_vcpu_arch, fpu.fpr[0]);
 	OFFSET(VCPU_FPR1, kvm_vcpu_arch, fpu.fpr[1]);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/branch.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/branch.c
--- linux-libre-4.9-gnu/arch/mips/kernel/branch.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/branch.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <asm/inst.h>
 #include <asm/mips-r2-to-r6-emul.h>
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * Calculate and return exception PC in case of branch delay slot
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/cevt-txx9.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/cevt-txx9.c
--- linux-libre-4.9-gnu/arch/mips/kernel/cevt-txx9.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/cevt-txx9.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@ struct txx9_clocksource {
 	struct txx9_tmr_reg __iomem *tmrptr;
 };
 
-static cycle_t txx9_cs_read(struct clocksource *cs)
+static u64 txx9_cs_read(struct clocksource *cs)
 {
 	struct txx9_clocksource *txx9_cs =
 		container_of(cs, struct txx9_clocksource, cs);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/cpu-probe.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/cpu-probe.c
--- linux-libre-4.9-gnu/arch/mips/kernel/cpu-probe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/cpu-probe.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <asm/elf.h>
 #include <asm/pgtable-bits.h>
 #include <asm/spram.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Hardware capabilities */
 unsigned int elf_hwcap __read_mostly;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/crash_dump.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/crash_dump.c
--- linux-libre-4.9-gnu/arch/mips/kernel/crash_dump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/crash_dump.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
 #include <linux/crash_dump.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/slab.h>
 
 static void *kdump_buf_page;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/csrc-bcm1480.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-bcm1480.c
--- linux-libre-4.9-gnu/arch/mips/kernel/csrc-bcm1480.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-bcm1480.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,9 +25,9 @@
 
 #include <asm/sibyte/sb1250.h>
 
-static cycle_t bcm1480_hpt_read(struct clocksource *cs)
+static u64 bcm1480_hpt_read(struct clocksource *cs)
 {
-	return (cycle_t) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT));
+	return (u64) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT));
 }
 
 struct clocksource bcm1480_clocksource = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/csrc-ioasic.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-ioasic.c
--- linux-libre-4.9-gnu/arch/mips/kernel/csrc-ioasic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-ioasic.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <asm/dec/ioasic.h>
 #include <asm/dec/ioasic_addrs.h>
 
-static cycle_t dec_ioasic_hpt_read(struct clocksource *cs)
+static u64 dec_ioasic_hpt_read(struct clocksource *cs)
 {
 	return ioasic_read(IO_REG_FCTR);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/csrc-r4k.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-r4k.c
--- linux-libre-4.9-gnu/arch/mips/kernel/csrc-r4k.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-r4k.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 
 #include <asm/time.h>
 
-static cycle_t c0_hpt_read(struct clocksource *cs)
+static u64 c0_hpt_read(struct clocksource *cs)
 {
 	return read_c0_count();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/csrc-sb1250.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-sb1250.c
--- linux-libre-4.9-gnu/arch/mips/kernel/csrc-sb1250.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/csrc-sb1250.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
  * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
  * again.
  */
-static inline cycle_t sb1250_hpt_get_cycles(void)
+static inline u64 sb1250_hpt_get_cycles(void)
 {
 	unsigned int count;
 	void __iomem *addr;
@@ -41,7 +41,7 @@ static inline cycle_t sb1250_hpt_get_cyc
 	return SB1250_HPT_VALUE - count;
 }
 
-static cycle_t sb1250_hpt_read(struct clocksource *cs)
+static u64 sb1250_hpt_read(struct clocksource *cs)
 {
 	return sb1250_hpt_get_cycles();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/irq.c
--- linux-libre-4.9-gnu/arch/mips/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/ftrace.h>
 
 #include <linux/atomic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/kgdb.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/kgdb.c
--- linux-libre-4.9-gnu/arch/mips/kernel/kgdb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/kgdb.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static struct hard_trap_info {
 	unsigned char tt;	/* Trap type code for MIPS R3xxx and R4xxx */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/linux32.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/linux32.c
--- linux-libre-4.9-gnu/arch/mips/kernel/linux32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/linux32.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 
 #include <asm/compat-signal.h>
 #include <asm/sim.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/mman.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/mips_ksyms.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/mips_ksyms.c
--- linux-libre-4.9-gnu/arch/mips/kernel/mips_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/mips_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/export.h>
 #include <asm/checksum.h>
 #include <linux/mm.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ftrace.h>
 #include <asm/fpu.h>
 #include <asm/msa.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/mips-mt-fpaff.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/mips-mt-fpaff.c
--- linux-libre-4.9-gnu/arch/mips/kernel/mips-mt-fpaff.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/mips-mt-fpaff.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/sched.h>
 #include <linux/security.h>
 #include <linux/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c
--- linux-libre-4.9-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/mips-r2-to-r6-emul.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/local.h>
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_64BIT
 #define ADDIU	"daddiu "
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/pm-cps.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/pm-cps.c
--- linux-libre-4.9-gnu/arch/mips/kernel/pm-cps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/pm-cps.c	2017-02-12 16:03:20.000000000 -0500
@@ -713,7 +713,7 @@ static int __init cps_pm_init(void)
 		pr_warn("pm-cps: no CPC, clock & power gating unavailable\n");
 	}
 
-	return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "AP_PM_CPS_CPU_ONLINE",
+	return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mips/cps_pm:online",
 				 cps_pm_online_cpu, NULL);
 }
 arch_initcall(cps_pm_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/process.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/process.c
--- linux-libre-4.9-gnu/arch/mips/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/reg.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/elf.h>
 #include <asm/isadep.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/ptrace32.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/ptrace32.c
--- linux-libre-4.9-gnu/arch/mips/kernel/ptrace32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/ptrace32.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/reg.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/bootinfo.h>
 
 /*
@@ -69,7 +69,7 @@ long compat_arch_ptrace(struct task_stru
 		if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
 			break;
 
-		copied = access_process_vm(child, (u64)addrOthers, &tmp,
+		copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
 				sizeof(tmp), FOLL_FORCE);
 		if (copied != sizeof(tmp))
 			break;
@@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_stru
 		if (get_user(addrOthers, (u32 __user * __user *) (unsigned long) addr) != 0)
 			break;
 		ret = 0;
-		if (access_process_vm(child, (u64)addrOthers, &data,
+		if (ptrace_access_vm(child, (u64)addrOthers, &data,
 					sizeof(data),
 					FOLL_FORCE | FOLL_WRITE) == sizeof(data))
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/mips/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/syscall.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/bootinfo.h>
 #include <asm/reg.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/signal32.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/signal32.c
--- linux-libre-4.9-gnu/arch/mips/kernel/signal32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/signal32.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 
 #include <asm/compat.h>
 #include <asm/compat-signal.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 
 #include "signal-common.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/signal_n32.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/signal_n32.c
--- linux-libre-4.9-gnu/arch/mips/kernel/signal_n32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/signal_n32.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <asm/cacheflush.h>
 #include <asm/compat-signal.h>
 #include <asm/sim.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ucontext.h>
 #include <asm/fpu.h>
 #include <asm/cpu-features.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/syscall.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/syscall.c
--- linux-libre-4.9-gnu/arch/mips/kernel/syscall.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/syscall.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 #include <asm/sim.h>
 #include <asm/shmparam.h>
 #include <asm/sysmips.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/switch_to.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/traps.c
--- linux-libre-4.9-gnu/arch/mips/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,7 +61,7 @@
 #include <asm/siginfo.h>
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/watch.h>
 #include <asm/mmu_context.h>
 #include <asm/types.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kernel/unaligned.c linux-libre-4.10-rc8-gnu/arch/mips/kernel/unaligned.c
--- linux-libre-4.9-gnu/arch/mips/kernel/unaligned.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kernel/unaligned.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,7 @@
 #include <asm/fpu.h>
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define STR(x)	__STR(x)
 #define __STR(x)  #x
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kvm/entry.c linux-libre-4.10-rc8-gnu/arch/mips/kvm/entry.c
--- linux-libre-4.9-gnu/arch/mips/kvm/entry.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kvm/entry.c	2017-02-12 16:03:20.000000000 -0500
@@ -521,6 +521,9 @@ void *kvm_mips_build_exit(void *addr)
 	uasm_i_and(&p, V0, V0, AT);
 	uasm_i_lui(&p, AT, ST0_CU0 >> 16);
 	uasm_i_or(&p, V0, V0, AT);
+#ifdef CONFIG_64BIT
+	uasm_i_ori(&p, V0, V0, ST0_SX | ST0_UX);
+#endif
 	uasm_i_mtc0(&p, V0, C0_STATUS);
 	uasm_i_ehb(&p);
 
@@ -643,7 +646,7 @@ static void *kvm_mips_build_ret_to_guest
 
 	/* Setup status register for running guest in UM */
 	uasm_i_ori(&p, V1, V1, ST0_EXL | KSU_USER | ST0_IE);
-	UASM_i_LA(&p, AT, ~(ST0_CU0 | ST0_MX));
+	UASM_i_LA(&p, AT, ~(ST0_CU0 | ST0_MX | ST0_SX | ST0_UX));
 	uasm_i_and(&p, V1, V1, AT);
 	uasm_i_mtc0(&p, V1, C0_STATUS);
 	uasm_i_ehb(&p);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/kvm/mips.c linux-libre-4.10-rc8-gnu/arch/mips/kvm/mips.c
--- linux-libre-4.9-gnu/arch/mips/kvm/mips.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/kvm/mips.c	2017-02-12 16:03:20.000000000 -0500
@@ -360,8 +360,8 @@ struct kvm_vcpu *kvm_arch_vcpu_create(st
 	dump_handler("kvm_exit", gebase + 0x2000, vcpu->arch.vcpu_run);
 
 	/* Invalidate the icache for these ranges */
-	local_flush_icache_range((unsigned long)gebase,
-				(unsigned long)gebase + ALIGN(size, PAGE_SIZE));
+	flush_icache_range((unsigned long)gebase,
+			   (unsigned long)gebase + ALIGN(size, PAGE_SIZE));
 
 	/*
 	 * Allocate comm page for guest kernel, a TLB will be reserved for
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/loongson32/common/time.c linux-libre-4.10-rc8-gnu/arch/mips/loongson32/common/time.c
--- linux-libre-4.9-gnu/arch/mips/loongson32/common/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/loongson32/common/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,7 +63,7 @@ void __init ls1x_pwmtimer_init(void)
 	ls1x_pwmtimer_restart();
 }
 
-static cycle_t ls1x_clocksource_read(struct clocksource *cs)
+static u64 ls1x_clocksource_read(struct clocksource *cs)
 {
 	unsigned long flags;
 	int count;
@@ -107,7 +107,7 @@ static cycle_t ls1x_clocksource_read(str
 
 	raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags);
 
-	return (cycle_t) (jifs * ls1x_jiffies_per_tick) + count;
+	return (u64) (jifs * ls1x_jiffies_per_tick) + count;
 }
 
 static struct clocksource ls1x_clocksource = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c linux-libre-4.10-rc8-gnu/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c
--- linux-libre-4.9-gnu/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c	2017-02-12 16:03:20.000000000 -0500
@@ -144,7 +144,7 @@ void __init setup_mfgpt0_timer(void)
  * to just read by itself. So use jiffies to emulate a free
  * running counter:
  */
-static cycle_t mfgpt_read(struct clocksource *cs)
+static u64 mfgpt_read(struct clocksource *cs)
 {
 	unsigned long flags;
 	int count;
@@ -188,7 +188,7 @@ static cycle_t mfgpt_read(struct clockso
 
 	raw_spin_unlock_irqrestore(&mfgpt_lock, flags);
 
-	return (cycle_t) (jifs * COMPARE) + count;
+	return (u64) (jifs * COMPARE) + count;
 }
 
 static struct clocksource clocksource_mfgpt = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/loongson64/common/dma-swiotlb.c linux-libre-4.10-rc8-gnu/arch/mips/loongson64/common/dma-swiotlb.c
--- linux-libre-4.9-gnu/arch/mips/loongson64/common/dma-swiotlb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/loongson64/common/dma-swiotlb.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,7 +61,7 @@ static int loongson_dma_map_sg(struct de
 				int nents, enum dma_data_direction dir,
 				unsigned long attrs)
 {
-	int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, 0);
+	int r = swiotlb_map_sg_attrs(dev, sg, nents, dir, attrs);
 	mb();
 
 	return r;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/loongson64/loongson-3/hpet.c linux-libre-4.10-rc8-gnu/arch/mips/loongson64/loongson-3/hpet.c
--- linux-libre-4.9-gnu/arch/mips/loongson64/loongson-3/hpet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/loongson64/loongson-3/hpet.c	2017-02-12 16:03:20.000000000 -0500
@@ -248,9 +248,9 @@ void __init setup_hpet_timer(void)
 	pr_info("hpet clock event device register\n");
 }
 
-static cycle_t hpet_read_counter(struct clocksource *cs)
+static u64 hpet_read_counter(struct clocksource *cs)
 {
-	return (cycle_t)hpet_read(HPET_COUNTER);
+	return (u64)hpet_read(HPET_COUNTER);
 }
 
 static void hpet_suspend(struct clocksource *cs)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/math-emu/cp1emu.c linux-libre-4.10-rc8-gnu/arch/mips/math-emu/cp1emu.c
--- linux-libre-4.9-gnu/arch/mips/math-emu/cp1emu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/math-emu/cp1emu.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@
 #include <asm/inst.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/cpu-info.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/math-emu/dsemul.c linux-libre-4.10-rc8-gnu/arch/mips/math-emu/dsemul.c
--- linux-libre-4.9-gnu/arch/mips/math-emu/dsemul.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/math-emu/dsemul.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
 #include <asm/fpu_emulator.h>
 #include <asm/inst.h>
 #include <asm/mipsregs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /**
  * struct emuframe - The 'emulation' frame structure
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/mm/dma-default.c linux-libre-4.10-rc8-gnu/arch/mips/mm/dma-default.c
--- linux-libre-4.9-gnu/arch/mips/mm/dma-default.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/mm/dma-default.c	2017-02-12 16:03:20.000000000 -0500
@@ -293,7 +293,7 @@ static inline void __dma_sync(struct pag
 static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
 	size_t size, enum dma_data_direction direction, unsigned long attrs)
 {
-	if (cpu_needs_post_dma_flush(dev))
+	if (cpu_needs_post_dma_flush(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 		__dma_sync(dma_addr_to_page(dev, dma_addr),
 			   dma_addr & ~PAGE_MASK, size, direction);
 	plat_post_dma_flush(dev);
@@ -307,7 +307,8 @@ static int mips_dma_map_sg(struct device
 	struct scatterlist *sg;
 
 	for_each_sg(sglist, sg, nents, i) {
-		if (!plat_device_is_coherent(dev))
+		if (!plat_device_is_coherent(dev) &&
+		    !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 			__dma_sync(sg_page(sg), sg->offset, sg->length,
 				   direction);
 #ifdef CONFIG_NEED_SG_DMA_LENGTH
@@ -324,7 +325,7 @@ static dma_addr_t mips_dma_map_page(stru
 	unsigned long offset, size_t size, enum dma_data_direction direction,
 	unsigned long attrs)
 {
-	if (!plat_device_is_coherent(dev))
+	if (!plat_device_is_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 		__dma_sync(page, offset, size, direction);
 
 	return plat_map_dma_mem_page(dev, page) + offset;
@@ -339,6 +340,7 @@ static void mips_dma_unmap_sg(struct dev
 
 	for_each_sg(sglist, sg, nhwentries, i) {
 		if (!plat_device_is_coherent(dev) &&
+		    !(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
 		    direction != DMA_TO_DEVICE)
 			__dma_sync(sg_page(sg), sg->offset, sg->length,
 				   direction);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/mm/extable.c linux-libre-4.10-rc8-gnu/arch/mips/mm/extable.c
--- linux-libre-4.9-gnu/arch/mips/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
 #include <linux/extable.h>
 #include <linux/spinlock.h>
 #include <asm/branch.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/mm/sc-debugfs.c linux-libre-4.10-rc8-gnu/arch/mips/mm/sc-debugfs.c
--- linux-libre-4.9-gnu/arch/mips/mm/sc-debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/mm/sc-debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 
 #include <asm/bcache.h>
 #include <asm/debug.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/debugfs.h>
 #include <linux/init.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/mti-malta/malta-time.c linux-libre-4.10-rc8-gnu/arch/mips/mti-malta/malta-time.c
--- linux-libre-4.9-gnu/arch/mips/mti-malta/malta-time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/mti-malta/malta-time.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,7 @@ static void __init estimate_frequencies(
 	unsigned int count, start;
 	unsigned char secs1, secs2, ctrl;
 	int secs;
-	cycle_t giccount = 0, gicstart = 0;
+	u64 giccount = 0, gicstart = 0;
 
 #if defined(CONFIG_KVM_GUEST) && CONFIG_KVM_GUEST_TIMER_FREQ
 	mips_hpt_frequency = CONFIG_KVM_GUEST_TIMER_FREQ * 1000000;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/netlogic/common/time.c linux-libre-4.10-rc8-gnu/arch/mips/netlogic/common/time.c
--- linux-libre-4.9-gnu/arch/mips/netlogic/common/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/netlogic/common/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,14 +59,14 @@ unsigned int get_c0_compare_int(void)
 	return IRQ_TIMER;
 }
 
-static cycle_t nlm_get_pic_timer(struct clocksource *cs)
+static u64 nlm_get_pic_timer(struct clocksource *cs)
 {
 	uint64_t picbase = nlm_get_node(0)->picbase;
 
 	return ~nlm_pic_read_timer(picbase, PIC_CLOCK_TIMER);
 }
 
-static cycle_t nlm_get_pic_timer32(struct clocksource *cs)
+static u64 nlm_get_pic_timer32(struct clocksource *cs)
 {
 	uint64_t picbase = nlm_get_node(0)->picbase;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/oprofile/op_model_loongson3.c linux-libre-4.10-rc8-gnu/arch/mips/oprofile/op_model_loongson3.c
--- linux-libre-4.9-gnu/arch/mips/oprofile/op_model_loongson3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/oprofile/op_model_loongson3.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/oprofile.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <irq.h>
 #include <loongson.h>
 #include "op_impl.h"
@@ -186,7 +186,7 @@ static int __init loongson3_init(void)
 {
 	on_each_cpu(reset_counters, NULL, 1);
 	cpuhp_setup_state_nocalls(CPUHP_AP_MIPS_OP_LOONGSON3_STARTING,
-				  "AP_MIPS_OP_LOONGSON3_STARTING",
+				  "mips/oprofile/loongson3:starting",
 				  loongson3_starting_cpu, loongson3_dying_cpu);
 	save_perf_irq = perf_irq;
 	perf_irq = loongson3_perfcount_handler;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/sgi-ip22/ip28-berr.c linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip22/ip28-berr.c
--- linux-libre-4.9-gnu/arch/mips/sgi-ip22/ip28-berr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip22/ip28-berr.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <asm/sgi/ioc.h>
 #include <asm/sgi/ip22.h>
 #include <asm/r4kcache.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/bootinfo.h>
 
 static unsigned int count_be_is_fixup;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/sgi-ip27/ip27-berr.c linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip27/ip27-berr.c
--- linux-libre-4.9-gnu/arch/mips/sgi-ip27/ip27-berr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip27/ip27-berr.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <asm/sn/sn0/hub.h>
 #include <asm/tlbdebug.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static void dump_hub_information(unsigned long errst0, unsigned long errst1)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/sgi-ip27/ip27-timer.c linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip27/ip27-timer.c
--- linux-libre-4.9-gnu/arch/mips/sgi-ip27/ip27-timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip27/ip27-timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -140,7 +140,7 @@ static void __init hub_rt_clock_event_gl
 	setup_irq(irq, &hub_rt_irqaction);
 }
 
-static cycle_t hub_rt_read(struct clocksource *cs)
+static u64 hub_rt_read(struct clocksource *cs)
 {
 	return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/sgi-ip32/ip32-berr.c linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip32/ip32-berr.c
--- linux-libre-4.9-gnu/arch/mips/sgi-ip32/ip32-berr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/sgi-ip32/ip32-berr.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/addrspace.h>
 #include <asm/ptrace.h>
 #include <asm/tlbdebug.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mips/sibyte/common/sb_tbprof.c linux-libre-4.10-rc8-gnu/arch/mips/sibyte/common/sb_tbprof.c
--- linux-libre-4.9-gnu/arch/mips/sibyte/common/sb_tbprof.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mips/sibyte/common/sb_tbprof.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 #define K_INT_PERF_CNT K_BCM1480_INT_PERF_CNT
 #endif
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define SBPROF_TB_MAJOR 240
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/mn10300/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/mn10300/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/* MN10300 Mutex fastpath
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
- *
- *
- * 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-null.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/mn10300/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/mn10300/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -69,7 +69,6 @@ extern void print_cpu_info(struct mn1030
 extern void dodgy_tsc(void);
 
 #define cpu_relax() barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 /*
  * User space process size: 1.75GB (default).
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/include/asm/switch_to.h linux-libre-4.10-rc8-gnu/arch/mn10300/include/asm/switch_to.h
--- linux-libre-4.9-gnu/arch/mn10300/include/asm/switch_to.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/include/asm/switch_to.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 struct task_struct;
 struct thread_struct;
 
-#if !defined(CONFIG_LAZY_SAVE_FPU)
+#if defined(CONFIG_FPU) && !defined(CONFIG_LAZY_SAVE_FPU)
 struct fpu_state_struct;
 extern asmlinkage void fpu_save(struct fpu_state_struct *);
 #define switch_fpu(prev, next)						\
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/mn10300/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/mn10300/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,4 +90,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _ASM_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/csrc-mn10300.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/csrc-mn10300.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/csrc-mn10300.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/csrc-mn10300.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 #include <asm/timex.h>
 #include "internal.h"
 
-static cycle_t mn10300_read(struct clocksource *cs)
+static u64 mn10300_read(struct clocksource *cs)
 {
 	return read_timestamp_counter();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/fpu.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/fpu.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/fpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/fpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation; either version
  * 2 of the Licence, or (at your option) any later version.
  */
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/fpu.h>
 #include <asm/elf.h>
 #include <asm/exceptions.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/mn10300_ksyms.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/mn10300_ksyms.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/mn10300_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/mn10300_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
  * 2 of the Licence, or (at your option) any later version.
  */
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/process.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/process.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/rcupdate.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/regset.h>
 #include <linux/elf.h>
 #include <linux/tracehook.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/cacheflush.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/setup.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/cpu.h>
 #include <asm/processor.h>
 #include <linux/console.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/smp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/signal.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/tracehook.h>
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/fpu.h>
 #include "sigframe.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/kernel/sys_mn10300.c linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/sys_mn10300.c
--- linux-libre-4.9-gnu/arch/mn10300/kernel/sys_mn10300.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/kernel/sys_mn10300.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/file.h>
 #include <linux/tty.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 asmlinkage long old_mmap(unsigned long addr, unsigned long len,
 			 unsigned long prot, unsigned long flags,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/lib/checksum.c linux-libre-4.10-rc8-gnu/arch/mn10300/lib/checksum.c
--- linux-libre-4.9-gnu/arch/mn10300/lib/checksum.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/lib/checksum.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/checksum.h>
 #include "internal.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/mm/cache.c linux-libre-4.10-rc8-gnu/arch/mn10300/mm/cache.c
--- linux-libre-4.9-gnu/arch/mn10300/mm/cache.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/mm/cache.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <asm/processor.h>
 #include <asm/cacheflush.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/smp.h>
 #include "cache-smp.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/mm/cache-smp.c linux-libre-4.10-rc8-gnu/arch/mn10300/mm/cache-smp.c
--- linux-libre-4.9-gnu/arch/mn10300/mm/cache-smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/mm/cache-smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <asm/processor.h>
 #include <asm/cacheflush.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/smp.h>
 #include "cache-smp.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/mm/extable.c linux-libre-4.10-rc8-gnu/arch/mn10300/mm/extable.c
--- linux-libre-4.9-gnu/arch/mn10300/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
  */
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/mm/init.c linux-libre-4.10-rc8-gnu/arch/mn10300/mm/init.c
--- linux-libre-4.9-gnu/arch/mn10300/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/gfp.h>
 
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/mm/misalignment.c linux-libre-4.10-rc8-gnu/arch/mn10300/mm/misalignment.c
--- linux-libre-4.9-gnu/arch/mn10300/mm/misalignment.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/mm/misalignment.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <asm/smp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/proc-mn2ws0050/proc-init.c linux-libre-4.10-rc8-gnu/arch/mn10300/proc-mn2ws0050/proc-init.c
--- linux-libre-4.9-gnu/arch/mn10300/proc-mn2ws0050/proc-init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/proc-mn2ws0050/proc-init.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <asm/smp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/mn10300/unit-asb2303/include/unit/smc91111.h linux-libre-4.10-rc8-gnu/arch/mn10300/unit-asb2303/include/unit/smc91111.h
--- linux-libre-4.9-gnu/arch/mn10300/unit-asb2303/include/unit/smc91111.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/mn10300/unit-asb2303/include/unit/smc91111.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 
 #if SMC_CAN_USE_16BIT
 #define SMC_inw(a, r)		inw((unsigned long) ((a) + (r)))
-#define SMC_outw(v, a, r)	outw(v, (unsigned long) ((a) + (r)))
+#define SMC_outw(lp, v, a, r)	outw(v, (unsigned long) ((a) + (r)))
 #define SMC_insw(a, r, p, l)	insw((unsigned long) ((a) + (r)), (p), (l))
 #define SMC_outsw(a, r, p, l)	outsw((unsigned long) ((a) + (r)), (p), (l))
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/nios2/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/nios2/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/nios2/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/nios2/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <asm-generic/mutex-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/nios2/include/asm/page.h linux-libre-4.10-rc8-gnu/arch/nios2/include/asm/page.h
--- linux-libre-4.9-gnu/arch/nios2/include/asm/page.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/nios2/include/asm/page.h	2017-02-12 16:03:20.000000000 -0500
@@ -76,8 +76,6 @@ extern unsigned long memory_size;
 
 extern struct page *mem_map;
 
-#endif /* !__ASSEMBLY__ */
-
 # define __pa(x)		\
 	((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
 # define __va(x)		\
@@ -87,8 +85,15 @@ extern struct page *mem_map;
 	((void *)(((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
 
 # define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
-# define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET &&	\
-					(pfn) < max_mapnr)
+
+static inline bool pfn_valid(unsigned long pfn)
+{
+	/* avoid <linux/mm.h> include hell */
+	extern unsigned long max_mapnr;
+	unsigned long pfn_offset = ARCH_PFN_OFFSET;
+
+	return pfn >= pfn_offset && pfn < max_mapnr;
+}
 
 # define virt_to_page(vaddr)	pfn_to_page(PFN_DOWN(virt_to_phys(vaddr)))
 # define virt_addr_valid(vaddr)	pfn_valid(PFN_DOWN(virt_to_phys(vaddr)))
@@ -106,4 +111,6 @@ extern struct page *mem_map;
 
 #include <asm-generic/getorder.h>
 
+#endif /* !__ASSEMBLY__ */
+
 #endif /* _ASM_NIOS2_PAGE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/nios2/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/nios2/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/nios2/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/nios2/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -88,7 +88,6 @@ extern unsigned long get_wchan(struct ta
 #define KSTK_ESP(tsk)	((tsk)->thread.kregs->sp)
 
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency()  cpu_relax()
 
 #endif /* __ASSEMBLY__ */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/nios2/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/nios2/kernel/setup.c
--- linux-libre-4.9-gnu/arch/nios2/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/nios2/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/bootmem.h>
 #include <linux/initrd.h>
 #include <linux/of_fdt.h>
+#include <linux/screen_info.h>
 
 #include <asm/mmu_context.h>
 #include <asm/sections.h>
@@ -36,6 +37,10 @@ static struct pt_regs fake_regs = { 0, 0
 					0, 0, 0, 0, 0, 0,
 					0};
 
+#ifdef CONFIG_VT
+struct screen_info screen_info;
+#endif
+
 /* Copy a short hook instruction sequence to the exception address */
 static inline void copy_exception_handler(unsigned int addr)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/nios2/kernel/time.c linux-libre-4.10-rc8-gnu/arch/nios2/kernel/time.c
--- linux-libre-4.9-gnu/arch/nios2/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/nios2/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,7 +81,7 @@ static inline unsigned long read_timersn
 	return count;
 }
 
-static cycle_t nios2_timer_read(struct clocksource *cs)
+static u64 nios2_timer_read(struct clocksource *cs)
 {
 	struct nios2_clocksource *nios2_cs = to_nios2_clksource(cs);
 	unsigned long flags;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/nios2/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/nios2/kernel/traps.c
--- linux-libre-4.9-gnu/arch/nios2/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/nios2/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 #include <asm/traps.h>
 #include <asm/sections.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static DEFINE_SPINLOCK(die_lock);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/nios2/mm/dma-mapping.c linux-libre-4.10-rc8-gnu/arch/nios2/mm/dma-mapping.c
--- linux-libre-4.9-gnu/arch/nios2/mm/dma-mapping.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/nios2/mm/dma-mapping.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,13 +98,17 @@ static int nios2_dma_map_sg(struct devic
 	int i;
 
 	for_each_sg(sg, sg, nents, i) {
-		void *addr;
+		void *addr = sg_virt(sg);
 
-		addr = sg_virt(sg);
-		if (addr) {
-			__dma_sync_for_device(addr, sg->length, direction);
-			sg->dma_address = sg_phys(sg);
-		}
+		if (!addr)
+			continue;
+
+		sg->dma_address = sg_phys(sg);
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
+		__dma_sync_for_device(addr, sg->length, direction);
 	}
 
 	return nents;
@@ -117,7 +121,9 @@ static dma_addr_t nios2_dma_map_page(str
 {
 	void *addr = page_address(page) + offset;
 
-	__dma_sync_for_device(addr, size, direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		__dma_sync_for_device(addr, size, direction);
+
 	return page_to_phys(page) + offset;
 }
 
@@ -125,7 +131,8 @@ static void nios2_dma_unmap_page(struct
 		size_t size, enum dma_data_direction direction,
 		unsigned long attrs)
 {
-	__dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		__dma_sync_for_cpu(phys_to_virt(dma_address), size, direction);
 }
 
 static void nios2_dma_unmap_sg(struct device *dev, struct scatterlist *sg,
@@ -138,6 +145,9 @@ static void nios2_dma_unmap_sg(struct de
 	if (direction == DMA_TO_DEVICE)
 		return;
 
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return;
+
 	for_each_sg(sg, sg, nhwentries, i) {
 		addr = sg_virt(sg);
 		if (addr)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/openrisc/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-/*
- * OpenRISC Linux
- *
- * Linux architectural port borrowing liberally from similar works of
- * others.  All original copyrights apply as per the original source
- * declaration.
- *
- * OpenRISC implementation:
- * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
- * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
- * et al.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/include/asm/pgalloc.h linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/pgalloc.h
--- linux-libre-4.9-gnu/arch/openrisc/include/asm/pgalloc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/pgalloc.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/threads.h>
 #include <linux/mm.h>
 #include <linux/memblock.h>
-#include <linux/bootmem.h>
 
 extern int mem_init_done;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/include/asm/pgtable.h linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/pgtable.h
--- linux-libre-4.9-gnu/arch/openrisc/include/asm/pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -69,7 +69,7 @@ extern void paging_init(void);
  */
 #define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-2))
 
-#define PTRS_PER_PGD	(1UL << (PAGE_SHIFT-2))
+#define PTRS_PER_PGD	(1UL << (32-PGDIR_SHIFT))
 
 /* calculate how many PGD entries a user-level program can use
  * the first mappable virtual address is 0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/openrisc/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -92,7 +92,6 @@ extern unsigned long thread_saved_pc(str
 #define init_stack      (init_thread_union.stack)
 
 #define cpu_relax()     barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_OPENRISC_PROCESSOR_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/Kconfig linux-libre-4.10-rc8-gnu/arch/openrisc/Kconfig
--- linux-libre-4.9-gnu/arch/openrisc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@ config OPENRISC
 	select HAVE_DEBUG_STACKOVERFLOW
 	select OR1K_PIC
 	select CPU_NO_EFFICIENT_FFS if !OPENRISC_HAVE_INST_FF1
+	select NO_BOOTMEM
 
 config MMU
 	def_bool y
@@ -98,6 +99,9 @@ config OPENRISC_HAVE_INST_DIV
 	  Select this if your implementation has a hardware divide instruction
 endmenu
 
+config NR_CPUS
+	int
+	default "1"
 
 source kernel/Kconfig.hz
 source kernel/Kconfig.preempt
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/dma.c linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/dma.c
--- linux-libre-4.9-gnu/arch/openrisc/kernel/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -141,6 +141,9 @@ or1k_map_page(struct device *dev, struct
 	unsigned long cl;
 	dma_addr_t addr = page_to_phys(page) + offset;
 
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return addr;
+
 	switch (dir) {
 	case DMA_TO_DEVICE:
 		/* Flush the dcache for the requested range */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/entry.S linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/entry.S
--- linux-libre-4.9-gnu/arch/openrisc/kernel/entry.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/entry.S	2017-02-12 16:03:20.000000000 -0500
@@ -264,7 +264,7 @@ EXCEPTION_ENTRY(_data_page_fault_handler
 	l.srli  r6,r6,26                   // check opcode for write access
 #endif
 
-	l.sfgeui r6,0x34		   // check opcode for write access
+	l.sfgeui r6,0x33		   // check opcode for write access
 	l.bnf   1f
 	l.sfleui r6,0x37
 	l.bnf   1f
@@ -1101,8 +1101,16 @@ ENTRY(__sys_fork)
 	 l.addi	r3,r1,0
 
 ENTRY(sys_rt_sigreturn)
-	l.j	_sys_rt_sigreturn
+	l.jal	_sys_rt_sigreturn
+	 l.addi	r3,r1,0
+	l.sfne	r30,r0
+	l.bnf	_no_syscall_trace
+	 l.nop
+	l.jal	do_syscall_trace_leave
 	 l.addi	r3,r1,0
+_no_syscall_trace:
+	l.j	_resume_userspace
+	 l.nop
 
 /* This is a catch-all syscall for atomic instructions for the OpenRISC 1000.
  * The functions takes a variable number of parameters depending on which
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/or32_ksyms.c linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/or32_ksyms.c
--- linux-libre-4.9-gnu/arch/openrisc/kernel/or32_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/or32_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/semaphore.h>
 
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
 #include <asm/hardirq.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/process.c linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/process.c
--- linux-libre-4.9-gnu/arch/openrisc/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 #include <linux/mqueue.h>
 #include <linux/fs.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -173,6 +173,19 @@ copy_thread(unsigned long clone_flags, u
 
 		if (usp)
 			userregs->sp = usp;
+
+		/*
+		 * For CLONE_SETTLS set "tp" (r10) to the TLS pointer passed to sys_clone.
+		 *
+		 * The kernel entry is:
+		 *	int clone (long flags, void *child_stack, int *parent_tid,
+		 *		int *child_tid, struct void *tls)
+		 *
+		 * This makes the source r7 in the kernel registers.
+		 */
+		if (clone_flags & CLONE_SETTLS)
+			userregs->gpr[10] = userregs->gpr[7];
+
 		userregs->gpr[11] = 0;	/* Result from fork() */
 
 		kregs->gpr[20] = 0;	/* Userspace thread */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/setup.c
--- linux-libre-4.9-gnu/arch/openrisc/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,6 @@
 #include <linux/of.h>
 #include <linux/memblock.h>
 #include <linux/device.h>
-#include <linux/of_platform.h>
 
 #include <asm/sections.h>
 #include <asm/segment.h>
@@ -51,18 +50,16 @@
 
 #include "vmlinux.h"
 
-static unsigned long __init setup_memory(void)
+static void __init setup_memory(void)
 {
-	unsigned long bootmap_size;
 	unsigned long ram_start_pfn;
-	unsigned long free_ram_start_pfn;
 	unsigned long ram_end_pfn;
 	phys_addr_t memory_start, memory_end;
 	struct memblock_region *region;
 
 	memory_end = memory_start = 0;
 
-	/* Find main memory where is the kernel */
+	/* Find main memory where is the kernel, we assume its the only one */
 	for_each_memblock(memory, region) {
 		memory_start = region->base;
 		memory_end = region->base + region->size;
@@ -75,10 +72,11 @@ static unsigned long __init setup_memory
 	}
 
 	ram_start_pfn = PFN_UP(memory_start);
-	/* free_ram_start_pfn is first page after kernel */
-	free_ram_start_pfn = PFN_UP(__pa(_end));
 	ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
 
+	/* setup bootmem globals (we use no_bootmem, but mm still depends on this) */
+	min_low_pfn = ram_start_pfn;
+	max_low_pfn = ram_end_pfn;
 	max_pfn = ram_end_pfn;
 
 	/*
@@ -86,22 +84,13 @@ static unsigned long __init setup_memory
 	 *
 	 * This makes the memory from the end of the kernel to the end of
 	 * RAM usable.
-	 * init_bootmem sets the global values min_low_pfn, max_low_pfn.
 	 */
-	bootmap_size = init_bootmem(free_ram_start_pfn,
-				    ram_end_pfn - ram_start_pfn);
-	free_bootmem(PFN_PHYS(free_ram_start_pfn),
-		     (ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
-	reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
-			BOOTMEM_DEFAULT);
+	memblock_reserve(__pa(_stext), _end - _stext);
 
-	for_each_memblock(reserved, region) {
-		printk(KERN_INFO "Reserved - 0x%08x-0x%08x\n",
-		       (u32) region->base, (u32) region->size);
-		reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
-	}
+	early_init_fdt_reserve_self();
+	early_init_fdt_scan_reserved_mem();
 
-	return ram_end_pfn;
+	memblock_dump_all();
 }
 
 struct cpuinfo cpuinfo;
@@ -219,15 +208,6 @@ void __init or32_early_setup(void *fdt)
 	early_init_devtree(fdt);
 }
 
-static int __init openrisc_device_probe(void)
-{
-	of_platform_populate(NULL, NULL, NULL, NULL);
-
-	return 0;
-}
-
-device_initcall(openrisc_device_probe);
-
 static inline unsigned long extract_value_bits(unsigned long reg,
 					       short bit_nr, short width)
 {
@@ -282,8 +262,6 @@ void calibrate_delay(void)
 
 void __init setup_arch(char **cmdline_p)
 {
-	unsigned long max_low_pfn;
-
 	unflatten_and_copy_device_tree();
 
 	setup_cpuinfo();
@@ -304,8 +282,8 @@ void __init setup_arch(char **cmdline_p)
 	initrd_below_start_ok = 1;
 #endif
 
-	/* setup bootmem allocator */
-	max_low_pfn = setup_memory();
+	/* setup memblock allocator */
+	setup_memory();
 
 	/* paging_init() sets up the MMU and marks all pages as reserved */
 	paging_init();
@@ -317,7 +295,7 @@ void __init setup_arch(char **cmdline_p)
 
 	*cmdline_p = boot_command_line;
 
-	printk(KERN_INFO "OpenRISC Linux -- http://openrisc.net\n");
+	printk(KERN_INFO "OpenRISC Linux -- http://openrisc.io\n");
 }
 
 static int show_cpuinfo(struct seq_file *m, void *v)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/signal.c
--- linux-libre-4.9-gnu/arch/openrisc/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <asm/processor.h>
 #include <asm/syscall.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define DEBUG_SIG 0
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/time.c linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/time.c
--- linux-libre-4.9-gnu/arch/openrisc/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -117,9 +117,9 @@ static __init void openrisc_clockevent_i
  * is 32 bits wide and runs at the CPU clock frequency.
  */
 
-static cycle_t openrisc_timer_read(struct clocksource *cs)
+static u64 openrisc_timer_read(struct clocksource *cs)
 {
-	return (cycle_t) mfspr(SPR_TTCR);
+	return (u64) mfspr(SPR_TTCR);
 }
 
 static struct clocksource openrisc_timer = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/traps.c
--- linux-libre-4.9-gnu/arch/openrisc/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/timer.h>
 #include <linux/mm.h>
 #include <linux/kallsyms.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/kernel/vmlinux.lds.S linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/vmlinux.lds.S
--- linux-libre-4.9-gnu/arch/openrisc/kernel/vmlinux.lds.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/kernel/vmlinux.lds.S	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,13 @@
 #include <asm/cache.h>
 #include <asm-generic/vmlinux.lds.h>
 
-OUTPUT_FORMAT("elf32-or32", "elf32-or32", "elf32-or32")
+#ifdef __OR1K__
+#define __OUTPUT_FORMAT        "elf32-or1k"
+#else
+#define __OUTPUT_FORMAT        "elf32-or32"
+#endif
+
+OUTPUT_FORMAT(__OUTPUT_FORMAT, __OUTPUT_FORMAT, __OUTPUT_FORMAT)
 jiffies = jiffies_64 + 4;
 
 SECTIONS
@@ -38,6 +44,8 @@ SECTIONS
         /* Read-only sections, merged into text segment: */
         . = LOAD_BASE ;
 
+	_text = .;
+
 	/* _s_kernel_ro must be page aligned */
 	. = ALIGN(PAGE_SIZE);
 	_s_kernel_ro = .;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/mm/fault.c linux-libre-4.10-rc8-gnu/arch/openrisc/mm/fault.c
--- linux-libre-4.9-gnu/arch/openrisc/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/siginfo.h>
 #include <asm/signal.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/mm/init.c linux-libre-4.10-rc8-gnu/arch/openrisc/mm/init.c
--- linux-libre-4.9-gnu/arch/openrisc/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -106,11 +106,11 @@ static void __init map_ram(void)
 			}
 
 			/* Alloc one page for holding PTE's... */
-			pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+			pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
 			set_pmd(pme, __pmd(_KERNPG_TABLE + __pa(pte)));
 
 			/* Fill the newly allocated page with PTE'S */
-			for (j = 0; p < e && j < PTRS_PER_PGD;
+			for (j = 0; p < e && j < PTRS_PER_PTE;
 			     v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
 				if (v >= (u32) _e_kernel_ro ||
 				    v < (u32) _s_kernel_ro)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/mm/ioremap.c linux-libre-4.10-rc8-gnu/arch/openrisc/mm/ioremap.c
--- linux-libre-4.9-gnu/arch/openrisc/mm/ioremap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/mm/ioremap.c	2017-02-12 16:03:20.000000000 -0500
@@ -124,11 +124,7 @@ pte_t __ref *pte_alloc_one_kernel(struct
 	if (likely(mem_init_done)) {
 		pte = (pte_t *) __get_free_page(GFP_KERNEL);
 	} else {
-		pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-#if 0
-		/* FIXME: use memblock... */
 		pte = (pte_t *) __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE));
-#endif
 	}
 
 	if (pte)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/README.openrisc linux-libre-4.10-rc8-gnu/arch/openrisc/README.openrisc
--- linux-libre-4.9-gnu/arch/openrisc/README.openrisc	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/README.openrisc	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@ target architecture, specifically, is th
 
 For information about OpenRISC processors and ongoing development:
 
-	website		http://openrisc.net
+	website		http://openrisc.io
 
 For more information about Linux on OpenRISC, please contact South Pole AB.
 
@@ -24,17 +24,17 @@ In order to build and run Linux for Open
 toolchain and, perhaps, the architectural simulator.  Steps to get these bits
 in place are outlined here.
 
-1)  The toolchain can be obtained from openrisc.net.  Instructions for building
+1)  The toolchain can be obtained from openrisc.io.  Instructions for building
 a toolchain can be found at:
 
-http://openrisc.net/toolchain-build.html
+https://github.com/openrisc/tutorials
 
 2) or1ksim (optional)
 
 or1ksim is the architectural simulator which will allow you to actually run
 your OpenRISC Linux kernel if you don't have an OpenRISC processor at hand.
 
-	git clone git://openrisc.net/jonas/or1ksim-svn
+	git clone https://github.com/openrisc/or1ksim.git
 
 	cd or1ksim
 	./configure --prefix=$OPENRISC_PREFIX
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/openrisc/TODO.openrisc linux-libre-4.10-rc8-gnu/arch/openrisc/TODO.openrisc
--- linux-libre-4.9-gnu/arch/openrisc/TODO.openrisc	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/openrisc/TODO.openrisc	2017-02-12 16:03:20.000000000 -0500
@@ -5,9 +5,6 @@ that are due for investigation shortly,
 
 -- Implement the rest of the DMA API... dma_map_sg, etc.
 
--- Consolidate usage of memblock and bootmem... move everything over to
-   memblock.
-
 -- Finish the renaming cleanup... there are references to or32 in the code
    which was an older name for the architecture.  The name we've settled on is
    or1k and this change is slowly trickling through the stack.  For the time
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/asm/bitops.h linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/bitops.h
--- linux-libre-4.9-gnu/arch/parisc/include/asm/bitops.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/bitops.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
 #endif
 
 #include <linux/compiler.h>
-#include <asm/types.h>		/* for BITS_PER_LONG/SHIFT_PER_LONG */
+#include <asm/types.h>
 #include <asm/byteorder.h>
 #include <asm/barrier.h>
 #include <linux/atomic.h>
@@ -17,6 +17,12 @@
  * to include/asm-i386/bitops.h or kerneldoc
  */
 
+#if __BITS_PER_LONG == 64
+#define SHIFT_PER_LONG 6
+#else
+#define SHIFT_PER_LONG 5
+#endif
+
 #define CHOP_SHIFTCOUNT(x) (((unsigned long) (x)) & (BITS_PER_LONG - 1))
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/asm/elf.h linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/elf.h
--- linux-libre-4.9-gnu/arch/parisc/include/asm/elf.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/elf.h	2017-02-12 16:03:20.000000000 -0500
@@ -348,9 +348,10 @@ struct pt_regs;	/* forward declaration..
 
 #define ELF_HWCAP	0
 
-#define STACK_RND_MASK	(is_32bit_task() ? \
-				0x7ff >> (PAGE_SHIFT - 12) : \
-				0x3ffff >> (PAGE_SHIFT - 12))
+/* Masks for stack and mmap randomization */
+#define BRK_RND_MASK	(is_32bit_task() ? 0x07ffUL : 0x3ffffUL)
+#define MMAP_RND_MASK	(is_32bit_task() ? 0x1fffUL : 0x3ffffUL)
+#define STACK_RND_MASK	MMAP_RND_MASK
 
 struct mm_struct;
 extern unsigned long arch_randomize_brk(struct mm_struct *);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/parisc/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,6 @@ generic-y += local.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
-generic-y += mutex.h
 generic-y += param.h
 generic-y += percpu.h
 generic-y += poll.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/asm/pdcpat.h linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/pdcpat.h
--- linux-libre-4.9-gnu/arch/parisc/include/asm/pdcpat.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/pdcpat.h	2017-02-12 16:03:20.000000000 -0500
@@ -289,7 +289,7 @@ extern int pdc_pat_cell_get_number(struc
 extern int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, unsigned long view_type, void *mem_addr);
 extern int pdc_pat_cell_num_to_loc(void *, unsigned long);
 
-extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa);
+extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned long hpa);
 
 extern int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, unsigned long count, unsigned long offset);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/parisc/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -93,9 +93,7 @@ struct system_cpuinfo_parisc {
 /* Per CPU data structure - ie varies per CPU.  */
 struct cpuinfo_parisc {
 	unsigned long it_value;     /* Interval Timer at last timer Intr */
-	unsigned long it_delta;     /* Interval delta (tic_10ms / HZ * 100) */
 	unsigned long irq_count;    /* number of IRQ's since boot */
-	unsigned long irq_max_cr16; /* longest time to handle a single IRQ */
 	unsigned long cpuid;        /* aka slot_number or set to NO_PROC_ID */
 	unsigned long hpa;          /* Host Physical address */
 	unsigned long txn_addr;     /* MMIO addr of EIR or id_eid */
@@ -103,8 +101,6 @@ struct cpuinfo_parisc {
 	unsigned long pending_ipi;  /* bitmap of type ipi_message_type */
 #endif
 	unsigned long bh_count;     /* number of times bh was invoked */
-	unsigned long prof_counter; /* per CPU profiling support */
-	unsigned long prof_multiplier;	/* per CPU profiling support */
 	unsigned long fp_rev;
 	unsigned long fp_model;
 	unsigned int state;
@@ -309,7 +305,6 @@ extern unsigned long get_wchan(struct ta
 #define KSTK_ESP(tsk)	((tsk)->thread.regs.gr[30])
 
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 /*
  * parisc_requires_coherency() is used to identify the combined VIPT/PIPT
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/asm/thread_info.h linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/thread_info.h
--- linux-libre-4.9-gnu/arch/parisc/include/asm/thread_info.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/asm/thread_info.h	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,6 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG	3	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_32BIT               4       /* 32 bit binary */
 #define TIF_MEMDIE		5	/* is terminating due to OOM killer */
-#define TIF_RESTORE_SIGMASK	6	/* restore saved signal mask */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_NOTIFY_RESUME	8	/* callback before returning to user */
 #define TIF_SINGLESTEP		9	/* single stepping? */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/uapi/asm/bitsperlong.h linux-libre-4.10-rc8-gnu/arch/parisc/include/uapi/asm/bitsperlong.h
--- linux-libre-4.9-gnu/arch/parisc/include/uapi/asm/bitsperlong.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/uapi/asm/bitsperlong.h	2017-02-12 16:03:20.000000000 -0500
@@ -3,10 +3,8 @@
 
 #if defined(__LP64__)
 #define __BITS_PER_LONG 64
-#define SHIFT_PER_LONG 6
 #else
 #define __BITS_PER_LONG 32
-#define SHIFT_PER_LONG 5
 #endif
 
 #include <asm-generic/bitsperlong.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/parisc/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/parisc/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -89,4 +89,6 @@
 
 #define SO_CNX_ADVICE		0x402E
 
+#define SCM_TIMESTAMPING_OPT_STATS	0x402F
+
 #endif /* _UAPI_ASM_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/include/uapi/asm/swab.h linux-libre-4.10-rc8-gnu/arch/parisc/include/uapi/asm/swab.h
--- linux-libre-4.9-gnu/arch/parisc/include/uapi/asm/swab.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/include/uapi/asm/swab.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,7 @@
 #ifndef _PARISC_SWAB_H
 #define _PARISC_SWAB_H
 
+#include <asm/bitsperlong.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
 
@@ -38,7 +39,7 @@ static inline __attribute_const__ __u32
 }
 #define __arch_swab32 __arch_swab32
 
-#if BITS_PER_LONG > 32
+#if __BITS_PER_LONG > 32
 /*
 ** From "PA-RISC 2.0 Architecture", HP Professional Books.
 ** See Appendix I page 8 , "Endian Byte Swapping".
@@ -61,6 +62,6 @@ static inline __attribute_const__ __u64
 	return x;
 }
 #define __arch_swab64 __arch_swab64
-#endif /* BITS_PER_LONG > 32 */
+#endif /* __BITS_PER_LONG > 32 */
 
 #endif /* _PARISC_SWAB_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/Kconfig linux-libre-4.10-rc8-gnu/arch/parisc/Kconfig
--- linux-libre-4.9-gnu/arch/parisc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@ config PARISC
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_SYSCALL_TRACEPOINTS
 	select ARCH_WANT_FRAME_POINTERS
+	select ARCH_HAS_ELF_RANDOMIZE
 	select RTC_CLASS
 	select RTC_DRV_GENERIC
 	select INIT_ALL_POSSIBLE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/asm-offsets.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/asm-offsets.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/asm-offsets.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/asm-offsets.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/pdc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_64BIT
 #define FRAME_SIZE	128
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/entry.S linux-libre-4.10-rc8-gnu/arch/parisc/kernel/entry.S
--- linux-libre-4.9-gnu/arch/parisc/kernel/entry.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/entry.S	2017-02-12 16:03:20.000000000 -0500
@@ -878,6 +878,9 @@ ENTRY_CFI(syscall_exit_rfi)
 	STREG   %r19,PT_SR7(%r16)
 
 intr_return:
+	/* NOTE: Need to enable interrupts incase we schedule. */
+	ssm     PSW_SM_I, %r0
+
 	/* check for reschedule */
 	mfctl   %cr30,%r1
 	LDREG   TI_FLAGS(%r1),%r19	/* sched.h: TIF_NEED_RESCHED */
@@ -904,11 +907,6 @@ intr_check_sig:
 	LDREG	PT_IASQ1(%r16), %r20
 	cmpib,COND(=),n 0,%r20,intr_restore /* backward */
 
-	/* NOTE: We need to enable interrupts if we have to deliver
-	 * signals. We used to do this earlier but it caused kernel
-	 * stack overflows. */
-	ssm     PSW_SM_I, %r0
-
 	copy	%r0, %r25			/* long in_syscall = 0 */
 #ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29			/* Reference param save area */
@@ -960,10 +958,6 @@ intr_do_resched:
 	cmpib,COND(=)	0, %r20, intr_do_preempt
 	nop
 
-	/* NOTE: We need to enable interrupts if we schedule.  We used
-	 * to do this earlier but it caused kernel stack overflows. */
-	ssm     PSW_SM_I, %r0
-
 #ifdef CONFIG_64BIT
 	ldo	-16(%r30),%r29		/* Reference param save area */
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/firmware.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/firmware.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/firmware.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/firmware.c	2017-02-12 16:03:20.000000000 -0500
@@ -1258,7 +1258,7 @@ int pdc_pat_cell_module(unsigned long *a
  *
  * Retrieve the cpu number for the cpu at the specified HPA.
  */
-int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa)
+int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned long hpa)
 {
 	int retval;
 	unsigned long flags;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/inventory.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/inventory.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/inventory.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/inventory.c	2017-02-12 16:03:20.000000000 -0500
@@ -216,9 +216,9 @@ pat_query_module(ulong pcell_loc, ulong
 	register_parisc_device(dev);	/* advertise device */
 
 #ifdef DEBUG_PAT
-	pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
 	/* dump what we see so far... */
 	switch (PAT_GET_ENTITY(dev->mod_info)) {
+		pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
 		unsigned long i;
 
 	case PAT_ENTITY_PROC:
@@ -259,9 +259,9 @@ pat_query_module(ulong pcell_loc, ulong
 				pa_pdc_cell->mod[4 + i * 3]);	/* finish (ie end) */
 			printk(KERN_DEBUG 
 				"  IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 
-				i, io_pdc_cell->mod[2 + i * 3],	/* type */
-				io_pdc_cell->mod[3 + i * 3],	/* start */
-				io_pdc_cell->mod[4 + i * 3]);	/* finish (ie end) */
+				i, io_pdc_cell.mod[2 + i * 3],	/* type */
+				io_pdc_cell.mod[3 + i * 3],	/* start */
+				io_pdc_cell.mod[4 + i * 3]);	/* finish (ie end) */
 		}
 		printk(KERN_DEBUG "\n");
 		break;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/parisc_ksyms.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/parisc_ksyms.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/parisc_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/parisc_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@ EXPORT_SYMBOL(__xchg64);
 EXPORT_SYMBOL(__cmpxchg_u64);
 #endif
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 EXPORT_SYMBOL(lclear_user);
 EXPORT_SYMBOL(lstrnlen_user);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/pci-dma.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/pci-dma.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/pci-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/pci-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <asm/io.h>
 #include <asm/page.h>	/* get_order */
 #include <asm/pgalloc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/tlbflush.h>	/* for purge_tlb_*() macros */
 
 static struct proc_dir_entry * proc_gsc_root __read_mostly = NULL;
@@ -459,7 +459,9 @@ static dma_addr_t pa11_dma_map_page(stru
 	void *addr = page_address(page) + offset;
 	BUG_ON(direction == DMA_NONE);
 
-	flush_kernel_dcache_range((unsigned long) addr, size);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		flush_kernel_dcache_range((unsigned long) addr, size);
+
 	return virt_to_phys(addr);
 }
 
@@ -469,8 +471,11 @@ static void pa11_dma_unmap_page(struct d
 {
 	BUG_ON(direction == DMA_NONE);
 
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return;
+
 	if (direction == DMA_TO_DEVICE)
-	    return;
+		return;
 
 	/*
 	 * For PCI_DMA_FROMDEVICE this flush is not necessary for the
@@ -479,7 +484,6 @@ static void pa11_dma_unmap_page(struct d
 	 */
 
 	flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size);
-	return;
 }
 
 static int pa11_dma_map_sg(struct device *dev, struct scatterlist *sglist,
@@ -496,6 +500,10 @@ static int pa11_dma_map_sg(struct device
 
 		sg_dma_address(sg) = (dma_addr_t) virt_to_phys(vaddr);
 		sg_dma_len(sg) = sg->length;
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		flush_kernel_dcache_range(vaddr, sg->length);
 	}
 	return nents;
@@ -510,14 +518,16 @@ static void pa11_dma_unmap_sg(struct dev
 
 	BUG_ON(direction == DMA_NONE);
 
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return;
+
 	if (direction == DMA_TO_DEVICE)
-	    return;
+		return;
 
 	/* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */
 
 	for_each_sg(sglist, sg, nents, i)
 		flush_kernel_vmap_range(sg_virt(sg), sg->length);
-	return;
 }
 
 static void pa11_dma_sync_single_for_cpu(struct device *dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/perf.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/perf.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/perf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/perf.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 #include <linux/miscdevice.h>
 #include <linux/spinlock.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/perf.h>
 #include <asm/parisc-device.h>
 #include <asm/processor.h>
@@ -301,7 +301,6 @@ static ssize_t perf_read(struct file *fi
 static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, 
 	loff_t *ppos)
 {
-	int err;
 	size_t image_size;
 	uint32_t image_type;
 	uint32_t interface_type;
@@ -320,8 +319,8 @@ static ssize_t perf_write(struct file *f
 	if (count != sizeof(uint32_t))
 		return -EIO;
 
-	if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0) 
-		return err;
+	if (copy_from_user(&image_type, buf, sizeof(uint32_t)))
+		return -EFAULT;
 
 	/* Get the interface type and test type */
    	interface_type = (image_type >> 16) & 0xffff;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/process.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/process.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -276,11 +276,7 @@ void *dereference_function_descriptor(vo
 
 static inline unsigned long brk_rnd(void)
 {
-	/* 8MB for 32bit, 1GB for 64bit */
-	if (is_32bit_task())
-		return (get_random_int() & 0x7ffUL) << PAGE_SHIFT;
-	else
-		return (get_random_int() & 0x3ffffUL) << PAGE_SHIFT;
+	return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT;
 }
 
 unsigned long arch_randomize_brk(struct mm_struct *mm)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/processor.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/processor.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/processor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/processor.c	2017-02-12 16:03:20.000000000 -0500
@@ -78,11 +78,6 @@ DEFINE_PER_CPU(struct cpuinfo_parisc, cp
 static void
 init_percpu_prof(unsigned long cpunum)
 {
-	struct cpuinfo_parisc *p;
-
-	p = &per_cpu(cpu_data, cpunum);
-	p->prof_counter = 1;
-	p->prof_multiplier = 1;
 }
 
 
@@ -99,6 +94,7 @@ static int processor_probe(struct parisc
 	unsigned long txn_addr;
 	unsigned long cpuid;
 	struct cpuinfo_parisc *p;
+	struct pdc_pat_cpu_num cpu_info __maybe_unused;
 
 #ifdef CONFIG_SMP
 	if (num_online_cpus() >= nr_cpu_ids) {
@@ -123,10 +119,6 @@ static int processor_probe(struct parisc
 		ulong status;
 		unsigned long bytecnt;
 	        pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;
-#undef USE_PAT_CPUID
-#ifdef USE_PAT_CPUID
-		struct pdc_pat_cpu_num cpu_info;
-#endif
 
 		pa_pdc_cell = kmalloc(sizeof (*pa_pdc_cell), GFP_KERNEL);
 		if (!pa_pdc_cell)
@@ -145,22 +137,27 @@ static int processor_probe(struct parisc
 
 		kfree(pa_pdc_cell);
 
+		/* get the cpu number */
+		status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start);
+		BUG_ON(PDC_OK != status);
+
+		pr_info("Logical CPU #%lu is physical cpu #%lu at location "
+			"0x%lx with hpa %pa\n",
+			cpuid, cpu_info.cpu_num, cpu_info.cpu_loc,
+			&dev->hpa.start);
+
+#undef USE_PAT_CPUID
 #ifdef USE_PAT_CPUID
 /* We need contiguous numbers for cpuid. Firmware's notion
  * of cpuid is for physical CPUs and we just don't care yet.
  * We'll care when we need to query PAT PDC about a CPU *after*
  * boot time (ie shutdown a CPU from an OS perspective).
  */
-		/* get the cpu number */
-		status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa.start);
-
-		BUG_ON(PDC_OK != status);
-
 		if (cpu_info.cpu_num >= NR_CPUS) {
-			printk(KERN_WARNING "IGNORING CPU at 0x%x,"
+			printk(KERN_WARNING "IGNORING CPU at %pa,"
 				" cpu_slot_id > NR_CPUS"
 				" (%ld > %d)\n",
-				dev->hpa.start, cpu_info.cpu_num, NR_CPUS);
+				&dev->hpa.start, cpu_info.cpu_num, NR_CPUS);
 			/* Ignore CPU since it will only crash */
 			boot_cpu_data.cpu_count--;
 			return 1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/signal.h>
 #include <linux/audit.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/asm-offsets.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/signal32.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/signal32.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/signal32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/signal32.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "signal32.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/signal.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/elf.h>
 #include <asm/ucontext.h>
 #include <asm/rt_sigframe.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/asm-offsets.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/sys_parisc.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/sys_parisc.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/sys_parisc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/sys_parisc.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/elf.h>
 #include <linux/file.h>
 #include <linux/fs.h>
@@ -225,19 +225,17 @@ static unsigned long mmap_rnd(void)
 {
 	unsigned long rnd = 0;
 
-	/*
-	*  8 bits of randomness in 32bit mmaps, 20 address space bits
-	* 28 bits of randomness in 64bit mmaps, 40 address space bits
-	*/
-	if (current->flags & PF_RANDOMIZE) {
-		if (is_32bit_task())
-			rnd = get_random_int() % (1<<8);
-		else
-			rnd = get_random_int() % (1<<28);
-	}
+	if (current->flags & PF_RANDOMIZE)
+		rnd = get_random_int() & MMAP_RND_MASK;
+
 	return rnd << PAGE_SHIFT;
 }
 
+unsigned long arch_mmap_rnd(void)
+{
+	return (get_random_int() & MMAP_RND_MASK) << PAGE_SHIFT;
+}
+
 static unsigned long mmap_legacy_base(void)
 {
 	return TASK_UNMAPPED_BASE + mmap_rnd();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/time.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/time.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/platform_device.h>
 #include <linux/ftrace.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/page.h>
@@ -59,10 +59,9 @@ static unsigned long clocktick __read_mo
  */
 irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
 {
-	unsigned long now, now2;
+	unsigned long now;
 	unsigned long next_tick;
-	unsigned long cycles_elapsed, ticks_elapsed = 1;
-	unsigned long cycles_remainder;
+	unsigned long ticks_elapsed = 0;
 	unsigned int cpu = smp_processor_id();
 	struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
 
@@ -71,102 +70,49 @@ irqreturn_t __irq_entry timer_interrupt(
 
 	profile_tick(CPU_PROFILING);
 
-	/* Initialize next_tick to the expected tick time. */
+	/* Initialize next_tick to the old expected tick time. */
 	next_tick = cpuinfo->it_value;
 
-	/* Get current cycle counter (Control Register 16). */
-	now = mfctl(16);
-
-	cycles_elapsed = now - next_tick;
-
-	if ((cycles_elapsed >> 6) < cpt) {
-		/* use "cheap" math (add/subtract) instead
-		 * of the more expensive div/mul method
-		 */
-		cycles_remainder = cycles_elapsed;
-		while (cycles_remainder > cpt) {
-			cycles_remainder -= cpt;
-			ticks_elapsed++;
-		}
-	} else {
-		/* TODO: Reduce this to one fdiv op */
-		cycles_remainder = cycles_elapsed % cpt;
-		ticks_elapsed += cycles_elapsed / cpt;
-	}
-
-	/* convert from "division remainder" to "remainder of clock tick" */
-	cycles_remainder = cpt - cycles_remainder;
-
-	/* Determine when (in CR16 cycles) next IT interrupt will fire.
-	 * We want IT to fire modulo clocktick even if we miss/skip some.
-	 * But those interrupts don't in fact get delivered that regularly.
-	 */
-	next_tick = now + cycles_remainder;
+	/* Calculate how many ticks have elapsed. */
+	do {
+		++ticks_elapsed;
+		next_tick += cpt;
+		now = mfctl(16);
+	} while (next_tick - now > cpt);
 
+	/* Store (in CR16 cycles) up to when we are accounting right now. */
 	cpuinfo->it_value = next_tick;
 
-	/* Program the IT when to deliver the next interrupt.
-	 * Only bottom 32-bits of next_tick are writable in CR16!
-	 */
-	mtctl(next_tick, 16);
+	/* Go do system house keeping. */
+	if (cpu == 0)
+		xtime_update(ticks_elapsed);
 
-	/* Skip one clocktick on purpose if we missed next_tick.
+	update_process_times(user_mode(get_irq_regs()));
+
+	/* Skip clockticks on purpose if we know we would miss those.
 	 * The new CR16 must be "later" than current CR16 otherwise
 	 * itimer would not fire until CR16 wrapped - e.g 4 seconds
 	 * later on a 1Ghz processor. We'll account for the missed
-	 * tick on the next timer interrupt.
+	 * ticks on the next timer interrupt.
+	 * We want IT to fire modulo clocktick even if we miss/skip some.
+	 * But those interrupts don't in fact get delivered that regularly.
 	 *
 	 * "next_tick - now" will always give the difference regardless
 	 * if one or the other wrapped. If "now" is "bigger" we'll end up
 	 * with a very large unsigned number.
 	 */
-	now2 = mfctl(16);
-	if (next_tick - now2 > cpt)
-		mtctl(next_tick+cpt, 16);
-
-#if 1
-/*
- * GGG: DEBUG code for how many cycles programming CR16 used.
- */
-	if (unlikely(now2 - now > 0x3000)) 	/* 12K cycles */
-		printk (KERN_CRIT "timer_interrupt(CPU %d): SLOW! 0x%lx cycles!"
-			" cyc %lX rem %lX "
-			" next/now %lX/%lX\n",
-			cpu, now2 - now, cycles_elapsed, cycles_remainder,
-			next_tick, now );
-#endif
-
-	/* Can we differentiate between "early CR16" (aka Scenario 1) and
-	 * "long delay" (aka Scenario 3)? I don't think so.
-	 *
-	 * Timer_interrupt will be delivered at least a few hundred cycles
-	 * after the IT fires. But it's arbitrary how much time passes
-	 * before we call it "late". I've picked one second.
-	 *
-	 * It's important NO printk's are between reading CR16 and
-	 * setting up the next value. May introduce huge variance.
-	 */
-	if (unlikely(ticks_elapsed > HZ)) {
-		/* Scenario 3: very long delay?  bad in any case */
-		printk (KERN_CRIT "timer_interrupt(CPU %d): delayed!"
-			" cycles %lX rem %lX "
-			" next/now %lX/%lX\n",
-			cpu,
-			cycles_elapsed, cycles_remainder,
-			next_tick, now );
-	}
+	while (next_tick - mfctl(16) > cpt)
+		next_tick += cpt;
 
-	/* Done mucking with unreliable delivery of interrupts.
-	 * Go do system house keeping.
+	/* Program the IT when to deliver the next interrupt.
+	 * Only bottom 32-bits of next_tick are writable in CR16!
+	 * Timer interrupt will be delivered at least a few hundred cycles
+	 * after the IT fires, so if we are too close (<= 500 cycles) to the
+	 * next cycle, simply skip it.
 	 */
-
-	if (!--cpuinfo->prof_counter) {
-		cpuinfo->prof_counter = cpuinfo->prof_multiplier;
-		update_process_times(user_mode(get_irq_regs()));
-	}
-
-	if (cpu == 0)
-		xtime_update(ticks_elapsed);
+	if (next_tick - mfctl(16) <= 500)
+		next_tick += cpt;
+	mtctl(next_tick, 16);
 
 	return IRQ_HANDLED;
 }
@@ -191,7 +137,7 @@ EXPORT_SYMBOL(profile_pc);
 
 /* clock source code */
 
-static cycle_t notrace read_cr16(struct clocksource *cs)
+static u64 notrace read_cr16(struct clocksource *cs)
 {
 	return get_cycles();
 }
@@ -289,9 +235,26 @@ void __init time_init(void)
 
 	cr16_hz = 100 * PAGE0->mem_10msec;  /* Hz */
 
-	/* register at clocksource framework */
-	clocksource_register_hz(&clocksource_cr16, cr16_hz);
-
 	/* register as sched_clock source */
 	sched_clock_register(read_cr16_sched_clock, BITS_PER_LONG, cr16_hz);
 }
+
+static int __init init_cr16_clocksource(void)
+{
+	/*
+	 * The cr16 interval timers are not syncronized across CPUs, so mark
+	 * them unstable and lower rating on SMP systems.
+	 */
+	if (num_online_cpus() > 1) {
+		clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE;
+		clocksource_cr16.rating = 0;
+	}
+
+	/* register at clocksource framework */
+	clocksource_register_hz(&clocksource_cr16,
+		100 * PAGE0->mem_10msec);
+
+	return 0;
+}
+
+device_initcall(init_cr16_clocksource);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/unaligned.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/unaligned.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/unaligned.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/unaligned.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/ratelimit.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/hardirq.h>
 #include <asm/traps.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/kernel/unwind.c linux-libre-4.10-rc8-gnu/arch/parisc/kernel/unwind.c
--- linux-libre-4.9-gnu/arch/parisc/kernel/unwind.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/kernel/unwind.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/kallsyms.h>
 #include <linux/sort.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/assembly.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/lib/checksum.c linux-libre-4.10-rc8-gnu/arch/parisc/lib/checksum.c
--- linux-libre-4.9-gnu/arch/parisc/lib/checksum.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/lib/checksum.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <net/checksum.h>
 #include <asm/byteorder.h>
 #include <asm/string.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define addc(_t,_r)                     \
 	__asm__ __volatile__ (          \
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/parisc/mm/fault.c linux-libre-4.10-rc8-gnu/arch/parisc/mm/fault.c
--- linux-libre-4.9-gnu/arch/parisc/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/parisc/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -234,7 +234,7 @@ show_signal_msg(struct pt_regs *regs, un
 	    tsk->comm, code, address);
 	print_vma_addr(KERN_CONT " in ", regs->iaoq[0]);
 
-	pr_cont(" trap #%lu: %s%c", code, trap_name(code),
+	pr_cont("\ntrap #%lu: %s%c", code, trap_name(code),
 		vma ? ',':'\n');
 
 	if (vma)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1023rdb.dts linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1023rdb.dts
--- linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1023rdb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1023rdb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,27 @@
 	#size-cells = <2>;
 	interrupt-parent = <&mpic>;
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		bman_fbpr: bman-fbpr {
+			size = <0 0x1000000>;
+			alignment = <0 0x1000000>;
+		};
+
+		qman_fqd: qman-fqd {
+			size = <0 0x400000>;
+			alignment = <0 0x400000>;
+		};
+
+		qman_pfdr: qman-pfdr {
+			size = <0 0x2000000>;
+			alignment = <0 0x2000000>;
+		};
+	};
+
 	ifc: localbus@ffe124000 {
 		reg = <0xf 0xfe124000 0 0x2000>;
 		ranges = <0 0 0xf 0xe8000000 0x08000000
@@ -72,6 +93,14 @@
 		ranges = <0x00000000 0xf 0x00000000 0x01072000>;
 	};
 
+	bportals: bman-portals@ff4000000 {
+		ranges = <0x0 0xf 0xf4000000 0x2000000>;
+	};
+
+	qportals: qman-portals@ff6000000 {
+		ranges = <0x0 0xf 0xf6000000 0x2000000>;
+	};
+
 	soc: soc@ffe000000 {
 		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
 		reg = <0xf 0xfe000000 0 0x00001000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi
--- linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1023si-post.dtsi	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,21 @@
 
 #include <dt-bindings/thermal/thermal.h>
 
+&bman_fbpr {
+	compatible = "fsl,bman-fbpr";
+	alloc-ranges = <0 0 0x10000 0>;
+};
+
+&qman_fqd {
+	compatible = "fsl,qman-fqd";
+	alloc-ranges = <0 0 0x10000 0>;
+};
+
+&qman_pfdr {
+	compatible = "fsl,qman-pfdr";
+	alloc-ranges = <0 0 0x10000 0>;
+};
+
 &ifc {
 	#address-cells = <2>;
 	#size-cells = <1>;
@@ -180,6 +195,92 @@
 	};
 };
 
+&bportals {
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+	compatible = "simple-bus";
+
+	bman-portal@0 {
+		cell-index = <0x0>;
+		compatible = "fsl,bman-portal";
+		reg = <0x0 0x4000>, <0x1000000 0x1000>;
+		interrupts = <105 2 0 0>;
+	};
+	bman-portal@4000 {
+		cell-index = <0x1>;
+		compatible = "fsl,bman-portal";
+		reg = <0x4000 0x4000>, <0x1001000 0x1000>;
+		interrupts = <107 2 0 0>;
+	};
+	bman-portal@8000 {
+		cell-index = <2>;
+		compatible = "fsl,bman-portal";
+		reg = <0x8000 0x4000>, <0x1002000 0x1000>;
+		interrupts = <109 2 0 0>;
+	};
+	bman-portal@c000 {
+		cell-index = <0x3>;
+		compatible = "fsl,bman-portal";
+		reg = <0xc000 0x4000>, <0x1003000 0x1000>;
+		interrupts = <111 2 0 0>;
+	};
+	bman-portal@10000 {
+		cell-index = <0x4>;
+		compatible = "fsl,bman-portal";
+		reg = <0x10000 0x4000>, <0x1004000 0x1000>;
+		interrupts = <113 2 0 0>;
+	};
+	bman-portal@14000 {
+		cell-index = <0x5>;
+		compatible = "fsl,bman-portal";
+		reg = <0x14000 0x4000>, <0x1005000 0x1000>;
+		interrupts = <115 2 0 0>;
+	};
+};
+
+&qportals {
+	#address-cells = <0x1>;
+	#size-cells = <0x1>;
+	compatible = "simple-bus";
+
+	qportal0: qman-portal@0 {
+		compatible = "fsl,qman-portal";
+		reg = <0x0 0x4000>, <0x1000000 0x1000>;
+		interrupts = <104 0x2 0 0>;
+		cell-index = <0x0>;
+	};
+	qportal1: qman-portal@4000 {
+		compatible = "fsl,qman-portal";
+		reg = <0x4000 0x4000>, <0x1001000 0x1000>;
+		interrupts = <106 0x2 0 0>;
+		cell-index = <0x1>;
+	};
+	qportal2: qman-portal@8000 {
+		compatible = "fsl,qman-portal";
+		reg = <0x8000 0x4000>, <0x1002000 0x1000>;
+		interrupts = <108 0x2 0 0>;
+		cell-index = <0x2>;
+	};
+	qportal3: qman-portal@c000 {
+		compatible = "fsl,qman-portal";
+		reg = <0xc000 0x4000>, <0x1003000 0x1000>;
+		interrupts = <110 0x2 0 0>;
+		cell-index = <0x3>;
+	};
+	qportal4: qman-portal@10000 {
+		compatible = "fsl,qman-portal";
+		reg = <0x10000 0x4000>, <0x1004000 0x1000>;
+		interrupts = <112 0x2 0 0>;
+		cell-index = <0x4>;
+	};
+	qportal5: qman-portal@14000 {
+		compatible = "fsl,qman-portal";
+		reg = <0x14000 0x4000>, <0x1005000 0x1000>;
+		interrupts = <114 0x2 0 0>;
+		cell-index = <0x5>;
+	};
+};
+
 &soc {
 	#address-cells = <1>;
 	#size-cells = <1>;
@@ -413,6 +514,8 @@
 	};
 
 /include/ "qoriq-sec5.0-0.dtsi"
+/include/ "qoriq-qman3.dtsi"
+/include/ "qoriq-bman1.dtsi"
 
 /include/ "qoriq-fman3l-0.dtsi"
 /include/ "qoriq-fman3-0-10g-0-best-effort.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1024qds.dts linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1024qds.dts
--- linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1024qds.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1024qds.dts	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,27 @@
 	#size-cells = <2>;
 	interrupt-parent = <&mpic>;
 
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		bman_fbpr: bman-fbpr {
+			size = <0 0x1000000>;
+			alignment = <0 0x1000000>;
+		};
+
+		qman_fqd: qman-fqd {
+			size = <0 0x400000>;
+			alignment = <0 0x400000>;
+		};
+
+		qman_pfdr: qman-pfdr {
+			size = <0 0x2000000>;
+			alignment = <0 0x2000000>;
+		};
+	};
+
 	ifc: localbus@ffe124000 {
 		reg = <0xf 0xfe124000 0 0x2000>;
 		ranges = <0 0 0xf 0xe8000000 0x08000000
@@ -80,6 +101,14 @@
 		ranges = <0x00000000 0xf 0x00000000 0x01072000>;
 	};
 
+	bportals: bman-portals@ff4000000 {
+		ranges = <0x0 0xf 0xf4000000 0x2000000>;
+	};
+
+	qportals: qman-portals@ff6000000 {
+		ranges = <0x0 0xf 0xf6000000 0x2000000>;
+	};
+
 	soc: soc@ffe000000 {
 		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
 		reg = <0xf 0xfe000000 0 0x00001000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1024rdb.dts linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1024rdb.dts
--- linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1024rdb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1024rdb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,31 @@
 	#size-cells = <2>;
 	interrupt-parent = <&mpic>;
 
+	aliases {
+		sg_2500_aqr105_phy4 = &sg_2500_aqr105_phy4;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		bman_fbpr: bman-fbpr {
+			size = <0 0x1000000>;
+			alignment = <0 0x1000000>;
+		};
+
+		qman_fqd: qman-fqd {
+			size = <0 0x400000>;
+			alignment = <0 0x400000>;
+		};
+
+		qman_pfdr: qman-pfdr {
+			size = <0 0x2000000>;
+			alignment = <0 0x2000000>;
+		};
+	};
+
 	ifc: localbus@ffe124000 {
 		reg = <0xf 0xfe124000 0 0x2000>;
 		ranges = <0 0 0xf 0xe8000000 0x08000000
@@ -82,6 +107,14 @@
 		ranges = <0x00000000 0xf 0x00000000 0x01072000>;
 	};
 
+	bportals: bman-portals@ff4000000 {
+		ranges = <0x0 0xf 0xf4000000 0x2000000>;
+	};
+
+	qportals: qman-portals@ff6000000 {
+		ranges = <0x0 0xf 0xf6000000 0x2000000>;
+	};
+
 	soc: soc@ffe000000 {
 		ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
 		reg = <0xf 0xfe000000 0 0x00001000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1042d4rdb.dts linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1042d4rdb.dts
--- linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t1042d4rdb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t1042d4rdb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,58 @@
 					"fsl,deepsleep-cpld";
 		};
 	};
+
+	soc: soc@ffe000000 {
+		fman0: fman@400000 {
+			ethernet@e0000 {
+				phy-handle = <&phy_sgmii_0>;
+				phy-connection-type = "sgmii";
+			};
+
+			ethernet@e2000 {
+				phy-handle = <&phy_sgmii_1>;
+				phy-connection-type = "sgmii";
+			};
+
+			ethernet@e4000 {
+				phy-handle = <&phy_sgmii_2>;
+				phy-connection-type = "sgmii";
+			};
+
+			ethernet@e6000 {
+				phy-handle = <&phy_rgmii_0>;
+				phy-connection-type = "rgmii";
+			};
+
+			ethernet@e8000 {
+				phy-handle = <&phy_rgmii_1>;
+				phy-connection-type = "rgmii";
+			};
+
+			mdio0: mdio@fc000 {
+				phy_sgmii_0: ethernet-phy@02 {
+					reg = <0x02>;
+				};
+
+				phy_sgmii_1: ethernet-phy@03 {
+					reg = <0x03>;
+				};
+
+				phy_sgmii_2: ethernet-phy@01 {
+					reg = <0x01>;
+				};
+
+				phy_rgmii_0: ethernet-phy@04 {
+					reg = <0x04>;
+				};
+
+				phy_rgmii_1: ethernet-phy@05 {
+					reg = <0x05>;
+				};
+			};
+		};
+	};
+
 };
 
 #include "t1042si-post.dtsi"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t4240rdb.dts linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t4240rdb.dts
--- linux-libre-4.9-gnu/arch/powerpc/boot/dts/fsl/t4240rdb.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/dts/fsl/t4240rdb.dts	2017-02-12 16:03:20.000000000 -0500
@@ -125,6 +125,10 @@
 		};
 
 		i2c@118000 {
+			hwmon@2f {
+				compatible = "winbond,w83793";
+				reg = <0x2f>;
+			};
 			eeprom@52 {
 				compatible = "at24,24c256";
 				reg = <0x52>;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/Makefile linux-libre-4.10-rc8-gnu/arch/powerpc/boot/Makefile
--- linux-libre-4.9-gnu/arch/powerpc/boot/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -172,10 +172,6 @@ $(addprefix $(obj)/,$(libfdt) $(libfdthe
 $(obj)/empty.c:
 	$(Q)touch $@
 
-$(obj)/zImage.lds: $(obj)/%: $(srctree)/$(src)/%.S
-	$(CROSS32CC) $(cpp_flags) -E -Wp,-MD,$(depfile) -P -Upowerpc \
-		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
-
 $(obj)/zImage.coff.lds $(obj)/zImage.ps3.lds : $(obj)/%: $(srctree)/$(src)/%.S
 	$(Q)cp $< $@
 
@@ -357,17 +353,17 @@ $(addprefix $(obj)/, $(initrd-y)): $(obj
 # Don't put the ramdisk on the pattern rule; when its missing make will try
 # the pattern rule with less dependencies that also matches (even with the
 # hard dependency listed).
-$(obj)/zImage.initrd.%: vmlinux $(wrapperbits)
+$(obj)/zImage.initrd.%: vmlinux $(wrapperbits) FORCE
 	$(call if_changed,wrap,$*,,,$(obj)/ramdisk.image.gz)
 
-$(addprefix $(obj)/, $(sort $(filter zImage.%, $(image-y)))): vmlinux $(wrapperbits)
+$(addprefix $(obj)/, $(sort $(filter zImage.%, $(image-y)))): vmlinux $(wrapperbits) FORCE
 	$(call if_changed,wrap,$(subst $(obj)/zImage.,,$@))
 
 # dtbImage% - a dtbImage is a zImage with an embedded device tree blob
-$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb
+$(obj)/dtbImage.initrd.%: vmlinux $(wrapperbits) $(obj)/%.dtb FORCE
 	$(call if_changed,wrap,$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
 
-$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
+$(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb FORCE
 	$(call if_changed,wrap,$*,,$(obj)/$*.dtb)
 
 # This cannot be in the root of $(src) as the zImage rule always adds a $(obj)
@@ -375,31 +371,31 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits
 $(obj)/vmlinux.strip: vmlinux
 	$(STRIP) -s -R .comment $< -o $@
 
-$(obj)/uImage: vmlinux $(wrapperbits)
+$(obj)/uImage: vmlinux $(wrapperbits) FORCE
 	$(call if_changed,wrap,uboot)
 
-$(obj)/uImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/uImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,uboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
 
-$(obj)/uImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/uImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,uboot-$*,,$(obj)/$*.dtb)
 
-$(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/cuImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
 
-$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/cuImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,cuboot-$*,,$(obj)/$*.dtb)
 
-$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/simpleImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
 
-$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/simpleImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,simpleboot-$*,,$(obj)/$*.dtb)
 
-$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/treeImage.initrd.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb,$(obj)/ramdisk.image.gz)
 
-$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits)
+$(obj)/treeImage.%: vmlinux $(obj)/%.dtb $(wrapperbits) FORCE
 	$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
 
 # Rule to build device tree blobs
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/ps3.c linux-libre-4.10-rc8-gnu/arch/powerpc/boot/ps3.c
--- linux-libre-4.9-gnu/arch/powerpc/boot/ps3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/ps3.c	2017-02-12 16:03:20.000000000 -0500
@@ -119,13 +119,12 @@ void ps3_copy_vectors(void)
 	flush_cache((void *)0x100, 512);
 }
 
-void platform_init(unsigned long null_check)
+void platform_init(void)
 {
 	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
 	void *chosen;
 	unsigned long ft_addr;
 	u64 rm_size;
-	unsigned long val;
 
 	console_ops.write = ps3_console_write;
 	platform_ops.exit = ps3_exit;
@@ -153,11 +152,6 @@ void platform_init(unsigned long null_ch
 
 	printf(" flat tree at 0x%lx\n\r", ft_addr);
 
-	val = *(unsigned long *)0;
-
-	if (val != null_check)
-		printf("null check failed: %lx != %lx\n\r", val, null_check);
-
 	((kernel_entry_t)0)(ft_addr, 0, NULL);
 
 	ps3_exit();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/ps3-head.S linux-libre-4.10-rc8-gnu/arch/powerpc/boot/ps3-head.S
--- linux-libre-4.9-gnu/arch/powerpc/boot/ps3-head.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/ps3-head.S	2017-02-12 16:03:20.000000000 -0500
@@ -57,11 +57,6 @@ __system_reset_overlay:
 	bctr
 
 1:
-	/* Save the value at addr zero for a null pointer write check later. */
-
-	li	r4, 0
-	lwz	r3, 0(r4)
-
 	/* Primary delays then goes to _zimage_start in wrapper. */
 
 	or	31, 31, 31 /* db16cyc */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/boot/wrapper linux-libre-4.10-rc8-gnu/arch/powerpc/boot/wrapper
--- linux-libre-4.9-gnu/arch/powerpc/boot/wrapper	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/boot/wrapper	2017-02-12 16:03:20.000000000 -0500
@@ -181,6 +181,28 @@ case "$elfformat" in
     elf32-powerpc)	format=elf32ppc	;;
 esac
 
+ld_version()
+{
+    # Poached from scripts/ld-version.sh, but we don't want to call that because
+    # this script (wrapper) is distributed separately from the kernel source.
+    # Extract linker version number from stdin and turn into single number.
+    awk '{
+	gsub(".*\\)", "");
+	gsub(".*version ", "");
+	gsub("-.*", "");
+	split($1,a, ".");
+	print a[1]*100000000 + a[2]*1000000 + a[3]*10000;
+	exit
+    }'
+}
+
+# Do not include PT_INTERP segment when linking pie. Non-pie linking
+# just ignores this option.
+LD_VERSION=$(${CROSS}ld --version | ld_version)
+LD_NO_DL_MIN_VERSION=$(echo 2.26 | ld_version)
+if [ "$LD_VERSION" -ge "$LD_NO_DL_MIN_VERSION" ] ; then
+	nodl="--no-dynamic-linker"
+fi
 
 platformo=$object/"$platform".o
 lds=$object/zImage.lds
@@ -446,7 +468,7 @@ if [ "$platform" != "miboot" ]; then
         text_start="-Ttext $link_address"
     fi
 #link everything
-    ${CROSS}ld -m $format -T $lds $text_start $pie -o "$ofile" \
+    ${CROSS}ld -m $format -T $lds $text_start $pie $nodl -o "$ofile" \
 	$platformo $tmp $object/wrapper.a
     rm $tmp
 fi
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/amigaone_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/amigaone_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/amigaone_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/amigaone_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -45,12 +45,6 @@ CONFIG_PARPORT_PC_FIFO=y
 CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_SIIMAGE=y
-CONFIG_BLK_DEV_VIA82CXXX=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -61,6 +55,10 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 # CONFIG_SCSI_SYM53C8XX_MMIO is not set
+CONFIG_ATA=y
+CONFIG_PATA_SIL680=y
+CONFIG_PATA_VIA=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 CONFIG_VORTEX=y
 CONFIG_8139CP=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/cell_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/cell_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/cell_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/cell_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -108,16 +108,15 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_IDE=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_AEC62XX=y
-CONFIG_BLK_DEV_SIIMAGE=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
 CONFIG_SATA_PROMISE=y
+CONFIG_PATA_ARTOP=y
 CONFIG_PATA_PDC2027X=m
+CONFIG_PATA_SIL680=y
+CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/chrp32_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/chrp32_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/chrp32_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/chrp32_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -42,12 +42,6 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug
 CONFIG_BLK_DEV_FD=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_SL82C105=y
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
@@ -56,6 +50,10 @@ CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_ATA=y
+CONFIG_PATA_VIA=y
+CONFIG_PATA_WINBOND=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 CONFIG_PCNET32=y
 CONFIG_NET_TULIP=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/dpaa.config linux-libre-4.10-rc8-gnu/arch/powerpc/configs/dpaa.config
--- linux-libre-4.9-gnu/arch/powerpc/configs/dpaa.config	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/dpaa.config	2017-02-12 16:03:20.000000000 -0500
@@ -1 +1,4 @@
 CONFIG_FSL_DPAA=y
+CONFIG_FSL_PAMU=y
+CONFIG_FSL_FMAN=y
+CONFIG_FSL_DPAA_ETH=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/fsl-emb-nonhw.config linux-libre-4.10-rc8-gnu/arch/powerpc/configs/fsl-emb-nonhw.config
--- linux-libre-4.9-gnu/arch/powerpc/configs/fsl-emb-nonhw.config	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/fsl-emb-nonhw.config	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAME_WARN=1024
 CONFIG_FTL=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
 CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_HIGH_RES_TIMERS=y
@@ -104,8 +105,13 @@ CONFIG_PACKET=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_PERF_EVENTS=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
 CONFIG_QNX4FS_FS=m
 CONFIG_RCU_TRACE=y
+CONFIG_RESET_CONTROLLER=y
 CONFIG_ROOT_NFS=y
 CONFIG_SYSV_FS=m
 CONFIG_SYSVIPC=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/g5_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/g5_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/g5_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/g5_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -60,10 +60,6 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_CDROM_PKTCDVD=m
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
@@ -73,6 +69,7 @@ CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_ATA=y
 CONFIG_SATA_SVW=y
+CONFIG_PATA_MACIO=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/maple_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/maple_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/maple_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/maple_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -39,16 +39,15 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_TASK_IOCTL=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_IPR=y
 CONFIG_ATA=y
+CONFIG_PATA_AMD=y
+CONFIG_ATA_GENERIC=y
 CONFIG_NETDEVICES=y
 CONFIG_AMD8111_ETH=y
 CONFIG_TIGON3=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/pasemi_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/pasemi_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/pasemi_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/pasemi_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -58,9 +58,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_EEPROM_LEGACY=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_IDE_TASK_IOCTL=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_CHR_DEV_OSST=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/pmac32_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/pmac32_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/pmac32_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/pmac32_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -117,15 +117,6 @@ CONFIG_CONNECTOR=y
 CONFIG_MAC_FLOPPY=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECS=m
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PDC202XX_NEW=y
-CONFIG_BLK_DEV_SL82C105=y
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
@@ -140,6 +131,12 @@ CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_MESH=y
 CONFIG_SCSI_MAC53C94=y
+CONFIG_ATA=y
+CONFIG_PATA_MACIO=y
+CONFIG_PATA_PDC2027X=y
+CONFIG_PATA_WINBOND=y
+CONFIG_PATA_PCMCIA=m
+CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/powernv_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/powernv_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/powernv_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/powernv_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,7 @@ CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
 CONFIG_HOTPLUG_CPU=y
 CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NUMA=y
 CONFIG_MEMORY_HOTPLUG=y
@@ -241,10 +242,6 @@ CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 CONFIG_JFS_SECURITY=y
@@ -300,7 +297,10 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPT_CRC32C_VPMSUM=m
+CONFIG_CRYPTO_MD5_PPC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -308,6 +308,7 @@ CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SHA1_PPC=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/ppc64_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/ppc64_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/ppc64_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/ppc64_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -46,6 +46,7 @@ CONFIG_HZ_100=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
 CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
 CONFIG_CRASH_DUMP=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTREMOVE=y
@@ -85,12 +86,6 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_VIRTIO_BLK=m
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_AMD74XX=y
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
@@ -120,6 +115,9 @@ CONFIG_SATA_AHCI=y
 CONFIG_SATA_SIL24=y
 CONFIG_SATA_MV=y
 CONFIG_SATA_SVW=y
+CONFIG_PATA_AMD=y
+CONFIG_PATA_MACIO=y
+CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
@@ -335,7 +333,10 @@ CONFIG_PPC_EARLY_DEBUG=y
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPT_CRC32C_VPMSUM=m
+CONFIG_CRYPTO_MD5_PPC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -343,6 +344,7 @@ CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SHA1_PPC=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/ppc64e_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/ppc64e_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/ppc64e_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/ppc64e_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -59,10 +59,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_AMD74XX=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
@@ -79,6 +75,8 @@ CONFIG_SCSI_DEBUG=m
 CONFIG_ATA=y
 CONFIG_SATA_SIL24=y
 CONFIG_SATA_SVW=y
+CONFIG_PATA_AMD=y
+CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/ppc6xx_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/ppc6xx_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/ppc6xx_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/ppc6xx_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -378,13 +378,6 @@ CONFIG_EEPROM_AT24=m
 CONFIG_EEPROM_LEGACY=m
 CONFIG_EEPROM_MAX6875=m
 CONFIG_EEPROM_93CX6=m
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=m
-CONFIG_IDE_TASK_IOCTL=y
-# CONFIG_IDEPCI_PCIBUS_ORDER is not set
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_IDE_PMAC=y
-CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_RAID_ATTRS=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
@@ -411,13 +404,14 @@ CONFIG_ATA=y
 CONFIG_SATA_FSL=m
 CONFIG_PDC_ADMA=m
 CONFIG_ATA_PIIX=m
+CONFIG_PATA_MACIO=y
 CONFIG_PATA_MPC52xx=m
 CONFIG_PATA_OPTIDMA=m
 CONFIG_PATA_SCH=m
 CONFIG_PATA_VIA=m
 CONFIG_PATA_PLATFORM=m
 CONFIG_PATA_OF_PLATFORM=m
-CONFIG_ATA_GENERIC=m
+CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/pseries_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/pseries_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/pseries_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/pseries_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -52,6 +52,7 @@ CONFIG_HZ_100=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
 CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
@@ -92,10 +93,6 @@ CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_VIRTIO_BLK=m
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_AMD74XX=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
@@ -122,7 +119,8 @@ CONFIG_SCSI_DH_RDAC=m
 CONFIG_SCSI_DH_ALUA=m
 CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
-# CONFIG_ATA_SFF is not set
+CONFIG_PATA_AMD=y
+CONFIG_ATA_GENERIC=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
@@ -244,10 +242,6 @@ CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
-CONFIG_REISERFS_FS=m
-CONFIG_REISERFS_FS_XATTR=y
-CONFIG_REISERFS_FS_POSIX_ACL=y
-CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
 CONFIG_JFS_SECURITY=y
@@ -302,7 +296,10 @@ CONFIG_XMON=y
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPT_CRC32C_VPMSUM=m
+CONFIG_CRYPTO_MD5_PPC=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -310,6 +307,7 @@ CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAST6=m
 CONFIG_CRYPTO_KHAZAD=m
 CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SHA1_PPC=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/configs/storcenter_defconfig linux-libre-4.10-rc8-gnu/arch/powerpc/configs/storcenter_defconfig
--- linux-libre-4.9-gnu/arch/powerpc/configs/storcenter_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/configs/storcenter_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -36,12 +36,11 @@ CONFIG_NFTL_RW=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP=y
-CONFIG_IDE=y
-CONFIG_BLK_DEV_VIA82CXXX=y
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_ATA=y
+CONFIG_PATA_VIA=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=y
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/crypto/Makefile linux-libre-4.10-rc8-gnu/arch/powerpc/crypto/Makefile
--- linux-libre-4.9-gnu/arch/powerpc/crypto/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/crypto/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@ obj-$(CONFIG_CRYPTO_MD5_PPC) += md5-ppc.
 obj-$(CONFIG_CRYPTO_SHA1_PPC) += sha1-powerpc.o
 obj-$(CONFIG_CRYPTO_SHA1_PPC_SPE) += sha1-ppc-spe.o
 obj-$(CONFIG_CRYPTO_SHA256_PPC_SPE) += sha256-ppc-spe.o
-obj-$(CONFIG_CRYPT_CRC32C_VPMSUM) += crc32c-vpmsum.o
+obj-$(CONFIG_CRYPTO_CRC32C_VPMSUM) += crc32c-vpmsum.o
 
 aes-ppc-spe-y := aes-spe-core.o aes-spe-keys.o aes-tab-4k.o aes-spe-modes.o aes-spe-glue.o
 md5-ppc-y := md5-asm.o md5-glue.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/asm-prototypes.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/asm-prototypes.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/asm-prototypes.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/asm-prototypes.h	2017-02-12 16:03:20.000000000 -0500
@@ -13,10 +13,9 @@
  */
 
 #include <linux/threads.h>
-#include <linux/kprobes.h>
 #include <asm/cacheflush.h>
 #include <asm/checksum.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/epapr_hcalls.h>
 
 #include <uapi/asm/ucontext.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/32/pgalloc.h	2017-02-12 16:03:20.000000000 -0500
@@ -2,14 +2,42 @@
 #define _ASM_POWERPC_BOOK3S_32_PGALLOC_H
 
 #include <linux/threads.h>
+#include <linux/slab.h>
 
-/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
-#define MAX_PGTABLE_INDEX_SIZE	0
+/*
+ * Functions that deal with pagetables that could be at any level of
+ * the table need to be passed an "index_size" so they know how to
+ * handle allocation.  For PTE pages (which are linked to a struct
+ * page for now, and drawn from the main get_free_pages() pool), the
+ * allocation size will be (2^index_size * sizeof(pointer)) and
+ * allocations are drawn from the kmem_cache in PGT_CACHE(index_size).
+ *
+ * The maximum index size needs to be big enough to allow any
+ * pagetable sizes we need, but small enough to fit in the low bits of
+ * any page table pointer.  In other words all pagetables, even tiny
+ * ones, must be aligned to allow at least enough low 0 bits to
+ * contain this value.  This value is also used as a mask, so it must
+ * be one less than a power of two.
+ */
+#define MAX_PGTABLE_INDEX_SIZE	0xf
 
 extern void __bad_pte(pmd_t *pmd);
 
-extern pgd_t *pgd_alloc(struct mm_struct *mm);
-extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+extern struct kmem_cache *pgtable_cache[];
+#define PGT_CACHE(shift) ({				\
+			BUG_ON(!(shift));		\
+			pgtable_cache[(shift) - 1];	\
+		})
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
+}
 
 /*
  * We don't have any real pmd's, and this code never triggers because
@@ -68,8 +96,12 @@ static inline void pte_free(struct mm_st
 
 static inline void pgtable_free(void *table, unsigned index_size)
 {
-	BUG_ON(index_size); /* 32-bit doesn't use this */
-	free_page((unsigned long)table);
+	if (!index_size) {
+		free_page((unsigned long)table);
+	} else {
+		BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE);
+		kmem_cache_free(PGT_CACHE(index_size), table);
+	}
 }
 
 #define check_pgt_cache()	do { } while (0)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/32/pgtable.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/32/pgtable.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/32/pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/32/pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,23 @@
 /* And here we include common definitions */
 #include <asm/pte-common.h>
 
+#define PTE_INDEX_SIZE	PTE_SHIFT
+#define PMD_INDEX_SIZE	0
+#define PUD_INDEX_SIZE	0
+#define PGD_INDEX_SIZE	(32 - PGDIR_SHIFT)
+
+#define PMD_CACHE_INDEX	PMD_INDEX_SIZE
+
+#ifndef __ASSEMBLY__
+#define PTE_TABLE_SIZE	(sizeof(pte_t) << PTE_INDEX_SIZE)
+#define PMD_TABLE_SIZE	0
+#define PUD_TABLE_SIZE	0
+#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
+#endif	/* __ASSEMBLY__ */
+
+#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
+#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
+
 /*
  * The normal case is that PTEs are 32-bits and we have a 1-page
  * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages.  -- paulus
@@ -19,14 +36,10 @@
  * -Matt
  */
 /* PGDIR_SHIFT determines what a top-level page table entry can map */
-#define PGDIR_SHIFT	(PAGE_SHIFT + PTE_SHIFT)
+#define PGDIR_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
-#define PTRS_PER_PTE	(1 << PTE_SHIFT)
-#define PTRS_PER_PMD	1
-#define PTRS_PER_PGD	(1 << (32 - PGDIR_SHIFT))
-
 #define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 /*
  * This is the bottom of the PKMAP area with HIGHMEM or an arbitrary
@@ -82,12 +95,8 @@
 
 extern unsigned long ioremap_bot;
 
-/*
- * entries per page directory level: our page-table tree is two-level, so
- * we don't really have any PMD directory.
- */
-#define PTE_TABLE_SIZE	(sizeof(pte_t) << PTE_SHIFT)
-#define PGD_TABLE_SIZE	(sizeof(pgd_t) << (32 - PGDIR_SHIFT))
+/* Bits to mask out from a PGD to get to the PUD page */
+#define PGD_MASKED_BITS		0
 
 #define pte_ERROR(e) \
 	pr_err("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \
@@ -224,7 +233,8 @@ static inline void huge_ptep_set_wrprote
 
 
 static inline void __ptep_set_access_flags(struct mm_struct *mm,
-					   pte_t *ptep, pte_t entry)
+					   pte_t *ptep, pte_t entry,
+					   unsigned long address)
 {
 	unsigned long set = pte_val(entry) &
 		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
@@ -283,15 +293,6 @@ static inline void __ptep_set_access_fla
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 3 })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val << 3 })
 
-#ifndef CONFIG_PPC_4K_PAGES
-void pgtable_cache_init(void);
-#else
-/*
- * No page table caches to initialise
- */
-#define pgtable_cache_init()	do { } while (0)
-#endif
-
 extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
 		      pmd_t **pmdp);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hash-4k.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,9 +16,6 @@
 #define H_PUD_TABLE_SIZE	(sizeof(pud_t) << H_PUD_INDEX_SIZE)
 #define H_PGD_TABLE_SIZE	(sizeof(pgd_t) << H_PGD_INDEX_SIZE)
 
-/* With 4k base page size, hugepage PTEs go at the PMD level */
-#define MIN_HUGEPTE_SHIFT	PMD_SHIFT
-
 /* PTE flags to conserve for HPTE identification */
 #define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE | \
 			 H_PAGE_F_SECOND | H_PAGE_F_GIX)
@@ -39,12 +36,13 @@
 #ifdef CONFIG_HUGETLB_PAGE
 static inline int hash__hugepd_ok(hugepd_t hpd)
 {
+	unsigned long hpdval = hpd_val(hpd);
 	/*
 	 * if it is not a pte and have hugepd shift mask
 	 * set, then it is a hugepd directory pointer
 	 */
-	if (!(hpd.pd & _PAGE_PTE) &&
-	    ((hpd.pd & HUGEPD_SHIFT_MASK) != 0))
+	if (!(hpdval & _PAGE_PTE) &&
+	    ((hpdval & HUGEPD_SHIFT_MASK) != 0))
 		return true;
 	return false;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hash-64k.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,9 +6,6 @@
 #define H_PUD_INDEX_SIZE  5
 #define H_PGD_INDEX_SIZE  12
 
-/* With 4k base page size, hugepage PTEs go at the PMD level */
-#define MIN_HUGEPTE_SHIFT	PAGE_SHIFT
-
 #define H_PAGE_COMBO	0x00001000 /* this is a combo 4k page */
 #define H_PAGE_4K_PFN	0x00002000 /* PFN is for a single 4k page */
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hash.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hash.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hash.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hash.h	2017-02-12 16:03:20.000000000 -0500
@@ -201,6 +201,10 @@ extern int __meminit hash__vmemmap_creat
 					      unsigned long phys);
 extern void hash__vmemmap_remove_mapping(unsigned long start,
 				     unsigned long page_size);
+
+int hash__create_section_mapping(unsigned long start, unsigned long end);
+int hash__remove_section_mapping(unsigned long start, unsigned long end);
+
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_BOOK3S_64_HASH_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hugetlb.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hugetlb.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hugetlb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hugetlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,53 @@
+#ifndef _ASM_POWERPC_BOOK3S_64_HUGETLB_H
+#define _ASM_POWERPC_BOOK3S_64_HUGETLB_H
+/*
+ * For radix we want generic code to handle hugetlb. But then if we want
+ * both hash and radix to be enabled together we need to workaround the
+ * limitations.
+ */
+void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern unsigned long
+radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+				unsigned long len, unsigned long pgoff,
+				unsigned long flags);
+
+static inline int hstate_get_psize(struct hstate *hstate)
+{
+	unsigned long shift;
+
+	shift = huge_page_shift(hstate);
+	if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
+		return MMU_PAGE_2M;
+	else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
+		return MMU_PAGE_1G;
+	else if (shift == mmu_psize_defs[MMU_PAGE_16M].shift)
+		return MMU_PAGE_16M;
+	else if (shift == mmu_psize_defs[MMU_PAGE_16G].shift)
+		return MMU_PAGE_16G;
+	else {
+		WARN(1, "Wrong huge page shift\n");
+		return mmu_virtual_psize;
+	}
+}
+
+#define arch_make_huge_pte arch_make_huge_pte
+static inline pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma,
+				       struct page *page, int writable)
+{
+	unsigned long page_shift;
+
+	if (!cpu_has_feature(CPU_FTR_POWER9_DD1))
+		return entry;
+
+	page_shift = huge_page_shift(hstate_vma(vma));
+	/*
+	 * We don't support 1G hugetlb pages yet.
+	 */
+	VM_WARN_ON(page_shift == mmu_psize_defs[MMU_PAGE_1G].shift);
+	if (page_shift == mmu_psize_defs[MMU_PAGE_2M].shift)
+		return __pte(pte_val(entry) | _PAGE_LARGE);
+	else
+		return entry;
+}
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/hugetlb-radix.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-#ifndef _ASM_POWERPC_BOOK3S_64_HUGETLB_RADIX_H
-#define _ASM_POWERPC_BOOK3S_64_HUGETLB_RADIX_H
-/*
- * For radix we want generic code to handle hugetlb. But then if we want
- * both hash and radix to be enabled together we need to workaround the
- * limitations.
- */
-void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-extern unsigned long
-radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
-				unsigned long len, unsigned long pgoff,
-				unsigned long flags);
-
-static inline int hstate_get_psize(struct hstate *hstate)
-{
-	unsigned long shift;
-
-	shift = huge_page_shift(hstate);
-	if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
-		return MMU_PAGE_2M;
-	else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
-		return MMU_PAGE_1G;
-	else {
-		WARN(1, "Wrong huge page shift\n");
-		return mmu_virtual_psize;
-	}
-}
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/mmu-hash.h	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,9 @@
 
 #define HPTE_V_SSIZE_SHIFT	62
 #define HPTE_V_AVPN_SHIFT	7
+#define HPTE_V_COMMON_BITS	ASM_CONST(0x000fffffffffffff)
 #define HPTE_V_AVPN		ASM_CONST(0x3fffffffffffff80)
+#define HPTE_V_AVPN_3_0		ASM_CONST(0x000fffffffffff80)
 #define HPTE_V_AVPN_VAL(x)	(((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
 #define HPTE_V_COMPARE(x,y)	(!(((x) ^ (y)) & 0xffffffffffffff80UL))
 #define HPTE_V_BOLTED		ASM_CONST(0x0000000000000010)
@@ -80,14 +82,16 @@
 #define HPTE_V_VALID		ASM_CONST(0x0000000000000001)
 
 /*
- * ISA 3.0 have a different HPTE format.
+ * ISA 3.0 has a different HPTE format.
  */
 #define HPTE_R_3_0_SSIZE_SHIFT	58
+#define HPTE_R_3_0_SSIZE_MASK	(3ull << HPTE_R_3_0_SSIZE_SHIFT)
 #define HPTE_R_PP0		ASM_CONST(0x8000000000000000)
 #define HPTE_R_TS		ASM_CONST(0x4000000000000000)
 #define HPTE_R_KEY_HI		ASM_CONST(0x3000000000000000)
 #define HPTE_R_RPN_SHIFT	12
 #define HPTE_R_RPN		ASM_CONST(0x0ffffffffffff000)
+#define HPTE_R_RPN_3_0		ASM_CONST(0x01fffffffffff000)
 #define HPTE_R_PP		ASM_CONST(0x0000000000000003)
 #define HPTE_R_PPP		ASM_CONST(0x8000000000000003)
 #define HPTE_R_N		ASM_CONST(0x0000000000000004)
@@ -316,12 +320,43 @@ static inline unsigned long hpte_encode_
 	 */
 	v = (vpn >> (23 - VPN_SHIFT)) & ~(mmu_psize_defs[psize].avpnm);
 	v <<= HPTE_V_AVPN_SHIFT;
-	if (!cpu_has_feature(CPU_FTR_ARCH_300))
-		v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
+	v |= ((unsigned long) ssize) << HPTE_V_SSIZE_SHIFT;
 	return v;
 }
 
 /*
+ * ISA v3.0 defines a new HPTE format, which differs from the old
+ * format in having smaller AVPN and ARPN fields, and the B field
+ * in the second dword instead of the first.
+ */
+static inline unsigned long hpte_old_to_new_v(unsigned long v)
+{
+	/* trim AVPN, drop B */
+	return v & HPTE_V_COMMON_BITS;
+}
+
+static inline unsigned long hpte_old_to_new_r(unsigned long v, unsigned long r)
+{
+	/* move B field from 1st to 2nd dword, trim ARPN */
+	return (r & ~HPTE_R_3_0_SSIZE_MASK) |
+		(((v) >> HPTE_V_SSIZE_SHIFT) << HPTE_R_3_0_SSIZE_SHIFT);
+}
+
+static inline unsigned long hpte_new_to_old_v(unsigned long v, unsigned long r)
+{
+	/* insert B field */
+	return (v & HPTE_V_COMMON_BITS) |
+		((r & HPTE_R_3_0_SSIZE_MASK) <<
+		 (HPTE_V_SSIZE_SHIFT - HPTE_R_3_0_SSIZE_SHIFT));
+}
+
+static inline unsigned long hpte_new_to_old_r(unsigned long r)
+{
+	/* clear out B field */
+	return r & ~HPTE_R_3_0_SSIZE_MASK;
+}
+
+/*
  * This function sets the AVPN and L fields of the HPTE  appropriately
  * using the base page size and actual page size.
  */
@@ -341,12 +376,8 @@ static inline unsigned long hpte_encode_
  * aligned for the requested page size
  */
 static inline unsigned long hpte_encode_r(unsigned long pa, int base_psize,
-					  int actual_psize, int ssize)
+					  int actual_psize)
 {
-
-	if (cpu_has_feature(CPU_FTR_ARCH_300))
-		pa |= ((unsigned long) ssize) << HPTE_R_3_0_SSIZE_SHIFT;
-
 	/* A 4K page needs no special encoding */
 	if (actual_psize == MMU_PAGE_4K)
 		return pa & HPTE_R_RPN;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,11 @@
 #define _RPAGE_SW1		0x00800
 #define _RPAGE_SW2		0x00400
 #define _RPAGE_SW3		0x00200
+#define _RPAGE_RSV1		0x1000000000000000UL
+#define _RPAGE_RSV2		0x0800000000000000UL
+#define _RPAGE_RSV3		0x0400000000000000UL
+#define _RPAGE_RSV4		0x0200000000000000UL
+
 #ifdef CONFIG_MEM_SOFT_DIRTY
 #define _PAGE_SOFT_DIRTY	_RPAGE_SW3 /* software: software dirty tracking */
 #else
@@ -33,6 +38,11 @@
 #endif
 #define _PAGE_SPECIAL		_RPAGE_SW2 /* software: special page */
 
+/*
+ * For P9 DD1 only, we need to track whether the pte's huge.
+ */
+#define _PAGE_LARGE	_RPAGE_RSV1
+
 
 #define _PAGE_PTE		(1ul << 62)	/* distinguishes PTEs from pointers */
 #define _PAGE_PRESENT		(1ul << 63)	/* pte contains a translation */
@@ -568,10 +578,11 @@ static inline bool check_pte_access(unsi
  */
 
 static inline void __ptep_set_access_flags(struct mm_struct *mm,
-					   pte_t *ptep, pte_t entry)
+					   pte_t *ptep, pte_t entry,
+					   unsigned long address)
 {
 	if (radix_enabled())
-		return radix__ptep_set_access_flags(mm, ptep, entry);
+		return radix__ptep_set_access_flags(mm, ptep, entry, address);
 	return hash__ptep_set_access_flags(ptep, entry);
 }
 
@@ -789,9 +800,6 @@ extern struct page *pgd_page(pgd_t pgd);
 #define pgd_ERROR(e) \
 	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
-void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
-void pgtable_cache_init(void);
-
 static inline int map_kernel_page(unsigned long ea, unsigned long pa,
 				  unsigned long flags)
 {
@@ -1009,7 +1017,8 @@ static inline void pmdp_huge_split_prepa
 #define pmd_move_must_withdraw pmd_move_must_withdraw
 struct spinlock;
 static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
-					 struct spinlock *old_pmd_ptl)
+					 struct spinlock *old_pmd_ptl,
+					 struct vm_area_struct *vma)
 {
 	if (radix_enabled())
 		return false;
@@ -1020,6 +1029,16 @@ static inline int pmd_move_must_withdraw
 	 */
 	return true;
 }
+
+
+#define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
+static inline bool arch_needs_pgtable_deposit(void)
+{
+	if (radix_enabled())
+		return false;
+	return true;
+}
+
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 #endif /* __ASSEMBLY__ */
 #endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/radix.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/radix.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/radix.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/radix.h	2017-02-12 16:03:20.000000000 -0500
@@ -140,19 +140,20 @@ static inline unsigned long radix__pte_u
 		unsigned long new_pte;
 
 		old_pte = __radix_pte_update(ptep, ~0, 0);
-		asm volatile("ptesync" : : : "memory");
 		/*
 		 * new value of pte
 		 */
 		new_pte = (old_pte | set) & ~clr;
-
 		/*
-		 * For now let's do heavy pid flush
-		 * radix__flush_tlb_page_psize(mm, addr, mmu_virtual_psize);
+		 * If we are trying to clear the pte, we can skip
+		 * the below sequence and batch the tlb flush. The
+		 * tlb flush batching is done by mmu gather code
 		 */
-		radix__flush_tlb_mm(mm);
-
-		__radix_pte_update(ptep, 0, new_pte);
+		if (new_pte) {
+			asm volatile("ptesync" : : : "memory");
+			radix__flush_tlb_pte_p9_dd1(old_pte, mm, addr);
+			__radix_pte_update(ptep, 0, new_pte);
+		}
 	} else
 		old_pte = __radix_pte_update(ptep, clr, set);
 	asm volatile("ptesync" : : : "memory");
@@ -167,7 +168,8 @@ static inline unsigned long radix__pte_u
  * function doesn't need to invalidate tlb.
  */
 static inline void radix__ptep_set_access_flags(struct mm_struct *mm,
-						pte_t *ptep, pte_t entry)
+						pte_t *ptep, pte_t entry,
+						unsigned long address)
 {
 
 	unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
@@ -183,13 +185,7 @@ static inline void radix__ptep_set_acces
 		 * new value of pte
 		 */
 		new_pte = old_pte | set;
-
-		/*
-		 * For now let's do heavy pid flush
-		 * radix__flush_tlb_page_psize(mm, addr, mmu_virtual_psize);
-		 */
-		radix__flush_tlb_mm(mm);
-
+		radix__flush_tlb_pte_p9_dd1(old_pte, mm, address);
 		__radix_pte_update(ptep, 0, new_pte);
 	} else
 		__radix_pte_update(ptep, 0, set);
@@ -243,6 +239,8 @@ static inline int radix__pmd_trans_huge(
 
 static inline pmd_t radix__pmd_mkhuge(pmd_t pmd)
 {
+	if (cpu_has_feature(CPU_FTR_POWER9_DD1))
+		return __pmd(pmd_val(pmd) | _PAGE_PTE | _PAGE_LARGE);
 	return __pmd(pmd_val(pmd) | _PAGE_PTE);
 }
 static inline void radix__pmdp_huge_split_prepare(struct vm_area_struct *vma,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h	2017-02-12 16:03:20.000000000 -0500
@@ -42,4 +42,6 @@ extern void radix__flush_tlb_lpid_va(uns
 				     unsigned long page_size);
 extern void radix__flush_tlb_lpid(unsigned long lpid);
 extern void radix__flush_tlb_all(void);
+extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
+					unsigned long address);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/cache.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cache.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/cache.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cache.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,12 +20,15 @@
 #endif
 #else /* CONFIG_PPC64 */
 #define L1_CACHE_SHIFT		7
+#define IFETCH_ALIGN_SHIFT	4 /* POWER8,9 */
 #endif
 
 #define	L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
 
 #define	SMP_CACHE_BYTES		L1_CACHE_BYTES
 
+#define IFETCH_ALIGN_BYTES	(1 << IFETCH_ALIGN_SHIFT)
+
 #if defined(__powerpc64__) && !defined(__ASSEMBLY__)
 struct ppc64_caches {
 	u32	dsize;			/* L1 d-cache size */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/cmpxchg.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cmpxchg.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/cmpxchg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cmpxchg.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,71 @@
 #include <asm/asm-compat.h>
 #include <linux/bug.h>
 
+#ifdef __BIG_ENDIAN
+#define BITOFF_CAL(size, off)	((sizeof(u32) - size - off) * BITS_PER_BYTE)
+#else
+#define BITOFF_CAL(size, off)	(off * BITS_PER_BYTE)
+#endif
+
+#define XCHG_GEN(type, sfx, cl)				\
+static inline u32 __xchg_##type##sfx(volatile void *p, u32 val)	\
+{								\
+	unsigned int prev, prev_mask, tmp, bitoff, off;		\
+								\
+	off = (unsigned long)p % sizeof(u32);			\
+	bitoff = BITOFF_CAL(sizeof(type), off);			\
+	p -= off;						\
+	val <<= bitoff;						\
+	prev_mask = (u32)(type)-1 << bitoff;			\
+								\
+	__asm__ __volatile__(					\
+"1:	lwarx   %0,0,%3\n"					\
+"	andc	%1,%0,%5\n"					\
+"	or	%1,%1,%4\n"					\
+	PPC405_ERR77(0,%3)					\
+"	stwcx.	%1,0,%3\n"					\
+"	bne-	1b\n"						\
+	: "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p)		\
+	: "r" (p), "r" (val), "r" (prev_mask)			\
+	: "cc", cl);						\
+								\
+	return prev >> bitoff;					\
+}
+
+#define CMPXCHG_GEN(type, sfx, br, br2, cl)			\
+static inline							\
+u32 __cmpxchg_##type##sfx(volatile void *p, u32 old, u32 new)	\
+{								\
+	unsigned int prev, prev_mask, tmp, bitoff, off;		\
+								\
+	off = (unsigned long)p % sizeof(u32);			\
+	bitoff = BITOFF_CAL(sizeof(type), off);			\
+	p -= off;						\
+	old <<= bitoff;						\
+	new <<= bitoff;						\
+	prev_mask = (u32)(type)-1 << bitoff;			\
+								\
+	__asm__ __volatile__(					\
+	br							\
+"1:	lwarx   %0,0,%3\n"					\
+"	and	%1,%0,%6\n"					\
+"	cmpw	0,%1,%4\n"					\
+"	bne-	2f\n"						\
+"	andc	%1,%0,%6\n"					\
+"	or	%1,%1,%5\n"					\
+	PPC405_ERR77(0,%3)					\
+"	stwcx.  %1,0,%3\n"					\
+"	bne-    1b\n"						\
+	br2							\
+	"\n"							\
+"2:"								\
+	: "=&r" (prev), "=&r" (tmp), "+m" (*(u32*)p)		\
+	: "r" (p), "r" (old), "r" (new), "r" (prev_mask)	\
+	: "cc", cl);						\
+								\
+	return prev >> bitoff;					\
+}
+
 /*
  * Atomic exchange
  *
@@ -14,6 +79,11 @@
  * the previous value stored there.
  */
 
+XCHG_GEN(u8, _local, "memory");
+XCHG_GEN(u8, _relaxed, "cc");
+XCHG_GEN(u16, _local, "memory");
+XCHG_GEN(u16, _relaxed, "cc");
+
 static __always_inline unsigned long
 __xchg_u32_local(volatile void *p, unsigned long val)
 {
@@ -85,9 +155,13 @@ __xchg_u64_relaxed(u64 *p, unsigned long
 #endif
 
 static __always_inline unsigned long
-__xchg_local(volatile void *ptr, unsigned long x, unsigned int size)
+__xchg_local(void *ptr, unsigned long x, unsigned int size)
 {
 	switch (size) {
+	case 1:
+		return __xchg_u8_local(ptr, x);
+	case 2:
+		return __xchg_u16_local(ptr, x);
 	case 4:
 		return __xchg_u32_local(ptr, x);
 #ifdef CONFIG_PPC64
@@ -103,6 +177,10 @@ static __always_inline unsigned long
 __xchg_relaxed(void *ptr, unsigned long x, unsigned int size)
 {
 	switch (size) {
+	case 1:
+		return __xchg_u8_relaxed(ptr, x);
+	case 2:
+		return __xchg_u16_relaxed(ptr, x);
 	case 4:
 		return __xchg_u32_relaxed(ptr, x);
 #ifdef CONFIG_PPC64
@@ -131,6 +209,15 @@ __xchg_relaxed(void *ptr, unsigned long
  * and return the old value of *p.
  */
 
+CMPXCHG_GEN(u8, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory");
+CMPXCHG_GEN(u8, _local, , , "memory");
+CMPXCHG_GEN(u8, _acquire, , PPC_ACQUIRE_BARRIER, "memory");
+CMPXCHG_GEN(u8, _relaxed, , , "cc");
+CMPXCHG_GEN(u16, , PPC_ATOMIC_ENTRY_BARRIER, PPC_ATOMIC_EXIT_BARRIER, "memory");
+CMPXCHG_GEN(u16, _local, , , "memory");
+CMPXCHG_GEN(u16, _acquire, , PPC_ACQUIRE_BARRIER, "memory");
+CMPXCHG_GEN(u16, _relaxed, , , "cc");
+
 static __always_inline unsigned long
 __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
 {
@@ -316,6 +403,10 @@ __cmpxchg(volatile void *ptr, unsigned l
 	  unsigned int size)
 {
 	switch (size) {
+	case 1:
+		return __cmpxchg_u8(ptr, old, new);
+	case 2:
+		return __cmpxchg_u16(ptr, old, new);
 	case 4:
 		return __cmpxchg_u32(ptr, old, new);
 #ifdef CONFIG_PPC64
@@ -328,10 +419,14 @@ __cmpxchg(volatile void *ptr, unsigned l
 }
 
 static __always_inline unsigned long
-__cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new,
+__cmpxchg_local(void *ptr, unsigned long old, unsigned long new,
 	  unsigned int size)
 {
 	switch (size) {
+	case 1:
+		return __cmpxchg_u8_local(ptr, old, new);
+	case 2:
+		return __cmpxchg_u16_local(ptr, old, new);
 	case 4:
 		return __cmpxchg_u32_local(ptr, old, new);
 #ifdef CONFIG_PPC64
@@ -348,6 +443,10 @@ __cmpxchg_relaxed(void *ptr, unsigned lo
 		  unsigned int size)
 {
 	switch (size) {
+	case 1:
+		return __cmpxchg_u8_relaxed(ptr, old, new);
+	case 2:
+		return __cmpxchg_u16_relaxed(ptr, old, new);
 	case 4:
 		return __cmpxchg_u32_relaxed(ptr, old, new);
 #ifdef CONFIG_PPC64
@@ -364,6 +463,10 @@ __cmpxchg_acquire(void *ptr, unsigned lo
 		  unsigned int size)
 {
 	switch (size) {
+	case 1:
+		return __cmpxchg_u8_acquire(ptr, old, new);
+	case 2:
+		return __cmpxchg_u16_acquire(ptr, old, new);
 	case 4:
 		return __cmpxchg_u32_acquire(ptr, old, new);
 #ifdef CONFIG_PPC64
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/cpu_has_feature.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cpu_has_feature.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/cpu_has_feature.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cpu_has_feature.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,9 @@ static __always_inline bool cpu_has_feat
 {
 	int i;
 
+#ifndef __clang__ /* clang can't cope with this */
 	BUILD_BUG_ON(!__builtin_constant_p(feature));
+#endif
 
 #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
 	if (!static_key_initialized) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/cputime.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cputime.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/cputime.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/cputime.h	2017-02-12 16:03:20.000000000 -0500
@@ -46,26 +46,12 @@ extern cputime_t cputime_one_jiffy;
  * Convert cputime <-> jiffies
  */
 extern u64 __cputime_jiffies_factor;
-DECLARE_PER_CPU(unsigned long, cputime_last_delta);
-DECLARE_PER_CPU(unsigned long, cputime_scaled_last_delta);
 
 static inline unsigned long cputime_to_jiffies(const cputime_t ct)
 {
 	return mulhdu((__force u64) ct, __cputime_jiffies_factor);
 }
 
-/* Estimate the scaled cputime by scaling the real cputime based on
- * the last scaled to real ratio */
-static inline cputime_t cputime_to_scaled(const cputime_t ct)
-{
-	if (cpu_has_feature(CPU_FTR_SPURR) &&
-	    __this_cpu_read(cputime_last_delta))
-		return (__force u64) ct *
-			__this_cpu_read(cputime_scaled_last_delta) /
-			__this_cpu_read(cputime_last_delta);
-	return ct;
-}
-
 static inline cputime_t jiffies_to_cputime(const unsigned long jif)
 {
 	u64 ct;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/debug.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/debug.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/debug.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/debug.h	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@ struct pt_regs;
 
 extern struct dentry *powerpc_debugfs_root;
 
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
 
 extern int (*__debugger)(struct pt_regs *regs);
 extern int (*__debugger_ipi)(struct pt_regs *regs);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/futex.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/futex.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/futex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/futex.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,10 +23,8 @@
 "4:	li	%1,%3\n" \
 	"b	3b\n" \
 	".previous\n" \
-	".section __ex_table,\"a\"\n" \
-	".align 3\n" \
-	PPC_LONG "1b,4b,2b,4b\n" \
-	".previous" \
+	EX_TABLE(1b, 4b) \
+	EX_TABLE(2b, 4b) \
 	: "=&r" (oldval), "=&r" (ret) \
 	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 	: "cr0", "memory")
@@ -104,11 +102,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval,
 "3:	.section .fixup,\"ax\"\n\
 4:	li	%0,%6\n\
 	b	3b\n\
-	.previous\n\
-	.section __ex_table,\"a\"\n\
-	.align 3\n\
-	" PPC_LONG "1b,4b,2b,4b\n\
-	.previous" \
+	.previous\n"
+	EX_TABLE(1b, 4b)
+	EX_TABLE(2b, 4b)
         : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
         : "cc", "memory");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/head-64.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/head-64.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/head-64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/head-64.h	2017-02-12 16:03:20.000000000 -0500
@@ -95,12 +95,12 @@ end_##sname:
 
 #define __FIXED_SECTION_ENTRY_BEGIN(sname, name, __align)	\
 	USE_FIXED_SECTION(sname);				\
-	.align __align;						\
+	.balign __align;					\
 	.global name;						\
 name:
 
 #define FIXED_SECTION_ENTRY_BEGIN(sname, name)			\
-	__FIXED_SECTION_ENTRY_BEGIN(sname, name, 0)
+	__FIXED_SECTION_ENTRY_BEGIN(sname, name, IFETCH_ALIGN_BYTES)
 
 #define FIXED_SECTION_ENTRY_BEGIN_LOCATION(sname, name, start)		\
 	USE_FIXED_SECTION(sname);				\
@@ -203,9 +203,9 @@ name:
 #define EXC_VIRT_END(name, start, end)			\
 	FIXED_SECTION_ENTRY_END_LOCATION(virt_vectors, exc_virt_##start##_##name, end)
 
-#define EXC_COMMON_BEGIN(name)					\
+#define EXC_COMMON_BEGIN(name)						\
 	USE_TEXT_SECTION();						\
-	.align	7;							\
+	.balign IFETCH_ALIGN_BYTES;					\
 	.global name;							\
 	DEFINE_FIXED_SYMBOL(name);					\
 name:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/hugetlb.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/hugetlb.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/hugetlb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/hugetlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@ extern struct kmem_cache *hugepte_cache;
 
 #ifdef CONFIG_PPC_BOOK3S_64
 
-#include <asm/book3s/64/hugetlb-radix.h>
+#include <asm/book3s/64/hugetlb.h>
 /*
  * This should work for other subarchs too. But right now we use the
  * new format only for 64bit book3s
@@ -21,12 +21,12 @@ static inline pte_t *hugepd_page(hugepd_
 	 * We have only four bits to encode, MMU page size
 	 */
 	BUILD_BUG_ON((MMU_PAGE_COUNT - 1) > 0xf);
-	return __va(hpd.pd & HUGEPD_ADDR_MASK);
+	return __va(hpd_val(hpd) & HUGEPD_ADDR_MASK);
 }
 
 static inline unsigned int hugepd_mmu_psize(hugepd_t hpd)
 {
-	return (hpd.pd & HUGEPD_SHIFT_MASK) >> 2;
+	return (hpd_val(hpd) & HUGEPD_SHIFT_MASK) >> 2;
 }
 
 static inline unsigned int hugepd_shift(hugepd_t hpd)
@@ -51,12 +51,22 @@ static inline void __local_flush_hugetlb
 static inline pte_t *hugepd_page(hugepd_t hpd)
 {
 	BUG_ON(!hugepd_ok(hpd));
-	return (pte_t *)((hpd.pd & ~HUGEPD_SHIFT_MASK) | PD_HUGE);
+#ifdef CONFIG_PPC_8xx
+	return (pte_t *)__va(hpd_val(hpd) &
+			     ~(_PMD_PAGE_MASK | _PMD_PRESENT_MASK));
+#else
+	return (pte_t *)((hpd_val(hpd) &
+			  ~HUGEPD_SHIFT_MASK) | PD_HUGE);
+#endif
 }
 
 static inline unsigned int hugepd_shift(hugepd_t hpd)
 {
-	return hpd.pd & HUGEPD_SHIFT_MASK;
+#ifdef CONFIG_PPC_8xx
+	return ((hpd_val(hpd) & _PMD_PAGE_MASK) >> 1) + 17;
+#else
+	return hpd_val(hpd) & HUGEPD_SHIFT_MASK;
+#endif
 }
 
 #endif /* CONFIG_PPC_BOOK3S_64 */
@@ -99,7 +109,15 @@ static inline int is_hugepage_only_range
 
 void book3e_hugetlb_preload(struct vm_area_struct *vma, unsigned long ea,
 			    pte_t pte);
+#ifdef CONFIG_PPC_8xx
+static inline void flush_hugetlb_page(struct vm_area_struct *vma,
+				      unsigned long vmaddr)
+{
+	flush_tlb_page(vma, vmaddr);
+}
+#else
 void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+#endif
 
 void hugetlb_free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 			    unsigned long end, unsigned long floor,
@@ -205,7 +223,8 @@ static inline pte_t *hugepte_offset(huge
  * are reserved early in the boot process by memblock instead of via
  * the .dts as on IBM platforms.
  */
-#if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PPC_FSL_BOOK3E)
+#if defined(CONFIG_HUGETLB_PAGE) && (defined(CONFIG_PPC_FSL_BOOK3E) || \
+    defined(CONFIG_PPC_8xx))
 extern void __init reserve_hugetlb_gpages(void);
 #else
 static inline void reserve_hugetlb_gpages(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/hvcall.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/hvcall.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/hvcall.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/hvcall.h	2017-02-12 16:03:20.000000000 -0500
@@ -275,7 +275,9 @@
 #define H_COP			0x304
 #define H_GET_MPP_X		0x314
 #define H_SET_MODE		0x31C
-#define MAX_HCALL_OPCODE	H_SET_MODE
+#define H_CLEAR_HPT		0x358
+#define H_SIGNAL_SYS_RESET	0x380
+#define MAX_HCALL_OPCODE	H_SIGNAL_SYS_RESET
 
 /* H_VIOCTL functions */
 #define H_GET_VIOA_DUMP_SIZE	0x01
@@ -306,6 +308,11 @@
 #define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE	3
 #define H_SET_MODE_RESOURCE_LE			4
 
+/* Values for argument to H_SIGNAL_SYS_RESET */
+#define H_SIGNAL_SYS_RESET_ALL			-1
+#define H_SIGNAL_SYS_RESET_ALL_OTHERS		-2
+/* >= 0 values are CPU number */
+
 #ifndef __ASSEMBLY__
 
 /**
@@ -412,27 +419,6 @@ static inline unsigned int get_longbusy_
 	}
 }
 
-#ifdef CONFIG_PPC_PSERIES
-extern int CMO_PrPSP;
-extern int CMO_SecPSP;
-extern unsigned long CMO_PageSize;
-
-static inline int cmo_get_primary_psp(void)
-{
-	return CMO_PrPSP;
-}
-
-static inline int cmo_get_secondary_psp(void)
-{
-	return CMO_SecPSP;
-}
-
-static inline unsigned long cmo_get_page_size(void)
-{
-	return CMO_PageSize;
-}
-#endif /* CONFIG_PPC_PSERIES */
-
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/ima.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ima.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/ima.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ima.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,29 @@
+#ifndef _ASM_POWERPC_IMA_H
+#define _ASM_POWERPC_IMA_H
+
+struct kimage;
+
+int ima_get_kexec_buffer(void **addr, size_t *size);
+int ima_free_kexec_buffer(void);
+
+#ifdef CONFIG_IMA
+void remove_ima_buffer(void *fdt, int chosen_node);
+#else
+static inline void remove_ima_buffer(void *fdt, int chosen_node) {}
+#endif
+
+#ifdef CONFIG_IMA_KEXEC
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+			      size_t size);
+
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node);
+#else
+static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
+				   int chosen_node)
+{
+	remove_ima_buffer(fdt, chosen_node);
+	return 0;
+}
+#endif /* CONFIG_IMA_KEXEC */
+
+#endif /* _ASM_POWERPC_IMA_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/io.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/io.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/io.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/io.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,6 +33,7 @@ extern struct pci_dev *isa_bridge_pcidev
 #include <asm/synch.h>
 #include <asm/delay.h>
 #include <asm/mmu.h>
+#include <asm/ppc_asm.h>
 
 #include <asm-generic/iomap.h>
 
@@ -458,13 +459,10 @@ static inline unsigned int name(unsigned
 		"5:	li	%0,-1\n"		\
 		"	b	4b\n"			\
 		".previous\n"				\
-		".section __ex_table,\"a\"\n"		\
-		"	.align	2\n"			\
-		"	.long	0b,5b\n"		\
-		"	.long	1b,5b\n"		\
-		"	.long	2b,5b\n"		\
-		"	.long	3b,5b\n"		\
-		".previous"				\
+		EX_TABLE(0b, 5b)			\
+		EX_TABLE(1b, 5b)			\
+		EX_TABLE(2b, 5b)			\
+		EX_TABLE(3b, 5b)			\
 		: "=&r" (x)				\
 		: "r" (port + _IO_BASE)			\
 		: "memory");  				\
@@ -479,11 +477,8 @@ static inline void name(unsigned int val
 		"0:" op " %0,0,%1\n"			\
 		"1:	sync\n"				\
 		"2:\n"					\
-		".section __ex_table,\"a\"\n"		\
-		"	.align	2\n"			\
-		"	.long	0b,2b\n"		\
-		"	.long	1b,2b\n"		\
-		".previous"				\
+		EX_TABLE(0b, 2b)			\
+		EX_TABLE(1b, 2b)			\
 		: : "r" (val), "r" (port + _IO_BASE)	\
 		: "memory");   	   	   		\
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/kexec.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kexec.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/kexec.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kexec.h	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@
 
 typedef void (*crash_shutdown_t)(void);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 
 /*
  * This function is responsible for capturing register states if coming
@@ -91,7 +91,28 @@ static inline bool kdump_in_progress(voi
 	return crashing_cpu >= 0;
 }
 
-#else /* !CONFIG_KEXEC */
+#ifdef CONFIG_KEXEC_FILE
+extern struct kexec_file_ops kexec_elf64_ops;
+
+#ifdef CONFIG_IMA_KEXEC
+#define ARCH_HAS_KIMAGE_ARCH
+
+struct kimage_arch {
+	phys_addr_t ima_buffer_addr;
+	size_t ima_buffer_size;
+};
+#endif
+
+int setup_purgatory(struct kimage *image, const void *slave_code,
+		    const void *fdt, unsigned long kernel_load_addr,
+		    unsigned long fdt_load_addr);
+int setup_new_fdt(const struct kimage *image, void *fdt,
+		  unsigned long initrd_load_addr, unsigned long initrd_len,
+		  const char *cmdline);
+int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size);
+#endif /* CONFIG_KEXEC_FILE */
+
+#else /* !CONFIG_KEXEC_CORE */
 static inline void crash_kexec_secondary(struct pt_regs *regs) { }
 
 static inline int overlaps_crashkernel(unsigned long start, unsigned long size)
@@ -116,7 +137,7 @@ static inline bool kdump_in_progress(voi
 	return false;
 }
 
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 #endif /* ! __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_KEXEC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/kprobes.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kprobes.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/kprobes.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kprobes.h	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,7 @@
 #include <asm/probes.h>
 #include <asm/code-patching.h>
 
+#ifdef CONFIG_KPROBES
 #define  __ARCH_WANT_KPROBES_INSN_SLOT
 
 struct pt_regs;
@@ -127,5 +128,11 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 					unsigned long val, void *data);
 extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+extern int kprobe_handler(struct pt_regs *regs);
+extern int kprobe_post_handler(struct pt_regs *regs);
+#else
+static inline int kprobe_handler(struct pt_regs *regs) { return 0; }
+static inline int kprobe_post_handler(struct pt_regs *regs) { return 0; }
+#endif /* CONFIG_KPROBES */
 #endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_KPROBES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/kvm_asm.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kvm_asm.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/kvm_asm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kvm_asm.h	2017-02-12 16:03:20.000000000 -0500
@@ -99,6 +99,7 @@
 #define BOOK3S_INTERRUPT_H_EMUL_ASSIST	0xe40
 #define BOOK3S_INTERRUPT_HMI		0xe60
 #define BOOK3S_INTERRUPT_H_DOORBELL	0xe80
+#define BOOK3S_INTERRUPT_H_VIRT		0xea0
 #define BOOK3S_INTERRUPT_PERFMON	0xf00
 #define BOOK3S_INTERRUPT_ALTIVEC	0xf20
 #define BOOK3S_INTERRUPT_VSX		0xf40
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/kvm_host.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kvm_host.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/kvm_host.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kvm_host.h	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 #ifdef CONFIG_KVM_MMIO
 #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
 #endif
-#define KVM_HALT_POLL_NS_DEFAULT 500000
+#define KVM_HALT_POLL_NS_DEFAULT 10000	/* 10 us */
 
 /* These values are internal and can be increased later */
 #define KVM_NR_IRQCHIPS          1
@@ -244,8 +244,10 @@ struct kvm_arch_memory_slot {
 struct kvm_arch {
 	unsigned int lpid;
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	unsigned int tlb_sets;
 	unsigned long hpt_virt;
 	struct revmap_entry *revmap;
+	atomic64_t mmio_update;
 	unsigned int host_lpid;
 	unsigned long host_lpcr;
 	unsigned long sdr1;
@@ -408,6 +410,24 @@ struct kvmppc_passthru_irqmap {
 #define KVMPPC_IRQ_MPIC		1
 #define KVMPPC_IRQ_XICS		2
 
+#define MMIO_HPTE_CACHE_SIZE	4
+
+struct mmio_hpte_cache_entry {
+	unsigned long hpte_v;
+	unsigned long hpte_r;
+	unsigned long rpte;
+	unsigned long pte_index;
+	unsigned long eaddr;
+	unsigned long slb_v;
+	long mmio_update;
+	unsigned int slb_base_pshift;
+};
+
+struct mmio_hpte_cache {
+	struct mmio_hpte_cache_entry entry[MMIO_HPTE_CACHE_SIZE];
+	unsigned int index;
+};
+
 struct openpic;
 
 struct kvm_vcpu_arch {
@@ -498,6 +518,8 @@ struct kvm_vcpu_arch {
 	ulong tcscr;
 	ulong acop;
 	ulong wort;
+	ulong tid;
+	ulong psscr;
 	ulong shadow_srr1;
 #endif
 	u32 vrsave; /* also USPRG0 */
@@ -546,6 +568,7 @@ struct kvm_vcpu_arch {
 	u64 tfiar;
 
 	u32 cr_tm;
+	u64 xer_tm;
 	u64 lr_tm;
 	u64 ctr_tm;
 	u64 amr_tm;
@@ -655,9 +678,11 @@ struct kvm_vcpu_arch {
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 	struct kvm_vcpu_arch_shared shregs;
 
+	struct mmio_hpte_cache mmio_cache;
 	unsigned long pgfault_addr;
 	long pgfault_index;
 	unsigned long pgfault_hpte[2];
+	struct mmio_hpte_cache_entry *pgfault_cache;
 
 	struct task_struct *run_task;
 	struct kvm_run *kvm_run;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/kvm_ppc.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kvm_ppc.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/kvm_ppc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/kvm_ppc.h	2017-02-12 16:03:20.000000000 -0500
@@ -483,9 +483,10 @@ extern void kvmppc_xics_set_mapped(struc
 				   unsigned long host_irq);
 extern void kvmppc_xics_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
 				   unsigned long host_irq);
-extern long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu, u32 xirr,
-				 struct kvmppc_irq_map *irq_map,
-				 struct kvmppc_passthru_irqmap *pimap);
+extern long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu, __be32 xirr,
+					struct kvmppc_irq_map *irq_map,
+					struct kvmppc_passthru_irqmap *pimap,
+					bool *again);
 extern int h_ipi_redirect;
 #else
 static inline struct kvmppc_passthru_irqmap *kvmppc_get_passthru_irqmap(
@@ -510,6 +511,48 @@ static inline int kvmppc_xics_hcall(stru
 #endif
 
 /*
+ * Prototypes for functions called only from assembler code.
+ * Having prototypes reduces sparse errors.
+ */
+long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+			 unsigned long ioba, unsigned long tce);
+long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+				  unsigned long liobn, unsigned long ioba,
+				  unsigned long tce_list, unsigned long npages);
+long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
+			   unsigned long liobn, unsigned long ioba,
+			   unsigned long tce_value, unsigned long npages);
+long int kvmppc_rm_h_confer(struct kvm_vcpu *vcpu, int target,
+                            unsigned int yield_count);
+long kvmppc_h_random(struct kvm_vcpu *vcpu);
+void kvmhv_commence_exit(int trap);
+long kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu);
+void kvmppc_subcore_enter_guest(void);
+void kvmppc_subcore_exit_guest(void);
+long kvmppc_realmode_hmi_handler(void);
+long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
+                    long pte_index, unsigned long pteh, unsigned long ptel);
+long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
+                     unsigned long pte_index, unsigned long avpn);
+long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu);
+long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
+                      unsigned long pte_index, unsigned long avpn,
+                      unsigned long va);
+long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
+                   unsigned long pte_index);
+long kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags,
+                        unsigned long pte_index);
+long kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags,
+                        unsigned long pte_index);
+long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
+                          unsigned long slb_v, unsigned int status, bool data);
+unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu);
+int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+                    unsigned long mfrr);
+int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr);
+int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr);
+
+/*
  * Host-side operations we want to set up while running in real
  * mode in the guest operating on the xics.
  * Currently only VCPU wakeup is supported.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/machdep.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/machdep.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/machdep.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/machdep.h	2017-02-12 16:03:20.000000000 -0500
@@ -183,7 +183,7 @@ struct machdep_calls {
 	 */
 	void (*machine_shutdown)(void);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	void (*kexec_cpu_down)(int crash_shutdown, int secondary);
 
 	/* Called to do what every setup is needed on image and the
@@ -198,7 +198,7 @@ struct machdep_calls {
 	 * no return.
 	 */
 	void (*machine_kexec)(struct kimage *image);
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 #ifdef CONFIG_SUSPEND
 	/* These are called to disable and enable, respectively, IRQs when
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/mmu-8xx.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mmu-8xx.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/mmu-8xx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mmu-8xx.h	2017-02-12 16:03:20.000000000 -0500
@@ -172,6 +172,41 @@ typedef struct {
 
 #define PHYS_IMMR_BASE (mfspr(SPRN_IMMR) & 0xfff80000)
 #define VIRT_IMMR_BASE (__fix_to_virt(FIX_IMMR_BASE))
+
+/* Page size definitions, common between 32 and 64-bit
+ *
+ *    shift : is the "PAGE_SHIFT" value for that page size
+ *    penc  : is the pte encoding mask
+ *
+ */
+struct mmu_psize_def {
+	unsigned int	shift;	/* number of bits */
+	unsigned int	enc;	/* PTE encoding */
+	unsigned int    ind;    /* Corresponding indirect page size shift */
+	unsigned int	flags;
+#define MMU_PAGE_SIZE_DIRECT	0x1	/* Supported as a direct size */
+#define MMU_PAGE_SIZE_INDIRECT	0x2	/* Supported as an indirect size */
+};
+
+extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
+
+static inline int shift_to_mmu_psize(unsigned int shift)
+{
+	int psize;
+
+	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize)
+		if (mmu_psize_defs[psize].shift == shift)
+			return psize;
+	return -1;
+}
+
+static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
+{
+	if (mmu_psize_defs[mmu_psize].shift)
+		return mmu_psize_defs[mmu_psize].shift;
+	BUG();
+}
+
 #endif /* !__ASSEMBLY__ */
 
 #if defined(CONFIG_PPC_4K_PAGES)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/mmu_context.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mmu_context.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/mmu_context.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mmu_context.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,16 +19,18 @@ extern void destroy_context(struct mm_st
 struct mm_iommu_table_group_mem_t;
 
 extern int isolate_lru_page(struct page *page);	/* from internal.h */
-extern bool mm_iommu_preregistered(void);
-extern long mm_iommu_get(unsigned long ua, unsigned long entries,
+extern bool mm_iommu_preregistered(struct mm_struct *mm);
+extern long mm_iommu_get(struct mm_struct *mm,
+		unsigned long ua, unsigned long entries,
 		struct mm_iommu_table_group_mem_t **pmem);
-extern long mm_iommu_put(struct mm_iommu_table_group_mem_t *mem);
-extern void mm_iommu_init(mm_context_t *ctx);
-extern void mm_iommu_cleanup(mm_context_t *ctx);
-extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(unsigned long ua,
-		unsigned long size);
-extern struct mm_iommu_table_group_mem_t *mm_iommu_find(unsigned long ua,
-		unsigned long entries);
+extern long mm_iommu_put(struct mm_struct *mm,
+		struct mm_iommu_table_group_mem_t *mem);
+extern void mm_iommu_init(struct mm_struct *mm);
+extern void mm_iommu_cleanup(struct mm_struct *mm);
+extern struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm,
+		unsigned long ua, unsigned long size);
+extern struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
+		unsigned long ua, unsigned long entries);
 extern long mm_iommu_ua_to_hpa(struct mm_iommu_table_group_mem_t *mem,
 		unsigned long ua, unsigned long *hpa);
 extern long mm_iommu_mapped_inc(struct mm_iommu_table_group_mem_t *mem);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/mmu.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mmu.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/mmu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mmu.h	2017-02-12 16:03:20.000000000 -0500
@@ -160,7 +160,9 @@ static __always_inline bool mmu_has_feat
 {
 	int i;
 
+#ifndef __clang__ /* clang can't cope with this */
 	BUILD_BUG_ON(!__builtin_constant_p(feature));
+#endif
 
 #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG
 	if (!static_key_initialized) {
@@ -214,6 +216,11 @@ extern u64 ppc64_rma_size;
 /* Cleanup function used by kexec */
 extern void mmu_cleanup_all(void);
 extern void radix__mmu_cleanup_all(void);
+
+/* Functions for creating and updating partition table on POWER9 */
+extern void mmu_partition_table_init(void);
+extern void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
+					  unsigned long dw1);
 #endif /* CONFIG_PPC64 */
 
 struct mm_struct;
@@ -270,19 +277,20 @@ static inline bool early_radix_enabled(v
 #define MMU_PAGE_64K	2
 #define MMU_PAGE_64K_AP	3	/* "Admixed pages" (hash64 only) */
 #define MMU_PAGE_256K	4
-#define MMU_PAGE_1M	5
-#define MMU_PAGE_2M	6
-#define MMU_PAGE_4M	7
-#define MMU_PAGE_8M	8
-#define MMU_PAGE_16M	9
-#define MMU_PAGE_64M	10
-#define MMU_PAGE_256M	11
-#define MMU_PAGE_1G	12
-#define MMU_PAGE_16G	13
-#define MMU_PAGE_64G	14
+#define MMU_PAGE_512K	5
+#define MMU_PAGE_1M	6
+#define MMU_PAGE_2M	7
+#define MMU_PAGE_4M	8
+#define MMU_PAGE_8M	9
+#define MMU_PAGE_16M	10
+#define MMU_PAGE_64M	11
+#define MMU_PAGE_256M	12
+#define MMU_PAGE_1G	13
+#define MMU_PAGE_16G	14
+#define MMU_PAGE_64G	15
 
 /* N.B. we need to change the type of hpte_page_sizes if this gets to be > 16 */
-#define MMU_PAGE_COUNT	15
+#define MMU_PAGE_COUNT	16
 
 #ifdef CONFIG_PPC_BOOK3S_64
 #include <asm/book3s/64/mmu.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/module.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/module.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/module.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/module.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,13 +90,5 @@ static inline int module_finalize_ftrace
 }
 #endif
 
-struct exception_table_entry;
-void sort_ex_table(struct exception_table_entry *start,
-		   struct exception_table_entry *finish);
-
-#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64)
-#define ARCH_RELOCATES_KCRCTAB
-#define reloc_start PHYSICAL_START
-#endif
 #endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_MODULE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-/*
- * Optimised mutex implementation of include/asm-generic/mutex-dec.h algorithm
- */
-#ifndef _ASM_POWERPC_MUTEX_H
-#define _ASM_POWERPC_MUTEX_H
-
-static inline int __mutex_cmpxchg_lock(atomic_t *v, int old, int new)
-{
-	int t;
-
-	__asm__ __volatile__ (
-"1:	lwarx	%0,0,%1		# mutex trylock\n\
-	cmpw	0,%0,%2\n\
-	bne-	2f\n"
-	PPC405_ERR77(0,%1)
-"	stwcx.	%3,0,%1\n\
-	bne-	1b"
-	PPC_ACQUIRE_BARRIER
-	"\n\
-2:"
-	: "=&r" (t)
-	: "r" (&v->counter), "r" (old), "r" (new)
-	: "cc", "memory");
-
-	return t;
-}
-
-static inline int __mutex_dec_return_lock(atomic_t *v)
-{
-	int t;
-
-	__asm__ __volatile__(
-"1:	lwarx	%0,0,%1		# mutex lock\n\
-	addic	%0,%0,-1\n"
-	PPC405_ERR77(0,%1)
-"	stwcx.	%0,0,%1\n\
-	bne-	1b"
-	PPC_ACQUIRE_BARRIER
-	: "=&r" (t)
-	: "r" (&v->counter)
-	: "cc", "memory");
-
-	return t;
-}
-
-static inline int __mutex_inc_return_unlock(atomic_t *v)
-{
-	int t;
-
-	__asm__ __volatile__(
-	PPC_RELEASE_BARRIER
-"1:	lwarx	%0,0,%1		# mutex unlock\n\
-	addic	%0,%0,1\n"
-	PPC405_ERR77(0,%1)
-"	stwcx.	%0,0,%1 \n\
-	bne-	1b"
-	: "=&r" (t)
-	: "r" (&v->counter)
-	: "cc", "memory");
-
-	return t;
-}
-
-/**
- *  __mutex_fastpath_lock - try to take the lock by moving the count
- *                          from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fail_fn> if
- * it wasn't 1 originally. This function MUST leave the value lower than
- * 1 even when the "1" assertion wasn't true.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	if (unlikely(__mutex_dec_return_lock(count) < 0))
-		fail_fn(count);
-}
-
-/**
- *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
- *                                 from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
-	if (unlikely(__mutex_dec_return_lock(count) < 0))
-		return -1;
-	return 0;
-}
-
-/**
- *  __mutex_fastpath_unlock - try to promote the count from 0 to 1
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 0
- *
- * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value to
- * 1, or to set it to a value lower than 1.
- */
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	if (unlikely(__mutex_inc_return_unlock(count) <= 0))
-		fail_fn(count);
-}
-
-#define __mutex_slowpath_needs_to_unlock()		1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- *  @count: pointer of type atomic_t
- *  @fail_fn: fallback function
- *
- * Change the count from 1 to 0, and return 1 (success), or if the count
- * was not 1, then return 0 (failure).
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
-	if (likely(atomic_read(count) == 1 && __mutex_cmpxchg_lock(count, 1, 0) == 1))
-		return 1;
-	return 0;
-}
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/32/pgalloc.h	2017-02-12 16:03:20.000000000 -0500
@@ -2,14 +2,42 @@
 #define _ASM_POWERPC_PGALLOC_32_H
 
 #include <linux/threads.h>
+#include <linux/slab.h>
 
-/* For 32-bit, all levels of page tables are just drawn from get_free_page() */
-#define MAX_PGTABLE_INDEX_SIZE	0
+/*
+ * Functions that deal with pagetables that could be at any level of
+ * the table need to be passed an "index_size" so they know how to
+ * handle allocation.  For PTE pages (which are linked to a struct
+ * page for now, and drawn from the main get_free_pages() pool), the
+ * allocation size will be (2^index_size * sizeof(pointer)) and
+ * allocations are drawn from the kmem_cache in PGT_CACHE(index_size).
+ *
+ * The maximum index size needs to be big enough to allow any
+ * pagetable sizes we need, but small enough to fit in the low bits of
+ * any page table pointer.  In other words all pagetables, even tiny
+ * ones, must be aligned to allow at least enough low 0 bits to
+ * contain this value.  This value is also used as a mask, so it must
+ * be one less than a power of two.
+ */
+#define MAX_PGTABLE_INDEX_SIZE	0xf
 
 extern void __bad_pte(pmd_t *pmd);
 
-extern pgd_t *pgd_alloc(struct mm_struct *mm);
-extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+extern struct kmem_cache *pgtable_cache[];
+#define PGT_CACHE(shift) ({				\
+			BUG_ON(!(shift));		\
+			pgtable_cache[(shift) - 1];	\
+		})
+
+static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+{
+	return kmem_cache_alloc(PGT_CACHE(PGD_INDEX_SIZE), GFP_KERNEL);
+}
+
+static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+	kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd);
+}
 
 /*
  * We don't have any real pmd's, and this code never triggers because
@@ -68,8 +96,12 @@ static inline void pte_free(struct mm_st
 
 static inline void pgtable_free(void *table, unsigned index_size)
 {
-	BUG_ON(index_size); /* 32-bit doesn't use this */
-	free_page((unsigned long)table);
+	if (!index_size) {
+		free_page((unsigned long)table);
+	} else {
+		BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE);
+		kmem_cache_free(PGT_CACHE(index_size), table);
+	}
 }
 
 #define check_pgt_cache()	do { } while (0)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/32/pgtable.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/32/pgtable.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/32/pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/32/pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,23 @@ extern int icache_44x_need_flush;
 
 #endif /* __ASSEMBLY__ */
 
+#define PTE_INDEX_SIZE	PTE_SHIFT
+#define PMD_INDEX_SIZE	0
+#define PUD_INDEX_SIZE	0
+#define PGD_INDEX_SIZE	(32 - PGDIR_SHIFT)
+
+#define PMD_CACHE_INDEX	PMD_INDEX_SIZE
+
+#ifndef __ASSEMBLY__
+#define PTE_TABLE_SIZE	(sizeof(pte_t) << PTE_INDEX_SIZE)
+#define PMD_TABLE_SIZE	0
+#define PUD_TABLE_SIZE	0
+#define PGD_TABLE_SIZE	(sizeof(pgd_t) << PGD_INDEX_SIZE)
+#endif	/* __ASSEMBLY__ */
+
+#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
+#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
+
 /*
  * The normal case is that PTEs are 32-bits and we have a 1-page
  * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages.  -- paulus
@@ -27,22 +44,12 @@ extern int icache_44x_need_flush;
  * -Matt
  */
 /* PGDIR_SHIFT determines what a top-level page table entry can map */
-#define PGDIR_SHIFT	(PAGE_SHIFT + PTE_SHIFT)
+#define PGDIR_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
-/*
- * entries per page directory level: our page-table tree is two-level, so
- * we don't really have any PMD directory.
- */
-#ifndef __ASSEMBLY__
-#define PTE_TABLE_SIZE	(sizeof(pte_t) << PTE_SHIFT)
-#define PGD_TABLE_SIZE	(sizeof(pgd_t) << (32 - PGDIR_SHIFT))
-#endif	/* __ASSEMBLY__ */
-
-#define PTRS_PER_PTE	(1 << PTE_SHIFT)
-#define PTRS_PER_PMD	1
-#define PTRS_PER_PGD	(1 << (32 - PGDIR_SHIFT))
+/* Bits to mask out from a PGD to get to the PUD page */
+#define PGD_MASKED_BITS		0
 
 #define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 #define FIRST_USER_ADDRESS	0UL
@@ -268,7 +275,8 @@ static inline void huge_ptep_set_wrprote
 
 
 static inline void __ptep_set_access_flags(struct mm_struct *mm,
-					   pte_t *ptep, pte_t entry)
+					   pte_t *ptep, pte_t entry,
+					   unsigned long address)
 {
 	unsigned long set = pte_val(entry) &
 		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
@@ -328,15 +336,6 @@ static inline void __ptep_set_access_fla
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) >> 3 })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val << 3 })
 
-#ifndef CONFIG_PPC_4K_PAGES
-void pgtable_cache_init(void);
-#else
-/*
- * No page table caches to initialise
- */
-#define pgtable_cache_init()	do { } while (0)
-#endif
-
 extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep,
 		      pmd_t **pmdp);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/32/pte-8xx.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/32/pte-8xx.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/32/pte-8xx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/32/pte-8xx.h	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,7 @@
 #define _PMD_BAD	0x0ff0
 #define _PMD_PAGE_MASK	0x000c
 #define _PMD_PAGE_8M	0x000c
+#define _PMD_PAGE_512K	0x0004
 
 /* Until my rework is finished, 8xx still needs atomic PTE updates */
 #define PTE_ATOMIC_UPDATES	1
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/64/pgtable-4k.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/64/pgtable-4k.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/64/pgtable-4k.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/64/pgtable-4k.h	2017-02-12 16:03:20.000000000 -0500
@@ -27,9 +27,6 @@
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 
-/* With 4k base page size, hugepage PTEs go at the PMD level */
-#define MIN_HUGEPTE_SHIFT	PMD_SHIFT
-
 /* PUD_SHIFT determines what a third-level page table entry can map */
 #define PUD_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
 #define PUD_SIZE	(1UL << PUD_SHIFT)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/64/pgtable-64k.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/64/pgtable-64k.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/64/pgtable-64k.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/64/pgtable-64k.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,9 +31,6 @@
 #define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
 #define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
 
-/* With 4k base page size, hugepage PTEs go at the PMD level */
-#define MIN_HUGEPTE_SHIFT	PAGE_SHIFT
-
 /* PMD_SHIFT determines what a second-level page table entry can map */
 #define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
 #define PMD_SIZE	(1UL << PMD_SHIFT)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/64/pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -26,15 +26,11 @@
 #else
 #define PMD_CACHE_INDEX	PMD_INDEX_SIZE
 #endif
+
 /*
  * Define the address range of the kernel non-linear virtual area
  */
-
-#ifdef CONFIG_PPC_BOOK3E
 #define KERN_VIRT_START ASM_CONST(0x8000000000000000)
-#else
-#define KERN_VIRT_START ASM_CONST(0xD000000000000000)
-#endif
 #define KERN_VIRT_SIZE	ASM_CONST(0x0000100000000000)
 
 /*
@@ -43,11 +39,7 @@
  * (we keep a quarter for the virtual memmap)
  */
 #define VMALLOC_START	KERN_VIRT_START
-#ifdef CONFIG_PPC_BOOK3E
 #define VMALLOC_SIZE	(KERN_VIRT_SIZE >> 2)
-#else
-#define VMALLOC_SIZE	(KERN_VIRT_SIZE >> 1)
-#endif
 #define VMALLOC_END	(VMALLOC_START + VMALLOC_SIZE)
 
 /*
@@ -85,12 +77,8 @@
  * Defines the address of the vmemap area, in its own region on
  * hash table CPUs and after the vmalloc space on Book3E
  */
-#ifdef CONFIG_PPC_BOOK3E
 #define VMEMMAP_BASE		VMALLOC_END
 #define VMEMMAP_END		KERN_IO_START
-#else
-#define VMEMMAP_BASE		(VMEMMAP_REGION_ID << REGION_SHIFT)
-#endif
 #define vmemmap			((struct page *)VMEMMAP_BASE)
 
 
@@ -301,7 +289,8 @@ static inline void pte_clear(struct mm_s
  * function doesn't need to flush the hash entry
  */
 static inline void __ptep_set_access_flags(struct mm_struct *mm,
-					   pte_t *ptep, pte_t entry)
+					   pte_t *ptep, pte_t entry,
+					   unsigned long address)
 {
 	unsigned long bits = pte_val(entry) &
 		(_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
@@ -358,8 +347,6 @@ static inline void __ptep_set_access_fla
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val((pte)) })
 #define __swp_entry_to_pte(x)		__pte((x).val)
 
-void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
-void pgtable_cache_init(void);
 extern int map_kernel_page(unsigned long ea, unsigned long pa,
 			   unsigned long flags);
 extern int __meminit vmemmap_create_mapping(unsigned long start,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/pgtable.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/pgtable.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/nohash/pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/nohash/pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -226,7 +226,12 @@ extern pgprot_t phys_mem_access_prot(str
 #ifdef CONFIG_HUGETLB_PAGE
 static inline int hugepd_ok(hugepd_t hpd)
 {
-	return (hpd.pd > 0);
+#ifdef CONFIG_PPC_8xx
+	return ((hpd_val(hpd) & 0x4) != 0);
+#else
+	/* We clear the top bit to indicate hugepd */
+	return ((hpd_val(hpd) & PD_HUGE) ==  0);
+#endif
 }
 
 static inline int pmd_huge(pmd_t pmd)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/opal.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/opal.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/opal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/opal.h	2017-02-12 16:03:20.000000000 -0500
@@ -220,9 +220,12 @@ int64_t opal_pci_set_power_state(uint64_
 int64_t opal_pci_poll2(uint64_t id, uint64_t data);
 
 int64_t opal_int_get_xirr(uint32_t *out_xirr, bool just_poll);
+int64_t opal_rm_int_get_xirr(__be32 *out_xirr, bool just_poll);
 int64_t opal_int_set_cppr(uint8_t cppr);
 int64_t opal_int_eoi(uint32_t xirr);
+int64_t opal_rm_int_eoi(uint32_t xirr);
 int64_t opal_int_set_mfrr(uint32_t cpu, uint8_t mfrr);
+int64_t opal_rm_int_set_mfrr(uint32_t cpu, uint8_t mfrr);
 int64_t opal_pci_tce_kill(uint64_t phb_id, uint32_t kill_type,
 			  uint32_t pe_num, uint32_t tce_size,
 			  uint64_t dma_addr, uint32_t npages);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/page.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/page.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/page.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/page.h	2017-02-12 16:03:20.000000000 -0500
@@ -294,15 +294,12 @@ extern long long virt_phys_offset;
 #include <asm/pgtable-types.h>
 #endif
 
-typedef struct { signed long pd; } hugepd_t;
 
 #ifndef CONFIG_HUGETLB_PAGE
 #define is_hugepd(pdep)		(0)
 #define pgd_huge(pgd)		(0)
 #endif /* CONFIG_HUGETLB_PAGE */
 
-#define __hugepd(x) ((hugepd_t) { (x) })
-
 struct page;
 extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
 extern void copy_user_page(void *to, void *from, unsigned long vaddr,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/perf_event_server.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/perf_event_server.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/perf_event_server.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/perf_event_server.h	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,7 @@ struct power_pmu {
 #define PPMU_HAS_SSLOT		0x00000020 /* Has sampled slot in MMCRA */
 #define PPMU_HAS_SIER		0x00000040 /* Has SIER */
 #define PPMU_ARCH_207S		0x00000080 /* PMC is architecture v2.07S */
+#define PPMU_NO_SIAR		0x00000100 /* Do not use SIAR */
 
 /*
  * Values for flags to get_alternatives()
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/pgtable-be-types.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/pgtable-be-types.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/pgtable-be-types.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/pgtable-be-types.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,4 +104,12 @@ static inline bool pmd_xchg(pmd_t *pmdp,
 	return pmd_raw(old) == prev;
 }
 
+typedef struct { __be64 pdbe; } hugepd_t;
+#define __hugepd(x) ((hugepd_t) { cpu_to_be64(x) })
+
+static inline unsigned long hpd_val(hugepd_t x)
+{
+	return be64_to_cpu(x.pdbe);
+}
+
 #endif /* _ASM_POWERPC_PGTABLE_BE_TYPES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/pgtable.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/pgtable.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/pgtable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/pgtable.h	2017-02-12 16:03:20.000000000 -0500
@@ -78,6 +78,8 @@ static inline pte_t *find_linux_pte_or_h
 
 unsigned long vmalloc_to_phys(void *vmalloc_addr);
 
+void pgtable_cache_add(unsigned shift, void (*ctor)(void *));
+void pgtable_cache_init(void);
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_PGTABLE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/pgtable-types.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/pgtable-types.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/pgtable-types.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/pgtable-types.h	2017-02-12 16:03:20.000000000 -0500
@@ -66,4 +66,11 @@ static inline bool pte_xchg(pte_t *ptep,
 }
 #endif
 
+typedef struct { unsigned long pd; } hugepd_t;
+#define __hugepd(x) ((hugepd_t) { (x) })
+static inline unsigned long hpd_val(hugepd_t x)
+{
+	return x.pd;
+}
+
 #endif /* _ASM_POWERPC_PGTABLE_TYPES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/plpar_wrappers.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/plpar_wrappers.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/plpar_wrappers.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/plpar_wrappers.h	2017-02-12 16:03:20.000000000 -0500
@@ -93,38 +93,6 @@ static inline long register_dtl(unsigned
 	return vpa_call(H_VPA_REG_DTL, cpu, vpa);
 }
 
-static inline long plpar_page_set_loaned(unsigned long vpa)
-{
-	unsigned long cmo_page_sz = cmo_get_page_size();
-	long rc = 0;
-	int i;
-
-	for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
-		rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa + i, 0);
-
-	for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
-		plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE,
-				   vpa + i - cmo_page_sz, 0);
-
-	return rc;
-}
-
-static inline long plpar_page_set_active(unsigned long vpa)
-{
-	unsigned long cmo_page_sz = cmo_get_page_size();
-	long rc = 0;
-	int i;
-
-	for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
-		rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa + i, 0);
-
-	for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
-		plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED,
-				   vpa + i - cmo_page_sz, 0);
-
-	return rc;
-}
-
 extern void vpa_init(int cpu);
 
 static inline long plpar_pte_enter(unsigned long flags,
@@ -340,4 +308,9 @@ static inline long plapr_set_watchpoint0
 	return plpar_set_mode(0, H_SET_MODE_RESOURCE_SET_DAWR, dawr0, dawrx0);
 }
 
+static inline long plapr_signal_sys_reset(long cpu)
+{
+	return plpar_hcall_norets(H_SIGNAL_SYS_RESET, cpu);
+}
+
 #endif /* _ASM_POWERPC_PLPAR_WRAPPERS_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/ppc_asm.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ppc_asm.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/ppc_asm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ppc_asm.h	2017-02-12 16:03:20.000000000 -0500
@@ -10,9 +10,7 @@
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
 
-#ifndef __ASSEMBLY__
-#error __FILE__ should only be used in assembler files
-#else
+#ifdef __ASSEMBLY__
 
 #define SZL			(BITS_PER_LONG/8)
 
@@ -265,10 +263,14 @@ n:
  * latter is for those that incdentially must be excluded from probing
  * and allows them to be linked at more optimal location within text.
  */
+#ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
 	.pushsection "_kprobe_blacklist","aw";		\
 	PPC_LONG (entry) ;				\
 	.popsection
+#else
+#define _ASM_NOKPROBE_SYMBOL(entry)
+#endif
 
 #define FUNC_START(name)	_GLOBAL(name)
 #define FUNC_END(name)
@@ -779,5 +781,17 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
 	.long 0xa6037b7d; /* mtsrr1 r11				*/ \
 	.long 0x2400004c  /* rfid				*/
 #endif /* !CONFIG_PPC_BOOK3E */
+
 #endif /*  __ASSEMBLY__ */
+
+/*
+ * Helper macro for exception table entries
+ */
+#define EX_TABLE(_fault, _target)		\
+	stringify_in_c(.section __ex_table,"a";)\
+	stringify_in_c(.balign 4;)		\
+	stringify_in_c(.long (_fault) - . ;)	\
+	stringify_in_c(.long (_target) - . ;)	\
+	stringify_in_c(.previous)
+
 #endif /* _ASM_POWERPC_PPC_ASM_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/ppc-opcode.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ppc-opcode.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/ppc-opcode.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ppc-opcode.h	2017-02-12 16:03:20.000000000 -0500
@@ -157,7 +157,7 @@
 #define PPC_INST_MCRXR			0x7c000400
 #define PPC_INST_MCRXR_MASK		0xfc0007fe
 #define PPC_INST_MFSPR_PVR		0x7c1f42a6
-#define PPC_INST_MFSPR_PVR_MASK		0xfc1fffff
+#define PPC_INST_MFSPR_PVR_MASK		0xfc1ffffe
 #define PPC_INST_MFTMR			0x7c0002dc
 #define PPC_INST_MSGSND			0x7c00019c
 #define PPC_INST_MSGCLR			0x7c0001dc
@@ -174,13 +174,13 @@
 #define PPC_INST_RFDI			0x4c00004e
 #define PPC_INST_RFMCI			0x4c00004c
 #define PPC_INST_MFSPR_DSCR		0x7c1102a6
-#define PPC_INST_MFSPR_DSCR_MASK	0xfc1fffff
+#define PPC_INST_MFSPR_DSCR_MASK	0xfc1ffffe
 #define PPC_INST_MTSPR_DSCR		0x7c1103a6
-#define PPC_INST_MTSPR_DSCR_MASK	0xfc1fffff
+#define PPC_INST_MTSPR_DSCR_MASK	0xfc1ffffe
 #define PPC_INST_MFSPR_DSCR_USER	0x7c0302a6
-#define PPC_INST_MFSPR_DSCR_USER_MASK	0xfc1fffff
+#define PPC_INST_MFSPR_DSCR_USER_MASK	0xfc1ffffe
 #define PPC_INST_MTSPR_DSCR_USER	0x7c0303a6
-#define PPC_INST_MTSPR_DSCR_USER_MASK	0xfc1fffff
+#define PPC_INST_MTSPR_DSCR_USER_MASK	0xfc1ffffe
 #define PPC_INST_MFVSRD			0x7c000066
 #define PPC_INST_MTVSRD			0x7c000166
 #define PPC_INST_SLBFEE			0x7c0007a7
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/ppc-pci.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ppc-pci.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/ppc-pci.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/ppc-pci.h	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@ void eeh_addr_cache_rmv_dev(struct pci_d
 struct eeh_dev *eeh_addr_cache_get_dev(unsigned long addr);
 void eeh_slot_error_detail(struct eeh_pe *pe, int severity);
 int eeh_pci_enable(struct eeh_pe *pe, int function);
-int eeh_reset_pe(struct eeh_pe *);
+int eeh_pe_reset_full(struct eeh_pe *pe);
 void eeh_save_bars(struct eeh_dev *edev);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -312,8 +312,6 @@ struct thread_struct {
 	unsigned long	mmcr2;
 	unsigned 	mmcr0;
 	unsigned 	used_ebb;
-	unsigned long	lmrr;
-	unsigned long	lmser;
 #endif
 };
 
@@ -404,8 +402,6 @@ static inline unsigned long __pack_fe01(
 #define cpu_relax()	barrier()
 #endif
 
-#define cpu_relax_lowlatency() cpu_relax()
-
 /* Check that a certain kernel stack pointer is valid in task_struct p */
 int validate_sp(unsigned long sp, struct task_struct *p,
                        unsigned long nbytes);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/prom.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/prom.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/prom.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/prom.h	2017-02-12 16:03:20.000000000 -0500
@@ -159,11 +159,5 @@ struct of_drconf_cell {
 /* Option Vector 6: IBM PAPR hints */
 #define OV6_LINUX		0x02	/* Linux is our OS */
 
-/*
- * The architecture vector has an array of PVR mask/value pairs,
- * followed by # option vectors - 1, followed by the option vectors.
- */
-extern unsigned char ibm_architecture_vec[];
-
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PROM_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/reg_8xx.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/reg_8xx.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/reg_8xx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/reg_8xx.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
 #ifndef _ASM_POWERPC_REG_8xx_H
 #define _ASM_POWERPC_REG_8xx_H
 
-#include <asm/mmu-8xx.h>
+#include <asm/mmu.h>
 
 /* Cache control on the MPC8xx is provided through some additional
  * special purpose registers.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/reg.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/reg.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -153,6 +153,8 @@
 #define PSSCR_EC		0x00100000 /* Exit Criterion */
 #define PSSCR_ESL		0x00200000 /* Enable State Loss */
 #define PSSCR_SD		0x00400000 /* Status Disable */
+#define PSSCR_PLS	0xf000000000000000 /* Power-saving Level Status */
+#define PSSCR_GUEST_VIS	0xf0000000000003ff /* Guest-visible PSSCR fields */
 
 /* Floating Point Status and Control Register (FPSCR) Fields */
 #define FPSCR_FX	0x80000000	/* FPU exception summary */
@@ -236,6 +238,7 @@
 #define SPRN_TEXASRU	0x83	/* ''	   ''	   ''	 Upper 32  */
 #define   TEXASR_FS	__MASK(63-36) /* TEXASR Failure Summary */
 #define SPRN_TFHAR	0x80	/* Transaction Failure Handler Addr */
+#define SPRN_TIDR	144	/* Thread ID register */
 #define SPRN_CTRLF	0x088
 #define SPRN_CTRLT	0x098
 #define   CTRL_CT	0xc0000000	/* current thread */
@@ -292,8 +295,7 @@
 #define SPRN_HRMOR	0x139	/* Real mode offset register */
 #define SPRN_HSRR0	0x13A	/* Hypervisor Save/Restore 0 */
 #define SPRN_HSRR1	0x13B	/* Hypervisor Save/Restore 1 */
-#define SPRN_LMRR	0x32D	/* Load Monitor Region Register */
-#define SPRN_LMSER	0x32E	/* Load Monitor Section Enable Register */
+#define SPRN_ASDR	0x330	/* Access segment descriptor register */
 #define SPRN_IC		0x350	/* Virtual Instruction Count */
 #define SPRN_VTB	0x351	/* Virtual Time Base */
 #define SPRN_LDBAR	0x352	/* LD Base Address Register */
@@ -304,7 +306,7 @@
 #define SPRN_PMCR	0x374	/* Power Management Control Register */
 
 /* HFSCR and FSCR bit numbers are the same */
-#define FSCR_LM_LG	11	/* Enable Load Monitor Registers */
+#define FSCR_MSGP_LG	10	/* Enable MSGP */
 #define FSCR_TAR_LG	8	/* Enable Target Address Register */
 #define FSCR_EBB_LG	7	/* Enable Event Based Branching */
 #define FSCR_TM_LG	5	/* Enable Transactional Memory */
@@ -314,12 +316,11 @@
 #define FSCR_VECVSX_LG	1	/* Enable VMX/VSX  */
 #define FSCR_FP_LG	0	/* Enable Floating Point */
 #define SPRN_FSCR	0x099	/* Facility Status & Control Register */
-#define   FSCR_LM	__MASK(FSCR_LM_LG)
 #define   FSCR_TAR	__MASK(FSCR_TAR_LG)
 #define   FSCR_EBB	__MASK(FSCR_EBB_LG)
 #define   FSCR_DSCR	__MASK(FSCR_DSCR_LG)
 #define SPRN_HFSCR	0xbe	/* HV=1 Facility Status & Control Register */
-#define   HFSCR_LM	__MASK(FSCR_LM_LG)
+#define   HFSCR_MSGP	__MASK(FSCR_MSGP_LG)
 #define   HFSCR_TAR	__MASK(FSCR_TAR_LG)
 #define   HFSCR_EBB	__MASK(FSCR_EBB_LG)
 #define   HFSCR_TM	__MASK(FSCR_TM_LG)
@@ -358,6 +359,7 @@
 #define     LPCR_PECE_HVEE	ASM_CONST(0x0000400000000000)	/* P9 Wakeup on HV interrupts */
 #define   LPCR_MER		ASM_CONST(0x0000000000000800)	/* Mediated External Exception */
 #define   LPCR_MER_SH		11
+#define	  LPCR_GTSE		ASM_CONST(0x0000000000000400)  	/* Guest Translation Shootdown Enable */
 #define   LPCR_TC		ASM_CONST(0x0000000000000200)	/* Translation control */
 #define   LPCR_LPES		0x0000000c
 #define   LPCR_LPES0		ASM_CONST(0x0000000000000008)      /* LPAR Env selector 0 */
@@ -378,6 +380,12 @@
 #define   PCR_VEC_DIS	(1ul << (63-0))	/* Vec. disable (bit NA since POWER8) */
 #define   PCR_VSX_DIS	(1ul << (63-1))	/* VSX disable (bit NA since POWER8) */
 #define   PCR_TM_DIS	(1ul << (63-2))	/* Trans. memory disable (POWER8) */
+/*
+ * These bits are used in the function kvmppc_set_arch_compat() to specify and
+ * determine both the compatibility level which we want to emulate and the
+ * compatibility level which the host is capable of emulating.
+ */
+#define   PCR_ARCH_207	0x8		/* Architecture 2.07 */
 #define   PCR_ARCH_206	0x4		/* Architecture 2.06 */
 #define   PCR_ARCH_205	0x2		/* Architecture 2.05 */
 #define	SPRN_HEIR	0x153	/* Hypervisor Emulated Instruction Register */
@@ -641,9 +649,10 @@
 #define   SRR1_ISI_N_OR_G	0x10000000 /* ISI: Access is no-exec or G */
 #define   SRR1_ISI_PROT		0x08000000 /* ISI: Other protection fault */
 #define   SRR1_WAKEMASK		0x00380000 /* reason for wakeup */
-#define   SRR1_WAKEMASK_P8	0x003c0000 /* reason for wakeup on POWER8 */
+#define   SRR1_WAKEMASK_P8	0x003c0000 /* reason for wakeup on POWER8 and 9 */
 #define   SRR1_WAKESYSERR	0x00300000 /* System error */
 #define   SRR1_WAKEEE		0x00200000 /* External interrupt */
+#define   SRR1_WAKEHVI		0x00240000 /* Hypervisor Virtualization Interrupt (P9) */
 #define   SRR1_WAKEMT		0x00280000 /* mtctrl */
 #define	  SRR1_WAKEHMI		0x00280000 /* Hypervisor maintenance */
 #define   SRR1_WAKEDEC		0x00180000 /* Decrementer interrupt */
@@ -1219,6 +1228,7 @@
 #define PVR_ARCH_206	0x0f000003
 #define PVR_ARCH_206p	0x0f100003
 #define PVR_ARCH_207	0x0f000004
+#define PVR_ARCH_300	0x0f000005
 
 /* Macros for setting and retrieving special purpose registers */
 #ifndef __ASSEMBLY__
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/smp.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/smp.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/smp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/smp.h	2017-02-12 16:03:20.000000000 -0500
@@ -176,7 +176,7 @@ static inline void set_hard_smp_processo
 #endif /* !CONFIG_SMP */
 #endif /* !CONFIG_PPC64 */
 
-#if defined(CONFIG_PPC64) && (defined(CONFIG_SMP) || defined(CONFIG_KEXEC))
+#if defined(CONFIG_PPC64) && (defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE))
 extern void smp_release_cpus(void);
 #else
 static inline void smp_release_cpus(void) { };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/spinlock.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/spinlock.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/spinlock.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/spinlock.h	2017-02-12 16:03:20.000000000 -0500
@@ -52,6 +52,14 @@
 #define SYNC_IO
 #endif
 
+#ifdef CONFIG_PPC_PSERIES
+#define vcpu_is_preempted vcpu_is_preempted
+static inline bool vcpu_is_preempted(int cpu)
+{
+	return !!(be32_to_cpu(lppaca_of(cpu).yield_count) & 1);
+}
+#endif
+
 static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock)
 {
 	return lock.slock == 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/systbl.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/systbl.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/systbl.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/systbl.h	2017-02-12 16:03:20.000000000 -0500
@@ -386,3 +386,4 @@ SYSCALL(mlock2)
 SYSCALL(copy_file_range)
 COMPAT_SYS_SPU(preadv2)
 COMPAT_SYS_SPU(pwritev2)
+SYSCALL(kexec_file_load)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/tlb.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/tlb.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/tlb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/tlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
 #define tlb_start_vma(tlb, vma)	do { } while (0)
 #define tlb_end_vma(tlb, vma)	do { } while (0)
 #define __tlb_remove_tlb_entry	__tlb_remove_tlb_entry
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
 
 extern void tlb_flush(struct mmu_gather *tlb);
 
@@ -46,6 +47,21 @@ static inline void __tlb_remove_tlb_entr
 #endif
 }
 
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+						     unsigned int page_size)
+{
+	if (!tlb->page_size)
+		tlb->page_size = page_size;
+	else if (tlb->page_size != page_size) {
+		tlb_flush_mmu(tlb);
+		/*
+		 * update the page size after flush for the new
+		 * mmu_gather.
+		 */
+		tlb->page_size = page_size;
+	}
+}
+
 #ifdef CONFIG_SMP
 static inline int mm_is_core_local(struct mm_struct *mm)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/trace.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/trace.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/trace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@ DEFINE_EVENT(ppc64_interrupt_class, time
 );
 
 #ifdef CONFIG_PPC_PSERIES
-extern void hcall_tracepoint_regfunc(void);
+extern int hcall_tracepoint_regfunc(void);
 extern void hcall_tracepoint_unregfunc(void);
 
 TRACE_EVENT_FN_COND(hcall_entry,
@@ -104,7 +104,7 @@ TRACE_EVENT_FN_COND(hcall_exit,
 #endif
 
 #ifdef CONFIG_PPC_POWERNV
-extern void opal_tracepoint_regfunc(void);
+extern int opal_tracepoint_regfunc(void);
 extern void opal_tracepoint_unregfunc(void);
 
 TRACE_EVENT_FN(opal_entry,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/uaccess.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/uaccess.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/uaccess.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/uaccess.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <asm/asm-compat.h>
+#include <asm/ppc_asm.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 
@@ -63,23 +64,30 @@
 	 __access_ok((__force unsigned long)(addr), (size), get_fs()))
 
 /*
- * The exception table consists of pairs of addresses: the first is the
- * address of an instruction that is allowed to fault, and the second is
+ * The exception table consists of pairs of relative addresses: the first is
+ * the address of an instruction that is allowed to fault, and the second is
  * the address at which the program should continue.  No registers are
- * modified, so it is entirely up to the continuation code to figure out
- * what to do.
+ * modified, so it is entirely up to the continuation code to figure out what
+ * to do.
  *
- * All the routines below use bits of fixup code that are out of line
- * with the main instruction path.  This means when everything is well,
- * we don't even have to jump over them.  Further, they do not intrude
- * on our cache or tlb entries.
+ * All the routines below use bits of fixup code that are out of line with the
+ * main instruction path.  This means when everything is well, we don't even
+ * have to jump over them.  Further, they do not intrude on our cache or tlb
+ * entries.
  */
 
+#define ARCH_HAS_RELATIVE_EXTABLE
+
 struct exception_table_entry {
-	unsigned long insn;
-	unsigned long fixup;
+	int insn;
+	int fixup;
 };
 
+static inline unsigned long extable_fixup(const struct exception_table_entry *x)
+{
+	return (unsigned long)&x->fixup + x->fixup;
+}
+
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
@@ -132,10 +140,7 @@ extern long __put_user_bad(void);
 		"3:	li %0,%3\n"				\
 		"	b 2b\n"					\
 		".previous\n"					\
-		".section __ex_table,\"a\"\n"			\
-			PPC_LONG_ALIGN "\n"			\
-			PPC_LONG "1b,3b\n"			\
-		".previous"					\
+		EX_TABLE(1b, 3b)				\
 		: "=r" (err)					\
 		: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
 
@@ -152,11 +157,8 @@ extern long __put_user_bad(void);
 		"4:	li %0,%3\n"				\
 		"	b 3b\n"					\
 		".previous\n"					\
-		".section __ex_table,\"a\"\n"			\
-			PPC_LONG_ALIGN "\n"			\
-			PPC_LONG "1b,4b\n"			\
-			PPC_LONG "2b,4b\n"			\
-		".previous"					\
+		EX_TABLE(1b, 4b)				\
+		EX_TABLE(2b, 4b)				\
 		: "=r" (err)					\
 		: "r" (x), "b" (addr), "i" (-EFAULT), "0" (err))
 #endif /* __powerpc64__ */
@@ -215,10 +217,7 @@ extern long __get_user_bad(void);
 		"	li %1,0\n"			\
 		"	b 2b\n"				\
 		".previous\n"				\
-		".section __ex_table,\"a\"\n"		\
-			PPC_LONG_ALIGN "\n"		\
-			PPC_LONG "1b,3b\n"		\
-		".previous"				\
+		EX_TABLE(1b, 3b)			\
 		: "=r" (err), "=r" (x)			\
 		: "b" (addr), "i" (-EFAULT), "0" (err))
 
@@ -237,11 +236,8 @@ extern long __get_user_bad(void);
 		"	li %1+1,0\n"			\
 		"	b 3b\n"				\
 		".previous\n"				\
-		".section __ex_table,\"a\"\n"		\
-			PPC_LONG_ALIGN "\n"		\
-			PPC_LONG "1b,4b\n"		\
-			PPC_LONG "2b,4b\n"		\
-		".previous"				\
+		EX_TABLE(1b, 4b)			\
+		EX_TABLE(2b, 4b)			\
 		: "=r" (err), "=&r" (x)			\
 		: "b" (addr), "i" (-EFAULT), "0" (err))
 #endif /* __powerpc64__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/unistd.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/unistd.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/unistd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/unistd.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls		382
+#define NR_syscalls		383
 
 #define __NR__exit __NR_exit
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/word-at-a-time.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/word-at-a-time.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/word-at-a-time.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/word-at-a-time.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
 
 #include <linux/kernel.h>
 #include <asm/asm-compat.h>
+#include <asm/ppc_asm.h>
 
 #ifdef __BIG_ENDIAN__
 
@@ -193,10 +194,7 @@ static inline unsigned long load_unalign
 #endif
 	"b	2b\n"
 	".previous\n"
-	".section __ex_table,\"a\"\n\t"
-		PPC_LONG_ALIGN "\n\t"
-		PPC_LONG "1b,3b\n"
-	".previous"
+	EX_TABLE(1b, 3b)
 	: [tmp] "=&b" (tmp), [offset] "=&r" (offset), [ret] "=&r" (ret)
 	: [addr] "b" (addr), "m" (*(unsigned long *)addr));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/xics.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/xics.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/xics.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/xics.h	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,7 @@ static inline int icp_hv_init(void) { re
 
 #ifdef CONFIG_PPC_POWERNV
 extern int icp_opal_init(void);
+extern void icp_opal_flush_interrupt(void);
 #else
 static inline int icp_opal_init(void) { return -ENODEV; }
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/asm/xilinx_intc.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/xilinx_intc.h
--- linux-libre-4.9-gnu/arch/powerpc/include/asm/xilinx_intc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/asm/xilinx_intc.h	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #ifdef __KERNEL__
 
 extern void __init xilinx_intc_init_tree(void);
-extern unsigned int xilinx_intc_get_irq(void);
+extern unsigned int xintc_get_irq(void);
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_XILINX_INTC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/uapi/asm/kvm.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/uapi/asm/kvm.h
--- linux-libre-4.9-gnu/arch/powerpc/include/uapi/asm/kvm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/uapi/asm/kvm.h	2017-02-12 16:03:20.000000000 -0500
@@ -573,6 +573,10 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_SPRG9	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
 #define KVM_REG_PPC_DBSR	(KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
 
+/* POWER9 registers */
+#define KVM_REG_PPC_TIDR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
+#define KVM_REG_PPC_PSSCR	(KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
+
 /* Transactional Memory checkpointed state:
  * This is all GPRs, all VSX regs and a subset of SPRs
  */
@@ -596,6 +600,7 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_TM_VSCR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
 #define KVM_REG_PPC_TM_DSCR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
 #define KVM_REG_PPC_TM_TAR	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
+#define KVM_REG_PPC_TM_XER	(KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x6a)
 
 /* PPC64 eXternal Interrupt Controller Specification */
 #define KVM_DEV_XICS_GRP_SOURCES	1	/* 64-bit source attributes */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/powerpc/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -97,4 +97,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif	/* _ASM_POWERPC_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/include/uapi/asm/unistd.h linux-libre-4.10-rc8-gnu/arch/powerpc/include/uapi/asm/unistd.h
--- linux-libre-4.9-gnu/arch/powerpc/include/uapi/asm/unistd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/include/uapi/asm/unistd.h	2017-02-12 16:03:20.000000000 -0500
@@ -392,5 +392,6 @@
 #define __NR_copy_file_range	379
 #define __NR_preadv2		380
 #define __NR_pwritev2		381
+#define __NR_kexec_file_load	382
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -80,6 +80,7 @@ config ARCH_HAS_DMA_SET_COHERENT_MASK
 config PPC
 	bool
 	default y
+	select BUILDTIME_EXTABLE_SORT
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select BINFMT_ELF
@@ -160,6 +161,7 @@ config PPC
 	select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
 	select GENERIC_CPU_AUTOPROBE
 	select HAVE_VIRT_CPU_ACCOUNTING
+	select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE
 	select HAVE_ARCH_HARDENED_USERCOPY
 	select HAVE_KERNEL_GZIP
 
@@ -395,6 +397,14 @@ config MPROFILE_KERNEL
 	depends on PPC64 && CPU_LITTLE_ENDIAN
 	def_bool !DISABLE_MPROFILE_KERNEL
 
+config USE_THIN_ARCHIVES
+	bool "Build the kernel using thin archives"
+	default n
+	select THIN_ARCHIVES
+	help
+	  Build the kernel using thin archives.
+	  If you're unsure say N.
+
 config IOMMU_HELPER
 	def_bool PPC64
 
@@ -455,10 +465,25 @@ config KEXEC
 	  interface is strongly in flux, so no good recommendation can be
 	  made.
 
+config KEXEC_FILE
+	bool "kexec file based system call"
+	select KEXEC_CORE
+	select HAVE_IMA_KEXEC
+	select BUILD_BIN2C
+	depends on PPC64
+	depends on CRYPTO=y
+	depends on CRYPTO_SHA256=y
+	help
+	  This is a new version of the kexec system call. This call is
+	  file based and takes in file descriptors as system call arguments
+	  for kernel and initramfs as opposed to a list of segments as is the
+	  case for the older kexec call.
+
 config RELOCATABLE
 	bool "Build a relocatable kernel"
 	depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE))
 	select NONSTATIC_KERNEL
+	select MODULE_REL_CRCS if MODVERSIONS
 	help
 	  This builds a kernel image that is capable of running at the
 	  location the kernel is loaded at. For ppc32, there is no any
@@ -478,6 +503,15 @@ config RELOCATABLE
 	  setting can still be useful to bootwrappers that need to know the
 	  load address of the kernel (eg. u-boot/mkimage).
 
+config RELOCATABLE_TEST
+	bool "Test relocatable kernel"
+	depends on (PPC64 && RELOCATABLE)
+	default n
+	help
+	  This runs the relocatable kernel at the address it was initially
+	  loaded at, which tends to be non-zero and therefore test the
+	  relocation code.
+
 config CRASH_DUMP
 	bool "Build a kdump crash kernel"
 	depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
@@ -489,7 +523,7 @@ config CRASH_DUMP
 
 config FA_DUMP
 	bool "Firmware-assisted dump"
-	depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC
+	depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC_CORE
 	help
 	  A robust mechanism to get reliable kernel crash dump with
 	  assistance from firmware. This approach does not use kexec,
@@ -548,6 +582,13 @@ config ARCH_SPARSEMEM_DEFAULT
 config SYS_SUPPORTS_HUGETLBFS
 	bool
 
+config ILLEGAL_POINTER_VALUE
+	hex
+	# This is roughly half way between the top of user space and the bottom
+	# of kernel space, which seems about as good as we can get.
+	default 0x5deadbeef0000000 if PPC64
+	default 0
+
 source "mm/Kconfig"
 
 config ARCH_MEMORY_PROBE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/Kconfig.debug linux-libre-4.10-rc8-gnu/arch/powerpc/Kconfig.debug
--- linux-libre-4.9-gnu/arch/powerpc/Kconfig.debug	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/Kconfig.debug	2017-02-12 16:03:20.000000000 -0500
@@ -354,4 +354,20 @@ config FAIL_IOMMU
 
 	  If you are unsure, say N.
 
+config PPC_PTDUMP
+        bool "Export kernel pagetable layout to userspace via debugfs"
+        depends on DEBUG_KERNEL
+        select DEBUG_FS
+        help
+	  This option exports the state of the kernel pagetables to a
+	  debugfs file. This is only useful for kernel developers who are
+	  working in architecture specific areas of the kernel - probably
+	  not a good idea to enable this feature in a production kernel.
+
+	  If you are unsure, say N.
+
+config PPC_HTDUMP
+	def_bool y
+	depends on PPC_PTDUMP && PPC_BOOK3S
+
 endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/align.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/align.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/align.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/align.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cache.h>
 #include <asm/cputable.h>
 #include <asm/emulated_ops.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/asm-offsets.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/asm-offsets.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/asm-offsets.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/asm-offsets.c	2017-02-12 16:03:20.000000000 -0500
@@ -487,6 +487,7 @@ int main(void)
 
 	/* book3s */
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	DEFINE(KVM_TLB_SETS, offsetof(struct kvm, arch.tlb_sets));
 	DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1));
 	DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid));
 	DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr));
@@ -548,6 +549,8 @@ int main(void)
 	DEFINE(VCPU_TCSCR, offsetof(struct kvm_vcpu, arch.tcscr));
 	DEFINE(VCPU_ACOP, offsetof(struct kvm_vcpu, arch.acop));
 	DEFINE(VCPU_WORT, offsetof(struct kvm_vcpu, arch.wort));
+	DEFINE(VCPU_TID, offsetof(struct kvm_vcpu, arch.tid));
+	DEFINE(VCPU_PSSCR, offsetof(struct kvm_vcpu, arch.psscr));
 	DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_map));
 	DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest));
 	DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads));
@@ -569,6 +572,7 @@ int main(void)
 	DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
 	DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
 	DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
+	DEFINE(VCPU_XER_TM, offsetof(struct kvm_vcpu, arch.xer_tm));
 	DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
 	DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
 	DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/cpu_setup_power.S linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/cpu_setup_power.S
--- linux-libre-4.9-gnu/arch/powerpc/kernel/cpu_setup_power.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/cpu_setup_power.S	2017-02-12 16:03:20.000000000 -0500
@@ -96,6 +96,7 @@ _GLOBAL(__setup_cpu_power9)
 	mtlr	r11
 	beqlr
 	li	r0,0
+	mtspr	SPRN_PSSCR,r0
 	mtspr	SPRN_LPID,r0
 	mfspr	r3,SPRN_LPCR
 	LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
@@ -116,6 +117,7 @@ _GLOBAL(__restore_cpu_power9)
 	mtlr	r11
 	beqlr
 	li	r0,0
+	mtspr	SPRN_PSSCR,r0
 	mtspr	SPRN_LPID,r0
 	mfspr   r3,SPRN_LPCR
 	LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE)
@@ -174,7 +176,7 @@ __init_FSCR:
 __init_HFSCR:
 	mfspr	r3,SPRN_HFSCR
 	ori	r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|\
-		      HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB
+		      HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB|HFSCR_MSGP
 	mtspr	SPRN_HFSCR,r3
 	blr
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/crash_dump.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/crash_dump.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/crash_dump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/crash_dump.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <asm/kdump.h>
 #include <asm/prom.h>
 #include <asm/firmware.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/rtas.h>
 
 #ifdef DEBUG
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/dma.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/dma.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -203,6 +203,10 @@ static int dma_direct_map_sg(struct devi
 	for_each_sg(sgl, sg, nents, i) {
 		sg->dma_address = sg_phys(sg) + get_dma_offset(dev);
 		sg->dma_length = sg->length;
+
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+
 		__dma_sync_page(sg_page(sg), sg->offset, sg->length, direction);
 	}
 
@@ -235,7 +239,10 @@ static inline dma_addr_t dma_direct_map_
 					     unsigned long attrs)
 {
 	BUG_ON(dir == DMA_NONE);
-	__dma_sync_page(page, offset, size, dir);
+
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		__dma_sync_page(page, offset, size, dir);
+
 	return page_to_phys(page) + offset + get_dma_offset(dev);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/eeh.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/eeh.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh.c	2017-02-12 16:03:20.000000000 -0500
@@ -298,9 +298,17 @@ void eeh_slot_error_detail(struct eeh_pe
 	 *
 	 * For pHyp, we have to enable IO for log retrieval. Otherwise,
 	 * 0xFF's is always returned from PCI config space.
+	 *
+	 * When the @severity is EEH_LOG_PERM, the PE is going to be
+	 * removed. Prior to that, the drivers for devices included in
+	 * the PE will be closed. The drivers rely on working IO path
+	 * to bring the devices to quiet state. Otherwise, PCI traffic
+	 * from those devices after they are removed is like to cause
+	 * another unexpected EEH error.
 	 */
 	if (!(pe->type & EEH_PE_PHB)) {
-		if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG))
+		if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG) ||
+		    severity == EEH_LOG_PERM)
 			eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
 
 		/*
@@ -372,7 +380,7 @@ static int eeh_phb_check_failure(struct
 	/* Find the PHB PE */
 	phb_pe = eeh_phb_pe_get(pe->phb);
 	if (!phb_pe) {
-		pr_warn("%s Can't find PE for PHB#%d\n",
+		pr_warn("%s Can't find PE for PHB#%x\n",
 			__func__, pe->phb->global_number);
 		return -EEXIST;
 	}
@@ -664,7 +672,7 @@ int eeh_pci_enable(struct eeh_pe *pe, in
 	rc = eeh_ops->set_option(pe, function);
 	if (rc)
 		pr_warn("%s: Unexpected state change %d on "
-			"PHB#%d-PE#%x, err=%d\n",
+			"PHB#%x-PE#%x, err=%d\n",
 			__func__, function, pe->phb->global_number,
 			pe->addr, rc);
 
@@ -808,76 +816,67 @@ static void *eeh_set_dev_freset(void *da
 }
 
 /**
- * eeh_reset_pe_once - Assert the pci #RST line for 1/4 second
+ * eeh_pe_reset_full - Complete a full reset process on the indicated PE
  * @pe: EEH PE
  *
- * Assert the PCI #RST line for 1/4 second.
+ * This function executes a full reset procedure on a PE, including setting
+ * the appropriate flags, performing a fundamental or hot reset, and then
+ * deactivating the reset status.  It is designed to be used within the EEH
+ * subsystem, as opposed to eeh_pe_reset which is exported to drivers and
+ * only performs a single operation at a time.
+ *
+ * This function will attempt to reset a PE three times before failing.
  */
-static void eeh_reset_pe_once(struct eeh_pe *pe)
+int eeh_pe_reset_full(struct eeh_pe *pe)
 {
+	int active_flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
+	int reset_state = (EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
+	int type = EEH_RESET_HOT;
 	unsigned int freset = 0;
+	int i, state, ret;
 
-	/* Determine type of EEH reset required for
-	 * Partitionable Endpoint, a hot-reset (1)
-	 * or a fundamental reset (3).
-	 * A fundamental reset required by any device under
-	 * Partitionable Endpoint trumps hot-reset.
+	/*
+	 * Determine the type of reset to perform - hot or fundamental.
+	 * Hot reset is the default operation, unless any device under the
+	 * PE requires a fundamental reset.
 	 */
 	eeh_pe_dev_traverse(pe, eeh_set_dev_freset, &freset);
 
 	if (freset)
-		eeh_ops->reset(pe, EEH_RESET_FUNDAMENTAL);
-	else
-		eeh_ops->reset(pe, EEH_RESET_HOT);
-
-	eeh_ops->reset(pe, EEH_RESET_DEACTIVATE);
-}
-
-/**
- * eeh_reset_pe - Reset the indicated PE
- * @pe: EEH PE
- *
- * This routine should be called to reset indicated device, including
- * PE. A PE might include multiple PCI devices and sometimes PCI bridges
- * might be involved as well.
- */
-int eeh_reset_pe(struct eeh_pe *pe)
-{
-	int flags = (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE);
-	int i, state, ret;
+		type = EEH_RESET_FUNDAMENTAL;
 
-	/* Mark as reset and block config space */
-	eeh_pe_state_mark(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
+	/* Mark the PE as in reset state and block config space accesses */
+	eeh_pe_state_mark(pe, reset_state);
 
-	/* Take three shots at resetting the bus */
+	/* Make three attempts at resetting the bus */
 	for (i = 0; i < 3; i++) {
-		eeh_reset_pe_once(pe);
+		ret = eeh_pe_reset(pe, type);
+		if (ret)
+			break;
 
-		/*
-		 * EEH_PE_ISOLATED is expected to be removed after
-		 * BAR restore.
-		 */
+		ret = eeh_pe_reset(pe, EEH_RESET_DEACTIVATE);
+		if (ret)
+			break;
+
+		/* Wait until the PE is in a functioning state */
 		state = eeh_ops->wait_state(pe, PCI_BUS_RESET_WAIT_MSEC);
-		if ((state & flags) == flags) {
-			ret = 0;
-			goto out;
-		}
+		if ((state & active_flags) == active_flags)
+			break;
 
 		if (state < 0) {
-			pr_warn("%s: Unrecoverable slot failure on PHB#%d-PE#%x",
+			pr_warn("%s: Unrecoverable slot failure on PHB#%x-PE#%x",
 				__func__, pe->phb->global_number, pe->addr);
 			ret = -ENOTRECOVERABLE;
-			goto out;
+			break;
 		}
 
-		/* We might run out of credits */
+		/* Set error in case this is our last attempt */
 		ret = -EIO;
 		pr_warn("%s: Failure %d resetting PHB#%x-PE#%x\n (%d)\n",
 			__func__, state, pe->phb->global_number, pe->addr, (i + 1));
 	}
 
-out:
-	eeh_pe_state_clear(pe, EEH_PE_RESET | EEH_PE_CFG_BLOCKED);
+	eeh_pe_state_clear(pe, reset_state);
 	return ret;
 }
 
@@ -1601,6 +1600,7 @@ static int eeh_pe_reenable_devices(struc
 	return eeh_unfreeze_pe(pe, true);
 }
 
+
 /**
  * eeh_pe_reset - Issue PE reset according to specified type
  * @pe: EEH PE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/eeh_driver.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh_driver.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/eeh_driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh_driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -545,7 +545,7 @@ static void *eeh_pe_detach_dev(void *dat
 static void *__eeh_clear_pe_frozen_state(void *data, void *flag)
 {
 	struct eeh_pe *pe = (struct eeh_pe *)data;
-	bool *clear_sw_state = flag;
+	bool clear_sw_state = *(bool *)flag;
 	int i, rc = 1;
 
 	for (i = 0; rc && i < 3; i++)
@@ -588,7 +588,7 @@ int eeh_pe_reset_and_recover(struct eeh_
 	eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
 
 	/* Issue reset */
-	ret = eeh_reset_pe(pe);
+	ret = eeh_pe_reset_full(pe);
 	if (ret) {
 		eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
 		return ret;
@@ -659,7 +659,7 @@ static int eeh_reset_device(struct eeh_p
 	 * config accesses. So we prefer to block them. However, controlled
 	 * PCI config accesses initiated from EEH itself are allowed.
 	 */
-	rc = eeh_reset_pe(pe);
+	rc = eeh_pe_reset_full(pe);
 	if (rc)
 		return rc;
 
@@ -734,7 +734,7 @@ static void eeh_handle_normal_event(stru
 
 	frozen_bus = eeh_pe_bus_get(pe);
 	if (!frozen_bus) {
-		pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n",
+		pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n",
 			__func__, pe->phb->global_number, pe->addr);
 		return;
 	}
@@ -878,7 +878,7 @@ excess_failures:
 	 * are due to poorly seated PCI cards. Only 10% or so are
 	 * due to actual, failed cards.
 	 */
-	pr_err("EEH: PHB#%d-PE#%x has failed %d times in the\n"
+	pr_err("EEH: PHB#%x-PE#%x has failed %d times in the\n"
 	       "last hour and has been permanently disabled.\n"
 	       "Please try reseating or replacing it.\n",
 		pe->phb->global_number, pe->addr,
@@ -886,7 +886,7 @@ excess_failures:
 	goto perm_error;
 
 hard_fail:
-	pr_err("EEH: Unable to recover from failure from PHB#%d-PE#%x.\n"
+	pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n"
 	       "Please try reseating or replacing it\n",
 		pe->phb->global_number, pe->addr);
 
@@ -1000,7 +1000,7 @@ static void eeh_handle_special_event(voi
 				bus = eeh_pe_bus_get(phb_pe);
 				if (!bus) {
 					pr_err("%s: Cannot find PCI bus for "
-					       "PHB#%d-PE#%x\n",
+					       "PHB#%x-PE#%x\n",
 					       __func__,
 					       pe->phb->global_number,
 					       pe->addr);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/eeh_event.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh_event.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/eeh_event.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh_event.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,11 +75,11 @@ static int eeh_event_handler(void * dumm
 		if (pe) {
 			eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
 			if (pe->type & EEH_PE_PHB)
-				pr_info("EEH: Detected error on PHB#%d\n",
+				pr_info("EEH: Detected error on PHB#%x\n",
 					 pe->phb->global_number);
 			else
 				pr_info("EEH: Detected PCI bus error on "
-					"PHB#%d-PE#%x\n",
+					"PHB#%x-PE#%x\n",
 					pe->phb->global_number, pe->addr);
 			eeh_handle_event(pe);
 			eeh_pe_state_clear(pe, EEH_PE_RECOVERING);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/eeh_pe.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh_pe.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/eeh_pe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/eeh_pe.c	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@ int eeh_phb_pe_create(struct pci_control
 	/* Put it into the list */
 	list_add_tail(&pe->child, &eeh_phb_pe);
 
-	pr_debug("EEH: Add PE for PHB#%d\n", phb->global_number);
+	pr_debug("EEH: Add PE for PHB#%x\n", phb->global_number);
 
 	return 0;
 }
@@ -333,7 +333,7 @@ int eeh_add_to_parent_pe(struct eeh_dev
 
 	/* Check if the PE number is valid */
 	if (!eeh_has_flag(EEH_VALID_PE_ZERO) && !edev->pe_config_addr) {
-		pr_err("%s: Invalid PE#0 for edev 0x%x on PHB#%d\n",
+		pr_err("%s: Invalid PE#0 for edev 0x%x on PHB#%x\n",
 		       __func__, edev->config_addr, edev->phb->global_number);
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/exceptions-64e.S linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/exceptions-64e.S
--- linux-libre-4.9-gnu/arch/powerpc/kernel/exceptions-64e.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/exceptions-64e.S	2017-02-12 16:03:20.000000000 -0500
@@ -923,10 +923,10 @@ kernel_dbg_exc:
 			        PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0x340)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.save_nvgprs
+	bl	save_nvgprs
 	INTS_RESTORE_HARD
-	bl	.unknown_exception
-	b	.ret_from_except
+	bl	unknown_exception
+	b	ret_from_except
 
 /*
  * An interrupt came in while soft-disabled; We mark paca->irq_happened
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/exceptions-64s.S linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-4.9-gnu/arch/powerpc/kernel/exceptions-64s.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/exceptions-64s.S	2017-02-12 16:03:20.000000000 -0500
@@ -1408,7 +1408,7 @@ USE_TEXT_SECTION()
 /*
  * Hash table stuff
  */
-	.align	7
+	.balign	IFETCH_ALIGN_BYTES
 do_hash_page:
 #ifdef CONFIG_PPC_STD_MMU_64
 	andis.	r0,r4,0xa410		/* weird error? */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/ftrace.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ftrace.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/ftrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ftrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,13 +47,11 @@ ftrace_modify_code(unsigned long ip, uns
 	unsigned int replaced;
 
 	/*
-	 * Note: Due to modules and __init, code can
-	 *  disappear and change, we need to protect against faulting
-	 *  as well as code changing. We do this by using the
-	 *  probe_kernel_* functions.
-	 *
-	 * No real locking needed, this code is run through
-	 * kstop_machine, or before SMP starts.
+	 * Note:
+	 * We are paranoid about modifying text, as if a bug was to happen, it
+	 * could cause us to read or write to someplace that could cause harm.
+	 * Carefully read and modify the code with probe_kernel_*(), and make
+	 * sure what we read is what we expected it to be before modifying it.
 	 */
 
 	/* read the text we want to modify */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/head_64.S linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/head_64.S
--- linux-libre-4.9-gnu/arch/powerpc/kernel/head_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/head_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -107,12 +107,19 @@ __secondary_hold_acknowledge:
 	 * crash_kernel region.  The loader is responsible for
 	 * observing the alignment requirement.
 	 */
+
+#ifdef CONFIG_RELOCATABLE_TEST
+#define RUN_AT_LOAD_DEFAULT 1		/* Test relocation, do not copy to 0 */
+#else
+#define RUN_AT_LOAD_DEFAULT 0x72756e30  /* "run0" -- relocate to 0 by default */
+#endif
+
 	/* Do not move this variable as kexec-tools knows about it. */
 	. = 0x5c
 	.globl	__run_at_load
 __run_at_load:
 DEFINE_FIXED_SYMBOL(__run_at_load)
-	.long	0x72756e30	/* "run0" -- relocate to 0 by default */
+	.long	RUN_AT_LOAD_DEFAULT
 #endif
 
 	. = 0x60
@@ -153,7 +160,7 @@ __secondary_hold:
 	cmpdi	0,r12,0
 	beq	100b
 
-#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
 #ifdef CONFIG_PPC_BOOK3E
 	tovirt(r12,r12)
 #endif
@@ -214,9 +221,9 @@ booting_thread_hwid:
  */
 _GLOBAL(book3e_start_thread)
 	LOAD_REG_IMMEDIATE(r5, MSR_KERNEL)
-	cmpi	0, r3, 0
+	cmpwi	r3, 0
 	beq	10f
-	cmpi	0, r3, 1
+	cmpwi	r3, 1
 	beq	11f
 	/* If the thread id is invalid, just exit. */
 	b	13f
@@ -241,9 +248,9 @@ _GLOBAL(book3e_start_thread)
  * r3 = the thread physical id
  */
 _GLOBAL(book3e_stop_thread)
-	cmpi	0, r3, 0
+	cmpwi	r3, 0
 	beq	10f
-	cmpi	0, r3, 1
+	cmpwi	r3, 1
 	beq	10f
 	/* If the thread id is invalid, just exit. */
 	b	13f
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/head_8xx.S linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/head_8xx.S
--- linux-libre-4.9-gnu/arch/powerpc/kernel/head_8xx.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/head_8xx.S	2017-02-12 16:03:20.000000000 -0500
@@ -73,6 +73,9 @@
 #define RPN_PATTERN	0x00f0
 #endif
 
+#define PAGE_SHIFT_512K		19
+#define PAGE_SHIFT_8M		23
+
 	__HEAD
 _ENTRY(_stext);
 _ENTRY(_start);
@@ -322,7 +325,7 @@ SystemCall:
 #endif
 
 InstructionTLBMiss:
-#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
+#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
 	mtspr	SPRN_SPRG_SCRATCH2, r3
 #endif
 	EXCEPTION_PROLOG_0
@@ -332,10 +335,12 @@ InstructionTLBMiss:
 	 */
 	mfspr	r10, SPRN_SRR0	/* Get effective address of fault */
 	INVALIDATE_ADJACENT_PAGES_CPU15(r11, r10)
-#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
 	/* Only modules will cause ITLB Misses as we always
 	 * pin the first 8MB of kernel memory */
+#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
 	mfcr	r3
+#endif
+#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
 	IS_KERNEL(r11, r10)
 #endif
 	mfspr	r11, SPRN_M_TW	/* Get level 1 table */
@@ -343,7 +348,6 @@ InstructionTLBMiss:
 	BRANCH_UNLESS_KERNEL(3f)
 	lis	r11, (swapper_pg_dir-PAGE_OFFSET)@ha
 3:
-	mtcr	r3
 #endif
 	/* Insert level 1 index */
 	rlwimi	r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
@@ -351,14 +355,25 @@ InstructionTLBMiss:
 
 	/* Extract level 2 index */
 	rlwinm	r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
+#ifdef CONFIG_HUGETLB_PAGE
+	mtcr	r11
+	bt-	28, 10f		/* bit 28 = Large page (8M) */
+	bt-	29, 20f		/* bit 29 = Large page (8M or 512k) */
+#endif
 	rlwimi	r10, r11, 0, 0, 32 - PAGE_SHIFT - 1	/* Add level 2 base */
 	lwz	r10, 0(r10)	/* Get the pte */
-
+4:
+#if defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
+	mtcr	r3
+#endif
 	/* Insert the APG into the TWC from the Linux PTE. */
 	rlwimi	r11, r10, 0, 25, 26
 	/* Load the MI_TWC with the attributes for this "segment." */
 	MTSPR_CPU6(SPRN_MI_TWC, r11, r3)	/* Set segment attributes */
 
+#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
+	rlwimi	r10, r11, 1, MI_SPS16K
+#endif
 #ifdef CONFIG_SWAP
 	rlwinm	r11, r10, 32-5, _PAGE_PRESENT
 	and	r11, r11, r10
@@ -371,16 +386,45 @@ InstructionTLBMiss:
 	 * set.  All other Linux PTE bits control the behavior
 	 * of the MMU.
 	 */
+#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
+	rlwimi	r10, r11, 0, 0x0ff0	/* Set 24-27, clear 20-23 */
+#else
 	rlwimi	r10, r11, 0, 0x0ff8	/* Set 24-27, clear 20-23,28 */
+#endif
 	MTSPR_CPU6(SPRN_MI_RPN, r10, r3)	/* Update TLB entry */
 
 	/* Restore registers */
-#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC)
+#if defined(CONFIG_8xx_CPU6) || defined(CONFIG_MODULES) || defined (CONFIG_DEBUG_PAGEALLOC) || defined (CONFIG_HUGETLB_PAGE)
 	mfspr	r3, SPRN_SPRG_SCRATCH2
 #endif
 	EXCEPTION_EPILOG_0
 	rfi
 
+#ifdef CONFIG_HUGETLB_PAGE
+10:	/* 8M pages */
+#ifdef CONFIG_PPC_16K_PAGES
+	/* Extract level 2 index */
+	rlwinm	r10, r10, 32 - (PAGE_SHIFT_8M - PAGE_SHIFT), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1), 29
+	/* Add level 2 base */
+	rlwimi	r10, r11, 0, 0, 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1) - 1
+#else
+	/* Level 2 base */
+	rlwinm	r10, r11, 0, ~HUGEPD_SHIFT_MASK
+#endif
+	lwz	r10, 0(r10)	/* Get the pte */
+	rlwinm	r11, r11, 0, 0xf
+	b	4b
+
+20:	/* 512k pages */
+	/* Extract level 2 index */
+	rlwinm	r10, r10, 32 - (PAGE_SHIFT_512K - PAGE_SHIFT), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1), 29
+	/* Add level 2 base */
+	rlwimi	r10, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
+	lwz	r10, 0(r10)	/* Get the pte */
+	rlwinm	r11, r11, 0, 0xf
+	b	4b
+#endif
+
 	. = 0x1200
 DataStoreTLBMiss:
 	mtspr	SPRN_SPRG_SCRATCH2, r3
@@ -407,7 +451,6 @@ _ENTRY(DTLBMiss_jmp)
 #endif
 	blt	cr7, DTLBMissLinear
 3:
-	mtcr	r3
 	mfspr	r10, SPRN_MD_EPN
 
 	/* Insert level 1 index */
@@ -418,8 +461,15 @@ _ENTRY(DTLBMiss_jmp)
 	 */
 	/* Extract level 2 index */
 	rlwinm	r10, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
+#ifdef CONFIG_HUGETLB_PAGE
+	mtcr	r11
+	bt-	28, 10f		/* bit 28 = Large page (8M) */
+	bt-	29, 20f		/* bit 29 = Large page (8M or 512k) */
+#endif
 	rlwimi	r10, r11, 0, 0, 32 - PAGE_SHIFT - 1	/* Add level 2 base */
 	lwz	r10, 0(r10)	/* Get the pte */
+4:
+	mtcr	r3
 
 	/* Insert the Guarded flag and APG into the TWC from the Linux PTE.
 	 * It is bit 26-27 of both the Linux PTE and the TWC (at least
@@ -434,6 +484,11 @@ _ENTRY(DTLBMiss_jmp)
 	rlwimi	r11, r10, 32-5, 30, 30
 	MTSPR_CPU6(SPRN_MD_TWC, r11, r3)
 
+	/* In 4k pages mode, SPS (bit 28) in RPN must match PS[1] (bit 29)
+	 * In 16k pages mode, SPS is always 1 */
+#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
+	rlwimi	r10, r11, 1, MD_SPS16K
+#endif
 	/* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set.
 	 * We also need to know if the insn is a load/store, so:
 	 * Clear _PAGE_PRESENT and load that which will
@@ -455,7 +510,11 @@ _ENTRY(DTLBMiss_jmp)
 	 * of the MMU.
 	 */
 	li	r11, RPN_PATTERN
+#if defined (CONFIG_HUGETLB_PAGE) && defined (CONFIG_PPC_4K_PAGES)
+	rlwimi	r10, r11, 0, 24, 27	/* Set 24-27 */
+#else
 	rlwimi	r10, r11, 0, 24, 28	/* Set 24-27, clear 28 */
+#endif
 	rlwimi	r10, r11, 0, 20, 20	/* clear 20 */
 	MTSPR_CPU6(SPRN_MD_RPN, r10, r3)	/* Update TLB entry */
 
@@ -465,6 +524,30 @@ _ENTRY(DTLBMiss_jmp)
 	EXCEPTION_EPILOG_0
 	rfi
 
+#ifdef CONFIG_HUGETLB_PAGE
+10:	/* 8M pages */
+	/* Extract level 2 index */
+#ifdef CONFIG_PPC_16K_PAGES
+	rlwinm	r10, r10, 32 - (PAGE_SHIFT_8M - PAGE_SHIFT), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1), 29
+	/* Add level 2 base */
+	rlwimi	r10, r11, 0, 0, 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1) - 1
+#else
+	/* Level 2 base */
+	rlwinm	r10, r11, 0, ~HUGEPD_SHIFT_MASK
+#endif
+	lwz	r10, 0(r10)	/* Get the pte */
+	rlwinm	r11, r11, 0, 0xf
+	b	4b
+
+20:	/* 512k pages */
+	/* Extract level 2 index */
+	rlwinm	r10, r10, 32 - (PAGE_SHIFT_512K - PAGE_SHIFT), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1), 29
+	/* Add level 2 base */
+	rlwimi	r10, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
+	lwz	r10, 0(r10)	/* Get the pte */
+	rlwinm	r11, r11, 0, 0xf
+	b	4b
+#endif
 
 /* This is an instruction TLB error on the MPC8xx.  This could be due
  * to many reasons, such as executing guarded memory or illegal instruction
@@ -586,6 +669,9 @@ _ENTRY(FixupDAR_cmp)
 	/* Insert level 1 index */
 3:	rlwimi	r11, r10, 32 - ((PAGE_SHIFT - 2) << 1), (PAGE_SHIFT - 2) << 1, 29
 	lwz	r11, (swapper_pg_dir-PAGE_OFFSET)@l(r11)	/* Get the level 1 entry */
+	mtcr	r11
+	bt	28,200f		/* bit 28 = Large page (8M) */
+	bt	29,202f		/* bit 29 = Large page (8M or 512K) */
 	rlwinm	r11, r11,0,0,19	/* Extract page descriptor page address */
 	/* Insert level 2 index */
 	rlwimi	r11, r10, 32 - (PAGE_SHIFT - 2), 32 - PAGE_SHIFT, 29
@@ -611,6 +697,27 @@ _ENTRY(FixupDAR_cmp)
 141:	mfspr	r10,SPRN_SPRG_SCRATCH2
 	b	DARFixed	/* Nope, go back to normal TLB processing */
 
+	/* concat physical page address(r11) and page offset(r10) */
+200:
+#ifdef CONFIG_PPC_16K_PAGES
+	rlwinm	r11, r11, 0, 0, 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1) - 1
+	rlwimi	r11, r10, 32 - (PAGE_SHIFT_8M - 2), 32 + PAGE_SHIFT_8M - (PAGE_SHIFT << 1), 29
+#else
+	rlwinm	r11, r10, 0, ~HUGEPD_SHIFT_MASK
+#endif
+	lwz	r11, 0(r11)	/* Get the pte */
+	/* concat physical page address(r11) and page offset(r10) */
+	rlwimi	r11, r10, 0, 32 - PAGE_SHIFT_8M, 31
+	b	201b
+
+202:
+	rlwinm	r11, r11, 0, 0, 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1) - 1
+	rlwimi	r11, r10, 32 - (PAGE_SHIFT_512K - 2), 32 + PAGE_SHIFT_512K - (PAGE_SHIFT << 1), 29
+	lwz	r11, 0(r11)	/* Get the pte */
+	/* concat physical page address(r11) and page offset(r10) */
+	rlwimi	r11, r10, 0, 32 - PAGE_SHIFT_512K, 31
+	b	201b
+
 144:	mfspr	r10, SPRN_DSISR
 	rlwinm	r10, r10,0,7,5	/* Clear store bit for buggy dcbst insn */
 	mtspr	SPRN_DSISR, r10
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/hw_breakpoint.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/hw_breakpoint.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/hw_breakpoint.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/hw_breakpoint.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <asm/hw_breakpoint.h>
 #include <asm/processor.h>
 #include <asm/sstep.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * Stores the breakpoints currently in use on each breakpoint address
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/ibmebus.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ibmebus.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/ibmebus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ibmebus.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,759 +0,0 @@
-/*
- * IBM PowerPC IBM eBus Infrastructure Support.
- *
- * Copyright (c) 2005 IBM Corporation
- *  Joachim Fenkes <fenkes@de.ibm.com>
- *  Heiko J Schick <schickhj@de.ibm.com>
- *
- * All rights reserved.
- *
- * This source code is distributed under a dual license of GPL v2.0 and OpenIB
- * BSD.
- *
- * OpenIB BSD License
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/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>
-
-static struct device ibmebus_bus_device = { /* fake "parent" device */
-	.init_name = "ibmebus",
-};
-
-struct bus_type ibmebus_bus_type;
-
-/* These devices will automatically be added to the bus during init */
-static const struct of_device_id ibmebus_matches[] __initconst = {
-	{ .compatible = "IBM,lhca" },
-	{ .compatible = "IBM,lhea" },
-	{},
-};
-
-static void *ibmebus_alloc_coherent(struct device *dev,
-				    size_t size,
-				    dma_addr_t *dma_handle,
-				    gfp_t flag,
-				    unsigned long attrs)
-{
-	void *mem;
-
-	mem = kmalloc(size, flag);
-	*dma_handle = (dma_addr_t)mem;
-
-	return mem;
-}
-
-static void ibmebus_free_coherent(struct device *dev,
-				  size_t size, void *vaddr,
-				  dma_addr_t dma_handle,
-				  unsigned long attrs)
-{
-	kfree(vaddr);
-}
-
-static dma_addr_t ibmebus_map_page(struct device *dev,
-				   struct page *page,
-				   unsigned long offset,
-				   size_t size,
-				   enum dma_data_direction direction,
-				   unsigned long attrs)
-{
-	return (dma_addr_t)(page_address(page) + offset);
-}
-
-static void ibmebus_unmap_page(struct device *dev,
-			       dma_addr_t dma_addr,
-			       size_t size,
-			       enum dma_data_direction direction,
-			       unsigned long attrs)
-{
-	return;
-}
-
-static int ibmebus_map_sg(struct device *dev,
-			  struct scatterlist *sgl,
-			  int nents, enum dma_data_direction direction,
-			  unsigned long attrs)
-{
-	struct scatterlist *sg;
-	int i;
-
-	for_each_sg(sgl, sg, nents, i) {
-		sg->dma_address = (dma_addr_t) sg_virt(sg);
-		sg->dma_length = sg->length;
-	}
-
-	return nents;
-}
-
-static void ibmebus_unmap_sg(struct device *dev,
-			     struct scatterlist *sg,
-			     int nents, enum dma_data_direction direction,
-			     unsigned long attrs)
-{
-	return;
-}
-
-static int ibmebus_dma_supported(struct device *dev, u64 mask)
-{
-	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              = ibmebus_alloc_coherent,
-	.free               = 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)
-{
-	struct device_node *dn = to_platform_device(dev)->dev.of_node;
-	return (dn->full_name &&
-		(strcasecmp((char *)data, dn->full_name) == 0));
-}
-
-static int ibmebus_match_node(struct device *dev, void *data)
-{
-	return to_platform_device(dev)->dev.of_node == data;
-}
-
-static int ibmebus_create_device(struct device_node *dn)
-{
-	struct platform_device *dev;
-	int ret;
-
-	dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
-	if (!dev)
-		return -ENOMEM;
-
-	dev->dev.bus = &ibmebus_bus_type;
-	dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
-
-	ret = of_device_add(dev);
-	if (ret)
-		platform_device_put(dev);
-	return ret;
-}
-
-static int ibmebus_create_devices(const struct of_device_id *matches)
-{
-	struct device_node *root, *child;
-	int ret = 0;
-
-	root = of_find_node_by_path("/");
-
-	for_each_child_of_node(root, child) {
-		if (!of_match_node(matches, child))
-			continue;
-
-		if (bus_find_device(&ibmebus_bus_type, NULL, child,
-				    ibmebus_match_node))
-			continue;
-
-		ret = ibmebus_create_device(child);
-		if (ret) {
-			printk(KERN_ERR "%s: failed to create device (%i)",
-			       __func__, ret);
-			of_node_put(child);
-			break;
-		}
-	}
-
-	of_node_put(root);
-	return ret;
-}
-
-int ibmebus_register_driver(struct platform_driver *drv)
-{
-	/* If the driver uses devices that ibmebus doesn't know, add them */
-	ibmebus_create_devices(drv->driver.of_match_table);
-
-	drv->driver.bus = &ibmebus_bus_type;
-	return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL(ibmebus_register_driver);
-
-void ibmebus_unregister_driver(struct platform_driver *drv)
-{
-	driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL(ibmebus_unregister_driver);
-
-int ibmebus_request_irq(u32 ist, irq_handler_t handler,
-			unsigned long irq_flags, const char *devname,
-			void *dev_id)
-{
-	unsigned int irq = irq_create_mapping(NULL, ist);
-
-	if (!irq)
-		return -EINVAL;
-
-	return request_irq(irq, handler, irq_flags, devname, dev_id);
-}
-EXPORT_SYMBOL(ibmebus_request_irq);
-
-void ibmebus_free_irq(u32 ist, void *dev_id)
-{
-	unsigned int irq = irq_find_mapping(NULL, ist);
-
-	free_irq(irq, dev_id);
-	irq_dispose_mapping(irq);
-}
-EXPORT_SYMBOL(ibmebus_free_irq);
-
-static char *ibmebus_chomp(const char *in, size_t count)
-{
-	char *out = kmalloc(count + 1, GFP_KERNEL);
-
-	if (!out)
-		return NULL;
-
-	memcpy(out, in, count);
-	out[count] = '\0';
-	if (out[count - 1] == '\n')
-		out[count - 1] = '\0';
-
-	return out;
-}
-
-static ssize_t ibmebus_store_probe(struct bus_type *bus,
-				   const char *buf, size_t count)
-{
-	struct device_node *dn = NULL;
-	char *path;
-	ssize_t rc = 0;
-
-	path = ibmebus_chomp(buf, count);
-	if (!path)
-		return -ENOMEM;
-
-	if (bus_find_device(&ibmebus_bus_type, NULL, path,
-			    ibmebus_match_path)) {
-		printk(KERN_WARNING "%s: %s has already been probed\n",
-		       __func__, path);
-		rc = -EEXIST;
-		goto out;
-	}
-
-	if ((dn = of_find_node_by_path(path))) {
-		rc = ibmebus_create_device(dn);
-		of_node_put(dn);
-	} else {
-		printk(KERN_WARNING "%s: no such device node: %s\n",
-		       __func__, path);
-		rc = -ENODEV;
-	}
-
-out:
-	kfree(path);
-	if (rc)
-		return rc;
-	return count;
-}
-static BUS_ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe);
-
-static ssize_t ibmebus_store_remove(struct bus_type *bus,
-				    const char *buf, size_t count)
-{
-	struct device *dev;
-	char *path;
-
-	path = ibmebus_chomp(buf, count);
-	if (!path)
-		return -ENOMEM;
-
-	if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
-				   ibmebus_match_path))) {
-		of_device_unregister(to_platform_device(dev));
-
-		kfree(path);
-		return count;
-	} else {
-		printk(KERN_WARNING "%s: %s not on the bus\n",
-		       __func__, path);
-
-		kfree(path);
-		return -ENODEV;
-	}
-}
-static BUS_ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove);
-
-static struct attribute *ibmbus_bus_attrs[] = {
-	&bus_attr_probe.attr,
-	&bus_attr_remove.attr,
-	NULL,
-};
-ATTRIBUTE_GROUPS(ibmbus_bus);
-
-static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
-{
-	const struct of_device_id *matches = drv->of_match_table;
-
-	if (!matches)
-		return 0;
-
-	return of_match_device(matches, dev) != NULL;
-}
-
-static int ibmebus_bus_device_probe(struct device *dev)
-{
-	int error = -ENODEV;
-	struct platform_driver *drv;
-	struct platform_device *of_dev;
-
-	drv = to_platform_driver(dev->driver);
-	of_dev = to_platform_device(dev);
-
-	if (!drv->probe)
-		return error;
-
-	of_dev_get(of_dev);
-
-	if (of_driver_match_device(dev, dev->driver))
-		error = drv->probe(of_dev);
-	if (error)
-		of_dev_put(of_dev);
-
-	return error;
-}
-
-static int ibmebus_bus_device_remove(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct platform_driver *drv = to_platform_driver(dev->driver);
-
-	if (dev->driver && drv->remove)
-		drv->remove(of_dev);
-	return 0;
-}
-
-static void ibmebus_bus_device_shutdown(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct platform_driver *drv = to_platform_driver(dev->driver);
-
-	if (dev->driver && drv->shutdown)
-		drv->shutdown(of_dev);
-}
-
-/*
- * ibmebus_bus_device_attrs
- */
-static ssize_t devspec_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct platform_device *ofdev;
-
-	ofdev = to_platform_device(dev);
-	return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name);
-}
-
-static ssize_t name_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct platform_device *ofdev;
-
-	ofdev = to_platform_device(dev);
-	return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
-}
-
-static ssize_t modalias_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
-	buf[len] = '\n';
-	buf[len+1] = 0;
-	return len+1;
-}
-
-static struct device_attribute ibmebus_bus_device_attrs[] = {
-	__ATTR_RO(devspec),
-	__ATTR_RO(name),
-	__ATTR_RO(modalias),
-	__ATTR_NULL
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int ibmebus_bus_legacy_suspend(struct device *dev, pm_message_t mesg)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct platform_driver *drv = to_platform_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->suspend)
-		ret = drv->suspend(of_dev, mesg);
-	return ret;
-}
-
-static int ibmebus_bus_legacy_resume(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct platform_driver *drv = to_platform_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->resume)
-		ret = drv->resume(of_dev);
-	return ret;
-}
-
-static int ibmebus_bus_pm_prepare(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (drv && drv->pm && drv->pm->prepare)
-		ret = drv->pm->prepare(dev);
-
-	return ret;
-}
-
-static void ibmebus_bus_pm_complete(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-
-	if (drv && drv->pm && drv->pm->complete)
-		drv->pm->complete(dev);
-}
-
-#ifdef CONFIG_SUSPEND
-
-static int ibmebus_bus_pm_suspend(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->suspend)
-			ret = drv->pm->suspend(dev);
-	} else {
-		ret = ibmebus_bus_legacy_suspend(dev, PMSG_SUSPEND);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_suspend_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->suspend_noirq)
-			ret = drv->pm->suspend_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_resume(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->resume)
-			ret = drv->pm->resume(dev);
-	} else {
-		ret = ibmebus_bus_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_resume_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->resume_noirq)
-			ret = drv->pm->resume_noirq(dev);
-	}
-
-	return ret;
-}
-
-#else /* !CONFIG_SUSPEND */
-
-#define ibmebus_bus_pm_suspend		NULL
-#define ibmebus_bus_pm_resume		NULL
-#define ibmebus_bus_pm_suspend_noirq	NULL
-#define ibmebus_bus_pm_resume_noirq	NULL
-
-#endif /* !CONFIG_SUSPEND */
-
-#ifdef CONFIG_HIBERNATE_CALLBACKS
-
-static int ibmebus_bus_pm_freeze(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->freeze)
-			ret = drv->pm->freeze(dev);
-	} else {
-		ret = ibmebus_bus_legacy_suspend(dev, PMSG_FREEZE);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_freeze_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->freeze_noirq)
-			ret = drv->pm->freeze_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_thaw(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->thaw)
-			ret = drv->pm->thaw(dev);
-	} else {
-		ret = ibmebus_bus_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_thaw_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->thaw_noirq)
-			ret = drv->pm->thaw_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_poweroff(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->poweroff)
-			ret = drv->pm->poweroff(dev);
-	} else {
-		ret = ibmebus_bus_legacy_suspend(dev, PMSG_HIBERNATE);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_poweroff_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->poweroff_noirq)
-			ret = drv->pm->poweroff_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_restore(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->restore)
-			ret = drv->pm->restore(dev);
-	} else {
-		ret = ibmebus_bus_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int ibmebus_bus_pm_restore_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->restore_noirq)
-			ret = drv->pm->restore_noirq(dev);
-	}
-
-	return ret;
-}
-
-#else /* !CONFIG_HIBERNATE_CALLBACKS */
-
-#define ibmebus_bus_pm_freeze		NULL
-#define ibmebus_bus_pm_thaw		NULL
-#define ibmebus_bus_pm_poweroff		NULL
-#define ibmebus_bus_pm_restore		NULL
-#define ibmebus_bus_pm_freeze_noirq	NULL
-#define ibmebus_bus_pm_thaw_noirq		NULL
-#define ibmebus_bus_pm_poweroff_noirq	NULL
-#define ibmebus_bus_pm_restore_noirq	NULL
-
-#endif /* !CONFIG_HIBERNATE_CALLBACKS */
-
-static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
-	.prepare = ibmebus_bus_pm_prepare,
-	.complete = ibmebus_bus_pm_complete,
-	.suspend = ibmebus_bus_pm_suspend,
-	.resume = ibmebus_bus_pm_resume,
-	.freeze = ibmebus_bus_pm_freeze,
-	.thaw = ibmebus_bus_pm_thaw,
-	.poweroff = ibmebus_bus_pm_poweroff,
-	.restore = ibmebus_bus_pm_restore,
-	.suspend_noirq = ibmebus_bus_pm_suspend_noirq,
-	.resume_noirq = ibmebus_bus_pm_resume_noirq,
-	.freeze_noirq = ibmebus_bus_pm_freeze_noirq,
-	.thaw_noirq = ibmebus_bus_pm_thaw_noirq,
-	.poweroff_noirq = ibmebus_bus_pm_poweroff_noirq,
-	.restore_noirq = ibmebus_bus_pm_restore_noirq,
-};
-
-#define IBMEBUS_BUS_PM_OPS_PTR	(&ibmebus_bus_dev_pm_ops)
-
-#else /* !CONFIG_PM_SLEEP */
-
-#define IBMEBUS_BUS_PM_OPS_PTR	NULL
-
-#endif /* !CONFIG_PM_SLEEP */
-
-struct bus_type ibmebus_bus_type = {
-	.name      = "ibmebus",
-	.uevent    = of_device_uevent_modalias,
-	.bus_groups = ibmbus_bus_groups,
-	.match     = ibmebus_bus_bus_match,
-	.probe     = ibmebus_bus_device_probe,
-	.remove    = ibmebus_bus_device_remove,
-	.shutdown  = ibmebus_bus_device_shutdown,
-	.dev_attrs = ibmebus_bus_device_attrs,
-	.pm        = IBMEBUS_BUS_PM_OPS_PTR,
-};
-EXPORT_SYMBOL(ibmebus_bus_type);
-
-static int __init ibmebus_bus_init(void)
-{
-	int err;
-
-	printk(KERN_INFO "IBM eBus Device Driver\n");
-
-	err = bus_register(&ibmebus_bus_type);
-	if (err) {
-		printk(KERN_ERR "%s: failed to register IBM eBus.\n",
-		       __func__);
-		return err;
-	}
-
-	err = device_register(&ibmebus_bus_device);
-	if (err) {
-		printk(KERN_WARNING "%s: device_register returned %i\n",
-		       __func__, err);
-		bus_unregister(&ibmebus_bus_type);
-
-		return err;
-	}
-
-	err = ibmebus_create_devices(ibmebus_matches);
-	if (err) {
-		device_unregister(&ibmebus_bus_device);
-		bus_unregister(&ibmebus_bus_type);
-		return err;
-	}
-
-	return 0;
-}
-postcore_initcall(ibmebus_bus_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/ima_kexec.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ima_kexec.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/ima_kexec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ima_kexec.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * Authors:
+ * Thiago Jung Bauermann <bauerman@linux.vnet.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.
+ */
+
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/of.h>
+#include <linux/memblock.h>
+#include <linux/libfdt.h>
+
+static int get_addr_size_cells(int *addr_cells, int *size_cells)
+{
+	struct device_node *root;
+
+	root = of_find_node_by_path("/");
+	if (!root)
+		return -EINVAL;
+
+	*addr_cells = of_n_addr_cells(root);
+	*size_cells = of_n_size_cells(root);
+
+	of_node_put(root);
+
+	return 0;
+}
+
+static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
+			       size_t *size)
+{
+	int ret, addr_cells, size_cells;
+
+	ret = get_addr_size_cells(&addr_cells, &size_cells);
+	if (ret)
+		return ret;
+
+	if (len < 4 * (addr_cells + size_cells))
+		return -ENOENT;
+
+	*addr = of_read_number(prop, addr_cells);
+	*size = of_read_number(prop + 4 * addr_cells, size_cells);
+
+	return 0;
+}
+
+/**
+ * ima_get_kexec_buffer - get IMA buffer from the previous kernel
+ * @addr:	On successful return, set to point to the buffer contents.
+ * @size:	On successful return, set to the buffer size.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int ima_get_kexec_buffer(void **addr, size_t *size)
+{
+	int ret, len;
+	unsigned long tmp_addr;
+	size_t tmp_size;
+	const void *prop;
+
+	prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
+	if (!prop)
+		return -ENOENT;
+
+	ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size);
+	if (ret)
+		return ret;
+
+	*addr = __va(tmp_addr);
+	*size = tmp_size;
+
+	return 0;
+}
+
+/**
+ * ima_free_kexec_buffer - free memory used by the IMA buffer
+ */
+int ima_free_kexec_buffer(void)
+{
+	int ret;
+	unsigned long addr;
+	size_t size;
+	struct property *prop;
+
+	prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
+	if (!prop)
+		return -ENOENT;
+
+	ret = do_get_kexec_buffer(prop->value, prop->length, &addr, &size);
+	if (ret)
+		return ret;
+
+	ret = of_remove_property(of_chosen, prop);
+	if (ret)
+		return ret;
+
+	return memblock_free(addr, size);
+
+}
+
+/**
+ * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
+ *
+ * The IMA measurement buffer is of no use to a subsequent kernel, so we always
+ * remove it from the device tree.
+ */
+void remove_ima_buffer(void *fdt, int chosen_node)
+{
+	int ret, len;
+	unsigned long addr;
+	size_t size;
+	const void *prop;
+
+	prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
+	if (!prop)
+		return;
+
+	ret = do_get_kexec_buffer(prop, len, &addr, &size);
+	fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
+	if (ret)
+		return;
+
+	ret = delete_fdt_mem_rsv(fdt, addr, size);
+	if (!ret)
+		pr_debug("Removed old IMA buffer reservation.\n");
+}
+
+#ifdef CONFIG_IMA_KEXEC
+/**
+ * arch_ima_add_kexec_buffer - do arch-specific steps to add the IMA buffer
+ *
+ * Architectures should use this function to pass on the IMA buffer
+ * information to the next kernel.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+			      size_t size)
+{
+	image->arch.ima_buffer_addr = load_addr;
+	image->arch.ima_buffer_size = size;
+
+	return 0;
+}
+
+static int write_number(void *p, u64 value, int cells)
+{
+	if (cells == 1) {
+		u32 tmp;
+
+		if (value > U32_MAX)
+			return -EINVAL;
+
+		tmp = cpu_to_be32(value);
+		memcpy(p, &tmp, sizeof(tmp));
+	} else if (cells == 2) {
+		u64 tmp;
+
+		tmp = cpu_to_be64(value);
+		memcpy(p, &tmp, sizeof(tmp));
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * setup_ima_buffer - add IMA buffer information to the fdt
+ * @image:		kexec image being loaded.
+ * @fdt:		Flattened device tree for the next kernel.
+ * @chosen_node:	Offset to the chosen node.
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node)
+{
+	int ret, addr_cells, size_cells, entry_size;
+	u8 value[16];
+
+	remove_ima_buffer(fdt, chosen_node);
+	if (!image->arch.ima_buffer_size)
+		return 0;
+
+	ret = get_addr_size_cells(&addr_cells, &size_cells);
+	if (ret)
+		return ret;
+
+	entry_size = 4 * (addr_cells + size_cells);
+
+	if (entry_size > sizeof(value))
+		return -EINVAL;
+
+	ret = write_number(value, image->arch.ima_buffer_addr, addr_cells);
+	if (ret)
+		return ret;
+
+	ret = write_number(value + 4 * addr_cells, image->arch.ima_buffer_size,
+			   size_cells);
+	if (ret)
+		return ret;
+
+	ret = fdt_setprop(fdt, chosen_node, "linux,ima-kexec-buffer", value,
+			  entry_size);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = fdt_add_mem_rsv(fdt, image->arch.ima_buffer_addr,
+			      image->arch.ima_buffer_size);
+	if (ret)
+		return -EINVAL;
+
+	pr_debug("IMA buffer at 0x%llx, size = 0x%zx\n",
+		 image->arch.ima_buffer_addr, image->arch.ima_buffer_size);
+
+	return 0;
+}
+#endif /* CONFIG_IMA_KEXEC */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/irq.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -55,7 +55,7 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/kexec_elf_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/kexec_elf_64.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/kexec_elf_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/kexec_elf_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,663 @@
+/*
+ * Load ELF vmlinux file for the kexec_file_load syscall.
+ *
+ * Copyright (C) 2004  Adam Litke (agl@us.ibm.com)
+ * Copyright (C) 2004  IBM Corp.
+ * Copyright (C) 2005  R Sharada (sharada@in.ibm.com)
+ * Copyright (C) 2006  Mohan Kumar M (mohan@in.ibm.com)
+ * Copyright (C) 2016  IBM Corporation
+ *
+ * Based on kexec-tools' kexec-elf-exec.c and kexec-elf-ppc64.c.
+ * Heavily modified for the kernel by
+ * Thiago Jung Bauermann <bauerman@linux.vnet.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 (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.
+ */
+
+#define pr_fmt(fmt)	"kexec_elf: " fmt
+
+#include <linux/elf.h>
+#include <linux/kexec.h>
+#include <linux/libfdt.h>
+#include <linux/module.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define PURGATORY_STACK_SIZE	(16 * 1024)
+
+#define elf_addr_to_cpu	elf64_to_cpu
+
+#ifndef Elf_Rel
+#define Elf_Rel		Elf64_Rel
+#endif /* Elf_Rel */
+
+struct elf_info {
+	/*
+	 * Where the ELF binary contents are kept.
+	 * Memory managed by the user of the struct.
+	 */
+	const char *buffer;
+
+	const struct elfhdr *ehdr;
+	const struct elf_phdr *proghdrs;
+	struct elf_shdr *sechdrs;
+};
+
+static inline bool elf_is_elf_file(const struct elfhdr *ehdr)
+{
+       return memcmp(ehdr->e_ident, ELFMAG, SELFMAG) == 0;
+}
+
+static uint64_t elf64_to_cpu(const struct elfhdr *ehdr, uint64_t value)
+{
+	if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+		value = le64_to_cpu(value);
+	else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+		value = be64_to_cpu(value);
+
+	return value;
+}
+
+static uint16_t elf16_to_cpu(const struct elfhdr *ehdr, uint16_t value)
+{
+	if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+		value = le16_to_cpu(value);
+	else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+		value = be16_to_cpu(value);
+
+	return value;
+}
+
+static uint32_t elf32_to_cpu(const struct elfhdr *ehdr, uint32_t value)
+{
+	if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+		value = le32_to_cpu(value);
+	else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+		value = be32_to_cpu(value);
+
+	return value;
+}
+
+/**
+ * elf_is_ehdr_sane - check that it is safe to use the ELF header
+ * @buf_len:	size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_ehdr_sane(const struct elfhdr *ehdr, size_t buf_len)
+{
+	if (ehdr->e_phnum > 0 && ehdr->e_phentsize != sizeof(struct elf_phdr)) {
+		pr_debug("Bad program header size.\n");
+		return false;
+	} else if (ehdr->e_shnum > 0 &&
+		   ehdr->e_shentsize != sizeof(struct elf_shdr)) {
+		pr_debug("Bad section header size.\n");
+		return false;
+	} else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
+		   ehdr->e_version != EV_CURRENT) {
+		pr_debug("Unknown ELF version.\n");
+		return false;
+	}
+
+	if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
+		size_t phdr_size;
+
+		/*
+		 * e_phnum is at most 65535 so calculating the size of the
+		 * program header cannot overflow.
+		 */
+		phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
+
+		/* Sanity check the program header table location. */
+		if (ehdr->e_phoff + phdr_size < ehdr->e_phoff) {
+			pr_debug("Program headers at invalid location.\n");
+			return false;
+		} else if (ehdr->e_phoff + phdr_size > buf_len) {
+			pr_debug("Program headers truncated.\n");
+			return false;
+		}
+	}
+
+	if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
+		size_t shdr_size;
+
+		/*
+		 * e_shnum is at most 65536 so calculating
+		 * the size of the section header cannot overflow.
+		 */
+		shdr_size = sizeof(struct elf_shdr) * ehdr->e_shnum;
+
+		/* Sanity check the section header table location. */
+		if (ehdr->e_shoff + shdr_size < ehdr->e_shoff) {
+			pr_debug("Section headers at invalid location.\n");
+			return false;
+		} else if (ehdr->e_shoff + shdr_size > buf_len) {
+			pr_debug("Section headers truncated.\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
+{
+	struct elfhdr *buf_ehdr;
+
+	if (len < sizeof(*buf_ehdr)) {
+		pr_debug("Buffer is too small to hold ELF header.\n");
+		return -ENOEXEC;
+	}
+
+	memset(ehdr, 0, sizeof(*ehdr));
+	memcpy(ehdr->e_ident, buf, sizeof(ehdr->e_ident));
+	if (!elf_is_elf_file(ehdr)) {
+		pr_debug("No ELF header magic.\n");
+		return -ENOEXEC;
+	}
+
+	if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
+		pr_debug("Not a supported ELF class.\n");
+		return -ENOEXEC;
+	} else  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
+		ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
+		pr_debug("Not a supported ELF data format.\n");
+		return -ENOEXEC;
+	}
+
+	buf_ehdr = (struct elfhdr *) buf;
+	if (elf16_to_cpu(ehdr, buf_ehdr->e_ehsize) != sizeof(*buf_ehdr)) {
+		pr_debug("Bad ELF header size.\n");
+		return -ENOEXEC;
+	}
+
+	ehdr->e_type      = elf16_to_cpu(ehdr, buf_ehdr->e_type);
+	ehdr->e_machine   = elf16_to_cpu(ehdr, buf_ehdr->e_machine);
+	ehdr->e_version   = elf32_to_cpu(ehdr, buf_ehdr->e_version);
+	ehdr->e_entry     = elf_addr_to_cpu(ehdr, buf_ehdr->e_entry);
+	ehdr->e_phoff     = elf_addr_to_cpu(ehdr, buf_ehdr->e_phoff);
+	ehdr->e_shoff     = elf_addr_to_cpu(ehdr, buf_ehdr->e_shoff);
+	ehdr->e_flags     = elf32_to_cpu(ehdr, buf_ehdr->e_flags);
+	ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize);
+	ehdr->e_phnum     = elf16_to_cpu(ehdr, buf_ehdr->e_phnum);
+	ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize);
+	ehdr->e_shnum     = elf16_to_cpu(ehdr, buf_ehdr->e_shnum);
+	ehdr->e_shstrndx  = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx);
+
+	return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_is_phdr_sane - check that it is safe to use the program header
+ * @buf_len:	size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_phdr_sane(const struct elf_phdr *phdr, size_t buf_len)
+{
+
+	if (phdr->p_offset + phdr->p_filesz < phdr->p_offset) {
+		pr_debug("ELF segment location wraps around.\n");
+		return false;
+	} else if (phdr->p_offset + phdr->p_filesz > buf_len) {
+		pr_debug("ELF segment not in file.\n");
+		return false;
+	} else if (phdr->p_paddr + phdr->p_memsz < phdr->p_paddr) {
+		pr_debug("ELF segment address wraps around.\n");
+		return false;
+	}
+
+	return true;
+}
+
+static int elf_read_phdr(const char *buf, size_t len, struct elf_info *elf_info,
+			 int idx)
+{
+	/* Override the const in proghdrs, we are the ones doing the loading. */
+	struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx];
+	const char *pbuf;
+	struct elf_phdr *buf_phdr;
+
+	pbuf = buf + elf_info->ehdr->e_phoff + (idx * sizeof(*buf_phdr));
+	buf_phdr = (struct elf_phdr *) pbuf;
+
+	phdr->p_type   = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type);
+	phdr->p_offset = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_offset);
+	phdr->p_paddr  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_paddr);
+	phdr->p_vaddr  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_vaddr);
+	phdr->p_flags  = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags);
+
+	/*
+	 * The following fields have a type equivalent to Elf_Addr
+	 * both in 32 bit and 64 bit ELF.
+	 */
+	phdr->p_filesz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_filesz);
+	phdr->p_memsz  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_memsz);
+	phdr->p_align  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_align);
+
+	return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_read_phdrs - read the program headers from the buffer
+ *
+ * This function assumes that the program header table was checked for sanity.
+ * Use elf_is_ehdr_sane() if it wasn't.
+ */
+static int elf_read_phdrs(const char *buf, size_t len,
+			  struct elf_info *elf_info)
+{
+	size_t phdr_size, i;
+	const struct elfhdr *ehdr = elf_info->ehdr;
+
+	/*
+	 * e_phnum is at most 65535 so calculating the size of the
+	 * program header cannot overflow.
+	 */
+	phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
+
+	elf_info->proghdrs = kzalloc(phdr_size, GFP_KERNEL);
+	if (!elf_info->proghdrs)
+		return -ENOMEM;
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		int ret;
+
+		ret = elf_read_phdr(buf, len, elf_info, i);
+		if (ret) {
+			kfree(elf_info->proghdrs);
+			elf_info->proghdrs = NULL;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * elf_is_shdr_sane - check that it is safe to use the section header
+ * @buf_len:	size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_shdr_sane(const struct elf_shdr *shdr, size_t buf_len)
+{
+	bool size_ok;
+
+	/* SHT_NULL headers have undefined values, so we can't check them. */
+	if (shdr->sh_type == SHT_NULL)
+		return true;
+
+	/* Now verify sh_entsize */
+	switch (shdr->sh_type) {
+	case SHT_SYMTAB:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Sym);
+		break;
+	case SHT_RELA:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Rela);
+		break;
+	case SHT_DYNAMIC:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Dyn);
+		break;
+	case SHT_REL:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Rel);
+		break;
+	case SHT_NOTE:
+	case SHT_PROGBITS:
+	case SHT_HASH:
+	case SHT_NOBITS:
+	default:
+		/*
+		 * This is a section whose entsize requirements
+		 * I don't care about.  If I don't know about
+		 * the section I can't care about it's entsize
+		 * requirements.
+		 */
+		size_ok = true;
+		break;
+	}
+
+	if (!size_ok) {
+		pr_debug("ELF section with wrong entry size.\n");
+		return false;
+	} else if (shdr->sh_addr + shdr->sh_size < shdr->sh_addr) {
+		pr_debug("ELF section address wraps around.\n");
+		return false;
+	}
+
+	if (shdr->sh_type != SHT_NOBITS) {
+		if (shdr->sh_offset + shdr->sh_size < shdr->sh_offset) {
+			pr_debug("ELF section location wraps around.\n");
+			return false;
+		} else if (shdr->sh_offset + shdr->sh_size > buf_len) {
+			pr_debug("ELF section not in file.\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static int elf_read_shdr(const char *buf, size_t len, struct elf_info *elf_info,
+			 int idx)
+{
+	struct elf_shdr *shdr = &elf_info->sechdrs[idx];
+	const struct elfhdr *ehdr = elf_info->ehdr;
+	const char *sbuf;
+	struct elf_shdr *buf_shdr;
+
+	sbuf = buf + ehdr->e_shoff + idx * sizeof(*buf_shdr);
+	buf_shdr = (struct elf_shdr *) sbuf;
+
+	shdr->sh_name      = elf32_to_cpu(ehdr, buf_shdr->sh_name);
+	shdr->sh_type      = elf32_to_cpu(ehdr, buf_shdr->sh_type);
+	shdr->sh_addr      = elf_addr_to_cpu(ehdr, buf_shdr->sh_addr);
+	shdr->sh_offset    = elf_addr_to_cpu(ehdr, buf_shdr->sh_offset);
+	shdr->sh_link      = elf32_to_cpu(ehdr, buf_shdr->sh_link);
+	shdr->sh_info      = elf32_to_cpu(ehdr, buf_shdr->sh_info);
+
+	/*
+	 * The following fields have a type equivalent to Elf_Addr
+	 * both in 32 bit and 64 bit ELF.
+	 */
+	shdr->sh_flags     = elf_addr_to_cpu(ehdr, buf_shdr->sh_flags);
+	shdr->sh_size      = elf_addr_to_cpu(ehdr, buf_shdr->sh_size);
+	shdr->sh_addralign = elf_addr_to_cpu(ehdr, buf_shdr->sh_addralign);
+	shdr->sh_entsize   = elf_addr_to_cpu(ehdr, buf_shdr->sh_entsize);
+
+	return elf_is_shdr_sane(shdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_read_shdrs - read the section headers from the buffer
+ *
+ * This function assumes that the section header table was checked for sanity.
+ * Use elf_is_ehdr_sane() if it wasn't.
+ */
+static int elf_read_shdrs(const char *buf, size_t len,
+			  struct elf_info *elf_info)
+{
+	size_t shdr_size, i;
+
+	/*
+	 * e_shnum is at most 65536 so calculating
+	 * the size of the section header cannot overflow.
+	 */
+	shdr_size = sizeof(struct elf_shdr) * elf_info->ehdr->e_shnum;
+
+	elf_info->sechdrs = kzalloc(shdr_size, GFP_KERNEL);
+	if (!elf_info->sechdrs)
+		return -ENOMEM;
+
+	for (i = 0; i < elf_info->ehdr->e_shnum; i++) {
+		int ret;
+
+		ret = elf_read_shdr(buf, len, elf_info, i);
+		if (ret) {
+			kfree(elf_info->sechdrs);
+			elf_info->sechdrs = NULL;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * elf_read_from_buffer - read ELF file and sets up ELF header and ELF info
+ * @buf:	Buffer to read ELF file from.
+ * @len:	Size of @buf.
+ * @ehdr:	Pointer to existing struct which will be populated.
+ * @elf_info:	Pointer to existing struct which will be populated.
+ *
+ * This function allows reading ELF files with different byte order than
+ * the kernel, byte-swapping the fields as needed.
+ *
+ * Return:
+ * On success returns 0, and the caller should call elf_free_info(elf_info) to
+ * free the memory allocated for the section and program headers.
+ */
+int elf_read_from_buffer(const char *buf, size_t len, struct elfhdr *ehdr,
+			 struct elf_info *elf_info)
+{
+	int ret;
+
+	ret = elf_read_ehdr(buf, len, ehdr);
+	if (ret)
+		return ret;
+
+	elf_info->buffer = buf;
+	elf_info->ehdr = ehdr;
+	if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
+		ret = elf_read_phdrs(buf, len, elf_info);
+		if (ret)
+			return ret;
+	}
+	if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
+		ret = elf_read_shdrs(buf, len, elf_info);
+		if (ret) {
+			kfree(elf_info->proghdrs);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * elf_free_info - free memory allocated by elf_read_from_buffer
+ */
+void elf_free_info(struct elf_info *elf_info)
+{
+	kfree(elf_info->proghdrs);
+	kfree(elf_info->sechdrs);
+	memset(elf_info, 0, sizeof(*elf_info));
+}
+/**
+ * build_elf_exec_info - read ELF executable and check that we can use it
+ */
+static int build_elf_exec_info(const char *buf, size_t len, struct elfhdr *ehdr,
+			       struct elf_info *elf_info)
+{
+	int i;
+	int ret;
+
+	ret = elf_read_from_buffer(buf, len, ehdr, elf_info);
+	if (ret)
+		return ret;
+
+	/* Big endian vmlinux has type ET_DYN. */
+	if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
+		pr_err("Not an ELF executable.\n");
+		goto error;
+	} else if (!elf_info->proghdrs) {
+		pr_err("No ELF program header.\n");
+		goto error;
+	}
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		/*
+		 * Kexec does not support loading interpreters.
+		 * In addition this check keeps us from attempting
+		 * to kexec ordinay executables.
+		 */
+		if (elf_info->proghdrs[i].p_type == PT_INTERP) {
+			pr_err("Requires an ELF interpreter.\n");
+			goto error;
+		}
+	}
+
+	return 0;
+error:
+	elf_free_info(elf_info);
+	return -ENOEXEC;
+}
+
+static int elf64_probe(const char *buf, unsigned long len)
+{
+	struct elfhdr ehdr;
+	struct elf_info elf_info;
+	int ret;
+
+	ret = build_elf_exec_info(buf, len, &ehdr, &elf_info);
+	if (ret)
+		return ret;
+
+	elf_free_info(&elf_info);
+
+	return elf_check_arch(&ehdr) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_exec_load - load ELF executable image
+ * @lowest_load_addr:	On return, will be the address where the first PT_LOAD
+ *			section will be loaded in memory.
+ *
+ * Return:
+ * 0 on success, negative value on failure.
+ */
+static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr,
+			 struct elf_info *elf_info,
+			 unsigned long *lowest_load_addr)
+{
+	unsigned long base = 0, lowest_addr = UINT_MAX;
+	int ret;
+	size_t i;
+	struct kexec_buf kbuf = { .image = image, .buf_max = ppc64_rma_size,
+				  .top_down = false };
+
+	/* Read in the PT_LOAD segments. */
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		unsigned long load_addr;
+		size_t size;
+		const struct elf_phdr *phdr;
+
+		phdr = &elf_info->proghdrs[i];
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		size = phdr->p_filesz;
+		if (size > phdr->p_memsz)
+			size = phdr->p_memsz;
+
+		kbuf.buffer = (void *) elf_info->buffer + phdr->p_offset;
+		kbuf.bufsz = size;
+		kbuf.memsz = phdr->p_memsz;
+		kbuf.buf_align = phdr->p_align;
+		kbuf.buf_min = phdr->p_paddr + base;
+		ret = kexec_add_buffer(&kbuf);
+		if (ret)
+			goto out;
+		load_addr = kbuf.mem;
+
+		if (load_addr < lowest_addr)
+			lowest_addr = load_addr;
+	}
+
+	/* Update entry point to reflect new load address. */
+	ehdr->e_entry += base;
+
+	*lowest_load_addr = lowest_addr;
+	ret = 0;
+ out:
+	return ret;
+}
+
+static void *elf64_load(struct kimage *image, char *kernel_buf,
+			unsigned long kernel_len, char *initrd,
+			unsigned long initrd_len, char *cmdline,
+			unsigned long cmdline_len)
+{
+	int ret;
+	unsigned int fdt_size;
+	unsigned long kernel_load_addr, purgatory_load_addr;
+	unsigned long initrd_load_addr = 0, fdt_load_addr;
+	void *fdt;
+	const void *slave_code;
+	struct elfhdr ehdr;
+	struct elf_info elf_info;
+	struct kexec_buf kbuf = { .image = image, .buf_min = 0,
+				  .buf_max = ppc64_rma_size };
+
+	ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info);
+	if (ret)
+		goto out;
+
+	ret = elf_exec_load(image, &ehdr, &elf_info, &kernel_load_addr);
+	if (ret)
+		goto out;
+
+	pr_debug("Loaded the kernel at 0x%lx\n", kernel_load_addr);
+
+	ret = kexec_load_purgatory(image, 0, ppc64_rma_size, true,
+				   &purgatory_load_addr);
+	if (ret) {
+		pr_err("Loading purgatory failed.\n");
+		goto out;
+	}
+
+	pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+
+	if (initrd != NULL) {
+		kbuf.buffer = initrd;
+		kbuf.bufsz = kbuf.memsz = initrd_len;
+		kbuf.buf_align = PAGE_SIZE;
+		kbuf.top_down = false;
+		ret = kexec_add_buffer(&kbuf);
+		if (ret)
+			goto out;
+		initrd_load_addr = kbuf.mem;
+
+		pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr);
+	}
+
+	fdt_size = fdt_totalsize(initial_boot_params) * 2;
+	fdt = kmalloc(fdt_size, GFP_KERNEL);
+	if (!fdt) {
+		pr_err("Not enough memory for the device tree.\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+	ret = fdt_open_into(initial_boot_params, fdt, fdt_size);
+	if (ret < 0) {
+		pr_err("Error setting up the new device tree.\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len, cmdline);
+	if (ret)
+		goto out;
+
+	fdt_pack(fdt);
+
+	kbuf.buffer = fdt;
+	kbuf.bufsz = kbuf.memsz = fdt_size;
+	kbuf.buf_align = PAGE_SIZE;
+	kbuf.top_down = true;
+	ret = kexec_add_buffer(&kbuf);
+	if (ret)
+		goto out;
+	fdt_load_addr = kbuf.mem;
+
+	pr_debug("Loaded device tree at 0x%lx\n", fdt_load_addr);
+
+	slave_code = elf_info.buffer + elf_info.proghdrs[0].p_offset;
+	ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
+			      fdt_load_addr);
+	if (ret)
+		pr_err("Error setting up the purgatory.\n");
+
+out:
+	elf_free_info(&elf_info);
+
+	/* Make kimage_file_post_load_cleanup free the fdt buffer for us. */
+	return ret ? ERR_PTR(ret) : fdt;
+}
+
+struct kexec_file_ops kexec_elf64_ops = {
+	.probe = elf64_probe,
+	.load = elf64_load,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/kprobes.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/kprobes.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/kprobes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/kprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <asm/code-patching.h>
 #include <asm/cacheflush.h>
 #include <asm/sstep.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
@@ -140,13 +140,16 @@ void __kprobes arch_prepare_kretprobe(st
 	regs->link = (unsigned long)kretprobe_trampoline;
 }
 
-static int __kprobes kprobe_handler(struct pt_regs *regs)
+int __kprobes kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p;
 	int ret = 0;
 	unsigned int *addr = (unsigned int *)regs->nip;
 	struct kprobe_ctlblk *kcb;
 
+	if (user_mode(regs))
+		return 0;
+
 	/*
 	 * We don't want to be preempted for the entire
 	 * duration of kprobe processing
@@ -359,12 +362,12 @@ static int __kprobes trampoline_probe_ha
  * single-stepped a copy of the instruction.  The address of this
  * copy is p->ainsn.insn.
  */
-static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+int __kprobes kprobe_post_handler(struct pt_regs *regs)
 {
 	struct kprobe *cur = kprobe_running();
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-	if (!cur)
+	if (!cur || user_mode(regs))
 		return 0;
 
 	/* make sure we got here for instruction we have a kprobe on */
@@ -449,7 +452,7 @@ int __kprobes kprobe_fault_handler(struc
 		 * zero, try to fix up.
 		 */
 		if ((entry = search_exception_tables(regs->nip)) != NULL) {
-			regs->nip = entry->fixup;
+			regs->nip = extable_fixup(entry);
 			return 1;
 		}
 
@@ -470,25 +473,7 @@ int __kprobes kprobe_fault_handler(struc
 int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
 				       unsigned long val, void *data)
 {
-	struct die_args *args = (struct die_args *)data;
-	int ret = NOTIFY_DONE;
-
-	if (args->regs && user_mode(args->regs))
-		return ret;
-
-	switch (val) {
-	case DIE_BPT:
-		if (kprobe_handler(args->regs))
-			ret = NOTIFY_STOP;
-		break;
-	case DIE_SSTEP:
-		if (post_kprobe_handler(args->regs))
-			ret = NOTIFY_STOP;
-		break;
-	default:
-		break;
-	}
-	return ret;
+	return NOTIFY_DONE;
 }
 
 unsigned long arch_deref_entry_point(void *entry)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/machine_kexec_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/machine_kexec_64.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/machine_kexec_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/machine_kexec_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -310,7 +310,7 @@ void default_machine_kexec(struct kimage
 	if (!kdump_in_progress())
 		kexec_prepare_cpus();
 
-	pr_debug("kexec: Starting switchover sequence.\n");
+	printk("kexec: Starting switchover sequence.\n");
 
 	/* switch to a staticly allocated stack.  Based on irq stack code.
 	 * We setup preempt_count to avoid using VMX in memcpy.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/machine_kexec_file_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/machine_kexec_file_64.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/machine_kexec_file_64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/machine_kexec_file_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,347 @@
+/*
+ * ppc64 code to implement the kexec_file_load syscall
+ *
+ * Copyright (C) 2004  Adam Litke (agl@us.ibm.com)
+ * Copyright (C) 2004  IBM Corp.
+ * Copyright (C) 2004,2005  Milton D Miller II, IBM Corporation
+ * Copyright (C) 2005  R Sharada (sharada@in.ibm.com)
+ * Copyright (C) 2006  Mohan Kumar M (mohan@in.ibm.com)
+ * Copyright (C) 2016  IBM Corporation
+ *
+ * Based on kexec-tools' kexec-elf-ppc64.c, fs2dt.c.
+ * Heavily modified for the kernel by
+ * Thiago Jung Bauermann <bauerman@linux.vnet.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 (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/memblock.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
+#include <asm/ima.h>
+
+#define SLAVE_CODE_SIZE		256
+
+static struct kexec_file_ops *kexec_file_loaders[] = {
+	&kexec_elf64_ops,
+};
+
+int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
+				  unsigned long buf_len)
+{
+	int i, ret = -ENOEXEC;
+	struct kexec_file_ops *fops;
+
+	/* We don't support crash kernels yet. */
+	if (image->type == KEXEC_TYPE_CRASH)
+		return -ENOTSUPP;
+
+	for (i = 0; i < ARRAY_SIZE(kexec_file_loaders); i++) {
+		fops = kexec_file_loaders[i];
+		if (!fops || !fops->probe)
+			continue;
+
+		ret = fops->probe(buf, buf_len);
+		if (!ret) {
+			image->fops = fops;
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+void *arch_kexec_kernel_image_load(struct kimage *image)
+{
+	if (!image->fops || !image->fops->load)
+		return ERR_PTR(-ENOEXEC);
+
+	return image->fops->load(image, image->kernel_buf,
+				 image->kernel_buf_len, image->initrd_buf,
+				 image->initrd_buf_len, image->cmdline_buf,
+				 image->cmdline_buf_len);
+}
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image)
+{
+	if (!image->fops || !image->fops->cleanup)
+		return 0;
+
+	return image->fops->cleanup(image->image_loader_data);
+}
+
+/**
+ * arch_kexec_walk_mem - call func(data) for each unreserved memory block
+ * @kbuf:	Context info for the search. Also passed to @func.
+ * @func:	Function to call for each memory block.
+ *
+ * This function is used by kexec_add_buffer and kexec_locate_mem_hole
+ * to find unreserved memory to load kexec segments into.
+ *
+ * Return: The memory walk will stop when func returns a non-zero value
+ * and that value will be returned. If all free regions are visited without
+ * func returning non-zero, then zero will be returned.
+ */
+int arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *))
+{
+	int ret = 0;
+	u64 i;
+	phys_addr_t mstart, mend;
+
+	if (kbuf->top_down) {
+		for_each_free_mem_range_reverse(i, NUMA_NO_NODE, 0,
+						&mstart, &mend, NULL) {
+			/*
+			 * In memblock, end points to the first byte after the
+			 * range while in kexec, end points to the last byte
+			 * in the range.
+			 */
+			ret = func(mstart, mend - 1, kbuf);
+			if (ret)
+				break;
+		}
+	} else {
+		for_each_free_mem_range(i, NUMA_NO_NODE, 0, &mstart, &mend,
+					NULL) {
+			/*
+			 * In memblock, end points to the first byte after the
+			 * range while in kexec, end points to the last byte
+			 * in the range.
+			 */
+			ret = func(mstart, mend - 1, kbuf);
+			if (ret)
+				break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * setup_purgatory - initialize the purgatory's global variables
+ * @image:		kexec image.
+ * @slave_code:		Slave code for the purgatory.
+ * @fdt:		Flattened device tree for the next kernel.
+ * @kernel_load_addr:	Address where the kernel is loaded.
+ * @fdt_load_addr:	Address where the flattened device tree is loaded.
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int setup_purgatory(struct kimage *image, const void *slave_code,
+		    const void *fdt, unsigned long kernel_load_addr,
+		    unsigned long fdt_load_addr)
+{
+	unsigned int *slave_code_buf, master_entry;
+	int ret;
+
+	slave_code_buf = kmalloc(SLAVE_CODE_SIZE, GFP_KERNEL);
+	if (!slave_code_buf)
+		return -ENOMEM;
+
+	/* Get the slave code from the new kernel and put it in purgatory. */
+	ret = kexec_purgatory_get_set_symbol(image, "purgatory_start",
+					     slave_code_buf, SLAVE_CODE_SIZE,
+					     true);
+	if (ret) {
+		kfree(slave_code_buf);
+		return ret;
+	}
+
+	master_entry = slave_code_buf[0];
+	memcpy(slave_code_buf, slave_code, SLAVE_CODE_SIZE);
+	slave_code_buf[0] = master_entry;
+	ret = kexec_purgatory_get_set_symbol(image, "purgatory_start",
+					     slave_code_buf, SLAVE_CODE_SIZE,
+					     false);
+	kfree(slave_code_buf);
+
+	ret = kexec_purgatory_get_set_symbol(image, "kernel", &kernel_load_addr,
+					     sizeof(kernel_load_addr), false);
+	if (ret)
+		return ret;
+	ret = kexec_purgatory_get_set_symbol(image, "dt_offset", &fdt_load_addr,
+					     sizeof(fdt_load_addr), false);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/**
+ * delete_fdt_mem_rsv - delete memory reservation with given address and size
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
+{
+	int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
+
+	for (i = 0; i < num_rsvs; i++) {
+		uint64_t rsv_start, rsv_size;
+
+		ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
+		if (ret) {
+			pr_err("Malformed device tree.\n");
+			return -EINVAL;
+		}
+
+		if (rsv_start == start && rsv_size == size) {
+			ret = fdt_del_mem_rsv(fdt, i);
+			if (ret) {
+				pr_err("Error deleting device tree reservation.\n");
+				return -EINVAL;
+			}
+
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+/*
+ * setup_new_fdt - modify /chosen and memory reservation for the next kernel
+ * @image:		kexec image being loaded.
+ * @fdt:		Flattened device tree for the next kernel.
+ * @initrd_load_addr:	Address where the next initrd will be loaded.
+ * @initrd_len:		Size of the next initrd, or 0 if there will be none.
+ * @cmdline:		Command line for the next kernel, or NULL if there will
+ *			be none.
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int setup_new_fdt(const struct kimage *image, void *fdt,
+		  unsigned long initrd_load_addr, unsigned long initrd_len,
+		  const char *cmdline)
+{
+	int ret, chosen_node;
+	const void *prop;
+
+	/* Remove memory reservation for the current device tree. */
+	ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
+				 fdt_totalsize(initial_boot_params));
+	if (ret == 0)
+		pr_debug("Removed old device tree reservation.\n");
+	else if (ret != -ENOENT)
+		return ret;
+
+	chosen_node = fdt_path_offset(fdt, "/chosen");
+	if (chosen_node == -FDT_ERR_NOTFOUND) {
+		chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
+					      "chosen");
+		if (chosen_node < 0) {
+			pr_err("Error creating /chosen.\n");
+			return -EINVAL;
+		}
+	} else if (chosen_node < 0) {
+		pr_err("Malformed device tree: error reading /chosen.\n");
+		return -EINVAL;
+	}
+
+	/* Did we boot using an initrd? */
+	prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
+	if (prop) {
+		uint64_t tmp_start, tmp_end, tmp_size;
+
+		tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+		prop = fdt_getprop(fdt, chosen_node, "linux,initrd-end", NULL);
+		if (!prop) {
+			pr_err("Malformed device tree.\n");
+			return -EINVAL;
+		}
+		tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+		/*
+		 * kexec reserves exact initrd size, while firmware may
+		 * reserve a multiple of PAGE_SIZE, so check for both.
+		 */
+		tmp_size = tmp_end - tmp_start;
+		ret = delete_fdt_mem_rsv(fdt, tmp_start, tmp_size);
+		if (ret == -ENOENT)
+			ret = delete_fdt_mem_rsv(fdt, tmp_start,
+						 round_up(tmp_size, PAGE_SIZE));
+		if (ret == 0)
+			pr_debug("Removed old initrd reservation.\n");
+		else if (ret != -ENOENT)
+			return ret;
+
+		/* If there's no new initrd, delete the old initrd's info. */
+		if (initrd_len == 0) {
+			ret = fdt_delprop(fdt, chosen_node,
+					  "linux,initrd-start");
+			if (ret) {
+				pr_err("Error deleting linux,initrd-start.\n");
+				return -EINVAL;
+			}
+
+			ret = fdt_delprop(fdt, chosen_node, "linux,initrd-end");
+			if (ret) {
+				pr_err("Error deleting linux,initrd-end.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (initrd_len) {
+		ret = fdt_setprop_u64(fdt, chosen_node,
+				      "linux,initrd-start",
+				      initrd_load_addr);
+		if (ret < 0) {
+			pr_err("Error setting up the new device tree.\n");
+			return -EINVAL;
+		}
+
+		/* initrd-end is the first address after the initrd image. */
+		ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-end",
+				      initrd_load_addr + initrd_len);
+		if (ret < 0) {
+			pr_err("Error setting up the new device tree.\n");
+			return -EINVAL;
+		}
+
+		ret = fdt_add_mem_rsv(fdt, initrd_load_addr, initrd_len);
+		if (ret) {
+			pr_err("Error reserving initrd memory: %s\n",
+			       fdt_strerror(ret));
+			return -EINVAL;
+		}
+	}
+
+	if (cmdline != NULL) {
+		ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline);
+		if (ret < 0) {
+			pr_err("Error setting up the new device tree.\n");
+			return -EINVAL;
+		}
+	} else {
+		ret = fdt_delprop(fdt, chosen_node, "bootargs");
+		if (ret && ret != -FDT_ERR_NOTFOUND) {
+			pr_err("Error deleting bootargs.\n");
+			return -EINVAL;
+		}
+	}
+
+	ret = setup_ima_buffer(image, fdt, chosen_node);
+	if (ret) {
+		pr_err("Error setting up the new device tree.\n");
+		return ret;
+	}
+
+	ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
+	if (ret) {
+		pr_err("Error setting up the new device tree.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/Makefile linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/Makefile
--- linux-libre-4.9-gnu/arch/powerpc/kernel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -58,8 +58,6 @@ obj-$(CONFIG_PPC_RTAS)		+= rtas.o rtas-r
 obj-$(CONFIG_PPC_RTAS_DAEMON)	+= rtasd.o
 obj-$(CONFIG_RTAS_FLASH)	+= rtas_flash.o
 obj-$(CONFIG_RTAS_PROC)		+= rtas-proc.o
-obj-$(CONFIG_IBMVIO)		+= vio.o
-obj-$(CONFIG_IBMEBUS)           += ibmebus.o
 obj-$(CONFIG_EEH)              += eeh.o eeh_pe.o eeh_dev.o eeh_cache.o \
 				  eeh_driver.o eeh_event.o eeh_sysfs.o
 obj-$(CONFIG_GENERIC_TBSYNC)	+= smp-tbsync.o
@@ -107,8 +105,13 @@ pci64-$(CONFIG_PPC64)		+= pci_dn.o pci-h
 obj-$(CONFIG_PCI)		+= pci_$(BITS).o $(pci64-y) \
 				   pci-common.o pci_of_scan.o
 obj-$(CONFIG_PCI_MSI)		+= msi.o
-obj-$(CONFIG_KEXEC)		+= machine_kexec.o crash.o \
+obj-$(CONFIG_KEXEC_CORE)	+= machine_kexec.o crash.o \
 				   machine_kexec_$(BITS).o
+obj-$(CONFIG_KEXEC_FILE)	+= machine_kexec_file_$(BITS).o kexec_elf_$(BITS).o
+ifeq ($(CONFIG_HAVE_IMA_KEXEC)$(CONFIG_IMA),yy)
+obj-y				+= ima_kexec.o
+endif
+
 obj-$(CONFIG_AUDIT)		+= audit.o
 obj64-$(CONFIG_AUDIT)		+= compat_audit.o
 
@@ -128,7 +131,7 @@ obj64-$(CONFIG_PPC_TRANSACTIONAL_MEM)	+=
 obj-$(CONFIG_PPC64)		+= $(obj64-y)
 obj-$(CONFIG_PPC32)		+= $(obj32-y)
 
-ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
+ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC_CORE),)
 obj-y				+= ppc_save_regs.o
 endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/mce.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/mce.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/mce.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/mce.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,6 @@ void save_mce_event(struct pt_regs *regs
 		    struct mce_error_info *mce_err,
 		    uint64_t nip, uint64_t addr)
 {
-	uint64_t srr1;
 	int index = __this_cpu_inc_return(mce_nest_count) - 1;
 	struct machine_check_event *mce = this_cpu_ptr(&mce_event[index]);
 
@@ -99,8 +98,6 @@ void save_mce_event(struct pt_regs *regs
 		mce->disposition = MCE_DISPOSITION_NOT_RECOVERED;
 	mce->severity = MCE_SEV_ERROR_SYNC;
 
-	srr1 = regs->msr;
-
 	/*
 	 * Populate the mce error_type and type-specific error_type.
 	 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/misc_32.S linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/misc_32.S
--- linux-libre-4.9-gnu/arch/powerpc/kernel/misc_32.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/misc_32.S	2017-02-12 16:03:20.000000000 -0500
@@ -296,7 +296,7 @@ _GLOBAL(flush_instruction_cache)
 	lis	r3, KERNELBASE@h
 	iccci	0,r3
 #endif
-#elif CONFIG_FSL_BOOKE
+#elif defined(CONFIG_FSL_BOOKE)
 BEGIN_FTR_SECTION
 	mfspr   r3,SPRN_L1CSR0
 	ori     r3,r3,L1CSR0_CFI|L1CSR0_CLFC
@@ -614,7 +614,7 @@ _GLOBAL(start_secondary_resume)
 _GLOBAL(__main)
 	blr
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	/*
 	 * Must be relocatable PIC code callable as a C function.
 	 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/misc_64.S linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/misc_64.S
--- linux-libre-4.9-gnu/arch/powerpc/kernel/misc_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/misc_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -478,7 +478,7 @@ _GLOBAL(kexec_wait)
 	addi	r5,r5,kexec_flag-1b
 
 99:	HMT_LOW
-#ifdef CONFIG_KEXEC		/* use no memory without kexec */
+#ifdef CONFIG_KEXEC_CORE	/* use no memory without kexec */
 	lwz	r4,0(r5)
 	cmpwi	0,r4,0
 	beq	99b
@@ -503,7 +503,7 @@ kexec_flag:
 	.long	0
 
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 #ifdef CONFIG_PPC_BOOK3E
 /*
  * BOOK3E has no real MMU mode, so we have to setup the initial TLB
@@ -716,4 +716,4 @@ _GLOBAL(kexec_sequence)
 	mtlr	4
 	li	r5,0
 	blr	/* image->start(physid, image->start, 0); */
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/module_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/module_64.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/module_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/module_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -286,14 +286,6 @@ static void dedotify_versions(struct mod
 	for (end = (void *)vers + size; vers < end; vers++)
 		if (vers->name[0] == '.') {
 			memmove(vers->name, vers->name+1, strlen(vers->name));
-#ifdef ARCH_RELOCATES_KCRCTAB
-			/* The TOC symbol has no CRC computed. To avoid CRC
-			 * check failing, we must force it to the expected
-			 * value (see CRC check in module.c).
-			 */
-			if (!strcmp(vers->name, "TOC."))
-				vers->crc = -(unsigned long)reloc_start;
-#endif
 		}
 }
 
@@ -652,6 +644,11 @@ int apply_relocate_add(Elf64_Shdr *sechd
 			*location = value - (unsigned long)location;
 			break;
 
+		case R_PPC64_REL32:
+			/* 32 bits relative (used by relative exception tables) */
+			*(u32 *)location = value - (unsigned long)location;
+			break;
+
 		case R_PPC64_TOCSAVE:
 			/*
 			 * Marker reloc indicates we don't have to save r2.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/module.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/module.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/module.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/module.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/vmalloc.h>
 #include <linux/bug.h>
 #include <asm/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/firmware.h>
 #include <linux/sort.h>
 #include <asm/setup.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/nvram_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/nvram_64.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/nvram_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/nvram_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/pagemap.h>
 #include <linux/pstore.h>
 #include <linux/zlib.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
 #include <asm/prom.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/of_platform.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/of_platform.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/of_platform.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/of_platform.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,11 +114,6 @@ static struct platform_driver of_pci_phb
 	},
 };
 
-static __init int of_pci_phb_init(void)
-{
-	return platform_driver_register(&of_pci_phb_driver);
-}
-
-device_initcall(of_pci_phb_init);
+builtin_platform_driver(of_pci_phb_driver);
 
 #endif /* CONFIG_PPC_OF_PLATFORM_PCI */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/pci_32.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/pci_32.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/pci_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/pci_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/machdep.h>
 
 #undef DEBUG
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/process.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/process.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -1051,14 +1051,6 @@ static inline void save_sprs(struct thre
 		 */
 		t->tar = mfspr(SPRN_TAR);
 	}
-
-	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
-		/* Conditionally save Load Monitor registers, if enabled */
-		if (t->fscr & FSCR_LM) {
-			t->lmrr = mfspr(SPRN_LMRR);
-			t->lmser = mfspr(SPRN_LMSER);
-		}
-	}
 #endif
 }
 
@@ -1094,16 +1086,6 @@ static inline void restore_sprs(struct t
 		if (old_thread->tar != new_thread->tar)
 			mtspr(SPRN_TAR, new_thread->tar);
 	}
-
-	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
-		/* Conditionally restore Load Monitor registers, if enabled */
-		if (new_thread->fscr & FSCR_LM) {
-			if (old_thread->lmrr != new_thread->lmrr)
-				mtspr(SPRN_LMRR, new_thread->lmrr);
-			if (old_thread->lmser != new_thread->lmser)
-				mtspr(SPRN_LMSER, new_thread->lmser);
-		}
-	}
 #endif
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/proc_powerpc.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/proc_powerpc.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/proc_powerpc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/proc_powerpc.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <asm/machdep.h>
 #include <asm/vdso_datapage.h>
 #include <asm/rtas.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/prom.h>
 
 #ifdef CONFIG_PPC64
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/prom.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/prom.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/prom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/prom.c	2017-02-12 16:03:20.000000000 -0500
@@ -156,21 +156,22 @@ static struct ibm_pa_feature {
 	unsigned char	pabit;		/* bit number (big-endian) */
 	unsigned char	invert;		/* if 1, pa bit set => clear feature */
 } ibm_pa_features[] __initdata = {
-	{0, 0, PPC_FEATURE_HAS_MMU, 0,		0, 0, 0},
-	{0, 0, PPC_FEATURE_HAS_FPU, 0,		0, 1, 0},
-	{CPU_FTR_CTRL, 0, 0, 0,			0, 3, 0},
-	{CPU_FTR_NOEXECUTE, 0, 0, 0,		0, 6, 0},
-	{CPU_FTR_NODSISRALIGN, 0, 0, 0,		1, 1, 1},
-	{0, MMU_FTR_CI_LARGE_PAGE, 0, 0,		1, 2, 0},
-	{CPU_FTR_REAL_LE, 0, PPC_FEATURE_TRUE_LE, 0, 5, 0, 0},
+	{ .pabyte = 0,  .pabit = 0, .cpu_user_ftrs = PPC_FEATURE_HAS_MMU },
+	{ .pabyte = 0,  .pabit = 1, .cpu_user_ftrs = PPC_FEATURE_HAS_FPU },
+	{ .pabyte = 0,  .pabit = 3, .cpu_features  = CPU_FTR_CTRL },
+	{ .pabyte = 0,  .pabit = 6, .cpu_features  = CPU_FTR_NOEXECUTE },
+	{ .pabyte = 1,  .pabit = 2, .mmu_features  = MMU_FTR_CI_LARGE_PAGE },
+	{ .pabyte = 40, .pabit = 0, .mmu_features  = MMU_FTR_TYPE_RADIX },
+	{ .pabyte = 1,  .pabit = 1, .invert = 1, .cpu_features = CPU_FTR_NODSISRALIGN },
+	{ .pabyte = 5,  .pabit = 0, .cpu_features  = CPU_FTR_REAL_LE,
+				    .cpu_user_ftrs = PPC_FEATURE_TRUE_LE },
 	/*
 	 * If the kernel doesn't support TM (ie CONFIG_PPC_TRANSACTIONAL_MEM=n),
 	 * we don't want to turn on TM here, so we use the *_COMP versions
 	 * which are 0 if the kernel doesn't support TM.
 	 */
-	{CPU_FTR_TM_COMP, 0, 0,
-	 PPC_FEATURE2_HTM_COMP|PPC_FEATURE2_HTM_NOSC_COMP, 22, 0, 0},
-	{0, MMU_FTR_TYPE_RADIX, 0, 0,		40, 0, 0},
+	{ .pabyte = 22, .pabit = 0, .cpu_features = CPU_FTR_TM_COMP,
+	  .cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP },
 };
 
 static void __init scan_features(unsigned long node, const unsigned char *ftrs,
@@ -427,7 +428,7 @@ static int __init early_init_dt_scan_cho
 		tce_alloc_end = *lprop;
 #endif
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	lprop = of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
 	if (lprop)
 		crashk_res.start = *lprop;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/prom_init.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/prom_init.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/prom_init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/prom_init.c	2017-02-12 16:03:20.000000000 -0500
@@ -461,14 +461,14 @@ static int __init prom_next_node(phandle
 	}
 }
 
-static int inline prom_getprop(phandle node, const char *pname,
+static inline int prom_getprop(phandle node, const char *pname,
 			       void *value, size_t valuelen)
 {
 	return call_prom("getprop", 4, 1, node, ADDR(pname),
 			 (u32)(unsigned long) value, (u32) valuelen);
 }
 
-static int inline prom_getproplen(phandle node, const char *pname)
+static inline int prom_getproplen(phandle node, const char *pname)
 {
 	return call_prom("getproplen", 2, 1, node, ADDR(pname));
 }
@@ -635,13 +635,7 @@ static void __init early_cmdline_parse(v
  *
  * See prom.h for the definition of the bits specified in the
  * architecture vector.
- *
- * Because the description vector contains a mix of byte and word
- * values, we declare it as an unsigned char array, and use this
- * macro to put word values in.
  */
-#define W(x)	((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
-		((x) >> 8) & 0xff, (x) & 0xff
 
 /* Firmware expects the value to be n - 1, where n is the # of vectors */
 #define NUM_VECTORS(n)		((n) - 1)
@@ -652,92 +646,205 @@ static void __init early_cmdline_parse(v
  */
 #define VECTOR_LENGTH(n)	(1 + (n) - 2)
 
-unsigned char ibm_architecture_vec[] = {
-	W(0xfffe0000), W(0x003a0000),	/* POWER5/POWER5+ */
-	W(0xffff0000), W(0x003e0000),	/* POWER6 */
-	W(0xffff0000), W(0x003f0000),	/* POWER7 */
-	W(0xffff0000), W(0x004b0000),	/* POWER8E */
-	W(0xffff0000), W(0x004c0000),   /* POWER8NVL */
-	W(0xffff0000), W(0x004d0000),	/* POWER8 */
-	W(0xffffffff), W(0x0f000004),	/* all 2.07-compliant */
-	W(0xffffffff), W(0x0f000003),	/* all 2.06-compliant */
-	W(0xffffffff), W(0x0f000002),	/* all 2.05-compliant */
-	W(0xfffffffe), W(0x0f000001),	/* all 2.04-compliant and earlier */
-	NUM_VECTORS(6),			/* 6 option vectors */
+struct option_vector1 {
+	u8 byte1;
+	u8 arch_versions;
+} __packed;
 
-	/* option vector 1: processor architectures supported */
-	VECTOR_LENGTH(2),		/* length */
-	0,				/* don't ignore, don't halt */
-	OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
-	OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
+struct option_vector2 {
+	u8 byte1;
+	__be16 reserved;
+	__be32 real_base;
+	__be32 real_size;
+	__be32 virt_base;
+	__be32 virt_size;
+	__be32 load_base;
+	__be32 min_rma;
+	__be32 min_load;
+	u8 min_rma_percent;
+	u8 max_pft_size;
+} __packed;
+
+struct option_vector3 {
+	u8 byte1;
+	u8 byte2;
+} __packed;
+
+struct option_vector4 {
+	u8 byte1;
+	u8 min_vp_cap;
+} __packed;
+
+struct option_vector5 {
+	u8 byte1;
+	u8 byte2;
+	u8 byte3;
+	u8 cmo;
+	u8 associativity;
+	u8 bin_opts;
+	u8 micro_checkpoint;
+	u8 reserved0;
+	__be32 max_cpus;
+	__be16 papr_level;
+	__be16 reserved1;
+	u8 platform_facilities;
+	u8 reserved2;
+	__be16 reserved3;
+	u8 subprocessors;
+} __packed;
+
+struct option_vector6 {
+	u8 reserved;
+	u8 secondary_pteg;
+	u8 os_name;
+} __packed;
+
+struct ibm_arch_vec {
+	struct { u32 mask, val; } pvrs[10];
+
+	u8 num_vectors;
+
+	u8 vec1_len;
+	struct option_vector1 vec1;
+
+	u8 vec2_len;
+	struct option_vector2 vec2;
+
+	u8 vec3_len;
+	struct option_vector3 vec3;
+
+	u8 vec4_len;
+	struct option_vector4 vec4;
+
+	u8 vec5_len;
+	struct option_vector5 vec5;
+
+	u8 vec6_len;
+	struct option_vector6 vec6;
+} __packed;
+
+struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
+	.pvrs = {
+		{
+			.mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
+			.val  = cpu_to_be32(0x003a0000),
+		},
+		{
+			.mask = cpu_to_be32(0xffff0000), /* POWER6 */
+			.val  = cpu_to_be32(0x003e0000),
+		},
+		{
+			.mask = cpu_to_be32(0xffff0000), /* POWER7 */
+			.val  = cpu_to_be32(0x003f0000),
+		},
+		{
+			.mask = cpu_to_be32(0xffff0000), /* POWER8E */
+			.val  = cpu_to_be32(0x004b0000),
+		},
+		{
+			.mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
+			.val  = cpu_to_be32(0x004c0000),
+		},
+		{
+			.mask = cpu_to_be32(0xffff0000), /* POWER8 */
+			.val  = cpu_to_be32(0x004d0000),
+		},
+		{
+			.mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
+			.val  = cpu_to_be32(0x0f000004),
+		},
+		{
+			.mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
+			.val  = cpu_to_be32(0x0f000003),
+		},
+		{
+			.mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
+			.val  = cpu_to_be32(0x0f000002),
+		},
+		{
+			.mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
+			.val  = cpu_to_be32(0x0f000001),
+		},
+	},
+
+	.num_vectors = NUM_VECTORS(6),
 
+	.vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
+	.vec1 = {
+		.byte1 = 0,
+		.arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
+				 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
+	},
+
+	.vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
 	/* option vector 2: Open Firmware options supported */
-	VECTOR_LENGTH(33),		/* length */
-	OV2_REAL_MODE,
-	0, 0,
-	W(0xffffffff),			/* real_base */
-	W(0xffffffff),			/* real_size */
-	W(0xffffffff),			/* virt_base */
-	W(0xffffffff),			/* virt_size */
-	W(0xffffffff),			/* load_base */
-	W(256),				/* 256MB min RMA */
-	W(0xffffffff),			/* full client load */
-	0,				/* min RMA percentage of total RAM */
-	48,				/* max log_2(hash table size) */
+	.vec2 = {
+		.byte1 = OV2_REAL_MODE,
+		.reserved = 0,
+		.real_base = cpu_to_be32(0xffffffff),
+		.real_size = cpu_to_be32(0xffffffff),
+		.virt_base = cpu_to_be32(0xffffffff),
+		.virt_size = cpu_to_be32(0xffffffff),
+		.load_base = cpu_to_be32(0xffffffff),
+		.min_rma = cpu_to_be32(256),		/* 256MB min RMA */
+		.min_load = cpu_to_be32(0xffffffff),	/* full client load */
+		.min_rma_percent = 0,	/* min RMA percentage of total RAM */
+		.max_pft_size = 48,	/* max log_2(hash table size) */
+	},
 
+	.vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
 	/* option vector 3: processor options supported */
-	VECTOR_LENGTH(2),		/* length */
-	0,				/* don't ignore, don't halt */
-	OV3_FP | OV3_VMX | OV3_DFP,
+	.vec3 = {
+		.byte1 = 0,			/* don't ignore, don't halt */
+		.byte2 = OV3_FP | OV3_VMX | OV3_DFP,
+	},
 
+	.vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
 	/* option vector 4: IBM PAPR implementation */
-	VECTOR_LENGTH(2),		/* length */
-	0,				/* don't halt */
-	OV4_MIN_ENT_CAP,		/* minimum VP entitled capacity */
+	.vec4 = {
+		.byte1 = 0,			/* don't halt */
+		.min_vp_cap = OV4_MIN_ENT_CAP,	/* minimum VP entitled capacity */
+	},
 
+	.vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
 	/* option vector 5: PAPR/OF options */
-	VECTOR_LENGTH(21),		/* length */
-	0,				/* don't ignore, don't halt */
-	OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
-	OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
+	.vec5 = {
+		.byte1 = 0,				/* don't ignore, don't halt */
+		.byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
+		OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
 #ifdef CONFIG_PCI_MSI
-	/* PCIe/MSI support.  Without MSI full PCIe is not supported */
-	OV5_FEAT(OV5_MSI),
+		/* PCIe/MSI support.  Without MSI full PCIe is not supported */
+		OV5_FEAT(OV5_MSI),
 #else
-	0,
+		0,
 #endif
-	0,
+		.byte3 = 0,
+		.cmo =
 #ifdef CONFIG_PPC_SMLPAR
-	OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
+		OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
 #else
-	0,
+		0,
 #endif
-	OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
-	0,
-	0,
-	0,
-	/* WARNING: The offset of the "number of cores" field below
-	 * must match by the macro below. Update the definition if
-	 * the structure layout changes.
-	 */
-#define IBM_ARCH_VEC_NRCORES_OFFSET	133
-	W(NR_CPUS),			/* number of cores supported */
-	0,
-	0,
-	0,
-	0,
-	OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
-	OV5_FEAT(OV5_PFO_HW_842),				/* Byte 17 */
-	0,							/* Byte 18 */
-	0,							/* Byte 19 */
-	0,							/* Byte 20 */
-	OV5_FEAT(OV5_SUB_PROCESSORS),				/* Byte 21 */
+		.associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
+		.bin_opts = 0,
+		.micro_checkpoint = 0,
+		.reserved0 = 0,
+		.max_cpus = cpu_to_be32(NR_CPUS),	/* number of cores supported */
+		.papr_level = 0,
+		.reserved1 = 0,
+		.platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
+		.reserved2 = 0,
+		.reserved3 = 0,
+		.subprocessors = 1,
+	},
 
 	/* option vector 6: IBM PAPR hints */
-	VECTOR_LENGTH(3),		/* length */
-	0,
-	0,
-	OV6_LINUX,
+	.vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
+	.vec6 = {
+		.reserved = 0,
+		.secondary_pteg = 0,
+		.os_name = OV6_LINUX,
+	},
 };
 
 /* Old method - ELF header with PT_NOTE sections only works on BE */
@@ -873,7 +980,6 @@ static void __init prom_send_capabilitie
 	ihandle root;
 	prom_arg_t ret;
 	u32 cores;
-	unsigned char *ptcores;
 
 	root = call_prom("open", 1, 1, ADDR("/"));
 	if (root != 0) {
@@ -884,37 +990,18 @@ static void __init prom_send_capabilitie
 		 * divide NR_CPUS.
 		 */
 
-		/* The core value may start at an odd address. If such a word
-		 * access is made at a cache line boundary, this leads to an
-		 * exception which may not be handled at this time.
-		 * Forcing a per byte access to avoid exception.
-		 */
-		ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
-		cores = 0;
-		cores |= ptcores[0] << 24;
-		cores |= ptcores[1] << 16;
-		cores |= ptcores[2] << 8;
-		cores |= ptcores[3];
-		if (cores != NR_CPUS) {
-			prom_printf("WARNING ! "
-				    "ibm_architecture_vec structure inconsistent: %lu!\n",
-				    cores);
-		} else {
-			cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
-			prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
-				    cores, NR_CPUS);
-			ptcores[0] = (cores >> 24) & 0xff;
-			ptcores[1] = (cores >> 16) & 0xff;
-			ptcores[2] = (cores >> 8) & 0xff;
-			ptcores[3] = cores & 0xff;
-		}
+		cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
+		prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
+			    cores, NR_CPUS);
+
+		ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
 
 		/* try calling the ibm,client-architecture-support method */
 		prom_printf("Calling ibm,client-architecture-support...");
 		if (call_prom_ret("call-method", 3, 2, &ret,
 				  ADDR("ibm,client-architecture-support"),
 				  root,
-				  ADDR(ibm_architecture_vec)) == 0) {
+				  ADDR(&ibm_architecture_vec)) == 0) {
 			/* the call exists... */
 			if (ret)
 				prom_printf("\nWARNING: ibm,client-architecture"
@@ -2747,6 +2834,9 @@ static void __init prom_find_boot_cpu(vo
 
 	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
 
+	if (!PHANDLE_VALID(cpu_pkg))
+		return;
+
 	prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
 	prom.cpu = be32_to_cpu(rval);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/ptrace32.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ptrace32.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/ptrace32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ptrace32.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/signal.h>
 #include <linux/compat.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/switch_to.h>
@@ -73,7 +73,7 @@ long compat_arch_ptrace(struct task_stru
 		if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
 			break;
 
-		copied = access_process_vm(child, (u64)addrOthers, &tmp,
+		copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
 				sizeof(tmp), FOLL_FORCE);
 		if (copied != sizeof(tmp))
 			break;
@@ -178,7 +178,7 @@ long compat_arch_ptrace(struct task_stru
 		if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
 			break;
 		ret = 0;
-		if (access_process_vm(child, (u64)addrOthers, &tmp,
+		if (ptrace_access_vm(child, (u64)addrOthers, &tmp,
 					sizeof(tmp),
 					FOLL_FORCE | FOLL_WRITE) == sizeof(tmp))
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/perf_event.h>
 #include <linux/context_tracking.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/switch_to.h>
@@ -463,6 +463,10 @@ static int fpr_set(struct task_struct *t
 
 	flush_fp_to_thread(target);
 
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.TS_FPR(i);
+	buf[32] = target->thread.fp_state.fpscr;
+
 	/* copy to local buffer then write that out */
 	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 	if (i)
@@ -672,6 +676,9 @@ static int vsr_set(struct task_struct *t
 	flush_altivec_to_thread(target);
 	flush_vsx_to_thread(target);
 
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
+
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 buf, 0, 32 * sizeof(double));
 	if (!ret)
@@ -1019,6 +1026,10 @@ static int tm_cfpr_set(struct task_struc
 	flush_fp_to_thread(target);
 	flush_altivec_to_thread(target);
 
+	for (i = 0; i < 32; i++)
+		buf[i] = target->thread.TS_CKFPR(i);
+	buf[32] = target->thread.ckfp_state.fpscr;
+
 	/* copy to local buffer then write that out */
 	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
 	if (i)
@@ -1283,6 +1294,9 @@ static int tm_cvsx_set(struct task_struc
 	flush_altivec_to_thread(target);
 	flush_vsx_to_thread(target);
 
+	for (i = 0; i < 32 ; i++)
+		buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
+
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				 buf, 0, 32 * sizeof(double));
 	if (!ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/rtas.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtas.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/rtas.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtas.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <asm/page.h>
 #include <asm/param.h>
 #include <asm/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/udbg.h>
 #include <asm/syscalls.h>
 #include <asm/smp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/rtasd.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtasd.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/rtasd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtasd.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/rtas.h>
 #include <asm/prom.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/rtas_flash.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtas_flash.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/rtas_flash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtas_flash.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/proc_fs.h>
 #include <linux/reboot.h>
 #include <asm/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/rtas.h>
 
 #define MODULE_VERS "1.0"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/rtas-proc.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtas-proc.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/rtas-proc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/rtas-proc.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/bitops.h>
 #include <linux/rtc.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/prom.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/setup_32.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/setup_32.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/setup_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/setup_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/bootx.h>
 #include <asm/btext.h>
 #include <asm/machdep.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pmac_feature.h>
 #include <asm/sections.h>
 #include <asm/nvram.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/setup_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/setup_64.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/setup_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/setup_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -354,7 +354,7 @@ void early_setup_secondary(void)
 
 #endif /* CONFIG_SMP */
 
-#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
 static bool use_spinloop(void)
 {
 	if (!IS_ENABLED(CONFIG_PPC_BOOK3E))
@@ -399,7 +399,7 @@ void smp_release_cpus(void)
 
 	DBG(" <- smp_release_cpus()\n");
 }
-#endif /* CONFIG_SMP || CONFIG_KEXEC */
+#endif /* CONFIG_SMP || CONFIG_KEXEC_CORE */
 
 /*
  * Initialize some remaining members of the ppc64_caches and systemcfg
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/setup-common.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/setup-common.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/setup-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/setup-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -915,7 +915,7 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.context.pte_frag = NULL;
 #endif
 #ifdef CONFIG_SPAPR_TCE_IOMMU
-	mm_iommu_init(&init_mm.context);
+	mm_iommu_init(&init_mm);
 #endif
 	irqstack_early_init();
 	exc_lvl_early_init();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/signal_32.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/signal_32.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/signal_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/signal_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@
 #include <linux/binfmts.h>
 #endif
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/syscalls.h>
 #include <asm/sigcontext.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/signal_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/signal_64.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/signal_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/signal_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 
 #include <asm/sigcontext.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/signal.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/key.h>
 #include <linux/context_tracking.h>
 #include <asm/hw_breakpoint.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/debug.h>
 #include <asm/tm.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/smp.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/smp.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -193,7 +193,7 @@ int smp_request_message_ipi(int virq, in
 	if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
 		return -EINVAL;
 	}
-#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
+#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC_CORE)
 	if (msg == PPC_MSG_DEBUGGER_BREAK) {
 		return 1;
 	}
@@ -325,7 +325,7 @@ void tick_broadcast(const struct cpumask
 }
 #endif
 
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
 void smp_send_debugger_break(void)
 {
 	int cpu;
@@ -340,7 +340,7 @@ void smp_send_debugger_break(void)
 }
 #endif
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
 {
 	crash_ipi_function_ptr = crash_ipi_callback;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/syscalls.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/syscalls.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/syscalls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/syscalls.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 #include <linux/file.h>
 #include <linux/personality.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/syscalls.h>
 #include <asm/time.h>
 #include <asm/unistd.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/sysfs.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/sysfs.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -703,7 +703,7 @@ static struct device_attribute pa6t_attr
 #endif /* HAS_PPC_PMC_PA6T */
 #endif /* HAS_PPC_PMC_CLASSIC */
 
-static void register_cpu_online(unsigned int cpu)
+static int register_cpu_online(unsigned int cpu)
 {
 	struct cpu *c = &per_cpu(cpu_devices, cpu);
 	struct device *s = &c->dev;
@@ -782,11 +782,12 @@ static void register_cpu_online(unsigned
 	}
 #endif
 	cacheinfo_cpu_online(cpu);
+	return 0;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void unregister_cpu_online(unsigned int cpu)
+static int unregister_cpu_online(unsigned int cpu)
 {
+#ifdef CONFIG_HOTPLUG_CPU
 	struct cpu *c = &per_cpu(cpu_devices, cpu);
 	struct device *s = &c->dev;
 	struct device_attribute *attrs, *pmc_attrs;
@@ -863,6 +864,8 @@ static void unregister_cpu_online(unsign
 	}
 #endif
 	cacheinfo_cpu_offline(cpu);
+#endif /* CONFIG_HOTPLUG_CPU */
+	return 0;
 }
 
 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
@@ -883,32 +886,6 @@ ssize_t arch_cpu_release(const char *buf
 }
 #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
 
-#endif /* CONFIG_HOTPLUG_CPU */
-
-static int sysfs_cpu_notify(struct notifier_block *self,
-				      unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned int)(long)hcpu;
-
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		register_cpu_online(cpu);
-		break;
-#ifdef CONFIG_HOTPLUG_CPU
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		unregister_cpu_online(cpu);
-		break;
-#endif
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block sysfs_cpu_nb = {
-	.notifier_call	= sysfs_cpu_notify,
-};
-
 static DEFINE_MUTEX(cpu_mutex);
 
 int cpu_add_dev_attr(struct device_attribute *attr)
@@ -1023,12 +1000,10 @@ static DEVICE_ATTR(physical_id, 0444, sh
 
 static int __init topology_init(void)
 {
-	int cpu;
+	int cpu, r;
 
 	register_nodes();
 
-	cpu_notifier_register_begin();
-
 	for_each_possible_cpu(cpu) {
 		struct cpu *c = &per_cpu(cpu_devices, cpu);
 
@@ -1047,15 +1022,10 @@ static int __init topology_init(void)
 
 			device_create_file(&c->dev, &dev_attr_physical_id);
 		}
-
-		if (cpu_online(cpu))
-			register_cpu_online(cpu);
 	}
-
-	__register_cpu_notifier(&sysfs_cpu_nb);
-
-	cpu_notifier_register_done();
-
+	r = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/topology:online",
+			      register_cpu_online, unregister_cpu_online);
+	WARN_ON(r < 0);
 #ifdef CONFIG_PPC64
 	sysfs_create_dscr_default();
 #endif /* CONFIG_PPC64 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/sys_ppc32.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/sys_ppc32.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/sys_ppc32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/sys_ppc32.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/time.h>
 #include <asm/mmu_context.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/time.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/time.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,7 +64,7 @@
 #include <asm/nvram.h>
 #include <asm/cache.h>
 #include <asm/machdep.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/time.h>
 #include <asm/prom.h>
 #include <asm/irq.h>
@@ -80,7 +80,7 @@
 #include <linux/clockchips.h>
 #include <linux/timekeeper_internal.h>
 
-static cycle_t rtc_read(struct clocksource *);
+static u64 rtc_read(struct clocksource *);
 static struct clocksource clocksource_rtc = {
 	.name         = "rtc",
 	.rating       = 400,
@@ -89,7 +89,7 @@ static struct clocksource clocksource_rt
 	.read         = rtc_read,
 };
 
-static cycle_t timebase_read(struct clocksource *);
+static u64 timebase_read(struct clocksource *);
 static struct clocksource clocksource_timebase = {
 	.name         = "timebase",
 	.rating       = 400,
@@ -164,8 +164,6 @@ u64 __cputime_sec_factor;
 EXPORT_SYMBOL(__cputime_sec_factor);
 u64 __cputime_clockt_factor;
 EXPORT_SYMBOL(__cputime_clockt_factor);
-DEFINE_PER_CPU(unsigned long, cputime_last_delta);
-DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta);
 
 cputime_t cputime_one_jiffy;
 
@@ -360,7 +358,8 @@ void vtime_account_system(struct task_st
 	unsigned long delta, sys_scaled, stolen;
 
 	delta = vtime_delta(tsk, &sys_scaled, &stolen);
-	account_system_time(tsk, 0, delta, sys_scaled);
+	account_system_time(tsk, 0, delta);
+	tsk->stimescaled += sys_scaled;
 	if (stolen)
 		account_steal_time(stolen);
 }
@@ -393,7 +392,8 @@ void vtime_account_user(struct task_stru
 	acct->user_time = 0;
 	acct->user_time_scaled = 0;
 	acct->utime_sspurr = 0;
-	account_user_time(tsk, utime, utimescaled);
+	account_user_time(tsk, utime);
+	tsk->utimescaled += utimescaled;
 }
 
 #ifdef CONFIG_PPC32
@@ -802,18 +802,18 @@ void read_persistent_clock(struct timesp
 }
 
 /* clocksource code */
-static cycle_t rtc_read(struct clocksource *cs)
+static u64 rtc_read(struct clocksource *cs)
 {
-	return (cycle_t)get_rtc();
+	return (u64)get_rtc();
 }
 
-static cycle_t timebase_read(struct clocksource *cs)
+static u64 timebase_read(struct clocksource *cs)
 {
-	return (cycle_t)get_tb();
+	return (u64)get_tb();
 }
 
 void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
-			 struct clocksource *clock, u32 mult, cycle_t cycle_last)
+			 struct clocksource *clock, u32 mult, u64 cycle_last)
 {
 	u64 new_tb_to_xs, new_stamp_xsec;
 	u32 frac_sec;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/traps.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@
 
 #include <asm/emulated_ops.h>
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/rtas.h>
@@ -64,8 +64,9 @@
 #include <asm/asm-prototypes.h>
 #include <asm/hmi.h>
 #include <sysdev/fsl_pci.h>
+#include <asm/kprobes.h>
 
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
 int (*__debugger)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_ipi)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_bpt)(struct pt_regs *regs) __read_mostly;
@@ -122,9 +123,6 @@ static unsigned long oops_begin(struct p
 	int cpu;
 	unsigned long flags;
 
-	if (debugger(regs))
-		return 1;
-
 	oops_enter();
 
 	/* racy, but better than risking deadlock. */
@@ -150,14 +148,15 @@ static void oops_end(unsigned long flags
 			       int signr)
 {
 	bust_spinlocks(0);
-	die_owner = -1;
 	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
 	die_nest_count--;
 	oops_exit();
 	printk("\n");
-	if (!die_nest_count)
+	if (!die_nest_count) {
 		/* Nest count reaches zero, release the lock. */
+		die_owner = -1;
 		arch_spin_unlock(&die_lock);
+	}
 	raw_local_irq_restore(flags);
 
 	crash_fadump(regs, "die oops");
@@ -227,8 +226,12 @@ NOKPROBE_SYMBOL(__die);
 
 void die(const char *str, struct pt_regs *regs, long err)
 {
-	unsigned long flags = oops_begin(regs);
+	unsigned long flags;
+
+	if (debugger(regs))
+		return;
 
+	flags = oops_begin(regs);
 	if (__die(str, regs, err))
 		err = 0;
 	oops_end(flags, regs, err);
@@ -365,7 +368,7 @@ static inline int check_io_access(struct
 			       (*nip & 0x100)? "OUT to": "IN from",
 			       regs->gpr[rb] - _IO_BASE, nip);
 			regs->msr |= MSR_RI;
-			regs->nip = entry->fixup;
+			regs->nip = extable_fixup(entry);
 			return 1;
 		}
 	}
@@ -824,6 +827,9 @@ void single_step_exception(struct pt_reg
 
 	clear_single_step(regs);
 
+	if (kprobe_post_handler(regs))
+		return;
+
 	if (notify_die(DIE_SSTEP, "single_step", regs, 5,
 					5, SIGTRAP) == NOTIFY_STOP)
 		goto bail;
@@ -1177,6 +1183,9 @@ void program_check_exception(struct pt_r
 		if (debugger_bpt(regs))
 			goto bail;
 
+		if (kprobe_handler(regs))
+			goto bail;
+
 		/* trap exception */
 		if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
 				== NOTIFY_STOP)
@@ -1430,7 +1439,6 @@ void facility_unavailable_exception(stru
 		[FSCR_TM_LG] = "TM",
 		[FSCR_EBB_LG] = "EBB",
 		[FSCR_TAR_LG] = "TAR",
-		[FSCR_LM_LG] = "LM",
 	};
 	char *facility = "unknown";
 	u64 value;
@@ -1488,14 +1496,6 @@ void facility_unavailable_exception(stru
 			emulate_single_step(regs);
 		}
 		return;
-	} else if ((status == FSCR_LM_LG) && cpu_has_feature(CPU_FTR_ARCH_300)) {
-		/*
-		 * This process has touched LM, so turn it on forever
-		 * for this process
-		 */
-		current->thread.fscr |= FSCR_LM;
-		mtspr(SPRN_FSCR, current->thread.fscr);
-		return;
 	}
 
 	if (status == FSCR_TM_LG) {
@@ -1519,7 +1519,8 @@ void facility_unavailable_exception(stru
 		return;
 	}
 
-	if ((status < ARRAY_SIZE(facility_strings)) &&
+	if ((hv || status >= 2) &&
+	    (status < ARRAY_SIZE(facility_strings)) &&
 	    facility_strings[status])
 		facility = facility_strings[status];
 
@@ -1527,9 +1528,8 @@ void facility_unavailable_exception(stru
 	if (!arch_irq_disabled_regs(regs))
 		local_irq_enable();
 
-	pr_err_ratelimited(
-		"%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
-		hv ? "Hypervisor " : "", facility, regs->nip, regs->msr);
+	pr_err_ratelimited("%sFacility '%s' unavailable (%d), exception at 0x%lx, MSR=%lx\n",
+		hv ? "Hypervisor " : "", facility, status, regs->nip, regs->msr);
 
 out:
 	if (user_mode(regs)) {
@@ -1754,6 +1754,9 @@ void DebugException(struct pt_regs *regs
 			return;
 		}
 
+		if (kprobe_post_handler(regs))
+			return;
+
 		if (notify_die(DIE_SSTEP, "block_step", regs, 5,
 			       5, SIGTRAP) == NOTIFY_STOP) {
 			return;
@@ -1768,6 +1771,9 @@ void DebugException(struct pt_regs *regs
 		/* Clear the instruction completion event */
 		mtspr(SPRN_DBSR, DBSR_IC);
 
+		if (kprobe_post_handler(regs))
+			return;
+
 		if (notify_die(DIE_SSTEP, "single_step", regs, 5,
 			       5, SIGTRAP) == NOTIFY_STOP) {
 			return;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/vecemu.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/vecemu.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/vecemu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/vecemu.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@
 #include <linux/sched.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Functions in vector.S */
 extern void vaddfp(vector128 *dst, vector128 *a, vector128 *b);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kernel/vio.c linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/vio.c
--- linux-libre-4.9-gnu/arch/powerpc/kernel/vio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kernel/vio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1702 +0,0 @@
-/*
- * IBM PowerPC Virtual I/O Infrastructure Support.
- *
- *    Copyright (c) 2003,2008 IBM Corp.
- *     Dave Engebretsen engebret@us.ibm.com
- *     Santiago Leon santil@us.ibm.com
- *     Hollis Blanchard <hollisb@us.ibm.com>
- *     Stephen Rothwell
- *     Robert Jennings <rcjenn@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.
- */
-
-#include <linux/cpu.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/stat.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/console.h>
-#include <linux/export.h>
-#include <linux/mm.h>
-#include <linux/dma-mapping.h>
-#include <linux/kobject.h>
-
-#include <asm/iommu.h>
-#include <asm/dma.h>
-#include <asm/vio.h>
-#include <asm/prom.h>
-#include <asm/firmware.h>
-#include <asm/tce.h>
-#include <asm/page.h>
-#include <asm/hvcall.h>
-
-static struct vio_dev vio_bus_device  = { /* fake "parent" device */
-	.name = "vio",
-	.type = "",
-	.dev.init_name = "vio",
-	.dev.bus = &vio_bus_type,
-};
-
-#ifdef CONFIG_PPC_SMLPAR
-/**
- * vio_cmo_pool - A pool of IO memory for CMO use
- *
- * @size: The size of the pool in bytes
- * @free: The amount of free memory in the pool
- */
-struct vio_cmo_pool {
-	size_t size;
-	size_t free;
-};
-
-/* How many ms to delay queued balance work */
-#define VIO_CMO_BALANCE_DELAY 100
-
-/* Portion out IO memory to CMO devices by this chunk size */
-#define VIO_CMO_BALANCE_CHUNK 131072
-
-/**
- * vio_cmo_dev_entry - A device that is CMO-enabled and requires entitlement
- *
- * @vio_dev: struct vio_dev pointer
- * @list: pointer to other devices on bus that are being tracked
- */
-struct vio_cmo_dev_entry {
-	struct vio_dev *viodev;
-	struct list_head list;
-};
-
-/**
- * vio_cmo - VIO bus accounting structure for CMO entitlement
- *
- * @lock: spinlock for entire structure
- * @balance_q: work queue for balancing system entitlement
- * @device_list: list of CMO-enabled devices requiring entitlement
- * @entitled: total system entitlement in bytes
- * @reserve: pool of memory from which devices reserve entitlement, incl. spare
- * @excess: pool of excess entitlement not needed for device reserves or spare
- * @spare: IO memory for device hotplug functionality
- * @min: minimum necessary for system operation
- * @desired: desired memory for system operation
- * @curr: bytes currently allocated
- * @high: high water mark for IO data usage
- */
-static struct vio_cmo {
-	spinlock_t lock;
-	struct delayed_work balance_q;
-	struct list_head device_list;
-	size_t entitled;
-	struct vio_cmo_pool reserve;
-	struct vio_cmo_pool excess;
-	size_t spare;
-	size_t min;
-	size_t desired;
-	size_t curr;
-	size_t high;
-} vio_cmo;
-
-/**
- * vio_cmo_OF_devices - Count the number of OF devices that have DMA windows
- */
-static int vio_cmo_num_OF_devs(void)
-{
-	struct device_node *node_vroot;
-	int count = 0;
-
-	/*
-	 * Count the number of vdevice entries with an
-	 * ibm,my-dma-window OF property
-	 */
-	node_vroot = of_find_node_by_name(NULL, "vdevice");
-	if (node_vroot) {
-		struct device_node *of_node;
-		struct property *prop;
-
-		for_each_child_of_node(node_vroot, of_node) {
-			prop = of_find_property(of_node, "ibm,my-dma-window",
-			                       NULL);
-			if (prop)
-				count++;
-		}
-	}
-	of_node_put(node_vroot);
-	return count;
-}
-
-/**
- * vio_cmo_alloc - allocate IO memory for CMO-enable devices
- *
- * @viodev: VIO device requesting IO memory
- * @size: size of allocation requested
- *
- * Allocations come from memory reserved for the devices and any excess
- * IO memory available to all devices.  The spare pool used to service
- * hotplug must be equal to %VIO_CMO_MIN_ENT for the excess pool to be
- * made available.
- *
- * Return codes:
- *  0 for successful allocation and -ENOMEM for a failure
- */
-static inline int vio_cmo_alloc(struct vio_dev *viodev, size_t size)
-{
-	unsigned long flags;
-	size_t reserve_free = 0;
-	size_t excess_free = 0;
-	int ret = -ENOMEM;
-
-	spin_lock_irqsave(&vio_cmo.lock, flags);
-
-	/* Determine the amount of free entitlement available in reserve */
-	if (viodev->cmo.entitled > viodev->cmo.allocated)
-		reserve_free = viodev->cmo.entitled - viodev->cmo.allocated;
-
-	/* If spare is not fulfilled, the excess pool can not be used. */
-	if (vio_cmo.spare >= VIO_CMO_MIN_ENT)
-		excess_free = vio_cmo.excess.free;
-
-	/* The request can be satisfied */
-	if ((reserve_free + excess_free) >= size) {
-		vio_cmo.curr += size;
-		if (vio_cmo.curr > vio_cmo.high)
-			vio_cmo.high = vio_cmo.curr;
-		viodev->cmo.allocated += size;
-		size -= min(reserve_free, size);
-		vio_cmo.excess.free -= size;
-		ret = 0;
-	}
-
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-	return ret;
-}
-
-/**
- * vio_cmo_dealloc - deallocate IO memory from CMO-enable devices
- * @viodev: VIO device freeing IO memory
- * @size: size of deallocation
- *
- * IO memory is freed by the device back to the correct memory pools.
- * The spare pool is replenished first from either memory pool, then
- * the reserve pool is used to reduce device entitlement, the excess
- * pool is used to increase the reserve pool toward the desired entitlement
- * target, and then the remaining memory is returned to the pools.
- *
- */
-static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size)
-{
-	unsigned long flags;
-	size_t spare_needed = 0;
-	size_t excess_freed = 0;
-	size_t reserve_freed = size;
-	size_t tmp;
-	int balance = 0;
-
-	spin_lock_irqsave(&vio_cmo.lock, flags);
-	vio_cmo.curr -= size;
-
-	/* Amount of memory freed from the excess pool */
-	if (viodev->cmo.allocated > viodev->cmo.entitled) {
-		excess_freed = min(reserve_freed, (viodev->cmo.allocated -
-		                                   viodev->cmo.entitled));
-		reserve_freed -= excess_freed;
-	}
-
-	/* Remove allocation from device */
-	viodev->cmo.allocated -= (reserve_freed + excess_freed);
-
-	/* Spare is a subset of the reserve pool, replenish it first. */
-	spare_needed = VIO_CMO_MIN_ENT - vio_cmo.spare;
-
-	/*
-	 * Replenish the spare in the reserve pool from the excess pool.
-	 * This moves entitlement into the reserve pool.
-	 */
-	if (spare_needed && excess_freed) {
-		tmp = min(excess_freed, spare_needed);
-		vio_cmo.excess.size -= tmp;
-		vio_cmo.reserve.size += tmp;
-		vio_cmo.spare += tmp;
-		excess_freed -= tmp;
-		spare_needed -= tmp;
-		balance = 1;
-	}
-
-	/*
-	 * Replenish the spare in the reserve pool from the reserve pool.
-	 * This removes entitlement from the device down to VIO_CMO_MIN_ENT,
-	 * if needed, and gives it to the spare pool. The amount of used
-	 * memory in this pool does not change.
-	 */
-	if (spare_needed && reserve_freed) {
-		tmp = min3(spare_needed, reserve_freed, (viodev->cmo.entitled - VIO_CMO_MIN_ENT));
-
-		vio_cmo.spare += tmp;
-		viodev->cmo.entitled -= tmp;
-		reserve_freed -= tmp;
-		spare_needed -= tmp;
-		balance = 1;
-	}
-
-	/*
-	 * Increase the reserve pool until the desired allocation is met.
-	 * Move an allocation freed from the excess pool into the reserve
-	 * pool and schedule a balance operation.
-	 */
-	if (excess_freed && (vio_cmo.desired > vio_cmo.reserve.size)) {
-		tmp = min(excess_freed, (vio_cmo.desired - vio_cmo.reserve.size));
-
-		vio_cmo.excess.size -= tmp;
-		vio_cmo.reserve.size += tmp;
-		excess_freed -= tmp;
-		balance = 1;
-	}
-
-	/* Return memory from the excess pool to that pool */
-	if (excess_freed)
-		vio_cmo.excess.free += excess_freed;
-
-	if (balance)
-		schedule_delayed_work(&vio_cmo.balance_q, VIO_CMO_BALANCE_DELAY);
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-}
-
-/**
- * vio_cmo_entitlement_update - Manage system entitlement changes
- *
- * @new_entitlement: new system entitlement to attempt to accommodate
- *
- * Increases in entitlement will be used to fulfill the spare entitlement
- * and the rest is given to the excess pool.  Decreases, if they are
- * possible, come from the excess pool and from unused device entitlement
- *
- * Returns: 0 on success, -ENOMEM when change can not be made
- */
-int vio_cmo_entitlement_update(size_t new_entitlement)
-{
-	struct vio_dev *viodev;
-	struct vio_cmo_dev_entry *dev_ent;
-	unsigned long flags;
-	size_t avail, delta, tmp;
-
-	spin_lock_irqsave(&vio_cmo.lock, flags);
-
-	/* Entitlement increases */
-	if (new_entitlement > vio_cmo.entitled) {
-		delta = new_entitlement - vio_cmo.entitled;
-
-		/* Fulfill spare allocation */
-		if (vio_cmo.spare < VIO_CMO_MIN_ENT) {
-			tmp = min(delta, (VIO_CMO_MIN_ENT - vio_cmo.spare));
-			vio_cmo.spare += tmp;
-			vio_cmo.reserve.size += tmp;
-			delta -= tmp;
-		}
-
-		/* Remaining new allocation goes to the excess pool */
-		vio_cmo.entitled += delta;
-		vio_cmo.excess.size += delta;
-		vio_cmo.excess.free += delta;
-
-		goto out;
-	}
-
-	/* Entitlement decreases */
-	delta = vio_cmo.entitled - new_entitlement;
-	avail = vio_cmo.excess.free;
-
-	/*
-	 * Need to check how much unused entitlement each device can
-	 * sacrifice to fulfill entitlement change.
-	 */
-	list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
-		if (avail >= delta)
-			break;
-
-		viodev = dev_ent->viodev;
-		if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
-		    (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
-				avail += viodev->cmo.entitled -
-				         max_t(size_t, viodev->cmo.allocated,
-				               VIO_CMO_MIN_ENT);
-	}
-
-	if (delta <= avail) {
-		vio_cmo.entitled -= delta;
-
-		/* Take entitlement from the excess pool first */
-		tmp = min(vio_cmo.excess.free, delta);
-		vio_cmo.excess.size -= tmp;
-		vio_cmo.excess.free -= tmp;
-		delta -= tmp;
-
-		/*
-		 * Remove all but VIO_CMO_MIN_ENT bytes from devices
-		 * until entitlement change is served
-		 */
-		list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
-			if (!delta)
-				break;
-
-			viodev = dev_ent->viodev;
-			tmp = 0;
-			if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
-			    (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
-				tmp = viodev->cmo.entitled -
-				      max_t(size_t, viodev->cmo.allocated,
-				            VIO_CMO_MIN_ENT);
-			viodev->cmo.entitled -= min(tmp, delta);
-			delta -= min(tmp, delta);
-		}
-	} else {
-		spin_unlock_irqrestore(&vio_cmo.lock, flags);
-		return -ENOMEM;
-	}
-
-out:
-	schedule_delayed_work(&vio_cmo.balance_q, 0);
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-	return 0;
-}
-
-/**
- * vio_cmo_balance - Balance entitlement among devices
- *
- * @work: work queue structure for this operation
- *
- * Any system entitlement above the minimum needed for devices, or
- * already allocated to devices, can be distributed to the devices.
- * The list of devices is iterated through to recalculate the desired
- * entitlement level and to determine how much entitlement above the
- * minimum entitlement is allocated to devices.
- *
- * Small chunks of the available entitlement are given to devices until
- * their requirements are fulfilled or there is no entitlement left to give.
- * Upon completion sizes of the reserve and excess pools are calculated.
- *
- * The system minimum entitlement level is also recalculated here.
- * Entitlement will be reserved for devices even after vio_bus_remove to
- * accommodate reloading the driver.  The OF tree is walked to count the
- * number of devices present and this will remove entitlement for devices
- * that have actually left the system after having vio_bus_remove called.
- */
-static void vio_cmo_balance(struct work_struct *work)
-{
-	struct vio_cmo *cmo;
-	struct vio_dev *viodev;
-	struct vio_cmo_dev_entry *dev_ent;
-	unsigned long flags;
-	size_t avail = 0, level, chunk, need;
-	int devcount = 0, fulfilled;
-
-	cmo = container_of(work, struct vio_cmo, balance_q.work);
-
-	spin_lock_irqsave(&vio_cmo.lock, flags);
-
-	/* Calculate minimum entitlement and fulfill spare */
-	cmo->min = vio_cmo_num_OF_devs() * VIO_CMO_MIN_ENT;
-	BUG_ON(cmo->min > cmo->entitled);
-	cmo->spare = min_t(size_t, VIO_CMO_MIN_ENT, (cmo->entitled - cmo->min));
-	cmo->min += cmo->spare;
-	cmo->desired = cmo->min;
-
-	/*
-	 * Determine how much entitlement is available and reset device
-	 * entitlements
-	 */
-	avail = cmo->entitled - cmo->spare;
-	list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
-		viodev = dev_ent->viodev;
-		devcount++;
-		viodev->cmo.entitled = VIO_CMO_MIN_ENT;
-		cmo->desired += (viodev->cmo.desired - VIO_CMO_MIN_ENT);
-		avail -= max_t(size_t, viodev->cmo.allocated, VIO_CMO_MIN_ENT);
-	}
-
-	/*
-	 * Having provided each device with the minimum entitlement, loop
-	 * over the devices portioning out the remaining entitlement
-	 * until there is nothing left.
-	 */
-	level = VIO_CMO_MIN_ENT;
-	while (avail) {
-		fulfilled = 0;
-		list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
-			viodev = dev_ent->viodev;
-
-			if (viodev->cmo.desired <= level) {
-				fulfilled++;
-				continue;
-			}
-
-			/*
-			 * Give the device up to VIO_CMO_BALANCE_CHUNK
-			 * bytes of entitlement, but do not exceed the
-			 * desired level of entitlement for the device.
-			 */
-			chunk = min_t(size_t, avail, VIO_CMO_BALANCE_CHUNK);
-			chunk = min(chunk, (viodev->cmo.desired -
-			                    viodev->cmo.entitled));
-			viodev->cmo.entitled += chunk;
-
-			/*
-			 * If the memory for this entitlement increase was
-			 * already allocated to the device it does not come
-			 * from the available pool being portioned out.
-			 */
-			need = max(viodev->cmo.allocated, viodev->cmo.entitled)-
-			       max(viodev->cmo.allocated, level);
-			avail -= need;
-
-		}
-		if (fulfilled == devcount)
-			break;
-		level += VIO_CMO_BALANCE_CHUNK;
-	}
-
-	/* Calculate new reserve and excess pool sizes */
-	cmo->reserve.size = cmo->min;
-	cmo->excess.free = 0;
-	cmo->excess.size = 0;
-	need = 0;
-	list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
-		viodev = dev_ent->viodev;
-		/* Calculated reserve size above the minimum entitlement */
-		if (viodev->cmo.entitled)
-			cmo->reserve.size += (viodev->cmo.entitled -
-			                      VIO_CMO_MIN_ENT);
-		/* Calculated used excess entitlement */
-		if (viodev->cmo.allocated > viodev->cmo.entitled)
-			need += viodev->cmo.allocated - viodev->cmo.entitled;
-	}
-	cmo->excess.size = cmo->entitled - cmo->reserve.size;
-	cmo->excess.free = cmo->excess.size - need;
-
-	cancel_delayed_work(to_delayed_work(work));
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-}
-
-static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
-					  dma_addr_t *dma_handle, gfp_t flag,
-					  unsigned long attrs)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	void *ret;
-
-	if (vio_cmo_alloc(viodev, roundup(size, PAGE_SIZE))) {
-		atomic_inc(&viodev->cmo.allocs_failed);
-		return NULL;
-	}
-
-	ret = dma_iommu_ops.alloc(dev, size, dma_handle, flag, attrs);
-	if (unlikely(ret == NULL)) {
-		vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
-		atomic_inc(&viodev->cmo.allocs_failed);
-	}
-
-	return ret;
-}
-
-static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
-					void *vaddr, dma_addr_t dma_handle,
-					unsigned long attrs)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-
-	dma_iommu_ops.free(dev, size, vaddr, dma_handle, attrs);
-
-	vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
-}
-
-static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
-                                         unsigned long offset, size_t size,
-                                         enum dma_data_direction direction,
-                                         unsigned long attrs)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	struct iommu_table *tbl;
-	dma_addr_t ret = DMA_ERROR_CODE;
-
-	tbl = get_iommu_table_base(dev);
-	if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)))) {
-		atomic_inc(&viodev->cmo.allocs_failed);
-		return ret;
-	}
-
-	ret = dma_iommu_ops.map_page(dev, page, offset, size, direction, attrs);
-	if (unlikely(dma_mapping_error(dev, ret))) {
-		vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
-		atomic_inc(&viodev->cmo.allocs_failed);
-	}
-
-	return ret;
-}
-
-static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
-				     size_t size,
-				     enum dma_data_direction direction,
-				     unsigned long attrs)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	struct iommu_table *tbl;
-
-	tbl = get_iommu_table_base(dev);
-	dma_iommu_ops.unmap_page(dev, dma_handle, size, direction, attrs);
-
-	vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
-}
-
-static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
-                                int nelems, enum dma_data_direction direction,
-                                unsigned long attrs)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	struct iommu_table *tbl;
-	struct scatterlist *sgl;
-	int ret, count;
-	size_t alloc_size = 0;
-
-	tbl = get_iommu_table_base(dev);
-	for_each_sg(sglist, sgl, nelems, count)
-		alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE(tbl));
-
-	if (vio_cmo_alloc(viodev, alloc_size)) {
-		atomic_inc(&viodev->cmo.allocs_failed);
-		return 0;
-	}
-
-	ret = dma_iommu_ops.map_sg(dev, sglist, nelems, direction, attrs);
-
-	if (unlikely(!ret)) {
-		vio_cmo_dealloc(viodev, alloc_size);
-		atomic_inc(&viodev->cmo.allocs_failed);
-		return ret;
-	}
-
-	for_each_sg(sglist, sgl, ret, count)
-		alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
-	if (alloc_size)
-		vio_cmo_dealloc(viodev, alloc_size);
-
-	return ret;
-}
-
-static void vio_dma_iommu_unmap_sg(struct device *dev,
-		struct scatterlist *sglist, int nelems,
-		enum dma_data_direction direction,
-		unsigned long attrs)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	struct iommu_table *tbl;
-	struct scatterlist *sgl;
-	size_t alloc_size = 0;
-	int count;
-
-	tbl = get_iommu_table_base(dev);
-	for_each_sg(sglist, sgl, nelems, count)
-		alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
-
-	dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs);
-
-	vio_cmo_dealloc(viodev, alloc_size);
-}
-
-static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
-{
-        return dma_iommu_ops.dma_supported(dev, mask);
-}
-
-static u64 vio_dma_get_required_mask(struct device *dev)
-{
-        return dma_iommu_ops.get_required_mask(dev);
-}
-
-static struct dma_map_ops vio_dma_mapping_ops = {
-	.alloc             = vio_dma_iommu_alloc_coherent,
-	.free              = vio_dma_iommu_free_coherent,
-	.mmap		   = dma_direct_mmap_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,
-};
-
-/**
- * vio_cmo_set_dev_desired - Set desired entitlement for a device
- *
- * @viodev: struct vio_dev for device to alter
- * @desired: new desired entitlement level in bytes
- *
- * For use by devices to request a change to their entitlement at runtime or
- * through sysfs.  The desired entitlement level is changed and a balancing
- * of system resources is scheduled to run in the future.
- */
-void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired)
-{
-	unsigned long flags;
-	struct vio_cmo_dev_entry *dev_ent;
-	int found = 0;
-
-	if (!firmware_has_feature(FW_FEATURE_CMO))
-		return;
-
-	spin_lock_irqsave(&vio_cmo.lock, flags);
-	if (desired < VIO_CMO_MIN_ENT)
-		desired = VIO_CMO_MIN_ENT;
-
-	/*
-	 * Changes will not be made for devices not in the device list.
-	 * If it is not in the device list, then no driver is loaded
-	 * for the device and it can not receive entitlement.
-	 */
-	list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
-		if (viodev == dev_ent->viodev) {
-			found = 1;
-			break;
-		}
-	if (!found) {
-		spin_unlock_irqrestore(&vio_cmo.lock, flags);
-		return;
-	}
-
-	/* Increase/decrease in desired device entitlement */
-	if (desired >= viodev->cmo.desired) {
-		/* Just bump the bus and device values prior to a balance*/
-		vio_cmo.desired += desired - viodev->cmo.desired;
-		viodev->cmo.desired = desired;
-	} else {
-		/* Decrease bus and device values for desired entitlement */
-		vio_cmo.desired -= viodev->cmo.desired - desired;
-		viodev->cmo.desired = desired;
-		/*
-		 * If less entitlement is desired than current entitlement, move
-		 * any reserve memory in the change region to the excess pool.
-		 */
-		if (viodev->cmo.entitled > desired) {
-			vio_cmo.reserve.size -= viodev->cmo.entitled - desired;
-			vio_cmo.excess.size += viodev->cmo.entitled - desired;
-			/*
-			 * If entitlement moving from the reserve pool to the
-			 * excess pool is currently unused, add to the excess
-			 * free counter.
-			 */
-			if (viodev->cmo.allocated < viodev->cmo.entitled)
-				vio_cmo.excess.free += viodev->cmo.entitled -
-				                       max(viodev->cmo.allocated, desired);
-			viodev->cmo.entitled = desired;
-		}
-	}
-	schedule_delayed_work(&vio_cmo.balance_q, 0);
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-}
-
-/**
- * vio_cmo_bus_probe - Handle CMO specific bus probe activities
- *
- * @viodev - Pointer to struct vio_dev for device
- *
- * Determine the devices IO memory entitlement needs, attempting
- * to satisfy the system minimum entitlement at first and scheduling
- * a balance operation to take care of the rest at a later time.
- *
- * Returns: 0 on success, -EINVAL when device doesn't support CMO, and
- *          -ENOMEM when entitlement is not available for device or
- *          device entry.
- *
- */
-static int vio_cmo_bus_probe(struct vio_dev *viodev)
-{
-	struct vio_cmo_dev_entry *dev_ent;
-	struct device *dev = &viodev->dev;
-	struct iommu_table *tbl;
-	struct vio_driver *viodrv = to_vio_driver(dev->driver);
-	unsigned long flags;
-	size_t size;
-	bool dma_capable = false;
-
-	tbl = get_iommu_table_base(dev);
-
-	/* A device requires entitlement if it has a DMA window property */
-	switch (viodev->family) {
-	case VDEVICE:
-		if (of_get_property(viodev->dev.of_node,
-					"ibm,my-dma-window", NULL))
-			dma_capable = true;
-		break;
-	case PFO:
-		dma_capable = false;
-		break;
-	default:
-		dev_warn(dev, "unknown device family: %d\n", viodev->family);
-		BUG();
-		break;
-	}
-
-	/* Configure entitlement for the device. */
-	if (dma_capable) {
-		/* Check that the driver is CMO enabled and get desired DMA */
-		if (!viodrv->get_desired_dma) {
-			dev_err(dev, "%s: device driver does not support CMO\n",
-			        __func__);
-			return -EINVAL;
-		}
-
-		viodev->cmo.desired =
-			IOMMU_PAGE_ALIGN(viodrv->get_desired_dma(viodev), tbl);
-		if (viodev->cmo.desired < VIO_CMO_MIN_ENT)
-			viodev->cmo.desired = VIO_CMO_MIN_ENT;
-		size = VIO_CMO_MIN_ENT;
-
-		dev_ent = kmalloc(sizeof(struct vio_cmo_dev_entry),
-		                  GFP_KERNEL);
-		if (!dev_ent)
-			return -ENOMEM;
-
-		dev_ent->viodev = viodev;
-		spin_lock_irqsave(&vio_cmo.lock, flags);
-		list_add(&dev_ent->list, &vio_cmo.device_list);
-	} else {
-		viodev->cmo.desired = 0;
-		size = 0;
-		spin_lock_irqsave(&vio_cmo.lock, flags);
-	}
-
-	/*
-	 * If the needs for vio_cmo.min have not changed since they
-	 * were last set, the number of devices in the OF tree has
-	 * been constant and the IO memory for this is already in
-	 * the reserve pool.
-	 */
-	if (vio_cmo.min == ((vio_cmo_num_OF_devs() + 1) *
-	                    VIO_CMO_MIN_ENT)) {
-		/* Updated desired entitlement if device requires it */
-		if (size)
-			vio_cmo.desired += (viodev->cmo.desired -
-		                        VIO_CMO_MIN_ENT);
-	} else {
-		size_t tmp;
-
-		tmp = vio_cmo.spare + vio_cmo.excess.free;
-		if (tmp < size) {
-			dev_err(dev, "%s: insufficient free "
-			        "entitlement to add device. "
-			        "Need %lu, have %lu\n", __func__,
-				size, (vio_cmo.spare + tmp));
-			spin_unlock_irqrestore(&vio_cmo.lock, flags);
-			return -ENOMEM;
-		}
-
-		/* Use excess pool first to fulfill request */
-		tmp = min(size, vio_cmo.excess.free);
-		vio_cmo.excess.free -= tmp;
-		vio_cmo.excess.size -= tmp;
-		vio_cmo.reserve.size += tmp;
-
-		/* Use spare if excess pool was insufficient */
-		vio_cmo.spare -= size - tmp;
-
-		/* Update bus accounting */
-		vio_cmo.min += size;
-		vio_cmo.desired += viodev->cmo.desired;
-	}
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-	return 0;
-}
-
-/**
- * vio_cmo_bus_remove - Handle CMO specific bus removal activities
- *
- * @viodev - Pointer to struct vio_dev for device
- *
- * Remove the device from the cmo device list.  The minimum entitlement
- * will be reserved for the device as long as it is in the system.  The
- * rest of the entitlement the device had been allocated will be returned
- * to the system.
- */
-static void vio_cmo_bus_remove(struct vio_dev *viodev)
-{
-	struct vio_cmo_dev_entry *dev_ent;
-	unsigned long flags;
-	size_t tmp;
-
-	spin_lock_irqsave(&vio_cmo.lock, flags);
-	if (viodev->cmo.allocated) {
-		dev_err(&viodev->dev, "%s: device had %lu bytes of IO "
-		        "allocated after remove operation.\n",
-		        __func__, viodev->cmo.allocated);
-		BUG();
-	}
-
-	/*
-	 * Remove the device from the device list being maintained for
-	 * CMO enabled devices.
-	 */
-	list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
-		if (viodev == dev_ent->viodev) {
-			list_del(&dev_ent->list);
-			kfree(dev_ent);
-			break;
-		}
-
-	/*
-	 * Devices may not require any entitlement and they do not need
-	 * to be processed.  Otherwise, return the device's entitlement
-	 * back to the pools.
-	 */
-	if (viodev->cmo.entitled) {
-		/*
-		 * This device has not yet left the OF tree, it's
-		 * minimum entitlement remains in vio_cmo.min and
-		 * vio_cmo.desired
-		 */
-		vio_cmo.desired -= (viodev->cmo.desired - VIO_CMO_MIN_ENT);
-
-		/*
-		 * Save min allocation for device in reserve as long
-		 * as it exists in OF tree as determined by later
-		 * balance operation
-		 */
-		viodev->cmo.entitled -= VIO_CMO_MIN_ENT;
-
-		/* Replenish spare from freed reserve pool */
-		if (viodev->cmo.entitled && (vio_cmo.spare < VIO_CMO_MIN_ENT)) {
-			tmp = min(viodev->cmo.entitled, (VIO_CMO_MIN_ENT -
-			                                 vio_cmo.spare));
-			vio_cmo.spare += tmp;
-			viodev->cmo.entitled -= tmp;
-		}
-
-		/* Remaining reserve goes to excess pool */
-		vio_cmo.excess.size += viodev->cmo.entitled;
-		vio_cmo.excess.free += viodev->cmo.entitled;
-		vio_cmo.reserve.size -= viodev->cmo.entitled;
-
-		/*
-		 * Until the device is removed it will keep a
-		 * minimum entitlement; this will guarantee that
-		 * a module unload/load will result in a success.
-		 */
-		viodev->cmo.entitled = VIO_CMO_MIN_ENT;
-		viodev->cmo.desired = VIO_CMO_MIN_ENT;
-		atomic_set(&viodev->cmo.allocs_failed, 0);
-	}
-
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-}
-
-static void vio_cmo_set_dma_ops(struct vio_dev *viodev)
-{
-	set_dma_ops(&viodev->dev, &vio_dma_mapping_ops);
-}
-
-/**
- * vio_cmo_bus_init - CMO entitlement initialization at bus init time
- *
- * Set up the reserve and excess entitlement pools based on available
- * system entitlement and the number of devices in the OF tree that
- * require entitlement in the reserve pool.
- */
-static void vio_cmo_bus_init(void)
-{
-	struct hvcall_mpp_data mpp_data;
-	int err;
-
-	memset(&vio_cmo, 0, sizeof(struct vio_cmo));
-	spin_lock_init(&vio_cmo.lock);
-	INIT_LIST_HEAD(&vio_cmo.device_list);
-	INIT_DELAYED_WORK(&vio_cmo.balance_q, vio_cmo_balance);
-
-	/* Get current system entitlement */
-	err = h_get_mpp(&mpp_data);
-
-	/*
-	 * On failure, continue with entitlement set to 0, will panic()
-	 * later when spare is reserved.
-	 */
-	if (err != H_SUCCESS) {
-		printk(KERN_ERR "%s: unable to determine system IO "\
-		       "entitlement. (%d)\n", __func__, err);
-		vio_cmo.entitled = 0;
-	} else {
-		vio_cmo.entitled = mpp_data.entitled_mem;
-	}
-
-	/* Set reservation and check against entitlement */
-	vio_cmo.spare = VIO_CMO_MIN_ENT;
-	vio_cmo.reserve.size = vio_cmo.spare;
-	vio_cmo.reserve.size += (vio_cmo_num_OF_devs() *
-	                         VIO_CMO_MIN_ENT);
-	if (vio_cmo.reserve.size > vio_cmo.entitled) {
-		printk(KERN_ERR "%s: insufficient system entitlement\n",
-		       __func__);
-		panic("%s: Insufficient system entitlement", __func__);
-	}
-
-	/* Set the remaining accounting variables */
-	vio_cmo.excess.size = vio_cmo.entitled - vio_cmo.reserve.size;
-	vio_cmo.excess.free = vio_cmo.excess.size;
-	vio_cmo.min = vio_cmo.reserve.size;
-	vio_cmo.desired = vio_cmo.reserve.size;
-}
-
-/* sysfs device functions and data structures for CMO */
-
-#define viodev_cmo_rd_attr(name)                                        \
-static ssize_t viodev_cmo_##name##_show(struct device *dev,             \
-                                        struct device_attribute *attr,  \
-                                         char *buf)                     \
-{                                                                       \
-	return sprintf(buf, "%lu\n", to_vio_dev(dev)->cmo.name);        \
-}
-
-static ssize_t viodev_cmo_allocs_failed_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	return sprintf(buf, "%d\n", atomic_read(&viodev->cmo.allocs_failed));
-}
-
-static ssize_t viodev_cmo_allocs_failed_reset(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	atomic_set(&viodev->cmo.allocs_failed, 0);
-	return count;
-}
-
-static ssize_t viodev_cmo_desired_set(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	size_t new_desired;
-	int ret;
-
-	ret = kstrtoul(buf, 10, &new_desired);
-	if (ret)
-		return ret;
-
-	vio_cmo_set_dev_desired(viodev, new_desired);
-	return count;
-}
-
-viodev_cmo_rd_attr(desired);
-viodev_cmo_rd_attr(entitled);
-viodev_cmo_rd_attr(allocated);
-
-static ssize_t name_show(struct device *, struct device_attribute *, char *);
-static ssize_t devspec_show(struct device *, struct device_attribute *, char *);
-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
-			     char *buf);
-static struct device_attribute vio_cmo_dev_attrs[] = {
-	__ATTR_RO(name),
-	__ATTR_RO(devspec),
-	__ATTR_RO(modalias),
-	__ATTR(cmo_desired,       S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
-	       viodev_cmo_desired_show, viodev_cmo_desired_set),
-	__ATTR(cmo_entitled,      S_IRUGO, viodev_cmo_entitled_show,      NULL),
-	__ATTR(cmo_allocated,     S_IRUGO, viodev_cmo_allocated_show,     NULL),
-	__ATTR(cmo_allocs_failed, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
-	       viodev_cmo_allocs_failed_show, viodev_cmo_allocs_failed_reset),
-	__ATTR_NULL
-};
-
-/* sysfs bus functions and data structures for CMO */
-
-#define viobus_cmo_rd_attr(name)                                        \
-static ssize_t cmo_##name##_show(struct bus_type *bt, char *buf)        \
-{                                                                       \
-	return sprintf(buf, "%lu\n", vio_cmo.name);                     \
-}                                                                       \
-static BUS_ATTR_RO(cmo_##name)
-
-#define viobus_cmo_pool_rd_attr(name, var)                              \
-static ssize_t                                                          \
-cmo_##name##_##var##_show(struct bus_type *bt, char *buf)               \
-{                                                                       \
-	return sprintf(buf, "%lu\n", vio_cmo.name.var);                 \
-}                                                                       \
-static BUS_ATTR_RO(cmo_##name##_##var)
-
-viobus_cmo_rd_attr(entitled);
-viobus_cmo_rd_attr(spare);
-viobus_cmo_rd_attr(min);
-viobus_cmo_rd_attr(desired);
-viobus_cmo_rd_attr(curr);
-viobus_cmo_pool_rd_attr(reserve, size);
-viobus_cmo_pool_rd_attr(excess, size);
-viobus_cmo_pool_rd_attr(excess, free);
-
-static ssize_t cmo_high_show(struct bus_type *bt, char *buf)
-{
-	return sprintf(buf, "%lu\n", vio_cmo.high);
-}
-
-static ssize_t cmo_high_store(struct bus_type *bt, const char *buf,
-			      size_t count)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&vio_cmo.lock, flags);
-	vio_cmo.high = vio_cmo.curr;
-	spin_unlock_irqrestore(&vio_cmo.lock, flags);
-
-	return count;
-}
-static BUS_ATTR_RW(cmo_high);
-
-static struct attribute *vio_bus_attrs[] = {
-	&bus_attr_cmo_entitled.attr,
-	&bus_attr_cmo_spare.attr,
-	&bus_attr_cmo_min.attr,
-	&bus_attr_cmo_desired.attr,
-	&bus_attr_cmo_curr.attr,
-	&bus_attr_cmo_high.attr,
-	&bus_attr_cmo_reserve_size.attr,
-	&bus_attr_cmo_excess_size.attr,
-	&bus_attr_cmo_excess_free.attr,
-	NULL,
-};
-ATTRIBUTE_GROUPS(vio_bus);
-
-static void vio_cmo_sysfs_init(void)
-{
-	vio_bus_type.dev_attrs = vio_cmo_dev_attrs;
-	vio_bus_type.bus_groups = vio_bus_groups;
-}
-#else /* CONFIG_PPC_SMLPAR */
-int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
-void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {}
-static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; }
-static void vio_cmo_bus_remove(struct vio_dev *viodev) {}
-static void vio_cmo_set_dma_ops(struct vio_dev *viodev) {}
-static void vio_cmo_bus_init(void) {}
-static void vio_cmo_sysfs_init(void) { }
-#endif /* CONFIG_PPC_SMLPAR */
-EXPORT_SYMBOL(vio_cmo_entitlement_update);
-EXPORT_SYMBOL(vio_cmo_set_dev_desired);
-
-
-/*
- * Platform Facilities Option (PFO) support
- */
-
-/**
- * vio_h_cop_sync - Perform a synchronous PFO co-processor operation
- *
- * @vdev - Pointer to a struct vio_dev for device
- * @op - Pointer to a struct vio_pfo_op for the operation parameters
- *
- * Calls the hypervisor to synchronously perform the PFO operation
- * described in @op.  In the case of a busy response from the hypervisor,
- * the operation will be re-submitted indefinitely unless a non-zero timeout
- * is specified or an error occurs. The timeout places a limit on when to
- * stop re-submitting a operation, the total time can be exceeded if an
- * operation is in progress.
- *
- * If op->hcall_ret is not NULL, this will be set to the return from the
- * last h_cop_op call or it will be 0 if an error not involving the h_call
- * was encountered.
- *
- * Returns:
- *	0 on success,
- *	-EINVAL if the h_call fails due to an invalid parameter,
- *	-E2BIG if the h_call can not be performed synchronously,
- *	-EBUSY if a timeout is specified and has elapsed,
- *	-EACCES if the memory area for data/status has been rescinded, or
- *	-EPERM if a hardware fault has been indicated
- */
-int vio_h_cop_sync(struct vio_dev *vdev, struct vio_pfo_op *op)
-{
-	struct device *dev = &vdev->dev;
-	unsigned long deadline = 0;
-	long hret = 0;
-	int ret = 0;
-
-	if (op->timeout)
-		deadline = jiffies + msecs_to_jiffies(op->timeout);
-
-	while (true) {
-		hret = plpar_hcall_norets(H_COP, op->flags,
-				vdev->resource_id,
-				op->in, op->inlen, op->out,
-				op->outlen, op->csbcpb);
-
-		if (hret == H_SUCCESS ||
-		    (hret != H_NOT_ENOUGH_RESOURCES &&
-		     hret != H_BUSY && hret != H_RESOURCE) ||
-		    (op->timeout && time_after(deadline, jiffies)))
-			break;
-
-		dev_dbg(dev, "%s: hcall ret(%ld), retrying.\n", __func__, hret);
-	}
-
-	switch (hret) {
-	case H_SUCCESS:
-		ret = 0;
-		break;
-	case H_OP_MODE:
-	case H_TOO_BIG:
-		ret = -E2BIG;
-		break;
-	case H_RESCINDED:
-		ret = -EACCES;
-		break;
-	case H_HARDWARE:
-		ret = -EPERM;
-		break;
-	case H_NOT_ENOUGH_RESOURCES:
-	case H_RESOURCE:
-	case H_BUSY:
-		ret = -EBUSY;
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	if (ret)
-		dev_dbg(dev, "%s: Sync h_cop_op failure (ret:%d) (hret:%ld)\n",
-				__func__, ret, hret);
-
-	op->hcall_err = hret;
-	return ret;
-}
-EXPORT_SYMBOL(vio_h_cop_sync);
-
-static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
-{
-	const __be32 *dma_window;
-	struct iommu_table *tbl;
-	unsigned long offset, size;
-
-	dma_window = of_get_property(dev->dev.of_node,
-				  "ibm,my-dma-window", NULL);
-	if (!dma_window)
-		return NULL;
-
-	tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
-	if (tbl == NULL)
-		return NULL;
-
-	of_parse_dma_window(dev->dev.of_node, dma_window,
-			    &tbl->it_index, &offset, &size);
-
-	/* TCE table size - measured in tce entries */
-	tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
-	tbl->it_size = size >> tbl->it_page_shift;
-	/* offset for VIO should always be 0 */
-	tbl->it_offset = offset >> tbl->it_page_shift;
-	tbl->it_busno = 0;
-	tbl->it_type = TCE_VB;
-	tbl->it_blocksize = 16;
-
-	if (firmware_has_feature(FW_FEATURE_LPAR))
-		tbl->it_ops = &iommu_table_lpar_multi_ops;
-	else
-		tbl->it_ops = &iommu_table_pseries_ops;
-
-	return iommu_init_table(tbl, -1);
-}
-
-/**
- * vio_match_device: - Tell if a VIO device has a matching
- *			VIO device id structure.
- * @ids:	array of VIO device id structures to search in
- * @dev:	the VIO device structure to match against
- *
- * Used by a driver to check whether a VIO device present in the
- * system is in its list of supported devices. Returns the matching
- * vio_device_id structure or NULL if there is no match.
- */
-static const struct vio_device_id *vio_match_device(
-		const struct vio_device_id *ids, const struct vio_dev *dev)
-{
-	while (ids->type[0] != '\0') {
-		if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
-		    of_device_is_compatible(dev->dev.of_node,
-					 ids->compat))
-			return ids;
-		ids++;
-	}
-	return NULL;
-}
-
-/*
- * Convert from struct device to struct vio_dev and pass to driver.
- * dev->driver has already been set by generic code because vio_bus_match
- * succeeded.
- */
-static int vio_bus_probe(struct device *dev)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	struct vio_driver *viodrv = to_vio_driver(dev->driver);
-	const struct vio_device_id *id;
-	int error = -ENODEV;
-
-	if (!viodrv->probe)
-		return error;
-
-	id = vio_match_device(viodrv->id_table, viodev);
-	if (id) {
-		memset(&viodev->cmo, 0, sizeof(viodev->cmo));
-		if (firmware_has_feature(FW_FEATURE_CMO)) {
-			error = vio_cmo_bus_probe(viodev);
-			if (error)
-				return error;
-		}
-		error = viodrv->probe(viodev, id);
-		if (error && firmware_has_feature(FW_FEATURE_CMO))
-			vio_cmo_bus_remove(viodev);
-	}
-
-	return error;
-}
-
-/* convert from struct device to struct vio_dev and pass to driver. */
-static int vio_bus_remove(struct device *dev)
-{
-	struct vio_dev *viodev = to_vio_dev(dev);
-	struct vio_driver *viodrv = to_vio_driver(dev->driver);
-	struct device *devptr;
-	int ret = 1;
-
-	/*
-	 * Hold a reference to the device after the remove function is called
-	 * to allow for CMO accounting cleanup for the device.
-	 */
-	devptr = get_device(dev);
-
-	if (viodrv->remove)
-		ret = viodrv->remove(viodev);
-
-	if (!ret && firmware_has_feature(FW_FEATURE_CMO))
-		vio_cmo_bus_remove(viodev);
-
-	put_device(devptr);
-	return ret;
-}
-
-/**
- * vio_register_driver: - Register a new vio driver
- * @viodrv:	The vio_driver structure to be registered.
- */
-int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
-			  const char *mod_name)
-{
-	pr_debug("%s: driver %s registering\n", __func__, viodrv->name);
-
-	/* fill in 'struct driver' fields */
-	viodrv->driver.name = viodrv->name;
-	viodrv->driver.pm = viodrv->pm;
-	viodrv->driver.bus = &vio_bus_type;
-	viodrv->driver.owner = owner;
-	viodrv->driver.mod_name = mod_name;
-
-	return driver_register(&viodrv->driver);
-}
-EXPORT_SYMBOL(__vio_register_driver);
-
-/**
- * vio_unregister_driver - Remove registration of vio driver.
- * @viodrv:	The vio_driver struct to be removed form registration
- */
-void vio_unregister_driver(struct vio_driver *viodrv)
-{
-	driver_unregister(&viodrv->driver);
-}
-EXPORT_SYMBOL(vio_unregister_driver);
-
-/* vio_dev refcount hit 0 */
-static void vio_dev_release(struct device *dev)
-{
-	struct iommu_table *tbl = get_iommu_table_base(dev);
-
-	if (tbl)
-		iommu_free_table(tbl, of_node_full_name(dev->of_node));
-	of_node_put(dev->of_node);
-	kfree(to_vio_dev(dev));
-}
-
-/**
- * vio_register_device_node: - Register a new vio device.
- * @of_node:	The OF node for this device.
- *
- * Creates and initializes a vio_dev structure from the data in
- * of_node and adds it to the list of virtual devices.
- * Returns a pointer to the created vio_dev or NULL if node has
- * NULL device_type or compatible fields.
- */
-struct vio_dev *vio_register_device_node(struct device_node *of_node)
-{
-	struct vio_dev *viodev;
-	struct device_node *parent_node;
-	const __be32 *prop;
-	enum vio_dev_family family;
-	const char *of_node_name = of_node->name ? of_node->name : "<unknown>";
-
-	/*
-	 * Determine if this node is a under the /vdevice node or under the
-	 * /ibm,platform-facilities node.  This decides the device's family.
-	 */
-	parent_node = of_get_parent(of_node);
-	if (parent_node) {
-		if (!strcmp(parent_node->full_name, "/ibm,platform-facilities"))
-			family = PFO;
-		else if (!strcmp(parent_node->full_name, "/vdevice"))
-			family = VDEVICE;
-		else {
-			pr_warn("%s: parent(%s) of %s not recognized.\n",
-					__func__,
-					parent_node->full_name,
-					of_node_name);
-			of_node_put(parent_node);
-			return NULL;
-		}
-		of_node_put(parent_node);
-	} else {
-		pr_warn("%s: could not determine the parent of node %s.\n",
-				__func__, of_node_name);
-		return NULL;
-	}
-
-	if (family == PFO) {
-		if (of_get_property(of_node, "interrupt-controller", NULL)) {
-			pr_debug("%s: Skipping the interrupt controller %s.\n",
-					__func__, of_node_name);
-			return NULL;
-		}
-	}
-
-	/* allocate a vio_dev for this node */
-	viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL);
-	if (viodev == NULL) {
-		pr_warn("%s: allocation failure for VIO device.\n", __func__);
-		return NULL;
-	}
-
-	/* we need the 'device_type' property, in order to match with drivers */
-	viodev->family = family;
-	if (viodev->family == VDEVICE) {
-		unsigned int unit_address;
-
-		if (of_node->type != NULL)
-			viodev->type = of_node->type;
-		else {
-			pr_warn("%s: node %s is missing the 'device_type' "
-					"property.\n", __func__, of_node_name);
-			goto out;
-		}
-
-		prop = of_get_property(of_node, "reg", NULL);
-		if (prop == NULL) {
-			pr_warn("%s: node %s missing 'reg'\n",
-					__func__, of_node_name);
-			goto out;
-		}
-		unit_address = of_read_number(prop, 1);
-		dev_set_name(&viodev->dev, "%x", unit_address);
-		viodev->irq = irq_of_parse_and_map(of_node, 0);
-		viodev->unit_address = unit_address;
-	} else {
-		/* PFO devices need their resource_id for submitting COP_OPs
-		 * This is an optional field for devices, but is required when
-		 * performing synchronous ops */
-		prop = of_get_property(of_node, "ibm,resource-id", NULL);
-		if (prop != NULL)
-			viodev->resource_id = of_read_number(prop, 1);
-
-		dev_set_name(&viodev->dev, "%s", of_node_name);
-		viodev->type = of_node_name;
-		viodev->irq = 0;
-	}
-
-	viodev->name = of_node->name;
-	viodev->dev.of_node = of_node_get(of_node);
-
-	set_dev_node(&viodev->dev, of_node_to_nid(of_node));
-
-	/* init generic 'struct device' fields: */
-	viodev->dev.parent = &vio_bus_device.dev;
-	viodev->dev.bus = &vio_bus_type;
-	viodev->dev.release = vio_dev_release;
-
-	if (of_get_property(viodev->dev.of_node, "ibm,my-dma-window", NULL)) {
-		if (firmware_has_feature(FW_FEATURE_CMO))
-			vio_cmo_set_dma_ops(viodev);
-		else
-			set_dma_ops(&viodev->dev, &dma_iommu_ops);
-
-		set_iommu_table_base(&viodev->dev,
-				     vio_build_iommu_table(viodev));
-
-		/* needed to ensure proper operation of coherent allocations
-		 * later, in case driver doesn't set it explicitly */
-		viodev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
-		viodev->dev.dma_mask = &viodev->dev.coherent_dma_mask;
-	}
-
-	/* register with generic device framework */
-	if (device_register(&viodev->dev)) {
-		printk(KERN_ERR "%s: failed to register device %s\n",
-				__func__, dev_name(&viodev->dev));
-		put_device(&viodev->dev);
-		return NULL;
-	}
-
-	return viodev;
-
-out:	/* Use this exit point for any return prior to device_register */
-	kfree(viodev);
-
-	return NULL;
-}
-EXPORT_SYMBOL(vio_register_device_node);
-
-/*
- * vio_bus_scan_for_devices - Scan OF and register each child device
- * @root_name - OF node name for the root of the subtree to search.
- *		This must be non-NULL
- *
- * Starting from the root node provide, register the device node for
- * each child beneath the root.
- */
-static void vio_bus_scan_register_devices(char *root_name)
-{
-	struct device_node *node_root, *node_child;
-
-	if (!root_name)
-		return;
-
-	node_root = of_find_node_by_name(NULL, root_name);
-	if (node_root) {
-
-		/*
-		 * Create struct vio_devices for each virtual device in
-		 * the device tree. Drivers will associate with them later.
-		 */
-		node_child = of_get_next_child(node_root, NULL);
-		while (node_child) {
-			vio_register_device_node(node_child);
-			node_child = of_get_next_child(node_root, node_child);
-		}
-		of_node_put(node_root);
-	}
-}
-
-/**
- * vio_bus_init: - Initialize the virtual IO bus
- */
-static int __init vio_bus_init(void)
-{
-	int err;
-
-	if (firmware_has_feature(FW_FEATURE_CMO))
-		vio_cmo_sysfs_init();
-
-	err = bus_register(&vio_bus_type);
-	if (err) {
-		printk(KERN_ERR "failed to register VIO bus\n");
-		return err;
-	}
-
-	/*
-	 * The fake parent of all vio devices, just to give us
-	 * a nice directory
-	 */
-	err = device_register(&vio_bus_device.dev);
-	if (err) {
-		printk(KERN_WARNING "%s: device_register returned %i\n",
-				__func__, err);
-		return err;
-	}
-
-	if (firmware_has_feature(FW_FEATURE_CMO))
-		vio_cmo_bus_init();
-
-	return 0;
-}
-postcore_initcall(vio_bus_init);
-
-static int __init vio_device_init(void)
-{
-	vio_bus_scan_register_devices("vdevice");
-	vio_bus_scan_register_devices("ibm,platform-facilities");
-
-	return 0;
-}
-device_initcall(vio_device_init);
-
-static ssize_t name_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
-}
-
-static ssize_t devspec_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct device_node *of_node = dev->of_node;
-
-	return sprintf(buf, "%s\n", of_node_full_name(of_node));
-}
-
-static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	const struct vio_dev *vio_dev = to_vio_dev(dev);
-	struct device_node *dn;
-	const char *cp;
-
-	dn = dev->of_node;
-	if (!dn) {
-		strcpy(buf, "\n");
-		return strlen(buf);
-	}
-	cp = of_get_property(dn, "compatible", NULL);
-	if (!cp) {
-		strcpy(buf, "\n");
-		return strlen(buf);
-	}
-
-	return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp);
-}
-
-static struct device_attribute vio_dev_attrs[] = {
-	__ATTR_RO(name),
-	__ATTR_RO(devspec),
-	__ATTR_RO(modalias),
-	__ATTR_NULL
-};
-
-void vio_unregister_device(struct vio_dev *viodev)
-{
-	device_unregister(&viodev->dev);
-}
-EXPORT_SYMBOL(vio_unregister_device);
-
-static int vio_bus_match(struct device *dev, struct device_driver *drv)
-{
-	const struct vio_dev *vio_dev = to_vio_dev(dev);
-	struct vio_driver *vio_drv = to_vio_driver(drv);
-	const struct vio_device_id *ids = vio_drv->id_table;
-
-	return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
-}
-
-static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
-{
-	const struct vio_dev *vio_dev = to_vio_dev(dev);
-	struct device_node *dn;
-	const char *cp;
-
-	dn = dev->of_node;
-	if (!dn)
-		return -ENODEV;
-	cp = of_get_property(dn, "compatible", NULL);
-	if (!cp)
-		return -ENODEV;
-
-	add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp);
-	return 0;
-}
-
-struct bus_type vio_bus_type = {
-	.name = "vio",
-	.dev_attrs = vio_dev_attrs,
-	.uevent = vio_hotplug,
-	.match = vio_bus_match,
-	.probe = vio_bus_probe,
-	.remove = vio_bus_remove,
-};
-
-/**
- * vio_get_attribute: - get attribute for virtual device
- * @vdev:	The vio device to get property.
- * @which:	The property/attribute to be extracted.
- * @length:	Pointer to length of returned data size (unused if NULL).
- *
- * Calls prom.c's of_get_property() to return the value of the
- * attribute specified by @which
-*/
-const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
-{
-	return of_get_property(vdev->dev.of_node, which, length);
-}
-EXPORT_SYMBOL(vio_get_attribute);
-
-#ifdef CONFIG_PPC_PSERIES
-/* vio_find_name() - internal because only vio.c knows how we formatted the
- * kobject name
- */
-static struct vio_dev *vio_find_name(const char *name)
-{
-	struct device *found;
-
-	found = bus_find_device_by_name(&vio_bus_type, NULL, name);
-	if (!found)
-		return NULL;
-
-	return to_vio_dev(found);
-}
-
-/**
- * vio_find_node - find an already-registered vio_dev
- * @vnode: device_node of the virtual device we're looking for
- */
-struct vio_dev *vio_find_node(struct device_node *vnode)
-{
-	char kobj_name[20];
-	struct device_node *vnode_parent;
-	const char *dev_type;
-
-	vnode_parent = of_get_parent(vnode);
-	if (!vnode_parent)
-		return NULL;
-
-	dev_type = of_get_property(vnode_parent, "device_type", NULL);
-	of_node_put(vnode_parent);
-	if (!dev_type)
-		return NULL;
-
-	/* construct the kobject name from the device node */
-	if (!strcmp(dev_type, "vdevice")) {
-		const __be32 *prop;
-		
-		prop = of_get_property(vnode, "reg", NULL);
-		if (!prop)
-			return NULL;
-		snprintf(kobj_name, sizeof(kobj_name), "%x",
-			 (uint32_t)of_read_number(prop, 1));
-	} else if (!strcmp(dev_type, "ibm,platform-facilities"))
-		snprintf(kobj_name, sizeof(kobj_name), "%s", vnode->name);
-	else
-		return NULL;
-
-	return vio_find_name(kobj_name);
-}
-EXPORT_SYMBOL(vio_find_node);
-
-int vio_enable_interrupts(struct vio_dev *dev)
-{
-	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
-	if (rc != H_SUCCESS)
-		printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
-	return rc;
-}
-EXPORT_SYMBOL(vio_enable_interrupts);
-
-int vio_disable_interrupts(struct vio_dev *dev)
-{
-	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
-	if (rc != H_SUCCESS)
-		printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
-	return rc;
-}
-EXPORT_SYMBOL(vio_disable_interrupts);
-#endif /* CONFIG_PPC_PSERIES */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_64_mmu_hv.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,6 +88,8 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u
 	/* 128 (2**7) bytes in each HPTEG */
 	kvm->arch.hpt_mask = (1ul << (order - 7)) - 1;
 
+	atomic64_set(&kvm->arch.mmio_update, 0);
+
 	/* Allocate reverse map array */
 	rev = vmalloc(sizeof(struct revmap_entry) * kvm->arch.hpt_npte);
 	if (!rev) {
@@ -255,7 +257,7 @@ static void kvmppc_mmu_book3s_64_hv_rese
 	kvmppc_set_msr(vcpu, msr);
 }
 
-long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
+static long kvmppc_virtmode_do_h_enter(struct kvm *kvm, unsigned long flags,
 				long pte_index, unsigned long pteh,
 				unsigned long ptel, unsigned long *pte_idx_ret)
 {
@@ -312,7 +314,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate
 	struct kvmppc_slb *slbe;
 	unsigned long slb_v;
 	unsigned long pp, key;
-	unsigned long v, gr;
+	unsigned long v, orig_v, gr;
 	__be64 *hptep;
 	int index;
 	int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR);
@@ -337,10 +339,12 @@ static int kvmppc_mmu_book3s_64_hv_xlate
 		return -ENOENT;
 	}
 	hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
-	v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
+	v = orig_v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK;
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		v = hpte_new_to_old_v(v, be64_to_cpu(hptep[1]));
 	gr = kvm->arch.revmap[index].guest_rpte;
 
-	unlock_hpte(hptep, v);
+	unlock_hpte(hptep, orig_v);
 	preempt_enable();
 
 	gpte->eaddr = eaddr;
@@ -438,6 +442,7 @@ int kvmppc_book3s_hv_page_fault(struct k
 {
 	struct kvm *kvm = vcpu->kvm;
 	unsigned long hpte[3], r;
+	unsigned long hnow_v, hnow_r;
 	__be64 *hptep;
 	unsigned long mmu_seq, psize, pte_size;
 	unsigned long gpa_base, gfn_base;
@@ -451,6 +456,7 @@ int kvmppc_book3s_hv_page_fault(struct k
 	unsigned int writing, write_ok;
 	struct vm_area_struct *vma;
 	unsigned long rcbits;
+	long mmio_update;
 
 	/*
 	 * Real-mode code has already searched the HPT and found the
@@ -460,6 +466,19 @@ int kvmppc_book3s_hv_page_fault(struct k
 	 */
 	if (ea != vcpu->arch.pgfault_addr)
 		return RESUME_GUEST;
+
+	if (vcpu->arch.pgfault_cache) {
+		mmio_update = atomic64_read(&kvm->arch.mmio_update);
+		if (mmio_update == vcpu->arch.pgfault_cache->mmio_update) {
+			r = vcpu->arch.pgfault_cache->rpte;
+			psize = hpte_page_size(vcpu->arch.pgfault_hpte[0], r);
+			gpa_base = r & HPTE_R_RPN & ~(psize - 1);
+			gfn_base = gpa_base >> PAGE_SHIFT;
+			gpa = gpa_base | (ea & (psize - 1));
+			return kvmppc_hv_emulate_mmio(run, vcpu, gpa, ea,
+						dsisr & DSISR_ISSTORE);
+		}
+	}
 	index = vcpu->arch.pgfault_index;
 	hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
 	rev = &kvm->arch.revmap[index];
@@ -472,6 +491,10 @@ int kvmppc_book3s_hv_page_fault(struct k
 	unlock_hpte(hptep, hpte[0]);
 	preempt_enable();
 
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		hpte[0] = hpte_new_to_old_v(hpte[0], hpte[1]);
+		hpte[1] = hpte_new_to_old_r(hpte[1]);
+	}
 	if (hpte[0] != vcpu->arch.pgfault_hpte[0] ||
 	    hpte[1] != vcpu->arch.pgfault_hpte[1])
 		return RESUME_GUEST;
@@ -575,16 +598,22 @@ int kvmppc_book3s_hv_page_fault(struct k
 	 */
 	if (psize < PAGE_SIZE)
 		psize = PAGE_SIZE;
-	r = (r & ~(HPTE_R_PP0 - psize)) | ((pfn << PAGE_SHIFT) & ~(psize - 1));
+	r = (r & HPTE_R_KEY_HI) | (r & ~(HPTE_R_PP0 - psize)) |
+					((pfn << PAGE_SHIFT) & ~(psize - 1));
 	if (hpte_is_writable(r) && !write_ok)
 		r = hpte_make_readonly(r);
 	ret = RESUME_GUEST;
 	preempt_disable();
 	while (!try_lock_hpte(hptep, HPTE_V_HVLOCK))
 		cpu_relax();
-	if ((be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK) != hpte[0] ||
-		be64_to_cpu(hptep[1]) != hpte[1] ||
-		rev->guest_rpte != hpte[2])
+	hnow_v = be64_to_cpu(hptep[0]);
+	hnow_r = be64_to_cpu(hptep[1]);
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		hnow_v = hpte_new_to_old_v(hnow_v, hnow_r);
+		hnow_r = hpte_new_to_old_r(hnow_r);
+	}
+	if ((hnow_v & ~HPTE_V_HVLOCK) != hpte[0] || hnow_r != hpte[1] ||
+	    rev->guest_rpte != hpte[2])
 		/* HPTE has been changed under us; let the guest retry */
 		goto out_unlock;
 	hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID;
@@ -615,6 +644,10 @@ int kvmppc_book3s_hv_page_fault(struct k
 		kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0);
 	}
 
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		r = hpte_old_to_new_r(hpte[0], r);
+		hpte[0] = hpte_old_to_new_v(hpte[0]);
+	}
 	hptep[1] = cpu_to_be64(r);
 	eieio();
 	__unlock_hpte(hptep, hpte[0]);
@@ -758,6 +791,7 @@ static int kvm_unmap_rmapp(struct kvm *k
 		    hpte_rpn(ptel, psize) == gfn) {
 			hptep[0] |= cpu_to_be64(HPTE_V_ABSENT);
 			kvmppc_invalidate_hpte(kvm, hptep, i);
+			hptep[1] &= ~cpu_to_be64(HPTE_R_KEY_HI | HPTE_R_KEY_LO);
 			/* Harvest R and C */
 			rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C);
 			*rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT;
@@ -1165,7 +1199,7 @@ static long record_hpte(unsigned long fl
 			unsigned long *hpte, struct revmap_entry *revp,
 			int want_valid, int first_pass)
 {
-	unsigned long v, r;
+	unsigned long v, r, hr;
 	unsigned long rcbits_unset;
 	int ok = 1;
 	int valid, dirty;
@@ -1192,6 +1226,11 @@ static long record_hpte(unsigned long fl
 		while (!try_lock_hpte(hptp, HPTE_V_HVLOCK))
 			cpu_relax();
 		v = be64_to_cpu(hptp[0]);
+		hr = be64_to_cpu(hptp[1]);
+		if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+			v = hpte_new_to_old_v(v, hr);
+			hr = hpte_new_to_old_r(hr);
+		}
 
 		/* re-evaluate valid and dirty from synchronized HPTE value */
 		valid = !!(v & HPTE_V_VALID);
@@ -1199,8 +1238,8 @@ static long record_hpte(unsigned long fl
 
 		/* Harvest R and C into guest view if necessary */
 		rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C);
-		if (valid && (rcbits_unset & be64_to_cpu(hptp[1]))) {
-			revp->guest_rpte |= (be64_to_cpu(hptp[1]) &
+		if (valid && (rcbits_unset & hr)) {
+			revp->guest_rpte |= (hr &
 				(HPTE_R_R | HPTE_R_C)) | HPTE_GR_MODIFIED;
 			dirty = 1;
 		}
@@ -1608,7 +1647,7 @@ static ssize_t debugfs_htab_read(struct
 	return ret;
 }
 
-ssize_t debugfs_htab_write(struct file *file, const char __user *buf,
+static ssize_t debugfs_htab_write(struct file *file, const char __user *buf,
 			   size_t len, loff_t *ppos)
 {
 	return -EACCES;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_64_vio_hv.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_64_vio_hv.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_64_vio_hv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_64_vio_hv.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,6 @@
 #include <asm/udbg.h>
 #include <asm/iommu.h>
 #include <asm/tce.h>
-#include <asm/iommu.h>
 
 #define TCES_PER_PAGE	(PAGE_SIZE / sizeof(u64))
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <asm/cputable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_builtin.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_builtin.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_builtin.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_builtin.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,8 @@
 #include <asm/dbell.h>
 #include <asm/cputhreads.h>
 #include <asm/io.h>
+#include <asm/opal.h>
+#include <asm/smp.h>
 
 #define KVM_CMA_CHUNK_ORDER	18
 
@@ -205,12 +207,18 @@ static inline void rm_writeb(unsigned lo
 void kvmhv_rm_send_ipi(int cpu)
 {
 	unsigned long xics_phys;
+	unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
 
-	/* On POWER8 for IPIs to threads in the same core, use msgsnd */
+	/* On POWER9 we can use msgsnd for any destination cpu. */
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		msg |= get_hard_smp_processor_id(cpu);
+		__asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
+		return;
+	}
+	/* On POWER8 for IPIs to threads in the same core, use msgsnd. */
 	if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
 	    cpu_first_thread_sibling(cpu) ==
 	    cpu_first_thread_sibling(raw_smp_processor_id())) {
-		unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
 		msg |= cpu_thread_in_core(cpu);
 		__asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
 		return;
@@ -218,7 +226,11 @@ void kvmhv_rm_send_ipi(int cpu)
 
 	/* Else poke the target with an IPI */
 	xics_phys = paca[cpu].kvm_hstate.xics_phys;
-	rm_writeb(xics_phys + XICS_MFRR, IPI_PRIORITY);
+	if (xics_phys)
+		rm_writeb(xics_phys + XICS_MFRR, IPI_PRIORITY);
+	else
+		opal_rm_int_set_mfrr(get_hard_smp_processor_id(cpu),
+				     IPI_PRIORITY);
 }
 
 /*
@@ -329,7 +341,7 @@ static struct kvmppc_irq_map *get_irqmap
  * saved a copy of the XIRR in the PACA, it will be picked up by
  * the host ICP driver.
  */
-static int kvmppc_check_passthru(u32 xisr, __be32 xirr)
+static int kvmppc_check_passthru(u32 xisr, __be32 xirr, bool *again)
 {
 	struct kvmppc_passthru_irqmap *pimap;
 	struct kvmppc_irq_map *irq_map;
@@ -348,11 +360,11 @@ static int kvmppc_check_passthru(u32 xis
 	/* We're handling this interrupt, generic code doesn't need to */
 	local_paca->kvm_hstate.saved_xirr = 0;
 
-	return kvmppc_deliver_irq_passthru(vcpu, xirr, irq_map, pimap);
+	return kvmppc_deliver_irq_passthru(vcpu, xirr, irq_map, pimap, again);
 }
 
 #else
-static inline int kvmppc_check_passthru(u32 xisr, __be32 xirr)
+static inline int kvmppc_check_passthru(u32 xisr, __be32 xirr, bool *again)
 {
 	return 1;
 }
@@ -367,14 +379,31 @@ static inline int kvmppc_check_passthru(
  *	-1 if there was a guest wakeup IPI (which has now been cleared)
  *	-2 if there is PCI passthrough external interrupt that was handled
  */
+static long kvmppc_read_one_intr(bool *again);
 
 long kvmppc_read_intr(void)
 {
+	long ret = 0;
+	long rc;
+	bool again;
+
+	do {
+		again = false;
+		rc = kvmppc_read_one_intr(&again);
+		if (rc && (ret == 0 || rc > ret))
+			ret = rc;
+	} while (again);
+	return ret;
+}
+
+static long kvmppc_read_one_intr(bool *again)
+{
 	unsigned long xics_phys;
 	u32 h_xirr;
 	__be32 xirr;
 	u32 xisr;
 	u8 host_ipi;
+	int64_t rc;
 
 	/* see if a host IPI is pending */
 	host_ipi = local_paca->kvm_hstate.host_ipi;
@@ -383,8 +412,14 @@ long kvmppc_read_intr(void)
 
 	/* Now read the interrupt from the ICP */
 	xics_phys = local_paca->kvm_hstate.xics_phys;
-	if (unlikely(!xics_phys))
-		return 1;
+	if (!xics_phys) {
+		/* Use OPAL to read the XIRR */
+		rc = opal_rm_int_get_xirr(&xirr, false);
+		if (rc < 0)
+			return 1;
+	} else {
+		xirr = _lwzcix(xics_phys + XICS_XIRR);
+	}
 
 	/*
 	 * Save XIRR for later. Since we get control in reverse endian
@@ -392,7 +427,6 @@ long kvmppc_read_intr(void)
 	 * host endian. Note that xirr is the value read from the
 	 * XIRR register, while h_xirr is the host endian version.
 	 */
-	xirr = _lwzcix(xics_phys + XICS_XIRR);
 	h_xirr = be32_to_cpu(xirr);
 	local_paca->kvm_hstate.saved_xirr = h_xirr;
 	xisr = h_xirr & 0xffffff;
@@ -411,8 +445,16 @@ long kvmppc_read_intr(void)
 	 * If it is an IPI, clear the MFRR and EOI it.
 	 */
 	if (xisr == XICS_IPI) {
-		_stbcix(xics_phys + XICS_MFRR, 0xff);
-		_stwcix(xics_phys + XICS_XIRR, xirr);
+		if (xics_phys) {
+			_stbcix(xics_phys + XICS_MFRR, 0xff);
+			_stwcix(xics_phys + XICS_XIRR, xirr);
+		} else {
+			opal_rm_int_set_mfrr(hard_smp_processor_id(), 0xff);
+			rc = opal_rm_int_eoi(h_xirr);
+			/* If rc > 0, there is another interrupt pending */
+			*again = rc > 0;
+		}
+
 		/*
 		 * Need to ensure side effects of above stores
 		 * complete before proceeding.
@@ -429,7 +471,11 @@ long kvmppc_read_intr(void)
 			/* We raced with the host,
 			 * we need to resend that IPI, bummer
 			 */
-			_stbcix(xics_phys + XICS_MFRR, IPI_PRIORITY);
+			if (xics_phys)
+				_stbcix(xics_phys + XICS_MFRR, IPI_PRIORITY);
+			else
+				opal_rm_int_set_mfrr(hard_smp_processor_id(),
+						     IPI_PRIORITY);
 			/* Let side effects complete */
 			smp_mb();
 			return 1;
@@ -440,5 +486,5 @@ long kvmppc_read_intr(void)
 		return -1;
 	}
 
-	return kvmppc_check_passthru(xisr, xirr);
+	return kvmppc_check_passthru(xisr, xirr, again);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@
 #include <asm/cputable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
@@ -54,6 +54,9 @@
 #include <asm/dbell.h>
 #include <asm/hmi.h>
 #include <asm/pnv-pci.h>
+#include <asm/mmu.h>
+#include <asm/opal.h>
+#include <asm/xics.h>
 #include <linux/gfp.h>
 #include <linux/vmalloc.h>
 #include <linux/highmem.h>
@@ -62,6 +65,7 @@
 #include <linux/irqbypass.h>
 #include <linux/module.h>
 #include <linux/compiler.h>
+#include <linux/of.h>
 
 #include "book3s.h"
 
@@ -104,23 +108,6 @@ module_param_cb(h_ipi_redirect, &module_
 MODULE_PARM_DESC(h_ipi_redirect, "Redirect H_IPI wakeup to a free host core");
 #endif
 
-/* Maximum halt poll interval defaults to KVM_HALT_POLL_NS_DEFAULT */
-static unsigned int halt_poll_max_ns = KVM_HALT_POLL_NS_DEFAULT;
-module_param(halt_poll_max_ns, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(halt_poll_max_ns, "Maximum halt poll time in ns");
-
-/* Factor by which the vcore halt poll interval is grown, default is to double
- */
-static unsigned int halt_poll_ns_grow = 2;
-module_param(halt_poll_ns_grow, int, S_IRUGO);
-MODULE_PARM_DESC(halt_poll_ns_grow, "Factor halt poll time is grown by");
-
-/* Factor by which the vcore halt poll interval is shrunk, default is to reset
- */
-static unsigned int halt_poll_ns_shrink;
-module_param(halt_poll_ns_shrink, int, S_IRUGO);
-MODULE_PARM_DESC(halt_poll_ns_shrink, "Factor halt poll time is shrunk by");
-
 static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
 
@@ -146,12 +133,21 @@ static inline struct kvm_vcpu *next_runn
 
 static bool kvmppc_ipi_thread(int cpu)
 {
+	unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
+
+	/* On POWER9 we can use msgsnd to IPI any cpu */
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		msg |= get_hard_smp_processor_id(cpu);
+		smp_mb();
+		__asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
+		return true;
+	}
+
 	/* On POWER8 for IPIs to threads in the same core, use msgsnd */
 	if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
 		preempt_disable();
 		if (cpu_first_thread_sibling(cpu) ==
 		    cpu_first_thread_sibling(smp_processor_id())) {
-			unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
 			msg |= cpu_thread_in_core(cpu);
 			smp_mb();
 			__asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
@@ -162,8 +158,12 @@ static bool kvmppc_ipi_thread(int cpu)
 	}
 
 #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
-	if (cpu >= 0 && cpu < nr_cpu_ids && paca[cpu].kvm_hstate.xics_phys) {
-		xics_wake_cpu(cpu);
+	if (cpu >= 0 && cpu < nr_cpu_ids) {
+		if (paca[cpu].kvm_hstate.xics_phys) {
+			xics_wake_cpu(cpu);
+			return true;
+		}
+		opal_int_set_mfrr(get_hard_smp_processor_id(cpu), IPI_PRIORITY);
 		return true;
 	}
 #endif
@@ -299,41 +299,54 @@ static void kvmppc_set_pvr_hv(struct kvm
 	vcpu->arch.pvr = pvr;
 }
 
+/* Dummy value used in computing PCR value below */
+#define PCR_ARCH_300	(PCR_ARCH_207 << 1)
+
 static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
 {
-	unsigned long pcr = 0;
+	unsigned long host_pcr_bit = 0, guest_pcr_bit = 0;
 	struct kvmppc_vcore *vc = vcpu->arch.vcore;
 
+	/* We can (emulate) our own architecture version and anything older */
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		host_pcr_bit = PCR_ARCH_300;
+	else if (cpu_has_feature(CPU_FTR_ARCH_207S))
+		host_pcr_bit = PCR_ARCH_207;
+	else if (cpu_has_feature(CPU_FTR_ARCH_206))
+		host_pcr_bit = PCR_ARCH_206;
+	else
+		host_pcr_bit = PCR_ARCH_205;
+
+	/* Determine lowest PCR bit needed to run guest in given PVR level */
+	guest_pcr_bit = host_pcr_bit;
 	if (arch_compat) {
 		switch (arch_compat) {
 		case PVR_ARCH_205:
-			/*
-			 * If an arch bit is set in PCR, all the defined
-			 * higher-order arch bits also have to be set.
-			 */
-			pcr = PCR_ARCH_206 | PCR_ARCH_205;
+			guest_pcr_bit = PCR_ARCH_205;
 			break;
 		case PVR_ARCH_206:
 		case PVR_ARCH_206p:
-			pcr = PCR_ARCH_206;
+			guest_pcr_bit = PCR_ARCH_206;
 			break;
 		case PVR_ARCH_207:
+			guest_pcr_bit = PCR_ARCH_207;
+			break;
+		case PVR_ARCH_300:
+			guest_pcr_bit = PCR_ARCH_300;
 			break;
 		default:
 			return -EINVAL;
 		}
-
-		if (!cpu_has_feature(CPU_FTR_ARCH_207S)) {
-			/* POWER7 can't emulate POWER8 */
-			if (!(pcr & PCR_ARCH_206))
-				return -EINVAL;
-			pcr &= ~PCR_ARCH_206;
-		}
 	}
 
+	/* Check requested PCR bits don't exceed our capabilities */
+	if (guest_pcr_bit > host_pcr_bit)
+		return -EINVAL;
+
 	spin_lock(&vc->lock);
 	vc->arch_compat = arch_compat;
-	vc->pcr = pcr;
+	/* Set all PCR bits for which guest_pcr_bit <= bit < host_pcr_bit */
+	vc->pcr = host_pcr_bit - guest_pcr_bit;
 	spin_unlock(&vc->lock);
 
 	return 0;
@@ -945,6 +958,7 @@ static int kvmppc_handle_exit_hv(struct
 		break;
 	case BOOK3S_INTERRUPT_EXTERNAL:
 	case BOOK3S_INTERRUPT_H_DOORBELL:
+	case BOOK3S_INTERRUPT_H_VIRT:
 		vcpu->stat.ext_intr_exits++;
 		r = RESUME_GUEST;
 		break;
@@ -1229,6 +1243,12 @@ static int kvmppc_get_one_reg_hv(struct
 	case KVM_REG_PPC_WORT:
 		*val = get_reg_val(id, vcpu->arch.wort);
 		break;
+	case KVM_REG_PPC_TIDR:
+		*val = get_reg_val(id, vcpu->arch.tid);
+		break;
+	case KVM_REG_PPC_PSSCR:
+		*val = get_reg_val(id, vcpu->arch.psscr);
+		break;
 	case KVM_REG_PPC_VPA_ADDR:
 		spin_lock(&vcpu->arch.vpa_update_lock);
 		*val = get_reg_val(id, vcpu->arch.vpa.next_gpa);
@@ -1288,6 +1308,9 @@ static int kvmppc_get_one_reg_hv(struct
 	case KVM_REG_PPC_TM_CR:
 		*val = get_reg_val(id, vcpu->arch.cr_tm);
 		break;
+	case KVM_REG_PPC_TM_XER:
+		*val = get_reg_val(id, vcpu->arch.xer_tm);
+		break;
 	case KVM_REG_PPC_TM_LR:
 		*val = get_reg_val(id, vcpu->arch.lr_tm);
 		break;
@@ -1427,6 +1450,12 @@ static int kvmppc_set_one_reg_hv(struct
 	case KVM_REG_PPC_WORT:
 		vcpu->arch.wort = set_reg_val(id, *val);
 		break;
+	case KVM_REG_PPC_TIDR:
+		vcpu->arch.tid = set_reg_val(id, *val);
+		break;
+	case KVM_REG_PPC_PSSCR:
+		vcpu->arch.psscr = set_reg_val(id, *val) & PSSCR_GUEST_VIS;
+		break;
 	case KVM_REG_PPC_VPA_ADDR:
 		addr = set_reg_val(id, *val);
 		r = -EINVAL;
@@ -1498,6 +1527,9 @@ static int kvmppc_set_one_reg_hv(struct
 	case KVM_REG_PPC_TM_CR:
 		vcpu->arch.cr_tm = set_reg_val(id, *val);
 		break;
+	case KVM_REG_PPC_TM_XER:
+		vcpu->arch.xer_tm = set_reg_val(id, *val);
+		break;
 	case KVM_REG_PPC_TM_LR:
 		vcpu->arch.lr_tm = set_reg_val(id, *val);
 		break;
@@ -1540,6 +1572,20 @@ static int kvmppc_set_one_reg_hv(struct
 	return r;
 }
 
+/*
+ * On POWER9, threads are independent and can be in different partitions.
+ * Therefore we consider each thread to be a subcore.
+ * There is a restriction that all threads have to be in the same
+ * MMU mode (radix or HPT), unfortunately, but since we only support
+ * HPT guests on a HPT host so far, that isn't an impediment yet.
+ */
+static int threads_per_vcore(void)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		return 1;
+	return threads_per_subcore;
+}
+
 static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
 {
 	struct kvmppc_vcore *vcore;
@@ -1554,7 +1600,7 @@ static struct kvmppc_vcore *kvmppc_vcore
 	init_swait_queue_head(&vcore->wq);
 	vcore->preempt_tb = TB_NIL;
 	vcore->lpcr = kvm->arch.lpcr;
-	vcore->first_vcpuid = core * threads_per_subcore;
+	vcore->first_vcpuid = core * threads_per_vcore();
 	vcore->kvm = kvm;
 	INIT_LIST_HEAD(&vcore->preempt_list);
 
@@ -1717,7 +1763,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu
 	int core;
 	struct kvmppc_vcore *vcore;
 
-	core = id / threads_per_subcore;
+	core = id / threads_per_vcore();
 	if (core >= KVM_MAX_VCORES)
 		goto out;
 
@@ -1826,8 +1872,7 @@ static void kvmppc_set_timer(struct kvm_
 	}
 	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);
+	hrtimer_start(&vcpu->arch.dec_timer, dec_nsec, HRTIMER_MODE_REL);
 	vcpu->arch.timer_running = 1;
 }
 
@@ -1935,7 +1980,10 @@ static void kvmppc_wait_for_nap(void)
 {
 	int cpu = smp_processor_id();
 	int i, loops;
+	int n_threads = threads_per_vcore();
 
+	if (n_threads <= 1)
+		return;
 	for (loops = 0; loops < 1000000; ++loops) {
 		/*
 		 * Check if all threads are finished.
@@ -1943,17 +1991,17 @@ static void kvmppc_wait_for_nap(void)
 		 * and the thread clears it when finished, so we look
 		 * for any threads that still have a non-NULL vcore ptr.
 		 */
-		for (i = 1; i < threads_per_subcore; ++i)
+		for (i = 1; i < n_threads; ++i)
 			if (paca[cpu + i].kvm_hstate.kvm_vcore)
 				break;
-		if (i == threads_per_subcore) {
+		if (i == n_threads) {
 			HMT_medium();
 			return;
 		}
 		HMT_low();
 	}
 	HMT_medium();
-	for (i = 1; i < threads_per_subcore; ++i)
+	for (i = 1; i < n_threads; ++i)
 		if (paca[cpu + i].kvm_hstate.kvm_vcore)
 			pr_err("KVM: CPU %d seems to be stuck\n", cpu + i);
 }
@@ -2019,7 +2067,7 @@ static void kvmppc_vcore_preempt(struct
 
 	vc->vcore_state = VCORE_PREEMPT;
 	vc->pcpu = smp_processor_id();
-	if (vc->num_threads < threads_per_subcore) {
+	if (vc->num_threads < threads_per_vcore()) {
 		spin_lock(&lp->lock);
 		list_add_tail(&vc->preempt_list, &lp->list);
 		spin_unlock(&lp->lock);
@@ -2123,8 +2171,7 @@ static bool can_dynamic_split(struct kvm
 	cip->subcore_threads[sub] = vc->num_threads;
 	cip->subcore_vm[sub] = vc->kvm;
 	init_master_vcore(vc);
-	list_del(&vc->preempt_list);
-	list_add_tail(&vc->preempt_list, &cip->vcs[sub]);
+	list_move_tail(&vc->preempt_list, &cip->vcs[sub]);
 
 	return true;
 }
@@ -2254,12 +2301,12 @@ static void post_guest_process(struct kv
  * enter the guest. Only do this if it is the primary thread of the
  * core (not if a subcore) that is entering the guest.
  */
-static inline void kvmppc_clear_host_core(int cpu)
+static inline int kvmppc_clear_host_core(unsigned int cpu)
 {
 	int core;
 
 	if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu))
-		return;
+		return 0;
 	/*
 	 * Memory barrier can be omitted here as we will do a smp_wmb()
 	 * later in kvmppc_start_thread and we need ensure that state is
@@ -2267,6 +2314,7 @@ static inline void kvmppc_clear_host_cor
 	 */
 	core = cpu >> threads_shift;
 	kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 0;
+	return 0;
 }
 
 /*
@@ -2274,12 +2322,12 @@ static inline void kvmppc_clear_host_cor
  * Only need to do this if it is the primary thread of the core that is
  * exiting.
  */
-static inline void kvmppc_set_host_core(int cpu)
+static inline int kvmppc_set_host_core(unsigned int cpu)
 {
 	int core;
 
 	if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu))
-		return;
+		return 0;
 
 	/*
 	 * Memory barrier can be omitted here because we do a spin_unlock
@@ -2287,6 +2335,7 @@ static inline void kvmppc_set_host_core(
 	 */
 	core = cpu >> threads_shift;
 	kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 1;
+	return 0;
 }
 
 /*
@@ -2307,6 +2356,7 @@ static noinline void kvmppc_run_core(str
 	unsigned long cmd_bit, stat_bit;
 	int pcpu, thr;
 	int target_threads;
+	int controlled_threads;
 
 	/*
 	 * Remove from the list any threads that have a signal pending
@@ -2325,11 +2375,18 @@ static noinline void kvmppc_run_core(str
 	vc->preempt_tb = TB_NIL;
 
 	/*
+	 * Number of threads that we will be controlling: the same as
+	 * the number of threads per subcore, except on POWER9,
+	 * where it's 1 because the threads are (mostly) independent.
+	 */
+	controlled_threads = threads_per_vcore();
+
+	/*
 	 * Make sure we are running on primary threads, and that secondary
 	 * threads are offline.  Also check if the number of threads in this
 	 * guest are greater than the current system threads per guest.
 	 */
-	if ((threads_per_core > 1) &&
+	if ((controlled_threads > 1) &&
 	    ((vc->num_threads > threads_per_subcore) || !on_primary_thread())) {
 		for_each_runnable_thread(i, vcpu, vc) {
 			vcpu->arch.ret = -EBUSY;
@@ -2345,7 +2402,7 @@ static noinline void kvmppc_run_core(str
 	 */
 	init_core_info(&core_info, vc);
 	pcpu = smp_processor_id();
-	target_threads = threads_per_subcore;
+	target_threads = controlled_threads;
 	if (target_smt_mode && target_smt_mode < target_threads)
 		target_threads = target_smt_mode;
 	if (vc->num_threads < target_threads)
@@ -2381,7 +2438,7 @@ static noinline void kvmppc_run_core(str
 		smp_wmb();
 	}
 	pcpu = smp_processor_id();
-	for (thr = 0; thr < threads_per_subcore; ++thr)
+	for (thr = 0; thr < controlled_threads; ++thr)
 		paca[pcpu + thr].kvm_hstate.kvm_split_mode = sip;
 
 	/* Initiate micro-threading (split-core) if required */
@@ -2491,7 +2548,7 @@ static noinline void kvmppc_run_core(str
 	}
 
 	/* Let secondaries go back to the offline loop */
-	for (i = 0; i < threads_per_subcore; ++i) {
+	for (i = 0; i < controlled_threads; ++i) {
 		kvmppc_release_hwthread(pcpu + i);
 		if (sip && sip->napped[i])
 			kvmppc_ipi_thread(pcpu + i);
@@ -2543,9 +2600,6 @@ static void grow_halt_poll_ns(struct kvm
 		vc->halt_poll_ns = 10000;
 	else
 		vc->halt_poll_ns *= halt_poll_ns_grow;
-
-	if (vc->halt_poll_ns > halt_poll_max_ns)
-		vc->halt_poll_ns = halt_poll_max_ns;
 }
 
 static void shrink_halt_poll_ns(struct kvmppc_vcore *vc)
@@ -2556,7 +2610,8 @@ static void shrink_halt_poll_ns(struct k
 		vc->halt_poll_ns /= halt_poll_ns_shrink;
 }
 
-/* Check to see if any of the runnable vcpus on the vcore have pending
+/*
+ * Check to see if any of the runnable vcpus on the vcore have pending
  * exceptions or are no longer ceded
  */
 static int kvmppc_vcore_check_block(struct kvmppc_vcore *vc)
@@ -2655,16 +2710,18 @@ out:
 	}
 
 	/* Adjust poll time */
-	if (halt_poll_max_ns) {
+	if (halt_poll_ns) {
 		if (block_ns <= vc->halt_poll_ns)
 			;
 		/* We slept and blocked for longer than the max halt time */
-		else if (vc->halt_poll_ns && block_ns > halt_poll_max_ns)
+		else if (vc->halt_poll_ns && block_ns > halt_poll_ns)
 			shrink_halt_poll_ns(vc);
 		/* We slept and our poll time is too small */
-		else if (vc->halt_poll_ns < halt_poll_max_ns &&
-				block_ns < halt_poll_max_ns)
+		else if (vc->halt_poll_ns < halt_poll_ns &&
+				block_ns < halt_poll_ns)
 			grow_halt_poll_ns(vc);
+		if (vc->halt_poll_ns > halt_poll_ns)
+			vc->halt_poll_ns = halt_poll_ns;
 	} else
 		vc->halt_poll_ns = 0;
 
@@ -2971,6 +3028,15 @@ static void kvmppc_core_commit_memory_re
 	struct kvm_memslots *slots;
 	struct kvm_memory_slot *memslot;
 
+	/*
+	 * If we are making a new memslot, it might make
+	 * some address that was previously cached as emulated
+	 * MMIO be no longer emulated MMIO, so invalidate
+	 * all the caches of emulated MMIO translations.
+	 */
+	if (npages)
+		atomic64_inc(&kvm->arch.mmio_update);
+
 	if (npages && old->npages) {
 		/*
 		 * If modifying a memslot, reset all the rmap dirty bits.
@@ -3015,6 +3081,22 @@ static void kvmppc_mmu_destroy_hv(struct
 	return;
 }
 
+static void kvmppc_setup_partition_table(struct kvm *kvm)
+{
+	unsigned long dw0, dw1;
+
+	/* PS field - page size for VRMA */
+	dw0 = ((kvm->arch.vrma_slb_v & SLB_VSID_L) >> 1) |
+		((kvm->arch.vrma_slb_v & SLB_VSID_LP) << 1);
+	/* HTABSIZE and HTABORG fields */
+	dw0 |= kvm->arch.sdr1;
+
+	/* Second dword has GR=0; other fields are unused since UPRT=0 */
+	dw1 = 0;
+
+	mmu_partition_table_set_entry(kvm->arch.lpid, dw0, dw1);
+}
+
 static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu)
 {
 	int err = 0;
@@ -3066,17 +3148,20 @@ static int kvmppc_hv_setup_htab_rma(stru
 	      psize == 0x1000000))
 		goto out_srcu;
 
-	/* Update VRMASD field in the LPCR */
 	senc = slb_pgsize_encoding(psize);
 	kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T |
 		(VRMA_VSID << SLB_VSID_SHIFT_1T);
-	/* the -4 is to account for senc values starting at 0x10 */
-	lpcr = senc << (LPCR_VRMASD_SH - 4);
-
 	/* Create HPTEs in the hash page table for the VRMA */
 	kvmppc_map_vrma(vcpu, memslot, porder);
 
-	kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD);
+	/* Update VRMASD field in the LPCR */
+	if (!cpu_has_feature(CPU_FTR_ARCH_300)) {
+		/* the -4 is to account for senc values starting at 0x10 */
+		lpcr = senc << (LPCR_VRMASD_SH - 4);
+		kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD);
+	} else {
+		kvmppc_setup_partition_table(kvm);
+	}
 
 	/* Order updates to kvm->arch.lpcr etc. vs. hpte_setup_done */
 	smp_wmb();
@@ -3094,36 +3179,6 @@ static int kvmppc_hv_setup_htab_rma(stru
 }
 
 #ifdef CONFIG_KVM_XICS
-static int kvmppc_cpu_notify(struct notifier_block *self, unsigned long action,
-			void *hcpu)
-{
-	unsigned long cpu = (long)hcpu;
-
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		kvmppc_set_host_core(cpu);
-		break;
-
-#ifdef CONFIG_HOTPLUG_CPU
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-		kvmppc_clear_host_core(cpu);
-		break;
-#endif
-	default:
-		break;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block kvmppc_cpu_notifier = {
-	    .notifier_call = kvmppc_cpu_notify,
-};
-
 /*
  * Allocate a per-core structure for managing state about which cores are
  * running in the host versus the guest and for exchanging data between
@@ -3185,15 +3240,17 @@ void kvmppc_alloc_host_rm_ops(void)
 		return;
 	}
 
-	register_cpu_notifier(&kvmppc_cpu_notifier);
-
+	cpuhp_setup_state_nocalls(CPUHP_KVM_PPC_BOOK3S_PREPARE,
+				  "ppc/kvm_book3s:prepare",
+				  kvmppc_set_host_core,
+				  kvmppc_clear_host_core);
 	put_online_cpus();
 }
 
 void kvmppc_free_host_rm_ops(void)
 {
 	if (kvmppc_host_rm_ops_hv) {
-		unregister_cpu_notifier(&kvmppc_cpu_notifier);
+		cpuhp_remove_state_nocalls(CPUHP_KVM_PPC_BOOK3S_PREPARE);
 		kfree(kvmppc_host_rm_ops_hv->rm_core);
 		kfree(kvmppc_host_rm_ops_hv);
 		kvmppc_host_rm_ops_hv = NULL;
@@ -3219,14 +3276,18 @@ static int kvmppc_core_init_vm_hv(struct
 	 * Since we don't flush the TLB when tearing down a VM,
 	 * and this lpid might have previously been used,
 	 * make sure we flush on each core before running the new VM.
+	 * On POWER9, the tlbie in mmu_partition_table_set_entry()
+	 * does this flush for us.
 	 */
-	cpumask_setall(&kvm->arch.need_tlb_flush);
+	if (!cpu_has_feature(CPU_FTR_ARCH_300))
+		cpumask_setall(&kvm->arch.need_tlb_flush);
 
 	/* Start out with the default set of hcalls enabled */
 	memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls,
 	       sizeof(kvm->arch.enabled_hcalls));
 
-	kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
+	if (!cpu_has_feature(CPU_FTR_ARCH_300))
+		kvm->arch.host_sdr1 = mfspr(SPRN_SDR1);
 
 	/* Init LPCR for virtual RMA mode */
 	kvm->arch.host_lpid = mfspr(SPRN_LPID);
@@ -3239,9 +3300,29 @@ static int kvmppc_core_init_vm_hv(struct
 	/* On POWER8 turn on online bit to enable PURR/SPURR */
 	if (cpu_has_feature(CPU_FTR_ARCH_207S))
 		lpcr |= LPCR_ONL;
+	/*
+	 * On POWER9, VPM0 bit is reserved (VPM0=1 behaviour is assumed)
+	 * Set HVICE bit to enable hypervisor virtualization interrupts.
+	 */
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		lpcr &= ~LPCR_VPM0;
+		lpcr |= LPCR_HVICE;
+	}
+
 	kvm->arch.lpcr = lpcr;
 
 	/*
+	 * Work out how many sets the TLB has, for the use of
+	 * the TLB invalidation loop in book3s_hv_rmhandlers.S.
+	 */
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		kvm->arch.tlb_sets = POWER9_TLB_SETS_HASH;	/* 256 */
+	else if (cpu_has_feature(CPU_FTR_ARCH_207S))
+		kvm->arch.tlb_sets = POWER8_TLB_SETS;		/* 512 */
+	else
+		kvm->arch.tlb_sets = POWER7_TLB_SETS;		/* 128 */
+
+	/*
 	 * Track that we now have a HV mode VM active. This blocks secondary
 	 * CPU threads from coming online.
 	 */
@@ -3305,9 +3386,9 @@ static int kvmppc_core_check_processor_c
 	    !cpu_has_feature(CPU_FTR_ARCH_206))
 		return -EIO;
 	/*
-	 * Disable KVM for Power9, untill the required bits merged.
+	 * Disable KVM for Power9 in radix mode.
 	 */
-	if (cpu_has_feature(CPU_FTR_ARCH_300))
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && radix_enabled())
 		return -EIO;
 
 	return 0;
@@ -3661,6 +3742,23 @@ static int kvmppc_book3s_init_hv(void)
 	if (r)
 		return r;
 
+	/*
+	 * We need a way of accessing the XICS interrupt controller,
+	 * either directly, via paca[cpu].kvm_hstate.xics_phys, or
+	 * indirectly, via OPAL.
+	 */
+#ifdef CONFIG_SMP
+	if (!get_paca()->kvm_hstate.xics_phys) {
+		struct device_node *np;
+
+		np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc");
+		if (!np) {
+			pr_err("KVM-HV: Cannot determine method for accessing XICS\n");
+			return -ENODEV;
+		}
+	}
+#endif
+
 	kvm_ops_hv.owner = THIS_MODULE;
 	kvmppc_hv_ops = &kvm_ops_hv;
 
@@ -3683,3 +3781,4 @@ module_exit(kvmppc_book3s_exit_hv);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(KVM_MINOR);
 MODULE_ALIAS("devname:kvm");
+
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_ras.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_ras.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_ras.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_ras.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 #include <asm/machdep.h>
 #include <asm/cputhreads.h>
 #include <asm/hmi.h>
+#include <asm/kvm_ppc.h>
 
 /* SRR1 bits for machine check on POWER7 */
 #define SRR1_MC_LDSTERR		(1ul << (63-42))
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_rmhandlers.S	2017-02-12 16:03:20.000000000 -0500
@@ -501,17 +501,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	cmpwi	r0, 0
 	beq	57f
 	li	r3, (LPCR_PECEDH | LPCR_PECE0) >> 4
-	mfspr	r4, SPRN_LPCR
-	rlwimi	r4, r3, 4, (LPCR_PECEDP | LPCR_PECEDH | LPCR_PECE0 | LPCR_PECE1)
-	mtspr	SPRN_LPCR, r4
-	isync
-	std	r0, HSTATE_SCRATCH0(r13)
-	ptesync
-	ld	r0, HSTATE_SCRATCH0(r13)
-1:	cmpd	r0, r0
-	bne	1b
-	nap
-	b	.
+	mfspr	r5, SPRN_LPCR
+	rlwimi	r5, r3, 4, (LPCR_PECEDP | LPCR_PECEDH | LPCR_PECE0 | LPCR_PECE1)
+	b	kvm_nap_sequence
 
 57:	li	r0, 0
 	stbx	r0, r3, r4
@@ -523,6 +515,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
  *                                                                            *
  *****************************************************************************/
 
+/* Stack frame offsets */
+#define STACK_SLOT_TID		(112-16)
+#define STACK_SLOT_PSSCR	(112-24)
+
 .global kvmppc_hv_entry
 kvmppc_hv_entry:
 
@@ -581,12 +577,14 @@ kvmppc_hv_entry:
 	ld	r9,VCORE_KVM(r5)	/* pointer to struct kvm */
 	cmpwi	r6,0
 	bne	10f
-	ld	r6,KVM_SDR1(r9)
 	lwz	r7,KVM_LPID(r9)
+BEGIN_FTR_SECTION
+	ld	r6,KVM_SDR1(r9)
 	li	r0,LPID_RSVD		/* switch to reserved LPID */
 	mtspr	SPRN_LPID,r0
 	ptesync
 	mtspr	SPRN_SDR1,r6		/* switch to partition page table */
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
 	mtspr	SPRN_LPID,r7
 	isync
 
@@ -607,12 +605,8 @@ kvmppc_hv_entry:
 	stdcx.	r7,0,r6
 	bne	23b
 	/* Flush the TLB of any entries for this LPID */
-	/* use arch 2.07S as a proxy for POWER8 */
-BEGIN_FTR_SECTION
-	li	r6,512			/* POWER8 has 512 sets */
-FTR_SECTION_ELSE
-	li	r6,128			/* POWER7 has 128 sets */
-ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_207S)
+	lwz	r6,KVM_TLB_SETS(r9)
+	li	r0,0			/* RS for P9 version of tlbiel */
 	mtctr	r6
 	li	r7,0x800		/* IS field = 0b10 */
 	ptesync
@@ -698,6 +692,14 @@ kvmppc_got_guest:
 	mtspr	SPRN_PURR,r7
 	mtspr	SPRN_SPURR,r8
 
+	/* Save host values of some registers */
+BEGIN_FTR_SECTION
+	mfspr	r5, SPRN_TIDR
+	mfspr	r6, SPRN_PSSCR
+	std	r5, STACK_SLOT_TID(r1)
+	std	r6, STACK_SLOT_PSSCR(r1)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
 BEGIN_FTR_SECTION
 	/* Set partition DABR */
 	/* Do this before re-enabling PMU to avoid P7 DABR corruption bug */
@@ -750,14 +752,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_PMAO_BUG)
 BEGIN_FTR_SECTION
 	ld	r5, VCPU_MMCR + 24(r4)
 	ld	r6, VCPU_SIER(r4)
+	mtspr	SPRN_MMCR2, r5
+	mtspr	SPRN_SIER, r6
+BEGIN_FTR_SECTION_NESTED(96)
 	lwz	r7, VCPU_PMC + 24(r4)
 	lwz	r8, VCPU_PMC + 28(r4)
 	ld	r9, VCPU_MMCR + 32(r4)
-	mtspr	SPRN_MMCR2, r5
-	mtspr	SPRN_SIER, r6
 	mtspr	SPRN_SPMC1, r7
 	mtspr	SPRN_SPMC2, r8
 	mtspr	SPRN_MMCRS, r9
+END_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96)
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	mtspr	SPRN_MMCR0, r3
 	isync
@@ -813,20 +817,30 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	mtspr	SPRN_EBBHR, r8
 	ld	r5, VCPU_EBBRR(r4)
 	ld	r6, VCPU_BESCR(r4)
-	ld	r7, VCPU_CSIGR(r4)
-	ld	r8, VCPU_TACR(r4)
+	lwz	r7, VCPU_GUEST_PID(r4)
+	ld	r8, VCPU_WORT(r4)
 	mtspr	SPRN_EBBRR, r5
 	mtspr	SPRN_BESCR, r6
-	mtspr	SPRN_CSIGR, r7
-	mtspr	SPRN_TACR, r8
+	mtspr	SPRN_PID, r7
+	mtspr	SPRN_WORT, r8
+BEGIN_FTR_SECTION
+	/* POWER8-only registers */
 	ld	r5, VCPU_TCSCR(r4)
 	ld	r6, VCPU_ACOP(r4)
-	lwz	r7, VCPU_GUEST_PID(r4)
-	ld	r8, VCPU_WORT(r4)
+	ld	r7, VCPU_CSIGR(r4)
+	ld	r8, VCPU_TACR(r4)
 	mtspr	SPRN_TCSCR, r5
 	mtspr	SPRN_ACOP, r6
-	mtspr	SPRN_PID, r7
-	mtspr	SPRN_WORT, r8
+	mtspr	SPRN_CSIGR, r7
+	mtspr	SPRN_TACR, r8
+FTR_SECTION_ELSE
+	/* POWER9-only registers */
+	ld	r5, VCPU_TID(r4)
+	ld	r6, VCPU_PSSCR(r4)
+	oris	r6, r6, PSSCR_EC@h	/* This makes stop trap to HV */
+	mtspr	SPRN_TIDR, r5
+	mtspr	SPRN_PSSCR, r6
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 8:
 
 	/*
@@ -1341,20 +1355,29 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	std	r8, VCPU_EBBHR(r9)
 	mfspr	r5, SPRN_EBBRR
 	mfspr	r6, SPRN_BESCR
-	mfspr	r7, SPRN_CSIGR
-	mfspr	r8, SPRN_TACR
+	mfspr	r7, SPRN_PID
+	mfspr	r8, SPRN_WORT
 	std	r5, VCPU_EBBRR(r9)
 	std	r6, VCPU_BESCR(r9)
-	std	r7, VCPU_CSIGR(r9)
-	std	r8, VCPU_TACR(r9)
+	stw	r7, VCPU_GUEST_PID(r9)
+	std	r8, VCPU_WORT(r9)
+BEGIN_FTR_SECTION
 	mfspr	r5, SPRN_TCSCR
 	mfspr	r6, SPRN_ACOP
-	mfspr	r7, SPRN_PID
-	mfspr	r8, SPRN_WORT
+	mfspr	r7, SPRN_CSIGR
+	mfspr	r8, SPRN_TACR
 	std	r5, VCPU_TCSCR(r9)
 	std	r6, VCPU_ACOP(r9)
-	stw	r7, VCPU_GUEST_PID(r9)
-	std	r8, VCPU_WORT(r9)
+	std	r7, VCPU_CSIGR(r9)
+	std	r8, VCPU_TACR(r9)
+FTR_SECTION_ELSE
+	mfspr	r5, SPRN_TIDR
+	mfspr	r6, SPRN_PSSCR
+	std	r5, VCPU_TID(r9)
+	rldicl	r6, r6, 4, 50		/* r6 &= PSSCR_GUEST_VIS */
+	rotldi	r6, r6, 60
+	std	r6, VCPU_PSSCR(r9)
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 	/*
 	 * Restore various registers to 0, where non-zero values
 	 * set by the guest could disrupt the host.
@@ -1363,12 +1386,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	mtspr	SPRN_IAMR, r0
 	mtspr	SPRN_CIABR, r0
 	mtspr	SPRN_DAWRX, r0
-	mtspr	SPRN_TCSCR, r0
 	mtspr	SPRN_WORT, r0
+BEGIN_FTR_SECTION
+	mtspr	SPRN_TCSCR, r0
 	/* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
 	li	r0, 1
 	sldi	r0, r0, 31
 	mtspr	SPRN_MMCRS, r0
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
 8:
 
 	/* Save and reset AMR and UAMOR before turning on the MMU */
@@ -1502,15 +1527,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	stw	r8, VCPU_PMC + 20(r9)
 BEGIN_FTR_SECTION
 	mfspr	r5, SPRN_SIER
+	std	r5, VCPU_SIER(r9)
+BEGIN_FTR_SECTION_NESTED(96)
 	mfspr	r6, SPRN_SPMC1
 	mfspr	r7, SPRN_SPMC2
 	mfspr	r8, SPRN_MMCRS
-	std	r5, VCPU_SIER(r9)
 	stw	r6, VCPU_PMC + 24(r9)
 	stw	r7, VCPU_PMC + 28(r9)
 	std	r8, VCPU_MMCR + 32(r9)
 	lis	r4, 0x8000
 	mtspr	SPRN_MMCRS, r4
+END_FTR_SECTION_NESTED(CPU_FTR_ARCH_300, 0, 96)
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 22:
 	/* Clear out SLB */
@@ -1519,6 +1546,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	slbia
 	ptesync
 
+	/* Restore host values of some registers */
+BEGIN_FTR_SECTION
+	ld	r5, STACK_SLOT_TID(r1)
+	ld	r6, STACK_SLOT_PSSCR(r1)
+	mtspr	SPRN_TIDR, r5
+	mtspr	SPRN_PSSCR, r6
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
 	/*
 	 * POWER7/POWER8 guest -> host partition switch code.
 	 * We don't have to lock against tlbies but we do
@@ -1552,12 +1587,14 @@ kvmhv_switch_to_host:
 	beq	19f
 
 	/* Primary thread switches back to host partition */
-	ld	r6,KVM_HOST_SDR1(r4)
 	lwz	r7,KVM_HOST_LPID(r4)
+BEGIN_FTR_SECTION
+	ld	r6,KVM_HOST_SDR1(r4)
 	li	r8,LPID_RSVD		/* switch to reserved LPID */
 	mtspr	SPRN_LPID,r8
 	ptesync
-	mtspr	SPRN_SDR1,r6		/* switch to partition page table */
+	mtspr	SPRN_SDR1,r6		/* switch to host page table */
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
 	mtspr	SPRN_LPID,r7
 	isync
 
@@ -2211,6 +2248,21 @@ BEGIN_FTR_SECTION
 	ori	r5, r5, LPCR_PECEDH
 	rlwimi	r5, r3, 0, LPCR_PECEDP
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
+
+kvm_nap_sequence:		/* desired LPCR value in r5 */
+BEGIN_FTR_SECTION
+	/*
+	 * PSSCR bits:	exit criterion = 1 (wakeup based on LPCR at sreset)
+	 *		enable state loss = 1 (allow SMT mode switch)
+	 *		requested level = 0 (just stop dispatching)
+	 */
+	lis	r3, (PSSCR_EC | PSSCR_ESL)@h
+	mtspr	SPRN_PSSCR, r3
+	/* Set LPCR_PECE_HVEE bit to enable wakeup by HV interrupts */
+	li	r4, LPCR_PECE_HVEE@higher
+	sldi	r4, r4, 32
+	or	r5, r5, r4
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
 	mtspr	SPRN_LPCR,r5
 	isync
 	li	r0, 0
@@ -2219,7 +2271,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	ld	r0, HSTATE_SCRATCH0(r13)
 1:	cmpd	r0, r0
 	bne	1b
+BEGIN_FTR_SECTION
 	nap
+FTR_SECTION_ELSE
+	PPC_STOP
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
 	b	.
 
 33:	mr	r4, r3
@@ -2600,11 +2656,13 @@ kvmppc_save_tm:
 	mfctr	r7
 	mfspr	r8, SPRN_AMR
 	mfspr	r10, SPRN_TAR
+	mfxer	r11
 	std	r5, VCPU_LR_TM(r9)
 	stw	r6, VCPU_CR_TM(r9)
 	std	r7, VCPU_CTR_TM(r9)
 	std	r8, VCPU_AMR_TM(r9)
 	std	r10, VCPU_TAR_TM(r9)
+	std	r11, VCPU_XER_TM(r9)
 
 	/* Restore r12 as trap number. */
 	lwz	r12, VCPU_TRAP(r9)
@@ -2697,11 +2755,13 @@ kvmppc_restore_tm:
 	ld	r7, VCPU_CTR_TM(r4)
 	ld	r8, VCPU_AMR_TM(r4)
 	ld	r9, VCPU_TAR_TM(r4)
+	ld	r10, VCPU_XER_TM(r4)
 	mtlr	r5
 	mtcr	r6
 	mtctr	r7
 	mtspr	SPRN_AMR, r8
 	mtspr	SPRN_TAR, r9
+	mtxer	r10
 
 	/*
 	 * Load up PPR and DSCR values but don't put them in the actual SPRs
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_rm_mmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -264,8 +264,10 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 
 	if (pa)
 		pteh |= HPTE_V_VALID;
-	else
+	else {
 		pteh |= HPTE_V_ABSENT;
+		ptel &= ~(HPTE_R_KEY_HI | HPTE_R_KEY_LO);
+	}
 
 	/*If we had host pte mapping then  Check WIMG */
 	if (ptep && !hpte_cache_flags_ok(ptel, is_ci)) {
@@ -351,6 +353,7 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 			/* inval in progress, write a non-present HPTE */
 			pteh |= HPTE_V_ABSENT;
 			pteh &= ~HPTE_V_VALID;
+			ptel &= ~(HPTE_R_KEY_HI | HPTE_R_KEY_LO);
 			unlock_rmap(rmap);
 		} else {
 			kvmppc_add_revmap_chain(kvm, rev, rmap, pte_index,
@@ -361,6 +364,11 @@ long kvmppc_do_h_enter(struct kvm *kvm,
 		}
 	}
 
+	/* Convert to new format on P9 */
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		ptel = hpte_old_to_new_r(pteh, ptel);
+		pteh = hpte_old_to_new_v(pteh);
+	}
 	hpte[1] = cpu_to_be64(ptel);
 
 	/* Write the first HPTE dword, unlocking the HPTE and making it valid */
@@ -386,6 +394,13 @@ long kvmppc_h_enter(struct kvm_vcpu *vcp
 #define LOCK_TOKEN	(*(u32 *)(&get_paca()->paca_index))
 #endif
 
+static inline int is_mmio_hpte(unsigned long v, unsigned long r)
+{
+	return ((v & HPTE_V_ABSENT) &&
+		(r & (HPTE_R_KEY_HI | HPTE_R_KEY_LO)) ==
+		(HPTE_R_KEY_HI | HPTE_R_KEY_LO));
+}
+
 static inline int try_lock_tlbie(unsigned int *lock)
 {
 	unsigned int tmp, old;
@@ -409,13 +424,18 @@ static void do_tlbies(struct kvm *kvm, u
 {
 	long i;
 
+	/*
+	 * We use the POWER9 5-operand versions of tlbie and tlbiel here.
+	 * Since we are using RIC=0 PRS=0 R=0, and P7/P8 tlbiel ignores
+	 * the RS field, this is backwards-compatible with P7 and P8.
+	 */
 	if (global) {
 		while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
 			cpu_relax();
 		if (need_sync)
 			asm volatile("ptesync" : : : "memory");
 		for (i = 0; i < npages; ++i)
-			asm volatile(PPC_TLBIE(%1,%0) : :
+			asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
 				     "r" (rbvalues[i]), "r" (kvm->arch.lpid));
 		asm volatile("eieio; tlbsync; ptesync" : : : "memory");
 		kvm->arch.tlbie_lock = 0;
@@ -423,7 +443,8 @@ static void do_tlbies(struct kvm *kvm, u
 		if (need_sync)
 			asm volatile("ptesync" : : : "memory");
 		for (i = 0; i < npages; ++i)
-			asm volatile("tlbiel %0" : : "r" (rbvalues[i]));
+			asm volatile(PPC_TLBIEL(%0,%1,0,0,0) : :
+				     "r" (rbvalues[i]), "r" (0));
 		asm volatile("ptesync" : : : "memory");
 	}
 }
@@ -435,18 +456,23 @@ long kvmppc_do_h_remove(struct kvm *kvm,
 	__be64 *hpte;
 	unsigned long v, r, rb;
 	struct revmap_entry *rev;
-	u64 pte;
+	u64 pte, orig_pte, pte_r;
 
 	if (pte_index >= kvm->arch.hpt_npte)
 		return H_PARAMETER;
 	hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
 	while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 		cpu_relax();
-	pte = be64_to_cpu(hpte[0]);
+	pte = orig_pte = be64_to_cpu(hpte[0]);
+	pte_r = be64_to_cpu(hpte[1]);
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		pte = hpte_new_to_old_v(pte, pte_r);
+		pte_r = hpte_new_to_old_r(pte_r);
+	}
 	if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
 	    ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) ||
 	    ((flags & H_ANDCOND) && (pte & avpn) != 0)) {
-		__unlock_hpte(hpte, pte);
+		__unlock_hpte(hpte, orig_pte);
 		return H_NOT_FOUND;
 	}
 
@@ -454,7 +480,7 @@ long kvmppc_do_h_remove(struct kvm *kvm,
 	v = pte & ~HPTE_V_HVLOCK;
 	if (v & HPTE_V_VALID) {
 		hpte[0] &= ~cpu_to_be64(HPTE_V_VALID);
-		rb = compute_tlbie_rb(v, be64_to_cpu(hpte[1]), pte_index);
+		rb = compute_tlbie_rb(v, pte_r, pte_index);
 		do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true);
 		/*
 		 * The reference (R) and change (C) bits in a HPT
@@ -472,6 +498,9 @@ long kvmppc_do_h_remove(struct kvm *kvm,
 	note_hpte_modification(kvm, rev);
 	unlock_hpte(hpte, 0);
 
+	if (is_mmio_hpte(v, pte_r))
+		atomic64_inc(&kvm->arch.mmio_update);
+
 	if (v & HPTE_V_ABSENT)
 		v = (v & ~HPTE_V_ABSENT) | HPTE_V_VALID;
 	hpret[0] = v;
@@ -498,7 +527,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 	int global;
 	long int ret = H_SUCCESS;
 	struct revmap_entry *rev, *revs[4];
-	u64 hp0;
+	u64 hp0, hp1;
 
 	global = global_invalidates(kvm, 0);
 	for (i = 0; i < 4 && ret == H_SUCCESS; ) {
@@ -531,6 +560,11 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 			}
 			found = 0;
 			hp0 = be64_to_cpu(hp[0]);
+			hp1 = be64_to_cpu(hp[1]);
+			if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+				hp0 = hpte_new_to_old_v(hp0, hp1);
+				hp1 = hpte_new_to_old_r(hp1);
+			}
 			if (hp0 & (HPTE_V_ABSENT | HPTE_V_VALID)) {
 				switch (flags & 3) {
 				case 0:		/* absolute */
@@ -561,13 +595,14 @@ long kvmppc_h_bulk_remove(struct kvm_vcp
 				rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
 				args[j] |= rcbits << (56 - 5);
 				hp[0] = 0;
+				if (is_mmio_hpte(hp0, hp1))
+					atomic64_inc(&kvm->arch.mmio_update);
 				continue;
 			}
 
 			/* leave it locked */
 			hp[0] &= ~cpu_to_be64(HPTE_V_VALID);
-			tlbrb[n] = compute_tlbie_rb(be64_to_cpu(hp[0]),
-				be64_to_cpu(hp[1]), pte_index);
+			tlbrb[n] = compute_tlbie_rb(hp0, hp1, pte_index);
 			indexes[n] = j;
 			hptes[n] = hp;
 			revs[n] = rev;
@@ -605,7 +640,7 @@ long kvmppc_h_protect(struct kvm_vcpu *v
 	__be64 *hpte;
 	struct revmap_entry *rev;
 	unsigned long v, r, rb, mask, bits;
-	u64 pte;
+	u64 pte_v, pte_r;
 
 	if (pte_index >= kvm->arch.hpt_npte)
 		return H_PARAMETER;
@@ -613,14 +648,16 @@ long kvmppc_h_protect(struct kvm_vcpu *v
 	hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
 	while (!try_lock_hpte(hpte, HPTE_V_HVLOCK))
 		cpu_relax();
-	pte = be64_to_cpu(hpte[0]);
-	if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
-	    ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) {
-		__unlock_hpte(hpte, pte);
+	v = pte_v = be64_to_cpu(hpte[0]);
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		v = hpte_new_to_old_v(v, be64_to_cpu(hpte[1]));
+	if ((v & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 ||
+	    ((flags & H_AVPN) && (v & ~0x7fUL) != avpn)) {
+		__unlock_hpte(hpte, pte_v);
 		return H_NOT_FOUND;
 	}
 
-	v = pte;
+	pte_r = be64_to_cpu(hpte[1]);
 	bits = (flags << 55) & HPTE_R_PP0;
 	bits |= (flags << 48) & HPTE_R_KEY_HI;
 	bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO);
@@ -642,22 +679,26 @@ long kvmppc_h_protect(struct kvm_vcpu *v
 		 * readonly to writable.  If it should be writable, we'll
 		 * take a trap and let the page fault code sort it out.
 		 */
-		pte = be64_to_cpu(hpte[1]);
-		r = (pte & ~mask) | bits;
-		if (hpte_is_writable(r) && !hpte_is_writable(pte))
+		r = (pte_r & ~mask) | bits;
+		if (hpte_is_writable(r) && !hpte_is_writable(pte_r))
 			r = hpte_make_readonly(r);
 		/* If the PTE is changing, invalidate it first */
-		if (r != pte) {
+		if (r != pte_r) {
 			rb = compute_tlbie_rb(v, r, pte_index);
-			hpte[0] = cpu_to_be64((v & ~HPTE_V_VALID) |
+			hpte[0] = cpu_to_be64((pte_v & ~HPTE_V_VALID) |
 					      HPTE_V_ABSENT);
 			do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags),
 				  true);
+			/* Don't lose R/C bit updates done by hardware */
+			r |= be64_to_cpu(hpte[1]) & (HPTE_R_R | HPTE_R_C);
 			hpte[1] = cpu_to_be64(r);
 		}
 	}
-	unlock_hpte(hpte, v & ~HPTE_V_HVLOCK);
+	unlock_hpte(hpte, pte_v & ~HPTE_V_HVLOCK);
 	asm volatile("ptesync" : : : "memory");
+	if (is_mmio_hpte(v, pte_r))
+		atomic64_inc(&kvm->arch.mmio_update);
+
 	return H_SUCCESS;
 }
 
@@ -681,6 +722,10 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu
 		hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4));
 		v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
 		r = be64_to_cpu(hpte[1]);
+		if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+			v = hpte_new_to_old_v(v, r);
+			r = hpte_new_to_old_r(r);
+		}
 		if (v & HPTE_V_ABSENT) {
 			v &= ~HPTE_V_ABSENT;
 			v |= HPTE_V_VALID;
@@ -798,10 +843,16 @@ void kvmppc_invalidate_hpte(struct kvm *
 			unsigned long pte_index)
 {
 	unsigned long rb;
+	u64 hp0, hp1;
 
 	hptep[0] &= ~cpu_to_be64(HPTE_V_VALID);
-	rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
-			      pte_index);
+	hp0 = be64_to_cpu(hptep[0]);
+	hp1 = be64_to_cpu(hptep[1]);
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		hp0 = hpte_new_to_old_v(hp0, hp1);
+		hp1 = hpte_new_to_old_r(hp1);
+	}
+	rb = compute_tlbie_rb(hp0, hp1, pte_index);
 	do_tlbies(kvm, &rb, 1, 1, true);
 }
 EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte);
@@ -811,9 +862,15 @@ void kvmppc_clear_ref_hpte(struct kvm *k
 {
 	unsigned long rb;
 	unsigned char rbyte;
+	u64 hp0, hp1;
 
-	rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]),
-			      pte_index);
+	hp0 = be64_to_cpu(hptep[0]);
+	hp1 = be64_to_cpu(hptep[1]);
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		hp0 = hpte_new_to_old_v(hp0, hp1);
+		hp1 = hpte_new_to_old_r(hp1);
+	}
+	rb = compute_tlbie_rb(hp0, hp1, pte_index);
 	rbyte = (be64_to_cpu(hptep[1]) & ~HPTE_R_R) >> 8;
 	/* modify only the second-last byte, which contains the ref bit */
 	*((char *)hptep + 14) = rbyte;
@@ -828,6 +885,37 @@ static int slb_base_page_shift[4] = {
 	20,	/* 1M, unsupported */
 };
 
+static struct mmio_hpte_cache_entry *mmio_cache_search(struct kvm_vcpu *vcpu,
+		unsigned long eaddr, unsigned long slb_v, long mmio_update)
+{
+	struct mmio_hpte_cache_entry *entry = NULL;
+	unsigned int pshift;
+	unsigned int i;
+
+	for (i = 0; i < MMIO_HPTE_CACHE_SIZE; i++) {
+		entry = &vcpu->arch.mmio_cache.entry[i];
+		if (entry->mmio_update == mmio_update) {
+			pshift = entry->slb_base_pshift;
+			if ((entry->eaddr >> pshift) == (eaddr >> pshift) &&
+			    entry->slb_v == slb_v)
+				return entry;
+		}
+	}
+	return NULL;
+}
+
+static struct mmio_hpte_cache_entry *
+			next_mmio_cache_entry(struct kvm_vcpu *vcpu)
+{
+	unsigned int index = vcpu->arch.mmio_cache.index;
+
+	vcpu->arch.mmio_cache.index++;
+	if (vcpu->arch.mmio_cache.index == MMIO_HPTE_CACHE_SIZE)
+		vcpu->arch.mmio_cache.index = 0;
+
+	return &vcpu->arch.mmio_cache.entry[index];
+}
+
 /* When called from virtmode, this func should be protected by
  * preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK
  * can trigger deadlock issue.
@@ -842,7 +930,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm
 	unsigned long avpn;
 	__be64 *hpte;
 	unsigned long mask, val;
-	unsigned long v, r;
+	unsigned long v, r, orig_v;
 
 	/* Get page shift, work out hash and AVPN etc. */
 	mask = SLB_VSID_B | HPTE_V_AVPN | HPTE_V_SECONDARY;
@@ -877,6 +965,8 @@ long kvmppc_hv_find_lock_hpte(struct kvm
 		for (i = 0; i < 16; i += 2) {
 			/* Read the PTE racily */
 			v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
+			if (cpu_has_feature(CPU_FTR_ARCH_300))
+				v = hpte_new_to_old_v(v, be64_to_cpu(hpte[i+1]));
 
 			/* Check valid/absent, hash, segment size and AVPN */
 			if (!(v & valid) || (v & mask) != val)
@@ -885,8 +975,12 @@ long kvmppc_hv_find_lock_hpte(struct kvm
 			/* Lock the PTE and read it under the lock */
 			while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK))
 				cpu_relax();
-			v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
+			v = orig_v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK;
 			r = be64_to_cpu(hpte[i+1]);
+			if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+				v = hpte_new_to_old_v(v, r);
+				r = hpte_new_to_old_r(r);
+			}
 
 			/*
 			 * Check the HPTE again, including base page size
@@ -896,7 +990,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm
 				/* Return with the HPTE still locked */
 				return (hash << 3) + (i >> 1);
 
-			__unlock_hpte(&hpte[i], v);
+			__unlock_hpte(&hpte[i], orig_v);
 		}
 
 		if (val & HPTE_V_SECONDARY)
@@ -924,30 +1018,45 @@ long kvmppc_hpte_hv_fault(struct kvm_vcp
 {
 	struct kvm *kvm = vcpu->kvm;
 	long int index;
-	unsigned long v, r, gr;
+	unsigned long v, r, gr, orig_v;
 	__be64 *hpte;
 	unsigned long valid;
 	struct revmap_entry *rev;
 	unsigned long pp, key;
+	struct mmio_hpte_cache_entry *cache_entry = NULL;
+	long mmio_update = 0;
 
 	/* For protection fault, expect to find a valid HPTE */
 	valid = HPTE_V_VALID;
-	if (status & DSISR_NOHPTE)
+	if (status & DSISR_NOHPTE) {
 		valid |= HPTE_V_ABSENT;
-
-	index = kvmppc_hv_find_lock_hpte(kvm, addr, slb_v, valid);
-	if (index < 0) {
-		if (status & DSISR_NOHPTE)
-			return status;	/* there really was no HPTE */
-		return 0;		/* for prot fault, HPTE disappeared */
+		mmio_update = atomic64_read(&kvm->arch.mmio_update);
+		cache_entry = mmio_cache_search(vcpu, addr, slb_v, mmio_update);
 	}
-	hpte = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
-	v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
-	r = be64_to_cpu(hpte[1]);
-	rev = real_vmalloc_addr(&kvm->arch.revmap[index]);
-	gr = rev->guest_rpte;
+	if (cache_entry) {
+		index = cache_entry->pte_index;
+		v = cache_entry->hpte_v;
+		r = cache_entry->hpte_r;
+		gr = cache_entry->rpte;
+	} else {
+		index = kvmppc_hv_find_lock_hpte(kvm, addr, slb_v, valid);
+		if (index < 0) {
+			if (status & DSISR_NOHPTE)
+				return status;	/* there really was no HPTE */
+			return 0;	/* for prot fault, HPTE disappeared */
+		}
+		hpte = (__be64 *)(kvm->arch.hpt_virt + (index << 4));
+		v = orig_v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK;
+		r = be64_to_cpu(hpte[1]);
+		if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+			v = hpte_new_to_old_v(v, r);
+			r = hpte_new_to_old_r(r);
+		}
+		rev = real_vmalloc_addr(&kvm->arch.revmap[index]);
+		gr = rev->guest_rpte;
 
-	unlock_hpte(hpte, v);
+		unlock_hpte(hpte, orig_v);
+	}
 
 	/* For not found, if the HPTE is valid by now, retry the instruction */
 	if ((status & DSISR_NOHPTE) && (v & HPTE_V_VALID))
@@ -985,12 +1094,32 @@ long kvmppc_hpte_hv_fault(struct kvm_vcp
 	vcpu->arch.pgfault_index = index;
 	vcpu->arch.pgfault_hpte[0] = v;
 	vcpu->arch.pgfault_hpte[1] = r;
+	vcpu->arch.pgfault_cache = cache_entry;
 
 	/* Check the storage key to see if it is possibly emulated MMIO */
-	if (data && (vcpu->arch.shregs.msr & MSR_IR) &&
-	    (r & (HPTE_R_KEY_HI | HPTE_R_KEY_LO)) ==
-	    (HPTE_R_KEY_HI | HPTE_R_KEY_LO))
-		return -2;	/* MMIO emulation - load instr word */
+	if ((r & (HPTE_R_KEY_HI | HPTE_R_KEY_LO)) ==
+	    (HPTE_R_KEY_HI | HPTE_R_KEY_LO)) {
+		if (!cache_entry) {
+			unsigned int pshift = 12;
+			unsigned int pshift_index;
+
+			if (slb_v & SLB_VSID_L) {
+				pshift_index = ((slb_v & SLB_VSID_LP) >> 4);
+				pshift = slb_base_page_shift[pshift_index];
+			}
+			cache_entry = next_mmio_cache_entry(vcpu);
+			cache_entry->eaddr = addr;
+			cache_entry->slb_base_pshift = pshift;
+			cache_entry->pte_index = index;
+			cache_entry->hpte_v = v;
+			cache_entry->hpte_r = r;
+			cache_entry->rpte = gr;
+			cache_entry->slb_v = slb_v;
+			cache_entry->mmio_update = mmio_update;
+		}
+		if (data && (vcpu->arch.shregs.msr & MSR_IR))
+			return -2;	/* MMIO emulation - load instr word */
+	}
 
 	return -1;		/* send fault up to host kernel mode */
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_hv_rm_xics.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,11 @@ static inline void icp_send_hcore_msg(in
 	hcpu = hcore << threads_shift;
 	kvmppc_host_rm_ops_hv->rm_core[hcore].rm_data = vcpu;
 	smp_muxed_ipi_set_message(hcpu, PPC_MSG_RM_HOST_ACTION);
-	icp_native_cause_ipi_rm(hcpu);
+	if (paca[hcpu].kvm_hstate.xics_phys)
+		icp_native_cause_ipi_rm(hcpu);
+	else
+		opal_rm_int_set_mfrr(get_hard_smp_processor_id(hcpu),
+				     IPI_PRIORITY);
 }
 #else
 static inline void icp_send_hcore_msg(int hcore, struct kvm_vcpu *vcpu) { }
@@ -737,7 +741,7 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcp
 
 unsigned long eoi_rc;
 
-static void icp_eoi(struct irq_chip *c, u32 hwirq, u32 xirr)
+static void icp_eoi(struct irq_chip *c, u32 hwirq, __be32 xirr, bool *again)
 {
 	unsigned long xics_phys;
 	int64_t rc;
@@ -751,7 +755,12 @@ static void icp_eoi(struct irq_chip *c,
 
 	/* EOI it */
 	xics_phys = local_paca->kvm_hstate.xics_phys;
-	_stwcix(xics_phys + XICS_XIRR, xirr);
+	if (xics_phys) {
+		_stwcix(xics_phys + XICS_XIRR, xirr);
+	} else {
+		rc = opal_rm_int_eoi(be32_to_cpu(xirr));
+		*again = rc > 0;
+	}
 }
 
 static int xics_opal_rm_set_server(unsigned int hw_irq, int server_cpu)
@@ -809,9 +818,10 @@ static void kvmppc_rm_handle_irq_desc(st
 }
 
 long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu,
-				 u32 xirr,
+				 __be32 xirr,
 				 struct kvmppc_irq_map *irq_map,
-				 struct kvmppc_passthru_irqmap *pimap)
+				 struct kvmppc_passthru_irqmap *pimap,
+				 bool *again)
 {
 	struct kvmppc_xics *xics;
 	struct kvmppc_icp *icp;
@@ -825,7 +835,8 @@ long kvmppc_deliver_irq_passthru(struct
 	icp_rm_deliver_irq(xics, icp, irq);
 
 	/* EOI the interrupt */
-	icp_eoi(irq_desc_get_chip(irq_map->desc), irq_map->r_hwirq, xirr);
+	icp_eoi(irq_desc_get_chip(irq_map->desc), irq_map->r_hwirq, xirr,
+		again);
 
 	if (check_too_hard(xics, icp) == H_TOO_HARD)
 		return 2;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_pr.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_pr.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_pr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_pr.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <asm/cputable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_pr_papr.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_pr_papr.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_pr_papr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_pr_papr.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 
 #include <linux/anon_inodes.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_rtas.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_rtas.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_rtas.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_rtas.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/kvm.h>
 #include <linux/err.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/kvm_book3s.h>
 #include <asm/kvm_ppc.h>
 #include <asm/hvcall.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_xics.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_xics.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/book3s_xics.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/book3s_xics.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/anon_inodes.h>
 #include <linux/spinlock.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/kvm_book3s.h>
 #include <asm/kvm_ppc.h>
 #include <asm/hvcall.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/booke.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/booke.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/booke.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/booke.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <linux/fs.h>
 
 #include <asm/cputable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/kvm_ppc.h>
 #include <asm/cacheflush.h>
 #include <asm/dbell.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/mpic.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/mpic.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/mpic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/mpic.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/anon_inodes.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mpic.h>
 #include <asm/kvm_para.h>
 #include <asm/kvm_host.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/powerpc.c linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/powerpc.c
--- linux-libre-4.9-gnu/arch/powerpc/kvm/powerpc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/powerpc.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <linux/irqbypass.h>
 #include <linux/kvm_irqfd.h>
 #include <asm/cputable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/kvm_ppc.h>
 #include <asm/tlbflush.h>
 #include <asm/cputhreads.h>
@@ -536,7 +536,6 @@ int kvm_vm_ioctl_check_extension(struct
 #ifdef CONFIG_PPC_BOOK3S_64
 	case KVM_CAP_SPAPR_TCE:
 	case KVM_CAP_SPAPR_TCE_64:
-	case KVM_CAP_PPC_ALLOC_HTAB:
 	case KVM_CAP_PPC_RTAS:
 	case KVM_CAP_PPC_FIXUP_HCALL:
 	case KVM_CAP_PPC_ENABLE_HCALL:
@@ -545,13 +544,20 @@ int kvm_vm_ioctl_check_extension(struct
 #endif
 		r = 1;
 		break;
+
+	case KVM_CAP_PPC_ALLOC_HTAB:
+		r = hv_enabled;
+		break;
 #endif /* CONFIG_PPC_BOOK3S_64 */
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 	case KVM_CAP_PPC_SMT:
-		if (hv_enabled)
-			r = threads_per_subcore;
-		else
-			r = 0;
+		r = 0;
+		if (hv_enabled) {
+			if (cpu_has_feature(CPU_FTR_ARCH_300))
+				r = 1;
+			else
+				r = threads_per_subcore;
+		}
 		break;
 	case KVM_CAP_PPC_RMA:
 		r = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/kvm/trace_hv.h linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/trace_hv.h
--- linux-libre-4.9-gnu/arch/powerpc/kvm/trace_hv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/kvm/trace_hv.h	2017-02-12 16:03:20.000000000 -0500
@@ -449,7 +449,7 @@ TRACE_EVENT(kvmppc_vcore_wakeup,
 		__entry->tgid   = current->tgid;
 	),
 
-	TP_printk("%s time %lld ns, tgid=%d",
+	TP_printk("%s time %llu ns, tgid=%d",
 		__entry->waited ? "wait" : "poll",
 		__entry->ns, __entry->tgid)
 );
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/checksum_32.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/checksum_32.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/checksum_32.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/checksum_32.S	2017-02-12 16:03:20.000000000 -0500
@@ -103,17 +103,14 @@ EXPORT_SYMBOL(__csum_partial)
 	adde	r12,r12,r10
 
 #define CSUM_COPY_16_BYTES_EXCODE(n)		\
-.section __ex_table,"a";		\
-	.align	2;			\
-	.long	8 ## n ## 0b,src_error;	\
-	.long	8 ## n ## 1b,src_error;	\
-	.long	8 ## n ## 2b,src_error;	\
-	.long	8 ## n ## 3b,src_error;	\
-	.long	8 ## n ## 4b,dst_error;	\
-	.long	8 ## n ## 5b,dst_error;	\
-	.long	8 ## n ## 6b,dst_error;	\
-	.long	8 ## n ## 7b,dst_error;	\
-	.text
+	EX_TABLE(8 ## n ## 0b, src_error);	\
+	EX_TABLE(8 ## n ## 1b, src_error);	\
+	EX_TABLE(8 ## n ## 2b, src_error);	\
+	EX_TABLE(8 ## n ## 3b, src_error);	\
+	EX_TABLE(8 ## n ## 4b, dst_error);	\
+	EX_TABLE(8 ## n ## 5b, dst_error);	\
+	EX_TABLE(8 ## n ## 6b, dst_error);	\
+	EX_TABLE(8 ## n ## 7b, dst_error);
 
 	.text
 	.stabs	"arch/powerpc/lib/",N_SO,0,0,0f
@@ -263,14 +260,11 @@ dst_error:
 	stw	r0,0(r8)
 	blr
 
-	.section __ex_table,"a"
-	.align	2
-	.long	70b,src_error
-	.long	71b,dst_error
-	.long	72b,src_error
-	.long	73b,dst_error
-	.long	54b,dst_error
-	.text
+	EX_TABLE(70b, src_error);
+	EX_TABLE(71b, dst_error);
+	EX_TABLE(72b, src_error);
+	EX_TABLE(73b, dst_error);
+	EX_TABLE(54b, dst_error);
 
 /*
  * this stuff handles faults in the cacheline loop and branches to either
@@ -291,12 +285,11 @@ dst_error:
 #endif
 #endif
 
-	.section __ex_table,"a"
-	.align	2
-	.long	30b,src_error
-	.long	31b,dst_error
-	.long	40b,src_error
-	.long	41b,dst_error
-	.long	50b,src_error
-	.long	51b,dst_error
+	EX_TABLE(30b, src_error);
+	EX_TABLE(31b, dst_error);
+	EX_TABLE(40b, src_error);
+	EX_TABLE(41b, dst_error);
+	EX_TABLE(50b, src_error);
+	EX_TABLE(51b, dst_error);
+
 EXPORT_SYMBOL(csum_partial_copy_generic)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/checksum_64.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/checksum_64.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/checksum_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/checksum_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -182,34 +182,22 @@ EXPORT_SYMBOL(__csum_partial)
 
 	.macro srcnr
 100:
-	.section __ex_table,"a"
-	.align 3
-	.llong 100b,.Lsrc_error_nr
-	.previous
+	EX_TABLE(100b,.Lsrc_error_nr)
 	.endm
 
 	.macro source
 150:
-	.section __ex_table,"a"
-	.align 3
-	.llong 150b,.Lsrc_error
-	.previous
+	EX_TABLE(150b,.Lsrc_error)
 	.endm
 
 	.macro dstnr
 200:
-	.section __ex_table,"a"
-	.align 3
-	.llong 200b,.Ldest_error_nr
-	.previous
+	EX_TABLE(200b,.Ldest_error_nr)
 	.endm
 
 	.macro dest
 250:
-	.section __ex_table,"a"
-	.align 3
-	.llong 250b,.Ldest_error
-	.previous
+	EX_TABLE(250b,.Ldest_error)
 	.endm
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/checksum_wrappers.c linux-libre-4.10-rc8-gnu/arch/powerpc/lib/checksum_wrappers.c
--- linux-libre-4.9-gnu/arch/powerpc/lib/checksum_wrappers.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/checksum_wrappers.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/checksum.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 __wsum csum_and_copy_from_user(const void __user *src, void *dst,
 			       int len, __wsum sum, int *err_ptr)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/code-patching.c linux-libre-4.10-rc8-gnu/arch/powerpc/lib/code-patching.c
--- linux-libre-4.9-gnu/arch/powerpc/lib/code-patching.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/code-patching.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/mm.h>
 #include <asm/page.h>
 #include <asm/code-patching.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 int patch_instruction(unsigned int *addr, unsigned int instr)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/copy_32.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/copy_32.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/copy_32.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/copy_32.S	2017-02-12 16:03:20.000000000 -0500
@@ -49,17 +49,14 @@
 9 ## n ## 1:					\
 	addi	r5,r5,-(16 * n);		\
 	b	105f;				\
-.section __ex_table,"a";			\
-	.align	2;				\
-	.long	8 ## n ## 0b,9 ## n ## 0b;	\
-	.long	8 ## n ## 1b,9 ## n ## 0b;	\
-	.long	8 ## n ## 2b,9 ## n ## 0b;	\
-	.long	8 ## n ## 3b,9 ## n ## 0b;	\
-	.long	8 ## n ## 4b,9 ## n ## 1b;	\
-	.long	8 ## n ## 5b,9 ## n ## 1b;	\
-	.long	8 ## n ## 6b,9 ## n ## 1b;	\
-	.long	8 ## n ## 7b,9 ## n ## 1b;	\
-	.text
+	EX_TABLE(8 ## n ## 0b,9 ## n ## 0b);	\
+	EX_TABLE(8 ## n ## 1b,9 ## n ## 0b);	\
+	EX_TABLE(8 ## n ## 2b,9 ## n ## 0b);	\
+	EX_TABLE(8 ## n ## 3b,9 ## n ## 0b);	\
+	EX_TABLE(8 ## n ## 4b,9 ## n ## 1b);	\
+	EX_TABLE(8 ## n ## 5b,9 ## n ## 1b);	\
+	EX_TABLE(8 ## n ## 6b,9 ## n ## 1b);	\
+	EX_TABLE(8 ## n ## 7b,9 ## n ## 1b)
 
 	.text
 	.stabs	"arch/powerpc/lib/",N_SO,0,0,0f
@@ -323,13 +320,10 @@ _GLOBAL(__copy_tofrom_user)
 73:	stwu	r9,4(r6)
 	bdnz	72b
 
-	.section __ex_table,"a"
-	.align	2
-	.long	70b,100f
-	.long	71b,101f
-	.long	72b,102f
-	.long	73b,103f
-	.text
+	EX_TABLE(70b,100f)
+	EX_TABLE(71b,101f)
+	EX_TABLE(72b,102f)
+	EX_TABLE(73b,103f)
 
 58:	srwi.	r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
 	clrlwi	r5,r5,32-LG_CACHELINE_BYTES
@@ -364,10 +358,7 @@ _GLOBAL(__copy_tofrom_user)
 
 53:	dcbt	r3,r4
 54:	dcbz	r11,r6
-	.section __ex_table,"a"
-	.align	2
-	.long	54b,105f
-	.text
+	EX_TABLE(54b,105f)
 /* the main body of the cacheline loop */
 	COPY_16_BYTES_WITHEX(0)
 #if L1_CACHE_BYTES >= 32
@@ -500,15 +491,13 @@ _GLOBAL(__copy_tofrom_user)
 	bdnz	114b
 120:	blr
 
-	.section __ex_table,"a"
-	.align	2
-	.long	30b,108b
-	.long	31b,109b
-	.long	40b,110b
-	.long	41b,111b
-	.long	130b,132b
-	.long	131b,120b
-	.long	112b,120b
-	.long	114b,120b
-	.text
+	EX_TABLE(30b,108b)
+	EX_TABLE(31b,109b)
+	EX_TABLE(40b,110b)
+	EX_TABLE(41b,111b)
+	EX_TABLE(130b,132b)
+	EX_TABLE(131b,120b)
+	EX_TABLE(112b,120b)
+	EX_TABLE(114b,120b)
+
 EXPORT_SYMBOL(__copy_tofrom_user)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/copyuser_64.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/copyuser_64.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/copyuser_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/copyuser_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -394,70 +394,66 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_
 192:
 	blr			/* #bytes not copied in r3 */
 
-	.section __ex_table,"a"
-	.align	3
-	.llong	20b,120b
-	.llong	220b,320b
-	.llong	21b,121b
-	.llong	221b,321b
-	.llong	70b,170b
-	.llong	270b,370b
-	.llong	22b,122b
-	.llong	222b,322b
-	.llong	71b,171b
-	.llong	271b,371b
-	.llong	72b,172b
-	.llong	272b,372b
-	.llong	244b,344b
-	.llong	245b,345b
-	.llong	23b,123b
-	.llong	73b,173b
-	.llong	44b,144b
-	.llong	74b,174b
-	.llong	45b,145b
-	.llong	75b,175b
-	.llong	24b,124b
-	.llong	25b,125b
-	.llong	26b,126b
-	.llong	27b,127b
-	.llong	28b,128b
-	.llong	29b,129b
-	.llong	30b,130b
-	.llong	31b,131b
-	.llong	32b,132b
-	.llong	76b,176b
-	.llong	33b,133b
-	.llong	77b,177b
-	.llong	78b,178b
-	.llong	79b,179b
-	.llong	80b,180b
-	.llong	34b,134b
-	.llong	94b,194b
-	.llong	95b,195b
-	.llong	96b,196b
-	.llong	35b,135b
-	.llong	81b,181b
-	.llong	36b,136b
-	.llong	82b,182b
-	.llong	37b,137b
-	.llong	83b,183b
-	.llong	38b,138b
-	.llong	39b,139b
-	.llong	84b,184b
-	.llong	85b,185b
-	.llong	40b,140b
-	.llong	86b,186b
-	.llong	41b,141b
-	.llong	87b,187b
-	.llong	42b,142b
-	.llong	88b,188b
-	.llong	43b,143b
-	.llong	89b,189b
-	.llong	90b,190b
-	.llong	91b,191b
-	.llong	92b,192b
-	
-	.text
+	EX_TABLE(20b,120b)
+	EX_TABLE(220b,320b)
+	EX_TABLE(21b,121b)
+	EX_TABLE(221b,321b)
+	EX_TABLE(70b,170b)
+	EX_TABLE(270b,370b)
+	EX_TABLE(22b,122b)
+	EX_TABLE(222b,322b)
+	EX_TABLE(71b,171b)
+	EX_TABLE(271b,371b)
+	EX_TABLE(72b,172b)
+	EX_TABLE(272b,372b)
+	EX_TABLE(244b,344b)
+	EX_TABLE(245b,345b)
+	EX_TABLE(23b,123b)
+	EX_TABLE(73b,173b)
+	EX_TABLE(44b,144b)
+	EX_TABLE(74b,174b)
+	EX_TABLE(45b,145b)
+	EX_TABLE(75b,175b)
+	EX_TABLE(24b,124b)
+	EX_TABLE(25b,125b)
+	EX_TABLE(26b,126b)
+	EX_TABLE(27b,127b)
+	EX_TABLE(28b,128b)
+	EX_TABLE(29b,129b)
+	EX_TABLE(30b,130b)
+	EX_TABLE(31b,131b)
+	EX_TABLE(32b,132b)
+	EX_TABLE(76b,176b)
+	EX_TABLE(33b,133b)
+	EX_TABLE(77b,177b)
+	EX_TABLE(78b,178b)
+	EX_TABLE(79b,179b)
+	EX_TABLE(80b,180b)
+	EX_TABLE(34b,134b)
+	EX_TABLE(94b,194b)
+	EX_TABLE(95b,195b)
+	EX_TABLE(96b,196b)
+	EX_TABLE(35b,135b)
+	EX_TABLE(81b,181b)
+	EX_TABLE(36b,136b)
+	EX_TABLE(82b,182b)
+	EX_TABLE(37b,137b)
+	EX_TABLE(83b,183b)
+	EX_TABLE(38b,138b)
+	EX_TABLE(39b,139b)
+	EX_TABLE(84b,184b)
+	EX_TABLE(85b,185b)
+	EX_TABLE(40b,140b)
+	EX_TABLE(86b,186b)
+	EX_TABLE(41b,141b)
+	EX_TABLE(87b,187b)
+	EX_TABLE(42b,142b)
+	EX_TABLE(88b,188b)
+	EX_TABLE(43b,143b)
+	EX_TABLE(89b,189b)
+	EX_TABLE(90b,190b)
+	EX_TABLE(91b,191b)
+	EX_TABLE(92b,192b)
 
 /*
  * Routine to copy a whole page of data, optimized for POWER4.
@@ -598,78 +594,77 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_
 	li	r5,4096
 	b	.Ldst_aligned
 
-	.section __ex_table,"a"
-	.align	3
-	.llong	20b,100b
-	.llong	21b,100b
-	.llong	22b,100b
-	.llong	23b,100b
-	.llong	24b,100b
-	.llong	25b,100b
-	.llong	26b,100b
-	.llong	27b,100b
-	.llong	28b,100b
-	.llong	29b,100b
-	.llong	30b,100b
-	.llong	31b,100b
-	.llong	32b,100b
-	.llong	33b,100b
-	.llong	34b,100b
-	.llong	35b,100b
-	.llong	36b,100b
-	.llong	37b,100b
-	.llong	38b,100b
-	.llong	39b,100b
-	.llong	40b,100b
-	.llong	41b,100b
-	.llong	42b,100b
-	.llong	43b,100b
-	.llong	44b,100b
-	.llong	45b,100b
-	.llong	46b,100b
-	.llong	47b,100b
-	.llong	48b,100b
-	.llong	49b,100b
-	.llong	50b,100b
-	.llong	51b,100b
-	.llong	52b,100b
-	.llong	53b,100b
-	.llong	54b,100b
-	.llong	55b,100b
-	.llong	56b,100b
-	.llong	57b,100b
-	.llong	58b,100b
-	.llong	59b,100b
-	.llong	60b,100b
-	.llong	61b,100b
-	.llong	62b,100b
-	.llong	63b,100b
-	.llong	64b,100b
-	.llong	65b,100b
-	.llong	66b,100b
-	.llong	67b,100b
-	.llong	68b,100b
-	.llong	69b,100b
-	.llong	70b,100b
-	.llong	71b,100b
-	.llong	72b,100b
-	.llong	73b,100b
-	.llong	74b,100b
-	.llong	75b,100b
-	.llong	76b,100b
-	.llong	77b,100b
-	.llong	78b,100b
-	.llong	79b,100b
-	.llong	80b,100b
-	.llong	81b,100b
-	.llong	82b,100b
-	.llong	83b,100b
-	.llong	84b,100b
-	.llong	85b,100b
-	.llong	86b,100b
-	.llong	87b,100b
-	.llong	88b,100b
-	.llong	89b,100b
-	.llong	90b,100b
-	.llong	91b,100b
+	EX_TABLE(20b,100b)
+	EX_TABLE(21b,100b)
+	EX_TABLE(22b,100b)
+	EX_TABLE(23b,100b)
+	EX_TABLE(24b,100b)
+	EX_TABLE(25b,100b)
+	EX_TABLE(26b,100b)
+	EX_TABLE(27b,100b)
+	EX_TABLE(28b,100b)
+	EX_TABLE(29b,100b)
+	EX_TABLE(30b,100b)
+	EX_TABLE(31b,100b)
+	EX_TABLE(32b,100b)
+	EX_TABLE(33b,100b)
+	EX_TABLE(34b,100b)
+	EX_TABLE(35b,100b)
+	EX_TABLE(36b,100b)
+	EX_TABLE(37b,100b)
+	EX_TABLE(38b,100b)
+	EX_TABLE(39b,100b)
+	EX_TABLE(40b,100b)
+	EX_TABLE(41b,100b)
+	EX_TABLE(42b,100b)
+	EX_TABLE(43b,100b)
+	EX_TABLE(44b,100b)
+	EX_TABLE(45b,100b)
+	EX_TABLE(46b,100b)
+	EX_TABLE(47b,100b)
+	EX_TABLE(48b,100b)
+	EX_TABLE(49b,100b)
+	EX_TABLE(50b,100b)
+	EX_TABLE(51b,100b)
+	EX_TABLE(52b,100b)
+	EX_TABLE(53b,100b)
+	EX_TABLE(54b,100b)
+	EX_TABLE(55b,100b)
+	EX_TABLE(56b,100b)
+	EX_TABLE(57b,100b)
+	EX_TABLE(58b,100b)
+	EX_TABLE(59b,100b)
+	EX_TABLE(60b,100b)
+	EX_TABLE(61b,100b)
+	EX_TABLE(62b,100b)
+	EX_TABLE(63b,100b)
+	EX_TABLE(64b,100b)
+	EX_TABLE(65b,100b)
+	EX_TABLE(66b,100b)
+	EX_TABLE(67b,100b)
+	EX_TABLE(68b,100b)
+	EX_TABLE(69b,100b)
+	EX_TABLE(70b,100b)
+	EX_TABLE(71b,100b)
+	EX_TABLE(72b,100b)
+	EX_TABLE(73b,100b)
+	EX_TABLE(74b,100b)
+	EX_TABLE(75b,100b)
+	EX_TABLE(76b,100b)
+	EX_TABLE(77b,100b)
+	EX_TABLE(78b,100b)
+	EX_TABLE(79b,100b)
+	EX_TABLE(80b,100b)
+	EX_TABLE(81b,100b)
+	EX_TABLE(82b,100b)
+	EX_TABLE(83b,100b)
+	EX_TABLE(84b,100b)
+	EX_TABLE(85b,100b)
+	EX_TABLE(86b,100b)
+	EX_TABLE(87b,100b)
+	EX_TABLE(88b,100b)
+	EX_TABLE(89b,100b)
+	EX_TABLE(90b,100b)
+	EX_TABLE(91b,100b)
+
 EXPORT_SYMBOL(__copy_tofrom_user)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/copyuser_power7.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/copyuser_power7.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/copyuser_power7.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/copyuser_power7.S	2017-02-12 16:03:20.000000000 -0500
@@ -29,35 +29,23 @@
 
 	.macro err1
 100:
-	.section __ex_table,"a"
-	.align 3
-	.llong 100b,.Ldo_err1
-	.previous
+	EX_TABLE(100b,.Ldo_err1)
 	.endm
 
 	.macro err2
 200:
-	.section __ex_table,"a"
-	.align 3
-	.llong 200b,.Ldo_err2
-	.previous
+	EX_TABLE(200b,.Ldo_err2)
 	.endm
 
 #ifdef CONFIG_ALTIVEC
 	.macro err3
 300:
-	.section __ex_table,"a"
-	.align 3
-	.llong 300b,.Ldo_err3
-	.previous
+	EX_TABLE(300b,.Ldo_err3)
 	.endm
 
 	.macro err4
 400:
-	.section __ex_table,"a"
-	.align 3
-	.llong 400b,.Ldo_err4
-	.previous
+	EX_TABLE(400b,.Ldo_err4)
 	.endm
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/ldstfp.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/ldstfp.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/ldstfp.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/ldstfp.S	2017-02-12 16:03:20.000000000 -0500
@@ -21,18 +21,12 @@
 
 #define STKFRM	(PPC_MIN_STKFRM + 16)
 
-	.macro	extab	instr,handler
-	.section __ex_table,"a"
-	PPC_LONG \instr,\handler
-	.previous
-	.endm
-
 	.macro	inst32	op
 reg = 0
 	.rept	32
 20:	\op	reg,0,r4
 	b	3f
-	extab	20b,99f
+	EX_TABLE(20b,99f)
 reg = reg + 1
 	.endr
 	.endm
@@ -100,7 +94,7 @@ _GLOBAL(do_lfs)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 
 /* Load FP reg N from double at *p.  N is in r3, p in r4. */
 _GLOBAL(do_lfd)
@@ -127,7 +121,7 @@ _GLOBAL(do_lfd)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 
 /* Store FP reg N to float at *p.  N is in r3, p in r4. */
 _GLOBAL(do_stfs)
@@ -154,7 +148,7 @@ _GLOBAL(do_stfs)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 
 /* Store FP reg N to double at *p.  N is in r3, p in r4. */
 _GLOBAL(do_stfd)
@@ -181,7 +175,7 @@ _GLOBAL(do_stfd)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 
 #ifdef CONFIG_ALTIVEC
 /* Get the contents of vrN into v0; N is in r3. */
@@ -248,7 +242,7 @@ _GLOBAL(do_lvx)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 
 /* Store vector reg N to *p.  N is in r3, p in r4. */
 _GLOBAL(do_stvx)
@@ -276,7 +270,7 @@ _GLOBAL(do_stvx)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_VSX
@@ -344,7 +338,7 @@ _GLOBAL(do_lxvd2x)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 
 /* Store VSX reg N to vector doubleword *p.  N is in r3, p in r4. */
 _GLOBAL(do_stxvd2x)
@@ -372,7 +366,7 @@ _GLOBAL(do_stxvd2x)
 	mr	r3,r9
 	addi	r1,r1,STKFRM
 	blr
-	extab	2b,3b
+	EX_TABLE(2b,3b)
 
 #endif /* CONFIG_VSX */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/sstep.c linux-libre-4.10-rc8-gnu/arch/powerpc/lib/sstep.c
--- linux-libre-4.9-gnu/arch/powerpc/lib/sstep.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/sstep.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,8 @@
 #include <linux/prefetch.h>
 #include <asm/sstep.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <asm/cpu_has_feature.h>
 #include <asm/cputable.h>
 
 extern char system_call_common[];
@@ -493,10 +494,7 @@ static int __kprobes do_vsx_store(int rn
 		"3:	li	%0,%4\n"		\
 		"	b	2b\n"			\
 		".previous\n"				\
-		".section __ex_table,\"a\"\n"		\
-			PPC_LONG_ALIGN "\n"		\
-			PPC_LONG "1b,3b\n"		\
-		".previous"				\
+		EX_TABLE(1b, 3b)			\
 		: "=r" (err), "=r" (cr)			\
 		: "r" (x), "r" (addr), "i" (-EFAULT), "0" (err))
 
@@ -508,10 +506,7 @@ static int __kprobes do_vsx_store(int rn
 		"3:	li	%0,%3\n"		\
 		"	b	2b\n"			\
 		".previous\n"				\
-		".section __ex_table,\"a\"\n"		\
-			PPC_LONG_ALIGN "\n"		\
-			PPC_LONG "1b,3b\n"		\
-		".previous"				\
+		EX_TABLE(1b, 3b)			\
 		: "=r" (err), "=r" (x)			\
 		: "r" (addr), "i" (-EFAULT), "0" (err))
 
@@ -523,10 +518,7 @@ static int __kprobes do_vsx_store(int rn
 		"3:	li	%0,%3\n"		\
 		"	b	2b\n"			\
 		".previous\n"				\
-		".section __ex_table,\"a\"\n"		\
-			PPC_LONG_ALIGN "\n"		\
-			PPC_LONG "1b,3b\n"		\
-		".previous"				\
+		EX_TABLE(1b, 3b)			\
 		: "=r" (err)				\
 		: "r" (addr), "i" (-EFAULT), "0" (err))
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/string_64.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/string_64.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/string_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/string_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
  */
 
 #include <asm/ppc_asm.h>
+#include <asm/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/export.h>
 
@@ -41,26 +42,17 @@ PPC64_CACHES:
 
 	.macro err1
 100:
-	.section __ex_table,"a"
-	.align 3
-	.llong 100b,.Ldo_err1
-	.previous
+	EX_TABLE(100b,.Ldo_err1)
 	.endm
 
 	.macro err2
 200:
-	.section __ex_table,"a"
-	.align 3
-	.llong 200b,.Ldo_err2
-	.previous
+	EX_TABLE(200b,.Ldo_err2)
 	.endm
 
 	.macro err3
 300:
-	.section __ex_table,"a"
-	.align 3
-	.llong 300b,.Ldo_err3
-	.previous
+	EX_TABLE(300b,.Ldo_err3)
 	.endm
 
 .Ldo_err1:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/string.S linux-libre-4.10-rc8-gnu/arch/powerpc/lib/string.S
--- linux-libre-4.9-gnu/arch/powerpc/lib/string.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/string.S	2017-02-12 16:03:20.000000000 -0500
@@ -13,8 +13,6 @@
 #include <asm/ppc_asm.h>
 #include <asm/export.h>
 
-	.section __ex_table,"a"
-	PPC_LONG_ALIGN
 	.text
 	
 /* This clears out any unused part of the destination buffer,
@@ -125,10 +123,9 @@ _GLOBAL(__clear_user)
 92:	mfctr	r3
 	blr
 
-	.section __ex_table,"a"
-	PPC_LONG	11b,90b
-	PPC_LONG	1b,91b
-	PPC_LONG	8b,92b
-	.text
+	EX_TABLE(11b, 90b)
+	EX_TABLE(1b, 91b)
+	EX_TABLE(8b, 92b)
+
 EXPORT_SYMBOL(__clear_user)
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/lib/usercopy_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/lib/usercopy_64.c
--- linux-libre-4.9-gnu/arch/powerpc/lib/usercopy_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/lib/usercopy_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/Makefile linux-libre-4.10-rc8-gnu/arch/powerpc/Makefile
--- linux-libre-4.9-gnu/arch/powerpc/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@ CROSS32AR		:= $(CROSS32_COMPILE)ar
 ifeq ($(HAS_BIARCH),y)
 ifeq ($(CROSS32_COMPILE),)
 CROSS32CC	:= $(CC) -m32
-CROSS32AR	:= GNUTARGET=elf32-powerpc $(AR)
+KBUILD_ARFLAGS	+= --target=elf32-powerpc
 endif
 endif
 
@@ -85,7 +85,7 @@ ifeq ($(HAS_BIARCH),y)
 override AS	+= -a$(BITS)
 override LD	+= -m elf$(BITS)$(LDEMULATION)
 override CC	+= -m$(BITS)
-override AR	:= GNUTARGET=elf$(BITS)-$(GNUTARGET) $(AR)
+KBUILD_ARFLAGS	+= --target=elf$(BITS)-$(GNUTARGET)
 endif
 
 LDFLAGS_vmlinux-y := -Bstatic
@@ -121,6 +121,7 @@ CFLAGS-$(CONFIG_PPC32)	:= -ffixed-r2 $(M
 
 ifeq ($(CONFIG_PPC_BOOK3S_64),y)
 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
+CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=power4
 else
 CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
 endif
@@ -249,6 +250,7 @@ core-y				+= arch/powerpc/kernel/ \
 core-$(CONFIG_XMON)		+= arch/powerpc/xmon/
 core-$(CONFIG_KVM) 		+= arch/powerpc/kvm/
 core-$(CONFIG_PERF_EVENTS)	+= arch/powerpc/perf/
+core-$(CONFIG_KEXEC_FILE)	+= arch/powerpc/purgatory/
 
 drivers-$(CONFIG_OPROFILE)	+= arch/powerpc/oprofile/
 
@@ -275,16 +277,16 @@ zImage: relocs_check
 endif
 
 $(BOOT_TARGETS1): vmlinux
-	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+	$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 $(BOOT_TARGETS2): vmlinux
-	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+	$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
 
 bootwrapper_install:
-	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+	$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
 %.dtb: scripts
-	$(Q)$(MAKE) ARCH=ppc64 $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
+	$(Q)$(MAKE) $(build)=$(boot) $(patsubst %,$(boot)/%,$@)
 
 # Used to create 'merged defconfigs'
 # To use it $(call) it with the first argument as the base defconfig
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fabs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fabs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fabs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fabs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 fabs(u32 *frD, u32 *frB)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fadd.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fadd.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fadd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fadd.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fadds.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fadds.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fadds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fadds.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fcmpo.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fcmpo.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fcmpo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fcmpo.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fcmpu.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fcmpu.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fcmpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fcmpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fctiw.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fctiw.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fctiw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fctiw.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fctiwz.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fctiwz.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fctiwz.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fctiwz.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fdiv.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fdiv.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fdiv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fdiv.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fdivs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fdivs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fdivs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fdivs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fmadd.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmadd.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fmadd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmadd.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fmadds.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmadds.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fmadds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmadds.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fmr.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmr.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fmr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmr.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 fmr(u32 *frD, u32 *frB)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fmsub.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmsub.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fmsub.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmsub.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fmsubs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmsubs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fmsubs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmsubs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fmul.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmul.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fmul.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmul.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fmuls.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmuls.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fmuls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fmuls.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fnabs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnabs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fnabs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnabs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 fnabs(u32 *frD, u32 *frB)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fneg.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fneg.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fneg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fneg.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 fneg(u32 *frD, u32 *frB)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmadd.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmadd.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmadd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmadd.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmadds.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmadds.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmadds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmadds.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmsub.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmsub.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmsub.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmsub.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmsubs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmsubs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fnmsubs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fnmsubs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fre.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fre.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fre.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fre.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int fre(void *frD, void *frB)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fres.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fres.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fres.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fres.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 fres(void *frD, void *frB)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/frsp.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/frsp.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/frsp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/frsp.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/frsqrte.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/frsqrte.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/frsqrte.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/frsqrte.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 frsqrte(void *frD, void *frB)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/frsqrtes.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/frsqrtes.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/frsqrtes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/frsqrtes.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int frsqrtes(void *frD, void *frB)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fsel.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsel.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fsel.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsel.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fsqrt.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsqrt.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fsqrt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsqrt.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fsqrts.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsqrts.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fsqrts.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsqrts.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fsub.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsub.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fsub.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsub.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/fsubs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsubs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/fsubs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/fsubs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/lfd.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/lfd.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/lfd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/lfd.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/double.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/lfs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/lfs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/lfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/lfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/math.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/math.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/math.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/math.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/reg.h>
 #include <asm/switch_to.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/math_efp.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/math_efp.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/math_efp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/math_efp.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/types.h>
 #include <linux/prctl.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/reg.h>
 
 #define FP_EX_BOOKE_E500_SPE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/mcrfs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mcrfs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/mcrfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mcrfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/mffs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mffs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/mffs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mffs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsb0.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsb0.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsb0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsb0.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsb1.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsb1.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsb1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsb1.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsf.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsf.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsf.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsfi.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsfi.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/mtfsfi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/mtfsfi.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/stfd.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/stfd.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/stfd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/stfd.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 stfd(void *frS, void *ea)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/stfiwx.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/stfiwx.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/stfiwx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/stfiwx.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int
 stfiwx(u32 *frS, void *ea)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/math-emu/stfs.c linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/stfs.c
--- linux-libre-4.9-gnu/arch/powerpc/math-emu/stfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/math-emu/stfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/sfp-machine.h>
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/40x_mmu.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/40x_mmu.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/40x_mmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/40x_mmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/smp.h>
 #include <asm/bootx.h>
 #include <asm/machdep.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/copro_fault.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/copro_fault.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/copro_fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/copro_fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -134,6 +134,9 @@ int copro_calculate_slb(struct mm_struct
 		pr_debug("%s: invalid region access at %016llx\n", __func__, ea);
 		return 1;
 	}
+	/* Bad address */
+	if (!vsid)
+		return 1;
 
 	vsid = (vsid << slb_vsid_shift(ssize)) | vsidkey;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/dump_hashpagetable.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/dump_hashpagetable.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/dump_hashpagetable.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/dump_hashpagetable.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,551 @@
+/*
+ * Copyright 2016, Rashmica Gupta, IBM Corp.
+ *
+ * This traverses the kernel virtual memory and dumps the pages that are in
+ * the hash pagetable, along with their flags to
+ * /sys/kernel/debug/kernel_hash_pagetable.
+ *
+ * If radix is enabled then there is no hash page table and so no debugfs file
+ * is generated.
+ *
+ * This program is free software; 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/debugfs.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/plpar_wrappers.h>
+#include <linux/memblock.h>
+#include <asm/firmware.h>
+
+struct pg_state {
+	struct seq_file *seq;
+	const struct addr_marker *marker;
+	unsigned long start_address;
+	unsigned int level;
+	u64 current_flags;
+};
+
+struct addr_marker {
+	unsigned long start_address;
+	const char *name;
+};
+
+static struct addr_marker address_markers[] = {
+	{ 0,	"Start of kernel VM" },
+	{ 0,	"vmalloc() Area" },
+	{ 0,	"vmalloc() End" },
+	{ 0,	"isa I/O start" },
+	{ 0,	"isa I/O end" },
+	{ 0,	"phb I/O start" },
+	{ 0,	"phb I/O end" },
+	{ 0,	"I/O remap start" },
+	{ 0,	"I/O remap end" },
+	{ 0,	"vmemmap start" },
+	{ -1,	NULL },
+};
+
+struct flag_info {
+	u64		mask;
+	u64		val;
+	const char	*set;
+	const char	*clear;
+	bool		is_val;
+	int		shift;
+};
+
+static const struct flag_info v_flag_array[] = {
+	{
+		.mask   = SLB_VSID_B,
+		.val    = SLB_VSID_B_256M,
+		.set    = "ssize: 256M",
+		.clear  = "ssize: 1T  ",
+	}, {
+		.mask	= HPTE_V_SECONDARY,
+		.val	= HPTE_V_SECONDARY,
+		.set	= "secondary",
+		.clear	= "primary  ",
+	}, {
+		.mask	= HPTE_V_VALID,
+		.val	= HPTE_V_VALID,
+		.set	= "valid  ",
+		.clear	= "invalid",
+	}, {
+		.mask	= HPTE_V_BOLTED,
+		.val	= HPTE_V_BOLTED,
+		.set	= "bolted",
+		.clear	= "",
+	}
+};
+
+static const struct flag_info r_flag_array[] = {
+	{
+		.mask	= HPTE_R_PP0 | HPTE_R_PP,
+		.val	= PP_RWXX,
+		.set	= "prot:RW--",
+	}, {
+		.mask	= HPTE_R_PP0 | HPTE_R_PP,
+		.val	= PP_RWRX,
+		.set	= "prot:RWR-",
+	}, {
+		.mask	= HPTE_R_PP0 | HPTE_R_PP,
+		.val	= PP_RWRW,
+		.set	= "prot:RWRW",
+	}, {
+		.mask	= HPTE_R_PP0 | HPTE_R_PP,
+		.val	= PP_RXRX,
+		.set	= "prot:R-R-",
+	}, {
+		.mask	= HPTE_R_PP0 | HPTE_R_PP,
+		.val	= PP_RXXX,
+		.set	= "prot:R---",
+	}, {
+		.mask	= HPTE_R_KEY_HI | HPTE_R_KEY_LO,
+		.val	= HPTE_R_KEY_HI | HPTE_R_KEY_LO,
+		.set	= "key",
+		.clear	= "",
+		.is_val = true,
+	}, {
+		.mask	= HPTE_R_R,
+		.val	= HPTE_R_R,
+		.set	= "ref",
+		.clear	= "   ",
+	}, {
+		.mask	= HPTE_R_C,
+		.val	= HPTE_R_C,
+		.set	= "changed",
+		.clear	= "       ",
+	}, {
+		.mask	= HPTE_R_N,
+		.val	= HPTE_R_N,
+		.set	= "no execute",
+	}, {
+		.mask	= HPTE_R_WIMG,
+		.val	= HPTE_R_W,
+		.set	= "writethru",
+	}, {
+		.mask	= HPTE_R_WIMG,
+		.val	= HPTE_R_I,
+		.set	= "no cache",
+	}, {
+		.mask	= HPTE_R_WIMG,
+		.val	= HPTE_R_G,
+		.set	= "guarded",
+	}
+};
+
+static int calculate_pagesize(struct pg_state *st, int ps, char s[])
+{
+	static const char units[] = "BKMGTPE";
+	const char *unit = units;
+
+	while (ps > 9 && unit[1]) {
+		ps -= 10;
+		unit++;
+	}
+	seq_printf(st->seq, "  %s_ps: %i%c\t", s, 1<<ps, *unit);
+	return ps;
+}
+
+static void dump_flag_info(struct pg_state *st, const struct flag_info
+		*flag, u64 pte, int num)
+{
+	unsigned int i;
+
+	for (i = 0; i < num; i++, flag++) {
+		const char *s = NULL;
+		u64 val;
+
+		/* flag not defined so don't check it */
+		if (flag->mask == 0)
+			continue;
+		/* Some 'flags' are actually values */
+		if (flag->is_val) {
+			val = pte & flag->val;
+			if (flag->shift)
+				val = val >> flag->shift;
+			seq_printf(st->seq, "  %s:%llx", flag->set, val);
+		} else {
+			if ((pte & flag->mask) == flag->val)
+				s = flag->set;
+			else
+				s = flag->clear;
+			if (s)
+				seq_printf(st->seq, "  %s", s);
+		}
+	}
+}
+
+static void dump_hpte_info(struct pg_state *st, unsigned long ea, u64 v, u64 r,
+		unsigned long rpn, int bps, int aps, unsigned long lp)
+{
+	int aps_index;
+
+	while (ea >= st->marker[1].start_address) {
+		st->marker++;
+		seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+	}
+	seq_printf(st->seq, "0x%lx:\t", ea);
+	seq_printf(st->seq, "AVPN:%llx\t", HPTE_V_AVPN_VAL(v));
+	dump_flag_info(st, v_flag_array, v, ARRAY_SIZE(v_flag_array));
+	seq_printf(st->seq, "  rpn: %lx\t", rpn);
+	dump_flag_info(st, r_flag_array, r, ARRAY_SIZE(r_flag_array));
+
+	calculate_pagesize(st, bps, "base");
+	aps_index = calculate_pagesize(st, aps, "actual");
+	if (aps_index != 2)
+		seq_printf(st->seq, "LP enc: %lx", lp);
+	seq_puts(st->seq, "\n");
+}
+
+
+static int native_find(unsigned long ea, int psize, bool primary, u64 *v, u64
+		*r)
+{
+	struct hash_pte *hptep;
+	unsigned long hash, vsid, vpn, hpte_group, want_v, hpte_v;
+	int i, ssize = mmu_kernel_ssize;
+	unsigned long shift = mmu_psize_defs[psize].shift;
+
+	/* calculate hash */
+	vsid = get_kernel_vsid(ea, ssize);
+	vpn  = hpt_vpn(ea, vsid, ssize);
+	hash = hpt_hash(vpn, shift, ssize);
+	want_v = hpte_encode_avpn(vpn, psize, ssize);
+
+	/* to check in the secondary hash table, we invert the hash */
+	if (!primary)
+		hash = ~hash;
+	hpte_group = (hash & htab_hash_mask) * HPTES_PER_GROUP;
+	for (i = 0; i < HPTES_PER_GROUP; i++) {
+		hptep = htab_address + hpte_group;
+		hpte_v = be64_to_cpu(hptep->v);
+
+		if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) {
+			/* HPTE matches */
+			*v = be64_to_cpu(hptep->v);
+			*r = be64_to_cpu(hptep->r);
+			return 0;
+		}
+		++hpte_group;
+	}
+	return -1;
+}
+
+#ifdef CONFIG_PPC_PSERIES
+static int pseries_find(unsigned long ea, int psize, bool primary, u64 *v, u64 *r)
+{
+	struct hash_pte ptes[4];
+	unsigned long vsid, vpn, hash, hpte_group, want_v;
+	int i, j, ssize = mmu_kernel_ssize;
+	long lpar_rc = 0;
+	unsigned long shift = mmu_psize_defs[psize].shift;
+
+	/* calculate hash */
+	vsid = get_kernel_vsid(ea, ssize);
+	vpn  = hpt_vpn(ea, vsid, ssize);
+	hash = hpt_hash(vpn, shift, ssize);
+	want_v = hpte_encode_avpn(vpn, psize, ssize);
+
+	/* to check in the secondary hash table, we invert the hash */
+	if (!primary)
+		hash = ~hash;
+	hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
+	/* see if we can find an entry in the hpte with this hash */
+	for (i = 0; i < HPTES_PER_GROUP; i += 4, hpte_group += 4) {
+		lpar_rc = plpar_pte_read_4(0, hpte_group, (void *)ptes);
+
+		if (lpar_rc != H_SUCCESS)
+			continue;
+		for (j = 0; j < 4; j++) {
+			if (HPTE_V_COMPARE(ptes[j].v, want_v) &&
+					(ptes[j].v & HPTE_V_VALID)) {
+				/* HPTE matches */
+				*v = ptes[j].v;
+				*r = ptes[j].r;
+				return 0;
+			}
+		}
+	}
+	return -1;
+}
+#endif
+
+static void decode_r(int bps, unsigned long r, unsigned long *rpn, int *aps,
+		unsigned long *lp_bits)
+{
+	struct mmu_psize_def entry;
+	unsigned long arpn, mask, lp;
+	int penc = -2, idx = 0, shift;
+
+	/*.
+	 * The LP field has 8 bits. Depending on the actual page size, some of
+	 * these bits are concatenated with the APRN to get the RPN. The rest
+	 * of the bits in the LP field is the LP value and is an encoding for
+	 * the base page size and the actual page size.
+	 *
+	 *  -	find the mmu entry for our base page size
+	 *  -	go through all page encodings and use the associated mask to
+	 *	find an encoding that matches our encoding in the LP field.
+	 */
+	arpn = (r & HPTE_R_RPN) >> HPTE_R_RPN_SHIFT;
+	lp = arpn & 0xff;
+
+	entry = mmu_psize_defs[bps];
+	while (idx < MMU_PAGE_COUNT) {
+		penc = entry.penc[idx];
+		if ((penc != -1) && (mmu_psize_defs[idx].shift)) {
+			shift = mmu_psize_defs[idx].shift -  HPTE_R_RPN_SHIFT;
+			mask = (0x1 << (shift)) - 1;
+			if ((lp & mask) == penc) {
+				*aps = mmu_psize_to_shift(idx);
+				*lp_bits = lp & mask;
+				*rpn = arpn >> shift;
+				return;
+			}
+		}
+		idx++;
+	}
+}
+
+static int base_hpte_find(unsigned long ea, int psize, bool primary, u64 *v,
+			  u64 *r)
+{
+#ifdef CONFIG_PPC_PSERIES
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		return pseries_find(ea, psize, primary, v, r);
+#endif
+	return native_find(ea, psize, primary, v, r);
+}
+
+static unsigned long hpte_find(struct pg_state *st, unsigned long ea, int psize)
+{
+	unsigned long slot;
+	u64 v  = 0, r = 0;
+	unsigned long rpn, lp_bits;
+	int base_psize = 0, actual_psize = 0;
+
+	if (ea <= PAGE_OFFSET)
+		return -1;
+
+	/* Look in primary table */
+	slot = base_hpte_find(ea, psize, true, &v, &r);
+
+	/* Look in secondary table */
+	if (slot == -1)
+		slot = base_hpte_find(ea, psize, true, &v, &r);
+
+	/* No entry found */
+	if (slot == -1)
+		return -1;
+
+	/*
+	 * We found an entry in the hash page table:
+	 *  - check that this has the same base page
+	 *  - find the actual page size
+	 *  - find the RPN
+	 */
+	base_psize = mmu_psize_to_shift(psize);
+
+	if ((v & HPTE_V_LARGE) == HPTE_V_LARGE) {
+		decode_r(psize, r, &rpn, &actual_psize, &lp_bits);
+	} else {
+		/* 4K actual page size */
+		actual_psize = 12;
+		rpn = (r & HPTE_R_RPN) >> HPTE_R_RPN_SHIFT;
+		/* In this case there are no LP bits */
+		lp_bits = -1;
+	}
+	/*
+	 * We didn't find a matching encoding, so the PTE we found isn't for
+	 * this address.
+	 */
+	if (actual_psize == -1)
+		return -1;
+
+	dump_hpte_info(st, ea, v, r, rpn, base_psize, actual_psize, lp_bits);
+	return 0;
+}
+
+static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
+{
+	pte_t *pte = pte_offset_kernel(pmd, 0);
+	unsigned long addr, pteval, psize;
+	int i, status;
+
+	for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
+		addr = start + i * PAGE_SIZE;
+		pteval = pte_val(*pte);
+
+		if (addr < VMALLOC_END)
+			psize = mmu_vmalloc_psize;
+		else
+			psize = mmu_io_psize;
+#ifdef CONFIG_PPC_64K_PAGES
+		/* check for secret 4K mappings */
+		if (((pteval & H_PAGE_COMBO) == H_PAGE_COMBO) ||
+			((pteval & H_PAGE_4K_PFN) == H_PAGE_4K_PFN))
+			psize = mmu_io_psize;
+#endif
+		/* check for hashpte */
+		status = hpte_find(st, addr, psize);
+
+		if (((pteval & H_PAGE_HASHPTE) != H_PAGE_HASHPTE)
+				&& (status != -1)) {
+		/* found a hpte that is not in the linux page tables */
+			seq_printf(st->seq, "page probably bolted before linux"
+				" pagetables were set: addr:%lx, pteval:%lx\n",
+				addr, pteval);
+		}
+	}
+}
+
+static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
+{
+	pmd_t *pmd = pmd_offset(pud, 0);
+	unsigned long addr;
+	unsigned int i;
+
+	for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
+		addr = start + i * PMD_SIZE;
+		if (!pmd_none(*pmd))
+			/* pmd exists */
+			walk_pte(st, pmd, addr);
+	}
+}
+
+static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
+{
+	pud_t *pud = pud_offset(pgd, 0);
+	unsigned long addr;
+	unsigned int i;
+
+	for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
+		addr = start + i * PUD_SIZE;
+		if (!pud_none(*pud))
+			/* pud exists */
+			walk_pmd(st, pud, addr);
+	}
+}
+
+static void walk_pagetables(struct pg_state *st)
+{
+	pgd_t *pgd = pgd_offset_k(0UL);
+	unsigned int i;
+	unsigned long addr;
+
+	/*
+	 * Traverse the linux pagetable structure and dump pages that are in
+	 * the hash pagetable.
+	 */
+	for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
+		addr = KERN_VIRT_START + i * PGDIR_SIZE;
+		if (!pgd_none(*pgd))
+			/* pgd exists */
+			walk_pud(st, pgd, addr);
+	}
+}
+
+
+static void walk_linearmapping(struct pg_state *st)
+{
+	unsigned long addr;
+
+	/*
+	 * Traverse the linear mapping section of virtual memory and dump pages
+	 * that are in the hash pagetable.
+	 */
+	unsigned long psize = 1 << mmu_psize_defs[mmu_linear_psize].shift;
+
+	for (addr = PAGE_OFFSET; addr < PAGE_OFFSET +
+			memblock_phys_mem_size(); addr += psize)
+		hpte_find(st, addr, mmu_linear_psize);
+}
+
+static void walk_vmemmap(struct pg_state *st)
+{
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+	struct vmemmap_backing *ptr = vmemmap_list;
+
+	/*
+	 * Traverse the vmemmaped memory and dump pages that are in the hash
+	 * pagetable.
+	 */
+	while (ptr->list) {
+		hpte_find(st, ptr->virt_addr, mmu_vmemmap_psize);
+		ptr = ptr->list;
+	}
+	seq_puts(st->seq, "---[ vmemmap end ]---\n");
+#endif
+}
+
+static void populate_markers(void)
+{
+	address_markers[0].start_address = PAGE_OFFSET;
+	address_markers[1].start_address = VMALLOC_START;
+	address_markers[2].start_address = VMALLOC_END;
+	address_markers[3].start_address = ISA_IO_BASE;
+	address_markers[4].start_address = ISA_IO_END;
+	address_markers[5].start_address = PHB_IO_BASE;
+	address_markers[6].start_address = PHB_IO_END;
+	address_markers[7].start_address = IOREMAP_BASE;
+	address_markers[8].start_address = IOREMAP_END;
+#ifdef CONFIG_PPC_STD_MMU_64
+	address_markers[9].start_address =  H_VMEMMAP_BASE;
+#else
+	address_markers[9].start_address =  VMEMMAP_BASE;
+#endif
+}
+
+static int ptdump_show(struct seq_file *m, void *v)
+{
+	struct pg_state st = {
+		.seq = m,
+		.start_address = PAGE_OFFSET,
+		.marker = address_markers,
+	};
+	/*
+	 * Traverse the 0xc, 0xd and 0xf areas of the kernel virtual memory and
+	 * dump pages that are in the hash pagetable.
+	 */
+	walk_linearmapping(&st);
+	walk_pagetables(&st);
+	walk_vmemmap(&st);
+	return 0;
+}
+
+static int ptdump_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ptdump_show, NULL);
+}
+
+static const struct file_operations ptdump_fops = {
+	.open		= ptdump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int ptdump_init(void)
+{
+	struct dentry *debugfs_file;
+
+	if (!radix_enabled()) {
+		populate_markers();
+		debugfs_file = debugfs_create_file("kernel_hash_pagetable",
+				0400, NULL, NULL, &ptdump_fops);
+		return debugfs_file ? 0 : -ENOMEM;
+	}
+	return 0;
+}
+device_initcall(ptdump_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/dump_linuxpagetables.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/dump_linuxpagetables.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/dump_linuxpagetables.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/dump_linuxpagetables.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2016, Rashmica Gupta, IBM Corp.
+ *
+ * This traverses the kernel pagetables and dumps the
+ * information about the used sections of memory to
+ * /sys/kernel/debug/kernel_pagetables.
+ *
+ * Derived from the arm64 implementation:
+ * Copyright (c) 2014, The Linux Foundation, Laura Abbott.
+ * (C) Copyright 2008 Intel Corporation, Arjan van de Ven.
+ *
+ * This program is free software; 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/debugfs.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <asm/fixmap.h>
+#include <asm/pgtable.h>
+#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+
+/*
+ * To visualise what is happening,
+ *
+ *  - PTRS_PER_P** = how many entries there are in the corresponding P**
+ *  - P**_SHIFT = how many bits of the address we use to index into the
+ * corresponding P**
+ *  - P**_SIZE is how much memory we can access through the table - not the
+ * size of the table itself.
+ * P**={PGD, PUD, PMD, PTE}
+ *
+ *
+ * Each entry of the PGD points to a PUD. Each entry of a PUD points to a
+ * PMD. Each entry of a PMD points to a PTE. And every PTE entry points to
+ * a page.
+ *
+ * In the case where there are only 3 levels, the PUD is folded into the
+ * PGD: every PUD has only one entry which points to the PMD.
+ *
+ * The page dumper groups page table entries of the same type into a single
+ * description. It uses pg_state to track the range information while
+ * iterating over the PTE entries. When the continuity is broken it then
+ * dumps out a description of the range - ie PTEs that are virtually contiguous
+ * with the same PTE flags are chunked together. This is to make it clear how
+ * different areas of the kernel virtual memory are used.
+ *
+ */
+struct pg_state {
+	struct seq_file *seq;
+	const struct addr_marker *marker;
+	unsigned long start_address;
+	unsigned int level;
+	u64 current_flags;
+};
+
+struct addr_marker {
+	unsigned long start_address;
+	const char *name;
+};
+
+static struct addr_marker address_markers[] = {
+	{ 0,	"Start of kernel VM" },
+	{ 0,	"vmalloc() Area" },
+	{ 0,	"vmalloc() End" },
+	{ 0,	"isa I/O start" },
+	{ 0,	"isa I/O end" },
+	{ 0,	"phb I/O start" },
+	{ 0,	"phb I/O end" },
+	{ 0,	"I/O remap start" },
+	{ 0,	"I/O remap end" },
+	{ 0,	"vmemmap start" },
+	{ -1,	NULL },
+};
+
+struct flag_info {
+	u64		mask;
+	u64		val;
+	const char	*set;
+	const char	*clear;
+	bool		is_val;
+	int		shift;
+};
+
+static const struct flag_info flag_array[] = {
+	{
+#ifdef CONFIG_PPC_STD_MMU_64
+		.mask	= _PAGE_PRIVILEGED,
+		.val	= 0,
+#else
+		.mask	= _PAGE_USER,
+		.val	= _PAGE_USER,
+#endif
+		.set	= "user",
+		.clear	= "    ",
+	}, {
+		.mask	= _PAGE_RW,
+		.val	= _PAGE_RW,
+		.set	= "rw",
+		.clear	= "ro",
+	}, {
+		.mask	= _PAGE_EXEC,
+		.val	= _PAGE_EXEC,
+		.set	= " X ",
+		.clear	= "   ",
+	}, {
+		.mask	= _PAGE_PTE,
+		.val	= _PAGE_PTE,
+		.set	= "pte",
+		.clear	= "   ",
+	}, {
+		.mask	= _PAGE_PRESENT,
+		.val	= _PAGE_PRESENT,
+		.set	= "present",
+		.clear	= "       ",
+	}, {
+#ifdef CONFIG_PPC_STD_MMU_64
+		.mask	= H_PAGE_HASHPTE,
+		.val	= H_PAGE_HASHPTE,
+#else
+		.mask	= _PAGE_HASHPTE,
+		.val	= _PAGE_HASHPTE,
+#endif
+		.set	= "hpte",
+		.clear	= "    ",
+	}, {
+#ifndef CONFIG_PPC_STD_MMU_64
+		.mask	= _PAGE_GUARDED,
+		.val	= _PAGE_GUARDED,
+		.set	= "guarded",
+		.clear	= "       ",
+	}, {
+#endif
+		.mask	= _PAGE_DIRTY,
+		.val	= _PAGE_DIRTY,
+		.set	= "dirty",
+		.clear	= "     ",
+	}, {
+		.mask	= _PAGE_ACCESSED,
+		.val	= _PAGE_ACCESSED,
+		.set	= "accessed",
+		.clear	= "        ",
+	}, {
+#ifndef CONFIG_PPC_STD_MMU_64
+		.mask	= _PAGE_WRITETHRU,
+		.val	= _PAGE_WRITETHRU,
+		.set	= "write through",
+		.clear	= "             ",
+	}, {
+#endif
+		.mask	= _PAGE_NO_CACHE,
+		.val	= _PAGE_NO_CACHE,
+		.set	= "no cache",
+		.clear	= "        ",
+	}, {
+#ifdef CONFIG_PPC_BOOK3S_64
+		.mask	= H_PAGE_BUSY,
+		.val	= H_PAGE_BUSY,
+		.set	= "busy",
+	}, {
+#ifdef CONFIG_PPC_64K_PAGES
+		.mask	= H_PAGE_COMBO,
+		.val	= H_PAGE_COMBO,
+		.set	= "combo",
+	}, {
+		.mask	= H_PAGE_4K_PFN,
+		.val	= H_PAGE_4K_PFN,
+		.set	= "4K_pfn",
+	}, {
+#endif
+		.mask	= H_PAGE_F_GIX,
+		.val	= H_PAGE_F_GIX,
+		.set	= "f_gix",
+		.is_val	= true,
+		.shift	= H_PAGE_F_GIX_SHIFT,
+	}, {
+		.mask	= H_PAGE_F_SECOND,
+		.val	= H_PAGE_F_SECOND,
+		.set	= "f_second",
+	}, {
+#endif
+		.mask	= _PAGE_SPECIAL,
+		.val	= _PAGE_SPECIAL,
+		.set	= "special",
+	}
+};
+
+struct pgtable_level {
+	const struct flag_info *flag;
+	size_t num;
+	u64 mask;
+};
+
+static struct pgtable_level pg_level[] = {
+	{
+	}, { /* pgd */
+		.flag	= flag_array,
+		.num	= ARRAY_SIZE(flag_array),
+	}, { /* pud */
+		.flag	= flag_array,
+		.num	= ARRAY_SIZE(flag_array),
+	}, { /* pmd */
+		.flag	= flag_array,
+		.num	= ARRAY_SIZE(flag_array),
+	}, { /* pte */
+		.flag	= flag_array,
+		.num	= ARRAY_SIZE(flag_array),
+	},
+};
+
+static void dump_flag_info(struct pg_state *st, const struct flag_info
+		*flag, u64 pte, int num)
+{
+	unsigned int i;
+
+	for (i = 0; i < num; i++, flag++) {
+		const char *s = NULL;
+		u64 val;
+
+		/* flag not defined so don't check it */
+		if (flag->mask == 0)
+			continue;
+		/* Some 'flags' are actually values */
+		if (flag->is_val) {
+			val = pte & flag->val;
+			if (flag->shift)
+				val = val >> flag->shift;
+			seq_printf(st->seq, "  %s:%llx", flag->set, val);
+		} else {
+			if ((pte & flag->mask) == flag->val)
+				s = flag->set;
+			else
+				s = flag->clear;
+			if (s)
+				seq_printf(st->seq, "  %s", s);
+		}
+		st->current_flags &= ~flag->mask;
+	}
+	if (st->current_flags != 0)
+		seq_printf(st->seq, "  unknown flags:%llx", st->current_flags);
+}
+
+static void dump_addr(struct pg_state *st, unsigned long addr)
+{
+	static const char units[] = "KMGTPE";
+	const char *unit = units;
+	unsigned long delta;
+
+	seq_printf(st->seq, "0x%016lx-0x%016lx   ", st->start_address, addr-1);
+	delta = (addr - st->start_address) >> 10;
+	/* Work out what appropriate unit to use */
+	while (!(delta & 1023) && unit[1]) {
+		delta >>= 10;
+		unit++;
+	}
+	seq_printf(st->seq, "%9lu%c", delta, *unit);
+
+}
+
+static void note_page(struct pg_state *st, unsigned long addr,
+	       unsigned int level, u64 val)
+{
+	u64 flag = val & pg_level[level].mask;
+	/* At first no level is set */
+	if (!st->level) {
+		st->level = level;
+		st->current_flags = flag;
+		st->start_address = addr;
+		seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+	/*
+	 * Dump the section of virtual memory when:
+	 *   - the PTE flags from one entry to the next differs.
+	 *   - we change levels in the tree.
+	 *   - the address is in a different section of memory and is thus
+	 *   used for a different purpose, regardless of the flags.
+	 */
+	} else if (flag != st->current_flags || level != st->level ||
+		   addr >= st->marker[1].start_address) {
+
+		/* Check the PTE flags */
+		if (st->current_flags) {
+			dump_addr(st, addr);
+
+			/* Dump all the flags */
+			if (pg_level[st->level].flag)
+				dump_flag_info(st, pg_level[st->level].flag,
+					  st->current_flags,
+					  pg_level[st->level].num);
+
+			seq_puts(st->seq, "\n");
+		}
+
+		/*
+		 * Address indicates we have passed the end of the
+		 * current section of virtual memory
+		 */
+		while (addr >= st->marker[1].start_address) {
+			st->marker++;
+			seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
+		}
+		st->start_address = addr;
+		st->current_flags = flag;
+		st->level = level;
+	}
+}
+
+static void walk_pte(struct pg_state *st, pmd_t *pmd, unsigned long start)
+{
+	pte_t *pte = pte_offset_kernel(pmd, 0);
+	unsigned long addr;
+	unsigned int i;
+
+	for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
+		addr = start + i * PAGE_SIZE;
+		note_page(st, addr, 4, pte_val(*pte));
+
+	}
+}
+
+static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
+{
+	pmd_t *pmd = pmd_offset(pud, 0);
+	unsigned long addr;
+	unsigned int i;
+
+	for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
+		addr = start + i * PMD_SIZE;
+		if (!pmd_none(*pmd))
+			/* pmd exists */
+			walk_pte(st, pmd, addr);
+		else
+			note_page(st, addr, 3, pmd_val(*pmd));
+	}
+}
+
+static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
+{
+	pud_t *pud = pud_offset(pgd, 0);
+	unsigned long addr;
+	unsigned int i;
+
+	for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
+		addr = start + i * PUD_SIZE;
+		if (!pud_none(*pud))
+			/* pud exists */
+			walk_pmd(st, pud, addr);
+		else
+			note_page(st, addr, 2, pud_val(*pud));
+	}
+}
+
+static void walk_pagetables(struct pg_state *st)
+{
+	pgd_t *pgd = pgd_offset_k(0UL);
+	unsigned int i;
+	unsigned long addr;
+
+	/*
+	 * Traverse the linux pagetable structure and dump pages that are in
+	 * the hash pagetable.
+	 */
+	for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
+		addr = KERN_VIRT_START + i * PGDIR_SIZE;
+		if (!pgd_none(*pgd))
+			/* pgd exists */
+			walk_pud(st, pgd, addr);
+		else
+			note_page(st, addr, 1, pgd_val(*pgd));
+	}
+}
+
+static void populate_markers(void)
+{
+	address_markers[0].start_address = PAGE_OFFSET;
+	address_markers[1].start_address = VMALLOC_START;
+	address_markers[2].start_address = VMALLOC_END;
+	address_markers[3].start_address = ISA_IO_BASE;
+	address_markers[4].start_address = ISA_IO_END;
+	address_markers[5].start_address = PHB_IO_BASE;
+	address_markers[6].start_address = PHB_IO_END;
+	address_markers[7].start_address = IOREMAP_BASE;
+	address_markers[8].start_address = IOREMAP_END;
+#ifdef CONFIG_PPC_STD_MMU_64
+	address_markers[9].start_address =  H_VMEMMAP_BASE;
+#else
+	address_markers[9].start_address =  VMEMMAP_BASE;
+#endif
+}
+
+static int ptdump_show(struct seq_file *m, void *v)
+{
+	struct pg_state st = {
+		.seq = m,
+		.start_address = KERN_VIRT_START,
+		.marker = address_markers,
+	};
+	/* Traverse kernel page tables */
+	walk_pagetables(&st);
+	note_page(&st, 0, 0, 0);
+	return 0;
+}
+
+
+static int ptdump_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ptdump_show, NULL);
+}
+
+static const struct file_operations ptdump_fops = {
+	.open		= ptdump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void build_pgtable_complete_mask(void)
+{
+	unsigned int i, j;
+
+	for (i = 0; i < ARRAY_SIZE(pg_level); i++)
+		if (pg_level[i].flag)
+			for (j = 0; j < pg_level[i].num; j++)
+				pg_level[i].mask |= pg_level[i].flag[j].mask;
+}
+
+static int ptdump_init(void)
+{
+	struct dentry *debugfs_file;
+
+	populate_markers();
+	build_pgtable_complete_mask();
+	debugfs_file = debugfs_create_file("kernel_pagetables", 0400, NULL,
+			NULL, &ptdump_fops);
+	return debugfs_file ? 0 : -ENOMEM;
+}
+device_initcall(ptdump_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/fault.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/fault.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -253,8 +253,11 @@ int do_page_fault(struct pt_regs *regs,
 	if (unlikely(debugger_fault_handler(regs)))
 		goto bail;
 
-	/* On a kernel SLB miss we can only check for a valid exception entry */
-	if (!user_mode(regs) && (address >= TASK_SIZE)) {
+	/*
+	 * The kernel should never take an execute fault nor should it
+	 * take a page fault to a kernel address.
+	 */
+	if (!user_mode(regs) && (is_exec || (address >= TASK_SIZE))) {
 		rc = SIGSEGV;
 		goto bail;
 	}
@@ -404,6 +407,7 @@ good_area:
 		    (cpu_has_feature(CPU_FTR_NOEXECUTE) ||
 		     !(vma->vm_flags & (VM_READ | VM_WRITE))))
 			goto bad_area;
+
 #ifdef CONFIG_PPC_STD_MMU
 		/*
 		 * protfault should only happen due to us
@@ -512,7 +516,7 @@ void bad_page_fault(struct pt_regs *regs
 
 	/* Are we prepared to handle this fault?  */
 	if ((entry = search_exception_tables(regs->nip)) != NULL) {
-		regs->nip = entry->fixup;
+		regs->nip = extable_fixup(entry);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/fsl_booke_mmu.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/fsl_booke_mmu.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/fsl_booke_mmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/fsl_booke_mmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/smp.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/hash_native_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hash_native_64.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/hash_native_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hash_native_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -123,8 +123,9 @@ static inline void __tlbiel(unsigned lon
 		va |= ssize << 8;
 		sllp = get_sllp_encoding(apsize);
 		va |= sllp << 5;
-		asm volatile(".long 0x7c000224 | (%0 << 11) | (0 << 21)"
-			     : : "r"(va) : "memory");
+		asm volatile(ASM_FTR_IFSET("tlbiel %0", "tlbiel %0,0", %1)
+			     : : "r" (va), "i" (CPU_FTR_ARCH_206)
+			     : "memory");
 		break;
 	default:
 		/* We need 14 to 14 + i bits of va */
@@ -141,8 +142,9 @@ static inline void __tlbiel(unsigned lon
 		 */
 		va |= (vpn & 0xfe);
 		va |= 1; /* L */
-		asm volatile(".long 0x7c000224 | (%0 << 11) | (1 << 21)"
-			     : : "r"(va) : "memory");
+		asm volatile(ASM_FTR_IFSET("tlbiel %0", "tlbiel %0,1", %1)
+			     : : "r" (va), "i" (CPU_FTR_ARCH_206)
+			     : "memory");
 		break;
 	}
 
@@ -221,13 +223,18 @@ static long native_hpte_insert(unsigned
 		return -1;
 
 	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
-	hpte_r = hpte_encode_r(pa, psize, apsize, ssize) | rflags;
+	hpte_r = hpte_encode_r(pa, psize, apsize) | rflags;
 
 	if (!(vflags & HPTE_V_BOLTED)) {
 		DBG_LOW(" i=%x hpte_v=%016lx, hpte_r=%016lx\n",
 			i, hpte_v, hpte_r);
 	}
 
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		hpte_r = hpte_old_to_new_r(hpte_v, hpte_r);
+		hpte_v = hpte_old_to_new_v(hpte_v);
+	}
+
 	hptep->r = cpu_to_be64(hpte_r);
 	/* Guarantee the second dword is visible before the valid bit */
 	eieio();
@@ -295,6 +302,8 @@ static long native_hpte_updatepp(unsigne
 		vpn, want_v & HPTE_V_AVPN, slot, newpp);
 
 	hpte_v = be64_to_cpu(hptep->v);
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		hpte_v = hpte_new_to_old_v(hpte_v, be64_to_cpu(hptep->r));
 	/*
 	 * We need to invalidate the TLB always because hpte_remove doesn't do
 	 * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less
@@ -309,6 +318,8 @@ static long native_hpte_updatepp(unsigne
 		native_lock_hpte(hptep);
 		/* recheck with locks held */
 		hpte_v = be64_to_cpu(hptep->v);
+		if (cpu_has_feature(CPU_FTR_ARCH_300))
+			hpte_v = hpte_new_to_old_v(hpte_v, be64_to_cpu(hptep->r));
 		if (unlikely(!HPTE_V_COMPARE(hpte_v, want_v) ||
 			     !(hpte_v & HPTE_V_VALID))) {
 			ret = -1;
@@ -350,6 +361,8 @@ static long native_hpte_find(unsigned lo
 	for (i = 0; i < HPTES_PER_GROUP; i++) {
 		hptep = htab_address + slot;
 		hpte_v = be64_to_cpu(hptep->v);
+		if (cpu_has_feature(CPU_FTR_ARCH_300))
+			hpte_v = hpte_new_to_old_v(hpte_v, be64_to_cpu(hptep->r));
 
 		if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID))
 			/* HPTE matches */
@@ -409,6 +422,8 @@ static void native_hpte_invalidate(unsig
 	want_v = hpte_encode_avpn(vpn, bpsize, ssize);
 	native_lock_hpte(hptep);
 	hpte_v = be64_to_cpu(hptep->v);
+	if (cpu_has_feature(CPU_FTR_ARCH_300))
+		hpte_v = hpte_new_to_old_v(hpte_v, be64_to_cpu(hptep->r));
 
 	/*
 	 * We need to invalidate the TLB always because hpte_remove doesn't do
@@ -467,6 +482,8 @@ static void native_hugepage_invalidate(u
 		want_v = hpte_encode_avpn(vpn, psize, ssize);
 		native_lock_hpte(hptep);
 		hpte_v = be64_to_cpu(hptep->v);
+		if (cpu_has_feature(CPU_FTR_ARCH_300))
+			hpte_v = hpte_new_to_old_v(hpte_v, be64_to_cpu(hptep->r));
 
 		/* Even if we miss, we need to invalidate the TLB */
 		if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID))
@@ -504,6 +521,10 @@ static void hpte_decode(struct hash_pte
 	/* Look at the 8 bit LP value */
 	unsigned int lp = (hpte_r >> LP_SHIFT) & ((1 << LP_BITS) - 1);
 
+	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
+		hpte_v = hpte_new_to_old_v(hpte_v, hpte_r);
+		hpte_r = hpte_new_to_old_r(hpte_r);
+	}
 	if (!(hpte_v & HPTE_V_LARGE)) {
 		size   = MMU_PAGE_4K;
 		a_size = MMU_PAGE_4K;
@@ -512,11 +533,7 @@ static void hpte_decode(struct hash_pte
 		a_size = hpte_page_sizes[lp] >> 4;
 	}
 	/* This works for all page sizes, and for 256M and 1T segments */
-	if (cpu_has_feature(CPU_FTR_ARCH_300))
-		*ssize = hpte_r >> HPTE_R_3_0_SSIZE_SHIFT;
-	else
-		*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
-
+	*ssize = hpte_v >> HPTE_V_SSIZE_SHIFT;
 	shift = mmu_psize_defs[size].shift;
 
 	avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm);
@@ -639,6 +656,9 @@ static void native_flush_hash_range(unsi
 			want_v = hpte_encode_avpn(vpn, psize, ssize);
 			native_lock_hpte(hptep);
 			hpte_v = be64_to_cpu(hptep->v);
+			if (cpu_has_feature(CPU_FTR_ARCH_300))
+				hpte_v = hpte_new_to_old_v(hpte_v,
+						be64_to_cpu(hptep->r));
 			if (!HPTE_V_COMPARE(hpte_v, want_v) ||
 			    !(hpte_v & HPTE_V_VALID))
 				native_unlock_hpte(hptep);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/hash_utils_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/hash_utils_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hash_utils_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@
 #include <asm/mmu_context.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
 #include <asm/tlbflush.h>
@@ -747,7 +747,7 @@ static unsigned long __init htab_get_tab
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-int create_section_mapping(unsigned long start, unsigned long end)
+int hash__create_section_mapping(unsigned long start, unsigned long end)
 {
 	int rc = htab_bolt_mapping(start, end, __pa(start),
 				   pgprot_val(PAGE_KERNEL), mmu_linear_psize,
@@ -761,7 +761,7 @@ int create_section_mapping(unsigned long
 	return rc;
 }
 
-int remove_section_mapping(unsigned long start, unsigned long end)
+int hash__remove_section_mapping(unsigned long start, unsigned long end)
 {
 	int rc = htab_remove_mapping(start, end, mmu_linear_psize,
 				     mmu_kernel_ssize);
@@ -796,37 +796,17 @@ static void update_hid_for_hash(void)
 static void __init hash_init_partition_table(phys_addr_t hash_table,
 					     unsigned long htab_size)
 {
-	unsigned long ps_field;
-	unsigned long patb_size = 1UL << PATB_SIZE_SHIFT;
+	mmu_partition_table_init();
 
 	/*
-	 * slb llp encoding for the page size used in VPM real mode.
-	 * We can ignore that for lpid 0
+	 * PS field (VRMA page size) is not used for LPID 0, hence set to 0.
+	 * For now, UPRT is 0 and we have no segment table.
 	 */
-	ps_field = 0;
 	htab_size =  __ilog2(htab_size) - 18;
-
-	BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large.");
-	partition_tb = __va(memblock_alloc_base(patb_size, patb_size,
-						MEMBLOCK_ALLOC_ANYWHERE));
-
-	/* Initialize the Partition Table with no entries */
-	memset((void *)partition_tb, 0, patb_size);
-	partition_tb->patb0 = cpu_to_be64(ps_field | hash_table | htab_size);
-	/*
-	 * FIXME!! This should be done via update_partition table
-	 * For now UPRT is 0 for us.
-	 */
-	partition_tb->patb1 = 0;
+	mmu_partition_table_set_entry(0, hash_table | htab_size, 0);
 	pr_info("Partition table %p\n", partition_tb);
 	if (cpu_has_feature(CPU_FTR_POWER9_DD1))
 		update_hid_for_hash();
-	/*
-	 * update partition table control register,
-	 * 64 K size.
-	 */
-	mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
-
 }
 
 static void __init htab_initialize(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/hugetlbpage.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hugetlbpage.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/hugetlbpage.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hugetlbpage.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,8 @@
 #ifdef CONFIG_HUGETLB_PAGE
 
 #define PAGE_SHIFT_64K	16
+#define PAGE_SHIFT_512K	19
+#define PAGE_SHIFT_8M	23
 #define PAGE_SHIFT_16M	24
 #define PAGE_SHIFT_16G	34
 
@@ -38,7 +40,7 @@ unsigned int HPAGE_SHIFT;
  * implementations may have more than one gpage size, so we need multiple
  * arrays
  */
-#ifdef CONFIG_PPC_FSL_BOOK3E
+#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_8xx)
 #define MAX_NUMBER_GPAGES	128
 struct psize_gpages {
 	u64 gpage_list[MAX_NUMBER_GPAGES];
@@ -51,7 +53,7 @@ static u64 gpage_freearray[MAX_NUMBER_GP
 static unsigned nr_gpages;
 #endif
 
-#define hugepd_none(hpd)	((hpd).pd == 0)
+#define hugepd_none(hpd)	(hpd_val(hpd) == 0)
 
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
@@ -64,14 +66,16 @@ static int __hugepte_alloc(struct mm_str
 {
 	struct kmem_cache *cachep;
 	pte_t *new;
-
-#ifdef CONFIG_PPC_FSL_BOOK3E
 	int i;
-	int num_hugepd = 1 << (pshift - pdshift);
-	cachep = hugepte_cache;
-#else
-	cachep = PGT_CACHE(pdshift - pshift);
-#endif
+	int num_hugepd;
+
+	if (pshift >= pdshift) {
+		cachep = hugepte_cache;
+		num_hugepd = 1 << (pshift - pdshift);
+	} else {
+		cachep = PGT_CACHE(pdshift - pshift);
+		num_hugepd = 1;
+	}
 
 	new = kmem_cache_zalloc(cachep, GFP_KERNEL);
 
@@ -89,7 +93,7 @@ static int __hugepte_alloc(struct mm_str
 	smp_wmb();
 
 	spin_lock(&mm->page_table_lock);
-#ifdef CONFIG_PPC_FSL_BOOK3E
+
 	/*
 	 * We have multiple higher-level entries that point to the same
 	 * actual pte location.  Fill in each as we go and backtrack on error.
@@ -99,27 +103,26 @@ static int __hugepte_alloc(struct mm_str
 	for (i = 0; i < num_hugepd; i++, hpdp++) {
 		if (unlikely(!hugepd_none(*hpdp)))
 			break;
-		else
+		else {
+#ifdef CONFIG_PPC_BOOK3S_64
+			*hpdp = __hugepd(__pa(new) |
+					 (shift_to_mmu_psize(pshift) << 2));
+#elif defined(CONFIG_PPC_8xx)
+			*hpdp = __hugepd(__pa(new) |
+					 (pshift == PAGE_SHIFT_8M ? _PMD_PAGE_8M :
+					  _PMD_PAGE_512K) | _PMD_PRESENT);
+#else
 			/* We use the old format for PPC_FSL_BOOK3E */
-			hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
+			*hpdp = __hugepd(((unsigned long)new & ~PD_HUGE) | pshift);
+#endif
+		}
 	}
 	/* 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);
-	}
-#else
-	if (!hugepd_none(*hpdp))
+			*hpdp = __hugepd(0);
 		kmem_cache_free(cachep, new);
-	else {
-#ifdef CONFIG_PPC_BOOK3S_64
-		hpdp->pd = __pa(new) | (shift_to_mmu_psize(pshift) << 2);
-#else
-		hpdp->pd = ((unsigned long)new & ~PD_HUGE) | pshift;
-#endif
 	}
-#endif
 	spin_unlock(&mm->page_table_lock);
 	return 0;
 }
@@ -128,7 +131,7 @@ static int __hugepte_alloc(struct mm_str
  * These macros define how to determine which level of the page table holds
  * the hpdp.
  */
-#ifdef CONFIG_PPC_FSL_BOOK3E
+#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_8xx)
 #define HUGEPD_PGD_SHIFT PGDIR_SHIFT
 #define HUGEPD_PUD_SHIFT PUD_SHIFT
 #else
@@ -136,7 +139,6 @@ static int __hugepte_alloc(struct mm_str
 #define HUGEPD_PUD_SHIFT PMD_SHIFT
 #endif
 
-#ifdef CONFIG_PPC_BOOK3S_64
 /*
  * At this point we do the placement change only for BOOK3S 64. This would
  * possibly work on other subarchs.
@@ -153,6 +155,7 @@ pte_t *huge_pte_alloc(struct mm_struct *
 	addr &= ~(sz-1);
 	pg = pgd_offset(mm, addr);
 
+#ifdef CONFIG_PPC_BOOK3S_64
 	if (pshift == PGDIR_SHIFT)
 		/* 16GB huge page */
 		return (pte_t *) pg;
@@ -178,32 +181,7 @@ pte_t *huge_pte_alloc(struct mm_struct *
 				hpdp = (hugepd_t *)pm;
 		}
 	}
-	if (!hpdp)
-		return NULL;
-
-	BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp));
-
-	if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift))
-		return NULL;
-
-	return hugepte_offset(*hpdp, addr, pdshift);
-}
-
 #else
-
-pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz)
-{
-	pgd_t *pg;
-	pud_t *pu;
-	pmd_t *pm;
-	hugepd_t *hpdp = NULL;
-	unsigned pshift = __ffs(sz);
-	unsigned pdshift = PGDIR_SHIFT;
-
-	addr &= ~(sz-1);
-
-	pg = pgd_offset(mm, addr);
-
 	if (pshift >= HUGEPD_PGD_SHIFT) {
 		hpdp = (hugepd_t *)pg;
 	} else {
@@ -217,7 +195,7 @@ pte_t *huge_pte_alloc(struct mm_struct *
 			hpdp = (hugepd_t *)pm;
 		}
 	}
-
+#endif
 	if (!hpdp)
 		return NULL;
 
@@ -228,9 +206,8 @@ pte_t *huge_pte_alloc(struct mm_struct *
 
 	return hugepte_offset(*hpdp, addr, pdshift);
 }
-#endif
 
-#ifdef CONFIG_PPC_FSL_BOOK3E
+#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_8xx)
 /* Build list of addresses of gigantic pages.  This function is used in early
  * boot before the buddy allocator is setup.
  */
@@ -310,7 +287,11 @@ static int __init do_gpage_early_setup(c
 				npages = 0;
 			if (npages > MAX_NUMBER_GPAGES) {
 				pr_warn("MMU: %lu pages requested for page "
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
 					"size %llu KB, limiting to "
+#else
+					"size %u KB, limiting to "
+#endif
 					__stringify(MAX_NUMBER_GPAGES) "\n",
 					npages, size / 1024);
 				npages = MAX_NUMBER_GPAGES;
@@ -392,7 +373,7 @@ int alloc_bootmem_huge_page(struct hstat
 }
 #endif
 
-#ifdef CONFIG_PPC_FSL_BOOK3E
+#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_8xx)
 #define HUGEPD_FREELIST_SIZE \
 	((PAGE_SIZE - sizeof(struct hugepd_freelist)) / sizeof(pte_t))
 
@@ -442,6 +423,8 @@ static void hugepd_free(struct mmu_gathe
 	}
 	put_cpu_var(hugepd_freelist_cur);
 }
+#else
+static inline void hugepd_free(struct mmu_gather *tlb, void *hugepte) {}
 #endif
 
 static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshift,
@@ -453,13 +436,11 @@ static void free_hugepd_range(struct mmu
 
 	unsigned long pdmask = ~((1UL << pdshift) - 1);
 	unsigned int num_hugepd = 1;
+	unsigned int shift = hugepd_shift(*hpdp);
 
-#ifdef CONFIG_PPC_FSL_BOOK3E
 	/* Note: On fsl the hpdp may be the first of several */
-	num_hugepd = (1 << (hugepd_shift(*hpdp) - pdshift));
-#else
-	unsigned int shift = hugepd_shift(*hpdp);
-#endif
+	if (shift > pdshift)
+		num_hugepd = 1 << (shift - pdshift);
 
 	start &= pdmask;
 	if (start < floor)
@@ -473,13 +454,12 @@ static void free_hugepd_range(struct mmu
 		return;
 
 	for (i = 0; i < num_hugepd; i++, hpdp++)
-		hpdp->pd = 0;
+		*hpdp = __hugepd(0);
 
-#ifdef CONFIG_PPC_FSL_BOOK3E
-	hugepd_free(tlb, hugepte);
-#else
-	pgtable_free_tlb(tlb, hugepte, pdshift - shift);
-#endif
+	if (shift >= pdshift)
+		hugepd_free(tlb, hugepte);
+	else
+		pgtable_free_tlb(tlb, hugepte, pdshift - shift);
 }
 
 static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
@@ -492,6 +472,8 @@ static void hugetlb_free_pmd_range(struc
 
 	start = addr;
 	do {
+		unsigned long more;
+
 		pmd = pmd_offset(pud, addr);
 		next = pmd_addr_end(addr, end);
 		if (!is_hugepd(__hugepd(pmd_val(*pmd)))) {
@@ -502,15 +484,16 @@ static void hugetlb_free_pmd_range(struc
 			WARN_ON(!pmd_none_or_clear_bad(pmd));
 			continue;
 		}
-#ifdef CONFIG_PPC_FSL_BOOK3E
 		/*
 		 * Increment next by the size of the huge mapping since
 		 * there may be more than one entry at this 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 *)pmd));
-#endif
+		more = addr + (1 << hugepd_shift(*(hugepd_t *)pmd));
+		if (more > next)
+			next = more;
+
 		free_hugepd_range(tlb, (hugepd_t *)pmd, PMD_SHIFT,
 				  addr, next, floor, ceiling);
 	} while (addr = next, addr != end);
@@ -550,15 +533,17 @@ static void hugetlb_free_pud_range(struc
 			hugetlb_free_pmd_range(tlb, pud, addr, next, floor,
 					       ceiling);
 		} else {
-#ifdef CONFIG_PPC_FSL_BOOK3E
+			unsigned long more;
 			/*
 			 * Increment next by the size of the huge mapping since
 			 * there may be more than one entry at this 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 *)pud));
-#endif
+			more = addr + (1 << hugepd_shift(*(hugepd_t *)pud));
+			if (more > next)
+				next = more;
+
 			free_hugepd_range(tlb, (hugepd_t *)pud, PUD_SHIFT,
 					  addr, next, floor, ceiling);
 		}
@@ -615,15 +600,17 @@ void hugetlb_free_pgd_range(struct mmu_g
 				continue;
 			hugetlb_free_pud_range(tlb, pgd, addr, next, floor, ceiling);
 		} else {
-#ifdef CONFIG_PPC_FSL_BOOK3E
+			unsigned long more;
 			/*
 			 * Increment next by the size of the huge mapping since
 			 * 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
+			more = addr + (1 << hugepd_shift(*(hugepd_t *)pgd));
+			if (more > next)
+				next = more;
+
 			free_hugepd_range(tlb, (hugepd_t *)pgd, PGDIR_SHIFT,
 					  addr, next, floor, ceiling);
 		}
@@ -753,12 +740,13 @@ static int __init add_huge_page_size(uns
 
 	/* 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))
+	if (size <= PAGE_SIZE)
 		return -EINVAL;
-#else
-	if (!is_power_of_2(size)
-	    || (shift > SLICE_HIGH_SHIFT) || (shift <= PAGE_SHIFT))
+#if defined(CONFIG_PPC_FSL_BOOK3E)
+	if (!is_power_of_4(size))
+		return -EINVAL;
+#elif !defined(CONFIG_PPC_8xx)
+	if (!is_power_of_2(size) || (shift > SLICE_HIGH_SHIFT))
 		return -EINVAL;
 #endif
 
@@ -791,53 +779,15 @@ static int __init hugepage_setup_sz(char
 }
 __setup("hugepagesz=", hugepage_setup_sz);
 
-#ifdef CONFIG_PPC_FSL_BOOK3E
 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;
-
+#if !defined(CONFIG_PPC_FSL_BOOK3E) && !defined(CONFIG_PPC_8xx)
 	if (!radix_enabled() && !mmu_has_feature(MMU_FTR_16M_PAGE))
 		return -ENODEV;
-
+#endif
 	for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) {
 		unsigned shift;
 		unsigned pdshift;
@@ -850,9 +800,9 @@ static int __init hugetlbpage_init(void)
 		if (add_huge_page_size(1ULL << shift) < 0)
 			continue;
 
-		if (shift < PMD_SHIFT)
+		if (shift < HUGEPD_PUD_SHIFT)
 			pdshift = PMD_SHIFT;
-		else if (shift < PUD_SHIFT)
+		else if (shift < HUGEPD_PGD_SHIFT)
 			pdshift = PUD_SHIFT;
 		else
 			pdshift = PGDIR_SHIFT;
@@ -860,14 +810,34 @@ static int __init hugetlbpage_init(void)
 		 * if we have pdshift and shift value same, we don't
 		 * use pgt cache for hugepd.
 		 */
-		if (pdshift != shift) {
+		if (pdshift > shift)
 			pgtable_cache_add(pdshift - shift, NULL);
-			if (!PGT_CACHE(pdshift - shift))
-				panic("hugetlbpage_init(): could not create "
-				      "pgtable cache for %d bit pagesize\n", shift);
+#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_8xx)
+		else if (!hugepte_cache) {
+			/*
+			 * 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__);
+
 		}
+#endif
 	}
 
+#if defined(CONFIG_PPC_FSL_BOOK3E) || defined(CONFIG_PPC_8xx)
+	/* Default hpage size = 4M on FSL_BOOK3E and 512k on 8xx */
+	if (mmu_psize_defs[MMU_PAGE_4M].shift)
+		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_4M].shift;
+	else if (mmu_psize_defs[MMU_PAGE_512K].shift)
+		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_512K].shift;
+#else
 	/* Set default large page size. Currently, we pick 16M or 1M
 	 * depending on what is available
 	 */
@@ -877,11 +847,10 @@ static int __init hugetlbpage_init(void)
 		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_1M].shift;
 	else if (mmu_psize_defs[MMU_PAGE_2M].shift)
 		HPAGE_SHIFT = mmu_psize_defs[MMU_PAGE_2M].shift;
-
-
+#endif
 	return 0;
 }
-#endif
+
 arch_initcall(hugetlbpage_init);
 
 void flush_dcache_icache_hugepage(struct page *page)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/hugetlbpage-hash64.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hugetlbpage-hash64.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/hugetlbpage-hash64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/hugetlbpage-hash64.c	2017-02-12 16:03:20.000000000 -0500
@@ -125,11 +125,14 @@ int __hash_page_huge(unsigned long ea, u
 int hugepd_ok(hugepd_t hpd)
 {
 	bool is_hugepd;
+	unsigned long hpdval;
+
+	hpdval = hpd_val(hpd);
 
 	/*
 	 * We should not find this format in page directory, warn otherwise.
 	 */
-	is_hugepd = (((hpd.pd & 0x3) == 0x0) && ((hpd.pd & HUGEPD_SHIFT_MASK) != 0));
+	is_hugepd = (((hpdval & 0x3) == 0x0) && ((hpdval & HUGEPD_SHIFT_MASK) != 0));
 	WARN(is_hugepd, "Found wrong page directory format\n");
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/init_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/init_64.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/init_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/init_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,7 +51,7 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/smp.h>
 #include <asm/machdep.h>
 #include <asm/tlb.h>
@@ -80,83 +80,6 @@ EXPORT_SYMBOL_GPL(memstart_addr);
 phys_addr_t kernstart_addr;
 EXPORT_SYMBOL_GPL(kernstart_addr);
 
-static void pgd_ctor(void *addr)
-{
-	memset(addr, 0, PGD_TABLE_SIZE);
-}
-
-static void pud_ctor(void *addr)
-{
-	memset(addr, 0, PUD_TABLE_SIZE);
-}
-
-static void pmd_ctor(void *addr)
-{
-	memset(addr, 0, PMD_TABLE_SIZE);
-}
-
-struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE];
-
-/*
- * Create a kmem_cache() for pagetables.  This is not used for PTE
- * pages - they're linked to struct page, come from the normal free
- * pages pool and have a different entry size (see real_pte_t) to
- * everything else.  Caches created by this function are used for all
- * the higher level pagetables, and for hugepage pagetables.
- */
-void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
-{
-	char *name;
-	unsigned long table_size = sizeof(void *) << shift;
-	unsigned long align = table_size;
-
-	/* When batching pgtable pointers for RCU freeing, we store
-	 * the index size in the low bits.  Table alignment must be
-	 * big enough to fit it.
-	 *
-	 * Likewise, hugeapge pagetable pointers contain a (different)
-	 * shift value in the low bits.  All tables must be aligned so
-	 * as to leave enough 0 bits in the address to contain it. */
-	unsigned long minalign = max(MAX_PGTABLE_INDEX_SIZE + 1,
-				     HUGEPD_SHIFT_MASK + 1);
-	struct kmem_cache *new;
-
-	/* It would be nice if this was a BUILD_BUG_ON(), but at the
-	 * moment, gcc doesn't seem to recognize is_power_of_2 as a
-	 * constant expression, so so much for that. */
-	BUG_ON(!is_power_of_2(minalign));
-	BUG_ON((shift < 1) || (shift > MAX_PGTABLE_INDEX_SIZE));
-
-	if (PGT_CACHE(shift))
-		return; /* Already have a cache of this size */
-
-	align = max_t(unsigned long, align, minalign);
-	name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
-	new = kmem_cache_create(name, table_size, align, 0, ctor);
-	kfree(name);
-	pgtable_cache[shift - 1] = new;
-	pr_debug("Allocated pgtable cache for order %d\n", shift);
-}
-
-
-void pgtable_cache_init(void)
-{
-	pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor);
-	pgtable_cache_add(PMD_CACHE_INDEX, pmd_ctor);
-	/*
-	 * In all current configs, when the PUD index exists it's the
-	 * same size as either the pgd or pmd index except with THP enabled
-	 * on book3s 64
-	 */
-	if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE))
-		pgtable_cache_add(PUD_INDEX_SIZE, pud_ctor);
-
-	if (!PGT_CACHE(PGD_INDEX_SIZE) || !PGT_CACHE(PMD_CACHE_INDEX))
-		panic("Couldn't allocate pgtable caches");
-	if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE))
-		panic("Couldn't allocate pud pgtable caches");
-}
-
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 /*
  * Given an address within the vmemmap, determine the pfn of the page that
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/init-common.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/init-common.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/init-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/init-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,104 @@
+/*
+ *  PowerPC version
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ *  and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ *    Copyright (C) 1996 Paul Mackerras
+ *
+ *  Derived from "arch/i386/mm/init.c"
+ *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ *
+ *  Dave Engebretsen <engebret@us.ibm.com>
+ *      Rework for PPC64 port.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the 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/string.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+static void pgd_ctor(void *addr)
+{
+	memset(addr, 0, PGD_TABLE_SIZE);
+}
+
+static void pud_ctor(void *addr)
+{
+	memset(addr, 0, PUD_TABLE_SIZE);
+}
+
+static void pmd_ctor(void *addr)
+{
+	memset(addr, 0, PMD_TABLE_SIZE);
+}
+
+struct kmem_cache *pgtable_cache[MAX_PGTABLE_INDEX_SIZE];
+
+/*
+ * Create a kmem_cache() for pagetables.  This is not used for PTE
+ * pages - they're linked to struct page, come from the normal free
+ * pages pool and have a different entry size (see real_pte_t) to
+ * everything else.  Caches created by this function are used for all
+ * the higher level pagetables, and for hugepage pagetables.
+ */
+void pgtable_cache_add(unsigned shift, void (*ctor)(void *))
+{
+	char *name;
+	unsigned long table_size = sizeof(void *) << shift;
+	unsigned long align = table_size;
+
+	/* When batching pgtable pointers for RCU freeing, we store
+	 * the index size in the low bits.  Table alignment must be
+	 * big enough to fit it.
+	 *
+	 * Likewise, hugeapge pagetable pointers contain a (different)
+	 * shift value in the low bits.  All tables must be aligned so
+	 * as to leave enough 0 bits in the address to contain it. */
+	unsigned long minalign = max(MAX_PGTABLE_INDEX_SIZE + 1,
+				     HUGEPD_SHIFT_MASK + 1);
+	struct kmem_cache *new;
+
+	/* It would be nice if this was a BUILD_BUG_ON(), but at the
+	 * moment, gcc doesn't seem to recognize is_power_of_2 as a
+	 * constant expression, so so much for that. */
+	BUG_ON(!is_power_of_2(minalign));
+	BUG_ON((shift < 1) || (shift > MAX_PGTABLE_INDEX_SIZE));
+
+	if (PGT_CACHE(shift))
+		return; /* Already have a cache of this size */
+
+	align = max_t(unsigned long, align, minalign);
+	name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
+	new = kmem_cache_create(name, table_size, align, 0, ctor);
+	if (!new)
+		panic("Could not allocate pgtable cache for order %d", shift);
+
+	kfree(name);
+	pgtable_cache[shift - 1] = new;
+
+	pr_debug("Allocated pgtable cache for order %d\n", shift);
+}
+
+
+void pgtable_cache_init(void)
+{
+	pgtable_cache_add(PGD_INDEX_SIZE, pgd_ctor);
+
+	if (PMD_CACHE_INDEX && !PGT_CACHE(PMD_CACHE_INDEX))
+		pgtable_cache_add(PMD_CACHE_INDEX, pmd_ctor);
+	/*
+	 * In all current configs, when the PUD index exists it's the
+	 * same size as either the pgd or pmd index except with THP enabled
+	 * on book3s 64
+	 */
+	if (PUD_INDEX_SIZE && !PGT_CACHE(PUD_INDEX_SIZE))
+		pgtable_cache_add(PUD_INDEX_SIZE, pud_ctor);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/Makefile linux-libre-4.10-rc8-gnu/arch/powerpc/mm/Makefile
--- linux-libre-4.9-gnu/arch/powerpc/mm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,8 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -
 ccflags-$(CONFIG_PPC64)	:= $(NO_MINIMAL_TOC)
 
 obj-y				:= fault.o mem.o pgtable.o mmap.o \
-				   init_$(BITS).o pgtable_$(BITS).o
+				   init_$(BITS).o pgtable_$(BITS).o \
+				   init-common.o
 obj-$(CONFIG_PPC_MMU_NOHASH)	+= mmu_context_nohash.o tlb_nohash.o \
 				   tlb_nohash_low.o
 obj-$(CONFIG_PPC_BOOK3E)	+= tlb_low_$(BITS)e.o
@@ -42,3 +43,5 @@ obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-
 obj-$(CONFIG_HIGHMEM)		+= highmem.o
 obj-$(CONFIG_PPC_COPRO_BASE)	+= copro_fault.o
 obj-$(CONFIG_SPAPR_TCE_IOMMU)	+= mmu_context_iommu.o
+obj-$(CONFIG_PPC_PTDUMP)	+= dump_linuxpagetables.o
+obj-$(CONFIG_PPC_HTDUMP)	+= dump_hashpagetable.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/mmu_context_book3s64.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/mmu_context_book3s64.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/mmu_context_book3s64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/mmu_context_book3s64.c	2017-02-12 16:03:20.000000000 -0500
@@ -115,7 +115,7 @@ int init_new_context(struct task_struct
 	mm->context.pte_frag = NULL;
 #endif
 #ifdef CONFIG_SPAPR_TCE_IOMMU
-	mm_iommu_init(&mm->context);
+	mm_iommu_init(mm);
 #endif
 	return 0;
 }
@@ -156,13 +156,11 @@ static inline void destroy_pagetable_pag
 }
 #endif
 
-
 void destroy_context(struct mm_struct *mm)
 {
 #ifdef CONFIG_SPAPR_TCE_IOMMU
-	mm_iommu_cleanup(&mm->context);
+	WARN_ON_ONCE(!list_empty(&mm->context.iommu_group_mem_list));
 #endif
-
 #ifdef CONFIG_PPC_ICSWX
 	drop_cop(mm->context.acop, mm);
 	kfree(mm->context.cop_lockp);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/mmu_context_iommu.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/mmu_context_iommu.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/mmu_context_iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/mmu_context_iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ static long mm_iommu_adjust_locked_vm(st
 	}
 
 	pr_debug("[%d] RLIMIT_MEMLOCK HASH64 %c%ld %ld/%ld\n",
-			current->pid,
+			current ? current->pid : 0,
 			incr ? '+' : '-',
 			npages << PAGE_SHIFT,
 			mm->locked_vm << PAGE_SHIFT,
@@ -66,12 +66,9 @@ static long mm_iommu_adjust_locked_vm(st
 	return ret;
 }
 
-bool mm_iommu_preregistered(void)
+bool mm_iommu_preregistered(struct mm_struct *mm)
 {
-	if (!current || !current->mm)
-		return false;
-
-	return !list_empty(&current->mm->context.iommu_group_mem_list);
+	return !list_empty(&mm->context.iommu_group_mem_list);
 }
 EXPORT_SYMBOL_GPL(mm_iommu_preregistered);
 
@@ -124,19 +121,16 @@ static int mm_iommu_move_page_from_cma(s
 	return 0;
 }
 
-long mm_iommu_get(unsigned long ua, unsigned long entries,
+long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
 		struct mm_iommu_table_group_mem_t **pmem)
 {
 	struct mm_iommu_table_group_mem_t *mem;
 	long i, j, ret = 0, locked_entries = 0;
 	struct page *page = NULL;
 
-	if (!current || !current->mm)
-		return -ESRCH; /* process exited */
-
 	mutex_lock(&mem_list_mutex);
 
-	list_for_each_entry_rcu(mem, &current->mm->context.iommu_group_mem_list,
+	list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list,
 			next) {
 		if ((mem->ua == ua) && (mem->entries == entries)) {
 			++mem->used;
@@ -154,7 +148,7 @@ long mm_iommu_get(unsigned long ua, unsi
 
 	}
 
-	ret = mm_iommu_adjust_locked_vm(current->mm, entries, true);
+	ret = mm_iommu_adjust_locked_vm(mm, entries, true);
 	if (ret)
 		goto unlock_exit;
 
@@ -215,11 +209,11 @@ populate:
 	mem->entries = entries;
 	*pmem = mem;
 
-	list_add_rcu(&mem->next, &current->mm->context.iommu_group_mem_list);
+	list_add_rcu(&mem->next, &mm->context.iommu_group_mem_list);
 
 unlock_exit:
 	if (locked_entries && ret)
-		mm_iommu_adjust_locked_vm(current->mm, locked_entries, false);
+		mm_iommu_adjust_locked_vm(mm, locked_entries, false);
 
 	mutex_unlock(&mem_list_mutex);
 
@@ -264,17 +258,13 @@ static void mm_iommu_free(struct rcu_hea
 static void mm_iommu_release(struct mm_iommu_table_group_mem_t *mem)
 {
 	list_del_rcu(&mem->next);
-	mm_iommu_adjust_locked_vm(current->mm, mem->entries, false);
 	call_rcu(&mem->rcu, mm_iommu_free);
 }
 
-long mm_iommu_put(struct mm_iommu_table_group_mem_t *mem)
+long mm_iommu_put(struct mm_struct *mm, struct mm_iommu_table_group_mem_t *mem)
 {
 	long ret = 0;
 
-	if (!current || !current->mm)
-		return -ESRCH; /* process exited */
-
 	mutex_lock(&mem_list_mutex);
 
 	if (mem->used == 0) {
@@ -297,6 +287,8 @@ long mm_iommu_put(struct mm_iommu_table_
 	/* @mapped became 0 so now mappings are disabled, release the region */
 	mm_iommu_release(mem);
 
+	mm_iommu_adjust_locked_vm(mm, mem->entries, false);
+
 unlock_exit:
 	mutex_unlock(&mem_list_mutex);
 
@@ -304,14 +296,12 @@ unlock_exit:
 }
 EXPORT_SYMBOL_GPL(mm_iommu_put);
 
-struct mm_iommu_table_group_mem_t *mm_iommu_lookup(unsigned long ua,
-		unsigned long size)
+struct mm_iommu_table_group_mem_t *mm_iommu_lookup(struct mm_struct *mm,
+		unsigned long ua, unsigned long size)
 {
 	struct mm_iommu_table_group_mem_t *mem, *ret = NULL;
 
-	list_for_each_entry_rcu(mem,
-			&current->mm->context.iommu_group_mem_list,
-			next) {
+	list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list, next) {
 		if ((mem->ua <= ua) &&
 				(ua + size <= mem->ua +
 				 (mem->entries << PAGE_SHIFT))) {
@@ -324,14 +314,12 @@ struct mm_iommu_table_group_mem_t *mm_io
 }
 EXPORT_SYMBOL_GPL(mm_iommu_lookup);
 
-struct mm_iommu_table_group_mem_t *mm_iommu_find(unsigned long ua,
-		unsigned long entries)
+struct mm_iommu_table_group_mem_t *mm_iommu_find(struct mm_struct *mm,
+		unsigned long ua, unsigned long entries)
 {
 	struct mm_iommu_table_group_mem_t *mem, *ret = NULL;
 
-	list_for_each_entry_rcu(mem,
-			&current->mm->context.iommu_group_mem_list,
-			next) {
+	list_for_each_entry_rcu(mem, &mm->context.iommu_group_mem_list, next) {
 		if ((mem->ua == ua) && (mem->entries == entries)) {
 			ret = mem;
 			break;
@@ -373,17 +361,7 @@ void mm_iommu_mapped_dec(struct mm_iommu
 }
 EXPORT_SYMBOL_GPL(mm_iommu_mapped_dec);
 
-void mm_iommu_init(mm_context_t *ctx)
-{
-	INIT_LIST_HEAD_RCU(&ctx->iommu_group_mem_list);
-}
-
-void mm_iommu_cleanup(mm_context_t *ctx)
+void mm_iommu_init(struct mm_struct *mm)
 {
-	struct mm_iommu_table_group_mem_t *mem, *tmp;
-
-	list_for_each_entry_safe(mem, tmp, &ctx->iommu_group_mem_list, next) {
-		list_del_rcu(&mem->next);
-		mm_iommu_do_free(mem);
-	}
+	INIT_LIST_HEAD_RCU(&mm->context.iommu_group_mem_list);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/numa.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/numa.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/numa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/numa.c	2017-02-12 16:03:20.000000000 -0500
@@ -944,7 +944,7 @@ void __init initmem_init(void)
 	 * _nocalls() + manual invocation is used because cpuhp is not yet
 	 * initialized for the boot CPU.
 	 */
-	cpuhp_setup_state_nocalls(CPUHP_POWER_NUMA_PREPARE, "POWER_NUMA_PREPARE",
+	cpuhp_setup_state_nocalls(CPUHP_POWER_NUMA_PREPARE, "powerpc/numa:prepare",
 				  ppc_numa_cpu_prepare, ppc_numa_cpu_dead);
 	for_each_present_cpu(cpu)
 		numa_setup_cpu(cpu);
@@ -1085,7 +1085,7 @@ static int hot_add_node_scn_to_nid(unsig
 int hot_add_scn_to_nid(unsigned long scn_addr)
 {
 	struct device_node *memory = NULL;
-	int nid, found = 0;
+	int nid;
 
 	if (!numa_enabled || (min_common_depth < 0))
 		return first_online_node;
@@ -1101,17 +1101,6 @@ int hot_add_scn_to_nid(unsigned long scn
 	if (nid < 0 || !node_online(nid))
 		nid = first_online_node;
 
-	if (NODE_DATA(nid)->node_spanned_pages)
-		return nid;
-
-	for_each_online_node(nid) {
-		if (NODE_DATA(nid)->node_spanned_pages) {
-			found = 1;
-			break;
-		}
-	}
-
-	BUG_ON(!found);
 	return nid;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/pgtable_32.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable_32.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/pgtable_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,43 +42,6 @@ EXPORT_SYMBOL(ioremap_bot);	/* aka VMALL
 
 extern char etext[], _stext[], _sinittext[], _einittext[];
 
-#define PGDIR_ORDER	(32 + PGD_T_LOG2 - PGDIR_SHIFT)
-
-#ifndef CONFIG_PPC_4K_PAGES
-static struct kmem_cache *pgtable_cache;
-
-void pgtable_cache_init(void)
-{
-	pgtable_cache = kmem_cache_create("PGDIR cache", 1 << PGDIR_ORDER,
-					  1 << PGDIR_ORDER, 0, NULL);
-	if (pgtable_cache == NULL)
-		panic("Couldn't allocate pgtable caches");
-}
-#endif
-
-pgd_t *pgd_alloc(struct mm_struct *mm)
-{
-	pgd_t *ret;
-
-	/* pgdir take page or two with 4K pages and a page fraction otherwise */
-#ifndef CONFIG_PPC_4K_PAGES
-	ret = kmem_cache_alloc(pgtable_cache, GFP_KERNEL | __GFP_ZERO);
-#else
-	ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
-			PGDIR_ORDER - PAGE_SHIFT);
-#endif
-	return ret;
-}
-
-void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
-#ifndef CONFIG_PPC_4K_PAGES
-	kmem_cache_free(pgtable_cache, (void *)pgd);
-#else
-	free_pages((unsigned long)pgd, PGDIR_ORDER - PAGE_SHIFT);
-#endif
-}
-
 __ref pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
 	pte_t *pte;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/pgtable_64.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable_64.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/pgtable_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -431,3 +431,37 @@ void pgtable_free_tlb(struct mmu_gather
 	}
 }
 #endif
+
+#ifdef CONFIG_PPC_BOOK3S_64
+void __init mmu_partition_table_init(void)
+{
+	unsigned long patb_size = 1UL << PATB_SIZE_SHIFT;
+
+	BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 36), "Partition table size too large.");
+	partition_tb = __va(memblock_alloc_base(patb_size, patb_size,
+						MEMBLOCK_ALLOC_ANYWHERE));
+
+	/* Initialize the Partition Table with no entries */
+	memset((void *)partition_tb, 0, patb_size);
+
+	/*
+	 * update partition table control register,
+	 * 64 K size.
+	 */
+	mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+}
+
+void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
+				   unsigned long dw1)
+{
+	partition_tb[lpid].patb0 = cpu_to_be64(dw0);
+	partition_tb[lpid].patb1 = cpu_to_be64(dw1);
+
+	/* Global flush of TLBs and partition table caches for this lpid */
+	asm volatile("ptesync" : : : "memory");
+	asm volatile(PPC_TLBIE_5(%0,%1,2,0,0) : :
+		     "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
+	asm volatile("eieio; tlbsync; ptesync" : : : "memory");
+}
+EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);
+#endif /* CONFIG_PPC_BOOK3S_64 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/pgtable-book3s64.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable-book3s64.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/pgtable-book3s64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable-book3s64.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,8 @@ int pmdp_set_access_flags(struct vm_area
 #endif
 	changed = !pmd_same(*(pmdp), entry);
 	if (changed) {
-		__ptep_set_access_flags(vma->vm_mm, pmdp_ptep(pmdp), pmd_pte(entry));
+		__ptep_set_access_flags(vma->vm_mm, pmdp_ptep(pmdp),
+					pmd_pte(entry), address);
 		flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
 	}
 	return changed;
@@ -125,3 +126,21 @@ void mmu_cleanup_all(void)
 	else if (mmu_hash_ops.hpte_clear_all)
 		mmu_hash_ops.hpte_clear_all();
 }
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+int create_section_mapping(unsigned long start, unsigned long end)
+{
+	if (radix_enabled())
+		return -ENODEV;
+
+	return hash__create_section_mapping(start, end);
+}
+
+int remove_section_mapping(unsigned long start, unsigned long end)
+{
+	if (radix_enabled())
+		return -ENODEV;
+
+	return hash__remove_section_mapping(start, end);
+}
+#endif /* CONFIG_MEMORY_HOTPLUG */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/pgtable.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/pgtable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable.c	2017-02-12 16:03:20.000000000 -0500
@@ -224,7 +224,7 @@ int ptep_set_access_flags(struct vm_area
 	if (changed) {
 		if (!is_vm_hugetlb_page(vma))
 			assert_pte_locked(vma->vm_mm, address);
-		__ptep_set_access_flags(vma->vm_mm, ptep, entry);
+		__ptep_set_access_flags(vma->vm_mm, ptep, entry, address);
 		flush_tlb_page(vma, address);
 	}
 	return changed;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/pgtable-radix.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable-radix.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/pgtable-radix.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/pgtable-radix.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,7 +65,7 @@ int radix__map_kernel_page(unsigned long
 		if (!pmdp)
 			return -ENOMEM;
 		if (map_page_size == PMD_SIZE) {
-			ptep = (pte_t *)pudp;
+			ptep = pmdp_ptep(pmdp);
 			goto set_the_pte;
 		}
 		ptep = pte_alloc_kernel(pmdp, ea);
@@ -90,7 +90,7 @@ int radix__map_kernel_page(unsigned long
 		}
 		pmdp = pmd_offset(pudp, ea);
 		if (map_page_size == PMD_SIZE) {
-			ptep = (pte_t *)pudp;
+			ptep = pmdp_ptep(pmdp);
 			goto set_the_pte;
 		}
 		if (!pmd_present(*pmdp)) {
@@ -159,7 +159,7 @@ redo:
 	 * Allocate Partition table and process table for the
 	 * host.
 	 */
-	BUILD_BUG_ON_MSG((PRTB_SIZE_SHIFT > 23), "Process table size too large.");
+	BUILD_BUG_ON_MSG((PRTB_SIZE_SHIFT > 36), "Process table size too large.");
 	process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT);
 	/*
 	 * Fill in the process table.
@@ -177,23 +177,15 @@ redo:
 
 static void __init radix_init_partition_table(void)
 {
-	unsigned long rts_field;
+	unsigned long rts_field, dw0;
 
+	mmu_partition_table_init();
 	rts_field = radix__get_tree_size();
+	dw0 = rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE | PATB_HR;
+	mmu_partition_table_set_entry(0, dw0, 0);
 
-	BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 24), "Partition table size too large.");
-	partition_tb = early_alloc_pgtable(1UL << PATB_SIZE_SHIFT);
-	partition_tb->patb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) |
-					  RADIX_PGD_INDEX_SIZE | PATB_HR);
 	pr_info("Initializing Radix MMU\n");
 	pr_info("Partition table %p\n", partition_tb);
-
-	memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
-	/*
-	 * update partition table control register,
-	 * 64 K size.
-	 */
-	mtspr(SPRN_PTCR, __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
 }
 
 void __init radix_init_native(void)
@@ -248,7 +240,7 @@ static int __init radix_dt_scan_page_siz
 		/* top 3 bit is AP encoding */
 		shift = be32_to_cpu(prop[0]) & ~(0xe << 28);
 		ap = be32_to_cpu(prop[0]) >> 29;
-		pr_info("Page size sift = %d AP=0x%x\n", shift, ap);
+		pr_info("Page size shift = %d AP=0x%x\n", shift, ap);
 
 		idx = get_idx_from_shift(shift);
 		if (idx < 0)
@@ -320,6 +312,38 @@ static void update_hid_for_radix(void)
 		cpu_relax();
 }
 
+static void radix_init_amor(void)
+{
+	/*
+	* In HV mode, we init AMOR (Authority Mask Override Register) so that
+	* the hypervisor and guest can setup IAMR (Instruction Authority Mask
+	* Register), enable key 0 and set it to 1.
+	*
+	* AMOR = 0b1100 .... 0000 (Mask for key 0 is 11)
+	*/
+	mtspr(SPRN_AMOR, (3ul << 62));
+}
+
+static void radix_init_iamr(void)
+{
+	unsigned long iamr;
+
+	/*
+	 * The IAMR should set to 0 on DD1.
+	 */
+	if (cpu_has_feature(CPU_FTR_POWER9_DD1))
+		iamr = 0;
+	else
+		iamr = (1ul << 62);
+
+	/*
+	 * Radix always uses key0 of the IAMR to determine if an access is
+	 * allowed. We set bit 0 (IBM bit 1) of key0, to prevent instruction
+	 * fetch.
+	 */
+	mtspr(SPRN_IAMR, iamr);
+}
+
 void __init radix__early_init_mmu(void)
 {
 	unsigned long lpcr;
@@ -376,8 +400,12 @@ void __init radix__early_init_mmu(void)
 		lpcr = mfspr(SPRN_LPCR);
 		mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR);
 		radix_init_partition_table();
+		radix_init_amor();
 	}
 
+	memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
+
+	radix_init_iamr();
 	radix_init_pgtable();
 }
 
@@ -397,7 +425,9 @@ void radix__early_init_mmu_secondary(voi
 
 		mtspr(SPRN_PTCR,
 		      __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
+		radix_init_amor();
 	}
+	radix_init_iamr();
 }
 
 void radix__mmu_cleanup_all(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/subpage-prot.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/subpage-prot.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/subpage-prot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/subpage-prot.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/hugetlb.h>
 
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/tlbflush.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/tlb_nohash.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/tlb_nohash.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/tlb_nohash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/tlb_nohash.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@
  * other sizes not listed here.   The .ind field is only used on MMUs that have
  * indirect page table entries.
  */
-#ifdef CONFIG_PPC_BOOK3E_MMU
+#if defined(CONFIG_PPC_BOOK3E_MMU) || defined(CONFIG_PPC_8xx)
 #ifdef CONFIG_PPC_FSL_BOOK3E
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
 	[MMU_PAGE_4K] = {
@@ -85,6 +85,25 @@ struct mmu_psize_def mmu_psize_defs[MMU_
 		.enc	= BOOK3E_PAGESZ_1GB,
 	},
 };
+#elif defined(CONFIG_PPC_8xx)
+struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
+	/* we only manage 4k and 16k pages as normal pages */
+#ifdef CONFIG_PPC_4K_PAGES
+	[MMU_PAGE_4K] = {
+		.shift	= 12,
+	},
+#else
+	[MMU_PAGE_16K] = {
+		.shift	= 14,
+	},
+#endif
+	[MMU_PAGE_512K] = {
+		.shift	= 19,
+	},
+	[MMU_PAGE_8M] = {
+		.shift	= 23,
+	},
+};
 #else
 struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = {
 	[MMU_PAGE_4K] = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/mm/tlb-radix.c linux-libre-4.10-rc8-gnu/arch/powerpc/mm/tlb-radix.c
--- linux-libre-4.9-gnu/arch/powerpc/mm/tlb-radix.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/mm/tlb-radix.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,9 +50,7 @@ static inline void _tlbiel_pid(unsigned
 	for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) {
 		__tlbiel_pid(pid, set, ric);
 	}
-	if (cpu_has_feature(CPU_FTR_POWER9_DD1))
-		asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
-	return;
+	asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory");
 }
 
 static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
@@ -85,8 +83,6 @@ static inline void _tlbiel_va(unsigned l
 	asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
 		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
 	asm volatile("ptesync": : :"memory");
-	if (cpu_has_feature(CPU_FTR_POWER9_DD1))
-		asm volatile(PPC_INVALIDATE_ERAT : : :"memory");
 }
 
 static inline void _tlbie_va(unsigned long va, unsigned long pid,
@@ -428,3 +424,21 @@ void radix__flush_tlb_all(void)
 		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(0) : "memory");
 	asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
+
+void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
+				 unsigned long address)
+{
+	/*
+	 * We track page size in pte only for DD1, So we can
+	 * call this only on DD1.
+	 */
+	if (!cpu_has_feature(CPU_FTR_POWER9_DD1)) {
+		VM_WARN_ON(1);
+		return;
+	}
+
+	if (old_pte & _PAGE_LARGE)
+		radix__flush_tlb_page_psize(mm, address, MMU_PAGE_2M);
+	else
+		radix__flush_tlb_page_psize(mm, address, mmu_virtual_psize);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/net/bpf_jit_comp64.c linux-libre-4.10-rc8-gnu/arch/powerpc/net/bpf_jit_comp64.c
--- linux-libre-4.9-gnu/arch/powerpc/net/bpf_jit_comp64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/net/bpf_jit_comp64.c	2017-02-12 16:03:20.000000000 -0500
@@ -766,7 +766,7 @@ emit_clear:
 			func = (u8 *) __bpf_call_base + imm;
 
 			/* Save skb pointer if we need to re-cache skb data */
-			if (bpf_helper_changes_skb_data(func))
+			if (bpf_helper_changes_pkt_data(func))
 				PPC_BPF_STL(3, 1, bpf_jit_stack_local(ctx));
 
 			bpf_jit_emit_func_call(image, ctx, (u64)func);
@@ -775,7 +775,7 @@ emit_clear:
 			PPC_MR(b2p[BPF_REG_0], 3);
 
 			/* refresh skb cache */
-			if (bpf_helper_changes_skb_data(func)) {
+			if (bpf_helper_changes_pkt_data(func)) {
 				/* reload skb pointer to r3 */
 				PPC_BPF_LL(3, 1, bpf_jit_stack_local(ctx));
 				bpf_jit_emit_skb_loads(image, ctx);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/oprofile/cell/spu_profiler.c linux-libre-4.10-rc8-gnu/arch/powerpc/oprofile/cell/spu_profiler.c
--- linux-libre-4.9-gnu/arch/powerpc/oprofile/cell/spu_profiler.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/oprofile/cell/spu_profiler.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,7 +180,7 @@ static enum hrtimer_restart profile_spus
 	smp_wmb();	/* insure spu event buffer updates are written */
 			/* don't want events intermingled... */
 
-	kt = ktime_set(0, profiling_interval);
+	kt = profiling_interval;
 	if (!spu_prof_running)
 		goto stop;
 	hrtimer_forward(timer, timer->base->get_time(), kt);
@@ -204,7 +204,7 @@ int start_spu_profiling_cycles(unsigned
 	ktime_t kt;
 
 	pr_debug("timer resolution: %lu\n", TICK_NSEC);
-	kt = ktime_set(0, profiling_interval);
+	kt = profiling_interval;
 	hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	hrtimer_set_expires(&timer, kt);
 	timer.function = profile_spus;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/oprofile/cell/spu_task_sync.c linux-libre-4.10-rc8-gnu/arch/powerpc/oprofile/cell/spu_task_sync.c
--- linux-libre-4.9-gnu/arch/powerpc/oprofile/cell/spu_task_sync.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/oprofile/cell/spu_task_sync.c	2017-02-12 16:03:20.000000000 -0500
@@ -295,7 +295,7 @@ out:
  * dcookie user still being registered (namely, the reader
  * of the event buffer).
  */
-static inline unsigned long fast_get_dcookie(struct path *path)
+static inline unsigned long fast_get_dcookie(const struct path *path)
 {
 	unsigned long cookie;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/perf/core-book3s.c linux-libre-4.10-rc8-gnu/arch/powerpc/perf/core-book3s.c
--- linux-libre-4.9-gnu/arch/powerpc/perf/core-book3s.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/perf/core-book3s.c	2017-02-12 16:03:20.000000000 -0500
@@ -295,6 +295,8 @@ static inline void perf_read_regs(struct
 	 */
 	if (TRAP(regs) != 0xf00)
 		use_siar = 0;
+	else if ((ppmu->flags & PPMU_NO_SIAR))
+		use_siar = 0;
 	else if (marked)
 		use_siar = 1;
 	else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
@@ -2189,7 +2191,7 @@ int register_power_pmu(struct power_pmu
 #endif /* CONFIG_PPC64 */
 
 	perf_pmu_register(&power_pmu, "cpu", PERF_TYPE_RAW);
-	cpuhp_setup_state(CPUHP_PERF_POWER, "PERF_POWER",
+	cpuhp_setup_state(CPUHP_PERF_POWER, "perf/powerpc:prepare",
 			  power_pmu_prepare_cpu, NULL);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/perf/isa207-common.c linux-libre-4.10-rc8-gnu/arch/powerpc/perf/isa207-common.c
--- linux-libre-4.9-gnu/arch/powerpc/perf/isa207-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/perf/isa207-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,40 @@
  */
 #include "isa207-common.h"
 
+PMU_FORMAT_ATTR(event,		"config:0-49");
+PMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
+PMU_FORMAT_ATTR(mark,		"config:8");
+PMU_FORMAT_ATTR(combine,	"config:11");
+PMU_FORMAT_ATTR(unit,		"config:12-15");
+PMU_FORMAT_ATTR(pmc,		"config:16-19");
+PMU_FORMAT_ATTR(cache_sel,	"config:20-23");
+PMU_FORMAT_ATTR(sample_mode,	"config:24-28");
+PMU_FORMAT_ATTR(thresh_sel,	"config:29-31");
+PMU_FORMAT_ATTR(thresh_stop,	"config:32-35");
+PMU_FORMAT_ATTR(thresh_start,	"config:36-39");
+PMU_FORMAT_ATTR(thresh_cmp,	"config:40-49");
+
+struct attribute *isa207_pmu_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_pmcxsel.attr,
+	&format_attr_mark.attr,
+	&format_attr_combine.attr,
+	&format_attr_unit.attr,
+	&format_attr_pmc.attr,
+	&format_attr_cache_sel.attr,
+	&format_attr_sample_mode.attr,
+	&format_attr_thresh_sel.attr,
+	&format_attr_thresh_stop.attr,
+	&format_attr_thresh_start.attr,
+	&format_attr_thresh_cmp.attr,
+	NULL,
+};
+
+struct attribute_group isa207_pmu_format_group = {
+	.name = "format",
+	.attrs = isa207_pmu_format_attr,
+};
+
 static inline bool event_is_fab_match(u64 event)
 {
 	/* Only check pmc, unit and pmcxsel, ignore the edge bit (0) */
@@ -21,6 +55,48 @@ static inline bool event_is_fab_match(u6
 	return (event == 0x30056 || event == 0x4f052);
 }
 
+static bool is_event_valid(u64 event)
+{
+	u64 valid_mask = EVENT_VALID_MASK;
+
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
+		valid_mask = p9_EVENT_VALID_MASK;
+
+	return !(event & ~valid_mask);
+}
+
+static u64 mmcra_sdar_mode(u64 event)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
+		return p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT;
+
+	return MMCRA_SDAR_MODE_TLB;
+}
+
+static u64 thresh_cmp_val(u64 value)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
+		return value << p9_MMCRA_THR_CMP_SHIFT;
+
+	return value << MMCRA_THR_CMP_SHIFT;
+}
+
+static unsigned long combine_from_event(u64 event)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
+		return p9_EVENT_COMBINE(event);
+
+	return EVENT_COMBINE(event);
+}
+
+static unsigned long combine_shift(unsigned long pmc)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
+		return p9_MMCR1_COMBINE_SHIFT(pmc);
+
+	return MMCR1_COMBINE_SHIFT(pmc);
+}
+
 int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 {
 	unsigned int unit, pmc, cache, ebb;
@@ -28,7 +104,7 @@ int isa207_get_constraint(u64 event, uns
 
 	mask = value = 0;
 
-	if (event & ~EVENT_VALID_MASK)
+	if (!is_event_valid(event))
 		return -1;
 
 	pmc   = (event >> EVENT_PMC_SHIFT)        & EVENT_PMC_MASK;
@@ -155,15 +231,13 @@ int isa207_compute_mmcr(u64 event[], int
 			pmc_inuse |= 1 << pmc;
 	}
 
-	/* In continuous sampling mode, update SDAR on TLB miss */
-	mmcra = MMCRA_SDAR_MODE_TLB;
-	mmcr1 = mmcr2 = 0;
+	mmcra = mmcr1 = mmcr2 = 0;
 
 	/* Second pass: assign PMCs, set all MMCR1 fields */
 	for (i = 0; i < n_ev; ++i) {
 		pmc     = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK;
 		unit    = (event[i] >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK;
-		combine = (event[i] >> EVENT_COMBINE_SHIFT) & EVENT_COMBINE_MASK;
+		combine = combine_from_event(event[i]);
 		psel    =  event[i] & EVENT_PSEL_MASK;
 
 		if (!pmc) {
@@ -177,10 +251,13 @@ int isa207_compute_mmcr(u64 event[], int
 
 		if (pmc <= 4) {
 			mmcr1 |= unit << MMCR1_UNIT_SHIFT(pmc);
-			mmcr1 |= combine << MMCR1_COMBINE_SHIFT(pmc);
+			mmcr1 |= combine << combine_shift(pmc);
 			mmcr1 |= psel << MMCR1_PMCSEL_SHIFT(pmc);
 		}
 
+		/* In continuous sampling mode, update SDAR on TLB miss */
+		mmcra |= mmcra_sdar_mode(event[i]);
+
 		if (event[i] & EVENT_IS_L1) {
 			cache = event[i] >> EVENT_CACHE_SEL_SHIFT;
 			mmcr1 |= (cache & 1) << MMCR1_IC_QUAL_SHIFT;
@@ -211,7 +288,7 @@ int isa207_compute_mmcr(u64 event[], int
 			val = (event[i] >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK;
 			mmcra |= val << MMCRA_THR_SEL_SHIFT;
 			val = (event[i] >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK;
-			mmcra |= val << MMCRA_THR_CMP_SHIFT;
+			mmcra |= thresh_cmp_val(val);
 		}
 
 		if (event[i] & EVENT_WANTS_BHRB) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/perf/isa207-common.h linux-libre-4.10-rc8-gnu/arch/powerpc/perf/isa207-common.h
--- linux-libre-4.9-gnu/arch/powerpc/perf/isa207-common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/perf/isa207-common.h	2017-02-12 16:03:20.000000000 -0500
@@ -107,6 +107,7 @@
 #define EVENT_UNIT_MASK		0xf
 #define EVENT_COMBINE_SHIFT	11	/* Combine bit */
 #define EVENT_COMBINE_MASK	0x1
+#define EVENT_COMBINE(v)	(((v) >> EVENT_COMBINE_SHIFT) & EVENT_COMBINE_MASK)
 #define EVENT_MARKED_SHIFT	8	/* Marked bit */
 #define EVENT_MARKED_MASK	0x1
 #define EVENT_IS_MARKED		(EVENT_MARKED_MASK << EVENT_MARKED_SHIFT)
@@ -134,6 +135,26 @@
 	 PERF_SAMPLE_BRANCH_KERNEL      |\
 	 PERF_SAMPLE_BRANCH_HV)
 
+/* Contants to support power9 raw encoding format */
+#define p9_EVENT_COMBINE_SHIFT	10	/* Combine bit */
+#define p9_EVENT_COMBINE_MASK	0x3ull
+#define p9_EVENT_COMBINE(v)	(((v) >> p9_EVENT_COMBINE_SHIFT) & p9_EVENT_COMBINE_MASK)
+#define p9_SDAR_MODE_SHIFT	50
+#define p9_SDAR_MODE_MASK	0x3ull
+#define p9_SDAR_MODE(v)		(((v) >> p9_SDAR_MODE_SHIFT) & p9_SDAR_MODE_MASK)
+
+#define p9_EVENT_VALID_MASK		\
+	((p9_SDAR_MODE_MASK   << p9_SDAR_MODE_SHIFT		|	\
+	(EVENT_THRESH_MASK    << EVENT_THRESH_SHIFT)		|	\
+	(EVENT_SAMPLE_MASK    << EVENT_SAMPLE_SHIFT)		|	\
+	(EVENT_CACHE_SEL_MASK << EVENT_CACHE_SEL_SHIFT)		|	\
+	(EVENT_PMC_MASK       << EVENT_PMC_SHIFT)		|	\
+	(EVENT_UNIT_MASK      << EVENT_UNIT_SHIFT)		|	\
+	(p9_EVENT_COMBINE_MASK << p9_EVENT_COMBINE_SHIFT)	|	\
+	(EVENT_MARKED_MASK    << EVENT_MARKED_SHIFT)		|	\
+	 EVENT_LINUX_MASK					|	\
+	 EVENT_PSEL_MASK))
+
 /*
  * Layout of constraint bits:
  *
@@ -210,15 +231,22 @@
 #define MMCR1_DC_QUAL_SHIFT		47
 #define MMCR1_IC_QUAL_SHIFT		46
 
+/* MMCR1 Combine bits macro for power9 */
+#define p9_MMCR1_COMBINE_SHIFT(pmc)	(38 - ((pmc - 1) * 2))
+
 /* Bits in MMCRA for PowerISA v2.07 */
 #define MMCRA_SAMP_MODE_SHIFT		1
 #define MMCRA_SAMP_ELIG_SHIFT		4
 #define MMCRA_THR_CTL_SHIFT		8
 #define MMCRA_THR_SEL_SHIFT		16
 #define MMCRA_THR_CMP_SHIFT		32
-#define MMCRA_SDAR_MODE_TLB		(1ull << 42)
+#define MMCRA_SDAR_MODE_SHIFT		42
+#define MMCRA_SDAR_MODE_TLB		(1ull << MMCRA_SDAR_MODE_SHIFT)
 #define MMCRA_IFM_SHIFT			30
 
+/* MMCR1 Threshold Compare bit constant for power9 */
+#define p9_MMCRA_THR_CMP_SHIFT	45
+
 /* Bits in MMCR2 for PowerISA v2.07 */
 #define MMCR2_FCS(pmc)			(1ull << (63 - (((pmc) - 1) * 9)))
 #define MMCR2_FCP(pmc)			(1ull << (62 - (((pmc) - 1) * 9)))
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/perf/power8-pmu.c linux-libre-4.10-rc8-gnu/arch/powerpc/perf/power8-pmu.c
--- linux-libre-4.9-gnu/arch/powerpc/perf/power8-pmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/perf/power8-pmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,9 @@ enum {
 #define	POWER8_MMCRA_IFM2		0x0000000080000000UL
 #define	POWER8_MMCRA_IFM3		0x00000000C0000000UL
 
+/* PowerISA v2.07 format attribute structure*/
+extern struct attribute_group isa207_pmu_format_group;
+
 /* Table of alternatives, sorted by column 0 */
 static const unsigned int event_alternatives[][MAX_ALT] = {
 	{ PM_MRK_ST_CMPL,		PM_MRK_ST_CMPL_ALT },
@@ -175,42 +178,8 @@ static struct attribute_group power8_pmu
 	.attrs = power8_events_attr,
 };
 
-PMU_FORMAT_ATTR(event,		"config:0-49");
-PMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
-PMU_FORMAT_ATTR(mark,		"config:8");
-PMU_FORMAT_ATTR(combine,	"config:11");
-PMU_FORMAT_ATTR(unit,		"config:12-15");
-PMU_FORMAT_ATTR(pmc,		"config:16-19");
-PMU_FORMAT_ATTR(cache_sel,	"config:20-23");
-PMU_FORMAT_ATTR(sample_mode,	"config:24-28");
-PMU_FORMAT_ATTR(thresh_sel,	"config:29-31");
-PMU_FORMAT_ATTR(thresh_stop,	"config:32-35");
-PMU_FORMAT_ATTR(thresh_start,	"config:36-39");
-PMU_FORMAT_ATTR(thresh_cmp,	"config:40-49");
-
-static struct attribute *power8_pmu_format_attr[] = {
-	&format_attr_event.attr,
-	&format_attr_pmcxsel.attr,
-	&format_attr_mark.attr,
-	&format_attr_combine.attr,
-	&format_attr_unit.attr,
-	&format_attr_pmc.attr,
-	&format_attr_cache_sel.attr,
-	&format_attr_sample_mode.attr,
-	&format_attr_thresh_sel.attr,
-	&format_attr_thresh_stop.attr,
-	&format_attr_thresh_start.attr,
-	&format_attr_thresh_cmp.attr,
-	NULL,
-};
-
-static struct attribute_group power8_pmu_format_group = {
-	.name = "format",
-	.attrs = power8_pmu_format_attr,
-};
-
 static const struct attribute_group *power8_pmu_attr_groups[] = {
-	&power8_pmu_format_group,
+	&isa207_pmu_format_group,
 	&power8_pmu_events_group,
 	NULL,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/perf/power9-events-list.h linux-libre-4.10-rc8-gnu/arch/powerpc/perf/power9-events-list.h
--- linux-libre-4.9-gnu/arch/powerpc/perf/power9-events-list.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/perf/power9-events-list.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@ EVENT(PM_CYC,					0x0001e)
 EVENT(PM_ICT_NOSLOT_CYC,			0x100f8)
 EVENT(PM_CMPLU_STALL,				0x1e054)
 EVENT(PM_INST_CMPL,				0x00002)
-EVENT(PM_BRU_CMPL,				0x40060)
+EVENT(PM_BRU_CMPL,				0x10012)
 EVENT(PM_BR_MPRED_CMPL,				0x400f6)
 
 /* All L1 D cache load references counted at finish, gated by reject */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/perf/power9-pmu.c linux-libre-4.10-rc8-gnu/arch/powerpc/perf/power9-pmu.c
--- linux-libre-4.9-gnu/arch/powerpc/perf/power9-pmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/perf/power9-pmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,78 @@
 #include "isa207-common.h"
 
 /*
+ * Raw event encoding for Power9:
+ *
+ *        60        56        52        48        44        40        36        32
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ *   | | [ ]                       [ ] [      thresh_cmp     ]   [  thresh_ctl   ]
+ *   | |  |                         |                                     |
+ *   | |  *- IFM (Linux)            |    thresh start/stop OR FAB match -*
+ *   | *- BHRB (Linux)              *sm
+ *   *- EBB (Linux)
+ *
+ *        28        24        20        16        12         8         4         0
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ *   [   ] [  sample ]   [cache]   [ pmc ]   [unit ]   []    m   [    pmcxsel    ]
+ *     |        |           |                          |     |
+ *     |        |           |                          |     *- mark
+ *     |        |           *- L1/L2/L3 cache_sel      |
+ *     |        |                                      |
+ *     |        *- sampling mode for marked events     *- combine
+ *     |
+ *     *- thresh_sel
+ *
+ * Below uses IBM bit numbering.
+ *
+ * MMCR1[x:y] = unit    (PMCxUNIT)
+ * MMCR1[24]   = pmc1combine[0]
+ * MMCR1[25]   = pmc1combine[1]
+ * MMCR1[26]   = pmc2combine[0]
+ * MMCR1[27]   = pmc2combine[1]
+ * MMCR1[28]   = pmc3combine[0]
+ * MMCR1[29]   = pmc3combine[1]
+ * MMCR1[30]   = pmc4combine[0]
+ * MMCR1[31]   = pmc4combine[1]
+ *
+ * if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011
+ *	# PM_MRK_FAB_RSP_MATCH
+ *	MMCR1[20:27] = thresh_ctl   (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
+ * else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001
+ *	# PM_MRK_FAB_RSP_MATCH_CYC
+ *	MMCR1[20:27] = thresh_ctl   (FAB_CRESP_MATCH / FAB_TYPE_MATCH)
+ * else
+ *	MMCRA[48:55] = thresh_ctl   (THRESH START/END)
+ *
+ * if thresh_sel:
+ *	MMCRA[45:47] = thresh_sel
+ *
+ * if thresh_cmp:
+ *	MMCRA[9:11] = thresh_cmp[0:2]
+ *	MMCRA[12:18] = thresh_cmp[3:9]
+ *
+ * if unit == 6 or unit == 7
+ *	MMCRC[53:55] = cache_sel[1:3]      (L2EVENT_SEL)
+ * else if unit == 8 or unit == 9:
+ *	if cache_sel[0] == 0: # L3 bank
+ *		MMCRC[47:49] = cache_sel[1:3]  (L3EVENT_SEL0)
+ *	else if cache_sel[0] == 1:
+ *		MMCRC[50:51] = cache_sel[2:3]  (L3EVENT_SEL1)
+ * else if cache_sel[1]: # L1 event
+ *	MMCR1[16] = cache_sel[2]
+ *	MMCR1[17] = cache_sel[3]
+ *
+ * if mark:
+ *	MMCRA[63]    = 1		(SAMPLE_ENABLE)
+ *	MMCRA[57:59] = sample[0:2]	(RAND_SAMP_ELIG)
+ *	MMCRA[61:62] = sample[3:4]	(RAND_SAMP_MODE)
+ *
+ * if EBB and BHRB:
+ *	MMCRA[32:33] = IFM
+ *
+ * MMCRA[SDAR_MODE]  = sm
+ */
+
+/*
  * Some power9 event codes.
  */
 #define EVENT(_name, _code)	_name = _code,
@@ -31,6 +103,9 @@ enum {
 #define POWER9_MMCRA_IFM2		0x0000000080000000UL
 #define POWER9_MMCRA_IFM3		0x00000000C0000000UL
 
+/* PowerISA v2.07 format attribute structure*/
+extern struct attribute_group isa207_pmu_format_group;
+
 GENERIC_EVENT_ATTR(cpu-cycles,			PM_CYC);
 GENERIC_EVENT_ATTR(stalled-cycles-frontend,	PM_ICT_NOSLOT_CYC);
 GENERIC_EVENT_ATTR(stalled-cycles-backend,	PM_CMPLU_STALL);
@@ -90,10 +165,16 @@ static struct attribute_group power9_pmu
 	.attrs = power9_events_attr,
 };
 
-PMU_FORMAT_ATTR(event,		"config:0-49");
+static const struct attribute_group *power9_isa207_pmu_attr_groups[] = {
+	&isa207_pmu_format_group,
+	&power9_pmu_events_group,
+	NULL,
+};
+
+PMU_FORMAT_ATTR(event,		"config:0-51");
 PMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
 PMU_FORMAT_ATTR(mark,		"config:8");
-PMU_FORMAT_ATTR(combine,	"config:11");
+PMU_FORMAT_ATTR(combine,	"config:10-11");
 PMU_FORMAT_ATTR(unit,		"config:12-15");
 PMU_FORMAT_ATTR(pmc,		"config:16-19");
 PMU_FORMAT_ATTR(cache_sel,	"config:20-23");
@@ -102,6 +183,7 @@ PMU_FORMAT_ATTR(thresh_sel,	"config:29-3
 PMU_FORMAT_ATTR(thresh_stop,	"config:32-35");
 PMU_FORMAT_ATTR(thresh_start,	"config:36-39");
 PMU_FORMAT_ATTR(thresh_cmp,	"config:40-49");
+PMU_FORMAT_ATTR(sdar_mode,	"config:50-51");
 
 static struct attribute *power9_pmu_format_attr[] = {
 	&format_attr_event.attr,
@@ -116,6 +198,7 @@ static struct attribute *power9_pmu_form
 	&format_attr_thresh_stop.attr,
 	&format_attr_thresh_start.attr,
 	&format_attr_thresh_cmp.attr,
+	&format_attr_sdar_mode.attr,
 	NULL,
 };
 
@@ -291,6 +374,24 @@ static int power9_cache_events[C(MAX)][C
 
 #undef C
 
+static struct power_pmu power9_isa207_pmu = {
+	.name			= "POWER9",
+	.n_counter		= MAX_PMU_COUNTERS,
+	.add_fields		= ISA207_ADD_FIELDS,
+	.test_adder		= ISA207_TEST_ADDER,
+	.compute_mmcr		= isa207_compute_mmcr,
+	.config_bhrb		= power9_config_bhrb,
+	.bhrb_filter_map	= power9_bhrb_filter_map,
+	.get_constraint		= isa207_get_constraint,
+	.disable_pmc		= isa207_disable_pmc,
+	.flags			= PPMU_NO_SIAR | PPMU_ARCH_207S,
+	.n_generic		= ARRAY_SIZE(power9_generic_events),
+	.generic_events		= power9_generic_events,
+	.cache_events		= &power9_cache_events,
+	.attr_groups		= power9_isa207_pmu_attr_groups,
+	.bhrb_nr		= 32,
+};
+
 static struct power_pmu power9_pmu = {
 	.name			= "POWER9",
 	.n_counter		= MAX_PMU_COUNTERS,
@@ -311,14 +412,19 @@ static struct power_pmu power9_pmu = {
 
 static int __init init_power9_pmu(void)
 {
-	int rc;
+	int rc = 0;
 
 	/* Comes from cpu_specs[] */
 	if (!cur_cpu_spec->oprofile_cpu_type ||
 	    strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power9"))
 		return -ENODEV;
 
-	rc = register_power_pmu(&power9_pmu);
+	if (cpu_has_feature(CPU_FTR_POWER9_DD1)) {
+		rc = register_power_pmu(&power9_isa207_pmu);
+	} else {
+		rc = register_power_pmu(&power9_pmu);
+	}
+
 	if (rc)
 		return rc;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/40x/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/40x/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/platforms/40x/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/40x/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,7 @@ config XILINX_VIRTEX_GENERIC_BOARD
 	default n
 	select XILINX_VIRTEX_II_PRO
 	select XILINX_VIRTEX_4_FX
+	select XILINX_INTC
 	help
 	  This option enables generic support for Xilinx Virtex based boards.
 
@@ -102,18 +103,18 @@ config 405GP
 	bool
 	select IBM405_ERR77
 	select IBM405_ERR51
-	select IBM_EMAC_ZMII
+	select IBM_EMAC_ZMII if IBM_EMAC
 
 config 405EX
 	bool
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_RGMII
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_RGMII if IBM_EMAC
 
 config 405EZ
 	bool
-	select IBM_EMAC_NO_FLOW_CTRL
-	select IBM_EMAC_MAL_CLR_ICINTSTAT
-	select IBM_EMAC_MAL_COMMON_ERR
+	select IBM_EMAC_NO_FLOW_CTRL if IBM_EMAC
+	select IBM_EMAC_MAL_CLR_ICINTSTAT if IBM_EMAC
+	select IBM_EMAC_MAL_COMMON_ERR if IBM_EMAC
 
 config XILINX_VIRTEX
 	bool
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/40x/virtex.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/40x/virtex.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/40x/virtex.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/40x/virtex.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@ define_machine(virtex) {
 	.probe			= virtex_probe,
 	.setup_arch		= xilinx_pci_init,
 	.init_IRQ		= xilinx_intc_init_tree,
-	.get_irq		= xilinx_intc_get_irq,
+	.get_irq		= xintc_get_irq,
 	.restart		= ppc4xx_reset_system,
 	.calibrate_decr		= generic_calibrate_decr,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/44x/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/44x/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/platforms/44x/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/44x/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@ config BLUESTONE
 	select PCI_MSI
 	select PPC4xx_MSI
 	select PPC4xx_PCI_EXPRESS
-	select IBM_EMAC_RGMII
+	select IBM_EMAC_RGMII if IBM_EMAC
 	help
 	  This option enables support for the APM APM821xx Evaluation board.
 
@@ -125,8 +125,8 @@ config CANYONLANDS
 	select PPC4xx_PCI_EXPRESS
 	select PCI_MSI
 	select PPC4xx_MSI
-	select IBM_EMAC_RGMII
-	select IBM_EMAC_ZMII
+	select IBM_EMAC_RGMII if IBM_EMAC
+	select IBM_EMAC_ZMII if IBM_EMAC
 	help
 	  This option enables support for the AMCC PPC460EX evaluation board.
 
@@ -138,8 +138,8 @@ config GLACIER
 	select 460EX # Odd since it uses 460GT but the effects are the same
 	select PCI
 	select PPC4xx_PCI_EXPRESS
-	select IBM_EMAC_RGMII
-	select IBM_EMAC_ZMII
+	select IBM_EMAC_RGMII if IBM_EMAC
+	select IBM_EMAC_ZMII if IBM_EMAC
 	help
 	  This option enables support for the AMCC PPC460GT evaluation board.
 
@@ -164,7 +164,7 @@ config EIGER
 	select 460SX
 	select PCI
 	select PPC4xx_PCI_EXPRESS
-	select IBM_EMAC_RGMII
+	select IBM_EMAC_RGMII if IBM_EMAC
 	help
 	  This option enables support for the AMCC PPC460SX evaluation board.
 
@@ -213,7 +213,7 @@ config AKEBONO
 	select NETDEVICES
 	select ETHERNET
 	select NET_VENDOR_IBM
-	select IBM_EMAC_EMAC4
+	select IBM_EMAC_EMAC4 if IBM_EMAC
 	select USB if USB_SUPPORT
 	select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD
 	select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD
@@ -241,6 +241,7 @@ config XILINX_VIRTEX440_GENERIC_BOARD
 	depends on 44x
 	default n
 	select XILINX_VIRTEX_5_FXT
+	select XILINX_INTC
 	help
 	  This option enables generic support for Xilinx Virtex based boards
 	  that use a 440 based processor in the Virtex 5 FXT FPGA architecture.
@@ -290,54 +291,54 @@ config 440EP
 	bool
 	select PPC_FPU
 	select IBM440EP_ERR42
-	select IBM_EMAC_ZMII
+	select IBM_EMAC_ZMII if IBM_EMAC
 
 config 440EPX
 	bool
 	select PPC_FPU
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_RGMII
-	select IBM_EMAC_ZMII
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_RGMII if IBM_EMAC
+	select IBM_EMAC_ZMII if IBM_EMAC
 	select USB_EHCI_BIG_ENDIAN_MMIO
 	select USB_EHCI_BIG_ENDIAN_DESC
 
 config 440GRX
 	bool
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_RGMII
-	select IBM_EMAC_ZMII
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_RGMII if IBM_EMAC
+	select IBM_EMAC_ZMII if IBM_EMAC
 
 config 440GP
 	bool
-	select IBM_EMAC_ZMII
+	select IBM_EMAC_ZMII if IBM_EMAC
 
 config 440GX
 	bool
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_RGMII
-	select IBM_EMAC_ZMII #test only
-	select IBM_EMAC_TAH  #test only
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_RGMII if IBM_EMAC
+	select IBM_EMAC_ZMII if IBM_EMAC #test only
+	select IBM_EMAC_TAH if IBM_EMAC  #test only
 
 config 440SP
 	bool
 
 config 440SPe
 	bool
-	select IBM_EMAC_EMAC4
+	select IBM_EMAC_EMAC4 if IBM_EMAC
 
 config 460EX
 	bool
 	select PPC_FPU
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_TAH
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_TAH if IBM_EMAC
 
 config 460SX
 	bool
 	select PPC_FPU
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_RGMII
-	select IBM_EMAC_ZMII
-	select IBM_EMAC_TAH
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_RGMII if IBM_EMAC
+	select IBM_EMAC_ZMII if IBM_EMAC
+	select IBM_EMAC_TAH if IBM_EMAC
 
 config 476FPE
 	bool
@@ -346,8 +347,8 @@ config 476FPE
 config APM821xx
 	bool
 	select PPC_FPU
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_TAH
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_TAH if IBM_EMAC
 
 config 476FPE_ERR46
 	depends on 476FPE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/44x/virtex.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/44x/virtex.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/44x/virtex.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/44x/virtex.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@ define_machine(virtex) {
 	.probe			= virtex_probe,
 	.setup_arch		= xilinx_pci_init,
 	.init_IRQ		= xilinx_intc_init_tree,
-	.get_irq		= xilinx_intc_get_irq,
+	.get_irq		= xintc_get_irq,
 	.calibrate_decr		= generic_calibrate_decr,
 	.restart		= ppc4xx_reset_system,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/83xx/suspend.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/83xx/suspend.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/83xx/suspend.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/83xx/suspend.c	2017-02-12 16:03:20.000000000 -0500
@@ -441,8 +441,4 @@ static struct platform_driver pmc_driver
 	.remove = pmc_remove
 };
 
-static int pmc_init(void)
-{
-	return platform_driver_register(&pmc_driver);
-}
-device_initcall(pmc_init);
+builtin_platform_driver(pmc_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/85xx/corenet_generic.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/85xx/corenet_generic.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/85xx/corenet_generic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/85xx/corenet_generic.c	2017-02-12 16:03:20.000000000 -0500
@@ -117,9 +117,6 @@ static const struct of_device_id of_devi
 	{
 		.compatible	= "fsl,qe",
 	},
-	{
-		.compatible    = "fsl,fman",
-	},
 	/* The following two are for the Freescale hypervisor */
 	{
 		.name		= "hypervisor",
@@ -220,7 +217,7 @@ define_machine(corenet_generic) {
  *
  * Likewise, problems have been seen with kexec when coreint is enabled.
  */
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC_CORE)
 	.get_irq		= mpic_get_irq,
 #else
 	.get_irq		= mpic_get_coreint_irq,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/85xx/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/85xx/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/platforms/85xx/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/85xx/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -253,6 +253,8 @@ endif # PPC32
 config PPC_QEMU_E500
 	bool "QEMU generic e500 platform"
 	select DEFAULT_UIMAGE
+	select E500
+	select PPC_E500MC if PPC64
 	help
 	  This option enables support for running as a QEMU guest using
 	  QEMU's generic e500 machine.  This is not required if you're
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/85xx/smp.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/85xx/smp.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/85xx/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/85xx/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -349,13 +349,13 @@ struct smp_ops_t smp_85xx_ops = {
 	.cpu_disable	= generic_cpu_disable,
 	.cpu_die	= generic_cpu_die,
 #endif
-#if defined(CONFIG_KEXEC) && !defined(CONFIG_PPC64)
+#if defined(CONFIG_KEXEC_CORE) && !defined(CONFIG_PPC64)
 	.give_timebase	= smp_generic_give_timebase,
 	.take_timebase	= smp_generic_take_timebase,
 #endif
 };
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 #ifdef CONFIG_PPC32
 atomic_t kexec_down_cpus = ATOMIC_INIT(0);
 
@@ -458,7 +458,7 @@ static void mpc85xx_smp_machine_kexec(st
 
 	default_machine_kexec(image);
 }
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 static void smp_85xx_basic_setup(int cpu_nr)
 {
@@ -512,7 +512,7 @@ void __init mpc85xx_smp_init(void)
 #endif
 	smp_ops = &smp_85xx_ops;
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	ppc_md.kexec_cpu_down = mpc85xx_smp_kexec_cpu_down;
 	ppc_md.machine_kexec = mpc85xx_smp_machine_kexec;
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/8xx/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/8xx/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/platforms/8xx/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/8xx/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -130,6 +130,7 @@ config 8xx_CPU6
 
 config 8xx_CPU15
 	bool "CPU15 Silicon Errata"
+	depends on !HUGETLB_PAGE
 	default y
 	help
 	  This enables a workaround for erratum CPU15 on MPC8xx chips.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/cell/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/platforms/cell/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -17,10 +17,10 @@ config PPC_CELL_NATIVE
 	select PPC_CELL_COMMON
 	select MPIC
 	select PPC_IO_WORKAROUNDS
-	select IBM_EMAC_EMAC4
-	select IBM_EMAC_RGMII
-	select IBM_EMAC_ZMII #test only
-	select IBM_EMAC_TAH  #test only
+	select IBM_EMAC_EMAC4 if IBM_EMAC
+	select IBM_EMAC_RGMII if IBM_EMAC
+	select IBM_EMAC_ZMII if IBM_EMAC #test only
+	select IBM_EMAC_TAH if IBM_EMAC  #test only
 	default n
 
 config PPC_IBM_CELL_BLADE
@@ -46,7 +46,6 @@ config SPU_FS
 	default m
 	depends on PPC_CELL
 	select SPU_BASE
-	select MEMORY_HOTPLUG
 	help
 	  The SPU file system is used to access Synergistic Processing
 	  Units on machines implementing the Broadband Processor
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spu_base.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spu_base.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spu_base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spu_base.c	2017-02-12 16:03:20.000000000 -0500
@@ -676,7 +676,7 @@ static ssize_t spu_stat_show(struct devi
 
 static DEVICE_ATTR(stat, 0444, spu_stat_show, NULL);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 
 struct crash_spu_info {
 	struct spu *spu;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/coredump.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/coredump.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/coredump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/coredump.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <linux/coredump.h>
 #include <linux/binfmts.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "spufs.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/file.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/file.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/file.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/file.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <asm/time.h>
 #include <asm/spu.h>
 #include <asm/spu_info.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "spufs.h"
 #include "sputrace.h"
@@ -236,7 +236,6 @@ static int
 spufs_mem_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct spu_context *ctx	= vma->vm_file->private_data;
-	unsigned long address = (unsigned long)vmf->virtual_address;
 	unsigned long pfn, offset;
 
 	offset = vmf->pgoff << PAGE_SHIFT;
@@ -244,7 +243,7 @@ spufs_mem_mmap_fault(struct vm_area_stru
 		return VM_FAULT_SIGBUS;
 
 	pr_debug("spufs_mem_mmap_fault address=0x%lx, offset=0x%lx\n",
-			address, offset);
+			vmf->address, offset);
 
 	if (spu_acquire(ctx))
 		return VM_FAULT_NOPAGE;
@@ -256,7 +255,7 @@ spufs_mem_mmap_fault(struct vm_area_stru
 		vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot);
 		pfn = (ctx->spu->local_store_phys + offset) >> PAGE_SHIFT;
 	}
-	vm_insert_pfn(vma, address, pfn);
+	vm_insert_pfn(vma, vmf->address, pfn);
 
 	spu_release(ctx);
 
@@ -355,8 +354,7 @@ static int spufs_ps_fault(struct vm_area
 		down_read(&current->mm->mmap_sem);
 	} else {
 		area = ctx->spu->problem_phys + ps_offs;
-		vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
-					(area + offset) >> PAGE_SHIFT);
+		vm_insert_pfn(vma, vmf->address, (area + offset) >> PAGE_SHIFT);
 		spu_context_trace(spufs_ps_fault__insert, ctx, ctx->spu);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/inode.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/inode.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/inode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/inode.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <asm/prom.h>
 #include <asm/spu.h>
 #include <asm/spu_priv1.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "spufs.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 #include <linux/namei.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "spufs.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/chrp/nvram.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/chrp/nvram.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/chrp/nvram.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/chrp/nvram.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/rtas.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/embedded6xx/holly.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/embedded6xx/holly.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/embedded6xx/holly.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/embedded6xx/holly.c	2017-02-12 16:03:20.000000000 -0500
@@ -263,7 +263,7 @@ static int ppc750_machine_check_exceptio
 	if ((entry = search_exception_tables(regs->nip)) != NULL) {
 		tsi108_clear_pci_cfg_error();
 		regs->msr |= MSR_RI;
-		regs->nip = entry->fixup;
+		regs->nip = extable_fixup(entry);
 		return 1;
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2017-02-12 16:03:20.000000000 -0500
@@ -174,7 +174,7 @@ static int mpc7448_machine_check_excepti
 	if ((entry = search_exception_tables(regs->nip)) != NULL) {
 		tsi108_clear_pci_cfg_error();
 		regs->msr |= MSR_RI;
-		regs->nip = entry->fixup;
+		regs->nip = extable_fixup(entry);
 		return 1;
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/platforms/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -168,17 +168,6 @@ config MPIC_BROKEN_REGREAD
 	  well, but enabling it uses about 8KB of memory to keep copies
 	  of the register contents in software.
 
-config IBMVIO
-	depends on PPC_PSERIES
-	bool
-	default y
-
-config IBMEBUS
-	depends on PPC_PSERIES
-	bool "Support for GX bus based adapters"
-	help
-	  Bus device driver for GX bus based adapters.
-
 config EEH
 	bool
 	depends on (PPC_POWERNV || PPC_PSERIES) && PCI
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/Kconfig.cputype linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/Kconfig.cputype
--- linux-libre-4.9-gnu/arch/powerpc/platforms/Kconfig.cputype	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/Kconfig.cputype	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,7 @@ config PPC_8xx
 	select FSL_SOC
 	select 8xx
 	select PPC_LIB_RHEAP
+	select SYS_SUPPORTS_HUGETLBFS
 
 config 40x
 	bool "AMCC 40x"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powermac/low_i2c.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powermac/low_i2c.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powermac/low_i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powermac/low_i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -90,6 +90,7 @@ struct pmac_i2c_bus
 	int			opened;
 	int			polled;		/* open mode */
 	struct platform_device	*platform_dev;
+	struct lock_class_key   lock_key;
 
 	/* ops */
 	int (*open)(struct pmac_i2c_bus *bus);
@@ -587,6 +588,7 @@ static void __init kw_i2c_add(struct pma
 	bus->close = kw_i2c_close;
 	bus->xfer = kw_i2c_xfer;
 	mutex_init(&bus->mutex);
+	lockdep_set_class(&bus->mutex, &bus->lock_key);
 	if (controller == busnode)
 		bus->flags = pmac_i2c_multibus;
 	list_add(&bus->link, &pmac_i2c_busses);
@@ -815,6 +817,7 @@ static void __init pmu_i2c_probe(void)
 		bus->hostdata = bus + 1;
 		bus->xfer = pmu_i2c_xfer;
 		mutex_init(&bus->mutex);
+		lockdep_set_class(&bus->mutex, &bus->lock_key);
 		bus->flags = pmac_i2c_multibus;
 		list_add(&bus->link, &pmac_i2c_busses);
 
@@ -938,6 +941,7 @@ static void __init smu_i2c_probe(void)
 		bus->hostdata = bus + 1;
 		bus->xfer = smu_i2c_xfer;
 		mutex_init(&bus->mutex);
+		lockdep_set_class(&bus->mutex, &bus->lock_key);
 		bus->flags = 0;
 		list_add(&bus->link, &pmac_i2c_busses);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/eeh-powernv.c	2017-02-12 16:03:20.000000000 -0500
@@ -393,7 +393,7 @@ static void *pnv_eeh_probe(struct pci_dn
 	/* Create PE */
 	ret = eeh_add_to_parent_pe(edev);
 	if (ret) {
-		pr_warn("%s: Can't add PCI dev %04x:%02x:%02x.%01x to parent PE (%d)\n",
+		pr_warn("%s: Can't add PCI dev %04x:%02x:%02x.%01x to parent PE (%x)\n",
 			__func__, hose->global_number, pdn->busno,
 			PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn), ret);
 		return NULL;
@@ -1097,7 +1097,7 @@ static int pnv_eeh_reset(struct eeh_pe *
 
 	bus = eeh_pe_bus_get(pe);
 	if (!bus) {
-		pr_err("%s: Cannot find PCI bus for PHB#%d-PE#%x\n",
+		pr_err("%s: Cannot find PCI bus for PHB#%x-PE#%x\n",
 			__func__, pe->phb->global_number, pe->addr);
 		return -EIO;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/npu-dma.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/npu-dma.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/npu-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/npu-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -263,7 +263,7 @@ static int pnv_npu_dma_set_bypass(struct
 	/* Enable the bypass window */
 
 	top = roundup_pow_of_two(top);
-	dev_info(&npe->pdev->dev, "Enabling bypass for PE %d\n",
+	dev_info(&npe->pdev->dev, "Enabling bypass for PE %x\n",
 			npe->pe_number);
 	rc = opal_pci_map_pe_dma_window_real(phb->opal_id,
 			npe->pe_number, npe->pe_number,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal.c	2017-02-12 16:03:20.000000000 -0500
@@ -632,21 +632,11 @@ static void __init opal_dump_region_init
 			"rc = %d\n", rc);
 }
 
-static void opal_pdev_init(struct device_node *opal_node,
-		const char *compatible)
-{
-	struct device_node *np;
-
-	for_each_child_of_node(opal_node, np)
-		if (of_device_is_compatible(np, compatible))
-			of_platform_device_create(np, NULL, NULL);
-}
-
-static void opal_i2c_create_devs(void)
+static void opal_pdev_init(const char *compatible)
 {
 	struct device_node *np;
 
-	for_each_compatible_node(np, NULL, "ibm,opal-i2c")
+	for_each_compatible_node(np, NULL, compatible)
 		of_platform_device_create(np, NULL, NULL);
 }
 
@@ -718,7 +708,7 @@ static int __init opal_init(void)
 	opal_hmi_handler_init();
 
 	/* Create i2c platform devices */
-	opal_i2c_create_devs();
+	opal_pdev_init("ibm,opal-i2c");
 
 	/* Setup a heatbeat thread if requested by OPAL */
 	opal_init_heartbeat();
@@ -753,12 +743,12 @@ static int __init opal_init(void)
 	}
 
 	/* Initialize platform devices: IPMI backend, PRD & flash interface */
-	opal_pdev_init(opal_node, "ibm,opal-ipmi");
-	opal_pdev_init(opal_node, "ibm,opal-flash");
-	opal_pdev_init(opal_node, "ibm,opal-prd");
+	opal_pdev_init("ibm,opal-ipmi");
+	opal_pdev_init("ibm,opal-flash");
+	opal_pdev_init("ibm,opal-prd");
 
 	/* Initialise platform device: oppanel interface */
-	opal_pdev_init(opal_node, "ibm,opal-oppanel");
+	opal_pdev_init("ibm,opal-oppanel");
 
 	/* Initialise OPAL kmsg dumper for flushing console on panic */
 	opal_kmsg_init();
@@ -896,3 +886,5 @@ EXPORT_SYMBOL_GPL(opal_leds_get_ind);
 EXPORT_SYMBOL_GPL(opal_leds_set_ind);
 /* Export this symbol for PowerNV Operator Panel class driver */
 EXPORT_SYMBOL_GPL(opal_write_oppanel_async);
+/* Export this for KVM */
+EXPORT_SYMBOL_GPL(opal_int_set_mfrr);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-elog.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-elog.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-elog.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-elog.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/vmalloc.h>
 #include <linux/fcntl.h>
 #include <linux/kobject.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/opal.h>
 
 struct elog_obj {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-lpc.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-lpc.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-lpc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-lpc.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <asm/xics.h>
 #include <asm/opal.h>
 #include <asm/prom.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/debug.h>
 
 static int opal_lpc_chip_id = -1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-prd.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-prd.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-prd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-prd.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/opal-prd.h>
 #include <asm/opal.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-tracepoints.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,9 +6,10 @@
 #ifdef HAVE_JUMP_LABEL
 struct static_key opal_tracepoint_key = STATIC_KEY_INIT;
 
-void opal_tracepoint_regfunc(void)
+int opal_tracepoint_regfunc(void)
 {
 	static_key_slow_inc(&opal_tracepoint_key);
+	return 0;
 }
 
 void opal_tracepoint_unregfunc(void)
@@ -25,9 +26,10 @@ void opal_tracepoint_unregfunc(void)
 /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
 extern long opal_tracepoint_refcount;
 
-void opal_tracepoint_regfunc(void)
+int opal_tracepoint_regfunc(void)
 {
 	opal_tracepoint_refcount++;
+	return 0;
 }
 
 void opal_tracepoint_unregfunc(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/opal-wrappers.S	2017-02-12 16:03:20.000000000 -0500
@@ -304,8 +304,11 @@ OPAL_CALL(opal_pci_get_presence_state,
 OPAL_CALL(opal_pci_get_power_state,		OPAL_PCI_GET_POWER_STATE);
 OPAL_CALL(opal_pci_set_power_state,		OPAL_PCI_SET_POWER_STATE);
 OPAL_CALL(opal_int_get_xirr,			OPAL_INT_GET_XIRR);
+OPAL_CALL_REAL(opal_rm_int_get_xirr,		OPAL_INT_GET_XIRR);
 OPAL_CALL(opal_int_set_cppr,			OPAL_INT_SET_CPPR);
 OPAL_CALL(opal_int_eoi,				OPAL_INT_EOI);
+OPAL_CALL_REAL(opal_rm_int_eoi,			OPAL_INT_EOI);
 OPAL_CALL(opal_int_set_mfrr,			OPAL_INT_SET_MFRR);
+OPAL_CALL_REAL(opal_rm_int_set_mfrr,		OPAL_INT_SET_MFRR);
 OPAL_CALL(opal_pci_tce_kill,			OPAL_PCI_TCE_KILL);
 OPAL_CALL_REAL(opal_rm_pci_tce_kill,		OPAL_PCI_TCE_KILL);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/pci.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/pci.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -234,7 +234,7 @@ static void pnv_pci_dump_p7ioc_diag_data
 	int i;
 
 	data = (struct OpalIoP7IOCPhbErrorData *)common;
-	pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n",
+	pr_info("P7IOC PHB#%x Diag-data (Version: %d)\n",
 		hose->global_number, be32_to_cpu(common->version));
 
 	if (data->brdgCtl)
@@ -326,7 +326,7 @@ static void pnv_pci_dump_phb3_diag_data(
 	int i;
 
 	data = (struct OpalIoPhb3ErrorData*)common;
-	pr_info("PHB3 PHB#%d Diag-data (Version: %d)\n",
+	pr_info("PHB3 PHB#%x Diag-data (Version: %d)\n",
 		hose->global_number, be32_to_cpu(common->version));
 	if (data->brdgCtl)
 		pr_info("brdgCtl:     %08x\n",
@@ -516,7 +516,7 @@ static void pnv_pci_config_check_eeh(str
 		}
 	}
 
-	pr_devel(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n",
+	pr_devel(" -> EEH check, bdfn=%04x PE#%x fstate=%x\n",
 		 (pdn->busno << 8) | (pdn->devfn), pe_no, fstate);
 
 	/* Clear the frozen state if applicable */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/pci-ioda.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/pci-ioda.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/pci-ioda.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/pci-ioda.c	2017-02-12 16:03:20.000000000 -0500
@@ -83,7 +83,7 @@ void pe_level_printk(const struct pnv_io
 			PCI_SLOT(pe->rid), PCI_FUNC(pe->rid));
 #endif /* CONFIG_PCI_IOV*/
 
-	printk("%spci %s: [PE# %.3d] %pV",
+	printk("%spci %s: [PE# %.2x] %pV",
 	       level, pfix, pe->pe_number, &vaf);
 
 	va_end(args);
@@ -145,8 +145,8 @@ static struct pnv_ioda_pe *pnv_ioda_init
 	 */
 	rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
 				       OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
-	if (rc != OPAL_SUCCESS)
-		pr_warn("%s: Error %lld unfreezing PHB#%d-PE#%d\n",
+	if (rc != OPAL_SUCCESS && rc != OPAL_UNSUPPORTED)
+		pr_warn("%s: Error %lld unfreezing PHB#%x-PE#%x\n",
 			__func__, rc, phb->hose->global_number, pe_no);
 
 	return &phb->ioda.pe_array[pe_no];
@@ -155,13 +155,13 @@ static struct pnv_ioda_pe *pnv_ioda_init
 static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no)
 {
 	if (!(pe_no >= 0 && pe_no < phb->ioda.total_pe_num)) {
-		pr_warn("%s: Invalid PE %d on PHB#%x\n",
+		pr_warn("%s: Invalid PE %x on PHB#%x\n",
 			__func__, pe_no, phb->hose->global_number);
 		return;
 	}
 
 	if (test_and_set_bit(pe_no, phb->ioda.pe_alloc))
-		pr_debug("%s: PE %d was reserved on PHB#%x\n",
+		pr_debug("%s: PE %x was reserved on PHB#%x\n",
 			 __func__, pe_no, phb->hose->global_number);
 
 	pnv_ioda_init_pe(phb, pe_no);
@@ -229,7 +229,7 @@ static int pnv_ioda2_init_m64(struct pnv
 	else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
 		r->end -= (2 * phb->ioda.m64_segsize);
 	else
-		pr_warn("  Cannot strip M64 segment for reserved PE#%d\n",
+		pr_warn("  Cannot strip M64 segment for reserved PE#%x\n",
 			phb->ioda.reserved_pe_idx);
 
 	return 0;
@@ -291,7 +291,7 @@ static int pnv_ioda1_init_m64(struct pnv
 				OPAL_M64_WINDOW_TYPE, index, base, 0,
 				PNV_IODA1_M64_SEGS * segsz);
 		if (rc != OPAL_SUCCESS) {
-			pr_warn("  Error %lld setting M64 PHB#%d-BAR#%d\n",
+			pr_warn("  Error %lld setting M64 PHB#%x-BAR#%d\n",
 				rc, phb->hose->global_number, index);
 			goto fail;
 		}
@@ -300,7 +300,7 @@ static int pnv_ioda1_init_m64(struct pnv
 				OPAL_M64_WINDOW_TYPE, index,
 				OPAL_ENABLE_M64_SPLIT);
 		if (rc != OPAL_SUCCESS) {
-			pr_warn("  Error %lld enabling M64 PHB#%d-BAR#%d\n",
+			pr_warn("  Error %lld enabling M64 PHB#%x-BAR#%d\n",
 				rc, phb->hose->global_number, index);
 			goto fail;
 		}
@@ -316,7 +316,7 @@ static int pnv_ioda1_init_m64(struct pnv
 	else if (phb->ioda.reserved_pe_idx == (phb->ioda.total_pe_num - 1))
 		r->end -= (2 * phb->ioda.m64_segsize);
 	else
-		WARN(1, "Wrong reserved PE#%d on PHB#%d\n",
+		WARN(1, "Wrong reserved PE#%x on PHB#%x\n",
 		     phb->ioda.reserved_pe_idx, phb->hose->global_number);
 
 	return 0;
@@ -414,7 +414,7 @@ static struct pnv_ioda_pe *pnv_ioda_pick
 					pe->pe_number / PNV_IODA1_M64_SEGS,
 					pe->pe_number % PNV_IODA1_M64_SEGS);
 			if (rc != OPAL_SUCCESS)
-				pr_warn("%s: Error %lld mapping M64 for PHB#%d-PE#%d\n",
+				pr_warn("%s: Error %lld mapping M64 for PHB#%x-PE#%x\n",
 					__func__, rc, phb->hose->global_number,
 					pe->pe_number);
 		}
@@ -941,14 +941,14 @@ static int pnv_ioda_configure_pe(struct
 	pe->mve_number = pe->pe_number;
 	rc = opal_pci_set_mve(phb->opal_id, pe->mve_number, pe->pe_number);
 	if (rc != OPAL_SUCCESS) {
-		pe_err(pe, "OPAL error %ld setting up MVE %d\n",
+		pe_err(pe, "OPAL error %ld setting up MVE %x\n",
 		       rc, pe->mve_number);
 		pe->mve_number = -1;
 	} else {
 		rc = opal_pci_set_mve_enable(phb->opal_id,
 					     pe->mve_number, OPAL_ENABLE_MVE);
 		if (rc) {
-			pe_err(pe, "OPAL error %ld enabling MVE %d\n",
+			pe_err(pe, "OPAL error %ld enabling MVE %x\n",
 			       rc, pe->mve_number);
 			pe->mve_number = -1;
 		}
@@ -1159,10 +1159,10 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 	pe->rid = bus->busn_res.start << 8;
 
 	if (all)
-		pe_info(pe, "Secondary bus %d..%d associated with PE#%d\n",
+		pe_info(pe, "Secondary bus %d..%d associated with PE#%x\n",
 			bus->busn_res.start, bus->busn_res.end, pe->pe_number);
 	else
-		pe_info(pe, "Secondary bus %d associated with PE#%d\n",
+		pe_info(pe, "Secondary bus %d associated with PE#%x\n",
 			bus->busn_res.start, pe->pe_number);
 
 	if (pnv_ioda_configure_pe(phb, pe)) {
@@ -1213,7 +1213,7 @@ static struct pnv_ioda_pe *pnv_ioda_setu
 			 * peer NPU.
 			 */
 			dev_info(&npu_pdev->dev,
-				"Associating to existing PE %d\n", pe_num);
+				"Associating to existing PE %x\n", pe_num);
 			pci_dev_get(npu_pdev);
 			npu_pdn = pci_get_pdn(npu_pdev);
 			rid = npu_pdev->bus->number << 8 | npu_pdn->devfn;
@@ -1539,7 +1539,7 @@ static void pnv_ioda_setup_vf_PE(struct
 		pe->rid = (pci_iov_virtfn_bus(pdev, vf_index) << 8) |
 			   pci_iov_virtfn_devfn(pdev, vf_index);
 
-		pe_info(pe, "VF %04d:%02d:%02d.%d associated with PE#%d\n",
+		pe_info(pe, "VF %04d:%02d:%02d.%d associated with PE#%x\n",
 			hose->global_number, pdev->bus->number,
 			PCI_SLOT(pci_iov_virtfn_devfn(pdev, vf_index)),
 			PCI_FUNC(pci_iov_virtfn_devfn(pdev, vf_index)), pe_num);
@@ -2844,7 +2844,7 @@ static int pnv_pci_ioda_msi_setup(struct
 	pnv_set_msi_irq_chip(phb, virq);
 
 	pr_devel("%s: %s-bit MSI on hwirq %x (xive #%d),"
-		 " address=%x_%08x data=%x PE# %d\n",
+		 " address=%x_%08x data=%x PE# %x\n",
 		 pci_name(dev), is_64 ? "64" : "32", hwirq, xive_num,
 		 msg->address_hi, msg->address_lo, data, pe->pe_number);
 
@@ -2993,7 +2993,7 @@ static void pnv_ioda_setup_pe_res(struct
 			rc = opal_pci_map_pe_mmio_window(phb->opal_id,
 				pe->pe_number, OPAL_IO_WINDOW_TYPE, 0, index);
 			if (rc != OPAL_SUCCESS) {
-				pr_err("%s: Error %lld mapping IO segment#%d to PE#%d\n",
+				pr_err("%s: Error %lld mapping IO segment#%d to PE#%x\n",
 				       __func__, rc, index, pe->pe_number);
 				break;
 			}
@@ -3017,7 +3017,7 @@ static void pnv_ioda_setup_pe_res(struct
 			rc = opal_pci_map_pe_mmio_window(phb->opal_id,
 				pe->pe_number, OPAL_M32_WINDOW_TYPE, 0, index);
 			if (rc != OPAL_SUCCESS) {
-				pr_err("%s: Error %lld mapping M32 segment#%d to PE#%d",
+				pr_err("%s: Error %lld mapping M32 segment#%d to PE#%x",
 				       __func__, rc, index, pe->pe_number);
 				break;
 			}
@@ -3281,7 +3281,7 @@ static void pnv_pci_setup_bridge(struct
 		pnv_pci_ioda2_setup_dma_pe(phb, pe);
 		break;
 	default:
-		pr_warn("%s: No DMA for PHB#%d (type %d)\n",
+		pr_warn("%s: No DMA for PHB#%x (type %d)\n",
 			__func__, phb->hose->global_number, phb->type);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/setup.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/setup.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -174,7 +174,7 @@ static void pnv_shutdown(void)
 	opal_shutdown();
 }
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 static void pnv_kexec_wait_secondaries_down(void)
 {
 	int my_cpu, i, notified = -1;
@@ -245,7 +245,7 @@ static void pnv_kexec_cpu_down(int crash
 		opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_BE);
 	}
 }
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static unsigned long pnv_memory_block_size(void)
@@ -311,7 +311,7 @@ define_machine(powernv) {
 	.machine_shutdown	= pnv_shutdown,
 	.power_save             = NULL,
 	.calibrate_decr		= generic_calibrate_decr,
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	.kexec_cpu_down		= pnv_kexec_cpu_down,
 #endif
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/smp.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/smp.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/powernv/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/powernv/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -155,8 +155,10 @@ static void pnv_smp_cpu_kill_self(void)
 		wmask = SRR1_WAKEMASK_P8;
 
 	idle_states = pnv_get_supported_cpuidle_states();
+
 	/* We don't want to take decrementer interrupts while we are offline,
-	 * so clear LPCR:PECE1. We keep PECE2 enabled.
+	 * so clear LPCR:PECE1. We keep PECE2 (and LPCR_PECE_HVEE on P9)
+	 * enabled as to let IPIs in.
 	 */
 	mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
 
@@ -206,8 +208,12 @@ static void pnv_smp_cpu_kill_self(void)
 		 * contains 0.
 		 */
 		if (((srr1 & wmask) == SRR1_WAKEEE) ||
+		    ((srr1 & wmask) == SRR1_WAKEHVI) ||
 		    (local_paca->irq_happened & PACA_IRQ_EE)) {
-			icp_native_flush_interrupt();
+			if (cpu_has_feature(CPU_FTR_ARCH_300))
+				icp_opal_flush_interrupt();
+			else
+				icp_native_flush_interrupt();
 		} else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
 			unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
 			asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
@@ -221,6 +227,8 @@ static void pnv_smp_cpu_kill_self(void)
 		if (srr1 && !generic_check_cpu_restart(cpu))
 			DBG("CPU%d Unexpected exit while offline !\n", cpu);
 	}
+
+	/* Re-enable decrementer interrupts */
 	mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
 	DBG("CPU%d coming online...\n", cpu);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/ps3/htab.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/ps3/htab.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/ps3/htab.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/ps3/htab.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,7 +63,7 @@ static long ps3_hpte_insert(unsigned lon
 	vflags &= ~HPTE_V_SECONDARY;
 
 	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
-	hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize, apsize, ssize) | rflags;
+	hpte_r = hpte_encode_r(ps3_mm_phys_to_lpar(pa), psize, apsize) | rflags;
 
 	spin_lock_irqsave(&ps3_htab_lock, flags);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/ps3/setup.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/ps3/setup.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/ps3/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/ps3/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -250,7 +250,7 @@ static int __init ps3_probe(void)
 	return 1;
 }
 
-#if defined(CONFIG_KEXEC)
+#if defined(CONFIG_KEXEC_CORE)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
 	int cpu = smp_processor_id();
@@ -276,7 +276,7 @@ define_machine(ps3) {
 	.progress			= ps3_progress,
 	.restart			= ps3_restart,
 	.halt				= ps3_halt,
-#if defined(CONFIG_KEXEC)
+#if defined(CONFIG_KEXEC_CORE)
 	.kexec_cpu_down			= ps3_kexec_cpu_down,
 #endif
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/cmm.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/cmm.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/cmm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/cmm.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,10 +37,12 @@
 #include <asm/hvcall.h>
 #include <asm/mmu.h>
 #include <asm/pgalloc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/memory.h>
 #include <asm/plpar_wrappers.h>
 
+#include "pseries.h"
+
 #define CMM_DRIVER_VERSION	"1.0.0"
 #define CMM_DEFAULT_DELAY	1
 #define CMM_HOTPLUG_DELAY	5
@@ -109,6 +111,38 @@ static int hotplug_occurred; /* protecte
 
 static struct task_struct *cmm_thread_ptr;
 
+static long plpar_page_set_loaned(unsigned long vpa)
+{
+	unsigned long cmo_page_sz = cmo_get_page_size();
+	long rc = 0;
+	int i;
+
+	for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
+		rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa + i, 0);
+
+	for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
+		plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE,
+				   vpa + i - cmo_page_sz, 0);
+
+	return rc;
+}
+
+static long plpar_page_set_active(unsigned long vpa)
+{
+	unsigned long cmo_page_sz = cmo_get_page_size();
+	long rc = 0;
+	int i;
+
+	for (i = 0; !rc && i < PAGE_SIZE; i += cmo_page_sz)
+		rc = plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa + i, 0);
+
+	for (i -= cmo_page_sz; rc && i != 0; i -= cmo_page_sz)
+		plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED,
+				   vpa + i - cmo_page_sz, 0);
+
+	return rc;
+}
+
 /**
  * cmm_alloc_pages - Allocate pages and mark them as loaned
  * @nr:	number of pages to allocate
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/dlpar.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/dlpar.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/dlpar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/dlpar.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/rtas.h>
 
 static struct workqueue_struct *pseries_hp_wq;
@@ -418,84 +418,136 @@ void queue_hotplug_event(struct pseries_
 	}
 }
 
-static ssize_t dlpar_store(struct class *class, struct class_attribute *attr,
-			   const char *buf, size_t count)
+static int dlpar_parse_resource(char **cmd, struct pseries_hp_errorlog *hp_elog)
 {
-	struct pseries_hp_errorlog *hp_elog;
-	struct completion hotplug_done;
-	const char *arg;
-	int rc;
+	char *arg;
 
-	hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
-	if (!hp_elog) {
-		rc = -ENOMEM;
-		goto dlpar_store_out;
-	}
+	arg = strsep(cmd, " ");
+	if (!arg)
+		return -EINVAL;
 
-	/* Parse out the request from the user, this will be in the form
-	 * <resource> <action> <id_type> <id>
-	 */
-	arg = buf;
-	if (!strncmp(arg, "memory", 6)) {
+	if (sysfs_streq(arg, "memory")) {
 		hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_MEM;
-		arg += strlen("memory ");
-	} else if (!strncmp(arg, "cpu", 3)) {
+	} else if (sysfs_streq(arg, "cpu")) {
 		hp_elog->resource = PSERIES_HP_ELOG_RESOURCE_CPU;
-		arg += strlen("cpu ");
 	} else {
-		pr_err("Invalid resource specified: \"%s\"\n", buf);
-		rc = -EINVAL;
-		goto dlpar_store_out;
+		pr_err("Invalid resource specified.\n");
+		return -EINVAL;
 	}
 
-	if (!strncmp(arg, "add", 3)) {
+	return 0;
+}
+
+static int dlpar_parse_action(char **cmd, struct pseries_hp_errorlog *hp_elog)
+{
+	char *arg;
+
+	arg = strsep(cmd, " ");
+	if (!arg)
+		return -EINVAL;
+
+	if (sysfs_streq(arg, "add")) {
 		hp_elog->action = PSERIES_HP_ELOG_ACTION_ADD;
-		arg += strlen("add ");
-	} else if (!strncmp(arg, "remove", 6)) {
+	} else if (sysfs_streq(arg, "remove")) {
 		hp_elog->action = PSERIES_HP_ELOG_ACTION_REMOVE;
-		arg += strlen("remove ");
 	} else {
-		pr_err("Invalid action specified: \"%s\"\n", buf);
-		rc = -EINVAL;
-		goto dlpar_store_out;
+		pr_err("Invalid action specified.\n");
+		return -EINVAL;
 	}
 
-	if (!strncmp(arg, "index", 5)) {
-		u32 index;
+	return 0;
+}
+
+static int dlpar_parse_id_type(char **cmd, struct pseries_hp_errorlog *hp_elog)
+{
+	char *arg;
+	u32 count, index;
+
+	arg = strsep(cmd, " ");
+	if (!arg)
+		return -EINVAL;
 
+	if (sysfs_streq(arg, "index")) {
 		hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_INDEX;
-		arg += strlen("index ");
+		arg = strsep(cmd, " ");
+		if (!arg) {
+			pr_err("No DRC Index specified.\n");
+			return -EINVAL;
+		}
+
 		if (kstrtou32(arg, 0, &index)) {
-			rc = -EINVAL;
-			pr_err("Invalid drc_index specified: \"%s\"\n", buf);
-			goto dlpar_store_out;
+			pr_err("Invalid DRC Index specified.\n");
+			return -EINVAL;
 		}
 
 		hp_elog->_drc_u.drc_index = cpu_to_be32(index);
-	} else if (!strncmp(arg, "count", 5)) {
-		u32 count;
-
+	} else if (sysfs_streq(arg, "count")) {
 		hp_elog->id_type = PSERIES_HP_ELOG_ID_DRC_COUNT;
-		arg += strlen("count ");
+		arg = strsep(cmd, " ");
+		if (!arg) {
+			pr_err("No DRC count specified.\n");
+			return -EINVAL;
+		}
+
 		if (kstrtou32(arg, 0, &count)) {
-			rc = -EINVAL;
-			pr_err("Invalid count specified: \"%s\"\n", buf);
-			goto dlpar_store_out;
+			pr_err("Invalid DRC count specified.\n");
+			return -EINVAL;
 		}
 
 		hp_elog->_drc_u.drc_count = cpu_to_be32(count);
 	} else {
-		pr_err("Invalid id_type specified: \"%s\"\n", buf);
-		rc = -EINVAL;
-		goto dlpar_store_out;
+		pr_err("Invalid id_type specified.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static ssize_t dlpar_store(struct class *class, struct class_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct pseries_hp_errorlog *hp_elog;
+	struct completion hotplug_done;
+	char *argbuf;
+	char *args;
+	int rc;
+
+	args = argbuf = kstrdup(buf, GFP_KERNEL);
+	hp_elog = kzalloc(sizeof(*hp_elog), GFP_KERNEL);
+	if (!hp_elog || !argbuf) {
+		pr_info("Could not allocate resources for DLPAR operation\n");
+		kfree(argbuf);
+		kfree(hp_elog);
+		return -ENOMEM;
 	}
 
+	/*
+	 * Parse out the request from the user, this will be in the form:
+	 * <resource> <action> <id_type> <id>
+	 */
+	rc = dlpar_parse_resource(&args, hp_elog);
+	if (rc)
+		goto dlpar_store_out;
+
+	rc = dlpar_parse_action(&args, hp_elog);
+	if (rc)
+		goto dlpar_store_out;
+
+	rc = dlpar_parse_id_type(&args, hp_elog);
+	if (rc)
+		goto dlpar_store_out;
+
 	init_completion(&hotplug_done);
 	queue_hotplug_event(hp_elog, &hotplug_done, &rc);
 	wait_for_completion(&hotplug_done);
 
 dlpar_store_out:
+	kfree(argbuf);
 	kfree(hp_elog);
+
+	if (rc)
+		pr_err("Could not handle DLPAR request \"%s\"\n", buf);
+
 	return rc ? rc : count;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/dtl.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/dtl.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/dtl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/dtl.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/debugfs.h>
 #include <linux/spinlock.h>
 #include <asm/smp.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/firmware.h>
 #include <asm/lppaca.h>
 #include <asm/debug.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/eeh_pseries.c	2017-02-12 16:03:20.000000000 -0500
@@ -270,7 +270,7 @@ static void *pseries_eeh_probe(struct pc
 			eeh_add_flag(EEH_ENABLED);
 			eeh_add_to_parent_pe(edev);
 
-			pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%d-PE#%x\n",
+			pr_debug("%s: EEH enabled on %02x:%02x.%01x PHB#%x-PE#%x\n",
 				__func__, pdn->busno, PCI_SLOT(pdn->devfn),
 				PCI_FUNC(pdn->devfn), pe.phb->global_number,
 				pe.addr);
@@ -371,7 +371,7 @@ static int pseries_eeh_get_pe_addr(struc
 				pe->config_addr, BUID_HI(pe->phb->buid),
 				BUID_LO(pe->phb->buid), 0);
 		if (ret) {
-			pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n",
+			pr_warn("%s: Failed to get address for PHB#%x-PE#%x\n",
 				__func__, pe->phb->global_number, pe->config_addr);
 			return 0;
 		}
@@ -384,7 +384,7 @@ static int pseries_eeh_get_pe_addr(struc
 				pe->config_addr, BUID_HI(pe->phb->buid),
 				BUID_LO(pe->phb->buid), 0);
 		if (ret) {
-			pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n",
+			pr_warn("%s: Failed to get address for PHB#%x-PE#%x\n",
 				__func__, pe->phb->global_number, pe->config_addr);
 			return 0;
 		}
@@ -653,7 +653,7 @@ static int pseries_eeh_configure_bridge(
 		rtas_busy_delay(ret);
 	}
 
-	pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+	pr_warn("%s: Unable to configure bridge PHB#%x-PE#%x (%d)\n",
 		__func__, pe->phb->global_number, pe->addr, ret);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2017-02-12 16:03:20.000000000 -0500
@@ -472,12 +472,15 @@ static int dlpar_memory_remove_by_count(
 
 	/* Validate that there are enough LMBs to satisfy the request */
 	for (i = 0; i < num_lmbs; i++) {
-		if (lmbs[i].flags & DRCONF_MEM_ASSIGNED)
+		if (lmb_is_removable(&lmbs[i]))
 			lmbs_available++;
 	}
 
-	if (lmbs_available < lmbs_to_remove)
+	if (lmbs_available < lmbs_to_remove) {
+		pr_info("Not enough LMBs available (%d of %d) to satisfy request\n",
+			lmbs_available, lmbs_to_remove);
 		return -EINVAL;
+	}
 
 	for (i = 0; i < num_lmbs && lmbs_removed < lmbs_to_remove; i++) {
 		rc = dlpar_remove_lmb(&lmbs[i]);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/ibmebus.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/ibmebus.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/ibmebus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/ibmebus.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,469 @@
+/*
+ * IBM PowerPC IBM eBus Infrastructure Support.
+ *
+ * Copyright (c) 2005 IBM Corporation
+ *  Joachim Fenkes <fenkes@de.ibm.com>
+ *  Heiko J Schick <schickhj@de.ibm.com>
+ *
+ * All rights reserved.
+ *
+ * This source code is distributed under a dual license of GPL v2.0 and OpenIB
+ * BSD.
+ *
+ * OpenIB BSD License
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/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>
+
+static struct device ibmebus_bus_device = { /* fake "parent" device */
+	.init_name = "ibmebus",
+};
+
+struct bus_type ibmebus_bus_type;
+
+/* These devices will automatically be added to the bus during init */
+static const struct of_device_id ibmebus_matches[] __initconst = {
+	{ .compatible = "IBM,lhca" },
+	{ .compatible = "IBM,lhea" },
+	{},
+};
+
+static void *ibmebus_alloc_coherent(struct device *dev,
+				    size_t size,
+				    dma_addr_t *dma_handle,
+				    gfp_t flag,
+				    unsigned long attrs)
+{
+	void *mem;
+
+	mem = kmalloc(size, flag);
+	*dma_handle = (dma_addr_t)mem;
+
+	return mem;
+}
+
+static void ibmebus_free_coherent(struct device *dev,
+				  size_t size, void *vaddr,
+				  dma_addr_t dma_handle,
+				  unsigned long attrs)
+{
+	kfree(vaddr);
+}
+
+static dma_addr_t ibmebus_map_page(struct device *dev,
+				   struct page *page,
+				   unsigned long offset,
+				   size_t size,
+				   enum dma_data_direction direction,
+				   unsigned long attrs)
+{
+	return (dma_addr_t)(page_address(page) + offset);
+}
+
+static void ibmebus_unmap_page(struct device *dev,
+			       dma_addr_t dma_addr,
+			       size_t size,
+			       enum dma_data_direction direction,
+			       unsigned long attrs)
+{
+	return;
+}
+
+static int ibmebus_map_sg(struct device *dev,
+			  struct scatterlist *sgl,
+			  int nents, enum dma_data_direction direction,
+			  unsigned long attrs)
+{
+	struct scatterlist *sg;
+	int i;
+
+	for_each_sg(sgl, sg, nents, i) {
+		sg->dma_address = (dma_addr_t) sg_virt(sg);
+		sg->dma_length = sg->length;
+	}
+
+	return nents;
+}
+
+static void ibmebus_unmap_sg(struct device *dev,
+			     struct scatterlist *sg,
+			     int nents, enum dma_data_direction direction,
+			     unsigned long attrs)
+{
+	return;
+}
+
+static int ibmebus_dma_supported(struct device *dev, u64 mask)
+{
+	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              = ibmebus_alloc_coherent,
+	.free               = 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)
+{
+	struct device_node *dn = to_platform_device(dev)->dev.of_node;
+	return (dn->full_name &&
+		(strcasecmp((char *)data, dn->full_name) == 0));
+}
+
+static int ibmebus_match_node(struct device *dev, void *data)
+{
+	return to_platform_device(dev)->dev.of_node == data;
+}
+
+static int ibmebus_create_device(struct device_node *dn)
+{
+	struct platform_device *dev;
+	int ret;
+
+	dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->dev.bus = &ibmebus_bus_type;
+	dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
+
+	ret = of_device_add(dev);
+	if (ret)
+		platform_device_put(dev);
+	return ret;
+}
+
+static int ibmebus_create_devices(const struct of_device_id *matches)
+{
+	struct device_node *root, *child;
+	struct device *dev;
+	int ret = 0;
+
+	root = of_find_node_by_path("/");
+
+	for_each_child_of_node(root, child) {
+		if (!of_match_node(matches, child))
+			continue;
+
+		dev = bus_find_device(&ibmebus_bus_type, NULL, child,
+				      ibmebus_match_node);
+		if (dev) {
+			put_device(dev);
+			continue;
+		}
+
+		ret = ibmebus_create_device(child);
+		if (ret) {
+			printk(KERN_ERR "%s: failed to create device (%i)",
+			       __func__, ret);
+			of_node_put(child);
+			break;
+		}
+	}
+
+	of_node_put(root);
+	return ret;
+}
+
+int ibmebus_register_driver(struct platform_driver *drv)
+{
+	/* If the driver uses devices that ibmebus doesn't know, add them */
+	ibmebus_create_devices(drv->driver.of_match_table);
+
+	drv->driver.bus = &ibmebus_bus_type;
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(ibmebus_register_driver);
+
+void ibmebus_unregister_driver(struct platform_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(ibmebus_unregister_driver);
+
+int ibmebus_request_irq(u32 ist, irq_handler_t handler,
+			unsigned long irq_flags, const char *devname,
+			void *dev_id)
+{
+	unsigned int irq = irq_create_mapping(NULL, ist);
+
+	if (!irq)
+		return -EINVAL;
+
+	return request_irq(irq, handler, irq_flags, devname, dev_id);
+}
+EXPORT_SYMBOL(ibmebus_request_irq);
+
+void ibmebus_free_irq(u32 ist, void *dev_id)
+{
+	unsigned int irq = irq_find_mapping(NULL, ist);
+
+	free_irq(irq, dev_id);
+	irq_dispose_mapping(irq);
+}
+EXPORT_SYMBOL(ibmebus_free_irq);
+
+static char *ibmebus_chomp(const char *in, size_t count)
+{
+	char *out = kmalloc(count + 1, GFP_KERNEL);
+
+	if (!out)
+		return NULL;
+
+	memcpy(out, in, count);
+	out[count] = '\0';
+	if (out[count - 1] == '\n')
+		out[count - 1] = '\0';
+
+	return out;
+}
+
+static ssize_t ibmebus_store_probe(struct bus_type *bus,
+				   const char *buf, size_t count)
+{
+	struct device_node *dn = NULL;
+	struct device *dev;
+	char *path;
+	ssize_t rc = 0;
+
+	path = ibmebus_chomp(buf, count);
+	if (!path)
+		return -ENOMEM;
+
+	dev = bus_find_device(&ibmebus_bus_type, NULL, path,
+			      ibmebus_match_path);
+	if (dev) {
+		put_device(dev);
+		printk(KERN_WARNING "%s: %s has already been probed\n",
+		       __func__, path);
+		rc = -EEXIST;
+		goto out;
+	}
+
+	if ((dn = of_find_node_by_path(path))) {
+		rc = ibmebus_create_device(dn);
+		of_node_put(dn);
+	} else {
+		printk(KERN_WARNING "%s: no such device node: %s\n",
+		       __func__, path);
+		rc = -ENODEV;
+	}
+
+out:
+	kfree(path);
+	if (rc)
+		return rc;
+	return count;
+}
+static BUS_ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe);
+
+static ssize_t ibmebus_store_remove(struct bus_type *bus,
+				    const char *buf, size_t count)
+{
+	struct device *dev;
+	char *path;
+
+	path = ibmebus_chomp(buf, count);
+	if (!path)
+		return -ENOMEM;
+
+	if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
+				   ibmebus_match_path))) {
+		of_device_unregister(to_platform_device(dev));
+		put_device(dev);
+
+		kfree(path);
+		return count;
+	} else {
+		printk(KERN_WARNING "%s: %s not on the bus\n",
+		       __func__, path);
+
+		kfree(path);
+		return -ENODEV;
+	}
+}
+static BUS_ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove);
+
+static struct attribute *ibmbus_bus_attrs[] = {
+	&bus_attr_probe.attr,
+	&bus_attr_remove.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(ibmbus_bus);
+
+static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
+{
+	const struct of_device_id *matches = drv->of_match_table;
+
+	if (!matches)
+		return 0;
+
+	return of_match_device(matches, dev) != NULL;
+}
+
+static int ibmebus_bus_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct platform_driver *drv;
+	struct platform_device *of_dev;
+
+	drv = to_platform_driver(dev->driver);
+	of_dev = to_platform_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	of_dev_get(of_dev);
+
+	if (of_driver_match_device(dev, dev->driver))
+		error = drv->probe(of_dev);
+	if (error)
+		of_dev_put(of_dev);
+
+	return error;
+}
+
+static int ibmebus_bus_device_remove(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct platform_driver *drv = to_platform_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(of_dev);
+	return 0;
+}
+
+static void ibmebus_bus_device_shutdown(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct platform_driver *drv = to_platform_driver(dev->driver);
+
+	if (dev->driver && drv->shutdown)
+		drv->shutdown(of_dev);
+}
+
+/*
+ * ibmebus_bus_device_attrs
+ */
+static ssize_t devspec_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *ofdev;
+
+	ofdev = to_platform_device(dev);
+	return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name);
+}
+
+static ssize_t name_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *ofdev;
+
+	ofdev = to_platform_device(dev);
+	return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
+}
+
+static ssize_t modalias_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
+	buf[len] = '\n';
+	buf[len+1] = 0;
+	return len+1;
+}
+
+static struct device_attribute ibmebus_bus_device_attrs[] = {
+	__ATTR_RO(devspec),
+	__ATTR_RO(name),
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
+
+struct bus_type ibmebus_bus_type = {
+	.name      = "ibmebus",
+	.uevent    = of_device_uevent_modalias,
+	.bus_groups = ibmbus_bus_groups,
+	.match     = ibmebus_bus_bus_match,
+	.probe     = ibmebus_bus_device_probe,
+	.remove    = ibmebus_bus_device_remove,
+	.shutdown  = ibmebus_bus_device_shutdown,
+	.dev_attrs = ibmebus_bus_device_attrs,
+};
+EXPORT_SYMBOL(ibmebus_bus_type);
+
+static int __init ibmebus_bus_init(void)
+{
+	int err;
+
+	printk(KERN_INFO "IBM eBus Device Driver\n");
+
+	err = bus_register(&ibmebus_bus_type);
+	if (err) {
+		printk(KERN_ERR "%s: failed to register IBM eBus.\n",
+		       __func__);
+		return err;
+	}
+
+	err = device_register(&ibmebus_bus_device);
+	if (err) {
+		printk(KERN_WARNING "%s: device_register returned %i\n",
+		       __func__, err);
+		bus_unregister(&ibmebus_bus_type);
+
+		return err;
+	}
+
+	err = ibmebus_create_devices(ibmebus_matches);
+	if (err) {
+		device_unregister(&ibmebus_bus_device);
+		bus_unregister(&ibmebus_bus_type);
+		return err;
+	}
+
+	return 0;
+}
+postcore_initcall(ibmebus_bus_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/Kconfig linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/Kconfig
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -127,3 +127,14 @@ config HV_PERF_CTRS
 	  systems. 24x7 is available on Power 8 systems.
 
           If unsure, select Y.
+
+config IBMVIO
+	depends on PPC_PSERIES
+	bool
+	default y
+
+config IBMEBUS
+	depends on PPC_PSERIES && !CPU_LITTLE_ENDIAN
+	bool "Support for GX bus based adapters"
+	help
+	  Bus device driver for GX bus based adapters.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/lpar.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/lpar.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/lpar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/lpar.c	2017-02-12 16:03:20.000000000 -0500
@@ -145,7 +145,7 @@ static long pSeries_lpar_hpte_insert(uns
 			 hpte_group, vpn,  pa, rflags, vflags, psize);
 
 	hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
-	hpte_r = hpte_encode_r(pa, psize, apsize, ssize) | rflags;
+	hpte_r = hpte_encode_r(pa, psize, apsize) | rflags;
 
 	if (!(vflags & HPTE_V_BOLTED))
 		pr_devel(" hpte_v=%016lx, hpte_r=%016lx\n", hpte_v, hpte_r);
@@ -221,7 +221,7 @@ static long pSeries_lpar_hpte_remove(uns
 	return -1;
 }
 
-static void pSeries_lpar_hptab_clear(void)
+static void manual_hpte_clear_all(void)
 {
 	unsigned long size_bytes = 1UL << ppc64_pft_size;
 	unsigned long hpte_count = size_bytes >> 4;
@@ -249,6 +249,26 @@ static void pSeries_lpar_hptab_clear(voi
 					&(ptes[j].pteh), &(ptes[j].ptel));
 		}
 	}
+}
+
+static int hcall_hpte_clear_all(void)
+{
+	int rc;
+
+	do {
+		rc = plpar_hcall_norets(H_CLEAR_HPT);
+	} while (rc == H_CONTINUE);
+
+	return rc;
+}
+
+static void pseries_hpte_clear_all(void)
+{
+	int rc;
+
+	rc = hcall_hpte_clear_all();
+	if (rc != H_SUCCESS)
+		manual_hpte_clear_all();
 
 #ifdef __LITTLE_ENDIAN__
 	/*
@@ -598,7 +618,7 @@ void __init hpte_init_pseries(void)
 	mmu_hash_ops.hpte_remove	 = pSeries_lpar_hpte_remove;
 	mmu_hash_ops.hpte_removebolted   = pSeries_lpar_hpte_removebolted;
 	mmu_hash_ops.flush_hash_range	 = pSeries_lpar_flush_hash_range;
-	mmu_hash_ops.hpte_clear_all      = pSeries_lpar_hptab_clear;
+	mmu_hash_ops.hpte_clear_all      = pseries_hpte_clear_all;
 	mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate;
 }
 
@@ -661,9 +681,10 @@ EXPORT_SYMBOL(arch_free_page);
 #ifdef HAVE_JUMP_LABEL
 struct static_key hcall_tracepoint_key = STATIC_KEY_INIT;
 
-void hcall_tracepoint_regfunc(void)
+int hcall_tracepoint_regfunc(void)
 {
 	static_key_slow_inc(&hcall_tracepoint_key);
+	return 0;
 }
 
 void hcall_tracepoint_unregfunc(void)
@@ -680,9 +701,10 @@ void hcall_tracepoint_unregfunc(void)
 /* NB: reg/unreg are called while guarded with the tracepoints_mutex */
 extern long hcall_tracepoint_refcount;
 
-void hcall_tracepoint_regfunc(void)
+int hcall_tracepoint_regfunc(void)
 {
 	hcall_tracepoint_refcount++;
+	return 0;
 }
 
 void hcall_tracepoint_unregfunc(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/lparcfg.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/lparcfg.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/lparcfg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/lparcfg.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/init.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/lppaca.h>
 #include <asm/hvcall.h>
 #include <asm/firmware.h>
@@ -37,6 +37,7 @@
 #include <asm/mmu.h>
 #include <asm/machdep.h>
 
+#include "pseries.h"
 
 /*
  * This isn't a module but we expose that to userspace
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/Makefile linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/Makefile
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@ obj-y			:= lpar.o hvCall.o nvram.o recon
 			   pci.o pci_dlpar.o eeh_pseries.o msi.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
-obj-$(CONFIG_KEXEC)	+= kexec.o
+obj-$(CONFIG_KEXEC_CORE)	+= kexec.o
 obj-$(CONFIG_PSERIES_ENERGY)	+= pseries_energy.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
@@ -21,6 +21,8 @@ obj-$(CONFIG_CMM)		+= cmm.o
 obj-$(CONFIG_DTL)		+= dtl.o
 obj-$(CONFIG_IO_EVENT_IRQ)	+= io_event_irq.o
 obj-$(CONFIG_LPARCFG)		+= lparcfg.o
+obj-$(CONFIG_IBMVIO)		+= vio.o
+obj-$(CONFIG_IBMEBUS)		+= ibmebus.o
 
 ifeq ($(CONFIG_PPC_PSERIES),y)
 obj-$(CONFIG_SUSPEND)		+= suspend.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/nvram.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/nvram.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/nvram.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/nvram.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
 #include <asm/prom.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/pseries.h linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/pseries.h
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/pseries.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/pseries.h	2017-02-12 16:03:20.000000000 -0500
@@ -79,4 +79,23 @@ extern struct pci_controller_ops pseries
 
 unsigned long pseries_memory_block_size(void);
 
+extern int CMO_PrPSP;
+extern int CMO_SecPSP;
+extern unsigned long CMO_PageSize;
+
+static inline int cmo_get_primary_psp(void)
+{
+	return CMO_PrPSP;
+}
+
+static inline int cmo_get_secondary_psp(void)
+{
+	return CMO_SecPSP;
+}
+
+static inline unsigned long cmo_get_page_size(void)
+{
+	return CMO_PageSize;
+}
+
 #endif /* _PSERIES_PSERIES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/reconfig.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/reconfig.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/reconfig.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/reconfig.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmu.h>
 
 #include "of_helpers.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/scanlog.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/scanlog.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/scanlog.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/scanlog.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/rtas.h>
 #include <asm/prom.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/setup.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/setup.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -367,7 +367,7 @@ void pseries_disable_reloc_on_exc(void)
 }
 EXPORT_SYMBOL(pseries_disable_reloc_on_exc);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 static void pSeries_machine_kexec(struct kimage *image)
 {
 	if (firmware_has_feature(FW_FEATURE_SET_MODE))
@@ -725,7 +725,7 @@ define_machine(pseries) {
 	.progress		= rtas_progress,
 	.system_reset_exception = pSeries_system_reset_exception,
 	.machine_check_exception = pSeries_machine_check_exception,
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	.machine_kexec          = pSeries_machine_kexec,
 	.kexec_cpu_down         = pseries_kexec_cpu_down,
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/vio.c linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/vio.c
--- linux-libre-4.9-gnu/arch/powerpc/platforms/pseries/vio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/platforms/pseries/vio.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1705 @@
+/*
+ * IBM PowerPC Virtual I/O Infrastructure Support.
+ *
+ *    Copyright (c) 2003,2008 IBM Corp.
+ *     Dave Engebretsen engebret@us.ibm.com
+ *     Santiago Leon santil@us.ibm.com
+ *     Hollis Blanchard <hollisb@us.ibm.com>
+ *     Stephen Rothwell
+ *     Robert Jennings <rcjenn@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.
+ */
+
+#include <linux/cpu.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/stat.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/console.h>
+#include <linux/export.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/kobject.h>
+
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#include <asm/vio.h>
+#include <asm/prom.h>
+#include <asm/firmware.h>
+#include <asm/tce.h>
+#include <asm/page.h>
+#include <asm/hvcall.h>
+
+static struct vio_dev vio_bus_device  = { /* fake "parent" device */
+	.name = "vio",
+	.type = "",
+	.dev.init_name = "vio",
+	.dev.bus = &vio_bus_type,
+};
+
+#ifdef CONFIG_PPC_SMLPAR
+/**
+ * vio_cmo_pool - A pool of IO memory for CMO use
+ *
+ * @size: The size of the pool in bytes
+ * @free: The amount of free memory in the pool
+ */
+struct vio_cmo_pool {
+	size_t size;
+	size_t free;
+};
+
+/* How many ms to delay queued balance work */
+#define VIO_CMO_BALANCE_DELAY 100
+
+/* Portion out IO memory to CMO devices by this chunk size */
+#define VIO_CMO_BALANCE_CHUNK 131072
+
+/**
+ * vio_cmo_dev_entry - A device that is CMO-enabled and requires entitlement
+ *
+ * @vio_dev: struct vio_dev pointer
+ * @list: pointer to other devices on bus that are being tracked
+ */
+struct vio_cmo_dev_entry {
+	struct vio_dev *viodev;
+	struct list_head list;
+};
+
+/**
+ * vio_cmo - VIO bus accounting structure for CMO entitlement
+ *
+ * @lock: spinlock for entire structure
+ * @balance_q: work queue for balancing system entitlement
+ * @device_list: list of CMO-enabled devices requiring entitlement
+ * @entitled: total system entitlement in bytes
+ * @reserve: pool of memory from which devices reserve entitlement, incl. spare
+ * @excess: pool of excess entitlement not needed for device reserves or spare
+ * @spare: IO memory for device hotplug functionality
+ * @min: minimum necessary for system operation
+ * @desired: desired memory for system operation
+ * @curr: bytes currently allocated
+ * @high: high water mark for IO data usage
+ */
+static struct vio_cmo {
+	spinlock_t lock;
+	struct delayed_work balance_q;
+	struct list_head device_list;
+	size_t entitled;
+	struct vio_cmo_pool reserve;
+	struct vio_cmo_pool excess;
+	size_t spare;
+	size_t min;
+	size_t desired;
+	size_t curr;
+	size_t high;
+} vio_cmo;
+
+/**
+ * vio_cmo_OF_devices - Count the number of OF devices that have DMA windows
+ */
+static int vio_cmo_num_OF_devs(void)
+{
+	struct device_node *node_vroot;
+	int count = 0;
+
+	/*
+	 * Count the number of vdevice entries with an
+	 * ibm,my-dma-window OF property
+	 */
+	node_vroot = of_find_node_by_name(NULL, "vdevice");
+	if (node_vroot) {
+		struct device_node *of_node;
+		struct property *prop;
+
+		for_each_child_of_node(node_vroot, of_node) {
+			prop = of_find_property(of_node, "ibm,my-dma-window",
+			                       NULL);
+			if (prop)
+				count++;
+		}
+	}
+	of_node_put(node_vroot);
+	return count;
+}
+
+/**
+ * vio_cmo_alloc - allocate IO memory for CMO-enable devices
+ *
+ * @viodev: VIO device requesting IO memory
+ * @size: size of allocation requested
+ *
+ * Allocations come from memory reserved for the devices and any excess
+ * IO memory available to all devices.  The spare pool used to service
+ * hotplug must be equal to %VIO_CMO_MIN_ENT for the excess pool to be
+ * made available.
+ *
+ * Return codes:
+ *  0 for successful allocation and -ENOMEM for a failure
+ */
+static inline int vio_cmo_alloc(struct vio_dev *viodev, size_t size)
+{
+	unsigned long flags;
+	size_t reserve_free = 0;
+	size_t excess_free = 0;
+	int ret = -ENOMEM;
+
+	spin_lock_irqsave(&vio_cmo.lock, flags);
+
+	/* Determine the amount of free entitlement available in reserve */
+	if (viodev->cmo.entitled > viodev->cmo.allocated)
+		reserve_free = viodev->cmo.entitled - viodev->cmo.allocated;
+
+	/* If spare is not fulfilled, the excess pool can not be used. */
+	if (vio_cmo.spare >= VIO_CMO_MIN_ENT)
+		excess_free = vio_cmo.excess.free;
+
+	/* The request can be satisfied */
+	if ((reserve_free + excess_free) >= size) {
+		vio_cmo.curr += size;
+		if (vio_cmo.curr > vio_cmo.high)
+			vio_cmo.high = vio_cmo.curr;
+		viodev->cmo.allocated += size;
+		size -= min(reserve_free, size);
+		vio_cmo.excess.free -= size;
+		ret = 0;
+	}
+
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+	return ret;
+}
+
+/**
+ * vio_cmo_dealloc - deallocate IO memory from CMO-enable devices
+ * @viodev: VIO device freeing IO memory
+ * @size: size of deallocation
+ *
+ * IO memory is freed by the device back to the correct memory pools.
+ * The spare pool is replenished first from either memory pool, then
+ * the reserve pool is used to reduce device entitlement, the excess
+ * pool is used to increase the reserve pool toward the desired entitlement
+ * target, and then the remaining memory is returned to the pools.
+ *
+ */
+static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size)
+{
+	unsigned long flags;
+	size_t spare_needed = 0;
+	size_t excess_freed = 0;
+	size_t reserve_freed = size;
+	size_t tmp;
+	int balance = 0;
+
+	spin_lock_irqsave(&vio_cmo.lock, flags);
+	vio_cmo.curr -= size;
+
+	/* Amount of memory freed from the excess pool */
+	if (viodev->cmo.allocated > viodev->cmo.entitled) {
+		excess_freed = min(reserve_freed, (viodev->cmo.allocated -
+		                                   viodev->cmo.entitled));
+		reserve_freed -= excess_freed;
+	}
+
+	/* Remove allocation from device */
+	viodev->cmo.allocated -= (reserve_freed + excess_freed);
+
+	/* Spare is a subset of the reserve pool, replenish it first. */
+	spare_needed = VIO_CMO_MIN_ENT - vio_cmo.spare;
+
+	/*
+	 * Replenish the spare in the reserve pool from the excess pool.
+	 * This moves entitlement into the reserve pool.
+	 */
+	if (spare_needed && excess_freed) {
+		tmp = min(excess_freed, spare_needed);
+		vio_cmo.excess.size -= tmp;
+		vio_cmo.reserve.size += tmp;
+		vio_cmo.spare += tmp;
+		excess_freed -= tmp;
+		spare_needed -= tmp;
+		balance = 1;
+	}
+
+	/*
+	 * Replenish the spare in the reserve pool from the reserve pool.
+	 * This removes entitlement from the device down to VIO_CMO_MIN_ENT,
+	 * if needed, and gives it to the spare pool. The amount of used
+	 * memory in this pool does not change.
+	 */
+	if (spare_needed && reserve_freed) {
+		tmp = min3(spare_needed, reserve_freed, (viodev->cmo.entitled - VIO_CMO_MIN_ENT));
+
+		vio_cmo.spare += tmp;
+		viodev->cmo.entitled -= tmp;
+		reserve_freed -= tmp;
+		spare_needed -= tmp;
+		balance = 1;
+	}
+
+	/*
+	 * Increase the reserve pool until the desired allocation is met.
+	 * Move an allocation freed from the excess pool into the reserve
+	 * pool and schedule a balance operation.
+	 */
+	if (excess_freed && (vio_cmo.desired > vio_cmo.reserve.size)) {
+		tmp = min(excess_freed, (vio_cmo.desired - vio_cmo.reserve.size));
+
+		vio_cmo.excess.size -= tmp;
+		vio_cmo.reserve.size += tmp;
+		excess_freed -= tmp;
+		balance = 1;
+	}
+
+	/* Return memory from the excess pool to that pool */
+	if (excess_freed)
+		vio_cmo.excess.free += excess_freed;
+
+	if (balance)
+		schedule_delayed_work(&vio_cmo.balance_q, VIO_CMO_BALANCE_DELAY);
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+/**
+ * vio_cmo_entitlement_update - Manage system entitlement changes
+ *
+ * @new_entitlement: new system entitlement to attempt to accommodate
+ *
+ * Increases in entitlement will be used to fulfill the spare entitlement
+ * and the rest is given to the excess pool.  Decreases, if they are
+ * possible, come from the excess pool and from unused device entitlement
+ *
+ * Returns: 0 on success, -ENOMEM when change can not be made
+ */
+int vio_cmo_entitlement_update(size_t new_entitlement)
+{
+	struct vio_dev *viodev;
+	struct vio_cmo_dev_entry *dev_ent;
+	unsigned long flags;
+	size_t avail, delta, tmp;
+
+	spin_lock_irqsave(&vio_cmo.lock, flags);
+
+	/* Entitlement increases */
+	if (new_entitlement > vio_cmo.entitled) {
+		delta = new_entitlement - vio_cmo.entitled;
+
+		/* Fulfill spare allocation */
+		if (vio_cmo.spare < VIO_CMO_MIN_ENT) {
+			tmp = min(delta, (VIO_CMO_MIN_ENT - vio_cmo.spare));
+			vio_cmo.spare += tmp;
+			vio_cmo.reserve.size += tmp;
+			delta -= tmp;
+		}
+
+		/* Remaining new allocation goes to the excess pool */
+		vio_cmo.entitled += delta;
+		vio_cmo.excess.size += delta;
+		vio_cmo.excess.free += delta;
+
+		goto out;
+	}
+
+	/* Entitlement decreases */
+	delta = vio_cmo.entitled - new_entitlement;
+	avail = vio_cmo.excess.free;
+
+	/*
+	 * Need to check how much unused entitlement each device can
+	 * sacrifice to fulfill entitlement change.
+	 */
+	list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+		if (avail >= delta)
+			break;
+
+		viodev = dev_ent->viodev;
+		if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
+		    (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
+				avail += viodev->cmo.entitled -
+				         max_t(size_t, viodev->cmo.allocated,
+				               VIO_CMO_MIN_ENT);
+	}
+
+	if (delta <= avail) {
+		vio_cmo.entitled -= delta;
+
+		/* Take entitlement from the excess pool first */
+		tmp = min(vio_cmo.excess.free, delta);
+		vio_cmo.excess.size -= tmp;
+		vio_cmo.excess.free -= tmp;
+		delta -= tmp;
+
+		/*
+		 * Remove all but VIO_CMO_MIN_ENT bytes from devices
+		 * until entitlement change is served
+		 */
+		list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+			if (!delta)
+				break;
+
+			viodev = dev_ent->viodev;
+			tmp = 0;
+			if ((viodev->cmo.entitled > viodev->cmo.allocated) &&
+			    (viodev->cmo.entitled > VIO_CMO_MIN_ENT))
+				tmp = viodev->cmo.entitled -
+				      max_t(size_t, viodev->cmo.allocated,
+				            VIO_CMO_MIN_ENT);
+			viodev->cmo.entitled -= min(tmp, delta);
+			delta -= min(tmp, delta);
+		}
+	} else {
+		spin_unlock_irqrestore(&vio_cmo.lock, flags);
+		return -ENOMEM;
+	}
+
+out:
+	schedule_delayed_work(&vio_cmo.balance_q, 0);
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+	return 0;
+}
+
+/**
+ * vio_cmo_balance - Balance entitlement among devices
+ *
+ * @work: work queue structure for this operation
+ *
+ * Any system entitlement above the minimum needed for devices, or
+ * already allocated to devices, can be distributed to the devices.
+ * The list of devices is iterated through to recalculate the desired
+ * entitlement level and to determine how much entitlement above the
+ * minimum entitlement is allocated to devices.
+ *
+ * Small chunks of the available entitlement are given to devices until
+ * their requirements are fulfilled or there is no entitlement left to give.
+ * Upon completion sizes of the reserve and excess pools are calculated.
+ *
+ * The system minimum entitlement level is also recalculated here.
+ * Entitlement will be reserved for devices even after vio_bus_remove to
+ * accommodate reloading the driver.  The OF tree is walked to count the
+ * number of devices present and this will remove entitlement for devices
+ * that have actually left the system after having vio_bus_remove called.
+ */
+static void vio_cmo_balance(struct work_struct *work)
+{
+	struct vio_cmo *cmo;
+	struct vio_dev *viodev;
+	struct vio_cmo_dev_entry *dev_ent;
+	unsigned long flags;
+	size_t avail = 0, level, chunk, need;
+	int devcount = 0, fulfilled;
+
+	cmo = container_of(work, struct vio_cmo, balance_q.work);
+
+	spin_lock_irqsave(&vio_cmo.lock, flags);
+
+	/* Calculate minimum entitlement and fulfill spare */
+	cmo->min = vio_cmo_num_OF_devs() * VIO_CMO_MIN_ENT;
+	BUG_ON(cmo->min > cmo->entitled);
+	cmo->spare = min_t(size_t, VIO_CMO_MIN_ENT, (cmo->entitled - cmo->min));
+	cmo->min += cmo->spare;
+	cmo->desired = cmo->min;
+
+	/*
+	 * Determine how much entitlement is available and reset device
+	 * entitlements
+	 */
+	avail = cmo->entitled - cmo->spare;
+	list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+		viodev = dev_ent->viodev;
+		devcount++;
+		viodev->cmo.entitled = VIO_CMO_MIN_ENT;
+		cmo->desired += (viodev->cmo.desired - VIO_CMO_MIN_ENT);
+		avail -= max_t(size_t, viodev->cmo.allocated, VIO_CMO_MIN_ENT);
+	}
+
+	/*
+	 * Having provided each device with the minimum entitlement, loop
+	 * over the devices portioning out the remaining entitlement
+	 * until there is nothing left.
+	 */
+	level = VIO_CMO_MIN_ENT;
+	while (avail) {
+		fulfilled = 0;
+		list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+			viodev = dev_ent->viodev;
+
+			if (viodev->cmo.desired <= level) {
+				fulfilled++;
+				continue;
+			}
+
+			/*
+			 * Give the device up to VIO_CMO_BALANCE_CHUNK
+			 * bytes of entitlement, but do not exceed the
+			 * desired level of entitlement for the device.
+			 */
+			chunk = min_t(size_t, avail, VIO_CMO_BALANCE_CHUNK);
+			chunk = min(chunk, (viodev->cmo.desired -
+			                    viodev->cmo.entitled));
+			viodev->cmo.entitled += chunk;
+
+			/*
+			 * If the memory for this entitlement increase was
+			 * already allocated to the device it does not come
+			 * from the available pool being portioned out.
+			 */
+			need = max(viodev->cmo.allocated, viodev->cmo.entitled)-
+			       max(viodev->cmo.allocated, level);
+			avail -= need;
+
+		}
+		if (fulfilled == devcount)
+			break;
+		level += VIO_CMO_BALANCE_CHUNK;
+	}
+
+	/* Calculate new reserve and excess pool sizes */
+	cmo->reserve.size = cmo->min;
+	cmo->excess.free = 0;
+	cmo->excess.size = 0;
+	need = 0;
+	list_for_each_entry(dev_ent, &vio_cmo.device_list, list) {
+		viodev = dev_ent->viodev;
+		/* Calculated reserve size above the minimum entitlement */
+		if (viodev->cmo.entitled)
+			cmo->reserve.size += (viodev->cmo.entitled -
+			                      VIO_CMO_MIN_ENT);
+		/* Calculated used excess entitlement */
+		if (viodev->cmo.allocated > viodev->cmo.entitled)
+			need += viodev->cmo.allocated - viodev->cmo.entitled;
+	}
+	cmo->excess.size = cmo->entitled - cmo->reserve.size;
+	cmo->excess.free = cmo->excess.size - need;
+
+	cancel_delayed_work(to_delayed_work(work));
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
+					  dma_addr_t *dma_handle, gfp_t flag,
+					  unsigned long attrs)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	void *ret;
+
+	if (vio_cmo_alloc(viodev, roundup(size, PAGE_SIZE))) {
+		atomic_inc(&viodev->cmo.allocs_failed);
+		return NULL;
+	}
+
+	ret = dma_iommu_ops.alloc(dev, size, dma_handle, flag, attrs);
+	if (unlikely(ret == NULL)) {
+		vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
+		atomic_inc(&viodev->cmo.allocs_failed);
+	}
+
+	return ret;
+}
+
+static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
+					void *vaddr, dma_addr_t dma_handle,
+					unsigned long attrs)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+
+	dma_iommu_ops.free(dev, size, vaddr, dma_handle, attrs);
+
+	vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
+}
+
+static dma_addr_t vio_dma_iommu_map_page(struct device *dev, struct page *page,
+                                         unsigned long offset, size_t size,
+                                         enum dma_data_direction direction,
+                                         unsigned long attrs)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct iommu_table *tbl;
+	dma_addr_t ret = DMA_ERROR_CODE;
+
+	tbl = get_iommu_table_base(dev);
+	if (vio_cmo_alloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)))) {
+		atomic_inc(&viodev->cmo.allocs_failed);
+		return ret;
+	}
+
+	ret = dma_iommu_ops.map_page(dev, page, offset, size, direction, attrs);
+	if (unlikely(dma_mapping_error(dev, ret))) {
+		vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
+		atomic_inc(&viodev->cmo.allocs_failed);
+	}
+
+	return ret;
+}
+
+static void vio_dma_iommu_unmap_page(struct device *dev, dma_addr_t dma_handle,
+				     size_t size,
+				     enum dma_data_direction direction,
+				     unsigned long attrs)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct iommu_table *tbl;
+
+	tbl = get_iommu_table_base(dev);
+	dma_iommu_ops.unmap_page(dev, dma_handle, size, direction, attrs);
+
+	vio_cmo_dealloc(viodev, roundup(size, IOMMU_PAGE_SIZE(tbl)));
+}
+
+static int vio_dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
+                                int nelems, enum dma_data_direction direction,
+                                unsigned long attrs)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct iommu_table *tbl;
+	struct scatterlist *sgl;
+	int ret, count;
+	size_t alloc_size = 0;
+
+	tbl = get_iommu_table_base(dev);
+	for_each_sg(sglist, sgl, nelems, count)
+		alloc_size += roundup(sgl->length, IOMMU_PAGE_SIZE(tbl));
+
+	if (vio_cmo_alloc(viodev, alloc_size)) {
+		atomic_inc(&viodev->cmo.allocs_failed);
+		return 0;
+	}
+
+	ret = dma_iommu_ops.map_sg(dev, sglist, nelems, direction, attrs);
+
+	if (unlikely(!ret)) {
+		vio_cmo_dealloc(viodev, alloc_size);
+		atomic_inc(&viodev->cmo.allocs_failed);
+		return ret;
+	}
+
+	for_each_sg(sglist, sgl, ret, count)
+		alloc_size -= roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
+	if (alloc_size)
+		vio_cmo_dealloc(viodev, alloc_size);
+
+	return ret;
+}
+
+static void vio_dma_iommu_unmap_sg(struct device *dev,
+		struct scatterlist *sglist, int nelems,
+		enum dma_data_direction direction,
+		unsigned long attrs)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct iommu_table *tbl;
+	struct scatterlist *sgl;
+	size_t alloc_size = 0;
+	int count;
+
+	tbl = get_iommu_table_base(dev);
+	for_each_sg(sglist, sgl, nelems, count)
+		alloc_size += roundup(sgl->dma_length, IOMMU_PAGE_SIZE(tbl));
+
+	dma_iommu_ops.unmap_sg(dev, sglist, nelems, direction, attrs);
+
+	vio_cmo_dealloc(viodev, alloc_size);
+}
+
+static int vio_dma_iommu_dma_supported(struct device *dev, u64 mask)
+{
+        return dma_iommu_ops.dma_supported(dev, mask);
+}
+
+static u64 vio_dma_get_required_mask(struct device *dev)
+{
+        return dma_iommu_ops.get_required_mask(dev);
+}
+
+static struct dma_map_ops vio_dma_mapping_ops = {
+	.alloc             = vio_dma_iommu_alloc_coherent,
+	.free              = vio_dma_iommu_free_coherent,
+	.mmap		   = dma_direct_mmap_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,
+};
+
+/**
+ * vio_cmo_set_dev_desired - Set desired entitlement for a device
+ *
+ * @viodev: struct vio_dev for device to alter
+ * @desired: new desired entitlement level in bytes
+ *
+ * For use by devices to request a change to their entitlement at runtime or
+ * through sysfs.  The desired entitlement level is changed and a balancing
+ * of system resources is scheduled to run in the future.
+ */
+void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired)
+{
+	unsigned long flags;
+	struct vio_cmo_dev_entry *dev_ent;
+	int found = 0;
+
+	if (!firmware_has_feature(FW_FEATURE_CMO))
+		return;
+
+	spin_lock_irqsave(&vio_cmo.lock, flags);
+	if (desired < VIO_CMO_MIN_ENT)
+		desired = VIO_CMO_MIN_ENT;
+
+	/*
+	 * Changes will not be made for devices not in the device list.
+	 * If it is not in the device list, then no driver is loaded
+	 * for the device and it can not receive entitlement.
+	 */
+	list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
+		if (viodev == dev_ent->viodev) {
+			found = 1;
+			break;
+		}
+	if (!found) {
+		spin_unlock_irqrestore(&vio_cmo.lock, flags);
+		return;
+	}
+
+	/* Increase/decrease in desired device entitlement */
+	if (desired >= viodev->cmo.desired) {
+		/* Just bump the bus and device values prior to a balance*/
+		vio_cmo.desired += desired - viodev->cmo.desired;
+		viodev->cmo.desired = desired;
+	} else {
+		/* Decrease bus and device values for desired entitlement */
+		vio_cmo.desired -= viodev->cmo.desired - desired;
+		viodev->cmo.desired = desired;
+		/*
+		 * If less entitlement is desired than current entitlement, move
+		 * any reserve memory in the change region to the excess pool.
+		 */
+		if (viodev->cmo.entitled > desired) {
+			vio_cmo.reserve.size -= viodev->cmo.entitled - desired;
+			vio_cmo.excess.size += viodev->cmo.entitled - desired;
+			/*
+			 * If entitlement moving from the reserve pool to the
+			 * excess pool is currently unused, add to the excess
+			 * free counter.
+			 */
+			if (viodev->cmo.allocated < viodev->cmo.entitled)
+				vio_cmo.excess.free += viodev->cmo.entitled -
+				                       max(viodev->cmo.allocated, desired);
+			viodev->cmo.entitled = desired;
+		}
+	}
+	schedule_delayed_work(&vio_cmo.balance_q, 0);
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+/**
+ * vio_cmo_bus_probe - Handle CMO specific bus probe activities
+ *
+ * @viodev - Pointer to struct vio_dev for device
+ *
+ * Determine the devices IO memory entitlement needs, attempting
+ * to satisfy the system minimum entitlement at first and scheduling
+ * a balance operation to take care of the rest at a later time.
+ *
+ * Returns: 0 on success, -EINVAL when device doesn't support CMO, and
+ *          -ENOMEM when entitlement is not available for device or
+ *          device entry.
+ *
+ */
+static int vio_cmo_bus_probe(struct vio_dev *viodev)
+{
+	struct vio_cmo_dev_entry *dev_ent;
+	struct device *dev = &viodev->dev;
+	struct iommu_table *tbl;
+	struct vio_driver *viodrv = to_vio_driver(dev->driver);
+	unsigned long flags;
+	size_t size;
+	bool dma_capable = false;
+
+	tbl = get_iommu_table_base(dev);
+
+	/* A device requires entitlement if it has a DMA window property */
+	switch (viodev->family) {
+	case VDEVICE:
+		if (of_get_property(viodev->dev.of_node,
+					"ibm,my-dma-window", NULL))
+			dma_capable = true;
+		break;
+	case PFO:
+		dma_capable = false;
+		break;
+	default:
+		dev_warn(dev, "unknown device family: %d\n", viodev->family);
+		BUG();
+		break;
+	}
+
+	/* Configure entitlement for the device. */
+	if (dma_capable) {
+		/* Check that the driver is CMO enabled and get desired DMA */
+		if (!viodrv->get_desired_dma) {
+			dev_err(dev, "%s: device driver does not support CMO\n",
+			        __func__);
+			return -EINVAL;
+		}
+
+		viodev->cmo.desired =
+			IOMMU_PAGE_ALIGN(viodrv->get_desired_dma(viodev), tbl);
+		if (viodev->cmo.desired < VIO_CMO_MIN_ENT)
+			viodev->cmo.desired = VIO_CMO_MIN_ENT;
+		size = VIO_CMO_MIN_ENT;
+
+		dev_ent = kmalloc(sizeof(struct vio_cmo_dev_entry),
+		                  GFP_KERNEL);
+		if (!dev_ent)
+			return -ENOMEM;
+
+		dev_ent->viodev = viodev;
+		spin_lock_irqsave(&vio_cmo.lock, flags);
+		list_add(&dev_ent->list, &vio_cmo.device_list);
+	} else {
+		viodev->cmo.desired = 0;
+		size = 0;
+		spin_lock_irqsave(&vio_cmo.lock, flags);
+	}
+
+	/*
+	 * If the needs for vio_cmo.min have not changed since they
+	 * were last set, the number of devices in the OF tree has
+	 * been constant and the IO memory for this is already in
+	 * the reserve pool.
+	 */
+	if (vio_cmo.min == ((vio_cmo_num_OF_devs() + 1) *
+	                    VIO_CMO_MIN_ENT)) {
+		/* Updated desired entitlement if device requires it */
+		if (size)
+			vio_cmo.desired += (viodev->cmo.desired -
+		                        VIO_CMO_MIN_ENT);
+	} else {
+		size_t tmp;
+
+		tmp = vio_cmo.spare + vio_cmo.excess.free;
+		if (tmp < size) {
+			dev_err(dev, "%s: insufficient free "
+			        "entitlement to add device. "
+			        "Need %lu, have %lu\n", __func__,
+				size, (vio_cmo.spare + tmp));
+			spin_unlock_irqrestore(&vio_cmo.lock, flags);
+			return -ENOMEM;
+		}
+
+		/* Use excess pool first to fulfill request */
+		tmp = min(size, vio_cmo.excess.free);
+		vio_cmo.excess.free -= tmp;
+		vio_cmo.excess.size -= tmp;
+		vio_cmo.reserve.size += tmp;
+
+		/* Use spare if excess pool was insufficient */
+		vio_cmo.spare -= size - tmp;
+
+		/* Update bus accounting */
+		vio_cmo.min += size;
+		vio_cmo.desired += viodev->cmo.desired;
+	}
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+	return 0;
+}
+
+/**
+ * vio_cmo_bus_remove - Handle CMO specific bus removal activities
+ *
+ * @viodev - Pointer to struct vio_dev for device
+ *
+ * Remove the device from the cmo device list.  The minimum entitlement
+ * will be reserved for the device as long as it is in the system.  The
+ * rest of the entitlement the device had been allocated will be returned
+ * to the system.
+ */
+static void vio_cmo_bus_remove(struct vio_dev *viodev)
+{
+	struct vio_cmo_dev_entry *dev_ent;
+	unsigned long flags;
+	size_t tmp;
+
+	spin_lock_irqsave(&vio_cmo.lock, flags);
+	if (viodev->cmo.allocated) {
+		dev_err(&viodev->dev, "%s: device had %lu bytes of IO "
+		        "allocated after remove operation.\n",
+		        __func__, viodev->cmo.allocated);
+		BUG();
+	}
+
+	/*
+	 * Remove the device from the device list being maintained for
+	 * CMO enabled devices.
+	 */
+	list_for_each_entry(dev_ent, &vio_cmo.device_list, list)
+		if (viodev == dev_ent->viodev) {
+			list_del(&dev_ent->list);
+			kfree(dev_ent);
+			break;
+		}
+
+	/*
+	 * Devices may not require any entitlement and they do not need
+	 * to be processed.  Otherwise, return the device's entitlement
+	 * back to the pools.
+	 */
+	if (viodev->cmo.entitled) {
+		/*
+		 * This device has not yet left the OF tree, it's
+		 * minimum entitlement remains in vio_cmo.min and
+		 * vio_cmo.desired
+		 */
+		vio_cmo.desired -= (viodev->cmo.desired - VIO_CMO_MIN_ENT);
+
+		/*
+		 * Save min allocation for device in reserve as long
+		 * as it exists in OF tree as determined by later
+		 * balance operation
+		 */
+		viodev->cmo.entitled -= VIO_CMO_MIN_ENT;
+
+		/* Replenish spare from freed reserve pool */
+		if (viodev->cmo.entitled && (vio_cmo.spare < VIO_CMO_MIN_ENT)) {
+			tmp = min(viodev->cmo.entitled, (VIO_CMO_MIN_ENT -
+			                                 vio_cmo.spare));
+			vio_cmo.spare += tmp;
+			viodev->cmo.entitled -= tmp;
+		}
+
+		/* Remaining reserve goes to excess pool */
+		vio_cmo.excess.size += viodev->cmo.entitled;
+		vio_cmo.excess.free += viodev->cmo.entitled;
+		vio_cmo.reserve.size -= viodev->cmo.entitled;
+
+		/*
+		 * Until the device is removed it will keep a
+		 * minimum entitlement; this will guarantee that
+		 * a module unload/load will result in a success.
+		 */
+		viodev->cmo.entitled = VIO_CMO_MIN_ENT;
+		viodev->cmo.desired = VIO_CMO_MIN_ENT;
+		atomic_set(&viodev->cmo.allocs_failed, 0);
+	}
+
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+}
+
+static void vio_cmo_set_dma_ops(struct vio_dev *viodev)
+{
+	set_dma_ops(&viodev->dev, &vio_dma_mapping_ops);
+}
+
+/**
+ * vio_cmo_bus_init - CMO entitlement initialization at bus init time
+ *
+ * Set up the reserve and excess entitlement pools based on available
+ * system entitlement and the number of devices in the OF tree that
+ * require entitlement in the reserve pool.
+ */
+static void vio_cmo_bus_init(void)
+{
+	struct hvcall_mpp_data mpp_data;
+	int err;
+
+	memset(&vio_cmo, 0, sizeof(struct vio_cmo));
+	spin_lock_init(&vio_cmo.lock);
+	INIT_LIST_HEAD(&vio_cmo.device_list);
+	INIT_DELAYED_WORK(&vio_cmo.balance_q, vio_cmo_balance);
+
+	/* Get current system entitlement */
+	err = h_get_mpp(&mpp_data);
+
+	/*
+	 * On failure, continue with entitlement set to 0, will panic()
+	 * later when spare is reserved.
+	 */
+	if (err != H_SUCCESS) {
+		printk(KERN_ERR "%s: unable to determine system IO "\
+		       "entitlement. (%d)\n", __func__, err);
+		vio_cmo.entitled = 0;
+	} else {
+		vio_cmo.entitled = mpp_data.entitled_mem;
+	}
+
+	/* Set reservation and check against entitlement */
+	vio_cmo.spare = VIO_CMO_MIN_ENT;
+	vio_cmo.reserve.size = vio_cmo.spare;
+	vio_cmo.reserve.size += (vio_cmo_num_OF_devs() *
+	                         VIO_CMO_MIN_ENT);
+	if (vio_cmo.reserve.size > vio_cmo.entitled) {
+		printk(KERN_ERR "%s: insufficient system entitlement\n",
+		       __func__);
+		panic("%s: Insufficient system entitlement", __func__);
+	}
+
+	/* Set the remaining accounting variables */
+	vio_cmo.excess.size = vio_cmo.entitled - vio_cmo.reserve.size;
+	vio_cmo.excess.free = vio_cmo.excess.size;
+	vio_cmo.min = vio_cmo.reserve.size;
+	vio_cmo.desired = vio_cmo.reserve.size;
+}
+
+/* sysfs device functions and data structures for CMO */
+
+#define viodev_cmo_rd_attr(name)                                        \
+static ssize_t viodev_cmo_##name##_show(struct device *dev,             \
+                                        struct device_attribute *attr,  \
+                                         char *buf)                     \
+{                                                                       \
+	return sprintf(buf, "%lu\n", to_vio_dev(dev)->cmo.name);        \
+}
+
+static ssize_t viodev_cmo_allocs_failed_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	return sprintf(buf, "%d\n", atomic_read(&viodev->cmo.allocs_failed));
+}
+
+static ssize_t viodev_cmo_allocs_failed_reset(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	atomic_set(&viodev->cmo.allocs_failed, 0);
+	return count;
+}
+
+static ssize_t viodev_cmo_desired_set(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	size_t new_desired;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &new_desired);
+	if (ret)
+		return ret;
+
+	vio_cmo_set_dev_desired(viodev, new_desired);
+	return count;
+}
+
+viodev_cmo_rd_attr(desired);
+viodev_cmo_rd_attr(entitled);
+viodev_cmo_rd_attr(allocated);
+
+static ssize_t name_show(struct device *, struct device_attribute *, char *);
+static ssize_t devspec_show(struct device *, struct device_attribute *, char *);
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+			     char *buf);
+static struct device_attribute vio_cmo_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(devspec),
+	__ATTR_RO(modalias),
+	__ATTR(cmo_desired,       S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+	       viodev_cmo_desired_show, viodev_cmo_desired_set),
+	__ATTR(cmo_entitled,      S_IRUGO, viodev_cmo_entitled_show,      NULL),
+	__ATTR(cmo_allocated,     S_IRUGO, viodev_cmo_allocated_show,     NULL),
+	__ATTR(cmo_allocs_failed, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH,
+	       viodev_cmo_allocs_failed_show, viodev_cmo_allocs_failed_reset),
+	__ATTR_NULL
+};
+
+/* sysfs bus functions and data structures for CMO */
+
+#define viobus_cmo_rd_attr(name)                                        \
+static ssize_t cmo_##name##_show(struct bus_type *bt, char *buf)        \
+{                                                                       \
+	return sprintf(buf, "%lu\n", vio_cmo.name);                     \
+}                                                                       \
+static BUS_ATTR_RO(cmo_##name)
+
+#define viobus_cmo_pool_rd_attr(name, var)                              \
+static ssize_t                                                          \
+cmo_##name##_##var##_show(struct bus_type *bt, char *buf)               \
+{                                                                       \
+	return sprintf(buf, "%lu\n", vio_cmo.name.var);                 \
+}                                                                       \
+static BUS_ATTR_RO(cmo_##name##_##var)
+
+viobus_cmo_rd_attr(entitled);
+viobus_cmo_rd_attr(spare);
+viobus_cmo_rd_attr(min);
+viobus_cmo_rd_attr(desired);
+viobus_cmo_rd_attr(curr);
+viobus_cmo_pool_rd_attr(reserve, size);
+viobus_cmo_pool_rd_attr(excess, size);
+viobus_cmo_pool_rd_attr(excess, free);
+
+static ssize_t cmo_high_show(struct bus_type *bt, char *buf)
+{
+	return sprintf(buf, "%lu\n", vio_cmo.high);
+}
+
+static ssize_t cmo_high_store(struct bus_type *bt, const char *buf,
+			      size_t count)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&vio_cmo.lock, flags);
+	vio_cmo.high = vio_cmo.curr;
+	spin_unlock_irqrestore(&vio_cmo.lock, flags);
+
+	return count;
+}
+static BUS_ATTR_RW(cmo_high);
+
+static struct attribute *vio_bus_attrs[] = {
+	&bus_attr_cmo_entitled.attr,
+	&bus_attr_cmo_spare.attr,
+	&bus_attr_cmo_min.attr,
+	&bus_attr_cmo_desired.attr,
+	&bus_attr_cmo_curr.attr,
+	&bus_attr_cmo_high.attr,
+	&bus_attr_cmo_reserve_size.attr,
+	&bus_attr_cmo_excess_size.attr,
+	&bus_attr_cmo_excess_free.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(vio_bus);
+
+static void vio_cmo_sysfs_init(void)
+{
+	vio_bus_type.dev_attrs = vio_cmo_dev_attrs;
+	vio_bus_type.bus_groups = vio_bus_groups;
+}
+#else /* CONFIG_PPC_SMLPAR */
+int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; }
+void vio_cmo_set_dev_desired(struct vio_dev *viodev, size_t desired) {}
+static int vio_cmo_bus_probe(struct vio_dev *viodev) { return 0; }
+static void vio_cmo_bus_remove(struct vio_dev *viodev) {}
+static void vio_cmo_set_dma_ops(struct vio_dev *viodev) {}
+static void vio_cmo_bus_init(void) {}
+static void vio_cmo_sysfs_init(void) { }
+#endif /* CONFIG_PPC_SMLPAR */
+EXPORT_SYMBOL(vio_cmo_entitlement_update);
+EXPORT_SYMBOL(vio_cmo_set_dev_desired);
+
+
+/*
+ * Platform Facilities Option (PFO) support
+ */
+
+/**
+ * vio_h_cop_sync - Perform a synchronous PFO co-processor operation
+ *
+ * @vdev - Pointer to a struct vio_dev for device
+ * @op - Pointer to a struct vio_pfo_op for the operation parameters
+ *
+ * Calls the hypervisor to synchronously perform the PFO operation
+ * described in @op.  In the case of a busy response from the hypervisor,
+ * the operation will be re-submitted indefinitely unless a non-zero timeout
+ * is specified or an error occurs. The timeout places a limit on when to
+ * stop re-submitting a operation, the total time can be exceeded if an
+ * operation is in progress.
+ *
+ * If op->hcall_ret is not NULL, this will be set to the return from the
+ * last h_cop_op call or it will be 0 if an error not involving the h_call
+ * was encountered.
+ *
+ * Returns:
+ *	0 on success,
+ *	-EINVAL if the h_call fails due to an invalid parameter,
+ *	-E2BIG if the h_call can not be performed synchronously,
+ *	-EBUSY if a timeout is specified and has elapsed,
+ *	-EACCES if the memory area for data/status has been rescinded, or
+ *	-EPERM if a hardware fault has been indicated
+ */
+int vio_h_cop_sync(struct vio_dev *vdev, struct vio_pfo_op *op)
+{
+	struct device *dev = &vdev->dev;
+	unsigned long deadline = 0;
+	long hret = 0;
+	int ret = 0;
+
+	if (op->timeout)
+		deadline = jiffies + msecs_to_jiffies(op->timeout);
+
+	while (true) {
+		hret = plpar_hcall_norets(H_COP, op->flags,
+				vdev->resource_id,
+				op->in, op->inlen, op->out,
+				op->outlen, op->csbcpb);
+
+		if (hret == H_SUCCESS ||
+		    (hret != H_NOT_ENOUGH_RESOURCES &&
+		     hret != H_BUSY && hret != H_RESOURCE) ||
+		    (op->timeout && time_after(deadline, jiffies)))
+			break;
+
+		dev_dbg(dev, "%s: hcall ret(%ld), retrying.\n", __func__, hret);
+	}
+
+	switch (hret) {
+	case H_SUCCESS:
+		ret = 0;
+		break;
+	case H_OP_MODE:
+	case H_TOO_BIG:
+		ret = -E2BIG;
+		break;
+	case H_RESCINDED:
+		ret = -EACCES;
+		break;
+	case H_HARDWARE:
+		ret = -EPERM;
+		break;
+	case H_NOT_ENOUGH_RESOURCES:
+	case H_RESOURCE:
+	case H_BUSY:
+		ret = -EBUSY;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret)
+		dev_dbg(dev, "%s: Sync h_cop_op failure (ret:%d) (hret:%ld)\n",
+				__func__, ret, hret);
+
+	op->hcall_err = hret;
+	return ret;
+}
+EXPORT_SYMBOL(vio_h_cop_sync);
+
+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+{
+	const __be32 *dma_window;
+	struct iommu_table *tbl;
+	unsigned long offset, size;
+
+	dma_window = of_get_property(dev->dev.of_node,
+				  "ibm,my-dma-window", NULL);
+	if (!dma_window)
+		return NULL;
+
+	tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
+	if (tbl == NULL)
+		return NULL;
+
+	of_parse_dma_window(dev->dev.of_node, dma_window,
+			    &tbl->it_index, &offset, &size);
+
+	/* TCE table size - measured in tce entries */
+	tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K;
+	tbl->it_size = size >> tbl->it_page_shift;
+	/* offset for VIO should always be 0 */
+	tbl->it_offset = offset >> tbl->it_page_shift;
+	tbl->it_busno = 0;
+	tbl->it_type = TCE_VB;
+	tbl->it_blocksize = 16;
+
+	if (firmware_has_feature(FW_FEATURE_LPAR))
+		tbl->it_ops = &iommu_table_lpar_multi_ops;
+	else
+		tbl->it_ops = &iommu_table_pseries_ops;
+
+	return iommu_init_table(tbl, -1);
+}
+
+/**
+ * vio_match_device: - Tell if a VIO device has a matching
+ *			VIO device id structure.
+ * @ids:	array of VIO device id structures to search in
+ * @dev:	the VIO device structure to match against
+ *
+ * Used by a driver to check whether a VIO device present in the
+ * system is in its list of supported devices. Returns the matching
+ * vio_device_id structure or NULL if there is no match.
+ */
+static const struct vio_device_id *vio_match_device(
+		const struct vio_device_id *ids, const struct vio_dev *dev)
+{
+	while (ids->type[0] != '\0') {
+		if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
+		    of_device_is_compatible(dev->dev.of_node,
+					 ids->compat))
+			return ids;
+		ids++;
+	}
+	return NULL;
+}
+
+/*
+ * Convert from struct device to struct vio_dev and pass to driver.
+ * dev->driver has already been set by generic code because vio_bus_match
+ * succeeded.
+ */
+static int vio_bus_probe(struct device *dev)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct vio_driver *viodrv = to_vio_driver(dev->driver);
+	const struct vio_device_id *id;
+	int error = -ENODEV;
+
+	if (!viodrv->probe)
+		return error;
+
+	id = vio_match_device(viodrv->id_table, viodev);
+	if (id) {
+		memset(&viodev->cmo, 0, sizeof(viodev->cmo));
+		if (firmware_has_feature(FW_FEATURE_CMO)) {
+			error = vio_cmo_bus_probe(viodev);
+			if (error)
+				return error;
+		}
+		error = viodrv->probe(viodev, id);
+		if (error && firmware_has_feature(FW_FEATURE_CMO))
+			vio_cmo_bus_remove(viodev);
+	}
+
+	return error;
+}
+
+/* convert from struct device to struct vio_dev and pass to driver. */
+static int vio_bus_remove(struct device *dev)
+{
+	struct vio_dev *viodev = to_vio_dev(dev);
+	struct vio_driver *viodrv = to_vio_driver(dev->driver);
+	struct device *devptr;
+	int ret = 1;
+
+	/*
+	 * Hold a reference to the device after the remove function is called
+	 * to allow for CMO accounting cleanup for the device.
+	 */
+	devptr = get_device(dev);
+
+	if (viodrv->remove)
+		ret = viodrv->remove(viodev);
+
+	if (!ret && firmware_has_feature(FW_FEATURE_CMO))
+		vio_cmo_bus_remove(viodev);
+
+	put_device(devptr);
+	return ret;
+}
+
+/**
+ * vio_register_driver: - Register a new vio driver
+ * @viodrv:	The vio_driver structure to be registered.
+ */
+int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
+			  const char *mod_name)
+{
+	pr_debug("%s: driver %s registering\n", __func__, viodrv->name);
+
+	/* fill in 'struct driver' fields */
+	viodrv->driver.name = viodrv->name;
+	viodrv->driver.pm = viodrv->pm;
+	viodrv->driver.bus = &vio_bus_type;
+	viodrv->driver.owner = owner;
+	viodrv->driver.mod_name = mod_name;
+
+	return driver_register(&viodrv->driver);
+}
+EXPORT_SYMBOL(__vio_register_driver);
+
+/**
+ * vio_unregister_driver - Remove registration of vio driver.
+ * @viodrv:	The vio_driver struct to be removed form registration
+ */
+void vio_unregister_driver(struct vio_driver *viodrv)
+{
+	driver_unregister(&viodrv->driver);
+}
+EXPORT_SYMBOL(vio_unregister_driver);
+
+/* vio_dev refcount hit 0 */
+static void vio_dev_release(struct device *dev)
+{
+	struct iommu_table *tbl = get_iommu_table_base(dev);
+
+	if (tbl)
+		iommu_free_table(tbl, of_node_full_name(dev->of_node));
+	of_node_put(dev->of_node);
+	kfree(to_vio_dev(dev));
+}
+
+/**
+ * vio_register_device_node: - Register a new vio device.
+ * @of_node:	The OF node for this device.
+ *
+ * Creates and initializes a vio_dev structure from the data in
+ * of_node and adds it to the list of virtual devices.
+ * Returns a pointer to the created vio_dev or NULL if node has
+ * NULL device_type or compatible fields.
+ */
+struct vio_dev *vio_register_device_node(struct device_node *of_node)
+{
+	struct vio_dev *viodev;
+	struct device_node *parent_node;
+	const __be32 *prop;
+	enum vio_dev_family family;
+	const char *of_node_name = of_node->name ? of_node->name : "<unknown>";
+
+	/*
+	 * Determine if this node is a under the /vdevice node or under the
+	 * /ibm,platform-facilities node.  This decides the device's family.
+	 */
+	parent_node = of_get_parent(of_node);
+	if (parent_node) {
+		if (!strcmp(parent_node->full_name, "/ibm,platform-facilities"))
+			family = PFO;
+		else if (!strcmp(parent_node->full_name, "/vdevice"))
+			family = VDEVICE;
+		else {
+			pr_warn("%s: parent(%s) of %s not recognized.\n",
+					__func__,
+					parent_node->full_name,
+					of_node_name);
+			of_node_put(parent_node);
+			return NULL;
+		}
+		of_node_put(parent_node);
+	} else {
+		pr_warn("%s: could not determine the parent of node %s.\n",
+				__func__, of_node_name);
+		return NULL;
+	}
+
+	if (family == PFO) {
+		if (of_get_property(of_node, "interrupt-controller", NULL)) {
+			pr_debug("%s: Skipping the interrupt controller %s.\n",
+					__func__, of_node_name);
+			return NULL;
+		}
+	}
+
+	/* allocate a vio_dev for this node */
+	viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL);
+	if (viodev == NULL) {
+		pr_warn("%s: allocation failure for VIO device.\n", __func__);
+		return NULL;
+	}
+
+	/* we need the 'device_type' property, in order to match with drivers */
+	viodev->family = family;
+	if (viodev->family == VDEVICE) {
+		unsigned int unit_address;
+
+		if (of_node->type != NULL)
+			viodev->type = of_node->type;
+		else {
+			pr_warn("%s: node %s is missing the 'device_type' "
+					"property.\n", __func__, of_node_name);
+			goto out;
+		}
+
+		prop = of_get_property(of_node, "reg", NULL);
+		if (prop == NULL) {
+			pr_warn("%s: node %s missing 'reg'\n",
+					__func__, of_node_name);
+			goto out;
+		}
+		unit_address = of_read_number(prop, 1);
+		dev_set_name(&viodev->dev, "%x", unit_address);
+		viodev->irq = irq_of_parse_and_map(of_node, 0);
+		viodev->unit_address = unit_address;
+	} else {
+		/* PFO devices need their resource_id for submitting COP_OPs
+		 * This is an optional field for devices, but is required when
+		 * performing synchronous ops */
+		prop = of_get_property(of_node, "ibm,resource-id", NULL);
+		if (prop != NULL)
+			viodev->resource_id = of_read_number(prop, 1);
+
+		dev_set_name(&viodev->dev, "%s", of_node_name);
+		viodev->type = of_node_name;
+		viodev->irq = 0;
+	}
+
+	viodev->name = of_node->name;
+	viodev->dev.of_node = of_node_get(of_node);
+
+	set_dev_node(&viodev->dev, of_node_to_nid(of_node));
+
+	/* init generic 'struct device' fields: */
+	viodev->dev.parent = &vio_bus_device.dev;
+	viodev->dev.bus = &vio_bus_type;
+	viodev->dev.release = vio_dev_release;
+
+	if (of_get_property(viodev->dev.of_node, "ibm,my-dma-window", NULL)) {
+		if (firmware_has_feature(FW_FEATURE_CMO))
+			vio_cmo_set_dma_ops(viodev);
+		else
+			set_dma_ops(&viodev->dev, &dma_iommu_ops);
+
+		set_iommu_table_base(&viodev->dev,
+				     vio_build_iommu_table(viodev));
+
+		/* needed to ensure proper operation of coherent allocations
+		 * later, in case driver doesn't set it explicitly */
+		viodev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
+		viodev->dev.dma_mask = &viodev->dev.coherent_dma_mask;
+	}
+
+	/* register with generic device framework */
+	if (device_register(&viodev->dev)) {
+		printk(KERN_ERR "%s: failed to register device %s\n",
+				__func__, dev_name(&viodev->dev));
+		put_device(&viodev->dev);
+		return NULL;
+	}
+
+	return viodev;
+
+out:	/* Use this exit point for any return prior to device_register */
+	kfree(viodev);
+
+	return NULL;
+}
+EXPORT_SYMBOL(vio_register_device_node);
+
+/*
+ * vio_bus_scan_for_devices - Scan OF and register each child device
+ * @root_name - OF node name for the root of the subtree to search.
+ *		This must be non-NULL
+ *
+ * Starting from the root node provide, register the device node for
+ * each child beneath the root.
+ */
+static void vio_bus_scan_register_devices(char *root_name)
+{
+	struct device_node *node_root, *node_child;
+
+	if (!root_name)
+		return;
+
+	node_root = of_find_node_by_name(NULL, root_name);
+	if (node_root) {
+
+		/*
+		 * Create struct vio_devices for each virtual device in
+		 * the device tree. Drivers will associate with them later.
+		 */
+		node_child = of_get_next_child(node_root, NULL);
+		while (node_child) {
+			vio_register_device_node(node_child);
+			node_child = of_get_next_child(node_root, node_child);
+		}
+		of_node_put(node_root);
+	}
+}
+
+/**
+ * vio_bus_init: - Initialize the virtual IO bus
+ */
+static int __init vio_bus_init(void)
+{
+	int err;
+
+	if (firmware_has_feature(FW_FEATURE_CMO))
+		vio_cmo_sysfs_init();
+
+	err = bus_register(&vio_bus_type);
+	if (err) {
+		printk(KERN_ERR "failed to register VIO bus\n");
+		return err;
+	}
+
+	/*
+	 * The fake parent of all vio devices, just to give us
+	 * a nice directory
+	 */
+	err = device_register(&vio_bus_device.dev);
+	if (err) {
+		printk(KERN_WARNING "%s: device_register returned %i\n",
+				__func__, err);
+		return err;
+	}
+
+	if (firmware_has_feature(FW_FEATURE_CMO))
+		vio_cmo_bus_init();
+
+	return 0;
+}
+postcore_initcall(vio_bus_init);
+
+static int __init vio_device_init(void)
+{
+	vio_bus_scan_register_devices("vdevice");
+	vio_bus_scan_register_devices("ibm,platform-facilities");
+
+	return 0;
+}
+device_initcall(vio_device_init);
+
+static ssize_t name_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
+}
+
+static ssize_t devspec_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct device_node *of_node = dev->of_node;
+
+	return sprintf(buf, "%s\n", of_node_full_name(of_node));
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	const struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct device_node *dn;
+	const char *cp;
+
+	dn = dev->of_node;
+	if (!dn) {
+		strcpy(buf, "\n");
+		return strlen(buf);
+	}
+	cp = of_get_property(dn, "compatible", NULL);
+	if (!cp) {
+		strcpy(buf, "\n");
+		return strlen(buf);
+	}
+
+	return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp);
+}
+
+static struct device_attribute vio_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(devspec),
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
+
+void vio_unregister_device(struct vio_dev *viodev)
+{
+	device_unregister(&viodev->dev);
+}
+EXPORT_SYMBOL(vio_unregister_device);
+
+static int vio_bus_match(struct device *dev, struct device_driver *drv)
+{
+	const struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct vio_driver *vio_drv = to_vio_driver(drv);
+	const struct vio_device_id *ids = vio_drv->id_table;
+
+	return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL);
+}
+
+static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
+{
+	const struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct device_node *dn;
+	const char *cp;
+
+	dn = dev->of_node;
+	if (!dn)
+		return -ENODEV;
+	cp = of_get_property(dn, "compatible", NULL);
+	if (!cp)
+		return -ENODEV;
+
+	add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp);
+	return 0;
+}
+
+struct bus_type vio_bus_type = {
+	.name = "vio",
+	.dev_attrs = vio_dev_attrs,
+	.uevent = vio_hotplug,
+	.match = vio_bus_match,
+	.probe = vio_bus_probe,
+	.remove = vio_bus_remove,
+};
+
+/**
+ * vio_get_attribute: - get attribute for virtual device
+ * @vdev:	The vio device to get property.
+ * @which:	The property/attribute to be extracted.
+ * @length:	Pointer to length of returned data size (unused if NULL).
+ *
+ * Calls prom.c's of_get_property() to return the value of the
+ * attribute specified by @which
+*/
+const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
+{
+	return of_get_property(vdev->dev.of_node, which, length);
+}
+EXPORT_SYMBOL(vio_get_attribute);
+
+#ifdef CONFIG_PPC_PSERIES
+/* vio_find_name() - internal because only vio.c knows how we formatted the
+ * kobject name
+ */
+static struct vio_dev *vio_find_name(const char *name)
+{
+	struct device *found;
+
+	found = bus_find_device_by_name(&vio_bus_type, NULL, name);
+	if (!found)
+		return NULL;
+
+	return to_vio_dev(found);
+}
+
+/**
+ * vio_find_node - find an already-registered vio_dev
+ * @vnode: device_node of the virtual device we're looking for
+ *
+ * Takes a reference to the embedded struct device which needs to be dropped
+ * after use.
+ */
+struct vio_dev *vio_find_node(struct device_node *vnode)
+{
+	char kobj_name[20];
+	struct device_node *vnode_parent;
+	const char *dev_type;
+
+	vnode_parent = of_get_parent(vnode);
+	if (!vnode_parent)
+		return NULL;
+
+	dev_type = of_get_property(vnode_parent, "device_type", NULL);
+	of_node_put(vnode_parent);
+	if (!dev_type)
+		return NULL;
+
+	/* construct the kobject name from the device node */
+	if (!strcmp(dev_type, "vdevice")) {
+		const __be32 *prop;
+		
+		prop = of_get_property(vnode, "reg", NULL);
+		if (!prop)
+			return NULL;
+		snprintf(kobj_name, sizeof(kobj_name), "%x",
+			 (uint32_t)of_read_number(prop, 1));
+	} else if (!strcmp(dev_type, "ibm,platform-facilities"))
+		snprintf(kobj_name, sizeof(kobj_name), "%s", vnode->name);
+	else
+		return NULL;
+
+	return vio_find_name(kobj_name);
+}
+EXPORT_SYMBOL(vio_find_node);
+
+int vio_enable_interrupts(struct vio_dev *dev)
+{
+	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
+	if (rc != H_SUCCESS)
+		printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(vio_enable_interrupts);
+
+int vio_disable_interrupts(struct vio_dev *dev)
+{
+	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
+	if (rc != H_SUCCESS)
+		printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(vio_disable_interrupts);
+#endif /* CONFIG_PPC_PSERIES */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/purgatory/.gitignore linux-libre-4.10-rc8-gnu/arch/powerpc/purgatory/.gitignore
--- linux-libre-4.9-gnu/arch/powerpc/purgatory/.gitignore	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/purgatory/.gitignore	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2 @@
+kexec-purgatory.c
+purgatory.ro
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/purgatory/Makefile linux-libre-4.10-rc8-gnu/arch/powerpc/purgatory/Makefile
--- linux-libre-4.9-gnu/arch/powerpc/purgatory/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/purgatory/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,15 @@
+targets += trampoline.o purgatory.ro kexec-purgatory.c
+
+LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined
+
+$(obj)/purgatory.ro: $(obj)/trampoline.o FORCE
+		$(call if_changed,ld)
+
+CMD_BIN2C = $(objtree)/scripts/basic/bin2c
+quiet_cmd_bin2c = BIN2C   $@
+      cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
+
+$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
+	$(call if_changed,bin2c)
+
+obj-y	+= kexec-purgatory.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/purgatory/trampoline.S linux-libre-4.10-rc8-gnu/arch/powerpc/purgatory/trampoline.S
--- linux-libre-4.9-gnu/arch/powerpc/purgatory/trampoline.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/purgatory/trampoline.S	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * kexec trampoline
+ *
+ * Based on code taken from kexec-tools and kexec-lite.
+ *
+ * Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
+ * Copyright (C) 2006, Mohan Kumar M, IBM Corporation
+ * Copyright (C) 2013, Anton Blanchard, 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 (version 2 of the License).
+ */
+
+#if defined(__LITTLE_ENDIAN__)
+#define STWX_BE	stwbrx
+#define LWZX_BE	lwbrx
+#elif defined(__BIG_ENDIAN__)
+#define STWX_BE	stwx
+#define LWZX_BE	lwzx
+#else
+#error no endianness defined!
+#endif
+
+	.machine ppc64
+	.balign 256
+	.globl purgatory_start
+purgatory_start:
+	b	master
+
+	/* ABI: possible run_at_load flag at 0x5c */
+	.org purgatory_start + 0x5c
+	.globl run_at_load
+run_at_load:
+	.long 0
+	.size run_at_load, . - run_at_load
+
+	/* ABI: slaves start at 60 with r3=phys */
+	.org purgatory_start + 0x60
+slave:
+	b .
+	/* ABI: end of copied region */
+	.org purgatory_start + 0x100
+	.size purgatory_start, . - purgatory_start
+
+/*
+ * The above 0x100 bytes at purgatory_start are replaced with the
+ * code from the kernel (or next stage) by setup_purgatory().
+ */
+
+master:
+	or	%r1,%r1,%r1	/* low priority to let other threads catchup */
+	isync
+	mr	%r17,%r3	/* save cpu id to r17 */
+	mr	%r15,%r4	/* save physical address in reg15 */
+
+	or	%r3,%r3,%r3	/* ok now to high priority, lets boot */
+	lis	%r6,0x1
+	mtctr	%r6		/* delay a bit for slaves to catch up */
+	bdnz	.		/* before we overwrite 0-100 again */
+
+	bl	0f		/* Work out where we're running */
+0:	mflr	%r18
+
+	/* load device-tree address */
+	ld	%r3, (dt_offset - 0b)(%r18)
+	mr	%r16,%r3	/* save dt address in reg16 */
+	li	%r4,20
+	LWZX_BE	%r6,%r3,%r4	/* fetch __be32 version number at byte 20 */
+	cmpwi	%r0,%r6,2	/* v2 or later? */
+	blt	1f
+	li	%r4,28
+	STWX_BE	%r17,%r3,%r4	/* Store my cpu as __be32 at byte 28 */
+1:
+	/* load the kernel address */
+	ld	%r4,(kernel - 0b)(%r18)
+
+	/* load the run_at_load flag */
+	/* possibly patched by kexec */
+	ld	%r6,(run_at_load - 0b)(%r18)
+	/* and patch it into the kernel */
+	stw	%r6,(0x5c)(%r4)
+
+	mr	%r3,%r16	/* restore dt address */
+
+	li	%r5,0		/* r5 will be 0 for kernel */
+
+	mfmsr	%r11
+	andi.	%r10,%r11,1	/* test MSR_LE */
+	bne	.Little_endian
+
+	mtctr	%r4		/* prepare branch to */
+	bctr			/* start kernel */
+
+.Little_endian:
+	mtsrr0	%r4		/* prepare branch to */
+
+	clrrdi	%r11,%r11,1	/* clear MSR_LE */
+	mtsrr1	%r11
+
+	rfid			/* update MSR and start kernel */
+
+
+	.balign 8
+	.globl kernel
+kernel:
+	.llong  0x0
+	.size kernel, . - kernel
+
+	.balign 8
+	.globl dt_offset
+dt_offset:
+	.llong  0x0
+	.size dt_offset, . - dt_offset
+
+
+	.data
+	.balign 8
+.globl sha256_digest
+sha256_digest:
+	.skip	32
+	.size sha256_digest, . - sha256_digest
+
+	.balign 8
+.globl sha_regions
+sha_regions:
+	.skip	8 * 2 * 16
+	.size sha_regions, . - sha_regions
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_lbc.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_lbc.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_lbc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_lbc.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <asm/prom.h>
 #include <asm/fsl_lbc.h>
 
-static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
+static DEFINE_SPINLOCK(fsl_lbc_lock);
 struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
 EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_pmc.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_pmc.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_pmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_pmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -85,8 +85,4 @@ static struct platform_driver pmc_driver
 	.probe = pmc_probe,
 };
 
-static int __init pmc_init(void)
-{
-	return platform_driver_register(&pmc_driver);
-}
-device_initcall(pmc_init);
+builtin_platform_driver(pmc_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_rio.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_rio.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_rio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_rio.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,10 +80,8 @@
 		"3:	li %1,-1\n"			\
 		"	li %0,%3\n"			\
 		"	b 2b\n"				\
-		".section __ex_table,\"a\"\n"		\
-			PPC_LONG_ALIGN "\n"		\
-			PPC_LONG "1b,3b\n"		\
-		".text"					\
+		".previous\n"				\
+		EX_TABLE(1b, 3b)			\
 		: "=r" (err), "=r" (x)			\
 		: "b" (addr), "i" (-EFAULT), "0" (err))
 
@@ -113,7 +111,7 @@ int fsl_rio_mcheck_exception(struct pt_r
 			out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
 				 0);
 			regs->msr |= MSR_RI;
-			regs->nip = entry->fixup;
+			regs->nip = extable_fixup(entry);
 			return 1;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_soc.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_soc.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/fsl_soc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/fsl_soc.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,13 +77,10 @@ phys_addr_t get_immrbase(void)
 
 EXPORT_SYMBOL(get_immrbase);
 
-static u32 sysfreq = -1;
-
 u32 fsl_get_sys_freq(void)
 {
+	static u32 sysfreq = -1;
 	struct device_node *soc;
-	const u32 *prop;
-	int size;
 
 	if (sysfreq != -1)
 		return sysfreq;
@@ -92,12 +89,9 @@ u32 fsl_get_sys_freq(void)
 	if (!soc)
 		return -1;
 
-	prop = of_get_property(soc, "clock-frequency", &size);
-	if (!prop || size != sizeof(*prop) || *prop == 0)
-		prop = of_get_property(soc, "bus-frequency", &size);
-
-	if (prop && size == sizeof(*prop))
-		sysfreq = *prop;
+	of_property_read_u32(soc, "clock-frequency", &sysfreq);
+	if (sysfreq == -1 || !sysfreq)
+		of_property_read_u32(soc, "bus-frequency", &sysfreq);
 
 	of_node_put(soc);
 	return sysfreq;
@@ -106,23 +100,17 @@ EXPORT_SYMBOL(fsl_get_sys_freq);
 
 #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
 
-static u32 brgfreq = -1;
-
 u32 get_brgfreq(void)
 {
+	static u32 brgfreq = -1;
 	struct device_node *node;
-	const unsigned int *prop;
-	int size;
 
 	if (brgfreq != -1)
 		return brgfreq;
 
 	node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");
 	if (node) {
-		prop = of_get_property(node, "clock-frequency", &size);
-		if (prop && size == 4)
-			brgfreq = *prop;
-
+		of_property_read_u32(node, "clock-frequency", &brgfreq);
 		of_node_put(node);
 		return brgfreq;
 	}
@@ -135,15 +123,11 @@ u32 get_brgfreq(void)
 		node = of_find_node_by_type(NULL, "qe");
 
 	if (node) {
-		prop = of_get_property(node, "brg-frequency", &size);
-		if (prop && size == 4)
-			brgfreq = *prop;
-
-		if (brgfreq == -1 || brgfreq == 0) {
-			prop = of_get_property(node, "bus-frequency", &size);
-			if (prop && size == 4)
-				brgfreq = *prop / 2;
-		}
+		of_property_read_u32(node, "brg-frequency", &brgfreq);
+		if (brgfreq == -1 || !brgfreq)
+			if (!of_property_read_u32(node, "bus-frequency",
+						  &brgfreq))
+				brgfreq /= 2;
 		of_node_put(node);
 	}
 
@@ -152,10 +136,9 @@ u32 get_brgfreq(void)
 
 EXPORT_SYMBOL(get_brgfreq);
 
-static u32 fs_baudrate = -1;
-
 u32 get_baudrate(void)
 {
+	static u32 fs_baudrate = -1;
 	struct device_node *node;
 
 	if (fs_baudrate != -1)
@@ -163,12 +146,7 @@ u32 get_baudrate(void)
 
 	node = of_find_node_by_type(NULL, "serial");
 	if (node) {
-		int size;
-		const unsigned int *prop = of_get_property(node,
-				"current-speed", &size);
-
-		if (prop)
-			fs_baudrate = *prop;
+		of_property_read_u32(node, "current-speed", &fs_baudrate);
 		of_node_put(node);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/scom.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/scom.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/scom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/scom.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <asm/debug.h>
 #include <asm/prom.h>
 #include <asm/scom.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 const struct scom_controller *scom_controller;
 EXPORT_SYMBOL_GPL(scom_controller);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/tsi108_pci.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/tsi108_pci.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/tsi108_pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/tsi108_pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/machdep.h>
 #include <asm/pci-bridge.h>
 #include <asm/tsi108.h>
@@ -137,10 +137,8 @@ void tsi108_clear_pci_error(u32 pci_cfg_
 		".section .fixup,\"ax\"\n"		\
 		"3:	li %0,-1\n"			\
 		"	b 2b\n"				\
-		".section __ex_table,\"a\"\n"		\
-		"	.align 2\n"			\
-		"	.long 1b,3b\n"			\
-		".text"					\
+		".previous\n"				\
+		EX_TABLE(1b, 3b)			\
 		: "=r"(x) : "r"(addr))
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/xics/icp-opal.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/xics/icp-opal.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/xics/icp-opal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/xics/icp-opal.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,7 @@
 #include <asm/xics.h>
 #include <asm/io.h>
 #include <asm/opal.h>
+#include <asm/kvm_ppc.h>
 
 static void icp_opal_teardown_cpu(void)
 {
@@ -39,7 +40,26 @@ static void icp_opal_flush_ipi(void)
 	 * Should we be flagging idle loop instead?
 	 * Or creating some task to be scheduled?
 	 */
-	opal_int_eoi((0x00 << 24) | XICS_IPI);
+	if (opal_int_eoi((0x00 << 24) | XICS_IPI) > 0)
+		force_external_irq_replay();
+}
+
+static unsigned int icp_opal_get_xirr(void)
+{
+	unsigned int kvm_xirr;
+	__be32 hw_xirr;
+	int64_t rc;
+
+	/* Handle an interrupt latched by KVM first */
+	kvm_xirr = kvmppc_get_xics_latch();
+	if (kvm_xirr)
+		return kvm_xirr;
+
+	/* Then ask OPAL */
+	rc = opal_int_get_xirr(&hw_xirr, false);
+	if (rc < 0)
+		return 0;
+	return be32_to_cpu(hw_xirr);
 }
 
 static unsigned int icp_opal_get_irq(void)
@@ -47,12 +67,8 @@ static unsigned int icp_opal_get_irq(voi
 	unsigned int xirr;
 	unsigned int vec;
 	unsigned int irq;
-	int64_t rc;
 
-	rc = opal_int_get_xirr(&xirr, false);
-	if (rc < 0)
-		return 0;
-	xirr = be32_to_cpu(xirr);
+	xirr = icp_opal_get_xirr();
 	vec = xirr & 0x00ffffff;
 	if (vec == XICS_IRQ_SPURIOUS)
 		return 0;
@@ -67,7 +83,8 @@ static unsigned int icp_opal_get_irq(voi
 	xics_mask_unknown_vec(vec);
 
 	/* We might learn about it later, so EOI it */
-	opal_int_eoi(xirr);
+	if (opal_int_eoi(xirr) > 0)
+		force_external_irq_replay();
 
 	return 0;
 }
@@ -103,18 +120,49 @@ static void icp_opal_cause_ipi(int cpu,
 {
 	int hw_cpu = get_hard_smp_processor_id(cpu);
 
+	kvmppc_set_host_ipi(cpu, 1);
 	opal_int_set_mfrr(hw_cpu, IPI_PRIORITY);
 }
 
 static irqreturn_t icp_opal_ipi_action(int irq, void *dev_id)
 {
-	int hw_cpu = hard_smp_processor_id();
+	int cpu = smp_processor_id();
 
-	opal_int_set_mfrr(hw_cpu, 0xff);
+	kvmppc_set_host_ipi(cpu, 0);
+	opal_int_set_mfrr(get_hard_smp_processor_id(cpu), 0xff);
 
 	return smp_ipi_demux();
 }
 
+/*
+ * Called when an interrupt is received on an off-line CPU to
+ * clear the interrupt, so that the CPU can go back to nap mode.
+ */
+void icp_opal_flush_interrupt(void)
+{
+	unsigned int xirr;
+	unsigned int vec;
+
+	do {
+		xirr = icp_opal_get_xirr();
+		vec = xirr & 0x00ffffff;
+		if (vec == XICS_IRQ_SPURIOUS)
+			break;
+		if (vec == XICS_IPI) {
+			/* Clear pending IPI */
+			int cpu = smp_processor_id();
+			kvmppc_set_host_ipi(cpu, 0);
+			opal_int_set_mfrr(get_hard_smp_processor_id(cpu), 0xff);
+		} else {
+			pr_err("XICS: hw interrupt 0x%x to offline cpu, "
+			       "disabling\n", vec);
+			xics_mask_unknown_vec(vec);
+		}
+
+		/* EOI the interrupt */
+	} while (opal_int_eoi(xirr) > 0);
+}
+
 #endif /* CONFIG_SMP */
 
 static const struct icp_ops icp_opal_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/sysdev/xilinx_intc.c linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/xilinx_intc.c
--- linux-libre-4.9-gnu/arch/powerpc/sysdev/xilinx_intc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/sysdev/xilinx_intc.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,194 +29,7 @@
 #include <asm/processor.h>
 #include <asm/i8259.h>
 #include <asm/irq.h>
-
-/*
- * INTC Registers
- */
-#define XINTC_ISR	0	/* Interrupt Status */
-#define XINTC_IPR	4	/* Interrupt Pending */
-#define XINTC_IER	8	/* Interrupt Enable */
-#define XINTC_IAR	12	/* Interrupt Acknowledge */
-#define XINTC_SIE	16	/* Set Interrupt Enable bits */
-#define XINTC_CIE	20	/* Clear Interrupt Enable bits */
-#define XINTC_IVR	24	/* Interrupt Vector */
-#define XINTC_MER	28	/* Master Enable */
-
-static struct irq_domain *master_irqhost;
-
-#define XILINX_INTC_MAXIRQS	(32)
-
-/* The following table allows the interrupt type, edge or level,
- * to be cached after being read from the device tree until the interrupt
- * is mapped
- */
-static int xilinx_intc_typetable[XILINX_INTC_MAXIRQS];
-
-/* Map the interrupt type from the device tree to the interrupt types
- * used by the interrupt subsystem
- */
-static unsigned char xilinx_intc_map_senses[] = {
-	IRQ_TYPE_EDGE_RISING,
-	IRQ_TYPE_EDGE_FALLING,
-	IRQ_TYPE_LEVEL_HIGH,
-	IRQ_TYPE_LEVEL_LOW,
-};
-
-/*
- * The interrupt controller is setup such that it doesn't work well with
- * the level interrupt handler in the kernel because the handler acks the
- * interrupt before calling the application interrupt handler. To deal with
- * that, we use 2 different irq chips so that different functions can be
- * used for level and edge type interrupts.
- *
- * IRQ Chip common (across level and edge) operations
- */
-static void xilinx_intc_mask(struct irq_data *d)
-{
-	int irq = irqd_to_hwirq(d);
-	void * regs = irq_data_get_irq_chip_data(d);
-	pr_debug("mask: %d\n", irq);
-	out_be32(regs + XINTC_CIE, 1 << irq);
-}
-
-static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	return 0;
-}
-
-/*
- * IRQ Chip level operations
- */
-static void xilinx_intc_level_unmask(struct irq_data *d)
-{
-	int irq = irqd_to_hwirq(d);
-	void * regs = irq_data_get_irq_chip_data(d);
-	pr_debug("unmask: %d\n", irq);
-	out_be32(regs + XINTC_SIE, 1 << irq);
-
-	/* ack level irqs because they can't be acked during
-	 * ack function since the handle_level_irq function
-	 * acks the irq before calling the inerrupt handler
-	 */
-	out_be32(regs + XINTC_IAR, 1 << irq);
-}
-
-static struct irq_chip xilinx_intc_level_irqchip = {
-	.name = "Xilinx Level INTC",
-	.irq_mask = xilinx_intc_mask,
-	.irq_mask_ack = xilinx_intc_mask,
-	.irq_unmask = xilinx_intc_level_unmask,
-	.irq_set_type = xilinx_intc_set_type,
-};
-
-/*
- * IRQ Chip edge operations
- */
-static void xilinx_intc_edge_unmask(struct irq_data *d)
-{
-	int irq = irqd_to_hwirq(d);
-	void *regs = irq_data_get_irq_chip_data(d);
-	pr_debug("unmask: %d\n", irq);
-	out_be32(regs + XINTC_SIE, 1 << irq);
-}
-
-static void xilinx_intc_edge_ack(struct irq_data *d)
-{
-	int irq = irqd_to_hwirq(d);
-	void * regs = irq_data_get_irq_chip_data(d);
-	pr_debug("ack: %d\n", irq);
-	out_be32(regs + XINTC_IAR, 1 << irq);
-}
-
-static struct irq_chip xilinx_intc_edge_irqchip = {
-	.name = "Xilinx Edge  INTC",
-	.irq_mask = xilinx_intc_mask,
-	.irq_unmask = xilinx_intc_edge_unmask,
-	.irq_ack = xilinx_intc_edge_ack,
-	.irq_set_type = xilinx_intc_set_type,
-};
-
-/*
- * IRQ Host operations
- */
-
-/**
- * xilinx_intc_xlate - translate virq# from device tree interrupts property
- */
-static int xilinx_intc_xlate(struct irq_domain *h, struct device_node *ct,
-				const u32 *intspec, unsigned int intsize,
-				irq_hw_number_t *out_hwirq,
-				unsigned int *out_flags)
-{
-	if ((intsize < 2) || (intspec[0] >= XILINX_INTC_MAXIRQS))
-		return -EINVAL;
-
-	/* keep a copy of the interrupt type til the interrupt is mapped
-	 */
-	xilinx_intc_typetable[intspec[0]] = xilinx_intc_map_senses[intspec[1]];
-
-	/* Xilinx uses 2 interrupt entries, the 1st being the h/w
-	 * interrupt number, the 2nd being the interrupt type, edge or level
-	 */
-	*out_hwirq = intspec[0];
-	*out_flags = xilinx_intc_map_senses[intspec[1]];
-
-	return 0;
-}
-static int xilinx_intc_map(struct irq_domain *h, unsigned int virq,
-				  irq_hw_number_t irq)
-{
-	irq_set_chip_data(virq, h->host_data);
-
-	if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH ||
-	    xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) {
-		irq_set_chip_and_handler(virq, &xilinx_intc_level_irqchip,
-					 handle_level_irq);
-	} else {
-		irq_set_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
-					 handle_edge_irq);
-	}
-	return 0;
-}
-
-static const struct irq_domain_ops xilinx_intc_ops = {
-	.map = xilinx_intc_map,
-	.xlate = xilinx_intc_xlate,
-};
-
-struct irq_domain * __init
-xilinx_intc_init(struct device_node *np)
-{
-	struct irq_domain * irq;
-	void * regs;
-
-	/* Find and map the intc registers */
-	regs = of_iomap(np, 0);
-	if (!regs) {
-		pr_err("xilinx_intc: could not map registers\n");
-		return NULL;
-	}
-
-	/* Setup interrupt controller */
-	out_be32(regs + XINTC_IER, 0); /* disable all irqs */
-	out_be32(regs + XINTC_IAR, ~(u32) 0); /* Acknowledge pending irqs */
-	out_be32(regs + XINTC_MER, 0x3UL); /* Turn on the Master Enable. */
-
-	/* Allocate and initialize an irq_domain structure. */
-	irq = irq_domain_add_linear(np, XILINX_INTC_MAXIRQS, &xilinx_intc_ops,
-				    regs);
-	if (!irq)
-		panic(__FILE__ ": Cannot allocate IRQ host\n");
-
-	return irq;
-}
-
-int xilinx_intc_get_irq(void)
-{
-	void * regs = master_irqhost->host_data;
-	pr_debug("get_irq:\n");
-	return irq_linear_revmap(master_irqhost, in_be32(regs + XINTC_IVR));
-}
+#include <linux/irqchip.h>
 
 #if defined(CONFIG_PPC_I8259)
 /*
@@ -265,31 +78,11 @@ static void __init xilinx_i8259_setup_ca
 static inline void xilinx_i8259_setup_cascade(void) { return; }
 #endif /* defined(CONFIG_PPC_I8259) */
 
-static const struct of_device_id xilinx_intc_match[] __initconst = {
-	{ .compatible = "xlnx,opb-intc-1.00.c", },
-	{ .compatible = "xlnx,xps-intc-1.00.a", },
-	{}
-};
-
 /*
  * Initialize master Xilinx interrupt controller
  */
 void __init xilinx_intc_init_tree(void)
 {
-	struct device_node *np;
-
-	/* find top level interrupt controller */
-	for_each_matching_node(np, xilinx_intc_match) {
-		if (!of_get_property(np, "interrupts", NULL))
-			break;
-	}
-	BUG_ON(!np);
-
-	master_irqhost = xilinx_intc_init(np);
-	BUG_ON(!master_irqhost);
-
-	irq_set_default_host(master_irqhost);
-	of_node_put(np);
-
+	irqchip_init();
 	xilinx_i8259_setup_cascade();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/powerpc/xmon/xmon.c linux-libre-4.10-rc8-gnu/arch/powerpc/xmon/xmon.c
--- linux-libre-4.9-gnu/arch/powerpc/xmon/xmon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/powerpc/xmon/xmon.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,8 @@
  *      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/errno.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
@@ -225,6 +227,7 @@ Commands:\n\
 #endif
   "\
   dr	dump stream of raw bytes\n\
+  dt	dump the tracing buffers (uses printk)\n\
   e	print exception information\n\
   f	flush cache\n\
   la	lookup symbol+offset of specified address\n\
@@ -2364,6 +2367,9 @@ dump(void)
 		dump_log_buf();
 	} else if (c == 'o') {
 		dump_opal_msglog();
+	} else if (c == 't') {
+		ftrace_dump(DUMP_ALL);
+		tracing_on();
 	} else if (c == 'r') {
 		scanhex(&ndump);
 		if (ndump == 0)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/appldata/appldata_base.c linux-libre-4.10-rc8-gnu/arch/s390/appldata/appldata_base.c
--- linux-libre-4.9-gnu/arch/s390/appldata/appldata_base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/appldata/appldata_base.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/platform_device.h>
 #include <asm/appldata.h>
 #include <asm/vtimer.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/boot/compressed/head.S linux-libre-4.10-rc8-gnu/arch/s390/boot/compressed/head.S
--- linux-libre-4.9-gnu/arch/s390/boot/compressed/head.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/boot/compressed/head.S	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@ mover_end:
 
 	.align	8
 .Lstack:
-	.quad	0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
+	.quad	0x8000 + (1<<(PAGE_SHIFT+THREAD_SIZE_ORDER))
 .Loffset:
 	.quad	0x11000
 .Lmvsize:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/boot/compressed/Makefile linux-libre-4.10-rc8-gnu/arch/s390/boot/compressed/Makefile
--- linux-libre-4.9-gnu/arch/s390/boot/compressed/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/boot/compressed/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@ targets	:= vmlinux.lds vmlinux vmlinux.b
 targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4
 targets += misc.o piggy.o sizes.h head.o
 
-KBUILD_CFLAGS := -m64 -D__KERNEL__ $(LINUX_INCLUDE) -O2
+KBUILD_CFLAGS := -m64 -D__KERNEL__ -O2
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 KBUILD_CFLAGS += $(cflags-y) -fno-delete-null-pointer-checks -msoft-float
 KBUILD_CFLAGS += $(call cc-option,-mpacked-stack)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/boot/compressed/misc.c linux-libre-4.10-rc8-gnu/arch/s390/boot/compressed/misc.c
--- linux-libre-4.9-gnu/arch/s390/boot/compressed/misc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/boot/compressed/misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
  * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/sclp.h>
 #include <asm/ipl.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/configs/default_defconfig linux-libre-4.10-rc8-gnu/arch/s390/configs/default_defconfig
--- linux-libre-4.9-gnu/arch/s390/configs/default_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/configs/default_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -66,8 +66,10 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
 CONFIG_CMA=y
+CONFIG_CMA_DEBUG=y
+CONFIG_CMA_DEBUGFS=y
 CONFIG_MEM_SOFT_DIRTY=y
-CONFIG_ZPOOL=m
+CONFIG_ZSWAP=y
 CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
 CONFIG_ZSMALLOC_STAT=y
@@ -139,8 +141,6 @@ CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
@@ -157,13 +157,12 @@ CONFIG_NF_TABLES=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
-CONFIG_NFT_RBTREE=m
-CONFIG_NFT_HASH=m
 CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -217,7 +216,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -256,7 +254,6 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
 CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -366,6 +363,8 @@ CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
 CONFIG_NET_TCPPROBE=m
 CONFIG_DEVTMPFS=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
@@ -432,13 +431,11 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
-CONFIG_VHOST_NET=m
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -477,6 +474,7 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
 CONFIG_JBD2_DEBUG=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
@@ -589,14 +587,12 @@ CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_LOCKDEP=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
-CONFIG_DEBUG_LIST=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
 CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
 CONFIG_NOTIFIER_ERROR_INJECTION=m
-CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
 CONFIG_PM_NOTIFIER_ERROR_INJECT=m
 CONFIG_FAULT_INJECTION=y
 CONFIG_FAILSLAB=y
@@ -615,6 +611,7 @@ CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
 CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
@@ -627,6 +624,7 @@ CONFIG_TEST_STRING_HELPERS=y
 CONFIG_TEST_KSTRTOX=y
 CONFIG_DMA_API_DEBUG=y
 CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_S390_PTDUMP=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
@@ -637,16 +635,18 @@ CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=
 CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_IMA=y
 CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_RSA=m
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
-# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
 CONFIG_CRYPTO_CRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -670,11 +670,13 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_ZCRYPT=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
@@ -693,3 +695,4 @@ CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
 CONFIG_KVM_S390_UCONTROL=y
+CONFIG_VHOST_NET=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/configs/gcov_defconfig linux-libre-4.10-rc8-gnu/arch/s390/configs/gcov_defconfig
--- linux-libre-4.9-gnu/arch/s390/configs/gcov_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/configs/gcov_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@ CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_NUMA_BALANCING=y
+# CONFIG_NUMA_BALANCING_DEFAULT_ENABLED is not set
 CONFIG_MEMCG=y
 CONFIG_MEMCG_SWAP=y
 CONFIG_BLK_CGROUP=y
@@ -54,8 +55,9 @@ CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_UNIXWARE_DISKLABEL=y
 CONFIG_CFQ_GROUP_IOSCHED=y
 CONFIG_DEFAULT_DEADLINE=y
+CONFIG_LIVEPATCH=y
 CONFIG_TUNE_ZEC12=y
-CONFIG_NR_CPUS=256
+CONFIG_NR_CPUS=512
 CONFIG_NUMA=y
 CONFIG_HZ_100=y
 CONFIG_MEMORY_HOTPLUG=y
@@ -65,6 +67,7 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
 CONFIG_CMA=y
+CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
 CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
@@ -136,8 +139,6 @@ CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
@@ -154,13 +155,12 @@ CONFIG_NF_TABLES=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
-CONFIG_NFT_RBTREE=m
-CONFIG_NFT_HASH=m
 CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -214,7 +214,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -253,7 +252,6 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
 CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -362,6 +360,8 @@ CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
 CONFIG_NET_TCPPROBE=m
 CONFIG_DEVTMPFS=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
@@ -428,13 +428,11 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
-CONFIG_VHOST_NET=m
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -459,6 +457,7 @@ CONFIG_HW_RANDOM_VIRTIO=m
 CONFIG_RAW_DRIVER=m
 CONFIG_HANGCHECK_TIMER=m
 CONFIG_TN3270_FS=y
+# CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG_NOWAYOUT=y
 CONFIG_SOFT_WATCHDOG=m
@@ -472,6 +471,7 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
 CONFIG_JBD2_DEBUG=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
@@ -494,6 +494,7 @@ CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=m
 CONFIG_OVERLAY_FS=m
+CONFIG_OVERLAY_FS_REDIRECT_DIR=y
 CONFIG_FSCACHE=m
 CONFIG_CACHEFILES=m
 CONFIG_ISO9660_FS=y
@@ -550,25 +551,27 @@ CONFIG_FRAME_WARN=1024
 CONFIG_UNUSED_SYMBOLS=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
-CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_PANIC_ON_OOPS=y
 CONFIG_TIMER_STATS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
-CONFIG_NOTIFIER_ERROR_INJECTION=m
-CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
-CONFIG_PM_NOTIFIER_ERROR_INJECT=m
 CONFIG_LATENCYTOP=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-# CONFIG_KPROBE_EVENT is not set
+CONFIG_UPROBE_EVENT=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
-CONFIG_RBTREE_TEST=m
-CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_S390_PTDUMP=y
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
@@ -576,18 +579,25 @@ CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
 CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
 CONFIG_IMA=y
+CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_PCRYPT=m
 CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -597,6 +607,7 @@ CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -611,10 +622,13 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_ZCRYPT=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
@@ -623,9 +637,6 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
-CONFIG_ASYMMETRIC_KEY_TYPE=y
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
-CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
 CONFIG_CORDIC=m
@@ -633,3 +644,4 @@ CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
 CONFIG_KVM_S390_UCONTROL=y
+CONFIG_VHOST_NET=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/configs/performance_defconfig linux-libre-4.10-rc8-gnu/arch/s390/configs/performance_defconfig
--- linux-libre-4.9-gnu/arch/s390/configs/performance_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/configs/performance_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,7 @@ CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CLEANCACHE=y
 CONFIG_FRONTSWAP=y
 CONFIG_CMA=y
+CONFIG_MEM_SOFT_DIRTY=y
 CONFIG_ZSWAP=y
 CONFIG_ZBUD=m
 CONFIG_ZSMALLOC=m
@@ -136,8 +137,6 @@ CONFIG_NF_CONNTRACK_SECMARK=y
 CONFIG_NF_CONNTRACK_EVENTS=y
 CONFIG_NF_CONNTRACK_TIMEOUT=y
 CONFIG_NF_CONNTRACK_TIMESTAMP=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
 CONFIG_NF_CONNTRACK_AMANDA=m
 CONFIG_NF_CONNTRACK_FTP=m
 CONFIG_NF_CONNTRACK_H323=m
@@ -154,13 +153,12 @@ CONFIG_NF_TABLES=m
 CONFIG_NFT_EXTHDR=m
 CONFIG_NFT_META=m
 CONFIG_NFT_CT=m
-CONFIG_NFT_RBTREE=m
-CONFIG_NFT_HASH=m
 CONFIG_NFT_COUNTER=m
 CONFIG_NFT_LOG=m
 CONFIG_NFT_LIMIT=m
 CONFIG_NFT_NAT=m
 CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -214,7 +212,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m
 CONFIG_NETFILTER_XT_MATCH_RATEEST=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_RECENT=m
-CONFIG_NETFILTER_XT_MATCH_SOCKET=m
 CONFIG_NETFILTER_XT_MATCH_STATE=m
 CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
 CONFIG_NETFILTER_XT_MATCH_STRING=m
@@ -253,7 +250,6 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set
 CONFIG_NF_TABLES_IPV4=m
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
 CONFIG_NF_TABLES_ARP=m
@@ -362,6 +358,8 @@ CONFIG_BPF_JIT=y
 CONFIG_NET_PKTGEN=m
 CONFIG_NET_TCPPROBE=m
 CONFIG_DEVTMPFS=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=0
 CONFIG_CONNECTOR=y
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_CRYPTOLOOP=m
@@ -428,13 +426,11 @@ CONFIG_EQUALIZER=m
 CONFIG_IFB=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
-CONFIG_IPVLAN=m
 CONFIG_VXLAN=m
 CONFIG_TUN=m
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=m
 CONFIG_NLMON=m
-CONFIG_VHOST_NET=m
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_VENDOR_CHELSIO is not set
 # CONFIG_NET_VENDOR_INTEL is not set
@@ -473,6 +469,7 @@ CONFIG_VIRTIO_BALLOON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
 CONFIG_JBD2_DEBUG=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
@@ -495,6 +492,7 @@ CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=m
 CONFIG_OVERLAY_FS=m
+CONFIG_OVERLAY_FS_REDIRECT_DIR=y
 CONFIG_FSCACHE=m
 CONFIG_CACHEFILES=m
 CONFIG_ISO9660_FS=y
@@ -562,12 +560,16 @@ CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_UPROBE_EVENT=y
 CONFIG_FUNCTION_PROFILER=y
+CONFIG_HIST_TRIGGERS=y
 CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_S390_PTDUMP=y
+CONFIG_PERSISTENT_KEYRINGS=y
+CONFIG_BIG_KEYS=y
 CONFIG_ENCRYPTED_KEYS=m
 CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
@@ -575,18 +577,25 @@ CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0
 CONFIG_SECURITY_SELINUX_DISABLE=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
 CONFIG_IMA=y
+CONFIG_IMA_WRITE_POLICY=y
 CONFIG_IMA_APPRAISE=y
+CONFIG_CRYPTO_DH=m
+CONFIG_CRYPTO_ECDH=m
 CONFIG_CRYPTO_USER=m
 # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_PCRYPT=m
 CONFIG_CRYPTO_CRYPTD=m
+CONFIG_CRYPTO_MCRYPTD=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
-CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
 CONFIG_CRYPTO_LRW=m
 CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_KEYWRAP=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
@@ -596,6 +605,7 @@ CONFIG_CRYPTO_RMD160=m
 CONFIG_CRYPTO_RMD256=m
 CONFIG_CRYPTO_RMD320=m
 CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
@@ -610,10 +620,13 @@ CONFIG_CRYPTO_SEED=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_842=m
 CONFIG_CRYPTO_LZ4=m
 CONFIG_CRYPTO_LZ4HC=m
 CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_SKCIPHER=m
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
 CONFIG_ZCRYPT=m
 CONFIG_CRYPTO_SHA1_S390=m
 CONFIG_CRYPTO_SHA256_S390=m
@@ -622,9 +635,6 @@ CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_CRC32_S390=y
-CONFIG_ASYMMETRIC_KEY_TYPE=y
-CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m
-CONFIG_X509_CERTIFICATE_PARSER=m
 CONFIG_CRC7=m
 CONFIG_CRC8=m
 CONFIG_CORDIC=m
@@ -632,3 +642,4 @@ CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
 CONFIG_KVM_S390_UCONTROL=y
+CONFIG_VHOST_NET=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/crypto/prng.c linux-libre-4.10-rc8-gnu/arch/s390/crypto/prng.c
--- linux-libre-4.9-gnu/arch/s390/crypto/prng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/crypto/prng.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/random.h>
 #include <linux/slab.h>
 #include <asm/debug.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/timex.h>
 #include <asm/cpacf.h>
 
@@ -507,8 +507,10 @@ static ssize_t prng_tdes_read(struct fil
 		prng_data->prngws.byte_counter += n;
 		prng_data->prngws.reseed_counter += n;
 
-		if (copy_to_user(ubuf, prng_data->buf, chunk))
-			return -EFAULT;
+		if (copy_to_user(ubuf, prng_data->buf, chunk)) {
+			ret = -EFAULT;
+			break;
+		}
 
 		nbytes -= chunk;
 		ret += chunk;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/defconfig linux-libre-4.10-rc8-gnu/arch/s390/defconfig
--- linux-libre-4.9-gnu/arch/s390/defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,6 @@ CONFIG_JUMP_LABEL=y
 CONFIG_STATIC_KEYS_SELFTEST=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
 CONFIG_BLK_DEV_INTEGRITY=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
@@ -130,8 +129,11 @@ CONFIG_DUMMY=m
 CONFIG_EQUALIZER=m
 CONFIG_TUN=m
 CONFIG_VIRTIO_NET=y
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
+CONFIG_DEVKMEM=y
 CONFIG_RAW_DRIVER=m
 CONFIG_VIRTIO_BALLOON=y
 CONFIG_EXT4_FS=y
@@ -183,7 +185,6 @@ CONFIG_TRACE_ENUM_MAP_FILE=y
 CONFIG_KPROBES_SANITY_TEST=y
 CONFIG_S390_PTDUMP=y
 CONFIG_CRYPTO_CRYPTD=m
-CONFIG_CRYPTO_AUTHENC=m
 CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_GCM=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/hypfs/inode.c linux-libre-4.10-rc8-gnu/arch/s390/hypfs/inode.c
--- linux-libre-4.9-gnu/arch/s390/hypfs/inode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/hypfs/inode.c	2017-02-12 16:03:20.000000000 -0500
@@ -3,6 +3,7 @@
  *
  *    Copyright IBM Corp. 2006, 2008
  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ *    License: GPL
  */
 
 #define KMSG_COMPONENT "hypfs"
@@ -18,7 +19,8 @@
 #include <linux/time.h>
 #include <linux/parser.h>
 #include <linux/sysfs.h>
-#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
 #include <linux/seq_file.h>
 #include <linux/mount.h>
 #include <linux/uio.h>
@@ -443,7 +445,6 @@ static struct file_system_type hypfs_typ
 	.mount		= hypfs_mount,
 	.kill_sb	= hypfs_kill_super
 };
-MODULE_ALIAS_FS("s390_hypfs");
 
 static const struct super_operations hypfs_s_ops = {
 	.statfs		= simple_statfs,
@@ -497,21 +498,4 @@ fail_dbfs_exit:
 	pr_err("Initialization of hypfs failed with rc=%i\n", rc);
 	return rc;
 }
-
-static void __exit hypfs_exit(void)
-{
-	unregister_filesystem(&hypfs_type);
-	sysfs_remove_mount_point(hypervisor_kobj, "s390");
-	hypfs_diag0c_exit();
-	hypfs_sprp_exit();
-	hypfs_vm_exit();
-	hypfs_diag_exit();
-	hypfs_dbfs_exit();
-}
-
-module_init(hypfs_init)
-module_exit(hypfs_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Michael Holzheu <holzheu@de.ibm.com>");
-MODULE_DESCRIPTION("s390 Hypervisor Filesystem");
+device_initcall(hypfs_init)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/asm-offsets.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/asm-offsets.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/asm-offsets.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/asm-offsets.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-#include <generated/asm-offsets.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/asm-prototypes.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/asm-prototypes.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/asm-prototypes.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/asm-prototypes.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+#ifndef _ASM_S390_PROTOTYPES_H
+
+#include <linux/kvm_host.h>
+#include <linux/ftrace.h>
+#include <asm/fpu/api.h>
+#include <asm-generic/asm-prototypes.h>
+
+#endif /* _ASM_S390_PROTOTYPES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/atomic.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/atomic.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/atomic.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/atomic.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,13 +1,8 @@
 /*
- * Copyright IBM Corp. 1999, 2009
+ * Copyright IBM Corp. 1999, 2016
  * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *	      Denis Joseph Barrow,
- *	      Arnd Bergmann <arndb@de.ibm.com>,
- *
- * Atomic operations that C can't guarantee us.
- * Useful for resource counting etc.
- * s390 uses 'Compare And Swap' for atomicity in SMP environment.
- *
+ *	      Arnd Bergmann,
  */
 
 #ifndef __ARCH_S390_ATOMIC__
@@ -15,62 +10,12 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <asm/atomic_ops.h>
 #include <asm/barrier.h>
 #include <asm/cmpxchg.h>
 
 #define ATOMIC_INIT(i)  { (i) }
 
-#define __ATOMIC_NO_BARRIER	"\n"
-
-#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
-
-#define __ATOMIC_OR	"lao"
-#define __ATOMIC_AND	"lan"
-#define __ATOMIC_ADD	"laa"
-#define __ATOMIC_XOR	"lax"
-#define __ATOMIC_BARRIER "bcr	14,0\n"
-
-#define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier)		\
-({									\
-	int old_val;							\
-									\
-	typecheck(atomic_t *, ptr);					\
-	asm volatile(							\
-		op_string "	%0,%2,%1\n"				\
-		__barrier						\
-		: "=d" (old_val), "+Q" ((ptr)->counter)			\
-		: "d" (op_val)						\
-		: "cc", "memory");					\
-	old_val;							\
-})
-
-#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
-
-#define __ATOMIC_OR	"or"
-#define __ATOMIC_AND	"nr"
-#define __ATOMIC_ADD	"ar"
-#define __ATOMIC_XOR	"xr"
-#define __ATOMIC_BARRIER "\n"
-
-#define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier)		\
-({									\
-	int old_val, new_val;						\
-									\
-	typecheck(atomic_t *, ptr);					\
-	asm volatile(							\
-		"	l	%0,%2\n"				\
-		"0:	lr	%1,%0\n"				\
-		op_string "	%1,%3\n"				\
-		"	cs	%0,%1,%2\n"				\
-		"	jl	0b"					\
-		: "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\
-		: "d" (op_val)						\
-		: "cc", "memory");					\
-	old_val;							\
-})
-
-#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
-
 static inline int atomic_read(const atomic_t *v)
 {
 	int c;
@@ -90,27 +35,23 @@ static inline void atomic_set(atomic_t *
 
 static inline int atomic_add_return(int i, atomic_t *v)
 {
-	return __ATOMIC_LOOP(v, i, __ATOMIC_ADD, __ATOMIC_BARRIER) + i;
+	return __atomic_add_barrier(i, &v->counter) + i;
 }
 
 static inline int atomic_fetch_add(int i, atomic_t *v)
 {
-	return __ATOMIC_LOOP(v, i, __ATOMIC_ADD, __ATOMIC_BARRIER);
+	return __atomic_add_barrier(i, &v->counter);
 }
 
 static inline void atomic_add(int i, atomic_t *v)
 {
 #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
 	if (__builtin_constant_p(i) && (i > -129) && (i < 128)) {
-		asm volatile(
-			"asi	%0,%1\n"
-			: "+Q" (v->counter)
-			: "i" (i)
-			: "cc", "memory");
+		__atomic_add_const(i, &v->counter);
 		return;
 	}
 #endif
-	__ATOMIC_LOOP(v, i, __ATOMIC_ADD, __ATOMIC_NO_BARRIER);
+	__atomic_add(i, &v->counter);
 }
 
 #define atomic_add_negative(_i, _v)	(atomic_add_return(_i, _v) < 0)
@@ -125,19 +66,19 @@ static inline void atomic_add(int i, ato
 #define atomic_dec_return(_v)		atomic_sub_return(1, _v)
 #define atomic_dec_and_test(_v)		(atomic_sub_return(1, _v) == 0)
 
-#define ATOMIC_OPS(op, OP)						\
+#define ATOMIC_OPS(op)							\
 static inline void atomic_##op(int i, atomic_t *v)			\
 {									\
-	__ATOMIC_LOOP(v, i, __ATOMIC_##OP, __ATOMIC_NO_BARRIER);	\
+	__atomic_##op(i, &v->counter);					\
 }									\
 static inline int atomic_fetch_##op(int i, atomic_t *v)			\
 {									\
-	return __ATOMIC_LOOP(v, i, __ATOMIC_##OP, __ATOMIC_BARRIER);	\
+	return __atomic_##op##_barrier(i, &v->counter);			\
 }
 
-ATOMIC_OPS(and, AND)
-ATOMIC_OPS(or, OR)
-ATOMIC_OPS(xor, XOR)
+ATOMIC_OPS(and)
+ATOMIC_OPS(or)
+ATOMIC_OPS(xor)
 
 #undef ATOMIC_OPS
 
@@ -145,12 +86,7 @@ ATOMIC_OPS(xor, XOR)
 
 static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
 {
-	asm volatile(
-		"	cs	%0,%2,%1"
-		: "+d" (old), "+Q" (v->counter)
-		: "d" (new)
-		: "cc", "memory");
-	return old;
+	return __atomic_cmpxchg(&v->counter, old, new);
 }
 
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
@@ -168,65 +104,11 @@ static inline int __atomic_add_unless(at
 	return c;
 }
 
-
-#undef __ATOMIC_LOOP
-
 #define ATOMIC64_INIT(i)  { (i) }
 
-#define __ATOMIC64_NO_BARRIER	"\n"
-
-#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
-
-#define __ATOMIC64_OR	"laog"
-#define __ATOMIC64_AND	"lang"
-#define __ATOMIC64_ADD	"laag"
-#define __ATOMIC64_XOR	"laxg"
-#define __ATOMIC64_BARRIER "bcr	14,0\n"
-
-#define __ATOMIC64_LOOP(ptr, op_val, op_string, __barrier)		\
-({									\
-	long long old_val;						\
-									\
-	typecheck(atomic64_t *, ptr);					\
-	asm volatile(							\
-		op_string "	%0,%2,%1\n"				\
-		__barrier						\
-		: "=d" (old_val), "+Q" ((ptr)->counter)			\
-		: "d" (op_val)						\
-		: "cc", "memory");					\
-	old_val;							\
-})
-
-#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
-
-#define __ATOMIC64_OR	"ogr"
-#define __ATOMIC64_AND	"ngr"
-#define __ATOMIC64_ADD	"agr"
-#define __ATOMIC64_XOR	"xgr"
-#define __ATOMIC64_BARRIER "\n"
-
-#define __ATOMIC64_LOOP(ptr, op_val, op_string, __barrier)		\
-({									\
-	long long old_val, new_val;					\
-									\
-	typecheck(atomic64_t *, ptr);					\
-	asm volatile(							\
-		"	lg	%0,%2\n"				\
-		"0:	lgr	%1,%0\n"				\
-		op_string "	%1,%3\n"				\
-		"	csg	%0,%1,%2\n"				\
-		"	jl	0b"					\
-		: "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\
-		: "d" (op_val)						\
-		: "cc", "memory");					\
-	old_val;							\
-})
-
-#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
-
-static inline long long atomic64_read(const atomic64_t *v)
+static inline long atomic64_read(const atomic64_t *v)
 {
-	long long c;
+	long c;
 
 	asm volatile(
 		"	lg	%0,%1\n"
@@ -234,71 +116,60 @@ static inline long long atomic64_read(co
 	return c;
 }
 
-static inline void atomic64_set(atomic64_t *v, long long i)
+static inline void atomic64_set(atomic64_t *v, long i)
 {
 	asm volatile(
 		"	stg	%1,%0\n"
 		: "=Q" (v->counter) : "d" (i));
 }
 
-static inline long long atomic64_add_return(long long i, atomic64_t *v)
+static inline long atomic64_add_return(long i, atomic64_t *v)
 {
-	return __ATOMIC64_LOOP(v, i, __ATOMIC64_ADD, __ATOMIC64_BARRIER) + i;
+	return __atomic64_add_barrier(i, &v->counter) + i;
 }
 
-static inline long long atomic64_fetch_add(long long i, atomic64_t *v)
+static inline long atomic64_fetch_add(long i, atomic64_t *v)
 {
-	return __ATOMIC64_LOOP(v, i, __ATOMIC64_ADD, __ATOMIC64_BARRIER);
+	return __atomic64_add_barrier(i, &v->counter);
 }
 
-static inline void atomic64_add(long long i, atomic64_t *v)
+static inline void atomic64_add(long i, atomic64_t *v)
 {
 #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
 	if (__builtin_constant_p(i) && (i > -129) && (i < 128)) {
-		asm volatile(
-			"agsi	%0,%1\n"
-			: "+Q" (v->counter)
-			: "i" (i)
-			: "cc", "memory");
+		__atomic64_add_const(i, &v->counter);
 		return;
 	}
 #endif
-	__ATOMIC64_LOOP(v, i, __ATOMIC64_ADD, __ATOMIC64_NO_BARRIER);
+	__atomic64_add(i, &v->counter);
 }
 
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 
-static inline long long atomic64_cmpxchg(atomic64_t *v,
-					     long long old, long long new)
+static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
 {
-	asm volatile(
-		"	csg	%0,%2,%1"
-		: "+d" (old), "+Q" (v->counter)
-		: "d" (new)
-		: "cc", "memory");
-	return old;
+	return __atomic64_cmpxchg(&v->counter, old, new);
 }
 
-#define ATOMIC64_OPS(op, OP)						\
+#define ATOMIC64_OPS(op)						\
 static inline void atomic64_##op(long i, atomic64_t *v)			\
 {									\
-	__ATOMIC64_LOOP(v, i, __ATOMIC64_##OP, __ATOMIC64_NO_BARRIER);	\
+	__atomic64_##op(i, &v->counter);				\
 }									\
 static inline long atomic64_fetch_##op(long i, atomic64_t *v)		\
 {									\
-	return __ATOMIC64_LOOP(v, i, __ATOMIC64_##OP, __ATOMIC64_BARRIER); \
+	return __atomic64_##op##_barrier(i, &v->counter);		\
 }
 
-ATOMIC64_OPS(and, AND)
-ATOMIC64_OPS(or, OR)
-ATOMIC64_OPS(xor, XOR)
+ATOMIC64_OPS(and)
+ATOMIC64_OPS(or)
+ATOMIC64_OPS(xor)
 
 #undef ATOMIC64_OPS
-#undef __ATOMIC64_LOOP
 
-static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)
+static inline int atomic64_add_unless(atomic64_t *v, long i, long u)
 {
-	long long c, old;
+	long c, old;
 
 	c = atomic64_read(v);
 	for (;;) {
@@ -312,9 +183,9 @@ static inline int atomic64_add_unless(at
 	return c != u;
 }
 
-static inline long long atomic64_dec_if_positive(atomic64_t *v)
+static inline long atomic64_dec_if_positive(atomic64_t *v)
 {
-	long long c, old, dec;
+	long c, old, dec;
 
 	c = atomic64_read(v);
 	for (;;) {
@@ -333,9 +204,9 @@ static inline long long atomic64_dec_if_
 #define atomic64_inc(_v)		atomic64_add(1, _v)
 #define atomic64_inc_return(_v)		atomic64_add_return(1, _v)
 #define atomic64_inc_and_test(_v)	(atomic64_add_return(1, _v) == 0)
-#define atomic64_sub_return(_i, _v)	atomic64_add_return(-(long long)(_i), _v)
-#define atomic64_fetch_sub(_i, _v)	atomic64_fetch_add(-(long long)(_i), _v)
-#define atomic64_sub(_i, _v)		atomic64_add(-(long long)(_i), _v)
+#define atomic64_sub_return(_i, _v)	atomic64_add_return(-(long)(_i), _v)
+#define atomic64_fetch_sub(_i, _v)	atomic64_fetch_add(-(long)(_i), _v)
+#define atomic64_sub(_i, _v)		atomic64_add(-(long)(_i), _v)
 #define atomic64_sub_and_test(_i, _v)	(atomic64_sub_return(_i, _v) == 0)
 #define atomic64_dec(_v)		atomic64_sub(1, _v)
 #define atomic64_dec_return(_v)		atomic64_sub_return(1, _v)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/atomic_ops.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/atomic_ops.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/atomic_ops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/atomic_ops.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,130 @@
+/*
+ * Low level function for atomic operations
+ *
+ * Copyright IBM Corp. 1999, 2016
+ */
+
+#ifndef __ARCH_S390_ATOMIC_OPS__
+#define __ARCH_S390_ATOMIC_OPS__
+
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define __ATOMIC_OP(op_name, op_type, op_string, op_barrier)		\
+static inline op_type op_name(op_type val, op_type *ptr)		\
+{									\
+	op_type old;							\
+									\
+	asm volatile(							\
+		op_string "	%[old],%[val],%[ptr]\n"			\
+		op_barrier						\
+		: [old] "=d" (old), [ptr] "+Q" (*ptr)			\
+		: [val] "d" (val) : "cc", "memory");			\
+	return old;							\
+}									\
+
+#define __ATOMIC_OPS(op_name, op_type, op_string)			\
+	__ATOMIC_OP(op_name, op_type, op_string, "\n")			\
+	__ATOMIC_OP(op_name##_barrier, op_type, op_string, "bcr 14,0\n")
+
+__ATOMIC_OPS(__atomic_add, int, "laa")
+__ATOMIC_OPS(__atomic_and, int, "lan")
+__ATOMIC_OPS(__atomic_or,  int, "lao")
+__ATOMIC_OPS(__atomic_xor, int, "lax")
+
+__ATOMIC_OPS(__atomic64_add, long, "laag")
+__ATOMIC_OPS(__atomic64_and, long, "lang")
+__ATOMIC_OPS(__atomic64_or,  long, "laog")
+__ATOMIC_OPS(__atomic64_xor, long, "laxg")
+
+#undef __ATOMIC_OPS
+#undef __ATOMIC_OP
+
+static inline void __atomic_add_const(int val, int *ptr)
+{
+	asm volatile(
+		"	asi	%[ptr],%[val]\n"
+		: [ptr] "+Q" (*ptr) : [val] "i" (val) : "cc");
+}
+
+static inline void __atomic64_add_const(long val, long *ptr)
+{
+	asm volatile(
+		"	agsi	%[ptr],%[val]\n"
+		: [ptr] "+Q" (*ptr) : [val] "i" (val) : "cc");
+}
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+#define __ATOMIC_OP(op_name, op_string)					\
+static inline int op_name(int val, int *ptr)				\
+{									\
+	int old, new;							\
+									\
+	asm volatile(							\
+		"0:	lr	%[new],%[old]\n"			\
+		op_string "	%[new],%[val]\n"			\
+		"	cs	%[old],%[new],%[ptr]\n"			\
+		"	jl	0b"					\
+		: [old] "=d" (old), [new] "=&d" (new), [ptr] "+Q" (*ptr)\
+		: [val] "d" (val), "0" (*ptr) : "cc", "memory");	\
+	return old;							\
+}
+
+#define __ATOMIC_OPS(op_name, op_string)				\
+	__ATOMIC_OP(op_name, op_string)					\
+	__ATOMIC_OP(op_name##_barrier, op_string)
+
+__ATOMIC_OPS(__atomic_add, "ar")
+__ATOMIC_OPS(__atomic_and, "nr")
+__ATOMIC_OPS(__atomic_or,  "or")
+__ATOMIC_OPS(__atomic_xor, "xr")
+
+#undef __ATOMIC_OPS
+
+#define __ATOMIC64_OP(op_name, op_string)				\
+static inline long op_name(long val, long *ptr)				\
+{									\
+	long old, new;							\
+									\
+	asm volatile(							\
+		"0:	lgr	%[new],%[old]\n"			\
+		op_string "	%[new],%[val]\n"			\
+		"	csg	%[old],%[new],%[ptr]\n"			\
+		"	jl	0b"					\
+		: [old] "=d" (old), [new] "=&d" (new), [ptr] "+Q" (*ptr)\
+		: [val] "d" (val), "0" (*ptr) : "cc", "memory");	\
+	return old;							\
+}
+
+#define __ATOMIC64_OPS(op_name, op_string)				\
+	__ATOMIC64_OP(op_name, op_string)				\
+	__ATOMIC64_OP(op_name##_barrier, op_string)
+
+__ATOMIC64_OPS(__atomic64_add, "agr")
+__ATOMIC64_OPS(__atomic64_and, "ngr")
+__ATOMIC64_OPS(__atomic64_or,  "ogr")
+__ATOMIC64_OPS(__atomic64_xor, "xgr")
+
+#undef __ATOMIC64_OPS
+
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+static inline int __atomic_cmpxchg(int *ptr, int old, int new)
+{
+	asm volatile(
+		"	cs	%[old],%[new],%[ptr]"
+		: [old] "+d" (old), [ptr] "+Q" (*ptr)
+		: [new] "d" (new) : "cc", "memory");
+	return old;
+}
+
+static inline long __atomic64_cmpxchg(long *ptr, long old, long new)
+{
+	asm volatile(
+		"	csg	%[old],%[new],%[ptr]"
+		: [old] "+d" (old), [ptr] "+Q" (*ptr)
+		: [new] "d" (new) : "cc", "memory");
+	return old;
+}
+
+#endif /* __ARCH_S390_ATOMIC_OPS__  */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/bitops.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/bitops.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/bitops.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/bitops.h	2017-02-12 16:03:20.000000000 -0500
@@ -42,57 +42,9 @@
 
 #include <linux/typecheck.h>
 #include <linux/compiler.h>
+#include <asm/atomic_ops.h>
 #include <asm/barrier.h>
 
-#define __BITOPS_NO_BARRIER	"\n"
-
-#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
-
-#define __BITOPS_OR		"laog"
-#define __BITOPS_AND		"lang"
-#define __BITOPS_XOR		"laxg"
-#define __BITOPS_BARRIER	"bcr	14,0\n"
-
-#define __BITOPS_LOOP(__addr, __val, __op_string, __barrier)	\
-({								\
-	unsigned long __old;					\
-								\
-	typecheck(unsigned long *, (__addr));			\
-	asm volatile(						\
-		__op_string "	%0,%2,%1\n"			\
-		__barrier					\
-		: "=d" (__old),	"+Q" (*(__addr))		\
-		: "d" (__val)					\
-		: "cc", "memory");				\
-	__old;							\
-})
-
-#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
-
-#define __BITOPS_OR		"ogr"
-#define __BITOPS_AND		"ngr"
-#define __BITOPS_XOR		"xgr"
-#define __BITOPS_BARRIER	"\n"
-
-#define __BITOPS_LOOP(__addr, __val, __op_string, __barrier)	\
-({								\
-	unsigned long __old, __new;				\
-								\
-	typecheck(unsigned long *, (__addr));			\
-	asm volatile(						\
-		"	lg	%0,%2\n"			\
-		"0:	lgr	%1,%0\n"			\
-		__op_string "	%1,%3\n"			\
-		"	csg	%0,%1,%2\n"			\
-		"	jl	0b"				\
-		: "=&d" (__old), "=&d" (__new), "+Q" (*(__addr))\
-		: "d" (__val)					\
-		: "cc", "memory");				\
-	__old;							\
-})
-
-#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
-
 #define __BITOPS_WORDS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
 
 static inline unsigned long *
@@ -128,7 +80,7 @@ static inline void set_bit(unsigned long
 	}
 #endif
 	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	__BITOPS_LOOP(addr, mask, __BITOPS_OR, __BITOPS_NO_BARRIER);
+	__atomic64_or(mask, addr);
 }
 
 static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)
@@ -149,7 +101,7 @@ static inline void clear_bit(unsigned lo
 	}
 #endif
 	mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
-	__BITOPS_LOOP(addr, mask, __BITOPS_AND, __BITOPS_NO_BARRIER);
+	__atomic64_and(mask, addr);
 }
 
 static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)
@@ -170,7 +122,7 @@ static inline void change_bit(unsigned l
 	}
 #endif
 	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	__BITOPS_LOOP(addr, mask, __BITOPS_XOR, __BITOPS_NO_BARRIER);
+	__atomic64_xor(mask, addr);
 }
 
 static inline int
@@ -180,7 +132,7 @@ test_and_set_bit(unsigned long nr, volat
 	unsigned long old, mask;
 
 	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	old = __BITOPS_LOOP(addr, mask, __BITOPS_OR, __BITOPS_BARRIER);
+	old = __atomic64_or_barrier(mask, addr);
 	return (old & mask) != 0;
 }
 
@@ -191,7 +143,7 @@ test_and_clear_bit(unsigned long nr, vol
 	unsigned long old, mask;
 
 	mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
-	old = __BITOPS_LOOP(addr, mask, __BITOPS_AND, __BITOPS_BARRIER);
+	old = __atomic64_and_barrier(mask, addr);
 	return (old & ~mask) != 0;
 }
 
@@ -202,7 +154,7 @@ test_and_change_bit(unsigned long nr, vo
 	unsigned long old, mask;
 
 	mask = 1UL << (nr & (BITS_PER_LONG - 1));
-	old = __BITOPS_LOOP(addr, mask, __BITOPS_XOR, __BITOPS_BARRIER);
+	old = __atomic64_xor_barrier(mask, addr);
 	return (old & mask) != 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/checksum.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/checksum.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/checksum.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/checksum.h	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #ifndef _S390_CHECKSUM_H
 #define _S390_CHECKSUM_H
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * computes the checksum of a memory block at buff, length len,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/cpu_mf.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/cpu_mf.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/cpu_mf.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/cpu_mf.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,8 @@ struct hws_basic_entry {
 	unsigned int P:1;	    /* 28 PSW Problem state		 */
 	unsigned int AS:2;	    /* 29-30 PSW address-space control	 */
 	unsigned int I:1;	    /* 31 entry valid or invalid	 */
-	unsigned int:16;
+	unsigned int CL:2;	    /* 32-33 Configuration Level	 */
+	unsigned int:14;
 	unsigned int prim_asn:16;   /* primary ASN			 */
 	unsigned long long ia;	    /* Instruction Address		 */
 	unsigned long long gpp;     /* Guest Program Parameter		 */
@@ -212,18 +213,14 @@ static inline int stcctm5(u64 num, u64 *
 /* Query sampling information */
 static inline int qsi(struct hws_qsi_info_block *info)
 {
-	int cc;
-	cc = 1;
+	int cc = 1;
 
 	asm volatile(
-		"0:	.insn	s,0xb2860000,0(%1)\n"
+		"0:	.insn	s,0xb2860000,%1\n"
 		"1:	lhi	%0,0\n"
 		"2:\n"
 		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
-		: "=d" (cc), "+a" (info)
-		: "m" (*info)
-		: "cc", "memory");
-
+		: "+d" (cc), "+Q" (*info));
 	return cc ? -EINVAL : 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/ctl_reg.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/ctl_reg.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/ctl_reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/ctl_reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,9 @@
 	BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
 	asm volatile(							\
 		"	lctlg	%1,%2,%0\n"				\
-		: : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\
+		:							\
+		: "Q" (*(addrtype *)(&array)), "i" (low), "i" (high)	\
+		: "memory");						\
 }
 
 #define __ctl_store(array, low, high) {					\
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/elf.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/elf.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/elf.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/elf.h	2017-02-12 16:03:20.000000000 -0500
@@ -193,7 +193,7 @@ extern char elf_platform[];
 do {								\
 	set_personality(PER_LINUX |				\
 		(current->personality & (~PER_MASK)));		\
-	current_thread_info()->sys_call_table = 		\
+	current->thread.sys_call_table =			\
 		(unsigned long) &sys_call_table;		\
 } while (0)
 #else /* CONFIG_COMPAT */
@@ -204,11 +204,11 @@ do {								\
 			(current->personality & ~PER_MASK));	\
 	if ((ex).e_ident[EI_CLASS] == ELFCLASS32) {		\
 		set_thread_flag(TIF_31BIT);			\
-		current_thread_info()->sys_call_table =		\
+		current->thread.sys_call_table =		\
 			(unsigned long)	&sys_call_table_emu;	\
 	} else {						\
 		clear_thread_flag(TIF_31BIT);			\
-		current_thread_info()->sys_call_table =		\
+		current->thread.sys_call_table =		\
 			(unsigned long) &sys_call_table;	\
 	}							\
 } while (0)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/facilities_src.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/facilities_src.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/facilities_src.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/facilities_src.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,82 +0,0 @@
-/*
- *    Copyright IBM Corp. 2015
- */
-
-#ifndef S390_GEN_FACILITIES_C
-#error "This file can only be included by gen_facilities.c"
-#endif
-
-#include <linux/kconfig.h>
-
-struct facility_def {
-	char *name;
-	int *bits;
-};
-
-static struct facility_def facility_defs[] = {
-	{
-		/*
-		 * FACILITIES_ALS contains the list of facilities that are
-		 * required to run a kernel that is compiled e.g. with
-		 * -march=<machine>.
-		 */
-		.name = "FACILITIES_ALS",
-		.bits = (int[]){
-#ifdef CONFIG_HAVE_MARCH_Z900_FEATURES
-			0,  /* N3 instructions */
-			1,  /* z/Arch mode installed */
-#endif
-#ifdef CONFIG_HAVE_MARCH_Z990_FEATURES
-			18, /* long displacement facility */
-#endif
-#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
-			7,  /* stfle */
-			17, /* message security assist */
-			21, /* extended-immediate facility */
-			25, /* store clock fast */
-#endif
-#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
-			27, /* mvcos */
-			32, /* compare and swap and store */
-			33, /* compare and swap and store 2 */
-			34, /* general extension facility */
-			35, /* execute extensions */
-#endif
-#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
-			45, /* fast-BCR, etc. */
-#endif
-#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
-			49, /* misc-instruction-extensions */
-			52, /* interlocked facility 2 */
-#endif
-#ifdef CONFIG_HAVE_MARCH_Z13_FEATURES
-			53, /* load-and-zero-rightmost-byte, etc. */
-#endif
-			-1 /* END */
-		}
-	},
-	{
-		.name = "FACILITIES_KVM",
-		.bits = (int[]){
-			0,  /* N3 instructions */
-			1,  /* z/Arch mode installed */
-			2,  /* z/Arch mode active */
-			3,  /* DAT-enhancement */
-			4,  /* idte segment table */
-			5,  /* idte region table */
-			6,  /* ASN-and-LX reuse */
-			7,  /* stfle */
-			8,  /* enhanced-DAT 1 */
-			9,  /* sense-running-status */
-			10, /* conditional sske */
-			13, /* ipte-range */
-			14, /* nonquiescing key-setting */
-			73, /* transactional execution */
-			75, /* access-exception-fetch/store indication */
-			76, /* msa extension 3 */
-			77, /* msa extension 4 */
-			78, /* enhanced-DAT 2 */
-			-1  /* END */
-		}
-	},
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/idals.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/idals.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/idals.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/idals.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <asm/cio.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define IDA_SIZE_LOG 12 /* 11 for 2k , 12 for 4k */
 #define IDA_BLOCK_SIZE (1L<<IDA_SIZE_LOG)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/ipl.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/ipl.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/ipl.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/ipl.h	2017-02-12 16:03:20.000000000 -0500
@@ -97,7 +97,7 @@ void __init save_area_add_vxrs(struct sa
 extern void do_reipl(void);
 extern void do_halt(void);
 extern void do_poff(void);
-extern void ipl_save_parameters(void);
+extern void ipl_verify_parameters(void);
 extern void ipl_update_parameters(void);
 extern size_t append_ipl_vmparm(char *, size_t);
 extern size_t append_ipl_scpdata(char *, size_t);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/s390/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/s390/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
-
-
+generic-y += asm-offsets.h
 generic-y += clkdev.h
+generic-y += dma-contiguous.h
 generic-y += export.h
 generic-y += irq_work.h
 generic-y += mcs_spinlock.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/lowcore.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/lowcore.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/lowcore.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/lowcore.h	2017-02-12 16:03:20.000000000 -0500
@@ -95,7 +95,7 @@ struct lowcore {
 
 	/* Current process. */
 	__u64	current_task;			/* 0x0310 */
-	__u64	thread_info;			/* 0x0318 */
+	__u8	pad_0x318[0x320-0x318];		/* 0x0318 */
 	__u64	kernel_stack;			/* 0x0320 */
 
 	/* Interrupt, panic and restart stack. */
@@ -126,7 +126,8 @@ struct lowcore {
 	__u64	percpu_offset;			/* 0x0378 */
 	__u64	vdso_per_cpu_data;		/* 0x0380 */
 	__u64	machine_flags;			/* 0x0388 */
-	__u8	pad_0x0390[0x0398-0x0390];	/* 0x0390 */
+	__u32	preempt_count;			/* 0x0390 */
+	__u8	pad_0x0394[0x0398-0x0394];	/* 0x0394 */
 	__u64	gmap;				/* 0x0398 */
 	__u32	spinlock_lockval;		/* 0x03a0 */
 	__u32	fpu_flags;			/* 0x03a4 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/mmu_context.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/mmu_context.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/mmu_context.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/mmu_context.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
 #define __S390_MMU_CONTEXT_H
 
 #include <asm/pgalloc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/tlbflush.h>
 #include <asm/ctl_reg.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/pci_clp.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/pci_clp.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/pci_clp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/pci_clp.h	2017-02-12 16:03:20.000000000 -0500
@@ -46,6 +46,8 @@ struct clp_fh_list_entry {
 #define CLP_UTIL_STR_LEN	64
 #define CLP_PFIP_NR_SEGMENTS	4
 
+extern bool zpci_unique_uid;
+
 /* List PCI functions request */
 struct clp_req_list_pci {
 	struct clp_req_hdr hdr;
@@ -59,7 +61,8 @@ struct clp_rsp_list_pci {
 	u64 resume_token;
 	u32 reserved2;
 	u16 max_fn;
-	u8 reserved3;
+	u8			: 7;
+	u8 uid_checking		: 1;
 	u8 entry_size;
 	struct clp_fh_list_entry fh_list[CLP_FH_LIST_NR_ENTRIES];
 } __packed;
@@ -84,7 +87,8 @@ struct clp_rsp_query_pci {
 	u16 pchid;
 	u32 bar[PCI_BAR_COUNT];
 	u8 pfip[CLP_PFIP_NR_SEGMENTS];	/* pci function internal path */
-	u32			: 24;
+	u32			: 16;
+	u8 fmb_len;
 	u8 pft;				/* pci function type */
 	u64 sdma;			/* start dma as */
 	u64 edma;			/* end dma as */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/pci.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/pci.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/pci.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/pci.h	2017-02-12 16:03:20.000000000 -0500
@@ -133,6 +133,7 @@ struct zpci_dev {
 	/* Function measurement block */
 	struct zpci_fmb *fmb;
 	u16		fmb_update;	/* update interval */
+	u16		fmb_length;
 	/* software counters */
 	atomic64_t allocated_pages;
 	atomic64_t mapped_pages;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/pgalloc.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/pgalloc.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/pgalloc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/pgalloc.h	2017-02-12 16:03:20.000000000 -0500
@@ -27,17 +27,17 @@ extern int page_table_allocate_pgste;
 
 static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
 {
-	typedef struct { char _[n]; } addrtype;
+	struct addrtype { char _[256]; };
+	int i;
 
-	*s = val;
-	n = (n / 256) - 1;
-	asm volatile(
-		"	mvc	8(248,%0),0(%0)\n"
-		"0:	mvc	256(256,%0),0(%0)\n"
-		"	la	%0,256(%0)\n"
-		"	brct	%1,0b\n"
-		: "+a" (s), "+d" (n), "=m" (*(addrtype *) s)
-		: "m" (*(addrtype *) s));
+	for (i = 0; i < n; i += 256) {
+		*s = val;
+		asm volatile(
+			"mvc	8(248,%[s]),0(%[s])\n"
+			: "+m" (*(struct addrtype *) s)
+			: [s] "a" (s));
+		s += 256 / sizeof(long);
+	}
 }
 
 static inline void crst_table_init(unsigned long *crst, unsigned long entry)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/preempt.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/preempt.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/preempt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/preempt.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,137 @@
+#ifndef __ASM_PREEMPT_H
+#define __ASM_PREEMPT_H
+
+#include <asm/current.h>
+#include <linux/thread_info.h>
+#include <asm/atomic_ops.h>
+
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+
+#define PREEMPT_ENABLED	(0 + PREEMPT_NEED_RESCHED)
+
+static inline int preempt_count(void)
+{
+	return READ_ONCE(S390_lowcore.preempt_count) & ~PREEMPT_NEED_RESCHED;
+}
+
+static inline void preempt_count_set(int pc)
+{
+	int old, new;
+
+	do {
+		old = READ_ONCE(S390_lowcore.preempt_count);
+		new = (old & PREEMPT_NEED_RESCHED) |
+			(pc & ~PREEMPT_NEED_RESCHED);
+	} while (__atomic_cmpxchg(&S390_lowcore.preempt_count,
+				  old, new) != old);
+}
+
+#define init_task_preempt_count(p)	do { } while (0)
+
+#define init_idle_preempt_count(p, cpu)	do { \
+	S390_lowcore.preempt_count = PREEMPT_ENABLED; \
+} while (0)
+
+static inline void set_preempt_need_resched(void)
+{
+	__atomic_and(~PREEMPT_NEED_RESCHED, &S390_lowcore.preempt_count);
+}
+
+static inline void clear_preempt_need_resched(void)
+{
+	__atomic_or(PREEMPT_NEED_RESCHED, &S390_lowcore.preempt_count);
+}
+
+static inline bool test_preempt_need_resched(void)
+{
+	return !(READ_ONCE(S390_lowcore.preempt_count) & PREEMPT_NEED_RESCHED);
+}
+
+static inline void __preempt_count_add(int val)
+{
+	if (__builtin_constant_p(val) && (val >= -128) && (val <= 127))
+		__atomic_add_const(val, &S390_lowcore.preempt_count);
+	else
+		__atomic_add(val, &S390_lowcore.preempt_count);
+}
+
+static inline void __preempt_count_sub(int val)
+{
+	__preempt_count_add(-val);
+}
+
+static inline bool __preempt_count_dec_and_test(void)
+{
+	return __atomic_add(-1, &S390_lowcore.preempt_count) == 1;
+}
+
+static inline bool should_resched(int preempt_offset)
+{
+	return unlikely(READ_ONCE(S390_lowcore.preempt_count) ==
+			preempt_offset);
+}
+
+#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+#define PREEMPT_ENABLED	(0)
+
+static inline int preempt_count(void)
+{
+	return READ_ONCE(S390_lowcore.preempt_count);
+}
+
+static inline void preempt_count_set(int pc)
+{
+	S390_lowcore.preempt_count = pc;
+}
+
+#define init_task_preempt_count(p)	do { } while (0)
+
+#define init_idle_preempt_count(p, cpu)	do { \
+	S390_lowcore.preempt_count = PREEMPT_ENABLED; \
+} while (0)
+
+static inline void set_preempt_need_resched(void)
+{
+}
+
+static inline void clear_preempt_need_resched(void)
+{
+}
+
+static inline bool test_preempt_need_resched(void)
+{
+	return false;
+}
+
+static inline void __preempt_count_add(int val)
+{
+	S390_lowcore.preempt_count += val;
+}
+
+static inline void __preempt_count_sub(int val)
+{
+	S390_lowcore.preempt_count -= val;
+}
+
+static inline bool __preempt_count_dec_and_test(void)
+{
+	return !--S390_lowcore.preempt_count && tif_need_resched();
+}
+
+static inline bool should_resched(int preempt_offset)
+{
+	return unlikely(preempt_count() == preempt_offset &&
+			tif_need_resched());
+}
+
+#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */
+
+#ifdef CONFIG_PREEMPT
+extern asmlinkage void preempt_schedule(void);
+#define __preempt_schedule() preempt_schedule()
+extern asmlinkage void preempt_schedule_notrace(void);
+#define __preempt_schedule_notrace() preempt_schedule_notrace()
+#endif /* CONFIG_PREEMPT */
+
+#endif /* __ASM_PREEMPT_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -110,14 +110,20 @@ typedef struct {
 struct thread_struct {
 	unsigned int  acrs[NUM_ACRS];
         unsigned long ksp;              /* kernel stack pointer             */
+	unsigned long user_timer;	/* task cputime in user space */
+	unsigned long system_timer;	/* task cputime in kernel space */
+	unsigned long sys_call_table;	/* system call table address */
 	mm_segment_t mm_segment;
 	unsigned long gmap_addr;	/* address of last gmap fault. */
 	unsigned int gmap_write_flag;	/* gmap fault write indication */
 	unsigned int gmap_int_code;	/* int code of last gmap fault */
 	unsigned int gmap_pfault;	/* signal of a pending guest pfault */
+	/* Per-thread information related to debugging */
 	struct per_regs per_user;	/* User specified PER registers */
 	struct per_event per_event;	/* Cause of the last PER trap */
 	unsigned long per_flags;	/* Flags to control debug behavior */
+	unsigned int system_call;	/* system call number in signal */
+	unsigned long last_break;	/* last breaking-event-address. */
         /* pfault_wait is used to block the process on a pfault event */
 	unsigned long pfault_wait;
 	struct list_head list;
@@ -234,9 +240,10 @@ static inline unsigned short stap(void)
 /*
  * Give up the time slice of the virtual PU.
  */
-void cpu_relax(void);
+#define cpu_relax_yield cpu_relax_yield
+void cpu_relax_yield(void);
 
-#define cpu_relax_lowlatency()  barrier()
+#define cpu_relax() barrier()
 
 #define ECAG_CACHE_ATTRIBUTE	0
 #define ECAG_CPU_ATTRIBUTE	1
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/sclp.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/sclp.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/sclp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/sclp.h	2017-02-12 16:03:20.000000000 -0500
@@ -101,7 +101,8 @@ struct zpci_report_error_header {
 	u8 data[0];	/* Subsequent Data passed verbatim to SCLP ET 24 */
 } __packed;
 
-int sclp_get_core_info(struct sclp_core_info *info);
+int _sclp_get_core_info_early(struct sclp_core_info *info);
+int _sclp_get_core_info(struct sclp_core_info *info);
 int sclp_core_configure(u8 core);
 int sclp_core_deconfigure(u8 core);
 int sclp_sdias_blk_count(void);
@@ -119,4 +120,11 @@ void sclp_early_detect(void);
 void _sclp_print_early(const char *);
 void sclp_ocf_cpc_name_copy(char *dst);
 
+static inline int sclp_get_core_info(struct sclp_core_info *info, int early)
+{
+	if (early)
+		return _sclp_get_core_info_early(info);
+	return _sclp_get_core_info(info);
+}
+
 #endif /* _ASM_S390_SCLP_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/scsw.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/scsw.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/scsw.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/scsw.h	2017-02-12 16:03:20.000000000 -0500
@@ -96,7 +96,8 @@ struct tm_scsw {
 	u32 dstat:8;
 	u32 cstat:8;
 	u32 fcxs:8;
-	u32 schxs:8;
+	u32 ifob:1;
+	u32 sesq:7;
 } __attribute__ ((packed));
 
 /**
@@ -177,6 +178,9 @@ union scsw {
 #define SCHN_STAT_INTF_CTRL_CHK	 0x02
 #define SCHN_STAT_CHAIN_CHECK	 0x01
 
+#define SCSW_SESQ_DEV_NOFCX	 3
+#define SCSW_SESQ_PATH_NOFCX	 4
+
 /*
  * architectured values for first sense byte
  */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/smp.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/smp.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/smp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/smp.h	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,7 @@ extern void smp_yield_cpu(int cpu);
 extern void smp_cpu_set_polarization(int cpu, int val);
 extern int smp_cpu_get_polarization(int cpu);
 extern void smp_fill_possible_mask(void);
+extern void smp_detect_cpus(void);
 
 #else /* CONFIG_SMP */
 
@@ -56,6 +57,7 @@ static inline int smp_store_status(int c
 static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
 static inline void smp_fill_possible_mask(void) { }
+static inline void smp_detect_cpus(void) { }
 
 #endif /* CONFIG_SMP */
 
@@ -69,6 +71,12 @@ static inline void smp_stop_cpu(void)
 	}
 }
 
+/* Return thread 0 CPU number as base CPU */
+static inline int smp_get_base_cpu(int cpu)
+{
+	return cpu - (cpu % (smp_cpu_mtid + 1));
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 extern int smp_rescan_cpus(void);
 extern void __noreturn cpu_die(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/spinlock.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/spinlock.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/spinlock.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/spinlock.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,14 @@ _raw_compare_and_swap(unsigned int *lock
 	return __sync_bool_compare_and_swap(lock, old, new);
 }
 
+#ifndef CONFIG_SMP
+static inline bool arch_vcpu_is_preempted(int cpu) { return false; }
+#else
+bool arch_vcpu_is_preempted(int cpu);
+#endif
+
+#define vcpu_is_preempted arch_vcpu_is_preempted
+
 /*
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/string.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/string.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/string.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/string.h	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
 #define __HAVE_ARCH_MEMCHR	/* inline & arch function */
 #define __HAVE_ARCH_MEMCMP	/* arch function */
 #define __HAVE_ARCH_MEMCPY	/* gcc builtin & arch function */
+#define __HAVE_ARCH_MEMMOVE	/* gcc builtin & arch function */
 #define __HAVE_ARCH_MEMSCAN	/* inline & arch function */
 #define __HAVE_ARCH_MEMSET	/* gcc builtin & arch function */
 #define __HAVE_ARCH_STRCAT	/* inline & arch function */
@@ -32,6 +33,7 @@
 extern int memcmp(const void *, const void *, size_t);
 extern void *memcpy(void *, const void *, size_t);
 extern void *memset(void *, int, size_t);
+extern void *memmove(void *, const void *, size_t);
 extern int strcmp(const char *,const char *);
 extern size_t strlcat(char *, const char *, size_t);
 extern size_t strlcpy(char *, const char *, size_t);
@@ -40,7 +42,6 @@ extern char *strncpy(char *, const char
 extern char *strrchr(const char *, int);
 extern char *strstr(const char *, const char *);
 
-#undef __HAVE_ARCH_MEMMOVE
 #undef __HAVE_ARCH_STRCHR
 #undef __HAVE_ARCH_STRNCHR
 #undef __HAVE_ARCH_STRNCMP
@@ -61,7 +62,7 @@ static inline void *memchr(const void *
 		"	jl	1f\n"
 		"	la	%0,0\n"
 		"1:"
-		: "+a" (ret), "+&a" (s) : "d" (r0) : "cc");
+		: "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
 	return (void *) ret;
 }
 
@@ -73,7 +74,7 @@ static inline void *memscan(void *s, int
 	asm volatile(
 		"0:	srst	%0,%1\n"
 		"	jo	0b\n"
-		: "+a" (ret), "+&a" (s) : "d" (r0) : "cc");
+		: "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
 	return (void *) ret;
 }
 
@@ -114,7 +115,7 @@ static inline size_t strlen(const char *
 	asm volatile(
 		"0:	srst	%0,%1\n"
 		"	jo	0b"
-		: "+d" (r0), "+a" (tmp) :  : "cc");
+		: "+d" (r0), "+a" (tmp) :  : "cc", "memory");
 	return r0 - (unsigned long) s;
 }
 
@@ -127,7 +128,7 @@ static inline size_t strnlen(const char
 	asm volatile(
 		"0:	srst	%0,%1\n"
 		"	jo	0b"
-		: "+a" (end), "+a" (tmp) : "d" (r0)  : "cc");
+		: "+a" (end), "+a" (tmp) : "d" (r0)  : "cc", "memory");
 	return end - s;
 }
 #else /* IN_ARCH_STRING_C */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/sysinfo.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/sysinfo.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/sysinfo.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/sysinfo.h	2017-02-12 16:03:20.000000000 -0500
@@ -107,6 +107,11 @@ struct sysinfo_2_2_2 {
 	char reserved_3[5];
 	unsigned short cpus_dedicated;
 	unsigned short cpus_shared;
+	char reserved_4[3];
+	unsigned char vsne;
+	uuid_be uuid;
+	char reserved_5[160];
+	char ext_name[256];
 };
 
 #define LPAR_CHAR_DEDICATED	(1 << 7)
@@ -127,7 +132,7 @@ struct sysinfo_3_2_2 {
 		unsigned int caf;
 		char cpi[16];
 		char reserved_1[3];
-		char ext_name_encoding;
+		unsigned char evmne;
 		unsigned int reserved_2;
 		uuid_be uuid;
 	} vm[8];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/thread_info.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/thread_info.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/thread_info.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/thread_info.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,10 +12,10 @@
 /*
  * Size of kernel stack for each process
  */
-#define THREAD_ORDER 2
+#define THREAD_SIZE_ORDER 2
 #define ASYNC_ORDER  2
 
-#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
+#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define ASYNC_SIZE  (PAGE_SIZE << ASYNC_ORDER)
 
 #ifndef __ASSEMBLY__
@@ -30,15 +30,7 @@
  * - if the contents of this structure are changed, the assembly constants must also be changed
  */
 struct thread_info {
-	struct task_struct	*task;		/* main task structure */
 	unsigned long		flags;		/* low level flags */
-	unsigned long		sys_call_table;	/* System call table address */
-	unsigned int		cpu;		/* current CPU */
-	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
-	unsigned int		system_call;
-	__u64			user_timer;
-	__u64			system_timer;
-	unsigned long		last_break;	/* last breaking-event-address. */
 };
 
 /*
@@ -46,26 +38,14 @@ struct thread_info {
  */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
-	.task		= &tsk,			\
 	.flags		= 0,			\
-	.cpu		= 0,			\
-	.preempt_count	= INIT_PREEMPT_COUNT,	\
 }
 
-#define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
 
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
-	return (struct thread_info *) S390_lowcore.thread_info;
-}
-
 void arch_release_task_struct(struct task_struct *tsk);
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
 
-#define THREAD_SIZE_ORDER THREAD_ORDER
-
 #endif
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/timex.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/timex.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/timex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/timex.h	2017-02-12 16:03:20.000000000 -0500
@@ -52,11 +52,9 @@ static inline void store_clock_comparato
 
 void clock_comparator_work(void);
 
-void __init ptff_init(void);
+void __init time_early_init(void);
 
 extern unsigned char ptff_function_mask[16];
-extern unsigned long lpar_offset;
-extern unsigned long initial_leap_seconds;
 
 /* Function codes for the ptff instruction. */
 #define PTFF_QAF	0x00	/* query available functions */
@@ -100,21 +98,28 @@ struct ptff_qui {
 	unsigned int pad_0x5c[41];
 } __packed;
 
-static inline int ptff(void *ptff_block, size_t len, unsigned int func)
-{
-	typedef struct { char _[len]; } addrtype;
-	register unsigned int reg0 asm("0") = func;
-	register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
-	int rc;
-
-	asm volatile(
-		"	.word	0x0104\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (rc), "+m" (*(addrtype *) ptff_block)
-		: "d" (reg0), "d" (reg1) : "cc");
-	return rc;
-}
+/*
+ * ptff - Perform timing facility function
+ * @ptff_block: Pointer to ptff parameter block
+ * @len: Length of parameter block
+ * @func: Function code
+ * Returns: Condition code (0 on success)
+ */
+#define ptff(ptff_block, len, func)					\
+({									\
+	struct addrtype { char _[len]; };				\
+	register unsigned int reg0 asm("0") = func;			\
+	register unsigned long reg1 asm("1") = (unsigned long) (ptff_block);\
+	int rc;								\
+									\
+	asm volatile(							\
+		"	.word	0x0104\n"				\
+		"	ipm	%0\n"					\
+		"	srl	%0,28\n"				\
+		: "=d" (rc), "+m" (*(struct addrtype *) reg1)		\
+		: "d" (reg0), "d" (reg1) : "cc");			\
+	rc;								\
+})
 
 static inline unsigned long long local_tick_disable(void)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/tlb.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/tlb.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/tlb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/tlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,12 +104,6 @@ static inline bool __tlb_remove_page_siz
 	return __tlb_remove_page(tlb, page);
 }
 
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
-					 struct page *page)
-{
-	return __tlb_remove_page(tlb, page);
-}
-
 static inline void tlb_remove_page_size(struct mmu_gather *tlb,
 					struct page *page, int page_size)
 {
@@ -162,5 +156,13 @@ static inline void pud_free_tlb(struct m
 #define tlb_remove_tlb_entry(tlb, ptep, addr)	do { } while (0)
 #define tlb_remove_pmd_tlb_entry(tlb, pmdp, addr)	do { } while (0)
 #define tlb_migrate_finish(mm)			do { } while (0)
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	\
+	tlb_remove_tlb_entry(tlb, ptep, address)
+
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+						     unsigned int page_size)
+{
+}
 
 #endif /* _S390_TLB_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/topology.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/topology.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/topology.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/topology.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,21 +22,22 @@ struct cpu_topology_s390 {
 	cpumask_t drawer_mask;
 };
 
-DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology);
+extern struct cpu_topology_s390 cpu_topology[NR_CPUS];
+extern cpumask_t cpus_with_topology;
 
-#define topology_physical_package_id(cpu) (per_cpu(cpu_topology, cpu).socket_id)
-#define topology_thread_id(cpu)		  (per_cpu(cpu_topology, cpu).thread_id)
-#define topology_sibling_cpumask(cpu) \
-		(&per_cpu(cpu_topology, cpu).thread_mask)
-#define topology_core_id(cpu)		  (per_cpu(cpu_topology, cpu).core_id)
-#define topology_core_cpumask(cpu)	  (&per_cpu(cpu_topology, cpu).core_mask)
-#define topology_book_id(cpu)		  (per_cpu(cpu_topology, cpu).book_id)
-#define topology_book_cpumask(cpu)	  (&per_cpu(cpu_topology, cpu).book_mask)
-#define topology_drawer_id(cpu)		  (per_cpu(cpu_topology, cpu).drawer_id)
-#define topology_drawer_cpumask(cpu)	  (&per_cpu(cpu_topology, cpu).drawer_mask)
+#define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id)
+#define topology_thread_id(cpu)		  (cpu_topology[cpu].thread_id)
+#define topology_sibling_cpumask(cpu)	  (&cpu_topology[cpu].thread_mask)
+#define topology_core_id(cpu)		  (cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu)	  (&cpu_topology[cpu].core_mask)
+#define topology_book_id(cpu)		  (cpu_topology[cpu].book_id)
+#define topology_book_cpumask(cpu)	  (&cpu_topology[cpu].book_mask)
+#define topology_drawer_id(cpu)		  (cpu_topology[cpu].drawer_id)
+#define topology_drawer_cpumask(cpu)	  (&cpu_topology[cpu].drawer_mask)
 
 #define mc_capable() 1
 
+void topology_init_early(void);
 int topology_cpu_init(struct cpu *);
 int topology_set_cpu_management(int fc);
 void topology_schedule_update(void);
@@ -46,6 +47,7 @@ const struct cpumask *cpu_coregroup_mask
 
 #else /* CONFIG_SCHED_TOPOLOGY */
 
+static inline void topology_init_early(void) { }
 static inline void topology_schedule_update(void) { }
 static inline int topology_cpu_init(struct cpu *cpu) { return 0; }
 static inline void topology_expect_change(void) { }
@@ -65,7 +67,7 @@ static inline void topology_expect_chang
 #define cpu_to_node cpu_to_node
 static inline int cpu_to_node(int cpu)
 {
-	return per_cpu(cpu_topology, cpu).node_id;
+	return cpu_topology[cpu].node_id;
 }
 
 /* Returns a pointer to the cpumask of CPUs on node 'node'. */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/trace/zcrypt.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/trace/zcrypt.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/trace/zcrypt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/trace/zcrypt.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,122 @@
+/*
+ * Tracepoint definitions for the s390 zcrypt device driver
+ *
+ * Copyright IBM Corp. 2016
+ * Author(s): Harald Freudenberger <freude@de.ibm.com>
+ *
+ * Currently there are two tracepoint events defined here.
+ * An s390_zcrypt_req request event occurs as soon as the request is
+ * recognized by the zcrypt ioctl function. This event may act as some kind
+ * of request-processing-starts-now indication.
+ * As late as possible within the zcrypt ioctl function there occurs the
+ * s390_zcrypt_rep event which may act as the point in time where the
+ * request has been processed by the kernel and the result is about to be
+ * transferred back to userspace.
+ * The glue which binds together request and reply event is the ptr
+ * parameter, which is the local buffer address where the request from
+ * userspace has been stored by the ioctl function.
+ *
+ * The main purpose of this zcrypt tracepoint api is to get some data for
+ * performance measurements together with information about on which card
+ * and queue the request has been processed. It is not an ffdc interface as
+ * there is already code in the zcrypt device driver to serve the s390
+ * debug feature interface.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM s390
+
+#if !defined(_TRACE_S390_ZCRYPT_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_S390_ZCRYPT_H
+
+#include <linux/tracepoint.h>
+
+#define TP_ICARSAMODEXPO  0x0001
+#define TP_ICARSACRT	  0x0002
+#define TB_ZSECSENDCPRB   0x0003
+#define TP_ZSENDEP11CPRB  0x0004
+#define TP_HWRNGCPRB	  0x0005
+
+#define show_zcrypt_tp_type(type)				\
+	__print_symbolic(type,					\
+			 { TP_ICARSAMODEXPO, "ICARSAMODEXPO" }, \
+			 { TP_ICARSACRT, "ICARSACRT" },		\
+			 { TB_ZSECSENDCPRB, "ZSECSENDCPRB" },	\
+			 { TP_ZSENDEP11CPRB, "ZSENDEP11CPRB" }, \
+			 { TP_HWRNGCPRB, "HWRNGCPRB" })
+
+/**
+ * trace_s390_zcrypt_req - zcrypt request tracepoint function
+ * @ptr:  Address of the local buffer where the request from userspace
+ *	  is stored. Can be used as a unique id to relate together
+ *	  request and reply.
+ * @type: One of the TP_ defines above.
+ *
+ * Called when a request from userspace is recognised within the ioctl
+ * function of the zcrypt device driver and may act as an entry
+ * timestamp.
+ */
+TRACE_EVENT(s390_zcrypt_req,
+	    TP_PROTO(void *ptr, u32 type),
+	    TP_ARGS(ptr, type),
+	    TP_STRUCT__entry(
+		    __field(void *, ptr)
+		    __field(u32, type)),
+	    TP_fast_assign(
+		    __entry->ptr = ptr;
+		    __entry->type = type;),
+	    TP_printk("ptr=%p type=%s",
+		      __entry->ptr,
+		      show_zcrypt_tp_type(__entry->type))
+);
+
+/**
+ * trace_s390_zcrypt_rep - zcrypt reply tracepoint function
+ * @ptr:  Address of the local buffer where the request from userspace
+ *	  is stored. Can be used as a unique id to match together
+ *	  request and reply.
+ * @fc:   Function code.
+ * @rc:   The bare returncode as returned by the device driver ioctl
+ *	  function.
+ * @dev:  The adapter nr where this request was actually processed.
+ * @dom:  Domain id of the device where this request was processed.
+ *
+ * Called upon recognising the reply from the crypto adapter. This
+ * message may act as the exit timestamp for the request but also
+ * carries some info about on which adapter the request was processed
+ * and the returncode from the device driver.
+ */
+TRACE_EVENT(s390_zcrypt_rep,
+	    TP_PROTO(void *ptr, u32 fc, u32 rc, u16 dev, u16 dom),
+	    TP_ARGS(ptr, fc, rc, dev, dom),
+	    TP_STRUCT__entry(
+		    __field(void *, ptr)
+		    __field(u32, fc)
+		    __field(u32, rc)
+		    __field(u16, device)
+		    __field(u16, domain)),
+	    TP_fast_assign(
+		    __entry->ptr = ptr;
+		    __entry->fc = fc;
+		    __entry->rc = rc;
+		    __entry->device = dev;
+		    __entry->domain = dom;),
+	    TP_printk("ptr=%p fc=0x%04x rc=%d dev=0x%02hx domain=0x%04hx",
+		      __entry->ptr,
+		      (unsigned int) __entry->fc,
+		      (int) __entry->rc,
+		      (unsigned short) __entry->device,
+		      (unsigned short) __entry->domain)
+);
+
+#endif /* _TRACE_S390_ZCRYPT_H */
+
+/* This part must be outside protection */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+
+#define TRACE_INCLUDE_PATH asm/trace
+#define TRACE_INCLUDE_FILE zcrypt
+
+#include <trace/define_trace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/uaccess.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/uaccess.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/uaccess.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/uaccess.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,14 +37,14 @@
 #define get_ds()        (KERNEL_DS)
 #define get_fs()        (current->thread.mm_segment)
 
-#define set_fs(x) \
-({									\
+#define set_fs(x)							\
+{									\
 	unsigned long __pto;						\
 	current->thread.mm_segment = (x);				\
 	__pto = current->thread.mm_segment.ar4 ?			\
 		S390_lowcore.user_asce : S390_lowcore.kernel_asce;	\
 	__ctl_load(__pto, 7, 7);					\
-})
+}
 
 #define segment_eq(a,b) ((a).ar4 == (b).ar4)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/asm/vdso.h linux-libre-4.10-rc8-gnu/arch/s390/include/asm/vdso.h
--- linux-libre-4.9-gnu/arch/s390/include/asm/vdso.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/asm/vdso.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,6 +33,8 @@ struct vdso_data {
 	__u32 ectg_available;		/* ECTG instruction present	0x58 */
 	__u32 tk_mult;			/* Mult. used for xtime_nsec	0x5c */
 	__u32 tk_shift;			/* Shift used for xtime_nsec	0x60 */
+	__u32 ts_dir;			/* TOD steering direction	0x64 */
+	__u64 ts_end;			/* TOD steering end		0x68 */
 };
 
 struct vdso_per_cpu_data {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/uapi/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/s390/include/uapi/asm/Kbuild
--- linux-libre-4.9-gnu/arch/s390/include/uapi/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/uapi/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@ header-y += dasd.h
 header-y += debug.h
 header-y += errno.h
 header-y += fcntl.h
+header-y += hypfs.h
 header-y += ioctl.h
 header-y += ioctls.h
 header-y += ipcbuf.h
@@ -29,16 +30,16 @@ header-y += ptrace.h
 header-y += qeth.h
 header-y += resource.h
 header-y += schid.h
+header-y += sclp_ctl.h
 header-y += sembuf.h
 header-y += setup.h
 header-y += shmbuf.h
+header-y += sie.h
 header-y += sigcontext.h
 header-y += siginfo.h
 header-y += signal.h
 header-y += socket.h
 header-y += sockios.h
-header-y += sclp_ctl.h
-header-y += sie.h
 header-y += stat.h
 header-y += statfs.h
 header-y += swab.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/s390/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/s390/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -96,4 +96,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif /* _ASM_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/include/uapi/asm/zcrypt.h linux-libre-4.10-rc8-gnu/arch/s390/include/uapi/asm/zcrypt.h
--- linux-libre-4.9-gnu/arch/s390/include/uapi/asm/zcrypt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/include/uapi/asm/zcrypt.h	2017-02-12 16:03:20.000000000 -0500
@@ -215,6 +215,42 @@ struct ep11_urb {
 	uint64_t		resp;
 } __attribute__((packed));
 
+/**
+ * struct zcrypt_device_status
+ * @hwtype:		raw hardware type
+ * @qid:		6 bit device index, 8 bit domain
+ * @functions:		AP device function bit field 'abcdef'
+ *			a, b, c = reserved
+ *			d = CCA coprocessor
+ *			e = Accelerator
+ *			f = EP11 coprocessor
+ * @online		online status
+ * @reserved		reserved
+ */
+struct zcrypt_device_status {
+	unsigned int hwtype:8;
+	unsigned int qid:14;
+	unsigned int online:1;
+	unsigned int functions:6;
+	unsigned int reserved:3;
+};
+
+#define MAX_ZDEV_CARDIDS 64
+#define MAX_ZDEV_DOMAINS 256
+
+/**
+ * Maximum number of zcrypt devices
+ */
+#define MAX_ZDEV_ENTRIES (MAX_ZDEV_CARDIDS * MAX_ZDEV_DOMAINS)
+
+/**
+ * zcrypt_device_matrix
+ * Device matrix of all zcrypt devices
+ */
+struct zcrypt_device_matrix {
+	struct zcrypt_device_status device[MAX_ZDEV_ENTRIES];
+};
+
 #define AUTOSELECT ((unsigned int)0xFFFFFFFF)
 
 #define ZCRYPT_IOCTL_MAGIC 'z'
@@ -321,6 +357,7 @@ struct ep11_urb {
 #define ICARSACRT	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x06, 0)
 #define ZSECSENDCPRB	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x81, 0)
 #define ZSENDEP11CPRB	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x04, 0)
+#define ZDEVICESTATUS	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x4f, 0)
 
 /* New status calls */
 #define Z90STAT_TOTALCOUNT	_IOR(ZCRYPT_IOCTL_MAGIC, 0x40, int)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/Kconfig linux-libre-4.10-rc8-gnu/arch/s390/Kconfig
--- linux-libre-4.9-gnu/arch/s390/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -136,6 +136,7 @@ config S390
 	select HAVE_CMPXCHG_LOCAL
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
+	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
@@ -169,8 +170,10 @@ config S390
 	select OLD_SIGSUSPEND3
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
+	select THREAD_INFO_IN_TASK
 	select TTY
 	select VIRT_CPU_ACCOUNTING
+	select ARCH_HAS_SCALED_CPUTIME
 	select VIRT_TO_BUS
 	select HAVE_NMI
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/asm-offsets.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/asm-offsets.c
--- linux-libre-4.9-gnu/arch/s390/kernel/asm-offsets.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/asm-offsets.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,12 +25,14 @@
 int main(void)
 {
 	/* task struct offsets */
-	OFFSET(__TASK_thread_info, task_struct, stack);
+	OFFSET(__TASK_stack, task_struct, stack);
 	OFFSET(__TASK_thread, task_struct, thread);
 	OFFSET(__TASK_pid, task_struct, pid);
 	BLANK();
 	/* thread struct offsets */
 	OFFSET(__THREAD_ksp, thread_struct, ksp);
+	OFFSET(__THREAD_sysc_table,  thread_struct, sys_call_table);
+	OFFSET(__THREAD_last_break, thread_struct, last_break);
 	OFFSET(__THREAD_FPU_fpc, thread_struct, fpu.fpc);
 	OFFSET(__THREAD_FPU_regs, thread_struct, fpu.regs);
 	OFFSET(__THREAD_per_cause, thread_struct, per_event.cause);
@@ -39,14 +41,7 @@ int main(void)
 	OFFSET(__THREAD_trap_tdb, thread_struct, trap_tdb);
 	BLANK();
 	/* thread info offsets */
-	OFFSET(__TI_task, thread_info, task);
-	OFFSET(__TI_flags, thread_info, flags);
-	OFFSET(__TI_sysc_table, thread_info, sys_call_table);
-	OFFSET(__TI_cpu, thread_info, cpu);
-	OFFSET(__TI_precount, thread_info, preempt_count);
-	OFFSET(__TI_user_timer, thread_info, user_timer);
-	OFFSET(__TI_system_timer, thread_info, system_timer);
-	OFFSET(__TI_last_break, thread_info, last_break);
+	OFFSET(__TI_flags, task_struct, thread_info.flags);
 	BLANK();
 	/* pt_regs offsets */
 	OFFSET(__PT_ARGS, pt_regs, args);
@@ -79,6 +74,8 @@ int main(void)
 	OFFSET(__VDSO_ECTG_OK, vdso_data, ectg_available);
 	OFFSET(__VDSO_TK_MULT, vdso_data, tk_mult);
 	OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift);
+	OFFSET(__VDSO_TS_DIR, vdso_data, ts_dir);
+	OFFSET(__VDSO_TS_END, vdso_data, ts_end);
 	OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
 	OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
 	OFFSET(__VDSO_CPU_NR, vdso_per_cpu_data, cpu_nr);
@@ -159,7 +156,6 @@ int main(void)
 	OFFSET(__LC_INT_CLOCK, lowcore, int_clock);
 	OFFSET(__LC_MCCK_CLOCK, lowcore, mcck_clock);
 	OFFSET(__LC_CURRENT, lowcore, current_task);
-	OFFSET(__LC_THREAD_INFO, lowcore, thread_info);
 	OFFSET(__LC_KERNEL_STACK, lowcore, kernel_stack);
 	OFFSET(__LC_ASYNC_STACK, lowcore, async_stack);
 	OFFSET(__LC_PANIC_STACK, lowcore, panic_stack);
@@ -173,6 +169,7 @@ int main(void)
 	OFFSET(__LC_PERCPU_OFFSET, lowcore, percpu_offset);
 	OFFSET(__LC_VDSO_PER_CPU, lowcore, vdso_per_cpu_data);
 	OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags);
+	OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count);
 	OFFSET(__LC_GMAP, lowcore, gmap);
 	OFFSET(__LC_PASTE, lowcore, paste);
 	/* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/compat_linux.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/compat_linux.c
--- linux-libre-4.9-gnu/arch/s390/kernel/compat_linux.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/compat_linux.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,7 +51,7 @@
 #include <linux/slab.h>
 
 #include <asm/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <net/scm.h>
 #include <net/sock.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/compat_signal.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/compat_signal.c
--- linux-libre-4.9-gnu/arch/s390/kernel/compat_signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/compat_signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/lowcore.h>
 #include <asm/switch_to.h>
 #include "compat_linux.h"
@@ -446,7 +446,7 @@ static int setup_frame32(struct ksignal
 		/* set extra registers only for synchronous signals */
 		regs->gprs[4] = regs->int_code & 127;
 		regs->gprs[5] = regs->int_parm_long;
-		regs->gprs[6] = task_thread_info(current)->last_break;
+		regs->gprs[6] = current->thread.last_break;
 	}
 
 	return 0;
@@ -523,7 +523,7 @@ static int setup_rt_frame32(struct ksign
 	regs->gprs[2] = ksig->sig;
 	regs->gprs[3] = (__force __u64) &frame->info;
 	regs->gprs[4] = (__force __u64) &frame->uc;
-	regs->gprs[5] = task_thread_info(current)->last_break;
+	regs->gprs[5] = current->thread.last_break;
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/debug.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/debug.c
--- linux-libre-4.9-gnu/arch/s390/kernel/debug.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/debug.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/sysctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/fs.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/dis.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/dis.c
--- linux-libre-4.9-gnu/arch/s390/kernel/dis.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/dis.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/dis.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/early.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/early.c
--- linux-libre-4.9-gnu/arch/s390/kernel/early.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/early.c	2017-02-12 16:03:20.000000000 -0500
@@ -293,6 +293,7 @@ static noinline __init void setup_lowcor
 	psw.addr = (unsigned long) s390_base_pgm_handler;
 	S390_lowcore.program_new_psw = psw;
 	s390_base_pgm_handler_fn = early_pgm_check_handler;
+	S390_lowcore.preempt_count = INIT_PREEMPT_COUNT;
 }
 
 static noinline __init void setup_facility_list(void)
@@ -391,7 +392,49 @@ static int __init cad_init(void)
 }
 early_initcall(cad_init);
 
-static __init void rescue_initrd(void)
+static __init void memmove_early(void *dst, const void *src, size_t n)
+{
+	unsigned long addr;
+	long incr;
+	psw_t old;
+
+	if (!n)
+		return;
+	incr = 1;
+	if (dst > src) {
+		incr = -incr;
+		dst += n - 1;
+		src += n - 1;
+	}
+	old = S390_lowcore.program_new_psw;
+	S390_lowcore.program_new_psw.mask = __extract_psw();
+	asm volatile(
+		"	larl	%[addr],1f\n"
+		"	stg	%[addr],%[psw_pgm_addr]\n"
+		"0:     mvc	0(1,%[dst]),0(%[src])\n"
+		"	agr	%[dst],%[incr]\n"
+		"	agr	%[src],%[incr]\n"
+		"	brctg	%[n],0b\n"
+		"1:\n"
+		: [addr] "=&d" (addr),
+		  [psw_pgm_addr] "=Q" (S390_lowcore.program_new_psw.addr),
+		  [dst] "+&a" (dst), [src] "+&a" (src),  [n] "+d" (n)
+		: [incr] "d" (incr)
+		: "cc", "memory");
+	S390_lowcore.program_new_psw = old;
+}
+
+static __init noinline void ipl_save_parameters(void)
+{
+	void *src, *dst;
+
+	src = (void *)(unsigned long) S390_lowcore.ipl_parmblock_ptr;
+	dst = (void *) IPL_PARMBLOCK_ORIGIN;
+	memmove_early(dst, src, PAGE_SIZE);
+	S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
+}
+
+static __init noinline void rescue_initrd(void)
 {
 #ifdef CONFIG_BLK_DEV_INITRD
 	unsigned long min_initrd_addr = (unsigned long) _end + (4UL << 20);
@@ -405,7 +448,7 @@ static __init void rescue_initrd(void)
 		return;
 	if (INITRD_START >= min_initrd_addr)
 		return;
-	memmove((void *) min_initrd_addr, (void *) INITRD_START, INITRD_SIZE);
+	memmove_early((void *) min_initrd_addr, (void *) INITRD_START, INITRD_SIZE);
 	INITRD_START = min_initrd_addr;
 #endif
 }
@@ -467,7 +510,8 @@ void __init startup_init(void)
 	ipl_save_parameters();
 	rescue_initrd();
 	clear_bss_section();
-	ptff_init();
+	ipl_verify_parameters();
+	time_early_init();
 	init_kernel_storage_key();
 	lockdep_off();
 	setup_lowcore_early();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/entry.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/entry.S
--- linux-libre-4.9-gnu/arch/s390/kernel/entry.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/entry.S	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@ __PT_R13     =	__PT_GPRS + 104
 __PT_R14     =	__PT_GPRS + 112
 __PT_R15     =	__PT_GPRS + 120
 
-STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
+STACK_SHIFT = PAGE_SHIFT + THREAD_SIZE_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
 
@@ -123,8 +123,14 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 
 	.macro	LAST_BREAK scratch
 	srag	\scratch,%r10,23
+#ifdef CONFIG_HAVE_MARCH_Z990_FEATURES
 	jz	.+10
-	stg	%r10,__TI_last_break(%r12)
+	stg	%r10,__TASK_thread+__THREAD_last_break(%r12)
+#else
+	jz	.+14
+	lghi	\scratch,__TASK_thread
+	stg	%r10,__THREAD_last_break(\scratch,%r12)
+#endif
 	.endm
 
 	.macro REENABLE_IRQS
@@ -186,14 +192,13 @@ ENTRY(__switch_to)
 	stmg	%r6,%r15,__SF_GPRS(%r15)	# store gprs of prev task
 	lgr	%r1,%r2
 	aghi	%r1,__TASK_thread		# thread_struct of prev task
-	lg	%r5,__TASK_thread_info(%r3)	# get thread_info of next
+	lg	%r5,__TASK_stack(%r3)		# start of kernel stack of next
 	stg	%r15,__THREAD_ksp(%r1)		# store kernel stack of prev
 	lgr	%r1,%r3
 	aghi	%r1,__TASK_thread		# thread_struct of next task
 	lgr	%r15,%r5
 	aghi	%r15,STACK_INIT			# end of kernel stack of next
 	stg	%r3,__LC_CURRENT		# store task struct of next
-	stg	%r5,__LC_THREAD_INFO		# store thread info of next
 	stg	%r15,__LC_KERNEL_STACK		# store end of kernel stack
 	lg	%r15,__THREAD_ksp(%r1)		# load kernel stack of next
 	/* c4 is used in guest detection: arch/s390/kernel/perf_cpum_sf.c */
@@ -274,7 +279,7 @@ ENTRY(system_call)
 .Lsysc_stmg:
 	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
 	lg	%r10,__LC_LAST_BREAK
-	lg	%r12,__LC_THREAD_INFO
+	lg	%r12,__LC_CURRENT
 	lghi	%r14,_PIF_SYSCALL
 .Lsysc_per:
 	lg	%r15,__LC_KERNEL_STACK
@@ -288,7 +293,13 @@ ENTRY(system_call)
 	mvc	__PT_INT_CODE(4,%r11),__LC_SVC_ILC
 	stg	%r14,__PT_FLAGS(%r11)
 .Lsysc_do_svc:
-	lg	%r10,__TI_sysc_table(%r12)	# address of system call table
+	# load address of system call table
+#ifdef CONFIG_HAVE_MARCH_Z990_FEATURES
+	lg	%r10,__TASK_thread+__THREAD_sysc_table(%r12)
+#else
+	lghi	%r13,__TASK_thread
+	lg	%r10,__THREAD_sysc_table(%r13,%r12)
+#endif
 	llgh	%r8,__PT_INT_CODE+2(%r11)
 	slag	%r8,%r8,2			# shift and test for svc 0
 	jnz	.Lsysc_nr_ok
@@ -389,7 +400,6 @@ ENTRY(system_call)
 	TSTMSK	__PT_FLAGS(%r11),_PIF_SYSCALL
 	jno	.Lsysc_return
 	lmg	%r2,%r7,__PT_R2(%r11)	# load svc arguments
-	lg	%r10,__TI_sysc_table(%r12)	# address of system call table
 	lghi	%r8,0			# svc 0 returns -ENOSYS
 	llgh	%r1,__PT_INT_CODE+2(%r11)	# load new svc number
 	cghi	%r1,NR_syscalls
@@ -457,7 +467,7 @@ ENTRY(system_call)
 #
 ENTRY(ret_from_fork)
 	la	%r11,STACK_FRAME_OVERHEAD(%r15)
-	lg	%r12,__LC_THREAD_INFO
+	lg	%r12,__LC_CURRENT
 	brasl	%r14,schedule_tail
 	TRACE_IRQS_ON
 	ssm	__LC_SVC_NEW_PSW	# reenable interrupts
@@ -478,7 +488,7 @@ ENTRY(pgm_check_handler)
 	stpt	__LC_SYNC_ENTER_TIMER
 	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
 	lg	%r10,__LC_LAST_BREAK
-	lg	%r12,__LC_THREAD_INFO
+	lg	%r12,__LC_CURRENT
 	larl	%r13,cleanup_critical
 	lmg	%r8,%r9,__LC_PGM_OLD_PSW
 	tmhh	%r8,0x0001		# test problem state bit
@@ -501,7 +511,7 @@ ENTRY(pgm_check_handler)
 2:	LAST_BREAK %r14
 	UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
 	lg	%r15,__LC_KERNEL_STACK
-	lg	%r14,__TI_task(%r12)
+	lgr	%r14,%r12
 	aghi	%r14,__TASK_thread	# pointer to thread_struct
 	lghi	%r13,__LC_PGM_TDB
 	tm	__LC_PGM_ILC+2,0x02	# check for transaction abort
@@ -567,7 +577,7 @@ ENTRY(io_int_handler)
 	stpt	__LC_ASYNC_ENTER_TIMER
 	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
 	lg	%r10,__LC_LAST_BREAK
-	lg	%r12,__LC_THREAD_INFO
+	lg	%r12,__LC_CURRENT
 	larl	%r13,cleanup_critical
 	lmg	%r8,%r9,__LC_IO_OLD_PSW
 	SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
@@ -626,7 +636,7 @@ ENTRY(io_int_handler)
 	jo	.Lio_work_user		# yes -> do resched & signal
 #ifdef CONFIG_PREEMPT
 	# check for preemptive scheduling
-	icm	%r0,15,__TI_precount(%r12)
+	icm	%r0,15,__LC_PREEMPT_COUNT
 	jnz	.Lio_restore		# preemption is disabled
 	TSTMSK	__TI_flags(%r12),_TIF_NEED_RESCHED
 	jno	.Lio_restore
@@ -741,7 +751,7 @@ ENTRY(ext_int_handler)
 	stpt	__LC_ASYNC_ENTER_TIMER
 	stmg	%r8,%r15,__LC_SAVE_AREA_ASYNC
 	lg	%r10,__LC_LAST_BREAK
-	lg	%r12,__LC_THREAD_INFO
+	lg	%r12,__LC_CURRENT
 	larl	%r13,cleanup_critical
 	lmg	%r8,%r9,__LC_EXT_OLD_PSW
 	SWITCH_ASYNC __LC_SAVE_AREA_ASYNC,__LC_ASYNC_ENTER_TIMER
@@ -798,13 +808,10 @@ ENTRY(save_fpu_regs)
 	TSTMSK	__LC_CPU_FLAGS,_CIF_FPU
 	bor	%r14
 	stfpc	__THREAD_FPU_fpc(%r2)
-.Lsave_fpu_regs_fpc_end:
 	lg	%r3,__THREAD_FPU_regs(%r2)
 	TSTMSK	__LC_MACHINE_FLAGS,MACHINE_FLAG_VX
 	jz	.Lsave_fpu_regs_fp	  # no -> store FP regs
-.Lsave_fpu_regs_vx_low:
 	VSTM	%v0,%v15,0,%r3		  # vstm 0,15,0(3)
-.Lsave_fpu_regs_vx_high:
 	VSTM	%v16,%v31,256,%r3	  # vstm 16,31,256(3)
 	j	.Lsave_fpu_regs_done	  # -> set CIF_FPU flag
 .Lsave_fpu_regs_fp:
@@ -851,9 +858,7 @@ load_fpu_regs:
 	TSTMSK	__LC_MACHINE_FLAGS,MACHINE_FLAG_VX
 	lg	%r4,__THREAD_FPU_regs(%r4)	# %r4 <- reg save area
 	jz	.Lload_fpu_regs_fp		# -> no VX, load FP regs
-.Lload_fpu_regs_vx:
 	VLM	%v0,%v15,0,%r4
-.Lload_fpu_regs_vx_high:
 	VLM	%v16,%v31,256,%r4
 	j	.Lload_fpu_regs_done
 .Lload_fpu_regs_fp:
@@ -889,7 +894,7 @@ ENTRY(mcck_int_handler)
 	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
 	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
 	lg	%r10,__LC_LAST_BREAK
-	lg	%r12,__LC_THREAD_INFO
+	lg	%r12,__LC_CURRENT
 	larl	%r13,cleanup_critical
 	lmg	%r8,%r9,__LC_MCK_OLD_PSW
 	TSTMSK	__LC_MCCK_CODE,MCCK_CODE_SYSTEM_DAMAGE
@@ -948,7 +953,7 @@ ENTRY(mcck_int_handler)
 
 .Lmcck_panic:
 	lg	%r15,__LC_PANIC_STACK
-	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
+	la	%r11,STACK_FRAME_OVERHEAD(%r15)
 	j	.Lmcck_skip
 
 #
@@ -1085,7 +1090,7 @@ cleanup_critical:
 	jhe	0f
 	# set up saved registers r10 and r12
 	stg	%r10,16(%r11)		# r10 last break
-	stg	%r12,32(%r11)		# r12 thread-info pointer
+	stg	%r12,32(%r11)		# r12 task struct pointer
 0:	# check if the user time update has been done
 	clg	%r9,BASED(.Lcleanup_system_call_insn+24)
 	jh	0f
@@ -1106,7 +1111,9 @@ cleanup_critical:
 	lg	%r9,16(%r11)
 	srag	%r9,%r9,23
 	jz	0f
-	mvc	__TI_last_break(8,%r12),16(%r11)
+	lgr	%r9,%r12
+	aghi	%r9,__TASK_thread
+	mvc	__THREAD_last_break(8,%r9),16(%r11)
 0:	# set up saved register r11
 	lg	%r15,__LC_KERNEL_STACK
 	la	%r9,STACK_FRAME_OVERHEAD(%r15)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/head64.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/head64.S
--- linux-libre-4.9-gnu/arch/s390/kernel/head64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/head64.S	2017-02-12 16:03:20.000000000 -0500
@@ -32,11 +32,10 @@ ENTRY(startup_continue)
 #
 # Setup stack
 #
-	larl	%r15,init_thread_union
-	stg	%r15,__LC_THREAD_INFO	# cache thread info in lowcore
-	lg	%r14,__TI_task(%r15)	# cache current in lowcore
+	larl	%r14,init_task
 	stg	%r14,__LC_CURRENT
-	aghi	%r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE
+	larl	%r15,init_thread_union
+	aghi	%r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER) # init_task_union + THREAD_SIZE
 	stg	%r15,__LC_KERNEL_STACK	# set end of kernel stack
 	aghi	%r15,-160
 #
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/head.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/head.S
--- linux-libre-4.9-gnu/arch/s390/kernel/head.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/head.S	2017-02-12 16:03:20.000000000 -0500
@@ -315,7 +315,7 @@ ENTRY(startup_kdump)
 	jg	startup_continue
 
 .Lstack:
-	.long	0x8000 + (1<<(PAGE_SHIFT+THREAD_ORDER))
+	.long	0x8000 + (1<<(PAGE_SHIFT+THREAD_SIZE_ORDER))
 	.align	8
 6:	.long	0x7fffffff,0xffffffff
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/ipl.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/ipl.c
--- linux-libre-4.9-gnu/arch/s390/kernel/ipl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/ipl.c	2017-02-12 16:03:20.000000000 -0500
@@ -1991,10 +1991,9 @@ void __init ipl_update_parameters(void)
 		diag308_set_works = 1;
 }
 
-void __init ipl_save_parameters(void)
+void __init ipl_verify_parameters(void)
 {
 	struct cio_iplinfo iplinfo;
-	void *src, *dst;
 
 	if (cio_get_iplinfo(&iplinfo))
 		return;
@@ -2005,10 +2004,6 @@ void __init ipl_save_parameters(void)
 	if (!iplinfo.is_qdio)
 		return;
 	ipl_flags |= IPL_PARMBLOCK_VALID;
-	src = (void *)(unsigned long)S390_lowcore.ipl_parmblock_ptr;
-	dst = (void *)IPL_PARMBLOCK_ORIGIN;
-	memmove(dst, src, PAGE_SIZE);
-	S390_lowcore.ipl_parmblock_ptr = IPL_PARMBLOCK_ORIGIN;
 }
 
 static LIST_HEAD(rcall);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/irq.c
--- linux-libre-4.9-gnu/arch/s390/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -168,7 +168,7 @@ void do_softirq_own_stack(void)
 	old = current_stack_pointer();
 	/* Check against async. stack address range. */
 	new = S390_lowcore.async_stack;
-	if (((new - old) >> (PAGE_SHIFT + THREAD_ORDER)) != 0) {
+	if (((new - old) >> (PAGE_SHIFT + THREAD_SIZE_ORDER)) != 0) {
 		/* Need to switch to the async. stack. */
 		new -= STACK_FRAME_OVERHEAD;
 		((struct stack_frame *) new)->back_chain = old;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/kprobes.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/kprobes.c
--- linux-libre-4.9-gnu/arch/s390/kernel/kprobes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/kprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <linux/ftrace.h>
 #include <asm/cacheflush.h>
 #include <asm/sections.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/dis.h>
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/lgr.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/lgr.c
--- linux-libre-4.9-gnu/arch/s390/kernel/lgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/lgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,8 @@
  * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/export.h>
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <asm/facility.h>
@@ -183,4 +184,4 @@ static int __init lgr_init(void)
 	lgr_timer_set();
 	return 0;
 }
-module_init(lgr_init);
+device_initcall(lgr_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/Makefile linux-libre-4.10-rc8-gnu/arch/s390/kernel/Makefile
--- linux-libre-4.9-gnu/arch/s390/kernel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,20 +2,47 @@
 # Makefile for the linux kernel.
 #
 
-KCOV_INSTRUMENT_early.o := n
-KCOV_INSTRUMENT_sclp.o := n
-KCOV_INSTRUMENT_als.o := n
-
 ifdef CONFIG_FUNCTION_TRACER
-# Don't trace early setup code and tracing code
-CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE)
-CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)
+
+# Do not trace tracer code
+CFLAGS_REMOVE_ftrace.o	= $(CC_FLAGS_FTRACE)
+
+# Do not trace early setup code
+CFLAGS_REMOVE_als.o	= $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_early.o	= $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_sclp.o	= $(CC_FLAGS_FTRACE)
+
+endif
+
+GCOV_PROFILE_als.o	:= n
+GCOV_PROFILE_early.o	:= n
+GCOV_PROFILE_sclp.o	:= n
+
+KCOV_INSTRUMENT_als.o	:= n
+KCOV_INSTRUMENT_early.o	:= n
+KCOV_INSTRUMENT_sclp.o	:= n
+
+UBSAN_SANITIZE_als.o	:= n
+UBSAN_SANITIZE_early.o	:= n
+UBSAN_SANITIZE_sclp.o	:= n
+
+#
+# Use -march=z900 for sclp.c and als.c to be able to print an error
+# message if the kernel is started on a machine which is too old
+#
+ifneq ($(CC_FLAGS_MARCH),-march=z900)
+CFLAGS_REMOVE_als.o	+= $(CC_FLAGS_MARCH)
+CFLAGS_als.o		+= -march=z900
+CFLAGS_REMOVE_sclp.o	+= $(CC_FLAGS_MARCH)
+CFLAGS_sclp.o		+= -march=z900
+AFLAGS_REMOVE_head.o	+= $(CC_FLAGS_MARCH)
+AFLAGS_head.o		+= -march=z900
 endif
 
 #
 # Passing null pointers is ok for smp code, since we access the lowcore here.
 #
-CFLAGS_smp.o	:= -Wno-nonnull
+CFLAGS_smp.o		:= -Wno-nonnull
 
 #
 # Disable tailcall optimizations for stack / callchain walking functions
@@ -30,27 +57,7 @@ CFLAGS_dumpstack.o	+= -fno-optimize-sibl
 #
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
-CFLAGS_sysinfo.o += -w
-
-#
-# Use -march=z900 for sclp.c and als.c to be able to print an error
-# message if the kernel is started on a machine which is too old
-#
-CFLAGS_REMOVE_sclp.o = $(CC_FLAGS_FTRACE)
-CFLAGS_REMOVE_als.o = $(CC_FLAGS_FTRACE)
-ifneq ($(CC_FLAGS_MARCH),-march=z900)
-CFLAGS_REMOVE_sclp.o	+= $(CC_FLAGS_MARCH)
-CFLAGS_sclp.o		+= -march=z900
-CFLAGS_REMOVE_als.o	+= $(CC_FLAGS_MARCH)
-CFLAGS_als.o		+= -march=z900
-AFLAGS_REMOVE_head.o	+= $(CC_FLAGS_MARCH)
-AFLAGS_head.o		+= -march=z900
-endif
-GCOV_PROFILE_sclp.o := n
-GCOV_PROFILE_als.o := n
-UBSAN_SANITIZE_als.o := n
-UBSAN_SANITIZE_early.o := n
-UBSAN_SANITIZE_sclp.o := n
+CFLAGS_sysinfo.o	+= -w
 
 obj-y	:= traps.o time.o process.o base.o early.o setup.o idle.o vtime.o
 obj-y	+= processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/nmi.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/nmi.c
--- linux-libre-4.9-gnu/arch/s390/kernel/nmi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/nmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,7 @@ static int notrace s390_validate_registe
 {
 	int kill_task;
 	u64 zero;
-	void *fpt_save_area, *fpt_creg_save_area;
+	void *fpt_save_area;
 
 	kill_task = 0;
 	zero = 0;
@@ -130,7 +130,6 @@ static int notrace s390_validate_registe
 			kill_task = 1;
 	}
 	fpt_save_area = &S390_lowcore.floating_pt_save_area;
-	fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
 	if (!mci.fc) {
 		/*
 		 * Floating point control register can't be restored.
@@ -142,11 +141,13 @@ static int notrace s390_validate_registe
 		 */
 		if (S390_lowcore.fpu_flags & KERNEL_FPC)
 			s390_handle_damage();
-		asm volatile("lfpc 0(%0)" : : "a" (&zero), "m" (zero));
+		asm volatile("lfpc %0" : : "Q" (zero));
 		if (!test_cpu_flag(CIF_FPU))
 			kill_task = 1;
-	} else
-		asm volatile("lfpc 0(%0)" : : "a" (fpt_creg_save_area));
+	} else {
+		asm volatile("lfpc %0"
+			     : : "Q" (S390_lowcore.fpt_creg_save_area));
+	}
 
 	if (!MACHINE_HAS_VX) {
 		/* Validate floating point registers */
@@ -167,7 +168,7 @@ static int notrace s390_validate_registe
 			"	ld	13,104(%0)\n"
 			"	ld	14,112(%0)\n"
 			"	ld	15,120(%0)\n"
-			: : "a" (fpt_save_area));
+			: : "a" (fpt_save_area) : "memory");
 	} else {
 		/* Validate vector registers */
 		union ctlreg0 cr0;
@@ -217,7 +218,7 @@ static int notrace s390_validate_registe
 	} else {
 		asm volatile(
 			"	lctlg	0,15,0(%0)"
-			: : "a" (&S390_lowcore.cregs_save_area));
+			: : "a" (&S390_lowcore.cregs_save_area) : "memory");
 	}
 	/*
 	 * We don't even try to validate the TOD register, since we simply
@@ -234,9 +235,9 @@ static int notrace s390_validate_registe
 			: : : "0", "cc");
 	else
 		asm volatile(
-			"	l	0,0(%0)\n"
+			"	l	0,%0\n"
 			"	sckpf"
-			: : "a" (&S390_lowcore.tod_progreg_save_area)
+			: : "Q" (S390_lowcore.tod_progreg_save_area)
 			: "0", "cc");
 	/* Validate clock comparator register */
 	set_clock_comparator(S390_lowcore.clock_comparator);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/perf_cpum_cf.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/perf_cpum_cf.c
--- linux-libre-4.9-gnu/arch/s390/kernel/perf_cpum_cf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/perf_cpum_cf.c	2017-02-12 16:03:20.000000000 -0500
@@ -711,7 +711,7 @@ static int __init cpumf_pmu_init(void)
 		return rc;
 	}
 	return cpuhp_setup_state(CPUHP_AP_PERF_S390_CF_ONLINE,
-				 "AP_PERF_S390_CF_ONLINE",
+				 "perf/s390/cf:online",
 				 s390_pmu_online_cpu, s390_pmu_offline_cpu);
 }
 early_initcall(cpumf_pmu_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/perf_cpum_sf.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/perf_cpum_sf.c
--- linux-libre-4.9-gnu/arch/s390/kernel/perf_cpum_sf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/perf_cpum_sf.c	2017-02-12 16:03:20.000000000 -0500
@@ -995,39 +995,36 @@ static int perf_push_sample(struct perf_
 	regs.int_parm = CPU_MF_INT_SF_PRA;
 	sde_regs = (struct perf_sf_sde_regs *) &regs.int_parm_long;
 
-	regs.psw.addr = sfr->basic.ia;
-	if (sfr->basic.T)
-		regs.psw.mask |= PSW_MASK_DAT;
-	if (sfr->basic.W)
-		regs.psw.mask |= PSW_MASK_WAIT;
-	if (sfr->basic.P)
-		regs.psw.mask |= PSW_MASK_PSTATE;
-	switch (sfr->basic.AS) {
-	case 0x0:
-		regs.psw.mask |= PSW_ASC_PRIMARY;
-		break;
-	case 0x1:
-		regs.psw.mask |= PSW_ASC_ACCREG;
-		break;
-	case 0x2:
-		regs.psw.mask |= PSW_ASC_SECONDARY;
-		break;
-	case 0x3:
-		regs.psw.mask |= PSW_ASC_HOME;
-		break;
-	}
+	psw_bits(regs.psw).ia = sfr->basic.ia;
+	psw_bits(regs.psw).t  = sfr->basic.T;
+	psw_bits(regs.psw).w  = sfr->basic.W;
+	psw_bits(regs.psw).p  = sfr->basic.P;
+	psw_bits(regs.psw).as = sfr->basic.AS;
 
 	/*
-	 * A non-zero guest program parameter indicates a guest
-	 * sample.
-	 * Note that some early samples or samples from guests without
+	 * Use the hardware provided configuration level to decide if the
+	 * sample belongs to a guest or host. If that is not available,
+	 * fall back to the following heuristics:
+	 * A non-zero guest program parameter always indicates a guest
+	 * sample. Some early samples or samples from guests without
 	 * lpp usage would be misaccounted to the host. We use the asn
-	 * value as a heuristic to detect most of these guest samples.
-	 * If the value differs from the host hpp value, we assume
-	 * it to be a KVM guest.
+	 * value as an addon heuristic to detect most of these guest samples.
+	 * If the value differs from the host hpp value, we assume to be a
+	 * KVM guest.
 	 */
-	if (sfr->basic.gpp || sfr->basic.prim_asn != (u16) sfr->basic.hpp)
+	switch (sfr->basic.CL) {
+	case 1: /* logical partition */
+		sde_regs->in_guest = 0;
+		break;
+	case 2: /* virtual machine */
 		sde_regs->in_guest = 1;
+		break;
+	default: /* old machine, use heuristics */
+		if (sfr->basic.gpp ||
+		    sfr->basic.prim_asn != (u16)sfr->basic.hpp)
+			sde_regs->in_guest = 1;
+		break;
+	}
 
 	overflow = 0;
 	if (perf_exclude_event(event, &regs, sde_regs))
@@ -1626,7 +1623,7 @@ static int __init init_cpum_sampling_pmu
 		goto out;
 	}
 
-	cpuhp_setup_state(CPUHP_AP_PERF_S390_SF_ONLINE, "AP_PERF_S390_SF_ONLINE",
+	cpuhp_setup_state(CPUHP_AP_PERF_S390_SF_ONLINE, "perf/s390/sf:online",
 			  s390_pmu_sf_online_cpu, s390_pmu_sf_offline_cpu);
 out:
 	return err;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/process.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/process.c
--- linux-libre-4.9-gnu/arch/s390/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -103,7 +103,6 @@ int arch_dup_task_struct(struct task_str
 int copy_thread(unsigned long clone_flags, unsigned long new_stackp,
 		unsigned long arg, struct task_struct *p)
 {
-	struct thread_info *ti;
 	struct fake_frame
 	{
 		struct stack_frame sf;
@@ -121,9 +120,8 @@ int copy_thread(unsigned long clone_flag
 	memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
 	clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
 	/* Initialize per thread user and system timer values */
-	ti = task_thread_info(p);
-	ti->user_timer = 0;
-	ti->system_timer = 0;
+	p->thread.user_timer = 0;
+	p->thread.system_timer = 0;
 
 	frame->sf.back_chain = 0;
 	/* new return point is ret_from_fork */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/processor.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/processor.c
--- linux-libre-4.9-gnu/arch/s390/kernel/processor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/processor.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@ void s390_update_cpu_mhz(void)
 		on_each_cpu(update_cpu_mhz, NULL, 0);
 }
 
-void notrace cpu_relax(void)
+void notrace cpu_relax_yield(void)
 {
 	if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) {
 		diag_stat_inc(DIAG_STAT_X044);
@@ -61,7 +61,7 @@ void notrace cpu_relax(void)
 	}
 	barrier();
 }
-EXPORT_SYMBOL(cpu_relax);
+EXPORT_SYMBOL(cpu_relax_yield);
 
 /*
  * cpu_init - initializes state that is per-CPU.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/s390/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/switch_to.h>
 #include "entry.h"
@@ -461,7 +461,7 @@ long arch_ptrace(struct task_struct *chi
 		}
 		return 0;
 	case PTRACE_GET_LAST_BREAK:
-		put_user(task_thread_info(child)->last_break,
+		put_user(child->thread.last_break,
 			 (unsigned long __user *) data);
 		return 0;
 	case PTRACE_ENABLE_TE:
@@ -811,7 +811,7 @@ long compat_arch_ptrace(struct task_stru
 		}
 		return 0;
 	case PTRACE_GET_LAST_BREAK:
-		put_user(task_thread_info(child)->last_break,
+		put_user(child->thread.last_break,
 			 (unsigned int __user *) data);
 		return 0;
 	}
@@ -963,6 +963,11 @@ static int s390_fpregs_set(struct task_s
 	if (target == current)
 		save_fpu_regs();
 
+	if (MACHINE_HAS_VX)
+		convert_vx_to_fp(fprs, target->thread.fpu.vxrs);
+	else
+		memcpy(&fprs, target->thread.fpu.fprs, sizeof(fprs));
+
 	/* If setting FPC, must validate it first. */
 	if (count > 0 && pos < offsetof(s390_fp_regs, fprs)) {
 		u32 ufpc[2] = { target->thread.fpu.fpc, 0 };
@@ -997,10 +1002,10 @@ static int s390_last_break_get(struct ta
 	if (count > 0) {
 		if (kbuf) {
 			unsigned long *k = kbuf;
-			*k = task_thread_info(target)->last_break;
+			*k = target->thread.last_break;
 		} else {
 			unsigned long  __user *u = ubuf;
-			if (__put_user(task_thread_info(target)->last_break, u))
+			if (__put_user(target->thread.last_break, u))
 				return -EFAULT;
 		}
 	}
@@ -1067,6 +1072,9 @@ static int s390_vxrs_low_set(struct task
 	if (target == current)
 		save_fpu_regs();
 
+	for (i = 0; i < __NUM_VXRS_LOW; i++)
+		vxrs[i] = *((__u64 *)(target->thread.fpu.vxrs + i) + 1);
+
 	rc = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vxrs, 0, -1);
 	if (rc == 0)
 		for (i = 0; i < __NUM_VXRS_LOW; i++)
@@ -1113,7 +1121,7 @@ static int s390_system_call_get(struct t
 				unsigned int pos, unsigned int count,
 				void *kbuf, void __user *ubuf)
 {
-	unsigned int *data = &task_thread_info(target)->system_call;
+	unsigned int *data = &target->thread.system_call;
 	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				   data, 0, sizeof(unsigned int));
 }
@@ -1123,7 +1131,7 @@ static int s390_system_call_set(struct t
 				unsigned int pos, unsigned int count,
 				const void *kbuf, const void __user *ubuf)
 {
-	unsigned int *data = &task_thread_info(target)->system_call;
+	unsigned int *data = &target->thread.system_call;
 	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
 				  data, 0, sizeof(unsigned int));
 }
@@ -1327,7 +1335,7 @@ static int s390_compat_last_break_get(st
 	compat_ulong_t last_break;
 
 	if (count > 0) {
-		last_break = task_thread_info(target)->last_break;
+		last_break = target->thread.last_break;
 		if (kbuf) {
 			unsigned long *k = kbuf;
 			*k = last_break;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/setup.c
--- linux-libre-4.9-gnu/arch/s390/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/root_dev.h>
 #include <linux/console.h>
 #include <linux/kernel_stat.h>
+#include <linux/dma-contiguous.h>
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/pfn.h>
@@ -303,7 +304,7 @@ static void __init setup_lowcore(void)
 	 * Setup lowcore for boot cpu
 	 */
 	BUILD_BUG_ON(sizeof(struct lowcore) != LC_PAGES * 4096);
-	lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
+	lc = memblock_virt_alloc_low(sizeof(*lc), sizeof(*lc));
 	lc->restart_psw.mask = PSW_KERNEL_BITS;
 	lc->restart_psw.addr = (unsigned long) restart_int_handler;
 	lc->external_new_psw.mask = PSW_KERNEL_BITS |
@@ -324,15 +325,15 @@ static void __init setup_lowcore(void)
 	lc->kernel_stack = ((unsigned long) &init_thread_union)
 		+ THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
 	lc->async_stack = (unsigned long)
-		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0)
+		memblock_virt_alloc(ASYNC_SIZE, ASYNC_SIZE)
 		+ ASYNC_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
 	lc->panic_stack = (unsigned long)
-		__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0)
+		memblock_virt_alloc(PAGE_SIZE, PAGE_SIZE)
 		+ PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
-	lc->current_task = (unsigned long) init_thread_union.thread_info.task;
-	lc->thread_info = (unsigned long) &init_thread_union;
+	lc->current_task = (unsigned long)&init_task;
 	lc->lpp = LPP_MAGIC;
 	lc->machine_flags = S390_lowcore.machine_flags;
+	lc->preempt_count = S390_lowcore.preempt_count;
 	lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
 	memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
 	       MAX_FACILITY_BIT/8);
@@ -349,7 +350,7 @@ static void __init setup_lowcore(void)
 	lc->last_update_timer = S390_lowcore.last_update_timer;
 	lc->last_update_clock = S390_lowcore.last_update_clock;
 
-	restart_stack = __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0);
+	restart_stack = memblock_virt_alloc(ASYNC_SIZE, ASYNC_SIZE);
 	restart_stack += ASYNC_SIZE;
 
 	/*
@@ -412,7 +413,7 @@ static void __init setup_resources(void)
 	bss_resource.end = (unsigned long) &__bss_stop - 1;
 
 	for_each_memblock(memory, reg) {
-		res = alloc_bootmem_low(sizeof(*res));
+		res = memblock_virt_alloc(sizeof(*res), 8);
 		res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM;
 
 		res->name = "System RAM";
@@ -426,7 +427,7 @@ static void __init setup_resources(void)
 			    std_res->start > res->end)
 				continue;
 			if (std_res->end > res->end) {
-				sub_res = alloc_bootmem_low(sizeof(*sub_res));
+				sub_res = memblock_virt_alloc(sizeof(*sub_res), 8);
 				*sub_res = *std_res;
 				sub_res->end = res->end;
 				std_res->start = res->end + 1;
@@ -445,7 +446,7 @@ static void __init setup_resources(void)
 	 * part of the System RAM resource.
 	 */
 	if (crashk_res.end) {
-		memblock_add(crashk_res.start, resource_size(&crashk_res));
+		memblock_add_node(crashk_res.start, resource_size(&crashk_res), 0);
 		memblock_reserve(crashk_res.start, resource_size(&crashk_res));
 		insert_resource(&iomem_resource, &crashk_res);
 	}
@@ -484,7 +485,7 @@ static void __init setup_memory_end(void
 	max_pfn = max_low_pfn = PFN_DOWN(memory_end);
 	memblock_remove(memory_end, ULONG_MAX);
 
-	pr_notice("Max memory size: %luMB\n", memory_end >> 20);
+	pr_notice("The maximum memory size is %luMB\n", memory_end >> 20);
 }
 
 static void __init setup_vmcoreinfo(void)
@@ -649,7 +650,7 @@ static void __init check_initrd(void)
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (INITRD_START && INITRD_SIZE &&
 	    !memblock_is_region_memory(INITRD_START, INITRD_SIZE)) {
-		pr_err("initrd does not fit memory.\n");
+		pr_err("The initial RAM disk does not fit into the memory\n");
 		memblock_free(INITRD_START, INITRD_SIZE);
 		initrd_start = initrd_end = 0;
 	}
@@ -903,6 +904,7 @@ void __init setup_arch(char **cmdline_p)
 
 	setup_memory_end();
 	setup_memory();
+	dma_contiguous_reserve(memory_end);
 
 	check_initrd();
 	reserve_crashkernel();
@@ -921,6 +923,8 @@ void __init setup_arch(char **cmdline_p)
 	cpu_detect_mhz_feature();
         cpu_init();
 	numa_setup();
+	smp_detect_cpus();
+	topology_init_early();
 
 	/*
 	 * Create kernel page tables and switch to virtual addressing.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/signal.c
--- linux-libre-4.9-gnu/arch/s390/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/lowcore.h>
 #include <asm/switch_to.h>
 #include "entry.h"
@@ -359,7 +359,7 @@ static int setup_frame(int sig, struct k
 		/* set extra registers only for synchronous signals */
 		regs->gprs[4] = regs->int_code & 127;
 		regs->gprs[5] = regs->int_parm_long;
-		regs->gprs[6] = task_thread_info(current)->last_break;
+		regs->gprs[6] = current->thread.last_break;
 	}
 	return 0;
 }
@@ -430,7 +430,7 @@ static int setup_rt_frame(struct ksignal
 	regs->gprs[2] = ksig->sig;
 	regs->gprs[3] = (unsigned long) &frame->info;
 	regs->gprs[4] = (unsigned long) &frame->uc;
-	regs->gprs[5] = task_thread_info(current)->last_break;
+	regs->gprs[5] = current->thread.last_break;
 	return 0;
 }
 
@@ -467,13 +467,13 @@ void do_signal(struct pt_regs *regs)
 	 * the debugger may change all our registers, including the system
 	 * call information.
 	 */
-	current_thread_info()->system_call =
+	current->thread.system_call =
 		test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0;
 
 	if (get_signal(&ksig)) {
 		/* Whee!  Actually deliver the signal.  */
-		if (current_thread_info()->system_call) {
-			regs->int_code = current_thread_info()->system_call;
+		if (current->thread.system_call) {
+			regs->int_code = current->thread.system_call;
 			/* Check for system call restarting. */
 			switch (regs->gprs[2]) {
 			case -ERESTART_RESTARTBLOCK:
@@ -506,8 +506,8 @@ void do_signal(struct pt_regs *regs)
 
 	/* No handlers present - check for system call restart */
 	clear_pt_regs_flag(regs, PIF_SYSCALL);
-	if (current_thread_info()->system_call) {
-		regs->int_code = current_thread_info()->system_call;
+	if (current->thread.system_call) {
+		regs->int_code = current->thread.system_call;
 		switch (regs->gprs[2]) {
 		case -ERESTART_RESTARTBLOCK:
 			/* Restart with sys_restart_syscall */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/smp.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/smp.c
--- linux-libre-4.9-gnu/arch/s390/kernel/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/workqueue.h>
+#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -259,16 +260,14 @@ static void pcpu_prepare_secondary(struc
 static void pcpu_attach_task(struct pcpu *pcpu, struct task_struct *tsk)
 {
 	struct lowcore *lc = pcpu->lowcore;
-	struct thread_info *ti = task_thread_info(tsk);
 
 	lc->kernel_stack = (unsigned long) task_stack_page(tsk)
 		+ THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
-	lc->thread_info = (unsigned long) task_thread_info(tsk);
 	lc->current_task = (unsigned long) tsk;
 	lc->lpp = LPP_MAGIC;
 	lc->current_pid = tsk->pid;
-	lc->user_timer = ti->user_timer;
-	lc->system_timer = ti->system_timer;
+	lc->user_timer = tsk->thread.user_timer;
+	lc->system_timer = tsk->thread.system_timer;
 	lc->steal_timer = 0;
 }
 
@@ -368,10 +367,15 @@ int smp_find_processor_id(u16 address)
 	return -1;
 }
 
-int smp_vcpu_scheduled(int cpu)
+bool arch_vcpu_is_preempted(int cpu)
 {
-	return pcpu_running(pcpu_devices + cpu);
+	if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu))
+		return false;
+	if (pcpu_running(pcpu_devices + cpu))
+		return false;
+	return true;
 }
+EXPORT_SYMBOL(arch_vcpu_is_preempted);
 
 void smp_yield_cpu(int cpu)
 {
@@ -657,14 +661,12 @@ int smp_cpu_get_polarization(int cpu)
 	return pcpu_devices[cpu].polarization;
 }
 
-static struct sclp_core_info *smp_get_core_info(void)
+static void __ref smp_get_core_info(struct sclp_core_info *info, int early)
 {
 	static int use_sigp_detection;
-	struct sclp_core_info *info;
 	int address;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (info && (use_sigp_detection || sclp_get_core_info(info))) {
+	if (use_sigp_detection || sclp_get_core_info(info, early)) {
 		use_sigp_detection = 1;
 		for (address = 0;
 		     address < (SCLP_MAX_CORES << smp_cpu_mt_shift);
@@ -678,7 +680,6 @@ static struct sclp_core_info *smp_get_co
 		}
 		info->combined = info->configured;
 	}
-	return info;
 }
 
 static int smp_add_present_cpu(int cpu);
@@ -719,17 +720,15 @@ static int __smp_rescan_cpus(struct sclp
 	return nr;
 }
 
-static void __init smp_detect_cpus(void)
+void __init smp_detect_cpus(void)
 {
 	unsigned int cpu, mtid, c_cpus, s_cpus;
 	struct sclp_core_info *info;
 	u16 address;
 
 	/* Get CPU information */
-	info = smp_get_core_info();
-	if (!info)
-		panic("smp_detect_cpus failed to allocate memory\n");
-
+	info = memblock_virt_alloc(sizeof(*info), 8);
+	smp_get_core_info(info, 1);
 	/* Find boot CPU type */
 	if (sclp.has_core_type) {
 		address = stap();
@@ -765,7 +764,7 @@ static void __init smp_detect_cpus(void)
 	get_online_cpus();
 	__smp_rescan_cpus(info, 0);
 	put_online_cpus();
-	kfree(info);
+	memblock_free_early((unsigned long)info, sizeof(*info));
 }
 
 /*
@@ -802,7 +801,7 @@ int __cpu_up(unsigned int cpu, struct ta
 	pcpu = pcpu_devices + cpu;
 	if (pcpu->state != CPU_STATE_CONFIGURED)
 		return -EIO;
-	base = cpu - (cpu % (smp_cpu_mtid + 1));
+	base = smp_get_base_cpu(cpu);
 	for (i = 0; i <= smp_cpu_mtid; i++) {
 		if (base + i < nr_cpu_ids)
 			if (cpu_online(base + i))
@@ -902,7 +901,6 @@ void __init smp_prepare_cpus(unsigned in
 	/* request the 0x1202 external call external interrupt */
 	if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt))
 		panic("Couldn't request external interrupt 0x1202");
-	smp_detect_cpus();
 }
 
 void __init smp_prepare_boot_cpu(void)
@@ -968,7 +966,7 @@ static ssize_t cpu_configure_store(struc
 	rc = -EBUSY;
 	/* disallow configuration changes of online cpus and cpu 0 */
 	cpu = dev->id;
-	cpu -= cpu % (smp_cpu_mtid + 1);
+	cpu = smp_get_base_cpu(cpu);
 	if (cpu == 0)
 		goto out;
 	for (i = 0; i <= smp_cpu_mtid; i++)
@@ -1047,22 +1045,18 @@ static struct attribute_group cpu_online
 	.attrs = cpu_online_attrs,
 };
 
-static int smp_cpu_notify(struct notifier_block *self, unsigned long action,
-			  void *hcpu)
+static int smp_cpu_online(unsigned int cpu)
 {
-	unsigned int cpu = (unsigned int)(long)hcpu;
 	struct device *s = &per_cpu(cpu_device, cpu)->dev;
-	int err = 0;
 
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_ONLINE:
-		err = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
-		break;
-	case CPU_DEAD:
-		sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
-		break;
-	}
-	return notifier_from_errno(err);
+	return sysfs_create_group(&s->kobj, &cpu_online_attr_group);
+}
+static int smp_cpu_pre_down(unsigned int cpu)
+{
+	struct device *s = &per_cpu(cpu_device, cpu)->dev;
+
+	sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
+	return 0;
 }
 
 static int smp_add_present_cpu(int cpu)
@@ -1083,20 +1077,12 @@ static int smp_add_present_cpu(int cpu)
 	rc = sysfs_create_group(&s->kobj, &cpu_common_attr_group);
 	if (rc)
 		goto out_cpu;
-	if (cpu_online(cpu)) {
-		rc = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
-		if (rc)
-			goto out_online;
-	}
 	rc = topology_cpu_init(c);
 	if (rc)
 		goto out_topology;
 	return 0;
 
 out_topology:
-	if (cpu_online(cpu))
-		sysfs_remove_group(&s->kobj, &cpu_online_attr_group);
-out_online:
 	sysfs_remove_group(&s->kobj, &cpu_common_attr_group);
 out_cpu:
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1113,9 +1099,10 @@ int __ref smp_rescan_cpus(void)
 	struct sclp_core_info *info;
 	int nr;
 
-	info = smp_get_core_info();
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
+	smp_get_core_info(info, 0);
 	get_online_cpus();
 	mutex_lock(&smp_cpu_state_mutex);
 	nr = __smp_rescan_cpus(info, 1);
@@ -1149,17 +1136,15 @@ static int __init s390_smp_init(void)
 	if (rc)
 		return rc;
 #endif
-	cpu_notifier_register_begin();
 	for_each_present_cpu(cpu) {
 		rc = smp_add_present_cpu(cpu);
 		if (rc)
 			goto out;
 	}
 
-	__hotcpu_notifier(smp_cpu_notify, 0);
-
+	rc = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "s390/smp:online",
+			       smp_cpu_online, smp_cpu_pre_down);
 out:
-	cpu_notifier_register_done();
 	return rc;
 }
 subsys_initcall(s390_smp_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/swsusp.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/swsusp.S
--- linux-libre-4.9-gnu/arch/s390/kernel/swsusp.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/swsusp.S	2017-02-12 16:03:20.000000000 -0500
@@ -194,7 +194,7 @@ pgm_check_entry:
 
 	/* Suspend CPU not available -> panic */
 	larl	%r15,init_thread_union
-	ahi	%r15,1<<(PAGE_SHIFT+THREAD_ORDER)
+	ahi	%r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER)
 	larl	%r2,.Lpanic_string
 	larl	%r3,_sclp_print_early
 	lghi	%r1,0
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/sysinfo.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/sysinfo.c
--- linux-libre-4.9-gnu/arch/s390/kernel/sysinfo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/sysinfo.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,6 +56,20 @@ int stsi(void *sysinfo, int fc, int sel1
 }
 EXPORT_SYMBOL(stsi);
 
+static bool convert_ext_name(unsigned char encoding, char *name, size_t len)
+{
+	switch (encoding) {
+	case 1: /* EBCDIC */
+		EBCASC(name, len);
+		break;
+	case 2:	/* UTF-8 */
+		break;
+	default:
+		return false;
+	}
+	return true;
+}
+
 static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info)
 {
 	int i;
@@ -207,24 +221,19 @@ static void stsi_2_2_2(struct seq_file *
 		seq_printf(m, "LPAR CPUs S-MTID:     %d\n", info->mt_stid);
 		seq_printf(m, "LPAR CPUs PS-MTID:    %d\n", info->mt_psmtid);
 	}
+	if (convert_ext_name(info->vsne, info->ext_name, sizeof(info->ext_name))) {
+		seq_printf(m, "LPAR Extended Name:   %-.256s\n", info->ext_name);
+		seq_printf(m, "LPAR UUID:            %pUb\n", &info->uuid);
+	}
 }
 
 static void print_ext_name(struct seq_file *m, int lvl,
 			   struct sysinfo_3_2_2 *info)
 {
-	if (info->vm[lvl].ext_name_encoding == 0)
-		return;
-	if (info->ext_names[lvl][0] == 0)
-		return;
-	switch (info->vm[lvl].ext_name_encoding) {
-	case 1: /* EBCDIC */
-		EBCASC(info->ext_names[lvl], sizeof(info->ext_names[lvl]));
-		break;
-	case 2:	/* UTF-8 */
-		break;
-	default:
+	size_t len = sizeof(info->ext_names[lvl]);
+
+	if (!convert_ext_name(info->vm[lvl].evmne, info->ext_names[lvl], len))
 		return;
-	}
 	seq_printf(m, "VM%02d Extended Name:   %-.256s\n", lvl,
 		   info->ext_names[lvl]);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/sys_s390.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/sys_s390.c
--- linux-libre-4.9-gnu/arch/s390/kernel/sys_s390.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/sys_s390.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/personality.h>
 #include <linux/unistd.h>
 #include <linux/ipc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "entry.h"
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/time.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/time.c
--- linux-libre-4.9-gnu/arch/s390/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <linux/clockchips.h>
 #include <linux/gfp.h>
 #include <linux/kprobes.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/facility.h>
 #include <asm/delay.h>
 #include <asm/div64.h>
@@ -59,19 +59,27 @@ ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_no
 EXPORT_SYMBOL(s390_epoch_delta_notifier);
 
 unsigned char ptff_function_mask[16];
-unsigned long lpar_offset;
-unsigned long initial_leap_seconds;
+
+static unsigned long long lpar_offset;
+static unsigned long long initial_leap_seconds;
+static unsigned long long tod_steering_end;
+static long long tod_steering_delta;
 
 /*
  * Get time offsets with PTFF
  */
-void __init ptff_init(void)
+void __init time_early_init(void)
 {
 	struct ptff_qto qto;
 	struct ptff_qui qui;
 
+	/* Initialize TOD steering parameters */
+	tod_steering_end = sched_clock_base_cc;
+	vdso_data->ts_end = tod_steering_end;
+
 	if (!test_facility(28))
 		return;
+
 	ptff(&ptff_function_mask, sizeof(ptff_function_mask), PTFF_QAF);
 
 	/* get LPAR offset */
@@ -80,7 +88,7 @@ void __init ptff_init(void)
 
 	/* get initial leap seconds */
 	if (ptff_query(PTFF_QUI) && ptff(&qui, sizeof(qui), PTFF_QUI) == 0)
-		initial_leap_seconds = (unsigned long)
+		initial_leap_seconds = (unsigned long long)
 			((long) qui.old_leap * 4096000000L);
 }
 
@@ -123,18 +131,6 @@ void clock_comparator_work(void)
 	cd->event_handler(cd);
 }
 
-/*
- * Fixup the clock comparator.
- */
-static void fixup_clock_comparator(unsigned long long delta)
-{
-	/* If nobody is waiting there's nothing to fix. */
-	if (S390_lowcore.clock_comparator == -1ULL)
-		return;
-	S390_lowcore.clock_comparator += delta;
-	set_clock_comparator(S390_lowcore.clock_comparator);
-}
-
 static int s390_next_event(unsigned long delta,
 			   struct clock_event_device *evt)
 {
@@ -213,9 +209,23 @@ void read_boot_clock64(struct timespec64
 	tod_to_timeval(clock - TOD_UNIX_EPOCH, ts);
 }
 
-static cycle_t read_tod_clock(struct clocksource *cs)
+static u64 read_tod_clock(struct clocksource *cs)
 {
-	return get_tod_clock();
+	unsigned long long now, adj;
+
+	preempt_disable(); /* protect from changes to steering parameters */
+	now = get_tod_clock();
+	adj = tod_steering_end - now;
+	if (unlikely((s64) adj >= 0))
+		/*
+		 * manually steer by 1 cycle every 2^16 cycles. This
+		 * corresponds to shifting the tod delta by 15. 1s is
+		 * therefore steered in ~9h. The adjust will decrease
+		 * over time, until it finally reaches 0.
+		 */
+		now += (tod_steering_delta < 0) ? (adj >> 15) : -(adj >> 15);
+	preempt_enable();
+	return now;
 }
 
 static struct clocksource clocksource_tod = {
@@ -384,6 +394,55 @@ static inline int check_sync_clock(void)
 	return rc;
 }
 
+/*
+ * Apply clock delta to the global data structures.
+ * This is called once on the CPU that performed the clock sync.
+ */
+static void clock_sync_global(unsigned long long delta)
+{
+	unsigned long now, adj;
+	struct ptff_qto qto;
+
+	/* Fixup the monotonic sched clock. */
+	sched_clock_base_cc += delta;
+	/* Adjust TOD steering parameters. */
+	vdso_data->tb_update_count++;
+	now = get_tod_clock();
+	adj = tod_steering_end - now;
+	if (unlikely((s64) adj >= 0))
+		/* Calculate how much of the old adjustment is left. */
+		tod_steering_delta = (tod_steering_delta < 0) ?
+			-(adj >> 15) : (adj >> 15);
+	tod_steering_delta += delta;
+	if ((abs(tod_steering_delta) >> 48) != 0)
+		panic("TOD clock sync offset %lli is too large to drift\n",
+		      tod_steering_delta);
+	tod_steering_end = now + (abs(tod_steering_delta) << 15);
+	vdso_data->ts_dir = (tod_steering_delta < 0) ? 0 : 1;
+	vdso_data->ts_end = tod_steering_end;
+	vdso_data->tb_update_count++;
+	/* Update LPAR offset. */
+	if (ptff_query(PTFF_QTO) && ptff(&qto, sizeof(qto), PTFF_QTO) == 0)
+		lpar_offset = qto.tod_epoch_difference;
+	/* Call the TOD clock change notifier. */
+	atomic_notifier_call_chain(&s390_epoch_delta_notifier, 0, &delta);
+}
+
+/*
+ * Apply clock delta to the per-CPU data structures of this CPU.
+ * This is called for each online CPU after the call to clock_sync_global.
+ */
+static void clock_sync_local(unsigned long long delta)
+{
+	/* Add the delta to the clock comparator. */
+	if (S390_lowcore.clock_comparator != -1ULL) {
+		S390_lowcore.clock_comparator += delta;
+		set_clock_comparator(S390_lowcore.clock_comparator);
+	}
+	/* Adjust the last_update_clock time-stamp. */
+	S390_lowcore.last_update_clock += delta;
+}
+
 /* Single threaded workqueue used for stp sync events */
 static struct workqueue_struct *time_sync_wq;
 
@@ -397,31 +456,9 @@ static void __init time_init_wq(void)
 struct clock_sync_data {
 	atomic_t cpus;
 	int in_sync;
-	unsigned long long fixup_cc;
+	unsigned long long clock_delta;
 };
 
-static void clock_sync_cpu(struct clock_sync_data *sync)
-{
-	atomic_dec(&sync->cpus);
-	enable_sync_clock();
-	while (sync->in_sync == 0) {
-		__udelay(1);
-		/*
-		 * A different cpu changes *in_sync. Therefore use
-		 * barrier() to force memory access.
-		 */
-		barrier();
-	}
-	if (sync->in_sync != 1)
-		/* Didn't work. Clear per-cpu in sync bit again. */
-		disable_sync_clock(NULL);
-	/*
-	 * This round of TOD syncing is done. Set the clock comparator
-	 * to the next tick and let the processor continue.
-	 */
-	fixup_clock_comparator(sync->fixup_cc);
-}
-
 /*
  * Server Time Protocol (STP) code.
  */
@@ -523,54 +560,46 @@ void stp_queue_work(void)
 
 static int stp_sync_clock(void *data)
 {
-	static int first;
+	struct clock_sync_data *sync = data;
 	unsigned long long clock_delta;
-	struct clock_sync_data *stp_sync;
-	struct ptff_qto qto;
+	static int first;
 	int rc;
 
-	stp_sync = data;
-
-	if (xchg(&first, 1) == 1) {
-		/* Slave */
-		clock_sync_cpu(stp_sync);
-		return 0;
-	}
-
-	/* Wait until all other cpus entered the sync function. */
-	while (atomic_read(&stp_sync->cpus) != 0)
-		cpu_relax();
-
 	enable_sync_clock();
-
-	rc = 0;
-	if (stp_info.todoff[0] || stp_info.todoff[1] ||
-	    stp_info.todoff[2] || stp_info.todoff[3] ||
-	    stp_info.tmd != 2) {
-		rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0, &clock_delta);
-		if (rc == 0) {
-			/* fixup the monotonic sched clock */
-			sched_clock_base_cc += clock_delta;
-			if (ptff_query(PTFF_QTO) &&
-			    ptff(&qto, sizeof(qto), PTFF_QTO) == 0)
-				/* Update LPAR offset */
-				lpar_offset = qto.tod_epoch_difference;
-			atomic_notifier_call_chain(&s390_epoch_delta_notifier,
-						   0, &clock_delta);
-			stp_sync->fixup_cc = clock_delta;
-			fixup_clock_comparator(clock_delta);
-			rc = chsc_sstpi(stp_page, &stp_info,
-					sizeof(struct stp_sstpi));
-			if (rc == 0 && stp_info.tmd != 2)
-				rc = -EAGAIN;
+	if (xchg(&first, 1) == 0) {
+		/* Wait until all other cpus entered the sync function. */
+		while (atomic_read(&sync->cpus) != 0)
+			cpu_relax();
+		rc = 0;
+		if (stp_info.todoff[0] || stp_info.todoff[1] ||
+		    stp_info.todoff[2] || stp_info.todoff[3] ||
+		    stp_info.tmd != 2) {
+			rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0,
+					&clock_delta);
+			if (rc == 0) {
+				sync->clock_delta = clock_delta;
+				clock_sync_global(clock_delta);
+				rc = chsc_sstpi(stp_page, &stp_info,
+						sizeof(struct stp_sstpi));
+				if (rc == 0 && stp_info.tmd != 2)
+					rc = -EAGAIN;
+			}
 		}
+		sync->in_sync = rc ? -EAGAIN : 1;
+		xchg(&first, 0);
+	} else {
+		/* Slave */
+		atomic_dec(&sync->cpus);
+		/* Wait for in_sync to be set. */
+		while (READ_ONCE(sync->in_sync) == 0)
+			__udelay(1);
 	}
-	if (rc) {
+	if (sync->in_sync != 1)
+		/* Didn't work. Clear per-cpu in sync bit again. */
 		disable_sync_clock(NULL);
-		stp_sync->in_sync = -EAGAIN;
-	} else
-		stp_sync->in_sync = 1;
-	xchg(&first, 0);
+	/* Apply clock delta to per-CPU fields of this CPU. */
+	clock_sync_local(sync->clock_delta);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/topology.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/topology.c
--- linux-libre-4.9-gnu/arch/s390/kernel/topology.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/topology.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/workqueue.h>
+#include <linux/bootmem.h>
 #include <linux/cpuset.h>
 #include <linux/device.h>
 #include <linux/export.h>
@@ -41,15 +42,17 @@ static bool topology_enabled = true;
 static DECLARE_WORK(topology_work, topology_work_fn);
 
 /*
- * Socket/Book linked lists and per_cpu(cpu_topology) updates are
+ * Socket/Book linked lists and cpu_topology updates are
  * protected by "sched_domains_mutex".
  */
 static struct mask_info socket_info;
 static struct mask_info book_info;
 static struct mask_info drawer_info;
 
-DEFINE_PER_CPU(struct cpu_topology_s390, cpu_topology);
-EXPORT_PER_CPU_SYMBOL_GPL(cpu_topology);
+struct cpu_topology_s390 cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
+
+cpumask_t cpus_with_topology;
 
 static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
@@ -97,7 +100,7 @@ static void add_cpus_to_mask(struct topo
 		if (lcpu < 0)
 			continue;
 		for (i = 0; i <= smp_cpu_mtid; i++) {
-			topo = &per_cpu(cpu_topology, lcpu + i);
+			topo = &cpu_topology[lcpu + i];
 			topo->drawer_id = drawer->id;
 			topo->book_id = book->id;
 			topo->socket_id = socket->id;
@@ -106,6 +109,7 @@ static void add_cpus_to_mask(struct topo
 			cpumask_set_cpu(lcpu + i, &drawer->mask);
 			cpumask_set_cpu(lcpu + i, &book->mask);
 			cpumask_set_cpu(lcpu + i, &socket->mask);
+			cpumask_set_cpu(lcpu + i, &cpus_with_topology);
 			smp_cpu_set_polarization(lcpu + i, tl_core->pp);
 		}
 	}
@@ -220,7 +224,7 @@ static void update_cpu_masks(void)
 	int cpu;
 
 	for_each_possible_cpu(cpu) {
-		topo = &per_cpu(cpu_topology, cpu);
+		topo = &cpu_topology[cpu];
 		topo->thread_mask = cpu_thread_map(cpu);
 		topo->core_mask = cpu_group_map(&socket_info, cpu);
 		topo->book_mask = cpu_group_map(&book_info, cpu);
@@ -231,6 +235,8 @@ static void update_cpu_masks(void)
 			topo->socket_id = cpu;
 			topo->book_id = cpu;
 			topo->drawer_id = cpu;
+			if (cpu_present(cpu))
+				cpumask_set_cpu(cpu, &cpus_with_topology);
 		}
 	}
 	numa_update_cpu_topology();
@@ -241,12 +247,12 @@ void store_topology(struct sysinfo_15_1_
 	stsi(info, 15, 1, min(topology_max_mnest, 4));
 }
 
-int arch_update_cpu_topology(void)
+static int __arch_update_cpu_topology(void)
 {
 	struct sysinfo_15_1_x *info = tl_info;
-	struct device *dev;
-	int cpu, rc = 0;
+	int rc = 0;
 
+	cpumask_clear(&cpus_with_topology);
 	if (MACHINE_HAS_TOPOLOGY) {
 		rc = 1;
 		store_topology(info);
@@ -255,6 +261,15 @@ int arch_update_cpu_topology(void)
 	update_cpu_masks();
 	if (!MACHINE_HAS_TOPOLOGY)
 		topology_update_polarization_simple();
+	return rc;
+}
+
+int arch_update_cpu_topology(void)
+{
+	struct device *dev;
+	int cpu, rc;
+
+	rc = __arch_update_cpu_topology();
 	for_each_online_cpu(cpu) {
 		dev = get_cpu_device(cpu);
 		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
@@ -394,23 +409,23 @@ int topology_cpu_init(struct cpu *cpu)
 
 static const struct cpumask *cpu_thread_mask(int cpu)
 {
-	return &per_cpu(cpu_topology, cpu).thread_mask;
+	return &cpu_topology[cpu].thread_mask;
 }
 
 
 const struct cpumask *cpu_coregroup_mask(int cpu)
 {
-	return &per_cpu(cpu_topology, cpu).core_mask;
+	return &cpu_topology[cpu].core_mask;
 }
 
 static const struct cpumask *cpu_book_mask(int cpu)
 {
-	return &per_cpu(cpu_topology, cpu).book_mask;
+	return &cpu_topology[cpu].book_mask;
 }
 
 static const struct cpumask *cpu_drawer_mask(int cpu)
 {
-	return &per_cpu(cpu_topology, cpu).drawer_mask;
+	return &cpu_topology[cpu].drawer_mask;
 }
 
 static int __init early_parse_topology(char *p)
@@ -438,19 +453,20 @@ static void __init alloc_masks(struct sy
 		nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
 	nr_masks = max(nr_masks, 1);
 	for (i = 0; i < nr_masks; i++) {
-		mask->next = kzalloc(sizeof(*mask->next), GFP_KERNEL);
+		mask->next = memblock_virt_alloc(sizeof(*mask->next), 8);
 		mask = mask->next;
 	}
 }
 
-static int __init s390_topology_init(void)
+void __init topology_init_early(void)
 {
 	struct sysinfo_15_1_x *info;
 	int i;
 
+	set_sched_topology(s390_topology);
 	if (!MACHINE_HAS_TOPOLOGY)
-		return 0;
-	tl_info = (struct sysinfo_15_1_x *)__get_free_page(GFP_KERNEL);
+		goto out;
+	tl_info = memblock_virt_alloc(sizeof(*tl_info), PAGE_SIZE);
 	info = tl_info;
 	store_topology(info);
 	pr_info("The CPU configuration topology of the machine is:");
@@ -460,10 +476,9 @@ static int __init s390_topology_init(voi
 	alloc_masks(info, &socket_info, 1);
 	alloc_masks(info, &book_info, 2);
 	alloc_masks(info, &drawer_info, 3);
-	set_sched_topology(s390_topology);
-	return 0;
+out:
+	__arch_update_cpu_topology();
 }
-early_initcall(s390_topology_init);
 
 static int __init topology_init(void)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/traps.c
--- linux-libre-4.9-gnu/arch/s390/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/fpu/api.h>
 #include "entry.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/vdso32/clock_gettime.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso32/clock_gettime.S
--- linux-libre-4.9-gnu/arch/s390/kernel/vdso32/clock_gettime.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso32/clock_gettime.S	2017-02-12 16:03:20.000000000 -0500
@@ -99,8 +99,27 @@ __kernel_clock_gettime:
 	tml	%r4,0x0001			/* pending update ? loop */
 	jnz	11b
 	stcke	0(%r15)				/* Store TOD clock */
-	lm	%r0,%r1,1(%r15)
-	s	%r0,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
+	lm	%r0,%r1,__VDSO_TS_END(%r5)	/* TOD steering end time */
+	s	%r0,1(%r15)			/* no - ts_steering_end */
+	sl	%r1,5(%r15)
+	brc	3,22f
+	ahi	%r0,-1
+22:	ltr	%r0,%r0				/* past end of steering? */
+	jm	24f
+	srdl	%r0,15				/* 1 per 2^16 */
+	tm	__VDSO_TS_DIR+3(%r5),0x01	/* steering direction? */
+	jz	23f
+	lcr	%r0,%r0				/* negative TOD offset */
+	lcr	%r1,%r1
+	je	23f
+	ahi	%r0,-1
+23:	a	%r0,1(%r15)			/* add TOD timestamp */
+	al	%r1,5(%r15)
+	brc	12,25f
+	ahi	%r0,1
+	j	25f
+24:	lm	%r0,%r1,1(%r15)			/* load TOD timestamp */
+25:	s	%r0,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
 	sl	%r1,__VDSO_XTIME_STAMP+4(%r5)
 	brc	3,12f
 	ahi	%r0,-1
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/vdso32/gettimeofday.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso32/gettimeofday.S
--- linux-libre-4.9-gnu/arch/s390/kernel/vdso32/gettimeofday.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso32/gettimeofday.S	2017-02-12 16:03:20.000000000 -0500
@@ -31,8 +31,27 @@ __kernel_gettimeofday:
 	tml	%r4,0x0001			/* pending update ? loop */
 	jnz	1b
 	stcke	0(%r15)				/* Store TOD clock */
-	lm	%r0,%r1,1(%r15)
-	s	%r0,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
+	lm	%r0,%r1,__VDSO_TS_END(%r5)	/* TOD steering end time */
+	s	%r0,1(%r15)
+	sl	%r1,5(%r15)
+	brc	3,14f
+	ahi	%r0,-1
+14:	ltr	%r0,%r0				/* past end of steering? */
+	jm	16f
+	srdl	%r0,15				/* 1 per 2^16 */
+	tm	__VDSO_TS_DIR+3(%r5),0x01	/* steering direction? */
+	jz	15f
+	lcr	%r0,%r0				/* negative TOD offset */
+	lcr	%r1,%r1
+	je	15f
+	ahi	%r0,-1
+15:	a	%r0,1(%r15)			/* add TOD timestamp */
+	al	%r1,5(%r15)
+	brc	12,17f
+	ahi	%r0,1
+	j	17f
+16:	lm	%r0,%r1,1(%r15)			/* load TOD timestamp */
+17:	s	%r0,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
 	sl	%r1,__VDSO_XTIME_STAMP+4(%r5)
 	brc	3,3f
 	ahi	%r0,-1
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/vdso64/clock_gettime.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso64/clock_gettime.S
--- linux-libre-4.9-gnu/arch/s390/kernel/vdso64/clock_gettime.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso64/clock_gettime.S	2017-02-12 16:03:20.000000000 -0500
@@ -83,8 +83,17 @@ __kernel_clock_gettime:
 	tmll	%r4,0x0001			/* pending update ? loop */
 	jnz	5b
 	stcke	0(%r15)				/* Store TOD clock */
-	lgf	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */
 	lg	%r1,1(%r15)
+	lg	%r0,__VDSO_TS_END(%r5)		/* TOD steering end time */
+	slgr	%r0,%r1				/* now - ts_steering_end */
+	ltgr	%r0,%r0				/* past end of steering ? */
+	jm	17f
+	srlg	%r0,%r0,15			/* 1 per 2^16 */
+	tm	__VDSO_TS_DIR+3(%r5),0x01	/* steering direction? */
+	jz	18f
+	lcgr	%r0,%r0				/* negative TOD offset */
+18:	algr	%r1,%r0				/* add steering offset */
+17:	lgf	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */
 	sg	%r1,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
 	msgf	%r1,__VDSO_TK_MULT(%r5)		/*  * tk->mult */
 	alg	%r1,__VDSO_XTIME_NSEC(%r5)	/*  + tk->xtime_nsec */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/vdso64/gettimeofday.S linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso64/gettimeofday.S
--- linux-libre-4.9-gnu/arch/s390/kernel/vdso64/gettimeofday.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/vdso64/gettimeofday.S	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,16 @@ __kernel_gettimeofday:
 	jnz	0b
 	stcke	0(%r15)				/* Store TOD clock */
 	lg	%r1,1(%r15)
-	sg	%r1,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
+	lg	%r0,__VDSO_TS_END(%r5)		/* TOD steering end time */
+	slgr	%r0,%r1				/* now - ts_steering_end */
+	ltgr	%r0,%r0				/* past end of steering ? */
+	jm	6f
+	srlg	%r0,%r0,15			/* 1 per 2^16 */
+	tm	__VDSO_TS_DIR+3(%r5),0x01	/* steering direction? */
+	jz	7f
+	lcgr	%r0,%r0				/* negative TOD offset */
+7:	algr	%r1,%r0				/* add steering offset */
+6:	sg	%r1,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
 	msgf	%r1,__VDSO_TK_MULT(%r5)		/*  * tk->mult */
 	alg	%r1,__VDSO_XTIME_NSEC(%r5)	/*  + tk->xtime_nsec */
 	lg	%r0,__VDSO_XTIME_SEC(%r5)	/* tk->xtime_sec */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kernel/vtime.c linux-libre-4.10-rc8-gnu/arch/s390/kernel/vtime.c
--- linux-libre-4.9-gnu/arch/s390/kernel/vtime.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kernel/vtime.c	2017-02-12 16:03:20.000000000 -0500
@@ -94,9 +94,8 @@ static void update_mt_scaling(void)
  * Update process times based on virtual cpu times stored by entry.S
  * to the lowcore fields user_timer, system_timer & steal_clock.
  */
-static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
+static int do_account_vtime(struct task_struct *tsk)
 {
-	struct thread_info *ti = task_thread_info(tsk);
 	u64 timer, clock, user, system, steal;
 	u64 user_scaled, system_scaled;
 
@@ -119,13 +118,13 @@ static int do_account_vtime(struct task_
 	    time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies)))
 		update_mt_scaling();
 
-	user = S390_lowcore.user_timer - ti->user_timer;
+	user = S390_lowcore.user_timer - tsk->thread.user_timer;
 	S390_lowcore.steal_timer -= user;
-	ti->user_timer = S390_lowcore.user_timer;
+	tsk->thread.user_timer = S390_lowcore.user_timer;
 
-	system = S390_lowcore.system_timer - ti->system_timer;
+	system = S390_lowcore.system_timer - tsk->thread.system_timer;
 	S390_lowcore.steal_timer -= system;
-	ti->system_timer = S390_lowcore.system_timer;
+	tsk->thread.system_timer = S390_lowcore.system_timer;
 
 	user_scaled = user;
 	system_scaled = system;
@@ -137,8 +136,10 @@ static int do_account_vtime(struct task_
 		user_scaled = (user_scaled * mult) / div;
 		system_scaled = (system_scaled * mult) / div;
 	}
-	account_user_time(tsk, user, user_scaled);
-	account_system_time(tsk, hardirq_offset, system, system_scaled);
+	account_user_time(tsk, user);
+	tsk->utimescaled += user_scaled;
+	account_system_time(tsk, 0, system);
+	tsk->stimescaled += system_scaled;
 
 	steal = S390_lowcore.steal_timer;
 	if ((s64) steal > 0) {
@@ -151,15 +152,11 @@ static int do_account_vtime(struct task_
 
 void vtime_task_switch(struct task_struct *prev)
 {
-	struct thread_info *ti;
-
-	do_account_vtime(prev, 0);
-	ti = task_thread_info(prev);
-	ti->user_timer = S390_lowcore.user_timer;
-	ti->system_timer = S390_lowcore.system_timer;
-	ti = task_thread_info(current);
-	S390_lowcore.user_timer = ti->user_timer;
-	S390_lowcore.system_timer = ti->system_timer;
+	do_account_vtime(prev);
+	prev->thread.user_timer = S390_lowcore.user_timer;
+	prev->thread.system_timer = S390_lowcore.system_timer;
+	S390_lowcore.user_timer = current->thread.user_timer;
+	S390_lowcore.system_timer = current->thread.system_timer;
 }
 
 /*
@@ -169,7 +166,7 @@ void vtime_task_switch(struct task_struc
  */
 void vtime_account_user(struct task_struct *tsk)
 {
-	if (do_account_vtime(tsk, HARDIRQ_OFFSET))
+	if (do_account_vtime(tsk))
 		virt_timer_expire();
 }
 
@@ -179,7 +176,6 @@ void vtime_account_user(struct task_stru
  */
 void vtime_account_irq_enter(struct task_struct *tsk)
 {
-	struct thread_info *ti = task_thread_info(tsk);
 	u64 timer, system, system_scaled;
 
 	timer = S390_lowcore.last_update_timer;
@@ -191,9 +187,9 @@ void vtime_account_irq_enter(struct task
 	    time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies)))
 		update_mt_scaling();
 
-	system = S390_lowcore.system_timer - ti->system_timer;
+	system = S390_lowcore.system_timer - tsk->thread.system_timer;
 	S390_lowcore.steal_timer -= system;
-	ti->system_timer = S390_lowcore.system_timer;
+	tsk->thread.system_timer = S390_lowcore.system_timer;
 	system_scaled = system;
 	/* Do MT utilization scaling */
 	if (smp_cpu_mtid) {
@@ -202,7 +198,8 @@ void vtime_account_irq_enter(struct task
 
 		system_scaled = (system_scaled * mult) / div;
 	}
-	account_system_time(tsk, 0, system, system_scaled);
+	account_system_time(tsk, 0, system);
+	tsk->stimescaled += system_scaled;
 
 	virt_timer_forward(system);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kvm/interrupt.c linux-libre-4.10-rc8-gnu/arch/s390/kvm/interrupt.c
--- linux-libre-4.9-gnu/arch/s390/kvm/interrupt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kvm/interrupt.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/vmalloc.h>
 #include <asm/asm-offsets.h>
 #include <asm/dis.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sclp.h>
 #include <asm/isc.h>
 #include <asm/gmap.h>
@@ -415,7 +415,7 @@ static int __write_machine_check(struct
 	int rc;
 
 	mci.val = mchk->mcic;
-	/* take care of lazy register loading via vcpu load/put */
+	/* take care of lazy register loading */
 	save_fpu_regs();
 	save_access_regs(vcpu->run->s.regs.acrs);
 
@@ -1019,7 +1019,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu
 		return 0;
 
 	__set_cpu_idle(vcpu);
-	hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
+	hrtimer_start(&vcpu->arch.ckc_timer, sltime, HRTIMER_MODE_REL);
 	VCPU_EVENT(vcpu, 4, "enabled wait: %llu ns", sltime);
 no_timer:
 	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/kvm/kvm-s390.c linux-libre-4.10-rc8-gnu/arch/s390/kvm/kvm-s390.c
--- linux-libre-4.9-gnu/arch/s390/kvm/kvm-s390.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/kvm/kvm-s390.c	2017-02-12 16:03:20.000000000 -0500
@@ -916,7 +916,7 @@ static int kvm_s390_get_machine(struct k
 	memcpy(&mach->fac_mask, kvm->arch.model.fac_mask,
 	       S390_ARCH_FAC_LIST_SIZE_BYTE);
 	memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list,
-	       S390_ARCH_FAC_LIST_SIZE_BYTE);
+	       sizeof(S390_lowcore.stfle_fac_list));
 	if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach)))
 		ret = -EFAULT;
 	kfree(mach);
@@ -1437,7 +1437,7 @@ int kvm_arch_init_vm(struct kvm *kvm, un
 
 	/* Populate the facility mask initially. */
 	memcpy(kvm->arch.model.fac_mask, S390_lowcore.stfle_fac_list,
-	       S390_ARCH_FAC_LIST_SIZE_BYTE);
+	       sizeof(S390_lowcore.stfle_fac_list));
 	for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) {
 		if (i < kvm_s390_fac_list_mask_size())
 			kvm->arch.model.fac_mask[i] &= kvm_s390_fac_list_mask[i];
@@ -1812,22 +1812,7 @@ __u64 kvm_s390_get_cpu_timer(struct kvm_
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
-	/* Save host register state */
-	save_fpu_regs();
-	vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
-	vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
 
-	if (MACHINE_HAS_VX)
-		current->thread.fpu.regs = vcpu->run->s.regs.vrs;
-	else
-		current->thread.fpu.regs = vcpu->run->s.regs.fprs;
-	current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
-	if (test_fp_ctl(current->thread.fpu.fpc))
-		/* User space provided an invalid FPC, let's clear it */
-		current->thread.fpu.fpc = 0;
-
-	save_access_regs(vcpu->arch.host_acrs);
-	restore_access_regs(vcpu->run->s.regs.acrs);
 	gmap_enable(vcpu->arch.enabled_gmap);
 	atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 	if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
@@ -1844,16 +1829,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
 	vcpu->arch.enabled_gmap = gmap_get_enabled();
 	gmap_disable(vcpu->arch.enabled_gmap);
 
-	/* Save guest register state */
-	save_fpu_regs();
-	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
-
-	/* Restore host register state */
-	current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
-	current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
-
-	save_access_regs(vcpu->run->s.regs.acrs);
-	restore_access_regs(vcpu->arch.host_acrs);
 }
 
 static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
@@ -2243,7 +2218,6 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct
 {
 	memcpy(&vcpu->run->s.regs.acrs, &sregs->acrs, sizeof(sregs->acrs));
 	memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
-	restore_access_regs(vcpu->run->s.regs.acrs);
 	return 0;
 }
 
@@ -2257,11 +2231,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct
 
 int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
 {
-	/* make sure the new values will be lazily loaded */
-	save_fpu_regs();
 	if (test_fp_ctl(fpu->fpc))
 		return -EINVAL;
-	current->thread.fpu.fpc = fpu->fpc;
+	vcpu->run->s.regs.fpc = fpu->fpc;
 	if (MACHINE_HAS_VX)
 		convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs,
 				 (freg_t *) fpu->fprs);
@@ -2279,7 +2251,7 @@ int kvm_arch_vcpu_ioctl_get_fpu(struct k
 				 (__vector128 *) vcpu->run->s.regs.vrs);
 	else
 		memcpy(fpu->fprs, vcpu->run->s.regs.fprs, sizeof(fpu->fprs));
-	fpu->fpc = current->thread.fpu.fpc;
+	fpu->fpc = vcpu->run->s.regs.fpc;
 	return 0;
 }
 
@@ -2740,6 +2712,20 @@ static void sync_regs(struct kvm_vcpu *v
 		if (riccb->valid)
 			vcpu->arch.sie_block->ecb3 |= 0x01;
 	}
+	save_access_regs(vcpu->arch.host_acrs);
+	restore_access_regs(vcpu->run->s.regs.acrs);
+	/* save host (userspace) fprs/vrs */
+	save_fpu_regs();
+	vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
+	vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
+	if (MACHINE_HAS_VX)
+		current->thread.fpu.regs = vcpu->run->s.regs.vrs;
+	else
+		current->thread.fpu.regs = vcpu->run->s.regs.fprs;
+	current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
+	if (test_fp_ctl(current->thread.fpu.fpc))
+		/* User space provided an invalid FPC, let's clear it */
+		current->thread.fpu.fpc = 0;
 
 	kvm_run->kvm_dirty_regs = 0;
 }
@@ -2758,6 +2744,15 @@ static void store_regs(struct kvm_vcpu *
 	kvm_run->s.regs.pft = vcpu->arch.pfault_token;
 	kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
 	kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
+	save_access_regs(vcpu->run->s.regs.acrs);
+	restore_access_regs(vcpu->arch.host_acrs);
+	/* Save guest register state */
+	save_fpu_regs();
+	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
+	/* Restore will be done lazily at return */
+	current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
+	current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
+
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -2874,7 +2869,7 @@ int kvm_s390_vcpu_store_status(struct kv
 {
 	/*
 	 * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy
-	 * copying in vcpu load/put. Lets update our copies before we save
+	 * switch in the run ioctl. Let's update our copies before we save
 	 * it into the save area
 	 */
 	save_fpu_regs();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/lib/mem.S linux-libre-4.10-rc8-gnu/arch/s390/lib/mem.S
--- linux-libre-4.9-gnu/arch/s390/lib/mem.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/lib/mem.S	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,45 @@
 #include <asm/export.h>
 
 /*
+ * void *memmove(void *dest, const void *src, size_t n)
+ */
+ENTRY(memmove)
+	ltgr	%r4,%r4
+	lgr	%r1,%r2
+	bzr	%r14
+	clgr	%r2,%r3
+	jnh	.Lmemmove_forward
+	la	%r5,0(%r4,%r3)
+	clgr	%r2,%r5
+	jl	.Lmemmove_reverse
+.Lmemmove_forward:
+	aghi	%r4,-1
+	srlg	%r0,%r4,8
+	ltgr	%r0,%r0
+	jz	.Lmemmove_rest
+.Lmemmove_loop:
+	mvc	0(256,%r1),0(%r3)
+	la	%r1,256(%r1)
+	la	%r3,256(%r3)
+	brctg	%r0,.Lmemmove_loop
+.Lmemmove_rest:
+	larl	%r5,.Lmemmove_mvc
+	ex	%r4,0(%r5)
+	br	%r14
+.Lmemmove_reverse:
+	aghi	%r4,-1
+.Lmemmove_reverse_loop:
+	ic	%r0,0(%r4,%r3)
+	stc	%r0,0(%r4,%r1)
+	brctg	%r4,.Lmemmove_reverse_loop
+	ic	%r0,0(%r4,%r3)
+	stc	%r0,0(%r4,%r1)
+	br	%r14
+.Lmemmove_mvc:
+	mvc	0(1,%r1),0(%r3)
+EXPORT_SYMBOL(memmove)
+
+/*
  * memset implementation
  *
  * This code corresponds to the C construct below. We do distinguish
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/lib/spinlock.c linux-libre-4.10-rc8-gnu/arch/s390/lib/spinlock.c
--- linux-libre-4.9-gnu/arch/s390/lib/spinlock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/lib/spinlock.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,15 +37,6 @@ static inline void _raw_compare_and_dela
 	asm(".insn rsy,0xeb0000000022,%0,0,%1" : : "d" (old), "Q" (*lock));
 }
 
-static inline int cpu_is_preempted(int cpu)
-{
-	if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu))
-		return 0;
-	if (smp_vcpu_scheduled(cpu))
-		return 0;
-	return 1;
-}
-
 void arch_spin_lock_wait(arch_spinlock_t *lp)
 {
 	unsigned int cpu = SPINLOCK_LOCKVAL;
@@ -62,7 +53,7 @@ void arch_spin_lock_wait(arch_spinlock_t
 			continue;
 		}
 		/* First iteration: check if the lock owner is running. */
-		if (first_diag && cpu_is_preempted(~owner)) {
+		if (first_diag && arch_vcpu_is_preempted(~owner)) {
 			smp_yield_cpu(~owner);
 			first_diag = 0;
 			continue;
@@ -81,7 +72,7 @@ void arch_spin_lock_wait(arch_spinlock_t
 		 * yield the CPU unconditionally. For LPAR rely on the
 		 * sense running status.
 		 */
-		if (!MACHINE_IS_LPAR || cpu_is_preempted(~owner)) {
+		if (!MACHINE_IS_LPAR || arch_vcpu_is_preempted(~owner)) {
 			smp_yield_cpu(~owner);
 			first_diag = 0;
 		}
@@ -108,7 +99,7 @@ void arch_spin_lock_wait_flags(arch_spin
 			continue;
 		}
 		/* Check if the lock owner is running. */
-		if (first_diag && cpu_is_preempted(~owner)) {
+		if (first_diag && arch_vcpu_is_preempted(~owner)) {
 			smp_yield_cpu(~owner);
 			first_diag = 0;
 			continue;
@@ -127,7 +118,7 @@ void arch_spin_lock_wait_flags(arch_spin
 		 * yield the CPU unconditionally. For LPAR rely on the
 		 * sense running status.
 		 */
-		if (!MACHINE_IS_LPAR || cpu_is_preempted(~owner)) {
+		if (!MACHINE_IS_LPAR || arch_vcpu_is_preempted(~owner)) {
 			smp_yield_cpu(~owner);
 			first_diag = 0;
 		}
@@ -165,7 +156,7 @@ void _raw_read_lock_wait(arch_rwlock_t *
 	owner = 0;
 	while (1) {
 		if (count-- <= 0) {
-			if (owner && cpu_is_preempted(~owner))
+			if (owner && arch_vcpu_is_preempted(~owner))
 				smp_yield_cpu(~owner);
 			count = spin_retry;
 		}
@@ -211,7 +202,7 @@ void _raw_write_lock_wait(arch_rwlock_t
 	owner = 0;
 	while (1) {
 		if (count-- <= 0) {
-			if (owner && cpu_is_preempted(~owner))
+			if (owner && arch_vcpu_is_preempted(~owner))
 				smp_yield_cpu(~owner);
 			count = spin_retry;
 		}
@@ -241,7 +232,7 @@ void _raw_write_lock_wait(arch_rwlock_t
 	owner = 0;
 	while (1) {
 		if (count-- <= 0) {
-			if (owner && cpu_is_preempted(~owner))
+			if (owner && arch_vcpu_is_preempted(~owner))
 				smp_yield_cpu(~owner);
 			count = spin_retry;
 		}
@@ -285,7 +276,7 @@ void arch_lock_relax(unsigned int cpu)
 {
 	if (!cpu)
 		return;
-	if (MACHINE_IS_LPAR && !cpu_is_preempted(~cpu))
+	if (MACHINE_IS_LPAR && !arch_vcpu_is_preempted(~cpu))
 		return;
 	smp_yield_cpu(~cpu);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/lib/string.c linux-libre-4.10-rc8-gnu/arch/s390/lib/string.c
--- linux-libre-4.9-gnu/arch/s390/lib/string.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/lib/string.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@ static inline char *__strend(const char
 
 	asm volatile ("0: srst  %0,%1\n"
 		      "   jo    0b"
-		      : "+d" (r0), "+a" (s) :  : "cc" );
+		      : "+d" (r0), "+a" (s) :  : "cc", "memory");
 	return (char *) r0;
 }
 
@@ -31,7 +31,7 @@ static inline char *__strnend(const char
 
 	asm volatile ("0: srst  %0,%1\n"
 		      "   jo    0b"
-		      : "+d" (p), "+a" (s) : "d" (r0) : "cc" );
+		      : "+d" (p), "+a" (s) : "d" (r0) : "cc", "memory");
 	return (char *) p;
 }
 
@@ -213,7 +213,7 @@ int strcmp(const char *cs, const char *c
 		      "   sr   %0,%1\n"
 		      "1:"
 		      : "+d" (ret), "+d" (r0), "+a" (cs), "+a" (ct)
-		      : : "cc" );
+		      : : "cc", "memory");
 	return ret;
 }
 EXPORT_SYMBOL(strcmp);
@@ -250,7 +250,7 @@ static inline int clcle(const char *s1,
 		      "   ipm   %0\n"
 		      "   srl   %0,28"
 		      : "=&d" (cc), "+a" (r2), "+a" (r3),
-			"+a" (r4), "+a" (r5) : : "cc");
+			"+a" (r4), "+a" (r5) : : "cc", "memory");
 	return cc;
 }
 
@@ -298,7 +298,7 @@ void *memchr(const void *s, int c, size_
 		      "   jl	1f\n"
 		      "   la    %0,0\n"
 		      "1:"
-		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
+		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
 	return (void *) ret;
 }
 EXPORT_SYMBOL(memchr);
@@ -336,7 +336,7 @@ void *memscan(void *s, int c, size_t n)
 
 	asm volatile ("0: srst  %0,%1\n"
 		      "   jo    0b\n"
-		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc" );
+		      : "+a" (ret), "+&a" (s) : "d" (r0) : "cc", "memory");
 	return (void *) ret;
 }
 EXPORT_SYMBOL(memscan);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/mm/extmem.c linux-libre-4.10-rc8-gnu/arch/s390/mm/extmem.c
--- linux-libre-4.9-gnu/arch/s390/mm/extmem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/mm/extmem.c	2017-02-12 16:03:20.000000000 -0500
@@ -122,7 +122,7 @@ dcss_set_subcodes(void)
 		"1:	la	%2,3\n"
 		"2:\n"
 		EX_TABLE(0b, 1b)
-		: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc");
+		: "+d" (rx), "+d" (ry), "=d" (rc) : : "cc", "memory");
 
 	kfree(name);
 	/* Diag x'64' new subcodes are supported, set to new subcodes */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/mm/fault.c linux-libre-4.10-rc8-gnu/arch/s390/mm/fault.c
--- linux-libre-4.9-gnu/arch/s390/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -733,6 +733,7 @@ block:
 			 * return to userspace schedule() to block. */
 			__set_current_state(TASK_UNINTERRUPTIBLE);
 			set_tsk_need_resched(tsk);
+			set_preempt_need_resched();
 		}
 	}
 out:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/mm/gmap.c linux-libre-4.10-rc8-gnu/arch/s390/mm/gmap.c
--- linux-libre-4.9-gnu/arch/s390/mm/gmap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/mm/gmap.c	2017-02-12 16:03:20.000000000 -0500
@@ -1015,7 +1015,7 @@ static inline void gmap_insert_rmap(stru
 	if (slot) {
 		rmap->next = radix_tree_deref_slot_protected(slot,
 							&sg->guest_table_lock);
-		radix_tree_replace_slot(slot, rmap);
+		radix_tree_replace_slot(&sg->host_to_rmap, slot, rmap);
 	} else {
 		rmap->next = NULL;
 		radix_tree_insert(&sg->host_to_rmap, vmaddr >> PAGE_SHIFT,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/mm/init.c linux-libre-4.10-rc8-gnu/arch/s390/mm/init.c
--- linux-libre-4.9-gnu/arch/s390/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/mm/pgtable.c linux-libre-4.10-rc8-gnu/arch/s390/mm/pgtable.c
--- linux-libre-4.9-gnu/arch/s390/mm/pgtable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/mm/pgtable.c	2017-02-12 16:03:20.000000000 -0500
@@ -202,7 +202,7 @@ static inline pgste_t ptep_xchg_start(st
 	return pgste;
 }
 
-static inline void ptep_xchg_commit(struct mm_struct *mm,
+static inline pte_t ptep_xchg_commit(struct mm_struct *mm,
 				    unsigned long addr, pte_t *ptep,
 				    pgste_t pgste, pte_t old, pte_t new)
 {
@@ -220,6 +220,7 @@ static inline void ptep_xchg_commit(stru
 	} else {
 		*ptep = new;
 	}
+	return old;
 }
 
 pte_t ptep_xchg_direct(struct mm_struct *mm, unsigned long addr,
@@ -231,7 +232,7 @@ pte_t ptep_xchg_direct(struct mm_struct
 	preempt_disable();
 	pgste = ptep_xchg_start(mm, addr, ptep);
 	old = ptep_flush_direct(mm, addr, ptep);
-	ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
+	old = ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
 	preempt_enable();
 	return old;
 }
@@ -246,7 +247,7 @@ pte_t ptep_xchg_lazy(struct mm_struct *m
 	preempt_disable();
 	pgste = ptep_xchg_start(mm, addr, ptep);
 	old = ptep_flush_lazy(mm, addr, ptep);
-	ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
+	old = ptep_xchg_commit(mm, addr, ptep, pgste, old, new);
 	preempt_enable();
 	return old;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/mm/vmem.c linux-libre-4.10-rc8-gnu/arch/s390/mm/vmem.c
--- linux-libre-4.9-gnu/arch/s390/mm/vmem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/mm/vmem.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@ static void __ref *vmem_alloc_pages(unsi
 
 	if (slab_is_available())
 		return (void *)__get_free_pages(GFP_KERNEL, order);
-	return alloc_bootmem_align(size, size);
+	return (void *) memblock_alloc(size, size);
 }
 
 static inline pud_t *vmem_pud_alloc(void)
@@ -61,17 +61,16 @@ pmd_t *vmem_pmd_alloc(void)
 
 pte_t __ref *vmem_pte_alloc(void)
 {
+	unsigned long size = PTRS_PER_PTE * sizeof(pte_t);
 	pte_t *pte;
 
 	if (slab_is_available())
 		pte = (pte_t *) page_table_alloc(&init_mm);
 	else
-		pte = alloc_bootmem_align(PTRS_PER_PTE * sizeof(pte_t),
-					  PTRS_PER_PTE * sizeof(pte_t));
+		pte = (pte_t *) memblock_alloc(size, size);
 	if (!pte)
 		return NULL;
-	clear_table((unsigned long *) pte, _PAGE_INVALID,
-		    PTRS_PER_PTE * sizeof(pte_t));
+	clear_table((unsigned long *) pte, _PAGE_INVALID, size);
 	return pte;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/net/bpf_jit_comp.c linux-libre-4.10-rc8-gnu/arch/s390/net/bpf_jit_comp.c
--- linux-libre-4.9-gnu/arch/s390/net/bpf_jit_comp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/net/bpf_jit_comp.c	2017-02-12 16:03:20.000000000 -0500
@@ -981,7 +981,7 @@ static noinline int bpf_jit_insn(struct
 		EMIT2(0x0d00, REG_14, REG_W1);
 		/* lgr %b0,%r2: load return value into %b0 */
 		EMIT4(0xb9040000, BPF_REG_0, REG_2);
-		if (bpf_helper_changes_skb_data((void *)func)) {
+		if (bpf_helper_changes_pkt_data((void *)func)) {
 			jit->seen |= SEEN_SKB_CHANGE;
 			/* lg %b1,ST_OFF_SKBP(%r15) */
 			EMIT6_DISP_LH(0xe3000000, 0x0004, BPF_REG_1, REG_0,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/numa/mode_emu.c linux-libre-4.10-rc8-gnu/arch/s390/numa/mode_emu.c
--- linux-libre-4.9-gnu/arch/s390/numa/mode_emu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/numa/mode_emu.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/cpumask.h>
 #include <linux/memblock.h>
+#include <linux/bootmem.h>
 #include <linux/node.h>
 #include <linux/memory.h>
 #include <linux/slab.h>
@@ -307,13 +308,11 @@ fail:
 /*
  * Allocate and initialize core to node mapping
  */
-static void create_core_to_node_map(void)
+static void __ref create_core_to_node_map(void)
 {
 	int i;
 
-	emu_cores = kzalloc(sizeof(*emu_cores), GFP_KERNEL);
-	if (emu_cores == NULL)
-		panic("Could not allocate cores to node memory");
+	emu_cores = memblock_virt_alloc(sizeof(*emu_cores), 8);
 	for (i = 0; i < ARRAY_SIZE(emu_cores->to_node_id); i++)
 		emu_cores->to_node_id[i] = NODE_ID_FREE;
 }
@@ -354,13 +353,13 @@ static struct toptree *toptree_from_topo
 
 	phys = toptree_new(TOPTREE_ID_PHYS, 1);
 
-	for_each_online_cpu(cpu) {
-		top = &per_cpu(cpu_topology, cpu);
+	for_each_cpu(cpu, &cpus_with_topology) {
+		top = &cpu_topology[cpu];
 		node = toptree_get_child(phys, 0);
 		drawer = toptree_get_child(node, top->drawer_id);
 		book = toptree_get_child(drawer, top->book_id);
 		mc = toptree_get_child(book, top->socket_id);
-		core = toptree_get_child(mc, top->core_id);
+		core = toptree_get_child(mc, smp_get_base_cpu(cpu));
 		if (!drawer || !book || !mc || !core)
 			panic("NUMA emulation could not allocate memory");
 		cpumask_set_cpu(cpu, &core->mask);
@@ -378,7 +377,7 @@ static void topology_add_core(struct top
 	int cpu;
 
 	for_each_cpu(cpu, &core->mask) {
-		top = &per_cpu(cpu_topology, cpu);
+		top = &cpu_topology[cpu];
 		cpumask_copy(&top->thread_mask, &core->mask);
 		cpumask_copy(&top->core_mask, &core_mc(core)->mask);
 		cpumask_copy(&top->book_mask, &core_book(core)->mask);
@@ -425,6 +424,27 @@ static void print_node_to_core_map(void)
 	}
 }
 
+static void pin_all_possible_cpus(void)
+{
+	int core_id, node_id, cpu;
+	static int initialized;
+
+	if (initialized)
+		return;
+	print_node_to_core_map();
+	node_id = 0;
+	for_each_possible_cpu(cpu) {
+		core_id = smp_get_base_cpu(cpu);
+		if (emu_cores->to_node_id[core_id] != NODE_ID_FREE)
+			continue;
+		pin_core_to_node(core_id, node_id);
+		cpu_topology[cpu].node_id = node_id;
+		node_id = (node_id + 1) % emu_nodes;
+	}
+	print_node_to_core_map();
+	initialized = 1;
+}
+
 /*
  * Transfer physical topology into a NUMA topology and modify CPU masks
  * according to the NUMA topology.
@@ -442,7 +462,7 @@ static void emu_update_cpu_topology(void
 	toptree_free(phys);
 	toptree_to_topology(numa);
 	toptree_free(numa);
-	print_node_to_core_map();
+	pin_all_possible_cpus();
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/numa/toptree.c linux-libre-4.10-rc8-gnu/arch/s390/numa/toptree.c
--- linux-libre-4.9-gnu/arch/s390/numa/toptree.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/numa/toptree.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/bootmem.h>
 #include <linux/cpumask.h>
 #include <linux/list.h>
 #include <linux/list_sort.h>
@@ -25,10 +26,14 @@
  * RETURNS:
  * Pointer to the new tree node or NULL on error
  */
-struct toptree *toptree_alloc(int level, int id)
+struct toptree __ref *toptree_alloc(int level, int id)
 {
-	struct toptree *res = kzalloc(sizeof(struct toptree), GFP_KERNEL);
+	struct toptree *res;
 
+	if (slab_is_available())
+		res = kzalloc(sizeof(*res), GFP_KERNEL);
+	else
+		res = memblock_virt_alloc(sizeof(*res), 8);
 	if (!res)
 		return res;
 
@@ -65,7 +70,7 @@ static void toptree_remove(struct toptre
  * cleanly using toptree_remove. Possible children are freed
  * recursively. In the end @cand itself is freed.
  */
-void toptree_free(struct toptree *cand)
+void __ref toptree_free(struct toptree *cand)
 {
 	struct toptree *child, *tmp;
 
@@ -73,7 +78,10 @@ void toptree_free(struct toptree *cand)
 		toptree_remove(cand);
 	toptree_for_each_child_safe(child, tmp, cand)
 		toptree_free(child);
-	kfree(cand);
+	if (slab_is_available())
+		kfree(cand);
+	else
+		memblock_free_early((unsigned long)cand, sizeof(*cand));
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/pci/pci.c linux-libre-4.10-rc8-gnu/arch/s390/pci/pci.c
--- linux-libre-4.9-gnu/arch/s390/pci/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/pci/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,7 +180,7 @@ int zpci_fmb_enable_device(struct zpci_d
 {
 	struct mod_pci_args args = { 0, 0, 0, 0 };
 
-	if (zdev->fmb)
+	if (zdev->fmb || sizeof(*zdev->fmb) < zdev->fmb_length)
 		return -EINVAL;
 
 	zdev->fmb = kmem_cache_zalloc(zdev_fmb_cache, GFP_KERNEL);
@@ -722,6 +722,11 @@ struct dev_pm_ops pcibios_pm_ops = {
 
 static int zpci_alloc_domain(struct zpci_dev *zdev)
 {
+	if (zpci_unique_uid) {
+		zdev->domain = (u16) zdev->uid;
+		return 0;
+	}
+
 	spin_lock(&zpci_domain_lock);
 	zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES);
 	if (zdev->domain == ZPCI_NR_DEVICES) {
@@ -735,6 +740,9 @@ static int zpci_alloc_domain(struct zpci
 
 static void zpci_free_domain(struct zpci_dev *zdev)
 {
+	if (zpci_unique_uid)
+		return;
+
 	spin_lock(&zpci_domain_lock);
 	clear_bit(zdev->domain, zpci_domain);
 	spin_unlock(&zpci_domain_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/pci/pci_clp.c linux-libre-4.10-rc8-gnu/arch/s390/pci/pci_clp.c
--- linux-libre-4.9-gnu/arch/s390/pci/pci_clp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/pci/pci_clp.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,8 @@
 #include <asm/clp.h>
 #include <uapi/asm/clp.h>
 
+bool zpci_unique_uid;
+
 static inline void zpci_err_clp(unsigned int rsp, int rc)
 {
 	struct {
@@ -146,6 +148,7 @@ static int clp_store_query_pci_fn(struct
 	zdev->pft = response->pft;
 	zdev->vfn = response->vfn;
 	zdev->uid = response->uid;
+	zdev->fmb_length = sizeof(u32) * response->fmb_len;
 
 	memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip));
 	if (response->util_str_avail) {
@@ -315,6 +318,7 @@ static int clp_list_pci(struct clp_req_r
 			goto out;
 		}
 
+		zpci_unique_uid = rrb->response.uid_checking;
 		WARN_ON_ONCE(rrb->response.entry_size !=
 			sizeof(struct clp_fh_list_entry));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/pci/pci_debug.c linux-libre-4.10-rc8-gnu/arch/s390/pci/pci_debug.c
--- linux-libre-4.9-gnu/arch/s390/pci/pci_debug.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/pci/pci_debug.c	2017-02-12 16:03:20.000000000 -0500
@@ -69,7 +69,7 @@ static void pci_sw_counter_show(struct s
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(pci_sw_names); i++, counter++)
-		seq_printf(m, "%26s:\t%llu\n", pci_sw_names[i],
+		seq_printf(m, "%26s:\t%lu\n", pci_sw_names[i],
 			   atomic64_read(counter));
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/pci/pci_dma.c linux-libre-4.10-rc8-gnu/arch/s390/pci/pci_dma.c
--- linux-libre-4.9-gnu/arch/s390/pci/pci_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/pci/pci_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -181,14 +181,17 @@ static int __dma_purge_tlb(struct zpci_d
 	/*
 	 * With zdev->tlb_refresh == 0, rpcit is not required to establish new
 	 * translations when previously invalid translation-table entries are
-	 * validated. With lazy unmap, it also is skipped for previously valid
+	 * validated. With lazy unmap, rpcit is skipped for previously valid
 	 * entries, but a global rpcit is then required before any address can
 	 * be re-used, i.e. after each iommu bitmap wrap-around.
 	 */
-	if (!zdev->tlb_refresh &&
-			(!s390_iommu_strict ||
-			((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID)))
-		return 0;
+	if ((flags & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID) {
+		if (!zdev->tlb_refresh)
+			return 0;
+	} else {
+		if (!s390_iommu_strict)
+			return 0;
+	}
 
 	return zpci_refresh_trans((u64) zdev->fh << 32, dma_addr,
 				  PAGE_ALIGN(size));
@@ -257,7 +260,7 @@ static dma_addr_t dma_alloc_address(stru
 	spin_lock_irqsave(&zdev->iommu_bitmap_lock, flags);
 	offset = __dma_alloc_iommu(dev, zdev->next_bit, size);
 	if (offset == -1) {
-		if (!zdev->tlb_refresh && !s390_iommu_strict) {
+		if (!s390_iommu_strict) {
 			/* global flush before DMA addresses are reused */
 			if (zpci_refresh_global(zdev))
 				goto out_error;
@@ -292,7 +295,7 @@ static void dma_free_address(struct devi
 	if (!zdev->iommu_bitmap)
 		goto out;
 
-	if (zdev->tlb_refresh || s390_iommu_strict)
+	if (s390_iommu_strict)
 		bitmap_clear(zdev->iommu_bitmap, offset, size);
 	else
 		bitmap_set(zdev->lazy_bitmap, offset, size);
@@ -388,8 +391,6 @@ static void *s390_dma_alloc(struct devic
 		return NULL;
 
 	pa = page_to_phys(page);
-	memset((void *) pa, 0, size);
-
 	map = s390_dma_map_pages(dev, page, 0, size, DMA_BIDIRECTIONAL, 0);
 	if (dma_mapping_error(dev, map)) {
 		free_pages(pa, get_order(size));
@@ -419,6 +420,7 @@ static int __s390_dma_map_sg(struct devi
 			     size_t size, dma_addr_t *handle,
 			     enum dma_data_direction dir)
 {
+	unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	struct zpci_dev *zdev = to_zpci(to_pci_dev(dev));
 	dma_addr_t dma_addr_base, dma_addr;
 	int flags = ZPCI_PTE_VALID;
@@ -426,8 +428,7 @@ static int __s390_dma_map_sg(struct devi
 	unsigned long pa = 0;
 	int ret;
 
-	size = PAGE_ALIGN(size);
-	dma_addr_base = dma_alloc_address(dev, size >> PAGE_SHIFT);
+	dma_addr_base = dma_alloc_address(dev, nr_pages);
 	if (dma_addr_base == DMA_ERROR_CODE)
 		return -ENOMEM;
 
@@ -436,26 +437,27 @@ static int __s390_dma_map_sg(struct devi
 		flags |= ZPCI_TABLE_PROTECTED;
 
 	for (s = sg; dma_addr < dma_addr_base + size; s = sg_next(s)) {
-		pa = page_to_phys(sg_page(s)) + s->offset;
-		ret = __dma_update_trans(zdev, pa, dma_addr, s->length, flags);
+		pa = page_to_phys(sg_page(s));
+		ret = __dma_update_trans(zdev, pa, dma_addr,
+					 s->offset + s->length, flags);
 		if (ret)
 			goto unmap;
 
-		dma_addr += s->length;
+		dma_addr += s->offset + s->length;
 	}
 	ret = __dma_purge_tlb(zdev, dma_addr_base, size, flags);
 	if (ret)
 		goto unmap;
 
 	*handle = dma_addr_base;
-	atomic64_add(size >> PAGE_SHIFT, &zdev->mapped_pages);
+	atomic64_add(nr_pages, &zdev->mapped_pages);
 
 	return ret;
 
 unmap:
 	dma_update_trans(zdev, 0, dma_addr_base, dma_addr - dma_addr_base,
 			 ZPCI_PTE_INVALID);
-	dma_free_address(dev, dma_addr_base, size >> PAGE_SHIFT);
+	dma_free_address(dev, dma_addr_base, nr_pages);
 	zpci_err("map error:\n");
 	zpci_err_dma(ret, pa);
 	return ret;
@@ -564,7 +566,7 @@ int zpci_dma_init_device(struct zpci_dev
 		rc = -ENOMEM;
 		goto free_dma_table;
 	}
-	if (!zdev->tlb_refresh && !s390_iommu_strict) {
+	if (!s390_iommu_strict) {
 		zdev->lazy_bitmap = vzalloc(zdev->iommu_pages / 8);
 		if (!zdev->lazy_bitmap) {
 			rc = -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/tools/gen_facilities.c linux-libre-4.10-rc8-gnu/arch/s390/tools/gen_facilities.c
--- linux-libre-4.9-gnu/arch/s390/tools/gen_facilities.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/tools/gen_facilities.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,13 +7,83 @@
  *
  */
 
-#define S390_GEN_FACILITIES_C
-
 #include <strings.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <asm/facilities_src.h>
+
+struct facility_def {
+	char *name;
+	int *bits;
+};
+
+static struct facility_def facility_defs[] = {
+	{
+		/*
+		 * FACILITIES_ALS contains the list of facilities that are
+		 * required to run a kernel that is compiled e.g. with
+		 * -march=<machine>.
+		 */
+		.name = "FACILITIES_ALS",
+		.bits = (int[]){
+#ifdef CONFIG_HAVE_MARCH_Z900_FEATURES
+			0,  /* N3 instructions */
+			1,  /* z/Arch mode installed */
+#endif
+#ifdef CONFIG_HAVE_MARCH_Z990_FEATURES
+			18, /* long displacement facility */
+#endif
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+			7,  /* stfle */
+			17, /* message security assist */
+			21, /* extended-immediate facility */
+			25, /* store clock fast */
+#endif
+#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
+			27, /* mvcos */
+			32, /* compare and swap and store */
+			33, /* compare and swap and store 2 */
+			34, /* general extension facility */
+			35, /* execute extensions */
+#endif
+#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
+			45, /* fast-BCR, etc. */
+#endif
+#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES
+			49, /* misc-instruction-extensions */
+			52, /* interlocked facility 2 */
+#endif
+#ifdef CONFIG_HAVE_MARCH_Z13_FEATURES
+			53, /* load-and-zero-rightmost-byte, etc. */
+#endif
+			-1 /* END */
+		}
+	},
+	{
+		.name = "FACILITIES_KVM",
+		.bits = (int[]){
+			0,  /* N3 instructions */
+			1,  /* z/Arch mode installed */
+			2,  /* z/Arch mode active */
+			3,  /* DAT-enhancement */
+			4,  /* idte segment table */
+			5,  /* idte region table */
+			6,  /* ASN-and-LX reuse */
+			7,  /* stfle */
+			8,  /* enhanced-DAT 1 */
+			9,  /* sense-running-status */
+			10, /* conditional sske */
+			13, /* ipte-range */
+			14, /* nonquiescing key-setting */
+			73, /* transactional execution */
+			75, /* access-exception-fetch/store indication */
+			76, /* msa extension 3 */
+			77, /* msa extension 4 */
+			78, /* enhanced-DAT 2 */
+			-1  /* END */
+		}
+	},
+};
 
 static void print_facility_list(struct facility_def *def)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/s390/tools/Makefile linux-libre-4.10-rc8-gnu/arch/s390/tools/Makefile
--- linux-libre-4.9-gnu/arch/s390/tools/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/s390/tools/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,5 @@ define filechk_facilities.h
 	$(obj)/gen_facilities
 endef
 
-$(obj)/gen_facilities.o: $(srctree)/arch/s390/tools/gen_facilities.c
-
 include/generated/facilities.h: $(obj)/gen_facilities FORCE
 	$(call filechk,facilities.h)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/score/include/asm/checksum.h linux-libre-4.10-rc8-gnu/arch/score/include/asm/checksum.h
--- linux-libre-4.9-gnu/arch/score/include/asm/checksum.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/score/include/asm/checksum.h	2017-02-12 16:03:20.000000000 -0500
@@ -2,7 +2,7 @@
 #define _ASM_SCORE_CHECKSUM_H
 
 #include <linux/in6.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * computes the checksum of a memory block at buff, length len,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/score/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/score/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/score/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/score/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,6 +0,0 @@
-#ifndef _ASM_SCORE_MUTEX_H
-#define _ASM_SCORE_MUTEX_H
-
-#include <asm-generic/mutex-dec.h>
-
-#endif /* _ASM_SCORE_MUTEX_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/score/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/score/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/score/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/score/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,6 @@ extern unsigned long get_wchan(struct ta
 #define current_text_addr() ({ __label__ _l; _l: &&_l; })
 
 #define cpu_relax()		barrier()
-#define cpu_relax_lowlatency()        cpu_relax()
 #define release_thread(thread)	do {} while (0)
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/score/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/score/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/score/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/score/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * retrieve the contents of SCORE userspace general registers
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/score/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/score/kernel/traps.c
--- linux-libre-4.9-gnu/arch/score/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/score/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/cacheflush.h>
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 unsigned long exception_handlers[32];
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/score/lib/checksum_copy.c linux-libre-4.10-rc8-gnu/arch/score/lib/checksum_copy.c
--- linux-libre-4.9-gnu/arch/score/lib/checksum_copy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/score/lib/checksum_copy.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 
 #include <net/checksum.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 unsigned int csum_partial_copy(const char *src, char *dst,
 				int len, unsigned int sum)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/boards/mach-landisk/gio.c linux-libre-4.10-rc8-gnu/arch/sh/boards/mach-landisk/gio.c
--- linux-libre-4.9-gnu/arch/sh/boards/mach-landisk/gio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/boards/mach-landisk/gio.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/cdev.h>
 #include <linux/fs.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <mach-landisk/mach/gio.h>
 #include <mach-landisk/mach/iodata_landisk.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/boot/compressed/misc.c linux-libre-4.10-rc8-gnu/arch/sh/boot/compressed/misc.c
--- linux-libre-4.9-gnu/arch/sh/boot/compressed/misc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/boot/compressed/misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
  * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/include/asm/mmu_context.h linux-libre-4.10-rc8-gnu/arch/sh/include/asm/mmu_context.h
--- linux-libre-4.9-gnu/arch/sh/include/asm/mmu_context.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/include/asm/mmu_context.h	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #ifdef __KERNEL__
 #include <cpu/mmu_context.h>
 #include <asm/tlbflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm-generic/mm_hooks.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/sh/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/sh/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-/*
- * 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)
- */
-#if defined(CONFIG_CPU_SH4A)
-#include <asm/mutex-llsc.h>
-#else
-#include <asm-generic/mutex-dec.h>
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/include/asm/mutex-llsc.h linux-libre-4.10-rc8-gnu/arch/sh/include/asm/mutex-llsc.h
--- linux-libre-4.9-gnu/arch/sh/include/asm/mutex-llsc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/include/asm/mutex-llsc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-/*
- * arch/sh/include/asm/mutex-llsc.h
- *
- * SH-4A optimized mutex locking primitives
- *
- * Please look into asm-generic/mutex-xchg.h for a formal definition.
- */
-#ifndef __ASM_SH_MUTEX_LLSC_H
-#define __ASM_SH_MUTEX_LLSC_H
-
-/*
- * Attempting to lock a mutex on SH4A is done like in ARMv6+ architecure.
- * with a bastardized atomic decrement (it is not a reliable atomic decrement
- * but it satisfies the defined semantics for our purpose, while being
- * smaller and faster than a real atomic decrement or atomic swap.
- * The idea is to attempt  decrementing the lock value only once. If once
- * decremented it isn't zero, or if its store-back fails due to a dispute
- * on the exclusive store, we simply bail out immediately through the slow
- * path where the lock will be reattempted until it succeeds.
- */
-static inline void
-__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	int __done, __res;
-
-	__asm__ __volatile__ (
-		"movli.l	@%2, %0	\n"
-		"add		#-1, %0	\n"
-		"movco.l	%0, @%2	\n"
-		"movt		%1	\n"
-		: "=&z" (__res), "=&r" (__done)
-		: "r" (&(count)->counter)
-		: "t");
-
-	if (unlikely(!__done || __res != 0))
-		fail_fn(count);
-}
-
-static inline int
-__mutex_fastpath_lock_retval(atomic_t *count)
-{
-	int __done, __res;
-
-	__asm__ __volatile__ (
-		"movli.l	@%2, %0	\n"
-		"add		#-1, %0	\n"
-		"movco.l	%0, @%2	\n"
-		"movt		%1	\n"
-		: "=&z" (__res), "=&r" (__done)
-		: "r" (&(count)->counter)
-		: "t");
-
-	if (unlikely(!__done || __res != 0))
-		__res = -1;
-
-	return __res;
-}
-
-static inline void
-__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
-{
-	int __done, __res;
-
-	__asm__ __volatile__ (
-		"movli.l	@%2, %0	\n\t"
-		"add		#1, %0	\n\t"
-		"movco.l	%0, @%2 \n\t"
-		"movt		%1	\n\t"
-		: "=&z" (__res), "=&r" (__done)
-		: "r" (&(count)->counter)
-		: "t");
-
-	if (unlikely(!__done || __res <= 0))
-		fail_fn(count);
-}
-
-/*
- * If the unlock was done on a contended lock, or if the unlock simply fails
- * then the mutex remains locked.
- */
-#define __mutex_slowpath_needs_to_unlock()	1
-
-/*
- * For __mutex_fastpath_trylock we do an atomic decrement and check the
- * result and put it in the __res variable.
- */
-static inline int
-__mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
-{
-	int __res, __orig;
-
-	__asm__ __volatile__ (
-		"1: movli.l	@%2, %0		\n\t"
-		"dt		%0		\n\t"
-		"movco.l	%0,@%2		\n\t"
-		"bf		1b		\n\t"
-		"cmp/eq		#0,%0		\n\t"
-		"bt		2f		\n\t"
-		"mov		#0, %1		\n\t"
-		"bf		3f		\n\t"
-		"2: mov		#1, %1		\n\t"
-		"3:				"
-		: "=&z" (__orig), "=&r" (__res)
-		: "r" (&count->counter)
-		: "t");
-
-	return __res;
-}
-#endif /* __ASM_SH_MUTEX_LLSC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/sh/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/sh/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -97,7 +97,6 @@ extern struct sh_cpuinfo cpu_data[];
 
 #define cpu_sleep()	__asm__ __volatile__ ("sleep" : : : "memory")
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 void default_idle(void);
 void stop_this_cpu(void *);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/include/asm/tlb.h linux-libre-4.10-rc8-gnu/arch/sh/include/asm/tlb.h
--- linux-libre-4.9-gnu/arch/sh/include/asm/tlb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/include/asm/tlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,9 @@ tlb_remove_tlb_entry(struct mmu_gather *
 		tlb->end = address + PAGE_SIZE;
 }
 
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	\
+	tlb_remove_tlb_entry(tlb, ptep, address)
+
 /*
  * In the case of tlb vma handling, we can optimise these away in the
  * case where we're doing a full MM flush.  When we're doing a munmap,
@@ -115,18 +118,18 @@ static inline bool __tlb_remove_page_siz
 	return __tlb_remove_page(tlb, page);
 }
 
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
-					 struct page *page)
-{
-	return __tlb_remove_page(tlb, page);
-}
-
 static inline void tlb_remove_page_size(struct mmu_gather *tlb,
 					struct page *page, int page_size)
 {
 	return tlb_remove_page(tlb, page);
 }
 
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+						     unsigned int page_size)
+{
+}
+
 #define pte_free_tlb(tlb, ptep, addr)	pte_free((tlb)->mm, ptep)
 #define pmd_free_tlb(tlb, pmdp, addr)	pmd_free((tlb)->mm, pmdp)
 #define pud_free_tlb(tlb, pudp, addr)	pud_free((tlb)->mm, pudp)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/cpu/init.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/init.c
--- linux-libre-4.9-gnu/arch/sh/kernel/cpu/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/log2.h>
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/cpu/irq/Makefile linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/irq/Makefile
--- linux-libre-4.9-gnu/arch/sh/kernel/cpu/irq/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/irq/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 #
-# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
+# Makefile for the Linux/SuperH CPU-specific IRQ handlers.
 #
 obj-$(CONFIG_SUPERH32)			+= imask.o
 obj-$(CONFIG_CPU_SH5)			+= intc-sh5.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/cpu/Makefile linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/Makefile
--- linux-libre-4.9-gnu/arch/sh/kernel/cpu/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 #
-# Makefile for the Linux/SuperH CPU-specifc backends.
+# Makefile for the Linux/SuperH CPU-specific backends.
 #
 
 obj-$(CONFIG_CPU_SH2)		= sh2/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c
--- linux-libre-4.9-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/cpuidle.h>
 #include <linux/export.h>
 #include <asm/suspend.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static unsigned long cpuidle_mode[] = {
 	SUSP_SH_SLEEP, /* regular sleep mode */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/cpu/shmobile/pm.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/shmobile/pm.c
--- linux-libre-4.9-gnu/arch/sh/kernel/cpu/shmobile/pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/cpu/shmobile/pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/io.h>
 #include <linux/suspend.h>
 #include <asm/suspend.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/bl_bit.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/crash_dump.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/crash_dump.c
--- linux-libre-4.9-gnu/arch/sh/kernel/crash_dump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/crash_dump.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@
 #include <linux/errno.h>
 #include <linux/crash_dump.h>
 #include <linux/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /**
  * copy_oldmem_page - copy one page from "oldmem"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/dma-nommu.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/dma-nommu.c
--- linux-libre-4.9-gnu/arch/sh/kernel/dma-nommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/dma-nommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,9 @@ static dma_addr_t nommu_map_page(struct
 	dma_addr_t addr = page_to_phys(page) + offset;
 
 	WARN_ON(size == 0);
-	dma_cache_sync(dev, page_address(page) + offset, size, dir);
+
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		dma_cache_sync(dev, page_address(page) + offset, size, dir);
 
 	return addr;
 }
@@ -35,7 +37,8 @@ static int nommu_map_sg(struct device *d
 	for_each_sg(sg, s, nents, i) {
 		BUG_ON(!sg_page(s));
 
-		dma_cache_sync(dev, sg_virt(s), s->length, dir);
+		if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+			dma_cache_sync(dev, sg_virt(s), s->length, dir);
 
 		s->dma_address = sg_phys(s);
 		s->dma_length = s->length;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/io_trapped.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/io_trapped.c
--- linux-libre-4.9-gnu/arch/sh/kernel/io_trapped.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/io_trapped.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <asm/mmu_context.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/io_trapped.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/irq.c
--- linux-libre-4.9-gnu/arch/sh/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/ratelimit.h>
 #include <asm/processor.h>
 #include <asm/machvec.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/thread_info.h>
 #include <cpu/mmu_context.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/kprobes.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/kprobes.c
--- linux-libre-4.9-gnu/arch/sh/kernel/kprobes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/kprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/kdebug.h>
 #include <linux/slab.h>
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/process_32.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/process_32.c
--- linux-libre-4.9-gnu/arch/sh/kernel/process_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/process_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/prefetch.h>
 #include <linux/stackprotector.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/fpu.h>
 #include <asm/syscalls.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/process_64.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/process_64.c
--- linux-libre-4.9-gnu/arch/sh/kernel/process_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/process_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/io.h>
 #include <asm/syscalls.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/fpu.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/ptrace_32.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/ptrace_32.c
--- linux-libre-4.9-gnu/arch/sh/kernel/ptrace_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/ptrace_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/elf.h>
 #include <linux/regset.h>
 #include <linux/hw_breakpoint.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/ptrace_64.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/ptrace_64.c
--- linux-libre-4.9-gnu/arch/sh/kernel/ptrace_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/ptrace_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <linux/elf.h>
 #include <linux/regset.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/setup.c
--- linux-libre-4.9-gnu/arch/sh/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/memblock.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/elf.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/sh_ksyms_64.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/sh_ksyms_64.c
--- linux-libre-4.9-gnu/arch/sh/kernel/sh_ksyms_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/sh_ksyms_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/screen_info.h>
 #include <asm/cacheflush.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/checksum.h>
 #include <asm/io.h>
 #include <asm/delay.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/signal_32.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/signal_32.c
--- linux-libre-4.9-gnu/arch/sh/kernel/signal_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/signal_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/io.h>
 #include <linux/tracehook.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 #include <asm/syscalls.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/signal_64.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/signal_64.c
--- linux-libre-4.9-gnu/arch/sh/kernel/signal_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/signal_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/stddef.h>
 #include <linux/tracehook.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 #include <asm/fpu.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/sys_sh32.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/sys_sh32.c
--- linux-libre-4.9-gnu/arch/sh/kernel/sys_sh32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/sys_sh32.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/fs.h>
 #include <linux/ipc.h>
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/syscalls.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/sys_sh.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/sys_sh.c
--- linux-libre-4.9-gnu/arch/sh/kernel/sys_sh.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/sys_sh.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/fs.h>
 #include <linux/ipc.h>
 #include <asm/syscalls.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
 #include <asm/cachectl.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/kernel/traps_64.c linux-libre-4.10-rc8-gnu/arch/sh/kernel/traps_64.c
--- linux-libre-4.9-gnu/arch/sh/kernel/traps_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/kernel/traps_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/sysctl.h>
 #include <linux/module.h>
 #include <linux/perf_event.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/alignment.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/math-emu/math.c linux-libre-4.10-rc8-gnu/arch/sh/math-emu/math.c
--- linux-libre-4.9-gnu/arch/sh/math-emu/math.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/math-emu/math.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/signal.h>
 #include <linux/perf_event.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/processor.h>
 #include <asm/io.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/cache-debugfs.c linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-debugfs.c
--- linux-libre-4.9-gnu/arch/sh/mm/cache-debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cache.h>
 #include <asm/io.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/cache-sh3.c linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-sh3.c
--- linux-libre-4.9-gnu/arch/sh/mm/cache-sh3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-sh3.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <asm/processor.h>
 #include <asm/cache.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/cache-sh5.c linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-sh5.c
--- linux-libre-4.9-gnu/arch/sh/mm/cache-sh5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-sh5.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <asm/processor.h>
 #include <asm/cache.h>
 #include <asm/pgalloc.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 
 extern void __weak sh4__flush_region_init(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/cache-sh7705.c linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-sh7705.c
--- linux-libre-4.9-gnu/arch/sh/mm/cache-sh7705.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/cache-sh7705.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <asm/processor.h>
 #include <asm/cache.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/extable_32.c linux-libre-4.10-rc8-gnu/arch/sh/mm/extable_32.c
--- linux-libre-4.9-gnu/arch/sh/mm/extable_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/extable_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/extable_64.c linux-libre-4.10-rc8-gnu/arch/sh/mm/extable_64.c
--- linux-libre-4.9-gnu/arch/sh/mm/extable_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/extable_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
  */
 #include <linux/rwsem.h>
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 extern unsigned long copy_user_memcpy, copy_user_memcpy_end;
 extern void __copy_user_fixup(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/nommu.c linux-libre-4.10-rc8-gnu/arch/sh/mm/nommu.c
--- linux-libre-4.9-gnu/arch/sh/mm/nommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/nommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/page.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * Nothing too terribly exciting here ..
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/pmb.c linux-libre-4.10-rc8-gnu/arch/sh/mm/pmb.c
--- linux-libre-4.9-gnu/arch/sh/mm/pmb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/pmb.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/vmalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/tlbex_64.c linux-libre-4.10-rc8-gnu/arch/sh/mm/tlbex_64.c
--- linux-libre-4.9-gnu/arch/sh/mm/tlbex_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/tlbex_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 #include <linux/kprobes.h>
 #include <asm/tlb.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/tlbflush_64.c linux-libre-4.10-rc8-gnu/arch/sh/mm/tlbflush_64.c
--- linux-libre-4.9-gnu/arch/sh/mm/tlbflush_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/tlbflush_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/tlb.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/mm/tlb-sh3.c linux-libre-4.10-rc8-gnu/arch/sh/mm/tlb-sh3.c
--- linux-libre-4.9-gnu/arch/sh/mm/tlb-sh3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/mm/tlb-sh3.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/interrupt.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sh/oprofile/backtrace.c linux-libre-4.10-rc8-gnu/arch/sh/oprofile/backtrace.c
--- linux-libre-4.9-gnu/arch/sh/oprofile/backtrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sh/oprofile/backtrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/mm.h>
 #include <asm/unwinder.h>
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sections.h>
 #include <asm/stacktrace.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/configs/sparc64_defconfig linux-libre-4.10-rc8-gnu/arch/sparc/configs/sparc64_defconfig
--- linux-libre-4.9-gnu/arch/sparc/configs/sparc64_defconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/configs/sparc64_defconfig	2017-02-12 16:03:20.000000000 -0500
@@ -213,6 +213,7 @@ CONFIG_SCHEDSTATS=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_UPROBE_EVENTS=y
 CONFIG_KEYS=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_TEST=m
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/checksum_32.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/checksum_32.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/checksum_32.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/checksum_32.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
  */
 
 #include <linux/in6.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/checksum_64.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/checksum_64.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/checksum_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/checksum_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
  */
 
 #include <linux/in6.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/sparc/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,6 @@ generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += module.h
-generic-y += mutex.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += serial.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/kdebug_64.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/kdebug_64.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/kdebug_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/kdebug_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,8 @@ enum die_val {
 	DIE_OOPS = 1,
 	DIE_DEBUG,	/* ta 0x70 */
 	DIE_DEBUG_2,	/* ta 0x71 */
+	DIE_BPT,	/* ta 0x73 */
+	DIE_SSTEP,	/* ta 0x74 */
 	DIE_DIE,
 	DIE_TRAP,
 	DIE_TRAP_TL1,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/mmu_context_64.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/mmu_context_64.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/mmu_context_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/mmu_context_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,15 +35,15 @@ void __tsb_context_switch(unsigned long
 static inline void tsb_context_switch(struct mm_struct *mm)
 {
 	__tsb_context_switch(__pa(mm->pgd),
-			     &mm->context.tsb_block[0],
+			     &mm->context.tsb_block[MM_TSB_BASE],
 #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-			     (mm->context.tsb_block[1].tsb ?
-			      &mm->context.tsb_block[1] :
+			     (mm->context.tsb_block[MM_TSB_HUGE].tsb ?
+			      &mm->context.tsb_block[MM_TSB_HUGE] :
 			      NULL)
 #else
 			     NULL
 #endif
-			     , __pa(&mm->context.tsb_descr[0]));
+			     , __pa(&mm->context.tsb_descr[MM_TSB_BASE]));
 }
 
 void tsb_grow(struct mm_struct *mm,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/pgtable_64.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/pgtable_64.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/pgtable_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/pgtable_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -826,7 +826,7 @@ static inline unsigned long __pmd_page(p
 #define pgd_page_vaddr(pgd)		\
 	((unsigned long) __va(pgd_val(pgd)))
 #define pgd_present(pgd)		(pgd_val(pgd) != 0U)
-#define pgd_clear(pgdp)			(pgd_val(*(pgd)) = 0UL)
+#define pgd_clear(pgdp)			(pgd_val(*(pgdp)) = 0UL)
 
 static inline unsigned long pud_large(pud_t pud)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/processor_32.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/processor_32.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/processor_32.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/processor_32.h	2017-02-12 16:03:20.000000000 -0500
@@ -119,7 +119,6 @@ extern struct task_struct *last_task_use
 int do_mathemu(struct pt_regs *regs, struct task_struct *fpt);
 
 #define cpu_relax()	barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 extern void (*sparc_idle)(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/processor_64.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/processor_64.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/processor_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/processor_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -216,7 +216,6 @@ unsigned long get_wchan(struct task_stru
 				     "nop\n\t"				\
 				     ".previous"			\
 				     ::: "memory")
-#define cpu_relax_lowlatency() cpu_relax()
 
 /* Prefetch support.  This is tuned for UltraSPARC-III and later.
  * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/ptrace.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/ptrace.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/ptrace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/ptrace.h	2017-02-12 16:03:20.000000000 -0500
@@ -61,7 +61,10 @@ extern union global_cpu_snapshot global_
 #define force_successful_syscall_return() set_thread_noerror(1)
 #define user_mode(regs) (!((regs)->tstate & TSTATE_PRIV))
 #define instruction_pointer(regs) ((regs)->tpc)
-#define instruction_pointer_set(regs, val) ((regs)->tpc = (val))
+#define instruction_pointer_set(regs, val) do { \
+		(regs)->tpc = (val); \
+		(regs)->tnpc = (val)+4; \
+	} while (0)
 #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP])
 static inline int is_syscall_success(struct pt_regs *regs)
 {
@@ -77,6 +80,36 @@ unsigned long profile_pc(struct pt_regs
 #else
 #define profile_pc(regs) instruction_pointer(regs)
 #endif
+
+#define MAX_REG_OFFSET (offsetof(struct pt_regs, magic))
+
+extern int regs_query_register_offset(const char *name);
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs:	pt_regs from which register value is gotten
+ * @offset:	offset number of the register.
+ *
+ * regs_get_register returns the value of a register whose
+ * offset from @regs. The @offset is the offset of the register
+ * in struct pt_regs. If @offset is bigger than MAX_REG_OFFSET,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+					     unsigned long offset)
+{
+	if (unlikely(offset >= MAX_REG_OFFSET))
+		return 0;
+	if (offset == PT_V9_Y)
+		return *(unsigned int *)((unsigned long)regs + offset);
+	return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/* Valid only for Kernel mode traps. */
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+	return regs->u_regs[UREG_I6];
+}
 #else /* __ASSEMBLY__ */
 #endif /* __ASSEMBLY__ */
 #else /* (defined(__sparc__) && defined(__arch64__)) */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/thread_info_64.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/thread_info_64.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/thread_info_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/thread_info_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -180,7 +180,7 @@ register struct thread_info *current_thr
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 /* flag bit 4 is available */
 #define TIF_UNALIGNED		5	/* allowed to do unaligned accesses */
-/* flag bit 6 is available */
+#define TIF_UPROBE		6	/* breakpointed or singlestepped */
 #define TIF_32BIT		7	/* 32-bit binary */
 #define TIF_NOHZ		8	/* in adaptive nohz mode */
 #define TIF_SECCOMP		9	/* secure computing */
@@ -199,6 +199,7 @@ register struct thread_info *current_thr
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_UNALIGNED		(1<<TIF_UNALIGNED)
+#define _TIF_UPROBE		(1<<TIF_UPROBE)
 #define _TIF_32BIT		(1<<TIF_32BIT)
 #define _TIF_NOHZ		(1<<TIF_NOHZ)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
@@ -209,7 +210,8 @@ register struct thread_info *current_thr
 #define _TIF_USER_WORK_MASK	((0xff << TI_FLAG_WSAVED_SHIFT) | \
 				 _TIF_DO_NOTIFY_RESUME_MASK | \
 				 _TIF_NEED_RESCHED)
-#define _TIF_DO_NOTIFY_RESUME_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING)
+#define _TIF_DO_NOTIFY_RESUME_MASK	(_TIF_NOTIFY_RESUME | \
+					 _TIF_SIGPENDING | _TIF_UPROBE)
 
 #define is_32bit_task()	(test_thread_flag(TIF_32BIT))
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/topology_64.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/topology_64.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/topology_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/topology_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,6 +4,7 @@
 #ifdef CONFIG_NUMA
 
 #include <asm/mmzone.h>
+#include <asm/cpudata.h>
 
 static inline int cpu_to_node(int cpu)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/ttable.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/ttable.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/ttable.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/ttable.h	2017-02-12 16:03:20.000000000 -0500
@@ -186,6 +186,12 @@
 #define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
 #endif
 
+#ifdef CONFIG_UPROBES
+#define UPROBES_TRAP(lvl) TRAP_ARG(uprobe_trap, lvl)
+#else
+#define UPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
+#endif
+
 #ifdef CONFIG_KGDB
 #define KGDB_TRAP(lvl) TRAP_IRQ(kgdb_trap, lvl)
 #else
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/asm/uprobes.h linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/uprobes.h
--- linux-libre-4.9-gnu/arch/sparc/include/asm/uprobes.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/asm/uprobes.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,59 @@
+#ifndef _ASM_UPROBES_H
+#define _ASM_UPROBES_H
+/*
+ * User-space Probes (UProbes) for sparc
+ *
+ * Copyright (C) 2013 Oracle, 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *     Jose E. Marchesi <jose.marchesi@oracle.com>
+ *	Eric Saint Etienne <eric.saint.etienne@oracle.com>
+ */
+
+typedef u32 uprobe_opcode_t;
+
+#define MAX_UINSN_BYTES		4
+#define UPROBE_XOL_SLOT_BYTES	(MAX_UINSN_BYTES * 2)
+
+#define UPROBE_SWBP_INSN_SIZE	4
+#define UPROBE_SWBP_INSN	0x91d02073 /* ta 0x73 */
+#define UPROBE_STP_INSN		0x91d02074 /* ta 0x74 */
+
+#define ANNUL_BIT (1 << 29)
+
+struct arch_uprobe {
+	union {
+		u8  insn[MAX_UINSN_BYTES];
+		u32 ixol;
+	};
+};
+
+struct arch_uprobe_task {
+	u32 saved_tpc;
+	u32 saved_tnpc;
+};
+
+struct task_struct;
+struct notifier_block;
+
+extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+extern int  arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data);
+extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+
+#endif	/* _ASM_UPROBES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/sparc/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/sparc/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -86,6 +86,8 @@
 
 #define SO_CNX_ADVICE		0x0037
 
+#define SCM_TIMESTAMPING_OPT_STATS	0x0038
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/Kconfig linux-libre-4.10-rc8-gnu/arch/sparc/Kconfig
--- linux-libre-4.9-gnu/arch/sparc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -155,6 +155,9 @@ config PGTABLE_LEVELS
 	default 4 if 64BIT
 	default 3
 
+config ARCH_SUPPORTS_UPROBES
+	def_bool y if SPARC64
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/apc.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/apc.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/apc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/apc.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 
 #include <asm/io.h>
 #include <asm/oplib.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/auxio.h>
 #include <asm/apc.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/iommu.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/iommu.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -415,7 +415,7 @@ static void dma_4u_unmap_page(struct dev
 		ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
 
 	/* Step 1: Kick data out of streaming buffers if necessary. */
-	if (strbuf->strbuf_enabled)
+	if (strbuf->strbuf_enabled && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 		strbuf_flush(strbuf, iommu, bus_addr, ctx,
 			     npages, direction);
 
@@ -640,7 +640,7 @@ static void dma_4u_unmap_sg(struct devic
 		base = iommu->page_table + entry;
 
 		dma_handle &= IO_PAGE_MASK;
-		if (strbuf->strbuf_enabled)
+		if (strbuf->strbuf_enabled && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 			strbuf_flush(strbuf, iommu, dma_handle, ctx,
 				     npages, direction);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/ioport.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ioport.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/ioport.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ioport.c	2017-02-12 16:03:20.000000000 -0500
@@ -527,7 +527,7 @@ static dma_addr_t pci32_map_page(struct
 static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
 			     enum dma_data_direction dir, unsigned long attrs)
 {
-	if (dir != PCI_DMA_TODEVICE)
+	if (dir != PCI_DMA_TODEVICE && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
 		dma_make_coherent(ba, PAGE_ALIGN(size));
 }
 
@@ -572,7 +572,7 @@ static void pci32_unmap_sg(struct device
 	struct scatterlist *sg;
 	int n;
 
-	if (dir != PCI_DMA_TODEVICE) {
+	if (dir != PCI_DMA_TODEVICE && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) {
 		for_each_sg(sgl, sg, nents, n) {
 			dma_make_coherent(sg_phys(sg), PAGE_ALIGN(sg->length));
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/irq_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/irq_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/irq_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/irq_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <asm/timer.h>
 #include <asm/smp.h>
 #include <asm/starfire.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cache.h>
 #include <asm/cpudata.h>
 #include <asm/auxio.h>
@@ -1021,7 +1021,7 @@ static void __init alloc_one_queue(unsig
 	unsigned long order = get_order(size);
 	unsigned long p;
 
-	p = __get_free_pages(GFP_KERNEL, order);
+	p = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
 	if (!p) {
 		prom_printf("SUN4V: Error, cannot allocate queue.\n");
 		prom_halt();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/kprobes.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/kprobes.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/kprobes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/kprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/context_tracking.h>
 #include <asm/signal.h>
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* We do not have hardware single-stepping on sparc64.
  * So we implement software single-stepping with breakpoint
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/leon_kernel.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/leon_kernel.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/leon_kernel.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/leon_kernel.c	2017-02-12 16:03:20.000000000 -0500
@@ -349,37 +349,37 @@ void __init leon_init_timers(void)
 
 	/* Find GPTIMER Timer Registers base address otherwise bail out. */
 	nnp = rootnp;
-	do {
-		np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
-		if (!np) {
-			np = of_find_node_by_name(nnp, "01_011");
-			if (!np)
-				goto bad;
-		}
 
-		ampopts = 0;
-		pp = of_find_property(np, "ampopts", &len);
-		if (pp) {
-			ampopts = *(int *)pp->value;
-			if (ampopts == 0) {
-				/* Skip this instance, resource already
-				 * allocated by other OS */
-				nnp = np;
-				continue;
-			}
+retry:
+	np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
+	if (!np) {
+		np = of_find_node_by_name(nnp, "01_011");
+		if (!np)
+			goto bad;
+	}
+
+	ampopts = 0;
+	pp = of_find_property(np, "ampopts", &len);
+	if (pp) {
+		ampopts = *(int *)pp->value;
+		if (ampopts == 0) {
+			/* Skip this instance, resource already
+			 * allocated by other OS */
+			nnp = np;
+			goto retry;
 		}
+	}
 
-		/* Select Timer-Instance on Timer Core. Default is zero */
-		leon3_gptimer_idx = ampopts & 0x7;
+	/* Select Timer-Instance on Timer Core. Default is zero */
+	leon3_gptimer_idx = ampopts & 0x7;
 
-		pp = of_find_property(np, "reg", &len);
-		if (pp)
-			leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
-						pp->value;
-		pp = of_find_property(np, "interrupts", &len);
-		if (pp)
-			leon3_gptimer_irq = *(unsigned int *)pp->value;
-	} while (0);
+	pp = of_find_property(np, "reg", &len);
+	if (pp)
+		leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
+					pp->value;
+	pp = of_find_property(np, "interrupts", &len);
+	if (pp)
+		leon3_gptimer_irq = *(unsigned int *)pp->value;
 
 	if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq))
 		goto bad;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/Makefile linux-libre-4.10-rc8-gnu/arch/sparc/kernel/Makefile
--- linux-libre-4.9-gnu/arch/sparc/kernel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -116,4 +116,5 @@ obj-$(CONFIG_COMPAT)    += $(audit--y)
 pc--$(CONFIG_PERF_EVENTS) := perf_event.o
 obj-$(CONFIG_SPARC64)	+= $(pc--y)
 
+obj-$(CONFIG_UPROBES)	+= uprobes.o
 obj-$(CONFIG_SPARC64)	+= jump_label.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/mdesc.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/mdesc.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/mdesc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/mdesc.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <asm/hypervisor.h>
 #include <asm/mdesc.h>
 #include <asm/prom.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/oplib.h>
 #include <asm/smp.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/nmi.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/nmi.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/nmi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/nmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@ static int panic_on_timeout;
  */
 atomic_t nmi_active = ATOMIC_INIT(0);		/* oprofile uses this */
 EXPORT_SYMBOL(nmi_active);
-
+static int nmi_init_done;
 static unsigned int nmi_hz = HZ;
 static DEFINE_PER_CPU(short, wd_enabled);
 static int endflag __initdata;
@@ -153,6 +153,8 @@ static void report_broken_nmi(int cpu, i
 
 void stop_nmi_watchdog(void *unused)
 {
+	if (!__this_cpu_read(wd_enabled))
+		return;
 	pcr_ops->write_pcr(0, pcr_ops->pcr_nmi_disable);
 	__this_cpu_write(wd_enabled, 0);
 	atomic_dec(&nmi_active);
@@ -207,6 +209,9 @@ error:
 
 void start_nmi_watchdog(void *unused)
 {
+	if (__this_cpu_read(wd_enabled))
+		return;
+
 	__this_cpu_write(wd_enabled, 1);
 	atomic_inc(&nmi_active);
 
@@ -259,6 +264,8 @@ int __init nmi_init(void)
 		}
 	}
 
+	nmi_init_done = 1;
+
 	return err;
 }
 
@@ -270,3 +277,38 @@ static int __init setup_nmi_watchdog(cha
 	return 0;
 }
 __setup("nmi_watchdog=", setup_nmi_watchdog);
+
+/*
+ * sparc specific NMI watchdog enable function.
+ * Enables watchdog if it is not enabled already.
+ */
+int watchdog_nmi_enable(unsigned int cpu)
+{
+	if (atomic_read(&nmi_active) == -1) {
+		pr_warn("NMI watchdog cannot be enabled or disabled\n");
+		return -1;
+	}
+
+	/*
+	 * watchdog thread could start even before nmi_init is called.
+	 * Just Return in that case. Let nmi_init finish the init
+	 * process first.
+	 */
+	if (!nmi_init_done)
+		return 0;
+
+	smp_call_function_single(cpu, start_nmi_watchdog, NULL, 1);
+
+	return 0;
+}
+/*
+ * sparc specific NMI watchdog disable function.
+ * Disables watchdog if it is not disabled already.
+ */
+void watchdog_nmi_disable(unsigned int cpu)
+{
+	if (atomic_read(&nmi_active) == -1)
+		pr_warn_once("NMI watchdog cannot be enabled or disabled\n");
+	else
+		smp_call_function_single(cpu, stop_nmi_watchdog, NULL, 1);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/pci.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pci.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/pcic.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pcic.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/pcic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pcic.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <asm/pcic.h>
 #include <asm/timex.h>
 #include <asm/timer.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq_regs.h>
 
 #include "kernel.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/pci_sun4v.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pci_sun4v.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/pci_sun4v.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pci_sun4v.c	2017-02-12 16:03:20.000000000 -0500
@@ -242,6 +242,7 @@ static void *dma_4v_alloc_coherent(struc
 	return ret;
 
 iommu_map_fail:
+	local_irq_restore(flags);
 	iommu_tbl_range_free(tbl, *dma_addrp, npages, IOMMU_ERROR_CODE);
 
 range_alloc_fail:
@@ -414,6 +415,7 @@ bad:
 	return DMA_ERROR_CODE;
 
 iommu_map_fail:
+	local_irq_restore(flags);
 	iommu_tbl_range_free(tbl, bus_addr, npages, IOMMU_ERROR_CODE);
 	return DMA_ERROR_CODE;
 }
@@ -478,11 +480,10 @@ static int dma_4v_map_sg(struct device *
 	BUG_ON(direction == DMA_NONE);
 
 	iommu = dev->archdata.iommu;
-	atu = iommu->atu;
-
 	if (nelems == 0 || !iommu)
 		return 0;
-	
+	atu = iommu->atu;
+
 	prot = HV_PCI_MAP_ATTR_READ;
 	if (direction != DMA_TO_DEVICE)
 		prot |= HV_PCI_MAP_ATTR_WRITE;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/pmc.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pmc.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/pmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/pmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 
 #include <asm/io.h>
 #include <asm/oplib.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/auxio.h>
 #include <asm/processor.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/power.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/power.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/power.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/power.c	2017-02-12 16:03:20.000000000 -0500
@@ -67,9 +67,4 @@ static struct platform_driver power_driv
 	},
 };
 
-static int __init power_init(void)
-{
-	return platform_driver_register(&power_driver);
-}
-
-device_initcall(power_init);
+builtin_platform_driver(power_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/process_32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/process_32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/process_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/process_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 
 #include <asm/auxio.h>
 #include <asm/oplib.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/process_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/process_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/process_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/process_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <linux/nmi.h>
 #include <linux/context_tracking.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/ptrace_32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ptrace_32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/ptrace_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ptrace_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/tracehook.h>
 
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 
 #include "kernel.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/ptrace_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ptrace_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/ptrace_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ptrace_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 
 #include <asm/asi.h>
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/psrcompat.h>
 #include <asm/visasm.h>
 #include <asm/spitfire.h>
@@ -46,6 +46,43 @@
 
 /* #define ALLOW_INIT_TRACING */
 
+struct pt_regs_offset {
+	const char *name;
+	int offset;
+};
+
+#define REG_OFFSET_NAME(n, r) \
+	{.name = n, .offset = (PT_V9_##r)}
+#define REG_OFFSET_END {.name = NULL, .offset = 0}
+
+static const struct pt_regs_offset regoffset_table[] = {
+	REG_OFFSET_NAME("g0", G0),
+	REG_OFFSET_NAME("g1", G1),
+	REG_OFFSET_NAME("g2", G2),
+	REG_OFFSET_NAME("g3", G3),
+	REG_OFFSET_NAME("g4", G4),
+	REG_OFFSET_NAME("g5", G5),
+	REG_OFFSET_NAME("g6", G6),
+	REG_OFFSET_NAME("g7", G7),
+
+	REG_OFFSET_NAME("i0", I0),
+	REG_OFFSET_NAME("i1", I1),
+	REG_OFFSET_NAME("i2", I2),
+	REG_OFFSET_NAME("i3", I3),
+	REG_OFFSET_NAME("i4", I4),
+	REG_OFFSET_NAME("i5", I5),
+	REG_OFFSET_NAME("i6", I6),
+	REG_OFFSET_NAME("i7", I7),
+
+	REG_OFFSET_NAME("tstate", TSTATE),
+	REG_OFFSET_NAME("pc", TPC),
+	REG_OFFSET_NAME("npc", TNPC),
+	REG_OFFSET_NAME("y", Y),
+	REG_OFFSET_NAME("lr", I7),
+
+	REG_OFFSET_END,
+};
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -1107,3 +1144,20 @@ asmlinkage void syscall_trace_leave(stru
 	if (test_thread_flag(TIF_NOHZ))
 		user_enter();
 }
+
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name:	the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+	const struct pt_regs_offset *roff;
+
+	for (roff = regoffset_table; roff->name != NULL; roff++)
+		if (!strcmp(roff->name, name))
+			return roff->offset;
+	return -EINVAL;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/signal_32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/signal_32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/signal_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/signal_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/bitops.h>
 #include <linux/tracehook.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/signal32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/signal32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/signal32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/signal32.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/bitops.h>
 #include <linux/tracehook.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/pgtable.h>
 #include <asm/psrcompat.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/signal_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/signal_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/signal_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/signal_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/bitops.h>
 #include <linux/context_tracking.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace.h>
 #include <asm/pgtable.h>
 #include <asm/fpumacro.h>
@@ -545,6 +545,8 @@ static void do_signal(struct pt_regs *re
 void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
 {
 	user_exit();
+	if (thread_info_flags & _TIF_UPROBE)
+		uprobe_notify_resume(regs);
 	if (thread_info_flags & _TIF_SIGPENDING)
 		do_signal(regs, orig_i0);
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/smp_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/smp_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/smp_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/smp_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/oplib.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/starfire.h>
 #include <asm/tlb.h>
 #include <asm/sections.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/sstate.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sstate.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/sstate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sstate.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,8 +43,8 @@ static const char poweroff_msg[32] __att
 	"Linux powering off";
 static const char rebooting_msg[32] __attribute__((aligned(32))) =
 	"Linux rebooting";
-static const char panicing_msg[32] __attribute__((aligned(32))) =
-	"Linux panicing";
+static const char panicking_msg[32] __attribute__((aligned(32))) =
+	"Linux panicking";
 
 static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused)
 {
@@ -76,7 +76,7 @@ static struct notifier_block sstate_rebo
 
 static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr)
 {
-	do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg);
+	do_set_sstate(HV_SOFT_STATE_TRANSITION, panicking_msg);
 
 	return NOTIFY_DONE;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/sysfs.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sysfs.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -221,7 +221,7 @@ static struct device_attribute cpu_core_
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
-static void register_cpu_online(unsigned int cpu)
+static int register_cpu_online(unsigned int cpu)
 {
 	struct cpu *c = &per_cpu(cpu_devices, cpu);
 	struct device *s = &c->dev;
@@ -231,11 +231,12 @@ static void register_cpu_online(unsigned
 		device_create_file(s, &cpu_core_attrs[i]);
 
 	register_mmu_stats(s);
+	return 0;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void unregister_cpu_online(unsigned int cpu)
+static int unregister_cpu_online(unsigned int cpu)
 {
+#ifdef CONFIG_HOTPLUG_CPU
 	struct cpu *c = &per_cpu(cpu_devices, cpu);
 	struct device *s = &c->dev;
 	int i;
@@ -243,33 +244,10 @@ static void unregister_cpu_online(unsign
 	unregister_mmu_stats(s);
 	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
 		device_remove_file(s, &cpu_core_attrs[i]);
-}
 #endif
-
-static int sysfs_cpu_notify(struct notifier_block *self,
-				      unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned int)(long)hcpu;
-
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		register_cpu_online(cpu);
-		break;
-#ifdef CONFIG_HOTPLUG_CPU
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		unregister_cpu_online(cpu);
-		break;
-#endif
-	}
-	return NOTIFY_OK;
+	return 0;
 }
 
-static struct notifier_block sysfs_cpu_nb = {
-	.notifier_call	= sysfs_cpu_notify,
-};
-
 static void __init check_mmu_stats(void)
 {
 	unsigned long dummy1, err;
@@ -294,26 +272,21 @@ static void register_nodes(void)
 
 static int __init topology_init(void)
 {
-	int cpu;
+	int cpu, ret;
 
 	register_nodes();
 
 	check_mmu_stats();
 
-	cpu_notifier_register_begin();
-
 	for_each_possible_cpu(cpu) {
 		struct cpu *c = &per_cpu(cpu_devices, cpu);
 
 		register_cpu(c, cpu);
-		if (cpu_online(cpu))
-			register_cpu_online(cpu);
 	}
 
-	__register_cpu_notifier(&sysfs_cpu_nb);
-
-	cpu_notifier_register_done();
-
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "sparc/topology:online",
+				register_cpu_online, unregister_cpu_online);
+	WARN_ON(ret < 0);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/sys_sparc_32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sys_sparc_32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/sys_sparc_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sys_sparc_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/smp.h>
 #include <linux/ipc.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 
 #include "systbls.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/sys_sparc32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sys_sparc32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/sys_sparc32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sys_sparc32.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 #include <linux/slab.h>
 
 #include <asm/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/fpumacro.h>
 #include <asm/mmu_context.h>
 #include <asm/compat_signal.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/sys_sparc_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sys_sparc_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/sys_sparc_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/sys_sparc_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/export.h>
 #include <linux/context_tracking.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/utrap.h>
 #include <asm/unistd.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/time_32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/time_32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/time_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/time_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -148,7 +148,7 @@ static unsigned int sbus_cycles_offset(v
 	return offset;
 }
 
-static cycle_t timer_cs_read(struct clocksource *cs)
+static u64 timer_cs_read(struct clocksource *cs)
 {
 	unsigned int seq, offset;
 	u64 cycles;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/time_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/time_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/time_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/time_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
 #include <asm/smp.h>
 #include <asm/sections.h>
 #include <asm/cpudata.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq_regs.h>
 
 #include "entry.h"
@@ -770,7 +770,7 @@ void udelay(unsigned long usecs)
 }
 EXPORT_SYMBOL(udelay);
 
-static cycle_t clocksource_tick_read(struct clocksource *cs)
+static u64 clocksource_tick_read(struct clocksource *cs)
 {
 	return tick_ops->get_tick();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/traps_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/traps_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/traps_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/traps_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/unistd.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/fpumacro.h>
 #include <asm/lsu.h>
 #include <asm/dcu.h>
@@ -85,7 +85,7 @@ static void dump_tl1_traplog(struct tl1_
 
 void bad_trap(struct pt_regs *regs, long lvl)
 {
-	char buffer[32];
+	char buffer[36];
 	siginfo_t info;
 
 	if (notify_die(DIE_TRAP, "bad trap", regs,
@@ -116,7 +116,7 @@ void bad_trap(struct pt_regs *regs, long
 
 void bad_trap_tl1(struct pt_regs *regs, long lvl)
 {
-	char buffer[32];
+	char buffer[36];
 	
 	if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
 		       0, lvl, SIGTRAP) == NOTIFY_STOP)
@@ -2051,6 +2051,73 @@ void sun4v_resum_overflow(struct pt_regs
 	atomic_inc(&sun4v_resum_oflow_cnt);
 }
 
+/* Given a set of registers, get the virtual addressi that was being accessed
+ * by the faulting instructions at tpc.
+ */
+static unsigned long sun4v_get_vaddr(struct pt_regs *regs)
+{
+	unsigned int insn;
+
+	if (!copy_from_user(&insn, (void __user *)regs->tpc, 4)) {
+		return compute_effective_address(regs, insn,
+						 (insn >> 25) & 0x1f);
+	}
+	return 0;
+}
+
+/* Attempt to handle non-resumable errors generated from userspace.
+ * Returns true if the signal was handled, false otherwise.
+ */
+bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
+				  struct sun4v_error_entry *ent) {
+
+	unsigned int attrs = ent->err_attrs;
+
+	if (attrs & SUN4V_ERR_ATTRS_MEMORY) {
+		unsigned long addr = ent->err_raddr;
+		siginfo_t info;
+
+		if (addr == ~(u64)0) {
+			/* This seems highly unlikely to ever occur */
+			pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory error detected in unknown location!\n");
+		} else {
+			unsigned long page_cnt = DIV_ROUND_UP(ent->err_size,
+							      PAGE_SIZE);
+
+			/* Break the unfortunate news. */
+			pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory failed at %016lX\n",
+				 addr);
+			pr_emerg("SUN4V NON-RECOVERABLE ERROR:   Claiming %lu ages.\n",
+				 page_cnt);
+
+			while (page_cnt-- > 0) {
+				if (pfn_valid(addr >> PAGE_SHIFT))
+					get_page(pfn_to_page(addr >> PAGE_SHIFT));
+				addr += PAGE_SIZE;
+			}
+		}
+		info.si_signo = SIGKILL;
+		info.si_errno = 0;
+		info.si_trapno = 0;
+		force_sig_info(info.si_signo, &info, current);
+
+		return true;
+	}
+	if (attrs & SUN4V_ERR_ATTRS_PIO) {
+		siginfo_t info;
+
+		info.si_signo = SIGBUS;
+		info.si_code = BUS_ADRERR;
+		info.si_addr = (void __user *)sun4v_get_vaddr(regs);
+		force_sig_info(info.si_signo, &info, current);
+
+		return true;
+	}
+
+	/* Default to doing nothing */
+	return false;
+}
+
 /* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
  * Log the event, clear the first word of the entry, and die.
  */
@@ -2075,6 +2142,12 @@ void sun4v_nonresum_error(struct pt_regs
 
 	put_cpu();
 
+	if (!(regs->tstate & TSTATE_PRIV) &&
+	    sun4v_nonresum_error_user_handled(regs, &local_copy)) {
+		/* DON'T PANIC: This userspace error was handled. */
+		return;
+	}
+
 #ifdef CONFIG_PCI
 	/* Check for the special PCI poke sequence. */
 	if (pci_poke_in_progress && pci_poke_cpu == cpu) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/ttable_64.S linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ttable_64.S
--- linux-libre-4.9-gnu/arch/sparc/kernel/ttable_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/ttable_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -165,7 +165,7 @@ tl0_resv169:	BTRAP(0x169) BTRAP(0x16a) B
 tl0_linux64:	LINUX_64BIT_SYSCALL_TRAP
 tl0_gsctx:	TRAP(sparc64_get_context) TRAP(sparc64_set_context)
 tl0_resv170:	KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) KGDB_TRAP(0x172)
-tl0_resv173:	BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
+tl0_resv173:	UPROBES_TRAP(0x173) UPROBES_TRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
 tl0_resv178:	BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
 tl0_resv17d:	BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
 #define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/unaligned_32.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/unaligned_32.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/unaligned_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/unaligned_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/mm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/smp.h>
 #include <linux/perf_event.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/unaligned_64.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/unaligned_64.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/unaligned_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/unaligned_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <asm/ptrace.h>
 #include <asm/pstate.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/smp.h>
 #include <linux/bitops.h>
 #include <linux/perf_event.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/uprobes.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/uprobes.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/uprobes.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/uprobes.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,331 @@
+/*
+ * User-space Probes (UProbes) for sparc
+ *
+ * Copyright (C) 2013 Oracle 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *	Jose E. Marchesi <jose.marchesi@oracle.com>
+ *	Eric Saint Etienne <eric.saint.etienne@oracle.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/highmem.h>
+#include <linux/uprobes.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h> /* For struct task_struct */
+#include <linux/kdebug.h>
+
+#include <asm/cacheflush.h>
+#include <linux/uaccess.h>
+
+/* Compute the address of the breakpoint instruction and return it.
+ *
+ * Note that uprobe_get_swbp_addr is defined as a weak symbol in
+ * kernel/events/uprobe.c.
+ */
+unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
+{
+	return instruction_pointer(regs);
+}
+
+static void copy_to_page(struct page *page, unsigned long vaddr,
+			 const void *src, int len)
+{
+	void *kaddr = kmap_atomic(page);
+
+	memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len);
+	kunmap_atomic(kaddr);
+}
+
+/* Fill in the xol area with the probed instruction followed by the
+ * single-step trap.  Some fixups in the copied instruction are
+ * performed at this point.
+ *
+ * Note that uprobe_xol_copy is defined as a weak symbol in
+ * kernel/events/uprobe.c.
+ */
+void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
+			   void *src, unsigned long len)
+{
+	const u32 stp_insn = UPROBE_STP_INSN;
+	u32 insn = *(u32 *) src;
+
+	/* Branches annulling their delay slot must be fixed to not do
+	 * so.  Clearing the annul bit on these instructions we can be
+	 * sure the single-step breakpoint in the XOL slot will be
+	 * executed.
+	 */
+
+	u32 op = (insn >> 30) & 0x3;
+	u32 op2 = (insn >> 22) & 0x7;
+
+	if (op == 0 &&
+	    (op2 == 1 || op2 == 2 || op2 == 3 || op2 == 5 || op2 == 6) &&
+	    (insn & ANNUL_BIT) == ANNUL_BIT)
+		insn &= ~ANNUL_BIT;
+
+	copy_to_page(page, vaddr, &insn, len);
+	copy_to_page(page, vaddr+len, &stp_insn, 4);
+}
+
+
+/* Instruction analysis/validity.
+ *
+ * This function returns 0 on success or a -ve number on error.
+ */
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
+			     struct mm_struct *mm, unsigned long addr)
+{
+	/* Any unsupported instruction?  Then return -EINVAL  */
+	return 0;
+}
+
+/* If INSN is a relative control transfer instruction, return the
+ * corrected branch destination value.
+ *
+ * Note that regs->tpc and regs->tnpc still hold the values of the
+ * program counters at the time of the single-step trap due to the
+ * execution of the UPROBE_STP_INSN at utask->xol_vaddr + 4.
+ *
+ */
+static unsigned long relbranch_fixup(u32 insn, struct uprobe_task *utask,
+				     struct pt_regs *regs)
+{
+	/* Branch not taken, no mods necessary.  */
+	if (regs->tnpc == regs->tpc + 0x4UL)
+		return utask->autask.saved_tnpc + 0x4UL;
+
+	/* The three cases are call, branch w/prediction,
+	 * and traditional branch.
+	 */
+	if ((insn & 0xc0000000) == 0x40000000 ||
+	    (insn & 0xc1c00000) == 0x00400000 ||
+	    (insn & 0xc1c00000) == 0x00800000) {
+		unsigned long real_pc = (unsigned long) utask->vaddr;
+		unsigned long ixol_addr = utask->xol_vaddr;
+
+		/* The instruction did all the work for us
+		 * already, just apply the offset to the correct
+		 * instruction location.
+		 */
+		return (real_pc + (regs->tnpc - ixol_addr));
+	}
+
+	/* It is jmpl or some other absolute PC modification instruction,
+	 * leave NPC as-is.
+	 */
+	return regs->tnpc;
+}
+
+/* If INSN is an instruction which writes its PC location
+ * into a destination register, fix that up.
+ */
+static int retpc_fixup(struct pt_regs *regs, u32 insn,
+		       unsigned long real_pc)
+{
+	unsigned long *slot = NULL;
+	int rc = 0;
+
+	/* Simplest case is 'call', which always uses %o7 */
+	if ((insn & 0xc0000000) == 0x40000000)
+		slot = &regs->u_regs[UREG_I7];
+
+	/* 'jmpl' encodes the register inside of the opcode */
+	if ((insn & 0xc1f80000) == 0x81c00000) {
+		unsigned long rd = ((insn >> 25) & 0x1f);
+
+		if (rd <= 15) {
+			slot = &regs->u_regs[rd];
+		} else {
+			unsigned long fp = regs->u_regs[UREG_FP];
+			/* Hard case, it goes onto the stack. */
+			flushw_all();
+
+			rd -= 16;
+			if (test_thread_64bit_stack(fp)) {
+				unsigned long __user *uslot =
+			(unsigned long __user *) (fp + STACK_BIAS) + rd;
+				rc = __put_user(real_pc, uslot);
+			} else {
+				unsigned int __user *uslot = (unsigned int
+						__user *) fp + rd;
+				rc = __put_user((u32) real_pc, uslot);
+			}
+		}
+	}
+	if (slot != NULL)
+		*slot = real_pc;
+	return rc;
+}
+
+/* Single-stepping can be avoided for certain instructions: NOPs and
+ * instructions that can be emulated.  This function determines
+ * whether the instruction where the uprobe is installed falls in one
+ * of these cases and emulates it.
+ *
+ * This function returns true if the single-stepping can be skipped,
+ * false otherwise.
+ */
+bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	/* We currently only emulate NOP instructions.
+	 */
+
+	if (auprobe->ixol == (1 << 24)) {
+		regs->tnpc += 4;
+		regs->tpc += 4;
+		return true;
+	}
+
+	return false;
+}
+
+/* Prepare to execute out of line.  At this point
+ * current->utask->xol_vaddr points to an allocated XOL slot properly
+ * initialized with the original instruction and the single-stepping
+ * trap instruction.
+ *
+ * This function returns 0 on success, any other number on error.
+ */
+int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+	struct arch_uprobe_task *autask = &current->utask->autask;
+
+	/* Save the current program counters so they can be restored
+	 * later.
+	 */
+	autask->saved_tpc = regs->tpc;
+	autask->saved_tnpc = regs->tnpc;
+
+	/* Adjust PC and NPC so the first instruction in the XOL slot
+	 * will be executed by the user task.
+	 */
+	instruction_pointer_set(regs, utask->xol_vaddr);
+
+	return 0;
+}
+
+/* Prepare to resume execution after the single-step.  Called after
+ * single-stepping. To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.
+ *
+ * This function returns 0 on success, any other number on error.
+ */
+int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+	struct arch_uprobe_task *autask = &utask->autask;
+	u32 insn = auprobe->ixol;
+	int rc = 0;
+
+	if (utask->state == UTASK_SSTEP_ACK) {
+		regs->tnpc = relbranch_fixup(insn, utask, regs);
+		regs->tpc = autask->saved_tnpc;
+		rc =  retpc_fixup(regs, insn, (unsigned long) utask->vaddr);
+	} else {
+		regs->tnpc = utask->vaddr+4;
+		regs->tpc = autask->saved_tnpc+4;
+	}
+	return rc;
+}
+
+/* Handler for uprobe traps.  This is called from the traps table and
+ * triggers the proper die notification.
+ */
+asmlinkage void uprobe_trap(struct pt_regs *regs,
+			    unsigned long trap_level)
+{
+	BUG_ON(trap_level != 0x173 && trap_level != 0x174);
+
+	/* We are only interested in user-mode code.  Uprobe traps
+	 * shall not be present in kernel code.
+	 */
+	if (!user_mode(regs)) {
+		local_irq_enable();
+		bad_trap(regs, trap_level);
+		return;
+	}
+
+	/* trap_level == 0x173 --> ta 0x73
+	 * trap_level == 0x174 --> ta 0x74
+	 */
+	if (notify_die((trap_level == 0x173) ? DIE_BPT : DIE_SSTEP,
+				(trap_level == 0x173) ? "bpt" : "sstep",
+				regs, 0, trap_level, SIGTRAP) != NOTIFY_STOP)
+		bad_trap(regs, trap_level);
+}
+
+/* Callback routine for handling die notifications.
+*/
+int arch_uprobe_exception_notify(struct notifier_block *self,
+				 unsigned long val, void *data)
+{
+	int ret = NOTIFY_DONE;
+	struct die_args *args = (struct die_args *)data;
+
+	/* We are only interested in userspace traps */
+	if (args->regs && !user_mode(args->regs))
+		return NOTIFY_DONE;
+
+	switch (val) {
+	case DIE_BPT:
+		if (uprobe_pre_sstep_notifier(args->regs))
+			ret = NOTIFY_STOP;
+		break;
+
+	case DIE_SSTEP:
+		if (uprobe_post_sstep_notifier(args->regs))
+			ret = NOTIFY_STOP;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/* This function gets called when a XOL instruction either gets
+ * trapped or the thread has a fatal signal, so reset the instruction
+ * pointer to its probed address.
+ */
+void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+{
+	struct uprobe_task *utask = current->utask;
+
+	instruction_pointer_set(regs, utask->vaddr);
+}
+
+/* If xol insn itself traps and generates a signal(Say,
+ * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped
+ * instruction jumps back to its own address.
+ */
+bool arch_uprobe_xol_was_trapped(struct task_struct *t)
+{
+	return false;
+}
+
+unsigned long
+arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
+				  struct pt_regs *regs)
+{
+	unsigned long orig_ret_vaddr = regs->u_regs[UREG_I7];
+
+	regs->u_regs[UREG_I7] = trampoline_vaddr-8;
+
+	return orig_ret_vaddr + 8;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/visemul.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/visemul.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/visemul.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/visemul.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <asm/ptrace.h>
 #include <asm/pstate.h>
 #include <asm/fpumacro.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 
 /* OPF field of various VIS instructions.  */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/kernel/windows.c linux-libre-4.10-rc8-gnu/arch/sparc/kernel/windows.c
--- linux-libre-4.9-gnu/arch/sparc/kernel/windows.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/kernel/windows.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/smp.h>
 
 #include <asm/cacheflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "kernel.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/math-emu/math_32.c linux-libre-4.10-rc8-gnu/arch/sparc/math-emu/math_32.c
--- linux-libre-4.9-gnu/arch/sparc/math-emu/math_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/math-emu/math_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,7 +68,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/perf_event.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "sfp-util_32.h"
 #include <math-emu/soft-fp.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/math-emu/math_64.c linux-libre-4.10-rc8-gnu/arch/sparc/math-emu/math_64.c
--- linux-libre-4.9-gnu/arch/sparc/math-emu/math_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/math-emu/math_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 
 #include <asm/fpumacro.h>
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 
 #include "sfp-util_64.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/mm/extable.c linux-libre-4.10-rc8-gnu/arch/sparc/mm/extable.c
--- linux-libre-4.9-gnu/arch/sparc/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
  */
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 void sort_extable(struct exception_table_entry *start,
 		  struct exception_table_entry *finish)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/sparc/mm/init_64.c linux-libre-4.10-rc8-gnu/arch/sparc/mm/init_64.c
--- linux-libre-4.9-gnu/arch/sparc/mm/init_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/sparc/mm/init_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <asm/oplib.h>
 #include <asm/iommu.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 #include <asm/dma.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/include/asm/cache.h linux-libre-4.10-rc8-gnu/arch/tile/include/asm/cache.h
--- linux-libre-4.9-gnu/arch/tile/include/asm/cache.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/include/asm/cache.h	2017-02-12 16:03:20.000000000 -0500
@@ -50,18 +50,15 @@
 
 /*
  * Originally we used small TLB pages for kernel data and grouped some
- * things together as "write once", enforcing the property at the end
+ * things together as ro-after-init, enforcing the property at the end
  * of initialization by making those pages read-only and non-coherent.
  * This allowed better cache utilization since cache inclusion did not
  * need to be maintained.  However, to do this requires an extra TLB
  * entry, which on balance is more of a performance hit than the
  * non-coherence is a performance gain, so we now just make "read
- * mostly" and "write once" be synonyms.  We keep the attribute
+ * mostly" and "ro-after-init" be synonyms.  We keep the attribute
  * separate in case we change our minds at a future date.
  */
-#define __write_once __read_mostly
-
-/* __ro_after_init is the generic name for the tile arch __write_once. */
 #define __ro_after_init __read_mostly
 
 #endif /* _ASM_TILE_CACHE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/tile/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/tile/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,6 @@ generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += msgbuf.h
-generic-y += mutex.h
 generic-y += param.h
 generic-y += parport.h
 generic-y += poll.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/tile/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/tile/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -264,8 +264,6 @@ static inline void cpu_relax(void)
 	barrier();
 }
 
-#define cpu_relax_lowlatency() cpu_relax()
-
 /* Info on this processor (see fs/proc/cpuinfo.c) */
 struct seq_operations;
 extern const struct seq_operations cpuinfo_op;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/include/asm/sections.h linux-libre-4.10-rc8-gnu/arch/tile/include/asm/sections.h
--- linux-libre-4.9-gnu/arch/tile/include/asm/sections.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/include/asm/sections.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,9 +19,6 @@
 
 #include <asm-generic/sections.h>
 
-/* Write-once data is writable only till the end of initialization. */
-extern char __w1data_begin[], __w1data_end[];
-
 extern char vdso_start[], vdso_end[];
 #ifdef CONFIG_COMPAT
 extern char vdso32_start[], vdso32_end[];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/module.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/module.c
--- linux-libre-4.9-gnu/arch/tile/kernel/module.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/module.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,29 +43,28 @@ void *module_alloc(unsigned long size)
 	int npages;
 
 	npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
-	pages = kmalloc(npages * sizeof(struct page *), GFP_KERNEL);
+	pages = kmalloc_array(npages, sizeof(*pages), GFP_KERNEL);
 	if (pages == NULL)
 		return NULL;
 	for (; i < npages; ++i) {
 		pages[i] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
 		if (!pages[i])
-			goto error;
+			goto free_pages;
 	}
 
 	area = __get_vm_area(size, VM_ALLOC, MEM_MODULE_START, MEM_MODULE_END);
 	if (!area)
-		goto error;
+		goto free_pages;
 	area->nr_pages = npages;
 	area->pages = pages;
 
 	if (map_vm_area(area, prot_rwx, pages)) {
 		vunmap(area->addr);
-		goto error;
+		goto free_pages;
 	}
 
 	return area->addr;
-
-error:
+ free_pages:
 	while (--i >= 0)
 		__free_page(pages[i]);
 	kfree(pages);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/pci.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/pci.c
--- linux-libre-4.9-gnu/arch/tile/kernel/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@ static int pci_probe = 1;
  * This flag tells if the platform is TILEmpower that needs
  * special configuration for the PLX switch chip.
  */
-int __write_once tile_plx_gen1;
+int __ro_after_init tile_plx_gen1;
 
 static struct pci_controller controllers[TILE_NUM_PCIE];
 static int num_controllers;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/pci-dma.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/pci-dma.c
--- linux-libre-4.9-gnu/arch/tile/kernel/pci-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/pci-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -213,10 +213,12 @@ static int tile_dma_map_sg(struct device
 
 	for_each_sg(sglist, sg, nents, i) {
 		sg->dma_address = sg_phys(sg);
-		__dma_prep_pa_range(sg->dma_address, sg->length, direction);
 #ifdef CONFIG_NEED_SG_DMA_LENGTH
 		sg->dma_length = sg->length;
 #endif
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
+		__dma_prep_pa_range(sg->dma_address, sg->length, direction);
 	}
 
 	return nents;
@@ -232,6 +234,8 @@ static void tile_dma_unmap_sg(struct dev
 	BUG_ON(!valid_dma_direction(direction));
 	for_each_sg(sglist, sg, nents, i) {
 		sg->dma_address = sg_phys(sg);
+		if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+			continue;
 		__dma_complete_pa_range(sg->dma_address, sg->length,
 					direction);
 	}
@@ -245,7 +249,8 @@ static dma_addr_t tile_dma_map_page(stru
 	BUG_ON(!valid_dma_direction(direction));
 
 	BUG_ON(offset + size > PAGE_SIZE);
-	__dma_prep_page(page, offset, size, direction);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		__dma_prep_page(page, offset, size, direction);
 
 	return page_to_pa(page) + offset;
 }
@@ -256,6 +261,9 @@ static void tile_dma_unmap_page(struct d
 {
 	BUG_ON(!valid_dma_direction(direction));
 
+	if (attrs & DMA_ATTR_SKIP_CPU_SYNC)
+		return;
+
 	__dma_complete_page(pfn_to_page(PFN_DOWN(dma_address)),
 			    dma_address & (PAGE_SIZE - 1), size, direction);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/pci_gx.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/pci_gx.c
--- linux-libre-4.9-gnu/arch/tile/kernel/pci_gx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/pci_gx.c	2017-02-12 16:03:20.000000000 -0500
@@ -131,7 +131,7 @@ static int tile_irq_cpu(int irq)
 
 	count = cpumask_weight(&intr_cpus_map);
 	if (unlikely(count == 0)) {
-		pr_warn("intr_cpus_map empty, interrupts will be delievered to dataplane tiles\n");
+		pr_warn("intr_cpus_map empty, interrupts will be delivered to dataplane tiles\n");
 		return irq % (smp_height * smp_width);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/process.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/process.c
--- linux-libre-4.9-gnu/arch/tile/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <asm/syscalls.h>
 #include <asm/traps.h>
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #ifdef CONFIG_HARDWALL
 #include <asm/hardwall.h>
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/tile/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -111,7 +111,7 @@ static int tile_gpr_set(struct task_stru
 			  const void *kbuf, const void __user *ubuf)
 {
 	int ret;
-	struct pt_regs regs;
+	struct pt_regs regs = *task_pt_regs(target);
 
 	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &regs, 0,
 				 sizeof(regs));
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/setup.c
--- linux-libre-4.9-gnu/arch/tile/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,7 @@
 static inline int ABS(int x) { return x >= 0 ? x : -x; }
 
 /* Chip information */
-char chip_model[64] __write_once;
+char chip_model[64] __ro_after_init;
 
 #ifdef CONFIG_VT
 struct screen_info screen_info;
@@ -97,17 +97,17 @@ int node_controller[MAX_NUMNODES] = { [0
 #ifdef CONFIG_HIGHMEM
 /* Map information from VAs to PAs */
 unsigned long pbase_map[1 << (32 - HPAGE_SHIFT)]
-  __write_once __attribute__((aligned(L2_CACHE_BYTES)));
+  __ro_after_init __attribute__((aligned(L2_CACHE_BYTES)));
 EXPORT_SYMBOL(pbase_map);
 
 /* Map information from PAs to VAs */
 void *vbase_map[NR_PA_HIGHBIT_VALUES]
-  __write_once __attribute__((aligned(L2_CACHE_BYTES)));
+  __ro_after_init __attribute__((aligned(L2_CACHE_BYTES)));
 EXPORT_SYMBOL(vbase_map);
 #endif
 
 /* Node number as a function of the high PA bits */
-int highbits_to_node[NR_PA_HIGHBIT_VALUES] __write_once;
+int highbits_to_node[NR_PA_HIGHBIT_VALUES] __ro_after_init;
 EXPORT_SYMBOL(highbits_to_node);
 
 static unsigned int __initdata maxmem_pfn = -1U;
@@ -844,11 +844,11 @@ static void __init zone_sizes_init(void)
 #ifdef CONFIG_NUMA
 
 /* which logical CPUs are on which nodes */
-struct cpumask node_2_cpu_mask[MAX_NUMNODES] __write_once;
+struct cpumask node_2_cpu_mask[MAX_NUMNODES] __ro_after_init;
 EXPORT_SYMBOL(node_2_cpu_mask);
 
 /* which node each logical CPU is on */
-char cpu_2_node[NR_CPUS] __write_once __attribute__((aligned(L2_CACHE_BYTES)));
+char cpu_2_node[NR_CPUS] __ro_after_init __attribute__((aligned(L2_CACHE_BYTES)));
 EXPORT_SYMBOL(cpu_2_node);
 
 /* Return cpu_to_node() except for cpus not yet assigned, which return -1 */
@@ -1269,7 +1269,7 @@ static void __init validate_va(void)
  * cpus plus any other cpus that are willing to share their cache.
  * It is set by hv_inquire_tiles(HV_INQ_TILES_LOTAR).
  */
-struct cpumask __write_once cpu_lotar_map;
+struct cpumask __ro_after_init cpu_lotar_map;
 EXPORT_SYMBOL(cpu_lotar_map);
 
 /*
@@ -1291,7 +1291,7 @@ EXPORT_SYMBOL(hash_for_home_map);
  * cache, those tiles will only appear in cpu_lotar_map, NOT in
  * cpu_cacheable_map, as they are a special case.
  */
-struct cpumask __write_once cpu_cacheable_map;
+struct cpumask __ro_after_init cpu_cacheable_map;
 EXPORT_SYMBOL(cpu_cacheable_map);
 
 static __initdata struct cpumask disabled_map;
@@ -1506,7 +1506,7 @@ void __init setup_arch(char **cmdline_p)
  * Set up per-cpu memory.
  */
 
-unsigned long __per_cpu_offset[NR_CPUS] __write_once;
+unsigned long __per_cpu_offset[NR_CPUS] __ro_after_init;
 EXPORT_SYMBOL(__per_cpu_offset);
 
 static size_t __initdata pfn_offset[MAX_NUMNODES] = { 0 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/single_step.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/single_step.c
--- linux-libre-4.9-gnu/arch/tile/kernel/single_step.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/single_step.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/prctl.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 #include <arch/abi.h>
 #include <arch/spr_def.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/smp.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/smp.c
--- linux-libre-4.9-gnu/arch/tile/kernel/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
  * We write to width and height with a single store in head_NN.S,
  * so make the variable aligned to "long".
  */
-HV_Topology smp_topology __write_once __aligned(sizeof(long));
+HV_Topology smp_topology __ro_after_init __aligned(sizeof(long));
 EXPORT_SYMBOL(smp_topology);
 
 #if CHIP_HAS_IPI()
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/time.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/time.c
--- linux-libre-4.9-gnu/arch/tile/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@
  */
 
 /* How many cycles per second we are running at. */
-static cycles_t cycles_per_sec __write_once;
+static cycles_t cycles_per_sec __ro_after_init;
 
 cycles_t get_clock_rate(void)
 {
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(get_cycles);
  */
 #define SCHED_CLOCK_SHIFT 10
 
-static unsigned long sched_clock_mult __write_once;
+static unsigned long sched_clock_mult __ro_after_init;
 
 static cycles_t clocksource_get_cycles(struct clocksource *cs)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/kernel/unaligned.c linux-libre-4.10-rc8-gnu/arch/tile/kernel/unaligned.c
--- linux-libre-4.9-gnu/arch/tile/kernel/unaligned.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/kernel/unaligned.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,12 +22,12 @@
 #include <linux/mman.h>
 #include <linux/types.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/extable.h>
 #include <linux/compat.h>
 #include <linux/prctl.h>
 #include <asm/cacheflush.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 #include <arch/abi.h>
 #include <arch/spr_def.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/lib/cacheflush.c linux-libre-4.10-rc8-gnu/arch/tile/lib/cacheflush.c
--- linux-libre-4.9-gnu/arch/tile/lib/cacheflush.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/lib/cacheflush.c	2017-02-12 16:03:20.000000000 -0500
@@ -138,19 +138,13 @@ finv_buffer_remote(void *buffer, size_t
 	if ((unsigned long)base < (unsigned long)buffer)
 		base = buffer;
 
-	/*
-	 * Fire all the loads we need.  The MAF only has eight entries
-	 * so we can have at most eight outstanding loads, so we
-	 * unroll by that amount.
-	 */
-#pragma unroll 8
+	/* Fire all the loads we need. */
 	for (; p >= base; p -= step_size)
 		force_load(p);
 
 	/*
 	 * Repeat, but with finv's instead of loads, to get rid of the
 	 * data we just loaded into our own cache and the old home L3.
-	 * No need to unroll since finv's don't target a register.
 	 * The finv's are guaranteed not to actually flush the data in
 	 * the buffer back to their home, since we just read it, so the
 	 * lines are clean in cache; we will only invalidate those lines.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/mm/extable.c linux-libre-4.10-rc8-gnu/arch/tile/mm/extable.c
--- linux-libre-4.9-gnu/arch/tile/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
  *   more details.
  */
 
-#include <linux/module.h>
+#include <linux/extable.h>
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/mm/fault.c linux-libre-4.10-rc8-gnu/arch/tile/mm/fault.c
--- linux-libre-4.9-gnu/arch/tile/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/tty.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/highmem.h>
-#include <linux/module.h>
+#include <linux/extable.h>
 #include <linux/kprobes.h>
 #include <linux/hugetlb.h>
 #include <linux/syscalls.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/mm/homecache.c linux-libre-4.10-rc8-gnu/arch/tile/mm/homecache.c
--- linux-libre-4.9-gnu/arch/tile/mm/homecache.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/mm/homecache.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@
  * The noallocl2 option suppresses all use of the L2 cache to cache
  * locally from a remote home.
  */
-static int __write_once noallocl2;
+static int __ro_after_init noallocl2;
 static int __init set_noallocl2(char *str)
 {
 	noallocl2 = 1;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/tile/mm/init.c linux-libre-4.10-rc8-gnu/arch/tile/mm/init.c
--- linux-libre-4.9-gnu/arch/tile/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/tile/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -190,9 +190,9 @@ static void __init page_table_range_init
 
 static int __initdata ktext_hash = 1;  /* .text pages */
 static int __initdata kdata_hash = 1;  /* .data and .bss pages */
-int __write_once hash_default = 1;     /* kernel allocator pages */
+int __ro_after_init hash_default = 1;     /* kernel allocator pages */
 EXPORT_SYMBOL(hash_default);
-int __write_once kstack_hash = 1;      /* if no homecaching, use h4h */
+int __ro_after_init kstack_hash = 1;      /* if no homecaching, use h4h */
 
 /*
  * CPUs to use to for striping the pages of kernel data.  If hash-for-home
@@ -203,7 +203,7 @@ int __write_once kstack_hash = 1;      /
 static __initdata struct cpumask kdata_mask;
 static __initdata int kdata_arg_seen;
 
-int __write_once kdata_huge;       /* if no homecaching, small pages */
+int __ro_after_init kdata_huge;       /* if no homecaching, small pages */
 
 
 /* Combine a generic pgprot_t with cache home to get a cache-aware pgprot. */
@@ -896,8 +896,8 @@ void __init pgtable_cache_init(void)
 		panic("pgtable_cache_init(): Cannot create pgd cache");
 }
 
-static long __write_once initfree = 1;
-static bool __write_once set_initfree_done;
+static long __ro_after_init initfree = 1;
+static bool __ro_after_init set_initfree_done;
 
 /* Select whether to free (1) or mark unusable (0) the __init pages. */
 static int __init set_initfree(char *str)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/harddog_kern.c linux-libre-4.10-rc8-gnu/arch/um/drivers/harddog_kern.c
--- linux-libre-4.9-gnu/arch/um/drivers/harddog_kern.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/harddog_kern.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
 #include <linux/mutex.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "mconsole.h"
 
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/hostaudio_kern.c linux-libre-4.10-rc8-gnu/arch/um/drivers/hostaudio_kern.c
--- linux-libre-4.9-gnu/arch/um/drivers/hostaudio_kern.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/hostaudio_kern.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 #include <linux/sound.h>
 #include <linux/soundcard.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <init.h>
 #include <os.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/mconsole_kern.c linux-libre-4.10-rc8-gnu/arch/um/drivers/mconsole_kern.c
--- linux-libre-4.9-gnu/arch/um/drivers/mconsole_kern.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/mconsole_kern.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/fs.h>
 #include <linux/mount.h>
 #include <linux/file.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/switch_to.h>
 
 #include <init.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/mmapper_kern.c linux-libre-4.10-rc8-gnu/arch/um/drivers/mmapper_kern.c
--- linux-libre-4.9-gnu/arch/um/drivers/mmapper_kern.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/mmapper_kern.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <mem_user.h>
 
 /* These are set in mmapper_init, which is called at boot time */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/net_kern.c linux-libre-4.10-rc8-gnu/arch/um/drivers/net_kern.c
--- linux-libre-4.9-gnu/arch/um/drivers/net_kern.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/net_kern.c	2017-02-12 16:03:20.000000000 -0500
@@ -256,13 +256,6 @@ static void uml_net_tx_timeout(struct ne
 	netif_wake_queue(dev);
 }
 
-static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
-{
-	dev->mtu = new_mtu;
-
-	return 0;
-}
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void uml_net_poll_controller(struct net_device *dev)
 {
@@ -374,7 +367,6 @@ static const struct net_device_ops uml_n
 	.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,
 	.ndo_validate_addr	= eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = uml_net_poll_controller,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/random.c linux-libre-4.10-rc8-gnu/arch/um/drivers/random.c
--- linux-libre-4.9-gnu/arch/um/drivers/random.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/random.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <irq_kern.h>
 #include <os.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/ubd.h linux-libre-4.10-rc8-gnu/arch/um/drivers/ubd.h
--- linux-libre-4.9-gnu/arch/um/drivers/ubd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/ubd.h	2017-02-12 16:03:20.000000000 -0500
@@ -11,5 +11,10 @@ extern int start_io_thread(unsigned long
 extern int io_thread(void *arg);
 extern int kernel_fd;
 
+extern int ubd_read_poll(int timeout);
+extern int ubd_write_poll(int timeout);
+
+#define UBD_REQ_BUFFER_SIZE 64
+
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/ubd_kern.c linux-libre-4.10-rc8-gnu/arch/um/drivers/ubd_kern.c
--- linux-libre-4.9-gnu/arch/um/drivers/ubd_kern.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/ubd_kern.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015-2016 Anton Ivanov (aivanov@brocade.com)
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
@@ -58,6 +59,17 @@ struct io_thread_req {
 	int error;
 };
 
+
+static struct io_thread_req * (*irq_req_buffer)[];
+static struct io_thread_req *irq_remainder;
+static int irq_remainder_size;
+
+static struct io_thread_req * (*io_req_buffer)[];
+static struct io_thread_req *io_remainder;
+static int io_remainder_size;
+
+
+
 static inline int ubd_test_bit(__u64 bit, unsigned char *data)
 {
 	__u64 n;
@@ -442,29 +454,91 @@ static void do_ubd_request(struct reques
 static int thread_fd = -1;
 static LIST_HEAD(restart);
 
-/* XXX - move this inside ubd_intr. */
+/* Function to read several request pointers at a time
+* handling fractional reads if (and as) needed
+*/
+
+static int bulk_req_safe_read(
+	int fd,
+	struct io_thread_req * (*request_buffer)[],
+	struct io_thread_req **remainder,
+	int *remainder_size,
+	int max_recs
+	)
+{
+	int n = 0;
+	int res = 0;
+
+	if (*remainder_size > 0) {
+		memmove(
+			(char *) request_buffer,
+			(char *) remainder, *remainder_size
+		);
+		n = *remainder_size;
+	}
+
+	res = os_read_file(
+			fd,
+			((char *) request_buffer) + *remainder_size,
+			sizeof(struct io_thread_req *)*max_recs
+				- *remainder_size
+		);
+	if (res > 0) {
+		n += res;
+		if ((n % sizeof(struct io_thread_req *)) > 0) {
+			/*
+			* Read somehow returned not a multiple of dword
+			* theoretically possible, but never observed in the
+			* wild, so read routine must be able to handle it
+			*/
+			*remainder_size = n % sizeof(struct io_thread_req *);
+			WARN(*remainder_size > 0, "UBD IPC read returned a partial result");
+			memmove(
+				remainder,
+				((char *) request_buffer) +
+					(n/sizeof(struct io_thread_req *))*sizeof(struct io_thread_req *),
+				*remainder_size
+			);
+			n = n - *remainder_size;
+		}
+	} else {
+		n = res;
+	}
+	return n;
+}
+
 /* Called without dev->lock held, and only in interrupt context. */
 static void ubd_handler(void)
 {
-	struct io_thread_req *req;
 	struct ubd *ubd;
 	struct list_head *list, *next_ele;
 	unsigned long flags;
 	int n;
+	int count;
 
 	while(1){
-		n = os_read_file(thread_fd, &req,
-				 sizeof(struct io_thread_req *));
-		if(n != sizeof(req)){
+		n = bulk_req_safe_read(
+			thread_fd,
+			irq_req_buffer,
+			&irq_remainder,
+			&irq_remainder_size,
+			UBD_REQ_BUFFER_SIZE
+		);
+		if (n < 0) {
 			if(n == -EAGAIN)
 				break;
 			printk(KERN_ERR "spurious interrupt in ubd_handler, "
 			       "err = %d\n", -n);
 			return;
 		}
-
-		blk_end_request(req->req, 0, req->length);
-		kfree(req);
+		for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
+			blk_end_request(
+				(*irq_req_buffer)[count]->req,
+				0,
+				(*irq_req_buffer)[count]->length
+			);
+			kfree((*irq_req_buffer)[count]);
+		}
 	}
 	reactivate_fd(thread_fd, UBD_IRQ);
 
@@ -1064,6 +1138,28 @@ static int __init ubd_init(void)
 		if (register_blkdev(fake_major, "ubd"))
 			return -1;
 	}
+
+	irq_req_buffer = kmalloc(
+			sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE,
+			GFP_KERNEL
+		);
+	irq_remainder = 0;
+
+	if (irq_req_buffer == NULL) {
+		printk(KERN_ERR "Failed to initialize ubd buffering\n");
+		return -1;
+	}
+	io_req_buffer = kmalloc(
+			sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE,
+			GFP_KERNEL
+		);
+
+	io_remainder = 0;
+
+	if (io_req_buffer == NULL) {
+		printk(KERN_ERR "Failed to initialize ubd buffering\n");
+		return -1;
+	}
 	platform_driver_register(&ubd_driver);
 	mutex_lock(&ubd_lock);
 	for (i = 0; i < MAX_DEV; i++){
@@ -1458,31 +1554,51 @@ static int io_count = 0;
 
 int io_thread(void *arg)
 {
-	struct io_thread_req *req;
-	int n;
+	int n, count, written, res;
 
 	os_fix_helper_signals();
 
 	while(1){
-		n = os_read_file(kernel_fd, &req,
-				 sizeof(struct io_thread_req *));
-		if(n != sizeof(struct io_thread_req *)){
-			if(n < 0)
+		n = bulk_req_safe_read(
+			kernel_fd,
+			io_req_buffer,
+			&io_remainder,
+			&io_remainder_size,
+			UBD_REQ_BUFFER_SIZE
+		);
+		if (n < 0) {
+			if (n == -EAGAIN) {
+				ubd_read_poll(-1);
+				continue;
+			} else {
 				printk("io_thread - read failed, fd = %d, "
-				       "err = %d\n", kernel_fd, -n);
-			else {
-				printk("io_thread - short read, fd = %d, "
-				       "length = %d\n", kernel_fd, n);
+				       "err = %d,"
+				       "reminder = %d\n",
+				       kernel_fd, -n, io_remainder_size);
 			}
-			continue;
 		}
-		io_count++;
-		do_io(req);
-		n = os_write_file(kernel_fd, &req,
-				  sizeof(struct io_thread_req *));
-		if(n != sizeof(struct io_thread_req *))
-			printk("io_thread - write failed, fd = %d, err = %d\n",
-			       kernel_fd, -n);
+
+		for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
+			io_count++;
+			do_io((*io_req_buffer)[count]);
+		}
+
+		written = 0;
+
+		do {
+			res = os_write_file(kernel_fd, ((char *) io_req_buffer) + written, n);
+			if (res > 0) {
+				written += res;
+			} else {
+				if (res != -EAGAIN) {
+					printk("io_thread - read failed, fd = %d, "
+					       "err = %d\n", kernel_fd, -n);
+				}
+			}
+			if (written < n) {
+				ubd_write_poll(-1);
+			}
+		} while (written < n);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/drivers/ubd_user.c linux-libre-4.10-rc8-gnu/arch/um/drivers/ubd_user.c
--- linux-libre-4.9-gnu/arch/um/drivers/ubd_user.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/drivers/ubd_user.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,5 @@
-/* 
+/*
+ * Copyright (C) 2016 Anton Ivanov (aivanov@brocade.com)
  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com)
  * Licensed under the GPL
@@ -20,6 +21,9 @@
 
 #include "ubd.h"
 #include <os.h>
+#include <poll.h>
+
+struct pollfd kernel_pollfd;
 
 int start_io_thread(unsigned long sp, int *fd_out)
 {
@@ -32,9 +36,12 @@ int start_io_thread(unsigned long sp, in
 	}
 
 	kernel_fd = fds[0];
+	kernel_pollfd.fd = kernel_fd;
+	kernel_pollfd.events = POLLIN;
 	*fd_out = fds[1];
 
 	err = os_set_fd_block(*fd_out, 0);
+	err = os_set_fd_block(kernel_fd, 0);
 	if (err) {
 		printk("start_io_thread - failed to set nonblocking I/O.\n");
 		goto out_close;
@@ -57,3 +64,15 @@ int start_io_thread(unsigned long sp, in
  out:
 	return err;
 }
+
+int ubd_read_poll(int timeout)
+{
+	kernel_pollfd.events = POLLIN;
+	return poll(&kernel_pollfd, 1, timeout);
+}
+int ubd_write_poll(int timeout)
+{
+	kernel_pollfd.events = POLLOUT;
+	return poll(&kernel_pollfd, 1, timeout);
+}
+
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/um/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/um/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,6 @@ generic-y += irq_work.h
 generic-y += kdebug.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
-generic-y += mutex.h
 generic-y += param.h
 generic-y += pci.h
 generic-y += percpu.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/include/asm/tlb.h linux-libre-4.10-rc8-gnu/arch/um/include/asm/tlb.h
--- linux-libre-4.9-gnu/arch/um/include/asm/tlb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/include/asm/tlb.h	2017-02-12 16:03:20.000000000 -0500
@@ -116,12 +116,6 @@ static inline bool __tlb_remove_page_siz
 	return __tlb_remove_page(tlb, page);
 }
 
-static inline bool __tlb_remove_pte_page(struct mmu_gather *tlb,
-					 struct page *page)
-{
-	return __tlb_remove_page(tlb, page);
-}
-
 static inline void tlb_remove_page_size(struct mmu_gather *tlb,
 					struct page *page, int page_size)
 {
@@ -141,6 +135,15 @@ static inline void tlb_remove_page_size(
 		__tlb_remove_tlb_entry(tlb, ptep, address);	\
 	} while (0)
 
+#define tlb_remove_huge_tlb_entry(h, tlb, ptep, address)	\
+	tlb_remove_tlb_entry(tlb, ptep, address)
+
+#define tlb_remove_check_page_size_change tlb_remove_check_page_size_change
+static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb,
+						     unsigned int page_size)
+{
+}
+
 #define pte_free_tlb(tlb, ptep, addr) __pte_free_tlb(tlb, ptep, addr)
 
 #define pud_free_tlb(tlb, pudp, addr) __pud_free_tlb(tlb, pudp, addr)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/kernel/exec.c linux-libre-4.10-rc8-gnu/arch/um/kernel/exec.c
--- linux-libre-4.9-gnu/arch/um/kernel/exec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/kernel/exec.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/slab.h>
 #include <asm/current.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <as-layout.h>
 #include <mem_user.h>
 #include <skas.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/kernel/exitcode.c linux-libre-4.10-rc8-gnu/arch/um/kernel/exitcode.c
--- linux-libre-4.9-gnu/arch/um/kernel/exitcode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/kernel/exitcode.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*
  * If read and write race, the read will still atomically read a valid
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/kernel/process.c linux-libre-4.10-rc8-gnu/arch/um/kernel/process.c
--- linux-libre-4.9-gnu/arch/um/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <asm/current.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <as-layout.h>
 #include <kern_util.h>
 #include <os.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/um/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/um/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@
 #include <linux/ptrace.h>
 #include <linux/sched.h>
 #include <linux/tracehook.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace-abi.h>
 
 void user_enable_single_step(struct task_struct *child)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/kernel/syscall.c linux-libre-4.10-rc8-gnu/arch/um/kernel/syscall.c
--- linux-libre-4.9-gnu/arch/um/kernel/syscall.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/kernel/syscall.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/syscalls.h>
 #include <asm/current.h>
 #include <asm/mman.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unistd.h>
 
 long old_mmap(unsigned long addr, unsigned long len,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/um/kernel/time.c linux-libre-4.10-rc8-gnu/arch/um/kernel/time.c
--- linux-libre-4.9-gnu/arch/um/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/um/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -83,7 +83,7 @@ static irqreturn_t um_timer(int irq, voi
 	return IRQ_HANDLED;
 }
 
-static cycle_t timer_read(struct clocksource *cs)
+static u64 timer_read(struct clocksource *cs)
 {
 	return os_nsecs() / TIMER_MULTIPLIER;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/unicore32/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/unicore32/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/unicore32/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/unicore32/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/mutex.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * UniCore optimized mutex locking primitives
- *
- * Please look into asm-generic/mutex-xchg.h for a formal definition.
- */
-#ifndef __UNICORE_MUTEX_H__
-#define __UNICORE_MUTEX_H__
-
-# include <asm-generic/mutex-xchg.h>
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/unicore32/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/unicore32/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/unicore32/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/unicore32/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,6 @@ extern void release_thread(struct task_s
 unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()			barrier()
-#define cpu_relax_lowlatency()                cpu_relax()
 
 #define task_pt_regs(p) \
 	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/unicore32/kernel/time.c linux-libre-4.10-rc8-gnu/arch/unicore32/kernel/time.c
--- linux-libre-4.9-gnu/arch/unicore32/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/unicore32/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,7 @@ static struct clock_event_device ckevt_p
 	.set_state_oneshot	= puv3_osmr0_shutdown,
 };
 
-static cycle_t puv3_read_oscr(struct clocksource *cs)
+static u64 puv3_read_oscr(struct clocksource *cs)
 {
 	return readl(OST_OSCR);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/boot/compressed/eboot.c linux-libre-4.10-rc8-gnu/arch/x86/boot/compressed/eboot.c
--- linux-libre-4.9-gnu/arch/x86/boot/compressed/eboot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/boot/compressed/eboot.c	2017-02-12 16:03:20.000000000 -0500
@@ -537,6 +537,69 @@ free_handle:
 	efi_call_early(free_pool, pci_handle);
 }
 
+static void retrieve_apple_device_properties(struct boot_params *boot_params)
+{
+	efi_guid_t guid = APPLE_PROPERTIES_PROTOCOL_GUID;
+	struct setup_data *data, *new;
+	efi_status_t status;
+	u32 size = 0;
+	void *p;
+
+	status = efi_call_early(locate_protocol, &guid, NULL, &p);
+	if (status != EFI_SUCCESS)
+		return;
+
+	if (efi_table_attr(apple_properties_protocol, version, p) != 0x10000) {
+		efi_printk(sys_table, "Unsupported properties proto version\n");
+		return;
+	}
+
+	efi_call_proto(apple_properties_protocol, get_all, p, NULL, &size);
+	if (!size)
+		return;
+
+	do {
+		status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
+					size + sizeof(struct setup_data), &new);
+		if (status != EFI_SUCCESS) {
+			efi_printk(sys_table,
+					"Failed to alloc mem for properties\n");
+			return;
+		}
+
+		status = efi_call_proto(apple_properties_protocol, get_all, p,
+					new->data, &size);
+
+		if (status == EFI_BUFFER_TOO_SMALL)
+			efi_call_early(free_pool, new);
+	} while (status == EFI_BUFFER_TOO_SMALL);
+
+	new->type = SETUP_APPLE_PROPERTIES;
+	new->len  = size;
+	new->next = 0;
+
+	data = (struct setup_data *)(unsigned long)boot_params->hdr.setup_data;
+	if (!data)
+		boot_params->hdr.setup_data = (unsigned long)new;
+	else {
+		while (data->next)
+			data = (struct setup_data *)(unsigned long)data->next;
+		data->next = (unsigned long)new;
+	}
+}
+
+static void setup_quirks(struct boot_params *boot_params)
+{
+	efi_char16_t const apple[] = { 'A', 'p', 'p', 'l', 'e', 0 };
+	efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long)
+		efi_table_attr(efi_system_table, fw_vendor, sys_table);
+
+	if (!memcmp(fw_vendor, apple, sizeof(apple))) {
+		if (IS_ENABLED(CONFIG_APPLE_PROPERTIES))
+			retrieve_apple_device_properties(boot_params);
+	}
+}
+
 static efi_status_t
 setup_uga32(void **uga_handle, unsigned long size, u32 *width, u32 *height)
 {
@@ -1098,6 +1161,8 @@ struct boot_params *efi_main(struct efi_
 
 	setup_efi_pci(boot_params);
 
+	setup_quirks(boot_params);
+
 	status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
 				sizeof(*gdt), (void **)&gdt);
 	if (status != EFI_SUCCESS) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/boot/compressed/head_64.S linux-libre-4.10-rc8-gnu/arch/x86/boot/compressed/head_64.S
--- linux-libre-4.9-gnu/arch/x86/boot/compressed/head_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/boot/compressed/head_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -119,8 +119,7 @@ ENTRY(startup_32)
  */
 
 	/* Load new GDT with the 64bit segments using 32bit descriptor */
-	leal	gdt(%ebp), %eax
-	movl	%eax, gdt+2(%ebp)
+	addl	%ebp, gdt+2(%ebp)
 	lgdt	gdt(%ebp)
 
 	/* Enable PAE mode */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/boot/compressed/Makefile linux-libre-4.10-rc8-gnu/arch/x86/boot/compressed/Makefile
--- linux-libre-4.9-gnu/arch/x86/boot/compressed/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/boot/compressed/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@ KCOV_INSTRUMENT		:= n
 targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
 	vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
 
-KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
+KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ -O2
 KBUILD_CFLAGS += -fno-strict-aliasing $(call cc-option, -fPIE, -fPIC)
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
 cflags-$(CONFIG_X86_32) := -march=i386
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/boot/cpu.c linux-libre-4.10-rc8-gnu/arch/x86/boot/cpu.c
--- linux-libre-4.9-gnu/arch/x86/boot/cpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/boot/cpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,12 +87,6 @@ int validate_cpu(void)
 		return -1;
 	}
 
-	if (CONFIG_X86_MINIMUM_CPU_FAMILY <= 4 && !IS_ENABLED(CONFIG_M486) &&
-	    !has_eflag(X86_EFLAGS_ID)) {
-		printf("This kernel requires a CPU with the CPUID instruction.  Build with CONFIG_M486=y to run on this CPU.\n");
-		return -1;
-	}
-
 	if (err_flags) {
 		puts("This kernel requires the following features "
 		     "not present on the CPU:\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/boot/Makefile linux-libre-4.10-rc8-gnu/arch/x86/boot/Makefile
--- linux-libre-4.9-gnu/arch/x86/boot/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/boot/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -65,7 +65,7 @@ clean-files += cpustr.h
 
 # ---------------------------------------------------------------------------
 
-KBUILD_CFLAGS	:= $(USERINCLUDE) $(REALMODE_CFLAGS) -D_SETUP
+KBUILD_CFLAGS	:= $(REALMODE_CFLAGS) -D_SETUP
 KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
 GCOV_PROFILE := n
 UBSAN_SANITIZE := n
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/boot/string.c linux-libre-4.10-rc8-gnu/arch/x86/boot/string.c
--- linux-libre-4.9-gnu/arch/x86/boot/string.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/boot/string.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include "ctype.h"
+#include "string.h"
 
 int memcmp(const void *s1, const void *s2, size_t len)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/boot/string.h linux-libre-4.10-rc8-gnu/arch/x86/boot/string.h
--- linux-libre-4.9-gnu/arch/x86/boot/string.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/boot/string.h	2017-02-12 16:03:20.000000000 -0500
@@ -18,4 +18,13 @@ int memcmp(const void *s1, const void *s
 #define memset(d,c,l) __builtin_memset(d,c,l)
 #define memcmp	__builtin_memcmp
 
+extern int strcmp(const char *str1, const char *str2);
+extern int strncmp(const char *cs, const char *ct, size_t count);
+extern size_t strlen(const char *s);
+extern char *strstr(const char *s1, const char *s2);
+extern size_t strnlen(const char *s, size_t maxlen);
+extern unsigned int atou(const char *s);
+extern unsigned long long simple_strtoull(const char *cp, char **endp,
+					  unsigned int base);
+
 #endif /* BOOT_STRING_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/aesni-intel_glue.c linux-libre-4.10-rc8-gnu/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-4.9-gnu/arch/x86/crypto/aesni-intel_glue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/aesni-intel_glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,6 @@
 
 #include <linux/hardirq.h>
 #include <linux/types.h>
-#include <linux/crypto.h>
 #include <linux/module.h>
 #include <linux/err.h>
 #include <crypto/algapi.h>
@@ -29,14 +28,14 @@
 #include <crypto/cryptd.h>
 #include <crypto/ctr.h>
 #include <crypto/b128ops.h>
-#include <crypto/lrw.h>
 #include <crypto/xts.h>
 #include <asm/cpu_device_id.h>
 #include <asm/fpu/api.h>
 #include <asm/crypto/aes.h>
-#include <crypto/ablk_helper.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/internal/aead.h>
+#include <crypto/internal/simd.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #ifdef CONFIG_X86_64
@@ -45,28 +44,26 @@
 
 
 #define AESNI_ALIGN	16
+#define AESNI_ALIGN_ATTR __attribute__ ((__aligned__(AESNI_ALIGN)))
 #define AES_BLOCK_MASK	(~(AES_BLOCK_SIZE - 1))
 #define RFC4106_HASH_SUBKEY_SIZE 16
+#define AESNI_ALIGN_EXTRA ((AESNI_ALIGN - 1) & ~(CRYPTO_MINALIGN - 1))
+#define CRYPTO_AES_CTX_SIZE (sizeof(struct crypto_aes_ctx) + AESNI_ALIGN_EXTRA)
+#define XTS_AES_CTX_SIZE (sizeof(struct aesni_xts_ctx) + AESNI_ALIGN_EXTRA)
 
 /* This data is stored at the end of the crypto_tfm struct.
  * It's a type of per "session" data storage location.
  * This needs to be 16 byte aligned.
  */
 struct aesni_rfc4106_gcm_ctx {
-	u8 hash_subkey[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
-	struct crypto_aes_ctx aes_key_expanded
-		__attribute__ ((__aligned__(AESNI_ALIGN)));
+	u8 hash_subkey[16] AESNI_ALIGN_ATTR;
+	struct crypto_aes_ctx aes_key_expanded AESNI_ALIGN_ATTR;
 	u8 nonce[4];
 };
 
-struct aesni_lrw_ctx {
-	struct lrw_table_ctx lrw_table;
-	u8 raw_aes_ctx[sizeof(struct crypto_aes_ctx) + AESNI_ALIGN - 1];
-};
-
 struct aesni_xts_ctx {
-	u8 raw_tweak_ctx[sizeof(struct crypto_aes_ctx) + AESNI_ALIGN - 1];
-	u8 raw_crypt_ctx[sizeof(struct crypto_aes_ctx) + AESNI_ALIGN - 1];
+	u8 raw_tweak_ctx[sizeof(struct crypto_aes_ctx)] AESNI_ALIGN_ATTR;
+	u8 raw_crypt_ctx[sizeof(struct crypto_aes_ctx)] AESNI_ALIGN_ATTR;
 };
 
 asmlinkage int aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
@@ -360,96 +357,95 @@ static void __aes_decrypt(struct crypto_
 	aesni_dec(ctx, dst, src);
 }
 
-static int ecb_encrypt(struct blkcipher_desc *desc,
-		       struct scatterlist *dst, struct scatterlist *src,
-		       unsigned int nbytes)
+static int aesni_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
+			         unsigned int len)
 {
-	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
-	struct blkcipher_walk walk;
+	return aes_set_key_common(crypto_skcipher_tfm(tfm),
+				  crypto_skcipher_ctx(tfm), key, len);
+}
+
+static int ecb_encrypt(struct skcipher_request *req)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_skcipher_ctx(tfm));
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
 		aesni_ecb_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
 			      nbytes & AES_BLOCK_MASK);
 		nbytes &= AES_BLOCK_SIZE - 1;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 	kernel_fpu_end();
 
 	return err;
 }
 
-static int ecb_decrypt(struct blkcipher_desc *desc,
-		       struct scatterlist *dst, struct scatterlist *src,
-		       unsigned int nbytes)
+static int ecb_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_skcipher_ctx(tfm));
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
 		aesni_ecb_dec(ctx, walk.dst.virt.addr, walk.src.virt.addr,
 			      nbytes & AES_BLOCK_MASK);
 		nbytes &= AES_BLOCK_SIZE - 1;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 	kernel_fpu_end();
 
 	return err;
 }
 
-static int cbc_encrypt(struct blkcipher_desc *desc,
-		       struct scatterlist *dst, struct scatterlist *src,
-		       unsigned int nbytes)
+static int cbc_encrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_skcipher_ctx(tfm));
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
 		aesni_cbc_enc(ctx, walk.dst.virt.addr, walk.src.virt.addr,
 			      nbytes & AES_BLOCK_MASK, walk.iv);
 		nbytes &= AES_BLOCK_SIZE - 1;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 	kernel_fpu_end();
 
 	return err;
 }
 
-static int cbc_decrypt(struct blkcipher_desc *desc,
-		       struct scatterlist *dst, struct scatterlist *src,
-		       unsigned int nbytes)
+static int cbc_decrypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_skcipher_ctx(tfm));
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes)) {
 		aesni_cbc_dec(ctx, walk.dst.virt.addr, walk.src.virt.addr,
 			      nbytes & AES_BLOCK_MASK, walk.iv);
 		nbytes &= AES_BLOCK_SIZE - 1;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 	kernel_fpu_end();
 
@@ -458,7 +454,7 @@ static int cbc_decrypt(struct blkcipher_
 
 #ifdef CONFIG_X86_64
 static void ctr_crypt_final(struct crypto_aes_ctx *ctx,
-			    struct blkcipher_walk *walk)
+			    struct skcipher_walk *walk)
 {
 	u8 *ctrblk = walk->iv;
 	u8 keystream[AES_BLOCK_SIZE];
@@ -491,157 +487,53 @@ static void aesni_ctr_enc_avx_tfm(struct
 }
 #endif
 
-static int ctr_crypt(struct blkcipher_desc *desc,
-		     struct scatterlist *dst, struct scatterlist *src,
-		     unsigned int nbytes)
+static int ctr_crypt(struct skcipher_request *req)
 {
-	struct crypto_aes_ctx *ctx = aes_ctx(crypto_blkcipher_ctx(desc->tfm));
-	struct blkcipher_walk walk;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_aes_ctx *ctx = aes_ctx(crypto_skcipher_ctx(tfm));
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
+	err = skcipher_walk_virt(&walk, req, true);
 
 	kernel_fpu_begin();
 	while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
 		aesni_ctr_enc_tfm(ctx, walk.dst.virt.addr, walk.src.virt.addr,
 			              nbytes & AES_BLOCK_MASK, walk.iv);
 		nbytes &= AES_BLOCK_SIZE - 1;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 	if (walk.nbytes) {
 		ctr_crypt_final(ctx, &walk);
-		err = blkcipher_walk_done(desc, &walk, 0);
+		err = skcipher_walk_done(&walk, 0);
 	}
 	kernel_fpu_end();
 
 	return err;
 }
-#endif
-
-static int ablk_ecb_init(struct crypto_tfm *tfm)
-{
-	return ablk_init_common(tfm, "__driver-ecb-aes-aesni");
-}
-
-static int ablk_cbc_init(struct crypto_tfm *tfm)
-{
-	return ablk_init_common(tfm, "__driver-cbc-aes-aesni");
-}
-
-#ifdef CONFIG_X86_64
-static int ablk_ctr_init(struct crypto_tfm *tfm)
-{
-	return ablk_init_common(tfm, "__driver-ctr-aes-aesni");
-}
-
-#endif
-
-#if IS_ENABLED(CONFIG_CRYPTO_PCBC)
-static int ablk_pcbc_init(struct crypto_tfm *tfm)
-{
-	return ablk_init_common(tfm, "fpu(pcbc(__driver-aes-aesni))");
-}
-#endif
-
-static void lrw_xts_encrypt_callback(void *ctx, u8 *blks, unsigned int nbytes)
-{
-	aesni_ecb_enc(ctx, blks, blks, nbytes);
-}
-
-static void lrw_xts_decrypt_callback(void *ctx, u8 *blks, unsigned int nbytes)
-{
-	aesni_ecb_dec(ctx, blks, blks, nbytes);
-}
 
-static int lrw_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
+static int xts_aesni_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			    unsigned int keylen)
 {
-	struct aesni_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct aesni_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 	int err;
 
-	err = aes_set_key_common(tfm, ctx->raw_aes_ctx, key,
-				 keylen - AES_BLOCK_SIZE);
+	err = xts_verify_key(tfm, key, keylen);
 	if (err)
 		return err;
 
-	return lrw_init_table(&ctx->lrw_table, key + keylen - AES_BLOCK_SIZE);
-}
-
-static void lrw_aesni_exit_tfm(struct crypto_tfm *tfm)
-{
-	struct aesni_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
-
-	lrw_free_table(&ctx->lrw_table);
-}
-
-static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
-{
-	struct aesni_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	be128 buf[8];
-	struct lrw_crypt_req req = {
-		.tbuf = buf,
-		.tbuflen = sizeof(buf),
-
-		.table_ctx = &ctx->lrw_table,
-		.crypt_ctx = aes_ctx(ctx->raw_aes_ctx),
-		.crypt_fn = lrw_xts_encrypt_callback,
-	};
-	int ret;
-
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-
-	kernel_fpu_begin();
-	ret = lrw_crypt(desc, dst, src, nbytes, &req);
-	kernel_fpu_end();
-
-	return ret;
-}
-
-static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
-{
-	struct aesni_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	be128 buf[8];
-	struct lrw_crypt_req req = {
-		.tbuf = buf,
-		.tbuflen = sizeof(buf),
-
-		.table_ctx = &ctx->lrw_table,
-		.crypt_ctx = aes_ctx(ctx->raw_aes_ctx),
-		.crypt_fn = lrw_xts_decrypt_callback,
-	};
-	int ret;
-
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-
-	kernel_fpu_begin();
-	ret = lrw_crypt(desc, dst, src, nbytes, &req);
-	kernel_fpu_end();
-
-	return ret;
-}
-
-static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
-			    unsigned int keylen)
-{
-	struct aesni_xts_ctx *ctx = crypto_tfm_ctx(tfm);
-	int err;
-
-	err = xts_check_key(tfm, key, keylen);
-	if (err)
-		return err;
+	keylen /= 2;
 
 	/* first half of xts-key is for crypt */
-	err = aes_set_key_common(tfm, ctx->raw_crypt_ctx, key, keylen / 2);
+	err = aes_set_key_common(crypto_skcipher_tfm(tfm), ctx->raw_crypt_ctx,
+				 key, keylen);
 	if (err)
 		return err;
 
 	/* second half of xts-key is for tweak */
-	return aes_set_key_common(tfm, ctx->raw_tweak_ctx, key + keylen / 2,
-				  keylen / 2);
+	return aes_set_key_common(crypto_skcipher_tfm(tfm), ctx->raw_tweak_ctx,
+				  key + keylen, keylen);
 }
 
 
@@ -650,8 +542,6 @@ static void aesni_xts_tweak(void *ctx, u
 	aesni_enc(ctx, out, in);
 }
 
-#ifdef CONFIG_X86_64
-
 static void aesni_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv)
 {
 	glue_xts_crypt_128bit_one(ctx, dst, src, iv, GLUE_FUNC_CAST(aesni_enc));
@@ -698,83 +588,28 @@ static const struct common_glue_ctx aesn
 	} }
 };
 
-static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
-{
-	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-
-	return glue_xts_crypt_128bit(&aesni_enc_xts, desc, dst, src, nbytes,
-				     XTS_TWEAK_CAST(aesni_xts_tweak),
-				     aes_ctx(ctx->raw_tweak_ctx),
-				     aes_ctx(ctx->raw_crypt_ctx));
-}
-
-static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
-{
-	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-
-	return glue_xts_crypt_128bit(&aesni_dec_xts, desc, dst, src, nbytes,
-				     XTS_TWEAK_CAST(aesni_xts_tweak),
-				     aes_ctx(ctx->raw_tweak_ctx),
-				     aes_ctx(ctx->raw_crypt_ctx));
-}
-
-#else
-
-static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int xts_encrypt(struct skcipher_request *req)
 {
-	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	be128 buf[8];
-	struct xts_crypt_req req = {
-		.tbuf = buf,
-		.tbuflen = sizeof(buf),
-
-		.tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
-		.tweak_fn = aesni_xts_tweak,
-		.crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
-		.crypt_fn = lrw_xts_encrypt_callback,
-	};
-	int ret;
-
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-
-	kernel_fpu_begin();
-	ret = xts_crypt(desc, dst, src, nbytes, &req);
-	kernel_fpu_end();
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct aesni_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return ret;
+	return glue_xts_req_128bit(&aesni_enc_xts, req,
+				   XTS_TWEAK_CAST(aesni_xts_tweak),
+				   aes_ctx(ctx->raw_tweak_ctx),
+				   aes_ctx(ctx->raw_crypt_ctx));
 }
 
-static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		       struct scatterlist *src, unsigned int nbytes)
+static int xts_decrypt(struct skcipher_request *req)
 {
-	struct aesni_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
-	be128 buf[8];
-	struct xts_crypt_req req = {
-		.tbuf = buf,
-		.tbuflen = sizeof(buf),
-
-		.tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
-		.tweak_fn = aesni_xts_tweak,
-		.crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
-		.crypt_fn = lrw_xts_decrypt_callback,
-	};
-	int ret;
-
-	desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
-
-	kernel_fpu_begin();
-	ret = xts_crypt(desc, dst, src, nbytes, &req);
-	kernel_fpu_end();
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct aesni_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return ret;
+	return glue_xts_req_128bit(&aesni_dec_xts, req,
+				   XTS_TWEAK_CAST(aesni_xts_tweak),
+				   aes_ctx(ctx->raw_tweak_ctx),
+				   aes_ctx(ctx->raw_crypt_ctx));
 }
 
-#endif
-
-#ifdef CONFIG_X86_64
 static int rfc4106_init(struct crypto_aead *aead)
 {
 	struct cryptd_aead *cryptd_tfm;
@@ -1077,9 +912,7 @@ static struct crypto_alg aesni_algs[] =
 	.cra_priority		= 300,
 	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
 	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx) +
-				  AESNI_ALIGN - 1,
-	.cra_alignmask		= 0,
+	.cra_ctxsize		= CRYPTO_AES_CTX_SIZE,
 	.cra_module		= THIS_MODULE,
 	.cra_u	= {
 		.cipher	= {
@@ -1091,14 +924,12 @@ static struct crypto_alg aesni_algs[] =
 		}
 	}
 }, {
-	.cra_name		= "__aes-aesni",
-	.cra_driver_name	= "__driver-aes-aesni",
-	.cra_priority		= 0,
+	.cra_name		= "__aes",
+	.cra_driver_name	= "__aes-aesni",
+	.cra_priority		= 300,
 	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER | CRYPTO_ALG_INTERNAL,
 	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx) +
-				  AESNI_ALIGN - 1,
-	.cra_alignmask		= 0,
+	.cra_ctxsize		= CRYPTO_AES_CTX_SIZE,
 	.cra_module		= THIS_MODULE,
 	.cra_u	= {
 		.cipher	= {
@@ -1109,250 +940,95 @@ static struct crypto_alg aesni_algs[] =
 			.cia_decrypt		= __aes_decrypt
 		}
 	}
-}, {
-	.cra_name		= "__ecb-aes-aesni",
-	.cra_driver_name	= "__driver-ecb-aes-aesni",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx) +
-				  AESNI_ALIGN - 1,
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_u = {
-		.blkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
-			.setkey		= aes_set_key,
-			.encrypt	= ecb_encrypt,
-			.decrypt	= ecb_decrypt,
-		},
-	},
-}, {
-	.cra_name		= "__cbc-aes-aesni",
-	.cra_driver_name	= "__driver-cbc-aes-aesni",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx) +
-				  AESNI_ALIGN - 1,
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_u = {
-		.blkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
-			.setkey		= aes_set_key,
-			.encrypt	= cbc_encrypt,
-			.decrypt	= cbc_decrypt,
-		},
-	},
-}, {
-	.cra_name		= "ecb(aes)",
-	.cra_driver_name	= "ecb-aes-aesni",
-	.cra_priority		= 400,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_ecb_init,
-	.cra_exit		= ablk_exit,
-	.cra_u = {
-		.ablkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
-			.setkey		= ablk_set_key,
-			.encrypt	= ablk_encrypt,
-			.decrypt	= ablk_decrypt,
+} };
+
+static struct skcipher_alg aesni_skciphers[] = {
+	{
+		.base = {
+			.cra_name		= "__ecb(aes)",
+			.cra_driver_name	= "__ecb-aes-aesni",
+			.cra_priority		= 400,
+			.cra_flags		= CRYPTO_ALG_INTERNAL,
+			.cra_blocksize		= AES_BLOCK_SIZE,
+			.cra_ctxsize		= CRYPTO_AES_CTX_SIZE,
+			.cra_module		= THIS_MODULE,
 		},
-	},
-}, {
-	.cra_name		= "cbc(aes)",
-	.cra_driver_name	= "cbc-aes-aesni",
-	.cra_priority		= 400,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_cbc_init,
-	.cra_exit		= ablk_exit,
-	.cra_u = {
-		.ablkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= ablk_set_key,
-			.encrypt	= ablk_encrypt,
-			.decrypt	= ablk_decrypt,
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+		.setkey		= aesni_skcipher_setkey,
+		.encrypt	= ecb_encrypt,
+		.decrypt	= ecb_decrypt,
+	}, {
+		.base = {
+			.cra_name		= "__cbc(aes)",
+			.cra_driver_name	= "__cbc-aes-aesni",
+			.cra_priority		= 400,
+			.cra_flags		= CRYPTO_ALG_INTERNAL,
+			.cra_blocksize		= AES_BLOCK_SIZE,
+			.cra_ctxsize		= CRYPTO_AES_CTX_SIZE,
+			.cra_module		= THIS_MODULE,
 		},
-	},
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.setkey		= aesni_skcipher_setkey,
+		.encrypt	= cbc_encrypt,
+		.decrypt	= cbc_decrypt,
 #ifdef CONFIG_X86_64
-}, {
-	.cra_name		= "__ctr-aes-aesni",
-	.cra_driver_name	= "__driver-ctr-aes-aesni",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct crypto_aes_ctx) +
-				  AESNI_ALIGN - 1,
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_u = {
-		.blkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= aes_set_key,
-			.encrypt	= ctr_crypt,
-			.decrypt	= ctr_crypt,
+	}, {
+		.base = {
+			.cra_name		= "__ctr(aes)",
+			.cra_driver_name	= "__ctr-aes-aesni",
+			.cra_priority		= 400,
+			.cra_flags		= CRYPTO_ALG_INTERNAL,
+			.cra_blocksize		= 1,
+			.cra_ctxsize		= CRYPTO_AES_CTX_SIZE,
+			.cra_module		= THIS_MODULE,
 		},
-	},
-}, {
-	.cra_name		= "ctr(aes)",
-	.cra_driver_name	= "ctr-aes-aesni",
-	.cra_priority		= 400,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= 1,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_ctr_init,
-	.cra_exit		= ablk_exit,
-	.cra_u = {
-		.ablkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= ablk_set_key,
-			.encrypt	= ablk_encrypt,
-			.decrypt	= ablk_encrypt,
-			.geniv		= "chainiv",
+		.min_keysize	= AES_MIN_KEY_SIZE,
+		.max_keysize	= AES_MAX_KEY_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.chunksize	= AES_BLOCK_SIZE,
+		.setkey		= aesni_skcipher_setkey,
+		.encrypt	= ctr_crypt,
+		.decrypt	= ctr_crypt,
+	}, {
+		.base = {
+			.cra_name		= "__xts(aes)",
+			.cra_driver_name	= "__xts-aes-aesni",
+			.cra_priority		= 401,
+			.cra_flags		= CRYPTO_ALG_INTERNAL,
+			.cra_blocksize		= AES_BLOCK_SIZE,
+			.cra_ctxsize		= XTS_AES_CTX_SIZE,
+			.cra_module		= THIS_MODULE,
 		},
-	},
+		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.setkey		= xts_aesni_setkey,
+		.encrypt	= xts_encrypt,
+		.decrypt	= xts_decrypt,
 #endif
-#if IS_ENABLED(CONFIG_CRYPTO_PCBC)
-}, {
-	.cra_name		= "pcbc(aes)",
-	.cra_driver_name	= "pcbc-aes-aesni",
-	.cra_priority		= 400,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_pcbc_init,
-	.cra_exit		= ablk_exit,
-	.cra_u = {
-		.ablkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= ablk_set_key,
-			.encrypt	= ablk_encrypt,
-			.decrypt	= ablk_decrypt,
-		},
+	}
+};
+
+struct simd_skcipher_alg *aesni_simd_skciphers[ARRAY_SIZE(aesni_skciphers)];
+
+struct {
+	const char *algname;
+	const char *drvname;
+	const char *basename;
+	struct simd_skcipher_alg *simd;
+} aesni_simd_skciphers2[] = {
+#if (defined(MODULE) && IS_ENABLED(CONFIG_CRYPTO_PCBC)) || \
+    IS_BUILTIN(CONFIG_CRYPTO_PCBC)
+	{
+		.algname	= "pcbc(aes)",
+		.drvname	= "pcbc-aes-aesni",
+		.basename	= "fpu(pcbc(__aes-aesni))",
 	},
 #endif
-}, {
-	.cra_name		= "__lrw-aes-aesni",
-	.cra_driver_name	= "__driver-lrw-aes-aesni",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct aesni_lrw_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_exit		= lrw_aesni_exit_tfm,
-	.cra_u = {
-		.blkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= lrw_aesni_setkey,
-			.encrypt	= lrw_encrypt,
-			.decrypt	= lrw_decrypt,
-		},
-	},
-}, {
-	.cra_name		= "__xts-aes-aesni",
-	.cra_driver_name	= "__driver-xts-aes-aesni",
-	.cra_priority		= 0,
-	.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
-				  CRYPTO_ALG_INTERNAL,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct aesni_xts_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_blkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_u = {
-		.blkcipher = {
-			.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-			.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= xts_aesni_setkey,
-			.encrypt	= xts_encrypt,
-			.decrypt	= xts_decrypt,
-		},
-	},
-}, {
-	.cra_name		= "lrw(aes)",
-	.cra_driver_name	= "lrw-aes-aesni",
-	.cra_priority		= 400,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_u = {
-		.ablkcipher = {
-			.min_keysize	= AES_MIN_KEY_SIZE + AES_BLOCK_SIZE,
-			.max_keysize	= AES_MAX_KEY_SIZE + AES_BLOCK_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= ablk_set_key,
-			.encrypt	= ablk_encrypt,
-			.decrypt	= ablk_decrypt,
-		},
-	},
-}, {
-	.cra_name		= "xts(aes)",
-	.cra_driver_name	= "xts-aes-aesni",
-	.cra_priority		= 400,
-	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
-	.cra_blocksize		= AES_BLOCK_SIZE,
-	.cra_ctxsize		= sizeof(struct async_helper_ctx),
-	.cra_alignmask		= 0,
-	.cra_type		= &crypto_ablkcipher_type,
-	.cra_module		= THIS_MODULE,
-	.cra_init		= ablk_init,
-	.cra_exit		= ablk_exit,
-	.cra_u = {
-		.ablkcipher = {
-			.min_keysize	= 2 * AES_MIN_KEY_SIZE,
-			.max_keysize	= 2 * AES_MAX_KEY_SIZE,
-			.ivsize		= AES_BLOCK_SIZE,
-			.setkey		= ablk_set_key,
-			.encrypt	= ablk_encrypt,
-			.decrypt	= ablk_decrypt,
-		},
-	},
-} };
+};
 
 #ifdef CONFIG_X86_64
 static struct aead_alg aesni_aead_algs[] = { {
@@ -1401,9 +1077,27 @@ static const struct x86_cpu_id aesni_cpu
 };
 MODULE_DEVICE_TABLE(x86cpu, aesni_cpu_id);
 
+static void aesni_free_simds(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers) &&
+		    aesni_simd_skciphers[i]; i++)
+		simd_skcipher_free(aesni_simd_skciphers[i]);
+
+	for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers2); i++)
+		if (aesni_simd_skciphers2[i].simd)
+			simd_skcipher_free(aesni_simd_skciphers2[i].simd);
+}
+
 static int __init aesni_init(void)
 {
+	struct simd_skcipher_alg *simd;
+	const char *basename;
+	const char *algname;
+	const char *drvname;
 	int err;
+	int i;
 
 	if (!x86_match_cpu(aesni_cpu_id))
 		return -ENODEV;
@@ -1445,13 +1139,48 @@ static int __init aesni_init(void)
 	if (err)
 		goto fpu_exit;
 
+	err = crypto_register_skciphers(aesni_skciphers,
+					ARRAY_SIZE(aesni_skciphers));
+	if (err)
+		goto unregister_algs;
+
 	err = crypto_register_aeads(aesni_aead_algs,
 				    ARRAY_SIZE(aesni_aead_algs));
 	if (err)
-		goto unregister_algs;
+		goto unregister_skciphers;
 
-	return err;
+	for (i = 0; i < ARRAY_SIZE(aesni_skciphers); i++) {
+		algname = aesni_skciphers[i].base.cra_name + 2;
+		drvname = aesni_skciphers[i].base.cra_driver_name + 2;
+		basename = aesni_skciphers[i].base.cra_driver_name;
+		simd = simd_skcipher_create_compat(algname, drvname, basename);
+		err = PTR_ERR(simd);
+		if (IS_ERR(simd))
+			goto unregister_simds;
+
+		aesni_simd_skciphers[i] = simd;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(aesni_simd_skciphers2); i++) {
+		algname = aesni_simd_skciphers2[i].algname;
+		drvname = aesni_simd_skciphers2[i].drvname;
+		basename = aesni_simd_skciphers2[i].basename;
+		simd = simd_skcipher_create_compat(algname, drvname, basename);
+		err = PTR_ERR(simd);
+		if (IS_ERR(simd))
+			continue;
+
+		aesni_simd_skciphers2[i].simd = simd;
+	}
 
+	return 0;
+
+unregister_simds:
+	aesni_free_simds();
+	crypto_unregister_aeads(aesni_aead_algs, ARRAY_SIZE(aesni_aead_algs));
+unregister_skciphers:
+	crypto_unregister_skciphers(aesni_skciphers,
+				    ARRAY_SIZE(aesni_skciphers));
 unregister_algs:
 	crypto_unregister_algs(aesni_algs, ARRAY_SIZE(aesni_algs));
 fpu_exit:
@@ -1461,7 +1190,10 @@ fpu_exit:
 
 static void __exit aesni_exit(void)
 {
+	aesni_free_simds();
 	crypto_unregister_aeads(aesni_aead_algs, ARRAY_SIZE(aesni_aead_algs));
+	crypto_unregister_skciphers(aesni_skciphers,
+				    ARRAY_SIZE(aesni_skciphers));
 	crypto_unregister_algs(aesni_algs, ARRAY_SIZE(aesni_algs));
 
 	crypto_fpu_exit();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/crc32c-intel_glue.c linux-libre-4.10-rc8-gnu/arch/x86/crypto/crc32c-intel_glue.c
--- linux-libre-4.9-gnu/arch/x86/crypto/crc32c-intel_glue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/crc32c-intel_glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,26 +48,13 @@
 #ifdef CONFIG_X86_64
 /*
  * use carryless multiply version of crc32c when buffer
- * size is >= 512 (when eager fpu is enabled) or
- * >= 1024 (when eager fpu is disabled) to account
+ * size is >= 512 to account
  * for fpu state save/restore overhead.
  */
-#define CRC32C_PCL_BREAKEVEN_EAGERFPU	512
-#define CRC32C_PCL_BREAKEVEN_NOEAGERFPU	1024
+#define CRC32C_PCL_BREAKEVEN	512
 
 asmlinkage unsigned int crc_pcl(const u8 *buffer, int len,
 				unsigned int crc_init);
-static int crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_EAGERFPU;
-#if defined(X86_FEATURE_EAGER_FPU)
-#define set_pcl_breakeven_point()					\
-do {									\
-	if (!use_eager_fpu())						\
-		crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU;	\
-} while (0)
-#else
-#define set_pcl_breakeven_point()					\
-	(crc32c_pcl_breakeven = CRC32C_PCL_BREAKEVEN_NOEAGERFPU)
-#endif
 #endif /* CONFIG_X86_64 */
 
 static u32 crc32c_intel_le_hw_byte(u32 crc, unsigned char const *data, size_t length)
@@ -190,7 +177,7 @@ static int crc32c_pcl_intel_update(struc
 	 * use faster PCL version if datasize is large enough to
 	 * overcome kernel fpu state save/restore overhead
 	 */
-	if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+	if (len >= CRC32C_PCL_BREAKEVEN && irq_fpu_usable()) {
 		kernel_fpu_begin();
 		*crcp = crc_pcl(data, len, *crcp);
 		kernel_fpu_end();
@@ -202,7 +189,7 @@ static int crc32c_pcl_intel_update(struc
 static int __crc32c_pcl_intel_finup(u32 *crcp, const u8 *data, unsigned int len,
 				u8 *out)
 {
-	if (len >= crc32c_pcl_breakeven && irq_fpu_usable()) {
+	if (len >= CRC32C_PCL_BREAKEVEN && irq_fpu_usable()) {
 		kernel_fpu_begin();
 		*(__le32 *)out = ~cpu_to_le32(crc_pcl(data, len, *crcp));
 		kernel_fpu_end();
@@ -261,7 +248,6 @@ static int __init crc32c_intel_mod_init(
 		alg.update = crc32c_pcl_intel_update;
 		alg.finup = crc32c_pcl_intel_finup;
 		alg.digest = crc32c_pcl_intel_digest;
-		set_pcl_breakeven_point();
 	}
 #endif
 	return crypto_register_shash(&alg);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/fpu.c linux-libre-4.10-rc8-gnu/arch/x86/crypto/fpu.c
--- linux-libre-4.9-gnu/arch/x86/crypto/fpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/fpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,143 +11,186 @@
  *
  */
 
-#include <crypto/algapi.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/crypto.h>
 #include <asm/fpu/api.h>
 
 struct crypto_fpu_ctx {
-	struct crypto_blkcipher *child;
+	struct crypto_skcipher *child;
 };
 
-static int crypto_fpu_setkey(struct crypto_tfm *parent, const u8 *key,
+static int crypto_fpu_setkey(struct crypto_skcipher *parent, const u8 *key,
 			     unsigned int keylen)
 {
-	struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(parent);
-	struct crypto_blkcipher *child = ctx->child;
+	struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(parent);
+	struct crypto_skcipher *child = ctx->child;
 	int err;
 
-	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-	crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
-				   CRYPTO_TFM_REQ_MASK);
-	err = crypto_blkcipher_setkey(child, key, keylen);
-	crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
-				     CRYPTO_TFM_RES_MASK);
+	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_skcipher_setkey(child, key, keylen);
+	crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) &
+					  CRYPTO_TFM_RES_MASK);
 	return err;
 }
 
-static int crypto_fpu_encrypt(struct blkcipher_desc *desc_in,
-			      struct scatterlist *dst, struct scatterlist *src,
-			      unsigned int nbytes)
+static int crypto_fpu_encrypt(struct skcipher_request *req)
 {
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *child = ctx->child;
+	SKCIPHER_REQUEST_ON_STACK(subreq, child);
 	int err;
-	struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
-	struct crypto_blkcipher *child = ctx->child;
-	struct blkcipher_desc desc = {
-		.tfm = child,
-		.info = desc_in->info,
-		.flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
-	};
+
+	skcipher_request_set_tfm(subreq, child);
+	skcipher_request_set_callback(subreq, 0, NULL, NULL);
+	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
+				   req->iv);
 
 	kernel_fpu_begin();
-	err = crypto_blkcipher_crt(desc.tfm)->encrypt(&desc, dst, src, nbytes);
+	err = crypto_skcipher_encrypt(subreq);
 	kernel_fpu_end();
+
+	skcipher_request_zero(subreq);
 	return err;
 }
 
-static int crypto_fpu_decrypt(struct blkcipher_desc *desc_in,
-			      struct scatterlist *dst, struct scatterlist *src,
-			      unsigned int nbytes)
+static int crypto_fpu_decrypt(struct skcipher_request *req)
 {
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *child = ctx->child;
+	SKCIPHER_REQUEST_ON_STACK(subreq, child);
 	int err;
-	struct crypto_fpu_ctx *ctx = crypto_blkcipher_ctx(desc_in->tfm);
-	struct crypto_blkcipher *child = ctx->child;
-	struct blkcipher_desc desc = {
-		.tfm = child,
-		.info = desc_in->info,
-		.flags = desc_in->flags & ~CRYPTO_TFM_REQ_MAY_SLEEP,
-	};
+
+	skcipher_request_set_tfm(subreq, child);
+	skcipher_request_set_callback(subreq, 0, NULL, NULL);
+	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
+				   req->iv);
 
 	kernel_fpu_begin();
-	err = crypto_blkcipher_crt(desc.tfm)->decrypt(&desc, dst, src, nbytes);
+	err = crypto_skcipher_decrypt(subreq);
 	kernel_fpu_end();
+
+	skcipher_request_zero(subreq);
 	return err;
 }
 
-static int crypto_fpu_init_tfm(struct crypto_tfm *tfm)
+static int crypto_fpu_init_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
-	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
-	struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
-	struct crypto_blkcipher *cipher;
+	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
+	struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher_spawn *spawn;
+	struct crypto_skcipher *cipher;
 
-	cipher = crypto_spawn_blkcipher(spawn);
+	spawn = skcipher_instance_ctx(inst);
+	cipher = crypto_spawn_skcipher(spawn);
 	if (IS_ERR(cipher))
 		return PTR_ERR(cipher);
 
 	ctx->child = cipher;
+
 	return 0;
 }
 
-static void crypto_fpu_exit_tfm(struct crypto_tfm *tfm)
+static void crypto_fpu_exit_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_fpu_ctx *ctx = crypto_tfm_ctx(tfm);
-	crypto_free_blkcipher(ctx->child);
+	struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+	crypto_free_skcipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_fpu_alloc(struct rtattr **tb)
+static void crypto_fpu_free(struct skcipher_instance *inst)
 {
-	struct crypto_instance *inst;
-	struct crypto_alg *alg;
+	crypto_drop_skcipher(skcipher_instance_ctx(inst));
+	kfree(inst);
+}
+
+static int crypto_fpu_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct crypto_skcipher_spawn *spawn;
+	struct skcipher_instance *inst;
+	struct crypto_attr_type *algt;
+	struct skcipher_alg *alg;
+	const char *cipher_name;
 	int err;
 
-	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return PTR_ERR(algt);
+
+	if ((algt->type ^ (CRYPTO_ALG_INTERNAL | CRYPTO_ALG_TYPE_SKCIPHER)) &
+	    algt->mask)
+		return -EINVAL;
+
+	if (!(algt->mask & CRYPTO_ALG_INTERNAL))
+		return -EINVAL;
+
+	cipher_name = crypto_attr_alg_name(tb[1]);
+	if (IS_ERR(cipher_name))
+		return PTR_ERR(cipher_name);
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	spawn = skcipher_instance_ctx(inst);
+
+	crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst));
+	err = crypto_grab_skcipher(spawn, cipher_name, CRYPTO_ALG_INTERNAL,
+				   CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
 	if (err)
-		return ERR_PTR(err);
+		goto out_free_inst;
 
-	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
-				  CRYPTO_ALG_TYPE_MASK);
-	if (IS_ERR(alg))
-		return ERR_CAST(alg);
+	alg = crypto_skcipher_spawn_alg(spawn);
 
-	inst = crypto_alloc_instance("fpu", alg);
-	if (IS_ERR(inst))
-		goto out_put_alg;
+	err = crypto_inst_setname(skcipher_crypto_instance(inst), "fpu",
+				  &alg->base);
+	if (err)
+		goto out_drop_skcipher;
 
-	inst->alg.cra_flags = alg->cra_flags;
-	inst->alg.cra_priority = alg->cra_priority;
-	inst->alg.cra_blocksize = alg->cra_blocksize;
-	inst->alg.cra_alignmask = alg->cra_alignmask;
-	inst->alg.cra_type = alg->cra_type;
-	inst->alg.cra_blkcipher.ivsize = alg->cra_blkcipher.ivsize;
-	inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
-	inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
-	inst->alg.cra_ctxsize = sizeof(struct crypto_fpu_ctx);
-	inst->alg.cra_init = crypto_fpu_init_tfm;
-	inst->alg.cra_exit = crypto_fpu_exit_tfm;
-	inst->alg.cra_blkcipher.setkey = crypto_fpu_setkey;
-	inst->alg.cra_blkcipher.encrypt = crypto_fpu_encrypt;
-	inst->alg.cra_blkcipher.decrypt = crypto_fpu_decrypt;
+	inst->alg.base.cra_flags = CRYPTO_ALG_INTERNAL;
+	inst->alg.base.cra_priority = alg->base.cra_priority;
+	inst->alg.base.cra_blocksize = alg->base.cra_blocksize;
+	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
 
-out_put_alg:
-	crypto_mod_put(alg);
-	return inst;
-}
+	inst->alg.ivsize = crypto_skcipher_alg_ivsize(alg);
+	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg);
+	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg);
 
-static void crypto_fpu_free(struct crypto_instance *inst)
-{
-	crypto_drop_spawn(crypto_instance_ctx(inst));
+	inst->alg.base.cra_ctxsize = sizeof(struct crypto_fpu_ctx);
+
+	inst->alg.init = crypto_fpu_init_tfm;
+	inst->alg.exit = crypto_fpu_exit_tfm;
+
+	inst->alg.setkey = crypto_fpu_setkey;
+	inst->alg.encrypt = crypto_fpu_encrypt;
+	inst->alg.decrypt = crypto_fpu_decrypt;
+
+	inst->free = crypto_fpu_free;
+
+	err = skcipher_register_instance(tmpl, inst);
+	if (err)
+		goto out_drop_skcipher;
+
+out:
+	return err;
+
+out_drop_skcipher:
+	crypto_drop_skcipher(spawn);
+out_free_inst:
 	kfree(inst);
+	goto out;
 }
 
 static struct crypto_template crypto_fpu_tmpl = {
 	.name = "fpu",
-	.alloc = crypto_fpu_alloc,
-	.free = crypto_fpu_free,
+	.create = crypto_fpu_create,
 	.module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/glue_helper.c linux-libre-4.10-rc8-gnu/arch/x86/crypto/glue_helper.c
--- linux-libre-4.9-gnu/arch/x86/crypto/glue_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/glue_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,10 +27,10 @@
 
 #include <linux/module.h>
 #include <crypto/b128ops.h>
+#include <crypto/internal/skcipher.h>
 #include <crypto/lrw.h>
 #include <crypto/xts.h>
 #include <asm/crypto/glue_helper.h>
-#include <crypto/scatterwalk.h>
 
 static int __glue_ecb_crypt_128bit(const struct common_glue_ctx *gctx,
 				   struct blkcipher_desc *desc,
@@ -339,6 +339,41 @@ done:
 	return nbytes;
 }
 
+static unsigned int __glue_xts_req_128bit(const struct common_glue_ctx *gctx,
+					  void *ctx,
+					  struct skcipher_walk *walk)
+{
+	const unsigned int bsize = 128 / 8;
+	unsigned int nbytes = walk->nbytes;
+	u128 *src = walk->src.virt.addr;
+	u128 *dst = walk->dst.virt.addr;
+	unsigned int num_blocks, func_bytes;
+	unsigned int i;
+
+	/* Process multi-block batch */
+	for (i = 0; i < gctx->num_funcs; i++) {
+		num_blocks = gctx->funcs[i].num_blocks;
+		func_bytes = bsize * num_blocks;
+
+		if (nbytes >= func_bytes) {
+			do {
+				gctx->funcs[i].fn_u.xts(ctx, dst, src,
+							walk->iv);
+
+				src += num_blocks;
+				dst += num_blocks;
+				nbytes -= func_bytes;
+			} while (nbytes >= func_bytes);
+
+			if (nbytes < bsize)
+				goto done;
+		}
+	}
+
+done:
+	return nbytes;
+}
+
 /* for implementations implementing faster XTS IV generator */
 int glue_xts_crypt_128bit(const struct common_glue_ctx *gctx,
 			  struct blkcipher_desc *desc, struct scatterlist *dst,
@@ -379,6 +414,43 @@ int glue_xts_crypt_128bit(const struct c
 }
 EXPORT_SYMBOL_GPL(glue_xts_crypt_128bit);
 
+int glue_xts_req_128bit(const struct common_glue_ctx *gctx,
+			struct skcipher_request *req,
+			common_glue_func_t tweak_fn, void *tweak_ctx,
+			void *crypt_ctx)
+{
+	const unsigned int bsize = 128 / 8;
+	struct skcipher_walk walk;
+	bool fpu_enabled = false;
+	unsigned int nbytes;
+	int err;
+
+	err = skcipher_walk_virt(&walk, req, false);
+	nbytes = walk.nbytes;
+	if (!nbytes)
+		return err;
+
+	/* set minimum length to bsize, for tweak_fn */
+	fpu_enabled = glue_skwalk_fpu_begin(bsize, gctx->fpu_blocks_limit,
+					    &walk, fpu_enabled,
+					    nbytes < bsize ? bsize : nbytes);
+
+	/* calculate first value of T */
+	tweak_fn(tweak_ctx, walk.iv, walk.iv);
+
+	while (nbytes) {
+		nbytes = __glue_xts_req_128bit(gctx, crypt_ctx, &walk);
+
+		err = skcipher_walk_done(&walk, nbytes);
+		nbytes = walk.nbytes;
+	}
+
+	glue_fpu_end(fpu_enabled);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(glue_xts_req_128bit);
+
 void glue_xts_crypt_128bit_one(void *ctx, u128 *dst, const u128 *src, le128 *iv,
 			       common_glue_func_t fn)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/sha1-mb/sha1_mb.c linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha1-mb/sha1_mb.c
--- linux-libre-4.9-gnu/arch/x86/crypto/sha1-mb/sha1_mb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha1-mb/sha1_mb.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,7 +114,7 @@ static inline void sha1_init_digest(uint
 }
 
 static inline uint32_t sha1_pad(uint8_t padblock[SHA1_BLOCK_SIZE * 2],
-			 uint32_t total_len)
+			 uint64_t total_len)
 {
 	uint32_t i = total_len & (SHA1_BLOCK_SIZE - 1);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/sha1-mb/sha1_mb_ctx.h linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha1-mb/sha1_mb_ctx.h
--- linux-libre-4.9-gnu/arch/x86/crypto/sha1-mb/sha1_mb_ctx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha1-mb/sha1_mb_ctx.h	2017-02-12 16:03:20.000000000 -0500
@@ -125,7 +125,7 @@ struct sha1_hash_ctx {
 	/* error flag */
 	int error;
 
-	uint32_t	total_length;
+	uint64_t	total_length;
 	const void	*incoming_buffer;
 	uint32_t	incoming_buffer_length;
 	uint8_t		partial_block_buffer[SHA1_BLOCK_SIZE * 2];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/sha256-mb/sha256_mb.c linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha256-mb/sha256_mb.c
--- linux-libre-4.9-gnu/arch/x86/crypto/sha256-mb/sha256_mb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha256-mb/sha256_mb.c	2017-02-12 16:03:20.000000000 -0500
@@ -115,7 +115,7 @@ inline void sha256_init_digest(uint32_t
 }
 
 inline uint32_t sha256_pad(uint8_t padblock[SHA256_BLOCK_SIZE * 2],
-			 uint32_t total_len)
+			 uint64_t total_len)
 {
 	uint32_t i = total_len & (SHA256_BLOCK_SIZE - 1);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/sha256-mb/sha256_mb_ctx.h linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha256-mb/sha256_mb_ctx.h
--- linux-libre-4.9-gnu/arch/x86/crypto/sha256-mb/sha256_mb_ctx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha256-mb/sha256_mb_ctx.h	2017-02-12 16:03:20.000000000 -0500
@@ -125,7 +125,7 @@ struct sha256_hash_ctx {
 	/* error flag */
 	int error;
 
-	uint32_t	total_length;
+	uint64_t	total_length;
 	const void	*incoming_buffer;
 	uint32_t	incoming_buffer_length;
 	uint8_t		partial_block_buffer[SHA256_BLOCK_SIZE * 2];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/sha512-mb/sha512_mb.c linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha512-mb/sha512_mb.c
--- linux-libre-4.9-gnu/arch/x86/crypto/sha512-mb/sha512_mb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha512-mb/sha512_mb.c	2017-02-12 16:03:20.000000000 -0500
@@ -117,7 +117,7 @@ inline void sha512_init_digest(uint64_t
 }
 
 inline uint32_t sha512_pad(uint8_t padblock[SHA512_BLOCK_SIZE * 2],
-			 uint32_t total_len)
+			 uint64_t total_len)
 {
 	uint32_t i = total_len & (SHA512_BLOCK_SIZE - 1);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/crypto/sha512-mb/sha512_mb_ctx.h linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha512-mb/sha512_mb_ctx.h
--- linux-libre-4.9-gnu/arch/x86/crypto/sha512-mb/sha512_mb_ctx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/crypto/sha512-mb/sha512_mb_ctx.h	2017-02-12 16:03:20.000000000 -0500
@@ -119,7 +119,7 @@ struct sha512_hash_ctx {
 	/* error flag */
 	int error;
 
-	uint32_t        total_length;
+	uint64_t        total_length;
 	const void      *incoming_buffer;
 	uint32_t        incoming_buffer_length;
 	uint8_t         partial_block_buffer[SHA512_BLOCK_SIZE * 2];
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/entry/calling.h linux-libre-4.10-rc8-gnu/arch/x86/entry/calling.h
--- linux-libre-4.9-gnu/arch/x86/entry/calling.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/entry/calling.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,8 +90,8 @@ For 32-bit we have the following convent
 
 #define SIZEOF_PTREGS	21*8
 
-	.macro ALLOC_PT_GPREGS_ON_STACK addskip=0
-	addq	$-(15*8+\addskip), %rsp
+	.macro ALLOC_PT_GPREGS_ON_STACK
+	addq	$-(15*8), %rsp
 	.endm
 
 	.macro SAVE_C_REGS_HELPER offset=0 rax=1 rcx=1 r8910=1 r11=1
@@ -147,15 +147,6 @@ For 32-bit we have the following convent
 	movq 5*8+\offset(%rsp), %rbx
 	.endm
 
-	.macro ZERO_EXTRA_REGS
-	xorl	%r15d, %r15d
-	xorl	%r14d, %r14d
-	xorl	%r13d, %r13d
-	xorl	%r12d, %r12d
-	xorl	%ebp, %ebp
-	xorl	%ebx, %ebx
-	.endm
-
 	.macro RESTORE_C_REGS_HELPER rstor_rax=1, rstor_rcx=1, rstor_r11=1, rstor_r8910=1, rstor_rdx=1
 	.if \rstor_r11
 	movq 6*8(%rsp), %r11
@@ -201,6 +192,26 @@ For 32-bit we have the following convent
 	.byte 0xf1
 	.endm
 
+/*
+ * This is a sneaky trick to help the unwinder find pt_regs on the stack.  The
+ * frame pointer is replaced with an encoded pointer to pt_regs.  The encoding
+ * is just setting the LSB, which makes it an invalid stack address and is also
+ * a signal to the unwinder that it's a pt_regs pointer in disguise.
+ *
+ * NOTE: This macro must be used *after* SAVE_EXTRA_REGS because it corrupts
+ * the original rbp.
+ */
+.macro ENCODE_FRAME_POINTER ptregs_offset=0
+#ifdef CONFIG_FRAME_POINTER
+	.if \ptregs_offset
+		leaq \ptregs_offset(%rsp), %rbp
+	.else
+		mov %rsp, %rbp
+	.endif
+	orq	$0x1, %rbp
+#endif
+.endm
+
 #endif /* CONFIG_X86_64 */
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/entry/common.c linux-libre-4.10-rc8-gnu/arch/x86/entry/common.c
--- linux-libre-4.9-gnu/arch/x86/entry/common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/entry/common.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <asm/desc.h>
 #include <asm/traps.h>
 #include <asm/vdso.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cpufeature.h>
 
 #define CREATE_TRACE_POINTS
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/entry/entry_32.S linux-libre-4.10-rc8-gnu/arch/x86/entry/entry_32.S
--- linux-libre-4.9-gnu/arch/x86/entry/entry_32.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/entry/entry_32.S	2017-02-12 16:03:20.000000000 -0500
@@ -45,6 +45,7 @@
 #include <asm/asm.h>
 #include <asm/smap.h>
 #include <asm/export.h>
+#include <asm/frame.h>
 
 	.section .entry.text, "ax"
 
@@ -175,6 +176,22 @@
 	SET_KERNEL_GS %edx
 .endm
 
+/*
+ * This is a sneaky trick to help the unwinder find pt_regs on the stack.  The
+ * frame pointer is replaced with an encoded pointer to pt_regs.  The encoding
+ * is just setting the LSB, which makes it an invalid stack address and is also
+ * a signal to the unwinder that it's a pt_regs pointer in disguise.
+ *
+ * NOTE: This macro must be used *after* SAVE_ALL because it corrupts the
+ * original rbp.
+ */
+.macro ENCODE_FRAME_POINTER
+#ifdef CONFIG_FRAME_POINTER
+	mov %esp, %ebp
+	orl $0x1, %ebp
+#endif
+.endm
+
 .macro RESTORE_INT_REGS
 	popl	%ebx
 	popl	%ecx
@@ -245,6 +262,12 @@ END(__switch_to_asm)
  * edi: kernel thread arg
  */
 ENTRY(ret_from_fork)
+	FRAME_BEGIN		/* help unwinder find end of stack */
+
+	/*
+	 * schedule_tail() is asmlinkage so we have to put its 'prev' argument
+	 * on the stack.
+	 */
 	pushl	%eax
 	call	schedule_tail
 	popl	%eax
@@ -254,8 +277,9 @@ ENTRY(ret_from_fork)
 
 2:
 	/* When we fork, we trace the syscall return in the child, too. */
-	movl    %esp, %eax
+	leal	FRAME_OFFSET(%esp), %eax
 	call    syscall_return_slowpath
+	FRAME_END
 	jmp     restore_all
 
 	/* kernel thread */
@@ -307,13 +331,13 @@ END(ret_from_exception)
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
 	DISABLE_INTERRUPTS(CLBR_ANY)
-need_resched:
+.Lneed_resched:
 	cmpl	$0, PER_CPU_VAR(__preempt_count)
 	jnz	restore_all
 	testl	$X86_EFLAGS_IF, PT_EFLAGS(%esp)	# interrupts off (exception path) ?
 	jz	restore_all
 	call	preempt_schedule_irq
-	jmp	need_resched
+	jmp	.Lneed_resched
 END(resume_kernel)
 #endif
 
@@ -334,7 +358,7 @@ GLOBAL(__begin_SYSENTER_singlestep_regio
  */
 ENTRY(xen_sysenter_target)
 	addl	$5*4, %esp			/* remove xen-provided frame */
-	jmp	sysenter_past_esp
+	jmp	.Lsysenter_past_esp
 #endif
 
 /*
@@ -371,7 +395,7 @@ ENTRY(xen_sysenter_target)
  */
 ENTRY(entry_SYSENTER_32)
 	movl	TSS_sysenter_sp0(%esp), %esp
-sysenter_past_esp:
+.Lsysenter_past_esp:
 	pushl	$__USER_DS		/* pt_regs->ss */
 	pushl	%ebp			/* pt_regs->sp (stashed in bp) */
 	pushfl				/* pt_regs->flags (except IF = 0) */
@@ -504,9 +528,9 @@ ENTRY(entry_INT80_32)
 
 restore_all:
 	TRACE_IRQS_IRET
-restore_all_notrace:
+.Lrestore_all_notrace:
 #ifdef CONFIG_X86_ESPFIX32
-	ALTERNATIVE	"jmp restore_nocheck", "", X86_BUG_ESPFIX
+	ALTERNATIVE	"jmp .Lrestore_nocheck", "", X86_BUG_ESPFIX
 
 	movl	PT_EFLAGS(%esp), %eax		# mix EFLAGS, SS and CS
 	/*
@@ -518,22 +542,23 @@ restore_all_notrace:
 	movb	PT_CS(%esp), %al
 	andl	$(X86_EFLAGS_VM | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
 	cmpl	$((SEGMENT_LDT << 8) | USER_RPL), %eax
-	je ldt_ss				# returning to user-space with LDT SS
+	je .Lldt_ss				# returning to user-space with LDT SS
 #endif
-restore_nocheck:
+.Lrestore_nocheck:
 	RESTORE_REGS 4				# skip orig_eax/error_code
-irq_return:
+.Lirq_return:
 	INTERRUPT_RETURN
+
 .section .fixup, "ax"
 ENTRY(iret_exc	)
 	pushl	$0				# no error code
 	pushl	$do_iret_error
-	jmp	error_code
+	jmp	common_exception
 .previous
-	_ASM_EXTABLE(irq_return, iret_exc)
+	_ASM_EXTABLE(.Lirq_return, iret_exc)
 
 #ifdef CONFIG_X86_ESPFIX32
-ldt_ss:
+.Lldt_ss:
 /*
  * Setup and switch to ESPFIX stack
  *
@@ -562,7 +587,7 @@ ldt_ss:
 	 */
 	DISABLE_INTERRUPTS(CLBR_EAX)
 	lss	(%esp), %esp			/* switch to espfix segment */
-	jmp	restore_nocheck
+	jmp	.Lrestore_nocheck
 #endif
 ENDPROC(entry_INT80_32)
 
@@ -624,6 +649,7 @@ common_interrupt:
 	ASM_CLAC
 	addl	$-0x80, (%esp)			/* Adjust vector into the [-256, -1] range */
 	SAVE_ALL
+	ENCODE_FRAME_POINTER
 	TRACE_IRQS_OFF
 	movl	%esp, %eax
 	call	do_IRQ
@@ -635,6 +661,7 @@ ENTRY(name)				\
 	ASM_CLAC;			\
 	pushl	$~(nr);			\
 	SAVE_ALL;			\
+	ENCODE_FRAME_POINTER;		\
 	TRACE_IRQS_OFF			\
 	movl	%esp, %eax;		\
 	call	fn;			\
@@ -659,7 +686,7 @@ ENTRY(coprocessor_error)
 	ASM_CLAC
 	pushl	$0
 	pushl	$do_coprocessor_error
-	jmp	error_code
+	jmp	common_exception
 END(coprocessor_error)
 
 ENTRY(simd_coprocessor_error)
@@ -673,14 +700,14 @@ ENTRY(simd_coprocessor_error)
 #else
 	pushl	$do_simd_coprocessor_error
 #endif
-	jmp	error_code
+	jmp	common_exception
 END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
 	ASM_CLAC
 	pushl	$-1				# mark this as an int
 	pushl	$do_device_not_available
-	jmp	error_code
+	jmp	common_exception
 END(device_not_available)
 
 #ifdef CONFIG_PARAVIRT
@@ -694,59 +721,59 @@ ENTRY(overflow)
 	ASM_CLAC
 	pushl	$0
 	pushl	$do_overflow
-	jmp	error_code
+	jmp	common_exception
 END(overflow)
 
 ENTRY(bounds)
 	ASM_CLAC
 	pushl	$0
 	pushl	$do_bounds
-	jmp	error_code
+	jmp	common_exception
 END(bounds)
 
 ENTRY(invalid_op)
 	ASM_CLAC
 	pushl	$0
 	pushl	$do_invalid_op
-	jmp	error_code
+	jmp	common_exception
 END(invalid_op)
 
 ENTRY(coprocessor_segment_overrun)
 	ASM_CLAC
 	pushl	$0
 	pushl	$do_coprocessor_segment_overrun
-	jmp	error_code
+	jmp	common_exception
 END(coprocessor_segment_overrun)
 
 ENTRY(invalid_TSS)
 	ASM_CLAC
 	pushl	$do_invalid_TSS
-	jmp	error_code
+	jmp	common_exception
 END(invalid_TSS)
 
 ENTRY(segment_not_present)
 	ASM_CLAC
 	pushl	$do_segment_not_present
-	jmp	error_code
+	jmp	common_exception
 END(segment_not_present)
 
 ENTRY(stack_segment)
 	ASM_CLAC
 	pushl	$do_stack_segment
-	jmp	error_code
+	jmp	common_exception
 END(stack_segment)
 
 ENTRY(alignment_check)
 	ASM_CLAC
 	pushl	$do_alignment_check
-	jmp	error_code
+	jmp	common_exception
 END(alignment_check)
 
 ENTRY(divide_error)
 	ASM_CLAC
 	pushl	$0				# no error code
 	pushl	$do_divide_error
-	jmp	error_code
+	jmp	common_exception
 END(divide_error)
 
 #ifdef CONFIG_X86_MCE
@@ -754,7 +781,7 @@ ENTRY(machine_check)
 	ASM_CLAC
 	pushl	$0
 	pushl	machine_check_vector
-	jmp	error_code
+	jmp	common_exception
 END(machine_check)
 #endif
 
@@ -762,13 +789,14 @@ ENTRY(spurious_interrupt_bug)
 	ASM_CLAC
 	pushl	$0
 	pushl	$do_spurious_interrupt_bug
-	jmp	error_code
+	jmp	common_exception
 END(spurious_interrupt_bug)
 
 #ifdef CONFIG_XEN
 ENTRY(xen_hypervisor_callback)
 	pushl	$-1				/* orig_ax = -1 => not a system call */
 	SAVE_ALL
+	ENCODE_FRAME_POINTER
 	TRACE_IRQS_OFF
 
 	/*
@@ -823,6 +851,7 @@ ENTRY(xen_failsafe_callback)
 	jmp	iret_exc
 5:	pushl	$-1				/* orig_ax = -1 => not a system call */
 	SAVE_ALL
+	ENCODE_FRAME_POINTER
 	jmp	ret_from_exception
 
 .section .fixup, "ax"
@@ -882,15 +911,15 @@ ftrace_call:
 	popl	%edx
 	popl	%ecx
 	popl	%eax
-ftrace_ret:
+.Lftrace_ret:
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 .globl ftrace_graph_call
 ftrace_graph_call:
 	jmp	ftrace_stub
 #endif
 
-.globl ftrace_stub
-ftrace_stub:
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
 	ret
 END(ftrace_caller)
 
@@ -952,7 +981,7 @@ GLOBAL(ftrace_regs_call)
 	popl	%gs
 	addl	$8, %esp			/* Skip orig_ax and ip */
 	popf					/* Pop flags at end (no addl to corrupt flags) */
-	jmp	ftrace_ret
+	jmp	.Lftrace_ret
 
 	popf
 	jmp	ftrace_stub
@@ -963,7 +992,7 @@ ENTRY(mcount)
 	jb	ftrace_stub			/* Paging not enabled yet? */
 
 	cmpl	$ftrace_stub, ftrace_trace_function
-	jnz	trace
+	jnz	.Ltrace
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	cmpl	$ftrace_stub, ftrace_graph_return
 	jnz	ftrace_graph_caller
@@ -976,7 +1005,7 @@ ftrace_stub:
 	ret
 
 	/* taken from glibc */
-trace:
+.Ltrace:
 	pushl	%eax
 	pushl	%ecx
 	pushl	%edx
@@ -1027,7 +1056,7 @@ return_to_handler:
 ENTRY(trace_page_fault)
 	ASM_CLAC
 	pushl	$trace_do_page_fault
-	jmp	error_code
+	jmp	common_exception
 END(trace_page_fault)
 #endif
 
@@ -1035,7 +1064,10 @@ ENTRY(page_fault)
 	ASM_CLAC
 	pushl	$do_page_fault
 	ALIGN
-error_code:
+	jmp common_exception
+END(page_fault)
+
+common_exception:
 	/* the function address is in %gs's slot on the stack */
 	pushl	%fs
 	pushl	%es
@@ -1047,6 +1079,7 @@ error_code:
 	pushl	%edx
 	pushl	%ecx
 	pushl	%ebx
+	ENCODE_FRAME_POINTER
 	cld
 	movl	$(__KERNEL_PERCPU), %ecx
 	movl	%ecx, %fs
@@ -1064,7 +1097,7 @@ error_code:
 	movl	%esp, %eax			# pt_regs pointer
 	call	*%edi
 	jmp	ret_from_exception
-END(page_fault)
+END(common_exception)
 
 ENTRY(debug)
 	/*
@@ -1079,6 +1112,7 @@ ENTRY(debug)
 	ASM_CLAC
 	pushl	$-1				# mark this as an int
 	SAVE_ALL
+	ENCODE_FRAME_POINTER
 	xorl	%edx, %edx			# error code 0
 	movl	%esp, %eax			# pt_regs pointer
 
@@ -1094,11 +1128,11 @@ ENTRY(debug)
 
 .Ldebug_from_sysenter_stack:
 	/* We're on the SYSENTER stack.  Switch off. */
-	movl	%esp, %ebp
+	movl	%esp, %ebx
 	movl	PER_CPU_VAR(cpu_current_top_of_stack), %esp
 	TRACE_IRQS_OFF
 	call	do_debug
-	movl	%ebp, %esp
+	movl	%ebx, %esp
 	jmp	ret_from_exception
 END(debug)
 
@@ -1116,11 +1150,12 @@ ENTRY(nmi)
 	movl	%ss, %eax
 	cmpw	$__ESPFIX_SS, %ax
 	popl	%eax
-	je	nmi_espfix_stack
+	je	.Lnmi_espfix_stack
 #endif
 
 	pushl	%eax				# pt_regs->orig_ax
 	SAVE_ALL
+	ENCODE_FRAME_POINTER
 	xorl	%edx, %edx			# zero error code
 	movl	%esp, %eax			# pt_regs pointer
 
@@ -1132,21 +1167,21 @@ ENTRY(nmi)
 
 	/* Not on SYSENTER stack. */
 	call	do_nmi
-	jmp	restore_all_notrace
+	jmp	.Lrestore_all_notrace
 
 .Lnmi_from_sysenter_stack:
 	/*
 	 * We're on the SYSENTER stack.  Switch off.  No one (not even debug)
 	 * is using the thread stack right now, so it's safe for us to use it.
 	 */
-	movl	%esp, %ebp
+	movl	%esp, %ebx
 	movl	PER_CPU_VAR(cpu_current_top_of_stack), %esp
 	call	do_nmi
-	movl	%ebp, %esp
-	jmp	restore_all_notrace
+	movl	%ebx, %esp
+	jmp	.Lrestore_all_notrace
 
 #ifdef CONFIG_X86_ESPFIX32
-nmi_espfix_stack:
+.Lnmi_espfix_stack:
 	/*
 	 * create the pointer to lss back
 	 */
@@ -1159,12 +1194,13 @@ nmi_espfix_stack:
 	.endr
 	pushl	%eax
 	SAVE_ALL
+	ENCODE_FRAME_POINTER
 	FIXUP_ESPFIX_STACK			# %eax == %esp
 	xorl	%edx, %edx			# zero error code
 	call	do_nmi
 	RESTORE_REGS
 	lss	12+4(%esp), %esp		# back to espfix stack
-	jmp	irq_return
+	jmp	.Lirq_return
 #endif
 END(nmi)
 
@@ -1172,6 +1208,7 @@ ENTRY(int3)
 	ASM_CLAC
 	pushl	$-1				# mark this as an int
 	SAVE_ALL
+	ENCODE_FRAME_POINTER
 	TRACE_IRQS_OFF
 	xorl	%edx, %edx			# zero error code
 	movl	%esp, %eax			# pt_regs pointer
@@ -1181,14 +1218,14 @@ END(int3)
 
 ENTRY(general_protection)
 	pushl	$do_general_protection
-	jmp	error_code
+	jmp	common_exception
 END(general_protection)
 
 #ifdef CONFIG_KVM_GUEST
 ENTRY(async_page_fault)
 	ASM_CLAC
 	pushl	$do_async_page_fault
-	jmp	error_code
+	jmp	common_exception
 END(async_page_fault)
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/entry/entry_64.S linux-libre-4.10-rc8-gnu/arch/x86/entry/entry_64.S
--- linux-libre-4.9-gnu/arch/x86/entry/entry_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/entry/entry_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -36,14 +36,9 @@
 #include <asm/smap.h>
 #include <asm/pgtable_types.h>
 #include <asm/export.h>
+#include <asm/frame.h>
 #include <linux/err.h>
 
-/* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */
-#include <linux/elf-em.h>
-#define AUDIT_ARCH_X86_64			(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
-#define __AUDIT_ARCH_64BIT			0x80000000
-#define __AUDIT_ARCH_LE				0x40000000
-
 .code64
 .section .entry.text, "ax"
 
@@ -414,17 +409,19 @@ END(__switch_to_asm)
  * r12: kernel thread arg
  */
 ENTRY(ret_from_fork)
+	FRAME_BEGIN			/* help unwinder find end of stack */
 	movq	%rax, %rdi
-	call	schedule_tail			/* rdi: 'prev' task parameter */
+	call	schedule_tail		/* rdi: 'prev' task parameter */
 
-	testq	%rbx, %rbx			/* from kernel_thread? */
-	jnz	1f				/* kernel threads are uncommon */
+	testq	%rbx, %rbx		/* from kernel_thread? */
+	jnz	1f			/* kernel threads are uncommon */
 
 2:
-	movq	%rsp, %rdi
+	leaq	FRAME_OFFSET(%rsp),%rdi	/* pt_regs pointer */
 	call	syscall_return_slowpath	/* returns with IRQs disabled */
 	TRACE_IRQS_ON			/* user mode is traced as IRQS on */
 	SWAPGS
+	FRAME_END
 	jmp	restore_regs_and_iret
 
 1:
@@ -469,6 +466,7 @@ END(irq_entries_start)
 	ALLOC_PT_GPREGS_ON_STACK
 	SAVE_C_REGS
 	SAVE_EXTRA_REGS
+	ENCODE_FRAME_POINTER
 
 	testb	$3, CS(%rsp)
 	jz	1f
@@ -985,6 +983,7 @@ ENTRY(xen_failsafe_callback)
 	ALLOC_PT_GPREGS_ON_STACK
 	SAVE_C_REGS
 	SAVE_EXTRA_REGS
+	ENCODE_FRAME_POINTER
 	jmp	error_exit
 END(xen_failsafe_callback)
 
@@ -1028,6 +1027,7 @@ ENTRY(paranoid_entry)
 	cld
 	SAVE_C_REGS 8
 	SAVE_EXTRA_REGS 8
+	ENCODE_FRAME_POINTER 8
 	movl	$1, %ebx
 	movl	$MSR_GS_BASE, %ecx
 	rdmsr
@@ -1075,6 +1075,7 @@ ENTRY(error_entry)
 	cld
 	SAVE_C_REGS 8
 	SAVE_EXTRA_REGS 8
+	ENCODE_FRAME_POINTER 8
 	xorl	%ebx, %ebx
 	testb	$3, CS+8(%rsp)
 	jz	.Lerror_kernelspace
@@ -1257,6 +1258,7 @@ ENTRY(nmi)
 	pushq	%r13		/* pt_regs->r13 */
 	pushq	%r14		/* pt_regs->r14 */
 	pushq	%r15		/* pt_regs->r15 */
+	ENCODE_FRAME_POINTER
 
 	/*
 	 * At this point we no longer need to worry about stack damage
@@ -1270,11 +1272,10 @@ ENTRY(nmi)
 
 	/*
 	 * Return back to user mode.  We must *not* do the normal exit
-	 * work, because we don't want to enable interrupts.  Fortunately,
-	 * do_nmi doesn't modify pt_regs.
+	 * work, because we don't want to enable interrupts.
 	 */
 	SWAPGS
-	jmp	restore_c_regs_and_iret
+	jmp	restore_regs_and_iret
 
 .Lnmi_from_kernel:
 	/*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/entry/vdso/vclock_gettime.c linux-libre-4.10-rc8-gnu/arch/x86/entry/vdso/vclock_gettime.c
--- linux-libre-4.9-gnu/arch/x86/entry/vdso/vclock_gettime.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/entry/vdso/vclock_gettime.c	2017-02-12 16:03:20.000000000 -0500
@@ -92,10 +92,10 @@ static notrace const struct pvclock_vsys
 	return (const struct pvclock_vsyscall_time_info *)&pvclock_page;
 }
 
-static notrace cycle_t vread_pvclock(int *mode)
+static notrace u64 vread_pvclock(int *mode)
 {
 	const struct pvclock_vcpu_time_info *pvti = &get_pvti0()->pvti;
-	cycle_t ret;
+	u64 ret;
 	u64 last;
 	u32 version;
 
@@ -142,9 +142,9 @@ static notrace cycle_t vread_pvclock(int
 }
 #endif
 
-notrace static cycle_t vread_tsc(void)
+notrace static u64 vread_tsc(void)
 {
-	cycle_t ret = (cycle_t)rdtsc_ordered();
+	u64 ret = (u64)rdtsc_ordered();
 	u64 last = gtod->cycle_last;
 
 	if (likely(ret >= last))
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/entry/vdso/vma.c linux-libre-4.10-rc8-gnu/arch/x86/entry/vdso/vma.c
--- linux-libre-4.9-gnu/arch/x86/entry/vdso/vma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/entry/vdso/vma.c	2017-02-12 16:03:20.000000000 -0500
@@ -109,7 +109,7 @@ static int vvar_fault(const struct vm_sp
 		return VM_FAULT_SIGBUS;
 
 	if (sym_offset == image->sym_vvar_page) {
-		ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
+		ret = vm_insert_pfn(vma, vmf->address,
 				    __pa_symbol(&__vvar_page) >> PAGE_SHIFT);
 	} else if (sym_offset == image->sym_pvclock_page) {
 		struct pvclock_vsyscall_time_info *pvti =
@@ -117,7 +117,7 @@ static int vvar_fault(const struct vm_sp
 		if (pvti && vclock_was_used(VCLOCK_PVCLOCK)) {
 			ret = vm_insert_pfn(
 				vma,
-				(unsigned long)vmf->virtual_address,
+				vmf->address,
 				__pa(pvti) >> PAGE_SHIFT);
 		}
 	}
@@ -161,8 +161,6 @@ static int map_vdso(const struct vdso_im
 	}
 
 	text_start = addr - image->sym_vvar_start;
-	current->mm->context.vdso = (void __user *)text_start;
-	current->mm->context.vdso_image = image;
 
 	/*
 	 * MAYWRITE to allow gdb to COW and set breakpoints
@@ -189,14 +187,12 @@ static int map_vdso(const struct vdso_im
 	if (IS_ERR(vma)) {
 		ret = PTR_ERR(vma);
 		do_munmap(mm, text_start, image->size);
+	} else {
+		current->mm->context.vdso = (void __user *)text_start;
+		current->mm->context.vdso_image = image;
 	}
 
 up_fail:
-	if (ret) {
-		current->mm->context.vdso = NULL;
-		current->mm->context.vdso_image = NULL;
-	}
-
 	up_write(&mm->mmap_sem);
 	return ret;
 }
@@ -375,7 +371,7 @@ static int __init init_vdso(void)
 
 	/* notifier priority > KVM */
 	return cpuhp_setup_state(CPUHP_AP_X86_VDSO_VMA_ONLINE,
-				 "AP_X86_VDSO_VMA_ONLINE", vgetcpu_online, NULL);
+				 "x86/vdso/vma:online", vgetcpu_online, NULL);
 }
 subsys_initcall(init_vdso);
 #endif /* CONFIG_X86_64 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/amd/ibs.c linux-libre-4.10-rc8-gnu/arch/x86/events/amd/ibs.c
--- linux-libre-4.9-gnu/arch/x86/events/amd/ibs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/amd/ibs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1010,7 +1010,7 @@ static __init int amd_ibs_init(void)
 	 * all online cpus.
 	 */
 	cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_IBS_STARTING,
-			  "AP_PERF_X86_AMD_IBS_STARTING",
+			  "perf/x86/amd/ibs:starting",
 			  x86_pmu_amd_ibs_starting_cpu,
 			  x86_pmu_amd_ibs_dying_cpu);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/amd/power.c linux-libre-4.10-rc8-gnu/arch/x86/events/amd/power.c
--- linux-libre-4.9-gnu/arch/x86/events/amd/power.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/amd/power.c	2017-02-12 16:03:20.000000000 -0500
@@ -291,7 +291,7 @@ static int __init amd_power_pmu_init(voi
 
 
 	cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_POWER_ONLINE,
-			  "AP_PERF_X86_AMD_POWER_ONLINE",
+			  "perf/x86/amd/power:online",
 			  power_cpu_init, power_cpu_exit);
 
 	ret = perf_pmu_register(&pmu_class, "power", -1);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/amd/uncore.c linux-libre-4.10-rc8-gnu/arch/x86/events/amd/uncore.c
--- linux-libre-4.9-gnu/arch/x86/events/amd/uncore.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/amd/uncore.c	2017-02-12 16:03:20.000000000 -0500
@@ -527,16 +527,16 @@ static int __init amd_uncore_init(void)
 	 * Install callbacks. Core will call them for each online cpu.
 	 */
 	if (cpuhp_setup_state(CPUHP_PERF_X86_AMD_UNCORE_PREP,
-			      "PERF_X86_AMD_UNCORE_PREP",
+			      "perf/x86/amd/uncore:prepare",
 			      amd_uncore_cpu_up_prepare, amd_uncore_cpu_dead))
 		goto fail_l2;
 
 	if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING,
-			      "AP_PERF_X86_AMD_UNCORE_STARTING",
+			      "perf/x86/amd/uncore:starting",
 			      amd_uncore_cpu_starting, NULL))
 		goto fail_prep;
 	if (cpuhp_setup_state(CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE,
-			      "AP_PERF_X86_AMD_UNCORE_ONLINE",
+			      "perf/x86/amd/uncore:online",
 			      amd_uncore_cpu_online,
 			      amd_uncore_cpu_down_prepare))
 		goto fail_start;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/core.c linux-libre-4.10-rc8-gnu/arch/x86/events/core.c
--- linux-libre-4.9-gnu/arch/x86/events/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -365,7 +365,11 @@ int x86_add_exclusive(unsigned int what)
 {
 	int i;
 
-	if (x86_pmu.lbr_pt_coexist)
+	/*
+	 * When lbr_pt_coexist we allow PT to coexist with either LBR or BTS.
+	 * LBR and BTS are still mutually exclusive.
+	 */
+	if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
 		return 0;
 
 	if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
@@ -388,7 +392,7 @@ fail_unlock:
 
 void x86_del_exclusive(unsigned int what)
 {
-	if (x86_pmu.lbr_pt_coexist)
+	if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
 		return;
 
 	atomic_dec(&x86_pmu.lbr_exclusive[what]);
@@ -501,6 +505,10 @@ int x86_pmu_hw_config(struct perf_event
 
 		if (event->attr.precise_ip > precise)
 			return -EOPNOTSUPP;
+
+		/* There's no sense in having PEBS for non sampling events: */
+		if (!is_sampling_event(event))
+			return -EINVAL;
 	}
 	/*
 	 * check that PEBS LBR correction does not conflict with
@@ -1816,18 +1824,18 @@ static int __init init_hw_perf_events(vo
 	 * Install callbacks. Core will call them for each online
 	 * cpu.
 	 */
-	err = cpuhp_setup_state(CPUHP_PERF_X86_PREPARE, "PERF_X86_PREPARE",
+	err = cpuhp_setup_state(CPUHP_PERF_X86_PREPARE, "perf/x86:prepare",
 				x86_pmu_prepare_cpu, x86_pmu_dead_cpu);
 	if (err)
 		return err;
 
 	err = cpuhp_setup_state(CPUHP_AP_PERF_X86_STARTING,
-				"AP_PERF_X86_STARTING", x86_pmu_starting_cpu,
+				"perf/x86:starting", x86_pmu_starting_cpu,
 				x86_pmu_dying_cpu);
 	if (err)
 		goto out;
 
-	err = cpuhp_setup_state(CPUHP_AP_PERF_X86_ONLINE, "AP_PERF_X86_ONLINE",
+	err = cpuhp_setup_state(CPUHP_AP_PERF_X86_ONLINE, "perf/x86:online",
 				x86_pmu_online_cpu, NULL);
 	if (err)
 		goto out1;
@@ -2299,7 +2307,7 @@ valid_user_frame(const void __user *fp,
 static unsigned long get_segment_base(unsigned int segment)
 {
 	struct desc_struct *desc;
-	int idx = segment >> 3;
+	unsigned int idx = segment >> 3;
 
 	if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
 #ifdef CONFIG_MODIFY_LDT_SYSCALL
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/core.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/core.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -2110,6 +2110,27 @@ again:
 		    GLOBAL_STATUS_LBRS_FROZEN);
 	if (!status)
 		goto done;
+	/*
+	 * In case multiple PEBS events are sampled at the same time,
+	 * it is possible to have GLOBAL_STATUS bit 62 set indicating
+	 * PEBS buffer overflow and also seeing at most 3 PEBS counters
+	 * having their bits set in the status register. This is a sign
+	 * that there was at least one PEBS record pending at the time
+	 * of the PMU interrupt. PEBS counters must only be processed
+	 * via the drain_pebs() calls and not via the regular sample
+	 * processing loop coming after that the function, otherwise
+	 * phony regular samples may be generated in the sampling buffer
+	 * not marked with the EXACT tag. Another possibility is to have
+	 * one PEBS event and at least one non-PEBS event whic hoverflows
+	 * while PEBS has armed. In this case, bit 62 of GLOBAL_STATUS will
+	 * not be set, yet the overflow status bit for the PEBS counter will
+	 * be on Skylake.
+	 *
+	 * To avoid this problem, we systematically ignore the PEBS-enabled
+	 * counters from the GLOBAL_STATUS mask and we always process PEBS
+	 * events via drain_pebs().
+	 */
+	status &= ~cpuc->pebs_enabled;
 
 	/*
 	 * PEBS overflow sets bit 62 in the global status register
@@ -2117,15 +2138,6 @@ again:
 	if (__test_and_clear_bit(62, (unsigned long *)&status)) {
 		handled++;
 		x86_pmu.drain_pebs(regs);
-		/*
-		 * There are cases where, even though, the PEBS ovfl bit is set
-		 * in GLOBAL_OVF_STATUS, the PEBS events may also have their
-		 * overflow bits set for their counters. We must clear them
-		 * here because they have been processed as exact samples in
-		 * the drain_pebs() routine. They must not be processed again
-		 * in the for_each_bit_set() loop for regular samples below.
-		 */
-		status &= ~cpuc->pebs_enabled;
 		status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
 	}
 
@@ -3164,13 +3176,16 @@ static void intel_pmu_cpu_starting(int c
 
 	if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
 		for_each_cpu(i, topology_sibling_cpumask(cpu)) {
+			struct cpu_hw_events *sibling;
 			struct intel_excl_cntrs *c;
 
-			c = per_cpu(cpu_hw_events, i).excl_cntrs;
+			sibling = &per_cpu(cpu_hw_events, i);
+			c = sibling->excl_cntrs;
 			if (c && c->core_id == core_id) {
 				cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
 				cpuc->excl_cntrs = c;
-				cpuc->excl_thread_id = 1;
+				if (!sibling->excl_thread_id)
+					cpuc->excl_thread_id = 1;
 				break;
 			}
 		}
@@ -3975,7 +3990,7 @@ __init int intel_pmu_init(void)
 		     x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
 		x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
 	}
-	x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+	x86_pmu.intel_ctrl = (1ULL << x86_pmu.num_counters) - 1;
 
 	if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
 		WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/cqm.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/cqm.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/cqm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/cqm.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,9 +7,9 @@
 #include <linux/perf_event.h>
 #include <linux/slab.h>
 #include <asm/cpu_device_id.h>
+#include <asm/intel_rdt_common.h>
 #include "../perf_event.h"
 
-#define MSR_IA32_PQR_ASSOC	0x0c8f
 #define MSR_IA32_QM_CTR		0x0c8e
 #define MSR_IA32_QM_EVTSEL	0x0c8d
 
@@ -24,32 +24,13 @@ static unsigned int cqm_l3_scale; /* sup
 static bool cqm_enabled, mbm_enabled;
 unsigned int mbm_socket_max;
 
-/**
- * struct intel_pqr_state - State cache for the PQR MSR
- * @rmid:		The cached Resource Monitoring ID
- * @closid:		The cached Class Of Service ID
- * @rmid_usecnt:	The usage counter for rmid
- *
- * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
- * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
- * contains both parts, so we need to cache them.
- *
- * The cache also helps to avoid pointless updates if the value does
- * not change.
- */
-struct intel_pqr_state {
-	u32			rmid;
-	u32			closid;
-	int			rmid_usecnt;
-};
-
 /*
  * The cached intel_pqr_state is strictly per CPU and can never be
  * updated from a remote CPU. Both functions which modify the state
  * (intel_cqm_event_start and intel_cqm_event_stop) are called with
  * interrupts disabled, which is sufficient for the protection.
  */
-static DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
+DEFINE_PER_CPU(struct intel_pqr_state, pqr_state);
 static struct hrtimer *mbm_timers;
 /**
  * struct sample - mbm event's (local or total) data
@@ -1766,9 +1747,9 @@ static int __init intel_cqm_init(void)
 	 * is enabled to avoid notifier leak.
 	 */
 	cpuhp_setup_state(CPUHP_AP_PERF_X86_CQM_STARTING,
-			  "AP_PERF_X86_CQM_STARTING",
+			  "perf/x86/cqm:starting",
 			  intel_cqm_cpu_starting, NULL);
-	cpuhp_setup_state(CPUHP_AP_PERF_X86_CQM_ONLINE, "AP_PERF_X86_CQM_ONLINE",
+	cpuhp_setup_state(CPUHP_AP_PERF_X86_CQM_ONLINE, "perf/x86/cqm:online",
 			  NULL, intel_cqm_cpu_exit);
 
 out:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/cstate.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/cstate.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/cstate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/cstate.c	2017-02-12 16:03:20.000000000 -0500
@@ -434,6 +434,7 @@ static struct pmu cstate_core_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static struct pmu cstate_pkg_pmu = {
@@ -447,6 +448,7 @@ static struct pmu cstate_pkg_pmu = {
 	.stop		= cstate_pmu_event_stop,
 	.read		= cstate_pmu_event_update,
 	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT,
+	.module		= THIS_MODULE,
 };
 
 static const struct cstate_model nhm_cstates __initconst = {
@@ -594,6 +596,9 @@ static int __init cstate_probe(const str
 
 static inline void cstate_cleanup(void)
 {
+	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_ONLINE);
+	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_STARTING);
+
 	if (has_cstate_core)
 		perf_pmu_unregister(&cstate_core_pmu);
 
@@ -606,16 +611,16 @@ static int __init cstate_init(void)
 	int err;
 
 	cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_STARTING,
-			  "AP_PERF_X86_CSTATE_STARTING", cstate_cpu_init,
-			  NULL);
+			  "perf/x86/cstate:starting", cstate_cpu_init, NULL);
 	cpuhp_setup_state(CPUHP_AP_PERF_X86_CSTATE_ONLINE,
-			  "AP_PERF_X86_CSTATE_ONLINE", NULL, cstate_cpu_exit);
+			  "perf/x86/cstate:online", NULL, cstate_cpu_exit);
 
 	if (has_cstate_core) {
 		err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);
 		if (err) {
 			has_cstate_core = false;
 			pr_info("Failed to register cstate core pmu\n");
+			cstate_cleanup();
 			return err;
 		}
 	}
@@ -629,8 +634,7 @@ static int __init cstate_init(void)
 			return err;
 		}
 	}
-
-	return err;
+	return 0;
 }
 
 static int __init cstate_pmu_init(void)
@@ -655,8 +659,6 @@ module_init(cstate_pmu_init);
 
 static void __exit cstate_pmu_exit(void)
 {
-	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_ONLINE);
-	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_CSTATE_STARTING);
 	cstate_cleanup();
 }
 module_exit(cstate_pmu_exit);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/ds.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/ds.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/ds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/ds.c	2017-02-12 16:03:20.000000000 -0500
@@ -1389,9 +1389,13 @@ static void intel_pmu_drain_pebs_nhm(str
 			continue;
 
 		/* log dropped samples number */
-		if (error[bit])
+		if (error[bit]) {
 			perf_log_lost_samples(event, error[bit]);
 
+			if (perf_event_account_interrupt(event))
+				x86_pmu_stop(event, 0);
+		}
+
 		if (counts[bit]) {
 			__intel_pmu_pebs_event(event, iregs, base,
 					       top, bit, counts[bit]);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/pt.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/pt.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/pt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/pt.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,13 +36,6 @@ static DEFINE_PER_CPU(struct pt, pt_ctx)
 
 static struct pt_pmu pt_pmu;
 
-enum cpuid_regs {
-	CR_EAX = 0,
-	CR_ECX,
-	CR_EDX,
-	CR_EBX
-};
-
 /*
  * Capabilities of Intel PT hardware, such as number of address bits or
  * supported output schemes, are cached and exported to userspace as "caps"
@@ -64,21 +57,21 @@ static struct pt_cap_desc {
 	u8		reg;
 	u32		mask;
 } pt_caps[] = {
-	PT_CAP(max_subleaf,		0, CR_EAX, 0xffffffff),
-	PT_CAP(cr3_filtering,		0, CR_EBX, BIT(0)),
-	PT_CAP(psb_cyc,			0, CR_EBX, BIT(1)),
-	PT_CAP(ip_filtering,		0, CR_EBX, BIT(2)),
-	PT_CAP(mtc,			0, CR_EBX, BIT(3)),
-	PT_CAP(ptwrite,			0, CR_EBX, BIT(4)),
-	PT_CAP(power_event_trace,	0, CR_EBX, BIT(5)),
-	PT_CAP(topa_output,		0, CR_ECX, BIT(0)),
-	PT_CAP(topa_multiple_entries,	0, CR_ECX, BIT(1)),
-	PT_CAP(single_range_output,	0, CR_ECX, BIT(2)),
-	PT_CAP(payloads_lip,		0, CR_ECX, BIT(31)),
-	PT_CAP(num_address_ranges,	1, CR_EAX, 0x3),
-	PT_CAP(mtc_periods,		1, CR_EAX, 0xffff0000),
-	PT_CAP(cycle_thresholds,	1, CR_EBX, 0xffff),
-	PT_CAP(psb_periods,		1, CR_EBX, 0xffff0000),
+	PT_CAP(max_subleaf,		0, CPUID_EAX, 0xffffffff),
+	PT_CAP(cr3_filtering,		0, CPUID_EBX, BIT(0)),
+	PT_CAP(psb_cyc,			0, CPUID_EBX, BIT(1)),
+	PT_CAP(ip_filtering,		0, CPUID_EBX, BIT(2)),
+	PT_CAP(mtc,			0, CPUID_EBX, BIT(3)),
+	PT_CAP(ptwrite,			0, CPUID_EBX, BIT(4)),
+	PT_CAP(power_event_trace,	0, CPUID_EBX, BIT(5)),
+	PT_CAP(topa_output,		0, CPUID_ECX, BIT(0)),
+	PT_CAP(topa_multiple_entries,	0, CPUID_ECX, BIT(1)),
+	PT_CAP(single_range_output,	0, CPUID_ECX, BIT(2)),
+	PT_CAP(payloads_lip,		0, CPUID_ECX, BIT(31)),
+	PT_CAP(num_address_ranges,	1, CPUID_EAX, 0x3),
+	PT_CAP(mtc_periods,		1, CPUID_EAX, 0xffff0000),
+	PT_CAP(cycle_thresholds,	1, CPUID_EBX, 0xffff),
+	PT_CAP(psb_periods,		1, CPUID_EBX, 0xffff0000),
 };
 
 static u32 pt_cap_get(enum pt_capabilities cap)
@@ -213,10 +206,10 @@ static int __init pt_pmu_hw_init(void)
 
 	for (i = 0; i < PT_CPUID_LEAVES; i++) {
 		cpuid_count(20, i,
-			    &pt_pmu.caps[CR_EAX + i*PT_CPUID_REGS_NUM],
-			    &pt_pmu.caps[CR_EBX + i*PT_CPUID_REGS_NUM],
-			    &pt_pmu.caps[CR_ECX + i*PT_CPUID_REGS_NUM],
-			    &pt_pmu.caps[CR_EDX + i*PT_CPUID_REGS_NUM]);
+			    &pt_pmu.caps[CPUID_EAX + i*PT_CPUID_REGS_NUM],
+			    &pt_pmu.caps[CPUID_EBX + i*PT_CPUID_REGS_NUM],
+			    &pt_pmu.caps[CPUID_ECX + i*PT_CPUID_REGS_NUM],
+			    &pt_pmu.caps[CPUID_EDX + i*PT_CPUID_REGS_NUM]);
 	}
 
 	ret = -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/rapl.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/rapl.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/rapl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/rapl.c	2017-02-12 16:03:20.000000000 -0500
@@ -161,7 +161,13 @@ static u64 rapl_timer_ms;
 
 static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
 {
-	return rapl_pmus->pmus[topology_logical_package_id(cpu)];
+	unsigned int pkgid = topology_logical_package_id(cpu);
+
+	/*
+	 * The unsigned check also catches the '-1' return value for non
+	 * existent mappings in the topology map.
+	 */
+	return pkgid < rapl_pmus->maxpkg ? rapl_pmus->pmus[pkgid] : NULL;
 }
 
 static inline u64 rapl_read_counter(struct perf_event *event)
@@ -402,6 +408,8 @@ static int rapl_pmu_event_init(struct pe
 
 	/* must be done before validate_group */
 	pmu = cpu_to_rapl_pmu(event->cpu);
+	if (!pmu)
+		return -EINVAL;
 	event->cpu = pmu->cpu;
 	event->pmu_private = pmu;
 	event->hw.event_base = msr;
@@ -585,6 +593,20 @@ static int rapl_cpu_online(unsigned int
 	struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
 	int target;
 
+	if (!pmu) {
+		pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
+		if (!pmu)
+			return -ENOMEM;
+
+		raw_spin_lock_init(&pmu->lock);
+		INIT_LIST_HEAD(&pmu->active_list);
+		pmu->pmu = &rapl_pmus->pmu;
+		pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
+		rapl_hrtimer_init(pmu);
+
+		rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
+	}
+
 	/*
 	 * Check if there is an online cpu in the package which collects rapl
 	 * events already.
@@ -598,27 +620,6 @@ static int rapl_cpu_online(unsigned int
 	return 0;
 }
 
-static int rapl_cpu_prepare(unsigned int cpu)
-{
-	struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
-
-	if (pmu)
-		return 0;
-
-	pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
-	if (!pmu)
-		return -ENOMEM;
-
-	raw_spin_lock_init(&pmu->lock);
-	INIT_LIST_HEAD(&pmu->active_list);
-	pmu->pmu = &rapl_pmus->pmu;
-	pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
-	pmu->cpu = -1;
-	rapl_hrtimer_init(pmu);
-	rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
-	return 0;
-}
-
 static int rapl_check_hw_unit(bool apply_quirk)
 {
 	u64 msr_rapl_power_unit_bits;
@@ -697,6 +698,7 @@ static int __init init_rapl_pmus(void)
 	rapl_pmus->pmu.start		= rapl_pmu_event_start;
 	rapl_pmus->pmu.stop		= rapl_pmu_event_stop;
 	rapl_pmus->pmu.read		= rapl_pmu_event_read;
+	rapl_pmus->pmu.module		= THIS_MODULE;
 	return 0;
 }
 
@@ -802,29 +804,21 @@ static int __init rapl_pmu_init(void)
 	/*
 	 * Install callbacks. Core will call them for each online cpu.
 	 */
-
-	ret = cpuhp_setup_state(CPUHP_PERF_X86_RAPL_PREP, "PERF_X86_RAPL_PREP",
-				rapl_cpu_prepare, NULL);
-	if (ret)
-		goto out;
-
 	ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_RAPL_ONLINE,
-				"AP_PERF_X86_RAPL_ONLINE",
+				"perf/x86/rapl:online",
 				rapl_cpu_online, rapl_cpu_offline);
 	if (ret)
-		goto out1;
+		goto out;
 
 	ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1);
 	if (ret)
-		goto out2;
+		goto out1;
 
 	rapl_advertise();
 	return 0;
 
-out2:
-	cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
 out1:
-	cpuhp_remove_state(CPUHP_PERF_X86_RAPL_PREP);
+	cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
 out:
 	pr_warn("Initialization failed (%d), disabled\n", ret);
 	cleanup_rapl_pmus();
@@ -835,7 +829,6 @@ module_init(rapl_pmu_init);
 static void __exit intel_rapl_exit(void)
 {
 	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_RAPL_ONLINE);
-	cpuhp_remove_state_nocalls(CPUHP_PERF_X86_RAPL_PREP);
 	perf_pmu_unregister(&rapl_pmus->pmu);
 	cleanup_rapl_pmus();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/uncore.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/uncore.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/uncore.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/uncore.c	2017-02-12 16:03:20.000000000 -0500
@@ -100,7 +100,13 @@ ssize_t uncore_event_show(struct kobject
 
 struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
 {
-	return pmu->boxes[topology_logical_package_id(cpu)];
+	unsigned int pkgid = topology_logical_package_id(cpu);
+
+	/*
+	 * The unsigned check also catches the '-1' return value for non
+	 * existent mappings in the topology map.
+	 */
+	return pkgid < max_packages ? pmu->boxes[pkgid] : NULL;
 }
 
 u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
@@ -733,6 +739,7 @@ static int uncore_pmu_register(struct in
 			.start		= uncore_pmu_event_start,
 			.stop		= uncore_pmu_event_stop,
 			.read		= uncore_pmu_event_read,
+			.module		= THIS_MODULE,
 		};
 	} else {
 		pmu->pmu = *pmu->type->pmu;
@@ -763,30 +770,6 @@ static void uncore_pmu_unregister(struct
 	pmu->registered = false;
 }
 
-static void __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)
-{
-	struct intel_uncore_pmu *pmu = type->pmus;
-	struct intel_uncore_box *box;
-	int i, pkg;
-
-	if (pmu) {
-		pkg = topology_physical_package_id(cpu);
-		for (i = 0; i < type->num_boxes; i++, pmu++) {
-			box = pmu->boxes[pkg];
-			if (box)
-				uncore_box_exit(box);
-		}
-	}
-}
-
-static void uncore_exit_boxes(void *dummy)
-{
-	struct intel_uncore_type **types;
-
-	for (types = uncore_msr_uncores; *types; types++)
-		__uncore_exit_boxes(*types++, smp_processor_id());
-}
-
 static void uncore_free_boxes(struct intel_uncore_pmu *pmu)
 {
 	int pkg;
@@ -1057,86 +1040,6 @@ static void uncore_pci_exit(void)
 	}
 }
 
-static int uncore_cpu_dying(unsigned int cpu)
-{
-	struct intel_uncore_type *type, **types = uncore_msr_uncores;
-	struct intel_uncore_pmu *pmu;
-	struct intel_uncore_box *box;
-	int i, pkg;
-
-	pkg = topology_logical_package_id(cpu);
-	for (; *types; types++) {
-		type = *types;
-		pmu = type->pmus;
-		for (i = 0; i < type->num_boxes; i++, pmu++) {
-			box = pmu->boxes[pkg];
-			if (box && atomic_dec_return(&box->refcnt) == 0)
-				uncore_box_exit(box);
-		}
-	}
-	return 0;
-}
-
-static int first_init;
-
-static int uncore_cpu_starting(unsigned int cpu)
-{
-	struct intel_uncore_type *type, **types = uncore_msr_uncores;
-	struct intel_uncore_pmu *pmu;
-	struct intel_uncore_box *box;
-	int i, pkg, ncpus = 1;
-
-	if (first_init) {
-		/*
-		 * On init we get the number of online cpus in the package
-		 * and set refcount for all of them.
-		 */
-		ncpus = cpumask_weight(topology_core_cpumask(cpu));
-	}
-
-	pkg = topology_logical_package_id(cpu);
-	for (; *types; types++) {
-		type = *types;
-		pmu = type->pmus;
-		for (i = 0; i < type->num_boxes; i++, pmu++) {
-			box = pmu->boxes[pkg];
-			if (!box)
-				continue;
-			/* The first cpu on a package activates the box */
-			if (atomic_add_return(ncpus, &box->refcnt) == ncpus)
-				uncore_box_init(box);
-		}
-	}
-
-	return 0;
-}
-
-static int uncore_cpu_prepare(unsigned int cpu)
-{
-	struct intel_uncore_type *type, **types = uncore_msr_uncores;
-	struct intel_uncore_pmu *pmu;
-	struct intel_uncore_box *box;
-	int i, pkg;
-
-	pkg = topology_logical_package_id(cpu);
-	for (; *types; types++) {
-		type = *types;
-		pmu = type->pmus;
-		for (i = 0; i < type->num_boxes; i++, pmu++) {
-			if (pmu->boxes[pkg])
-				continue;
-			/* First cpu of a package allocates the box */
-			box = uncore_alloc_box(type, cpu_to_node(cpu));
-			if (!box)
-				return -ENOMEM;
-			box->pmu = pmu;
-			box->pkgid = pkg;
-			pmu->boxes[pkg] = box;
-		}
-	}
-	return 0;
-}
-
 static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_cpu,
 				   int new_cpu)
 {
@@ -1176,12 +1079,14 @@ static void uncore_change_context(struct
 
 static int uncore_event_cpu_offline(unsigned int cpu)
 {
-	int target;
+	struct intel_uncore_type *type, **types = uncore_msr_uncores;
+	struct intel_uncore_pmu *pmu;
+	struct intel_uncore_box *box;
+	int i, pkg, target;
 
 	/* Check if exiting cpu is used for collecting uncore events */
 	if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
-		return 0;
-
+		goto unref;
 	/* Find a new cpu to collect uncore events */
 	target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
 
@@ -1193,12 +1098,82 @@ static int uncore_event_cpu_offline(unsi
 
 	uncore_change_context(uncore_msr_uncores, cpu, target);
 	uncore_change_context(uncore_pci_uncores, cpu, target);
+
+unref:
+	/* Clear the references */
+	pkg = topology_logical_package_id(cpu);
+	for (; *types; types++) {
+		type = *types;
+		pmu = type->pmus;
+		for (i = 0; i < type->num_boxes; i++, pmu++) {
+			box = pmu->boxes[pkg];
+			if (box && atomic_dec_return(&box->refcnt) == 0)
+				uncore_box_exit(box);
+		}
+	}
+	return 0;
+}
+
+static int allocate_boxes(struct intel_uncore_type **types,
+			 unsigned int pkg, unsigned int cpu)
+{
+	struct intel_uncore_box *box, *tmp;
+	struct intel_uncore_type *type;
+	struct intel_uncore_pmu *pmu;
+	LIST_HEAD(allocated);
+	int i;
+
+	/* Try to allocate all required boxes */
+	for (; *types; types++) {
+		type = *types;
+		pmu = type->pmus;
+		for (i = 0; i < type->num_boxes; i++, pmu++) {
+			if (pmu->boxes[pkg])
+				continue;
+			box = uncore_alloc_box(type, cpu_to_node(cpu));
+			if (!box)
+				goto cleanup;
+			box->pmu = pmu;
+			box->pkgid = pkg;
+			list_add(&box->active_list, &allocated);
+		}
+	}
+	/* Install them in the pmus */
+	list_for_each_entry_safe(box, tmp, &allocated, active_list) {
+		list_del_init(&box->active_list);
+		box->pmu->boxes[pkg] = box;
+	}
 	return 0;
+
+cleanup:
+	list_for_each_entry_safe(box, tmp, &allocated, active_list) {
+		list_del_init(&box->active_list);
+		kfree(box);
+	}
+	return -ENOMEM;
 }
 
 static int uncore_event_cpu_online(unsigned int cpu)
 {
-	int target;
+	struct intel_uncore_type *type, **types = uncore_msr_uncores;
+	struct intel_uncore_pmu *pmu;
+	struct intel_uncore_box *box;
+	int i, ret, pkg, target;
+
+	pkg = topology_logical_package_id(cpu);
+	ret = allocate_boxes(types, pkg, cpu);
+	if (ret)
+		return ret;
+
+	for (; *types; types++) {
+		type = *types;
+		pmu = type->pmus;
+		for (i = 0; i < type->num_boxes; i++, pmu++) {
+			box = pmu->boxes[pkg];
+			if (!box && atomic_inc_return(&box->refcnt) == 1)
+				uncore_box_init(box);
+		}
+	}
 
 	/*
 	 * Check if there is an online cpu in the package
@@ -1388,38 +1363,16 @@ static int __init intel_uncore_init(void
 	if (cret && pret)
 		return -ENODEV;
 
-	/*
-	 * Install callbacks. Core will call them for each online cpu.
-	 *
-	 * The first online cpu of each package allocates and takes
-	 * the refcounts for all other online cpus in that package.
-	 * If msrs are not enabled no allocation is required and
-	 * uncore_cpu_prepare() is not called for each online cpu.
-	 */
-	if (!cret) {
-	       ret = cpuhp_setup_state(CPUHP_PERF_X86_UNCORE_PREP,
-					"PERF_X86_UNCORE_PREP",
-					uncore_cpu_prepare, NULL);
-		if (ret)
-			goto err;
-	} else {
-		cpuhp_setup_state_nocalls(CPUHP_PERF_X86_UNCORE_PREP,
-					  "PERF_X86_UNCORE_PREP",
-					  uncore_cpu_prepare, NULL);
-	}
-	first_init = 1;
-	cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_STARTING,
-			  "AP_PERF_X86_UNCORE_STARTING",
-			  uncore_cpu_starting, uncore_cpu_dying);
-	first_init = 0;
-	cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE,
-			  "AP_PERF_X86_UNCORE_ONLINE",
-			  uncore_event_cpu_online, uncore_event_cpu_offline);
+	/* Install hotplug callbacks to setup the targets for each package */
+	ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE,
+				"perf/x86/intel/uncore:online",
+				uncore_event_cpu_online,
+				uncore_event_cpu_offline);
+	if (ret)
+		goto err;
 	return 0;
 
 err:
-	/* Undo box->init_box() */
-	on_each_cpu_mask(&uncore_cpu_mask, uncore_exit_boxes, NULL, 1);
 	uncore_types_exit(uncore_msr_uncores);
 	uncore_pci_exit();
 	return ret;
@@ -1428,9 +1381,7 @@ module_init(intel_uncore_init);
 
 static void __exit intel_uncore_exit(void)
 {
-	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_UNCORE_ONLINE);
-	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_UNCORE_STARTING);
-	cpuhp_remove_state_nocalls(CPUHP_PERF_X86_UNCORE_PREP);
+	cpuhp_remove_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE);
 	uncore_types_exit(uncore_msr_uncores);
 	uncore_pci_exit();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/intel/uncore_snbep.c linux-libre-4.10-rc8-gnu/arch/x86/events/intel/uncore_snbep.c
--- linux-libre-4.9-gnu/arch/x86/events/intel/uncore_snbep.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/intel/uncore_snbep.c	2017-02-12 16:03:20.000000000 -0500
@@ -669,7 +669,7 @@ static struct event_constraint snbep_unc
 	UNCORE_EVENT_CONSTRAINT(0x1c, 0xc),
 	UNCORE_EVENT_CONSTRAINT(0x1d, 0xc),
 	UNCORE_EVENT_CONSTRAINT(0x1e, 0xc),
-	EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff),
+	UNCORE_EVENT_CONSTRAINT(0x1f, 0xe),
 	UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
 	UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
 	UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
@@ -2686,7 +2686,7 @@ static struct intel_uncore_type *hswep_m
 
 void hswep_uncore_cpu_init(void)
 {
-	int pkg = topology_phys_to_logical_pkg(0);
+	int pkg = boot_cpu_data.logical_proc_id;
 
 	if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
 		hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/events/perf_event.h linux-libre-4.10-rc8-gnu/arch/x86/events/perf_event.h
--- linux-libre-4.9-gnu/arch/x86/events/perf_event.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/events/perf_event.h	2017-02-12 16:03:20.000000000 -0500
@@ -604,7 +604,7 @@ struct x86_pmu {
 	u64		lbr_sel_mask;		   /* LBR_SELECT valid bits */
 	const int	*lbr_sel_map;		   /* lbr_select mappings */
 	bool		lbr_double_abort;	   /* duplicated lbr aborts */
-	bool		lbr_pt_coexist;		   /* LBR may coexist with PT */
+	bool		lbr_pt_coexist;		   /* (LBR|BTS) may coexist with PT */
 
 	/*
 	 * Intel PT/LBR/BTS are exclusive
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/ia32/ia32_aout.c linux-libre-4.10-rc8-gnu/arch/x86/ia32/ia32_aout.c
--- linux-libre-4.9-gnu/arch/x86/ia32/ia32_aout.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/ia32/ia32_aout.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/jiffies.h>
 #include <linux/perf_event.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/user32.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/ia32/ia32_signal.c linux-libre-4.10-rc8-gnu/arch/x86/ia32/ia32_signal.c
--- linux-libre-4.9-gnu/arch/x86/ia32/ia32_signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/ia32/ia32_signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/compat.h>
 #include <linux/binfmts.h>
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/fpu/internal.h>
 #include <asm/fpu/signal.h>
 #include <asm/ptrace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/ia32/sys_ia32.c linux-libre-4.10-rc8-gnu/arch/x86/ia32/sys_ia32.c
--- linux-libre-4.9-gnu/arch/x86/ia32/sys_ia32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/ia32/sys_ia32.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@
 #include <linux/slab.h>
 #include <asm/mman.h>
 #include <asm/types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
 #include <asm/vgtod.h>
 #include <asm/sys_ia32.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/acpi.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/acpi.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/acpi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/acpi.h	2017-02-12 16:03:20.000000000 -0500
@@ -94,7 +94,7 @@ static inline unsigned int acpi_processo
 	    boot_cpu_data.x86_model <= 0x05 &&
 	    boot_cpu_data.x86_mask < 0x0A)
 		return 1;
-	else if (amd_e400_c1e_detected)
+	else if (boot_cpu_has(X86_BUG_AMD_APIC_C1E))
 		return 1;
 	else
 		return max_cstate;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/amd_nb.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/amd_nb.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/amd_nb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/amd_nb.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,10 @@ extern int amd_numa_init(void);
 extern int amd_get_subcaches(int);
 extern int amd_set_subcaches(int, unsigned long);
 
+extern int amd_smn_read(u16 node, u32 address, u32 *value);
+extern int amd_smn_write(u16 node, u32 address, u32 value);
+extern int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo);
+
 struct amd_l3_cache {
 	unsigned indices;
 	u8	 subcaches[4];
@@ -55,6 +59,7 @@ struct threshold_bank {
 };
 
 struct amd_northbridge {
+	struct pci_dev *root;
 	struct pci_dev *misc;
 	struct pci_dev *link;
 	struct amd_l3_cache l3_cache;
@@ -66,7 +71,6 @@ struct amd_northbridge_info {
 	u64 flags;
 	struct amd_northbridge *nb;
 };
-extern struct amd_northbridge_info amd_northbridges;
 
 #define AMD_NB_GART			BIT(0)
 #define AMD_NB_L3_INDEX_DISABLE		BIT(1)
@@ -74,20 +78,9 @@ extern struct amd_northbridge_info amd_n
 
 #ifdef CONFIG_AMD_NB
 
-static inline u16 amd_nb_num(void)
-{
-	return amd_northbridges.num;
-}
-
-static inline bool amd_nb_has_feature(unsigned feature)
-{
-	return ((amd_northbridges.flags & feature) == feature);
-}
-
-static inline struct amd_northbridge *node_to_amd_nb(int node)
-{
-	return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] : NULL;
-}
+u16 amd_nb_num(void);
+bool amd_nb_has_feature(unsigned int feature);
+struct amd_northbridge *node_to_amd_nb(int node);
 
 static inline u16 amd_pci_dev_to_node_id(struct pci_dev *pdev)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/apic.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/apic.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/apic.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/apic.h	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,6 @@
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
 #include <asm/msr.h>
-#include <asm/idle.h>
 
 #define ARCH_APICTIMER_STOPS_ON_C3	1
 
@@ -196,7 +195,7 @@ static inline void native_apic_msr_write
 
 static inline void native_apic_msr_eoi_write(u32 reg, u32 v)
 {
-	wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
+	wrmsr_notrace(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
 }
 
 static inline u32 native_apic_msr_read(u32 reg)
@@ -332,6 +331,7 @@ struct apic {
 	 * on write for EOI.
 	 */
 	void (*eoi_write)(u32 reg, u32 v);
+	void (*native_eoi_write)(u32 reg, u32 v);
 	u64 (*icr_read)(void);
 	void (*icr_write)(u32 low, u32 high);
 	void (*wait_icr_idle)(void);
@@ -639,7 +639,6 @@ extern void irq_exit(void);
 static inline void entering_irq(void)
 {
 	irq_enter();
-	exit_idle();
 }
 
 static inline void entering_ack_irq(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/asm-prototypes.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/asm-prototypes.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/asm-prototypes.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/asm-prototypes.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,16 @@
+#include <asm/ftrace.h>
+#include <linux/uaccess.h>
+#include <asm/string.h>
+#include <asm/page.h>
+#include <asm/checksum.h>
+
+#include <asm-generic/asm-prototypes.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/special_insns.h>
+#include <asm/preempt.h>
+
+#ifndef CONFIG_X86_CMPXCHG64
+extern void cmpxchg8b_emu(void);
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/bitops.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/bitops.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/bitops.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/bitops.h	2017-02-12 16:03:20.000000000 -0500
@@ -139,6 +139,19 @@ static __always_inline void __clear_bit(
 	asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
 }
 
+static __always_inline bool clear_bit_unlock_is_negative_byte(long nr, volatile unsigned long *addr)
+{
+	bool negative;
+	asm volatile(LOCK_PREFIX "andb %2,%1\n\t"
+		CC_SET(s)
+		: CC_OUT(s) (negative), ADDR
+		: "ir" ((char) ~(1 << nr)) : "memory");
+	return negative;
+}
+
+// Let everybody know we have it
+#define clear_bit_unlock_is_negative_byte clear_bit_unlock_is_negative_byte
+
 /*
  * __clear_bit_unlock - Clears a bit in memory
  * @nr: Bit to clear
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/checksum_64.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/checksum_64.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/checksum_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/checksum_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
  */
 
 #include <linux/compiler.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/byteorder.h>
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/cpufeature.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/cpufeature.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/cpufeature.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/cpufeature.h	2017-02-12 16:03:20.000000000 -0500
@@ -204,6 +204,7 @@ static __always_inline __pure bool _stat
 
 #define static_cpu_has_bug(bit)		static_cpu_has((bit))
 #define boot_cpu_has_bug(bit)		cpu_has_bug(&boot_cpu_data, (bit))
+#define boot_cpu_set_bug(bit)		set_cpu_cap(&boot_cpu_data, (bit))
 
 #define MAX_CPU_FEATURES		(NCAPINTS * 32)
 #define cpu_have_feature		boot_cpu_has
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/cpufeatures.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/cpufeatures.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/cpufeatures.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/cpufeatures.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,8 +104,8 @@
 #define X86_FEATURE_EXTD_APICID	( 3*32+26) /* has extended APICID (8 bits) */
 #define X86_FEATURE_AMD_DCM     ( 3*32+27) /* multi-node processor */
 #define X86_FEATURE_APERFMPERF	( 3*32+28) /* APERFMPERF */
-#define X86_FEATURE_EAGER_FPU	( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
 #define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
+#define X86_FEATURE_TSC_KNOWN_FREQ ( 3*32+31) /* TSC has known frequency */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	( 4*32+ 0) /* "pni" SSE-3 */
@@ -189,10 +189,14 @@
 
 #define X86_FEATURE_CPB		( 7*32+ 2) /* AMD Core Performance Boost */
 #define X86_FEATURE_EPB		( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
+#define X86_FEATURE_CAT_L3	( 7*32+ 4) /* Cache Allocation Technology L3 */
+#define X86_FEATURE_CAT_L2	( 7*32+ 5) /* Cache Allocation Technology L2 */
+#define X86_FEATURE_CDP_L3	( 7*32+ 6) /* Code and Data Prioritization L3 */
 
 #define X86_FEATURE_HW_PSTATE	( 7*32+ 8) /* AMD HW-PState */
 #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
 
+#define X86_FEATURE_INTEL_PPIN	( 7*32+14) /* Intel Processor Inventory Number */
 #define X86_FEATURE_INTEL_PT	( 7*32+15) /* Intel Processor Trace */
 #define X86_FEATURE_AVX512_4VNNIW (7*32+16) /* AVX-512 Neural Network Instructions */
 #define X86_FEATURE_AVX512_4FMAPS (7*32+17) /* AVX-512 Multiply Accumulation Single precision */
@@ -221,11 +225,13 @@
 #define X86_FEATURE_RTM		( 9*32+11) /* Restricted Transactional Memory */
 #define X86_FEATURE_CQM		( 9*32+12) /* Cache QoS Monitoring */
 #define X86_FEATURE_MPX		( 9*32+14) /* Memory Protection Extension */
+#define X86_FEATURE_RDT_A	( 9*32+15) /* Resource Director Technology Allocation */
 #define X86_FEATURE_AVX512F	( 9*32+16) /* AVX-512 Foundation */
 #define X86_FEATURE_AVX512DQ	( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */
 #define X86_FEATURE_RDSEED	( 9*32+18) /* The RDSEED instruction */
 #define X86_FEATURE_ADX		( 9*32+19) /* The ADCX and ADOX instructions */
 #define X86_FEATURE_SMAP	( 9*32+20) /* Supervisor Mode Access Prevention */
+#define X86_FEATURE_AVX512IFMA  ( 9*32+21) /* AVX-512 Integer Fused Multiply-Add instructions */
 #define X86_FEATURE_CLFLUSHOPT	( 9*32+23) /* CLFLUSHOPT instruction */
 #define X86_FEATURE_CLWB	( 9*32+24) /* CLWB instruction */
 #define X86_FEATURE_AVX512PF	( 9*32+26) /* AVX-512 Prefetch */
@@ -279,8 +285,10 @@
 #define X86_FEATURE_AVIC	(15*32+13) /* Virtual Interrupt Controller */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
+#define X86_FEATURE_AVX512VBMI  (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
 #define X86_FEATURE_PKU		(16*32+ 3) /* Protection Keys for Userspace */
 #define X86_FEATURE_OSPKE	(16*32+ 4) /* OS Protection Keys Enable */
+#define X86_FEATURE_RDPID	(16*32+ 22) /* RDPID instruction */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
@@ -311,4 +319,6 @@
 #define X86_BUG_NULL_SEG	X86_BUG(10) /* Nulling a selector preserves the base */
 #define X86_BUG_SWAPGS_FENCE	X86_BUG(11) /* SWAPGS without input dep on GS */
 #define X86_BUG_MONITOR		X86_BUG(12) /* IPI required to wake up remote CPU */
+#define X86_BUG_AMD_E400	X86_BUG(13) /* CPU is among the affected by Erratum 400 */
+
 #endif /* _ASM_X86_CPUFEATURES_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/crypto/glue_helper.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/crypto/glue_helper.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/crypto/glue_helper.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/crypto/glue_helper.h	2017-02-12 16:03:20.000000000 -0500
@@ -5,8 +5,8 @@
 #ifndef _CRYPTO_GLUE_HELPER_H
 #define _CRYPTO_GLUE_HELPER_H
 
+#include <crypto/internal/skcipher.h>
 #include <linux/kernel.h>
-#include <linux/crypto.h>
 #include <asm/fpu/api.h>
 #include <crypto/b128ops.h>
 
@@ -69,6 +69,31 @@ static inline bool glue_fpu_begin(unsign
 	return true;
 }
 
+static inline bool glue_skwalk_fpu_begin(unsigned int bsize,
+					 int fpu_blocks_limit,
+					 struct skcipher_walk *walk,
+					 bool fpu_enabled, unsigned int nbytes)
+{
+	if (likely(fpu_blocks_limit < 0))
+		return false;
+
+	if (fpu_enabled)
+		return true;
+
+	/*
+	 * Vector-registers are only used when chunk to be processed is large
+	 * enough, so do not enable FPU until it is necessary.
+	 */
+	if (nbytes < bsize * (unsigned int)fpu_blocks_limit)
+		return false;
+
+	/* prevent sleeping if FPU is in use */
+	skcipher_walk_atomise(walk);
+
+	kernel_fpu_begin();
+	return true;
+}
+
 static inline void glue_fpu_end(bool fpu_enabled)
 {
 	if (fpu_enabled)
@@ -139,6 +164,18 @@ extern int glue_xts_crypt_128bit(const s
 				 common_glue_func_t tweak_fn, void *tweak_ctx,
 				 void *crypt_ctx);
 
+extern int glue_xts_crypt_128bit(const struct common_glue_ctx *gctx,
+				 struct blkcipher_desc *desc,
+				 struct scatterlist *dst,
+				 struct scatterlist *src, unsigned int nbytes,
+				 common_glue_func_t tweak_fn, void *tweak_ctx,
+				 void *crypt_ctx);
+
+extern int glue_xts_req_128bit(const struct common_glue_ctx *gctx,
+			       struct skcipher_request *req,
+			       common_glue_func_t tweak_fn, void *tweak_ctx,
+			       void *crypt_ctx);
+
 extern void glue_xts_crypt_128bit_one(void *ctx, u128 *dst, const u128 *src,
 				      le128 *iv, common_glue_func_t fn);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/e820.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/e820.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/e820.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/e820.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,13 +1,17 @@
 #ifndef _ASM_X86_E820_H
 #define _ASM_X86_E820_H
 
-#ifdef CONFIG_EFI
+/*
+ * E820_X_MAX is the maximum size of the extended E820 table.  The extended
+ * table may contain up to 3 extra E820 entries per possible NUMA node, so we
+ * make room for 3 * MAX_NUMNODES possible entries, beyond the standard 128.
+ * Also note that E820_X_MAX *must* be defined before we include uapi/asm/e820.h.
+ */
 #include <linux/numa.h>
 #define E820_X_MAX (E820MAX + 3 * MAX_NUMNODES)
-#else	/* ! CONFIG_EFI */
-#define E820_X_MAX E820MAX
-#endif
+
 #include <uapi/asm/e820.h>
+
 #ifndef __ASSEMBLY__
 /* see comment in arch/x86/kernel/e820.c */
 extern struct e820map *e820;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/efi.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/efi.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/efi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/efi.h	2017-02-12 16:03:20.000000000 -0500
@@ -210,12 +210,18 @@ static inline bool efi_is_64bit(void)
 	return __efi_early()->is64;
 }
 
+#define efi_table_attr(table, attr, instance)				\
+	(efi_is_64bit() ?						\
+		((table##_64_t *)(unsigned long)instance)->attr :	\
+		((table##_32_t *)(unsigned long)instance)->attr)
+
+#define efi_call_proto(protocol, f, instance, ...)			\
+	__efi_early()->call(efi_table_attr(protocol, f, instance),	\
+		instance, ##__VA_ARGS__)
+
 #define efi_call_early(f, ...)						\
-	__efi_early()->call(efi_is_64bit() ?				\
-		((efi_boot_services_64_t *)(unsigned long)		\
-			__efi_early()->boot_services)->f :		\
-		((efi_boot_services_32_t *)(unsigned long)		\
-			__efi_early()->boot_services)->f, __VA_ARGS__)
+	__efi_early()->call(efi_table_attr(efi_boot_services, f,	\
+		__efi_early()->boot_services), __VA_ARGS__)
 
 #define __efi_call_early(f, ...)					\
 	__efi_early()->call((unsigned long)f, __VA_ARGS__);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/floppy.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/floppy.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/floppy.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/floppy.h	2017-02-12 16:03:20.000000000 -0500
@@ -229,18 +229,18 @@ static struct fd_routine_l {
 	int (*_dma_setup)(char *addr, unsigned long size, int mode, int io);
 } fd_routine[] = {
 	{
-		request_dma,
-		free_dma,
-		get_dma_residue,
-		dma_mem_alloc,
-		hard_dma_setup
+		._request_dma		= request_dma,
+		._free_dma		= free_dma,
+		._get_dma_residue	= get_dma_residue,
+		._dma_mem_alloc		= dma_mem_alloc,
+		._dma_setup		= hard_dma_setup
 	},
 	{
-		vdma_request_dma,
-		vdma_nop,
-		vdma_get_dma_residue,
-		vdma_mem_alloc,
-		vdma_dma_setup
+		._request_dma		= vdma_request_dma,
+		._free_dma		= vdma_nop,
+		._get_dma_residue	= vdma_get_dma_residue,
+		._dma_mem_alloc		= vdma_mem_alloc,
+		._dma_setup		= vdma_dma_setup
 	}
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/fpu/api.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/api.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/fpu/api.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/api.h	2017-02-12 16:03:20.000000000 -0500
@@ -27,16 +27,6 @@ extern void kernel_fpu_end(void);
 extern bool irq_fpu_usable(void);
 
 /*
- * Some instructions like VIA's padlock instructions generate a spurious
- * DNA fault but don't modify SSE registers. And these instructions
- * get used from interrupt context as well. To prevent these kernel instructions
- * in interrupt context interacting wrongly with other user/kernel fpu usage, we
- * should use them only in the context of irq_ts_save/restore()
- */
-extern int  irq_ts_save(void);
-extern void irq_ts_restore(int TS_state);
-
-/*
  * Query the presence of one or more xfeatures. Works on any legacy CPU as well.
  *
  * If 'feature_name' is set then put a human-readable description of
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/fpu/internal.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/internal.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/fpu/internal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/internal.h	2017-02-12 16:03:20.000000000 -0500
@@ -60,11 +60,6 @@ extern u64 fpu__get_supported_xfeatures_
 /*
  * FPU related CPU feature flag helper routines:
  */
-static __always_inline __pure bool use_eager_fpu(void)
-{
-	return static_cpu_has(X86_FEATURE_EAGER_FPU);
-}
-
 static __always_inline __pure bool use_xsaveopt(void)
 {
 	return static_cpu_has(X86_FEATURE_XSAVEOPT);
@@ -484,42 +479,42 @@ extern int copy_fpstate_to_sigframe(void
 DECLARE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);
 
 /*
- * Must be run with preemption disabled: this clears the fpu_fpregs_owner_ctx,
- * on this CPU.
+ * The in-register FPU state for an FPU context on a CPU is assumed to be
+ * valid if the fpu->last_cpu matches the CPU, and the fpu_fpregs_owner_ctx
+ * matches the FPU.
  *
- * This will disable any lazy FPU state restore of the current FPU state,
- * but if the current thread owns the FPU, it will still be saved by.
+ * If the FPU register state is valid, the kernel can skip restoring the
+ * FPU state from memory.
+ *
+ * Any code that clobbers the FPU registers or updates the in-memory
+ * FPU state for a task MUST let the rest of the kernel know that the
+ * FPU registers are no longer valid for this task.
+ *
+ * Either one of these invalidation functions is enough. Invalidate
+ * a resource you control: CPU if using the CPU for something else
+ * (with preemption disabled), FPU for the current task, or a task that
+ * is prevented from running by the current task.
  */
-static inline void __cpu_disable_lazy_restore(unsigned int cpu)
-{
-	per_cpu(fpu_fpregs_owner_ctx, cpu) = NULL;
-}
-
-static inline int fpu_want_lazy_restore(struct fpu *fpu, unsigned int cpu)
+static inline void __cpu_invalidate_fpregs_state(void)
 {
-	return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
+	__this_cpu_write(fpu_fpregs_owner_ctx, NULL);
 }
 
-
-/*
- * Wrap lazy FPU TS handling in a 'hw fpregs activation/deactivation'
- * idiom, which is then paired with the sw-flag (fpregs_active) later on:
- */
-
-static inline void __fpregs_activate_hw(void)
+static inline void __fpu_invalidate_fpregs_state(struct fpu *fpu)
 {
-	if (!use_eager_fpu())
-		clts();
+	fpu->last_cpu = -1;
 }
 
-static inline void __fpregs_deactivate_hw(void)
+static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu)
 {
-	if (!use_eager_fpu())
-		stts();
+	return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
 }
 
-/* Must be paired with an 'stts' (fpregs_deactivate_hw()) after! */
-static inline void __fpregs_deactivate(struct fpu *fpu)
+/*
+ * These generally need preemption protection to work,
+ * do try to avoid using these on their own:
+ */
+static inline void fpregs_deactivate(struct fpu *fpu)
 {
 	WARN_ON_FPU(!fpu->fpregs_active);
 
@@ -528,8 +523,7 @@ static inline void __fpregs_deactivate(s
 	trace_x86_fpu_regs_deactivated(fpu);
 }
 
-/* Must be paired with a 'clts' (fpregs_activate_hw()) before! */
-static inline void __fpregs_activate(struct fpu *fpu)
+static inline void fpregs_activate(struct fpu *fpu)
 {
 	WARN_ON_FPU(fpu->fpregs_active);
 
@@ -554,51 +548,19 @@ static inline int fpregs_active(void)
 }
 
 /*
- * Encapsulate the CR0.TS handling together with the
- * software flag.
- *
- * These generally need preemption protection to work,
- * do try to avoid using these on their own.
- */
-static inline void fpregs_activate(struct fpu *fpu)
-{
-	__fpregs_activate_hw();
-	__fpregs_activate(fpu);
-}
-
-static inline void fpregs_deactivate(struct fpu *fpu)
-{
-	__fpregs_deactivate(fpu);
-	__fpregs_deactivate_hw();
-}
-
-/*
  * FPU state switching for scheduling.
  *
  * This is a two-stage process:
  *
- *  - switch_fpu_prepare() saves the old state and
- *    sets the new state of the CR0.TS bit. This is
- *    done within the context of the old process.
+ *  - switch_fpu_prepare() saves the old state.
+ *    This is done within the context of the old process.
  *
  *  - switch_fpu_finish() restores the new state as
  *    necessary.
  */
-typedef struct { int preload; } fpu_switch_t;
-
-static inline fpu_switch_t
-switch_fpu_prepare(struct fpu *old_fpu, struct fpu *new_fpu, int cpu)
+static inline void
+switch_fpu_prepare(struct fpu *old_fpu, int cpu)
 {
-	fpu_switch_t fpu;
-
-	/*
-	 * If the task has used the math, pre-load the FPU on xsave processors
-	 * or if the past 5 consecutive context-switches used math.
-	 */
-	fpu.preload = static_cpu_has(X86_FEATURE_FPU) &&
-		      new_fpu->fpstate_active &&
-		      (use_eager_fpu() || new_fpu->counter > 5);
-
 	if (old_fpu->fpregs_active) {
 		if (!copy_fpregs_to_fpstate(old_fpu))
 			old_fpu->last_cpu = -1;
@@ -608,29 +570,8 @@ switch_fpu_prepare(struct fpu *old_fpu,
 		/* But leave fpu_fpregs_owner_ctx! */
 		old_fpu->fpregs_active = 0;
 		trace_x86_fpu_regs_deactivated(old_fpu);
-
-		/* Don't change CR0.TS if we just switch! */
-		if (fpu.preload) {
-			new_fpu->counter++;
-			__fpregs_activate(new_fpu);
-			trace_x86_fpu_regs_activated(new_fpu);
-			prefetch(&new_fpu->state);
-		} else {
-			__fpregs_deactivate_hw();
-		}
-	} else {
-		old_fpu->counter = 0;
+	} else
 		old_fpu->last_cpu = -1;
-		if (fpu.preload) {
-			new_fpu->counter++;
-			if (fpu_want_lazy_restore(new_fpu, cpu))
-				fpu.preload = 0;
-			else
-				prefetch(&new_fpu->state);
-			fpregs_activate(new_fpu);
-		}
-	}
-	return fpu;
 }
 
 /*
@@ -638,15 +579,19 @@ switch_fpu_prepare(struct fpu *old_fpu,
  */
 
 /*
- * By the time this gets called, we've already cleared CR0.TS and
- * given the process the FPU if we are going to preload the FPU
- * state - all we need to do is to conditionally restore the register
- * state itself.
+ * Set up the userspace FPU context for the new task, if the task
+ * has used the FPU.
  */
-static inline void switch_fpu_finish(struct fpu *new_fpu, fpu_switch_t fpu_switch)
+static inline void switch_fpu_finish(struct fpu *new_fpu, int cpu)
 {
-	if (fpu_switch.preload)
-		copy_kernel_to_fpregs(&new_fpu->state);
+	bool preload = static_cpu_has(X86_FEATURE_FPU) &&
+		       new_fpu->fpstate_active;
+
+	if (preload) {
+		if (!fpregs_state_valid(new_fpu, cpu))
+			copy_kernel_to_fpregs(&new_fpu->state);
+		fpregs_activate(new_fpu);
+	}
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/fpu/types.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/types.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/fpu/types.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/types.h	2017-02-12 16:03:20.000000000 -0500
@@ -322,17 +322,6 @@ struct fpu {
 	unsigned char			fpregs_active;
 
 	/*
-	 * @counter:
-	 *
-	 * This counter contains the number of consecutive context switches
-	 * during which the FPU stays used. If this is over a threshold, the
-	 * lazy FPU restore logic becomes eager, to save the trap overhead.
-	 * This is an unsigned char so that after 256 iterations the counter
-	 * wraps and the context switch behavior turns lazy again; this is to
-	 * deal with bursty apps that only use the FPU for a short time:
-	 */
-	unsigned char			counter;
-	/*
 	 * @state:
 	 *
 	 * In-memory copy of all FPU registers that we save/restore
@@ -340,29 +329,6 @@ struct fpu {
 	 * the registers in the FPU are more recent than this state
 	 * copy. If the task context-switches away then they get
 	 * saved here and represent the FPU state.
-	 *
-	 * After context switches there may be a (short) time period
-	 * during which the in-FPU hardware registers are unchanged
-	 * and still perfectly match this state, if the tasks
-	 * scheduled afterwards are not using the FPU.
-	 *
-	 * This is the 'lazy restore' window of optimization, which
-	 * we track though 'fpu_fpregs_owner_ctx' and 'fpu->last_cpu'.
-	 *
-	 * We detect whether a subsequent task uses the FPU via setting
-	 * CR0::TS to 1, which causes any FPU use to raise a #NM fault.
-	 *
-	 * During this window, if the task gets scheduled again, we
-	 * might be able to skip having to do a restore from this
-	 * memory buffer to the hardware registers - at the cost of
-	 * incurring the overhead of #NM fault traps.
-	 *
-	 * Note that on modern CPUs that support the XSAVEOPT (or other
-	 * optimized XSAVE instructions), we don't use #NM traps anymore,
-	 * as the hardware can track whether FPU registers need saving
-	 * or not. On such CPUs we activate the non-lazy ('eagerfpu')
-	 * logic, which unconditionally saves/restores all FPU state
-	 * across context switches. (if FPU state exists.)
 	 */
 	union fpregs_state		state;
 	/*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/fpu/xstate.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/xstate.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/fpu/xstate.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/fpu/xstate.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,21 +21,16 @@
 /* Supervisor features */
 #define XFEATURE_MASK_SUPERVISOR (XFEATURE_MASK_PT)
 
-/* Supported features which support lazy state saving */
-#define XFEATURE_MASK_LAZY	(XFEATURE_MASK_FP | \
+/* All currently supported features */
+#define XCNTXT_MASK		(XFEATURE_MASK_FP | \
 				 XFEATURE_MASK_SSE | \
 				 XFEATURE_MASK_YMM | \
 				 XFEATURE_MASK_OPMASK | \
 				 XFEATURE_MASK_ZMM_Hi256 | \
-				 XFEATURE_MASK_Hi16_ZMM)
-
-/* Supported features which require eager state saving */
-#define XFEATURE_MASK_EAGER	(XFEATURE_MASK_BNDREGS | \
-				 XFEATURE_MASK_BNDCSR | \
-				 XFEATURE_MASK_PKRU)
-
-/* All currently supported features */
-#define XCNTXT_MASK	(XFEATURE_MASK_LAZY | XFEATURE_MASK_EAGER)
+				 XFEATURE_MASK_Hi16_ZMM	 | \
+				 XFEATURE_MASK_PKRU | \
+				 XFEATURE_MASK_BNDREGS | \
+				 XFEATURE_MASK_BNDCSR)
 
 #ifdef CONFIG_X86_64
 #define REX_PREFIX	"0x48, "
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/idle.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/idle.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/idle.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/idle.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-#ifndef _ASM_X86_IDLE_H
-#define _ASM_X86_IDLE_H
-
-#define IDLE_START 1
-#define IDLE_END 2
-
-struct notifier_block;
-void idle_notifier_register(struct notifier_block *n);
-void idle_notifier_unregister(struct notifier_block *n);
-
-#ifdef CONFIG_X86_64
-void enter_idle(void);
-void exit_idle(void);
-#else /* !CONFIG_X86_64 */
-static inline void enter_idle(void) { }
-static inline void exit_idle(void) { }
-static inline void __exit_idle(void) { }
-#endif /* CONFIG_X86_64 */
-
-void amd_e400_remove_cpu(int cpu);
-
-#endif /* _ASM_X86_IDLE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/intel-family.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/intel-family.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/intel-family.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/intel-family.h	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@
 #define INTEL_FAM6_ATOM_SILVERMONT2	0x4D /* Avaton/Rangely */
 #define INTEL_FAM6_ATOM_AIRMONT		0x4C /* CherryTrail / Braswell */
 #define INTEL_FAM6_ATOM_MERRIFIELD	0x4A /* Tangier */
-#define INTEL_FAM6_ATOM_MOOREFIELD	0x5A /* Annidale */
+#define INTEL_FAM6_ATOM_MOOREFIELD	0x5A /* Anniedale */
 #define INTEL_FAM6_ATOM_GOLDMONT	0x5C
 #define INTEL_FAM6_ATOM_DENVERTON	0x5F /* Goldmont Microserver */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/intel_rdt_common.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/intel_rdt_common.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/intel_rdt_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/intel_rdt_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,27 @@
+#ifndef _ASM_X86_INTEL_RDT_COMMON_H
+#define _ASM_X86_INTEL_RDT_COMMON_H
+
+#define MSR_IA32_PQR_ASSOC	0x0c8f
+
+/**
+ * struct intel_pqr_state - State cache for the PQR MSR
+ * @rmid:		The cached Resource Monitoring ID
+ * @closid:		The cached Class Of Service ID
+ * @rmid_usecnt:	The usage counter for rmid
+ *
+ * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
+ * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
+ * contains both parts, so we need to cache them.
+ *
+ * The cache also helps to avoid pointless updates if the value does
+ * not change.
+ */
+struct intel_pqr_state {
+	u32			rmid;
+	u32			closid;
+	int			rmid_usecnt;
+};
+
+DECLARE_PER_CPU(struct intel_pqr_state, pqr_state);
+
+#endif /* _ASM_X86_INTEL_RDT_COMMON_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/intel_rdt.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/intel_rdt.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/intel_rdt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/intel_rdt.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,224 @@
+#ifndef _ASM_X86_INTEL_RDT_H
+#define _ASM_X86_INTEL_RDT_H
+
+#ifdef CONFIG_INTEL_RDT_A
+
+#include <linux/kernfs.h>
+#include <linux/jump_label.h>
+
+#include <asm/intel_rdt_common.h>
+
+#define IA32_L3_QOS_CFG		0xc81
+#define IA32_L3_CBM_BASE	0xc90
+#define IA32_L2_CBM_BASE	0xd10
+
+#define L3_QOS_CDP_ENABLE	0x01ULL
+
+/**
+ * struct rdtgroup - store rdtgroup's data in resctrl file system.
+ * @kn:				kernfs node
+ * @rdtgroup_list:		linked list for all rdtgroups
+ * @closid:			closid for this rdtgroup
+ * @cpu_mask:			CPUs assigned to this rdtgroup
+ * @flags:			status bits
+ * @waitcount:			how many cpus expect to find this
+ *				group when they acquire rdtgroup_mutex
+ */
+struct rdtgroup {
+	struct kernfs_node	*kn;
+	struct list_head	rdtgroup_list;
+	int			closid;
+	struct cpumask		cpu_mask;
+	int			flags;
+	atomic_t		waitcount;
+};
+
+/* rdtgroup.flags */
+#define	RDT_DELETED		1
+
+/* List of all resource groups */
+extern struct list_head rdt_all_groups;
+
+int __init rdtgroup_init(void);
+
+/**
+ * struct rftype - describe each file in the resctrl file system
+ * @name: file name
+ * @mode: access mode
+ * @kf_ops: operations
+ * @seq_show: show content of the file
+ * @write: write to the file
+ */
+struct rftype {
+	char			*name;
+	umode_t			mode;
+	struct kernfs_ops	*kf_ops;
+
+	int (*seq_show)(struct kernfs_open_file *of,
+			struct seq_file *sf, void *v);
+	/*
+	 * write() is the generic write callback which maps directly to
+	 * kernfs write operation and overrides all other operations.
+	 * Maximum write size is determined by ->max_write_len.
+	 */
+	ssize_t (*write)(struct kernfs_open_file *of,
+			 char *buf, size_t nbytes, loff_t off);
+};
+
+/**
+ * struct rdt_resource - attributes of an RDT resource
+ * @enabled:			Is this feature enabled on this machine
+ * @capable:			Is this feature available on this machine
+ * @name:			Name to use in "schemata" file
+ * @num_closid:			Number of CLOSIDs available
+ * @max_cbm:			Largest Cache Bit Mask allowed
+ * @min_cbm_bits:		Minimum number of consecutive bits to be set
+ *				in a cache bit mask
+ * @domains:			All domains for this resource
+ * @num_domains:		Number of domains active
+ * @msr_base:			Base MSR address for CBMs
+ * @tmp_cbms:			Scratch space when updating schemata
+ * @num_tmp_cbms:		Number of CBMs in tmp_cbms
+ * @cache_level:		Which cache level defines scope of this domain
+ * @cbm_idx_multi:		Multiplier of CBM index
+ * @cbm_idx_offset:		Offset of CBM index. CBM index is computed by:
+ *				closid * cbm_idx_multi + cbm_idx_offset
+ */
+struct rdt_resource {
+	bool			enabled;
+	bool			capable;
+	char			*name;
+	int			num_closid;
+	int			cbm_len;
+	int			min_cbm_bits;
+	u32			max_cbm;
+	struct list_head	domains;
+	int			num_domains;
+	int			msr_base;
+	u32			*tmp_cbms;
+	int			num_tmp_cbms;
+	int			cache_level;
+	int			cbm_idx_multi;
+	int			cbm_idx_offset;
+};
+
+/**
+ * struct rdt_domain - group of cpus sharing an RDT resource
+ * @list:	all instances of this resource
+ * @id:		unique id for this instance
+ * @cpu_mask:	which cpus share this resource
+ * @cbm:	array of cache bit masks (indexed by CLOSID)
+ */
+struct rdt_domain {
+	struct list_head	list;
+	int			id;
+	struct cpumask		cpu_mask;
+	u32			*cbm;
+};
+
+/**
+ * struct msr_param - set a range of MSRs from a domain
+ * @res:       The resource to use
+ * @low:       Beginning index from base MSR
+ * @high:      End index
+ */
+struct msr_param {
+	struct rdt_resource	*res;
+	int			low;
+	int			high;
+};
+
+extern struct mutex rdtgroup_mutex;
+
+extern struct rdt_resource rdt_resources_all[];
+extern struct rdtgroup rdtgroup_default;
+DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+
+int __init rdtgroup_init(void);
+
+enum {
+	RDT_RESOURCE_L3,
+	RDT_RESOURCE_L3DATA,
+	RDT_RESOURCE_L3CODE,
+	RDT_RESOURCE_L2,
+
+	/* Must be the last */
+	RDT_NUM_RESOURCES,
+};
+
+#define for_each_capable_rdt_resource(r)				      \
+	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
+	     r++) 							      \
+		if (r->capable)
+
+#define for_each_enabled_rdt_resource(r)				      \
+	for (r = rdt_resources_all; r < rdt_resources_all + RDT_NUM_RESOURCES;\
+	     r++)							      \
+		if (r->enabled)
+
+/* CPUID.(EAX=10H, ECX=ResID=1).EAX */
+union cpuid_0x10_1_eax {
+	struct {
+		unsigned int cbm_len:5;
+	} split;
+	unsigned int full;
+};
+
+/* CPUID.(EAX=10H, ECX=ResID=1).EDX */
+union cpuid_0x10_1_edx {
+	struct {
+		unsigned int cos_max:16;
+	} split;
+	unsigned int full;
+};
+
+DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid);
+
+void rdt_cbm_update(void *arg);
+struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn);
+void rdtgroup_kn_unlock(struct kernfs_node *kn);
+ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
+				char *buf, size_t nbytes, loff_t off);
+int rdtgroup_schemata_show(struct kernfs_open_file *of,
+			   struct seq_file *s, void *v);
+
+/*
+ * intel_rdt_sched_in() - Writes the task's CLOSid to IA32_PQR_MSR
+ *
+ * Following considerations are made so that this has minimal impact
+ * on scheduler hot path:
+ * - This will stay as no-op unless we are running on an Intel SKU
+ *   which supports resource control and we enable by mounting the
+ *   resctrl file system.
+ * - Caches the per cpu CLOSid values and does the MSR write only
+ *   when a task with a different CLOSid is scheduled in.
+ *
+ * Must be called with preemption disabled.
+ */
+static inline void intel_rdt_sched_in(void)
+{
+	if (static_branch_likely(&rdt_enable_key)) {
+		struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
+		int closid;
+
+		/*
+		 * If this task has a closid assigned, use it.
+		 * Else use the closid assigned to this cpu.
+		 */
+		closid = current->closid;
+		if (closid == 0)
+			closid = this_cpu_read(cpu_closid);
+
+		if (closid != state->closid) {
+			state->closid = closid;
+			wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, closid);
+		}
+	}
+}
+
+#else
+
+static inline void intel_rdt_sched_in(void) {}
+
+#endif /* CONFIG_INTEL_RDT_A */
+#endif /* _ASM_X86_INTEL_RDT_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/x86/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/x86/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -6,10 +6,6 @@ generated-y += unistd_32_ia32.h
 generated-y += unistd_64_x32.h
 generated-y += xen-hypercalls.h
 
-genhdr-y += unistd_32.h
-genhdr-y += unistd_64.h
-genhdr-y += unistd_x32.h
-
 generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += dma-contiguous.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/kdebug.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/kdebug.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/kdebug.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/kdebug.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,6 @@ enum die_val {
 	DIE_NMIUNKNOWN,
 };
 
-extern void printk_address(unsigned long address);
 extern void die(const char *, struct pt_regs *,long);
 extern int __must_check __die(const char *, struct pt_regs *, long);
 extern void show_stack_regs(struct pt_regs *regs);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/kvm_host.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/kvm_host.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/kvm_host.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/kvm_host.h	2017-02-12 16:03:20.000000000 -0500
@@ -191,6 +191,8 @@ enum {
 #define PFERR_RSVD_BIT 3
 #define PFERR_FETCH_BIT 4
 #define PFERR_PK_BIT 5
+#define PFERR_GUEST_FINAL_BIT 32
+#define PFERR_GUEST_PAGE_BIT 33
 
 #define PFERR_PRESENT_MASK (1U << PFERR_PRESENT_BIT)
 #define PFERR_WRITE_MASK (1U << PFERR_WRITE_BIT)
@@ -198,6 +200,13 @@ enum {
 #define PFERR_RSVD_MASK (1U << PFERR_RSVD_BIT)
 #define PFERR_FETCH_MASK (1U << PFERR_FETCH_BIT)
 #define PFERR_PK_MASK (1U << PFERR_PK_BIT)
+#define PFERR_GUEST_FINAL_MASK (1ULL << PFERR_GUEST_FINAL_BIT)
+#define PFERR_GUEST_PAGE_MASK (1ULL << PFERR_GUEST_PAGE_BIT)
+
+#define PFERR_NESTED_GUEST_PAGE (PFERR_GUEST_PAGE_MASK |	\
+				 PFERR_USER_MASK |		\
+				 PFERR_WRITE_MASK |		\
+				 PFERR_PRESENT_MASK)
 
 /* apic attention bits */
 #define KVM_APIC_CHECK_VAPIC	0
@@ -695,6 +704,7 @@ struct kvm_apic_map {
 
 /* Hyper-V emulation context */
 struct kvm_hv {
+	struct mutex hv_lock;
 	u64 hv_guest_os_id;
 	u64 hv_hypercall;
 	u64 hv_tsc_page;
@@ -758,7 +768,7 @@ struct kvm_arch {
 	spinlock_t pvclock_gtod_sync_lock;
 	bool use_master_clock;
 	u64 master_kernel_ns;
-	cycle_t master_cycle_now;
+	u64 master_cycle_now;
 	struct delayed_work kvmclock_update_work;
 	struct delayed_work kvmclock_sync_work;
 
@@ -1062,6 +1072,7 @@ unsigned int kvm_mmu_calculate_mmu_pages
 void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages);
 
 int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3);
+bool pdptrs_changed(struct kvm_vcpu *vcpu);
 
 int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa,
 			  const void *val, int bytes);
@@ -1124,7 +1135,8 @@ int kvm_set_msr(struct kvm_vcpu *vcpu, s
 struct x86_emulate_ctxt;
 
 int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port);
-void kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
+int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, unsigned short port);
+int kvm_emulate_cpuid(struct kvm_vcpu *vcpu);
 int kvm_emulate_halt(struct kvm_vcpu *vcpu);
 int kvm_vcpu_halt(struct kvm_vcpu *vcpu);
 int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu);
@@ -1203,7 +1215,7 @@ void kvm_vcpu_deactivate_apicv(struct kv
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code,
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u64 error_code,
 		       void *insn, int insn_len);
 void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
 void kvm_mmu_new_cr3(struct kvm_vcpu *vcpu);
@@ -1358,7 +1370,8 @@ void kvm_arch_async_page_ready(struct kv
 bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu);
 extern bool kvm_find_async_pf_gfn(struct kvm_vcpu *vcpu, gfn_t gfn);
 
-void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
+int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu);
+int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err);
 
 int kvm_is_in_guest(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/kvm_page_track.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/kvm_page_track.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/kvm_page_track.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/kvm_page_track.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,9 +29,20 @@ struct kvm_page_track_notifier_node {
 	 * @gpa: the physical address written by guest.
 	 * @new: the data was written to the address.
 	 * @bytes: the written length.
+	 * @node: this node
 	 */
 	void (*track_write)(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
-			    int bytes);
+			    int bytes, struct kvm_page_track_notifier_node *node);
+	/*
+	 * It is called when memory slot is being moved or removed
+	 * users can drop write-protection for the pages in that memory slot
+	 *
+	 * @kvm: the kvm where memory slot being moved or removed
+	 * @slot: the memory slot being moved or removed
+	 * @node: this node
+	 */
+	void (*track_flush_slot)(struct kvm *kvm, struct kvm_memory_slot *slot,
+			    struct kvm_page_track_notifier_node *node);
 };
 
 void kvm_page_track_init(struct kvm *kvm);
@@ -58,4 +69,5 @@ kvm_page_track_unregister_notifier(struc
 				   struct kvm_page_track_notifier_node *n);
 void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
 			  int bytes);
+void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/lguest_hcall.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/lguest_hcall.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/lguest_hcall.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/lguest_hcall.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,6 @@
 #define LHCALL_FLUSH_TLB	5
 #define LHCALL_LOAD_IDT_ENTRY	6
 #define LHCALL_SET_STACK	7
-#define LHCALL_TS		8
 #define LHCALL_SET_CLOCKEVENT	9
 #define LHCALL_HALT		10
 #define LHCALL_SET_PMD		13
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/mce.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mce.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/mce.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mce.h	2017-02-12 16:03:20.000000000 -0500
@@ -252,8 +252,10 @@ static inline void cmci_recheck(void) {}
 
 #ifdef CONFIG_X86_MCE_AMD
 void mce_amd_feature_init(struct cpuinfo_x86 *c);
+int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr);
 #else
 static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
+static inline int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr) { return -EINVAL; };
 #endif
 
 int mce_available(struct cpuinfo_x86 *c);
@@ -293,9 +295,7 @@ void do_machine_check(struct pt_regs *,
 /*
  * Threshold handler
  */
-
 extern void (*mce_threshold_vector)(void);
-extern void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
 
 /* Deferred error interrupt handler */
 extern void (*deferred_error_int_vector)(void);
@@ -356,27 +356,31 @@ enum smca_bank_types {
 	N_SMCA_BANK_TYPES
 };
 
-struct smca_bank_name {
-	const char *name;	/* Short name for sysfs */
-	const char *long_name;	/* Long name for pretty-printing */
-};
-
-extern struct smca_bank_name smca_bank_names[N_SMCA_BANK_TYPES];
-
-#define HWID_MCATYPE(hwid, mcatype) ((hwid << 16) | mcatype)
+#define HWID_MCATYPE(hwid, mcatype) (((hwid) << 16) | (mcatype))
 
-struct smca_hwid_mcatype {
+struct smca_hwid {
 	unsigned int bank_type;	/* Use with smca_bank_types for easy indexing. */
 	u32 hwid_mcatype;	/* (hwid,mcatype) tuple */
 	u32 xec_bitmap;		/* Bitmap of valid ExtErrorCodes; current max is 21. */
 };
 
-struct smca_bank_info {
-	struct smca_hwid_mcatype *type;
-	u32 type_instance;
+struct smca_bank {
+	struct smca_hwid *hwid;
+	/* Instance ID */
+	u32 id;
 };
 
-extern struct smca_bank_info smca_banks[MAX_NR_BANKS];
+extern struct smca_bank smca_banks[MAX_NR_BANKS];
+
+extern const char *smca_get_long_name(enum smca_bank_types t);
+
+extern int mce_threshold_create_device(unsigned int cpu);
+extern int mce_threshold_remove_device(unsigned int cpu);
+
+#else
+
+static inline int mce_threshold_create_device(unsigned int cpu) { return 0; };
+static inline int mce_threshold_remove_device(unsigned int cpu) { return 0; };
 
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/microcode_amd.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/microcode_amd.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/microcode_amd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/microcode_amd.h	2017-02-12 16:03:20.000000000 -0500
@@ -40,38 +40,18 @@ struct microcode_amd {
 	unsigned int			mpb[0];
 };
 
-static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
-				unsigned int sig)
-{
-	int i = 0;
-
-	if (!equiv_cpu_table)
-		return 0;
-
-	while (equiv_cpu_table[i].installed_cpu != 0) {
-		if (sig == equiv_cpu_table[i].installed_cpu)
-			return equiv_cpu_table[i].equiv_cpu;
-
-		i++;
-	}
-	return 0;
-}
-
-extern int __apply_microcode_amd(struct microcode_amd *mc_amd);
-extern int apply_microcode_amd(int cpu);
-extern enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);
-
 #define PATCH_MAX_SIZE PAGE_SIZE
 
 #ifdef CONFIG_MICROCODE_AMD
 extern void __init load_ucode_amd_bsp(unsigned int family);
-extern void load_ucode_amd_ap(void);
-extern int __init save_microcode_in_initrd_amd(void);
+extern void load_ucode_amd_ap(unsigned int family);
+extern int __init save_microcode_in_initrd_amd(unsigned int family);
 void reload_ucode_amd(void);
 #else
 static inline void __init load_ucode_amd_bsp(unsigned int family) {}
-static inline void load_ucode_amd_ap(void) {}
-static inline int __init save_microcode_in_initrd_amd(void) { return -EINVAL; }
+static inline void load_ucode_amd_ap(unsigned int family) {}
+static inline int __init
+save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
 void reload_ucode_amd(void) {}
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/microcode.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/microcode.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/microcode.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/microcode.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,15 @@ do {							\
 			 (u32)((u64)(val)),		\
 			 (u32)((u64)(val) >> 32))
 
+struct ucode_patch {
+	struct list_head plist;
+	void *data;		/* Intel uses only this one */
+	u32 patch_id;
+	u16 equiv_cpu;
+};
+
+extern struct list_head microcode_cache;
+
 struct cpu_signature {
 	unsigned int sig;
 	unsigned int pf;
@@ -55,12 +64,7 @@ struct ucode_cpu_info {
 	void			*mc;
 };
 extern struct ucode_cpu_info ucode_cpu_info[];
-
-#ifdef CONFIG_MICROCODE
-int __init microcode_init(void);
-#else
-static inline int __init microcode_init(void)	{ return 0; };
-#endif
+struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa);
 
 #ifdef CONFIG_MICROCODE_INTEL
 extern struct microcode_ops * __init init_intel_microcode(void);
@@ -131,11 +135,14 @@ static inline unsigned int x86_cpuid_fam
 }
 
 #ifdef CONFIG_MICROCODE
+int __init microcode_init(void);
 extern void __init load_ucode_bsp(void);
 extern void load_ucode_ap(void);
 void reload_early_microcode(void);
 extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
+extern bool initrd_gone;
 #else
+static inline int __init microcode_init(void)			{ return 0; };
 static inline void __init load_ucode_bsp(void)			{ }
 static inline void load_ucode_ap(void)				{ }
 static inline void reload_early_microcode(void)			{ }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/microcode_intel.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/microcode_intel.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/microcode_intel.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/microcode_intel.h	2017-02-12 16:03:20.000000000 -0500
@@ -52,9 +52,20 @@ struct extended_sigtable {
 
 #define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
 
-extern int has_newer_microcode(void *mc, unsigned int csig, int cpf, int rev);
-extern int microcode_sanity_check(void *mc, int print_err);
-extern int find_matching_signature(void *mc, unsigned int csig, int cpf);
+static inline u32 intel_get_microcode_revision(void)
+{
+	u32 rev, dummy;
+
+	native_wrmsrl(MSR_IA32_UCODE_REV, 0);
+
+	/* As documented in the SDM: Do a CPUID 1 here */
+	native_cpuid_eax(1);
+
+	/* get the current revision from MSR 0x8B */
+	native_rdmsr(MSR_IA32_UCODE_REV, dummy, rev);
+
+	return rev;
+}
 
 #ifdef CONFIG_MICROCODE_INTEL
 extern void __init load_ucode_intel_bsp(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/mmu_context.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mmu_context.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/mmu_context.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mmu_context.h	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@ struct ldt_struct {
 	 * allocations, but it's not worth trying to optimize.
 	 */
 	struct desc_struct *entries;
-	int size;
+	unsigned int size;
 };
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/mmu.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mmu.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/mmu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mmu.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,10 @@ typedef struct {
 	u16 pkey_allocation_map;
 	s16 execute_only_pkey;
 #endif
+#ifdef CONFIG_X86_INTEL_MPX
+	/* address of the bounds directory */
+	void __user *bd_addr;
+#endif
 } mm_context_t;
 
 #ifdef CONFIG_SMP
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/mpx.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mpx.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/mpx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mpx.h	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@ siginfo_t *mpx_generate_siginfo(struct p
 int mpx_handle_bd_fault(void);
 static inline int kernel_managing_mpx_tables(struct mm_struct *mm)
 {
-	return (mm->bd_addr != MPX_INVALID_BOUNDS_DIR);
+	return (mm->context.bd_addr != MPX_INVALID_BOUNDS_DIR);
 }
 static inline void mpx_mm_init(struct mm_struct *mm)
 {
@@ -67,7 +67,7 @@ static inline void mpx_mm_init(struct mm
 	 * NULL is theoretically a valid place to put the bounds
 	 * directory, so point this at an invalid address.
 	 */
-	mm->bd_addr = MPX_INVALID_BOUNDS_DIR;
+	mm->context.bd_addr = MPX_INVALID_BOUNDS_DIR;
 }
 void mpx_notify_unmap(struct mm_struct *mm, struct vm_area_struct *vma,
 		      unsigned long start, unsigned long end);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/msr.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/msr.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/msr.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/msr.h	2017-02-12 16:03:20.000000000 -0500
@@ -70,14 +70,14 @@ extern struct tracepoint __tracepoint_re
 extern struct tracepoint __tracepoint_write_msr;
 extern struct tracepoint __tracepoint_rdpmc;
 #define msr_tracepoint_active(t) static_key_false(&(t).key)
-extern void do_trace_write_msr(unsigned msr, u64 val, int failed);
-extern void do_trace_read_msr(unsigned msr, u64 val, int failed);
-extern void do_trace_rdpmc(unsigned msr, u64 val, int failed);
+extern void do_trace_write_msr(unsigned int msr, u64 val, int failed);
+extern void do_trace_read_msr(unsigned int msr, u64 val, int failed);
+extern void do_trace_rdpmc(unsigned int msr, u64 val, int failed);
 #else
 #define msr_tracepoint_active(t) false
-static inline void do_trace_write_msr(unsigned msr, u64 val, int failed) {}
-static inline void do_trace_read_msr(unsigned msr, u64 val, int failed) {}
-static inline void do_trace_rdpmc(unsigned msr, u64 val, int failed) {}
+static inline void do_trace_write_msr(unsigned int msr, u64 val, int failed) {}
+static inline void do_trace_read_msr(unsigned int msr, u64 val, int failed) {}
+static inline void do_trace_rdpmc(unsigned int msr, u64 val, int failed) {}
 #endif
 
 static inline unsigned long long native_read_msr(unsigned int msr)
@@ -115,22 +115,36 @@ static inline unsigned long long native_
 }
 
 /* Can be uninlined because referenced by paravirt */
-notrace static inline void native_write_msr(unsigned int msr,
-					    unsigned low, unsigned high)
+static inline void notrace
+__native_write_msr_notrace(unsigned int msr, u32 low, u32 high)
 {
 	asm volatile("1: wrmsr\n"
 		     "2:\n"
 		     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_unsafe)
 		     : : "c" (msr), "a"(low), "d" (high) : "memory");
+}
+
+/* Can be uninlined because referenced by paravirt */
+static inline void notrace
+native_write_msr(unsigned int msr, u32 low, u32 high)
+{
+	__native_write_msr_notrace(msr, low, high);
 	if (msr_tracepoint_active(__tracepoint_write_msr))
 		do_trace_write_msr(msr, ((u64)high << 32 | low), 0);
 }
 
+static inline void
+wrmsr_notrace(unsigned int msr, u32 low, u32 high)
+{
+	__native_write_msr_notrace(msr, low, high);
+}
+
 /* Can be uninlined because referenced by paravirt */
-notrace static inline int native_write_msr_safe(unsigned int msr,
-					unsigned low, unsigned high)
+static inline int notrace
+native_write_msr_safe(unsigned int msr, u32 low, u32 high)
 {
 	int err;
+
 	asm volatile("2: wrmsr ; xor %[err],%[err]\n"
 		     "1:\n\t"
 		     ".section .fixup,\"ax\"\n\t"
@@ -223,7 +237,7 @@ do {								\
 	(void)((high) = (u32)(__val >> 32));			\
 } while (0)
 
-static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
+static inline void wrmsr(unsigned int msr, u32 low, u32 high)
 {
 	native_write_msr(msr, low, high);
 }
@@ -231,13 +245,13 @@ static inline void wrmsr(unsigned msr, u
 #define rdmsrl(msr, val)			\
 	((val) = native_read_msr((msr)))
 
-static inline void wrmsrl(unsigned msr, u64 val)
+static inline void wrmsrl(unsigned int msr, u64 val)
 {
 	native_write_msr(msr, (u32)(val & 0xffffffffULL), (u32)(val >> 32));
 }
 
 /* wrmsr with exception handling */
-static inline int wrmsr_safe(unsigned msr, unsigned low, unsigned high)
+static inline int wrmsr_safe(unsigned int msr, u32 low, u32 high)
 {
 	return native_write_msr_safe(msr, low, high);
 }
@@ -252,7 +266,7 @@ static inline int wrmsr_safe(unsigned ms
 	__err;							\
 })
 
-static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
+static inline int rdmsrl_safe(unsigned int msr, unsigned long long *p)
 {
 	int err;
 
@@ -325,12 +339,12 @@ static inline int wrmsrl_on_cpu(unsigned
 static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no,
 				struct msr *msrs)
 {
-       rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h));
+	rdmsr_on_cpu(0, msr_no, &(msrs[0].l), &(msrs[0].h));
 }
 static inline void wrmsr_on_cpus(const struct cpumask *m, u32 msr_no,
 				struct msr *msrs)
 {
-       wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h);
+	wrmsr_on_cpu(0, msr_no, msrs[0].l, msrs[0].h);
 }
 static inline int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no,
 				    u32 *l, u32 *h)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/msr-index.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/msr-index.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/msr-index.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/msr-index.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,10 @@
 #define EFER_FFXSR		(1<<_EFER_FFXSR)
 
 /* Intel MSRs. Some also available on other CPUs */
+
+#define MSR_PPIN_CTL			0x0000004e
+#define MSR_PPIN			0x0000004f
+
 #define MSR_IA32_PERFCTR0		0x000000c1
 #define MSR_IA32_PERFCTR1		0x000000c2
 #define MSR_FSB_FREQ			0x000000cd
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/mutex_32.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mutex_32.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/mutex_32.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mutex_32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-/*
- * Assembly implementation of the mutex fastpath, based on atomic
- * decrement/increment.
- *
- * started by Ingo Molnar:
- *
- *  Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- */
-#ifndef _ASM_X86_MUTEX_32_H
-#define _ASM_X86_MUTEX_32_H
-
-#include <asm/alternative.h>
-
-/**
- *  __mutex_fastpath_lock - try to take the lock by moving the count
- *                          from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *  @fn: function to call if the original value was not 1
- *
- * Change the count from 1 to a value lower than 1, and call <fn> if it
- * wasn't 1 originally. This function MUST leave the value lower than 1
- * even when the "1" assertion wasn't true.
- */
-#define __mutex_fastpath_lock(count, fail_fn)			\
-do {								\
-	unsigned int dummy;					\
-								\
-	typecheck(atomic_t *, count);				\
-	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
-								\
-	asm volatile(LOCK_PREFIX "   decl (%%eax)\n"		\
-		     "   jns 1f	\n"				\
-		     "   call " #fail_fn "\n"			\
-		     "1:\n"					\
-		     : "=a" (dummy)				\
-		     : "a" (count)				\
-		     : "memory", "ecx", "edx");			\
-} while (0)
-
-
-/**
- *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
- *                                 from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int __mutex_fastpath_lock_retval(atomic_t *count)
-{
-	if (unlikely(atomic_dec_return(count) < 0))
-		return -1;
-	else
-		return 0;
-}
-
-/**
- *  __mutex_fastpath_unlock - try to promote the mutex from 0 to 1
- *  @count: pointer of type atomic_t
- *  @fail_fn: function to call if the original value was not 0
- *
- * try to promote the mutex from 0 to 1. if it wasn't 0, call <fail_fn>.
- * In the failure case, this function is allowed to either set the value
- * to 1, or to set it to a value lower than 1.
- *
- * If the implementation sets it to a value of lower than 1, the
- * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
- * to return 0 otherwise.
- */
-#define __mutex_fastpath_unlock(count, fail_fn)			\
-do {								\
-	unsigned int dummy;					\
-								\
-	typecheck(atomic_t *, count);				\
-	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
-								\
-	asm volatile(LOCK_PREFIX "   incl (%%eax)\n"		\
-		     "   jg	1f\n"				\
-		     "   call " #fail_fn "\n"			\
-		     "1:\n"					\
-		     : "=a" (dummy)				\
-		     : "a" (count)				\
-		     : "memory", "ecx", "edx");			\
-} while (0)
-
-#define __mutex_slowpath_needs_to_unlock()	1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- *  @count: pointer of type atomic_t
- *  @fail_fn: fallback function
- *
- * Change the count from 1 to a value lower than 1, and return 0 (failure)
- * if it wasn't 1 originally, or return 1 (success) otherwise. This function
- * MUST leave the value lower than 1 even when the "1" assertion wasn't true.
- * Additionally, if the value was < 0 originally, this function must not leave
- * it to 0 on failure.
- */
-static inline int __mutex_fastpath_trylock(atomic_t *count,
-					   int (*fail_fn)(atomic_t *))
-{
-	/* cmpxchg because it never induces a false contention state. */
-	if (likely(atomic_read(count) == 1 && atomic_cmpxchg(count, 1, 0) == 1))
-		return 1;
-
-	return 0;
-}
-
-#endif /* _ASM_X86_MUTEX_32_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/mutex_64.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mutex_64.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/mutex_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mutex_64.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,127 +0,0 @@
-/*
- * Assembly implementation of the mutex fastpath, based on atomic
- * decrement/increment.
- *
- * started by Ingo Molnar:
- *
- *  Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- */
-#ifndef _ASM_X86_MUTEX_64_H
-#define _ASM_X86_MUTEX_64_H
-
-/**
- * __mutex_fastpath_lock - decrement and call function if negative
- * @v: pointer of type atomic_t
- * @fail_fn: function to call if the result is negative
- *
- * Atomically decrements @v and calls <fail_fn> if the result is negative.
- */
-#ifdef CC_HAVE_ASM_GOTO
-static inline void __mutex_fastpath_lock(atomic_t *v,
-					 void (*fail_fn)(atomic_t *))
-{
-	asm_volatile_goto(LOCK_PREFIX "   decl %0\n"
-			  "   jns %l[exit]\n"
-			  : : "m" (v->counter)
-			  : "memory", "cc"
-			  : exit);
-	fail_fn(v);
-exit:
-	return;
-}
-#else
-#define __mutex_fastpath_lock(v, fail_fn)			\
-do {								\
-	unsigned long dummy;					\
-								\
-	typecheck(atomic_t *, v);				\
-	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
-								\
-	asm volatile(LOCK_PREFIX "   decl (%%rdi)\n"		\
-		     "   jns 1f		\n"			\
-		     "   call " #fail_fn "\n"			\
-		     "1:"					\
-		     : "=D" (dummy)				\
-		     : "D" (v)					\
-		     : "rax", "rsi", "rdx", "rcx",		\
-		       "r8", "r9", "r10", "r11", "memory");	\
-} while (0)
-#endif
-
-/**
- *  __mutex_fastpath_lock_retval - try to take the lock by moving the count
- *                                 from 1 to a 0 value
- *  @count: pointer of type atomic_t
- *
- * Change the count from 1 to a value lower than 1. This function returns 0
- * if the fastpath succeeds, or -1 otherwise.
- */
-static inline int __mutex_fastpath_lock_retval(atomic_t *count)
-{
-	if (unlikely(atomic_dec_return(count) < 0))
-		return -1;
-	else
-		return 0;
-}
-
-/**
- * __mutex_fastpath_unlock - increment and call function if nonpositive
- * @v: pointer of type atomic_t
- * @fail_fn: function to call if the result is nonpositive
- *
- * Atomically increments @v and calls <fail_fn> if the result is nonpositive.
- */
-#ifdef CC_HAVE_ASM_GOTO
-static inline void __mutex_fastpath_unlock(atomic_t *v,
-					   void (*fail_fn)(atomic_t *))
-{
-	asm_volatile_goto(LOCK_PREFIX "   incl %0\n"
-			  "   jg %l[exit]\n"
-			  : : "m" (v->counter)
-			  : "memory", "cc"
-			  : exit);
-	fail_fn(v);
-exit:
-	return;
-}
-#else
-#define __mutex_fastpath_unlock(v, fail_fn)			\
-do {								\
-	unsigned long dummy;					\
-								\
-	typecheck(atomic_t *, v);				\
-	typecheck_fn(void (*)(atomic_t *), fail_fn);		\
-								\
-	asm volatile(LOCK_PREFIX "   incl (%%rdi)\n"		\
-		     "   jg 1f\n"				\
-		     "   call " #fail_fn "\n"			\
-		     "1:"					\
-		     : "=D" (dummy)				\
-		     : "D" (v)					\
-		     : "rax", "rsi", "rdx", "rcx",		\
-		       "r8", "r9", "r10", "r11", "memory");	\
-} while (0)
-#endif
-
-#define __mutex_slowpath_needs_to_unlock()	1
-
-/**
- * __mutex_fastpath_trylock - try to acquire the mutex, without waiting
- *
- *  @count: pointer of type atomic_t
- *  @fail_fn: fallback function
- *
- * Change the count from 1 to 0 and return 1 (success), or return 0 (failure)
- * if it wasn't 1 originally. [the fallback function is never used on
- * x86_64, because all x86_64 CPUs have a CMPXCHG instruction.]
- */
-static inline int __mutex_fastpath_trylock(atomic_t *count,
-					   int (*fail_fn)(atomic_t *))
-{
-	if (likely(atomic_read(count) == 1 && atomic_cmpxchg(count, 1, 0) == 1))
-		return 1;
-
-	return 0;
-}
-
-#endif /* _ASM_X86_MUTEX_64_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-#ifdef CONFIG_X86_32
-# include <asm/mutex_32.h>
-#else
-# include <asm/mutex_64.h>
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/paravirt.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/paravirt.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/paravirt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/paravirt.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,11 +41,6 @@ static inline void set_debugreg(unsigned
 	PVOP_VCALL2(pv_cpu_ops.set_debugreg, reg, val);
 }
 
-static inline void clts(void)
-{
-	PVOP_VCALL0(pv_cpu_ops.clts);
-}
-
 static inline unsigned long read_cr0(void)
 {
 	return PVOP_CALL0(unsigned long, pv_cpu_ops.read_cr0);
@@ -678,6 +673,11 @@ static __always_inline void pv_kick(int
 	PVOP_VCALL1(pv_lock_ops.kick, cpu);
 }
 
+static __always_inline bool pv_vcpu_is_preempted(int cpu)
+{
+	return PVOP_CALLEE1(bool, pv_lock_ops.vcpu_is_preempted, cpu);
+}
+
 #endif /* SMP && PARAVIRT_SPINLOCKS */
 
 #ifdef CONFIG_X86_32
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/paravirt_types.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/paravirt_types.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/paravirt_types.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/paravirt_types.h	2017-02-12 16:03:20.000000000 -0500
@@ -103,8 +103,6 @@ struct pv_cpu_ops {
 	unsigned long (*get_debugreg)(int regno);
 	void (*set_debugreg)(int regno, unsigned long value);
 
-	void (*clts)(void);
-
 	unsigned long (*read_cr0)(void);
 	void (*write_cr0)(unsigned long);
 
@@ -310,6 +308,8 @@ struct pv_lock_ops {
 
 	void (*wait)(u8 *ptr, u8 val);
 	void (*kick)(int cpu);
+
+	struct paravirt_callee_save vcpu_is_preempted;
 };
 
 /* This contains all the paravirt structures: we get a convenient
@@ -508,6 +508,18 @@ int paravirt_disable_iospace(void);
 #define PVOP_TEST_NULL(op)	((void)op)
 #endif
 
+#define PVOP_RETMASK(rettype)						\
+	({	unsigned long __mask = ~0UL;				\
+		switch (sizeof(rettype)) {				\
+		case 1: __mask =       0xffUL; break;			\
+		case 2: __mask =     0xffffUL; break;			\
+		case 4: __mask = 0xffffffffUL; break;			\
+		default: break;						\
+		}							\
+		__mask;							\
+	})
+
+
 #define ____PVOP_CALL(rettype, op, clbr, call_clbr, extra_clbr,		\
 		      pre, post, ...)					\
 	({								\
@@ -535,7 +547,7 @@ int paravirt_disable_iospace(void);
 				       paravirt_clobber(clbr),		\
 				       ##__VA_ARGS__			\
 				     : "memory", "cc" extra_clbr);	\
-			__ret = (rettype)__eax;				\
+			__ret = (rettype)(__eax & PVOP_RETMASK(rettype));	\
 		}							\
 		__ret;							\
 	})
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/percpu.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/percpu.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/percpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/percpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -507,17 +507,6 @@ do {									\
 
 #endif
 
-/* This is not atomic against other CPUs -- CPU preemption needs to be off */
-#define x86_test_and_clear_bit_percpu(bit, var)				\
-({									\
-	bool old__;							\
-	asm volatile("btr %2,"__percpu_arg(1)"\n\t"			\
-		     CC_SET(c)						\
-		     : CC_OUT(c) (old__), "+m" (var)			\
-		     : "dIr" (bit));					\
-	old__;								\
-})
-
 static __always_inline bool x86_this_cpu_constant_test_bit(unsigned int nr,
                         const unsigned long __percpu *addr)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/pgtable_64.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/pgtable_64.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/pgtable_64.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/pgtable_64.h	2017-02-12 16:03:20.000000000 -0500
@@ -116,8 +116,7 @@ static inline void native_pgd_clear(pgd_
 	native_set_pgd(pgd, native_make_pgd(0));
 }
 
-extern void sync_global_pgds(unsigned long start, unsigned long end,
-			     int removed);
+extern void sync_global_pgds(unsigned long start, unsigned long end);
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/preempt.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/preempt.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/preempt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/preempt.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,13 @@ static __always_inline int preempt_count
 
 static __always_inline void preempt_count_set(int pc)
 {
-	raw_cpu_write_4(__preempt_count, pc);
+	int old, new;
+
+	do {
+		old = raw_cpu_read_4(__preempt_count);
+		new = (old & PREEMPT_NEED_RESCHED) |
+			(pc & ~PREEMPT_NEED_RESCHED);
+	} while (raw_cpu_cmpxchg_4(__preempt_count, old, new) != old);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,6 +104,7 @@ struct cpuinfo_x86 {
 	__u8			x86_phys_bits;
 	/* CPUID returned core id bits: */
 	__u8			x86_coreid_bits;
+	__u8			cu_id;
 	/* Max extended CPUID function supported: */
 	__u32			extended_cpuid_level;
 	/* Maximum supported CPUID level, -1=no CPUID: */
@@ -137,6 +138,17 @@ struct cpuinfo_x86 {
 	u32			microcode;
 };
 
+struct cpuid_regs {
+	u32 eax, ebx, ecx, edx;
+};
+
+enum cpuid_regs_idx {
+	CPUID_EAX = 0,
+	CPUID_EBX,
+	CPUID_ECX,
+	CPUID_EDX,
+};
+
 #define X86_VENDOR_INTEL	0
 #define X86_VENDOR_CYRIX	1
 #define X86_VENDOR_AMD		2
@@ -178,6 +190,9 @@ extern void identify_secondary_cpu(struc
 extern void print_cpu_info(struct cpuinfo_x86 *);
 void print_cpu_msr(struct cpuinfo_x86 *);
 extern void init_scattered_cpuid_features(struct cpuinfo_x86 *c);
+extern u32 get_scattered_cpuid_leaf(unsigned int level,
+				    unsigned int sub_leaf,
+				    enum cpuid_regs_idx reg);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
 extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
 
@@ -205,6 +220,24 @@ static inline void native_cpuid(unsigned
 	    : "memory");
 }
 
+#define native_cpuid_reg(reg)					\
+static inline unsigned int native_cpuid_##reg(unsigned int op)	\
+{								\
+	unsigned int eax = op, ebx, ecx = 0, edx;		\
+								\
+	native_cpuid(&eax, &ebx, &ecx, &edx);			\
+								\
+	return reg;						\
+}
+
+/*
+ * Native CPUID functions returning a single datum.
+ */
+native_cpuid_reg(eax)
+native_cpuid_reg(ebx)
+native_cpuid_reg(ecx)
+native_cpuid_reg(edx)
+
 static inline void load_cr3(pgd_t *pgdir)
 {
 	write_cr3(__pa(pgdir));
@@ -588,43 +621,76 @@ static __always_inline void cpu_relax(vo
 	rep_nop();
 }
 
-#define cpu_relax_lowlatency() cpu_relax()
-
-/* Stop speculative execution and prefetching of modified code. */
+/*
+ * This function forces the icache and prefetched instruction stream to
+ * catch up with reality in two very specific cases:
+ *
+ *  a) Text was modified using one virtual address and is about to be executed
+ *     from the same physical page at a different virtual address.
+ *
+ *  b) Text was modified on a different CPU, may subsequently be
+ *     executed on this CPU, and you want to make sure the new version
+ *     gets executed.  This generally means you're calling this in a IPI.
+ *
+ * If you're calling this for a different reason, you're probably doing
+ * it wrong.
+ */
 static inline void sync_core(void)
 {
-	int tmp;
-
-#ifdef CONFIG_M486
 	/*
-	 * Do a CPUID if available, otherwise do a jump.  The jump
-	 * can conveniently enough be the jump around CPUID.
+	 * There are quite a few ways to do this.  IRET-to-self is nice
+	 * because it works on every CPU, at any CPL (so it's compatible
+	 * with paravirtualization), and it never exits to a hypervisor.
+	 * The only down sides are that it's a bit slow (it seems to be
+	 * a bit more than 2x slower than the fastest options) and that
+	 * it unmasks NMIs.  The "push %cs" is needed because, in
+	 * paravirtual environments, __KERNEL_CS may not be a valid CS
+	 * value when we do IRET directly.
+	 *
+	 * In case NMI unmasking or performance ever becomes a problem,
+	 * the next best option appears to be MOV-to-CR2 and an
+	 * unconditional jump.  That sequence also works on all CPUs,
+	 * but it will fault at CPL3 (i.e. Xen PV and lguest).
+	 *
+	 * CPUID is the conventional way, but it's nasty: it doesn't
+	 * exist on some 486-like CPUs, and it usually exits to a
+	 * hypervisor.
+	 *
+	 * Like all of Linux's memory ordering operations, this is a
+	 * compiler barrier as well.
 	 */
-	asm volatile("cmpl %2,%1\n\t"
-		     "jl 1f\n\t"
-		     "cpuid\n"
-		     "1:"
-		     : "=a" (tmp)
-		     : "rm" (boot_cpu_data.cpuid_level), "ri" (0), "0" (1)
-		     : "ebx", "ecx", "edx", "memory");
+	register void *__sp asm(_ASM_SP);
+
+#ifdef CONFIG_X86_32
+	asm volatile (
+		"pushfl\n\t"
+		"pushl %%cs\n\t"
+		"pushl $1f\n\t"
+		"iret\n\t"
+		"1:"
+		: "+r" (__sp) : : "memory");
 #else
-	/*
-	 * CPUID is a barrier to speculative execution.
-	 * Prefetched instructions are automatically
-	 * invalidated when modified.
-	 */
-	asm volatile("cpuid"
-		     : "=a" (tmp)
-		     : "0" (1)
-		     : "ebx", "ecx", "edx", "memory");
+	unsigned int tmp;
+
+	asm volatile (
+		"mov %%ss, %0\n\t"
+		"pushq %q0\n\t"
+		"pushq %%rsp\n\t"
+		"addq $8, (%%rsp)\n\t"
+		"pushfq\n\t"
+		"mov %%cs, %0\n\t"
+		"pushq %q0\n\t"
+		"pushq $1f\n\t"
+		"iretq\n\t"
+		"1:"
+		: "=&r" (tmp), "+r" (__sp) : : "cc", "memory");
 #endif
 }
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
-extern void init_amd_e400_c1e_mask(void);
+extern void amd_e400_c1e_apic_setup(void);
 
 extern unsigned long		boot_option_idle_override;
-extern bool			amd_e400_c1e_detected;
 
 enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
 			 IDLE_POLL};
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/pvclock.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/pvclock.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/pvclock.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/pvclock.h	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@ static inline struct pvclock_vsyscall_ti
 #endif
 
 /* some helper functions for xen and kvm pv clock sources */
-cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
+u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src);
 u8 pvclock_read_flags(struct pvclock_vcpu_time_info *src);
 void pvclock_set_flags(u8 flags);
 unsigned long pvclock_tsc_khz(struct pvclock_vcpu_time_info *src);
@@ -87,11 +87,10 @@ static inline u64 pvclock_scale_delta(u6
 }
 
 static __always_inline
-cycle_t __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src,
-			      u64 tsc)
+u64 __pvclock_read_cycles(const struct pvclock_vcpu_time_info *src, u64 tsc)
 {
 	u64 delta = tsc - src->tsc_timestamp;
-	cycle_t offset = pvclock_scale_delta(delta, src->tsc_to_system_mul,
+	u64 offset = pvclock_scale_delta(delta, src->tsc_to_system_mul,
 					     src->tsc_shift);
 	return src->system_time + offset;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/qspinlock.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/qspinlock.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/qspinlock.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/qspinlock.h	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,12 @@ static inline void queued_spin_unlock(st
 {
 	pv_queued_spin_unlock(lock);
 }
+
+#define vcpu_is_preempted vcpu_is_preempted
+static inline bool vcpu_is_preempted(int cpu)
+{
+	return pv_vcpu_is_preempted(cpu);
+}
 #else
 static inline void queued_spin_unlock(struct qspinlock *lock)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/special_insns.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/special_insns.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/special_insns.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/special_insns.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,11 +6,6 @@
 
 #include <asm/nops.h>
 
-static inline void native_clts(void)
-{
-	asm volatile("clts");
-}
-
 /*
  * Volatile isn't enough to prevent the compiler from reordering the
  * read/write functions for the control registers and messing everything up.
@@ -208,16 +203,8 @@ static inline void load_gs_index(unsigne
 
 #endif
 
-/* Clear the 'TS' bit */
-static inline void clts(void)
-{
-	native_clts();
-}
-
 #endif/* CONFIG_PARAVIRT */
 
-#define stts() write_cr0(read_cr0() | X86_CR0_TS)
-
 static inline void clflush(volatile void *__p)
 {
 	asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/stacktrace.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/stacktrace.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/stacktrace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/stacktrace.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,8 +30,7 @@ bool in_task_stack(unsigned long *stack,
 int get_stack_info(unsigned long *stack, struct task_struct *task,
 		   struct stack_info *info, unsigned long *visit_mask);
 
-void stack_type_str(enum stack_type type, const char **begin,
-		    const char **end);
+const char *stack_type_name(enum stack_type type);
 
 static inline bool on_stack(struct stack_info *info, void *addr, size_t len)
 {
@@ -43,8 +42,6 @@ static inline bool on_stack(struct stack
 		addr + len > begin && addr + len <= end);
 }
 
-extern int kstack_depth_to_print;
-
 #ifdef CONFIG_X86_32
 #define STACKSLOTS_PER_LINE 8
 #else
@@ -61,7 +58,7 @@ get_frame_pointer(struct task_struct *ta
 	if (task == current)
 		return __builtin_frame_address(0);
 
-	return (unsigned long *)((struct inactive_task_frame *)task->thread.sp)->bp;
+	return &((struct inactive_task_frame *)task->thread.sp)->bp;
 }
 #else
 static inline unsigned long *
@@ -86,9 +83,6 @@ get_stack_pointer(struct task_struct *ta
 void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
 			unsigned long *stack, char *log_lvl);
 
-void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-			unsigned long *sp, char *log_lvl);
-
 extern unsigned int code_bytes;
 
 /* The form of the top of the frame on the stack */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/switch_to.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/switch_to.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/switch_to.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/switch_to.h	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,10 @@ static inline void prepare_switch_to(str
 
 asmlinkage void ret_from_fork(void);
 
-/* data that is pointed to by thread.sp */
+/*
+ * This is the structure pointed to by thread.sp for an inactive task.  The
+ * order of the fields must match the code in __switch_to_asm().
+ */
 struct inactive_task_frame {
 #ifdef CONFIG_X86_64
 	unsigned long r15;
@@ -48,6 +51,11 @@ struct inactive_task_frame {
 	unsigned long di;
 #endif
 	unsigned long bx;
+
+	/*
+	 * These two fields must be together.  They form a stack frame header,
+	 * needed by get_frame_pointer().
+	 */
 	unsigned long bp;
 	unsigned long ret_addr;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/topology.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/topology.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/topology.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/topology.h	2017-02-12 16:03:20.000000000 -0500
@@ -146,4 +146,36 @@ struct pci_bus;
 int x86_pci_root_bus_node(int bus);
 void x86_pci_root_bus_resources(int bus, struct list_head *resources);
 
+extern bool x86_topology_update;
+
+#ifdef CONFIG_SCHED_MC_PRIO
+#include <asm/percpu.h>
+
+DECLARE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
+extern unsigned int __read_mostly sysctl_sched_itmt_enabled;
+
+/* Interface to set priority of a cpu */
+void sched_set_itmt_core_prio(int prio, int core_cpu);
+
+/* Interface to notify scheduler that system supports ITMT */
+int sched_set_itmt_support(void);
+
+/* Interface to notify scheduler that system revokes ITMT support */
+void sched_clear_itmt_support(void);
+
+#else /* CONFIG_SCHED_MC_PRIO */
+
+#define sysctl_sched_itmt_enabled	0
+static inline void sched_set_itmt_core_prio(int prio, int core_cpu)
+{
+}
+static inline int sched_set_itmt_support(void)
+{
+	return 0;
+}
+static inline void sched_clear_itmt_support(void)
+{
+}
+#endif /* CONFIG_SCHED_MC_PRIO */
+
 #endif /* _ASM_X86_TOPOLOGY_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/trace/exceptions.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/trace/exceptions.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/trace/exceptions.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/trace/exceptions.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
 
 #include <linux/tracepoint.h>
 
-extern void trace_irq_vector_regfunc(void);
+extern int trace_irq_vector_regfunc(void);
 extern void trace_irq_vector_unregfunc(void);
 
 DECLARE_EVENT_CLASS(x86_exceptions,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/trace/fpu.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/trace/fpu.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/trace/fpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/trace/fpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,6 @@ DECLARE_EVENT_CLASS(x86_fpu,
 		__field(struct fpu *, fpu)
 		__field(bool, fpregs_active)
 		__field(bool, fpstate_active)
-		__field(int, counter)
 		__field(u64, xfeatures)
 		__field(u64, xcomp_bv)
 		),
@@ -23,17 +22,15 @@ DECLARE_EVENT_CLASS(x86_fpu,
 		__entry->fpu		= fpu;
 		__entry->fpregs_active	= fpu->fpregs_active;
 		__entry->fpstate_active	= fpu->fpstate_active;
-		__entry->counter	= fpu->counter;
 		if (boot_cpu_has(X86_FEATURE_OSXSAVE)) {
 			__entry->xfeatures = fpu->state.xsave.header.xfeatures;
 			__entry->xcomp_bv  = fpu->state.xsave.header.xcomp_bv;
 		}
 	),
-	TP_printk("x86/fpu: %p fpregs_active: %d fpstate_active: %d counter: %d xfeatures: %llx xcomp_bv: %llx",
+	TP_printk("x86/fpu: %p fpregs_active: %d fpstate_active: %d xfeatures: %llx xcomp_bv: %llx",
 			__entry->fpu,
 			__entry->fpregs_active,
 			__entry->fpstate_active,
-			__entry->counter,
 			__entry->xfeatures,
 			__entry->xcomp_bv
 	)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/trace/irq_vectors.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/trace/irq_vectors.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/trace/irq_vectors.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/trace/irq_vectors.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
 
 #include <linux/tracepoint.h>
 
-extern void trace_irq_vector_regfunc(void);
+extern int trace_irq_vector_regfunc(void);
 extern void trace_irq_vector_unregfunc(void);
 
 DECLARE_EVENT_CLASS(x86_irq_vector,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/tsc.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/tsc.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/tsc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/tsc.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@ static inline cycles_t get_cycles(void)
 	return rdtsc();
 }
 
-extern struct system_counterval_t convert_art_to_tsc(cycle_t art);
+extern struct system_counterval_t convert_art_to_tsc(u64 art);
 
 extern void tsc_init(void);
 extern void mark_tsc_unstable(char *reason);
@@ -45,8 +45,17 @@ extern int tsc_clocksource_reliable;
  * Boot-time check whether the TSCs are synchronized across
  * all CPUs/cores:
  */
+#ifdef CONFIG_X86_TSC
+extern bool tsc_store_and_check_tsc_adjust(bool bootcpu);
+extern void tsc_verify_tsc_adjust(bool resume);
 extern void check_tsc_sync_source(int cpu);
 extern void check_tsc_sync_target(void);
+#else
+static inline bool tsc_store_and_check_tsc_adjust(bool bootcpu) { return false; }
+static inline void tsc_verify_tsc_adjust(bool resume) { }
+static inline void check_tsc_sync_source(int cpu) { }
+static inline void check_tsc_sync_target(void) { }
+#endif
 
 extern int notsc_setup(char *);
 extern void tsc_save_sched_clock_state(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/uaccess.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/uaccess.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/uaccess.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/uaccess.h	2017-02-12 16:03:20.000000000 -0500
@@ -68,6 +68,12 @@ static inline bool __chk_range_not_ok(un
 	__chk_range_not_ok((unsigned long __force)(addr), size, limit); \
 })
 
+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
+# define WARN_ON_IN_IRQ()	WARN_ON_ONCE(!in_task())
+#else
+# define WARN_ON_IN_IRQ()
+#endif
+
 /**
  * access_ok: - Checks if a user space pointer is valid
  * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE.  Note that
@@ -88,8 +94,11 @@ static inline bool __chk_range_not_ok(un
  * checks that the pointer is in the user space range - after calling
  * this function, memory access functions may still return -EFAULT.
  */
-#define access_ok(type, addr, size) \
-	likely(!__range_not_ok(addr, size, user_addr_max()))
+#define access_ok(type, addr, size)					\
+({									\
+	WARN_ON_IN_IRQ();						\
+	likely(!__range_not_ok(addr, size, user_addr_max()));		\
+})
 
 /*
  * These are the main single-value transfer routines.  They automatically
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/unwind.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/unwind.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/unwind.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/unwind.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,8 @@ struct unwind_state {
 	struct task_struct *task;
 	int graph_idx;
 #ifdef CONFIG_FRAME_POINTER
-	unsigned long *bp;
+	unsigned long *bp, *orig_sp;
+	struct pt_regs *regs;
 #else
 	unsigned long *sp;
 #endif
@@ -47,7 +48,15 @@ unsigned long *unwind_get_return_address
 	if (unwind_done(state))
 		return NULL;
 
-	return state->bp + 1;
+	return state->regs ? &state->regs->ip : state->bp + 1;
+}
+
+static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
+{
+	if (unwind_done(state))
+		return NULL;
+
+	return state->regs;
 }
 
 #else /* !CONFIG_FRAME_POINTER */
@@ -57,6 +66,11 @@ unsigned long *unwind_get_return_address
 {
 	return NULL;
 }
+
+static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
+{
+	return NULL;
+}
 
 #endif /* CONFIG_FRAME_POINTER */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/vgtod.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/vgtod.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/vgtod.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/vgtod.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,8 +17,8 @@ struct vsyscall_gtod_data {
 	unsigned seq;
 
 	int vclock_mode;
-	cycle_t	cycle_last;
-	cycle_t	mask;
+	u64	cycle_last;
+	u64	mask;
 	u32	mult;
 	u32	shift;
 
@@ -89,8 +89,13 @@ static inline unsigned int __getcpu(void
 	 * works on all CPUs.  This is volatile so that it orders
 	 * correctly wrt barrier() and to keep gcc from cleverly
 	 * hoisting it out of the calling function.
+	 *
+	 * If RDPID is available, use it.
 	 */
-	asm volatile ("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+	alternative_io ("lsl %[p],%[seg]",
+			".byte 0xf3,0x0f,0xc7,0xf8", /* RDPID %eax/rax */
+			X86_FEATURE_RDPID,
+			[p] "=a" (p), [seg] "r" (__PER_CPU_SEG));
 
 	return p;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/vmx.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/vmx.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/vmx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/vmx.h	2017-02-12 16:03:20.000000000 -0500
@@ -25,6 +25,7 @@
 #define VMX_H
 
 
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <uapi/asm/vmx.h>
 
@@ -60,6 +61,7 @@
  */
 #define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
 #define SECONDARY_EXEC_ENABLE_EPT               0x00000002
+#define SECONDARY_EXEC_DESC			0x00000004
 #define SECONDARY_EXEC_RDTSCP			0x00000008
 #define SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE   0x00000010
 #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
@@ -110,6 +112,36 @@
 #define VMX_MISC_SAVE_EFER_LMA			0x00000020
 #define VMX_MISC_ACTIVITY_HLT			0x00000040
 
+static inline u32 vmx_basic_vmcs_revision_id(u64 vmx_basic)
+{
+	return vmx_basic & GENMASK_ULL(30, 0);
+}
+
+static inline u32 vmx_basic_vmcs_size(u64 vmx_basic)
+{
+	return (vmx_basic & GENMASK_ULL(44, 32)) >> 32;
+}
+
+static inline int vmx_misc_preemption_timer_rate(u64 vmx_misc)
+{
+	return vmx_misc & VMX_MISC_PREEMPTION_TIMER_RATE_MASK;
+}
+
+static inline int vmx_misc_cr3_count(u64 vmx_misc)
+{
+	return (vmx_misc & GENMASK_ULL(24, 16)) >> 16;
+}
+
+static inline int vmx_misc_max_msr(u64 vmx_misc)
+{
+	return (vmx_misc & GENMASK_ULL(27, 25)) >> 25;
+}
+
+static inline int vmx_misc_mseg_revid(u64 vmx_misc)
+{
+	return (vmx_misc & GENMASK_ULL(63, 32)) >> 32;
+}
+
 /* VMCS Encodings */
 enum vmcs_field {
 	VIRTUAL_PROCESSOR_ID            = 0x00000000,
@@ -399,10 +431,11 @@ enum vmcs_field {
 #define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT	(KVM_USER_MEM_SLOTS + 2)
 
 #define VMX_NR_VPIDS				(1 << 16)
+#define VMX_VPID_EXTENT_INDIVIDUAL_ADDR		0
 #define VMX_VPID_EXTENT_SINGLE_CONTEXT		1
 #define VMX_VPID_EXTENT_ALL_CONTEXT		2
+#define VMX_VPID_EXTENT_SINGLE_NON_GLOBAL	3
 
-#define VMX_EPT_EXTENT_INDIVIDUAL_ADDR		0
 #define VMX_EPT_EXTENT_CONTEXT			1
 #define VMX_EPT_EXTENT_GLOBAL			2
 #define VMX_EPT_EXTENT_SHIFT			24
@@ -419,8 +452,10 @@ enum vmcs_field {
 #define VMX_EPT_EXTENT_GLOBAL_BIT		(1ull << 26)
 
 #define VMX_VPID_INVVPID_BIT                    (1ull << 0) /* (32 - 32) */
+#define VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT     (1ull << 8) /* (40 - 32) */
 #define VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT      (1ull << 9) /* (41 - 32) */
 #define VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT      (1ull << 10) /* (42 - 32) */
+#define VMX_VPID_EXTENT_SINGLE_NON_GLOBAL_BIT   (1ull << 11) /* (43 - 32) */
 
 #define VMX_EPT_DEFAULT_GAW			3
 #define VMX_EPT_MAX_GAW				0x4
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/x86_init.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/x86_init.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/x86_init.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/x86_init.h	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@ struct x86_init_irqs {
 
 /**
  * struct x86_init_oem - oem platform specific customizing functions
- * @arch_setup:			platform specific architecure setup
+ * @arch_setup:			platform specific architecture setup
  * @banner:			print a platform specific banner
  */
 struct x86_init_oem {
@@ -165,8 +165,25 @@ struct x86_legacy_devices {
 };
 
 /**
+ * enum x86_legacy_i8042_state - i8042 keyboard controller state
+ * @X86_LEGACY_I8042_PLATFORM_ABSENT: the controller is always absent on
+ *	given platform/subarch.
+ * @X86_LEGACY_I8042_FIRMWARE_ABSENT: firmware reports that the controller
+ *	is absent.
+ * @X86_LEGACY_i8042_EXPECTED_PRESENT: the controller is likely to be
+ *	present, the i8042 driver should probe for controller existence.
+ */
+enum x86_legacy_i8042_state {
+	X86_LEGACY_I8042_PLATFORM_ABSENT,
+	X86_LEGACY_I8042_FIRMWARE_ABSENT,
+	X86_LEGACY_I8042_EXPECTED_PRESENT,
+};
+
+/**
  * struct x86_legacy_features - legacy x86 features
  *
+ * @i8042: indicated if we expect the device to have i8042 controller
+ *	present.
  * @rtc: this device has a CMOS real-time clock present
  * @reserve_bios_regions: boot code will search for the EBDA address and the
  * 	start of the 640k - 1M BIOS region.  If false, the platform must
@@ -175,6 +192,7 @@ struct x86_legacy_devices {
  * 	documentation for further details.
  */
 struct x86_legacy_features {
+	enum x86_legacy_i8042_state i8042;
 	int rtc;
 	int reserve_bios_regions;
 	struct x86_legacy_devices devices;
@@ -188,15 +206,14 @@ struct x86_legacy_features {
  * @set_wallclock:		set time back to HW clock
  * @is_untracked_pat_range	exclude from PAT logic
  * @nmi_init			enable NMI on cpus
- * @i8042_detect		pre-detect if i8042 controller exists
  * @save_sched_clock_state:	save state for sched_clock() on suspend
  * @restore_sched_clock_state:	restore state for sched_clock() on resume
- * @apic_post_init:		adjust apic if neeeded
+ * @apic_post_init:		adjust apic if needed
  * @legacy:			legacy features
  * @set_legacy_features:	override legacy features. Use of this callback
  * 				is highly discouraged. You should only need
  * 				this if your hardware platform requires further
- * 				custom fine tuning far beyong what may be
+ * 				custom fine tuning far beyond what may be
  * 				possible in x86_early_init_platform_quirks() by
  * 				only using the current x86_hardware_subarch
  * 				semantics.
@@ -210,7 +227,6 @@ struct x86_platform_ops {
 	bool (*is_untracked_pat_range)(u64 start, u64 end);
 	void (*nmi_init)(void);
 	unsigned char (*get_nmi_reason)(void);
-	int (*i8042_detect)(void);
 	void (*save_sched_clock_state)(void);
 	void (*restore_sched_clock_state)(void);
 	void (*apic_post_init)(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/asm/xen/page.h linux-libre-4.10-rc8-gnu/arch/x86/include/asm/xen/page.h
--- linux-libre-4.9-gnu/arch/x86/include/asm/xen/page.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/asm/xen/page.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@
 #include <linux/pfn.h>
 #include <linux/mm.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/uapi/asm/bootparam.h linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/bootparam.h
--- linux-libre-4.9-gnu/arch/x86/include/uapi/asm/bootparam.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/bootparam.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
 #define SETUP_DTB			2
 #define SETUP_PCI			3
 #define SETUP_EFI			4
+#define SETUP_APPLE_PROPERTIES		5
 
 /* ram_size flags */
 #define RAMDISK_IMAGE_START_MASK	0x07FF
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/uapi/asm/kvm_para.h linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/kvm_para.h
--- linux-libre-4.9-gnu/arch/x86/include/uapi/asm/kvm_para.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/kvm_para.h	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,9 @@ struct kvm_steal_time {
 	__u64 steal;
 	__u32 version;
 	__u32 flags;
-	__u32 pad[12];
+	__u8  preempted;
+	__u8  u8_pad[3];
+	__u32 pad[11];
 };
 
 #define KVM_STEAL_ALIGNMENT_BITS 5
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/uapi/asm/mce.h linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/mce.h
--- linux-libre-4.9-gnu/arch/x86/include/uapi/asm/mce.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/mce.h	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@ struct mce {
 	__u64 mcgcap;	/* MCGCAP MSR: machine check capabilities of CPU */
 	__u64 synd;	/* MCA_SYND MSR: only valid on SMCA systems */
 	__u64 ipid;	/* MCA_IPID MSR: only valid on SMCA systems */
+	__u64 ppin;	/* Protected Processor Inventory Number */
 };
 
 #define MCE_GET_RECORD_LEN   _IOR('M', 1, int)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/uapi/asm/prctl.h linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/prctl.h
--- linux-libre-4.9-gnu/arch/x86/include/uapi/asm/prctl.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/prctl.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,10 +6,8 @@
 #define ARCH_GET_FS 0x1003
 #define ARCH_GET_GS 0x1004
 
-#ifdef CONFIG_CHECKPOINT_RESTORE
-# define ARCH_MAP_VDSO_X32	0x2001
-# define ARCH_MAP_VDSO_32	0x2002
-# define ARCH_MAP_VDSO_64	0x2003
-#endif
+#define ARCH_MAP_VDSO_X32	0x2001
+#define ARCH_MAP_VDSO_32	0x2002
+#define ARCH_MAP_VDSO_64	0x2003
 
 #endif /* _ASM_X86_PRCTL_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/include/uapi/asm/vmx.h linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/vmx.h
--- linux-libre-4.9-gnu/arch/x86/include/uapi/asm/vmx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/include/uapi/asm/vmx.h	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,8 @@
 #define EXIT_REASON_TPR_BELOW_THRESHOLD 43
 #define EXIT_REASON_APIC_ACCESS         44
 #define EXIT_REASON_EOI_INDUCED         45
+#define EXIT_REASON_GDTR_IDTR           46
+#define EXIT_REASON_LDTR_TR             47
 #define EXIT_REASON_EPT_VIOLATION       48
 #define EXIT_REASON_EPT_MISCONFIG       49
 #define EXIT_REASON_INVEPT              50
@@ -113,6 +115,8 @@
 	{ EXIT_REASON_MCE_DURING_VMENTRY,    "MCE_DURING_VMENTRY" }, \
 	{ EXIT_REASON_TPR_BELOW_THRESHOLD,   "TPR_BELOW_THRESHOLD" }, \
 	{ EXIT_REASON_APIC_ACCESS,           "APIC_ACCESS" }, \
+	{ EXIT_REASON_GDTR_IDTR,	     "GDTR_IDTR" }, \
+	{ EXIT_REASON_LDTR_TR,		     "LDTR_TR" }, \
 	{ EXIT_REASON_EPT_VIOLATION,         "EPT_VIOLATION" }, \
 	{ EXIT_REASON_EPT_MISCONFIG,         "EPT_MISCONFIG" }, \
 	{ EXIT_REASON_INVEPT,                "INVEPT" }, \
@@ -129,6 +133,7 @@
 	{ EXIT_REASON_XRSTORS,               "XRSTORS" }
 
 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL        1
+#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL       2
 #define VMX_ABORT_LOAD_HOST_MSR_FAIL         4
 
 #endif /* _UAPIVMX_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/Kconfig linux-libre-4.10-rc8-gnu/arch/x86/Kconfig
--- linux-libre-4.9-gnu/arch/x86/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -9,28 +9,50 @@ config 64BIT
 config X86_32
 	def_bool y
 	depends on !64BIT
+	# Options that are inherently 32-bit kernel only:
+	select ARCH_WANT_IPC_PARSE_VERSION
+	select CLKSRC_I8253
+	select CLONE_BACKWARDS
+	select HAVE_AOUT
+	select HAVE_GENERIC_DMA_COHERENT
+	select MODULES_USE_ELF_REL
+	select OLD_SIGACTION
 
 config X86_64
 	def_bool y
 	depends on 64BIT
+	# Options that are inherently 64-bit kernel only:
+	select ARCH_HAS_GIGANTIC_PAGE
+	select ARCH_SUPPORTS_INT128
+	select ARCH_USE_CMPXCHG_LOCKREF
+	select HAVE_ARCH_SOFT_DIRTY
+	select MODULES_USE_ELF_RELA
+	select X86_DEV_DMA_OPS
 
-### Arch settings
+#
+# Arch settings
+#
+# ( Note that options that are marked 'if X86_64' could in principle be
+#   ported to 32-bit as well. )
+#
 config X86
 	def_bool y
+	#
+	# Note: keep this list sorted alphabetically
+	#
 	select ACPI_LEGACY_TABLES_LOOKUP	if ACPI
 	select ACPI_SYSTEM_POWER_STATES_SUPPORT	if ACPI
 	select ANON_INODES
 	select ARCH_CLOCKSOURCE_DATA
 	select ARCH_DISCARD_MEMBLOCK
-	select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
+	select ARCH_HAS_ACPI_TABLE_UPGRADE	if ACPI
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_FAST_MULTIPLIER
 	select ARCH_HAS_GCOV_PROFILE_ALL
-	select ARCH_HAS_GIGANTIC_PAGE		if X86_64
 	select ARCH_HAS_KCOV			if X86_64
-	select ARCH_HAS_PMEM_API		if X86_64
 	select ARCH_HAS_MMIO_FLUSH
+	select ARCH_HAS_PMEM_API		if X86_64
 	select ARCH_HAS_SG_CHAIN
 	select ARCH_HAS_UBSAN_SANITIZE_ALL
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
@@ -39,23 +61,17 @@ config X86
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select ARCH_SUPPORTS_ATOMIC_RMW
 	select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
-	select ARCH_SUPPORTS_INT128		if X86_64
 	select ARCH_SUPPORTS_NUMA_BALANCING	if X86_64
 	select ARCH_USE_BUILTIN_BSWAP
-	select ARCH_USE_CMPXCHG_LOCKREF		if X86_64
 	select ARCH_USE_QUEUED_RWLOCKS
 	select ARCH_USE_QUEUED_SPINLOCKS
 	select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH if SMP
-	select ARCH_WANTS_DYNAMIC_TASK_STRUCT
 	select ARCH_WANT_FRAME_POINTERS
-	select ARCH_WANT_IPC_PARSE_VERSION	if X86_32
+	select ARCH_WANTS_DYNAMIC_TASK_STRUCT
 	select BUILDTIME_EXTABLE_SORT
 	select CLKEVT_I8253
-	select CLKSRC_I8253			if X86_32
 	select CLOCKSOURCE_VALIDATE_LAST_CYCLE
 	select CLOCKSOURCE_WATCHDOG
-	select CLONE_BACKWARDS			if X86_32
-	select COMPAT_OLD_SIGACTION		if IA32_EMULATION
 	select DCACHE_WORD_ACCESS
 	select EDAC_ATOMIC_SCRUB
 	select EDAC_SUPPORT
@@ -77,7 +93,6 @@ config X86
 	select HAVE_ACPI_APEI			if ACPI
 	select HAVE_ACPI_APEI_NMI		if ACPI
 	select HAVE_ALIGNED_STRUCT_PAGE		if SLUB
-	select HAVE_AOUT			if X86_32
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_HARDENED_USERCOPY
 	select HAVE_ARCH_HUGE_VMAP		if X86_64 || X86_PAE
@@ -88,12 +103,10 @@ config X86
 	select HAVE_ARCH_MMAP_RND_BITS		if MMU
 	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if MMU && COMPAT
 	select HAVE_ARCH_SECCOMP_FILTER
-	select HAVE_ARCH_SOFT_DIRTY		if X86_64
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
-	select HAVE_ARCH_WITHIN_STACK_FRAMES
-	select HAVE_EBPF_JIT			if X86_64
 	select HAVE_ARCH_VMAP_STACK		if X86_64
+	select HAVE_ARCH_WITHIN_STACK_FRAMES
 	select HAVE_CC_STACKPROTECTOR
 	select HAVE_CMPXCHG_DOUBLE
 	select HAVE_CMPXCHG_LOCAL
@@ -106,6 +119,7 @@ config X86
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
+	select HAVE_EBPF_JIT			if X86_64
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
 	select HAVE_EXIT_THREAD
 	select HAVE_FENTRY			if X86_64
@@ -113,7 +127,6 @@ config X86
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_FUNCTION_TRACER
 	select HAVE_GCC_PLUGINS
-	select HAVE_GENERIC_DMA_COHERENT	if X86_32
 	select HAVE_HW_BREAKPOINT
 	select HAVE_IDE
 	select HAVE_IOREMAP_PROT
@@ -142,15 +155,11 @@ config X86
 	select HAVE_PERF_REGS
 	select HAVE_PERF_USER_STACK_DUMP
 	select HAVE_REGS_AND_STACK_ACCESS_API
+	select HAVE_STACK_VALIDATION		if X86_64
 	select HAVE_SYSCALL_TRACEPOINTS
-	select HAVE_UID16			if X86_32 || IA32_EMULATION
 	select HAVE_UNSTABLE_SCHED_CLOCK
 	select HAVE_USER_RETURN_NOTIFIER
 	select IRQ_FORCED_THREADING
-	select MODULES_USE_ELF_RELA		if X86_64
-	select MODULES_USE_ELF_REL		if X86_32
-	select OLD_SIGACTION			if X86_32
-	select OLD_SIGSUSPEND3			if X86_32 || IA32_EMULATION
 	select PERF_EVENTS
 	select RTC_LIB
 	select RTC_MC146818_LIB
@@ -160,11 +169,7 @@ config X86
 	select THREAD_INFO_IN_TASK
 	select USER_STACKTRACE_SUPPORT
 	select VIRT_TO_BUS
-	select X86_DEV_DMA_OPS			if X86_64
 	select X86_FEATURE_NAMES		if PROC_FS
-	select HAVE_STACK_VALIDATION		if X86_64
-	select ARCH_USES_HIGH_VMA_FLAGS		if X86_INTEL_MEMORY_PROTECTION_KEYS
-	select ARCH_HAS_PKEYS			if X86_INTEL_MEMORY_PROTECTION_KEYS
 
 config INSTRUCTION_DECODER
 	def_bool y
@@ -407,6 +412,19 @@ config GOLDFISH
        def_bool y
        depends on X86_GOLDFISH
 
+config INTEL_RDT_A
+	bool "Intel Resource Director Technology Allocation support"
+	default n
+	depends on X86 && CPU_SUP_INTEL
+	select KERNFS
+	help
+	  Select to enable resource allocation which is a sub-feature of
+	  Intel Resource Director Technology(RDT). More information about
+	  RDT can be found in the Intel x86 Architecture Software
+	  Developer Manual.
+
+	  Say N if unsure.
+
 if X86_32
 config X86_EXTENDED_PLATFORM
 	bool "Support for extended (non-PC) x86 platforms"
@@ -550,18 +568,6 @@ config X86_INTEL_QUARK
 	  Say Y here if you have a Quark based system such as the Arduino
 	  compatible Intel Galileo.
 
-config MLX_PLATFORM
-	tristate "Mellanox Technologies platform support"
-	depends on X86_64
-	depends on X86_EXTENDED_PLATFORM
-	---help---
-	  This option enables system support for the Mellanox Technologies
-	  platform.
-
-	  Say Y here if you are building a kernel for Mellanox system.
-
-	  Otherwise, say N.
-
 config X86_INTEL_LPSS
 	bool "Intel Low Power Subsystem Support"
 	depends on X86 && ACPI
@@ -939,6 +945,27 @@ config SCHED_MC
 	  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_MC_PRIO
+	bool "CPU core priorities scheduler support"
+	depends on SCHED_MC && CPU_SUP_INTEL
+	select X86_INTEL_PSTATE
+	select CPU_FREQ
+	default y
+	---help---
+	  Intel Turbo Boost Max Technology 3.0 enabled CPUs have a
+	  core ordering determined at manufacturing time, which allows
+	  certain cores to reach higher turbo frequencies (when running
+	  single threaded workloads) than others.
+
+	  Enabling this kernel feature teaches the scheduler about
+	  the TBM3 (aka ITMT) priority order of the CPU cores and adjusts the
+	  scheduler's CPU selection logic accordingly, so that higher
+	  overall system performance can be achieved.
+
+	  This feature will have no effect on CPUs without this feature.
+
+	  If unsure say Y here.
+
 source "kernel/Kconfig.preempt"
 
 config UP_LATE_INIT
@@ -1025,7 +1052,7 @@ config X86_MCE_INTEL
 config X86_MCE_AMD
 	def_bool y
 	prompt "AMD MCE features"
-	depends on X86_MCE && X86_LOCAL_APIC
+	depends on X86_MCE && X86_LOCAL_APIC && AMD_NB
 	---help---
 	   Additional support for AMD specific MCE features such as
 	   the DRAM Error Threshold.
@@ -1525,7 +1552,7 @@ config X86_CHECK_BIOS_CORRUPTION
 	  line.  By default it scans the low 64k of memory every 60
 	  seconds; see the memory_corruption_check_size and
 	  memory_corruption_check_period parameters in
-	  Documentation/kernel-parameters.txt to adjust this.
+	  Documentation/admin-guide/kernel-parameters.rst to adjust this.
 
 	  When enabled with the default parameters, this option has
 	  almost no overhead, as it reserves a relatively small amount
@@ -1737,6 +1764,8 @@ config X86_INTEL_MEMORY_PROTECTION_KEYS
 	def_bool y
 	# Note: only available in 64-bit mode
 	depends on CPU_SUP_INTEL && X86_64
+	select ARCH_USES_HIGH_VMA_FLAGS
+	select ARCH_HAS_PKEYS
 	---help---
 	  Memory Protection Keys provides a mechanism for enforcing
 	  page-based protections, but without requiring modification of the
@@ -2092,7 +2121,7 @@ config DEBUG_HOTPLUG_CPU0
 config COMPAT_VDSO
 	def_bool n
 	prompt "Disable the 32-bit vDSO (needed for glibc 2.3.3)"
-	depends on X86_32 || IA32_EMULATION
+	depends on COMPAT_32
 	---help---
 	  Certain buggy versions of glibc will crash if they are
 	  presented with a 32-bit vDSO that is not mapped at the address
@@ -2694,9 +2723,10 @@ source "fs/Kconfig.binfmt"
 config IA32_EMULATION
 	bool "IA32 Emulation"
 	depends on X86_64
+	select ARCH_WANT_OLD_COMPAT_IPC
 	select BINFMT_ELF
 	select COMPAT_BINFMT_ELF
-	select ARCH_WANT_OLD_COMPAT_IPC
+	select COMPAT_OLD_SIGACTION
 	---help---
 	  Include code to run legacy 32-bit programs under a
 	  64-bit kernel. You should likely turn this on, unless you're
@@ -2721,6 +2751,12 @@ config X86_X32
 	  elf32_x86_64 support enabled to compile a kernel with this
 	  option set.
 
+config COMPAT_32
+	def_bool y
+	depends on IA32_EMULATION || X86_32
+	select HAVE_UID16
+	select OLD_SIGSUSPEND3
+
 config COMPAT
 	def_bool y
 	depends on IA32_EMULATION || X86_X32
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/acpi/apei.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/acpi/apei.c
--- linux-libre-4.9-gnu/arch/x86/kernel/acpi/apei.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/acpi/apei.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,9 +24,6 @@ int arch_apei_enable_cmcff(struct acpi_h
 	struct acpi_hest_ia_corrected *cmc;
 	struct acpi_hest_ia_error_bank *mc_bank;
 
-	if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
-		return 0;
-
 	cmc = (struct acpi_hest_ia_corrected *)hest_hdr;
 	if (!cmc->enabled)
 		return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/acpi/boot.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/acpi/boot.c
--- linux-libre-4.9-gnu/arch/x86/kernel/acpi/boot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/acpi/boot.c	2017-02-12 16:03:20.000000000 -0500
@@ -76,6 +76,7 @@ int acpi_fix_pin2_polarity __initdata;
 static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
 #endif
 
+#ifdef CONFIG_X86_IO_APIC
 /*
  * Locks related to IOAPIC hotplug
  * Hotplug side:
@@ -88,6 +89,7 @@ static u64 acpi_lapic_addr __initdata =
  *			->ioapic_lock
  */
 static DEFINE_MUTEX(acpi_ioapic_lock);
+#endif
 
 /* --------------------------------------------------------------------------
                               Boot-time Configuration
@@ -713,7 +715,7 @@ int acpi_map_cpu2node(acpi_handle handle
 	int nid;
 
 	nid = acpi_get_node(handle);
-	if (nid != -1) {
+	if (nid != NUMA_NO_NODE) {
 		set_apicid_to_node(physid, nid);
 		numa_set_node(cpu, nid);
 	}
@@ -928,6 +930,13 @@ static int __init acpi_parse_fadt(struct
 		x86_platform.legacy.devices.pnpbios = 0;
 	}
 
+	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
+	    !(acpi_gbl_FADT.boot_flags & ACPI_FADT_8042) &&
+	    x86_platform.legacy.i8042 != X86_LEGACY_I8042_PLATFORM_ABSENT) {
+		pr_debug("ACPI: i8042 controller is absent\n");
+		x86_platform.legacy.i8042 = X86_LEGACY_I8042_FIRMWARE_ABSENT;
+	}
+
 	if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
 		pr_debug("ACPI: not registering RTC platform device\n");
 		x86_platform.legacy.rtc = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/acpi/wakeup_64.S linux-libre-4.10-rc8-gnu/arch/x86/kernel/acpi/wakeup_64.S
--- linux-libre-4.9-gnu/arch/x86/kernel/acpi/wakeup_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/acpi/wakeup_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -109,6 +109,15 @@ ENTRY(do_suspend_lowlevel)
 	movq	pt_regs_r14(%rax), %r14
 	movq	pt_regs_r15(%rax), %r15
 
+#ifdef CONFIG_KASAN
+	/*
+	 * The suspend path may have poisoned some areas deeper in the stack,
+	 * which we now need to unpoison.
+	 */
+	movq	%rsp, %rdi
+	call	kasan_unpoison_task_stack_below
+#endif
+
 	xorl	%eax, %eax
 	addq	$8, %rsp
 	FRAME_END
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/alternative.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/alternative.c
--- linux-libre-4.9-gnu/arch/x86/kernel/alternative.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/alternative.c	2017-02-12 16:03:20.000000000 -0500
@@ -337,7 +337,11 @@ done:
 		n_dspl, (unsigned long)orig_insn + n_dspl + repl_len);
 }
 
-static void __init_or_module optimize_nops(struct alt_instr *a, u8 *instr)
+/*
+ * "noinline" to cause control flow change and thus invalidate I$ and
+ * cause refetch after modification.
+ */
+static void __init_or_module noinline optimize_nops(struct alt_instr *a, u8 *instr)
 {
 	unsigned long flags;
 
@@ -346,7 +350,6 @@ static void __init_or_module optimize_no
 
 	local_irq_save(flags);
 	add_nops(instr + (a->instrlen - a->padlen), a->padlen);
-	sync_core();
 	local_irq_restore(flags);
 
 	DUMP_BYTES(instr, a->instrlen, "%p: [%d:%d) optimized NOPs: ",
@@ -359,9 +362,12 @@ static void __init_or_module optimize_no
  * This implies that asymmetric systems where APs have less capabilities than
  * the boot processor are not handled. Tough. Make sure you disable such
  * features by hand.
+ *
+ * Marked "noinline" to cause control flow change and thus insn cache
+ * to refetch changed I$ lines.
  */
-void __init_or_module apply_alternatives(struct alt_instr *start,
-					 struct alt_instr *end)
+void __init_or_module noinline apply_alternatives(struct alt_instr *start,
+						  struct alt_instr *end)
 {
 	struct alt_instr *a;
 	u8 *instr, *replacement;
@@ -667,7 +673,6 @@ void *__init_or_module text_poke_early(v
 	unsigned long flags;
 	local_irq_save(flags);
 	memcpy(addr, opcode, len);
-	sync_core();
 	local_irq_restore(flags);
 	/* Could also do a CLFLUSH here to speed up CPU recovery; but
 	   that causes hangs on some VIA CPUs. */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/amd_nb.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/amd_nb.c
--- linux-libre-4.9-gnu/arch/x86/kernel/amd_nb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/amd_nb.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,8 +13,20 @@
 #include <linux/spinlock.h>
 #include <asm/amd_nb.h>
 
+#define PCI_DEVICE_ID_AMD_17H_ROOT	0x1450
+#define PCI_DEVICE_ID_AMD_17H_DF_F3	0x1463
+#define PCI_DEVICE_ID_AMD_17H_DF_F4	0x1464
+
+/* Protect the PCI config register pairs used for SMN and DF indirect access. */
+static DEFINE_MUTEX(smn_mutex);
+
 static u32 *flush_words;
 
+static const struct pci_device_id amd_root_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) },
+	{}
+};
+
 const struct pci_device_id amd_nb_misc_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
@@ -24,9 +36,10 @@ const struct pci_device_id amd_nb_misc_i
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
 	{}
 };
-EXPORT_SYMBOL(amd_nb_misc_ids);
+EXPORT_SYMBOL_GPL(amd_nb_misc_ids);
 
 static const struct pci_device_id amd_nb_link_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
@@ -34,6 +47,7 @@ static const struct pci_device_id amd_nb
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
 	{}
 };
 
@@ -44,8 +58,25 @@ const struct amd_nb_bus_dev_range amd_nb
 	{ }
 };
 
-struct amd_northbridge_info amd_northbridges;
-EXPORT_SYMBOL(amd_northbridges);
+static struct amd_northbridge_info amd_northbridges;
+
+u16 amd_nb_num(void)
+{
+	return amd_northbridges.num;
+}
+EXPORT_SYMBOL_GPL(amd_nb_num);
+
+bool amd_nb_has_feature(unsigned int feature)
+{
+	return ((amd_northbridges.flags & feature) == feature);
+}
+EXPORT_SYMBOL_GPL(amd_nb_has_feature);
+
+struct amd_northbridge *node_to_amd_nb(int node)
+{
+	return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] : NULL;
+}
+EXPORT_SYMBOL_GPL(node_to_amd_nb);
 
 static struct pci_dev *next_northbridge(struct pci_dev *dev,
 					const struct pci_device_id *ids)
@@ -58,13 +89,106 @@ static struct pci_dev *next_northbridge(
 	return dev;
 }
 
+static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
+{
+	struct pci_dev *root;
+	int err = -ENODEV;
+
+	if (node >= amd_northbridges.num)
+		goto out;
+
+	root = node_to_amd_nb(node)->root;
+	if (!root)
+		goto out;
+
+	mutex_lock(&smn_mutex);
+
+	err = pci_write_config_dword(root, 0x60, address);
+	if (err) {
+		pr_warn("Error programming SMN address 0x%x.\n", address);
+		goto out_unlock;
+	}
+
+	err = (write ? pci_write_config_dword(root, 0x64, *value)
+		     : pci_read_config_dword(root, 0x64, value));
+	if (err)
+		pr_warn("Error %s SMN address 0x%x.\n",
+			(write ? "writing to" : "reading from"), address);
+
+out_unlock:
+	mutex_unlock(&smn_mutex);
+
+out:
+	return err;
+}
+
+int amd_smn_read(u16 node, u32 address, u32 *value)
+{
+	return __amd_smn_rw(node, address, value, false);
+}
+EXPORT_SYMBOL_GPL(amd_smn_read);
+
+int amd_smn_write(u16 node, u32 address, u32 value)
+{
+	return __amd_smn_rw(node, address, &value, true);
+}
+EXPORT_SYMBOL_GPL(amd_smn_write);
+
+/*
+ * Data Fabric Indirect Access uses FICAA/FICAD.
+ *
+ * Fabric Indirect Configuration Access Address (FICAA): Constructed based
+ * on the device's Instance Id and the PCI function and register offset of
+ * the desired register.
+ *
+ * Fabric Indirect Configuration Access Data (FICAD): There are FICAD LO
+ * and FICAD HI registers but so far we only need the LO register.
+ */
+int amd_df_indirect_read(u16 node, u8 func, u16 reg, u8 instance_id, u32 *lo)
+{
+	struct pci_dev *F4;
+	u32 ficaa;
+	int err = -ENODEV;
+
+	if (node >= amd_northbridges.num)
+		goto out;
+
+	F4 = node_to_amd_nb(node)->link;
+	if (!F4)
+		goto out;
+
+	ficaa  = 1;
+	ficaa |= reg & 0x3FC;
+	ficaa |= (func & 0x7) << 11;
+	ficaa |= instance_id << 16;
+
+	mutex_lock(&smn_mutex);
+
+	err = pci_write_config_dword(F4, 0x5C, ficaa);
+	if (err) {
+		pr_warn("Error writing DF Indirect FICAA, FICAA=0x%x\n", ficaa);
+		goto out_unlock;
+	}
+
+	err = pci_read_config_dword(F4, 0x98, lo);
+	if (err)
+		pr_warn("Error reading DF Indirect FICAD LO, FICAA=0x%x.\n", ficaa);
+
+out_unlock:
+	mutex_unlock(&smn_mutex);
+
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(amd_df_indirect_read);
+
 int amd_cache_northbridges(void)
 {
 	u16 i = 0;
 	struct amd_northbridge *nb;
-	struct pci_dev *misc, *link;
+	struct pci_dev *root, *misc, *link;
 
-	if (amd_nb_num())
+	if (amd_northbridges.num)
 		return 0;
 
 	misc = NULL;
@@ -74,15 +198,17 @@ int amd_cache_northbridges(void)
 	if (!i)
 		return -ENODEV;
 
-	nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
+	nb = kcalloc(i, sizeof(struct amd_northbridge), GFP_KERNEL);
 	if (!nb)
 		return -ENOMEM;
 
 	amd_northbridges.nb = nb;
 	amd_northbridges.num = i;
 
-	link = misc = NULL;
-	for (i = 0; i != amd_nb_num(); i++) {
+	link = misc = root = NULL;
+	for (i = 0; i != amd_northbridges.num; i++) {
+		node_to_amd_nb(i)->root = root =
+			next_northbridge(root, amd_root_ids);
 		node_to_amd_nb(i)->misc = misc =
 			next_northbridge(misc, amd_nb_misc_ids);
 		node_to_amd_nb(i)->link = link =
@@ -139,13 +265,13 @@ struct resource *amd_get_mmconfig_range(
 {
 	u32 address;
 	u64 base, msr;
-	unsigned segn_busn_bits;
+	unsigned int segn_busn_bits;
 
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
 		return NULL;
 
 	/* assume all cpus from fam10h have mmconfig */
-        if (boot_cpu_data.x86 < 0x10)
+	if (boot_cpu_data.x86 < 0x10)
 		return NULL;
 
 	address = MSR_FAM10H_MMIO_CONF_BASE;
@@ -226,14 +352,14 @@ static void amd_cache_gart(void)
 	if (!amd_nb_has_feature(AMD_NB_GART))
 		return;
 
-	flush_words = kmalloc(amd_nb_num() * sizeof(u32), GFP_KERNEL);
+	flush_words = kmalloc_array(amd_northbridges.num, sizeof(u32), GFP_KERNEL);
 	if (!flush_words) {
 		amd_northbridges.flags &= ~AMD_NB_GART;
 		pr_notice("Cannot initialize GART flush words, GART support disabled\n");
 		return;
 	}
 
-	for (i = 0; i != amd_nb_num(); i++)
+	for (i = 0; i != amd_northbridges.num; i++)
 		pci_read_config_dword(node_to_amd_nb(i)->misc, 0x9c, &flush_words[i]);
 }
 
@@ -246,18 +372,20 @@ void amd_flush_garts(void)
 	if (!amd_nb_has_feature(AMD_NB_GART))
 		return;
 
-	/* Avoid races between AGP and IOMMU. In theory it's not needed
-	   but I'm not sure if the hardware won't lose flush requests
-	   when another is pending. This whole thing is so expensive anyways
-	   that it doesn't matter to serialize more. -AK */
+	/*
+	 * Avoid races between AGP and IOMMU. In theory it's not needed
+	 * but I'm not sure if the hardware won't lose flush requests
+	 * when another is pending. This whole thing is so expensive anyways
+	 * that it doesn't matter to serialize more. -AK
+	 */
 	spin_lock_irqsave(&gart_lock, flags);
 	flushed = 0;
-	for (i = 0; i < amd_nb_num(); i++) {
+	for (i = 0; i < amd_northbridges.num; i++) {
 		pci_write_config_dword(node_to_amd_nb(i)->misc, 0x9c,
 				       flush_words[i] | 1);
 		flushed++;
 	}
-	for (i = 0; i < amd_nb_num(); i++) {
+	for (i = 0; i < amd_northbridges.num; i++) {
 		u32 w;
 		/* Make sure the hardware actually executed the flush*/
 		for (;;) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/apb_timer.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/apb_timer.c
--- linux-libre-4.9-gnu/arch/x86/kernel/apb_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/apb_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -234,7 +234,7 @@ static __init int apbt_late_init(void)
 	if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ||
 		!apb_timer_block_enabled)
 		return 0;
-	return cpuhp_setup_state(CPUHP_X86_APB_DEAD, "X86_APB_DEAD", NULL,
+	return cpuhp_setup_state(CPUHP_X86_APB_DEAD, "x86/apb:dead", NULL,
 				 apbt_cpu_dead);
 }
 fs_initcall(apbt_late_init);
@@ -247,7 +247,7 @@ void apbt_setup_secondary_clock(void) {}
 static int apbt_clocksource_register(void)
 {
 	u64 start, now;
-	cycle_t t1;
+	u64 t1;
 
 	/* Start the counter, use timer 2 as source, timer 0/1 for event */
 	dw_apb_clocksource_start(clocksource_apbt);
@@ -355,7 +355,7 @@ unsigned long apbt_quick_calibrate(void)
 {
 	int i, scale;
 	u64 old, new;
-	cycle_t t1, t2;
+	u64 t1, t2;
 	unsigned long khz = 0;
 	u32 loop, shift;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/apic/apic.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/apic/apic.c
--- linux-libre-4.9-gnu/arch/x86/kernel/apic/apic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/apic/apic.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,6 @@
 #include <asm/io_apic.h>
 #include <asm/desc.h>
 #include <asm/hpet.h>
-#include <asm/idle.h>
 #include <asm/mtrr.h>
 #include <asm/time.h>
 #include <asm/smp.h>
@@ -894,11 +893,13 @@ void __init setup_boot_APIC_clock(void)
 
 	/* Setup the lapic or request the broadcast */
 	setup_APIC_timer();
+	amd_e400_c1e_apic_setup();
 }
 
 void setup_secondary_APIC_clock(void)
 {
 	setup_APIC_timer();
+	amd_e400_c1e_apic_setup();
 }
 
 /*
@@ -2159,21 +2160,6 @@ int __generic_processor_info(int apicid,
 	}
 
 	/*
-	 * This can happen on physical hotplug. The sanity check at boot time
-	 * is done from native_smp_prepare_cpus() after num_possible_cpus() is
-	 * established.
-	 */
-	if (topology_update_package_map(apicid, cpu) < 0) {
-		int thiscpu = max + disabled_cpus;
-
-		pr_warning("APIC: Package limit reached. Processor %d/0x%x ignored.\n",
-			   thiscpu, apicid);
-
-		disabled_cpus++;
-		return -ENOSPC;
-	}
-
-	/*
 	 * Validate version
 	 */
 	if (version == 0x0) {
@@ -2263,6 +2249,7 @@ void __init apic_set_eoi_write(void (*eo
 	for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
 		/* Should happen once for each apic */
 		WARN_ON((*drv)->eoi_write == eoi_write);
+		(*drv)->native_eoi_write = (*drv)->eoi_write;
 		(*drv)->eoi_write = eoi_write;
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-4.9-gnu/arch/x86/kernel/apic/io_apic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/apic/io_apic.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,6 @@
 #include <linux/bootmem.h>
 
 #include <asm/irqdomain.h>
-#include <asm/idle.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/cpu.h>
@@ -2116,6 +2115,7 @@ static inline void __init check_timer(vo
 			if (idx != -1 && irq_trigger(idx))
 				unmask_ioapic_irq(irq_get_chip_data(0));
 		}
+		irq_domain_deactivate_irq(irq_data);
 		irq_domain_activate_irq(irq_data);
 		if (timer_irq_works()) {
 			if (disable_timer_pin_1 > 0)
@@ -2137,6 +2137,7 @@ static inline void __init check_timer(vo
 		 * legacy devices should be connected to IO APIC #0
 		 */
 		replace_pin_at_irq_node(data, node, apic1, pin1, apic2, pin2);
+		irq_domain_deactivate_irq(irq_data);
 		irq_domain_activate_irq(irq_data);
 		legacy_pic->unmask(0);
 		if (timer_irq_works()) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/apic/x2apic_cluster.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/apic/x2apic_cluster.c
--- linux-libre-4.9-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2017-02-12 16:03:20.000000000 -0500
@@ -191,7 +191,7 @@ static int x2apic_cluster_probe(void)
 	if (!x2apic_mode)
 		return 0;
 
-	ret = cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "X2APIC_PREPARE",
+	ret = cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "x86/x2apic:prepare",
 				x2apic_prepare_cpu, x2apic_dead_cpu);
 	if (ret < 0) {
 		pr_err("Failed to register X2APIC_PREPARE\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/apm_32.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/apm_32.c
--- linux-libre-4.9-gnu/arch/x86/kernel/apm_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/apm_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -234,7 +234,7 @@
 #include <linux/i8253.h>
 #include <linux/cpuidle.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/desc.h>
 #include <asm/olpc.h>
 #include <asm/paravirt.h>
@@ -906,14 +906,14 @@ static int apm_cpu_idle(struct cpuidle_d
 	static int use_apm_idle; /* = 0 */
 	static unsigned int last_jiffies; /* = 0 */
 	static unsigned int last_stime; /* = 0 */
-	cputime_t stime;
+	cputime_t stime, utime;
 
 	int apm_idle_done = 0;
 	unsigned int jiffies_since_last_check = jiffies - last_jiffies;
 	unsigned int bucket;
 
 recalc:
-	task_cputime(current, NULL, &stime);
+	task_cputime(current, &utime, &stime);
 	if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
 		use_apm_idle = 0;
 	} else if (jiffies_since_last_check > idle_period) {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/amd.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/amd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/amd.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,10 @@
 
 #include "cpu.h"
 
+static const int amd_erratum_383[];
+static const int amd_erratum_400[];
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
+
 /*
  * nodes_per_socket: Stores the number of nodes per socket.
  * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
@@ -308,17 +312,43 @@ static void amd_get_topology(struct cpui
 		u32 eax, ebx, ecx, edx;
 
 		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
-		node_id = ecx & 7;
 
-		/* get compute unit information */
-		smp_num_siblings = ((ebx >> 8) & 3) + 1;
-		c->x86_max_cores /= smp_num_siblings;
-		c->cpu_core_id = ebx & 0xff;
+		node_id  = ecx & 0xff;
+		smp_num_siblings = ((ebx >> 8) & 0xff) + 1;
+
+		if (c->x86 == 0x15)
+			c->cu_id = ebx & 0xff;
+
+		if (c->x86 >= 0x17) {
+			c->cpu_core_id = ebx & 0xff;
+
+			if (smp_num_siblings > 1)
+				c->x86_max_cores /= smp_num_siblings;
+		}
+
+		/*
+		 * We may have multiple LLCs if L3 caches exist, so check if we
+		 * have an L3 cache by looking at the L3 cache CPUID leaf.
+		 */
+		if (cpuid_edx(0x80000006)) {
+			if (c->x86 == 0x17) {
+				/*
+				 * LLC is at the core complex level.
+				 * Core complex id is ApicId[3].
+				 */
+				per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
+			} else {
+				/* LLC is at the node level. */
+				per_cpu(cpu_llc_id, cpu) = node_id;
+			}
+		}
 	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
 		u64 value;
 
 		rdmsrl(MSR_FAM10H_NODE_ID, value);
 		node_id = value & 7;
+
+		per_cpu(cpu_llc_id, cpu) = node_id;
 	} else
 		return;
 
@@ -329,9 +359,6 @@ static void amd_get_topology(struct cpui
 		set_cpu_cap(c, X86_FEATURE_AMD_DCM);
 		cus_per_node = c->x86_max_cores / nodes_per_socket;
 
-		/* store NodeID, use llc_shared_map to store sibling info */
-		per_cpu(cpu_llc_id, cpu) = node_id;
-
 		/* core id has to be in the [0 .. cores_per_node - 1] range */
 		c->cpu_core_id %= cus_per_node;
 	}
@@ -356,15 +383,6 @@ static void amd_detect_cmp(struct cpuinf
 	/* use socket ID also for last level cache */
 	per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
 	amd_get_topology(c);
-
-	/*
-	 * Fix percpu cpu_llc_id here as LLC topology is different
-	 * for Fam17h systems.
-	 */
-	 if (c->x86 != 0x17 || !cpuid_edx(0x80000006))
-		return;
-
-	per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
 #endif
 }
 
@@ -585,11 +603,16 @@ static void early_init_amd(struct cpuinf
 	/* F16h erratum 793, CVE-2013-6885 */
 	if (c->x86 == 0x16 && c->x86_model <= 0xf)
 		msr_set_bit(MSR_AMD64_LS_CFG, 15);
-}
 
-static const int amd_erratum_383[];
-static const int amd_erratum_400[];
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
+	/*
+	 * Check whether the machine is affected by erratum 400. This is
+	 * used to select the proper idle routine and to enable the check
+	 * whether the machine is affected in arch_post_acpi_init(), which
+	 * sets the X86_BUG_AMD_APIC_C1E bug depending on the MSR check.
+	 */
+	if (cpu_has_amd_erratum(c, amd_erratum_400))
+		set_cpu_bug(c, X86_BUG_AMD_E400);
+}
 
 static void init_amd_k8(struct cpuinfo_x86 *c)
 {
@@ -770,9 +793,6 @@ static void init_amd(struct cpuinfo_x86
 	if (c->x86 > 0x11)
 		set_cpu_cap(c, X86_FEATURE_ARAT);
 
-	if (cpu_has_amd_erratum(c, amd_erratum_400))
-		set_cpu_bug(c, X86_BUG_AMD_APIC_C1E);
-
 	rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
 
 	/* 3DNow or LM implies PREFETCHW */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/bugs_64.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/bugs_64.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/bugs_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/bugs_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,33 +0,0 @@
-/*
- *  Copyright (C) 1994  Linus Torvalds
- *  Copyright (C) 2000  SuSE
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/alternative.h>
-#include <asm/bugs.h>
-#include <asm/processor.h>
-#include <asm/mtrr.h>
-#include <asm/cacheflush.h>
-
-void __init check_bugs(void)
-{
-	identify_boot_cpu();
-#if !defined(CONFIG_SMP)
-	pr_info("CPU: ");
-	print_cpu_info(&boot_cpu_data);
-#endif
-	alternative_instructions();
-
-	/*
-	 * Make sure the first 2MB area is not mapped by huge pages
-	 * There are typically fixed size MTRRs in there and overlapping
-	 * MTRRs into large pages causes slow downs.
-	 *
-	 * Right now we don't do that with gbpages because there seems
-	 * very little benefit for that case.
-	 */
-	if (!direct_gbpages)
-		set_memory_4k((unsigned long)__va(0), 1);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/bugs.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/bugs.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/bugs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/bugs.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,15 +16,19 @@
 #include <asm/msr.h>
 #include <asm/paravirt.h>
 #include <asm/alternative.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
 
 void __init check_bugs(void)
 {
 	identify_boot_cpu();
-#ifndef CONFIG_SMP
-	pr_info("CPU: ");
-	print_cpu_info(&boot_cpu_data);
-#endif
 
+	if (!IS_ENABLED(CONFIG_SMP)) {
+		pr_info("CPU: ");
+		print_cpu_info(&boot_cpu_data);
+	}
+
+#ifdef CONFIG_X86_32
 	/*
 	 * Check whether we are able to run this kernel safely on SMP.
 	 *
@@ -40,4 +44,18 @@ void __init check_bugs(void)
 	alternative_instructions();
 
 	fpu__init_check_bugs();
+#else /* CONFIG_X86_64 */
+	alternative_instructions();
+
+	/*
+	 * Make sure the first 2MB area is not mapped by huge pages
+	 * There are typically fixed size MTRRs in there and overlapping
+	 * MTRRs into large pages causes slow downs.
+	 *
+	 * Right now we don't do that with gbpages because there seems
+	 * very little benefit for that case.
+	 */
+	if (!direct_gbpages)
+		set_memory_4k((unsigned long)__va(0), 1);
+#endif
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/common.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/common.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/common.c	2017-02-12 16:03:20.000000000 -0500
@@ -667,13 +667,14 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
 		c->x86_capability[CPUID_1_EDX] = edx;
 	}
 
+	/* Thermal and Power Management Leaf: level 0x00000006 (eax) */
+	if (c->cpuid_level >= 0x00000006)
+		c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006);
+
 	/* Additional Intel-defined flags: level 0x00000007 */
 	if (c->cpuid_level >= 0x00000007) {
 		cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
-
 		c->x86_capability[CPUID_7_0_EBX] = ebx;
-
-		c->x86_capability[CPUID_6_EAX] = cpuid_eax(0x00000006);
 		c->x86_capability[CPUID_7_ECX] = ecx;
 	}
 
@@ -979,29 +980,21 @@ static void x86_init_cache_qos(struct cp
 }
 
 /*
- * The physical to logical package id mapping is initialized from the
- * acpi/mptables information. Make sure that CPUID actually agrees with
- * that.
+ * Validate that ACPI/mptables have the same information about the
+ * effective APIC id and update the package map.
  */
-static void sanitize_package_id(struct cpuinfo_x86 *c)
+static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
-	unsigned int pkg, apicid, cpu = smp_processor_id();
+	unsigned int apicid, cpu = smp_processor_id();
 
 	apicid = apic->cpu_present_to_apicid(cpu);
-	pkg = apicid >> boot_cpu_data.x86_coreid_bits;
 
-	if (apicid != c->initial_apicid) {
-		pr_err(FW_BUG "CPU%u: APIC id mismatch. Firmware: %x CPUID: %x\n",
+	if (apicid != c->apicid) {
+		pr_err(FW_BUG "CPU%u: APIC id mismatch. Firmware: %x APIC: %x\n",
 		       cpu, apicid, c->initial_apicid);
-		c->initial_apicid = apicid;
-	}
-	if (pkg != c->phys_proc_id) {
-		pr_err(FW_BUG "CPU%u: Using firmware package id %u instead of %u\n",
-		       cpu, pkg, c->phys_proc_id);
-		c->phys_proc_id = pkg;
 	}
-	c->logical_proc_id = topology_phys_to_logical_pkg(pkg);
+	BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
 #else
 	c->logical_proc_id = 0;
 #endif
@@ -1022,6 +1015,7 @@ static void identify_cpu(struct cpuinfo_
 	c->x86_model_id[0] = '\0';  /* Unset */
 	c->x86_max_cores = 1;
 	c->x86_coreid_bits = 0;
+	c->cu_id = 0xff;
 #ifdef CONFIG_X86_64
 	c->x86_clflush_size = 64;
 	c->x86_phys_bits = 36;
@@ -1132,7 +1126,6 @@ static void identify_cpu(struct cpuinfo_
 #ifdef CONFIG_NUMA
 	numa_add_cpu(smp_processor_id());
 #endif
-	sanitize_package_id(c);
 }
 
 /*
@@ -1172,7 +1165,6 @@ void enable_sep_cpu(void)
 void __init identify_boot_cpu(void)
 {
 	identify_cpu(&boot_cpu_data);
-	init_amd_e400_c1e_mask();
 #ifdef CONFIG_X86_32
 	sysenter_setup();
 	enable_sep_cpu();
@@ -1188,53 +1180,9 @@ void identify_secondary_cpu(struct cpuin
 	enable_sep_cpu();
 #endif
 	mtrr_ap_init();
+	validate_apic_and_package_id(c);
 }
 
-struct msr_range {
-	unsigned	min;
-	unsigned	max;
-};
-
-static const struct msr_range msr_range_array[] = {
-	{ 0x00000000, 0x00000418},
-	{ 0xc0000000, 0xc000040b},
-	{ 0xc0010000, 0xc0010142},
-	{ 0xc0011000, 0xc001103b},
-};
-
-static void __print_cpu_msr(void)
-{
-	unsigned index_min, index_max;
-	unsigned index;
-	u64 val;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msr_range_array); i++) {
-		index_min = msr_range_array[i].min;
-		index_max = msr_range_array[i].max;
-
-		for (index = index_min; index < index_max; index++) {
-			if (rdmsrl_safe(index, &val))
-				continue;
-			pr_info(" MSR%08x: %016llx\n", index, val);
-		}
-	}
-}
-
-static int show_msr;
-
-static __init int setup_show_msr(char *arg)
-{
-	int num;
-
-	get_option(&arg, &num);
-
-	if (num > 0)
-		show_msr = num;
-	return 1;
-}
-__setup("show_msr=", setup_show_msr);
-
 static __init int setup_noclflush(char *arg)
 {
 	setup_clear_cpu_cap(X86_FEATURE_CLFLUSH);
@@ -1268,21 +1216,13 @@ void print_cpu_info(struct cpuinfo_x86 *
 		pr_cont(", stepping: 0x%x)\n", c->x86_mask);
 	else
 		pr_cont(")\n");
-
-	print_cpu_msr(c);
-}
-
-void print_cpu_msr(struct cpuinfo_x86 *c)
-{
-	if (c->cpu_index < show_msr)
-		__print_cpu_msr();
 }
 
 static __init int setup_disablecpuid(char *arg)
 {
 	int bit;
 
-	if (get_option(&arg, &bit) && bit < NCAPINTS*32)
+	if (get_option(&arg, &bit) && bit >= 0 && bit < NCAPINTS * 32)
 		setup_clear_cpu_cap(bit);
 	else
 		return 0;
@@ -1490,11 +1430,8 @@ void cpu_init(void)
 	 */
 	cr4_init_shadow();
 
-	/*
-	 * Load microcode on this cpu if a valid microcode is available.
-	 * This is early microcode loading procedure.
-	 */
-	load_ucode_ap();
+	if (cpu)
+		load_ucode_ap();
 
 	t = &per_cpu(cpu_tss, cpu);
 	oist = &per_cpu(orig_ist, cpu);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
 #include <asm/bugs.h>
 #include <asm/cpu.h>
 #include <asm/intel-family.h>
+#include <asm/microcode_intel.h>
 
 #ifdef CONFIG_X86_64
 #include <linux/topology.h>
@@ -78,14 +79,8 @@ static void early_init_intel(struct cpui
 		(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);
-	}
+	if (c->x86 >= 6 && !cpu_has(c, X86_FEATURE_IA64))
+		c->microcode = intel_get_microcode_revision();
 
 	/*
 	 * Atom erratum AAE44/AAF40/AAG38/AAH41:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2017-02-12 16:03:20.000000000 -0500
@@ -153,6 +153,7 @@ struct _cpuid4_info_regs {
 	union _cpuid4_leaf_eax eax;
 	union _cpuid4_leaf_ebx ebx;
 	union _cpuid4_leaf_ecx ecx;
+	unsigned int id;
 	unsigned long size;
 	struct amd_northbridge *nb;
 };
@@ -894,6 +895,8 @@ static void __cache_cpumap_setup(unsigne
 static void ci_leaf_init(struct cacheinfo *this_leaf,
 			 struct _cpuid4_info_regs *base)
 {
+	this_leaf->id = base->id;
+	this_leaf->attributes = CACHE_ID;
 	this_leaf->level = base->eax.split.level;
 	this_leaf->type = cache_type_map[base->eax.split.type];
 	this_leaf->coherency_line_size =
@@ -920,6 +923,22 @@ static int __init_cache_level(unsigned i
 	return 0;
 }
 
+/*
+ * The max shared threads number comes from CPUID.4:EAX[25-14] with input
+ * ECX as cache index. Then right shift apicid by the number's order to get
+ * cache id for this cache node.
+ */
+static void get_cache_id(int cpu, struct _cpuid4_info_regs *id4_regs)
+{
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	unsigned long num_threads_sharing;
+	int index_msb;
+
+	num_threads_sharing = 1 + id4_regs->eax.split.num_threads_sharing;
+	index_msb = get_count_order(num_threads_sharing);
+	id4_regs->id = c->apicid >> index_msb;
+}
+
 static int __populate_cache_leaves(unsigned int cpu)
 {
 	unsigned int idx, ret;
@@ -931,9 +950,12 @@ static int __populate_cache_leaves(unsig
 		ret = cpuid4_cache_lookup_regs(idx, &id4_regs);
 		if (ret)
 			return ret;
+		get_cache_id(cpu, &id4_regs);
 		ci_leaf_init(this_leaf++, &id4_regs);
 		__cache_cpumap_setup(cpu, idx, &id4_regs);
 	}
+	this_cpu_ci->cpu_map_populated = true;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_rdt.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_rdt.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_rdt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_rdt.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,403 @@
+/*
+ * Resource Director Technology(RDT)
+ * - Cache Allocation code.
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Authors:
+ *    Fenghua Yu <fenghua.yu@intel.com>
+ *    Tony Luck <tony.luck@intel.com>
+ *    Vikas Shivappa <vikas.shivappa@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.
+ *
+ * More information about RDT be found in the Intel (R) x86 Architecture
+ * Software Developer Manual June 2016, volume 3, section 17.17.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/cacheinfo.h>
+#include <linux/cpuhotplug.h>
+
+#include <asm/intel-family.h>
+#include <asm/intel_rdt.h>
+
+/* Mutex to protect rdtgroup access. */
+DEFINE_MUTEX(rdtgroup_mutex);
+
+DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid);
+
+#define domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].domains)
+
+struct rdt_resource rdt_resources_all[] = {
+	{
+		.name		= "L3",
+		.domains	= domain_init(RDT_RESOURCE_L3),
+		.msr_base	= IA32_L3_CBM_BASE,
+		.min_cbm_bits	= 1,
+		.cache_level	= 3,
+		.cbm_idx_multi	= 1,
+		.cbm_idx_offset	= 0
+	},
+	{
+		.name		= "L3DATA",
+		.domains	= domain_init(RDT_RESOURCE_L3DATA),
+		.msr_base	= IA32_L3_CBM_BASE,
+		.min_cbm_bits	= 1,
+		.cache_level	= 3,
+		.cbm_idx_multi	= 2,
+		.cbm_idx_offset	= 0
+	},
+	{
+		.name		= "L3CODE",
+		.domains	= domain_init(RDT_RESOURCE_L3CODE),
+		.msr_base	= IA32_L3_CBM_BASE,
+		.min_cbm_bits	= 1,
+		.cache_level	= 3,
+		.cbm_idx_multi	= 2,
+		.cbm_idx_offset	= 1
+	},
+	{
+		.name		= "L2",
+		.domains	= domain_init(RDT_RESOURCE_L2),
+		.msr_base	= IA32_L2_CBM_BASE,
+		.min_cbm_bits	= 1,
+		.cache_level	= 2,
+		.cbm_idx_multi	= 1,
+		.cbm_idx_offset	= 0
+	},
+};
+
+static int cbm_idx(struct rdt_resource *r, int closid)
+{
+	return closid * r->cbm_idx_multi + r->cbm_idx_offset;
+}
+
+/*
+ * cache_alloc_hsw_probe() - Have to probe for Intel haswell server CPUs
+ * as they do not have CPUID enumeration support for Cache allocation.
+ * The check for Vendor/Family/Model is not enough to guarantee that
+ * the MSRs won't #GP fault because only the following SKUs support
+ * CAT:
+ *	Intel(R) Xeon(R)  CPU E5-2658  v3  @  2.20GHz
+ *	Intel(R) Xeon(R)  CPU E5-2648L v3  @  1.80GHz
+ *	Intel(R) Xeon(R)  CPU E5-2628L v3  @  2.00GHz
+ *	Intel(R) Xeon(R)  CPU E5-2618L v3  @  2.30GHz
+ *	Intel(R) Xeon(R)  CPU E5-2608L v3  @  2.00GHz
+ *	Intel(R) Xeon(R)  CPU E5-2658A v3  @  2.20GHz
+ *
+ * Probe by trying to write the first of the L3 cach mask registers
+ * and checking that the bits stick. Max CLOSids is always 4 and max cbm length
+ * is always 20 on hsw server parts. The minimum cache bitmask length
+ * allowed for HSW server is always 2 bits. Hardcode all of them.
+ */
+static inline bool cache_alloc_hsw_probe(void)
+{
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+	    boot_cpu_data.x86 == 6 &&
+	    boot_cpu_data.x86_model == INTEL_FAM6_HASWELL_X) {
+		struct rdt_resource *r  = &rdt_resources_all[RDT_RESOURCE_L3];
+		u32 l, h, max_cbm = BIT_MASK(20) - 1;
+
+		if (wrmsr_safe(IA32_L3_CBM_BASE, max_cbm, 0))
+			return false;
+		rdmsr(IA32_L3_CBM_BASE, l, h);
+
+		/* If all the bits were set in MSR, return success */
+		if (l != max_cbm)
+			return false;
+
+		r->num_closid = 4;
+		r->cbm_len = 20;
+		r->max_cbm = max_cbm;
+		r->min_cbm_bits = 2;
+		r->capable = true;
+		r->enabled = true;
+
+		return true;
+	}
+
+	return false;
+}
+
+static void rdt_get_config(int idx, struct rdt_resource *r)
+{
+	union cpuid_0x10_1_eax eax;
+	union cpuid_0x10_1_edx edx;
+	u32 ebx, ecx;
+
+	cpuid_count(0x00000010, idx, &eax.full, &ebx, &ecx, &edx.full);
+	r->num_closid = edx.split.cos_max + 1;
+	r->cbm_len = eax.split.cbm_len + 1;
+	r->max_cbm = BIT_MASK(eax.split.cbm_len + 1) - 1;
+	r->capable = true;
+	r->enabled = true;
+}
+
+static void rdt_get_cdp_l3_config(int type)
+{
+	struct rdt_resource *r_l3 = &rdt_resources_all[RDT_RESOURCE_L3];
+	struct rdt_resource *r = &rdt_resources_all[type];
+
+	r->num_closid = r_l3->num_closid / 2;
+	r->cbm_len = r_l3->cbm_len;
+	r->max_cbm = r_l3->max_cbm;
+	r->capable = true;
+	/*
+	 * By default, CDP is disabled. CDP can be enabled by mount parameter
+	 * "cdp" during resctrl file system mount time.
+	 */
+	r->enabled = false;
+}
+
+static inline bool get_rdt_resources(void)
+{
+	bool ret = false;
+
+	if (cache_alloc_hsw_probe())
+		return true;
+
+	if (!boot_cpu_has(X86_FEATURE_RDT_A))
+		return false;
+
+	if (boot_cpu_has(X86_FEATURE_CAT_L3)) {
+		rdt_get_config(1, &rdt_resources_all[RDT_RESOURCE_L3]);
+		if (boot_cpu_has(X86_FEATURE_CDP_L3)) {
+			rdt_get_cdp_l3_config(RDT_RESOURCE_L3DATA);
+			rdt_get_cdp_l3_config(RDT_RESOURCE_L3CODE);
+		}
+		ret = true;
+	}
+	if (boot_cpu_has(X86_FEATURE_CAT_L2)) {
+		/* CPUID 0x10.2 fields are same format at 0x10.1 */
+		rdt_get_config(2, &rdt_resources_all[RDT_RESOURCE_L2]);
+		ret = true;
+	}
+
+	return ret;
+}
+
+static int get_cache_id(int cpu, int level)
+{
+	struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu);
+	int i;
+
+	for (i = 0; i < ci->num_leaves; i++) {
+		if (ci->info_list[i].level == level)
+			return ci->info_list[i].id;
+	}
+
+	return -1;
+}
+
+void rdt_cbm_update(void *arg)
+{
+	struct msr_param *m = (struct msr_param *)arg;
+	struct rdt_resource *r = m->res;
+	int i, cpu = smp_processor_id();
+	struct rdt_domain *d;
+
+	list_for_each_entry(d, &r->domains, list) {
+		/* Find the domain that contains this CPU */
+		if (cpumask_test_cpu(cpu, &d->cpu_mask))
+			goto found;
+	}
+	pr_info_once("cpu %d not found in any domain for resource %s\n",
+		     cpu, r->name);
+
+	return;
+
+found:
+	for (i = m->low; i < m->high; i++) {
+		int idx = cbm_idx(r, i);
+
+		wrmsrl(r->msr_base + idx, d->cbm[i]);
+	}
+}
+
+/*
+ * rdt_find_domain - Find a domain in a resource that matches input resource id
+ *
+ * Search resource r's domain list to find the resource id. If the resource
+ * id is found in a domain, return the domain. Otherwise, if requested by
+ * caller, return the first domain whose id is bigger than the input id.
+ * The domain list is sorted by id in ascending order.
+ */
+static struct rdt_domain *rdt_find_domain(struct rdt_resource *r, int id,
+					  struct list_head **pos)
+{
+	struct rdt_domain *d;
+	struct list_head *l;
+
+	if (id < 0)
+		return ERR_PTR(id);
+
+	list_for_each(l, &r->domains) {
+		d = list_entry(l, struct rdt_domain, list);
+		/* When id is found, return its domain. */
+		if (id == d->id)
+			return d;
+		/* Stop searching when finding id's position in sorted list. */
+		if (id < d->id)
+			break;
+	}
+
+	if (pos)
+		*pos = l;
+
+	return NULL;
+}
+
+/*
+ * domain_add_cpu - Add a cpu to a resource's domain list.
+ *
+ * If an existing domain in the resource r's domain list matches the cpu's
+ * resource id, add the cpu in the domain.
+ *
+ * Otherwise, a new domain is allocated and inserted into the right position
+ * in the domain list sorted by id in ascending order.
+ *
+ * The order in the domain list is visible to users when we print entries
+ * in the schemata file and schemata input is validated to have the same order
+ * as this list.
+ */
+static void domain_add_cpu(int cpu, struct rdt_resource *r)
+{
+	int i, id = get_cache_id(cpu, r->cache_level);
+	struct list_head *add_pos = NULL;
+	struct rdt_domain *d;
+
+	d = rdt_find_domain(r, id, &add_pos);
+	if (IS_ERR(d)) {
+		pr_warn("Could't find cache id for cpu %d\n", cpu);
+		return;
+	}
+
+	if (d) {
+		cpumask_set_cpu(cpu, &d->cpu_mask);
+		return;
+	}
+
+	d = kzalloc_node(sizeof(*d), GFP_KERNEL, cpu_to_node(cpu));
+	if (!d)
+		return;
+
+	d->id = id;
+
+	d->cbm = kmalloc_array(r->num_closid, sizeof(*d->cbm), GFP_KERNEL);
+	if (!d->cbm) {
+		kfree(d);
+		return;
+	}
+
+	for (i = 0; i < r->num_closid; i++) {
+		int idx = cbm_idx(r, i);
+
+		d->cbm[i] = r->max_cbm;
+		wrmsrl(r->msr_base + idx, d->cbm[i]);
+	}
+
+	cpumask_set_cpu(cpu, &d->cpu_mask);
+	list_add_tail(&d->list, add_pos);
+	r->num_domains++;
+}
+
+static void domain_remove_cpu(int cpu, struct rdt_resource *r)
+{
+	int id = get_cache_id(cpu, r->cache_level);
+	struct rdt_domain *d;
+
+	d = rdt_find_domain(r, id, NULL);
+	if (IS_ERR_OR_NULL(d)) {
+		pr_warn("Could't find cache id for cpu %d\n", cpu);
+		return;
+	}
+
+	cpumask_clear_cpu(cpu, &d->cpu_mask);
+	if (cpumask_empty(&d->cpu_mask)) {
+		r->num_domains--;
+		kfree(d->cbm);
+		list_del(&d->list);
+		kfree(d);
+	}
+}
+
+static void clear_closid(int cpu)
+{
+	struct intel_pqr_state *state = this_cpu_ptr(&pqr_state);
+
+	per_cpu(cpu_closid, cpu) = 0;
+	state->closid = 0;
+	wrmsr(MSR_IA32_PQR_ASSOC, state->rmid, 0);
+}
+
+static int intel_rdt_online_cpu(unsigned int cpu)
+{
+	struct rdt_resource *r;
+
+	mutex_lock(&rdtgroup_mutex);
+	for_each_capable_rdt_resource(r)
+		domain_add_cpu(cpu, r);
+	/* The cpu is set in default rdtgroup after online. */
+	cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask);
+	clear_closid(cpu);
+	mutex_unlock(&rdtgroup_mutex);
+
+	return 0;
+}
+
+static int intel_rdt_offline_cpu(unsigned int cpu)
+{
+	struct rdtgroup *rdtgrp;
+	struct rdt_resource *r;
+
+	mutex_lock(&rdtgroup_mutex);
+	for_each_capable_rdt_resource(r)
+		domain_remove_cpu(cpu, r);
+	list_for_each_entry(rdtgrp, &rdt_all_groups, rdtgroup_list) {
+		if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask))
+			break;
+	}
+	clear_closid(cpu);
+	mutex_unlock(&rdtgroup_mutex);
+
+	return 0;
+}
+
+static int __init intel_rdt_late_init(void)
+{
+	struct rdt_resource *r;
+	int state, ret;
+
+	if (!get_rdt_resources())
+		return -ENODEV;
+
+	state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+				  "x86/rdt/cat:online:",
+				  intel_rdt_online_cpu, intel_rdt_offline_cpu);
+	if (state < 0)
+		return state;
+
+	ret = rdtgroup_init();
+	if (ret) {
+		cpuhp_remove_state(state);
+		return ret;
+	}
+
+	for_each_capable_rdt_resource(r)
+		pr_info("Intel RDT %s allocation detected\n", r->name);
+
+	return 0;
+}
+
+late_initcall(intel_rdt_late_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1115 @@
+/*
+ * User interface for Resource Alloction in Resource Director Technology(RDT)
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Author: Fenghua Yu <fenghua.yu@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.
+ *
+ * More information about RDT be found in the Intel (R) x86 Architecture
+ * Software Developer Manual.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/cpu.h>
+#include <linux/fs.h>
+#include <linux/sysfs.h>
+#include <linux/kernfs.h>
+#include <linux/seq_file.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/task_work.h>
+
+#include <uapi/linux/magic.h>
+
+#include <asm/intel_rdt.h>
+#include <asm/intel_rdt_common.h>
+
+DEFINE_STATIC_KEY_FALSE(rdt_enable_key);
+struct kernfs_root *rdt_root;
+struct rdtgroup rdtgroup_default;
+LIST_HEAD(rdt_all_groups);
+
+/* Kernel fs node for "info" directory under root */
+static struct kernfs_node *kn_info;
+
+/*
+ * Trivial allocator for CLOSIDs. Since h/w only supports a small number,
+ * we can keep a bitmap of free CLOSIDs in a single integer.
+ *
+ * Using a global CLOSID across all resources has some advantages and
+ * some drawbacks:
+ * + We can simply set "current->closid" to assign a task to a resource
+ *   group.
+ * + Context switch code can avoid extra memory references deciding which
+ *   CLOSID to load into the PQR_ASSOC MSR
+ * - We give up some options in configuring resource groups across multi-socket
+ *   systems.
+ * - Our choices on how to configure each resource become progressively more
+ *   limited as the number of resources grows.
+ */
+static int closid_free_map;
+
+static void closid_init(void)
+{
+	struct rdt_resource *r;
+	int rdt_min_closid = 32;
+
+	/* Compute rdt_min_closid across all resources */
+	for_each_enabled_rdt_resource(r)
+		rdt_min_closid = min(rdt_min_closid, r->num_closid);
+
+	closid_free_map = BIT_MASK(rdt_min_closid) - 1;
+
+	/* CLOSID 0 is always reserved for the default group */
+	closid_free_map &= ~1;
+}
+
+int closid_alloc(void)
+{
+	int closid = ffs(closid_free_map);
+
+	if (closid == 0)
+		return -ENOSPC;
+	closid--;
+	closid_free_map &= ~(1 << closid);
+
+	return closid;
+}
+
+static void closid_free(int closid)
+{
+	closid_free_map |= 1 << closid;
+}
+
+/* set uid and gid of rdtgroup dirs and files to that of the creator */
+static int rdtgroup_kn_set_ugid(struct kernfs_node *kn)
+{
+	struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
+				.ia_uid = current_fsuid(),
+				.ia_gid = current_fsgid(), };
+
+	if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
+	    gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
+		return 0;
+
+	return kernfs_setattr(kn, &iattr);
+}
+
+static int rdtgroup_add_file(struct kernfs_node *parent_kn, struct rftype *rft)
+{
+	struct kernfs_node *kn;
+	int ret;
+
+	kn = __kernfs_create_file(parent_kn, rft->name, rft->mode,
+				  0, rft->kf_ops, rft, NULL, NULL);
+	if (IS_ERR(kn))
+		return PTR_ERR(kn);
+
+	ret = rdtgroup_kn_set_ugid(kn);
+	if (ret) {
+		kernfs_remove(kn);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rdtgroup_add_files(struct kernfs_node *kn, struct rftype *rfts,
+			      int len)
+{
+	struct rftype *rft;
+	int ret;
+
+	lockdep_assert_held(&rdtgroup_mutex);
+
+	for (rft = rfts; rft < rfts + len; rft++) {
+		ret = rdtgroup_add_file(kn, rft);
+		if (ret)
+			goto error;
+	}
+
+	return 0;
+error:
+	pr_warn("Failed to add %s, err=%d\n", rft->name, ret);
+	while (--rft >= rfts)
+		kernfs_remove_by_name(kn, rft->name);
+	return ret;
+}
+
+static int rdtgroup_seqfile_show(struct seq_file *m, void *arg)
+{
+	struct kernfs_open_file *of = m->private;
+	struct rftype *rft = of->kn->priv;
+
+	if (rft->seq_show)
+		return rft->seq_show(of, m, arg);
+	return 0;
+}
+
+static ssize_t rdtgroup_file_write(struct kernfs_open_file *of, char *buf,
+				   size_t nbytes, loff_t off)
+{
+	struct rftype *rft = of->kn->priv;
+
+	if (rft->write)
+		return rft->write(of, buf, nbytes, off);
+
+	return -EINVAL;
+}
+
+static struct kernfs_ops rdtgroup_kf_single_ops = {
+	.atomic_write_len	= PAGE_SIZE,
+	.write			= rdtgroup_file_write,
+	.seq_show		= rdtgroup_seqfile_show,
+};
+
+static int rdtgroup_cpus_show(struct kernfs_open_file *of,
+			      struct seq_file *s, void *v)
+{
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+
+	if (rdtgrp)
+		seq_printf(s, "%*pb\n", cpumask_pr_args(&rdtgrp->cpu_mask));
+	else
+		ret = -ENOENT;
+	rdtgroup_kn_unlock(of->kn);
+
+	return ret;
+}
+
+/*
+ * This is safe against intel_rdt_sched_in() called from __switch_to()
+ * because __switch_to() is executed with interrupts disabled. A local call
+ * from rdt_update_closid() is proteced against __switch_to() because
+ * preemption is disabled.
+ */
+static void rdt_update_cpu_closid(void *closid)
+{
+	if (closid)
+		this_cpu_write(cpu_closid, *(int *)closid);
+	/*
+	 * We cannot unconditionally write the MSR because the current
+	 * executing task might have its own closid selected. Just reuse
+	 * the context switch code.
+	 */
+	intel_rdt_sched_in();
+}
+
+/*
+ * Update the PGR_ASSOC MSR on all cpus in @cpu_mask,
+ *
+ * Per task closids must have been set up before calling this function.
+ *
+ * The per cpu closids are updated with the smp function call, when @closid
+ * is not NULL. If @closid is NULL then all affected percpu closids must
+ * have been set up before calling this function.
+ */
+static void
+rdt_update_closid(const struct cpumask *cpu_mask, int *closid)
+{
+	int cpu = get_cpu();
+
+	if (cpumask_test_cpu(cpu, cpu_mask))
+		rdt_update_cpu_closid(closid);
+	smp_call_function_many(cpu_mask, rdt_update_cpu_closid, closid, 1);
+	put_cpu();
+}
+
+static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of,
+				   char *buf, size_t nbytes, loff_t off)
+{
+	cpumask_var_t tmpmask, newmask;
+	struct rdtgroup *rdtgrp, *r;
+	int ret;
+
+	if (!buf)
+		return -EINVAL;
+
+	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
+		return -ENOMEM;
+	if (!zalloc_cpumask_var(&newmask, GFP_KERNEL)) {
+		free_cpumask_var(tmpmask);
+		return -ENOMEM;
+	}
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+	if (!rdtgrp) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+
+	ret = cpumask_parse(buf, newmask);
+	if (ret)
+		goto unlock;
+
+	/* check that user didn't specify any offline cpus */
+	cpumask_andnot(tmpmask, newmask, cpu_online_mask);
+	if (cpumask_weight(tmpmask)) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	/* Check whether cpus are dropped from this group */
+	cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask);
+	if (cpumask_weight(tmpmask)) {
+		/* Can't drop from default group */
+		if (rdtgrp == &rdtgroup_default) {
+			ret = -EINVAL;
+			goto unlock;
+		}
+		/* Give any dropped cpus to rdtgroup_default */
+		cpumask_or(&rdtgroup_default.cpu_mask,
+			   &rdtgroup_default.cpu_mask, tmpmask);
+		rdt_update_closid(tmpmask, &rdtgroup_default.closid);
+	}
+
+	/*
+	 * If we added cpus, remove them from previous group that owned them
+	 * and update per-cpu closid
+	 */
+	cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask);
+	if (cpumask_weight(tmpmask)) {
+		list_for_each_entry(r, &rdt_all_groups, rdtgroup_list) {
+			if (r == rdtgrp)
+				continue;
+			cpumask_andnot(&r->cpu_mask, &r->cpu_mask, tmpmask);
+		}
+		rdt_update_closid(tmpmask, &rdtgrp->closid);
+	}
+
+	/* Done pushing/pulling - update this group with new mask */
+	cpumask_copy(&rdtgrp->cpu_mask, newmask);
+
+unlock:
+	rdtgroup_kn_unlock(of->kn);
+	free_cpumask_var(tmpmask);
+	free_cpumask_var(newmask);
+
+	return ret ?: nbytes;
+}
+
+struct task_move_callback {
+	struct callback_head	work;
+	struct rdtgroup		*rdtgrp;
+};
+
+static void move_myself(struct callback_head *head)
+{
+	struct task_move_callback *callback;
+	struct rdtgroup *rdtgrp;
+
+	callback = container_of(head, struct task_move_callback, work);
+	rdtgrp = callback->rdtgrp;
+
+	/*
+	 * If resource group was deleted before this task work callback
+	 * was invoked, then assign the task to root group and free the
+	 * resource group.
+	 */
+	if (atomic_dec_and_test(&rdtgrp->waitcount) &&
+	    (rdtgrp->flags & RDT_DELETED)) {
+		current->closid = 0;
+		kfree(rdtgrp);
+	}
+
+	preempt_disable();
+	/* update PQR_ASSOC MSR to make resource group go into effect */
+	intel_rdt_sched_in();
+	preempt_enable();
+
+	kfree(callback);
+}
+
+static int __rdtgroup_move_task(struct task_struct *tsk,
+				struct rdtgroup *rdtgrp)
+{
+	struct task_move_callback *callback;
+	int ret;
+
+	callback = kzalloc(sizeof(*callback), GFP_KERNEL);
+	if (!callback)
+		return -ENOMEM;
+	callback->work.func = move_myself;
+	callback->rdtgrp = rdtgrp;
+
+	/*
+	 * Take a refcount, so rdtgrp cannot be freed before the
+	 * callback has been invoked.
+	 */
+	atomic_inc(&rdtgrp->waitcount);
+	ret = task_work_add(tsk, &callback->work, true);
+	if (ret) {
+		/*
+		 * Task is exiting. Drop the refcount and free the callback.
+		 * No need to check the refcount as the group cannot be
+		 * deleted before the write function unlocks rdtgroup_mutex.
+		 */
+		atomic_dec(&rdtgrp->waitcount);
+		kfree(callback);
+	} else {
+		tsk->closid = rdtgrp->closid;
+	}
+	return ret;
+}
+
+static int rdtgroup_task_write_permission(struct task_struct *task,
+					  struct kernfs_open_file *of)
+{
+	const struct cred *tcred = get_task_cred(task);
+	const struct cred *cred = current_cred();
+	int ret = 0;
+
+	/*
+	 * Even if we're attaching all tasks in the thread group, we only
+	 * need to check permissions on one of them.
+	 */
+	if (!uid_eq(cred->euid, GLOBAL_ROOT_UID) &&
+	    !uid_eq(cred->euid, tcred->uid) &&
+	    !uid_eq(cred->euid, tcred->suid))
+		ret = -EPERM;
+
+	put_cred(tcred);
+	return ret;
+}
+
+static int rdtgroup_move_task(pid_t pid, struct rdtgroup *rdtgrp,
+			      struct kernfs_open_file *of)
+{
+	struct task_struct *tsk;
+	int ret;
+
+	rcu_read_lock();
+	if (pid) {
+		tsk = find_task_by_vpid(pid);
+		if (!tsk) {
+			rcu_read_unlock();
+			return -ESRCH;
+		}
+	} else {
+		tsk = current;
+	}
+
+	get_task_struct(tsk);
+	rcu_read_unlock();
+
+	ret = rdtgroup_task_write_permission(tsk, of);
+	if (!ret)
+		ret = __rdtgroup_move_task(tsk, rdtgrp);
+
+	put_task_struct(tsk);
+	return ret;
+}
+
+static ssize_t rdtgroup_tasks_write(struct kernfs_open_file *of,
+				    char *buf, size_t nbytes, loff_t off)
+{
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+	pid_t pid;
+
+	if (kstrtoint(strstrip(buf), 0, &pid) || pid < 0)
+		return -EINVAL;
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+
+	if (rdtgrp)
+		ret = rdtgroup_move_task(pid, rdtgrp, of);
+	else
+		ret = -ENOENT;
+
+	rdtgroup_kn_unlock(of->kn);
+
+	return ret ?: nbytes;
+}
+
+static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s)
+{
+	struct task_struct *p, *t;
+
+	rcu_read_lock();
+	for_each_process_thread(p, t) {
+		if (t->closid == r->closid)
+			seq_printf(s, "%d\n", t->pid);
+	}
+	rcu_read_unlock();
+}
+
+static int rdtgroup_tasks_show(struct kernfs_open_file *of,
+			       struct seq_file *s, void *v)
+{
+	struct rdtgroup *rdtgrp;
+	int ret = 0;
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+	if (rdtgrp)
+		show_rdt_tasks(rdtgrp, s);
+	else
+		ret = -ENOENT;
+	rdtgroup_kn_unlock(of->kn);
+
+	return ret;
+}
+
+/* Files in each rdtgroup */
+static struct rftype rdtgroup_base_files[] = {
+	{
+		.name		= "cpus",
+		.mode		= 0644,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.write		= rdtgroup_cpus_write,
+		.seq_show	= rdtgroup_cpus_show,
+	},
+	{
+		.name		= "tasks",
+		.mode		= 0644,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.write		= rdtgroup_tasks_write,
+		.seq_show	= rdtgroup_tasks_show,
+	},
+	{
+		.name		= "schemata",
+		.mode		= 0644,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.write		= rdtgroup_schemata_write,
+		.seq_show	= rdtgroup_schemata_show,
+	},
+};
+
+static int rdt_num_closids_show(struct kernfs_open_file *of,
+				struct seq_file *seq, void *v)
+{
+	struct rdt_resource *r = of->kn->parent->priv;
+
+	seq_printf(seq, "%d\n", r->num_closid);
+
+	return 0;
+}
+
+static int rdt_cbm_mask_show(struct kernfs_open_file *of,
+			     struct seq_file *seq, void *v)
+{
+	struct rdt_resource *r = of->kn->parent->priv;
+
+	seq_printf(seq, "%x\n", r->max_cbm);
+
+	return 0;
+}
+
+static int rdt_min_cbm_bits_show(struct kernfs_open_file *of,
+			     struct seq_file *seq, void *v)
+{
+	struct rdt_resource *r = of->kn->parent->priv;
+
+	seq_printf(seq, "%d\n", r->min_cbm_bits);
+
+	return 0;
+}
+
+/* rdtgroup information files for one cache resource. */
+static struct rftype res_info_files[] = {
+	{
+		.name		= "num_closids",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= rdt_num_closids_show,
+	},
+	{
+		.name		= "cbm_mask",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= rdt_cbm_mask_show,
+	},
+	{
+		.name		= "min_cbm_bits",
+		.mode		= 0444,
+		.kf_ops		= &rdtgroup_kf_single_ops,
+		.seq_show	= rdt_min_cbm_bits_show,
+	},
+};
+
+static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
+{
+	struct kernfs_node *kn_subdir;
+	struct rdt_resource *r;
+	int ret;
+
+	/* create the directory */
+	kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL);
+	if (IS_ERR(kn_info))
+		return PTR_ERR(kn_info);
+	kernfs_get(kn_info);
+
+	for_each_enabled_rdt_resource(r) {
+		kn_subdir = kernfs_create_dir(kn_info, r->name,
+					      kn_info->mode, r);
+		if (IS_ERR(kn_subdir)) {
+			ret = PTR_ERR(kn_subdir);
+			goto out_destroy;
+		}
+		kernfs_get(kn_subdir);
+		ret = rdtgroup_kn_set_ugid(kn_subdir);
+		if (ret)
+			goto out_destroy;
+		ret = rdtgroup_add_files(kn_subdir, res_info_files,
+					 ARRAY_SIZE(res_info_files));
+		if (ret)
+			goto out_destroy;
+		kernfs_activate(kn_subdir);
+	}
+
+	/*
+	 * This extra ref will be put in kernfs_remove() and guarantees
+	 * that @rdtgrp->kn is always accessible.
+	 */
+	kernfs_get(kn_info);
+
+	ret = rdtgroup_kn_set_ugid(kn_info);
+	if (ret)
+		goto out_destroy;
+
+	kernfs_activate(kn_info);
+
+	return 0;
+
+out_destroy:
+	kernfs_remove(kn_info);
+	return ret;
+}
+
+static void l3_qos_cfg_update(void *arg)
+{
+	bool *enable = arg;
+
+	wrmsrl(IA32_L3_QOS_CFG, *enable ? L3_QOS_CDP_ENABLE : 0ULL);
+}
+
+static int set_l3_qos_cfg(struct rdt_resource *r, bool enable)
+{
+	cpumask_var_t cpu_mask;
+	struct rdt_domain *d;
+	int cpu;
+
+	if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	list_for_each_entry(d, &r->domains, list) {
+		/* Pick one CPU from each domain instance to update MSR */
+		cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
+	}
+	cpu = get_cpu();
+	/* Update QOS_CFG MSR on this cpu if it's in cpu_mask. */
+	if (cpumask_test_cpu(cpu, cpu_mask))
+		l3_qos_cfg_update(&enable);
+	/* Update QOS_CFG MSR on all other cpus in cpu_mask. */
+	smp_call_function_many(cpu_mask, l3_qos_cfg_update, &enable, 1);
+	put_cpu();
+
+	free_cpumask_var(cpu_mask);
+
+	return 0;
+}
+
+static int cdp_enable(void)
+{
+	struct rdt_resource *r_l3data = &rdt_resources_all[RDT_RESOURCE_L3DATA];
+	struct rdt_resource *r_l3code = &rdt_resources_all[RDT_RESOURCE_L3CODE];
+	struct rdt_resource *r_l3 = &rdt_resources_all[RDT_RESOURCE_L3];
+	int ret;
+
+	if (!r_l3->capable || !r_l3data->capable || !r_l3code->capable)
+		return -EINVAL;
+
+	ret = set_l3_qos_cfg(r_l3, true);
+	if (!ret) {
+		r_l3->enabled = false;
+		r_l3data->enabled = true;
+		r_l3code->enabled = true;
+	}
+	return ret;
+}
+
+static void cdp_disable(void)
+{
+	struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3];
+
+	r->enabled = r->capable;
+
+	if (rdt_resources_all[RDT_RESOURCE_L3DATA].enabled) {
+		rdt_resources_all[RDT_RESOURCE_L3DATA].enabled = false;
+		rdt_resources_all[RDT_RESOURCE_L3CODE].enabled = false;
+		set_l3_qos_cfg(r, false);
+	}
+}
+
+static int parse_rdtgroupfs_options(char *data)
+{
+	char *token, *o = data;
+	int ret = 0;
+
+	while ((token = strsep(&o, ",")) != NULL) {
+		if (!*token)
+			return -EINVAL;
+
+		if (!strcmp(token, "cdp"))
+			ret = cdp_enable();
+	}
+
+	return ret;
+}
+
+/*
+ * We don't allow rdtgroup directories to be created anywhere
+ * except the root directory. Thus when looking for the rdtgroup
+ * structure for a kernfs node we are either looking at a directory,
+ * in which case the rdtgroup structure is pointed at by the "priv"
+ * field, otherwise we have a file, and need only look to the parent
+ * to find the rdtgroup.
+ */
+static struct rdtgroup *kernfs_to_rdtgroup(struct kernfs_node *kn)
+{
+	if (kernfs_type(kn) == KERNFS_DIR) {
+		/*
+		 * All the resource directories use "kn->priv"
+		 * to point to the "struct rdtgroup" for the
+		 * resource. "info" and its subdirectories don't
+		 * have rdtgroup structures, so return NULL here.
+		 */
+		if (kn == kn_info || kn->parent == kn_info)
+			return NULL;
+		else
+			return kn->priv;
+	} else {
+		return kn->parent->priv;
+	}
+}
+
+struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn)
+{
+	struct rdtgroup *rdtgrp = kernfs_to_rdtgroup(kn);
+
+	if (!rdtgrp)
+		return NULL;
+
+	atomic_inc(&rdtgrp->waitcount);
+	kernfs_break_active_protection(kn);
+
+	mutex_lock(&rdtgroup_mutex);
+
+	/* Was this group deleted while we waited? */
+	if (rdtgrp->flags & RDT_DELETED)
+		return NULL;
+
+	return rdtgrp;
+}
+
+void rdtgroup_kn_unlock(struct kernfs_node *kn)
+{
+	struct rdtgroup *rdtgrp = kernfs_to_rdtgroup(kn);
+
+	if (!rdtgrp)
+		return;
+
+	mutex_unlock(&rdtgroup_mutex);
+
+	if (atomic_dec_and_test(&rdtgrp->waitcount) &&
+	    (rdtgrp->flags & RDT_DELETED)) {
+		kernfs_unbreak_active_protection(kn);
+		kernfs_put(kn);
+		kfree(rdtgrp);
+	} else {
+		kernfs_unbreak_active_protection(kn);
+	}
+}
+
+static struct dentry *rdt_mount(struct file_system_type *fs_type,
+				int flags, const char *unused_dev_name,
+				void *data)
+{
+	struct dentry *dentry;
+	int ret;
+
+	mutex_lock(&rdtgroup_mutex);
+	/*
+	 * resctrl file system can only be mounted once.
+	 */
+	if (static_branch_unlikely(&rdt_enable_key)) {
+		dentry = ERR_PTR(-EBUSY);
+		goto out;
+	}
+
+	ret = parse_rdtgroupfs_options(data);
+	if (ret) {
+		dentry = ERR_PTR(ret);
+		goto out_cdp;
+	}
+
+	closid_init();
+
+	ret = rdtgroup_create_info_dir(rdtgroup_default.kn);
+	if (ret) {
+		dentry = ERR_PTR(ret);
+		goto out_cdp;
+	}
+
+	dentry = kernfs_mount(fs_type, flags, rdt_root,
+			      RDTGROUP_SUPER_MAGIC, NULL);
+	if (IS_ERR(dentry))
+		goto out_cdp;
+
+	static_branch_enable(&rdt_enable_key);
+	goto out;
+
+out_cdp:
+	cdp_disable();
+out:
+	mutex_unlock(&rdtgroup_mutex);
+
+	return dentry;
+}
+
+static int reset_all_cbms(struct rdt_resource *r)
+{
+	struct msr_param msr_param;
+	cpumask_var_t cpu_mask;
+	struct rdt_domain *d;
+	int i, cpu;
+
+	if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	msr_param.res = r;
+	msr_param.low = 0;
+	msr_param.high = r->num_closid;
+
+	/*
+	 * Disable resource control for this resource by setting all
+	 * CBMs in all domains to the maximum mask value. Pick one CPU
+	 * from each domain to update the MSRs below.
+	 */
+	list_for_each_entry(d, &r->domains, list) {
+		cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
+
+		for (i = 0; i < r->num_closid; i++)
+			d->cbm[i] = r->max_cbm;
+	}
+	cpu = get_cpu();
+	/* Update CBM on this cpu if it's in cpu_mask. */
+	if (cpumask_test_cpu(cpu, cpu_mask))
+		rdt_cbm_update(&msr_param);
+	/* Update CBM on all other cpus in cpu_mask. */
+	smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1);
+	put_cpu();
+
+	free_cpumask_var(cpu_mask);
+
+	return 0;
+}
+
+/*
+ * Move tasks from one to the other group. If @from is NULL, then all tasks
+ * in the systems are moved unconditionally (used for teardown).
+ *
+ * If @mask is not NULL the cpus on which moved tasks are running are set
+ * in that mask so the update smp function call is restricted to affected
+ * cpus.
+ */
+static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
+				 struct cpumask *mask)
+{
+	struct task_struct *p, *t;
+
+	read_lock(&tasklist_lock);
+	for_each_process_thread(p, t) {
+		if (!from || t->closid == from->closid) {
+			t->closid = to->closid;
+#ifdef CONFIG_SMP
+			/*
+			 * This is safe on x86 w/o barriers as the ordering
+			 * of writing to task_cpu() and t->on_cpu is
+			 * reverse to the reading here. The detection is
+			 * inaccurate as tasks might move or schedule
+			 * before the smp function call takes place. In
+			 * such a case the function call is pointless, but
+			 * there is no other side effect.
+			 */
+			if (mask && t->on_cpu)
+				cpumask_set_cpu(task_cpu(t), mask);
+#endif
+		}
+	}
+	read_unlock(&tasklist_lock);
+}
+
+/*
+ * Forcibly remove all of subdirectories under root.
+ */
+static void rmdir_all_sub(void)
+{
+	struct rdtgroup *rdtgrp, *tmp;
+
+	/* Move all tasks to the default resource group */
+	rdt_move_group_tasks(NULL, &rdtgroup_default, NULL);
+
+	list_for_each_entry_safe(rdtgrp, tmp, &rdt_all_groups, rdtgroup_list) {
+		/* Remove each rdtgroup other than root */
+		if (rdtgrp == &rdtgroup_default)
+			continue;
+
+		/*
+		 * Give any CPUs back to the default group. We cannot copy
+		 * cpu_online_mask because a CPU might have executed the
+		 * offline callback already, but is still marked online.
+		 */
+		cpumask_or(&rdtgroup_default.cpu_mask,
+			   &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
+
+		kernfs_remove(rdtgrp->kn);
+		list_del(&rdtgrp->rdtgroup_list);
+		kfree(rdtgrp);
+	}
+	/* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */
+	get_online_cpus();
+	rdt_update_closid(cpu_online_mask, &rdtgroup_default.closid);
+	put_online_cpus();
+
+	kernfs_remove(kn_info);
+}
+
+static void rdt_kill_sb(struct super_block *sb)
+{
+	struct rdt_resource *r;
+
+	mutex_lock(&rdtgroup_mutex);
+
+	/*Put everything back to default values. */
+	for_each_enabled_rdt_resource(r)
+		reset_all_cbms(r);
+	cdp_disable();
+	rmdir_all_sub();
+	static_branch_disable(&rdt_enable_key);
+	kernfs_kill_sb(sb);
+	mutex_unlock(&rdtgroup_mutex);
+}
+
+static struct file_system_type rdt_fs_type = {
+	.name    = "resctrl",
+	.mount   = rdt_mount,
+	.kill_sb = rdt_kill_sb,
+};
+
+static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
+			  umode_t mode)
+{
+	struct rdtgroup *parent, *rdtgrp;
+	struct kernfs_node *kn;
+	int ret, closid;
+
+	/* Only allow mkdir in the root directory */
+	if (parent_kn != rdtgroup_default.kn)
+		return -EPERM;
+
+	/* Do not accept '\n' to avoid unparsable situation. */
+	if (strchr(name, '\n'))
+		return -EINVAL;
+
+	parent = rdtgroup_kn_lock_live(parent_kn);
+	if (!parent) {
+		ret = -ENODEV;
+		goto out_unlock;
+	}
+
+	ret = closid_alloc();
+	if (ret < 0)
+		goto out_unlock;
+	closid = ret;
+
+	/* allocate the rdtgroup. */
+	rdtgrp = kzalloc(sizeof(*rdtgrp), GFP_KERNEL);
+	if (!rdtgrp) {
+		ret = -ENOSPC;
+		goto out_closid_free;
+	}
+	rdtgrp->closid = closid;
+	list_add(&rdtgrp->rdtgroup_list, &rdt_all_groups);
+
+	/* kernfs creates the directory for rdtgrp */
+	kn = kernfs_create_dir(parent->kn, name, mode, rdtgrp);
+	if (IS_ERR(kn)) {
+		ret = PTR_ERR(kn);
+		goto out_cancel_ref;
+	}
+	rdtgrp->kn = kn;
+
+	/*
+	 * kernfs_remove() will drop the reference count on "kn" which
+	 * will free it. But we still need it to stick around for the
+	 * rdtgroup_kn_unlock(kn} call below. Take one extra reference
+	 * here, which will be dropped inside rdtgroup_kn_unlock().
+	 */
+	kernfs_get(kn);
+
+	ret = rdtgroup_kn_set_ugid(kn);
+	if (ret)
+		goto out_destroy;
+
+	ret = rdtgroup_add_files(kn, rdtgroup_base_files,
+				 ARRAY_SIZE(rdtgroup_base_files));
+	if (ret)
+		goto out_destroy;
+
+	kernfs_activate(kn);
+
+	ret = 0;
+	goto out_unlock;
+
+out_destroy:
+	kernfs_remove(rdtgrp->kn);
+out_cancel_ref:
+	list_del(&rdtgrp->rdtgroup_list);
+	kfree(rdtgrp);
+out_closid_free:
+	closid_free(closid);
+out_unlock:
+	rdtgroup_kn_unlock(parent_kn);
+	return ret;
+}
+
+static int rdtgroup_rmdir(struct kernfs_node *kn)
+{
+	int ret, cpu, closid = rdtgroup_default.closid;
+	struct rdtgroup *rdtgrp;
+	cpumask_var_t tmpmask;
+
+	if (!zalloc_cpumask_var(&tmpmask, GFP_KERNEL))
+		return -ENOMEM;
+
+	rdtgrp = rdtgroup_kn_lock_live(kn);
+	if (!rdtgrp) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	/* Give any tasks back to the default group */
+	rdt_move_group_tasks(rdtgrp, &rdtgroup_default, tmpmask);
+
+	/* Give any CPUs back to the default group */
+	cpumask_or(&rdtgroup_default.cpu_mask,
+		   &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
+
+	/* Update per cpu closid of the moved CPUs first */
+	for_each_cpu(cpu, &rdtgrp->cpu_mask)
+		per_cpu(cpu_closid, cpu) = closid;
+	/*
+	 * Update the MSR on moved CPUs and CPUs which have moved
+	 * task running on them.
+	 */
+	cpumask_or(tmpmask, tmpmask, &rdtgrp->cpu_mask);
+	rdt_update_closid(tmpmask, NULL);
+
+	rdtgrp->flags = RDT_DELETED;
+	closid_free(rdtgrp->closid);
+	list_del(&rdtgrp->rdtgroup_list);
+
+	/*
+	 * one extra hold on this, will drop when we kfree(rdtgrp)
+	 * in rdtgroup_kn_unlock()
+	 */
+	kernfs_get(kn);
+	kernfs_remove(rdtgrp->kn);
+	ret = 0;
+out:
+	rdtgroup_kn_unlock(kn);
+	free_cpumask_var(tmpmask);
+	return ret;
+}
+
+static int rdtgroup_show_options(struct seq_file *seq, struct kernfs_root *kf)
+{
+	if (rdt_resources_all[RDT_RESOURCE_L3DATA].enabled)
+		seq_puts(seq, ",cdp");
+	return 0;
+}
+
+static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = {
+	.mkdir		= rdtgroup_mkdir,
+	.rmdir		= rdtgroup_rmdir,
+	.show_options	= rdtgroup_show_options,
+};
+
+static int __init rdtgroup_setup_root(void)
+{
+	int ret;
+
+	rdt_root = kernfs_create_root(&rdtgroup_kf_syscall_ops,
+				      KERNFS_ROOT_CREATE_DEACTIVATED,
+				      &rdtgroup_default);
+	if (IS_ERR(rdt_root))
+		return PTR_ERR(rdt_root);
+
+	mutex_lock(&rdtgroup_mutex);
+
+	rdtgroup_default.closid = 0;
+	list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups);
+
+	ret = rdtgroup_add_files(rdt_root->kn, rdtgroup_base_files,
+				 ARRAY_SIZE(rdtgroup_base_files));
+	if (ret) {
+		kernfs_destroy_root(rdt_root);
+		goto out;
+	}
+
+	rdtgroup_default.kn = rdt_root->kn;
+	kernfs_activate(rdtgroup_default.kn);
+
+out:
+	mutex_unlock(&rdtgroup_mutex);
+
+	return ret;
+}
+
+/*
+ * rdtgroup_init - rdtgroup initialization
+ *
+ * Setup resctrl file system including set up root, create mount point,
+ * register rdtgroup filesystem, and initialize files under root directory.
+ *
+ * Return: 0 on success or -errno
+ */
+int __init rdtgroup_init(void)
+{
+	int ret = 0;
+
+	ret = rdtgroup_setup_root();
+	if (ret)
+		return ret;
+
+	ret = sysfs_create_mount_point(fs_kobj, "resctrl");
+	if (ret)
+		goto cleanup_root;
+
+	ret = register_filesystem(&rdt_fs_type);
+	if (ret)
+		goto cleanup_mountpoint;
+
+	return 0;
+
+cleanup_mountpoint:
+	sysfs_remove_mount_point(fs_kobj, "resctrl");
+cleanup_root:
+	kernfs_destroy_root(rdt_root);
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_rdt_schemata.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_rdt_schemata.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/intel_rdt_schemata.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/intel_rdt_schemata.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,245 @@
+/*
+ * Resource Director Technology(RDT)
+ * - Cache Allocation code.
+ *
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Authors:
+ *    Fenghua Yu <fenghua.yu@intel.com>
+ *    Tony Luck <tony.luck@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.
+ *
+ * More information about RDT be found in the Intel (R) x86 Architecture
+ * Software Developer Manual June 2016, volume 3, section 17.17.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/kernfs.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <asm/intel_rdt.h>
+
+/*
+ * Check whether a cache bit mask is valid. The SDM says:
+ *	Please note that all (and only) contiguous '1' combinations
+ *	are allowed (e.g. FFFFH, 0FF0H, 003CH, etc.).
+ * Additionally Haswell requires at least two bits set.
+ */
+static bool cbm_validate(unsigned long var, struct rdt_resource *r)
+{
+	unsigned long first_bit, zero_bit;
+
+	if (var == 0 || var > r->max_cbm)
+		return false;
+
+	first_bit = find_first_bit(&var, r->cbm_len);
+	zero_bit = find_next_zero_bit(&var, r->cbm_len, first_bit);
+
+	if (find_next_bit(&var, r->cbm_len, zero_bit) < r->cbm_len)
+		return false;
+
+	if ((zero_bit - first_bit) < r->min_cbm_bits)
+		return false;
+	return true;
+}
+
+/*
+ * Read one cache bit mask (hex). Check that it is valid for the current
+ * resource type.
+ */
+static int parse_cbm(char *buf, struct rdt_resource *r)
+{
+	unsigned long data;
+	int ret;
+
+	ret = kstrtoul(buf, 16, &data);
+	if (ret)
+		return ret;
+	if (!cbm_validate(data, r))
+		return -EINVAL;
+	r->tmp_cbms[r->num_tmp_cbms++] = data;
+
+	return 0;
+}
+
+/*
+ * For each domain in this resource we expect to find a series of:
+ *	id=mask
+ * separated by ";". The "id" is in decimal, and must appear in the
+ * right order.
+ */
+static int parse_line(char *line, struct rdt_resource *r)
+{
+	char *dom = NULL, *id;
+	struct rdt_domain *d;
+	unsigned long dom_id;
+
+	list_for_each_entry(d, &r->domains, list) {
+		dom = strsep(&line, ";");
+		if (!dom)
+			return -EINVAL;
+		id = strsep(&dom, "=");
+		if (kstrtoul(id, 10, &dom_id) || dom_id != d->id)
+			return -EINVAL;
+		if (parse_cbm(dom, r))
+			return -EINVAL;
+	}
+
+	/* Any garbage at the end of the line? */
+	if (line && line[0])
+		return -EINVAL;
+	return 0;
+}
+
+static int update_domains(struct rdt_resource *r, int closid)
+{
+	struct msr_param msr_param;
+	cpumask_var_t cpu_mask;
+	struct rdt_domain *d;
+	int cpu, idx = 0;
+
+	if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
+		return -ENOMEM;
+
+	msr_param.low = closid;
+	msr_param.high = msr_param.low + 1;
+	msr_param.res = r;
+
+	list_for_each_entry(d, &r->domains, list) {
+		cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
+		d->cbm[msr_param.low] = r->tmp_cbms[idx++];
+	}
+	cpu = get_cpu();
+	/* Update CBM on this cpu if it's in cpu_mask. */
+	if (cpumask_test_cpu(cpu, cpu_mask))
+		rdt_cbm_update(&msr_param);
+	/* Update CBM on other cpus. */
+	smp_call_function_many(cpu_mask, rdt_cbm_update, &msr_param, 1);
+	put_cpu();
+
+	free_cpumask_var(cpu_mask);
+
+	return 0;
+}
+
+ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
+				char *buf, size_t nbytes, loff_t off)
+{
+	struct rdtgroup *rdtgrp;
+	struct rdt_resource *r;
+	char *tok, *resname;
+	int closid, ret = 0;
+	u32 *l3_cbms = NULL;
+
+	/* Valid input requires a trailing newline */
+	if (nbytes == 0 || buf[nbytes - 1] != '\n')
+		return -EINVAL;
+	buf[nbytes - 1] = '\0';
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+	if (!rdtgrp) {
+		rdtgroup_kn_unlock(of->kn);
+		return -ENOENT;
+	}
+
+	closid = rdtgrp->closid;
+
+	/* get scratch space to save all the masks while we validate input */
+	for_each_enabled_rdt_resource(r) {
+		r->tmp_cbms = kcalloc(r->num_domains, sizeof(*l3_cbms),
+				      GFP_KERNEL);
+		if (!r->tmp_cbms) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		r->num_tmp_cbms = 0;
+	}
+
+	while ((tok = strsep(&buf, "\n")) != NULL) {
+		resname = strsep(&tok, ":");
+		if (!tok) {
+			ret = -EINVAL;
+			goto out;
+		}
+		for_each_enabled_rdt_resource(r) {
+			if (!strcmp(resname, r->name) &&
+			    closid < r->num_closid) {
+				ret = parse_line(tok, r);
+				if (ret)
+					goto out;
+				break;
+			}
+		}
+		if (!r->name) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	/* Did the parser find all the masks we need? */
+	for_each_enabled_rdt_resource(r) {
+		if (r->num_tmp_cbms != r->num_domains) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	for_each_enabled_rdt_resource(r) {
+		ret = update_domains(r, closid);
+		if (ret)
+			goto out;
+	}
+
+out:
+	rdtgroup_kn_unlock(of->kn);
+	for_each_enabled_rdt_resource(r) {
+		kfree(r->tmp_cbms);
+		r->tmp_cbms = NULL;
+	}
+	return ret ?: nbytes;
+}
+
+static void show_doms(struct seq_file *s, struct rdt_resource *r, int closid)
+{
+	struct rdt_domain *dom;
+	bool sep = false;
+
+	seq_printf(s, "%s:", r->name);
+	list_for_each_entry(dom, &r->domains, list) {
+		if (sep)
+			seq_puts(s, ";");
+		seq_printf(s, "%d=%x", dom->id, dom->cbm[closid]);
+		sep = true;
+	}
+	seq_puts(s, "\n");
+}
+
+int rdtgroup_schemata_show(struct kernfs_open_file *of,
+			   struct seq_file *s, void *v)
+{
+	struct rdtgroup *rdtgrp;
+	struct rdt_resource *r;
+	int closid, ret = 0;
+
+	rdtgrp = rdtgroup_kn_lock_live(of->kn);
+	if (rdtgrp) {
+		closid = rdtgrp->closid;
+		for_each_enabled_rdt_resource(r) {
+			if (closid < r->num_closid)
+				show_doms(s, r, closid);
+		}
+	} else {
+		ret = -ENOENT;
+	}
+	rdtgroup_kn_unlock(of->kn);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/Makefile linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/Makefile
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -20,13 +20,11 @@ obj-y			:= intel_cacheinfo.o scattered.o
 obj-y			+= common.o
 obj-y			+= rdrand.o
 obj-y			+= match.o
+obj-y			+= bugs.o
 
 obj-$(CONFIG_PROC_FS)	+= proc.o
 obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o
 
-obj-$(CONFIG_X86_32)	+= bugs.o
-obj-$(CONFIG_X86_64)	+= bugs_64.o
-
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel.o
 obj-$(CONFIG_CPU_SUP_AMD)		+= amd.o
 obj-$(CONFIG_CPU_SUP_CYRIX_32)		+= cyrix.o
@@ -34,6 +32,8 @@ obj-$(CONFIG_CPU_SUP_CENTAUR)		+= centau
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)	+= transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)		+= umc.o
 
+obj-$(CONFIG_INTEL_RDT_A)	+= intel_rdt.o intel_rdt_rdtgroup.o intel_rdt_schemata.o
+
 obj-$(CONFIG_X86_MCE)			+= mcheck/
 obj-$(CONFIG_MTRR)			+= mtrr/
 obj-$(CONFIG_MICROCODE)			+= microcode/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,6 @@
 
 #include <asm/amd_nb.h>
 #include <asm/apic.h>
-#include <asm/idle.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 #include <asm/trace/irq_vectors.h>
@@ -55,6 +54,8 @@
 /* Threshold LVT offset is at MSR0xC0000410[15:12] */
 #define SMCA_THR_LVT_OFF	0xF000
 
+static bool thresholding_en;
+
 static const char * const th_names[] = {
 	"load_store",
 	"insn_fetch",
@@ -69,7 +70,12 @@ static const char * const smca_umc_block
 	"misc_umc"
 };
 
-struct smca_bank_name smca_bank_names[] = {
+struct smca_bank_name {
+	const char *name;	/* Short name for sysfs */
+	const char *long_name;	/* Long name for pretty-printing */
+};
+
+static struct smca_bank_name smca_names[] = {
 	[SMCA_LS]	= { "load_store",	"Load Store Unit" },
 	[SMCA_IF]	= { "insn_fetch",	"Instruction Fetch Unit" },
 	[SMCA_L2_CACHE]	= { "l2_cache",		"L2 Cache" },
@@ -84,9 +90,25 @@ struct smca_bank_name smca_bank_names[]
 	[SMCA_PSP]	= { "psp",		"Platform Security Processor" },
 	[SMCA_SMU]	= { "smu",		"System Management Unit" },
 };
-EXPORT_SYMBOL_GPL(smca_bank_names);
 
-static struct smca_hwid_mcatype smca_hwid_mcatypes[] = {
+const char *smca_get_name(enum smca_bank_types t)
+{
+	if (t >= N_SMCA_BANK_TYPES)
+		return NULL;
+
+	return smca_names[t].name;
+}
+
+const char *smca_get_long_name(enum smca_bank_types t)
+{
+	if (t >= N_SMCA_BANK_TYPES)
+		return NULL;
+
+	return smca_names[t].long_name;
+}
+EXPORT_SYMBOL_GPL(smca_get_long_name);
+
+static struct smca_hwid smca_hwid_mcatypes[] = {
 	/* { bank_type, hwid_mcatype, xec_bitmap } */
 
 	/* ZN Core (HWID=0xB0) MCA types */
@@ -116,7 +138,7 @@ static struct smca_hwid_mcatype smca_hwi
 	{ SMCA_SMU,	 HWID_MCATYPE(0x01, 0x0), 0x1 },
 };
 
-struct smca_bank_info smca_banks[MAX_NR_BANKS];
+struct smca_bank smca_banks[MAX_NR_BANKS];
 EXPORT_SYMBOL_GPL(smca_banks);
 
 /*
@@ -142,35 +164,34 @@ static void default_deferred_error_inter
 }
 void (*deferred_error_int_vector)(void) = default_deferred_error_interrupt;
 
-/*
- * CPU Initialization
- */
-
 static void get_smca_bank_info(unsigned int bank)
 {
 	unsigned int i, hwid_mcatype, cpu = smp_processor_id();
-	struct smca_hwid_mcatype *type;
-	u32 high, instanceId;
-	u16 hwid, mcatype;
+	struct smca_hwid *s_hwid;
+	u32 high, instance_id;
 
 	/* Collect bank_info using CPU 0 for now. */
 	if (cpu)
 		return;
 
-	if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &instanceId, &high)) {
+	if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &instance_id, &high)) {
 		pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
 		return;
 	}
 
-	hwid = high & MCI_IPID_HWID;
-	mcatype = (high & MCI_IPID_MCATYPE) >> 16;
-	hwid_mcatype = HWID_MCATYPE(hwid, mcatype);
+	hwid_mcatype = HWID_MCATYPE(high & MCI_IPID_HWID,
+				    (high & MCI_IPID_MCATYPE) >> 16);
 
 	for (i = 0; i < ARRAY_SIZE(smca_hwid_mcatypes); i++) {
-		type = &smca_hwid_mcatypes[i];
-		if (hwid_mcatype == type->hwid_mcatype) {
-			smca_banks[bank].type = type;
-			smca_banks[bank].type_instance = instanceId;
+		s_hwid = &smca_hwid_mcatypes[i];
+		if (hwid_mcatype == s_hwid->hwid_mcatype) {
+
+			WARN(smca_banks[bank].hwid,
+			     "Bank %s already initialized!\n",
+			     smca_get_name(s_hwid->bank_type));
+
+			smca_banks[bank].hwid = s_hwid;
+			smca_banks[bank].id = instance_id;
 			break;
 		}
 	}
@@ -533,6 +554,206 @@ void mce_amd_feature_init(struct cpuinfo
 		deferred_error_interrupt_enable(c);
 }
 
+int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr)
+{
+	u64 dram_base_addr, dram_limit_addr, dram_hole_base;
+	/* We start from the normalized address */
+	u64 ret_addr = norm_addr;
+
+	u32 tmp;
+
+	u8 die_id_shift, die_id_mask, socket_id_shift, socket_id_mask;
+	u8 intlv_num_dies, intlv_num_chan, intlv_num_sockets;
+	u8 intlv_addr_sel, intlv_addr_bit;
+	u8 num_intlv_bits, hashed_bit;
+	u8 lgcy_mmio_hole_en, base = 0;
+	u8 cs_mask, cs_id = 0;
+	bool hash_enabled = false;
+
+	/* Read D18F0x1B4 (DramOffset), check if base 1 is used. */
+	if (amd_df_indirect_read(nid, 0, 0x1B4, umc, &tmp))
+		goto out_err;
+
+	/* Remove HiAddrOffset from normalized address, if enabled: */
+	if (tmp & BIT(0)) {
+		u64 hi_addr_offset = (tmp & GENMASK_ULL(31, 20)) << 8;
+
+		if (norm_addr >= hi_addr_offset) {
+			ret_addr -= hi_addr_offset;
+			base = 1;
+		}
+	}
+
+	/* Read D18F0x110 (DramBaseAddress). */
+	if (amd_df_indirect_read(nid, 0, 0x110 + (8 * base), umc, &tmp))
+		goto out_err;
+
+	/* Check if address range is valid. */
+	if (!(tmp & BIT(0))) {
+		pr_err("%s: Invalid DramBaseAddress range: 0x%x.\n",
+			__func__, tmp);
+		goto out_err;
+	}
+
+	lgcy_mmio_hole_en = tmp & BIT(1);
+	intlv_num_chan	  = (tmp >> 4) & 0xF;
+	intlv_addr_sel	  = (tmp >> 8) & 0x7;
+	dram_base_addr	  = (tmp & GENMASK_ULL(31, 12)) << 16;
+
+	/* {0, 1, 2, 3} map to address bits {8, 9, 10, 11} respectively */
+	if (intlv_addr_sel > 3) {
+		pr_err("%s: Invalid interleave address select %d.\n",
+			__func__, intlv_addr_sel);
+		goto out_err;
+	}
+
+	/* Read D18F0x114 (DramLimitAddress). */
+	if (amd_df_indirect_read(nid, 0, 0x114 + (8 * base), umc, &tmp))
+		goto out_err;
+
+	intlv_num_sockets = (tmp >> 8) & 0x1;
+	intlv_num_dies	  = (tmp >> 10) & 0x3;
+	dram_limit_addr	  = ((tmp & GENMASK_ULL(31, 12)) << 16) | GENMASK_ULL(27, 0);
+
+	intlv_addr_bit = intlv_addr_sel + 8;
+
+	/* Re-use intlv_num_chan by setting it equal to log2(#channels) */
+	switch (intlv_num_chan) {
+	case 0:	intlv_num_chan = 0; break;
+	case 1: intlv_num_chan = 1; break;
+	case 3: intlv_num_chan = 2; break;
+	case 5:	intlv_num_chan = 3; break;
+	case 7:	intlv_num_chan = 4; break;
+
+	case 8: intlv_num_chan = 1;
+		hash_enabled = true;
+		break;
+	default:
+		pr_err("%s: Invalid number of interleaved channels %d.\n",
+			__func__, intlv_num_chan);
+		goto out_err;
+	}
+
+	num_intlv_bits = intlv_num_chan;
+
+	if (intlv_num_dies > 2) {
+		pr_err("%s: Invalid number of interleaved nodes/dies %d.\n",
+			__func__, intlv_num_dies);
+		goto out_err;
+	}
+
+	num_intlv_bits += intlv_num_dies;
+
+	/* Add a bit if sockets are interleaved. */
+	num_intlv_bits += intlv_num_sockets;
+
+	/* Assert num_intlv_bits <= 4 */
+	if (num_intlv_bits > 4) {
+		pr_err("%s: Invalid interleave bits %d.\n",
+			__func__, num_intlv_bits);
+		goto out_err;
+	}
+
+	if (num_intlv_bits > 0) {
+		u64 temp_addr_x, temp_addr_i, temp_addr_y;
+		u8 die_id_bit, sock_id_bit, cs_fabric_id;
+
+		/*
+		 * Read FabricBlockInstanceInformation3_CS[BlockFabricID].
+		 * This is the fabric id for this coherent slave. Use
+		 * umc/channel# as instance id of the coherent slave
+		 * for FICAA.
+		 */
+		if (amd_df_indirect_read(nid, 0, 0x50, umc, &tmp))
+			goto out_err;
+
+		cs_fabric_id = (tmp >> 8) & 0xFF;
+		die_id_bit   = 0;
+
+		/* If interleaved over more than 1 channel: */
+		if (intlv_num_chan) {
+			die_id_bit = intlv_num_chan;
+			cs_mask	   = (1 << die_id_bit) - 1;
+			cs_id	   = cs_fabric_id & cs_mask;
+		}
+
+		sock_id_bit = die_id_bit;
+
+		/* Read D18F1x208 (SystemFabricIdMask). */
+		if (intlv_num_dies || intlv_num_sockets)
+			if (amd_df_indirect_read(nid, 1, 0x208, umc, &tmp))
+				goto out_err;
+
+		/* If interleaved over more than 1 die. */
+		if (intlv_num_dies) {
+			sock_id_bit  = die_id_bit + intlv_num_dies;
+			die_id_shift = (tmp >> 24) & 0xF;
+			die_id_mask  = (tmp >> 8) & 0xFF;
+
+			cs_id |= ((cs_fabric_id & die_id_mask) >> die_id_shift) << die_id_bit;
+		}
+
+		/* If interleaved over more than 1 socket. */
+		if (intlv_num_sockets) {
+			socket_id_shift	= (tmp >> 28) & 0xF;
+			socket_id_mask	= (tmp >> 16) & 0xFF;
+
+			cs_id |= ((cs_fabric_id & socket_id_mask) >> socket_id_shift) << sock_id_bit;
+		}
+
+		/*
+		 * The pre-interleaved address consists of XXXXXXIIIYYYYY
+		 * where III is the ID for this CS, and XXXXXXYYYYY are the
+		 * address bits from the post-interleaved address.
+		 * "num_intlv_bits" has been calculated to tell us how many "I"
+		 * bits there are. "intlv_addr_bit" tells us how many "Y" bits
+		 * there are (where "I" starts).
+		 */
+		temp_addr_y = ret_addr & GENMASK_ULL(intlv_addr_bit-1, 0);
+		temp_addr_i = (cs_id << intlv_addr_bit);
+		temp_addr_x = (ret_addr & GENMASK_ULL(63, intlv_addr_bit)) << num_intlv_bits;
+		ret_addr    = temp_addr_x | temp_addr_i | temp_addr_y;
+	}
+
+	/* Add dram base address */
+	ret_addr += dram_base_addr;
+
+	/* If legacy MMIO hole enabled */
+	if (lgcy_mmio_hole_en) {
+		if (amd_df_indirect_read(nid, 0, 0x104, umc, &tmp))
+			goto out_err;
+
+		dram_hole_base = tmp & GENMASK(31, 24);
+		if (ret_addr >= dram_hole_base)
+			ret_addr += (BIT_ULL(32) - dram_hole_base);
+	}
+
+	if (hash_enabled) {
+		/* Save some parentheses and grab ls-bit at the end. */
+		hashed_bit =	(ret_addr >> 12) ^
+				(ret_addr >> 18) ^
+				(ret_addr >> 21) ^
+				(ret_addr >> 30) ^
+				cs_id;
+
+		hashed_bit &= BIT(0);
+
+		if (hashed_bit != ((ret_addr >> intlv_addr_bit) & BIT(0)))
+			ret_addr ^= BIT(intlv_addr_bit);
+	}
+
+	/* Is calculated system address is above DRAM limit address? */
+	if (ret_addr > dram_limit_addr)
+		goto out_err;
+
+	*sys_addr = ret_addr;
+	return 0;
+
+out_err:
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
+
 static void
 __log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
 {
@@ -645,6 +866,7 @@ static void amd_threshold_interrupt(void
 {
 	u32 low = 0, high = 0, address = 0;
 	unsigned int bank, block, cpu = smp_processor_id();
+	struct thresh_restart tr;
 
 	/* assume first bank caused it */
 	for (bank = 0; bank < mca_cfg.banks; ++bank) {
@@ -681,6 +903,11 @@ static void amd_threshold_interrupt(void
 
 log:
 	__log_error(bank, false, true, ((u64)high << 32) | low);
+
+	/* Reset threshold block after logging error. */
+	memset(&tr, 0, sizeof(tr));
+	tr.b = &per_cpu(threshold_banks, cpu)[bank]->blocks[block];
+	threshold_restart_bank(&tr);
 }
 
 /*
@@ -826,10 +1053,10 @@ static const char *get_name(unsigned int
 		return th_names[bank];
 	}
 
-	if (!smca_banks[bank].type)
+	if (!smca_banks[bank].hwid)
 		return NULL;
 
-	bank_type = smca_banks[bank].type->bank_type;
+	bank_type = smca_banks[bank].hwid->bank_type;
 
 	if (b && bank_type == SMCA_UMC) {
 		if (b->block < ARRAY_SIZE(smca_umc_block_names))
@@ -838,8 +1065,8 @@ static const char *get_name(unsigned int
 	}
 
 	snprintf(buf_mcatype, MAX_MCATYPE_NAME_LEN,
-		 "%s_%x", smca_bank_names[bank_type].name,
-			  smca_banks[bank].type_instance);
+		 "%s_%x", smca_get_name(bank_type),
+			  smca_banks[bank].id);
 	return buf_mcatype;
 }
 
@@ -955,6 +1182,9 @@ static int threshold_create_bank(unsigne
 	const char *name = get_name(bank, NULL);
 	int err = 0;
 
+	if (!dev)
+		return -ENODEV;
+
 	if (is_shared_bank(bank)) {
 		nb = node_to_amd_nb(amd_get_nb_id(cpu));
 
@@ -1010,31 +1240,6 @@ static int threshold_create_bank(unsigne
 	return err;
 }
 
-/* create dir/files for all valid threshold banks */
-static int threshold_create_device(unsigned int cpu)
-{
-	unsigned int bank;
-	struct threshold_bank **bp;
-	int err = 0;
-
-	bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks,
-		     GFP_KERNEL);
-	if (!bp)
-		return -ENOMEM;
-
-	per_cpu(threshold_banks, cpu) = bp;
-
-	for (bank = 0; bank < mca_cfg.banks; ++bank) {
-		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
-			continue;
-		err = threshold_create_bank(cpu, bank);
-		if (err)
-			return err;
-	}
-
-	return err;
-}
-
 static void deallocate_threshold_block(unsigned int cpu,
 						 unsigned int bank)
 {
@@ -1102,48 +1307,71 @@ free_out:
 	per_cpu(threshold_banks, cpu)[bank] = NULL;
 }
 
-static void threshold_remove_device(unsigned int cpu)
+int mce_threshold_remove_device(unsigned int cpu)
 {
 	unsigned int bank;
 
+	if (!thresholding_en)
+		return 0;
+
 	for (bank = 0; bank < mca_cfg.banks; ++bank) {
 		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
 			continue;
 		threshold_remove_bank(cpu, bank);
 	}
 	kfree(per_cpu(threshold_banks, cpu));
+	per_cpu(threshold_banks, cpu) = NULL;
+	return 0;
 }
 
-/* get notified when a cpu comes on/off */
-static void
-amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu)
+/* create dir/files for all valid threshold banks */
+int mce_threshold_create_device(unsigned int cpu)
 {
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		threshold_create_device(cpu);
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		threshold_remove_device(cpu);
-		break;
-	default:
-		break;
+	unsigned int bank;
+	struct threshold_bank **bp;
+	int err = 0;
+
+	if (!thresholding_en)
+		return 0;
+
+	bp = per_cpu(threshold_banks, cpu);
+	if (bp)
+		return 0;
+
+	bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks,
+		     GFP_KERNEL);
+	if (!bp)
+		return -ENOMEM;
+
+	per_cpu(threshold_banks, cpu) = bp;
+
+	for (bank = 0; bank < mca_cfg.banks; ++bank) {
+		if (!(per_cpu(bank_map, cpu) & (1 << bank)))
+			continue;
+		err = threshold_create_bank(cpu, bank);
+		if (err)
+			goto err;
 	}
+	return err;
+err:
+	mce_threshold_remove_device(cpu);
+	return err;
 }
 
 static __init int threshold_init_device(void)
 {
 	unsigned lcpu = 0;
 
+	if (mce_threshold_vector == amd_threshold_interrupt)
+		thresholding_en = true;
+
 	/* to hit CPUs online before the notifier is up */
 	for_each_online_cpu(lcpu) {
-		int err = threshold_create_device(lcpu);
+		int err = mce_threshold_create_device(lcpu);
 
 		if (err)
 			return err;
 	}
-	threshold_cpu_callback = amd_64_threshold_cpu_callback;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,7 @@
 #include <linux/export.h>
 #include <linux/jump_label.h>
 
+#include <asm/intel-family.h>
 #include <asm/processor.h>
 #include <asm/traps.h>
 #include <asm/tlbflush.h>
@@ -135,6 +136,9 @@ void mce_setup(struct mce *m)
 	m->socketid = cpu_data(m->extcpu).phys_proc_id;
 	m->apicid = cpu_data(m->extcpu).initial_apicid;
 	rdmsrl(MSR_IA32_MCG_CAP, m->mcgcap);
+
+	if (this_cpu_has(X86_FEATURE_INTEL_PPIN))
+		rdmsrl(MSR_PPIN, m->ppin);
 }
 
 DEFINE_PER_CPU(struct mce, injectm);
@@ -207,8 +211,12 @@ EXPORT_SYMBOL_GPL(mce_inject_log);
 
 static struct notifier_block mce_srao_nb;
 
+static atomic_t num_notifiers;
+
 void mce_register_decode_chain(struct notifier_block *nb)
 {
+	atomic_inc(&num_notifiers);
+
 	/* Ensure SRAO notifier has the highest priority in the decode chain. */
 	if (nb != &mce_srao_nb && nb->priority == INT_MAX)
 		nb->priority -= 1;
@@ -219,6 +227,8 @@ EXPORT_SYMBOL_GPL(mce_register_decode_ch
 
 void mce_unregister_decode_chain(struct notifier_block *nb)
 {
+	atomic_dec(&num_notifiers);
+
 	atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb);
 }
 EXPORT_SYMBOL_GPL(mce_unregister_decode_chain);
@@ -270,17 +280,17 @@ struct mca_msr_regs msr_ops = {
 	.misc	= misc_reg
 };
 
-static void print_mce(struct mce *m)
+static void __print_mce(struct mce *m)
 {
-	int ret = 0;
-
-	pr_emerg(HW_ERR "CPU %d: Machine Check Exception: %Lx Bank %d: %016Lx\n",
-	       m->extcpu, m->mcgstatus, m->bank, m->status);
+	pr_emerg(HW_ERR "CPU %d: Machine Check%s: %Lx Bank %d: %016Lx\n",
+		 m->extcpu,
+		 (m->mcgstatus & MCG_STATUS_MCIP ? " Exception" : ""),
+		 m->mcgstatus, m->bank, m->status);
 
 	if (m->ip) {
 		pr_emerg(HW_ERR "RIP%s %02x:<%016Lx> ",
 			!(m->mcgstatus & MCG_STATUS_EIPV) ? " !INEXACT!" : "",
-				m->cs, m->ip);
+			m->cs, m->ip);
 
 		if (m->cs == __KERNEL_CS)
 			print_symbol("{%s}", m->ip);
@@ -308,6 +318,13 @@ static void print_mce(struct mce *m)
 	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);
+}
+
+static void print_mce(struct mce *m)
+{
+	int ret = 0;
+
+	__print_mce(m);
 
 	/*
 	 * Print out human-readable details about the MCE error,
@@ -499,7 +516,7 @@ int mce_available(struct cpuinfo_x86 *c)
 
 static void mce_schedule_work(void)
 {
-	if (!mce_gen_pool_empty() && keventd_up())
+	if (!mce_gen_pool_empty())
 		schedule_work(&mce_work);
 }
 
@@ -569,6 +586,32 @@ static struct notifier_block mce_srao_nb
 	.priority = INT_MAX,
 };
 
+static int mce_default_notifier(struct notifier_block *nb, unsigned long val,
+				void *data)
+{
+	struct mce *m = (struct mce *)data;
+
+	if (!m)
+		return NOTIFY_DONE;
+
+	/*
+	 * Run the default notifier if we have only the SRAO
+	 * notifier and us registered.
+	 */
+	if (atomic_read(&num_notifiers) > 2)
+		return NOTIFY_DONE;
+
+	__print_mce(m);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block mce_default_nb = {
+	.notifier_call	= mce_default_notifier,
+	/* lowest prio, we want it to run last. */
+	.priority	= 0,
+};
+
 /*
  * Read ADDR and MISC registers.
  */
@@ -667,6 +710,15 @@ bool machine_check_poll(enum mcp_flags f
 
 	mce_gather_info(&m, NULL);
 
+	/*
+	 * m.tsc was set in mce_setup(). Clear it if not requested.
+	 *
+	 * FIXME: Propagate @flags to mce_gather_info/mce_setup() to avoid
+	 *	  that dance.
+	 */
+	if (!(flags & MCP_TIMESTAMP))
+		m.tsc = 0;
+
 	for (i = 0; i < mca_cfg.banks; i++) {
 		if (!mce_banks[i].ctl || !test_bit(i, *b))
 			continue;
@@ -674,14 +726,12 @@ bool machine_check_poll(enum mcp_flags f
 		m.misc = 0;
 		m.addr = 0;
 		m.bank = i;
-		m.tsc = 0;
 
 		barrier();
 		m.status = mce_rdmsrl(msr_ops.status(i));
 		if (!(m.status & MCI_STATUS_VAL))
 			continue;
 
-
 		/*
 		 * Uncorrected or signalled events are handled by the exception
 		 * handler when it is enabled, so don't process those here.
@@ -696,9 +746,6 @@ bool machine_check_poll(enum mcp_flags f
 
 		mce_read_aux(&m, i);
 
-		if (!(flags & MCP_TIMESTAMP))
-			m.tsc = 0;
-
 		severity = mce_severity(&m, mca_cfg.tolerant, NULL, false);
 
 		if (severity == MCE_DEFERRED_SEVERITY && memory_error(&m))
@@ -1326,20 +1373,15 @@ static unsigned long mce_adjust_timer_de
 
 static unsigned long (*mce_adjust_timer)(unsigned long interval) = mce_adjust_timer_default;
 
-static void __restart_timer(struct timer_list *t, unsigned long interval)
+static void __start_timer(struct timer_list *t, unsigned long interval)
 {
 	unsigned long when = jiffies + interval;
 	unsigned long flags;
 
 	local_irq_save(flags);
 
-	if (timer_pending(t)) {
-		if (time_before(when, t->expires))
-			mod_timer(t, when);
-	} else {
-		t->expires = round_jiffies(when);
-		add_timer_on(t, smp_processor_id());
-	}
+	if (!timer_pending(t) || time_before(when, t->expires))
+		mod_timer(t, round_jiffies(when));
 
 	local_irq_restore(flags);
 }
@@ -1355,7 +1397,7 @@ static void mce_timer_fn(unsigned long d
 	iv = __this_cpu_read(mce_next_interval);
 
 	if (mce_available(this_cpu_ptr(&cpu_info))) {
-		machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_poll_banks));
+		machine_check_poll(0, this_cpu_ptr(&mce_poll_banks));
 
 		if (mce_intel_cmci_poll()) {
 			iv = mce_adjust_timer(iv);
@@ -1374,7 +1416,7 @@ static void mce_timer_fn(unsigned long d
 
 done:
 	__this_cpu_write(mce_next_interval, iv);
-	__restart_timer(t, iv);
+	__start_timer(t, iv);
 }
 
 /*
@@ -1385,7 +1427,7 @@ void mce_timer_kick(unsigned long interv
 	struct timer_list *t = this_cpu_ptr(&mce_timer);
 	unsigned long iv = __this_cpu_read(mce_next_interval);
 
-	__restart_timer(t, interval);
+	__start_timer(t, interval);
 
 	if (interval < iv)
 		__this_cpu_write(mce_next_interval, interval);
@@ -1732,17 +1774,23 @@ static void __mcheck_cpu_clear_vendor(st
 	}
 }
 
-static void mce_start_timer(unsigned int cpu, struct timer_list *t)
+static void mce_start_timer(struct timer_list *t)
 {
 	unsigned long iv = check_interval * HZ;
 
 	if (mca_cfg.ignore_ce || !iv)
 		return;
 
-	per_cpu(mce_next_interval, cpu) = iv;
+	this_cpu_write(mce_next_interval, iv);
+	__start_timer(t, iv);
+}
 
-	t->expires = round_jiffies(jiffies + iv);
-	add_timer_on(t, cpu);
+static void __mcheck_cpu_setup_timer(void)
+{
+	struct timer_list *t = this_cpu_ptr(&mce_timer);
+	unsigned int cpu = smp_processor_id();
+
+	setup_pinned_timer(t, mce_timer_fn, cpu);
 }
 
 static void __mcheck_cpu_init_timer(void)
@@ -1751,7 +1799,7 @@ static void __mcheck_cpu_init_timer(void
 	unsigned int cpu = smp_processor_id();
 
 	setup_pinned_timer(t, mce_timer_fn, cpu);
-	mce_start_timer(cpu, t);
+	mce_start_timer(t);
 }
 
 /* Handle unconfigured int18 (should never happen) */
@@ -1796,7 +1844,7 @@ void mcheck_cpu_init(struct cpuinfo_x86
 	__mcheck_cpu_init_generic();
 	__mcheck_cpu_init_vendor(c);
 	__mcheck_cpu_init_clear_banks();
-	__mcheck_cpu_init_timer();
+	__mcheck_cpu_setup_timer();
 }
 
 /*
@@ -2138,6 +2186,7 @@ int __init mcheck_init(void)
 {
 	mcheck_intel_therm_init();
 	mce_register_decode_chain(&mce_srao_nb);
+	mce_register_decode_chain(&mce_default_nb);
 	mcheck_vendor_init_severity();
 
 	INIT_WORK(&mce_work, mce_process_work);
@@ -2255,8 +2304,6 @@ static struct bus_type mce_subsys = {
 
 DEFINE_PER_CPU(struct device *, mce_device);
 
-void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu);
-
 static inline struct mce_bank *attr_to_bank(struct device_attribute *attr)
 {
 	return container_of(attr, struct mce_bank, attr);
@@ -2409,6 +2456,10 @@ static int mce_device_create(unsigned in
 	if (!mce_available(&boot_cpu_data))
 		return -EIO;
 
+	dev = per_cpu(mce_device, cpu);
+	if (dev)
+		return 0;
+
 	dev = kzalloc(sizeof *dev, GFP_KERNEL);
 	if (!dev)
 		return -ENOMEM;
@@ -2468,28 +2519,25 @@ static void mce_device_remove(unsigned i
 }
 
 /* Make sure there are no machine checks on offlined CPUs. */
-static void mce_disable_cpu(void *h)
+static void mce_disable_cpu(void)
 {
-	unsigned long action = *(unsigned long *)h;
-
 	if (!mce_available(raw_cpu_ptr(&cpu_info)))
 		return;
 
-	if (!(action & CPU_TASKS_FROZEN))
+	if (!cpuhp_tasks_frozen)
 		cmci_clear();
 
 	vendor_disable_error_reporting();
 }
 
-static void mce_reenable_cpu(void *h)
+static void mce_reenable_cpu(void)
 {
-	unsigned long action = *(unsigned long *)h;
 	int i;
 
 	if (!mce_available(raw_cpu_ptr(&cpu_info)))
 		return;
 
-	if (!(action & CPU_TASKS_FROZEN))
+	if (!cpuhp_tasks_frozen)
 		cmci_reenable();
 	for (i = 0; i < mca_cfg.banks; i++) {
 		struct mce_bank *b = &mce_banks[i];
@@ -2499,45 +2547,43 @@ static void mce_reenable_cpu(void *h)
 	}
 }
 
-/* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static int
-mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int mce_cpu_dead(unsigned int cpu)
 {
-	unsigned int cpu = (unsigned long)hcpu;
-	struct timer_list *t = &per_cpu(mce_timer, cpu);
+	mce_intel_hcpu_update(cpu);
 
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_ONLINE:
-		mce_device_create(cpu);
-		if (threshold_cpu_callback)
-			threshold_cpu_callback(action, cpu);
-		break;
-	case CPU_DEAD:
-		if (threshold_cpu_callback)
-			threshold_cpu_callback(action, cpu);
-		mce_device_remove(cpu);
-		mce_intel_hcpu_update(cpu);
+	/* intentionally ignoring frozen here */
+	if (!cpuhp_tasks_frozen)
+		cmci_rediscover();
+	return 0;
+}
 
-		/* intentionally ignoring frozen here */
-		if (!(action & CPU_TASKS_FROZEN))
-			cmci_rediscover();
-		break;
-	case CPU_DOWN_PREPARE:
-		smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
-		del_timer_sync(t);
-		break;
-	case CPU_DOWN_FAILED:
-		smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
-		mce_start_timer(cpu, t);
-		break;
-	}
+static int mce_cpu_online(unsigned int cpu)
+{
+	struct timer_list *t = this_cpu_ptr(&mce_timer);
+	int ret;
 
-	return NOTIFY_OK;
+	mce_device_create(cpu);
+
+	ret = mce_threshold_create_device(cpu);
+	if (ret) {
+		mce_device_remove(cpu);
+		return ret;
+	}
+	mce_reenable_cpu();
+	mce_start_timer(t);
+	return 0;
 }
 
-static struct notifier_block mce_cpu_notifier = {
-	.notifier_call = mce_cpu_callback,
-};
+static int mce_cpu_pre_down(unsigned int cpu)
+{
+	struct timer_list *t = this_cpu_ptr(&mce_timer);
+
+	mce_disable_cpu();
+	del_timer_sync(t);
+	mce_threshold_remove_device(cpu);
+	mce_device_remove(cpu);
+	return 0;
+}
 
 static __init void mce_init_banks(void)
 {
@@ -2559,8 +2605,8 @@ static __init void mce_init_banks(void)
 
 static __init int mcheck_init_device(void)
 {
+	enum cpuhp_state hp_online;
 	int err;
-	int i = 0;
 
 	if (!mce_available(&boot_cpu_data)) {
 		err = -EIO;
@@ -2578,23 +2624,16 @@ static __init int mcheck_init_device(voi
 	if (err)
 		goto err_out_mem;
 
-	cpu_notifier_register_begin();
-	for_each_online_cpu(i) {
-		err = mce_device_create(i);
-		if (err) {
-			/*
-			 * Register notifier anyway (and do not unreg it) so
-			 * that we don't leave undeleted timers, see notifier
-			 * callback above.
-			 */
-			__register_hotcpu_notifier(&mce_cpu_notifier);
-			cpu_notifier_register_done();
-			goto err_device_create;
-		}
-	}
+	err = cpuhp_setup_state(CPUHP_X86_MCE_DEAD, "x86/mce:dead", NULL,
+				mce_cpu_dead);
+	if (err)
+		goto err_out_mem;
 
-	__register_hotcpu_notifier(&mce_cpu_notifier);
-	cpu_notifier_register_done();
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/mce:online",
+				mce_cpu_online, mce_cpu_pre_down);
+	if (err < 0)
+		goto err_out_online;
+	hp_online = err;
 
 	register_syscore_ops(&mce_syscore_ops);
 
@@ -2607,16 +2646,10 @@ static __init int mcheck_init_device(voi
 
 err_register:
 	unregister_syscore_ops(&mce_syscore_ops);
+	cpuhp_remove_state(hp_online);
 
-err_device_create:
-	/*
-	 * We didn't keep track of which devices were created above, but
-	 * even if we had, the set of online cpus might have changed.
-	 * Play safe and remove for every possible cpu, since
-	 * mce_device_remove() will do the right thing.
-	 */
-	for_each_possible_cpu(i)
-		mce_device_remove(i);
+err_out_online:
+	cpuhp_remove_state(CPUHP_X86_MCE_DEAD);
 
 err_out_mem:
 	free_cpumask_var(mce_device_initialized);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce_intel.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,8 @@
 #include <linux/sched.h>
 #include <linux/cpumask.h>
 #include <asm/apic.h>
+#include <asm/cpufeature.h>
+#include <asm/intel-family.h>
 #include <asm/processor.h>
 #include <asm/msr.h>
 #include <asm/mce.h>
@@ -130,7 +132,7 @@ bool mce_intel_cmci_poll(void)
 	 * Reset the counter if we've logged an error in the last poll
 	 * during the storm.
 	 */
-	if (machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned)))
+	if (machine_check_poll(0, this_cpu_ptr(&mce_banks_owned)))
 		this_cpu_write(cmci_backoff_cnt, INITIAL_CHECK_INTERVAL);
 	else
 		this_cpu_dec(cmci_backoff_cnt);
@@ -342,7 +344,7 @@ void cmci_recheck(void)
 		return;
 
 	local_irq_save(flags);
-	machine_check_poll(MCP_TIMESTAMP, this_cpu_ptr(&mce_banks_owned));
+	machine_check_poll(0, this_cpu_ptr(&mce_banks_owned));
 	local_irq_restore(flags);
 }
 
@@ -464,11 +466,46 @@ static void intel_clear_lmce(void)
 	wrmsrl(MSR_IA32_MCG_EXT_CTL, val);
 }
 
+static void intel_ppin_init(struct cpuinfo_x86 *c)
+{
+	unsigned long long val;
+
+	/*
+	 * Even if testing the presence of the MSR would be enough, we don't
+	 * want to risk the situation where other models reuse this MSR for
+	 * other purposes.
+	 */
+	switch (c->x86_model) {
+	case INTEL_FAM6_IVYBRIDGE_X:
+	case INTEL_FAM6_HASWELL_X:
+	case INTEL_FAM6_BROADWELL_XEON_D:
+	case INTEL_FAM6_BROADWELL_X:
+	case INTEL_FAM6_SKYLAKE_X:
+		if (rdmsrl_safe(MSR_PPIN_CTL, &val))
+			return;
+
+		if ((val & 3UL) == 1UL) {
+			/* PPIN available but disabled: */
+			return;
+		}
+
+		/* If PPIN is disabled, but not locked, try to enable: */
+		if (!(val & 3UL)) {
+			wrmsrl_safe(MSR_PPIN_CTL,  val | 2UL);
+			rdmsrl_safe(MSR_PPIN_CTL, &val);
+		}
+
+		if ((val & 3UL) == 2UL)
+			set_cpu_cap(c, X86_FEATURE_INTEL_PPIN);
+	}
+}
+
 void mce_intel_feature_init(struct cpuinfo_x86 *c)
 {
 	intel_init_thermal(c);
 	intel_init_cmci();
 	intel_init_lmce();
+	intel_ppin_init(c);
 }
 
 void mce_intel_feature_clear(struct cpuinfo_x86 *c)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/mce-severity.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/debugfs.h>
 #include <asm/mce.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "mce-internal.h"
 
@@ -311,7 +311,7 @@ static int mce_severity_intel(struct mce
 			*msg = s->msg;
 		s->covered = 1;
 		if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL) {
-			if (panic_on_oops || tolerant < 1)
+			if (tolerant < 1)
 				return MCE_PANIC_SEVERITY;
 		}
 		return s->sev;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,6 @@
 
 #include <asm/processor.h>
 #include <asm/apic.h>
-#include <asm/idle.h>
 #include <asm/mce.h>
 #include <asm/msr.h>
 #include <asm/trace/irq_vectors.h>
@@ -271,58 +270,32 @@ static void thermal_throttle_remove_dev(
 }
 
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static int
-thermal_throttle_cpu_callback(struct notifier_block *nfb,
-			      unsigned long action,
-			      void *hcpu)
+static int thermal_throttle_online(unsigned int cpu)
 {
-	unsigned int cpu = (unsigned long)hcpu;
-	struct device *dev;
-	int err = 0;
-
-	dev = get_cpu_device(cpu);
+	struct device *dev = get_cpu_device(cpu);
 
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		err = thermal_throttle_add_dev(dev, cpu);
-		WARN_ON(err);
-		break;
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		thermal_throttle_remove_dev(dev);
-		break;
-	}
-	return notifier_from_errno(err);
+	return thermal_throttle_add_dev(dev, cpu);
 }
 
-static struct notifier_block thermal_throttle_cpu_notifier =
+static int thermal_throttle_offline(unsigned int cpu)
 {
-	.notifier_call = thermal_throttle_cpu_callback,
-};
+	struct device *dev = get_cpu_device(cpu);
+
+	thermal_throttle_remove_dev(dev);
+	return 0;
+}
 
 static __init int thermal_throttle_init_device(void)
 {
-	unsigned int cpu = 0;
-	int err;
+	int ret;
 
 	if (!atomic_read(&therm_throt_en))
 		return 0;
 
-	cpu_notifier_register_begin();
-
-	/* connect live CPUs to sysfs */
-	for_each_online_cpu(cpu) {
-		err = thermal_throttle_add_dev(get_cpu_device(cpu), cpu);
-		WARN_ON(err);
-	}
-
-	__register_hotcpu_notifier(&thermal_throttle_cpu_notifier);
-	cpu_notifier_register_done();
-
-	return 0;
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/therm:online",
+				thermal_throttle_online,
+				thermal_throttle_offline);
+	return ret < 0 ? ret : 0;
 }
 device_initcall(thermal_throttle_init_device);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/threshold.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/threshold.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/mcheck/threshold.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mcheck/threshold.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,6 @@
 
 #include <asm/irq_vectors.h>
 #include <asm/apic.h>
-#include <asm/idle.h>
 #include <asm/mce.h>
 #include <asm/trace/irq_vectors.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/amd.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/amd.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/amd.c	2016-12-11 17:39:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/amd.c	2017-02-12 17:21:21.000000000 -0500
@@ -5,6 +5,7 @@
  *  CPUs and later.
  *
  *  Copyright (C) 2008-2011 Advanced Micro Devices Inc.
+ *	          2013-2016 Borislav Petkov <bp@alien8.de>
  *
  *  Author: Peter Oruba <peter.oruba@amd.com>
  *
@@ -39,64 +40,25 @@
 
 static struct equiv_cpu_entry *equiv_cpu_table;
 
-struct ucode_patch {
-	struct list_head plist;
-	void *data;
-	u32 patch_id;
-	u16 equiv_cpu;
-};
-
-static LIST_HEAD(pcache);
-
 /*
  * This points to the current valid container of microcode patches which we will
- * save from the initrd before jettisoning its contents.
+ * save from the initrd/builtin before jettisoning its contents.
  */
-static u8 *container;
-static size_t container_size;
-static bool ucode_builtin;
+struct container {
+	u8 *data;
+	size_t size;
+} cont;
 
 static u32 ucode_new_rev;
 static u8 amd_ucode_patch[PATCH_MAX_SIZE];
 static u16 this_equiv_id;
 
-static struct cpio_data ucode_cpio;
-
-static struct cpio_data __init find_ucode_in_initrd(void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
-	char *path;
-	void *start;
-	size_t size;
-
-	/*
-	 * Microcode patch container file is prepended to the initrd in cpio
-	 * format. See Documentation/x86/early-microcode.txt
-	 */
-	static __initdata char ucode_path[] = "/*(DEBLOBBED)*/";
-
-#ifdef CONFIG_X86_32
-	struct boot_params *p;
-
-	/*
-	 * On 32-bit, early load occurs before paging is turned on so we need
-	 * to use physical addresses.
-	 */
-	p       = (struct boot_params *)__pa_nodebug(&boot_params);
-	path    = (char *)__pa_nodebug(ucode_path);
-	start   = (void *)p->hdr.ramdisk_image;
-	size    = p->hdr.ramdisk_size;
-#else
-	path    = ucode_path;
-	start   = (void *)(boot_params.hdr.ramdisk_image + PAGE_OFFSET);
-	size    = boot_params.hdr.ramdisk_size;
-#endif /* !CONFIG_X86_32 */
-
-	return find_cpio_data(path, start, size, NULL);
-#else
-	return (struct cpio_data){ NULL, 0, "" };
-#endif
-}
+/*
+ * Microcode patch container file is prepended to the initrd in cpio
+ * format. See Documentation/x86/early-microcode.txt
+ */
+static const char
+ucode_path[] __maybe_unused = "/*(DEBLOBBED)*/";
 
 static size_t compute_container_size(u8 *data, u32 total_size)
 {
@@ -135,48 +97,49 @@ static size_t compute_container_size(u8
 	return size;
 }
 
+static inline u16 find_equiv_id(struct equiv_cpu_entry *equiv_cpu_table,
+				unsigned int sig)
+{
+	int i = 0;
+
+	if (!equiv_cpu_table)
+		return 0;
+
+	while (equiv_cpu_table[i].installed_cpu != 0) {
+		if (sig == equiv_cpu_table[i].installed_cpu)
+			return equiv_cpu_table[i].equiv_cpu;
+
+		i++;
+	}
+	return 0;
+}
+
 /*
- * Early load occurs before we can vmalloc(). So we look for the microcode
- * patch container file in initrd, traverse equivalent cpu table, look for a
- * matching microcode patch, and update, all in initrd memory in place.
- * When vmalloc() is available for use later -- on 64-bit during first AP load,
- * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
- * load_microcode_amd() to save equivalent cpu table and microcode patches in
- * kernel heap memory.
+ * This scans the ucode blob for the proper container as we can have multiple
+ * containers glued together. Returns the equivalence ID from the equivalence
+ * table or 0 if none found.
  */
-static void apply_ucode_in_initrd(void *ucode, size_t size, bool save_patch)
+static u16
+find_proper_container(u8 *ucode, size_t size, struct container *ret_cont)
 {
+	struct container ret = { NULL, 0 };
+	u32 eax, ebx, ecx, edx;
 	struct equiv_cpu_entry *eq;
-	size_t *cont_sz;
-	u32 *header;
-	u8  *data, **cont;
-	u8 (*patch)[PATCH_MAX_SIZE];
-	u16 eq_id = 0;
 	int offset, left;
-	u32 rev, eax, ebx, ecx, edx;
-	u32 *new_rev;
-
-#ifdef CONFIG_X86_32
-	new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
-	cont_sz = (size_t *)__pa_nodebug(&container_size);
-	cont	= (u8 **)__pa_nodebug(&container);
-	patch	= (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
-#else
-	new_rev = &ucode_new_rev;
-	cont_sz = &container_size;
-	cont	= &container;
-	patch	= &amd_ucode_patch;
-#endif
+	u16 eq_id = 0;
+	u32 *header;
+	u8 *data;
 
 	data   = ucode;
 	left   = size;
 	header = (u32 *)data;
 
+
 	/* find equiv cpu table */
 	if (header[0] != UCODE_MAGIC ||
 	    header[1] != UCODE_EQUIV_CPU_TABLE_TYPE || /* type */
 	    header[2] == 0)                            /* size */
-		return;
+		return eq_id;
 
 	eax = 0x00000001;
 	ecx = 0;
@@ -185,7 +148,7 @@ static void apply_ucode_in_initrd(void *
 	while (left > 0) {
 		eq = (struct equiv_cpu_entry *)(data + CONTAINER_HDR_SZ);
 
-		*cont = data;
+		ret.data = data;
 
 		/* Advance past the container header */
 		offset = header[2] + CONTAINER_HDR_SZ;
@@ -194,15 +157,16 @@ static void apply_ucode_in_initrd(void *
 
 		eq_id = find_equiv_id(eq, eax);
 		if (eq_id) {
-			this_equiv_id = eq_id;
-			*cont_sz = compute_container_size(*cont, left + offset);
+			ret.size = compute_container_size(ret.data, left + offset);
 
 			/*
 			 * truncate how much we need to iterate over in the
 			 * ucode update loop below
 			 */
-			left = *cont_sz - offset;
-			break;
+			left = ret.size - offset;
+
+			*ret_cont = ret;
+			return eq_id;
 		}
 
 		/*
@@ -212,6 +176,7 @@ static void apply_ucode_in_initrd(void *
 		 */
 		while (left > 0) {
 			header = (u32 *)data;
+
 			if (header[0] == UCODE_MAGIC &&
 			    header[1] == UCODE_EQUIV_CPU_TABLE_TYPE)
 				break;
@@ -226,14 +191,65 @@ static void apply_ucode_in_initrd(void *
 		ucode     = data;
 	}
 
-	if (!eq_id) {
-		*cont = NULL;
-		*cont_sz = 0;
-		return;
-	}
+	return eq_id;
+}
+
+static int __apply_microcode_amd(struct microcode_amd *mc_amd)
+{
+	u32 rev, dummy;
+
+	native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
+
+	/* verify patch application was successful */
+	native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
+	if (rev != mc_amd->hdr.patch_id)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Early load occurs before we can vmalloc(). So we look for the microcode
+ * patch container file in initrd, traverse equivalent cpu table, look for a
+ * matching microcode patch, and update, all in initrd memory in place.
+ * When vmalloc() is available for use later -- on 64-bit during first AP load,
+ * and on 32-bit during save_microcode_in_initrd_amd() -- we can call
+ * load_microcode_amd() to save equivalent cpu table and microcode patches in
+ * kernel heap memory.
+ *
+ * Returns true if container found (sets @ret_cont), false otherwise.
+ */
+static bool apply_microcode_early_amd(void *ucode, size_t size, bool save_patch,
+				      struct container *ret_cont)
+{
+	u8 (*patch)[PATCH_MAX_SIZE];
+	u32 rev, *header, *new_rev;
+	struct container ret;
+	int offset, left;
+	u16 eq_id = 0;
+	u8  *data;
+
+#ifdef CONFIG_X86_32
+	new_rev = (u32 *)__pa_nodebug(&ucode_new_rev);
+	patch	= (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
+#else
+	new_rev = &ucode_new_rev;
+	patch	= &amd_ucode_patch;
+#endif
 
 	if (check_current_patch_level(&rev, true))
-		return;
+		return false;
+
+	eq_id = find_proper_container(ucode, size, &ret);
+	if (!eq_id)
+		return false;
+
+	this_equiv_id = eq_id;
+	header = (u32 *)ret.data;
+
+	/* We're pointing to an equiv table, skip over it. */
+	data = ret.data +  header[2] + CONTAINER_HDR_SZ;
+	left = ret.size - (header[2] + CONTAINER_HDR_SZ);
 
 	while (left > 0) {
 		struct microcode_amd *mc;
@@ -252,8 +268,7 @@ static void apply_ucode_in_initrd(void *
 				*new_rev = rev;
 
 				if (save_patch)
-					memcpy(patch, mc,
-					       min_t(u32, header[1], PATCH_MAX_SIZE));
+					memcpy(patch, mc, min_t(u32, header[1], PATCH_MAX_SIZE));
 			}
 		}
 
@@ -261,10 +276,14 @@ static void apply_ucode_in_initrd(void *
 		data   += offset;
 		left   -= offset;
 	}
+
+	if (ret_cont)
+		*ret_cont = ret;
+
+	return true;
 }
 
-static bool __init load_builtin_amd_microcode(struct cpio_data *cp,
-					      unsigned int family)
+static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
 {
 #ifdef CONFIG_X86_64
 	char fw_name[36] = "/*(DEBLOBBED)*/";
@@ -281,47 +300,49 @@ static bool __init load_builtin_amd_micr
 
 void __init load_ucode_amd_bsp(unsigned int family)
 {
+	struct ucode_cpu_info *uci;
+	u32 eax, ebx, ecx, edx;
 	struct cpio_data cp;
-	bool *builtin;
-	void **data;
-	size_t *size;
+	const char *path;
+	bool use_pa;
 
-#ifdef CONFIG_X86_32
-	data =  (void **)__pa_nodebug(&ucode_cpio.data);
-	size = (size_t *)__pa_nodebug(&ucode_cpio.size);
-	builtin = (bool *)__pa_nodebug(&ucode_builtin);
-#else
-	data = &ucode_cpio.data;
-	size = &ucode_cpio.size;
-	builtin = &ucode_builtin;
-#endif
+	if (IS_ENABLED(CONFIG_X86_32)) {
+		uci	= (struct ucode_cpu_info *)__pa_nodebug(ucode_cpu_info);
+		path	= (const char *)__pa_nodebug(ucode_path);
+		use_pa	= true;
+	} else {
+		uci     = ucode_cpu_info;
+		path	= ucode_path;
+		use_pa	= false;
+	}
 
-	*builtin = load_builtin_amd_microcode(&cp, family);
-	if (!*builtin)
-		cp = find_ucode_in_initrd();
+	if (!get_builtin_microcode(&cp, family))
+		cp = find_microcode_in_initrd(path, use_pa);
 
 	if (!(cp.data && cp.size))
 		return;
 
-	*data = cp.data;
-	*size = cp.size;
+	/* Get BSP's CPUID.EAX(1), needed in load_microcode_amd() */
+	eax = 1;
+	ecx = 0;
+	native_cpuid(&eax, &ebx, &ecx, &edx);
+	uci->cpu_sig.sig = eax;
 
-	apply_ucode_in_initrd(cp.data, cp.size, true);
+	apply_microcode_early_amd(cp.data, cp.size, true, NULL);
 }
 
 #ifdef CONFIG_X86_32
 /*
  * On 32-bit, since AP's early load occurs before paging is turned on, we
- * cannot traverse cpu_equiv_table and pcache in kernel heap memory. So during
- * cold boot, AP will apply_ucode_in_initrd() just like the BSP. During
- * save_microcode_in_initrd_amd() BSP's patch is copied to amd_ucode_patch,
+ * cannot traverse cpu_equiv_table and microcode_cache in kernel heap memory.
+ * So during cold boot, AP will apply_ucode_in_initrd() just like the BSP.
+ * In save_microcode_in_initrd_amd() BSP's patch is copied to amd_ucode_patch,
  * which is used upon resume from suspend.
  */
-void load_ucode_amd_ap(void)
+void load_ucode_amd_ap(unsigned int family)
 {
 	struct microcode_amd *mc;
-	size_t *usize;
-	void **ucode;
+	struct cpio_data cp;
 
 	mc = (struct microcode_amd *)__pa_nodebug(amd_ucode_patch);
 	if (mc->hdr.patch_id && mc->hdr.processor_rev_id) {
@@ -329,60 +350,63 @@ void load_ucode_amd_ap(void)
 		return;
 	}
 
-	ucode = (void *)__pa_nodebug(&container);
-	usize = (size_t *)__pa_nodebug(&container_size);
+	if (!get_builtin_microcode(&cp, family))
+		cp = find_microcode_in_initrd((const char *)__pa_nodebug(ucode_path), true);
 
-	if (!*ucode || !*usize)
+	if (!(cp.data && cp.size))
 		return;
 
-	apply_ucode_in_initrd(*ucode, *usize, false);
-}
-
-static void __init collect_cpu_sig_on_bsp(void *arg)
-{
-	unsigned int cpu = smp_processor_id();
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-	uci->cpu_sig.sig = cpuid_eax(0x00000001);
-}
-
-static void __init get_bsp_sig(void)
-{
-	unsigned int bsp = boot_cpu_data.cpu_index;
-	struct ucode_cpu_info *uci = ucode_cpu_info + bsp;
-
-	if (!uci->cpu_sig.sig)
-		smp_call_function_single(bsp, collect_cpu_sig_on_bsp, NULL, 1);
+	/*
+	 * This would set amd_ucode_patch above so that the following APs can
+	 * use it directly instead of going down this path again.
+	 */
+	apply_microcode_early_amd(cp.data, cp.size, true, NULL);
 }
 #else
-void load_ucode_amd_ap(void)
+void load_ucode_amd_ap(unsigned int family)
 {
-	unsigned int cpu = smp_processor_id();
 	struct equiv_cpu_entry *eq;
 	struct microcode_amd *mc;
-	u8 *cont = container;
 	u32 rev, eax;
 	u16 eq_id;
 
-	/* Exit if called on the BSP. */
-	if (!cpu)
+	/* 64-bit runs with paging enabled, thus early==false. */
+	if (check_current_patch_level(&rev, false))
 		return;
 
-	if (!container)
-		return;
+	/* First AP hasn't cached it yet, go through the blob. */
+	if (!cont.data) {
+		struct cpio_data cp = { NULL, 0, "" };
 
-	/*
-	 * 64-bit runs with paging enabled, thus early==false.
-	 */
-	if (check_current_patch_level(&rev, false))
-		return;
+		if (cont.size == -1)
+			return;
 
-	/* Add CONFIG_RANDOMIZE_MEMORY offset. */
-	if (!ucode_builtin)
-		cont += PAGE_OFFSET - __PAGE_OFFSET_BASE;
+reget:
+		if (!get_builtin_microcode(&cp, family)) {
+#ifdef CONFIG_BLK_DEV_INITRD
+			if (!initrd_gone)
+				cp = find_cpio_data(ucode_path, (void *)initrd_start,
+						    initrd_end - initrd_start, NULL);
+#endif
+			if (!(cp.data && cp.size)) {
+				/*
+				 * Mark it so that other APs do not scan again
+				 * for no real reason and slow down boot
+				 * needlessly.
+				 */
+				cont.size = -1;
+				return;
+			}
+		}
+
+		if (!apply_microcode_early_amd(cp.data, cp.size, false, &cont)) {
+			cont.size = -1;
+			return;
+		}
+	}
 
 	eax = cpuid_eax(0x00000001);
-	eq  = (struct equiv_cpu_entry *)(cont + CONTAINER_HDR_SZ);
+	eq  = (struct equiv_cpu_entry *)(cont.data + CONTAINER_HDR_SZ);
 
 	eq_id = find_equiv_id(eq, eax);
 	if (!eq_id)
@@ -397,61 +421,50 @@ void load_ucode_amd_ap(void)
 		}
 
 	} else {
-		if (!ucode_cpio.data)
-			return;
 
 		/*
 		 * AP has a different equivalence ID than BSP, looks like
 		 * mixed-steppings silicon so go through the ucode blob anew.
 		 */
-		apply_ucode_in_initrd(ucode_cpio.data, ucode_cpio.size, false);
+		goto reget;
 	}
 }
-#endif
+#endif /* CONFIG_X86_32 */
 
-int __init save_microcode_in_initrd_amd(void)
+static enum ucode_state
+load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size);
+
+int __init save_microcode_in_initrd_amd(unsigned int fam)
 {
-	unsigned long cont;
-	int retval = 0;
 	enum ucode_state ret;
-	u8 *cont_va;
-	u32 eax;
+	int retval = 0;
+	u16 eq_id;
 
-	if (!container)
-		return -EINVAL;
+	if (!cont.data) {
+		if (IS_ENABLED(CONFIG_X86_32) && (cont.size != -1)) {
+			struct cpio_data cp = { NULL, 0, "" };
 
-#ifdef CONFIG_X86_32
-	get_bsp_sig();
-	cont	= (unsigned long)container;
-	cont_va = __va(container);
-#else
-	/*
-	 * We need the physical address of the container for both bitness since
-	 * boot_params.hdr.ramdisk_image is a physical address.
-	 */
-	cont    = __pa_nodebug(container);
-	cont_va = container;
+#ifdef CONFIG_BLK_DEV_INITRD
+			cp = find_cpio_data(ucode_path, (void *)initrd_start,
+					    initrd_end - initrd_start, NULL);
 #endif
 
-	/*
-	 * Take into account the fact that the ramdisk might get relocated and
-	 * therefore we need to recompute the container's position in virtual
-	 * memory space.
-	 */
-	if (relocated_ramdisk)
-		container = (u8 *)(__va(relocated_ramdisk) +
-			     (cont - boot_params.hdr.ramdisk_image));
-	else
-		container = cont_va;
+			if (!(cp.data && cp.size)) {
+				cont.size = -1;
+				return -EINVAL;
+			}
 
-	/* Add CONFIG_RANDOMIZE_MEMORY offset. */
-	if (!ucode_builtin)
-		container += PAGE_OFFSET - __PAGE_OFFSET_BASE;
+			eq_id = find_proper_container(cp.data, cp.size, &cont);
+			if (!eq_id) {
+				cont.size = -1;
+				return -EINVAL;
+			}
 
-	eax   = cpuid_eax(0x00000001);
-	eax   = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff);
+		} else
+			return -EINVAL;
+	}
 
-	ret = load_microcode_amd(smp_processor_id(), eax, container, container_size);
+	ret = load_microcode_amd(smp_processor_id(), fam, cont.data, cont.size);
 	if (ret != UCODE_OK)
 		retval = -EINVAL;
 
@@ -459,8 +472,8 @@ int __init save_microcode_in_initrd_amd(
 	 * This will be freed any msec now, stash patches for the current
 	 * family and switch to patch cache for cpu hotplug, etc later.
 	 */
-	container = NULL;
-	container_size = 0;
+	cont.data = NULL;
+	cont.size = 0;
 
 	return retval;
 }
@@ -478,8 +491,10 @@ void reload_ucode_amd(void)
 		return;
 
 	mc = (struct microcode_amd *)amd_ucode_patch;
+	if (!mc)
+		return;
 
-	if (mc && rev < mc->hdr.patch_id) {
+	if (rev < mc->hdr.patch_id) {
 		if (!__apply_microcode_amd(mc)) {
 			ucode_new_rev = mc->hdr.patch_id;
 			pr_info("reload patch_level=0x%08x\n", ucode_new_rev);
@@ -513,7 +528,7 @@ static struct ucode_patch *cache_find_pa
 {
 	struct ucode_patch *p;
 
-	list_for_each_entry(p, &pcache, plist)
+	list_for_each_entry(p, &microcode_cache, plist)
 		if (p->equiv_cpu == equiv_cpu)
 			return p;
 	return NULL;
@@ -523,7 +538,7 @@ static void update_cache(struct ucode_pa
 {
 	struct ucode_patch *p;
 
-	list_for_each_entry(p, &pcache, plist) {
+	list_for_each_entry(p, &microcode_cache, plist) {
 		if (p->equiv_cpu == new_patch->equiv_cpu) {
 			if (p->patch_id >= new_patch->patch_id)
 				/* we already have the latest patch */
@@ -536,14 +551,14 @@ static void update_cache(struct ucode_pa
 		}
 	}
 	/* no patch found, add it */
-	list_add_tail(&new_patch->plist, &pcache);
+	list_add_tail(&new_patch->plist, &microcode_cache);
 }
 
 static void free_cache(void)
 {
 	struct ucode_patch *p, *tmp;
 
-	list_for_each_entry_safe(p, tmp, &pcache, plist) {
+	list_for_each_entry_safe(p, tmp, &microcode_cache, plist) {
 		__list_del(p->plist.prev, p->plist.next);
 		kfree(p->data);
 		kfree(p);
@@ -663,21 +678,7 @@ bool check_current_patch_level(u32 *rev,
 	return ret;
 }
 
-int __apply_microcode_amd(struct microcode_amd *mc_amd)
-{
-	u32 rev, dummy;
-
-	native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc_amd->hdr.data_code);
-
-	/* verify patch application was successful */
-	native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
-	if (rev != mc_amd->hdr.patch_id)
-		return -1;
-
-	return 0;
-}
-
-int apply_microcode_amd(int cpu)
+static int apply_microcode_amd(int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	struct microcode_amd *mc_amd;
@@ -860,7 +861,8 @@ static enum ucode_state __load_microcode
 	return UCODE_OK;
 }
 
-enum ucode_state load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
+static enum ucode_state
+load_microcode_amd(int cpu, u8 family, const u8 *data, size_t size)
 {
 	enum ucode_state ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/core.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/core.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *	      2006	Shaohua Li <shaohua.li@intel.com>
- *	      2013-2015	Borislav Petkov <bp@alien8.de>
+ *	      2013-2016	Borislav Petkov <bp@alien8.de>
  *
  * X86 CPU microcode early update for Linux:
  *
@@ -39,11 +39,16 @@
 #include <asm/microcode.h>
 #include <asm/processor.h>
 #include <asm/cmdline.h>
+#include <asm/setup.h>
 
-#define MICROCODE_VERSION	"2.01"
+#define DRIVER_VERSION	"2.2"
 
 static struct microcode_ops	*microcode_ops;
-static bool dis_ucode_ldr;
+static bool dis_ucode_ldr = true;
+
+bool initrd_gone;
+
+LIST_HEAD(microcode_cache);
 
 /*
  * Synchronization.
@@ -73,6 +78,7 @@ struct cpu_info_ctx {
 static bool __init check_loader_disabled_bsp(void)
 {
 	static const char *__dis_opt_str = "dis_ucode_ldr";
+	u32 a, b, c, d;
 
 #ifdef CONFIG_X86_32
 	const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
@@ -85,8 +91,23 @@ static bool __init check_loader_disabled
 	bool *res = &dis_ucode_ldr;
 #endif
 
-	if (cmdline_find_option_bool(cmdline, option))
-		*res = true;
+	if (!have_cpuid_p())
+		return *res;
+
+	a = 1;
+	c = 0;
+	native_cpuid(&a, &b, &c, &d);
+
+	/*
+	 * CPUID(1).ECX[31]: reserved for hypervisor use. This is still not
+	 * completely accurate as xen pv guests don't see that CPUID bit set but
+	 * that's good enough as they don't land on the BSP path anyway.
+	 */
+	if (c & BIT(31))
+		return *res;
+
+	if (cmdline_find_option_bool(cmdline, option) <= 0)
+		*res = false;
 
 	return *res;
 }
@@ -118,9 +139,6 @@ void __init load_ucode_bsp(void)
 	if (check_loader_disabled_bsp())
 		return;
 
-	if (!have_cpuid_p())
-		return;
-
 	vendor = x86_cpuid_vendor();
 	family = x86_cpuid_family();
 
@@ -154,9 +172,6 @@ void load_ucode_ap(void)
 	if (check_loader_disabled_ap())
 		return;
 
-	if (!have_cpuid_p())
-		return;
-
 	vendor = x86_cpuid_vendor();
 	family = x86_cpuid_family();
 
@@ -167,7 +182,7 @@ void load_ucode_ap(void)
 		break;
 	case X86_VENDOR_AMD:
 		if (family >= 0x10)
-			load_ucode_amd_ap();
+			load_ucode_amd_ap(family);
 		break;
 	default:
 		break;
@@ -177,21 +192,81 @@ void load_ucode_ap(void)
 static int __init save_microcode_in_initrd(void)
 {
 	struct cpuinfo_x86 *c = &boot_cpu_data;
+	int ret = -EINVAL;
 
 	switch (c->x86_vendor) {
 	case X86_VENDOR_INTEL:
 		if (c->x86 >= 6)
-			return save_microcode_in_initrd_intel();
+			ret = save_microcode_in_initrd_intel();
 		break;
 	case X86_VENDOR_AMD:
 		if (c->x86 >= 0x10)
-			return save_microcode_in_initrd_amd();
+			ret = save_microcode_in_initrd_amd(c->x86);
 		break;
 	default:
 		break;
 	}
 
-	return -EINVAL;
+	initrd_gone = true;
+
+	return ret;
+}
+
+struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	unsigned long start = 0;
+	size_t size;
+
+#ifdef CONFIG_X86_32
+	struct boot_params *params;
+
+	if (use_pa)
+		params = (struct boot_params *)__pa_nodebug(&boot_params);
+	else
+		params = &boot_params;
+
+	size = params->hdr.ramdisk_size;
+
+	/*
+	 * Set start only if we have an initrd image. We cannot use initrd_start
+	 * because it is not set that early yet.
+	 */
+	if (size)
+		start = params->hdr.ramdisk_image;
+
+# else /* CONFIG_X86_64 */
+	size  = (unsigned long)boot_params.ext_ramdisk_size << 32;
+	size |= boot_params.hdr.ramdisk_size;
+
+	if (size) {
+		start  = (unsigned long)boot_params.ext_ramdisk_image << 32;
+		start |= boot_params.hdr.ramdisk_image;
+
+		start += PAGE_OFFSET;
+	}
+# endif
+
+	/*
+	 * Fixup the start address: after reserve_initrd() runs, initrd_start
+	 * has the virtual address of the beginning of the initrd. It also
+	 * possibly relocates the ramdisk. In either case, initrd_start contains
+	 * the updated address so use that instead.
+	 *
+	 * initrd_gone is for the hotplug case where we've thrown out initrd
+	 * already.
+	 */
+	if (!use_pa) {
+		if (initrd_gone)
+			return (struct cpio_data){ NULL, 0, "" };
+		if (initrd_start)
+			start = initrd_start;
+	}
+
+	return find_cpio_data(path, (void *)start, size, NULL);
+#else /* !CONFIG_BLK_DEV_INITRD */
+	return (struct cpio_data){ NULL, 0, "" };
+#endif
 }
 
 void reload_early_microcode(void)
@@ -453,16 +528,17 @@ static struct attribute_group mc_attr_gr
 
 static void microcode_fini_cpu(int cpu)
 {
-	microcode_ops->microcode_fini_cpu(cpu);
+	if (microcode_ops->microcode_fini_cpu)
+		microcode_ops->microcode_fini_cpu(cpu);
 }
 
 static enum ucode_state microcode_resume_cpu(int cpu)
 {
-	pr_debug("CPU%d updated upon resume\n", cpu);
-
 	if (apply_microcode_on_target(cpu))
 		return UCODE_ERROR;
 
+	pr_debug("CPU%d updated upon resume\n", cpu);
+
 	return UCODE_OK;
 }
 
@@ -496,6 +572,9 @@ static enum ucode_state microcode_update
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
+	/* Refresh CPU microcode revision after resume. */
+	collect_cpu_info(cpu);
+
 	if (uci->valid)
 		return microcode_resume_cpu(cpu);
 
@@ -579,12 +658,7 @@ static int mc_cpu_down_prep(unsigned int
 	/* Suspend is in progress, only remove the interface */
 	sysfs_remove_group(&dev->kobj, &mc_attr_group);
 	pr_debug("CPU%d removed\n", cpu);
-	/*
-	 * 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.
-	 */
+
 	return 0;
 }
 
@@ -649,8 +723,7 @@ int __init microcode_init(void)
 	cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
 				  mc_cpu_online, mc_cpu_down_prep);
 
-	pr_info("Microcode Update Driver: v" MICROCODE_VERSION
-		" <tigran@aivazian.fsnet.co.uk>, Peter Oruba\n");
+	pr_info("Microcode Update Driver: v%s.", DRIVER_VERSION);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/intel.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/intel.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/intel.c	2016-12-11 17:39:24.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/intel.c	2017-02-12 17:21:26.000000000 -0500
@@ -39,125 +39,83 @@
 #include <asm/setup.h>
 #include <asm/msr.h>
 
-/*
- * Temporary microcode blobs pointers storage. We note here during early load
- * the pointers to microcode blobs we've got from whatever storage (detached
- * initrd, builtin). Later on, we put those into final storage
- * mc_saved_data.mc_saved.
- *
- * Important: those are offsets from the beginning of initrd or absolute
- * addresses within the kernel image when built-in.
- */
-static unsigned long mc_tmp_ptrs[MAX_UCODE_COUNT];
-
-static struct mc_saved_data {
-	unsigned int num_saved;
-	struct microcode_intel **mc_saved;
-} mc_saved_data;
+static const char ucode_path[] = "/*(DEBLOBBED)*/";
 
-/* Microcode blobs within the initrd. 0 if builtin. */
-static struct ucode_blobs {
-	unsigned long start;
-	bool valid;
-} blobs;
+/* Current microcode patch used in early patching on the APs. */
+struct microcode_intel *intel_ucode_patch;
 
-/* Go through saved patches and find the one suitable for the current CPU. */
-static enum ucode_state
-find_microcode_patch(struct microcode_intel **saved,
-		     unsigned int num_saved, struct ucode_cpu_info *uci)
+static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
+					unsigned int s2, unsigned int p2)
 {
-	struct microcode_intel *ucode_ptr, *new_mc = NULL;
-	struct microcode_header_intel *mc_hdr;
-	int new_rev, ret, i;
-
-	new_rev = uci->cpu_sig.rev;
-
-	for (i = 0; i < num_saved; i++) {
-		ucode_ptr = saved[i];
-		mc_hdr	  = (struct microcode_header_intel *)ucode_ptr;
-
-		ret = has_newer_microcode(ucode_ptr,
-					  uci->cpu_sig.sig,
-					  uci->cpu_sig.pf,
-					  new_rev);
-		if (!ret)
-			continue;
-
-		new_rev = mc_hdr->rev;
-		new_mc  = ucode_ptr;
-	}
+	if (s1 != s2)
+		return false;
 
-	if (!new_mc)
-		return UCODE_NFOUND;
+	/* Processor flags are either both 0 ... */
+	if (!p1 && !p2)
+		return true;
 
-	uci->mc = (struct microcode_intel *)new_mc;
-	return UCODE_OK;
+	/* ... or they intersect. */
+	return p1 & p2;
 }
 
-static inline void
-copy_ptrs(struct microcode_intel **mc_saved, unsigned long *mc_ptrs,
-	  unsigned long off, int num_saved)
+/*
+ * Returns 1 if update has been found, 0 otherwise.
+ */
+static int find_matching_signature(void *mc, unsigned int csig, int cpf)
 {
+	struct microcode_header_intel *mc_hdr = mc;
+	struct extended_sigtable *ext_hdr;
+	struct extended_signature *ext_sig;
 	int i;
 
-	for (i = 0; i < num_saved; i++)
-		mc_saved[i] = (struct microcode_intel *)(mc_ptrs[i] + off);
-}
-
-#ifdef CONFIG_X86_32
-static void
-microcode_phys(struct microcode_intel **mc_saved_tmp, struct mc_saved_data *mcs)
-{
-	int i;
-	struct microcode_intel ***mc_saved;
+	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+		return 1;
 
-	mc_saved = (struct microcode_intel ***)__pa_nodebug(&mcs->mc_saved);
+	/* Look for ext. headers: */
+	if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
+		return 0;
 
-	for (i = 0; i < mcs->num_saved; i++) {
-		struct microcode_intel *p;
+	ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
+	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
 
-		p = *(struct microcode_intel **)__pa_nodebug(mcs->mc_saved + i);
-		mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p);
+	for (i = 0; i < ext_hdr->count; i++) {
+		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+			return 1;
+		ext_sig++;
 	}
+	return 0;
 }
-#endif
 
-static enum ucode_state
-load_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
-	       unsigned long offset, struct ucode_cpu_info *uci)
+/*
+ * Returns 1 if update has been found, 0 otherwise.
+ */
+static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev)
 {
-	struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
-	unsigned int count = mcs->num_saved;
+	struct microcode_header_intel *mc_hdr = mc;
 
-	if (!mcs->mc_saved) {
-		copy_ptrs(mc_saved_tmp, mc_ptrs, offset, count);
+	if (mc_hdr->rev <= new_rev)
+		return 0;
 
-		return find_microcode_patch(mc_saved_tmp, count, uci);
-	} else {
-#ifdef CONFIG_X86_32
-		microcode_phys(mc_saved_tmp, mcs);
-		return find_microcode_patch(mc_saved_tmp, count, uci);
-#else
-		return find_microcode_patch(mcs->mc_saved, count, uci);
-#endif
-	}
+	return find_matching_signature(mc, csig, cpf);
 }
 
 /*
  * Given CPU signature and a microcode patch, this function finds if the
  * microcode patch has matching family and model with the CPU.
+ *
+ * %true - if there's a match
+ * %false - otherwise
  */
-static enum ucode_state
-matching_model_microcode(struct microcode_header_intel *mc_header,
-			unsigned long sig)
+static bool microcode_matches(struct microcode_header_intel *mc_header,
+			      unsigned long sig)
 {
-	unsigned int fam, model;
-	unsigned int fam_ucode, model_ucode;
-	struct extended_sigtable *ext_header;
 	unsigned long total_size = get_totalsize(mc_header);
 	unsigned long data_size = get_datasize(mc_header);
-	int ext_sigcount, i;
+	struct extended_sigtable *ext_header;
+	unsigned int fam_ucode, model_ucode;
 	struct extended_signature *ext_sig;
+	unsigned int fam, model;
+	int ext_sigcount, i;
 
 	fam   = x86_family(sig);
 	model = x86_model(sig);
@@ -166,11 +124,11 @@ matching_model_microcode(struct microcod
 	model_ucode = x86_model(mc_header->sig);
 
 	if (fam == fam_ucode && model == model_ucode)
-		return UCODE_OK;
+		return true;
 
 	/* Look for ext. headers: */
 	if (total_size <= data_size + MC_HEADER_SIZE)
-		return UCODE_NFOUND;
+		return false;
 
 	ext_header   = (void *) mc_header + data_size + MC_HEADER_SIZE;
 	ext_sig      = (void *)ext_header + EXT_HEADER_SIZE;
@@ -181,192 +139,242 @@ matching_model_microcode(struct microcod
 		model_ucode = x86_model(ext_sig->sig);
 
 		if (fam == fam_ucode && model == model_ucode)
-			return UCODE_OK;
+			return true;
 
 		ext_sig++;
 	}
-	return UCODE_NFOUND;
+	return false;
 }
 
-static int
-save_microcode(struct mc_saved_data *mcs,
-	       struct microcode_intel **mc_saved_src,
-	       unsigned int num_saved)
+static struct ucode_patch *__alloc_microcode_buf(void *data, unsigned int size)
 {
-	int i, j;
-	struct microcode_intel **saved_ptr;
-	int ret;
+	struct ucode_patch *p;
 
-	if (!num_saved)
-		return -EINVAL;
+	p = kzalloc(sizeof(struct ucode_patch), GFP_KERNEL);
+	if (!p)
+		return ERR_PTR(-ENOMEM);
 
-	/*
-	 * Copy new microcode data.
-	 */
-	saved_ptr = kcalloc(num_saved, sizeof(struct microcode_intel *), GFP_KERNEL);
-	if (!saved_ptr)
-		return -ENOMEM;
+	p->data = kmemdup(data, size, GFP_KERNEL);
+	if (!p->data) {
+		kfree(p);
+		return ERR_PTR(-ENOMEM);
+	}
 
-	for (i = 0; i < num_saved; i++) {
-		struct microcode_header_intel *mc_hdr;
-		struct microcode_intel *mc;
-		unsigned long size;
+	return p;
+}
 
-		if (!mc_saved_src[i]) {
-			ret = -EINVAL;
-			goto err;
-		}
+static void save_microcode_patch(void *data, unsigned int size)
+{
+	struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
+	struct ucode_patch *iter, *tmp, *p;
+	bool prev_found = false;
+	unsigned int sig, pf;
 
-		mc     = mc_saved_src[i];
-		mc_hdr = &mc->hdr;
-		size   = get_totalsize(mc_hdr);
+	mc_hdr = (struct microcode_header_intel *)data;
 
-		saved_ptr[i] = kmemdup(mc, size, GFP_KERNEL);
-		if (!saved_ptr[i]) {
-			ret = -ENOMEM;
-			goto err;
+	list_for_each_entry_safe(iter, tmp, &microcode_cache, plist) {
+		mc_saved_hdr = (struct microcode_header_intel *)iter->data;
+		sig	     = mc_saved_hdr->sig;
+		pf	     = mc_saved_hdr->pf;
+
+		if (find_matching_signature(data, sig, pf)) {
+			prev_found = true;
+
+			if (mc_hdr->rev <= mc_saved_hdr->rev)
+				continue;
+
+			p = __alloc_microcode_buf(data, size);
+			if (IS_ERR(p))
+				pr_err("Error allocating buffer %p\n", data);
+			else
+				list_replace(&iter->plist, &p->plist);
 		}
 	}
 
 	/*
-	 * Point to newly saved microcode.
+	 * There weren't any previous patches found in the list cache; save the
+	 * newly found.
 	 */
-	mcs->mc_saved  = saved_ptr;
-	mcs->num_saved = num_saved;
-
-	return 0;
-
-err:
-	for (j = 0; j <= i; j++)
-		kfree(saved_ptr[j]);
-	kfree(saved_ptr);
-
-	return ret;
+	if (!prev_found) {
+		p = __alloc_microcode_buf(data, size);
+		if (IS_ERR(p))
+			pr_err("Error allocating buffer for %p\n", data);
+		else
+			list_add_tail(&p->plist, &microcode_cache);
+	}
 }
 
-/*
- * A microcode patch in ucode_ptr is saved into mc_saved
- * - if it has matching signature and newer revision compared to an existing
- *   patch mc_saved.
- * - or if it is a newly discovered microcode patch.
- *
- * The microcode patch should have matching model with CPU.
- *
- * Returns: The updated number @num_saved of saved microcode patches.
- */
-static unsigned int _save_mc(struct microcode_intel **mc_saved,
-			     u8 *ucode_ptr, unsigned int num_saved)
+static int microcode_sanity_check(void *mc, int print_err)
 {
-	struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
-	unsigned int sig, pf;
-	int found = 0, i;
+	unsigned long total_size, data_size, ext_table_size;
+	struct microcode_header_intel *mc_header = mc;
+	struct extended_sigtable *ext_header = NULL;
+	u32 sum, orig_sum, ext_sigcount = 0, i;
+	struct extended_signature *ext_sig;
 
-	mc_hdr = (struct microcode_header_intel *)ucode_ptr;
+	total_size = get_totalsize(mc_header);
+	data_size = get_datasize(mc_header);
 
-	for (i = 0; i < num_saved; i++) {
-		mc_saved_hdr = (struct microcode_header_intel *)mc_saved[i];
-		sig	     = mc_saved_hdr->sig;
-		pf	     = mc_saved_hdr->pf;
+	if (data_size + MC_HEADER_SIZE > total_size) {
+		if (print_err)
+			pr_err("Error: bad microcode data file size.\n");
+		return -EINVAL;
+	}
 
-		if (!find_matching_signature(ucode_ptr, sig, pf))
-			continue;
+	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+		if (print_err)
+			pr_err("Error: invalid/unknown microcode update format.\n");
+		return -EINVAL;
+	}
 
-		found = 1;
+	ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+	if (ext_table_size) {
+		u32 ext_table_sum = 0;
+		u32 *ext_tablep;
 
-		if (mc_hdr->rev <= mc_saved_hdr->rev)
-			continue;
+		if ((ext_table_size < EXT_HEADER_SIZE)
+		 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+			if (print_err)
+				pr_err("Error: truncated extended signature table.\n");
+			return -EINVAL;
+		}
+
+		ext_header = mc + MC_HEADER_SIZE + data_size;
+		if (ext_table_size != exttable_size(ext_header)) {
+			if (print_err)
+				pr_err("Error: extended signature table size mismatch.\n");
+			return -EFAULT;
+		}
+
+		ext_sigcount = ext_header->count;
 
 		/*
-		 * Found an older ucode saved earlier. Replace it with
-		 * this newer one.
+		 * Check extended table checksum: the sum of all dwords that
+		 * comprise a valid table must be 0.
 		 */
-		mc_saved[i] = (struct microcode_intel *)ucode_ptr;
-		break;
+		ext_tablep = (u32 *)ext_header;
+
+		i = ext_table_size / sizeof(u32);
+		while (i--)
+			ext_table_sum += ext_tablep[i];
+
+		if (ext_table_sum) {
+			if (print_err)
+				pr_warn("Bad extended signature table checksum, aborting.\n");
+			return -EINVAL;
+		}
 	}
 
-	/* Newly detected microcode, save it to memory. */
-	if (i >= num_saved && !found)
-		mc_saved[num_saved++] = (struct microcode_intel *)ucode_ptr;
+	/*
+	 * Calculate the checksum of update data and header. The checksum of
+	 * valid update data and header including the extended signature table
+	 * must be 0.
+	 */
+	orig_sum = 0;
+	i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
+	while (i--)
+		orig_sum += ((u32 *)mc)[i];
 
-	return num_saved;
+	if (orig_sum) {
+		if (print_err)
+			pr_err("Bad microcode data checksum, aborting.\n");
+		return -EINVAL;
+	}
+
+	if (!ext_table_size)
+		return 0;
+
+	/*
+	 * Check extended signature checksum: 0 => valid.
+	 */
+	for (i = 0; i < ext_sigcount; i++) {
+		ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
+			  EXT_SIGNATURE_SIZE * i;
+
+		sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
+		      (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+		if (sum) {
+			if (print_err)
+				pr_err("Bad extended signature checksum, aborting.\n");
+			return -EINVAL;
+		}
+	}
+	return 0;
 }
 
 /*
  * Get microcode matching with BSP's model. Only CPUs with the same model as
  * BSP can stay in the platform.
  */
-static enum ucode_state __init
-get_matching_model_microcode(unsigned long start, void *data, size_t size,
-			     struct mc_saved_data *mcs, unsigned long *mc_ptrs,
-			     struct ucode_cpu_info *uci)
+static struct microcode_intel *
+scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
 {
-	struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
 	struct microcode_header_intel *mc_header;
-	unsigned int num_saved = mcs->num_saved;
-	enum ucode_state state = UCODE_OK;
-	unsigned int leftover = size;
-	u8 *ucode_ptr = data;
+	struct microcode_intel *patch = NULL;
 	unsigned int mc_size;
-	int i;
-
-	while (leftover && num_saved < ARRAY_SIZE(mc_saved_tmp)) {
 
-		if (leftover < sizeof(mc_header))
+	while (size) {
+		if (size < sizeof(struct microcode_header_intel))
 			break;
 
-		mc_header = (struct microcode_header_intel *)ucode_ptr;
+		mc_header = (struct microcode_header_intel *)data;
 
 		mc_size = get_totalsize(mc_header);
-		if (!mc_size || mc_size > leftover ||
-			microcode_sanity_check(ucode_ptr, 0) < 0)
+		if (!mc_size ||
+		    mc_size > size ||
+		    microcode_sanity_check(data, 0) < 0)
 			break;
 
-		leftover -= mc_size;
+		size -= mc_size;
 
-		/*
-		 * Since APs with same family and model as the BSP may boot in
-		 * the platform, we need to find and save microcode patches
-		 * with the same family and model as the BSP.
-		 */
-		if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != UCODE_OK) {
-			ucode_ptr += mc_size;
+		if (!microcode_matches(mc_header, uci->cpu_sig.sig)) {
+			data += mc_size;
 			continue;
 		}
 
-		num_saved = _save_mc(mc_saved_tmp, ucode_ptr, num_saved);
+		if (save) {
+			save_microcode_patch(data, mc_size);
+			goto next;
+		}
 
-		ucode_ptr += mc_size;
-	}
 
-	if (leftover) {
-		state = UCODE_ERROR;
-		return state;
-	}
+		if (!patch) {
+			if (!has_newer_microcode(data,
+						 uci->cpu_sig.sig,
+						 uci->cpu_sig.pf,
+						 uci->cpu_sig.rev))
+				goto next;
 
-	if (!num_saved) {
-		state = UCODE_NFOUND;
-		return state;
-	}
+		} else {
+			struct microcode_header_intel *phdr = &patch->hdr;
 
-	for (i = 0; i < num_saved; i++)
-		mc_ptrs[i] = (unsigned long)mc_saved_tmp[i] - start;
+			if (!has_newer_microcode(data,
+						 phdr->sig,
+						 phdr->pf,
+						 phdr->rev))
+				goto next;
+		}
 
-	mcs->num_saved = num_saved;
+		/* We have a newer patch, save it. */
+		patch = data;
 
-	return state;
+next:
+		data += mc_size;
+	}
+
+	if (size)
+		return NULL;
+
+	return patch;
 }
 
 static int collect_cpu_info_early(struct ucode_cpu_info *uci)
 {
 	unsigned int val[2];
 	unsigned int family, model;
-	struct cpu_signature csig;
+	struct cpu_signature csig = { 0 };
 	unsigned int eax, ebx, ecx, edx;
 
-	csig.sig = 0;
-	csig.pf = 0;
-	csig.rev = 0;
-
 	memset(uci, 0, sizeof(*uci));
 
 	eax = 0x00000001;
@@ -374,23 +382,16 @@ static int collect_cpu_info_early(struct
 	native_cpuid(&eax, &ebx, &ecx, &edx);
 	csig.sig = eax;
 
-	family = x86_family(csig.sig);
-	model  = x86_model(csig.sig);
+	family = x86_family(eax);
+	model  = x86_model(eax);
 
 	if ((model >= 5) || (family > 6)) {
 		/* get processor flags from MSR 0x17 */
 		native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
 		csig.pf = 1 << ((val[1] >> 18) & 7);
 	}
-	native_wrmsrl(MSR_IA32_UCODE_REV, 0);
-
-	/* As documented in the SDM: Do a CPUID 1 here */
-	sync_core();
-
-	/* get the current revision from MSR 0x8B */
-	native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 
-	csig.rev = val[1];
+	csig.rev = intel_get_microcode_revision();
 
 	uci->cpu_sig = csig;
 	uci->valid = 1;
@@ -401,40 +402,41 @@ static int collect_cpu_info_early(struct
 static void show_saved_mc(void)
 {
 #ifdef DEBUG
-	int i, j;
+	int i = 0, j;
 	unsigned int sig, pf, rev, total_size, data_size, date;
 	struct ucode_cpu_info uci;
+	struct ucode_patch *p;
 
-	if (!mc_saved_data.num_saved) {
+	if (list_empty(&microcode_cache)) {
 		pr_debug("no microcode data saved.\n");
 		return;
 	}
-	pr_debug("Total microcode saved: %d\n", mc_saved_data.num_saved);
 
 	collect_cpu_info_early(&uci);
 
-	sig = uci.cpu_sig.sig;
-	pf = uci.cpu_sig.pf;
-	rev = uci.cpu_sig.rev;
+	sig	= uci.cpu_sig.sig;
+	pf	= uci.cpu_sig.pf;
+	rev	= uci.cpu_sig.rev;
 	pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev);
 
-	for (i = 0; i < mc_saved_data.num_saved; i++) {
+	list_for_each_entry(p, &microcode_cache, plist) {
 		struct microcode_header_intel *mc_saved_header;
 		struct extended_sigtable *ext_header;
-		int ext_sigcount;
 		struct extended_signature *ext_sig;
+		int ext_sigcount;
 
-		mc_saved_header = (struct microcode_header_intel *)
-				  mc_saved_data.mc_saved[i];
-		sig = mc_saved_header->sig;
-		pf = mc_saved_header->pf;
-		rev = mc_saved_header->rev;
-		total_size = get_totalsize(mc_saved_header);
-		data_size = get_datasize(mc_saved_header);
-		date = mc_saved_header->date;
+		mc_saved_header = (struct microcode_header_intel *)p->data;
+
+		sig	= mc_saved_header->sig;
+		pf	= mc_saved_header->pf;
+		rev	= mc_saved_header->rev;
+		date	= mc_saved_header->date;
+
+		total_size	= get_totalsize(mc_saved_header);
+		data_size	= get_datasize(mc_saved_header);
 
 		pr_debug("mc_saved[%d]: sig=0x%x, pf=0x%x, rev=0x%x, total size=0x%x, date = %04x-%02x-%02x\n",
-			 i, sig, pf, rev, total_size,
+			 i++, sig, pf, rev, total_size,
 			 date & 0xffff,
 			 date >> 24,
 			 (date >> 16) & 0xff);
@@ -443,7 +445,7 @@ static void show_saved_mc(void)
 		if (total_size <= data_size + MC_HEADER_SIZE)
 			continue;
 
-		ext_header = (void *) mc_saved_header + data_size + MC_HEADER_SIZE;
+		ext_header = (void *)mc_saved_header + data_size + MC_HEADER_SIZE;
 		ext_sigcount = ext_header->count;
 		ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
 
@@ -456,85 +458,43 @@ static void show_saved_mc(void)
 
 			ext_sig++;
 		}
-
 	}
 #endif
 }
 
 /*
- * Save this mc into mc_saved_data. So it will be loaded early when a CPU is
- * hot added or resumes.
- *
- * Please make sure this mc should be a valid microcode patch before calling
- * this function.
+ * Save this microcode patch. It will be loaded early when a CPU is
+ * hot-added or resumes.
  */
-static void save_mc_for_early(u8 *mc)
+static void save_mc_for_early(u8 *mc, unsigned int size)
 {
 #ifdef CONFIG_HOTPLUG_CPU
 	/* Synchronization during CPU hotplug. */
 	static DEFINE_MUTEX(x86_cpu_microcode_mutex);
 
-	struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT];
-	unsigned int mc_saved_count_init;
-	unsigned int num_saved;
-	struct microcode_intel **mc_saved;
-	int ret, i;
-
 	mutex_lock(&x86_cpu_microcode_mutex);
 
-	mc_saved_count_init = mc_saved_data.num_saved;
-	num_saved = mc_saved_data.num_saved;
-	mc_saved = mc_saved_data.mc_saved;
-
-	if (mc_saved && num_saved)
-		memcpy(mc_saved_tmp, mc_saved,
-		       num_saved * sizeof(struct microcode_intel *));
-	/*
-	 * Save the microcode patch mc in mc_save_tmp structure if it's a newer
-	 * version.
-	 */
-	num_saved = _save_mc(mc_saved_tmp, mc, num_saved);
-
-	/*
-	 * Save the mc_save_tmp in global mc_saved_data.
-	 */
-	ret = save_microcode(&mc_saved_data, mc_saved_tmp, num_saved);
-	if (ret) {
-		pr_err("Cannot save microcode patch.\n");
-		goto out;
-	}
-
+	save_microcode_patch(mc, size);
 	show_saved_mc();
 
-	/*
-	 * Free old saved microcode data.
-	 */
-	if (mc_saved) {
-		for (i = 0; i < mc_saved_count_init; i++)
-			kfree(mc_saved[i]);
-		kfree(mc_saved);
-	}
-
-out:
 	mutex_unlock(&x86_cpu_microcode_mutex);
 #endif
 }
 
-static bool __init load_builtin_intel_microcode(struct cpio_data *cp)
+static bool load_builtin_intel_microcode(struct cpio_data *cp)
 {
-#ifdef CONFIG_X86_64
-	unsigned int eax = 0x00000001, ebx, ecx = 0, edx;
+	unsigned int eax = 1, ebx, ecx = 0, edx;
 	char name[30];
 
+	if (IS_ENABLED(CONFIG_X86_32))
+		return false;
+
 	native_cpuid(&eax, &ebx, &ecx, &edx);
 
 	sprintf(name, "/*(DEBLOBBED)*/",
 		      x86_family(eax), x86_model(eax), x86_stepping(eax));
 
 	return get_builtin_firmware(cp, name);
-#else
-	return false;
-#endif
 }
 
 /*
@@ -570,8 +530,7 @@ void show_ucode_info_early(void)
 }
 
 /*
- * At this point, we can not call printk() yet. Keep microcode patch number in
- * mc_saved_data.mc_saved and delay printing microcode info in
+ * At this point, we can not call printk() yet. Delay printing microcode info in
  * show_ucode_info_early() until printk() works.
  */
 static void print_ucode(struct ucode_cpu_info *uci)
@@ -616,7 +575,7 @@ static inline void print_ucode(struct uc
 static int apply_microcode_early(struct ucode_cpu_info *uci, bool early)
 {
 	struct microcode_intel *mc;
-	unsigned int val[2];
+	u32 rev;
 
 	mc = uci->mc;
 	if (!mc)
@@ -624,21 +583,16 @@ static int apply_microcode_early(struct
 
 	/* write microcode via MSR 0x79 */
 	native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
-	native_wrmsrl(MSR_IA32_UCODE_REV, 0);
-
-	/* As documented in the SDM: Do a CPUID 1 here */
-	sync_core();
 
-	/* get the current revision from MSR 0x8B */
-	native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
-	if (val[1] != mc->hdr.rev)
+	rev = intel_get_microcode_revision();
+	if (rev != mc->hdr.rev)
 		return -1;
 
 #ifdef CONFIG_X86_64
 	/* Flush global tlb. This is precaution. */
 	flush_tlb_early();
 #endif
-	uci->cpu_sig.rev = val[1];
+	uci->cpu_sig.rev = rev;
 
 	if (early)
 		print_ucode(uci);
@@ -648,206 +602,133 @@ static int apply_microcode_early(struct
 	return 0;
 }
 
-/*
- * This function converts microcode patch offsets previously stored in
- * mc_tmp_ptrs to pointers and stores the pointers in mc_saved_data.
- */
 int __init save_microcode_in_initrd_intel(void)
 {
-	struct microcode_intel *mc_saved[MAX_UCODE_COUNT];
-	unsigned int count = mc_saved_data.num_saved;
-	unsigned long offset = 0;
-	int ret;
+	struct ucode_cpu_info uci;
+	struct cpio_data cp;
 
-	if (!count)
+	if (!load_builtin_intel_microcode(&cp))
+		cp = find_microcode_in_initrd(ucode_path, false);
+
+	if (!(cp.data && cp.size))
 		return 0;
 
-	/*
-	 * We have found a valid initrd but it might've been relocated in the
-	 * meantime so get its updated address.
-	 */
-	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && blobs.valid)
-		offset = initrd_start;
+	collect_cpu_info_early(&uci);
 
-	copy_ptrs(mc_saved, mc_tmp_ptrs, offset, count);
+	scan_microcode(cp.data, cp.size, &uci, true);
 
-	ret = save_microcode(&mc_saved_data, mc_saved, count);
-	if (ret)
-		pr_err("Cannot save microcode patches from initrd.\n");
-	else
-		show_saved_mc();
+	show_saved_mc();
 
-	return ret;
+	return 0;
 }
 
-static __init enum ucode_state
-__scan_microcode_initrd(struct cpio_data *cd, struct ucode_blobs *blbp)
+/*
+ * @res_patch, output: a pointer to the patch we found.
+ */
+static struct microcode_intel *__load_ucode_intel(struct ucode_cpu_info *uci)
 {
-#ifdef CONFIG_BLK_DEV_INITRD
-	static __initdata char ucode_name[] = "/*(DEBLOBBED)*/";
-	char *p = IS_ENABLED(CONFIG_X86_32) ? (char *)__pa_nodebug(ucode_name)
-						    : ucode_name;
-# ifdef CONFIG_X86_32
-	unsigned long start = 0, size;
-	struct boot_params *params;
-
-	params = (struct boot_params *)__pa_nodebug(&boot_params);
-	size   = params->hdr.ramdisk_size;
-
-	/*
-	 * Set start only if we have an initrd image. We cannot use initrd_start
-	 * because it is not set that early yet.
-	 */
-	start = (size ? params->hdr.ramdisk_image : 0);
-
-# else /* CONFIG_X86_64 */
-	unsigned long start = 0, size;
-
-	size  = (u64)boot_params.ext_ramdisk_size << 32;
-	size |= boot_params.hdr.ramdisk_size;
-
-	if (size) {
-		start  = (u64)boot_params.ext_ramdisk_image << 32;
-		start |= boot_params.hdr.ramdisk_image;
+	static const char *path;
+	struct cpio_data cp;
+	bool use_pa;
 
-		start += PAGE_OFFSET;
+	if (IS_ENABLED(CONFIG_X86_32)) {
+		path	  = (const char *)__pa_nodebug(ucode_path);
+		use_pa	  = true;
+	} else {
+		path	  = ucode_path;
+		use_pa	  = false;
 	}
-# endif
 
-	*cd = find_cpio_data(p, (void *)start, size, NULL);
-	if (cd->data) {
-		blbp->start = start;
-		blbp->valid = true;
-
-		return UCODE_OK;
-	} else
-#endif /* CONFIG_BLK_DEV_INITRD */
-		return UCODE_ERROR;
-}
+	/* try built-in microcode first */
+	if (!load_builtin_intel_microcode(&cp))
+		cp = find_microcode_in_initrd(path, use_pa);
 
-static __init enum ucode_state
-scan_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
-	       struct ucode_cpu_info *uci, struct ucode_blobs *blbp)
-{
-	struct cpio_data cd = { NULL, 0, "" };
-	enum ucode_state ret;
+	if (!(cp.data && cp.size))
+		return NULL;
 
-	/* try built-in microcode first */
-	if (load_builtin_intel_microcode(&cd))
-		/*
-		 * Invalidate blobs as we might've gotten an initrd too,
-		 * supplied by the boot loader, by mistake or simply forgotten
-		 * there. That's fine, we ignore it since we've found builtin
-		 * microcode already.
-		 */
-		blbp->valid = false;
-	else {
-		ret = __scan_microcode_initrd(&cd, blbp);
-		if (ret != UCODE_OK)
-			return ret;
-	}
+	collect_cpu_info_early(uci);
 
-	return get_matching_model_microcode(blbp->start, cd.data, cd.size,
-					    mcs, mc_ptrs, uci);
+	return scan_microcode(cp.data, cp.size, uci, false);
 }
 
-static void __init
-_load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs,
-		      struct ucode_blobs *blbp)
+void __init load_ucode_intel_bsp(void)
 {
+	struct microcode_intel *patch;
 	struct ucode_cpu_info uci;
-	enum ucode_state ret;
 
-	collect_cpu_info_early(&uci);
-
-	ret = scan_microcode(mcs, mc_ptrs, &uci, blbp);
-	if (ret != UCODE_OK)
+	patch = __load_ucode_intel(&uci);
+	if (!patch)
 		return;
 
-	ret = load_microcode(mcs, mc_ptrs, blbp->start, &uci);
-	if (ret != UCODE_OK)
-		return;
+	uci.mc = patch;
 
 	apply_microcode_early(&uci, true);
 }
 
-void __init load_ucode_intel_bsp(void)
+void load_ucode_intel_ap(void)
 {
-	struct ucode_blobs *blobs_p;
-	struct mc_saved_data *mcs;
-	unsigned long *ptrs;
+	struct microcode_intel *patch, **iup;
+	struct ucode_cpu_info uci;
 
-#ifdef CONFIG_X86_32
-	mcs	= (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
-	ptrs	= (unsigned long *)__pa_nodebug(&mc_tmp_ptrs);
-	blobs_p	= (struct ucode_blobs *)__pa_nodebug(&blobs);
-#else
-	mcs	= &mc_saved_data;
-	ptrs	= mc_tmp_ptrs;
-	blobs_p = &blobs;
-#endif
+	if (IS_ENABLED(CONFIG_X86_32))
+		iup = (struct microcode_intel **) __pa_nodebug(&intel_ucode_patch);
+	else
+		iup = &intel_ucode_patch;
 
-	_load_ucode_intel_bsp(mcs, ptrs, blobs_p);
+reget:
+	if (!*iup) {
+		patch = __load_ucode_intel(&uci);
+		if (!patch)
+			return;
+
+		*iup = patch;
+	}
+
+	uci.mc = *iup;
+
+	if (apply_microcode_early(&uci, true)) {
+		/* Mixed-silicon system? Try to refetch the proper patch: */
+		*iup = NULL;
+
+		goto reget;
+	}
 }
 
-void load_ucode_intel_ap(void)
+static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
 {
-	struct ucode_blobs *blobs_p;
-	unsigned long *ptrs, start = 0;
-	struct mc_saved_data *mcs;
-	struct ucode_cpu_info uci;
-	enum ucode_state ret;
-
-#ifdef CONFIG_X86_32
-	mcs	= (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
-	ptrs	= (unsigned long *)__pa_nodebug(mc_tmp_ptrs);
-	blobs_p	= (struct ucode_blobs *)__pa_nodebug(&blobs);
-#else
-	mcs	= &mc_saved_data;
-	ptrs	= mc_tmp_ptrs;
-	blobs_p = &blobs;
-#endif
+	struct microcode_header_intel *phdr;
+	struct ucode_patch *iter, *tmp;
 
-	/*
-	 * If there is no valid ucode previously saved in memory, no need to
-	 * update ucode on this AP.
-	 */
-	if (!mcs->num_saved)
-		return;
+	list_for_each_entry_safe(iter, tmp, &microcode_cache, plist) {
 
-	if (blobs_p->valid) {
-		start = blobs_p->start;
+		phdr = (struct microcode_header_intel *)iter->data;
 
-		/*
-		 * Pay attention to CONFIG_RANDOMIZE_MEMORY=y as it shuffles
-		 * physmem mapping too and there we have the initrd.
-		 */
-		start += PAGE_OFFSET - __PAGE_OFFSET_BASE;
-	}
+		if (phdr->rev <= uci->cpu_sig.rev)
+			continue;
 
-	collect_cpu_info_early(&uci);
-	ret = load_microcode(mcs, ptrs, start, &uci);
-	if (ret != UCODE_OK)
-		return;
+		if (!find_matching_signature(phdr,
+					     uci->cpu_sig.sig,
+					     uci->cpu_sig.pf))
+			continue;
 
-	apply_microcode_early(&uci, true);
+		return iter->data;
+	}
+	return NULL;
 }
 
 void reload_ucode_intel(void)
 {
+	struct microcode_intel *p;
 	struct ucode_cpu_info uci;
-	enum ucode_state ret;
-
-	if (!mc_saved_data.num_saved)
-		return;
 
 	collect_cpu_info_early(&uci);
 
-	ret = find_microcode_patch(mc_saved_data.mc_saved,
-				   mc_saved_data.num_saved, &uci);
-	if (ret != UCODE_OK)
+	p = find_patch(&uci);
+	if (!p)
 		return;
 
+	uci.mc = p;
+
 	apply_microcode_early(&uci, false);
 }
 
@@ -879,31 +760,13 @@ static int collect_cpu_info(int cpu_num,
 	return 0;
 }
 
-/*
- * return 0 - no update found
- * return 1 - found update
- */
-static int get_matching_mc(struct microcode_intel *mc, int cpu)
-{
-	struct cpu_signature cpu_sig;
-	unsigned int csig, cpf, crev;
-
-	collect_cpu_info(cpu, &cpu_sig);
-
-	csig = cpu_sig.sig;
-	cpf = cpu_sig.pf;
-	crev = cpu_sig.rev;
-
-	return has_newer_microcode(mc, csig, cpf, crev);
-}
-
 static int apply_microcode_intel(int cpu)
 {
 	struct microcode_intel *mc;
 	struct ucode_cpu_info *uci;
 	struct cpuinfo_x86 *c;
-	unsigned int val[2];
 	static int prev_rev;
+	u32 rev;
 
 	/* We should bind the task to the CPU */
 	if (WARN_ON(raw_smp_processor_id() != cpu))
@@ -911,46 +774,37 @@ static int apply_microcode_intel(int cpu
 
 	uci = ucode_cpu_info + cpu;
 	mc = uci->mc;
-	if (!mc)
-		return 0;
-
-	/*
-	 * Microcode on this CPU could be updated earlier. Only apply the
-	 * microcode patch in mc when it is newer than the one on this
-	 * CPU.
-	 */
-	if (!get_matching_mc(mc, cpu))
-		return 0;
+	if (!mc) {
+		/* Look for a newer patch in our cache: */
+		mc = find_patch(uci);
+		if (!mc)
+			return 0;
+	}
 
 	/* write microcode via MSR 0x79 */
 	wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
-	wrmsrl(MSR_IA32_UCODE_REV, 0);
 
-	/* As documented in the SDM: Do a CPUID 1 here */
-	sync_core();
-
-	/* get the current revision from MSR 0x8B */
-	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
+	rev = intel_get_microcode_revision();
 
-	if (val[1] != mc->hdr.rev) {
+	if (rev != mc->hdr.rev) {
 		pr_err("CPU%d update to revision 0x%x failed\n",
 		       cpu, mc->hdr.rev);
 		return -1;
 	}
 
-	if (val[1] != prev_rev) {
+	if (rev != prev_rev) {
 		pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
-			val[1],
+			rev,
 			mc->hdr.date & 0xffff,
 			mc->hdr.date >> 24,
 			(mc->hdr.date >> 16) & 0xff);
-		prev_rev = val[1];
+		prev_rev = rev;
 	}
 
 	c = &cpu_data(cpu);
 
-	uci->cpu_sig.rev = val[1];
-	c->microcode = val[1];
+	uci->cpu_sig.rev = rev;
+	c->microcode = rev;
 
 	return 0;
 }
@@ -962,8 +816,7 @@ static enum ucode_state generic_load_mic
 	u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL;
 	int new_rev = uci->cpu_sig.rev;
 	unsigned int leftover = size;
-	enum ucode_state state = UCODE_OK;
-	unsigned int curr_mc_size = 0;
+	unsigned int curr_mc_size = 0, new_mc_size = 0;
 	unsigned int csig, cpf;
 
 	while (leftover) {
@@ -1004,6 +857,7 @@ static enum ucode_state generic_load_mic
 			vfree(new_mc);
 			new_rev = mc_header.rev;
 			new_mc  = mc;
+			new_mc_size = mc_size;
 			mc = NULL;	/* trigger new vmalloc */
 		}
 
@@ -1015,14 +869,11 @@ static enum ucode_state generic_load_mic
 
 	if (leftover) {
 		vfree(new_mc);
-		state = UCODE_ERROR;
-		goto out;
+		return UCODE_ERROR;
 	}
 
-	if (!new_mc) {
-		state = UCODE_NFOUND;
-		goto out;
-	}
+	if (!new_mc)
+		return UCODE_NFOUND;
 
 	vfree(uci->mc);
 	uci->mc = (struct microcode_intel *)new_mc;
@@ -1032,12 +883,12 @@ static enum ucode_state generic_load_mic
 	 * permanent memory. So it will be loaded early when a CPU is hot added
 	 * or resumes.
 	 */
-	save_mc_for_early(new_mc);
+	save_mc_for_early(new_mc, new_mc_size);
 
 	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
 		 cpu, new_rev, uci->cpu_sig.rev);
-out:
-	return state;
+
+	return UCODE_OK;
 }
 
 static int get_ucode_fw(void *to, const void *from, size_t n)
@@ -1081,20 +932,11 @@ request_microcode_user(int cpu, const vo
 	return generic_load_microcode(cpu, (void *)buf, size, &get_ucode_user);
 }
 
-static void microcode_fini_cpu(int cpu)
-{
-	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
-	vfree(uci->mc);
-	uci->mc = NULL;
-}
-
 static struct microcode_ops microcode_intel_ops = {
 	.request_microcode_user		  = request_microcode_user,
 	.request_microcode_fw             = request_microcode_fw,
 	.collect_cpu_info                 = collect_cpu_info,
 	.apply_microcode                  = apply_microcode_intel,
-	.microcode_fini_cpu               = microcode_fini_cpu,
 };
 
 struct microcode_ops * __init init_intel_microcode(void)
@@ -1109,4 +951,3 @@ struct microcode_ops * __init init_intel
 
 	return &microcode_intel_ops;
 }
-
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/intel_lib.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/intel_lib.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/intel_lib.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/intel_lib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,184 +0,0 @@
-/*
- *	Intel CPU Microcode Update Driver for Linux
- *
- *	Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
- *			   H Peter Anvin" <hpa@zytor.com>
- *
- *	This driver allows to upgrade microcode on Intel processors
- *	belonging to IA-32 family - PentiumPro, Pentium II,
- *	Pentium III, Xeon, Pentium 4, etc.
- *
- *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
- *	Software Developer's Manual
- *	Order Number 253668 or free download from:
- *
- *	http://developer.intel.com/Assets/PDF/manual/253668.pdf
- *
- *	For more information, go to http://www.urbanmyth.org/microcode
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the 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/firmware.h>
-#include <linux/uaccess.h>
-#include <linux/kernel.h>
-
-#include <asm/microcode_intel.h>
-#include <asm/processor.h>
-#include <asm/msr.h>
-
-static inline bool cpu_signatures_match(unsigned int s1, unsigned int p1,
-					unsigned int s2, unsigned int p2)
-{
-	if (s1 != s2)
-		return false;
-
-	/* Processor flags are either both 0 ... */
-	if (!p1 && !p2)
-		return true;
-
-	/* ... or they intersect. */
-	return p1 & p2;
-}
-
-int microcode_sanity_check(void *mc, int print_err)
-{
-	unsigned long total_size, data_size, ext_table_size;
-	struct microcode_header_intel *mc_header = mc;
-	struct extended_sigtable *ext_header = NULL;
-	u32 sum, orig_sum, ext_sigcount = 0, i;
-	struct extended_signature *ext_sig;
-
-	total_size = get_totalsize(mc_header);
-	data_size = get_datasize(mc_header);
-
-	if (data_size + MC_HEADER_SIZE > total_size) {
-		if (print_err)
-			pr_err("Error: bad microcode data file size.\n");
-		return -EINVAL;
-	}
-
-	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
-		if (print_err)
-			pr_err("Error: invalid/unknown microcode update format.\n");
-		return -EINVAL;
-	}
-
-	ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
-	if (ext_table_size) {
-		u32 ext_table_sum = 0;
-		u32 *ext_tablep;
-
-		if ((ext_table_size < EXT_HEADER_SIZE)
-		 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
-			if (print_err)
-				pr_err("Error: truncated extended signature table.\n");
-			return -EINVAL;
-		}
-
-		ext_header = mc + MC_HEADER_SIZE + data_size;
-		if (ext_table_size != exttable_size(ext_header)) {
-			if (print_err)
-				pr_err("Error: extended signature table size mismatch.\n");
-			return -EFAULT;
-		}
-
-		ext_sigcount = ext_header->count;
-
-		/*
-		 * Check extended table checksum: the sum of all dwords that
-		 * comprise a valid table must be 0.
-		 */
-		ext_tablep = (u32 *)ext_header;
-
-		i = ext_table_size / sizeof(u32);
-		while (i--)
-			ext_table_sum += ext_tablep[i];
-
-		if (ext_table_sum) {
-			if (print_err)
-				pr_warn("Bad extended signature table checksum, aborting.\n");
-			return -EINVAL;
-		}
-	}
-
-	/*
-	 * Calculate the checksum of update data and header. The checksum of
-	 * valid update data and header including the extended signature table
-	 * must be 0.
-	 */
-	orig_sum = 0;
-	i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
-	while (i--)
-		orig_sum += ((u32 *)mc)[i];
-
-	if (orig_sum) {
-		if (print_err)
-			pr_err("Bad microcode data checksum, aborting.\n");
-		return -EINVAL;
-	}
-
-	if (!ext_table_size)
-		return 0;
-
-	/*
-	 * Check extended signature checksum: 0 => valid.
-	 */
-	for (i = 0; i < ext_sigcount; i++) {
-		ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
-			  EXT_SIGNATURE_SIZE * i;
-
-		sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
-		      (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
-		if (sum) {
-			if (print_err)
-				pr_err("Bad extended signature checksum, aborting.\n");
-			return -EINVAL;
-		}
-	}
-	return 0;
-}
-
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
-int find_matching_signature(void *mc, unsigned int csig, int cpf)
-{
-	struct microcode_header_intel *mc_hdr = mc;
-	struct extended_sigtable *ext_hdr;
-	struct extended_signature *ext_sig;
-	int i;
-
-	if (cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
-		return 1;
-
-	/* Look for ext. headers: */
-	if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
-		return 0;
-
-	ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
-	ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
-
-	for (i = 0; i < ext_hdr->count; i++) {
-		if (cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
-			return 1;
-		ext_sig++;
-	}
-	return 0;
-}
-
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
-int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev)
-{
-	struct microcode_header_intel *mc_hdr = mc;
-
-	if (mc_hdr->rev <= new_rev)
-		return 0;
-
-	return find_matching_signature(mc, csig, cpf);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/Makefile linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/Makefile
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/microcode/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/microcode/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
 microcode-y				:= core.o
 obj-$(CONFIG_MICROCODE)			+= microcode.o
-microcode-$(CONFIG_MICROCODE_INTEL)	+= intel.o intel_lib.o
+microcode-$(CONFIG_MICROCODE_INTEL)	+= intel.o
 microcode-$(CONFIG_MICROCODE_AMD)	+= amd.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/mshyperv.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mshyperv.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/mshyperv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/mshyperv.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,12 +25,12 @@
 #include <asm/hyperv.h>
 #include <asm/mshyperv.h>
 #include <asm/desc.h>
-#include <asm/idle.h>
 #include <asm/irq_regs.h>
 #include <asm/i8259.h>
 #include <asm/apic.h>
 #include <asm/timer.h>
 #include <asm/reboot.h>
+#include <asm/nmi.h>
 
 struct ms_hyperv_info ms_hyperv;
 EXPORT_SYMBOL_GPL(ms_hyperv);
@@ -133,9 +133,9 @@ static uint32_t  __init ms_hyperv_platfo
 	return 0;
 }
 
-static cycle_t read_hv_clock(struct clocksource *arg)
+static u64 read_hv_clock(struct clocksource *arg)
 {
-	cycle_t current_tick;
+	u64 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
@@ -158,6 +158,26 @@ static unsigned char hv_get_nmi_reason(v
 	return 0;
 }
 
+#ifdef CONFIG_X86_LOCAL_APIC
+/*
+ * Prior to WS2016 Debug-VM sends NMIs to all CPUs which makes
+ * it dificult to process CHANNELMSG_UNLOAD in case of crash. Handle
+ * unknown NMI on the first CPU which gets it.
+ */
+static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
+{
+	static atomic_t nmi_cpu = ATOMIC_INIT(-1);
+
+	if (!unknown_nmi_panic)
+		return NMI_DONE;
+
+	if (atomic_cmpxchg(&nmi_cpu, -1, raw_smp_processor_id()) != -1)
+		return NMI_HANDLED;
+
+	return NMI_DONE;
+}
+#endif
+
 static void __init ms_hyperv_init_platform(void)
 {
 	/*
@@ -183,6 +203,9 @@ static void __init ms_hyperv_init_platfo
 		pr_info("HyperV: LAPIC Timer Frequency: %#x\n",
 			lapic_timer_frequency);
 	}
+
+	register_nmi_handler(NMI_UNKNOWN, hv_nmi_unknown, NMI_FLAG_FIRST,
+			     "hv_nmi_unknown");
 #endif
 
 	if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/scattered.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/scattered.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/scattered.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/scattered.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,11 +17,20 @@ struct cpuid_bit {
 	u32 sub_leaf;
 };
 
-enum cpuid_regs {
-	CR_EAX = 0,
-	CR_ECX,
-	CR_EDX,
-	CR_EBX
+/* Please keep the leaf sorted by cpuid_bit.level for faster search. */
+static const struct cpuid_bit cpuid_bits[] = {
+	{ X86_FEATURE_APERFMPERF,       CPUID_ECX,  0, 0x00000006, 0 },
+	{ X86_FEATURE_EPB,		CPUID_ECX,  3, 0x00000006, 0 },
+	{ X86_FEATURE_INTEL_PT,		CPUID_EBX, 25, 0x00000007, 0 },
+	{ X86_FEATURE_AVX512_4VNNIW,    CPUID_EDX,  2, 0x00000007, 0 },
+	{ X86_FEATURE_AVX512_4FMAPS,    CPUID_EDX,  3, 0x00000007, 0 },
+	{ X86_FEATURE_CAT_L3,		CPUID_EBX,  1, 0x00000010, 0 },
+	{ X86_FEATURE_CAT_L2,		CPUID_EBX,  2, 0x00000010, 0 },
+	{ X86_FEATURE_CDP_L3,		CPUID_ECX,  2, 0x00000010, 1 },
+	{ X86_FEATURE_HW_PSTATE,	CPUID_EDX,  7, 0x80000007, 0 },
+	{ X86_FEATURE_CPB,		CPUID_EDX,  9, 0x80000007, 0 },
+	{ X86_FEATURE_PROC_FEEDBACK,    CPUID_EDX, 11, 0x80000007, 0 },
+	{ 0, 0, 0, 0, 0 }
 };
 
 void init_scattered_cpuid_features(struct cpuinfo_x86 *c)
@@ -30,18 +39,6 @@ void init_scattered_cpuid_features(struc
 	u32 regs[4];
 	const struct cpuid_bit *cb;
 
-	static const struct cpuid_bit cpuid_bits[] = {
-		{ X86_FEATURE_INTEL_PT,		CR_EBX,25, 0x00000007, 0 },
-		{ X86_FEATURE_AVX512_4VNNIW,	CR_EDX, 2, 0x00000007, 0 },
-		{ X86_FEATURE_AVX512_4FMAPS,	CR_EDX, 3, 0x00000007, 0 },
-		{ X86_FEATURE_APERFMPERF,	CR_ECX, 0, 0x00000006, 0 },
-		{ X86_FEATURE_EPB,		CR_ECX, 3, 0x00000006, 0 },
-		{ X86_FEATURE_HW_PSTATE,	CR_EDX, 7, 0x80000007, 0 },
-		{ X86_FEATURE_CPB,		CR_EDX, 9, 0x80000007, 0 },
-		{ X86_FEATURE_PROC_FEEDBACK,	CR_EDX,11, 0x80000007, 0 },
-		{ 0, 0, 0, 0, 0 }
-	};
-
 	for (cb = cpuid_bits; cb->feature; cb++) {
 
 		/* Verify that the level is valid */
@@ -50,10 +47,35 @@ void init_scattered_cpuid_features(struc
 		    max_level > (cb->level | 0xffff))
 			continue;
 
-		cpuid_count(cb->level, cb->sub_leaf, &regs[CR_EAX],
-			    &regs[CR_EBX], &regs[CR_ECX], &regs[CR_EDX]);
+		cpuid_count(cb->level, cb->sub_leaf, &regs[CPUID_EAX],
+			    &regs[CPUID_EBX], &regs[CPUID_ECX],
+			    &regs[CPUID_EDX]);
 
 		if (regs[cb->reg] & (1 << cb->bit))
 			set_cpu_cap(c, cb->feature);
 	}
 }
+
+u32 get_scattered_cpuid_leaf(unsigned int level, unsigned int sub_leaf,
+			     enum cpuid_regs_idx reg)
+{
+	const struct cpuid_bit *cb;
+	u32 cpuid_val = 0;
+
+	for (cb = cpuid_bits; cb->feature; cb++) {
+
+		if (level > cb->level)
+			continue;
+
+		if (level < cb->level)
+			break;
+
+		if (reg == cb->reg && sub_leaf == cb->sub_leaf) {
+			if (cpu_has(&boot_cpu_data, cb->feature))
+				cpuid_val |= BIT(cb->bit);
+		}
+	}
+
+	return cpuid_val;
+}
+EXPORT_SYMBOL_GPL(get_scattered_cpuid_leaf);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpu/vmware.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/vmware.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpu/vmware.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpu/vmware.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,11 +24,16 @@
 #include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/export.h>
+#include <linux/clocksource.h>
 #include <asm/div64.h>
 #include <asm/x86_init.h>
 #include <asm/hypervisor.h>
 #include <asm/timer.h>
 #include <asm/apic.h>
+#include <asm/timer.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt)	"vmware: " fmt
 
 #define CPUID_VMWARE_INFO_LEAF	0x40000000
 #define VMWARE_HYPERVISOR_MAGIC	0x564D5868
@@ -48,6 +53,8 @@
 			"2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) :	\
 			"memory");
 
+static unsigned long vmware_tsc_khz __ro_after_init;
+
 static inline int __vmware_platform(void)
 {
 	uint32_t eax, ebx, ecx, edx;
@@ -57,35 +64,80 @@ static inline int __vmware_platform(void
 
 static unsigned long vmware_get_tsc_khz(void)
 {
-	uint64_t tsc_hz, lpj;
-	uint32_t eax, ebx, ecx, edx;
+	return vmware_tsc_khz;
+}
 
-	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
+#ifdef CONFIG_PARAVIRT
+static struct cyc2ns_data vmware_cyc2ns __ro_after_init;
+static int vmw_sched_clock __initdata = 1;
 
-	tsc_hz = eax | (((uint64_t)ebx) << 32);
-	do_div(tsc_hz, 1000);
-	BUG_ON(tsc_hz >> 32);
-	pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
-			 (unsigned long) tsc_hz / 1000,
-			 (unsigned long) tsc_hz % 1000);
+static __init int setup_vmw_sched_clock(char *s)
+{
+	vmw_sched_clock = 0;
+	return 0;
+}
+early_param("no-vmw-sched-clock", setup_vmw_sched_clock);
 
-	if (!preset_lpj) {
-		lpj = ((u64)tsc_hz * 1000);
-		do_div(lpj, HZ);
-		preset_lpj = lpj;
-	}
+static unsigned long long vmware_sched_clock(void)
+{
+	unsigned long long ns;
 
-	return tsc_hz;
+	ns = mul_u64_u32_shr(rdtsc(), vmware_cyc2ns.cyc2ns_mul,
+			     vmware_cyc2ns.cyc2ns_shift);
+	ns -= vmware_cyc2ns.cyc2ns_offset;
+	return ns;
+}
+
+static void __init vmware_sched_clock_setup(void)
+{
+	struct cyc2ns_data *d = &vmware_cyc2ns;
+	unsigned long long tsc_now = rdtsc();
+
+	clocks_calc_mult_shift(&d->cyc2ns_mul, &d->cyc2ns_shift,
+			       vmware_tsc_khz, NSEC_PER_MSEC, 0);
+	d->cyc2ns_offset = mul_u64_u32_shr(tsc_now, d->cyc2ns_mul,
+					   d->cyc2ns_shift);
+
+	pv_time_ops.sched_clock = vmware_sched_clock;
+	pr_info("using sched offset of %llu ns\n", d->cyc2ns_offset);
+}
+
+static void __init vmware_paravirt_ops_setup(void)
+{
+	pv_info.name = "VMware hypervisor";
+	pv_cpu_ops.io_delay = paravirt_nop;
+
+	if (vmware_tsc_khz && vmw_sched_clock)
+		vmware_sched_clock_setup();
 }
+#else
+#define vmware_paravirt_ops_setup() do {} while (0)
+#endif
 
 static void __init vmware_platform_setup(void)
 {
 	uint32_t eax, ebx, ecx, edx;
+	uint64_t lpj, tsc_khz;
 
 	VMWARE_PORT(GETHZ, eax, ebx, ecx, edx);
 
 	if (ebx != UINT_MAX) {
+		lpj = tsc_khz = eax | (((uint64_t)ebx) << 32);
+		do_div(tsc_khz, 1000);
+		WARN_ON(tsc_khz >> 32);
+		pr_info("TSC freq read from hypervisor : %lu.%03lu MHz\n",
+			(unsigned long) tsc_khz / 1000,
+			(unsigned long) tsc_khz % 1000);
+
+		if (!preset_lpj) {
+			do_div(lpj, HZ);
+			preset_lpj = lpj;
+		}
+
+		vmware_tsc_khz = tsc_khz;
 		x86_platform.calibrate_tsc = vmware_get_tsc_khz;
+		x86_platform.calibrate_cpu = vmware_get_tsc_khz;
+
 #ifdef CONFIG_X86_LOCAL_APIC
 		/* Skip lapic calibration since we know the bus frequency. */
 		lapic_timer_frequency = ecx / HZ;
@@ -96,6 +148,8 @@ static void __init vmware_platform_setup
 		pr_warn("Failed to get TSC freq from the hypervisor\n");
 	}
 
+	vmware_paravirt_ops_setup();
+
 #ifdef CONFIG_X86_IO_APIC
 	no_timer_check = 1;
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/cpuid.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpuid.c
--- linux-libre-4.9-gnu/arch/x86/kernel/cpuid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/cpuid.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,10 +45,7 @@
 #include <asm/msr.h>
 
 static struct class *cpuid_class;
-
-struct cpuid_regs {
-	u32 eax, ebx, ecx, edx;
-};
+static enum cpuhp_state cpuhp_cpuid_state;
 
 static void cpuid_smp_cpuid(void *cmd_block)
 {
@@ -115,7 +112,7 @@ static const struct file_operations cpui
 	.open = cpuid_open,
 };
 
-static int cpuid_device_create(int cpu)
+static int cpuid_device_create(unsigned int cpu)
 {
 	struct device *dev;
 
@@ -124,35 +121,12 @@ static int cpuid_device_create(int cpu)
 	return PTR_ERR_OR_ZERO(dev);
 }
 
-static void cpuid_device_destroy(int cpu)
+static int cpuid_device_destroy(unsigned int cpu)
 {
 	device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+	return 0;
 }
 
-static int cpuid_class_cpu_callback(struct notifier_block *nfb,
-				    unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long)hcpu;
-	int err = 0;
-
-	switch (action) {
-	case CPU_UP_PREPARE:
-		err = cpuid_device_create(cpu);
-		break;
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-	case CPU_DEAD:
-		cpuid_device_destroy(cpu);
-		break;
-	}
-	return notifier_from_errno(err);
-}
-
-static struct notifier_block cpuid_class_cpu_notifier =
-{
-	.notifier_call = cpuid_class_cpu_callback,
-};
-
 static char *cpuid_devnode(struct device *dev, umode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt));
@@ -160,15 +134,13 @@ static char *cpuid_devnode(struct device
 
 static int __init cpuid_init(void)
 {
-	int i, err = 0;
-	i = 0;
+	int err;
 
 	if (__register_chrdev(CPUID_MAJOR, 0, NR_CPUS,
 			      "cpu/cpuid", &cpuid_fops)) {
 		printk(KERN_ERR "cpuid: unable to get major %d for cpuid\n",
 		       CPUID_MAJOR);
-		err = -EBUSY;
-		goto out;
+		return -EBUSY;
 	}
 	cpuid_class = class_create(THIS_MODULE, "cpuid");
 	if (IS_ERR(cpuid_class)) {
@@ -177,45 +149,28 @@ static int __init cpuid_init(void)
 	}
 	cpuid_class->devnode = cpuid_devnode;
 
-	cpu_notifier_register_begin();
-	for_each_online_cpu(i) {
-		err = cpuid_device_create(i);
-		if (err != 0)
-			goto out_class;
-	}
-	__register_hotcpu_notifier(&cpuid_class_cpu_notifier);
-	cpu_notifier_register_done();
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/cpuid:online",
+				cpuid_device_create, cpuid_device_destroy);
+	if (err < 0)
+		goto out_class;
 
-	err = 0;
-	goto out;
+	cpuhp_cpuid_state = err;
+	return 0;
 
 out_class:
-	i = 0;
-	for_each_online_cpu(i) {
-		cpuid_device_destroy(i);
-	}
-	cpu_notifier_register_done();
 	class_destroy(cpuid_class);
 out_chrdev:
 	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
-out:
 	return err;
 }
+module_init(cpuid_init);
 
 static void __exit cpuid_exit(void)
 {
-	int cpu = 0;
-
-	cpu_notifier_register_begin();
-	for_each_online_cpu(cpu)
-		cpuid_device_destroy(cpu);
+	cpuhp_remove_state(cpuhp_cpuid_state);
 	class_destroy(cpuid_class);
 	__unregister_chrdev(CPUID_MAJOR, 0, NR_CPUS, "cpu/cpuid");
-	__unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
-	cpu_notifier_register_done();
 }
-
-module_init(cpuid_init);
 module_exit(cpuid_exit);
 
 MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/crash.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/crash.c
--- linux-libre-4.9-gnu/arch/x86/kernel/crash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/crash.c	2017-02-12 16:03:20.000000000 -0500
@@ -631,9 +631,9 @@ static int determine_backup_region(u64 s
 
 int crash_load_segments(struct kimage *image)
 {
-	unsigned long src_start, src_sz, elf_sz;
-	void *elf_addr;
 	int ret;
+	struct kexec_buf kbuf = { .image = image, .buf_min = 0,
+				  .buf_max = ULONG_MAX, .top_down = false };
 
 	/*
 	 * Determine and load a segment for backup area. First 640K RAM
@@ -647,43 +647,44 @@ int crash_load_segments(struct kimage *i
 	if (ret < 0)
 		return ret;
 
-	src_start = image->arch.backup_src_start;
-	src_sz = image->arch.backup_src_sz;
-
 	/* Add backup segment. */
-	if (src_sz) {
+	if (image->arch.backup_src_sz) {
+		kbuf.buffer = &crash_zero_bytes;
+		kbuf.bufsz = sizeof(crash_zero_bytes);
+		kbuf.memsz = image->arch.backup_src_sz;
+		kbuf.buf_align = PAGE_SIZE;
 		/*
 		 * Ideally there is no source for backup segment. This is
 		 * copied in purgatory after crash. Just add a zero filled
 		 * segment for now to make sure checksum logic works fine.
 		 */
-		ret = kexec_add_buffer(image, (char *)&crash_zero_bytes,
-				       sizeof(crash_zero_bytes), src_sz,
-				       PAGE_SIZE, 0, -1, 0,
-				       &image->arch.backup_load_addr);
+		ret = kexec_add_buffer(&kbuf);
 		if (ret)
 			return ret;
+		image->arch.backup_load_addr = kbuf.mem;
 		pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n",
-			 image->arch.backup_load_addr, src_start, src_sz);
+			 image->arch.backup_load_addr,
+			 image->arch.backup_src_start, kbuf.memsz);
 	}
 
 	/* Prepare elf headers and add a segment */
-	ret = prepare_elf_headers(image, &elf_addr, &elf_sz);
+	ret = prepare_elf_headers(image, &kbuf.buffer, &kbuf.bufsz);
 	if (ret)
 		return ret;
 
-	image->arch.elf_headers = elf_addr;
-	image->arch.elf_headers_sz = elf_sz;
+	image->arch.elf_headers = kbuf.buffer;
+	image->arch.elf_headers_sz = kbuf.bufsz;
 
-	ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz,
-			ELF_CORE_HEADER_ALIGN, 0, -1, 0,
-			&image->arch.elf_load_addr);
+	kbuf.memsz = kbuf.bufsz;
+	kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
+	ret = kexec_add_buffer(&kbuf);
 	if (ret) {
 		vfree((void *)image->arch.elf_headers);
 		return ret;
 	}
+	image->arch.elf_load_addr = kbuf.mem;
 	pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
-		 image->arch.elf_load_addr, elf_sz, elf_sz);
+		 image->arch.elf_load_addr, kbuf.bufsz, kbuf.bufsz);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/crash_dump_32.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/crash_dump_32.c
--- linux-libre-4.9-gnu/arch/x86/kernel/crash_dump_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/crash_dump_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/highmem.h>
 #include <linux/crash_dump.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static void *kdump_buf_page;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/doublefault.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/doublefault.c
--- linux-libre-4.9-gnu/arch/x86/kernel/doublefault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/doublefault.c	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
 #include <linux/init_task.h>
 #include <linux/fs.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/desc.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/dumpstack_32.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/dumpstack_32.c
--- linux-libre-4.9-gnu/arch/x86/kernel/dumpstack_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/dumpstack_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,18 +16,15 @@
 
 #include <asm/stacktrace.h>
 
-void stack_type_str(enum stack_type type, const char **begin, const char **end)
+const char *stack_type_name(enum stack_type type)
 {
-	switch (type) {
-	case STACK_TYPE_IRQ:
-	case STACK_TYPE_SOFTIRQ:
-		*begin = "IRQ";
-		*end   = "EOI";
-		break;
-	default:
-		*begin = NULL;
-		*end   = NULL;
-	}
+	if (type == STACK_TYPE_IRQ)
+		return "IRQ";
+
+	if (type == STACK_TYPE_SOFTIRQ)
+		return "SOFTIRQ";
+
+	return NULL;
 }
 
 static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
@@ -109,8 +106,10 @@ recursion_check:
 	 * just break out and report an unknown stack type.
 	 */
 	if (visit_mask) {
-		if (*visit_mask & (1UL << info->type))
+		if (*visit_mask & (1UL << info->type)) {
+			printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
 			goto unknown;
+		}
 		*visit_mask |= 1UL << info->type;
 	}
 
@@ -121,36 +120,6 @@ unknown:
 	return -EINVAL;
 }
 
-void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-			unsigned long *sp, char *log_lvl)
-{
-	unsigned long *stack;
-	int i;
-
-	if (!try_get_task_stack(task))
-		return;
-
-	sp = sp ? : get_stack_pointer(task, regs);
-
-	stack = sp;
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (kstack_end(stack))
-			break;
-		if ((i % STACKSLOTS_PER_LINE) == 0) {
-			if (i != 0)
-				pr_cont("\n");
-			printk("%s %08lx", log_lvl, *stack++);
-		} else
-			pr_cont(" %08lx", *stack++);
-		touch_nmi_watchdog();
-	}
-	pr_cont("\n");
-	show_trace_log_lvl(task, regs, sp, log_lvl);
-
-	put_task_stack(task);
-}
-
-
 void show_regs(struct pt_regs *regs)
 {
 	int i;
@@ -168,8 +137,7 @@ void show_regs(struct pt_regs *regs)
 		unsigned char c;
 		u8 *ip;
 
-		pr_emerg("Stack:\n");
-		show_stack_log_lvl(current, regs, NULL, KERN_EMERG);
+		show_trace_log_lvl(current, regs, NULL, KERN_EMERG);
 
 		pr_emerg("Code:");
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/dumpstack_64.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/dumpstack_64.c
--- linux-libre-4.9-gnu/arch/x86/kernel/dumpstack_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/dumpstack_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,23 +28,17 @@ static unsigned long exception_stack_siz
 	[DEBUG_STACK - 1]			= DEBUG_STKSZ
 };
 
-void stack_type_str(enum stack_type type, const char **begin, const char **end)
+const char *stack_type_name(enum stack_type type)
 {
 	BUILD_BUG_ON(N_EXCEPTION_STACKS != 4);
 
-	switch (type) {
-	case STACK_TYPE_IRQ:
-		*begin = "IRQ";
-		*end   = "EOI";
-		break;
-	case STACK_TYPE_EXCEPTION ... STACK_TYPE_EXCEPTION_LAST:
-		*begin = exception_stack_names[type - STACK_TYPE_EXCEPTION];
-		*end   = "EOE";
-		break;
-	default:
-		*begin = NULL;
-		*end   = NULL;
-	}
+	if (type == STACK_TYPE_IRQ)
+		return "IRQ";
+
+	if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
+		return exception_stack_names[type - STACK_TYPE_EXCEPTION];
+
+	return NULL;
 }
 
 static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
@@ -128,8 +122,10 @@ recursion_check:
 	 * just break out and report an unknown stack type.
 	 */
 	if (visit_mask) {
-		if (*visit_mask & (1UL << info->type))
+		if (*visit_mask & (1UL << info->type)) {
+			printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
 			goto unknown;
+		}
 		*visit_mask |= 1UL << info->type;
 	}
 
@@ -140,56 +136,6 @@ unknown:
 	return -EINVAL;
 }
 
-void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-			unsigned long *sp, char *log_lvl)
-{
-	unsigned long *irq_stack_end;
-	unsigned long *irq_stack;
-	unsigned long *stack;
-	int i;
-
-	if (!try_get_task_stack(task))
-		return;
-
-	irq_stack_end = (unsigned long *)this_cpu_read(irq_stack_ptr);
-	irq_stack     = irq_stack_end - (IRQ_STACK_SIZE / sizeof(long));
-
-	sp = sp ? : get_stack_pointer(task, regs);
-
-	stack = sp;
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		unsigned long word;
-
-		if (stack >= irq_stack && stack <= irq_stack_end) {
-			if (stack == irq_stack_end) {
-				stack = (unsigned long *) (irq_stack_end[-1]);
-				pr_cont(" <EOI> ");
-			}
-		} else {
-		if (kstack_end(stack))
-			break;
-		}
-
-		if (probe_kernel_address(stack, word))
-			break;
-
-		if ((i % STACKSLOTS_PER_LINE) == 0) {
-			if (i != 0)
-				pr_cont("\n");
-			printk("%s %016lx", log_lvl, word);
-		} else
-			pr_cont(" %016lx", word);
-
-		stack++;
-		touch_nmi_watchdog();
-	}
-
-	pr_cont("\n");
-	show_trace_log_lvl(task, regs, sp, log_lvl);
-
-	put_task_stack(task);
-}
-
 void show_regs(struct pt_regs *regs)
 {
 	int i;
@@ -207,8 +153,7 @@ void show_regs(struct pt_regs *regs)
 		unsigned char c;
 		u8 *ip;
 
-		printk(KERN_DEFAULT "Stack:\n");
-		show_stack_log_lvl(current, regs, NULL, KERN_DEFAULT);
+		show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
 
 		printk(KERN_DEFAULT "Code: ");
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/dumpstack.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/dumpstack.c
--- linux-libre-4.9-gnu/arch/x86/kernel/dumpstack.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/dumpstack.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
 int panic_on_unrecovered_nmi;
 int panic_on_io_nmi;
 unsigned int code_bytes = 64;
-int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE;
 static int die_counter;
 
 bool in_task_stack(unsigned long *stack, struct task_struct *task,
@@ -46,14 +45,7 @@ static void printk_stack_address(unsigne
 				 char *log_lvl)
 {
 	touch_nmi_watchdog();
-	printk("%s [<%p>] %s%pB\n",
-		log_lvl, (void *)address, reliable ? "" : "? ",
-		(void *)address);
-}
-
-void printk_address(unsigned long address)
-{
-	pr_cont(" [<%p>] %pS\n", (void *)address, (void *)address);
+	printk("%s %s%pB\n", log_lvl, reliable ? "" : "? ", (void *)address);
 }
 
 void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
@@ -67,6 +59,7 @@ void show_trace_log_lvl(struct task_stru
 	printk("%sCall Trace:\n", log_lvl);
 
 	unwind_start(&state, task, regs, stack);
+	stack = stack ? : get_stack_pointer(task, regs);
 
 	/*
 	 * Iterate through the stacks, starting with the current stack pointer.
@@ -82,8 +75,8 @@ void show_trace_log_lvl(struct task_stru
 	 * - softirq stack
 	 * - hardirq stack
 	 */
-	for (; stack; stack = stack_info.next_sp) {
-		const char *str_begin, *str_end;
+	for (regs = NULL; stack; stack = stack_info.next_sp) {
+		const char *stack_name;
 
 		/*
 		 * If we overflowed the task stack into a guard page, jump back
@@ -95,9 +88,9 @@ void show_trace_log_lvl(struct task_stru
 		if (get_stack_info(stack, task, &stack_info, &visit_mask))
 			break;
 
-		stack_type_str(stack_info.type, &str_begin, &str_end);
-		if (str_begin)
-			printk("%s <%s> ", log_lvl, str_begin);
+		stack_name = stack_type_name(stack_info.type);
+		if (stack_name)
+			printk("%s <%s>\n", log_lvl, stack_name);
 
 		/*
 		 * Scan the stack, printing any text addresses we find.  At the
@@ -119,6 +112,15 @@ void show_trace_log_lvl(struct task_stru
 			if (!__kernel_text_address(addr))
 				continue;
 
+			/*
+			 * Don't print regs->ip again if it was already printed
+			 * by __show_regs() below.
+			 */
+			if (regs && stack == &regs->ip) {
+				unwind_next_frame(&state);
+				continue;
+			}
+
 			if (stack == ret_addr_p)
 				reliable = 1;
 
@@ -146,10 +148,15 @@ void show_trace_log_lvl(struct task_stru
 			 * of the addresses will just be printed as unreliable.
 			 */
 			unwind_next_frame(&state);
+
+			/* if the frame has entry regs, print them */
+			regs = unwind_get_entry_regs(&state);
+			if (regs)
+				__show_regs(regs, 0);
 		}
 
-		if (str_end)
-			printk("%s <%s> ", log_lvl, str_end);
+		if (stack_name)
+			printk("%s </%s>\n", log_lvl, stack_name);
 	}
 }
 
@@ -164,12 +171,12 @@ void show_stack(struct task_struct *task
 	if (!sp && task == current)
 		sp = get_stack_pointer(current, NULL);
 
-	show_stack_log_lvl(task, NULL, sp, "");
+	show_trace_log_lvl(task, NULL, sp, KERN_DEFAULT);
 }
 
 void show_stack_regs(struct pt_regs *regs)
 {
-	show_stack_log_lvl(current, regs, NULL, "");
+	show_trace_log_lvl(current, regs, NULL, KERN_DEFAULT);
 }
 
 static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED;
@@ -261,14 +268,11 @@ int __die(const char *str, struct pt_reg
 		sp = kernel_stack_pointer(regs);
 		savesegment(ss, ss);
 	}
-	printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip);
-	print_symbol("%s", regs->ip);
-	printk(" SS:ESP %04x:%08lx\n", ss, sp);
+	printk(KERN_EMERG "EIP: %pS SS:ESP: %04x:%08lx\n",
+	       (void *)regs->ip, ss, sp);
 #else
 	/* Executive summary in case the oops scrolled away */
-	printk(KERN_ALERT "RIP ");
-	printk_address(regs->ip);
-	printk(" RSP <%016lx>\n", regs->sp);
+	printk(KERN_ALERT "RIP: %pS RSP: %016lx\n", (void *)regs->ip, regs->sp);
 #endif
 	return 0;
 }
@@ -291,22 +295,6 @@ void die(const char *str, struct pt_regs
 	oops_end(flags, regs, sig);
 }
 
-static int __init kstack_setup(char *s)
-{
-	ssize_t ret;
-	unsigned long val;
-
-	if (!s)
-		return -EINVAL;
-
-	ret = kstrtoul(s, 0, &val);
-	if (ret)
-		return ret;
-	kstack_depth_to_print = val;
-	return 0;
-}
-early_param("kstack", kstack_setup);
-
 static int __init code_bytes_setup(char *s)
 {
 	ssize_t ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/fpu/bugs.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/bugs.c
--- linux-libre-4.9-gnu/arch/x86/kernel/fpu/bugs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/bugs.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,17 +23,12 @@ static double __initdata y = 3145727.0;
  */
 void __init fpu__init_check_bugs(void)
 {
-	u32 cr0_saved;
 	s32 fdiv_bug;
 
 	/* kernel_fpu_begin/end() relies on patched alternative instructions. */
 	if (!boot_cpu_has(X86_FEATURE_FPU))
 		return;
 
-	/* We might have CR0::TS set already, clear it: */
-	cr0_saved = read_cr0();
-	write_cr0(cr0_saved & ~X86_CR0_TS);
-
 	kernel_fpu_begin();
 
 	/*
@@ -56,8 +51,6 @@ void __init fpu__init_check_bugs(void)
 
 	kernel_fpu_end();
 
-	write_cr0(cr0_saved);
-
 	if (fdiv_bug) {
 		set_cpu_bug(&boot_cpu_data, X86_BUG_FDIV);
 		pr_warn("Hmm, FPU with FDIV bug\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/fpu/core.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/core.c
--- linux-libre-4.9-gnu/arch/x86/kernel/fpu/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,7 @@
 #include <asm/fpu/regset.h>
 #include <asm/fpu/signal.h>
 #include <asm/fpu/types.h>
+#include <asm/fpu/xstate.h>
 #include <asm/traps.h>
 
 #include <linux/hardirq.h>
@@ -58,27 +59,9 @@ static bool kernel_fpu_disabled(void)
 	return this_cpu_read(in_kernel_fpu);
 }
 
-/*
- * Were we in an interrupt that interrupted kernel mode?
- *
- * On others, we can do a kernel_fpu_begin/end() pair *ONLY* if that
- * pair does nothing at all: the thread must not have fpu (so
- * that we don't try to save the FPU state), and TS must
- * be set (so that the clts/stts pair does nothing that is
- * visible in the interrupted kernel thread).
- *
- * Except for the eagerfpu case when we return true; in the likely case
- * the thread has FPU but we are not going to set/clear TS.
- */
 static bool interrupted_kernel_fpu_idle(void)
 {
-	if (kernel_fpu_disabled())
-		return false;
-
-	if (use_eager_fpu())
-		return true;
-
-	return !current->thread.fpu.fpregs_active && (read_cr0() & X86_CR0_TS);
+	return !kernel_fpu_disabled();
 }
 
 /*
@@ -125,8 +108,7 @@ void __kernel_fpu_begin(void)
 		 */
 		copy_fpregs_to_fpstate(fpu);
 	} else {
-		this_cpu_write(fpu_fpregs_owner_ctx, NULL);
-		__fpregs_activate_hw();
+		__cpu_invalidate_fpregs_state();
 	}
 }
 EXPORT_SYMBOL(__kernel_fpu_begin);
@@ -137,8 +119,6 @@ void __kernel_fpu_end(void)
 
 	if (fpu->fpregs_active)
 		copy_kernel_to_fpregs(&fpu->state);
-	else
-		__fpregs_deactivate_hw();
 
 	kernel_fpu_enable();
 }
@@ -159,35 +139,6 @@ void kernel_fpu_end(void)
 EXPORT_SYMBOL_GPL(kernel_fpu_end);
 
 /*
- * CR0::TS save/restore functions:
- */
-int irq_ts_save(void)
-{
-	/*
-	 * If in process context and not atomic, we can take a spurious DNA fault.
-	 * Otherwise, doing clts() in process context requires disabling preemption
-	 * or some heavy lifting like kernel_fpu_begin()
-	 */
-	if (!in_atomic())
-		return 0;
-
-	if (read_cr0() & X86_CR0_TS) {
-		clts();
-		return 1;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(irq_ts_save);
-
-void irq_ts_restore(int TS_state)
-{
-	if (TS_state)
-		stts();
-}
-EXPORT_SYMBOL_GPL(irq_ts_restore);
-
-/*
  * Save the FPU state (mark it for reload if necessary):
  *
  * This only ever gets called for the current task.
@@ -200,10 +151,7 @@ void fpu__save(struct fpu *fpu)
 	trace_x86_fpu_before_save(fpu);
 	if (fpu->fpregs_active) {
 		if (!copy_fpregs_to_fpstate(fpu)) {
-			if (use_eager_fpu())
-				copy_kernel_to_fpregs(&fpu->state);
-			else
-				fpregs_deactivate(fpu);
+			copy_kernel_to_fpregs(&fpu->state);
 		}
 	}
 	trace_x86_fpu_after_save(fpu);
@@ -236,7 +184,8 @@ void fpstate_init(union fpregs_state *st
 	 * it will #GP. Make sure it is replaced after the memset().
 	 */
 	if (static_cpu_has(X86_FEATURE_XSAVES))
-		state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT;
+		state->xsave.header.xcomp_bv = XCOMP_BV_COMPACTED_FORMAT |
+					       xfeatures_mask;
 
 	if (static_cpu_has(X86_FEATURE_FXSR))
 		fpstate_init_fxstate(&state->fxsave);
@@ -247,7 +196,6 @@ EXPORT_SYMBOL_GPL(fpstate_init);
 
 int fpu__copy(struct fpu *dst_fpu, struct fpu *src_fpu)
 {
-	dst_fpu->counter = 0;
 	dst_fpu->fpregs_active = 0;
 	dst_fpu->last_cpu = -1;
 
@@ -260,8 +208,7 @@ int fpu__copy(struct fpu *dst_fpu, struc
 	 * Don't let 'init optimized' areas of the XSAVE area
 	 * leak into the child task:
 	 */
-	if (use_eager_fpu())
-		memset(&dst_fpu->state.xsave, 0, fpu_kernel_xstate_size);
+	memset(&dst_fpu->state.xsave, 0, fpu_kernel_xstate_size);
 
 	/*
 	 * Save current FPU registers directly into the child
@@ -283,10 +230,7 @@ int fpu__copy(struct fpu *dst_fpu, struc
 		memcpy(&src_fpu->state, &dst_fpu->state,
 		       fpu_kernel_xstate_size);
 
-		if (use_eager_fpu())
-			copy_kernel_to_fpregs(&src_fpu->state);
-		else
-			fpregs_deactivate(src_fpu);
+		copy_kernel_to_fpregs(&src_fpu->state);
 	}
 	preempt_enable();
 
@@ -366,7 +310,7 @@ void fpu__activate_fpstate_write(struct
 
 	if (fpu->fpstate_active) {
 		/* Invalidate any lazy state: */
-		fpu->last_cpu = -1;
+		__fpu_invalidate_fpregs_state(fpu);
 	} else {
 		fpstate_init(&fpu->state);
 		trace_x86_fpu_init_state(fpu);
@@ -409,7 +353,7 @@ void fpu__current_fpstate_write_begin(vo
 	 * ensures we will not be lazy and skip a XRSTOR in the
 	 * future.
 	 */
-	fpu->last_cpu = -1;
+	__fpu_invalidate_fpregs_state(fpu);
 }
 
 /*
@@ -459,7 +403,6 @@ void fpu__restore(struct fpu *fpu)
 	trace_x86_fpu_before_restore(fpu);
 	fpregs_activate(fpu);
 	copy_kernel_to_fpregs(&fpu->state);
-	fpu->counter++;
 	trace_x86_fpu_after_restore(fpu);
 	kernel_fpu_enable();
 }
@@ -477,7 +420,6 @@ EXPORT_SYMBOL_GPL(fpu__restore);
 void fpu__drop(struct fpu *fpu)
 {
 	preempt_disable();
-	fpu->counter = 0;
 
 	if (fpu->fpregs_active) {
 		/* Ignore delayed exceptions from user space */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/fpu/init.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/init.c
--- linux-libre-4.9-gnu/arch/x86/kernel/fpu/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,18 +10,6 @@
 #include <linux/init.h>
 
 /*
- * Initialize the TS bit in CR0 according to the style of context-switches
- * we are using:
- */
-static void fpu__init_cpu_ctx_switch(void)
-{
-	if (!boot_cpu_has(X86_FEATURE_EAGER_FPU))
-		stts();
-	else
-		clts();
-}
-
-/*
  * Initialize the registers found in all CPUs, CR0 and CR4:
  */
 static void fpu__init_cpu_generic(void)
@@ -58,7 +46,6 @@ void fpu__init_cpu(void)
 {
 	fpu__init_cpu_generic();
 	fpu__init_cpu_xstate();
-	fpu__init_cpu_ctx_switch();
 }
 
 /*
@@ -233,82 +220,16 @@ static void __init fpu__init_system_xsta
 }
 
 /*
- * FPU context switching strategies:
- *
- * Against popular belief, we don't do lazy FPU saves, due to the
- * task migration complications it brings on SMP - we only do
- * lazy FPU restores.
- *
- * 'lazy' is the traditional strategy, which is based on setting
- * CR0::TS to 1 during context-switch (instead of doing a full
- * restore of the FPU state), which causes the first FPU instruction
- * after the context switch (whenever it is executed) to fault - at
- * which point we lazily restore the FPU state into FPU registers.
- *
- * Tasks are of course under no obligation to execute FPU instructions,
- * so it can easily happen that another context-switch occurs without
- * a single FPU instruction being executed. If we eventually switch
- * back to the original task (that still owns the FPU) then we have
- * not only saved the restores along the way, but we also have the
- * FPU ready to be used for the original task.
- *
- * 'lazy' is deprecated because it's almost never a performance win
- * and it's much more complicated than 'eager'.
- *
- * 'eager' switching is by default on all CPUs, there we switch the FPU
- * state during every context switch, regardless of whether the task
- * has used FPU instructions in that time slice or not. This is done
- * because modern FPU context saving instructions are able to optimize
- * state saving and restoration in hardware: they can detect both
- * unused and untouched FPU state and optimize accordingly.
- *
- * [ Note that even in 'lazy' mode we might optimize context switches
- *   to use 'eager' restores, if we detect that a task is using the FPU
- *   frequently. See the fpu->counter logic in fpu/internal.h for that. ]
- */
-static enum { ENABLE, DISABLE } eagerfpu = ENABLE;
-
-/*
  * Find supported xfeatures based on cpu features and command-line input.
  * This must be called after fpu__init_parse_early_param() is called and
  * xfeatures_mask is enumerated.
  */
 u64 __init fpu__get_supported_xfeatures_mask(void)
 {
-	/* Support all xfeatures known to us */
-	if (eagerfpu != DISABLE)
-		return XCNTXT_MASK;
-
-	/* Warning of xfeatures being disabled for no eagerfpu mode */
-	if (xfeatures_mask & XFEATURE_MASK_EAGER) {
-		pr_err("x86/fpu: eagerfpu switching disabled, disabling the following xstate features: 0x%llx.\n",
-			xfeatures_mask & XFEATURE_MASK_EAGER);
-	}
-
-	/* Return a mask that masks out all features requiring eagerfpu mode */
-	return ~XFEATURE_MASK_EAGER;
-}
-
-/*
- * Disable features dependent on eagerfpu.
- */
-static void __init fpu__clear_eager_fpu_features(void)
-{
-	setup_clear_cpu_cap(X86_FEATURE_MPX);
+	return XCNTXT_MASK;
 }
 
-/*
- * Pick the FPU context switching strategy:
- *
- * When eagerfpu is AUTO or ENABLE, we ensure it is ENABLE if either of
- * the following is true:
- *
- * (1) the cpu has xsaveopt, as it has the optimization and doing eager
- *     FPU switching has a relatively low cost compared to a plain xsave;
- * (2) the cpu has xsave features (e.g. MPX) that depend on eager FPU
- *     switching. Should the kernel boot with noxsaveopt, we support MPX
- *     with eager FPU switching at a higher cost.
- */
+/* Legacy code to initialize eager fpu mode. */
 static void __init fpu__init_system_ctx_switch(void)
 {
 	static bool on_boot_cpu __initdata = 1;
@@ -317,17 +238,6 @@ static void __init fpu__init_system_ctx_
 	on_boot_cpu = 0;
 
 	WARN_ON_FPU(current->thread.fpu.fpstate_active);
-
-	if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE)
-		eagerfpu = ENABLE;
-
-	if (xfeatures_mask & XFEATURE_MASK_EAGER)
-		eagerfpu = ENABLE;
-
-	if (eagerfpu == ENABLE)
-		setup_force_cpu_cap(X86_FEATURE_EAGER_FPU);
-
-	printk(KERN_INFO "x86/fpu: Using '%s' FPU context switches.\n", eagerfpu == ENABLE ? "eager" : "lazy");
 }
 
 /*
@@ -336,11 +246,6 @@ static void __init fpu__init_system_ctx_
  */
 static void __init fpu__init_parse_early_param(void)
 {
-	if (cmdline_find_option_bool(boot_command_line, "eagerfpu=off")) {
-		eagerfpu = DISABLE;
-		fpu__clear_eager_fpu_features();
-	}
-
 	if (cmdline_find_option_bool(boot_command_line, "no387"))
 		setup_clear_cpu_cap(X86_FEATURE_FPU);
 
@@ -375,14 +280,6 @@ void __init fpu__init_system(struct cpui
 	 */
 	fpu__init_cpu();
 
-	/*
-	 * But don't leave CR0::TS set yet, as some of the FPU setup
-	 * methods depend on being able to execute FPU instructions
-	 * that will fault on a set TS, such as the FXSAVE in
-	 * fpu__init_system_mxcsr().
-	 */
-	clts();
-
 	fpu__init_system_generic();
 	fpu__init_system_xstate_size_legacy();
 	fpu__init_system_xstate();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/fpu/signal.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/signal.c
--- linux-libre-4.9-gnu/arch/x86/kernel/fpu/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -340,11 +340,9 @@ static int __fpu__restore_sig(void __use
 		}
 
 		fpu->fpstate_active = 1;
-		if (use_eager_fpu()) {
-			preempt_disable();
-			fpu__restore(fpu);
-			preempt_enable();
-		}
+		preempt_disable();
+		fpu__restore(fpu);
+		preempt_enable();
 
 		return err;
 	} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/fpu/xstate.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/xstate.c
--- linux-libre-4.9-gnu/arch/x86/kernel/fpu/xstate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/fpu/xstate.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,7 @@ void fpu__xstate_clear_all_cpu_caps(void
 	setup_clear_cpu_cap(X86_FEATURE_AVX);
 	setup_clear_cpu_cap(X86_FEATURE_AVX2);
 	setup_clear_cpu_cap(X86_FEATURE_AVX512F);
+	setup_clear_cpu_cap(X86_FEATURE_AVX512IFMA);
 	setup_clear_cpu_cap(X86_FEATURE_AVX512PF);
 	setup_clear_cpu_cap(X86_FEATURE_AVX512ER);
 	setup_clear_cpu_cap(X86_FEATURE_AVX512CD);
@@ -73,6 +74,7 @@ void fpu__xstate_clear_all_cpu_caps(void
 	setup_clear_cpu_cap(X86_FEATURE_AVX512VL);
 	setup_clear_cpu_cap(X86_FEATURE_MPX);
 	setup_clear_cpu_cap(X86_FEATURE_XGETBV1);
+	setup_clear_cpu_cap(X86_FEATURE_AVX512VBMI);
 	setup_clear_cpu_cap(X86_FEATURE_PKU);
 	setup_clear_cpu_cap(X86_FEATURE_AVX512_4VNNIW);
 	setup_clear_cpu_cap(X86_FEATURE_AVX512_4FMAPS);
@@ -890,15 +892,6 @@ int arch_set_user_pkey_access(struct tas
 	 */
 	if (!boot_cpu_has(X86_FEATURE_OSPKE))
 		return -EINVAL;
-	/*
-	 * For most XSAVE components, this would be an arduous task:
-	 * brining fpstate up to date with fpregs, updating fpstate,
-	 * then re-populating fpregs.  But, for components that are
-	 * never lazily managed, we can just access the fpregs
-	 * directly.  PKRU is never managed lazily, so we can just
-	 * manipulate it directly.  Make sure it stays that way.
-	 */
-	WARN_ON_ONCE(!use_eager_fpu());
 
 	/* Set the bits we need in PKRU:  */
 	if (init_val & PKEY_DISABLE_ACCESS)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/head_32.S linux-libre-4.10-rc8-gnu/arch/x86/kernel/head_32.S
--- linux-libre-4.9-gnu/arch/x86/kernel/head_32.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/head_32.S	2017-02-12 16:03:20.000000000 -0500
@@ -63,6 +63,8 @@
 #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #endif
 
+#define SIZEOF_PTREGS 17*4
+
 /*
  * Number of possible pages in the lowmem region.
  *
@@ -248,19 +250,19 @@ page_pde_offset = (__PAGE_OFFSET >> 20);
 #ifdef CONFIG_PARAVIRT
 	/* This is can only trip for a broken bootloader... */
 	cmpw $0x207, pa(boot_params + BP_version)
-	jb default_entry
+	jb .Ldefault_entry
 
 	/* Paravirt-compatible boot parameters.  Look to see what architecture
 		we're booting under. */
 	movl pa(boot_params + BP_hardware_subarch), %eax
 	cmpl $num_subarch_entries, %eax
-	jae bad_subarch
+	jae .Lbad_subarch
 
 	movl pa(subarch_entries)(,%eax,4), %eax
 	subl $__PAGE_OFFSET, %eax
 	jmp *%eax
 
-bad_subarch:
+.Lbad_subarch:
 WEAK(lguest_entry)
 WEAK(xen_entry)
 	/* Unknown implementation; there's really
@@ -270,14 +272,14 @@ WEAK(xen_entry)
 	__INITDATA
 
 subarch_entries:
-	.long default_entry		/* normal x86/PC */
+	.long .Ldefault_entry		/* normal x86/PC */
 	.long lguest_entry		/* lguest hypervisor */
 	.long xen_entry			/* Xen hypervisor */
-	.long default_entry		/* Moorestown MID */
+	.long .Ldefault_entry		/* Moorestown MID */
 num_subarch_entries = (. - subarch_entries) / 4
 .previous
 #else
-	jmp default_entry
+	jmp .Ldefault_entry
 #endif /* CONFIG_PARAVIRT */
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -289,7 +291,8 @@ num_subarch_entries = (. - subarch_entri
 ENTRY(start_cpu0)
 	movl initial_stack, %ecx
 	movl %ecx, %esp
-	jmp  *(initial_code)
+	call *(initial_code)
+1:	jmp 1b
 ENDPROC(start_cpu0)
 #endif
 
@@ -317,7 +320,7 @@ ENTRY(startup_32_smp)
 	call load_ucode_ap
 #endif
 
-default_entry:
+.Ldefault_entry:
 #define CR0_STATE	(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
 			 X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
 			 X86_CR0_PG)
@@ -347,7 +350,7 @@ default_entry:
 	pushfl
 	popl %eax			# get EFLAGS
 	testl $X86_EFLAGS_ID,%eax	# did EFLAGS.ID remained set?
-	jz enable_paging		# hw disallowed setting of ID bit
+	jz .Lenable_paging		# hw disallowed setting of ID bit
 					# which means no CPUID and no CR4
 
 	xorl %eax,%eax
@@ -357,13 +360,13 @@ default_entry:
 	movl $1,%eax
 	cpuid
 	andl $~1,%edx			# Ignore CPUID.FPU
-	jz enable_paging		# No flags or only CPUID.FPU = no CR4
+	jz .Lenable_paging		# No flags or only CPUID.FPU = no CR4
 
 	movl pa(mmu_cr4_features),%eax
 	movl %eax,%cr4
 
 	testb $X86_CR4_PAE, %al		# check if PAE is enabled
-	jz enable_paging
+	jz .Lenable_paging
 
 	/* Check if extended functions are implemented */
 	movl $0x80000000, %eax
@@ -371,7 +374,7 @@ default_entry:
 	/* Value must be in the range 0x80000001 to 0x8000ffff */
 	subl $0x80000001, %eax
 	cmpl $(0x8000ffff-0x80000001), %eax
-	ja enable_paging
+	ja .Lenable_paging
 
 	/* Clear bogus XD_DISABLE bits */
 	call verify_cpu
@@ -380,7 +383,7 @@ default_entry:
 	cpuid
 	/* Execute Disable bit supported? */
 	btl $(X86_FEATURE_NX & 31), %edx
-	jnc enable_paging
+	jnc .Lenable_paging
 
 	/* Setup EFER (Extended Feature Enable Register) */
 	movl $MSR_EFER, %ecx
@@ -390,7 +393,7 @@ default_entry:
 	/* Make changes effective */
 	wrmsr
 
-enable_paging:
+.Lenable_paging:
 
 /*
  * Enable paging
@@ -419,7 +422,7 @@ enable_paging:
  */
 	movb $4,X86			# at least 486
 	cmpl $-1,X86_CPUID
-	je is486
+	je .Lis486
 
 	/* get vendor info */
 	xorl %eax,%eax			# call CPUID with 0 -> return vendor ID
@@ -430,7 +433,7 @@ enable_paging:
 	movl %ecx,X86_VENDOR_ID+8	# last 4 chars
 
 	orl %eax,%eax			# do we have processor info as well?
-	je is486
+	je .Lis486
 
 	movl $1,%eax		# Use the CPUID instruction to get CPU type
 	cpuid
@@ -444,7 +447,7 @@ enable_paging:
 	movb %cl,X86_MASK
 	movl %edx,X86_CAPABILITY
 
-is486:
+.Lis486:
 	movl $0x50022,%ecx	# set AM, WP, NE and MP
 	movl %cr0,%eax
 	andl $0x80000011,%eax	# Save PG,PE,ET
@@ -470,8 +473,9 @@ is486:
 	xorl %eax,%eax			# Clear LDT
 	lldt %ax
 
-	pushl $0		# fake return address for unwinder
-	jmp *(initial_code)
+	call *(initial_code)
+1:	jmp 1b
+ENDPROC(startup_32_smp)
 
 #include "verify_cpu.S"
 
@@ -709,7 +713,12 @@ ENTRY(initial_page_table)
 .data
 .balign 4
 ENTRY(initial_stack)
-	.long init_thread_union+THREAD_SIZE
+	/*
+	 * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+	 * unwinder reliably detect the end of the stack.
+	 */
+	.long init_thread_union + THREAD_SIZE - SIZEOF_PTREGS - \
+	      TOP_OF_KERNEL_STACK_PADDING;
 
 __INITRODATA
 int_msg:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/head_64.S linux-libre-4.10-rc8-gnu/arch/x86/kernel/head_64.S
--- linux-libre-4.9-gnu/arch/x86/kernel/head_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/head_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -66,13 +66,8 @@ startup_64:
 	 * tables and then reload them.
 	 */
 
-	/*
-	 * Setup stack for verify_cpu(). "-8" because initial_stack is defined
-	 * this way, see below. Our best guess is a NULL ptr for stack
-	 * termination heuristics and we don't want to break anything which
-	 * might depend on it (kgdb, ...).
-	 */
-	leaq	(__end_init_task - 8)(%rip), %rsp
+	/* Set up the stack for verify_cpu(), similar to initial_stack below */
+	leaq	(__end_init_task - SIZEOF_PTREGS)(%rip), %rsp
 
 	/* Sanitize CPU configuration */
 	call verify_cpu
@@ -117,20 +112,20 @@ startup_64:
 	movq	%rdi, %rax
 	shrq	$PGDIR_SHIFT, %rax
 
-	leaq	(4096 + _KERNPG_TABLE)(%rbx), %rdx
+	leaq	(PAGE_SIZE + _KERNPG_TABLE)(%rbx), %rdx
 	movq	%rdx, 0(%rbx,%rax,8)
 	movq	%rdx, 8(%rbx,%rax,8)
 
-	addq	$4096, %rdx
+	addq	$PAGE_SIZE, %rdx
 	movq	%rdi, %rax
 	shrq	$PUD_SHIFT, %rax
 	andl	$(PTRS_PER_PUD-1), %eax
-	movq	%rdx, 4096(%rbx,%rax,8)
+	movq	%rdx, PAGE_SIZE(%rbx,%rax,8)
 	incl	%eax
 	andl	$(PTRS_PER_PUD-1), %eax
-	movq	%rdx, 4096(%rbx,%rax,8)
+	movq	%rdx, PAGE_SIZE(%rbx,%rax,8)
 
-	addq	$8192, %rbx
+	addq	$PAGE_SIZE * 2, %rbx
 	movq	%rdi, %rax
 	shrq	$PMD_SHIFT, %rdi
 	addq	$(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL), %rax
@@ -147,6 +142,9 @@ startup_64:
 	decl	%ecx
 	jnz	1b
 
+	test %rbp, %rbp
+	jz .Lskip_fixup
+
 	/*
 	 * Fixup the kernel text+data virtual addresses. Note that
 	 * we might write invalid pmds, when the kernel is relocated
@@ -154,9 +152,9 @@ startup_64:
 	 * beyond _end.
 	 */
 	leaq	level2_kernel_pgt(%rip), %rdi
-	leaq	4096(%rdi), %r8
+	leaq	PAGE_SIZE(%rdi), %r8
 	/* See if it is a valid page table entry */
-1:	testb	$1, 0(%rdi)
+1:	testb	$_PAGE_PRESENT, 0(%rdi)
 	jz	2f
 	addq	%rbp, 0(%rdi)
 	/* Go to the next page */
@@ -167,6 +165,7 @@ startup_64:
 	/* Fixup phys_base */
 	addq	%rbp, phys_base(%rip)
 
+.Lskip_fixup:
 	movq	$(early_level4_pgt - __START_KERNEL_map), %rax
 	jmp 1f
 ENTRY(secondary_startup_64)
@@ -265,13 +264,17 @@ ENTRY(secondary_startup_64)
 	movl	$MSR_GS_BASE,%ecx
 	movl	initial_gs(%rip),%eax
 	movl	initial_gs+4(%rip),%edx
-	wrmsr	
+	wrmsr
 
 	/* rsi is pointer to real mode structure with interesting info.
 	   pass it to C */
 	movq	%rsi, %rdi
-	
-	/* Finally jump to run C code and to be on real kernel address
+	jmp	start_cpu
+ENDPROC(secondary_startup_64)
+
+ENTRY(start_cpu)
+	/*
+	 * Jump to run C code and to be on a real kernel address.
 	 * Since we are running on identity-mapped space we have to jump
 	 * to the full 64bit address, this is only possible as indirect
 	 * jump.  In addition we need to ensure %cs is set so we make this
@@ -295,12 +298,14 @@ ENTRY(secondary_startup_64)
 	 *	REX.W + FF /5 JMP m16:64 Jump far, absolute indirect,
 	 *		address given in m16:64.
 	 */
-	movq	initial_code(%rip),%rax
-	pushq	$0		# fake return address to stop unwinder
+	pushq	$.Lafter_lret	# put return address on stack for unwinder
+	xorq	%rbp, %rbp	# clear frame pointer
+	movq	initial_code(%rip), %rax
 	pushq	$__KERNEL_CS	# set correct cs
 	pushq	%rax		# target address in negative space
 	lretq
-ENDPROC(secondary_startup_64)
+.Lafter_lret:
+ENDPROC(start_cpu)
 
 #include "verify_cpu.S"
 
@@ -308,15 +313,11 @@ ENDPROC(secondary_startup_64)
 /*
  * Boot CPU0 entry point. It's called from play_dead(). Everything has been set
  * up already except stack. We just set up stack here. Then call
- * start_secondary().
+ * start_secondary() via start_cpu().
  */
 ENTRY(start_cpu0)
-	movq initial_stack(%rip),%rsp
-	movq	initial_code(%rip),%rax
-	pushq	$0		# fake return address to stop unwinder
-	pushq	$__KERNEL_CS	# set correct cs
-	pushq	%rax		# target address in negative space
-	lretq
+	movq	initial_stack(%rip), %rsp
+	jmp	start_cpu
 ENDPROC(start_cpu0)
 #endif
 
@@ -328,7 +329,11 @@ ENDPROC(start_cpu0)
 	GLOBAL(initial_gs)
 	.quad	INIT_PER_CPU_VAR(irq_stack_union)
 	GLOBAL(initial_stack)
-	.quad  init_thread_union+THREAD_SIZE-8
+	/*
+	 * The SIZEOF_PTREGS gap is a convention which helps the in-kernel
+	 * unwinder reliably detect the end of the stack.
+	 */
+	.quad  init_thread_union + THREAD_SIZE - SIZEOF_PTREGS
 	__FINITDATA
 
 bad_address:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/hpet.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/hpet.c
--- linux-libre-4.9-gnu/arch/x86/kernel/hpet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/hpet.c	2017-02-12 16:03:20.000000000 -0500
@@ -352,6 +352,7 @@ static int hpet_resume(struct clock_even
 	} else {
 		struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
 
+		irq_domain_deactivate_irq(irq_get_irq_data(hdev->irq));
 		irq_domain_activate_irq(irq_get_irq_data(hdev->irq));
 		disable_irq(hdev->irq);
 		irq_set_affinity(hdev->irq, cpumask_of(hdev->cpu));
@@ -791,7 +792,7 @@ static union hpet_lock hpet __cacheline_
 	{ .lock = __ARCH_SPIN_LOCK_UNLOCKED, },
 };
 
-static cycle_t read_hpet(struct clocksource *cs)
+static u64 read_hpet(struct clocksource *cs)
 {
 	unsigned long flags;
 	union hpet_lock old, new;
@@ -802,7 +803,7 @@ static cycle_t read_hpet(struct clocksou
 	 * Read HPET directly if in NMI.
 	 */
 	if (in_nmi())
-		return (cycle_t)hpet_readl(HPET_COUNTER);
+		return (u64)hpet_readl(HPET_COUNTER);
 
 	/*
 	 * Read the current state of the lock and HPET value atomically.
@@ -821,7 +822,7 @@ static cycle_t read_hpet(struct clocksou
 		WRITE_ONCE(hpet.value, new.value);
 		arch_spin_unlock(&hpet.lock);
 		local_irq_restore(flags);
-		return (cycle_t)new.value;
+		return (u64)new.value;
 	}
 	local_irq_restore(flags);
 
@@ -843,15 +844,15 @@ contended:
 		new.lockval = READ_ONCE(hpet.lockval);
 	} while ((new.value == old.value) && arch_spin_is_locked(&new.lock));
 
-	return (cycle_t)new.value;
+	return (u64)new.value;
 }
 #else
 /*
  * For UP or 32-bit.
  */
-static cycle_t read_hpet(struct clocksource *cs)
+static u64 read_hpet(struct clocksource *cs)
 {
-	return (cycle_t)hpet_readl(HPET_COUNTER);
+	return (u64)hpet_readl(HPET_COUNTER);
 }
 #endif
 
@@ -867,7 +868,7 @@ static struct clocksource clocksource_hp
 static int hpet_clocksource_register(void)
 {
 	u64 start, now;
-	cycle_t t1;
+	u64 t1;
 
 	/* Start the counter */
 	hpet_restart_counter();
@@ -1051,11 +1052,11 @@ static __init int hpet_late_init(void)
 		return 0;
 
 	/* This notifier should be called after workqueue is ready */
-	ret = cpuhp_setup_state(CPUHP_AP_X86_HPET_ONLINE, "AP_X86_HPET_ONLINE",
+	ret = cpuhp_setup_state(CPUHP_AP_X86_HPET_ONLINE, "x86/hpet:online",
 				hpet_cpuhp_online, NULL);
 	if (ret)
 		return ret;
-	ret = cpuhp_setup_state(CPUHP_X86_HPET_DEAD, "X86_HPET_DEAD", NULL,
+	ret = cpuhp_setup_state(CPUHP_X86_HPET_DEAD, "x86/hpet:dead", NULL,
 				hpet_cpuhp_dead);
 	if (ret)
 		goto err_cpuhp;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/irq_64.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/irq_64.c
--- linux-libre-4.9-gnu/arch/x86/kernel/irq_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/irq_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,6 @@
 #include <linux/uaccess.h>
 #include <linux/smp.h>
 #include <asm/io_apic.h>
-#include <asm/idle.h>
 #include <asm/apic.h>
 
 int sysctl_panic_on_stackoverflow;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/irq.c
--- linux-libre-4.9-gnu/arch/x86/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,6 @@
 #include <asm/apic.h>
 #include <asm/io_apic.h>
 #include <asm/irq.h>
-#include <asm/idle.h>
 #include <asm/mce.h>
 #include <asm/hw_irq.h>
 #include <asm/desc.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/itmt.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/itmt.c
--- linux-libre-4.9-gnu/arch/x86/kernel/itmt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/itmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,215 @@
+/*
+ * itmt.c: Support Intel Turbo Boost Max Technology 3.0
+ *
+ * (C) Copyright 2016 Intel Corporation
+ * Author: Tim Chen <tim.c.chen@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
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * On platforms supporting Intel Turbo Boost Max Technology 3.0, (ITMT),
+ * the maximum turbo frequencies of some cores in a CPU package may be
+ * higher than for the other cores in the same package.  In that case,
+ * better performance can be achieved by making the scheduler prefer
+ * to run tasks on the CPUs with higher max turbo frequencies.
+ *
+ * This file provides functions and data structures for enabling the
+ * scheduler to favor scheduling on cores can be boosted to a higher
+ * frequency under ITMT.
+ */
+
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/cpuset.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/sysctl.h>
+#include <linux/nodemask.h>
+
+static DEFINE_MUTEX(itmt_update_mutex);
+DEFINE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
+
+/* Boolean to track if system has ITMT capabilities */
+static bool __read_mostly sched_itmt_capable;
+
+/*
+ * Boolean to control whether we want to move processes to cpu capable
+ * of higher turbo frequency for cpus supporting Intel Turbo Boost Max
+ * Technology 3.0.
+ *
+ * It can be set via /proc/sys/kernel/sched_itmt_enabled
+ */
+unsigned int __read_mostly sysctl_sched_itmt_enabled;
+
+static int sched_itmt_update_handler(struct ctl_table *table, int write,
+				     void __user *buffer, size_t *lenp,
+				     loff_t *ppos)
+{
+	unsigned int old_sysctl;
+	int ret;
+
+	mutex_lock(&itmt_update_mutex);
+
+	if (!sched_itmt_capable) {
+		mutex_unlock(&itmt_update_mutex);
+		return -EINVAL;
+	}
+
+	old_sysctl = sysctl_sched_itmt_enabled;
+	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+	if (!ret && write && old_sysctl != sysctl_sched_itmt_enabled) {
+		x86_topology_update = true;
+		rebuild_sched_domains();
+	}
+
+	mutex_unlock(&itmt_update_mutex);
+
+	return ret;
+}
+
+static unsigned int zero;
+static unsigned int one = 1;
+static struct ctl_table itmt_kern_table[] = {
+	{
+		.procname	= "sched_itmt_enabled",
+		.data		= &sysctl_sched_itmt_enabled,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= sched_itmt_update_handler,
+		.extra1		= &zero,
+		.extra2		= &one,
+	},
+	{}
+};
+
+static struct ctl_table itmt_root_table[] = {
+	{
+		.procname	= "kernel",
+		.mode		= 0555,
+		.child		= itmt_kern_table,
+	},
+	{}
+};
+
+static struct ctl_table_header *itmt_sysctl_header;
+
+/**
+ * sched_set_itmt_support() - Indicate platform supports ITMT
+ *
+ * This function is used by the OS to indicate to scheduler that the platform
+ * is capable of supporting the ITMT feature.
+ *
+ * The current scheme has the pstate driver detects if the system
+ * is ITMT capable and call sched_set_itmt_support.
+ *
+ * This must be done only after sched_set_itmt_core_prio
+ * has been called to set the cpus' priorities.
+ * It must not be called with cpu hot plug lock
+ * held as we need to acquire the lock to rebuild sched domains
+ * later.
+ *
+ * Return: 0 on success
+ */
+int sched_set_itmt_support(void)
+{
+	mutex_lock(&itmt_update_mutex);
+
+	if (sched_itmt_capable) {
+		mutex_unlock(&itmt_update_mutex);
+		return 0;
+	}
+
+	itmt_sysctl_header = register_sysctl_table(itmt_root_table);
+	if (!itmt_sysctl_header) {
+		mutex_unlock(&itmt_update_mutex);
+		return -ENOMEM;
+	}
+
+	sched_itmt_capable = true;
+
+	sysctl_sched_itmt_enabled = 1;
+
+	if (sysctl_sched_itmt_enabled) {
+		x86_topology_update = true;
+		rebuild_sched_domains();
+	}
+
+	mutex_unlock(&itmt_update_mutex);
+
+	return 0;
+}
+
+/**
+ * sched_clear_itmt_support() - Revoke platform's support of ITMT
+ *
+ * This function is used by the OS to indicate that it has
+ * revoked the platform's support of ITMT feature.
+ *
+ * It must not be called with cpu hot plug lock
+ * held as we need to acquire the lock to rebuild sched domains
+ * later.
+ */
+void sched_clear_itmt_support(void)
+{
+	mutex_lock(&itmt_update_mutex);
+
+	if (!sched_itmt_capable) {
+		mutex_unlock(&itmt_update_mutex);
+		return;
+	}
+	sched_itmt_capable = false;
+
+	if (itmt_sysctl_header) {
+		unregister_sysctl_table(itmt_sysctl_header);
+		itmt_sysctl_header = NULL;
+	}
+
+	if (sysctl_sched_itmt_enabled) {
+		/* disable sched_itmt if we are no longer ITMT capable */
+		sysctl_sched_itmt_enabled = 0;
+		x86_topology_update = true;
+		rebuild_sched_domains();
+	}
+
+	mutex_unlock(&itmt_update_mutex);
+}
+
+int arch_asym_cpu_priority(int cpu)
+{
+	return per_cpu(sched_core_priority, cpu);
+}
+
+/**
+ * sched_set_itmt_core_prio() - Set CPU priority based on ITMT
+ * @prio:	Priority of cpu core
+ * @core_cpu:	The cpu number associated with the core
+ *
+ * The pstate driver will find out the max boost frequency
+ * and call this function to set a priority proportional
+ * to the max boost frequency. CPU with higher boost
+ * frequency will receive higher priority.
+ *
+ * No need to rebuild sched domain after updating
+ * the CPU priorities. The sched domains have no
+ * dependency on CPU priorities.
+ */
+void sched_set_itmt_core_prio(int prio, int core_cpu)
+{
+	int cpu, i = 1;
+
+	for_each_cpu(cpu, topology_sibling_cpumask(core_cpu)) {
+		int smt_prio;
+
+		/*
+		 * Ensure that the siblings are moved to the end
+		 * of the priority chain and only used when
+		 * all other high priority cpus are out of capacity.
+		 */
+		smt_prio = prio * smp_num_siblings / i;
+		per_cpu(sched_core_priority, cpu) = smt_prio;
+		i++;
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/kexec-bzimage64.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/kexec-bzimage64.c
--- linux-libre-4.9-gnu/arch/x86/kernel/kexec-bzimage64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/kexec-bzimage64.c	2017-02-12 16:03:20.000000000 -0500
@@ -331,17 +331,17 @@ static void *bzImage64_load(struct kimag
 
 	struct setup_header *header;
 	int setup_sects, kern16_size, ret = 0;
-	unsigned long setup_header_size, params_cmdline_sz, params_misc_sz;
+	unsigned long setup_header_size, params_cmdline_sz;
 	struct boot_params *params;
 	unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr;
 	unsigned long purgatory_load_addr;
-	unsigned long kernel_bufsz, kernel_memsz, kernel_align;
-	char *kernel_buf;
 	struct bzimage64_data *ldata;
 	struct kexec_entry64_regs regs64;
 	void *stack;
 	unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr);
 	unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
+	struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX,
+				  .top_down = true };
 
 	header = (struct setup_header *)(kernel + setup_hdr_offset);
 	setup_sects = header->setup_sects;
@@ -402,11 +402,11 @@ static void *bzImage64_load(struct kimag
 	params_cmdline_sz = sizeof(struct boot_params) + cmdline_len +
 				MAX_ELFCOREHDR_STR_LEN;
 	params_cmdline_sz = ALIGN(params_cmdline_sz, 16);
-	params_misc_sz = params_cmdline_sz + efi_map_sz +
+	kbuf.bufsz = params_cmdline_sz + efi_map_sz +
 				sizeof(struct setup_data) +
 				sizeof(struct efi_setup_data);
 
-	params = kzalloc(params_misc_sz, GFP_KERNEL);
+	params = kzalloc(kbuf.bufsz, GFP_KERNEL);
 	if (!params)
 		return ERR_PTR(-ENOMEM);
 	efi_map_offset = params_cmdline_sz;
@@ -418,37 +418,41 @@ static void *bzImage64_load(struct kimag
 	/* Is there a limit on setup header size? */
 	memcpy(&params->hdr, (kernel + setup_hdr_offset), setup_header_size);
 
-	ret = kexec_add_buffer(image, (char *)params, params_misc_sz,
-			       params_misc_sz, 16, MIN_BOOTPARAM_ADDR,
-			       ULONG_MAX, 1, &bootparam_load_addr);
+	kbuf.buffer = params;
+	kbuf.memsz = kbuf.bufsz;
+	kbuf.buf_align = 16;
+	kbuf.buf_min = MIN_BOOTPARAM_ADDR;
+	ret = kexec_add_buffer(&kbuf);
 	if (ret)
 		goto out_free_params;
+	bootparam_load_addr = kbuf.mem;
 	pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
-		 bootparam_load_addr, params_misc_sz, params_misc_sz);
+		 bootparam_load_addr, kbuf.bufsz, kbuf.bufsz);
 
 	/* Load kernel */
-	kernel_buf = kernel + kern16_size;
-	kernel_bufsz =  kernel_len - kern16_size;
-	kernel_memsz = PAGE_ALIGN(header->init_size);
-	kernel_align = header->kernel_alignment;
-
-	ret = kexec_add_buffer(image, kernel_buf,
-			       kernel_bufsz, kernel_memsz, kernel_align,
-			       MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1,
-			       &kernel_load_addr);
+	kbuf.buffer = kernel + kern16_size;
+	kbuf.bufsz =  kernel_len - kern16_size;
+	kbuf.memsz = PAGE_ALIGN(header->init_size);
+	kbuf.buf_align = header->kernel_alignment;
+	kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
+	ret = kexec_add_buffer(&kbuf);
 	if (ret)
 		goto out_free_params;
+	kernel_load_addr = kbuf.mem;
 
 	pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
-		 kernel_load_addr, kernel_memsz, kernel_memsz);
+		 kernel_load_addr, kbuf.bufsz, kbuf.memsz);
 
 	/* Load initrd high */
 	if (initrd) {
-		ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len,
-				       PAGE_SIZE, MIN_INITRD_LOAD_ADDR,
-				       ULONG_MAX, 1, &initrd_load_addr);
+		kbuf.buffer = initrd;
+		kbuf.bufsz = kbuf.memsz = initrd_len;
+		kbuf.buf_align = PAGE_SIZE;
+		kbuf.buf_min = MIN_INITRD_LOAD_ADDR;
+		ret = kexec_add_buffer(&kbuf);
 		if (ret)
 			goto out_free_params;
+		initrd_load_addr = kbuf.mem;
 
 		pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
 				initrd_load_addr, initrd_len, initrd_len);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/kprobes/core.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/kprobes/core.c
--- linux-libre-4.9-gnu/arch/x86/kernel/kprobes/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/kprobes/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@
 #include <asm/cacheflush.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/alternative.h>
 #include <asm/insn.h>
 #include <asm/debugreg.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/kprobes/opt.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/kprobes/opt.c
--- linux-libre-4.9-gnu/arch/x86/kernel/kprobes/opt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/kprobes/opt.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <asm/cacheflush.h>
 #include <asm/desc.h>
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/alternative.h>
 #include <asm/insn.h>
 #include <asm/debugreg.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/kvm.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/kvm.c
--- linux-libre-4.9-gnu/arch/x86/kernel/kvm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/kvm.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,6 @@
 #include <asm/traps.h>
 #include <asm/desc.h>
 #include <asm/tlbflush.h>
-#include <asm/idle.h>
 #include <asm/apic.h>
 #include <asm/apicdef.h>
 #include <asm/hypervisor.h>
@@ -267,13 +266,11 @@ do_async_page_fault(struct pt_regs *regs
 	case KVM_PV_REASON_PAGE_NOT_PRESENT:
 		/* page is swapped out by the host. */
 		prev_state = exception_enter();
-		exit_idle();
 		kvm_async_pf_task_wait((u32)read_cr2());
 		exception_exit(prev_state);
 		break;
 	case KVM_PV_REASON_PAGE_READY:
 		rcu_irq_enter();
-		exit_idle();
 		kvm_async_pf_task_wake((u32)read_cr2());
 		rcu_irq_exit();
 		break;
@@ -308,7 +305,7 @@ static void kvm_register_steal_time(void
 
 static DEFINE_PER_CPU(unsigned long, kvm_apic_eoi) = KVM_PV_EOI_DISABLED;
 
-static void kvm_guest_apic_eoi_write(u32 reg, u32 val)
+static notrace void kvm_guest_apic_eoi_write(u32 reg, u32 val)
 {
 	/**
 	 * This relies on __test_and_clear_bit to modify the memory
@@ -319,7 +316,7 @@ static void kvm_guest_apic_eoi_write(u32
 	 */
 	if (__test_and_clear_bit(KVM_PV_EOI_BIT, this_cpu_ptr(&kvm_apic_eoi)))
 		return;
-	apic_write(APIC_EOI, APIC_EOI_ACK);
+	apic->native_eoi_write(APIC_EOI, APIC_EOI_ACK);
 }
 
 static void kvm_guest_cpu_init(void)
@@ -592,6 +589,14 @@ out:
 	local_irq_restore(flags);
 }
 
+__visible bool __kvm_vcpu_is_preempted(int cpu)
+{
+	struct kvm_steal_time *src = &per_cpu(steal_time, cpu);
+
+	return !!src->preempted;
+}
+PV_CALLEE_SAVE_REGS_THUNK(__kvm_vcpu_is_preempted);
+
 /*
  * Setup pv_lock_ops to exploit KVM_FEATURE_PV_UNHALT if present.
  */
@@ -608,6 +613,11 @@ void __init kvm_spinlock_init(void)
 	pv_lock_ops.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock);
 	pv_lock_ops.wait = kvm_wait;
 	pv_lock_ops.kick = kvm_kick_cpu;
+
+	if (kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
+		pv_lock_ops.vcpu_is_preempted =
+			PV_CALLEE_SAVE(__kvm_vcpu_is_preempted);
+	}
 }
 
 static __init int kvm_spinlock_init_jump(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/kvmclock.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/kvmclock.c
--- linux-libre-4.9-gnu/arch/x86/kernel/kvmclock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/kvmclock.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 static int kvmclock __ro_after_init = 1;
 static int msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
 static int msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
-static cycle_t kvm_sched_clock_offset;
+static u64 kvm_sched_clock_offset;
 
 static int parse_no_kvmclock(char *arg)
 {
@@ -79,10 +79,10 @@ static int kvm_set_wallclock(const struc
 	return -1;
 }
 
-static cycle_t kvm_clock_read(void)
+static u64 kvm_clock_read(void)
 {
 	struct pvclock_vcpu_time_info *src;
-	cycle_t ret;
+	u64 ret;
 	int cpu;
 
 	preempt_disable_notrace();
@@ -93,12 +93,12 @@ static cycle_t kvm_clock_read(void)
 	return ret;
 }
 
-static cycle_t kvm_clock_get_cycles(struct clocksource *cs)
+static u64 kvm_clock_get_cycles(struct clocksource *cs)
 {
 	return kvm_clock_read();
 }
 
-static cycle_t kvm_sched_clock_read(void)
+static u64 kvm_sched_clock_read(void)
 {
 	return kvm_clock_read() - kvm_sched_clock_offset;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/ldt.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/ldt.c
--- linux-libre-4.9-gnu/arch/x86/kernel/ldt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/ldt.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,10 +34,10 @@ static void flush_ldt(void *current_mm)
 }
 
 /* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */
-static struct ldt_struct *alloc_ldt_struct(int size)
+static struct ldt_struct *alloc_ldt_struct(unsigned int size)
 {
 	struct ldt_struct *new_ldt;
-	int alloc_size;
+	unsigned int alloc_size;
 
 	if (size > LDT_ENTRIES)
 		return NULL;
@@ -93,7 +93,7 @@ static void free_ldt_struct(struct ldt_s
 
 	paravirt_free_ldt(ldt->entries, ldt->size);
 	if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
-		vfree(ldt->entries);
+		vfree_atomic(ldt->entries);
 	else
 		free_page((unsigned long)ldt->entries);
 	kfree(ldt);
@@ -207,11 +207,11 @@ static int read_default_ldt(void __user
 static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
 {
 	struct mm_struct *mm = current->mm;
+	struct ldt_struct *new_ldt, *old_ldt;
+	unsigned int oldsize, newsize;
+	struct user_desc ldt_info;
 	struct desc_struct ldt;
 	int error;
-	struct user_desc ldt_info;
-	int oldsize, newsize;
-	struct ldt_struct *new_ldt, *old_ldt;
 
 	error = -EINVAL;
 	if (bytecount != sizeof(ldt_info))
@@ -249,7 +249,7 @@ static int write_ldt(void __user *ptr, u
 
 	old_ldt = mm->context.ldt;
 	oldsize = old_ldt ? old_ldt->size : 0;
-	newsize = max((int)(ldt_info.entry_number + 1), oldsize);
+	newsize = max(ldt_info.entry_number + 1, oldsize);
 
 	error = -ENOMEM;
 	new_ldt = alloc_ldt_struct(newsize);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/machine_kexec_64.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/machine_kexec_64.c
--- linux-libre-4.9-gnu/arch/x86/kernel/machine_kexec_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/machine_kexec_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -328,7 +328,7 @@ void machine_kexec(struct kimage *image)
 
 void arch_crash_save_vmcoreinfo(void)
 {
-	VMCOREINFO_SYMBOL(phys_base);
+	VMCOREINFO_NUMBER(phys_base);
 	VMCOREINFO_SYMBOL(init_level4_pgt);
 
 #ifdef CONFIG_NUMA
@@ -337,9 +337,7 @@ void arch_crash_save_vmcoreinfo(void)
 #endif
 	vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
 			      kaslr_offset());
-	VMCOREINFO_PAGE_OFFSET(PAGE_OFFSET);
-	VMCOREINFO_VMALLOC_START(VMALLOC_START);
-	VMCOREINFO_VMEMMAP_START(VMEMMAP_START);
+	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
 }
 
 /* arch-dependent functionality related to kexec file-based syscall */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/Makefile linux-libre-4.10-rc8-gnu/arch/x86/kernel/Makefile
--- linux-libre-4.9-gnu/arch/x86/kernel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,7 @@ apm-y				:= apm_32.o
 obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_SMP)		+= smpboot.o
-obj-$(CONFIG_SMP)		+= tsc_sync.o
+obj-$(CONFIG_X86_TSC)		+= tsc_sync.o
 obj-$(CONFIG_SMP)		+= setup_percpu.o
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-y				+= apic/
@@ -123,6 +123,7 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
+obj-$(CONFIG_SCHED_MC_PRIO)		+= itmt.o
 
 ifdef CONFIG_FRAME_POINTER
 obj-y					+= unwind_frame.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/msr.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/msr.c
--- linux-libre-4.9-gnu/arch/x86/kernel/msr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/msr.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,7 @@
 #include <asm/msr.h>
 
 static struct class *msr_class;
+static enum cpuhp_state cpuhp_msr_state;
 
 static ssize_t msr_read(struct file *file, char __user *buf,
 			size_t count, loff_t *ppos)
@@ -180,7 +181,7 @@ static const struct file_operations msr_
 	.compat_ioctl = msr_ioctl,
 };
 
-static int msr_device_create(int cpu)
+static int msr_device_create(unsigned int cpu)
 {
 	struct device *dev;
 
@@ -189,34 +190,12 @@ static int msr_device_create(int cpu)
 	return PTR_ERR_OR_ZERO(dev);
 }
 
-static void msr_device_destroy(int cpu)
+static int msr_device_destroy(unsigned int cpu)
 {
 	device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+	return 0;
 }
 
-static int msr_class_cpu_callback(struct notifier_block *nfb,
-				  unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long)hcpu;
-	int err = 0;
-
-	switch (action) {
-	case CPU_UP_PREPARE:
-		err = msr_device_create(cpu);
-		break;
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-	case CPU_DEAD:
-		msr_device_destroy(cpu);
-		break;
-	}
-	return notifier_from_errno(err);
-}
-
-static struct notifier_block __refdata msr_class_cpu_notifier = {
-	.notifier_call = msr_class_cpu_callback,
-};
-
 static char *msr_devnode(struct device *dev, umode_t *mode)
 {
 	return kasprintf(GFP_KERNEL, "cpu/%u/msr", MINOR(dev->devt));
@@ -224,13 +203,11 @@ static char *msr_devnode(struct device *
 
 static int __init msr_init(void)
 {
-	int i, err = 0;
-	i = 0;
+	int err;
 
 	if (__register_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr", &msr_fops)) {
 		pr_err("unable to get major %d for msr\n", MSR_MAJOR);
-		err = -EBUSY;
-		goto out;
+		return -EBUSY;
 	}
 	msr_class = class_create(THIS_MODULE, "msr");
 	if (IS_ERR(msr_class)) {
@@ -239,44 +216,27 @@ static int __init msr_init(void)
 	}
 	msr_class->devnode = msr_devnode;
 
-	cpu_notifier_register_begin();
-	for_each_online_cpu(i) {
-		err = msr_device_create(i);
-		if (err != 0)
-			goto out_class;
-	}
-	__register_hotcpu_notifier(&msr_class_cpu_notifier);
-	cpu_notifier_register_done();
-
-	err = 0;
-	goto out;
+	err  = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/msr:online",
+				 msr_device_create, msr_device_destroy);
+	if (err < 0)
+		goto out_class;
+	cpuhp_msr_state = err;
+	return 0;
 
 out_class:
-	i = 0;
-	for_each_online_cpu(i)
-		msr_device_destroy(i);
-	cpu_notifier_register_done();
 	class_destroy(msr_class);
 out_chrdev:
 	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
-out:
 	return err;
 }
+module_init(msr_init);
 
 static void __exit msr_exit(void)
 {
-	int cpu = 0;
-
-	cpu_notifier_register_begin();
-	for_each_online_cpu(cpu)
-		msr_device_destroy(cpu);
+	cpuhp_remove_state(cpuhp_msr_state);
 	class_destroy(msr_class);
 	__unregister_chrdev(MSR_MAJOR, 0, NR_CPUS, "cpu/msr");
-	__unregister_hotcpu_notifier(&msr_class_cpu_notifier);
-	cpu_notifier_register_done();
 }
-
-module_init(msr_init);
 module_exit(msr_exit)
 
 MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/paravirt.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt.c
--- linux-libre-4.9-gnu/arch/x86/kernel/paravirt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt.c	2017-02-12 16:03:20.000000000 -0500
@@ -328,7 +328,6 @@ __visible struct pv_cpu_ops pv_cpu_ops =
 	.cpuid = native_cpuid,
 	.get_debugreg = native_get_debugreg,
 	.set_debugreg = native_set_debugreg,
-	.clts = native_clts,
 	.read_cr0 = native_read_cr0,
 	.write_cr0 = native_write_cr0,
 	.read_cr4 = native_read_cr4,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/paravirt_patch_32.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt_patch_32.c
--- linux-libre-4.9-gnu/arch/x86/kernel/paravirt_patch_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt_patch_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,10 +8,10 @@ DEF_NATIVE(pv_cpu_ops, iret, "iret");
 DEF_NATIVE(pv_mmu_ops, read_cr2, "mov %cr2, %eax");
 DEF_NATIVE(pv_mmu_ops, write_cr3, "mov %eax, %cr3");
 DEF_NATIVE(pv_mmu_ops, read_cr3, "mov %cr3, %eax");
-DEF_NATIVE(pv_cpu_ops, clts, "clts");
 
 #if defined(CONFIG_PARAVIRT_SPINLOCKS)
 DEF_NATIVE(pv_lock_ops, queued_spin_unlock, "movb $0, (%eax)");
+DEF_NATIVE(pv_lock_ops, vcpu_is_preempted, "xor %eax, %eax");
 #endif
 
 unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len)
@@ -27,6 +27,7 @@ unsigned paravirt_patch_ident_64(void *i
 }
 
 extern bool pv_is_native_spin_unlock(void);
+extern bool pv_is_native_vcpu_is_preempted(void);
 
 unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
 		      unsigned long addr, unsigned len)
@@ -48,7 +49,6 @@ unsigned native_patch(u8 type, u16 clobb
 		PATCH_SITE(pv_mmu_ops, read_cr2);
 		PATCH_SITE(pv_mmu_ops, read_cr3);
 		PATCH_SITE(pv_mmu_ops, write_cr3);
-		PATCH_SITE(pv_cpu_ops, clts);
 #if defined(CONFIG_PARAVIRT_SPINLOCKS)
 		case PARAVIRT_PATCH(pv_lock_ops.queued_spin_unlock):
 			if (pv_is_native_spin_unlock()) {
@@ -56,9 +56,19 @@ unsigned native_patch(u8 type, u16 clobb
 				end   = end_pv_lock_ops_queued_spin_unlock;
 				goto patch_site;
 			}
+			goto patch_default;
+
+		case PARAVIRT_PATCH(pv_lock_ops.vcpu_is_preempted):
+			if (pv_is_native_vcpu_is_preempted()) {
+				start = start_pv_lock_ops_vcpu_is_preempted;
+				end   = end_pv_lock_ops_vcpu_is_preempted;
+				goto patch_site;
+			}
+			goto patch_default;
 #endif
 
 	default:
+patch_default: __maybe_unused
 		ret = paravirt_patch_default(type, clobbers, ibuf, addr, len);
 		break;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/paravirt_patch_64.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt_patch_64.c
--- linux-libre-4.9-gnu/arch/x86/kernel/paravirt_patch_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt_patch_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,6 @@ DEF_NATIVE(pv_mmu_ops, read_cr2, "movq %
 DEF_NATIVE(pv_mmu_ops, read_cr3, "movq %cr3, %rax");
 DEF_NATIVE(pv_mmu_ops, write_cr3, "movq %rdi, %cr3");
 DEF_NATIVE(pv_mmu_ops, flush_tlb_single, "invlpg (%rdi)");
-DEF_NATIVE(pv_cpu_ops, clts, "clts");
 DEF_NATIVE(pv_cpu_ops, wbinvd, "wbinvd");
 
 DEF_NATIVE(pv_cpu_ops, usergs_sysret64, "swapgs; sysretq");
@@ -21,6 +20,7 @@ DEF_NATIVE(, mov64, "mov %rdi, %rax");
 
 #if defined(CONFIG_PARAVIRT_SPINLOCKS)
 DEF_NATIVE(pv_lock_ops, queued_spin_unlock, "movb $0, (%rdi)");
+DEF_NATIVE(pv_lock_ops, vcpu_is_preempted, "xor %rax, %rax");
 #endif
 
 unsigned paravirt_patch_ident_32(void *insnbuf, unsigned len)
@@ -36,6 +36,7 @@ unsigned paravirt_patch_ident_64(void *i
 }
 
 extern bool pv_is_native_spin_unlock(void);
+extern bool pv_is_native_vcpu_is_preempted(void);
 
 unsigned native_patch(u8 type, u16 clobbers, void *ibuf,
 		      unsigned long addr, unsigned len)
@@ -58,7 +59,6 @@ unsigned native_patch(u8 type, u16 clobb
 		PATCH_SITE(pv_mmu_ops, read_cr2);
 		PATCH_SITE(pv_mmu_ops, read_cr3);
 		PATCH_SITE(pv_mmu_ops, write_cr3);
-		PATCH_SITE(pv_cpu_ops, clts);
 		PATCH_SITE(pv_mmu_ops, flush_tlb_single);
 		PATCH_SITE(pv_cpu_ops, wbinvd);
 #if defined(CONFIG_PARAVIRT_SPINLOCKS)
@@ -68,9 +68,19 @@ unsigned native_patch(u8 type, u16 clobb
 				end   = end_pv_lock_ops_queued_spin_unlock;
 				goto patch_site;
 			}
+			goto patch_default;
+
+		case PARAVIRT_PATCH(pv_lock_ops.vcpu_is_preempted):
+			if (pv_is_native_vcpu_is_preempted()) {
+				start = start_pv_lock_ops_vcpu_is_preempted;
+				end   = end_pv_lock_ops_vcpu_is_preempted;
+				goto patch_site;
+			}
+			goto patch_default;
 #endif
 
 	default:
+patch_default: __maybe_unused
 		ret = paravirt_patch_default(type, clobbers, ibuf, addr, len);
 		break;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/paravirt-spinlocks.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt-spinlocks.c
--- linux-libre-4.9-gnu/arch/x86/kernel/paravirt-spinlocks.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/paravirt-spinlocks.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,6 @@ __visible void __native_queued_spin_unlo
 {
 	native_queued_spin_unlock(lock);
 }
-
 PV_CALLEE_SAVE_REGS_THUNK(__native_queued_spin_unlock);
 
 bool pv_is_native_spin_unlock(void)
@@ -21,12 +20,25 @@ bool pv_is_native_spin_unlock(void)
 		__raw_callee_save___native_queued_spin_unlock;
 }
 
+__visible bool __native_vcpu_is_preempted(int cpu)
+{
+	return false;
+}
+PV_CALLEE_SAVE_REGS_THUNK(__native_vcpu_is_preempted);
+
+bool pv_is_native_vcpu_is_preempted(void)
+{
+	return pv_lock_ops.vcpu_is_preempted.func ==
+		__raw_callee_save___native_vcpu_is_preempted;
+}
+
 struct pv_lock_ops pv_lock_ops = {
 #ifdef CONFIG_SMP
 	.queued_spin_lock_slowpath = native_queued_spin_lock_slowpath,
 	.queued_spin_unlock = PV_CALLEE_SAVE(__native_queued_spin_unlock),
 	.wait = paravirt_nop,
 	.kick = paravirt_nop,
+	.vcpu_is_preempted = PV_CALLEE_SAVE(__native_vcpu_is_preempted),
 #endif /* SMP */
 };
 EXPORT_SYMBOL(pv_lock_ops);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/pci-swiotlb.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/pci-swiotlb.c
--- linux-libre-4.9-gnu/arch/x86/kernel/pci-swiotlb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/pci-swiotlb.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,12 +68,10 @@ static struct dma_map_ops swiotlb_dma_op
  */
 int __init pci_swiotlb_detect_override(void)
 {
-	int use_swiotlb = swiotlb | swiotlb_force;
-
-	if (swiotlb_force)
+	if (swiotlb_force == SWIOTLB_FORCE)
 		swiotlb = 1;
 
-	return use_swiotlb;
+	return swiotlb;
 }
 IOMMU_INIT_FINISH(pci_swiotlb_detect_override,
 		  pci_xen_swiotlb_detect,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/platform-quirks.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/platform-quirks.c
--- linux-libre-4.9-gnu/arch/x86/kernel/platform-quirks.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/platform-quirks.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,7 @@
 
 void __init x86_early_init_platform_quirks(void)
 {
+	x86_platform.legacy.i8042 = X86_LEGACY_I8042_EXPECTED_PRESENT;
 	x86_platform.legacy.rtc = 1;
 	x86_platform.legacy.reserve_bios_regions = 0;
 	x86_platform.legacy.devices.pnpbios = 1;
@@ -16,10 +17,14 @@ void __init x86_early_init_platform_quir
 		break;
 	case X86_SUBARCH_XEN:
 	case X86_SUBARCH_LGUEST:
+		x86_platform.legacy.devices.pnpbios = 0;
+		x86_platform.legacy.rtc = 0;
+		break;
 	case X86_SUBARCH_INTEL_MID:
 	case X86_SUBARCH_CE4100:
 		x86_platform.legacy.devices.pnpbios = 0;
 		x86_platform.legacy.rtc = 0;
+		x86_platform.legacy.i8042 = X86_LEGACY_I8042_PLATFORM_ABSENT;
 		break;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/process_32.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/process_32.c
--- linux-libre-4.9-gnu/arch/x86/kernel/process_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/process_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,11 +49,11 @@
 
 #include <asm/tlbflush.h>
 #include <asm/cpu.h>
-#include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
 #include <asm/switch_to.h>
 #include <asm/vm86.h>
+#include <asm/intel_rdt.h>
 
 void __show_regs(struct pt_regs *regs, int all)
 {
@@ -72,10 +72,9 @@ void __show_regs(struct pt_regs *regs, i
 		savesegment(gs, gs);
 	}
 
-	printk(KERN_DEFAULT "EIP: %04x:[<%08lx>] EFLAGS: %08lx CPU: %d\n",
-			(u16)regs->cs, regs->ip, regs->flags,
-			smp_processor_id());
-	print_symbol("EIP is at %s\n", regs->ip);
+	printk(KERN_DEFAULT "EIP: %pS\n", (void *)regs->ip);
+	printk(KERN_DEFAULT "EFLAGS: %08lx CPU: %d\n", regs->flags,
+		smp_processor_id());
 
 	printk(KERN_DEFAULT "EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
 		regs->ax, regs->bx, regs->cx, regs->dx);
@@ -232,11 +231,10 @@ __switch_to(struct task_struct *prev_p,
 	struct fpu *next_fpu = &next->fpu;
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
-	fpu_switch_t fpu_switch;
 
 	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
-	fpu_switch = switch_fpu_prepare(prev_fpu, next_fpu, cpu);
+	switch_fpu_prepare(prev_fpu, cpu);
 
 	/*
 	 * Save away %gs. No need to save %fs, as it was saved on the
@@ -295,9 +293,12 @@ __switch_to(struct task_struct *prev_p,
 	if (prev->gs | next->gs)
 		lazy_load_gs(next->gs);
 
-	switch_fpu_finish(next_fpu, fpu_switch);
+	switch_fpu_finish(next_fpu, cpu);
 
 	this_cpu_write(current_task, next_p);
 
+	/* Load the Intel cache allocation PQR MSR. */
+	intel_rdt_sched_in();
+
 	return prev_p;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/process_64.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/process_64.c
--- linux-libre-4.9-gnu/arch/x86/kernel/process_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/process_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,12 +44,12 @@
 #include <asm/desc.h>
 #include <asm/proto.h>
 #include <asm/ia32.h>
-#include <asm/idle.h>
 #include <asm/syscalls.h>
 #include <asm/debugreg.h>
 #include <asm/switch_to.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/vdso.h>
+#include <asm/intel_rdt.h>
 
 __visible DEFINE_PER_CPU(unsigned long, rsp_scratch);
 
@@ -61,10 +61,15 @@ void __show_regs(struct pt_regs *regs, i
 	unsigned int fsindex, gsindex;
 	unsigned int ds, cs, es;
 
-	printk(KERN_DEFAULT "RIP: %04lx:[<%016lx>] ", regs->cs & 0xffff, regs->ip);
-	printk_address(regs->ip);
-	printk(KERN_DEFAULT "RSP: %04lx:%016lx  EFLAGS: %08lx\n", regs->ss,
-			regs->sp, regs->flags);
+	printk(KERN_DEFAULT "RIP: %04lx:%pS\n", regs->cs & 0xffff,
+		(void *)regs->ip);
+	printk(KERN_DEFAULT "RSP: %04lx:%016lx EFLAGS: %08lx", regs->ss,
+		regs->sp, regs->flags);
+	if (regs->orig_ax != -1)
+		pr_cont(" ORIG_RAX: %016lx\n", regs->orig_ax);
+	else
+		pr_cont("\n");
+
 	printk(KERN_DEFAULT "RAX: %016lx RBX: %016lx RCX: %016lx\n",
 	       regs->ax, regs->bx, regs->cx);
 	printk(KERN_DEFAULT "RDX: %016lx RSI: %016lx RDI: %016lx\n",
@@ -265,9 +270,8 @@ __switch_to(struct task_struct *prev_p,
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = &per_cpu(cpu_tss, cpu);
 	unsigned prev_fsindex, prev_gsindex;
-	fpu_switch_t fpu_switch;
 
-	fpu_switch = switch_fpu_prepare(prev_fpu, next_fpu, cpu);
+	switch_fpu_prepare(prev_fpu, cpu);
 
 	/* We must save %fs and %gs before load_TLS() because
 	 * %fs and %gs may be cleared by load_TLS().
@@ -417,7 +421,7 @@ __switch_to(struct task_struct *prev_p,
 		prev->gsbase = 0;
 	prev->gsindex = prev_gsindex;
 
-	switch_fpu_finish(next_fpu, fpu_switch);
+	switch_fpu_finish(next_fpu, cpu);
 
 	/*
 	 * Switch the PDA and FPU contexts.
@@ -473,6 +477,9 @@ __switch_to(struct task_struct *prev_p,
 			loadsegment(ss, __KERNEL_DS);
 	}
 
+	/* Load the Intel cache allocation PQR MSR. */
+	intel_rdt_sched_in();
+
 	return prev_p;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/process.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/process.c
--- linux-libre-4.9-gnu/arch/x86/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,8 +23,7 @@
 #include <asm/cpu.h>
 #include <asm/apic.h>
 #include <asm/syscalls.h>
-#include <asm/idle.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mwait.h>
 #include <asm/fpu/internal.h>
 #include <asm/debugreg.h>
@@ -65,23 +64,6 @@ __visible DEFINE_PER_CPU_SHARED_ALIGNED(
 };
 EXPORT_PER_CPU_SYMBOL(cpu_tss);
 
-#ifdef CONFIG_X86_64
-static DEFINE_PER_CPU(unsigned char, is_idle);
-static ATOMIC_NOTIFIER_HEAD(idle_notifier);
-
-void idle_notifier_register(struct notifier_block *n)
-{
-	atomic_notifier_chain_register(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_register);
-
-void idle_notifier_unregister(struct notifier_block *n)
-{
-	atomic_notifier_chain_unregister(&idle_notifier, n);
-}
-EXPORT_SYMBOL_GPL(idle_notifier_unregister);
-#endif
-
 /*
  * this gets called so that we can store lazy state into memory and copy the
  * current task into the new thread.
@@ -251,39 +233,10 @@ static inline void play_dead(void)
 }
 #endif
 
-#ifdef CONFIG_X86_64
-void enter_idle(void)
-{
-	this_cpu_write(is_idle, 1);
-	atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
-}
-
-static void __exit_idle(void)
-{
-	if (x86_test_and_clear_bit_percpu(0, is_idle) == 0)
-		return;
-	atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
-}
-
-/* Called from interrupts to signify idle end */
-void exit_idle(void)
-{
-	/* idle loop has pid 0 */
-	if (current->pid)
-		return;
-	__exit_idle();
-}
-#endif
-
 void arch_cpu_idle_enter(void)
 {
+	tsc_verify_tsc_adjust(false);
 	local_touch_nmi();
-	enter_idle();
-}
-
-void arch_cpu_idle_exit(void)
-{
-	__exit_idle();
 }
 
 void arch_cpu_idle_dead(void)
@@ -336,59 +289,33 @@ void stop_this_cpu(void *dummy)
 		halt();
 }
 
-bool amd_e400_c1e_detected;
-EXPORT_SYMBOL(amd_e400_c1e_detected);
-
-static cpumask_var_t amd_e400_c1e_mask;
-
-void amd_e400_remove_cpu(int cpu)
-{
-	if (amd_e400_c1e_mask != NULL)
-		cpumask_clear_cpu(cpu, amd_e400_c1e_mask);
-}
-
 /*
- * AMD Erratum 400 aware idle routine. We check for C1E active in the interrupt
- * pending message MSR. If we detect C1E, then we handle it the same
- * way as C3 power states (local apic timer and TSC stop)
+ * AMD Erratum 400 aware idle routine. We handle it the same way as C3 power
+ * states (local apic timer and TSC stop).
  */
 static void amd_e400_idle(void)
 {
-	if (!amd_e400_c1e_detected) {
-		u32 lo, hi;
-
-		rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
-
-		if (lo & K8_INTP_C1E_ACTIVE_MASK) {
-			amd_e400_c1e_detected = true;
-			if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
-				mark_tsc_unstable("TSC halt in AMD C1E");
-			pr_info("System has AMD C1E enabled\n");
-		}
+	/*
+	 * We cannot use static_cpu_has_bug() here because X86_BUG_AMD_APIC_C1E
+	 * gets set after static_cpu_has() places have been converted via
+	 * alternatives.
+	 */
+	if (!boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
+		default_idle();
+		return;
 	}
 
-	if (amd_e400_c1e_detected) {
-		int cpu = smp_processor_id();
-
-		if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) {
-			cpumask_set_cpu(cpu, amd_e400_c1e_mask);
-			/* Force broadcast so ACPI can not interfere. */
-			tick_broadcast_force();
-			pr_info("Switch to broadcast mode on CPU%d\n", cpu);
-		}
-		tick_broadcast_enter();
+	tick_broadcast_enter();
 
-		default_idle();
+	default_idle();
 
-		/*
-		 * The switch back from broadcast mode needs to be
-		 * called with interrupts disabled.
-		 */
-		local_irq_disable();
-		tick_broadcast_exit();
-		local_irq_enable();
-	} else
-		default_idle();
+	/*
+	 * The switch back from broadcast mode needs to be called with
+	 * interrupts disabled.
+	 */
+	local_irq_disable();
+	tick_broadcast_exit();
+	local_irq_enable();
 }
 
 /*
@@ -448,8 +375,7 @@ void select_idle_routine(const struct cp
 	if (x86_idle || boot_option_idle_override == IDLE_POLL)
 		return;
 
-	if (cpu_has_bug(c, X86_BUG_AMD_APIC_C1E)) {
-		/* E400: APIC timer interrupt does not wake up CPU from C1e */
+	if (boot_cpu_has_bug(X86_BUG_AMD_E400)) {
 		pr_info("using AMD E400 aware idle routine\n");
 		x86_idle = amd_e400_idle;
 	} else if (prefer_mwait_c1_over_halt(c)) {
@@ -459,11 +385,37 @@ void select_idle_routine(const struct cp
 		x86_idle = default_idle;
 }
 
-void __init init_amd_e400_c1e_mask(void)
+void amd_e400_c1e_apic_setup(void)
 {
-	/* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */
-	if (x86_idle == amd_e400_idle)
-		zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL);
+	if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) {
+		pr_info("Switch to broadcast mode on CPU%d\n", smp_processor_id());
+		local_irq_disable();
+		tick_broadcast_force();
+		local_irq_enable();
+	}
+}
+
+void __init arch_post_acpi_subsys_init(void)
+{
+	u32 lo, hi;
+
+	if (!boot_cpu_has_bug(X86_BUG_AMD_E400))
+		return;
+
+	/*
+	 * AMD E400 detection needs to happen after ACPI has been enabled. If
+	 * the machine is affected K8_INTP_C1E_ACTIVE_MASK bits are set in
+	 * MSR_K8_INT_PENDING_MSG.
+	 */
+	rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
+	if (!(lo & K8_INTP_C1E_ACTIVE_MASK))
+		return;
+
+	boot_cpu_set_bug(X86_BUG_AMD_APIC_C1E);
+
+	if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
+		mark_tsc_unstable("TSC halt in AMD C1E");
+	pr_info("System has AMD C1E enabled\n");
 }
 
 static int __init idle_setup(char *str)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/x86/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/export.h>
 #include <linux/context_tracking.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/fpu/internal.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/pvclock.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/pvclock.c
--- linux-libre-4.9-gnu/arch/x86/kernel/pvclock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/pvclock.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,10 +71,10 @@ u8 pvclock_read_flags(struct pvclock_vcp
 	return flags & valid_flags;
 }
 
-cycle_t pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
+u64 pvclock_clocksource_read(struct pvclock_vcpu_time_info *src)
 {
 	unsigned version;
-	cycle_t ret;
+	u64 ret;
 	u64 last;
 	u8 flags;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/rtc.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/rtc.c
--- linux-libre-4.9-gnu/arch/x86/kernel/rtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/rtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,15 @@ void mach_get_cmos_time(struct timespec
 	unsigned int status, year, mon, day, hour, min, sec, century = 0;
 	unsigned long flags;
 
+	/*
+	 * If pm_trace abused the RTC as storage, set the timespec to 0,
+	 * which tells the caller that this RTC value is unusable.
+	 */
+	if (!pm_trace_rtc_valid()) {
+		now->tv_sec = now->tv_nsec = 0;
+		return;
+	}
+
 	spin_lock_irqsave(&rtc_lock, flags);
 
 	/*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/setup.c
--- linux-libre-4.9-gnu/arch/x86/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -985,6 +985,30 @@ void __init setup_arch(char **cmdline_p)
 
 	parse_early_param();
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+	/*
+	 * Memory used by the kernel cannot be hot-removed because Linux
+	 * cannot migrate the kernel pages. When memory hotplug is
+	 * enabled, we should prevent memblock from allocating memory
+	 * for the kernel.
+	 *
+	 * ACPI SRAT records all hotpluggable memory ranges. But before
+	 * SRAT is parsed, we don't know about it.
+	 *
+	 * The kernel image is loaded into memory at very early time. We
+	 * cannot prevent this anyway. So on NUMA system, we set any
+	 * node the kernel resides in as un-hotpluggable.
+	 *
+	 * Since on modern servers, one node could have double-digit
+	 * gigabytes memory, we can assume the memory around the kernel
+	 * image is also un-hotpluggable. So before SRAT is parsed, just
+	 * allocate memory near the kernel image to try the best to keep
+	 * the kernel away from hotpluggable memory.
+	 */
+	if (movable_node_is_enabled())
+		memblock_set_bottom_up(true);
+#endif
+
 	x86_report_nx();
 
 	/* after early param, so could get panic from serial */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/setup_percpu.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/setup_percpu.c
--- linux-libre-4.9-gnu/arch/x86/kernel/setup_percpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/setup_percpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/percpu.h>
@@ -12,6 +12,7 @@
 #include <linux/pfn.h>
 #include <asm/sections.h>
 #include <asm/processor.h>
+#include <asm/desc.h>
 #include <asm/setup.h>
 #include <asm/mpspec.h>
 #include <asm/apicdef.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/smpboot.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/smpboot.c
--- linux-libre-4.9-gnu/arch/x86/kernel/smpboot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/smpboot.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,6 @@
 #include <asm/desc.h>
 #include <asm/nmi.h>
 #include <asm/irq.h>
-#include <asm/idle.h>
 #include <asm/realmode.h>
 #include <asm/cpu.h>
 #include <asm/numa.h>
@@ -104,11 +103,21 @@ static unsigned int max_physical_pkg_id
 unsigned int __max_logical_packages __read_mostly;
 EXPORT_SYMBOL(__max_logical_packages);
 static unsigned int logical_packages __read_mostly;
-static bool logical_packages_frozen __read_mostly;
 
 /* Maximum number of SMT threads on any online core */
 int __max_smt_threads __read_mostly;
 
+/* Flag to indicate if a complete sched domain rebuild is required */
+bool x86_topology_update;
+
+int arch_update_cpu_topology(void)
+{
+	int retval = x86_topology_update;
+
+	x86_topology_update = false;
+	return retval;
+}
+
 static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
 {
 	unsigned long flags;
@@ -263,9 +272,14 @@ static void notrace start_secondary(void
 	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
 }
 
-int topology_update_package_map(unsigned int apicid, unsigned int cpu)
+/**
+ * topology_update_package_map - Update the physical to logical package map
+ * @pkg:	The physical package id as retrieved via CPUID
+ * @cpu:	The cpu for which this is updated
+ */
+int topology_update_package_map(unsigned int pkg, unsigned int cpu)
 {
-	unsigned int new, pkg = apicid >> boot_cpu_data.x86_coreid_bits;
+	unsigned int new;
 
 	/* Called from early boot ? */
 	if (!physical_package_map)
@@ -278,16 +292,17 @@ int topology_update_package_map(unsigned
 	if (test_and_set_bit(pkg, physical_package_map))
 		goto found;
 
-	if (logical_packages_frozen) {
-		physical_to_logical_pkg[pkg] = -1;
-		pr_warn("APIC(%x) Package %u exceeds logical package max\n",
-			apicid, pkg);
+	if (logical_packages >= __max_logical_packages) {
+		pr_warn("Package %u of CPU %u exceeds BIOS package data %u.\n",
+			logical_packages, cpu, __max_logical_packages);
 		return -ENOSPC;
 	}
 
 	new = logical_packages++;
-	pr_info("APIC(%x) Converting physical %u to logical package %u\n",
-		apicid, pkg, new);
+	if (new != pkg) {
+		pr_info("CPU %u Converting physical %u to logical package %u\n",
+			cpu, pkg, new);
+	}
 	physical_to_logical_pkg[pkg] = new;
 
 found:
@@ -308,9 +323,9 @@ int topology_phys_to_logical_pkg(unsigne
 }
 EXPORT_SYMBOL(topology_phys_to_logical_pkg);
 
-static void __init smp_init_package_map(void)
+static void __init smp_init_package_map(struct cpuinfo_x86 *c, unsigned int cpu)
 {
-	unsigned int ncpus, cpu;
+	unsigned int ncpus;
 	size_t size;
 
 	/*
@@ -355,27 +370,9 @@ static void __init smp_init_package_map(
 	size = BITS_TO_LONGS(max_physical_pkg_id) * sizeof(unsigned long);
 	physical_package_map = kzalloc(size, GFP_KERNEL);
 
-	for_each_present_cpu(cpu) {
-		unsigned int apicid = apic->cpu_present_to_apicid(cpu);
-
-		if (apicid == BAD_APICID || !apic->apic_id_valid(apicid))
-			continue;
-		if (!topology_update_package_map(apicid, cpu))
-			continue;
-		pr_warn("CPU %u APICId %x disabled\n", cpu, apicid);
-		per_cpu(x86_bios_cpu_apicid, cpu) = BAD_APICID;
-		set_cpu_possible(cpu, false);
-		set_cpu_present(cpu, false);
-	}
-
-	if (logical_packages > __max_logical_packages) {
-		pr_warn("Detected more packages (%u), then computed by BIOS data (%u).\n",
-			logical_packages, __max_logical_packages);
-		logical_packages_frozen = true;
-		__max_logical_packages  = logical_packages;
-	}
-
 	pr_info("Max logical packages: %u\n", __max_logical_packages);
+
+	topology_update_package_map(c->phys_proc_id, cpu);
 }
 
 void __init smp_store_boot_cpu_info(void)
@@ -385,7 +382,7 @@ void __init smp_store_boot_cpu_info(void
 
 	*c = boot_cpu_data;
 	c->cpu_index = id;
-	smp_init_package_map();
+	smp_init_package_map(c, id);
 }
 
 /*
@@ -436,9 +433,15 @@ static bool match_smt(struct cpuinfo_x86
 		int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
 
 		if (c->phys_proc_id == o->phys_proc_id &&
-		    per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2) &&
-		    c->cpu_core_id == o->cpu_core_id)
-			return topology_sane(c, o, "smt");
+		    per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2)) {
+			if (c->cpu_core_id == o->cpu_core_id)
+				return topology_sane(c, o, "smt");
+
+			if ((c->cu_id != 0xff) &&
+			    (o->cu_id != 0xff) &&
+			    (c->cu_id == o->cu_id))
+				return topology_sane(c, o, "smt");
+		}
 
 	} else if (c->phys_proc_id == o->phys_proc_id &&
 		   c->cpu_core_id == o->cpu_core_id) {
@@ -471,22 +474,42 @@ static bool match_die(struct cpuinfo_x86
 	return false;
 }
 
+#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC)
+static inline int x86_sched_itmt_flags(void)
+{
+	return sysctl_sched_itmt_enabled ? SD_ASYM_PACKING : 0;
+}
+
+#ifdef CONFIG_SCHED_MC
+static int x86_core_flags(void)
+{
+	return cpu_core_flags() | x86_sched_itmt_flags();
+}
+#endif
+#ifdef CONFIG_SCHED_SMT
+static int x86_smt_flags(void)
+{
+	return cpu_smt_flags() | x86_sched_itmt_flags();
+}
+#endif
+#endif
+
 static struct sched_domain_topology_level x86_numa_in_package_topology[] = {
 #ifdef CONFIG_SCHED_SMT
-	{ cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
+	{ cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) },
 #endif
 #ifdef CONFIG_SCHED_MC
-	{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
+	{ cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) },
 #endif
 	{ NULL, },
 };
 
 static struct sched_domain_topology_level x86_topology[] = {
 #ifdef CONFIG_SCHED_SMT
-	{ cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) },
+	{ cpu_smt_mask, x86_smt_flags, SD_INIT_NAME(SMT) },
 #endif
 #ifdef CONFIG_SCHED_MC
-	{ cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) },
+	{ cpu_coregroup_mask, x86_core_flags, SD_INIT_NAME(MC) },
 #endif
 	{ cpu_cpu_mask, SD_INIT_NAME(DIE) },
 	{ NULL, },
@@ -821,14 +844,6 @@ wakeup_secondary_cpu_via_init(int phys_a
 	return (send_status | accept_status);
 }
 
-void smp_announce(void)
-{
-	int num_nodes = num_online_nodes();
-
-	printk(KERN_INFO "x86: Booted up %d node%s, %d CPUs\n",
-	       num_nodes, (num_nodes > 1 ? "s" : ""), num_online_cpus());
-}
-
 /* reduce the number of lines printed when booting a large cpu count system */
 static void announce_cpu(int cpu, int apicid)
 {
@@ -964,9 +979,7 @@ static int do_boot_cpu(int apicid, int c
 	int cpu0_nmi_registered = 0;
 	unsigned long timeout;
 
-	idle->thread.sp = (unsigned long) (((struct pt_regs *)
-			  (THREAD_SIZE +  task_stack_page(idle))) - 1);
-
+	idle->thread.sp = (unsigned long)task_pt_regs(idle);
 	early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
 	initial_code = (unsigned long)start_secondary;
 	initial_stack  = idle->thread.sp;
@@ -1111,7 +1124,7 @@ int native_cpu_up(unsigned int cpu, stru
 		return err;
 
 	/* the FPU context is blank, nobody can own it */
-	__cpu_disable_lazy_restore(cpu);
+	per_cpu(fpu_fpregs_owner_ctx, cpu) = NULL;
 
 	common_cpu_up(cpu, tidle);
 
@@ -1331,7 +1344,7 @@ void __init native_smp_prepare_cpus(unsi
 	default_setup_apic_routing();
 	cpu0_logical_apicid = apic_bsp_setup(false);
 
-	pr_info("CPU%d: ", 0);
+	pr_info("CPU0: ");
 	print_cpu_info(&cpu_data(0));
 
 	if (is_uv_system())
@@ -1456,15 +1469,15 @@ __init void prefill_possible_map(void)
 		possible = i;
 	}
 
+	nr_cpu_ids = possible;
+
 	pr_info("Allowing %d CPUs, %d hotplug CPUs\n",
 		possible, max_t(int, possible - num_processors, 0));
 
+	reset_cpu_possible_mask();
+
 	for (i = 0; i < possible; i++)
 		set_cpu_possible(i, true);
-	for (; i < NR_CPUS; i++)
-		set_cpu_possible(i, false);
-
-	nr_cpu_ids = possible;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1575,7 +1588,6 @@ void play_dead_common(void)
 {
 	idle_task_exit();
 	reset_lazy_tlbstate();
-	amd_e400_remove_cpu(raw_smp_processor_id());
 
 	/* Ack it */
 	(void)cpu_report_death();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/smp.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/smp.c
--- linux-libre-4.9-gnu/arch/x86/kernel/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -261,10 +261,8 @@ static inline void __smp_reschedule_inte
 
 __visible void smp_reschedule_interrupt(struct pt_regs *regs)
 {
-	irq_enter();
 	ack_APIC_irq();
 	__smp_reschedule_interrupt();
-	irq_exit();
 	/*
 	 * KVM uses this interrupt to force a cpu out of guest mode
 	 */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/tboot.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/tboot.c
--- linux-libre-4.9-gnu/arch/x86/kernel/tboot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/tboot.c	2017-02-12 16:03:20.000000000 -0500
@@ -408,7 +408,7 @@ static __init int tboot_late_init(void)
 	tboot_create_trampoline();
 
 	atomic_set(&ap_wfs_count, 0);
-	cpuhp_setup_state(CPUHP_AP_X86_TBOOT_DYING, "AP_X86_TBOOT_DYING", NULL,
+	cpuhp_setup_state(CPUHP_AP_X86_TBOOT_DYING, "x86/tboot:dying", NULL,
 			  tboot_dying_cpu);
 #ifdef CONFIG_DEBUG_FS
 	debugfs_create_file("tboot_log", S_IRUSR,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/test_nx.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/test_nx.c
--- linux-libre-4.9-gnu/arch/x86/kernel/test_nx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/test_nx.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/sort.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/asm.h>
 
 extern int rodata_test_data;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/tls.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/tls.c
--- linux-libre-4.9-gnu/arch/x86/kernel/tls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/tls.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 #include <linux/regset.h>
 #include <linux/syscalls.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/desc.h>
 #include <asm/ldt.h>
 #include <asm/processor.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/tracepoint.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/tracepoint.c
--- linux-libre-4.9-gnu/arch/x86/kernel/tracepoint.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/tracepoint.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@ static void switch_idt(void *arg)
 	local_irq_restore(flags);
 }
 
-void trace_irq_vector_regfunc(void)
+int trace_irq_vector_regfunc(void)
 {
 	mutex_lock(&irq_vector_mutex);
 	if (!trace_irq_vector_refcount) {
@@ -44,6 +44,7 @@ void trace_irq_vector_regfunc(void)
 	}
 	trace_irq_vector_refcount++;
 	mutex_unlock(&irq_vector_mutex);
+	return 0;
 }
 
 void trace_irq_vector_unregfunc(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/traps.c
--- linux-libre-4.9-gnu/arch/x86/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -853,6 +853,8 @@ do_spurious_interrupt_bug(struct pt_regs
 dotraplinkage void
 do_device_not_available(struct pt_regs *regs, long error_code)
 {
+	unsigned long cr0;
+
 	RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
 
 #ifdef CONFIG_MATH_EMULATION
@@ -866,10 +868,20 @@ do_device_not_available(struct pt_regs *
 		return;
 	}
 #endif
-	fpu__restore(&current->thread.fpu); /* interrupts still off */
-#ifdef CONFIG_X86_32
-	cond_local_irq_enable(regs);
-#endif
+
+	/* This should not happen. */
+	cr0 = read_cr0();
+	if (WARN(cr0 & X86_CR0_TS, "CR0.TS was set")) {
+		/* Try to fix it up and carry on. */
+		write_cr0(cr0 & ~X86_CR0_TS);
+	} else {
+		/*
+		 * Something terrible happened, and we're better off trying
+		 * to kill the task than getting stuck in a never-ending
+		 * loop of #NM faults.
+		 */
+		die("unexpected #NM exception", regs, error_code);
+	}
 }
 NOKPROBE_SYMBOL(do_device_not_available);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/tsc.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/tsc.c
--- linux-libre-4.9-gnu/arch/x86/kernel/tsc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/tsc.c	2017-02-12 16:03:20.000000000 -0500
@@ -694,6 +694,7 @@ unsigned long native_calibrate_tsc(void)
 			crystal_khz = 24000;	/* 24.0 MHz */
 			break;
 		case INTEL_FAM6_SKYLAKE_X:
+		case INTEL_FAM6_ATOM_DENVERTON:
 			crystal_khz = 25000;	/* 25.0 MHz */
 			break;
 		case INTEL_FAM6_ATOM_GOLDMONT:
@@ -702,6 +703,20 @@ unsigned long native_calibrate_tsc(void)
 		}
 	}
 
+	/*
+	 * TSC frequency determined by CPUID is a "hardware reported"
+	 * frequency and is the most accurate one so far we have. This
+	 * is considered a known frequency.
+	 */
+	setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+
+	/*
+	 * For Atom SoCs TSC is the only reliable clocksource.
+	 * Mark TSC reliable so no watchdog on it.
+	 */
+	if (boot_cpu_data.x86_model == INTEL_FAM6_ATOM_GOLDMONT)
+		setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+
 	return crystal_khz * ebx_numerator / eax_denominator;
 }
 
@@ -1043,18 +1058,20 @@ static void detect_art(void)
 	if (boot_cpu_data.cpuid_level < ART_CPUID_LEAF)
 		return;
 
-	cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator,
-	      &art_to_tsc_numerator, unused, unused+1);
-
-	/* Don't enable ART in a VM, non-stop TSC required */
+	/* Don't enable ART in a VM, non-stop TSC and TSC_ADJUST required */
 	if (boot_cpu_has(X86_FEATURE_HYPERVISOR) ||
 	    !boot_cpu_has(X86_FEATURE_NONSTOP_TSC) ||
-	    art_to_tsc_denominator < ART_MIN_DENOMINATOR)
+	    !boot_cpu_has(X86_FEATURE_TSC_ADJUST))
 		return;
 
-	if (rdmsrl_safe(MSR_IA32_TSC_ADJUST, &art_to_tsc_offset))
+	cpuid(ART_CPUID_LEAF, &art_to_tsc_denominator,
+	      &art_to_tsc_numerator, unused, unused+1);
+
+	if (art_to_tsc_denominator < ART_MIN_DENOMINATOR)
 		return;
 
+	rdmsrl(MSR_IA32_TSC_ADJUST, art_to_tsc_offset);
+
 	/* Make this sticky over multiple CPU init calls */
 	setup_force_cpu_cap(X86_FEATURE_ART);
 }
@@ -1064,6 +1081,11 @@ static void detect_art(void)
 
 static struct clocksource clocksource_tsc;
 
+static void tsc_resume(struct clocksource *cs)
+{
+	tsc_verify_tsc_adjust(true);
+}
+
 /*
  * We used to compare the TSC to the cycle_last value in the clocksource
  * structure to avoid a nasty time-warp. This can be observed in a
@@ -1080,9 +1102,9 @@ static struct clocksource clocksource_ts
  * checking the result of read_tsc() - cycle_last for being negative.
  * That works because CLOCKSOURCE_MASK(64) does not mask out any bit.
  */
-static cycle_t read_tsc(struct clocksource *cs)
+static u64 read_tsc(struct clocksource *cs)
 {
-	return (cycle_t)rdtsc_ordered();
+	return (u64)rdtsc_ordered();
 }
 
 /*
@@ -1096,6 +1118,7 @@ static struct clocksource clocksource_ts
 	.flags                  = CLOCK_SOURCE_IS_CONTINUOUS |
 				  CLOCK_SOURCE_MUST_VERIFY,
 	.archdata               = { .vclock_mode = VCLOCK_TSC },
+	.resume			= tsc_resume,
 };
 
 void mark_tsc_unstable(char *reason)
@@ -1170,7 +1193,7 @@ int unsynchronized_tsc(void)
 /*
  * Convert ART to TSC given numerator/denominator found in detect_art()
  */
-struct system_counterval_t convert_art_to_tsc(cycle_t art)
+struct system_counterval_t convert_art_to_tsc(u64 art)
 {
 	u64 tmp, res, rem;
 
@@ -1283,10 +1306,10 @@ static int __init init_tsc_clocksource(v
 		clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
 
 	/*
-	 * Trust the results of the earlier calibration on systems
-	 * exporting a reliable TSC.
+	 * When TSC frequency is known (retrieved via MSR or CPUID), we skip
+	 * the refined calibration and directly register it as a clocksource.
 	 */
-	if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
+	if (boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ)) {
 		clocksource_register_khz(&clocksource_tsc, tsc_khz);
 		return 0;
 	}
@@ -1333,6 +1356,9 @@ void __init tsc_init(void)
 		(unsigned long)cpu_khz / 1000,
 		(unsigned long)cpu_khz % 1000);
 
+	/* Sanitize TSC ADJUST before cyc2ns gets initialized */
+	tsc_store_and_check_tsc_adjust(true);
+
 	/*
 	 * Secondary CPUs do not run through tsc_init(), so set up
 	 * all the scale factors for all CPUs, assuming the same
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/tsc_msr.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/tsc_msr.c
--- linux-libre-4.9-gnu/arch/x86/kernel/tsc_msr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/tsc_msr.c	2017-02-12 16:03:20.000000000 -0500
@@ -100,5 +100,24 @@ unsigned long cpu_khz_from_msr(void)
 #ifdef CONFIG_X86_LOCAL_APIC
 	lapic_timer_frequency = (freq * 1000) / HZ;
 #endif
+
+	/*
+	 * TSC frequency determined by MSR is always considered "known"
+	 * because it is reported by HW.
+	 * Another fact is that on MSR capable platforms, PIT/HPET is
+	 * generally not available so calibration won't work at all.
+	 */
+	setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+
+	/*
+	 * Unfortunately there is no way for hardware to tell whether the
+	 * TSC is reliable.  We were told by silicon design team that TSC
+	 * on Atom SoCs are always "reliable". TSC is also the only
+	 * reliable clocksource on these SoCs (HPET is either not present
+	 * or not functional) so mark TSC reliable which removes the
+	 * requirement for a watchdog clocksource.
+	 */
+	setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
+
 	return res;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/tsc_sync.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/tsc_sync.c
--- linux-libre-4.9-gnu/arch/x86/kernel/tsc_sync.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/tsc_sync.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,18 +14,166 @@
  * ( The serial nature of the boot logic and the CPU hotplug lock
  *   protects against more than 2 CPUs entering this code. )
  */
+#include <linux/topology.h>
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/nmi.h>
 #include <asm/tsc.h>
 
+struct tsc_adjust {
+	s64		bootval;
+	s64		adjusted;
+	unsigned long	nextcheck;
+	bool		warned;
+};
+
+static DEFINE_PER_CPU(struct tsc_adjust, tsc_adjust);
+
+void tsc_verify_tsc_adjust(bool resume)
+{
+	struct tsc_adjust *adj = this_cpu_ptr(&tsc_adjust);
+	s64 curval;
+
+	if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST))
+		return;
+
+	/* Rate limit the MSR check */
+	if (!resume && time_before(jiffies, adj->nextcheck))
+		return;
+
+	adj->nextcheck = jiffies + HZ;
+
+	rdmsrl(MSR_IA32_TSC_ADJUST, curval);
+	if (adj->adjusted == curval)
+		return;
+
+	/* Restore the original value */
+	wrmsrl(MSR_IA32_TSC_ADJUST, adj->adjusted);
+
+	if (!adj->warned || resume) {
+		pr_warn(FW_BUG "TSC ADJUST differs: CPU%u %lld --> %lld. Restoring\n",
+			smp_processor_id(), adj->adjusted, curval);
+		adj->warned = true;
+	}
+}
+
+static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval,
+				   unsigned int cpu, bool bootcpu)
+{
+	/*
+	 * First online CPU in a package stores the boot value in the
+	 * adjustment value. This value might change later via the sync
+	 * mechanism. If that fails we still can yell about boot values not
+	 * being consistent.
+	 *
+	 * On the boot cpu we just force set the ADJUST value to 0 if it's
+	 * non zero. We don't do that on non boot cpus because physical
+	 * hotplug should have set the ADJUST register to a value > 0 so
+	 * the TSC is in sync with the already running cpus.
+	 *
+	 * But we always force positive ADJUST values. Otherwise the TSC
+	 * deadline timer creates an interrupt storm. We also have to
+	 * prevent values > 0x7FFFFFFF as those wreckage the timer as well.
+	 */
+	if ((bootcpu && bootval != 0) || (!bootcpu && bootval < 0) ||
+	    (bootval > 0x7FFFFFFF)) {
+		pr_warn(FW_BUG "TSC ADJUST: CPU%u: %lld force to 0\n", cpu,
+			bootval);
+		wrmsrl(MSR_IA32_TSC_ADJUST, 0);
+		bootval = 0;
+	}
+	cur->adjusted = bootval;
+}
+
+#ifndef CONFIG_SMP
+bool __init tsc_store_and_check_tsc_adjust(bool bootcpu)
+{
+	struct tsc_adjust *cur = this_cpu_ptr(&tsc_adjust);
+	s64 bootval;
+
+	if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST))
+		return false;
+
+	rdmsrl(MSR_IA32_TSC_ADJUST, bootval);
+	cur->bootval = bootval;
+	cur->nextcheck = jiffies + HZ;
+	tsc_sanitize_first_cpu(cur, bootval, smp_processor_id(), bootcpu);
+	return false;
+}
+
+#else /* !CONFIG_SMP */
+
+/*
+ * Store and check the TSC ADJUST MSR if available
+ */
+bool tsc_store_and_check_tsc_adjust(bool bootcpu)
+{
+	struct tsc_adjust *ref, *cur = this_cpu_ptr(&tsc_adjust);
+	unsigned int refcpu, cpu = smp_processor_id();
+	struct cpumask *mask;
+	s64 bootval;
+
+	if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST))
+		return false;
+
+	rdmsrl(MSR_IA32_TSC_ADJUST, bootval);
+	cur->bootval = bootval;
+	cur->nextcheck = jiffies + HZ;
+	cur->warned = false;
+
+	/*
+	 * Check whether this CPU is the first in a package to come up. In
+	 * this case do not check the boot value against another package
+	 * because the new package might have been physically hotplugged,
+	 * where TSC_ADJUST is expected to be different. When called on the
+	 * boot CPU topology_core_cpumask() might not be available yet.
+	 */
+	mask = topology_core_cpumask(cpu);
+	refcpu = mask ? cpumask_any_but(mask, cpu) : nr_cpu_ids;
+
+	if (refcpu >= nr_cpu_ids) {
+		tsc_sanitize_first_cpu(cur, bootval, smp_processor_id(),
+				       bootcpu);
+		return false;
+	}
+
+	ref = per_cpu_ptr(&tsc_adjust, refcpu);
+	/*
+	 * Compare the boot value and complain if it differs in the
+	 * package.
+	 */
+	if (bootval != ref->bootval) {
+		pr_warn(FW_BUG "TSC ADJUST differs: Reference CPU%u: %lld CPU%u: %lld\n",
+			refcpu, ref->bootval, cpu, bootval);
+	}
+	/*
+	 * The TSC_ADJUST values in a package must be the same. If the boot
+	 * value on this newly upcoming CPU differs from the adjustment
+	 * value of the already online CPU in this package, set it to that
+	 * adjusted value.
+	 */
+	if (bootval != ref->adjusted) {
+		pr_warn("TSC ADJUST synchronize: Reference CPU%u: %lld CPU%u: %lld\n",
+			refcpu, ref->adjusted, cpu, bootval);
+		cur->adjusted = ref->adjusted;
+		wrmsrl(MSR_IA32_TSC_ADJUST, ref->adjusted);
+	}
+	/*
+	 * We have the TSCs forced to be in sync on this package. Skip sync
+	 * test:
+	 */
+	return true;
+}
+
 /*
  * Entry/exit counters that make sure that both CPUs
  * run the measurement code at once:
  */
 static atomic_t start_count;
 static atomic_t stop_count;
+static atomic_t skip_test;
+static atomic_t test_runs;
 
 /*
  * We use a raw spinlock in this exceptional case, because
@@ -37,15 +185,16 @@ static arch_spinlock_t sync_lock = __ARC
 static cycles_t last_tsc;
 static cycles_t max_warp;
 static int nr_warps;
+static int random_warps;
 
 /*
  * TSC-warp measurement loop running on both CPUs.  This is not called
  * if there is no TSC.
  */
-static void check_tsc_warp(unsigned int timeout)
+static cycles_t check_tsc_warp(unsigned int timeout)
 {
-	cycles_t start, now, prev, end;
-	int i;
+	cycles_t start, now, prev, end, cur_max_warp = 0;
+	int i, cur_warps = 0;
 
 	start = rdtsc_ordered();
 	/*
@@ -85,13 +234,22 @@ static void check_tsc_warp(unsigned int
 		if (unlikely(prev > now)) {
 			arch_spin_lock(&sync_lock);
 			max_warp = max(max_warp, prev - now);
+			cur_max_warp = max_warp;
+			/*
+			 * Check whether this bounces back and forth. Only
+			 * one CPU should observe time going backwards.
+			 */
+			if (cur_warps != nr_warps)
+				random_warps++;
 			nr_warps++;
+			cur_warps = nr_warps;
 			arch_spin_unlock(&sync_lock);
 		}
 	}
 	WARN(!(now-start),
 		"Warning: zero tsc calibration delta: %Ld [max: %Ld]\n",
 			now-start, end-start);
+	return cur_max_warp;
 }
 
 /*
@@ -128,23 +286,27 @@ void check_tsc_sync_source(int cpu)
 	if (unsynchronized_tsc())
 		return;
 
-	if (tsc_clocksource_reliable) {
-		if (cpu == (nr_cpu_ids-1) || system_state != SYSTEM_BOOTING)
-			pr_info(
-			"Skipped synchronization checks as TSC is reliable.\n");
-		return;
-	}
-
 	/*
-	 * Reset it - in case this is a second bootup:
+	 * Set the maximum number of test runs to
+	 *  1 if the CPU does not provide the TSC_ADJUST MSR
+	 *  3 if the MSR is available, so the target can try to adjust
 	 */
-	atomic_set(&stop_count, 0);
-
+	if (!boot_cpu_has(X86_FEATURE_TSC_ADJUST))
+		atomic_set(&test_runs, 1);
+	else
+		atomic_set(&test_runs, 3);
+retry:
 	/*
-	 * Wait for the target to arrive:
+	 * Wait for the target to start or to skip the test:
 	 */
-	while (atomic_read(&start_count) != cpus-1)
+	while (atomic_read(&start_count) != cpus - 1) {
+		if (atomic_read(&skip_test) > 0) {
+			atomic_set(&skip_test, 0);
+			return;
+		}
 		cpu_relax();
+	}
+
 	/*
 	 * Trigger the target to continue into the measurement too:
 	 */
@@ -155,21 +317,35 @@ void check_tsc_sync_source(int cpu)
 	while (atomic_read(&stop_count) != cpus-1)
 		cpu_relax();
 
-	if (nr_warps) {
+	/*
+	 * If the test was successful set the number of runs to zero and
+	 * stop. If not, decrement the number of runs an check if we can
+	 * retry. In case of random warps no retry is attempted.
+	 */
+	if (!nr_warps) {
+		atomic_set(&test_runs, 0);
+
+		pr_debug("TSC synchronization [CPU#%d -> CPU#%d]: passed\n",
+			smp_processor_id(), cpu);
+
+	} else if (atomic_dec_and_test(&test_runs) || random_warps) {
+		/* Force it to 0 if random warps brought us here */
+		atomic_set(&test_runs, 0);
+
 		pr_warning("TSC synchronization [CPU#%d -> CPU#%d]:\n",
 			smp_processor_id(), cpu);
 		pr_warning("Measured %Ld cycles TSC warp between CPUs, "
 			   "turning off TSC clock.\n", max_warp);
+		if (random_warps)
+			pr_warning("TSC warped randomly between CPUs\n");
 		mark_tsc_unstable("check_tsc_sync_source failed");
-	} else {
-		pr_debug("TSC synchronization [CPU#%d -> CPU#%d]: passed\n",
-			smp_processor_id(), cpu);
 	}
 
 	/*
 	 * Reset it - just in case we boot another CPU later:
 	 */
 	atomic_set(&start_count, 0);
+	random_warps = 0;
 	nr_warps = 0;
 	max_warp = 0;
 	last_tsc = 0;
@@ -178,6 +354,12 @@ void check_tsc_sync_source(int cpu)
 	 * Let the target continue with the bootup:
 	 */
 	atomic_inc(&stop_count);
+
+	/*
+	 * Retry, if there is a chance to do so.
+	 */
+	if (atomic_read(&test_runs) > 0)
+		goto retry;
 }
 
 /*
@@ -185,12 +367,30 @@ void check_tsc_sync_source(int cpu)
  */
 void check_tsc_sync_target(void)
 {
+	struct tsc_adjust *cur = this_cpu_ptr(&tsc_adjust);
+	unsigned int cpu = smp_processor_id();
+	cycles_t cur_max_warp, gbl_max_warp;
 	int cpus = 2;
 
 	/* Also aborts if there is no TSC. */
-	if (unsynchronized_tsc() || tsc_clocksource_reliable)
+	if (unsynchronized_tsc())
+		return;
+
+	/*
+	 * Store, verify and sanitize the TSC adjust register. If
+	 * successful skip the test.
+	 *
+	 * The test is also skipped when the TSC is marked reliable. This
+	 * is true for SoCs which have no fallback clocksource. On these
+	 * SoCs the TSC is frequency synchronized, but still the TSC ADJUST
+	 * register might have been wreckaged by the BIOS..
+	 */
+	if (tsc_store_and_check_tsc_adjust(false) || tsc_clocksource_reliable) {
+		atomic_inc(&skip_test);
 		return;
+	}
 
+retry:
 	/*
 	 * Register this CPU's participation and wait for the
 	 * source CPU to start the measurement:
@@ -199,7 +399,12 @@ void check_tsc_sync_target(void)
 	while (atomic_read(&start_count) != cpus)
 		cpu_relax();
 
-	check_tsc_warp(loop_timeout(smp_processor_id()));
+	cur_max_warp = check_tsc_warp(loop_timeout(cpu));
+
+	/*
+	 * Store the maximum observed warp value for a potential retry:
+	 */
+	gbl_max_warp = max_warp;
 
 	/*
 	 * Ok, we are done:
@@ -211,4 +416,61 @@ void check_tsc_sync_target(void)
 	 */
 	while (atomic_read(&stop_count) != cpus)
 		cpu_relax();
+
+	/*
+	 * Reset it for the next sync test:
+	 */
+	atomic_set(&stop_count, 0);
+
+	/*
+	 * Check the number of remaining test runs. If not zero, the test
+	 * failed and a retry with adjusted TSC is possible. If zero the
+	 * test was either successful or failed terminally.
+	 */
+	if (!atomic_read(&test_runs))
+		return;
+
+	/*
+	 * If the warp value of this CPU is 0, then the other CPU
+	 * observed time going backwards so this TSC was ahead and
+	 * needs to move backwards.
+	 */
+	if (!cur_max_warp)
+		cur_max_warp = -gbl_max_warp;
+
+	/*
+	 * Add the result to the previous adjustment value.
+	 *
+	 * The adjustement value is slightly off by the overhead of the
+	 * sync mechanism (observed values are ~200 TSC cycles), but this
+	 * really depends on CPU, node distance and frequency. So
+	 * compensating for this is hard to get right. Experiments show
+	 * that the warp is not longer detectable when the observed warp
+	 * value is used. In the worst case the adjustment needs to go
+	 * through a 3rd run for fine tuning.
+	 */
+	cur->adjusted += cur_max_warp;
+
+	/*
+	 * TSC deadline timer stops working or creates an interrupt storm
+	 * with adjust values < 0 and > x07ffffff.
+	 *
+	 * To allow adjust values > 0x7FFFFFFF we need to disable the
+	 * deadline timer and use the local APIC timer, but that requires
+	 * more intrusive changes and we do not have any useful information
+	 * from Intel about the underlying HW wreckage yet.
+	 */
+	if (cur->adjusted < 0)
+		cur->adjusted = 0;
+	if (cur->adjusted > 0x7FFFFFFF)
+		cur->adjusted = 0x7FFFFFFF;
+
+	pr_warn("TSC ADJUST compensate: CPU%u observed %lld warp. Adjust: %lld\n",
+		cpu, cur_max_warp, cur->adjusted);
+
+	wrmsrl(MSR_IA32_TSC_ADJUST, cur->adjusted);
+	goto retry;
+
 }
+
+#endif /* CONFIG_SMP */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/unwind_frame.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/unwind_frame.c
--- linux-libre-4.9-gnu/arch/x86/kernel/unwind_frame.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/unwind_frame.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,52 @@
 
 #define FRAME_HEADER_SIZE (sizeof(long) * 2)
 
+/*
+ * This disables KASAN checking when reading a value from another task's stack,
+ * since the other task could be running on another CPU and could have poisoned
+ * the stack in the meantime.
+ */
+#define READ_ONCE_TASK_STACK(task, x)			\
+({							\
+	unsigned long val;				\
+	if (task == current)				\
+		val = READ_ONCE(x);			\
+	else						\
+		val = READ_ONCE_NOCHECK(x);		\
+	val;						\
+})
+
+static void unwind_dump(struct unwind_state *state, unsigned long *sp)
+{
+	static bool dumped_before = false;
+	bool prev_zero, zero = false;
+	unsigned long word;
+
+	if (dumped_before)
+		return;
+
+	dumped_before = true;
+
+	printk_deferred("unwind stack type:%d next_sp:%p mask:%lx graph_idx:%d\n",
+			state->stack_info.type, state->stack_info.next_sp,
+			state->stack_mask, state->graph_idx);
+
+	for (sp = state->orig_sp; sp < state->stack_info.end; sp++) {
+		word = READ_ONCE_NOCHECK(*sp);
+
+		prev_zero = zero;
+		zero = word == 0;
+
+		if (zero) {
+			if (!prev_zero)
+				printk_deferred("%p: %016x ...\n", sp, 0);
+			continue;
+		}
+
+		printk_deferred("%p: %016lx (%pB)\n", sp, word, (void *)word);
+	}
+}
+
 unsigned long unwind_get_return_address(struct unwind_state *state)
 {
 	unsigned long addr;
@@ -14,17 +60,60 @@ unsigned long unwind_get_return_address(
 	if (unwind_done(state))
 		return 0;
 
-	addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, *addr_p,
+	if (state->regs && user_mode(state->regs))
+		return 0;
+
+	addr = READ_ONCE_TASK_STACK(state->task, *addr_p);
+	addr = ftrace_graph_ret_addr(state->task, &state->graph_idx, addr,
 				     addr_p);
 
 	return __kernel_text_address(addr) ? addr : 0;
 }
 EXPORT_SYMBOL_GPL(unwind_get_return_address);
 
+static size_t regs_size(struct pt_regs *regs)
+{
+	/* x86_32 regs from kernel mode are two words shorter: */
+	if (IS_ENABLED(CONFIG_X86_32) && !user_mode(regs))
+		return sizeof(*regs) - 2*sizeof(long);
+
+	return sizeof(*regs);
+}
+
+static bool is_last_task_frame(struct unwind_state *state)
+{
+	unsigned long bp = (unsigned long)state->bp;
+	unsigned long regs = (unsigned long)task_pt_regs(state->task);
+
+	/*
+	 * We have to check for the last task frame at two different locations
+	 * because gcc can occasionally decide to realign the stack pointer and
+	 * change the offset of the stack frame by a word in the prologue of a
+	 * function called by head/entry code.
+	 */
+	return bp == regs - FRAME_HEADER_SIZE ||
+	       bp == regs - FRAME_HEADER_SIZE - sizeof(long);
+}
+
+/*
+ * This determines if the frame pointer actually contains an encoded pointer to
+ * pt_regs on the stack.  See ENCODE_FRAME_POINTER.
+ */
+static struct pt_regs *decode_frame_pointer(unsigned long *bp)
+{
+	unsigned long regs = (unsigned long)bp;
+
+	if (!(regs & 0x1))
+		return NULL;
+
+	return (struct pt_regs *)(regs & ~0x1);
+}
+
 static bool update_stack_state(struct unwind_state *state, void *addr,
 			       size_t len)
 {
 	struct stack_info *info = &state->stack_info;
+	enum stack_type orig_type = info->type;
 
 	/*
 	 * If addr isn't on the current stack, switch to the next one.
@@ -38,31 +127,137 @@ static bool update_stack_state(struct un
 				   &state->stack_mask))
 			return false;
 
+	if (!state->orig_sp || info->type != orig_type)
+		state->orig_sp = addr;
+
 	return true;
 }
 
 bool unwind_next_frame(struct unwind_state *state)
 {
-	unsigned long *next_bp;
+	struct pt_regs *regs;
+	unsigned long *next_bp, *next_frame;
+	size_t next_len;
+	enum stack_type prev_type = state->stack_info.type;
 
 	if (unwind_done(state))
 		return false;
 
-	next_bp = (unsigned long *)*state->bp;
+	/* have we reached the end? */
+	if (state->regs && user_mode(state->regs))
+		goto the_end;
+
+	if (is_last_task_frame(state)) {
+		regs = task_pt_regs(state->task);
+
+		/*
+		 * kthreads (other than the boot CPU's idle thread) have some
+		 * partial regs at the end of their stack which were placed
+		 * there by copy_thread_tls().  But the regs don't have any
+		 * useful information, so we can skip them.
+		 *
+		 * This user_mode() check is slightly broader than a PF_KTHREAD
+		 * check because it also catches the awkward situation where a
+		 * newly forked kthread transitions into a user task by calling
+		 * do_execve(), which eventually clears PF_KTHREAD.
+		 */
+		if (!user_mode(regs))
+			goto the_end;
+
+		/*
+		 * We're almost at the end, but not quite: there's still the
+		 * syscall regs frame.  Entry code doesn't encode the regs
+		 * pointer for syscalls, so we have to set it manually.
+		 */
+		state->regs = regs;
+		state->bp = NULL;
+		return true;
+	}
+
+	/* get the next frame pointer */
+	if (state->regs)
+		next_bp = (unsigned long *)state->regs->bp;
+	else
+		next_bp = (unsigned long *)READ_ONCE_TASK_STACK(state->task,*state->bp);
+
+	/* is the next frame pointer an encoded pointer to pt_regs? */
+	regs = decode_frame_pointer(next_bp);
+	if (regs) {
+		next_frame = (unsigned long *)regs;
+		next_len = sizeof(*regs);
+	} else {
+		next_frame = next_bp;
+		next_len = FRAME_HEADER_SIZE;
+	}
 
 	/* make sure the next frame's data is accessible */
-	if (!update_stack_state(state, next_bp, FRAME_HEADER_SIZE))
-		return false;
+	if (!update_stack_state(state, next_frame, next_len)) {
+		/*
+		 * Don't warn on bad regs->bp.  An interrupt in entry code
+		 * might cause a false positive warning.
+		 */
+		if (state->regs)
+			goto the_end;
+
+		goto bad_address;
+	}
+
+	/* Make sure it only unwinds up and doesn't overlap the last frame: */
+	if (state->stack_info.type == prev_type) {
+		if (state->regs && (void *)next_frame < (void *)state->regs + regs_size(state->regs))
+			goto bad_address;
+
+		if (state->bp && (void *)next_frame < (void *)state->bp + FRAME_HEADER_SIZE)
+			goto bad_address;
+	}
 
 	/* move to the next frame */
-	state->bp = next_bp;
+	if (regs) {
+		state->regs = regs;
+		state->bp = NULL;
+	} else {
+		state->bp = next_bp;
+		state->regs = NULL;
+	}
+
 	return true;
+
+bad_address:
+	/*
+	 * When unwinding a non-current task, the task might actually be
+	 * running on another CPU, in which case it could be modifying its
+	 * stack while we're reading it.  This is generally not a problem and
+	 * can be ignored as long as the caller understands that unwinding
+	 * another task will not always succeed.
+	 */
+	if (state->task != current)
+		goto the_end;
+
+	if (state->regs) {
+		printk_deferred_once(KERN_WARNING
+			"WARNING: kernel stack regs at %p in %s:%d has bad 'bp' value %p\n",
+			state->regs, state->task->comm,
+			state->task->pid, next_frame);
+		unwind_dump(state, (unsigned long *)state->regs);
+	} else {
+		printk_deferred_once(KERN_WARNING
+			"WARNING: kernel stack frame pointer at %p in %s:%d has bad value %p\n",
+			state->bp, state->task->comm,
+			state->task->pid, next_frame);
+		unwind_dump(state, state->bp);
+	}
+the_end:
+	state->stack_info.type = STACK_TYPE_UNKNOWN;
+	return false;
 }
 EXPORT_SYMBOL_GPL(unwind_next_frame);
 
 void __unwind_start(struct unwind_state *state, struct task_struct *task,
 		    struct pt_regs *regs, unsigned long *first_frame)
 {
+	unsigned long *bp, *frame;
+	size_t len;
+
 	memset(state, 0, sizeof(*state));
 	state->task = task;
 
@@ -73,12 +268,22 @@ void __unwind_start(struct unwind_state
 	}
 
 	/* set up the starting stack frame */
-	state->bp = get_frame_pointer(task, regs);
+	bp = get_frame_pointer(task, regs);
+	regs = decode_frame_pointer(bp);
+	if (regs) {
+		state->regs = regs;
+		frame = (unsigned long *)regs;
+		len = sizeof(*regs);
+	} else {
+		state->bp = bp;
+		frame = bp;
+		len = FRAME_HEADER_SIZE;
+	}
 
 	/* initialize stack info and make sure the frame data is accessible */
-	get_stack_info(state->bp, state->task, &state->stack_info,
+	get_stack_info(frame, state->task, &state->stack_info,
 		       &state->stack_mask);
-	update_stack_state(state, state->bp, FRAME_HEADER_SIZE);
+	update_stack_state(state, frame, len);
 
 	/*
 	 * The caller can provide the address of the first frame directly
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/vm86_32.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/vm86_32.c
--- linux-libre-4.9-gnu/arch/x86/kernel/vm86_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/vm86_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@
 #include <linux/slab.h>
 #include <linux/security.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
 #include <asm/irq.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/vmlinux.lds.S linux-libre-4.10-rc8-gnu/arch/x86/kernel/vmlinux.lds.S
--- linux-libre-4.9-gnu/arch/x86/kernel/vmlinux.lds.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/vmlinux.lds.S	2017-02-12 16:03:20.000000000 -0500
@@ -91,10 +91,10 @@ SECTIONS
 	/* Text and read-only data */
 	.text :  AT(ADDR(.text) - LOAD_OFFSET) {
 		_text = .;
+		_stext = .;
 		/* bootstrapping code */
 		HEAD_TEXT
 		. = ALIGN(8);
-		_stext = .;
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kernel/x86_init.c linux-libre-4.10-rc8-gnu/arch/x86/kernel/x86_init.c
--- linux-libre-4.9-gnu/arch/x86/kernel/x86_init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kernel/x86_init.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,6 @@ struct x86_cpuinit_ops x86_cpuinit = {
 };
 
 static void default_nmi_init(void) { };
-static int default_i8042_detect(void) { return 1; };
 
 struct x86_platform_ops x86_platform __ro_after_init = {
 	.calibrate_cpu			= native_calibrate_cpu,
@@ -100,7 +99,6 @@ struct x86_platform_ops x86_platform __r
 	.is_untracked_pat_range		= is_ISA_range,
 	.nmi_init			= default_nmi_init,
 	.get_nmi_reason			= default_get_nmi_reason,
-	.i8042_detect			= default_i8042_detect,
 	.save_sched_clock_state 	= tsc_save_sched_clock_state,
 	.restore_sched_clock_state 	= tsc_restore_sched_clock_state,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/cpuid.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/cpuid.c
--- linux-libre-4.9-gnu/arch/x86/kvm/cpuid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/cpuid.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/export.h>
 #include <linux/vmalloc.h>
 #include <linux/uaccess.h>
-#include <asm/fpu/internal.h> /* For use_eager_fpu.  Ugh! */
+#include <asm/processor.h>
 #include <asm/user.h>
 #include <asm/fpu/xstate.h>
 #include "cpuid.h"
@@ -65,6 +65,11 @@ u64 kvm_supported_xcr0(void)
 
 #define F(x) bit(X86_FEATURE_##x)
 
+/* These are scattered features in cpufeatures.h. */
+#define KVM_CPUID_BIT_AVX512_4VNNIW     2
+#define KVM_CPUID_BIT_AVX512_4FMAPS     3
+#define KF(x) bit(KVM_CPUID_BIT_##x)
+
 int kvm_update_cpuid(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
@@ -81,6 +86,10 @@ int kvm_update_cpuid(struct kvm_vcpu *vc
 			best->ecx |= F(OSXSAVE);
 	}
 
+	best->edx &= ~F(APIC);
+	if (vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE)
+		best->edx |= F(APIC);
+
 	if (apic) {
 		if (best->ecx & F(TSC_DEADLINE_TIMER))
 			apic->lapic_timer.timer_mode_mask = 3 << 17;
@@ -114,8 +123,7 @@ int kvm_update_cpuid(struct kvm_vcpu *vc
 	if (best && (best->eax & (F(XSAVES) | F(XSAVEC))))
 		best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
 
-	if (use_eager_fpu())
-		kvm_x86_ops->fpu_activate(vcpu);
+	kvm_x86_ops->fpu_activate(vcpu);
 
 	/*
 	 * The existing code assumes virtual address is 48-bit in the canonical
@@ -365,16 +373,21 @@ static inline int __do_cpuid_ent(struct
 	const u32 kvm_cpuid_7_0_ebx_x86_features =
 		F(FSGSBASE) | F(BMI1) | F(HLE) | F(AVX2) | F(SMEP) |
 		F(BMI2) | F(ERMS) | f_invpcid | F(RTM) | f_mpx | F(RDSEED) |
-		F(ADX) | F(SMAP) | F(AVX512F) | F(AVX512PF) | F(AVX512ER) |
-		F(AVX512CD) | F(CLFLUSHOPT) | F(CLWB) | F(AVX512DQ) |
-		F(AVX512BW) | F(AVX512VL);
+		F(ADX) | F(SMAP) | F(AVX512IFMA) | F(AVX512F) | F(AVX512PF) |
+		F(AVX512ER) | F(AVX512CD) | F(CLFLUSHOPT) | F(CLWB) | F(AVX512DQ) |
+		F(SHA_NI) | F(AVX512BW) | F(AVX512VL);
 
 	/* cpuid 0xD.1.eax */
 	const u32 kvm_cpuid_D_1_eax_x86_features =
 		F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | f_xsaves;
 
 	/* cpuid 7.0.ecx*/
-	const u32 kvm_cpuid_7_0_ecx_x86_features = F(PKU) | 0 /*OSPKE*/;
+	const u32 kvm_cpuid_7_0_ecx_x86_features =
+		F(AVX512VBMI) | F(PKU) | 0 /*OSPKE*/;
+
+	/* cpuid 7.0.edx*/
+	const u32 kvm_cpuid_7_0_edx_x86_features =
+		KF(AVX512_4VNNIW) | KF(AVX512_4FMAPS);
 
 	/* all calls to cpuid_count() should be made on the same cpu */
 	get_cpu();
@@ -458,12 +471,14 @@ static inline int __do_cpuid_ent(struct
 			/* PKU is not yet implemented for shadow paging. */
 			if (!tdp_enabled)
 				entry->ecx &= ~F(PKU);
+			entry->edx &= kvm_cpuid_7_0_edx_x86_features;
+			entry->edx &= get_scattered_cpuid_leaf(7, 0, CPUID_EDX);
 		} else {
 			entry->ebx = 0;
 			entry->ecx = 0;
+			entry->edx = 0;
 		}
 		entry->eax = 0;
-		entry->edx = 0;
 		break;
 	}
 	case 9:
@@ -863,17 +878,17 @@ void kvm_cpuid(struct kvm_vcpu *vcpu, u3
 }
 EXPORT_SYMBOL_GPL(kvm_cpuid);
 
-void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
+int kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
 {
-	u32 function, eax, ebx, ecx, edx;
+	u32 eax, ebx, ecx, edx;
 
-	function = eax = kvm_register_read(vcpu, VCPU_REGS_RAX);
+	eax = kvm_register_read(vcpu, VCPU_REGS_RAX);
 	ecx = kvm_register_read(vcpu, VCPU_REGS_RCX);
 	kvm_cpuid(vcpu, &eax, &ebx, &ecx, &edx);
 	kvm_register_write(vcpu, VCPU_REGS_RAX, eax);
 	kvm_register_write(vcpu, VCPU_REGS_RBX, ebx);
 	kvm_register_write(vcpu, VCPU_REGS_RCX, ecx);
 	kvm_register_write(vcpu, VCPU_REGS_RDX, edx);
-	kvm_x86_ops->skip_emulated_instruction(vcpu);
+	return kvm_skip_emulated_instruction(vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/emulate.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/emulate.c
--- linux-libre-4.9-gnu/arch/x86/kvm/emulate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/emulate.c	2017-02-12 16:03:20.000000000 -0500
@@ -158,9 +158,11 @@
 #define Src2GS      (OpGS << Src2Shift)
 #define Src2Mask    (OpMask << Src2Shift)
 #define Mmx         ((u64)1 << 40)  /* MMX Vector instruction */
+#define AlignMask   ((u64)7 << 41)
 #define Aligned     ((u64)1 << 41)  /* Explicitly aligned (e.g. MOVDQA) */
-#define Unaligned   ((u64)1 << 42)  /* Explicitly unaligned (e.g. MOVDQU) */
-#define Avx         ((u64)1 << 43)  /* Advanced Vector Extensions */
+#define Unaligned   ((u64)2 << 41)  /* Explicitly unaligned (e.g. MOVDQU) */
+#define Avx         ((u64)3 << 41)  /* Advanced Vector Extensions */
+#define Aligned16   ((u64)4 << 41)  /* Aligned to 16 byte boundary (e.g. FXSAVE) */
 #define Fastop      ((u64)1 << 44)  /* Use opcode::u.fastop */
 #define NoWrite     ((u64)1 << 45)  /* No writeback */
 #define SrcWrite    ((u64)1 << 46)  /* Write back src operand */
@@ -446,6 +448,26 @@ FOP_END;
 FOP_START(salc) "pushf; sbb %al, %al; popf \n\t" FOP_RET
 FOP_END;
 
+/*
+ * XXX: inoutclob user must know where the argument is being expanded.
+ *      Relying on CC_HAVE_ASM_GOTO would allow us to remove _fault.
+ */
+#define asm_safe(insn, inoutclob...) \
+({ \
+	int _fault = 0; \
+ \
+	asm volatile("1:" insn "\n" \
+	             "2:\n" \
+	             ".pushsection .fixup, \"ax\"\n" \
+	             "3: movl $1, %[_fault]\n" \
+	             "   jmp  2b\n" \
+	             ".popsection\n" \
+	             _ASM_EXTABLE(1b, 3b) \
+	             : [_fault] "+qm"(_fault) inoutclob ); \
+ \
+	_fault ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; \
+})
+
 static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
 				    enum x86_intercept intercept,
 				    enum x86_intercept_stage stage)
@@ -632,21 +654,26 @@ static void set_segment_selector(struct
  * depending on whether they're AVX encoded or not.
  *
  * Also included is CMPXCHG16B which is not a vector instruction, yet it is
- * subject to the same check.
+ * subject to the same check.  FXSAVE and FXRSTOR are checked here too as their
+ * 512 bytes of data must be aligned to a 16 byte boundary.
  */
-static bool insn_aligned(struct x86_emulate_ctxt *ctxt, unsigned size)
+static unsigned insn_alignment(struct x86_emulate_ctxt *ctxt, unsigned size)
 {
+	u64 alignment = ctxt->d & AlignMask;
+
 	if (likely(size < 16))
-		return false;
+		return 1;
 
-	if (ctxt->d & Aligned)
-		return true;
-	else if (ctxt->d & Unaligned)
-		return false;
-	else if (ctxt->d & Avx)
-		return false;
-	else
-		return true;
+	switch (alignment) {
+	case Unaligned:
+	case Avx:
+		return 1;
+	case Aligned16:
+		return 16;
+	case Aligned:
+	default:
+		return size;
+	}
 }
 
 static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
@@ -704,7 +731,7 @@ static __always_inline int __linearize(s
 		}
 		break;
 	}
-	if (insn_aligned(ctxt, size) && ((la & (size - 1)) != 0))
+	if (la & (insn_alignment(ctxt, size) - 1))
 		return emulate_gp(ctxt, 0);
 	return X86EMUL_CONTINUE;
 bad:
@@ -791,6 +818,20 @@ static int segmented_read_std(struct x86
 	return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
 }
 
+static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
+			       struct segmented_address addr,
+			       void *data,
+			       unsigned int size)
+{
+	int rc;
+	ulong linear;
+
+	rc = linearize(ctxt, addr, size, true, &linear);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+	return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
+}
+
 /*
  * Prefetch the remaining bytes of the instruction without crossing page
  * boundary if they are not in fetch_cache yet.
@@ -1544,7 +1585,6 @@ static int write_segment_descriptor(stru
 				    &ctxt->exception);
 }
 
-/* Does not support long mode */
 static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 				     u16 selector, int seg, u8 cpl,
 				     enum x86_transfer_type transfer,
@@ -1581,20 +1621,34 @@ static int __load_segment_descriptor(str
 
 	rpl = selector & 3;
 
-	/* NULL selector is not valid for TR, CS and SS (except for long mode) */
-	if ((seg == VCPU_SREG_CS
-	     || (seg == VCPU_SREG_SS
-		 && (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl))
-	     || seg == VCPU_SREG_TR)
-	    && null_selector)
-		goto exception;
-
 	/* TR should be in GDT only */
 	if (seg == VCPU_SREG_TR && (selector & (1 << 2)))
 		goto exception;
 
-	if (null_selector) /* for NULL selector skip all following checks */
+	/* NULL selector is not valid for TR, CS and (except for long mode) SS */
+	if (null_selector) {
+		if (seg == VCPU_SREG_CS || seg == VCPU_SREG_TR)
+			goto exception;
+
+		if (seg == VCPU_SREG_SS) {
+			if (ctxt->mode != X86EMUL_MODE_PROT64 || rpl != cpl)
+				goto exception;
+
+			/*
+			 * ctxt->ops->set_segment expects the CPL to be in
+			 * SS.DPL, so fake an expand-up 32-bit data segment.
+			 */
+			seg_desc.type = 3;
+			seg_desc.p = 1;
+			seg_desc.s = 1;
+			seg_desc.dpl = cpl;
+			seg_desc.d = 1;
+			seg_desc.g = 1;
+		}
+
+		/* Skip all following checks */
 		goto load;
+	}
 
 	ret = read_segment_descriptor(ctxt, selector, &seg_desc, &desc_addr);
 	if (ret != X86EMUL_CONTINUE)
@@ -1710,6 +1764,21 @@ static int load_segment_descriptor(struc
 				   u16 selector, int seg)
 {
 	u8 cpl = ctxt->ops->cpl(ctxt);
+
+	/*
+	 * None of MOV, POP and LSS can load a NULL selector in CPL=3, but
+	 * they can load it at CPL<3 (Intel's manual says only LSS can,
+	 * but it's wrong).
+	 *
+	 * However, the Intel manual says that putting IST=1/DPL=3 in
+	 * an interrupt gate will result in SS=3 (the AMD manual instead
+	 * says it doesn't), so allow SS=3 in __load_segment_descriptor
+	 * and only forbid it here.
+	 */
+	if (seg == VCPU_SREG_SS && selector == 3 &&
+	    ctxt->mode == X86EMUL_MODE_PROT64)
+		return emulate_exception(ctxt, GP_VECTOR, 0, true);
+
 	return __load_segment_descriptor(ctxt, selector, seg, cpl,
 					 X86_TRANSFER_NONE, NULL);
 }
@@ -3658,8 +3727,8 @@ static int emulate_store_desc_ptr(struct
 	}
 	/* Disable writeback. */
 	ctxt->dst.type = OP_NONE;
-	return segmented_write(ctxt, ctxt->dst.addr.mem,
-			       &desc_ptr, 2 + ctxt->op_bytes);
+	return segmented_write_std(ctxt, ctxt->dst.addr.mem,
+				   &desc_ptr, 2 + ctxt->op_bytes);
 }
 
 static int em_sgdt(struct x86_emulate_ctxt *ctxt)
@@ -3842,6 +3911,131 @@ static int em_movsxd(struct x86_emulate_
 	return X86EMUL_CONTINUE;
 }
 
+static int check_fxsr(struct x86_emulate_ctxt *ctxt)
+{
+	u32 eax = 1, ebx, ecx = 0, edx;
+
+	ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx);
+	if (!(edx & FFL(FXSR)))
+		return emulate_ud(ctxt);
+
+	if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM))
+		return emulate_nm(ctxt);
+
+	/*
+	 * Don't emulate a case that should never be hit, instead of working
+	 * around a lack of fxsave64/fxrstor64 on old compilers.
+	 */
+	if (ctxt->mode >= X86EMUL_MODE_PROT64)
+		return X86EMUL_UNHANDLEABLE;
+
+	return X86EMUL_CONTINUE;
+}
+
+/*
+ * FXSAVE and FXRSTOR have 4 different formats depending on execution mode,
+ *  1) 16 bit mode
+ *  2) 32 bit mode
+ *     - like (1), but FIP and FDP (foo) are only 16 bit.  At least Intel CPUs
+ *       preserve whole 32 bit values, though, so (1) and (2) are the same wrt.
+ *       save and restore
+ *  3) 64-bit mode with REX.W prefix
+ *     - like (2), but XMM 8-15 are being saved and restored
+ *  4) 64-bit mode without REX.W prefix
+ *     - like (3), but FIP and FDP are 64 bit
+ *
+ * Emulation uses (3) for (1) and (2) and preserves XMM 8-15 to reach the
+ * desired result.  (4) is not emulated.
+ *
+ * Note: Guest and host CPUID.(EAX=07H,ECX=0H):EBX[bit 13] (deprecate FPU CS
+ * and FPU DS) should match.
+ */
+static int em_fxsave(struct x86_emulate_ctxt *ctxt)
+{
+	struct fxregs_state fx_state;
+	size_t size;
+	int rc;
+
+	rc = check_fxsr(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	ctxt->ops->get_fpu(ctxt);
+
+	rc = asm_safe("fxsave %[fx]", , [fx] "+m"(fx_state));
+
+	ctxt->ops->put_fpu(ctxt);
+
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	if (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR)
+		size = offsetof(struct fxregs_state, xmm_space[8 * 16/4]);
+	else
+		size = offsetof(struct fxregs_state, xmm_space[0]);
+
+	return segmented_write_std(ctxt, ctxt->memop.addr.mem, &fx_state, size);
+}
+
+static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
+		struct fxregs_state *new)
+{
+	int rc = X86EMUL_CONTINUE;
+	struct fxregs_state old;
+
+	rc = asm_safe("fxsave %[fx]", , [fx] "+m"(old));
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	/*
+	 * 64 bit host will restore XMM 8-15, which is not correct on non-64
+	 * bit guests.  Load the current values in order to preserve 64 bit
+	 * XMMs after fxrstor.
+	 */
+#ifdef CONFIG_X86_64
+	/* XXX: accessing XMM 8-15 very awkwardly */
+	memcpy(&new->xmm_space[8 * 16/4], &old.xmm_space[8 * 16/4], 8 * 16);
+#endif
+
+	/*
+	 * Hardware doesn't save and restore XMM 0-7 without CR4.OSFXSR, but
+	 * does save and restore MXCSR.
+	 */
+	if (!(ctxt->ops->get_cr(ctxt, 4) & X86_CR4_OSFXSR))
+		memcpy(new->xmm_space, old.xmm_space, 8 * 16);
+
+	return rc;
+}
+
+static int em_fxrstor(struct x86_emulate_ctxt *ctxt)
+{
+	struct fxregs_state fx_state;
+	int rc;
+
+	rc = check_fxsr(ctxt);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	rc = segmented_read_std(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
+
+	if (fx_state.mxcsr >> 16)
+		return emulate_gp(ctxt, 0);
+
+	ctxt->ops->get_fpu(ctxt);
+
+	if (ctxt->mode < X86EMUL_MODE_PROT64)
+		rc = fxrstor_fixup(ctxt, &fx_state);
+
+	if (rc == X86EMUL_CONTINUE)
+		rc = asm_safe("fxrstor %[fx]", : [fx] "m"(fx_state));
+
+	ctxt->ops->put_fpu(ctxt);
+
+	return rc;
+}
+
 static bool valid_cr(int nr)
 {
 	switch (nr) {
@@ -4194,7 +4388,9 @@ static const struct gprefix pfx_0f_ae_7
 };
 
 static const struct group_dual group15 = { {
-	N, N, N, N, N, N, N, GP(0, &pfx_0f_ae_7),
+	I(ModRM | Aligned16, em_fxsave),
+	I(ModRM | Aligned16, em_fxrstor),
+	N, N, N, N, N, GP(0, &pfx_0f_ae_7),
 }, {
 	N, N, N, N, N, N, N, N,
 } };
@@ -5066,21 +5262,13 @@ static bool string_insn_completed(struct
 
 static int flush_pending_x87_faults(struct x86_emulate_ctxt *ctxt)
 {
-	bool fault = false;
+	int rc;
 
 	ctxt->ops->get_fpu(ctxt);
-	asm volatile("1: fwait \n\t"
-		     "2: \n\t"
-		     ".pushsection .fixup,\"ax\" \n\t"
-		     "3: \n\t"
-		     "movb $1, %[fault] \n\t"
-		     "jmp 2b \n\t"
-		     ".popsection \n\t"
-		     _ASM_EXTABLE(1b, 3b)
-		     : [fault]"+qm"(fault));
+	rc = asm_safe("fwait");
 	ctxt->ops->put_fpu(ctxt);
 
-	if (unlikely(fault))
+	if (unlikely(rc != X86EMUL_CONTINUE))
 		return emulate_exception(ctxt, MF_VECTOR, 0, false);
 
 	return X86EMUL_CONTINUE;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/hyperv.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/hyperv.c
--- linux-libre-4.9-gnu/arch/x86/kvm/hyperv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/hyperv.c	2017-02-12 16:03:20.000000000 -0500
@@ -291,7 +291,7 @@ static int synic_get_msr(struct kvm_vcpu
 	return ret;
 }
 
-int synic_set_irq(struct kvm_vcpu_hv_synic *synic, u32 sint)
+static int synic_set_irq(struct kvm_vcpu_hv_synic *synic, u32 sint)
 {
 	struct kvm_vcpu *vcpu = synic_to_vcpu(synic);
 	struct kvm_lapic_irq irq;
@@ -852,6 +852,10 @@ void kvm_hv_setup_tsc_page(struct kvm *k
 	if (!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))
 		return;
 
+	mutex_lock(&kvm->arch.hyperv.hv_lock);
+	if (!(hv->hv_tsc_page & HV_X64_MSR_TSC_REFERENCE_ENABLE))
+		goto out_unlock;
+
 	gfn = hv->hv_tsc_page >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
 	/*
 	 * Because the TSC parameters only vary when there is a
@@ -859,7 +863,7 @@ void kvm_hv_setup_tsc_page(struct kvm *k
 	 */
 	if (unlikely(kvm_read_guest(kvm, gfn_to_gpa(gfn),
 				    &tsc_seq, sizeof(tsc_seq))))
-		return;
+		goto out_unlock;
 
 	/*
 	 * While we're computing and writing the parameters, force the
@@ -868,15 +872,15 @@ void kvm_hv_setup_tsc_page(struct kvm *k
 	hv->tsc_ref.tsc_sequence = 0;
 	if (kvm_write_guest(kvm, gfn_to_gpa(gfn),
 			    &hv->tsc_ref, sizeof(hv->tsc_ref.tsc_sequence)))
-		return;
+		goto out_unlock;
 
 	if (!compute_tsc_page_parameters(hv_clock, &hv->tsc_ref))
-		return;
+		goto out_unlock;
 
 	/* Ensure sequence is zero before writing the rest of the struct.  */
 	smp_wmb();
 	if (kvm_write_guest(kvm, gfn_to_gpa(gfn), &hv->tsc_ref, sizeof(hv->tsc_ref)))
-		return;
+		goto out_unlock;
 
 	/*
 	 * Now switch to the TSC page mechanism by writing the sequence.
@@ -891,6 +895,8 @@ void kvm_hv_setup_tsc_page(struct kvm *k
 	hv->tsc_ref.tsc_sequence = tsc_seq;
 	kvm_write_guest(kvm, gfn_to_gpa(gfn),
 			&hv->tsc_ref, sizeof(hv->tsc_ref.tsc_sequence));
+out_unlock:
+	mutex_unlock(&kvm->arch.hyperv.hv_lock);
 }
 
 static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data,
@@ -1142,9 +1148,9 @@ int kvm_hv_set_msr_common(struct kvm_vcp
 	if (kvm_hv_msr_partition_wide(msr)) {
 		int r;
 
-		mutex_lock(&vcpu->kvm->lock);
+		mutex_lock(&vcpu->kvm->arch.hyperv.hv_lock);
 		r = kvm_hv_set_msr_pw(vcpu, msr, data, host);
-		mutex_unlock(&vcpu->kvm->lock);
+		mutex_unlock(&vcpu->kvm->arch.hyperv.hv_lock);
 		return r;
 	} else
 		return kvm_hv_set_msr(vcpu, msr, data, host);
@@ -1155,9 +1161,9 @@ int kvm_hv_get_msr_common(struct kvm_vcp
 	if (kvm_hv_msr_partition_wide(msr)) {
 		int r;
 
-		mutex_lock(&vcpu->kvm->lock);
+		mutex_lock(&vcpu->kvm->arch.hyperv.hv_lock);
 		r = kvm_hv_get_msr_pw(vcpu, msr, pdata);
-		mutex_unlock(&vcpu->kvm->lock);
+		mutex_unlock(&vcpu->kvm->arch.hyperv.hv_lock);
 		return r;
 	} else
 		return kvm_hv_get_msr(vcpu, msr, pdata);
@@ -1165,7 +1171,7 @@ int kvm_hv_get_msr_common(struct kvm_vcp
 
 bool kvm_hv_hypercall_enabled(struct kvm *kvm)
 {
-	return kvm->arch.hyperv.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
+	return READ_ONCE(kvm->arch.hyperv.hv_hypercall) & HV_X64_MSR_HYPERCALL_ENABLE;
 }
 
 static void kvm_hv_hypercall_set_result(struct kvm_vcpu *vcpu, u64 result)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/i8254.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/i8254.c
--- linux-libre-4.9-gnu/arch/x86/kvm/i8254.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/i8254.c	2017-02-12 16:03:20.000000000 -0500
@@ -212,7 +212,7 @@ static void kvm_pit_ack_irq(struct kvm_i
 	 */
 	smp_mb();
 	if (atomic_dec_if_positive(&ps->pending) > 0)
-		kthread_queue_work(&pit->worker, &pit->expired);
+		kthread_queue_work(pit->worker, &pit->expired);
 }
 
 void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
@@ -272,7 +272,7 @@ static enum hrtimer_restart pit_timer_fn
 	if (atomic_read(&ps->reinject))
 		atomic_inc(&ps->pending);
 
-	kthread_queue_work(&pt->worker, &pt->expired);
+	kthread_queue_work(pt->worker, &pt->expired);
 
 	if (ps->is_periodic) {
 		hrtimer_add_expires_ns(&ps->timer, ps->period);
@@ -667,10 +667,8 @@ struct kvm_pit *kvm_create_pit(struct kv
 	pid_nr = pid_vnr(pid);
 	put_pid(pid);
 
-	kthread_init_worker(&pit->worker);
-	pit->worker_task = kthread_run(kthread_worker_fn, &pit->worker,
-				       "kvm-pit/%d", pid_nr);
-	if (IS_ERR(pit->worker_task))
+	pit->worker = kthread_create_worker(0, "kvm-pit/%d", pid_nr);
+	if (IS_ERR(pit->worker))
 		goto fail_kthread;
 
 	kthread_init_work(&pit->expired, pit_do_work);
@@ -713,7 +711,7 @@ fail_register_speaker:
 fail_register_pit:
 	mutex_unlock(&kvm->slots_lock);
 	kvm_pit_set_reinject(pit, false);
-	kthread_stop(pit->worker_task);
+	kthread_destroy_worker(pit->worker);
 fail_kthread:
 	kvm_free_irq_source_id(kvm, pit->irq_source_id);
 fail_request:
@@ -730,8 +728,7 @@ void kvm_free_pit(struct kvm *kvm)
 		kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &pit->speaker_dev);
 		kvm_pit_set_reinject(pit, false);
 		hrtimer_cancel(&pit->pit_state.timer);
-		kthread_flush_work(&pit->expired);
-		kthread_stop(pit->worker_task);
+		kthread_destroy_worker(pit->worker);
 		kvm_free_irq_source_id(kvm, pit->irq_source_id);
 		kfree(pit);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/i8254.h linux-libre-4.10-rc8-gnu/arch/x86/kvm/i8254.h
--- linux-libre-4.9-gnu/arch/x86/kvm/i8254.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/i8254.h	2017-02-12 16:03:20.000000000 -0500
@@ -44,8 +44,7 @@ struct kvm_pit {
 	struct kvm_kpit_state pit_state;
 	int irq_source_id;
 	struct kvm_irq_mask_notifier mask_notifier;
-	struct kthread_worker worker;
-	struct task_struct *worker_task;
+	struct kthread_worker *worker;
 	struct kthread_work expired;
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/lapic.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/lapic.c
--- linux-libre-4.9-gnu/arch/x86/kvm/lapic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/lapic.c	2017-02-12 16:03:20.000000000 -0500
@@ -342,9 +342,11 @@ void __kvm_apic_update_irr(u32 *pir, voi
 	u32 i, pir_val;
 
 	for (i = 0; i <= 7; i++) {
-		pir_val = xchg(&pir[i], 0);
-		if (pir_val)
+		pir_val = READ_ONCE(pir[i]);
+		if (pir_val) {
+			pir_val = xchg(&pir[i], 0);
 			*((u32 *)(regs + APIC_IRR + i * 0x10)) |= pir_val;
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(__kvm_apic_update_irr);
@@ -1090,7 +1092,7 @@ static void apic_send_ipi(struct kvm_lap
 
 static u32 apic_get_tmcct(struct kvm_lapic *apic)
 {
-	ktime_t remaining;
+	ktime_t remaining, now;
 	s64 ns;
 	u32 tmcct;
 
@@ -1101,9 +1103,10 @@ static u32 apic_get_tmcct(struct kvm_lap
 		apic->lapic_timer.period == 0)
 		return 0;
 
-	remaining = hrtimer_get_remaining(&apic->lapic_timer.timer);
+	now = ktime_get();
+	remaining = ktime_sub(apic->lapic_timer.target_expiration, now);
 	if (ktime_to_ns(remaining) < 0)
-		remaining = ktime_set(0, 0);
+		remaining = 0;
 
 	ns = mod_64(ktime_to_ns(remaining), apic->lapic_timer.period);
 	tmcct = div64_u64(ns,
@@ -1332,7 +1335,7 @@ static void start_sw_tscdeadline(struct
 
 	local_irq_save(flags);
 
-	now = apic->lapic_timer.timer.base->get_time();
+	now = ktime_get();
 	guest_tsc = kvm_read_l1_tsc(vcpu, rdtsc());
 	if (likely(tscdeadline > guest_tsc)) {
 		ns = (tscdeadline - guest_tsc) * 1000000ULL;
@@ -1347,6 +1350,79 @@ static void start_sw_tscdeadline(struct
 	local_irq_restore(flags);
 }
 
+static void start_sw_period(struct kvm_lapic *apic)
+{
+	if (!apic->lapic_timer.period)
+		return;
+
+	if (apic_lvtt_oneshot(apic) &&
+	    ktime_after(ktime_get(),
+			apic->lapic_timer.target_expiration)) {
+		apic_timer_expired(apic);
+		return;
+	}
+
+	hrtimer_start(&apic->lapic_timer.timer,
+		apic->lapic_timer.target_expiration,
+		HRTIMER_MODE_ABS_PINNED);
+}
+
+static bool set_target_expiration(struct kvm_lapic *apic)
+{
+	ktime_t now;
+	u64 tscl = rdtsc();
+
+	now = ktime_get();
+	apic->lapic_timer.period = (u64)kvm_lapic_get_reg(apic, APIC_TMICT)
+		* APIC_BUS_CYCLE_NS * apic->divide_count;
+
+	if (!apic->lapic_timer.period)
+		return false;
+
+	/*
+	 * 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;
+
+		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;
+		}
+	}
+
+	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__,
+		   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
+		   kvm_lapic_get_reg(apic, APIC_TMICT),
+		   apic->lapic_timer.period,
+		   ktime_to_ns(ktime_add_ns(now,
+				apic->lapic_timer.period)));
+
+	apic->lapic_timer.tscdeadline = kvm_read_l1_tsc(apic->vcpu, tscl) +
+		nsec_to_cycles(apic->vcpu, apic->lapic_timer.period);
+	apic->lapic_timer.target_expiration = ktime_add_ns(now, apic->lapic_timer.period);
+
+	return true;
+}
+
+static void advance_periodic_target_expiration(struct kvm_lapic *apic)
+{
+	apic->lapic_timer.tscdeadline +=
+		nsec_to_cycles(apic->vcpu, apic->lapic_timer.period);
+	apic->lapic_timer.target_expiration =
+		ktime_add_ns(apic->lapic_timer.target_expiration,
+				apic->lapic_timer.period);
+}
+
 bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
 {
 	if (!lapic_in_kernel(vcpu))
@@ -1356,52 +1432,59 @@ bool kvm_lapic_hv_timer_in_use(struct kv
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_hv_timer_in_use);
 
-static void cancel_hv_tscdeadline(struct kvm_lapic *apic)
+static void cancel_hv_timer(struct kvm_lapic *apic)
 {
 	kvm_x86_ops->cancel_hv_timer(apic->vcpu);
 	apic->lapic_timer.hv_timer_in_use = false;
 }
 
-void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu)
-{
-	struct kvm_lapic *apic = vcpu->arch.apic;
-
-	WARN_ON(!apic->lapic_timer.hv_timer_in_use);
-	WARN_ON(swait_active(&vcpu->wq));
-	cancel_hv_tscdeadline(apic);
-	apic_timer_expired(apic);
-}
-EXPORT_SYMBOL_GPL(kvm_lapic_expired_hv_timer);
-
-static bool start_hv_tscdeadline(struct kvm_lapic *apic)
+static bool start_hv_timer(struct kvm_lapic *apic)
 {
 	u64 tscdeadline = apic->lapic_timer.tscdeadline;
 
-	if (atomic_read(&apic->lapic_timer.pending) ||
+	if ((atomic_read(&apic->lapic_timer.pending) &&
+		!apic_lvtt_period(apic)) ||
 		kvm_x86_ops->set_hv_timer(apic->vcpu, tscdeadline)) {
 		if (apic->lapic_timer.hv_timer_in_use)
-			cancel_hv_tscdeadline(apic);
+			cancel_hv_timer(apic);
 	} else {
 		apic->lapic_timer.hv_timer_in_use = true;
 		hrtimer_cancel(&apic->lapic_timer.timer);
 
 		/* In case the sw timer triggered in the window */
-		if (atomic_read(&apic->lapic_timer.pending))
-			cancel_hv_tscdeadline(apic);
+		if (atomic_read(&apic->lapic_timer.pending) &&
+			!apic_lvtt_period(apic))
+			cancel_hv_timer(apic);
 	}
 	trace_kvm_hv_timer_state(apic->vcpu->vcpu_id,
 			apic->lapic_timer.hv_timer_in_use);
 	return apic->lapic_timer.hv_timer_in_use;
 }
 
+void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	WARN_ON(!apic->lapic_timer.hv_timer_in_use);
+	WARN_ON(swait_active(&vcpu->wq));
+	cancel_hv_timer(apic);
+	apic_timer_expired(apic);
+
+	if (apic_lvtt_period(apic) && apic->lapic_timer.period) {
+		advance_periodic_target_expiration(apic);
+		if (!start_hv_timer(apic))
+			start_sw_period(apic);
+	}
+}
+EXPORT_SYMBOL_GPL(kvm_lapic_expired_hv_timer);
+
 void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
 	WARN_ON(apic->lapic_timer.hv_timer_in_use);
 
-	if (apic_lvtt_tscdeadline(apic))
-		start_hv_tscdeadline(apic);
+	start_hv_timer(apic);
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_hv_timer);
 
@@ -1413,62 +1496,28 @@ void kvm_lapic_switch_to_sw_timer(struct
 	if (!apic->lapic_timer.hv_timer_in_use)
 		return;
 
-	cancel_hv_tscdeadline(apic);
+	cancel_hv_timer(apic);
 
 	if (atomic_read(&apic->lapic_timer.pending))
 		return;
 
-	start_sw_tscdeadline(apic);
+	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic))
+		start_sw_period(apic);
+	else if (apic_lvtt_tscdeadline(apic))
+		start_sw_tscdeadline(apic);
 }
 EXPORT_SYMBOL_GPL(kvm_lapic_switch_to_sw_timer);
 
 static void start_apic_timer(struct kvm_lapic *apic)
 {
-	ktime_t now;
-
 	atomic_set(&apic->lapic_timer.pending, 0);
 
 	if (apic_lvtt_period(apic) || apic_lvtt_oneshot(apic)) {
-		/* lapic timer in oneshot or periodic mode */
-		now = apic->lapic_timer.timer.base->get_time();
-		apic->lapic_timer.period = (u64)kvm_lapic_get_reg(apic, APIC_TMICT)
-			    * APIC_BUS_CYCLE_NS * apic->divide_count;
-
-		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;
-
-			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_PINNED);
-
-		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__,
-			   APIC_BUS_CYCLE_NS, ktime_to_ns(now),
-			   kvm_lapic_get_reg(apic, APIC_TMICT),
-			   apic->lapic_timer.period,
-			   ktime_to_ns(ktime_add_ns(now,
-					apic->lapic_timer.period)));
+		if (set_target_expiration(apic) &&
+			!(kvm_x86_ops->set_hv_timer && start_hv_timer(apic)))
+			start_sw_period(apic);
 	} else if (apic_lvtt_tscdeadline(apic)) {
-		if (!(kvm_x86_ops->set_hv_timer && start_hv_tscdeadline(apic)))
+		if (!(kvm_x86_ops->set_hv_timer && start_hv_timer(apic)))
 			start_sw_tscdeadline(apic);
 	}
 }
@@ -1701,13 +1750,22 @@ void kvm_free_lapic(struct kvm_vcpu *vcp
  * LAPIC interface
  *----------------------------------------------------------------------
  */
+u64 kvm_get_lapic_target_expiration_tsc(struct kvm_vcpu *vcpu)
+{
+	struct kvm_lapic *apic = vcpu->arch.apic;
+
+	if (!lapic_in_kernel(vcpu))
+		return 0;
+
+	return apic->lapic_timer.tscdeadline;
+}
 
 u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (!lapic_in_kernel(vcpu) || apic_lvtt_oneshot(apic) ||
-			apic_lvtt_period(apic))
+	if (!lapic_in_kernel(vcpu) ||
+		!apic_lvtt_tscdeadline(apic))
 		return 0;
 
 	return apic->lapic_timer.tscdeadline;
@@ -1748,14 +1806,17 @@ void kvm_lapic_set_base(struct kvm_vcpu
 	u64 old_value = vcpu->arch.apic_base;
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (!apic) {
+	if (!apic)
 		value |= MSR_IA32_APICBASE_BSP;
-		vcpu->arch.apic_base = value;
-		return;
-	}
 
 	vcpu->arch.apic_base = value;
 
+	if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE)
+		kvm_update_cpuid(vcpu);
+
+	if (!apic)
+		return;
+
 	/* update jump label if enable bit changes */
 	if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE) {
 		if (value & MSR_IA32_APICBASE_ENABLE) {
@@ -1909,6 +1970,7 @@ static enum hrtimer_restart apic_timer_f
 	apic_timer_expired(apic);
 
 	if (lapic_is_periodic(apic)) {
+		advance_periodic_target_expiration(apic);
 		hrtimer_add_expires_ns(&ktimer->timer, ktimer->period);
 		return HRTIMER_RESTART;
 	} else
@@ -1993,6 +2055,10 @@ void kvm_inject_apic_timer_irqs(struct k
 		kvm_apic_local_deliver(apic, APIC_LVTT);
 		if (apic_lvtt_tscdeadline(apic))
 			apic->lapic_timer.tscdeadline = 0;
+		if (apic_lvtt_oneshot(apic)) {
+			apic->lapic_timer.tscdeadline = 0;
+			apic->lapic_timer.target_expiration = 0;
+		}
 		atomic_set(&apic->lapic_timer.pending, 0);
 	}
 }
@@ -2360,3 +2426,9 @@ void kvm_lapic_init(void)
 	jump_label_rate_limit(&apic_hw_disabled, HZ);
 	jump_label_rate_limit(&apic_sw_disabled, HZ);
 }
+
+void kvm_lapic_exit(void)
+{
+	static_key_deferred_flush(&apic_hw_disabled);
+	static_key_deferred_flush(&apic_sw_disabled);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/lapic.h linux-libre-4.10-rc8-gnu/arch/x86/kvm/lapic.h
--- linux-libre-4.9-gnu/arch/x86/kvm/lapic.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/lapic.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 struct kvm_timer {
 	struct hrtimer timer;
 	s64 period; 				/* unit: ns */
+	ktime_t target_expiration;
 	u32 timer_mode;
 	u32 timer_mode_mask;
 	u64 tscdeadline;
@@ -85,6 +86,7 @@ int kvm_apic_get_state(struct kvm_vcpu *
 int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
+u64 kvm_get_lapic_target_expiration_tsc(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);
 
@@ -108,6 +110,7 @@ static inline bool kvm_hv_vapic_assist_p
 
 int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
 void kvm_lapic_init(void);
+void kvm_lapic_exit(void);
 
 #define VEC_POS(v) ((v) & (32 - 1))
 #define REG_POS(v) (((v) >> 5) << 4)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/mmu.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/mmu.c
--- linux-libre-4.9-gnu/arch/x86/kvm/mmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/mmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -1660,17 +1660,9 @@ int kvm_age_hva(struct kvm *kvm, unsigne
 	 * This has some overhead, but not as much as the cost of swapping
 	 * out actively used pages or breaking up actively used hugepages.
 	 */
-	if (!shadow_accessed_mask) {
-		/*
-		 * We are holding the kvm->mmu_lock, and we are blowing up
-		 * shadow PTEs. MMU notifier consumers need to be kept at bay.
-		 * This is correct as long as we don't decouple the mmu_lock
-		 * protected regions (like invalidate_range_start|end does).
-		 */
-		kvm->mmu_notifier_seq++;
+	if (!shadow_accessed_mask)
 		return kvm_handle_hva_range(kvm, start, end, 0,
 					    kvm_unmap_rmapp);
-	}
 
 	return kvm_handle_hva_range(kvm, start, end, 0, kvm_age_rmapp);
 }
@@ -4405,7 +4397,8 @@ static u64 *get_written_sptes(struct kvm
 }
 
 static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-			      const u8 *new, int bytes)
+			      const u8 *new, int bytes,
+			      struct kvm_page_track_notifier_node *node)
 {
 	gfn_t gfn = gpa >> PAGE_SHIFT;
 	struct kvm_mmu_page *sp;
@@ -4508,7 +4501,7 @@ static void make_mmu_pages_available(str
 	kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
 }
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u32 error_code,
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
 		       void *insn, int insn_len)
 {
 	int r, emulation_type = EMULTYPE_RETRY;
@@ -4527,12 +4520,28 @@ int kvm_mmu_page_fault(struct kvm_vcpu *
 			return r;
 	}
 
-	r = vcpu->arch.mmu.page_fault(vcpu, cr2, error_code, false);
+	r = vcpu->arch.mmu.page_fault(vcpu, cr2, lower_32_bits(error_code),
+				      false);
 	if (r < 0)
 		return r;
 	if (!r)
 		return 1;
 
+	/*
+	 * Before emulating the instruction, check if the error code
+	 * was due to a RO violation while translating the guest page.
+	 * This can occur when using nested virtualization with nested
+	 * paging in both guests. If true, we simply unprotect the page
+	 * and resume the guest.
+	 *
+	 * Note: AMD only (since it supports the PFERR_GUEST_PAGE_MASK used
+	 *       in PFERR_NEXT_GUEST_PAGE)
+	 */
+	if (error_code == PFERR_NESTED_GUEST_PAGE) {
+		kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(cr2));
+		return 1;
+	}
+
 	if (mmio_info_in_cache(vcpu, cr2, direct))
 		emulation_type = 0;
 emulate:
@@ -4617,11 +4626,19 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu
 	init_kvm_mmu(vcpu);
 }
 
+static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
+			struct kvm_memory_slot *slot,
+			struct kvm_page_track_notifier_node *node)
+{
+	kvm_mmu_invalidate_zap_all_pages(kvm);
+}
+
 void kvm_mmu_init_vm(struct kvm *kvm)
 {
 	struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
 
 	node->track_write = kvm_mmu_pte_write;
+	node->track_flush_slot = kvm_mmu_invalidate_zap_pages_in_memslot;
 	kvm_page_track_register_notifier(kvm, node);
 }
 
@@ -4958,7 +4975,7 @@ void kvm_mmu_invalidate_mmio_sptes(struc
 	 * zap all shadow pages.
 	 */
 	if (unlikely((slots->generation & MMIO_GEN_MASK) == 0)) {
-		printk_ratelimited(KERN_DEBUG "kvm: zapping shadow pages for mmio generation wraparound\n");
+		kvm_debug_ratelimited("kvm: zapping shadow pages for mmio generation wraparound\n");
 		kvm_mmu_invalidate_zap_all_pages(kvm);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/page_track.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/page_track.c
--- linux-libre-4.9-gnu/arch/x86/kvm/page_track.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/page_track.c	2017-02-12 16:03:20.000000000 -0500
@@ -106,6 +106,7 @@ void kvm_slot_page_track_add_page(struct
 		if (kvm_mmu_slot_gfn_write_protect(kvm, slot, gfn))
 			kvm_flush_remote_tlbs(kvm);
 }
+EXPORT_SYMBOL_GPL(kvm_slot_page_track_add_page);
 
 /*
  * remove the guest page from the tracking pool which stops the interception
@@ -135,6 +136,7 @@ void kvm_slot_page_track_remove_page(str
 	 */
 	kvm_mmu_gfn_allow_lpage(slot, gfn);
 }
+EXPORT_SYMBOL_GPL(kvm_slot_page_track_remove_page);
 
 /*
  * check if the corresponding access on the specified guest page is tracked.
@@ -181,6 +183,7 @@ kvm_page_track_register_notifier(struct
 	hlist_add_head_rcu(&n->node, &head->track_notifier_list);
 	spin_unlock(&kvm->mmu_lock);
 }
+EXPORT_SYMBOL_GPL(kvm_page_track_register_notifier);
 
 /*
  * stop receiving the event interception. It is the opposed operation of
@@ -199,6 +202,7 @@ kvm_page_track_unregister_notifier(struc
 	spin_unlock(&kvm->mmu_lock);
 	synchronize_srcu(&head->track_srcu);
 }
+EXPORT_SYMBOL_GPL(kvm_page_track_unregister_notifier);
 
 /*
  * Notify the node that write access is intercepted and write emulation is
@@ -222,6 +226,31 @@ void kvm_page_track_write(struct kvm_vcp
 	idx = srcu_read_lock(&head->track_srcu);
 	hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
 		if (n->track_write)
-			n->track_write(vcpu, gpa, new, bytes);
+			n->track_write(vcpu, gpa, new, bytes, n);
+	srcu_read_unlock(&head->track_srcu, idx);
+}
+
+/*
+ * Notify the node that memory slot is being removed or moved so that it can
+ * drop write-protection for the pages in the memory slot.
+ *
+ * The node should figure out it has any write-protected pages in this slot
+ * by itself.
+ */
+void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+	struct kvm_page_track_notifier_head *head;
+	struct kvm_page_track_notifier_node *n;
+	int idx;
+
+	head = &kvm->arch.track_notifier_head;
+
+	if (hlist_empty(&head->track_notifier_list))
+		return;
+
+	idx = srcu_read_lock(&head->track_srcu);
+	hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
+		if (n->track_flush_slot)
+			n->track_flush_slot(kvm, slot, n);
 	srcu_read_unlock(&head->track_srcu, idx);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/svm.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/svm.c
--- linux-libre-4.9-gnu/arch/x86/kvm/svm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/svm.c	2017-02-12 16:03:20.000000000 -0500
@@ -2074,7 +2074,7 @@ static void svm_set_dr7(struct kvm_vcpu
 static int pf_interception(struct vcpu_svm *svm)
 {
 	u64 fault_address = svm->vmcb->control.exit_info_2;
-	u32 error_code;
+	u64 error_code;
 	int r = 1;
 
 	switch (svm->apf_reason) {
@@ -2270,7 +2270,7 @@ static int io_interception(struct vcpu_s
 	++svm->vcpu.stat.io_exits;
 	string = (io_info & SVM_IOIO_STR_MASK) != 0;
 	in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
-	if (string || in)
+	if (string)
 		return emulate_instruction(vcpu, 0) == EMULATE_DONE;
 
 	port = io_info >> 16;
@@ -2278,7 +2278,8 @@ static int io_interception(struct vcpu_s
 	svm->next_rip = svm->vmcb->control.exit_info_2;
 	skip_emulated_instruction(&svm->vcpu);
 
-	return kvm_fast_pio_out(vcpu, size, port);
+	return in ? kvm_fast_pio_in(vcpu, size, port)
+		  : kvm_fast_pio_out(vcpu, size, port);
 }
 
 static int nmi_interception(struct vcpu_svm *svm)
@@ -3150,8 +3151,7 @@ static int skinit_interception(struct vc
 
 static int wbinvd_interception(struct vcpu_svm *svm)
 {
-	kvm_emulate_wbinvd(&svm->vcpu);
-	return 1;
+	return kvm_emulate_wbinvd(&svm->vcpu);
 }
 
 static int xsetbv_interception(struct vcpu_svm *svm)
@@ -3238,8 +3238,7 @@ static int task_switch_interception(stru
 static int cpuid_interception(struct vcpu_svm *svm)
 {
 	svm->next_rip = kvm_rip_read(&svm->vcpu) + 2;
-	kvm_emulate_cpuid(&svm->vcpu);
-	return 1;
+	return kvm_emulate_cpuid(&svm->vcpu);
 }
 
 static int iret_interception(struct vcpu_svm *svm)
@@ -3275,9 +3274,7 @@ static int rdpmc_interception(struct vcp
 		return emulate_on_interception(svm);
 
 	err = kvm_rdpmc(&svm->vcpu);
-	kvm_complete_insn_gp(&svm->vcpu, err);
-
-	return 1;
+	return kvm_complete_insn_gp(&svm->vcpu, err);
 }
 
 static bool check_selective_cr0_intercepted(struct vcpu_svm *svm,
@@ -3374,9 +3371,7 @@ static int cr_interception(struct vcpu_s
 		}
 		kvm_register_write(&svm->vcpu, reg, val);
 	}
-	kvm_complete_insn_gp(&svm->vcpu, err);
-
-	return 1;
+	return kvm_complete_insn_gp(&svm->vcpu, err);
 }
 
 static int dr_interception(struct vcpu_svm *svm)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/vmx.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/vmx.c
--- linux-libre-4.9-gnu/arch/x86/kvm/vmx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/vmx.c	2017-02-12 16:03:20.000000000 -0500
@@ -133,6 +133,16 @@ module_param_named(preemption_timer, ena
 #define VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE 5
 
 /*
+ * Hyper-V requires all of these, so mark them as supported even though
+ * they are just treated the same as all-context.
+ */
+#define VMX_VPID_EXTENT_SUPPORTED_MASK		\
+	(VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT |	\
+	VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT |	\
+	VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT |	\
+	VMX_VPID_EXTENT_SINGLE_NON_GLOBAL_BIT)
+
+/*
  * These 2 parameters are used to config the controls for Pause-Loop Exiting:
  * ple_gap:    upper bound on the amount of time between two successive
  *             executions of PAUSE in a loop. Also indicate if ple enabled.
@@ -446,23 +456,31 @@ struct nested_vmx {
 	u16 vpid02;
 	u16 last_vpid;
 
+	/*
+	 * We only store the "true" versions of the VMX capability MSRs. We
+	 * generate the "non-true" versions by setting the must-be-1 bits
+	 * according to the SDM.
+	 */
 	u32 nested_vmx_procbased_ctls_low;
 	u32 nested_vmx_procbased_ctls_high;
-	u32 nested_vmx_true_procbased_ctls_low;
 	u32 nested_vmx_secondary_ctls_low;
 	u32 nested_vmx_secondary_ctls_high;
 	u32 nested_vmx_pinbased_ctls_low;
 	u32 nested_vmx_pinbased_ctls_high;
 	u32 nested_vmx_exit_ctls_low;
 	u32 nested_vmx_exit_ctls_high;
-	u32 nested_vmx_true_exit_ctls_low;
 	u32 nested_vmx_entry_ctls_low;
 	u32 nested_vmx_entry_ctls_high;
-	u32 nested_vmx_true_entry_ctls_low;
 	u32 nested_vmx_misc_low;
 	u32 nested_vmx_misc_high;
 	u32 nested_vmx_ept_caps;
 	u32 nested_vmx_vpid_caps;
+	u64 nested_vmx_basic;
+	u64 nested_vmx_cr0_fixed0;
+	u64 nested_vmx_cr0_fixed1;
+	u64 nested_vmx_cr4_fixed0;
+	u64 nested_vmx_cr4_fixed1;
+	u64 nested_vmx_vmcs_enum;
 };
 
 #define POSTED_INTR_ON  0
@@ -520,6 +538,12 @@ static inline void pi_set_sn(struct pi_d
 			(unsigned long *)&pi_desc->control);
 }
 
+static inline void pi_clear_on(struct pi_desc *pi_desc)
+{
+	clear_bit(POSTED_INTR_ON,
+  		  (unsigned long *)&pi_desc->control);
+}
+
 static inline int pi_test_on(struct pi_desc *pi_desc)
 {
 	return test_bit(POSTED_INTR_ON,
@@ -920,16 +944,32 @@ static DEFINE_PER_CPU(struct desc_ptr, h
 static DEFINE_PER_CPU(struct list_head, blocked_vcpu_on_cpu);
 static DEFINE_PER_CPU(spinlock_t, blocked_vcpu_on_cpu_lock);
 
-static unsigned long *vmx_io_bitmap_a;
-static unsigned long *vmx_io_bitmap_b;
-static unsigned long *vmx_msr_bitmap_legacy;
-static unsigned long *vmx_msr_bitmap_longmode;
-static unsigned long *vmx_msr_bitmap_legacy_x2apic;
-static unsigned long *vmx_msr_bitmap_longmode_x2apic;
-static unsigned long *vmx_msr_bitmap_legacy_x2apic_apicv_inactive;
-static unsigned long *vmx_msr_bitmap_longmode_x2apic_apicv_inactive;
-static unsigned long *vmx_vmread_bitmap;
-static unsigned long *vmx_vmwrite_bitmap;
+enum {
+	VMX_IO_BITMAP_A,
+	VMX_IO_BITMAP_B,
+	VMX_MSR_BITMAP_LEGACY,
+	VMX_MSR_BITMAP_LONGMODE,
+	VMX_MSR_BITMAP_LEGACY_X2APIC_APICV,
+	VMX_MSR_BITMAP_LONGMODE_X2APIC_APICV,
+	VMX_MSR_BITMAP_LEGACY_X2APIC,
+	VMX_MSR_BITMAP_LONGMODE_X2APIC,
+	VMX_VMREAD_BITMAP,
+	VMX_VMWRITE_BITMAP,
+	VMX_BITMAP_NR
+};
+
+static unsigned long *vmx_bitmap[VMX_BITMAP_NR];
+
+#define vmx_io_bitmap_a                      (vmx_bitmap[VMX_IO_BITMAP_A])
+#define vmx_io_bitmap_b                      (vmx_bitmap[VMX_IO_BITMAP_B])
+#define vmx_msr_bitmap_legacy                (vmx_bitmap[VMX_MSR_BITMAP_LEGACY])
+#define vmx_msr_bitmap_longmode              (vmx_bitmap[VMX_MSR_BITMAP_LONGMODE])
+#define vmx_msr_bitmap_legacy_x2apic_apicv   (vmx_bitmap[VMX_MSR_BITMAP_LEGACY_X2APIC_APICV])
+#define vmx_msr_bitmap_longmode_x2apic_apicv (vmx_bitmap[VMX_MSR_BITMAP_LONGMODE_X2APIC_APICV])
+#define vmx_msr_bitmap_legacy_x2apic         (vmx_bitmap[VMX_MSR_BITMAP_LEGACY_X2APIC])
+#define vmx_msr_bitmap_longmode_x2apic       (vmx_bitmap[VMX_MSR_BITMAP_LONGMODE_X2APIC])
+#define vmx_vmread_bitmap                    (vmx_bitmap[VMX_VMREAD_BITMAP])
+#define vmx_vmwrite_bitmap                   (vmx_bitmap[VMX_VMWRITE_BITMAP])
 
 static bool cpu_has_load_ia32_efer;
 static bool cpu_has_load_perf_global_ctrl;
@@ -1343,10 +1383,10 @@ static inline bool nested_cpu_has_posted
 	return vmcs12->pin_based_vm_exec_control & PIN_BASED_POSTED_INTR;
 }
 
-static inline bool is_exception(u32 intr_info)
+static inline bool is_nmi(u32 intr_info)
 {
 	return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
-		== (INTR_TYPE_HARD_EXCEPTION | INTR_INFO_VALID_MASK);
+		== (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
 }
 
 static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
@@ -2145,12 +2185,6 @@ static void __vmx_load_host_state(struct
 #endif
 	if (vmx->host_state.msr_host_bndcfgs)
 		wrmsrl(MSR_IA32_BNDCFGS, vmx->host_state.msr_host_bndcfgs);
-	/*
-	 * If the FPU is not active (through the host task or
-	 * the guest vcpu), then restore the cr0.TS bit.
-	 */
-	if (!fpregs_active() && !vmx->vcpu.guest_fpu_loaded)
-		stts();
 	load_gdt(this_cpu_ptr(&host_gdt));
 }
 
@@ -2529,14 +2563,14 @@ static void vmx_set_msr_bitmap(struct kv
 		  SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
 		if (enable_apicv && kvm_vcpu_apicv_active(vcpu)) {
 			if (is_long_mode(vcpu))
-				msr_bitmap = vmx_msr_bitmap_longmode_x2apic;
+				msr_bitmap = vmx_msr_bitmap_longmode_x2apic_apicv;
 			else
-				msr_bitmap = vmx_msr_bitmap_legacy_x2apic;
+				msr_bitmap = vmx_msr_bitmap_legacy_x2apic_apicv;
 		} else {
 			if (is_long_mode(vcpu))
-				msr_bitmap = vmx_msr_bitmap_longmode_x2apic_apicv_inactive;
+				msr_bitmap = vmx_msr_bitmap_longmode_x2apic;
 			else
-				msr_bitmap = vmx_msr_bitmap_legacy_x2apic_apicv_inactive;
+				msr_bitmap = vmx_msr_bitmap_legacy_x2apic;
 		}
 	} else {
 		if (is_long_mode(vcpu))
@@ -2712,9 +2746,7 @@ static void nested_vmx_setup_ctls_msrs(s
 		vmx->nested.nested_vmx_exit_ctls_high |= VM_EXIT_CLEAR_BNDCFGS;
 
 	/* We support free control of debug control saving. */
-	vmx->nested.nested_vmx_true_exit_ctls_low =
-		vmx->nested.nested_vmx_exit_ctls_low &
-		~VM_EXIT_SAVE_DEBUG_CONTROLS;
+	vmx->nested.nested_vmx_exit_ctls_low &= ~VM_EXIT_SAVE_DEBUG_CONTROLS;
 
 	/* entry controls */
 	rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
@@ -2733,9 +2765,7 @@ static void nested_vmx_setup_ctls_msrs(s
 		vmx->nested.nested_vmx_entry_ctls_high |= VM_ENTRY_LOAD_BNDCFGS;
 
 	/* We support free control of debug control loading. */
-	vmx->nested.nested_vmx_true_entry_ctls_low =
-		vmx->nested.nested_vmx_entry_ctls_low &
-		~VM_ENTRY_LOAD_DEBUG_CONTROLS;
+	vmx->nested.nested_vmx_entry_ctls_low &= ~VM_ENTRY_LOAD_DEBUG_CONTROLS;
 
 	/* cpu-based controls */
 	rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
@@ -2768,8 +2798,7 @@ static void nested_vmx_setup_ctls_msrs(s
 		CPU_BASED_USE_MSR_BITMAPS;
 
 	/* We support free control of CR3 access interception. */
-	vmx->nested.nested_vmx_true_procbased_ctls_low =
-		vmx->nested.nested_vmx_procbased_ctls_low &
+	vmx->nested.nested_vmx_procbased_ctls_low &=
 		~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
 
 	/* secondary cpu-based controls */
@@ -2780,6 +2809,7 @@ static void nested_vmx_setup_ctls_msrs(s
 	vmx->nested.nested_vmx_secondary_ctls_high &=
 		SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
 		SECONDARY_EXEC_RDTSCP |
+		SECONDARY_EXEC_DESC |
 		SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
 		SECONDARY_EXEC_ENABLE_VPID |
 		SECONDARY_EXEC_APIC_REGISTER_VIRT |
@@ -2811,8 +2841,7 @@ static void nested_vmx_setup_ctls_msrs(s
 	 */
 	if (enable_vpid)
 		vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT |
-				VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT |
-				VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
+			VMX_VPID_EXTENT_SUPPORTED_MASK;
 	else
 		vmx->nested.nested_vmx_vpid_caps = 0;
 
@@ -2829,14 +2858,52 @@ static void nested_vmx_setup_ctls_msrs(s
 		VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE |
 		VMX_MISC_ACTIVITY_HLT;
 	vmx->nested.nested_vmx_misc_high = 0;
+
+	/*
+	 * This MSR reports some information about VMX support. We
+	 * should return information about the VMX we emulate for the
+	 * guest, and the VMCS structure we give it - not about the
+	 * VMX support of the underlying hardware.
+	 */
+	vmx->nested.nested_vmx_basic =
+		VMCS12_REVISION |
+		VMX_BASIC_TRUE_CTLS |
+		((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
+		(VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
+
+	if (cpu_has_vmx_basic_inout())
+		vmx->nested.nested_vmx_basic |= VMX_BASIC_INOUT;
+
+	/*
+	 * These MSRs specify bits which the guest must keep fixed on
+	 * while L1 is in VMXON mode (in L1's root mode, or running an L2).
+	 * We picked the standard core2 setting.
+	 */
+#define VMXON_CR0_ALWAYSON     (X86_CR0_PE | X86_CR0_PG | X86_CR0_NE)
+#define VMXON_CR4_ALWAYSON     X86_CR4_VMXE
+	vmx->nested.nested_vmx_cr0_fixed0 = VMXON_CR0_ALWAYSON;
+	vmx->nested.nested_vmx_cr4_fixed0 = VMXON_CR4_ALWAYSON;
+
+	/* These MSRs specify bits which the guest must keep fixed off. */
+	rdmsrl(MSR_IA32_VMX_CR0_FIXED1, vmx->nested.nested_vmx_cr0_fixed1);
+	rdmsrl(MSR_IA32_VMX_CR4_FIXED1, vmx->nested.nested_vmx_cr4_fixed1);
+
+	/* highest index: VMX_PREEMPTION_TIMER_VALUE */
+	vmx->nested.nested_vmx_vmcs_enum = 0x2e;
+}
+
+/*
+ * if fixed0[i] == 1: val[i] must be 1
+ * if fixed1[i] == 0: val[i] must be 0
+ */
+static inline bool fixed_bits_valid(u64 val, u64 fixed0, u64 fixed1)
+{
+	return ((val & fixed1) | fixed0) == val;
 }
 
 static inline bool vmx_control_verify(u32 control, u32 low, u32 high)
 {
-	/*
-	 * Bits 0 in high must be 0, and bits 1 in low must be 1.
-	 */
-	return ((control & high) | low) == control;
+	return fixed_bits_valid(control, low, high);
 }
 
 static inline u64 vmx_control_msr(u32 low, u32 high)
@@ -2844,87 +2911,285 @@ static inline u64 vmx_control_msr(u32 lo
 	return low | ((u64)high << 32);
 }
 
-/* Returns 0 on success, non-0 otherwise. */
-static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+static bool is_bitwise_subset(u64 superset, u64 subset, u64 mask)
+{
+	superset &= mask;
+	subset &= mask;
+
+	return (superset | subset) == superset;
+}
+
+static int vmx_restore_vmx_basic(struct vcpu_vmx *vmx, u64 data)
+{
+	const u64 feature_and_reserved =
+		/* feature (except bit 48; see below) */
+		BIT_ULL(49) | BIT_ULL(54) | BIT_ULL(55) |
+		/* reserved */
+		BIT_ULL(31) | GENMASK_ULL(47, 45) | GENMASK_ULL(63, 56);
+	u64 vmx_basic = vmx->nested.nested_vmx_basic;
+
+	if (!is_bitwise_subset(vmx_basic, data, feature_and_reserved))
+		return -EINVAL;
+
+	/*
+	 * KVM does not emulate a version of VMX that constrains physical
+	 * addresses of VMX structures (e.g. VMCS) to 32-bits.
+	 */
+	if (data & BIT_ULL(48))
+		return -EINVAL;
+
+	if (vmx_basic_vmcs_revision_id(vmx_basic) !=
+	    vmx_basic_vmcs_revision_id(data))
+		return -EINVAL;
+
+	if (vmx_basic_vmcs_size(vmx_basic) > vmx_basic_vmcs_size(data))
+		return -EINVAL;
+
+	vmx->nested.nested_vmx_basic = data;
+	return 0;
+}
+
+static int
+vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+{
+	u64 supported;
+	u32 *lowp, *highp;
+
+	switch (msr_index) {
+	case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
+		lowp = &vmx->nested.nested_vmx_pinbased_ctls_low;
+		highp = &vmx->nested.nested_vmx_pinbased_ctls_high;
+		break;
+	case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+		lowp = &vmx->nested.nested_vmx_procbased_ctls_low;
+		highp = &vmx->nested.nested_vmx_procbased_ctls_high;
+		break;
+	case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+		lowp = &vmx->nested.nested_vmx_exit_ctls_low;
+		highp = &vmx->nested.nested_vmx_exit_ctls_high;
+		break;
+	case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+		lowp = &vmx->nested.nested_vmx_entry_ctls_low;
+		highp = &vmx->nested.nested_vmx_entry_ctls_high;
+		break;
+	case MSR_IA32_VMX_PROCBASED_CTLS2:
+		lowp = &vmx->nested.nested_vmx_secondary_ctls_low;
+		highp = &vmx->nested.nested_vmx_secondary_ctls_high;
+		break;
+	default:
+		BUG();
+	}
+
+	supported = vmx_control_msr(*lowp, *highp);
+
+	/* Check must-be-1 bits are still 1. */
+	if (!is_bitwise_subset(data, supported, GENMASK_ULL(31, 0)))
+		return -EINVAL;
+
+	/* Check must-be-0 bits are still 0. */
+	if (!is_bitwise_subset(supported, data, GENMASK_ULL(63, 32)))
+		return -EINVAL;
+
+	*lowp = data;
+	*highp = data >> 32;
+	return 0;
+}
+
+static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data)
+{
+	const u64 feature_and_reserved_bits =
+		/* feature */
+		BIT_ULL(5) | GENMASK_ULL(8, 6) | BIT_ULL(14) | BIT_ULL(15) |
+		BIT_ULL(28) | BIT_ULL(29) | BIT_ULL(30) |
+		/* reserved */
+		GENMASK_ULL(13, 9) | BIT_ULL(31);
+	u64 vmx_misc;
+
+	vmx_misc = vmx_control_msr(vmx->nested.nested_vmx_misc_low,
+				   vmx->nested.nested_vmx_misc_high);
+
+	if (!is_bitwise_subset(vmx_misc, data, feature_and_reserved_bits))
+		return -EINVAL;
+
+	if ((vmx->nested.nested_vmx_pinbased_ctls_high &
+	     PIN_BASED_VMX_PREEMPTION_TIMER) &&
+	    vmx_misc_preemption_timer_rate(data) !=
+	    vmx_misc_preemption_timer_rate(vmx_misc))
+		return -EINVAL;
+
+	if (vmx_misc_cr3_count(data) > vmx_misc_cr3_count(vmx_misc))
+		return -EINVAL;
+
+	if (vmx_misc_max_msr(data) > vmx_misc_max_msr(vmx_misc))
+		return -EINVAL;
+
+	if (vmx_misc_mseg_revid(data) != vmx_misc_mseg_revid(vmx_misc))
+		return -EINVAL;
+
+	vmx->nested.nested_vmx_misc_low = data;
+	vmx->nested.nested_vmx_misc_high = data >> 32;
+	return 0;
+}
+
+static int vmx_restore_vmx_ept_vpid_cap(struct vcpu_vmx *vmx, u64 data)
+{
+	u64 vmx_ept_vpid_cap;
+
+	vmx_ept_vpid_cap = vmx_control_msr(vmx->nested.nested_vmx_ept_caps,
+					   vmx->nested.nested_vmx_vpid_caps);
+
+	/* Every bit is either reserved or a feature bit. */
+	if (!is_bitwise_subset(vmx_ept_vpid_cap, data, -1ULL))
+		return -EINVAL;
+
+	vmx->nested.nested_vmx_ept_caps = data;
+	vmx->nested.nested_vmx_vpid_caps = data >> 32;
+	return 0;
+}
+
+static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+{
+	u64 *msr;
+
+	switch (msr_index) {
+	case MSR_IA32_VMX_CR0_FIXED0:
+		msr = &vmx->nested.nested_vmx_cr0_fixed0;
+		break;
+	case MSR_IA32_VMX_CR4_FIXED0:
+		msr = &vmx->nested.nested_vmx_cr4_fixed0;
+		break;
+	default:
+		BUG();
+	}
+
+	/*
+	 * 1 bits (which indicates bits which "must-be-1" during VMX operation)
+	 * must be 1 in the restored value.
+	 */
+	if (!is_bitwise_subset(data, *msr, -1ULL))
+		return -EINVAL;
+
+	*msr = data;
+	return 0;
+}
+
+/*
+ * Called when userspace is restoring VMX MSRs.
+ *
+ * Returns 0 on success, non-0 otherwise.
+ */
+static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	switch (msr_index) {
 	case MSR_IA32_VMX_BASIC:
+		return vmx_restore_vmx_basic(vmx, data);
+	case MSR_IA32_VMX_PINBASED_CTLS:
+	case MSR_IA32_VMX_PROCBASED_CTLS:
+	case MSR_IA32_VMX_EXIT_CTLS:
+	case MSR_IA32_VMX_ENTRY_CTLS:
 		/*
-		 * This MSR reports some information about VMX support. We
-		 * should return information about the VMX we emulate for the
-		 * guest, and the VMCS structure we give it - not about the
-		 * VMX support of the underlying hardware.
+		 * The "non-true" VMX capability MSRs are generated from the
+		 * "true" MSRs, so we do not support restoring them directly.
+		 *
+		 * If userspace wants to emulate VMX_BASIC[55]=0, userspace
+		 * should restore the "true" MSRs with the must-be-1 bits
+		 * set according to the SDM Vol 3. A.2 "RESERVED CONTROLS AND
+		 * DEFAULT SETTINGS".
 		 */
-		*pdata = VMCS12_REVISION | VMX_BASIC_TRUE_CTLS |
-			   ((u64)VMCS12_SIZE << VMX_BASIC_VMCS_SIZE_SHIFT) |
-			   (VMX_BASIC_MEM_TYPE_WB << VMX_BASIC_MEM_TYPE_SHIFT);
-		if (cpu_has_vmx_basic_inout())
-			*pdata |= VMX_BASIC_INOUT;
+		return -EINVAL;
+	case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
+	case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
+	case MSR_IA32_VMX_TRUE_EXIT_CTLS:
+	case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
+	case MSR_IA32_VMX_PROCBASED_CTLS2:
+		return vmx_restore_control_msr(vmx, msr_index, data);
+	case MSR_IA32_VMX_MISC:
+		return vmx_restore_vmx_misc(vmx, data);
+	case MSR_IA32_VMX_CR0_FIXED0:
+	case MSR_IA32_VMX_CR4_FIXED0:
+		return vmx_restore_fixed0_msr(vmx, msr_index, data);
+	case MSR_IA32_VMX_CR0_FIXED1:
+	case MSR_IA32_VMX_CR4_FIXED1:
+		/*
+		 * These MSRs are generated based on the vCPU's CPUID, so we
+		 * do not support restoring them directly.
+		 */
+		return -EINVAL;
+	case MSR_IA32_VMX_EPT_VPID_CAP:
+		return vmx_restore_vmx_ept_vpid_cap(vmx, data);
+	case MSR_IA32_VMX_VMCS_ENUM:
+		vmx->nested.nested_vmx_vmcs_enum = data;
+		return 0;
+	default:
+		/*
+		 * The rest of the VMX capability MSRs do not support restore.
+		 */
+		return -EINVAL;
+	}
+}
+
+/* Returns 0 on success, non-0 otherwise. */
+static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+
+	switch (msr_index) {
+	case MSR_IA32_VMX_BASIC:
+		*pdata = vmx->nested.nested_vmx_basic;
 		break;
 	case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
 	case MSR_IA32_VMX_PINBASED_CTLS:
 		*pdata = vmx_control_msr(
 			vmx->nested.nested_vmx_pinbased_ctls_low,
 			vmx->nested.nested_vmx_pinbased_ctls_high);
+		if (msr_index == MSR_IA32_VMX_PINBASED_CTLS)
+			*pdata |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
 		break;
 	case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
-		*pdata = vmx_control_msr(
-			vmx->nested.nested_vmx_true_procbased_ctls_low,
-			vmx->nested.nested_vmx_procbased_ctls_high);
-		break;
 	case MSR_IA32_VMX_PROCBASED_CTLS:
 		*pdata = vmx_control_msr(
 			vmx->nested.nested_vmx_procbased_ctls_low,
 			vmx->nested.nested_vmx_procbased_ctls_high);
+		if (msr_index == MSR_IA32_VMX_PROCBASED_CTLS)
+			*pdata |= CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
 		break;
 	case MSR_IA32_VMX_TRUE_EXIT_CTLS:
-		*pdata = vmx_control_msr(
-			vmx->nested.nested_vmx_true_exit_ctls_low,
-			vmx->nested.nested_vmx_exit_ctls_high);
-		break;
 	case MSR_IA32_VMX_EXIT_CTLS:
 		*pdata = vmx_control_msr(
 			vmx->nested.nested_vmx_exit_ctls_low,
 			vmx->nested.nested_vmx_exit_ctls_high);
+		if (msr_index == MSR_IA32_VMX_EXIT_CTLS)
+			*pdata |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
 		break;
 	case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
-		*pdata = vmx_control_msr(
-			vmx->nested.nested_vmx_true_entry_ctls_low,
-			vmx->nested.nested_vmx_entry_ctls_high);
-		break;
 	case MSR_IA32_VMX_ENTRY_CTLS:
 		*pdata = vmx_control_msr(
 			vmx->nested.nested_vmx_entry_ctls_low,
 			vmx->nested.nested_vmx_entry_ctls_high);
+		if (msr_index == MSR_IA32_VMX_ENTRY_CTLS)
+			*pdata |= VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
 		break;
 	case MSR_IA32_VMX_MISC:
 		*pdata = vmx_control_msr(
 			vmx->nested.nested_vmx_misc_low,
 			vmx->nested.nested_vmx_misc_high);
 		break;
-	/*
-	 * These MSRs specify bits which the guest must keep fixed (on or off)
-	 * while L1 is in VMXON mode (in L1's root mode, or running an L2).
-	 * We picked the standard core2 setting.
-	 */
-#define VMXON_CR0_ALWAYSON	(X86_CR0_PE | X86_CR0_PG | X86_CR0_NE)
-#define VMXON_CR4_ALWAYSON	X86_CR4_VMXE
 	case MSR_IA32_VMX_CR0_FIXED0:
-		*pdata = VMXON_CR0_ALWAYSON;
+		*pdata = vmx->nested.nested_vmx_cr0_fixed0;
 		break;
 	case MSR_IA32_VMX_CR0_FIXED1:
-		*pdata = -1ULL;
+		*pdata = vmx->nested.nested_vmx_cr0_fixed1;
 		break;
 	case MSR_IA32_VMX_CR4_FIXED0:
-		*pdata = VMXON_CR4_ALWAYSON;
+		*pdata = vmx->nested.nested_vmx_cr4_fixed0;
 		break;
 	case MSR_IA32_VMX_CR4_FIXED1:
-		*pdata = -1ULL;
+		*pdata = vmx->nested.nested_vmx_cr4_fixed1;
 		break;
 	case MSR_IA32_VMX_VMCS_ENUM:
-		*pdata = 0x2e; /* highest index: VMX_PREEMPTION_TIMER_VALUE */
+		*pdata = vmx->nested.nested_vmx_vmcs_enum;
 		break;
 	case MSR_IA32_VMX_PROCBASED_CTLS2:
 		*pdata = vmx_control_msr(
@@ -3107,7 +3372,11 @@ static int vmx_set_msr(struct kvm_vcpu *
 			vmx_leave_nested(vcpu);
 		break;
 	case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
-		return 1; /* they are read-only */
+		if (!msr_info->host_initiated)
+			return 1; /* they are read-only */
+		if (!nested_vmx_allowed(vcpu))
+			return 1;
+		return vmx_set_vmx_msr(vcpu, msr_index, data);
 	case MSR_IA32_XSS:
 		if (!vmx_xsaves_supported())
 			return 1;
@@ -3869,6 +4138,40 @@ static void ept_save_pdptrs(struct kvm_v
 		  (unsigned long *)&vcpu->arch.regs_dirty);
 }
 
+static bool nested_guest_cr0_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+	u64 fixed0 = to_vmx(vcpu)->nested.nested_vmx_cr0_fixed0;
+	u64 fixed1 = to_vmx(vcpu)->nested.nested_vmx_cr0_fixed1;
+	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+
+	if (to_vmx(vcpu)->nested.nested_vmx_secondary_ctls_high &
+		SECONDARY_EXEC_UNRESTRICTED_GUEST &&
+	    nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST))
+		fixed0 &= ~(X86_CR0_PE | X86_CR0_PG);
+
+	return fixed_bits_valid(val, fixed0, fixed1);
+}
+
+static bool nested_host_cr0_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+	u64 fixed0 = to_vmx(vcpu)->nested.nested_vmx_cr0_fixed0;
+	u64 fixed1 = to_vmx(vcpu)->nested.nested_vmx_cr0_fixed1;
+
+	return fixed_bits_valid(val, fixed0, fixed1);
+}
+
+static bool nested_cr4_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+	u64 fixed0 = to_vmx(vcpu)->nested.nested_vmx_cr4_fixed0;
+	u64 fixed1 = to_vmx(vcpu)->nested.nested_vmx_cr4_fixed1;
+
+	return fixed_bits_valid(val, fixed0, fixed1);
+}
+
+/* No difference in the restrictions on guest and host CR4 in VMX operation. */
+#define nested_guest_cr4_valid	nested_cr4_valid
+#define nested_host_cr4_valid	nested_cr4_valid
+
 static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
 
 static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
@@ -3997,8 +4300,8 @@ static int vmx_set_cr4(struct kvm_vcpu *
 		if (!nested_vmx_allowed(vcpu))
 			return 1;
 	}
-	if (to_vmx(vcpu)->nested.vmxon &&
-	    ((cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON))
+
+	if (to_vmx(vcpu)->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
 		return 1;
 
 	vcpu->arch.cr4 = cr4;
@@ -4575,41 +4878,6 @@ static void __vmx_disable_intercept_for_
 	}
 }
 
-static void __vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
-						u32 msr, int type)
-{
-	int f = sizeof(unsigned long);
-
-	if (!cpu_has_vmx_msr_bitmap())
-		return;
-
-	/*
-	 * See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
-	 * have the write-low and read-high bitmap offsets the wrong way round.
-	 * We can control MSRs 0x00000000-0x00001fff and 0xc0000000-0xc0001fff.
-	 */
-	if (msr <= 0x1fff) {
-		if (type & MSR_TYPE_R)
-			/* read-low */
-			__set_bit(msr, msr_bitmap + 0x000 / f);
-
-		if (type & MSR_TYPE_W)
-			/* write-low */
-			__set_bit(msr, msr_bitmap + 0x800 / f);
-
-	} else if ((msr >= 0xc0000000) && (msr <= 0xc0001fff)) {
-		msr &= 0x1fff;
-		if (type & MSR_TYPE_R)
-			/* read-high */
-			__set_bit(msr, msr_bitmap + 0x400 / f);
-
-		if (type & MSR_TYPE_W)
-			/* write-high */
-			__set_bit(msr, msr_bitmap + 0xc00 / f);
-
-	}
-}
-
 /*
  * If a msr is allowed by L0, we should check whether it is allowed by L1.
  * The corresponding bit will be cleared unless both of L0 and L1 allow it.
@@ -4665,48 +4933,18 @@ static void vmx_disable_intercept_for_ms
 						msr, MSR_TYPE_R | MSR_TYPE_W);
 }
 
-static void vmx_enable_intercept_msr_read_x2apic(u32 msr, bool apicv_active)
+static void vmx_disable_intercept_msr_x2apic(u32 msr, int type, bool apicv_active)
 {
 	if (apicv_active) {
-		__vmx_enable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
-				msr, MSR_TYPE_R);
-		__vmx_enable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
-				msr, MSR_TYPE_R);
+		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic_apicv,
+				msr, type);
+		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic_apicv,
+				msr, type);
 	} else {
-		__vmx_enable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
-				msr, MSR_TYPE_R);
-		__vmx_enable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
-				msr, MSR_TYPE_R);
-	}
-}
-
-static void vmx_disable_intercept_msr_read_x2apic(u32 msr, bool apicv_active)
-{
-	if (apicv_active) {
 		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
-				msr, MSR_TYPE_R);
-		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
-				msr, MSR_TYPE_R);
-	} else {
-		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
-				msr, MSR_TYPE_R);
-		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
-				msr, MSR_TYPE_R);
-	}
-}
-
-static void vmx_disable_intercept_msr_write_x2apic(u32 msr, bool apicv_active)
-{
-	if (apicv_active) {
-		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic,
-				msr, MSR_TYPE_W);
+				msr, type);
 		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic,
-				msr, MSR_TYPE_W);
-	} else {
-		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
-				msr, MSR_TYPE_W);
-		__vmx_disable_intercept_for_msr(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
-				msr, MSR_TYPE_W);
+				msr, type);
 	}
 }
 
@@ -4828,9 +5066,15 @@ static void vmx_sync_pir_to_irr(struct k
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
-	if (!pi_test_and_clear_on(&vmx->pi_desc))
+	if (!pi_test_on(&vmx->pi_desc))
 		return;
 
+	pi_clear_on(&vmx->pi_desc);
+	/*
+	 * IOMMU can write to PIR.ON, so the barrier matters even on UP.
+	 * But on x86 this is just a compiler barrier anyway.
+	 */
+	smp_mb__after_atomic();
 	kvm_apic_update_irr(vcpu, vmx->pi_desc.pir);
 }
 
@@ -4845,9 +5089,11 @@ static void vmx_set_constant_host_state(
 	u32 low32, high32;
 	unsigned long tmpl;
 	struct desc_ptr dt;
-	unsigned long cr4;
+	unsigned long cr0, cr4;
 
-	vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS);  /* 22.2.3 */
+	cr0 = read_cr0();
+	WARN_ON(cr0 & X86_CR0_TS);
+	vmcs_writel(HOST_CR0, cr0);  /* 22.2.3 */
 	vmcs_writel(HOST_CR3, read_cr3());  /* 22.2.3  FIXME: shadow tables */
 
 	/* Save the most likely value for this task's CR4 in the VMCS. */
@@ -5476,7 +5722,7 @@ static int handle_exception(struct kvm_v
 	if (is_machine_check(intr_info))
 		return handle_machine_check(vcpu);
 
-	if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
+	if (is_nmi(intr_info))
 		return 1;  /* already handled by vmx_vcpu_run() */
 
 	if (is_no_device(intr_info)) {
@@ -5587,7 +5833,7 @@ static int handle_triple_fault(struct kv
 static int handle_io(struct kvm_vcpu *vcpu)
 {
 	unsigned long exit_qualification;
-	int size, in, string;
+	int size, in, string, ret;
 	unsigned port;
 
 	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
@@ -5601,9 +5847,14 @@ static int handle_io(struct kvm_vcpu *vc
 
 	port = exit_qualification >> 16;
 	size = (exit_qualification & 7) + 1;
-	skip_emulated_instruction(vcpu);
 
-	return kvm_fast_pio_out(vcpu, size, port);
+	ret = kvm_skip_emulated_instruction(vcpu);
+
+	/*
+	 * TODO: we might be squashing a KVM_GUESTDBG_SINGLESTEP-triggered
+	 * KVM_EXIT_DEBUG here.
+	 */
+	return kvm_fast_pio_out(vcpu, size, port) && ret;
 }
 
 static void
@@ -5617,18 +5868,6 @@ vmx_patch_hypercall(struct kvm_vcpu *vcp
 	hypercall[2] = 0xc1;
 }
 
-static bool nested_cr0_valid(struct kvm_vcpu *vcpu, unsigned long val)
-{
-	unsigned long always_on = VMXON_CR0_ALWAYSON;
-	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
-
-	if (to_vmx(vcpu)->nested.nested_vmx_secondary_ctls_high &
-		SECONDARY_EXEC_UNRESTRICTED_GUEST &&
-	    nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST))
-		always_on &= ~(X86_CR0_PE | X86_CR0_PG);
-	return (val & always_on) == always_on;
-}
-
 /* called to set cr0 as appropriate for a mov-to-cr0 exit. */
 static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
 {
@@ -5647,7 +5886,7 @@ static int handle_set_cr0(struct kvm_vcp
 		val = (val & ~vmcs12->cr0_guest_host_mask) |
 			(vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask);
 
-		if (!nested_cr0_valid(vcpu, val))
+		if (!nested_guest_cr0_valid(vcpu, val))
 			return 1;
 
 		if (kvm_set_cr0(vcpu, val))
@@ -5656,8 +5895,9 @@ static int handle_set_cr0(struct kvm_vcp
 		return 0;
 	} else {
 		if (to_vmx(vcpu)->nested.vmxon &&
-		    ((val & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON))
+		    !nested_host_cr0_valid(vcpu, val))
 			return 1;
+
 		return kvm_set_cr0(vcpu, val);
 	}
 }
@@ -5701,6 +5941,7 @@ static int handle_cr(struct kvm_vcpu *vc
 	int cr;
 	int reg;
 	int err;
+	int ret;
 
 	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 	cr = exit_qualification & 15;
@@ -5712,25 +5953,27 @@ static int handle_cr(struct kvm_vcpu *vc
 		switch (cr) {
 		case 0:
 			err = handle_set_cr0(vcpu, val);
-			kvm_complete_insn_gp(vcpu, err);
-			return 1;
+			return kvm_complete_insn_gp(vcpu, err);
 		case 3:
 			err = kvm_set_cr3(vcpu, val);
-			kvm_complete_insn_gp(vcpu, err);
-			return 1;
+			return kvm_complete_insn_gp(vcpu, err);
 		case 4:
 			err = handle_set_cr4(vcpu, val);
-			kvm_complete_insn_gp(vcpu, err);
-			return 1;
+			return kvm_complete_insn_gp(vcpu, err);
 		case 8: {
 				u8 cr8_prev = kvm_get_cr8(vcpu);
 				u8 cr8 = (u8)val;
 				err = kvm_set_cr8(vcpu, cr8);
-				kvm_complete_insn_gp(vcpu, err);
+				ret = kvm_complete_insn_gp(vcpu, err);
 				if (lapic_in_kernel(vcpu))
-					return 1;
+					return ret;
 				if (cr8_prev <= cr8)
-					return 1;
+					return ret;
+				/*
+				 * TODO: we might be squashing a
+				 * KVM_GUESTDBG_SINGLESTEP-triggered
+				 * KVM_EXIT_DEBUG here.
+				 */
 				vcpu->run->exit_reason = KVM_EXIT_SET_TPR;
 				return 0;
 			}
@@ -5739,23 +5982,20 @@ static int handle_cr(struct kvm_vcpu *vc
 	case 2: /* clts */
 		handle_clts(vcpu);
 		trace_kvm_cr_write(0, kvm_read_cr0(vcpu));
-		skip_emulated_instruction(vcpu);
 		vmx_fpu_activate(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	case 1: /*mov from cr*/
 		switch (cr) {
 		case 3:
 			val = kvm_read_cr3(vcpu);
 			kvm_register_write(vcpu, reg, val);
 			trace_kvm_cr_read(cr, val);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		case 8:
 			val = kvm_get_cr8(vcpu);
 			kvm_register_write(vcpu, reg, val);
 			trace_kvm_cr_read(cr, val);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 		break;
 	case 3: /* lmsw */
@@ -5763,8 +6003,7 @@ static int handle_cr(struct kvm_vcpu *vc
 		trace_kvm_cr_write(0, (kvm_read_cr0(vcpu) & ~0xful) | val);
 		kvm_lmsw(vcpu, val);
 
-		skip_emulated_instruction(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	default:
 		break;
 	}
@@ -5835,8 +6074,7 @@ static int handle_dr(struct kvm_vcpu *vc
 		if (kvm_set_dr(vcpu, dr, kvm_register_readl(vcpu, reg)))
 			return 1;
 
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static u64 vmx_get_dr6(struct kvm_vcpu *vcpu)
@@ -5868,8 +6106,7 @@ static void vmx_set_dr7(struct kvm_vcpu
 
 static int handle_cpuid(struct kvm_vcpu *vcpu)
 {
-	kvm_emulate_cpuid(vcpu);
-	return 1;
+	return kvm_emulate_cpuid(vcpu);
 }
 
 static int handle_rdmsr(struct kvm_vcpu *vcpu)
@@ -5890,8 +6127,7 @@ static int handle_rdmsr(struct kvm_vcpu
 	/* FIXME: handling of bits 32:63 of rax, rdx */
 	vcpu->arch.regs[VCPU_REGS_RAX] = msr_info.data & -1u;
 	vcpu->arch.regs[VCPU_REGS_RDX] = (msr_info.data >> 32) & -1u;
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int handle_wrmsr(struct kvm_vcpu *vcpu)
@@ -5911,8 +6147,7 @@ static int handle_wrmsr(struct kvm_vcpu
 	}
 
 	trace_kvm_msr_write(ecx, data);
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int handle_tpr_below_threshold(struct kvm_vcpu *vcpu)
@@ -5956,8 +6191,7 @@ static int handle_invlpg(struct kvm_vcpu
 	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 
 	kvm_mmu_invlpg(vcpu, exit_qualification);
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int handle_rdpmc(struct kvm_vcpu *vcpu)
@@ -5965,15 +6199,12 @@ static int handle_rdpmc(struct kvm_vcpu
 	int err;
 
 	err = kvm_rdpmc(vcpu);
-	kvm_complete_insn_gp(vcpu, err);
-
-	return 1;
+	return kvm_complete_insn_gp(vcpu, err);
 }
 
 static int handle_wbinvd(struct kvm_vcpu *vcpu)
 {
-	kvm_emulate_wbinvd(vcpu);
-	return 1;
+	return kvm_emulate_wbinvd(vcpu);
 }
 
 static int handle_xsetbv(struct kvm_vcpu *vcpu)
@@ -5982,20 +6213,20 @@ static int handle_xsetbv(struct kvm_vcpu
 	u32 index = kvm_register_read(vcpu, VCPU_REGS_RCX);
 
 	if (kvm_set_xcr(vcpu, index, new_bv) == 0)
-		skip_emulated_instruction(vcpu);
+		return kvm_skip_emulated_instruction(vcpu);
 	return 1;
 }
 
 static int handle_xsaves(struct kvm_vcpu *vcpu)
 {
-	skip_emulated_instruction(vcpu);
+	kvm_skip_emulated_instruction(vcpu);
 	WARN(1, "this should never happen\n");
 	return 1;
 }
 
 static int handle_xrstors(struct kvm_vcpu *vcpu)
 {
-	skip_emulated_instruction(vcpu);
+	kvm_skip_emulated_instruction(vcpu);
 	WARN(1, "this should never happen\n");
 	return 1;
 }
@@ -6016,8 +6247,7 @@ static int handle_apic_access(struct kvm
 		if ((access_type == TYPE_LINEAR_APIC_INST_WRITE) &&
 		    (offset == APIC_EOI)) {
 			kvm_lapic_set_eoi(vcpu);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 	}
 	return emulate_instruction(vcpu, 0) == EMULATE_DONE;
@@ -6165,9 +6395,8 @@ static int handle_ept_misconfig(struct k
 
 	gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
 	if (!kvm_io_bus_write(vcpu, KVM_FAST_MMIO_BUS, gpa, 0, NULL)) {
-		skip_emulated_instruction(vcpu);
 		trace_kvm_fast_mmio(gpa);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 
 	ret = handle_mmio_page_fault(vcpu, gpa, true);
@@ -6352,50 +6581,13 @@ static __init int hardware_setup(void)
 	for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i)
 		kvm_define_shared_msr(i, vmx_msr_index[i]);
 
-	vmx_io_bitmap_a = (unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_io_bitmap_a)
-		return r;
+	for (i = 0; i < VMX_BITMAP_NR; i++) {
+		vmx_bitmap[i] = (unsigned long *)__get_free_page(GFP_KERNEL);
+		if (!vmx_bitmap[i])
+			goto out;
+	}
 
 	vmx_io_bitmap_b = (unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_io_bitmap_b)
-		goto out;
-
-	vmx_msr_bitmap_legacy = (unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_msr_bitmap_legacy)
-		goto out1;
-
-	vmx_msr_bitmap_legacy_x2apic =
-				(unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_msr_bitmap_legacy_x2apic)
-		goto out2;
-
-	vmx_msr_bitmap_legacy_x2apic_apicv_inactive =
-				(unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_msr_bitmap_legacy_x2apic_apicv_inactive)
-		goto out3;
-
-	vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_msr_bitmap_longmode)
-		goto out4;
-
-	vmx_msr_bitmap_longmode_x2apic =
-				(unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_msr_bitmap_longmode_x2apic)
-		goto out5;
-
-	vmx_msr_bitmap_longmode_x2apic_apicv_inactive =
-				(unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_msr_bitmap_longmode_x2apic_apicv_inactive)
-		goto out6;
-
-	vmx_vmread_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_vmread_bitmap)
-		goto out7;
-
-	vmx_vmwrite_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL);
-	if (!vmx_vmwrite_bitmap)
-		goto out8;
-
 	memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
 	memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
 
@@ -6413,7 +6605,7 @@ static __init int hardware_setup(void)
 
 	if (setup_vmcs_config(&vmcs_config) < 0) {
 		r = -EIO;
-		goto out9;
+		goto out;
 	}
 
 	if (boot_cpu_has(X86_FEATURE_NX))
@@ -6476,39 +6668,34 @@ static __init int hardware_setup(void)
 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false);
 	vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true);
 
-	memcpy(vmx_msr_bitmap_legacy_x2apic,
+	memcpy(vmx_msr_bitmap_legacy_x2apic_apicv,
 			vmx_msr_bitmap_legacy, PAGE_SIZE);
-	memcpy(vmx_msr_bitmap_longmode_x2apic,
+	memcpy(vmx_msr_bitmap_longmode_x2apic_apicv,
 			vmx_msr_bitmap_longmode, PAGE_SIZE);
-	memcpy(vmx_msr_bitmap_legacy_x2apic_apicv_inactive,
+	memcpy(vmx_msr_bitmap_legacy_x2apic,
 			vmx_msr_bitmap_legacy, PAGE_SIZE);
-	memcpy(vmx_msr_bitmap_longmode_x2apic_apicv_inactive,
+	memcpy(vmx_msr_bitmap_longmode_x2apic,
 			vmx_msr_bitmap_longmode, PAGE_SIZE);
 
 	set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */
 
+	for (msr = 0x800; msr <= 0x8ff; msr++) {
+		if (msr == 0x839 /* TMCCT */)
+			continue;
+		vmx_disable_intercept_msr_x2apic(msr, MSR_TYPE_R, true);
+	}
+
 	/*
-	 * enable_apicv && kvm_vcpu_apicv_active()
+	 * TPR reads and writes can be virtualized even if virtual interrupt
+	 * delivery is not in use.
 	 */
-	for (msr = 0x800; msr <= 0x8ff; msr++)
-		vmx_disable_intercept_msr_read_x2apic(msr, true);
+	vmx_disable_intercept_msr_x2apic(0x808, MSR_TYPE_W, true);
+	vmx_disable_intercept_msr_x2apic(0x808, MSR_TYPE_R | MSR_TYPE_W, false);
 
-	/* TMCCT */
-	vmx_enable_intercept_msr_read_x2apic(0x839, true);
-	/* TPR */
-	vmx_disable_intercept_msr_write_x2apic(0x808, true);
 	/* EOI */
-	vmx_disable_intercept_msr_write_x2apic(0x80b, true);
+	vmx_disable_intercept_msr_x2apic(0x80b, MSR_TYPE_W, true);
 	/* SELF-IPI */
-	vmx_disable_intercept_msr_write_x2apic(0x83f, true);
-
-	/*
-	 * (enable_apicv && !kvm_vcpu_apicv_active()) ||
-	 * 	!enable_apicv
-	 */
-	/* TPR */
-	vmx_disable_intercept_msr_read_x2apic(0x808, false);
-	vmx_disable_intercept_msr_write_x2apic(0x808, false);
+	vmx_disable_intercept_msr_x2apic(0x83f, MSR_TYPE_W, true);
 
 	if (enable_ept) {
 		kvm_mmu_set_mask_ptes(VMX_EPT_READABLE_MASK,
@@ -6555,42 +6742,19 @@ static __init int hardware_setup(void)
 
 	return alloc_kvm_area();
 
-out9:
-	free_page((unsigned long)vmx_vmwrite_bitmap);
-out8:
-	free_page((unsigned long)vmx_vmread_bitmap);
-out7:
-	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic_apicv_inactive);
-out6:
-	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic);
-out5:
-	free_page((unsigned long)vmx_msr_bitmap_longmode);
-out4:
-	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic_apicv_inactive);
-out3:
-	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic);
-out2:
-	free_page((unsigned long)vmx_msr_bitmap_legacy);
-out1:
-	free_page((unsigned long)vmx_io_bitmap_b);
 out:
-	free_page((unsigned long)vmx_io_bitmap_a);
+	for (i = 0; i < VMX_BITMAP_NR; i++)
+		free_page((unsigned long)vmx_bitmap[i]);
 
     return r;
 }
 
 static __exit void hardware_unsetup(void)
 {
-	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic);
-	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic_apicv_inactive);
-	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic);
-	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic_apicv_inactive);
-	free_page((unsigned long)vmx_msr_bitmap_legacy);
-	free_page((unsigned long)vmx_msr_bitmap_longmode);
-	free_page((unsigned long)vmx_io_bitmap_b);
-	free_page((unsigned long)vmx_io_bitmap_a);
-	free_page((unsigned long)vmx_vmwrite_bitmap);
-	free_page((unsigned long)vmx_vmread_bitmap);
+	int i;
+
+	for (i = 0; i < VMX_BITMAP_NR; i++)
+		free_page((unsigned long)vmx_bitmap[i]);
 
 	free_kvm_area();
 }
@@ -6604,16 +6768,13 @@ static int handle_pause(struct kvm_vcpu
 	if (ple_gap)
 		grow_ple_window(vcpu);
 
-	skip_emulated_instruction(vcpu);
 	kvm_vcpu_on_spin(vcpu);
-
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int handle_nop(struct kvm_vcpu *vcpu)
 {
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int handle_mwait(struct kvm_vcpu *vcpu)
@@ -6920,8 +7081,7 @@ static int nested_vmx_check_vmptr(struct
 		 */
 		if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
 			nested_vmx_failInvalid(vcpu);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 
 		page = nested_get_page(vcpu, vmptr);
@@ -6929,8 +7089,7 @@ static int nested_vmx_check_vmptr(struct
 		    *(u32 *)kmap(page) != VMCS12_REVISION) {
 			nested_vmx_failInvalid(vcpu);
 			kunmap(page);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 		kunmap(page);
 		vmx->nested.vmxon_ptr = vmptr;
@@ -6939,30 +7098,26 @@ static int nested_vmx_check_vmptr(struct
 		if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
 			nested_vmx_failValid(vcpu,
 					     VMXERR_VMCLEAR_INVALID_ADDRESS);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 
 		if (vmptr == vmx->nested.vmxon_ptr) {
 			nested_vmx_failValid(vcpu,
 					     VMXERR_VMCLEAR_VMXON_POINTER);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 		break;
 	case EXIT_REASON_VMPTRLD:
 		if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
 			nested_vmx_failValid(vcpu,
 					     VMXERR_VMPTRLD_INVALID_ADDRESS);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 
 		if (vmptr == vmx->nested.vmxon_ptr) {
 			nested_vmx_failValid(vcpu,
-					     VMXERR_VMCLEAR_VMXON_POINTER);
-			skip_emulated_instruction(vcpu);
-			return 1;
+					     VMXERR_VMPTRLD_VMXON_POINTER);
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 		break;
 	default:
@@ -7018,8 +7173,7 @@ static int handle_vmon(struct kvm_vcpu *
 
 	if (vmx->nested.vmxon) {
 		nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
-		skip_emulated_instruction(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 
 	if ((vmx->msr_ia32_feature_control & VMXON_NEEDED_FEATURES)
@@ -7059,9 +7213,8 @@ static int handle_vmon(struct kvm_vcpu *
 
 	vmx->nested.vmxon = true;
 
-	skip_emulated_instruction(vcpu);
 	nested_vmx_succeed(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 
 out_shadow_vmcs:
 	kfree(vmx->nested.cached_vmcs12);
@@ -7180,9 +7333,8 @@ static int handle_vmoff(struct kvm_vcpu
 	if (!nested_vmx_check_permission(vcpu))
 		return 1;
 	free_nested(to_vmx(vcpu));
-	skip_emulated_instruction(vcpu);
 	nested_vmx_succeed(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 /* Emulate the VMCLEAR instruction */
@@ -7221,9 +7373,8 @@ static int handle_vmclear(struct kvm_vcp
 
 	nested_free_vmcs02(vmx, vmptr);
 
-	skip_emulated_instruction(vcpu);
 	nested_vmx_succeed(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch);
@@ -7421,7 +7572,6 @@ static int nested_vmx_check_vmcs12(struc
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	if (vmx->nested.current_vmptr == -1ull) {
 		nested_vmx_failInvalid(vcpu);
-		skip_emulated_instruction(vcpu);
 		return 0;
 	}
 	return 1;
@@ -7435,17 +7585,18 @@ static int handle_vmread(struct kvm_vcpu
 	u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
 	gva_t gva = 0;
 
-	if (!nested_vmx_check_permission(vcpu) ||
-	    !nested_vmx_check_vmcs12(vcpu))
+	if (!nested_vmx_check_permission(vcpu))
 		return 1;
 
+	if (!nested_vmx_check_vmcs12(vcpu))
+		return kvm_skip_emulated_instruction(vcpu);
+
 	/* Decode instruction info and find the field to read */
 	field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
 	/* Read the field, zero-extended to a u64 field_value */
 	if (vmcs12_read_any(vcpu, field, &field_value) < 0) {
 		nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
-		skip_emulated_instruction(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 	/*
 	 * Now copy part of this value to register or memory, as requested.
@@ -7465,8 +7616,7 @@ static int handle_vmread(struct kvm_vcpu
 	}
 
 	nested_vmx_succeed(vcpu);
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 
@@ -7485,10 +7635,12 @@ static int handle_vmwrite(struct kvm_vcp
 	u64 field_value = 0;
 	struct x86_exception e;
 
-	if (!nested_vmx_check_permission(vcpu) ||
-	    !nested_vmx_check_vmcs12(vcpu))
+	if (!nested_vmx_check_permission(vcpu))
 		return 1;
 
+	if (!nested_vmx_check_vmcs12(vcpu))
+		return kvm_skip_emulated_instruction(vcpu);
+
 	if (vmx_instruction_info & (1u << 10))
 		field_value = kvm_register_readl(vcpu,
 			(((vmx_instruction_info) >> 3) & 0xf));
@@ -7508,19 +7660,16 @@ static int handle_vmwrite(struct kvm_vcp
 	if (vmcs_field_readonly(field)) {
 		nested_vmx_failValid(vcpu,
 			VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
-		skip_emulated_instruction(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 
 	if (vmcs12_write_any(vcpu, field, field_value) < 0) {
 		nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
-		skip_emulated_instruction(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 
 	nested_vmx_succeed(vcpu);
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 /* Emulate the VMPTRLD instruction */
@@ -7541,8 +7690,7 @@ static int handle_vmptrld(struct kvm_vcp
 		page = nested_get_page(vcpu, vmptr);
 		if (page == NULL) {
 			nested_vmx_failInvalid(vcpu);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 		new_vmcs12 = kmap(page);
 		if (new_vmcs12->revision_id != VMCS12_REVISION) {
@@ -7550,8 +7698,7 @@ static int handle_vmptrld(struct kvm_vcp
 			nested_release_page_clean(page);
 			nested_vmx_failValid(vcpu,
 				VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
-			skip_emulated_instruction(vcpu);
-			return 1;
+			return kvm_skip_emulated_instruction(vcpu);
 		}
 
 		nested_release_vmcs12(vmx);
@@ -7575,8 +7722,7 @@ static int handle_vmptrld(struct kvm_vcp
 	}
 
 	nested_vmx_succeed(vcpu);
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 /* Emulate the VMPTRST instruction */
@@ -7601,8 +7747,7 @@ static int handle_vmptrst(struct kvm_vcp
 		return 1;
 	}
 	nested_vmx_succeed(vcpu);
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 /* Emulate the INVEPT instruction */
@@ -7640,8 +7785,7 @@ static int handle_invept(struct kvm_vcpu
 	if (type >= 32 || !(types & (1 << type))) {
 		nested_vmx_failValid(vcpu,
 				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
-		skip_emulated_instruction(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 
 	/* According to the Intel VMX instruction reference, the memory
@@ -7672,8 +7816,7 @@ static int handle_invept(struct kvm_vcpu
 		break;
 	}
 
-	skip_emulated_instruction(vcpu);
-	return 1;
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int handle_invvpid(struct kvm_vcpu *vcpu)
@@ -7698,13 +7841,13 @@ static int handle_invvpid(struct kvm_vcp
 	vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
 	type = kvm_register_readl(vcpu, (vmx_instruction_info >> 28) & 0xf);
 
-	types = (vmx->nested.nested_vmx_vpid_caps >> 8) & 0x7;
+	types = (vmx->nested.nested_vmx_vpid_caps &
+			VMX_VPID_EXTENT_SUPPORTED_MASK) >> 8;
 
 	if (type >= 32 || !(types & (1 << type))) {
 		nested_vmx_failValid(vcpu,
 			VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
-		skip_emulated_instruction(vcpu);
-		return 1;
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 
 	/* according to the intel vmx instruction reference, the memory
@@ -7720,23 +7863,26 @@ static int handle_invvpid(struct kvm_vcp
 	}
 
 	switch (type) {
+	case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
 	case VMX_VPID_EXTENT_SINGLE_CONTEXT:
-		/*
-		 * Old versions of KVM use the single-context version so we
-		 * have to support it; just treat it the same as all-context.
-		 */
+	case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
+		if (!vpid) {
+			nested_vmx_failValid(vcpu,
+				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+			return kvm_skip_emulated_instruction(vcpu);
+		}
+		break;
 	case VMX_VPID_EXTENT_ALL_CONTEXT:
-		__vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
-		nested_vmx_succeed(vcpu);
 		break;
 	default:
-		/* Trap individual address invalidation invvpid calls */
-		BUG_ON(1);
-		break;
+		WARN_ON_ONCE(1);
+		return kvm_skip_emulated_instruction(vcpu);
 	}
 
-	skip_emulated_instruction(vcpu);
-	return 1;
+	__vmx_flush_tlb(vcpu, vmx->nested.vpid02);
+	nested_vmx_succeed(vcpu);
+
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 static int handle_pml_full(struct kvm_vcpu *vcpu)
@@ -8018,7 +8164,7 @@ static bool nested_vmx_exit_handled(stru
 
 	switch (exit_reason) {
 	case EXIT_REASON_EXCEPTION_NMI:
-		if (!is_exception(intr_info))
+		if (is_nmi(intr_info))
 			return false;
 		else if (is_page_fault(intr_info))
 			return enable_ept;
@@ -8075,6 +8221,8 @@ static bool nested_vmx_exit_handled(stru
 		return nested_cpu_has(vmcs12, CPU_BASED_MOV_DR_EXITING);
 	case EXIT_REASON_IO_INSTRUCTION:
 		return nested_vmx_exit_handled_io(vcpu, vmcs12);
+	case EXIT_REASON_GDTR_IDTR: case EXIT_REASON_LDTR_TR:
+		return nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC);
 	case EXIT_REASON_MSR_READ:
 	case EXIT_REASON_MSR_WRITE:
 		return nested_vmx_exit_handled_msr(vcpu, vmcs12, exit_reason);
@@ -8611,8 +8759,7 @@ static void vmx_complete_atomic_exit(str
 		kvm_machine_check();
 
 	/* We need to handle NMIs before interrupts are enabled */
-	if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
-	    (exit_intr_info & INTR_INFO_VALID_MASK)) {
+	if (is_nmi(exit_intr_info)) {
 		kvm_before_handle_nmi(&vmx->vcpu);
 		asm("int $2");
 		kvm_after_handle_nmi(&vmx->vcpu);
@@ -8624,11 +8771,6 @@ static void vmx_handle_external_intr(str
 	u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
 	register void *__sp asm(_ASM_SP);
 
-	/*
-	 * If external interrupt exists, IF bit is set in rflags/eflags on the
-	 * interrupt stack frame, and interrupt will be enabled on a return
-	 * from interrupt handler.
-	 */
 	if ((exit_intr_info & (INTR_INFO_VALID_MASK | INTR_INFO_INTR_TYPE_MASK))
 			== (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR)) {
 		unsigned int vector;
@@ -8813,7 +8955,7 @@ static void atomic_switch_perf_msrs(stru
 					msrs[i].host);
 }
 
-void vmx_arm_hv_timer(struct kvm_vcpu *vcpu)
+static void vmx_arm_hv_timer(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u64 tscl;
@@ -9283,6 +9425,50 @@ static void vmcs_set_secondary_exec_cont
 		     (new_ctl & ~mask) | (cur_ctl & mask));
 }
 
+/*
+ * Generate MSR_IA32_VMX_CR{0,4}_FIXED1 according to CPUID. Only set bits
+ * (indicating "allowed-1") if they are supported in the guest's CPUID.
+ */
+static void nested_vmx_cr_fixed1_bits_update(struct kvm_vcpu *vcpu)
+{
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
+	struct kvm_cpuid_entry2 *entry;
+
+	vmx->nested.nested_vmx_cr0_fixed1 = 0xffffffff;
+	vmx->nested.nested_vmx_cr4_fixed1 = X86_CR4_PCE;
+
+#define cr4_fixed1_update(_cr4_mask, _reg, _cpuid_mask) do {		\
+	if (entry && (entry->_reg & (_cpuid_mask)))			\
+		vmx->nested.nested_vmx_cr4_fixed1 |= (_cr4_mask);	\
+} while (0)
+
+	entry = kvm_find_cpuid_entry(vcpu, 0x1, 0);
+	cr4_fixed1_update(X86_CR4_VME,        edx, bit(X86_FEATURE_VME));
+	cr4_fixed1_update(X86_CR4_PVI,        edx, bit(X86_FEATURE_VME));
+	cr4_fixed1_update(X86_CR4_TSD,        edx, bit(X86_FEATURE_TSC));
+	cr4_fixed1_update(X86_CR4_DE,         edx, bit(X86_FEATURE_DE));
+	cr4_fixed1_update(X86_CR4_PSE,        edx, bit(X86_FEATURE_PSE));
+	cr4_fixed1_update(X86_CR4_PAE,        edx, bit(X86_FEATURE_PAE));
+	cr4_fixed1_update(X86_CR4_MCE,        edx, bit(X86_FEATURE_MCE));
+	cr4_fixed1_update(X86_CR4_PGE,        edx, bit(X86_FEATURE_PGE));
+	cr4_fixed1_update(X86_CR4_OSFXSR,     edx, bit(X86_FEATURE_FXSR));
+	cr4_fixed1_update(X86_CR4_OSXMMEXCPT, edx, bit(X86_FEATURE_XMM));
+	cr4_fixed1_update(X86_CR4_VMXE,       ecx, bit(X86_FEATURE_VMX));
+	cr4_fixed1_update(X86_CR4_SMXE,       ecx, bit(X86_FEATURE_SMX));
+	cr4_fixed1_update(X86_CR4_PCIDE,      ecx, bit(X86_FEATURE_PCID));
+	cr4_fixed1_update(X86_CR4_OSXSAVE,    ecx, bit(X86_FEATURE_XSAVE));
+
+	entry = kvm_find_cpuid_entry(vcpu, 0x7, 0);
+	cr4_fixed1_update(X86_CR4_FSGSBASE,   ebx, bit(X86_FEATURE_FSGSBASE));
+	cr4_fixed1_update(X86_CR4_SMEP,       ebx, bit(X86_FEATURE_SMEP));
+	cr4_fixed1_update(X86_CR4_SMAP,       ebx, bit(X86_FEATURE_SMAP));
+	cr4_fixed1_update(X86_CR4_PKE,        ecx, bit(X86_FEATURE_PKU));
+	/* TODO: Use X86_CR4_UMIP and X86_FEATURE_UMIP macros */
+	cr4_fixed1_update(bit(11),            ecx, bit(2));
+
+#undef cr4_fixed1_update
+}
+
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpuid_entry2 *best;
@@ -9324,6 +9510,9 @@ static void vmx_cpuid_update(struct kvm_
 	else
 		to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &=
 			~FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
+
+	if (nested_vmx_allowed(vcpu))
+		nested_vmx_cr_fixed1_bits_update(vcpu);
 }
 
 static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
@@ -9778,6 +9967,49 @@ static int nested_vmx_store_msr(struct k
 	return 0;
 }
 
+static bool nested_cr3_valid(struct kvm_vcpu *vcpu, unsigned long val)
+{
+	unsigned long invalid_mask;
+
+	invalid_mask = (~0ULL) << cpuid_maxphyaddr(vcpu);
+	return (val & invalid_mask) == 0;
+}
+
+/*
+ * Load guest's/host's cr3 at nested entry/exit. nested_ept is true if we are
+ * emulating VM entry into a guest with EPT enabled.
+ * Returns 0 on success, 1 on failure. Invalid state exit qualification code
+ * is assigned to entry_failure_code on failure.
+ */
+static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool nested_ept,
+			       unsigned long *entry_failure_code)
+{
+	if (cr3 != kvm_read_cr3(vcpu) || (!nested_ept && pdptrs_changed(vcpu))) {
+		if (!nested_cr3_valid(vcpu, cr3)) {
+			*entry_failure_code = ENTRY_FAIL_DEFAULT;
+			return 1;
+		}
+
+		/*
+		 * If PAE paging and EPT are both on, CR3 is not used by the CPU and
+		 * must not be dereferenced.
+		 */
+		if (!is_long_mode(vcpu) && is_pae(vcpu) && is_paging(vcpu) &&
+		    !nested_ept) {
+			if (!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) {
+				*entry_failure_code = ENTRY_FAIL_PDPTE;
+				return 1;
+			}
+		}
+
+		vcpu->arch.cr3 = cr3;
+		__set_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail);
+	}
+
+	kvm_mmu_reset_context(vcpu);
+	return 0;
+}
+
 /*
  * prepare_vmcs02 is called when the L1 guest hypervisor runs its nested
  * L2 guest. L1 has a vmcs for L2 (vmcs12), and this function "merges" it
@@ -9786,11 +10018,15 @@ static int nested_vmx_store_msr(struct k
  * needs. In addition to modifying the active vmcs (which is vmcs02), this
  * function also has additional necessary side-effects, like setting various
  * vcpu->arch fields.
+ * Returns 0 on success, 1 on failure. Invalid state exit qualification code
+ * is assigned to entry_failure_code on failure.
  */
-static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
+static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
+			  unsigned long *entry_failure_code)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	u32 exec_control;
+	bool nested_ept_enabled = false;
 
 	vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector);
 	vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector);
@@ -9955,6 +10191,7 @@ static void prepare_vmcs02(struct kvm_vc
 				vmcs12->guest_intr_status);
 		}
 
+		nested_ept_enabled = (exec_control & SECONDARY_EXEC_ENABLE_EPT) != 0;
 		vmcs_write32(SECONDARY_VM_EXEC_CONTROL, exec_control);
 	}
 
@@ -9968,6 +10205,15 @@ static void prepare_vmcs02(struct kvm_vc
 	vmx_set_constant_host_state(vmx);
 
 	/*
+	 * Set the MSR load/store lists to match L0's settings.
+	 */
+	vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0);
+	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.nr);
+	vmcs_write64(VM_EXIT_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.host));
+	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.nr);
+	vmcs_write64(VM_ENTRY_MSR_LOAD_ADDR, __pa(vmx->msr_autoload.guest));
+
+	/*
 	 * HOST_RSP is normally set correctly in vmx_vcpu_run() just before
 	 * entry, but only if the current (host) sp changed from the value
 	 * we wrote last (vmx->host_rsp). This cache is no longer relevant
@@ -10073,15 +10319,6 @@ static void prepare_vmcs02(struct kvm_vc
 		nested_ept_init_mmu_context(vcpu);
 	}
 
-	if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)
-		vcpu->arch.efer = vmcs12->guest_ia32_efer;
-	else if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE)
-		vcpu->arch.efer |= (EFER_LMA | EFER_LME);
-	else
-		vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
-	/* Note: modifies VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */
-	vmx_set_efer(vcpu, vcpu->arch.efer);
-
 	/*
 	 * This sets GUEST_CR0 to vmcs12->guest_cr0, with possibly a modified
 	 * TS bit (for lazy fpu) and bits which we consider mandatory enabled.
@@ -10096,8 +10333,20 @@ static void prepare_vmcs02(struct kvm_vc
 	vmx_set_cr4(vcpu, vmcs12->guest_cr4);
 	vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12));
 
-	/* shadow page tables on either EPT or shadow page tables */
-	kvm_set_cr3(vcpu, vmcs12->guest_cr3);
+	if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)
+		vcpu->arch.efer = vmcs12->guest_ia32_efer;
+	else if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE)
+		vcpu->arch.efer |= (EFER_LMA | EFER_LME);
+	else
+		vcpu->arch.efer &= ~(EFER_LMA | EFER_LME);
+	/* Note: modifies VM_ENTRY/EXIT_CONTROLS and GUEST/HOST_IA32_EFER */
+	vmx_set_efer(vcpu, vcpu->arch.efer);
+
+	/* Shadow page tables on either EPT or shadow page tables. */
+	if (nested_vmx_load_cr3(vcpu, vmcs12->guest_cr3, nested_ept_enabled,
+				entry_failure_code))
+		return 1;
+
 	kvm_mmu_reset_context(vcpu);
 
 	if (!enable_ept)
@@ -10115,6 +10364,7 @@ static void prepare_vmcs02(struct kvm_vc
 
 	kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
 	kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip);
+	return 0;
 }
 
 /*
@@ -10129,12 +10379,14 @@ static int nested_vmx_run(struct kvm_vcp
 	struct loaded_vmcs *vmcs02;
 	bool ia32e;
 	u32 msr_entry_idx;
+	unsigned long exit_qualification;
 
-	if (!nested_vmx_check_permission(vcpu) ||
-	    !nested_vmx_check_vmcs12(vcpu))
+	if (!nested_vmx_check_permission(vcpu))
 		return 1;
 
-	skip_emulated_instruction(vcpu);
+	if (!nested_vmx_check_vmcs12(vcpu))
+		goto out;
+
 	vmcs12 = get_vmcs12(vcpu);
 
 	if (enable_shadow_vmcs)
@@ -10154,37 +10406,37 @@ static int nested_vmx_run(struct kvm_vcp
 		nested_vmx_failValid(vcpu,
 			launch ? VMXERR_VMLAUNCH_NONCLEAR_VMCS
 			       : VMXERR_VMRESUME_NONLAUNCHED_VMCS);
-		return 1;
+		goto out;
 	}
 
 	if (vmcs12->guest_activity_state != GUEST_ACTIVITY_ACTIVE &&
 	    vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT) {
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
-		return 1;
+		goto out;
 	}
 
 	if (!nested_get_vmcs12_pages(vcpu, vmcs12)) {
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
-		return 1;
+		goto out;
 	}
 
 	if (nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12)) {
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
-		return 1;
+		goto out;
 	}
 
 	if (nested_vmx_check_apicv_controls(vcpu, vmcs12)) {
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
-		return 1;
+		goto out;
 	}
 
 	if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12)) {
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
-		return 1;
+		goto out;
 	}
 
 	if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
-				vmx->nested.nested_vmx_true_procbased_ctls_low,
+				vmx->nested.nested_vmx_procbased_ctls_low,
 				vmx->nested.nested_vmx_procbased_ctls_high) ||
 	    !vmx_control_verify(vmcs12->secondary_vm_exec_control,
 				vmx->nested.nested_vmx_secondary_ctls_low,
@@ -10193,25 +10445,26 @@ static int nested_vmx_run(struct kvm_vcp
 				vmx->nested.nested_vmx_pinbased_ctls_low,
 				vmx->nested.nested_vmx_pinbased_ctls_high) ||
 	    !vmx_control_verify(vmcs12->vm_exit_controls,
-				vmx->nested.nested_vmx_true_exit_ctls_low,
+				vmx->nested.nested_vmx_exit_ctls_low,
 				vmx->nested.nested_vmx_exit_ctls_high) ||
 	    !vmx_control_verify(vmcs12->vm_entry_controls,
-				vmx->nested.nested_vmx_true_entry_ctls_low,
+				vmx->nested.nested_vmx_entry_ctls_low,
 				vmx->nested.nested_vmx_entry_ctls_high))
 	{
 		nested_vmx_failValid(vcpu, VMXERR_ENTRY_INVALID_CONTROL_FIELD);
-		return 1;
+		goto out;
 	}
 
-	if (((vmcs12->host_cr0 & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) ||
-	    ((vmcs12->host_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) {
+	if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) ||
+	    !nested_host_cr4_valid(vcpu, vmcs12->host_cr4) ||
+	    !nested_cr3_valid(vcpu, vmcs12->host_cr3)) {
 		nested_vmx_failValid(vcpu,
 			VMXERR_ENTRY_INVALID_HOST_STATE_FIELD);
-		return 1;
+		goto out;
 	}
 
-	if (!nested_cr0_valid(vcpu, vmcs12->guest_cr0) ||
-	    ((vmcs12->guest_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) {
+	if (!nested_guest_cr0_valid(vcpu, vmcs12->guest_cr0) ||
+	    !nested_guest_cr4_valid(vcpu, vmcs12->guest_cr4)) {
 		nested_vmx_entry_failure(vcpu, vmcs12,
 			EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);
 		return 1;
@@ -10270,6 +10523,12 @@ static int nested_vmx_run(struct kvm_vcp
 	if (!vmcs02)
 		return -ENOMEM;
 
+	/*
+	 * After this point, the trap flag no longer triggers a singlestep trap
+	 * on the vm entry instructions. Don't call
+	 * kvm_skip_emulated_instruction.
+	 */
+	skip_emulated_instruction(vcpu);
 	enter_guest_mode(vcpu);
 
 	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
@@ -10284,7 +10543,13 @@ static int nested_vmx_run(struct kvm_vcp
 
 	vmx_segment_cache_clear(vmx);
 
-	prepare_vmcs02(vcpu, vmcs12);
+	if (prepare_vmcs02(vcpu, vmcs12, &exit_qualification)) {
+		leave_guest_mode(vcpu);
+		vmx_load_vmcs01(vcpu);
+		nested_vmx_entry_failure(vcpu, vmcs12,
+				EXIT_REASON_INVALID_STATE, exit_qualification);
+		return 1;
+	}
 
 	msr_entry_idx = nested_vmx_load_msr(vcpu,
 					    vmcs12->vm_entry_msr_load_addr,
@@ -10311,6 +10576,9 @@ static int nested_vmx_run(struct kvm_vcp
 	 * the success flag) when L2 exits (see nested_vmx_vmexit()).
 	 */
 	return 1;
+
+out:
+	return kvm_skip_emulated_instruction(vcpu);
 }
 
 /*
@@ -10616,6 +10884,7 @@ static void load_vmcs12_host_state(struc
 				   struct vmcs12 *vmcs12)
 {
 	struct kvm_segment seg;
+	unsigned long entry_failure_code;
 
 	if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
 		vcpu->arch.efer = vmcs12->host_ia32_efer;
@@ -10653,8 +10922,12 @@ static void load_vmcs12_host_state(struc
 
 	nested_ept_uninit_mmu_context(vcpu);
 
-	kvm_set_cr3(vcpu, vmcs12->host_cr3);
-	kvm_mmu_reset_context(vcpu);
+	/*
+	 * Only PDPTE load can fail as the value of cr3 was checked on entry and
+	 * couldn't have changed.
+	 */
+	if (nested_vmx_load_cr3(vcpu, vmcs12->host_cr3, false, &entry_failure_code))
+		nested_vmx_abort(vcpu, VMX_ABORT_LOAD_HOST_PDPTE_FAIL);
 
 	if (!enable_ept)
 		vcpu->arch.walk_mmu->inject_page_fault = kvm_inject_page_fault;
@@ -10755,6 +11028,7 @@ static void nested_vmx_vmexit(struct kvm
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+	u32 vm_inst_error = 0;
 
 	/* trying to cancel vmlaunch/vmresume is a bug */
 	WARN_ON_ONCE(vmx->nested.nested_run_pending);
@@ -10767,6 +11041,9 @@ static void nested_vmx_vmexit(struct kvm
 				 vmcs12->vm_exit_msr_store_count))
 		nested_vmx_abort(vcpu, VMX_ABORT_SAVE_GUEST_MSR_FAIL);
 
+	if (unlikely(vmx->fail))
+		vm_inst_error = vmcs_read32(VM_INSTRUCTION_ERROR);
+
 	vmx_load_vmcs01(vcpu);
 
 	if ((exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT)
@@ -10795,6 +11072,8 @@ static void nested_vmx_vmexit(struct kvm
 	load_vmcs12_host_state(vcpu, vmcs12);
 
 	/* Update any VMCS fields that might have changed while L2 ran */
+	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.nr);
+	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.nr);
 	vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
 	if (vmx->hv_deadline_tsc == -1)
 		vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,
@@ -10843,7 +11122,7 @@ static void nested_vmx_vmexit(struct kvm
 	 */
 	if (unlikely(vmx->fail)) {
 		vmx->fail = 0;
-		nested_vmx_failValid(vcpu, vmcs_read32(VM_INSTRUCTION_ERROR));
+		nested_vmx_failValid(vcpu, vm_inst_error);
 	} else
 		nested_vmx_succeed(vcpu);
 	if (enable_shadow_vmcs)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/kvm/x86.c linux-libre-4.10-rc8-gnu/arch/x86/kvm/x86.c
--- linux-libre-4.9-gnu/arch/x86/kvm/x86.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/kvm/x86.c	2017-02-12 16:03:20.000000000 -0500
@@ -434,12 +434,14 @@ void kvm_requeue_exception(struct kvm_vc
 }
 EXPORT_SYMBOL_GPL(kvm_requeue_exception);
 
-void kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err)
+int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err)
 {
 	if (err)
 		kvm_inject_gp(vcpu, 0);
 	else
-		kvm_x86_ops->skip_emulated_instruction(vcpu);
+		return kvm_skip_emulated_instruction(vcpu);
+
+	return 1;
 }
 EXPORT_SYMBOL_GPL(kvm_complete_insn_gp);
 
@@ -573,7 +575,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(load_pdptrs);
 
-static bool pdptrs_changed(struct kvm_vcpu *vcpu)
+bool pdptrs_changed(struct kvm_vcpu *vcpu)
 {
 	u64 pdpte[ARRAY_SIZE(vcpu->arch.walk_mmu->pdptrs)];
 	bool changed = true;
@@ -599,6 +601,7 @@ out:
 
 	return changed;
 }
+EXPORT_SYMBOL_GPL(pdptrs_changed);
 
 int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
@@ -1128,8 +1131,8 @@ struct pvclock_gtod_data {
 
 	struct { /* extract of a clocksource struct */
 		int vclock_mode;
-		cycle_t	cycle_last;
-		cycle_t	mask;
+		u64	cycle_last;
+		u64	mask;
 		u32	mult;
 		u32	shift;
 	} clock;
@@ -1569,9 +1572,9 @@ static inline void adjust_tsc_offset_hos
 
 #ifdef CONFIG_X86_64
 
-static cycle_t read_tsc(void)
+static u64 read_tsc(void)
 {
-	cycle_t ret = (cycle_t)rdtsc_ordered();
+	u64 ret = (u64)rdtsc_ordered();
 	u64 last = pvclock_gtod_data.clock.cycle_last;
 
 	if (likely(ret >= last))
@@ -1589,7 +1592,7 @@ static cycle_t read_tsc(void)
 	return last;
 }
 
-static inline u64 vgettsc(cycle_t *cycle_now)
+static inline u64 vgettsc(u64 *cycle_now)
 {
 	long v;
 	struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
@@ -1600,7 +1603,7 @@ static inline u64 vgettsc(cycle_t *cycle
 	return v * gtod->clock.mult;
 }
 
-static int do_monotonic_boot(s64 *t, cycle_t *cycle_now)
+static int do_monotonic_boot(s64 *t, u64 *cycle_now)
 {
 	struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
 	unsigned long seq;
@@ -1621,7 +1624,7 @@ static int do_monotonic_boot(s64 *t, cyc
 }
 
 /* returns true if host is using tsc clocksource */
-static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
+static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *cycle_now)
 {
 	/* checked again under seqlock below */
 	if (pvclock_gtod_data.clock.vclock_mode != VCLOCK_TSC)
@@ -2071,6 +2074,8 @@ static void record_steal_time(struct kvm
 		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time))))
 		return;
 
+	vcpu->arch.st.steal.preempted = 0;
+
 	if (vcpu->arch.st.steal.version & 1)
 		vcpu->arch.st.steal.version += 1;  /* first time write, random junk */
 
@@ -2176,7 +2181,6 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		break;
 	case MSR_KVM_SYSTEM_TIME_NEW:
 	case MSR_KVM_SYSTEM_TIME: {
-		u64 gpa_offset;
 		struct kvm_arch *ka = &vcpu->kvm->arch;
 
 		kvmclock_reset(vcpu);
@@ -2198,8 +2202,6 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		if (!(data & 1))
 			break;
 
-		gpa_offset = data & ~(PAGE_MASK | 1);
-
 		if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
 		     &vcpu->arch.pv_time, data & ~1ULL,
 		     sizeof(struct pvclock_vcpu_time_info)))
@@ -2294,7 +2296,7 @@ int kvm_set_msr_common(struct kvm_vcpu *
 		if (kvm_pmu_is_valid_msr(vcpu, msr))
 			return kvm_pmu_set_msr(vcpu, msr_info);
 		if (!ignore_msrs) {
-			vcpu_unimpl(vcpu, "unhandled wrmsr: 0x%x data 0x%llx\n",
+			vcpu_debug_ratelimited(vcpu, "unhandled wrmsr: 0x%x data 0x%llx\n",
 				    msr, data);
 			return 1;
 		} else {
@@ -2506,7 +2508,8 @@ int kvm_get_msr_common(struct kvm_vcpu *
 		if (kvm_pmu_is_valid_msr(vcpu, msr_info->index))
 			return kvm_pmu_get_msr(vcpu, msr_info->index, &msr_info->data);
 		if (!ignore_msrs) {
-			vcpu_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr_info->index);
+			vcpu_debug_ratelimited(vcpu, "unhandled rdmsr: 0x%x\n",
+					       msr_info->index);
 			return 1;
 		} else {
 			vcpu_unimpl(vcpu, "ignored rdmsr: 0x%x\n", msr_info->index);
@@ -2810,7 +2813,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 		}
 		if (kvm_lapic_hv_timer_in_use(vcpu) &&
 				kvm_x86_ops->set_hv_timer(vcpu,
-					kvm_get_lapic_tscdeadline_msr(vcpu)))
+					kvm_get_lapic_target_expiration_tsc(vcpu)))
 			kvm_lapic_switch_to_sw_timer(vcpu);
 		/*
 		 * On a host with synchronized TSC, there is no need to update
@@ -2826,8 +2829,39 @@ void kvm_arch_vcpu_load(struct kvm_vcpu
 	kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
 }
 
+static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
+{
+	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
+		return;
+
+	vcpu->arch.st.steal.preempted = 1;
+
+	kvm_write_guest_offset_cached(vcpu->kvm, &vcpu->arch.st.stime,
+			&vcpu->arch.st.steal.preempted,
+			offsetof(struct kvm_steal_time, preempted),
+			sizeof(vcpu->arch.st.steal.preempted));
+}
+
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+	int idx;
+	/*
+	 * Disable page faults because we're in atomic context here.
+	 * kvm_write_guest_offset_cached() would call might_fault()
+	 * that relies on pagefault_disable() to tell if there's a
+	 * bug. NOTE: the write to guest memory may not go through if
+	 * during postcopy live migration or if there's heavy guest
+	 * paging.
+	 */
+	pagefault_disable();
+	/*
+	 * kvm_memslots() will be called by
+	 * kvm_write_guest_offset_cached() so take the srcu lock.
+	 */
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
+	kvm_steal_time_set_preempted(vcpu);
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
+	pagefault_enable();
 	kvm_x86_ops->vcpu_put(vcpu);
 	kvm_put_guest_fpu(vcpu);
 	vcpu->arch.last_host_tsc = rdtsc();
@@ -3036,6 +3070,8 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_
 	memset(&events->reserved, 0, sizeof(events->reserved));
 }
 
+static void kvm_set_hflags(struct kvm_vcpu *vcpu, unsigned emul_flags);
+
 static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
 					      struct kvm_vcpu_events *events)
 {
@@ -3072,10 +3108,13 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_e
 		vcpu->arch.apic->sipi_vector = events->sipi_vector;
 
 	if (events->flags & KVM_VCPUEVENT_VALID_SMM) {
+		u32 hflags = vcpu->arch.hflags;
 		if (events->smi.smm)
-			vcpu->arch.hflags |= HF_SMM_MASK;
+			hflags |= HF_SMM_MASK;
 		else
-			vcpu->arch.hflags &= ~HF_SMM_MASK;
+			hflags &= ~HF_SMM_MASK;
+		kvm_set_hflags(vcpu, hflags);
+
 		vcpu->arch.smi_pending = events->smi.pending;
 		if (events->smi.smm_inside_nmi)
 			vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK;
@@ -3143,6 +3182,7 @@ static void fill_xsave(u8 *dest, struct
 	memcpy(dest, xsave, XSAVE_HDR_OFFSET);
 
 	/* Set XSTATE_BV */
+	xstate_bv &= vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FPSSE;
 	*(u64 *)(dest + XSAVE_HDR_OFFSET) = xstate_bv;
 
 	/*
@@ -3303,6 +3343,8 @@ static int kvm_vcpu_ioctl_enable_cap(str
 
 	switch (cap->cap) {
 	case KVM_CAP_HYPERV_SYNIC:
+		if (!irqchip_in_kernel(vcpu->kvm))
+			return -EINVAL;
 		return kvm_hv_activate_synic(vcpu);
 	default:
 		return -EINVAL;
@@ -4816,7 +4858,7 @@ static void emulator_invlpg(struct x86_e
 	kvm_mmu_invlpg(emul_to_vcpu(ctxt), address);
 }
 
-int kvm_emulate_wbinvd_noskip(struct kvm_vcpu *vcpu)
+static int kvm_emulate_wbinvd_noskip(struct kvm_vcpu *vcpu)
 {
 	if (!need_emulate_wbinvd(vcpu))
 		return X86EMUL_CONTINUE;
@@ -4836,8 +4878,8 @@ int kvm_emulate_wbinvd_noskip(struct kvm
 
 int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu)
 {
-	kvm_x86_ops->skip_emulated_instruction(vcpu);
-	return kvm_emulate_wbinvd_noskip(vcpu);
+	kvm_emulate_wbinvd_noskip(vcpu);
+	return kvm_skip_emulated_instruction(vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_wbinvd);
 
@@ -5081,11 +5123,6 @@ static void emulator_get_fpu(struct x86_
 {
 	preempt_disable();
 	kvm_load_guest_fpu(emul_to_vcpu(ctxt));
-	/*
-	 * CR0.TS may reference the host fpu state, not the guest fpu state,
-	 * so it may be clear at this point.
-	 */
-	clts();
 }
 
 static void emulator_put_fpu(struct x86_emulate_ctxt *ctxt)
@@ -5440,7 +5477,6 @@ static void kvm_vcpu_check_singlestep(st
 			kvm_run->exit_reason = KVM_EXIT_DEBUG;
 			*r = EMULATE_USER_EXIT;
 		} else {
-			vcpu->arch.emulate_ctxt.eflags &= ~X86_EFLAGS_TF;
 			/*
 			 * "Certain debug exceptions may clear bit 0-3.  The
 			 * remaining contents of the DR6 register are never
@@ -5453,6 +5489,17 @@ static void kvm_vcpu_check_singlestep(st
 	}
 }
 
+int kvm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
+{
+	unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
+	int r = EMULATE_DONE;
+
+	kvm_x86_ops->skip_emulated_instruction(vcpu);
+	kvm_vcpu_check_singlestep(vcpu, rflags, &r);
+	return r == EMULATE_DONE;
+}
+EXPORT_SYMBOL_GPL(kvm_skip_emulated_instruction);
+
 static bool kvm_vcpu_check_breakpoint(struct kvm_vcpu *vcpu, int *r)
 {
 	if (unlikely(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) &&
@@ -5638,6 +5685,49 @@ int kvm_fast_pio_out(struct kvm_vcpu *vc
 }
 EXPORT_SYMBOL_GPL(kvm_fast_pio_out);
 
+static int complete_fast_pio_in(struct kvm_vcpu *vcpu)
+{
+	unsigned long val;
+
+	/* We should only ever be called with arch.pio.count equal to 1 */
+	BUG_ON(vcpu->arch.pio.count != 1);
+
+	/* For size less than 4 we merge, else we zero extend */
+	val = (vcpu->arch.pio.size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX)
+					: 0;
+
+	/*
+	 * Since vcpu->arch.pio.count == 1 let emulator_pio_in_emulated perform
+	 * the copy and tracing
+	 */
+	emulator_pio_in_emulated(&vcpu->arch.emulate_ctxt, vcpu->arch.pio.size,
+				 vcpu->arch.pio.port, &val, 1);
+	kvm_register_write(vcpu, VCPU_REGS_RAX, val);
+
+	return 1;
+}
+
+int kvm_fast_pio_in(struct kvm_vcpu *vcpu, int size, unsigned short port)
+{
+	unsigned long val;
+	int ret;
+
+	/* For size less than 4 we merge, else we zero extend */
+	val = (size < 4) ? kvm_register_read(vcpu, VCPU_REGS_RAX) : 0;
+
+	ret = emulator_pio_in_emulated(&vcpu->arch.emulate_ctxt, size, port,
+				       &val, 1);
+	if (ret) {
+		kvm_register_write(vcpu, VCPU_REGS_RAX, val);
+		return ret;
+	}
+
+	vcpu->arch.complete_userspace_io = complete_fast_pio_in;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(kvm_fast_pio_in);
+
 static int kvmclock_cpu_down_prep(unsigned int cpu)
 {
 	__this_cpu_write(cpu_tsc_khz, 0);
@@ -5773,7 +5863,7 @@ static void kvm_timer_init(void)
 	}
 	pr_debug("kvm: max_tsc_khz = %ld\n", max_tsc_khz);
 
-	cpuhp_setup_state(CPUHP_AP_X86_KVM_CLK_ONLINE, "AP_X86_KVM_CLK_ONLINE",
+	cpuhp_setup_state(CPUHP_AP_X86_KVM_CLK_ONLINE, "x86/kvm/clk:online",
 			  kvmclock_cpu_online, kvmclock_cpu_down_prep);
 }
 
@@ -5958,6 +6048,7 @@ out:
 
 void kvm_arch_exit(void)
 {
+	kvm_lapic_exit();
 	perf_unregister_guest_info_callbacks(&kvm_guest_cbs);
 
 	if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
@@ -5987,8 +6078,12 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_halt);
 
 int kvm_emulate_halt(struct kvm_vcpu *vcpu)
 {
-	kvm_x86_ops->skip_emulated_instruction(vcpu);
-	return kvm_vcpu_halt(vcpu);
+	int ret = kvm_skip_emulated_instruction(vcpu);
+	/*
+	 * TODO: we might be squashing a GUESTDBG_SINGLESTEP-triggered
+	 * KVM_EXIT_DEBUG here.
+	 */
+	return kvm_vcpu_halt(vcpu) && ret;
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_halt);
 
@@ -6019,9 +6114,9 @@ void kvm_vcpu_deactivate_apicv(struct kv
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 {
 	unsigned long nr, a0, a1, a2, a3, ret;
-	int op_64_bit, r = 1;
+	int op_64_bit, r;
 
-	kvm_x86_ops->skip_emulated_instruction(vcpu);
+	r = kvm_skip_emulated_instruction(vcpu);
 
 	if (kvm_hv_hypercall_enabled(vcpu->kvm))
 		return kvm_hv_hypercall(vcpu);
@@ -6077,7 +6172,8 @@ static int emulator_fix_hypercall(struct
 
 	kvm_x86_ops->patch_hypercall(vcpu, instruction);
 
-	return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
+	return emulator_write_emulated(ctxt, rip, instruction, 3,
+		&ctxt->exception);
 }
 
 static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu)
@@ -7407,25 +7503,13 @@ void kvm_load_guest_fpu(struct kvm_vcpu
 
 void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
 {
-	if (!vcpu->guest_fpu_loaded) {
-		vcpu->fpu_counter = 0;
+	if (!vcpu->guest_fpu_loaded)
 		return;
-	}
 
 	vcpu->guest_fpu_loaded = 0;
 	copy_fpregs_to_fpstate(&vcpu->arch.guest_fpu);
 	__kernel_fpu_end();
 	++vcpu->stat.fpu_reload;
-	/*
-	 * If using eager FPU mode, or if the guest is a frequent user
-	 * of the FPU, just leave the FPU active for next time.
-	 * Every 255 times fpu_counter rolls over to 0; a guest that uses
-	 * the FPU in bursts will revert to loading it on demand.
-	 */
-	if (!use_eager_fpu()) {
-		if (++vcpu->fpu_counter < 5)
-			kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
-	}
 	trace_kvm_fpu(0);
 }
 
@@ -7824,6 +7908,7 @@ int kvm_arch_init_vm(struct kvm *kvm, un
 
 	raw_spin_lock_init(&kvm->arch.tsc_write_lock);
 	mutex_init(&kvm->arch.apic_map_lock);
+	mutex_init(&kvm->arch.hyperv.hv_lock);
 	spin_lock_init(&kvm->arch.pvclock_gtod_sync_lock);
 
 	kvm->arch.kvmclock_offset = -ktime_get_boot_ns();
@@ -8176,7 +8261,7 @@ void kvm_arch_flush_shadow_all(struct kv
 void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
 				   struct kvm_memory_slot *slot)
 {
-	kvm_mmu_invalidate_zap_all_pages(kvm);
+	kvm_page_track_flush_slot(kvm, slot);
 }
 
 static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/lguest/boot.c linux-libre-4.10-rc8-gnu/arch/x86/lguest/boot.c
--- linux-libre-4.9-gnu/arch/x86/lguest/boot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/lguest/boot.c	2017-02-12 16:03:20.000000000 -0500
@@ -497,38 +497,24 @@ static void lguest_cpuid(unsigned int *a
  * a whole series of functions like read_cr0() and write_cr0().
  *
  * We start with cr0.  cr0 allows you to turn on and off all kinds of basic
- * features, but Linux only really cares about one: the horrifically-named Task
- * Switched (TS) bit at bit 3 (ie. 8)
+ * features, but the only cr0 bit that Linux ever used at runtime was the
+ * horrifically-named Task Switched (TS) bit at bit 3 (ie. 8)
  *
  * What does the TS bit do?  Well, it causes the CPU to trap (interrupt 7) if
  * the floating point unit is used.  Which allows us to restore FPU state
- * lazily after a task switch, and Linux uses that gratefully, but wouldn't a
- * name like "FPUTRAP bit" be a little less cryptic?
+ * lazily after a task switch if we wanted to, but wouldn't a name like
+ * "FPUTRAP bit" be a little less cryptic?
  *
- * We store cr0 locally because the Host never changes it.  The Guest sometimes
- * wants to read it and we'd prefer not to bother the Host unnecessarily.
+ * Fortunately, Linux keeps it simple and doesn't use TS, so we can ignore
+ * cr0.
  */
-static unsigned long current_cr0;
 static void lguest_write_cr0(unsigned long val)
 {
-	lazy_hcall1(LHCALL_TS, val & X86_CR0_TS);
-	current_cr0 = val;
 }
 
 static unsigned long lguest_read_cr0(void)
 {
-	return current_cr0;
-}
-
-/*
- * Intel provided a special instruction to clear the TS bit for people too cool
- * to use write_cr0() to do it.  This "clts" instruction is faster, because all
- * the vowels have been optimized out.
- */
-static void lguest_clts(void)
-{
-	lazy_hcall1(LHCALL_TS, 0);
-	current_cr0 &= ~X86_CR0_TS;
+	return 0;
 }
 
 /*
@@ -930,7 +916,7 @@ static unsigned long lguest_tsc_khz(void
  * If we can't use the TSC, the kernel falls back to our lower-priority
  * "lguest_clock", where we read the time value given to us by the Host.
  */
-static cycle_t lguest_clock_read(struct clocksource *cs)
+static u64 lguest_clock_read(struct clocksource *cs)
 {
 	unsigned long sec, nsec;
 
@@ -1432,7 +1418,6 @@ __init void lguest_init(void)
 	pv_cpu_ops.load_tls = lguest_load_tls;
 	pv_cpu_ops.get_debugreg = lguest_get_debugreg;
 	pv_cpu_ops.set_debugreg = lguest_set_debugreg;
-	pv_cpu_ops.clts = lguest_clts;
 	pv_cpu_ops.read_cr0 = lguest_read_cr0;
 	pv_cpu_ops.write_cr0 = lguest_write_cr0;
 	pv_cpu_ops.read_cr4 = lguest_read_cr4;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/lib/copy_user_64.S linux-libre-4.10-rc8-gnu/arch/x86/lib/copy_user_64.S
--- linux-libre-4.9-gnu/arch/x86/lib/copy_user_64.S	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/lib/copy_user_64.S	2017-02-12 16:03:20.000000000 -0500
@@ -16,53 +16,6 @@
 #include <asm/smap.h>
 #include <asm/export.h>
 
-/* Standard copy_to_user with segment limit checking */
-ENTRY(_copy_to_user)
-	mov PER_CPU_VAR(current_task), %rax
-	movq %rdi,%rcx
-	addq %rdx,%rcx
-	jc bad_to_user
-	cmpq TASK_addr_limit(%rax),%rcx
-	ja bad_to_user
-	ALTERNATIVE_2 "jmp copy_user_generic_unrolled",		\
-		      "jmp copy_user_generic_string",		\
-		      X86_FEATURE_REP_GOOD,			\
-		      "jmp copy_user_enhanced_fast_string",	\
-		      X86_FEATURE_ERMS
-ENDPROC(_copy_to_user)
-EXPORT_SYMBOL(_copy_to_user)
-
-/* Standard copy_from_user with segment limit checking */
-ENTRY(_copy_from_user)
-	mov PER_CPU_VAR(current_task), %rax
-	movq %rsi,%rcx
-	addq %rdx,%rcx
-	jc bad_from_user
-	cmpq TASK_addr_limit(%rax),%rcx
-	ja bad_from_user
-	ALTERNATIVE_2 "jmp copy_user_generic_unrolled",		\
-		      "jmp copy_user_generic_string",		\
-		      X86_FEATURE_REP_GOOD,			\
-		      "jmp copy_user_enhanced_fast_string",	\
-		      X86_FEATURE_ERMS
-ENDPROC(_copy_from_user)
-EXPORT_SYMBOL(_copy_from_user)
-
-
-	.section .fixup,"ax"
-	/* must zero dest */
-ENTRY(bad_from_user)
-bad_from_user:
-	movl %edx,%ecx
-	xorl %eax,%eax
-	rep
-	stosb
-bad_to_user:
-	movl %edx,%eax
-	ret
-ENDPROC(bad_from_user)
-	.previous
-
 /*
  * copy_user_generic_unrolled - memory copy with exception handling.
  * This version is for CPUs like P4 that don't have efficient micro
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/lib/msr.c linux-libre-4.10-rc8-gnu/arch/x86/lib/msr.c
--- linux-libre-4.9-gnu/arch/x86/lib/msr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/lib/msr.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,14 +113,14 @@ int msr_clear_bit(u32 msr, u8 bit)
 }
 
 #ifdef CONFIG_TRACEPOINTS
-void do_trace_write_msr(unsigned msr, u64 val, int failed)
+void do_trace_write_msr(unsigned int msr, u64 val, int failed)
 {
 	trace_write_msr(msr, val, failed);
 }
 EXPORT_SYMBOL(do_trace_write_msr);
 EXPORT_TRACEPOINT_SYMBOL(write_msr);
 
-void do_trace_read_msr(unsigned msr, u64 val, int failed)
+void do_trace_read_msr(unsigned int msr, u64 val, int failed)
 {
 	trace_read_msr(msr, val, failed);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/lib/usercopy_32.c linux-libre-4.10-rc8-gnu/arch/x86/lib/usercopy_32.c
--- linux-libre-4.9-gnu/arch/x86/lib/usercopy_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/lib/usercopy_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/export.h>
 #include <linux/backing-dev.h>
 #include <linux/interrupt.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmx.h>
 #include <asm/asm.h>
 
@@ -640,52 +640,3 @@ unsigned long __copy_from_user_ll_nocach
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
-
-/**
- * copy_to_user: - Copy a block of data into user space.
- * @to:   Destination address, in user space.
- * @from: Source address, in kernel space.
- * @n:    Number of bytes to copy.
- *
- * Context: User context only. This function may sleep if pagefaults are
- *          enabled.
- *
- * Copy data from kernel space to user space.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- */
-unsigned long _copy_to_user(void __user *to, const void *from, unsigned n)
-{
-	if (access_ok(VERIFY_WRITE, to, n))
-		n = __copy_to_user(to, from, n);
-	return n;
-}
-EXPORT_SYMBOL(_copy_to_user);
-
-/**
- * copy_from_user: - Copy a block of data from user space.
- * @to:   Destination address, in kernel space.
- * @from: Source address, in user space.
- * @n:    Number of bytes to copy.
- *
- * Context: User context only. This function may sleep if pagefaults are
- *          enabled.
- *
- * Copy data from user space to kernel space.
- *
- * Returns number of bytes that could not be copied.
- * On success, this will be zero.
- *
- * If some data could not be copied, this function will pad the copied
- * data to the requested size using zero bytes.
- */
-unsigned long _copy_from_user(void *to, const void __user *from, unsigned n)
-{
-	if (access_ok(VERIFY_READ, from, n))
-		n = __copy_from_user(to, from, n);
-	else
-		memset(to, 0, n);
-	return n;
-}
-EXPORT_SYMBOL(_copy_from_user);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/lib/usercopy.c linux-libre-4.10-rc8-gnu/arch/x86/lib/usercopy.c
--- linux-libre-4.9-gnu/arch/x86/lib/usercopy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/lib/usercopy.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,3 +34,52 @@ copy_from_user_nmi(void *to, const void
 	return ret;
 }
 EXPORT_SYMBOL_GPL(copy_from_user_nmi);
+
+/**
+ * copy_to_user: - Copy a block of data into user space.
+ * @to:   Destination address, in user space.
+ * @from: Source address, in kernel space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only. This function may sleep if pagefaults are
+ *          enabled.
+ *
+ * Copy data from kernel space to user space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ */
+unsigned long _copy_to_user(void __user *to, const void *from, unsigned n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		n = __copy_to_user(to, from, n);
+	return n;
+}
+EXPORT_SYMBOL(_copy_to_user);
+
+/**
+ * copy_from_user: - Copy a block of data from user space.
+ * @to:   Destination address, in kernel space.
+ * @from: Source address, in user space.
+ * @n:    Number of bytes to copy.
+ *
+ * Context: User context only. This function may sleep if pagefaults are
+ *          enabled.
+ *
+ * Copy data from user space to kernel space.
+ *
+ * Returns number of bytes that could not be copied.
+ * On success, this will be zero.
+ *
+ * If some data could not be copied, this function will pad the copied
+ * data to the requested size using zero bytes.
+ */
+unsigned long _copy_from_user(void *to, const void __user *from, unsigned n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		n = __copy_from_user(to, from, n);
+	else
+		memset(to, 0, n);
+	return n;
+}
+EXPORT_SYMBOL(_copy_from_user);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/math-emu/errors.c linux-libre-4.10-rc8-gnu/arch/x86/math-emu/errors.c
--- linux-libre-4.9-gnu/arch/x86/math-emu/errors.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/math-emu/errors.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 #include <linux/signal.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "fpu_emu.h"
 #include "fpu_system.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/math-emu/fpu_entry.c linux-libre-4.10-rc8-gnu/arch/x86/math-emu/fpu_entry.c
--- linux-libre-4.9-gnu/arch/x86/math-emu/fpu_entry.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/math-emu/fpu_entry.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/signal.h>
 #include <linux/regset.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/traps.h>
 #include <asm/user.h>
 #include <asm/fpu/internal.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/math-emu/get_address.c linux-libre-4.10-rc8-gnu/arch/x86/math-emu/get_address.c
--- linux-libre-4.9-gnu/arch/x86/math-emu/get_address.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/math-emu/get_address.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 #include <linux/stddef.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/vm86.h>
 
 #include "fpu_system.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/math-emu/load_store.c linux-libre-4.10-rc8-gnu/arch/x86/math-emu/load_store.c
--- linux-libre-4.9-gnu/arch/x86/math-emu/load_store.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/math-emu/load_store.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
  |    other processes using the emulator while swapping is in progress.      |
  +---------------------------------------------------------------------------*/
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/math-emu/reg_ld_str.c linux-libre-4.10-rc8-gnu/arch/x86/math-emu/reg_ld_str.c
--- linux-libre-4.9-gnu/arch/x86/math-emu/reg_ld_str.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/math-emu/reg_ld_str.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 #include "fpu_emu.h"
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "fpu_system.h"
 #include "exception.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/dump_pagetables.c linux-libre-4.10-rc8-gnu/arch/x86/mm/dump_pagetables.c
--- linux-libre-4.9-gnu/arch/x86/mm/dump_pagetables.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/dump_pagetables.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/debugfs.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
 
 #include <asm/pgtable.h>
@@ -406,6 +407,7 @@ static void ptdump_walk_pgd_level_core(s
 		} else
 			note_page(m, &st, __pgprot(0), 1);
 
+		cond_resched();
 		start++;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/extable.c linux-libre-4.10-rc8-gnu/arch/x86/mm/extable.c
--- linux-libre-4.9-gnu/arch/x86/mm/extable.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/extable.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 #include <linux/extable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/traps.h>
 #include <asm/kdebug.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/fault.c linux-libre-4.10-rc8-gnu/arch/x86/mm/fault.c
--- linux-libre-4.9-gnu/arch/x86/mm/fault.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/fault.c	2017-02-12 16:03:20.000000000 -0500
@@ -413,7 +413,7 @@ out:
 
 void vmalloc_sync_all(void)
 {
-	sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END, 0);
+	sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END);
 }
 
 /*
@@ -679,8 +679,7 @@ show_fault_oops(struct pt_regs *regs, un
 		printk(KERN_CONT "paging request");
 
 	printk(KERN_CONT " at %p\n", (void *) address);
-	printk(KERN_ALERT "IP:");
-	printk_address(regs->ip);
+	printk(KERN_ALERT "IP: %pS\n", (void *)regs->ip);
 
 	dump_pagetable(address);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/init_32.c linux-libre-4.10-rc8-gnu/arch/x86/mm/init_32.c
--- linux-libre-4.9-gnu/arch/x86/mm/init_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/init_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <asm/asm.h>
 #include <asm/bios_ebda.h>
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/fixmap.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/init_64.c linux-libre-4.10-rc8-gnu/arch/x86/mm/init_64.c
--- linux-libre-4.9-gnu/arch/x86/mm/init_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/init_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 
 #include <asm/processor.h>
 #include <asm/bios_ebda.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
@@ -89,10 +89,10 @@ static int __init nonx32_setup(char *str
 __setup("noexec32=", nonx32_setup);
 
 /*
- * When memory was added/removed make sure all the processes MM have
+ * When memory was added make sure all the processes MM have
  * suitable PGD entries in the local PGD level page.
  */
-void sync_global_pgds(unsigned long start, unsigned long end, int removed)
+void sync_global_pgds(unsigned long start, unsigned long end)
 {
 	unsigned long address;
 
@@ -100,12 +100,7 @@ void sync_global_pgds(unsigned long star
 		const pgd_t *pgd_ref = pgd_offset_k(address);
 		struct page *page;
 
-		/*
-		 * When it is called after memory hot remove, pgd_none()
-		 * returns true. In this case (removed == 1), we must clear
-		 * the PGD entries in the local PGD level page.
-		 */
-		if (pgd_none(*pgd_ref) && !removed)
+		if (pgd_none(*pgd_ref))
 			continue;
 
 		spin_lock(&pgd_lock);
@@ -122,13 +117,8 @@ void sync_global_pgds(unsigned long star
 				BUG_ON(pgd_page_vaddr(*pgd)
 				       != pgd_page_vaddr(*pgd_ref));
 
-			if (removed) {
-				if (pgd_none(*pgd_ref) && !pgd_none(*pgd))
-					pgd_clear(pgd);
-			} else {
-				if (pgd_none(*pgd))
-					set_pgd(pgd, *pgd_ref);
-			}
+			if (pgd_none(*pgd))
+				set_pgd(pgd, *pgd_ref);
 
 			spin_unlock(pgt_lock);
 		}
@@ -596,7 +586,7 @@ kernel_physical_mapping_init(unsigned lo
 	}
 
 	if (pgd_changed)
-		sync_global_pgds(vaddr_start, vaddr_end - 1, 0);
+		sync_global_pgds(vaddr_start, vaddr_end - 1);
 
 	__flush_tlb_all();
 
@@ -1239,7 +1229,7 @@ int __meminit vmemmap_populate(unsigned
 	} else
 		err = vmemmap_populate_basepages(start, end, node);
 	if (!err)
-		sync_global_pgds(start, end - 1, 0);
+		sync_global_pgds(start, end - 1);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/mpx.c linux-libre-4.10-rc8-gnu/arch/x86/mm/mpx.c
--- linux-libre-4.9-gnu/arch/x86/mm/mpx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/mpx.c	2017-02-12 16:03:20.000000000 -0500
@@ -293,7 +293,7 @@ siginfo_t *mpx_generate_siginfo(struct p
 	 * We were not able to extract an address from the instruction,
 	 * probably because there was something invalid in it.
 	 */
-	if (info->si_addr == (void *)-1) {
+	if (info->si_addr == (void __user *)-1) {
 		err = -EINVAL;
 		goto err_out;
 	}
@@ -350,12 +350,12 @@ int mpx_enable_management(void)
 	 * The copy_xregs_to_kernel() beneath get_xsave_field_ptr() is
 	 * expected to be relatively expensive. Storing the bounds
 	 * directory here means that we do not have to do xsave in the
-	 * unmap path; we can just use mm->bd_addr instead.
+	 * unmap path; we can just use mm->context.bd_addr instead.
 	 */
 	bd_base = mpx_get_bounds_dir();
 	down_write(&mm->mmap_sem);
-	mm->bd_addr = bd_base;
-	if (mm->bd_addr == MPX_INVALID_BOUNDS_DIR)
+	mm->context.bd_addr = bd_base;
+	if (mm->context.bd_addr == MPX_INVALID_BOUNDS_DIR)
 		ret = -ENXIO;
 
 	up_write(&mm->mmap_sem);
@@ -370,7 +370,7 @@ int mpx_disable_management(void)
 		return -ENXIO;
 
 	down_write(&mm->mmap_sem);
-	mm->bd_addr = MPX_INVALID_BOUNDS_DIR;
+	mm->context.bd_addr = MPX_INVALID_BOUNDS_DIR;
 	up_write(&mm->mmap_sem);
 	return 0;
 }
@@ -947,7 +947,7 @@ static int try_unmap_single_bt(struct mm
 		end = bta_end_vaddr;
 	}
 
-	bde_vaddr = mm->bd_addr + mpx_get_bd_entry_offset(mm, start);
+	bde_vaddr = mm->context.bd_addr + mpx_get_bd_entry_offset(mm, start);
 	ret = get_bt_addr(mm, bde_vaddr, &bt_addr);
 	/*
 	 * No bounds table there, so nothing to unmap.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/numa.c linux-libre-4.10-rc8-gnu/arch/x86/mm/numa.c
--- linux-libre-4.9-gnu/arch/x86/mm/numa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/numa.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 
 #include "numa_internal.h"
 
-int __initdata numa_off;
+int numa_off;
 nodemask_t numa_nodes_parsed __initdata;
 
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/pageattr.c linux-libre-4.10-rc8-gnu/arch/x86/mm/pageattr.c
--- linux-libre-4.9-gnu/arch/x86/mm/pageattr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/pageattr.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/proto.h>
 #include <asm/pat.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/pat.c linux-libre-4.10-rc8-gnu/arch/x86/mm/pat.c
--- linux-libre-4.9-gnu/arch/x86/mm/pat.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/pat.c	2017-02-12 16:03:20.000000000 -0500
@@ -986,20 +986,17 @@ int track_pfn_remap(struct vm_area_struc
 	return 0;
 }
 
-int track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot,
-		     pfn_t pfn)
+void track_pfn_insert(struct vm_area_struct *vma, pgprot_t *prot, pfn_t pfn)
 {
 	enum page_cache_mode pcm;
 
 	if (!pat_enabled())
-		return 0;
+		return;
 
 	/* Set prot based on lookup */
 	pcm = lookup_memtype(pfn_t_to_phys(pfn));
 	*prot = __pgprot((pgprot_val(*prot) & (~_PAGE_CACHE_MASK)) |
 			 cachemode2protval(pcm));
-
-	return 0;
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/mm/pkeys.c linux-libre-4.10-rc8-gnu/arch/x86/mm/pkeys.c
--- linux-libre-4.9-gnu/arch/x86/mm/pkeys.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/mm/pkeys.c	2017-02-12 16:03:20.000000000 -0500
@@ -141,8 +141,7 @@ u32 init_pkru_value = PKRU_AD_KEY( 1) |
  * Called from the FPU code when creating a fresh set of FPU
  * registers.  This is called from a very specific context where
  * we know the FPU regstiers are safe for use and we can use PKRU
- * directly.  The fact that PKRU is only available when we are
- * using eagerfpu mode makes this possible.
+ * directly.
  */
 void copy_init_pkru_to_fpregs(void)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/net/bpf_jit_comp.c linux-libre-4.10-rc8-gnu/arch/x86/net/bpf_jit_comp.c
--- linux-libre-4.9-gnu/arch/x86/net/bpf_jit_comp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/net/bpf_jit_comp.c	2017-02-12 16:03:20.000000000 -0500
@@ -853,7 +853,7 @@ xadd:			if (is_imm8(insn->off))
 			func = (u8 *) __bpf_call_base + imm32;
 			jmp_offset = func - (image + addrs[i]);
 			if (seen_ld_abs) {
-				reload_skb_data = bpf_helper_changes_skb_data(func);
+				reload_skb_data = bpf_helper_changes_pkt_data(func);
 				if (reload_skb_data) {
 					EMIT1(0x57); /* push %rdi */
 					jmp_offset += 22; /* pop, mov, sub, mov */
@@ -1172,6 +1172,8 @@ struct bpf_prog *bpf_int_jit_compile(str
 		set_memory_ro((unsigned long)header, header->pages);
 		prog->bpf_func = (void *)image;
 		prog->jited = 1;
+	} else {
+		prog = orig_prog;
 	}
 
 out_addrs:
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/oprofile/nmi_int.c linux-libre-4.10-rc8-gnu/arch/x86/oprofile/nmi_int.c
--- linux-libre-4.9-gnu/arch/x86/oprofile/nmi_int.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/oprofile/nmi_int.c	2017-02-12 16:03:20.000000000 -0500
@@ -339,10 +339,11 @@ fail:
 	return 0;
 }
 
-static void nmi_cpu_setup(void *dummy)
+static void nmi_cpu_setup(void)
 {
 	int cpu = smp_processor_id();
 	struct op_msrs *msrs = &per_cpu(cpu_msrs, cpu);
+
 	nmi_cpu_save_registers(msrs);
 	raw_spin_lock(&oprofilefs_lock);
 	model->setup_ctrs(model, msrs);
@@ -369,7 +370,7 @@ static void nmi_cpu_restore_registers(st
 	}
 }
 
-static void nmi_cpu_shutdown(void *dummy)
+static void nmi_cpu_shutdown(void)
 {
 	unsigned int v;
 	int cpu = smp_processor_id();
@@ -387,20 +388,26 @@ static void nmi_cpu_shutdown(void *dummy
 	nmi_cpu_restore_registers(msrs);
 }
 
-static void nmi_cpu_up(void *dummy)
+static int nmi_cpu_online(unsigned int cpu)
 {
+	local_irq_disable();
 	if (nmi_enabled)
-		nmi_cpu_setup(dummy);
+		nmi_cpu_setup();
 	if (ctr_running)
-		nmi_cpu_start(dummy);
+		nmi_cpu_start(NULL);
+	local_irq_enable();
+	return 0;
 }
 
-static void nmi_cpu_down(void *dummy)
+static int nmi_cpu_down_prep(unsigned int cpu)
 {
+	local_irq_disable();
 	if (ctr_running)
-		nmi_cpu_stop(dummy);
+		nmi_cpu_stop(NULL);
 	if (nmi_enabled)
-		nmi_cpu_shutdown(dummy);
+		nmi_cpu_shutdown();
+	local_irq_enable();
+	return 0;
 }
 
 static int nmi_create_files(struct dentry *root)
@@ -433,26 +440,7 @@ static int nmi_create_files(struct dentr
 	return 0;
 }
 
-static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action,
-				 void *data)
-{
-	int cpu = (unsigned long)data;
-
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_DOWN_FAILED:
-	case CPU_ONLINE:
-		smp_call_function_single(cpu, nmi_cpu_up, NULL, 0);
-		break;
-	case CPU_DOWN_PREPARE:
-		smp_call_function_single(cpu, nmi_cpu_down, NULL, 1);
-		break;
-	}
-	return NOTIFY_DONE;
-}
-
-static struct notifier_block oprofile_cpu_nb = {
-	.notifier_call = oprofile_cpu_notifier
-};
+static enum cpuhp_state cpuhp_nmi_online;
 
 static int nmi_setup(void)
 {
@@ -495,20 +483,17 @@ static int nmi_setup(void)
 	if (err)
 		goto fail;
 
-	cpu_notifier_register_begin();
-
-	/* Use get/put_online_cpus() to protect 'nmi_enabled' */
-	get_online_cpus();
 	nmi_enabled = 1;
 	/* make nmi_enabled visible to the nmi handler: */
 	smp_mb();
-	on_each_cpu(nmi_cpu_setup, NULL, 1);
-	__register_cpu_notifier(&oprofile_cpu_nb);
-	put_online_cpus();
-
-	cpu_notifier_register_done();
-
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/oprofile:online",
+				nmi_cpu_online, nmi_cpu_down_prep);
+	if (err < 0)
+		goto fail_nmi;
+	cpuhp_nmi_online = err;
 	return 0;
+fail_nmi:
+	unregister_nmi_handler(NMI_LOCAL, "oprofile");
 fail:
 	free_msrs();
 	return err;
@@ -518,17 +503,9 @@ static void nmi_shutdown(void)
 {
 	struct op_msrs *msrs;
 
-	cpu_notifier_register_begin();
-
-	/* Use get/put_online_cpus() to protect 'nmi_enabled' & 'ctr_running' */
-	get_online_cpus();
-	on_each_cpu(nmi_cpu_shutdown, NULL, 1);
+	cpuhp_remove_state(cpuhp_nmi_online);
 	nmi_enabled = 0;
 	ctr_running = 0;
-	__unregister_cpu_notifier(&oprofile_cpu_nb);
-	put_online_cpus();
-
-	cpu_notifier_register_done();
 
 	/* make variables visible to the nmi handler: */
 	smp_mb();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/pci/acpi.c linux-libre-4.10-rc8-gnu/arch/x86/pci/acpi.c
--- linux-libre-4.9-gnu/arch/x86/pci/acpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/pci/acpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,6 +114,16 @@ static const struct dmi_system_id pci_cr
 			DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
 		},
 	},
+	/* https://bugzilla.kernel.org/show_bug.cgi?id=42606 */
+	{
+		.callback = set_nouse_crs,
+		.ident = "Supermicro X8DTH",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X8DTH-i/6/iF/6F"),
+			DMI_MATCH(DMI_BIOS_VERSION, "2.0a"),
+		},
+	},
 
 	/* https://bugzilla.kernel.org/show_bug.cgi?id=15362 */
 	{
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/pci/amd_bus.c linux-libre-4.10-rc8-gnu/arch/x86/pci/amd_bus.c
--- linux-libre-4.9-gnu/arch/x86/pci/amd_bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/pci/amd_bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -327,35 +327,18 @@ static int __init early_root_info_init(v
 
 #define ENABLE_CF8_EXT_CFG      (1ULL << 46)
 
-static void enable_pci_io_ecs(void *unused)
+static int amd_bus_cpu_online(unsigned int cpu)
 {
 	u64 reg;
+
 	rdmsrl(MSR_AMD64_NB_CFG, reg);
 	if (!(reg & ENABLE_CF8_EXT_CFG)) {
 		reg |= ENABLE_CF8_EXT_CFG;
 		wrmsrl(MSR_AMD64_NB_CFG, reg);
 	}
+	return 0;
 }
 
-static int amd_cpu_notify(struct notifier_block *self, unsigned long action,
-			  void *hcpu)
-{
-	int cpu = (long)hcpu;
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		smp_call_function_single(cpu, enable_pci_io_ecs, NULL, 0);
-		break;
-	default:
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block amd_cpu_notifier = {
-	.notifier_call	= amd_cpu_notify,
-};
-
 static void __init pci_enable_pci_io_ecs(void)
 {
 #ifdef CONFIG_AMD_NB
@@ -385,7 +368,7 @@ static void __init pci_enable_pci_io_ecs
 
 static int __init pci_io_ecs_init(void)
 {
-	int cpu;
+	int ret;
 
 	/* assume all cpus from fam10h have IO ECS */
 	if (boot_cpu_data.x86 < 0x10)
@@ -395,12 +378,9 @@ static int __init pci_io_ecs_init(void)
 	if (early_pci_allowed())
 		pci_enable_pci_io_ecs();
 
-	cpu_notifier_register_begin();
-	for_each_online_cpu(cpu)
-		amd_cpu_notify(&amd_cpu_notifier, (unsigned long)CPU_ONLINE,
-			       (void *)(long)cpu);
-	__register_cpu_notifier(&amd_cpu_notifier);
-	cpu_notifier_register_done();
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/amd_bus:online",
+				amd_bus_cpu_online, NULL);
+	WARN_ON(ret < 0);
 
 	pci_probe |= PCI_HAS_IO_ECS;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/pci/xen.c linux-libre-4.10-rc8-gnu/arch/x86/pci/xen.c
--- linux-libre-4.9-gnu/arch/x86/pci/xen.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/pci/xen.c	2017-02-12 16:03:20.000000000 -0500
@@ -264,8 +264,8 @@ static int xen_hvm_setup_msi_irqs(struct
 	return 0;
 
 error:
-	dev_err(&dev->dev,
-		"Xen PCI frontend has not registered MSI/MSI-X support!\n");
+	dev_err(&dev->dev, "Failed to create MSI%s! ret=%d!\n",
+		type == PCI_CAP_ID_MSI ? "" : "-X", irq);
 	return irq;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/ce4100/ce4100.c linux-libre-4.10-rc8-gnu/arch/x86/platform/ce4100/ce4100.c
--- linux-libre-4.9-gnu/arch/x86/platform/ce4100/ce4100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/ce4100/ce4100.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,11 +23,6 @@
 #include <asm/io_apic.h>
 #include <asm/emergency-restart.h>
 
-static int ce4100_i8042_detect(void)
-{
-	return 0;
-}
-
 /*
  * The CE4100 platform has an internal 8051 Microcontroller which is
  * responsible for signaling to the external Power Management Unit the
@@ -89,7 +84,7 @@ static void ce4100_mem_serial_out(struct
 }
 
 static void ce4100_serial_fixup(int port, struct uart_port *up,
-	unsigned short *capabilites)
+	u32 *capabilites)
 {
 #ifdef CONFIG_EARLY_PRINTK
 	/*
@@ -145,7 +140,6 @@ static void sdv_pci_init(void)
 void __init x86_ce4100_early_setup(void)
 {
 	x86_init.oem.arch_setup = sdv_arch_setup;
-	x86_platform.i8042_detect = ce4100_i8042_detect;
 	x86_init.resources.probe_roms = x86_init_noop;
 	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
 	x86_init.mpparse.find_smp_config = x86_init_noop;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/efi/efi_64.c linux-libre-4.10-rc8-gnu/arch/x86/platform/efi/efi_64.c
--- linux-libre-4.9-gnu/arch/x86/platform/efi/efi_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/efi/efi_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -269,6 +269,22 @@ int __init efi_setup_page_tables(unsigne
 	efi_scratch.use_pgd = true;
 
 	/*
+	 * Certain firmware versions are way too sentimential and still believe
+	 * they are exclusive and unquestionable owners of the first physical page,
+	 * even though they explicitly mark it as EFI_CONVENTIONAL_MEMORY
+	 * (but then write-access it later during SetVirtualAddressMap()).
+	 *
+	 * Create a 1:1 mapping for this page, to avoid triple faults during early
+	 * boot with such firmware. We are free to hand this page to the BIOS,
+	 * as trim_bios_range() will reserve the first page and isolate it away
+	 * from memory allocators anyway.
+	 */
+	if (kernel_map_pages_in_pgd(pgd, 0x0, 0x0, 1, _PAGE_RW)) {
+		pr_err("Failed to create 1:1 mapping for the first page!\n");
+		return 1;
+	}
+
+	/*
 	 * When making calls to the firmware everything needs to be 1:1
 	 * mapped and addressable with 32-bit pointers. Map the kernel
 	 * text and allocate a new stack because we can't rely on the
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/efi/efi.c linux-libre-4.10-rc8-gnu/arch/x86/platform/efi/efi.c
--- linux-libre-4.9-gnu/arch/x86/platform/efi/efi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/efi/efi.c	2017-02-12 16:03:20.000000000 -0500
@@ -210,6 +210,70 @@ int __init efi_memblock_x86_reserve_rang
 	return 0;
 }
 
+#define OVERFLOW_ADDR_SHIFT	(64 - EFI_PAGE_SHIFT)
+#define OVERFLOW_ADDR_MASK	(U64_MAX << OVERFLOW_ADDR_SHIFT)
+#define U64_HIGH_BIT		(~(U64_MAX >> 1))
+
+static bool __init efi_memmap_entry_valid(const efi_memory_desc_t *md, int i)
+{
+	u64 end = (md->num_pages << EFI_PAGE_SHIFT) + md->phys_addr - 1;
+	u64 end_hi = 0;
+	char buf[64];
+
+	if (md->num_pages == 0) {
+		end = 0;
+	} else if (md->num_pages > EFI_PAGES_MAX ||
+		   EFI_PAGES_MAX - md->num_pages <
+		   (md->phys_addr >> EFI_PAGE_SHIFT)) {
+		end_hi = (md->num_pages & OVERFLOW_ADDR_MASK)
+			>> OVERFLOW_ADDR_SHIFT;
+
+		if ((md->phys_addr & U64_HIGH_BIT) && !(end & U64_HIGH_BIT))
+			end_hi += 1;
+	} else {
+		return true;
+	}
+
+	pr_warn_once(FW_BUG "Invalid EFI memory map entries:\n");
+
+	if (end_hi) {
+		pr_warn("mem%02u: %s range=[0x%016llx-0x%llx%016llx] (invalid)\n",
+			i, efi_md_typeattr_format(buf, sizeof(buf), md),
+			md->phys_addr, end_hi, end);
+	} else {
+		pr_warn("mem%02u: %s range=[0x%016llx-0x%016llx] (invalid)\n",
+			i, efi_md_typeattr_format(buf, sizeof(buf), md),
+			md->phys_addr, end);
+	}
+	return false;
+}
+
+static void __init efi_clean_memmap(void)
+{
+	efi_memory_desc_t *out = efi.memmap.map;
+	const efi_memory_desc_t *in = out;
+	const efi_memory_desc_t *end = efi.memmap.map_end;
+	int i, n_removal;
+
+	for (i = n_removal = 0; in < end; i++) {
+		if (efi_memmap_entry_valid(in, i)) {
+			if (out != in)
+				memcpy(out, in, efi.memmap.desc_size);
+			out = (void *)out + efi.memmap.desc_size;
+		} else {
+			n_removal++;
+		}
+		in = (void *)in + efi.memmap.desc_size;
+	}
+
+	if (n_removal > 0) {
+		u64 size = efi.memmap.nr_map - n_removal;
+
+		pr_warn("Removing %d invalid memory map entries.\n", n_removal);
+		efi_memmap_install(efi.memmap.phys_map, size);
+	}
+}
+
 void __init efi_print_memmap(void)
 {
 	efi_memory_desc_t *md;
@@ -472,6 +536,8 @@ void __init efi_init(void)
 		}
 	}
 
+	efi_clean_memmap();
+
 	if (efi_enabled(EFI_DBG))
 		efi_print_memmap();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/efi/quirks.c linux-libre-4.10-rc8-gnu/arch/x86/platform/efi/quirks.c
--- linux-libre-4.9-gnu/arch/x86/platform/efi/quirks.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/efi/quirks.c	2017-02-12 16:03:20.000000000 -0500
@@ -214,7 +214,7 @@ void __init efi_arch_mem_reserve(phys_ad
 
 	new_size = efi.memmap.desc_size * num_entries;
 
-	new_phys = memblock_alloc(new_size, 0);
+	new_phys = efi_memmap_alloc(num_entries);
 	if (!new_phys) {
 		pr_err("Could not allocate boot services memmap\n");
 		return;
@@ -355,7 +355,7 @@ void __init efi_free_boot_services(void)
 	}
 
 	new_size = efi.memmap.desc_size * num_entries;
-	new_phys = memblock_alloc(new_size, 0);
+	new_phys = efi_memmap_alloc(num_entries);
 	if (!new_phys) {
 		pr_err("Failed to allocate new EFI memmap\n");
 		return;
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-mid/device_libs/Makefile linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/device_libs/Makefile
--- linux-libre-4.9-gnu/arch/x86/platform/intel-mid/device_libs/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/device_libs/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -15,11 +15,11 @@ obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER
 obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
 obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
 # SPI Devices
-obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_spidev.o
+obj-$(subst m,y,$(CONFIG_SPI_SPIDEV)) += platform_mrfld_spidev.o
 # I2C Devices
 obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
 obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
-obj-$(subst m,y,$(CONFIG_INPUT_MPU3050)) += platform_mpu3050.o
+obj-$(subst m,y,$(CONFIG_MPU3050_I2C)) += platform_mpu3050.o
 obj-$(subst m,y,$(CONFIG_INPUT_BMA150)) += platform_bma023.o
 obj-$(subst m,y,$(CONFIG_DRM_MEDFIELD)) += platform_tc35876x.o
 # I2C GPIO Expanders
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c
--- linux-libre-4.9-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/device_libs/platform_mrfld_spidev.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * spidev platform data initilization file
+ *
+ * (C) Copyright 2014, 2016 Intel Corporation
+ * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+ *	    Dan O'Donovan <dan@emutex.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/err.h>
+#include <linux/init.h>
+#include <linux/sfi.h>
+#include <linux/spi/pxa2xx_spi.h>
+#include <linux/spi/spi.h>
+
+#include <asm/intel-mid.h>
+
+#define MRFLD_SPI_DEFAULT_DMA_BURST	8
+#define MRFLD_SPI_DEFAULT_TIMEOUT	500
+
+/* GPIO pin for spidev chipselect */
+#define MRFLD_SPIDEV_GPIO_CS		111
+
+static struct pxa2xx_spi_chip spidev_spi_chip = {
+	.dma_burst_size		= MRFLD_SPI_DEFAULT_DMA_BURST,
+	.timeout		= MRFLD_SPI_DEFAULT_TIMEOUT,
+	.gpio_cs		= MRFLD_SPIDEV_GPIO_CS,
+};
+
+static void __init *spidev_platform_data(void *info)
+{
+	struct spi_board_info *spi_info = info;
+
+	if (intel_mid_identify_cpu() != INTEL_MID_CPU_CHIP_TANGIER)
+		return ERR_PTR(-ENODEV);
+
+	spi_info->mode = SPI_MODE_0;
+	spi_info->controller_data = &spidev_spi_chip;
+
+	return NULL;
+}
+
+static const struct devs_id spidev_dev_id __initconst = {
+	.name			= "spidev",
+	.type			= SFI_DEV_TYPE_SPI,
+	.delay			= 0,
+	.get_platform_data	= &spidev_platform_data,
+};
+
+sfi_device(spidev_dev_id);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-mid/device_libs/platform_spidev.c linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/device_libs/platform_spidev.c
--- linux-libre-4.9-gnu/arch/x86/platform/intel-mid/device_libs/platform_spidev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/device_libs/platform_spidev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- * spidev platform data initilization file
- *
- * (C) Copyright 2014, 2016 Intel Corporation
- * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
- *	    Dan O'Donovan <dan@emutex.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/sfi.h>
-#include <linux/spi/pxa2xx_spi.h>
-#include <linux/spi/spi.h>
-
-#include <asm/intel-mid.h>
-
-#define MRFLD_SPI_DEFAULT_DMA_BURST	8
-#define MRFLD_SPI_DEFAULT_TIMEOUT	500
-
-/* GPIO pin for spidev chipselect */
-#define MRFLD_SPIDEV_GPIO_CS		111
-
-static struct pxa2xx_spi_chip spidev_spi_chip = {
-	.dma_burst_size		= MRFLD_SPI_DEFAULT_DMA_BURST,
-	.timeout		= MRFLD_SPI_DEFAULT_TIMEOUT,
-	.gpio_cs		= MRFLD_SPIDEV_GPIO_CS,
-};
-
-static void __init *spidev_platform_data(void *info)
-{
-	struct spi_board_info *spi_info = info;
-
-	spi_info->mode = SPI_MODE_0;
-	spi_info->controller_data = &spidev_spi_chip;
-
-	return NULL;
-}
-
-static const struct devs_id spidev_dev_id __initconst = {
-	.name			= "spidev",
-	.type			= SFI_DEV_TYPE_SPI,
-	.delay			= 0,
-	.get_platform_data	= &spidev_platform_data,
-};
-
-sfi_device(spidev_dev_id);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-mid/intel-mid.c linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/intel-mid.c
--- linux-libre-4.9-gnu/arch/x86/platform/intel-mid/intel-mid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/intel-mid.c	2017-02-12 16:03:20.000000000 -0500
@@ -161,12 +161,6 @@ out:
 	regulator_has_full_constraints();
 }
 
-/* MID systems don't have i8042 controller */
-static int intel_mid_i8042_detect(void)
-{
-	return 0;
-}
-
 /*
  * 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
@@ -197,7 +191,6 @@ void __init x86_intel_mid_early_setup(vo
 	x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock;
 
 	x86_platform.calibrate_tsc = intel_mid_calibrate_tsc;
-	x86_platform.i8042_detect = intel_mid_i8042_detect;
 	x86_init.timers.wallclock_init = intel_mid_rtc_init;
 	x86_platform.get_nmi_reason = intel_mid_get_nmi_reason;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-mid/mfld.c linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/mfld.c
--- linux-libre-4.9-gnu/arch/x86/platform/intel-mid/mfld.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/mfld.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,8 +49,13 @@ static unsigned long __init mfld_calibra
 	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);
+
+	/*
+	 * TSC on Intel Atom SoCs is reliable and of known frequency.
+	 * See tsc_msr.c for details.
+	 */
+	setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+	setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
 
 	return fast_calibrate;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-mid/mrfld.c linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/mrfld.c
--- linux-libre-4.9-gnu/arch/x86/platform/intel-mid/mrfld.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/mrfld.c	2017-02-12 16:03:20.000000000 -0500
@@ -78,8 +78,12 @@ static unsigned long __init tangier_cali
 	pr_debug("Setting lapic_timer_frequency = %d\n",
 			lapic_timer_frequency);
 
-	/* mark tsc clocksource as reliable */
-	set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+	/*
+	 * TSC on Intel Atom SoCs is reliable and of known frequency.
+	 * See tsc_msr.c for details.
+	 */
+	setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
+	setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
 
 	return fast_calibrate;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-mid/pwr.c linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/pwr.c
--- linux-libre-4.9-gnu/arch/x86/platform/intel-mid/pwr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-mid/pwr.c	2017-02-12 16:03:20.000000000 -0500
@@ -270,7 +270,6 @@ int intel_mid_pci_set_power_state(struct
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(intel_mid_pci_set_power_state);
 
 pci_power_t intel_mid_pci_get_power_state(struct pci_dev *pdev)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/intel-quark/imr_selftest.c linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-quark/imr_selftest.c
--- linux-libre-4.9-gnu/arch/x86/platform/intel-quark/imr_selftest.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/intel-quark/imr_selftest.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,8 @@
  * @fmt:	format string.
  * ...		variadic argument list.
  */
-static void __init imr_self_test_result(int res, const char *fmt, ...)
+static __printf(2, 3)
+void __init imr_self_test_result(int res, const char *fmt, ...)
 {
 	va_list vlist;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/Makefile linux-libre-4.10-rc8-gnu/arch/x86/platform/Makefile
--- linux-libre-4.9-gnu/arch/x86/platform/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,6 @@ obj-y	+= iris/
 obj-y	+= intel/
 obj-y	+= intel-mid/
 obj-y	+= intel-quark/
-obj-y	+= mellanox/
 obj-y	+= olpc/
 obj-y	+= scx200/
 obj-y	+= sfi/
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/mellanox/Makefile linux-libre-4.10-rc8-gnu/arch/x86/platform/mellanox/Makefile
--- linux-libre-4.9-gnu/arch/x86/platform/mellanox/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/mellanox/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-obj-$(CONFIG_MLX_PLATFORM)	+= mlx-platform.o
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/mellanox/mlx-platform.c linux-libre-4.10-rc8-gnu/arch/x86/platform/mellanox/mlx-platform.c
--- linux-libre-4.9-gnu/arch/x86/platform/mellanox/mlx-platform.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/mellanox/mlx-platform.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,266 +0,0 @@
-/*
- * arch/x86/platform/mellanox/mlx-platform.c
- * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
- * Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/device.h>
-#include <linux/dmi.h>
-#include <linux/i2c.h>
-#include <linux/i2c-mux.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/i2c-mux-reg.h>
-
-#define MLX_PLAT_DEVICE_NAME		"mlxplat"
-
-/* LPC bus IO offsets */
-#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR		0x2000
-#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR		0x2500
-#define MLXPLAT_CPLD_LPC_IO_RANGE		0x100
-#define MLXPLAT_CPLD_LPC_I2C_CH1_OFF		0xdb
-#define MLXPLAT_CPLD_LPC_I2C_CH2_OFF		0xda
-#define MLXPLAT_CPLD_LPC_PIO_OFFSET		0x10000UL
-#define MLXPLAT_CPLD_LPC_REG1	((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
-				  MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
-				  MLXPLAT_CPLD_LPC_PIO_OFFSET)
-#define MLXPLAT_CPLD_LPC_REG2	((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
-				  MLXPLAT_CPLD_LPC_I2C_CH2_OFF) | \
-				  MLXPLAT_CPLD_LPC_PIO_OFFSET)
-
-/* Start channel numbers */
-#define MLXPLAT_CPLD_CH1			2
-#define MLXPLAT_CPLD_CH2			10
-
-/* Number of LPC attached MUX platform devices */
-#define MLXPLAT_CPLD_LPC_MUX_DEVS		2
-
-/* mlxplat_priv - platform private data
- * @pdev_i2c - i2c controller platform device
- * @pdev_mux - array of mux platform devices
- */
-struct mlxplat_priv {
-	struct platform_device *pdev_i2c;
-	struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
-};
-
-/* Regions for LPC I2C controller and LPC base register space */
-static const struct resource mlxplat_lpc_resources[] = {
-	[0] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_I2C_BASE_ADRR,
-			       MLXPLAT_CPLD_LPC_IO_RANGE,
-			       "mlxplat_cpld_lpc_i2c_ctrl", IORESOURCE_IO),
-	[1] = DEFINE_RES_NAMED(MLXPLAT_CPLD_LPC_REG_BASE_ADRR,
-			       MLXPLAT_CPLD_LPC_IO_RANGE,
-			       "mlxplat_cpld_lpc_regs",
-			       IORESOURCE_IO),
-};
-
-/* Platform default channels */
-static const int mlxplat_default_channels[][8] = {
-	{
-		MLXPLAT_CPLD_CH1, MLXPLAT_CPLD_CH1 + 1, MLXPLAT_CPLD_CH1 + 2,
-		MLXPLAT_CPLD_CH1 + 3, MLXPLAT_CPLD_CH1 + 4, MLXPLAT_CPLD_CH1 +
-		5, MLXPLAT_CPLD_CH1 + 6, MLXPLAT_CPLD_CH1 + 7
-	},
-	{
-		MLXPLAT_CPLD_CH2, MLXPLAT_CPLD_CH2 + 1, MLXPLAT_CPLD_CH2 + 2,
-		MLXPLAT_CPLD_CH2 + 3, MLXPLAT_CPLD_CH2 + 4, MLXPLAT_CPLD_CH2 +
-		5, MLXPLAT_CPLD_CH2 + 6, MLXPLAT_CPLD_CH2 + 7
-	},
-};
-
-/* Platform channels for MSN21xx system family */
-static const int mlxplat_msn21xx_channels[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
-
-/* Platform mux data */
-static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = {
-	{
-		.parent = 1,
-		.base_nr = MLXPLAT_CPLD_CH1,
-		.write_only = 1,
-		.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG1,
-		.reg_size = 1,
-		.idle_in_use = 1,
-	},
-	{
-		.parent = 1,
-		.base_nr = MLXPLAT_CPLD_CH2,
-		.write_only = 1,
-		.reg = (void __iomem *)MLXPLAT_CPLD_LPC_REG2,
-		.reg_size = 1,
-		.idle_in_use = 1,
-	},
-
-};
-
-static struct platform_device *mlxplat_dev;
-
-static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
-		mlxplat_mux_data[i].values = mlxplat_default_channels[i];
-		mlxplat_mux_data[i].n_values =
-				ARRAY_SIZE(mlxplat_default_channels[i]);
-	}
-
-	return 1;
-};
-
-static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
-		mlxplat_mux_data[i].values = mlxplat_msn21xx_channels;
-		mlxplat_mux_data[i].n_values =
-				ARRAY_SIZE(mlxplat_msn21xx_channels);
-	}
-
-	return 1;
-};
-
-static struct dmi_system_id mlxplat_dmi_table[] __initdata = {
-	{
-		.callback = mlxplat_dmi_default_matched,
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MSN24"),
-		},
-	},
-	{
-		.callback = mlxplat_dmi_default_matched,
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MSN27"),
-		},
-	},
-	{
-		.callback = mlxplat_dmi_default_matched,
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MSB"),
-		},
-	},
-	{
-		.callback = mlxplat_dmi_default_matched,
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MSX"),
-		},
-	},
-	{
-		.callback = mlxplat_dmi_msn21xx_matched,
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Mellanox Technologies"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MSN21"),
-		},
-	},
-	{ }
-};
-
-static int __init mlxplat_init(void)
-{
-	struct mlxplat_priv *priv;
-	int i, err;
-
-	if (!dmi_check_system(mlxplat_dmi_table))
-		return -ENODEV;
-
-	mlxplat_dev = platform_device_register_simple(MLX_PLAT_DEVICE_NAME, -1,
-					mlxplat_lpc_resources,
-					ARRAY_SIZE(mlxplat_lpc_resources));
-
-	if (IS_ERR(mlxplat_dev))
-		return PTR_ERR(mlxplat_dev);
-
-	priv = devm_kzalloc(&mlxplat_dev->dev, sizeof(struct mlxplat_priv),
-			    GFP_KERNEL);
-	if (!priv) {
-		err = -ENOMEM;
-		goto fail_alloc;
-	}
-	platform_set_drvdata(mlxplat_dev, priv);
-
-	priv->pdev_i2c = platform_device_register_simple("i2c_mlxcpld", -1,
-							 NULL, 0);
-	if (IS_ERR(priv->pdev_i2c)) {
-		err = PTR_ERR(priv->pdev_i2c);
-		goto fail_alloc;
-	};
-
-	for (i = 0; i < ARRAY_SIZE(mlxplat_mux_data); i++) {
-		priv->pdev_mux[i] = platform_device_register_resndata(
-						&mlxplat_dev->dev,
-						"i2c-mux-reg", i, NULL,
-						0, &mlxplat_mux_data[i],
-						sizeof(mlxplat_mux_data[i]));
-		if (IS_ERR(priv->pdev_mux[i])) {
-			err = PTR_ERR(priv->pdev_mux[i]);
-			goto fail_platform_mux_register;
-		}
-	}
-
-	return 0;
-
-fail_platform_mux_register:
-	for (i--; i > 0 ; i--)
-		platform_device_unregister(priv->pdev_mux[i]);
-	platform_device_unregister(priv->pdev_i2c);
-fail_alloc:
-	platform_device_unregister(mlxplat_dev);
-
-	return err;
-}
-module_init(mlxplat_init);
-
-static void __exit mlxplat_exit(void)
-{
-	struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
-	int i;
-
-	for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
-		platform_device_unregister(priv->pdev_mux[i]);
-
-	platform_device_unregister(priv->pdev_i2c);
-	platform_device_unregister(mlxplat_dev);
-}
-module_exit(mlxplat_exit);
-
-MODULE_AUTHOR("Vadim Pasternak (vadimp@mellanox.com)");
-MODULE_DESCRIPTION("Mellanox platform driver");
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_ALIAS("dmi:*:*Mellanox*:MSN24*:");
-MODULE_ALIAS("dmi:*:*Mellanox*:MSN27*:");
-MODULE_ALIAS("dmi:*:*Mellanox*:MSB*:");
-MODULE_ALIAS("dmi:*:*Mellanox*:MSX*:");
-MODULE_ALIAS("dmi:*:*Mellanox*:MSN21*:");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/uv/tlb_uv.c linux-libre-4.10-rc8-gnu/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-4.9-gnu/arch/x86/platform/uv/tlb_uv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/uv/tlb_uv.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,6 @@
 #include <asm/uv/uv_hub.h>
 #include <asm/uv/uv_bau.h>
 #include <asm/apic.h>
-#include <asm/idle.h>
 #include <asm/tsc.h>
 #include <asm/irq_vectors.h>
 #include <asm/timer.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/uv/uv_nmi.c linux-libre-4.10-rc8-gnu/arch/x86/platform/uv/uv_nmi.c
--- linux-libre-4.9-gnu/arch/x86/platform/uv/uv_nmi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/uv/uv_nmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -387,8 +387,8 @@ static void uv_nmi_dump_cpu_ip_hdr(void)
 /* Dump Instruction Pointer info */
 static void uv_nmi_dump_cpu_ip(int cpu, struct pt_regs *regs)
 {
-	pr_info("UV: %4d %6d %-32.32s ", cpu, current->pid, current->comm);
-	printk_address(regs->ip);
+	pr_info("UV: %4d %6d %-32.32s %pS",
+		cpu, current->pid, current->comm, (void *)regs->ip);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/platform/uv/uv_time.c linux-libre-4.10-rc8-gnu/arch/x86/platform/uv/uv_time.c
--- linux-libre-4.9-gnu/arch/x86/platform/uv/uv_time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/platform/uv/uv_time.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 
 #define RTC_NAME		"sgi_rtc"
 
-static cycle_t uv_read_rtc(struct clocksource *cs);
+static u64 uv_read_rtc(struct clocksource *cs);
 static int uv_rtc_next_event(unsigned long, struct clock_event_device *);
 static int uv_rtc_shutdown(struct clock_event_device *evt);
 
@@ -38,7 +38,7 @@ static struct clocksource clocksource_uv
 	.name		= RTC_NAME,
 	.rating		= 299,
 	.read		= uv_read_rtc,
-	.mask		= (cycle_t)UVH_RTC_REAL_TIME_CLOCK_MASK,
+	.mask		= (u64)UVH_RTC_REAL_TIME_CLOCK_MASK,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -296,7 +296,7 @@ static int uv_rtc_unset_timer(int cpu, i
  * cachelines of it's own page.  This allows faster simultaneous reads
  * from a given socket.
  */
-static cycle_t uv_read_rtc(struct clocksource *cs)
+static u64 uv_read_rtc(struct clocksource *cs)
 {
 	unsigned long offset;
 
@@ -305,7 +305,7 @@ static cycle_t uv_read_rtc(struct clocks
 	else
 		offset = (uv_blade_processor_id() * L1_CACHE_BYTES) % PAGE_SIZE;
 
-	return (cycle_t)uv_read_local_mmr(UVH_RTC | offset);
+	return (u64)uv_read_local_mmr(UVH_RTC | offset);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/power/cpu.c linux-libre-4.10-rc8-gnu/arch/x86/power/cpu.c
--- linux-libre-4.9-gnu/arch/x86/power/cpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/power/cpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -252,6 +252,7 @@ static void notrace __restore_processor_
 	fix_processor_context();
 
 	do_fpu_end();
+	tsc_verify_tsc_adjust(true);
 	x86_platform.restore_sched_clock_state();
 	mtrr_bp_restore();
 	perf_restore_debug_store();
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/power/hibernate_64.c linux-libre-4.10-rc8-gnu/arch/x86/power/hibernate_64.c
--- linux-libre-4.9-gnu/arch/x86/power/hibernate_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/power/hibernate_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,10 @@
 #include <linux/gfp.h>
 #include <linux/smp.h>
 #include <linux/suspend.h>
+#include <linux/scatterlist.h>
+#include <linux/kdebug.h>
+
+#include <crypto/hash.h>
 
 #include <asm/init.h>
 #include <asm/proto.h>
@@ -177,14 +181,86 @@ int pfn_is_nosave(unsigned long pfn)
 	return (pfn >= nosave_begin_pfn) && (pfn < nosave_end_pfn);
 }
 
+#define MD5_DIGEST_SIZE 16
+
 struct restore_data_record {
 	unsigned long jump_address;
 	unsigned long jump_address_phys;
 	unsigned long cr3;
 	unsigned long magic;
+	u8 e820_digest[MD5_DIGEST_SIZE];
 };
 
-#define RESTORE_MAGIC	0x123456789ABCDEF0UL
+#define RESTORE_MAGIC	0x23456789ABCDEF01UL
+
+#if IS_BUILTIN(CONFIG_CRYPTO_MD5)
+/**
+ * get_e820_md5 - calculate md5 according to given e820 map
+ *
+ * @map: the e820 map to be calculated
+ * @buf: the md5 result to be stored to
+ */
+static int get_e820_md5(struct e820map *map, void *buf)
+{
+	struct scatterlist sg;
+	struct crypto_ahash *tfm;
+	int size;
+	int ret = 0;
+
+	tfm = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm))
+		return -ENOMEM;
+
+	{
+		AHASH_REQUEST_ON_STACK(req, tfm);
+		size = offsetof(struct e820map, map)
+			+ sizeof(struct e820entry) * map->nr_map;
+		ahash_request_set_tfm(req, tfm);
+		sg_init_one(&sg, (u8 *)map, size);
+		ahash_request_set_callback(req, 0, NULL, NULL);
+		ahash_request_set_crypt(req, &sg, buf, size);
+
+		if (crypto_ahash_digest(req))
+			ret = -EINVAL;
+		ahash_request_zero(req);
+	}
+	crypto_free_ahash(tfm);
+
+	return ret;
+}
+
+static void hibernation_e820_save(void *buf)
+{
+	get_e820_md5(e820_saved, buf);
+}
+
+static bool hibernation_e820_mismatch(void *buf)
+{
+	int ret;
+	u8 result[MD5_DIGEST_SIZE];
+
+	memset(result, 0, MD5_DIGEST_SIZE);
+	/* If there is no digest in suspend kernel, let it go. */
+	if (!memcmp(result, buf, MD5_DIGEST_SIZE))
+		return false;
+
+	ret = get_e820_md5(e820_saved, result);
+	if (ret)
+		return true;
+
+	return memcmp(result, buf, MD5_DIGEST_SIZE) ? true : false;
+}
+#else
+static void hibernation_e820_save(void *buf)
+{
+}
+
+static bool hibernation_e820_mismatch(void *buf)
+{
+	/* If md5 is not builtin for restore kernel, let it go. */
+	return false;
+}
+#endif
 
 /**
  *	arch_hibernation_header_save - populate the architecture specific part
@@ -201,6 +277,9 @@ int arch_hibernation_header_save(void *a
 	rdr->jump_address_phys = __pa_symbol(&restore_registers);
 	rdr->cr3 = restore_cr3;
 	rdr->magic = RESTORE_MAGIC;
+
+	hibernation_e820_save(rdr->e820_digest);
+
 	return 0;
 }
 
@@ -216,5 +295,16 @@ int arch_hibernation_header_restore(void
 	restore_jump_address = rdr->jump_address;
 	jump_address_phys = rdr->jump_address_phys;
 	restore_cr3 = rdr->cr3;
-	return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL;
+
+	if (rdr->magic != RESTORE_MAGIC) {
+		pr_crit("Unrecognized hibernate image header format!\n");
+		return -EINVAL;
+	}
+
+	if (hibernation_e820_mismatch(rdr->e820_digest)) {
+		pr_crit("Hibernate inconsistent memory map detected!\n");
+		return -ENODEV;
+	}
+
+	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/ras/mce_amd_inj.c linux-libre-4.10-rc8-gnu/arch/x86/ras/mce_amd_inj.c
--- linux-libre-4.9-gnu/arch/x86/ras/mce_amd_inj.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/ras/mce_amd_inj.c	2017-02-12 16:03:20.000000000 -0500
@@ -275,6 +275,8 @@ static void do_inject(void)
 	unsigned int cpu = i_mce.extcpu;
 	u8 b = i_mce.bank;
 
+	rdtscll(i_mce.tsc);
+
 	if (i_mce.misc)
 		i_mce.status |= MCI_STATUS_MISCV;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/realmode/rm/Makefile linux-libre-4.10-rc8-gnu/arch/x86/realmode/rm/Makefile
--- linux-libre-4.9-gnu/arch/x86/realmode/rm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/realmode/rm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -69,7 +69,7 @@ $(obj)/realmode.relocs: $(obj)/realmode.
 
 # ---------------------------------------------------------------------------
 
-KBUILD_CFLAGS	:= $(LINUXINCLUDE) $(REALMODE_CFLAGS) -D_SETUP -D_WAKEUP \
+KBUILD_CFLAGS	:= $(REALMODE_CFLAGS) -D_SETUP -D_WAKEUP \
 		   -I$(srctree)/arch/x86/boot
 KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
 GCOV_PROFILE := n
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/tools/insn_sanity.c linux-libre-4.10-rc8-gnu/arch/x86/tools/insn_sanity.c
--- linux-libre-4.9-gnu/arch/x86/tools/insn_sanity.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/tools/insn_sanity.c	2017-02-12 16:03:20.000000000 -0500
@@ -269,7 +269,8 @@ int main(int argc, char **argv)
 		insns++;
 	}
 
-	fprintf(stdout, "%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
+	fprintf((errors) ? stderr : stdout,
+		"%s: %s: decoded and checked %d %s instructions with %d errors (seed:0x%x)\n",
 		prog,
 		(errors) ? "Failure" : "Success",
 		insns,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/tools/relocs.c linux-libre-4.10-rc8-gnu/arch/x86/tools/relocs.c
--- linux-libre-4.9-gnu/arch/x86/tools/relocs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/tools/relocs.c	2017-02-12 16:03:20.000000000 -0500
@@ -992,11 +992,12 @@ static void emit_relocs(int as_text, int
 		die("Segment relocations found but --realmode not specified\n");
 
 	/* Order the relocations for more efficient processing */
-	sort_relocs(&relocs16);
 	sort_relocs(&relocs32);
 #if ELF_BITS == 64
 	sort_relocs(&relocs32neg);
 	sort_relocs(&relocs64);
+#else
+	sort_relocs(&relocs16);
 #endif
 
 	/* Print the relocations */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/tools/test_get_len.c linux-libre-4.10-rc8-gnu/arch/x86/tools/test_get_len.c
--- linux-libre-4.9-gnu/arch/x86/tools/test_get_len.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/tools/test_get_len.c	2017-02-12 16:03:20.000000000 -0500
@@ -167,7 +167,7 @@ int main(int argc, char **argv)
 		fprintf(stderr, "Warning: decoded and checked %d"
 			" instructions with %d warnings\n", insns, warnings);
 	else
-		fprintf(stderr, "Succeed: decoded and checked %d"
+		fprintf(stdout, "Success: decoded and checked %d"
 			" instructions\n", insns);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/um/asm/processor.h linux-libre-4.10-rc8-gnu/arch/x86/um/asm/processor.h
--- linux-libre-4.9-gnu/arch/x86/um/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/um/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,6 @@ static inline void rep_nop(void)
 }
 
 #define cpu_relax()		rep_nop()
-#define cpu_relax_lowlatency()	cpu_relax()
 
 #define task_pt_regs(t) (&(t)->thread.regs)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/um/ptrace_32.c linux-libre-4.10-rc8-gnu/arch/x86/um/ptrace_32.c
--- linux-libre-4.9-gnu/arch/x86/um/ptrace_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/um/ptrace_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace-abi.h>
 #include <skas.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/um/ptrace_64.c linux-libre-4.10-rc8-gnu/arch/x86/um/ptrace_64.c
--- linux-libre-4.9-gnu/arch/x86/um/ptrace_64.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/um/ptrace_64.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/errno.h>
 #define __FRAME_OFFSETS
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace-abi.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/um/signal.c linux-libre-4.10-rc8-gnu/arch/x86/um/signal.c
--- linux-libre-4.9-gnu/arch/x86/um/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/um/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
 #include <linux/ptrace.h>
 #include <linux/kernel.h>
 #include <asm/unistd.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ucontext.h>
 #include <frame_kern.h>
 #include <skas.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/um/tls_32.c linux-libre-4.10-rc8-gnu/arch/x86/um/tls_32.c
--- linux-libre-4.9-gnu/arch/x86/um/tls_32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/um/tls_32.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
 #include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/syscalls.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ptrace-abi.h>
 #include <os.h>
 #include <skas.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/enlighten.c linux-libre-4.10-rc8-gnu/arch/x86/xen/enlighten.c
--- linux-libre-4.9-gnu/arch/x86/xen/enlighten.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/enlighten.c	2017-02-12 16:03:20.000000000 -0500
@@ -980,17 +980,6 @@ static void xen_io_delay(void)
 {
 }
 
-static void xen_clts(void)
-{
-	struct multicall_space mcs;
-
-	mcs = xen_mc_entry(0);
-
-	MULTI_fpu_taskswitch(mcs.mc, 0);
-
-	xen_mc_issue(PARAVIRT_LAZY_CPU);
-}
-
 static DEFINE_PER_CPU(unsigned long, xen_cr0_value);
 
 static unsigned long xen_read_cr0(void)
@@ -1233,8 +1222,6 @@ static const struct pv_cpu_ops xen_cpu_o
 	.set_debugreg = xen_set_debugreg,
 	.get_debugreg = xen_get_debugreg,
 
-	.clts = xen_clts,
-
 	.read_cr0 = xen_read_cr0,
 	.write_cr0 = xen_write_cr0,
 
@@ -1542,11 +1529,11 @@ static int xen_cpuhp_setup(void)
 	int rc;
 
 	rc = cpuhp_setup_state_nocalls(CPUHP_XEN_PREPARE,
-				       "XEN_HVM_GUEST_PREPARE",
+				       "x86/xen/hvm_guest:prepare",
 				       xen_cpu_up_prepare, xen_cpu_dead);
 	if (rc >= 0) {
 		rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
-					       "XEN_HVM_GUEST_ONLINE",
+					       "x86/xen/hvm_guest:online",
 					       xen_cpu_up_online, NULL);
 		if (rc < 0)
 			cpuhp_remove_state_nocalls(CPUHP_XEN_PREPARE);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/p2m.c linux-libre-4.10-rc8-gnu/arch/x86/xen/p2m.c
--- linux-libre-4.9-gnu/arch/x86/xen/p2m.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/p2m.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,7 @@
 
 #include <asm/cache.h>
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <asm/xen/page.h>
 #include <asm/xen/hypercall.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/pci-swiotlb-xen.c linux-libre-4.10-rc8-gnu/arch/x86/xen/pci-swiotlb-xen.c
--- linux-libre-4.9-gnu/arch/x86/xen/pci-swiotlb-xen.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/pci-swiotlb-xen.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,6 @@
 int xen_swiotlb __read_mostly;
 
 static struct dma_map_ops xen_swiotlb_dma_ops = {
-	.mapping_error = xen_swiotlb_dma_mapping_error,
 	.alloc = xen_swiotlb_alloc_coherent,
 	.free = xen_swiotlb_free_coherent,
 	.sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu,
@@ -49,7 +48,7 @@ int __init pci_xen_swiotlb_detect(void)
 	 * activate this IOMMU. If running as PV privileged, activate it
 	 * irregardless.
 	 */
-	if ((xen_initial_domain() || swiotlb || swiotlb_force))
+	if (xen_initial_domain() || swiotlb || swiotlb_force == SWIOTLB_FORCE)
 		xen_swiotlb = 1;
 
 	/* If we are running under Xen, we MUST disable the native SWIOTLB.
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/setup.c linux-libre-4.10-rc8-gnu/arch/x86/xen/setup.c
--- linux-libre-4.9-gnu/arch/x86/xen/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@ struct xen_memory_region xen_extra_mem[X
 unsigned long xen_released_pages;
 
 /* E820 map used during setting up memory. */
-static struct e820entry xen_e820_map[E820MAX] __initdata;
+static struct e820entry xen_e820_map[E820_X_MAX] __initdata;
 static u32 xen_e820_map_entries __initdata;
 
 /*
@@ -713,10 +713,9 @@ static void __init xen_reserve_xen_mfnli
 		size = PFN_PHYS(xen_start_info->nr_p2m_frames);
 	}
 
-	if (!xen_is_e820_reserved(start, size)) {
-		memblock_reserve(start, size);
+	memblock_reserve(start, size);
+	if (!xen_is_e820_reserved(start, size))
 		return;
-	}
 
 #ifdef CONFIG_X86_32
 	/*
@@ -727,6 +726,7 @@ static void __init xen_reserve_xen_mfnli
 	BUG();
 #else
 	xen_relocate_p2m();
+	memblock_free(start, size);
 #endif
 }
 
@@ -750,7 +750,7 @@ char * __init xen_memory_setup(void)
 	max_pfn = min(max_pfn, xen_start_info->nr_pages);
 	mem_end = PFN_PHYS(max_pfn);
 
-	memmap.nr_entries = E820MAX;
+	memmap.nr_entries = ARRAY_SIZE(xen_e820_map);
 	set_xen_guest_handle(memmap.buffer, xen_e820_map);
 
 	op = xen_initial_domain() ?
@@ -923,7 +923,7 @@ char * __init xen_auto_xlated_memory_set
 	int i;
 	int rc;
 
-	memmap.nr_entries = E820MAX;
+	memmap.nr_entries = ARRAY_SIZE(xen_e820_map);
 	set_xen_guest_handle(memmap.buffer, xen_e820_map);
 
 	rc = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/smp.c linux-libre-4.10-rc8-gnu/arch/x86/xen/smp.c
--- linux-libre-4.9-gnu/arch/x86/xen/smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,12 +87,6 @@ static void cpu_bringup(void)
 	cpu_data(cpu).x86_max_cores = 1;
 	set_cpu_sibling_map(cpu);
 
-	/*
-	 * identify_cpu() may have set logical_pkg_id to -1 due
-	 * to incorrect phys_proc_id. Let's re-comupte it.
-	 */
-	topology_update_package_map(apic->cpu_present_to_apicid(cpu), cpu);
-
 	xen_setup_cpu_clockevents();
 
 	notify_cpu_starting(cpu);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/spinlock.c linux-libre-4.10-rc8-gnu/arch/x86/xen/spinlock.c
--- linux-libre-4.9-gnu/arch/x86/xen/spinlock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/spinlock.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,6 +114,7 @@ void xen_uninit_lock_cpu(int cpu)
 	per_cpu(irq_name, cpu) = NULL;
 }
 
+PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen);
 
 /*
  * Our init of PV spinlocks is split in two init functions due to us
@@ -137,6 +138,7 @@ void __init xen_init_spinlocks(void)
 	pv_lock_ops.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock);
 	pv_lock_ops.wait = xen_qlock_wait;
 	pv_lock_ops.kick = xen_qlock_kick;
+	pv_lock_ops.vcpu_is_preempted = PV_CALLEE_SAVE(xen_vcpu_stolen);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/time.c linux-libre-4.10-rc8-gnu/arch/x86/xen/time.c
--- linux-libre-4.9-gnu/arch/x86/xen/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,10 +39,10 @@ static unsigned long xen_tsc_khz(void)
 	return pvclock_tsc_khz(info);
 }
 
-cycle_t xen_clocksource_read(void)
+u64 xen_clocksource_read(void)
 {
         struct pvclock_vcpu_time_info *src;
-	cycle_t ret;
+	u64 ret;
 
 	preempt_disable_notrace();
 	src = &__this_cpu_read(xen_vcpu)->time;
@@ -51,7 +51,7 @@ cycle_t xen_clocksource_read(void)
 	return ret;
 }
 
-static cycle_t xen_clocksource_get_cycles(struct clocksource *cs)
+static u64 xen_clocksource_get_cycles(struct clocksource *cs)
 {
 	return xen_clocksource_read();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/x86/xen/xen-ops.h linux-libre-4.10-rc8-gnu/arch/x86/xen/xen-ops.h
--- linux-libre-4.9-gnu/arch/x86/xen/xen-ops.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/x86/xen/xen-ops.h	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@ void xen_init_irq_ops(void);
 void xen_setup_timer(int cpu);
 void xen_setup_runstate_info(int cpu);
 void xen_teardown_timer(int cpu);
-cycle_t xen_clocksource_read(void);
+u64 xen_clocksource_read(void);
 void xen_setup_cpu_clockevents(void);
 void __init xen_init_time_ops(void);
 void __init xen_hvm_init_time_ops(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/boot/dts/kc705.dts linux-libre-4.10-rc8-gnu/arch/xtensa/boot/dts/kc705.dts
--- linux-libre-4.9-gnu/arch/xtensa/boot/dts/kc705.dts	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/boot/dts/kc705.dts	2017-02-12 16:03:20.000000000 -0500
@@ -11,4 +11,20 @@
 		device_type = "memory";
 		reg = <0x00000000 0x38000000>;
 	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* global autoconfigured region for contiguous allocations */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x04000000>;
+			alignment = <0x2000>;
+			alloc-ranges = <0x00000000 0x20000000>;
+			linux,cma-default;
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/include/asm/checksum.h linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/checksum.h
--- linux-libre-4.9-gnu/arch/xtensa/include/asm/checksum.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/checksum.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #define _XTENSA_CHECKSUM_H
 
 #include <linux/in6.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <variant/core.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/include/asm/Kbuild linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/Kbuild
--- linux-libre-4.9-gnu/arch/xtensa/include/asm/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -3,6 +3,7 @@ generic-y += bug.h
 generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += div64.h
+generic-y += dma-contiguous.h
 generic-y += emergency-restart.h
 generic-y += errno.h
 generic-y += exec.h
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/include/asm/mutex.h linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/mutex.h
--- linux-libre-4.9-gnu/arch/xtensa/include/asm/mutex.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-/*
- * 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-dec.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/include/asm/processor.h linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/processor.h
--- linux-libre-4.9-gnu/arch/xtensa/include/asm/processor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/processor.h	2017-02-12 16:03:20.000000000 -0500
@@ -206,7 +206,6 @@ extern unsigned long get_wchan(struct ta
 #define KSTK_ESP(tsk)		(task_pt_regs(tsk)->areg[1])
 
 #define cpu_relax()  barrier()
-#define cpu_relax_lowlatency() cpu_relax()
 
 /* Special register access. */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/include/asm/segment.h linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/segment.h
--- linux-libre-4.9-gnu/arch/xtensa/include/asm/segment.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/include/asm/segment.h	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,6 @@
 #ifndef _XTENSA_SEGMENT_H
 #define _XTENSA_SEGMENT_H
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #endif	/* _XTENSA_SEGEMENT_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/include/uapi/asm/socket.h linux-libre-4.10-rc8-gnu/arch/xtensa/include/uapi/asm/socket.h
--- linux-libre-4.9-gnu/arch/xtensa/include/uapi/asm/socket.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/include/uapi/asm/socket.h	2017-02-12 16:03:20.000000000 -0500
@@ -101,4 +101,6 @@
 
 #define SO_CNX_ADVICE		53
 
+#define SCM_TIMESTAMPING_OPT_STATS	54
+
 #endif	/* _XTENSA_SOCKET_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/Kconfig linux-libre-4.10-rc8-gnu/arch/xtensa/Kconfig
--- linux-libre-4.9-gnu/arch/xtensa/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@ config XTENSA
 	select GENERIC_SCHED_CLOCK
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_API_DEBUG
+	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EXIT_THREAD
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUTEX_CMPXCHG if !MMU
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/asm-offsets.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/asm-offsets.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/asm-offsets.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/asm-offsets.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 int main(void)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/irq.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/irq.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/of.h>
 
 #include <asm/mxregs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/platform.h>
 
 DECLARE_PER_CPU(unsigned long, nmi_count);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/Makefile linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/Makefile
--- linux-libre-4.9-gnu/arch/xtensa/kernel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@ obj-$(CONFIG_FUNCTION_TRACER) += mcount.
 obj-$(CONFIG_SMP) += smp.o mxhead.o
 obj-$(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) += perf_event.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
+obj-$(CONFIG_S32C1I_SELFTEST) += s32c1i_selftest.o
 
 AFLAGS_head.o += -mtext-section-literals
 AFLAGS_mxhead.o += -mtext-section-literals
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/pci-dma.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/pci-dma.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/pci-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/pci-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
  * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
  */
 
+#include <linux/dma-contiguous.h>
 #include <linux/gfp.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
@@ -146,6 +147,8 @@ static void *xtensa_dma_alloc(struct dev
 {
 	unsigned long ret;
 	unsigned long uncached = 0;
+	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+	struct page *page = NULL;
 
 	/* ignore region speicifiers */
 
@@ -153,11 +156,18 @@ static void *xtensa_dma_alloc(struct dev
 
 	if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff))
 		flag |= GFP_DMA;
-	ret = (unsigned long)__get_free_pages(flag, get_order(size));
 
-	if (ret == 0)
+	if (gfpflags_allow_blocking(flag))
+		page = dma_alloc_from_contiguous(dev, count, get_order(size));
+
+	if (!page)
+		page = alloc_pages(flag, get_order(size));
+
+	if (!page)
 		return NULL;
 
+	ret = (unsigned long)page_address(page);
+
 	/* We currently don't support coherent memory outside KSEG */
 
 	BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
@@ -170,16 +180,19 @@ static void *xtensa_dma_alloc(struct dev
 	return (void *)uncached;
 }
 
-static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr,
+static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr,
 			    dma_addr_t dma_handle, unsigned long attrs)
 {
 	unsigned long addr = (unsigned long)vaddr +
 		XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
+	struct page *page = virt_to_page(addr);
+	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
 
 	BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR ||
 	       addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
 
-	free_pages(addr, get_order(size));
+	if (!dma_release_from_contiguous(dev, page, count))
+		__free_pages(page, get_order(size));
 }
 
 static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
@@ -189,7 +202,9 @@ static dma_addr_t xtensa_map_page(struct
 {
 	dma_addr_t dma_handle = page_to_phys(page) + offset;
 
-	xtensa_sync_single_for_device(dev, dma_handle, size, dir);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		xtensa_sync_single_for_device(dev, dma_handle, size, dir);
+
 	return dma_handle;
 }
 
@@ -197,7 +212,8 @@ static void xtensa_unmap_page(struct dev
 			      size_t size, enum dma_data_direction dir,
 			      unsigned long attrs)
 {
-	xtensa_sync_single_for_cpu(dev, dma_handle, size, dir);
+	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+		xtensa_sync_single_for_cpu(dev, dma_handle, size, dir);
 }
 
 static int xtensa_map_sg(struct device *dev, struct scatterlist *sg,
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/perf_event.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/perf_event.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/perf_event.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/perf_event.c	2017-02-12 16:03:20.000000000 -0500
@@ -422,7 +422,7 @@ static int __init xtensa_pmu_init(void)
 	int irq = irq_create_mapping(NULL, XCHAL_PROFILING_INTERRUPT);
 
 	ret = cpuhp_setup_state(CPUHP_AP_PERF_XTENSA_STARTING,
-				"AP_PERF_XTENSA_STARTING", xtensa_pmu_setup,
+				"perf/xtensa:starting", xtensa_pmu_setup,
 				NULL);
 	if (ret) {
 		pr_err("xtensa_pmu: failed to register CPU-hotplug.\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/process.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/process.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/process.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/process.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/rcupdate.h>
 
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 #include <asm/platform.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/ptrace.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/ptrace.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/ptrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/ptrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 void user_enable_single_step(struct task_struct *child)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/s32c1i_selftest.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/s32c1i_selftest.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/s32c1i_selftest.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/s32c1i_selftest.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * S32C1I selftest.
+ *
+ * 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) 2016 Cadence Design Systems Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/traps.h>
+
+#if XCHAL_HAVE_S32C1I
+
+static int __initdata rcw_word, rcw_probe_pc, rcw_exc;
+
+/*
+ * Basic atomic compare-and-swap, that records PC of S32C1I for probing.
+ *
+ * If *v == cmp, set *v = set.  Return previous *v.
+ */
+static inline int probed_compare_swap(int *v, int cmp, int set)
+{
+	int tmp;
+
+	__asm__ __volatile__(
+			"	movi	%1, 1f\n"
+			"	s32i	%1, %4, 0\n"
+			"	wsr	%2, scompare1\n"
+			"1:	s32c1i	%0, %3, 0\n"
+			: "=a" (set), "=&a" (tmp)
+			: "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set)
+			: "memory"
+			);
+	return set;
+}
+
+/* Handle probed exception */
+
+static void __init do_probed_exception(struct pt_regs *regs,
+				       unsigned long exccause)
+{
+	if (regs->pc == rcw_probe_pc) {	/* exception on s32c1i ? */
+		regs->pc += 3;		/* skip the s32c1i instruction */
+		rcw_exc = exccause;
+	} else {
+		do_unhandled(regs, exccause);
+	}
+}
+
+/* Simple test of S32C1I (soc bringup assist) */
+
+static int __init check_s32c1i(void)
+{
+	int n, cause1, cause2;
+	void *handbus, *handdata, *handaddr; /* temporarily saved handlers */
+
+	rcw_probe_pc = 0;
+	handbus  = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR,
+			do_probed_exception);
+	handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR,
+			do_probed_exception);
+	handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR,
+			do_probed_exception);
+
+	/* First try an S32C1I that does not store: */
+	rcw_exc = 0;
+	rcw_word = 1;
+	n = probed_compare_swap(&rcw_word, 0, 2);
+	cause1 = rcw_exc;
+
+	/* took exception? */
+	if (cause1 != 0) {
+		/* unclean exception? */
+		if (n != 2 || rcw_word != 1)
+			panic("S32C1I exception error");
+	} else if (rcw_word != 1 || n != 1) {
+		panic("S32C1I compare error");
+	}
+
+	/* Then an S32C1I that stores: */
+	rcw_exc = 0;
+	rcw_word = 0x1234567;
+	n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde);
+	cause2 = rcw_exc;
+
+	if (cause2 != 0) {
+		/* unclean exception? */
+		if (n != 0xabcde || rcw_word != 0x1234567)
+			panic("S32C1I exception error (b)");
+	} else if (rcw_word != 0xabcde || n != 0x1234567) {
+		panic("S32C1I store error");
+	}
+
+	/* Verify consistency of exceptions: */
+	if (cause1 || cause2) {
+		pr_warn("S32C1I took exception %d, %d\n", cause1, cause2);
+		/* If emulation of S32C1I upon bus error gets implemented,
+		 * we can get rid of this panic for single core (not SMP)
+		 */
+		panic("S32C1I exceptions not currently supported");
+	}
+	if (cause1 != cause2)
+		panic("inconsistent S32C1I exceptions");
+
+	trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus);
+	trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata);
+	trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr);
+	return 0;
+}
+
+#else /* XCHAL_HAVE_S32C1I */
+
+/* This condition should not occur with a commercially deployed processor.
+ * Display reminder for early engr test or demo chips / FPGA bitstreams
+ */
+static int __init check_s32c1i(void)
+{
+	pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
+	return 0;
+}
+
+#endif /* XCHAL_HAVE_S32C1I */
+
+early_initcall(check_s32c1i);
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/setup.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/setup.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/setup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/setup.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,10 +31,6 @@
 # include <linux/console.h>
 #endif
 
-#ifdef CONFIG_RTC
-# include <linux/timex.h>
-#endif
-
 #ifdef CONFIG_PROC_FS
 # include <linux/seq_file.h>
 #endif
@@ -48,24 +44,22 @@
 #include <asm/page.h>
 #include <asm/setup.h>
 #include <asm/param.h>
-#include <asm/traps.h>
 #include <asm/smp.h>
 #include <asm/sysmem.h>
 
 #include <platform/hardware.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
-struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
-#endif
-
-#ifdef CONFIG_BLK_DEV_FD
-extern struct fd_ops no_fd_ops;
-struct fd_ops *fd_ops;
+struct screen_info screen_info = {
+	.orig_x = 0,
+	.orig_y = 24,
+	.orig_video_cols = 80,
+	.orig_video_lines = 24,
+	.orig_video_isVGA = 1,
+	.orig_video_points = 16,
+};
 #endif
 
-extern struct rtc_ops no_rtc_ops;
-struct rtc_ops *rtc_ops;
-
 #ifdef CONFIG_BLK_DEV_INITRD
 extern unsigned long initrd_start;
 extern unsigned long initrd_end;
@@ -77,7 +71,6 @@ extern int initrd_below_start_ok;
 void *dtb_start = __dtb_start;
 #endif
 
-unsigned char aux_device_present;
 extern unsigned long loops_per_jiffy;
 
 /* Command line specified as configuration option. */
@@ -317,120 +310,6 @@ extern char _SecondaryResetVector_text_s
 extern char _SecondaryResetVector_text_end;
 #endif
 
-
-#ifdef CONFIG_S32C1I_SELFTEST
-#if XCHAL_HAVE_S32C1I
-
-static int __initdata rcw_word, rcw_probe_pc, rcw_exc;
-
-/*
- * Basic atomic compare-and-swap, that records PC of S32C1I for probing.
- *
- * If *v == cmp, set *v = set.  Return previous *v.
- */
-static inline int probed_compare_swap(int *v, int cmp, int set)
-{
-	int tmp;
-
-	__asm__ __volatile__(
-			"	movi	%1, 1f\n"
-			"	s32i	%1, %4, 0\n"
-			"	wsr	%2, scompare1\n"
-			"1:	s32c1i	%0, %3, 0\n"
-			: "=a" (set), "=&a" (tmp)
-			: "a" (cmp), "a" (v), "a" (&rcw_probe_pc), "0" (set)
-			: "memory"
-			);
-	return set;
-}
-
-/* Handle probed exception */
-
-static void __init do_probed_exception(struct pt_regs *regs,
-		unsigned long exccause)
-{
-	if (regs->pc == rcw_probe_pc) {	/* exception on s32c1i ? */
-		regs->pc += 3;		/* skip the s32c1i instruction */
-		rcw_exc = exccause;
-	} else {
-		do_unhandled(regs, exccause);
-	}
-}
-
-/* Simple test of S32C1I (soc bringup assist) */
-
-static int __init check_s32c1i(void)
-{
-	int n, cause1, cause2;
-	void *handbus, *handdata, *handaddr; /* temporarily saved handlers */
-
-	rcw_probe_pc = 0;
-	handbus  = trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR,
-			do_probed_exception);
-	handdata = trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR,
-			do_probed_exception);
-	handaddr = trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR,
-			do_probed_exception);
-
-	/* First try an S32C1I that does not store: */
-	rcw_exc = 0;
-	rcw_word = 1;
-	n = probed_compare_swap(&rcw_word, 0, 2);
-	cause1 = rcw_exc;
-
-	/* took exception? */
-	if (cause1 != 0) {
-		/* unclean exception? */
-		if (n != 2 || rcw_word != 1)
-			panic("S32C1I exception error");
-	} else if (rcw_word != 1 || n != 1) {
-		panic("S32C1I compare error");
-	}
-
-	/* Then an S32C1I that stores: */
-	rcw_exc = 0;
-	rcw_word = 0x1234567;
-	n = probed_compare_swap(&rcw_word, 0x1234567, 0xabcde);
-	cause2 = rcw_exc;
-
-	if (cause2 != 0) {
-		/* unclean exception? */
-		if (n != 0xabcde || rcw_word != 0x1234567)
-			panic("S32C1I exception error (b)");
-	} else if (rcw_word != 0xabcde || n != 0x1234567) {
-		panic("S32C1I store error");
-	}
-
-	/* Verify consistency of exceptions: */
-	if (cause1 || cause2) {
-		pr_warn("S32C1I took exception %d, %d\n", cause1, cause2);
-		/* If emulation of S32C1I upon bus error gets implemented,
-		   we can get rid of this panic for single core (not SMP) */
-		panic("S32C1I exceptions not currently supported");
-	}
-	if (cause1 != cause2)
-		panic("inconsistent S32C1I exceptions");
-
-	trap_set_handler(EXCCAUSE_LOAD_STORE_ERROR, handbus);
-	trap_set_handler(EXCCAUSE_LOAD_STORE_DATA_ERROR, handdata);
-	trap_set_handler(EXCCAUSE_LOAD_STORE_ADDR_ERROR, handaddr);
-	return 0;
-}
-
-#else /* XCHAL_HAVE_S32C1I */
-
-/* This condition should not occur with a commercially deployed processor.
-   Display reminder for early engr test or demo chips / FPGA bitstreams */
-static int __init check_s32c1i(void)
-{
-	pr_warn("Processor configuration lacks atomic compare-and-swap support!\n");
-	return 0;
-}
-
-#endif /* XCHAL_HAVE_S32C1I */
-early_initcall(check_s32c1i);
-#endif /* CONFIG_S32C1I_SELFTEST */
-
 static inline int mem_reserve(unsigned long start, unsigned long end)
 {
 	return memblock_reserve(start, end - start);
@@ -540,7 +419,7 @@ subsys_initcall(topology_init);
 
 void cpu_reset(void)
 {
-#if XCHAL_HAVE_PTP_MMU
+#if XCHAL_HAVE_PTP_MMU && IS_ENABLED(CONFIG_MMU)
 	local_irq_disable();
 	/*
 	 * We have full MMU: all autoload ways, ways 7, 8 and 9 of DTLB must
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/signal.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/signal.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/signal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/signal.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/tracehook.h>
 
 #include <asm/ucontext.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/coprocessor.h>
 #include <asm/unistd.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/stacktrace.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/stacktrace.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/stacktrace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/stacktrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #if IS_ENABLED(CONFIG_OPROFILE) || IS_ENABLED(CONFIG_PERF_EVENTS)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/syscall.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/syscall.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/syscall.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/syscall.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
  * Kevin Chea
  *
  */
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/syscall.h>
 #include <asm/unistd.h>
 #include <linux/linkage.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/time.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/time.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/time.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/time.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,9 +34,9 @@
 unsigned long ccount_freq;		/* ccount Hz */
 EXPORT_SYMBOL(ccount_freq);
 
-static cycle_t ccount_read(struct clocksource *cs)
+static u64 ccount_read(struct clocksource *cs)
 {
-	return (cycle_t)get_ccount();
+	return (u64)get_ccount();
 }
 
 static u64 notrace ccount_sched_clock_read(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/traps.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/traps.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/traps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/traps.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <asm/stacktrace.h>
 #include <asm/ptrace.h>
 #include <asm/timex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/traps.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/kernel/xtensa_ksyms.c linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/xtensa_ksyms.c
--- linux-libre-4.9-gnu/arch/xtensa/kernel/xtensa_ksyms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/kernel/xtensa_ksyms.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <asm/irq.h>
 #include <linux/in6.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/checksum.h>
 #include <asm/dma.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/mm/init.c linux-libre-4.10-rc8-gnu/arch/xtensa/mm/init.c
--- linux-libre-4.9-gnu/arch/xtensa/mm/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/mm/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/nodemask.h>
 #include <linux/mm.h>
 #include <linux/of_fdt.h>
+#include <linux/dma-contiguous.h>
 
 #include <asm/bootparam.h>
 #include <asm/page.h>
@@ -60,6 +61,7 @@ void __init bootmem_init(void)
 	max_low_pfn = min(max_pfn, MAX_LOW_PFN);
 
 	memblock_set_current_limit(PFN_PHYS(max_low_pfn));
+	dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
 
 	memblock_dump_all();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/platforms/iss/console.c linux-libre-4.10-rc8-gnu/arch/xtensa/platforms/iss/console.c
--- linux-libre-4.9-gnu/arch/xtensa/platforms/iss/console.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/platforms/iss/console.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/seq_file.h>
 #include <linux/serial.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 
 #include <platform/simcall.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/arch/xtensa/platforms/iss/simdisk.c linux-libre-4.10-rc8-gnu/arch/xtensa/platforms/iss/simdisk.c
--- linux-libre-4.9-gnu/arch/xtensa/platforms/iss/simdisk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/arch/xtensa/platforms/iss/simdisk.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/proc_fs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <platform/simcall.h>
 
 #define SIMDISK_MAJOR 240
diff -druNp --no-dereference linux-libre-4.9-gnu/block/bio.c linux-libre-4.10-rc8-gnu/block/bio.c
--- linux-libre-4.9-gnu/block/bio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/bio.c	2017-02-12 16:03:20.000000000 -0500
@@ -270,11 +270,15 @@ static void bio_free(struct bio *bio)
 	}
 }
 
-void bio_init(struct bio *bio)
+void bio_init(struct bio *bio, struct bio_vec *table,
+	      unsigned short max_vecs)
 {
 	memset(bio, 0, sizeof(*bio));
 	atomic_set(&bio->__bi_remaining, 1);
 	atomic_set(&bio->__bi_cnt, 1);
+
+	bio->bi_io_vec = table;
+	bio->bi_max_vecs = max_vecs;
 }
 EXPORT_SYMBOL(bio_init);
 
@@ -480,7 +484,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_m
 		return NULL;
 
 	bio = p + front_pad;
-	bio_init(bio);
+	bio_init(bio, NULL, 0);
 
 	if (nr_iovecs > inline_vecs) {
 		unsigned long idx = 0;
@@ -670,6 +674,7 @@ struct bio *bio_clone_bioset(struct bio
 	switch (bio_op(bio)) {
 	case REQ_OP_DISCARD:
 	case REQ_OP_SECURE_ERASE:
+	case REQ_OP_WRITE_ZEROES:
 		break;
 	case REQ_OP_WRITE_SAME:
 		bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0];
@@ -847,6 +852,55 @@ done:
 }
 EXPORT_SYMBOL(bio_add_page);
 
+/**
+ * bio_iov_iter_get_pages - pin user or kernel pages and add them to a bio
+ * @bio: bio to add pages to
+ * @iter: iov iterator describing the region to be mapped
+ *
+ * Pins as many pages from *iter and appends them to @bio's bvec array. The
+ * pages will have to be released using put_page() when done.
+ */
+int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
+{
+	unsigned short nr_pages = bio->bi_max_vecs - bio->bi_vcnt;
+	struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt;
+	struct page **pages = (struct page **)bv;
+	size_t offset, diff;
+	ssize_t size;
+
+	size = iov_iter_get_pages(iter, pages, LONG_MAX, nr_pages, &offset);
+	if (unlikely(size <= 0))
+		return size ? size : -EFAULT;
+	nr_pages = (size + offset + PAGE_SIZE - 1) / PAGE_SIZE;
+
+	/*
+	 * Deep magic below:  We need to walk the pinned pages backwards
+	 * because we are abusing the space allocated for the bio_vecs
+	 * for the page array.  Because the bio_vecs are larger than the
+	 * page pointers by definition this will always work.  But it also
+	 * means we can't use bio_add_page, so any changes to it's semantics
+	 * need to be reflected here as well.
+	 */
+	bio->bi_iter.bi_size += size;
+	bio->bi_vcnt += nr_pages;
+
+	diff = (nr_pages * PAGE_SIZE - offset) - size;
+	while (nr_pages--) {
+		bv[nr_pages].bv_page = pages[nr_pages];
+		bv[nr_pages].bv_len = PAGE_SIZE;
+		bv[nr_pages].bv_offset = 0;
+	}
+
+	bv[0].bv_offset += offset;
+	bv[0].bv_len -= offset;
+	if (diff)
+		bv[bio->bi_vcnt - 1].bv_len -= diff;
+
+	iov_iter_advance(iter, size);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(bio_iov_iter_get_pages);
+
 struct submit_bio_ret {
 	struct completion event;
 	int error;
@@ -1786,15 +1840,7 @@ struct bio *bio_split(struct bio *bio, i
 	BUG_ON(sectors <= 0);
 	BUG_ON(sectors >= bio_sectors(bio));
 
-	/*
-	 * Discards need a mutable bio_vec to accommodate the payload
-	 * required by the DSM TRIM and UNMAP commands.
-	 */
-	if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE)
-		split = bio_clone_bioset(bio, gfp, bs);
-	else
-		split = bio_clone_fast(bio, gfp, bs);
-
+	split = bio_clone_fast(bio, gfp, bs);
 	if (!split)
 		return NULL;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/block/bio-integrity.c linux-libre-4.10-rc8-gnu/block/bio-integrity.c
--- linux-libre-4.9-gnu/block/bio-integrity.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/bio-integrity.c	2017-02-12 16:03:20.000000000 -0500
@@ -172,7 +172,7 @@ bool bio_integrity_enabled(struct bio *b
 {
 	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
 
-	if (!bio_is_rw(bio))
+	if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE)
 		return false;
 
 	/* Already protected? */
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-cgroup.c linux-libre-4.10-rc8-gnu/block/blk-cgroup.c
--- linux-libre-4.9-gnu/block/blk-cgroup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-cgroup.c	2017-02-12 16:03:20.000000000 -0500
@@ -185,7 +185,8 @@ static struct blkcg_gq *blkg_create(stru
 	}
 
 	wb_congested = wb_congested_get_create(&q->backing_dev_info,
-					       blkcg->css.id, GFP_NOWAIT);
+					       blkcg->css.id,
+					       GFP_NOWAIT | __GFP_NOWARN);
 	if (!wb_congested) {
 		ret = -ENOMEM;
 		goto err_put_css;
@@ -193,7 +194,7 @@ static struct blkcg_gq *blkg_create(stru
 
 	/* allocate */
 	if (!new_blkg) {
-		new_blkg = blkg_alloc(blkcg, q, GFP_NOWAIT);
+		new_blkg = blkg_alloc(blkcg, q, GFP_NOWAIT | __GFP_NOWARN);
 		if (unlikely(!new_blkg)) {
 			ret = -ENOMEM;
 			goto err_put_congested;
@@ -1022,7 +1023,7 @@ blkcg_css_alloc(struct cgroup_subsys_sta
 	}
 
 	spin_lock_init(&blkcg->lock);
-	INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_NOWAIT);
+	INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_NOWAIT | __GFP_NOWARN);
 	INIT_HLIST_HEAD(&blkcg->blkg_list);
 #ifdef CONFIG_CGROUP_WRITEBACK
 	INIT_LIST_HEAD(&blkcg->cgwb_list);
@@ -1240,7 +1241,7 @@ pd_prealloc:
 		if (blkg->pd[pol->plid])
 			continue;
 
-		pd = pol->pd_alloc_fn(GFP_NOWAIT, q->node);
+		pd = pol->pd_alloc_fn(GFP_NOWAIT | __GFP_NOWARN, q->node);
 		if (!pd)
 			swap(pd, pd_prealloc);
 		if (!pd) {
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-core.c linux-libre-4.10-rc8-gnu/block/blk-core.c
--- linux-libre-4.9-gnu/block/blk-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,7 @@
 
 #include "blk.h"
 #include "blk-mq.h"
+#include "blk-wbt.h"
 
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
@@ -145,13 +146,13 @@ static void req_bio_endio(struct request
 	if (error)
 		bio->bi_error = error;
 
-	if (unlikely(rq->cmd_flags & REQ_QUIET))
+	if (unlikely(rq->rq_flags & RQF_QUIET))
 		bio_set_flag(bio, BIO_QUIET);
 
 	bio_advance(bio, nbytes);
 
 	/* don't actually finish bio if it's part of flush sequence */
-	if (bio->bi_iter.bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
+	if (bio->bi_iter.bi_size == 0 && !(rq->rq_flags & RQF_FLUSH_SEQ))
 		bio_endio(bio);
 }
 
@@ -882,6 +883,7 @@ blk_init_allocated_queue(struct request_
 
 fail:
 	blk_free_flush_queue(q->fq);
+	wbt_exit(q);
 	return NULL;
 }
 EXPORT_SYMBOL(blk_init_allocated_queue);
@@ -899,7 +901,7 @@ EXPORT_SYMBOL(blk_get_queue);
 
 static inline void blk_free_request(struct request_list *rl, struct request *rq)
 {
-	if (rq->cmd_flags & REQ_ELVPRIV) {
+	if (rq->rq_flags & RQF_ELVPRIV) {
 		elv_put_request(rl->q, rq);
 		if (rq->elv.icq)
 			put_io_context(rq->elv.icq->ioc);
@@ -961,14 +963,14 @@ static void __freed_request(struct reque
  * 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_list *rl, int op, unsigned int flags)
+static void freed_request(struct request_list *rl, bool sync,
+		req_flags_t rq_flags)
 {
 	struct request_queue *q = rl->q;
-	int sync = rw_is_sync(op, flags);
 
 	q->nr_rqs[sync]--;
 	rl->count[sync]--;
-	if (flags & REQ_ELVPRIV)
+	if (rq_flags & RQF_ELVPRIV)
 		q->nr_rqs_elvpriv--;
 
 	__freed_request(rl, sync);
@@ -1056,8 +1058,7 @@ static struct io_context *rq_ioc(struct
 /**
  * __get_request - get a free request
  * @rl: request list to allocate from
- * @op: REQ_OP_READ/REQ_OP_WRITE
- * @op_flags: rq_flag_bits
+ * @op: operation and flags
  * @bio: bio to allocate request for (can be %NULL)
  * @gfp_mask: allocation mask
  *
@@ -1068,22 +1069,22 @@ static struct io_context *rq_ioc(struct
  * Returns ERR_PTR on failure, with @q->queue_lock held.
  * Returns request pointer on success, with @q->queue_lock *not held*.
  */
-static struct request *__get_request(struct request_list *rl, int op,
-				     int op_flags, struct bio *bio,
-				     gfp_t gfp_mask)
+static struct request *__get_request(struct request_list *rl, unsigned int op,
+		struct bio *bio, gfp_t gfp_mask)
 {
 	struct request_queue *q = rl->q;
 	struct request *rq;
 	struct elevator_type *et = q->elevator->type;
 	struct io_context *ioc = rq_ioc(bio);
 	struct io_cq *icq = NULL;
-	const bool is_sync = rw_is_sync(op, op_flags) != 0;
+	const bool is_sync = op_is_sync(op);
 	int may_queue;
+	req_flags_t rq_flags = RQF_ALLOCED;
 
 	if (unlikely(blk_queue_dying(q)))
 		return ERR_PTR(-ENODEV);
 
-	may_queue = elv_may_queue(q, op, op_flags);
+	may_queue = elv_may_queue(q, op);
 	if (may_queue == ELV_MQUEUE_NO)
 		goto rq_starved;
 
@@ -1127,7 +1128,7 @@ static struct request *__get_request(str
 
 	/*
 	 * Decide whether the new request will be managed by elevator.  If
-	 * so, mark @op_flags and increment elvpriv.  Non-zero elvpriv will
+	 * so, mark @rq_flags and increment elvpriv.  Non-zero elvpriv will
 	 * prevent the current elevator from being destroyed until the new
 	 * request is freed.  This guarantees icq's won't be destroyed and
 	 * makes creating new ones safe.
@@ -1136,14 +1137,14 @@ static struct request *__get_request(str
 	 * it will be created after releasing queue_lock.
 	 */
 	if (blk_rq_should_init_elevator(bio) && !blk_queue_bypass(q)) {
-		op_flags |= REQ_ELVPRIV;
+		rq_flags |= RQF_ELVPRIV;
 		q->nr_rqs_elvpriv++;
 		if (et->icq_cache && ioc)
 			icq = ioc_lookup_icq(ioc, q);
 	}
 
 	if (blk_queue_io_stat(q))
-		op_flags |= REQ_IO_STAT;
+		rq_flags |= RQF_IO_STAT;
 	spin_unlock_irq(q->queue_lock);
 
 	/* allocate and init request */
@@ -1153,10 +1154,12 @@ static struct request *__get_request(str
 
 	blk_rq_init(q, rq);
 	blk_rq_set_rl(rq, rl);
-	req_set_op_attrs(rq, op, op_flags | REQ_ALLOCED);
+	blk_rq_set_prio(rq, ioc);
+	rq->cmd_flags = op;
+	rq->rq_flags = rq_flags;
 
 	/* init elvpriv */
-	if (op_flags & REQ_ELVPRIV) {
+	if (rq_flags & RQF_ELVPRIV) {
 		if (unlikely(et->icq_cache && !icq)) {
 			if (ioc)
 				icq = ioc_create_icq(ioc, q, gfp_mask);
@@ -1195,7 +1198,7 @@ fail_elvpriv:
 	printk_ratelimited(KERN_WARNING "%s: dev %s: request aux data allocation failed, iosched may be disturbed\n",
 			   __func__, dev_name(q->backing_dev_info.dev));
 
-	rq->cmd_flags &= ~REQ_ELVPRIV;
+	rq->rq_flags &= ~RQF_ELVPRIV;
 	rq->elv.icq = NULL;
 
 	spin_lock_irq(q->queue_lock);
@@ -1212,7 +1215,7 @@ fail_alloc:
 	 * queue, but this is pretty rare.
 	 */
 	spin_lock_irq(q->queue_lock);
-	freed_request(rl, op, op_flags);
+	freed_request(rl, is_sync, rq_flags);
 
 	/*
 	 * in the very unlikely event that allocation failed and no
@@ -1230,8 +1233,7 @@ rq_starved:
 /**
  * get_request - get a free request
  * @q: request_queue to allocate request from
- * @op: REQ_OP_READ/REQ_OP_WRITE
- * @op_flags: rq_flag_bits
+ * @op: operation and flags
  * @bio: bio to allocate request for (can be %NULL)
  * @gfp_mask: allocation mask
  *
@@ -1242,18 +1244,17 @@ rq_starved:
  * Returns ERR_PTR on failure, with @q->queue_lock held.
  * Returns request pointer on success, with @q->queue_lock *not held*.
  */
-static struct request *get_request(struct request_queue *q, int op,
-				   int op_flags, struct bio *bio,
-				   gfp_t gfp_mask)
+static struct request *get_request(struct request_queue *q, unsigned int op,
+		struct bio *bio, gfp_t gfp_mask)
 {
-	const bool is_sync = rw_is_sync(op, op_flags) != 0;
+	const bool is_sync = op_is_sync(op);
 	DEFINE_WAIT(wait);
 	struct request_list *rl;
 	struct request *rq;
 
 	rl = blk_get_rl(q, bio);	/* transferred to @rq on success */
 retry:
-	rq = __get_request(rl, op, op_flags, bio, gfp_mask);
+	rq = __get_request(rl, op, bio, gfp_mask);
 	if (!IS_ERR(rq))
 		return rq;
 
@@ -1295,7 +1296,7 @@ static struct request *blk_old_get_reque
 	create_io_context(gfp_mask, q->node);
 
 	spin_lock_irq(q->queue_lock);
-	rq = get_request(q, rw, 0, NULL, gfp_mask);
+	rq = get_request(q, rw, NULL, gfp_mask);
 	if (IS_ERR(rq)) {
 		spin_unlock_irq(q->queue_lock);
 		return rq;
@@ -1346,8 +1347,9 @@ void blk_requeue_request(struct request_
 	blk_delete_timer(rq);
 	blk_clear_rq_complete(rq);
 	trace_block_rq_requeue(q, rq);
+	wbt_requeue(q->rq_wb, &rq->issue_stat);
 
-	if (rq->cmd_flags & REQ_QUEUED)
+	if (rq->rq_flags & RQF_QUEUED)
 		blk_queue_end_tag(q, rq);
 
 	BUG_ON(blk_queued_rq(rq));
@@ -1409,7 +1411,7 @@ EXPORT_SYMBOL_GPL(part_round_stats);
 #ifdef CONFIG_PM
 static void blk_pm_put_request(struct request *rq)
 {
-	if (rq->q->dev && !(rq->cmd_flags & REQ_PM) && !--rq->q->nr_pending)
+	if (rq->q->dev && !(rq->rq_flags & RQF_PM) && !--rq->q->nr_pending)
 		pm_runtime_mark_last_busy(rq->q->dev);
 }
 #else
@@ -1421,6 +1423,8 @@ static inline void blk_pm_put_request(st
  */
 void __blk_put_request(struct request_queue *q, struct request *req)
 {
+	req_flags_t rq_flags = req->rq_flags;
+
 	if (unlikely(!q))
 		return;
 
@@ -1436,20 +1440,21 @@ void __blk_put_request(struct request_qu
 	/* this is a bio leak */
 	WARN_ON(req->bio != NULL);
 
+	wbt_done(q->rq_wb, &req->issue_stat);
+
 	/*
 	 * Request may not have originated from ll_rw_blk. if not,
 	 * it didn't come out of our reserved rq pools
 	 */
-	if (req->cmd_flags & REQ_ALLOCED) {
-		unsigned int flags = req->cmd_flags;
-		int op = req_op(req);
+	if (rq_flags & RQF_ALLOCED) {
 		struct request_list *rl = blk_rq_rl(req);
+		bool sync = op_is_sync(req->cmd_flags);
 
 		BUG_ON(!list_empty(&req->queuelist));
 		BUG_ON(ELV_ON_HASH(req));
 
 		blk_free_request(rl, req);
-		freed_request(rl, op, flags);
+		freed_request(rl, sync, rq_flags);
 		blk_put_rl(rl);
 	}
 }
@@ -1471,38 +1476,6 @@ void blk_put_request(struct request *req
 }
 EXPORT_SYMBOL(blk_put_request);
 
-/**
- * blk_add_request_payload - add a payload to a request
- * @rq: request to update
- * @page: page backing the payload
- * @offset: offset in page
- * @len: length of the payload.
- *
- * This allows to later add a payload to an already submitted request by
- * a block driver.  The driver needs to take care of freeing the payload
- * itself.
- *
- * Note that this is a quite horrible hack and nothing but handling of
- * discard requests should ever use it.
- */
-void blk_add_request_payload(struct request *rq, struct page *page,
-		int offset, unsigned int len)
-{
-	struct bio *bio = rq->bio;
-
-	bio->bi_io_vec->bv_page = page;
-	bio->bi_io_vec->bv_offset = offset;
-	bio->bi_io_vec->bv_len = len;
-
-	bio->bi_iter.bi_size = len;
-	bio->bi_vcnt = 1;
-	bio->bi_phys_segments = 1;
-
-	rq->__data_len = rq->resid_len = len;
-	rq->nr_phys_segments = 1;
-}
-EXPORT_SYMBOL_GPL(blk_add_request_payload);
-
 bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
 			    struct bio *bio)
 {
@@ -1649,24 +1622,23 @@ out:
 void init_request_from_bio(struct request *req, struct bio *bio)
 {
 	req->cmd_type = REQ_TYPE_FS;
-
-	req->cmd_flags |= bio->bi_opf & REQ_COMMON_MASK;
 	if (bio->bi_opf & REQ_RAHEAD)
 		req->cmd_flags |= REQ_FAILFAST_MASK;
 
 	req->errors = 0;
 	req->__sector = bio->bi_iter.bi_sector;
-	req->ioprio = bio_prio(bio);
+	if (ioprio_valid(bio_prio(bio)))
+		req->ioprio = bio_prio(bio);
 	blk_rq_bio_prep(req->q, req, bio);
 }
 
 static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
 {
-	const bool sync = !!(bio->bi_opf & REQ_SYNC);
 	struct blk_plug *plug;
-	int el_ret, rw_flags = 0, where = ELEVATOR_INSERT_SORT;
+	int el_ret, where = ELEVATOR_INSERT_SORT;
 	struct request *req;
 	unsigned int request_count = 0;
+	unsigned int wb_acct;
 
 	/*
 	 * low level driver can indicate that it wants pages above a
@@ -1719,30 +1691,22 @@ static blk_qc_t blk_queue_bio(struct req
 	}
 
 get_rq:
-	/*
-	 * This sync check and mask will be re-done in init_request_from_bio(),
-	 * but we need to set it earlier to expose the sync flag to the
-	 * rq allocator and io schedulers.
-	 */
-	if (sync)
-		rw_flags |= REQ_SYNC;
-
-	/*
-	 * Add in META/PRIO flags, if set, before we get to the IO scheduler
-	 */
-	rw_flags |= (bio->bi_opf & (REQ_META | REQ_PRIO));
+	wb_acct = wbt_wait(q->rq_wb, bio, q->queue_lock);
 
 	/*
 	 * Grab a free request. This is might sleep but can not fail.
 	 * Returns with the queue unlocked.
 	 */
-	req = get_request(q, bio_data_dir(bio), rw_flags, bio, GFP_NOIO);
+	req = get_request(q, bio->bi_opf, bio, GFP_NOIO);
 	if (IS_ERR(req)) {
+		__wbt_done(q->rq_wb, wb_acct);
 		bio->bi_error = PTR_ERR(req);
 		bio_endio(bio);
 		goto out_unlock;
 	}
 
+	wbt_track(&req->issue_stat, wb_acct);
+
 	/*
 	 * After dropping the lock and possibly sleeping here, our request
 	 * may now be mergeable after it had proven unmergeable (above).
@@ -1759,11 +1723,16 @@ get_rq:
 		/*
 		 * If this is the first request added after a plug, fire
 		 * of a plug trace.
+		 *
+		 * @request_count may become stale because of schedule
+		 * out, so check plug list again.
 		 */
-		if (!request_count)
+		if (!request_count || list_empty(&plug->list))
 			trace_block_plug(q);
 		else {
-			if (request_count >= BLK_MAX_REQUEST_COUNT) {
+			struct request *last = list_entry_rq(plug->list.prev);
+			if (request_count >= BLK_MAX_REQUEST_COUNT ||
+			    blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE) {
 				blk_flush_plug_list(plug, false);
 				trace_block_plug(q);
 			}
@@ -1788,7 +1757,12 @@ static inline void blk_partition_remap(s
 {
 	struct block_device *bdev = bio->bi_bdev;
 
-	if (bio_sectors(bio) && bdev != bdev->bd_contains) {
+	/*
+	 * Zone reset does not include bi_size so bio_sectors() is always 0.
+	 * Include a test for the reset op code and perform the remap if needed.
+	 */
+	if (bdev != bdev->bd_contains &&
+	    (bio_sectors(bio) || bio_op(bio) == REQ_OP_ZONE_RESET)) {
 		struct hd_struct *p = bdev->bd_part;
 
 		bio->bi_iter.bi_sector += p->start_sect;
@@ -1942,6 +1916,15 @@ generic_make_request_checks(struct bio *
 		if (!bdev_write_same(bio->bi_bdev))
 			goto not_supported;
 		break;
+	case REQ_OP_ZONE_REPORT:
+	case REQ_OP_ZONE_RESET:
+		if (!bdev_is_zoned(bio->bi_bdev))
+			goto not_supported;
+		break;
+	case REQ_OP_WRITE_ZEROES:
+		if (!bdev_write_zeroes_sectors(bio->bi_bdev))
+			goto not_supported;
+		break;
 	default:
 		break;
 	}
@@ -2210,7 +2193,7 @@ unsigned int blk_rq_err_bytes(const stru
 	unsigned int bytes = 0;
 	struct bio *bio;
 
-	if (!(rq->cmd_flags & REQ_MIXED_MERGE))
+	if (!(rq->rq_flags & RQF_MIXED_MERGE))
 		return blk_rq_bytes(rq);
 
 	/*
@@ -2253,7 +2236,7 @@ void blk_account_io_done(struct request
 	 * normal IO on queueing nor completion.  Accounting the
 	 * containing request is enough.
 	 */
-	if (blk_do_io_stat(req) && !(req->cmd_flags & REQ_FLUSH_SEQ)) {
+	if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
 		unsigned long duration = jiffies - req->start_time;
 		const int rw = rq_data_dir(req);
 		struct hd_struct *part;
@@ -2281,7 +2264,7 @@ static struct request *blk_pm_peek_reque
 					   struct request *rq)
 {
 	if (q->dev && (q->rpm_status == RPM_SUSPENDED ||
-	    (q->rpm_status != RPM_ACTIVE && !(rq->cmd_flags & REQ_PM))))
+	    (q->rpm_status != RPM_ACTIVE && !(rq->rq_flags & RQF_PM))))
 		return NULL;
 	else
 		return rq;
@@ -2357,13 +2340,13 @@ struct request *blk_peek_request(struct
 		if (!rq)
 			break;
 
-		if (!(rq->cmd_flags & REQ_STARTED)) {
+		if (!(rq->rq_flags & RQF_STARTED)) {
 			/*
 			 * This is the first time the device driver
 			 * sees this request (possibly after
 			 * requeueing).  Notify IO scheduler.
 			 */
-			if (rq->cmd_flags & REQ_SORTED)
+			if (rq->rq_flags & RQF_SORTED)
 				elv_activate_rq(q, rq);
 
 			/*
@@ -2371,7 +2354,7 @@ struct request *blk_peek_request(struct
 			 * it, a request that has been delayed should
 			 * not be passed by new incoming requests
 			 */
-			rq->cmd_flags |= REQ_STARTED;
+			rq->rq_flags |= RQF_STARTED;
 			trace_block_rq_issue(q, rq);
 		}
 
@@ -2380,7 +2363,7 @@ struct request *blk_peek_request(struct
 			q->boundary_rq = NULL;
 		}
 
-		if (rq->cmd_flags & REQ_DONTPREP)
+		if (rq->rq_flags & RQF_DONTPREP)
 			break;
 
 		if (q->dma_drain_size && blk_rq_bytes(rq)) {
@@ -2403,11 +2386,11 @@ struct request *blk_peek_request(struct
 			/*
 			 * the request may have been (partially) prepped.
 			 * we need to keep this request in the front to
-			 * avoid resource deadlock.  REQ_STARTED will
+			 * avoid resource deadlock.  RQF_STARTED will
 			 * prevent other fs requests from passing this one.
 			 */
 			if (q->dma_drain_size && blk_rq_bytes(rq) &&
-			    !(rq->cmd_flags & REQ_DONTPREP)) {
+			    !(rq->rq_flags & RQF_DONTPREP)) {
 				/*
 				 * remove the space for the drain we added
 				 * so that we don't add it again
@@ -2420,7 +2403,7 @@ struct request *blk_peek_request(struct
 		} else if (ret == BLKPREP_KILL || ret == BLKPREP_INVALID) {
 			int err = (ret == BLKPREP_INVALID) ? -EREMOTEIO : -EIO;
 
-			rq->cmd_flags |= REQ_QUIET;
+			rq->rq_flags |= RQF_QUIET;
 			/*
 			 * Mark this request as started so we don't trigger
 			 * any debug logic in the end I/O path.
@@ -2475,6 +2458,12 @@ void blk_start_request(struct request *r
 {
 	blk_dequeue_request(req);
 
+	if (test_bit(QUEUE_FLAG_STATS, &req->q->queue_flags)) {
+		blk_stat_set_issue_time(&req->issue_stat);
+		req->rq_flags |= RQF_STATS;
+		wbt_issue(req->q->rq_wb, &req->issue_stat);
+	}
+
 	/*
 	 * We are now handing the request to the hardware, initialize
 	 * resid_len to full count and add the timeout handler.
@@ -2557,7 +2546,7 @@ bool blk_update_request(struct request *
 		req->errors = 0;
 
 	if (error && req->cmd_type == REQ_TYPE_FS &&
-	    !(req->cmd_flags & REQ_QUIET)) {
+	    !(req->rq_flags & RQF_QUIET)) {
 		char *error_type;
 
 		switch (error) {
@@ -2623,6 +2612,8 @@ bool blk_update_request(struct request *
 		return false;
 	}
 
+	WARN_ON_ONCE(req->rq_flags & RQF_SPECIAL_PAYLOAD);
+
 	req->__data_len -= total_bytes;
 
 	/* update sector only for requests with clear definition of sector */
@@ -2630,7 +2621,7 @@ bool blk_update_request(struct request *
 		req->__sector += total_bytes >> 9;
 
 	/* mixed attributes always follow the first bio */
-	if (req->cmd_flags & REQ_MIXED_MERGE) {
+	if (req->rq_flags & RQF_MIXED_MERGE) {
 		req->cmd_flags &= ~REQ_FAILFAST_MASK;
 		req->cmd_flags |= req->bio->bi_opf & REQ_FAILFAST_MASK;
 	}
@@ -2683,7 +2674,7 @@ void blk_unprep_request(struct request *
 {
 	struct request_queue *q = req->q;
 
-	req->cmd_flags &= ~REQ_DONTPREP;
+	req->rq_flags &= ~RQF_DONTPREP;
 	if (q->unprep_rq_fn)
 		q->unprep_rq_fn(q, req);
 }
@@ -2694,8 +2685,13 @@ EXPORT_SYMBOL_GPL(blk_unprep_request);
  */
 void blk_finish_request(struct request *req, int error)
 {
-	if (req->cmd_flags & REQ_QUEUED)
-		blk_queue_end_tag(req->q, req);
+	struct request_queue *q = req->q;
+
+	if (req->rq_flags & RQF_STATS)
+		blk_stat_add(&q->rq_stats[rq_data_dir(req)], req);
+
+	if (req->rq_flags & RQF_QUEUED)
+		blk_queue_end_tag(q, req);
 
 	BUG_ON(blk_queued_rq(req));
 
@@ -2704,18 +2700,19 @@ void blk_finish_request(struct request *
 
 	blk_delete_timer(req);
 
-	if (req->cmd_flags & REQ_DONTPREP)
+	if (req->rq_flags & RQF_DONTPREP)
 		blk_unprep_request(req);
 
 	blk_account_io_done(req);
 
-	if (req->end_io)
+	if (req->end_io) {
+		wbt_done(req->q->rq_wb, &req->issue_stat);
 		req->end_io(req, error);
-	else {
+	} else {
 		if (blk_bidi_rq(req))
 			__blk_put_request(req->next_rq->q, req->next_rq);
 
-		__blk_put_request(req->q, req);
+		__blk_put_request(q, req);
 	}
 }
 EXPORT_SYMBOL(blk_finish_request);
@@ -2939,8 +2936,6 @@ EXPORT_SYMBOL_GPL(__blk_end_request_err)
 void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
 		     struct bio *bio)
 {
-	req_set_op(rq, bio_op(bio));
-
 	if (bio_has_data(bio))
 		rq->nr_phys_segments = bio_phys_segments(q, bio);
 
@@ -3024,8 +3019,7 @@ EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);
 static void __blk_rq_prep_clone(struct request *dst, struct request *src)
 {
 	dst->cpu = src->cpu;
-	req_set_op_attrs(dst, req_op(src),
-			 (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE);
+	dst->cmd_flags = src->cmd_flags | REQ_NOMERGE;
 	dst->cmd_type = src->cmd_type;
 	dst->__sector = blk_rq_pos(src);
 	dst->__data_len = blk_rq_bytes(src);
@@ -3303,52 +3297,6 @@ void blk_finish_plug(struct blk_plug *pl
 }
 EXPORT_SYMBOL(blk_finish_plug);
 
-bool blk_poll(struct request_queue *q, blk_qc_t cookie)
-{
-	struct blk_plug *plug;
-	long state;
-	unsigned int queue_num;
-	struct blk_mq_hw_ctx *hctx;
-
-	if (!q->mq_ops || !q->mq_ops->poll || !blk_qc_t_valid(cookie) ||
-	    !test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
-		return false;
-
-	queue_num = blk_qc_t_to_queue_num(cookie);
-	hctx = q->queue_hw_ctx[queue_num];
-	hctx->poll_considered++;
-
-	plug = current->plug;
-	if (plug)
-		blk_flush_plug_list(plug, false);
-
-	state = current->state;
-	while (!need_resched()) {
-		int ret;
-
-		hctx->poll_invoked++;
-
-		ret = q->mq_ops->poll(hctx, blk_qc_t_to_tag(cookie));
-		if (ret > 0) {
-			hctx->poll_success++;
-			set_current_state(TASK_RUNNING);
-			return true;
-		}
-
-		if (signal_pending_state(state, current))
-			set_current_state(TASK_RUNNING);
-
-		if (current->state == TASK_RUNNING)
-			return true;
-		if (ret < 0)
-			break;
-		cpu_relax();
-	}
-
-	return false;
-}
-EXPORT_SYMBOL_GPL(blk_poll);
-
 #ifdef CONFIG_PM
 /**
  * blk_pm_runtime_init - Block layer runtime PM initialization routine
@@ -3530,8 +3478,11 @@ EXPORT_SYMBOL(blk_set_runtime_active);
 
 int __init blk_dev_init(void)
 {
-	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
+	BUILD_BUG_ON(REQ_OP_LAST >= (1 << REQ_OP_BITS));
+	BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
 			FIELD_SIZEOF(struct request, cmd_flags));
+	BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
+			FIELD_SIZEOF(struct bio, bi_opf));
 
 	/* used for unplugging and affects IO latency/throughput - HIGHPRI */
 	kblockd_workqueue = alloc_workqueue("kblockd",
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-exec.c linux-libre-4.10-rc8-gnu/block/blk-exec.c
--- linux-libre-4.9-gnu/block/blk-exec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-exec.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,7 @@ void blk_execute_rq_nowait(struct reques
 	spin_lock_irq(q->queue_lock);
 
 	if (unlikely(blk_queue_dying(q))) {
-		rq->cmd_flags |= REQ_QUIET; 
+		rq->rq_flags |= RQF_QUIET;
 		rq->errors = -ENXIO;
 		__blk_end_request_all(rq, rq->errors);
 		spin_unlock_irq(q->queue_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-flush.c linux-libre-4.10-rc8-gnu/block/blk-flush.c
--- linux-libre-4.9-gnu/block/blk-flush.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-flush.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@
  * Once while executing DATA and again after the whole sequence is
  * complete.  The first completion updates the contained bio but doesn't
  * finish it so that the bio submitter is notified only after the whole
- * sequence is complete.  This is implemented by testing REQ_FLUSH_SEQ in
+ * sequence is complete.  This is implemented by testing RQF_FLUSH_SEQ in
  * req_bio_endio().
  *
  * The above peculiarity requires that each FLUSH/FUA request has only one
@@ -127,17 +127,14 @@ static void blk_flush_restore_request(st
 	rq->bio = rq->biotail;
 
 	/* make @rq a normal request */
-	rq->cmd_flags &= ~REQ_FLUSH_SEQ;
+	rq->rq_flags &= ~RQF_FLUSH_SEQ;
 	rq->end_io = rq->flush.saved_end_io;
 }
 
 static bool blk_flush_queue_rq(struct request *rq, bool add_front)
 {
 	if (rq->q->mq_ops) {
-		struct request_queue *q = rq->q;
-
-		blk_mq_add_to_requeue_list(rq, add_front);
-		blk_mq_kick_requeue_list(q);
+		blk_mq_add_to_requeue_list(rq, add_front, true);
 		return false;
 	} else {
 		if (add_front)
@@ -330,7 +327,8 @@ static bool blk_kick_flush(struct reques
 	}
 
 	flush_rq->cmd_type = REQ_TYPE_FS;
-	req_set_op_attrs(flush_rq, REQ_OP_FLUSH, WRITE_FLUSH | REQ_FLUSH_SEQ);
+	flush_rq->cmd_flags = REQ_OP_FLUSH | REQ_PREFLUSH;
+	flush_rq->rq_flags |= RQF_FLUSH_SEQ;
 	flush_rq->rq_disk = first_rq->rq_disk;
 	flush_rq->end_io = flush_end_io;
 
@@ -368,7 +366,7 @@ static void flush_data_end_io(struct req
 	elv_completed_request(q, rq);
 
 	/* for avoiding double accounting */
-	rq->cmd_flags &= ~REQ_STARTED;
+	rq->rq_flags &= ~RQF_STARTED;
 
 	/*
 	 * After populating an empty queue, kick it to avoid stall.  Read
@@ -426,6 +424,13 @@ void blk_insert_flush(struct request *rq
 		rq->cmd_flags &= ~REQ_FUA;
 
 	/*
+	 * REQ_PREFLUSH|REQ_FUA implies REQ_SYNC, so if we clear any
+	 * of those flags, we have to set REQ_SYNC to avoid skewing
+	 * the request accounting.
+	 */
+	rq->cmd_flags |= REQ_SYNC;
+
+	/*
 	 * An empty flush handed down from a stacking driver may
 	 * translate into nothing if the underlying device does not
 	 * advertise a write-back cache.  In this case, simply
@@ -449,7 +454,7 @@ void blk_insert_flush(struct request *rq
 	if ((policy & REQ_FSEQ_DATA) &&
 	    !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
 		if (q->mq_ops) {
-			blk_mq_insert_request(rq, false, false, true);
+			blk_mq_insert_request(rq, false, true, false);
 		} else
 			list_add_tail(&rq->queuelist, &q->queue_head);
 		return;
@@ -461,7 +466,7 @@ void blk_insert_flush(struct request *rq
 	 */
 	memset(&rq->flush, 0, sizeof(rq->flush));
 	INIT_LIST_HEAD(&rq->flush.list);
-	rq->cmd_flags |= REQ_FLUSH_SEQ;
+	rq->rq_flags |= RQF_FLUSH_SEQ;
 	rq->flush.saved_end_io = rq->end_io; /* Usually NULL */
 	if (q->mq_ops) {
 		rq->end_io = mq_flush_data_end_io;
@@ -513,7 +518,7 @@ int blkdev_issue_flush(struct block_devi
 
 	bio = bio_alloc(gfp_mask, 0);
 	bio->bi_bdev = bdev;
-	bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH);
+	bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 
 	ret = submit_bio_wait(bio);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk.h linux-libre-4.10-rc8-gnu/block/blk.h
--- linux-libre-4.9-gnu/block/blk.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk.h	2017-02-12 16:03:20.000000000 -0500
@@ -111,6 +111,7 @@ void blk_account_io_done(struct request
 enum rq_atomic_flags {
 	REQ_ATOM_COMPLETE = 0,
 	REQ_ATOM_STARTED,
+	REQ_ATOM_POLL_SLEPT,
 };
 
 /*
@@ -130,7 +131,7 @@ static inline void blk_clear_rq_complete
 /*
  * Internal elevator interface
  */
-#define ELV_ON_HASH(rq) ((rq)->cmd_flags & REQ_HASHED)
+#define ELV_ON_HASH(rq) ((rq)->rq_flags & RQF_HASHED)
 
 void blk_insert_flush(struct request *rq);
 
@@ -247,7 +248,7 @@ extern int blk_update_nr_requests(struct
 static inline int blk_do_io_stat(struct request *rq)
 {
 	return rq->rq_disk &&
-	       (rq->cmd_flags & REQ_IO_STAT) &&
+	       (rq->rq_flags & RQF_IO_STAT) &&
 		(rq->cmd_type == REQ_TYPE_FS);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-lib.c linux-libre-4.10-rc8-gnu/block/blk-lib.c
--- linux-libre-4.9-gnu/block/blk-lib.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-lib.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@ int __blkdev_issue_discard(struct block_
 	struct request_queue *q = bdev_get_queue(bdev);
 	struct bio *bio = *biop;
 	unsigned int granularity;
-	enum req_op op;
+	unsigned int op;
 	int alignment;
 	sector_t bs_mask;
 
@@ -80,7 +80,7 @@ int __blkdev_issue_discard(struct block_
 			req_sects = end_sect - sector;
 		}
 
-		bio = next_bio(bio, 1, gfp_mask);
+		bio = next_bio(bio, 0, gfp_mask);
 		bio->bi_iter.bi_sector = sector;
 		bio->bi_bdev = bdev;
 		bio_set_op_attrs(bio, op, 0);
@@ -137,24 +137,24 @@ int blkdev_issue_discard(struct block_de
 EXPORT_SYMBOL(blkdev_issue_discard);
 
 /**
- * blkdev_issue_write_same - queue a write same operation
+ * __blkdev_issue_write_same - generate number of bios with same page
  * @bdev:	target blockdev
  * @sector:	start sector
  * @nr_sects:	number of sectors to write
  * @gfp_mask:	memory allocation flags (for bio_alloc)
  * @page:	page containing data to write
+ * @biop:	pointer to anchor bio
  *
  * Description:
- *    Issue a write same request for the sectors in question.
+ *  Generate and issue number of bios(REQ_OP_WRITE_SAME) with same page.
  */
-int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
-			    sector_t nr_sects, gfp_t gfp_mask,
-			    struct page *page)
+static int __blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
+		sector_t nr_sects, gfp_t gfp_mask, struct page *page,
+		struct bio **biop)
 {
 	struct request_queue *q = bdev_get_queue(bdev);
 	unsigned int max_write_same_sectors;
-	struct bio *bio = NULL;
-	int ret = 0;
+	struct bio *bio = *biop;
 	sector_t bs_mask;
 
 	if (!q)
@@ -164,6 +164,9 @@ int blkdev_issue_write_same(struct block
 	if ((sector | nr_sects) & bs_mask)
 		return -EINVAL;
 
+	if (!bdev_write_same(bdev))
+		return -EOPNOTSUPP;
+
 	/* Ensure that max_write_same_sectors doesn't overflow bi_size */
 	max_write_same_sectors = UINT_MAX >> 9;
 
@@ -185,32 +188,112 @@ int blkdev_issue_write_same(struct block
 			bio->bi_iter.bi_size = nr_sects << 9;
 			nr_sects = 0;
 		}
+		cond_resched();
 	}
 
-	if (bio) {
+	*biop = bio;
+	return 0;
+}
+
+/**
+ * blkdev_issue_write_same - queue a write same operation
+ * @bdev:	target blockdev
+ * @sector:	start sector
+ * @nr_sects:	number of sectors to write
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @page:	page containing data
+ *
+ * Description:
+ *    Issue a write same request for the sectors in question.
+ */
+int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
+				sector_t nr_sects, gfp_t gfp_mask,
+				struct page *page)
+{
+	struct bio *bio = NULL;
+	struct blk_plug plug;
+	int ret;
+
+	blk_start_plug(&plug);
+	ret = __blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask, page,
+			&bio);
+	if (ret == 0 && bio) {
 		ret = submit_bio_wait(bio);
 		bio_put(bio);
 	}
+	blk_finish_plug(&plug);
 	return ret;
 }
 EXPORT_SYMBOL(blkdev_issue_write_same);
 
 /**
- * blkdev_issue_zeroout - generate number of zero filed write bios
+ * __blkdev_issue_write_zeroes - generate number of bios with WRITE ZEROES
  * @bdev:	blockdev to issue
  * @sector:	start sector
  * @nr_sects:	number of sectors to write
  * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @biop:	pointer to anchor bio
  *
  * Description:
- *  Generate and issue number of bios with zerofiled pages.
+ *  Generate and issue number of bios(REQ_OP_WRITE_ZEROES) with zerofiled pages.
  */
+static int __blkdev_issue_write_zeroes(struct block_device *bdev,
+		sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
+		struct bio **biop)
+{
+	struct bio *bio = *biop;
+	unsigned int max_write_zeroes_sectors;
+	struct request_queue *q = bdev_get_queue(bdev);
 
-static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
-				  sector_t nr_sects, gfp_t gfp_mask)
+	if (!q)
+		return -ENXIO;
+
+	/* Ensure that max_write_zeroes_sectors doesn't overflow bi_size */
+	max_write_zeroes_sectors = bdev_write_zeroes_sectors(bdev);
+
+	if (max_write_zeroes_sectors == 0)
+		return -EOPNOTSUPP;
+
+	while (nr_sects) {
+		bio = next_bio(bio, 0, gfp_mask);
+		bio->bi_iter.bi_sector = sector;
+		bio->bi_bdev = bdev;
+		bio_set_op_attrs(bio, REQ_OP_WRITE_ZEROES, 0);
+
+		if (nr_sects > max_write_zeroes_sectors) {
+			bio->bi_iter.bi_size = max_write_zeroes_sectors << 9;
+			nr_sects -= max_write_zeroes_sectors;
+			sector += max_write_zeroes_sectors;
+		} else {
+			bio->bi_iter.bi_size = nr_sects << 9;
+			nr_sects = 0;
+		}
+		cond_resched();
+	}
+
+	*biop = bio;
+	return 0;
+}
+
+/**
+ * __blkdev_issue_zeroout - generate number of zero filed write bios
+ * @bdev:	blockdev to issue
+ * @sector:	start sector
+ * @nr_sects:	number of sectors to write
+ * @gfp_mask:	memory allocation flags (for bio_alloc)
+ * @biop:	pointer to anchor bio
+ * @discard:	discard flag
+ *
+ * Description:
+ *  Generate and issue number of bios with zerofiled pages.
+ */
+int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
+		sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,
+		bool discard)
 {
 	int ret;
-	struct bio *bio = NULL;
+	int bi_size = 0;
+	struct bio *bio = *biop;
 	unsigned int sz;
 	sector_t bs_mask;
 
@@ -218,6 +301,12 @@ static int __blkdev_issue_zeroout(struct
 	if ((sector | nr_sects) & bs_mask)
 		return -EINVAL;
 
+	ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
+			biop);
+	if (ret == 0 || (ret && ret != -EOPNOTSUPP))
+		goto out;
+
+	ret = 0;
 	while (nr_sects != 0) {
 		bio = next_bio(bio, min(nr_sects, (sector_t)BIO_MAX_PAGES),
 				gfp_mask);
@@ -227,21 +316,20 @@ static int __blkdev_issue_zeroout(struct
 
 		while (nr_sects != 0) {
 			sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects);
-			ret = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0);
-			nr_sects -= ret >> 9;
-			sector += ret >> 9;
-			if (ret < (sz << 9))
+			bi_size = bio_add_page(bio, ZERO_PAGE(0), sz << 9, 0);
+			nr_sects -= bi_size >> 9;
+			sector += bi_size >> 9;
+			if (bi_size < (sz << 9))
 				break;
 		}
+		cond_resched();
 	}
 
-	if (bio) {
-		ret = submit_bio_wait(bio);
-		bio_put(bio);
-		return ret;
-	}
-	return 0;
+	*biop = bio;
+out:
+	return ret;
 }
+EXPORT_SYMBOL(__blkdev_issue_zeroout);
 
 /**
  * blkdev_issue_zeroout - zero-fill a block range
@@ -258,26 +346,37 @@ static int __blkdev_issue_zeroout(struct
  *  the discard request fail, if the discard flag is not set, or if
  *  discard_zeroes_data is not supported, this function will resort to
  *  zeroing the blocks manually, thus provisioning (allocating,
- *  anchoring) them. If the block device supports the WRITE SAME command
- *  blkdev_issue_zeroout() will use it to optimize the process of
+ *  anchoring) them. If the block device supports WRITE ZEROES or WRITE SAME
+ *  command(s), blkdev_issue_zeroout() will use it to optimize the process of
  *  clearing the block range. Otherwise the zeroing will be performed
  *  using regular WRITE calls.
  */
-
 int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 			 sector_t nr_sects, gfp_t gfp_mask, bool discard)
 {
+	int ret;
+	struct bio *bio = NULL;
+	struct blk_plug plug;
+
 	if (discard) {
 		if (!blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask,
 				BLKDEV_DISCARD_ZERO))
 			return 0;
 	}
 
-	if (bdev_write_same(bdev) &&
-	    blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
-				    ZERO_PAGE(0)) == 0)
+	if (!blkdev_issue_write_same(bdev, sector, nr_sects, gfp_mask,
+			ZERO_PAGE(0)))
 		return 0;
 
-	return __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask);
+	blk_start_plug(&plug);
+	ret = __blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
+			&bio, discard);
+	if (ret == 0 && bio) {
+		ret = submit_bio_wait(bio);
+		bio_put(bio);
+	}
+	blk_finish_plug(&plug);
+
+	return ret;
 }
 EXPORT_SYMBOL(blkdev_issue_zeroout);
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-map.c linux-libre-4.10-rc8-gnu/block/blk-map.c
--- linux-libre-4.9-gnu/block/blk-map.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-map.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,8 @@
 int blk_rq_append_bio(struct request *rq, struct bio *bio)
 {
 	if (!rq->bio) {
+		rq->cmd_flags &= REQ_OP_MASK;
+		rq->cmd_flags |= (bio->bi_opf & REQ_OP_MASK);
 		blk_rq_bio_prep(rq->q, rq, bio);
 	} else {
 		if (!ll_back_merge_fn(rq->q, rq, bio))
@@ -138,7 +140,7 @@ int blk_rq_map_user_iov(struct request_q
 	} while (iov_iter_count(&i));
 
 	if (!bio_flagged(bio, BIO_USER_MAPPED))
-		rq->cmd_flags |= REQ_COPY_USER;
+		rq->rq_flags |= RQF_COPY_USER;
 	return 0;
 
 unmap_rq:
@@ -236,7 +238,7 @@ int blk_rq_map_kern(struct request_queue
 		bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
 
 	if (do_copy)
-		rq->cmd_flags |= REQ_COPY_USER;
+		rq->rq_flags |= RQF_COPY_USER;
 
 	ret = blk_rq_append_bio(rq, bio);
 	if (unlikely(ret)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-merge.c linux-libre-4.10-rc8-gnu/block/blk-merge.c
--- linux-libre-4.9-gnu/block/blk-merge.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-merge.c	2017-02-12 16:03:20.000000000 -0500
@@ -199,6 +199,10 @@ void blk_queue_split(struct request_queu
 	case REQ_OP_SECURE_ERASE:
 		split = blk_bio_discard_split(q, *bio, bs, &nsegs);
 		break;
+	case REQ_OP_WRITE_ZEROES:
+		split = NULL;
+		nsegs = (*bio)->bi_phys_segments;
+		break;
 	case REQ_OP_WRITE_SAME:
 		split = blk_bio_write_same_split(q, *bio, bs, &nsegs);
 		break;
@@ -237,15 +241,14 @@ static unsigned int __blk_recalc_rq_segm
 	if (!bio)
 		return 0;
 
-	/*
-	 * This should probably be returning 0, but blk_add_request_payload()
-	 * (Christoph!!!!)
-	 */
-	if (bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_SECURE_ERASE)
-		return 1;
-
-	if (bio_op(bio) == REQ_OP_WRITE_SAME)
+	switch (bio_op(bio)) {
+	case REQ_OP_DISCARD:
+	case REQ_OP_SECURE_ERASE:
+	case REQ_OP_WRITE_ZEROES:
+		return 0;
+	case REQ_OP_WRITE_SAME:
 		return 1;
+	}
 
 	fbio = bio;
 	cluster = blk_queue_cluster(q);
@@ -402,38 +405,21 @@ new_segment:
 	*bvprv = *bvec;
 }
 
+static inline int __blk_bvec_map_sg(struct request_queue *q, struct bio_vec bv,
+		struct scatterlist *sglist, struct scatterlist **sg)
+{
+	*sg = sglist;
+	sg_set_page(*sg, bv.bv_page, bv.bv_len, bv.bv_offset);
+	return 1;
+}
+
 static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio,
 			     struct scatterlist *sglist,
 			     struct scatterlist **sg)
 {
 	struct bio_vec bvec, bvprv = { NULL };
 	struct bvec_iter iter;
-	int nsegs, cluster;
-
-	nsegs = 0;
-	cluster = blk_queue_cluster(q);
-
-	switch (bio_op(bio)) {
-	case REQ_OP_DISCARD:
-	case REQ_OP_SECURE_ERASE:
-		/*
-		 * This is a hack - drivers should be neither modifying the
-		 * biovec, nor relying on bi_vcnt - but because of
-		 * blk_add_request_payload(), a discard bio may or may not have
-		 * a payload we need to set up here (thank you Christoph) and
-		 * bi_vcnt is really the only way of telling if we need to.
-		 */
-		if (!bio->bi_vcnt)
-			return 0;
-		/* Fall through */
-	case REQ_OP_WRITE_SAME:
-		*sg = sglist;
-		bvec = bio_iovec(bio);
-		sg_set_page(*sg, bvec.bv_page, bvec.bv_len, bvec.bv_offset);
-		return 1;
-	default:
-		break;
-	}
+	int cluster = blk_queue_cluster(q), nsegs = 0;
 
 	for_each_bio(bio)
 		bio_for_each_segment(bvec, bio, iter)
@@ -453,10 +439,14 @@ int blk_rq_map_sg(struct request_queue *
 	struct scatterlist *sg = NULL;
 	int nsegs = 0;
 
-	if (rq->bio)
+	if (rq->rq_flags & RQF_SPECIAL_PAYLOAD)
+		nsegs = __blk_bvec_map_sg(q, rq->special_vec, sglist, &sg);
+	else if (rq->bio && bio_op(rq->bio) == REQ_OP_WRITE_SAME)
+		nsegs = __blk_bvec_map_sg(q, bio_iovec(rq->bio), sglist, &sg);
+	else if (rq->bio)
 		nsegs = __blk_bios_map_sg(q, rq->bio, sglist, &sg);
 
-	if (unlikely(rq->cmd_flags & REQ_COPY_USER) &&
+	if (unlikely(rq->rq_flags & RQF_COPY_USER) &&
 	    (blk_rq_bytes(rq) & q->dma_pad_mask)) {
 		unsigned int pad_len =
 			(q->dma_pad_mask & ~blk_rq_bytes(rq)) + 1;
@@ -486,12 +476,19 @@ int blk_rq_map_sg(struct request_queue *
 	 * Something must have been wrong if the figured number of
 	 * segment is bigger than number of req's physical segments
 	 */
-	WARN_ON(nsegs > rq->nr_phys_segments);
+	WARN_ON(nsegs > blk_rq_nr_phys_segments(rq));
 
 	return nsegs;
 }
 EXPORT_SYMBOL(blk_rq_map_sg);
 
+static void req_set_nomerge(struct request_queue *q, struct request *req)
+{
+	req->cmd_flags |= REQ_NOMERGE;
+	if (req == q->last_merge)
+		q->last_merge = NULL;
+}
+
 static inline int ll_new_hw_segment(struct request_queue *q,
 				    struct request *req,
 				    struct bio *bio)
@@ -512,9 +509,7 @@ static inline int ll_new_hw_segment(stru
 	return 1;
 
 no_merge:
-	req->cmd_flags |= REQ_NOMERGE;
-	if (req == q->last_merge)
-		q->last_merge = NULL;
+	req_set_nomerge(q, req);
 	return 0;
 }
 
@@ -528,9 +523,7 @@ int ll_back_merge_fn(struct request_queu
 		return 0;
 	if (blk_rq_sectors(req) + bio_sectors(bio) >
 	    blk_rq_get_max_sectors(req, blk_rq_pos(req))) {
-		req->cmd_flags |= REQ_NOMERGE;
-		if (req == q->last_merge)
-			q->last_merge = NULL;
+		req_set_nomerge(q, req);
 		return 0;
 	}
 	if (!bio_flagged(req->biotail, BIO_SEG_VALID))
@@ -552,9 +545,7 @@ int ll_front_merge_fn(struct request_que
 		return 0;
 	if (blk_rq_sectors(req) + bio_sectors(bio) >
 	    blk_rq_get_max_sectors(req, bio->bi_iter.bi_sector)) {
-		req->cmd_flags |= REQ_NOMERGE;
-		if (req == q->last_merge)
-			q->last_merge = NULL;
+		req_set_nomerge(q, req);
 		return 0;
 	}
 	if (!bio_flagged(bio, BIO_SEG_VALID))
@@ -634,7 +625,7 @@ void blk_rq_set_mixed_merge(struct reque
 	unsigned int ff = rq->cmd_flags & REQ_FAILFAST_MASK;
 	struct bio *bio;
 
-	if (rq->cmd_flags & REQ_MIXED_MERGE)
+	if (rq->rq_flags & RQF_MIXED_MERGE)
 		return;
 
 	/*
@@ -647,7 +638,7 @@ void blk_rq_set_mixed_merge(struct reque
 			     (bio->bi_opf & REQ_FAILFAST_MASK) != ff);
 		bio->bi_opf |= ff;
 	}
-	rq->cmd_flags |= REQ_MIXED_MERGE;
+	rq->rq_flags |= RQF_MIXED_MERGE;
 }
 
 static void blk_account_io_merge(struct request *req)
@@ -709,7 +700,7 @@ static int attempt_merge(struct request_
 	 * makes sure that all involved bios have mixable attributes
 	 * set properly.
 	 */
-	if ((req->cmd_flags | next->cmd_flags) & REQ_MIXED_MERGE ||
+	if (((req->rq_flags | next->rq_flags) & RQF_MIXED_MERGE) ||
 	    (req->cmd_flags & REQ_FAILFAST_MASK) !=
 	    (next->cmd_flags & REQ_FAILFAST_MASK)) {
 		blk_rq_set_mixed_merge(req);
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-mq.c linux-libre-4.10-rc8-gnu/block/blk-mq.c
--- linux-libre-4.9-gnu/block/blk-mq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-mq.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,8 @@
 #include "blk.h"
 #include "blk-mq.h"
 #include "blk-mq-tag.h"
+#include "blk-stat.h"
+#include "blk-wbt.h"
 
 static DEFINE_MUTEX(all_q_mutex);
 static LIST_HEAD(all_q_list);
@@ -115,6 +117,33 @@ void blk_mq_unfreeze_queue(struct reques
 }
 EXPORT_SYMBOL_GPL(blk_mq_unfreeze_queue);
 
+/**
+ * blk_mq_quiesce_queue() - wait until all ongoing queue_rq calls have finished
+ * @q: request queue.
+ *
+ * Note: this function does not prevent that the struct request end_io()
+ * callback function is invoked. Additionally, it is not prevented that
+ * new queue_rq() calls occur unless the queue has been stopped first.
+ */
+void blk_mq_quiesce_queue(struct request_queue *q)
+{
+	struct blk_mq_hw_ctx *hctx;
+	unsigned int i;
+	bool rcu = false;
+
+	blk_mq_stop_hw_queues(q);
+
+	queue_for_each_hw_ctx(q, hctx, i) {
+		if (hctx->flags & BLK_MQ_F_BLOCKING)
+			synchronize_srcu(&hctx->queue_rq_srcu);
+		else
+			rcu = true;
+	}
+	if (rcu)
+		synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);
+
 void blk_mq_wake_waiters(struct request_queue *q)
 {
 	struct blk_mq_hw_ctx *hctx;
@@ -139,17 +168,15 @@ bool blk_mq_can_queue(struct blk_mq_hw_c
 EXPORT_SYMBOL(blk_mq_can_queue);
 
 static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx,
-			       struct request *rq, int op,
-			       unsigned int op_flags)
+			       struct request *rq, unsigned int op)
 {
-	if (blk_queue_io_stat(q))
-		op_flags |= REQ_IO_STAT;
-
 	INIT_LIST_HEAD(&rq->queuelist);
 	/* csd/requeue_work/fifo_time is initialized before use */
 	rq->q = q;
 	rq->mq_ctx = ctx;
-	req_set_op_attrs(rq, op, op_flags);
+	rq->cmd_flags = op;
+	if (blk_queue_io_stat(q))
+		rq->rq_flags |= RQF_IO_STAT;
 	/* do not touch atomic flags, it needs atomic ops against the timer */
 	rq->cpu = -1;
 	INIT_HLIST_NODE(&rq->hash);
@@ -184,11 +211,11 @@ static void blk_mq_rq_ctx_init(struct re
 	rq->end_io_data = NULL;
 	rq->next_rq = NULL;
 
-	ctx->rq_dispatched[rw_is_sync(op, op_flags)]++;
+	ctx->rq_dispatched[op_is_sync(op)]++;
 }
 
 static struct request *
-__blk_mq_alloc_request(struct blk_mq_alloc_data *data, int op, int op_flags)
+__blk_mq_alloc_request(struct blk_mq_alloc_data *data, unsigned int op)
 {
 	struct request *rq;
 	unsigned int tag;
@@ -198,12 +225,12 @@ __blk_mq_alloc_request(struct blk_mq_all
 		rq = data->hctx->tags->rqs[tag];
 
 		if (blk_mq_tag_busy(data->hctx)) {
-			rq->cmd_flags = REQ_MQ_INFLIGHT;
+			rq->rq_flags = RQF_MQ_INFLIGHT;
 			atomic_inc(&data->hctx->nr_active);
 		}
 
 		rq->tag = tag;
-		blk_mq_rq_ctx_init(data->q, data->ctx, rq, op, op_flags);
+		blk_mq_rq_ctx_init(data->q, data->ctx, rq, op);
 		return rq;
 	}
 
@@ -226,7 +253,7 @@ struct request *blk_mq_alloc_request(str
 	ctx = blk_mq_get_ctx(q);
 	hctx = blk_mq_map_queue(q, ctx->cpu);
 	blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx);
-	rq = __blk_mq_alloc_request(&alloc_data, rw, 0);
+	rq = __blk_mq_alloc_request(&alloc_data, rw);
 	blk_mq_put_ctx(ctx);
 
 	if (!rq) {
@@ -278,7 +305,7 @@ struct request *blk_mq_alloc_request_hct
 	ctx = __blk_mq_get_ctx(q, cpumask_first(hctx->cpumask));
 
 	blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx);
-	rq = __blk_mq_alloc_request(&alloc_data, rw, 0);
+	rq = __blk_mq_alloc_request(&alloc_data, rw);
 	if (!rq) {
 		ret = -EWOULDBLOCK;
 		goto out_queue_exit;
@@ -298,11 +325,14 @@ static void __blk_mq_free_request(struct
 	const int tag = rq->tag;
 	struct request_queue *q = rq->q;
 
-	if (rq->cmd_flags & REQ_MQ_INFLIGHT)
+	if (rq->rq_flags & RQF_MQ_INFLIGHT)
 		atomic_dec(&hctx->nr_active);
-	rq->cmd_flags = 0;
+
+	wbt_done(q->rq_wb, &rq->issue_stat);
+	rq->rq_flags = 0;
 
 	clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags);
+	clear_bit(REQ_ATOM_POLL_SLEPT, &rq->atomic_flags);
 	blk_mq_put_tag(hctx, ctx, tag);
 	blk_queue_exit(q);
 }
@@ -328,6 +358,7 @@ inline void __blk_mq_end_request(struct
 	blk_account_io_done(rq);
 
 	if (rq->end_io) {
+		wbt_done(rq->q->rq_wb, &rq->issue_stat);
 		rq->end_io(rq, error);
 	} else {
 		if (unlikely(blk_bidi_rq(rq)))
@@ -378,10 +409,27 @@ static void blk_mq_ipi_complete_request(
 	put_cpu();
 }
 
+static void blk_mq_stat_add(struct request *rq)
+{
+	if (rq->rq_flags & RQF_STATS) {
+		/*
+		 * We could rq->mq_ctx here, but there's less of a risk
+		 * of races if we have the completion event add the stats
+		 * to the local software queue.
+		 */
+		struct blk_mq_ctx *ctx;
+
+		ctx = __blk_mq_get_ctx(rq->q, raw_smp_processor_id());
+		blk_stat_add(&ctx->stat[rq_data_dir(rq)], rq);
+	}
+}
+
 static void __blk_mq_complete_request(struct request *rq)
 {
 	struct request_queue *q = rq->q;
 
+	blk_mq_stat_add(rq);
+
 	if (!q->softirq_done_fn)
 		blk_mq_end_request(rq, rq->errors);
 	else
@@ -425,6 +473,12 @@ void blk_mq_start_request(struct request
 	if (unlikely(blk_bidi_rq(rq)))
 		rq->next_rq->resid_len = blk_rq_bytes(rq->next_rq);
 
+	if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
+		blk_stat_set_issue_time(&rq->issue_stat);
+		rq->rq_flags |= RQF_STATS;
+		wbt_issue(q->rq_wb, &rq->issue_stat);
+	}
+
 	blk_add_timer(rq);
 
 	/*
@@ -460,6 +514,7 @@ static void __blk_mq_requeue_request(str
 	struct request_queue *q = rq->q;
 
 	trace_block_rq_requeue(q, rq);
+	wbt_requeue(q->rq_wb, &rq->issue_stat);
 
 	if (test_and_clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags)) {
 		if (q->dma_drain_size && blk_rq_bytes(rq))
@@ -467,12 +522,12 @@ static void __blk_mq_requeue_request(str
 	}
 }
 
-void blk_mq_requeue_request(struct request *rq)
+void blk_mq_requeue_request(struct request *rq, bool kick_requeue_list)
 {
 	__blk_mq_requeue_request(rq);
 
 	BUG_ON(blk_queued_rq(rq));
-	blk_mq_add_to_requeue_list(rq, true);
+	blk_mq_add_to_requeue_list(rq, true, kick_requeue_list);
 }
 EXPORT_SYMBOL(blk_mq_requeue_request);
 
@@ -489,10 +544,10 @@ static void blk_mq_requeue_work(struct w
 	spin_unlock_irqrestore(&q->requeue_lock, flags);
 
 	list_for_each_entry_safe(rq, next, &rq_list, queuelist) {
-		if (!(rq->cmd_flags & REQ_SOFTBARRIER))
+		if (!(rq->rq_flags & RQF_SOFTBARRIER))
 			continue;
 
-		rq->cmd_flags &= ~REQ_SOFTBARRIER;
+		rq->rq_flags &= ~RQF_SOFTBARRIER;
 		list_del_init(&rq->queuelist);
 		blk_mq_insert_request(rq, true, false, false);
 	}
@@ -503,14 +558,11 @@ static void blk_mq_requeue_work(struct w
 		blk_mq_insert_request(rq, false, false, false);
 	}
 
-	/*
-	 * Use the start variant of queue running here, so that running
-	 * the requeue work will kick stopped queues.
-	 */
-	blk_mq_start_hw_queues(q);
+	blk_mq_run_hw_queues(q, false);
 }
 
-void blk_mq_add_to_requeue_list(struct request *rq, bool at_head)
+void blk_mq_add_to_requeue_list(struct request *rq, bool at_head,
+				bool kick_requeue_list)
 {
 	struct request_queue *q = rq->q;
 	unsigned long flags;
@@ -519,24 +571,21 @@ void blk_mq_add_to_requeue_list(struct r
 	 * We abuse this flag that is otherwise used by the I/O scheduler to
 	 * request head insertation from the workqueue.
 	 */
-	BUG_ON(rq->cmd_flags & REQ_SOFTBARRIER);
+	BUG_ON(rq->rq_flags & RQF_SOFTBARRIER);
 
 	spin_lock_irqsave(&q->requeue_lock, flags);
 	if (at_head) {
-		rq->cmd_flags |= REQ_SOFTBARRIER;
+		rq->rq_flags |= RQF_SOFTBARRIER;
 		list_add(&rq->queuelist, &q->requeue_list);
 	} else {
 		list_add_tail(&rq->queuelist, &q->requeue_list);
 	}
 	spin_unlock_irqrestore(&q->requeue_lock, flags);
-}
-EXPORT_SYMBOL(blk_mq_add_to_requeue_list);
 
-void blk_mq_cancel_requeue_work(struct request_queue *q)
-{
-	cancel_delayed_work_sync(&q->requeue_work);
+	if (kick_requeue_list)
+		blk_mq_kick_requeue_list(q);
 }
-EXPORT_SYMBOL_GPL(blk_mq_cancel_requeue_work);
+EXPORT_SYMBOL(blk_mq_add_to_requeue_list);
 
 void blk_mq_kick_requeue_list(struct request_queue *q)
 {
@@ -772,44 +821,13 @@ static inline unsigned int queued_to_ind
 	return min(BLK_MQ_MAX_DISPATCH_ORDER - 1, ilog2(queued) + 1);
 }
 
-/*
- * Run this hardware queue, pulling any software queues mapped to it in.
- * Note that this function currently has various problems around ordering
- * of IO. In particular, we'd like FIFO behaviour on handling existing
- * items on the hctx->dispatch list. Ignore that for now.
- */
-static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
+bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *hctx, struct list_head *list)
 {
 	struct request_queue *q = hctx->queue;
 	struct request *rq;
-	LIST_HEAD(rq_list);
 	LIST_HEAD(driver_list);
 	struct list_head *dptr;
-	int queued;
-
-	if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
-		return;
-
-	WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) &&
-		cpu_online(hctx->next_cpu));
-
-	hctx->run++;
-
-	/*
-	 * Touch any software queue that has pending entries.
-	 */
-	flush_busy_ctxs(hctx, &rq_list);
-
-	/*
-	 * If we have previous entries on our dispatch list, grab them
-	 * and stuff them at the front for more fair dispatch.
-	 */
-	if (!list_empty_careful(&hctx->dispatch)) {
-		spin_lock(&hctx->lock);
-		if (!list_empty(&hctx->dispatch))
-			list_splice_init(&hctx->dispatch, &rq_list);
-		spin_unlock(&hctx->lock);
-	}
+	int queued, ret = BLK_MQ_RQ_QUEUE_OK;
 
 	/*
 	 * Start off with dptr being NULL, so we start the first request
@@ -821,16 +839,15 @@ static void __blk_mq_run_hw_queue(struct
 	 * Now process all the entries, sending them to the driver.
 	 */
 	queued = 0;
-	while (!list_empty(&rq_list)) {
+	while (!list_empty(list)) {
 		struct blk_mq_queue_data bd;
-		int ret;
 
-		rq = list_first_entry(&rq_list, struct request, queuelist);
+		rq = list_first_entry(list, struct request, queuelist);
 		list_del_init(&rq->queuelist);
 
 		bd.rq = rq;
 		bd.list = dptr;
-		bd.last = list_empty(&rq_list);
+		bd.last = list_empty(list);
 
 		ret = q->mq_ops->queue_rq(hctx, &bd);
 		switch (ret) {
@@ -838,7 +855,7 @@ static void __blk_mq_run_hw_queue(struct
 			queued++;
 			break;
 		case BLK_MQ_RQ_QUEUE_BUSY:
-			list_add(&rq->queuelist, &rq_list);
+			list_add(&rq->queuelist, list);
 			__blk_mq_requeue_request(rq);
 			break;
 		default:
@@ -856,7 +873,7 @@ static void __blk_mq_run_hw_queue(struct
 		 * We've done the first request. If we have more than 1
 		 * left in the list, set dptr to defer issue.
 		 */
-		if (!dptr && rq_list.next != rq_list.prev)
+		if (!dptr && list->next != list->prev)
 			dptr = &driver_list;
 	}
 
@@ -866,10 +883,11 @@ static void __blk_mq_run_hw_queue(struct
 	 * Any items that need requeuing? Stuff them into hctx->dispatch,
 	 * that is where we will continue on next queue run.
 	 */
-	if (!list_empty(&rq_list)) {
+	if (!list_empty(list)) {
 		spin_lock(&hctx->lock);
-		list_splice(&rq_list, &hctx->dispatch);
+		list_splice(list, &hctx->dispatch);
 		spin_unlock(&hctx->lock);
+
 		/*
 		 * the queue is expected stopped with BLK_MQ_RQ_QUEUE_BUSY, but
 		 * it's possible the queue is stopped and restarted again
@@ -881,6 +899,60 @@ static void __blk_mq_run_hw_queue(struct
 		 **/
 		blk_mq_run_hw_queue(hctx, true);
 	}
+
+	return ret != BLK_MQ_RQ_QUEUE_BUSY;
+}
+
+/*
+ * Run this hardware queue, pulling any software queues mapped to it in.
+ * Note that this function currently has various problems around ordering
+ * of IO. In particular, we'd like FIFO behaviour on handling existing
+ * items on the hctx->dispatch list. Ignore that for now.
+ */
+static void blk_mq_process_rq_list(struct blk_mq_hw_ctx *hctx)
+{
+	LIST_HEAD(rq_list);
+
+	if (unlikely(blk_mq_hctx_stopped(hctx)))
+		return;
+
+	hctx->run++;
+
+	/*
+	 * Touch any software queue that has pending entries.
+	 */
+	flush_busy_ctxs(hctx, &rq_list);
+
+	/*
+	 * If we have previous entries on our dispatch list, grab them
+	 * and stuff them at the front for more fair dispatch.
+	 */
+	if (!list_empty_careful(&hctx->dispatch)) {
+		spin_lock(&hctx->lock);
+		if (!list_empty(&hctx->dispatch))
+			list_splice_init(&hctx->dispatch, &rq_list);
+		spin_unlock(&hctx->lock);
+	}
+
+	blk_mq_dispatch_rq_list(hctx, &rq_list);
+}
+
+static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx)
+{
+	int srcu_idx;
+
+	WARN_ON(!cpumask_test_cpu(raw_smp_processor_id(), hctx->cpumask) &&
+		cpu_online(hctx->next_cpu));
+
+	if (!(hctx->flags & BLK_MQ_F_BLOCKING)) {
+		rcu_read_lock();
+		blk_mq_process_rq_list(hctx);
+		rcu_read_unlock();
+	} else {
+		srcu_idx = srcu_read_lock(&hctx->queue_rq_srcu);
+		blk_mq_process_rq_list(hctx);
+		srcu_read_unlock(&hctx->queue_rq_srcu, srcu_idx);
+	}
 }
 
 /*
@@ -895,7 +967,7 @@ static int blk_mq_hctx_next_cpu(struct b
 		return WORK_CPU_UNBOUND;
 
 	if (--hctx->next_cpu_batch <= 0) {
-		int cpu = hctx->next_cpu, next_cpu;
+		int next_cpu;
 
 		next_cpu = cpumask_next(hctx->next_cpu, hctx->cpumask);
 		if (next_cpu >= nr_cpu_ids)
@@ -903,8 +975,6 @@ static int blk_mq_hctx_next_cpu(struct b
 
 		hctx->next_cpu = next_cpu;
 		hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH;
-
-		return cpu;
 	}
 
 	return hctx->next_cpu;
@@ -912,8 +982,8 @@ static int blk_mq_hctx_next_cpu(struct b
 
 void blk_mq_run_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
 {
-	if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state) ||
-	    !blk_mq_hw_queue_mapped(hctx)))
+	if (unlikely(blk_mq_hctx_stopped(hctx) ||
+		     !blk_mq_hw_queue_mapped(hctx)))
 		return;
 
 	if (!async && !(hctx->flags & BLK_MQ_F_BLOCKING)) {
@@ -938,7 +1008,7 @@ void blk_mq_run_hw_queues(struct request
 	queue_for_each_hw_ctx(q, hctx, i) {
 		if ((!blk_mq_hctx_has_pending(hctx) &&
 		    list_empty_careful(&hctx->dispatch)) ||
-		    test_bit(BLK_MQ_S_STOPPED, &hctx->state))
+		    blk_mq_hctx_stopped(hctx))
 			continue;
 
 		blk_mq_run_hw_queue(hctx, async);
@@ -946,6 +1016,26 @@ void blk_mq_run_hw_queues(struct request
 }
 EXPORT_SYMBOL(blk_mq_run_hw_queues);
 
+/**
+ * blk_mq_queue_stopped() - check whether one or more hctxs have been stopped
+ * @q: request queue.
+ *
+ * The caller is responsible for serializing this function against
+ * blk_mq_{start,stop}_hw_queue().
+ */
+bool blk_mq_queue_stopped(struct request_queue *q)
+{
+	struct blk_mq_hw_ctx *hctx;
+	int i;
+
+	queue_for_each_hw_ctx(q, hctx, i)
+		if (blk_mq_hctx_stopped(hctx))
+			return true;
+
+	return false;
+}
+EXPORT_SYMBOL(blk_mq_queue_stopped);
+
 void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx)
 {
 	cancel_work(&hctx->run_work);
@@ -982,18 +1072,23 @@ void blk_mq_start_hw_queues(struct reque
 }
 EXPORT_SYMBOL(blk_mq_start_hw_queues);
 
+void blk_mq_start_stopped_hw_queue(struct blk_mq_hw_ctx *hctx, bool async)
+{
+	if (!blk_mq_hctx_stopped(hctx))
+		return;
+
+	clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
+	blk_mq_run_hw_queue(hctx, async);
+}
+EXPORT_SYMBOL_GPL(blk_mq_start_stopped_hw_queue);
+
 void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async)
 {
 	struct blk_mq_hw_ctx *hctx;
 	int i;
 
-	queue_for_each_hw_ctx(q, hctx, i) {
-		if (!test_bit(BLK_MQ_S_STOPPED, &hctx->state))
-			continue;
-
-		clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
-		blk_mq_run_hw_queue(hctx, async);
-	}
+	queue_for_each_hw_ctx(q, hctx, i)
+		blk_mq_start_stopped_hw_queue(hctx, async);
 }
 EXPORT_SYMBOL(blk_mq_start_stopped_hw_queues);
 
@@ -1155,7 +1250,7 @@ static void blk_mq_bio_to_request(struct
 {
 	init_request_from_bio(rq, bio);
 
-	blk_account_io_start(rq, 1);
+	blk_account_io_start(rq, true);
 }
 
 static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx)
@@ -1190,40 +1285,27 @@ insert_rq:
 	}
 }
 
-struct blk_map_ctx {
-	struct blk_mq_hw_ctx *hctx;
-	struct blk_mq_ctx *ctx;
-};
-
 static struct request *blk_mq_map_request(struct request_queue *q,
 					  struct bio *bio,
-					  struct blk_map_ctx *data)
+					  struct blk_mq_alloc_data *data)
 {
 	struct blk_mq_hw_ctx *hctx;
 	struct blk_mq_ctx *ctx;
 	struct request *rq;
-	int op = bio_data_dir(bio);
-	int op_flags = 0;
-	struct blk_mq_alloc_data alloc_data;
 
 	blk_queue_enter_live(q);
 	ctx = blk_mq_get_ctx(q);
 	hctx = blk_mq_map_queue(q, ctx->cpu);
 
-	if (rw_is_sync(bio_op(bio), bio->bi_opf))
-		op_flags |= REQ_SYNC;
-
-	trace_block_getrq(q, bio, op);
-	blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx);
-	rq = __blk_mq_alloc_request(&alloc_data, op, op_flags);
+	trace_block_getrq(q, bio, bio->bi_opf);
+	blk_mq_set_alloc_data(data, q, 0, ctx, hctx);
+	rq = __blk_mq_alloc_request(data, bio->bi_opf);
 
-	data->hctx = alloc_data.hctx;
-	data->ctx = alloc_data.ctx;
 	data->hctx->queued++;
 	return rq;
 }
 
-static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie)
+static void blk_mq_try_issue_directly(struct request *rq, blk_qc_t *cookie)
 {
 	int ret;
 	struct request_queue *q = rq->q;
@@ -1235,6 +1317,9 @@ static int blk_mq_direct_issue_request(s
 	};
 	blk_qc_t new_cookie = blk_tag_to_qc_t(rq->tag, hctx->queue_num);
 
+	if (blk_mq_hctx_stopped(hctx))
+		goto insert;
+
 	/*
 	 * For OK queue, we are done. For error, kill it. Any other
 	 * error (busy), just add it to our list as we previously
@@ -1243,7 +1328,7 @@ static int blk_mq_direct_issue_request(s
 	ret = q->mq_ops->queue_rq(hctx, &bd);
 	if (ret == BLK_MQ_RQ_QUEUE_OK) {
 		*cookie = new_cookie;
-		return 0;
+		return;
 	}
 
 	__blk_mq_requeue_request(rq);
@@ -1252,10 +1337,11 @@ static int blk_mq_direct_issue_request(s
 		*cookie = BLK_QC_T_NONE;
 		rq->errors = -EIO;
 		blk_mq_end_request(rq, rq->errors);
-		return 0;
+		return;
 	}
 
-	return -1;
+insert:
+	blk_mq_insert_request(rq, false, true, true);
 }
 
 /*
@@ -1265,14 +1351,15 @@ static int blk_mq_direct_issue_request(s
  */
 static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 {
-	const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf);
+	const int is_sync = op_is_sync(bio->bi_opf);
 	const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
-	struct blk_map_ctx data;
+	struct blk_mq_alloc_data data;
 	struct request *rq;
-	unsigned int request_count = 0;
+	unsigned int request_count = 0, srcu_idx;
 	struct blk_plug *plug;
 	struct request *same_queue_rq = NULL;
 	blk_qc_t cookie;
+	unsigned int wb_acct;
 
 	blk_queue_bounce(q, &bio);
 
@@ -1287,9 +1374,15 @@ static blk_qc_t blk_mq_make_request(stru
 	    blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
 		return BLK_QC_T_NONE;
 
+	wb_acct = wbt_wait(q->rq_wb, bio, NULL);
+
 	rq = blk_mq_map_request(q, bio, &data);
-	if (unlikely(!rq))
+	if (unlikely(!rq)) {
+		__wbt_done(q->rq_wb, wb_acct);
 		return BLK_QC_T_NONE;
+	}
+
+	wbt_track(&rq->issue_stat, wb_acct);
 
 	cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num);
 
@@ -1312,7 +1405,7 @@ static blk_qc_t blk_mq_make_request(stru
 		blk_mq_bio_to_request(rq, bio);
 
 		/*
-		 * We do limited pluging. If the bio can be merged, do that.
+		 * We do limited plugging. If the bio can be merged, do that.
 		 * Otherwise the existing request in the plug list will be
 		 * issued. So the plug list will have one request at most
 		 */
@@ -1332,9 +1425,16 @@ static blk_qc_t blk_mq_make_request(stru
 		blk_mq_put_ctx(data.ctx);
 		if (!old_rq)
 			goto done;
-		if (!blk_mq_direct_issue_request(old_rq, &cookie))
-			goto done;
-		blk_mq_insert_request(old_rq, false, true, true);
+
+		if (!(data.hctx->flags & BLK_MQ_F_BLOCKING)) {
+			rcu_read_lock();
+			blk_mq_try_issue_directly(old_rq, &cookie);
+			rcu_read_unlock();
+		} else {
+			srcu_idx = srcu_read_lock(&data.hctx->queue_rq_srcu);
+			blk_mq_try_issue_directly(old_rq, &cookie);
+			srcu_read_unlock(&data.hctx->queue_rq_srcu, srcu_idx);
+		}
 		goto done;
 	}
 
@@ -1359,13 +1459,14 @@ done:
  */
 static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
 {
-	const int is_sync = rw_is_sync(bio_op(bio), bio->bi_opf);
+	const int is_sync = op_is_sync(bio->bi_opf);
 	const int is_flush_fua = bio->bi_opf & (REQ_PREFLUSH | REQ_FUA);
 	struct blk_plug *plug;
 	unsigned int request_count = 0;
-	struct blk_map_ctx data;
+	struct blk_mq_alloc_data data;
 	struct request *rq;
 	blk_qc_t cookie;
+	unsigned int wb_acct;
 
 	blk_queue_bounce(q, &bio);
 
@@ -1382,9 +1483,15 @@ static blk_qc_t blk_sq_make_request(stru
 	} else
 		request_count = blk_plug_queued_count(q);
 
+	wb_acct = wbt_wait(q->rq_wb, bio, NULL);
+
 	rq = blk_mq_map_request(q, bio, &data);
-	if (unlikely(!rq))
+	if (unlikely(!rq)) {
+		__wbt_done(q->rq_wb, wb_acct);
 		return BLK_QC_T_NONE;
+	}
+
+	wbt_track(&rq->issue_stat, wb_acct);
 
 	cookie = blk_tag_to_qc_t(rq->tag, data.hctx->queue_num);
 
@@ -1401,13 +1508,25 @@ static blk_qc_t blk_sq_make_request(stru
 	 */
 	plug = current->plug;
 	if (plug) {
+		struct request *last = NULL;
+
 		blk_mq_bio_to_request(rq, bio);
+
+		/*
+		 * @request_count may become stale because of schedule
+		 * out, so check the list again.
+		 */
+		if (list_empty(&plug->mq_list))
+			request_count = 0;
 		if (!request_count)
 			trace_block_plug(q);
+		else
+			last = list_entry_rq(plug->mq_list.prev);
 
 		blk_mq_put_ctx(data.ctx);
 
-		if (request_count >= BLK_MAX_REQUEST_COUNT) {
+		if (request_count >= BLK_MAX_REQUEST_COUNT || (last &&
+		    blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE)) {
 			blk_flush_plug_list(plug, false);
 			trace_block_plug(q);
 		}
@@ -1485,7 +1604,7 @@ static struct blk_mq_tags *blk_mq_init_r
 	INIT_LIST_HEAD(&tags->page_list);
 
 	tags->rqs = kzalloc_node(set->queue_depth * sizeof(struct request *),
-				 GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+				 GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
 				 set->numa_node);
 	if (!tags->rqs) {
 		blk_mq_free_tags(tags);
@@ -1511,7 +1630,7 @@ static struct blk_mq_tags *blk_mq_init_r
 
 		do {
 			page = alloc_pages_node(set->numa_node,
-				GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
+				GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO,
 				this_order);
 			if (page)
 				break;
@@ -1532,7 +1651,7 @@ static struct blk_mq_tags *blk_mq_init_r
 		 * Allow kmemleak to scan these pages as they contain pointers
 		 * to additional allocations like via ops->init_request().
 		 */
-		kmemleak_alloc(p, order_to_size(this_order), 1, GFP_KERNEL);
+		kmemleak_alloc(p, order_to_size(this_order), 1, GFP_NOIO);
 		entries_per_page = order_to_size(this_order) / rq_size;
 		to_do = min(entries_per_page, set->queue_depth - i);
 		left -= to_do * rq_size;
@@ -1613,6 +1732,9 @@ static void blk_mq_exit_hctx(struct requ
 	if (set->ops->exit_hctx)
 		set->ops->exit_hctx(hctx, hctx_idx);
 
+	if (hctx->flags & BLK_MQ_F_BLOCKING)
+		cleanup_srcu_struct(&hctx->queue_rq_srcu);
+
 	blk_mq_remove_cpuhp(hctx);
 	blk_free_flush_queue(hctx->fq);
 	sbitmap_free(&hctx->ctx_map);
@@ -1693,6 +1815,9 @@ static int blk_mq_init_hctx(struct reque
 				   flush_start_tag + hctx_idx, node))
 		goto free_fq;
 
+	if (hctx->flags & BLK_MQ_F_BLOCKING)
+		init_srcu_struct(&hctx->queue_rq_srcu);
+
 	return 0;
 
  free_fq:
@@ -1723,6 +1848,8 @@ static void blk_mq_init_cpu_queues(struc
 		spin_lock_init(&__ctx->lock);
 		INIT_LIST_HEAD(&__ctx->rq_list);
 		__ctx->queue = q;
+		blk_stat_init(&__ctx->stat[BLK_STAT_READ]);
+		blk_stat_init(&__ctx->stat[BLK_STAT_WRITE]);
 
 		/* If the cpu isn't online, the cpu is mapped to first hctx */
 		if (!cpu_online(i))
@@ -1742,7 +1869,7 @@ static void blk_mq_init_cpu_queues(struc
 static void blk_mq_map_swqueue(struct request_queue *q,
 			       const struct cpumask *online_mask)
 {
-	unsigned int i;
+	unsigned int i, hctx_idx;
 	struct blk_mq_hw_ctx *hctx;
 	struct blk_mq_ctx *ctx;
 	struct blk_mq_tag_set *set = q->tag_set;
@@ -1765,6 +1892,21 @@ static void blk_mq_map_swqueue(struct re
 		if (!cpumask_test_cpu(i, online_mask))
 			continue;
 
+		hctx_idx = q->mq_map[i];
+		/* unmapped hw queue can be remapped after CPU topo changed */
+		if (!set->tags[hctx_idx]) {
+			set->tags[hctx_idx] = blk_mq_init_rq_map(set, hctx_idx);
+
+			/*
+			 * If tags initialization fail for some hctx,
+			 * that hctx won't be brought online.  In this
+			 * case, remap the current ctx to hctx[0] which
+			 * is guaranteed to always have tags allocated
+			 */
+			if (!set->tags[hctx_idx])
+				q->mq_map[i] = 0;
+		}
+
 		ctx = per_cpu_ptr(q->queue_ctx, i);
 		hctx = blk_mq_map_queue(q, i);
 
@@ -1781,7 +1923,11 @@ static void blk_mq_map_swqueue(struct re
 		 * disable it and free the request entries.
 		 */
 		if (!hctx->nr_ctx) {
-			if (set->tags[i]) {
+			/* Never unmap queue 0.  We need it as a
+			 * fallback in case of a new remap fails
+			 * allocation
+			 */
+			if (i && set->tags[i]) {
 				blk_mq_free_rq_map(set, set->tags[i], i);
 				set->tags[i] = NULL;
 			}
@@ -1789,9 +1935,6 @@ static void blk_mq_map_swqueue(struct re
 			continue;
 		}
 
-		/* unmapped hw queue can be remapped after CPU topo changed */
-		if (!set->tags[i])
-			set->tags[i] = blk_mq_init_rq_map(set, i);
 		hctx->tags = set->tags[i];
 		WARN_ON(!hctx->tags);
 
@@ -2018,6 +2161,11 @@ struct request_queue *blk_mq_init_alloca
 	 */
 	q->nr_requests = set->queue_depth;
 
+	/*
+	 * Default to classic polling
+	 */
+	q->poll_nsec = -1;
+
 	if (set->ops->complete)
 		blk_queue_softirq_done(q, set->ops->complete);
 
@@ -2053,6 +2201,8 @@ void blk_mq_free_queue(struct request_qu
 	list_del_init(&q->all_q_node);
 	mutex_unlock(&all_q_mutex);
 
+	wbt_exit(q);
+
 	blk_mq_del_queue_tag_set(q);
 
 	blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
@@ -2099,16 +2249,9 @@ static void blk_mq_queue_reinit_work(voi
 	 */
 	list_for_each_entry(q, &all_q_list, all_q_node)
 		blk_mq_freeze_queue_start(q);
-	list_for_each_entry(q, &all_q_list, all_q_node) {
+	list_for_each_entry(q, &all_q_list, all_q_node)
 		blk_mq_freeze_queue_wait(q);
 
-		/*
-		 * timeout handler can't touch hw queue during the
-		 * reinitialization
-		 */
-		del_timer_sync(&q->timeout);
-	}
-
 	list_for_each_entry(q, &all_q_list, all_q_node)
 		blk_mq_queue_reinit(q, &cpuhp_online_new);
 
@@ -2353,6 +2496,165 @@ void blk_mq_update_nr_hw_queues(struct b
 }
 EXPORT_SYMBOL_GPL(blk_mq_update_nr_hw_queues);
 
+static unsigned long blk_mq_poll_nsecs(struct request_queue *q,
+				       struct blk_mq_hw_ctx *hctx,
+				       struct request *rq)
+{
+	struct blk_rq_stat stat[2];
+	unsigned long ret = 0;
+
+	/*
+	 * If stats collection isn't on, don't sleep but turn it on for
+	 * future users
+	 */
+	if (!blk_stat_enable(q))
+		return 0;
+
+	/*
+	 * We don't have to do this once per IO, should optimize this
+	 * to just use the current window of stats until it changes
+	 */
+	memset(&stat, 0, sizeof(stat));
+	blk_hctx_stat_get(hctx, stat);
+
+	/*
+	 * As an optimistic guess, use half of the mean service time
+	 * for this type of request. We can (and should) make this smarter.
+	 * For instance, if the completion latencies are tight, we can
+	 * get closer than just half the mean. This is especially
+	 * important on devices where the completion latencies are longer
+	 * than ~10 usec.
+	 */
+	if (req_op(rq) == REQ_OP_READ && stat[BLK_STAT_READ].nr_samples)
+		ret = (stat[BLK_STAT_READ].mean + 1) / 2;
+	else if (req_op(rq) == REQ_OP_WRITE && stat[BLK_STAT_WRITE].nr_samples)
+		ret = (stat[BLK_STAT_WRITE].mean + 1) / 2;
+
+	return ret;
+}
+
+static bool blk_mq_poll_hybrid_sleep(struct request_queue *q,
+				     struct blk_mq_hw_ctx *hctx,
+				     struct request *rq)
+{
+	struct hrtimer_sleeper hs;
+	enum hrtimer_mode mode;
+	unsigned int nsecs;
+	ktime_t kt;
+
+	if (test_bit(REQ_ATOM_POLL_SLEPT, &rq->atomic_flags))
+		return false;
+
+	/*
+	 * poll_nsec can be:
+	 *
+	 * -1:	don't ever hybrid sleep
+	 *  0:	use half of prev avg
+	 * >0:	use this specific value
+	 */
+	if (q->poll_nsec == -1)
+		return false;
+	else if (q->poll_nsec > 0)
+		nsecs = q->poll_nsec;
+	else
+		nsecs = blk_mq_poll_nsecs(q, hctx, rq);
+
+	if (!nsecs)
+		return false;
+
+	set_bit(REQ_ATOM_POLL_SLEPT, &rq->atomic_flags);
+
+	/*
+	 * This will be replaced with the stats tracking code, using
+	 * 'avg_completion_time / 2' as the pre-sleep target.
+	 */
+	kt = nsecs;
+
+	mode = HRTIMER_MODE_REL;
+	hrtimer_init_on_stack(&hs.timer, CLOCK_MONOTONIC, mode);
+	hrtimer_set_expires(&hs.timer, kt);
+
+	hrtimer_init_sleeper(&hs, current);
+	do {
+		if (test_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags))
+			break;
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		hrtimer_start_expires(&hs.timer, mode);
+		if (hs.task)
+			io_schedule();
+		hrtimer_cancel(&hs.timer);
+		mode = HRTIMER_MODE_ABS;
+	} while (hs.task && !signal_pending(current));
+
+	__set_current_state(TASK_RUNNING);
+	destroy_hrtimer_on_stack(&hs.timer);
+	return true;
+}
+
+static bool __blk_mq_poll(struct blk_mq_hw_ctx *hctx, struct request *rq)
+{
+	struct request_queue *q = hctx->queue;
+	long state;
+
+	/*
+	 * If we sleep, have the caller restart the poll loop to reset
+	 * the state. Like for the other success return cases, the
+	 * caller is responsible for checking if the IO completed. If
+	 * the IO isn't complete, we'll get called again and will go
+	 * straight to the busy poll loop.
+	 */
+	if (blk_mq_poll_hybrid_sleep(q, hctx, rq))
+		return true;
+
+	hctx->poll_considered++;
+
+	state = current->state;
+	while (!need_resched()) {
+		int ret;
+
+		hctx->poll_invoked++;
+
+		ret = q->mq_ops->poll(hctx, rq->tag);
+		if (ret > 0) {
+			hctx->poll_success++;
+			set_current_state(TASK_RUNNING);
+			return true;
+		}
+
+		if (signal_pending_state(state, current))
+			set_current_state(TASK_RUNNING);
+
+		if (current->state == TASK_RUNNING)
+			return true;
+		if (ret < 0)
+			break;
+		cpu_relax();
+	}
+
+	return false;
+}
+
+bool blk_mq_poll(struct request_queue *q, blk_qc_t cookie)
+{
+	struct blk_mq_hw_ctx *hctx;
+	struct blk_plug *plug;
+	struct request *rq;
+
+	if (!q->mq_ops || !q->mq_ops->poll || !blk_qc_t_valid(cookie) ||
+	    !test_bit(QUEUE_FLAG_POLL, &q->queue_flags))
+		return false;
+
+	plug = current->plug;
+	if (plug)
+		blk_flush_plug_list(plug, false);
+
+	hctx = q->queue_hw_ctx[blk_qc_t_to_queue_num(cookie)];
+	rq = blk_mq_tag_to_rq(hctx->tags, blk_qc_t_to_tag(cookie));
+
+	return __blk_mq_poll(hctx, rq);
+}
+EXPORT_SYMBOL_GPL(blk_mq_poll);
+
 void blk_mq_disable_hotplug(void)
 {
 	mutex_lock(&all_q_mutex);
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-mq-cpumap.c linux-libre-4.10-rc8-gnu/block/blk-mq-cpumap.c
--- linux-libre-4.9-gnu/block/blk-mq-cpumap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-mq-cpumap.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,6 +87,7 @@ int blk_mq_map_queues(struct blk_mq_tag_
 	free_cpumask_var(cpus);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(blk_mq_map_queues);
 
 /*
  * We have no quick way of doing reverse lookups. This is only used at
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-mq.h linux-libre-4.10-rc8-gnu/block/blk-mq.h
--- linux-libre-4.9-gnu/block/blk-mq.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-mq.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,8 @@
 #ifndef INT_BLK_MQ_H
 #define INT_BLK_MQ_H
 
+#include "blk-stat.h"
+
 struct blk_mq_tag_set;
 
 struct blk_mq_ctx {
@@ -18,6 +20,7 @@ struct blk_mq_ctx {
 
 	/* incremented at completion time */
 	unsigned long		____cacheline_aligned_in_smp rq_completed[2];
+	struct blk_rq_stat	stat[2];
 
 	struct request_queue	*queue;
 	struct kobject		kobj;
@@ -28,6 +31,7 @@ void blk_mq_freeze_queue(struct request_
 void blk_mq_free_queue(struct request_queue *q);
 int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr);
 void blk_mq_wake_waiters(struct request_queue *q);
+bool blk_mq_dispatch_rq_list(struct blk_mq_hw_ctx *, struct list_head *);
 
 /*
  * CPU hotplug helpers
@@ -38,7 +42,6 @@ void blk_mq_disable_hotplug(void);
 /*
  * CPU -> queue mappings
  */
-int blk_mq_map_queues(struct blk_mq_tag_set *set);
 extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int);
 
 static inline struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *q,
@@ -100,6 +103,11 @@ static inline void blk_mq_set_alloc_data
 	data->hctx = hctx;
 }
 
+static inline bool blk_mq_hctx_stopped(struct blk_mq_hw_ctx *hctx)
+{
+	return test_bit(BLK_MQ_S_STOPPED, &hctx->state);
+}
+
 static inline bool blk_mq_hw_queue_mapped(struct blk_mq_hw_ctx *hctx)
 {
 	return hctx->nr_ctx && hctx->tags;
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-mq-sysfs.c linux-libre-4.10-rc8-gnu/block/blk-mq-sysfs.c
--- linux-libre-4.9-gnu/block/blk-mq-sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-mq-sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -259,6 +259,47 @@ static ssize_t blk_mq_hw_sysfs_cpus_show
 	return ret;
 }
 
+static void blk_mq_stat_clear(struct blk_mq_hw_ctx *hctx)
+{
+	struct blk_mq_ctx *ctx;
+	unsigned int i;
+
+	hctx_for_each_ctx(hctx, ctx, i) {
+		blk_stat_init(&ctx->stat[BLK_STAT_READ]);
+		blk_stat_init(&ctx->stat[BLK_STAT_WRITE]);
+	}
+}
+
+static ssize_t blk_mq_hw_sysfs_stat_store(struct blk_mq_hw_ctx *hctx,
+					  const char *page, size_t count)
+{
+	blk_mq_stat_clear(hctx);
+	return count;
+}
+
+static ssize_t print_stat(char *page, struct blk_rq_stat *stat, const char *pre)
+{
+	return sprintf(page, "%s samples=%llu, mean=%lld, min=%lld, max=%lld\n",
+			pre, (long long) stat->nr_samples,
+			(long long) stat->mean, (long long) stat->min,
+			(long long) stat->max);
+}
+
+static ssize_t blk_mq_hw_sysfs_stat_show(struct blk_mq_hw_ctx *hctx, char *page)
+{
+	struct blk_rq_stat stat[2];
+	ssize_t ret;
+
+	blk_stat_init(&stat[BLK_STAT_READ]);
+	blk_stat_init(&stat[BLK_STAT_WRITE]);
+
+	blk_hctx_stat_get(hctx, stat);
+
+	ret = print_stat(page, &stat[BLK_STAT_READ], "read :");
+	ret += print_stat(page + ret, &stat[BLK_STAT_WRITE], "write:");
+	return ret;
+}
+
 static struct blk_mq_ctx_sysfs_entry blk_mq_sysfs_dispatched = {
 	.attr = {.name = "dispatched", .mode = S_IRUGO },
 	.show = blk_mq_sysfs_dispatched_show,
@@ -317,6 +358,11 @@ static struct blk_mq_hw_ctx_sysfs_entry
 	.show = blk_mq_hw_sysfs_poll_show,
 	.store = blk_mq_hw_sysfs_poll_store,
 };
+static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_stat = {
+	.attr = {.name = "stats", .mode = S_IRUGO | S_IWUSR },
+	.show = blk_mq_hw_sysfs_stat_show,
+	.store = blk_mq_hw_sysfs_stat_store,
+};
 
 static struct attribute *default_hw_ctx_attrs[] = {
 	&blk_mq_hw_sysfs_queued.attr,
@@ -327,6 +373,7 @@ static struct attribute *default_hw_ctx_
 	&blk_mq_hw_sysfs_cpus.attr,
 	&blk_mq_hw_sysfs_active.attr,
 	&blk_mq_hw_sysfs_poll.attr,
+	&blk_mq_hw_sysfs_stat.attr,
 	NULL,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-settings.c linux-libre-4.10-rc8-gnu/block/blk-settings.c
--- linux-libre-4.9-gnu/block/blk-settings.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-settings.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/gfp.h>
 
 #include "blk.h"
+#include "blk-wbt.h"
 
 unsigned long blk_max_low_pfn;
 EXPORT_SYMBOL(blk_max_low_pfn);
@@ -95,6 +96,7 @@ void blk_set_default_limits(struct queue
 	lim->max_dev_sectors = 0;
 	lim->chunk_sectors = 0;
 	lim->max_write_same_sectors = 0;
+	lim->max_write_zeroes_sectors = 0;
 	lim->max_discard_sectors = 0;
 	lim->max_hw_discard_sectors = 0;
 	lim->discard_granularity = 0;
@@ -107,6 +109,7 @@ void blk_set_default_limits(struct queue
 	lim->io_opt = 0;
 	lim->misaligned = 0;
 	lim->cluster = 1;
+	lim->zoned = BLK_ZONED_NONE;
 }
 EXPORT_SYMBOL(blk_set_default_limits);
 
@@ -130,6 +133,7 @@ void blk_set_stacking_limits(struct queu
 	lim->max_sectors = UINT_MAX;
 	lim->max_dev_sectors = UINT_MAX;
 	lim->max_write_same_sectors = UINT_MAX;
+	lim->max_write_zeroes_sectors = UINT_MAX;
 }
 EXPORT_SYMBOL(blk_set_stacking_limits);
 
@@ -249,6 +253,7 @@ void blk_queue_max_hw_sectors(struct req
 	max_sectors = min_not_zero(max_hw_sectors, limits->max_dev_sectors);
 	max_sectors = min_t(unsigned int, max_sectors, BLK_DEF_MAX_SECTORS);
 	limits->max_sectors = max_sectors;
+	q->backing_dev_info.io_pages = max_sectors >> (PAGE_SHIFT - 9);
 }
 EXPORT_SYMBOL(blk_queue_max_hw_sectors);
 
@@ -298,6 +303,19 @@ void blk_queue_max_write_same_sectors(st
 EXPORT_SYMBOL(blk_queue_max_write_same_sectors);
 
 /**
+ * blk_queue_max_write_zeroes_sectors - set max sectors for a single
+ *                                      write zeroes
+ * @q:  the request queue for the device
+ * @max_write_zeroes_sectors: maximum number of sectors to write per command
+ **/
+void blk_queue_max_write_zeroes_sectors(struct request_queue *q,
+		unsigned int max_write_zeroes_sectors)
+{
+	q->limits.max_write_zeroes_sectors = max_write_zeroes_sectors;
+}
+EXPORT_SYMBOL(blk_queue_max_write_zeroes_sectors);
+
+/**
  * blk_queue_max_segments - set max hw segments for a request for this queue
  * @q:  the request queue for the device
  * @max_segments:  max number of segments
@@ -525,6 +543,8 @@ int blk_stack_limits(struct queue_limits
 	t->max_dev_sectors = min_not_zero(t->max_dev_sectors, b->max_dev_sectors);
 	t->max_write_same_sectors = min(t->max_write_same_sectors,
 					b->max_write_same_sectors);
+	t->max_write_zeroes_sectors = min(t->max_write_zeroes_sectors,
+					b->max_write_zeroes_sectors);
 	t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn);
 
 	t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask,
@@ -630,6 +650,10 @@ int blk_stack_limits(struct queue_limits
 			t->discard_granularity;
 	}
 
+	if (b->chunk_sectors)
+		t->chunk_sectors = min_not_zero(t->chunk_sectors,
+						b->chunk_sectors);
+
 	return ret;
 }
 EXPORT_SYMBOL(blk_stack_limits);
@@ -832,6 +856,19 @@ void blk_queue_flush_queueable(struct re
 EXPORT_SYMBOL_GPL(blk_queue_flush_queueable);
 
 /**
+ * blk_set_queue_depth - tell the block layer about the device queue depth
+ * @q:		the request queue for the device
+ * @depth:		queue depth
+ *
+ */
+void blk_set_queue_depth(struct request_queue *q, unsigned int depth)
+{
+	q->queue_depth = depth;
+	wbt_set_queue_depth(q->rq_wb, depth);
+}
+EXPORT_SYMBOL(blk_set_queue_depth);
+
+/**
  * blk_queue_write_cache - configure queue's write cache
  * @q:		the request queue for the device
  * @wc:		write back cache on or off
@@ -851,6 +888,8 @@ void blk_queue_write_cache(struct reques
 	else
 		queue_flag_clear(QUEUE_FLAG_FUA, q);
 	spin_unlock_irq(q->queue_lock);
+
+	wbt_set_write_cache(q->rq_wb, test_bit(QUEUE_FLAG_WC, &q->queue_flags));
 }
 EXPORT_SYMBOL_GPL(blk_queue_write_cache);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-stat.c linux-libre-4.10-rc8-gnu/block/blk-stat.c
--- linux-libre-4.9-gnu/block/blk-stat.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-stat.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,256 @@
+/*
+ * Block stat tracking code
+ *
+ * Copyright (C) 2016 Jens Axboe
+ */
+#include <linux/kernel.h>
+#include <linux/blk-mq.h>
+
+#include "blk-stat.h"
+#include "blk-mq.h"
+
+static void blk_stat_flush_batch(struct blk_rq_stat *stat)
+{
+	const s32 nr_batch = READ_ONCE(stat->nr_batch);
+	const s32 nr_samples = READ_ONCE(stat->nr_samples);
+
+	if (!nr_batch)
+		return;
+	if (!nr_samples)
+		stat->mean = div64_s64(stat->batch, nr_batch);
+	else {
+		stat->mean = div64_s64((stat->mean * nr_samples) +
+					stat->batch,
+					nr_batch + nr_samples);
+	}
+
+	stat->nr_samples += nr_batch;
+	stat->nr_batch = stat->batch = 0;
+}
+
+static void blk_stat_sum(struct blk_rq_stat *dst, struct blk_rq_stat *src)
+{
+	if (!src->nr_samples)
+		return;
+
+	blk_stat_flush_batch(src);
+
+	dst->min = min(dst->min, src->min);
+	dst->max = max(dst->max, src->max);
+
+	if (!dst->nr_samples)
+		dst->mean = src->mean;
+	else {
+		dst->mean = div64_s64((src->mean * src->nr_samples) +
+					(dst->mean * dst->nr_samples),
+					dst->nr_samples + src->nr_samples);
+	}
+	dst->nr_samples += src->nr_samples;
+}
+
+static void blk_mq_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
+{
+	struct blk_mq_hw_ctx *hctx;
+	struct blk_mq_ctx *ctx;
+	uint64_t latest = 0;
+	int i, j, nr;
+
+	blk_stat_init(&dst[BLK_STAT_READ]);
+	blk_stat_init(&dst[BLK_STAT_WRITE]);
+
+	nr = 0;
+	do {
+		uint64_t newest = 0;
+
+		queue_for_each_hw_ctx(q, hctx, i) {
+			hctx_for_each_ctx(hctx, ctx, j) {
+				blk_stat_flush_batch(&ctx->stat[BLK_STAT_READ]);
+				blk_stat_flush_batch(&ctx->stat[BLK_STAT_WRITE]);
+
+				if (!ctx->stat[BLK_STAT_READ].nr_samples &&
+				    !ctx->stat[BLK_STAT_WRITE].nr_samples)
+					continue;
+				if (ctx->stat[BLK_STAT_READ].time > newest)
+					newest = ctx->stat[BLK_STAT_READ].time;
+				if (ctx->stat[BLK_STAT_WRITE].time > newest)
+					newest = ctx->stat[BLK_STAT_WRITE].time;
+			}
+		}
+
+		/*
+		 * No samples
+		 */
+		if (!newest)
+			break;
+
+		if (newest > latest)
+			latest = newest;
+
+		queue_for_each_hw_ctx(q, hctx, i) {
+			hctx_for_each_ctx(hctx, ctx, j) {
+				if (ctx->stat[BLK_STAT_READ].time == newest) {
+					blk_stat_sum(&dst[BLK_STAT_READ],
+						     &ctx->stat[BLK_STAT_READ]);
+					nr++;
+				}
+				if (ctx->stat[BLK_STAT_WRITE].time == newest) {
+					blk_stat_sum(&dst[BLK_STAT_WRITE],
+						     &ctx->stat[BLK_STAT_WRITE]);
+					nr++;
+				}
+			}
+		}
+		/*
+		 * If we race on finding an entry, just loop back again.
+		 * Should be very rare.
+		 */
+	} while (!nr);
+
+	dst[BLK_STAT_READ].time = dst[BLK_STAT_WRITE].time = latest;
+}
+
+void blk_queue_stat_get(struct request_queue *q, struct blk_rq_stat *dst)
+{
+	if (q->mq_ops)
+		blk_mq_stat_get(q, dst);
+	else {
+		blk_stat_flush_batch(&q->rq_stats[BLK_STAT_READ]);
+		blk_stat_flush_batch(&q->rq_stats[BLK_STAT_WRITE]);
+		memcpy(&dst[BLK_STAT_READ], &q->rq_stats[BLK_STAT_READ],
+				sizeof(struct blk_rq_stat));
+		memcpy(&dst[BLK_STAT_WRITE], &q->rq_stats[BLK_STAT_WRITE],
+				sizeof(struct blk_rq_stat));
+	}
+}
+
+void blk_hctx_stat_get(struct blk_mq_hw_ctx *hctx, struct blk_rq_stat *dst)
+{
+	struct blk_mq_ctx *ctx;
+	unsigned int i, nr;
+
+	nr = 0;
+	do {
+		uint64_t newest = 0;
+
+		hctx_for_each_ctx(hctx, ctx, i) {
+			blk_stat_flush_batch(&ctx->stat[BLK_STAT_READ]);
+			blk_stat_flush_batch(&ctx->stat[BLK_STAT_WRITE]);
+
+			if (!ctx->stat[BLK_STAT_READ].nr_samples &&
+			    !ctx->stat[BLK_STAT_WRITE].nr_samples)
+				continue;
+
+			if (ctx->stat[BLK_STAT_READ].time > newest)
+				newest = ctx->stat[BLK_STAT_READ].time;
+			if (ctx->stat[BLK_STAT_WRITE].time > newest)
+				newest = ctx->stat[BLK_STAT_WRITE].time;
+		}
+
+		if (!newest)
+			break;
+
+		hctx_for_each_ctx(hctx, ctx, i) {
+			if (ctx->stat[BLK_STAT_READ].time == newest) {
+				blk_stat_sum(&dst[BLK_STAT_READ],
+						&ctx->stat[BLK_STAT_READ]);
+				nr++;
+			}
+			if (ctx->stat[BLK_STAT_WRITE].time == newest) {
+				blk_stat_sum(&dst[BLK_STAT_WRITE],
+						&ctx->stat[BLK_STAT_WRITE]);
+				nr++;
+			}
+		}
+		/*
+		 * If we race on finding an entry, just loop back again.
+		 * Should be very rare, as the window is only updated
+		 * occasionally
+		 */
+	} while (!nr);
+}
+
+static void __blk_stat_init(struct blk_rq_stat *stat, s64 time_now)
+{
+	stat->min = -1ULL;
+	stat->max = stat->nr_samples = stat->mean = 0;
+	stat->batch = stat->nr_batch = 0;
+	stat->time = time_now & BLK_STAT_NSEC_MASK;
+}
+
+void blk_stat_init(struct blk_rq_stat *stat)
+{
+	__blk_stat_init(stat, ktime_to_ns(ktime_get()));
+}
+
+static bool __blk_stat_is_current(struct blk_rq_stat *stat, s64 now)
+{
+	return (now & BLK_STAT_NSEC_MASK) == (stat->time & BLK_STAT_NSEC_MASK);
+}
+
+bool blk_stat_is_current(struct blk_rq_stat *stat)
+{
+	return __blk_stat_is_current(stat, ktime_to_ns(ktime_get()));
+}
+
+void blk_stat_add(struct blk_rq_stat *stat, struct request *rq)
+{
+	s64 now, value;
+
+	now = __blk_stat_time(ktime_to_ns(ktime_get()));
+	if (now < blk_stat_time(&rq->issue_stat))
+		return;
+
+	if (!__blk_stat_is_current(stat, now))
+		__blk_stat_init(stat, now);
+
+	value = now - blk_stat_time(&rq->issue_stat);
+	if (value > stat->max)
+		stat->max = value;
+	if (value < stat->min)
+		stat->min = value;
+
+	if (stat->batch + value < stat->batch ||
+	    stat->nr_batch + 1 == BLK_RQ_STAT_BATCH)
+		blk_stat_flush_batch(stat);
+
+	stat->batch += value;
+	stat->nr_batch++;
+}
+
+void blk_stat_clear(struct request_queue *q)
+{
+	if (q->mq_ops) {
+		struct blk_mq_hw_ctx *hctx;
+		struct blk_mq_ctx *ctx;
+		int i, j;
+
+		queue_for_each_hw_ctx(q, hctx, i) {
+			hctx_for_each_ctx(hctx, ctx, j) {
+				blk_stat_init(&ctx->stat[BLK_STAT_READ]);
+				blk_stat_init(&ctx->stat[BLK_STAT_WRITE]);
+			}
+		}
+	} else {
+		blk_stat_init(&q->rq_stats[BLK_STAT_READ]);
+		blk_stat_init(&q->rq_stats[BLK_STAT_WRITE]);
+	}
+}
+
+void blk_stat_set_issue_time(struct blk_issue_stat *stat)
+{
+	stat->time = (stat->time & BLK_STAT_MASK) |
+			(ktime_to_ns(ktime_get()) & BLK_STAT_TIME_MASK);
+}
+
+/*
+ * Enable stat tracking, return whether it was enabled
+ */
+bool blk_stat_enable(struct request_queue *q)
+{
+	if (!test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
+		set_bit(QUEUE_FLAG_STATS, &q->queue_flags);
+		return false;
+	}
+
+	return true;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-stat.h linux-libre-4.10-rc8-gnu/block/blk-stat.h
--- linux-libre-4.9-gnu/block/blk-stat.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-stat.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,42 @@
+#ifndef BLK_STAT_H
+#define BLK_STAT_H
+
+/*
+ * ~0.13s window as a power-of-2 (2^27 nsecs)
+ */
+#define BLK_STAT_NSEC		134217728ULL
+#define BLK_STAT_NSEC_MASK	~(BLK_STAT_NSEC - 1)
+
+/*
+ * Upper 3 bits can be used elsewhere
+ */
+#define BLK_STAT_RES_BITS	3
+#define BLK_STAT_SHIFT		(64 - BLK_STAT_RES_BITS)
+#define BLK_STAT_TIME_MASK	((1ULL << BLK_STAT_SHIFT) - 1)
+#define BLK_STAT_MASK		~BLK_STAT_TIME_MASK
+
+enum {
+	BLK_STAT_READ	= 0,
+	BLK_STAT_WRITE,
+};
+
+void blk_stat_add(struct blk_rq_stat *, struct request *);
+void blk_hctx_stat_get(struct blk_mq_hw_ctx *, struct blk_rq_stat *);
+void blk_queue_stat_get(struct request_queue *, struct blk_rq_stat *);
+void blk_stat_clear(struct request_queue *);
+void blk_stat_init(struct blk_rq_stat *);
+bool blk_stat_is_current(struct blk_rq_stat *);
+void blk_stat_set_issue_time(struct blk_issue_stat *);
+bool blk_stat_enable(struct request_queue *);
+
+static inline u64 __blk_stat_time(u64 time)
+{
+	return time & BLK_STAT_TIME_MASK;
+}
+
+static inline u64 blk_stat_time(struct blk_issue_stat *stat)
+{
+	return __blk_stat_time(stat->time);
+}
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-sysfs.c linux-libre-4.10-rc8-gnu/block/blk-sysfs.c
--- linux-libre-4.9-gnu/block/blk-sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include "blk.h"
 #include "blk-mq.h"
+#include "blk-wbt.h"
 
 struct queue_sysfs_entry {
 	struct attribute attr;
@@ -41,6 +42,19 @@ queue_var_store(unsigned long *var, cons
 	return count;
 }
 
+static ssize_t queue_var_store64(s64 *var, const char *page)
+{
+	int err;
+	s64 v;
+
+	err = kstrtos64(page, 10, &v);
+	if (err < 0)
+		return err;
+
+	*var = v;
+	return 0;
+}
+
 static ssize_t queue_requests_show(struct request_queue *q, char *page)
 {
 	return queue_var_show(q->nr_requests, (page));
@@ -130,6 +144,11 @@ static ssize_t queue_physical_block_size
 	return queue_var_show(queue_physical_block_size(q), page);
 }
 
+static ssize_t queue_chunk_sectors_show(struct request_queue *q, char *page)
+{
+	return queue_var_show(q->limits.chunk_sectors, page);
+}
+
 static ssize_t queue_io_min_show(struct request_queue *q, char *page)
 {
 	return queue_var_show(queue_io_min(q), page);
@@ -192,6 +211,11 @@ static ssize_t queue_write_same_max_show
 		(unsigned long long)q->limits.max_write_same_sectors << 9);
 }
 
+static ssize_t queue_write_zeroes_max_show(struct request_queue *q, char *page)
+{
+	return sprintf(page, "%llu\n",
+		(unsigned long long)q->limits.max_write_zeroes_sectors << 9);
+}
 
 static ssize_t
 queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
@@ -212,6 +236,7 @@ queue_max_sectors_store(struct request_q
 
 	spin_lock_irq(q->queue_lock);
 	q->limits.max_sectors = max_sectors_kb << 1;
+	q->backing_dev_info.io_pages = max_sectors_kb >> (PAGE_SHIFT - 10);
 	spin_unlock_irq(q->queue_lock);
 
 	return ret;
@@ -257,6 +282,18 @@ QUEUE_SYSFS_BIT_FNS(random, ADD_RANDOM,
 QUEUE_SYSFS_BIT_FNS(iostats, IO_STAT, 0);
 #undef QUEUE_SYSFS_BIT_FNS
 
+static ssize_t queue_zoned_show(struct request_queue *q, char *page)
+{
+	switch (blk_queue_zoned_model(q)) {
+	case BLK_ZONED_HA:
+		return sprintf(page, "host-aware\n");
+	case BLK_ZONED_HM:
+		return sprintf(page, "host-managed\n");
+	default:
+		return sprintf(page, "none\n");
+	}
+}
+
 static ssize_t queue_nomerges_show(struct request_queue *q, char *page)
 {
 	return queue_var_show((blk_queue_nomerges(q) << 1) |
@@ -319,6 +356,38 @@ queue_rq_affinity_store(struct request_q
 	return ret;
 }
 
+static ssize_t queue_poll_delay_show(struct request_queue *q, char *page)
+{
+	int val;
+
+	if (q->poll_nsec == -1)
+		val = -1;
+	else
+		val = q->poll_nsec / 1000;
+
+	return sprintf(page, "%d\n", val);
+}
+
+static ssize_t queue_poll_delay_store(struct request_queue *q, const char *page,
+				size_t count)
+{
+	int err, val;
+
+	if (!q->mq_ops || !q->mq_ops->poll)
+		return -EINVAL;
+
+	err = kstrtoint(page, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val == -1)
+		q->poll_nsec = -1;
+	else
+		q->poll_nsec = val * 1000;
+
+	return count;
+}
+
 static ssize_t queue_poll_show(struct request_queue *q, char *page)
 {
 	return queue_var_show(test_bit(QUEUE_FLAG_POLL, &q->queue_flags), page);
@@ -347,6 +416,50 @@ static ssize_t queue_poll_store(struct r
 	return ret;
 }
 
+static ssize_t queue_wb_lat_show(struct request_queue *q, char *page)
+{
+	if (!q->rq_wb)
+		return -EINVAL;
+
+	return sprintf(page, "%llu\n", div_u64(q->rq_wb->min_lat_nsec, 1000));
+}
+
+static ssize_t queue_wb_lat_store(struct request_queue *q, const char *page,
+				  size_t count)
+{
+	struct rq_wb *rwb;
+	ssize_t ret;
+	s64 val;
+
+	ret = queue_var_store64(&val, page);
+	if (ret < 0)
+		return ret;
+	if (val < -1)
+		return -EINVAL;
+
+	rwb = q->rq_wb;
+	if (!rwb) {
+		ret = wbt_init(q);
+		if (ret)
+			return ret;
+
+		rwb = q->rq_wb;
+		if (!rwb)
+			return -EINVAL;
+	}
+
+	if (val == -1)
+		rwb->min_lat_nsec = wbt_default_latency_nsec(q);
+	else if (val >= 0)
+		rwb->min_lat_nsec = val * 1000ULL;
+
+	if (rwb->enable_state == WBT_STATE_ON_DEFAULT)
+		rwb->enable_state = WBT_STATE_ON_MANUAL;
+
+	wbt_update_limits(rwb);
+	return count;
+}
+
 static ssize_t queue_wc_show(struct request_queue *q, char *page)
 {
 	if (test_bit(QUEUE_FLAG_WC, &q->queue_flags))
@@ -384,6 +497,26 @@ static ssize_t queue_dax_show(struct req
 	return queue_var_show(blk_queue_dax(q), page);
 }
 
+static ssize_t print_stat(char *page, struct blk_rq_stat *stat, const char *pre)
+{
+	return sprintf(page, "%s samples=%llu, mean=%lld, min=%lld, max=%lld\n",
+			pre, (long long) stat->nr_samples,
+			(long long) stat->mean, (long long) stat->min,
+			(long long) stat->max);
+}
+
+static ssize_t queue_stats_show(struct request_queue *q, char *page)
+{
+	struct blk_rq_stat stat[2];
+	ssize_t ret;
+
+	blk_queue_stat_get(q, stat);
+
+	ret = print_stat(page, &stat[BLK_STAT_READ], "read :");
+	ret += print_stat(page + ret, &stat[BLK_STAT_WRITE], "write:");
+	return ret;
+}
+
 static struct queue_sysfs_entry queue_requests_entry = {
 	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_requests_show,
@@ -443,6 +576,11 @@ static struct queue_sysfs_entry queue_ph
 	.show = queue_physical_block_size_show,
 };
 
+static struct queue_sysfs_entry queue_chunk_sectors_entry = {
+	.attr = {.name = "chunk_sectors", .mode = S_IRUGO },
+	.show = queue_chunk_sectors_show,
+};
+
 static struct queue_sysfs_entry queue_io_min_entry = {
 	.attr = {.name = "minimum_io_size", .mode = S_IRUGO },
 	.show = queue_io_min_show,
@@ -479,12 +617,22 @@ static struct queue_sysfs_entry queue_wr
 	.show = queue_write_same_max_show,
 };
 
+static struct queue_sysfs_entry queue_write_zeroes_max_entry = {
+	.attr = {.name = "write_zeroes_max_bytes", .mode = S_IRUGO },
+	.show = queue_write_zeroes_max_show,
+};
+
 static struct queue_sysfs_entry queue_nonrot_entry = {
 	.attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_show_nonrot,
 	.store = queue_store_nonrot,
 };
 
+static struct queue_sysfs_entry queue_zoned_entry = {
+	.attr = {.name = "zoned", .mode = S_IRUGO },
+	.show = queue_zoned_show,
+};
+
 static struct queue_sysfs_entry queue_nomerges_entry = {
 	.attr = {.name = "nomerges", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_nomerges_show,
@@ -515,6 +663,12 @@ static struct queue_sysfs_entry queue_po
 	.store = queue_poll_store,
 };
 
+static struct queue_sysfs_entry queue_poll_delay_entry = {
+	.attr = {.name = "io_poll_delay", .mode = S_IRUGO | S_IWUSR },
+	.show = queue_poll_delay_show,
+	.store = queue_poll_delay_store,
+};
+
 static struct queue_sysfs_entry queue_wc_entry = {
 	.attr = {.name = "write_cache", .mode = S_IRUGO | S_IWUSR },
 	.show = queue_wc_show,
@@ -526,6 +680,17 @@ static struct queue_sysfs_entry queue_da
 	.show = queue_dax_show,
 };
 
+static struct queue_sysfs_entry queue_stats_entry = {
+	.attr = {.name = "stats", .mode = S_IRUGO },
+	.show = queue_stats_show,
+};
+
+static struct queue_sysfs_entry queue_wb_lat_entry = {
+	.attr = {.name = "wbt_lat_usec", .mode = S_IRUGO | S_IWUSR },
+	.show = queue_wb_lat_show,
+	.store = queue_wb_lat_store,
+};
+
 static struct attribute *default_attrs[] = {
 	&queue_requests_entry.attr,
 	&queue_ra_entry.attr,
@@ -538,6 +703,7 @@ static struct attribute *default_attrs[]
 	&queue_hw_sector_size_entry.attr,
 	&queue_logical_block_size_entry.attr,
 	&queue_physical_block_size_entry.attr,
+	&queue_chunk_sectors_entry.attr,
 	&queue_io_min_entry.attr,
 	&queue_io_opt_entry.attr,
 	&queue_discard_granularity_entry.attr,
@@ -545,7 +711,9 @@ static struct attribute *default_attrs[]
 	&queue_discard_max_hw_entry.attr,
 	&queue_discard_zeroes_data_entry.attr,
 	&queue_write_same_max_entry.attr,
+	&queue_write_zeroes_max_entry.attr,
 	&queue_nonrot_entry.attr,
+	&queue_zoned_entry.attr,
 	&queue_nomerges_entry.attr,
 	&queue_rq_affinity_entry.attr,
 	&queue_iostats_entry.attr,
@@ -553,6 +721,9 @@ static struct attribute *default_attrs[]
 	&queue_poll_entry.attr,
 	&queue_wc_entry.attr,
 	&queue_dax_entry.attr,
+	&queue_stats_entry.attr,
+	&queue_wb_lat_entry.attr,
+	&queue_poll_delay_entry.attr,
 	NULL,
 };
 
@@ -627,6 +798,7 @@ static void blk_release_queue(struct kob
 	struct request_queue *q =
 		container_of(kobj, struct request_queue, kobj);
 
+	wbt_exit(q);
 	bdi_exit(&q->backing_dev_info);
 	blkcg_exit_queue(q);
 
@@ -667,6 +839,23 @@ struct kobj_type blk_queue_ktype = {
 	.release	= blk_release_queue,
 };
 
+static void blk_wb_init(struct request_queue *q)
+{
+#ifndef CONFIG_BLK_WBT_MQ
+	if (q->mq_ops)
+		return;
+#endif
+#ifndef CONFIG_BLK_WBT_SQ
+	if (q->request_fn)
+		return;
+#endif
+
+	/*
+	 * If this fails, we don't get throttling
+	 */
+	wbt_init(q);
+}
+
 int blk_register_queue(struct gendisk *disk)
 {
 	int ret;
@@ -706,6 +895,8 @@ int blk_register_queue(struct gendisk *d
 	if (q->mq_ops)
 		blk_mq_register_dev(dev, q);
 
+	blk_wb_init(q);
+
 	if (!q->request_fn)
 		return 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-tag.c linux-libre-4.10-rc8-gnu/block/blk-tag.c
--- linux-libre-4.9-gnu/block/blk-tag.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-tag.c	2017-02-12 16:03:20.000000000 -0500
@@ -270,7 +270,7 @@ void blk_queue_end_tag(struct request_qu
 	BUG_ON(tag >= bqt->real_max_depth);
 
 	list_del_init(&rq->queuelist);
-	rq->cmd_flags &= ~REQ_QUEUED;
+	rq->rq_flags &= ~RQF_QUEUED;
 	rq->tag = -1;
 
 	if (unlikely(bqt->tag_index[tag] == NULL))
@@ -316,7 +316,7 @@ int blk_queue_start_tag(struct request_q
 	unsigned max_depth;
 	int tag;
 
-	if (unlikely((rq->cmd_flags & REQ_QUEUED))) {
+	if (unlikely((rq->rq_flags & RQF_QUEUED))) {
 		printk(KERN_ERR
 		       "%s: request %p for device [%s] already tagged %d",
 		       __func__, rq,
@@ -371,7 +371,7 @@ int blk_queue_start_tag(struct request_q
 	 */
 
 	bqt->next_tag = (tag + 1) % bqt->max_depth;
-	rq->cmd_flags |= REQ_QUEUED;
+	rq->rq_flags |= RQF_QUEUED;
 	rq->tag = tag;
 	bqt->tag_index[tag] = rq;
 	blk_start_request(rq);
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-throttle.c linux-libre-4.10-rc8-gnu/block/blk-throttle.c
--- linux-libre-4.9-gnu/block/blk-throttle.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-throttle.c	2017-02-12 16:03:20.000000000 -0500
@@ -818,13 +818,13 @@ static void throtl_charge_bio(struct thr
 	tg->io_disp[rw]++;
 
 	/*
-	 * REQ_THROTTLED is used to prevent the same bio to be throttled
+	 * BIO_THROTTLED is used to prevent the same bio to be throttled
 	 * more than once as a throttled bio will go through blk-throtl the
 	 * second time when it eventually gets issued.  Set it when a bio
 	 * is being charged to a tg.
 	 */
-	if (!(bio->bi_opf & REQ_THROTTLED))
-		bio->bi_opf |= REQ_THROTTLED;
+	if (!bio_flagged(bio, BIO_THROTTLED))
+		bio_set_flag(bio, BIO_THROTTLED);
 }
 
 /**
@@ -1401,7 +1401,7 @@ bool blk_throtl_bio(struct request_queue
 	WARN_ON_ONCE(!rcu_read_lock_held());
 
 	/* see throtl_charge_bio() */
-	if ((bio->bi_opf & REQ_THROTTLED) || !tg->has_rules[rw])
+	if (bio_flagged(bio, BIO_THROTTLED) || !tg->has_rules[rw])
 		goto out;
 
 	spin_lock_irq(q->queue_lock);
@@ -1480,7 +1480,7 @@ out:
 	 * being issued.
 	 */
 	if (!throttled)
-		bio->bi_opf &= ~REQ_THROTTLED;
+		bio_clear_flag(bio, BIO_THROTTLED);
 	return throttled;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-wbt.c linux-libre-4.10-rc8-gnu/block/blk-wbt.c
--- linux-libre-4.9-gnu/block/blk-wbt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-wbt.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,751 @@
+/*
+ * buffered writeback throttling. loosely based on CoDel. We can't drop
+ * packets for IO scheduling, so the logic is something like this:
+ *
+ * - Monitor latencies in a defined window of time.
+ * - If the minimum latency in the above window exceeds some target, increment
+ *   scaling step and scale down queue depth by a factor of 2x. The monitoring
+ *   window is then shrunk to 100 / sqrt(scaling step + 1).
+ * - For any window where we don't have solid data on what the latencies
+ *   look like, retain status quo.
+ * - If latencies look good, decrement scaling step.
+ * - If we're only doing writes, allow the scaling step to go negative. This
+ *   will temporarily boost write performance, snapping back to a stable
+ *   scaling step of 0 if reads show up or the heavy writers finish. Unlike
+ *   positive scaling steps where we shrink the monitoring window, a negative
+ *   scaling step retains the default step==0 window size.
+ *
+ * Copyright (C) 2016 Jens Axboe
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/blk_types.h>
+#include <linux/slab.h>
+#include <linux/backing-dev.h>
+#include <linux/swap.h>
+
+#include "blk-wbt.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/wbt.h>
+
+enum {
+	/*
+	 * Default setting, we'll scale up (to 75% of QD max) or down (min 1)
+	 * from here depending on device stats
+	 */
+	RWB_DEF_DEPTH	= 16,
+
+	/*
+	 * 100msec window
+	 */
+	RWB_WINDOW_NSEC		= 100 * 1000 * 1000ULL,
+
+	/*
+	 * Disregard stats, if we don't meet this minimum
+	 */
+	RWB_MIN_WRITE_SAMPLES	= 3,
+
+	/*
+	 * If we have this number of consecutive windows with not enough
+	 * information to scale up or down, scale up.
+	 */
+	RWB_UNKNOWN_BUMP	= 5,
+};
+
+static inline bool rwb_enabled(struct rq_wb *rwb)
+{
+	return rwb && rwb->wb_normal != 0;
+}
+
+/*
+ * Increment 'v', if 'v' is below 'below'. Returns true if we succeeded,
+ * false if 'v' + 1 would be bigger than 'below'.
+ */
+static bool atomic_inc_below(atomic_t *v, int below)
+{
+	int cur = atomic_read(v);
+
+	for (;;) {
+		int old;
+
+		if (cur >= below)
+			return false;
+		old = atomic_cmpxchg(v, cur, cur + 1);
+		if (old == cur)
+			break;
+		cur = old;
+	}
+
+	return true;
+}
+
+static void wb_timestamp(struct rq_wb *rwb, unsigned long *var)
+{
+	if (rwb_enabled(rwb)) {
+		const unsigned long cur = jiffies;
+
+		if (cur != *var)
+			*var = cur;
+	}
+}
+
+/*
+ * If a task was rate throttled in balance_dirty_pages() within the last
+ * second or so, use that to indicate a higher cleaning rate.
+ */
+static bool wb_recent_wait(struct rq_wb *rwb)
+{
+	struct bdi_writeback *wb = &rwb->queue->backing_dev_info.wb;
+
+	return time_before(jiffies, wb->dirty_sleep + HZ);
+}
+
+static inline struct rq_wait *get_rq_wait(struct rq_wb *rwb, bool is_kswapd)
+{
+	return &rwb->rq_wait[is_kswapd];
+}
+
+static void rwb_wake_all(struct rq_wb *rwb)
+{
+	int i;
+
+	for (i = 0; i < WBT_NUM_RWQ; i++) {
+		struct rq_wait *rqw = &rwb->rq_wait[i];
+
+		if (waitqueue_active(&rqw->wait))
+			wake_up_all(&rqw->wait);
+	}
+}
+
+void __wbt_done(struct rq_wb *rwb, enum wbt_flags wb_acct)
+{
+	struct rq_wait *rqw;
+	int inflight, limit;
+
+	if (!(wb_acct & WBT_TRACKED))
+		return;
+
+	rqw = get_rq_wait(rwb, wb_acct & WBT_KSWAPD);
+	inflight = atomic_dec_return(&rqw->inflight);
+
+	/*
+	 * wbt got disabled with IO in flight. Wake up any potential
+	 * waiters, we don't have to do more than that.
+	 */
+	if (unlikely(!rwb_enabled(rwb))) {
+		rwb_wake_all(rwb);
+		return;
+	}
+
+	/*
+	 * If the device does write back caching, drop further down
+	 * before we wake people up.
+	 */
+	if (rwb->wc && !wb_recent_wait(rwb))
+		limit = 0;
+	else
+		limit = rwb->wb_normal;
+
+	/*
+	 * Don't wake anyone up if we are above the normal limit.
+	 */
+	if (inflight && inflight >= limit)
+		return;
+
+	if (waitqueue_active(&rqw->wait)) {
+		int diff = limit - inflight;
+
+		if (!inflight || diff >= rwb->wb_background / 2)
+			wake_up_all(&rqw->wait);
+	}
+}
+
+/*
+ * Called on completion of a request. Note that it's also called when
+ * a request is merged, when the request gets freed.
+ */
+void wbt_done(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+	if (!rwb)
+		return;
+
+	if (!wbt_is_tracked(stat)) {
+		if (rwb->sync_cookie == stat) {
+			rwb->sync_issue = 0;
+			rwb->sync_cookie = NULL;
+		}
+
+		if (wbt_is_read(stat))
+			wb_timestamp(rwb, &rwb->last_comp);
+		wbt_clear_state(stat);
+	} else {
+		WARN_ON_ONCE(stat == rwb->sync_cookie);
+		__wbt_done(rwb, wbt_stat_to_mask(stat));
+		wbt_clear_state(stat);
+	}
+}
+
+/*
+ * Return true, if we can't increase the depth further by scaling
+ */
+static bool calc_wb_limits(struct rq_wb *rwb)
+{
+	unsigned int depth;
+	bool ret = false;
+
+	if (!rwb->min_lat_nsec) {
+		rwb->wb_max = rwb->wb_normal = rwb->wb_background = 0;
+		return false;
+	}
+
+	/*
+	 * For QD=1 devices, this is a special case. It's important for those
+	 * to have one request ready when one completes, so force a depth of
+	 * 2 for those devices. On the backend, it'll be a depth of 1 anyway,
+	 * since the device can't have more than that in flight. If we're
+	 * scaling down, then keep a setting of 1/1/1.
+	 */
+	if (rwb->queue_depth == 1) {
+		if (rwb->scale_step > 0)
+			rwb->wb_max = rwb->wb_normal = 1;
+		else {
+			rwb->wb_max = rwb->wb_normal = 2;
+			ret = true;
+		}
+		rwb->wb_background = 1;
+	} else {
+		/*
+		 * scale_step == 0 is our default state. If we have suffered
+		 * latency spikes, step will be > 0, and we shrink the
+		 * allowed write depths. If step is < 0, we're only doing
+		 * writes, and we allow a temporarily higher depth to
+		 * increase performance.
+		 */
+		depth = min_t(unsigned int, RWB_DEF_DEPTH, rwb->queue_depth);
+		if (rwb->scale_step > 0)
+			depth = 1 + ((depth - 1) >> min(31, rwb->scale_step));
+		else if (rwb->scale_step < 0) {
+			unsigned int maxd = 3 * rwb->queue_depth / 4;
+
+			depth = 1 + ((depth - 1) << -rwb->scale_step);
+			if (depth > maxd) {
+				depth = maxd;
+				ret = true;
+			}
+		}
+
+		/*
+		 * Set our max/normal/bg queue depths based on how far
+		 * we have scaled down (->scale_step).
+		 */
+		rwb->wb_max = depth;
+		rwb->wb_normal = (rwb->wb_max + 1) / 2;
+		rwb->wb_background = (rwb->wb_max + 3) / 4;
+	}
+
+	return ret;
+}
+
+static inline bool stat_sample_valid(struct blk_rq_stat *stat)
+{
+	/*
+	 * We need at least one read sample, and a minimum of
+	 * RWB_MIN_WRITE_SAMPLES. We require some write samples to know
+	 * that it's writes impacting us, and not just some sole read on
+	 * a device that is in a lower power state.
+	 */
+	return stat[BLK_STAT_READ].nr_samples >= 1 &&
+		stat[BLK_STAT_WRITE].nr_samples >= RWB_MIN_WRITE_SAMPLES;
+}
+
+static u64 rwb_sync_issue_lat(struct rq_wb *rwb)
+{
+	u64 now, issue = ACCESS_ONCE(rwb->sync_issue);
+
+	if (!issue || !rwb->sync_cookie)
+		return 0;
+
+	now = ktime_to_ns(ktime_get());
+	return now - issue;
+}
+
+enum {
+	LAT_OK = 1,
+	LAT_UNKNOWN,
+	LAT_UNKNOWN_WRITES,
+	LAT_EXCEEDED,
+};
+
+static int __latency_exceeded(struct rq_wb *rwb, struct blk_rq_stat *stat)
+{
+	struct backing_dev_info *bdi = &rwb->queue->backing_dev_info;
+	u64 thislat;
+
+	/*
+	 * If our stored sync issue exceeds the window size, or it
+	 * exceeds our min target AND we haven't logged any entries,
+	 * flag the latency as exceeded. wbt works off completion latencies,
+	 * but for a flooded device, a single sync IO can take a long time
+	 * to complete after being issued. If this time exceeds our
+	 * monitoring window AND we didn't see any other completions in that
+	 * window, then count that sync IO as a violation of the latency.
+	 */
+	thislat = rwb_sync_issue_lat(rwb);
+	if (thislat > rwb->cur_win_nsec ||
+	    (thislat > rwb->min_lat_nsec && !stat[BLK_STAT_READ].nr_samples)) {
+		trace_wbt_lat(bdi, thislat);
+		return LAT_EXCEEDED;
+	}
+
+	/*
+	 * No read/write mix, if stat isn't valid
+	 */
+	if (!stat_sample_valid(stat)) {
+		/*
+		 * If we had writes in this stat window and the window is
+		 * current, we're only doing writes. If a task recently
+		 * waited or still has writes in flights, consider us doing
+		 * just writes as well.
+		 */
+		if ((stat[BLK_STAT_WRITE].nr_samples && blk_stat_is_current(stat)) ||
+		    wb_recent_wait(rwb) || wbt_inflight(rwb))
+			return LAT_UNKNOWN_WRITES;
+		return LAT_UNKNOWN;
+	}
+
+	/*
+	 * If the 'min' latency exceeds our target, step down.
+	 */
+	if (stat[BLK_STAT_READ].min > rwb->min_lat_nsec) {
+		trace_wbt_lat(bdi, stat[BLK_STAT_READ].min);
+		trace_wbt_stat(bdi, stat);
+		return LAT_EXCEEDED;
+	}
+
+	if (rwb->scale_step)
+		trace_wbt_stat(bdi, stat);
+
+	return LAT_OK;
+}
+
+static int latency_exceeded(struct rq_wb *rwb)
+{
+	struct blk_rq_stat stat[2];
+
+	blk_queue_stat_get(rwb->queue, stat);
+	return __latency_exceeded(rwb, stat);
+}
+
+static void rwb_trace_step(struct rq_wb *rwb, const char *msg)
+{
+	struct backing_dev_info *bdi = &rwb->queue->backing_dev_info;
+
+	trace_wbt_step(bdi, msg, rwb->scale_step, rwb->cur_win_nsec,
+			rwb->wb_background, rwb->wb_normal, rwb->wb_max);
+}
+
+static void scale_up(struct rq_wb *rwb)
+{
+	/*
+	 * Hit max in previous round, stop here
+	 */
+	if (rwb->scaled_max)
+		return;
+
+	rwb->scale_step--;
+	rwb->unknown_cnt = 0;
+	blk_stat_clear(rwb->queue);
+
+	rwb->scaled_max = calc_wb_limits(rwb);
+
+	rwb_wake_all(rwb);
+
+	rwb_trace_step(rwb, "step up");
+}
+
+/*
+ * Scale rwb down. If 'hard_throttle' is set, do it quicker, since we
+ * had a latency violation.
+ */
+static void scale_down(struct rq_wb *rwb, bool hard_throttle)
+{
+	/*
+	 * Stop scaling down when we've hit the limit. This also prevents
+	 * ->scale_step from going to crazy values, if the device can't
+	 * keep up.
+	 */
+	if (rwb->wb_max == 1)
+		return;
+
+	if (rwb->scale_step < 0 && hard_throttle)
+		rwb->scale_step = 0;
+	else
+		rwb->scale_step++;
+
+	rwb->scaled_max = false;
+	rwb->unknown_cnt = 0;
+	blk_stat_clear(rwb->queue);
+	calc_wb_limits(rwb);
+	rwb_trace_step(rwb, "step down");
+}
+
+static void rwb_arm_timer(struct rq_wb *rwb)
+{
+	unsigned long expires;
+
+	if (rwb->scale_step > 0) {
+		/*
+		 * We should speed this up, using some variant of a fast
+		 * integer inverse square root calculation. Since we only do
+		 * this for every window expiration, it's not a huge deal,
+		 * though.
+		 */
+		rwb->cur_win_nsec = div_u64(rwb->win_nsec << 4,
+					int_sqrt((rwb->scale_step + 1) << 8));
+	} else {
+		/*
+		 * For step < 0, we don't want to increase/decrease the
+		 * window size.
+		 */
+		rwb->cur_win_nsec = rwb->win_nsec;
+	}
+
+	expires = jiffies + nsecs_to_jiffies(rwb->cur_win_nsec);
+	mod_timer(&rwb->window_timer, expires);
+}
+
+static void wb_timer_fn(unsigned long data)
+{
+	struct rq_wb *rwb = (struct rq_wb *) data;
+	unsigned int inflight = wbt_inflight(rwb);
+	int status;
+
+	status = latency_exceeded(rwb);
+
+	trace_wbt_timer(&rwb->queue->backing_dev_info, status, rwb->scale_step,
+			inflight);
+
+	/*
+	 * If we exceeded the latency target, step down. If we did not,
+	 * step one level up. If we don't know enough to say either exceeded
+	 * or ok, then don't do anything.
+	 */
+	switch (status) {
+	case LAT_EXCEEDED:
+		scale_down(rwb, true);
+		break;
+	case LAT_OK:
+		scale_up(rwb);
+		break;
+	case LAT_UNKNOWN_WRITES:
+		/*
+		 * We started a the center step, but don't have a valid
+		 * read/write sample, but we do have writes going on.
+		 * Allow step to go negative, to increase write perf.
+		 */
+		scale_up(rwb);
+		break;
+	case LAT_UNKNOWN:
+		if (++rwb->unknown_cnt < RWB_UNKNOWN_BUMP)
+			break;
+		/*
+		 * We get here when previously scaled reduced depth, and we
+		 * currently don't have a valid read/write sample. For that
+		 * case, slowly return to center state (step == 0).
+		 */
+		if (rwb->scale_step > 0)
+			scale_up(rwb);
+		else if (rwb->scale_step < 0)
+			scale_down(rwb, false);
+		break;
+	default:
+		break;
+	}
+
+	/*
+	 * Re-arm timer, if we have IO in flight
+	 */
+	if (rwb->scale_step || inflight)
+		rwb_arm_timer(rwb);
+}
+
+void wbt_update_limits(struct rq_wb *rwb)
+{
+	rwb->scale_step = 0;
+	rwb->scaled_max = false;
+	calc_wb_limits(rwb);
+
+	rwb_wake_all(rwb);
+}
+
+static bool close_io(struct rq_wb *rwb)
+{
+	const unsigned long now = jiffies;
+
+	return time_before(now, rwb->last_issue + HZ / 10) ||
+		time_before(now, rwb->last_comp + HZ / 10);
+}
+
+#define REQ_HIPRIO	(REQ_SYNC | REQ_META | REQ_PRIO)
+
+static inline unsigned int get_limit(struct rq_wb *rwb, unsigned long rw)
+{
+	unsigned int limit;
+
+	/*
+	 * At this point we know it's a buffered write. If this is
+	 * kswapd trying to free memory, or REQ_SYNC is set, set, then
+	 * it's WB_SYNC_ALL writeback, and we'll use the max limit for
+	 * that. If the write is marked as a background write, then use
+	 * the idle limit, or go to normal if we haven't had competing
+	 * IO for a bit.
+	 */
+	if ((rw & REQ_HIPRIO) || wb_recent_wait(rwb) || current_is_kswapd())
+		limit = rwb->wb_max;
+	else if ((rw & REQ_BACKGROUND) || close_io(rwb)) {
+		/*
+		 * If less than 100ms since we completed unrelated IO,
+		 * limit us to half the depth for background writeback.
+		 */
+		limit = rwb->wb_background;
+	} else
+		limit = rwb->wb_normal;
+
+	return limit;
+}
+
+static inline bool may_queue(struct rq_wb *rwb, struct rq_wait *rqw,
+			     wait_queue_t *wait, unsigned long rw)
+{
+	/*
+	 * inc it here even if disabled, since we'll dec it at completion.
+	 * this only happens if the task was sleeping in __wbt_wait(),
+	 * and someone turned it off at the same time.
+	 */
+	if (!rwb_enabled(rwb)) {
+		atomic_inc(&rqw->inflight);
+		return true;
+	}
+
+	/*
+	 * If the waitqueue is already active and we are not the next
+	 * in line to be woken up, wait for our turn.
+	 */
+	if (waitqueue_active(&rqw->wait) &&
+	    rqw->wait.task_list.next != &wait->task_list)
+		return false;
+
+	return atomic_inc_below(&rqw->inflight, get_limit(rwb, rw));
+}
+
+/*
+ * Block if we will exceed our limit, or if we are currently waiting for
+ * the timer to kick off queuing again.
+ */
+static void __wbt_wait(struct rq_wb *rwb, unsigned long rw, spinlock_t *lock)
+	__releases(lock)
+	__acquires(lock)
+{
+	struct rq_wait *rqw = get_rq_wait(rwb, current_is_kswapd());
+	DEFINE_WAIT(wait);
+
+	if (may_queue(rwb, rqw, &wait, rw))
+		return;
+
+	do {
+		prepare_to_wait_exclusive(&rqw->wait, &wait,
+						TASK_UNINTERRUPTIBLE);
+
+		if (may_queue(rwb, rqw, &wait, rw))
+			break;
+
+		if (lock) {
+			spin_unlock_irq(lock);
+			io_schedule();
+			spin_lock_irq(lock);
+		} else
+			io_schedule();
+	} while (1);
+
+	finish_wait(&rqw->wait, &wait);
+}
+
+static inline bool wbt_should_throttle(struct rq_wb *rwb, struct bio *bio)
+{
+	const int op = bio_op(bio);
+
+	/*
+	 * If not a WRITE, do nothing
+	 */
+	if (op != REQ_OP_WRITE)
+		return false;
+
+	/*
+	 * Don't throttle WRITE_ODIRECT
+	 */
+	if ((bio->bi_opf & (REQ_SYNC | REQ_IDLE)) == (REQ_SYNC | REQ_IDLE))
+		return false;
+
+	return true;
+}
+
+/*
+ * Returns true if the IO request should be accounted, false if not.
+ * May sleep, if we have exceeded the writeback limits. Caller can pass
+ * in an irq held spinlock, if it holds one when calling this function.
+ * If we do sleep, we'll release and re-grab it.
+ */
+enum wbt_flags wbt_wait(struct rq_wb *rwb, struct bio *bio, spinlock_t *lock)
+{
+	unsigned int ret = 0;
+
+	if (!rwb_enabled(rwb))
+		return 0;
+
+	if (bio_op(bio) == REQ_OP_READ)
+		ret = WBT_READ;
+
+	if (!wbt_should_throttle(rwb, bio)) {
+		if (ret & WBT_READ)
+			wb_timestamp(rwb, &rwb->last_issue);
+		return ret;
+	}
+
+	__wbt_wait(rwb, bio->bi_opf, lock);
+
+	if (!timer_pending(&rwb->window_timer))
+		rwb_arm_timer(rwb);
+
+	if (current_is_kswapd())
+		ret |= WBT_KSWAPD;
+
+	return ret | WBT_TRACKED;
+}
+
+void wbt_issue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+	if (!rwb_enabled(rwb))
+		return;
+
+	/*
+	 * Track sync issue, in case it takes a long time to complete. Allows
+	 * us to react quicker, if a sync IO takes a long time to complete.
+	 * Note that this is just a hint. 'stat' can go away when the
+	 * request completes, so it's important we never dereference it. We
+	 * only use the address to compare with, which is why we store the
+	 * sync_issue time locally.
+	 */
+	if (wbt_is_read(stat) && !rwb->sync_issue) {
+		rwb->sync_cookie = stat;
+		rwb->sync_issue = blk_stat_time(stat);
+	}
+}
+
+void wbt_requeue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+	if (!rwb_enabled(rwb))
+		return;
+	if (stat == rwb->sync_cookie) {
+		rwb->sync_issue = 0;
+		rwb->sync_cookie = NULL;
+	}
+}
+
+void wbt_set_queue_depth(struct rq_wb *rwb, unsigned int depth)
+{
+	if (rwb) {
+		rwb->queue_depth = depth;
+		wbt_update_limits(rwb);
+	}
+}
+
+void wbt_set_write_cache(struct rq_wb *rwb, bool write_cache_on)
+{
+	if (rwb)
+		rwb->wc = write_cache_on;
+}
+
+ /*
+ * Disable wbt, if enabled by default. Only called from CFQ, if we have
+ * cgroups enabled
+ */
+void wbt_disable_default(struct request_queue *q)
+{
+	struct rq_wb *rwb = q->rq_wb;
+
+	if (rwb && rwb->enable_state == WBT_STATE_ON_DEFAULT) {
+		del_timer_sync(&rwb->window_timer);
+		rwb->win_nsec = rwb->min_lat_nsec = 0;
+		wbt_update_limits(rwb);
+	}
+}
+EXPORT_SYMBOL_GPL(wbt_disable_default);
+
+u64 wbt_default_latency_nsec(struct request_queue *q)
+{
+	/*
+	 * We default to 2msec for non-rotational storage, and 75msec
+	 * for rotational storage.
+	 */
+	if (blk_queue_nonrot(q))
+		return 2000000ULL;
+	else
+		return 75000000ULL;
+}
+
+int wbt_init(struct request_queue *q)
+{
+	struct rq_wb *rwb;
+	int i;
+
+	/*
+	 * For now, we depend on the stats window being larger than
+	 * our monitoring window. Ensure that this isn't inadvertently
+	 * violated.
+	 */
+	BUILD_BUG_ON(RWB_WINDOW_NSEC > BLK_STAT_NSEC);
+	BUILD_BUG_ON(WBT_NR_BITS > BLK_STAT_RES_BITS);
+
+	rwb = kzalloc(sizeof(*rwb), GFP_KERNEL);
+	if (!rwb)
+		return -ENOMEM;
+
+	for (i = 0; i < WBT_NUM_RWQ; i++) {
+		atomic_set(&rwb->rq_wait[i].inflight, 0);
+		init_waitqueue_head(&rwb->rq_wait[i].wait);
+	}
+
+	setup_timer(&rwb->window_timer, wb_timer_fn, (unsigned long) rwb);
+	rwb->wc = 1;
+	rwb->queue_depth = RWB_DEF_DEPTH;
+	rwb->last_comp = rwb->last_issue = jiffies;
+	rwb->queue = q;
+	rwb->win_nsec = RWB_WINDOW_NSEC;
+	rwb->enable_state = WBT_STATE_ON_DEFAULT;
+	wbt_update_limits(rwb);
+
+	/*
+	 * Assign rwb, and turn on stats tracking for this queue
+	 */
+	q->rq_wb = rwb;
+	blk_stat_enable(q);
+
+	rwb->min_lat_nsec = wbt_default_latency_nsec(q);
+
+	wbt_set_queue_depth(rwb, blk_queue_depth(q));
+	wbt_set_write_cache(rwb, test_bit(QUEUE_FLAG_WC, &q->queue_flags));
+
+	return 0;
+}
+
+void wbt_exit(struct request_queue *q)
+{
+	struct rq_wb *rwb = q->rq_wb;
+
+	if (rwb) {
+		del_timer_sync(&rwb->window_timer);
+		q->rq_wb = NULL;
+		kfree(rwb);
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-wbt.h linux-libre-4.10-rc8-gnu/block/blk-wbt.h
--- linux-libre-4.9-gnu/block/blk-wbt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-wbt.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,171 @@
+#ifndef WB_THROTTLE_H
+#define WB_THROTTLE_H
+
+#include <linux/kernel.h>
+#include <linux/atomic.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+#include <linux/ktime.h>
+
+#include "blk-stat.h"
+
+enum wbt_flags {
+	WBT_TRACKED		= 1,	/* write, tracked for throttling */
+	WBT_READ		= 2,	/* read */
+	WBT_KSWAPD		= 4,	/* write, from kswapd */
+
+	WBT_NR_BITS		= 3,	/* number of bits */
+};
+
+enum {
+	WBT_NUM_RWQ		= 2,
+};
+
+/*
+ * Enable states. Either off, or on by default (done at init time),
+ * or on through manual setup in sysfs.
+ */
+enum {
+	WBT_STATE_ON_DEFAULT	= 1,
+	WBT_STATE_ON_MANUAL	= 2,
+};
+
+static inline void wbt_clear_state(struct blk_issue_stat *stat)
+{
+	stat->time &= BLK_STAT_TIME_MASK;
+}
+
+static inline enum wbt_flags wbt_stat_to_mask(struct blk_issue_stat *stat)
+{
+	return (stat->time & BLK_STAT_MASK) >> BLK_STAT_SHIFT;
+}
+
+static inline void wbt_track(struct blk_issue_stat *stat, enum wbt_flags wb_acct)
+{
+	stat->time |= ((u64) wb_acct) << BLK_STAT_SHIFT;
+}
+
+static inline bool wbt_is_tracked(struct blk_issue_stat *stat)
+{
+	return (stat->time >> BLK_STAT_SHIFT) & WBT_TRACKED;
+}
+
+static inline bool wbt_is_read(struct blk_issue_stat *stat)
+{
+	return (stat->time >> BLK_STAT_SHIFT) & WBT_READ;
+}
+
+struct rq_wait {
+	wait_queue_head_t wait;
+	atomic_t inflight;
+};
+
+struct rq_wb {
+	/*
+	 * Settings that govern how we throttle
+	 */
+	unsigned int wb_background;		/* background writeback */
+	unsigned int wb_normal;			/* normal writeback */
+	unsigned int wb_max;			/* max throughput writeback */
+	int scale_step;
+	bool scaled_max;
+
+	short enable_state;			/* WBT_STATE_* */
+
+	/*
+	 * Number of consecutive periods where we don't have enough
+	 * information to make a firm scale up/down decision.
+	 */
+	unsigned int unknown_cnt;
+
+	u64 win_nsec;				/* default window size */
+	u64 cur_win_nsec;			/* current window size */
+
+	struct timer_list window_timer;
+
+	s64 sync_issue;
+	void *sync_cookie;
+
+	unsigned int wc;
+	unsigned int queue_depth;
+
+	unsigned long last_issue;		/* last non-throttled issue */
+	unsigned long last_comp;		/* last non-throttled comp */
+	unsigned long min_lat_nsec;
+	struct request_queue *queue;
+	struct rq_wait rq_wait[WBT_NUM_RWQ];
+};
+
+static inline unsigned int wbt_inflight(struct rq_wb *rwb)
+{
+	unsigned int i, ret = 0;
+
+	for (i = 0; i < WBT_NUM_RWQ; i++)
+		ret += atomic_read(&rwb->rq_wait[i].inflight);
+
+	return ret;
+}
+
+#ifdef CONFIG_BLK_WBT
+
+void __wbt_done(struct rq_wb *, enum wbt_flags);
+void wbt_done(struct rq_wb *, struct blk_issue_stat *);
+enum wbt_flags wbt_wait(struct rq_wb *, struct bio *, spinlock_t *);
+int wbt_init(struct request_queue *);
+void wbt_exit(struct request_queue *);
+void wbt_update_limits(struct rq_wb *);
+void wbt_requeue(struct rq_wb *, struct blk_issue_stat *);
+void wbt_issue(struct rq_wb *, struct blk_issue_stat *);
+void wbt_disable_default(struct request_queue *);
+
+void wbt_set_queue_depth(struct rq_wb *, unsigned int);
+void wbt_set_write_cache(struct rq_wb *, bool);
+
+u64 wbt_default_latency_nsec(struct request_queue *);
+
+#else
+
+static inline void __wbt_done(struct rq_wb *rwb, enum wbt_flags flags)
+{
+}
+static inline void wbt_done(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+}
+static inline enum wbt_flags wbt_wait(struct rq_wb *rwb, struct bio *bio,
+				      spinlock_t *lock)
+{
+	return 0;
+}
+static inline int wbt_init(struct request_queue *q)
+{
+	return -EINVAL;
+}
+static inline void wbt_exit(struct request_queue *q)
+{
+}
+static inline void wbt_update_limits(struct rq_wb *rwb)
+{
+}
+static inline void wbt_requeue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+}
+static inline void wbt_issue(struct rq_wb *rwb, struct blk_issue_stat *stat)
+{
+}
+static inline void wbt_disable_default(struct request_queue *q)
+{
+}
+static inline void wbt_set_queue_depth(struct rq_wb *rwb, unsigned int depth)
+{
+}
+static inline void wbt_set_write_cache(struct rq_wb *rwb, bool wc)
+{
+}
+static inline u64 wbt_default_latency_nsec(struct request_queue *q)
+{
+	return 0;
+}
+
+#endif /* CONFIG_BLK_WBT */
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/block/blk-zoned.c linux-libre-4.10-rc8-gnu/block/blk-zoned.c
--- linux-libre-4.9-gnu/block/blk-zoned.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/blk-zoned.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,348 @@
+/*
+ * Zoned block device handling
+ *
+ * Copyright (c) 2015, Hannes Reinecke
+ * Copyright (c) 2015, SUSE Linux GmbH
+ *
+ * Copyright (c) 2016, Damien Le Moal
+ * Copyright (c) 2016, Western Digital
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rbtree.h>
+#include <linux/blkdev.h>
+
+static inline sector_t blk_zone_start(struct request_queue *q,
+				      sector_t sector)
+{
+	sector_t zone_mask = blk_queue_zone_sectors(q) - 1;
+
+	return sector & ~zone_mask;
+}
+
+/*
+ * Check that a zone report belongs to the partition.
+ * If yes, fix its start sector and write pointer, copy it in the
+ * zone information array and return true. Return false otherwise.
+ */
+static bool blkdev_report_zone(struct block_device *bdev,
+			       struct blk_zone *rep,
+			       struct blk_zone *zone)
+{
+	sector_t offset = get_start_sect(bdev);
+
+	if (rep->start < offset)
+		return false;
+
+	rep->start -= offset;
+	if (rep->start + rep->len > bdev->bd_part->nr_sects)
+		return false;
+
+	if (rep->type == BLK_ZONE_TYPE_CONVENTIONAL)
+		rep->wp = rep->start + rep->len;
+	else
+		rep->wp -= offset;
+	memcpy(zone, rep, sizeof(struct blk_zone));
+
+	return true;
+}
+
+/**
+ * blkdev_report_zones - Get zones information
+ * @bdev:	Target block device
+ * @sector:	Sector from which to report zones
+ * @zones:	Array of zone structures where to return the zones information
+ * @nr_zones:	Number of zone structures in the zone array
+ * @gfp_mask:	Memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ *    Get zone information starting from the zone containing @sector.
+ *    The number of zone information reported may be less than the number
+ *    requested by @nr_zones. The number of zones actually reported is
+ *    returned in @nr_zones.
+ */
+int blkdev_report_zones(struct block_device *bdev,
+			sector_t sector,
+			struct blk_zone *zones,
+			unsigned int *nr_zones,
+			gfp_t gfp_mask)
+{
+	struct request_queue *q = bdev_get_queue(bdev);
+	struct blk_zone_report_hdr *hdr;
+	unsigned int nrz = *nr_zones;
+	struct page *page;
+	unsigned int nr_rep;
+	size_t rep_bytes;
+	unsigned int nr_pages;
+	struct bio *bio;
+	struct bio_vec *bv;
+	unsigned int i, n, nz;
+	unsigned int ofst;
+	void *addr;
+	int ret;
+
+	if (!q)
+		return -ENXIO;
+
+	if (!blk_queue_is_zoned(q))
+		return -EOPNOTSUPP;
+
+	if (!nrz)
+		return 0;
+
+	if (sector > bdev->bd_part->nr_sects) {
+		*nr_zones = 0;
+		return 0;
+	}
+
+	/*
+	 * The zone report has a header. So make room for it in the
+	 * payload. Also make sure that the report fits in a single BIO
+	 * that will not be split down the stack.
+	 */
+	rep_bytes = sizeof(struct blk_zone_report_hdr) +
+		sizeof(struct blk_zone) * nrz;
+	rep_bytes = (rep_bytes + PAGE_SIZE - 1) & PAGE_MASK;
+	if (rep_bytes > (queue_max_sectors(q) << 9))
+		rep_bytes = queue_max_sectors(q) << 9;
+
+	nr_pages = min_t(unsigned int, BIO_MAX_PAGES,
+			 rep_bytes >> PAGE_SHIFT);
+	nr_pages = min_t(unsigned int, nr_pages,
+			 queue_max_segments(q));
+
+	bio = bio_alloc(gfp_mask, nr_pages);
+	if (!bio)
+		return -ENOMEM;
+
+	bio->bi_bdev = bdev;
+	bio->bi_iter.bi_sector = blk_zone_start(q, sector);
+	bio_set_op_attrs(bio, REQ_OP_ZONE_REPORT, 0);
+
+	for (i = 0; i < nr_pages; i++) {
+		page = alloc_page(gfp_mask);
+		if (!page) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		if (!bio_add_page(bio, page, PAGE_SIZE, 0)) {
+			__free_page(page);
+			break;
+		}
+	}
+
+	if (i == 0)
+		ret = -ENOMEM;
+	else
+		ret = submit_bio_wait(bio);
+	if (ret)
+		goto out;
+
+	/*
+	 * Process the report result: skip the header and go through the
+	 * reported zones to fixup and fixup the zone information for
+	 * partitions. At the same time, return the zone information into
+	 * the zone array.
+	 */
+	n = 0;
+	nz = 0;
+	nr_rep = 0;
+	bio_for_each_segment_all(bv, bio, i) {
+
+		if (!bv->bv_page)
+			break;
+
+		addr = kmap_atomic(bv->bv_page);
+
+		/* Get header in the first page */
+		ofst = 0;
+		if (!nr_rep) {
+			hdr = (struct blk_zone_report_hdr *) addr;
+			nr_rep = hdr->nr_zones;
+			ofst = sizeof(struct blk_zone_report_hdr);
+		}
+
+		/* Fixup and report zones */
+		while (ofst < bv->bv_len &&
+		       n < nr_rep && nz < nrz) {
+			if (blkdev_report_zone(bdev, addr + ofst, &zones[nz]))
+				nz++;
+			ofst += sizeof(struct blk_zone);
+			n++;
+		}
+
+		kunmap_atomic(addr);
+
+		if (n >= nr_rep || nz >= nrz)
+			break;
+
+	}
+
+	*nr_zones = nz;
+out:
+	bio_for_each_segment_all(bv, bio, i)
+		__free_page(bv->bv_page);
+	bio_put(bio);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(blkdev_report_zones);
+
+/**
+ * blkdev_reset_zones - Reset zones write pointer
+ * @bdev:	Target block device
+ * @sector:	Start sector of the first zone to reset
+ * @nr_sectors:	Number of sectors, at least the length of one zone
+ * @gfp_mask:	Memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ *    Reset the write pointer of the zones contained in the range
+ *    @sector..@sector+@nr_sectors. Specifying the entire disk sector range
+ *    is valid, but the specified range should not contain conventional zones.
+ */
+int blkdev_reset_zones(struct block_device *bdev,
+		       sector_t sector, sector_t nr_sectors,
+		       gfp_t gfp_mask)
+{
+	struct request_queue *q = bdev_get_queue(bdev);
+	sector_t zone_sectors;
+	sector_t end_sector = sector + nr_sectors;
+	struct bio *bio;
+	int ret;
+
+	if (!q)
+		return -ENXIO;
+
+	if (!blk_queue_is_zoned(q))
+		return -EOPNOTSUPP;
+
+	if (end_sector > bdev->bd_part->nr_sects)
+		/* Out of range */
+		return -EINVAL;
+
+	/* Check alignment (handle eventual smaller last zone) */
+	zone_sectors = blk_queue_zone_sectors(q);
+	if (sector & (zone_sectors - 1))
+		return -EINVAL;
+
+	if ((nr_sectors & (zone_sectors - 1)) &&
+	    end_sector != bdev->bd_part->nr_sects)
+		return -EINVAL;
+
+	while (sector < end_sector) {
+
+		bio = bio_alloc(gfp_mask, 0);
+		bio->bi_iter.bi_sector = sector;
+		bio->bi_bdev = bdev;
+		bio_set_op_attrs(bio, REQ_OP_ZONE_RESET, 0);
+
+		ret = submit_bio_wait(bio);
+		bio_put(bio);
+
+		if (ret)
+			return ret;
+
+		sector += zone_sectors;
+
+		/* This may take a while, so be nice to others */
+		cond_resched();
+
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blkdev_reset_zones);
+
+/**
+ * BLKREPORTZONE ioctl processing.
+ * Called from blkdev_ioctl.
+ */
+int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
+			      unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	struct request_queue *q;
+	struct blk_zone_report rep;
+	struct blk_zone *zones;
+	int ret;
+
+	if (!argp)
+		return -EINVAL;
+
+	q = bdev_get_queue(bdev);
+	if (!q)
+		return -ENXIO;
+
+	if (!blk_queue_is_zoned(q))
+		return -ENOTTY;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (copy_from_user(&rep, argp, sizeof(struct blk_zone_report)))
+		return -EFAULT;
+
+	if (!rep.nr_zones)
+		return -EINVAL;
+
+	zones = kcalloc(rep.nr_zones, sizeof(struct blk_zone), GFP_KERNEL);
+	if (!zones)
+		return -ENOMEM;
+
+	ret = blkdev_report_zones(bdev, rep.sector,
+				  zones, &rep.nr_zones,
+				  GFP_KERNEL);
+	if (ret)
+		goto out;
+
+	if (copy_to_user(argp, &rep, sizeof(struct blk_zone_report))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (rep.nr_zones) {
+		if (copy_to_user(argp + sizeof(struct blk_zone_report), zones,
+				 sizeof(struct blk_zone) * rep.nr_zones))
+			ret = -EFAULT;
+	}
+
+ out:
+	kfree(zones);
+
+	return ret;
+}
+
+/**
+ * BLKRESETZONE ioctl processing.
+ * Called from blkdev_ioctl.
+ */
+int blkdev_reset_zones_ioctl(struct block_device *bdev, fmode_t mode,
+			     unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	struct request_queue *q;
+	struct blk_zone_range zrange;
+
+	if (!argp)
+		return -EINVAL;
+
+	q = bdev_get_queue(bdev);
+	if (!q)
+		return -ENXIO;
+
+	if (!blk_queue_is_zoned(q))
+		return -ENOTTY;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (!(mode & FMODE_WRITE))
+		return -EBADF;
+
+	if (copy_from_user(&zrange, argp, sizeof(struct blk_zone_range)))
+		return -EFAULT;
+
+	return blkdev_reset_zones(bdev, zrange.sector, zrange.nr_sectors,
+				  GFP_KERNEL);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/block/bsg.c linux-libre-4.10-rc8-gnu/block/bsg.c
--- linux-libre-4.9-gnu/block/bsg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/bsg.c	2017-02-12 16:03:20.000000000 -0500
@@ -176,7 +176,7 @@ static int blk_fill_sgv4_hdr_rq(struct r
  * Check if sg_io_v4 from user is allowed and valid
  */
 static int
-bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
+bsg_validate_sgv4_hdr(struct sg_io_v4 *hdr, int *rw)
 {
 	int ret = 0;
 
@@ -226,7 +226,7 @@ bsg_map_hdr(struct bsg_device *bd, struc
 		hdr->dout_xfer_len, (unsigned long long) hdr->din_xferp,
 		hdr->din_xfer_len);
 
-	ret = bsg_validate_sgv4_hdr(q, hdr, &rw);
+	ret = bsg_validate_sgv4_hdr(hdr, &rw);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -655,6 +655,9 @@ bsg_write(struct file *file, const char
 
 	dprintk("%s: write %Zd bytes\n", bd->name, count);
 
+	if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+		return -EINVAL;
+
 	bsg_set_block(bd, file);
 
 	bytes_written = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/block/bsg-lib.c linux-libre-4.10-rc8-gnu/block/bsg-lib.c
--- linux-libre-4.9-gnu/block/bsg-lib.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/bsg-lib.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,8 +32,13 @@
  * bsg_destroy_job - routine to teardown/delete a bsg job
  * @job: bsg_job that is to be torn down
  */
-static void bsg_destroy_job(struct bsg_job *job)
+static void bsg_destroy_job(struct kref *kref)
 {
+	struct bsg_job *job = container_of(kref, struct bsg_job, kref);
+	struct request *rq = job->req;
+
+	blk_end_request_all(rq, rq->errors);
+
 	put_device(job->dev);	/* release reference for the request */
 
 	kfree(job->request_payload.sg_list);
@@ -41,6 +46,18 @@ static void bsg_destroy_job(struct bsg_j
 	kfree(job);
 }
 
+void bsg_job_put(struct bsg_job *job)
+{
+	kref_put(&job->kref, bsg_destroy_job);
+}
+EXPORT_SYMBOL_GPL(bsg_job_put);
+
+int bsg_job_get(struct bsg_job *job)
+{
+	return kref_get_unless_zero(&job->kref);
+}
+EXPORT_SYMBOL_GPL(bsg_job_get);
+
 /**
  * bsg_job_done - completion routine for bsg requests
  * @job: bsg_job that is complete
@@ -83,8 +100,7 @@ static void bsg_softirq_done(struct requ
 {
 	struct bsg_job *job = rq->special;
 
-	blk_end_request_all(rq, rq->errors);
-	bsg_destroy_job(job);
+	bsg_job_put(job);
 }
 
 static int bsg_map_buffer(struct bsg_buffer *buf, struct request *req)
@@ -142,6 +158,7 @@ static int bsg_create_job(struct device
 	job->dev = dev;
 	/* take a reference for the request */
 	get_device(job->dev);
+	kref_init(&job->kref);
 	return 0;
 
 failjob_rls_rqst_payload:
@@ -161,6 +178,8 @@ failjob_rls_job:
  * Drivers/subsys should pass this to the queue init function.
  */
 void bsg_request_fn(struct request_queue *q)
+	__releases(q->queue_lock)
+	__acquires(q->queue_lock)
 {
 	struct device *dev = q->queuedata;
 	struct request *req;
diff -druNp --no-dereference linux-libre-4.9-gnu/block/cfq-iosched.c linux-libre-4.10-rc8-gnu/block/cfq-iosched.c
--- linux-libre-4.9-gnu/block/cfq-iosched.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/cfq-iosched.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/blktrace_api.h>
 #include <linux/blk-cgroup.h>
 #include "blk.h"
+#include "blk-wbt.h"
 
 /*
  * tunables
@@ -667,10 +668,10 @@ static inline void cfqg_put(struct cfq_g
 } while (0)
 
 static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg,
-					    struct cfq_group *curr_cfqg, int op,
-					    int op_flags)
+					    struct cfq_group *curr_cfqg,
+					    unsigned int op)
 {
-	blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, 1);
+	blkg_rwstat_add(&cfqg->stats.queued, op, 1);
 	cfqg_stats_end_empty_time(&cfqg->stats);
 	cfqg_stats_set_start_group_wait_time(cfqg, curr_cfqg);
 }
@@ -684,30 +685,29 @@ static inline void cfqg_stats_update_tim
 #endif
 }
 
-static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op,
-					       int op_flags)
+static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg,
+					       unsigned int op)
 {
-	blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, -1);
+	blkg_rwstat_add(&cfqg->stats.queued, op, -1);
 }
 
-static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op,
-					       int op_flags)
+static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg,
+					       unsigned int op)
 {
-	blkg_rwstat_add(&cfqg->stats.merged, op, op_flags, 1);
+	blkg_rwstat_add(&cfqg->stats.merged, op, 1);
 }
 
 static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,
-			uint64_t start_time, uint64_t io_start_time, int op,
-			int op_flags)
+			uint64_t start_time, uint64_t io_start_time,
+			unsigned int op)
 {
 	struct cfqg_stats *stats = &cfqg->stats;
 	unsigned long long now = sched_clock();
 
 	if (time_after64(now, io_start_time))
-		blkg_rwstat_add(&stats->service_time, op, op_flags,
-				now - io_start_time);
+		blkg_rwstat_add(&stats->service_time, op, now - io_start_time);
 	if (time_after64(io_start_time, start_time))
-		blkg_rwstat_add(&stats->wait_time, op, op_flags,
+		blkg_rwstat_add(&stats->wait_time, op,
 				io_start_time - start_time);
 }
 
@@ -786,16 +786,16 @@ static inline void cfqg_put(struct cfq_g
 #define cfq_log_cfqg(cfqd, cfqg, fmt, args...)		do {} while (0)
 
 static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg,
-			struct cfq_group *curr_cfqg, int op, int op_flags) { }
+			struct cfq_group *curr_cfqg, unsigned int op) { }
 static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg,
 			uint64_t time, unsigned long unaccounted_time) { }
-static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op,
-			int op_flags) { }
-static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op,
-			int op_flags) { }
+static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg,
+			unsigned int op) { }
+static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg,
+			unsigned int op) { }
 static inline void cfqg_stats_update_completion(struct cfq_group *cfqg,
-			uint64_t start_time, uint64_t io_start_time, int op,
-			int op_flags) { }
+			uint64_t start_time, uint64_t io_start_time,
+			unsigned int op) { }
 
 #endif	/* CONFIG_CFQ_GROUP_IOSCHED */
 
@@ -913,15 +913,6 @@ static inline struct cfq_data *cic_to_cf
 }
 
 /*
- * We regard a request as SYNC, if it's either a read or has the SYNC bit
- * set (in which case it could also be direct WRITE).
- */
-static inline bool cfq_bio_sync(struct bio *bio)
-{
-	return bio_data_dir(bio) == READ || (bio->bi_opf & REQ_SYNC);
-}
-
-/*
  * scheduler run of queue, if there are requests pending and no one in the
  * driver that will restart queueing
  */
@@ -1596,7 +1587,7 @@ static struct blkcg_policy_data *cfq_cpd
 {
 	struct cfq_group_data *cgd;
 
-	cgd = kzalloc(sizeof(*cgd), GFP_KERNEL);
+	cgd = kzalloc(sizeof(*cgd), gfp);
 	if (!cgd)
 		return NULL;
 	return &cgd->cpd;
@@ -2474,10 +2465,10 @@ static void cfq_reposition_rq_rb(struct
 {
 	elv_rb_del(&cfqq->sort_list, rq);
 	cfqq->queued[rq_is_sync(rq)]--;
-	cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags);
+	cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags);
 	cfq_add_rq_rb(rq);
 	cfqg_stats_update_io_add(RQ_CFQG(rq), cfqq->cfqd->serving_group,
-				 req_op(rq), rq->cmd_flags);
+				 rq->cmd_flags);
 }
 
 static struct request *
@@ -2491,7 +2482,7 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd
 	if (!cic)
 		return NULL;
 
-	cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
+	cfqq = cic_to_cfqq(cic, op_is_sync(bio->bi_opf));
 	if (cfqq)
 		return elv_rb_find(&cfqq->sort_list, bio_end_sector(bio));
 
@@ -2530,7 +2521,7 @@ static void cfq_remove_request(struct re
 	cfq_del_rq_rb(rq);
 
 	cfqq->cfqd->rq_queued--;
-	cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags);
+	cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags);
 	if (rq->cmd_flags & REQ_PRIO) {
 		WARN_ON(!cfqq->prio_pending);
 		cfqq->prio_pending--;
@@ -2565,7 +2556,7 @@ static void cfq_merged_request(struct re
 static void cfq_bio_merged(struct request_queue *q, struct request *req,
 				struct bio *bio)
 {
-	cfqg_stats_update_io_merged(RQ_CFQG(req), bio_op(bio), bio->bi_opf);
+	cfqg_stats_update_io_merged(RQ_CFQG(req), bio->bi_opf);
 }
 
 static void
@@ -2588,7 +2579,7 @@ cfq_merged_requests(struct request_queue
 	if (cfqq->next_rq == next)
 		cfqq->next_rq = rq;
 	cfq_remove_request(next);
-	cfqg_stats_update_io_merged(RQ_CFQG(rq), req_op(next), next->cmd_flags);
+	cfqg_stats_update_io_merged(RQ_CFQG(rq), next->cmd_flags);
 
 	cfqq = RQ_CFQQ(next);
 	/*
@@ -2605,13 +2596,14 @@ static int cfq_allow_bio_merge(struct re
 			       struct bio *bio)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
+	bool is_sync = op_is_sync(bio->bi_opf);
 	struct cfq_io_cq *cic;
 	struct cfq_queue *cfqq;
 
 	/*
 	 * Disallow merge of a sync bio into an async request.
 	 */
-	if (cfq_bio_sync(bio) && !rq_is_sync(rq))
+	if (is_sync && !rq_is_sync(rq))
 		return false;
 
 	/*
@@ -2622,7 +2614,7 @@ static int cfq_allow_bio_merge(struct re
 	if (!cic)
 		return false;
 
-	cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
+	cfqq = cic_to_cfqq(cic, is_sync);
 	return cfqq == RQ_CFQQ(rq);
 }
 
@@ -3771,9 +3763,11 @@ static void check_blkcg_changed(struct c
 	struct cfq_data *cfqd = cic_to_cfqd(cic);
 	struct cfq_queue *cfqq;
 	uint64_t serial_nr;
+	bool nonroot_cg;
 
 	rcu_read_lock();
 	serial_nr = bio_blkcg(bio)->css.serial_nr;
+	nonroot_cg = bio_blkcg(bio) != &blkcg_root;
 	rcu_read_unlock();
 
 	/*
@@ -3784,6 +3778,14 @@ static void check_blkcg_changed(struct c
 		return;
 
 	/*
+	 * If we have a non-root cgroup, we can depend on that to
+	 * do proper throttling of writes. Turn off wbt for that
+	 * case, if it was enabled by default.
+	 */
+	if (nonroot_cg)
+		wbt_disable_default(cfqd->queue);
+
+	/*
 	 * Drop reference to queues.  New queues will be assigned in new
 	 * group upon arrival of fresh requests.
 	 */
@@ -3854,7 +3856,8 @@ cfq_get_queue(struct cfq_data *cfqd, boo
 			goto out;
 	}
 
-	cfqq = kmem_cache_alloc_node(cfq_pool, GFP_NOWAIT | __GFP_ZERO,
+	cfqq = kmem_cache_alloc_node(cfq_pool,
+				     GFP_NOWAIT | __GFP_ZERO | __GFP_NOWARN,
 				     cfqd->queue->node);
 	if (!cfqq) {
 		cfqq = &cfqd->oom_cfqq;
@@ -3923,6 +3926,12 @@ cfq_update_io_seektime(struct cfq_data *
 		cfqq->seek_history |= (sdist > CFQQ_SEEK_THR);
 }
 
+static inline bool req_noidle(struct request *req)
+{
+	return req_op(req) == REQ_OP_WRITE &&
+		(req->cmd_flags & (REQ_SYNC | REQ_IDLE)) == REQ_SYNC;
+}
+
 /*
  * Disable idle window if the process thinks too long or seeks so much that
  * it doesn't matter
@@ -3944,7 +3953,7 @@ cfq_update_idle_window(struct cfq_data *
 	if (cfqq->queued[0] + cfqq->queued[1] >= 4)
 		cfq_mark_cfqq_deep(cfqq);
 
-	if (cfqq->next_rq && (cfqq->next_rq->cmd_flags & REQ_NOIDLE))
+	if (cfqq->next_rq && req_noidle(cfqq->next_rq))
 		enable_idle = 0;
 	else if (!atomic_read(&cic->icq.ioc->active_ref) ||
 		 !cfqd->cfq_slice_idle ||
@@ -4142,7 +4151,7 @@ static void cfq_insert_request(struct re
 	rq->fifo_time = ktime_get_ns() + cfqd->cfq_fifo_expire[rq_is_sync(rq)];
 	list_add_tail(&rq->queuelist, &cfqq->fifo);
 	cfq_add_rq_rb(rq);
-	cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group, req_op(rq),
+	cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group,
 				 rq->cmd_flags);
 	cfq_rq_enqueued(cfqd, cfqq, rq);
 }
@@ -4229,8 +4238,7 @@ static void cfq_completed_request(struct
 	const int sync = rq_is_sync(rq);
 	u64 now = ktime_get_ns();
 
-	cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d",
-		     !!(rq->cmd_flags & REQ_NOIDLE));
+	cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", req_noidle(rq));
 
 	cfq_update_hw_tag(cfqd);
 
@@ -4240,8 +4248,7 @@ static void cfq_completed_request(struct
 	cfqq->dispatched--;
 	(RQ_CFQG(rq))->dispatched--;
 	cfqg_stats_update_completion(cfqq->cfqg, rq_start_time_ns(rq),
-				     rq_io_start_time_ns(rq), req_op(rq),
-				     rq->cmd_flags);
+				     rq_io_start_time_ns(rq), rq->cmd_flags);
 
 	cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--;
 
@@ -4319,14 +4326,14 @@ static void cfq_completed_request(struct
 		cfq_schedule_dispatch(cfqd);
 }
 
-static void cfqq_boost_on_prio(struct cfq_queue *cfqq, int op_flags)
+static void cfqq_boost_on_prio(struct cfq_queue *cfqq, unsigned int op)
 {
 	/*
 	 * If REQ_PRIO is set, boost class and prio level, if it's below
 	 * BE/NORM. If prio is not set, restore the potentially boosted
 	 * class/prio level.
 	 */
-	if (!(op_flags & REQ_PRIO)) {
+	if (!(op & REQ_PRIO)) {
 		cfqq->ioprio_class = cfqq->org_ioprio_class;
 		cfqq->ioprio = cfqq->org_ioprio;
 	} else {
@@ -4347,7 +4354,7 @@ static inline int __cfq_may_queue(struct
 	return ELV_MQUEUE_MAY;
 }
 
-static int cfq_may_queue(struct request_queue *q, int op, int op_flags)
+static int cfq_may_queue(struct request_queue *q, unsigned int op)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct task_struct *tsk = current;
@@ -4364,10 +4371,10 @@ static int cfq_may_queue(struct request_
 	if (!cic)
 		return ELV_MQUEUE_MAY;
 
-	cfqq = cic_to_cfqq(cic, rw_is_sync(op, op_flags));
+	cfqq = cic_to_cfqq(cic, op_is_sync(op));
 	if (cfqq) {
 		cfq_init_prio_data(cfqq, cic);
-		cfqq_boost_on_prio(cfqq, op_flags);
+		cfqq_boost_on_prio(cfqq, op);
 
 		return __cfq_may_queue(cfqq);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/block/elevator.c linux-libre-4.10-rc8-gnu/block/elevator.c
--- linux-libre-4.9-gnu/block/elevator.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/elevator.c	2017-02-12 16:03:20.000000000 -0500
@@ -245,31 +245,31 @@ EXPORT_SYMBOL(elevator_exit);
 static inline void __elv_rqhash_del(struct request *rq)
 {
 	hash_del(&rq->hash);
-	rq->cmd_flags &= ~REQ_HASHED;
+	rq->rq_flags &= ~RQF_HASHED;
 }
 
-static void elv_rqhash_del(struct request_queue *q, struct request *rq)
+void elv_rqhash_del(struct request_queue *q, struct request *rq)
 {
 	if (ELV_ON_HASH(rq))
 		__elv_rqhash_del(rq);
 }
 
-static void elv_rqhash_add(struct request_queue *q, struct request *rq)
+void elv_rqhash_add(struct request_queue *q, struct request *rq)
 {
 	struct elevator_queue *e = q->elevator;
 
 	BUG_ON(ELV_ON_HASH(rq));
 	hash_add(e->hash, &rq->hash, rq_hash_key(rq));
-	rq->cmd_flags |= REQ_HASHED;
+	rq->rq_flags |= RQF_HASHED;
 }
 
-static void elv_rqhash_reposition(struct request_queue *q, struct request *rq)
+void elv_rqhash_reposition(struct request_queue *q, struct request *rq)
 {
 	__elv_rqhash_del(rq);
 	elv_rqhash_add(q, rq);
 }
 
-static struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
+struct request *elv_rqhash_find(struct request_queue *q, sector_t offset)
 {
 	struct elevator_queue *e = q->elevator;
 	struct hlist_node *next;
@@ -352,7 +352,6 @@ void elv_dispatch_sort(struct request_qu
 {
 	sector_t boundary;
 	struct list_head *entry;
-	int stop_flags;
 
 	if (q->last_merge == rq)
 		q->last_merge = NULL;
@@ -362,7 +361,6 @@ void elv_dispatch_sort(struct request_qu
 	q->nr_sorted--;
 
 	boundary = q->end_sector;
-	stop_flags = REQ_SOFTBARRIER | REQ_STARTED;
 	list_for_each_prev(entry, &q->queue_head) {
 		struct request *pos = list_entry_rq(entry);
 
@@ -370,7 +368,7 @@ void elv_dispatch_sort(struct request_qu
 			break;
 		if (rq_data_dir(rq) != rq_data_dir(pos))
 			break;
-		if (pos->cmd_flags & stop_flags)
+		if (pos->rq_flags & (RQF_STARTED | RQF_SOFTBARRIER))
 			break;
 		if (blk_rq_pos(rq) >= boundary) {
 			if (blk_rq_pos(pos) < boundary)
@@ -510,7 +508,7 @@ void elv_merge_requests(struct request_q
 			     struct request *next)
 {
 	struct elevator_queue *e = q->elevator;
-	const int next_sorted = next->cmd_flags & REQ_SORTED;
+	const int next_sorted = next->rq_flags & RQF_SORTED;
 
 	if (next_sorted && e->type->ops.elevator_merge_req_fn)
 		e->type->ops.elevator_merge_req_fn(q, rq, next);
@@ -537,13 +535,13 @@ void elv_bio_merged(struct request_queue
 #ifdef CONFIG_PM
 static void blk_pm_requeue_request(struct request *rq)
 {
-	if (rq->q->dev && !(rq->cmd_flags & REQ_PM))
+	if (rq->q->dev && !(rq->rq_flags & RQF_PM))
 		rq->q->nr_pending--;
 }
 
 static void blk_pm_add_request(struct request_queue *q, struct request *rq)
 {
-	if (q->dev && !(rq->cmd_flags & REQ_PM) && q->nr_pending++ == 0 &&
+	if (q->dev && !(rq->rq_flags & RQF_PM) && q->nr_pending++ == 0 &&
 	    (q->rpm_status == RPM_SUSPENDED || q->rpm_status == RPM_SUSPENDING))
 		pm_request_resume(q->dev);
 }
@@ -563,11 +561,11 @@ void elv_requeue_request(struct request_
 	 */
 	if (blk_account_rq(rq)) {
 		q->in_flight[rq_is_sync(rq)]--;
-		if (rq->cmd_flags & REQ_SORTED)
+		if (rq->rq_flags & RQF_SORTED)
 			elv_deactivate_rq(q, rq);
 	}
 
-	rq->cmd_flags &= ~REQ_STARTED;
+	rq->rq_flags &= ~RQF_STARTED;
 
 	blk_pm_requeue_request(rq);
 
@@ -597,13 +595,13 @@ void __elv_add_request(struct request_qu
 
 	rq->q = q;
 
-	if (rq->cmd_flags & REQ_SOFTBARRIER) {
+	if (rq->rq_flags & RQF_SOFTBARRIER) {
 		/* barriers are scheduling boundary, update end_sector */
 		if (rq->cmd_type == REQ_TYPE_FS) {
 			q->end_sector = rq_end_sector(rq);
 			q->boundary_rq = rq;
 		}
-	} else if (!(rq->cmd_flags & REQ_ELVPRIV) &&
+	} else if (!(rq->rq_flags & RQF_ELVPRIV) &&
 		    (where == ELEVATOR_INSERT_SORT ||
 		     where == ELEVATOR_INSERT_SORT_MERGE))
 		where = ELEVATOR_INSERT_BACK;
@@ -611,12 +609,12 @@ void __elv_add_request(struct request_qu
 	switch (where) {
 	case ELEVATOR_INSERT_REQUEUE:
 	case ELEVATOR_INSERT_FRONT:
-		rq->cmd_flags |= REQ_SOFTBARRIER;
+		rq->rq_flags |= RQF_SOFTBARRIER;
 		list_add(&rq->queuelist, &q->queue_head);
 		break;
 
 	case ELEVATOR_INSERT_BACK:
-		rq->cmd_flags |= REQ_SOFTBARRIER;
+		rq->rq_flags |= RQF_SOFTBARRIER;
 		elv_drain_elevator(q);
 		list_add_tail(&rq->queuelist, &q->queue_head);
 		/*
@@ -642,7 +640,7 @@ void __elv_add_request(struct request_qu
 			break;
 	case ELEVATOR_INSERT_SORT:
 		BUG_ON(rq->cmd_type != REQ_TYPE_FS);
-		rq->cmd_flags |= REQ_SORTED;
+		rq->rq_flags |= RQF_SORTED;
 		q->nr_sorted++;
 		if (rq_mergeable(rq)) {
 			elv_rqhash_add(q, rq);
@@ -659,7 +657,7 @@ void __elv_add_request(struct request_qu
 		break;
 
 	case ELEVATOR_INSERT_FLUSH:
-		rq->cmd_flags |= REQ_SOFTBARRIER;
+		rq->rq_flags |= RQF_SOFTBARRIER;
 		blk_insert_flush(rq);
 		break;
 	default:
@@ -716,12 +714,12 @@ void elv_put_request(struct request_queu
 		e->type->ops.elevator_put_req_fn(rq);
 }
 
-int elv_may_queue(struct request_queue *q, int op, int op_flags)
+int elv_may_queue(struct request_queue *q, unsigned int op)
 {
 	struct elevator_queue *e = q->elevator;
 
 	if (e->type->ops.elevator_may_queue_fn)
-		return e->type->ops.elevator_may_queue_fn(q, op, op_flags);
+		return e->type->ops.elevator_may_queue_fn(q, op);
 
 	return ELV_MQUEUE_MAY;
 }
@@ -735,7 +733,7 @@ void elv_completed_request(struct reques
 	 */
 	if (blk_account_rq(rq)) {
 		q->in_flight[rq_is_sync(rq)]--;
-		if ((rq->cmd_flags & REQ_SORTED) &&
+		if ((rq->rq_flags & RQF_SORTED) &&
 		    e->type->ops.elevator_completed_req_fn)
 			e->type->ops.elevator_completed_req_fn(q, rq);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/block/ioctl.c linux-libre-4.10-rc8-gnu/block/ioctl.c
--- linux-libre-4.9-gnu/block/ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@
 #include <linux/fs.h>
 #include <linux/blktrace_api.h>
 #include <linux/pr.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user *arg)
 {
@@ -45,6 +45,9 @@ static int blkpg_ioctl(struct block_devi
 				    || pstart < 0 || plength < 0 || partno > 65535)
 					return -EINVAL;
 			}
+			/* check if partition is aligned to blocksize */
+			if (p.start & (bdev_logical_block_size(bdev) - 1))
+				return -EINVAL;
 
 			mutex_lock(&bdev->bd_mutex);
 
@@ -519,6 +522,10 @@ int blkdev_ioctl(struct block_device *bd
 				BLKDEV_DISCARD_SECURE);
 	case BLKZEROOUT:
 		return blk_ioctl_zeroout(bdev, mode, arg);
+	case BLKREPORTZONE:
+		return blkdev_report_zones_ioctl(bdev, mode, cmd, arg);
+	case BLKRESETZONE:
+		return blkdev_reset_zones_ioctl(bdev, mode, cmd, arg);
 	case HDIO_GETGEO:
 		return blkdev_getgeo(bdev, argp);
 	case BLKRAGET:
diff -druNp --no-dereference linux-libre-4.9-gnu/block/Kconfig linux-libre-4.10-rc8-gnu/block/Kconfig
--- linux-libre-4.9-gnu/block/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -5,6 +5,7 @@ menuconfig BLOCK
        bool "Enable the block layer" if EXPERT
        default y
        select SBITMAP
+       select SRCU
        help
 	 Provide block layer support for the kernel.
 
@@ -89,6 +90,14 @@ config BLK_DEV_INTEGRITY
 	T10/SCSI Data Integrity Field or the T13/ATA External Path
 	Protection.  If in doubt, say N.
 
+config BLK_DEV_ZONED
+	bool "Zoned block device support"
+	---help---
+	Block layer zoned block device support. This option enables
+	support for ZAC/ZBC host-managed and host-aware zoned block devices.
+
+	Say yes here if you have a ZAC or ZBC storage device.
+
 config BLK_DEV_THROTTLING
 	bool "Block layer bio throttling support"
 	depends on BLK_CGROUP=y
@@ -112,6 +121,32 @@ config BLK_CMDLINE_PARSER
 
 	See Documentation/block/cmdline-partition.txt for more information.
 
+config BLK_WBT
+	bool "Enable support for block device writeback throttling"
+	default n
+	---help---
+	Enabling this option enables the block layer to throttle buffered
+	background writeback from the VM, making it more smooth and having
+	less impact on foreground operations. The throttling is done
+	dynamically on an algorithm loosely based on CoDel, factoring in
+	the realtime performance of the disk.
+
+config BLK_WBT_SQ
+	bool "Single queue writeback throttling"
+	default n
+	depends on BLK_WBT
+	---help---
+	Enable writeback throttling by default on legacy single queue devices
+
+config BLK_WBT_MQ
+	bool "Multiqueue writeback throttling"
+	default y
+	depends on BLK_WBT
+	---help---
+	Enable writeback throttling by default on multiqueue devices.
+	Multiqueue currently doesn't have support for IO scheduling,
+	enabling this option is recommended.
+
 menu "Partition Types"
 
 source "block/partitions/Kconfig"
diff -druNp --no-dereference linux-libre-4.9-gnu/block/Makefile linux-libre-4.10-rc8-gnu/block/Makefile
--- linux-libre-4.9-gnu/block/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 obj-$(CONFIG_BLOCK) := bio.o elevator.o blk-core.o blk-tag.o blk-sysfs.o \
 			blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
 			blk-exec.o blk-merge.o blk-softirq.o blk-timeout.o \
-			blk-lib.o blk-mq.o blk-mq-tag.o \
+			blk-lib.o blk-mq.o blk-mq-tag.o blk-stat.o \
 			blk-mq-sysfs.o blk-mq-cpumap.o ioctl.o \
 			genhd.o scsi_ioctl.o partition-generic.o ioprio.o \
 			badblocks.o partitions/
@@ -23,3 +23,5 @@ obj-$(CONFIG_BLOCK_COMPAT)	+= compat_ioc
 obj-$(CONFIG_BLK_CMDLINE_PARSER)	+= cmdline-parser.o
 obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
 obj-$(CONFIG_BLK_MQ_PCI)	+= blk-mq-pci.o
+obj-$(CONFIG_BLK_DEV_ZONED)	+= blk-zoned.o
+obj-$(CONFIG_BLK_WBT)		+= blk-wbt.o
diff -druNp --no-dereference linux-libre-4.9-gnu/block/partition-generic.c linux-libre-4.10-rc8-gnu/block/partition-generic.c
--- linux-libre-4.9-gnu/block/partition-generic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/partition-generic.c	2017-02-12 16:03:20.000000000 -0500
@@ -430,6 +430,56 @@ static int drop_partitions(struct gendis
 	return 0;
 }
 
+static bool part_zone_aligned(struct gendisk *disk,
+			      struct block_device *bdev,
+			      sector_t from, sector_t size)
+{
+	unsigned int zone_sectors = bdev_zone_sectors(bdev);
+
+	/*
+	 * If this function is called, then the disk is a zoned block device
+	 * (host-aware or host-managed). This can be detected even if the
+	 * zoned block device support is disabled (CONFIG_BLK_DEV_ZONED not
+	 * set). In this case, however, only host-aware devices will be seen
+	 * as a block device is not created for host-managed devices. Without
+	 * zoned block device support, host-aware drives can still be used as
+	 * regular block devices (no zone operation) and their zone size will
+	 * be reported as 0. Allow this case.
+	 */
+	if (!zone_sectors)
+		return true;
+
+	/*
+	 * Check partition start and size alignement. If the drive has a
+	 * smaller last runt zone, ignore it and allow the partition to
+	 * use it. Check the zone size too: it should be a power of 2 number
+	 * of sectors.
+	 */
+	if (WARN_ON_ONCE(!is_power_of_2(zone_sectors))) {
+		u32 rem;
+
+		div_u64_rem(from, zone_sectors, &rem);
+		if (rem)
+			return false;
+		if ((from + size) < get_capacity(disk)) {
+			div_u64_rem(size, zone_sectors, &rem);
+			if (rem)
+				return false;
+		}
+
+	} else {
+
+		if (from & (zone_sectors - 1))
+			return false;
+		if ((from + size) < get_capacity(disk) &&
+		    (size & (zone_sectors - 1)))
+			return false;
+
+	}
+
+	return true;
+}
+
 int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
 {
 	struct parsed_partitions *state = NULL;
@@ -529,6 +579,21 @@ rescan:
 			}
 		}
 
+		/*
+		 * On a zoned block device, partitions should be aligned on the
+		 * device zone size (i.e. zone boundary crossing not allowed).
+		 * Otherwise, resetting the write pointer of the last zone of
+		 * one partition may impact the following partition.
+		 */
+		if (bdev_is_zoned(bdev) &&
+		    !part_zone_aligned(disk, bdev, from, size)) {
+			printk(KERN_WARNING
+			       "%s: p%d start %llu+%llu is not zone aligned\n",
+			       disk->disk_name, p, (unsigned long long) from,
+			       (unsigned long long) size);
+			continue;
+		}
+
 		part = add_partition(disk, p, from, size,
 				     state->parts[p].flags,
 				     &state->parts[p].info);
diff -druNp --no-dereference linux-libre-4.9-gnu/block/partitions/ibm.c linux-libre-4.10-rc8-gnu/block/partitions/ibm.c
--- linux-libre-4.9-gnu/block/partitions/ibm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/partitions/ibm.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/slab.h>
 #include <asm/dasd.h>
 #include <asm/ebcdic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/vtoc.h>
 
 #include "check.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/block/scsi_ioctl.c linux-libre-4.10-rc8-gnu/block/scsi_ioctl.c
--- linux-libre-4.9-gnu/block/scsi_ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/block/scsi_ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/slab.h>
 #include <linux/times.h>
 #include <linux/uio.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
@@ -182,6 +182,9 @@ static void blk_set_cmd_filter_defaults(
 	__set_bit(WRITE_16, filter->write_ok);
 	__set_bit(WRITE_LONG, filter->write_ok);
 	__set_bit(WRITE_LONG_2, filter->write_ok);
+	__set_bit(WRITE_SAME, filter->write_ok);
+	__set_bit(WRITE_SAME_16, filter->write_ok);
+	__set_bit(WRITE_SAME_32, filter->write_ok);
 	__set_bit(ERASE, filter->write_ok);
 	__set_bit(GPCMD_MODE_SELECT_10, filter->write_ok);
 	__set_bit(MODE_SELECT, filter->write_ok);
diff -druNp --no-dereference linux-libre-4.9-gnu/CREDITS linux-libre-4.10-rc8-gnu/CREDITS
--- linux-libre-4.9-gnu/CREDITS	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/CREDITS	2017-02-12 16:03:20.000000000 -0500
@@ -2775,6 +2775,10 @@ S: C/ Mieses 20, 9-B
 S: Valladolid 47009
 S: Spain
 
+N: Peter Oruba
+D: AMD Microcode loader driver
+S: Germany
+
 N: Jens Osterkamp
 E: jens@de.ibm.com
 D: Maintainer of Spidernet network driver for Cell
@@ -3945,8 +3949,6 @@ E: gwingerde@gmail.com
 D: Ralink rt2x00 WLAN driver
 D: Minix V2 file-system
 D: Misc fixes
-S: Geessinkweg 177
-S: 7544 TX Enschede
 S: The Netherlands
 
 N: Lars Wirzenius
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/842.c linux-libre-4.10-rc8-gnu/crypto/842.c
--- linux-libre-4.9-gnu/crypto/842.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/842.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,11 +31,46 @@
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <linux/sw842.h>
+#include <crypto/internal/scompress.h>
 
 struct crypto842_ctx {
-	char wmem[SW842_MEM_COMPRESS];	/* working memory for compress */
+	void *wmem;	/* working memory for compress */
 };
 
+static void *crypto842_alloc_ctx(struct crypto_scomp *tfm)
+{
+	void *ctx;
+
+	ctx = kmalloc(SW842_MEM_COMPRESS, GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	return ctx;
+}
+
+static int crypto842_init(struct crypto_tfm *tfm)
+{
+	struct crypto842_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	ctx->wmem = crypto842_alloc_ctx(NULL);
+	if (IS_ERR(ctx->wmem))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void crypto842_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	kfree(ctx);
+}
+
+static void crypto842_exit(struct crypto_tfm *tfm)
+{
+	struct crypto842_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto842_free_ctx(NULL, ctx->wmem);
+}
+
 static int crypto842_compress(struct crypto_tfm *tfm,
 			      const u8 *src, unsigned int slen,
 			      u8 *dst, unsigned int *dlen)
@@ -45,6 +80,13 @@ static int crypto842_compress(struct cry
 	return sw842_compress(src, slen, dst, dlen, ctx->wmem);
 }
 
+static int crypto842_scompress(struct crypto_scomp *tfm,
+			       const u8 *src, unsigned int slen,
+			       u8 *dst, unsigned int *dlen, void *ctx)
+{
+	return sw842_compress(src, slen, dst, dlen, ctx);
+}
+
 static int crypto842_decompress(struct crypto_tfm *tfm,
 				const u8 *src, unsigned int slen,
 				u8 *dst, unsigned int *dlen)
@@ -52,6 +94,13 @@ static int crypto842_decompress(struct c
 	return sw842_decompress(src, slen, dst, dlen);
 }
 
+static int crypto842_sdecompress(struct crypto_scomp *tfm,
+				 const u8 *src, unsigned int slen,
+				 u8 *dst, unsigned int *dlen, void *ctx)
+{
+	return sw842_decompress(src, slen, dst, dlen);
+}
+
 static struct crypto_alg alg = {
 	.cra_name		= "842",
 	.cra_driver_name	= "842-generic",
@@ -59,20 +108,48 @@ static struct crypto_alg alg = {
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
 	.cra_ctxsize		= sizeof(struct crypto842_ctx),
 	.cra_module		= THIS_MODULE,
+	.cra_init		= crypto842_init,
+	.cra_exit		= crypto842_exit,
 	.cra_u			= { .compress = {
 	.coa_compress		= crypto842_compress,
 	.coa_decompress		= crypto842_decompress } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= crypto842_alloc_ctx,
+	.free_ctx		= crypto842_free_ctx,
+	.compress		= crypto842_scompress,
+	.decompress		= crypto842_sdecompress,
+	.base			= {
+		.cra_name	= "842",
+		.cra_driver_name = "842-scomp",
+		.cra_priority	 = 100,
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init crypto842_mod_init(void)
 {
-	return crypto_register_alg(&alg);
+	int ret;
+
+	ret = crypto_register_alg(&alg);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg);
+		return ret;
+	}
+
+	return ret;
 }
 module_init(crypto842_mod_init);
 
 static void __exit crypto842_mod_exit(void)
 {
 	crypto_unregister_alg(&alg);
+	crypto_unregister_scomp(&scomp);
 }
 module_exit(crypto842_mod_exit);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/acompress.c linux-libre-4.10-rc8-gnu/crypto/acompress.c
--- linux-libre-4.9-gnu/crypto/acompress.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/acompress.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,169 @@
+/*
+ * Asynchronous Compression operations
+ *
+ * Copyright (c) 2016, Intel Corporation
+ * Authors: Weigang Li <weigang.li@intel.com>
+ *          Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <crypto/algapi.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <crypto/internal/acompress.h>
+#include <crypto/internal/scompress.h>
+#include "internal.h"
+
+static const struct crypto_type crypto_acomp_type;
+
+#ifdef CONFIG_NET
+static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_acomp racomp;
+
+	strncpy(racomp.type, "acomp", sizeof(racomp.type));
+
+	if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
+		    sizeof(struct crypto_report_acomp), &racomp))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_acomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
+static void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg)
+	__attribute__ ((unused));
+
+static void crypto_acomp_show(struct seq_file *m, struct crypto_alg *alg)
+{
+	seq_puts(m, "type         : acomp\n");
+}
+
+static void crypto_acomp_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
+	struct acomp_alg *alg = crypto_acomp_alg(acomp);
+
+	alg->exit(acomp);
+}
+
+static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
+	struct acomp_alg *alg = crypto_acomp_alg(acomp);
+
+	if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
+		return crypto_init_scomp_ops_async(tfm);
+
+	acomp->compress = alg->compress;
+	acomp->decompress = alg->decompress;
+	acomp->dst_free = alg->dst_free;
+	acomp->reqsize = alg->reqsize;
+
+	if (alg->exit)
+		acomp->base.exit = crypto_acomp_exit_tfm;
+
+	if (alg->init)
+		return alg->init(acomp);
+
+	return 0;
+}
+
+static unsigned int crypto_acomp_extsize(struct crypto_alg *alg)
+{
+	int extsize = crypto_alg_extsize(alg);
+
+	if (alg->cra_type != &crypto_acomp_type)
+		extsize += sizeof(struct crypto_scomp *);
+
+	return extsize;
+}
+
+static const struct crypto_type crypto_acomp_type = {
+	.extsize = crypto_acomp_extsize,
+	.init_tfm = crypto_acomp_init_tfm,
+#ifdef CONFIG_PROC_FS
+	.show = crypto_acomp_show,
+#endif
+	.report = crypto_acomp_report,
+	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
+	.maskset = CRYPTO_ALG_TYPE_ACOMPRESS_MASK,
+	.type = CRYPTO_ALG_TYPE_ACOMPRESS,
+	.tfmsize = offsetof(struct crypto_acomp, base),
+};
+
+struct crypto_acomp *crypto_alloc_acomp(const char *alg_name, u32 type,
+					u32 mask)
+{
+	return crypto_alloc_tfm(alg_name, &crypto_acomp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_acomp);
+
+struct acomp_req *acomp_request_alloc(struct crypto_acomp *acomp)
+{
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+	struct acomp_req *req;
+
+	req = __acomp_request_alloc(acomp);
+	if (req && (tfm->__crt_alg->cra_type != &crypto_acomp_type))
+		return crypto_acomp_scomp_alloc_ctx(req);
+
+	return req;
+}
+EXPORT_SYMBOL_GPL(acomp_request_alloc);
+
+void acomp_request_free(struct acomp_req *req)
+{
+	struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+
+	if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
+		crypto_acomp_scomp_free_ctx(req);
+
+	if (req->flags & CRYPTO_ACOMP_ALLOC_OUTPUT) {
+		acomp->dst_free(req->dst);
+		req->dst = NULL;
+	}
+
+	__acomp_request_free(req);
+}
+EXPORT_SYMBOL_GPL(acomp_request_free);
+
+int crypto_register_acomp(struct acomp_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+
+	base->cra_type = &crypto_acomp_type;
+	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+	base->cra_flags |= CRYPTO_ALG_TYPE_ACOMPRESS;
+
+	return crypto_register_alg(base);
+}
+EXPORT_SYMBOL_GPL(crypto_register_acomp);
+
+int crypto_unregister_acomp(struct acomp_alg *alg)
+{
+	return crypto_unregister_alg(&alg->base);
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_acomp);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Asynchronous compression type");
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/algapi.c linux-libre-4.10-rc8-gnu/crypto/algapi.c
--- linux-libre-4.9-gnu/crypto/algapi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/algapi.c	2017-02-12 16:03:20.000000000 -0500
@@ -356,6 +356,7 @@ int crypto_register_alg(struct crypto_al
 	struct crypto_larval *larval;
 	int err;
 
+	alg->cra_flags &= ~CRYPTO_ALG_DEAD;
 	err = crypto_check_alg(alg);
 	if (err)
 		return err;
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/algboss.c linux-libre-4.10-rc8-gnu/crypto/algboss.c
--- linux-libre-4.9-gnu/crypto/algboss.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/algboss.c	2017-02-12 16:03:20.000000000 -0500
@@ -247,12 +247,8 @@ static int cryptomgr_schedule_test(struc
 	memcpy(param->alg, alg->cra_name, sizeof(param->alg));
 	type = alg->cra_flags;
 
-	/* This piece of crap needs to disappear into per-type test hooks. */
-	if (!((type ^ CRYPTO_ALG_TYPE_BLKCIPHER) &
-	      CRYPTO_ALG_TYPE_BLKCIPHER_MASK) && !(type & CRYPTO_ALG_GENIV) &&
-	    ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
-	     CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
-					 alg->cra_ablkcipher.ivsize))
+	/* Do not test internal algorithms. */
+	if (type & CRYPTO_ALG_INTERNAL)
 		type |= CRYPTO_ALG_TESTED;
 
 	param->type = type;
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/algif_aead.c linux-libre-4.10-rc8-gnu/crypto/algif_aead.c
--- linux-libre-4.9-gnu/crypto/algif_aead.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/algif_aead.c	2017-02-12 16:03:20.000000000 -0500
@@ -136,28 +136,27 @@ static void aead_wmem_wakeup(struct sock
 
 static int aead_wait_for_data(struct sock *sk, unsigned flags)
 {
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	struct alg_sock *ask = alg_sk(sk);
 	struct aead_ctx *ctx = ask->private;
 	long timeout;
-	DEFINE_WAIT(wait);
 	int err = -ERESTARTSYS;
 
 	if (flags & MSG_DONTWAIT)
 		return -EAGAIN;
 
 	sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-
+	add_wait_queue(sk_sleep(sk), &wait);
 	for (;;) {
 		if (signal_pending(current))
 			break;
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
 		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (sk_wait_event(sk, &timeout, !ctx->more)) {
+		if (sk_wait_event(sk, &timeout, !ctx->more, &wait)) {
 			err = 0;
 			break;
 		}
 	}
-	finish_wait(sk_sleep(sk), &wait);
+	remove_wait_queue(sk_sleep(sk), &wait);
 
 	sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
 
@@ -455,12 +454,13 @@ static int aead_recvmsg_async(struct soc
 	used -= ctx->aead_assoclen;
 
 	/* take over all tx sgls from ctx */
-	areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur,
+	areq->tsgl = sock_kmalloc(sk,
+				  sizeof(*areq->tsgl) * max_t(u32, sgl->cur, 1),
 				  GFP_KERNEL);
 	if (unlikely(!areq->tsgl))
 		goto free;
 
-	sg_init_table(areq->tsgl, sgl->cur);
+	sg_init_table(areq->tsgl, max_t(u32, sgl->cur, 1));
 	for (i = 0; i < sgl->cur; i++)
 		sg_set_page(&areq->tsgl[i], sg_page(&sgl->sg[i]),
 			    sgl->sg[i].length, sgl->sg[i].offset);
@@ -556,18 +556,8 @@ static int aead_recvmsg_sync(struct sock
 	lock_sock(sk);
 
 	/*
-	 * AEAD memory structure: For encryption, the tag is appended to the
-	 * ciphertext which implies that the memory allocated for the ciphertext
-	 * must be increased by the tag length. For decryption, the tag
-	 * is expected to be concatenated to the ciphertext. The plaintext
-	 * therefore has a memory size of the ciphertext minus the tag length.
-	 *
-	 * The memory structure for cipher operation has the following
-	 * structure:
-	 *	AEAD encryption input:  assoc data || plaintext
-	 *	AEAD encryption output: cipherntext || auth tag
-	 *	AEAD decryption input:  assoc data || ciphertext || auth tag
-	 *	AEAD decryption output: plaintext
+	 * Please see documentation of aead_request_set_crypt for the
+	 * description of the AEAD memory structure expected from the caller.
 	 */
 
 	if (ctx->more) {
@@ -671,9 +661,9 @@ static int aead_recvmsg_sync(struct sock
 unlock:
 	list_for_each_entry_safe(rsgl, tmp, &ctx->list, list) {
 		af_alg_free_sg(&rsgl->sgl);
+		list_del(&rsgl->list);
 		if (rsgl != &ctx->first_rsgl)
 			sock_kfree_s(sk, rsgl, sizeof(*rsgl));
-		list_del(&rsgl->list);
 	}
 	INIT_LIST_HEAD(&ctx->list);
 	aead_wmem_wakeup(sk);
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/algif_skcipher.c linux-libre-4.10-rc8-gnu/crypto/algif_skcipher.c
--- linux-libre-4.9-gnu/crypto/algif_skcipher.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/algif_skcipher.c	2017-02-12 16:03:20.000000000 -0500
@@ -199,26 +199,26 @@ static void skcipher_free_sgl(struct soc
 
 static int skcipher_wait_for_wmem(struct sock *sk, unsigned flags)
 {
-	long timeout;
-	DEFINE_WAIT(wait);
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	int err = -ERESTARTSYS;
+	long timeout;
 
 	if (flags & MSG_DONTWAIT)
 		return -EAGAIN;
 
 	sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
 
+	add_wait_queue(sk_sleep(sk), &wait);
 	for (;;) {
 		if (signal_pending(current))
 			break;
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
 		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (sk_wait_event(sk, &timeout, skcipher_writable(sk))) {
+		if (sk_wait_event(sk, &timeout, skcipher_writable(sk), &wait)) {
 			err = 0;
 			break;
 		}
 	}
-	finish_wait(sk_sleep(sk), &wait);
+	remove_wait_queue(sk_sleep(sk), &wait);
 
 	return err;
 }
@@ -242,10 +242,10 @@ static void skcipher_wmem_wakeup(struct
 
 static int skcipher_wait_for_data(struct sock *sk, unsigned flags)
 {
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	struct alg_sock *ask = alg_sk(sk);
 	struct skcipher_ctx *ctx = ask->private;
 	long timeout;
-	DEFINE_WAIT(wait);
 	int err = -ERESTARTSYS;
 
 	if (flags & MSG_DONTWAIT) {
@@ -254,17 +254,17 @@ static int skcipher_wait_for_data(struct
 
 	sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
 
+	add_wait_queue(sk_sleep(sk), &wait);
 	for (;;) {
 		if (signal_pending(current))
 			break;
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
 		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (sk_wait_event(sk, &timeout, ctx->used)) {
+		if (sk_wait_event(sk, &timeout, ctx->used, &wait)) {
 			err = 0;
 			break;
 		}
 	}
-	finish_wait(sk_sleep(sk), &wait);
+	remove_wait_queue(sk_sleep(sk), &wait);
 
 	sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
 
@@ -566,8 +566,10 @@ static int skcipher_recvmsg_async(struct
 			 * need to expand */
 			tmp = kcalloc(tx_nents * 2, sizeof(*tmp),
 				      GFP_KERNEL);
-			if (!tmp)
+			if (!tmp) {
+				err = -ENOMEM;
 				goto free;
+			}
 
 			sg_init_table(tmp, tx_nents * 2);
 			for (x = 0; x < tx_nents; x++)
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/api.c linux-libre-4.10-rc8-gnu/crypto/api.c
--- linux-libre-4.9-gnu/crypto/api.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/api.c	2017-02-12 16:03:20.000000000 -0500
@@ -211,8 +211,8 @@ struct crypto_alg *crypto_larval_lookup(
 	if (!name)
 		return ERR_PTR(-ENOENT);
 
+	type &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
 	mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
-	type &= mask;
 
 	alg = crypto_alg_lookup(name, type, mask);
 	if (!alg) {
@@ -310,24 +310,8 @@ static void crypto_exit_ops(struct crypt
 {
 	const struct crypto_type *type = tfm->__crt_alg->cra_type;
 
-	if (type) {
-		if (tfm->exit)
-			tfm->exit(tfm);
-		return;
-	}
-
-	switch (crypto_tfm_alg_type(tfm)) {
-	case CRYPTO_ALG_TYPE_CIPHER:
-		crypto_exit_cipher_ops(tfm);
-		break;
-
-	case CRYPTO_ALG_TYPE_COMPRESS:
-		crypto_exit_compress_ops(tfm);
-		break;
-
-	default:
-		BUG();
-	}
+	if (type && tfm->exit)
+		tfm->exit(tfm);
 }
 
 static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/asymmetric_keys/public_key.c linux-libre-4.10-rc8-gnu/crypto/asymmetric_keys/public_key.c
--- linux-libre-4.9-gnu/crypto/asymmetric_keys/public_key.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/asymmetric_keys/public_key.c	2017-02-12 16:03:20.000000000 -0500
@@ -121,6 +121,7 @@ int public_key_verify_signature(const st
 	if (ret)
 		goto error_free_req;
 
+	ret = -ENOMEM;
 	outlen = crypto_akcipher_maxsize(tfm);
 	output = kmalloc(outlen, GFP_KERNEL);
 	if (!output)
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/authenc.c linux-libre-4.10-rc8-gnu/crypto/authenc.c
--- linux-libre-4.9-gnu/crypto/authenc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/authenc.c	2017-02-12 16:03:20.000000000 -0500
@@ -324,7 +324,7 @@ static int crypto_authenc_init_tfm(struc
 	if (IS_ERR(auth))
 		return PTR_ERR(auth);
 
-	enc = crypto_spawn_skcipher2(&ictx->enc);
+	enc = crypto_spawn_skcipher(&ictx->enc);
 	err = PTR_ERR(enc);
 	if (IS_ERR(enc))
 		goto err_free_ahash;
@@ -420,9 +420,9 @@ static int crypto_authenc_create(struct
 		goto err_free_inst;
 
 	crypto_set_skcipher_spawn(&ctx->enc, aead_crypto_instance(inst));
-	err = crypto_grab_skcipher2(&ctx->enc, enc_name, 0,
-				    crypto_requires_sync(algt->type,
-							 algt->mask));
+	err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
 	if (err)
 		goto err_drop_auth;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/authencesn.c linux-libre-4.10-rc8-gnu/crypto/authencesn.c
--- linux-libre-4.9-gnu/crypto/authencesn.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/authencesn.c	2017-02-12 16:03:20.000000000 -0500
@@ -342,7 +342,7 @@ static int crypto_authenc_esn_init_tfm(s
 	if (IS_ERR(auth))
 		return PTR_ERR(auth);
 
-	enc = crypto_spawn_skcipher2(&ictx->enc);
+	enc = crypto_spawn_skcipher(&ictx->enc);
 	err = PTR_ERR(enc);
 	if (IS_ERR(enc))
 		goto err_free_ahash;
@@ -441,9 +441,9 @@ static int crypto_authenc_esn_create(str
 		goto err_free_inst;
 
 	crypto_set_skcipher_spawn(&ctx->enc, aead_crypto_instance(inst));
-	err = crypto_grab_skcipher2(&ctx->enc, enc_name, 0,
-				    crypto_requires_sync(algt->type,
-							 algt->mask));
+	err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
 	if (err)
 		goto err_drop_auth;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/cbc.c linux-libre-4.10-rc8-gnu/crypto/cbc.c
--- linux-libre-4.9-gnu/crypto/cbc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/cbc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * CBC: Cipher Block Chaining mode
  *
- * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
+ * Copyright (c) 2006-2016 Herbert Xu <herbert@gondor.apana.org.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
@@ -10,191 +10,78 @@
  *
  */
 
-#include <crypto/algapi.h>
+#include <crypto/cbc.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/log2.h>
 #include <linux/module.h>
-#include <linux/scatterlist.h>
 #include <linux/slab.h>
 
 struct crypto_cbc_ctx {
 	struct crypto_cipher *child;
 };
 
-static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key,
+static int crypto_cbc_setkey(struct crypto_skcipher *parent, const u8 *key,
 			     unsigned int keylen)
 {
-	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(parent);
+	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(parent);
 	struct crypto_cipher *child = ctx->child;
 	int err;
 
 	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+	crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) &
 				       CRYPTO_TFM_REQ_MASK);
 	err = crypto_cipher_setkey(child, key, keylen);
-	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
-				     CRYPTO_TFM_RES_MASK);
+	crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) &
+					  CRYPTO_TFM_RES_MASK);
 	return err;
 }
 
-static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
-				      struct blkcipher_walk *walk,
-				      struct crypto_cipher *tfm)
-{
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_encrypt;
-	int bsize = crypto_cipher_blocksize(tfm);
-	unsigned int nbytes = walk->nbytes;
-	u8 *src = walk->src.virt.addr;
-	u8 *dst = walk->dst.virt.addr;
-	u8 *iv = walk->iv;
-
-	do {
-		crypto_xor(iv, src, bsize);
-		fn(crypto_cipher_tfm(tfm), dst, iv);
-		memcpy(iv, dst, bsize);
-
-		src += bsize;
-		dst += bsize;
-	} while ((nbytes -= bsize) >= bsize);
-
-	return nbytes;
-}
-
-static int crypto_cbc_encrypt_inplace(struct blkcipher_desc *desc,
-				      struct blkcipher_walk *walk,
-				      struct crypto_cipher *tfm)
-{
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_encrypt;
-	int bsize = crypto_cipher_blocksize(tfm);
-	unsigned int nbytes = walk->nbytes;
-	u8 *src = walk->src.virt.addr;
-	u8 *iv = walk->iv;
-
-	do {
-		crypto_xor(src, iv, bsize);
-		fn(crypto_cipher_tfm(tfm), src, src);
-		iv = src;
-
-		src += bsize;
-	} while ((nbytes -= bsize) >= bsize);
-
-	memcpy(walk->iv, iv, bsize);
-
-	return nbytes;
-}
-
-static int crypto_cbc_encrypt(struct blkcipher_desc *desc,
-			      struct scatterlist *dst, struct scatterlist *src,
-			      unsigned int nbytes)
+static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm,
+					  const u8 *src, u8 *dst)
 {
-	struct blkcipher_walk walk;
-	struct crypto_blkcipher *tfm = desc->tfm;
-	struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
-	struct crypto_cipher *child = ctx->child;
-	int err;
-
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-
-	while ((nbytes = walk.nbytes)) {
-		if (walk.src.virt.addr == walk.dst.virt.addr)
-			nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child);
-		else
-			nbytes = crypto_cbc_encrypt_segment(desc, &walk, child);
-		err = blkcipher_walk_done(desc, &walk, nbytes);
-	}
+	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return err;
+	crypto_cipher_encrypt_one(ctx->child, dst, src);
 }
 
-static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
-				      struct blkcipher_walk *walk,
-				      struct crypto_cipher *tfm)
+static int crypto_cbc_encrypt(struct skcipher_request *req)
 {
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_decrypt;
-	int bsize = crypto_cipher_blocksize(tfm);
-	unsigned int nbytes = walk->nbytes;
-	u8 *src = walk->src.virt.addr;
-	u8 *dst = walk->dst.virt.addr;
-	u8 *iv = walk->iv;
-
-	do {
-		fn(crypto_cipher_tfm(tfm), dst, src);
-		crypto_xor(dst, iv, bsize);
-		iv = src;
-
-		src += bsize;
-		dst += bsize;
-	} while ((nbytes -= bsize) >= bsize);
-
-	memcpy(walk->iv, iv, bsize);
-
-	return nbytes;
+	return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one);
 }
 
-static int crypto_cbc_decrypt_inplace(struct blkcipher_desc *desc,
-				      struct blkcipher_walk *walk,
-				      struct crypto_cipher *tfm)
+static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm,
+					  const u8 *src, u8 *dst)
 {
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_decrypt;
-	int bsize = crypto_cipher_blocksize(tfm);
-	unsigned int nbytes = walk->nbytes;
-	u8 *src = walk->src.virt.addr;
-	u8 last_iv[bsize];
-
-	/* Start of the last block. */
-	src += nbytes - (nbytes & (bsize - 1)) - bsize;
-	memcpy(last_iv, src, bsize);
-
-	for (;;) {
-		fn(crypto_cipher_tfm(tfm), src, src);
-		if ((nbytes -= bsize) < bsize)
-			break;
-		crypto_xor(src, src - bsize, bsize);
-		src -= bsize;
-	}
-
-	crypto_xor(src, walk->iv, bsize);
-	memcpy(walk->iv, last_iv, bsize);
+	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return nbytes;
+	crypto_cipher_decrypt_one(ctx->child, dst, src);
 }
 
-static int crypto_cbc_decrypt(struct blkcipher_desc *desc,
-			      struct scatterlist *dst, struct scatterlist *src,
-			      unsigned int nbytes)
+static int crypto_cbc_decrypt(struct skcipher_request *req)
 {
-	struct blkcipher_walk walk;
-	struct crypto_blkcipher *tfm = desc->tfm;
-	struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
-	struct crypto_cipher *child = ctx->child;
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct skcipher_walk walk;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, false);
 
-	while ((nbytes = walk.nbytes)) {
-		if (walk.src.virt.addr == walk.dst.virt.addr)
-			nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child);
-		else
-			nbytes = crypto_cbc_decrypt_segment(desc, &walk, child);
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+	while (walk.nbytes) {
+		err = crypto_cbc_decrypt_blocks(&walk, tfm,
+						crypto_cbc_decrypt_one);
+		err = skcipher_walk_done(&walk, err);
 	}
 
 	return err;
 }
 
-static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
+static int crypto_cbc_init_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
-	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
+	struct crypto_spawn *spawn = skcipher_instance_ctx(inst);
+	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 	struct crypto_cipher *cipher;
 
 	cipher = crypto_spawn_cipher(spawn);
@@ -205,72 +92,94 @@ static int crypto_cbc_init_tfm(struct cr
 	return 0;
 }
 
-static void crypto_cbc_exit_tfm(struct crypto_tfm *tfm)
+static void crypto_cbc_exit_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_cbc_ctx *ctx = crypto_skcipher_ctx(tfm);
+
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
+static void crypto_cbc_free(struct skcipher_instance *inst)
 {
-	struct crypto_instance *inst;
+	crypto_drop_skcipher(skcipher_instance_ctx(inst));
+	kfree(inst);
+}
+
+static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct skcipher_instance *inst;
+	struct crypto_spawn *spawn;
 	struct crypto_alg *alg;
 	int err;
 
-	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER);
 	if (err)
-		return ERR_PTR(err);
+		return err;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
 
 	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
 				  CRYPTO_ALG_TYPE_MASK);
+	err = PTR_ERR(alg);
 	if (IS_ERR(alg))
-		return ERR_CAST(alg);
+		goto err_free_inst;
 
-	inst = ERR_PTR(-EINVAL);
-	if (!is_power_of_2(alg->cra_blocksize))
-		goto out_put_alg;
+	spawn = skcipher_instance_ctx(inst);
+	err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
+				CRYPTO_ALG_TYPE_MASK);
+	crypto_mod_put(alg);
+	if (err)
+		goto err_free_inst;
 
-	inst = crypto_alloc_instance("cbc", alg);
-	if (IS_ERR(inst))
-		goto out_put_alg;
+	err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg);
+	if (err)
+		goto err_drop_spawn;
 
-	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
-	inst->alg.cra_priority = alg->cra_priority;
-	inst->alg.cra_blocksize = alg->cra_blocksize;
-	inst->alg.cra_alignmask = alg->cra_alignmask;
-	inst->alg.cra_type = &crypto_blkcipher_type;
+	err = -EINVAL;
+	if (!is_power_of_2(alg->cra_blocksize))
+		goto err_drop_spawn;
+
+	inst->alg.base.cra_priority = alg->cra_priority;
+	inst->alg.base.cra_blocksize = alg->cra_blocksize;
+	inst->alg.base.cra_alignmask = alg->cra_alignmask;
 
 	/* We access the data as u32s when xoring. */
-	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
+	inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
 
-	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
-	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
-	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+	inst->alg.ivsize = alg->cra_blocksize;
+	inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize;
+	inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize;
 
-	inst->alg.cra_ctxsize = sizeof(struct crypto_cbc_ctx);
+	inst->alg.base.cra_ctxsize = sizeof(struct crypto_cbc_ctx);
 
-	inst->alg.cra_init = crypto_cbc_init_tfm;
-	inst->alg.cra_exit = crypto_cbc_exit_tfm;
+	inst->alg.init = crypto_cbc_init_tfm;
+	inst->alg.exit = crypto_cbc_exit_tfm;
 
-	inst->alg.cra_blkcipher.setkey = crypto_cbc_setkey;
-	inst->alg.cra_blkcipher.encrypt = crypto_cbc_encrypt;
-	inst->alg.cra_blkcipher.decrypt = crypto_cbc_decrypt;
+	inst->alg.setkey = crypto_cbc_setkey;
+	inst->alg.encrypt = crypto_cbc_encrypt;
+	inst->alg.decrypt = crypto_cbc_decrypt;
 
-out_put_alg:
-	crypto_mod_put(alg);
-	return inst;
-}
+	inst->free = crypto_cbc_free;
 
-static void crypto_cbc_free(struct crypto_instance *inst)
-{
-	crypto_drop_spawn(crypto_instance_ctx(inst));
+	err = skcipher_register_instance(tmpl, inst);
+	if (err)
+		goto err_drop_spawn;
+
+out:
+	return err;
+
+err_drop_spawn:
+	crypto_drop_spawn(spawn);
+err_free_inst:
 	kfree(inst);
+	goto out;
 }
 
 static struct crypto_template crypto_cbc_tmpl = {
 	.name = "cbc",
-	.alloc = crypto_cbc_alloc,
-	.free = crypto_cbc_free,
+	.create = crypto_cbc_create,
 	.module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/ccm.c linux-libre-4.10-rc8-gnu/crypto/ccm.c
--- linux-libre-4.9-gnu/crypto/ccm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/ccm.c	2017-02-12 16:03:20.000000000 -0500
@@ -462,7 +462,7 @@ static int crypto_ccm_init_tfm(struct cr
 	if (IS_ERR(cipher))
 		return PTR_ERR(cipher);
 
-	ctr = crypto_spawn_skcipher2(&ictx->ctr);
+	ctr = crypto_spawn_skcipher(&ictx->ctr);
 	err = PTR_ERR(ctr);
 	if (IS_ERR(ctr))
 		goto err_free_cipher;
@@ -544,9 +544,9 @@ static int crypto_ccm_create_common(stru
 		goto err_free_inst;
 
 	crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst));
-	err = crypto_grab_skcipher2(&ictx->ctr, ctr_name, 0,
-				    crypto_requires_sync(algt->type,
-							 algt->mask));
+	err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
 	if (err)
 		goto err_drop_cipher;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/chacha20poly1305.c linux-libre-4.10-rc8-gnu/crypto/chacha20poly1305.c
--- linux-libre-4.9-gnu/crypto/chacha20poly1305.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/chacha20poly1305.c	2017-02-12 16:03:20.000000000 -0500
@@ -532,7 +532,7 @@ static int chachapoly_init(struct crypto
 	if (IS_ERR(poly))
 		return PTR_ERR(poly);
 
-	chacha = crypto_spawn_skcipher2(&ictx->chacha);
+	chacha = crypto_spawn_skcipher(&ictx->chacha);
 	if (IS_ERR(chacha)) {
 		crypto_free_ahash(poly);
 		return PTR_ERR(chacha);
@@ -625,9 +625,9 @@ static int chachapoly_create(struct cryp
 		goto err_free_inst;
 
 	crypto_set_skcipher_spawn(&ctx->chacha, aead_crypto_instance(inst));
-	err = crypto_grab_skcipher2(&ctx->chacha, chacha_name, 0,
-				    crypto_requires_sync(algt->type,
-							 algt->mask));
+	err = crypto_grab_skcipher(&ctx->chacha, chacha_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
 	if (err)
 		goto err_drop_poly;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/cipher.c linux-libre-4.10-rc8-gnu/crypto/cipher.c
--- linux-libre-4.9-gnu/crypto/cipher.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/cipher.c	2017-02-12 16:03:20.000000000 -0500
@@ -116,7 +116,3 @@ int crypto_init_cipher_ops(struct crypto
 
 	return 0;
 }
-
-void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
-{
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/cmac.c linux-libre-4.10-rc8-gnu/crypto/cmac.c
--- linux-libre-4.9-gnu/crypto/cmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/cmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,8 @@ static int crypto_cmac_digest_setkey(str
 	unsigned long alignmask = crypto_shash_alignmask(parent);
 	struct cmac_tfm_ctx *ctx = crypto_shash_ctx(parent);
 	unsigned int bs = crypto_shash_blocksize(parent);
-	__be64 *consts = PTR_ALIGN((void *)ctx->ctx, alignmask + 1);
+	__be64 *consts = PTR_ALIGN((void *)ctx->ctx,
+				   (alignmask | (__alignof__(__be64) - 1)) + 1);
 	u64 _const[2];
 	int i, err = 0;
 	u8 msb_mask, gfmask;
@@ -173,7 +174,8 @@ static int crypto_cmac_digest_final(stru
 	struct cmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
 	struct crypto_cipher *tfm = tctx->child;
 	int bs = crypto_shash_blocksize(parent);
-	u8 *consts = PTR_ALIGN((void *)tctx->ctx, alignmask + 1);
+	u8 *consts = PTR_ALIGN((void *)tctx->ctx,
+			       (alignmask | (__alignof__(__be64) - 1)) + 1);
 	u8 *odds = PTR_ALIGN((void *)ctx->ctx, alignmask + 1);
 	u8 *prev = odds + bs;
 	unsigned int offset = 0;
@@ -243,6 +245,7 @@ static int cmac_create(struct crypto_tem
 	case 8:
 		break;
 	default:
+		err = -EINVAL;
 		goto out_put_alg;
 	}
 
@@ -257,7 +260,8 @@ static int cmac_create(struct crypto_tem
 	if (err)
 		goto out_free_inst;
 
-	alignmask = alg->cra_alignmask | (sizeof(long) - 1);
+	/* We access the data as u32s when xoring. */
+	alignmask = alg->cra_alignmask | (__alignof__(u32) - 1);
 	inst->alg.base.cra_alignmask = alignmask;
 	inst->alg.base.cra_priority = alg->cra_priority;
 	inst->alg.base.cra_blocksize = alg->cra_blocksize;
@@ -269,7 +273,9 @@ static int cmac_create(struct crypto_tem
 		+ alg->cra_blocksize * 2;
 
 	inst->alg.base.cra_ctxsize =
-		ALIGN(sizeof(struct cmac_tfm_ctx), alignmask + 1)
+		ALIGN(sizeof(struct cmac_tfm_ctx), crypto_tfm_ctx_alignment())
+		+ ((alignmask | (__alignof__(__be64) - 1)) &
+		   ~(crypto_tfm_ctx_alignment() - 1))
 		+ alg->cra_blocksize * 2;
 
 	inst->alg.base.cra_init = cmac_init_tfm;
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/compress.c linux-libre-4.10-rc8-gnu/crypto/compress.c
--- linux-libre-4.9-gnu/crypto/compress.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/compress.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,3 @@ int crypto_init_compress_ops(struct cryp
 
 	return 0;
 }
-
-void crypto_exit_compress_ops(struct crypto_tfm *tfm)
-{
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/cryptd.c linux-libre-4.10-rc8-gnu/crypto/cryptd.c
--- linux-libre-4.9-gnu/crypto/cryptd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/cryptd.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,9 +17,9 @@
  *
  */
 
-#include <crypto/algapi.h>
 #include <crypto/internal/hash.h>
 #include <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
 #include <crypto/cryptd.h>
 #include <crypto/crypto_wq.h>
 #include <linux/atomic.h>
@@ -48,6 +48,11 @@ struct cryptd_instance_ctx {
 	struct cryptd_queue *queue;
 };
 
+struct skcipherd_instance_ctx {
+	struct crypto_skcipher_spawn spawn;
+	struct cryptd_queue *queue;
+};
+
 struct hashd_instance_ctx {
 	struct crypto_shash_spawn spawn;
 	struct cryptd_queue *queue;
@@ -67,6 +72,15 @@ struct cryptd_blkcipher_request_ctx {
 	crypto_completion_t complete;
 };
 
+struct cryptd_skcipher_ctx {
+	atomic_t refcnt;
+	struct crypto_skcipher *child;
+};
+
+struct cryptd_skcipher_request_ctx {
+	crypto_completion_t complete;
+};
+
 struct cryptd_hash_ctx {
 	atomic_t refcnt;
 	struct crypto_shash *child;
@@ -122,7 +136,6 @@ static int cryptd_enqueue_request(struct
 {
 	int cpu, err;
 	struct cryptd_cpu_queue *cpu_queue;
-	struct crypto_tfm *tfm;
 	atomic_t *refcnt;
 	bool may_backlog;
 
@@ -141,7 +154,6 @@ static int cryptd_enqueue_request(struct
 	if (!atomic_read(refcnt))
 		goto out_put_cpu;
 
-	tfm = request->tfm;
 	atomic_inc(refcnt);
 
 out_put_cpu:
@@ -432,6 +444,216 @@ out_put_alg:
 	return err;
 }
 
+static int cryptd_skcipher_setkey(struct crypto_skcipher *parent,
+				  const u8 *key, unsigned int keylen)
+{
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(parent);
+	struct crypto_skcipher *child = ctx->child;
+	int err;
+
+	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_skcipher_setkey(child, key, keylen);
+	crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) &
+					  CRYPTO_TFM_RES_MASK);
+	return err;
+}
+
+static void cryptd_skcipher_complete(struct skcipher_request *req, int err)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
+	int refcnt = atomic_read(&ctx->refcnt);
+
+	local_bh_disable();
+	rctx->complete(&req->base, err);
+	local_bh_enable();
+
+	if (err != -EINPROGRESS && refcnt && atomic_dec_and_test(&ctx->refcnt))
+		crypto_free_skcipher(tfm);
+}
+
+static void cryptd_skcipher_encrypt(struct crypto_async_request *base,
+				    int err)
+{
+	struct skcipher_request *req = skcipher_request_cast(base);
+	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *child = ctx->child;
+	SKCIPHER_REQUEST_ON_STACK(subreq, child);
+
+	if (unlikely(err == -EINPROGRESS))
+		goto out;
+
+	skcipher_request_set_tfm(subreq, child);
+	skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP,
+				      NULL, NULL);
+	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
+				   req->iv);
+
+	err = crypto_skcipher_encrypt(subreq);
+	skcipher_request_zero(subreq);
+
+	req->base.complete = rctx->complete;
+
+out:
+	cryptd_skcipher_complete(req, err);
+}
+
+static void cryptd_skcipher_decrypt(struct crypto_async_request *base,
+				    int err)
+{
+	struct skcipher_request *req = skcipher_request_cast(base);
+	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *child = ctx->child;
+	SKCIPHER_REQUEST_ON_STACK(subreq, child);
+
+	if (unlikely(err == -EINPROGRESS))
+		goto out;
+
+	skcipher_request_set_tfm(subreq, child);
+	skcipher_request_set_callback(subreq, CRYPTO_TFM_REQ_MAY_SLEEP,
+				      NULL, NULL);
+	skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
+				   req->iv);
+
+	err = crypto_skcipher_decrypt(subreq);
+	skcipher_request_zero(subreq);
+
+	req->base.complete = rctx->complete;
+
+out:
+	cryptd_skcipher_complete(req, err);
+}
+
+static int cryptd_skcipher_enqueue(struct skcipher_request *req,
+				   crypto_completion_t compl)
+{
+	struct cryptd_skcipher_request_ctx *rctx = skcipher_request_ctx(req);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct cryptd_queue *queue;
+
+	queue = cryptd_get_queue(crypto_skcipher_tfm(tfm));
+	rctx->complete = req->base.complete;
+	req->base.complete = compl;
+
+	return cryptd_enqueue_request(queue, &req->base);
+}
+
+static int cryptd_skcipher_encrypt_enqueue(struct skcipher_request *req)
+{
+	return cryptd_skcipher_enqueue(req, cryptd_skcipher_encrypt);
+}
+
+static int cryptd_skcipher_decrypt_enqueue(struct skcipher_request *req)
+{
+	return cryptd_skcipher_enqueue(req, cryptd_skcipher_decrypt);
+}
+
+static int cryptd_skcipher_init_tfm(struct crypto_skcipher *tfm)
+{
+	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
+	struct skcipherd_instance_ctx *ictx = skcipher_instance_ctx(inst);
+	struct crypto_skcipher_spawn *spawn = &ictx->spawn;
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *cipher;
+
+	cipher = crypto_spawn_skcipher(spawn);
+	if (IS_ERR(cipher))
+		return PTR_ERR(cipher);
+
+	ctx->child = cipher;
+	crypto_skcipher_set_reqsize(
+		tfm, sizeof(struct cryptd_skcipher_request_ctx));
+	return 0;
+}
+
+static void cryptd_skcipher_exit_tfm(struct crypto_skcipher *tfm)
+{
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+	crypto_free_skcipher(ctx->child);
+}
+
+static void cryptd_skcipher_free(struct skcipher_instance *inst)
+{
+	struct skcipherd_instance_ctx *ctx = skcipher_instance_ctx(inst);
+
+	crypto_drop_skcipher(&ctx->spawn);
+}
+
+static int cryptd_create_skcipher(struct crypto_template *tmpl,
+				  struct rtattr **tb,
+				  struct cryptd_queue *queue)
+{
+	struct skcipherd_instance_ctx *ctx;
+	struct skcipher_instance *inst;
+	struct skcipher_alg *alg;
+	const char *name;
+	u32 type;
+	u32 mask;
+	int err;
+
+	type = 0;
+	mask = CRYPTO_ALG_ASYNC;
+
+	cryptd_check_internal(tb, &type, &mask);
+
+	name = crypto_attr_alg_name(tb[1]);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	ctx = skcipher_instance_ctx(inst);
+	ctx->queue = queue;
+
+	crypto_set_skcipher_spawn(&ctx->spawn, skcipher_crypto_instance(inst));
+	err = crypto_grab_skcipher(&ctx->spawn, name, type, mask);
+	if (err)
+		goto out_free_inst;
+
+	alg = crypto_spawn_skcipher_alg(&ctx->spawn);
+	err = cryptd_init_instance(skcipher_crypto_instance(inst), &alg->base);
+	if (err)
+		goto out_drop_skcipher;
+
+	inst->alg.base.cra_flags = CRYPTO_ALG_ASYNC |
+				   (alg->base.cra_flags & CRYPTO_ALG_INTERNAL);
+
+	inst->alg.ivsize = crypto_skcipher_alg_ivsize(alg);
+	inst->alg.chunksize = crypto_skcipher_alg_chunksize(alg);
+	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg);
+	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg);
+
+	inst->alg.base.cra_ctxsize = sizeof(struct cryptd_skcipher_ctx);
+
+	inst->alg.init = cryptd_skcipher_init_tfm;
+	inst->alg.exit = cryptd_skcipher_exit_tfm;
+
+	inst->alg.setkey = cryptd_skcipher_setkey;
+	inst->alg.encrypt = cryptd_skcipher_encrypt_enqueue;
+	inst->alg.decrypt = cryptd_skcipher_decrypt_enqueue;
+
+	inst->free = cryptd_skcipher_free;
+
+	err = skcipher_register_instance(tmpl, inst);
+	if (err) {
+out_drop_skcipher:
+		crypto_drop_skcipher(&ctx->spawn);
+out_free_inst:
+		kfree(inst);
+	}
+	return err;
+}
+
 static int cryptd_hash_init_tfm(struct crypto_tfm *tfm)
 {
 	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
@@ -895,7 +1117,11 @@ static int cryptd_create(struct crypto_t
 
 	switch (algt->type & algt->mask & CRYPTO_ALG_TYPE_MASK) {
 	case CRYPTO_ALG_TYPE_BLKCIPHER:
-		return cryptd_create_blkcipher(tmpl, tb, &queue);
+		if ((algt->type & CRYPTO_ALG_TYPE_MASK) ==
+		    CRYPTO_ALG_TYPE_BLKCIPHER)
+			return cryptd_create_blkcipher(tmpl, tb, &queue);
+
+		return cryptd_create_skcipher(tmpl, tb, &queue);
 	case CRYPTO_ALG_TYPE_DIGEST:
 		return cryptd_create_hash(tmpl, tb, &queue);
 	case CRYPTO_ALG_TYPE_AEAD:
@@ -985,6 +1211,58 @@ void cryptd_free_ablkcipher(struct crypt
 }
 EXPORT_SYMBOL_GPL(cryptd_free_ablkcipher);
 
+struct cryptd_skcipher *cryptd_alloc_skcipher(const char *alg_name,
+					      u32 type, u32 mask)
+{
+	char cryptd_alg_name[CRYPTO_MAX_ALG_NAME];
+	struct cryptd_skcipher_ctx *ctx;
+	struct crypto_skcipher *tfm;
+
+	if (snprintf(cryptd_alg_name, CRYPTO_MAX_ALG_NAME,
+		     "cryptd(%s)", alg_name) >= CRYPTO_MAX_ALG_NAME)
+		return ERR_PTR(-EINVAL);
+
+	tfm = crypto_alloc_skcipher(cryptd_alg_name, type, mask);
+	if (IS_ERR(tfm))
+		return ERR_CAST(tfm);
+
+	if (tfm->base.__crt_alg->cra_module != THIS_MODULE) {
+		crypto_free_skcipher(tfm);
+		return ERR_PTR(-EINVAL);
+	}
+
+	ctx = crypto_skcipher_ctx(tfm);
+	atomic_set(&ctx->refcnt, 1);
+
+	return container_of(tfm, struct cryptd_skcipher, base);
+}
+EXPORT_SYMBOL_GPL(cryptd_alloc_skcipher);
+
+struct crypto_skcipher *cryptd_skcipher_child(struct cryptd_skcipher *tfm)
+{
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
+
+	return ctx->child;
+}
+EXPORT_SYMBOL_GPL(cryptd_skcipher_child);
+
+bool cryptd_skcipher_queued(struct cryptd_skcipher *tfm)
+{
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
+
+	return atomic_read(&ctx->refcnt) - 1;
+}
+EXPORT_SYMBOL_GPL(cryptd_skcipher_queued);
+
+void cryptd_free_skcipher(struct cryptd_skcipher *tfm)
+{
+	struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(&tfm->base);
+
+	if (atomic_dec_and_test(&ctx->refcnt))
+		crypto_free_skcipher(&tfm->base);
+}
+EXPORT_SYMBOL_GPL(cryptd_free_skcipher);
+
 struct cryptd_ahash *cryptd_alloc_ahash(const char *alg_name,
 					u32 type, u32 mask)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/crypto_engine.c linux-libre-4.10-rc8-gnu/crypto/crypto_engine.c
--- linux-libre-4.9-gnu/crypto/crypto_engine.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/crypto_engine.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@ static void crypto_pump_requests(struct
 
 	/* If another context is idling then defer */
 	if (engine->idling) {
-		kthread_queue_work(&engine->kworker, &engine->pump_requests);
+		kthread_queue_work(engine->kworker, &engine->pump_requests);
 		goto out;
 	}
 
@@ -58,7 +58,7 @@ static void crypto_pump_requests(struct
 
 		/* Only do teardown in the thread */
 		if (!in_kthread) {
-			kthread_queue_work(&engine->kworker,
+			kthread_queue_work(engine->kworker,
 					   &engine->pump_requests);
 			goto out;
 		}
@@ -189,7 +189,7 @@ int crypto_transfer_cipher_request(struc
 	ret = ablkcipher_enqueue_request(&engine->queue, req);
 
 	if (!engine->busy && need_pump)
-		kthread_queue_work(&engine->kworker, &engine->pump_requests);
+		kthread_queue_work(engine->kworker, &engine->pump_requests);
 
 	spin_unlock_irqrestore(&engine->queue_lock, flags);
 	return ret;
@@ -231,7 +231,7 @@ int crypto_transfer_hash_request(struct
 	ret = ahash_enqueue_request(&engine->queue, req);
 
 	if (!engine->busy && need_pump)
-		kthread_queue_work(&engine->kworker, &engine->pump_requests);
+		kthread_queue_work(engine->kworker, &engine->pump_requests);
 
 	spin_unlock_irqrestore(&engine->queue_lock, flags);
 	return ret;
@@ -284,7 +284,7 @@ void crypto_finalize_cipher_request(stru
 
 	req->base.complete(&req->base, err);
 
-	kthread_queue_work(&engine->kworker, &engine->pump_requests);
+	kthread_queue_work(engine->kworker, &engine->pump_requests);
 }
 EXPORT_SYMBOL_GPL(crypto_finalize_cipher_request);
 
@@ -321,7 +321,7 @@ void crypto_finalize_hash_request(struct
 
 	req->base.complete(&req->base, err);
 
-	kthread_queue_work(&engine->kworker, &engine->pump_requests);
+	kthread_queue_work(engine->kworker, &engine->pump_requests);
 }
 EXPORT_SYMBOL_GPL(crypto_finalize_hash_request);
 
@@ -345,7 +345,7 @@ int crypto_engine_start(struct crypto_en
 	engine->running = true;
 	spin_unlock_irqrestore(&engine->queue_lock, flags);
 
-	kthread_queue_work(&engine->kworker, &engine->pump_requests);
+	kthread_queue_work(engine->kworker, &engine->pump_requests);
 
 	return 0;
 }
@@ -422,11 +422,8 @@ struct crypto_engine *crypto_engine_allo
 	crypto_init_queue(&engine->queue, CRYPTO_ENGINE_MAX_QLEN);
 	spin_lock_init(&engine->queue_lock);
 
-	kthread_init_worker(&engine->kworker);
-	engine->kworker_task = kthread_run(kthread_worker_fn,
-					   &engine->kworker, "%s",
-					   engine->name);
-	if (IS_ERR(engine->kworker_task)) {
+	engine->kworker = kthread_create_worker(0, "%s", engine->name);
+	if (IS_ERR(engine->kworker)) {
 		dev_err(dev, "failed to create crypto request pump task\n");
 		return NULL;
 	}
@@ -434,7 +431,7 @@ struct crypto_engine *crypto_engine_allo
 
 	if (engine->rt) {
 		dev_info(dev, "will run requests pump with realtime priority\n");
-		sched_setscheduler(engine->kworker_task, SCHED_FIFO, &param);
+		sched_setscheduler(engine->kworker->task, SCHED_FIFO, &param);
 	}
 
 	return engine;
@@ -455,8 +452,7 @@ int crypto_engine_exit(struct crypto_eng
 	if (ret)
 		return ret;
 
-	kthread_flush_worker(&engine->kworker);
-	kthread_stop(engine->kworker_task);
+	kthread_destroy_worker(engine->kworker);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/crypto_user.c linux-libre-4.10-rc8-gnu/crypto/crypto_user.c
--- linux-libre-4.9-gnu/crypto/crypto_user.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/crypto_user.c	2017-02-12 16:03:20.000000000 -0500
@@ -112,6 +112,21 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
+static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_acomp racomp;
+
+	strncpy(racomp.type, "acomp", sizeof(racomp.type));
+
+	if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
+		    sizeof(struct crypto_report_acomp), &racomp))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
 static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
 {
 	struct crypto_report_akcipher rakcipher;
@@ -186,7 +201,11 @@ static int crypto_report_one(struct cryp
 			goto nla_put_failure;
 
 		break;
+	case CRYPTO_ALG_TYPE_ACOMPRESS:
+		if (crypto_report_acomp(skb, alg))
+			goto nla_put_failure;
 
+		break;
 	case CRYPTO_ALG_TYPE_AKCIPHER:
 		if (crypto_report_akcipher(skb, alg))
 			goto nla_put_failure;
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/ctr.c linux-libre-4.10-rc8-gnu/crypto/ctr.c
--- linux-libre-4.9-gnu/crypto/ctr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/ctr.c	2017-02-12 16:03:20.000000000 -0500
@@ -312,7 +312,7 @@ static int crypto_rfc3686_init_tfm(struc
 	unsigned long align;
 	unsigned int reqsize;
 
-	cipher = crypto_spawn_skcipher2(spawn);
+	cipher = crypto_spawn_skcipher(spawn);
 	if (IS_ERR(cipher))
 		return PTR_ERR(cipher);
 
@@ -370,9 +370,9 @@ static int crypto_rfc3686_create(struct
 	spawn = skcipher_instance_ctx(inst);
 
 	crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst));
-	err = crypto_grab_skcipher2(spawn, cipher_name, 0,
-				    crypto_requires_sync(algt->type,
-							 algt->mask));
+	err = crypto_grab_skcipher(spawn, cipher_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
 	if (err)
 		goto err_free_inst;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/cts.c linux-libre-4.10-rc8-gnu/crypto/cts.c
--- linux-libre-4.9-gnu/crypto/cts.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/cts.c	2017-02-12 16:03:20.000000000 -0500
@@ -290,7 +290,7 @@ static int crypto_cts_init_tfm(struct cr
 	unsigned bsize;
 	unsigned align;
 
-	cipher = crypto_spawn_skcipher2(spawn);
+	cipher = crypto_spawn_skcipher(spawn);
 	if (IS_ERR(cipher))
 		return PTR_ERR(cipher);
 
@@ -348,9 +348,9 @@ static int crypto_cts_create(struct cryp
 	spawn = skcipher_instance_ctx(inst);
 
 	crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst));
-	err = crypto_grab_skcipher2(spawn, cipher_name, 0,
-				    crypto_requires_sync(algt->type,
-							 algt->mask));
+	err = crypto_grab_skcipher(spawn, cipher_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
 	if (err)
 		goto err_free_inst;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/deflate.c linux-libre-4.10-rc8-gnu/crypto/deflate.c
--- linux-libre-4.9-gnu/crypto/deflate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/deflate.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/net.h>
+#include <crypto/internal/scompress.h>
 
 #define DEFLATE_DEF_LEVEL		Z_DEFAULT_COMPRESSION
 #define DEFLATE_DEF_WINBITS		11
@@ -101,9 +102,8 @@ static void deflate_decomp_exit(struct d
 	vfree(ctx->decomp_stream.workspace);
 }
 
-static int deflate_init(struct crypto_tfm *tfm)
+static int __deflate_init(void *ctx)
 {
-	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
 	int ret;
 
 	ret = deflate_comp_init(ctx);
@@ -116,19 +116,55 @@ out:
 	return ret;
 }
 
-static void deflate_exit(struct crypto_tfm *tfm)
+static void *deflate_alloc_ctx(struct crypto_scomp *tfm)
+{
+	struct deflate_ctx *ctx;
+	int ret;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	ret = __deflate_init(ctx);
+	if (ret) {
+		kfree(ctx);
+		return ERR_PTR(ret);
+	}
+
+	return ctx;
+}
+
+static int deflate_init(struct crypto_tfm *tfm)
 {
 	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
 
+	return __deflate_init(ctx);
+}
+
+static void __deflate_exit(void *ctx)
+{
 	deflate_comp_exit(ctx);
 	deflate_decomp_exit(ctx);
 }
 
-static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
-			    unsigned int slen, u8 *dst, unsigned int *dlen)
+static void deflate_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	__deflate_exit(ctx);
+	kzfree(ctx);
+}
+
+static void deflate_exit(struct crypto_tfm *tfm)
+{
+	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	__deflate_exit(ctx);
+}
+
+static int __deflate_compress(const u8 *src, unsigned int slen,
+			      u8 *dst, unsigned int *dlen, void *ctx)
 {
 	int ret = 0;
-	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+	struct deflate_ctx *dctx = ctx;
 	struct z_stream_s *stream = &dctx->comp_stream;
 
 	ret = zlib_deflateReset(stream);
@@ -153,12 +189,27 @@ out:
 	return ret;
 }
 
-static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
-			      unsigned int slen, u8 *dst, unsigned int *dlen)
+static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
+			    unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+
+	return __deflate_compress(src, slen, dst, dlen, dctx);
+}
+
+static int deflate_scompress(struct crypto_scomp *tfm, const u8 *src,
+			     unsigned int slen, u8 *dst, unsigned int *dlen,
+			     void *ctx)
+{
+	return __deflate_compress(src, slen, dst, dlen, ctx);
+}
+
+static int __deflate_decompress(const u8 *src, unsigned int slen,
+				u8 *dst, unsigned int *dlen, void *ctx)
 {
 
 	int ret = 0;
-	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+	struct deflate_ctx *dctx = ctx;
 	struct z_stream_s *stream = &dctx->decomp_stream;
 
 	ret = zlib_inflateReset(stream);
@@ -194,6 +245,21 @@ out:
 	return ret;
 }
 
+static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
+
+	return __deflate_decompress(src, slen, dst, dlen, dctx);
+}
+
+static int deflate_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+			       unsigned int slen, u8 *dst, unsigned int *dlen,
+			       void *ctx)
+{
+	return __deflate_decompress(src, slen, dst, dlen, ctx);
+}
+
 static struct crypto_alg alg = {
 	.cra_name		= "deflate",
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
@@ -206,14 +272,39 @@ static struct crypto_alg alg = {
 	.coa_decompress  	= deflate_decompress } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= deflate_alloc_ctx,
+	.free_ctx		= deflate_free_ctx,
+	.compress		= deflate_scompress,
+	.decompress		= deflate_sdecompress,
+	.base			= {
+		.cra_name	= "deflate",
+		.cra_driver_name = "deflate-scomp",
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init deflate_mod_init(void)
 {
-	return crypto_register_alg(&alg);
+	int ret;
+
+	ret = crypto_register_alg(&alg);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg);
+		return ret;
+	}
+
+	return ret;
 }
 
 static void __exit deflate_mod_fini(void)
 {
 	crypto_unregister_alg(&alg);
+	crypto_unregister_scomp(&scomp);
 }
 
 module_init(deflate_mod_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/dh.c linux-libre-4.10-rc8-gnu/crypto/dh.c
--- linux-libre-4.9-gnu/crypto/dh.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/dh.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,7 +118,7 @@ static int dh_compute_value(struct kpp_r
 	if (req->src) {
 		base = mpi_read_raw_from_sgl(req->src, req->src_len);
 		if (!base) {
-			ret = EINVAL;
+			ret = -EINVAL;
 			goto err_free_val;
 		}
 	} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/drbg.c linux-libre-4.10-rc8-gnu/crypto/drbg.c
--- linux-libre-4.9-gnu/crypto/drbg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/drbg.c	2017-02-12 16:03:20.000000000 -0500
@@ -1782,6 +1782,7 @@ static int drbg_kcapi_sym_ctr(struct drb
 		memcpy(outbuf, drbg->outscratchpad, cryptlen);
 
 		outlen -= cryptlen;
+		outbuf += cryptlen;
 	}
 	ret = 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/gcm.c linux-libre-4.10-rc8-gnu/crypto/gcm.c
--- linux-libre-4.9-gnu/crypto/gcm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/gcm.c	2017-02-12 16:03:20.000000000 -0500
@@ -575,7 +575,7 @@ static int crypto_gcm_init_tfm(struct cr
 	if (IS_ERR(ghash))
 		return PTR_ERR(ghash);
 
-	ctr = crypto_spawn_skcipher2(&ictx->ctr);
+	ctr = crypto_spawn_skcipher(&ictx->ctr);
 	err = PTR_ERR(ctr);
 	if (IS_ERR(ctr))
 		goto err_free_hash;
@@ -663,20 +663,20 @@ static int crypto_gcm_create_common(stru
 		goto err_drop_ghash;
 
 	crypto_set_skcipher_spawn(&ctx->ctr, aead_crypto_instance(inst));
-	err = crypto_grab_skcipher2(&ctx->ctr, ctr_name, 0,
-				    crypto_requires_sync(algt->type,
-							 algt->mask));
+	err = crypto_grab_skcipher(&ctx->ctr, ctr_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
 	if (err)
 		goto err_drop_ghash;
 
 	ctr = crypto_spawn_skcipher_alg(&ctx->ctr);
 
 	/* We only support 16-byte blocks. */
+	err = -EINVAL;
 	if (crypto_skcipher_alg_ivsize(ctr) != 16)
 		goto out_put_ctr;
 
 	/* Not a stream cipher? */
-	err = -EINVAL;
 	if (ctr->base.cra_blocksize != 1)
 		goto out_put_ctr;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/gf128mul.c linux-libre-4.10-rc8-gnu/crypto/gf128mul.c
--- linux-libre-4.9-gnu/crypto/gf128mul.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/gf128mul.c	2017-02-12 16:03:20.000000000 -0500
@@ -263,48 +263,6 @@ EXPORT_SYMBOL(gf128mul_bbe);
  * t[1][BYTE] contains g*x^8*BYTE
  *  ..
  * t[15][BYTE] contains g*x^120*BYTE */
-struct gf128mul_64k *gf128mul_init_64k_lle(const be128 *g)
-{
-	struct gf128mul_64k *t;
-	int i, j, k;
-
-	t = kzalloc(sizeof(*t), GFP_KERNEL);
-	if (!t)
-		goto out;
-
-	for (i = 0; i < 16; i++) {
-		t->t[i] = kzalloc(sizeof(*t->t[i]), GFP_KERNEL);
-		if (!t->t[i]) {
-			gf128mul_free_64k(t);
-			t = NULL;
-			goto out;
-		}
-	}
-
-	t->t[0]->t[128] = *g;
-	for (j = 64; j > 0; j >>= 1)
-		gf128mul_x_lle(&t->t[0]->t[j], &t->t[0]->t[j + j]);
-
-	for (i = 0;;) {
-		for (j = 2; j < 256; j += j)
-			for (k = 1; k < j; ++k)
-				be128_xor(&t->t[i]->t[j + k],
-					  &t->t[i]->t[j], &t->t[i]->t[k]);
-
-		if (++i >= 16)
-			break;
-
-		for (j = 128; j > 0; j >>= 1) {
-			t->t[i]->t[j] = t->t[i - 1]->t[j];
-			gf128mul_x8_lle(&t->t[i]->t[j]);
-		}
-	}
-
-out:
-	return t;
-}
-EXPORT_SYMBOL(gf128mul_init_64k_lle);
-
 struct gf128mul_64k *gf128mul_init_64k_bbe(const be128 *g)
 {
 	struct gf128mul_64k *t;
@@ -352,24 +310,11 @@ void gf128mul_free_64k(struct gf128mul_6
 	int i;
 
 	for (i = 0; i < 16; i++)
-		kfree(t->t[i]);
-	kfree(t);
+		kzfree(t->t[i]);
+	kzfree(t);
 }
 EXPORT_SYMBOL(gf128mul_free_64k);
 
-void gf128mul_64k_lle(be128 *a, struct gf128mul_64k *t)
-{
-	u8 *ap = (u8 *)a;
-	be128 r[1];
-	int i;
-
-	*r = t->t[0]->t[ap[0]];
-	for (i = 1; i < 16; ++i)
-		be128_xor(r, r, &t->t[i]->t[ap[i]]);
-	*a = *r;
-}
-EXPORT_SYMBOL(gf128mul_64k_lle);
-
 void gf128mul_64k_bbe(be128 *a, struct gf128mul_64k *t)
 {
 	u8 *ap = (u8 *)a;
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/internal.h linux-libre-4.10-rc8-gnu/crypto/internal.h
--- linux-libre-4.9-gnu/crypto/internal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/internal.h	2017-02-12 16:03:20.000000000 -0500
@@ -76,9 +76,6 @@ struct crypto_alg *crypto_alg_mod_lookup
 int crypto_init_cipher_ops(struct crypto_tfm *tfm);
 int crypto_init_compress_ops(struct crypto_tfm *tfm);
 
-void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
-void crypto_exit_compress_ops(struct crypto_tfm *tfm);
-
 struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask);
 void crypto_larval_kill(struct crypto_alg *alg);
 struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/jitterentropy-kcapi.c linux-libre-4.10-rc8-gnu/crypto/jitterentropy-kcapi.c
--- linux-libre-4.9-gnu/crypto/jitterentropy-kcapi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/jitterentropy-kcapi.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,6 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/module.h>
 #include <linux/fips.h>
 #include <linux/time.h>
 #include <linux/crypto.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/Kconfig linux-libre-4.10-rc8-gnu/crypto/Kconfig
--- linux-libre-4.9-gnu/crypto/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@ comment "Crypto core or helper"
 config CRYPTO_FIPS
 	bool "FIPS 200 compliance"
 	depends on (CRYPTO_ANSI_CPRNG || CRYPTO_DRBG) && !CRYPTO_MANAGER_DISABLE_TESTS
-	depends on MODULE_SIG
+	depends on (MODULE_SIG || !MODULES)
 	help
 	  This options enables the fips boot option which is
 	  required if you want to system to operate in a FIPS 200
@@ -102,6 +102,15 @@ config CRYPTO_KPP
 	select CRYPTO_ALGAPI
 	select CRYPTO_KPP2
 
+config CRYPTO_ACOMP2
+	tristate
+	select CRYPTO_ALGAPI2
+
+config CRYPTO_ACOMP
+	tristate
+	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
+
 config CRYPTO_RSA
 	tristate "RSA algorithm"
 	select CRYPTO_AKCIPHER
@@ -138,6 +147,7 @@ config CRYPTO_MANAGER2
 	select CRYPTO_BLKCIPHER2
 	select CRYPTO_AKCIPHER2
 	select CRYPTO_KPP2
+	select CRYPTO_ACOMP2
 
 config CRYPTO_USER
 	tristate "Userspace cryptographic algorithm configuration"
@@ -236,10 +246,14 @@ config CRYPTO_ABLK_HELPER
 	tristate
 	select CRYPTO_CRYPTD
 
+config CRYPTO_SIMD
+	tristate
+	select CRYPTO_CRYPTD
+
 config CRYPTO_GLUE_HELPER_X86
 	tristate
 	depends on X86
-	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
 
 config CRYPTO_ENGINE
 	tristate
@@ -437,7 +451,7 @@ config CRYPTO_CRC32C_INTEL
 	  gain performance compared with software implementation.
 	  Module will be crc32c-intel.
 
-config CRYPT_CRC32C_VPMSUM
+config CRYPTO_CRC32C_VPMSUM
 	tristate "CRC32c CRC algorithm (powerpc64)"
 	depends on PPC64 && ALTIVEC
 	select CRYPTO_HASH
@@ -928,14 +942,13 @@ config CRYPTO_AES_X86_64
 config CRYPTO_AES_NI_INTEL
 	tristate "AES cipher algorithms (AES-NI)"
 	depends on X86
+	select CRYPTO_AEAD
 	select CRYPTO_AES_X86_64 if 64BIT
 	select CRYPTO_AES_586 if !64BIT
-	select CRYPTO_CRYPTD
-	select CRYPTO_ABLK_HELPER
 	select CRYPTO_ALGAPI
+	select CRYPTO_BLKCIPHER
 	select CRYPTO_GLUE_HELPER_X86 if 64BIT
-	select CRYPTO_LRW
-	select CRYPTO_XTS
+	select CRYPTO_SIMD
 	help
 	  Use Intel AES-NI instructions for AES algorithm.
 
@@ -1568,6 +1581,7 @@ comment "Compression"
 config CRYPTO_DEFLATE
 	tristate "Deflate compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select ZLIB_INFLATE
 	select ZLIB_DEFLATE
 	help
@@ -1579,6 +1593,7 @@ config CRYPTO_DEFLATE
 config CRYPTO_LZO
 	tristate "LZO compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select LZO_COMPRESS
 	select LZO_DECOMPRESS
 	help
@@ -1587,6 +1602,7 @@ config CRYPTO_LZO
 config CRYPTO_842
 	tristate "842 compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select 842_COMPRESS
 	select 842_DECOMPRESS
 	help
@@ -1595,6 +1611,7 @@ config CRYPTO_842
 config CRYPTO_LZ4
 	tristate "LZ4 compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select LZ4_COMPRESS
 	select LZ4_DECOMPRESS
 	help
@@ -1603,6 +1620,7 @@ config CRYPTO_LZ4
 config CRYPTO_LZ4HC
 	tristate "LZ4HC compression algorithm"
 	select CRYPTO_ALGAPI
+	select CRYPTO_ACOMP2
 	select LZ4HC_COMPRESS
 	select LZ4_DECOMPRESS
 	help
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/lrw.c linux-libre-4.10-rc8-gnu/crypto/lrw.c
--- linux-libre-4.9-gnu/crypto/lrw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/lrw.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,8 @@
  *
  * The test vectors are included in the testing module tcrypt.[ch] */
 
-#include <crypto/algapi.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -29,11 +30,30 @@
 #include <crypto/gf128mul.h>
 #include <crypto/lrw.h>
 
+#define LRW_BUFFER_SIZE 128u
+
 struct priv {
-	struct crypto_cipher *child;
+	struct crypto_skcipher *child;
 	struct lrw_table_ctx table;
 };
 
+struct rctx {
+	be128 buf[LRW_BUFFER_SIZE / sizeof(be128)];
+
+	be128 t;
+
+	be128 *ext;
+
+	struct scatterlist srcbuf[2];
+	struct scatterlist dstbuf[2];
+	struct scatterlist *src;
+	struct scatterlist *dst;
+
+	unsigned int left;
+
+	struct skcipher_request subreq;
+};
+
 static inline void setbit128_bbe(void *b, int bit)
 {
 	__set_bit(bit ^ (0x80 -
@@ -76,32 +96,26 @@ void lrw_free_table(struct lrw_table_ctx
 }
 EXPORT_SYMBOL_GPL(lrw_free_table);
 
-static int setkey(struct crypto_tfm *parent, const u8 *key,
+static int setkey(struct crypto_skcipher *parent, const u8 *key,
 		  unsigned int keylen)
 {
-	struct priv *ctx = crypto_tfm_ctx(parent);
-	struct crypto_cipher *child = ctx->child;
+	struct priv *ctx = crypto_skcipher_ctx(parent);
+	struct crypto_skcipher *child = ctx->child;
 	int err, bsize = LRW_BLOCK_SIZE;
 	const u8 *tweak = key + keylen - bsize;
 
-	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
-				       CRYPTO_TFM_REQ_MASK);
-	err = crypto_cipher_setkey(child, key, keylen - bsize);
+	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_skcipher_setkey(child, key, keylen - bsize);
+	crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) &
+					  CRYPTO_TFM_RES_MASK);
 	if (err)
 		return err;
-	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
-				     CRYPTO_TFM_RES_MASK);
 
 	return lrw_init_table(&ctx->table, tweak);
 }
 
-struct sinfo {
-	be128 t;
-	struct crypto_tfm *tfm;
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
-};
-
 static inline void inc(be128 *iv)
 {
 	be64_add_cpu(&iv->b, 1);
@@ -109,13 +123,6 @@ static inline void inc(be128 *iv)
 		be64_add_cpu(&iv->a, 1);
 }
 
-static inline void lrw_round(struct sinfo *s, void *dst, const void *src)
-{
-	be128_xor(dst, &s->t, src);		/* PP <- T xor P */
-	s->fn(s->tfm, dst, dst);		/* CC <- E(Key2,PP) */
-	be128_xor(dst, dst, &s->t);		/* C <- T xor CC */
-}
-
 /* this returns the number of consequative 1 bits starting
  * from the right, get_index128(00 00 00 00 00 00 ... 00 00 10 FB) = 2 */
 static inline int get_index128(be128 *block)
@@ -135,83 +142,263 @@ static inline int get_index128(be128 *bl
 	return x;
 }
 
-static int crypt(struct blkcipher_desc *d,
-		 struct blkcipher_walk *w, struct priv *ctx,
-		 void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
+static int post_crypt(struct skcipher_request *req)
 {
+	struct rctx *rctx = skcipher_request_ctx(req);
+	be128 *buf = rctx->ext ?: rctx->buf;
+	struct skcipher_request *subreq;
+	const int bs = LRW_BLOCK_SIZE;
+	struct skcipher_walk w;
+	struct scatterlist *sg;
+	unsigned offset;
 	int err;
-	unsigned int avail;
+
+	subreq = &rctx->subreq;
+	err = skcipher_walk_virt(&w, subreq, false);
+
+	while (w.nbytes) {
+		unsigned int avail = w.nbytes;
+		be128 *wdst;
+
+		wdst = w.dst.virt.addr;
+
+		do {
+			be128_xor(wdst, buf++, wdst);
+			wdst++;
+		} while ((avail -= bs) >= bs);
+
+		err = skcipher_walk_done(&w, avail);
+	}
+
+	rctx->left -= subreq->cryptlen;
+
+	if (err || !rctx->left)
+		goto out;
+
+	rctx->dst = rctx->dstbuf;
+
+	scatterwalk_done(&w.out, 0, 1);
+	sg = w.out.sg;
+	offset = w.out.offset;
+
+	if (rctx->dst != sg) {
+		rctx->dst[0] = *sg;
+		sg_unmark_end(rctx->dst);
+		scatterwalk_crypto_chain(rctx->dst, sg_next(sg), 0, 2);
+	}
+	rctx->dst[0].length -= offset - sg->offset;
+	rctx->dst[0].offset = offset;
+
+out:
+	return err;
+}
+
+static int pre_crypt(struct skcipher_request *req)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct rctx *rctx = skcipher_request_ctx(req);
+	struct priv *ctx = crypto_skcipher_ctx(tfm);
+	be128 *buf = rctx->ext ?: rctx->buf;
+	struct skcipher_request *subreq;
 	const int bs = LRW_BLOCK_SIZE;
-	struct sinfo s = {
-		.tfm = crypto_cipher_tfm(ctx->child),
-		.fn = fn
-	};
+	struct skcipher_walk w;
+	struct scatterlist *sg;
+	unsigned cryptlen;
+	unsigned offset;
 	be128 *iv;
-	u8 *wsrc;
-	u8 *wdst;
+	bool more;
+	int err;
 
-	err = blkcipher_walk_virt(d, w);
-	if (!(avail = w->nbytes))
-		return err;
+	subreq = &rctx->subreq;
+	skcipher_request_set_tfm(subreq, tfm);
 
-	wsrc = w->src.virt.addr;
-	wdst = w->dst.virt.addr;
+	cryptlen = subreq->cryptlen;
+	more = rctx->left > cryptlen;
+	if (!more)
+		cryptlen = rctx->left;
 
-	/* calculate first value of T */
-	iv = (be128 *)w->iv;
-	s.t = *iv;
+	skcipher_request_set_crypt(subreq, rctx->src, rctx->dst,
+				   cryptlen, req->iv);
 
-	/* T <- I*Key2 */
-	gf128mul_64k_bbe(&s.t, ctx->table.table);
+	err = skcipher_walk_virt(&w, subreq, false);
+	iv = w.iv;
 
-	goto first;
+	while (w.nbytes) {
+		unsigned int avail = w.nbytes;
+		be128 *wsrc;
+		be128 *wdst;
+
+		wsrc = w.src.virt.addr;
+		wdst = w.dst.virt.addr;
 
-	for (;;) {
 		do {
+			*buf++ = rctx->t;
+			be128_xor(wdst++, &rctx->t, wsrc++);
+
 			/* T <- I*Key2, using the optimization
 			 * discussed in the specification */
-			be128_xor(&s.t, &s.t,
+			be128_xor(&rctx->t, &rctx->t,
 				  &ctx->table.mulinc[get_index128(iv)]);
 			inc(iv);
+		} while ((avail -= bs) >= bs);
 
-first:
-			lrw_round(&s, wdst, wsrc);
+		err = skcipher_walk_done(&w, avail);
+	}
 
-			wsrc += bs;
-			wdst += bs;
-		} while ((avail -= bs) >= bs);
+	skcipher_request_set_tfm(subreq, ctx->child);
+	skcipher_request_set_crypt(subreq, rctx->dst, rctx->dst,
+				   cryptlen, NULL);
 
-		err = blkcipher_walk_done(d, w, avail);
-		if (!(avail = w->nbytes))
-			break;
+	if (err || !more)
+		goto out;
 
-		wsrc = w->src.virt.addr;
-		wdst = w->dst.virt.addr;
+	rctx->src = rctx->srcbuf;
+
+	scatterwalk_done(&w.in, 0, 1);
+	sg = w.in.sg;
+	offset = w.in.offset;
+
+	if (rctx->src != sg) {
+		rctx->src[0] = *sg;
+		sg_unmark_end(rctx->src);
+		scatterwalk_crypto_chain(rctx->src, sg_next(sg), 0, 2);
 	}
+	rctx->src[0].length -= offset - sg->offset;
+	rctx->src[0].offset = offset;
 
+out:
 	return err;
 }
 
-static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		   struct scatterlist *src, unsigned int nbytes)
+static int init_crypt(struct skcipher_request *req, crypto_completion_t done)
 {
-	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk w;
+	struct priv *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
+	struct rctx *rctx = skcipher_request_ctx(req);
+	struct skcipher_request *subreq;
+	gfp_t gfp;
 
-	blkcipher_walk_init(&w, dst, src, nbytes);
-	return crypt(desc, &w, ctx,
-		     crypto_cipher_alg(ctx->child)->cia_encrypt);
+	subreq = &rctx->subreq;
+	skcipher_request_set_callback(subreq, req->base.flags, done, req);
+
+	gfp = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+							   GFP_ATOMIC;
+	rctx->ext = NULL;
+
+	subreq->cryptlen = LRW_BUFFER_SIZE;
+	if (req->cryptlen > LRW_BUFFER_SIZE) {
+		subreq->cryptlen = min(req->cryptlen, (unsigned)PAGE_SIZE);
+		rctx->ext = kmalloc(subreq->cryptlen, gfp);
+	}
+
+	rctx->src = req->src;
+	rctx->dst = req->dst;
+	rctx->left = req->cryptlen;
+
+	/* calculate first value of T */
+	memcpy(&rctx->t, req->iv, sizeof(rctx->t));
+
+	/* T <- I*Key2 */
+	gf128mul_64k_bbe(&rctx->t, ctx->table.table);
+
+	return 0;
 }
 
-static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		   struct scatterlist *src, unsigned int nbytes)
+static void exit_crypt(struct skcipher_request *req)
 {
-	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk w;
+	struct rctx *rctx = skcipher_request_ctx(req);
 
-	blkcipher_walk_init(&w, dst, src, nbytes);
-	return crypt(desc, &w, ctx,
-		     crypto_cipher_alg(ctx->child)->cia_decrypt);
+	rctx->left = 0;
+
+	if (rctx->ext)
+		kfree(rctx->ext);
+}
+
+static int do_encrypt(struct skcipher_request *req, int err)
+{
+	struct rctx *rctx = skcipher_request_ctx(req);
+	struct skcipher_request *subreq;
+
+	subreq = &rctx->subreq;
+
+	while (!err && rctx->left) {
+		err = pre_crypt(req) ?:
+		      crypto_skcipher_encrypt(subreq) ?:
+		      post_crypt(req);
+
+		if (err == -EINPROGRESS ||
+		    (err == -EBUSY &&
+		     req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
+			return err;
+	}
+
+	exit_crypt(req);
+	return err;
+}
+
+static void encrypt_done(struct crypto_async_request *areq, int err)
+{
+	struct skcipher_request *req = areq->data;
+	struct skcipher_request *subreq;
+	struct rctx *rctx;
+
+	rctx = skcipher_request_ctx(req);
+	subreq = &rctx->subreq;
+	subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
+
+	err = do_encrypt(req, err ?: post_crypt(req));
+	if (rctx->left)
+		return;
+
+	skcipher_request_complete(req, err);
+}
+
+static int encrypt(struct skcipher_request *req)
+{
+	return do_encrypt(req, init_crypt(req, encrypt_done));
+}
+
+static int do_decrypt(struct skcipher_request *req, int err)
+{
+	struct rctx *rctx = skcipher_request_ctx(req);
+	struct skcipher_request *subreq;
+
+	subreq = &rctx->subreq;
+
+	while (!err && rctx->left) {
+		err = pre_crypt(req) ?:
+		      crypto_skcipher_decrypt(subreq) ?:
+		      post_crypt(req);
+
+		if (err == -EINPROGRESS ||
+		    (err == -EBUSY &&
+		     req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
+			return err;
+	}
+
+	exit_crypt(req);
+	return err;
+}
+
+static void decrypt_done(struct crypto_async_request *areq, int err)
+{
+	struct skcipher_request *req = areq->data;
+	struct skcipher_request *subreq;
+	struct rctx *rctx;
+
+	rctx = skcipher_request_ctx(req);
+	subreq = &rctx->subreq;
+	subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
+
+	err = do_decrypt(req, err ?: post_crypt(req));
+	if (rctx->left)
+		return;
+
+	skcipher_request_complete(req, err);
+}
+
+static int decrypt(struct skcipher_request *req)
+{
+	return do_decrypt(req, init_crypt(req, decrypt_done));
 }
 
 int lrw_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst,
@@ -293,95 +480,161 @@ first:
 }
 EXPORT_SYMBOL_GPL(lrw_crypt);
 
-static int init_tfm(struct crypto_tfm *tfm)
+static int init_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_cipher *cipher;
-	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
-	struct priv *ctx = crypto_tfm_ctx(tfm);
-	u32 *flags = &tfm->crt_flags;
+	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
+	struct crypto_skcipher_spawn *spawn = skcipher_instance_ctx(inst);
+	struct priv *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *cipher;
 
-	cipher = crypto_spawn_cipher(spawn);
+	cipher = crypto_spawn_skcipher(spawn);
 	if (IS_ERR(cipher))
 		return PTR_ERR(cipher);
 
-	if (crypto_cipher_blocksize(cipher) != LRW_BLOCK_SIZE) {
-		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
-		crypto_free_cipher(cipher);
-		return -EINVAL;
-	}
-
 	ctx->child = cipher;
+
+	crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(cipher) +
+					 sizeof(struct rctx));
+
 	return 0;
 }
 
-static void exit_tfm(struct crypto_tfm *tfm)
+static void exit_tfm(struct crypto_skcipher *tfm)
 {
-	struct priv *ctx = crypto_tfm_ctx(tfm);
+	struct priv *ctx = crypto_skcipher_ctx(tfm);
 
 	lrw_free_table(&ctx->table);
-	crypto_free_cipher(ctx->child);
+	crypto_free_skcipher(ctx->child);
 }
 
-static struct crypto_instance *alloc(struct rtattr **tb)
+static void free(struct skcipher_instance *inst)
 {
-	struct crypto_instance *inst;
-	struct crypto_alg *alg;
+	crypto_drop_skcipher(skcipher_instance_ctx(inst));
+	kfree(inst);
+}
+
+static int create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct crypto_skcipher_spawn *spawn;
+	struct skcipher_instance *inst;
+	struct crypto_attr_type *algt;
+	struct skcipher_alg *alg;
+	const char *cipher_name;
+	char ecb_name[CRYPTO_MAX_ALG_NAME];
 	int err;
 
-	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return PTR_ERR(algt);
+
+	if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask)
+		return -EINVAL;
+
+	cipher_name = crypto_attr_alg_name(tb[1]);
+	if (IS_ERR(cipher_name))
+		return PTR_ERR(cipher_name);
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	spawn = skcipher_instance_ctx(inst);
+
+	crypto_set_skcipher_spawn(spawn, skcipher_crypto_instance(inst));
+	err = crypto_grab_skcipher(spawn, cipher_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
+	if (err == -ENOENT) {
+		err = -ENAMETOOLONG;
+		if (snprintf(ecb_name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
+			     cipher_name) >= CRYPTO_MAX_ALG_NAME)
+			goto err_free_inst;
+
+		err = crypto_grab_skcipher(spawn, ecb_name, 0,
+					   crypto_requires_sync(algt->type,
+								algt->mask));
+	}
+
 	if (err)
-		return ERR_PTR(err);
+		goto err_free_inst;
 
-	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK);
-	if (IS_ERR(alg))
-		return ERR_CAST(alg);
+	alg = crypto_skcipher_spawn_alg(spawn);
 
-	inst = crypto_alloc_instance("lrw", alg);
-	if (IS_ERR(inst))
-		goto out_put_alg;
+	err = -EINVAL;
+	if (alg->base.cra_blocksize != LRW_BLOCK_SIZE)
+		goto err_drop_spawn;
 
-	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
-	inst->alg.cra_priority = alg->cra_priority;
-	inst->alg.cra_blocksize = alg->cra_blocksize;
+	if (crypto_skcipher_alg_ivsize(alg))
+		goto err_drop_spawn;
 
-	if (alg->cra_alignmask < 7) inst->alg.cra_alignmask = 7;
-	else inst->alg.cra_alignmask = alg->cra_alignmask;
-	inst->alg.cra_type = &crypto_blkcipher_type;
+	err = crypto_inst_setname(skcipher_crypto_instance(inst), "lrw",
+				  &alg->base);
+	if (err)
+		goto err_drop_spawn;
 
-	if (!(alg->cra_blocksize % 4))
-		inst->alg.cra_alignmask |= 3;
-	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
-	inst->alg.cra_blkcipher.min_keysize =
-		alg->cra_cipher.cia_min_keysize + alg->cra_blocksize;
-	inst->alg.cra_blkcipher.max_keysize =
-		alg->cra_cipher.cia_max_keysize + alg->cra_blocksize;
+	err = -EINVAL;
+	cipher_name = alg->base.cra_name;
 
-	inst->alg.cra_ctxsize = sizeof(struct priv);
+	/* Alas we screwed up the naming so we have to mangle the
+	 * cipher name.
+	 */
+	if (!strncmp(cipher_name, "ecb(", 4)) {
+		unsigned len;
 
-	inst->alg.cra_init = init_tfm;
-	inst->alg.cra_exit = exit_tfm;
+		len = strlcpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
+		if (len < 2 || len >= sizeof(ecb_name))
+			goto err_drop_spawn;
 
-	inst->alg.cra_blkcipher.setkey = setkey;
-	inst->alg.cra_blkcipher.encrypt = encrypt;
-	inst->alg.cra_blkcipher.decrypt = decrypt;
+		if (ecb_name[len - 1] != ')')
+			goto err_drop_spawn;
 
-out_put_alg:
-	crypto_mod_put(alg);
-	return inst;
-}
+		ecb_name[len - 1] = 0;
 
-static void free(struct crypto_instance *inst)
-{
-	crypto_drop_spawn(crypto_instance_ctx(inst));
+		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+			     "lrw(%s)", ecb_name) >= CRYPTO_MAX_ALG_NAME)
+			return -ENAMETOOLONG;
+	}
+
+	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
+	inst->alg.base.cra_priority = alg->base.cra_priority;
+	inst->alg.base.cra_blocksize = LRW_BLOCK_SIZE;
+	inst->alg.base.cra_alignmask = alg->base.cra_alignmask |
+				       (__alignof__(u64) - 1);
+
+	inst->alg.ivsize = LRW_BLOCK_SIZE;
+	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) +
+				LRW_BLOCK_SIZE;
+	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) +
+				LRW_BLOCK_SIZE;
+
+	inst->alg.base.cra_ctxsize = sizeof(struct priv);
+
+	inst->alg.init = init_tfm;
+	inst->alg.exit = exit_tfm;
+
+	inst->alg.setkey = setkey;
+	inst->alg.encrypt = encrypt;
+	inst->alg.decrypt = decrypt;
+
+	inst->free = free;
+
+	err = skcipher_register_instance(tmpl, inst);
+	if (err)
+		goto err_drop_spawn;
+
+out:
+	return err;
+
+err_drop_spawn:
+	crypto_drop_skcipher(spawn);
+err_free_inst:
 	kfree(inst);
+	goto out;
 }
 
 static struct crypto_template crypto_tmpl = {
 	.name = "lrw",
-	.alloc = alloc,
-	.free = free,
+	.create = create,
 	.module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/lz4.c linux-libre-4.10-rc8-gnu/crypto/lz4.c
--- linux-libre-4.9-gnu/crypto/lz4.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/lz4.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,36 +23,53 @@
 #include <linux/crypto.h>
 #include <linux/vmalloc.h>
 #include <linux/lz4.h>
+#include <crypto/internal/scompress.h>
 
 struct lz4_ctx {
 	void *lz4_comp_mem;
 };
 
+static void *lz4_alloc_ctx(struct crypto_scomp *tfm)
+{
+	void *ctx;
+
+	ctx = vmalloc(LZ4_MEM_COMPRESS);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	return ctx;
+}
+
 static int lz4_init(struct crypto_tfm *tfm)
 {
 	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	ctx->lz4_comp_mem = vmalloc(LZ4_MEM_COMPRESS);
-	if (!ctx->lz4_comp_mem)
+	ctx->lz4_comp_mem = lz4_alloc_ctx(NULL);
+	if (IS_ERR(ctx->lz4_comp_mem))
 		return -ENOMEM;
 
 	return 0;
 }
 
+static void lz4_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	vfree(ctx);
+}
+
 static void lz4_exit(struct crypto_tfm *tfm)
 {
 	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
-	vfree(ctx->lz4_comp_mem);
+
+	lz4_free_ctx(NULL, ctx->lz4_comp_mem);
 }
 
-static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			    unsigned int slen, u8 *dst, unsigned int *dlen)
+static int __lz4_compress_crypto(const u8 *src, unsigned int slen,
+				 u8 *dst, unsigned int *dlen, void *ctx)
 {
-	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
 	size_t tmp_len = *dlen;
 	int err;
 
-	err = lz4_compress(src, slen, dst, &tmp_len, ctx->lz4_comp_mem);
+	err = lz4_compress(src, slen, dst, &tmp_len, ctx);
 
 	if (err < 0)
 		return -EINVAL;
@@ -61,8 +78,23 @@ static int lz4_compress_crypto(struct cr
 	return 0;
 }
 
-static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			      unsigned int slen, u8 *dst, unsigned int *dlen)
+static int lz4_scompress(struct crypto_scomp *tfm, const u8 *src,
+			 unsigned int slen, u8 *dst, unsigned int *dlen,
+			 void *ctx)
+{
+	return __lz4_compress_crypto(src, slen, dst, dlen, ctx);
+}
+
+static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+			       unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct lz4_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	return __lz4_compress_crypto(src, slen, dst, dlen, ctx->lz4_comp_mem);
+}
+
+static int __lz4_decompress_crypto(const u8 *src, unsigned int slen,
+				   u8 *dst, unsigned int *dlen, void *ctx)
 {
 	int err;
 	size_t tmp_len = *dlen;
@@ -76,6 +108,20 @@ static int lz4_decompress_crypto(struct
 	return err;
 }
 
+static int lz4_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+			   unsigned int slen, u8 *dst, unsigned int *dlen,
+			   void *ctx)
+{
+	return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
+static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+				 unsigned int slen, u8 *dst,
+				 unsigned int *dlen)
+{
+	return __lz4_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
 static struct crypto_alg alg_lz4 = {
 	.cra_name		= "lz4",
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
@@ -89,14 +135,39 @@ static struct crypto_alg alg_lz4 = {
 	.coa_decompress		= lz4_decompress_crypto } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= lz4_alloc_ctx,
+	.free_ctx		= lz4_free_ctx,
+	.compress		= lz4_scompress,
+	.decompress		= lz4_sdecompress,
+	.base			= {
+		.cra_name	= "lz4",
+		.cra_driver_name = "lz4-scomp",
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init lz4_mod_init(void)
 {
-	return crypto_register_alg(&alg_lz4);
+	int ret;
+
+	ret = crypto_register_alg(&alg_lz4);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg_lz4);
+		return ret;
+	}
+
+	return ret;
 }
 
 static void __exit lz4_mod_fini(void)
 {
 	crypto_unregister_alg(&alg_lz4);
+	crypto_unregister_scomp(&scomp);
 }
 
 module_init(lz4_mod_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/lz4hc.c linux-libre-4.10-rc8-gnu/crypto/lz4hc.c
--- linux-libre-4.9-gnu/crypto/lz4hc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/lz4hc.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,37 +22,53 @@
 #include <linux/crypto.h>
 #include <linux/vmalloc.h>
 #include <linux/lz4.h>
+#include <crypto/internal/scompress.h>
 
 struct lz4hc_ctx {
 	void *lz4hc_comp_mem;
 };
 
+static void *lz4hc_alloc_ctx(struct crypto_scomp *tfm)
+{
+	void *ctx;
+
+	ctx = vmalloc(LZ4HC_MEM_COMPRESS);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	return ctx;
+}
+
 static int lz4hc_init(struct crypto_tfm *tfm)
 {
 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	ctx->lz4hc_comp_mem = vmalloc(LZ4HC_MEM_COMPRESS);
-	if (!ctx->lz4hc_comp_mem)
+	ctx->lz4hc_comp_mem = lz4hc_alloc_ctx(NULL);
+	if (IS_ERR(ctx->lz4hc_comp_mem))
 		return -ENOMEM;
 
 	return 0;
 }
 
+static void lz4hc_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	vfree(ctx);
+}
+
 static void lz4hc_exit(struct crypto_tfm *tfm)
 {
 	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	vfree(ctx->lz4hc_comp_mem);
+	lz4hc_free_ctx(NULL, ctx->lz4hc_comp_mem);
 }
 
-static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			    unsigned int slen, u8 *dst, unsigned int *dlen)
+static int __lz4hc_compress_crypto(const u8 *src, unsigned int slen,
+				   u8 *dst, unsigned int *dlen, void *ctx)
 {
-	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
 	size_t tmp_len = *dlen;
 	int err;
 
-	err = lz4hc_compress(src, slen, dst, &tmp_len, ctx->lz4hc_comp_mem);
+	err = lz4hc_compress(src, slen, dst, &tmp_len, ctx);
 
 	if (err < 0)
 		return -EINVAL;
@@ -61,8 +77,25 @@ static int lz4hc_compress_crypto(struct
 	return 0;
 }
 
-static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
-			      unsigned int slen, u8 *dst, unsigned int *dlen)
+static int lz4hc_scompress(struct crypto_scomp *tfm, const u8 *src,
+			   unsigned int slen, u8 *dst, unsigned int *dlen,
+			   void *ctx)
+{
+	return __lz4hc_compress_crypto(src, slen, dst, dlen, ctx);
+}
+
+static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src,
+				 unsigned int slen, u8 *dst,
+				 unsigned int *dlen)
+{
+	struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	return __lz4hc_compress_crypto(src, slen, dst, dlen,
+					ctx->lz4hc_comp_mem);
+}
+
+static int __lz4hc_decompress_crypto(const u8 *src, unsigned int slen,
+				     u8 *dst, unsigned int *dlen, void *ctx)
 {
 	int err;
 	size_t tmp_len = *dlen;
@@ -76,6 +109,20 @@ static int lz4hc_decompress_crypto(struc
 	return err;
 }
 
+static int lz4hc_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+			     unsigned int slen, u8 *dst, unsigned int *dlen,
+			     void *ctx)
+{
+	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
+static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src,
+				   unsigned int slen, u8 *dst,
+				   unsigned int *dlen)
+{
+	return __lz4hc_decompress_crypto(src, slen, dst, dlen, NULL);
+}
+
 static struct crypto_alg alg_lz4hc = {
 	.cra_name		= "lz4hc",
 	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
@@ -89,14 +136,39 @@ static struct crypto_alg alg_lz4hc = {
 	.coa_decompress		= lz4hc_decompress_crypto } }
 };
 
+static struct scomp_alg scomp = {
+	.alloc_ctx		= lz4hc_alloc_ctx,
+	.free_ctx		= lz4hc_free_ctx,
+	.compress		= lz4hc_scompress,
+	.decompress		= lz4hc_sdecompress,
+	.base			= {
+		.cra_name	= "lz4hc",
+		.cra_driver_name = "lz4hc-scomp",
+		.cra_module	 = THIS_MODULE,
+	}
+};
+
 static int __init lz4hc_mod_init(void)
 {
-	return crypto_register_alg(&alg_lz4hc);
+	int ret;
+
+	ret = crypto_register_alg(&alg_lz4hc);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg_lz4hc);
+		return ret;
+	}
+
+	return ret;
 }
 
 static void __exit lz4hc_mod_fini(void)
 {
 	crypto_unregister_alg(&alg_lz4hc);
+	crypto_unregister_scomp(&scomp);
 }
 
 module_init(lz4hc_mod_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/lzo.c linux-libre-4.10-rc8-gnu/crypto/lzo.c
--- linux-libre-4.9-gnu/crypto/lzo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/lzo.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,40 +22,55 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/lzo.h>
+#include <crypto/internal/scompress.h>
 
 struct lzo_ctx {
 	void *lzo_comp_mem;
 };
 
+static void *lzo_alloc_ctx(struct crypto_scomp *tfm)
+{
+	void *ctx;
+
+	ctx = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_NOWARN);
+	if (!ctx)
+		ctx = vmalloc(LZO1X_MEM_COMPRESS);
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
+
+	return ctx;
+}
+
 static int lzo_init(struct crypto_tfm *tfm)
 {
 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS,
-				    GFP_KERNEL | __GFP_NOWARN);
-	if (!ctx->lzo_comp_mem)
-		ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
-	if (!ctx->lzo_comp_mem)
+	ctx->lzo_comp_mem = lzo_alloc_ctx(NULL);
+	if (IS_ERR(ctx->lzo_comp_mem))
 		return -ENOMEM;
 
 	return 0;
 }
 
+static void lzo_free_ctx(struct crypto_scomp *tfm, void *ctx)
+{
+	kvfree(ctx);
+}
+
 static void lzo_exit(struct crypto_tfm *tfm)
 {
 	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	kvfree(ctx->lzo_comp_mem);
+	lzo_free_ctx(NULL, ctx->lzo_comp_mem);
 }
 
-static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
-			    unsigned int slen, u8 *dst, unsigned int *dlen)
+static int __lzo_compress(const u8 *src, unsigned int slen,
+			  u8 *dst, unsigned int *dlen, void *ctx)
 {
-	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
 	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
 	int err;
 
-	err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx->lzo_comp_mem);
+	err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx);
 
 	if (err != LZO_E_OK)
 		return -EINVAL;
@@ -64,8 +79,23 @@ static int lzo_compress(struct crypto_tf
 	return 0;
 }
 
-static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
-			      unsigned int slen, u8 *dst, unsigned int *dlen)
+static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
+			unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	return __lzo_compress(src, slen, dst, dlen, ctx->lzo_comp_mem);
+}
+
+static int lzo_scompress(struct crypto_scomp *tfm, const u8 *src,
+			 unsigned int slen, u8 *dst, unsigned int *dlen,
+			 void *ctx)
+{
+	return __lzo_compress(src, slen, dst, dlen, ctx);
+}
+
+static int __lzo_decompress(const u8 *src, unsigned int slen,
+			    u8 *dst, unsigned int *dlen)
 {
 	int err;
 	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
@@ -77,7 +107,19 @@ static int lzo_decompress(struct crypto_
 
 	*dlen = tmp_len;
 	return 0;
+}
+
+static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
+			  unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+	return __lzo_decompress(src, slen, dst, dlen);
+}
 
+static int lzo_sdecompress(struct crypto_scomp *tfm, const u8 *src,
+			   unsigned int slen, u8 *dst, unsigned int *dlen,
+			   void *ctx)
+{
+	return __lzo_decompress(src, slen, dst, dlen);
 }
 
 static struct crypto_alg alg = {
@@ -88,18 +130,43 @@ static struct crypto_alg alg = {
 	.cra_init		= lzo_init,
 	.cra_exit		= lzo_exit,
 	.cra_u			= { .compress = {
-	.coa_compress 		= lzo_compress,
-	.coa_decompress  	= lzo_decompress } }
+	.coa_compress		= lzo_compress,
+	.coa_decompress		= lzo_decompress } }
+};
+
+static struct scomp_alg scomp = {
+	.alloc_ctx		= lzo_alloc_ctx,
+	.free_ctx		= lzo_free_ctx,
+	.compress		= lzo_scompress,
+	.decompress		= lzo_sdecompress,
+	.base			= {
+		.cra_name	= "lzo",
+		.cra_driver_name = "lzo-scomp",
+		.cra_module	 = THIS_MODULE,
+	}
 };
 
 static int __init lzo_mod_init(void)
 {
-	return crypto_register_alg(&alg);
+	int ret;
+
+	ret = crypto_register_alg(&alg);
+	if (ret)
+		return ret;
+
+	ret = crypto_register_scomp(&scomp);
+	if (ret) {
+		crypto_unregister_alg(&alg);
+		return ret;
+	}
+
+	return ret;
 }
 
 static void __exit lzo_mod_fini(void)
 {
 	crypto_unregister_alg(&alg);
+	crypto_unregister_scomp(&scomp);
 }
 
 module_init(lzo_mod_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/Makefile linux-libre-4.10-rc8-gnu/crypto/Makefile
--- linux-libre-4.9-gnu/crypto/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -51,6 +51,10 @@ rsa_generic-y += rsa_helper.o
 rsa_generic-y += rsa-pkcs1pad.o
 obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
 
+crypto_acompress-y := acompress.o
+crypto_acompress-y += scompress.o
+obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o
+
 cryptomgr-y := algboss.o testmgr.o
 
 obj-$(CONFIG_CRYPTO_MANAGER2) += cryptomgr.o
@@ -139,3 +143,5 @@ obj-$(CONFIG_ASYNC_CORE) += async_tx/
 obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
 obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
 obj-$(CONFIG_CRYPTO_ABLK_HELPER) += ablk_helper.o
+crypto_simd-y := simd.o
+obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/pcbc.c linux-libre-4.10-rc8-gnu/crypto/pcbc.c
--- linux-libre-4.9-gnu/crypto/pcbc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/pcbc.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,40 +14,37 @@
  *
  */
 
-#include <crypto/algapi.h>
+#include <crypto/internal/skcipher.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/scatterlist.h>
 #include <linux/slab.h>
 
 struct crypto_pcbc_ctx {
 	struct crypto_cipher *child;
 };
 
-static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
+static int crypto_pcbc_setkey(struct crypto_skcipher *parent, const u8 *key,
 			      unsigned int keylen)
 {
-	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(parent);
+	struct crypto_pcbc_ctx *ctx = crypto_skcipher_ctx(parent);
 	struct crypto_cipher *child = ctx->child;
 	int err;
 
 	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
-				CRYPTO_TFM_REQ_MASK);
+	crypto_cipher_set_flags(child, crypto_skcipher_get_flags(parent) &
+				       CRYPTO_TFM_REQ_MASK);
 	err = crypto_cipher_setkey(child, key, keylen);
-	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
-			     CRYPTO_TFM_RES_MASK);
+	crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(child) &
+					  CRYPTO_TFM_RES_MASK);
 	return err;
 }
 
-static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
-				       struct blkcipher_walk *walk,
+static int crypto_pcbc_encrypt_segment(struct skcipher_request *req,
+				       struct skcipher_walk *walk,
 				       struct crypto_cipher *tfm)
 {
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_encrypt;
 	int bsize = crypto_cipher_blocksize(tfm);
 	unsigned int nbytes = walk->nbytes;
 	u8 *src = walk->src.virt.addr;
@@ -56,7 +53,7 @@ static int crypto_pcbc_encrypt_segment(s
 
 	do {
 		crypto_xor(iv, src, bsize);
-		fn(crypto_cipher_tfm(tfm), dst, iv);
+		crypto_cipher_encrypt_one(tfm, dst, iv);
 		memcpy(iv, dst, bsize);
 		crypto_xor(iv, src, bsize);
 
@@ -67,12 +64,10 @@ static int crypto_pcbc_encrypt_segment(s
 	return nbytes;
 }
 
-static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
-				       struct blkcipher_walk *walk,
+static int crypto_pcbc_encrypt_inplace(struct skcipher_request *req,
+				       struct skcipher_walk *walk,
 				       struct crypto_cipher *tfm)
 {
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_encrypt;
 	int bsize = crypto_cipher_blocksize(tfm);
 	unsigned int nbytes = walk->nbytes;
 	u8 *src = walk->src.virt.addr;
@@ -82,7 +77,7 @@ static int crypto_pcbc_encrypt_inplace(s
 	do {
 		memcpy(tmpbuf, src, bsize);
 		crypto_xor(iv, src, bsize);
-		fn(crypto_cipher_tfm(tfm), src, iv);
+		crypto_cipher_encrypt_one(tfm, src, iv);
 		memcpy(iv, tmpbuf, bsize);
 		crypto_xor(iv, src, bsize);
 
@@ -94,38 +89,34 @@ static int crypto_pcbc_encrypt_inplace(s
 	return nbytes;
 }
 
-static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
-			       struct scatterlist *dst, struct scatterlist *src,
-			       unsigned int nbytes)
+static int crypto_pcbc_encrypt(struct skcipher_request *req)
 {
-	struct blkcipher_walk walk;
-	struct crypto_blkcipher *tfm = desc->tfm;
-	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_pcbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 	struct crypto_cipher *child = ctx->child;
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, false);
 
 	while ((nbytes = walk.nbytes)) {
 		if (walk.src.virt.addr == walk.dst.virt.addr)
-			nbytes = crypto_pcbc_encrypt_inplace(desc, &walk,
+			nbytes = crypto_pcbc_encrypt_inplace(req, &walk,
 							     child);
 		else
-			nbytes = crypto_pcbc_encrypt_segment(desc, &walk,
+			nbytes = crypto_pcbc_encrypt_segment(req, &walk,
 							     child);
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 
 	return err;
 }
 
-static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
-				       struct blkcipher_walk *walk,
+static int crypto_pcbc_decrypt_segment(struct skcipher_request *req,
+				       struct skcipher_walk *walk,
 				       struct crypto_cipher *tfm)
 {
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_decrypt;
 	int bsize = crypto_cipher_blocksize(tfm);
 	unsigned int nbytes = walk->nbytes;
 	u8 *src = walk->src.virt.addr;
@@ -133,7 +124,7 @@ static int crypto_pcbc_decrypt_segment(s
 	u8 *iv = walk->iv;
 
 	do {
-		fn(crypto_cipher_tfm(tfm), dst, src);
+		crypto_cipher_decrypt_one(tfm, dst, src);
 		crypto_xor(dst, iv, bsize);
 		memcpy(iv, src, bsize);
 		crypto_xor(iv, dst, bsize);
@@ -147,21 +138,19 @@ static int crypto_pcbc_decrypt_segment(s
 	return nbytes;
 }
 
-static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
-				       struct blkcipher_walk *walk,
+static int crypto_pcbc_decrypt_inplace(struct skcipher_request *req,
+				       struct skcipher_walk *walk,
 				       struct crypto_cipher *tfm)
 {
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-		crypto_cipher_alg(tfm)->cia_decrypt;
 	int bsize = crypto_cipher_blocksize(tfm);
 	unsigned int nbytes = walk->nbytes;
 	u8 *src = walk->src.virt.addr;
 	u8 *iv = walk->iv;
-	u8 tmpbuf[bsize];
+	u8 tmpbuf[bsize] __attribute__ ((aligned(__alignof__(u32))));
 
 	do {
 		memcpy(tmpbuf, src, bsize);
-		fn(crypto_cipher_tfm(tfm), src, src);
+		crypto_cipher_decrypt_one(tfm, src, src);
 		crypto_xor(src, iv, bsize);
 		memcpy(iv, tmpbuf, bsize);
 		crypto_xor(iv, src, bsize);
@@ -174,37 +163,35 @@ static int crypto_pcbc_decrypt_inplace(s
 	return nbytes;
 }
 
-static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
-			       struct scatterlist *dst, struct scatterlist *src,
-			       unsigned int nbytes)
+static int crypto_pcbc_decrypt(struct skcipher_request *req)
 {
-	struct blkcipher_walk walk;
-	struct crypto_blkcipher *tfm = desc->tfm;
-	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct crypto_pcbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 	struct crypto_cipher *child = ctx->child;
+	struct skcipher_walk walk;
+	unsigned int nbytes;
 	int err;
 
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
+	err = skcipher_walk_virt(&walk, req, false);
 
 	while ((nbytes = walk.nbytes)) {
 		if (walk.src.virt.addr == walk.dst.virt.addr)
-			nbytes = crypto_pcbc_decrypt_inplace(desc, &walk,
+			nbytes = crypto_pcbc_decrypt_inplace(req, &walk,
 							     child);
 		else
-			nbytes = crypto_pcbc_decrypt_segment(desc, &walk,
+			nbytes = crypto_pcbc_decrypt_segment(req, &walk,
 							     child);
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 
 	return err;
 }
 
-static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
+static int crypto_pcbc_init_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
-	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
+	struct crypto_spawn *spawn = skcipher_instance_ctx(inst);
+	struct crypto_pcbc_ctx *ctx = crypto_skcipher_ctx(tfm);
 	struct crypto_cipher *cipher;
 
 	cipher = crypto_spawn_cipher(spawn);
@@ -215,68 +202,98 @@ static int crypto_pcbc_init_tfm(struct c
 	return 0;
 }
 
-static void crypto_pcbc_exit_tfm(struct crypto_tfm *tfm)
+static void crypto_pcbc_exit_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_pcbc_ctx *ctx = crypto_skcipher_ctx(tfm);
+
 	crypto_free_cipher(ctx->child);
 }
 
-static struct crypto_instance *crypto_pcbc_alloc(struct rtattr **tb)
+static void crypto_pcbc_free(struct skcipher_instance *inst)
 {
-	struct crypto_instance *inst;
+	crypto_drop_skcipher(skcipher_instance_ctx(inst));
+	kfree(inst);
+}
+
+static int crypto_pcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct skcipher_instance *inst;
+	struct crypto_attr_type *algt;
+	struct crypto_spawn *spawn;
 	struct crypto_alg *alg;
 	int err;
 
-	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
-	if (err)
-		return ERR_PTR(err);
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return PTR_ERR(algt);
 
-	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK);
+	if (((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask) &
+	    ~CRYPTO_ALG_INTERNAL)
+		return -EINVAL;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER |
+				      (algt->type & CRYPTO_ALG_INTERNAL),
+				  CRYPTO_ALG_TYPE_MASK |
+				  (algt->mask & CRYPTO_ALG_INTERNAL));
+	err = PTR_ERR(alg);
 	if (IS_ERR(alg))
-		return ERR_CAST(alg);
+		goto err_free_inst;
 
-	inst = crypto_alloc_instance("pcbc", alg);
-	if (IS_ERR(inst))
-		goto out_put_alg;
+	spawn = skcipher_instance_ctx(inst);
+	err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
+				CRYPTO_ALG_TYPE_MASK);
+	crypto_mod_put(alg);
+	if (err)
+		goto err_free_inst;
 
-	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
-	inst->alg.cra_priority = alg->cra_priority;
-	inst->alg.cra_blocksize = alg->cra_blocksize;
-	inst->alg.cra_alignmask = alg->cra_alignmask;
-	inst->alg.cra_type = &crypto_blkcipher_type;
+	err = crypto_inst_setname(skcipher_crypto_instance(inst), "pcbc", alg);
+	if (err)
+		goto err_drop_spawn;
+
+	inst->alg.base.cra_flags = alg->cra_flags & CRYPTO_ALG_INTERNAL;
+	inst->alg.base.cra_priority = alg->cra_priority;
+	inst->alg.base.cra_blocksize = alg->cra_blocksize;
+	inst->alg.base.cra_alignmask = alg->cra_alignmask;
 
 	/* We access the data as u32s when xoring. */
-	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
+	inst->alg.base.cra_alignmask |= __alignof__(u32) - 1;
 
-	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
-	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
-	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+	inst->alg.ivsize = alg->cra_blocksize;
+	inst->alg.min_keysize = alg->cra_cipher.cia_min_keysize;
+	inst->alg.max_keysize = alg->cra_cipher.cia_max_keysize;
 
-	inst->alg.cra_ctxsize = sizeof(struct crypto_pcbc_ctx);
+	inst->alg.base.cra_ctxsize = sizeof(struct crypto_pcbc_ctx);
 
-	inst->alg.cra_init = crypto_pcbc_init_tfm;
-	inst->alg.cra_exit = crypto_pcbc_exit_tfm;
+	inst->alg.init = crypto_pcbc_init_tfm;
+	inst->alg.exit = crypto_pcbc_exit_tfm;
 
-	inst->alg.cra_blkcipher.setkey = crypto_pcbc_setkey;
-	inst->alg.cra_blkcipher.encrypt = crypto_pcbc_encrypt;
-	inst->alg.cra_blkcipher.decrypt = crypto_pcbc_decrypt;
+	inst->alg.setkey = crypto_pcbc_setkey;
+	inst->alg.encrypt = crypto_pcbc_encrypt;
+	inst->alg.decrypt = crypto_pcbc_decrypt;
 
-out_put_alg:
-	crypto_mod_put(alg);
-	return inst;
-}
+	inst->free = crypto_pcbc_free;
 
-static void crypto_pcbc_free(struct crypto_instance *inst)
-{
-	crypto_drop_spawn(crypto_instance_ctx(inst));
+	err = skcipher_register_instance(tmpl, inst);
+	if (err)
+		goto err_drop_spawn;
+
+out:
+	return err;
+
+err_drop_spawn:
+	crypto_drop_spawn(spawn);
+err_free_inst:
 	kfree(inst);
+	goto out;
 }
 
 static struct crypto_template crypto_pcbc_tmpl = {
 	.name = "pcbc",
-	.alloc = crypto_pcbc_alloc,
-	.free = crypto_pcbc_free,
+	.create = crypto_pcbc_create,
 	.module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/poly1305_generic.c linux-libre-4.10-rc8-gnu/crypto/poly1305_generic.c
--- linux-libre-4.9-gnu/crypto/poly1305_generic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/poly1305_generic.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/crypto.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <asm/unaligned.h>
 
 static inline u64 mlt(u64 a, u64 b)
 {
@@ -33,11 +34,6 @@ static inline u32 and(u32 v, u32 mask)
 	return v & mask;
 }
 
-static inline u32 le32_to_cpuvp(const void *p)
-{
-	return le32_to_cpup(p);
-}
-
 int crypto_poly1305_init(struct shash_desc *desc)
 {
 	struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
@@ -65,19 +61,19 @@ EXPORT_SYMBOL_GPL(crypto_poly1305_setkey
 static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
 {
 	/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
-	dctx->r[0] = (le32_to_cpuvp(key +  0) >> 0) & 0x3ffffff;
-	dctx->r[1] = (le32_to_cpuvp(key +  3) >> 2) & 0x3ffff03;
-	dctx->r[2] = (le32_to_cpuvp(key +  6) >> 4) & 0x3ffc0ff;
-	dctx->r[3] = (le32_to_cpuvp(key +  9) >> 6) & 0x3f03fff;
-	dctx->r[4] = (le32_to_cpuvp(key + 12) >> 8) & 0x00fffff;
+	dctx->r[0] = (get_unaligned_le32(key +  0) >> 0) & 0x3ffffff;
+	dctx->r[1] = (get_unaligned_le32(key +  3) >> 2) & 0x3ffff03;
+	dctx->r[2] = (get_unaligned_le32(key +  6) >> 4) & 0x3ffc0ff;
+	dctx->r[3] = (get_unaligned_le32(key +  9) >> 6) & 0x3f03fff;
+	dctx->r[4] = (get_unaligned_le32(key + 12) >> 8) & 0x00fffff;
 }
 
 static void poly1305_setskey(struct poly1305_desc_ctx *dctx, const u8 *key)
 {
-	dctx->s[0] = le32_to_cpuvp(key +  0);
-	dctx->s[1] = le32_to_cpuvp(key +  4);
-	dctx->s[2] = le32_to_cpuvp(key +  8);
-	dctx->s[3] = le32_to_cpuvp(key + 12);
+	dctx->s[0] = get_unaligned_le32(key +  0);
+	dctx->s[1] = get_unaligned_le32(key +  4);
+	dctx->s[2] = get_unaligned_le32(key +  8);
+	dctx->s[3] = get_unaligned_le32(key + 12);
 }
 
 unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
@@ -137,11 +133,11 @@ static unsigned int poly1305_blocks(stru
 	while (likely(srclen >= POLY1305_BLOCK_SIZE)) {
 
 		/* h += m[i] */
-		h0 += (le32_to_cpuvp(src +  0) >> 0) & 0x3ffffff;
-		h1 += (le32_to_cpuvp(src +  3) >> 2) & 0x3ffffff;
-		h2 += (le32_to_cpuvp(src +  6) >> 4) & 0x3ffffff;
-		h3 += (le32_to_cpuvp(src +  9) >> 6) & 0x3ffffff;
-		h4 += (le32_to_cpuvp(src + 12) >> 8) | hibit;
+		h0 += (get_unaligned_le32(src +  0) >> 0) & 0x3ffffff;
+		h1 += (get_unaligned_le32(src +  3) >> 2) & 0x3ffffff;
+		h2 += (get_unaligned_le32(src +  6) >> 4) & 0x3ffffff;
+		h3 += (get_unaligned_le32(src +  9) >> 6) & 0x3ffffff;
+		h4 += (get_unaligned_le32(src + 12) >> 8) | hibit;
 
 		/* h *= r */
 		d0 = mlt(h0, r0) + mlt(h1, s4) + mlt(h2, s3) +
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/scompress.c linux-libre-4.10-rc8-gnu/crypto/scompress.c
--- linux-libre-4.9-gnu/crypto/scompress.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/scompress.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,356 @@
+/*
+ * Synchronous Compression operations
+ *
+ * Copyright 2015 LG Electronics Inc.
+ * Copyright (c) 2016, Intel Corporation
+ * Author: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/vmalloc.h>
+#include <crypto/algapi.h>
+#include <linux/cryptouser.h>
+#include <net/netlink.h>
+#include <linux/scatterlist.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/internal/acompress.h>
+#include <crypto/internal/scompress.h>
+#include "internal.h"
+
+static const struct crypto_type crypto_scomp_type;
+static void * __percpu *scomp_src_scratches;
+static void * __percpu *scomp_dst_scratches;
+static int scomp_scratch_users;
+static DEFINE_MUTEX(scomp_lock);
+
+#ifdef CONFIG_NET
+static int crypto_scomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	struct crypto_report_comp rscomp;
+
+	strncpy(rscomp.type, "scomp", sizeof(rscomp.type));
+
+	if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
+		    sizeof(struct crypto_report_comp), &rscomp))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+#else
+static int crypto_scomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+	return -ENOSYS;
+}
+#endif
+
+static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
+	__attribute__ ((unused));
+
+static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
+{
+	seq_puts(m, "type         : scomp\n");
+}
+
+static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
+{
+	return 0;
+}
+
+static void crypto_scomp_free_scratches(void * __percpu *scratches)
+{
+	int i;
+
+	if (!scratches)
+		return;
+
+	for_each_possible_cpu(i)
+		vfree(*per_cpu_ptr(scratches, i));
+
+	free_percpu(scratches);
+}
+
+static void * __percpu *crypto_scomp_alloc_scratches(void)
+{
+	void * __percpu *scratches;
+	int i;
+
+	scratches = alloc_percpu(void *);
+	if (!scratches)
+		return NULL;
+
+	for_each_possible_cpu(i) {
+		void *scratch;
+
+		scratch = vmalloc_node(SCOMP_SCRATCH_SIZE, cpu_to_node(i));
+		if (!scratch)
+			goto error;
+		*per_cpu_ptr(scratches, i) = scratch;
+	}
+
+	return scratches;
+
+error:
+	crypto_scomp_free_scratches(scratches);
+	return NULL;
+}
+
+static void crypto_scomp_free_all_scratches(void)
+{
+	if (!--scomp_scratch_users) {
+		crypto_scomp_free_scratches(scomp_src_scratches);
+		crypto_scomp_free_scratches(scomp_dst_scratches);
+		scomp_src_scratches = NULL;
+		scomp_dst_scratches = NULL;
+	}
+}
+
+static int crypto_scomp_alloc_all_scratches(void)
+{
+	if (!scomp_scratch_users++) {
+		scomp_src_scratches = crypto_scomp_alloc_scratches();
+		if (!scomp_src_scratches)
+			return -ENOMEM;
+		scomp_dst_scratches = crypto_scomp_alloc_scratches();
+		if (!scomp_dst_scratches)
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+static void crypto_scomp_sg_free(struct scatterlist *sgl)
+{
+	int i, n;
+	struct page *page;
+
+	if (!sgl)
+		return;
+
+	n = sg_nents(sgl);
+	for_each_sg(sgl, sgl, n, i) {
+		page = sg_page(sgl);
+		if (page)
+			__free_page(page);
+	}
+
+	kfree(sgl);
+}
+
+static struct scatterlist *crypto_scomp_sg_alloc(size_t size, gfp_t gfp)
+{
+	struct scatterlist *sgl;
+	struct page *page;
+	int i, n;
+
+	n = ((size - 1) >> PAGE_SHIFT) + 1;
+
+	sgl = kmalloc_array(n, sizeof(struct scatterlist), gfp);
+	if (!sgl)
+		return NULL;
+
+	sg_init_table(sgl, n);
+
+	for (i = 0; i < n; i++) {
+		page = alloc_page(gfp);
+		if (!page)
+			goto err;
+		sg_set_page(sgl + i, page, PAGE_SIZE, 0);
+	}
+
+	return sgl;
+
+err:
+	sg_mark_end(sgl + i);
+	crypto_scomp_sg_free(sgl);
+	return NULL;
+}
+
+static int scomp_acomp_comp_decomp(struct acomp_req *req, int dir)
+{
+	struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
+	void **tfm_ctx = acomp_tfm_ctx(tfm);
+	struct crypto_scomp *scomp = *tfm_ctx;
+	void **ctx = acomp_request_ctx(req);
+	const int cpu = get_cpu();
+	u8 *scratch_src = *per_cpu_ptr(scomp_src_scratches, cpu);
+	u8 *scratch_dst = *per_cpu_ptr(scomp_dst_scratches, cpu);
+	int ret;
+
+	if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (req->dst && !req->dlen) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (!req->dlen || req->dlen > SCOMP_SCRATCH_SIZE)
+		req->dlen = SCOMP_SCRATCH_SIZE;
+
+	scatterwalk_map_and_copy(scratch_src, req->src, 0, req->slen, 0);
+	if (dir)
+		ret = crypto_scomp_compress(scomp, scratch_src, req->slen,
+					    scratch_dst, &req->dlen, *ctx);
+	else
+		ret = crypto_scomp_decompress(scomp, scratch_src, req->slen,
+					      scratch_dst, &req->dlen, *ctx);
+	if (!ret) {
+		if (!req->dst) {
+			req->dst = crypto_scomp_sg_alloc(req->dlen,
+				   req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
+				   GFP_KERNEL : GFP_ATOMIC);
+			if (!req->dst)
+				goto out;
+		}
+		scatterwalk_map_and_copy(scratch_dst, req->dst, 0, req->dlen,
+					 1);
+	}
+out:
+	put_cpu();
+	return ret;
+}
+
+static int scomp_acomp_compress(struct acomp_req *req)
+{
+	return scomp_acomp_comp_decomp(req, 1);
+}
+
+static int scomp_acomp_decompress(struct acomp_req *req)
+{
+	return scomp_acomp_comp_decomp(req, 0);
+}
+
+static void crypto_exit_scomp_ops_async(struct crypto_tfm *tfm)
+{
+	struct crypto_scomp **ctx = crypto_tfm_ctx(tfm);
+
+	crypto_free_scomp(*ctx);
+}
+
+int crypto_init_scomp_ops_async(struct crypto_tfm *tfm)
+{
+	struct crypto_alg *calg = tfm->__crt_alg;
+	struct crypto_acomp *crt = __crypto_acomp_tfm(tfm);
+	struct crypto_scomp **ctx = crypto_tfm_ctx(tfm);
+	struct crypto_scomp *scomp;
+
+	if (!crypto_mod_get(calg))
+		return -EAGAIN;
+
+	scomp = crypto_create_tfm(calg, &crypto_scomp_type);
+	if (IS_ERR(scomp)) {
+		crypto_mod_put(calg);
+		return PTR_ERR(scomp);
+	}
+
+	*ctx = scomp;
+	tfm->exit = crypto_exit_scomp_ops_async;
+
+	crt->compress = scomp_acomp_compress;
+	crt->decompress = scomp_acomp_decompress;
+	crt->dst_free = crypto_scomp_sg_free;
+	crt->reqsize = sizeof(void *);
+
+	return 0;
+}
+
+struct acomp_req *crypto_acomp_scomp_alloc_ctx(struct acomp_req *req)
+{
+	struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+	struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
+	struct crypto_scomp *scomp = *tfm_ctx;
+	void *ctx;
+
+	ctx = crypto_scomp_alloc_ctx(scomp);
+	if (IS_ERR(ctx)) {
+		kfree(req);
+		return NULL;
+	}
+
+	*req->__ctx = ctx;
+
+	return req;
+}
+
+void crypto_acomp_scomp_free_ctx(struct acomp_req *req)
+{
+	struct crypto_acomp *acomp = crypto_acomp_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_acomp_tfm(acomp);
+	struct crypto_scomp **tfm_ctx = crypto_tfm_ctx(tfm);
+	struct crypto_scomp *scomp = *tfm_ctx;
+	void *ctx = *req->__ctx;
+
+	if (ctx)
+		crypto_scomp_free_ctx(scomp, ctx);
+}
+
+static const struct crypto_type crypto_scomp_type = {
+	.extsize = crypto_alg_extsize,
+	.init_tfm = crypto_scomp_init_tfm,
+#ifdef CONFIG_PROC_FS
+	.show = crypto_scomp_show,
+#endif
+	.report = crypto_scomp_report,
+	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
+	.maskset = CRYPTO_ALG_TYPE_MASK,
+	.type = CRYPTO_ALG_TYPE_SCOMPRESS,
+	.tfmsize = offsetof(struct crypto_scomp, base),
+};
+
+int crypto_register_scomp(struct scomp_alg *alg)
+{
+	struct crypto_alg *base = &alg->base;
+	int ret = -ENOMEM;
+
+	mutex_lock(&scomp_lock);
+	if (crypto_scomp_alloc_all_scratches())
+		goto error;
+
+	base->cra_type = &crypto_scomp_type;
+	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
+	base->cra_flags |= CRYPTO_ALG_TYPE_SCOMPRESS;
+
+	ret = crypto_register_alg(base);
+	if (ret)
+		goto error;
+
+	mutex_unlock(&scomp_lock);
+	return ret;
+
+error:
+	crypto_scomp_free_all_scratches();
+	mutex_unlock(&scomp_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(crypto_register_scomp);
+
+int crypto_unregister_scomp(struct scomp_alg *alg)
+{
+	int ret;
+
+	mutex_lock(&scomp_lock);
+	ret = crypto_unregister_alg(&alg->base);
+	crypto_scomp_free_all_scratches();
+	mutex_unlock(&scomp_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(crypto_unregister_scomp);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Synchronous compression type");
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/simd.c linux-libre-4.10-rc8-gnu/crypto/simd.c
--- linux-libre-4.9-gnu/crypto/simd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/simd.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,226 @@
+/*
+ * Shared crypto simd helpers
+ *
+ * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+ * Copyright (c) 2016 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * Based on aesni-intel_glue.c by:
+ *  Copyright (C) 2008, Intel Corp.
+ *    Author: Huang Ying <ying.huang@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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/cryptd.h>
+#include <crypto/internal/simd.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <asm/simd.h>
+
+struct simd_skcipher_alg {
+	const char *ialg_name;
+	struct skcipher_alg alg;
+};
+
+struct simd_skcipher_ctx {
+	struct cryptd_skcipher *cryptd_tfm;
+};
+
+static int simd_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
+				unsigned int key_len)
+{
+	struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *child = &ctx->cryptd_tfm->base;
+	int err;
+
+	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(tfm) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_skcipher_setkey(child, key, key_len);
+	crypto_skcipher_set_flags(tfm, crypto_skcipher_get_flags(child) &
+				       CRYPTO_TFM_RES_MASK);
+	return err;
+}
+
+static int simd_skcipher_encrypt(struct skcipher_request *req)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_request *subreq;
+	struct crypto_skcipher *child;
+
+	subreq = skcipher_request_ctx(req);
+	*subreq = *req;
+
+	if (!may_use_simd() ||
+	    (in_atomic() && cryptd_skcipher_queued(ctx->cryptd_tfm)))
+		child = &ctx->cryptd_tfm->base;
+	else
+		child = cryptd_skcipher_child(ctx->cryptd_tfm);
+
+	skcipher_request_set_tfm(subreq, child);
+
+	return crypto_skcipher_encrypt(subreq);
+}
+
+static int simd_skcipher_decrypt(struct skcipher_request *req)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_request *subreq;
+	struct crypto_skcipher *child;
+
+	subreq = skcipher_request_ctx(req);
+	*subreq = *req;
+
+	if (!may_use_simd() ||
+	    (in_atomic() && cryptd_skcipher_queued(ctx->cryptd_tfm)))
+		child = &ctx->cryptd_tfm->base;
+	else
+		child = cryptd_skcipher_child(ctx->cryptd_tfm);
+
+	skcipher_request_set_tfm(subreq, child);
+
+	return crypto_skcipher_decrypt(subreq);
+}
+
+static void simd_skcipher_exit(struct crypto_skcipher *tfm)
+{
+	struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+	cryptd_free_skcipher(ctx->cryptd_tfm);
+}
+
+static int simd_skcipher_init(struct crypto_skcipher *tfm)
+{
+	struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct cryptd_skcipher *cryptd_tfm;
+	struct simd_skcipher_alg *salg;
+	struct skcipher_alg *alg;
+	unsigned reqsize;
+
+	alg = crypto_skcipher_alg(tfm);
+	salg = container_of(alg, struct simd_skcipher_alg, alg);
+
+	cryptd_tfm = cryptd_alloc_skcipher(salg->ialg_name,
+					   CRYPTO_ALG_INTERNAL,
+					   CRYPTO_ALG_INTERNAL);
+	if (IS_ERR(cryptd_tfm))
+		return PTR_ERR(cryptd_tfm);
+
+	ctx->cryptd_tfm = cryptd_tfm;
+
+	reqsize = sizeof(struct skcipher_request);
+	reqsize += crypto_skcipher_reqsize(&cryptd_tfm->base);
+
+	crypto_skcipher_set_reqsize(tfm, reqsize);
+
+	return 0;
+}
+
+struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
+						      const char *drvname,
+						      const char *basename)
+{
+	struct simd_skcipher_alg *salg;
+	struct crypto_skcipher *tfm;
+	struct skcipher_alg *ialg;
+	struct skcipher_alg *alg;
+	int err;
+
+	tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL,
+				    CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tfm))
+		return ERR_CAST(tfm);
+
+	ialg = crypto_skcipher_alg(tfm);
+
+	salg = kzalloc(sizeof(*salg), GFP_KERNEL);
+	if (!salg) {
+		salg = ERR_PTR(-ENOMEM);
+		goto out_put_tfm;
+	}
+
+	salg->ialg_name = basename;
+	alg = &salg->alg;
+
+	err = -ENAMETOOLONG;
+	if (snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", algname) >=
+	    CRYPTO_MAX_ALG_NAME)
+		goto out_free_salg;
+
+	if (snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+		     drvname) >= CRYPTO_MAX_ALG_NAME)
+		goto out_free_salg;
+
+	alg->base.cra_flags = CRYPTO_ALG_ASYNC;
+	alg->base.cra_priority = ialg->base.cra_priority;
+	alg->base.cra_blocksize = ialg->base.cra_blocksize;
+	alg->base.cra_alignmask = ialg->base.cra_alignmask;
+	alg->base.cra_module = ialg->base.cra_module;
+	alg->base.cra_ctxsize = sizeof(struct simd_skcipher_ctx);
+
+	alg->ivsize = ialg->ivsize;
+	alg->chunksize = ialg->chunksize;
+	alg->min_keysize = ialg->min_keysize;
+	alg->max_keysize = ialg->max_keysize;
+
+	alg->init = simd_skcipher_init;
+	alg->exit = simd_skcipher_exit;
+
+	alg->setkey = simd_skcipher_setkey;
+	alg->encrypt = simd_skcipher_encrypt;
+	alg->decrypt = simd_skcipher_decrypt;
+
+	err = crypto_register_skcipher(alg);
+	if (err)
+		goto out_free_salg;
+
+out_put_tfm:
+	crypto_free_skcipher(tfm);
+	return salg;
+
+out_free_salg:
+	kfree(salg);
+	salg = ERR_PTR(err);
+	goto out_put_tfm;
+}
+EXPORT_SYMBOL_GPL(simd_skcipher_create_compat);
+
+struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
+					       const char *basename)
+{
+	char drvname[CRYPTO_MAX_ALG_NAME];
+
+	if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
+	    CRYPTO_MAX_ALG_NAME)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	return simd_skcipher_create_compat(algname, drvname, basename);
+}
+EXPORT_SYMBOL_GPL(simd_skcipher_create);
+
+void simd_skcipher_free(struct simd_skcipher_alg *salg)
+{
+	crypto_unregister_skcipher(&salg->alg);
+	kfree(salg);
+}
+EXPORT_SYMBOL_GPL(simd_skcipher_free);
+
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/skcipher.c linux-libre-4.10-rc8-gnu/crypto/skcipher.c
--- linux-libre-4.9-gnu/crypto/skcipher.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/skcipher.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,9 +14,12 @@
  *
  */
 
+#include <crypto/internal/aead.h>
 #include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
 #include <linux/bug.h>
 #include <linux/cryptouser.h>
+#include <linux/list.h>
 #include <linux/module.h>
 #include <linux/rtnetlink.h>
 #include <linux/seq_file.h>
@@ -24,6 +27,545 @@
 
 #include "internal.h"
 
+enum {
+	SKCIPHER_WALK_PHYS = 1 << 0,
+	SKCIPHER_WALK_SLOW = 1 << 1,
+	SKCIPHER_WALK_COPY = 1 << 2,
+	SKCIPHER_WALK_DIFF = 1 << 3,
+	SKCIPHER_WALK_SLEEP = 1 << 4,
+};
+
+struct skcipher_walk_buffer {
+	struct list_head entry;
+	struct scatter_walk dst;
+	unsigned int len;
+	u8 *data;
+	u8 buffer[];
+};
+
+static int skcipher_walk_next(struct skcipher_walk *walk);
+
+static inline void skcipher_unmap(struct scatter_walk *walk, void *vaddr)
+{
+	if (PageHighMem(scatterwalk_page(walk)))
+		kunmap_atomic(vaddr);
+}
+
+static inline void *skcipher_map(struct scatter_walk *walk)
+{
+	struct page *page = scatterwalk_page(walk);
+
+	return (PageHighMem(page) ? kmap_atomic(page) : page_address(page)) +
+	       offset_in_page(walk->offset);
+}
+
+static inline void skcipher_map_src(struct skcipher_walk *walk)
+{
+	walk->src.virt.addr = skcipher_map(&walk->in);
+}
+
+static inline void skcipher_map_dst(struct skcipher_walk *walk)
+{
+	walk->dst.virt.addr = skcipher_map(&walk->out);
+}
+
+static inline void skcipher_unmap_src(struct skcipher_walk *walk)
+{
+	skcipher_unmap(&walk->in, walk->src.virt.addr);
+}
+
+static inline void skcipher_unmap_dst(struct skcipher_walk *walk)
+{
+	skcipher_unmap(&walk->out, walk->dst.virt.addr);
+}
+
+static inline gfp_t skcipher_walk_gfp(struct skcipher_walk *walk)
+{
+	return walk->flags & SKCIPHER_WALK_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
+}
+
+/* Get a spot of the specified length that does not straddle a page.
+ * The caller needs to ensure that there is enough space for this operation.
+ */
+static inline u8 *skcipher_get_spot(u8 *start, unsigned int len)
+{
+	u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK);
+
+	return max(start, end_page);
+}
+
+static int skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize)
+{
+	u8 *addr;
+
+	addr = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1);
+	addr = skcipher_get_spot(addr, bsize);
+	scatterwalk_copychunks(addr, &walk->out, bsize,
+			       (walk->flags & SKCIPHER_WALK_PHYS) ? 2 : 1);
+	return 0;
+}
+
+int skcipher_walk_done(struct skcipher_walk *walk, int err)
+{
+	unsigned int n = walk->nbytes - err;
+	unsigned int nbytes;
+
+	nbytes = walk->total - n;
+
+	if (unlikely(err < 0)) {
+		nbytes = 0;
+		n = 0;
+	} else if (likely(!(walk->flags & (SKCIPHER_WALK_PHYS |
+					   SKCIPHER_WALK_SLOW |
+					   SKCIPHER_WALK_COPY |
+					   SKCIPHER_WALK_DIFF)))) {
+unmap_src:
+		skcipher_unmap_src(walk);
+	} else if (walk->flags & SKCIPHER_WALK_DIFF) {
+		skcipher_unmap_dst(walk);
+		goto unmap_src;
+	} else if (walk->flags & SKCIPHER_WALK_COPY) {
+		skcipher_map_dst(walk);
+		memcpy(walk->dst.virt.addr, walk->page, n);
+		skcipher_unmap_dst(walk);
+	} else if (unlikely(walk->flags & SKCIPHER_WALK_SLOW)) {
+		if (WARN_ON(err)) {
+			err = -EINVAL;
+			nbytes = 0;
+		} else
+			n = skcipher_done_slow(walk, n);
+	}
+
+	if (err > 0)
+		err = 0;
+
+	walk->total = nbytes;
+	walk->nbytes = nbytes;
+
+	scatterwalk_advance(&walk->in, n);
+	scatterwalk_advance(&walk->out, n);
+	scatterwalk_done(&walk->in, 0, nbytes);
+	scatterwalk_done(&walk->out, 1, nbytes);
+
+	if (nbytes) {
+		crypto_yield(walk->flags & SKCIPHER_WALK_SLEEP ?
+			     CRYPTO_TFM_REQ_MAY_SLEEP : 0);
+		return skcipher_walk_next(walk);
+	}
+
+	/* Short-circuit for the common/fast path. */
+	if (!((unsigned long)walk->buffer | (unsigned long)walk->page))
+		goto out;
+
+	if (walk->flags & SKCIPHER_WALK_PHYS)
+		goto out;
+
+	if (walk->iv != walk->oiv)
+		memcpy(walk->oiv, walk->iv, walk->ivsize);
+	if (walk->buffer != walk->page)
+		kfree(walk->buffer);
+	if (walk->page)
+		free_page((unsigned long)walk->page);
+
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_done);
+
+void skcipher_walk_complete(struct skcipher_walk *walk, int err)
+{
+	struct skcipher_walk_buffer *p, *tmp;
+
+	list_for_each_entry_safe(p, tmp, &walk->buffers, entry) {
+		u8 *data;
+
+		if (err)
+			goto done;
+
+		data = p->data;
+		if (!data) {
+			data = PTR_ALIGN(&p->buffer[0], walk->alignmask + 1);
+			data = skcipher_get_spot(data, walk->chunksize);
+		}
+
+		scatterwalk_copychunks(data, &p->dst, p->len, 1);
+
+		if (offset_in_page(p->data) + p->len + walk->chunksize >
+		    PAGE_SIZE)
+			free_page((unsigned long)p->data);
+
+done:
+		list_del(&p->entry);
+		kfree(p);
+	}
+
+	if (!err && walk->iv != walk->oiv)
+		memcpy(walk->oiv, walk->iv, walk->ivsize);
+	if (walk->buffer != walk->page)
+		kfree(walk->buffer);
+	if (walk->page)
+		free_page((unsigned long)walk->page);
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_complete);
+
+static void skcipher_queue_write(struct skcipher_walk *walk,
+				 struct skcipher_walk_buffer *p)
+{
+	p->dst = walk->out;
+	list_add_tail(&p->entry, &walk->buffers);
+}
+
+static int skcipher_next_slow(struct skcipher_walk *walk, unsigned int bsize)
+{
+	bool phys = walk->flags & SKCIPHER_WALK_PHYS;
+	unsigned alignmask = walk->alignmask;
+	struct skcipher_walk_buffer *p;
+	unsigned a;
+	unsigned n;
+	u8 *buffer;
+	void *v;
+
+	if (!phys) {
+		if (!walk->buffer)
+			walk->buffer = walk->page;
+		buffer = walk->buffer;
+		if (buffer)
+			goto ok;
+	}
+
+	/* Start with the minimum alignment of kmalloc. */
+	a = crypto_tfm_ctx_alignment() - 1;
+	n = bsize;
+
+	if (phys) {
+		/* Calculate the minimum alignment of p->buffer. */
+		a &= (sizeof(*p) ^ (sizeof(*p) - 1)) >> 1;
+		n += sizeof(*p);
+	}
+
+	/* Minimum size to align p->buffer by alignmask. */
+	n += alignmask & ~a;
+
+	/* Minimum size to ensure p->buffer does not straddle a page. */
+	n += (bsize - 1) & ~(alignmask | a);
+
+	v = kzalloc(n, skcipher_walk_gfp(walk));
+	if (!v)
+		return skcipher_walk_done(walk, -ENOMEM);
+
+	if (phys) {
+		p = v;
+		p->len = bsize;
+		skcipher_queue_write(walk, p);
+		buffer = p->buffer;
+	} else {
+		walk->buffer = v;
+		buffer = v;
+	}
+
+ok:
+	walk->dst.virt.addr = PTR_ALIGN(buffer, alignmask + 1);
+	walk->dst.virt.addr = skcipher_get_spot(walk->dst.virt.addr, bsize);
+	walk->src.virt.addr = walk->dst.virt.addr;
+
+	scatterwalk_copychunks(walk->src.virt.addr, &walk->in, bsize, 0);
+
+	walk->nbytes = bsize;
+	walk->flags |= SKCIPHER_WALK_SLOW;
+
+	return 0;
+}
+
+static int skcipher_next_copy(struct skcipher_walk *walk)
+{
+	struct skcipher_walk_buffer *p;
+	u8 *tmp = walk->page;
+
+	skcipher_map_src(walk);
+	memcpy(tmp, walk->src.virt.addr, walk->nbytes);
+	skcipher_unmap_src(walk);
+
+	walk->src.virt.addr = tmp;
+	walk->dst.virt.addr = tmp;
+
+	if (!(walk->flags & SKCIPHER_WALK_PHYS))
+		return 0;
+
+	p = kmalloc(sizeof(*p), skcipher_walk_gfp(walk));
+	if (!p)
+		return -ENOMEM;
+
+	p->data = walk->page;
+	p->len = walk->nbytes;
+	skcipher_queue_write(walk, p);
+
+	if (offset_in_page(walk->page) + walk->nbytes + walk->chunksize >
+	    PAGE_SIZE)
+		walk->page = NULL;
+	else
+		walk->page += walk->nbytes;
+
+	return 0;
+}
+
+static int skcipher_next_fast(struct skcipher_walk *walk)
+{
+	unsigned long diff;
+
+	walk->src.phys.page = scatterwalk_page(&walk->in);
+	walk->src.phys.offset = offset_in_page(walk->in.offset);
+	walk->dst.phys.page = scatterwalk_page(&walk->out);
+	walk->dst.phys.offset = offset_in_page(walk->out.offset);
+
+	if (walk->flags & SKCIPHER_WALK_PHYS)
+		return 0;
+
+	diff = walk->src.phys.offset - walk->dst.phys.offset;
+	diff |= walk->src.virt.page - walk->dst.virt.page;
+
+	skcipher_map_src(walk);
+	walk->dst.virt.addr = walk->src.virt.addr;
+
+	if (diff) {
+		walk->flags |= SKCIPHER_WALK_DIFF;
+		skcipher_map_dst(walk);
+	}
+
+	return 0;
+}
+
+static int skcipher_walk_next(struct skcipher_walk *walk)
+{
+	unsigned int bsize;
+	unsigned int n;
+	int err;
+
+	walk->flags &= ~(SKCIPHER_WALK_SLOW | SKCIPHER_WALK_COPY |
+			 SKCIPHER_WALK_DIFF);
+
+	n = walk->total;
+	bsize = min(walk->chunksize, max(n, walk->blocksize));
+	n = scatterwalk_clamp(&walk->in, n);
+	n = scatterwalk_clamp(&walk->out, n);
+
+	if (unlikely(n < bsize)) {
+		if (unlikely(walk->total < walk->blocksize))
+			return skcipher_walk_done(walk, -EINVAL);
+
+slow_path:
+		err = skcipher_next_slow(walk, bsize);
+		goto set_phys_lowmem;
+	}
+
+	if (unlikely((walk->in.offset | walk->out.offset) & walk->alignmask)) {
+		if (!walk->page) {
+			gfp_t gfp = skcipher_walk_gfp(walk);
+
+			walk->page = (void *)__get_free_page(gfp);
+			if (!walk->page)
+				goto slow_path;
+		}
+
+		walk->nbytes = min_t(unsigned, n,
+				     PAGE_SIZE - offset_in_page(walk->page));
+		walk->flags |= SKCIPHER_WALK_COPY;
+		err = skcipher_next_copy(walk);
+		goto set_phys_lowmem;
+	}
+
+	walk->nbytes = n;
+
+	return skcipher_next_fast(walk);
+
+set_phys_lowmem:
+	if (!err && (walk->flags & SKCIPHER_WALK_PHYS)) {
+		walk->src.phys.page = virt_to_page(walk->src.virt.addr);
+		walk->dst.phys.page = virt_to_page(walk->dst.virt.addr);
+		walk->src.phys.offset &= PAGE_SIZE - 1;
+		walk->dst.phys.offset &= PAGE_SIZE - 1;
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_next);
+
+static int skcipher_copy_iv(struct skcipher_walk *walk)
+{
+	unsigned a = crypto_tfm_ctx_alignment() - 1;
+	unsigned alignmask = walk->alignmask;
+	unsigned ivsize = walk->ivsize;
+	unsigned bs = walk->chunksize;
+	unsigned aligned_bs;
+	unsigned size;
+	u8 *iv;
+
+	aligned_bs = ALIGN(bs, alignmask);
+
+	/* Minimum size to align buffer by alignmask. */
+	size = alignmask & ~a;
+
+	if (walk->flags & SKCIPHER_WALK_PHYS)
+		size += ivsize;
+	else {
+		size += aligned_bs + ivsize;
+
+		/* Minimum size to ensure buffer does not straddle a page. */
+		size += (bs - 1) & ~(alignmask | a);
+	}
+
+	walk->buffer = kmalloc(size, skcipher_walk_gfp(walk));
+	if (!walk->buffer)
+		return -ENOMEM;
+
+	iv = PTR_ALIGN(walk->buffer, alignmask + 1);
+	iv = skcipher_get_spot(iv, bs) + aligned_bs;
+
+	walk->iv = memcpy(iv, walk->iv, walk->ivsize);
+	return 0;
+}
+
+static int skcipher_walk_first(struct skcipher_walk *walk)
+{
+	walk->nbytes = 0;
+
+	if (WARN_ON_ONCE(in_irq()))
+		return -EDEADLK;
+
+	if (unlikely(!walk->total))
+		return 0;
+
+	walk->buffer = NULL;
+	if (unlikely(((unsigned long)walk->iv & walk->alignmask))) {
+		int err = skcipher_copy_iv(walk);
+		if (err)
+			return err;
+	}
+
+	walk->page = NULL;
+	walk->nbytes = walk->total;
+
+	return skcipher_walk_next(walk);
+}
+
+static int skcipher_walk_skcipher(struct skcipher_walk *walk,
+				  struct skcipher_request *req)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+
+	scatterwalk_start(&walk->in, req->src);
+	scatterwalk_start(&walk->out, req->dst);
+
+	walk->total = req->cryptlen;
+	walk->iv = req->iv;
+	walk->oiv = req->iv;
+
+	walk->flags &= ~SKCIPHER_WALK_SLEEP;
+	walk->flags |= req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ?
+		       SKCIPHER_WALK_SLEEP : 0;
+
+	walk->blocksize = crypto_skcipher_blocksize(tfm);
+	walk->chunksize = crypto_skcipher_chunksize(tfm);
+	walk->ivsize = crypto_skcipher_ivsize(tfm);
+	walk->alignmask = crypto_skcipher_alignmask(tfm);
+
+	return skcipher_walk_first(walk);
+}
+
+int skcipher_walk_virt(struct skcipher_walk *walk,
+		       struct skcipher_request *req, bool atomic)
+{
+	int err;
+
+	walk->flags &= ~SKCIPHER_WALK_PHYS;
+
+	err = skcipher_walk_skcipher(walk, req);
+
+	walk->flags &= atomic ? ~SKCIPHER_WALK_SLEEP : ~0;
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_virt);
+
+void skcipher_walk_atomise(struct skcipher_walk *walk)
+{
+	walk->flags &= ~SKCIPHER_WALK_SLEEP;
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_atomise);
+
+int skcipher_walk_async(struct skcipher_walk *walk,
+			struct skcipher_request *req)
+{
+	walk->flags |= SKCIPHER_WALK_PHYS;
+
+	INIT_LIST_HEAD(&walk->buffers);
+
+	return skcipher_walk_skcipher(walk, req);
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_async);
+
+static int skcipher_walk_aead_common(struct skcipher_walk *walk,
+				     struct aead_request *req, bool atomic)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	int err;
+
+	walk->flags &= ~SKCIPHER_WALK_PHYS;
+
+	scatterwalk_start(&walk->in, req->src);
+	scatterwalk_start(&walk->out, req->dst);
+
+	scatterwalk_copychunks(NULL, &walk->in, req->assoclen, 2);
+	scatterwalk_copychunks(NULL, &walk->out, req->assoclen, 2);
+
+	walk->iv = req->iv;
+	walk->oiv = req->iv;
+
+	if (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP)
+		walk->flags |= SKCIPHER_WALK_SLEEP;
+	else
+		walk->flags &= ~SKCIPHER_WALK_SLEEP;
+
+	walk->blocksize = crypto_aead_blocksize(tfm);
+	walk->chunksize = crypto_aead_chunksize(tfm);
+	walk->ivsize = crypto_aead_ivsize(tfm);
+	walk->alignmask = crypto_aead_alignmask(tfm);
+
+	err = skcipher_walk_first(walk);
+
+	if (atomic)
+		walk->flags &= ~SKCIPHER_WALK_SLEEP;
+
+	return err;
+}
+
+int skcipher_walk_aead(struct skcipher_walk *walk, struct aead_request *req,
+		       bool atomic)
+{
+	walk->total = req->cryptlen;
+
+	return skcipher_walk_aead_common(walk, req, atomic);
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_aead);
+
+int skcipher_walk_aead_encrypt(struct skcipher_walk *walk,
+			       struct aead_request *req, bool atomic)
+{
+	walk->total = req->cryptlen;
+
+	return skcipher_walk_aead_common(walk, req, atomic);
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_aead_encrypt);
+
+int skcipher_walk_aead_decrypt(struct skcipher_walk *walk,
+			       struct aead_request *req, bool atomic)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+
+	walk->total = req->cryptlen - crypto_aead_authsize(tfm);
+
+	return skcipher_walk_aead_common(walk, req, atomic);
+}
+EXPORT_SYMBOL_GPL(skcipher_walk_aead_decrypt);
+
 static unsigned int crypto_skcipher_extsize(struct crypto_alg *alg)
 {
 	if (alg->cra_type == &crypto_blkcipher_type)
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/testmgr.c linux-libre-4.10-rc8-gnu/crypto/testmgr.c
--- linux-libre-4.9-gnu/crypto/testmgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/testmgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,6 +33,7 @@
 #include <crypto/drbg.h>
 #include <crypto/akcipher.h>
 #include <crypto/kpp.h>
+#include <crypto/acompress.h>
 
 #include "internal.h"
 
@@ -62,7 +63,7 @@ int alg_test(const char *driver, const c
  */
 #define IDX1		32
 #define IDX2		32400
-#define IDX3		1
+#define IDX3		1511
 #define IDX4		8193
 #define IDX5		22222
 #define IDX6		17101
@@ -1442,6 +1443,152 @@ out:
 	return ret;
 }
 
+static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
+		      struct comp_testvec *dtemplate, int ctcount, int dtcount)
+{
+	const char *algo = crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
+	unsigned int i;
+	char *output;
+	int ret;
+	struct scatterlist src, dst;
+	struct acomp_req *req;
+	struct tcrypt_result result;
+
+	output = kmalloc(COMP_BUF_SIZE, GFP_KERNEL);
+	if (!output)
+		return -ENOMEM;
+
+	for (i = 0; i < ctcount; i++) {
+		unsigned int dlen = COMP_BUF_SIZE;
+		int ilen = ctemplate[i].inlen;
+		void *input_vec;
+
+		input_vec = kmalloc(ilen, GFP_KERNEL);
+		if (!input_vec) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		memcpy(input_vec, ctemplate[i].input, ilen);
+		memset(output, 0, dlen);
+		init_completion(&result.completion);
+		sg_init_one(&src, input_vec, ilen);
+		sg_init_one(&dst, output, dlen);
+
+		req = acomp_request_alloc(tfm);
+		if (!req) {
+			pr_err("alg: acomp: request alloc failed for %s\n",
+			       algo);
+			kfree(input_vec);
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		acomp_request_set_params(req, &src, &dst, ilen, dlen);
+		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					   tcrypt_complete, &result);
+
+		ret = wait_async_op(&result, crypto_acomp_compress(req));
+		if (ret) {
+			pr_err("alg: acomp: compression failed on test %d for %s: ret=%d\n",
+			       i + 1, algo, -ret);
+			kfree(input_vec);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (req->dlen != ctemplate[i].outlen) {
+			pr_err("alg: acomp: Compression test %d failed for %s: output len = %d\n",
+			       i + 1, algo, req->dlen);
+			ret = -EINVAL;
+			kfree(input_vec);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (memcmp(output, ctemplate[i].output, req->dlen)) {
+			pr_err("alg: acomp: Compression test %d failed for %s\n",
+			       i + 1, algo);
+			hexdump(output, req->dlen);
+			ret = -EINVAL;
+			kfree(input_vec);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		kfree(input_vec);
+		acomp_request_free(req);
+	}
+
+	for (i = 0; i < dtcount; i++) {
+		unsigned int dlen = COMP_BUF_SIZE;
+		int ilen = dtemplate[i].inlen;
+		void *input_vec;
+
+		input_vec = kmalloc(ilen, GFP_KERNEL);
+		if (!input_vec) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		memcpy(input_vec, dtemplate[i].input, ilen);
+		memset(output, 0, dlen);
+		init_completion(&result.completion);
+		sg_init_one(&src, input_vec, ilen);
+		sg_init_one(&dst, output, dlen);
+
+		req = acomp_request_alloc(tfm);
+		if (!req) {
+			pr_err("alg: acomp: request alloc failed for %s\n",
+			       algo);
+			kfree(input_vec);
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		acomp_request_set_params(req, &src, &dst, ilen, dlen);
+		acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+					   tcrypt_complete, &result);
+
+		ret = wait_async_op(&result, crypto_acomp_decompress(req));
+		if (ret) {
+			pr_err("alg: acomp: decompression failed on test %d for %s: ret=%d\n",
+			       i + 1, algo, -ret);
+			kfree(input_vec);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (req->dlen != dtemplate[i].outlen) {
+			pr_err("alg: acomp: Decompression test %d failed for %s: output len = %d\n",
+			       i + 1, algo, req->dlen);
+			ret = -EINVAL;
+			kfree(input_vec);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		if (memcmp(output, dtemplate[i].output, req->dlen)) {
+			pr_err("alg: acomp: Decompression test %d failed for %s\n",
+			       i + 1, algo);
+			hexdump(output, req->dlen);
+			ret = -EINVAL;
+			kfree(input_vec);
+			acomp_request_free(req);
+			goto out;
+		}
+
+		kfree(input_vec);
+		acomp_request_free(req);
+	}
+
+	ret = 0;
+
+out:
+	kfree(output);
+	return ret;
+}
+
 static int test_cprng(struct crypto_rng *tfm, struct cprng_testvec *template,
 		      unsigned int tcount)
 {
@@ -1509,7 +1656,7 @@ static int alg_test_aead(const struct al
 	struct crypto_aead *tfm;
 	int err = 0;
 
-	tfm = crypto_alloc_aead(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	tfm = crypto_alloc_aead(driver, type, mask);
 	if (IS_ERR(tfm)) {
 		printk(KERN_ERR "alg: aead: Failed to load transform for %s: "
 		       "%ld\n", driver, PTR_ERR(tfm));
@@ -1538,7 +1685,7 @@ static int alg_test_cipher(const struct
 	struct crypto_cipher *tfm;
 	int err = 0;
 
-	tfm = crypto_alloc_cipher(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	tfm = crypto_alloc_cipher(driver, type, mask);
 	if (IS_ERR(tfm)) {
 		printk(KERN_ERR "alg: cipher: Failed to load transform for "
 		       "%s: %ld\n", driver, PTR_ERR(tfm));
@@ -1567,7 +1714,7 @@ static int alg_test_skcipher(const struc
 	struct crypto_skcipher *tfm;
 	int err = 0;
 
-	tfm = crypto_alloc_skcipher(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	tfm = crypto_alloc_skcipher(driver, type, mask);
 	if (IS_ERR(tfm)) {
 		printk(KERN_ERR "alg: skcipher: Failed to load transform for "
 		       "%s: %ld\n", driver, PTR_ERR(tfm));
@@ -1593,22 +1740,38 @@ out:
 static int alg_test_comp(const struct alg_test_desc *desc, const char *driver,
 			 u32 type, u32 mask)
 {
-	struct crypto_comp *tfm;
+	struct crypto_comp *comp;
+	struct crypto_acomp *acomp;
 	int err;
+	u32 algo_type = type & CRYPTO_ALG_TYPE_ACOMPRESS_MASK;
 
-	tfm = crypto_alloc_comp(driver, type, mask);
-	if (IS_ERR(tfm)) {
-		printk(KERN_ERR "alg: comp: Failed to load transform for %s: "
-		       "%ld\n", driver, PTR_ERR(tfm));
-		return PTR_ERR(tfm);
-	}
+	if (algo_type == CRYPTO_ALG_TYPE_ACOMPRESS) {
+		acomp = crypto_alloc_acomp(driver, type, mask);
+		if (IS_ERR(acomp)) {
+			pr_err("alg: acomp: Failed to load transform for %s: %ld\n",
+			       driver, PTR_ERR(acomp));
+			return PTR_ERR(acomp);
+		}
+		err = test_acomp(acomp, desc->suite.comp.comp.vecs,
+				 desc->suite.comp.decomp.vecs,
+				 desc->suite.comp.comp.count,
+				 desc->suite.comp.decomp.count);
+		crypto_free_acomp(acomp);
+	} else {
+		comp = crypto_alloc_comp(driver, type, mask);
+		if (IS_ERR(comp)) {
+			pr_err("alg: comp: Failed to load transform for %s: %ld\n",
+			       driver, PTR_ERR(comp));
+			return PTR_ERR(comp);
+		}
 
-	err = test_comp(tfm, desc->suite.comp.comp.vecs,
-			desc->suite.comp.decomp.vecs,
-			desc->suite.comp.comp.count,
-			desc->suite.comp.decomp.count);
+		err = test_comp(comp, desc->suite.comp.comp.vecs,
+				desc->suite.comp.decomp.vecs,
+				desc->suite.comp.comp.count,
+				desc->suite.comp.decomp.count);
 
-	crypto_free_comp(tfm);
+		crypto_free_comp(comp);
+	}
 	return err;
 }
 
@@ -1618,7 +1781,7 @@ static int alg_test_hash(const struct al
 	struct crypto_ahash *tfm;
 	int err;
 
-	tfm = crypto_alloc_ahash(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	tfm = crypto_alloc_ahash(driver, type, mask);
 	if (IS_ERR(tfm)) {
 		printk(KERN_ERR "alg: hash: Failed to load transform for %s: "
 		       "%ld\n", driver, PTR_ERR(tfm));
@@ -1646,7 +1809,7 @@ static int alg_test_crc32c(const struct
 	if (err)
 		goto out;
 
-	tfm = crypto_alloc_shash(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	tfm = crypto_alloc_shash(driver, type, mask);
 	if (IS_ERR(tfm)) {
 		printk(KERN_ERR "alg: crc32c: Failed to load transform for %s: "
 		       "%ld\n", driver, PTR_ERR(tfm));
@@ -1688,7 +1851,7 @@ static int alg_test_cprng(const struct a
 	struct crypto_rng *rng;
 	int err;
 
-	rng = crypto_alloc_rng(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	rng = crypto_alloc_rng(driver, type, mask);
 	if (IS_ERR(rng)) {
 		printk(KERN_ERR "alg: cprng: Failed to load transform for %s: "
 		       "%ld\n", driver, PTR_ERR(rng));
@@ -1715,7 +1878,7 @@ static int drbg_cavs_test(struct drbg_te
 	if (!buf)
 		return -ENOMEM;
 
-	drng = crypto_alloc_rng(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	drng = crypto_alloc_rng(driver, type, mask);
 	if (IS_ERR(drng)) {
 		printk(KERN_ERR "alg: drbg: could not allocate DRNG handle for "
 		       "%s\n", driver);
@@ -1909,7 +2072,7 @@ static int alg_test_kpp(const struct alg
 	struct crypto_kpp *tfm;
 	int err = 0;
 
-	tfm = crypto_alloc_kpp(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	tfm = crypto_alloc_kpp(driver, type, mask);
 	if (IS_ERR(tfm)) {
 		pr_err("alg: kpp: Failed to load tfm for %s: %ld\n",
 		       driver, PTR_ERR(tfm));
@@ -2068,7 +2231,7 @@ static int alg_test_akcipher(const struc
 	struct crypto_akcipher *tfm;
 	int err = 0;
 
-	tfm = crypto_alloc_akcipher(driver, type | CRYPTO_ALG_INTERNAL, mask);
+	tfm = crypto_alloc_akcipher(driver, type, mask);
 	if (IS_ERR(tfm)) {
 		pr_err("alg: akcipher: Failed to load tfm for %s: %ld\n",
 		       driver, PTR_ERR(tfm));
@@ -2091,88 +2254,6 @@ static int alg_test_null(const struct al
 /* Please keep this list sorted by algorithm name. */
 static const struct alg_test_desc alg_test_descs[] = {
 	{
-		.alg = "__cbc-cast5-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__cbc-cast6-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__cbc-serpent-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__cbc-serpent-avx2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__cbc-serpent-sse2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__cbc-twofish-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-aes-aesni",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
-		.alg = "__driver-cbc-camellia-aesni",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-camellia-aesni-avx2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-cast5-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-cast6-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-serpent-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-serpent-avx2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-serpent-sse2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-cbc-twofish-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-aes-aesni",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
-		.alg = "__driver-ecb-camellia-aesni",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-camellia-aesni-avx2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-cast5-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-cast6-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-serpent-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-serpent-avx2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-serpent-sse2",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-ecb-twofish-avx",
-		.test = alg_test_null,
-	}, {
-		.alg = "__driver-gcm-aes-aesni",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
-		.alg = "__ghash-pclmulqdqni",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
 		.alg = "ansi_cprng",
 		.test = alg_test_cprng,
 		.suite = {
@@ -2659,55 +2740,6 @@ static const struct alg_test_desc alg_te
 			}
 		}
 	}, {
-		.alg = "cryptd(__driver-cbc-aes-aesni)",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
-		.alg = "cryptd(__driver-cbc-camellia-aesni)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-cbc-camellia-aesni-avx2)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-cbc-serpent-avx2)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-aes-aesni)",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
-		.alg = "cryptd(__driver-ecb-camellia-aesni)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-camellia-aesni-avx2)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-cast5-avx)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-cast6-avx)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-serpent-avx)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-serpent-avx2)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-serpent-sse2)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-ecb-twofish-avx)",
-		.test = alg_test_null,
-	}, {
-		.alg = "cryptd(__driver-gcm-aes-aesni)",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
-		.alg = "cryptd(__ghash-pclmulqdqni)",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
 		.alg = "ctr(aes)",
 		.test = alg_test_skcipher,
 		.fips_allowed = 1,
@@ -3034,10 +3066,6 @@ static const struct alg_test_desc alg_te
 		.fips_allowed = 1,
 		.test = alg_test_null,
 	}, {
-		.alg = "ecb(__aes-aesni)",
-		.test = alg_test_null,
-		.fips_allowed = 1,
-	}, {
 		.alg = "ecb(aes)",
 		.test = alg_test_skcipher,
 		.fips_allowed = 1,
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/testmgr.h linux-libre-4.10-rc8-gnu/crypto/testmgr.h
--- linux-libre-4.9-gnu/crypto/testmgr.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/testmgr.h	2017-02-12 16:03:20.000000000 -0500
@@ -1334,36 +1334,50 @@ static struct hash_testvec rmd320_tv_tem
 	}
 };
 
-#define CRCT10DIF_TEST_VECTORS	3
+#define CRCT10DIF_TEST_VECTORS	ARRAY_SIZE(crct10dif_tv_template)
 static struct hash_testvec crct10dif_tv_template[] = {
 	{
-		.plaintext = "abc",
-		.psize  = 3,
-#ifdef __LITTLE_ENDIAN
-		.digest = "\x3b\x44",
-#else
-		.digest = "\x44\x3b",
-#endif
+		.plaintext	= "abc",
+		.psize		= 3,
+		.digest		= (u8 *)(u16 []){ 0x443b },
 	}, {
-		.plaintext = "1234567890123456789012345678901234567890"
-			     "123456789012345678901234567890123456789",
-		.psize	= 79,
-#ifdef __LITTLE_ENDIAN
-		.digest	= "\x70\x4b",
-#else
-		.digest	= "\x4b\x70",
-#endif
+		.plaintext 	= "1234567890123456789012345678901234567890"
+				  "123456789012345678901234567890123456789",
+		.psize		= 79,
+		.digest 	= (u8 *)(u16 []){ 0x4b70 },
+		.np		= 2,
+		.tap		= { 63, 16 },
 	}, {
-		.plaintext =
-		"abcddddddddddddddddddddddddddddddddddddddddddddddddddddd",
-		.psize  = 56,
-#ifdef __LITTLE_ENDIAN
-		.digest = "\xe3\x9c",
-#else
-		.digest = "\x9c\xe3",
-#endif
-		.np     = 2,
-		.tap    = { 28, 28 }
+		.plaintext	= "abcdddddddddddddddddddddddddddddddddddddddd"
+				  "ddddddddddddd",
+		.psize		= 56,
+		.digest		= (u8 *)(u16 []){ 0x9ce3 },
+		.np		= 8,
+		.tap		= { 1, 2, 28, 7, 6, 5, 4, 3 },
+	}, {
+		.plaintext 	= "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "123456789012345678901234567890123456789",
+		.psize		= 319,
+		.digest		= (u8 *)(u16 []){ 0x44c6 },
+	}, {
+		.plaintext 	= "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "1234567890123456789012345678901234567890"
+				  "123456789012345678901234567890123456789",
+		.psize		= 319,
+		.digest		= (u8 *)(u16 []){ 0x44c6 },
+		.np		= 4,
+		.tap		= { 1, 255, 57, 6 },
 	}
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/crypto/xts.c linux-libre-4.10-rc8-gnu/crypto/xts.c
--- linux-libre-4.9-gnu/crypto/xts.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/crypto/xts.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,8 @@
  * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  */
-#include <crypto/algapi.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -25,140 +26,320 @@
 #include <crypto/b128ops.h>
 #include <crypto/gf128mul.h>
 
+#define XTS_BUFFER_SIZE 128u
+
 struct priv {
-	struct crypto_cipher *child;
+	struct crypto_skcipher *child;
 	struct crypto_cipher *tweak;
 };
 
-static int setkey(struct crypto_tfm *parent, const u8 *key,
+struct xts_instance_ctx {
+	struct crypto_skcipher_spawn spawn;
+	char name[CRYPTO_MAX_ALG_NAME];
+};
+
+struct rctx {
+	be128 buf[XTS_BUFFER_SIZE / sizeof(be128)];
+
+	be128 t;
+
+	be128 *ext;
+
+	struct scatterlist srcbuf[2];
+	struct scatterlist dstbuf[2];
+	struct scatterlist *src;
+	struct scatterlist *dst;
+
+	unsigned int left;
+
+	struct skcipher_request subreq;
+};
+
+static int setkey(struct crypto_skcipher *parent, const u8 *key,
 		  unsigned int keylen)
 {
-	struct priv *ctx = crypto_tfm_ctx(parent);
-	struct crypto_cipher *child = ctx->tweak;
+	struct priv *ctx = crypto_skcipher_ctx(parent);
+	struct crypto_skcipher *child;
+	struct crypto_cipher *tweak;
 	int err;
 
-	err = xts_check_key(parent, key, keylen);
+	err = xts_verify_key(parent, key, keylen);
 	if (err)
 		return err;
 
+	keylen /= 2;
+
 	/* we need two cipher instances: one to compute the initial 'tweak'
 	 * by encrypting the IV (usually the 'plain' iv) and the other
 	 * one to encrypt and decrypt the data */
 
 	/* tweak cipher, uses Key2 i.e. the second half of *key */
-	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
+	tweak = ctx->tweak;
+	crypto_cipher_clear_flags(tweak, CRYPTO_TFM_REQ_MASK);
+	crypto_cipher_set_flags(tweak, crypto_skcipher_get_flags(parent) &
 				       CRYPTO_TFM_REQ_MASK);
-	err = crypto_cipher_setkey(child, key + keylen/2, keylen/2);
+	err = crypto_cipher_setkey(tweak, key + keylen, keylen);
+	crypto_skcipher_set_flags(parent, crypto_cipher_get_flags(tweak) &
+					  CRYPTO_TFM_RES_MASK);
 	if (err)
 		return err;
 
-	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
-				     CRYPTO_TFM_RES_MASK);
-
+	/* data cipher, uses Key1 i.e. the first half of *key */
 	child = ctx->child;
+	crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
+	crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_skcipher_setkey(child, key, keylen);
+	crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) &
+					  CRYPTO_TFM_RES_MASK);
 
-	/* data cipher, uses Key1 i.e. the first half of *key */
-	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
-				       CRYPTO_TFM_REQ_MASK);
-	err = crypto_cipher_setkey(child, key, keylen/2);
-	if (err)
-		return err;
+	return err;
+}
 
-	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
-				     CRYPTO_TFM_RES_MASK);
+static int post_crypt(struct skcipher_request *req)
+{
+	struct rctx *rctx = skcipher_request_ctx(req);
+	be128 *buf = rctx->ext ?: rctx->buf;
+	struct skcipher_request *subreq;
+	const int bs = XTS_BLOCK_SIZE;
+	struct skcipher_walk w;
+	struct scatterlist *sg;
+	unsigned offset;
+	int err;
 
-	return 0;
-}
+	subreq = &rctx->subreq;
+	err = skcipher_walk_virt(&w, subreq, false);
 
-struct sinfo {
-	be128 *t;
-	struct crypto_tfm *tfm;
-	void (*fn)(struct crypto_tfm *, u8 *, const u8 *);
-};
+	while (w.nbytes) {
+		unsigned int avail = w.nbytes;
+		be128 *wdst;
 
-static inline void xts_round(struct sinfo *s, void *dst, const void *src)
-{
-	be128_xor(dst, s->t, src);		/* PP <- T xor P */
-	s->fn(s->tfm, dst, dst);		/* CC <- E(Key1,PP) */
-	be128_xor(dst, dst, s->t);		/* C <- T xor CC */
+		wdst = w.dst.virt.addr;
+
+		do {
+			be128_xor(wdst, buf++, wdst);
+			wdst++;
+		} while ((avail -= bs) >= bs);
+
+		err = skcipher_walk_done(&w, avail);
+	}
+
+	rctx->left -= subreq->cryptlen;
+
+	if (err || !rctx->left)
+		goto out;
+
+	rctx->dst = rctx->dstbuf;
+
+	scatterwalk_done(&w.out, 0, 1);
+	sg = w.out.sg;
+	offset = w.out.offset;
+
+	if (rctx->dst != sg) {
+		rctx->dst[0] = *sg;
+		sg_unmark_end(rctx->dst);
+		scatterwalk_crypto_chain(rctx->dst, sg_next(sg), 0, 2);
+	}
+	rctx->dst[0].length -= offset - sg->offset;
+	rctx->dst[0].offset = offset;
+
+out:
+	return err;
 }
 
-static int crypt(struct blkcipher_desc *d,
-		 struct blkcipher_walk *w, struct priv *ctx,
-		 void (*tw)(struct crypto_tfm *, u8 *, const u8 *),
-		 void (*fn)(struct crypto_tfm *, u8 *, const u8 *))
+static int pre_crypt(struct skcipher_request *req)
 {
-	int err;
-	unsigned int avail;
+	struct rctx *rctx = skcipher_request_ctx(req);
+	be128 *buf = rctx->ext ?: rctx->buf;
+	struct skcipher_request *subreq;
 	const int bs = XTS_BLOCK_SIZE;
-	struct sinfo s = {
-		.tfm = crypto_cipher_tfm(ctx->child),
-		.fn = fn
-	};
-	u8 *wsrc;
-	u8 *wdst;
+	struct skcipher_walk w;
+	struct scatterlist *sg;
+	unsigned cryptlen;
+	unsigned offset;
+	bool more;
+	int err;
 
-	err = blkcipher_walk_virt(d, w);
-	if (!w->nbytes)
-		return err;
+	subreq = &rctx->subreq;
+	cryptlen = subreq->cryptlen;
 
-	s.t = (be128 *)w->iv;
-	avail = w->nbytes;
+	more = rctx->left > cryptlen;
+	if (!more)
+		cryptlen = rctx->left;
 
-	wsrc = w->src.virt.addr;
-	wdst = w->dst.virt.addr;
+	skcipher_request_set_crypt(subreq, rctx->src, rctx->dst,
+				   cryptlen, NULL);
 
-	/* calculate first value of T */
-	tw(crypto_cipher_tfm(ctx->tweak), w->iv, w->iv);
+	err = skcipher_walk_virt(&w, subreq, false);
 
-	goto first;
+	while (w.nbytes) {
+		unsigned int avail = w.nbytes;
+		be128 *wsrc;
+		be128 *wdst;
+
+		wsrc = w.src.virt.addr;
+		wdst = w.dst.virt.addr;
 
-	for (;;) {
 		do {
-			gf128mul_x_ble(s.t, s.t);
+			*buf++ = rctx->t;
+			be128_xor(wdst++, &rctx->t, wsrc++);
+			gf128mul_x_ble(&rctx->t, &rctx->t);
+		} while ((avail -= bs) >= bs);
 
-first:
-			xts_round(&s, wdst, wsrc);
+		err = skcipher_walk_done(&w, avail);
+	}
 
-			wsrc += bs;
-			wdst += bs;
-		} while ((avail -= bs) >= bs);
+	skcipher_request_set_crypt(subreq, rctx->dst, rctx->dst,
+				   cryptlen, NULL);
 
-		err = blkcipher_walk_done(d, w, avail);
-		if (!w->nbytes)
-			break;
+	if (err || !more)
+		goto out;
 
-		avail = w->nbytes;
+	rctx->src = rctx->srcbuf;
 
-		wsrc = w->src.virt.addr;
-		wdst = w->dst.virt.addr;
+	scatterwalk_done(&w.in, 0, 1);
+	sg = w.in.sg;
+	offset = w.in.offset;
+
+	if (rctx->src != sg) {
+		rctx->src[0] = *sg;
+		sg_unmark_end(rctx->src);
+		scatterwalk_crypto_chain(rctx->src, sg_next(sg), 0, 2);
 	}
+	rctx->src[0].length -= offset - sg->offset;
+	rctx->src[0].offset = offset;
 
+out:
 	return err;
 }
 
-static int encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		   struct scatterlist *src, unsigned int nbytes)
+static int init_crypt(struct skcipher_request *req, crypto_completion_t done)
 {
-	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk w;
+	struct priv *ctx = crypto_skcipher_ctx(crypto_skcipher_reqtfm(req));
+	struct rctx *rctx = skcipher_request_ctx(req);
+	struct skcipher_request *subreq;
+	gfp_t gfp;
 
-	blkcipher_walk_init(&w, dst, src, nbytes);
-	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
-		     crypto_cipher_alg(ctx->child)->cia_encrypt);
+	subreq = &rctx->subreq;
+	skcipher_request_set_tfm(subreq, ctx->child);
+	skcipher_request_set_callback(subreq, req->base.flags, done, req);
+
+	gfp = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+							   GFP_ATOMIC;
+	rctx->ext = NULL;
+
+	subreq->cryptlen = XTS_BUFFER_SIZE;
+	if (req->cryptlen > XTS_BUFFER_SIZE) {
+		subreq->cryptlen = min(req->cryptlen, (unsigned)PAGE_SIZE);
+		rctx->ext = kmalloc(subreq->cryptlen, gfp);
+	}
+
+	rctx->src = req->src;
+	rctx->dst = req->dst;
+	rctx->left = req->cryptlen;
+
+	/* calculate first value of T */
+	crypto_cipher_encrypt_one(ctx->tweak, (u8 *)&rctx->t, req->iv);
+
+	return 0;
 }
 
-static int decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
-		   struct scatterlist *src, unsigned int nbytes)
+static void exit_crypt(struct skcipher_request *req)
 {
-	struct priv *ctx = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk w;
+	struct rctx *rctx = skcipher_request_ctx(req);
 
-	blkcipher_walk_init(&w, dst, src, nbytes);
-	return crypt(desc, &w, ctx, crypto_cipher_alg(ctx->tweak)->cia_encrypt,
-		     crypto_cipher_alg(ctx->child)->cia_decrypt);
+	rctx->left = 0;
+
+	if (rctx->ext)
+		kzfree(rctx->ext);
+}
+
+static int do_encrypt(struct skcipher_request *req, int err)
+{
+	struct rctx *rctx = skcipher_request_ctx(req);
+	struct skcipher_request *subreq;
+
+	subreq = &rctx->subreq;
+
+	while (!err && rctx->left) {
+		err = pre_crypt(req) ?:
+		      crypto_skcipher_encrypt(subreq) ?:
+		      post_crypt(req);
+
+		if (err == -EINPROGRESS ||
+		    (err == -EBUSY &&
+		     req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
+			return err;
+	}
+
+	exit_crypt(req);
+	return err;
+}
+
+static void encrypt_done(struct crypto_async_request *areq, int err)
+{
+	struct skcipher_request *req = areq->data;
+	struct skcipher_request *subreq;
+	struct rctx *rctx;
+
+	rctx = skcipher_request_ctx(req);
+	subreq = &rctx->subreq;
+	subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
+
+	err = do_encrypt(req, err ?: post_crypt(req));
+	if (rctx->left)
+		return;
+
+	skcipher_request_complete(req, err);
+}
+
+static int encrypt(struct skcipher_request *req)
+{
+	return do_encrypt(req, init_crypt(req, encrypt_done));
+}
+
+static int do_decrypt(struct skcipher_request *req, int err)
+{
+	struct rctx *rctx = skcipher_request_ctx(req);
+	struct skcipher_request *subreq;
+
+	subreq = &rctx->subreq;
+
+	while (!err && rctx->left) {
+		err = pre_crypt(req) ?:
+		      crypto_skcipher_decrypt(subreq) ?:
+		      post_crypt(req);
+
+		if (err == -EINPROGRESS ||
+		    (err == -EBUSY &&
+		     req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
+			return err;
+	}
+
+	exit_crypt(req);
+	return err;
+}
+
+static void decrypt_done(struct crypto_async_request *areq, int err)
+{
+	struct skcipher_request *req = areq->data;
+	struct skcipher_request *subreq;
+	struct rctx *rctx;
+
+	rctx = skcipher_request_ctx(req);
+	subreq = &rctx->subreq;
+	subreq->base.flags &= CRYPTO_TFM_REQ_MAY_BACKLOG;
+
+	err = do_decrypt(req, err ?: post_crypt(req));
+	if (rctx->left)
+		return;
+
+	skcipher_request_complete(req, err);
+}
+
+static int decrypt(struct skcipher_request *req)
+{
+	return do_decrypt(req, init_crypt(req, decrypt_done));
 }
 
 int xts_crypt(struct blkcipher_desc *desc, struct scatterlist *sdst,
@@ -233,112 +414,168 @@ first:
 }
 EXPORT_SYMBOL_GPL(xts_crypt);
 
-static int init_tfm(struct crypto_tfm *tfm)
+static int init_tfm(struct crypto_skcipher *tfm)
 {
-	struct crypto_cipher *cipher;
-	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
-	struct priv *ctx = crypto_tfm_ctx(tfm);
-	u32 *flags = &tfm->crt_flags;
-
-	cipher = crypto_spawn_cipher(spawn);
-	if (IS_ERR(cipher))
-		return PTR_ERR(cipher);
+	struct skcipher_instance *inst = skcipher_alg_instance(tfm);
+	struct xts_instance_ctx *ictx = skcipher_instance_ctx(inst);
+	struct priv *ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_skcipher *child;
+	struct crypto_cipher *tweak;
 
-	if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) {
-		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
-		crypto_free_cipher(cipher);
-		return -EINVAL;
-	}
+	child = crypto_spawn_skcipher(&ictx->spawn);
+	if (IS_ERR(child))
+		return PTR_ERR(child);
 
-	ctx->child = cipher;
+	ctx->child = child;
 
-	cipher = crypto_spawn_cipher(spawn);
-	if (IS_ERR(cipher)) {
-		crypto_free_cipher(ctx->child);
-		return PTR_ERR(cipher);
+	tweak = crypto_alloc_cipher(ictx->name, 0, 0);
+	if (IS_ERR(tweak)) {
+		crypto_free_skcipher(ctx->child);
+		return PTR_ERR(tweak);
 	}
 
-	/* this check isn't really needed, leave it here just in case */
-	if (crypto_cipher_blocksize(cipher) != XTS_BLOCK_SIZE) {
-		crypto_free_cipher(cipher);
-		crypto_free_cipher(ctx->child);
-		*flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN;
-		return -EINVAL;
-	}
+	ctx->tweak = tweak;
 
-	ctx->tweak = cipher;
+	crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(child) +
+					 sizeof(struct rctx));
 
 	return 0;
 }
 
-static void exit_tfm(struct crypto_tfm *tfm)
+static void exit_tfm(struct crypto_skcipher *tfm)
 {
-	struct priv *ctx = crypto_tfm_ctx(tfm);
-	crypto_free_cipher(ctx->child);
+	struct priv *ctx = crypto_skcipher_ctx(tfm);
+
+	crypto_free_skcipher(ctx->child);
 	crypto_free_cipher(ctx->tweak);
 }
 
-static struct crypto_instance *alloc(struct rtattr **tb)
+static void free(struct skcipher_instance *inst)
 {
-	struct crypto_instance *inst;
-	struct crypto_alg *alg;
+	crypto_drop_skcipher(skcipher_instance_ctx(inst));
+	kfree(inst);
+}
+
+static int create(struct crypto_template *tmpl, struct rtattr **tb)
+{
+	struct skcipher_instance *inst;
+	struct crypto_attr_type *algt;
+	struct xts_instance_ctx *ctx;
+	struct skcipher_alg *alg;
+	const char *cipher_name;
 	int err;
 
-	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
+	algt = crypto_get_attr_type(tb);
+	if (IS_ERR(algt))
+		return PTR_ERR(algt);
+
+	if ((algt->type ^ CRYPTO_ALG_TYPE_SKCIPHER) & algt->mask)
+		return -EINVAL;
+
+	cipher_name = crypto_attr_alg_name(tb[1]);
+	if (IS_ERR(cipher_name))
+		return PTR_ERR(cipher_name);
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	ctx = skcipher_instance_ctx(inst);
+
+	crypto_set_skcipher_spawn(&ctx->spawn, skcipher_crypto_instance(inst));
+	err = crypto_grab_skcipher(&ctx->spawn, cipher_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
+	if (err == -ENOENT) {
+		err = -ENAMETOOLONG;
+		if (snprintf(ctx->name, CRYPTO_MAX_ALG_NAME, "ecb(%s)",
+			     cipher_name) >= CRYPTO_MAX_ALG_NAME)
+			goto err_free_inst;
+
+		err = crypto_grab_skcipher(&ctx->spawn, ctx->name, 0,
+					   crypto_requires_sync(algt->type,
+								algt->mask));
+	}
+
 	if (err)
-		return ERR_PTR(err);
+		goto err_free_inst;
 
-	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
-				  CRYPTO_ALG_TYPE_MASK);
-	if (IS_ERR(alg))
-		return ERR_CAST(alg);
+	alg = crypto_skcipher_spawn_alg(&ctx->spawn);
 
-	inst = crypto_alloc_instance("xts", alg);
-	if (IS_ERR(inst))
-		goto out_put_alg;
+	err = -EINVAL;
+	if (alg->base.cra_blocksize != XTS_BLOCK_SIZE)
+		goto err_drop_spawn;
 
-	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
-	inst->alg.cra_priority = alg->cra_priority;
-	inst->alg.cra_blocksize = alg->cra_blocksize;
+	if (crypto_skcipher_alg_ivsize(alg))
+		goto err_drop_spawn;
 
-	if (alg->cra_alignmask < 7)
-		inst->alg.cra_alignmask = 7;
-	else
-		inst->alg.cra_alignmask = alg->cra_alignmask;
+	err = crypto_inst_setname(skcipher_crypto_instance(inst), "xts",
+				  &alg->base);
+	if (err)
+		goto err_drop_spawn;
 
-	inst->alg.cra_type = &crypto_blkcipher_type;
+	err = -EINVAL;
+	cipher_name = alg->base.cra_name;
 
-	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
-	inst->alg.cra_blkcipher.min_keysize =
-		2 * alg->cra_cipher.cia_min_keysize;
-	inst->alg.cra_blkcipher.max_keysize =
-		2 * alg->cra_cipher.cia_max_keysize;
+	/* Alas we screwed up the naming so we have to mangle the
+	 * cipher name.
+	 */
+	if (!strncmp(cipher_name, "ecb(", 4)) {
+		unsigned len;
 
-	inst->alg.cra_ctxsize = sizeof(struct priv);
+		len = strlcpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
+		if (len < 2 || len >= sizeof(ctx->name))
+			goto err_drop_spawn;
 
-	inst->alg.cra_init = init_tfm;
-	inst->alg.cra_exit = exit_tfm;
+		if (ctx->name[len - 1] != ')')
+			goto err_drop_spawn;
 
-	inst->alg.cra_blkcipher.setkey = setkey;
-	inst->alg.cra_blkcipher.encrypt = encrypt;
-	inst->alg.cra_blkcipher.decrypt = decrypt;
+		ctx->name[len - 1] = 0;
 
-out_put_alg:
-	crypto_mod_put(alg);
-	return inst;
-}
+		if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
+			     "xts(%s)", ctx->name) >= CRYPTO_MAX_ALG_NAME)
+			return -ENAMETOOLONG;
+	} else
+		goto err_drop_spawn;
 
-static void free(struct crypto_instance *inst)
-{
-	crypto_drop_spawn(crypto_instance_ctx(inst));
+	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
+	inst->alg.base.cra_priority = alg->base.cra_priority;
+	inst->alg.base.cra_blocksize = XTS_BLOCK_SIZE;
+	inst->alg.base.cra_alignmask = alg->base.cra_alignmask |
+				       (__alignof__(u64) - 1);
+
+	inst->alg.ivsize = XTS_BLOCK_SIZE;
+	inst->alg.min_keysize = crypto_skcipher_alg_min_keysize(alg) * 2;
+	inst->alg.max_keysize = crypto_skcipher_alg_max_keysize(alg) * 2;
+
+	inst->alg.base.cra_ctxsize = sizeof(struct priv);
+
+	inst->alg.init = init_tfm;
+	inst->alg.exit = exit_tfm;
+
+	inst->alg.setkey = setkey;
+	inst->alg.encrypt = encrypt;
+	inst->alg.decrypt = decrypt;
+
+	inst->free = free;
+
+	err = skcipher_register_instance(tmpl, inst);
+	if (err)
+		goto err_drop_spawn;
+
+out:
+	return err;
+
+err_drop_spawn:
+	crypto_drop_skcipher(&ctx->spawn);
+err_free_inst:
 	kfree(inst);
+	goto out;
 }
 
 static struct crypto_template crypto_tmpl = {
 	.name = "xts",
-	.alloc = alloc,
-	.free = free,
+	.create = create,
 	.module = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/00-INDEX linux-libre-4.10-rc8-gnu/Documentation/00-INDEX
--- linux-libre-4.9-gnu/Documentation/00-INDEX	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/00-INDEX	2017-02-12 16:03:20.000000000 -0500
@@ -14,13 +14,8 @@ Following translations are available on
 	- this file.
 ABI/
 	- info on kernel <-> userspace ABI and relative interface stability.
-
-BUG-HUNTING
-	- brute force method of doing binary search of patches to find bug.
-Changes
-	- list of changes that break older software packages.
 CodingStyle
-	- how the maintainers expect the C code in the kernel to look.
+	- nothing here, just a pointer to process/coding-style.rst.
 DMA-API.txt
 	- DMA API, pci_ API & extensions for non-consistent memory machines.
 DMA-API-HOWTO.txt
@@ -33,8 +28,6 @@ DocBook/
 	- directory with DocBook templates etc. for kernel documentation.
 EDID/
 	- directory with info on customizing EDID for broken gfx/displays.
-HOWTO
-	- the process and procedures of how to do Linux kernel development.
 IPMI.txt
 	- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
 IRQ-affinity.txt
@@ -46,62 +39,43 @@ IRQ.txt
 Intel-IOMMU.txt
 	- basic info on the Intel IOMMU virtualization support.
 Makefile
-	- This file does nothing. Removing it breaks make htmldocs and
-	  make distclean.
-ManagementStyle
-	- how to (attempt to) manage kernel hackers.
+	- It's not of interest for those who aren't touching the build system.
+Makefile.sphinx
+	- It's not of interest for those who aren't touching the build system.
+PCI/
+	- info related to PCI drivers.
 RCU/
 	- directory with info on RCU (read-copy update).
 SAK.txt
 	- info on Secure Attention Keys.
 SM501.txt
 	- Silicon Motion SM501 multimedia companion chip
-SecurityBugs
-	- procedure for reporting security bugs found in the kernel.
-SubmitChecklist
-	- Linux kernel patch submission checklist.
-SubmittingDrivers
-	- procedure to get a new driver source included into the kernel tree.
 SubmittingPatches
-	- procedure to get a source patch included into the kernel tree.
-VGA-softcursor.txt
-	- how to change your VGA cursor from a blinking underscore.
+	- nothing here, just a pointer to process/coding-style.rst.
 accounting/
 	- documentation on accounting and taskstats.
 acpi/
 	- info on ACPI-specific hooks in the kernel.
+admin-guide/
+	- info related to Linux users and system admins.
 aoe/
 	- description of AoE (ATA over Ethernet) along with config examples.
-applying-patches.txt
-	- description of various trees and how to apply their patches.
 arm/
 	- directory with info about Linux on the ARM architecture.
 arm64/
 	- directory with info about Linux on the 64 bit ARM architecture.
-assoc_array.txt
-	- generic associative array intro.
-atomic_ops.txt
-	- semantics and behavior of atomic and bitmask operations.
 auxdisplay/
 	- misc. LCD driver documentation (cfag12864b, ks0108).
 backlight/
 	- directory with info on controlling backlights in flat panel displays
-bad_memory.txt
-	- how to use kernel parameters to exclude bad RAM regions.
-basic_profiling.txt
-	- basic instructions for those who wants to profile Linux kernel.
 bcache.txt
 	- Block-layer cache on fast SSDs to improve slow (raid) I/O performance.
-binfmt_misc.txt
-	- info on the kernel support for extra binary formats.
 blackfin/
 	- directory with documentation for the Blackfin arch.
 block/
 	- info on the Block I/O (BIO) layer.
 blockdev/
 	- info on block devices & drivers
-braille-console.txt
-	- info on how to use serial devices for Braille support.
 bt8xxgpio.txt
 	- info on how to modify a bt8xx video card for GPIO usage.
 btmrvl.txt
@@ -114,18 +88,24 @@ cachetlb.txt
 	- describes the cache/TLB flushing interfaces Linux uses.
 cdrom/
 	- directory with information on the CD-ROM drivers that Linux has.
-cgroups/
-	- cgroups features, including cpusets and memory controller.
+cgroup-v1/
+	- cgroups v1 features, including cpusets and memory controller.
+cgroup-v2.txt
+	- cgroups v2 features, including cpusets and memory controller.
 circular-buffers.txt
 	- how to make use of the existing circular buffer infrastructure
 clk.txt
 	- info on the common clock framework
-coccinelle.txt
-	- info on how to get and use the Coccinelle code checking tool.
+cma/
+	- Continuous Memory Area (CMA) debugfs interface.
+conf.py
+	- It's not of interest for those who aren't touching the build system.
 connector/
 	- docs on the netlink based userspace<->kernel space communication mod.
 console/
 	- documentation on Linux console drivers.
+core-api/
+	- documentation on kernel core components.
 cpu-freq/
 	- info on CPU frequency and voltage scaling.
 cpu-hotplug.txt
@@ -150,42 +130,42 @@ debugging-via-ohci1394.txt
 	- how to use firewire like a hardware debugger memory reader.
 dell_rbu.txt
 	- document demonstrating the use of the Dell Remote BIOS Update driver.
-development-process/
-	- how to work with the mainline kernel development process.
+dev-tools/
+	- directory with info on development tools for the kernel.
 device-mapper/
 	- directory with info on Device Mapper.
-devices.txt
-	- plain ASCII listing of all the nodes in /dev/ with major minor #'s.
+dmaengine/
+	- the DMA engine and controller API guides.
 devicetree/
 	- directory with info on device tree files used by OF/PowerPC/ARM
 digsig.txt
 	-info on the Digital Signature Verification API
 dma-buf-sharing.txt
 	- the DMA Buffer Sharing API Guide
+docutils.conf
+	- nothing here. Just a configuration file for docutils.
 dontdiff
 	- file containing a list of files that should never be diff'ed.
+driver-api/
+	- the Linux driver implementer's API guide.
 driver-model/
 	- directory with info about Linux driver model.
-dvb/
-	- info on Linux Digital Video Broadcast (DVB) subsystem.
-dynamic-debug-howto.txt
-	- how to use the dynamic debug (dyndbg) feature.
 early-userspace/
 	- info about initramfs, klibc, and userspace early during boot.
-edac.txt
-	- information on EDAC - Error Detection And Correction
 efi-stub.txt
 	- How to use the EFI boot stub to bypass GRUB or elilo on EFI systems.
 eisa.txt
 	- info on EISA bus support.
-email-clients.txt
-	- info on how to use e-mail to send un-mangled (git) patches.
 extcon/
 	- directory with porting guide for Android kernel switch driver.
+isa.txt
+	- info on EISA bus support.
 fault-injection/
 	- dir with docs about the fault injection capabilities infrastructure.
 fb/
 	- directory with info on the frame buffer graphics abstraction layer.
+features/
+	- status of feature implementation on different architectures.
 filesystems/
 	- info on the vfs and the various filesystems that Linux supports.
 firmware_class/
@@ -194,20 +174,22 @@ flexible-arrays.txt
 	- how to make use of flexible sized arrays in linux
 fmc/
 	- information about the FMC bus abstraction
+fpga/
+	- FPGA Manager Core.
 frv/
 	- Fujitsu FR-V Linux documentation.
 futex-requeue-pi.txt
 	- info on requeueing of tasks from a non-PI futex to a PI futex
-gcov.txt
-	- use of GCC's coverage testing tool "gcov" with the Linux kernel
+gcc-plugins.txt
+	- GCC plugin infrastructure.
 gpio/
 	- gpio related documentation
+gpu/
+	- directory with information on GPU driver developer's guide.
 hid/
 	- directory with information on human interface devices
 highuid.txt
 	- notes on the change from 16 bit to 32 bit user/group IDs.
-hsi.txt
-	- HSI subsystem overview.
 hwspinlock.txt
 	- hardware spinlock provides hardware assistance for synchronization
 timers/
@@ -218,18 +200,18 @@ hwmon/
 	- directory with docs on various hardware monitoring drivers.
 i2c/
 	- directory with info about the I2C bus/protocol (2 wire, kHz speed).
-i2o/
-	- directory with info about the Linux I2O subsystem.
 x86/i386/
 	- directory with info about Linux on Intel 32 bit architecture.
 ia64/
 	- directory with info about Linux on Intel 64 bit architecture.
+ide/
+	- Information regarding the Enhanced IDE drive.
+iio/
+	- info on industrial IIO configfs support.
+index.rst
+	- main index for the documentation at ReST format.
 infiniband/
 	- directory with documents concerning Linux InfiniBand support.
-init.txt
-	- what to do when the kernel can't find the 1st process to run.
-initrd.txt
-	- how to use the RAM disk as an initial/temporary root filesystem.
 input/
 	- info on Linux input device support.
 intel_txt.txt
@@ -248,28 +230,16 @@ isapnp.txt
 	- info on Linux ISA Plug & Play support.
 isdn/
 	- directory with info on the Linux ISDN support, and supported cards.
-java.txt
-	- info on the in-kernel binary support for Java(tm).
-ja_JP/
-	- directory with Japanese translations of various documents
 kbuild/
 	- directory with info about the kernel build process.
+kernel-doc-nano-HOWTO.txt
+	- outdated info about kernel-doc documentation.
 kdump/
 	- directory with mini HowTo on getting the crash dump code to work.
-kernel-docs.txt
-	- listing of various WWW + books that document kernel internals.
-kernel-documentation.rst
+doc-guide/
 	- how to write and format reStructuredText kernel documentation
-kernel-parameters.txt
-	- summary listing of command line / boot prompt args for the kernel.
 kernel-per-CPU-kthreads.txt
 	- List of all per-CPU kthreads and how they introduce jitter.
-kmemcheck.txt
-	- info on dynamic checker that detects uses of uninitialized memory.
-kmemleak.txt
-	- info on how to make use of the kernel memory leak detection system
-ko_KR/
-	- directory with Korean translations of various documents
 kobject.txt
 	- info of the kobject infrastructure of the Linux kernel.
 kprobes.txt
@@ -284,8 +254,8 @@ ldm.txt
 	- a brief description of LDM (Windows Dynamic Disks).
 leds/
 	- directory with info about LED handling under Linux.
-local_ops.txt
-	- semantics and behavior of local atomic operations.
+livepatch/
+	- info on kernel live patching.
 locking/
 	- directory with info about kernel locking primitives
 lockup-watchdogs.txt
@@ -298,22 +268,24 @@ lzo.txt
 	- kernel LZO decompressor input formats
 m68k/
 	- directory with info about Linux on Motorola 68k architecture.
-magic-number.txt
-	- list of magic numbers used to mark/protect kernel data structures.
 mailbox.txt
 	- How to write drivers for the common mailbox framework (IPC).
-md.txt
-	- info on boot arguments for the multiple devices driver.
-media-framework.txt
-	- info on media framework, its data structures, functions and usage.
+md-cluster.txt
+	- info on shared-device RAID MD cluster.
+media/
+	- info on media drivers: uAPI, kAPI and driver documentation.
 memory-barriers.txt
 	- info on Linux kernel memory barriers.
 memory-devices/
 	- directory with info on parts like the Texas Instruments EMIF driver
 memory-hotplug.txt
 	- Hotpluggable memory support, how to use and current status.
+men-chameleon-bus.txt
+	- info on MEN chameleon bus.
 metag/
 	- directory with info about Linux on Meta architecture.
+mic/
+	- Intel Many Integrated Core (MIC) architecture device driver.
 mips/
 	- directory with info about Linux on MIPS architecture.
 misc-devices/
@@ -322,12 +294,8 @@ mmc/
 	- directory with info about the MMC subsystem
 mn10300/
 	- directory with info about the mn10300 architecture port
-module-signing.txt
-	- Kernel module signing for increased security when loading modules.
 mtd/
 	- directory with info about memory technology devices (flash)
-mono.txt
-	- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
 namespaces/
 	- directory with various information about namespaces
 netlabel/
@@ -336,30 +304,42 @@ networking/
 	- directory with info on various aspects of networking with Linux.
 nfc/
 	- directory relating info about Near Field Communications support.
+nios2/
+	- Linux on the Nios II architecture.
 nommu-mmap.txt
 	- documentation about no-mmu memory mapping support.
 numastat.txt
 	- info on how to read Numa policy hit/miss statistics in sysfs.
-oops-tracing.txt
-	- how to decode those nasty internal kernel error dump messages.
+ntb.txt
+	- info on Non-Transparent Bridge (NTB) drivers.
+nvdimm/
+	- info on non-volatile devices.
+nvmem/
+	- info on non volatile memory framework.
+output/
+	- default directory where html/LaTeX/pdf files will be written.
 padata.txt
 	- An introduction to the "padata" parallel execution API
 parisc/
 	- directory with info on using Linux on PA-RISC architecture.
-parport.txt
-	- how to use the parallel-port driver.
 parport-lowlevel.txt
 	- description and usage of the low level parallel port functions.
 pcmcia/
 	- info on the Linux PCMCIA driver.
 percpu-rw-semaphore.txt
 	- RCU based read-write semaphore optimized for locking for reading
+perf/
+	- info about the APM X-Gene SoC Performance Monitoring Unit (PMU).
+phy/
+	- ino on Samsung USB 2.0 PHY adaptation layer.
 phy.txt
 	- Description of the generic PHY framework.
 pi-futex.txt
 	- documentation on lightweight priority inheritance futexes.
 pinctrl.txt
 	- info on pinctrl subsystem and the PINMUX/PINCONF and drivers
+platform/
+	- List of supported hardware by compal and Dell laptop.
 pnp.txt
 	- Linux Plug and Play documentation.
 power/
@@ -372,14 +352,16 @@ preempt-locking.txt
 	- info on locking under a preemptive kernel.
 printk-formats.txt
 	- how to get printk format specifiers right
+process/
+	- how to work with the mainline kernel development process.
 pps/
 	- directory with information on the pulse-per-second support
+pti/
+	- directory with info on Intel MID PTI.
 ptp/
 	- directory with info on support for IEEE 1588 PTP clocks in Linux.
 pwm.txt
 	- info on the pulse width modulation driver subsystem
-ramoops.txt
-	- documentation of the ramoops oops/panic logging module.
 rapidio/
 	- directory with info on RapidIO packet-based fabric interconnect
 rbtree.txt
@@ -406,8 +388,6 @@ security/
 	- directory that contains security-related info
 serial/
 	- directory with info on the low level serial API.
-serial-console.txt
-	- how to set up Linux with a serial line console as the default.
 sgi-ioc4.txt
 	- description of the SGI IOC4 PCI (multi function) device.
 sh/
@@ -416,24 +396,20 @@ smsc_ece1099.txt
 	-info on the smsc Keyboard Scan Expansion/GPIO Expansion device.
 sound/
 	- directory with info on sound card support.
-sparse.txt
-	- info on how to obtain and use the sparse tool for typechecking.
 spi/
 	- overview of Linux kernel Serial Peripheral Interface (SPI) support.
-stable_api_nonsense.txt
-	- info on why the kernel does not have a stable in-kernel api or abi.
-stable_kernel_rules.txt
-	- rules and procedures for the -stable kernel releases.
+sphinx/
+	- no documentation here, just files required by Sphinx toolchain.
+sphinx-static/
+	- no documentation here, just files required by Sphinx toolchain.
 static-keys.txt
 	- info on how static keys allow debug code in hotpaths via patching
 svga.txt
 	- short guide on selecting video modes at boot via VGA BIOS.
-sysfs-rules.txt
-	- How not to use sysfs.
+sync_file.txt
+	- Sync file API guide.
 sysctl/
 	- directory with info on the /proc/sys/* files.
-sysrq.txt
-	- info on the magic SysRq key.
 target/
 	- directory with info on generating TCM v4 fabric .ko modules
 this_cpu_ops.txt
@@ -442,39 +418,29 @@ thermal/
 	- directory with information on managing thermal issues (CPU/temp)
 trace/
 	- directory with info on tracing technologies within linux
+translations/
+	- translations of this document from English to another language
 unaligned-memory-access.txt
 	- info on how to avoid arch breaking unaligned memory access in code.
-unicode.txt
-	- info on the Unicode character/font mapping used in Linux.
 unshare.txt
 	- description of the Linux unshare system call.
 usb/
 	- directory with info regarding the Universal Serial Bus.
-vDSO/
-	- directory with info regarding virtual dynamic shared objects
 vfio.txt
 	- info on Virtual Function I/O used in guest/hypervisor instances.
-vgaarbiter.txt
-	- info on enable/disable the legacy decoding on different VGA devices
 video-output.txt
 	- sysfs class driver interface to enable/disable a video output device.
-video4linux/
-	- directory with info regarding video/TV/radio cards and linux.
 virtual/
 	- directory with information on the various linux virtualizations.
 vm/
 	- directory with info on the Linux vm code.
-vme_api.txt
-	- file relating info on the VME bus API in linux
-volatile-considered-harmful.txt
-	- Why the "volatile" type class should not be used
 w1/
 	- directory with documents regarding the 1-wire (w1) subsystem.
 watchdog/
 	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
 wimax/
 	- directory with info about Intel Wireless Wimax Connections
-workqueue.txt
+core-api/workqueue.rst
 	- information on the Concurrency Managed Workqueue implementation
 x86/x86_64/
 	- directory with info on Linux support for AMD x86-64 (Hammer) machines.
@@ -484,7 +450,5 @@ xtensa/
 	- directory with documents relating to arch/xtensa port/implementation
 xz.txt
 	- how to make use of the XZ data compression within linux kernel
-zh_CN/
-	- directory with Chinese translations of various documents
 zorro.txt
 	- info on writing drivers for Zorro bus devices found on Amigas.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/80211/cfg80211.rst linux-libre-4.10-rc8-gnu/Documentation/80211/cfg80211.rst
--- linux-libre-4.9-gnu/Documentation/80211/cfg80211.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/80211/cfg80211.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,345 +0,0 @@
-==================
-cfg80211 subsystem
-==================
-
-Device registration
-===================
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: Device registration
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_channel_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_channel
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_rate_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_rate
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_sta_ht_cap
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_supported_band
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_signal_type
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_params_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wireless_dev
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_new
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_register
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_unregister
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_free
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_name
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_dev
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_priv
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: priv_to_wiphy
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: set_wiphy_dev
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wdev_priv
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_iface_limit
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_iface_combination
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_check_combinations
-
-Actions and configuration
-=========================
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: Actions and configuration
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_ops
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: vif_params
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: key_params
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: survey_info_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: survey_info
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_beacon_data
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_ap_settings
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: station_parameters
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: rate_info_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: rate_info
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: station_info
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: monitor_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: mpath_info_flags
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: mpath_info
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: bss_parameters
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_txq_params
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_crypto_settings
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_auth_request
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_assoc_request
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_deauth_request
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_disassoc_request
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_ibss_params
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_connect_params
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_pmksa
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_rx_mlme_mgmt
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_auth_timeout
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_rx_assoc_resp
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_assoc_timeout
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_tx_mlme_mgmt
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_ibss_joined
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_connect_result
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_connect_bss
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_connect_timeout
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_roamed
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_disconnected
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_ready_on_channel
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_remain_on_channel_expired
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_new_sta
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_rx_mgmt
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_mgmt_tx_status
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_cqm_rssi_notify
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_cqm_pktloss_notify
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_michael_mic_failure
-
-Scanning and BSS list handling
-==============================
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: Scanning and BSS list handling
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_ssid
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_scan_request
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_scan_done
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_bss
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_inform_bss
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_inform_bss_frame_data
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_inform_bss_data
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_unlink_bss
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_find_ie
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_bss_get_ie
-
-Utility functions
-=================
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: Utility functions
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_channel_to_frequency
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_frequency_to_channel
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_get_channel
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_get_response_rate
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_hdrlen
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_get_hdrlen_from_skb
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_radiotap_iterator
-
-Data path helpers
-=================
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: Data path helpers
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_data_to_8023
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_data_from_8023
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: ieee80211_amsdu_to_8023s
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_classify8021d
-
-Regulatory enforcement infrastructure
-=====================================
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: Regulatory enforcement infrastructure
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: regulatory_hint
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_apply_custom_regulatory
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: freq_reg_info
-
-RFkill integration
-==================
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: RFkill integration
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_rfkill_set_hw_state
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_rfkill_start_polling
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: wiphy_rfkill_stop_polling
-
-Test mode
-=========
-
-.. kernel-doc:: include/net/cfg80211.h
-   :doc: Test mode
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_testmode_alloc_reply_skb
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_testmode_reply
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_testmode_alloc_event_skb
-
-.. kernel-doc:: include/net/cfg80211.h
-   :functions: cfg80211_testmode_event
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/80211/conf.py linux-libre-4.10-rc8-gnu/Documentation/80211/conf.py
--- linux-libre-4.9-gnu/Documentation/80211/conf.py	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/80211/conf.py	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = "Linux 802.11 Driver Developer's Guide"
-
-tags.add("subproject")
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/80211/index.rst linux-libre-4.10-rc8-gnu/Documentation/80211/index.rst
--- linux-libre-4.9-gnu/Documentation/80211/index.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/80211/index.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-=====================================
-Linux 802.11 Driver Developer's Guide
-=====================================
-
-.. toctree::
-
-   introduction
-   cfg80211
-   mac80211
-   mac80211-advanced
-
-.. only::  subproject
-
-   Indices
-   =======
-
-   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/80211/introduction.rst linux-libre-4.10-rc8-gnu/Documentation/80211/introduction.rst
--- linux-libre-4.9-gnu/Documentation/80211/introduction.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/80211/introduction.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-============
-Introduction
-============
-
-Explaining wireless 802.11 networking in the Linux kernel
-
-Copyright 2007-2009 Johannes Berg
-
-These books attempt to give a description of the various subsystems
-that play a role in 802.11 wireless networking in Linux. Since these
-books are for kernel developers they attempts to document the
-structures and functions used in the kernel as well as giving a
-higher-level overview.
-
-The reader is expected to be familiar with the 802.11 standard as
-published by the IEEE in 802.11-2007 (or possibly later versions).
-References to this standard will be given as "802.11-2007 8.1.5".
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/80211/mac80211-advanced.rst linux-libre-4.10-rc8-gnu/Documentation/80211/mac80211-advanced.rst
--- linux-libre-4.9-gnu/Documentation/80211/mac80211-advanced.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/80211/mac80211-advanced.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,295 +0,0 @@
-=============================
-mac80211 subsystem (advanced)
-=============================
-
-Information contained within this part of the book is of interest only
-for advanced interaction of mac80211 with drivers to exploit more
-hardware capabilities and improve performance.
-
-LED support
-===========
-
-Mac80211 supports various ways of blinking LEDs. Wherever possible,
-device LEDs should be exposed as LED class devices and hooked up to the
-appropriate trigger, which will then be triggered appropriately by
-mac80211.
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_tx_led_name
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_rx_led_name
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_assoc_led_name
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_radio_led_name
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tpt_blink
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tpt_led_trigger_flags
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_create_tpt_led_trigger
-
-Hardware crypto acceleration
-============================
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: Hardware crypto acceleration
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: set_key_cmd
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_key_conf
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_key_flags
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_tkip_p1k
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_tkip_p1k_iv
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_tkip_p2k
-
-Powersave support
-=================
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: Powersave support
-
-Beacon filter support
-=====================
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: Beacon filter support
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_beacon_loss
-
-Multiple queues and QoS support
-===============================
-
-TBD
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_queue_params
-
-Access point mode support
-=========================
-
-TBD
-
-Some parts of the if_conf should be discussed here instead
-
-Insert notes about VLAN interfaces with hw crypto here or in the hw
-crypto chapter.
-
-support for powersaving clients
--------------------------------
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: AP support for powersaving clients
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_get_buffered_bc
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_beacon_get
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_sta_eosp
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_frame_release_type
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_sta_ps_transition
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_sta_ps_transition_ni
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_sta_set_buffered
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_sta_block_awake
-
-Supporting multiple virtual interfaces
-======================================
-
-TBD
-
-Note: WDS with identical MAC address should almost always be OK
-
-Insert notes about having multiple virtual interfaces with different MAC
-addresses here, note which configurations are supported by mac80211, add
-notes about supporting hw crypto with it.
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_iterate_active_interfaces
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_iterate_active_interfaces_atomic
-
-Station handling
-================
-
-TODO
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_sta
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: sta_notify_cmd
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_find_sta
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_find_sta_by_ifaddr
-
-Hardware scan offload
-=====================
-
-TBD
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_scan_completed
-
-Aggregation
-===========
-
-TX A-MPDU aggregation
----------------------
-
-.. kernel-doc:: net/mac80211/agg-tx.c
-   :doc: TX A-MPDU aggregation
-
-.. WARNING: DOCPROC directive not supported: !Cnet/mac80211/agg-tx.c
-
-RX A-MPDU aggregation
----------------------
-
-.. kernel-doc:: net/mac80211/agg-rx.c
-   :doc: RX A-MPDU aggregation
-
-.. WARNING: DOCPROC directive not supported: !Cnet/mac80211/agg-rx.c
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_ampdu_mlme_action
-
-Spatial Multiplexing Powersave (SMPS)
-=====================================
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: Spatial multiplexing power save
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_request_smps
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_smps_mode
-
-TBD
-
-This part of the book describes the rate control algorithm interface and
-how it relates to mac80211 and drivers.
-
-Rate Control API
-================
-
-TBD
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_start_tx_ba_session
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_start_tx_ba_cb_irqsafe
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_stop_tx_ba_session
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_stop_tx_ba_cb_irqsafe
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_rate_control_changed
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_rate_control
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: rate_control_send_low
-
-TBD
-
-This part of the book describes mac80211 internals.
-
-Key handling
-============
-
-Key handling basics
--------------------
-
-.. kernel-doc:: net/mac80211/key.c
-   :doc: Key handling basics
-
-MORE TBD
---------
-
-TBD
-
-Receive processing
-==================
-
-TBD
-
-Transmit processing
-===================
-
-TBD
-
-Station info handling
-=====================
-
-Programming information
------------------------
-
-.. kernel-doc:: net/mac80211/sta_info.h
-   :functions: sta_info
-
-.. kernel-doc:: net/mac80211/sta_info.h
-   :functions: ieee80211_sta_info_flags
-
-STA information lifetime rules
-------------------------------
-
-.. kernel-doc:: net/mac80211/sta_info.c
-   :doc: STA information lifetime rules
-
-Aggregation
-===========
-
-.. kernel-doc:: net/mac80211/sta_info.h
-   :functions: sta_ampdu_mlme
-
-.. kernel-doc:: net/mac80211/sta_info.h
-   :functions: tid_ampdu_tx
-
-.. kernel-doc:: net/mac80211/sta_info.h
-   :functions: tid_ampdu_rx
-
-Synchronisation
-===============
-
-TBD
-
-Locking, lots of RCU
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/80211/mac80211.rst linux-libre-4.10-rc8-gnu/Documentation/80211/mac80211.rst
--- linux-libre-4.9-gnu/Documentation/80211/mac80211.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/80211/mac80211.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,216 +0,0 @@
-===========================
-mac80211 subsystem (basics)
-===========================
-
-You should read and understand the information contained within this
-part of the book while implementing a mac80211 driver. In some chapters,
-advanced usage is noted, those may be skipped if this isn't needed.
-
-This part of the book only covers station and monitor mode
-functionality, additional information required to implement the other
-modes is covered in the second part of the book.
-
-Basic hardware handling
-=======================
-
-TBD
-
-This chapter shall contain information on getting a hw struct allocated
-and registered with mac80211.
-
-Since it is required to allocate rates/modes before registering a hw
-struct, this chapter shall also contain information on setting up the
-rate/mode structs.
-
-Additionally, some discussion about the callbacks and the general
-programming model should be in here, including the definition of
-ieee80211_ops which will be referred to a lot.
-
-Finally, a discussion of hardware capabilities should be done with
-references to other parts of the book.
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_hw
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_hw_flags
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: SET_IEEE80211_DEV
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: SET_IEEE80211_PERM_ADDR
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_ops
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_alloc_hw
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_register_hw
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_unregister_hw
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_free_hw
-
-PHY configuration
-=================
-
-TBD
-
-This chapter should describe PHY handling including start/stop callbacks
-and the various structures used.
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_conf
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_conf_flags
-
-Virtual interfaces
-==================
-
-TBD
-
-This chapter should describe virtual interface basics that are relevant
-to the driver (VLANs, MGMT etc are not.) It should explain the use of
-the add_iface/remove_iface callbacks as well as the interface
-configuration callbacks.
-
-Things related to AP mode should be discussed there.
-
-Things related to supporting multiple interfaces should be in the
-appropriate chapter, a BIG FAT note should be here about this though and
-the recommendation to allow only a single interface in STA mode at
-first!
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_vif
-
-Receive and transmit processing
-===============================
-
-what should be here
--------------------
-
-TBD
-
-This should describe the receive and transmit paths in mac80211/the
-drivers as well as transmit status handling.
-
-Frame format
-------------
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: Frame format
-
-Packet alignment
-----------------
-
-.. kernel-doc:: net/mac80211/rx.c
-   :doc: Packet alignment
-
-Calling into mac80211 from interrupts
--------------------------------------
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: Calling mac80211 from interrupts
-
-functions/definitions
----------------------
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_rx_status
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: mac80211_rx_flags
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: mac80211_tx_info_flags
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: mac80211_tx_control_flags
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: mac80211_rate_control_flags
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_rate
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_info
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_info_clear_status
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_rx
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_rx_ni
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_rx_irqsafe
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_status
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_status_ni
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_tx_status_irqsafe
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_rts_get
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_rts_duration
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_ctstoself_get
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_ctstoself_duration
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_generic_frame_duration
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_wake_queue
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_stop_queue
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_wake_queues
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_stop_queues
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_queue_stopped
-
-Frame filtering
-===============
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: Frame filtering
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_filter_flags
-
-The mac80211 workqueue
-======================
-
-.. kernel-doc:: include/net/mac80211.h
-   :doc: mac80211 workqueue
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_queue_work
-
-.. kernel-doc:: include/net/mac80211.h
-   :functions: ieee80211_queue_delayed_work
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/README linux-libre-4.10-rc8-gnu/Documentation/ABI/README
--- linux-libre-4.9-gnu/Documentation/ABI/README	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/README	2017-02-12 16:03:20.000000000 -0500
@@ -84,4 +84,4 @@ stable:
 
 - Kernel-internal symbols.  Do not rely on the presence, absence, location, or
   type of any kernel symbol, either in System.map files or the kernel binary
-  itself.  See Documentation/stable_api_nonsense.txt.
+  itself.  See Documentation/process/stable-api-nonsense.rst.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/stable/sysfs-devices linux-libre-4.10-rc8-gnu/Documentation/ABI/stable/sysfs-devices
--- linux-libre-4.9-gnu/Documentation/ABI/stable/sysfs-devices	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/stable/sysfs-devices	2017-02-12 16:03:20.000000000 -0500
@@ -8,3 +8,17 @@ Description:
 		Any device associated with a device-tree node will have
 		an of_path symlink pointing to the corresponding device
 		node in /sys/firmware/devicetree/
+
+What:		/sys/devices/*/devspec
+Date:		October 2016
+Contact:	Device Tree mailing list <devicetree@vger.kernel.org>
+Description:
+		If CONFIG_OF is enabled, then this file is present. When
+		read, it returns full name of the device node.
+
+What:		/sys/devices/*/obppath
+Date:		October 2016
+Contact:	Device Tree mailing list <devicetree@vger.kernel.org>
+Description:
+		If CONFIG_OF is enabled, then this file is present. When
+		read, it returns full name of the device node.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-block linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-block
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-block	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-block	2017-02-12 16:03:20.000000000 -0500
@@ -235,3 +235,45 @@ Description:
 		write_same_max_bytes is 0, write same is not supported
 		by the device.
 
+What:		/sys/block/<disk>/queue/write_zeroes_max_bytes
+Date:		November 2016
+Contact:	Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
+Description:
+		Devices that support write zeroes operation in which a
+		single request can be issued to zero out the range of
+		contiguous blocks on storage without having any payload
+		in the request. This can be used to optimize writing zeroes
+		to the devices. write_zeroes_max_bytes indicates how many
+		bytes can be written in a single write zeroes command. If
+		write_zeroes_max_bytes is 0, write zeroes is not supported
+		by the device.
+
+What:		/sys/block/<disk>/queue/zoned
+Date:		September 2016
+Contact:	Damien Le Moal <damien.lemoal@hgst.com>
+Description:
+		zoned indicates if the device is a zoned block device
+		and the zone model of the device if it is indeed zoned.
+		The possible values indicated by zoned are "none" for
+		regular block devices and "host-aware" or "host-managed"
+		for zoned block devices. The characteristics of
+		host-aware and host-managed zoned block devices are
+		described in the ZBC (Zoned Block Commands) and ZAC
+		(Zoned Device ATA Command Set) standards. These standards
+		also define the "drive-managed" zone model. However,
+		since drive-managed zoned block devices do not support
+		zone commands, they will be treated as regular block
+		devices and zoned will report "none".
+
+What:		/sys/block/<disk>/queue/chunk_sectors
+Date:		September 2016
+Contact:	Hannes Reinecke <hare@suse.com>
+Description:
+		chunk_sectors has different meaning depending on the type
+		of the disk. For a RAID device (dm-raid), chunk_sectors
+		indicates the size in 512B sectors of the RAID volume
+		stripe segment. For a zoned block device, either
+		host-aware or host-managed, chunk_sectors indicates the
+		size of 512B sectors of the zones of the device, with
+		the eventual exception of the last zone of the device
+		which may be smaller.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-fsl-mc linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-fsl-mc
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-fsl-mc	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-fsl-mc	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,21 @@
+What:		/sys/bus/fsl-mc/drivers/.../bind
+Date:		December 2016
+Contact:	stuart.yoder@nxp.com
+Description:
+		Writing a device location to this file will cause
+		the driver to attempt to bind to the device found at
+		this location. The format for the location is Object.Id
+		and is the same as found in /sys/bus/fsl-mc/devices/.
+                For example:
+		# echo dpni.2 > /sys/bus/fsl-mc/drivers/fsl_dpaa2_eth/bind
+
+What:		/sys/bus/fsl-mc/drivers/.../unbind
+Date:		December 2016
+Contact:	stuart.yoder@nxp.com
+Description:
+		Writing a device location to this file will cause the
+		driver to attempt to unbind from the device found at
+		this location. The format for the location is Object.Id
+		and is the same as found in /sys/bus/fsl-mc/devices/.
+                For example:
+		# echo dpni.2 > /sys/bus/fsl-mc/drivers/fsl_dpaa2_eth/unbind
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio	2017-02-12 16:03:20.000000000 -0500
@@ -329,6 +329,7 @@ What:		/sys/bus/iio/devices/iio:deviceX/
 What:		/sys/bus/iio/devices/iio:deviceX/in_humidityrelative_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_velocity_sqrt(x^2+y^2+z^2)_scale
 What:		/sys/bus/iio/devices/iio:deviceX/in_illuminance_scale
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_scale
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -1579,3 +1580,20 @@ Contact:	linux-iio@vger.kernel.org
 Description:
 		Raw (unscaled no offset etc.) electric conductivity reading that
 		can be processed to siemens per meter.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_raw
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw counter device counts from channel Y. For quadrature
+		counters, multiplication by an available [Y]_scale results in
+		the counts of a single quadrature signal phase from channel Y.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_indexY_raw
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw counter device index value from channel Y. This attribute
+		provides an absolute positional reference (e.g. a pulse once per
+		revolution) which may be used to home positional systems as
+		required.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-adc-envelope-detector	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,36 @@
+What:		/sys/bus/iio/devices/iio:deviceX/in_altvoltageY_invert
+Date:		October 2016
+KernelVersion:	4.9
+Contact:	Peter Rosin <peda@axentia.se>
+Description:
+		The DAC is used to find the peak level of an alternating
+		voltage input signal by a binary search using the output
+		of a comparator wired to an interrupt pin. Like so:
+		                           _
+		                          | \
+		     input +------>-------|+ \
+		                          |   \
+		            .-------.     |    }---.
+		            |       |     |   /    |
+		            |    dac|-->--|- /     |
+		            |       |     |_/      |
+		            |       |              |
+		            |       |              |
+		            |    irq|------<-------'
+		            |       |
+		            '-------'
+		The boolean invert attribute (0/1) should be set when the
+		input signal is centered around the maximum value of the
+		dac instead of zero. The envelope detector will search
+		from below in this case and will also invert the result.
+		The edge/level of the interrupt is also switched to its
+		opposite value.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_altvoltageY_compare_interval
+Date:		October 2016
+KernelVersion:	4.9
+Contact:	Peter Rosin <peda@axentia.se>
+Description:
+		Number of milliseconds to wait for the comparator in each
+		step of the binary search for the input peak level. Needs
+		to relate to the frequency of the input signal.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8 linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-counter-104-quad-8	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,125 @@
+What:		/sys/bus/iio/devices/iio:deviceX/in_count_count_direction_available
+What:		/sys/bus/iio/devices/iio:deviceX/in_count_count_mode_available
+What:		/sys/bus/iio/devices/iio:deviceX/in_count_noise_error_available
+What:		/sys/bus/iio/devices/iio:deviceX/in_count_quadrature_mode_available
+What:		/sys/bus/iio/devices/iio:deviceX/in_index_index_polarity_available
+What:		/sys/bus/iio/devices/iio:deviceX/in_index_synchronous_mode_available
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Discrete set of available values for the respective counter
+		configuration are listed in this file.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_count_direction
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read-only attribute that indicates whether the counter for
+		channel Y is counting up or down.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_count_mode
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Count mode for channel Y. Four count modes are available:
+		normal, range limit, non-recycle, and modulo-n. The preset value
+		for channel Y is used by the count mode where required.
+
+		Normal:
+			Counting is continuous in either direction.
+
+		Range Limit:
+			An upper or lower limit is set, mimicking limit switches
+			in the mechanical counterpart. The upper limit is set to
+			the preset value, while the lower limit is set to 0. The
+			counter freezes at count = preset when counting up, and
+			at count = 0 when counting down. At either of these
+			limits, the counting is resumed only when the count
+			direction is reversed.
+
+		Non-recycle:
+			Counter is disabled whenever a 24-bit count overflow or
+			underflow takes place. The counter is re-enabled when a
+			new count value is loaded to the counter via a preset
+			operation or write to raw.
+
+		Modulo-N:
+			A count boundary is set between 0 and the preset value.
+			The counter is reset to 0 at count = preset when
+			counting up, while the counter is set to the preset
+			value at count = 0 when counting down; the counter does
+			not freeze at the bundary points, but counts
+			continuously throughout.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_noise_error
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read-only attribute that indicates whether excessive noise is
+		present at the channel Y count inputs in quadrature clock mode;
+		irrelevant in non-quadrature clock mode.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_preset
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		If the counter device supports preset registers, the preset
+		count for channel Y is provided by this attribute.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_quadrature_mode
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Configure channel Y counter for non-quadrature or quadrature
+		clock mode. Selecting non-quadrature clock mode will disable
+		synchronous load mode. In quadrature clock mode, the channel Y
+		scale attribute selects the encoder phase division (scale of 1
+		selects full-cycle, scale of 0.5 selects half-cycle, scale of
+		0.25 selects quarter-cycle) processed by the channel Y counter.
+
+		Non-quadrature:
+			The filter and decoder circuit are bypassed. Encoder A
+			input serves as the count input and B as the UP/DOWN
+			direction control input, with B = 1 selecting UP Count
+			mode and B = 0 selecting Down Count mode.
+
+		Quadrature:
+			Encoder A and B inputs are digitally filtered and
+			decoded for UP/DN clock.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_countY_set_to_preset_on_index
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Whether to set channel Y counter with channel Y preset value
+		when channel Y index input is active, or continuously count.
+		Valid attribute values are boolean.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_indexY_index_polarity
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Active level of channel Y index input; irrelevant in
+		non-synchronous load mode.
+
+What:		/sys/bus/iio/devices/iio:deviceX/in_indexY_synchronous_mode
+KernelVersion:	4.9
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Configure channel Y counter for non-synchronous or synchronous
+		load mode. Synchronous load mode cannot be selected in
+		non-quadrature clock mode.
+
+		Non-synchronous:
+			A logic low level is the active level at this index
+			input. The index function (as enabled via
+			set_to_preset_on_index) is performed directly on the
+			active level of the index input.
+
+		Synchronous:
+			Intended for interfacing with encoder Index output in
+			quadrature clock mode. The active level is configured
+			via index_polarity. The index function (as enabled via
+			set_to_preset_on_index) is performed synchronously with
+			the quadrature clock on the active level of the index
+			input.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-cros-ec linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-cros-ec	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-cros-ec	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,18 @@
+What:		/sys/bus/iio/devices/iio:deviceX/calibrate
+Date:		July 2015
+KernelVersion:	4.7
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Writing '1' will perform a FOC (Fast Online Calibration). The
+                corresponding calibration offsets can be read from *_calibbias
+                entries.
+
+What:		/sys/bus/iio/devices/iio:deviceX/location
+Date:		July 2015
+KernelVersion:	4.7
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This attribute returns a string with the physical location where
+                the motion sensor is placed. For example, in a laptop a motion
+                sensor can be located on the base or on the lid. Current valid
+		values are 'base' and 'lid'.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-dac-dpot-dac	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+What:		/sys/bus/iio/devices/iio:deviceX/out_voltageY_raw_available
+Date:		October 2016
+KernelVersion:	4.9
+Contact:	Peter Rosin <peda@axentia.se>
+Description:
+		The range of available values represented as the minimum value,
+		the step and the maximum value, all enclosed in square brackets.
+		Example: [0 1 256]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-isl29018 linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-isl29018
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-isl29018	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-isl29018	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,19 @@
+What:		/sys/bus/iio/devices/iio:deviceX/proximity_on_chip_ambient_infrared_suppression
+Date:		January 2011
+KernelVersion:	2.6.37
+Contact:	linux-iio@vger.kernel.org
+Description:
+		From ISL29018 Data Sheet (FN6619.4, Oct 8, 2012) regarding the
+		infrared suppression:
+
+		Scheme 0, makes full n (4, 8, 12, 16) bits (unsigned) proximity
+		detection. The range of Scheme 0 proximity count is from 0 to
+		2^n. Logic 1 of this bit, Scheme 1, makes n-1 (3, 7, 11, 15)
+		bits (2's complementary) proximity_less_ambient detection. The
+		range of Scheme 1 proximity count is from -2^(n-1) to 2^(n-1).
+		The sign bit is extended for resolutions less than 16. While
+		Scheme 0 has wider dynamic range, Scheme 1 proximity detection
+		is less affected by the ambient IR noise variation.
+
+		0 Sensing IR from LED and ambient
+		1 Sensing IR from LED with ambient IR rejection
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-tsl2583 linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-tsl2583
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-tsl2583	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-light-tsl2583	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+What:		/sys/bus/iio/devices/device[n]/in_illuminance_calibrate
+KernelVersion:	2.6.37
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This property causes an internal calibration of the als gain trim
+		value which is later used in calculating illuminance in lux.
+
+What:		/sys/bus/iio/devices/device[n]/in_illuminance_lux_table
+KernelVersion:	2.6.37
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This property gets/sets the table of coefficients
+		used in calculating illuminance in lux.
+
+What:		/sys/bus/iio/devices/device[n]/in_illuminance_input_target
+KernelVersion:	2.6.37
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This property is the known externally illuminance (in lux).
+		It is used in the process of calibrating the device accuracy.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531 linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-iio-potentiometer-mcp4531	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+What:		/sys/bus/iio/devices/iio:deviceX/out_resistance_raw_available
+Date:		October 2016
+KernelVersion:	4.9
+Contact:	Peter Rosin <peda@axentia.se>
+Description:
+		The range of available values represented as the minimum value,
+		the step and the maximum value, all enclosed in square brackets.
+		Example: [0 1 256]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-pci linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-pci
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-pci	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-pci	2017-02-12 16:03:20.000000000 -0500
@@ -294,3 +294,10 @@ Description:
 		a firmware bug to the system vendor.  Writing to this file
 		taints the kernel with TAINT_FIRMWARE_WORKAROUND, which
 		reduces the supportability of your system.
+
+What:		/sys/bus/pci/devices/.../revision
+Date:		November 2016
+Contact:	Emil Velikov <emil.l.velikov@gmail.com>
+Description:
+		This file contains the revision field of the the PCI device.
+		The value comes from device config space. The file is read only.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-vfio-mdev linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-vfio-mdev
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-bus-vfio-mdev	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-bus-vfio-mdev	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,111 @@
+What:           /sys/.../<device>/mdev_supported_types/
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+                This directory contains list of directories of currently
+		supported mediated device types and their details for
+		<device>. Supported type attributes are defined by the
+		vendor driver who registers with Mediated device framework.
+		Each supported type is a directory whose name is created
+		by adding the device driver string as a prefix to the
+		string provided by the vendor driver.
+
+What:           /sys/.../<device>/mdev_supported_types/<type-id>/
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+                This directory gives details of supported type, like name,
+		description, available_instances, device_api etc.
+		'device_api' and 'available_instances' are mandatory
+		attributes to be provided by vendor driver. 'name',
+		'description' and other vendor driver specific attributes
+		are optional.
+
+What:           /sys/.../mdev_supported_types/<type-id>/create
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		Writing UUID to this file will create mediated device of
+		type <type-id> for parent device <device>. This is a
+		write-only file.
+		For example:
+		# echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1001" >	\
+		       /sys/devices/foo/mdev_supported_types/foo-1/create
+
+What:           /sys/.../mdev_supported_types/<type-id>/devices/
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		This directory contains symbolic links pointing to mdev
+		devices sysfs entries which are created of this <type-id>.
+
+What:           /sys/.../mdev_supported_types/<type-id>/available_instances
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		Reading this attribute will show the number of mediated
+		devices of type <type-id> that can be created. This is a
+		readonly file.
+Users:
+		Userspace applications interested in creating mediated
+		device of that type. Userspace application should check
+		the number of available instances could be created before
+		creating mediated device of this type.
+
+What:           /sys/.../mdev_supported_types/<type-id>/device_api
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		Reading this attribute will show VFIO device API supported
+		by this type. For example, "vfio-pci" for a PCI device,
+		"vfio-platform" for platform device.
+
+What:           /sys/.../mdev_supported_types/<type-id>/name
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		Reading this attribute will show human readable name of the
+		mediated device that will get created of type <type-id>.
+		This is optional attribute. For example: "Grid M60-0Q"
+Users:
+		Userspace applications interested in knowing the name of
+		a particular <type-id> that can help in understanding the
+		type of mediated device.
+
+What:           /sys/.../mdev_supported_types/<type-id>/description
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		Reading this attribute will show description of the type of
+		mediated device that will get created of type <type-id>.
+		This is optional attribute. For example:
+		"2 heads, 512M FB, 2560x1600 maximum resolution"
+Users:
+		Userspace applications interested in knowing the details of
+		a particular <type-id> that can help in understanding the
+		features provided by that type of mediated device.
+
+What:           /sys/.../<device>/<UUID>/
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		This directory represents device directory of mediated
+		device. It contains all the attributes related to mediated
+		device.
+
+What:           /sys/.../<device>/<UUID>/mdev_type
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		This is symbolic link pointing to supported type, <type-id>
+		directory of which this mediated device is created.
+
+What:           /sys/.../<device>/<UUID>/remove
+Date:           October 2016
+Contact:        Kirti Wankhede <kwankhede@nvidia.com>
+Description:
+		Writing '1' to this file destroys the mediated device. The
+		vendor driver can fail the remove() callback if that device
+		is active and the vendor driver doesn't support hot unplug.
+		Example:
+		# echo 1 > /sys/bus/mdev/devices/<UUID>/remove
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-fpga-bridge linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-fpga-bridge
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-fpga-bridge	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-fpga-bridge	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,11 @@
+What:		/sys/class/fpga_bridge/<bridge>/name
+Date:		January 2016
+KernelVersion:	4.5
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Name of low level FPGA bridge driver.
+
+What:		/sys/class/fpga_bridge/<bridge>/state
+Date:		January 2016
+KernelVersion:	4.5
+Contact:	Alan Tull <atull@opensource.altera.com>
+Description:	Show bridge state as "enabled" or "disabled"
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-led linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-led
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-led	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-led	2017-02-12 16:03:20.000000000 -0500
@@ -4,16 +4,24 @@ KernelVersion:	2.6.17
 Contact:	Richard Purdie <rpurdie@rpsys.net>
 Description:
 		Set the brightness of the LED. Most LEDs don't
-		have hardware brightness support so will just be turned on for
+		have hardware brightness support, so will just be turned on for
 		non-zero brightness settings. The value is between 0 and
 		/sys/class/leds/<led>/max_brightness.
 
+		Writing 0 to this file clears active trigger.
+
+		Writing non-zero to this file while trigger is active changes the
+		top brightness trigger is going to use.
+
 What:		/sys/class/leds/<led>/max_brightness
 Date:		March 2006
 KernelVersion:	2.6.17
 Contact:	Richard Purdie <rpurdie@rpsys.net>
 Description:
-		Maximum brightness level for this led, default is 255 (LED_FULL).
+		Maximum brightness level for this LED, default is 255 (LED_FULL).
+
+		If the LED does not support different brightness levels, this
+		should be 1.
 
 What:		/sys/class/leds/<led>/trigger
 Date:		March 2006
@@ -21,7 +29,7 @@ KernelVersion:	2.6.17
 Contact:	Richard Purdie <rpurdie@rpsys.net>
 Description:
 		Set the trigger for this LED. A trigger is a kernel based source
-		of led events.
+		of LED events.
 		You can change triggers in a similar manner to the way an IO
 		scheduler is chosen. Trigger specific parameters can appear in
 		/sys/class/leds/<led> once a given trigger is selected. For
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-mei linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-mei
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-mei	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-mei	2017-02-12 16:03:20.000000000 -0500
@@ -29,3 +29,19 @@ Description:	Display fw status registers
 		Also number of registers varies between 1 and 6
 		depending on generation.
 
+What:		/sys/class/mei/meiN/hbm_ver
+Date:		Aug 2016
+KernelVersion:	4.9
+Contact:	Tomas Winkler <tomas.winkler@intel.com>
+Description:	Display the negotiated HBM protocol version.
+
+		The HBM protocol version negotiated
+		between the driver and the device.
+
+What:		/sys/class/mei/meiN/hbm_ver_drv
+Date:		Aug 2016
+KernelVersion:	4.9
+Contact:	Tomas Winkler <tomas.winkler@intel.com>
+Description:	Display the driver HBM protocol version.
+
+		The HBM protocol version supported by the driver.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-remoteproc linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-remoteproc
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-remoteproc	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-remoteproc	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,50 @@
+What:		/sys/class/remoteproc/.../firmware
+Date:		October 2016
+Contact:	Matt Redfearn <matt.redfearn@imgtec.com>
+Description:	Remote processor firmware
+
+		Reports the name of the firmware currently loaded to the
+		remote processor.
+
+		To change the running firmware, ensure the remote processor is
+		stopped (using /sys/class/remoteproc/.../state) and write a new filename.
+
+What:		/sys/class/remoteproc/.../state
+Date:		October 2016
+Contact:	Matt Redfearn <matt.redfearn@imgtec.com>
+Description:	Remote processor state
+
+		Reports the state of the remote processor, which will be one of:
+
+		"offline"
+		"suspended"
+		"running"
+		"crashed"
+		"invalid"
+
+		"offline" means the remote processor is powered off.
+
+		"suspended" means that the remote processor is suspended and
+		must be woken to receive messages.
+
+		"running" is the normal state of an available remote processor
+
+		"crashed" indicates that a problem/crash has been detected on
+		the remote processor.
+
+		"invalid" is returned if the remote processor is in an
+		unknown state.
+
+		Writing this file controls the state of the remote processor.
+		The following states can be written:
+
+		"start"
+		"stop"
+
+		Writing "start" will attempt to start the processor running the
+		firmware indicated by, or written to,
+		/sys/class/remoteproc/.../firmware. The remote processor should
+		transition to "running" state.
+
+		Writing "stop" will attempt to halt the remote processor and
+		return it to the "offline" state.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration	2017-02-12 16:03:20.000000000 -0500
@@ -1,8 +1,9 @@
-What:           Attribute for calibrating ST-Ericsson AB8500 Real Time Clock
+What:           /sys/class/rtc/rtc0/device/rtc_calibration
 Date:           Oct 2011
 KernelVersion:  3.0
 Contact:        Mark Godfrey <mark.godfrey@stericsson.com>
-Description:    The rtc_calibration attribute allows the userspace to
+Description:    Attribute for calibrating ST-Ericsson AB8500 Real Time Clock
+		The rtc_calibration attribute allows the userspace to
                 calibrate the AB8500.s 32KHz Real Time Clock.
                 Every 60 seconds the AB8500 will correct the RTC's value
                 by adding to it the value of this attribute.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-devices-system-cpu linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-devices-system-cpu
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-devices-system-cpu	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-devices-system-cpu	2017-02-12 16:03:20.000000000 -0500
@@ -272,6 +272,22 @@ Description:	Parameters for the CPU cach
 				     the modified cache line is written to main
 				     memory only when it is replaced
 
+
+What:		/sys/devices/system/cpu/cpu*/cache/index*/id
+Date:		September 2016
+Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
+Description:	Cache id
+
+		The id provides a unique number for a specific instance of
+		a cache of a particular type. E.g. there may be a level
+		3 unified cache on each socket in a server and we may
+		assign them ids 0, 1, 2, ...
+
+		Note that id value can be non-contiguous. E.g. level 1
+		caches typically exist per core, but there may not be a
+		power of two cores on a socket, so these caches may be
+		numbered 0, 1, 2, 3, 4, 5, 8, 9, 10, ...
+
 What:		/sys/devices/system/cpu/cpuX/cpufreq/throttle_stats
 		/sys/devices/system/cpu/cpuX/cpufreq/throttle_stats/turbo_stat
 		/sys/devices/system/cpu/cpuX/cpufreq/throttle_stats/sub_turbo_stat
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-kernel-slab linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-kernel-slab
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-kernel-slab	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-kernel-slab	2017-02-12 16:03:20.000000000 -0500
@@ -347,7 +347,7 @@ Description:
 		because of fragmentation, SLUB will retry with the minimum order
 		possible depending on its characteristics.
 		When debug_guardpage_minorder=N (N > 0) parameter is specified
-		(see Documentation/kernel-parameters.txt), the minimum possible
+		(see Documentation/admin-guide/kernel-parameters.rst), the minimum possible
 		order is used and this sysfs entry can not be used to change
 		the order at run time.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2 linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-platform-phy-rcar-gen3-usb2	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,15 @@
+What:		/sys/devices/platform/<phy-name>/role
+Date:		October 2016
+KernelVersion:	4.10
+Contact:	Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Description:
+		This file can be read and write.
+		The file can show/change the phy mode for role swap of usb.
+
+		Write the following strings to change the mode:
+		 "host" - switching mode from peripheral to host.
+		 "peripheral" - switching mode from host to peripheral.
+
+		Read the file, then it shows the following strings:
+		 "host" - The mode is host now.
+		 "peripheral" - The mode is peripheral now.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-platform-sst-atom linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-platform-sst-atom
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-platform-sst-atom	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-platform-sst-atom	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,17 @@
+What:		/sys/devices/platform/8086%x:00/firmware_version
+Date:		November 2016
+KernelVersion:	4.10
+Contact:	"Sebastien Guiriec" <sebastien.guiriec@intel.com>
+Description:
+		LPE Firmware version for SST driver on all atom
+		plaforms (BYT/CHT/Merrifield/BSW).
+		If the FW has never been loaded it will display:
+			"FW not yet loaded"
+		If FW has been loaded it will display:
+			"v01.aa.bb.cc"
+		aa: Major version is reflecting SoC version:
+			0d: BYT FW
+			0b: BSW FW
+			07: Merrifield FW
+		bb: Minor version
+		cc: Build version
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-power linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-power
--- linux-libre-4.9-gnu/Documentation/ABI/testing/sysfs-power	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ABI/testing/sysfs-power	2017-02-12 16:03:20.000000000 -0500
@@ -7,30 +7,35 @@ Description:
 		subsystem.
 
 What:		/sys/power/state
-Date:		May 2014
+Date:		November 2016
 Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
 Description:
 		The /sys/power/state file controls system sleep states.
 		Reading from this file returns the available sleep state
-		labels, which may be "mem", "standby", "freeze" and "disk"
-		(hibernation).  The meanings of the first three labels depend on
-		the relative_sleep_states command line argument as follows:
-		 1) relative_sleep_states = 1
-		    "mem", "standby", "freeze" represent non-hibernation sleep
-		    states from the deepest ("mem", always present) to the
-		    shallowest ("freeze").  "standby" and "freeze" may or may
-		    not be present depending on the capabilities of the
-		    platform.  "freeze" can only be present if "standby" is
-		    present.
-		 2) relative_sleep_states = 0 (default)
-		    "mem" - "suspend-to-RAM", present if supported.
-		    "standby" - "power-on suspend", present if supported.
-		    "freeze" - "suspend-to-idle", always present.
+		labels, which may be "mem" (suspend), "standby" (power-on
+		suspend), "freeze" (suspend-to-idle) and "disk" (hibernation).
 
-		Writing to this file one of these strings causes the system to
-		transition into the corresponding state, if available.  See
-		Documentation/power/states.txt for a description of what
-		"suspend-to-RAM", "power-on suspend" and "suspend-to-idle" mean.
+		Writing one of the above strings to this file causes the system
+		to transition into the corresponding state, if available.
+
+		See Documentation/power/states.txt for more information.
+
+What:		/sys/power/mem_sleep
+Date:		November 2016
+Contact:	Rafael J. Wysocki <rjw@rjwysocki.net>
+Description:
+		The /sys/power/mem_sleep file controls the operating mode of
+		system suspend.  Reading from it returns the available modes
+		as "s2idle" (always present), "shallow" and "deep" (present if
+		supported).  The mode that will be used on subsequent attempts
+		to suspend the system (by writing "mem" to the /sys/power/state
+		file described above) is enclosed in square brackets.
+
+		Writing one of the above strings to this file causes the mode
+		represented by it to be used on subsequent attempts to suspend
+		the system.
+
+		See Documentation/power/states.txt for more information.
 
 What:		/sys/power/disk
 Date:		September 2006
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/acpi/DSD-properties-rules.txt linux-libre-4.10-rc8-gnu/Documentation/acpi/DSD-properties-rules.txt
--- linux-libre-4.9-gnu/Documentation/acpi/DSD-properties-rules.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/acpi/DSD-properties-rules.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,97 @@
+_DSD Device Properties Usage Rules
+----------------------------------
+
+Properties, Property Sets and Property Subsets
+----------------------------------------------
+
+The _DSD (Device Specific Data) configuration object, introduced in ACPI 5.1,
+allows any type of device configuration data to be provided via the ACPI
+namespace.  In principle, the format of the data may be arbitrary, but it has to
+be identified by a UUID which must be recognized by the driver processing the
+_DSD output.  However, there are generic UUIDs defined for _DSD recognized by
+the ACPI subsystem in the Linux kernel which automatically processes the data
+packages associated with them and makes those data available to device drivers
+as "device properties".
+
+A device property is a data item consisting of a string key and a value (of a
+specific type) associated with it.
+
+In the ACPI _DSD context it is an element of the sub-package following the
+generic Device Properties UUID in the _DSD return package as specified in the
+Device Properties UUID definition document [1].
+
+It also may be regarded as the definition of a key and the associated data type
+that can be returned by _DSD in the Device Properties UUID sub-package for a
+given device.
+
+A property set is a collection of properties applicable to a hardware entity
+like a device.  In the ACPI _DSD context it is the set of all properties that
+can be returned in the Device Properties UUID sub-package for the device in
+question.
+
+Property subsets are nested collections of properties.  Each of them is
+associated with an additional key (name) allowing the subset to be referred
+to as a whole (and to be treated as a separate entity).  The canonical
+representation of property subsets is via the mechanism specified in the
+Hierarchical Properties Extension UUID definition document [2].
+
+Property sets may be hierarchical.  That is, a property set may contain
+multiple property subsets that each may contain property subsets of its
+own and so on.
+
+General Validity Rule for Property Sets
+---------------------------------------
+
+Valid property sets must follow the guidance given by the Device Properties UUID
+definition document [1].
+
+_DSD properties are intended to be used in addition to, and not instead of, the
+existing mechanisms defined by the ACPI specification.  Therefore, as a rule,
+they should only be used if the ACPI specification does not make direct
+provisions for handling the underlying use case.  It generally is invalid to
+return property sets which do not follow that rule from _DSD in data packages
+associated with the Device Properties UUID.
+
+Additional Considerations
+-------------------------
+
+There are cases in which, even if the general rule given above is followed in
+principle, the property set may still not be regarded as a valid one.
+
+For example, that applies to device properties which may cause kernel code
+(either a device driver or a library/subsystem) to access hardware in a way
+possibly leading to a conflict with AML methods in the ACPI namespace.  In
+particular, that may happen if the kernel code uses device properties to
+manipulate hardware normally controlled by ACPI methods related to power
+management, like _PSx and _DSW (for device objects) or _ON and _OFF (for power
+resource objects), or by ACPI device disabling/enabling methods, like _DIS and
+_SRS.
+
+In all cases in which kernel code may do something that will confuse AML as a
+result of using device properties, the device properties in question are not
+suitable for the ACPI environment and consequently they cannot belong to a valid
+property set.
+
+Property Sets and Device Tree Bindings
+--------------------------------------
+
+It often is useful to make _DSD return property sets that follow Device Tree
+bindings.
+
+In those cases, however, the above validity considerations must be taken into
+account in the first place and returning invalid property sets from _DSD must be
+avoided.  For this reason, it may not be possible to make _DSD return a property
+set following the given DT binding literally and completely.  Still, for the
+sake of code re-use, it may make sense to provide as much of the configuration
+data as possible in the form of device properties and complement that with an
+ACPI-specific mechanism suitable for the use case at hand.
+
+In any case, property sets following DT bindings literally should not be
+expected to automatically work in the ACPI environment regardless of their
+contents.
+
+References
+----------
+
+[1] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
+[2] http://www.uefi.org/sites/default/files/resources/_DSD-hierarchical-data-extension-UUID-v1.1.pdf
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/acpi/enumeration.txt linux-libre-4.10-rc8-gnu/Documentation/acpi/enumeration.txt
--- linux-libre-4.9-gnu/Documentation/acpi/enumeration.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/acpi/enumeration.txt	2017-02-12 16:03:20.000000000 -0500
@@ -415,3 +415,12 @@ the "compatible" property in the _DSD or
 ancestors provides a _DSD with a valid "compatible" property.  Such device
 objects are then simply regarded as additional "blocks" providing hierarchical
 configuration information to the driver of the composite ancestor device.
+
+However, PRP0001 can only be returned from either _HID or _CID of a device
+object if all of the properties returned by the _DSD associated with it (either
+the _DSD of the device object itself or the _DSD of its ancestor in the
+"composite device" case described above) can be used in the ACPI environment.
+Otherwise, the _DSD itself is regarded as invalid and therefore the "compatible"
+property returned by it is meaningless.
+
+Refer to DSD-properties-rules.txt for more information.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/acpi/gpio-properties.txt linux-libre-4.10-rc8-gnu/Documentation/acpi/gpio-properties.txt
--- linux-libre-4.9-gnu/Documentation/acpi/gpio-properties.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/acpi/gpio-properties.txt	2017-02-12 16:03:20.000000000 -0500
@@ -51,6 +51,68 @@ it to 1 marks the GPIO as active low.
 In our Bluetooth example the "reset-gpios" refers to the second GpioIo()
 resource, second pin in that resource with the GPIO number of 31.
 
+It is possible to leave holes in the array of GPIOs. This is useful in
+cases like with SPI host controllers where some chip selects may be
+implemented as GPIOs and some as native signals. For example a SPI host
+controller can have chip selects 0 and 2 implemented as GPIOs and 1 as
+native:
+
+  Package () {
+      "cs-gpios",
+      Package () {
+          ^GPIO, 19, 0, 0, // chip select 0: GPIO
+          0,               // chip select 1: native signal
+          ^GPIO, 20, 0, 0, // chip select 2: GPIO
+      }
+  }
+
+Other supported properties
+--------------------------
+
+Following Device Tree compatible device properties are also supported by
+_DSD device properties for GPIO controllers:
+
+- gpio-hog
+- output-high
+- output-low
+- input
+- line-name
+
+Example:
+
+  Name (_DSD, Package () {
+      // _DSD Hierarchical Properties Extension UUID
+      ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
+      Package () {
+          Package () {"hog-gpio8", "G8PU"}
+      }
+  })
+
+  Name (G8PU, Package () {
+      ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+      Package () {
+          Package () {"gpio-hog", 1},
+          Package () {"gpios", Package () {8, 0}},
+          Package () {"output-high", 1},
+          Package () {"line-name", "gpio8-pullup"},
+      }
+  })
+
+- gpio-line-names
+
+Example:
+
+  Package () {
+      "gpio-line-names",
+      Package () {
+          "SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD", "MUX7_IO",
+          "LVL_C_A1", "MUX0_IO", "SPI1_MISO"
+      }
+  }
+
+See Documentation/devicetree/bindings/gpio/gpio.txt for more information
+about these properties.
+
 ACPI GPIO Mappings Provided by Drivers
 --------------------------------------
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/acpi/osi.txt linux-libre-4.10-rc8-gnu/Documentation/acpi/osi.txt
--- linux-libre-4.9-gnu/Documentation/acpi/osi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/acpi/osi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,187 @@
+ACPI _OSI and _REV methods
+--------------------------
+
+An ACPI BIOS can use the "Operating System Interfaces" method (_OSI)
+to find out what the operating system supports. Eg. If BIOS
+AML code includes _OSI("XYZ"), the kernel's AML interpreter
+can evaluate that method, look to see if it supports 'XYZ'
+and answer YES or NO to the BIOS.
+
+The ACPI _REV method returns the "Revision of the ACPI specification
+that OSPM supports"
+
+This document explains how and why the BIOS and Linux should use these methods.
+It also explains how and why they are widely misused.
+
+How to use _OSI
+---------------
+
+Linux runs on two groups of machines -- those that are tested by the OEM
+to be compatible with Linux, and those that were never tested with Linux,
+but where Linux was installed to replace the original OS (Windows or OSX).
+
+The larger group is the systems tested to run only Windows.  Not only that,
+but many were tested to run with just one specific version of Windows.
+So even though the BIOS may use _OSI to query what version of Windows is running,
+only a single path through the BIOS has actually been tested.
+Experience shows that taking untested paths through the BIOS
+exposes Linux to an entire category of BIOS bugs.
+For this reason, Linux _OSI defaults must continue to claim compatibility
+with all versions of Windows.
+
+But Linux isn't actually compatible with Windows, and the Linux community
+has also been hurt with regressions when Linux adds the latest version of
+Windows to its list of _OSI strings.  So it is possible that additional strings
+will be more thoroughly vetted before shipping upstream in the future.
+But it is likely that they will all eventually be added.
+
+What should an OEM do if they want to support Linux and Windows
+using the same BIOS image?  Often they need to do something different
+for Linux to deal with how Linux is different from Windows.
+Here the BIOS should ask exactly what it wants to know:
+
+_OSI("Linux-OEM-my_interface_name")
+where 'OEM' is needed if this is an OEM-specific hook,
+and 'my_interface_name' describes the hook, which could be a
+quirk, a bug, or a bug-fix.
+
+In addition, the OEM should send a patch to upstream Linux
+via the linux-acpi@vger.kernel.org mailing list.  When that patch
+is checked into Linux, the OS will answer "YES" when the BIOS
+on the OEM's system uses _OSI to ask if the interface is supported
+by the OS.  Linux distributors can back-port that patch for Linux
+pre-installs, and it will be included by all distributions that
+re-base to upstream.  If the distribution can not update the kernel binary,
+they can also add an acpi_osi=Linux-OEM-my_interface_name
+cmdline parameter to the boot loader, as needed.
+
+If the string refers to a feature where the upstream kernel
+eventually grows support, a patch should be sent to remove
+the string when that support is added to the kernel.
+
+That was easy.  Read on, to find out how to do it wrong.
+
+Before _OSI, there was _OS
+--------------------------
+
+ACPI 1.0 specified "_OS" as an
+"object that evaluates to a string that identifies the operating system."
+
+The ACPI BIOS flow would include an evaluation of _OS, and the AML
+interpreter in the kernel would return to it a string identifying the OS:
+
+Windows 98, SE: "Microsoft Windows"
+Windows ME: "Microsoft WindowsME:Millenium Edition"
+Windows NT: "Microsoft Windows NT"
+
+The idea was on a platform tasked with running multiple OS's,
+the BIOS could use _OS to enable devices that an OS
+might support, or enable quirks or bug workarounds
+necessary to make the platform compatible with that pre-existing OS.
+
+But _OS had fundamental problems.  First, the BIOS needed to know the name
+of every possible version of the OS that would run on it, and needed to know
+all the quirks of those OS's.  Certainly it would make more sense
+for the BIOS to ask *specific* things of the OS, such
+"do you support a specific interface", and thus in ACPI 3.0,
+_OSI was born to replace _OS.
+
+_OS was abandoned, though even today, many BIOS look for
+_OS "Microsoft Windows NT", though it seems somewhat far-fetched
+that anybody would install those old operating systems
+over what came with the machine.
+
+Linux answers "Microsoft Windows NT" to please that BIOS idiom.
+That is the *only* viable strategy, as that is what modern Windows does,
+and so doing otherwise could steer the BIOS down an untested path.
+
+_OSI is born, and immediately misused
+--------------------------------------
+
+With _OSI, the *BIOS* provides the string describing an interface,
+and asks the OS: "YES/NO, are you compatible with this interface?"
+
+eg. _OSI("3.0 Thermal Model") would return TRUE if the OS knows how
+to deal with the thermal extensions made to the ACPI 3.0 specification.
+An old OS that doesn't know about those extensions would answer FALSE,
+and a new OS may be able to return TRUE.
+
+For an OS-specific interface, the ACPI spec said that the BIOS and the OS
+were to agree on a string of the form such as "Windows-interface_name".
+
+But two bad things happened.  First, the Windows ecosystem used _OSI
+not as designed, but as a direct replacement for _OS -- identifying
+the OS version, rather than an OS supported interface.  Indeed, right
+from the start, the ACPI 3.0 spec itself codified this misuse
+in example code using _OSI("Windows 2001").
+
+This misuse was adopted and continues today.
+
+Linux had no choice but to also return TRUE to _OSI("Windows 2001")
+and its successors.  To do otherwise would virtually guarantee breaking
+a BIOS that has been tested only with that _OSI returning TRUE.
+
+This strategy is problematic, as Linux is never completely compatible with
+the latest version of Windows, and sometimes it takes more than a year
+to iron out incompatibilities.
+
+Not to be out-done, the Linux community made things worse by returning TRUE
+to _OSI("Linux").  Doing so is even worse than the Windows misuse
+of _OSI, as "Linux" does not even contain any version information.
+_OSI("Linux") led to some BIOS' malfunctioning due to BIOS writer's
+using it in untested BIOS flows.  But some OEM's used _OSI("Linux")
+in tested flows to support real Linux features.  In 2009, Linux
+removed _OSI("Linux"), and added a cmdline parameter to restore it
+for legacy systems still needed it.  Further a BIOS_BUG warning prints
+for all BIOS's that invoke it.
+
+No BIOS should use _OSI("Linux").
+
+The result is a strategy for Linux to maximize compatibility with
+ACPI BIOS that are tested on Windows machines.  There is a real risk
+of over-stating that compatibility; but the alternative has often been
+catastrophic failure resulting from the BIOS taking paths that
+were never validated under *any* OS.
+
+Do not use _REV
+---------------
+
+Since _OSI("Linux") went away, some BIOS writers used _REV
+to support Linux and Windows differences in the same BIOS.
+
+_REV was defined in ACPI 1.0 to return the version of ACPI
+supported by the OS and the OS AML interpreter.
+
+Modern Windows returns _REV = 2.  Linux used ACPI_CA_SUPPORT_LEVEL,
+which would increment, based on the version of the spec supported.
+
+Unfortunately, _REV was also misused.  eg. some BIOS would check
+for _REV = 3, and do something for Linux, but when Linux returned
+_REV = 4, that support broke.
+
+In response to this problem, Linux returns _REV = 2 always,
+from mid-2015 onward.  The ACPI specification will also be updated
+to reflect that _REV is deprecated, and always returns 2.
+
+Apple Mac and _OSI("Darwin")
+----------------------------
+
+On Apple's Mac platforms, the ACPI BIOS invokes _OSI("Darwin")
+to determine if the machine is running Apple OSX.
+
+Like Linux's _OSI("*Windows*") strategy, Linux defaults to
+answering YES to _OSI("Darwin") to enable full access
+to the hardware and validated BIOS paths seen by OSX.
+Just like on Windows-tested platforms, this strategy has risks.
+
+Starting in Linux-3.18, the kernel answered YES to _OSI("Darwin")
+for the purpose of enabling Mac Thunderbolt support.  Further,
+if the kernel noticed _OSI("Darwin") being invoked, it additionally
+disabled all _OSI("*Windows*") to keep poorly written Mac BIOS
+from going down untested combinations of paths.
+
+The Linux-3.18 change in default caused power regressions on Mac
+laptops, and the 3.18 implementation did not allow changing
+the default via cmdline "acpi_osi=!Darwin".  Linux-4.7 fixed
+the ability to use acpi_osi=!Darwin as a workaround, and
+we hope to see Mac Thunderbolt power management support in Linux-4.11.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/acpi/video_extension.txt linux-libre-4.10-rc8-gnu/Documentation/acpi/video_extension.txt
--- linux-libre-4.9-gnu/Documentation/acpi/video_extension.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/acpi/video_extension.txt	2017-02-12 16:03:20.000000000 -0500
@@ -101,6 +101,6 @@ received a notification, it will set the
 not affect the sending of event to user space, they are always sent to user
 space regardless of whether or not the video module controls the backlight level
 directly. This behaviour can be controlled through the brightness_switch_enabled
-module parameter as documented in kernel-parameters.txt. It is recommended to
+module parameter as documented in admin-guide/kernel-parameters.rst. It is recommended to
 disable this behaviour once a GUI environment starts up and wants to have full
 control of the backlight level.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/adding-syscalls.txt linux-libre-4.10-rc8-gnu/Documentation/adding-syscalls.txt
--- linux-libre-4.9-gnu/Documentation/adding-syscalls.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/adding-syscalls.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,527 +0,0 @@
-Adding a New System Call
-========================
-
-This document describes what's involved in adding a new system call to the
-Linux kernel, over and above the normal submission advice in
-Documentation/SubmittingPatches.
-
-
-System Call Alternatives
-------------------------
-
-The first thing to consider when adding a new system call is whether one of
-the alternatives might be suitable instead.  Although system calls are the
-most traditional and most obvious interaction points between userspace and the
-kernel, there are other possibilities -- choose what fits best for your
-interface.
-
- - If the operations involved can be made to look like a filesystem-like
-   object, it may make more sense to create a new filesystem or device.  This
-   also makes it easier to encapsulate the new functionality in a kernel module
-   rather than requiring it to be built into the main kernel.
-     - If the new functionality involves operations where the kernel notifies
-       userspace that something has happened, then returning a new file
-       descriptor for the relevant object allows userspace to use
-       poll/select/epoll to receive that notification.
-     - However, operations that don't map to read(2)/write(2)-like operations
-       have to be implemented as ioctl(2) requests, which can lead to a
-       somewhat opaque API.
- - If you're just exposing runtime system information, a new node in sysfs
-   (see Documentation/filesystems/sysfs.txt) or the /proc filesystem may be
-   more appropriate.  However, access to these mechanisms requires that the
-   relevant filesystem is mounted, which might not always be the case (e.g.
-   in a namespaced/sandboxed/chrooted environment).  Avoid adding any API to
-   debugfs, as this is not considered a 'production' interface to userspace.
- - If the operation is specific to a particular file or file descriptor, then
-   an additional fcntl(2) command option may be more appropriate.  However,
-   fcntl(2) is a multiplexing system call that hides a lot of complexity, so
-   this option is best for when the new function is closely analogous to
-   existing fcntl(2) functionality, or the new functionality is very simple
-   (for example, getting/setting a simple flag related to a file descriptor).
- - If the operation is specific to a particular task or process, then an
-   additional prctl(2) command option may be more appropriate.  As with
-   fcntl(2), this system call is a complicated multiplexor so is best reserved
-   for near-analogs of existing prctl() commands or getting/setting a simple
-   flag related to a process.
-
-
-Designing the API: Planning for Extension
------------------------------------------
-
-A new system call forms part of the API of the kernel, and has to be supported
-indefinitely.  As such, it's a very good idea to explicitly discuss the
-interface on the kernel mailing list, and it's important to plan for future
-extensions of the interface.
-
-(The syscall table is littered with historical examples where this wasn't done,
-together with the corresponding follow-up system calls -- eventfd/eventfd2,
-dup2/dup3, inotify_init/inotify_init1,  pipe/pipe2, renameat/renameat2 -- so
-learn from the history of the kernel and plan for extensions from the start.)
-
-For simpler system calls that only take a couple of arguments, the preferred
-way to allow for future extensibility is to include a flags argument to the
-system call.  To make sure that userspace programs can safely use flags
-between kernel versions, check whether the flags value holds any unknown
-flags, and reject the system call (with EINVAL) if it does:
-
-    if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
-        return -EINVAL;
-
-(If no flags values are used yet, check that the flags argument is zero.)
-
-For more sophisticated system calls that involve a larger number of arguments,
-it's preferred to encapsulate the majority of the arguments into a structure
-that is passed in by pointer.  Such a structure can cope with future extension
-by including a size argument in the structure:
-
-    struct xyzzy_params {
-        u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */
-        u32 param_1;
-        u64 param_2;
-        u64 param_3;
-    };
-
-As long as any subsequently added field, say param_4, is designed so that a
-zero value gives the previous behaviour, then this allows both directions of
-version mismatch:
-
- - To cope with a later userspace program calling an older kernel, the kernel
-   code should check that any memory beyond the size of the structure that it
-   expects is zero (effectively checking that param_4 == 0).
- - To cope with an older userspace program calling a newer kernel, the kernel
-   code can zero-extend a smaller instance of the structure (effectively
-   setting param_4 = 0).
-
-See perf_event_open(2) and the perf_copy_attr() function (in
-kernel/events/core.c) for an example of this approach.
-
-
-Designing the API: Other Considerations
----------------------------------------
-
-If your new system call allows userspace to refer to a kernel object, it
-should use a file descriptor as the handle for that object -- don't invent a
-new type of userspace object handle when the kernel already has mechanisms and
-well-defined semantics for using file descriptors.
-
-If your new xyzzy(2) system call does return a new file descriptor, then the
-flags argument should include a value that is equivalent to setting O_CLOEXEC
-on the new FD.  This makes it possible for userspace to close the timing
-window between xyzzy() and calling fcntl(fd, F_SETFD, FD_CLOEXEC), where an
-unexpected fork() and execve() in another thread could leak a descriptor to
-the exec'ed program. (However, resist the temptation to re-use the actual value
-of the O_CLOEXEC constant, as it is architecture-specific and is part of a
-numbering space of O_* flags that is fairly full.)
-
-If your system call returns a new file descriptor, you should also consider
-what it means to use the poll(2) family of system calls on that file
-descriptor. Making a file descriptor ready for reading or writing is the
-normal way for the kernel to indicate to userspace that an event has
-occurred on the corresponding kernel object.
-
-If your new xyzzy(2) system call involves a filename argument:
-
-    int sys_xyzzy(const char __user *path, ..., unsigned int flags);
-
-you should also consider whether an xyzzyat(2) version is more appropriate:
-
-    int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);
-
-This allows more flexibility for how userspace specifies the file in question;
-in particular it allows userspace to request the functionality for an
-already-opened file descriptor using the AT_EMPTY_PATH flag, effectively giving
-an fxyzzy(3) operation for free:
-
- - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...)
- - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...)
-
-(For more details on the rationale of the *at() calls, see the openat(2) man
-page; for an example of AT_EMPTY_PATH, see the fstatat(2) man page.)
-
-If your new xyzzy(2) system call involves a parameter describing an offset
-within a file, make its type loff_t so that 64-bit offsets can be supported
-even on 32-bit architectures.
-
-If your new xyzzy(2) system call involves privileged functionality, it needs
-to be governed by the appropriate Linux capability bit (checked with a call to
-capable()), as described in the capabilities(7) man page.  Choose an existing
-capability bit that governs related functionality, but try to avoid combining
-lots of only vaguely related functions together under the same bit, as this
-goes against capabilities' purpose of splitting the power of root.  In
-particular, avoid adding new uses of the already overly-general CAP_SYS_ADMIN
-capability.
-
-If your new xyzzy(2) system call manipulates a process other than the calling
-process, it should be restricted (using a call to ptrace_may_access()) so that
-only a calling process with the same permissions as the target process, or
-with the necessary capabilities, can manipulate the target process.
-
-Finally, be aware that some non-x86 architectures have an easier time if
-system call parameters that are explicitly 64-bit fall on odd-numbered
-arguments (i.e. parameter 1, 3, 5), to allow use of contiguous pairs of 32-bit
-registers.  (This concern does not apply if the arguments are part of a
-structure that's passed in by pointer.)
-
-
-Proposing the API
------------------
-
-To make new system calls easy to review, it's best to divide up the patchset
-into separate chunks.  These should include at least the following items as
-distinct commits (each of which is described further below):
-
- - The core implementation of the system call, together with prototypes,
-   generic numbering, Kconfig changes and fallback stub implementation.
- - Wiring up of the new system call for one particular architecture, usually
-   x86 (including all of x86_64, x86_32 and x32).
- - A demonstration of the use of the new system call in userspace via a
-   selftest in tools/testing/selftests/.
- - A draft man-page for the new system call, either as plain text in the
-   cover letter, or as a patch to the (separate) man-pages repository.
-
-New system call proposals, like any change to the kernel's API, should always
-be cc'ed to linux-api@vger.kernel.org.
-
-
-Generic System Call Implementation
-----------------------------------
-
-The main entry point for your new xyzzy(2) system call will be called
-sys_xyzzy(), but you add this entry point with the appropriate
-SYSCALL_DEFINEn() macro rather than explicitly.  The 'n' indicates the number
-of arguments to the system call, and the macro takes the system call name
-followed by the (type, name) pairs for the parameters as arguments.  Using
-this macro allows metadata about the new system call to be made available for
-other tools.
-
-The new entry point also needs a corresponding function prototype, in
-include/linux/syscalls.h, marked as asmlinkage to match the way that system
-calls are invoked:
-
-    asmlinkage long sys_xyzzy(...);
-
-Some architectures (e.g. x86) have their own architecture-specific syscall
-tables, but several other architectures share a generic syscall table. Add your
-new system call to the generic list by adding an entry to the list in
-include/uapi/asm-generic/unistd.h:
-
-    #define __NR_xyzzy 292
-    __SYSCALL(__NR_xyzzy, sys_xyzzy)
-
-Also update the __NR_syscalls count to reflect the additional system call, and
-note that if multiple new system calls are added in the same merge window,
-your new syscall number may get adjusted to resolve conflicts.
-
-The file kernel/sys_ni.c provides a fallback stub implementation of each system
-call, returning -ENOSYS.  Add your new system call here too:
-
-    cond_syscall(sys_xyzzy);
-
-Your new kernel functionality, and the system call that controls it, should
-normally be optional, so add a CONFIG option (typically to init/Kconfig) for
-it. As usual for new CONFIG options:
-
- - Include a description of the new functionality and system call controlled
-   by the option.
- - Make the option depend on EXPERT if it should be hidden from normal users.
- - Make any new source files implementing the function dependent on the CONFIG
-   option in the Makefile (e.g. "obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.c").
- - Double check that the kernel still builds with the new CONFIG option turned
-   off.
-
-To summarize, you need a commit that includes:
-
- - CONFIG option for the new function, normally in init/Kconfig
- - SYSCALL_DEFINEn(xyzzy, ...) for the entry point
- - corresponding prototype in include/linux/syscalls.h
- - generic table entry in include/uapi/asm-generic/unistd.h
- - fallback stub in kernel/sys_ni.c
-
-
-x86 System Call Implementation
-------------------------------
-
-To wire up your new system call for x86 platforms, you need to update the
-master syscall tables.  Assuming your new system call isn't special in some
-way (see below), this involves a "common" entry (for x86_64 and x32) in
-arch/x86/entry/syscalls/syscall_64.tbl:
-
-    333   common   xyzzy     sys_xyzzy
-
-and an "i386" entry in arch/x86/entry/syscalls/syscall_32.tbl:
-
-    380   i386     xyzzy     sys_xyzzy
-
-Again, these numbers are liable to be changed if there are conflicts in the
-relevant merge window.
-
-
-Compatibility System Calls (Generic)
-------------------------------------
-
-For most system calls the same 64-bit implementation can be invoked even when
-the userspace program is itself 32-bit; even if the system call's parameters
-include an explicit pointer, this is handled transparently.
-
-However, there are a couple of situations where a compatibility layer is
-needed to cope with size differences between 32-bit and 64-bit.
-
-The first is if the 64-bit kernel also supports 32-bit userspace programs, and
-so needs to parse areas of (__user) memory that could hold either 32-bit or
-64-bit values.  In particular, this is needed whenever a system call argument
-is:
-
- - a pointer to a pointer
- - a pointer to a struct containing a pointer (e.g. struct iovec __user *)
- - a pointer to a varying sized integral type (time_t, off_t, long, ...)
- - a pointer to a struct containing a varying sized integral type.
-
-The second situation that requires a compatibility layer is if one of the
-system call's arguments has a type that is explicitly 64-bit even on a 32-bit
-architecture, for example loff_t or __u64.  In this case, a value that arrives
-at a 64-bit kernel from a 32-bit application will be split into two 32-bit
-values, which then need to be re-assembled in the compatibility layer.
-
-(Note that a system call argument that's a pointer to an explicit 64-bit type
-does *not* need a compatibility layer; for example, splice(2)'s arguments of
-type loff_t __user * do not trigger the need for a compat_ system call.)
-
-The compatibility version of the system call is called compat_sys_xyzzy(), and
-is added with the COMPAT_SYSCALL_DEFINEn() macro, analogously to
-SYSCALL_DEFINEn.  This version of the implementation runs as part of a 64-bit
-kernel, but expects to receive 32-bit parameter values and does whatever is
-needed to deal with them.  (Typically, the compat_sys_ version converts the
-values to 64-bit versions and either calls on to the sys_ version, or both of
-them call a common inner implementation function.)
-
-The compat entry point also needs a corresponding function prototype, in
-include/linux/compat.h, marked as asmlinkage to match the way that system
-calls are invoked:
-
-    asmlinkage long compat_sys_xyzzy(...);
-
-If the system call involves a structure that is laid out differently on 32-bit
-and 64-bit systems, say struct xyzzy_args, then the include/linux/compat.h
-header file should also include a compat version of the structure (struct
-compat_xyzzy_args) where each variable-size field has the appropriate compat_
-type that corresponds to the type in struct xyzzy_args.  The
-compat_sys_xyzzy() routine can then use this compat_ structure to parse the
-arguments from a 32-bit invocation.
-
-For example, if there are fields:
-
-    struct xyzzy_args {
-        const char __user *ptr;
-        __kernel_long_t varying_val;
-        u64 fixed_val;
-        /* ... */
-    };
-
-in struct xyzzy_args, then struct compat_xyzzy_args would have:
-
-    struct compat_xyzzy_args {
-        compat_uptr_t ptr;
-        compat_long_t varying_val;
-        u64 fixed_val;
-        /* ... */
-    };
-
-The generic system call list also needs adjusting to allow for the compat
-version; the entry in include/uapi/asm-generic/unistd.h should use
-__SC_COMP rather than __SYSCALL:
-
-    #define __NR_xyzzy 292
-    __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)
-
-To summarize, you need:
-
- - a COMPAT_SYSCALL_DEFINEn(xyzzy, ...) for the compat entry point
- - corresponding prototype in include/linux/compat.h
- - (if needed) 32-bit mapping struct in include/linux/compat.h
- - instance of __SC_COMP not __SYSCALL in include/uapi/asm-generic/unistd.h
-
-
-Compatibility System Calls (x86)
---------------------------------
-
-To wire up the x86 architecture of a system call with a compatibility version,
-the entries in the syscall tables need to be adjusted.
-
-First, the entry in arch/x86/entry/syscalls/syscall_32.tbl gets an extra
-column to indicate that a 32-bit userspace program running on a 64-bit kernel
-should hit the compat entry point:
-
-    380   i386     xyzzy     sys_xyzzy    compat_sys_xyzzy
-
-Second, you need to figure out what should happen for the x32 ABI version of
-the new system call.  There's a choice here: the layout of the arguments
-should either match the 64-bit version or the 32-bit version.
-
-If there's a pointer-to-a-pointer involved, the decision is easy: x32 is
-ILP32, so the layout should match the 32-bit version, and the entry in
-arch/x86/entry/syscalls/syscall_64.tbl is split so that x32 programs hit the
-compatibility wrapper:
-
-    333   64       xyzzy     sys_xyzzy
-    ...
-    555   x32      xyzzy     compat_sys_xyzzy
-
-If no pointers are involved, then it is preferable to re-use the 64-bit system
-call for the x32 ABI (and consequently the entry in
-arch/x86/entry/syscalls/syscall_64.tbl is unchanged).
-
-In either case, you should check that the types involved in your argument
-layout do indeed map exactly from x32 (-mx32) to either the 32-bit (-m32) or
-64-bit (-m64) equivalents.
-
-
-System Calls Returning Elsewhere
---------------------------------
-
-For most system calls, once the system call is complete the user program
-continues exactly where it left off -- at the next instruction, with the
-stack the same and most of the registers the same as before the system call,
-and with the same virtual memory space.
-
-However, a few system calls do things differently.  They might return to a
-different location (rt_sigreturn) or change the memory space (fork/vfork/clone)
-or even architecture (execve/execveat) of the program.
-
-To allow for this, the kernel implementation of the system call may need to
-save and restore additional registers to the kernel stack, allowing complete
-control of where and how execution continues after the system call.
-
-This is arch-specific, but typically involves defining assembly entry points
-that save/restore additional registers and invoke the real system call entry
-point.
-
-For x86_64, this is implemented as a stub_xyzzy entry point in
-arch/x86/entry/entry_64.S, and the entry in the syscall table
-(arch/x86/entry/syscalls/syscall_64.tbl) is adjusted to match:
-
-    333   common   xyzzy     stub_xyzzy
-
-The equivalent for 32-bit programs running on a 64-bit kernel is normally
-called stub32_xyzzy and implemented in arch/x86/entry/entry_64_compat.S,
-with the corresponding syscall table adjustment in
-arch/x86/entry/syscalls/syscall_32.tbl:
-
-    380   i386     xyzzy     sys_xyzzy    stub32_xyzzy
-
-If the system call needs a compatibility layer (as in the previous section)
-then the stub32_ version needs to call on to the compat_sys_ version of the
-system call rather than the native 64-bit version.  Also, if the x32 ABI
-implementation is not common with the x86_64 version, then its syscall
-table will also need to invoke a stub that calls on to the compat_sys_
-version.
-
-For completeness, it's also nice to set up a mapping so that user-mode Linux
-still works -- its syscall table will reference stub_xyzzy, but the UML build
-doesn't include arch/x86/entry/entry_64.S implementation (because UML
-simulates registers etc).  Fixing this is as simple as adding a #define to
-arch/x86/um/sys_call_table_64.c:
-
-    #define stub_xyzzy sys_xyzzy
-
-
-Other Details
--------------
-
-Most of the kernel treats system calls in a generic way, but there is the
-occasional exception that may need updating for your particular system call.
-
-The audit subsystem is one such special case; it includes (arch-specific)
-functions that classify some special types of system call -- specifically
-file open (open/openat), program execution (execve/exeveat) or socket
-multiplexor (socketcall) operations. If your new system call is analogous to
-one of these, then the audit system should be updated.
-
-More generally, if there is an existing system call that is analogous to your
-new system call, it's worth doing a kernel-wide grep for the existing system
-call to check there are no other special cases.
-
-
-Testing
--------
-
-A new system call should obviously be tested; it is also useful to provide
-reviewers with a demonstration of how user space programs will use the system
-call.  A good way to combine these aims is to include a simple self-test
-program in a new directory under tools/testing/selftests/.
-
-For a new system call, there will obviously be no libc wrapper function and so
-the test will need to invoke it using syscall(); also, if the system call
-involves a new userspace-visible structure, the corresponding header will need
-to be installed to compile the test.
-
-Make sure the selftest runs successfully on all supported architectures.  For
-example, check that it works when compiled as an x86_64 (-m64), x86_32 (-m32)
-and x32 (-mx32) ABI program.
-
-For more extensive and thorough testing of new functionality, you should also
-consider adding tests to the Linux Test Project, or to the xfstests project
-for filesystem-related changes.
- - https://linux-test-project.github.io/
- - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git
-
-
-Man Page
---------
-
-All new system calls should come with a complete man page, ideally using groff
-markup, but plain text will do.  If groff is used, it's helpful to include a
-pre-rendered ASCII version of the man page in the cover email for the
-patchset, for the convenience of reviewers.
-
-The man page should be cc'ed to linux-man@vger.kernel.org
-For more details, see https://www.kernel.org/doc/man-pages/patches.html
-
-References and Sources
-----------------------
-
- - LWN article from Michael Kerrisk on use of flags argument in system calls:
-   https://lwn.net/Articles/585415/
- - LWN article from Michael Kerrisk on how to handle unknown flags in a system
-   call: https://lwn.net/Articles/588444/
- - LWN article from Jake Edge describing constraints on 64-bit system call
-   arguments: https://lwn.net/Articles/311630/
- - Pair of LWN articles from David Drysdale that describe the system call
-   implementation paths in detail for v3.14:
-    - https://lwn.net/Articles/604287/
-    - https://lwn.net/Articles/604515/
- - Architecture-specific requirements for system calls are discussed in the
-   syscall(2) man-page:
-   http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
- - Collated emails from Linus Torvalds discussing the problems with ioctl():
-   http://yarchive.net/comp/linux/ioctl.html
- - "How to not invent kernel interfaces", Arnd Bergmann,
-   http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
- - LWN article from Michael Kerrisk on avoiding new uses of CAP_SYS_ADMIN:
-   https://lwn.net/Articles/486306/
- - Recommendation from Andrew Morton that all related information for a new
-   system call should come in the same email thread:
-   https://lkml.org/lkml/2014/7/24/641
- - Recommendation from Michael Kerrisk that a new system call should come with
-   a man page: https://lkml.org/lkml/2014/6/13/309
- - Suggestion from Thomas Gleixner that x86 wire-up should be in a separate
-   commit: https://lkml.org/lkml/2014/11/19/254
- - Suggestion from Greg Kroah-Hartman that it's good for new system calls to
-   come with a man-page & selftest: https://lkml.org/lkml/2014/3/19/710
- - Discussion from Michael Kerrisk of new system call vs. prctl(2) extension:
-   https://lkml.org/lkml/2014/6/3/411
- - Suggestion from Ingo Molnar that system calls that involve multiple
-   arguments should encapsulate those arguments in a struct, which includes a
-   size field for future extensibility: https://lkml.org/lkml/2015/7/30/117
- - Numbering oddities arising from (re-)use of O_* numbering space flags:
-    - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
-      check")
-    - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
-      conflict")
-    - commit bb458c644a59 ("Safer ABI for O_TMPFILE")
- - Discussion from Matthew Wilcox about restrictions on 64-bit arguments:
-   https://lkml.org/lkml/2008/12/12/187
- - Recommendation from Greg Kroah-Hartman that unknown flags should be
-   policed: https://lkml.org/lkml/2014/7/17/577
- - Recommendation from Linus Torvalds that x32 system calls should prefer
-   compatibility with 64-bit versions rather than 32-bit versions:
-   https://lkml.org/lkml/2011/8/31/244
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/binfmt-misc.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/binfmt-misc.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/binfmt-misc.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/binfmt-misc.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,151 @@
+Kernel Support for miscellaneous (your favourite) Binary Formats v1.1
+=====================================================================
+
+This Kernel feature allows you to invoke almost (for restrictions see below)
+every program by simply typing its name in the shell.
+This includes for example compiled Java(TM), Python or Emacs programs.
+
+To achieve this you must tell binfmt_misc which interpreter has to be invoked
+with which binary. Binfmt_misc recognises the binary-type by matching some bytes
+at the beginning of the file with a magic byte sequence (masking out specified
+bits) you have supplied. Binfmt_misc can also recognise a filename extension
+aka ``.com`` or ``.exe``.
+
+First you must mount binfmt_misc::
+
+	mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
+
+To actually register a new binary type, you have to set up a string looking like
+``:name:type:offset:magic:mask:interpreter:flags`` (where you can choose the
+``:`` upon your needs) and echo it to ``/proc/sys/fs/binfmt_misc/register``.
+
+Here is what the fields mean:
+
+- ``name``
+   is an identifier string. A new /proc file will be created with this
+   ``name below /proc/sys/fs/binfmt_misc``; cannot contain slashes ``/`` for
+   obvious reasons.
+- ``type``
+   is the type of recognition. Give ``M`` for magic and ``E`` for extension.
+- ``offset``
+   is the offset of the magic/mask in the file, counted in bytes. This
+   defaults to 0 if you omit it (i.e. you write ``:name:type::magic...``).
+   Ignored when using filename extension matching.
+- ``magic``
+   is the byte sequence binfmt_misc is matching for. The magic string
+   may contain hex-encoded characters like ``\x0a`` or ``\xA4``. Note that you
+   must escape any NUL bytes; parsing halts at the first one. In a shell
+   environment you might have to write ``\\x0a`` to prevent the shell from
+   eating your ``\``.
+   If you chose filename extension matching, this is the extension to be
+   recognised (without the ``.``, the ``\x0a`` specials are not allowed).
+   Extension    matching is case sensitive, and slashes ``/`` are not allowed!
+- ``mask``
+   is an (optional, defaults to all 0xff) mask. You can mask out some
+   bits from matching by supplying a string like magic and as long as magic.
+   The mask is anded with the byte sequence of the file. Note that you must
+   escape any NUL bytes; parsing halts at the first one. Ignored when using
+   filename extension matching.
+- ``interpreter``
+   is the program that should be invoked with the binary as first
+   argument (specify the full path)
+- ``flags``
+   is an optional field that controls several aspects of the invocation
+   of the interpreter. It is a string of capital letters, each controls a
+   certain aspect. The following flags are supported:
+
+      ``P`` - preserve-argv[0]
+            Legacy behavior of binfmt_misc is to overwrite
+            the original argv[0] with the full path to the binary. When this
+            flag is included, binfmt_misc will add an argument to the argument
+            vector for this purpose, thus preserving the original ``argv[0]``.
+            e.g. If your interp is set to ``/bin/foo`` and you run ``blah``
+            (which is in ``/usr/local/bin``), then the kernel will execute
+            ``/bin/foo`` with ``argv[]`` set to ``["/bin/foo", "/usr/local/bin/blah", "blah"]``.  The interp has to be aware of this so it can
+            execute ``/usr/local/bin/blah``
+            with ``argv[]`` set to ``["blah"]``.
+      ``O`` - open-binary
+	    Legacy behavior of binfmt_misc is to pass the full path
+            of the binary to the interpreter as an argument. When this flag is
+            included, binfmt_misc will open the file for reading and pass its
+            descriptor as an argument, instead of the full path, thus allowing
+            the interpreter to execute non-readable binaries. This feature
+            should be used with care - the interpreter has to be trusted not to
+            emit the contents of the non-readable binary.
+      ``C`` - credentials
+            Currently, the behavior of binfmt_misc is to calculate
+            the credentials and security token of the new process according to
+            the interpreter. When this flag is included, these attributes are
+            calculated according to the binary. It also implies the ``O`` flag.
+            This feature should be used with care as the interpreter
+            will run with root permissions when a setuid binary owned by root
+            is run with binfmt_misc.
+      ``F`` - fix binary
+            The usual behaviour of binfmt_misc is to spawn the
+	    binary lazily when the misc format file is invoked.  However,
+	    this doesn``t work very well in the face of mount namespaces and
+	    changeroots, so the ``F`` mode opens the binary as soon as the
+	    emulation is installed and uses the opened image to spawn the
+	    emulator, meaning it is always available once installed,
+	    regardless of how the environment changes.
+
+
+There are some restrictions:
+
+ - the whole register string may not exceed 1920 characters
+ - the magic must reside in the first 128 bytes of the file, i.e.
+   offset+size(magic) has to be less than 128
+ - the interpreter string may not exceed 127 characters
+
+To use binfmt_misc you have to mount it first. You can mount it with
+``mount -t binfmt_misc none /proc/sys/fs/binfmt_misc`` command, or you can add
+a line ``none  /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0`` to your
+``/etc/fstab`` so it auto mounts on boot.
+
+You may want to add the binary formats in one of your ``/etc/rc`` scripts during
+boot-up. Read the manual of your init program to figure out how to do this
+right.
+
+Think about the order of adding entries! Later added entries are matched first!
+
+
+A few examples (assumed you are in ``/proc/sys/fs/binfmt_misc``):
+
+- enable support for em86 (like binfmt_em86, for Alpha AXP only)::
+
+    echo ':i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
+    echo ':i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
+
+- enable support for packed DOS applications (pre-configured dosemu hdimages)::
+
+    echo ':DEXE:M::\x0eDEX::/usr/bin/dosexec:' > register
+
+- enable support for Windows executables using wine::
+
+    echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > register
+
+For java support see Documentation/admin-guide/java.rst
+
+
+You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable)
+or 1 (to enable) to ``/proc/sys/fs/binfmt_misc/status`` or
+``/proc/.../the_name``.
+Catting the file tells you the current status of ``binfmt_misc/the_entry``.
+
+You can remove one entry or all entries by echoing -1 to ``/proc/.../the_name``
+or ``/proc/sys/fs/binfmt_misc/status``.
+
+
+Hints
+-----
+
+If you want to pass special arguments to your interpreter, you can
+write a wrapper script for it. See Documentation/admin-guide/java.rst for an
+example.
+
+Your interpreter should NOT look in the PATH for the filename; the kernel
+passes it the full filename (or the file descriptor) to use.  Using ``$PATH`` can
+cause unexpected behaviour and can be a security hazard.
+
+
+Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/braille-console.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/braille-console.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/braille-console.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/braille-console.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+Linux Braille Console
+=====================
+
+To get early boot messages on a braille device (before userspace screen
+readers can start), you first need to compile the support for the usual serial
+console (see :ref:`Documentation/admin-guide/serial-console.rst <serial_console>`), and
+for braille device
+(in :menuselection:`Device Drivers --> Accessibility support --> Console on braille device`).
+
+Then you need to specify a ``console=brl``, option on the kernel command line, the
+format is::
+
+	console=brl,serial_options...
+
+where ``serial_options...`` are the same as described in
+:ref:`Documentation/admin-guide/serial-console.rst <serial_console>`.
+
+So for instance you can use ``console=brl,ttyS0`` if the braille device is connected to the first serial port, and ``console=brl,ttyS0,115200`` to
+override the baud rate to 115200, etc.
+
+By default, the braille device will just show the last kernel message (console
+mode).  To review previous messages, press the Insert key to switch to the VT
+review mode.  In review mode, the arrow keys permit to browse in the VT content,
+:kbd:`PAGE-UP`/:kbd:`PAGE-DOWN` keys go at the top/bottom of the screen, and
+the :kbd:`HOME` key goes back
+to the cursor, hence providing very basic screen reviewing facility.
+
+Sound feedback can be obtained by adding the ``braille_console.sound=1`` kernel
+parameter.
+
+For simplicity, only one braille console can be enabled, other uses of
+``console=brl,...`` will be discarded.  Also note that it does not interfere with
+the console selection mechanism described in
+:ref:`Documentation/admin-guide/serial-console.rst <serial_console>`.
+
+For now, only the VisioBraille device is supported.
+
+Samuel Thibault <samuel.thibault@ens-lyon.org>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/bug-bisect.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/bug-bisect.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/bug-bisect.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/bug-bisect.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,76 @@
+Bisecting a bug
++++++++++++++++
+
+Last updated: 28 October 2016
+
+Introduction
+============
+
+Always try the latest kernel from kernel.org and build from source. If you are
+not confident in doing that please report the bug to your distribution vendor
+instead of to a kernel developer.
+
+Finding bugs is not always easy. Have a go though. If you can't find it don't
+give up. Report as much as you have found to the relevant maintainer. See
+MAINTAINERS for who that is for the subsystem you have worked on.
+
+Before you submit a bug report read
+:ref:`Documentation/admin-guide/reporting-bugs.rst <reportingbugs>`.
+
+Devices not appearing
+=====================
+
+Often this is caused by udev/systemd. Check that first before blaming it
+on the kernel.
+
+Finding patch that caused a bug
+===============================
+
+Using the provided tools with ``git`` makes finding bugs easy provided the bug
+is reproducible.
+
+Steps to do it:
+
+- build the Kernel from its git source
+- start bisect with [#f1]_::
+
+	$ git bisect start
+
+- mark the broken changeset with::
+
+	$ git bisect bad [commit]
+
+- mark a changeset where the code is known to work with::
+
+	$ git bisect good [commit]
+
+- rebuild the Kernel and test
+- interact with git bisect by using either::
+
+	$ git bisect good
+
+  or::
+
+	$ git bisect bad
+
+  depending if the bug happened on the changeset you're testing
+- After some interactions, git bisect will give you the changeset that
+  likely caused the bug.
+
+- For example, if you know that the current version is bad, and version
+  4.8 is good, you could do::
+
+           $ git bisect start
+           $ git bisect bad                 # Current version is bad
+           $ git bisect good v4.8
+
+
+.. [#f1] You can, optionally, provide both good and bad arguments at git
+	 start with ``git bisect start [BAD] [GOOD]``
+
+For further references, please read:
+
+- The man page for ``git-bisect``
+- `Fighting regressions with git bisect <https://www.kernel.org/pub/software/scm/git/docs/git-bisect-lk2009.html>`_
+- `Fully automated bisecting with "git bisect run" <https://lwn.net/Articles/317154>`_
+- `Using Git bisect to figure out when brokenness was introduced <http://webchick.net/node/99>`_
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/bug-hunting.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/bug-hunting.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/bug-hunting.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/bug-hunting.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,369 @@
+Bug hunting
+===========
+
+Kernel bug reports often come with a stack dump like the one below::
+
+	------------[ cut here ]------------
+	WARNING: CPU: 1 PID: 28102 at kernel/module.c:1108 module_put+0x57/0x70
+	Modules linked in: dvb_usb_gp8psk(-) dvb_usb dvb_core nvidia_drm(PO) nvidia_modeset(PO) snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd soundcore nvidia(PO) [last unloaded: rc_core]
+	CPU: 1 PID: 28102 Comm: rmmod Tainted: P        WC O 4.8.4-build.1 #1
+	Hardware name: MSI MS-7309/MS-7309, BIOS V1.12 02/23/2009
+	 00000000 c12ba080 00000000 00000000 c103ed6a c1616014 00000001 00006dc6
+	 c1615862 00000454 c109e8a7 c109e8a7 00000009 ffffffff 00000000 f13f6a10
+	 f5f5a600 c103ee33 00000009 00000000 00000000 c109e8a7 f80ca4d0 c109f617
+	Call Trace:
+	 [<c12ba080>] ? dump_stack+0x44/0x64
+	 [<c103ed6a>] ? __warn+0xfa/0x120
+	 [<c109e8a7>] ? module_put+0x57/0x70
+	 [<c109e8a7>] ? module_put+0x57/0x70
+	 [<c103ee33>] ? warn_slowpath_null+0x23/0x30
+	 [<c109e8a7>] ? module_put+0x57/0x70
+	 [<f80ca4d0>] ? gp8psk_fe_set_frontend+0x460/0x460 [dvb_usb_gp8psk]
+	 [<c109f617>] ? symbol_put_addr+0x27/0x50
+	 [<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
+	 [<f80bb3bf>] ? dvb_usb_exit+0x2f/0xd0 [dvb_usb]
+	 [<c13d03bc>] ? usb_disable_endpoint+0x7c/0xb0
+	 [<f80bb48a>] ? dvb_usb_device_exit+0x2a/0x50 [dvb_usb]
+	 [<c13d2882>] ? usb_unbind_interface+0x62/0x250
+	 [<c136b514>] ? __pm_runtime_idle+0x44/0x70
+	 [<c13620d8>] ? __device_release_driver+0x78/0x120
+	 [<c1362907>] ? driver_detach+0x87/0x90
+	 [<c1361c48>] ? bus_remove_driver+0x38/0x90
+	 [<c13d1c18>] ? usb_deregister+0x58/0xb0
+	 [<c109fbb0>] ? SyS_delete_module+0x130/0x1f0
+	 [<c1055654>] ? task_work_run+0x64/0x80
+	 [<c1000fa5>] ? exit_to_usermode_loop+0x85/0x90
+	 [<c10013f0>] ? do_fast_syscall_32+0x80/0x130
+	 [<c1549f43>] ? sysenter_past_esp+0x40/0x6a
+	---[ end trace 6ebc60ef3981792f ]---
+
+Such stack traces provide enough information to identify the line inside the
+Kernel's source code where the bug happened. Depending on the severity of
+the issue, it may also contain the word **Oops**, as on this one::
+
+	BUG: unable to handle kernel NULL pointer dereference at   (null)
+	IP: [<c06969d4>] iret_exc+0x7d0/0xa59
+	*pdpt = 000000002258a001 *pde = 0000000000000000
+	Oops: 0002 [#1] PREEMPT SMP
+	...
+
+Despite being an **Oops** or some other sort of stack trace, the offended
+line is usually required to identify and handle the bug. Along this chapter,
+we'll refer to "Oops" for all kinds of stack traces that need to be analized.
+
+.. note::
+
+  ``ksymoops`` is useless on 2.6 or upper.  Please use the Oops in its original
+  format (from ``dmesg``, etc).  Ignore any references in this or other docs to
+  "decoding the Oops" or "running it through ksymoops".
+  If you post an Oops from 2.6+ that has been run through ``ksymoops``,
+  people will just tell you to repost it.
+
+Where is the Oops message is located?
+-------------------------------------
+
+Normally the Oops text is read from the kernel buffers by klogd and
+handed to ``syslogd`` which writes it to a syslog file, typically
+``/var/log/messages`` (depends on ``/etc/syslog.conf``). On systems with
+systemd, it may also be stored by the ``journald`` daemon, and accessed
+by running ``journalctl`` command.
+
+Sometimes ``klogd`` dies, in which case you can run ``dmesg > file`` to
+read the data from the kernel buffers and save it.  Or you can
+``cat /proc/kmsg > file``, however you have to break in to stop the transfer,
+``kmsg`` is a "never ending file".
+
+If the machine has crashed so badly that you cannot enter commands or
+the disk is not available then you have three options:
+
+(1) Hand copy the text from the screen and type it in after the machine
+    has restarted.  Messy but it is the only option if you have not
+    planned for a crash. Alternatively, you can take a picture of
+    the screen with a digital camera - not nice, but better than
+    nothing.  If the messages scroll off the top of the console, you
+    may find that booting with a higher resolution (eg, ``vga=791``)
+    will allow you to read more of the text. (Caveat: This needs ``vesafb``,
+    so won't help for 'early' oopses)
+
+(2) Boot with a serial console (see
+    :ref:`Documentation/admin-guide/serial-console.rst <serial_console>`),
+    run a null modem to a second machine and capture the output there
+    using your favourite communication program.  Minicom works well.
+
+(3) Use Kdump (see Documentation/kdump/kdump.txt),
+    extract the kernel ring buffer from old memory with using dmesg
+    gdbmacro in Documentation/kdump/gdbmacros.txt.
+
+Finding the bug's location
+--------------------------
+
+Reporting a bug works best if you point the location of the bug at the
+Kernel source file. There are two methods for doing that. Usually, using
+``gdb`` is easier, but the Kernel should be pre-compiled with debug info.
+
+gdb
+^^^
+
+The GNU debug (``gdb``) is the best way to figure out the exact file and line
+number of the OOPS from the ``vmlinux`` file.
+
+The usage of gdb works best on a kernel compiled with ``CONFIG_DEBUG_INFO``.
+This can be set by running::
+
+  $ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
+
+On a kernel compiled with ``CONFIG_DEBUG_INFO``, you can simply copy the
+EIP value from the OOPS::
+
+ EIP:    0060:[<c021e50e>]    Not tainted VLI
+
+And use GDB to translate that to human-readable form::
+
+  $ gdb vmlinux
+  (gdb) l *0xc021e50e
+
+If you don't have ``CONFIG_DEBUG_INFO`` enabled, you use the function
+offset from the OOPS::
+
+ EIP is at vt_ioctl+0xda8/0x1482
+
+And recompile the kernel with ``CONFIG_DEBUG_INFO`` enabled::
+
+  $ ./scripts/config -d COMPILE_TEST -e DEBUG_KERNEL -e DEBUG_INFO
+  $ make vmlinux
+  $ gdb vmlinux
+  (gdb) l *vt_ioctl+0xda8
+  0x1888 is in vt_ioctl (drivers/tty/vt/vt_ioctl.c:293).
+  288	{
+  289		struct vc_data *vc = NULL;
+  290		int ret = 0;
+  291
+  292		console_lock();
+  293		if (VT_BUSY(vc_num))
+  294			ret = -EBUSY;
+  295		else if (vc_num)
+  296			vc = vc_deallocate(vc_num);
+  297		console_unlock();
+
+or, if you want to be more verbose::
+
+  (gdb) p vt_ioctl
+  $1 = {int (struct tty_struct *, unsigned int, unsigned long)} 0xae0 <vt_ioctl>
+  (gdb) l *0xae0+0xda8
+
+You could, instead, use the object file::
+
+  $ make drivers/tty/
+  $ gdb drivers/tty/vt/vt_ioctl.o
+  (gdb) l *vt_ioctl+0xda8
+
+If you have a call trace, such as::
+
+     Call Trace:
+      [<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
+      [<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
+      [<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
+      ...
+
+this shows the problem likely in the :jbd: module. You can load that module
+in gdb and list the relevant code::
+
+  $ gdb fs/jbd/jbd.ko
+  (gdb) l *log_wait_commit+0xa3
+
+.. note::
+
+     You can also do the same for any function call at the stack trace,
+     like this one::
+
+	 [<f80bc9ca>] ? dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]
+
+     The position where the above call happened can be seen with::
+
+	$ gdb drivers/media/usb/dvb-usb/dvb-usb.o
+	(gdb) l *dvb_usb_adapter_frontend_exit+0x3a
+
+objdump
+^^^^^^^
+
+To debug a kernel, use objdump and look for the hex offset from the crash
+output to find the valid line of code/assembler. Without debug symbols, you
+will see the assembler code for the routine shown, but if your kernel has
+debug symbols the C code will also be available. (Debug symbols can be enabled
+in the kernel hacking menu of the menu configuration.) For example::
+
+    $ objdump -r -S -l --disassemble net/dccp/ipv4.o
+
+.. note::
+
+   You need to be at the top level of the kernel tree for this to pick up
+   your C files.
+
+If you don't have access to the code you can also debug on some crash dumps
+e.g. crash dump output as shown by Dave Miller::
+
+     EIP is at 	+0x14/0x4c0
+      ...
+     Code: 44 24 04 e8 6f 05 00 00 e9 e8 fe ff ff 8d 76 00 8d bc 27 00 00
+     00 00 55 57  56 53 81 ec bc 00 00 00 8b ac 24 d0 00 00 00 8b 5d 08
+     <8b> 83 3c 01 00 00 89 44  24 14 8b 45 28 85 c0 89 44 24 18 0f 85
+
+     Put the bytes into a "foo.s" file like this:
+
+            .text
+            .globl foo
+     foo:
+            .byte  .... /* bytes from Code: part of OOPS dump */
+
+     Compile it with "gcc -c -o foo.o foo.s" then look at the output of
+     "objdump --disassemble foo.o".
+
+     Output:
+
+     ip_queue_xmit:
+         push       %ebp
+         push       %edi
+         push       %esi
+         push       %ebx
+         sub        $0xbc, %esp
+         mov        0xd0(%esp), %ebp        ! %ebp = arg0 (skb)
+         mov        0x8(%ebp), %ebx         ! %ebx = skb->sk
+         mov        0x13c(%ebx), %eax       ! %eax = inet_sk(sk)->opt
+
+Reporting the bug
+-----------------
+
+Once you find where the bug happened, by inspecting its location,
+you could either try to fix it yourself or report it upstream.
+
+In order to report it upstream, you should identify the mailing list
+used for the development of the affected code. This can be done by using
+the ``get_maintainer.pl`` script.
+
+For example, if you find a bug at the gspca's conex.c file, you can get
+their maintainers with::
+
+	$ ./scripts/get_maintainer.pl -f drivers/media/usb/gspca/sonixj.c
+	Hans Verkuil <hverkuil@xs4all.nl> (odd fixer:GSPCA USB WEBCAM DRIVER,commit_signer:1/1=100%)
+	Mauro Carvalho Chehab <mchehab@kernel.org> (maintainer:MEDIA INPUT INFRASTRUCTURE (V4L/DVB),commit_signer:1/1=100%)
+	Tejun Heo <tj@kernel.org> (commit_signer:1/1=100%)
+	Bhaktipriya Shridhar <bhaktipriya96@gmail.com> (commit_signer:1/1=100%,authored:1/1=100%,added_lines:4/4=100%,removed_lines:9/9=100%)
+	linux-media@vger.kernel.org (open list:GSPCA USB WEBCAM DRIVER)
+	linux-kernel@vger.kernel.org (open list)
+
+Please notice that it will point to:
+
+- The last developers that touched on the source code. On the above example,
+  Tejun and Bhaktipriya (in this specific case, none really envolved on the
+  development of this file);
+- The driver maintainer (Hans Verkuil);
+- The subsystem maintainer (Mauro Carvalho Chehab)
+- The driver and/or subsystem mailing list (linux-media@vger.kernel.org);
+- the Linux Kernel mailing list (linux-kernel@vger.kernel.org).
+
+Usually, the fastest way to have your bug fixed is to report it to mailing
+list used for the development of the code (linux-media ML) copying the driver maintainer (Hans).
+
+If you are totally stumped as to whom to send the report, and
+``get_maintainer.pl`` didn't provide you anything useful, send it to
+linux-kernel@vger.kernel.org.
+
+Thanks for your help in making Linux as stable as humanly possible.
+
+Fixing the bug
+--------------
+
+If you know programming, you could help us by not only reporting the bug,
+but also providing us with a solution. After all open source is about
+sharing what you do and don't you want to be recognised for your genius?
+
+If you decide to take this way, once you have worked out a fix please submit
+it upstream.
+
+Please do read
+ref:`Documentation/process/submitting-patches.rst <submittingpatches>` though
+to help your code get accepted.
+
+
+---------------------------------------------------------------------------
+
+Notes on Oops tracing with ``klogd``
+------------------------------------
+
+In order to help Linus and the other kernel developers there has been
+substantial support incorporated into ``klogd`` for processing protection
+faults.  In order to have full support for address resolution at least
+version 1.3-pl3 of the ``sysklogd`` package should be used.
+
+When a protection fault occurs the ``klogd`` daemon automatically
+translates important addresses in the kernel log messages to their
+symbolic equivalents.  This translated kernel message is then
+forwarded through whatever reporting mechanism ``klogd`` is using.  The
+protection fault message can be simply cut out of the message files
+and forwarded to the kernel developers.
+
+Two types of address resolution are performed by ``klogd``.  The first is
+static translation and the second is dynamic translation.  Static
+translation uses the System.map file in much the same manner that
+ksymoops does.  In order to do static translation the ``klogd`` daemon
+must be able to find a system map file at daemon initialization time.
+See the klogd man page for information on how ``klogd`` searches for map
+files.
+
+Dynamic address translation is important when kernel loadable modules
+are being used.  Since memory for kernel modules is allocated from the
+kernel's dynamic memory pools there are no fixed locations for either
+the start of the module or for functions and symbols in the module.
+
+The kernel supports system calls which allow a program to determine
+which modules are loaded and their location in memory.  Using these
+system calls the klogd daemon builds a symbol table which can be used
+to debug a protection fault which occurs in a loadable kernel module.
+
+At the very minimum klogd will provide the name of the module which
+generated the protection fault.  There may be additional symbolic
+information available if the developer of the loadable module chose to
+export symbol information from the module.
+
+Since the kernel module environment can be dynamic there must be a
+mechanism for notifying the ``klogd`` daemon when a change in module
+environment occurs.  There are command line options available which
+allow klogd to signal the currently executing daemon that symbol
+information should be refreshed.  See the ``klogd`` manual page for more
+information.
+
+A patch is included with the sysklogd distribution which modifies the
+``modules-2.0.0`` package to automatically signal klogd whenever a module
+is loaded or unloaded.  Applying this patch provides essentially
+seamless support for debugging protection faults which occur with
+kernel loadable modules.
+
+The following is an example of a protection fault in a loadable module
+processed by ``klogd``::
+
+	Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
+	Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
+	Aug 29 09:51:01 blizard kernel: *pde = 00000000
+	Aug 29 09:51:01 blizard kernel: Oops: 0002
+	Aug 29 09:51:01 blizard kernel: CPU:    0
+	Aug 29 09:51:01 blizard kernel: EIP:    0010:[oops:_oops+16/3868]
+	Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
+	Aug 29 09:51:01 blizard kernel: eax: 315e97cc   ebx: 003a6f80   ecx: 001be77b   edx: 00237c0c
+	Aug 29 09:51:01 blizard kernel: esi: 00000000   edi: bffffdb3   ebp: 00589f90   esp: 00589f8c
+	Aug 29 09:51:01 blizard kernel: ds: 0018   es: 0018   fs: 002b   gs: 002b   ss: 0018
+	Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
+	Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
+	Aug 29 09:51:01 blizard kernel:        00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
+	Aug 29 09:51:01 blizard kernel:        bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
+	Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
+	Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
+
+---------------------------------------------------------------------------
+
+::
+
+  Dr. G.W. Wettstein           Oncology Research Div. Computing Facility
+  Roger Maris Cancer Center    INTERNET: greg@wind.rmcc.com
+  820 4th St. N.
+  Fargo, ND  58122
+  Phone: 701-234-7556
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/conf.py linux-libre-4.10-rc8-gnu/Documentation/admin-guide/conf.py
--- linux-libre-4.9-gnu/Documentation/admin-guide/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel User Documentation'
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'linux-user.tex', 'Linux Kernel User Documentation',
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/devices.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/devices.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/devices.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/devices.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,268 @@
+
+Linux allocated devices (4.x+ version)
+======================================
+
+This list is the Linux Device List, the official registry of allocated
+device numbers and ``/dev`` directory nodes for the Linux operating
+system.
+
+The LaTeX version of this document is no longer maintained, nor is
+the document that used to reside at lanana.org.  This version in the
+mainline Linux kernel is the master document.  Updates shall be sent
+as patches to the kernel maintainers (see the
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>` document).
+Specifically explore the sections titled "CHAR and MISC DRIVERS", and
+"BLOCK LAYER" in the MAINTAINERS file to find the right maintainers
+to involve for character and block devices.
+
+This document is included by reference into the Filesystem Hierarchy
+Standard (FHS).	 The FHS is available from http://www.pathname.com/fhs/.
+
+Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga
+platform only.	Allocations marked (68k/Atari) apply to Linux/68k on
+the Atari platform only.
+
+This document is in the public domain.	The authors requests, however,
+that semantically altered versions are not distributed without
+permission of the authors, assuming the authors can be contacted without
+an unreasonable effort.
+
+
+.. attention::
+
+  DEVICE DRIVERS AUTHORS PLEASE READ THIS
+
+  Linux now has extensive support for dynamic allocation of device numbering
+  and can use ``sysfs`` and ``udev`` (``systemd``) to handle the naming needs.
+  There are still some exceptions in the serial and boot device area. Before
+  asking   for a device number make sure you actually need one.
+
+  To have a major number allocated, or a minor number in situations
+  where that applies (e.g. busmice), please submit a patch and send to
+  the authors as indicated above.
+
+  Keep the description of the device *in the same format
+  as this list*. The reason for this is that it is the only way we have
+  found to ensure we have all the requisite information to publish your
+  device and avoid conflicts.
+
+  Finally, sometimes we have to play "namespace police."  Please don't be
+  offended.  We often get submissions for ``/dev`` names that would be bound
+  to cause conflicts down the road.  We are trying to avoid getting in a
+  situation where we would have to suffer an incompatible forward
+  change.  Therefore, please consult with us **before** you make your
+  device names and numbers in any way public, at least to the point
+  where it would be at all difficult to get them changed.
+
+  Your cooperation is appreciated.
+
+.. include:: devices.txt
+   :literal:
+
+Additional ``/dev/`` directory entries
+--------------------------------------
+
+This section details additional entries that should or may exist in
+the /dev directory.  It is preferred that symbolic links use the same
+form (absolute or relative) as is indicated here.  Links are
+classified as "hard" or "symbolic" depending on the preferred type of
+link; if possible, the indicated type of link should be used.
+
+Compulsory links
+++++++++++++++++
+
+These links should exist on all systems:
+
+=============== =============== =============== ===============================
+/dev/fd		/proc/self/fd	symbolic	File descriptors
+/dev/stdin	fd/0		symbolic	stdin file descriptor
+/dev/stdout	fd/1		symbolic	stdout file descriptor
+/dev/stderr	fd/2		symbolic	stderr file descriptor
+/dev/nfsd	socksys		symbolic	Required by iBCS-2
+/dev/X0R	null		symbolic	Required by iBCS-2
+=============== =============== =============== ===============================
+
+Note: ``/dev/X0R`` is <letter X>-<digit 0>-<letter R>.
+
+Recommended links
++++++++++++++++++
+
+It is recommended that these links exist on all systems:
+
+
+=============== =============== =============== ===============================
+/dev/core	/proc/kcore	symbolic	Backward compatibility
+/dev/ramdisk	ram0		symbolic	Backward compatibility
+/dev/ftape	qft0		symbolic	Backward compatibility
+/dev/bttv0	video0		symbolic	Backward compatibility
+/dev/radio	radio0		symbolic	Backward compatibility
+/dev/i2o*	/dev/i2o/*	symbolic	Backward compatibility
+/dev/scd?	sr?		hard		Alternate SCSI CD-ROM name
+=============== =============== =============== ===============================
+
+Locally defined links
++++++++++++++++++++++
+
+The following links may be established locally to conform to the
+configuration of the system.  This is merely a tabulation of existing
+practice, and does not constitute a recommendation.  However, if they
+exist, they should have the following uses.
+
+=============== =============== =============== ===============================
+/dev/mouse	mouse port	symbolic	Current mouse device
+/dev/tape	tape device	symbolic	Current tape device
+/dev/cdrom	CD-ROM device	symbolic	Current CD-ROM device
+/dev/cdwriter	CD-writer	symbolic	Current CD-writer device
+/dev/scanner	scanner		symbolic	Current scanner device
+/dev/modem	modem port	symbolic	Current dialout device
+/dev/root	root device	symbolic	Current root filesystem
+/dev/swap	swap device	symbolic	Current swap device
+=============== =============== =============== ===============================
+
+``/dev/modem`` should not be used for a modem which supports dialin as
+well as dialout, as it tends to cause lock file problems.  If it
+exists, ``/dev/modem`` should point to the appropriate primary TTY device
+(the use of the alternate callout devices is deprecated).
+
+For SCSI devices, ``/dev/tape`` and ``/dev/cdrom`` should point to the
+*cooked* devices (``/dev/st*`` and ``/dev/sr*``, respectively), whereas
+``/dev/cdwriter`` and /dev/scanner should point to the appropriate generic
+SCSI devices (/dev/sg*).
+
+``/dev/mouse`` may point to a primary serial TTY device, a hardware mouse
+device, or a socket for a mouse driver program (e.g. ``/dev/gpmdata``).
+
+Sockets and pipes
++++++++++++++++++
+
+Non-transient sockets and named pipes may exist in /dev.  Common entries are:
+
+=============== =============== ===============================================
+/dev/printer	socket		lpd local socket
+/dev/log	socket		syslog local socket
+/dev/gpmdata	socket		gpm mouse multiplexer
+=============== =============== ===============================================
+
+Mount points
+++++++++++++
+
+The following names are reserved for mounting special filesystems
+under /dev.  These special filesystems provide kernel interfaces that
+cannot be provided with standard device nodes.
+
+=============== =============== ===============================================
+/dev/pts	devpts		PTY slave filesystem
+/dev/shm	tmpfs		POSIX shared memory maintenance access
+=============== =============== ===============================================
+
+Terminal devices
+----------------
+
+Terminal, or TTY devices are a special class of character devices.  A
+terminal device is any device that could act as a controlling terminal
+for a session; this includes virtual consoles, serial ports, and
+pseudoterminals (PTYs).
+
+All terminal devices share a common set of capabilities known as line
+disciplines; these include the common terminal line discipline as well
+as SLIP and PPP modes.
+
+All terminal devices are named similarly; this section explains the
+naming and use of the various types of TTYs.  Note that the naming
+conventions include several historical warts; some of these are
+Linux-specific, some were inherited from other systems, and some
+reflect Linux outgrowing a borrowed convention.
+
+A hash mark (``#``) in a device name is used here to indicate a decimal
+number without leading zeroes.
+
+Virtual consoles and the console device
++++++++++++++++++++++++++++++++++++++++
+
+Virtual consoles are full-screen terminal displays on the system video
+monitor.  Virtual consoles are named ``/dev/tty#``, with numbering
+starting at ``/dev/tty1``; ``/dev/tty0`` is the current virtual console.
+``/dev/tty0`` is the device that should be used to access the system video
+card on those architectures for which the frame buffer devices
+(``/dev/fb*``) are not applicable. Do not use ``/dev/console``
+for this purpose.
+
+The console device, ``/dev/console``, is the device to which system
+messages should be sent, and on which logins should be permitted in
+single-user mode.  Starting with Linux 2.1.71, ``/dev/console`` is managed
+by the kernel; for previous versions it should be a symbolic link to
+either ``/dev/tty0``, a specific virtual console such as ``/dev/tty1``, or to
+a serial port primary (``tty*``, not ``cu*``) device, depending on the
+configuration of the system.
+
+Serial ports
+++++++++++++
+
+Serial ports are RS-232 serial ports and any device which simulates
+one, either in hardware (such as internal modems) or in software (such
+as the ISDN driver.)  Under Linux, each serial ports has two device
+names, the primary or callin device and the alternate or callout one.
+Each kind of device is indicated by a different letter.	 For any
+letter X, the names of the devices are ``/dev/ttyX#`` and ``/dev/cux#``,
+respectively; for historical reasons, ``/dev/ttyS#`` and ``/dev/ttyC#``
+correspond to ``/dev/cua#`` and ``/dev/cub#``. In the future, it should be
+expected that multiple letters will be used; all letters will be upper
+case for the "tty" device (e.g. ``/dev/ttyDP#``) and lower case for the
+"cu" device (e.g. ``/dev/cudp#``).
+
+The names ``/dev/ttyQ#`` and ``/dev/cuq#`` are reserved for local use.
+
+The alternate devices provide for kernel-based exclusion and somewhat
+different defaults than the primary devices.  Their main purpose is to
+allow the use of serial ports with programs with no inherent or broken
+support for serial ports.  Their use is deprecated, and they may be
+removed from a future version of Linux.
+
+Arbitration of serial ports is provided by the use of lock files with
+the names ``/var/lock/LCK..ttyX#``. The contents of the lock file should
+be the PID of the locking process as an ASCII number.
+
+It is common practice to install links such as /dev/modem
+which point to serial ports.  In order to ensure proper locking in the
+presence of these links, it is recommended that software chase
+symlinks and lock all possible names; additionally, it is recommended
+that a lock file be installed with the corresponding alternate
+device.	 In order to avoid deadlocks, it is recommended that the locks
+are acquired in the following order, and released in the reverse:
+
+	1. The symbolic link name, if any (``/var/lock/LCK..modem``)
+	2. The "tty" name (``/var/lock/LCK..ttyS2``)
+	3. The alternate device name (``/var/lock/LCK..cua2``)
+
+In the case of nested symbolic links, the lock files should be
+installed in the order the symlinks are resolved.
+
+Under no circumstances should an application hold a lock while waiting
+for another to be released.  In addition, applications which attempt
+to create lock files for the corresponding alternate device names
+should take into account the possibility of being used on a non-serial
+port TTY, for which no alternate device would exist.
+
+Pseudoterminals (PTYs)
+++++++++++++++++++++++
+
+Pseudoterminals, or PTYs, are used to create login sessions or provide
+other capabilities requiring a TTY line discipline (including SLIP or
+PPP capability) to arbitrary data-generation processes.	 Each PTY has
+a master side, named ``/dev/pty[p-za-e][0-9a-f]``, and a slave side, named
+``/dev/tty[p-za-e][0-9a-f]``.  The kernel arbitrates the use of PTYs by
+allowing each master side to be opened only once.
+
+Once the master side has been opened, the corresponding slave device
+can be used in the same manner as any TTY device.  The master and
+slave devices are connected by the kernel, generating the equivalent
+of a bidirectional pipe with TTY capabilities.
+
+Recent versions of the Linux kernels and GNU libc contain support for
+the System V/Unix98 naming scheme for PTYs, which assigns a common
+device, ``/dev/ptmx``, to all the masters (opening it will automatically
+give you a previously unassigned PTY) and a subdirectory, ``/dev/pts``,
+for the slaves; the slaves are named with decimal integers (``/dev/pts/#``
+in our notation).  This removes the problem of exhausting the
+namespace and enables the kernel to automatically create the device
+nodes for the slaves on demand using the "devpts" filesystem.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/devices.txt linux-libre-4.10-rc8-gnu/Documentation/admin-guide/devices.txt
--- linux-libre-4.9-gnu/Documentation/admin-guide/devices.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/devices.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3081 @@
+   0		Unnamed devices (e.g. non-device mounts)
+		  0 = reserved as null device number
+		See block major 144, 145, 146 for expansion areas.
+
+   1 char	Memory devices
+		  1 = /dev/mem		Physical memory access
+		  2 = /dev/kmem		Kernel virtual memory access
+		  3 = /dev/null		Null device
+		  4 = /dev/port		I/O port access
+		  5 = /dev/zero		Null byte source
+		  6 = /dev/core		OBSOLETE - replaced by /proc/kcore
+		  7 = /dev/full		Returns ENOSPC on write
+		  8 = /dev/random	Nondeterministic random number gen.
+		  9 = /dev/urandom	Faster, less secure random number gen.
+		 10 = /dev/aio		Asynchronous I/O notification interface
+		 11 = /dev/kmsg		Writes to this come out as printk's, reads
+					export the buffered printk records.
+		 12 = /dev/oldmem	OBSOLETE - replaced by /proc/vmcore
+
+   1 block	RAM disk
+		  0 = /dev/ram0		First RAM disk
+		  1 = /dev/ram1		Second RAM disk
+		    ...
+		250 = /dev/initrd	Initial RAM disk
+
+		Older kernels had /dev/ramdisk (1, 1) here.
+		/dev/initrd refers to a RAM disk which was preloaded
+		by the boot loader; newer kernels use /dev/ram0 for
+		the initrd.
+
+   2 char	Pseudo-TTY masters
+		  0 = /dev/ptyp0	First PTY master
+		  1 = /dev/ptyp1	Second PTY master
+		    ...
+		255 = /dev/ptyef	256th PTY master
+
+		Pseudo-tty's are named as follows:
+		* Masters are "pty", slaves are "tty";
+		* the fourth letter is one of pqrstuvwxyzabcde indicating
+		  the 1st through 16th series of 16 pseudo-ttys each, and
+		* the fifth letter is one of 0123456789abcdef indicating
+		  the position within the series.
+
+		These are the old-style (BSD) PTY devices; Unix98
+		devices are on major 128 and above and use the PTY
+		master multiplex (/dev/ptmx) to acquire a PTY on
+		demand.
+
+   2 block	Floppy disks
+		  0 = /dev/fd0		Controller 0, drive 0, autodetect
+		  1 = /dev/fd1		Controller 0, drive 1, autodetect
+		  2 = /dev/fd2		Controller 0, drive 2, autodetect
+		  3 = /dev/fd3		Controller 0, drive 3, autodetect
+		128 = /dev/fd4		Controller 1, drive 0, autodetect
+		129 = /dev/fd5		Controller 1, drive 1, autodetect
+		130 = /dev/fd6		Controller 1, drive 2, autodetect
+		131 = /dev/fd7		Controller 1, drive 3, autodetect
+
+		To specify format, add to the autodetect device number:
+		  0 = /dev/fd?		Autodetect format
+		  4 = /dev/fd?d360	5.25"  360K in a 360K  drive(1)
+		 20 = /dev/fd?h360	5.25"  360K in a 1200K drive(1)
+		 48 = /dev/fd?h410	5.25"  410K in a 1200K drive
+		 64 = /dev/fd?h420	5.25"  420K in a 1200K drive
+		 24 = /dev/fd?h720	5.25"  720K in a 1200K drive
+		 80 = /dev/fd?h880	5.25"  880K in a 1200K drive(1)
+		  8 = /dev/fd?h1200	5.25" 1200K in a 1200K drive(1)
+		 40 = /dev/fd?h1440	5.25" 1440K in a 1200K drive(1)
+		 56 = /dev/fd?h1476	5.25" 1476K in a 1200K drive
+		 72 = /dev/fd?h1494	5.25" 1494K in a 1200K drive
+		 92 = /dev/fd?h1600	5.25" 1600K in a 1200K drive(1)
+
+		 12 = /dev/fd?u360	3.5"   360K Double Density(2)
+		 16 = /dev/fd?u720	3.5"   720K Double Density(1)
+		120 = /dev/fd?u800	3.5"   800K Double Density(2)
+		 52 = /dev/fd?u820	3.5"   820K Double Density
+		 68 = /dev/fd?u830	3.5"   830K Double Density
+		 84 = /dev/fd?u1040	3.5"  1040K Double Density(1)
+		 88 = /dev/fd?u1120	3.5"  1120K Double Density(1)
+		 28 = /dev/fd?u1440	3.5"  1440K High Density(1)
+		124 = /dev/fd?u1600	3.5"  1600K High Density(1)
+		 44 = /dev/fd?u1680	3.5"  1680K High Density(3)
+		 60 = /dev/fd?u1722	3.5"  1722K High Density
+		 76 = /dev/fd?u1743	3.5"  1743K High Density
+		 96 = /dev/fd?u1760	3.5"  1760K High Density
+		116 = /dev/fd?u1840	3.5"  1840K High Density(3)
+		100 = /dev/fd?u1920	3.5"  1920K High Density(1)
+		 32 = /dev/fd?u2880	3.5"  2880K Extra Density(1)
+		104 = /dev/fd?u3200	3.5"  3200K Extra Density
+		108 = /dev/fd?u3520	3.5"  3520K Extra Density
+		112 = /dev/fd?u3840	3.5"  3840K Extra Density(1)
+
+		 36 = /dev/fd?CompaQ	Compaq 2880K drive; obsolete?
+
+		(1) Autodetectable format
+		(2) Autodetectable format in a Double Density (720K) drive only
+		(3) Autodetectable format in a High Density (1440K) drive only
+
+		NOTE: The letter in the device name (d, q, h or u)
+		signifies the type of drive: 5.25" Double Density (d),
+		5.25" Quad Density (q), 5.25" High Density (h) or 3.5"
+		(any model, u).	 The use of the capital letters D, H
+		and E for the 3.5" models have been deprecated, since
+		the drive type is insignificant for these devices.
+
+   3 char	Pseudo-TTY slaves
+		  0 = /dev/ttyp0	First PTY slave
+		  1 = /dev/ttyp1	Second PTY slave
+		    ...
+		255 = /dev/ttyef	256th PTY slave
+
+		These are the old-style (BSD) PTY devices; Unix98
+		devices are on major 136 and above.
+
+   3 block	First MFM, RLL and IDE hard disk/CD-ROM interface
+		  0 = /dev/hda		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdb		Slave: whole disk (or CD-ROM)
+
+		For partitions, add to the whole disk device number:
+		  0 = /dev/hd?		Whole disk
+		  1 = /dev/hd?1		First partition
+		  2 = /dev/hd?2		Second partition
+		    ...
+		 63 = /dev/hd?63	63rd partition
+
+		For Linux/i386, partitions 1-4 are the primary
+		partitions, and 5 and above are logical partitions.
+		Other versions of Linux use partitioning schemes
+		appropriate to their respective architectures.
+
+   4 char	TTY devices
+		  0 = /dev/tty0		Current virtual console
+
+		  1 = /dev/tty1		First virtual console
+		    ...
+		 63 = /dev/tty63	63rd virtual console
+		 64 = /dev/ttyS0	First UART serial port
+		    ...
+		255 = /dev/ttyS191	192nd UART serial port
+
+		UART serial ports refer to 8250/16450/16550 series devices.
+
+		Older versions of the Linux kernel used this major
+		number for BSD PTY devices.  As of Linux 2.1.115, this
+		is no longer supported.	 Use major numbers 2 and 3.
+
+   4 block	Aliases for dynamically allocated major devices to be used
+		when its not possible to create the real device nodes
+		because the root filesystem is mounted read-only.
+
+		   0 = /dev/root
+
+   5 char	Alternate TTY devices
+		  0 = /dev/tty		Current TTY device
+		  1 = /dev/console	System console
+		  2 = /dev/ptmx		PTY master multiplex
+		  3 = /dev/ttyprintk	User messages via printk TTY device
+		 64 = /dev/cua0		Callout device for ttyS0
+		    ...
+		255 = /dev/cua191	Callout device for ttyS191
+
+		(5,1) is /dev/console starting with Linux 2.1.71.  See
+		the section on terminal devices for more information
+		on /dev/console.
+
+   6 char	Parallel printer devices
+		  0 = /dev/lp0		Parallel printer on parport0
+		  1 = /dev/lp1		Parallel printer on parport1
+		    ...
+
+		Current Linux kernels no longer have a fixed mapping
+		between parallel ports and I/O addresses.  Instead,
+		they are redirected through the parport multiplex layer.
+
+   7 char	Virtual console capture devices
+		  0 = /dev/vcs		Current vc text contents
+		  1 = /dev/vcs1		tty1 text contents
+		    ...
+		 63 = /dev/vcs63	tty63 text contents
+		128 = /dev/vcsa		Current vc text/attribute contents
+		129 = /dev/vcsa1	tty1 text/attribute contents
+		    ...
+		191 = /dev/vcsa63	tty63 text/attribute contents
+
+		NOTE: These devices permit both read and write access.
+
+   7 block	Loopback devices
+		  0 = /dev/loop0	First loop device
+		  1 = /dev/loop1	Second loop device
+		    ...
+
+		The loop devices are used to mount filesystems not
+		associated with block devices.	The binding to the
+		loop devices is handled by mount(8) or losetup(8).
+
+   8 block	SCSI disk devices (0-15)
+		  0 = /dev/sda		First SCSI disk whole disk
+		 16 = /dev/sdb		Second SCSI disk whole disk
+		 32 = /dev/sdc		Third SCSI disk whole disk
+		    ...
+		240 = /dev/sdp		Sixteenth SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+   9 char	SCSI tape devices
+		  0 = /dev/st0		First SCSI tape, mode 0
+		  1 = /dev/st1		Second SCSI tape, mode 0
+		    ...
+		 32 = /dev/st0l		First SCSI tape, mode 1
+		 33 = /dev/st1l		Second SCSI tape, mode 1
+		    ...
+		 64 = /dev/st0m		First SCSI tape, mode 2
+		 65 = /dev/st1m		Second SCSI tape, mode 2
+		    ...
+		 96 = /dev/st0a		First SCSI tape, mode 3
+		 97 = /dev/st1a		Second SCSI tape, mode 3
+		      ...
+		128 = /dev/nst0		First SCSI tape, mode 0, no rewind
+		129 = /dev/nst1		Second SCSI tape, mode 0, no rewind
+		    ...
+		160 = /dev/nst0l	First SCSI tape, mode 1, no rewind
+		161 = /dev/nst1l	Second SCSI tape, mode 1, no rewind
+		    ...
+		192 = /dev/nst0m	First SCSI tape, mode 2, no rewind
+		193 = /dev/nst1m	Second SCSI tape, mode 2, no rewind
+		    ...
+		224 = /dev/nst0a	First SCSI tape, mode 3, no rewind
+		225 = /dev/nst1a	Second SCSI tape, mode 3, no rewind
+		    ...
+
+		"No rewind" refers to the omission of the default
+		automatic rewind on device close.  The MTREW or MTOFFL
+		ioctl()'s can be used to rewind the tape regardless of
+		the device used to access it.
+
+   9 block	Metadisk (RAID) devices
+		  0 = /dev/md0		First metadisk group
+		  1 = /dev/md1		Second metadisk group
+		    ...
+
+		The metadisk driver is used to span a
+		filesystem across multiple physical disks.
+
+  10 char	Non-serial mice, misc features
+		  0 = /dev/logibm	Logitech bus mouse
+		  1 = /dev/psaux	PS/2-style mouse port
+		  2 = /dev/inportbm	Microsoft Inport bus mouse
+		  3 = /dev/atibm	ATI XL bus mouse
+		  4 = /dev/jbm		J-mouse
+		  4 = /dev/amigamouse	Amiga mouse (68k/Amiga)
+		  5 = /dev/atarimouse	Atari mouse
+		  6 = /dev/sunmouse	Sun mouse
+		  7 = /dev/amigamouse1	Second Amiga mouse
+		  8 = /dev/smouse	Simple serial mouse driver
+		  9 = /dev/pc110pad	IBM PC-110 digitizer pad
+		 10 = /dev/adbmouse	Apple Desktop Bus mouse
+		 11 = /dev/vrtpanel	Vr41xx embedded touch panel
+		 13 = /dev/vpcmouse	Connectix Virtual PC Mouse
+		 14 = /dev/touchscreen/ucb1x00  UCB 1x00 touchscreen
+		 15 = /dev/touchscreen/mk712	MK712 touchscreen
+		128 = /dev/beep		Fancy beep device
+		129 =
+		130 = /dev/watchdog	Watchdog timer port
+		131 = /dev/temperature	Machine internal temperature
+		132 = /dev/hwtrap	Hardware fault trap
+		133 = /dev/exttrp	External device trap
+		134 = /dev/apm_bios	Advanced Power Management BIOS
+		135 = /dev/rtc		Real Time Clock
+		137 = /dev/vhci		Bluetooth virtual HCI driver
+		139 = /dev/openprom	SPARC OpenBoot PROM
+		140 = /dev/relay8	Berkshire Products Octal relay card
+		141 = /dev/relay16	Berkshire Products ISO-16 relay card
+		142 =
+		143 = /dev/pciconf	PCI configuration space
+		144 = /dev/nvram	Non-volatile configuration RAM
+		145 = /dev/hfmodem	Soundcard shortwave modem control
+		146 = /dev/graphics	Linux/SGI graphics device
+		147 = /dev/opengl	Linux/SGI OpenGL pipe
+		148 = /dev/gfx		Linux/SGI graphics effects device
+		149 = /dev/input/mouse	Linux/SGI Irix emulation mouse
+		150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard
+		151 = /dev/led		Front panel LEDs
+		152 = /dev/kpoll	Kernel Poll Driver
+		153 = /dev/mergemem	Memory merge device
+		154 = /dev/pmu		Macintosh PowerBook power manager
+		155 = /dev/isictl	MultiTech ISICom serial control
+		156 = /dev/lcd		Front panel LCD display
+		157 = /dev/ac		Applicom Intl Profibus card
+		158 = /dev/nwbutton	Netwinder external button
+		159 = /dev/nwdebug	Netwinder debug interface
+		160 = /dev/nwflash	Netwinder flash memory
+		161 = /dev/userdma	User-space DMA access
+		162 = /dev/smbus	System Management Bus
+		163 = /dev/lik		Logitech Internet Keyboard
+		164 = /dev/ipmo		Intel Intelligent Platform Management
+		165 = /dev/vmmon	VMware virtual machine monitor
+		166 = /dev/i2o/ctl	I2O configuration manager
+		167 = /dev/specialix_sxctl Specialix serial control
+		168 = /dev/tcldrv	Technology Concepts serial control
+		169 = /dev/specialix_rioctl Specialix RIO serial control
+		170 = /dev/thinkpad/thinkpad	IBM Thinkpad devices
+		171 = /dev/srripc	QNX4 API IPC manager
+		172 = /dev/usemaclone	Semaphore clone device
+		173 = /dev/ipmikcs	Intelligent Platform Management
+		174 = /dev/uctrl	SPARCbook 3 microcontroller
+		175 = /dev/agpgart	AGP Graphics Address Remapping Table
+		176 = /dev/gtrsc	Gorgy Timing radio clock
+		177 = /dev/cbm		Serial CBM bus
+		178 = /dev/jsflash	JavaStation OS flash SIMM
+		179 = /dev/xsvc		High-speed shared-mem/semaphore service
+		180 = /dev/vrbuttons	Vr41xx button input device
+		181 = /dev/toshiba	Toshiba laptop SMM support
+		182 = /dev/perfctr	Performance-monitoring counters
+		183 = /dev/hwrng	Generic random number generator
+		184 = /dev/cpu/microcode CPU microcode update interface
+		186 = /dev/atomicps	Atomic shapshot of process state data
+		187 = /dev/irnet	IrNET device
+		188 = /dev/smbusbios	SMBus BIOS
+		189 = /dev/ussp_ctl	User space serial port control
+		190 = /dev/crash	Mission Critical Linux crash dump facility
+		191 = /dev/pcl181	<information missing>
+		192 = /dev/nas_xbus	NAS xbus LCD/buttons access
+		193 = /dev/d7s		SPARC 7-segment display
+		194 = /dev/zkshim	Zero-Knowledge network shim control
+		195 = /dev/elographics/e2201	Elographics touchscreen E271-2201
+		196 = /dev/vfio/vfio	VFIO userspace driver interface
+		197 = /dev/pxa3xx-gcu	PXA3xx graphics controller unit driver
+		198 = /dev/sexec	Signed executable interface
+		199 = /dev/scanners/cuecat :CueCat barcode scanner
+		200 = /dev/net/tun	TAP/TUN network device
+		201 = /dev/button/gulpb	Transmeta GULP-B buttons
+		202 = /dev/emd/ctl	Enhanced Metadisk RAID (EMD) control
+		203 = /dev/cuse		Cuse (character device in user-space)
+		204 = /dev/video/em8300		EM8300 DVD decoder control
+		205 = /dev/video/em8300_mv	EM8300 DVD decoder video
+		206 = /dev/video/em8300_ma	EM8300 DVD decoder audio
+		207 = /dev/video/em8300_sp	EM8300 DVD decoder subpicture
+		208 = /dev/compaq/cpqphpc	Compaq PCI Hot Plug Controller
+		209 = /dev/compaq/cpqrid	Compaq Remote Insight Driver
+		210 = /dev/impi/bt	IMPI coprocessor block transfer
+		211 = /dev/impi/smic	IMPI coprocessor stream interface
+		212 = /dev/watchdogs/0	First watchdog device
+		213 = /dev/watchdogs/1	Second watchdog device
+		214 = /dev/watchdogs/2	Third watchdog device
+		215 = /dev/watchdogs/3	Fourth watchdog device
+		216 = /dev/fujitsu/apanel	Fujitsu/Siemens application panel
+		217 = /dev/ni/natmotn		National Instruments Motion
+		218 = /dev/kchuid	Inter-process chuid control
+		219 = /dev/modems/mwave	MWave modem firmware upload
+		220 = /dev/mptctl	Message passing technology (MPT) control
+		221 = /dev/mvista/hssdsi	Montavista PICMG hot swap system driver
+		222 = /dev/mvista/hasi		Montavista PICMG high availability
+		223 = /dev/input/uinput		User level driver support for input
+		224 = /dev/tpm		TCPA TPM driver
+		225 = /dev/pps		Pulse Per Second driver
+		226 = /dev/systrace	Systrace device
+		227 = /dev/mcelog	X86_64 Machine Check Exception driver
+		228 = /dev/hpet		HPET driver
+		229 = /dev/fuse		Fuse (virtual filesystem in user-space)
+		230 = /dev/midishare	MidiShare driver
+		231 = /dev/snapshot	System memory snapshot device
+		232 = /dev/kvm		Kernel-based virtual machine (hardware virtualization extensions)
+		233 = /dev/kmview	View-OS A process with a view
+		234 = /dev/btrfs-control	Btrfs control device
+		235 = /dev/autofs	Autofs control device
+		236 = /dev/mapper/control	Device-Mapper control device
+		237 = /dev/loop-control Loopback control device
+		238 = /dev/vhost-net	Host kernel accelerator for virtio net
+		239 = /dev/uhid		User-space I/O driver support for HID subsystem
+
+		240-254			Reserved for local use
+		255			Reserved for MISC_DYNAMIC_MINOR
+
+  11 char	Raw keyboard device	(Linux/SPARC only)
+		  0 = /dev/kbd		Raw keyboard device
+
+  11 char	Serial Mux device	(Linux/PA-RISC only)
+		  0 = /dev/ttyB0	First mux port
+		  1 = /dev/ttyB1	Second mux port
+		    ...
+
+  11 block	SCSI CD-ROM devices
+		  0 = /dev/scd0		First SCSI CD-ROM
+		  1 = /dev/scd1		Second SCSI CD-ROM
+		    ...
+
+		The prefix /dev/sr (instead of /dev/scd) has been deprecated.
+
+  12 char	QIC-02 tape
+		  2 = /dev/ntpqic11	QIC-11, no rewind-on-close
+		  3 = /dev/tpqic11	QIC-11, rewind-on-close
+		  4 = /dev/ntpqic24	QIC-24, no rewind-on-close
+		  5 = /dev/tpqic24	QIC-24, rewind-on-close
+		  6 = /dev/ntpqic120	QIC-120, no rewind-on-close
+		  7 = /dev/tpqic120	QIC-120, rewind-on-close
+		  8 = /dev/ntpqic150	QIC-150, no rewind-on-close
+		  9 = /dev/tpqic150	QIC-150, rewind-on-close
+
+		The device names specified are proposed -- if there
+		are "standard" names for these devices, please let me know.
+
+  12 block
+
+  13 char	Input core
+		  0 = /dev/input/js0	First joystick
+		  1 = /dev/input/js1	Second joystick
+		    ...
+		 32 = /dev/input/mouse0	First mouse
+		 33 = /dev/input/mouse1	Second mouse
+		    ...
+		 63 = /dev/input/mice	Unified mouse
+		 64 = /dev/input/event0	First event queue
+		 65 = /dev/input/event1	Second event queue
+		    ...
+
+		Each device type has 5 bits (32 minors).
+
+  13 block	Previously used for the XT disk (/dev/xdN)
+		Deleted in kernel v3.9.
+
+  14 char	Open Sound System (OSS)
+		  0 = /dev/mixer	Mixer control
+		  1 = /dev/sequencer	Audio sequencer
+		  2 = /dev/midi00	First MIDI port
+		  3 = /dev/dsp		Digital audio
+		  4 = /dev/audio	Sun-compatible digital audio
+		  6 =
+		  7 = /dev/audioctl	SPARC audio control device
+		  8 = /dev/sequencer2	Sequencer -- alternate device
+		 16 = /dev/mixer1	Second soundcard mixer control
+		 17 = /dev/patmgr0	Sequencer patch manager
+		 18 = /dev/midi01	Second MIDI port
+		 19 = /dev/dsp1		Second soundcard digital audio
+		 20 = /dev/audio1	Second soundcard Sun digital audio
+		 33 = /dev/patmgr1	Sequencer patch manager
+		 34 = /dev/midi02	Third MIDI port
+		 50 = /dev/midi03	Fourth MIDI port
+
+  14 block
+
+  15 char	Joystick
+		  0 = /dev/js0		First analog joystick
+		  1 = /dev/js1		Second analog joystick
+		    ...
+		128 = /dev/djs0		First digital joystick
+		129 = /dev/djs1		Second digital joystick
+		    ...
+  15 block	Sony CDU-31A/CDU-33A CD-ROM
+		  0 = /dev/sonycd	Sony CDU-31a CD-ROM
+
+  16 char	Non-SCSI scanners
+		  0 = /dev/gs4500	Genius 4500 handheld scanner
+
+  16 block	GoldStar CD-ROM
+		  0 = /dev/gscd		GoldStar CD-ROM
+
+  17 char	OBSOLETE (was Chase serial card)
+		  0 = /dev/ttyH0	First Chase port
+		  1 = /dev/ttyH1	Second Chase port
+		    ...
+  17 block	Optics Storage CD-ROM
+		  0 = /dev/optcd	Optics Storage CD-ROM
+
+  18 char	OBSOLETE (was Chase serial card - alternate devices)
+		  0 = /dev/cuh0		Callout device for ttyH0
+		  1 = /dev/cuh1		Callout device for ttyH1
+		    ...
+  18 block	Sanyo CD-ROM
+		  0 = /dev/sjcd		Sanyo CD-ROM
+
+  19 char	Cyclades serial card
+		  0 = /dev/ttyC0	First Cyclades port
+		    ...
+		 31 = /dev/ttyC31	32nd Cyclades port
+
+  19 block	"Double" compressed disk
+		  0 = /dev/double0	First compressed disk
+		    ...
+		  7 = /dev/double7	Eighth compressed disk
+		128 = /dev/cdouble0	Mirror of first compressed disk
+		    ...
+		135 = /dev/cdouble7	Mirror of eighth compressed disk
+
+		See the Double documentation for the meaning of the
+		mirror devices.
+
+  20 char	Cyclades serial card - alternate devices
+		  0 = /dev/cub0		Callout device for ttyC0
+		    ...
+		 31 = /dev/cub31	Callout device for ttyC31
+
+  20 block	Hitachi CD-ROM (under development)
+		  0 = /dev/hitcd	Hitachi CD-ROM
+
+  21 char	Generic SCSI access
+		  0 = /dev/sg0		First generic SCSI device
+		  1 = /dev/sg1		Second generic SCSI device
+		    ...
+
+		Most distributions name these /dev/sga, /dev/sgb...;
+		this sets an unnecessary limit of 26 SCSI devices in
+		the system and is counter to standard Linux
+		device-naming practice.
+
+  21 block	Acorn MFM hard drive interface
+		  0 = /dev/mfma		First MFM drive whole disk
+		 64 = /dev/mfmb		Second MFM drive whole disk
+
+		This device is used on the ARM-based Acorn RiscPC.
+		Partitions are handled the same way as for IDE disks
+		(see major number 3).
+
+  22 char	Digiboard serial card
+		  0 = /dev/ttyD0	First Digiboard port
+		  1 = /dev/ttyD1	Second Digiboard port
+		    ...
+  22 block	Second IDE hard disk/CD-ROM interface
+		  0 = /dev/hdc		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdd		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  23 char	Digiboard serial card - alternate devices
+		  0 = /dev/cud0		Callout device for ttyD0
+		  1 = /dev/cud1		Callout device for ttyD1
+		      ...
+  23 block	Mitsumi proprietary CD-ROM
+		  0 = /dev/mcd		Mitsumi CD-ROM
+
+  24 char	Stallion serial card
+		  0 = /dev/ttyE0	Stallion port 0 card 0
+		  1 = /dev/ttyE1	Stallion port 1 card 0
+		    ...
+		 64 = /dev/ttyE64	Stallion port 0 card 1
+		 65 = /dev/ttyE65	Stallion port 1 card 1
+		      ...
+		128 = /dev/ttyE128	Stallion port 0 card 2
+		129 = /dev/ttyE129	Stallion port 1 card 2
+		    ...
+		192 = /dev/ttyE192	Stallion port 0 card 3
+		193 = /dev/ttyE193	Stallion port 1 card 3
+		    ...
+  24 block	Sony CDU-535 CD-ROM
+		  0 = /dev/cdu535	Sony CDU-535 CD-ROM
+
+  25 char	Stallion serial card - alternate devices
+		  0 = /dev/cue0		Callout device for ttyE0
+		  1 = /dev/cue1		Callout device for ttyE1
+		    ...
+		 64 = /dev/cue64	Callout device for ttyE64
+		 65 = /dev/cue65	Callout device for ttyE65
+		    ...
+		128 = /dev/cue128	Callout device for ttyE128
+		129 = /dev/cue129	Callout device for ttyE129
+		    ...
+		192 = /dev/cue192	Callout device for ttyE192
+		193 = /dev/cue193	Callout device for ttyE193
+		      ...
+  25 block	First Matsushita (Panasonic/SoundBlaster) CD-ROM
+		  0 = /dev/sbpcd0	Panasonic CD-ROM controller 0 unit 0
+		  1 = /dev/sbpcd1	Panasonic CD-ROM controller 0 unit 1
+		  2 = /dev/sbpcd2	Panasonic CD-ROM controller 0 unit 2
+		  3 = /dev/sbpcd3	Panasonic CD-ROM controller 0 unit 3
+
+  26 char
+
+  26 block	Second Matsushita (Panasonic/SoundBlaster) CD-ROM
+		  0 = /dev/sbpcd4	Panasonic CD-ROM controller 1 unit 0
+		  1 = /dev/sbpcd5	Panasonic CD-ROM controller 1 unit 1
+		  2 = /dev/sbpcd6	Panasonic CD-ROM controller 1 unit 2
+		  3 = /dev/sbpcd7	Panasonic CD-ROM controller 1 unit 3
+
+  27 char	QIC-117 tape
+		  0 = /dev/qft0		Unit 0, rewind-on-close
+		  1 = /dev/qft1		Unit 1, rewind-on-close
+		  2 = /dev/qft2		Unit 2, rewind-on-close
+		  3 = /dev/qft3		Unit 3, rewind-on-close
+		  4 = /dev/nqft0	Unit 0, no rewind-on-close
+		  5 = /dev/nqft1	Unit 1, no rewind-on-close
+		  6 = /dev/nqft2	Unit 2, no rewind-on-close
+		  7 = /dev/nqft3	Unit 3, no rewind-on-close
+		 16 = /dev/zqft0	Unit 0, rewind-on-close, compression
+		 17 = /dev/zqft1	Unit 1, rewind-on-close, compression
+		 18 = /dev/zqft2	Unit 2, rewind-on-close, compression
+		 19 = /dev/zqft3	Unit 3, rewind-on-close, compression
+		 20 = /dev/nzqft0	Unit 0, no rewind-on-close, compression
+		 21 = /dev/nzqft1	Unit 1, no rewind-on-close, compression
+		 22 = /dev/nzqft2	Unit 2, no rewind-on-close, compression
+		 23 = /dev/nzqft3	Unit 3, no rewind-on-close, compression
+		 32 = /dev/rawqft0	Unit 0, rewind-on-close, no file marks
+		 33 = /dev/rawqft1	Unit 1, rewind-on-close, no file marks
+		 34 = /dev/rawqft2	Unit 2, rewind-on-close, no file marks
+		 35 = /dev/rawqft3	Unit 3, rewind-on-close, no file marks
+		 36 = /dev/nrawqft0	Unit 0, no rewind-on-close, no file marks
+		 37 = /dev/nrawqft1	Unit 1, no rewind-on-close, no file marks
+		 38 = /dev/nrawqft2	Unit 2, no rewind-on-close, no file marks
+		 39 = /dev/nrawqft3	Unit 3, no rewind-on-close, no file marks
+
+  27 block	Third Matsushita (Panasonic/SoundBlaster) CD-ROM
+		  0 = /dev/sbpcd8	Panasonic CD-ROM controller 2 unit 0
+		  1 = /dev/sbpcd9	Panasonic CD-ROM controller 2 unit 1
+		  2 = /dev/sbpcd10	Panasonic CD-ROM controller 2 unit 2
+		  3 = /dev/sbpcd11	Panasonic CD-ROM controller 2 unit 3
+
+  28 char	Stallion serial card - card programming
+		  0 = /dev/staliomem0	First Stallion card I/O memory
+		  1 = /dev/staliomem1	Second Stallion card I/O memory
+		  2 = /dev/staliomem2	Third Stallion card I/O memory
+		  3 = /dev/staliomem3	Fourth Stallion card I/O memory
+
+  28 char	Atari SLM ACSI laser printer (68k/Atari)
+		  0 = /dev/slm0		First SLM laser printer
+		  1 = /dev/slm1		Second SLM laser printer
+		    ...
+  28 block	Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
+		  0 = /dev/sbpcd12	Panasonic CD-ROM controller 3 unit 0
+		  1 = /dev/sbpcd13	Panasonic CD-ROM controller 3 unit 1
+		  2 = /dev/sbpcd14	Panasonic CD-ROM controller 3 unit 2
+		  3 = /dev/sbpcd15	Panasonic CD-ROM controller 3 unit 3
+
+  28 block	ACSI disk (68k/Atari)
+		  0 = /dev/ada		First ACSI disk whole disk
+		 16 = /dev/adb		Second ACSI disk whole disk
+		 32 = /dev/adc		Third ACSI disk whole disk
+		    ...
+		240 = /dev/adp		16th ACSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15, like SCSI.
+
+  29 char	Universal frame buffer
+		  0 = /dev/fb0		First frame buffer
+		  1 = /dev/fb1		Second frame buffer
+		    ...
+		 31 = /dev/fb31		32nd frame buffer
+
+  29 block	Aztech/Orchid/Okano/Wearnes CD-ROM
+		  0 = /dev/aztcd	Aztech CD-ROM
+
+  30 char	iBCS-2 compatibility devices
+		  0 = /dev/socksys	Socket access
+		  1 = /dev/spx		SVR3 local X interface
+		 32 = /dev/inet/ip	Network access
+		 33 = /dev/inet/icmp
+		 34 = /dev/inet/ggp
+		 35 = /dev/inet/ipip
+		 36 = /dev/inet/tcp
+		 37 = /dev/inet/egp
+		 38 = /dev/inet/pup
+		 39 = /dev/inet/udp
+		 40 = /dev/inet/idp
+		 41 = /dev/inet/rawip
+
+		Additionally, iBCS-2 requires the following links:
+
+		/dev/ip -> /dev/inet/ip
+		/dev/icmp -> /dev/inet/icmp
+		/dev/ggp -> /dev/inet/ggp
+		/dev/ipip -> /dev/inet/ipip
+		/dev/tcp -> /dev/inet/tcp
+		/dev/egp -> /dev/inet/egp
+		/dev/pup -> /dev/inet/pup
+		/dev/udp -> /dev/inet/udp
+		/dev/idp -> /dev/inet/idp
+		/dev/rawip -> /dev/inet/rawip
+		/dev/inet/arp -> /dev/inet/udp
+		/dev/inet/rip -> /dev/inet/udp
+		/dev/nfsd -> /dev/socksys
+		/dev/X0R -> /dev/null (? apparently not required ?)
+
+  30 block	Philips LMS CM-205 CD-ROM
+		  0 = /dev/cm205cd	Philips LMS CM-205 CD-ROM
+
+		/dev/lmscd is an older name for this device.  This
+		driver does not work with the CM-205MS CD-ROM.
+
+  31 char	MPU-401 MIDI
+		  0 = /dev/mpu401data	MPU-401 data port
+		  1 = /dev/mpu401stat	MPU-401 status port
+
+  31 block	ROM/flash memory card
+		  0 = /dev/rom0		First ROM card (rw)
+		      ...
+		  7 = /dev/rom7		Eighth ROM card (rw)
+		  8 = /dev/rrom0	First ROM card (ro)
+		    ...
+		 15 = /dev/rrom7	Eighth ROM card (ro)
+		 16 = /dev/flash0	First flash memory card (rw)
+		    ...
+		 23 = /dev/flash7	Eighth flash memory card (rw)
+		 24 = /dev/rflash0	First flash memory card (ro)
+		    ...
+		 31 = /dev/rflash7	Eighth flash memory card (ro)
+
+		The read-write (rw) devices support back-caching
+		written data in RAM, as well as writing to flash RAM
+		devices.  The read-only devices (ro) support reading
+		only.
+
+  32 char	Specialix serial card
+		  0 = /dev/ttyX0	First Specialix port
+		  1 = /dev/ttyX1	Second Specialix port
+		    ...
+  32 block	Philips LMS CM-206 CD-ROM
+		  0 = /dev/cm206cd	Philips LMS CM-206 CD-ROM
+
+  33 char	Specialix serial card - alternate devices
+		  0 = /dev/cux0		Callout device for ttyX0
+		  1 = /dev/cux1		Callout device for ttyX1
+		    ...
+  33 block	Third IDE hard disk/CD-ROM interface
+		  0 = /dev/hde		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdf		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  34 char	Z8530 HDLC driver
+		  0 = /dev/scc0		First Z8530, first port
+		  1 = /dev/scc1		First Z8530, second port
+		  2 = /dev/scc2		Second Z8530, first port
+		  3 = /dev/scc3		Second Z8530, second port
+		    ...
+
+		In a previous version these devices were named
+		/dev/sc1 for /dev/scc0, /dev/sc2 for /dev/scc1, and so
+		on.
+
+  34 block	Fourth IDE hard disk/CD-ROM interface
+		  0 = /dev/hdg		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdh		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  35 char	tclmidi MIDI driver
+		  0 = /dev/midi0	First MIDI port, kernel timed
+		  1 = /dev/midi1	Second MIDI port, kernel timed
+		  2 = /dev/midi2	Third MIDI port, kernel timed
+		  3 = /dev/midi3	Fourth MIDI port, kernel timed
+		 64 = /dev/rmidi0	First MIDI port, untimed
+		 65 = /dev/rmidi1	Second MIDI port, untimed
+		 66 = /dev/rmidi2	Third MIDI port, untimed
+		 67 = /dev/rmidi3	Fourth MIDI port, untimed
+		128 = /dev/smpte0	First MIDI port, SMPTE timed
+		129 = /dev/smpte1	Second MIDI port, SMPTE timed
+		130 = /dev/smpte2	Third MIDI port, SMPTE timed
+		131 = /dev/smpte3	Fourth MIDI port, SMPTE timed
+
+  35 block	Slow memory ramdisk
+		  0 = /dev/slram	Slow memory ramdisk
+
+  36 char	Netlink support
+		  0 = /dev/route	Routing, device updates, kernel to user
+		  1 = /dev/skip		enSKIP security cache control
+		  3 = /dev/fwmonitor	Firewall packet copies
+		 16 = /dev/tap0		First Ethertap device
+		    ...
+		 31 = /dev/tap15	16th Ethertap device
+
+  36 block	OBSOLETE (was MCA ESDI hard disk)
+
+  37 char	IDE tape
+		  0 = /dev/ht0		First IDE tape
+		  1 = /dev/ht1		Second IDE tape
+		    ...
+		128 = /dev/nht0		First IDE tape, no rewind-on-close
+		129 = /dev/nht1		Second IDE tape, no rewind-on-close
+		    ...
+
+		Currently, only one IDE tape drive is supported.
+
+  37 block	Zorro II ramdisk
+		  0 = /dev/z2ram	Zorro II ramdisk
+
+  38 char	Myricom PCI Myrinet board
+		  0 = /dev/mlanai0	First Myrinet board
+		  1 = /dev/mlanai1	Second Myrinet board
+		    ...
+
+		This device is used for status query, board control
+		and "user level packet I/O."  This board is also
+		accessible as a standard networking "eth" device.
+
+  38 block	OBSOLETE (was Linux/AP+)
+
+  39 char	ML-16P experimental I/O board
+		  0 = /dev/ml16pa-a0	First card, first analog channel
+		  1 = /dev/ml16pa-a1	First card, second analog channel
+		    ...
+		 15 = /dev/ml16pa-a15	First card, 16th analog channel
+		 16 = /dev/ml16pa-d	First card, digital lines
+		 17 = /dev/ml16pa-c0	First card, first counter/timer
+		 18 = /dev/ml16pa-c1	First card, second counter/timer
+		 19 = /dev/ml16pa-c2	First card, third counter/timer
+		 32 = /dev/ml16pb-a0	Second card, first analog channel
+		 33 = /dev/ml16pb-a1	Second card, second analog channel
+		    ...
+		 47 = /dev/ml16pb-a15	Second card, 16th analog channel
+		 48 = /dev/ml16pb-d	Second card, digital lines
+		 49 = /dev/ml16pb-c0	Second card, first counter/timer
+		 50 = /dev/ml16pb-c1	Second card, second counter/timer
+		 51 = /dev/ml16pb-c2	Second card, third counter/timer
+		      ...
+  39 block
+
+  40 char
+
+  40 block
+
+  41 char	Yet Another Micro Monitor
+		  0 = /dev/yamm		Yet Another Micro Monitor
+
+  41 block
+
+  42 char	Demo/sample use
+
+  42 block	Demo/sample use
+
+		This number is intended for use in sample code, as
+		well as a general "example" device number.  It
+		should never be used for a device driver that is being
+		distributed; either obtain an official number or use
+		the local/experimental range.  The sudden addition or
+		removal of a driver with this number should not cause
+		ill effects to the system (bugs excepted.)
+
+		IN PARTICULAR, ANY DISTRIBUTION WHICH CONTAINS A
+		DEVICE DRIVER USING MAJOR NUMBER 42 IS NONCOMPLIANT.
+
+  43 char	isdn4linux virtual modem
+		  0 = /dev/ttyI0	First virtual modem
+		    ...
+		 63 = /dev/ttyI63	64th virtual modem
+
+  43 block	Network block devices
+		  0 = /dev/nb0		First network block device
+		  1 = /dev/nb1		Second network block device
+		    ...
+
+		Network Block Device is somehow similar to loopback
+		devices: If you read from it, it sends packet across
+		network asking server for data. If you write to it, it
+		sends packet telling server to write. It could be used
+		to mounting filesystems over the net, swapping over
+		the net, implementing block device in userland etc.
+
+  44 char	isdn4linux virtual modem - alternate devices
+		  0 = /dev/cui0		Callout device for ttyI0
+		    ...
+		 63 = /dev/cui63	Callout device for ttyI63
+
+  44 block	Flash Translation Layer (FTL) filesystems
+		  0 = /dev/ftla		FTL on first Memory Technology Device
+		 16 = /dev/ftlb		FTL on second Memory Technology Device
+		 32 = /dev/ftlc		FTL on third Memory Technology Device
+		    ...
+		240 = /dev/ftlp		FTL on 16th Memory Technology Device
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the partition
+		limit is 15 rather than 63 per disk (same as SCSI.)
+
+  45 char	isdn4linux ISDN BRI driver
+		  0 = /dev/isdn0	First virtual B channel raw data
+		    ...
+		 63 = /dev/isdn63	64th virtual B channel raw data
+		 64 = /dev/isdnctrl0	First channel control/debug
+		    ...
+		127 = /dev/isdnctrl63	64th channel control/debug
+
+		128 = /dev/ippp0	First SyncPPP device
+		    ...
+		191 = /dev/ippp63	64th SyncPPP device
+
+		255 = /dev/isdninfo	ISDN monitor interface
+
+  45 block	Parallel port IDE disk devices
+		  0 = /dev/pda		First parallel port IDE disk
+		 16 = /dev/pdb		Second parallel port IDE disk
+		 32 = /dev/pdc		Third parallel port IDE disk
+		 48 = /dev/pdd		Fourth parallel port IDE disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the partition
+		limit is 15 rather than 63 per disk.
+
+  46 char	Comtrol Rocketport serial card
+		  0 = /dev/ttyR0	First Rocketport port
+		  1 = /dev/ttyR1	Second Rocketport port
+		    ...
+  46 block	Parallel port ATAPI CD-ROM devices
+		  0 = /dev/pcd0		First parallel port ATAPI CD-ROM
+		  1 = /dev/pcd1		Second parallel port ATAPI CD-ROM
+		  2 = /dev/pcd2		Third parallel port ATAPI CD-ROM
+		  3 = /dev/pcd3		Fourth parallel port ATAPI CD-ROM
+
+  47 char	Comtrol Rocketport serial card - alternate devices
+		  0 = /dev/cur0		Callout device for ttyR0
+		  1 = /dev/cur1		Callout device for ttyR1
+		    ...
+  47 block	Parallel port ATAPI disk devices
+		  0 = /dev/pf0		First parallel port ATAPI disk
+		  1 = /dev/pf1		Second parallel port ATAPI disk
+		  2 = /dev/pf2		Third parallel port ATAPI disk
+		  3 = /dev/pf3		Fourth parallel port ATAPI disk
+
+		This driver is intended for floppy disks and similar
+		devices and hence does not support partitioning.
+
+  48 char	SDL RISCom serial card
+		  0 = /dev/ttyL0	First RISCom port
+		  1 = /dev/ttyL1	Second RISCom port
+		    ...
+  48 block	Mylex DAC960 PCI RAID controller; first controller
+		  0 = /dev/rd/c0d0	First disk, whole disk
+		  8 = /dev/rd/c0d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c0d31	32nd disk, whole disk
+
+		For partitions add:
+		  0 = /dev/rd/c?d?	Whole disk
+		  1 = /dev/rd/c?d?p1	First partition
+		    ...
+		  7 = /dev/rd/c?d?p7	Seventh partition
+
+  49 char	SDL RISCom serial card - alternate devices
+		  0 = /dev/cul0		Callout device for ttyL0
+		  1 = /dev/cul1		Callout device for ttyL1
+		    ...
+  49 block	Mylex DAC960 PCI RAID controller; second controller
+		  0 = /dev/rd/c1d0	First disk, whole disk
+		  8 = /dev/rd/c1d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c1d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+  50 char	Reserved for GLINT
+
+  50 block	Mylex DAC960 PCI RAID controller; third controller
+		  0 = /dev/rd/c2d0	First disk, whole disk
+		  8 = /dev/rd/c2d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c2d31	32nd disk, whole disk
+
+  51 char	Baycom radio modem OR Radio Tech BIM-XXX-RS232 radio modem
+		  0 = /dev/bc0		First Baycom radio modem
+		  1 = /dev/bc1		Second Baycom radio modem
+		    ...
+  51 block	Mylex DAC960 PCI RAID controller; fourth controller
+		  0 = /dev/rd/c3d0	First disk, whole disk
+		  8 = /dev/rd/c3d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c3d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+  52 char	Spellcaster DataComm/BRI ISDN card
+		  0 = /dev/dcbri0	First DataComm card
+		  1 = /dev/dcbri1	Second DataComm card
+		  2 = /dev/dcbri2	Third DataComm card
+		  3 = /dev/dcbri3	Fourth DataComm card
+
+  52 block	Mylex DAC960 PCI RAID controller; fifth controller
+		  0 = /dev/rd/c4d0	First disk, whole disk
+		  8 = /dev/rd/c4d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c4d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+  53 char	BDM interface for remote debugging MC683xx microcontrollers
+		  0 = /dev/pd_bdm0	PD BDM interface on lp0
+		  1 = /dev/pd_bdm1	PD BDM interface on lp1
+		  2 = /dev/pd_bdm2	PD BDM interface on lp2
+		  4 = /dev/icd_bdm0	ICD BDM interface on lp0
+		  5 = /dev/icd_bdm1	ICD BDM interface on lp1
+		  6 = /dev/icd_bdm2	ICD BDM interface on lp2
+
+		This device is used for the interfacing to the MC683xx
+		microcontrollers via Background Debug Mode by use of a
+		Parallel Port interface. PD is the Motorola Public
+		Domain Interface and ICD is the commercial interface
+		by P&E.
+
+  53 block	Mylex DAC960 PCI RAID controller; sixth controller
+		  0 = /dev/rd/c5d0	First disk, whole disk
+		  8 = /dev/rd/c5d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c5d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+  54 char	Electrocardiognosis Holter serial card
+		  0 = /dev/holter0	First Holter port
+		  1 = /dev/holter1	Second Holter port
+		  2 = /dev/holter2	Third Holter port
+
+		A custom serial card used by Electrocardiognosis SRL
+		<mseritan@ottonel.pub.ro> to transfer data from Holter
+		24-hour heart monitoring equipment.
+
+  54 block	Mylex DAC960 PCI RAID controller; seventh controller
+		  0 = /dev/rd/c6d0	First disk, whole disk
+		  8 = /dev/rd/c6d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c6d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+  55 char	DSP56001 digital signal processor
+		  0 = /dev/dsp56k	First DSP56001
+
+  55 block	Mylex DAC960 PCI RAID controller; eighth controller
+		  0 = /dev/rd/c7d0	First disk, whole disk
+		  8 = /dev/rd/c7d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c7d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+  56 char	Apple Desktop Bus
+		  0 = /dev/adb		ADB bus control
+
+		Additional devices will be added to this number, all
+		starting with /dev/adb.
+
+  56 block	Fifth IDE hard disk/CD-ROM interface
+		  0 = /dev/hdi		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdj		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  57 char	Hayes ESP serial card
+		  0 = /dev/ttyP0	First ESP port
+		  1 = /dev/ttyP1	Second ESP port
+		    ...
+
+  57 block	Sixth IDE hard disk/CD-ROM interface
+		  0 = /dev/hdk		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdl		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  58 char	Hayes ESP serial card - alternate devices
+		  0 = /dev/cup0		Callout device for ttyP0
+		  1 = /dev/cup1		Callout device for ttyP1
+		    ...
+
+  58 block	Reserved for logical volume manager
+
+  59 char	sf firewall package
+		  0 = /dev/firewall	Communication with sf kernel module
+
+  59 block	Generic PDA filesystem device
+		  0 = /dev/pda0		First PDA device
+		  1 = /dev/pda1		Second PDA device
+		    ...
+
+		The pda devices are used to mount filesystems on
+		remote pda's (basically slow handheld machines with
+		proprietary OS's and limited memory and storage
+		running small fs translation drivers) through serial /
+		IRDA / parallel links.
+
+		NAMING CONFLICT -- PROPOSED REVISED NAME /dev/rpda0 etc
+
+  60-63 char	LOCAL/EXPERIMENTAL USE
+
+  60-63 block	LOCAL/EXPERIMENTAL USE
+		Allocated for local/experimental use.  For devices not
+		assigned official numbers, these ranges should be
+		used in order to avoid conflicting with future assignments.
+
+  64 char	ENskip kernel encryption package
+		  0 = /dev/enskip	Communication with ENskip kernel module
+
+  64 block	Scramdisk/DriveCrypt encrypted devices
+		  0 = /dev/scramdisk/master    Master node for ioctls
+		  1 = /dev/scramdisk/1         First encrypted device
+		  2 = /dev/scramdisk/2         Second encrypted device
+		  ...
+		255 = /dev/scramdisk/255       255th encrypted device
+
+		The filename of the encrypted container and the passwords
+		are sent via ioctls (using the sdmount tool) to the master
+		node which then activates them via one of the
+		/dev/scramdisk/x nodes for loop mounting (all handled
+		through the sdmount tool).
+
+		Requested by: andy@scramdisklinux.org
+
+  65 char	Sundance "plink" Transputer boards (obsolete, unused)
+		  0 = /dev/plink0	First plink device
+		  1 = /dev/plink1	Second plink device
+		  2 = /dev/plink2	Third plink device
+		  3 = /dev/plink3	Fourth plink device
+		 64 = /dev/rplink0	First plink device, raw
+		 65 = /dev/rplink1	Second plink device, raw
+		 66 = /dev/rplink2	Third plink device, raw
+		 67 = /dev/rplink3	Fourth plink device, raw
+		128 = /dev/plink0d	First plink device, debug
+		129 = /dev/plink1d	Second plink device, debug
+		130 = /dev/plink2d	Third plink device, debug
+		131 = /dev/plink3d	Fourth plink device, debug
+		192 = /dev/rplink0d	First plink device, raw, debug
+		193 = /dev/rplink1d	Second plink device, raw, debug
+		194 = /dev/rplink2d	Third plink device, raw, debug
+		195 = /dev/rplink3d	Fourth plink device, raw, debug
+
+		This is a commercial driver; contact James Howes
+		<jth@prosig.demon.co.uk> for information.
+
+  65 block	SCSI disk devices (16-31)
+		  0 = /dev/sdq		17th SCSI disk whole disk
+		 16 = /dev/sdr		18th SCSI disk whole disk
+		 32 = /dev/sds		19th SCSI disk whole disk
+		    ...
+		240 = /dev/sdaf		32nd SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  66 char	YARC PowerPC PCI coprocessor card
+		  0 = /dev/yppcpci0	First YARC card
+		  1 = /dev/yppcpci1	Second YARC card
+		    ...
+
+  66 block	SCSI disk devices (32-47)
+		  0 = /dev/sdag		33th SCSI disk whole disk
+		 16 = /dev/sdah		34th SCSI disk whole disk
+		 32 = /dev/sdai		35th SCSI disk whole disk
+		    ...
+		240 = /dev/sdav		48nd SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  67 char	Coda network file system
+		  0 = /dev/cfs0		Coda cache manager
+
+		See http://www.coda.cs.cmu.edu for information about Coda.
+
+  67 block	SCSI disk devices (48-63)
+		  0 = /dev/sdaw		49th SCSI disk whole disk
+		 16 = /dev/sdax		50th SCSI disk whole disk
+		 32 = /dev/sday		51st SCSI disk whole disk
+		    ...
+		240 = /dev/sdbl		64th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  68 char	CAPI 2.0 interface
+		  0 = /dev/capi20	Control device
+		  1 = /dev/capi20.00	First CAPI 2.0 application
+		  2 = /dev/capi20.01	Second CAPI 2.0 application
+		    ...
+		 20 = /dev/capi20.19	19th CAPI 2.0 application
+
+		ISDN CAPI 2.0 driver for use with CAPI 2.0
+		applications; currently supports the AVM B1 card.
+
+  68 block	SCSI disk devices (64-79)
+		  0 = /dev/sdbm		65th SCSI disk whole disk
+		 16 = /dev/sdbn		66th SCSI disk whole disk
+		 32 = /dev/sdbo		67th SCSI disk whole disk
+		    ...
+		240 = /dev/sdcb		80th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  69 char	MA16 numeric accelerator card
+		  0 = /dev/ma16		Board memory access
+
+  69 block	SCSI disk devices (80-95)
+		  0 = /dev/sdcc		81st SCSI disk whole disk
+		 16 = /dev/sdcd		82nd SCSI disk whole disk
+		 32 = /dev/sdce		83th SCSI disk whole disk
+		    ...
+		240 = /dev/sdcr		96th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  70 char	SpellCaster Protocol Services Interface
+		  0 = /dev/apscfg	Configuration interface
+		  1 = /dev/apsauth	Authentication interface
+		  2 = /dev/apslog	Logging interface
+		  3 = /dev/apsdbg	Debugging interface
+		 64 = /dev/apsisdn	ISDN command interface
+		 65 = /dev/apsasync	Async command interface
+		128 = /dev/apsmon	Monitor interface
+
+  70 block	SCSI disk devices (96-111)
+		  0 = /dev/sdcs		97th SCSI disk whole disk
+		 16 = /dev/sdct		98th SCSI disk whole disk
+		 32 = /dev/sdcu		99th SCSI disk whole disk
+		    ...
+		240 = /dev/sddh		112nd SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  71 char	Computone IntelliPort II serial card
+		  0 = /dev/ttyF0	IntelliPort II board 0, port 0
+		  1 = /dev/ttyF1	IntelliPort II board 0, port 1
+		    ...
+		 63 = /dev/ttyF63	IntelliPort II board 0, port 63
+		 64 = /dev/ttyF64	IntelliPort II board 1, port 0
+		 65 = /dev/ttyF65	IntelliPort II board 1, port 1
+		    ...
+		127 = /dev/ttyF127	IntelliPort II board 1, port 63
+		128 = /dev/ttyF128	IntelliPort II board 2, port 0
+		129 = /dev/ttyF129	IntelliPort II board 2, port 1
+		    ...
+		191 = /dev/ttyF191	IntelliPort II board 2, port 63
+		192 = /dev/ttyF192	IntelliPort II board 3, port 0
+		193 = /dev/ttyF193	IntelliPort II board 3, port 1
+		    ...
+		255 = /dev/ttyF255	IntelliPort II board 3, port 63
+
+  71 block	SCSI disk devices (112-127)
+		  0 = /dev/sddi		113th SCSI disk whole disk
+		 16 = /dev/sddj		114th SCSI disk whole disk
+		 32 = /dev/sddk		115th SCSI disk whole disk
+		    ...
+		240 = /dev/sddx		128th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  72 char	Computone IntelliPort II serial card - alternate devices
+		  0 = /dev/cuf0		Callout device for ttyF0
+		  1 = /dev/cuf1		Callout device for ttyF1
+		    ...
+		 63 = /dev/cuf63	Callout device for ttyF63
+		 64 = /dev/cuf64	Callout device for ttyF64
+		 65 = /dev/cuf65	Callout device for ttyF65
+		    ...
+		127 = /dev/cuf127	Callout device for ttyF127
+		128 = /dev/cuf128	Callout device for ttyF128
+		129 = /dev/cuf129	Callout device for ttyF129
+		    ...
+		191 = /dev/cuf191	Callout device for ttyF191
+		192 = /dev/cuf192	Callout device for ttyF192
+		193 = /dev/cuf193	Callout device for ttyF193
+		    ...
+		255 = /dev/cuf255	Callout device for ttyF255
+
+  72 block	Compaq Intelligent Drive Array, first controller
+		  0 = /dev/ida/c0d0	First logical drive whole disk
+		 16 = /dev/ida/c0d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c0d15	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+  73 char	Computone IntelliPort II serial card - control devices
+		  0 = /dev/ip2ipl0	Loadware device for board 0
+		  1 = /dev/ip2stat0	Status device for board 0
+		  4 = /dev/ip2ipl1	Loadware device for board 1
+		  5 = /dev/ip2stat1	Status device for board 1
+		  8 = /dev/ip2ipl2	Loadware device for board 2
+		  9 = /dev/ip2stat2	Status device for board 2
+		 12 = /dev/ip2ipl3	Loadware device for board 3
+		 13 = /dev/ip2stat3	Status device for board 3
+
+  73 block	Compaq Intelligent Drive Array, second controller
+		  0 = /dev/ida/c1d0	First logical drive whole disk
+		 16 = /dev/ida/c1d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c1d15	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+  74 char	SCI bridge
+		  0 = /dev/SCI/0	SCI device 0
+		  1 = /dev/SCI/1	SCI device 1
+		    ...
+
+		Currently for Dolphin Interconnect Solutions' PCI-SCI
+		bridge.
+
+  74 block	Compaq Intelligent Drive Array, third controller
+		  0 = /dev/ida/c2d0	First logical drive whole disk
+		 16 = /dev/ida/c2d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c2d15	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+  75 char	Specialix IO8+ serial card
+		  0 = /dev/ttyW0	First IO8+ port, first card
+		  1 = /dev/ttyW1	Second IO8+ port, first card
+		    ...
+		  8 = /dev/ttyW8	First IO8+ port, second card
+		    ...
+
+  75 block	Compaq Intelligent Drive Array, fourth controller
+		  0 = /dev/ida/c3d0	First logical drive whole disk
+		 16 = /dev/ida/c3d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c3d15	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+  76 char	Specialix IO8+ serial card - alternate devices
+		  0 = /dev/cuw0		Callout device for ttyW0
+		  1 = /dev/cuw1		Callout device for ttyW1
+		    ...
+		  8 = /dev/cuw8		Callout device for ttyW8
+		    ...
+
+  76 block	Compaq Intelligent Drive Array, fifth controller
+		  0 = /dev/ida/c4d0	First logical drive whole disk
+		 16 = /dev/ida/c4d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c4d15	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+
+  77 char	ComScire Quantum Noise Generator
+		  0 = /dev/qng		ComScire Quantum Noise Generator
+
+  77 block	Compaq Intelligent Drive Array, sixth controller
+		  0 = /dev/ida/c5d0	First logical drive whole disk
+		 16 = /dev/ida/c5d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c5d15	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+  78 char	PAM Software's multimodem boards
+		  0 = /dev/ttyM0	First PAM modem
+		  1 = /dev/ttyM1	Second PAM modem
+		    ...
+
+  78 block	Compaq Intelligent Drive Array, seventh controller
+		  0 = /dev/ida/c6d0	First logical drive whole disk
+		 16 = /dev/ida/c6d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c6d15	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+  79 char	PAM Software's multimodem boards - alternate devices
+		  0 = /dev/cum0		Callout device for ttyM0
+		  1 = /dev/cum1		Callout device for ttyM1
+		    ...
+
+  79 block	Compaq Intelligent Drive Array, eighth controller
+		  0 = /dev/ida/c7d0	First logical drive whole disk
+		 16 = /dev/ida/c7d1	Second logical drive whole disk
+		    ...
+		240 = /dev/ida/c715	16th logical drive whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+  80 char	Photometrics AT200 CCD camera
+		  0 = /dev/at200	Photometrics AT200 CCD camera
+
+  80 block	I2O hard disk
+		  0 = /dev/i2o/hda	First I2O hard disk, whole disk
+		 16 = /dev/i2o/hdb	Second I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hdp	16th I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  81 char	video4linux
+		  0 = /dev/video0	Video capture/overlay device
+		    ...
+		 63 = /dev/video63	Video capture/overlay device
+		 64 = /dev/radio0	Radio device
+		    ...
+		127 = /dev/radio63	Radio device
+		128 = /dev/swradio0	Software Defined Radio device
+		    ...
+		191 = /dev/swradio63	Software Defined Radio device
+		224 = /dev/vbi0		Vertical blank interrupt
+		    ...
+		255 = /dev/vbi31	Vertical blank interrupt
+
+		Minor numbers are allocated dynamically unless
+		CONFIG_VIDEO_FIXED_MINOR_RANGES (default n)
+		configuration option is set.
+
+  81 block	I2O hard disk
+		  0 = /dev/i2o/hdq	17th I2O hard disk, whole disk
+		 16 = /dev/i2o/hdr	18th I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hdaf	32nd I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  82 char	WiNRADiO communications receiver card
+		  0 = /dev/winradio0	First WiNRADiO card
+		  1 = /dev/winradio1	Second WiNRADiO card
+		    ...
+
+		The driver and documentation may be obtained from
+		http://www.winradio.com/
+
+  82 block	I2O hard disk
+		  0 = /dev/i2o/hdag	33rd I2O hard disk, whole disk
+		 16 = /dev/i2o/hdah	34th I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hdav	48th I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  83 char	Matrox mga_vid video driver
+		 0 = /dev/mga_vid0	1st video card
+		 1 = /dev/mga_vid1	2nd video card
+		 2 = /dev/mga_vid2	3rd video card
+		  ...
+		15 = /dev/mga_vid15	16th video card
+
+  83 block	I2O hard disk
+		  0 = /dev/i2o/hdaw	49th I2O hard disk, whole disk
+		 16 = /dev/i2o/hdax	50th I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hdbl	64th I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  84 char	Ikon 1011[57] Versatec Greensheet Interface
+		  0 = /dev/ihcp0	First Greensheet port
+		  1 = /dev/ihcp1	Second Greensheet port
+
+  84 block	I2O hard disk
+		  0 = /dev/i2o/hdbm	65th I2O hard disk, whole disk
+		 16 = /dev/i2o/hdbn	66th I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hdcb	80th I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  85 char	Linux/SGI shared memory input queue
+		  0 = /dev/shmiq	Master shared input queue
+		  1 = /dev/qcntl0	First device pushed
+		  2 = /dev/qcntl1	Second device pushed
+		    ...
+
+  85 block	I2O hard disk
+		  0 = /dev/i2o/hdcc	81st I2O hard disk, whole disk
+		 16 = /dev/i2o/hdcd	82nd I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hdcr	96th I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  86 char	SCSI media changer
+		  0 = /dev/sch0		First SCSI media changer
+		  1 = /dev/sch1		Second SCSI media changer
+		    ...
+
+  86 block	I2O hard disk
+		  0 = /dev/i2o/hdcs	97th I2O hard disk, whole disk
+		 16 = /dev/i2o/hdct	98th I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hddh	112th I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  87 char	Sony Control-A1 stereo control bus
+		  0 = /dev/controla0	First device on chain
+		  1 = /dev/controla1	Second device on chain
+		    ...
+
+  87 block	I2O hard disk
+		  0 = /dev/i2o/hddi	113rd I2O hard disk, whole disk
+		 16 = /dev/i2o/hddj	114th I2O hard disk, whole disk
+		    ...
+		240 = /dev/i2o/hddx	128th I2O hard disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  88 char	COMX synchronous serial card
+		  0 = /dev/comx0	COMX channel 0
+		  1 = /dev/comx1	COMX channel 1
+		    ...
+
+  88 block	Seventh IDE hard disk/CD-ROM interface
+		  0 = /dev/hdm		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdn		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  89 char	I2C bus interface
+		  0 = /dev/i2c-0	First I2C adapter
+		  1 = /dev/i2c-1	Second I2C adapter
+		    ...
+
+  89 block	Eighth IDE hard disk/CD-ROM interface
+		  0 = /dev/hdo		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdp		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  90 char	Memory Technology Device (RAM, ROM, Flash)
+		  0 = /dev/mtd0		First MTD (rw)
+		  1 = /dev/mtdr0	First MTD (ro)
+		    ...
+		 30 = /dev/mtd15	16th MTD (rw)
+		 31 = /dev/mtdr15	16th MTD (ro)
+
+  90 block	Ninth IDE hard disk/CD-ROM interface
+		  0 = /dev/hdq		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdr		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  91 char	CAN-Bus devices
+		  0 = /dev/can0		First CAN-Bus controller
+		  1 = /dev/can1		Second CAN-Bus controller
+		    ...
+
+  91 block	Tenth IDE hard disk/CD-ROM interface
+		  0 = /dev/hds		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdt		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+  92 char	Reserved for ith Kommunikationstechnik MIC ISDN card
+
+  92 block	PPDD encrypted disk driver
+		  0 = /dev/ppdd0	First encrypted disk
+		  1 = /dev/ppdd1	Second encrypted disk
+		    ...
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+  93 char
+
+  93 block	NAND Flash Translation Layer filesystem
+		  0 = /dev/nftla	First NFTL layer
+		 16 = /dev/nftlb	Second NFTL layer
+		    ...
+		240 = /dev/nftlp	16th NTFL layer
+
+  94 char
+
+  94 block	IBM S/390 DASD block storage
+		  0 = /dev/dasda First DASD device, major
+		  1 = /dev/dasda1 First DASD device, block 1
+		  2 = /dev/dasda2 First DASD device, block 2
+		  3 = /dev/dasda3 First DASD device, block 3
+		  4 = /dev/dasdb Second DASD device, major
+		  5 = /dev/dasdb1 Second DASD device, block 1
+		  6 = /dev/dasdb2 Second DASD device, block 2
+		  7 = /dev/dasdb3 Second DASD device, block 3
+		    ...
+
+  95 char	IP filter
+		  0 = /dev/ipl		Filter control device/log file
+		  1 = /dev/ipnat	NAT control device/log file
+		  2 = /dev/ipstate	State information log file
+		  3 = /dev/ipauth	Authentication control device/log file
+		    ...
+
+  96 char	Parallel port ATAPI tape devices
+		  0 = /dev/pt0		First parallel port ATAPI tape
+		  1 = /dev/pt1		Second parallel port ATAPI tape
+		    ...
+		128 = /dev/npt0		First p.p. ATAPI tape, no rewind
+		129 = /dev/npt1		Second p.p. ATAPI tape, no rewind
+		    ...
+
+  96 block	Inverse NAND Flash Translation Layer
+		  0 = /dev/inftla First INFTL layer
+		 16 = /dev/inftlb Second INFTL layer
+		    ...
+		240 = /dev/inftlp	16th INTFL layer
+
+  97 char	Parallel port generic ATAPI interface
+		  0 = /dev/pg0		First parallel port ATAPI device
+		  1 = /dev/pg1		Second parallel port ATAPI device
+		  2 = /dev/pg2		Third parallel port ATAPI device
+		  3 = /dev/pg3		Fourth parallel port ATAPI device
+
+		These devices support the same API as the generic SCSI
+		devices.
+
+  98 char	Control and Measurement Device (comedi)
+		  0 = /dev/comedi0	First comedi device
+		  1 = /dev/comedi1	Second comedi device
+		    ...
+
+		See http://stm.lbl.gov/comedi.
+
+  98 block	User-mode virtual block device
+		  0 = /dev/ubda		First user-mode block device
+		 16 = /dev/udbb		Second user-mode block device
+		    ...
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+		This device is used by the user-mode virtual kernel port.
+
+  99 char	Raw parallel ports
+		  0 = /dev/parport0	First parallel port
+		  1 = /dev/parport1	Second parallel port
+		    ...
+
+  99 block	JavaStation flash disk
+		  0 = /dev/jsfd		JavaStation flash disk
+
+ 100 char	Telephony for Linux
+		  0 = /dev/phone0	First telephony device
+		  1 = /dev/phone1	Second telephony device
+		    ...
+
+ 101 char	Motorola DSP 56xxx board
+		  0 = /dev/mdspstat	Status information
+		  1 = /dev/mdsp1	First DSP board I/O controls
+		    ...
+		 16 = /dev/mdsp16	16th DSP board I/O controls
+
+ 101 block	AMI HyperDisk RAID controller
+		  0 = /dev/amiraid/ar0	First array whole disk
+		 16 = /dev/amiraid/ar1	Second array whole disk
+		    ...
+		240 = /dev/amiraid/ar15	16th array whole disk
+
+		For each device, partitions are added as:
+		  0 = /dev/amiraid/ar?	  Whole disk
+		  1 = /dev/amiraid/ar?p1  First partition
+		  2 = /dev/amiraid/ar?p2  Second partition
+		    ...
+		 15 = /dev/amiraid/ar?p15 15th partition
+
+ 102 char
+
+ 102 block	Compressed block device
+		  0 = /dev/cbd/a	First compressed block device, whole device
+		 16 = /dev/cbd/b	Second compressed block device, whole device
+		    ...
+		240 = /dev/cbd/p	16th compressed block device, whole device
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 103 char	Arla network file system
+		  0 = /dev/nnpfs0	First NNPFS device
+		  1 = /dev/nnpfs1	Second NNPFS device
+
+		Arla is a free clone of the Andrew File System, AFS.
+		The NNPFS device gives user mode filesystem
+		implementations a kernel presence for caching and easy
+		mounting.  For more information about the project,
+		write to <arla-drinkers@stacken.kth.se> or see
+		http://www.stacken.kth.se/project/arla/
+
+ 103 block	Audit device
+		  0 = /dev/audit	Audit device
+
+ 104 char	Flash BIOS support
+
+ 104 block	Compaq Next Generation Drive Array, first controller
+		  0 = /dev/cciss/c0d0	First logical drive, whole disk
+		 16 = /dev/cciss/c0d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c0d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 105 char	Comtrol VS-1000 serial controller
+		  0 = /dev/ttyV0	First VS-1000 port
+		  1 = /dev/ttyV1	Second VS-1000 port
+		    ...
+
+ 105 block	Compaq Next Generation Drive Array, second controller
+		  0 = /dev/cciss/c1d0	First logical drive, whole disk
+		 16 = /dev/cciss/c1d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c1d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 106 char	Comtrol VS-1000 serial controller - alternate devices
+		  0 = /dev/cuv0		First VS-1000 port
+		  1 = /dev/cuv1		Second VS-1000 port
+		    ...
+
+ 106 block	Compaq Next Generation Drive Array, third controller
+		  0 = /dev/cciss/c2d0	First logical drive, whole disk
+		 16 = /dev/cciss/c2d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c2d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 107 char	3Dfx Voodoo Graphics device
+		  0 = /dev/3dfx		Primary 3Dfx graphics device
+
+ 107 block	Compaq Next Generation Drive Array, fourth controller
+		  0 = /dev/cciss/c3d0	First logical drive, whole disk
+		 16 = /dev/cciss/c3d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c3d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 108 char	Device independent PPP interface
+		  0 = /dev/ppp		Device independent PPP interface
+
+ 108 block	Compaq Next Generation Drive Array, fifth controller
+		  0 = /dev/cciss/c4d0	First logical drive, whole disk
+		 16 = /dev/cciss/c4d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c4d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 109 char	Reserved for logical volume manager
+
+ 109 block	Compaq Next Generation Drive Array, sixth controller
+		  0 = /dev/cciss/c5d0	First logical drive, whole disk
+		 16 = /dev/cciss/c5d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c5d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 110 char	miroMEDIA Surround board
+		  0 = /dev/srnd0	First miroMEDIA Surround board
+		  1 = /dev/srnd1	Second miroMEDIA Surround board
+		    ...
+
+ 110 block	Compaq Next Generation Drive Array, seventh controller
+		  0 = /dev/cciss/c6d0	First logical drive, whole disk
+		 16 = /dev/cciss/c6d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c6d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 111 char
+
+ 111 block	Compaq Next Generation Drive Array, eighth controller
+		  0 = /dev/cciss/c7d0	First logical drive, whole disk
+		 16 = /dev/cciss/c7d1	Second logical drive, whole disk
+		    ...
+		240 = /dev/cciss/c7d15	16th logical drive, whole disk
+
+		Partitions are handled the same way as for Mylex
+		DAC960 (see major number 48) except that the limit on
+		partitions is 15.
+
+ 112 char	ISI serial card
+		  0 = /dev/ttyM0	First ISI port
+		  1 = /dev/ttyM1	Second ISI port
+		    ...
+
+		There is currently a device-naming conflict between
+		these and PAM multimodems (major 78).
+
+ 112 block	IBM iSeries virtual disk
+		  0 = /dev/iseries/vda	First virtual disk, whole disk
+		  8 = /dev/iseries/vdb	Second virtual disk, whole disk
+		    ...
+		200 = /dev/iseries/vdz	26th virtual disk, whole disk
+		208 = /dev/iseries/vdaa	27th virtual disk, whole disk
+		    ...
+		248 = /dev/iseries/vdaf	32nd virtual disk, whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 7.
+
+ 113 char	ISI serial card - alternate devices
+		  0 = /dev/cum0		Callout device for ttyM0
+		  1 = /dev/cum1		Callout device for ttyM1
+		    ...
+
+ 113 block	IBM iSeries virtual CD-ROM
+		  0 = /dev/iseries/vcda	First virtual CD-ROM
+		  1 = /dev/iseries/vcdb	Second virtual CD-ROM
+		    ...
+
+ 114 char	Picture Elements ISE board
+		  0 = /dev/ise0		First ISE board
+		  1 = /dev/ise1		Second ISE board
+		    ...
+		128 = /dev/isex0	Control node for first ISE board
+		129 = /dev/isex1	Control node for second ISE board
+		    ...
+
+		The ISE board is an embedded computer, optimized for
+		image processing. The /dev/iseN nodes are the general
+		I/O access to the board, the /dev/isex0 nodes command
+		nodes used to control the board.
+
+ 114 block       IDE BIOS powered software RAID interfaces such as the
+		Promise Fastrak
+
+		   0 = /dev/ataraid/d0
+		   1 = /dev/ataraid/d0p1
+		   2 = /dev/ataraid/d0p2
+		  ...
+		  16 = /dev/ataraid/d1
+		  17 = /dev/ataraid/d1p1
+		  18 = /dev/ataraid/d1p2
+		  ...
+		 255 = /dev/ataraid/d15p15
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 115 char	TI link cable devices (115 was formerly the console driver speaker)
+		  0 = /dev/tipar0    Parallel cable on first parallel port
+		  ...
+		  7 = /dev/tipar7    Parallel cable on seventh parallel port
+
+		  8 = /dev/tiser0    Serial cable on first serial port
+		  ...
+		 15 = /dev/tiser7    Serial cable on seventh serial port
+
+		 16 = /dev/tiusb0    First USB cable
+		  ...
+		 47 = /dev/tiusb31   32nd USB cable
+
+ 115 block       NetWare (NWFS) Devices (0-255)
+
+		The NWFS (NetWare) devices are used to present a
+		collection of NetWare Mirror Groups or NetWare
+		Partitions as a logical storage segment for
+		use in mounting NetWare volumes.  A maximum of
+		 256 NetWare volumes can be supported in a single
+		machine.
+
+		http://cgfa.telepac.pt/ftp2/kernel.org/linux/kernel/people/jmerkey/nwfs/
+
+		 0 = /dev/nwfs/v0    First NetWare (NWFS) Logical Volume
+		 1 = /dev/nwfs/v1    Second NetWare (NWFS) Logical Volume
+		 2 = /dev/nwfs/v2    Third NetWare (NWFS) Logical Volume
+		      ...
+		 255 = /dev/nwfs/v255    Last NetWare (NWFS) Logical Volume
+
+ 116 char	Advanced Linux Sound Driver (ALSA)
+
+ 116 block       MicroMemory battery backed RAM adapter (NVRAM)
+		Supports 16 boards, 15 partitions each.
+		Requested by neilb at cse.unsw.edu.au.
+
+		 0 = /dev/umem/d0      Whole of first board
+		 1 = /dev/umem/d0p1    First partition of first board
+		 2 = /dev/umem/d0p2    Second partition of first board
+		15 = /dev/umem/d0p15   15th partition of first board
+
+		16 = /dev/umem/d1      Whole of second board
+		17 = /dev/umem/d1p1    First partition of second board
+		    ...
+		255= /dev/umem/d15p15  15th partition of 16th board.
+
+ 117 char	COSA/SRP synchronous serial card
+		  0 = /dev/cosa0c0	1st board, 1st channel
+		  1 = /dev/cosa0c1	1st board, 2nd channel
+		    ...
+		 16 = /dev/cosa1c0	2nd board, 1st channel
+		 17 = /dev/cosa1c1	2nd board, 2nd channel
+		    ...
+
+ 117 block       Enterprise Volume Management System (EVMS)
+
+		The EVMS driver uses a layered, plug-in model to provide
+		unparalleled flexibility and extensibility in managing
+		storage.  This allows for easy expansion or customization
+		of various levels of volume management.  Requested by
+		Mark Peloquin (peloquin at us.ibm.com).
+
+		Note: EVMS populates and manages all the devnodes in
+		/dev/evms.
+
+		http://sf.net/projects/evms
+
+		   0 = /dev/evms/block_device   EVMS block device
+		   1 = /dev/evms/legacyname1    First EVMS legacy device
+		   2 = /dev/evms/legacyname2    Second EVMS legacy device
+		    ...
+		    Both ranges can grow (down or up) until they meet.
+		    ...
+		 254 = /dev/evms/EVMSname2      Second EVMS native device
+		 255 = /dev/evms/EVMSname1      First EVMS native device
+
+		Note: legacyname(s) are derived from the normal legacy
+		device names.  For example, /dev/hda5 would become
+		/dev/evms/hda5.
+
+ 118 char	IBM Cryptographic Accelerator
+		  0 = /dev/ica	Virtual interface to all IBM Crypto Accelerators
+		  1 = /dev/ica0	IBMCA Device 0
+		  2 = /dev/ica1	IBMCA Device 1
+		    ...
+
+ 119 char	VMware virtual network control
+		  0 = /dev/vnet0	1st virtual network
+		  1 = /dev/vnet1	2nd virtual network
+		    ...
+
+ 120-127 char	LOCAL/EXPERIMENTAL USE
+
+ 120-127 block	LOCAL/EXPERIMENTAL USE
+		Allocated for local/experimental use.  For devices not
+		assigned official numbers, these ranges should be
+		used in order to avoid conflicting with future assignments.
+
+ 128-135 char	Unix98 PTY masters
+
+		These devices should not have corresponding device
+		nodes; instead they should be accessed through the
+		/dev/ptmx cloning interface.
+
+ 128 block       SCSI disk devices (128-143)
+		   0 = /dev/sddy         129th SCSI disk whole disk
+		  16 = /dev/sddz         130th SCSI disk whole disk
+		  32 = /dev/sdea         131th SCSI disk whole disk
+		    ...
+		 240 = /dev/sden         144th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 129 block       SCSI disk devices (144-159)
+		   0 = /dev/sdeo         145th SCSI disk whole disk
+		  16 = /dev/sdep         146th SCSI disk whole disk
+		  32 = /dev/sdeq         147th SCSI disk whole disk
+		    ...
+		 240 = /dev/sdfd         160th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 130 char 	(Misc devices)
+
+ 130 block       SCSI disk devices (160-175)
+		   0 = /dev/sdfe         161st SCSI disk whole disk
+		  16 = /dev/sdff         162nd SCSI disk whole disk
+		  32 = /dev/sdfg         163rd SCSI disk whole disk
+		    ...
+		 240 = /dev/sdft         176th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 131 block       SCSI disk devices (176-191)
+		   0 = /dev/sdfu         177th SCSI disk whole disk
+		  16 = /dev/sdfv         178th SCSI disk whole disk
+		  32 = /dev/sdfw         179th SCSI disk whole disk
+		    ...
+		 240 = /dev/sdgj         192nd SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 132 block       SCSI disk devices (192-207)
+		   0 = /dev/sdgk         193rd SCSI disk whole disk
+		  16 = /dev/sdgl         194th SCSI disk whole disk
+		  32 = /dev/sdgm         195th SCSI disk whole disk
+		    ...
+		 240 = /dev/sdgz         208th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 133 block       SCSI disk devices (208-223)
+		   0 = /dev/sdha         209th SCSI disk whole disk
+		  16 = /dev/sdhb         210th SCSI disk whole disk
+		  32 = /dev/sdhc         211th SCSI disk whole disk
+		    ...
+		 240 = /dev/sdhp         224th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 134 block       SCSI disk devices (224-239)
+		   0 = /dev/sdhq         225th SCSI disk whole disk
+		  16 = /dev/sdhr         226th SCSI disk whole disk
+		  32 = /dev/sdhs         227th SCSI disk whole disk
+		    ...
+		 240 = /dev/sdif         240th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 135 block       SCSI disk devices (240-255)
+		   0 = /dev/sdig         241st SCSI disk whole disk
+		  16 = /dev/sdih         242nd SCSI disk whole disk
+		  32 = /dev/sdih         243rd SCSI disk whole disk
+		    ...
+		 240 = /dev/sdiv         256th SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 136-143 char	Unix98 PTY slaves
+		  0 = /dev/pts/0	First Unix98 pseudo-TTY
+		  1 = /dev/pts/1	Second Unix98 pseudo-TTY
+		    ...
+
+		These device nodes are automatically generated with
+		the proper permissions and modes by mounting the
+		devpts filesystem onto /dev/pts with the appropriate
+		mount options (distribution dependent, however, on
+		*most* distributions the appropriate options are
+		"mode=0620,gid=<gid of the "tty" group>".)
+
+ 136 block	Mylex DAC960 PCI RAID controller; ninth controller
+		  0 = /dev/rd/c8d0	First disk, whole disk
+		  8 = /dev/rd/c8d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c8d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 137 block	Mylex DAC960 PCI RAID controller; tenth controller
+		  0 = /dev/rd/c9d0	First disk, whole disk
+		  8 = /dev/rd/c9d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c9d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 138 block	Mylex DAC960 PCI RAID controller; eleventh controller
+		  0 = /dev/rd/c10d0	First disk, whole disk
+		  8 = /dev/rd/c10d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c10d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 139 block	Mylex DAC960 PCI RAID controller; twelfth controller
+		  0 = /dev/rd/c11d0	First disk, whole disk
+		  8 = /dev/rd/c11d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c11d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 140 block	Mylex DAC960 PCI RAID controller; thirteenth controller
+		  0 = /dev/rd/c12d0	First disk, whole disk
+		  8 = /dev/rd/c12d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c12d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 141 block	Mylex DAC960 PCI RAID controller; fourteenth controller
+		  0 = /dev/rd/c13d0	First disk, whole disk
+		  8 = /dev/rd/c13d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c13d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 142 block	Mylex DAC960 PCI RAID controller; fifteenth controller
+		  0 = /dev/rd/c14d0	First disk, whole disk
+		  8 = /dev/rd/c14d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c14d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 143 block	Mylex DAC960 PCI RAID controller; sixteenth controller
+		  0 = /dev/rd/c15d0	First disk, whole disk
+		  8 = /dev/rd/c15d1	Second disk, whole disk
+		    ...
+		248 = /dev/rd/c15d31	32nd disk, whole disk
+
+		Partitions are handled as for major 48.
+
+ 144 char	Encapsulated PPP
+		  0 = /dev/pppox0	First PPP over Ethernet
+		    ...
+		 63 = /dev/pppox63	64th PPP over Ethernet
+
+		This is primarily used for ADSL.
+
+		The SST 5136-DN DeviceNet interface driver has been
+		relocated to major 183 due to an unfortunate conflict.
+
+ 144 block	Expansion Area #1 for more non-device (e.g. NFS) mounts
+		  0 = mounted device 256
+		255 = mounted device 511
+
+ 145 char	SAM9407-based soundcard
+		  0 = /dev/sam0_mixer
+		  1 = /dev/sam0_sequencer
+		  2 = /dev/sam0_midi00
+		  3 = /dev/sam0_dsp
+		  4 = /dev/sam0_audio
+		  6 = /dev/sam0_sndstat
+		 18 = /dev/sam0_midi01
+		 34 = /dev/sam0_midi02
+		 50 = /dev/sam0_midi03
+		 64 = /dev/sam1_mixer
+		    ...
+		128 = /dev/sam2_mixer
+		    ...
+		192 = /dev/sam3_mixer
+		    ...
+
+		Device functions match OSS, but offer a number of
+		addons, which are sam9407 specific.  OSS can be
+		operated simultaneously, taking care of the codec.
+
+ 145 block	Expansion Area #2 for more non-device (e.g. NFS) mounts
+		  0 = mounted device 512
+		255 = mounted device 767
+
+ 146 char	SYSTRAM SCRAMNet mirrored-memory network
+		  0 = /dev/scramnet0	First SCRAMNet device
+		  1 = /dev/scramnet1	Second SCRAMNet device
+		    ...
+
+ 146 block	Expansion Area #3 for more non-device (e.g. NFS) mounts
+		  0 = mounted device 768
+		255 = mounted device 1023
+
+ 147 char	Aureal Semiconductor Vortex Audio device
+		  0 = /dev/aureal0	First Aureal Vortex
+		  1 = /dev/aureal1	Second Aureal Vortex
+		    ...
+
+ 147 block	Distributed Replicated Block Device (DRBD)
+		  0 = /dev/drbd0	First DRBD device
+		  1 = /dev/drbd1	Second DRBD device
+		    ...
+
+ 148 char	Technology Concepts serial card
+		  0 = /dev/ttyT0	First TCL port
+		  1 = /dev/ttyT1	Second TCL port
+		    ...
+
+ 149 char	Technology Concepts serial card - alternate devices
+		  0 = /dev/cut0		Callout device for ttyT0
+		  1 = /dev/cut0		Callout device for ttyT1
+		    ...
+
+ 150 char	Real-Time Linux FIFOs
+		  0 = /dev/rtf0		First RTLinux FIFO
+		  1 = /dev/rtf1		Second RTLinux FIFO
+		    ...
+
+ 151 char	DPT I2O SmartRaid V controller
+		  0 = /dev/dpti0	First DPT I2O adapter
+		  1 = /dev/dpti1	Second DPT I2O adapter
+		    ...
+
+ 152 char	EtherDrive Control Device
+		  0 = /dev/etherd/ctl	Connect/Disconnect an EtherDrive
+		  1 = /dev/etherd/err	Monitor errors
+		  2 = /dev/etherd/raw	Raw AoE packet monitor
+
+ 152 block	EtherDrive Block Devices
+		  0 = /dev/etherd/0	EtherDrive 0
+		    ...
+		255 = /dev/etherd/255	EtherDrive 255
+
+ 153 char	SPI Bus Interface (sometimes referred to as MicroWire)
+		  0 = /dev/spi0		First SPI device on the bus
+		  1 = /dev/spi1		Second SPI device on the bus
+		    ...
+		 15 = /dev/spi15	Sixteenth SPI device on the bus
+
+ 153 block	Enhanced Metadisk RAID (EMD) storage units
+		  0 = /dev/emd/0	First unit
+		  1 = /dev/emd/0p1	Partition 1 on First unit
+		  2 = /dev/emd/0p2	Partition 2 on First unit
+		    ...
+		 15 = /dev/emd/0p15	Partition 15 on First unit
+
+		 16 = /dev/emd/1	Second unit
+		 32 = /dev/emd/2	Third unit
+		    ...
+		240 = /dev/emd/15	Sixteenth unit
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 154 char	Specialix RIO serial card
+		  0 = /dev/ttySR0	First RIO port
+		    ...
+		255 = /dev/ttySR255	256th RIO port
+
+ 155 char	Specialix RIO serial card - alternate devices
+		  0 = /dev/cusr0	Callout device for ttySR0
+		    ...
+		255 = /dev/cusr255	Callout device for ttySR255
+
+ 156 char	Specialix RIO serial card
+		  0 = /dev/ttySR256	257th RIO port
+		    ...
+		255 = /dev/ttySR511	512th RIO port
+
+ 157 char	Specialix RIO serial card - alternate devices
+		  0 = /dev/cusr256	Callout device for ttySR256
+		    ...
+		255 = /dev/cusr511	Callout device for ttySR511
+
+ 158 char	Dialogic GammaLink fax driver
+		  0 = /dev/gfax0	GammaLink channel 0
+		  1 = /dev/gfax1	GammaLink channel 1
+		    ...
+
+ 159 char	RESERVED
+
+ 159 block	RESERVED
+
+ 160 char	General Purpose Instrument Bus (GPIB)
+		  0 = /dev/gpib0	First GPIB bus
+		  1 = /dev/gpib1	Second GPIB bus
+		    ...
+
+ 160 block       Carmel 8-port SATA Disks on First Controller
+		  0 = /dev/carmel/0     SATA disk 0 whole disk
+		  1 = /dev/carmel/0p1   SATA disk 0 partition 1
+		    ...
+		 31 = /dev/carmel/0p31  SATA disk 0 partition 31
+
+		 32 = /dev/carmel/1     SATA disk 1 whole disk
+		 64 = /dev/carmel/2     SATA disk 2 whole disk
+		    ...
+		224 = /dev/carmel/7     SATA disk 7 whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 31.
+
+ 161 char	IrCOMM devices (IrDA serial/parallel emulation)
+		  0 = /dev/ircomm0	First IrCOMM device
+		  1 = /dev/ircomm1	Second IrCOMM device
+		    ...
+		 16 = /dev/irlpt0	First IrLPT device
+		 17 = /dev/irlpt1	Second IrLPT device
+		    ...
+
+ 161 block       Carmel 8-port SATA Disks on Second Controller
+		  0 = /dev/carmel/8     SATA disk 8 whole disk
+		  1 = /dev/carmel/8p1   SATA disk 8 partition 1
+		    ...
+		 31 = /dev/carmel/8p31  SATA disk 8 partition 31
+
+		 32 = /dev/carmel/9     SATA disk 9 whole disk
+		 64 = /dev/carmel/10    SATA disk 10 whole disk
+		    ...
+		224 = /dev/carmel/15    SATA disk 15 whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 31.
+
+ 162 char	Raw block device interface
+		  0 = /dev/rawctl	Raw I/O control device
+		  1 = /dev/raw/raw1	First raw I/O device
+		  2 = /dev/raw/raw2	Second raw I/O device
+		    ...
+		 max minor number of raw device is set by kernel config
+		 MAX_RAW_DEVS or raw module parameter 'max_raw_devs'
+
+ 163 char
+
+ 164 char	Chase Research AT/PCI-Fast serial card
+		  0 = /dev/ttyCH0	AT/PCI-Fast board 0, port 0
+		    ...
+		 15 = /dev/ttyCH15	AT/PCI-Fast board 0, port 15
+		 16 = /dev/ttyCH16	AT/PCI-Fast board 1, port 0
+		    ...
+		 31 = /dev/ttyCH31	AT/PCI-Fast board 1, port 15
+		 32 = /dev/ttyCH32	AT/PCI-Fast board 2, port 0
+		    ...
+		 47 = /dev/ttyCH47	AT/PCI-Fast board 2, port 15
+		 48 = /dev/ttyCH48	AT/PCI-Fast board 3, port 0
+		    ...
+		 63 = /dev/ttyCH63	AT/PCI-Fast board 3, port 15
+
+ 165 char	Chase Research AT/PCI-Fast serial card - alternate devices
+		  0 = /dev/cuch0	Callout device for ttyCH0
+		    ...
+		 63 = /dev/cuch63	Callout device for ttyCH63
+
+ 166 char	ACM USB modems
+		  0 = /dev/ttyACM0	First ACM modem
+		  1 = /dev/ttyACM1	Second ACM modem
+		    ...
+
+ 167 char	ACM USB modems - alternate devices
+		  0 = /dev/cuacm0	Callout device for ttyACM0
+		  1 = /dev/cuacm1	Callout device for ttyACM1
+		    ...
+
+ 168 char	Eracom CSA7000 PCI encryption adaptor
+		  0 = /dev/ecsa0	First CSA7000
+		  1 = /dev/ecsa1	Second CSA7000
+		    ...
+
+ 169 char	Eracom CSA8000 PCI encryption adaptor
+		  0 = /dev/ecsa8-0	First CSA8000
+		  1 = /dev/ecsa8-1	Second CSA8000
+		    ...
+
+ 170 char	AMI MegaRAC remote access controller
+		  0 = /dev/megarac0	First MegaRAC card
+		  1 = /dev/megarac1	Second MegaRAC card
+		    ...
+
+ 171 char	Reserved for IEEE 1394 (Firewire)
+
+ 172 char	Moxa Intellio serial card
+		  0 = /dev/ttyMX0	First Moxa port
+		  1 = /dev/ttyMX1	Second Moxa port
+		    ...
+		127 = /dev/ttyMX127	128th Moxa port
+		128 = /dev/moxactl	Moxa control port
+
+ 173 char	Moxa Intellio serial card - alternate devices
+		  0 = /dev/cumx0	Callout device for ttyMX0
+		  1 = /dev/cumx1	Callout device for ttyMX1
+		    ...
+		127 = /dev/cumx127	Callout device for ttyMX127
+
+ 174 char	SmartIO serial card
+		  0 = /dev/ttySI0	First SmartIO port
+		  1 = /dev/ttySI1	Second SmartIO port
+		    ...
+
+ 175 char	SmartIO serial card - alternate devices
+		  0 = /dev/cusi0	Callout device for ttySI0
+		  1 = /dev/cusi1	Callout device for ttySI1
+		    ...
+
+ 176 char	nCipher nFast PCI crypto accelerator
+		  0 = /dev/nfastpci0	First nFast PCI device
+		  1 = /dev/nfastpci1	First nFast PCI device
+		    ...
+
+ 177 char	TI PCILynx memory spaces
+		  0 = /dev/pcilynx/aux0	 AUX space of first PCILynx card
+		    ...
+		 15 = /dev/pcilynx/aux15 AUX space of 16th PCILynx card
+		 16 = /dev/pcilynx/rom0	 ROM space of first PCILynx card
+		    ...
+		 31 = /dev/pcilynx/rom15 ROM space of 16th PCILynx card
+		 32 = /dev/pcilynx/ram0	 RAM space of first PCILynx card
+		    ...
+		 47 = /dev/pcilynx/ram15 RAM space of 16th PCILynx card
+
+ 178 char	Giganet cLAN1xxx virtual interface adapter
+		  0 = /dev/clanvi0	First cLAN adapter
+		  1 = /dev/clanvi1	Second cLAN adapter
+		    ...
+
+ 179 block       MMC block devices
+		  0 = /dev/mmcblk0      First SD/MMC card
+		  1 = /dev/mmcblk0p1    First partition on first MMC card
+		  8 = /dev/mmcblk1      Second SD/MMC card
+		    ...
+
+		The start of next SD/MMC card can be configured with
+		CONFIG_MMC_BLOCK_MINORS, or overridden at boot/modprobe
+		time using the mmcblk.perdev_minors option. That would
+		bump the offset between each card to be the configured
+		value instead of the default 8.
+
+ 179 char	CCube DVXChip-based PCI products
+		  0 = /dev/dvxirq0	First DVX device
+		  1 = /dev/dvxirq1	Second DVX device
+		    ...
+
+ 180 char	USB devices
+		  0 = /dev/usb/lp0	First USB printer
+		    ...
+		 15 = /dev/usb/lp15	16th USB printer
+		 48 = /dev/usb/scanner0	First USB scanner
+		    ...
+		 63 = /dev/usb/scanner15 16th USB scanner
+		 64 = /dev/usb/rio500	Diamond Rio 500
+		 65 = /dev/usb/usblcd	USBLCD Interface (info@usblcd.de)
+		 66 = /dev/usb/cpad0	Synaptics cPad (mouse/LCD)
+		 96 = /dev/usb/hiddev0	1st USB HID device
+		    ...
+		111 = /dev/usb/hiddev15	16th USB HID device
+		112 = /dev/usb/auer0	1st auerswald ISDN device
+		    ...
+		127 = /dev/usb/auer15	16th auerswald ISDN device
+		128 = /dev/usb/brlvgr0	First Braille Voyager device
+		    ...
+		131 = /dev/usb/brlvgr3	Fourth Braille Voyager device
+		132 = /dev/usb/idmouse	ID Mouse (fingerprint scanner) device
+		133 = /dev/usb/sisusbvga1	First SiSUSB VGA device
+		    ...
+		140 = /dev/usb/sisusbvga8	Eighth SISUSB VGA device
+		144 = /dev/usb/lcd	USB LCD device
+		160 = /dev/usb/legousbtower0	1st USB Legotower device
+		    ...
+		175 = /dev/usb/legousbtower15	16th USB Legotower device
+		176 = /dev/usb/usbtmc1	First USB TMC device
+		   ...
+		191 = /dev/usb/usbtmc16	16th USB TMC device
+		192 = /dev/usb/yurex1	First USB Yurex device
+		   ...
+		209 = /dev/usb/yurex16	16th USB Yurex device
+
+ 180 block	USB block devices
+		  0 = /dev/uba		First USB block device
+		  8 = /dev/ubb		Second USB block device
+		 16 = /dev/ubc		Third USB block device
+		    ...
+
+ 181 char	Conrad Electronic parallel port radio clocks
+		  0 = /dev/pcfclock0	First Conrad radio clock
+		  1 = /dev/pcfclock1	Second Conrad radio clock
+		    ...
+
+ 182 char	Picture Elements THR2 binarizer
+		  0 = /dev/pethr0	First THR2 board
+		  1 = /dev/pethr1	Second THR2 board
+		    ...
+
+ 183 char	SST 5136-DN DeviceNet interface
+		  0 = /dev/ss5136dn0	First DeviceNet interface
+		  1 = /dev/ss5136dn1	Second DeviceNet interface
+		    ...
+
+		This device used to be assigned to major number 144.
+		It had to be moved due to an unfortunate conflict.
+
+ 184 char	Picture Elements' video simulator/sender
+		  0 = /dev/pevss0	First sender board
+		  1 = /dev/pevss1	Second sender board
+		    ...
+
+ 185 char	InterMezzo high availability file system
+		  0 = /dev/intermezzo0	First cache manager
+		  1 = /dev/intermezzo1	Second cache manager
+		    ...
+
+		See http://web.archive.org/web/20080115195241/
+		http://inter-mezzo.org/index.html
+
+ 186 char	Object-based storage control device
+		  0 = /dev/obd0		First obd control device
+		  1 = /dev/obd1		Second obd control device
+		    ...
+
+		See ftp://ftp.lustre.org/pub/obd for code and information.
+
+ 187 char	DESkey hardware encryption device
+		  0 = /dev/deskey0	First DES key
+		  1 = /dev/deskey1	Second DES key
+		    ...
+
+ 188 char	USB serial converters
+		  0 = /dev/ttyUSB0	First USB serial converter
+		  1 = /dev/ttyUSB1	Second USB serial converter
+		    ...
+
+ 189 char	USB serial converters - alternate devices
+		  0 = /dev/cuusb0	Callout device for ttyUSB0
+		  1 = /dev/cuusb1	Callout device for ttyUSB1
+		    ...
+
+ 190 char	Kansas City tracker/tuner card
+		  0 = /dev/kctt0	First KCT/T card
+		  1 = /dev/kctt1	Second KCT/T card
+		    ...
+
+ 191 char	Reserved for PCMCIA
+
+ 192 char	Kernel profiling interface
+		  0 = /dev/profile	Profiling control device
+		  1 = /dev/profile0	Profiling device for CPU 0
+		  2 = /dev/profile1	Profiling device for CPU 1
+		    ...
+
+ 193 char	Kernel event-tracing interface
+		  0 = /dev/trace	Tracing control device
+		  1 = /dev/trace0	Tracing device for CPU 0
+		  2 = /dev/trace1	Tracing device for CPU 1
+		    ...
+
+ 194 char	linVideoStreams (LINVS)
+		  0 = /dev/mvideo/status0	Video compression status
+		  1 = /dev/mvideo/stream0	Video stream
+		  2 = /dev/mvideo/frame0	Single compressed frame
+		  3 = /dev/mvideo/rawframe0	Raw uncompressed frame
+		  4 = /dev/mvideo/codec0	Direct codec access
+		  5 = /dev/mvideo/video4linux0	Video4Linux compatibility
+
+		 16 = /dev/mvideo/status1	Second device
+		    ...
+		 32 = /dev/mvideo/status2	Third device
+		    ...
+		    ...
+		240 = /dev/mvideo/status15	16th device
+		    ...
+
+ 195 char	Nvidia graphics devices
+		  0 = /dev/nvidia0		First Nvidia card
+		  1 = /dev/nvidia1		Second Nvidia card
+		    ...
+		255 = /dev/nvidiactl		Nvidia card control device
+
+ 196 char	Tormenta T1 card
+		  0 = /dev/tor/0		Master control channel for all cards
+		  1 = /dev/tor/1		First DS0
+		  2 = /dev/tor/2		Second DS0
+		    ...
+		 48 = /dev/tor/48		48th DS0
+		 49 = /dev/tor/49		First pseudo-channel
+		 50 = /dev/tor/50		Second pseudo-channel
+		    ...
+
+ 197 char	OpenTNF tracing facility
+		  0 = /dev/tnf/t0		Trace 0 data extraction
+		  1 = /dev/tnf/t1		Trace 1 data extraction
+		    ...
+		128 = /dev/tnf/status		Tracing facility status
+		130 = /dev/tnf/trace		Tracing device
+
+ 198 char	Total Impact TPMP2 quad coprocessor PCI card
+		  0 = /dev/tpmp2/0		First card
+		  1 = /dev/tpmp2/1		Second card
+		    ...
+
+ 199 char	Veritas volume manager (VxVM) volumes
+		  0 = /dev/vx/rdsk/*/*		First volume
+		  1 = /dev/vx/rdsk/*/*		Second volume
+		    ...
+
+ 199 block	Veritas volume manager (VxVM) volumes
+		  0 = /dev/vx/dsk/*/*		First volume
+		  1 = /dev/vx/dsk/*/*		Second volume
+		    ...
+
+		The namespace in these directories is maintained by
+		the user space VxVM software.
+
+ 200 char	Veritas VxVM configuration interface
+		   0 = /dev/vx/config		Configuration access node
+		   1 = /dev/vx/trace		Volume i/o trace access node
+		   2 = /dev/vx/iod		Volume i/o daemon access node
+		   3 = /dev/vx/info		Volume information access node
+		   4 = /dev/vx/task		Volume tasks access node
+		   5 = /dev/vx/taskmon		Volume tasks monitor daemon
+
+ 201 char	Veritas VxVM dynamic multipathing driver
+		  0 = /dev/vx/rdmp/*		First multipath device
+		  1 = /dev/vx/rdmp/*		Second multipath device
+		    ...
+ 201 block	Veritas VxVM dynamic multipathing driver
+		  0 = /dev/vx/dmp/*		First multipath device
+		  1 = /dev/vx/dmp/*		Second multipath device
+		    ...
+
+		The namespace in these directories is maintained by
+		the user space VxVM software.
+
+ 202 char	CPU model-specific registers
+		  0 = /dev/cpu/0/msr		MSRs on CPU 0
+		  1 = /dev/cpu/1/msr		MSRs on CPU 1
+		    ...
+
+ 202 block	Xen Virtual Block Device
+		  0 = /dev/xvda       First Xen VBD whole disk
+		  16 = /dev/xvdb      Second Xen VBD whole disk
+		  32 = /dev/xvdc      Third Xen VBD whole disk
+		    ...
+		  240 = /dev/xvdp     Sixteenth Xen VBD whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		partitions is 15.
+
+ 203 char	CPU CPUID information
+		  0 = /dev/cpu/0/cpuid		CPUID on CPU 0
+		  1 = /dev/cpu/1/cpuid		CPUID on CPU 1
+		    ...
+
+ 204 char	Low-density serial ports
+		  0 = /dev/ttyLU0		LinkUp Systems L72xx UART - port 0
+		  1 = /dev/ttyLU1		LinkUp Systems L72xx UART - port 1
+		  2 = /dev/ttyLU2		LinkUp Systems L72xx UART - port 2
+		  3 = /dev/ttyLU3		LinkUp Systems L72xx UART - port 3
+		  4 = /dev/ttyFB0		Intel Footbridge (ARM)
+		  5 = /dev/ttySA0		StrongARM builtin serial port 0
+		  6 = /dev/ttySA1		StrongARM builtin serial port 1
+		  7 = /dev/ttySA2		StrongARM builtin serial port 2
+		  8 = /dev/ttySC0		SCI serial port (SuperH) - port 0
+		  9 = /dev/ttySC1		SCI serial port (SuperH) - port 1
+		 10 = /dev/ttySC2		SCI serial port (SuperH) - port 2
+		 11 = /dev/ttySC3		SCI serial port (SuperH) - port 3
+		 12 = /dev/ttyFW0		Firmware console - port 0
+		 13 = /dev/ttyFW1		Firmware console - port 1
+		 14 = /dev/ttyFW2		Firmware console - port 2
+		 15 = /dev/ttyFW3		Firmware console - port 3
+		 16 = /dev/ttyAM0		ARM "AMBA" serial port 0
+		    ...
+		 31 = /dev/ttyAM15		ARM "AMBA" serial port 15
+		 32 = /dev/ttyDB0		DataBooster serial port 0
+		    ...
+		 39 = /dev/ttyDB7		DataBooster serial port 7
+		 40 = /dev/ttySG0		SGI Altix console port
+		 41 = /dev/ttySMX0		Motorola i.MX - port 0
+		 42 = /dev/ttySMX1		Motorola i.MX - port 1
+		 43 = /dev/ttySMX2		Motorola i.MX - port 2
+		 44 = /dev/ttyMM0		Marvell MPSC - port 0
+		 45 = /dev/ttyMM1		Marvell MPSC - port 1
+		 46 = /dev/ttyCPM0		PPC CPM (SCC or SMC) - port 0
+		    ...
+		 47 = /dev/ttyCPM5		PPC CPM (SCC or SMC) - port 5
+		 50 = /dev/ttyIOC0		Altix serial card
+		    ...
+		 81 = /dev/ttyIOC31		Altix serial card
+		 82 = /dev/ttyVR0		NEC VR4100 series SIU
+		 83 = /dev/ttyVR1		NEC VR4100 series DSIU
+		 84 = /dev/ttyIOC84		Altix ioc4 serial card
+		    ...
+		 115 = /dev/ttyIOC115		Altix ioc4 serial card
+		 116 = /dev/ttySIOC0		Altix ioc3 serial card
+		    ...
+		 147 = /dev/ttySIOC31		Altix ioc3 serial card
+		 148 = /dev/ttyPSC0		PPC PSC - port 0
+		    ...
+		 153 = /dev/ttyPSC5		PPC PSC - port 5
+		 154 = /dev/ttyAT0		ATMEL serial port 0
+		    ...
+		 169 = /dev/ttyAT15		ATMEL serial port 15
+		 170 = /dev/ttyNX0		Hilscher netX serial port 0
+		    ...
+		 185 = /dev/ttyNX15		Hilscher netX serial port 15
+		 186 = /dev/ttyJ0		JTAG1 DCC protocol based serial port emulation
+		 187 = /dev/ttyUL0		Xilinx uartlite - port 0
+		    ...
+		 190 = /dev/ttyUL3		Xilinx uartlite - port 3
+		 191 = /dev/xvc0		Xen virtual console - port 0
+		 192 = /dev/ttyPZ0		pmac_zilog - port 0
+		    ...
+		 195 = /dev/ttyPZ3		pmac_zilog - port 3
+		 196 = /dev/ttyTX0		TX39/49 serial port 0
+		    ...
+		 204 = /dev/ttyTX7		TX39/49 serial port 7
+		 205 = /dev/ttySC0		SC26xx serial port 0
+		 206 = /dev/ttySC1		SC26xx serial port 1
+		 207 = /dev/ttySC2		SC26xx serial port 2
+		 208 = /dev/ttySC3		SC26xx serial port 3
+		 209 = /dev/ttyMAX0		MAX3100 serial port 0
+		 210 = /dev/ttyMAX1		MAX3100 serial port 1
+		 211 = /dev/ttyMAX2		MAX3100 serial port 2
+		 212 = /dev/ttyMAX3		MAX3100 serial port 3
+
+ 205 char	Low-density serial ports (alternate device)
+		  0 = /dev/culu0		Callout device for ttyLU0
+		  1 = /dev/culu1		Callout device for ttyLU1
+		  2 = /dev/culu2		Callout device for ttyLU2
+		  3 = /dev/culu3		Callout device for ttyLU3
+		  4 = /dev/cufb0		Callout device for ttyFB0
+		  5 = /dev/cusa0		Callout device for ttySA0
+		  6 = /dev/cusa1		Callout device for ttySA1
+		  7 = /dev/cusa2		Callout device for ttySA2
+		  8 = /dev/cusc0		Callout device for ttySC0
+		  9 = /dev/cusc1		Callout device for ttySC1
+		 10 = /dev/cusc2		Callout device for ttySC2
+		 11 = /dev/cusc3		Callout device for ttySC3
+		 12 = /dev/cufw0		Callout device for ttyFW0
+		 13 = /dev/cufw1		Callout device for ttyFW1
+		 14 = /dev/cufw2		Callout device for ttyFW2
+		 15 = /dev/cufw3		Callout device for ttyFW3
+		 16 = /dev/cuam0		Callout device for ttyAM0
+		    ...
+		 31 = /dev/cuam15		Callout device for ttyAM15
+		 32 = /dev/cudb0		Callout device for ttyDB0
+		    ...
+		 39 = /dev/cudb7		Callout device for ttyDB7
+		 40 = /dev/cusg0		Callout device for ttySG0
+		 41 = /dev/ttycusmx0		Callout device for ttySMX0
+		 42 = /dev/ttycusmx1		Callout device for ttySMX1
+		 43 = /dev/ttycusmx2		Callout device for ttySMX2
+		 46 = /dev/cucpm0		Callout device for ttyCPM0
+		    ...
+		 49 = /dev/cucpm5		Callout device for ttyCPM5
+		 50 = /dev/cuioc40		Callout device for ttyIOC40
+		    ...
+		 81 = /dev/cuioc431		Callout device for ttyIOC431
+		 82 = /dev/cuvr0		Callout device for ttyVR0
+		 83 = /dev/cuvr1		Callout device for ttyVR1
+
+ 206 char	OnStream SC-x0 tape devices
+		  0 = /dev/osst0		First OnStream SCSI tape, mode 0
+		  1 = /dev/osst1		Second OnStream SCSI tape, mode 0
+		    ...
+		 32 = /dev/osst0l		First OnStream SCSI tape, mode 1
+		 33 = /dev/osst1l		Second OnStream SCSI tape, mode 1
+		    ...
+		 64 = /dev/osst0m		First OnStream SCSI tape, mode 2
+		 65 = /dev/osst1m		Second OnStream SCSI tape, mode 2
+		    ...
+		 96 = /dev/osst0a		First OnStream SCSI tape, mode 3
+		 97 = /dev/osst1a		Second OnStream SCSI tape, mode 3
+		    ...
+		128 = /dev/nosst0		No rewind version of /dev/osst0
+		129 = /dev/nosst1		No rewind version of /dev/osst1
+		    ...
+		160 = /dev/nosst0l		No rewind version of /dev/osst0l
+		161 = /dev/nosst1l		No rewind version of /dev/osst1l
+		    ...
+		192 = /dev/nosst0m		No rewind version of /dev/osst0m
+		193 = /dev/nosst1m		No rewind version of /dev/osst1m
+		    ...
+		224 = /dev/nosst0a		No rewind version of /dev/osst0a
+		225 = /dev/nosst1a		No rewind version of /dev/osst1a
+		    ...
+
+		The OnStream SC-x0 SCSI tapes do not support the
+		standard SCSI SASD command set and therefore need
+		their own driver "osst". Note that the IDE, USB (and
+		maybe ParPort) versions may be driven via ide-scsi or
+		usb-storage SCSI emulation and this osst device and
+		driver as well.  The ADR-x0 drives are QIC-157
+		compliant and don't need osst.
+
+ 207 char	Compaq ProLiant health feature indicate
+		  0 = /dev/cpqhealth/cpqw	Redirector interface
+		  1 = /dev/cpqhealth/crom	EISA CROM
+		  2 = /dev/cpqhealth/cdt	Data Table
+		  3 = /dev/cpqhealth/cevt	Event Log
+		  4 = /dev/cpqhealth/casr	Automatic Server Recovery
+		  5 = /dev/cpqhealth/cecc	ECC Memory
+		  6 = /dev/cpqhealth/cmca	Machine Check Architecture
+		  7 = /dev/cpqhealth/ccsm	Deprecated CDT
+		  8 = /dev/cpqhealth/cnmi	NMI Handling
+		  9 = /dev/cpqhealth/css	Sideshow Management
+		 10 = /dev/cpqhealth/cram	CMOS interface
+		 11 = /dev/cpqhealth/cpci	PCI IRQ interface
+
+ 208 char	User space serial ports
+		  0 = /dev/ttyU0		First user space serial port
+		  1 = /dev/ttyU1		Second user space serial port
+		    ...
+
+ 209 char	User space serial ports (alternate devices)
+		  0 = /dev/cuu0			Callout device for ttyU0
+		  1 = /dev/cuu1			Callout device for ttyU1
+		    ...
+
+ 210 char	SBE, Inc. sync/async serial card
+		  0 = /dev/sbei/wxcfg0		Configuration device for board 0
+		  1 = /dev/sbei/dld0		Download device for board 0
+		  2 = /dev/sbei/wan00		WAN device, port 0, board 0
+		  3 = /dev/sbei/wan01		WAN device, port 1, board 0
+		  4 = /dev/sbei/wan02		WAN device, port 2, board 0
+		  5 = /dev/sbei/wan03		WAN device, port 3, board 0
+		  6 = /dev/sbei/wanc00		WAN clone device, port 0, board 0
+		  7 = /dev/sbei/wanc01		WAN clone device, port 1, board 0
+		  8 = /dev/sbei/wanc02		WAN clone device, port 2, board 0
+		  9 = /dev/sbei/wanc03		WAN clone device, port 3, board 0
+		 10 = /dev/sbei/wxcfg1		Configuration device for board 1
+		 11 = /dev/sbei/dld1		Download device for board 1
+		 12 = /dev/sbei/wan10		WAN device, port 0, board 1
+		 13 = /dev/sbei/wan11		WAN device, port 1, board 1
+		 14 = /dev/sbei/wan12		WAN device, port 2, board 1
+		 15 = /dev/sbei/wan13		WAN device, port 3, board 1
+		 16 = /dev/sbei/wanc10		WAN clone device, port 0, board 1
+		 17 = /dev/sbei/wanc11		WAN clone device, port 1, board 1
+		 18 = /dev/sbei/wanc12		WAN clone device, port 2, board 1
+		 19 = /dev/sbei/wanc13		WAN clone device, port 3, board 1
+		    ...
+
+		Yes, each board is really spaced 10 (decimal) apart.
+
+ 211 char	Addinum CPCI1500 digital I/O card
+		  0 = /dev/addinum/cpci1500/0	First CPCI1500 card
+		  1 = /dev/addinum/cpci1500/1	Second CPCI1500 card
+		    ...
+
+ 212 char	LinuxTV.org DVB driver subsystem
+		  0 = /dev/dvb/adapter0/video0    first video decoder of first card
+		  1 = /dev/dvb/adapter0/audio0    first audio decoder of first card
+		  2 = /dev/dvb/adapter0/sec0      (obsolete/unused)
+		  3 = /dev/dvb/adapter0/frontend0 first frontend device of first card
+		  4 = /dev/dvb/adapter0/demux0    first demux device of first card
+		  5 = /dev/dvb/adapter0/dvr0      first digital video recoder device of first card
+		  6 = /dev/dvb/adapter0/ca0       first common access port of first card
+		  7 = /dev/dvb/adapter0/net0      first network device of first card
+		  8 = /dev/dvb/adapter0/osd0      first on-screen-display device of first card
+		  9 = /dev/dvb/adapter0/video1    second video decoder of first card
+		    ...
+		 64 = /dev/dvb/adapter1/video0    first video decoder of second card
+		    ...
+		128 = /dev/dvb/adapter2/video0    first video decoder of third card
+		    ...
+		196 = /dev/dvb/adapter3/video0    first video decoder of fourth card
+
+ 216 char	Bluetooth RFCOMM TTY devices
+		  0 = /dev/rfcomm0		First Bluetooth RFCOMM TTY device
+		  1 = /dev/rfcomm1		Second Bluetooth RFCOMM TTY device
+		    ...
+
+ 217 char	Bluetooth RFCOMM TTY devices (alternate devices)
+		  0 = /dev/curf0		Callout device for rfcomm0
+		  1 = /dev/curf1		Callout device for rfcomm1
+		    ...
+
+ 218 char	The Logical Company bus Unibus/Qbus adapters
+		  0 = /dev/logicalco/bci/0	First bus adapter
+		  1 = /dev/logicalco/bci/1	First bus adapter
+		    ...
+
+ 219 char	The Logical Company DCI-1300 digital I/O card
+		  0 = /dev/logicalco/dci1300/0	First DCI-1300 card
+		  1 = /dev/logicalco/dci1300/1	Second DCI-1300 card
+		    ...
+
+ 220 char	Myricom Myrinet "GM" board
+		  0 = /dev/myricom/gm0		First Myrinet GM board
+		  1 = /dev/myricom/gmp0		First board "root access"
+		  2 = /dev/myricom/gm1		Second Myrinet GM board
+		  3 = /dev/myricom/gmp1		Second board "root access"
+		    ...
+
+ 221 char	VME bus
+		  0 = /dev/bus/vme/m0		First master image
+		  1 = /dev/bus/vme/m1		Second master image
+		  2 = /dev/bus/vme/m2		Third master image
+		  3 = /dev/bus/vme/m3		Fourth master image
+		  4 = /dev/bus/vme/s0		First slave image
+		  5 = /dev/bus/vme/s1		Second slave image
+		  6 = /dev/bus/vme/s2		Third slave image
+		  7 = /dev/bus/vme/s3		Fourth slave image
+		  8 = /dev/bus/vme/ctl		Control
+
+		It is expected that all VME bus drivers will use the
+		same interface.  For interface documentation see
+		http://www.vmelinux.org/.
+
+ 224 char	A2232 serial card
+		  0 = /dev/ttyY0		First A2232 port
+		  1 = /dev/ttyY1		Second A2232 port
+		    ...
+
+ 225 char	A2232 serial card (alternate devices)
+		  0 = /dev/cuy0			Callout device for ttyY0
+		  1 = /dev/cuy1			Callout device for ttyY1
+		    ...
+
+ 226 char	Direct Rendering Infrastructure (DRI)
+		  0 = /dev/dri/card0		First graphics card
+		  1 = /dev/dri/card1		Second graphics card
+		    ...
+
+ 227 char	IBM 3270 terminal Unix tty access
+		  1 = /dev/3270/tty1		First 3270 terminal
+		  2 = /dev/3270/tty2		Seconds 3270 terminal
+		    ...
+
+ 228 char	IBM 3270 terminal block-mode access
+		  0 = /dev/3270/tub		Controlling interface
+		  1 = /dev/3270/tub1		First 3270 terminal
+		  2 = /dev/3270/tub2		Second 3270 terminal
+		    ...
+
+ 229 char	IBM iSeries/pSeries virtual console
+		  0 = /dev/hvc0			First console port
+		  1 = /dev/hvc1			Second console port
+		    ...
+
+ 230 char	IBM iSeries virtual tape
+		  0 = /dev/iseries/vt0		First virtual tape, mode 0
+		  1 = /dev/iseries/vt1		Second virtual tape, mode 0
+		    ...
+		 32 = /dev/iseries/vt0l		First virtual tape, mode 1
+		 33 = /dev/iseries/vt1l		Second virtual tape, mode 1
+		    ...
+		 64 = /dev/iseries/vt0m		First virtual tape, mode 2
+		 65 = /dev/iseries/vt1m		Second virtual tape, mode 2
+		    ...
+		 96 = /dev/iseries/vt0a		First virtual tape, mode 3
+		 97 = /dev/iseries/vt1a		Second virtual tape, mode 3
+		      ...
+		128 = /dev/iseries/nvt0		First virtual tape, mode 0, no rewind
+		129 = /dev/iseries/nvt1		Second virtual tape, mode 0, no rewind
+		    ...
+		160 = /dev/iseries/nvt0l	First virtual tape, mode 1, no rewind
+		161 = /dev/iseries/nvt1l	Second virtual tape, mode 1, no rewind
+		    ...
+		192 = /dev/iseries/nvt0m	First virtual tape, mode 2, no rewind
+		193 = /dev/iseries/nvt1m	Second virtual tape, mode 2, no rewind
+		    ...
+		224 = /dev/iseries/nvt0a	First virtual tape, mode 3, no rewind
+		225 = /dev/iseries/nvt1a	Second virtual tape, mode 3, no rewind
+		    ...
+
+		"No rewind" refers to the omission of the default
+		automatic rewind on device close.  The MTREW or MTOFFL
+		ioctl()'s can be used to rewind the tape regardless of
+		the device used to access it.
+
+ 231 char	InfiniBand
+		0 = /dev/infiniband/umad0
+		1 = /dev/infiniband/umad1
+		  ...
+		63 = /dev/infiniband/umad63    63rd InfiniBandMad device
+		64 = /dev/infiniband/issm0     First InfiniBand IsSM device
+		65 = /dev/infiniband/issm1     Second InfiniBand IsSM device
+		  ...
+		127 = /dev/infiniband/issm63    63rd InfiniBand IsSM device
+		128 = /dev/infiniband/uverbs0   First InfiniBand verbs device
+		129 = /dev/infiniband/uverbs1   Second InfiniBand verbs device
+		  ...
+		159 = /dev/infiniband/uverbs31  31st InfiniBand verbs device
+
+ 232 char	Biometric Devices
+		0 = /dev/biometric/sensor0/fingerprint	first fingerprint sensor on first device
+		1 = /dev/biometric/sensor0/iris		first iris sensor on first device
+		2 = /dev/biometric/sensor0/retina	first retina sensor on first device
+		3 = /dev/biometric/sensor0/voiceprint	first voiceprint sensor on first device
+		4 = /dev/biometric/sensor0/facial	first facial sensor on first device
+		5 = /dev/biometric/sensor0/hand		first hand sensor on first device
+		  ...
+		10 = /dev/biometric/sensor1/fingerprint	first fingerprint sensor on second device
+		  ...
+		20 = /dev/biometric/sensor2/fingerprint	first fingerprint sensor on third device
+		  ...
+
+ 233 char	PathScale InfiniPath interconnect
+		0 = /dev/ipath        Primary device for programs (any unit)
+		1 = /dev/ipath0       Access specifically to unit 0
+		2 = /dev/ipath1       Access specifically to unit 1
+		  ...
+		4 = /dev/ipath3       Access specifically to unit 3
+		129 = /dev/ipath_sma    Device used by Subnet Management Agent
+		130 = /dev/ipath_diag   Device used by diagnostics programs
+
+ 234-254	char	RESERVED FOR DYNAMIC ASSIGNMENT
+		Character devices that request a dynamic allocation of major number will
+		take numbers starting from 254 and downward.
+
+ 240-254 block	LOCAL/EXPERIMENTAL USE
+		Allocated for local/experimental use.  For devices not
+		assigned official numbers, these ranges should be
+		used in order to avoid conflicting with future assignments.
+
+ 255 char	RESERVED
+
+ 255 block	RESERVED
+
+		This major is reserved to assist the expansion to a
+		larger number space.  No device nodes with this major
+		should ever be created on the filesystem.
+		(This is probably not true anymore, but I'll leave it
+		for now /Torben)
+
+ ---LARGE MAJORS!!!!!---
+
+ 256 char	Equinox SST multi-port serial boards
+		   0 = /dev/ttyEQ0	First serial port on first Equinox SST board
+		 127 = /dev/ttyEQ127	Last serial port on first Equinox SST board
+		 128 = /dev/ttyEQ128	First serial port on second Equinox SST board
+		  ...
+		1027 = /dev/ttyEQ1027	Last serial port on eighth Equinox SST board
+
+ 256 block	Resident Flash Disk Flash Translation Layer
+		  0 = /dev/rfda		First RFD FTL layer
+		 16 = /dev/rfdb		Second RFD FTL layer
+		  ...
+		240 = /dev/rfdp		16th RFD FTL layer
+
+ 257 char	Phoenix Technologies Cryptographic Services Driver
+		  0 = /dev/ptlsec	Crypto Services Driver
+
+ 257 block	SSFDC Flash Translation Layer filesystem
+		  0 = /dev/ssfdca	First SSFDC layer
+		  8 = /dev/ssfdcb	Second SSFDC layer
+		 16 = /dev/ssfdcc	Third SSFDC layer
+		 24 = /dev/ssfdcd	4th SSFDC layer
+		 32 = /dev/ssfdce	5th SSFDC layer
+		 40 = /dev/ssfdcf	6th SSFDC layer
+		 48 = /dev/ssfdcg	7th SSFDC layer
+		 56 = /dev/ssfdch	8th SSFDC layer
+
+ 258 block	ROM/Flash read-only translation layer
+		  0 = /dev/blockrom0	First ROM card's translation layer interface
+		  1 = /dev/blockrom1	Second ROM card's translation layer interface
+		  ...
+
+ 259 block	Block Extended Major
+		  Used dynamically to hold additional partition minor
+		  numbers and allow large numbers of partitions per device
+
+ 259 char	FPGA configuration interfaces
+		  0 = /dev/icap0	First Xilinx internal configuration
+		  1 = /dev/icap1	Second Xilinx internal configuration
+
+ 260 char	OSD (Object-based-device) SCSI Device
+		  0 = /dev/osd0		First OSD Device
+		  1 = /dev/osd1		Second OSD Device
+		  ...
+		  255 = /dev/osd255	256th OSD Device
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/dynamic-debug-howto.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/dynamic-debug-howto.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/dynamic-debug-howto.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/dynamic-debug-howto.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,353 @@
+Dynamic debug
++++++++++++++
+
+
+Introduction
+============
+
+This document describes how to use the dynamic debug (dyndbg) feature.
+
+Dynamic debug is designed to allow you to dynamically enable/disable
+kernel code to obtain additional kernel information.  Currently, if
+``CONFIG_DYNAMIC_DEBUG`` is set, then all ``pr_debug()``/``dev_dbg()`` and
+``print_hex_dump_debug()``/``print_hex_dump_bytes()`` calls can be dynamically
+enabled per-callsite.
+
+If ``CONFIG_DYNAMIC_DEBUG`` is not set, ``print_hex_dump_debug()`` is just
+shortcut for ``print_hex_dump(KERN_DEBUG)``.
+
+For ``print_hex_dump_debug()``/``print_hex_dump_bytes()``, format string is
+its ``prefix_str`` argument, if it is constant string; or ``hexdump``
+in case ``prefix_str`` is build dynamically.
+
+Dynamic debug has even more useful features:
+
+ * Simple query language allows turning on and off debugging
+   statements by matching any combination of 0 or 1 of:
+
+   - source filename
+   - function name
+   - line number (including ranges of line numbers)
+   - module name
+   - format string
+
+ * Provides a debugfs control file: ``<debugfs>/dynamic_debug/control``
+   which can be read to display the complete list of known debug
+   statements, to help guide you
+
+Controlling dynamic debug Behaviour
+===================================
+
+The behaviour of ``pr_debug()``/``dev_dbg()`` are controlled via writing to a
+control file in the 'debugfs' filesystem. Thus, you must first mount
+the debugfs filesystem, in order to make use of this feature.
+Subsequently, we refer to the control file as:
+``<debugfs>/dynamic_debug/control``. For example, if you want to enable
+printing from source file ``svcsock.c``, line 1603 you simply do::
+
+  nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+If you make a mistake with the syntax, the write will fail thus::
+
+  nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
+				<debugfs>/dynamic_debug/control
+  -bash: echo: write error: Invalid argument
+
+Viewing Dynamic Debug Behaviour
+===============================
+
+You can view the currently configured behaviour of all the debug
+statements via::
+
+  nullarbor:~ # cat <debugfs>/dynamic_debug/control
+  # filename:lineno [module]function flags format
+  /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
+  /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline       : %d\012"
+  /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth         : %d\012"
+  /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests     : %d\012"
+  ...
+
+
+You can also apply standard Unix text manipulation filters to this
+data, e.g.::
+
+  nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control  | wc -l
+  62
+
+  nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
+  42
+
+The third column shows the currently enabled flags for each debug
+statement callsite (see below for definitions of the flags).  The
+default value, with no flags enabled, is ``=_``.  So you can view all
+the debug statement callsites with any non-default flags::
+
+  nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control
+  # filename:lineno [module]function flags format
+  /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
+
+Command Language Reference
+==========================
+
+At the lexical level, a command comprises a sequence of words separated
+by spaces or tabs.  So these are all equivalent::
+
+  nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+  nullarbor:~ # echo -c '  file   svcsock.c     line  1603 +p  ' >
+				<debugfs>/dynamic_debug/control
+  nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+Command submissions are bounded by a write() system call.
+Multiple commands can be written together, separated by ``;`` or ``\n``::
+
+  ~# echo "func pnpacpi_get_resources +p; func pnp_assign_mem +p" \
+     > <debugfs>/dynamic_debug/control
+
+If your query set is big, you can batch them too::
+
+  ~# cat query-batch-file > <debugfs>/dynamic_debug/control
+
+A another way is to use wildcard. The match rule support ``*`` (matches
+zero or more characters) and ``?`` (matches exactly one character).For
+example, you can match all usb drivers::
+
+  ~# echo "file drivers/usb/* +p" > <debugfs>/dynamic_debug/control
+
+At the syntactical level, a command comprises a sequence of match
+specifications, followed by a flags change specification::
+
+  command ::= match-spec* flags-spec
+
+The match-spec's are used to choose a subset of the known pr_debug()
+callsites to which to apply the flags-spec.  Think of them as a query
+with implicit ANDs between each pair.  Note that an empty list of
+match-specs will select all debug statement callsites.
+
+A match specification comprises a keyword, which controls the
+attribute of the callsite to be compared, and a value to compare
+against.  Possible keywords are:::
+
+  match-spec ::= 'func' string |
+		 'file' string |
+		 'module' string |
+		 'format' string |
+		 'line' line-range
+
+  line-range ::= lineno |
+		 '-'lineno |
+		 lineno'-' |
+		 lineno'-'lineno
+
+  lineno ::= unsigned-int
+
+.. note::
+
+  ``line-range`` cannot contain space, e.g.
+  "1-30" is valid range but "1 - 30" is not.
+
+
+The meanings of each keyword are:
+
+func
+    The given string is compared against the function name
+    of each callsite.  Example::
+
+	func svc_tcp_accept
+
+file
+    The given string is compared against either the full pathname, the
+    src-root relative pathname, or the basename of the source file of
+    each callsite.  Examples::
+
+	file svcsock.c
+	file kernel/freezer.c
+	file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c
+
+module
+    The given string is compared against the module name
+    of each callsite.  The module name is the string as
+    seen in ``lsmod``, i.e. without the directory or the ``.ko``
+    suffix and with ``-`` changed to ``_``.  Examples::
+
+	module sunrpc
+	module nfsd
+
+format
+    The given string is searched for in the dynamic debug format
+    string.  Note that the string does not need to match the
+    entire format, only some part.  Whitespace and other
+    special characters can be escaped using C octal character
+    escape ``\ooo`` notation, e.g. the space character is ``\040``.
+    Alternatively, the string can be enclosed in double quote
+    characters (``"``) or single quote characters (``'``).
+    Examples::
+
+	format svcrdma:         // many of the NFS/RDMA server pr_debugs
+	format readahead        // some pr_debugs in the readahead cache
+	format nfsd:\040SETATTR // one way to match a format with whitespace
+	format "nfsd: SETATTR"  // a neater way to match a format with whitespace
+	format 'nfsd: SETATTR'  // yet another way to match a format with whitespace
+
+line
+    The given line number or range of line numbers is compared
+    against the line number of each ``pr_debug()`` callsite.  A single
+    line number matches the callsite line number exactly.  A
+    range of line numbers matches any callsite between the first
+    and last line number inclusive.  An empty first number means
+    the first line in the file, an empty line number means the
+    last number in the file.  Examples::
+
+	line 1603           // exactly line 1603
+	line 1600-1605      // the six lines from line 1600 to line 1605
+	line -1605          // the 1605 lines from line 1 to line 1605
+	line 1600-          // all lines from line 1600 to the end of the file
+
+The flags specification comprises a change operation followed
+by one or more flag characters.  The change operation is one
+of the characters::
+
+  -    remove the given flags
+  +    add the given flags
+  =    set the flags to the given flags
+
+The flags are::
+
+  p    enables the pr_debug() callsite.
+  f    Include the function name in the printed message
+  l    Include line number in the printed message
+  m    Include module name in the printed message
+  t    Include thread ID in messages not generated from interrupt context
+  _    No flags are set. (Or'd with others on input)
+
+For ``print_hex_dump_debug()`` and ``print_hex_dump_bytes()``, only ``p`` flag
+have meaning, other flags ignored.
+
+For display, the flags are preceded by ``=``
+(mnemonic: what the flags are currently equal to).
+
+Note the regexp ``^[-+=][flmpt_]+$`` matches a flags specification.
+To clear all flags at once, use ``=_`` or ``-flmpt``.
+
+
+Debug messages during Boot Process
+==================================
+
+To activate debug messages for core code and built-in modules during
+the boot process, even before userspace and debugfs exists, use
+``dyndbg="QUERY"``, ``module.dyndbg="QUERY"``, or ``ddebug_query="QUERY"``
+(``ddebug_query`` is obsoleted by ``dyndbg``, and deprecated).  QUERY follows
+the syntax described above, but must not exceed 1023 characters.  Your
+bootloader may impose lower limits.
+
+These ``dyndbg`` params are processed just after the ddebug tables are
+processed, as part of the arch_initcall.  Thus you can enable debug
+messages in all code run after this arch_initcall via this boot
+parameter.
+
+On an x86 system for example ACPI enablement is a subsys_initcall and::
+
+   dyndbg="file ec.c +p"
+
+will show early Embedded Controller transactions during ACPI setup if
+your machine (typically a laptop) has an Embedded Controller.
+PCI (or other devices) initialization also is a hot candidate for using
+this boot parameter for debugging purposes.
+
+If ``foo`` module is not built-in, ``foo.dyndbg`` will still be processed at
+boot time, without effect, but will be reprocessed when module is
+loaded later. ``dyndbg_query=`` and bare ``dyndbg=`` are only processed at
+boot.
+
+
+Debug Messages at Module Initialization Time
+============================================
+
+When ``modprobe foo`` is called, modprobe scans ``/proc/cmdline`` for
+``foo.params``, strips ``foo.``, and passes them to the kernel along with
+params given in modprobe args or ``/etc/modprob.d/*.conf`` files,
+in the following order:
+
+1. parameters given via ``/etc/modprobe.d/*.conf``::
+
+	options foo dyndbg=+pt
+	options foo dyndbg # defaults to +p
+
+2. ``foo.dyndbg`` as given in boot args, ``foo.`` is stripped and passed::
+
+	foo.dyndbg=" func bar +p; func buz +mp"
+
+3. args to modprobe::
+
+	modprobe foo dyndbg==pmf # override previous settings
+
+These ``dyndbg`` queries are applied in order, with last having final say.
+This allows boot args to override or modify those from ``/etc/modprobe.d``
+(sensible, since 1 is system wide, 2 is kernel or boot specific), and
+modprobe args to override both.
+
+In the ``foo.dyndbg="QUERY"`` form, the query must exclude ``module foo``.
+``foo`` is extracted from the param-name, and applied to each query in
+``QUERY``, and only 1 match-spec of each type is allowed.
+
+The ``dyndbg`` option is a "fake" module parameter, which means:
+
+- modules do not need to define it explicitly
+- every module gets it tacitly, whether they use pr_debug or not
+- it doesn't appear in ``/sys/module/$module/parameters/``
+  To see it, grep the control file, or inspect ``/proc/cmdline.``
+
+For ``CONFIG_DYNAMIC_DEBUG`` kernels, any settings given at boot-time (or
+enabled by ``-DDEBUG`` flag during compilation) can be disabled later via
+the sysfs interface if the debug messages are no longer needed::
+
+   echo "module module_name -p" > <debugfs>/dynamic_debug/control
+
+Examples
+========
+
+::
+
+  // enable the message at line 1603 of file svcsock.c
+  nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
+				<debugfs>/dynamic_debug/control
+
+  // enable all the messages in file svcsock.c
+  nullarbor:~ # echo -n 'file svcsock.c +p' >
+				<debugfs>/dynamic_debug/control
+
+  // enable all the messages in the NFS server module
+  nullarbor:~ # echo -n 'module nfsd +p' >
+				<debugfs>/dynamic_debug/control
+
+  // enable all 12 messages in the function svc_process()
+  nullarbor:~ # echo -n 'func svc_process +p' >
+				<debugfs>/dynamic_debug/control
+
+  // disable all 12 messages in the function svc_process()
+  nullarbor:~ # echo -n 'func svc_process -p' >
+				<debugfs>/dynamic_debug/control
+
+  // enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
+  nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
+				<debugfs>/dynamic_debug/control
+
+  // enable messages in files of which the paths include string "usb"
+  nullarbor:~ # echo -n '*usb* +p' > <debugfs>/dynamic_debug/control
+
+  // enable all messages
+  nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control
+
+  // add module, function to all enabled messages
+  nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control
+
+  // boot-args example, with newlines and comments for readability
+  Kernel command line: ...
+    // see whats going on in dyndbg=value processing
+    dynamic_debug.verbose=1
+    // enable pr_debugs in 2 builtins, #cmt is stripped
+    dyndbg="module params +p #cmt ; module sys +p"
+    // enable pr_debugs in 2 functions in a module loaded later
+    pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p"
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/index.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/index.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+The Linux kernel user's and administrator's guide
+=================================================
+
+The following is a collection of user-oriented documents that have been
+added to the kernel over time.  There is, as yet, little overall order or
+organization here — this material was not written to be a single, coherent
+document!  With luck things will improve quickly over time.
+
+This initial section contains overall information, including the README
+file describing the kernel as a whole, documentation on kernel parameters,
+etc.
+
+.. toctree::
+   :maxdepth: 1
+
+   README
+   kernel-parameters
+   devices
+
+Here is a set of documents aimed at users who are trying to track down
+problems and bugs in particular.
+
+.. toctree::
+   :maxdepth: 1
+
+   reporting-bugs
+   security-bugs
+   bug-hunting
+   bug-bisect
+   tainted-kernels
+   ramoops
+   dynamic-debug-howto
+   init
+
+This is the beginning of a section with information of interest to
+application developers.  Documents covering various aspects of the kernel
+ABI will be found here.
+
+.. toctree::
+   :maxdepth: 1
+
+   sysfs-rules
+
+The rest of this manual consists of various unordered guides on how to
+configure specific aspects of kernel behavior to your liking.
+
+.. toctree::
+   :maxdepth: 1
+
+   initrd
+   serial-console
+   braille-console
+   parport
+   md
+   module-signing
+   sysrq
+   unicode
+   vga-softcursor
+   binfmt-misc
+   mono
+   java
+   ras
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/initrd.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/initrd.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/initrd.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/initrd.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,383 @@
+Using the initial RAM disk (initrd)
+===================================
+
+Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch> and
+Hans Lermen <lermen@fgan.de>
+
+
+initrd provides the capability to load a RAM disk by the boot loader.
+This RAM disk can then be mounted as the root file system and programs
+can be run from it. Afterwards, a new root file system can be mounted
+from a different device. The previous root (from initrd) is then moved
+to a directory and can be subsequently unmounted.
+
+initrd is mainly designed to allow system startup to occur in two phases,
+where the kernel comes up with a minimum set of compiled-in drivers, and
+where additional modules are loaded from initrd.
+
+This document gives a brief overview of the use of initrd. A more detailed
+discussion of the boot process can be found in [#f1]_.
+
+
+Operation
+---------
+
+When using initrd, the system typically boots as follows:
+
+  1) the boot loader loads the kernel and the initial RAM disk
+  2) the kernel converts initrd into a "normal" RAM disk and
+     frees the memory used by initrd
+  3) if the root device is not ``/dev/ram0``, the old (deprecated)
+     change_root procedure is followed. see the "Obsolete root change
+     mechanism" section below.
+  4) root device is mounted. if it is ``/dev/ram0``, the initrd image is
+     then mounted as root
+  5) /sbin/init is executed (this can be any valid executable, including
+     shell scripts; it is run with uid 0 and can do basically everything
+     init can do).
+  6) init mounts the "real" root file system
+  7) init places the root file system at the root directory using the
+     pivot_root system call
+  8) init execs the ``/sbin/init`` on the new root filesystem, performing
+     the usual boot sequence
+  9) the initrd file system is removed
+
+Note that changing the root directory does not involve unmounting it.
+It is therefore possible to leave processes running on initrd during that
+procedure. Also note that file systems mounted under initrd continue to
+be accessible.
+
+
+Boot command-line options
+-------------------------
+
+initrd adds the following new options::
+
+  initrd=<path>    (e.g. LOADLIN)
+
+    Loads the specified file as the initial RAM disk. When using LILO, you
+    have to specify the RAM disk image file in /etc/lilo.conf, using the
+    INITRD configuration variable.
+
+  noinitrd
+
+    initrd data is preserved but it is not converted to a RAM disk and
+    the "normal" root file system is mounted. initrd data can be read
+    from /dev/initrd. Note that the data in initrd can have any structure
+    in this case and doesn't necessarily have to be a file system image.
+    This option is used mainly for debugging.
+
+    Note: /dev/initrd is read-only and it can only be used once. As soon
+    as the last process has closed it, all data is freed and /dev/initrd
+    can't be opened anymore.
+
+  root=/dev/ram0
+
+    initrd is mounted as root, and the normal boot procedure is followed,
+    with the RAM disk mounted as root.
+
+Compressed cpio images
+----------------------
+
+Recent kernels have support for populating a ramdisk from a compressed cpio
+archive. On such systems, the creation of a ramdisk image doesn't need to
+involve special block devices or loopbacks; you merely create a directory on
+disk with the desired initrd content, cd to that directory, and run (as an
+example)::
+
+	find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img
+
+Examining the contents of an existing image file is just as simple::
+
+	mkdir /tmp/imagefile
+	cd /tmp/imagefile
+	gzip -cd /boot/imagefile.img | cpio -imd --quiet
+
+Installation
+------------
+
+First, a directory for the initrd file system has to be created on the
+"normal" root file system, e.g.::
+
+	# mkdir /initrd
+
+The name is not relevant. More details can be found on the
+:manpage:`pivot_root(2)` man page.
+
+If the root file system is created during the boot procedure (i.e. if
+you're building an install floppy), the root file system creation
+procedure should create the ``/initrd`` directory.
+
+If initrd will not be mounted in some cases, its content is still
+accessible if the following device has been created::
+
+	# mknod /dev/initrd b 1 250
+	# chmod 400 /dev/initrd
+
+Second, the kernel has to be compiled with RAM disk support and with
+support for the initial RAM disk enabled. Also, at least all components
+needed to execute programs from initrd (e.g. executable format and file
+system) must be compiled into the kernel.
+
+Third, you have to create the RAM disk image. This is done by creating a
+file system on a block device, copying files to it as needed, and then
+copying the content of the block device to the initrd file. With recent
+kernels, at least three types of devices are suitable for that:
+
+ - a floppy disk (works everywhere but it's painfully slow)
+ - a RAM disk (fast, but allocates physical memory)
+ - a loopback device (the most elegant solution)
+
+We'll describe the loopback device method:
+
+ 1) make sure loopback block devices are configured into the kernel
+ 2) create an empty file system of the appropriate size, e.g.::
+
+	# dd if=/dev/zero of=initrd bs=300k count=1
+	# mke2fs -F -m0 initrd
+
+    (if space is critical, you may want to use the Minix FS instead of Ext2)
+ 3) mount the file system, e.g.::
+
+	# mount -t ext2 -o loop initrd /mnt
+
+ 4) create the console device::
+
+    # mkdir /mnt/dev
+    # mknod /mnt/dev/console c 5 1
+
+ 5) copy all the files that are needed to properly use the initrd
+    environment. Don't forget the most important file, ``/sbin/init``
+
+    .. note:: ``/sbin/init`` permissions must include "x" (execute).
+
+ 6) correct operation the initrd environment can frequently be tested
+    even without rebooting with the command::
+
+	# chroot /mnt /sbin/init
+
+    This is of course limited to initrds that do not interfere with the
+    general system state (e.g. by reconfiguring network interfaces,
+    overwriting mounted devices, trying to start already running demons,
+    etc. Note however that it is usually possible to use pivot_root in
+    such a chroot'ed initrd environment.)
+ 7) unmount the file system::
+
+	# umount /mnt
+
+ 8) the initrd is now in the file "initrd". Optionally, it can now be
+    compressed::
+
+	# gzip -9 initrd
+
+For experimenting with initrd, you may want to take a rescue floppy and
+only add a symbolic link from ``/sbin/init`` to ``/bin/sh``. Alternatively, you
+can try the experimental newlib environment [#f2]_ to create a small
+initrd.
+
+Finally, you have to boot the kernel and load initrd. Almost all Linux
+boot loaders support initrd. Since the boot process is still compatible
+with an older mechanism, the following boot command line parameters
+have to be given::
+
+  root=/dev/ram0 rw
+
+(rw is only necessary if writing to the initrd file system.)
+
+With LOADLIN, you simply execute::
+
+     LOADLIN <kernel> initrd=<disk_image>
+
+e.g.::
+
+	LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 rw
+
+With LILO, you add the option ``INITRD=<path>`` to either the global section
+or to the section of the respective kernel in ``/etc/lilo.conf``, and pass
+the options using APPEND, e.g.::
+
+  image = /bzImage
+    initrd = /boot/initrd.gz
+    append = "root=/dev/ram0 rw"
+
+and run ``/sbin/lilo``
+
+For other boot loaders, please refer to the respective documentation.
+
+Now you can boot and enjoy using initrd.
+
+
+Changing the root device
+------------------------
+
+When finished with its duties, init typically changes the root device
+and proceeds with starting the Linux system on the "real" root device.
+
+The procedure involves the following steps:
+ - mounting the new root file system
+ - turning it into the root file system
+ - removing all accesses to the old (initrd) root file system
+ - unmounting the initrd file system and de-allocating the RAM disk
+
+Mounting the new root file system is easy: it just needs to be mounted on
+a directory under the current root. Example::
+
+	# mkdir /new-root
+	# mount -o ro /dev/hda1 /new-root
+
+The root change is accomplished with the pivot_root system call, which
+is also available via the ``pivot_root`` utility (see :manpage:`pivot_root(8)`
+man page; ``pivot_root`` is distributed with util-linux version 2.10h or higher
+[#f3]_). ``pivot_root`` moves the current root to a directory under the new
+root, and puts the new root at its place. The directory for the old root
+must exist before calling ``pivot_root``. Example::
+
+	# cd /new-root
+	# mkdir initrd
+	# pivot_root . initrd
+
+Now, the init process may still access the old root via its
+executable, shared libraries, standard input/output/error, and its
+current root directory. All these references are dropped by the
+following command::
+
+	# exec chroot . what-follows <dev/console >dev/console 2>&1
+
+Where what-follows is a program under the new root, e.g. ``/sbin/init``
+If the new root file system will be used with udev and has no valid
+``/dev`` directory, udev must be initialized before invoking chroot in order
+to provide ``/dev/console``.
+
+Note: implementation details of pivot_root may change with time. In order
+to ensure compatibility, the following points should be observed:
+
+ - before calling pivot_root, the current directory of the invoking
+   process should point to the new root directory
+ - use . as the first argument, and the _relative_ path of the directory
+   for the old root as the second argument
+ - a chroot program must be available under the old and the new root
+ - chroot to the new root afterwards
+ - use relative paths for dev/console in the exec command
+
+Now, the initrd can be unmounted and the memory allocated by the RAM
+disk can be freed::
+
+	# umount /initrd
+	# blockdev --flushbufs /dev/ram0
+
+It is also possible to use initrd with an NFS-mounted root, see the
+:manpage:`pivot_root(8)` man page for details.
+
+
+Usage scenarios
+---------------
+
+The main motivation for implementing initrd was to allow for modular
+kernel configuration at system installation. The procedure would work
+as follows:
+
+  1) system boots from floppy or other media with a minimal kernel
+     (e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and
+     loads initrd
+  2) ``/sbin/init`` determines what is needed to (1) mount the "real" root FS
+     (i.e. device type, device drivers, file system) and (2) the
+     distribution media (e.g. CD-ROM, network, tape, ...). This can be
+     done by asking the user, by auto-probing, or by using a hybrid
+     approach.
+  3) ``/sbin/init`` loads the necessary kernel modules
+  4) ``/sbin/init`` creates and populates the root file system (this doesn't
+     have to be a very usable system yet)
+  5) ``/sbin/init`` invokes ``pivot_root`` to change the root file system and
+     execs - via chroot - a program that continues the installation
+  6) the boot loader is installed
+  7) the boot loader is configured to load an initrd with the set of
+     modules that was used to bring up the system (e.g. ``/initrd`` can be
+     modified, then unmounted, and finally, the image is written from
+     ``/dev/ram0`` or ``/dev/rd/0`` to a file)
+  8) now the system is bootable and additional installation tasks can be
+     performed
+
+The key role of initrd here is to re-use the configuration data during
+normal system operation without requiring the use of a bloated "generic"
+kernel or re-compiling or re-linking the kernel.
+
+A second scenario is for installations where Linux runs on systems with
+different hardware configurations in a single administrative domain. In
+such cases, it is desirable to generate only a small set of kernels
+(ideally only one) and to keep the system-specific part of configuration
+information as small as possible. In this case, a common initrd could be
+generated with all the necessary modules. Then, only ``/sbin/init`` or a file
+read by it would have to be different.
+
+A third scenario is more convenient recovery disks, because information
+like the location of the root FS partition doesn't have to be provided at
+boot time, but the system loaded from initrd can invoke a user-friendly
+dialog and it can also perform some sanity checks (or even some form of
+auto-detection).
+
+Last not least, CD-ROM distributors may use it for better installation
+from CD, e.g. by using a boot floppy and bootstrapping a bigger RAM disk
+via initrd from CD; or by booting via a loader like ``LOADLIN`` or directly
+from the CD-ROM, and loading the RAM disk from CD without need of
+floppies.
+
+
+Obsolete root change mechanism
+------------------------------
+
+The following mechanism was used before the introduction of pivot_root.
+Current kernels still support it, but you should _not_ rely on its
+continued availability.
+
+It works by mounting the "real" root device (i.e. the one set with rdev
+in the kernel image or with root=... at the boot command line) as the
+root file system when linuxrc exits. The initrd file system is then
+unmounted, or, if it is still busy, moved to a directory ``/initrd``, if
+such a directory exists on the new root file system.
+
+In order to use this mechanism, you do not have to specify the boot
+command options root, init, or rw. (If specified, they will affect
+the real root file system, not the initrd environment.)
+
+If /proc is mounted, the "real" root device can be changed from within
+linuxrc by writing the number of the new root FS device to the special
+file /proc/sys/kernel/real-root-dev, e.g.::
+
+  # echo 0x301 >/proc/sys/kernel/real-root-dev
+
+Note that the mechanism is incompatible with NFS and similar file
+systems.
+
+This old, deprecated mechanism is commonly called ``change_root``, while
+the new, supported mechanism is called ``pivot_root``.
+
+
+Mixed change_root and pivot_root mechanism
+------------------------------------------
+
+In case you did not want to use ``root=/dev/ram0`` to trigger the pivot_root
+mechanism, you may create both ``/linuxrc`` and ``/sbin/init`` in your initrd
+image.
+
+``/linuxrc`` would contain only the following::
+
+	#! /bin/sh
+	mount -n -t proc proc /proc
+	echo 0x0100 >/proc/sys/kernel/real-root-dev
+	umount -n /proc
+
+Once linuxrc exited, the kernel would mount again your initrd as root,
+this time executing ``/sbin/init``. Again, it would be the duty of this init
+to build the right environment (maybe using the ``root= device`` passed on
+the cmdline) before the final execution of the real ``/sbin/init``.
+
+
+Resources
+---------
+
+.. [#f1] Almesberger, Werner; "Booting Linux: The History and the Future"
+    http://www.almesberger.net/cv/papers/ols2k-9.ps.gz
+.. [#f2] newlib package (experimental), with initrd example
+    https://www.sourceware.org/newlib/
+.. [#f3] util-linux: Miscellaneous utilities for Linux
+    https://www.kernel.org/pub/linux/utils/util-linux/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/init.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/init.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/init.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/init.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,52 @@
+Explaining the dreaded "No init found." boot hang message
+=========================================================
+
+OK, so you've got this pretty unintuitive message (currently located
+in init/main.c) and are wondering what the H*** went wrong.
+Some high-level reasons for failure (listed roughly in order of execution)
+to load the init binary are:
+
+A) Unable to mount root FS
+B) init binary doesn't exist on rootfs
+C) broken console device
+D) binary exists but dependencies not available
+E) binary cannot be loaded
+
+Detailed explanations:
+
+A) Set "debug" kernel parameter (in bootloader config file or CONFIG_CMDLINE)
+   to get more detailed kernel messages.
+B) make sure you have the correct root FS type
+   (and ``root=`` kernel parameter points to the correct partition),
+   required drivers such as storage hardware (such as SCSI or USB!)
+   and filesystem (ext3, jffs2 etc.) are builtin (alternatively as modules,
+   to be pre-loaded by an initrd)
+C) Possibly a conflict in ``console= setup`` --> initial console unavailable.
+   E.g. some serial consoles are unreliable due to serial IRQ issues (e.g.
+   missing interrupt-based configuration).
+   Try using a different ``console= device`` or e.g. ``netconsole=``.
+D) e.g. required library dependencies of the init binary such as
+   ``/lib/ld-linux.so.2`` missing or broken. Use
+   ``readelf -d <INIT>|grep NEEDED`` to find out which libraries are required.
+E) make sure the binary's architecture matches your hardware.
+   E.g. i386 vs. x86_64 mismatch, or trying to load x86 on ARM hardware.
+   In case you tried loading a non-binary file here (shell script?),
+   you should make sure that the script specifies an interpreter in its shebang
+   header line (``#!/...``) that is fully working (including its library
+   dependencies). And before tackling scripts, better first test a simple
+   non-script binary such as ``/bin/sh`` and confirm its successful execution.
+   To find out more, add code ``to init/main.c`` to display kernel_execve()s
+   return values.
+
+Please extend this explanation whenever you find new failure causes
+(after all loading the init binary is a CRITICAL and hard transition step
+which needs to be made as painless as possible), then submit patch to LKML.
+Further TODOs:
+
+- Implement the various ``run_init_process()`` invocations via a struct array
+  which can then store the ``kernel_execve()`` result value and on failure
+  log it all by iterating over **all** results (very important usability fix).
+- try to make the implementation itself more helpful in general,
+  e.g. by providing additional error messages at affected places.
+
+Andreas Mohr <andi at lisas period de>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/java.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/java.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/java.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/java.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,423 @@
+Java(tm) Binary Kernel Support for Linux v1.03
+----------------------------------------------
+
+Linux beats them ALL! While all other OS's are TALKING about direct
+support of Java Binaries in the OS, Linux is doing it!
+
+You can execute Java applications and Java Applets just like any
+other program after you have done the following:
+
+1) You MUST FIRST install the Java Developers Kit for Linux.
+   The Java on Linux HOWTO gives the details on getting and
+   installing this. This HOWTO can be found at:
+
+	ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Java-HOWTO
+
+   You should also set up a reasonable CLASSPATH environment
+   variable to use Java applications that make use of any
+   nonstandard classes (not included in the same directory
+   as the application itself).
+
+2) You have to compile BINFMT_MISC either as a module or into
+   the kernel (``CONFIG_BINFMT_MISC``) and set it up properly.
+   If you choose to compile it as a module, you will have
+   to insert it manually with modprobe/insmod, as kmod
+   cannot easily be supported with binfmt_misc.
+   Read the file 'binfmt_misc.txt' in this directory to know
+   more about the configuration process.
+
+3) Add the following configuration items to binfmt_misc
+   (you should really have read ``binfmt_misc.txt`` now):
+   support for Java applications::
+
+     ':Java:M::\xca\xfe\xba\xbe::/usr/local/bin/javawrapper:'
+
+   support for executable Jar files::
+
+     ':ExecutableJAR:E::jar::/usr/local/bin/jarwrapper:'
+
+   support for Java Applets::
+
+     ':Applet:E::html::/usr/bin/appletviewer:'
+
+   or the following, if you want to be more selective::
+
+     ':Applet:M::<!--applet::/usr/bin/appletviewer:'
+
+   Of course you have to fix the path names. The path/file names given in this
+   document match the Debian 2.1 system. (i.e. jdk installed in ``/usr``,
+   custom wrappers from this document in ``/usr/local``)
+
+   Note, that for the more selective applet support you have to modify
+   existing html-files to contain ``<!--applet-->`` in the first line
+   (``<`` has to be the first character!) to let this work!
+
+   For the compiled Java programs you need a wrapper script like the
+   following (this is because Java is broken in case of the filename
+   handling), again fix the path names, both in the script and in the
+   above given configuration string.
+
+   You, too, need the little program after the script. Compile like::
+
+	gcc -O2 -o javaclassname javaclassname.c
+
+   and stick it to ``/usr/local/bin``.
+
+   Both the javawrapper shellscript and the javaclassname program
+   were supplied by Colin J. Watson <cjw44@cam.ac.uk>.
+
+Javawrapper shell script:
+
+.. code-block:: sh
+
+  #!/bin/bash
+  # /usr/local/bin/javawrapper - the wrapper for binfmt_misc/java
+
+  if [ -z "$1" ]; then
+	exec 1>&2
+	echo Usage: $0 class-file
+	exit 1
+  fi
+
+  CLASS=$1
+  FQCLASS=`/usr/local/bin/javaclassname $1`
+  FQCLASSN=`echo $FQCLASS | sed -e 's/^.*\.\([^.]*\)$/\1/'`
+  FQCLASSP=`echo $FQCLASS | sed -e 's-\.-/-g' -e 's-^[^/]*$--' -e 's-/[^/]*$--'`
+
+  # for example:
+  # CLASS=Test.class
+  # FQCLASS=foo.bar.Test
+  # FQCLASSN=Test
+  # FQCLASSP=foo/bar
+
+  unset CLASSBASE
+
+  declare -i LINKLEVEL=0
+
+  while :; do
+	if [ "`basename $CLASS .class`" == "$FQCLASSN" ]; then
+		# See if this directory works straight off
+		cd -L `dirname $CLASS`
+		CLASSDIR=$PWD
+		cd $OLDPWD
+		if echo $CLASSDIR | grep -q "$FQCLASSP$"; then
+			CLASSBASE=`echo $CLASSDIR | sed -e "s.$FQCLASSP$.."`
+			break;
+		fi
+		# Try dereferencing the directory name
+		cd -P `dirname $CLASS`
+		CLASSDIR=$PWD
+		cd $OLDPWD
+		if echo $CLASSDIR | grep -q "$FQCLASSP$"; then
+			CLASSBASE=`echo $CLASSDIR | sed -e "s.$FQCLASSP$.."`
+			break;
+		fi
+		# If no other possible filename exists
+		if [ ! -L $CLASS ]; then
+			exec 1>&2
+			echo $0:
+			echo "  $CLASS should be in a" \
+			     "directory tree called $FQCLASSP"
+			exit 1
+		fi
+	fi
+	if [ ! -L $CLASS ]; then break; fi
+	# Go down one more level of symbolic links
+	let LINKLEVEL+=1
+	if [ $LINKLEVEL -gt 5 ]; then
+		exec 1>&2
+		echo $0:
+		echo "  Too many symbolic links encountered"
+		exit 1
+	fi
+	CLASS=`ls --color=no -l $CLASS | sed -e 's/^.* \([^ ]*\)$/\1/'`
+  done
+
+  if [ -z "$CLASSBASE" ]; then
+	if [ -z "$FQCLASSP" ]; then
+		GOODNAME=$FQCLASSN.class
+	else
+		GOODNAME=$FQCLASSP/$FQCLASSN.class
+	fi
+	exec 1>&2
+	echo $0:
+	echo "  $FQCLASS should be in a file called $GOODNAME"
+	exit 1
+  fi
+
+  if ! echo $CLASSPATH | grep -q "^\(.*:\)*$CLASSBASE\(:.*\)*"; then
+	# class is not in CLASSPATH, so prepend dir of class to CLASSPATH
+	if [ -z "${CLASSPATH}" ] ; then
+		export CLASSPATH=$CLASSBASE
+	else
+		export CLASSPATH=$CLASSBASE:$CLASSPATH
+	fi
+  fi
+
+  shift
+  /usr/bin/java $FQCLASS "$@"
+
+javaclassname.c:
+
+.. code-block:: c
+
+  /* javaclassname.c
+   *
+   * Extracts the class name from a Java class file; intended for use in a Java
+   * wrapper of the type supported by the binfmt_misc option in the Linux kernel.
+   *
+   * Copyright (C) 1999 Colin J. Watson <cjw44@cam.ac.uk>.
+   *
+   * This program is free software; you can redistribute it and/or modify
+   * it under the terms of the GNU General Public License as published by
+   * the Free Software Foundation; either version 2 of the License, or
+   * (at your option) any later version.
+   *
+   * This program is distributed in the hope that it will be useful,
+   * but WITHOUT ANY WARRANTY; without even the implied warranty of
+   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   * GNU General Public License for more details.
+   *
+   * You should have received a copy of the GNU General Public 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 <stdlib.h>
+  #include <stdio.h>
+  #include <stdarg.h>
+  #include <sys/types.h>
+
+  /* From Sun's Java VM Specification, as tag entries in the constant pool. */
+
+  #define CP_UTF8 1
+  #define CP_INTEGER 3
+  #define CP_FLOAT 4
+  #define CP_LONG 5
+  #define CP_DOUBLE 6
+  #define CP_CLASS 7
+  #define CP_STRING 8
+  #define CP_FIELDREF 9
+  #define CP_METHODREF 10
+  #define CP_INTERFACEMETHODREF 11
+  #define CP_NAMEANDTYPE 12
+  #define CP_METHODHANDLE 15
+  #define CP_METHODTYPE 16
+  #define CP_INVOKEDYNAMIC 18
+
+  /* Define some commonly used error messages */
+
+  #define seek_error() error("%s: Cannot seek\n", program)
+  #define corrupt_error() error("%s: Class file corrupt\n", program)
+  #define eof_error() error("%s: Unexpected end of file\n", program)
+  #define utf8_error() error("%s: Only ASCII 1-255 supported\n", program);
+
+  char *program;
+
+  long *pool;
+
+  u_int8_t read_8(FILE *classfile);
+  u_int16_t read_16(FILE *classfile);
+  void skip_constant(FILE *classfile, u_int16_t *cur);
+  void error(const char *format, ...);
+  int main(int argc, char **argv);
+
+  /* Reads in an unsigned 8-bit integer. */
+  u_int8_t read_8(FILE *classfile)
+  {
+	int b = fgetc(classfile);
+	if(b == EOF)
+		eof_error();
+	return (u_int8_t)b;
+  }
+
+  /* Reads in an unsigned 16-bit integer. */
+  u_int16_t read_16(FILE *classfile)
+  {
+	int b1, b2;
+	b1 = fgetc(classfile);
+	if(b1 == EOF)
+		eof_error();
+	b2 = fgetc(classfile);
+	if(b2 == EOF)
+		eof_error();
+	return (u_int16_t)((b1 << 8) | b2);
+  }
+
+  /* Reads in a value from the constant pool. */
+  void skip_constant(FILE *classfile, u_int16_t *cur)
+  {
+	u_int16_t len;
+	int seekerr = 1;
+	pool[*cur] = ftell(classfile);
+	switch(read_8(classfile))
+	{
+	case CP_UTF8:
+		len = read_16(classfile);
+		seekerr = fseek(classfile, len, SEEK_CUR);
+		break;
+	case CP_CLASS:
+	case CP_STRING:
+	case CP_METHODTYPE:
+		seekerr = fseek(classfile, 2, SEEK_CUR);
+		break;
+	case CP_METHODHANDLE:
+		seekerr = fseek(classfile, 3, SEEK_CUR);
+		break;
+	case CP_INTEGER:
+	case CP_FLOAT:
+	case CP_FIELDREF:
+	case CP_METHODREF:
+	case CP_INTERFACEMETHODREF:
+	case CP_NAMEANDTYPE:
+	case CP_INVOKEDYNAMIC:
+		seekerr = fseek(classfile, 4, SEEK_CUR);
+		break;
+	case CP_LONG:
+	case CP_DOUBLE:
+		seekerr = fseek(classfile, 8, SEEK_CUR);
+		++(*cur);
+		break;
+	default:
+		corrupt_error();
+	}
+	if(seekerr)
+		seek_error();
+  }
+
+  void error(const char *format, ...)
+  {
+	va_list ap;
+	va_start(ap, format);
+	vfprintf(stderr, format, ap);
+	va_end(ap);
+	exit(1);
+  }
+
+  int main(int argc, char **argv)
+  {
+	FILE *classfile;
+	u_int16_t cp_count, i, this_class, classinfo_ptr;
+	u_int8_t length;
+
+	program = argv[0];
+
+	if(!argv[1])
+		error("%s: Missing input file\n", program);
+	classfile = fopen(argv[1], "rb");
+	if(!classfile)
+		error("%s: Error opening %s\n", program, argv[1]);
+
+	if(fseek(classfile, 8, SEEK_SET))  /* skip magic and version numbers */
+		seek_error();
+	cp_count = read_16(classfile);
+	pool = calloc(cp_count, sizeof(long));
+	if(!pool)
+		error("%s: Out of memory for constant pool\n", program);
+
+	for(i = 1; i < cp_count; ++i)
+		skip_constant(classfile, &i);
+	if(fseek(classfile, 2, SEEK_CUR))	/* skip access flags */
+		seek_error();
+
+	this_class = read_16(classfile);
+	if(this_class < 1 || this_class >= cp_count)
+		corrupt_error();
+	if(!pool[this_class] || pool[this_class] == -1)
+		corrupt_error();
+	if(fseek(classfile, pool[this_class] + 1, SEEK_SET))
+		seek_error();
+
+	classinfo_ptr = read_16(classfile);
+	if(classinfo_ptr < 1 || classinfo_ptr >= cp_count)
+		corrupt_error();
+	if(!pool[classinfo_ptr] || pool[classinfo_ptr] == -1)
+		corrupt_error();
+	if(fseek(classfile, pool[classinfo_ptr] + 1, SEEK_SET))
+		seek_error();
+
+	length = read_16(classfile);
+	for(i = 0; i < length; ++i)
+	{
+		u_int8_t x = read_8(classfile);
+		if((x & 0x80) || !x)
+		{
+			if((x & 0xE0) == 0xC0)
+			{
+				u_int8_t y = read_8(classfile);
+				if((y & 0xC0) == 0x80)
+				{
+					int c = ((x & 0x1f) << 6) + (y & 0x3f);
+					if(c) putchar(c);
+					else utf8_error();
+				}
+				else utf8_error();
+			}
+			else utf8_error();
+		}
+		else if(x == '/') putchar('.');
+		else putchar(x);
+	}
+	putchar('\n');
+	free(pool);
+	fclose(classfile);
+	return 0;
+  }
+
+jarwrapper::
+
+  #!/bin/bash
+  # /usr/local/java/bin/jarwrapper - the wrapper for binfmt_misc/jar
+
+  java -jar $1
+
+
+Now simply ``chmod +x`` the ``.class``, ``.jar`` and/or ``.html`` files you
+want to execute.
+
+To add a Java program to your path best put a symbolic link to the main
+.class file into /usr/bin (or another place you like) omitting the .class
+extension. The directory containing the original .class file will be
+added to your CLASSPATH during execution.
+
+
+To test your new setup, enter in the following simple Java app, and name
+it "HelloWorld.java":
+
+.. code-block:: java
+
+	class HelloWorld {
+		public static void main(String args[]) {
+			System.out.println("Hello World!");
+		}
+	}
+
+Now compile the application with::
+
+	javac HelloWorld.java
+
+Set the executable permissions of the binary file, with::
+
+	chmod 755 HelloWorld.class
+
+And then execute it::
+
+	./HelloWorld.class
+
+
+To execute Java Jar files, simple chmod the ``*.jar`` files to include
+the execution bit, then just do::
+
+       ./Application.jar
+
+
+To execute Java Applets, simple chmod the ``*.html`` files to include
+the execution bit, then just do::
+
+	./Applet.html
+
+
+originally by Brian A. Lantz, brian@lantz.com
+heavily edited for binfmt_misc by Richard Günther
+new scripts by Colin J. Watson <cjw44@cam.ac.uk>
+added executable Jar file support by Kurt Huwig <kurt@iku-netz.de>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/kernel-parameters.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/kernel-parameters.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/kernel-parameters.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/kernel-parameters.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,209 @@
+The kernel's command-line parameters
+====================================
+
+The following is a consolidated list of the kernel parameters as
+implemented by the __setup(), core_param() and module_param() macros
+and sorted into English Dictionary order (defined as ignoring all
+punctuation and sorting digits before letters in a case insensitive
+manner), and with descriptions where known.
+
+The kernel parses parameters from the kernel command line up to "--";
+if it doesn't recognize a parameter and it doesn't contain a '.', the
+parameter gets passed to init: parameters with '=' go into init's
+environment, others are passed as command line arguments to init.
+Everything after "--" is passed as an argument to init.
+
+Module parameters can be specified in two ways: via the kernel command
+line with a module name prefix, or via modprobe, e.g.::
+
+	(kernel command line) usbcore.blinkenlights=1
+	(modprobe command line) modprobe usbcore blinkenlights=1
+
+Parameters for modules which are built into the kernel need to be
+specified on the kernel command line.  modprobe looks through the
+kernel command line (/proc/cmdline) and collects module parameters
+when it loads a module, so the kernel command line can be used for
+loadable modules too.
+
+Hyphens (dashes) and underscores are equivalent in parameter names, so::
+
+	log_buf_len=1M print-fatal-signals=1
+
+can also be entered as::
+
+	log-buf-len=1M print_fatal_signals=1
+
+Double-quotes can be used to protect spaces in values, e.g.::
+
+	param="spaces in here"
+
+cpu lists:
+----------
+
+Some kernel parameters take a list of CPUs as a value, e.g.  isolcpus,
+nohz_full, irqaffinity, rcu_nocbs.  The format of this list is:
+
+	<cpu number>,...,<cpu number>
+
+or
+
+	<cpu number>-<cpu number>
+	(must be a positive range in ascending order)
+
+or a mixture
+
+<cpu number>,...,<cpu number>-<cpu number>
+
+Note that for the special case of a range one can split the range into equal
+sized groups and for each group use some amount from the beginning of that
+group:
+
+	<cpu number>-cpu number>:<used size>/<group size>
+
+For example one can add to the command line following parameter:
+
+	isolcpus=1,2,10-20,100-2000:2/25
+
+where the final item represents CPUs 100,101,125,126,150,151,...
+
+
+
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+``echo -n ${value} > /sys/module/${modulename}/parameters/${parm}``.
+
+The parameters listed below are only valid if certain kernel build options were
+enabled and if respective hardware is present. The text in square brackets at
+the beginning of each description states the restrictions within which a
+parameter is applicable::
+
+	ACPI	ACPI support is enabled.
+	AGP	AGP (Accelerated Graphics Port) is enabled.
+	ALSA	ALSA sound support is enabled.
+	APIC	APIC support is enabled.
+	APM	Advanced Power Management support is enabled.
+	ARM	ARM architecture is enabled.
+	AVR32	AVR32 architecture is enabled.
+	AX25	Appropriate AX.25 support is enabled.
+	BLACKFIN Blackfin architecture is enabled.
+	CLK	Common clock infrastructure is enabled.
+	CMA	Contiguous Memory Area support is enabled.
+	DRM	Direct Rendering Management support is enabled.
+	DYNAMIC_DEBUG Build in debug messages and enable them at runtime
+	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.
+	HW	Appropriate hardware is enabled.
+	IA-64	IA-64 architecture is enabled.
+	IMA     Integrity measurement architecture is enabled.
+	IOSCHED	More than one I/O scheduler is enabled.
+	IP_PNP	IP DHCP, BOOTP, or RARP is enabled.
+	IPV6	IPv6 support is enabled.
+	ISAPNP	ISA PnP code is enabled.
+	ISDN	Appropriate ISDN support is enabled.
+	JOY	Appropriate joystick support is enabled.
+	KGDB	Kernel debugger support is enabled.
+	KVM	Kernel Virtual Machine support is enabled.
+	LIBATA  Libata driver is enabled
+	LP	Printer support is enabled.
+	LOOP	Loopback device support is enabled.
+	M68k	M68k architecture is enabled.
+			These options have more detailed description inside of
+			Documentation/m68k/kernel-options.txt.
+	MDA	MDA console support is enabled.
+	MIPS	MIPS architecture is enabled.
+	MOUSE	Appropriate mouse support is enabled.
+	MSI	Message Signaled Interrupts (PCI).
+	MTD	MTD (Memory Technology Device) support is enabled.
+	NET	Appropriate network support is enabled.
+	NUMA	NUMA support is enabled.
+	NFS	Appropriate NFS support is enabled.
+	OSS	OSS sound support is enabled.
+	PV_OPS	A paravirtualized kernel is enabled.
+	PARIDE	The ParIDE (parallel port IDE) subsystem is enabled.
+	PARISC	The PA-RISC architecture is enabled.
+	PCI	PCI bus support is enabled.
+	PCIE	PCI Express support is enabled.
+	PCMCIA	The PCMCIA subsystem is enabled.
+	PNP	Plug & Play support is enabled.
+	PPC	PowerPC architecture is enabled.
+	PPT	Parallel port support is enabled.
+	PS2	Appropriate PS/2 support is enabled.
+	RAM	RAM disk support is enabled.
+	S390	S390 architecture is enabled.
+	SCSI	Appropriate SCSI support is enabled.
+			A lot of drivers have their options described inside
+			the Documentation/scsi/ sub-directory.
+	SECURITY Different security models are enabled.
+	SELINUX SELinux support is enabled.
+	APPARMOR AppArmor support is enabled.
+	SERIAL	Serial support is enabled.
+	SH	SuperH architecture is enabled.
+	SMP	The kernel is an SMP kernel.
+	SPARC	Sparc architecture is enabled.
+	SWSUSP	Software suspend (hibernation) is enabled.
+	SUSPEND	System suspend states are enabled.
+	TPM	TPM drivers are enabled.
+	TS	Appropriate touchscreen support is enabled.
+	UMS	USB Mass Storage support is enabled.
+	USB	USB support is enabled.
+	USBHID	USB Human Interface Device support is enabled.
+	V4L	Video For Linux support is enabled.
+	VMMIO   Driver for memory mapped virtio devices is enabled.
+	VGA	The VGA console has been enabled.
+	VT	Virtual terminal support is enabled.
+	WDT	Watchdog support is enabled.
+	XT	IBM PC/XT MFM hard disk support is enabled.
+	X86-32	X86-32, aka i386 architecture is enabled.
+	X86-64	X86-64 architecture is enabled.
+			More X86-64 boot options can be found in
+			Documentation/x86/x86_64/boot-options.txt .
+	X86	Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
+	X86_UV	SGI UV support is enabled.
+	XEN	Xen support is enabled
+
+In addition, the following text indicates that the option::
+
+	BUGS=	Relates to possible processor bugs on the said processor.
+	KNL	Is a kernel start-up parameter.
+	BOOT	Is a boot loader parameter.
+
+Parameters denoted with BOOT are actually interpreted by the boot
+loader, and have no meaning to the kernel directly.
+Do not modify the syntax of boot loader parameters without extreme
+need or coordination with <Documentation/x86/boot.txt>.
+
+There are also arch-specific kernel-parameters not documented here.
+See for example <Documentation/x86/x86_64/boot-options.txt>.
+
+Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
+a trailing = on the name of any parameter states that that parameter will
+be entered as an environment variable, whereas its absence indicates that
+it will appear as a kernel argument readable via /proc/cmdline by programs
+running once the system is up.
+
+The number of kernel parameters is not limited, but the length of the
+complete command line (parameters including spaces etc.) is limited to
+a fixed number of characters. This limit depends on the architecture
+and is between 256 and 4096 characters. It is defined in the file
+./include/asm/setup.h as COMMAND_LINE_SIZE.
+
+Finally, the [KMG] suffix is commonly described after a number of kernel
+parameter values. These 'K', 'M', and 'G' letters represent the _binary_
+multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
+bytes respectively. Such letter suffixes can also be entirely omitted:
+
+.. include:: kernel-parameters.txt
+   :literal:
+
+Todo
+----
+
+	Add more DRM drivers.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/kernel-parameters.txt linux-libre-4.10-rc8-gnu/Documentation/admin-guide/kernel-parameters.txt
--- linux-libre-4.9-gnu/Documentation/admin-guide/kernel-parameters.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/kernel-parameters.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,4390 @@
+	acpi=		[HW,ACPI,X86,ARM64]
+			Advanced Configuration and Power Interface
+			Format: { force | on | off | strict | noirq | rsdt |
+				  copy_dsdt }
+			force -- enable ACPI if default was off
+			on -- enable ACPI but allow fallback to DT [arm64]
+			off -- disable ACPI if default was on
+			noirq -- do not use ACPI for IRQ routing
+			strict -- Be less tolerant of platforms that are not
+				strictly ACPI specification compliant.
+			rsdt -- prefer RSDT over (default) XSDT
+			copy_dsdt -- copy DSDT to memory
+			For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force"
+			are available
+
+			See also Documentation/power/runtime_pm.txt, pci=noacpi
+
+	acpi_apic_instance=	[ACPI, IOAPIC]
+			Format: <int>
+			2: use 2nd APIC table, if available
+			1,0: use 1st APIC table
+			default: 0
+
+	acpi_backlight=	[HW,ACPI]
+			acpi_backlight=vendor
+			acpi_backlight=video
+			If set to vendor, prefer vendor specific driver
+			(e.g. thinkpad_acpi, sony_acpi, etc.) instead
+			of the ACPI video.ko driver.
+
+	acpi_force_32bit_fadt_addr
+			force FADT to use 32 bit addresses rather than the
+			64 bit X_* addresses. Some firmware have broken 64
+			bit addresses for force ACPI ignore these and use
+			the older legacy 32 bit addresses.
+
+	acpica_no_return_repair [HW, ACPI]
+			Disable AML predefined validation mechanism
+			This mechanism can repair the evaluation result to make
+			the return objects more ACPI specification compliant.
+			This option is useful for developers to identify the
+			root cause of an AML interpreter issue when the issue
+			has something to do with the repair mechanism.
+
+	acpi.debug_layer=	[HW,ACPI,ACPI_DEBUG]
+	acpi.debug_level=	[HW,ACPI,ACPI_DEBUG]
+			Format: <int>
+			CONFIG_ACPI_DEBUG must be enabled to produce any ACPI
+			debug output.  Bits in debug_layer correspond to a
+			_COMPONENT in an ACPI source file, e.g.,
+			    #define _COMPONENT ACPI_PCI_COMPONENT
+			Bits in debug_level correspond to a level in
+			ACPI_DEBUG_PRINT statements, e.g.,
+			    ACPI_DEBUG_PRINT((ACPI_DB_INFO, ...
+			The debug_level mask defaults to "info".  See
+			Documentation/acpi/debug.txt for more information about
+			debug layers and levels.
+
+			Enable processor driver info messages:
+			    acpi.debug_layer=0x20000000
+			Enable PCI/PCI interrupt routing info messages:
+			    acpi.debug_layer=0x400000
+			Enable AML "Debug" output, i.e., stores to the Debug
+			object while interpreting AML:
+			    acpi.debug_layer=0xffffffff acpi.debug_level=0x2
+			Enable all messages related to ACPI hardware:
+			    acpi.debug_layer=0x2 acpi.debug_level=0xffffffff
+
+			Some values produce so much output that the system is
+			unusable.  The "log_buf_len" parameter may be useful
+			if you need to capture more output.
+
+	acpi_enforce_resources=	[ACPI]
+			{ strict | lax | no }
+			Check for resource conflicts between native drivers
+			and ACPI OperationRegions (SystemIO and SystemMemory
+			only). IO ports and memory declared in ACPI might be
+			used by the ACPI subsystem in arbitrary AML code and
+			can interfere with legacy drivers.
+			strict (default): access to resources claimed by ACPI
+			is denied; legacy drivers trying to access reserved
+			resources will fail to bind to device using them.
+			lax: access to resources claimed by ACPI is allowed;
+			legacy drivers trying to access reserved resources
+			will bind successfully but a warning message is logged.
+			no: ACPI OperationRegions are not marked as reserved,
+			no further checks are performed.
+
+	acpi_force_table_verification	[HW,ACPI]
+			Enable table checksum verification during early stage.
+			By default, this is disabled due to x86 early mapping
+			size limitation.
+
+	acpi_irq_balance [HW,ACPI]
+			ACPI will balance active IRQs
+			default in APIC mode
+
+	acpi_irq_nobalance [HW,ACPI]
+			ACPI will not move active IRQs (default)
+			default in PIC mode
+
+	acpi_irq_isa=	[HW,ACPI] If irq_balance, mark listed IRQs used by ISA
+			Format: <irq>,<irq>...
+
+	acpi_irq_pci=	[HW,ACPI] If irq_balance, clear listed IRQs for
+			use by PCI
+			Format: <irq>,<irq>...
+
+	acpi_mask_gpe=  [HW,ACPI]
+			Due to the existence of _Lxx/_Exx, some GPEs triggered
+			by unsupported hardware/firmware features can result in
+                        GPE floodings that cannot be automatically disabled by
+                        the GPE dispatcher.
+			This facility can be used to prevent such uncontrolled
+			GPE floodings.
+			Format: <int>
+			Support masking of GPEs numbered from 0x00 to 0x7f.
+
+	acpi_no_auto_serialize	[HW,ACPI]
+			Disable auto-serialization of AML methods
+			AML control methods that contain the opcodes to create
+			named objects will be marked as "Serialized" by the
+			auto-serialization feature.
+			This feature is enabled by default.
+			This option allows to turn off the feature.
+
+	acpi_no_memhotplug [ACPI] Disable memory hotplug.  Useful for kdump
+			   kernels.
+
+	acpi_no_static_ssdt	[HW,ACPI]
+			Disable installation of static SSDTs at early boot time
+			By default, SSDTs contained in the RSDT/XSDT will be
+			installed automatically and they will appear under
+			/sys/firmware/acpi/tables.
+			This option turns off this feature.
+			Note that specifying this option does not affect
+			dynamic table installation which will install SSDT
+			tables to /sys/firmware/acpi/tables/dynamic.
+
+	acpi_rsdp=	[ACPI,EFI,KEXEC]
+			Pass the RSDP address to the kernel, mostly used
+			on machines running EFI runtime service to boot the
+			second kernel for kdump.
+
+	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
+			Format: To spoof as Windows 98: ="Microsoft Windows"
+
+	acpi_rev_override [ACPI] Override the _REV object to return 5 (instead
+			of 2 which is mandated by ACPI 6) as the supported ACPI
+			specification revision (when using this switch, it may
+			be necessary to carry out a cold reboot _twice_ in a
+			row to make it take effect on the platform firmware).
+
+	acpi_osi=	[HW,ACPI] Modify list of supported OS interface strings
+			acpi_osi="string1"	# add string1
+			acpi_osi="!string2"	# remove string2
+			acpi_osi=!*		# remove all strings
+			acpi_osi=!		# disable all built-in OS vendor
+						  strings
+			acpi_osi=!!		# enable all built-in OS vendor
+						  strings
+			acpi_osi=		# disable all strings
+
+			'acpi_osi=!' can be used in combination with single or
+			multiple 'acpi_osi="string1"' to support specific OS
+			vendor string(s).  Note that such command can only
+			affect the default state of the OS vendor strings, thus
+			it cannot affect the default state of the feature group
+			strings and the current state of the OS vendor strings,
+			specifying it multiple times through kernel command line
+			is meaningless.  This command is useful when one do not
+			care about the state of the feature group strings which
+			should be controlled by the OSPM.
+			Examples:
+			  1. 'acpi_osi=! acpi_osi="Windows 2000"' is equivalent
+			     to 'acpi_osi="Windows 2000" acpi_osi=!', they all
+			     can make '_OSI("Windows 2000")' TRUE.
+
+			'acpi_osi=' cannot be used in combination with other
+			'acpi_osi=' command lines, the _OSI method will not
+			exist in the ACPI namespace.  NOTE that such command can
+			only affect the _OSI support state, thus specifying it
+			multiple times through kernel command line is also
+			meaningless.
+			Examples:
+			  1. 'acpi_osi=' can make 'CondRefOf(_OSI, Local1)'
+			     FALSE.
+
+			'acpi_osi=!*' can be used in combination with single or
+			multiple 'acpi_osi="string1"' to support specific
+			string(s).  Note that such command can affect the
+			current state of both the OS vendor strings and the
+			feature group strings, thus specifying it multiple times
+			through kernel command line is meaningful.  But it may
+			still not able to affect the final state of a string if
+			there are quirks related to this string.  This command
+			is useful when one want to control the state of the
+			feature group strings to debug BIOS issues related to
+			the OSPM features.
+			Examples:
+			  1. 'acpi_osi="Module Device" acpi_osi=!*' can make
+			     '_OSI("Module Device")' FALSE.
+			  2. 'acpi_osi=!* acpi_osi="Module Device"' can make
+			     '_OSI("Module Device")' TRUE.
+			  3. 'acpi_osi=! acpi_osi=!* acpi_osi="Windows 2000"' is
+			     equivalent to
+			     'acpi_osi=!* acpi_osi=! acpi_osi="Windows 2000"'
+			     and
+			     'acpi_osi=!* acpi_osi="Windows 2000" acpi_osi=!',
+			     they all will make '_OSI("Windows 2000")' TRUE.
+
+	acpi_pm_good	[X86]
+			Override the pmtimer bug detection: force the kernel
+			to assume that this machine's pmtimer latches its value
+			and always returns good values.
+
+	acpi_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
+			Format: { level | edge | high | low }
+
+	acpi_skip_timer_override [HW,ACPI]
+			Recognize and ignore IRQ0/pin2 Interrupt Override.
+			For broken nForce2 BIOS resulting in XT-PIC timer.
+
+	acpi_sleep=	[HW,ACPI] Sleep options
+			Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
+				  old_ordering, nonvs, sci_force_enable }
+			See Documentation/power/video.txt for information on
+			s3_bios and s3_mode.
+			s3_beep is for debugging; it makes the PC's speaker beep
+			as soon as the kernel's real-mode entry point is called.
+			s4_nohwsig prevents ACPI hardware signature from being
+			used during resume from hibernation.
+			old_ordering causes the ACPI 1.0 ordering of the _PTS
+			control method, with respect to putting devices into
+			low power states, to be enforced (the ACPI 2.0 ordering
+			of _PTS is used by default).
+			nonvs prevents the kernel from saving/restoring the
+			ACPI NVS memory during suspend/hibernation and resume.
+			sci_force_enable causes the kernel to set SCI_EN directly
+			on resume from S1/S3 (which is against the ACPI spec,
+			but some broken systems don't work without it).
+
+	acpi_use_timer_override [HW,ACPI]
+			Use timer override. For some broken Nvidia NF5 boards
+			that require a timer override, but don't have HPET
+
+	add_efi_memmap	[EFI; X86] Include EFI memory map in
+			kernel's map of available physical RAM.
+
+	agp=		[AGP]
+			{ off | try_unsupported }
+			off: disable AGP support
+			try_unsupported: try to drive unsupported chipsets
+				(may crash computer or cause data corruption)
+
+	ALSA		[HW,ALSA]
+			See Documentation/sound/alsa/alsa-parameters.txt
+
+	alignment=	[KNL,ARM]
+			Allow the default userspace alignment fault handler
+			behaviour to be specified.  Bit 0 enables warnings,
+			bit 1 enables fixups, and bit 2 sends a segfault.
+
+	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
+
+	alloc_snapshot	[FTRACE]
+			Allocate the ftrace snapshot buffer on boot up when the
+			main buffer is allocated. This is handy if debugging
+			and you need to use tracing_snapshot() on boot up, and
+			do not want to use tracing_snapshot_alloc() as it needs
+			to be done where GFP_KERNEL allocations are allowed.
+
+	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
+				    they are unmapped. Otherwise they are
+				    flushed before they will be reused, which
+				    is a lot of faster
+			off	  - do not initialize any AMD IOMMU found in
+				    the system
+			force_isolation - Force device isolation for all
+					  devices. The IOMMU driver is not
+					  allowed anymore to lift isolation
+					  requirements as needed. This option
+					  does not override iommu=pt
+
+	amd_iommu_dump=	[HW,X86-64]
+			Enable AMD IOMMU driver option to dump the ACPI table
+			for AMD IOMMU. With this option enabled, AMD IOMMU
+			driver will print ACPI tables for AMD IOMMU during
+			IOMMU initialization.
+
+	amd_iommu_intr=	[HW,X86-64]
+			Specifies one of the following AMD IOMMU interrupt
+			remapping modes:
+			legacy     - Use legacy interrupt remapping mode.
+			vapic      - Use virtual APIC mode, which allows IOMMU
+			             to inject interrupts directly into guest.
+			             This mode requires kvm-amd.avic=1.
+			             (Default when IOMMU HW support is present.)
+
+	amijoy.map=	[HW,JOY] Amiga joystick support
+			Map of devices attached to JOY0DAT and JOY1DAT
+			Format: <a>,<b>
+			See also Documentation/input/joystick.txt
+
+	analog.map=	[HW,JOY] Analog joystick and gamepad support
+			Specifies type or capabilities of an analog joystick
+			connected to one of 16 gameports
+			Format: <type1>,<type2>,..<type16>
+
+	apc=		[HW,SPARC]
+			Power management functions (SPARCstation-4/5 + deriv.)
+			Format: noidle
+			Disable APC CPU standby support. SPARCstation-Fox does
+			not play well with APC CPU idle - disable it if you have
+			APC and your system crashes randomly.
+
+	apic=		[APIC,X86-32] Advanced Programmable Interrupt Controller
+			Change the output verbosity whilst booting
+			Format: { quiet (default) | verbose | debug }
+			Change the amount of debugging information output
+			when initialising the APIC and IO-APIC components.
+
+	apic_extnmi=	[APIC,X86] External NMI delivery setting
+			Format: { bsp (default) | all | none }
+			bsp:  External NMI is delivered only to CPU 0
+			all:  External NMIs are broadcast to all CPUs as a
+			      backup of CPU 0
+			none: External NMI is masked for all CPUs. This is
+			      useful so that a dump capture kernel won't be
+			      shot down by NMI
+
+	autoconf=	[IPV6]
+			See Documentation/networking/ipv6.txt.
+
+	show_lapic=	[APIC,X86] Advanced Programmable Interrupt Controller
+			Limit apic dumping. The parameter defines the maximal
+			number of local apics being dumped. Also it is possible
+			to set it to "all" by meaning -- no limit here.
+			Format: { 1 (default) | 2 | ... | all }.
+			The parameter valid if only apic=debug or
+			apic=verbose is specified.
+			Example: apic=debug show_lapic=all
+
+	apm=		[APM] Advanced Power Management
+			See header of arch/x86/kernel/apm_32.c.
+
+	arcrimi=	[HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
+			Format: <io>,<irq>,<nodeID>
+
+	ataflop=	[HW,M68k]
+
+	atarimouse=	[HW,MOUSE] Atari Mouse
+
+	atkbd.extra=	[HW] Enable extra LEDs and keys on IBM RapidAccess,
+			EzKey and similar keyboards
+
+	atkbd.reset=	[HW] Reset keyboard during initialization
+
+	atkbd.set=	[HW] Select keyboard code set
+			Format: <int> (2 = AT (default), 3 = PS/2)
+
+	atkbd.scroll=	[HW] Enable scroll wheel on MS Office and similar
+			keyboards
+
+	atkbd.softraw=	[HW] Choose between synthetic and real raw mode
+			Format: <bool> (0 = real, 1 = synthetic (default))
+
+	atkbd.softrepeat= [HW]
+			Use software keyboard repeat
+
+	audit=		[KNL] Enable the audit sub-system
+			Format: { "0" | "1" } (0 = disabled, 1 = enabled)
+			0 - kernel audit is disabled and can not be enabled
+			    until the next reboot
+			unset - kernel audit is initialized but disabled and
+			    will be fully enabled by the userspace auditd.
+			1 - kernel audit is initialized and partially enabled,
+			    storing at most audit_backlog_limit messages in
+			    RAM until it is fully enabled by the userspace
+			    auditd.
+			Default: unset
+
+	audit_backlog_limit= [KNL] Set the audit queue size limit.
+			Format: <int> (must be >=0)
+			Default: 64
+
+	bau=		[X86_UV] Enable the BAU on SGI UV.  The default
+			behavior is to disable the BAU (i.e. bau=0).
+			Format: { "0" | "1" }
+			0 - Disable the BAU.
+			1 - Enable the BAU.
+			unset - Disable the BAU.
+
+	baycom_epp=	[HW,AX25]
+			Format: <io>,<mode>
+
+	baycom_par=	[HW,AX25] BayCom Parallel Port AX.25 Modem
+			Format: <io>,<mode>
+			See header of drivers/net/hamradio/baycom_par.c.
+
+	baycom_ser_fdx=	[HW,AX25]
+			BayCom Serial Port AX.25 Modem (Full Duplex Mode)
+			Format: <io>,<irq>,<mode>[,<baud>]
+			See header of drivers/net/hamradio/baycom_ser_fdx.c.
+
+	baycom_ser_hdx=	[HW,AX25]
+			BayCom Serial Port AX.25 Modem (Half Duplex Mode)
+			Format: <io>,<irq>,<mode>
+			See header of drivers/net/hamradio/baycom_ser_hdx.c.
+
+	blkdevparts=	Manual partition parsing of block device(s) for
+			embedded devices based on command line input.
+			See Documentation/block/cmdline-partition.txt
+
+	boot_delay=	Milliseconds to delay each printk during boot.
+			Values larger than 10 seconds (10000) are changed to
+			no delay (0).
+			Format: integer
+
+	bootmem_debug	[KNL] Enable bootmem allocator debug messages.
+
+	bert_disable	[ACPI]
+			Disable BERT OS support on buggy BIOSes.
+
+	bttv.card=	[HW,V4L] bttv (bt848 + bt878 based grabber cards)
+	bttv.radio=	Most important insmod options are available as
+			kernel args too.
+	bttv.pll=	See Documentation/video4linux/bttv/Insmod-options
+	bttv.tuner=
+
+	bulk_remove=off	[PPC]  This parameter disables the use of the pSeries
+			firmware feature for flushing multiple hpte entries
+			at a time.
+
+	c101=		[NET] Moxa C101 synchronous serial card
+
+	cachesize=	[BUGS=X86-32] Override level 2 CPU cache size detection.
+			Sometimes CPU hardware bugs make them report the cache
+			size incorrectly. The kernel will attempt work arounds
+			to fix known problems, but for some CPUs it is not
+			possible to determine what the correct size should be.
+			This option provides an override for these situations.
+
+	ca_keys=	[KEYS] This parameter identifies a specific key(s) on
+			the system trusted keyring to be used for certificate
+			trust validation.
+			format: { id:<keyid> | builtin }
+
+	cca=		[MIPS] Override the kernel pages' cache coherency
+			algorithm.  Accepted values range from 0 to 7
+			inclusive. See arch/mips/include/asm/pgtable-bits.h
+			for platform specific values (SB1, Loongson3 and
+			others).
+
+	ccw_timeout_log [S390]
+			See Documentation/s390/CommonIO for details.
+
+	cgroup_disable= [KNL] Disable a particular controller
+			Format: {name of the controller(s) to disable}
+			The effects of cgroup_disable=foo are:
+			- foo isn't auto-mounted if you mount all cgroups in
+			  a single hierarchy
+			- foo isn't visible as an individually mountable
+			  subsystem
+			{Currently only "memory" controller deal with this and
+			cut the overhead, others just disable the usage. So
+			only cgroup_disable=memory is actually worthy}
+
+	cgroup_no_v1=	[KNL] Disable one, multiple, all cgroup controllers in v1
+			Format: { controller[,controller...] | "all" }
+			Like cgroup_disable, but only applies to cgroup v1;
+			the blacklisted controllers remain available in cgroup2.
+
+	cgroup.memory=	[KNL] Pass options to the cgroup memory controller.
+			Format: <string>
+			nosocket -- Disable socket memory accounting.
+			nokmem -- Disable kernel memory accounting.
+
+	checkreqprot	[SELINUX] Set initial checkreqprot flag value.
+			Format: { "0" | "1" }
+			See security/selinux/Kconfig help text.
+			0 -- check protection applied by kernel (includes
+				any implied execute protection).
+			1 -- check protection requested by application.
+			Default value is set via a kernel config option.
+			Value can be changed at runtime via
+				/selinux/checkreqprot.
+
+	cio_ignore=	[S390]
+			See Documentation/s390/CommonIO for details.
+	clk_ignore_unused
+			[CLK]
+			Prevents the clock framework from automatically gating
+			clocks that have not been explicitly enabled by a Linux
+			device driver but are enabled in hardware at reset or
+			by the bootloader/firmware. Note that this does not
+			force such clocks to be always-on nor does it reserve
+			those clocks in any way. This parameter is useful for
+			debug and development, but should not be needed on a
+			platform with proper driver support.  For more
+			information, see Documentation/clk.txt.
+
+	clock=		[BUGS=X86-32, HW] gettimeofday clocksource override.
+			[Deprecated]
+			Forces specified clocksource (if available) to be used
+			when calculating gettimeofday(). If specified
+			clocksource is not available, it defaults to PIT.
+			Format: { pit | tsc | cyclone | pmtmr }
+
+	clocksource=	Override the default clocksource
+			Format: <string>
+			Override the default clocksource and use the clocksource
+			with the name specified.
+			Some clocksource names to choose from, depending on
+			the platform:
+			[all] jiffies (this is the base, fallback clocksource)
+			[ACPI] acpi_pm
+			[ARM] imx_timer1,OSTS,netx_timer,mpu_timer2,
+				pxa_timer,timer3,32k_counter,timer0_1
+			[AVR32] avr32
+			[X86-32] pit,hpet,tsc;
+				scx200_hrt on Geode; cyclone on IBM x440
+			[MIPS] MIPS
+			[PARISC] cr16
+			[S390] tod
+			[SH] SuperH
+			[SPARC64] tick
+			[X86-64] hpet,tsc
+
+	clocksource.arm_arch_timer.evtstrm=
+			[ARM,ARM64]
+			Format: <bool>
+			Enable/disable the eventstream feature of the ARM
+			architected timer so that code using WFE-based polling
+			loops can be debugged more effectively on production
+			systems.
+
+	clocksource.arm_arch_timer.fsl-a008585=
+			[ARM64]
+			Format: <bool>
+			Enable/disable the workaround of Freescale/NXP
+			erratum A-008585.  This can be useful for KVM
+			guests, if the guest device tree doesn't show the
+			erratum.  If unspecified, the workaround is
+			enabled based on the device tree.
+
+	clearcpuid=BITNUM [X86]
+			Disable CPUID feature X for the kernel. See
+			arch/x86/include/asm/cpufeatures.h for the valid bit
+			numbers. Note the Linux specific bits are not necessarily
+			stable over kernel options, but the vendor specific
+			ones should be.
+			Also note that user programs calling CPUID directly
+			or using the feature without checking anything
+			will still see it. This just prevents it from
+			being used by the kernel or shown in /proc/cpuinfo.
+			Also note the kernel might malfunction if you disable
+			some critical bits.
+
+	cma=nn[MG]@[start[MG][-end[MG]]]
+			[ARM,X86,KNL]
+			Sets the size of kernel global memory area for
+			contiguous memory allocations and optionally the
+			placement constraint by the physical address range of
+			memory allocations. A value of 0 disables CMA
+			altogether. For more information, see
+			include/linux/dma-contiguous.h
+
+	cmo_free_hint=	[PPC] Format: { yes | no }
+			Specify whether pages are marked as being inactive
+			when they are freed.  This is used in CMO environments
+			to determine OS memory pressure for page stealing by
+			a hypervisor.
+			Default: yes
+
+	coherent_pool=nn[KMG]	[ARM,KNL]
+			Sets the size of memory pool for coherent, atomic dma
+			allocations, by default set to 256K.
+
+	code_bytes	[X86] How many bytes of object code to print
+			in an oops report.
+			Range: 0 - 8192
+			Default: 64
+
+	com20020=	[HW,NET] ARCnet - COM20020 chipset
+			Format:
+			<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
+
+	com90io=	[HW,NET] ARCnet - COM90xx chipset (IO-mapped buffers)
+			Format: <io>[,<irq>]
+
+	com90xx=	[HW,NET]
+			ARCnet - COM90xx chipset (memory-mapped buffers)
+			Format: <io>[,<irq>[,<memstart>]]
+
+	condev=		[HW,S390] console device
+	conmode=
+
+	console=	[KNL] Output console device and options.
+
+		tty<n>	Use the virtual console device <n>.
+
+		ttyS<n>[,options]
+		ttyUSB0[,options]
+			Use the specified serial port.  The options are of
+			the form "bbbbpnf", where "bbbb" is the baud rate,
+			"p" is parity ("n", "o", or "e"), "n" is number of
+			bits, and "f" is flow control ("r" for RTS or
+			omit it).  Default is "9600n8".
+
+			See Documentation/admin-guide/serial-console.rst for more
+			information.  See
+			Documentation/networking/netconsole.txt for an
+			alternative.
+
+		uart[8250],io,<addr>[,options]
+		uart[8250],mmio,<addr>[,options]
+		uart[8250],mmio16,<addr>[,options]
+		uart[8250],mmio32,<addr>[,options]
+		uart[8250],0x<addr>[,options]
+			Start an early, polled-mode console on the 8250/16550
+			UART at the specified I/O port or MMIO address,
+			switching to the matching ttyS device later.
+			MMIO inter-register address stride is either 8-bit
+			(mmio), 16-bit (mmio16), or 32-bit (mmio32).
+			If none of [io|mmio|mmio16|mmio32], <addr> is assumed
+			to be equivalent to 'mmio'. 'options' are specified in
+			the same format described for ttyS above; if unspecified,
+			the h/w is not re-initialized.
+
+		hvc<n>	Use the hypervisor console device <n>. This is for
+			both Xen and PowerPC hypervisors.
+
+                If the device connected to the port is not a TTY but a braille
+                device, prepend "brl," before the device type, for instance
+			console=brl,ttyS0
+		For now, only VisioBraille is supported.
+
+	consoleblank=	[KNL] The console blank (screen saver) timeout in
+			seconds. Defaults to 10*60 = 10mins. A value of 0
+			disables the blank timer.
+
+	coredump_filter=
+			[KNL] Change the default value for
+			/proc/<pid>/coredump_filter.
+			See also Documentation/filesystems/proc.txt.
+
+	cpuidle.off=1	[CPU_IDLE]
+			disable the cpuidle sub-system
+
+	cpu_init_udelay=N
+			[X86] Delay for N microsec between assert and de-assert
+			of APIC INIT to start processors.  This delay occurs
+			on every CPU online, such as boot, and resume from suspend.
+			Default: 10000
+
+	cpcihp_generic=	[HW,PCI] Generic port I/O CompactPCI driver
+			Format:
+			<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
+
+	crashkernel=size[KMG][@offset[KMG]]
+			[KNL] Using kexec, Linux can switch to a 'crash kernel'
+			upon panic. This parameter reserves the physical
+			memory region [offset, offset + size] for that kernel
+			image. If '@offset' is omitted, then a suitable offset
+			is selected automatically. Check
+			Documentation/kdump/kdump.txt for further details.
+
+	crashkernel=range1:size1[,range2:size2,...][@offset]
+			[KNL] Same as above, but depends on the memory
+			in the running system. The syntax of range is
+			start-[end] where start and end are both
+			a memory unit (amount[KMG]). See also
+			Documentation/kdump/kdump.txt for an example.
+
+	crashkernel=size[KMG],high
+			[KNL, x86_64] range could be above 4G. Allow kernel
+			to allocate physical memory region from top, so could
+			be above 4G if system have more than 4G ram installed.
+			Otherwise memory region will be allocated below 4G, if
+			available.
+			It will be ignored if crashkernel=X is specified.
+	crashkernel=size[KMG],low
+			[KNL, x86_64] range under 4G. When crashkernel=X,high
+			is passed, kernel could allocate physical memory region
+			above 4G, that cause second kernel crash on system
+			that require some amount of low memory, e.g. swiotlb
+			requires at least 64M+32K low memory, also enough extra
+			low memory is needed to make sure DMA buffers for 32-bit
+			devices won't run out. Kernel would try to allocate at
+			at least 256M below 4G automatically.
+			This one let user to specify own low range under 4G
+			for second kernel instead.
+			0: to disable low allocation.
+			It will be ignored when crashkernel=X,high is not used
+			or memory reserved is below 4G.
+
+	cryptomgr.notests
+                        [KNL] Disable crypto self-tests
+
+	cs89x0_dma=	[HW,NET]
+			Format: <dma>
+
+	cs89x0_media=	[HW,NET]
+			Format: { rj45 | aui | bnc }
+
+	dasd=		[HW,NET]
+			See header of drivers/s390/block/dasd_devmap.c.
+
+	db9.dev[2|3]=	[HW,JOY] Multisystem joystick support via parallel port
+			(one device per port)
+			Format: <port#>,<type>
+			See also Documentation/input/joystick-parport.txt
+
+	ddebug_query=   [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
+			time. See Documentation/dynamic-debug-howto.txt for
+			details.  Deprecated, see dyndbg.
+
+	debug		[KNL] Enable kernel debugging (events log level).
+
+	debug_locks_verbose=
+			[KNL] verbose self-tests
+			Format=<0|1>
+			Print debugging info while doing the locking API
+			self-tests.
+			We default to 0 (no extra messages), setting it to
+			1 will print _a lot_ more information - normally
+			only useful to kernel developers.
+
+	debug_objects	[KNL] Enable object debugging
+
+	no_debug_objects
+			[KNL] Disable object debugging
+
+	debug_guardpage_minorder=
+			[KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
+			parameter allows control of the order of pages that will
+			be intentionally kept free (and hence protected) by the
+			buddy allocator. Bigger value increase the probability
+			of catching random memory corruption, but reduce the
+			amount of memory for normal system use. The maximum
+			possible value is MAX_ORDER/2.  Setting this parameter
+			to 1 or 2 should be enough to identify most random
+			memory corruption problems caused by bugs in kernel or
+			driver code when a CPU writes to (or reads from) a
+			random memory location. Note that there exists a class
+			of memory corruptions problems caused by buggy H/W or
+			F/W or by drivers badly programing DMA (basically when
+			memory is written at bus level and the CPU MMU is
+			bypassed) which are not detectable by
+			CONFIG_DEBUG_PAGEALLOC, hence this option will not help
+			tracking down these problems.
+
+	debug_pagealloc=
+			[KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
+			parameter enables the feature at boot time. In
+			default, it is disabled. We can avoid allocating huge
+			chunk of memory for debug pagealloc if we don't enable
+			it at boot time and the system will work mostly same
+			with the kernel built without CONFIG_DEBUG_PAGEALLOC.
+			on: enable the feature
+
+	debugpat	[X86] Enable PAT debugging
+
+	decnet.addr=	[HW,NET]
+			Format: <area>[,<node>]
+			See also Documentation/networking/decnet.txt.
+
+	default_hugepagesz=
+			[same as hugepagesz=] The size of the default
+			HugeTLB page size. This is the size represented by
+			the legacy /proc/ hugepages APIs, used for SHM, and
+			default size when mounting hugetlbfs filesystems.
+			Defaults to the default architecture's huge page size
+			if not specified.
+
+	dhash_entries=	[KNL]
+			Set number of hash buckets for dentry cache.
+
+	disable_1tb_segments [PPC]
+			Disables the use of 1TB hash page table segments. This
+			causes the kernel to fall back to 256MB segments which
+			can be useful when debugging issues that require an SLB
+			miss to occur.
+
+	disable=	[IPV6]
+			See Documentation/networking/ipv6.txt.
+
+	disable_radix	[PPC]
+			Disable RADIX MMU mode on POWER9
+
+	disable_cpu_apicid= [X86,APIC,SMP]
+			Format: <int>
+			The number of initial APIC ID for the
+			corresponding CPU to be disabled at boot,
+			mostly used for the kdump 2nd kernel to
+			disable BSP to wake up multiple CPUs without
+			causing system reset or hang due to sending
+			INIT from AP to BSP.
+
+	disable_ddw     [PPC/PSERIES]
+			Disable Dynamic DMA Window support. Use this if
+			to workaround buggy firmware.
+
+	disable_ipv6=	[IPV6]
+			See Documentation/networking/ipv6.txt.
+
+	disable_mtrr_cleanup [X86]
+			The kernel tries to adjust MTRR layout from continuous
+			to discrete, to make X server driver able to add WB
+			entry later. This parameter disables that.
+
+	disable_mtrr_trim [X86, Intel and AMD only]
+			By default the kernel will trim any uncacheable
+			memory out of your available memory pool based on
+			MTRR settings.  This parameter disables that behavior,
+			possibly causing your machine to run very slowly.
+
+	disable_timer_pin_1 [X86]
+			Disable PIN 1 of APIC timer
+			Can be useful to work around chipset bugs.
+
+	dis_ucode_ldr	[X86] Disable the microcode loader.
+
+	dma_debug=off	If the kernel is compiled with DMA_API_DEBUG support,
+			this option disables the debugging code at boot.
+
+	dma_debug_entries=<number>
+			This option allows to tune the number of preallocated
+			entries for DMA-API debugging code. One entry is
+			required per DMA-API allocation. Use this if the
+			DMA-API debugging code disables itself because the
+			architectural default is too low.
+
+	dma_debug_driver=<driver_name>
+			With this option the DMA-API debugging driver
+			filter feature can be enabled at boot time. Just
+			pass the driver to filter for as the parameter.
+			The filter can be disabled or changed to another
+			driver later using sysfs.
+
+	drm_kms_helper.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
+			Broken monitors, graphic adapters, KVMs and EDIDless
+			panels may send no or incorrect EDID data sets.
+			This parameter allows to specify an EDID data sets
+			in the /lib/firmware directory that are used instead.
+			Generic built-in EDID data sets are used, if one of
+			edid/1024x768.bin, edid/1280x1024.bin,
+			edid/1680x1050.bin, or edid/1920x1080.bin is given
+			and no file with the same name exists. Details and
+			instructions how to build your own EDID data are
+			available in Documentation/EDID/HOWTO.txt. An EDID
+			data set will only be used for a particular connector,
+			if its name and a colon are prepended to the EDID
+			name. Each connector may use a unique EDID data
+			set by separating the files with a comma.  An EDID
+			data set with no connector name will be used for
+			any connectors not explicitly specified.
+
+	dscc4.setup=	[NET]
+
+	dump_apple_properties	[X86]
+			Dump name and content of EFI device properties on
+			x86 Macs.  Useful for driver authors to determine
+			what data is available or for reverse-engineering.
+
+	dyndbg[="val"]		[KNL,DYNAMIC_DEBUG]
+	module.dyndbg[="val"]
+			Enable debug messages at boot time.  See
+			Documentation/dynamic-debug-howto.txt for details.
+
+	nompx		[X86] Disables Intel Memory Protection Extensions.
+			See Documentation/x86/intel_mpx.txt for more
+			information about the feature.
+
+	nopku		[X86] Disable Memory Protection Keys CPU feature found
+			in some Intel CPUs.
+
+	module.async_probe [KNL]
+			Enable asynchronous probe on this module.
+
+	early_ioremap_debug [KNL]
+			Enable debug messages in early_ioremap support. This
+			is useful for tracking down temporary early mappings
+			which are not unmapped.
+
+	earlycon=	[KNL] Output early console device and options.
+
+			When used with no options, the early console is
+			determined by the stdout-path property in device
+			tree's chosen node.
+
+		cdns,<addr>[,options]
+			Start an early, polled-mode console on a Cadence
+			(xuartps) serial port at the specified address. Only
+			supported option is baud rate. If baud rate is not
+			specified, the serial port must already be setup and
+			configured.
+
+		uart[8250],io,<addr>[,options]
+		uart[8250],mmio,<addr>[,options]
+		uart[8250],mmio32,<addr>[,options]
+		uart[8250],mmio32be,<addr>[,options]
+		uart[8250],0x<addr>[,options]
+			Start an early, polled-mode console on the 8250/16550
+			UART at the specified I/O port or MMIO address.
+			MMIO inter-register address stride is either 8-bit
+			(mmio) or 32-bit (mmio32 or mmio32be).
+			If none of [io|mmio|mmio32|mmio32be], <addr> is assumed
+			to be equivalent to 'mmio'. 'options' are specified
+			in the same format described for "console=ttyS<n>"; if
+			unspecified, the h/w is not initialized.
+
+		pl011,<addr>
+		pl011,mmio32,<addr>
+			Start an early, polled-mode console on a pl011 serial
+			port at the specified address. The pl011 serial port
+			must already be setup and configured. Options are not
+			yet supported.  If 'mmio32' is specified, then only
+			the driver will use only 32-bit accessors to read/write
+			the device registers.
+
+		meson,<addr>
+			Start an early, polled-mode console on a meson serial
+			port at the specified address. The serial port must
+			already be setup and configured. Options are not yet
+			supported.
+
+		msm_serial,<addr>
+			Start an early, polled-mode console on an msm serial
+			port at the specified address. The serial port
+			must already be setup and configured. Options are not
+			yet supported.
+
+		msm_serial_dm,<addr>
+			Start an early, polled-mode console on an msm serial
+			dm port at the specified address. The serial port
+			must already be setup and configured. Options are not
+			yet supported.
+
+		smh	Use ARM semihosting calls for early console.
+
+		s3c2410,<addr>
+		s3c2412,<addr>
+		s3c2440,<addr>
+		s3c6400,<addr>
+		s5pv210,<addr>
+		exynos4210,<addr>
+			Use early console provided by serial driver available
+			on Samsung SoCs, requires selecting proper type and
+			a correct base address of the selected UART port. The
+			serial port must already be setup and configured.
+			Options are not yet supported.
+
+		lpuart,<addr>
+		lpuart32,<addr>
+			Use early console provided by Freescale LP UART driver
+			found on Freescale Vybrid and QorIQ LS1021A processors.
+			A valid base address must be provided, and the serial
+			port must already be setup and configured.
+
+		armada3700_uart,<addr>
+			Start an early, polled-mode console on the
+			Armada 3700 serial port at the specified
+			address. The serial port must already be setup
+			and configured. Options are not yet supported.
+
+	earlyprintk=	[X86,SH,BLACKFIN,ARM,M68k]
+			earlyprintk=vga
+			earlyprintk=efi
+			earlyprintk=xen
+			earlyprintk=serial[,ttySn[,baudrate]]
+			earlyprintk=serial[,0x...[,baudrate]]
+			earlyprintk=ttySn[,baudrate]
+			earlyprintk=dbgp[debugController#]
+			earlyprintk=pciserial,bus:device.function[,baudrate]
+
+			earlyprintk is useful when the kernel crashes before
+			the normal console is initialized. It is not enabled by
+			default because it has some cosmetic problems.
+
+			Append ",keep" to not disable it when the real console
+			takes over.
+
+			Only one of vga, efi, serial, or usb debug port can
+			be used at a time.
+
+			Currently only ttyS0 and ttyS1 may be specified by
+			name.  Other I/O ports may be explicitly specified
+			on some architectures (x86 and arm at least) by
+			replacing ttySn with an I/O port address, like this:
+				earlyprintk=serial,0x1008,115200
+			You can find the port for a given device in
+			/proc/tty/driver/serial:
+				2: uart:ST16650V2 port:00001008 irq:18 ...
+
+			Interaction with the standard serial driver is not
+			very good.
+
+			The VGA and EFI output is eventually overwritten by
+			the real console.
+
+			The xen output can only be used by Xen PV guests.
+
+	edac_report=	[HW,EDAC] Control how to report EDAC event
+			Format: {"on" | "off" | "force"}
+			on: enable EDAC to report H/W event. May be overridden
+			by other higher priority error reporting module.
+			off: disable H/W event reporting through EDAC.
+			force: enforce the use of EDAC to report H/W event.
+			default: on.
+
+	ekgdboc=	[X86,KGDB] Allow early kernel console debugging
+			ekgdboc=kbd
+
+			This is designed to be used in conjunction with
+			the boot argument: earlyprintk=vga
+
+	edd=		[EDD]
+			Format: {"off" | "on" | "skip[mbr]"}
+
+	efi=		[EFI]
+			Format: { "old_map", "nochunk", "noruntime", "debug" }
+			old_map [X86-64]: switch to the old ioremap-based EFI
+			runtime services mapping. 32-bit still uses this one by
+			default.
+			nochunk: disable reading files in "chunks" in the EFI
+			boot stub, as chunking can cause problems with some
+			firmware implementations.
+			noruntime : disable EFI runtime services support
+			debug: enable misc debug output
+
+	efi_no_storage_paranoia [EFI; X86]
+			Using this parameter you can use more than 50% of
+			your efi variable storage. Use this parameter only if
+			you are really sure that your UEFI does sane gc and
+			fulfills the spec otherwise your board may brick.
+
+	efi_fake_mem=	nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI; X86]
+			Add arbitrary attribute to specific memory range by
+			updating original EFI memory map.
+			Region of memory which aa attribute is added to is
+			from ss to ss+nn.
+			If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
+			is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
+			attribute is added to range 0x100000000-0x180000000 and
+			0x10a0000000-0x1120000000.
+
+			Using this parameter you can do debugging of EFI memmap
+			related feature. For example, you can do debugging of
+			Address Range Mirroring feature even if your box
+			doesn't support it.
+
+	efivar_ssdt=	[EFI; X86] Name of an EFI variable that contains an SSDT
+			that is to be dynamically loaded by Linux. If there are
+			multiple variables with the same name but with different
+			vendor GUIDs, all of them will be loaded. See
+			Documentation/acpi/ssdt-overlays.txt for details.
+
+
+	eisa_irq_edge=	[PARISC,HW]
+			See header of drivers/parisc/eisa.c.
+
+	elanfreq=	[X86-32]
+			See comment before function elanfreq_setup() in
+			arch/x86/kernel/cpu/cpufreq/elanfreq.c.
+
+	elevator=	[IOSCHED]
+			Format: {"cfq" | "deadline" | "noop"}
+			See Documentation/block/cfq-iosched.txt and
+			Documentation/block/deadline-iosched.txt for details.
+
+	elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
+			Specifies physical address of start of kernel core
+			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]
+			The kernel tries to adjust MTRR layout from continuous
+			to discrete, to make X server driver able to add WB
+			entry later. This parameter enables that.
+
+	enable_timer_pin_1 [X86]
+			Enable PIN 1 of APIC timer
+			Can be useful to work around chipset bugs
+			(in particular on some ATI chipsets).
+			The kernel tries to set a reasonable default.
+
+	enforcing	[SELINUX] Set initial enforcing status.
+			Format: {"0" | "1"}
+			See security/selinux/Kconfig help text.
+			0 -- permissive (log only, no denials).
+			1 -- enforcing (deny and log).
+			Default value is 0.
+			Value can be changed at runtime via /selinux/enforce.
+
+	erst_disable	[ACPI]
+			Disable Error Record Serialization Table (ERST)
+			support.
+
+	ether=		[HW,NET] Ethernet cards parameters
+			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/.
+
+	floppy=		[HW]
+			See Documentation/blockdev/floppy.txt.
+
+	force_pal_cache_flush
+			[IA-64] Avoid check_sal_cache_flush which may hang on
+			buggy SAL_CACHE_FLUSH implementations. Using this
+			parameter will force ia64_sal_cache_flush to call
+			ia64_pal_cache_flush instead of SAL_CACHE_FLUSH.
+
+	forcepae [X86-32]
+			Forcefully enable Physical Address Extension (PAE).
+			Many Pentium M systems disable PAE but may have a
+			functionally usable PAE implementation.
+			Warning: use of this parameter will taint the kernel
+			and may cause unknown problems.
+
+	ftrace=[tracer]
+			[FTRACE] will set and start the specified tracer
+			as early as possible in order to facilitate early
+			boot debugging.
+
+	ftrace_dump_on_oops[=orig_cpu]
+			[FTRACE] will dump the trace buffers on oops.
+			If no parameter is passed, ftrace will dump
+			buffers of all CPUs, but if you pass orig_cpu, it will
+			dump only the buffer of the CPU that triggered the
+			oops.
+
+	ftrace_filter=[function-list]
+			[FTRACE] Limit the functions traced by the function
+			tracer at boot up. function-list is a comma separated
+			list of functions. This list can be changed at run
+			time by the set_ftrace_filter file in the debugfs
+			tracing directory.
+
+	ftrace_notrace=[function-list]
+			[FTRACE] Do not trace the functions specified in
+			function-list. This list can be changed at run time
+			by the set_ftrace_notrace file in the debugfs
+			tracing directory.
+
+	ftrace_graph_filter=[function-list]
+			[FTRACE] Limit the top level callers functions traced
+			by the function graph tracer at boot up.
+			function-list is a comma separated list of functions
+			that can be changed at run time by the
+			set_graph_function file in the debugfs tracing directory.
+
+	ftrace_graph_notrace=[function-list]
+			[FTRACE] Do not trace from the functions specified in
+			function-list.  This list is a comma separated list of
+			functions that can be changed at run time by the
+			set_graph_notrace file in the debugfs tracing directory.
+
+	gamecon.map[2|3]=
+			[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
+			support via parallel port (up to 5 devices per port)
+			Format: <port#>,<pad1>,<pad2>,<pad3>,<pad4>,<pad5>
+			See also Documentation/input/joystick-parport.txt
+
+	gamma=		[HW,DRM]
+
+	gart_fix_e820=  [X86_64] disable the fix e820 for K8 GART
+			Format: off | on
+			default: on
+
+	gcov_persist=	[GCOV] When non-zero (default), profiling data for
+			kernel modules is saved and remains accessible via
+			debugfs, even when the module is unloaded/reloaded.
+			When zero, profiling data is discarded and associated
+			debugfs files are removed at module unload time.
+
+	gpt		[EFI] Forces disk with valid GPT signature but
+			invalid Protective MBR to be treated as GPT. If the
+			primary GPT is corrupted, it enables the backup/alternate
+			GPT to be used instead.
+
+	grcan.enable0=	[HW] Configuration of physical interface 0. Determines
+			the "Enable 0" bit of the configuration register.
+			Format: 0 | 1
+			Default: 0
+	grcan.enable1=	[HW] Configuration of physical interface 1. Determines
+			the "Enable 0" bit of the configuration register.
+			Format: 0 | 1
+			Default: 0
+	grcan.select=	[HW] Select which physical interface to use.
+			Format: 0 | 1
+			Default: 0
+	grcan.txsize=	[HW] Sets the size of the tx buffer.
+			Format: <unsigned int> such that (txsize & ~0x1fffc0) == 0.
+			Default: 1024
+	grcan.rxsize=	[HW] Sets the size of the rx buffer.
+			Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
+			Default: 1024
+
+	gpio-mockup.gpio_mockup_ranges
+			[HW] Sets the ranges of gpiochip of for this device.
+			Format: <start1>,<end1>,<start2>,<end2>...
+
+	hardlockup_all_cpu_backtrace=
+			[KNL] Should the hard-lockup detector generate
+			backtraces on all cpus.
+			Format: <integer>
+
+	hashdist=	[KNL,NUMA] Large hashes allocated during boot
+			are distributed across NUMA nodes.  Defaults on
+			for 64-bit NUMA, off otherwise.
+			Format: 0 | 1 (for off | on)
+
+	hcl=		[IA-64] SGI's Hardware Graph compatibility layer
+
+	hd=		[EIDE] (E)IDE hard drive subsystem geometry
+			Format: <cyl>,<head>,<sect>
+
+	hest_disable	[ACPI]
+			Disable Hardware Error Source Table (HEST) support;
+			corresponding firmware-first mode error processing
+			logic will be disabled.
+
+	highmem=nn[KMG]	[KNL,BOOT] forces the highmem zone to have an exact
+			size of <nn>. This works even on boxes that have no
+			highmem otherwise. This also works to reduce highmem
+			size on bigger boxes.
+
+	highres=	[KNL] Enable/disable high resolution timer mode.
+			Valid parameters: "on", "off"
+			Default: "on"
+
+	hisax=		[HW,ISDN]
+			See Documentation/isdn/README.HiSax.
+
+	hlt		[BUGS=ARM,SH]
+
+	hpet=		[X86-32,HPET] option to control HPET usage
+			Format: { enable (default) | disable | force |
+				verbose }
+			disable: disable HPET and use PIT instead
+			force: allow force enabled of undocumented chips (ICH4,
+				VIA, nVidia)
+			verbose: show contents of HPET registers during setup
+
+	hpet_mmap=	[X86, HPET_MMAP] Allow userspace to mmap HPET
+			registers.  Default set by CONFIG_HPET_MMAP_DEFAULT.
+
+	hugepages=	[HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
+	hugepagesz=	[HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
+			On x86-64 and powerpc, this option can be specified
+			multiple times interleaved with hugepages= to reserve
+			huge pages of different sizes. Valid pages sizes on
+			x86-64 are 2M (when the CPU supports "pse") and 1G
+			(when the CPU supports the "pdpe1gb" cpuinfo flag).
+
+	hvc_iucv=	[S390] Number of z/VM IUCV hypervisor console (HVC)
+			       terminal devices. Valid values: 0..8
+	hvc_iucv_allow=	[S390] Comma-separated list of z/VM user IDs.
+			       If specified, z/VM IUCV HVC accepts connections
+			       from listed z/VM user IDs only.
+
+	hwthread_map=	[METAG] Comma-separated list of Linux cpu id to
+			        hardware thread id mappings.
+				Format: <cpu>:<hwthread>
+
+	keep_bootcon	[KNL]
+			Do not unregister boot console at start. This is only
+			useful for debugging when something happens in the window
+			between unregistering the boot console and initializing
+			the real console.
+
+	i2c_bus=	[HW] Override the default board specific I2C bus speed
+			     or register an additional I2C bus that is not
+			     registered from board initialization code.
+			     Format:
+			     <bus_id>,<clkrate>
+
+	i8042.debug	[HW] Toggle i8042 debug mode
+	i8042.unmask_kbd_data
+			[HW] Enable printing of interrupt data from the KBD port
+			     (disabled by default, and as a pre-condition
+			     requires that i8042.debug=1 be enabled)
+	i8042.direct	[HW] Put keyboard port into non-translated mode
+	i8042.dumbkbd	[HW] Pretend that controller can only read data from
+			     keyboard and cannot control its state
+			     (Don't attempt to blink the leds)
+	i8042.noaux	[HW] Don't check for auxiliary (== mouse) port
+	i8042.nokbd	[HW] Don't check/create keyboard port
+	i8042.noloop	[HW] Disable the AUX Loopback command while probing
+			     for the AUX port
+	i8042.nomux	[HW] Don't check presence of an active multiplexing
+			     controller
+	i8042.nopnp	[HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
+			     controllers
+	i8042.notimeout	[HW] Ignore timeout condition signalled by controller
+	i8042.reset	[HW] Reset the controller during init, cleanup and
+			     suspend-to-ram transitions, only during s2r
+			     transitions, or never reset
+			Format: { 1 | Y | y | 0 | N | n }
+			1, Y, y: always reset controller
+			0, N, n: don't ever reset controller
+			Default: only on s2r transitions on x86; most other
+			architectures force reset to be always executed
+	i8042.unlock	[HW] Unlock (ignore) the keylock
+	i8042.kbdreset  [HW] Reset device connected to KBD port
+
+	i810=		[HW,DRM]
+
+	i8k.ignore_dmi	[HW] Continue probing hardware even if DMI data
+			indicates that the driver is running on unsupported
+			hardware.
+	i8k.force	[HW] Activate i8k driver even if SMM BIOS signature
+			does not match list of supported models.
+	i8k.power_status
+			[HW] Report power status in /proc/i8k
+			(disabled by default)
+	i8k.restricted	[HW] Allow controlling fans only if SYS_ADMIN
+			capability is set.
+
+	i915.invert_brightness=
+			[DRM] Invert the sense of the variable that is used to
+			set the brightness of the panel backlight. Normally a
+			brightness value of 0 indicates backlight switched off,
+			and the maximum of the brightness value sets the backlight
+			to maximum brightness. If this parameter is set to 0
+			(default) and the machine requires it, or this parameter
+			is set to 1, a brightness value of 0 sets the backlight
+			to maximum brightness, and the maximum of the brightness
+			value switches the backlight off.
+			-1 -- never invert brightness
+			 0 -- machine default
+			 1 -- force brightness inversion
+
+	icn=		[HW,ISDN]
+			Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
+
+	ide-core.nodma=	[HW] (E)IDE subsystem
+			Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc
+			.vlb_clock .pci_clock .noflush .nohpa .noprobe .nowerr
+			.cdrom .chs .ignore_cable are additional options
+			See Documentation/ide/ide.txt.
+
+	ide-generic.probe-mask= [HW] (E)IDE subsystem
+			Format: <int>
+			Probe mask for legacy ISA IDE ports.  Depending on
+			platform up to 6 ports are supported, enabled by
+			setting corresponding bits in the mask to 1.  The
+			default value is 0x0, which has a special meaning.
+			On systems that have PCI, it triggers scanning the
+			PCI bus for the first and the second port, which
+			are then probed.  On systems without PCI the value
+			of 0x0 enables probing the two first ports as if it
+			was 0x3.
+
+	ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
+			Claim all unknown PCI IDE storage controllers.
+
+	idle=		[X86]
+			Format: idle=poll, idle=halt, idle=nomwait
+			Poll forces a polling idle loop that can slightly
+			improve the performance of waking up a idle CPU, but
+			will use a lot of power and make the system run hot.
+			Not recommended.
+			idle=halt: Halt is forced to be used for CPU idle.
+			In such case C2/C3 won't be used again.
+			idle=nomwait: Disable mwait for CPU C-states
+
+	ieee754=	[MIPS] Select IEEE Std 754 conformance mode
+			Format: { strict | legacy | 2008 | relaxed }
+			Default: strict
+
+			Choose which programs will be accepted for execution
+			based on the IEEE 754 NaN encoding(s) supported by
+			the FPU and the NaN encoding requested with the value
+			of an ELF file header flag individually set by each
+			binary.  Hardware implementations are permitted to
+			support either or both of the legacy and the 2008 NaN
+			encoding mode.
+
+			Available settings are as follows:
+			strict	accept binaries that request a NaN encoding
+				supported by the FPU
+			legacy	only accept legacy-NaN binaries, if supported
+				by the FPU
+			2008	only accept 2008-NaN binaries, if supported
+				by the FPU
+			relaxed	accept any binaries regardless of whether
+				supported by the FPU
+
+			The FPU emulator is always able to support both NaN
+			encodings, so if no FPU hardware is present or it has
+			been disabled with 'nofpu', then the settings of
+			'legacy' and '2008' strap the emulator accordingly,
+			'relaxed' straps the emulator for both legacy-NaN and
+			2008-NaN, whereas 'strict' enables legacy-NaN only on
+			legacy processors and both NaN encodings on MIPS32 or
+			MIPS64 CPUs.
+
+			The setting for ABS.fmt/NEG.fmt instruction execution
+			mode generally follows that for the NaN encoding,
+			except where unsupported by hardware.
+
+	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.
+
+	ignore_rlimit_data
+			Ignore RLIMIT_DATA setting for data mappings,
+			print warning at first misuse.  Can be changed via
+			/sys/module/kernel/parameters/ignore_rlimit_data.
+
+	ihash_entries=	[KNL]
+			Set number of hash buckets for inode cache.
+
+	ima_appraise=	[IMA] appraise integrity measurements
+			Format: { "off" | "enforce" | "fix" | "log" }
+			default: "enforce"
+
+	ima_appraise_tcb [IMA]
+			The builtin appraise policy appraises all files
+			owned by uid=0.
+
+	ima_canonical_fmt [IMA]
+			Use the canonical format for the binary runtime
+			measurements, instead of host native format.
+
+	ima_hash=	[IMA]
+			Format: { md5 | sha1 | rmd160 | sha256 | sha384
+				   | sha512 | ... }
+			default: "sha1"
+
+			The list of supported hash algorithms is defined
+			in crypto/hash_info.h.
+
+	ima_policy=	[IMA]
+			The builtin measurement policy to load during IMA
+			setup.  Specyfing "tcb" as the value, measures all
+			programs exec'd, files mmap'd for exec, and all files
+			opened with the read mode bit set by either the
+			effective uid (euid=0) or uid=0.
+			Format: "tcb"
+
+	ima_tcb		[IMA] Deprecated.  Use ima_policy= instead.
+			Load a policy which meets the needs of the Trusted
+			Computing Base.  This means IMA will measure all
+			programs exec'd, files mmap'd for exec, and all files
+			opened for read by uid=0.
+
+	ima_template=   [IMA]
+			Select one of defined IMA measurements template formats.
+			Formats: { "ima" | "ima-ng" | "ima-sig" }
+			Default: "ima-ng"
+
+	ima_template_fmt=
+	                [IMA] Define a custom template format.
+			Format: { "field1|...|fieldN" }
+
+	ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
+			Format: <min_file_size>
+			Set the minimal file size for using asynchronous hash.
+			If left unspecified, ahash usage is disabled.
+
+			ahash performance varies for different data sizes on
+			different crypto accelerators. This option can be used
+			to achieve the best performance for a particular HW.
+
+	ima.ahash_bufsize= [IMA] Asynchronous hash buffer size
+			Format: <bufsize>
+			Set hashing buffer size. Default: 4k.
+
+			ahash performance varies for different chunk sizes on
+			different crypto accelerators. This option can be used
+			to achieve best performance for particular HW.
+
+	init=		[KNL]
+			Format: <full_path>
+			Run specified binary instead of /sbin/init as init
+			process.
+
+	initcall_debug	[KNL] Trace initcalls as they are executed.  Useful
+			for working out where the kernel is dying during
+			startup.
+
+	initcall_blacklist=  [KNL] Do not execute a comma-separated list of
+			initcall functions.  Useful for debugging built-in
+			modules and initcalls.
+
+	initrd=		[BOOT] Specify the location of the initial ramdisk
+
+	init_pkru=	[x86] Specify the default memory protection keys rights
+			register contents for all processes.  0x55555554 by
+			default (disallow access to all but pkey 0).  Can
+			override in debugfs after boot.
+
+	inport.irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver
+			Format: <irq>
+
+	int_pln_enable  [x86] Enable power limit notification interrupt
+
+	integrity_audit=[IMA]
+			Format: { "0" | "1" }
+			0 -- basic integrity auditing messages. (Default)
+			1 -- additional integrity auditing messages.
+
+	intel_iommu=	[DMAR] Intel IOMMU driver (DMAR) option
+		on
+			Enable intel iommu driver.
+		off
+			Disable intel iommu driver.
+		igfx_off [Default Off]
+			By default, gfx is mapped as normal device. If a gfx
+			device has a dedicated DMAR unit, the DMAR unit is
+			bypassed by not enabling DMAR with this option. In
+			this case, gfx device will use physical address for
+			DMA.
+		forcedac [x86_64]
+			With this option iommu will not optimize to look
+			for io virtual address below 32-bit forcing dual
+			address cycle on pci bus for cards supporting greater
+			than 32-bit addressing. The default is to look
+			for translation below 32-bit and if not available
+			then look in the higher range.
+		strict [Default Off]
+			With this option on every unmap_single operation will
+			result in a hardware IOTLB flush operation as opposed
+			to batching them for performance.
+		sp_off [Default Off]
+			By default, super page will be supported if Intel IOMMU
+			has the capability. With this option, super page will
+			not be supported.
+		ecs_off [Default Off]
+			By default, extended context tables will be supported if
+			the hardware advertises that it has support both for the
+			extended tables themselves, and also PASID support. With
+			this option set, extended tables will not be used even
+			on hardware which claims to support them.
+
+	intel_idle.max_cstate=	[KNL,HW,ACPI,X86]
+			0	disables intel_idle and fall back on acpi_idle.
+			1 to 9	specify maximum depth of C-state.
+
+	intel_pstate=  [X86]
+		       disable
+		         Do not enable intel_pstate as the default
+		         scaling driver for the supported processors
+		       passive
+			 Use intel_pstate as a scaling driver, but configure it
+			 to work with generic cpufreq governors (instead of
+			 enabling its internal governor).  This mode cannot be
+			 used along with the hardware-managed P-states (HWP)
+			 feature.
+		       force
+			 Enable intel_pstate on systems that prohibit it by default
+			 in favor of acpi-cpufreq. Forcing the intel_pstate driver
+			 instead of acpi-cpufreq may disable platform features, such
+			 as thermal controls and power capping, that rely on ACPI
+			 P-States information being indicated to OSPM and therefore
+			 should be used with caution. This option does not work with
+			 processors that aren't supported by the intel_pstate driver
+			 or on platforms that use pcc-cpufreq instead of acpi-cpufreq.
+		       no_hwp
+		         Do not enable hardware P state control (HWP)
+			 if available.
+		hwp_only
+			Only load intel_pstate on systems which support
+			hardware P state control (HWP) if available.
+		support_acpi_ppc
+			Enforce ACPI _PPC performance limits. If the Fixed ACPI
+			Description Table, specifies preferred power management
+			profile as "Enterprise Server" or "Performance Server",
+			then this feature is turned on by default.
+		per_cpu_perf_limits
+			Allow per-logical-CPU P-State performance control limits using
+			cpufreq sysfs interface
+
+	intremap=	[X86-64, Intel-IOMMU]
+			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
+			nopost	disable Interrupt Posting
+
+	iomem=		Disable strict checking of access to MMIO memory
+		strict	regions from userspace.
+		relaxed
+
+	iommu=		[x86]
+		off
+		force
+		noforce
+		biomerge
+		panic
+		nopanic
+		merge
+		nomerge
+		forcesac
+		soft
+		pt		[x86, IA-64]
+		nobypass	[PPC/POWERNV]
+			Disable IOMMU bypass, using IOMMU for PCI devices.
+
+
+	io7=		[HW] IO7 for Marvel based alpha systems
+			See comment before marvel_specify_io7 in
+			arch/alpha/kernel/core_marvel.c.
+
+	io_delay=	[X86] I/O delay method
+		0x80
+			Standard port 0x80 based delay
+		0xed
+			Alternate port 0xed based delay (needed on some systems)
+		udelay
+			Simple two microseconds delay
+		none
+			No delay
+
+	ip=		[IP_PNP]
+			See Documentation/filesystems/nfs/nfsroot.txt.
+
+	irqaffinity=	[SMP] Set the default irq affinity mask
+			The argument is a cpu list, as described above.
+
+	irqfixup	[HW]
+			When an interrupt is not handled search all handlers
+			for it. Intended to get systems with badly broken
+			firmware running.
+
+	irqpoll		[HW]
+			When an interrupt is not handled search all handlers
+			for it. Also check all handlers each timer
+			interrupt. Intended to get systems with badly broken
+			firmware running.
+
+	isapnp=		[ISAPNP]
+			Format: <RDP>,<reset>,<pci_scan>,<verbosity>
+
+	isolcpus=	[KNL,SMP] Isolate CPUs from the general scheduler.
+			The argument is a cpu list, as described above.
+
+			This option can be used to specify one or more CPUs
+			to isolate from the general SMP balancing and scheduling
+			algorithms. You can move a process onto or off an
+			"isolated" CPU via the CPU affinity syscalls or cpuset.
+			<cpu number> begins at 0 and the maximum value is
+			"number of CPUs in system - 1".
+
+			This option is the preferred way to isolate CPUs. The
+			alternative -- manually setting the CPU mask of all
+			tasks in the system -- can cause problems and
+			suboptimal load balancer performance.
+
+	iucv=		[HW,NET]
+
+	ivrs_ioapic	[HW,X86_64]
+			Provide an override to the IOAPIC-ID<->DEVICE-ID
+			mapping provided in the IVRS ACPI table. For
+			example, to map IOAPIC-ID decimal 10 to
+			PCI device 00:14.0 write the parameter as:
+				ivrs_ioapic[10]=00:14.0
+
+	ivrs_hpet	[HW,X86_64]
+			Provide an override to the HPET-ID<->DEVICE-ID
+			mapping provided in the IVRS ACPI table. For
+			example, to map HPET-ID decimal 0 to
+			PCI device 00:14.0 write the parameter as:
+				ivrs_hpet[0]=00:14.0
+
+	ivrs_acpihid	[HW,X86_64]
+			Provide an override to the ACPI-HID:UID<->DEVICE-ID
+			mapping provided in the IVRS ACPI table. For
+			example, to map UART-HID:UID AMD0020:0 to
+			PCI device 00:14.5 write the parameter as:
+				ivrs_acpihid[00:14.5]=AMD0020:0
+
+	js=		[HW,JOY] Analog joystick
+			See Documentation/input/joystick.txt.
+
+	nokaslr		[KNL]
+			When CONFIG_RANDOMIZE_BASE is set, this disables
+			kernel and module base offset ASLR (Address Space
+			Layout Randomization).
+
+	keepinitrd	[HW,ARM]
+
+	kernelcore=	[KNL,X86,IA-64,PPC]
+			Format: nn[KMGTPE] | "mirror"
+			This parameter
+			specifies the amount of memory usable by the kernel
+			for non-movable allocations.  The requested amount is
+			spread evenly throughout all nodes in the system. The
+			remaining memory in each node is used for Movable
+			pages. In the event, a node is too small to have both
+			kernelcore and Movable pages, kernelcore pages will
+			take priority and other nodes will have a larger number
+			of Movable pages.  The Movable zone is used for the
+			allocation of pages that may be reclaimed or moved
+			by the page migration subsystem.  This means that
+			HugeTLB pages may not be allocated from this zone.
+			Note that allocations like PTEs-from-HighMem still
+			use the HighMem zone if it exists, and the Normal
+			zone if it does not.
+
+			Instead of specifying the amount of memory (nn[KMGTPE]),
+			you can specify "mirror" option. In case "mirror"
+			option is specified, mirrored (reliable) memory is used
+			for non-movable allocations and remaining memory is used
+			for Movable pages. nn[KMGTPE] and "mirror" are exclusive,
+			so you can NOT specify nn[KMGTPE] and "mirror" at the same
+			time.
+
+	kgdbdbgp=	[KGDB,HW] kgdb over EHCI usb debug port.
+			Format: <Controller#>[,poll interval]
+			The controller # is the number of the ehci usb debug
+			port as it is probed via PCI.  The poll interval is
+			optional and is the number seconds in between
+			each poll cycle to the debug port in case you need
+			the functionality for interrupting the kernel with
+			gdb or control-c on the dbgp connection.  When
+			not using this parameter you use sysrq-g to break into
+			the kernel debugger.
+
+	kgdboc=		[KGDB,HW] kgdb over consoles.
+			Requires a tty driver that supports console polling,
+			or a supported polling keyboard driver (non-usb).
+			 Serial only format: <serial_device>[,baud]
+			 keyboard only format: kbd
+			 keyboard and serial format: kbd,<serial_device>[,baud]
+			Optional Kernel mode setting:
+			 kms, kbd format: kms,kbd
+			 kms, kbd and serial format: kms,kbd,<ser_dev>[,baud]
+
+	kgdbwait	[KGDB] Stop kernel execution and enter the
+			kernel debugger at the earliest opportunity.
+
+	kmac=		[MIPS] korina ethernet MAC address.
+			Configure the RouterBoard 532 series on-chip
+			Ethernet adapter MAC address.
+
+	kmemleak=	[KNL] Boot-time kmemleak enable/disable
+			Valid arguments: on, off
+			Default: on
+			Built with CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y,
+			the default is off.
+
+	kmemcheck=	[X86] Boot-time kmemcheck enable/disable/one-shot mode
+			Valid arguments: 0, 1, 2
+			kmemcheck=0 (disabled)
+			kmemcheck=1 (enabled)
+			kmemcheck=2 (one-shot mode)
+			Default: 2 (one-shot mode)
+
+	kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
+			Default is 0 (don't ignore, but inject #GP)
+
+	kvm.mmu_audit=	[KVM] This is a R/W parameter which allows audit
+			KVM MMU at runtime.
+			Default is 0 (off)
+
+	kvm-amd.nested=	[KVM,AMD] Allow nested virtualization in KVM/SVM.
+			Default is 1 (enabled)
+
+	kvm-amd.npt=	[KVM,AMD] Disable nested paging (virtualized MMU)
+			for all guests.
+			Default is 1 (enabled) if in 64-bit or 32-bit PAE mode.
+
+	kvm-intel.ept=	[KVM,Intel] Disable extended page tables
+			(virtualized MMU) support on capable Intel chips.
+			Default is 1 (enabled)
+
+	kvm-intel.emulate_invalid_guest_state=
+			[KVM,Intel] Enable emulation of invalid guest states
+			Default is 0 (disabled)
+
+	kvm-intel.flexpriority=
+			[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
+			Intel chips. Default is 1 (enabled)
+
+	kvm-intel.vpid=	[KVM,Intel] Disable Virtual Processor Identification
+			feature (tagged TLBs) on capable Intel chips.
+			Default is 1 (enabled)
+
+	l2cr=		[PPC]
+
+	l3cr=		[PPC]
+
+	lapic		[X86-32,APIC] Enable the local APIC even if BIOS
+			disabled it.
+
+	lapic=		[x86,APIC] "notscdeadline" Do not use TSC deadline
+			value for LAPIC timer one-shot implementation. Default
+			back to the programmable timer unit in the LAPIC.
+
+	lapic_timer_c2_ok	[X86,APIC] trust the local apic timer
+			in C2 power state.
+
+	libata.dma=	[LIBATA] DMA control
+			libata.dma=0	  Disable all PATA and SATA DMA
+			libata.dma=1	  PATA and SATA Disk DMA only
+			libata.dma=2	  ATAPI (CDROM) DMA only
+			libata.dma=4	  Compact Flash DMA only
+			Combinations also work, so libata.dma=3 enables DMA
+			for disks and CDROMs, but not CFs.
+
+	libata.ignore_hpa=	[LIBATA] Ignore HPA limit
+			libata.ignore_hpa=0	  keep BIOS limits (default)
+			libata.ignore_hpa=1	  ignore limits, using full disk
+
+	libata.noacpi	[LIBATA] Disables use of ACPI in libata suspend/resume
+			when set.
+			Format: <int>
+
+	libata.force=	[LIBATA] Force configurations.  The format is comma
+			separated list of "[ID:]VAL" where ID is
+			PORT[.DEVICE].  PORT and DEVICE are decimal numbers
+			matching port, link or device.  Basically, it matches
+			the ATA ID string printed on console by libata.  If
+			the whole ID part is omitted, the last PORT and DEVICE
+			values are used.  If ID hasn't been specified yet, the
+			configuration applies to all ports, links and devices.
+
+			If only DEVICE is omitted, the parameter applies to
+			the port and all links and devices behind it.  DEVICE
+			number of 0 either selects the first device or the
+			first fan-out link behind PMP device.  It does not
+			select the host link.  DEVICE number of 15 selects the
+			host link and device attached to it.
+
+			The VAL specifies the configuration to force.  As long
+			as there's no ambiguity shortcut notation is allowed.
+			For example, both 1.5 and 1.5G would work for 1.5Gbps.
+			The following configurations can be forced.
+
+			* Cable type: 40c, 80c, short40c, unk, ign or sata.
+			  Any ID with matching PORT is used.
+
+			* SATA link speed limit: 1.5Gbps or 3.0Gbps.
+
+			* Transfer mode: pio[0-7], mwdma[0-4] and udma[0-7].
+			  udma[/][16,25,33,44,66,100,133] notation is also
+			  allowed.
+
+			* [no]ncq: Turn on or off NCQ.
+
+			* [no]ncqtrim: Turn off queued DSM TRIM.
+
+			* nohrst, nosrst, norst: suppress hard, soft
+                          and both resets.
+
+			* rstonce: only attempt one reset during
+			  hot-unplug link recovery
+
+			* dump_id: dump IDENTIFY data.
+
+			* atapi_dmadir: Enable ATAPI DMADIR bridge support
+
+			* disable: Disable this device.
+
+			If there are multiple matching configurations changing
+			the same attribute, the last one is used.
+
+	memblock=debug	[KNL] Enable memblock debug messages.
+
+	load_ramdisk=	[RAM] List of ramdisks to load from floppy
+			See Documentation/blockdev/ramdisk.txt.
+
+	lockd.nlm_grace_period=P  [NFS] Assign grace period.
+			Format: <integer>
+
+	lockd.nlm_tcpport=N	[NFS] Assign TCP port.
+			Format: <integer>
+
+	lockd.nlm_timeout=T	[NFS] Assign timeout value.
+			Format: <integer>
+
+	lockd.nlm_udpport=M	[NFS] Assign UDP port.
+			Format: <integer>
+
+	locktorture.nreaders_stress= [KNL]
+			Set the number of locking read-acquisition kthreads.
+			Defaults to being automatically set based on the
+			number of online CPUs.
+
+	locktorture.nwriters_stress= [KNL]
+			Set the number of locking write-acquisition kthreads.
+
+	locktorture.onoff_holdoff= [KNL]
+			Set time (s) after boot for CPU-hotplug testing.
+
+	locktorture.onoff_interval= [KNL]
+			Set time (s) between CPU-hotplug operations, or
+			zero to disable CPU-hotplug testing.
+
+	locktorture.shuffle_interval= [KNL]
+			Set task-shuffle interval (jiffies).  Shuffling
+			tasks allows some CPUs to go into dyntick-idle
+			mode during the locktorture test.
+
+	locktorture.shutdown_secs= [KNL]
+			Set time (s) after boot system shutdown.  This
+			is useful for hands-off automated testing.
+
+	locktorture.stat_interval= [KNL]
+			Time (s) between statistics printk()s.
+
+	locktorture.stutter= [KNL]
+			Time (s) to stutter testing, for example,
+			specifying five seconds causes the test to run for
+			five seconds, wait for five seconds, and so on.
+			This tests the locking primitive's ability to
+			transition abruptly to and from idle.
+
+	locktorture.torture_runnable= [BOOT]
+			Start locktorture running at boot time.
+
+	locktorture.torture_type= [KNL]
+			Specify the locking implementation to test.
+
+	locktorture.verbose= [KNL]
+			Enable additional printk() statements.
+
+	logibm.irq=	[HW,MOUSE] Logitech Bus Mouse Driver
+			Format: <irq>
+
+	loglevel=	All Kernel Messages with a loglevel smaller than the
+			console loglevel will be printed to the console. It can
+			also be changed with klogd or other programs. The
+			loglevels are defined as follows:
+
+			0 (KERN_EMERG)		system is unusable
+			1 (KERN_ALERT)		action must be taken immediately
+			2 (KERN_CRIT)		critical conditions
+			3 (KERN_ERR)		error conditions
+			4 (KERN_WARNING)	warning conditions
+			5 (KERN_NOTICE)		normal but significant condition
+			6 (KERN_INFO)		informational
+			7 (KERN_DEBUG)		debug-level messages
+
+	log_buf_len=n[KMG]	Sets the size of the printk ring buffer,
+			in bytes.  n must be a power of two and greater
+			than the minimal size. The minimal size is defined
+			by LOG_BUF_SHIFT kernel config parameter. There is
+			also CONFIG_LOG_CPU_MAX_BUF_SHIFT config parameter
+			that allows to increase the default size depending on
+			the number of CPUs. See init/Kconfig for more details.
+
+	logo.nologo	[FB] Disables display of the built-in Linux logo.
+			This may be used to provide more screen space for
+			kernel log messages and is useful when debugging
+			kernel boot problems.
+
+	lp=0		[LP]	Specify parallel ports to use, e.g,
+	lp=port[,port...]	lp=none,parport0 (lp0 not configured, lp1 uses
+	lp=reset		first parallel port). 'lp=0' disables the
+	lp=auto			printer driver. 'lp=reset' (which can be
+				specified in addition to the ports) causes
+				attached printers to be reset. Using
+				lp=port1,port2,... specifies the parallel ports
+				to associate lp devices with, starting with
+				lp0. A port specification may be 'none' to skip
+				that lp device, or a parport name such as
+				'parport0'. Specifying 'lp=auto' instead of a
+				port specification list means that device IDs
+				from each port should be examined, to see if
+				an IEEE 1284-compliant printer is attached; if
+				so, the driver will manage that printer.
+				See also header of drivers/char/lp.c.
+
+	lpj=n		[KNL]
+			Sets loops_per_jiffy to given constant, thus avoiding
+			time-consuming boot-time autodetection (up to 250 ms per
+			CPU). 0 enables autodetection (default). To determine
+			the correct value for your kernel, boot with normal
+			autodetection and see what value is printed. Note that
+			on SMP systems the preset will be applied to all CPUs,
+			which is likely to cause problems if your CPUs need
+			significantly divergent settings. An incorrect value
+			will cause delays in the kernel to be wrong, leading to
+			unpredictable I/O errors and other breakage. Although
+			unlikely, in the extreme case this might damage your
+			hardware.
+
+	ltpc=		[NET]
+			Format: <io>,<irq>,<dma>
+
+	machvec=	[IA-64] Force the use of a particular machine-vector
+			(machvec) in a generic kernel.
+			Example: machvec=hpzx1_swiotlb
+
+	machtype=	[Loongson] Share the same kernel image file between different
+			 yeeloong laptop.
+			Example: machtype=lemote-yeeloong-2f-7inch
+
+	max_addr=nn[KMG]	[KNL,BOOT,ia64] All physical memory greater
+			than or equal to this physical address is ignored.
+
+	maxcpus=	[SMP] Maximum number of processors that	an SMP kernel
+			will bring up during bootup.  maxcpus=n : n >= 0 limits
+			the kernel to bring up 'n' processors. Surely after
+			bootup you can bring up the other plugged cpu by executing
+			"echo 1 > /sys/devices/system/cpu/cpuX/online". So maxcpus
+			only takes effect during system bootup.
+			While n=0 is a special case, it is equivalent to "nosmp",
+			which also disables the IO APIC.
+
+	max_loop=	[LOOP] The number of loop block devices that get
+	(loop.max_loop)	unconditionally pre-created at init time. The default
+			number is configured by BLK_DEV_LOOP_MIN_COUNT. Instead
+			of statically allocating a predefined number, loop
+			devices can be requested on-demand with the
+			/dev/loop-control interface.
+
+	mce		[X86-32] Machine Check Exception
+
+	mce=option	[X86-64] See Documentation/x86/x86_64/boot-options.txt
+
+	md=		[HW] RAID subsystems devices and level
+			See Documentation/admin-guide/md.rst.
+
+	mdacon=		[MDA]
+			Format: <first>,<last>
+			Specifies range of consoles to be captured by the MDA.
+
+	mem=nn[KMG]	[KNL,BOOT] Force usage of a specific amount of memory
+			Amount of memory to be used when the kernel is not able
+			to see the whole system memory or for test.
+			[X86] Work as limiting max address. Use together
+			with memmap= to avoid physical address space collisions.
+			Without memmap= PCI devices could be placed at addresses
+			belonging to unused RAM.
+
+	mem=nopentium	[BUGS=X86-32] Disable usage of 4MB pages for kernel
+			memory.
+
+	memchunk=nn[KMG]
+			[KNL,SH] Allow user to override the default size for
+			per-device physically contiguous DMA buffers.
+
+        memhp_default_state=online/offline
+			[KNL] Set the initial state for the memory hotplug
+			onlining policy. If not specified, the default value is
+			set according to the
+			CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE kernel config
+			option.
+			See Documentation/memory-hotplug.txt.
+
+	memmap=exactmap	[KNL,X86] Enable setting of an exact
+			E820 memory map, as specified by the user.
+			Such memmap=exactmap lines can be constructed based on
+			BIOS output or other requirements. See the memmap=nn@ss
+			option description.
+
+	memmap=nn[KMG]@ss[KMG]
+			[KNL] Force usage of a specific region of memory.
+			Region of memory to be used is from ss to ss+nn.
+
+	memmap=nn[KMG]#ss[KMG]
+			[KNL,ACPI] Mark specific memory as ACPI data.
+			Region of memory to be marked is from ss to ss+nn.
+
+	memmap=nn[KMG]$ss[KMG]
+			[KNL,ACPI] Mark specific memory as reserved.
+			Region of memory to be reserved is from ss to ss+nn.
+			Example: Exclude memory from 0x18690000-0x1869ffff
+			         memmap=64K$0x18690000
+			         or
+			         memmap=0x10000$0x18690000
+
+	memmap=nn[KMG]!ss[KMG]
+			[KNL,X86] Mark specific memory as protected.
+			Region of memory to be used, from ss to ss+nn.
+			The memory region may be marked as e820 type 12 (0xc)
+			and is NVDIMM or ADR memory.
+
+	memory_corruption_check=0/1 [X86]
+			Some BIOSes seem to corrupt the first 64k of
+			memory when doing things like suspend/resume.
+			Setting this option will scan the memory
+			looking for corruption.  Enabling this will
+			both detect corruption and prevent the kernel
+			from using the memory being corrupted.
+			However, its intended as a diagnostic tool; if
+			repeatable BIOS-originated corruption always
+			affects the same memory, you can use memmap=
+			to prevent the kernel from using that memory.
+
+	memory_corruption_check_size=size [X86]
+			By default it checks for corruption in the low
+			64k, making this memory unavailable for normal
+			use.  Use this parameter to scan for
+			corruption in more or less memory.
+
+	memory_corruption_check_period=seconds [X86]
+			By default it checks for corruption every 60
+			seconds.  Use this parameter to check at some
+			other rate.  0 disables periodic checking.
+
+	memtest=	[KNL,X86,ARM] Enable memtest
+			Format: <integer>
+			default : 0 <disable>
+			Specifies the number of memtest passes to be
+			performed. Each pass selects another test
+			pattern from a given set of patterns. Memtest
+			fills the memory with this pattern, validates
+			memory contents and reserves bad memory
+			regions that are detected.
+
+	mem_sleep_default=	[SUSPEND] Default system suspend mode:
+			s2idle  - Suspend-To-Idle
+			shallow - Power-On Suspend or equivalent (if supported)
+			deep    - Suspend-To-RAM or equivalent (if supported)
+			See Documentation/power/states.txt.
+
+	meye.*=		[HW] Set MotionEye Camera parameters
+			See Documentation/video4linux/meye.txt.
+
+	mfgpt_irq=	[IA-32] Specify the IRQ to use for the
+			Multi-Function General Purpose Timers on AMD Geode
+			platforms.
+
+	mfgptfix	[X86-32] Fix MFGPT timers on AMD Geode platforms when
+			the BIOS has incorrectly applied a workaround. TinyBIOS
+			version 0.98 is known to be affected, 0.99 fixes the
+			problem by letting the user disable the workaround.
+
+	mga=		[HW,DRM]
+
+	min_addr=nn[KMG]	[KNL,BOOT,ia64] All physical memory below this
+			physical address is ignored.
+
+	mini2440=	[ARM,HW,KNL]
+			Format:[0..2][b][c][t]
+			Default: "0tb"
+			MINI2440 configuration specification:
+			0 - The attached screen is the 3.5" TFT
+			1 - The attached screen is the 7" TFT
+			2 - The VGA Shield is attached (1024x768)
+			Leaving out the screen size parameter will not load
+			the TFT driver, and the framebuffer will be left
+			unconfigured.
+			b - Enable backlight. The TFT backlight pin will be
+			linked to the kernel VESA blanking code and a GPIO
+			LED. This parameter is not necessary when using the
+			VGA shield.
+			c - Enable the s3c camera interface.
+			t - Reserved for enabling touchscreen support. The
+			touchscreen support is not enabled in the mainstream
+			kernel as of 2.6.30, a preliminary port can be found
+			in the "bleeding edge" mini2440 support kernel at
+			http://repo.or.cz/w/linux-2.6/mini2440.git
+
+	mminit_loglevel=
+			[KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
+			parameter allows control of the logging verbosity for
+			the additional memory initialisation checks. A value
+			of 0 disables mminit logging and a level of 4 will
+			log everything. Information is printed at KERN_DEBUG
+			so loglevel=8 may also need to be specified.
+
+	module.sig_enforce
+			[KNL] When CONFIG_MODULE_SIG is set, this means that
+			modules without (valid) signatures will fail to load.
+			Note that if CONFIG_MODULE_SIG_FORCE is set, that
+			is always true, so this option does nothing.
+
+	module_blacklist=  [KNL] Do not load a comma-separated list of
+			modules.  Useful for debugging problem modules.
+
+	mousedev.tap_time=
+			[MOUSE] Maximum time between finger touching and
+			leaving touchpad surface for touch to be considered
+			a tap and be reported as a left button click (for
+			touchpads working in absolute mode only).
+			Format: <msecs>
+	mousedev.xres=	[MOUSE] Horizontal screen resolution, used for devices
+			reporting absolute coordinates, such as tablets
+	mousedev.yres=	[MOUSE] Vertical screen resolution, used for devices
+			reporting absolute coordinates, such as tablets
+
+	movablecore=nn[KMG]	[KNL,X86,IA-64,PPC] This parameter
+			is similar to kernelcore except it specifies the
+			amount of memory used for migratable allocations.
+			If both kernelcore and movablecore is specified,
+			then kernelcore will be at *least* the specified
+			value but may be more. If movablecore on its own
+			is specified, the administrator must be careful
+			that the amount of memory usable for all allocations
+			is not too small.
+
+	movable_node	[KNL] Boot-time switch to enable the effects
+			of CONFIG_MOVABLE_NODE=y. See mm/Kconfig for details.
+
+	MTD_Partition=	[MTD]
+			Format: <name>,<region-number>,<size>,<offset>
+
+	MTD_Region=	[MTD] Format:
+			<name>,<region-number>[,<base>,<size>,<buswidth>,<altbuswidth>]
+
+	mtdparts=	[MTD]
+			See drivers/mtd/cmdlinepart.c.
+
+	multitce=off	[PPC]  This parameter disables the use of the pSeries
+			firmware feature for updating multiple TCE entries
+			at a time.
+
+	onenand.bdry=	[HW,MTD] Flex-OneNAND Boundary Configuration
+
+			Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock]
+
+			boundary - index of last SLC block on Flex-OneNAND.
+				   The remaining blocks are configured as MLC blocks.
+			lock	 - Configure if Flex-OneNAND boundary should be locked.
+				   Once locked, the boundary cannot be changed.
+				   1 indicates lock status, 0 indicates unlock status.
+
+	mtdset=		[ARM]
+			ARM/S3C2412 JIVE boot control
+
+			See arch/arm/mach-s3c2412/mach-jive.c
+
+	mtouchusb.raw_coordinates=
+			[HW] Make the MicroTouch USB driver use raw coordinates
+			('y', default) or cooked coordinates ('n')
+
+	mtrr_chunk_size=nn[KMG] [X86]
+			used for mtrr cleanup. It is largest continuous chunk
+			that could hold holes aka. UC entries.
+
+	mtrr_gran_size=nn[KMG] [X86]
+			Used for mtrr cleanup. It is granularity of mtrr block.
+			Default is 1.
+			Large value could prevent small alignment from
+			using up MTRRs.
+
+	mtrr_spare_reg_nr=n [X86]
+			Format: <integer>
+			Range: 0,7 : spare reg number
+			Default : 1
+			Used for mtrr cleanup. It is spare mtrr entries number.
+			Set to 2 or more if your graphical card needs more.
+
+	n2=		[NET] SDL Inc. RISCom/N2 synchronous serial card
+
+	netdev=		[NET] Network devices parameters
+			Format: <irq>,<io>,<mem_start>,<mem_end>,<name>
+			Note that mem_start is often overloaded to mean
+			something different and driver-specific.
+			This usage is only documented in each driver source
+			file if at all.
+
+	nf_conntrack.acct=
+			[NETFILTER] Enable connection tracking flow accounting
+			0 to disable accounting
+			1 to enable accounting
+			Default value is 0.
+
+	nfsaddrs=	[NFS] Deprecated.  Use ip= instead.
+			See Documentation/filesystems/nfs/nfsroot.txt.
+
+	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
+			See Documentation/filesystems/nfs/nfsroot.txt.
+
+	nfsrootdebug	[NFS] enable nfsroot debugging messages.
+			See Documentation/filesystems/nfs/nfsroot.txt.
+
+	nfs.callback_nr_threads=
+			[NFSv4] set the total number of threads that the
+			NFS client will assign to service NFSv4 callback
+			requests.
+
+	nfs.callback_tcpport=
+			[NFS] set the TCP port on which the NFSv4 callback
+			channel should listen.
+
+	nfs.cache_getent=
+			[NFS] sets the pathname to the program which is used
+			to update the NFS client cache entries.
+
+	nfs.cache_getent_timeout=
+			[NFS] sets the timeout after which an attempt to
+			update a cache entry is deemed to have failed.
+
+	nfs.idmap_cache_timeout=
+			[NFS] set the maximum lifetime for idmapper cache
+			entries.
+
+	nfs.enable_ino64=
+			[NFS] enable 64-bit inode numbers.
+			If zero, the NFS client will fake up a 32-bit inode
+			number for the readdir() and stat() syscalls instead
+			of returning the full 64-bit number.
+			The default is to return 64-bit inode numbers.
+
+	nfs.max_session_cb_slots=
+			[NFSv4.1] Sets the maximum number of session
+			slots the client will assign to the callback
+			channel. This determines the maximum number of
+			callbacks the client will process in parallel for
+			a particular server.
+
+	nfs.max_session_slots=
+			[NFSv4.1] Sets the maximum number of session slots
+			the client will attempt to negotiate with the server.
+			This limits the number of simultaneous RPC requests
+			that the client can send to the NFSv4.1 server.
+			Note that there is little point in setting this
+			value higher than the max_tcp_slot_table_limit.
+
+	nfs.nfs4_disable_idmapping=
+			[NFSv4] When set to the default of '1', this option
+			ensures that both the RPC level authentication
+			scheme and the NFS level operations agree to use
+			numeric uids/gids if the mount is using the
+			'sec=sys' security flavour. In effect it is
+			disabling idmapping, which can make migration from
+			legacy NFSv2/v3 systems to NFSv4 easier.
+			Servers that do not support this mode of operation
+			will be autodetected by the client, and it will fall
+			back to using the idmapper.
+			To turn off this behaviour, set the value to '0'.
+	nfs.nfs4_unique_id=
+			[NFS4] Specify an additional fixed unique ident-
+			ification string that NFSv4 clients can insert into
+			their nfs_client_id4 string.  This is typically a
+			UUID that is generated at system install time.
+
+	nfs.send_implementation_id =
+			[NFSv4.1] Send client implementation identification
+			information in exchange_id requests.
+			If zero, no implementation identification information
+			will be sent.
+			The default is to send the implementation identification
+			information.
+
+	nfs.recover_lost_locks =
+			[NFSv4] Attempt to recover locks that were lost due
+			to a lease timeout on the server. Please note that
+			doing this risks data corruption, since there are
+			no guarantees that the file will remain unchanged
+			after the locks are lost.
+			If you want to enable the kernel legacy behaviour of
+			attempting to recover these locks, then set this
+			parameter to '1'.
+			The default parameter value of '0' causes the kernel
+			not to attempt recovery of lost locks.
+
+	nfs4.layoutstats_timer =
+			[NFSv4.2] Change the rate at which the kernel sends
+			layoutstats to the pNFS metadata server.
+
+			Setting this to value to 0 causes the kernel to use
+			whatever value is the default set by the layout
+			driver. A non-zero value sets the minimum interval
+			in seconds between layoutstats transmissions.
+
+	nfsd.nfs4_disable_idmapping=
+			[NFSv4] When set to the default of '1', the NFSv4
+			server will return only numeric uids and gids to
+			clients using auth_sys, and will accept numeric uids
+			and gids from such clients.  This is intended to ease
+			migration from NFSv2/v3.
+
+	objlayoutdriver.osd_login_prog=
+			[NFS] [OBJLAYOUT] sets the pathname to the program which
+			is used to automatically discover and login into new
+			osd-targets. Please see:
+			Documentation/filesystems/pnfs.txt for more explanations
+
+	nmi_debug=	[KNL,AVR32,SH] Specify one or more actions to take
+			when a NMI is triggered.
+			Format: [state][,regs][,debounce][,die]
+
+	nmi_watchdog=	[KNL,BUGS=X86] Debugging features for SMP kernels
+			Format: [panic,][nopanic,][num]
+			Valid num: 0 or 1
+			0 - turn hardlockup detector in nmi_watchdog off
+			1 - turn hardlockup detector in nmi_watchdog on
+			When panic is specified, panic when an NMI watchdog
+			timeout occurs (or 'nopanic' to override the opposite
+			default). To disable both hard and soft lockup detectors,
+			please see 'nowatchdog'.
+			This is useful when you use a panic=... timeout and
+			need the box quickly up again.
+
+	netpoll.carrier_timeout=
+			[NET] Specifies amount of time (in seconds) that
+			netpoll should wait for a carrier. By default netpoll
+			waits 4 seconds.
+
+	no387		[BUGS=X86-32] Tells the kernel to use the 387 maths
+			emulation library even if a 387 maths coprocessor
+			is present.
+
+	no_console_suspend
+			[HW] Never suspend the console
+			Disable suspending of consoles during suspend and
+			hibernate operations.  Once disabled, debugging
+			messages can reach various consoles while the rest
+			of the system is being put to sleep (ie, while
+			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,
+			but will impact performance.
+
+	noalign		[KNL,ARM]
+
+	noapic		[SMP,APIC] Tells the kernel to not make use of any
+			IOAPICs that may be present in the system.
+
+	noautogroup	Disable scheduler automatic task group creation.
+
+	nobats		[PPC] Do not use BATs for mapping kernel lowmem
+			on "Classic" PPC cores.
+
+	nocache		[ARM]
+
+	noclflush	[BUGS=X86] Don't use the CLFLUSH instruction
+
+	nodelayacct	[KNL] Disable per-task delay accounting
+
+	nodsp		[SH] Disable hardware DSP at boot time.
+
+	noefi		Disable EFI runtime services support.
+
+	noexec		[IA-64]
+
+	noexec		[X86]
+			On X86-32 available only on PAE configured kernels.
+			noexec=on: enable non-executable mappings (default)
+			noexec=off: disable non-executable mappings
+
+	nosmap		[X86]
+			Disable SMAP (Supervisor Mode Access Prevention)
+			even if it is supported by processor.
+
+	nosmep		[X86]
+			Disable SMEP (Supervisor Mode Execution Prevention)
+			even if it is supported by processor.
+
+	noexec32	[X86-64]
+			This affects only 32-bit executables.
+			noexec32=on: enable non-executable mappings (default)
+				read doesn't imply executable mappings
+			noexec32=off: disable non-executable mappings
+				read implies executable mappings
+
+	nofpu		[MIPS,SH] Disable hardware FPU at boot time.
+
+	nofxsr		[BUGS=X86-32] Disables x86 floating point extended
+			register save and restore. The kernel will only save
+			legacy floating-point registers on task switch.
+
+	nohugeiomap	[KNL,x86] Disable kernel huge I/O mappings.
+
+	nosmt		[KNL,S390] Disable symmetric multithreading (SMT).
+			Equivalent to smt=1.
+
+	noxsave		[BUGS=X86] Disables x86 extended register state save
+			and restore using xsave. The kernel will fallback to
+			enabling legacy floating-point and sse state.
+
+	noxsaveopt	[X86] Disables xsaveopt used in saving x86 extended
+			register states. The kernel will fall back to use
+			xsave to save the states. By using this parameter,
+			performance of saving the states is degraded because
+			xsave doesn't support modified optimization while
+			xsaveopt supports it on xsaveopt enabled systems.
+
+	noxsaves	[X86] Disables xsaves and xrstors used in saving and
+			restoring x86 extended register state in compacted
+			form of xsave area. The kernel will fall back to use
+			xsaveopt and xrstor to save and restore the states
+			in standard form of xsave area. By using this
+			parameter, xsave area per process might occupy more
+			memory on xsaves enabled systems.
+
+	nohlt		[BUGS=ARM,SH] Tells the kernel that the sleep(SH) or
+			wfi(ARM) instruction doesn't work correctly and not to
+			use it. This is also useful when using JTAG debugger.
+
+	no_file_caps	Tells the kernel not to honor file capabilities.  The
+			only way then for a file to be executed with privilege
+			is to be setuid root or executed by root.
+
+	nohalt		[IA-64] Tells the kernel not to use the power saving
+			function PAL_HALT_LIGHT when idle. This increases
+			power-consumption. On the positive side, it reduces
+			interrupt wake-up latency, which may improve performance
+			in certain environments such as networked servers or
+			real-time systems.
+
+	nohibernate	[HIBERNATION] Disable hibernation and resume.
+
+	nohz=		[KNL] Boottime enable/disable dynamic ticks
+			Valid arguments: on, off
+			Default: on
+
+	nohz_full=	[KNL,BOOT]
+			The argument is a cpu list, as described above.
+			In kernels built with CONFIG_NO_HZ_FULL=y, set
+			the specified list of CPUs whose tick will be stopped
+			whenever possible. The boot CPU will be forced outside
+			the range to maintain the timekeeping.
+			The CPUs in this range must also be included in the
+			rcu_nocbs= set.
+
+	noiotrap	[SH] Disables trapped I/O port accesses.
+
+	noirqdebug	[X86-32] Disables the code which attempts to detect and
+			disable unhandled interrupt sources.
+
+	no_timer_check	[X86,APIC] Disables the code which tests for
+			broken timer IRQ sources.
+
+	noisapnp	[ISAPNP] Disables ISA PnP code.
+
+	noinitrd	[RAM] Tells the kernel not to load any configured
+			initial RAM disk.
+
+	nointremap	[X86-64, Intel-IOMMU] Do not enable interrupt
+			remapping.
+			[Deprecated - use intremap=off]
+
+	nointroute	[IA-64]
+
+	noinvpcid	[X86] Disable the INVPCID cpu feature.
+
+	nojitter	[IA-64] Disables jitter checking for ITC timers.
+
+	no-kvmclock	[X86,KVM] Disable paravirtualized KVM clock driver
+
+	no-kvmapf	[X86,KVM] Disable paravirtualized asynchronous page
+			fault handling.
+
+	no-vmw-sched-clock
+			[X86,PV_OPS] Disable paravirtualized VMware scheduler
+			clock and use the default one.
+
+	no-steal-acc    [X86,KVM] Disable paravirtualized steal time accounting.
+			steal time is computed, but won't influence scheduler
+			behaviour
+
+	nolapic		[X86-32,APIC] Do not enable or use the local APIC.
+
+	nolapic_timer	[X86-32,APIC] Do not use the local APIC timer.
+
+	noltlbs		[PPC] Do not use large page/tlb entries for kernel
+			lowmem mapping on PPC40x and PPC8xx
+
+	nomca		[IA-64] Disable machine check abort handling
+
+	nomce		[X86-32] Disable Machine Check Exception
+
+	nomfgpt		[X86-32] Disable Multi-Function General Purpose
+			Timer usage (for AMD Geode machines).
+
+	nonmi_ipi	[X86] Disable using NMI IPIs during panic/reboot to
+			shutdown the other cpus.  Instead use the REBOOT_VECTOR
+			irq.
+
+	nomodule	Disable module load
+
+	nopat		[X86] Disable PAT (page attribute table extension of
+			pagetables) support.
+
+	norandmaps	Don't use address space randomization.  Equivalent to
+			echo 0 > /proc/sys/kernel/randomize_va_space
+
+	noreplace-paravirt	[X86,IA-64,PV_OPS] Don't patch paravirt_ops
+
+	noreplace-smp	[X86-32,SMP] Don't replace SMP instructions
+			with UP alternatives
+
+	nordrand	[X86] Disable kernel use of the RDRAND and
+			RDSEED instructions even if they are supported
+			by the processor.  RDRAND and RDSEED are still
+			available to user space applications.
+
+	noresume	[SWSUSP] Disables resume and restores original swap
+			space.
+
+	no-scroll	[VGA] Disables scrollback.
+			This is required for the Braillex ib80-piezo Braille
+			reader made by F.H. Papenmeier (Germany).
+
+	nosbagart	[IA-64]
+
+	nosep		[BUGS=X86-32] Disables x86 SYSENTER/SYSEXIT support.
+
+	nosmp		[SMP] Tells an SMP kernel to act as a UP kernel,
+			and disable the IO APIC.  legacy for "maxcpus=0".
+
+	nosoftlockup	[KNL] Disable the soft-lockup detector.
+
+	nosync		[HW,M68K] Disables sync negotiation for all devices.
+
+	notsc		[BUGS=X86-32] Disable Time Stamp Counter
+
+	nowatchdog	[KNL] Disable both lockup detectors, i.e.
+                        soft-lockup and NMI watchdog (hard-lockup).
+
+	nowb		[ARM]
+
+	nox2apic	[X86-64,APIC] Do not enable x2APIC mode.
+
+	cpu0_hotplug	[X86] Turn on CPU0 hotplug feature when
+			CONFIG_BOOTPARAM_HOTPLUG_CPU0 is off.
+			Some features depend on CPU0. Known dependencies are:
+			1. Resume from suspend/hibernate depends on CPU0.
+			Suspend/hibernate will fail if CPU0 is offline and you
+			need to online CPU0 before suspend/hibernate.
+			2. PIC interrupts also depend on CPU0. CPU0 can't be
+			removed if a PIC interrupt is detected.
+			It's said poweroff/reboot may depend on CPU0 on some
+			machines although I haven't seen such issues so far
+			after CPU0 is offline on a few tested machines.
+			If the dependencies are under your control, you can
+			turn on cpu0_hotplug.
+
+	nptcg=		[IA-64] Override max number of concurrent global TLB
+			purges which is reported from either PAL_VM_SUMMARY or
+			SAL PALO.
+
+	nr_cpus=	[SMP] Maximum number of processors that	an SMP kernel
+			could support.  nr_cpus=n : n >= 1 limits the kernel to
+			support 'n' processors. It could be larger than the
+			number of already plugged CPU during bootup, later in
+			runtime you can physically add extra cpu until it reaches
+			n. So during boot up some boot time memory for per-cpu
+			variables need be pre-allocated for later physical cpu
+			hot plugging.
+
+	nr_uarts=	[SERIAL] maximum number of UARTs to be registered.
+
+	numa_balancing=	[KNL,X86] Enable or disable automatic NUMA balancing.
+			Allowed values are enable and disable
+
+	numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
+			one of ['zone', 'node', 'default'] can be specified
+			This can be set from sysctl after boot.
+			See Documentation/sysctl/vm.txt for details.
+
+	ohci1394_dma=early	[HW] enable debugging via the ohci1394 driver.
+			See Documentation/debugging-via-ohci1394.txt for more
+			info.
+
+	olpc_ec_timeout= [OLPC] ms delay when issuing EC commands
+			Rather than timing out after 20 ms if an EC
+			command is not properly ACKed, override the length
+			of the timeout.  We have interrupts disabled while
+			waiting for the ACK, so if this is set too high
+			interrupts *may* be lost!
+
+	omap_mux=	[OMAP] Override bootloader pin multiplexing.
+			Format: <mux_mode0.mode_name=value>...
+			For example, to override I2C bus2:
+			omap_mux=i2c2_scl.i2c2_scl=0x100,i2c2_sda.i2c2_sda=0x100
+
+	oprofile.timer=	[HW]
+			Use timer interrupt instead of performance counters
+
+	oprofile.cpu_type=	Force an oprofile cpu type
+			This might be useful if you have an older oprofile
+			userland or if you want common events.
+			Format: { arch_perfmon }
+			arch_perfmon: [X86] Force use of architectural
+				perfmon on Intel CPUs instead of the
+				CPU specific event set.
+			timer: [X86] Force use of architectural NMI
+				timer mode (see also oprofile.timer
+				for generic hr timer mode)
+
+	oops=panic	Always panic on oopses. Default is to just kill the
+			process, but there is a small probability of
+			deadlocking the machine.
+			This will also cause panics on machine check exceptions.
+			Useful together with panic=30 to trigger a reboot.
+
+	OSS		[HW,OSS]
+			See Documentation/sound/oss/oss-parameters.txt
+
+	page_owner=	[KNL] Boot-time page_owner enabling option.
+			Storage of the information about who allocated
+			each page is disabled in default. With this switch,
+			we can turn it on.
+			on: enable the feature
+
+	page_poison=	[KNL] Boot-time parameter changing the state of
+			poisoning on the buddy allocator.
+			off: turn off poisoning
+			on: turn on poisoning
+
+	panic=		[KNL] Kernel behaviour on panic: delay <timeout>
+			timeout > 0: seconds before rebooting
+			timeout = 0: wait forever
+			timeout < 0: reboot immediately
+			Format: <timeout>
+
+	panic_on_warn	panic() instead of WARN().  Useful to cause kdump
+			on a WARN().
+
+	crash_kexec_post_notifiers
+			Run kdump after running panic-notifiers and dumping
+			kmsg. This only for the users who doubt kdump always
+			succeeds in any situation.
+			Note that this also increases risks of kdump failure,
+			because some panic notifiers can make the crashed
+			kernel more unstable.
+
+	parkbd.port=	[HW] Parallel port number the keyboard adapter is
+			connected to, default is 0.
+			Format: <parport#>
+	parkbd.mode=	[HW] Parallel port keyboard adapter mode of operation,
+			0 for XT, 1 for AT (default is AT).
+			Format: <mode>
+
+	parport=	[HW,PPT] Specify parallel ports. 0 disables.
+			Format: { 0 | auto | 0xBBB[,IRQ[,DMA]] }
+			Use 'auto' to force the driver to use any
+			IRQ/DMA settings detected (the default is to
+			ignore detected IRQ/DMA settings because of
+			possible conflicts). You can specify the base
+			address, IRQ, and DMA settings; IRQ and DMA
+			should be numbers, or 'auto' (for using detected
+			settings on that particular port), or 'nofifo'
+			(to avoid using a FIFO even if it is detected).
+			Parallel ports are assigned in the order they
+			are specified on the command line, starting
+			with parport0.
+
+	parport_init_mode=	[HW,PPT]
+			Configure VIA parallel port to operate in
+			a specific mode. This is necessary on Pegasos
+			computer where firmware has no options for setting
+			up parallel port mode and sets it to spp.
+			Currently this function knows 686a and 8231 chips.
+			Format: [spp|ps2|epp|ecp|ecpepp]
+
+	pause_on_oops=
+			Halt all CPUs after the first oops has been printed for
+			the specified number of seconds.  This is to be used if
+			your oopses keep scrolling off the screen.
+
+	pcbit=		[HW,ISDN]
+
+	pcd.		[PARIDE]
+			See header of drivers/block/paride/pcd.c.
+			See also Documentation/blockdev/paride.txt.
+
+	pci=option[,option...]	[PCI] various PCI subsystem options:
+		earlydump	[X86] dump PCI config space before the kernel
+			        changes anything
+		off		[X86] don't probe for the PCI bus
+		bios		[X86-32] force use of PCI BIOS, don't access
+				the hardware directly. Use this if your machine
+				has a non-standard PCI host bridge.
+		nobios		[X86-32] disallow use of PCI BIOS, only direct
+				hardware access methods are allowed. Use this
+				if you experience crashes upon bootup and you
+				suspect they are caused by the BIOS.
+		conf1		[X86] Force use of PCI Configuration Access
+				Mechanism 1 (config address in IO port 0xCF8,
+				data in IO port 0xCFC, both 32-bit).
+		conf2		[X86] Force use of PCI Configuration Access
+				Mechanism 2 (IO port 0xCF8 is an 8-bit port for
+				the function, IO port 0xCFA, also 8-bit, sets
+				bus number. The config space is then accessed
+				through ports 0xC000-0xCFFF).
+				See http://wiki.osdev.org/PCI for more info
+				on the configuration access mechanisms.
+		noaer		[PCIE] If the PCIEAER kernel config parameter is
+				enabled, this kernel boot option can be used to
+				disable the use of PCIE advanced error reporting.
+		nodomains	[PCI] Disable support for multiple PCI
+				root domains (aka PCI segments, in ACPI-speak).
+		nommconf	[X86] Disable use of MMCONFIG for PCI
+				Configuration
+		check_enable_amd_mmconf [X86] check for and enable
+				properly configured MMIO access to PCI
+				config space on AMD family 10h CPU
+		nomsi		[MSI] If the PCI_MSI kernel config parameter is
+				enabled, this kernel boot option can be used to
+				disable the use of MSI interrupts system-wide.
+		noioapicquirk	[APIC] Disable all boot interrupt quirks.
+				Safety option to keep boot IRQs enabled. This
+				should never be necessary.
+		ioapicreroute	[APIC] Enable rerouting of boot IRQs to the
+				primary IO-APIC for bridges that cannot disable
+				boot IRQs. This fixes a source of spurious IRQs
+				when the system masks IRQs.
+		noioapicreroute	[APIC] Disable workaround that uses the
+				boot IRQ equivalent of an IRQ that connects to
+				a chipset where boot IRQs cannot be disabled.
+				The opposite of ioapicreroute.
+		biosirq		[X86-32] Use PCI BIOS calls to get the interrupt
+				routing table. These calls are known to be buggy
+				on several machines and they hang the machine
+				when used, but on other computers it's the only
+				way to get the interrupt routing table. Try
+				this option if the kernel is unable to allocate
+				IRQs or discover secondary PCI buses on your
+				motherboard.
+		rom		[X86] Assign address space to expansion ROMs.
+				Use with caution as certain devices share
+				address decoders between ROMs and other
+				resources.
+		norom		[X86] Do not assign address space to
+				expansion ROMs that do not already have
+				BIOS assigned address ranges.
+		nobar		[X86] Do not assign address space to the
+				BARs that weren't assigned by the BIOS.
+		irqmask=0xMMMM	[X86] Set a bit mask of IRQs allowed to be
+				assigned automatically to PCI devices. You can
+				make the kernel exclude IRQs of your ISA cards
+				this way.
+		pirqaddr=0xAAAAA	[X86] Specify the physical address
+				of the PIRQ table (normally generated
+				by the BIOS) if it is outside the
+				F0000h-100000h range.
+		lastbus=N	[X86] Scan all buses thru bus #N. Can be
+				useful if the kernel is unable to find your
+				secondary buses and you want to tell it
+				explicitly which ones they are.
+		assign-busses	[X86] Always assign all PCI bus
+				numbers ourselves, overriding
+				whatever the firmware may have done.
+		usepirqmask	[X86] Honor the possible IRQ mask stored
+				in the BIOS $PIR table. This is needed on
+				some systems with broken BIOSes, notably
+				some HP Pavilion N5400 and Omnibook XE3
+				notebooks. This will have no effect if ACPI
+				IRQ routing is enabled.
+		noacpi		[X86] Do not use ACPI for IRQ routing
+				or for PCI scanning.
+		use_crs		[X86] Use PCI host bridge window information
+				from ACPI.  On BIOSes from 2008 or later, this
+				is enabled by default.  If you need to use this,
+				please report a bug.
+		nocrs		[X86] Ignore PCI host bridge windows from ACPI.
+			        If you need to use this, please report a bug.
+		routeirq	Do IRQ routing for all PCI devices.
+				This is normally done in pci_enable_device(),
+				so this option is a temporary workaround
+				for broken drivers that don't call it.
+		skip_isa_align	[X86] do not align io start addr, so can
+				handle more pci cards
+		noearly		[X86] Don't do any early type 1 scanning.
+				This might help on some broken boards which
+				machine check when some devices' config space
+				is read. But various workarounds are disabled
+				and some IOMMU drivers will not work.
+		bfsort		Sort PCI devices into breadth-first order.
+				This sorting is done to get a device
+				order compatible with older (<= 2.4) kernels.
+		nobfsort	Don't sort PCI devices into breadth-first order.
+		pcie_bus_tune_off	Disable PCIe MPS (Max Payload Size)
+				tuning and use the BIOS-configured MPS defaults.
+		pcie_bus_safe	Set every device's MPS to the largest value
+				supported by all devices below the root complex.
+		pcie_bus_perf	Set device MPS to the largest allowable MPS
+				based on its parent bus. Also set MRRS (Max
+				Read Request Size) to the largest supported
+				value (no larger than the MPS that the device
+				or bus can support) for best performance.
+		pcie_bus_peer2peer	Set every device's MPS to 128B, which
+				every device is guaranteed to support. This
+				configuration allows peer-to-peer DMA between
+				any pair of devices, possibly at the cost of
+				reduced performance.  This also guarantees
+				that hot-added devices will work.
+		cbiosize=nn[KMG]	The fixed amount of bus space which is
+				reserved for the CardBus bridge's IO window.
+				The default value is 256 bytes.
+		cbmemsize=nn[KMG]	The fixed amount of bus space which is
+				reserved for the CardBus bridge's memory
+				window. The default value is 64 megabytes.
+		resource_alignment=
+				Format:
+				[<order of align>@][<domain>:]<bus>:<slot>.<func>[; ...]
+				[<order of align>@]pci:<vendor>:<device>\
+						[:<subvendor>:<subdevice>][; ...]
+				Specifies alignment and device to reassign
+				aligned memory resources.
+				If <order of align> is not specified,
+				PAGE_SIZE is used as alignment.
+				PCI-PCI bridge can be specified, if resource
+				windows need to be expanded.
+				To specify the alignment for several
+				instances of a device, the PCI vendor,
+				device, subvendor, and subdevice may be
+				specified, e.g., 4096@pci:8086:9c22:103c:198f
+		ecrc=		Enable/disable PCIe ECRC (transaction layer
+				end-to-end CRC checking).
+				bios: Use BIOS/firmware settings. This is the
+				the default.
+				off: Turn ECRC off
+				on: Turn ECRC on.
+		hpiosize=nn[KMG]	The fixed amount of bus space which is
+				reserved for hotplug bridge's IO window.
+				Default size is 256 bytes.
+		hpmemsize=nn[KMG]	The fixed amount of bus space which is
+				reserved for hotplug bridge's memory window.
+				Default size is 2 megabytes.
+		hpbussize=nn	The minimum amount of additional bus numbers
+				reserved for buses below a hotplug bridge.
+				Default is 1.
+		realloc=	Enable/disable reallocating PCI bridge resources
+				if allocations done by BIOS are too small to
+				accommodate resources required by all child
+				devices.
+				off: Turn realloc off
+				on: Turn realloc on
+		realloc		same as realloc=on
+		noari		do not use PCIe ARI.
+		pcie_scan_all	Scan all possible PCIe devices.  Otherwise we
+				only look for one device below a PCIe downstream
+				port.
+
+	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
+			Management.
+		off	Disable ASPM.
+		force	Enable ASPM even on devices that claim not to support it.
+			WARNING: Forcing ASPM on may cause system lockups.
+
+	pcie_hp=	[PCIE] PCI Express Hotplug driver options:
+		nomsi	Do not use MSI for PCI Express Native Hotplug (this
+			makes all PCIe ports use INTx for hotplug services).
+
+	pcie_ports=	[PCIE] PCIe ports handling:
+		auto	Ask the BIOS whether or not to use native PCIe services
+			associated with PCIe ports (PME, hot-plug, AER).  Use
+			them only if that is allowed by the BIOS.
+		native	Use native PCIe services associated with PCIe ports
+			unconditionally.
+		compat	Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
+			ports driver.
+
+	pcie_port_pm=	[PCIE] PCIe port power management handling:
+		off	Disable power management of all PCIe ports
+		force	Forcibly enable power management of all PCIe ports
+
+	pcie_pme=	[PCIE,PM] Native PCIe PME signaling options:
+		nomsi	Do not use MSI for native PCIe PME signaling (this makes
+			all PCIe root ports use INTx for all services).
+
+	pcmv=		[HW,PCMCIA] BadgePAD 4
+
+	pd_ignore_unused
+			[PM]
+			Keep all power-domains already enabled by bootloader on,
+			even if no driver has claimed them. This is useful
+			for debug and development, but should not be
+			needed on a platform with proper driver support.
+
+	pd.		[PARIDE]
+			See Documentation/blockdev/paride.txt.
+
+	pdcchassis=	[PARISC,HW] Disable/Enable PDC Chassis Status codes at
+			boot time.
+			Format: { 0 | 1 }
+			See arch/parisc/kernel/pdc_chassis.c
+
+	percpu_alloc=	Select which percpu first chunk allocator to use.
+			Currently supported values are "embed" and "page".
+			Archs may support subset or none of the	selections.
+			See comments in mm/percpu.c for details on each
+			allocator.  This parameter is primarily	for debugging
+			and performance comparison.
+
+	pf.		[PARIDE]
+			See Documentation/blockdev/paride.txt.
+
+	pg.		[PARIDE]
+			See Documentation/blockdev/paride.txt.
+
+	pirq=		[SMP,APIC] Manual mp-table setup
+			See Documentation/x86/i386/IO-APIC.txt.
+
+	plip=		[PPT,NET] Parallel port network link
+			Format: { parport<nr> | timid | 0 }
+			See also Documentation/parport.txt.
+
+	pmtmr=		[X86] Manual setup of pmtmr I/O Port.
+			Override pmtimer IOPort with a hex value.
+			e.g. pmtmr=0x508
+
+	pnp.debug=1	[PNP]
+			Enable PNP debug messages (depends on the
+			CONFIG_PNP_DEBUG_MESSAGES option).  Change at run-time
+			via /sys/module/pnp/parameters/debug.  We always show
+			current resource usage; turning this on also shows
+			possible settings and some assignment information.
+
+	pnpacpi=	[ACPI]
+			{ off }
+
+	pnpbios=	[ISAPNP]
+			{ on | off | curr | res | no-curr | no-res }
+
+	pnp_reserve_irq=
+			[ISAPNP] Exclude IRQs for the autoconfiguration
+
+	pnp_reserve_dma=
+			[ISAPNP] Exclude DMAs for the autoconfiguration
+
+	pnp_reserve_io=	[ISAPNP] Exclude I/O ports for the autoconfiguration
+			Ranges are in pairs (I/O port base and size).
+
+	pnp_reserve_mem=
+			[ISAPNP] Exclude memory regions for the
+			autoconfiguration.
+			Ranges are in pairs (memory base and size).
+
+	ports=		[IP_VS_FTP] IPVS ftp helper module
+			Default is 21.
+			Up to 8 (IP_VS_APP_MAX_PORTS) ports
+			may be specified.
+			Format: <port>,<port>....
+
+	powersave=off	[PPC] This option disables power saving features.
+			It specifically disables cpuidle and sets the
+			platform machine description specific power_save
+			function to NULL. On Idle the CPU just reduces
+			execution priority.
+
+	ppc_strict_facility_enable
+			[PPC] This option catches any kernel floating point,
+			Altivec, VSX and SPE outside of regions specifically
+			allowed (eg kernel_enable_fpu()/kernel_disable_fpu()).
+			There is some performance impact when enabling this.
+
+	print-fatal-signals=
+			[KNL] debug: print fatal signals
+
+			If enabled, warn about various signal handling
+			related application anomalies: too many signals,
+			too many POSIX.1 timers, fatal signals causing a
+			coredump - etc.
+
+			If you hit the warning due to signal overflow,
+			you might want to try "ulimit -i unlimited".
+
+			default: off.
+
+	printk.always_kmsg_dump=
+			Trigger kmsg_dump for cases other than kernel oops or
+			panics
+			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
+			default: disabled
+
+	printk.devkmsg={on,off,ratelimit}
+			Control writing to /dev/kmsg.
+			on - unlimited logging to /dev/kmsg from userspace
+			off - logging to /dev/kmsg disabled
+			ratelimit - ratelimit the logging
+			Default: ratelimit
+
+	printk.time=	Show timing data prefixed to each printk message line
+			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
+
+	processor.max_cstate=	[HW,ACPI]
+			Limit processor to maximum C-state
+			max_cstate=9 overrides any DMI blacklist limit.
+
+	processor.nocst	[HW,ACPI]
+			Ignore the _CST method to determine C-states,
+			instead using the legacy FADT method
+
+	profile=	[KNL] Enable kernel profiling via /proc/profile
+			Format: [schedule,]<number>
+			Param: "schedule" - profile schedule points.
+			Param: <number> - step/bucket size as a power of 2 for
+				statistical time based profiling.
+			Param: "sleep" - profile D-state sleeping (millisecs).
+				Requires CONFIG_SCHEDSTATS
+			Param: "kvm" - profile VM exits.
+
+	prompt_ramdisk=	[RAM] List of RAM disks to prompt for floppy disk
+			before loading.
+			See Documentation/blockdev/ramdisk.txt.
+
+	psmouse.proto=	[HW,MOUSE] Highest PS2 mouse protocol extension to
+			probe for; one of (bare|imps|exps|lifebook|any).
+	psmouse.rate=	[HW,MOUSE] Set desired mouse report rate, in reports
+			per second.
+	psmouse.resetafter=	[HW,MOUSE]
+			Try to reset the device after so many bad packets
+			(0 = never).
+	psmouse.resolution=
+			[HW,MOUSE] Set desired mouse resolution, in dpi.
+	psmouse.smartscroll=
+			[HW,MOUSE] Controls Logitech smartscroll autorepeat.
+			0 = disabled, 1 = enabled (default).
+
+	pstore.backend=	Specify the name of the pstore backend to use
+
+	pt.		[PARIDE]
+			See Documentation/blockdev/paride.txt.
+
+	pty.legacy_count=
+			[KNL] Number of legacy pty's. Overwrites compiled-in
+			default number.
+
+	quiet		[KNL] Disable most log messages
+
+	r128=		[HW,DRM]
+
+	raid=		[HW,RAID]
+			See Documentation/admin-guide/md.rst.
+
+	ramdisk_size=	[RAM] Sizes of RAM disks in kilobytes
+			See Documentation/blockdev/ramdisk.txt.
+
+	rcu_nocbs=	[KNL]
+			The argument is a cpu list, as described above.
+
+			In kernels built with CONFIG_RCU_NOCB_CPU=y, set
+			the specified list of CPUs to be no-callback CPUs.
+			Invocation of these CPUs' RCU callbacks will
+			be offloaded to "rcuox/N" kthreads created for
+			that purpose, where "x" is "b" for RCU-bh, "p"
+			for RCU-preempt, and "s" for RCU-sched, and "N"
+			is the CPU number.  This reduces OS jitter on the
+			offloaded CPUs, which can be useful for HPC and
+			real-time workloads.  It can also improve energy
+			efficiency for asymmetric multiprocessors.
+
+	rcu_nocb_poll	[KNL]
+			Rather than requiring that offloaded CPUs
+			(specified by rcu_nocbs= above) explicitly
+			awaken the corresponding "rcuoN" kthreads,
+			make these kthreads poll for callbacks.
+			This improves the real-time response for the
+			offloaded CPUs by relieving them of the need to
+			wake up the corresponding kthread, but degrades
+			energy efficiency by requiring that the kthreads
+			periodically wake up to do the polling.
+
+	rcutree.blimit=	[KNL]
+			Set maximum number of finished RCU callbacks to
+			process in one batch.
+
+	rcutree.dump_tree=	[KNL]
+			Dump the structure of the rcu_node combining tree
+			out at early boot.  This is used for diagnostic
+			purposes, to verify correct tree setup.
+
+	rcutree.gp_cleanup_delay=	[KNL]
+			Set the number of jiffies to delay each step of
+			RCU grace-period cleanup.  This only has effect
+			when CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP is set.
+
+	rcutree.gp_init_delay=	[KNL]
+			Set the number of jiffies to delay each step of
+			RCU grace-period initialization.  This only has
+			effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT
+			is set.
+
+	rcutree.gp_preinit_delay=	[KNL]
+			Set the number of jiffies to delay each step of
+			RCU grace-period pre-initialization, that is,
+			the propagation of recent CPU-hotplug changes up
+			the rcu_node combining tree.  This only has effect
+			when CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT is set.
+
+	rcutree.rcu_fanout_exact= [KNL]
+			Disable autobalancing of the rcu_node combining
+			tree.  This is used by rcutorture, and might
+			possibly be useful for architectures having high
+			cache-to-cache transfer latencies.
+
+	rcutree.rcu_fanout_leaf= [KNL]
+			Change the number of CPUs assigned to each
+			leaf rcu_node structure.  Useful for very
+			large systems, which will choose the value 64,
+			and for NUMA systems with large remote-access
+			latencies, which will choose a value aligned
+			with the appropriate hardware boundaries.
+
+	rcutree.jiffies_till_sched_qs= [KNL]
+			Set required age in jiffies for a
+			given grace period before RCU starts
+			soliciting quiescent-state help from
+			rcu_note_context_switch().
+
+	rcutree.jiffies_till_first_fqs= [KNL]
+			Set delay from grace-period initialization to
+			first attempt to force quiescent states.
+			Units are jiffies, minimum value is zero,
+			and maximum value is HZ.
+
+	rcutree.jiffies_till_next_fqs= [KNL]
+			Set delay between subsequent attempts to force
+			quiescent states.  Units are jiffies, minimum
+			value is one, and maximum value is HZ.
+
+	rcutree.kthread_prio= 	 [KNL,BOOT]
+			Set the SCHED_FIFO priority of the RCU per-CPU
+			kthreads (rcuc/N). This value is also used for
+			the priority of the RCU boost threads (rcub/N)
+			and for the RCU grace-period kthreads (rcu_bh,
+			rcu_preempt, and rcu_sched). If RCU_BOOST is
+			set, valid values are 1-99 and the default is 1
+			(the least-favored priority).  Otherwise, when
+			RCU_BOOST is not set, valid values are 0-99 and
+			the default is zero (non-realtime operation).
+
+	rcutree.rcu_nocb_leader_stride= [KNL]
+			Set the number of NOCB kthread groups, which
+			defaults to the square root of the number of
+			CPUs.  Larger numbers reduces the wakeup overhead
+			on the per-CPU grace-period kthreads, but increases
+			that same overhead on each group's leader.
+
+	rcutree.qhimark= [KNL]
+			Set threshold of queued RCU callbacks beyond which
+			batch limiting is disabled.
+
+	rcutree.qlowmark= [KNL]
+			Set threshold of queued RCU callbacks below which
+			batch limiting is re-enabled.
+
+	rcutree.rcu_idle_gp_delay= [KNL]
+			Set wakeup interval for idle CPUs that have
+			RCU callbacks (RCU_FAST_NO_HZ=y).
+
+	rcutree.rcu_idle_lazy_gp_delay= [KNL]
+			Set wakeup interval for idle CPUs that have
+			only "lazy" RCU callbacks (RCU_FAST_NO_HZ=y).
+			Lazy RCU callbacks are those which RCU can
+			prove do nothing more than free memory.
+
+	rcuperf.gp_exp= [KNL]
+			Measure performance of expedited synchronous
+			grace-period primitives.
+
+	rcuperf.holdoff= [KNL]
+			Set test-start holdoff period.  The purpose of
+			this parameter is to delay the start of the
+			test until boot completes in order to avoid
+			interference.
+
+	rcuperf.nreaders= [KNL]
+			Set number of RCU readers.  The value -1 selects
+			N, where N is the number of CPUs.  A value
+			"n" less than -1 selects N-n+1, where N is again
+			the number of CPUs.  For example, -2 selects N
+			(the number of CPUs), -3 selects N+1, and so on.
+			A value of "n" less than or equal to -N selects
+			a single reader.
+
+	rcuperf.nwriters= [KNL]
+			Set number of RCU writers.  The values operate
+			the same as for rcuperf.nreaders.
+			N, where N is the number of CPUs
+
+	rcuperf.perf_runnable= [BOOT]
+			Start rcuperf running at boot time.
+
+	rcuperf.shutdown= [KNL]
+			Shut the system down after performance tests
+			complete.  This is useful for hands-off automated
+			testing.
+
+	rcuperf.perf_type= [KNL]
+			Specify the RCU implementation to test.
+
+	rcuperf.verbose= [KNL]
+			Enable additional printk() statements.
+
+	rcutorture.cbflood_inter_holdoff= [KNL]
+			Set holdoff time (jiffies) between successive
+			callback-flood tests.
+
+	rcutorture.cbflood_intra_holdoff= [KNL]
+			Set holdoff time (jiffies) between successive
+			bursts of callbacks within a given callback-flood
+			test.
+
+	rcutorture.cbflood_n_burst= [KNL]
+			Set the number of bursts making up a given
+			callback-flood test.  Set this to zero to
+			disable callback-flood testing.
+
+	rcutorture.cbflood_n_per_burst= [KNL]
+			Set the number of callbacks to be registered
+			in a given burst of a callback-flood test.
+
+	rcutorture.fqs_duration= [KNL]
+			Set duration of force_quiescent_state bursts
+			in microseconds.
+
+	rcutorture.fqs_holdoff= [KNL]
+			Set holdoff time within force_quiescent_state bursts
+			in microseconds.
+
+	rcutorture.fqs_stutter= [KNL]
+			Set wait time between force_quiescent_state bursts
+			in seconds.
+
+	rcutorture.gp_cond= [KNL]
+			Use conditional/asynchronous update-side
+			primitives, if available.
+
+	rcutorture.gp_exp= [KNL]
+			Use expedited update-side primitives, if available.
+
+	rcutorture.gp_normal= [KNL]
+			Use normal (non-expedited) asynchronous
+			update-side primitives, if available.
+
+	rcutorture.gp_sync= [KNL]
+			Use normal (non-expedited) synchronous
+			update-side primitives, if available.  If all
+			of rcutorture.gp_cond=, rcutorture.gp_exp=,
+			rcutorture.gp_normal=, and rcutorture.gp_sync=
+			are zero, rcutorture acts as if is interpreted
+			they are all non-zero.
+
+	rcutorture.n_barrier_cbs= [KNL]
+			Set callbacks/threads for rcu_barrier() testing.
+
+	rcutorture.nfakewriters= [KNL]
+			Set number of concurrent RCU writers.  These just
+			stress RCU, they don't participate in the actual
+			test, hence the "fake".
+
+	rcutorture.nreaders= [KNL]
+			Set number of RCU readers.  The value -1 selects
+			N-1, where N is the number of CPUs.  A value
+			"n" less than -1 selects N-n-2, where N is again
+			the number of CPUs.  For example, -2 selects N
+			(the number of CPUs), -3 selects N+1, and so on.
+
+	rcutorture.object_debug= [KNL]
+			Enable debug-object double-call_rcu() testing.
+
+	rcutorture.onoff_holdoff= [KNL]
+			Set time (s) after boot for CPU-hotplug testing.
+
+	rcutorture.onoff_interval= [KNL]
+			Set time (s) between CPU-hotplug operations, or
+			zero to disable CPU-hotplug testing.
+
+	rcutorture.shuffle_interval= [KNL]
+			Set task-shuffle interval (s).  Shuffling tasks
+			allows some CPUs to go into dyntick-idle mode
+			during the rcutorture test.
+
+	rcutorture.shutdown_secs= [KNL]
+			Set time (s) after boot system shutdown.  This
+			is useful for hands-off automated testing.
+
+	rcutorture.stall_cpu= [KNL]
+			Duration of CPU stall (s) to test RCU CPU stall
+			warnings, zero to disable.
+
+	rcutorture.stall_cpu_holdoff= [KNL]
+			Time to wait (s) after boot before inducing stall.
+
+	rcutorture.stat_interval= [KNL]
+			Time (s) between statistics printk()s.
+
+	rcutorture.stutter= [KNL]
+			Time (s) to stutter testing, for example, specifying
+			five seconds causes the test to run for five seconds,
+			wait for five seconds, and so on.  This tests RCU's
+			ability to transition abruptly to and from idle.
+
+	rcutorture.test_boost= [KNL]
+			Test RCU priority boosting?  0=no, 1=maybe, 2=yes.
+			"Maybe" means test if the RCU implementation
+			under test support RCU priority boosting.
+
+	rcutorture.test_boost_duration= [KNL]
+			Duration (s) of each individual boost test.
+
+	rcutorture.test_boost_interval= [KNL]
+			Interval (s) between each boost test.
+
+	rcutorture.test_no_idle_hz= [KNL]
+			Test RCU's dyntick-idle handling.  See also the
+			rcutorture.shuffle_interval parameter.
+
+	rcutorture.torture_runnable= [BOOT]
+			Start rcutorture running at boot time.
+
+	rcutorture.torture_type= [KNL]
+			Specify the RCU implementation to test.
+
+	rcutorture.verbose= [KNL]
+			Enable additional printk() statements.
+
+	rcupdate.rcu_cpu_stall_suppress= [KNL]
+			Suppress RCU CPU stall warning messages.
+
+	rcupdate.rcu_cpu_stall_timeout= [KNL]
+			Set timeout for RCU CPU stall warning messages.
+
+	rcupdate.rcu_expedited= [KNL]
+			Use expedited grace-period primitives, for
+			example, synchronize_rcu_expedited() instead
+			of synchronize_rcu().  This reduces latency,
+			but can increase CPU utilization, degrade
+			real-time latency, and degrade energy efficiency.
+			No effect on CONFIG_TINY_RCU kernels.
+
+	rcupdate.rcu_normal= [KNL]
+			Use only normal grace-period primitives,
+			for example, synchronize_rcu() instead of
+			synchronize_rcu_expedited().  This improves
+			real-time latency, CPU utilization, and
+			energy efficiency, but can expose users to
+			increased grace-period latency.  This parameter
+			overrides rcupdate.rcu_expedited.  No effect on
+			CONFIG_TINY_RCU kernels.
+
+	rcupdate.rcu_normal_after_boot= [KNL]
+			Once boot has completed (that is, after
+			rcu_end_inkernel_boot() has been invoked), use
+			only normal grace-period primitives.  No effect
+			on CONFIG_TINY_RCU kernels.
+
+	rcupdate.rcu_task_stall_timeout= [KNL]
+			Set timeout in jiffies for RCU task stall warning
+			messages.  Disable with a value less than or equal
+			to zero.
+
+	rcupdate.rcu_self_test= [KNL]
+			Run the RCU early boot self tests
+
+	rcupdate.rcu_self_test_bh= [KNL]
+			Run the RCU bh early boot self tests
+
+	rcupdate.rcu_self_test_sched= [KNL]
+			Run the RCU sched early boot self tests
+
+	rdinit=		[KNL]
+			Format: <full_path>
+			Run specified binary instead of /init from the ramdisk,
+			used for early userspace startup. See initrd.
+
+	reboot=		[KNL]
+			Format (x86 or x86_64):
+				[w[arm] | c[old] | h[ard] | s[oft] | g[pio]] \
+				[[,]s[mp]#### \
+				[[,]b[ios] | a[cpi] | k[bd] | t[riple] | e[fi] | p[ci]] \
+				[[,]f[orce]
+			Where reboot_mode is one of warm (soft) or cold (hard) or gpio,
+			      reboot_type is one of bios, acpi, kbd, triple, efi, or pci,
+			      reboot_force is either force or not specified,
+			      reboot_cpu is s[mp]#### with #### being the processor
+					to be used for rebooting.
+
+	relax_domain_level=
+			[KNL, SMP] Set scheduler's default relax_domain_level.
+			See Documentation/cgroup-v1/cpusets.txt.
+
+	reserve=	[KNL,BUGS] Force the kernel to ignore some iomem area
+
+	reservetop=	[X86-32]
+			Format: nn[KMG]
+			Reserves a hole at the top of the kernel virtual
+			address space.
+
+	reservelow=	[X86]
+			Format: nn[K]
+			Set the amount of memory to reserve for BIOS at
+			the bottom of the address space.
+
+	reset_devices	[KNL] Force drivers to reset the underlying device
+			during initialization.
+
+	resume=		[SWSUSP]
+			Specify the partition device for software suspend
+			Format:
+			{/dev/<dev> | PARTUUID=<uuid> | <int>:<int> | <hex>}
+
+	resume_offset=	[SWSUSP]
+			Specify the offset from the beginning of the partition
+			given by "resume=" at which the swap header is located,
+			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.
+		nocompress	Don't compress/decompress hibernation images.
+		no		Disable hibernation and resume.
+		protect_image	Turn on image protection during restoration
+				(that will set all pages holding image data
+				during restoration read-only).
+
+	retain_initrd	[RAM] Keep initrd memory after extraction
+
+	rfkill.default_state=
+		0	"airplane mode".  All wifi, bluetooth, wimax, gps, fm,
+			etc. communication is blocked by default.
+		1	Unblocked.
+
+	rfkill.master_switch_mode=
+		0	The "airplane mode" button does nothing.
+		1	The "airplane mode" button toggles between everything
+			blocked and the previous configuration.
+		2	The "airplane mode" button toggles between everything
+			blocked and everything unblocked.
+
+	rhash_entries=	[KNL,NET]
+			Set number of hash buckets for route cache
+
+	ro		[KNL] Mount root device read-only on boot
+
+	rodata=		[KNL]
+		on	Mark read-only kernel memory as read-only (default).
+		off	Leave read-only kernel memory writable for debugging.
+
+	rockchip.usb_uart
+			Enable the uart passthrough on the designated usb port
+			on Rockchip SoCs. When active, the signals of the
+			debug-uart get routed to the D+ and D- pins of the usb
+			port and the regular usb controller gets disabled.
+
+	root=		[KNL] Root filesystem
+			See name_to_dev_t comment in init/do_mounts.c.
+
+	rootdelay=	[KNL] Delay (in seconds) to pause before attempting to
+			mount the root filesystem
+
+	rootflags=	[KNL] Set root filesystem mount option string
+
+	rootfstype=	[KNL] Set root filesystem type
+
+	rootwait	[KNL] Wait (indefinitely) for root device to show up.
+			Useful for devices that are detected asynchronously
+			(e.g. USB and MMC devices).
+
+	rproc_mem=nn[KMG][@address]
+			[KNL,ARM,CMA] Remoteproc physical memory block.
+			Memory area to be used by remote processor image,
+			managed by CMA.
+
+	rw		[KNL] Mount root device read-write on boot
+
+	S		[KNL] Run init in single mode
+
+	s390_iommu=	[HW,S390]
+			Set s390 IOTLB flushing mode
+		strict
+			With strict flushing every unmap operation will result in
+			an IOTLB flush. Default is lazy flushing before reuse,
+			which is faster.
+
+	sa1100ir	[NET]
+			See drivers/net/irda/sa1100_ir.c.
+
+	sbni=		[NET] Granch SBNI12 leased line adapter
+
+	sched_debug	[KNL] Enables verbose scheduler debug messages.
+
+	schedstats=	[KNL,X86] Enable or disable scheduled statistics.
+			Allowed values are enable and disable. This feature
+			incurs a small amount of overhead in the scheduler
+			but is useful for debugging and performance tuning.
+
+	skew_tick=	[KNL] Offset the periodic timer tick per cpu to mitigate
+			xtime_lock contention on larger systems, and/or RCU lock
+			contention on all systems with CONFIG_MAXSMP set.
+			Format: { "0" | "1" }
+			0 -- disable. (may be 1 via CONFIG_CMDLINE="skew_tick=1"
+			1 -- enable.
+			Note: increases power consumption, thus should only be
+			enabled if running jitter sensitive (HPC/RT) workloads.
+
+	security=	[SECURITY] Choose a security module to enable at boot.
+			If this boot parameter is not specified, only the first
+			security module asking for security registration will be
+			loaded. An invalid security module name will be treated
+			as if no module has been chosen.
+
+	selinux=	[SELINUX] Disable or enable SELinux at boot time.
+			Format: { "0" | "1" }
+			See security/selinux/Kconfig help text.
+			0 -- disable.
+			1 -- enable.
+			Default value is set via kernel config option.
+			If enabled at boot time, /selinux/disable can be used
+			later to disable prior to initial policy load.
+
+	apparmor=	[APPARMOR] Disable or enable AppArmor at boot time
+			Format: { "0" | "1" }
+			See security/apparmor/Kconfig help text
+			0 -- disable.
+			1 -- enable.
+			Default value is set via kernel config option.
+
+	serialnumber	[BUGS=X86-32]
+
+	shapers=	[NET]
+			Maximal number of shapers.
+
+	simeth=		[IA-64]
+	simscsi=
+
+	slram=		[HW,MTD]
+
+	slab_nomerge	[MM]
+			Disable merging of slabs with similar size. May be
+			necessary if there is some reason to distinguish
+			allocs to different slabs. Debug options disable
+			merging on their own.
+			For more information see Documentation/vm/slub.txt.
+
+	slab_max_order=	[MM, SLAB]
+			Determines the maximum allowed order for slabs.
+			A high setting may cause OOMs due to memory
+			fragmentation.  Defaults to 1 for systems with
+			more than 32MB of RAM, 0 otherwise.
+
+	slub_debug[=options[,slabs]]	[MM, SLUB]
+			Enabling slub_debug allows one to determine the
+			culprit if slab objects become corrupted. Enabling
+			slub_debug can create guard zones around objects and
+			may poison objects when not in use. Also tracks the
+			last alloc / free. For more information see
+			Documentation/vm/slub.txt.
+
+	slub_max_order= [MM, SLUB]
+			Determines the maximum allowed order for slabs.
+			A high setting may cause OOMs due to memory
+			fragmentation. For more information see
+			Documentation/vm/slub.txt.
+
+	slub_min_objects=	[MM, SLUB]
+			The minimum number of objects per slab. SLUB will
+			increase the slab order up to slub_max_order to
+			generate a sufficiently large slab able to contain
+			the number of objects indicated. The higher the number
+			of objects the smaller the overhead of tracking slabs
+			and the less frequently locks need to be acquired.
+			For more information see Documentation/vm/slub.txt.
+
+	slub_min_order=	[MM, SLUB]
+			Determines the minimum page order for slabs. Must be
+			lower than slub_max_order.
+			For more information see Documentation/vm/slub.txt.
+
+	slub_nomerge	[MM, SLUB]
+			Same with slab_nomerge. This is supported for legacy.
+			See slab_nomerge for more information.
+
+	smart2=		[HW]
+			Format: <io1>[,<io2>[,...,<io8>]]
+
+	smsc-ircc2.nopnp	[HW] Don't use PNP to discover SMC devices
+	smsc-ircc2.ircc_cfg=	[HW] Device configuration I/O port
+	smsc-ircc2.ircc_sir=	[HW] SIR base I/O port
+	smsc-ircc2.ircc_fir=	[HW] FIR base I/O port
+	smsc-ircc2.ircc_irq=	[HW] IRQ line
+	smsc-ircc2.ircc_dma=	[HW] DMA channel
+	smsc-ircc2.ircc_transceiver= [HW] Transceiver type:
+				0: Toshiba Satellite 1800 (GP data pin select)
+				1: Fast pin select (default)
+				2: ATC IRMode
+
+	smt		[KNL,S390] Set the maximum number of threads (logical
+			CPUs) to use per physical CPU on systems capable of
+			symmetric multithreading (SMT). Will be capped to the
+			actual hardware limit.
+			Format: <integer>
+			Default: -1 (no limit)
+
+	softlockup_panic=
+			[KNL] Should the soft-lockup detector generate panics.
+			Format: <integer>
+
+	softlockup_all_cpu_backtrace=
+			[KNL] Should the soft-lockup detector generate
+			backtraces on all cpus.
+			Format: <integer>
+
+	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
+			See Documentation/laptops/sonypi.txt
+
+	spia_io_base=	[HW,MTD]
+	spia_fio_base=
+	spia_pedr=
+	spia_peddr=
+
+	stacktrace	[FTRACE]
+			Enabled the stack tracer on boot up.
+
+	stacktrace_filter=[function-list]
+			[FTRACE] Limit the functions that the stack tracer
+			will trace at boot up. function-list is a comma separated
+			list of functions. This list can be changed at run
+			time by the stack_trace_filter file in the debugfs
+			tracing directory. Note, this enables stack tracing
+			and the stacktrace above is not needed.
+
+	sti=		[PARISC,HW]
+			Format: <num>
+			Set the STI (builtin display/keyboard on the HP-PARISC
+			machines) console (graphic card) which should be used
+			as the initial boot-console.
+			See also comment in drivers/video/console/sticore.c.
+
+	sti_font=	[HW]
+			See comment in drivers/video/console/sticore.c.
+
+	stifb=		[HW]
+			Format: bpp:<bpp1>[:<bpp2>[:<bpp3>...]]
+
+	sunrpc.min_resvport=
+	sunrpc.max_resvport=
+			[NFS,SUNRPC]
+			SunRPC servers often require that client requests
+			originate from a privileged port (i.e. a port in the
+			range 0 < portnr < 1024).
+			An administrator who wishes to reserve some of these
+			ports for other uses may adjust the range that the
+			kernel's sunrpc client considers to be privileged
+			using these two parameters to set the minimum and
+			maximum port values.
+
+	sunrpc.svc_rpc_per_connection_limit=
+			[NFS,SUNRPC]
+			Limit the number of requests that the server will
+			process in parallel from a single connection.
+			The default value is 0 (no limit).
+
+	sunrpc.pool_mode=
+			[NFS]
+			Control how the NFS server code allocates CPUs to
+			service thread pools.  Depending on how many NICs
+			you have and where their interrupts are bound, this
+			option will affect which CPUs will do NFS serving.
+			Note: this parameter cannot be changed while the
+			NFS server is running.
+
+			auto	    the server chooses an appropriate mode
+				    automatically using heuristics
+			global	    a single global pool contains all CPUs
+			percpu	    one pool for each CPU
+			pernode	    one pool for each NUMA node (equivalent
+				    to global on non-NUMA machines)
+
+	sunrpc.tcp_slot_table_entries=
+	sunrpc.udp_slot_table_entries=
+			[NFS,SUNRPC]
+			Sets the upper limit on the number of simultaneous
+			RPC calls that can be sent from the client to a
+			server. Increasing these values may allow you to
+			improve throughput, but will also increase the
+			amount of memory reserved for use by the client.
+
+	suspend.pm_test_delay=
+			[SUSPEND]
+			Sets the number of seconds to remain in a suspend test
+			mode before resuming the system (see
+			/sys/power/pm_test). Only available when CONFIG_PM_DEBUG
+			is set. Default value is 5.
+
+	swapaccount=[0|1]
+			[KNL] Enable accounting of swap in memory resource
+			controller if no parameter or 1 is given or disable
+			it if 0 is given (See Documentation/cgroup-v1/memory.txt)
+
+	swiotlb=	[ARM,IA-64,PPC,MIPS,X86]
+			Format: { <int> | force | noforce }
+			<int> -- Number of I/O TLB slabs
+			force -- force using of bounce buffers even if they
+			         wouldn't be automatically used by the kernel
+			noforce -- Never use bounce buffers (for debugging)
+
+	switches=	[HW,M68k]
+
+	sysfs.deprecated=0|1 [KNL]
+			Enable/disable old style sysfs layout for old udev
+			on older distributions. When this option is enabled
+			very new udev will not work anymore. When this option
+			is disabled (or CONFIG_SYSFS_DEPRECATED not compiled)
+			in older udev will not work anymore.
+			Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in
+			the kernel configuration.
+
+	sysrq_always_enabled
+			[KNL]
+			Ignore sysrq setting - this boot parameter will
+			neutralize any effect of /proc/sys/kernel/sysrq.
+			Useful for debugging.
+
+	tcpmhash_entries= [KNL,NET]
+			Set the number of tcp_metrics_hash slots.
+			Default value is 8192 or 16384 depending on total
+			ram pages. This is used to specify the TCP metrics
+			cache size. See Documentation/networking/ip-sysctl.txt
+			"tcp_no_metrics_save" section for more details.
+
+	tdfx=		[HW,DRM]
+
+	test_suspend=	[SUSPEND][,N]
+			Specify "mem" (for Suspend-to-RAM) or "standby" (for
+			standby suspend) or "freeze" (for suspend type freeze)
+			as the system sleep state during system startup with
+			the optional capability to repeat N number of times.
+			The system is woken from this state using a
+			wakeup-capable RTC alarm.
+
+	thash_entries=	[KNL,NET]
+			Set number of hash buckets for TCP connection
+
+	thermal.act=	[HW,ACPI]
+			-1: disable all active trip points in all thermal zones
+			<degrees C>: override all lowest active trip points
+
+	thermal.crt=	[HW,ACPI]
+			-1: disable all critical trip points in all thermal zones
+			<degrees C>: override all critical trip points
+
+	thermal.nocrt=	[HW,ACPI]
+			Set to disable actions on ACPI thermal zone
+			critical and hot trip points.
+
+	thermal.off=	[HW,ACPI]
+			1: disable ACPI thermal control
+
+	thermal.psv=	[HW,ACPI]
+			-1: disable all passive trip points
+			<degrees C>: override all passive trip points to this
+			value
+
+	thermal.tzp=	[HW,ACPI]
+			Specify global default ACPI thermal zone polling rate
+			<deci-seconds>: poll all this frequency
+			0: no polling (default)
+
+	threadirqs	[KNL]
+			Force threading of all interrupt handlers except those
+			marked explicitly IRQF_NO_THREAD.
+
+	tmem		[KNL,XEN]
+			Enable the Transcendent memory driver if built-in.
+
+	tmem.cleancache=0|1 [KNL, XEN]
+			Default is on (1). Disable the usage of the cleancache
+			API to send anonymous pages to the hypervisor.
+
+	tmem.frontswap=0|1 [KNL, XEN]
+			Default is on (1). Disable the usage of the frontswap
+			API to send swap pages to the hypervisor. If disabled
+			the selfballooning and selfshrinking are force disabled.
+
+	tmem.selfballooning=0|1 [KNL, XEN]
+			Default is on (1). Disable the driving of swap pages
+			to the hypervisor.
+
+	tmem.selfshrinking=0|1 [KNL, XEN]
+			Default is on (1). Partial swapoff that immediately
+			transfers pages from Xen hypervisor back to the
+			kernel based on different criteria.
+
+	topology=	[S390]
+			Format: {off | on}
+			Specify if the kernel should make use of the cpu
+			topology information if the hardware supports this.
+			The scheduler will make use of this information and
+			e.g. base its process migration decisions on it.
+			Default is on.
+
+	topology_updates= [KNL, PPC, NUMA]
+			Format: {off}
+			Specify if the kernel should ignore (off)
+			topology updates sent by the hypervisor to this
+			LPAR.
+
+	tp720=		[HW,PS2]
+
+	tpm_suspend_pcr=[HW,TPM]
+			Format: integer pcr id
+			Specify that at suspend time, the tpm driver
+			should extend the specified pcr with zeros,
+			as a workaround for some chips which fail to
+			flush the last written pcr on TPM_SaveState.
+			This will guarantee that all the other pcrs
+			are saved.
+
+	trace_buf_size=nn[KMG]
+			[FTRACE] will set tracing buffer size on each cpu.
+
+	trace_event=[event-list]
+			[FTRACE] Set and start specified trace events in order
+			to facilitate early boot debugging. The event-list is a
+			comma separated list of trace events to enable. See
+			also Documentation/trace/events.txt
+
+	trace_options=[option-list]
+			[FTRACE] Enable or disable tracer options at boot.
+			The option-list is a comma delimited list of options
+			that can be enabled or disabled just as if you were
+			to echo the option name into
+
+			    /sys/kernel/debug/tracing/trace_options
+
+			For example, to enable stacktrace option (to dump the
+			stack trace of each event), add to the command line:
+
+			      trace_options=stacktrace
+
+			See also Documentation/trace/ftrace.txt "trace options"
+			section.
+
+	tp_printk[FTRACE]
+			Have the tracepoints sent to printk as well as the
+			tracing ring buffer. This is useful for early boot up
+			where the system hangs or reboots and does not give the
+			option for reading the tracing buffer or performing a
+			ftrace_dump_on_oops.
+
+			To turn off having tracepoints sent to printk,
+			 echo 0 > /proc/sys/kernel/tracepoint_printk
+			Note, echoing 1 into this file without the
+			tracepoint_printk kernel cmdline option has no effect.
+
+			** CAUTION **
+
+			Having tracepoints sent to printk() and activating high
+			frequency tracepoints such as irq or sched, can cause
+			the system to live lock.
+
+	traceoff_on_warning
+			[FTRACE] enable this option to disable tracing when a
+			warning is hit. This turns off "tracing_on". Tracing can
+			be enabled again by echoing '1' into the "tracing_on"
+			file located in /sys/kernel/debug/tracing/
+
+			This option is useful, as it disables the trace before
+			the WARNING dump is called, which prevents the trace to
+			be filled with content caused by the warning output.
+
+			This option can also be set at run time via the sysctl
+			option:  kernel/traceoff_on_warning
+
+	transparent_hugepage=
+			[KNL]
+			Format: [always|madvise|never]
+			Can be used to control the default behavior of the system
+			with respect to transparent hugepages.
+			See Documentation/vm/transhuge.txt for more details.
+
+	tsc=		Disable clocksource stability checks for TSC.
+			Format: <string>
+			[x86] reliable: mark tsc clocksource as reliable, this
+			disables clocksource verification at runtime, as well
+			as the stability checks done at bootup.	Used to enable
+			high-resolution timer mode on older hardware, and in
+			virtualized environment.
+			[x86] noirqtime: Do not use TSC to do irq accounting.
+			Used to run time disable IRQ_TIME_ACCOUNTING on any
+			platforms where RDTSC is slow and this accounting
+			can add overhead.
+
+	turbografx.map[2|3]=	[HW,JOY]
+			TurboGraFX parallel port interface
+			Format:
+			<port#>,<js1>,<js2>,<js3>,<js4>,<js5>,<js6>,<js7>
+			See also Documentation/input/joystick-parport.txt
+
+	udbg-immortal	[PPC] When debugging early kernel crashes that
+			happen after console_init() and before a proper
+			console driver takes over, this boot options might
+			help "seeing" what's going on.
+
+	uhash_entries=	[KNL,NET]
+			Set number of hash buckets for UDP/UDP-Lite connections
+
+	uhci-hcd.ignore_oc=
+			[USB] Ignore overcurrent events (default N).
+			Some badly-designed motherboards generate lots of
+			bogus events, for ports that aren't wired to
+			anything.  Set this parameter to avoid log spamming.
+			Note that genuine overcurrent events won't be
+			reported either.
+
+	unknown_nmi_panic
+			[X86] Cause panic on unknown NMI.
+
+	usbcore.authorized_default=
+			[USB] Default USB device authorization:
+			(default -1 = authorized except for wireless USB,
+			0 = not authorized, 1 = authorized)
+
+	usbcore.autosuspend=
+			[USB] The autosuspend time delay (in seconds) used
+			for newly-detected USB devices (default 2).  This
+			is the time required before an idle device will be
+			autosuspended.  Devices for which the delay is set
+			to a negative value won't be autosuspended at all.
+
+	usbcore.usbfs_snoop=
+			[USB] Set to log all usbfs traffic (default 0 = off).
+
+	usbcore.usbfs_snoop_max=
+			[USB] Maximum number of bytes to snoop in each URB
+			(default = 65536).
+
+	usbcore.blinkenlights=
+			[USB] Set to cycle leds on hubs (default 0 = off).
+
+	usbcore.old_scheme_first=
+			[USB] Start with the old device initialization
+			scheme (default 0 = off).
+
+	usbcore.usbfs_memory_mb=
+			[USB] Memory limit (in MB) for buffers allocated by
+			usbfs (default = 16, 0 = max = 2047).
+
+	usbcore.use_both_schemes=
+			[USB] Try the other device initialization scheme
+			if the first one fails (default 1 = enabled).
+
+	usbcore.initial_descriptor_timeout=
+			[USB] Specifies timeout for the initial 64-byte
+                        USB_REQ_GET_DESCRIPTOR request in milliseconds
+			(default 5000 = 5.0 seconds).
+
+	usbcore.nousb	[USB] Disable the USB subsystem
+
+	usbhid.mousepoll=
+			[USBHID] The interval which mice are to be polled at.
+
+	usb-storage.delay_use=
+			[UMS] The delay in seconds before a new device is
+			scanned for Logical Units (default 1).
+
+	usb-storage.quirks=
+			[UMS] A list of quirks entries to supplement or
+			override the built-in unusual_devs list.  List
+			entries are separated by commas.  Each entry has
+			the form VID:PID:Flags where VID and PID are Vendor
+			and Product ID values (4-digit hex numbers) and
+			Flags is a set of characters, each corresponding
+			to a common usb-storage quirk flag as follows:
+				a = SANE_SENSE (collect more than 18 bytes
+					of sense data);
+				b = BAD_SENSE (don't collect more than 18
+					bytes of sense data);
+				c = FIX_CAPACITY (decrease the reported
+					device capacity by one sector);
+				d = NO_READ_DISC_INFO (don't use
+					READ_DISC_INFO command);
+				e = NO_READ_CAPACITY_16 (don't use
+					READ_CAPACITY_16 command);
+				f = NO_REPORT_OPCODES (don't use report opcodes
+					command, uas only);
+				g = MAX_SECTORS_240 (don't transfer more than
+					240 sectors at a time, uas only);
+				h = CAPACITY_HEURISTICS (decrease the
+					reported device capacity by one
+					sector if the number is odd);
+				i = IGNORE_DEVICE (don't bind to this
+					device);
+				j = NO_REPORT_LUNS (don't use report luns
+					command, uas only);
+				l = NOT_LOCKABLE (don't try to lock and
+					unlock ejectable media);
+				m = MAX_SECTORS_64 (don't transfer more
+					than 64 sectors = 32 KB at a time);
+				n = INITIAL_READ10 (force a retry of the
+					initial READ(10) command);
+				o = CAPACITY_OK (accept the capacity
+					reported by the device);
+				p = WRITE_CACHE (the device cache is ON
+					by default);
+				r = IGNORE_RESIDUE (the device reports
+					bogus residue values);
+				s = SINGLE_LUN (the device has only one
+					Logical Unit);
+				t = NO_ATA_1X (don't allow ATA(12) and ATA(16)
+					commands, uas only);
+				u = IGNORE_UAS (don't bind to the uas driver);
+				w = NO_WP_DETECT (don't test whether the
+					medium is write-protected).
+				y = ALWAYS_SYNC (issue a SYNCHRONIZE_CACHE
+					even if the device claims no cache)
+			Example: quirks=0419:aaf5:rl,0421:0433:rc
+
+	user_debug=	[KNL,ARM]
+			Format: <int>
+			See arch/arm/Kconfig.debug help text.
+				 1 - undefined instruction events
+				 2 - system calls
+				 4 - invalid data aborts
+				 8 - SIGSEGV faults
+				16 - SIGBUS faults
+			Example: user_debug=31
+
+	userpte=
+			[X86] Flags controlling user PTE allocations.
+
+				nohigh = do not allocate PTE pages in
+					HIGHMEM regardless of setting
+					of CONFIG_HIGHPTE.
+
+	vdso=		[X86,SH]
+			On X86_32, this is an alias for vdso32=.  Otherwise:
+
+			vdso=1: enable VDSO (the default)
+			vdso=0: disable VDSO mapping
+
+	vdso32=		[X86] Control the 32-bit vDSO
+			vdso32=1: enable 32-bit VDSO
+			vdso32=0 or vdso32=2: disable 32-bit VDSO
+
+			See the help text for CONFIG_COMPAT_VDSO for more
+			details.  If CONFIG_COMPAT_VDSO is set, the default is
+			vdso32=0; otherwise, the default is vdso32=1.
+
+			For compatibility with older kernels, vdso32=2 is an
+			alias for vdso32=0.
+
+			Try vdso32=0 if you encounter an error that says:
+			dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!
+
+	vector=		[IA-64,SMP]
+			vector=percpu: enable percpu vector domain
+
+	video=		[FB] Frame buffer configuration
+			See Documentation/fb/modedb.txt.
+
+	video.brightness_switch_enabled= [0,1]
+			If set to 1, on receiving an ACPI notify event
+			generated by hotkey, video driver will adjust brightness
+			level and then send out the event to user space through
+			the allocated input device; If set to 0, video driver
+			will only send out the event without touching backlight
+			brightness level.
+			default: 1
+
+	virtio_mmio.device=
+			[VMMIO] Memory mapped virtio (platform) device.
+
+				<size>@<baseaddr>:<irq>[:<id>]
+			where:
+				<size>     := size (can use standard suffixes
+						like K, M and G)
+				<baseaddr> := physical base address
+				<irq>      := interrupt number (as passed to
+						request_irq())
+				<id>       := (optional) platform device id
+			example:
+				virtio_mmio.device=1K@0x100b0000:48:7
+
+			Can be used multiple times for multiple devices.
+
+	vga=		[BOOT,X86-32] Select a particular video mode
+			See Documentation/x86/boot.txt and
+			Documentation/svga.txt.
+			Use vga=ask for menu.
+			This is actually a boot loader parameter; the value is
+			passed to the kernel using a special protocol.
+
+	vmalloc=nn[KMG]	[KNL,BOOT] Forces the vmalloc area to have an exact
+			size of <nn>. This can be used to increase the
+			minimum size (128MB on x86). It can also be used to
+			decrease the size and leave more room for directly
+			mapped kernel RAM.
+
+	vmhalt=		[KNL,S390] Perform z/VM CP command after system halt.
+			Format: <command>
+
+	vmpanic=	[KNL,S390] Perform z/VM CP command after kernel panic.
+			Format: <command>
+
+	vmpoff=		[KNL,S390] Perform z/VM CP command after power off.
+			Format: <command>
+
+	vsyscall=	[X86-64]
+			Controls the behavior of vsyscalls (i.e. calls to
+			fixed addresses of 0xffffffffff600x00 from legacy
+			code).  Most statically-linked binaries and older
+			versions of glibc use these calls.  Because these
+			functions are at fixed addresses, they make nice
+			targets for exploits that can control RIP.
+
+			emulate     [default] Vsyscalls turn into traps and are
+			            emulated reasonably safely.
+
+			native      Vsyscalls are native syscall instructions.
+			            This is a little bit faster than trapping
+			            and makes a few dynamic recompilers work
+			            better than they would in emulation mode.
+			            It also makes exploits much easier to write.
+
+			none        Vsyscalls don't work at all.  This makes
+			            them quite hard to use for exploits but
+			            might break your system.
+
+	vt.color=	[VT] Default text color.
+			Format: 0xYX, X = foreground, Y = background.
+			Default: 0x07 = light gray on black.
+
+	vt.cur_default=	[VT] Default cursor shape.
+			Format: 0xCCBBAA, where AA, BB, and CC are the same as
+			the parameters of the <Esc>[?A;B;Cc escape sequence;
+			see VGA-softcursor.txt. Default: 2 = underline.
+
+	vt.default_blu=	[VT]
+			Format: <blue0>,<blue1>,<blue2>,...,<blue15>
+			Change the default blue palette of the console.
+			This is a 16-member array composed of values
+			ranging from 0-255.
+
+	vt.default_grn=	[VT]
+			Format: <green0>,<green1>,<green2>,...,<green15>
+			Change the default green palette of the console.
+			This is a 16-member array composed of values
+			ranging from 0-255.
+
+	vt.default_red=	[VT]
+			Format: <red0>,<red1>,<red2>,...,<red15>
+			Change the default red palette of the console.
+			This is a 16-member array composed of values
+			ranging from 0-255.
+
+	vt.default_utf8=
+			[VT]
+			Format=<0|1>
+			Set system-wide default UTF-8 mode for all tty's.
+			Default is 1, i.e. UTF-8 mode is enabled for all
+			newly opened terminals.
+
+	vt.global_cursor_default=
+			[VT]
+			Format=<-1|0|1>
+			Set system-wide default for whether a cursor
+			is shown on new VTs. Default is -1,
+			i.e. cursors will be created by default unless
+			overridden by individual drivers. 0 will hide
+			cursors, 1 will display them.
+
+	vt.italic=	[VT] Default color for italic text; 0-15.
+			Default: 2 = green.
+
+	vt.underline=	[VT] Default color for underlined text; 0-15.
+			Default: 3 = cyan.
+
+	watchdog timers	[HW,WDT] For information on watchdog timers,
+			see Documentation/watchdog/watchdog-parameters.txt
+			or other driver-specific files in the
+			Documentation/watchdog/ directory.
+
+	workqueue.watchdog_thresh=
+			If CONFIG_WQ_WATCHDOG is configured, workqueue can
+			warn stall conditions and dump internal state to
+			help debugging.  0 disables workqueue stall
+			detection; otherwise, it's the stall threshold
+			duration in seconds.  The default value is 30 and
+			it can be updated at runtime by writing to the
+			corresponding sysfs file.
+
+	workqueue.disable_numa
+			By default, all work items queued to unbound
+			workqueues are affine to the NUMA nodes they're
+			issued on, which results in better behavior in
+			general.  If NUMA affinity needs to be disabled for
+			whatever reason, this option can be used.  Note
+			that this also can be controlled per-workqueue for
+			workqueues visible under /sys/bus/workqueue/.
+
+	workqueue.power_efficient
+			Per-cpu workqueues are generally preferred because
+			they show better performance thanks to cache
+			locality; unfortunately, per-cpu workqueues tend to
+			be more power hungry than unbound workqueues.
+
+			Enabling this makes the per-cpu workqueues which
+			were observed to contribute significantly to power
+			consumption unbound, leading to measurably lower
+			power usage at the cost of small performance
+			overhead.
+
+			The default value of this parameter is determined by
+			the config option CONFIG_WQ_POWER_EFFICIENT_DEFAULT.
+
+	workqueue.debug_force_rr_cpu
+			Workqueue used to implicitly guarantee that work
+			items queued without explicit CPU specified are put
+			on the local CPU.  This guarantee is no longer true
+			and while local CPU is still preferred work items
+			may be put on foreign CPUs.  This debug option
+			forces round-robin CPU selection to flush out
+			usages which depend on the now broken guarantee.
+			When enabled, memory and cache locality will be
+			impacted.
+
+	x2apic_phys	[X86-64,APIC] Use x2apic physical mode instead of
+			default x2apic cluster mode on platforms
+			supporting x2apic.
+
+	x86_intel_mid_timer= [X86-32,APBT]
+			Choose timer option for x86 Intel MID platform.
+			Two valid options are apbt timer only and lapic timer
+			plus one apbt timer for broadcast timer.
+			x86_intel_mid_timer=apbt_only | lapic_and_apbt
+
+	xen_512gb_limit		[KNL,X86-64,XEN]
+			Restricts the kernel running paravirtualized under Xen
+			to use only up to 512 GB of RAM. The reason to do so is
+			crash analysis tools and Xen tools for doing domain
+			save/restore/migration must be enabled to handle larger
+			domains.
+
+	xen_emul_unplug=		[HW,X86,XEN]
+			Unplug Xen emulated devices
+			Format: [unplug0,][unplug1]
+			ide-disks -- unplug primary master IDE devices
+			aux-ide-disks -- unplug non-primary-master IDE devices
+			nics -- unplug network devices
+			all -- unplug all emulated devices (NICs and IDE disks)
+			unnecessary -- unplugging emulated devices is
+				unnecessary even if the host did not respond to
+				the unplug protocol
+			never -- do not unplug even if version check succeeds
+
+	xen_nopvspin	[X86,XEN]
+			Disables the ticketlock slowpath using Xen PV
+			optimizations.
+
+	xen_nopv	[X86]
+			Disables the PV optimizations forcing the HVM guest to
+			run as generic HVM guest with no PV drivers.
+
+	xirc2ps_cs=	[NET,PCMCIA]
+			Format:
+			<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/md.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/md.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/md.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/md.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,727 @@
+RAID arrays
+===========
+
+Boot time assembly of RAID arrays
+---------------------------------
+
+Tools that manage md devices can be found at
+   http://www.kernel.org/pub/linux/utils/raid/
+
+
+You can boot with your md device with the following kernel command
+lines:
+
+for old raid arrays without persistent superblocks::
+
+  md=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn
+
+for raid arrays with persistent superblocks::
+
+  md=<md device no.>,dev0,dev1,...,devn
+
+or, to assemble a partitionable array::
+
+  md=d<md device no.>,dev0,dev1,...,devn
+
+``md device no.``
++++++++++++++++++
+
+The number of the md device
+
+================= =========
+``md device no.`` device
+================= =========
+              0		md0
+	      1		md1
+	      2		md2
+	      3		md3
+	      4		md4
+================= =========
+
+``raid level``
+++++++++++++++
+
+level of the RAID array
+
+=============== =============
+``raid level``  level
+=============== =============
+-1		linear mode
+0		striped mode
+=============== =============
+
+other modes are only supported with persistent super blocks
+
+``chunk size factor``
++++++++++++++++++++++
+
+(raid-0 and raid-1 only)
+
+Set  the chunk size as 4k << n.
+
+``fault level``
++++++++++++++++
+
+Totally ignored
+
+``dev0`` to ``devn``
+++++++++++++++++++++
+
+e.g. ``/dev/hda1``, ``/dev/hdc1``, ``/dev/sda1``, ``/dev/sdb1``
+
+A possible loadlin line (Harald Hoyer <HarryH@Royal.Net>)  looks like this::
+
+	e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
+
+
+Boot time autodetection of RAID arrays
+--------------------------------------
+
+When md is compiled into the kernel (not as module), partitions of
+type 0xfd are scanned and automatically assembled into RAID arrays.
+This autodetection may be suppressed with the kernel parameter
+``raid=noautodetect``.  As of kernel 2.6.9, only drives with a type 0
+superblock can be autodetected and run at boot time.
+
+The kernel parameter ``raid=partitionable`` (or ``raid=part``) means
+that all auto-detected arrays are assembled as partitionable.
+
+Boot time assembly of degraded/dirty arrays
+-------------------------------------------
+
+If a raid5 or raid6 array is both dirty and degraded, it could have
+undetectable data corruption.  This is because the fact that it is
+``dirty`` means that the parity cannot be trusted, and the fact that it
+is degraded means that some datablocks are missing and cannot reliably
+be reconstructed (due to no parity).
+
+For this reason, md will normally refuse to start such an array.  This
+requires the sysadmin to take action to explicitly start the array
+despite possible corruption.  This is normally done with::
+
+   mdadm --assemble --force ....
+
+This option is not really available if the array has the root
+filesystem on it.  In order to support this booting from such an
+array, md supports a module parameter ``start_dirty_degraded`` which,
+when set to 1, bypassed the checks and will allows dirty degraded
+arrays to be started.
+
+So, to boot with a root filesystem of a dirty degraded raid 5 or 6, use::
+
+   md-mod.start_dirty_degraded=1
+
+
+Superblock formats
+------------------
+
+The md driver can support a variety of different superblock formats.
+Currently, it supports superblock formats ``0.90.0`` and the ``md-1`` format
+introduced in the 2.5 development series.
+
+The kernel will autodetect which format superblock is being used.
+
+Superblock format ``0`` is treated differently to others for legacy
+reasons - it is the original superblock format.
+
+
+General Rules - apply for all superblock formats
+------------------------------------------------
+
+An array is ``created`` by writing appropriate superblocks to all
+devices.
+
+It is ``assembled`` by associating each of these devices with an
+particular md virtual device.  Once it is completely assembled, it can
+be accessed.
+
+An array should be created by a user-space tool.  This will write
+superblocks to all devices.  It will usually mark the array as
+``unclean``, or with some devices missing so that the kernel md driver
+can create appropriate redundancy (copying in raid 1, parity
+calculation in raid 4/5).
+
+When an array is assembled, it is first initialized with the
+SET_ARRAY_INFO ioctl.  This contains, in particular, a major and minor
+version number.  The major version number selects which superblock
+format is to be used.  The minor number might be used to tune handling
+of the format, such as suggesting where on each device to look for the
+superblock.
+
+Then each device is added using the ADD_NEW_DISK ioctl.  This
+provides, in particular, a major and minor number identifying the
+device to add.
+
+The array is started with the RUN_ARRAY ioctl.
+
+Once started, new devices can be added.  They should have an
+appropriate superblock written to them, and then be passed in with
+ADD_NEW_DISK.
+
+Devices that have failed or are not yet active can be detached from an
+array using HOT_REMOVE_DISK.
+
+
+Specific Rules that apply to format-0 super block arrays, and arrays with no superblock (non-persistent)
+--------------------------------------------------------------------------------------------------------
+
+An array can be ``created`` by describing the array (level, chunksize
+etc) in a SET_ARRAY_INFO ioctl.  This must have ``major_version==0`` and
+``raid_disks != 0``.
+
+Then uninitialized devices can be added with ADD_NEW_DISK.  The
+structure passed to ADD_NEW_DISK must specify the state of the device
+and its role in the array.
+
+Once started with RUN_ARRAY, uninitialized spares can be added with
+HOT_ADD_DISK.
+
+
+MD devices in sysfs
+-------------------
+
+md devices appear in sysfs (``/sys``) as regular block devices,
+e.g.::
+
+   /sys/block/md0
+
+Each ``md`` device will contain a subdirectory called ``md`` which
+contains further md-specific information about the device.
+
+All md devices contain:
+
+  level
+     a text file indicating the ``raid level``. e.g. raid0, raid1,
+     raid5, linear, multipath, faulty.
+     If no raid level has been set yet (array is still being
+     assembled), the value will reflect whatever has been written
+     to it, which may be a name like the above, or may be a number
+     such as ``0``, ``5``, etc.
+
+  raid_disks
+     a text file with a simple number indicating the number of devices
+     in a fully functional array.  If this is not yet known, the file
+     will be empty.  If an array is being resized this will contain
+     the new number of devices.
+     Some raid levels allow this value to be set while the array is
+     active.  This will reconfigure the array.   Otherwise it can only
+     be set while assembling an array.
+     A change to this attribute will not be permitted if it would
+     reduce the size of the array.  To reduce the number of drives
+     in an e.g. raid5, the array size must first be reduced by
+     setting the ``array_size`` attribute.
+
+  chunk_size
+     This is the size in bytes for ``chunks`` and is only relevant to
+     raid levels that involve striping (0,4,5,6,10). The address space
+     of the array is conceptually divided into chunks and consecutive
+     chunks are striped onto neighbouring devices.
+     The size should be at least PAGE_SIZE (4k) and should be a power
+     of 2.  This can only be set while assembling an array
+
+  layout
+     The ``layout`` for the array for the particular level.  This is
+     simply a number that is interpretted differently by different
+     levels.  It can be written while assembling an array.
+
+  array_size
+     This can be used to artificially constrain the available space in
+     the array to be less than is actually available on the combined
+     devices.  Writing a number (in Kilobytes) which is less than
+     the available size will set the size.  Any reconfiguration of the
+     array (e.g. adding devices) will not cause the size to change.
+     Writing the word ``default`` will cause the effective size of the
+     array to be whatever size is actually available based on
+     ``level``, ``chunk_size`` and ``component_size``.
+
+     This can be used to reduce the size of the array before reducing
+     the number of devices in a raid4/5/6, or to support external
+     metadata formats which mandate such clipping.
+
+  reshape_position
+     This is either ``none`` or a sector number within the devices of
+     the array where ``reshape`` is up to.  If this is set, the three
+     attributes mentioned above (raid_disks, chunk_size, layout) can
+     potentially have 2 values, an old and a new value.  If these
+     values differ, reading the attribute returns::
+
+        new (old)
+
+     and writing will effect the ``new`` value, leaving the ``old``
+     unchanged.
+
+  component_size
+     For arrays with data redundancy (i.e. not raid0, linear, faulty,
+     multipath), all components must be the same size - or at least
+     there must a size that they all provide space for.  This is a key
+     part or the geometry of the array.  It is measured in sectors
+     and can be read from here.  Writing to this value may resize
+     the array if the personality supports it (raid1, raid5, raid6),
+     and if the component drives are large enough.
+
+  metadata_version
+     This indicates the format that is being used to record metadata
+     about the array.  It can be 0.90 (traditional format), 1.0, 1.1,
+     1.2 (newer format in varying locations) or ``none`` indicating that
+     the kernel isn't managing metadata at all.
+     Alternately it can be ``external:`` followed by a string which
+     is set by user-space.  This indicates that metadata is managed
+     by a user-space program.  Any device failure or other event that
+     requires a metadata update will cause array activity to be
+     suspended until the event is acknowledged.
+
+  resync_start
+     The point at which resync should start.  If no resync is needed,
+     this will be a very large number (or ``none`` since 2.6.30-rc1).  At
+     array creation it will default to 0, though starting the array as
+     ``clean`` will set it much larger.
+
+   new_dev
+     This file can be written but not read.  The value written should
+     be a block device number as major:minor.  e.g. 8:0
+     This will cause that device to be attached to the array, if it is
+     available.  It will then appear at md/dev-XXX (depending on the
+     name of the device) and further configuration is then possible.
+
+   safe_mode_delay
+     When an md array has seen no write requests for a certain period
+     of time, it will be marked as ``clean``.  When another write
+     request arrives, the array is marked as ``dirty`` before the write
+     commences.  This is known as ``safe_mode``.
+     The ``certain period`` is controlled by this file which stores the
+     period as a number of seconds.  The default is 200msec (0.200).
+     Writing a value of 0 disables safemode.
+
+   array_state
+     This file contains a single word which describes the current
+     state of the array.  In many cases, the state can be set by
+     writing the word for the desired state, however some states
+     cannot be explicitly set, and some transitions are not allowed.
+
+     Select/poll works on this file.  All changes except between
+     Active_idle and active (which can be frequent and are not
+     very interesting) are notified.  active->active_idle is
+     reported if the metadata is externally managed.
+
+     clear
+         No devices, no size, no level
+
+         Writing is equivalent to STOP_ARRAY ioctl
+
+     inactive
+         May have some settings, but array is not active
+         all IO results in error
+
+         When written, doesn't tear down array, but just stops it
+
+     suspended (not supported yet)
+         All IO requests will block. The array can be reconfigured.
+
+         Writing this, if accepted, will block until array is quiessent
+
+     readonly
+         no resync can happen.  no superblocks get written.
+
+         Write requests fail
+
+     read-auto
+         like readonly, but behaves like ``clean`` on a write request.
+
+     clean
+         no pending writes, but otherwise active.
+
+         When written to inactive array, starts without resync
+
+         If a write request arrives then
+         if metadata is known, mark ``dirty`` and switch to ``active``.
+         if not known, block and switch to write-pending
+
+         If written to an active array that has pending writes, then fails.
+     active
+         fully active: IO and resync can be happening.
+         When written to inactive array, starts with resync
+
+     write-pending
+         clean, but writes are blocked waiting for ``active`` to be written.
+
+     active-idle
+         like active, but no writes have been seen for a while (safe_mode_delay).
+
+  bitmap/location
+     This indicates where the write-intent bitmap for the array is
+     stored.
+
+     It can be one of ``none``, ``file`` or ``[+-]N``.
+     ``file`` may later be extended to ``file:/file/name``
+     ``[+-]N`` means that many sectors from the start of the metadata.
+
+     This is replicated on all devices.  For arrays with externally
+     managed metadata, the offset is from the beginning of the
+     device.
+
+  bitmap/chunksize
+     The size, in bytes, of the chunk which will be represented by a
+     single bit.  For RAID456, it is a portion of an individual
+     device. For RAID10, it is a portion of the array.  For RAID1, it
+     is both (they come to the same thing).
+
+  bitmap/time_base
+     The time, in seconds, between looking for bits in the bitmap to
+     be cleared. In the current implementation, a bit will be cleared
+     between 2 and 3 times ``time_base`` after all the covered blocks
+     are known to be in-sync.
+
+  bitmap/backlog
+     When write-mostly devices are active in a RAID1, write requests
+     to those devices proceed in the background - the filesystem (or
+     other user of the device) does not have to wait for them.
+     ``backlog`` sets a limit on the number of concurrent background
+     writes.  If there are more than this, new writes will by
+     synchronous.
+
+  bitmap/metadata
+     This can be either ``internal`` or ``external``.
+
+     ``internal``
+       is the default and means the metadata for the bitmap
+       is stored in the first 256 bytes of the allocated space and is
+       managed by the md module.
+
+     ``external``
+       means that bitmap metadata is managed externally to
+       the kernel (i.e. by some userspace program)
+
+  bitmap/can_clear
+     This is either ``true`` or ``false``.  If ``true``, then bits in the
+     bitmap will be cleared when the corresponding blocks are thought
+     to be in-sync.  If ``false``, bits will never be cleared.
+     This is automatically set to ``false`` if a write happens on a
+     degraded array, or if the array becomes degraded during a write.
+     When metadata is managed externally, it should be set to true
+     once the array becomes non-degraded, and this fact has been
+     recorded in the metadata.
+
+
+
+
+As component devices are added to an md array, they appear in the ``md``
+directory as new directories named::
+
+      dev-XXX
+
+where ``XXX`` is a name that the kernel knows for the device, e.g. hdb1.
+Each directory contains:
+
+      block
+        a symlink to the block device in /sys/block, e.g.::
+
+	     /sys/block/md0/md/dev-hdb1/block -> ../../../../block/hdb/hdb1
+
+      super
+        A file containing an image of the superblock read from, or
+        written to, that device.
+
+      state
+	A file recording the current state of the device in the array
+	which can be a comma separated list of:
+
+	      faulty
+			device has been kicked from active use due to
+			a detected fault, or it has unacknowledged bad
+			blocks
+
+	      in_sync
+			device is a fully in-sync member of the array
+
+	      writemostly
+			device will only be subject to read
+			requests if there are no other options.
+
+			This applies only to raid1 arrays.
+
+	      blocked
+			device has failed, and the failure hasn't been
+			acknowledged yet by the metadata handler.
+
+			Writes that would write to this device if
+			it were not faulty are blocked.
+
+	      spare
+			device is working, but not a full member.
+
+			This includes spares that are in the process
+			of being recovered to
+
+	      write_error
+			device has ever seen a write error.
+
+	      want_replacement
+			device is (mostly) working but probably
+			should be replaced, either due to errors or
+			due to user request.
+
+	      replacement
+			device is a replacement for another active
+			device with same raid_disk.
+
+
+	This list may grow in future.
+
+	This can be written to.
+
+	Writing ``faulty``  simulates a failure on the device.
+
+	Writing ``remove`` removes the device from the array.
+
+	Writing ``writemostly`` sets the writemostly flag.
+
+	Writing ``-writemostly`` clears the writemostly flag.
+
+	Writing ``blocked`` sets the ``blocked`` flag.
+
+	Writing ``-blocked`` clears the ``blocked`` flags and allows writes
+	to complete and possibly simulates an error.
+
+	Writing ``in_sync`` sets the in_sync flag.
+
+	Writing ``write_error`` sets writeerrorseen flag.
+
+	Writing ``-write_error`` clears writeerrorseen flag.
+
+	Writing ``want_replacement`` is allowed at any time except to a
+	replacement device or a spare.  It sets the flag.
+
+	Writing ``-want_replacement`` is allowed at any time.  It clears
+	the flag.
+
+	Writing ``replacement`` or ``-replacement`` is only allowed before
+	starting the array.  It sets or clears the flag.
+
+
+	This file responds to select/poll. Any change to ``faulty``
+	or ``blocked`` causes an event.
+
+      errors
+	An approximate count of read errors that have been detected on
+	this device but have not caused the device to be evicted from
+	the array (either because they were corrected or because they
+	happened while the array was read-only).  When using version-1
+	metadata, this value persists across restarts of the array.
+
+	This value can be written while assembling an array thus
+	providing an ongoing count for arrays with metadata managed by
+	userspace.
+
+      slot
+        This gives the role that the device has in the array.  It will
+	either be ``none`` if the device is not active in the array
+        (i.e. is a spare or has failed) or an integer less than the
+	``raid_disks`` number for the array indicating which position
+	it currently fills.  This can only be set while assembling an
+	array.  A device for which this is set is assumed to be working.
+
+      offset
+        This gives the location in the device (in sectors from the
+        start) where data from the array will be stored.  Any part of
+        the device before this offset is not touched, unless it is
+        used for storing metadata (Formats 1.1 and 1.2).
+
+      size
+        The amount of the device, after the offset, that can be used
+        for storage of data.  This will normally be the same as the
+	component_size.  This can be written while assembling an
+        array.  If a value less than the current component_size is
+        written, it will be rejected.
+
+      recovery_start
+        When the device is not ``in_sync``, this records the number of
+	sectors from the start of the device which are known to be
+	correct.  This is normally zero, but during a recovery
+	operation it will steadily increase, and if the recovery is
+	interrupted, restoring this value can cause recovery to
+	avoid repeating the earlier blocks.  With v1.x metadata, this
+	value is saved and restored automatically.
+
+	This can be set whenever the device is not an active member of
+	the array, either before the array is activated, or before
+	the ``slot`` is set.
+
+	Setting this to ``none`` is equivalent to setting ``in_sync``.
+	Setting to any other value also clears the ``in_sync`` flag.
+
+      bad_blocks
+	This gives the list of all known bad blocks in the form of
+	start address and length (in sectors respectively). If output
+	is too big to fit in a page, it will be truncated. Writing
+	``sector length`` to this file adds new acknowledged (i.e.
+	recorded to disk safely) bad blocks.
+
+      unacknowledged_bad_blocks
+	This gives the list of known-but-not-yet-saved-to-disk bad
+	blocks in the same form of ``bad_blocks``. If output is too big
+	to fit in a page, it will be truncated. Writing to this file
+	adds bad blocks without acknowledging them. This is largely
+	for testing.
+
+
+
+An active md device will also contain an entry for each active device
+in the array.  These are named::
+
+    rdNN
+
+where ``NN`` is the position in the array, starting from 0.
+So for a 3 drive array there will be rd0, rd1, rd2.
+These are symbolic links to the appropriate ``dev-XXX`` entry.
+Thus, for example::
+
+       cat /sys/block/md*/md/rd*/state
+
+will show ``in_sync`` on every line.
+
+
+
+Active md devices for levels that support data redundancy (1,4,5,6,10)
+also have
+
+   sync_action
+     a text file that can be used to monitor and control the rebuild
+     process.  It contains one word which can be one of:
+
+       resync
+		redundancy is being recalculated after unclean
+                shutdown or creation
+
+       recover
+		a hot spare is being built to replace a
+		failed/missing device
+
+       idle
+		nothing is happening
+       check
+		A full check of redundancy was requested and is
+                happening.  This reads all blocks and checks
+                them. A repair may also happen for some raid
+                levels.
+
+       repair
+		A full check and repair is happening.  This is
+		similar to ``resync``, but was requested by the
+                user, and the write-intent bitmap is NOT used to
+		optimise the process.
+
+      This file is writable, and each of the strings that could be
+      read are meaningful for writing.
+
+	``idle`` will stop an active resync/recovery etc.  There is no
+	guarantee that another resync/recovery may not be automatically
+	started again, though some event will be needed to trigger
+	this.
+
+	``resync`` or ``recovery`` can be used to restart the
+        corresponding operation if it was stopped with ``idle``.
+
+	``check`` and ``repair`` will start the appropriate process
+	providing the current state is ``idle``.
+
+      This file responds to select/poll.  Any important change in the value
+      triggers a poll event.  Sometimes the value will briefly be
+      ``recover`` if a recovery seems to be needed, but cannot be
+      achieved. In that case, the transition to ``recover`` isn't
+      notified, but the transition away is.
+
+   degraded
+      This contains a count of the number of devices by which the
+      arrays is degraded.  So an optimal array will show ``0``.  A
+      single failed/missing drive will show ``1``, etc.
+
+      This file responds to select/poll, any increase or decrease
+      in the count of missing devices will trigger an event.
+
+   mismatch_count
+      When performing ``check`` and ``repair``, and possibly when
+      performing ``resync``, md will count the number of errors that are
+      found.  The count in ``mismatch_cnt`` is the number of sectors
+      that were re-written, or (for ``check``) would have been
+      re-written.  As most raid levels work in units of pages rather
+      than sectors, this may be larger than the number of actual errors
+      by a factor of the number of sectors in a page.
+
+   bitmap_set_bits
+      If the array has a write-intent bitmap, then writing to this
+      attribute can set bits in the bitmap, indicating that a resync
+      would need to check the corresponding blocks. Either individual
+      numbers or start-end pairs can be written.  Multiple numbers
+      can be separated by a space.
+
+      Note that the numbers are ``bit`` numbers, not ``block`` numbers.
+      They should be scaled by the bitmap_chunksize.
+
+   sync_speed_min, sync_speed_max
+     This are similar to ``/proc/sys/dev/raid/speed_limit_{min,max}``
+     however they only apply to the particular array.
+
+     If no value has been written to these, or if the word ``system``
+     is written, then the system-wide value is used.  If a value,
+     in kibibytes-per-second is written, then it is used.
+
+     When the files are read, they show the currently active value
+     followed by ``(local)`` or ``(system)`` depending on whether it is
+     a locally set or system-wide value.
+
+   sync_completed
+     This shows the number of sectors that have been completed of
+     whatever the current sync_action is, followed by the number of
+     sectors in total that could need to be processed.  The two
+     numbers are separated by a ``/``  thus effectively showing one
+     value, a fraction of the process that is complete.
+
+     A ``select`` on this attribute will return when resync completes,
+     when it reaches the current sync_max (below) and possibly at
+     other times.
+
+   sync_speed
+     This shows the current actual speed, in K/sec, of the current
+     sync_action.  It is averaged over the last 30 seconds.
+
+   suspend_lo, suspend_hi
+     The two values, given as numbers of sectors, indicate a range
+     within the array where IO will be blocked.  This is currently
+     only supported for raid4/5/6.
+
+   sync_min, sync_max
+     The two values, given as numbers of sectors, indicate a range
+     within the array where ``check``/``repair`` will operate. Must be
+     a multiple of chunk_size. When it reaches ``sync_max`` it will
+     pause, rather than complete.
+     You can use ``select`` or ``poll`` on ``sync_completed`` to wait for
+     that number to reach sync_max.  Then you can either increase
+     ``sync_max``, or can write ``idle`` to ``sync_action``.
+
+     The value of ``max`` for ``sync_max`` effectively disables the limit.
+     When a resync is active, the value can only ever be increased,
+     never decreased.
+     The value of ``0`` is the minimum for ``sync_min``.
+
+
+
+Each active md device may also have attributes specific to the
+personality module that manages it.
+These are specific to the implementation of the module and could
+change substantially if the implementation changes.
+
+These currently include:
+
+  stripe_cache_size  (currently raid5 only)
+      number of entries in the stripe cache.  This is writable, but
+      there are upper and lower limits (32768, 17).  Default is 256.
+
+  strip_cache_active (currently raid5 only)
+      number of active entries in the stripe cache
+
+  preread_bypass_threshold (currently raid5 only)
+      number of times a stripe requiring preread will be bypassed by
+      a stripe that does not require preread.  For fairness defaults
+      to 1.  Setting this to 0 disables bypass accounting and
+      requires preread stripes to wait until all full-width stripe-
+      writes are complete.  Valid values are 0 to stripe_cache_size.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/module-signing.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/module-signing.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/module-signing.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/module-signing.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,285 @@
+Kernel module signing facility
+------------------------------
+
+.. CONTENTS
+..
+.. - Overview.
+.. - Configuring module signing.
+.. - Generating signing keys.
+.. - Public keys in the kernel.
+.. - Manually signing modules.
+.. - Signed modules and stripping.
+.. - Loading signed modules.
+.. - Non-valid signatures and unsigned modules.
+.. - Administering/protecting the private key.
+
+
+========
+Overview
+========
+
+The kernel module signing facility cryptographically signs modules during
+installation and then checks the signature upon loading the module.  This
+allows increased kernel security by disallowing the loading of unsigned modules
+or modules signed with an invalid key.  Module signing increases security by
+making it harder to load a malicious module into the kernel.  The module
+signature checking is done by the kernel so that it is not necessary to have
+trusted userspace bits.
+
+This facility uses X.509 ITU-T standard certificates to encode the public keys
+involved.  The signatures are not themselves encoded in any industrial standard
+type.  The facility currently only supports the RSA public key encryption
+standard (though it is pluggable and permits others to be used).  The possible
+hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
+SHA-512 (the algorithm is selected by data in the signature).
+
+
+==========================
+Configuring module signing
+==========================
+
+The module signing facility is enabled by going to the
+:menuselection:`Enable Loadable Module Support` section of
+the kernel configuration and turning on::
+
+	CONFIG_MODULE_SIG	"Module signature verification"
+
+This has a number of options available:
+
+ (1) :menuselection:`Require modules to be validly signed`
+     (``CONFIG_MODULE_SIG_FORCE``)
+
+     This specifies how the kernel should deal with a module that has a
+     signature for which the key is not known or a module that is unsigned.
+
+     If this is off (ie. "permissive"), then modules for which the key is not
+     available and modules that are unsigned are permitted, but the kernel will
+     be marked as being tainted, and the concerned modules will be marked as
+     tainted, shown with the character 'E'.
+
+     If this is on (ie. "restrictive"), only modules that have a valid
+     signature that can be verified by a public key in the kernel's possession
+     will be loaded.  All other modules will generate an error.
+
+     Irrespective of the setting here, if the module has a signature block that
+     cannot be parsed, it will be rejected out of hand.
+
+
+ (2) :menuselection:`Automatically sign all modules`
+     (``CONFIG_MODULE_SIG_ALL``)
+
+     If this is on then modules will be automatically signed during the
+     modules_install phase of a build.  If this is off, then the modules must
+     be signed manually using::
+
+	scripts/sign-file
+
+
+ (3) :menuselection:`Which hash algorithm should modules be signed with?`
+
+     This presents a choice of which hash algorithm the installation phase will
+     sign the modules with:
+
+        =============================== ==========================================
+	``CONFIG_MODULE_SIG_SHA1``	:menuselection:`Sign modules with SHA-1`
+	``CONFIG_MODULE_SIG_SHA224``	:menuselection:`Sign modules with SHA-224`
+	``CONFIG_MODULE_SIG_SHA256``	:menuselection:`Sign modules with SHA-256`
+	``CONFIG_MODULE_SIG_SHA384``	:menuselection:`Sign modules with SHA-384`
+	``CONFIG_MODULE_SIG_SHA512``	:menuselection:`Sign modules with SHA-512`
+        =============================== ==========================================
+
+     The algorithm selected here will also be built into the kernel (rather
+     than being a module) so that modules signed with that algorithm can have
+     their signatures checked without causing a dependency loop.
+
+
+ (4) :menuselection:`File name or PKCS#11 URI of module signing key`
+     (``CONFIG_MODULE_SIG_KEY``)
+
+     Setting this option to something other than its default of
+     ``certs/signing_key.pem`` will disable the autogeneration of signing keys
+     and allow the kernel modules to be signed with a key of your choosing.
+     The string provided should identify a file containing both a private key
+     and its corresponding X.509 certificate in PEM form, or — on systems where
+     the OpenSSL ENGINE_pkcs11 is functional — a PKCS#11 URI as defined by
+     RFC7512. In the latter case, the PKCS#11 URI should reference both a
+     certificate and a private key.
+
+     If the PEM file containing the private key is encrypted, or if the
+     PKCS#11 token requries a PIN, this can be provided at build time by
+     means of the ``KBUILD_SIGN_PIN`` variable.
+
+
+ (5) :menuselection:`Additional X.509 keys for default system keyring`
+     (``CONFIG_SYSTEM_TRUSTED_KEYS``)
+
+     This option can be set to the filename of a PEM-encoded file containing
+     additional certificates which will be included in the system keyring by
+     default.
+
+Note that enabling module signing adds a dependency on the OpenSSL devel
+packages to the kernel build processes for the tool that does the signing.
+
+
+=======================
+Generating signing keys
+=======================
+
+Cryptographic keypairs are required to generate and check signatures.  A
+private key is used to generate a signature and the corresponding public key is
+used to check it.  The private key is only needed during the build, after which
+it can be deleted or stored securely.  The public key gets built into the
+kernel so that it can be used to check the signatures as the modules are
+loaded.
+
+Under normal conditions, when ``CONFIG_MODULE_SIG_KEY`` is unchanged from its
+default, the kernel build will automatically generate a new keypair using
+openssl if one does not exist in the file::
+
+	certs/signing_key.pem
+
+during the building of vmlinux (the public part of the key needs to be built
+into vmlinux) using parameters in the::
+
+	certs/x509.genkey
+
+file (which is also generated if it does not already exist).
+
+It is strongly recommended that you provide your own x509.genkey file.
+
+Most notably, in the x509.genkey file, the req_distinguished_name section
+should be altered from the default::
+
+	[ req_distinguished_name ]
+	#O = Unspecified company
+	CN = Build time autogenerated kernel key
+	#emailAddress = unspecified.user@unspecified.company
+
+The generated RSA key size can also be set with::
+
+	[ req ]
+	default_bits = 4096
+
+
+It is also possible to manually generate the key private/public files using the
+x509.genkey key generation configuration file in the root node of the Linux
+kernel sources tree and the openssl command.  The following is an example to
+generate the public/private key files::
+
+	openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
+	   -config x509.genkey -outform PEM -out kernel_key.pem \
+	   -keyout kernel_key.pem
+
+The full pathname for the resulting kernel_key.pem file can then be specified
+in the ``CONFIG_MODULE_SIG_KEY`` option, and the certificate and key therein will
+be used instead of an autogenerated keypair.
+
+
+=========================
+Public keys in the kernel
+=========================
+
+The kernel contains a ring of public keys that can be viewed by root.  They're
+in a keyring called ".system_keyring" that can be seen by::
+
+	[root@deneb ~]# cat /proc/keys
+	...
+	223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
+	302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
+	...
+
+Beyond the public key generated specifically for module signing, additional
+trusted certificates can be provided in a PEM-encoded file referenced by the
+``CONFIG_SYSTEM_TRUSTED_KEYS`` configuration option.
+
+Further, the architecture code may take public keys from a hardware store and
+add those in also (e.g. from the UEFI key database).
+
+Finally, it is possible to add additional public keys by doing::
+
+	keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
+
+e.g.::
+
+	keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
+
+Note, however, that the kernel will only permit keys to be added to
+``.system_keyring _if_`` the new key's X.509 wrapper is validly signed by a key
+that is already resident in the .system_keyring at the time the key was added.
+
+
+========================
+Manually signing modules
+========================
+
+To manually sign a module, use the scripts/sign-file tool available in
+the Linux kernel source tree.  The script requires 4 arguments:
+
+	1.  The hash algorithm (e.g., sha256)
+	2.  The private key filename or PKCS#11 URI
+	3.  The public key filename
+	4.  The kernel module to be signed
+
+The following is an example to sign a kernel module::
+
+	scripts/sign-file sha512 kernel-signkey.priv \
+		kernel-signkey.x509 module.ko
+
+The hash algorithm used does not have to match the one configured, but if it
+doesn't, you should make sure that hash algorithm is either built into the
+kernel or can be loaded without requiring itself.
+
+If the private key requires a passphrase or PIN, it can be provided in the
+$KBUILD_SIGN_PIN environment variable.
+
+
+============================
+Signed modules and stripping
+============================
+
+A signed module has a digital signature simply appended at the end.  The string
+``~Module signature appended~.`` at the end of the module's file confirms that a
+signature is present but it does not confirm that the signature is valid!
+
+Signed modules are BRITTLE as the signature is outside of the defined ELF
+container.  Thus they MAY NOT be stripped once the signature is computed and
+attached.  Note the entire module is the signed payload, including any and all
+debug information present at the time of signing.
+
+
+======================
+Loading signed modules
+======================
+
+Modules are loaded with insmod, modprobe, ``init_module()`` or
+``finit_module()``, exactly as for unsigned modules as no processing is
+done in userspace.  The signature checking is all done within the kernel.
+
+
+=========================================
+Non-valid signatures and unsigned modules
+=========================================
+
+If ``CONFIG_MODULE_SIG_FORCE`` is enabled or module.sig_enforce=1 is supplied on
+the kernel command line, the kernel will only load validly signed modules
+for which it has a public key.   Otherwise, it will also load modules that are
+unsigned.   Any module for which the kernel has a key, but which proves to have
+a signature mismatch will not be permitted to load.
+
+Any module that has an unparseable signature will be rejected.
+
+
+=========================================
+Administering/protecting the private key
+=========================================
+
+Since the private key is used to sign modules, viruses and malware could use
+the private key to sign modules and compromise the operating system.  The
+private key must be either destroyed or moved to a secure location and not kept
+in the root node of the kernel source tree.
+
+If you use the same private key to sign modules for multiple kernel
+configurations, you must ensure that the module version information is
+sufficient to prevent loading a module into a different kernel.  Either
+set ``CONFIG_MODVERSIONS=y`` or ensure that each configuration has a different
+kernel release string by changing ``EXTRAVERSION`` or ``CONFIG_LOCALVERSION``.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/mono.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/mono.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/mono.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/mono.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,70 @@
+Mono(tm) Binary Kernel Support for Linux
+-----------------------------------------
+
+To configure Linux to automatically execute Mono-based .NET binaries
+(in the form of .exe files) without the need to use the mono CLR
+wrapper, you can use the BINFMT_MISC kernel support.
+
+This will allow you to execute Mono-based .NET binaries just like any
+other program after you have done the following:
+
+1) You MUST FIRST install the Mono CLR support, either by downloading
+   a binary package, a source tarball or by installing from CVS. Binary
+   packages for several distributions can be found at:
+
+	http://go-mono.com/download.html
+
+   Instructions for compiling Mono can be found at:
+
+	http://www.go-mono.com/compiling.html
+
+   Once the Mono CLR support has been installed, just check that
+   ``/usr/bin/mono`` (which could be located elsewhere, for example
+   ``/usr/local/bin/mono``) is working.
+
+2) You have to compile BINFMT_MISC either as a module or into
+   the kernel (``CONFIG_BINFMT_MISC``) and set it up properly.
+   If you choose to compile it as a module, you will have
+   to insert it manually with modprobe/insmod, as kmod
+   cannot be easily supported with binfmt_misc.
+   Read the file ``binfmt_misc.txt`` in this directory to know
+   more about the configuration process.
+
+3) Add the following entries to ``/etc/rc.local`` or similar script
+   to be run at system startup:
+
+   .. code-block:: sh
+
+    # Insert BINFMT_MISC module into the kernel
+    if [ ! -e /proc/sys/fs/binfmt_misc/register ]; then
+        /sbin/modprobe binfmt_misc
+	# Some distributions, like Fedora Core, perform
+	# the following command automatically when the
+	# binfmt_misc module is loaded into the kernel
+	# or during normal boot up (systemd-based systems).
+	# Thus, it is possible that the following line
+	# is not needed at all.
+	mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
+    fi
+
+    # Register support for .NET CLR binaries
+    if [ -e /proc/sys/fs/binfmt_misc/register ]; then
+	# Replace /usr/bin/mono with the correct pathname to
+	# the Mono CLR runtime (usually /usr/local/bin/mono
+	# when compiling from sources or CVS).
+        echo ':CLR:M::MZ::/usr/bin/mono:' > /proc/sys/fs/binfmt_misc/register
+    else
+        echo "No binfmt_misc support"
+        exit 1
+    fi
+
+4) Check that ``.exe`` binaries can be ran without the need of a
+   wrapper script, simply by launching the ``.exe`` file directly
+   from a command prompt, for example::
+
+	/usr/bin/xsd.exe
+
+   .. note::
+
+      If this fails with a permission denied error, check
+      that the ``.exe`` file has execute permissions.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/parport.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/parport.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/parport.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/parport.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,286 @@
+Parport
++++++++
+
+The ``parport`` code provides parallel-port support under Linux.  This
+includes the ability to share one port between multiple device
+drivers.
+
+You can pass parameters to the ``parport`` code to override its automatic
+detection of your hardware.  This is particularly useful if you want
+to use IRQs, since in general these can't be autoprobed successfully.
+By default IRQs are not used even if they **can** be probed.  This is
+because there are a lot of people using the same IRQ for their
+parallel port and a sound card or network card.
+
+The ``parport`` code is split into two parts: generic (which deals with
+port-sharing) and architecture-dependent (which deals with actually
+using the port).
+
+
+Parport as modules
+==================
+
+If you load the `parport`` code as a module, say::
+
+	# insmod parport
+
+to load the generic ``parport`` code.  You then must load the
+architecture-dependent code with (for example)::
+
+	# insmod parport_pc io=0x3bc,0x378,0x278 irq=none,7,auto
+
+to tell the ``parport`` code that you want three PC-style ports, one at
+0x3bc with no IRQ, one at 0x378 using IRQ 7, and one at 0x278 with an
+auto-detected IRQ.  Currently, PC-style (``parport_pc``), Sun ``bpp``,
+Amiga, Atari, and MFC3 hardware is supported.
+
+PCI parallel I/O card support comes from ``parport_pc``.  Base I/O
+addresses should not be specified for supported PCI cards since they
+are automatically detected.
+
+
+modprobe
+--------
+
+If you use modprobe , you will find it useful to add lines as below to a
+configuration file in /etc/modprobe.d/ directory::
+
+	alias parport_lowlevel parport_pc
+	options parport_pc io=0x378,0x278 irq=7,auto
+
+modprobe will load ``parport_pc`` (with the options ``io=0x378,0x278 irq=7,auto``)
+whenever a parallel port device driver (such as ``lp``) is loaded.
+
+Note that these are example lines only!  You shouldn't in general need
+to specify any options to ``parport_pc`` in order to be able to use a
+parallel port.
+
+
+Parport probe [optional]
+------------------------
+
+In 2.2 kernels there was a module called ``parport_probe``, which was used
+for collecting IEEE 1284 device ID information.  This has now been
+enhanced and now lives with the IEEE 1284 support.  When a parallel
+port is detected, the devices that are connected to it are analysed,
+and information is logged like this::
+
+	parport0: Printer, BJC-210 (Canon)
+
+The probe information is available from files in ``/proc/sys/dev/parport/``.
+
+
+Parport linked into the kernel statically
+=========================================
+
+If you compile the ``parport`` code into the kernel, then you can use
+kernel boot parameters to get the same effect.  Add something like the
+following to your LILO command line::
+
+	parport=0x3bc parport=0x378,7 parport=0x278,auto,nofifo
+
+You can have many ``parport=...`` statements, one for each port you want
+to add.  Adding ``parport=0`` to the kernel command-line will disable
+parport support entirely.  Adding ``parport=auto`` to the kernel
+command-line will make ``parport`` use any IRQ lines or DMA channels that
+it auto-detects.
+
+
+Files in /proc
+==============
+
+If you have configured the ``/proc`` filesystem into your kernel, you will
+see a new directory entry: ``/proc/sys/dev/parport``.  In there will be a
+directory entry for each parallel port for which parport is
+configured.  In each of those directories are a collection of files
+describing that parallel port.
+
+The ``/proc/sys/dev/parport`` directory tree looks like::
+
+	parport
+	|-- default
+	|   |-- spintime
+	|   `-- timeslice
+	|-- parport0
+	|   |-- autoprobe
+	|   |-- autoprobe0
+	|   |-- autoprobe1
+	|   |-- autoprobe2
+	|   |-- autoprobe3
+	|   |-- devices
+	|   |   |-- active
+	|   |   `-- lp
+	|   |       `-- timeslice
+	|   |-- base-addr
+	|   |-- irq
+	|   |-- dma
+	|   |-- modes
+	|   `-- spintime
+	`-- parport1
+	|-- autoprobe
+	|-- autoprobe0
+	|-- autoprobe1
+	|-- autoprobe2
+	|-- autoprobe3
+	|-- devices
+	|   |-- active
+	|   `-- ppa
+	|       `-- timeslice
+	|-- base-addr
+	|-- irq
+	|-- dma
+	|-- modes
+	`-- spintime
+
+.. tabularcolumns:: |p{4.0cm}|p{13.5cm}|
+
+=======================	=======================================================
+File			Contents
+=======================	=======================================================
+``devices/active``	A list of the device drivers using that port.  A "+"
+			will appear by the name of the device currently using
+			the port (it might not appear against any).  The
+			string "none" means that there are no device drivers
+			using that port.
+
+``base-addr``		Parallel port's base address, or addresses if the port
+			has more than one in which case they are separated
+			with tabs.  These values might not have any sensible
+			meaning for some ports.
+
+``irq``			Parallel port's IRQ, or -1 if none is being used.
+
+``dma``			Parallel port's DMA channel, or -1 if none is being
+			used.
+
+``modes``		Parallel port's hardware modes, comma-separated,
+			meaning:
+
+			- PCSPP
+				PC-style SPP registers are available.
+
+			- TRISTATE
+				Port is bidirectional.
+
+			- COMPAT
+				Hardware acceleration for printers is
+				available and will be used.
+
+			- EPP
+				Hardware acceleration for EPP protocol
+				is available and will be used.
+
+			- ECP
+				Hardware acceleration for ECP protocol
+				is available and will be used.
+
+			- DMA
+				DMA is available and will be used.
+
+			Note that the current implementation will only take
+			advantage of COMPAT and ECP modes if it has an IRQ
+			line to use.
+
+``autoprobe``		Any IEEE-1284 device ID information that has been
+			acquired from the (non-IEEE 1284.3) device.
+
+``autoprobe[0-3]``	IEEE 1284 device ID information retrieved from
+			daisy-chain devices that conform to IEEE 1284.3.
+
+``spintime``		The number of microseconds to busy-loop while waiting
+			for the peripheral to respond.  You might find that
+			adjusting this improves performance, depending on your
+			peripherals.  This is a port-wide setting, i.e. it
+			applies to all devices on a particular port.
+
+``timeslice``		The number of milliseconds that a device driver is
+			allowed to keep a port claimed for.  This is advisory,
+			and driver can ignore it if it must.
+
+``default/*``		The defaults for spintime and timeslice. When a new
+			port is	registered, it picks up the default spintime.
+			When a new device is registered, it picks up the
+			default timeslice.
+=======================	=======================================================
+
+Device drivers
+==============
+
+Once the parport code is initialised, you can attach device drivers to
+specific ports.  Normally this happens automatically; if the lp driver
+is loaded it will create one lp device for each port found.  You can
+override this, though, by using parameters either when you load the lp
+driver::
+
+	# insmod lp parport=0,2
+
+or on the LILO command line::
+
+	lp=parport0 lp=parport2
+
+Both the above examples would inform lp that you want ``/dev/lp0`` to be
+the first parallel port, and /dev/lp1 to be the **third** parallel port,
+with no lp device associated with the second port (parport1).  Note
+that this is different to the way older kernels worked; there used to
+be a static association between the I/O port address and the device
+name, so ``/dev/lp0`` was always the port at 0x3bc.  This is no longer the
+case - if you only have one port, it will default to being ``/dev/lp0``,
+regardless of base address.
+
+Also:
+
+ * If you selected the IEEE 1284 support at compile time, you can say
+   ``lp=auto`` on the kernel command line, and lp will create devices
+   only for those ports that seem to have printers attached.
+
+ * If you give PLIP the ``timid`` parameter, either with ``plip=timid`` on
+   the command line, or with ``insmod plip timid=1`` when using modules,
+   it will avoid any ports that seem to be in use by other devices.
+
+ * IRQ autoprobing works only for a few port types at the moment.
+
+Reporting printer problems with parport
+=======================================
+
+If you are having problems printing, please go through these steps to
+try to narrow down where the problem area is.
+
+When reporting problems with parport, really you need to give all of
+the messages that ``parport_pc`` spits out when it initialises.  There are
+several code paths:
+
+- polling
+- interrupt-driven, protocol in software
+- interrupt-driven, protocol in hardware using PIO
+- interrupt-driven, protocol in hardware using DMA
+
+The kernel messages that ``parport_pc`` logs give an indication of which
+code path is being used. (They could be a lot better actually..)
+
+For normal printer protocol, having IEEE 1284 modes enabled or not
+should not make a difference.
+
+To turn off the 'protocol in hardware' code paths, disable
+``CONFIG_PARPORT_PC_FIFO``.  Note that when they are enabled they are not
+necessarily **used**; it depends on whether the hardware is available,
+enabled by the BIOS, and detected by the driver.
+
+So, to start with, disable ``CONFIG_PARPORT_PC_FIFO``, and load ``parport_pc``
+with ``irq=none``. See if printing works then.  It really should,
+because this is the simplest code path.
+
+If that works fine, try with ``io=0x378 irq=7`` (adjust for your
+hardware), to make it use interrupt-driven in-software protocol.
+
+If **that** works fine, then one of the hardware modes isn't working
+right.  Enable ``CONFIG_FIFO`` (no, it isn't a module option,
+and yes, it should be), set the port to ECP mode in the BIOS and note
+the DMA channel, and try with::
+
+    io=0x378 irq=7 dma=none (for PIO)
+    io=0x378 irq=7 dma=3 (for DMA)
+
+----------
+
+philb@gnu.org
+tim@cyberelk.net
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/ramoops.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/ramoops.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/ramoops.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/ramoops.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,156 @@
+Ramoops oops/panic logger
+=========================
+
+Sergiu Iordache <sergiu@chromium.org>
+
+Updated: 17 November 2011
+
+Introduction
+------------
+
+Ramoops is an oops/panic logger that writes its logs to RAM before the system
+crashes. It works by logging oopses and panics in a circular buffer. Ramoops
+needs a system with persistent RAM so that the content of that area can
+survive after a restart.
+
+Ramoops concepts
+----------------
+
+Ramoops uses a predefined memory area to store the dump. The start and size
+and type of the memory area are set using three variables:
+
+  * ``mem_address`` for the start
+  * ``mem_size`` for the size. The memory size will be rounded down to a
+    power of two.
+  * ``mem_type`` to specifiy if the memory type (default is pgprot_writecombine).
+
+Typically the default value of ``mem_type=0`` should be used as that sets the pstore
+mapping to pgprot_writecombine. Setting ``mem_type=1`` attempts to use
+``pgprot_noncached``, which only works on some platforms. This is because pstore
+depends on atomic operations. At least on ARM, pgprot_noncached causes the
+memory to be mapped strongly ordered, and atomic operations on strongly ordered
+memory are implementation defined, and won't work on many ARMs such as omaps.
+
+The memory area is divided into ``record_size`` chunks (also rounded down to
+power of two) and each oops/panic writes a ``record_size`` chunk of
+information.
+
+Dumping both oopses and panics can be done by setting 1 in the ``dump_oops``
+variable while setting 0 in that variable dumps only the panics.
+
+The module uses a counter to record multiple dumps but the counter gets reset
+on restart (i.e. new dumps after the restart will overwrite old ones).
+
+Ramoops also supports software ECC protection of persistent memory regions.
+This might be useful when a hardware reset was used to bring the machine back
+to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat
+corrupt, but usually it is restorable.
+
+Setting the parameters
+----------------------
+
+Setting the ramoops parameters can be done in several different manners:
+
+ A. Use the module parameters (which have the names of the variables described
+ as before). For quick debugging, you can also reserve parts of memory during
+ boot and then use the reserved memory for ramoops. For example, assuming a
+ machine with > 128 MB of memory, the following kernel command line will tell
+ the kernel to use only the first 128 MB of memory, and place ECC-protected
+ ramoops region at 128 MB boundary::
+
+	mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1
+
+ B. Use Device Tree bindings, as described in
+ ``Documentation/device-tree/bindings/reserved-memory/admin-guide/ramoops.rst``.
+ For example::
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ramoops@8f000000 {
+			compatible = "ramoops";
+			reg = <0 0x8f000000 0 0x100000>;
+			record-size = <0x4000>;
+			console-size = <0x4000>;
+		};
+	};
+
+ C. Use a platform device and set the platform data. The parameters can then
+ be set through that platform data. An example of doing that is:
+
+ .. code-block:: c
+
+  #include <linux/pstore_ram.h>
+  [...]
+
+  static struct ramoops_platform_data ramoops_data = {
+        .mem_size               = <...>,
+        .mem_address            = <...>,
+        .mem_type               = <...>,
+        .record_size            = <...>,
+        .dump_oops              = <...>,
+        .ecc                    = <...>,
+  };
+
+  static struct platform_device ramoops_dev = {
+        .name = "ramoops",
+        .dev = {
+                .platform_data = &ramoops_data,
+        },
+  };
+
+  [... inside a function ...]
+  int ret;
+
+  ret = platform_device_register(&ramoops_dev);
+  if (ret) {
+	printk(KERN_ERR "unable to register platform device\n");
+	return ret;
+  }
+
+You can specify either RAM memory or peripheral devices' memory. However, when
+specifying RAM, be sure to reserve the memory by issuing memblock_reserve()
+very early in the architecture code, e.g.::
+
+	#include <linux/memblock.h>
+
+	memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);
+
+Dump format
+-----------
+
+The data dump begins with a header, currently defined as ``====`` followed by a
+timestamp and a new line. The dump then continues with the actual data.
+
+Reading the data
+----------------
+
+The dump data can be read from the pstore filesystem. The format for these
+files is ``dmesg-ramoops-N``, where N is the record number in memory. To delete
+a stored record from RAM, simply unlink the respective pstore file.
+
+Persistent function tracing
+---------------------------
+
+Persistent function tracing might be useful for debugging software or hardware
+related hangs. The functions call chain log is stored in a ``ftrace-ramoops``
+file. Here is an example of usage::
+
+ # mount -t debugfs debugfs /sys/kernel/debug/
+ # echo 1 > /sys/kernel/debug/pstore/record_ftrace
+ # reboot -f
+ [...]
+ # mount -t pstore pstore /mnt/
+ # tail /mnt/ftrace-ramoops
+ 0 ffffffff8101ea64  ffffffff8101bcda  native_apic_mem_read <- disconnect_bsp_APIC+0x6a/0xc0
+ 0 ffffffff8101ea44  ffffffff8101bcf6  native_apic_mem_write <- disconnect_bsp_APIC+0x86/0xc0
+ 0 ffffffff81020084  ffffffff8101a4b5  hpet_disable <- native_machine_shutdown+0x75/0x90
+ 0 ffffffff81005f94  ffffffff8101a4bb  iommu_shutdown_noop <- native_machine_shutdown+0x7b/0x90
+ 0 ffffffff8101a6a1  ffffffff8101a437  native_machine_emergency_restart <- native_machine_restart+0x37/0x40
+ 0 ffffffff811f9876  ffffffff8101a73a  acpi_reboot <- native_machine_emergency_restart+0xaa/0x1e0
+ 0 ffffffff8101a514  ffffffff8101a772  mach_reboot_fixups <- native_machine_emergency_restart+0xe2/0x1e0
+ 0 ffffffff811d9c54  ffffffff8101a7a0  __const_udelay <- native_machine_emergency_restart+0x110/0x1e0
+ 0 ffffffff811d9c34  ffffffff811d9c80  __delay <- __const_udelay+0x30/0x40
+ 0 ffffffff811d9d14  ffffffff811d9c3f  delay_tsc <- __delay+0xf/0x20
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/ras.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/ras.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/ras.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/ras.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1190 @@
+.. include:: <isonum.txt>
+
+============================================
+Reliability, Availability and Serviceability
+============================================
+
+RAS concepts
+************
+
+Reliability, Availability and Serviceability (RAS) is a concept used on
+servers meant to measure their robusteness.
+
+Reliability
+  is the probability that a system will produce correct outputs.
+
+  * Generally measured as Mean Time Between Failures (MTBF)
+  * Enhanced by features that help to avoid, detect and repair hardware faults
+
+Availability
+  is the probability that a system is operational at a given time
+
+  * Generally measured as a percentage of downtime per a period of time
+  * Often uses mechanisms to detect and correct hardware faults in
+    runtime;
+
+Serviceability (or maintainability)
+  is the simplicity and speed with which a system can be repaired or
+  maintained
+
+  * Generally measured on Mean Time Between Repair (MTBR)
+
+Improving RAS
+-------------
+
+In order to reduce systems downtime, a system should be capable of detecting
+hardware errors, and, when possible correcting them in runtime. It should
+also provide mechanisms to detect hardware degradation, in order to warn
+the system administrator to take the action of replacing a component before
+it causes data loss or system downtime.
+
+Among the monitoring measures, the most usual ones include:
+
+* CPU – detect errors at instruction execution and at L1/L2/L3 caches;
+* Memory – add error correction logic (ECC) to detect and correct errors;
+* I/O – add CRC checksums for tranfered data;
+* Storage – RAID, journal file systems, checksums,
+  Self-Monitoring, Analysis and Reporting Technology (SMART).
+
+By monitoring the number of occurrences of error detections, it is possible
+to identify if the probability of hardware errors is increasing, and, on such
+case, do a preventive maintainance to replace a degrated component while
+those errors are correctable.
+
+Types of errors
+---------------
+
+Most mechanisms used on modern systems use use technologies like Hamming
+Codes that allow error correction when the number of errors on a bit packet
+is below a threshold. If the number of errors is above, those mechanisms
+can indicate with a high degree of confidence that an error happened, but
+they can't correct.
+
+Also, sometimes an error occur on a component that it is not used. For
+example, a part of the memory that it is not currently allocated.
+
+That defines some categories of errors:
+
+* **Correctable Error (CE)** - the error detection mechanism detected and
+  corrected the error. Such errors are usually not fatal, although some
+  Kernel mechanisms allow the system administrator to consider them as fatal.
+
+* **Uncorrected Error (UE)** - the amount of errors happened above the error
+  correction threshold, and the system was unable to auto-correct.
+
+* **Fatal Error** - when an UE error happens on a critical component of the
+  system (for example, a piece of the Kernel got corrupted by an UE), the
+  only reliable way to avoid data corruption is to hang or reboot the machine.
+
+* **Non-fatal Error** - when an UE error happens on an unused component,
+  like a CPU in power down state or an unused memory bank, the system may
+  still run, eventually replacing the affected hardware by a hot spare,
+  if available.
+
+  Also, when an error happens on an userspace process, it is also possible to
+  kill such process and let userspace restart it.
+
+The mechanism for handling non-fatal errors is usually complex and may
+require the help of some userspace application, in order to apply the
+policy desired by the system administrator.
+
+Identifying a bad hardware component
+------------------------------------
+
+Just detecting a hardware flaw is usually not enough, as the system needs
+to pinpoint to the minimal replaceable unit (MRU) that should be exchanged
+to make the hardware reliable again.
+
+So, it requires not only error logging facilities, but also mechanisms that
+will translate the error message to the silkscreen or component label for
+the MRU.
+
+Typically, it is very complex for memory, as modern CPUs interlace memory
+from different memory modules, in order to provide a better performance. The
+DMI BIOS usually have a list of memory module labels, with can be obtained
+using the ``dmidecode`` tool. For example, on a desktop machine, it shows::
+
+	Memory Device
+		Total Width: 64 bits
+		Data Width: 64 bits
+		Size: 16384 MB
+		Form Factor: SODIMM
+		Set: None
+		Locator: ChannelA-DIMM0
+		Bank Locator: BANK 0
+		Type: DDR4
+		Type Detail: Synchronous
+		Speed: 2133 MHz
+		Rank: 2
+		Configured Clock Speed: 2133 MHz
+
+On the above example, a DDR4 SO-DIMM memory module is located at the
+system's memory labeled as "BANK 0", as given by the *bank locator* field.
+Please notice that, on such system, the *total width* is equal to the
+*data witdh*. It means that such memory module doesn't have error
+detection/correction mechanisms.
+
+Unfortunately, not all systems use the same field to specify the memory
+bank. On this example, from an older server, ``dmidecode`` shows::
+
+	Memory Device
+		Array Handle: 0x1000
+		Error Information Handle: Not Provided
+		Total Width: 72 bits
+		Data Width: 64 bits
+		Size: 8192 MB
+		Form Factor: DIMM
+		Set: 1
+		Locator: DIMM_A1
+		Bank Locator: Not Specified
+		Type: DDR3
+		Type Detail: Synchronous Registered (Buffered)
+		Speed: 1600 MHz
+		Rank: 2
+		Configured Clock Speed: 1600 MHz
+
+There, the DDR3 RDIMM memory module is located at the system's memory labeled
+as "DIMM_A1", as given by the *locator* field. Please notice that this
+memory module has 64 bits of *data witdh* and 72 bits of *total width*. So,
+it has 8 extra bits to be used by error detection and correction mechanisms.
+Such kind of memory is called Error-correcting code memory (ECC memory).
+
+To make things even worse, it is not uncommon that systems with different
+labels on their system's board to use exactly the same BIOS, meaning that
+the labels provided by the BIOS won't match the real ones.
+
+ECC memory
+----------
+
+As mentioned on the previous section, ECC memory has extra bits to be
+used for error correction. So, on 64 bit systems, a memory module
+has 64 bits of *data width*, and 74 bits of *total width*. So, there are
+8 bits extra bits to be used for the error detection and correction
+mechanisms. Those extra bits are called *syndrome*\ [#f1]_\ [#f2]_.
+
+So, when the cpu requests the memory controller to write a word with
+*data width*, the memory controller calculates the *syndrome* in real time,
+using Hamming code, or some other error correction code, like SECDED+,
+producing a code with *total width* size. Such code is then written
+on the memory modules.
+
+At read, the *total width* bits code is converted back, using the same
+ECC code used on write, producing a word with *data width* and a *syndrome*.
+The word with *data width* is sent to the CPU, even when errors happen.
+
+The memory controller also looks at the *syndrome* in order to check if
+there was an error, and if the ECC code was able to fix such error.
+If the error was corrected, a Corrected Error (CE) happened. If not, an
+Uncorrected Error (UE) happened.
+
+The information about the CE/UE errors is stored on some special registers
+at the memory controller and can be accessed by reading such registers,
+either by BIOS, by some special CPUs or by Linux EDAC driver. On x86 64
+bit CPUs, such errors can also be retrieved via the Machine Check
+Architecture (MCA)\ [#f3]_.
+
+.. [#f1] Please notice that several memory controllers allow operation on a
+  mode called "Lock-Step", where it groups two memory modules together,
+  doing 128-bit reads/writes. That gives 16 bits for error correction, with
+  significatively improves the error correction mechanism, at the expense
+  that, when an error happens, there's no way to know what memory module is
+  to blame. So, it has to blame both memory modules.
+
+.. [#f2] Some memory controllers also allow using memory in mirror mode.
+  On such mode, the same data is written to two memory modules. At read,
+  the system checks both memory modules, in order to check if both provide
+  identical data. On such configuration, when an error happens, there's no
+  way to know what memory module is to blame. So, it has to blame both
+  memory modules (or 4 memory modules, if the system is also on Lock-step
+  mode).
+
+.. [#f3] For more details about the Machine Check Architecture (MCA),
+  please read Documentation/x86/x86_64/machinecheck at the Kernel tree.
+
+EDAC - Error Detection And Correction
+*************************************
+
+.. note::
+
+   "bluesmoke" was the name for this device driver subsystem when it
+   was "out-of-tree" and maintained at http://bluesmoke.sourceforge.net.
+   That site is mostly archaic now and can be used only for historical
+   purposes.
+
+   When the subsystem was pushed upstream for the first time, on
+   Kernel 2.6.16, for the first time, it was renamed to ``EDAC``.
+
+Purpose
+-------
+
+The ``edac`` kernel module's goal is to detect and report hardware errors
+that occur within the computer system running under linux.
+
+Memory
+------
+
+Memory Correctable Errors (CE) and Uncorrectable Errors (UE) are the
+primary errors being harvested. These types of errors are harvested by
+the ``edac_mc`` device.
+
+Detecting CE events, then harvesting those events and reporting them,
+**can** but must not necessarily be a predictor of future UE events. With
+CE events only, the system can and will continue to operate as no data
+has been damaged yet.
+
+However, preventive maintenance and proactive part replacement of memory
+modules exhibiting CEs can reduce the likelihood of the dreaded UE events
+and system panics.
+
+Other hardware elements
+-----------------------
+
+A new feature for EDAC, the ``edac_device`` class of device, was added in
+the 2.6.23 version of the kernel.
+
+This new device type allows for non-memory type of ECC hardware detectors
+to have their states harvested and presented to userspace via the sysfs
+interface.
+
+Some architectures have ECC detectors for L1, L2 and L3 caches,
+along with DMA engines, fabric switches, main data path switches,
+interconnections, and various other hardware data paths. If the hardware
+reports it, then a edac_device device probably can be constructed to
+harvest and present that to userspace.
+
+
+PCI bus scanning
+----------------
+
+In addition, PCI devices are scanned for PCI Bus Parity and SERR Errors
+in order to determine if errors are occurring during data transfers.
+
+The presence of PCI Parity errors must be examined with a grain of salt.
+There are several add-in adapters that do **not** follow the PCI specification
+with regards to Parity generation and reporting. The specification says
+the vendor should tie the parity status bits to 0 if they do not intend
+to generate parity.  Some vendors do not do this, and thus the parity bit
+can "float" giving false positives.
+
+There is a PCI device attribute located in sysfs that is checked by
+the EDAC PCI scanning code. If that attribute is set, PCI parity/error
+scanning is skipped for that device. The attribute is::
+
+	broken_parity_status
+
+and is located in ``/sys/devices/pci<XXX>/0000:XX:YY.Z`` directories for
+PCI devices.
+
+
+Versioning
+----------
+
+EDAC is composed of a "core" module (``edac_core.ko``) and several Memory
+Controller (MC) driver modules. On a given system, the CORE is loaded
+and one MC driver will be loaded. Both the CORE and the MC driver (or
+``edac_device`` driver) have individual versions that reflect current
+release level of their respective modules.
+
+Thus, to "report" on what version a system is running, one must report
+both the CORE's and the MC driver's versions.
+
+
+Loading
+-------
+
+If ``edac`` was statically linked with the kernel then no loading
+is necessary. If ``edac`` was built as modules then simply modprobe
+the ``edac`` pieces that you need. You should be able to modprobe
+hardware-specific modules and have the dependencies load the necessary
+core modules.
+
+Example::
+
+	$ modprobe amd76x_edac
+
+loads both the ``amd76x_edac.ko`` memory controller module and the
+``edac_mc.ko`` core module.
+
+
+Sysfs interface
+---------------
+
+EDAC presents a ``sysfs`` interface for control and reporting purposes. It
+lives in the /sys/devices/system/edac directory.
+
+Within this directory there currently reside 2 components:
+
+	======= ==============================
+	mc	memory controller(s) system
+	pci	PCI control and status system
+	======= ==============================
+
+
+
+Memory Controller (mc) Model
+----------------------------
+
+Each ``mc`` device controls a set of memory modules [#f4]_. These modules
+are laid out in a Chip-Select Row (``csrowX``) and Channel table (``chX``).
+There can be multiple csrows and multiple channels.
+
+.. [#f4] Nowadays, the term DIMM (Dual In-line Memory Module) is widely
+  used to refer to a memory module, although there are other memory
+  packaging alternatives, like SO-DIMM, SIMM, etc. Along this document,
+  and inside the EDAC system, the term "dimm" is used for all memory
+  modules, even when they use a different kind of packaging.
+
+Memory controllers allow for several csrows, with 8 csrows being a
+typical value. Yet, the actual number of csrows depends on the layout of
+a given motherboard, memory controller and memory module characteristics.
+
+Dual channels allow for dual data length (e. g. 128 bits, on 64 bit systems)
+data transfers to/from the CPU from/to memory. Some newer chipsets allow
+for more than 2 channels, like Fully Buffered DIMMs (FB-DIMMs) memory
+controllers. The following example will assume 2 channels:
+
+	+------------+-----------------------+
+	| Chip       |       Channels        |
+	| Select     +-----------+-----------+
+	| rows       |  ``ch0``  |  ``ch1``  |
+	+============+===========+===========+
+	| ``csrow0`` |  DIMM_A0  |  DIMM_B0  |
+	+------------+           |           |
+	| ``csrow1`` |           |           |
+	+------------+-----------+-----------+
+	| ``csrow2`` |  DIMM_A1  | DIMM_B1   |
+	+------------+           |           |
+	| ``csrow3`` |           |           |
+	+------------+-----------+-----------+
+
+In the above example, there are 4 physical slots on the motherboard
+for memory DIMMs:
+
+	+---------+---------+
+	| DIMM_A0 | DIMM_B0 |
+	+---------+---------+
+	| DIMM_A1 | DIMM_B1 |
+	+---------+---------+
+
+Labels for these slots are usually silk-screened on the motherboard.
+Slots labeled ``A`` are channel 0 in this example. Slots labeled ``B`` are
+channel 1. Notice that there are two csrows possible on a physical DIMM.
+These csrows are allocated their csrow assignment based on the slot into
+which the memory DIMM is placed. Thus, when 1 DIMM is placed in each
+Channel, the csrows cross both DIMMs.
+
+Memory DIMMs come single or dual "ranked". A rank is a populated csrow.
+Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above
+will have just one csrow (csrow0). csrow1 will be empty. On the other
+hand, when 2 dual ranked DIMMs are similarly placed, then both csrow0
+and csrow1 will be populated. The pattern repeats itself for csrow2 and
+csrow3.
+
+The representation of the above is reflected in the directory
+tree in EDAC's sysfs interface. Starting in directory
+``/sys/devices/system/edac/mc``, each memory controller will be
+represented by its own ``mcX`` directory, where ``X`` is the
+index of the MC::
+
+	..../edac/mc/
+		   |
+		   |->mc0
+		   |->mc1
+		   |->mc2
+		   ....
+
+Under each ``mcX`` directory each ``csrowX`` is again represented by a
+``csrowX``, where ``X`` is the csrow index::
+
+	.../mc/mc0/
+		|
+		|->csrow0
+		|->csrow2
+		|->csrow3
+		....
+
+Notice that there is no csrow1, which indicates that csrow0 is composed
+of a single ranked DIMMs. This should also apply in both Channels, in
+order to have dual-channel mode be operational. Since both csrow2 and
+csrow3 are populated, this indicates a dual ranked set of DIMMs for
+channels 0 and 1.
+
+Within each of the ``mcX`` and ``csrowX`` directories are several EDAC
+control and attribute files.
+
+``mcX`` directories
+-------------------
+
+In ``mcX`` directories are EDAC control and attribute files for
+this ``X`` instance of the memory controllers.
+
+For a description of the sysfs API, please see:
+
+	Documentation/ABI/testing/sysfs-devices-edac
+
+
+``dimmX`` or ``rankX`` directories
+----------------------------------
+
+The recommended way to use the EDAC subsystem is to look at the information
+provided by the ``dimmX`` or ``rankX`` directories [#f5]_.
+
+A typical EDAC system has the following structure under
+``/sys/devices/system/edac/``\ [#f6]_::
+
+	/sys/devices/system/edac/
+	├── mc
+	│   ├── mc0
+	│   │   ├── ce_count
+	│   │   ├── ce_noinfo_count
+	│   │   ├── dimm0
+	│   │   │   ├── dimm_dev_type
+	│   │   │   ├── dimm_edac_mode
+	│   │   │   ├── dimm_label
+	│   │   │   ├── dimm_location
+	│   │   │   ├── dimm_mem_type
+	│   │   │   ├── size
+	│   │   │   └── uevent
+	│   │   ├── max_location
+	│   │   ├── mc_name
+	│   │   ├── reset_counters
+	│   │   ├── seconds_since_reset
+	│   │   ├── size_mb
+	│   │   ├── ue_count
+	│   │   ├── ue_noinfo_count
+	│   │   └── uevent
+	│   ├── mc1
+	│   │   ├── ce_count
+	│   │   ├── ce_noinfo_count
+	│   │   ├── dimm0
+	│   │   │   ├── dimm_dev_type
+	│   │   │   ├── dimm_edac_mode
+	│   │   │   ├── dimm_label
+	│   │   │   ├── dimm_location
+	│   │   │   ├── dimm_mem_type
+	│   │   │   ├── size
+	│   │   │   └── uevent
+	│   │   ├── max_location
+	│   │   ├── mc_name
+	│   │   ├── reset_counters
+	│   │   ├── seconds_since_reset
+	│   │   ├── size_mb
+	│   │   ├── ue_count
+	│   │   ├── ue_noinfo_count
+	│   │   └── uevent
+	│   └── uevent
+	└── uevent
+
+In the ``dimmX`` directories are EDAC control and attribute files for
+this ``X`` memory module:
+
+- ``size`` - Total memory managed by this csrow attribute file
+
+	This attribute file displays, in count of megabytes, the memory
+	that this csrow contains.
+
+- ``dimm_dev_type``  - Device type attribute file
+
+	This attribute file will display what type of DRAM device is
+	being utilized on this DIMM.
+	Examples:
+
+		- x1
+		- x2
+		- x4
+		- x8
+
+- ``dimm_edac_mode`` - EDAC Mode of operation attribute file
+
+	This attribute file will display what type of Error detection
+	and correction is being utilized.
+
+- ``dimm_label`` - memory module label control file
+
+	This control file allows this DIMM to have a label assigned
+	to it. With this label in the module, when errors occur
+	the output can provide the DIMM label in the system log.
+	This becomes vital for panic events to isolate the
+	cause of the UE event.
+
+	DIMM Labels must be assigned after booting, with information
+	that correctly identifies the physical slot with its
+	silk screen label. This information is currently very
+	motherboard specific and determination of this information
+	must occur in userland at this time.
+
+- ``dimm_location`` - location of the memory module
+
+	The location can have up to 3 levels, and describe how the
+	memory controller identifies the location of a memory module.
+	Depending on the type of memory and memory controller, it
+	can be:
+
+		- *csrow* and *channel* - used when the memory controller
+		  doesn't identify a single DIMM - e. g. in ``rankX`` dir;
+		- *branch*, *channel*, *slot* - typically used on FB-DIMM memory
+		  controllers;
+		- *channel*, *slot* - used on Nehalem and newer Intel drivers.
+
+- ``dimm_mem_type`` - Memory Type attribute file
+
+	This attribute file will display what type of memory is currently
+	on this csrow. Normally, either buffered or unbuffered memory.
+	Examples:
+
+		- Registered-DDR
+		- Unbuffered-DDR
+
+.. [#f5] On some systems, the memory controller doesn't have any logic
+  to identify the memory module. On such systems, the directory is called ``rankX`` and works on a similar way as the ``csrowX`` directories.
+  On modern Intel memory controllers, the memory controller identifies the
+  memory modules directly. On such systems, the directory is called ``dimmX``.
+
+.. [#f6] There are also some ``power`` directories and ``subsystem``
+  symlinks inside the sysfs mapping that are automatically created by
+  the sysfs subsystem. Currently, they serve no purpose.
+
+``csrowX`` directories
+----------------------
+
+When CONFIG_EDAC_LEGACY_SYSFS is enabled, sysfs will contain the ``csrowX``
+directories. As this API doesn't work properly for Rambus, FB-DIMMs and
+modern Intel Memory Controllers, this is being deprecated in favor of
+``dimmX`` directories.
+
+In the ``csrowX`` directories are EDAC control and attribute files for
+this ``X`` instance of csrow:
+
+
+- ``ue_count`` - Total Uncorrectable Errors count attribute file
+
+	This attribute file displays the total count of uncorrectable
+	errors that have occurred on this csrow. If panic_on_ue is set
+	this counter will not have a chance to increment, since EDAC
+	will panic the system.
+
+
+- ``ce_count`` - Total Correctable Errors count attribute file
+
+	This attribute file displays the total count of correctable
+	errors that have occurred on this csrow. This count is very
+	important to examine. CEs provide early indications that a
+	DIMM is beginning to fail. This count field should be
+	monitored for non-zero values and report such information
+	to the system administrator.
+
+
+- ``size_mb`` - Total memory managed by this csrow attribute file
+
+	This attribute file displays, in count of megabytes, the memory
+	that this csrow contains.
+
+
+- ``mem_type`` - Memory Type attribute file
+
+	This attribute file will display what type of memory is currently
+	on this csrow. Normally, either buffered or unbuffered memory.
+	Examples:
+
+		- Registered-DDR
+		- Unbuffered-DDR
+
+
+- ``edac_mode`` - EDAC Mode of operation attribute file
+
+	This attribute file will display what type of Error detection
+	and correction is being utilized.
+
+
+- ``dev_type`` - Device type attribute file
+
+	This attribute file will display what type of DRAM device is
+	being utilized on this DIMM.
+	Examples:
+
+		- x1
+		- x2
+		- x4
+		- x8
+
+
+- ``ch0_ce_count`` - Channel 0 CE Count attribute file
+
+	This attribute file will display the count of CEs on this
+	DIMM located in channel 0.
+
+
+- ``ch0_ue_count`` - Channel 0 UE Count attribute file
+
+	This attribute file will display the count of UEs on this
+	DIMM located in channel 0.
+
+
+- ``ch0_dimm_label`` - Channel 0 DIMM Label control file
+
+
+	This control file allows this DIMM to have a label assigned
+	to it. With this label in the module, when errors occur
+	the output can provide the DIMM label in the system log.
+	This becomes vital for panic events to isolate the
+	cause of the UE event.
+
+	DIMM Labels must be assigned after booting, with information
+	that correctly identifies the physical slot with its
+	silk screen label. This information is currently very
+	motherboard specific and determination of this information
+	must occur in userland at this time.
+
+
+- ``ch1_ce_count`` - Channel 1 CE Count attribute file
+
+
+	This attribute file will display the count of CEs on this
+	DIMM located in channel 1.
+
+
+- ``ch1_ue_count`` - Channel 1 UE Count attribute file
+
+
+	This attribute file will display the count of UEs on this
+	DIMM located in channel 0.
+
+
+- ``ch1_dimm_label`` - Channel 1 DIMM Label control file
+
+	This control file allows this DIMM to have a label assigned
+	to it. With this label in the module, when errors occur
+	the output can provide the DIMM label in the system log.
+	This becomes vital for panic events to isolate the
+	cause of the UE event.
+
+	DIMM Labels must be assigned after booting, with information
+	that correctly identifies the physical slot with its
+	silk screen label. This information is currently very
+	motherboard specific and determination of this information
+	must occur in userland at this time.
+
+
+System Logging
+--------------
+
+If logging for UEs and CEs is enabled, then system logs will contain
+information indicating that errors have been detected::
+
+  EDAC MC0: CE page 0x283, offset 0xce0, grain 8, syndrome 0x6ec3, row 0, channel 1 "DIMM_B1": amd76x_edac
+  EDAC MC0: CE page 0x1e5, offset 0xfb0, grain 8, syndrome 0xb741, row 0, channel 1 "DIMM_B1": amd76x_edac
+
+
+The structure of the message is:
+
+	+---------------------------------------+-------------+
+	| Content                               + Example     |
+	+=======================================+=============+
+	| The memory controller                 | MC0         |
+	+---------------------------------------+-------------+
+	| Error type                            | CE          |
+	+---------------------------------------+-------------+
+	| Memory page                           | 0x283       |
+	+---------------------------------------+-------------+
+	| Offset in the page                    | 0xce0       |
+	+---------------------------------------+-------------+
+	| The byte granularity                  | grain 8     |
+	| or resolution of the error            |             |
+	+---------------------------------------+-------------+
+	| The error syndrome                    | 0xb741      |
+	+---------------------------------------+-------------+
+	| Memory row                            | row 0       +
+	+---------------------------------------+-------------+
+	| Memory channel                        | channel 1   |
+	+---------------------------------------+-------------+
+	| DIMM label, if set prior              | DIMM B1     |
+	+---------------------------------------+-------------+
+	| And then an optional, driver-specific |             |
+	| message that may have additional      |             |
+	| information.                          |             |
+	+---------------------------------------+-------------+
+
+Both UEs and CEs with no info will lack all but memory controller, error
+type, a notice of "no info" and then an optional, driver-specific error
+message.
+
+
+PCI Bus Parity Detection
+------------------------
+
+On Header Type 00 devices, the primary status is looked at for any
+parity error regardless of whether parity is enabled on the device or
+not. (The spec indicates parity is generated in some cases). On Header
+Type 01 bridges, the secondary status register is also looked at to see
+if parity occurred on the bus on the other side of the bridge.
+
+
+Sysfs configuration
+-------------------
+
+Under ``/sys/devices/system/edac/pci`` are control and attribute files as
+follows:
+
+
+- ``check_pci_parity`` - Enable/Disable PCI Parity checking control file
+
+	This control file enables or disables the PCI Bus Parity scanning
+	operation. Writing a 1 to this file enables the scanning. Writing
+	a 0 to this file disables the scanning.
+
+	Enable::
+
+		echo "1" >/sys/devices/system/edac/pci/check_pci_parity
+
+	Disable::
+
+		echo "0" >/sys/devices/system/edac/pci/check_pci_parity
+
+
+- ``pci_parity_count`` - Parity Count
+
+	This attribute file will display the number of parity errors that
+	have been detected.
+
+
+Module parameters
+-----------------
+
+- ``edac_mc_panic_on_ue`` - Panic on UE control file
+
+	An uncorrectable error will cause a machine panic.  This is usually
+	desirable.  It is a bad idea to continue when an uncorrectable error
+	occurs - it is indeterminate what was uncorrected and the operating
+	system context might be so mangled that continuing will lead to further
+	corruption. If the kernel has MCE configured, then EDAC will never
+	notice the UE.
+
+	LOAD TIME::
+
+		module/kernel parameter: edac_mc_panic_on_ue=[0|1]
+
+	RUN TIME::
+
+		echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue
+
+
+- ``edac_mc_log_ue`` - Log UE control file
+
+
+	Generate kernel messages describing uncorrectable errors.  These errors
+	are reported through the system message log system.  UE statistics
+	will be accumulated even when UE logging is disabled.
+
+	LOAD TIME::
+
+		module/kernel parameter: edac_mc_log_ue=[0|1]
+
+	RUN TIME::
+
+		echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue
+
+
+- ``edac_mc_log_ce`` - Log CE control file
+
+
+	Generate kernel messages describing correctable errors.  These
+	errors are reported through the system message log system.
+	CE statistics will be accumulated even when CE logging is disabled.
+
+	LOAD TIME::
+
+		module/kernel parameter: edac_mc_log_ce=[0|1]
+
+	RUN TIME::
+
+		echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce
+
+
+- ``edac_mc_poll_msec`` - Polling period control file
+
+
+	The time period, in milliseconds, for polling for error information.
+	Too small a value wastes resources.  Too large a value might delay
+	necessary handling of errors and might loose valuable information for
+	locating the error.  1000 milliseconds (once each second) is the current
+	default. Systems which require all the bandwidth they can get, may
+	increase this.
+
+	LOAD TIME::
+
+		module/kernel parameter: edac_mc_poll_msec=[0|1]
+
+	RUN TIME::
+
+		echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec
+
+
+- ``panic_on_pci_parity`` - Panic on PCI PARITY Error
+
+
+	This control file enables or disables panicking when a parity
+	error has been detected.
+
+
+	module/kernel parameter::
+
+			edac_panic_on_pci_pe=[0|1]
+
+	Enable::
+
+		echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
+
+	Disable::
+
+		echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
+
+
+
+EDAC device type
+----------------
+
+In the header file, edac_pci.h, there is a series of edac_device structures
+and APIs for the EDAC_DEVICE.
+
+User space access to an edac_device is through the sysfs interface.
+
+At the location ``/sys/devices/system/edac`` (sysfs) new edac_device devices
+will appear.
+
+There is a three level tree beneath the above ``edac`` directory. For example,
+the ``test_device_edac`` device (found at the http://bluesmoke.sourceforget.net
+website) installs itself as::
+
+	/sys/devices/system/edac/test-instance
+
+in this directory are various controls, a symlink and one or more ``instance``
+directories.
+
+The standard default controls are:
+
+	==============	=======================================================
+	log_ce		boolean to log CE events
+	log_ue		boolean to log UE events
+	panic_on_ue	boolean to ``panic`` the system if an UE is encountered
+			(default off, can be set true via startup script)
+	poll_msec	time period between POLL cycles for events
+	==============	=======================================================
+
+The test_device_edac device adds at least one of its own custom control:
+
+	==============	==================================================
+	test_bits	which in the current test driver does nothing but
+			show how it is installed. A ported driver can
+			add one or more such controls and/or attributes
+			for specific uses.
+			One out-of-tree driver uses controls here to allow
+			for ERROR INJECTION operations to hardware
+			injection registers
+	==============	==================================================
+
+The symlink points to the 'struct dev' that is registered for this edac_device.
+
+Instances
+---------
+
+One or more instance directories are present. For the ``test_device_edac``
+case:
+
+	+----------------+
+	| test-instance0 |
+	+----------------+
+
+
+In this directory there are two default counter attributes, which are totals of
+counter in deeper subdirectories.
+
+	==============	====================================
+	ce_count	total of CE events of subdirectories
+	ue_count	total of UE events of subdirectories
+	==============	====================================
+
+Blocks
+------
+
+At the lowest directory level is the ``block`` directory. There can be 0, 1
+or more blocks specified in each instance:
+
+	+-------------+
+	| test-block0 |
+	+-------------+
+
+In this directory the default attributes are:
+
+	==============	================================================
+	ce_count	which is counter of CE events for this ``block``
+			of hardware being monitored
+	ue_count	which is counter of UE events for this ``block``
+			of hardware being monitored
+	==============	================================================
+
+
+The ``test_device_edac`` device adds 4 attributes and 1 control:
+
+	================== ====================================================
+	test-block-bits-0	for every POLL cycle this counter
+				is incremented
+	test-block-bits-1	every 10 cycles, this counter is bumped once,
+				and test-block-bits-0 is set to 0
+	test-block-bits-2	every 100 cycles, this counter is bumped once,
+				and test-block-bits-1 is set to 0
+	test-block-bits-3	every 1000 cycles, this counter is bumped once,
+				and test-block-bits-2 is set to 0
+	================== ====================================================
+
+
+	================== ====================================================
+	reset-counters		writing ANY thing to this control will
+				reset all the above counters.
+	================== ====================================================
+
+
+Use of the ``test_device_edac`` driver should enable any others to create their own
+unique drivers for their hardware systems.
+
+The ``test_device_edac`` sample driver is located at the
+http://bluesmoke.sourceforge.net project site for EDAC.
+
+
+Usage of EDAC APIs on Nehalem and newer Intel CPUs
+--------------------------------------------------
+
+On older Intel architectures, the memory controller was part of the North
+Bridge chipset. Nehalem, Sandy Bridge, Ivy Bridge, Haswell, Sky Lake and
+newer Intel architectures integrated an enhanced version of the memory
+controller (MC) inside the CPUs.
+
+This chapter will cover the differences of the enhanced memory controllers
+found on newer Intel CPUs, such as ``i7core_edac``, ``sb_edac`` and
+``sbx_edac`` drivers.
+
+.. note::
+
+   The Xeon E7 processor families use a separate chip for the memory
+   controller, called Intel Scalable Memory Buffer. This section doesn't
+   apply for such families.
+
+1) There is one Memory Controller per Quick Patch Interconnect
+   (QPI). At the driver, the term "socket" means one QPI. This is
+   associated with a physical CPU socket.
+
+   Each MC have 3 physical read channels, 3 physical write channels and
+   3 logic channels. The driver currently sees it as just 3 channels.
+   Each channel can have up to 3 DIMMs.
+
+   The minimum known unity is DIMMs. There are no information about csrows.
+   As EDAC API maps the minimum unity is csrows, the driver sequentially
+   maps channel/DIMM into different csrows.
+
+   For example, supposing the following layout::
+
+	Ch0 phy rd0, wr0 (0x063f4031): 2 ranks, UDIMMs
+	  dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+	  dimm 1 1024 Mb offset: 4, bank: 8, rank: 1, row: 0x4000, col: 0x400
+        Ch1 phy rd1, wr1 (0x063f4031): 2 ranks, UDIMMs
+	  dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+	Ch2 phy rd3, wr3 (0x063f4031): 2 ranks, UDIMMs
+	  dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
+
+   The driver will map it as::
+
+	csrow0: channel 0, dimm0
+	csrow1: channel 0, dimm1
+	csrow2: channel 1, dimm0
+	csrow3: channel 2, dimm0
+
+   exports one DIMM per csrow.
+
+   Each QPI is exported as a different memory controller.
+
+2) The MC has the ability to inject errors to test drivers. The drivers
+   implement this functionality via some error injection nodes:
+
+   For injecting a memory error, there are some sysfs nodes, under
+   ``/sys/devices/system/edac/mc/mc?/``:
+
+   - ``inject_addrmatch/*``:
+      Controls the error injection mask register. It is possible to specify
+      several characteristics of the address to match an error code::
+
+         dimm = the affected dimm. Numbers are relative to a channel;
+         rank = the memory rank;
+         channel = the channel that will generate an error;
+         bank = the affected bank;
+         page = the page address;
+         column (or col) = the address column.
+
+      each of the above values can be set to "any" to match any valid value.
+
+      At driver init, all values are set to any.
+
+      For example, to generate an error at rank 1 of dimm 2, for any channel,
+      any bank, any page, any column::
+
+		echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
+		echo 1 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
+
+	To return to the default behaviour of matching any, you can do::
+
+		echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
+		echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
+
+   - ``inject_eccmask``:
+          specifies what bits will have troubles,
+
+   - ``inject_section``:
+       specifies what ECC cache section will get the error::
+
+		3 for both
+		2 for the highest
+		1 for the lowest
+
+   - ``inject_type``:
+       specifies the type of error, being a combination of the following bits::
+
+		bit 0 - repeat
+		bit 1 - ecc
+		bit 2 - parity
+
+   - ``inject_enable``:
+       starts the error generation when something different than 0 is written.
+
+   All inject vars can be read. root permission is needed for write.
+
+   Datasheet states that the error will only be generated after a write on an
+   address that matches inject_addrmatch. It seems, however, that reading will
+   also produce an error.
+
+   For example, the following code will generate an error for any write access
+   at socket 0, on any DIMM/address on channel 2::
+
+	echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/channel
+	echo 2 >/sys/devices/system/edac/mc/mc0/inject_type
+	echo 64 >/sys/devices/system/edac/mc/mc0/inject_eccmask
+	echo 3 >/sys/devices/system/edac/mc/mc0/inject_section
+	echo 1 >/sys/devices/system/edac/mc/mc0/inject_enable
+	dd if=/dev/mem of=/dev/null seek=16k bs=4k count=1 >& /dev/null
+
+   For socket 1, it is needed to replace "mc0" by "mc1" at the above
+   commands.
+
+   The generated error message will look like::
+
+	EDAC MC0: UE row 0, channel-a= 0 channel-b= 0 labels "-": NON_FATAL (addr = 0x0075b980, socket=0, Dimm=0, Channel=2, syndrome=0x00000040, count=1, Err=8c0000400001009f:4000080482 (read error: read ECC error))
+
+3) Corrected Error memory register counters
+
+   Those newer MCs have some registers to count memory errors. The driver
+   uses those registers to report Corrected Errors on devices with Registered
+   DIMMs.
+
+   However, those counters don't work with Unregistered DIMM. As the chipset
+   offers some counters that also work with UDIMMs (but with a worse level of
+   granularity than the default ones), the driver exposes those registers for
+   UDIMM memories.
+
+   They can be read by looking at the contents of ``all_channel_counts/``::
+
+     $ for i in /sys/devices/system/edac/mc/mc0/all_channel_counts/*; do echo $i; cat $i; done
+	/sys/devices/system/edac/mc/mc0/all_channel_counts/udimm0
+	0
+	/sys/devices/system/edac/mc/mc0/all_channel_counts/udimm1
+	0
+	/sys/devices/system/edac/mc/mc0/all_channel_counts/udimm2
+	0
+
+   What happens here is that errors on different csrows, but at the same
+   dimm number will increment the same counter.
+   So, in this memory mapping::
+
+	csrow0: channel 0, dimm0
+	csrow1: channel 0, dimm1
+	csrow2: channel 1, dimm0
+	csrow3: channel 2, dimm0
+
+   The hardware will increment udimm0 for an error at the first dimm at either
+   csrow0, csrow2  or csrow3;
+
+   The hardware will increment udimm1 for an error at the second dimm at either
+   csrow0, csrow2  or csrow3;
+
+   The hardware will increment udimm2 for an error at the third dimm at either
+   csrow0, csrow2  or csrow3;
+
+4) Standard error counters
+
+   The standard error counters are generated when an mcelog error is received
+   by the driver. Since, with UDIMM, this is counted by software, it is
+   possible that some errors could be lost. With RDIMM's, they display the
+   contents of the registers
+
+Reference documents used on ``amd64_edac``
+------------------------------------------
+
+``amd64_edac`` module is based on the following documents
+(available from http://support.amd.com/en-us/search/tech-docs):
+
+1. :Title:  BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD
+	   Opteron Processors
+   :AMD publication #: 26094
+   :Revision: 3.26
+   :Link: http://support.amd.com/TechDocs/26094.PDF
+
+2. :Title:  BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh
+	   Processors
+   :AMD publication #: 32559
+   :Revision: 3.00
+   :Issue Date: May 2006
+   :Link: http://support.amd.com/TechDocs/32559.pdf
+
+3. :Title:  BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h
+	   Processors
+   :AMD publication #: 31116
+   :Revision: 3.00
+   :Issue Date: September 07, 2007
+   :Link: http://support.amd.com/TechDocs/31116.pdf
+
+4. :Title: BIOS and Kernel Developer's Guide (BKDG) for AMD Family 15h
+	  Models 30h-3Fh Processors
+   :AMD publication #: 49125
+   :Revision: 3.06
+   :Issue Date: 2/12/2015 (latest release)
+   :Link: http://support.amd.com/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf
+
+5. :Title: BIOS and Kernel Developer's Guide (BKDG) for AMD Family 15h
+	  Models 60h-6Fh Processors
+   :AMD publication #: 50742
+   :Revision: 3.01
+   :Issue Date: 7/23/2015 (latest release)
+   :Link: http://support.amd.com/TechDocs/50742_15h_Models_60h-6Fh_BKDG.pdf
+
+6. :Title: BIOS and Kernel Developer's Guide (BKDG) for AMD Family 16h
+	  Models 00h-0Fh Processors
+   :AMD publication #: 48751
+   :Revision: 3.03
+   :Issue Date: 2/23/2015 (latest release)
+   :Link: http://support.amd.com/TechDocs/48751_16h_bkdg.pdf
+
+Credits
+=======
+
+* Written by Doug Thompson <dougthompson@xmission.com>
+
+  - 7 Dec 2005
+  - 17 Jul 2007	Updated
+
+* |copy| Mauro Carvalho Chehab
+
+  - 05 Aug 2009	Nehalem interface
+  - 26 Oct 2016 Converted to ReST and cleanups at the Nehalem section
+
+* EDAC authors/maintainers:
+
+  - Doug Thompson, Dave Jiang, Dave Peterson et al,
+  - Mauro Carvalho Chehab
+  - Borislav Petkov
+  - original author: Thayne Harbaugh
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/README.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/README.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/README.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/README.rst	2017-02-12 17:21:10.000000000 -0500
@@ -0,0 +1,411 @@
+GNU Linux-libre <http://linux-libre.fsfla.org>
+==============================================
+
+These are the release notes for GNU Linux-libre.  Read them carefully,
+as they tell you what this is all about, explain how to install the
+kernel, and what to do if something goes wrong.
+
+What is Linux?
+--------------
+
+  Linux is a clone of the Unix kernel, written from scratch by
+  Linus Torvalds with assistance from a loosely-knit team of hackers across
+  the Net. It aims towards POSIX and Single UNIX Specification compliance.
+
+  It has all the features you would expect in a modern fully-fledged Unix kernel,
+  including true multitasking, virtual memory, shared libraries, demand
+  loading, shared copy-on-write executables, proper memory management,
+  and multistack networking including IPv4 and IPv6.
+
+  It is distributed under the GNU General Public License - see the
+  accompanying COPYING file for more details.
+
+On what hardware does it run?
+-----------------------------
+
+  Although originally developed first for 32-bit x86-based PCs (386 or higher),
+  today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
+  UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell,
+  IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
+  Xtensa, Tilera TILE, AVR32, ARC and Renesas M32R architectures.
+
+  Linux is easily portable to most general-purpose 32- or 64-bit architectures
+  as long as they have a paged memory management unit (PMMU) and a port of the
+  GNU C compiler (gcc) (part of The GNU Compiler Collection, GCC). Linux has
+  also been ported to a number of architectures without a PMMU, although
+  functionality is then obviously somewhat limited.
+  Linux has also been ported to itself. You can now run the kernel as a
+  userspace application - this is called UserMode Linux (UML).
+
+Documentation
+-------------
+
+ - There is a lot of documentation available both in electronic form on
+   the Internet and in books, both Linux-specific and pertaining to
+   general UNIX questions.  I'd recommend looking into the documentation
+   subdirectories on any Linux FTP site for the LDP (Linux Documentation
+   Project) books.  This README is not meant to be documentation on the
+   system: there are much better sources available.
+
+ - There are various README files in the Documentation/ subdirectory:
+   these typically contain kernel-specific installation notes for some
+   drivers for example. See Documentation/00-INDEX for a list of what
+   is contained in each file.  Please read the
+   :ref:`Documentation/process/changes.rst <changes>` file, as it
+   contains information about the problems, which may result by upgrading
+   your kernel.
+
+ - The Documentation/DocBook/ subdirectory contains several guides for
+   kernel developers and users.  These guides can be rendered in a
+   number of formats:  PostScript (.ps), PDF, HTML, & man-pages, among others.
+   After installation, ``make psdocs``, ``make pdfdocs``, ``make htmldocs``,
+   or ``make mandocs`` will render the documentation in the requested format.
+
+Installing the kernel source
+----------------------------
+
+ - If you install the full sources, put the kernel tarball in a
+   directory where you have permissions (e.g. your home directory) and
+   unpack it::
+
+     xz -cd linux-4.X.tar.xz | tar xvf -
+
+   Replace "X" with the version number of the latest kernel.
+
+   Do NOT use the /usr/src/linux area! This area has a (usually
+   incomplete) set of kernel headers that are used by the library header
+   files.  They should match the library, and not get messed up by
+   whatever the kernel-du-jour happens to be.
+
+ - You can also upgrade between 4.x releases by patching.  Patches are
+   distributed in the xz format.  To install by patching, get all the
+   newer patch files, enter the top level directory of the kernel source
+   (linux-4.X) and execute::
+
+     xz -cd ../patch-4.x.xz | patch -p1
+
+   Replace "x" for all versions bigger than the version "X" of your current
+   source tree, **in_order**, and you should be ok.  You may want to remove
+   the backup files (some-file-name~ or some-file-name.orig), and make sure
+   that there are no failed patches (some-file-name# or some-file-name.rej).
+   If there are, either you or I have made a mistake.
+
+   Unlike patches for the 4.x kernels, patches for the 4.x.y kernels
+   (also known as the -stable kernels) are not incremental but instead apply
+   directly to the base 4.x kernel.  For example, if your base kernel is 4.0
+   and you want to apply the 4.0.3 patch, you must not first apply the 4.0.1
+   and 4.0.2 patches. Similarly, if you are running kernel version 4.0.2 and
+   want to jump to 4.0.3, you must first reverse the 4.0.2 patch (that is,
+   patch -R) **before** applying the 4.0.3 patch. You can read more on this in
+   :ref:`Documentation/process/applying-patches.rst <applying_patches>`.
+
+   Alternatively, the script patch-kernel can be used to automate this
+   process.  It determines the current kernel version and applies any
+   patches found::
+
+     linux/scripts/patch-kernel linux
+
+   The first argument in the command above is the location of the
+   kernel source.  Patches are applied from the current directory, but
+   an alternative directory can be specified as the second argument.
+
+ - Make sure you have no stale .o files and dependencies lying around::
+
+     cd linux
+     make mrproper
+
+   You should now have the sources correctly installed.
+
+Software requirements
+---------------------
+
+   Compiling and running the 4.x kernels requires up-to-date
+   versions of various software packages.  Consult
+   :ref:`Documentation/process/changes.rst <changes>` for the minimum version numbers
+   required and how to get updates for these packages.  Beware that using
+   excessively old versions of these packages can cause indirect
+   errors that are very difficult to track down, so don't assume that
+   you can just update packages when obvious problems arise during
+   build or operation.
+
+Build directory for the kernel
+------------------------------
+
+   When compiling the kernel, all output files will per default be
+   stored together with the kernel source code.
+   Using the option ``make O=output/dir`` allows you to specify an alternate
+   place for the output files (including .config).
+   Example::
+
+     kernel source code: /usr/src/linux-4.X
+     build directory:    /home/name/build/kernel
+
+   To configure and build the kernel, use::
+
+     cd /usr/src/linux-4.X
+     make O=/home/name/build/kernel menuconfig
+     make O=/home/name/build/kernel
+     sudo make O=/home/name/build/kernel modules_install install
+
+   Please note: If the ``O=output/dir`` option is used, then it must be
+   used for all invocations of make.
+
+Configuring the kernel
+----------------------
+
+   Do not skip this step even if you are only upgrading one minor
+   version.  New configuration options are added in each release, and
+   odd problems will turn up if the configuration files are not set up
+   as expected.  If you want to carry your existing configuration to a
+   new version with minimal work, use ``make oldconfig``, which will
+   only ask you for the answers to new questions.
+
+ - Alternative configuration commands are::
+
+     "make config"      Plain text interface.
+
+     "make menuconfig"  Text based color menus, radiolists & dialogs.
+
+     "make nconfig"     Enhanced text based color menus.
+
+     "make xconfig"     Qt based configuration tool.
+
+     "make gconfig"     GTK+ based configuration tool.
+
+     "make oldconfig"   Default all questions based on the contents of
+                        your existing ./.config file and asking about
+                        new config symbols.
+
+     "make silentoldconfig"
+                        Like above, but avoids cluttering the screen
+                        with questions already answered.
+                        Additionally updates the dependencies.
+
+     "make olddefconfig"
+                        Like above, but sets new symbols to their default
+                        values without prompting.
+
+     "make defconfig"   Create a ./.config file by using the default
+                        symbol values from either arch/$ARCH/defconfig
+                        or arch/$ARCH/configs/${PLATFORM}_defconfig,
+                        depending on the architecture.
+
+     "make ${PLATFORM}_defconfig"
+                        Create a ./.config file by using the default
+                        symbol values from
+                        arch/$ARCH/configs/${PLATFORM}_defconfig.
+                        Use "make help" to get a list of all available
+                        platforms of your architecture.
+
+     "make allyesconfig"
+                        Create a ./.config file by setting symbol
+                        values to 'y' as much as possible.
+
+     "make allmodconfig"
+                        Create a ./.config file by setting symbol
+                        values to 'm' as much as possible.
+
+     "make allnoconfig" Create a ./.config file by setting symbol
+                        values to 'n' as much as possible.
+
+     "make randconfig"  Create a ./.config file by setting symbol
+                        values to random values.
+
+     "make localmodconfig" Create a config based on current config and
+                           loaded modules (lsmod). Disables any module
+                           option that is not needed for the loaded modules.
+
+                           To create a localmodconfig for another machine,
+                           store the lsmod of that machine into a file
+                           and pass it in as a LSMOD parameter.
+
+                   target$ lsmod > /tmp/mylsmod
+                   target$ scp /tmp/mylsmod host:/tmp
+
+                   host$ make LSMOD=/tmp/mylsmod localmodconfig
+
+                           The above also works when cross compiling.
+
+     "make localyesconfig" Similar to localmodconfig, except it will convert
+                           all module options to built in (=y) options.
+
+   You can find more information on using the Linux kernel config tools
+   in Documentation/kbuild/kconfig.txt.
+
+ - NOTES on ``make config``:
+
+    - Having unnecessary drivers will make the kernel bigger, and can
+      under some circumstances lead to problems: probing for a
+      nonexistent controller card may confuse your other controllers
+
+    - A kernel with math-emulation compiled in will still use the
+      coprocessor if one is present: the math emulation will just
+      never get used in that case.  The kernel will be slightly larger,
+      but will work on different machines regardless of whether they
+      have a math coprocessor or not.
+
+    - The "kernel hacking" configuration details usually result in a
+      bigger or slower kernel (or both), and can even make the kernel
+      less stable by configuring some routines to actively try to
+      break bad code to find kernel problems (kmalloc()).  Thus you
+      should probably answer 'n' to the questions for "development",
+      "experimental", or "debugging" features.
+
+Compiling the kernel
+--------------------
+
+ - Make sure you have at least gcc 3.2 available.
+   For more information, refer to :ref:`Documentation/process/changes.rst <changes>`.
+
+   Please note that you can still run a.out user programs with this kernel.
+
+ - Do a ``make`` to create a compressed kernel image. It is also
+   possible to do ``make install`` if you have lilo installed to suit the
+   kernel makefiles, but you may want to check your particular lilo setup first.
+
+   To do the actual install, you have to be root, but none of the normal
+   build should require that. Don't take the name of root in vain.
+
+ - If you configured any of the parts of the kernel as ``modules``, you
+   will also have to do ``make modules_install``.
+
+ - Verbose kernel compile/build output:
+
+   Normally, the kernel build system runs in a fairly quiet mode (but not
+   totally silent).  However, sometimes you or other kernel developers need
+   to see compile, link, or other commands exactly as they are executed.
+   For this, use "verbose" build mode.  This is done by passing
+   ``V=1`` to the ``make`` command, e.g.::
+
+     make V=1 all
+
+   To have the build system also tell the reason for the rebuild of each
+   target, use ``V=2``.  The default is ``V=0``.
+
+ - Keep a backup kernel handy in case something goes wrong.  This is
+   especially true for the development releases, since each new release
+   contains new code which has not been debugged.  Make sure you keep a
+   backup of the modules corresponding to that kernel, as well.  If you
+   are installing a new kernel with the same version number as your
+   working kernel, make a backup of your modules directory before you
+   do a ``make modules_install``.
+
+   Alternatively, before compiling, use the kernel config option
+   "LOCALVERSION" to append a unique suffix to the regular kernel version.
+   LOCALVERSION can be set in the "General Setup" menu.
+
+ - In order to boot your new kernel, you'll need to copy the kernel
+   image (e.g. .../linux/arch/x86/boot/bzImage after compilation)
+   to the place where your regular bootable kernel is found.
+
+ - Booting a kernel directly from a floppy without the assistance of a
+   bootloader such as LILO, is no longer supported.
+
+   If you boot Linux from the hard drive, chances are you use LILO, which
+   uses the kernel image as specified in the file /etc/lilo.conf.  The
+   kernel image file is usually /vmlinuz, /boot/vmlinuz, /bzImage or
+   /boot/bzImage.  To use the new kernel, save a copy of the old image
+   and copy the new image over the old one.  Then, you MUST RERUN LILO
+   to update the loading map! If you don't, you won't be able to boot
+   the new kernel image.
+
+   Reinstalling LILO is usually a matter of running /sbin/lilo.
+   You may wish to edit /etc/lilo.conf to specify an entry for your
+   old kernel image (say, /vmlinux.old) in case the new one does not
+   work.  See the LILO docs for more information.
+
+   After reinstalling LILO, you should be all set.  Shutdown the system,
+   reboot, and enjoy!
+
+   If you ever need to change the default root device, video mode,
+   ramdisk size, etc.  in the kernel image, use the ``rdev`` program (or
+   alternatively the LILO boot options when appropriate).  No need to
+   recompile the kernel to change these parameters.
+
+ - Reboot with the new kernel and enjoy.
+
+If something goes wrong
+-----------------------
+
+ - If you have problems that seem to be due to kernel bugs, please check
+   the file MAINTAINERS to see if there is a particular person associated
+   with the part of the kernel that you are having trouble with. If there
+   isn't anyone listed there, then the second best thing is to mail
+   them to me (torvalds@linux-foundation.org), and possibly to any other
+   relevant mailing-list or to the newsgroup.
+
+ - In all bug-reports, *please* tell what kernel you are talking about,
+   how to duplicate the problem, and what your setup is (use your common
+   sense).  If the problem is new, tell me so, and if the problem is
+   old, please try to tell me when you first noticed it.
+
+ - If the bug results in a message like::
+
+     unable to handle kernel paging request at address C0000010
+     Oops: 0002
+     EIP:   0010:XXXXXXXX
+     eax: xxxxxxxx   ebx: xxxxxxxx   ecx: xxxxxxxx   edx: xxxxxxxx
+     esi: xxxxxxxx   edi: xxxxxxxx   ebp: xxxxxxxx
+     ds: xxxx  es: xxxx  fs: xxxx  gs: xxxx
+     Pid: xx, process nr: xx
+     xx xx xx xx xx xx xx xx xx xx
+
+   or similar kernel debugging information on your screen or in your
+   system log, please duplicate it *exactly*.  The dump may look
+   incomprehensible to you, but it does contain information that may
+   help debugging the problem.  The text above the dump is also
+   important: it tells something about why the kernel dumped code (in
+   the above example, it's due to a bad kernel pointer). More information
+   on making sense of the dump is in Documentation/admin-guide/oops-tracing.rst
+
+ - If you compiled the kernel with CONFIG_KALLSYMS you can send the dump
+   as is, otherwise you will have to use the ``ksymoops`` program to make
+   sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred).
+   This utility can be downloaded from
+   ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops/ .
+   Alternatively, you can do the dump lookup by hand:
+
+ - In debugging dumps like the above, it helps enormously if you can
+   look up what the EIP value means.  The hex value as such doesn't help
+   me or anybody else very much: it will depend on your particular
+   kernel setup.  What you should do is take the hex value from the EIP
+   line (ignore the ``0010:``), and look it up in the kernel namelist to
+   see which kernel function contains the offending address.
+
+   To find out the kernel function name, you'll need to find the system
+   binary associated with the kernel that exhibited the symptom.  This is
+   the file 'linux/vmlinux'.  To extract the namelist and match it against
+   the EIP from the kernel crash, do::
+
+     nm vmlinux | sort | less
+
+   This will give you a list of kernel addresses sorted in ascending
+   order, from which it is simple to find the function that contains the
+   offending address.  Note that the address given by the kernel
+   debugging messages will not necessarily match exactly with the
+   function addresses (in fact, that is very unlikely), so you can't
+   just 'grep' the list: the list will, however, give you the starting
+   point of each kernel function, so by looking for the function that
+   has a starting address lower than the one you are searching for but
+   is followed by a function with a higher address you will find the one
+   you want.  In fact, it may be a good idea to include a bit of
+   "context" in your problem report, giving a few lines around the
+   interesting one.
+
+   If you for some reason cannot do the above (you have a pre-compiled
+   kernel image or similar), telling me as much about your setup as
+   possible will help.  Please read the :ref:`admin-guide/reporting-bugs.rst <reportingbugs>`
+   document for details.
+
+ - Alternatively, you can use gdb on a running kernel. (read-only; i.e. you
+   cannot change values or set break points.) To do this, first compile the
+   kernel with -g; edit arch/x86/Makefile appropriately, then do a ``make
+   clean``. You'll also need to enable CONFIG_PROC_FS (via ``make config``).
+
+   After you've rebooted with the new kernel, do ``gdb vmlinux /proc/kcore``.
+   You can now use all the usual gdb commands. The command to look up the
+   point where your system crashed is ``l *0xXXXXXXXX``. (Replace the XXXes
+   with the EIP value.)
+
+   gdb'ing a non-running kernel currently fails because ``gdb`` (wrongly)
+   disregards the starting offset for which the kernel is compiled.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/reporting-bugs.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/reporting-bugs.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/reporting-bugs.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/reporting-bugs.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,182 @@
+.. _reportingbugs:
+
+Reporting bugs
+++++++++++++++
+
+Background
+==========
+
+The upstream Linux kernel maintainers only fix bugs for specific kernel
+versions.  Those versions include the current "release candidate" (or -rc)
+kernel, any "stable" kernel versions, and any "long term" kernels.
+
+Please see https://www.kernel.org/ for a list of supported kernels.  Any
+kernel marked with [EOL] is "end of life" and will not have any fixes
+backported to it.
+
+If you've found a bug on a kernel version that isn't listed on kernel.org,
+contact your Linux distribution or embedded vendor for support.
+Alternatively, you can attempt to run one of the supported stable or -rc
+kernels, and see if you can reproduce the bug on that.  It's preferable
+to reproduce the bug on the latest -rc kernel.
+
+
+How to report Linux kernel bugs
+===============================
+
+
+Identify the problematic subsystem
+----------------------------------
+
+Identifying which part of the Linux kernel might be causing your issue
+increases your chances of getting your bug fixed. Simply posting to the
+generic linux-kernel mailing list (LKML) may cause your bug report to be
+lost in the noise of a mailing list that gets 1000+ emails a day.
+
+Instead, try to figure out which kernel subsystem is causing the issue,
+and email that subsystem's maintainer and mailing list.  If the subsystem
+maintainer doesn't answer, then expand your scope to mailing lists like
+LKML.
+
+
+Identify who to notify
+----------------------
+
+Once you know the subsystem that is causing the issue, you should send a
+bug report.  Some maintainers prefer bugs to be reported via bugzilla
+(https://bugzilla.kernel.org), while others prefer that bugs be reported
+via the subsystem mailing list.
+
+To find out where to send an emailed bug report, find your subsystem or
+device driver in the MAINTAINERS file.  Search in the file for relevant
+entries, and send your bug report to the person(s) listed in the "M:"
+lines, making sure to Cc the mailing list(s) in the "L:" lines.  When the
+maintainer replies to you, make sure to 'Reply-all' in order to keep the
+public mailing list(s) in the email thread.
+
+If you know which driver is causing issues, you can pass one of the driver
+files to the get_maintainer.pl script::
+
+     perl scripts/get_maintainer.pl -f <filename>
+
+If it is a security bug, please copy the Security Contact listed in the
+MAINTAINERS file.  They can help coordinate bugfix and disclosure.  See
+:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>` for more information.
+
+If you can't figure out which subsystem caused the issue, you should file
+a bug in kernel.org bugzilla and send email to
+linux-kernel@vger.kernel.org, referencing the bugzilla URL.  (For more
+information on the linux-kernel mailing list see
+http://www.tux.org/lkml/).
+
+
+Tips for reporting bugs
+-----------------------
+
+If you haven't reported a bug before, please read:
+
+	http://www.chiark.greenend.org.uk/~sgtatham/bugs.html
+
+	http://www.catb.org/esr/faqs/smart-questions.html
+
+It's REALLY important to report bugs that seem unrelated as separate email
+threads or separate bugzilla entries.  If you report several unrelated
+bugs at once, it's difficult for maintainers to tease apart the relevant
+data.
+
+
+Gather information
+------------------
+
+The most important information in a bug report is how to reproduce the
+bug.  This includes system information, and (most importantly)
+step-by-step instructions for how a user can trigger the bug.
+
+If the failure includes an "OOPS:", take a picture of the screen, capture
+a netconsole trace, or type the message from your screen into the bug
+report.  Please read "Documentation/admin-guide/oops-tracing.rst" before posting your
+bug report. This explains what you should do with the "Oops" information
+to make it useful to the recipient.
+
+This is a suggested format for a bug report sent via email or bugzilla.
+Having a standardized bug report form makes it easier for you not to
+overlook things, and easier for the developers to find the pieces of
+information they're really interested in.  If some information is not
+relevant to your bug, feel free to exclude it.
+
+First run the ver_linux script included as scripts/ver_linux, which
+reports the version of some important subsystems.  Run this script with
+the command ``awk -f scripts/ver_linux``.
+
+Use that information to fill in all fields of the bug report form, and
+post it to the mailing list with a subject of "PROBLEM: <one line
+summary from [1.]>" for easy identification by the developers::
+
+  [1.] One line summary of the problem:
+  [2.] Full description of the problem/report:
+  [3.] Keywords (i.e., modules, networking, kernel):
+  [4.] Kernel information
+  [4.1.] Kernel version (from /proc/version):
+  [4.2.] Kernel .config file:
+  [5.] Most recent kernel version which did not have the bug:
+  [6.] Output of Oops.. message (if applicable) with symbolic information
+       resolved (see Documentation/admin-guide/oops-tracing.rst)
+  [7.] A small shell script or example program which triggers the
+       problem (if possible)
+  [8.] Environment
+  [8.1.] Software (add the output of the ver_linux script here)
+  [8.2.] Processor information (from /proc/cpuinfo):
+  [8.3.] Module information (from /proc/modules):
+  [8.4.] Loaded driver and hardware information (/proc/ioports, /proc/iomem)
+  [8.5.] PCI information ('lspci -vvv' as root)
+  [8.6.] SCSI information (from /proc/scsi/scsi)
+  [8.7.] Other information that might be relevant to the problem
+         (please look in /proc and include all information that you
+         think to be relevant):
+  [X.] Other notes, patches, fixes, workarounds:
+
+
+Follow up
+=========
+
+Expectations for bug reporters
+------------------------------
+
+Linux kernel maintainers expect bug reporters to be able to follow up on
+bug reports.  That may include running new tests, applying patches,
+recompiling your kernel, and/or re-triggering your bug.  The most
+frustrating thing for maintainers is for someone to report a bug, and then
+never follow up on a request to try out a fix.
+
+That said, it's still useful for a kernel maintainer to know a bug exists
+on a supported kernel, even if you can't follow up with retests.  Follow
+up reports, such as replying to the email thread with "I tried the latest
+kernel and I can't reproduce my bug anymore" are also helpful, because
+maintainers have to assume silence means things are still broken.
+
+Expectations for kernel maintainers
+-----------------------------------
+
+Linux kernel maintainers are busy, overworked human beings.  Some times
+they may not be able to address your bug in a day, a week, or two weeks.
+If they don't answer your email, they may be on vacation, or at a Linux
+conference.  Check the conference schedule at https://LWN.net for more info:
+
+	https://lwn.net/Calendar/
+
+In general, kernel maintainers take 1 to 5 business days to respond to
+bugs.  The majority of kernel maintainers are employed to work on the
+kernel, and they may not work on the weekends.  Maintainers are scattered
+around the world, and they may not work in your time zone.  Unless you
+have a high priority bug, please wait at least a week after the first bug
+report before sending the maintainer a reminder email.
+
+The exceptions to this rule are regressions, kernel crashes, security holes,
+or userspace breakage caused by new kernel behavior.  Those bugs should be
+addressed by the maintainers ASAP.  If you suspect a maintainer is not
+responding to these types of bugs in a timely manner (especially during a
+merge window), escalate the bug to LKML and Linus Torvalds.
+
+Thank you!
+
+[Some of this is taken from Frohwalt Egerer's original linux-kernel FAQ]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/security-bugs.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/security-bugs.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/security-bugs.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/security-bugs.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,46 @@
+.. _securitybugs:
+
+Security bugs
+=============
+
+Linux kernel developers take security very seriously.  As such, we'd
+like to know when a security bug is found so that it can be fixed and
+disclosed as quickly as possible.  Please report security bugs to the
+Linux kernel security team.
+
+Contact
+-------
+
+The Linux kernel security team can be contacted by email at
+<security@kernel.org>.  This is a private list of security officers
+who will help verify the bug report and develop and release a fix.
+It is possible that the security team will bring in extra help from
+area maintainers to understand and fix the security vulnerability.
+
+As it is with any bug, the more information provided the easier it
+will be to diagnose and fix.  Please review the procedure outlined in
+admin-guide/reporting-bugs.rst if you are unclear about what information is helpful.
+Any exploit code is very helpful and will not be released without
+consent from the reporter unless it has already been made public.
+
+Disclosure
+----------
+
+The goal of the Linux kernel security team is to work with the
+bug submitter to bug resolution as well as disclosure.  We prefer
+to fully disclose the bug as soon as possible.  It is reasonable to
+delay disclosure when the bug or the fix is not yet fully understood,
+the solution is not well-tested or for vendor coordination.  However, we
+expect these delays to be short, measurable in days, not weeks or months.
+A disclosure date is negotiated by the security team working with the
+bug submitter as well as vendors.  However, the kernel security team
+holds the final say when setting a disclosure date.  The timeframe for
+disclosure is from immediate (esp. if it's already publicly known)
+to a few weeks.  As a basic default policy, we expect report date to
+disclosure date to be on the order of 7 days.
+
+Non-disclosure agreements
+-------------------------
+
+The Linux kernel security team is not a formal body and therefore unable
+to enter any non-disclosure agreements.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/serial-console.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/serial-console.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/serial-console.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/serial-console.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,115 @@
+.. _serial_console:
+
+Linux Serial Console
+====================
+
+To use a serial port as console you need to compile the support into your
+kernel - by default it is not compiled in. For PC style serial ports
+it's the config option next to menu option:
+
+:menuselection:`Character devices --> Serial drivers --> 8250/16550 and compatible serial support --> Console on 8250/16550 and compatible serial port`
+
+You must compile serial support into the kernel and not as a module.
+
+It is possible to specify multiple devices for console output. You can
+define a new kernel command line option to select which device(s) to
+use for console output.
+
+The format of this option is::
+
+	console=device,options
+
+	device:		tty0 for the foreground virtual console
+			ttyX for any other virtual console
+			ttySx for a serial port
+			lp0 for the first parallel port
+			ttyUSB0 for the first USB serial device
+
+	options:	depend on the driver. For the serial port this
+			defines the baudrate/parity/bits/flow control of
+			the port, in the format BBBBPNF, where BBBB is the
+			speed, P is parity (n/o/e), N is number of bits,
+			and F is flow control ('r' for RTS). Default is
+			9600n8. The maximum baudrate is 115200.
+
+You can specify multiple console= options on the kernel command line.
+Output will appear on all of them. The last device will be used when
+you open ``/dev/console``. So, for example::
+
+	console=ttyS1,9600 console=tty0
+
+defines that opening ``/dev/console`` will get you the current foreground
+virtual console, and kernel messages will appear on both the VGA
+console and the 2nd serial port (ttyS1 or COM2) at 9600 baud.
+
+Note that you can only define one console per device type (serial, video).
+
+If no console device is specified, the first device found capable of
+acting as a system console will be used. At this time, the system
+first looks for a VGA card and then for a serial port. So if you don't
+have a VGA card in your system the first serial port will automatically
+become the console.
+
+You will need to create a new device to use ``/dev/console``. The official
+``/dev/console`` is now character device 5,1.
+
+(You can also use a network device as a console.  See
+``Documentation/networking/netconsole.txt`` for information on that.)
+
+Here's an example that will use ``/dev/ttyS1`` (COM2) as the console.
+Replace the sample values as needed.
+
+1. Create ``/dev/console`` (real console) and ``/dev/tty0`` (master virtual
+   console)::
+
+     cd /dev
+     rm -f console tty0
+     mknod -m 622 console c 5 1
+     mknod -m 622 tty0 c 4 0
+
+2. LILO can also take input from a serial device. This is a very
+   useful option. To tell LILO to use the serial port:
+   In lilo.conf (global section)::
+
+     serial  = 1,9600n8 (ttyS1, 9600 bd, no parity, 8 bits)
+
+3. Adjust to kernel flags for the new kernel,
+   again in lilo.conf (kernel section)::
+
+     append = "console=ttyS1,9600"
+
+4. Make sure a getty runs on the serial port so that you can login to
+   it once the system is done booting. This is done by adding a line
+   like this to ``/etc/inittab`` (exact syntax depends on your getty)::
+
+     S1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
+
+5. Init and ``/etc/ioctl.save``
+
+   Sysvinit remembers its stty settings in a file in ``/etc``, called
+   ``/etc/ioctl.save``. REMOVE THIS FILE before using the serial
+   console for the first time, because otherwise init will probably
+   set the baudrate to 38400 (baudrate of the virtual console).
+
+6. ``/dev/console`` and X
+   Programs that want to do something with the virtual console usually
+   open ``/dev/console``. If you have created the new ``/dev/console`` device,
+   and your console is NOT the virtual console some programs will fail.
+   Those are programs that want to access the VT interface, and use
+   ``/dev/console instead of /dev/tty0``. Some of those programs are::
+
+     Xfree86, svgalib, gpm, SVGATextMode
+
+   It should be fixed in modern versions of these programs though.
+
+   Note that if you boot without a ``console=`` option (or with
+   ``console=/dev/tty0``), ``/dev/console`` is the same as ``/dev/tty0``.
+   In that case everything will still work.
+
+7. Thanks
+
+   Thanks to Geert Uytterhoeven <geert@linux-m68k.org>
+   for porting the patches from 2.1.4x to 2.1.6x for taking care of
+   the integration of these patches into m68k, ppc and alpha.
+
+Miquel van Smoorenburg <miquels@cistron.nl>, 11-Jun-2000
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/sysfs-rules.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/sysfs-rules.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/sysfs-rules.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/sysfs-rules.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,192 @@
+Rules on how to access information in sysfs
+===========================================
+
+The kernel-exported sysfs exports internal kernel implementation details
+and depends on internal kernel structures and layout. It is agreed upon
+by the kernel developers that the Linux kernel does not provide a stable
+internal API. Therefore, there are aspects of the sysfs interface that
+may not be stable across kernel releases.
+
+To minimize the risk of breaking users of sysfs, which are in most cases
+low-level userspace applications, with a new kernel release, the users
+of sysfs must follow some rules to use an as-abstract-as-possible way to
+access this filesystem. The current udev and HAL programs already
+implement this and users are encouraged to plug, if possible, into the
+abstractions these programs provide instead of accessing sysfs directly.
+
+But if you really do want or need to access sysfs directly, please follow
+the following rules and then your programs should work with future
+versions of the sysfs interface.
+
+- Do not use libsysfs
+    It makes assumptions about sysfs which are not true. Its API does not
+    offer any abstraction, it exposes all the kernel driver-core
+    implementation details in its own API. Therefore it is not better than
+    reading directories and opening the files yourself.
+    Also, it is not actively maintained, in the sense of reflecting the
+    current kernel development. The goal of providing a stable interface
+    to sysfs has failed; it causes more problems than it solves. It
+    violates many of the rules in this document.
+
+- sysfs is always at ``/sys``
+    Parsing ``/proc/mounts`` is a waste of time. Other mount points are a
+    system configuration bug you should not try to solve. For test cases,
+    possibly support a ``SYSFS_PATH`` environment variable to overwrite the
+    application's behavior, but never try to search for sysfs. Never try
+    to mount it, if you are not an early boot script.
+
+- devices are only "devices"
+    There is no such thing like class-, bus-, physical devices,
+    interfaces, and such that you can rely on in userspace. Everything is
+    just simply a "device". Class-, bus-, physical, ... types are just
+    kernel implementation details which should not be expected by
+    applications that look for devices in sysfs.
+
+    The properties of a device are:
+
+    - devpath (``/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0``)
+
+      - identical to the DEVPATH value in the event sent from the kernel
+        at device creation and removal
+      - the unique key to the device at that point in time
+      - the kernel's path to the device directory without the leading
+        ``/sys``, and always starting with a slash
+      - all elements of a devpath must be real directories. Symlinks
+        pointing to /sys/devices must always be resolved to their real
+        target and the target path must be used to access the device.
+        That way the devpath to the device matches the devpath of the
+        kernel used at event time.
+      - using or exposing symlink values as elements in a devpath string
+        is a bug in the application
+
+    - kernel name (``sda``, ``tty``, ``0000:00:1f.2``, ...)
+
+      - a directory name, identical to the last element of the devpath
+      - applications need to handle spaces and characters like ``!`` in
+        the name
+
+    - subsystem (``block``, ``tty``, ``pci``, ...)
+
+      - simple string, never a path or a link
+      - retrieved by reading the "subsystem"-link and using only the
+        last element of the target path
+
+    - driver (``tg3``, ``ata_piix``, ``uhci_hcd``)
+
+      - a simple string, which may contain spaces, never a path or a
+        link
+      - it is retrieved by reading the "driver"-link and using only the
+        last element of the target path
+      - devices which do not have "driver"-link just do not have a
+        driver; copying the driver value in a child device context is a
+        bug in the application
+
+    - attributes
+
+      - the files in the device directory or files below subdirectories
+        of the same device directory
+      - accessing attributes reached by a symlink pointing to another device,
+        like the "device"-link, is a bug in the application
+
+    Everything else is just a kernel driver-core implementation detail
+    that should not be assumed to be stable across kernel releases.
+
+- Properties of parent devices never belong into a child device.
+    Always look at the parent devices themselves for determining device
+    context properties. If the device ``eth0`` or ``sda`` does not have a
+    "driver"-link, then this device does not have a driver. Its value is empty.
+    Never copy any property of the parent-device into a child-device. Parent
+    device properties may change dynamically without any notice to the
+    child device.
+
+- Hierarchy in a single device tree
+    There is only one valid place in sysfs where hierarchy can be examined
+    and this is below: ``/sys/devices.``
+    It is planned that all device directories will end up in the tree
+    below this directory.
+
+- Classification by subsystem
+    There are currently three places for classification of devices:
+    ``/sys/block,`` ``/sys/class`` and ``/sys/bus.`` It is planned that these will
+    not contain any device directories themselves, but only flat lists of
+    symlinks pointing to the unified ``/sys/devices`` tree.
+    All three places have completely different rules on how to access
+    device information. It is planned to merge all three
+    classification directories into one place at ``/sys/subsystem``,
+    following the layout of the bus directories. All buses and
+    classes, including the converted block subsystem, will show up
+    there.
+    The devices belonging to a subsystem will create a symlink in the
+    "devices" directory at ``/sys/subsystem/<name>/devices``,
+
+    If ``/sys/subsystem`` exists, ``/sys/bus``, ``/sys/class`` and ``/sys/block``
+    can be ignored. If it does not exist, you always have to scan all three
+    places, as the kernel is free to move a subsystem from one place to
+    the other, as long as the devices are still reachable by the same
+    subsystem name.
+
+    Assuming ``/sys/class/<subsystem>`` and ``/sys/bus/<subsystem>``, or
+    ``/sys/block`` and ``/sys/class/block`` are not interchangeable is a bug in
+    the application.
+
+- Block
+    The converted block subsystem at ``/sys/class/block`` or
+    ``/sys/subsystem/block`` will contain the links for disks and partitions
+    at the same level, never in a hierarchy. Assuming the block subsystem to
+    contain only disks and not partition devices in the same flat list is
+    a bug in the application.
+
+- "device"-link and <subsystem>:<kernel name>-links
+    Never depend on the "device"-link. The "device"-link is a workaround
+    for the old layout, where class devices are not created in
+    ``/sys/devices/`` like the bus devices. If the link-resolving of a
+    device directory does not end in ``/sys/devices/``, you can use the
+    "device"-link to find the parent devices in ``/sys/devices/``, That is the
+    single valid use of the "device"-link; it must never appear in any
+    path as an element. Assuming the existence of the "device"-link for
+    a device in ``/sys/devices/`` is a bug in the application.
+    Accessing ``/sys/class/net/eth0/device`` is a bug in the application.
+
+    Never depend on the class-specific links back to the ``/sys/class``
+    directory.  These links are also a workaround for the design mistake
+    that class devices are not created in ``/sys/devices.`` If a device
+    directory does not contain directories for child devices, these links
+    may be used to find the child devices in ``/sys/class.`` That is the single
+    valid use of these links; they must never appear in any path as an
+    element. Assuming the existence of these links for devices which are
+    real child device directories in the ``/sys/devices`` tree is a bug in
+    the application.
+
+    It is planned to remove all these links when all class device
+    directories live in ``/sys/devices.``
+
+- Position of devices along device chain can change.
+    Never depend on a specific parent device position in the devpath,
+    or the chain of parent devices. The kernel is free to insert devices into
+    the chain. You must always request the parent device you are looking for
+    by its subsystem value. You need to walk up the chain until you find
+    the device that matches the expected subsystem. Depending on a specific
+    position of a parent device or exposing relative paths using ``../`` to
+    access the chain of parents is a bug in the application.
+
+- When reading and writing sysfs device attribute files, avoid dependency
+    on specific error codes wherever possible. This minimizes coupling to
+    the error handling implementation within the kernel.
+
+    In general, failures to read or write sysfs device attributes shall
+    propagate errors wherever possible. Common errors include, but are not
+    limited to:
+
+	``-EIO``: The read or store operation is not supported, typically
+	returned by the sysfs system itself if the read or store pointer
+	is ``NULL``.
+
+	``-ENXIO``: The read or store operation failed
+
+    Error codes will not be changed without good reason, and should a change
+    to error codes result in user-space breakage, it will be fixed, or the
+    the offending change will be reverted.
+
+    Userspace applications can, however, expect the format and contents of
+    the attribute files to remain consistent in the absence of a version
+    attribute change in the context of a given attribute.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/sysrq.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/sysrq.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/sysrq.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/sysrq.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,289 @@
+Linux Magic System Request Key Hacks
+====================================
+
+Documentation for sysrq.c
+
+What is the magic SysRq key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is a 'magical' key combo you can hit which the kernel will respond to
+regardless of whatever else it is doing, unless it is completely locked up.
+
+How do I enable the magic SysRq key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
+configuring the kernel. When running a kernel with SysRq compiled in,
+/proc/sys/kernel/sysrq controls the functions allowed to be invoked via
+the SysRq key. The default value in this file is set by the
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults
+to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
+
+   -  0 - disable sysrq completely
+   -  1 - enable all functions of sysrq
+   - >1 - bitmask of allowed sysrq functions (see below for detailed function
+     description)::
+
+          2 =   0x2 - enable control of console logging level
+          4 =   0x4 - enable control of keyboard (SAK, unraw)
+          8 =   0x8 - enable debugging dumps of processes etc.
+         16 =  0x10 - enable sync command
+         32 =  0x20 - enable remount read-only
+         64 =  0x40 - enable signalling of processes (term, kill, oom-kill)
+        128 =  0x80 - allow reboot/poweroff
+        256 = 0x100 - allow nicing of all RT tasks
+
+You can set the value in the file by the following command::
+
+    echo "number" >/proc/sys/kernel/sysrq
+
+The number may be written here either as decimal or as hexadecimal
+with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be
+written in hexadecimal.
+
+Note that the value of ``/proc/sys/kernel/sysrq`` influences only the invocation
+via a keyboard. Invocation of any operation via ``/proc/sysrq-trigger`` is
+always allowed (by a user with admin privileges).
+
+How do I use the magic SysRq key?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On x86   - You press the key combo :kbd:`ALT-SysRq-<command key>`.
+
+.. note::
+	   Some
+           keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
+           also known as the 'Print Screen' key. Also some keyboards cannot
+	   handle so many keys being pressed at the same time, so you might
+	   have better luck with press :kbd:`Alt`, press :kbd:`SysRq`,
+	   release :kbd:`SysRq`, press :kbd:`<command key>`, release everything.
+
+On SPARC - You press :kbd:`ALT-STOP-<command key>`, I believe.
+
+On the serial console (PC style standard serial ports only)
+        You send a ``BREAK``, then within 5 seconds a command key. Sending
+        ``BREAK`` twice is interpreted as a normal BREAK.
+
+On PowerPC
+	Press :kbd:`ALT - Print Screen` (or :kbd:`F13`) - :kbd:`<command key>`,
+        :kbd:`Print Screen` (or :kbd:`F13`) - :kbd:`<command key>` may suffice.
+
+On other
+	If you know of the key combos for other architectures, please
+        let me know so I can add them to this section.
+
+On all
+	write a character to /proc/sysrq-trigger.  e.g.::
+
+		echo t > /proc/sysrq-trigger
+
+What are the 'command' keys?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+=========== ===================================================================
+Command	    Function
+=========== ===================================================================
+``b``	    Will immediately reboot the system without syncing or unmounting
+            your disks.
+
+``c``	    Will perform a system crash by a NULL pointer dereference.
+            A crashdump will be taken if configured.
+
+``d``	    Shows all locks that are held.
+
+``e``	    Send a SIGTERM to all processes, except for init.
+
+``f``	    Will call the oom killer to kill a memory hog process, but do not
+	    panic if nothing can be killed.
+
+``g``	    Used by kgdb (kernel debugger)
+
+``h``	    Will display help (actually any other key than those listed
+            here will display help. but ``h`` is easy to remember :-)
+
+``i``	    Send a SIGKILL to all processes, except for init.
+
+``j``	    Forcibly "Just thaw it" - filesystems frozen by the FIFREEZE ioctl.
+
+``k``	    Secure Access Key (SAK) Kills all programs on the current virtual
+            console. NOTE: See important comments below in SAK section.
+
+``l``	    Shows a stack backtrace for all active CPUs.
+
+``m``	    Will dump current memory info to your console.
+
+``n``	    Used to make RT tasks nice-able
+
+``o``	    Will shut your system off (if configured and supported).
+
+``p``	    Will dump the current registers and flags to your console.
+
+``q``	    Will dump per CPU lists of all armed hrtimers (but NOT regular
+            timer_list timers) and detailed information about all
+            clockevent devices.
+
+``r``	    Turns off keyboard raw mode and sets it to XLATE.
+
+``s``	    Will attempt to sync all mounted filesystems.
+
+``t``	    Will dump a list of current tasks and their information to your
+            console.
+
+``u``	    Will attempt to remount all mounted filesystems read-only.
+
+``v``	    Forcefully restores framebuffer console
+``v``	    Causes ETM buffer dump [ARM-specific]
+
+``w``	    Dumps tasks that are in uninterruptable (blocked) state.
+
+``x``	    Used by xmon interface on ppc/powerpc platforms.
+            Show global PMU Registers on sparc64.
+            Dump all TLB entries on MIPS.
+
+``y``	    Show global CPU Registers [SPARC-64 specific]
+
+``z``	    Dump the ftrace buffer
+
+``0``-``9`` Sets the console log level, controlling which kernel messages
+            will be printed to your console. (``0``, for example would make
+            it so that only emergency messages like PANICs or OOPSes would
+            make it to your console.)
+=========== ===================================================================
+
+Okay, so what can I use them for?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Well, unraw(r) is very handy when your X server or a svgalib program crashes.
+
+sak(k) (Secure Access Key) is useful when you want to be sure there is no
+trojan program running at console which could grab your password
+when you would try to login. It will kill all programs on given console,
+thus letting you make sure that the login prompt you see is actually
+the one from init, not some trojan program.
+
+.. important::
+
+   In its true form it is not a true SAK like the one in a
+   c2 compliant system, and it should not be mistaken as
+   such.
+
+It seems others find it useful as (System Attention Key) which is
+useful when you want to exit a program that will not let you switch consoles.
+(For example, X or a svgalib program.)
+
+``reboot(b)`` is good when you're unable to shut down. But you should also
+``sync(s)`` and ``umount(u)`` first.
+
+``crash(c)`` can be used to manually trigger a crashdump when the system is hung.
+Note that this just triggers a crash if there is no dump mechanism available.
+
+``sync(s)`` is great when your system is locked up, it allows you to sync your
+disks and will certainly lessen the chance of data loss and fscking. Note
+that the sync hasn't taken place until you see the "OK" and "Done" appear
+on the screen. (If the kernel is really in strife, you may not ever get the
+OK or Done message...)
+
+``umount(u)`` is basically useful in the same ways as ``sync(s)``. I generally
+``sync(s)``, ``umount(u)``, then ``reboot(b)`` when my system locks. It's saved
+me many a fsck. Again, the unmount (remount read-only) hasn't taken place until
+you see the "OK" and "Done" message appear on the screen.
+
+The loglevels ``0``-``9`` are useful when your console is being flooded with
+kernel messages you do not want to see. Selecting ``0`` will prevent all but
+the most urgent kernel messages from reaching your console. (They will
+still be logged if syslogd/klogd are alive, though.)
+
+``term(e)`` and ``kill(i)`` are useful if you have some sort of runaway process
+you are unable to kill any other way, especially if it's spawning other
+processes.
+
+"just thaw ``it(j)``" is useful if your system becomes unresponsive due to a
+frozen (probably root) filesystem via the FIFREEZE ioctl.
+
+Sometimes SysRq seems to get 'stuck' after using it, what can I do?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+That happens to me, also. I've found that tapping shift, alt, and control
+on both sides of the keyboard, and hitting an invalid sysrq sequence again
+will fix the problem. (i.e., something like :kbd:`alt-sysrq-z`). Switching to
+another virtual console (:kbd:`ALT+Fn`) and then back again should also help.
+
+I hit SysRq, but nothing seems to happen, what's wrong?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are some keyboards that produce a different keycode for SysRq than the
+pre-defined value of 99 (see ``KEY_SYSRQ`` in ``include/linux/input.h``), or
+which don't have a SysRq key at all. In these cases, run ``showkey -s`` to find
+an appropriate scancode sequence, and use ``setkeycodes <sequence> 99`` to map
+this sequence to the usual SysRq code (e.g., ``setkeycodes e05b 99``). It's
+probably best to put this command in a boot script. Oh, and by the way, you
+exit ``showkey`` by not typing anything for ten seconds.
+
+I want to add SysRQ key events to a module, how does it work?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to register a basic function with the table, you must first include
+the header ``include/linux/sysrq.h``, this will define everything else you need.
+Next, you must create a ``sysrq_key_op`` struct, and populate it with A) the key
+handler function you will use, B) a help_msg string, that will print when SysRQ
+prints help, and C) an action_msg string, that will print right before your
+handler is called. Your handler must conform to the prototype in 'sysrq.h'.
+
+After the ``sysrq_key_op`` is created, you can call the kernel function
+``register_sysrq_key(int key, struct sysrq_key_op *op_p);`` this will
+register the operation pointed to by ``op_p`` at table key 'key',
+if that slot in the table is blank. At module unload time, you must call
+the function ``unregister_sysrq_key(int key, struct sysrq_key_op *op_p)``, which
+will remove the key op pointed to by 'op_p' from the key 'key', if and only if
+it is currently registered in that slot. This is in case the slot has been
+overwritten since you registered it.
+
+The Magic SysRQ system works by registering key operations against a key op
+lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
+a number of operations registered into it at compile time, but is mutable,
+and 2 functions are exported for interface to it::
+
+	register_sysrq_key and unregister_sysrq_key.
+
+Of course, never ever leave an invalid pointer in the table. I.e., when
+your module that called register_sysrq_key() exits, it must call
+unregister_sysrq_key() to clean up the sysrq key table entry that it used.
+Null pointers in the table are always safe. :)
+
+If for some reason you feel the need to call the handle_sysrq function from
+within a function called by handle_sysrq, you must be aware that you are in
+a lock (you are also in an interrupt handler, which means don't sleep!), so
+you must call ``__handle_sysrq_nolock`` instead.
+
+When I hit a SysRq key combination only the header appears on the console?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sysrq output is subject to the same console loglevel control as all
+other console output.  This means that if the kernel was booted 'quiet'
+as is common on distro kernels the output may not appear on the actual
+console, even though it will appear in the dmesg buffer, and be accessible
+via the dmesg command and to the consumers of ``/proc/kmsg``.  As a specific
+exception the header line from the sysrq command is passed to all console
+consumers as if the current loglevel was maximum.  If only the header
+is emitted it is almost certain that the kernel loglevel is too low.
+Should you require the output on the console channel then you will need
+to temporarily up the console loglevel using :kbd:`alt-sysrq-8` or::
+
+    echo 8 > /proc/sysrq-trigger
+
+Remember to return the loglevel to normal after triggering the sysrq
+command you are interested in.
+
+I have more questions, who can I ask?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Just ask them on the linux-kernel mailing list:
+	linux-kernel@vger.kernel.org
+
+Credits
+~~~~~~~
+
+Written by Mydraal <vulpyne@vulpyne.net>
+Updated by Adam Sulmicki <adam@cfar.umd.edu>
+Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
+Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/tainted-kernels.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/tainted-kernels.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/tainted-kernels.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/tainted-kernels.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,59 @@
+Tainted kernels
+---------------
+
+Some oops reports contain the string **'Tainted: '** after the program
+counter. This indicates that the kernel has been tainted by some
+mechanism.  The string is followed by a series of position-sensitive
+characters, each representing a particular tainted value.
+
+  1) 'G' if all modules loaded have a GPL or compatible license, 'P' if
+     any proprietary module has been loaded.  Modules without a
+     MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
+     insmod as GPL compatible are assumed to be proprietary.
+
+  2) ``F`` if any module was force loaded by ``insmod -f``, ``' '`` if all
+     modules were loaded normally.
+
+  3) ``S`` if the oops occurred on an SMP kernel running on hardware that
+     hasn't been certified as safe to run multiprocessor.
+     Currently this occurs only on various Athlons that are not
+     SMP capable.
+
+  4) ``R`` if a module was force unloaded by ``rmmod -f``, ``' '`` if all
+     modules were unloaded normally.
+
+  5) ``M`` if any processor has reported a Machine Check Exception,
+     ``' '`` if no Machine Check Exceptions have occurred.
+
+  6) ``B`` if a page-release function has found a bad page reference or
+     some unexpected page flags.
+
+  7) ``U`` if a user or user application specifically requested that the
+     Tainted flag be set, ``' '`` otherwise.
+
+  8) ``D`` if the kernel has died recently, i.e. there was an OOPS or BUG.
+
+  9) ``A`` if the ACPI table has been overridden.
+
+ 10) ``W`` if a warning has previously been issued by the kernel.
+     (Though some warnings may set more specific taint flags.)
+
+ 11) ``C`` if a staging driver has been loaded.
+
+ 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.
+
+ 14) ``E`` if an unsigned module has been loaded in a kernel supporting
+     module signature.
+
+ 15) ``L`` if a soft lockup has previously occurred on the system.
+
+ 16) ``K`` if the kernel has been live patched.
+
+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
+unloaded, the tainted value remains to indicate that the kernel is not
+trustworthy.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/unicode.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/unicode.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/unicode.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/unicode.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,189 @@
+Unicode support
+===============
+
+		 Last update: 2005-01-17, version 1.4
+
+This file is maintained by H. Peter Anvin <unicode@lanana.org> as part
+of the Linux Assigned Names And Numbers Authority (LANANA) project.
+The current version can be found at:
+
+	    http://www.lanana.org/docs/unicode/admin-guide/unicode.rst
+
+Introduction
+------------
+
+The Linux kernel code has been rewritten to use Unicode to map
+characters to fonts.  By downloading a single Unicode-to-font table,
+both the eight-bit character sets and UTF-8 mode are changed to use
+the font as indicated.
+
+This changes the semantics of the eight-bit character tables subtly.
+The four character tables are now:
+
+=============== =============================== ================
+Map symbol	Map name			Escape code (G0)
+=============== =============================== ================
+LAT1_MAP	Latin-1 (ISO 8859-1)		ESC ( B
+GRAF_MAP	DEC VT100 pseudographics	ESC ( 0
+IBMPC_MAP	IBM code page 437		ESC ( U
+USER_MAP	User defined			ESC ( K
+=============== =============================== ================
+
+In particular, ESC ( U is no longer "straight to font", since the font
+might be completely different than the IBM character set.  This
+permits for example the use of block graphics even with a Latin-1 font
+loaded.
+
+Note that although these codes are similar to ISO 2022, neither the
+codes nor their uses match ISO 2022; Linux has two 8-bit codes (G0 and
+G1), whereas ISO 2022 has four 7-bit codes (G0-G3).
+
+In accordance with the Unicode standard/ISO 10646 the range U+F000 to
+U+F8FF has been reserved for OS-wide allocation (the Unicode Standard
+refers to this as a "Corporate Zone", since this is inaccurate for
+Linux we call it the "Linux Zone").  U+F000 was picked as the starting
+point since it lets the direct-mapping area start on a large power of
+two (in case 1024- or 2048-character fonts ever become necessary).
+This leaves U+E000 to U+EFFF as End User Zone.
+
+[v1.2]: The Unicodes range from U+F000 and up to U+F7FF have been
+hard-coded to map directly to the loaded font, bypassing the
+translation table.  The user-defined map now defaults to U+F000 to
+U+F0FF, emulating the previous behaviour.  In practice, this range
+might be shorter; for example, vgacon can only handle 256-character
+(U+F000..U+F0FF) or 512-character (U+F000..U+F1FF) fonts.
+
+
+Actual characters assigned in the Linux Zone
+--------------------------------------------
+
+In addition, the following characters not present in Unicode 1.1.4
+have been defined; these are used by the DEC VT graphics map.  [v1.2]
+THIS USE IS OBSOLETE AND SHOULD NO LONGER BE USED; PLEASE SEE BELOW.
+
+====== ======================================
+U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
+U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
+U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
+U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
+====== ======================================
+
+The DEC VT220 uses a 6x10 character matrix, and these characters form
+a smooth progression in the DEC VT graphics character set.  I have
+omitted the scan 5 line, since it is also used as a block-graphics
+character, and hence has been coded as U+2500 FORMS LIGHT HORIZONTAL.
+
+[v1.3]: These characters have been officially added to Unicode 3.2.0;
+they are added at U+23BA, U+23BB, U+23BC, U+23BD.  Linux now uses the
+new values.
+
+[v1.2]: The following characters have been added to represent common
+keyboard symbols that are unlikely to ever be added to Unicode proper
+since they are horribly vendor-specific.  This, of course, is an
+excellent example of horrible design.
+
+====== ======================================
+U+F810 KEYBOARD SYMBOL FLYING FLAG
+U+F811 KEYBOARD SYMBOL PULLDOWN MENU
+U+F812 KEYBOARD SYMBOL OPEN APPLE
+U+F813 KEYBOARD SYMBOL SOLID APPLE
+====== ======================================
+
+Klingon language support
+------------------------
+
+In 1996, Linux was the first operating system in the world to add
+support for the artificial language Klingon, created by Marc Okrand
+for the "Star Trek" television series.	This encoding was later
+adopted by the ConScript Unicode Registry and proposed (but ultimately
+rejected) for inclusion in Unicode Plane 1.  Thus, it remains as a
+Linux/CSUR private assignment in the Linux Zone.
+
+This encoding has been endorsed by the Klingon Language Institute.
+For more information, contact them at:
+
+	http://www.kli.org/
+
+Since the characters in the beginning of the Linux CZ have been more
+of the dingbats/symbols/forms type and this is a language, I have
+located it at the end, on a 16-cell boundary in keeping with standard
+Unicode practice.
+
+.. note::
+
+  This range is now officially managed by the ConScript Unicode
+  Registry.  The normative reference is at:
+
+	http://www.evertype.com/standards/csur/klingon.html
+
+Klingon has an alphabet of 26 characters, a positional numeric writing
+system with 10 digits, and is written left-to-right, top-to-bottom.
+
+Several glyph forms for the Klingon alphabet have been proposed.
+However, since the set of symbols appear to be consistent throughout,
+with only the actual shapes being different, in keeping with standard
+Unicode practice these differences are considered font variants.
+
+======	=======================================================
+U+F8D0	KLINGON LETTER A
+U+F8D1	KLINGON LETTER B
+U+F8D2	KLINGON LETTER CH
+U+F8D3	KLINGON LETTER D
+U+F8D4	KLINGON LETTER E
+U+F8D5	KLINGON LETTER GH
+U+F8D6	KLINGON LETTER H
+U+F8D7	KLINGON LETTER I
+U+F8D8	KLINGON LETTER J
+U+F8D9	KLINGON LETTER L
+U+F8DA	KLINGON LETTER M
+U+F8DB	KLINGON LETTER N
+U+F8DC	KLINGON LETTER NG
+U+F8DD	KLINGON LETTER O
+U+F8DE	KLINGON LETTER P
+U+F8DF	KLINGON LETTER Q
+	- Written <q> in standard Okrand Latin transliteration
+U+F8E0	KLINGON LETTER QH
+	- Written <Q> in standard Okrand Latin transliteration
+U+F8E1	KLINGON LETTER R
+U+F8E2	KLINGON LETTER S
+U+F8E3	KLINGON LETTER T
+U+F8E4	KLINGON LETTER TLH
+U+F8E5	KLINGON LETTER U
+U+F8E6	KLINGON LETTER V
+U+F8E7	KLINGON LETTER W
+U+F8E8	KLINGON LETTER Y
+U+F8E9	KLINGON LETTER GLOTTAL STOP
+
+U+F8F0	KLINGON DIGIT ZERO
+U+F8F1	KLINGON DIGIT ONE
+U+F8F2	KLINGON DIGIT TWO
+U+F8F3	KLINGON DIGIT THREE
+U+F8F4	KLINGON DIGIT FOUR
+U+F8F5	KLINGON DIGIT FIVE
+U+F8F6	KLINGON DIGIT SIX
+U+F8F7	KLINGON DIGIT SEVEN
+U+F8F8	KLINGON DIGIT EIGHT
+U+F8F9	KLINGON DIGIT NINE
+
+U+F8FD	KLINGON COMMA
+U+F8FE	KLINGON FULL STOP
+U+F8FF	KLINGON SYMBOL FOR EMPIRE
+======	=======================================================
+
+Other Fictional and Artificial Scripts
+--------------------------------------
+
+Since the assignment of the Klingon Linux Unicode block, a registry of
+fictional and artificial scripts has been established by John Cowan
+<jcowan@reutershealth.com> and Michael Everson <everson@evertype.com>.
+The ConScript Unicode Registry is accessible at:
+
+	  http://www.evertype.com/standards/csur/
+
+The ranges used fall at the low end of the End User Zone and can hence
+not be normatively assigned, but it is recommended that people who
+wish to encode fictional scripts use these codes, in the interest of
+interoperability.  For Klingon, CSUR has adopted the Linux encoding.
+The CSUR people are driving adding Tengwar and Cirth into Unicode
+Plane 1; the addition of Klingon to Unicode Plane 1 has been rejected
+and so the above encoding remains official.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/admin-guide/vga-softcursor.rst linux-libre-4.10-rc8-gnu/Documentation/admin-guide/vga-softcursor.rst
--- linux-libre-4.9-gnu/Documentation/admin-guide/vga-softcursor.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/admin-guide/vga-softcursor.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,62 @@
+Software cursor for VGA
+=======================
+
+by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
+and Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
+Linux now has some ability to manipulate cursor appearance.  Normally,
+you can set the size of hardware cursor.  You can now play a few new
+tricks: you can make your cursor look like a non-blinking red block,
+make it inverse background of the character it's over or to highlight
+that character and still choose whether the original hardware cursor
+should remain visible or not.  There may be other things I have never
+thought of.
+
+The cursor appearance is controlled by a ``<ESC>[?1;2;3c`` escape sequence
+where 1, 2 and 3 are parameters described below. If you omit any of them,
+they will default to zeroes.
+
+first Parameter
+	specifies cursor size::
+
+		0=default
+		1=invisible
+		2=underline,
+		...
+		8=full block
+		+ 16 if you want the software cursor to be applied
+		+ 32 if you want to always change the background color
+		+ 64 if you dislike having the background the same as the
+		     foreground.
+
+	Highlights are ignored for the last two flags.
+
+second parameter
+	selects character attribute bits you want to change
+	(by simply XORing them with the value of this parameter). On standard
+	VGA, the high four bits specify background and the low four the
+	foreground. In both groups, low three bits set color (as in normal
+	color codes used by the console) and the most significant one turns
+	on highlight (or sometimes blinking -- it depends on the configuration
+	of your VGA).
+
+third parameter
+	consists of character attribute bits you want to set.
+
+	Bit setting takes place before bit toggling, so you can simply clear a
+	bit by including it in both the set mask and the toggle mask.
+
+Examples
+--------
+
+To get normal blinking underline, use::
+
+	echo -e '\033[?2c'
+
+To get blinking block, use::
+
+	echo -e '\033[?6c'
+
+To get red non-blinking block, use::
+
+	echo -e '\033[?17;0;64c'
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/applying-patches.txt linux-libre-4.10-rc8-gnu/Documentation/applying-patches.txt
--- linux-libre-4.9-gnu/Documentation/applying-patches.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/applying-patches.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,465 +0,0 @@
-.. _applying_patches:
-
-Applying Patches To The Linux Kernel
-++++++++++++++++++++++++++++++++++++
-
-Original by:
-	Jesper Juhl, August 2005
-
-Last update:
-	2016-09-14
-
-
-A frequently asked question on the Linux Kernel Mailing List is how to apply
-a patch to the kernel or, more specifically, what base kernel a patch for
-one of the many trees/branches should be applied to. Hopefully this document
-will explain this to you.
-
-In addition to explaining how to apply and revert patches, a brief
-description of the different kernel trees (and examples of how to apply
-their specific patches) is also provided.
-
-
-What is a patch?
-================
-
-A patch is a small text document containing a delta of changes between two
-different versions of a source tree. Patches are created with the ``diff``
-program.
-
-To correctly apply a patch you need to know what base it was generated from
-and what new version the patch will change the source tree into. These
-should both be present in the patch file metadata or be possible to deduce
-from the filename.
-
-
-How do I apply or revert a patch?
-=================================
-
-You apply a patch with the ``patch`` program. The patch program reads a diff
-(or patch) file and makes the changes to the source tree described in it.
-
-Patches for the Linux kernel are generated relative to the parent directory
-holding the kernel source dir.
-
-This means that paths to files inside the patch file contain the name of the
-kernel source directories it was generated against (or some other directory
-names like "a/" and "b/").
-
-Since this is unlikely to match the name of the kernel source dir on your
-local machine (but is often useful info to see what version an otherwise
-unlabeled patch was generated against) you should change into your kernel
-source directory and then strip the first element of the path from filenames
-in the patch file when applying it (the ``-p1`` argument to ``patch`` does
-this).
-
-To revert a previously applied patch, use the -R argument to patch.
-So, if you applied a patch like this::
-
-	patch -p1 < ../patch-x.y.z
-
-You can revert (undo) it like this::
-
-	patch -R -p1 < ../patch-x.y.z
-
-
-How do I feed a patch/diff file to ``patch``?
-=============================================
-
-This (as usual with Linux and other UNIX like operating systems) can be
-done in several different ways.
-
-In all the examples below I feed the file (in uncompressed form) to patch
-via stdin using the following syntax::
-
-	patch -p1 < path/to/patch-x.y.z
-
-If you just want to be able to follow the examples below and don't want to
-know of more than one way to use patch, then you can stop reading this
-section here.
-
-Patch can also get the name of the file to use via the -i argument, like
-this::
-
-	patch -p1 -i path/to/patch-x.y.z
-
-If your patch file is compressed with gzip or xz and you don't want to
-uncompress it before applying it, then you can feed it to patch like this
-instead::
-
-	xzcat path/to/patch-x.y.z.xz | patch -p1
-	bzcat path/to/patch-x.y.z.gz | patch -p1
-
-If you wish to uncompress the patch file by hand first before applying it
-(what I assume you've done in the examples below), then you simply run
-gunzip or xz on the file -- like this::
-
-	gunzip patch-x.y.z.gz
-	xz -d patch-x.y.z.xz
-
-Which will leave you with a plain text patch-x.y.z file that you can feed to
-patch via stdin or the ``-i`` argument, as you prefer.
-
-A few other nice arguments for patch are ``-s`` which causes patch to be silent
-except for errors which is nice to prevent errors from scrolling out of the
-screen too fast, and ``--dry-run`` which causes patch to just print a listing of
-what would happen, but doesn't actually make any changes. Finally ``--verbose``
-tells patch to print more information about the work being done.
-
-
-Common errors when patching
-===========================
-
-When patch applies a patch file it attempts to verify the sanity of the
-file in different ways.
-
-Checking that the file looks like a valid patch file and checking the code
-around the bits being modified matches the context provided in the patch are
-just two of the basic sanity checks patch does.
-
-If patch encounters something that doesn't look quite right it has two
-options. It can either refuse to apply the changes and abort or it can try
-to find a way to make the patch apply with a few minor changes.
-
-One example of something that's not 'quite right' that patch will attempt to
-fix up is if all the context matches, the lines being changed match, but the
-line numbers are different. This can happen, for example, if the patch makes
-a change in the middle of the file but for some reasons a few lines have
-been added or removed near the beginning of the file. In that case
-everything looks good it has just moved up or down a bit, and patch will
-usually adjust the line numbers and apply the patch.
-
-Whenever patch applies a patch that it had to modify a bit to make it fit
-it'll tell you about it by saying the patch applied with **fuzz**.
-You should be wary of such changes since even though patch probably got it
-right it doesn't /always/ get it right, and the result will sometimes be
-wrong.
-
-When patch encounters a change that it can't fix up with fuzz it rejects it
-outright and leaves a file with a ``.rej`` extension (a reject file). You can
-read this file to see exactly what change couldn't be applied, so you can
-go fix it up by hand if you wish.
-
-If you don't have any third-party patches applied to your kernel source, but
-only patches from kernel.org and you apply the patches in the correct order,
-and have made no modifications yourself to the source files, then you should
-never see a fuzz or reject message from patch. If you do see such messages
-anyway, then there's a high risk that either your local source tree or the
-patch file is corrupted in some way. In that case you should probably try
-re-downloading the patch and if things are still not OK then you'd be advised
-to start with a fresh tree downloaded in full from kernel.org.
-
-Let's look a bit more at some of the messages patch can produce.
-
-If patch stops and presents a ``File to patch:`` prompt, then patch could not
-find a file to be patched. Most likely you forgot to specify -p1 or you are
-in the wrong directory. Less often, you'll find patches that need to be
-applied with ``-p0`` instead of ``-p1`` (reading the patch file should reveal if
-this is the case -- if so, then this is an error by the person who created
-the patch but is not fatal).
-
-If you get ``Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines).`` or a
-message similar to that, then it means that patch had to adjust the location
-of the change (in this example it needed to move 7 lines from where it
-expected to make the change to make it fit).
-
-The resulting file may or may not be OK, depending on the reason the file
-was different than expected.
-
-This often happens if you try to apply a patch that was generated against a
-different kernel version than the one you are trying to patch.
-
-If you get a message like ``Hunk #3 FAILED at 2387.``, then it means that the
-patch could not be applied correctly and the patch program was unable to
-fuzz its way through. This will generate a ``.rej`` file with the change that
-caused the patch to fail and also a ``.orig`` file showing you the original
-content that couldn't be changed.
-
-If you get ``Reversed (or previously applied) patch detected!  Assume -R? [n]``
-then patch detected that the change contained in the patch seems to have
-already been made.
-
-If you actually did apply this patch previously and you just re-applied it
-in error, then just say [n]o and abort this patch. If you applied this patch
-previously and actually intended to revert it, but forgot to specify -R,
-then you can say [**y**]es here to make patch revert it for you.
-
-This can also happen if the creator of the patch reversed the source and
-destination directories when creating the patch, and in that case reverting
-the patch will in fact apply it.
-
-A message similar to ``patch: **** unexpected end of file in patch`` or
-``patch unexpectedly ends in middle of line`` means that patch could make no
-sense of the file you fed to it. Either your download is broken, you tried to
-feed patch a compressed patch file without uncompressing it first, or the patch
-file that you are using has been mangled by a mail client or mail transfer
-agent along the way somewhere, e.g., by splitting a long line into two lines.
-Often these warnings can easily be fixed by joining (concatenating) the
-two lines that had been split.
-
-As I already mentioned above, these errors should never happen if you apply
-a patch from kernel.org to the correct version of an unmodified source tree.
-So if you get these errors with kernel.org patches then you should probably
-assume that either your patch file or your tree is broken and I'd advise you
-to start over with a fresh download of a full kernel tree and the patch you
-wish to apply.
-
-
-Are there any alternatives to ``patch``?
-========================================
-
-
-Yes there are alternatives.
-
-You can use the ``interdiff`` program (http://cyberelk.net/tim/patchutils/) to
-generate a patch representing the differences between two patches and then
-apply the result.
-
-This will let you move from something like 4.7.2 to 4.7.3 in a single
-step. The -z flag to interdiff will even let you feed it patches in gzip or
-bzip2 compressed form directly without the use of zcat or bzcat or manual
-decompression.
-
-Here's how you'd go from 4.7.2 to 4.7.3 in a single step::
-
-	interdiff -z ../patch-4.7.2.gz ../patch-4.7.3.gz | patch -p1
-
-Although interdiff may save you a step or two you are generally advised to
-do the additional steps since interdiff can get things wrong in some cases.
-
-Another alternative is ``ketchup``, which is a python script for automatic
-downloading and applying of patches (http://www.selenic.com/ketchup/).
-
-Other nice tools are diffstat, which shows a summary of changes made by a
-patch; lsdiff, which displays a short listing of affected files in a patch
-file, along with (optionally) the line numbers of the start of each patch;
-and grepdiff, which displays a list of the files modified by a patch where
-the patch contains a given regular expression.
-
-
-Where can I download the patches?
-=================================
-
-The patches are available at http://kernel.org/
-Most recent patches are linked from the front page, but they also have
-specific homes.
-
-The 4.x.y (-stable) and 4.x patches live at
-
-	ftp://ftp.kernel.org/pub/linux/kernel/v4.x/
-
-The -rc patches live at
-
-	ftp://ftp.kernel.org/pub/linux/kernel/v4.x/testing/
-
-In place of ``ftp.kernel.org`` you can use ``ftp.cc.kernel.org``, where cc is a
-country code. This way you'll be downloading from a mirror site that's most
-likely geographically closer to you, resulting in faster downloads for you,
-less bandwidth used globally and less load on the main kernel.org servers --
-these are good things, so do use mirrors when possible.
-
-
-The 4.x kernels
-===============
-
-These are the base stable releases released by Linus. The highest numbered
-release is the most recent.
-
-If regressions or other serious flaws are found, then a -stable fix patch
-will be released (see below) on top of this base. Once a new 4.x base
-kernel is released, a patch is made available that is a delta between the
-previous 4.x kernel and the new one.
-
-To apply a patch moving from 4.6 to 4.7, you'd do the following (note
-that such patches do **NOT** apply on top of 4.x.y kernels but on top of the
-base 4.x kernel -- if you need to move from 4.x.y to 4.x+1 you need to
-first revert the 4.x.y patch).
-
-Here are some examples::
-
-	# moving from 4.6 to 4.7
-
-	$ cd ~/linux-4.6		# change to kernel source dir
-	$ patch -p1 < ../patch-4.7	# apply the 4.7 patch
-	$ cd ..
-	$ mv linux-4.6 linux-4.7	# rename source dir
-
-	# moving from 4.6.1 to 4.7
-
-	$ cd ~/linux-4.6.1		# change to kernel source dir
-	$ patch -p1 -R < ../patch-4.6.1	# revert the 4.6.1 patch
-					# source dir is now 4.6
-	$ patch -p1 < ../patch-4.7	# apply new 4.7 patch
-	$ cd ..
-	$ mv linux-4.6.1 linux-4.7	# rename source dir
-
-
-The 4.x.y kernels
-=================
-
-Kernels with 3-digit versions are -stable kernels. They contain small(ish)
-critical fixes for security problems or significant regressions discovered
-in a given 4.x kernel.
-
-This is the recommended branch for users who want the most recent stable
-kernel and are not interested in helping test development/experimental
-versions.
-
-If no 4.x.y kernel is available, then the highest numbered 4.x kernel is
-the current stable kernel.
-
-.. note::
-
- The -stable team usually do make incremental patches available as well
- as patches against the latest mainline release, but I only cover the
- non-incremental ones below. The incremental ones can be found at
- ftp://ftp.kernel.org/pub/linux/kernel/v4.x/incr/
-
-These patches are not incremental, meaning that for example the 4.7.3
-patch does not apply on top of the 4.7.2 kernel source, but rather on top
-of the base 4.7 kernel source.
-
-So, in order to apply the 4.7.3 patch to your existing 4.7.2 kernel
-source you have to first back out the 4.7.2 patch (so you are left with a
-base 4.7 kernel source) and then apply the new 4.7.3 patch.
-
-Here's a small example::
-
-	$ cd ~/linux-4.7.2		# change to the kernel source dir
-	$ patch -p1 -R < ../patch-4.7.2	# revert the 4.7.2 patch
-	$ patch -p1 < ../patch-4.7.3	# apply the new 4.7.3 patch
-	$ cd ..
-	$ mv linux-4.7.2 linux-4.7.3	# rename the kernel source dir
-
-The -rc kernels
-===============
-
-These are release-candidate kernels. These are development kernels released
-by Linus whenever he deems the current git (the kernel's source management
-tool) tree to be in a reasonably sane state adequate for testing.
-
-These kernels are not stable and you should expect occasional breakage if
-you intend to run them. This is however the most stable of the main
-development branches and is also what will eventually turn into the next
-stable kernel, so it is important that it be tested by as many people as
-possible.
-
-This is a good branch to run for people who want to help out testing
-development kernels but do not want to run some of the really experimental
-stuff (such people should see the sections about -git and -mm kernels below).
-
-The -rc patches are not incremental, they apply to a base 4.x kernel, just
-like the 4.x.y patches described above. The kernel version before the -rcN
-suffix denotes the version of the kernel that this -rc kernel will eventually
-turn into.
-
-So, 4.8-rc5 means that this is the fifth release candidate for the 4.8
-kernel and the patch should be applied on top of the 4.7 kernel source.
-
-Here are 3 examples of how to apply these patches::
-
-	# first an example of moving from 4.7 to 4.8-rc3
-
-	$ cd ~/linux-4.7			# change to the 4.7 source dir
-	$ patch -p1 < ../patch-4.8-rc3		# apply the 4.8-rc3 patch
-	$ cd ..
-	$ mv linux-4.7 linux-4.8-rc3		# rename the source dir
-
-	# now let's move from 4.8-rc3 to 4.8-rc5
-
-	$ cd ~/linux-4.8-rc3			# change to the 4.8-rc3 dir
-	$ patch -p1 -R < ../patch-4.8-rc3	# revert the 4.8-rc3 patch
-	$ patch -p1 < ../patch-4.8-rc5		# apply the new 4.8-rc5 patch
-	$ cd ..
-	$ mv linux-4.8-rc3 linux-4.8-rc5	# rename the source dir
-
-	# finally let's try and move from 4.7.3 to 4.8-rc5
-
-	$ cd ~/linux-4.7.3			# change to the kernel source dir
-	$ patch -p1 -R < ../patch-4.7.3		# revert the 4.7.3 patch
-	$ patch -p1 < ../patch-4.8-rc5		# apply new 4.8-rc5 patch
-	$ cd ..
-	$ mv linux-4.7.3 linux-4.8-rc5		# rename the kernel source dir
-
-
-The -git kernels
-================
-
-These are daily snapshots of Linus' kernel tree (managed in a git
-repository, hence the name).
-
-These patches are usually released daily and represent the current state of
-Linus's tree. They are more experimental than -rc kernels since they are
-generated automatically without even a cursory glance to see if they are
-sane.
-
--git patches are not incremental and apply either to a base 4.x kernel or
-a base 4.x-rc kernel -- you can see which from their name.
-A patch named 4.7-git1 applies to the 4.7 kernel source and a patch
-named 4.8-rc3-git2 applies to the source of the 4.8-rc3 kernel.
-
-Here are some examples of how to apply these patches::
-
-	# moving from 4.7 to 4.7-git1
-
-	$ cd ~/linux-4.7			# change to the kernel source dir
-	$ patch -p1 < ../patch-4.7-git1		# apply the 4.7-git1 patch
-	$ cd ..
-	$ mv linux-4.7 linux-4.7-git1		# rename the kernel source dir
-
-	# moving from 4.7-git1 to 4.8-rc2-git3
-
-	$ cd ~/linux-4.7-git1			# change to the kernel source dir
-	$ patch -p1 -R < ../patch-4.7-git1	# revert the 4.7-git1 patch
-						# we now have a 4.7 kernel
-	$ patch -p1 < ../patch-4.8-rc2		# apply the 4.8-rc2 patch
-						# the kernel is now 4.8-rc2
-	$ patch -p1 < ../patch-4.8-rc2-git3	# apply the 4.8-rc2-git3 patch
-						# the kernel is now 4.8-rc2-git3
-	$ cd ..
-	$ mv linux-4.7-git1 linux-4.8-rc2-git3	# rename source dir
-
-
-The -mm patches and the linux-next tree
-=======================================
-
-The -mm patches are experimental patches released by Andrew Morton.
-
-In the past, -mm tree were used to also test subsystem patches, but this
-function is now done via the
-:ref:`linux-next <https://www.kernel.org/doc/man-pages/linux-next.html>`
-tree. The Subsystem maintainers push their patches first to linux-next,
-and, during the merge window, sends them directly to Linus.
-
-The -mm patches serve as a sort of proving ground for new features and other
-experimental patches that aren't merged via a subsystem tree.
-Once such patches has proved its worth in -mm for a while Andrew pushes
-it on to Linus for inclusion in mainline.
-
-The linux-next tree is daily updated, and includes the -mm patches.
-Both are in constant flux and contains many experimental features, a
-lot of debugging patches not appropriate for mainline etc., and is the most
-experimental of the branches described in this document.
-
-These patches are not appropriate for use on systems that are supposed to be
-stable and they are more risky to run than any of the other branches (make
-sure you have up-to-date backups -- that goes for any experimental kernel but
-even more so for -mm patches or using a Kernel from the linux-next tree).
-
-Testing of -mm patches and linux-next is greatly appreciated since the whole
-point of those are to weed out regressions, crashes, data corruption bugs,
-build breakage (and any other bug in general) before changes are merged into
-the more stable mainline Linus tree.
-
-But testers of -mm and linux-next should be aware that breakages are
-more common than in any other tree.
-
-
-This concludes this list of explanations of the various kernel trees.
-I hope you are now clear on how to apply the various patches and help testing
-the kernel.
-
-Thank you's to Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert,
-Johannes Stezenbach, Grant Coady, Pavel Machek and others that I may have
-forgotten for their reviews and contributions to this document.
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/arm/Booting linux-libre-4.10-rc8-gnu/Documentation/arm/Booting
--- linux-libre-4.9-gnu/Documentation/arm/Booting	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/arm/Booting	2017-02-12 16:03:20.000000000 -0500
@@ -51,7 +51,7 @@ As an alternative, the boot loader can p
 option to the kernel via the tagged lists specifying the port, and
 serial format options as described in
 
-       Documentation/kernel-parameters.txt.
+       Documentation/admin-guide/kernel-parameters.rst.
 
 
 3. Detect the machine type
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/arm/stm32/overview.txt linux-libre-4.10-rc8-gnu/Documentation/arm/stm32/overview.txt
--- linux-libre-4.9-gnu/Documentation/arm/stm32/overview.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/arm/stm32/overview.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,8 @@ Introduction
 ------------
 
   The STMicroelectronics family of Cortex-M based MCUs are supported by the
-  'STM32' platform of ARM Linux. Currently only the STM32F429 is supported.
+  'STM32' platform of ARM Linux. Currently only the STM32F429 (Cortex-M4)
+  and STM32F746 (Cortex-M7) are supported.
 
 
 Configuration
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/arm/stm32/stm32f746-overview.txt linux-libre-4.10-rc8-gnu/Documentation/arm/stm32/stm32f746-overview.txt
--- linux-libre-4.9-gnu/Documentation/arm/stm32/stm32f746-overview.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/arm/stm32/stm32f746-overview.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,34 @@
+			STM32F746 Overview
+			==================
+
+  Introduction
+  ------------
+	The STM32F746 is a Cortex-M7 MCU aimed at various applications.
+	It features:
+	- Cortex-M7 core running up to @216MHz
+	- 1MB internal flash, 320KBytes internal RAM (+4KB of backup SRAM)
+	- FMC controller to connect SDRAM, NOR and NAND memories
+	- Dual mode QSPI
+	- SD/MMC/SDIO support
+	- Ethernet controller
+	- USB OTFG FS & HS controllers
+	- I2C, SPI, CAN busses support
+	- Several 16 & 32 bits general purpose timers
+	- Serial Audio interface
+	- LCD controller
+	- HDMI-CEC
+	- SPDIFRX
+
+  Resources
+  ---------
+	Datasheet and reference manual are publicly available on ST website:
+	- http://www.st.com/content/st_com/en/products/microcontrollers/stm32-32-bit-arm-cortex-mcus/stm32f7-series/stm32f7x6/stm32f746ng.html
+
+  Document Author
+  ---------------
+	Alexandre Torgue <alexandre.torgue@st.com>
+
+
+
+
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/assoc_array.txt linux-libre-4.10-rc8-gnu/Documentation/assoc_array.txt
--- linux-libre-4.9-gnu/Documentation/assoc_array.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/assoc_array.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,574 +0,0 @@
-		   ========================================
-		   GENERIC ASSOCIATIVE ARRAY IMPLEMENTATION
-		   ========================================
-
-Contents:
-
- - Overview.
-
- - The public API.
-   - Edit script.
-   - Operations table.
-   - Manipulation functions.
-   - Access functions.
-   - Index key form.
-
- - Internal workings.
-   - Basic internal tree layout.
-   - Shortcuts.
-   - Splitting and collapsing nodes.
-   - Non-recursive iteration.
-   - Simultaneous alteration and iteration.
-
-
-========
-OVERVIEW
-========
-
-This associative array implementation is an object container with the following
-properties:
-
- (1) Objects are opaque pointers.  The implementation does not care where they
-     point (if anywhere) or what they point to (if anything).
-
-     [!] NOTE: Pointers to objects _must_ be zero in the least significant bit.
-
- (2) Objects do not need to contain linkage blocks for use by the array.  This
-     permits an object to be located in multiple arrays simultaneously.
-     Rather, the array is made up of metadata blocks that point to objects.
-
- (3) Objects require index keys to locate them within the array.
-
- (4) Index keys must be unique.  Inserting an object with the same key as one
-     already in the array will replace the old object.
-
- (5) Index keys can be of any length and can be of different lengths.
-
- (6) Index keys should encode the length early on, before any variation due to
-     length is seen.
-
- (7) Index keys can include a hash to scatter objects throughout the array.
-
- (8) The array can iterated over.  The objects will not necessarily come out in
-     key order.
-
- (9) The array can be iterated over whilst it is being modified, provided the
-     RCU readlock is being held by the iterator.  Note, however, under these
-     circumstances, some objects may be seen more than once.  If this is a
-     problem, the iterator should lock against modification.  Objects will not
-     be missed, however, unless deleted.
-
-(10) Objects in the array can be looked up by means of their index key.
-
-(11) Objects can be looked up whilst the array is being modified, provided the
-     RCU readlock is being held by the thread doing the look up.
-
-The implementation uses a tree of 16-pointer nodes internally that are indexed
-on each level by nibbles from the index key in the same manner as in a radix
-tree.  To improve memory efficiency, shortcuts can be emplaced to skip over
-what would otherwise be a series of single-occupancy nodes.  Further, nodes
-pack leaf object pointers into spare space in the node rather than making an
-extra branch until as such time an object needs to be added to a full node.
-
-
-==============
-THE PUBLIC API
-==============
-
-The public API can be found in <linux/assoc_array.h>.  The associative array is
-rooted on the following structure:
-
-	struct assoc_array {
-		...
-	};
-
-The code is selected by enabling CONFIG_ASSOCIATIVE_ARRAY.
-
-
-EDIT SCRIPT
------------
-
-The insertion and deletion functions produce an 'edit script' that can later be
-applied to effect the changes without risking ENOMEM.  This retains the
-preallocated metadata blocks that will be installed in the internal tree and
-keeps track of the metadata blocks that will be removed from the tree when the
-script is applied.
-
-This is also used to keep track of dead blocks and dead objects after the
-script has been applied so that they can be freed later.  The freeing is done
-after an RCU grace period has passed - thus allowing access functions to
-proceed under the RCU read lock.
-
-The script appears as outside of the API as a pointer of the type:
-
-	struct assoc_array_edit;
-
-There are two functions for dealing with the script:
-
- (1) Apply an edit script.
-
-	void assoc_array_apply_edit(struct assoc_array_edit *edit);
-
-     This will perform the edit functions, interpolating various write barriers
-     to permit accesses under the RCU read lock to continue.  The edit script
-     will then be passed to call_rcu() to free it and any dead stuff it points
-     to.
-
- (2) Cancel an edit script.
-
-	void assoc_array_cancel_edit(struct assoc_array_edit *edit);
-
-     This frees the edit script and all preallocated memory immediately.  If
-     this was for insertion, the new object is _not_ released by this function,
-     but must rather be released by the caller.
-
-These functions are guaranteed not to fail.
-
-
-OPERATIONS TABLE
-----------------
-
-Various functions take a table of operations:
-
-	struct assoc_array_ops {
-		...
-	};
-
-This points to a number of methods, all of which need to be provided:
-
- (1) Get a chunk of index key from caller data:
-
-	unsigned long (*get_key_chunk)(const void *index_key, int level);
-
-     This should return a chunk of caller-supplied index key starting at the
-     *bit* position given by the level argument.  The level argument will be a
-     multiple of ASSOC_ARRAY_KEY_CHUNK_SIZE and the function should return
-     ASSOC_ARRAY_KEY_CHUNK_SIZE bits.  No error is possible.
-
-
- (2) Get a chunk of an object's index key.
-
-	unsigned long (*get_object_key_chunk)(const void *object, int level);
-
-     As the previous function, but gets its data from an object in the array
-     rather than from a caller-supplied index key.
-
-
- (3) See if this is the object we're looking for.
-
-	bool (*compare_object)(const void *object, const void *index_key);
-
-     Compare the object against an index key and return true if it matches and
-     false if it doesn't.
-
-
- (4) Diff the index keys of two objects.
-
-	int (*diff_objects)(const void *object, const void *index_key);
-
-     Return the bit position at which the index key of the specified object
-     differs from the given index key or -1 if they are the same.
-
-
- (5) Free an object.
-
-	void (*free_object)(void *object);
-
-     Free the specified object.  Note that this may be called an RCU grace
-     period after assoc_array_apply_edit() was called, so synchronize_rcu() may
-     be necessary on module unloading.
-
-
-MANIPULATION FUNCTIONS
-----------------------
-
-There are a number of functions for manipulating an associative array:
-
- (1) Initialise an associative array.
-
-	void assoc_array_init(struct assoc_array *array);
-
-     This initialises the base structure for an associative array.  It can't
-     fail.
-
-
- (2) Insert/replace an object in an associative array.
-
-	struct assoc_array_edit *
-	assoc_array_insert(struct assoc_array *array,
-			   const struct assoc_array_ops *ops,
-			   const void *index_key,
-			   void *object);
-
-     This inserts the given object into the array.  Note that the least
-     significant bit of the pointer must be zero as it's used to type-mark
-     pointers internally.
-
-     If an object already exists for that key then it will be replaced with the
-     new object and the old one will be freed automatically.
-
-     The index_key argument should hold index key information and is
-     passed to the methods in the ops table when they are called.
-
-     This function makes no alteration to the array itself, but rather returns
-     an edit script that must be applied.  -ENOMEM is returned in the case of
-     an out-of-memory error.
-
-     The caller should lock exclusively against other modifiers of the array.
-
-
- (3) Delete an object from an associative array.
-
-	struct assoc_array_edit *
-	assoc_array_delete(struct assoc_array *array,
-			   const struct assoc_array_ops *ops,
-			   const void *index_key);
-
-     This deletes an object that matches the specified data from the array.
-
-     The index_key argument should hold index key information and is
-     passed to the methods in the ops table when they are called.
-
-     This function makes no alteration to the array itself, but rather returns
-     an edit script that must be applied.  -ENOMEM is returned in the case of
-     an out-of-memory error.  NULL will be returned if the specified object is
-     not found within the array.
-
-     The caller should lock exclusively against other modifiers of the array.
-
-
- (4) Delete all objects from an associative array.
-
-	struct assoc_array_edit *
-	assoc_array_clear(struct assoc_array *array,
-			  const struct assoc_array_ops *ops);
-
-     This deletes all the objects from an associative array and leaves it
-     completely empty.
-
-     This function makes no alteration to the array itself, but rather returns
-     an edit script that must be applied.  -ENOMEM is returned in the case of
-     an out-of-memory error.
-
-     The caller should lock exclusively against other modifiers of the array.
-
-
- (5) Destroy an associative array, deleting all objects.
-
-	void assoc_array_destroy(struct assoc_array *array,
-				 const struct assoc_array_ops *ops);
-
-     This destroys the contents of the associative array and leaves it
-     completely empty.  It is not permitted for another thread to be traversing
-     the array under the RCU read lock at the same time as this function is
-     destroying it as no RCU deferral is performed on memory release -
-     something that would require memory to be allocated.
-
-     The caller should lock exclusively against other modifiers and accessors
-     of the array.
-
-
- (6) Garbage collect an associative array.
-
-	int assoc_array_gc(struct assoc_array *array,
-			   const struct assoc_array_ops *ops,
-			   bool (*iterator)(void *object, void *iterator_data),
-			   void *iterator_data);
-
-     This iterates over the objects in an associative array and passes each one
-     to iterator().  If iterator() returns true, the object is kept.  If it
-     returns false, the object will be freed.  If the iterator() function
-     returns true, it must perform any appropriate refcount incrementing on the
-     object before returning.
-
-     The internal tree will be packed down if possible as part of the iteration
-     to reduce the number of nodes in it.
-
-     The iterator_data is passed directly to iterator() and is otherwise
-     ignored by the function.
-
-     The function will return 0 if successful and -ENOMEM if there wasn't
-     enough memory.
-
-     It is possible for other threads to iterate over or search the array under
-     the RCU read lock whilst this function is in progress.  The caller should
-     lock exclusively against other modifiers of the array.
-
-
-ACCESS FUNCTIONS
-----------------
-
-There are two functions for accessing an associative array:
-
- (1) Iterate over all the objects in an associative array.
-
-	int assoc_array_iterate(const struct assoc_array *array,
-				int (*iterator)(const void *object,
-						void *iterator_data),
-				void *iterator_data);
-
-     This passes each object in the array to the iterator callback function.
-     iterator_data is private data for that function.
-
-     This may be used on an array at the same time as the array is being
-     modified, provided the RCU read lock is held.  Under such circumstances,
-     it is possible for the iteration function to see some objects twice.  If
-     this is a problem, then modification should be locked against.  The
-     iteration algorithm should not, however, miss any objects.
-
-     The function will return 0 if no objects were in the array or else it will
-     return the result of the last iterator function called.  Iteration stops
-     immediately if any call to the iteration function results in a non-zero
-     return.
-
-
- (2) Find an object in an associative array.
-
-	void *assoc_array_find(const struct assoc_array *array,
-			       const struct assoc_array_ops *ops,
-			       const void *index_key);
-
-     This walks through the array's internal tree directly to the object
-     specified by the index key..
-
-     This may be used on an array at the same time as the array is being
-     modified, provided the RCU read lock is held.
-
-     The function will return the object if found (and set *_type to the object
-     type) or will return NULL if the object was not found.
-
-
-INDEX KEY FORM
---------------
-
-The index key can be of any form, but since the algorithms aren't told how long
-the key is, it is strongly recommended that the index key includes its length
-very early on before any variation due to the length would have an effect on
-comparisons.
-
-This will cause leaves with different length keys to scatter away from each
-other - and those with the same length keys to cluster together.
-
-It is also recommended that the index key begin with a hash of the rest of the
-key to maximise scattering throughout keyspace.
-
-The better the scattering, the wider and lower the internal tree will be.
-
-Poor scattering isn't too much of a problem as there are shortcuts and nodes
-can contain mixtures of leaves and metadata pointers.
-
-The index key is read in chunks of machine word.  Each chunk is subdivided into
-one nibble (4 bits) per level, so on a 32-bit CPU this is good for 8 levels and
-on a 64-bit CPU, 16 levels.  Unless the scattering is really poor, it is
-unlikely that more than one word of any particular index key will have to be
-used.
-
-
-=================
-INTERNAL WORKINGS
-=================
-
-The associative array data structure has an internal tree.  This tree is
-constructed of two types of metadata blocks: nodes and shortcuts.
-
-A node is an array of slots.  Each slot can contain one of four things:
-
- (*) A NULL pointer, indicating that the slot is empty.
-
- (*) A pointer to an object (a leaf).
-
- (*) A pointer to a node at the next level.
-
- (*) A pointer to a shortcut.
-
-
-BASIC INTERNAL TREE LAYOUT
---------------------------
-
-Ignoring shortcuts for the moment, the nodes form a multilevel tree.  The index
-key space is strictly subdivided by the nodes in the tree and nodes occur on
-fixed levels.  For example:
-
- Level:	0		1		2		3
-	===============	===============	===============	===============
-							NODE D
-			NODE B		NODE C	+------>+---+
-		+------>+---+	+------>+---+	|	| 0 |
-	NODE A	|	| 0 |	|	| 0 |	|	+---+
-	+---+	|	+---+	|	+---+	|	:   :
-	| 0 |	|	:   :	|	:   :	|	+---+
-	+---+	|	+---+	|	+---+	|	| f |
-	| 1 |---+	| 3 |---+	| 7 |---+	+---+
-	+---+		+---+		+---+
-	:   :		:   :		| 8 |---+
-	+---+		+---+		+---+	|	NODE E
-	| e |---+	| f |		:   :   +------>+---+
-	+---+	|	+---+		+---+		| 0 |
-	| f |	|			| f |		+---+
-	+---+	|			+---+		:   :
-		|	NODE F				+---+
-		+------>+---+				| f |
-			| 0 |		NODE G		+---+
-			+---+	+------>+---+
-			:   :	|	| 0 |
-			+---+	|	+---+
-			| 6 |---+	:   :
-			+---+		+---+
-			:   :		| f |
-			+---+		+---+
-			| f |
-			+---+
-
-In the above example, there are 7 nodes (A-G), each with 16 slots (0-f).
-Assuming no other meta data nodes in the tree, the key space is divided thusly:
-
-	KEY PREFIX	NODE
-	==========	====
-	137*		D
-	138*		E
-	13[0-69-f]*	C
-	1[0-24-f]*	B
-	e6*		G
-	e[0-57-f]*	F
-	[02-df]*	A
-
-So, for instance, keys with the following example index keys will be found in
-the appropriate nodes:
-
-	INDEX KEY	PREFIX	NODE
-	===============	=======	====
-	13694892892489	13	C
-	13795289025897	137	D
-	13889dde88793	138	E
-	138bbb89003093	138	E
-	1394879524789	12	C
-	1458952489	1	B
-	9431809de993ba	-	A
-	b4542910809cd	-	A
-	e5284310def98	e	F
-	e68428974237	e6	G
-	e7fffcbd443	e	F
-	f3842239082	-	A
-
-To save memory, if a node can hold all the leaves in its portion of keyspace,
-then the node will have all those leaves in it and will not have any metadata
-pointers - even if some of those leaves would like to be in the same slot.
-
-A node can contain a heterogeneous mix of leaves and metadata pointers.
-Metadata pointers must be in the slots that match their subdivisions of key
-space.  The leaves can be in any slot not occupied by a metadata pointer.  It
-is guaranteed that none of the leaves in a node will match a slot occupied by a
-metadata pointer.  If the metadata pointer is there, any leaf whose key matches
-the metadata key prefix must be in the subtree that the metadata pointer points
-to.
-
-In the above example list of index keys, node A will contain:
-
-	SLOT	CONTENT		INDEX KEY (PREFIX)
-	====	===============	==================
-	1	PTR TO NODE B	1*
-	any	LEAF		9431809de993ba
-	any	LEAF		b4542910809cd
-	e	PTR TO NODE F	e*
-	any	LEAF		f3842239082
-
-and node B:
-
-	3	PTR TO NODE C	13*
-	any	LEAF		1458952489
-
-
-SHORTCUTS
----------
-
-Shortcuts are metadata records that jump over a piece of keyspace.  A shortcut
-is a replacement for a series of single-occupancy nodes ascending through the
-levels.  Shortcuts exist to save memory and to speed up traversal.
-
-It is possible for the root of the tree to be a shortcut - say, for example,
-the tree contains at least 17 nodes all with key prefix '1111'.  The insertion
-algorithm will insert a shortcut to skip over the '1111' keyspace in a single
-bound and get to the fourth level where these actually become different.
-
-
-SPLITTING AND COLLAPSING NODES
-------------------------------
-
-Each node has a maximum capacity of 16 leaves and metadata pointers.  If the
-insertion algorithm finds that it is trying to insert a 17th object into a
-node, that node will be split such that at least two leaves that have a common
-key segment at that level end up in a separate node rooted on that slot for
-that common key segment.
-
-If the leaves in a full node and the leaf that is being inserted are
-sufficiently similar, then a shortcut will be inserted into the tree.
-
-When the number of objects in the subtree rooted at a node falls to 16 or
-fewer, then the subtree will be collapsed down to a single node - and this will
-ripple towards the root if possible.
-
-
-NON-RECURSIVE ITERATION
------------------------
-
-Each node and shortcut contains a back pointer to its parent and the number of
-slot in that parent that points to it.  None-recursive iteration uses these to
-proceed rootwards through the tree, going to the parent node, slot N + 1 to
-make sure progress is made without the need for a stack.
-
-The backpointers, however, make simultaneous alteration and iteration tricky.
-
-
-SIMULTANEOUS ALTERATION AND ITERATION
--------------------------------------
-
-There are a number of cases to consider:
-
- (1) Simple insert/replace.  This involves simply replacing a NULL or old
-     matching leaf pointer with the pointer to the new leaf after a barrier.
-     The metadata blocks don't change otherwise.  An old leaf won't be freed
-     until after the RCU grace period.
-
- (2) Simple delete.  This involves just clearing an old matching leaf.  The
-     metadata blocks don't change otherwise.  The old leaf won't be freed until
-     after the RCU grace period.
-
- (3) Insertion replacing part of a subtree that we haven't yet entered.  This
-     may involve replacement of part of that subtree - but that won't affect
-     the iteration as we won't have reached the pointer to it yet and the
-     ancestry blocks are not replaced (the layout of those does not change).
-
- (4) Insertion replacing nodes that we're actively processing.  This isn't a
-     problem as we've passed the anchoring pointer and won't switch onto the
-     new layout until we follow the back pointers - at which point we've
-     already examined the leaves in the replaced node (we iterate over all the
-     leaves in a node before following any of its metadata pointers).
-
-     We might, however, re-see some leaves that have been split out into a new
-     branch that's in a slot further along than we were at.
-
- (5) Insertion replacing nodes that we're processing a dependent branch of.
-     This won't affect us until we follow the back pointers.  Similar to (4).
-
- (6) Deletion collapsing a branch under us.  This doesn't affect us because the
-     back pointers will get us back to the parent of the new node before we
-     could see the new node.  The entire collapsed subtree is thrown away
-     unchanged - and will still be rooted on the same slot, so we shouldn't
-     process it a second time as we'll go back to slot + 1.
-
-Note:
-
- (*) Under some circumstances, we need to simultaneously change the parent
-     pointer and the parent slot pointer on a node (say, for example, we
-     inserted another node before it and moved it up a level).  We cannot do
-     this without locking against a read - so we have to replace that node too.
-
-     However, when we're changing a shortcut into a node this isn't a problem
-     as shortcuts only have one slot and so the parent slot number isn't used
-     when traversing backwards over one.  This means that it's okay to change
-     the slot number first - provided suitable barriers are used to make sure
-     the parent slot number is read after the back pointer.
-
-Obsolete blocks and leaves are freed up after an RCU grace period has passed,
-so as long as anyone doing walking or iteration holds the RCU read lock, the
-old superstructure should not go away on them.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/atomic_ops.txt linux-libre-4.10-rc8-gnu/Documentation/atomic_ops.txt
--- linux-libre-4.9-gnu/Documentation/atomic_ops.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/atomic_ops.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,640 +0,0 @@
-		Semantics and Behavior of Atomic and
-		         Bitmask Operations
-
-			  David S. Miller	 
-
-	This document is intended to serve as a guide to Linux port
-maintainers on how to implement atomic counter, bitops, and spinlock
-interfaces properly.
-
-	The atomic_t type should be defined as a signed integer and
-the atomic_long_t type as a signed long integer.  Also, they should
-be made opaque such that any kind of cast to a normal C integer type
-will fail.  Something like the following should suffice:
-
-	typedef struct { int counter; } atomic_t;
-	typedef struct { long counter; } atomic_long_t;
-
-Historically, counter has been declared volatile.  This is now discouraged.
-See Documentation/volatile-considered-harmful.txt for the complete rationale.
-
-local_t is very similar to atomic_t. If the counter is per CPU and only
-updated by one CPU, local_t is probably more appropriate. Please see
-Documentation/local_ops.txt for the semantics of local_t.
-
-The first operations to implement for atomic_t's are the initializers and
-plain reads.
-
-	#define ATOMIC_INIT(i)		{ (i) }
-	#define atomic_set(v, i)	((v)->counter = (i))
-
-The first macro is used in definitions, such as:
-
-static atomic_t my_counter = ATOMIC_INIT(1);
-
-The initializer is atomic in that the return values of the atomic operations
-are guaranteed to be correct reflecting the initialized value if the
-initializer is used before runtime.  If the initializer is used at runtime, a
-proper implicit or explicit read memory barrier is needed before reading the
-value with atomic_read from another thread.
-
-As with all of the atomic_ interfaces, replace the leading "atomic_"
-with "atomic_long_" to operate on atomic_long_t.
-
-The second interface can be used at runtime, as in:
-
-	struct foo { atomic_t counter; };
-	...
-
-	struct foo *k;
-
-	k = kmalloc(sizeof(*k), GFP_KERNEL);
-	if (!k)
-		return -ENOMEM;
-	atomic_set(&k->counter, 0);
-
-The setting is atomic in that the return values of the atomic operations by
-all threads are guaranteed to be correct reflecting either the value that has
-been set with this operation or set with another operation.  A proper implicit
-or explicit memory barrier is needed before the value set with the operation
-is guaranteed to be readable with atomic_read from another thread.
-
-Next, we have:
-
-	#define atomic_read(v)	((v)->counter)
-
-which simply reads the counter value currently visible to the calling thread.
-The read is atomic in that the return value is guaranteed to be one of the
-values initialized or modified with the interface operations if a proper
-implicit or explicit memory barrier is used after possible runtime
-initialization by any other thread and the value is modified only with the
-interface operations.  atomic_read does not guarantee that the runtime
-initialization by any other thread is visible yet, so the user of the
-interface must take care of that with a proper implicit or explicit memory
-barrier.
-
-*** WARNING: atomic_read() and atomic_set() DO NOT IMPLY BARRIERS! ***
-
-Some architectures may choose to use the volatile keyword, barriers, or inline
-assembly to guarantee some degree of immediacy for atomic_read() and
-atomic_set().  This is not uniformly guaranteed, and may change in the future,
-so all users of atomic_t should treat atomic_read() and atomic_set() as simple
-C statements that may be reordered or optimized away entirely by the compiler
-or processor, and explicitly invoke the appropriate compiler and/or memory
-barrier for each use case.  Failure to do so will result in code that may
-suddenly break when used with different architectures or compiler
-optimizations, or even changes in unrelated code which changes how the
-compiler optimizes the section accessing atomic_t variables.
-
-*** YOU HAVE BEEN WARNED! ***
-
-Properly aligned pointers, longs, ints, and chars (and unsigned
-equivalents) may be atomically loaded from and stored to in the same
-sense as described for atomic_read() and atomic_set().  The ACCESS_ONCE()
-macro should be used to prevent the compiler from using optimizations
-that might otherwise optimize accesses out of existence on the one hand,
-or that might create unsolicited accesses on the other.
-
-For example consider the following code:
-
-	while (a > 0)
-		do_something();
-
-If the compiler can prove that do_something() does not store to the
-variable a, then the compiler is within its rights transforming this to
-the following:
-
-	tmp = a;
-	if (a > 0)
-		for (;;)
-			do_something();
-
-If you don't want the compiler to do this (and you probably don't), then
-you should use something like the following:
-
-	while (ACCESS_ONCE(a) < 0)
-		do_something();
-
-Alternatively, you could place a barrier() call in the loop.
-
-For another example, consider the following code:
-
-	tmp_a = a;
-	do_something_with(tmp_a);
-	do_something_else_with(tmp_a);
-
-If the compiler can prove that do_something_with() does not store to the
-variable a, then the compiler is within its rights to manufacture an
-additional load as follows:
-
-	tmp_a = a;
-	do_something_with(tmp_a);
-	tmp_a = a;
-	do_something_else_with(tmp_a);
-
-This could fatally confuse your code if it expected the same value
-to be passed to do_something_with() and do_something_else_with().
-
-The compiler would be likely to manufacture this additional load if
-do_something_with() was an inline function that made very heavy use
-of registers: reloading from variable a could save a flush to the
-stack and later reload.  To prevent the compiler from attacking your
-code in this manner, write the following:
-
-	tmp_a = ACCESS_ONCE(a);
-	do_something_with(tmp_a);
-	do_something_else_with(tmp_a);
-
-For a final example, consider the following code, assuming that the
-variable a is set at boot time before the second CPU is brought online
-and never changed later, so that memory barriers are not needed:
-
-	if (a)
-		b = 9;
-	else
-		b = 42;
-
-The compiler is within its rights to manufacture an additional store
-by transforming the above code into the following:
-
-	b = 42;
-	if (a)
-		b = 9;
-
-This could come as a fatal surprise to other code running concurrently
-that expected b to never have the value 42 if a was zero.  To prevent
-the compiler from doing this, write something like:
-
-	if (a)
-		ACCESS_ONCE(b) = 9;
-	else
-		ACCESS_ONCE(b) = 42;
-
-Don't even -think- about doing this without proper use of memory barriers,
-locks, or atomic operations if variable a can change at runtime!
-
-*** WARNING: ACCESS_ONCE() DOES NOT IMPLY A BARRIER! ***
-
-Now, we move onto the atomic operation interfaces typically implemented with
-the help of assembly code.
-
-	void atomic_add(int i, atomic_t *v);
-	void atomic_sub(int i, atomic_t *v);
-	void atomic_inc(atomic_t *v);
-	void atomic_dec(atomic_t *v);
-
-These four routines add and subtract integral values to/from the given
-atomic_t value.  The first two routines pass explicit integers by
-which to make the adjustment, whereas the latter two use an implicit
-adjustment value of "1".
-
-One very important aspect of these two routines is that they DO NOT
-require any explicit memory barriers.  They need only perform the
-atomic_t counter update in an SMP safe manner.
-
-Next, we have:
-
-	int atomic_inc_return(atomic_t *v);
-	int atomic_dec_return(atomic_t *v);
-
-These routines add 1 and subtract 1, respectively, from the given
-atomic_t and return the new counter value after the operation is
-performed.
-
-Unlike the above routines, it is required that these primitives
-include explicit memory barriers that are performed before and after
-the operation.  It must be done such that all memory operations before
-and after the atomic operation calls are strongly ordered with respect
-to the atomic operation itself.
-
-For example, it should behave as if a smp_mb() call existed both
-before and after the atomic operation.
-
-If the atomic instructions used in an implementation provide explicit
-memory barrier semantics which satisfy the above requirements, that is
-fine as well.
-
-Let's move on:
-
-	int atomic_add_return(int i, atomic_t *v);
-	int atomic_sub_return(int i, atomic_t *v);
-
-These behave just like atomic_{inc,dec}_return() except that an
-explicit counter adjustment is given instead of the implicit "1".
-This means that like atomic_{inc,dec}_return(), the memory barrier
-semantics are required.
-
-Next:
-
-	int atomic_inc_and_test(atomic_t *v);
-	int atomic_dec_and_test(atomic_t *v);
-
-These two routines increment and decrement by 1, respectively, the
-given atomic counter.  They return a boolean indicating whether the
-resulting counter value was zero or not.
-
-Again, these primitives provide explicit memory barrier semantics around
-the atomic operation.
-
-	int atomic_sub_and_test(int i, atomic_t *v);
-
-This is identical to atomic_dec_and_test() except that an explicit
-decrement is given instead of the implicit "1".  This primitive must
-provide explicit memory barrier semantics around the operation.
-
-	int atomic_add_negative(int i, atomic_t *v);
-
-The given increment is added to the given atomic counter value.  A boolean
-is return which indicates whether the resulting counter value is negative.
-This primitive must provide explicit memory barrier semantics around
-the operation.
-
-Then:
-
-	int atomic_xchg(atomic_t *v, int new);
-
-This performs an atomic exchange operation on the atomic variable v, setting
-the given new value.  It returns the old value that the atomic variable v had
-just before the operation.
-
-atomic_xchg must provide explicit memory barriers around the operation.
-
-	int atomic_cmpxchg(atomic_t *v, int old, int new);
-
-This performs an atomic compare exchange operation on the atomic value v,
-with the given old and new values. Like all atomic_xxx operations,
-atomic_cmpxchg will only satisfy its atomicity semantics as long as all
-other accesses of *v are performed through atomic_xxx operations.
-
-atomic_cmpxchg must provide explicit memory barriers around the operation,
-although if the comparison fails then no memory ordering guarantees are
-required.
-
-The semantics for atomic_cmpxchg are the same as those defined for 'cas'
-below.
-
-Finally:
-
-	int atomic_add_unless(atomic_t *v, int a, int u);
-
-If the atomic value v is not equal to u, this function adds a to v, and
-returns non zero. If v is equal to u then it returns zero. This is done as
-an atomic operation.
-
-atomic_add_unless must provide explicit memory barriers around the
-operation unless it fails (returns 0).
-
-atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)
-
-
-If a caller requires memory barrier semantics around an atomic_t
-operation which does not return a value, a set of interfaces are
-defined which accomplish this:
-
-	void smp_mb__before_atomic(void);
-	void smp_mb__after_atomic(void);
-
-For example, smp_mb__before_atomic() can be used like so:
-
-	obj->dead = 1;
-	smp_mb__before_atomic();
-	atomic_dec(&obj->ref_count);
-
-It makes sure that all memory operations preceding the atomic_dec()
-call are strongly ordered with respect to the atomic counter
-operation.  In the above example, it guarantees that the assignment of
-"1" to obj->dead will be globally visible to other cpus before the
-atomic counter decrement.
-
-Without the explicit smp_mb__before_atomic() call, the
-implementation could legally allow the atomic counter update visible
-to other cpus before the "obj->dead = 1;" assignment.
-
-A missing memory barrier in the cases where they are required by the
-atomic_t implementation above can have disastrous results.  Here is
-an example, which follows a pattern occurring frequently in the Linux
-kernel.  It is the use of atomic counters to implement reference
-counting, and it works such that once the counter falls to zero it can
-be guaranteed that no other entity can be accessing the object:
-
-static void obj_list_add(struct obj *obj, struct list_head *head)
-{
-	obj->active = 1;
-	list_add(&obj->list, head);
-}
-
-static void obj_list_del(struct obj *obj)
-{
-	list_del(&obj->list);
-	obj->active = 0;
-}
-
-static void obj_destroy(struct obj *obj)
-{
-	BUG_ON(obj->active);
-	kfree(obj);
-}
-
-struct obj *obj_list_peek(struct list_head *head)
-{
-	if (!list_empty(head)) {
-		struct obj *obj;
-
-		obj = list_entry(head->next, struct obj, list);
-		atomic_inc(&obj->refcnt);
-		return obj;
-	}
-	return NULL;
-}
-
-void obj_poke(void)
-{
-	struct obj *obj;
-
-	spin_lock(&global_list_lock);
-	obj = obj_list_peek(&global_list);
-	spin_unlock(&global_list_lock);
-
-	if (obj) {
-		obj->ops->poke(obj);
-		if (atomic_dec_and_test(&obj->refcnt))
-			obj_destroy(obj);
-	}
-}
-
-void obj_timeout(struct obj *obj)
-{
-	spin_lock(&global_list_lock);
-	obj_list_del(obj);
-	spin_unlock(&global_list_lock);
-
-	if (atomic_dec_and_test(&obj->refcnt))
-		obj_destroy(obj);
-}
-
-(This is a simplification of the ARP queue management in the
- generic neighbour discover code of the networking.  Olaf Kirch
- found a bug wrt. memory barriers in kfree_skb() that exposed
- the atomic_t memory barrier requirements quite clearly.)
-
-Given the above scheme, it must be the case that the obj->active
-update done by the obj list deletion be visible to other processors
-before the atomic counter decrement is performed.
-
-Otherwise, the counter could fall to zero, yet obj->active would still
-be set, thus triggering the assertion in obj_destroy().  The error
-sequence looks like this:
-
-	cpu 0				cpu 1
-	obj_poke()			obj_timeout()
-	obj = obj_list_peek();
-	... gains ref to obj, refcnt=2
-					obj_list_del(obj);
-					obj->active = 0 ...
-					... visibility delayed ...
-					atomic_dec_and_test()
-					... refcnt drops to 1 ...
-	atomic_dec_and_test()
-	... refcount drops to 0 ...
-	obj_destroy()
-	BUG() triggers since obj->active
-	still seen as one
-					obj->active update visibility occurs
-
-With the memory barrier semantics required of the atomic_t operations
-which return values, the above sequence of memory visibility can never
-happen.  Specifically, in the above case the atomic_dec_and_test()
-counter decrement would not become globally visible until the
-obj->active update does.
-
-As a historical note, 32-bit Sparc used to only allow usage of
-24-bits of its atomic_t type.  This was because it used 8 bits
-as a spinlock for SMP safety.  Sparc32 lacked a "compare and swap"
-type instruction.  However, 32-bit Sparc has since been moved over
-to a "hash table of spinlocks" scheme, that allows the full 32-bit
-counter to be realized.  Essentially, an array of spinlocks are
-indexed into based upon the address of the atomic_t being operated
-on, and that lock protects the atomic operation.  Parisc uses the
-same scheme.
-
-Another note is that the atomic_t operations returning values are
-extremely slow on an old 386.
-
-We will now cover the atomic bitmask operations.  You will find that
-their SMP and memory barrier semantics are similar in shape and scope
-to the atomic_t ops above.
-
-Native atomic bit operations are defined to operate on objects aligned
-to the size of an "unsigned long" C data type, and are least of that
-size.  The endianness of the bits within each "unsigned long" are the
-native endianness of the cpu.
-
-	void set_bit(unsigned long nr, volatile unsigned long *addr);
-	void clear_bit(unsigned long nr, volatile unsigned long *addr);
-	void change_bit(unsigned long nr, volatile unsigned long *addr);
-
-These routines set, clear, and change, respectively, the bit number
-indicated by "nr" on the bit mask pointed to by "ADDR".
-
-They must execute atomically, yet there are no implicit memory barrier
-semantics required of these interfaces.
-
-	int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
-	int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
-	int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
-
-Like the above, except that these routines return a boolean which
-indicates whether the changed bit was set _BEFORE_ the atomic bit
-operation.
-
-WARNING! It is incredibly important that the value be a boolean,
-ie. "0" or "1".  Do not try to be fancy and save a few instructions by
-declaring the above to return "long" and just returning something like
-"old_val & mask" because that will not work.
-
-For one thing, this return value gets truncated to int in many code
-paths using these interfaces, so on 64-bit if the bit is set in the
-upper 32-bits then testers will never see that.
-
-One great example of where this problem crops up are the thread_info
-flag operations.  Routines such as test_and_set_ti_thread_flag() chop
-the return value into an int.  There are other places where things
-like this occur as well.
-
-These routines, like the atomic_t counter operations returning values,
-must provide explicit memory barrier semantics around their execution.
-All memory operations before the atomic bit operation call must be
-made visible globally before the atomic bit operation is made visible.
-Likewise, the atomic bit operation must be visible globally before any
-subsequent memory operation is made visible.  For example:
-
-	obj->dead = 1;
-	if (test_and_set_bit(0, &obj->flags))
-		/* ... */;
-	obj->killed = 1;
-
-The implementation of test_and_set_bit() must guarantee that
-"obj->dead = 1;" is visible to cpus before the atomic memory operation
-done by test_and_set_bit() becomes visible.  Likewise, the atomic
-memory operation done by test_and_set_bit() must become visible before
-"obj->killed = 1;" is visible.
-
-Finally there is the basic operation:
-
-	int test_bit(unsigned long nr, __const__ volatile unsigned long *addr);
-
-Which returns a boolean indicating if bit "nr" is set in the bitmask
-pointed to by "addr".
-
-If explicit memory barriers are required around {set,clear}_bit() (which do
-not return a value, and thus does not need to provide memory barrier
-semantics), two interfaces are provided:
-
-	void smp_mb__before_atomic(void);
-	void smp_mb__after_atomic(void);
-
-They are used as follows, and are akin to their atomic_t operation
-brothers:
-
-	/* All memory operations before this call will
-	 * be globally visible before the clear_bit().
-	 */
-	smp_mb__before_atomic();
-	clear_bit( ... );
-
-	/* The clear_bit() will be visible before all
-	 * subsequent memory operations.
-	 */
-	 smp_mb__after_atomic();
-
-There are two special bitops with lock barrier semantics (acquire/release,
-same as spinlocks). These operate in the same way as their non-_lock/unlock
-postfixed variants, except that they are to provide acquire/release semantics,
-respectively. This means they can be used for bit_spin_trylock and
-bit_spin_unlock type operations without specifying any more barriers.
-
-	int test_and_set_bit_lock(unsigned long nr, unsigned long *addr);
-	void clear_bit_unlock(unsigned long nr, unsigned long *addr);
-	void __clear_bit_unlock(unsigned long nr, unsigned long *addr);
-
-The __clear_bit_unlock version is non-atomic, however it still implements
-unlock barrier semantics. This can be useful if the lock itself is protecting
-the other bits in the word.
-
-Finally, there are non-atomic versions of the bitmask operations
-provided.  They are used in contexts where some other higher-level SMP
-locking scheme is being used to protect the bitmask, and thus less
-expensive non-atomic operations may be used in the implementation.
-They have names similar to the above bitmask operation interfaces,
-except that two underscores are prefixed to the interface name.
-
-	void __set_bit(unsigned long nr, volatile unsigned long *addr);
-	void __clear_bit(unsigned long nr, volatile unsigned long *addr);
-	void __change_bit(unsigned long nr, volatile unsigned long *addr);
-	int __test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
-	int __test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
-	int __test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
-
-These non-atomic variants also do not require any special memory
-barrier semantics.
-
-The routines xchg() and cmpxchg() must provide the same exact
-memory-barrier semantics as the atomic and bit operations returning
-values.
-
-Note: If someone wants to use xchg(), cmpxchg() and their variants,
-linux/atomic.h should be included rather than asm/cmpxchg.h, unless
-the code is in arch/* and can take care of itself.
-
-Spinlocks and rwlocks have memory barrier expectations as well.
-The rule to follow is simple:
-
-1) When acquiring a lock, the implementation must make it globally
-   visible before any subsequent memory operation.
-
-2) When releasing a lock, the implementation must make it such that
-   all previous memory operations are globally visible before the
-   lock release.
-
-Which finally brings us to _atomic_dec_and_lock().  There is an
-architecture-neutral version implemented in lib/dec_and_lock.c,
-but most platforms will wish to optimize this in assembler.
-
-	int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
-
-Atomically decrement the given counter, and if will drop to zero
-atomically acquire the given spinlock and perform the decrement
-of the counter to zero.  If it does not drop to zero, do nothing
-with the spinlock.
-
-It is actually pretty simple to get the memory barrier correct.
-Simply satisfy the spinlock grab requirements, which is make
-sure the spinlock operation is globally visible before any
-subsequent memory operation.
-
-We can demonstrate this operation more clearly if we define
-an abstract atomic operation:
-
-	long cas(long *mem, long old, long new);
-
-"cas" stands for "compare and swap".  It atomically:
-
-1) Compares "old" with the value currently at "mem".
-2) If they are equal, "new" is written to "mem".
-3) Regardless, the current value at "mem" is returned.
-
-As an example usage, here is what an atomic counter update
-might look like:
-
-void example_atomic_inc(long *counter)
-{
-	long old, new, ret;
-
-	while (1) {
-		old = *counter;
-		new = old + 1;
-
-		ret = cas(counter, old, new);
-		if (ret == old)
-			break;
-	}
-}
-
-Let's use cas() in order to build a pseudo-C atomic_dec_and_lock():
-
-int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
-{
-	long old, new, ret;
-	int went_to_zero;
-
-	went_to_zero = 0;
-	while (1) {
-		old = atomic_read(atomic);
-		new = old - 1;
-		if (new == 0) {
-			went_to_zero = 1;
-			spin_lock(lock);
-		}
-		ret = cas(atomic, old, new);
-		if (ret == old)
-			break;
-		if (went_to_zero) {
-			spin_unlock(lock);
-			went_to_zero = 0;
-		}
-	}
-
-	return went_to_zero;
-}
-
-Now, as far as memory barriers go, as long as spin_lock()
-strictly orders all subsequent memory operations (including
-the cas()) with respect to itself, things will be fine.
-
-Said another way, _atomic_dec_and_lock() must guarantee that
-a counter dropping to zero is never made visible before the
-spinlock being acquired.
-
-Note that this also means that for the case where the counter
-is not dropping to zero, there are no memory ordering
-requirements.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/bad_memory.txt linux-libre-4.10-rc8-gnu/Documentation/bad_memory.txt
--- linux-libre-4.9-gnu/Documentation/bad_memory.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/bad_memory.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-March 2008
-Jan-Simon Moeller, dl9pf@gmx.de
-
-
-How to deal with bad memory e.g. reported by memtest86+ ?
-#########################################################
-
-There are three possibilities I know of:
-
-1) Reinsert/swap the memory modules
-
-2) Buy new modules (best!) or try to exchange the memory
-   if you have spare-parts
-
-3) Use BadRAM or memmap
-
-This Howto is about number 3) .
-
-
-BadRAM
-######
-BadRAM is the actively developed and available as kernel-patch
-here:  http://rick.vanrein.org/linux/badram/
-
-For more details see the BadRAM documentation.
-
-memmap
-######
-
-memmap is already in the kernel and usable as kernel-parameter at
-boot-time.  Its syntax is slightly strange and you may need to
-calculate the values by yourself!
-
-Syntax to exclude a memory area (see kernel-parameters.txt for details):
-memmap=<size>$<address>
-
-Example: memtest86+ reported here errors at address 0x18691458, 0x18698424 and
-         some others. All had 0x1869xxxx in common, so I chose a pattern of
-         0x18690000,0xffff0000.
-
-With the numbers of the example above:
-memmap=64K$0x18690000
- or
-memmap=0x10000$0x18690000
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/basic_profiling.txt linux-libre-4.10-rc8-gnu/Documentation/basic_profiling.txt
--- linux-libre-4.9-gnu/Documentation/basic_profiling.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/basic_profiling.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-These instructions are deliberately very basic. If you want something clever,
-go read the real docs ;-) Please don't add more stuff, but feel free to 
-correct my mistakes ;-)    (mbligh@aracnet.com)
-Thanks to John Levon, Dave Hansen, et al. for help writing this.
-
-<test> is the thing you're trying to measure.
-Make sure you have the correct System.map / vmlinux referenced!
-
-It is probably easiest to use "make install" for linux and hack
-/sbin/installkernel to copy vmlinux to /boot, in addition to vmlinuz,
-config, System.map, which are usually installed by default.
-
-Readprofile
------------
-A recent readprofile command is needed for 2.6, such as found in util-linux
-2.12a, which can be downloaded from:
-
-http://www.kernel.org/pub/linux/utils/util-linux/
-
-Most distributions will ship it already.
-
-Add "profile=2" to the kernel command line.
-
-clear		readprofile -r
-		<test>
-dump output	readprofile -m /boot/System.map > captured_profile
-
-Oprofile
---------
-
-Get the source (see Changes for required version) from
-http://oprofile.sourceforge.net/ and add "idle=poll" to the kernel command
-line.
-
-Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
-
-./configure --with-kernel-support
-make install
-
-For superior results, be sure to enable the local APIC. If opreport sees
-a 0Hz CPU, APIC was not on. Be aware that idle=poll may mean a performance
-penalty.
-
-One time setup:
-		opcontrol --setup --vmlinux=/boot/vmlinux
-
-clear		opcontrol --reset
-start		opcontrol --start
-		<test>
-stop		opcontrol --stop
-dump output	opreport >  output_file
-
-To only report on the kernel, run opreport -l /boot/vmlinux > output_file
-
-A reset is needed to clear old statistics, which survive a reboot.
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/binfmt_misc.txt linux-libre-4.10-rc8-gnu/Documentation/binfmt_misc.txt
--- linux-libre-4.9-gnu/Documentation/binfmt_misc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/binfmt_misc.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,131 +0,0 @@
-     Kernel Support for miscellaneous (your favourite) Binary Formats v1.1
-     =====================================================================
-
-This Kernel feature allows you to invoke almost (for restrictions see below)
-every program by simply typing its name in the shell.
-This includes for example compiled Java(TM), Python or Emacs programs.
-
-To achieve this you must tell binfmt_misc which interpreter has to be invoked
-with which binary. Binfmt_misc recognises the binary-type by matching some bytes
-at the beginning of the file with a magic byte sequence (masking out specified
-bits) you have supplied. Binfmt_misc can also recognise a filename extension
-aka '.com' or '.exe'.
-
-First you must mount binfmt_misc:
-	mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc 
-
-To actually register a new binary type, you have to set up a string looking like
-:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':'
-upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
-
-Here is what the fields mean:
- - 'name' is an identifier string. A new /proc file will be created with this
-   name below /proc/sys/fs/binfmt_misc; cannot contain slashes '/' for obvious
-   reasons.
- - 'type' is the type of recognition. Give 'M' for magic and 'E' for extension.
- - 'offset' is the offset of the magic/mask in the file, counted in bytes. This
-   defaults to 0 if you omit it (i.e. you write ':name:type::magic...'). Ignored
-   when using filename extension matching.
- - 'magic' is the byte sequence binfmt_misc is matching for. The magic string
-   may contain hex-encoded characters like \x0a or \xA4. Note that you must
-   escape any NUL bytes; parsing halts at the first one. In a shell environment
-   you might have to write \\x0a to prevent the shell from eating your \.
-   If you chose filename extension matching, this is the extension to be
-   recognised (without the '.', the \x0a specials are not allowed). Extension
-   matching is case sensitive, and slashes '/' are not allowed!
- - 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some
-   bits from matching by supplying a string like magic and as long as magic.
-   The mask is anded with the byte sequence of the file. Note that you must
-   escape any NUL bytes; parsing halts at the first one. Ignored when using
-   filename extension matching.
- - 'interpreter' is the program that should be invoked with the binary as first
-   argument (specify the full path)
- - 'flags' is an optional field that controls several aspects of the invocation
-   of the interpreter. It is a string of capital letters, each controls a
-   certain aspect. The following flags are supported -
-      'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite
-            the original argv[0] with the full path to the binary. When this
-            flag is included, binfmt_misc will add an argument to the argument
-            vector for this purpose, thus preserving the original argv[0].
-            e.g. If your interp is set to /bin/foo and you run `blah` (which is
-            in /usr/local/bin), then the kernel will execute /bin/foo with
-            argv[] set to ["/bin/foo", "/usr/local/bin/blah", "blah"].  The
-            interp has to be aware of this so it can execute /usr/local/bin/blah
-            with argv[] set to ["blah"].
-      'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
-            of the binary to the interpreter as an argument. When this flag is
-            included, binfmt_misc will open the file for reading and pass its
-            descriptor as an argument, instead of the full path, thus allowing
-            the interpreter to execute non-readable binaries. This feature
-            should be used with care - the interpreter has to be trusted not to
-            emit the contents of the non-readable binary.
-      'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
-            the credentials and security token of the new process according to
-            the interpreter. When this flag is included, these attributes are
-            calculated according to the binary. It also implies the 'O' flag.
-            This feature should be used with care as the interpreter
-            will run with root permissions when a setuid binary owned by root
-            is run with binfmt_misc.
-      'F' - fix binary.  The usual behaviour of binfmt_misc is to spawn the
-      	    binary lazily when the misc format file is invoked.  However,
-	    this doesn't work very well in the face of mount namespaces and
-	    changeroots, so the F mode opens the binary as soon as the
-	    emulation is installed and uses the opened image to spawn the
-	    emulator, meaning it is always available once installed,
-	    regardless of how the environment changes.
-
-
-There are some restrictions:
- - the whole register string may not exceed 1920 characters
- - the magic must reside in the first 128 bytes of the file, i.e.
-   offset+size(magic) has to be less than 128
- - the interpreter string may not exceed 127 characters
-
-To use binfmt_misc you have to mount it first. You can mount it with
-"mount -t binfmt_misc none /proc/sys/fs/binfmt_misc" command, or you can add
-a line "none  /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0" to your
-/etc/fstab so it auto mounts on boot.
-
-You may want to add the binary formats in one of your /etc/rc scripts during
-boot-up. Read the manual of your init program to figure out how to do this
-right.
-
-Think about the order of adding entries! Later added entries are matched first!
-
-
-A few examples (assumed you are in /proc/sys/fs/binfmt_misc):
-
-- enable support for em86 (like binfmt_em86, for Alpha AXP only):
-  echo ':i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
-  echo ':i486:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff:/bin/em86:' > register
-
-- enable support for packed DOS applications (pre-configured dosemu hdimages):
-  echo ':DEXE:M::\x0eDEX::/usr/bin/dosexec:' > register
-
-- enable support for Windows executables using wine:
-  echo ':DOSWin:M::MZ::/usr/local/bin/wine:' > register
-
-For java support see Documentation/java.txt
-
-
-You can enable/disable binfmt_misc or one binary type by echoing 0 (to disable)
-or 1 (to enable) to /proc/sys/fs/binfmt_misc/status or /proc/.../the_name.
-Catting the file tells you the current status of binfmt_misc/the entry.
-
-You can remove one entry or all entries by echoing -1 to /proc/.../the_name
-or /proc/sys/fs/binfmt_misc/status.
-
-
-HINTS:
-======
-
-If you want to pass special arguments to your interpreter, you can
-write a wrapper script for it. See Documentation/java.txt for an
-example.
-
-Your interpreter should NOT look in the PATH for the filename; the kernel
-passes it the full filename (or the file descriptor) to use.  Using $PATH can
-cause unexpected behaviour and can be a security hazard.
-
-
-Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/block/biodoc.txt linux-libre-4.10-rc8-gnu/Documentation/block/biodoc.txt
--- linux-libre-4.9-gnu/Documentation/block/biodoc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/block/biodoc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -348,7 +348,7 @@ Drivers can now specify a request prepar
 block layer would invoke to pre-build device commands for a given request,
 or perform other preparatory processing for the request. This is routine is
 called by elv_next_request(), i.e. typically just before servicing a request.
-(The prepare function would not be called for requests that have REQ_DONTPREP
+(The prepare function would not be called for requests that have RQF_DONTPREP
 enabled)
 
 Aside:
@@ -553,8 +553,8 @@ struct request {
 	struct request_list *rl;
 }
 	
-See the rq_flag_bits definitions for an explanation of the various flags
-available. Some bits are used by the block layer or i/o scheduler.
+See the req_ops and req_flag_bits definitions for an explanation of the various
+flags available. Some bits are used by the block layer or i/o scheduler.
 	
 The behaviour of the various sector counts are almost the same as before,
 except that since we have multi-segment bios, current_nr_sectors refers
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/block/cfq-iosched.txt linux-libre-4.10-rc8-gnu/Documentation/block/cfq-iosched.txt
--- linux-libre-4.9-gnu/Documentation/block/cfq-iosched.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/block/cfq-iosched.txt	2017-02-12 16:03:20.000000000 -0500
@@ -240,11 +240,11 @@ All cfq queues doing synchronous sequent
 On this tree we idle on each queue individually.
 
 All synchronous non-sequential queues go on sync-noidle tree. Also any
-request which are marked with REQ_NOIDLE go on this service tree. On this
-tree we do not idle on individual queues instead idle on the whole group
-of queues or the tree. So if there are 4 queues waiting for IO to dispatch
-we will idle only once last queue has dispatched the IO and there is
-no more IO on this service tree.
+synchronous write request which is not marked with REQ_IDLE goes on this
+service tree. On this tree we do not idle on individual queues instead idle
+on the whole group of queues or the tree. So if there are 4 queues waiting
+for IO to dispatch we will idle only once last queue has dispatched the IO
+and there is no more IO on this service tree.
 
 All async writes go on async service tree. There is no idling on async
 queues.
@@ -257,17 +257,17 @@ tree idling provides isolation with buff
 
 FAQ
 ===
-Q1. Why to idle at all on queues marked with REQ_NOIDLE.
+Q1. Why to idle at all on queues not marked with REQ_IDLE.
 
-A1. We only do tree idle (all queues on sync-noidle tree) on queues marked
-    with REQ_NOIDLE. This helps in providing isolation with all the sync-idle
+A1. We only do tree idle (all queues on sync-noidle tree) on queues not marked
+    with REQ_IDLE. This helps in providing isolation with all the sync-idle
     queues. Otherwise in presence of many sequential readers, other
     synchronous IO might not get fair share of disk.
 
     For example, if there are 10 sequential readers doing IO and they get
-    100ms each. If a REQ_NOIDLE request comes in, it will be scheduled
-    roughly after 1 second. If after completion of REQ_NOIDLE request we
-    do not idle, and after a couple of milli seconds a another REQ_NOIDLE
+    100ms each. If a !REQ_IDLE request comes in, it will be scheduled
+    roughly after 1 second. If after completion of !REQ_IDLE request we
+    do not idle, and after a couple of milli seconds a another !REQ_IDLE
     request comes in, again it will be scheduled after 1second. Repeat it
     and notice how a workload can lose its disk share and suffer due to
     multiple sequential readers.
@@ -276,16 +276,16 @@ A1. We only do tree idle (all queues on
     context of fsync, and later some journaling data is written. Journaling
     data comes in only after fsync has finished its IO (atleast for ext4
     that seemed to be the case). Now if one decides not to idle on fsync
-    thread due to REQ_NOIDLE, then next journaling write will not get
+    thread due to !REQ_IDLE, then next journaling write will not get
     scheduled for another second. A process doing small fsync, will suffer
     badly in presence of multiple sequential readers.
 
-    Hence doing tree idling on threads using REQ_NOIDLE flag on requests
+    Hence doing tree idling on threads using !REQ_IDLE flag on requests
     provides isolation from multiple sequential readers and at the same
     time we do not idle on individual threads.
 
-Q2. When to specify REQ_NOIDLE
-A2. I would think whenever one is doing synchronous write and not expecting
+Q2. When to specify REQ_IDLE
+A2. I would think whenever one is doing synchronous write and expecting
     more writes to be dispatched from same context soon, should be able
-    to specify REQ_NOIDLE on writes and that probably should work well for
+    to specify REQ_IDLE on writes and that probably should work well for
     most of the cases.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/block/null_blk.txt linux-libre-4.10-rc8-gnu/Documentation/block/null_blk.txt
--- linux-libre-4.9-gnu/Documentation/block/null_blk.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/block/null_blk.txt	2017-02-12 16:03:20.000000000 -0500
@@ -72,4 +72,4 @@ use_per_node_hctx=[0/1]: Default: 0
      queue for each CPU node in the system.
 
 use_lightnvm=[0/1]: Default: 0
-  Register device with LightNVM. Requires blk-mq to be used.
+  Register device with LightNVM. Requires blk-mq and CONFIG_NVM to be enabled.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/block/queue-sysfs.txt linux-libre-4.10-rc8-gnu/Documentation/block/queue-sysfs.txt
--- linux-libre-4.9-gnu/Documentation/block/queue-sysfs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/block/queue-sysfs.txt	2017-02-12 16:03:20.000000000 -0500
@@ -54,9 +54,23 @@ This is the hardware sector size of the
 
 io_poll (RW)
 ------------
-When read, this file shows the total number of block IO polls and how
-many returned success.  Writing '0' to this file will disable polling
-for this device.  Writing any non-zero value will enable this feature.
+When read, this file shows whether polling is enabled (1) or disabled
+(0).  Writing '0' to this file will disable polling for this device.
+Writing any non-zero value will enable this feature.
+
+io_poll_delay (RW)
+------------------
+If polling is enabled, this controls what kind of polling will be
+performed. It defaults to -1, which is classic polling. In this mode,
+the CPU will repeatedly ask for completions without giving up any time.
+If set to 0, a hybrid polling mode is used, where the kernel will attempt
+to make an educated guess at when the IO will complete. Based on this
+guess, the kernel will put the process issuing IO to sleep for an amount
+of time, before entering a classic poll loop. This mode might be a
+little slower than pure classic polling, but it will be more efficient.
+If set to a value larger than 0, the kernel will put the process issuing
+IO to sleep for this amont of microseconds before entering classic
+polling.
 
 iostats (RW)
 -------------
@@ -169,5 +183,14 @@ This is the number of bytes the device c
 command.  A value of '0' means write-same is not supported by this
 device.
 
+wb_lat_usec (RW)
+----------------
+If the device is registered for writeback throttling, then this file shows
+the target minimum read latency. If this latency is exceeded in a given
+window of time (see wb_window_usec), then the writeback throttling will start
+scaling back writes. Writing a value of '0' to this file disables the
+feature. Writing a value of '-1' to this file resets the value to the
+default setting.
+
 
 Jens Axboe <jens.axboe@oracle.com>, February 2009
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/blockdev/cciss.txt linux-libre-4.10-rc8-gnu/Documentation/blockdev/cciss.txt
--- linux-libre-4.9-gnu/Documentation/blockdev/cciss.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/blockdev/cciss.txt	2017-02-12 16:03:20.000000000 -0500
@@ -184,7 +184,7 @@ infrequently used and the primary purpos
 act as a RAID controller for disk drives, so the vast majority of commands
 are allocated for disk devices.  However, if you have more than a few tape
 drives attached to a smart array, the default number of commands may not be
-enought (for example, if you have 8 tape drives, you could only rewind 6
+enough (for example, if you have 8 tape drives, you could only rewind 6
 at one time with the default number of commands.)  The cciss_tape_cmds module
 parameter allows more commands (up to 16 more) to be allocated for use by
 tape drives.  For example:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/blockdev/ramdisk.txt linux-libre-4.10-rc8-gnu/Documentation/blockdev/ramdisk.txt
--- linux-libre-4.9-gnu/Documentation/blockdev/ramdisk.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/blockdev/ramdisk.txt	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@ Contents:
 
 The RAM disk driver is a way to use main system memory as a block device.  It
 is required for initrd, an initial filesystem used if you need to load modules
-in order to access the root filesystem (see Documentation/initrd.txt).  It can
+in order to access the root filesystem (see Documentation/admin-guide/initrd.rst).  It can
 also be used for a temporary filesystem for crypto work, since the contents
 are erased on reboot.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/braille-console.txt linux-libre-4.10-rc8-gnu/Documentation/braille-console.txt
--- linux-libre-4.9-gnu/Documentation/braille-console.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/braille-console.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-                       Linux Braille Console
-
-To get early boot messages on a braille device (before userspace screen
-readers can start), you first need to compile the support for the usual serial
-console (see serial-console.txt), and for braille device (in Device Drivers -
-Accessibility).
-
-Then you need to specify a console=brl, option on the kernel command line, the
-format is:
-
-	console=brl,serial_options...
-
-where serial_options... are the same as described in serial-console.txt
-
-So for instance you can use console=brl,ttyS0 if the braille device is connected
-to the first serial port, and console=brl,ttyS0,115200 to override the baud rate
-to 115200, etc.
-
-By default, the braille device will just show the last kernel message (console
-mode).  To review previous messages, press the Insert key to switch to the VT
-review mode.  In review mode, the arrow keys permit to browse in the VT content,
-page up/down keys go at the top/bottom of the screen, and the home key goes back
-to the cursor, hence providing very basic screen reviewing facility.
-
-Sound feedback can be obtained by adding the braille_console.sound=1 kernel
-parameter.
-
-For simplicity, only one braille console can be enabled, other uses of
-console=brl,... will be discarded.  Also note that it does not interfere with
-the console selection mechanism described in serial-console.txt
-
-For now, only the VisioBraille device is supported.
-
-Samuel Thibault <samuel.thibault@ens-lyon.org>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/BUG-HUNTING linux-libre-4.10-rc8-gnu/Documentation/BUG-HUNTING
--- linux-libre-4.9-gnu/Documentation/BUG-HUNTING	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/BUG-HUNTING	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-Table of contents
-=================
-
-Last updated: 20 December 2005
-
-Contents
-========
-
-- Introduction
-- Devices not appearing
-- Finding patch that caused a bug
--- Finding using git-bisect
--- Finding it the old way
-- Fixing the bug
-
-Introduction
-============
-
-Always try the latest kernel from kernel.org and build from source. If you are
-not confident in doing that please report the bug to your distribution vendor
-instead of to a kernel developer.
-
-Finding bugs is not always easy. Have a go though. If you can't find it don't
-give up. Report as much as you have found to the relevant maintainer. See
-MAINTAINERS for who that is for the subsystem you have worked on.
-
-Before you submit a bug report read REPORTING-BUGS.
-
-Devices not appearing
-=====================
-
-Often this is caused by udev. Check that first before blaming it on the
-kernel.
-
-Finding patch that caused a bug
-===============================
-
-
-
-Finding using git-bisect
-------------------------
-
-Using the provided tools with git makes finding bugs easy provided the bug is
-reproducible.
-
-Steps to do it:
-- start using git for the kernel source
-- read the man page for git-bisect
-- have fun
-
-Finding it the old way
-----------------------
-
-[Sat Mar  2 10:32:33 PST 1996 KERNEL_BUG-HOWTO lm@sgi.com (Larry McVoy)]
-
-This is how to track down a bug if you know nothing about kernel hacking.
-It's a brute force approach but it works pretty well.
-
-You need:
-
-        . A reproducible bug - it has to happen predictably (sorry)
-        . All the kernel tar files from a revision that worked to the
-          revision that doesn't
-
-You will then do:
-
-        . Rebuild a revision that you believe works, install, and verify that.
-        . Do a binary search over the kernels to figure out which one
-          introduced the bug.  I.e., suppose 1.3.28 didn't have the bug, but
-          you know that 1.3.69 does.  Pick a kernel in the middle and build
-          that, like 1.3.50.  Build & test; if it works, pick the mid point
-          between .50 and .69, else the mid point between .28 and .50.
-        . You'll narrow it down to the kernel that introduced the bug.  You
-          can probably do better than this but it gets tricky.
-
-        . Narrow it down to a subdirectory
-
-          - Copy kernel that works into "test".  Let's say that 3.62 works,
-            but 3.63 doesn't.  So you diff -r those two kernels and come
-            up with a list of directories that changed.  For each of those
-            directories:
-
-                Copy the non-working directory next to the working directory
-                as "dir.63".
-                One directory at time, try moving the working directory to
-                "dir.62" and mv dir.63 dir"time, try
-
-                        mv dir dir.62
-                        mv dir.63 dir
-                        find dir -name '*.[oa]' -print | xargs rm -f
-
-                And then rebuild and retest.  Assuming that all related
-                changes were contained in the sub directory, this should
-                isolate the change to a directory.
-
-                Problems: changes in header files may have occurred; I've
-                found in my case that they were self explanatory - you may
-                or may not want to give up when that happens.
-
-        . Narrow it down to a file
-
-          - You can apply the same technique to each file in the directory,
-            hoping that the changes in that file are self contained.
-
-        . Narrow it down to a routine
-
-          - You can take the old file and the new file and manually create
-            a merged file that has
-
-                #ifdef VER62
-                routine()
-                {
-                        ...
-                }
-                #else
-                routine()
-                {
-                        ...
-                }
-                #endif
-
-            And then walk through that file, one routine at a time and
-            prefix it with
-
-                #define VER62
-                /* both routines here */
-                #undef VER62
-
-            Then recompile, retest, move the ifdefs until you find the one
-            that makes the difference.
-
-Finally, you take all the info that you have, kernel revisions, bug
-description, the extent to which you have narrowed it down, and pass
-that off to whomever you believe is the maintainer of that section.
-A post to linux.dev.kernel isn't such a bad idea if you've done some
-work to narrow it down.
-
-If you get it down to a routine, you'll probably get a fix in 24 hours.
-
-My apologies to Linus and the other kernel hackers for describing this
-brute force approach, it's hardly what a kernel hacker would do.  However,
-it does work and it lets non-hackers help fix bugs.  And it is cool
-because Linux snapshots will let you do this - something that you can't
-do with vendor supplied releases.
-
-Fixing the bug
-==============
-
-Nobody is going to tell you how to fix bugs. Seriously. You need to work it
-out. But below are some hints on how to use the tools.
-
-To debug a kernel, use objdump and look for the hex offset from the crash
-output to find the valid line of code/assembler. Without debug symbols, you
-will see the assembler code for the routine shown, but if your kernel has
-debug symbols the C code will also be available. (Debug symbols can be enabled
-in the kernel hacking menu of the menu configuration.) For example:
-
-    objdump -r -S -l --disassemble net/dccp/ipv4.o
-
-NB.: you need to be at the top level of the kernel tree for this to pick up
-your C files.
-
-If you don't have access to the code you can also debug on some crash dumps
-e.g. crash dump output as shown by Dave Miller.
-
->    EIP is at ip_queue_xmit+0x14/0x4c0
->     ...
->    Code: 44 24 04 e8 6f 05 00 00 e9 e8 fe ff ff 8d 76 00 8d bc 27 00 00
->    00 00 55 57  56 53 81 ec bc 00 00 00 8b ac 24 d0 00 00 00 8b 5d 08
->    <8b> 83 3c 01 00 00 89 44  24 14 8b 45 28 85 c0 89 44 24 18 0f 85
->
->    Put the bytes into a "foo.s" file like this:
->
->           .text
->           .globl foo
->    foo:
->           .byte  .... /* bytes from Code: part of OOPS dump */
->
->    Compile it with "gcc -c -o foo.o foo.s" then look at the output of
->    "objdump --disassemble foo.o".
->
->    Output:
->
->    ip_queue_xmit:
->        push       %ebp
->        push       %edi
->        push       %esi
->        push       %ebx
->        sub        $0xbc, %esp
->        mov        0xd0(%esp), %ebp        ! %ebp = arg0 (skb)
->        mov        0x8(%ebp), %ebx         ! %ebx = skb->sk
->        mov        0x13c(%ebx), %eax       ! %eax = inet_sk(sk)->opt
-
-In addition, you can use GDB to figure out the exact file and line
-number of the OOPS from the vmlinux file. If you have
-CONFIG_DEBUG_INFO enabled, you can simply copy the EIP value from the
-OOPS:
-
- EIP:    0060:[<c021e50e>]    Not tainted VLI
-
-And use GDB to translate that to human-readable form:
-
-  gdb vmlinux
-  (gdb) l *0xc021e50e
-
-If you don't have CONFIG_DEBUG_INFO enabled, you use the function
-offset from the OOPS:
-
- EIP is at vt_ioctl+0xda8/0x1482
-
-And recompile the kernel with CONFIG_DEBUG_INFO enabled:
-
-  make vmlinux
-  gdb vmlinux
-  (gdb) p vt_ioctl
-  (gdb) l *(0x<address of vt_ioctl> + 0xda8)
-or, as one command
-  (gdb) l *(vt_ioctl + 0xda8)
-
-If you have a call trace, such as :-
->Call Trace:
-> [<ffffffff8802c8e9>] :jbd:log_wait_commit+0xa3/0xf5
-> [<ffffffff810482d9>] autoremove_wake_function+0x0/0x2e
-> [<ffffffff8802770b>] :jbd:journal_stop+0x1be/0x1ee
-> ...
-this shows the problem in the :jbd: module. You can load that module in gdb
-and list the relevant code.
-  gdb fs/jbd/jbd.ko
-  (gdb) p log_wait_commit
-  (gdb) l *(0x<address> + 0xa3)
-or
-  (gdb) l *(log_wait_commit + 0xa3)
-
-
-Another very useful option of the Kernel Hacking section in menuconfig is
-Debug memory allocations. This will help you see whether data has been
-initialised and not set before use etc. To see the values that get assigned
-with this look at mm/slab.c and search for POISON_INUSE. When using this an
-Oops will often show the poisoned data instead of zero which is the default.
-
-Once you have worked out a fix please submit it upstream. After all open
-source is about sharing what you do and don't you want to be recognised for
-your genius?
-
-Please do read Documentation/SubmittingPatches though to help your code get
-accepted.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/cgroup-v1/00-INDEX linux-libre-4.10-rc8-gnu/Documentation/cgroup-v1/00-INDEX
--- linux-libre-4.9-gnu/Documentation/cgroup-v1/00-INDEX	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/cgroup-v1/00-INDEX	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@ cpuacct.txt
 	- CPU Accounting Controller; account CPU usage for groups of tasks.
 cpusets.txt
 	- documents the cpusets feature; assign CPUs and Mem to a set of tasks.
-devices.txt
+admin-guide/devices.rst
 	- Device Whitelist Controller; description, interface and security.
 freezer-subsystem.txt
 	- checkpointing; rationale to not use signals, interface.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/Changes linux-libre-4.10-rc8-gnu/Documentation/Changes
--- linux-libre-4.9-gnu/Documentation/Changes	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/Changes	1969-12-31 19:00:00.000000000 -0500
@@ -1,485 +0,0 @@
-.. _changes:
-
-Minimal requerements to compile the Kernel
-++++++++++++++++++++++++++++++++++++++++++
-
-Intro
-=====
-
-This document is designed to provide a list of the minimum levels of
-software necessary to run the 4.x kernels.
-
-This document is originally based on my "Changes" file for 2.0.x kernels
-and therefore owes credit to the same people as that file (Jared Mauch,
-Axel Boldt, Alessandro Sigala, and countless other users all over the
-'net).
-
-Current Minimal Requirements
-****************************
-
-Upgrade to at **least** these software revisions before thinking you've
-encountered a bug!  If you're unsure what version you're currently
-running, the suggested command should tell you.
-
-Again, keep in mind that this list assumes you are already functionally
-running a Linux kernel.  Also, not all tools are necessary on all
-systems; obviously, if you don't have any ISDN hardware, for example,
-you probably needn't concern yourself with isdn4k-utils.
-
-====================== ===============  ========================================
-        Program        Minimal version       Command to check the version
-====================== ===============  ========================================
-GNU C                  3.2              gcc --version
-GNU make               3.80             make --version
-binutils               2.12             ld -v
-util-linux             2.10o            fdformat --version
-module-init-tools      0.9.10           depmod -V
-e2fsprogs              1.41.4           e2fsck -V
-jfsutils               1.1.3            fsck.jfs -V
-reiserfsprogs          3.6.3            reiserfsck -V
-xfsprogs               2.6.0            xfs_db -V
-squashfs-tools         4.0              mksquashfs -version
-btrfs-progs            0.18             btrfsck
-pcmciautils            004              pccardctl -V
-quota-tools            3.09             quota -V
-PPP                    2.4.0            pppd --version
-isdn4k-utils           3.1pre1          isdnctrl 2>&1|grep version
-nfs-utils              1.0.5            showmount --version
-procps                 3.2.0            ps --version
-oprofile               0.9              oprofiled --version
-udev                   081              udevd --version
-grub                   0.93             grub --version || grub-install --version
-mcelog                 0.6              mcelog --version
-iptables               1.4.2            iptables -V
-openssl & libcrypto    1.0.0            openssl version
-bc                     1.06.95          bc --version
-Sphinx\ [#f1]_	       1.2		sphinx-build --version
-====================== ===============  ========================================
-
-.. [#f1] Sphinx is needed only to build the Kernel documentation
-
-Kernel compilation
-******************
-
-GCC
----
-
-The gcc version requirements may vary depending on the type of CPU in your
-computer.
-
-Make
-----
-
-You will need GNU make 3.80 or later to build the kernel.
-
-Binutils
---------
-
-Linux on IA-32 has recently switched from using ``as86`` to using ``gas`` for
-assembling the 16-bit boot code, removing the need for ``as86`` to compile
-your kernel.  This change does, however, mean that you need a recent
-release of binutils.
-
-Perl
-----
-
-You will need perl 5 and the following modules: ``Getopt::Long``,
-``Getopt::Std``, ``File::Basename``, and ``File::Find`` to build the kernel.
-
-BC
---
-
-You will need bc to build kernels 3.10 and higher
-
-
-OpenSSL
--------
-
-Module signing and external certificate handling use the OpenSSL program and
-crypto library to do key creation and signature generation.
-
-You will need openssl to build kernels 3.7 and higher if module signing is
-enabled.  You will also need openssl development packages to build kernels 4.3
-and higher.
-
-
-System utilities
-****************
-
-Architectural changes
----------------------
-
-DevFS has been obsoleted in favour of udev
-(http://www.kernel.org/pub/linux/utils/kernel/hotplug/)
-
-32-bit UID support is now in place.  Have fun!
-
-Linux documentation for functions is transitioning to inline
-documentation via specially-formatted comments near their
-definitions in the source.  These comments can be combined with the
-SGML templates in the Documentation/DocBook directory to make DocBook
-files, which can then be converted by DocBook stylesheets to PostScript,
-HTML, PDF files, and several other formats.  In order to convert from
-DocBook format to a format of your choice, you'll need to install Jade as
-well as the desired DocBook stylesheets.
-
-Util-linux
-----------
-
-New versions of util-linux provide ``fdisk`` support for larger disks,
-support new options to mount, recognize more supported partition
-types, have a fdformat which works with 2.4 kernels, and similar goodies.
-You'll probably want to upgrade.
-
-Ksymoops
---------
-
-If the unthinkable happens and your kernel oopses, you may need the
-ksymoops tool to decode it, but in most cases you don't.
-It is generally preferred to build the kernel with ``CONFIG_KALLSYMS`` so
-that it produces readable dumps that can be used as-is (this also
-produces better output than ksymoops).  If for some reason your kernel
-is not build with ``CONFIG_KALLSYMS`` and you have no way to rebuild and
-reproduce the Oops with that option, then you can still decode that Oops
-with ksymoops.
-
-Module-Init-Tools
------------------
-
-A new module loader is now in the kernel that requires ``module-init-tools``
-to use.  It is backward compatible with the 2.4.x series kernels.
-
-Mkinitrd
---------
-
-These changes to the ``/lib/modules`` file tree layout also require that
-mkinitrd be upgraded.
-
-E2fsprogs
----------
-
-The latest version of ``e2fsprogs`` fixes several bugs in fsck and
-debugfs.  Obviously, it's a good idea to upgrade.
-
-JFSutils
---------
-
-The ``jfsutils`` package contains the utilities for the file system.
-The following utilities are available:
-
-- ``fsck.jfs`` - initiate replay of the transaction log, and check
-  and repair a JFS formatted partition.
-
-- ``mkfs.jfs`` - create a JFS formatted partition.
-
-- other file system utilities are also available in this package.
-
-Reiserfsprogs
--------------
-
-The reiserfsprogs package should be used for reiserfs-3.6.x
-(Linux kernels 2.4.x). It is a combined package and contains working
-versions of ``mkreiserfs``, ``resize_reiserfs``, ``debugreiserfs`` and
-``reiserfsck``. These utils work on both i386 and alpha platforms.
-
-Xfsprogs
---------
-
-The latest version of ``xfsprogs`` contains ``mkfs.xfs``, ``xfs_db``, and the
-``xfs_repair`` utilities, among others, for the XFS filesystem.  It is
-architecture independent and any version from 2.0.0 onward should
-work correctly with this version of the XFS kernel code (2.6.0 or
-later is recommended, due to some significant improvements).
-
-PCMCIAutils
------------
-
-PCMCIAutils replaces ``pcmcia-cs``. It properly sets up
-PCMCIA sockets at system startup and loads the appropriate modules
-for 16-bit PCMCIA devices if the kernel is modularized and the hotplug
-subsystem is used.
-
-Quota-tools
------------
-
-Support for 32 bit uid's and gid's is required if you want to use
-the newer version 2 quota format.  Quota-tools version 3.07 and
-newer has this support.  Use the recommended version or newer
-from the table above.
-
-Intel IA32 microcode
---------------------
-
-A driver has been added to allow updating of Intel IA32 microcode,
-accessible as a normal (misc) character device.  If you are not using
-udev you may need to::
-
-  mkdir /dev/cpu
-  mknod /dev/cpu/microcode c 10 184
-  chmod 0644 /dev/cpu/microcode
-
-as root before you can use this.  You'll probably also want to
-get the user-space microcode_ctl utility to use with this.
-
-udev
-----
-
-``udev`` is a userspace application for populating ``/dev`` dynamically with
-only entries for devices actually present. ``udev`` replaces the basic
-functionality of devfs, while allowing persistent device naming for
-devices.
-
-FUSE
-----
-
-Needs libfuse 2.4.0 or later.  Absolute minimum is 2.3.0 but mount
-options ``direct_io`` and ``kernel_cache`` won't work.
-
-Networking
-**********
-
-General changes
----------------
-
-If you have advanced network configuration needs, you should probably
-consider using the network tools from ip-route2.
-
-Packet Filter / NAT
--------------------
-The packet filtering and NAT code uses the same tools like the previous 2.4.x
-kernel series (iptables).  It still includes backwards-compatibility modules
-for 2.2.x-style ipchains and 2.0.x-style ipfwadm.
-
-PPP
----
-
-The PPP driver has been restructured to support multilink and to
-enable it to operate over diverse media layers.  If you use PPP,
-upgrade pppd to at least 2.4.0.
-
-If you are not using udev, you must have the device file /dev/ppp
-which can be made by::
-
-  mknod /dev/ppp c 108 0
-
-as root.
-
-Isdn4k-utils
-------------
-
-Due to changes in the length of the phone number field, isdn4k-utils
-needs to be recompiled or (preferably) upgraded.
-
-NFS-utils
----------
-
-In ancient (2.4 and earlier) kernels, the nfs server needed to know
-about any client that expected to be able to access files via NFS.  This
-information would be given to the kernel by ``mountd`` when the client
-mounted the filesystem, or by ``exportfs`` at system startup.  exportfs
-would take information about active clients from ``/var/lib/nfs/rmtab``.
-
-This approach is quite fragile as it depends on rmtab being correct
-which is not always easy, particularly when trying to implement
-fail-over.  Even when the system is working well, ``rmtab`` suffers from
-getting lots of old entries that never get removed.
-
-With modern kernels we have the option of having the kernel tell mountd
-when it gets a request from an unknown host, and mountd can give
-appropriate export information to the kernel.  This removes the
-dependency on ``rmtab`` and means that the kernel only needs to know about
-currently active clients.
-
-To enable this new functionality, you need to::
-
-  mount -t nfsd nfsd /proc/fs/nfsd
-
-before running exportfs or mountd.  It is recommended that all NFS
-services be protected from the internet-at-large by a firewall where
-that is possible.
-
-mcelog
-------
-
-On x86 kernels the mcelog utility is needed to process and log machine check
-events when ``CONFIG_X86_MCE`` is enabled. Machine check events are errors
-reported by the CPU. Processing them is strongly encouraged.
-
-Kernel documentation
-********************
-
-Sphinx
-------
-
-The ReST markups currently used by the Documentation/ files are meant to be
-built with ``Sphinx`` version 1.2 or upper. If you're desiring to build
-PDF outputs, it is recommended to use version 1.4.6.
-
-.. note::
-
-  Please notice that, for PDF and LaTeX output, you'll also need ``XeLaTeX``
-  version 3.14159265. Depending on the distribution, you may also need
-  to install a series of ``texlive`` packages that provide the minimal
-  set of functionalities required for ``XeLaTex`` to work.
-
-Other tools
------------
-
-In order to produce documentation from DocBook, you'll also need ``xmlto``.
-Please notice, however, that we're currently migrating all documents to use
-``Sphinx``.
-
-Getting updated software
-========================
-
-Kernel compilation
-******************
-
-gcc
----
-
-- <ftp://ftp.gnu.org/gnu/gcc/>
-
-Make
-----
-
-- <ftp://ftp.gnu.org/gnu/make/>
-
-Binutils
---------
-
-- <ftp://ftp.kernel.org/pub/linux/devel/binutils/>
-
-OpenSSL
--------
-
-- <https://www.openssl.org/>
-
-System utilities
-****************
-
-Util-linux
-----------
-
-- <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>
-
-Ksymoops
---------
-
-- <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
-
-Module-Init-Tools
------------------
-
-- <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
-
-Mkinitrd
---------
-
-- <https://code.launchpad.net/initrd-tools/main>
-
-E2fsprogs
----------
-
-- <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.29.tar.gz>
-
-JFSutils
---------
-
-- <http://jfs.sourceforge.net/>
-
-Reiserfsprogs
--------------
-
-- <http://www.kernel.org/pub/linux/utils/fs/reiserfs/>
-
-Xfsprogs
---------
-
-- <ftp://oss.sgi.com/projects/xfs/>
-
-Pcmciautils
------------
-
-- <ftp://ftp.kernel.org/pub/linux/utils/kernel/pcmcia/>
-
-Quota-tools
------------
-
-- <http://sourceforge.net/projects/linuxquota/>
-
-DocBook Stylesheets
--------------------
-
-- <http://sourceforge.net/projects/docbook/files/docbook-dsssl/>
-
-XMLTO XSLT Frontend
--------------------
-
-- <http://cyberelk.net/tim/xmlto/>
-
-Intel P6 microcode
-------------------
-
-- <https://downloadcenter.intel.com/>
-
-udev
-----
-
-- <http://www.freedesktop.org/software/systemd/man/udev.html>
-
-FUSE
-----
-
-- <http://sourceforge.net/projects/fuse>
-
-mcelog
-------
-
-- <http://www.mcelog.org/>
-
-Networking
-**********
-
-PPP
----
-
-- <ftp://ftp.samba.org/pub/ppp/>
-
-Isdn4k-utils
-------------
-
-- <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/>
-
-NFS-utils
----------
-
-- <http://sourceforge.net/project/showfiles.php?group_id=14>
-
-Iptables
---------
-
-- <http://www.iptables.org/downloads.html>
-
-Ip-route2
----------
-
-- <https://www.kernel.org/pub/linux/utils/net/iproute2/>
-
-OProfile
---------
-
-- <http://oprofile.sf.net/download/>
-
-NFS-Utils
----------
-
-- <http://nfs.sourceforge.net/>
-
-Kernel documentation
-********************
-
-Sphinx
-------
-
-- <http://www.sphinx-doc.org/>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/circular-buffers.txt linux-libre-4.10-rc8-gnu/Documentation/circular-buffers.txt
--- linux-libre-4.9-gnu/Documentation/circular-buffers.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/circular-buffers.txt	2017-02-12 16:03:20.000000000 -0500
@@ -161,7 +161,7 @@ The producer will look something like th
 
 	unsigned long head = buffer->head;
 	/* The spin_unlock() and next spin_lock() provide needed ordering. */
-	unsigned long tail = ACCESS_ONCE(buffer->tail);
+	unsigned long tail = READ_ONCE(buffer->tail);
 
 	if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
 		/* insert one item into the buffer */
@@ -222,7 +222,7 @@ This will instruct the CPU to make sure
 the new item, and then it shall make sure the CPU has finished reading the item
 before it writes the new tail pointer, which will erase the item.
 
-Note the use of ACCESS_ONCE() and smp_load_acquire() to read the
+Note the use of READ_ONCE() and smp_load_acquire() to read the
 opposition index.  This prevents the compiler from discarding and
 reloading its cached value - which some compilers will do across
 smp_read_barrier_depends().  This isn't strictly needed if you can
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/CodeOfConflict linux-libre-4.10-rc8-gnu/Documentation/CodeOfConflict
--- linux-libre-4.9-gnu/Documentation/CodeOfConflict	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/CodeOfConflict	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-Code of Conflict
-----------------
-
-The Linux kernel development effort is a very personal process compared
-to "traditional" ways of developing software.  Your code and ideas
-behind it will be carefully reviewed, often resulting in critique and
-criticism.  The review will almost always require improvements to the
-code before it can be included in the kernel.  Know that this happens
-because everyone involved wants to see the best possible solution for
-the overall success of Linux.  This development process has been proven
-to create the most robust operating system kernel ever, and we do not
-want to do anything to cause the quality of submission and eventual
-result to ever decrease.
-
-If however, anyone feels personally abused, threatened, or otherwise
-uncomfortable due to this process, that is not acceptable.  If so,
-please contact the Linux Foundation's Technical Advisory Board at
-<tab@lists.linux-foundation.org>, or the individual members, and they
-will work to resolve the issue to the best of their ability.  For more
-information on who is on the Technical Advisory Board and what their
-role is, please see:
-	http://www.linuxfoundation.org/projects/linux/tab
-
-As a reviewer of code, please strive to keep things civil and focused on
-the technical issues involved.  We are all humans, and frustrations can
-be high on both sides of the process.  Try to keep in mind the immortal
-words of Bill and Ted, "Be excellent to each other."
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/CodingStyle linux-libre-4.10-rc8-gnu/Documentation/CodingStyle
--- linux-libre-4.9-gnu/Documentation/CodingStyle	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/CodingStyle	2017-02-12 16:03:20.000000000 -0500
@@ -1,1062 +1 @@
-.. _codingstyle:
-
-Linux kernel coding style
-=========================
-
-This is a short document describing the preferred coding style for the
-linux kernel.  Coding style is very personal, and I won't **force** my
-views on anybody, but this is what goes for anything that I have to be
-able to maintain, and I'd prefer it for most other things too.  Please
-at least consider the points made here.
-
-First off, I'd suggest printing out a copy of the GNU coding standards,
-and NOT read it.  Burn them, it's a great symbolic gesture.
-
-Anyway, here goes:
-
-
-1) Indentation
---------------
-
-Tabs are 8 characters, and thus indentations are also 8 characters.
-There are heretic movements that try to make indentations 4 (or even 2!)
-characters deep, and that is akin to trying to define the value of PI to
-be 3.
-
-Rationale: The whole idea behind indentation is to clearly define where
-a block of control starts and ends.  Especially when you've been looking
-at your screen for 20 straight hours, you'll find it a lot easier to see
-how the indentation works if you have large indentations.
-
-Now, some people will claim that having 8-character indentations makes
-the code move too far to the right, and makes it hard to read on a
-80-character terminal screen.  The answer to that is that if you need
-more than 3 levels of indentation, you're screwed anyway, and should fix
-your program.
-
-In short, 8-char indents make things easier to read, and have the added
-benefit of warning you when you're nesting your functions too deep.
-Heed that warning.
-
-The preferred way to ease multiple indentation levels in a switch statement is
-to align the ``switch`` and its subordinate ``case`` labels in the same column
-instead of ``double-indenting`` the ``case`` labels.  E.g.:
-
-.. code-block:: c
-
-	switch (suffix) {
-	case 'G':
-	case 'g':
-		mem <<= 30;
-		break;
-	case 'M':
-	case 'm':
-		mem <<= 20;
-		break;
-	case 'K':
-	case 'k':
-		mem <<= 10;
-		/* fall through */
-	default:
-		break;
-	}
-
-Don't put multiple statements on a single line unless you have
-something to hide:
-
-.. code-block:: c
-
-	if (condition) do_this;
-	  do_something_everytime;
-
-Don't put multiple assignments on a single line either.  Kernel coding style
-is super simple.  Avoid tricky expressions.
-
-Outside of comments, documentation and except in Kconfig, spaces are never
-used for indentation, and the above example is deliberately broken.
-
-Get a decent editor and don't leave whitespace at the end of lines.
-
-
-2) Breaking long lines and strings
-----------------------------------
-
-Coding style is all about readability and maintainability using commonly
-available tools.
-
-The limit on the length of lines is 80 columns and this is a strongly
-preferred limit.
-
-Statements longer than 80 columns will be broken into sensible chunks, unless
-exceeding 80 columns significantly increases readability and does not hide
-information. Descendants are always substantially shorter than the parent and
-are placed substantially to the right. The same applies to function headers
-with a long argument list. However, never break user-visible strings such as
-printk messages, because that breaks the ability to grep for them.
-
-
-3) Placing Braces and Spaces
-----------------------------
-
-The other issue that always comes up in C styling is the placement of
-braces.  Unlike the indent size, there are few technical reasons to
-choose one placement strategy over the other, but the preferred way, as
-shown to us by the prophets Kernighan and Ritchie, is to put the opening
-brace last on the line, and put the closing brace first, thusly:
-
-.. code-block:: c
-
-	if (x is true) {
-		we do y
-	}
-
-This applies to all non-function statement blocks (if, switch, for,
-while, do).  E.g.:
-
-.. code-block:: c
-
-	switch (action) {
-	case KOBJ_ADD:
-		return "add";
-	case KOBJ_REMOVE:
-		return "remove";
-	case KOBJ_CHANGE:
-		return "change";
-	default:
-		return NULL;
-	}
-
-However, there is one special case, namely functions: they have the
-opening brace at the beginning of the next line, thus:
-
-.. code-block:: c
-
-	int function(int x)
-	{
-		body of function
-	}
-
-Heretic people all over the world have claimed that this inconsistency
-is ...  well ...  inconsistent, but all right-thinking people know that
-(a) K&R are **right** and (b) K&R are right.  Besides, functions are
-special anyway (you can't nest them in C).
-
-Note that the closing brace is empty on a line of its own, **except** in
-the cases where it is followed by a continuation of the same statement,
-ie a ``while`` in a do-statement or an ``else`` in an if-statement, like
-this:
-
-.. code-block:: c
-
-	do {
-		body of do-loop
-	} while (condition);
-
-and
-
-.. code-block:: c
-
-	if (x == y) {
-		..
-	} else if (x > y) {
-		...
-	} else {
-		....
-	}
-
-Rationale: K&R.
-
-Also, note that this brace-placement also minimizes the number of empty
-(or almost empty) lines, without any loss of readability.  Thus, as the
-supply of new-lines on your screen is not a renewable resource (think
-25-line terminal screens here), you have more empty lines to put
-comments on.
-
-Do not unnecessarily use braces where a single statement will do.
-
-.. code-block:: c
-
-	if (condition)
-		action();
-
-and
-
-.. code-block:: none
-
-	if (condition)
-		do_this();
-	else
-		do_that();
-
-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:
-
-.. code-block:: c
-
-	if (condition) {
-		do_this();
-		do_that();
-	} else {
-		otherwise();
-	}
-
-3.1) Spaces
-***********
-
-Linux kernel style for use of spaces depends (mostly) on
-function-versus-keyword usage.  Use a space after (most) keywords.  The
-notable exceptions are sizeof, typeof, alignof, and __attribute__, which look
-somewhat like functions (and are usually used with parentheses in Linux,
-although they are not required in the language, as in: ``sizeof info`` after
-``struct fileinfo info;`` is declared).
-
-So use a space after these keywords::
-
-	if, switch, case, for, do, while
-
-but not with sizeof, typeof, alignof, or __attribute__.  E.g.,
-
-.. code-block:: c
-
-
-	s = sizeof(struct file);
-
-Do not add spaces around (inside) parenthesized expressions.  This example is
-**bad**:
-
-.. code-block:: c
-
-
-	s = sizeof( struct file );
-
-When declaring pointer data or a function that returns a pointer type, the
-preferred use of ``*`` is adjacent to the data name or function name and not
-adjacent to the type name.  Examples:
-
-.. code-block:: c
-
-
-	char *linux_banner;
-	unsigned long long memparse(char *ptr, char **retptr);
-	char *match_strdup(substring_t *s);
-
-Use one space around (on each side of) most binary and ternary operators,
-such as any of these::
-
-	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
-
-but no space after unary operators::
-
-	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
-
-no space before the postfix increment & decrement unary operators::
-
-	++  --
-
-no space after the prefix increment & decrement unary operators::
-
-	++  --
-
-and no space around the ``.`` and ``->`` structure member operators.
-
-Do not leave trailing whitespace at the ends of lines.  Some editors with
-``smart`` indentation will insert whitespace at the beginning of new lines as
-appropriate, so you can start typing the next line of code right away.
-However, some such editors do not remove the whitespace if you end up not
-putting a line of code there, such as if you leave a blank line.  As a result,
-you end up with lines containing trailing whitespace.
-
-Git will warn you about patches that introduce trailing whitespace, and can
-optionally strip the trailing whitespace for you; however, if applying a series
-of patches, this may make later patches in the series fail by changing their
-context lines.
-
-
-4) Naming
----------
-
-C is a Spartan language, and so should your naming be.  Unlike Modula-2
-and Pascal programmers, C programmers do not use cute names like
-ThisVariableIsATemporaryCounter.  A C programmer would call that
-variable ``tmp``, which is much easier to write, and not the least more
-difficult to understand.
-
-HOWEVER, while mixed-case names are frowned upon, descriptive names for
-global variables are a must.  To call a global function ``foo`` is a
-shooting offense.
-
-GLOBAL variables (to be used only if you **really** need them) need to
-have descriptive names, as do global functions.  If you have a function
-that counts the number of active users, you should call that
-``count_active_users()`` or similar, you should **not** call it ``cntusr()``.
-
-Encoding the type of a function into the name (so-called Hungarian
-notation) is brain damaged - the compiler knows the types anyway and can
-check those, and it only confuses the programmer.  No wonder MicroSoft
-makes buggy programs.
-
-LOCAL variable names should be short, and to the point.  If you have
-some random integer loop counter, it should probably be called ``i``.
-Calling it ``loop_counter`` is non-productive, if there is no chance of it
-being mis-understood.  Similarly, ``tmp`` can be just about any type of
-variable that is used to hold a temporary value.
-
-If you are afraid to mix up your local variable names, you have another
-problem, which is called the function-growth-hormone-imbalance syndrome.
-See chapter 6 (Functions).
-
-
-5) Typedefs
------------
-
-Please don't use things like ``vps_t``.
-It's a **mistake** to use typedef for structures and pointers. When you see a
-
-.. code-block:: c
-
-
-	vps_t a;
-
-in the source, what does it mean?
-In contrast, if it says
-
-.. code-block:: c
-
-	struct virtual_container *a;
-
-you can actually tell what ``a`` is.
-
-Lots of people think that typedefs ``help readability``. Not so. They are
-useful only for:
-
- (a) totally opaque objects (where the typedef is actively used to **hide**
-     what the object is).
-
-     Example: ``pte_t`` etc. opaque objects that you can only access using
-     the proper accessor functions.
-
-     .. note::
-
-       Opaqueness and ``accessor functions`` are not good in themselves.
-       The reason we have them for things like pte_t etc. is that there
-       really is absolutely **zero** portably accessible information there.
-
- (b) Clear integer types, where the abstraction **helps** avoid confusion
-     whether it is ``int`` or ``long``.
-
-     u8/u16/u32 are perfectly fine typedefs, although they fit into
-     category (d) better than here.
-
-     .. note::
-
-       Again - there needs to be a **reason** for this. If something is
-       ``unsigned long``, then there's no reason to do
-
-	typedef unsigned long myflags_t;
-
-     but if there is a clear reason for why it under certain circumstances
-     might be an ``unsigned int`` and under other configurations might be
-     ``unsigned long``, then by all means go ahead and use a typedef.
-
- (c) when you use sparse to literally create a **new** type for
-     type-checking.
-
- (d) New types which are identical to standard C99 types, in certain
-     exceptional circumstances.
-
-     Although it would only take a short amount of time for the eyes and
-     brain to become accustomed to the standard types like ``uint32_t``,
-     some people object to their use anyway.
-
-     Therefore, the Linux-specific ``u8/u16/u32/u64`` types and their
-     signed equivalents which are identical to standard types are
-     permitted -- although they are not mandatory in new code of your
-     own.
-
-     When editing existing code which already uses one or the other set
-     of types, you should conform to the existing choices in that code.
-
- (e) Types safe for use in userspace.
-
-     In certain structures which are visible to userspace, we cannot
-     require C99 types and cannot use the ``u32`` form above. Thus, we
-     use __u32 and similar types in all structures which are shared
-     with userspace.
-
-Maybe there are other cases too, but the rule should basically be to NEVER
-EVER use a typedef unless you can clearly match one of those rules.
-
-In general, a pointer, or a struct that has elements that can reasonably
-be directly accessed should **never** be a typedef.
-
-
-6) Functions
-------------
-
-Functions should be short and sweet, and do just one thing.  They should
-fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
-as we all know), and do one thing and do that well.
-
-The maximum length of a function is inversely proportional to the
-complexity and indentation level of that function.  So, if you have a
-conceptually simple function that is just one long (but simple)
-case-statement, where you have to do lots of small things for a lot of
-different cases, it's OK to have a longer function.
-
-However, if you have a complex function, and you suspect that a
-less-than-gifted first-year high-school student might not even
-understand what the function is all about, you should adhere to the
-maximum limits all the more closely.  Use helper functions with
-descriptive names (you can ask the compiler to in-line them if you think
-it's performance-critical, and it will probably do a better job of it
-than you would have done).
-
-Another measure of the function is the number of local variables.  They
-shouldn't exceed 5-10, or you're doing something wrong.  Re-think the
-function, and split it into smaller pieces.  A human brain can
-generally easily keep track of about 7 different things, anything more
-and it gets confused.  You know you're brilliant, but maybe you'd like
-to understand what you did 2 weeks from now.
-
-In source files, separate functions with one blank line.  If the function is
-exported, the **EXPORT** macro for it should follow immediately after the
-closing function brace line.  E.g.:
-
-.. code-block:: c
-
-	int system_is_up(void)
-	{
-		return system_state == SYSTEM_RUNNING;
-	}
-	EXPORT_SYMBOL(system_is_up);
-
-In function prototypes, include parameter names with their data types.
-Although this is not required by the C language, it is preferred in Linux
-because it is a simple way to add valuable information for the reader.
-
-
-7) Centralized exiting of functions
------------------------------------
-
-Albeit deprecated by some people, the equivalent of the goto statement is
-used frequently by compilers in form of the unconditional jump instruction.
-
-The goto statement comes in handy when a function exits from multiple
-locations and some common work such as cleanup has to be done.  If there is no
-cleanup needed then just return directly.
-
-Choose label names which say what the goto does or why the goto exists.  An
-example of a good name could be ``out_free_buffer:`` if the goto frees ``buffer``.
-Avoid using GW-BASIC names like ``err1:`` and ``err2:``, as you would have to
-renumber them if you ever add or remove exit paths, and they make correctness
-difficult to verify anyway.
-
-The rationale for using gotos is:
-
-- unconditional statements are easier to understand and follow
-- nesting is reduced
-- errors by not updating individual exit points when making
-  modifications are prevented
-- saves the compiler work to optimize redundant code away ;)
-
-.. code-block:: c
-
-	int fun(int a)
-	{
-		int result = 0;
-		char *buffer;
-
-		buffer = kmalloc(SIZE, GFP_KERNEL);
-		if (!buffer)
-			return -ENOMEM;
-
-		if (condition1) {
-			while (loop1) {
-				...
-			}
-			result = 1;
-			goto out_buffer;
-		}
-		...
-	out_free_buffer:
-		kfree(buffer);
-		return result;
-	}
-
-A common type of bug to be aware of is ``one err bugs`` which look like this:
-
-.. code-block:: c
-
-	err:
-		kfree(foo->bar);
-		kfree(foo);
-		return ret;
-
-The bug in this code is that on some exit paths ``foo`` is NULL.  Normally the
-fix for this is to split it up into two error labels ``err_free_bar:`` and
-``err_free_foo:``:
-
-.. code-block:: c
-
-	 err_free_bar:
-		kfree(foo->bar);
-	 err_free_foo:
-		kfree(foo);
-		return ret;
-
-Ideally you should simulate errors to test all exit paths.
-
-
-8) Commenting
--------------
-
-Comments are good, but there is also a danger of over-commenting.  NEVER
-try to explain HOW your code works in a comment: it's much better to
-write the code so that the **working** is obvious, and it's a waste of
-time to explain badly written code.
-
-Generally, you want your comments to tell WHAT your code does, not HOW.
-Also, try to avoid putting comments inside a function body: if the
-function is so complex that you need to separately comment parts of it,
-you should probably go back to chapter 6 for a while.  You can make
-small comments to note or warn about something particularly clever (or
-ugly), but try to avoid excess.  Instead, put the comments at the head
-of the function, telling people what it does, and possibly WHY it does
-it.
-
-When commenting the kernel API functions, please use the kernel-doc format.
-See the files Documentation/kernel-documentation.rst and scripts/kernel-doc
-for details.
-
-The preferred style for long (multi-line) comments is:
-
-.. code-block:: c
-
-	/*
-	 * This is the preferred style for multi-line
-	 * comments in the Linux kernel source code.
-	 * Please use it consistently.
-	 *
-	 * Description:  A column of asterisks on the left side,
-	 * with beginning and ending almost-blank lines.
-	 */
-
-For files in net/ and drivers/net/ the preferred style for long (multi-line)
-comments is a little different.
-
-.. code-block:: c
-
-	/* The preferred comment style for files in net/ and drivers/net
-	 * looks like this.
-	 *
-	 * It is nearly the same as the generally preferred comment style,
-	 * but there is no initial almost-blank line.
-	 */
-
-It's also important to comment data, whether they are basic types or derived
-types.  To this end, use just one data declaration per line (no commas for
-multiple data declarations).  This leaves you room for a small comment on each
-item, explaining its use.
-
-
-9) You've made a mess of it
----------------------------
-
-That's OK, we all do.  You've probably been told by your long-time Unix
-user helper that ``GNU emacs`` automatically formats the C sources for
-you, and you've noticed that yes, it does do that, but the defaults it
-uses are less than desirable (in fact, they are worse than random
-typing - an infinite number of monkeys typing into GNU emacs would never
-make a good program).
-
-So, you can either get rid of GNU emacs, or change it to use saner
-values.  To do the latter, you can stick the following in your .emacs file:
-
-.. code-block:: none
-
-  (defun c-lineup-arglist-tabs-only (ignored)
-    "Line up argument lists by tabs, not spaces"
-    (let* ((anchor (c-langelem-pos c-syntactic-element))
-           (column (c-langelem-2nd-pos c-syntactic-element))
-           (offset (- (1+ column) anchor))
-           (steps (floor offset c-basic-offset)))
-      (* (max steps 1)
-         c-basic-offset)))
-
-  (add-hook 'c-mode-common-hook
-            (lambda ()
-              ;; Add kernel style
-              (c-add-style
-               "linux-tabs-only"
-               '("linux" (c-offsets-alist
-                          (arglist-cont-nonempty
-                           c-lineup-gcc-asm-reg
-                           c-lineup-arglist-tabs-only))))))
-
-  (add-hook 'c-mode-hook
-            (lambda ()
-              (let ((filename (buffer-file-name)))
-                ;; Enable kernel mode for the appropriate files
-                (when (and filename
-                           (string-match (expand-file-name "~/src/linux-trees")
-                                         filename))
-                  (setq indent-tabs-mode t)
-                  (setq show-trailing-whitespace t)
-                  (c-set-style "linux-tabs-only")))))
-
-This will make emacs go better with the kernel coding style for C
-files below ``~/src/linux-trees``.
-
-But even if you fail in getting emacs to do sane formatting, not
-everything is lost: use ``indent``.
-
-Now, again, GNU indent has the same brain-dead settings that GNU emacs
-has, which is why you need to give it a few command line options.
-However, that's not too bad, because even the makers of GNU indent
-recognize the authority of K&R (the GNU people aren't evil, they are
-just severely misguided in this matter), so you just give indent the
-options ``-kr -i8`` (stands for ``K&R, 8 character indents``), or use
-``scripts/Lindent``, which indents in the latest style.
-
-``indent`` has a lot of options, and especially when it comes to comment
-re-formatting you may want to take a look at the man page.  But
-remember: ``indent`` is not a fix for bad programming.
-
-
-10) Kconfig configuration files
--------------------------------
-
-For all of the Kconfig* configuration files throughout the source tree,
-the indentation is somewhat different.  Lines under a ``config`` definition
-are indented with one tab, while help text is indented an additional two
-spaces.  Example::
-
-  config AUDIT
-	bool "Auditing support"
-	depends on NET
-	help
-	  Enable auditing infrastructure that can be used with another
-	  kernel subsystem, such as SELinux (which requires this for
-	  logging of avc messages output).  Does not do system-call
-	  auditing without CONFIG_AUDITSYSCALL.
-
-Seriously dangerous features (such as write support for certain
-filesystems) should advertise this prominently in their prompt string::
-
-  config ADFS_FS_RW
-	bool "ADFS write support (DANGEROUS)"
-	depends on ADFS_FS
-	...
-
-For full documentation on the configuration files, see the file
-Documentation/kbuild/kconfig-language.txt.
-
-
-11) Data structures
--------------------
-
-Data structures that have visibility outside the single-threaded
-environment they are created and destroyed in should always have
-reference counts.  In the kernel, garbage collection doesn't exist (and
-outside the kernel garbage collection is slow and inefficient), which
-means that you absolutely **have** to reference count all your uses.
-
-Reference counting means that you can avoid locking, and allows multiple
-users to have access to the data structure in parallel - and not having
-to worry about the structure suddenly going away from under them just
-because they slept or did something else for a while.
-
-Note that locking is **not** a replacement for reference counting.
-Locking is used to keep data structures coherent, while reference
-counting is a memory management technique.  Usually both are needed, and
-they are not to be confused with each other.
-
-Many data structures can indeed have two levels of reference counting,
-when there are users of different ``classes``.  The subclass count counts
-the number of subclass users, and decrements the global count just once
-when the subclass count goes to zero.
-
-Examples of this kind of ``multi-level-reference-counting`` can be found in
-memory management (``struct mm_struct``: mm_users and mm_count), and in
-filesystem code (``struct super_block``: s_count and s_active).
-
-Remember: if another thread can find your data structure, and you don't
-have a reference count on it, you almost certainly have a bug.
-
-
-12) Macros, Enums and RTL
--------------------------
-
-Names of macros defining constants and labels in enums are capitalized.
-
-.. code-block:: c
-
-	#define CONSTANT 0x12345
-
-Enums are preferred when defining several related constants.
-
-CAPITALIZED macro names are appreciated but macros resembling functions
-may be named in lower case.
-
-Generally, inline functions are preferable to macros resembling functions.
-
-Macros with multiple statements should be enclosed in a do - while block:
-
-.. code-block:: c
-
-	#define macrofun(a, b, c)			\
-		do {					\
-			if (a == 5)			\
-				do_this(b, c);		\
-		} while (0)
-
-Things to avoid when using macros:
-
-1) macros that affect control flow:
-
-.. code-block:: c
-
-	#define FOO(x)					\
-		do {					\
-			if (blah(x) < 0)		\
-				return -EBUGGERED;	\
-		} while (0)
-
-is a **very** bad idea.  It looks like a function call but exits the ``calling``
-function; don't break the internal parsers of those who will read the code.
-
-2) macros that depend on having a local variable with a magic name:
-
-.. code-block:: c
-
-	#define FOO(val) bar(index, val)
-
-might look like a good thing, but it's confusing as hell when one reads the
-code and it's prone to breakage from seemingly innocent changes.
-
-3) macros with arguments that are used as l-values: FOO(x) = y; will
-bite you if somebody e.g. turns FOO into an inline function.
-
-4) forgetting about precedence: macros defining constants using expressions
-must enclose the expression in parentheses. Beware of similar issues with
-macros using parameters.
-
-.. code-block:: c
-
-	#define CONSTANT 0x4000
-	#define CONSTEXP (CONSTANT | 3)
-
-5) namespace collisions when defining local variables in macros resembling
-functions:
-
-.. code-block:: c
-
-	#define FOO(x)				\
-	({					\
-		typeof(x) ret;			\
-		ret = calc_ret(x);		\
-		(ret);				\
-	})
-
-ret is a common name for a local variable - __foo_ret is less likely
-to collide with an existing variable.
-
-The cpp manual deals with macros exhaustively. The gcc internals manual also
-covers RTL which is used frequently with assembly language in the kernel.
-
-
-13) Printing kernel messages
-----------------------------
-
-Kernel developers like to be seen as literate. Do mind the spelling
-of kernel messages to make a good impression. Do not use crippled
-words like ``dont``; use ``do not`` or ``don't`` instead.  Make the messages
-concise, clear, and unambiguous.
-
-Kernel messages do not have to be terminated with a period.
-
-Printing numbers in parentheses (%d) adds no value and should be avoided.
-
-There are a number of driver model diagnostic macros in <linux/device.h>
-which you should use to make sure messages are matched to the right device
-and driver, and are tagged with the right level:  dev_err(), dev_warn(),
-dev_info(), and so forth.  For messages that aren't associated with a
-particular device, <linux/printk.h> defines pr_notice(), pr_info(),
-pr_warn(), pr_err(), etc.
-
-Coming up with good debugging messages can be quite a challenge; and once
-you have them, they can be a huge help for remote troubleshooting.  However
-debug message printing is handled differently than printing other non-debug
-messages.  While the other pr_XXX() functions print unconditionally,
-pr_debug() does not; it is compiled out by default, unless either DEBUG is
-defined or CONFIG_DYNAMIC_DEBUG is set.  That is true for dev_dbg() also,
-and a related convention uses VERBOSE_DEBUG to add dev_vdbg() messages to
-the ones already enabled by DEBUG.
-
-Many subsystems have Kconfig debug options to turn on -DDEBUG in the
-corresponding Makefile; in other cases specific files #define DEBUG.  And
-when a debug message should be unconditionally printed, such as if it is
-already inside a debug-related #ifdef section, printk(KERN_DEBUG ...) can be
-used.
-
-
-14) Allocating memory
----------------------
-
-The kernel provides the following general purpose memory allocators:
-kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), and
-vzalloc().  Please refer to the API documentation for further information
-about them.
-
-The preferred form for passing a size of a struct is the following:
-
-.. code-block:: c
-
-	p = kmalloc(sizeof(*p), ...);
-
-The alternative form where struct name is spelled out hurts readability and
-introduces an opportunity for a bug when the pointer variable type is changed
-but the corresponding sizeof that is passed to a memory allocator is not.
-
-Casting the return value which is a void pointer is redundant. The conversion
-from void pointer to any other pointer type is guaranteed by the C programming
-language.
-
-The preferred form for allocating an array is the following:
-
-.. code-block:: c
-
-	p = kmalloc_array(n, sizeof(...), ...);
-
-The preferred form for allocating a zeroed array is the following:
-
-.. code-block:: c
-
-	p = kcalloc(n, sizeof(...), ...);
-
-Both forms check for overflow on the allocation size n * sizeof(...),
-and return NULL if that occurred.
-
-
-15) The inline disease
-----------------------
-
-There appears to be a common misperception that gcc has a magic "make me
-faster" speedup option called ``inline``. While the use of inlines can be
-appropriate (for example as a means of replacing macros, see Chapter 12), it
-very often is not. Abundant use of the inline keyword leads to a much bigger
-kernel, which in turn slows the system as a whole down, due to a bigger
-icache footprint for the CPU and simply because there is less memory
-available for the pagecache. Just think about it; a pagecache miss causes a
-disk seek, which easily takes 5 milliseconds. There are a LOT of cpu cycles
-that can go into these 5 milliseconds.
-
-A reasonable rule of thumb is to not put inline at functions that have more
-than 3 lines of code in them. An exception to this rule are the cases where
-a parameter is known to be a compiletime constant, and as a result of this
-constantness you *know* the compiler will be able to optimize most of your
-function away at compile time. For a good example of this later case, see
-the kmalloc() inline function.
-
-Often people argue that adding inline to functions that are static and used
-only once is always a win since there is no space tradeoff. While this is
-technically correct, gcc is capable of inlining these automatically without
-help, and the maintenance issue of removing the inline when a second user
-appears outweighs the potential value of the hint that tells gcc to do
-something it would have done anyway.
-
-
-16) Function return values and names
-------------------------------------
-
-Functions can return values of many different kinds, and one of the
-most common is a value indicating whether the function succeeded or
-failed.  Such a value can be represented as an error-code integer
-(-Exxx = failure, 0 = success) or a ``succeeded`` boolean (0 = failure,
-non-zero = success).
-
-Mixing up these two sorts of representations is a fertile source of
-difficult-to-find bugs.  If the C language included a strong distinction
-between integers and booleans then the compiler would find these mistakes
-for us... but it doesn't.  To help prevent such bugs, always follow this
-convention::
-
-	If the name of a function is an action or an imperative command,
-	the function should return an error-code integer.  If the name
-	is a predicate, the function should return a "succeeded" boolean.
-
-For example, ``add work`` is a command, and the add_work() function returns 0
-for success or -EBUSY for failure.  In the same way, ``PCI device present`` is
-a predicate, and the pci_dev_present() function returns 1 if it succeeds in
-finding a matching device or 0 if it doesn't.
-
-All EXPORTed functions must respect this convention, and so should all
-public functions.  Private (static) functions need not, but it is
-recommended that they do.
-
-Functions whose return value is the actual result of a computation, rather
-than an indication of whether the computation succeeded, are not subject to
-this rule.  Generally they indicate failure by returning some out-of-range
-result.  Typical examples would be functions that return pointers; they use
-NULL or the ERR_PTR mechanism to report failure.
-
-
-17) Don't re-invent the kernel macros
--------------------------------------
-
-The header file include/linux/kernel.h contains a number of macros that
-you should use, rather than explicitly coding some variant of them yourself.
-For example, if you need to calculate the length of an array, take advantage
-of the macro
-
-.. code-block:: c
-
-	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-Similarly, if you need to calculate the size of some structure member, use
-
-.. code-block:: c
-
-	#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
-
-There are also min() and max() macros that do strict type checking if you
-need them.  Feel free to peruse that header file to see what else is already
-defined that you shouldn't reproduce in your code.
-
-
-18) Editor modelines and other cruft
-------------------------------------
-
-Some editors can interpret configuration information embedded in source files,
-indicated with special markers.  For example, emacs interprets lines marked
-like this:
-
-.. code-block:: c
-
-	-*- mode: c -*-
-
-Or like this:
-
-.. code-block:: c
-
-	/*
-	Local Variables:
-	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
-	End:
-	*/
-
-Vim interprets markers that look like this:
-
-.. code-block:: c
-
-	/* vim:set sw=8 noet */
-
-Do not include any of these in source files.  People have their own personal
-editor configurations, and your source files should not override them.  This
-includes markers for indentation and mode configuration.  People may use their
-own custom mode, or may have some other magic method for making indentation
-work correctly.
-
-
-19) Inline assembly
--------------------
-
-In architecture-specific code, you may need to use inline assembly to interface
-with CPU or platform functionality.  Don't hesitate to do so when necessary.
-However, don't use inline assembly gratuitously when C can do the job.  You can
-and should poke hardware from C when possible.
-
-Consider writing simple helper functions that wrap common bits of inline
-assembly, rather than repeatedly writing them with slight variations.  Remember
-that inline assembly can use C parameters.
-
-Large, non-trivial assembly functions should go in .S files, with corresponding
-C prototypes defined in C header files.  The C prototypes for assembly
-functions should use ``asmlinkage``.
-
-You may need to mark your asm statement as volatile, to prevent GCC from
-removing it if GCC doesn't notice any side effects.  You don't always need to
-do so, though, and doing so unnecessarily can limit optimization.
-
-When writing a single inline assembly statement containing multiple
-instructions, put each instruction on a separate line in a separate quoted
-string, and end each string except the last with \n\t to properly indent the
-next instruction in the assembly output:
-
-.. code-block:: c
-
-	asm ("magic %reg1, #42\n\t"
-	     "more_magic %reg2, %reg3"
-	     : /* outputs */ : /* inputs */ : /* clobbers */);
-
-
-20) Conditional Compilation
----------------------------
-
-Wherever possible, don't use preprocessor conditionals (#if, #ifdef) in .c
-files; doing so makes code harder to read and logic harder to follow.  Instead,
-use such conditionals in a header file defining functions for use in those .c
-files, providing no-op stub versions in the #else case, and then call those
-functions unconditionally from .c files.  The compiler will avoid generating
-any code for the stub calls, producing identical results, but the logic will
-remain easy to follow.
-
-Prefer to compile out entire functions, rather than portions of functions or
-portions of expressions.  Rather than putting an ifdef in an expression, factor
-out part or all of the expression into a separate helper function and apply the
-conditional to that function.
-
-If you have a function or variable which may potentially go unused in a
-particular configuration, and the compiler would warn about its definition
-going unused, mark the definition as __maybe_unused rather than wrapping it in
-a preprocessor conditional.  (However, if a function or variable *always* goes
-unused, delete it.)
-
-Within code, where possible, use the IS_ENABLED macro to convert a Kconfig
-symbol into a C boolean expression, and use it in a normal C conditional:
-
-.. code-block:: c
-
-	if (IS_ENABLED(CONFIG_SOMETHING)) {
-		...
-	}
-
-The compiler will constant-fold the conditional away, and include or exclude
-the block of code just as with an #ifdef, so this will not add any runtime
-overhead.  However, this approach still allows the C compiler to see the code
-inside the block, and check it for correctness (syntax, types, symbol
-references, etc).  Thus, you still have to use an #ifdef if the code inside the
-block references symbols that will not exist if the condition is not met.
-
-At the end of any non-trivial #if or #ifdef block (more than a few lines),
-place a comment after the #endif on the same line, noting the conditional
-expression used.  For instance:
-
-.. code-block:: c
-
-	#ifdef CONFIG_SOMETHING
-	...
-	#endif /* CONFIG_SOMETHING */
-
-
-Appendix I) References
-----------------------
-
-The C Programming Language, Second Edition
-by Brian W. Kernighan and Dennis M. Ritchie.
-Prentice Hall, Inc., 1988.
-ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
-
-The Practice of Programming
-by Brian W. Kernighan and Rob Pike.
-Addison-Wesley, Inc., 1999.
-ISBN 0-201-61586-X.
-
-GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
-gcc internals and indent, all available from http://www.gnu.org/manual/
-
-WG14 is the international standardization working group for the programming
-language C, URL: http://www.open-std.org/JTC1/SC22/WG14/
-
-Kernel CodingStyle, by greg@kroah.com at OLS 2002:
-http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
+This file has moved to process/coding-style.rst
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/conf.py linux-libre-4.10-rc8-gnu/Documentation/conf.py
--- linux-libre-4.9-gnu/Documentation/conf.py	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -34,10 +34,10 @@ from load_config import loadConfig
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
-extensions = ['kernel-doc', 'rstFlatTable', 'kernel_include', 'cdomain']
+extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain']
 
 # The name of the math extension changed on Sphinx 1.4
-if minor > 3:
+if major == 1 and minor > 3:
     extensions.append("sphinx.ext.imgmath")
 else:
     extensions.append("sphinx.ext.pngmath")
@@ -136,7 +136,7 @@ pygments_style = 'sphinx'
 todo_include_todos = False
 
 primary_domain = 'C'
-highlight_language = 'guess'
+highlight_language = 'none'
 
 # -- Options for HTML output ----------------------------------------------
 
@@ -332,18 +332,32 @@ latex_elements = {
      '''
 }
 
+# Fix reference escape troubles with Sphinx 1.4.x
+if major == 1 and minor > 3:
+    latex_elements['preamble']  += '\\renewcommand*{\\DUrole}[2]{ #2 }\n'
+
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
 latex_documents = [
+    ('doc-guide/index', 'kernel-doc-guide.tex', 'Linux Kernel Documentation Guide',
+     'The kernel development community', 'manual'),
+    ('admin-guide/index', 'linux-user.tex', 'Linux Kernel User Documentation',
+     'The kernel development community', 'manual'),
+    ('core-api/index', 'core-api.tex', 'The kernel core API manual',
+     'The kernel development community', 'manual'),
+    ('driver-api/index', 'driver-api.tex', 'The kernel driver API manual',
+     'The kernel development community', 'manual'),
     ('kernel-documentation', 'kernel-documentation.tex', 'The Linux Kernel Documentation',
      'The kernel development community', 'manual'),
-    ('development-process/index', 'development-process.tex', 'Linux Kernel Development Documentation',
+    ('process/index', 'development-process.tex', 'Linux Kernel Development Documentation',
      'The kernel development community', 'manual'),
     ('gpu/index', 'gpu.tex', 'Linux GPU Driver Developer\'s Guide',
      'The kernel development community', 'manual'),
     ('media/index', 'media.tex', 'Linux Media Subsystem Documentation',
      'The kernel development community', 'manual'),
+    ('security/index', 'security.tex', 'The kernel security subsystem manual',
+     'The kernel development community', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/assoc_array.rst linux-libre-4.10-rc8-gnu/Documentation/core-api/assoc_array.rst
--- linux-libre-4.9-gnu/Documentation/core-api/assoc_array.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/assoc_array.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,551 @@
+========================================
+Generic Associative Array Implementation
+========================================
+
+Overview
+========
+
+This associative array implementation is an object container with the following
+properties:
+
+1. Objects are opaque pointers.  The implementation does not care where they
+   point (if anywhere) or what they point to (if anything).
+.. note:: Pointers to objects _must_ be zero in the least significant bit.
+
+2. Objects do not need to contain linkage blocks for use by the array.  This
+   permits an object to be located in multiple arrays simultaneously.
+   Rather, the array is made up of metadata blocks that point to objects.
+
+3. Objects require index keys to locate them within the array.
+
+4. Index keys must be unique.  Inserting an object with the same key as one
+   already in the array will replace the old object.
+
+5. Index keys can be of any length and can be of different lengths.
+
+6. Index keys should encode the length early on, before any variation due to
+   length is seen.
+
+7. Index keys can include a hash to scatter objects throughout the array.
+
+8. The array can iterated over.  The objects will not necessarily come out in
+   key order.
+
+9. The array can be iterated over whilst it is being modified, provided the
+   RCU readlock is being held by the iterator.  Note, however, under these
+   circumstances, some objects may be seen more than once.  If this is a
+   problem, the iterator should lock against modification.  Objects will not
+   be missed, however, unless deleted.
+
+10. Objects in the array can be looked up by means of their index key.
+
+11. Objects can be looked up whilst the array is being modified, provided the
+    RCU readlock is being held by the thread doing the look up.
+
+The implementation uses a tree of 16-pointer nodes internally that are indexed
+on each level by nibbles from the index key in the same manner as in a radix
+tree.  To improve memory efficiency, shortcuts can be emplaced to skip over
+what would otherwise be a series of single-occupancy nodes.  Further, nodes
+pack leaf object pointers into spare space in the node rather than making an
+extra branch until as such time an object needs to be added to a full node.
+
+
+The Public API
+==============
+
+The public API can be found in ``<linux/assoc_array.h>``.  The associative
+array is rooted on the following structure::
+
+    struct assoc_array {
+            ...
+    };
+
+The code is selected by enabling ``CONFIG_ASSOCIATIVE_ARRAY`` with::
+
+    ./script/config -e ASSOCIATIVE_ARRAY
+
+
+Edit Script
+-----------
+
+The insertion and deletion functions produce an 'edit script' that can later be
+applied to effect the changes without risking ``ENOMEM``. This retains the
+preallocated metadata blocks that will be installed in the internal tree and
+keeps track of the metadata blocks that will be removed from the tree when the
+script is applied.
+
+This is also used to keep track of dead blocks and dead objects after the
+script has been applied so that they can be freed later.  The freeing is done
+after an RCU grace period has passed - thus allowing access functions to
+proceed under the RCU read lock.
+
+The script appears as outside of the API as a pointer of the type::
+
+    struct assoc_array_edit;
+
+There are two functions for dealing with the script:
+
+1. Apply an edit script::
+
+    void assoc_array_apply_edit(struct assoc_array_edit *edit);
+
+This will perform the edit functions, interpolating various write barriers
+to permit accesses under the RCU read lock to continue.  The edit script
+will then be passed to ``call_rcu()`` to free it and any dead stuff it points
+to.
+
+2. Cancel an edit script::
+
+    void assoc_array_cancel_edit(struct assoc_array_edit *edit);
+
+This frees the edit script and all preallocated memory immediately. If
+this was for insertion, the new object is _not_ released by this function,
+but must rather be released by the caller.
+
+These functions are guaranteed not to fail.
+
+
+Operations Table
+----------------
+
+Various functions take a table of operations::
+
+    struct assoc_array_ops {
+            ...
+    };
+
+This points to a number of methods, all of which need to be provided:
+
+1. Get a chunk of index key from caller data::
+
+    unsigned long (*get_key_chunk)(const void *index_key, int level);
+
+This should return a chunk of caller-supplied index key starting at the
+*bit* position given by the level argument.  The level argument will be a
+multiple of ``ASSOC_ARRAY_KEY_CHUNK_SIZE`` and the function should return
+``ASSOC_ARRAY_KEY_CHUNK_SIZE bits``.  No error is possible.
+
+
+2. Get a chunk of an object's index key::
+
+    unsigned long (*get_object_key_chunk)(const void *object, int level);
+
+As the previous function, but gets its data from an object in the array
+rather than from a caller-supplied index key.
+
+
+3. See if this is the object we're looking for::
+
+    bool (*compare_object)(const void *object, const void *index_key);
+
+Compare the object against an index key and return ``true`` if it matches and
+``false`` if it doesn't.
+
+
+4. Diff the index keys of two objects::
+
+    int (*diff_objects)(const void *object, const void *index_key);
+
+Return the bit position at which the index key of the specified object
+differs from the given index key or -1 if they are the same.
+
+
+5. Free an object::
+
+    void (*free_object)(void *object);
+
+Free the specified object.  Note that this may be called an RCU grace period
+after ``assoc_array_apply_edit()`` was called, so ``synchronize_rcu()`` may be
+necessary on module unloading.
+
+
+Manipulation Functions
+----------------------
+
+There are a number of functions for manipulating an associative array:
+
+1. Initialise an associative array::
+
+    void assoc_array_init(struct assoc_array *array);
+
+This initialises the base structure for an associative array.  It can't fail.
+
+
+2. Insert/replace an object in an associative array::
+
+    struct assoc_array_edit *
+    assoc_array_insert(struct assoc_array *array,
+                       const struct assoc_array_ops *ops,
+                       const void *index_key,
+                       void *object);
+
+This inserts the given object into the array.  Note that the least
+significant bit of the pointer must be zero as it's used to type-mark
+pointers internally.
+
+If an object already exists for that key then it will be replaced with the
+new object and the old one will be freed automatically.
+
+The ``index_key`` argument should hold index key information and is
+passed to the methods in the ops table when they are called.
+
+This function makes no alteration to the array itself, but rather returns
+an edit script that must be applied.  ``-ENOMEM`` is returned in the case of
+an out-of-memory error.
+
+The caller should lock exclusively against other modifiers of the array.
+
+
+3. Delete an object from an associative array::
+
+    struct assoc_array_edit *
+    assoc_array_delete(struct assoc_array *array,
+                       const struct assoc_array_ops *ops,
+                       const void *index_key);
+
+This deletes an object that matches the specified data from the array.
+
+The ``index_key`` argument should hold index key information and is
+passed to the methods in the ops table when they are called.
+
+This function makes no alteration to the array itself, but rather returns
+an edit script that must be applied.  ``-ENOMEM`` is returned in the case of
+an out-of-memory error.  ``NULL`` will be returned if the specified object is
+not found within the array.
+
+The caller should lock exclusively against other modifiers of the array.
+
+
+4. Delete all objects from an associative array::
+
+    struct assoc_array_edit *
+    assoc_array_clear(struct assoc_array *array,
+                      const struct assoc_array_ops *ops);
+
+This deletes all the objects from an associative array and leaves it
+completely empty.
+
+This function makes no alteration to the array itself, but rather returns
+an edit script that must be applied.  ``-ENOMEM`` is returned in the case of
+an out-of-memory error.
+
+The caller should lock exclusively against other modifiers of the array.
+
+
+5. Destroy an associative array, deleting all objects::
+
+    void assoc_array_destroy(struct assoc_array *array,
+                             const struct assoc_array_ops *ops);
+
+This destroys the contents of the associative array and leaves it
+completely empty.  It is not permitted for another thread to be traversing
+the array under the RCU read lock at the same time as this function is
+destroying it as no RCU deferral is performed on memory release -
+something that would require memory to be allocated.
+
+The caller should lock exclusively against other modifiers and accessors
+of the array.
+
+
+6. Garbage collect an associative array::
+
+    int assoc_array_gc(struct assoc_array *array,
+                       const struct assoc_array_ops *ops,
+                       bool (*iterator)(void *object, void *iterator_data),
+                       void *iterator_data);
+
+This iterates over the objects in an associative array and passes each one to
+``iterator()``.  If ``iterator()`` returns ``true``, the object is kept.  If it
+returns ``false``, the object will be freed.  If the ``iterator()`` function
+returns ``true``, it must perform any appropriate refcount incrementing on the
+object before returning.
+
+The internal tree will be packed down if possible as part of the iteration
+to reduce the number of nodes in it.
+
+The ``iterator_data`` is passed directly to ``iterator()`` and is otherwise
+ignored by the function.
+
+The function will return ``0`` if successful and ``-ENOMEM`` if there wasn't
+enough memory.
+
+It is possible for other threads to iterate over or search the array under
+the RCU read lock whilst this function is in progress.  The caller should
+lock exclusively against other modifiers of the array.
+
+
+Access Functions
+----------------
+
+There are two functions for accessing an associative array:
+
+1. Iterate over all the objects in an associative array::
+
+    int assoc_array_iterate(const struct assoc_array *array,
+                            int (*iterator)(const void *object,
+                                            void *iterator_data),
+                            void *iterator_data);
+
+This passes each object in the array to the iterator callback function.
+``iterator_data`` is private data for that function.
+
+This may be used on an array at the same time as the array is being
+modified, provided the RCU read lock is held.  Under such circumstances,
+it is possible for the iteration function to see some objects twice.  If
+this is a problem, then modification should be locked against.  The
+iteration algorithm should not, however, miss any objects.
+
+The function will return ``0`` if no objects were in the array or else it will
+return the result of the last iterator function called.  Iteration stops
+immediately if any call to the iteration function results in a non-zero
+return.
+
+
+2. Find an object in an associative array::
+
+    void *assoc_array_find(const struct assoc_array *array,
+                           const struct assoc_array_ops *ops,
+                           const void *index_key);
+
+This walks through the array's internal tree directly to the object
+specified by the index key..
+
+This may be used on an array at the same time as the array is being
+modified, provided the RCU read lock is held.
+
+The function will return the object if found (and set ``*_type`` to the object
+type) or will return ``NULL`` if the object was not found.
+
+
+Index Key Form
+--------------
+
+The index key can be of any form, but since the algorithms aren't told how long
+the key is, it is strongly recommended that the index key includes its length
+very early on before any variation due to the length would have an effect on
+comparisons.
+
+This will cause leaves with different length keys to scatter away from each
+other - and those with the same length keys to cluster together.
+
+It is also recommended that the index key begin with a hash of the rest of the
+key to maximise scattering throughout keyspace.
+
+The better the scattering, the wider and lower the internal tree will be.
+
+Poor scattering isn't too much of a problem as there are shortcuts and nodes
+can contain mixtures of leaves and metadata pointers.
+
+The index key is read in chunks of machine word.  Each chunk is subdivided into
+one nibble (4 bits) per level, so on a 32-bit CPU this is good for 8 levels and
+on a 64-bit CPU, 16 levels.  Unless the scattering is really poor, it is
+unlikely that more than one word of any particular index key will have to be
+used.
+
+
+Internal Workings
+=================
+
+The associative array data structure has an internal tree.  This tree is
+constructed of two types of metadata blocks: nodes and shortcuts.
+
+A node is an array of slots.  Each slot can contain one of four things:
+
+* A NULL pointer, indicating that the slot is empty.
+* A pointer to an object (a leaf).
+* A pointer to a node at the next level.
+* A pointer to a shortcut.
+
+
+Basic Internal Tree Layout
+--------------------------
+
+Ignoring shortcuts for the moment, the nodes form a multilevel tree.  The index
+key space is strictly subdivided by the nodes in the tree and nodes occur on
+fixed levels.  For example::
+
+ Level: 0               1               2               3
+        =============== =============== =============== ===============
+                                                        NODE D
+                        NODE B          NODE C  +------>+---+
+                +------>+---+   +------>+---+   |       | 0 |
+        NODE A  |       | 0 |   |       | 0 |   |       +---+
+        +---+   |       +---+   |       +---+   |       :   :
+        | 0 |   |       :   :   |       :   :   |       +---+
+        +---+   |       +---+   |       +---+   |       | f |
+        | 1 |---+       | 3 |---+       | 7 |---+       +---+
+        +---+           +---+           +---+
+        :   :           :   :           | 8 |---+
+        +---+           +---+           +---+   |       NODE E
+        | e |---+       | f |           :   :   +------>+---+
+        +---+   |       +---+           +---+           | 0 |
+        | f |   |                       | f |           +---+
+        +---+   |                       +---+           :   :
+                |       NODE F                          +---+
+                +------>+---+                           | f |
+                        | 0 |           NODE G          +---+
+                        +---+   +------>+---+
+                        :   :   |       | 0 |
+                        +---+   |       +---+
+                        | 6 |---+       :   :
+                        +---+           +---+
+                        :   :           | f |
+                        +---+           +---+
+                        | f |
+                        +---+
+
+In the above example, there are 7 nodes (A-G), each with 16 slots (0-f).
+Assuming no other meta data nodes in the tree, the key space is divided
+thusly::
+
+    KEY PREFIX      NODE
+    ==========      ====
+    137*            D
+    138*            E
+    13[0-69-f]*     C
+    1[0-24-f]*      B
+    e6*             G
+    e[0-57-f]*      F
+    [02-df]*        A
+
+So, for instance, keys with the following example index keys will be found in
+the appropriate nodes::
+
+    INDEX KEY       PREFIX  NODE
+    =============== ======= ====
+    13694892892489  13      C
+    13795289025897  137     D
+    13889dde88793   138     E
+    138bbb89003093  138     E
+    1394879524789   12      C
+    1458952489      1       B
+    9431809de993ba  -       A
+    b4542910809cd   -       A
+    e5284310def98   e       F
+    e68428974237    e6      G
+    e7fffcbd443     e       F
+    f3842239082     -       A
+
+To save memory, if a node can hold all the leaves in its portion of keyspace,
+then the node will have all those leaves in it and will not have any metadata
+pointers - even if some of those leaves would like to be in the same slot.
+
+A node can contain a heterogeneous mix of leaves and metadata pointers.
+Metadata pointers must be in the slots that match their subdivisions of key
+space.  The leaves can be in any slot not occupied by a metadata pointer.  It
+is guaranteed that none of the leaves in a node will match a slot occupied by a
+metadata pointer.  If the metadata pointer is there, any leaf whose key matches
+the metadata key prefix must be in the subtree that the metadata pointer points
+to.
+
+In the above example list of index keys, node A will contain::
+
+    SLOT    CONTENT         INDEX KEY (PREFIX)
+    ====    =============== ==================
+    1       PTR TO NODE B   1*
+    any     LEAF            9431809de993ba
+    any     LEAF            b4542910809cd
+    e       PTR TO NODE F   e*
+    any     LEAF            f3842239082
+
+and node B::
+
+    3	PTR TO NODE C	13*
+    any	LEAF		1458952489
+
+
+Shortcuts
+---------
+
+Shortcuts are metadata records that jump over a piece of keyspace.  A shortcut
+is a replacement for a series of single-occupancy nodes ascending through the
+levels.  Shortcuts exist to save memory and to speed up traversal.
+
+It is possible for the root of the tree to be a shortcut - say, for example,
+the tree contains at least 17 nodes all with key prefix ``1111``.  The
+insertion algorithm will insert a shortcut to skip over the ``1111`` keyspace
+in a single bound and get to the fourth level where these actually become
+different.
+
+
+Splitting And Collapsing Nodes
+------------------------------
+
+Each node has a maximum capacity of 16 leaves and metadata pointers.  If the
+insertion algorithm finds that it is trying to insert a 17th object into a
+node, that node will be split such that at least two leaves that have a common
+key segment at that level end up in a separate node rooted on that slot for
+that common key segment.
+
+If the leaves in a full node and the leaf that is being inserted are
+sufficiently similar, then a shortcut will be inserted into the tree.
+
+When the number of objects in the subtree rooted at a node falls to 16 or
+fewer, then the subtree will be collapsed down to a single node - and this will
+ripple towards the root if possible.
+
+
+Non-Recursive Iteration
+-----------------------
+
+Each node and shortcut contains a back pointer to its parent and the number of
+slot in that parent that points to it.  None-recursive iteration uses these to
+proceed rootwards through the tree, going to the parent node, slot N + 1 to
+make sure progress is made without the need for a stack.
+
+The backpointers, however, make simultaneous alteration and iteration tricky.
+
+
+Simultaneous Alteration And Iteration
+-------------------------------------
+
+There are a number of cases to consider:
+
+1. Simple insert/replace.  This involves simply replacing a NULL or old
+   matching leaf pointer with the pointer to the new leaf after a barrier.
+   The metadata blocks don't change otherwise.  An old leaf won't be freed
+   until after the RCU grace period.
+
+2. Simple delete.  This involves just clearing an old matching leaf.  The
+   metadata blocks don't change otherwise.  The old leaf won't be freed until
+   after the RCU grace period.
+
+3. Insertion replacing part of a subtree that we haven't yet entered.  This
+   may involve replacement of part of that subtree - but that won't affect
+   the iteration as we won't have reached the pointer to it yet and the
+   ancestry blocks are not replaced (the layout of those does not change).
+
+4. Insertion replacing nodes that we're actively processing.  This isn't a
+   problem as we've passed the anchoring pointer and won't switch onto the
+   new layout until we follow the back pointers - at which point we've
+   already examined the leaves in the replaced node (we iterate over all the
+   leaves in a node before following any of its metadata pointers).
+
+   We might, however, re-see some leaves that have been split out into a new
+   branch that's in a slot further along than we were at.
+
+5. Insertion replacing nodes that we're processing a dependent branch of.
+   This won't affect us until we follow the back pointers.  Similar to (4).
+
+6. Deletion collapsing a branch under us.  This doesn't affect us because the
+   back pointers will get us back to the parent of the new node before we
+   could see the new node.  The entire collapsed subtree is thrown away
+   unchanged - and will still be rooted on the same slot, so we shouldn't
+   process it a second time as we'll go back to slot + 1.
+
+.. note::
+
+   Under some circumstances, we need to simultaneously change the parent
+   pointer and the parent slot pointer on a node (say, for example, we
+   inserted another node before it and moved it up a level).  We cannot do
+   this without locking against a read - so we have to replace that node too.
+
+   However, when we're changing a shortcut into a node this isn't a problem
+   as shortcuts only have one slot and so the parent slot number isn't used
+   when traversing backwards over one.  This means that it's okay to change
+   the slot number first - provided suitable barriers are used to make sure
+   the parent slot number is read after the back pointer.
+
+Obsolete blocks and leaves are freed up after an RCU grace period has passed,
+so as long as anyone doing walking or iteration holds the RCU read lock, the
+old superstructure should not go away on them.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/atomic_ops.rst linux-libre-4.10-rc8-gnu/Documentation/core-api/atomic_ops.rst
--- linux-libre-4.9-gnu/Documentation/core-api/atomic_ops.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/atomic_ops.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,658 @@
+=======================================================
+Semantics and Behavior of Atomic and Bitmask Operations
+=======================================================
+
+:Author: David S. Miller
+
+This document is intended to serve as a guide to Linux port
+maintainers on how to implement atomic counter, bitops, and spinlock
+interfaces properly.
+
+Atomic Type And Operations
+==========================
+
+The atomic_t type should be defined as a signed integer and
+the atomic_long_t type as a signed long integer.  Also, they should
+be made opaque such that any kind of cast to a normal C integer type
+will fail.  Something like the following should suffice::
+
+	typedef struct { int counter; } atomic_t;
+	typedef struct { long counter; } atomic_long_t;
+
+Historically, counter has been declared volatile.  This is now discouraged.
+See :ref:`Documentation/process/volatile-considered-harmful.rst
+<volatile_considered_harmful>` for the complete rationale.
+
+local_t is very similar to atomic_t. If the counter is per CPU and only
+updated by one CPU, local_t is probably more appropriate. Please see
+:ref:`Documentation/core-api/local_ops.rst <local_ops>` for the semantics of
+local_t.
+
+The first operations to implement for atomic_t's are the initializers and
+plain reads. ::
+
+	#define ATOMIC_INIT(i)		{ (i) }
+	#define atomic_set(v, i)	((v)->counter = (i))
+
+The first macro is used in definitions, such as::
+
+	static atomic_t my_counter = ATOMIC_INIT(1);
+
+The initializer is atomic in that the return values of the atomic operations
+are guaranteed to be correct reflecting the initialized value if the
+initializer is used before runtime.  If the initializer is used at runtime, a
+proper implicit or explicit read memory barrier is needed before reading the
+value with atomic_read from another thread.
+
+As with all of the ``atomic_`` interfaces, replace the leading ``atomic_``
+with ``atomic_long_`` to operate on atomic_long_t.
+
+The second interface can be used at runtime, as in::
+
+	struct foo { atomic_t counter; };
+	...
+
+	struct foo *k;
+
+	k = kmalloc(sizeof(*k), GFP_KERNEL);
+	if (!k)
+		return -ENOMEM;
+	atomic_set(&k->counter, 0);
+
+The setting is atomic in that the return values of the atomic operations by
+all threads are guaranteed to be correct reflecting either the value that has
+been set with this operation or set with another operation.  A proper implicit
+or explicit memory barrier is needed before the value set with the operation
+is guaranteed to be readable with atomic_read from another thread.
+
+Next, we have::
+
+	#define atomic_read(v)	((v)->counter)
+
+which simply reads the counter value currently visible to the calling thread.
+The read is atomic in that the return value is guaranteed to be one of the
+values initialized or modified with the interface operations if a proper
+implicit or explicit memory barrier is used after possible runtime
+initialization by any other thread and the value is modified only with the
+interface operations.  atomic_read does not guarantee that the runtime
+initialization by any other thread is visible yet, so the user of the
+interface must take care of that with a proper implicit or explicit memory
+barrier.
+
+.. warning::
+
+	``atomic_read()`` and ``atomic_set()`` DO NOT IMPLY BARRIERS!
+
+	Some architectures may choose to use the volatile keyword, barriers, or
+	inline assembly to guarantee some degree of immediacy for atomic_read()
+	and atomic_set().  This is not uniformly guaranteed, and may change in
+	the future, so all users of atomic_t should treat atomic_read() and
+	atomic_set() as simple C statements that may be reordered or optimized
+	away entirely by the compiler or processor, and explicitly invoke the
+	appropriate compiler and/or memory barrier for each use case.  Failure
+	to do so will result in code that may suddenly break when used with
+	different architectures or compiler optimizations, or even changes in
+	unrelated code which changes how the compiler optimizes the section
+	accessing atomic_t variables.
+
+Properly aligned pointers, longs, ints, and chars (and unsigned
+equivalents) may be atomically loaded from and stored to in the same
+sense as described for atomic_read() and atomic_set().  The READ_ONCE()
+and WRITE_ONCE() macros should be used to prevent the compiler from using
+optimizations that might otherwise optimize accesses out of existence on
+the one hand, or that might create unsolicited accesses on the other.
+
+For example consider the following code::
+
+	while (a > 0)
+		do_something();
+
+If the compiler can prove that do_something() does not store to the
+variable a, then the compiler is within its rights transforming this to
+the following::
+
+	tmp = a;
+	if (a > 0)
+		for (;;)
+			do_something();
+
+If you don't want the compiler to do this (and you probably don't), then
+you should use something like the following::
+
+	while (READ_ONCE(a) < 0)
+		do_something();
+
+Alternatively, you could place a barrier() call in the loop.
+
+For another example, consider the following code::
+
+	tmp_a = a;
+	do_something_with(tmp_a);
+	do_something_else_with(tmp_a);
+
+If the compiler can prove that do_something_with() does not store to the
+variable a, then the compiler is within its rights to manufacture an
+additional load as follows::
+
+	tmp_a = a;
+	do_something_with(tmp_a);
+	tmp_a = a;
+	do_something_else_with(tmp_a);
+
+This could fatally confuse your code if it expected the same value
+to be passed to do_something_with() and do_something_else_with().
+
+The compiler would be likely to manufacture this additional load if
+do_something_with() was an inline function that made very heavy use
+of registers: reloading from variable a could save a flush to the
+stack and later reload.  To prevent the compiler from attacking your
+code in this manner, write the following::
+
+	tmp_a = READ_ONCE(a);
+	do_something_with(tmp_a);
+	do_something_else_with(tmp_a);
+
+For a final example, consider the following code, assuming that the
+variable a is set at boot time before the second CPU is brought online
+and never changed later, so that memory barriers are not needed::
+
+	if (a)
+		b = 9;
+	else
+		b = 42;
+
+The compiler is within its rights to manufacture an additional store
+by transforming the above code into the following::
+
+	b = 42;
+	if (a)
+		b = 9;
+
+This could come as a fatal surprise to other code running concurrently
+that expected b to never have the value 42 if a was zero.  To prevent
+the compiler from doing this, write something like::
+
+	if (a)
+		WRITE_ONCE(b, 9);
+	else
+		WRITE_ONCE(b, 42);
+
+Don't even -think- about doing this without proper use of memory barriers,
+locks, or atomic operations if variable a can change at runtime!
+
+.. warning::
+
+	``READ_ONCE()`` OR ``WRITE_ONCE()`` DO NOT IMPLY A BARRIER!
+
+Now, we move onto the atomic operation interfaces typically implemented with
+the help of assembly code. ::
+
+	void atomic_add(int i, atomic_t *v);
+	void atomic_sub(int i, atomic_t *v);
+	void atomic_inc(atomic_t *v);
+	void atomic_dec(atomic_t *v);
+
+These four routines add and subtract integral values to/from the given
+atomic_t value.  The first two routines pass explicit integers by
+which to make the adjustment, whereas the latter two use an implicit
+adjustment value of "1".
+
+One very important aspect of these two routines is that they DO NOT
+require any explicit memory barriers.  They need only perform the
+atomic_t counter update in an SMP safe manner.
+
+Next, we have::
+
+	int atomic_inc_return(atomic_t *v);
+	int atomic_dec_return(atomic_t *v);
+
+These routines add 1 and subtract 1, respectively, from the given
+atomic_t and return the new counter value after the operation is
+performed.
+
+Unlike the above routines, it is required that these primitives
+include explicit memory barriers that are performed before and after
+the operation.  It must be done such that all memory operations before
+and after the atomic operation calls are strongly ordered with respect
+to the atomic operation itself.
+
+For example, it should behave as if a smp_mb() call existed both
+before and after the atomic operation.
+
+If the atomic instructions used in an implementation provide explicit
+memory barrier semantics which satisfy the above requirements, that is
+fine as well.
+
+Let's move on::
+
+	int atomic_add_return(int i, atomic_t *v);
+	int atomic_sub_return(int i, atomic_t *v);
+
+These behave just like atomic_{inc,dec}_return() except that an
+explicit counter adjustment is given instead of the implicit "1".
+This means that like atomic_{inc,dec}_return(), the memory barrier
+semantics are required.
+
+Next::
+
+	int atomic_inc_and_test(atomic_t *v);
+	int atomic_dec_and_test(atomic_t *v);
+
+These two routines increment and decrement by 1, respectively, the
+given atomic counter.  They return a boolean indicating whether the
+resulting counter value was zero or not.
+
+Again, these primitives provide explicit memory barrier semantics around
+the atomic operation::
+
+	int atomic_sub_and_test(int i, atomic_t *v);
+
+This is identical to atomic_dec_and_test() except that an explicit
+decrement is given instead of the implicit "1".  This primitive must
+provide explicit memory barrier semantics around the operation::
+
+	int atomic_add_negative(int i, atomic_t *v);
+
+The given increment is added to the given atomic counter value.  A boolean
+is return which indicates whether the resulting counter value is negative.
+This primitive must provide explicit memory barrier semantics around
+the operation.
+
+Then::
+
+	int atomic_xchg(atomic_t *v, int new);
+
+This performs an atomic exchange operation on the atomic variable v, setting
+the given new value.  It returns the old value that the atomic variable v had
+just before the operation.
+
+atomic_xchg must provide explicit memory barriers around the operation. ::
+
+	int atomic_cmpxchg(atomic_t *v, int old, int new);
+
+This performs an atomic compare exchange operation on the atomic value v,
+with the given old and new values. Like all atomic_xxx operations,
+atomic_cmpxchg will only satisfy its atomicity semantics as long as all
+other accesses of \*v are performed through atomic_xxx operations.
+
+atomic_cmpxchg must provide explicit memory barriers around the operation,
+although if the comparison fails then no memory ordering guarantees are
+required.
+
+The semantics for atomic_cmpxchg are the same as those defined for 'cas'
+below.
+
+Finally::
+
+	int atomic_add_unless(atomic_t *v, int a, int u);
+
+If the atomic value v is not equal to u, this function adds a to v, and
+returns non zero. If v is equal to u then it returns zero. This is done as
+an atomic operation.
+
+atomic_add_unless must provide explicit memory barriers around the
+operation unless it fails (returns 0).
+
+atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)
+
+
+If a caller requires memory barrier semantics around an atomic_t
+operation which does not return a value, a set of interfaces are
+defined which accomplish this::
+
+	void smp_mb__before_atomic(void);
+	void smp_mb__after_atomic(void);
+
+For example, smp_mb__before_atomic() can be used like so::
+
+	obj->dead = 1;
+	smp_mb__before_atomic();
+	atomic_dec(&obj->ref_count);
+
+It makes sure that all memory operations preceding the atomic_dec()
+call are strongly ordered with respect to the atomic counter
+operation.  In the above example, it guarantees that the assignment of
+"1" to obj->dead will be globally visible to other cpus before the
+atomic counter decrement.
+
+Without the explicit smp_mb__before_atomic() call, the
+implementation could legally allow the atomic counter update visible
+to other cpus before the "obj->dead = 1;" assignment.
+
+A missing memory barrier in the cases where they are required by the
+atomic_t implementation above can have disastrous results.  Here is
+an example, which follows a pattern occurring frequently in the Linux
+kernel.  It is the use of atomic counters to implement reference
+counting, and it works such that once the counter falls to zero it can
+be guaranteed that no other entity can be accessing the object::
+
+	static void obj_list_add(struct obj *obj, struct list_head *head)
+	{
+		obj->active = 1;
+		list_add(&obj->list, head);
+	}
+
+	static void obj_list_del(struct obj *obj)
+	{
+		list_del(&obj->list);
+		obj->active = 0;
+	}
+
+	static void obj_destroy(struct obj *obj)
+	{
+		BUG_ON(obj->active);
+		kfree(obj);
+	}
+
+	struct obj *obj_list_peek(struct list_head *head)
+	{
+		if (!list_empty(head)) {
+			struct obj *obj;
+
+			obj = list_entry(head->next, struct obj, list);
+			atomic_inc(&obj->refcnt);
+			return obj;
+		}
+		return NULL;
+	}
+
+	void obj_poke(void)
+	{
+		struct obj *obj;
+
+		spin_lock(&global_list_lock);
+		obj = obj_list_peek(&global_list);
+		spin_unlock(&global_list_lock);
+
+		if (obj) {
+			obj->ops->poke(obj);
+			if (atomic_dec_and_test(&obj->refcnt))
+				obj_destroy(obj);
+		}
+	}
+
+	void obj_timeout(struct obj *obj)
+	{
+		spin_lock(&global_list_lock);
+		obj_list_del(obj);
+		spin_unlock(&global_list_lock);
+
+		if (atomic_dec_and_test(&obj->refcnt))
+			obj_destroy(obj);
+	}
+
+.. note::
+
+	This is a simplification of the ARP queue management in the generic
+	neighbour discover code of the networking.  Olaf Kirch found a bug wrt.
+	memory barriers in kfree_skb() that exposed the atomic_t memory barrier
+	requirements quite clearly.
+
+Given the above scheme, it must be the case that the obj->active
+update done by the obj list deletion be visible to other processors
+before the atomic counter decrement is performed.
+
+Otherwise, the counter could fall to zero, yet obj->active would still
+be set, thus triggering the assertion in obj_destroy().  The error
+sequence looks like this::
+
+	cpu 0				cpu 1
+	obj_poke()			obj_timeout()
+	obj = obj_list_peek();
+	... gains ref to obj, refcnt=2
+					obj_list_del(obj);
+					obj->active = 0 ...
+					... visibility delayed ...
+					atomic_dec_and_test()
+					... refcnt drops to 1 ...
+	atomic_dec_and_test()
+	... refcount drops to 0 ...
+	obj_destroy()
+	BUG() triggers since obj->active
+	still seen as one
+					obj->active update visibility occurs
+
+With the memory barrier semantics required of the atomic_t operations
+which return values, the above sequence of memory visibility can never
+happen.  Specifically, in the above case the atomic_dec_and_test()
+counter decrement would not become globally visible until the
+obj->active update does.
+
+As a historical note, 32-bit Sparc used to only allow usage of
+24-bits of its atomic_t type.  This was because it used 8 bits
+as a spinlock for SMP safety.  Sparc32 lacked a "compare and swap"
+type instruction.  However, 32-bit Sparc has since been moved over
+to a "hash table of spinlocks" scheme, that allows the full 32-bit
+counter to be realized.  Essentially, an array of spinlocks are
+indexed into based upon the address of the atomic_t being operated
+on, and that lock protects the atomic operation.  Parisc uses the
+same scheme.
+
+Another note is that the atomic_t operations returning values are
+extremely slow on an old 386.
+
+
+Atomic Bitmask
+==============
+
+We will now cover the atomic bitmask operations.  You will find that
+their SMP and memory barrier semantics are similar in shape and scope
+to the atomic_t ops above.
+
+Native atomic bit operations are defined to operate on objects aligned
+to the size of an "unsigned long" C data type, and are least of that
+size.  The endianness of the bits within each "unsigned long" are the
+native endianness of the cpu. ::
+
+	void set_bit(unsigned long nr, volatile unsigned long *addr);
+	void clear_bit(unsigned long nr, volatile unsigned long *addr);
+	void change_bit(unsigned long nr, volatile unsigned long *addr);
+
+These routines set, clear, and change, respectively, the bit number
+indicated by "nr" on the bit mask pointed to by "ADDR".
+
+They must execute atomically, yet there are no implicit memory barrier
+semantics required of these interfaces. ::
+
+	int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
+	int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
+	int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
+
+Like the above, except that these routines return a boolean which
+indicates whether the changed bit was set _BEFORE_ the atomic bit
+operation.
+
+WARNING! It is incredibly important that the value be a boolean,
+ie. "0" or "1".  Do not try to be fancy and save a few instructions by
+declaring the above to return "long" and just returning something like
+"old_val & mask" because that will not work.
+
+For one thing, this return value gets truncated to int in many code
+paths using these interfaces, so on 64-bit if the bit is set in the
+upper 32-bits then testers will never see that.
+
+One great example of where this problem crops up are the thread_info
+flag operations.  Routines such as test_and_set_ti_thread_flag() chop
+the return value into an int.  There are other places where things
+like this occur as well.
+
+These routines, like the atomic_t counter operations returning values,
+must provide explicit memory barrier semantics around their execution.
+All memory operations before the atomic bit operation call must be
+made visible globally before the atomic bit operation is made visible.
+Likewise, the atomic bit operation must be visible globally before any
+subsequent memory operation is made visible.  For example::
+
+	obj->dead = 1;
+	if (test_and_set_bit(0, &obj->flags))
+		/* ... */;
+	obj->killed = 1;
+
+The implementation of test_and_set_bit() must guarantee that
+"obj->dead = 1;" is visible to cpus before the atomic memory operation
+done by test_and_set_bit() becomes visible.  Likewise, the atomic
+memory operation done by test_and_set_bit() must become visible before
+"obj->killed = 1;" is visible.
+
+Finally there is the basic operation::
+
+	int test_bit(unsigned long nr, __const__ volatile unsigned long *addr);
+
+Which returns a boolean indicating if bit "nr" is set in the bitmask
+pointed to by "addr".
+
+If explicit memory barriers are required around {set,clear}_bit() (which do
+not return a value, and thus does not need to provide memory barrier
+semantics), two interfaces are provided::
+
+	void smp_mb__before_atomic(void);
+	void smp_mb__after_atomic(void);
+
+They are used as follows, and are akin to their atomic_t operation
+brothers::
+
+	/* All memory operations before this call will
+	 * be globally visible before the clear_bit().
+	 */
+	smp_mb__before_atomic();
+	clear_bit( ... );
+
+	/* The clear_bit() will be visible before all
+	 * subsequent memory operations.
+	 */
+	 smp_mb__after_atomic();
+
+There are two special bitops with lock barrier semantics (acquire/release,
+same as spinlocks). These operate in the same way as their non-_lock/unlock
+postfixed variants, except that they are to provide acquire/release semantics,
+respectively. This means they can be used for bit_spin_trylock and
+bit_spin_unlock type operations without specifying any more barriers. ::
+
+	int test_and_set_bit_lock(unsigned long nr, unsigned long *addr);
+	void clear_bit_unlock(unsigned long nr, unsigned long *addr);
+	void __clear_bit_unlock(unsigned long nr, unsigned long *addr);
+
+The __clear_bit_unlock version is non-atomic, however it still implements
+unlock barrier semantics. This can be useful if the lock itself is protecting
+the other bits in the word.
+
+Finally, there are non-atomic versions of the bitmask operations
+provided.  They are used in contexts where some other higher-level SMP
+locking scheme is being used to protect the bitmask, and thus less
+expensive non-atomic operations may be used in the implementation.
+They have names similar to the above bitmask operation interfaces,
+except that two underscores are prefixed to the interface name. ::
+
+	void __set_bit(unsigned long nr, volatile unsigned long *addr);
+	void __clear_bit(unsigned long nr, volatile unsigned long *addr);
+	void __change_bit(unsigned long nr, volatile unsigned long *addr);
+	int __test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
+	int __test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
+	int __test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
+
+These non-atomic variants also do not require any special memory
+barrier semantics.
+
+The routines xchg() and cmpxchg() must provide the same exact
+memory-barrier semantics as the atomic and bit operations returning
+values.
+
+.. note::
+
+	If someone wants to use xchg(), cmpxchg() and their variants,
+	linux/atomic.h should be included rather than asm/cmpxchg.h, unless the
+	code is in arch/* and can take care of itself.
+
+Spinlocks and rwlocks have memory barrier expectations as well.
+The rule to follow is simple:
+
+1) When acquiring a lock, the implementation must make it globally
+   visible before any subsequent memory operation.
+
+2) When releasing a lock, the implementation must make it such that
+   all previous memory operations are globally visible before the
+   lock release.
+
+Which finally brings us to _atomic_dec_and_lock().  There is an
+architecture-neutral version implemented in lib/dec_and_lock.c,
+but most platforms will wish to optimize this in assembler. ::
+
+	int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
+
+Atomically decrement the given counter, and if will drop to zero
+atomically acquire the given spinlock and perform the decrement
+of the counter to zero.  If it does not drop to zero, do nothing
+with the spinlock.
+
+It is actually pretty simple to get the memory barrier correct.
+Simply satisfy the spinlock grab requirements, which is make
+sure the spinlock operation is globally visible before any
+subsequent memory operation.
+
+We can demonstrate this operation more clearly if we define
+an abstract atomic operation::
+
+	long cas(long *mem, long old, long new);
+
+"cas" stands for "compare and swap".  It atomically:
+
+1) Compares "old" with the value currently at "mem".
+2) If they are equal, "new" is written to "mem".
+3) Regardless, the current value at "mem" is returned.
+
+As an example usage, here is what an atomic counter update
+might look like::
+
+	void example_atomic_inc(long *counter)
+	{
+		long old, new, ret;
+
+		while (1) {
+			old = *counter;
+			new = old + 1;
+
+			ret = cas(counter, old, new);
+			if (ret == old)
+				break;
+		}
+	}
+
+Let's use cas() in order to build a pseudo-C atomic_dec_and_lock()::
+
+	int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
+	{
+		long old, new, ret;
+		int went_to_zero;
+
+		went_to_zero = 0;
+		while (1) {
+			old = atomic_read(atomic);
+			new = old - 1;
+			if (new == 0) {
+				went_to_zero = 1;
+				spin_lock(lock);
+			}
+			ret = cas(atomic, old, new);
+			if (ret == old)
+				break;
+			if (went_to_zero) {
+				spin_unlock(lock);
+				went_to_zero = 0;
+			}
+		}
+
+		return went_to_zero;
+	}
+
+Now, as far as memory barriers go, as long as spin_lock()
+strictly orders all subsequent memory operations (including
+the cas()) with respect to itself, things will be fine.
+
+Said another way, _atomic_dec_and_lock() must guarantee that
+a counter dropping to zero is never made visible before the
+spinlock being acquired.
+
+.. note::
+
+	Note that this also means that for the case where the counter is not
+	dropping to zero, there are no memory ordering requirements.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/conf.py linux-libre-4.10-rc8-gnu/Documentation/core-api/conf.py
--- linux-libre-4.9-gnu/Documentation/core-api/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "Core-API Documentation"
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'core-api.tex', project,
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/debug-objects.rst linux-libre-4.10-rc8-gnu/Documentation/core-api/debug-objects.rst
--- linux-libre-4.9-gnu/Documentation/core-api/debug-objects.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/debug-objects.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,310 @@
+============================================
+The object-lifetime debugging infrastructure
+============================================
+
+:Author: Thomas Gleixner
+
+Introduction
+============
+
+debugobjects is a generic infrastructure to track the life time of
+kernel objects and validate the operations on those.
+
+debugobjects is useful to check for the following error patterns:
+
+-  Activation of uninitialized objects
+
+-  Initialization of active objects
+
+-  Usage of freed/destroyed objects
+
+debugobjects is not changing the data structure of the real object so it
+can be compiled in with a minimal runtime impact and enabled on demand
+with a kernel command line option.
+
+Howto use debugobjects
+======================
+
+A kernel subsystem needs to provide a data structure which describes the
+object type and add calls into the debug code at appropriate places. The
+data structure to describe the object type needs at minimum the name of
+the object type. Optional functions can and should be provided to fixup
+detected problems so the kernel can continue to work and the debug
+information can be retrieved from a live system instead of hard core
+debugging with serial consoles and stack trace transcripts from the
+monitor.
+
+The debug calls provided by debugobjects are:
+
+-  debug_object_init
+
+-  debug_object_init_on_stack
+
+-  debug_object_activate
+
+-  debug_object_deactivate
+
+-  debug_object_destroy
+
+-  debug_object_free
+
+-  debug_object_assert_init
+
+Each of these functions takes the address of the real object and a
+pointer to the object type specific debug description structure.
+
+Each detected error is reported in the statistics and a limited number
+of errors are printk'ed including a full stack trace.
+
+The statistics are available via /sys/kernel/debug/debug_objects/stats.
+They provide information about the number of warnings and the number of
+successful fixups along with information about the usage of the internal
+tracking objects and the state of the internal tracking objects pool.
+
+Debug functions
+===============
+
+.. kernel-doc:: lib/debugobjects.c
+   :functions: debug_object_init
+
+This function is called whenever the initialization function of a real
+object is called.
+
+When the real object is already tracked by debugobjects it is checked,
+whether the object can be initialized. Initializing is not allowed for
+active and destroyed objects. When debugobjects detects an error, then
+it calls the fixup_init function of the object type description
+structure if provided by the caller. The fixup function can correct the
+problem before the real initialization of the object happens. E.g. it
+can deactivate an active object in order to prevent damage to the
+subsystem.
+
+When the real object is not yet tracked by debugobjects, debugobjects
+allocates a tracker object for the real object and sets the tracker
+object state to ODEBUG_STATE_INIT. It verifies that the object is not
+on the callers stack. If it is on the callers stack then a limited
+number of warnings including a full stack trace is printk'ed. The
+calling code must use debug_object_init_on_stack() and remove the
+object before leaving the function which allocated it. See next section.
+
+.. kernel-doc:: lib/debugobjects.c
+   :functions: debug_object_init_on_stack
+
+This function is called whenever the initialization function of a real
+object which resides on the stack is called.
+
+When the real object is already tracked by debugobjects it is checked,
+whether the object can be initialized. Initializing is not allowed for
+active and destroyed objects. When debugobjects detects an error, then
+it calls the fixup_init function of the object type description
+structure if provided by the caller. The fixup function can correct the
+problem before the real initialization of the object happens. E.g. it
+can deactivate an active object in order to prevent damage to the
+subsystem.
+
+When the real object is not yet tracked by debugobjects debugobjects
+allocates a tracker object for the real object and sets the tracker
+object state to ODEBUG_STATE_INIT. It verifies that the object is on
+the callers stack.
+
+An object which is on the stack must be removed from the tracker by
+calling debug_object_free() before the function which allocates the
+object returns. Otherwise we keep track of stale objects.
+
+.. kernel-doc:: lib/debugobjects.c
+   :functions: debug_object_activate
+
+This function is called whenever the activation function of a real
+object is called.
+
+When the real object is already tracked by debugobjects it is checked,
+whether the object can be activated. Activating is not allowed for
+active and destroyed objects. When debugobjects detects an error, then
+it calls the fixup_activate function of the object type description
+structure if provided by the caller. The fixup function can correct the
+problem before the real activation of the object happens. E.g. it can
+deactivate an active object in order to prevent damage to the subsystem.
+
+When the real object is not yet tracked by debugobjects then the
+fixup_activate function is called if available. This is necessary to
+allow the legitimate activation of statically allocated and initialized
+objects. The fixup function checks whether the object is valid and calls
+the debug_objects_init() function to initialize the tracking of this
+object.
+
+When the activation is legitimate, then the state of the associated
+tracker object is set to ODEBUG_STATE_ACTIVE.
+
+
+.. kernel-doc:: lib/debugobjects.c
+   :functions: debug_object_deactivate
+
+This function is called whenever the deactivation function of a real
+object is called.
+
+When the real object is tracked by debugobjects it is checked, whether
+the object can be deactivated. Deactivating is not allowed for untracked
+or destroyed objects.
+
+When the deactivation is legitimate, then the state of the associated
+tracker object is set to ODEBUG_STATE_INACTIVE.
+
+.. kernel-doc:: lib/debugobjects.c
+   :functions: debug_object_destroy
+
+This function is called to mark an object destroyed. This is useful to
+prevent the usage of invalid objects, which are still available in
+memory: either statically allocated objects or objects which are freed
+later.
+
+When the real object is tracked by debugobjects it is checked, whether
+the object can be destroyed. Destruction is not allowed for active and
+destroyed objects. When debugobjects detects an error, then it calls the
+fixup_destroy function of the object type description structure if
+provided by the caller. The fixup function can correct the problem
+before the real destruction of the object happens. E.g. it can
+deactivate an active object in order to prevent damage to the subsystem.
+
+When the destruction is legitimate, then the state of the associated
+tracker object is set to ODEBUG_STATE_DESTROYED.
+
+.. kernel-doc:: lib/debugobjects.c
+   :functions: debug_object_free
+
+This function is called before an object is freed.
+
+When the real object is tracked by debugobjects it is checked, whether
+the object can be freed. Free is not allowed for active objects. When
+debugobjects detects an error, then it calls the fixup_free function of
+the object type description structure if provided by the caller. The
+fixup function can correct the problem before the real free of the
+object happens. E.g. it can deactivate an active object in order to
+prevent damage to the subsystem.
+
+Note that debug_object_free removes the object from the tracker. Later
+usage of the object is detected by the other debug checks.
+
+
+.. kernel-doc:: lib/debugobjects.c
+   :functions: debug_object_assert_init
+
+This function is called to assert that an object has been initialized.
+
+When the real object is not tracked by debugobjects, it calls
+fixup_assert_init of the object type description structure provided by
+the caller, with the hardcoded object state ODEBUG_NOT_AVAILABLE. The
+fixup function can correct the problem by calling debug_object_init
+and other specific initializing functions.
+
+When the real object is already tracked by debugobjects it is ignored.
+
+Fixup functions
+===============
+
+Debug object type description structure
+---------------------------------------
+
+.. kernel-doc:: include/linux/debugobjects.h
+   :internal:
+
+fixup_init
+-----------
+
+This function is called from the debug code whenever a problem in
+debug_object_init is detected. The function takes the address of the
+object and the state which is currently recorded in the tracker.
+
+Called from debug_object_init when the object state is:
+
+-  ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+Note, that the function needs to call the debug_object_init() function
+again, after the damage has been repaired in order to keep the state
+consistent.
+
+fixup_activate
+---------------
+
+This function is called from the debug code whenever a problem in
+debug_object_activate is detected.
+
+Called from debug_object_activate when the object state is:
+
+-  ODEBUG_STATE_NOTAVAILABLE
+
+-  ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+Note that the function needs to call the debug_object_activate()
+function again after the damage has been repaired in order to keep the
+state consistent.
+
+The activation of statically initialized objects is a special case. When
+debug_object_activate() has no tracked object for this object address
+then fixup_activate() is called with object state
+ODEBUG_STATE_NOTAVAILABLE. The fixup function needs to check whether
+this is a legitimate case of a statically initialized object or not. In
+case it is it calls debug_object_init() and debug_object_activate()
+to make the object known to the tracker and marked active. In this case
+the function should return false because this is not a real fixup.
+
+fixup_destroy
+--------------
+
+This function is called from the debug code whenever a problem in
+debug_object_destroy is detected.
+
+Called from debug_object_destroy when the object state is:
+
+-  ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+fixup_free
+-----------
+
+This function is called from the debug code whenever a problem in
+debug_object_free is detected. Further it can be called from the debug
+checks in kfree/vfree, when an active object is detected from the
+debug_check_no_obj_freed() sanity checks.
+
+Called from debug_object_free() or debug_check_no_obj_freed() when
+the object state is:
+
+-  ODEBUG_STATE_ACTIVE
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+fixup_assert_init
+-------------------
+
+This function is called from the debug code whenever a problem in
+debug_object_assert_init is detected.
+
+Called from debug_object_assert_init() with a hardcoded state
+ODEBUG_STATE_NOTAVAILABLE when the object is not found in the debug
+bucket.
+
+The function returns true when the fixup was successful, otherwise
+false. The return value is used to update the statistics.
+
+Note, this function should make sure debug_object_init() is called
+before returning.
+
+The handling of statically initialized objects is a special case. The
+fixup function should check if this is a legitimate case of a statically
+initialized object or not. In this case only debug_object_init()
+should be called to make the object known to the tracker. Then the
+function should return false because this is not a real fixup.
+
+Known Bugs And Assumptions
+==========================
+
+None (knock on wood).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/index.rst linux-libre-4.10-rc8-gnu/Documentation/core-api/index.rst
--- linux-libre-4.9-gnu/Documentation/core-api/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,33 @@
+======================
+Core API Documentation
+======================
+
+This is the beginning of a manual for core kernel APIs.  The conversion
+(and writing!) of documents for this manual is much appreciated!
+
+Core utilities
+==============
+
+.. toctree::
+   :maxdepth: 1
+
+   assoc_array
+   atomic_ops
+   local_ops
+   workqueue
+
+Interfaces for kernel debugging
+===============================
+
+.. toctree::
+   :maxdepth: 1
+
+   debug-objects
+   tracepoint
+
+.. only::  subproject
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/local_ops.rst linux-libre-4.10-rc8-gnu/Documentation/core-api/local_ops.rst
--- linux-libre-4.9-gnu/Documentation/core-api/local_ops.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/local_ops.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,206 @@
+
+.. _local_ops:
+
+=================================================
+Semantics and Behavior of Local Atomic Operations
+=================================================
+
+:Author: Mathieu Desnoyers
+
+
+This document explains the purpose of the local atomic operations, how
+to implement them for any given architecture and shows how they can be used
+properly. It also stresses on the precautions that must be taken when reading
+those local variables across CPUs when the order of memory writes matters.
+
+.. note::
+
+    Note that ``local_t`` based operations are not recommended for general
+    kernel use. Please use the ``this_cpu`` operations instead unless there is
+    really a special purpose. Most uses of ``local_t`` in the kernel have been
+    replaced by ``this_cpu`` operations. ``this_cpu`` operations combine the
+    relocation with the ``local_t`` like semantics in a single instruction and
+    yield more compact and faster executing code.
+
+
+Purpose of local atomic operations
+==================================
+
+Local atomic operations are meant to provide fast and highly reentrant per CPU
+counters. They minimize the performance cost of standard atomic operations by
+removing the LOCK prefix and memory barriers normally required to synchronize
+across CPUs.
+
+Having fast per CPU atomic counters is interesting in many cases: it does not
+require disabling interrupts to protect from interrupt handlers and it permits
+coherent counters in NMI handlers. It is especially useful for tracing purposes
+and for various performance monitoring counters.
+
+Local atomic operations only guarantee variable modification atomicity wrt the
+CPU which owns the data. Therefore, care must taken to make sure that only one
+CPU writes to the ``local_t`` data. This is done by using per cpu data and
+making sure that we modify it from within a preemption safe context. It is
+however permitted to read ``local_t`` data from any CPU: it will then appear to
+be written out of order wrt other memory writes by the owner CPU.
+
+
+Implementation for a given architecture
+=======================================
+
+It can be done by slightly modifying the standard atomic operations: only
+their UP variant must be kept. It typically means removing LOCK prefix (on
+i386 and x86_64) and any SMP synchronization barrier. If the architecture does
+not have a different behavior between SMP and UP, including
+``asm-generic/local.h`` in your architecture's ``local.h`` is sufficient.
+
+The ``local_t`` type is defined as an opaque ``signed long`` by embedding an
+``atomic_long_t`` inside a structure. This is made so a cast from this type to
+a ``long`` fails. The definition looks like::
+
+    typedef struct { atomic_long_t a; } local_t;
+
+
+Rules to follow when using local atomic operations
+==================================================
+
+* Variables touched by local ops must be per cpu variables.
+* *Only* the CPU owner of these variables must write to them.
+* This CPU can use local ops from any context (process, irq, softirq, nmi, ...)
+  to update its ``local_t`` variables.
+* Preemption (or interrupts) must be disabled when using local ops in
+  process context to make sure the process won't be migrated to a
+  different CPU between getting the per-cpu variable and doing the
+  actual local op.
+* When using local ops in interrupt context, no special care must be
+  taken on a mainline kernel, since they will run on the local CPU with
+  preemption already disabled. I suggest, however, to explicitly
+  disable preemption anyway to make sure it will still work correctly on
+  -rt kernels.
+* Reading the local cpu variable will provide the current copy of the
+  variable.
+* Reads of these variables can be done from any CPU, because updates to
+  "``long``", aligned, variables are always atomic. Since no memory
+  synchronization is done by the writer CPU, an outdated copy of the
+  variable can be read when reading some *other* cpu's variables.
+
+
+How to use local atomic operations
+==================================
+
+::
+
+    #include <linux/percpu.h>
+    #include <asm/local.h>
+
+    static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
+
+
+Counting
+========
+
+Counting is done on all the bits of a signed long.
+
+In preemptible context, use ``get_cpu_var()`` and ``put_cpu_var()`` around
+local atomic operations: it makes sure that preemption is disabled around write
+access to the per cpu variable. For instance::
+
+    local_inc(&get_cpu_var(counters));
+    put_cpu_var(counters);
+
+If you are already in a preemption-safe context, you can use
+``this_cpu_ptr()`` instead::
+
+    local_inc(this_cpu_ptr(&counters));
+
+
+
+Reading the counters
+====================
+
+Those local counters can be read from foreign CPUs to sum the count. Note that
+the data seen by local_read across CPUs must be considered to be out of order
+relatively to other memory writes happening on the CPU that owns the data::
+
+    long sum = 0;
+    for_each_online_cpu(cpu)
+            sum += local_read(&per_cpu(counters, cpu));
+
+If you want to use a remote local_read to synchronize access to a resource
+between CPUs, explicit ``smp_wmb()`` and ``smp_rmb()`` memory barriers must be used
+respectively on the writer and the reader CPUs. It would be the case if you use
+the ``local_t`` variable as a counter of bytes written in a buffer: there should
+be a ``smp_wmb()`` between the buffer write and the counter increment and also a
+``smp_rmb()`` between the counter read and the buffer read.
+
+
+Here is a sample module which implements a basic per cpu counter using
+``local.h``::
+
+    /* test-local.c
+     *
+     * Sample module for local.h usage.
+     */
+
+
+    #include <asm/local.h>
+    #include <linux/module.h>
+    #include <linux/timer.h>
+
+    static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
+
+    static struct timer_list test_timer;
+
+    /* IPI called on each CPU. */
+    static void test_each(void *info)
+    {
+            /* Increment the counter from a non preemptible context */
+            printk("Increment on cpu %d\n", smp_processor_id());
+            local_inc(this_cpu_ptr(&counters));
+
+            /* This is what incrementing the variable would look like within a
+             * preemptible context (it disables preemption) :
+             *
+             * local_inc(&get_cpu_var(counters));
+             * put_cpu_var(counters);
+             */
+    }
+
+    static void do_test_timer(unsigned long data)
+    {
+            int cpu;
+
+            /* Increment the counters */
+            on_each_cpu(test_each, NULL, 1);
+            /* Read all the counters */
+            printk("Counters read from CPU %d\n", smp_processor_id());
+            for_each_online_cpu(cpu) {
+                    printk("Read : CPU %d, count %ld\n", cpu,
+                            local_read(&per_cpu(counters, cpu)));
+            }
+            del_timer(&test_timer);
+            test_timer.expires = jiffies + 1000;
+            add_timer(&test_timer);
+    }
+
+    static int __init test_init(void)
+    {
+            /* initialize the timer that will increment the counter */
+            init_timer(&test_timer);
+            test_timer.function = do_test_timer;
+            test_timer.expires = jiffies + 1;
+            add_timer(&test_timer);
+
+            return 0;
+    }
+
+    static void __exit test_exit(void)
+    {
+            del_timer_sync(&test_timer);
+    }
+
+    module_init(test_init);
+    module_exit(test_exit);
+
+    MODULE_LICENSE("GPL");
+    MODULE_AUTHOR("Mathieu Desnoyers");
+    MODULE_DESCRIPTION("Local Atomic Ops");
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/tracepoint.rst linux-libre-4.10-rc8-gnu/Documentation/core-api/tracepoint.rst
--- linux-libre-4.9-gnu/Documentation/core-api/tracepoint.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/tracepoint.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,55 @@
+===============================
+The Linux Kernel Tracepoint API
+===============================
+
+:Author: Jason Baron
+:Author: William Cohen
+
+Introduction
+============
+
+Tracepoints are static probe points that are located in strategic points
+throughout the kernel. 'Probes' register/unregister with tracepoints via
+a callback mechanism. The 'probes' are strictly typed functions that are
+passed a unique set of parameters defined by each tracepoint.
+
+From this simple callback mechanism, 'probes' can be used to profile,
+debug, and understand kernel behavior. There are a number of tools that
+provide a framework for using 'probes'. These tools include Systemtap,
+ftrace, and LTTng.
+
+Tracepoints are defined in a number of header files via various macros.
+Thus, the purpose of this document is to provide a clear accounting of
+the available tracepoints. The intention is to understand not only what
+tracepoints are available but also to understand where future
+tracepoints might be added.
+
+The API presented has functions of the form:
+``trace_tracepointname(function parameters)``. These are the tracepoints
+callbacks that are found throughout the code. Registering and
+unregistering probes with these callback sites is covered in the
+``Documentation/trace/*`` directory.
+
+IRQ
+===
+
+.. kernel-doc:: include/trace/events/irq.h
+   :internal:
+
+SIGNAL
+======
+
+.. kernel-doc:: include/trace/events/signal.h
+   :internal:
+
+Block IO
+========
+
+.. kernel-doc:: include/trace/events/block.h
+   :internal:
+
+Workqueue
+=========
+
+.. kernel-doc:: include/trace/events/workqueue.h
+   :internal:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/core-api/workqueue.rst linux-libre-4.10-rc8-gnu/Documentation/core-api/workqueue.rst
--- linux-libre-4.9-gnu/Documentation/core-api/workqueue.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/core-api/workqueue.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,394 @@
+====================================
+Concurrency Managed Workqueue (cmwq)
+====================================
+
+:Date: September, 2010
+:Author: Tejun Heo <tj@kernel.org>
+:Author: Florian Mickler <florian@mickler.org>
+
+
+Introduction
+============
+
+There are many cases where an asynchronous process execution context
+is needed and the workqueue (wq) API is the most commonly used
+mechanism for such cases.
+
+When such an asynchronous execution context is needed, a work item
+describing which function to execute is put on a queue.  An
+independent thread serves as the asynchronous execution context.  The
+queue is called workqueue and the thread is called worker.
+
+While there are work items on the workqueue the worker executes the
+functions associated with the work items one after the other.  When
+there is no work item left on the workqueue the worker becomes idle.
+When a new work item gets queued, the worker begins executing again.
+
+
+Why cmwq?
+=========
+
+In the original wq implementation, a multi threaded (MT) wq had one
+worker thread per CPU and a single threaded (ST) wq had one worker
+thread system-wide.  A single MT wq needed to keep around the same
+number of workers as the number of CPUs.  The kernel grew a lot of MT
+wq users over the years and with the number of CPU cores continuously
+rising, some systems saturated the default 32k PID space just booting
+up.
+
+Although MT wq wasted a lot of resource, the level of concurrency
+provided was unsatisfactory.  The limitation was common to both ST and
+MT wq albeit less severe on MT.  Each wq maintained its own separate
+worker pool.  A MT wq could provide only one execution context per CPU
+while a ST wq one for the whole system.  Work items had to compete for
+those very limited execution contexts leading to various problems
+including proneness to deadlocks around the single execution context.
+
+The tension between the provided level of concurrency and resource
+usage also forced its users to make unnecessary tradeoffs like libata
+choosing to use ST wq for polling PIOs and accepting an unnecessary
+limitation that no two polling PIOs can progress at the same time.  As
+MT wq don't provide much better concurrency, users which require
+higher level of concurrency, like async or fscache, had to implement
+their own thread pool.
+
+Concurrency Managed Workqueue (cmwq) is a reimplementation of wq with
+focus on the following goals.
+
+* Maintain compatibility with the original workqueue API.
+
+* Use per-CPU unified worker pools shared by all wq to provide
+  flexible level of concurrency on demand without wasting a lot of
+  resource.
+
+* Automatically regulate worker pool and level of concurrency so that
+  the API users don't need to worry about such details.
+
+
+The Design
+==========
+
+In order to ease the asynchronous execution of functions a new
+abstraction, the work item, is introduced.
+
+A work item is a simple struct that holds a pointer to the function
+that is to be executed asynchronously.  Whenever a driver or subsystem
+wants a function to be executed asynchronously it has to set up a work
+item pointing to that function and queue that work item on a
+workqueue.
+
+Special purpose threads, called worker threads, execute the functions
+off of the queue, one after the other.  If no work is queued, the
+worker threads become idle.  These worker threads are managed in so
+called worker-pools.
+
+The cmwq design differentiates between the user-facing workqueues that
+subsystems and drivers queue work items on and the backend mechanism
+which manages worker-pools and processes the queued work items.
+
+There are two worker-pools, one for normal work items and the other
+for high priority ones, for each possible CPU and some extra
+worker-pools to serve work items queued on unbound workqueues - the
+number of these backing pools is dynamic.
+
+Subsystems and drivers can create and queue work items through special
+workqueue API functions as they see fit. They can influence some
+aspects of the way the work items are executed by setting flags on the
+workqueue they are putting the work item on. These flags include
+things like CPU locality, concurrency limits, priority and more.  To
+get a detailed overview refer to the API description of
+``alloc_workqueue()`` below.
+
+When a work item is queued to a workqueue, the target worker-pool is
+determined according to the queue parameters and workqueue attributes
+and appended on the shared worklist of the worker-pool.  For example,
+unless specifically overridden, a work item of a bound workqueue will
+be queued on the worklist of either normal or highpri worker-pool that
+is associated to the CPU the issuer is running on.
+
+For any worker pool implementation, managing the concurrency level
+(how many execution contexts are active) is an important issue.  cmwq
+tries to keep the concurrency at a minimal but sufficient level.
+Minimal to save resources and sufficient in that the system is used at
+its full capacity.
+
+Each worker-pool bound to an actual CPU implements concurrency
+management by hooking into the scheduler.  The worker-pool is notified
+whenever an active worker wakes up or sleeps and keeps track of the
+number of the currently runnable workers.  Generally, work items are
+not expected to hog a CPU and consume many cycles.  That means
+maintaining just enough concurrency to prevent work processing from
+stalling should be optimal.  As long as there are one or more runnable
+workers on the CPU, the worker-pool doesn't start execution of a new
+work, but, when the last running worker goes to sleep, it immediately
+schedules a new worker so that the CPU doesn't sit idle while there
+are pending work items.  This allows using a minimal number of workers
+without losing execution bandwidth.
+
+Keeping idle workers around doesn't cost other than the memory space
+for kthreads, so cmwq holds onto idle ones for a while before killing
+them.
+
+For unbound workqueues, the number of backing pools is dynamic.
+Unbound workqueue can be assigned custom attributes using
+``apply_workqueue_attrs()`` and workqueue will automatically create
+backing worker pools matching the attributes.  The responsibility of
+regulating concurrency level is on the users.  There is also a flag to
+mark a bound wq to ignore the concurrency management.  Please refer to
+the API section for details.
+
+Forward progress guarantee relies on that workers can be created when
+more execution contexts are necessary, which in turn is guaranteed
+through the use of rescue workers.  All work items which might be used
+on code paths that handle memory reclaim are required to be queued on
+wq's that have a rescue-worker reserved for execution under memory
+pressure.  Else it is possible that the worker-pool deadlocks waiting
+for execution contexts to free up.
+
+
+Application Programming Interface (API)
+=======================================
+
+``alloc_workqueue()`` allocates a wq.  The original
+``create_*workqueue()`` functions are deprecated and scheduled for
+removal.  ``alloc_workqueue()`` takes three arguments - @``name``,
+``@flags`` and ``@max_active``.  ``@name`` is the name of the wq and
+also used as the name of the rescuer thread if there is one.
+
+A wq no longer manages execution resources but serves as a domain for
+forward progress guarantee, flush and work item attributes. ``@flags``
+and ``@max_active`` control how work items are assigned execution
+resources, scheduled and executed.
+
+
+``flags``
+---------
+
+``WQ_UNBOUND``
+  Work items queued to an unbound wq are served by the special
+  worker-pools which host workers which are not bound to any
+  specific CPU.  This makes the wq behave as a simple execution
+  context provider without concurrency management.  The unbound
+  worker-pools try to start execution of work items as soon as
+  possible.  Unbound wq sacrifices locality but is useful for
+  the following cases.
+
+  * Wide fluctuation in the concurrency level requirement is
+    expected and using bound wq may end up creating large number
+    of mostly unused workers across different CPUs as the issuer
+    hops through different CPUs.
+
+  * Long running CPU intensive workloads which can be better
+    managed by the system scheduler.
+
+``WQ_FREEZABLE``
+  A freezable wq participates in the freeze phase of the system
+  suspend operations.  Work items on the wq are drained and no
+  new work item starts execution until thawed.
+
+``WQ_MEM_RECLAIM``
+  All wq which might be used in the memory reclaim paths **MUST**
+  have this flag set.  The wq is guaranteed to have at least one
+  execution context regardless of memory pressure.
+
+``WQ_HIGHPRI``
+  Work items of a highpri wq are queued to the highpri
+  worker-pool of the target cpu.  Highpri worker-pools are
+  served by worker threads with elevated nice level.
+
+  Note that normal and highpri worker-pools don't interact with
+  each other.  Each maintain its separate pool of workers and
+  implements concurrency management among its workers.
+
+``WQ_CPU_INTENSIVE``
+  Work items of a CPU intensive wq do not contribute to the
+  concurrency level.  In other words, runnable CPU intensive
+  work items will not prevent other work items in the same
+  worker-pool from starting execution.  This is useful for bound
+  work items which are expected to hog CPU cycles so that their
+  execution is regulated by the system scheduler.
+
+  Although CPU intensive work items don't contribute to the
+  concurrency level, start of their executions is still
+  regulated by the concurrency management and runnable
+  non-CPU-intensive work items can delay execution of CPU
+  intensive work items.
+
+  This flag is meaningless for unbound wq.
+
+Note that the flag ``WQ_NON_REENTRANT`` no longer exists as all
+workqueues are now non-reentrant - any work item is guaranteed to be
+executed by at most one worker system-wide at any given time.
+
+
+``max_active``
+--------------
+
+``@max_active`` determines the maximum number of execution contexts
+per CPU which can be assigned to the work items of a wq.  For example,
+with ``@max_active`` of 16, at most 16 work items of the wq can be
+executing at the same time per CPU.
+
+Currently, for a bound wq, the maximum limit for ``@max_active`` is
+512 and the default value used when 0 is specified is 256.  For an
+unbound wq, the limit is higher of 512 and 4 *
+``num_possible_cpus()``.  These values are chosen sufficiently high
+such that they are not the limiting factor while providing protection
+in runaway cases.
+
+The number of active work items of a wq is usually regulated by the
+users of the wq, more specifically, by how many work items the users
+may queue at the same time.  Unless there is a specific need for
+throttling the number of active work items, specifying '0' is
+recommended.
+
+Some users depend on the strict execution ordering of ST wq.  The
+combination of ``@max_active`` of 1 and ``WQ_UNBOUND`` is used to
+achieve this behavior.  Work items on such wq are always queued to the
+unbound worker-pools and only one work item can be active at any given
+time thus achieving the same ordering property as ST wq.
+
+
+Example Execution Scenarios
+===========================
+
+The following example execution scenarios try to illustrate how cmwq
+behave under different configurations.
+
+ Work items w0, w1, w2 are queued to a bound wq q0 on the same CPU.
+ w0 burns CPU for 5ms then sleeps for 10ms then burns CPU for 5ms
+ again before finishing.  w1 and w2 burn CPU for 5ms then sleep for
+ 10ms.
+
+Ignoring all other tasks, works and processing overhead, and assuming
+simple FIFO scheduling, the following is one highly simplified version
+of possible sequences of events with the original wq. ::
+
+ TIME IN MSECS	EVENT
+ 0		w0 starts and burns CPU
+ 5		w0 sleeps
+ 15		w0 wakes up and burns CPU
+ 20		w0 finishes
+ 20		w1 starts and burns CPU
+ 25		w1 sleeps
+ 35		w1 wakes up and finishes
+ 35		w2 starts and burns CPU
+ 40		w2 sleeps
+ 50		w2 wakes up and finishes
+
+And with cmwq with ``@max_active`` >= 3, ::
+
+ TIME IN MSECS	EVENT
+ 0		w0 starts and burns CPU
+ 5		w0 sleeps
+ 5		w1 starts and burns CPU
+ 10		w1 sleeps
+ 10		w2 starts and burns CPU
+ 15		w2 sleeps
+ 15		w0 wakes up and burns CPU
+ 20		w0 finishes
+ 20		w1 wakes up and finishes
+ 25		w2 wakes up and finishes
+
+If ``@max_active`` == 2, ::
+
+ TIME IN MSECS	EVENT
+ 0		w0 starts and burns CPU
+ 5		w0 sleeps
+ 5		w1 starts and burns CPU
+ 10		w1 sleeps
+ 15		w0 wakes up and burns CPU
+ 20		w0 finishes
+ 20		w1 wakes up and finishes
+ 20		w2 starts and burns CPU
+ 25		w2 sleeps
+ 35		w2 wakes up and finishes
+
+Now, let's assume w1 and w2 are queued to a different wq q1 which has
+``WQ_CPU_INTENSIVE`` set, ::
+
+ TIME IN MSECS	EVENT
+ 0		w0 starts and burns CPU
+ 5		w0 sleeps
+ 5		w1 and w2 start and burn CPU
+ 10		w1 sleeps
+ 15		w2 sleeps
+ 15		w0 wakes up and burns CPU
+ 20		w0 finishes
+ 20		w1 wakes up and finishes
+ 25		w2 wakes up and finishes
+
+
+Guidelines
+==========
+
+* Do not forget to use ``WQ_MEM_RECLAIM`` if a wq may process work
+  items which are used during memory reclaim.  Each wq with
+  ``WQ_MEM_RECLAIM`` set has an execution context reserved for it.  If
+  there is dependency among multiple work items used during memory
+  reclaim, they should be queued to separate wq each with
+  ``WQ_MEM_RECLAIM``.
+
+* Unless strict ordering is required, there is no need to use ST wq.
+
+* Unless there is a specific need, using 0 for @max_active is
+  recommended.  In most use cases, concurrency level usually stays
+  well under the default limit.
+
+* A wq serves as a domain for forward progress guarantee
+  (``WQ_MEM_RECLAIM``, flush and work item attributes.  Work items
+  which are not involved in memory reclaim and don't need to be
+  flushed as a part of a group of work items, and don't require any
+  special attribute, can use one of the system wq.  There is no
+  difference in execution characteristics between using a dedicated wq
+  and a system wq.
+
+* Unless work items are expected to consume a huge amount of CPU
+  cycles, using a bound wq is usually beneficial due to the increased
+  level of locality in wq operations and work item execution.
+
+
+Debugging
+=========
+
+Because the work functions are executed by generic worker threads
+there are a few tricks needed to shed some light on misbehaving
+workqueue users.
+
+Worker threads show up in the process list as: ::
+
+  root      5671  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/0:1]
+  root      5672  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/1:2]
+  root      5673  0.0  0.0      0     0 ?        S    12:12   0:00 [kworker/0:0]
+  root      5674  0.0  0.0      0     0 ?        S    12:13   0:00 [kworker/1:0]
+
+If kworkers are going crazy (using too much cpu), there are two types
+of possible problems:
+
+	1. Something being scheduled in rapid succession
+	2. A single work item that consumes lots of cpu cycles
+
+The first one can be tracked using tracing: ::
+
+	$ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event
+	$ cat /sys/kernel/debug/tracing/trace_pipe > out.txt
+	(wait a few secs)
+	^C
+
+If something is busy looping on work queueing, it would be dominating
+the output and the offender can be determined with the work item
+function.
+
+For the second type of problems it should be possible to just check
+the stack trace of the offending worker thread. ::
+
+	$ cat /proc/THE_OFFENDING_KWORKER/stack
+
+The work item's function should be trivially visible in the stack
+trace.
+
+
+Kernel Inline Documentations Reference
+======================================
+
+.. kernel-doc:: include/linux/workqueue.h
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/cpu-freq/cpufreq-stats.txt linux-libre-4.10-rc8-gnu/Documentation/cpu-freq/cpufreq-stats.txt
--- linux-libre-4.9-gnu/Documentation/cpu-freq/cpufreq-stats.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/cpu-freq/cpufreq-stats.txt	2017-02-12 16:03:20.000000000 -0500
@@ -44,11 +44,17 @@ the stats driver insertion.
 total 0
 drwxr-xr-x  2 root root    0 May 14 16:06 .
 drwxr-xr-x  3 root root    0 May 14 15:58 ..
+--w-------  1 root root 4096 May 14 16:06 reset
 -r--r--r--  1 root root 4096 May 14 16:06 time_in_state
 -r--r--r--  1 root root 4096 May 14 16:06 total_trans
 -r--r--r--  1 root root 4096 May 14 16:06 trans_table
 --------------------------------------------------------------------------------
 
+-  reset
+Write-only attribute that can be used to reset the stat counters. This can be
+useful for evaluating system behaviour under different governors without the
+need for a reboot.
+
 -  time_in_state
 This gives the amount of time spent in each of the frequencies supported by
 this CPU. The cat output will have "<frequency> <time>" pair in each line, which
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/cpu-freq/intel-pstate.txt linux-libre-4.10-rc8-gnu/Documentation/cpu-freq/intel-pstate.txt
--- linux-libre-4.9-gnu/Documentation/cpu-freq/intel-pstate.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/cpu-freq/intel-pstate.txt	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@ In addition to the frequency-controlling
 core, the driver provides its own sysfs files to control the P-State selection.
 These files have been added to /sys/devices/system/cpu/intel_pstate/.
 Any changes made to these files are applicable to all CPUs (even in a
-multi-package system).
+multi-package system, Refer to later section on placing "Per-CPU limits").
 
       max_perf_pct: Limits the maximum P-State that will be requested by
       the driver. It states it as a percentage of the available performance. The
@@ -120,13 +120,57 @@ frequency is fictional for Intel Core pr
 driver selects a single P-State, the actual frequency the processor
 will run at is selected by the processor itself.
 
+Per-CPU limits
+
+The kernel command line option "intel_pstate=per_cpu_perf_limits" forces
+the intel_pstate driver to use per-CPU performance limits.  When it is set,
+the sysfs control interface described above is subject to limitations.
+- The following controls are not available for both read and write
+	/sys/devices/system/cpu/intel_pstate/max_perf_pct
+	/sys/devices/system/cpu/intel_pstate/min_perf_pct
+- The following controls can be used to set performance limits, as far as the
+architecture of the processor permits:
+	/sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq
+	/sys/devices/system/cpu/cpu*/cpufreq/scaling_min_freq
+	/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
+- User can still observe turbo percent and number of P-States from
+	/sys/devices/system/cpu/intel_pstate/turbo_pct
+	/sys/devices/system/cpu/intel_pstate/num_pstates
+- User can read write system wide turbo status
+	/sys/devices/system/cpu/no_turbo
+
+Support of energy performance hints
+It is possible to provide hints to the HWP algorithms in the processor
+to be more performance centric to more energy centric. When the driver
+is using HWP, two additional cpufreq sysfs attributes are presented for
+each logical CPU.
+These attributes are:
+	- energy_performance_available_preferences
+	- energy_performance_preference
+
+To get list of supported hints:
+$ cat energy_performance_available_preferences
+    default performance balance_performance balance_power power
+
+The current preference can be read or changed via cpufreq sysfs
+attribute "energy_performance_preference". Reading from this attribute
+will display current effective setting. User can write any of the valid
+preference string to this attribute. User can always restore to power-on
+default by writing "default".
+
+Since threads can migrate to different CPUs, this is possible that the
+new CPU may have different energy performance preference than the previous
+one. To avoid such issues, either threads can be pinned to specific CPUs
+or set the same energy performance preference value to all CPUs.
+
 Tuning Intel P-State driver
 
-When HWP mode is not used, debugfs files have also been added to allow the
-tuning of the internal governor algorithm. These files are located at
-/sys/kernel/debug/pstate_snb/. The algorithm uses a PID (Proportional
-Integral Derivative) controller. The PID tunable parameters are:
+When the performance can be tuned using PID (Proportional Integral
+Derivative) controller, debugfs files are provided for adjusting performance.
+They are presented under:
+/sys/kernel/debug/pstate_snb/
 
+The PID tunable parameters are:
       deadband
       d_gain_pct
       i_gain_pct
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/cpu-hotplug.txt linux-libre-4.10-rc8-gnu/Documentation/cpu-hotplug.txt
--- linux-libre-4.9-gnu/Documentation/cpu-hotplug.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/cpu-hotplug.txt	2017-02-12 16:03:20.000000000 -0500
@@ -84,9 +84,9 @@ are added or removed anytime.  Trimming
 upfront can save some boot time memory. See below for how we use heuristics
 in x86_64 case to keep this under check.
 
-cpu_online_mask: Bitmap of all CPUs currently online. Its set in __cpu_up()
-after a cpu is available for kernel scheduling and ready to receive
-interrupts from devices. Its cleared when a cpu is brought down using
+cpu_online_mask: Bitmap of all CPUs currently online. It's set in __cpu_up()
+after a CPU is available for kernel scheduling and ready to receive
+interrupts from devices. It's cleared when a CPU is brought down using
 __cpu_disable(), before which all OS services including interrupts are
 migrated to another target CPU.
 
@@ -181,7 +181,7 @@ To support physical addition/removal, on
 the platform should have something like an attention button in PCI hotplug.
 CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs.
 
-Q: How do i logically offline a CPU?
+Q: How do I logically offline a CPU?
 A: Do the following.
 
 	#echo 0 > /sys/devices/system/cpu/cpuX/online
@@ -191,15 +191,15 @@ Once the logical offline is successful,
 	#cat /proc/interrupts
 
 You should now not see the CPU that you removed. Also online file will report
-the state as 0 when a cpu if offline and 1 when its online.
+the state as 0 when a CPU is offline and 1 when it's online.
 
 	#To display the current cpu state.
 	#cat /sys/devices/system/cpu/cpuX/online
 
-Q: Why can't i remove CPU0 on some systems?
+Q: Why can't I remove CPU0 on some systems?
 A: Some architectures may have some special dependency on a certain CPU.
 
-For e.g in IA64 platforms we have ability to sent platform interrupts to the
+For e.g in IA64 platforms we have ability to send platform interrupts to the
 OS. a.k.a Corrected Platform Error Interrupts (CPEI). In current ACPI
 specifications, we didn't have a way to change the target CPU. Hence if the
 current ACPI version doesn't support such re-direction, we disable that CPU
@@ -231,7 +231,7 @@ either by CONFIG_BOOTPARAM_HOTPLUG_CPU0
 
 --Fenghua Yu <fenghua.yu@intel.com>
 
-Q: How do i find out if a particular CPU is not removable?
+Q: How do I find out if a particular CPU is not removable?
 A: Depending on the implementation, some architectures may show this by the
 absence of the "online" file. This is done if it can be determined ahead of
 time that this CPU cannot be removed.
@@ -250,7 +250,7 @@ A: The following happen, listed in no pa
 - All processes are migrated away from this outgoing CPU to new CPUs.
   The new CPU is chosen from each process' current cpuset, which may be
   a subset of all online CPUs.
-- All interrupts targeted to this CPU is migrated to a new CPU
+- All interrupts targeted to this CPU are migrated to a new CPU
 - timers/bottom half/task lets are also migrated to a new CPU
 - Once all services are migrated, kernel calls an arch specific routine
   __cpu_disable() to perform arch specific cleanup.
@@ -259,10 +259,10 @@ A: The following happen, listed in no pa
   CPU is being offlined).
 
   "It is expected that each service cleans up when the CPU_DOWN_PREPARE
-  notifier is called, when CPU_DEAD is called its expected there is nothing
+  notifier is called, when CPU_DEAD is called it's expected there is nothing
   running on behalf of this CPU that was offlined"
 
-Q: If i have some kernel code that needs to be aware of CPU arrival and
+Q: If I have some kernel code that needs to be aware of CPU arrival and
    departure, how to i arrange for proper notification?
 A: This is what you would need in your kernel code to receive notifications.
 
@@ -311,7 +311,7 @@ things will happen if a notifier in path
 
 Q: I don't see my action being called for all CPUs already up and running?
 A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined.
-   If you need to perform some action for each cpu already in the system, then
+   If you need to perform some action for each CPU already in the system, then
    do this:
 
 	for_each_online_cpu(i) {
@@ -363,8 +363,8 @@ A: Yes, CPU notifiers are called only wh
     callbacks as well as initialize the already online CPUs.
 
 
-Q: If i would like to develop cpu hotplug support for a new architecture,
-   what do i need at a minimum?
+Q: If I would like to develop CPU hotplug support for a new architecture,
+   what do I need at a minimum?
 A: The following are what is required for CPU hotplug infrastructure to work
    correctly.
 
@@ -382,8 +382,8 @@ A: The following are what is required fo
                           per_cpu state to be set, to ensure the processor
                           dead routine is called to be sure positively.
 
-Q: I need to ensure that a particular cpu is not removed when there is some
-   work specific to this cpu is in progress.
+Q: I need to ensure that a particular CPU is not removed when there is some
+   work specific to this CPU in progress.
 A: There are two ways.  If your code can be run in interrupt context, use
    smp_call_function_single(), otherwise use work_on_cpu().  Note that
    work_on_cpu() is slow, and can fail due to out of memory:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-aead.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api-aead.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api-aead.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-aead.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,23 @@
+Authenticated Encryption With Associated Data (AEAD) Algorithm Definitions
+--------------------------------------------------------------------------
+
+.. kernel-doc:: include/crypto/aead.h
+   :doc: Authenticated Encryption With Associated Data (AEAD) Cipher API
+
+.. kernel-doc:: include/crypto/aead.h
+   :functions: aead_request aead_alg
+
+Authenticated Encryption With Associated Data (AEAD) Cipher API
+---------------------------------------------------------------
+
+.. kernel-doc:: include/crypto/aead.h
+   :functions: crypto_alloc_aead crypto_free_aead crypto_aead_ivsize crypto_aead_authsize crypto_aead_blocksize crypto_aead_setkey crypto_aead_setauthsize crypto_aead_encrypt crypto_aead_decrypt
+
+Asynchronous AEAD Request Handle
+--------------------------------
+
+.. kernel-doc:: include/crypto/aead.h
+   :doc: Asynchronous AEAD Request Handle
+
+.. kernel-doc:: include/crypto/aead.h
+   :functions: crypto_aead_reqsize aead_request_set_tfm aead_request_alloc aead_request_free aead_request_set_callback aead_request_set_crypt aead_request_set_ad
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-akcipher.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api-akcipher.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api-akcipher.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-akcipher.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+Asymmetric Cipher Algorithm Definitions
+---------------------------------------
+
+.. kernel-doc:: include/crypto/akcipher.h
+   :functions: akcipher_alg akcipher_request
+
+Asymmetric Cipher API
+---------------------
+
+.. kernel-doc:: include/crypto/akcipher.h
+   :doc: Generic Public Key API
+
+.. kernel-doc:: include/crypto/akcipher.h
+   :functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt crypto_akcipher_sign crypto_akcipher_verify
+
+Asymmetric Cipher Request Handle
+--------------------------------
+
+.. kernel-doc:: include/crypto/akcipher.h
+   :functions: akcipher_request_alloc akcipher_request_free akcipher_request_set_callback akcipher_request_set_crypt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-digest.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api-digest.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api-digest.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-digest.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,35 @@
+Message Digest Algorithm Definitions
+------------------------------------
+
+.. kernel-doc:: include/crypto/hash.h
+   :doc: Message Digest Algorithm Definitions
+
+.. kernel-doc:: include/crypto/hash.h
+   :functions: hash_alg_common ahash_alg shash_alg
+
+Asynchronous Message Digest API
+-------------------------------
+
+.. kernel-doc:: include/crypto/hash.h
+   :doc: Asynchronous Message Digest API
+
+.. kernel-doc:: include/crypto/hash.h
+   :functions: crypto_alloc_ahash crypto_free_ahash crypto_ahash_init crypto_ahash_digestsize crypto_ahash_reqtfm crypto_ahash_reqsize crypto_ahash_setkey crypto_ahash_finup crypto_ahash_final crypto_ahash_digest crypto_ahash_export crypto_ahash_import
+
+Asynchronous Hash Request Handle
+--------------------------------
+
+.. kernel-doc:: include/crypto/hash.h
+   :doc: Asynchronous Hash Request Handle
+
+.. kernel-doc:: include/crypto/hash.h
+   :functions: ahash_request_set_tfm ahash_request_alloc ahash_request_free ahash_request_set_callback ahash_request_set_crypt
+
+Synchronous Message Digest API
+------------------------------
+
+.. kernel-doc:: include/crypto/hash.h
+   :doc: Synchronous Message Digest API
+
+.. kernel-doc:: include/crypto/hash.h
+   :functions: crypto_alloc_shash crypto_free_shash crypto_shash_blocksize crypto_shash_digestsize crypto_shash_descsize crypto_shash_setkey crypto_shash_digest crypto_shash_export crypto_shash_import crypto_shash_init crypto_shash_update crypto_shash_final crypto_shash_finup
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-intro.txt linux-libre-4.10-rc8-gnu/Documentation/crypto/api-intro.txt
--- linux-libre-4.9-gnu/Documentation/crypto/api-intro.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-intro.txt	2017-02-12 16:03:20.000000000 -0500
@@ -44,12 +44,9 @@ one block while the former can operate o
 subject to block size requirements (i.e., non-stream ciphers can only
 process multiples of blocks).
 
-Support for hardware crypto devices via an asynchronous interface is
-under development.
-
 Here's an example of how to use the API:
 
-	#include <crypto/ahash.h>
+	#include <crypto/hash.h>
 	#include <linux/err.h>
 	#include <linux/scatterlist.h>
 	
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-kpp.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api-kpp.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api-kpp.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-kpp.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+Key-agreement Protocol Primitives (KPP) Cipher Algorithm Definitions
+--------------------------------------------------------------------
+
+.. kernel-doc:: include/crypto/kpp.h
+   :functions: kpp_request crypto_kpp kpp_alg kpp_secret
+
+Key-agreement Protocol Primitives (KPP) Cipher API
+--------------------------------------------------
+
+.. kernel-doc:: include/crypto/kpp.h
+   :doc: Generic Key-agreement Protocol Primitives API
+
+.. kernel-doc:: include/crypto/kpp.h
+   :functions: crypto_alloc_kpp crypto_free_kpp crypto_kpp_set_secret crypto_kpp_generate_public_key crypto_kpp_compute_shared_secret crypto_kpp_maxsize
+
+Key-agreement Protocol Primitives (KPP) Cipher Request Handle
+-------------------------------------------------------------
+
+.. kernel-doc:: include/crypto/kpp.h
+   :functions: kpp_request_alloc kpp_request_free kpp_request_set_callback kpp_request_set_input kpp_request_set_output
+
+ECDH Helper Functions
+---------------------
+
+.. kernel-doc:: include/crypto/ecdh.h
+   :doc: ECDH Helper Functions
+
+.. kernel-doc:: include/crypto/ecdh.h
+   :functions: ecdh crypto_ecdh_key_len crypto_ecdh_encode_key crypto_ecdh_decode_key
+
+DH Helper Functions
+-------------------
+
+.. kernel-doc:: include/crypto/dh.h
+   :doc: DH Helper Functions
+
+.. kernel-doc:: include/crypto/dh.h
+   :functions: dh crypto_dh_key_len crypto_dh_encode_key crypto_dh_decode_key
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-rng.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api-rng.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api-rng.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-rng.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,14 @@
+Random Number Algorithm Definitions
+-----------------------------------
+
+.. kernel-doc:: include/crypto/rng.h
+   :functions: rng_alg
+
+Crypto API Random Number API
+----------------------------
+
+.. kernel-doc:: include/crypto/rng.h
+   :doc: Random number generator API
+
+.. kernel-doc:: include/crypto/rng.h
+   :functions: crypto_alloc_rng crypto_rng_alg crypto_free_rng crypto_rng_generate crypto_rng_get_bytes crypto_rng_reset crypto_rng_seedsize
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,25 @@
+Programming Interface
+=====================
+
+Please note that the kernel crypto API contains the AEAD givcrypt API
+(crypto_aead_giv\* and aead_givcrypt\* function calls in
+include/crypto/aead.h). This API is obsolete and will be removed in the
+future. To obtain the functionality of an AEAD cipher with internal IV
+generation, use the IV generator as a regular cipher. For example,
+rfc4106(gcm(aes)) is the AEAD cipher with external IV generation and
+seqniv(rfc4106(gcm(aes))) implies that the kernel crypto API generates
+the IV. Different IV generators are available.
+
+.. class:: toc-title
+
+	   Table of contents
+
+.. toctree::
+   :maxdepth: 2
+
+   api-skcipher
+   api-aead
+   api-digest
+   api-rng
+   api-akcipher
+   api-kpp
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-samples.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api-samples.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api-samples.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-samples.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,224 @@
+Code Examples
+=============
+
+Code Example For Symmetric Key Cipher Operation
+-----------------------------------------------
+
+::
+
+
+    struct tcrypt_result {
+        struct completion completion;
+        int err;
+    };
+
+    /* tie all data structures together */
+    struct skcipher_def {
+        struct scatterlist sg;
+        struct crypto_skcipher *tfm;
+        struct skcipher_request *req;
+        struct tcrypt_result result;
+    };
+
+    /* Callback function */
+    static void test_skcipher_cb(struct crypto_async_request *req, int error)
+    {
+        struct tcrypt_result *result = req->data;
+
+        if (error == -EINPROGRESS)
+            return;
+        result->err = error;
+        complete(&result->completion);
+        pr_info("Encryption finished successfully\n");
+    }
+
+    /* Perform cipher operation */
+    static unsigned int test_skcipher_encdec(struct skcipher_def *sk,
+                         int enc)
+    {
+        int rc = 0;
+
+        if (enc)
+            rc = crypto_skcipher_encrypt(sk->req);
+        else
+            rc = crypto_skcipher_decrypt(sk->req);
+
+        switch (rc) {
+        case 0:
+            break;
+        case -EINPROGRESS:
+        case -EBUSY:
+            rc = wait_for_completion_interruptible(
+                &sk->result.completion);
+            if (!rc && !sk->result.err) {
+                reinit_completion(&sk->result.completion);
+                break;
+            }
+        default:
+            pr_info("skcipher encrypt returned with %d result %d\n",
+                rc, sk->result.err);
+            break;
+        }
+        init_completion(&sk->result.completion);
+
+        return rc;
+    }
+
+    /* Initialize and trigger cipher operation */
+    static int test_skcipher(void)
+    {
+        struct skcipher_def sk;
+        struct crypto_skcipher *skcipher = NULL;
+        struct skcipher_request *req = NULL;
+        char *scratchpad = NULL;
+        char *ivdata = NULL;
+        unsigned char key[32];
+        int ret = -EFAULT;
+
+        skcipher = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0);
+        if (IS_ERR(skcipher)) {
+            pr_info("could not allocate skcipher handle\n");
+            return PTR_ERR(skcipher);
+        }
+
+        req = skcipher_request_alloc(skcipher, GFP_KERNEL);
+        if (!req) {
+            pr_info("could not allocate skcipher request\n");
+            ret = -ENOMEM;
+            goto out;
+        }
+
+        skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                          test_skcipher_cb,
+                          &sk.result);
+
+        /* AES 256 with random key */
+        get_random_bytes(&key, 32);
+        if (crypto_skcipher_setkey(skcipher, key, 32)) {
+            pr_info("key could not be set\n");
+            ret = -EAGAIN;
+            goto out;
+        }
+
+        /* IV will be random */
+        ivdata = kmalloc(16, GFP_KERNEL);
+        if (!ivdata) {
+            pr_info("could not allocate ivdata\n");
+            goto out;
+        }
+        get_random_bytes(ivdata, 16);
+
+        /* Input data will be random */
+        scratchpad = kmalloc(16, GFP_KERNEL);
+        if (!scratchpad) {
+            pr_info("could not allocate scratchpad\n");
+            goto out;
+        }
+        get_random_bytes(scratchpad, 16);
+
+        sk.tfm = skcipher;
+        sk.req = req;
+
+        /* We encrypt one block */
+        sg_init_one(&sk.sg, scratchpad, 16);
+        skcipher_request_set_crypt(req, &sk.sg, &sk.sg, 16, ivdata);
+        init_completion(&sk.result.completion);
+
+        /* encrypt data */
+        ret = test_skcipher_encdec(&sk, 1);
+        if (ret)
+            goto out;
+
+        pr_info("Encryption triggered successfully\n");
+
+    out:
+        if (skcipher)
+            crypto_free_skcipher(skcipher);
+        if (req)
+            skcipher_request_free(req);
+        if (ivdata)
+            kfree(ivdata);
+        if (scratchpad)
+            kfree(scratchpad);
+        return ret;
+    }
+
+
+Code Example For Use of Operational State Memory With SHASH
+-----------------------------------------------------------
+
+::
+
+
+    struct sdesc {
+        struct shash_desc shash;
+        char ctx[];
+    };
+
+    static struct sdescinit_sdesc(struct crypto_shash *alg)
+    {
+        struct sdescsdesc;
+        int size;
+
+        size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
+        sdesc = kmalloc(size, GFP_KERNEL);
+        if (!sdesc)
+            return ERR_PTR(-ENOMEM);
+        sdesc->shash.tfm = alg;
+        sdesc->shash.flags = 0x0;
+        return sdesc;
+    }
+
+    static int calc_hash(struct crypto_shashalg,
+                 const unsigned chardata, unsigned int datalen,
+                 unsigned chardigest) {
+        struct sdescsdesc;
+        int ret;
+
+        sdesc = init_sdesc(alg);
+        if (IS_ERR(sdesc)) {
+            pr_info("trusted_key: can't alloc %s\n", hash_alg);
+            return PTR_ERR(sdesc);
+        }
+
+        ret = crypto_shash_digest(&sdesc->shash, data, datalen, digest);
+        kfree(sdesc);
+        return ret;
+    }
+
+
+Code Example For Random Number Generator Usage
+----------------------------------------------
+
+::
+
+
+    static int get_random_numbers(u8 *buf, unsigned int len)
+    {
+        struct crypto_rngrng = NULL;
+        chardrbg = "drbg_nopr_sha256"; /* Hash DRBG with SHA-256, no PR */
+        int ret;
+
+        if (!buf || !len) {
+            pr_debug("No output buffer provided\n");
+            return -EINVAL;
+        }
+
+        rng = crypto_alloc_rng(drbg, 0, 0);
+        if (IS_ERR(rng)) {
+            pr_debug("could not allocate RNG handle for %s\n", drbg);
+            return -PTR_ERR(rng);
+        }
+
+        ret = crypto_rng_get_bytes(rng, buf, len);
+        if (ret < 0)
+            pr_debug("generation of random numbers failed\n");
+        else if (ret == 0)
+            pr_debug("RNG returned no data");
+        else
+            pr_debug("RNG returned %d bytes of data\n", ret);
+
+    out:
+        crypto_free_rng(rng);
+        return ret;
+    }
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/api-skcipher.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/api-skcipher.rst
--- linux-libre-4.9-gnu/Documentation/crypto/api-skcipher.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/api-skcipher.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,62 @@
+Block Cipher Algorithm Definitions
+----------------------------------
+
+.. kernel-doc:: include/linux/crypto.h
+   :doc: Block Cipher Algorithm Definitions
+
+.. kernel-doc:: include/linux/crypto.h
+   :functions: crypto_alg ablkcipher_alg blkcipher_alg cipher_alg
+
+Symmetric Key Cipher API
+------------------------
+
+.. kernel-doc:: include/crypto/skcipher.h
+   :doc: Symmetric Key Cipher API
+
+.. kernel-doc:: include/crypto/skcipher.h
+   :functions: crypto_alloc_skcipher crypto_free_skcipher crypto_has_skcipher crypto_skcipher_ivsize crypto_skcipher_blocksize crypto_skcipher_setkey crypto_skcipher_reqtfm crypto_skcipher_encrypt crypto_skcipher_decrypt
+
+Symmetric Key Cipher Request Handle
+-----------------------------------
+
+.. kernel-doc:: include/crypto/skcipher.h
+   :doc: Symmetric Key Cipher Request Handle
+
+.. kernel-doc:: include/crypto/skcipher.h
+   :functions: crypto_skcipher_reqsize skcipher_request_set_tfm skcipher_request_alloc skcipher_request_free skcipher_request_set_callback skcipher_request_set_crypt
+
+Single Block Cipher API
+-----------------------
+
+.. kernel-doc:: include/linux/crypto.h
+   :doc: Single Block Cipher API
+
+.. kernel-doc:: include/linux/crypto.h
+   :functions: crypto_alloc_cipher crypto_free_cipher crypto_has_cipher crypto_cipher_blocksize crypto_cipher_setkey crypto_cipher_encrypt_one crypto_cipher_decrypt_one
+
+Asynchronous Block Cipher API - Deprecated
+------------------------------------------
+
+.. kernel-doc:: include/linux/crypto.h
+   :doc: Asynchronous Block Cipher API
+
+.. kernel-doc:: include/linux/crypto.h
+   :functions: crypto_free_ablkcipher crypto_has_ablkcipher crypto_ablkcipher_ivsize crypto_ablkcipher_blocksize crypto_ablkcipher_setkey crypto_ablkcipher_reqtfm crypto_ablkcipher_encrypt crypto_ablkcipher_decrypt
+
+Asynchronous Cipher Request Handle - Deprecated
+-----------------------------------------------
+
+.. kernel-doc:: include/linux/crypto.h
+   :doc: Asynchronous Cipher Request Handle
+
+.. kernel-doc:: include/linux/crypto.h
+   :functions: crypto_ablkcipher_reqsize ablkcipher_request_set_tfm ablkcipher_request_alloc ablkcipher_request_free ablkcipher_request_set_callback ablkcipher_request_set_crypt
+
+Synchronous Block Cipher API - Deprecated
+-----------------------------------------
+
+.. kernel-doc:: include/linux/crypto.h
+   :doc: Synchronous Block Cipher API
+
+.. kernel-doc:: include/linux/crypto.h
+   :functions: crypto_alloc_blkcipher rypto_free_blkcipher crypto_has_blkcipher crypto_blkcipher_name crypto_blkcipher_ivsize crypto_blkcipher_blocksize crypto_blkcipher_setkey crypto_blkcipher_encrypt crypto_blkcipher_encrypt_iv crypto_blkcipher_decrypt crypto_blkcipher_decrypt_iv crypto_blkcipher_set_iv crypto_blkcipher_get_iv
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/architecture.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/architecture.rst
--- linux-libre-4.9-gnu/Documentation/crypto/architecture.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/architecture.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,441 @@
+Kernel Crypto API Architecture
+==============================
+
+Cipher algorithm types
+----------------------
+
+The kernel crypto API provides different API calls for the following
+cipher types:
+
+-  Symmetric ciphers
+
+-  AEAD ciphers
+
+-  Message digest, including keyed message digest
+
+-  Random number generation
+
+-  User space interface
+
+Ciphers And Templates
+---------------------
+
+The kernel crypto API provides implementations of single block ciphers
+and message digests. In addition, the kernel crypto API provides
+numerous "templates" that can be used in conjunction with the single
+block ciphers and message digests. Templates include all types of block
+chaining mode, the HMAC mechanism, etc.
+
+Single block ciphers and message digests can either be directly used by
+a caller or invoked together with a template to form multi-block ciphers
+or keyed message digests.
+
+A single block cipher may even be called with multiple templates.
+However, templates cannot be used without a single cipher.
+
+See /proc/crypto and search for "name". For example:
+
+-  aes
+
+-  ecb(aes)
+
+-  cmac(aes)
+
+-  ccm(aes)
+
+-  rfc4106(gcm(aes))
+
+-  sha1
+
+-  hmac(sha1)
+
+-  authenc(hmac(sha1),cbc(aes))
+
+In these examples, "aes" and "sha1" are the ciphers and all others are
+the templates.
+
+Synchronous And Asynchronous Operation
+--------------------------------------
+
+The kernel crypto API provides synchronous and asynchronous API
+operations.
+
+When using the synchronous API operation, the caller invokes a cipher
+operation which is performed synchronously by the kernel crypto API.
+That means, the caller waits until the cipher operation completes.
+Therefore, the kernel crypto API calls work like regular function calls.
+For synchronous operation, the set of API calls is small and
+conceptually similar to any other crypto library.
+
+Asynchronous operation is provided by the kernel crypto API which
+implies that the invocation of a cipher operation will complete almost
+instantly. That invocation triggers the cipher operation but it does not
+signal its completion. Before invoking a cipher operation, the caller
+must provide a callback function the kernel crypto API can invoke to
+signal the completion of the cipher operation. Furthermore, the caller
+must ensure it can handle such asynchronous events by applying
+appropriate locking around its data. The kernel crypto API does not
+perform any special serialization operation to protect the caller's data
+integrity.
+
+Crypto API Cipher References And Priority
+-----------------------------------------
+
+A cipher is referenced by the caller with a string. That string has the
+following semantics:
+
+::
+
+        template(single block cipher)
+
+
+where "template" and "single block cipher" is the aforementioned
+template and single block cipher, respectively. If applicable,
+additional templates may enclose other templates, such as
+
+::
+
+        template1(template2(single block cipher)))
+
+
+The kernel crypto API may provide multiple implementations of a template
+or a single block cipher. For example, AES on newer Intel hardware has
+the following implementations: AES-NI, assembler implementation, or
+straight C. Now, when using the string "aes" with the kernel crypto API,
+which cipher implementation is used? The answer to that question is the
+priority number assigned to each cipher implementation by the kernel
+crypto API. When a caller uses the string to refer to a cipher during
+initialization of a cipher handle, the kernel crypto API looks up all
+implementations providing an implementation with that name and selects
+the implementation with the highest priority.
+
+Now, a caller may have the need to refer to a specific cipher
+implementation and thus does not want to rely on the priority-based
+selection. To accommodate this scenario, the kernel crypto API allows
+the cipher implementation to register a unique name in addition to
+common names. When using that unique name, a caller is therefore always
+sure to refer to the intended cipher implementation.
+
+The list of available ciphers is given in /proc/crypto. However, that
+list does not specify all possible permutations of templates and
+ciphers. Each block listed in /proc/crypto may contain the following
+information -- if one of the components listed as follows are not
+applicable to a cipher, it is not displayed:
+
+-  name: the generic name of the cipher that is subject to the
+   priority-based selection -- this name can be used by the cipher
+   allocation API calls (all names listed above are examples for such
+   generic names)
+
+-  driver: the unique name of the cipher -- this name can be used by the
+   cipher allocation API calls
+
+-  module: the kernel module providing the cipher implementation (or
+   "kernel" for statically linked ciphers)
+
+-  priority: the priority value of the cipher implementation
+
+-  refcnt: the reference count of the respective cipher (i.e. the number
+   of current consumers of this cipher)
+
+-  selftest: specification whether the self test for the cipher passed
+
+-  type:
+
+   -  skcipher for symmetric key ciphers
+
+   -  cipher for single block ciphers that may be used with an
+      additional template
+
+   -  shash for synchronous message digest
+
+   -  ahash for asynchronous message digest
+
+   -  aead for AEAD cipher type
+
+   -  compression for compression type transformations
+
+   -  rng for random number generator
+
+   -  givcipher for cipher with associated IV generator (see the geniv
+      entry below for the specification of the IV generator type used by
+      the cipher implementation)
+
+   -  kpp for a Key-agreement Protocol Primitive (KPP) cipher such as
+      an ECDH or DH implementation
+
+-  blocksize: blocksize of cipher in bytes
+
+-  keysize: key size in bytes
+
+-  ivsize: IV size in bytes
+
+-  seedsize: required size of seed data for random number generator
+
+-  digestsize: output size of the message digest
+
+-  geniv: IV generation type:
+
+   -  eseqiv for encrypted sequence number based IV generation
+
+   -  seqiv for sequence number based IV generation
+
+   -  chainiv for chain iv generation
+
+   -  <builtin> is a marker that the cipher implements IV generation and
+      handling as it is specific to the given cipher
+
+Key Sizes
+---------
+
+When allocating a cipher handle, the caller only specifies the cipher
+type. Symmetric ciphers, however, typically support multiple key sizes
+(e.g. AES-128 vs. AES-192 vs. AES-256). These key sizes are determined
+with the length of the provided key. Thus, the kernel crypto API does
+not provide a separate way to select the particular symmetric cipher key
+size.
+
+Cipher Allocation Type And Masks
+--------------------------------
+
+The different cipher handle allocation functions allow the specification
+of a type and mask flag. Both parameters have the following meaning (and
+are therefore not covered in the subsequent sections).
+
+The type flag specifies the type of the cipher algorithm. The caller
+usually provides a 0 when the caller wants the default handling.
+Otherwise, the caller may provide the following selections which match
+the aforementioned cipher types:
+
+-  CRYPTO_ALG_TYPE_CIPHER Single block cipher
+
+-  CRYPTO_ALG_TYPE_COMPRESS Compression
+
+-  CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with Associated Data
+   (MAC)
+
+-  CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher
+
+-  CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher
+
+-  CRYPTO_ALG_TYPE_GIVCIPHER Asynchronous multi-block cipher packed
+   together with an IV generator (see geniv field in the /proc/crypto
+   listing for the known IV generators)
+
+-  CRYPTO_ALG_TYPE_KPP Key-agreement Protocol Primitive (KPP) such as
+   an ECDH or DH implementation
+
+-  CRYPTO_ALG_TYPE_DIGEST Raw message digest
+
+-  CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST
+
+-  CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash
+
+-  CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash
+
+-  CRYPTO_ALG_TYPE_RNG Random Number Generation
+
+-  CRYPTO_ALG_TYPE_AKCIPHER Asymmetric cipher
+
+-  CRYPTO_ALG_TYPE_PCOMPRESS Enhanced version of
+   CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression /
+   decompression instead of performing the operation on one segment
+   only. CRYPTO_ALG_TYPE_PCOMPRESS is intended to replace
+   CRYPTO_ALG_TYPE_COMPRESS once existing consumers are converted.
+
+The mask flag restricts the type of cipher. The only allowed flag is
+CRYPTO_ALG_ASYNC to restrict the cipher lookup function to
+asynchronous ciphers. Usually, a caller provides a 0 for the mask flag.
+
+When the caller provides a mask and type specification, the caller
+limits the search the kernel crypto API can perform for a suitable
+cipher implementation for the given cipher name. That means, even when a
+caller uses a cipher name that exists during its initialization call,
+the kernel crypto API may not select it due to the used type and mask
+field.
+
+Internal Structure of Kernel Crypto API
+---------------------------------------
+
+The kernel crypto API has an internal structure where a cipher
+implementation may use many layers and indirections. This section shall
+help to clarify how the kernel crypto API uses various components to
+implement the complete cipher.
+
+The following subsections explain the internal structure based on
+existing cipher implementations. The first section addresses the most
+complex scenario where all other scenarios form a logical subset.
+
+Generic AEAD Cipher Structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following ASCII art decomposes the kernel crypto API layers when
+using the AEAD cipher with the automated IV generation. The shown
+example is used by the IPSEC layer.
+
+For other use cases of AEAD ciphers, the ASCII art applies as well, but
+the caller may not use the AEAD cipher with a separate IV generator. In
+this case, the caller must generate the IV.
+
+The depicted example decomposes the AEAD cipher of GCM(AES) based on the
+generic C implementations (gcm.c, aes-generic.c, ctr.c, ghash-generic.c,
+seqiv.c). The generic implementation serves as an example showing the
+complete logic of the kernel crypto API.
+
+It is possible that some streamlined cipher implementations (like
+AES-NI) provide implementations merging aspects which in the view of the
+kernel crypto API cannot be decomposed into layers any more. In case of
+the AES-NI implementation, the CTR mode, the GHASH implementation and
+the AES cipher are all merged into one cipher implementation registered
+with the kernel crypto API. In this case, the concept described by the
+following ASCII art applies too. However, the decomposition of GCM into
+the individual sub-components by the kernel crypto API is not done any
+more.
+
+Each block in the following ASCII art is an independent cipher instance
+obtained from the kernel crypto API. Each block is accessed by the
+caller or by other blocks using the API functions defined by the kernel
+crypto API for the cipher implementation type.
+
+The blocks below indicate the cipher type as well as the specific logic
+implemented in the cipher.
+
+The ASCII art picture also indicates the call structure, i.e. who calls
+which component. The arrows point to the invoked block where the caller
+uses the API applicable to the cipher type specified for the block.
+
+::
+
+
+    kernel crypto API                                |   IPSEC Layer
+                                                     |
+    +-----------+                                    |
+    |           |            (1)
+    |   aead    | <-----------------------------------  esp_output
+    |  (seqiv)  | ---+
+    +-----------+    |
+                     | (2)
+    +-----------+    |
+    |           | <--+                (2)
+    |   aead    | <-----------------------------------  esp_input
+    |   (gcm)   | ------------+
+    +-----------+             |
+          | (3)               | (5)
+          v                   v
+    +-----------+       +-----------+
+    |           |       |           |
+    |  skcipher |       |   ahash   |
+    |   (ctr)   | ---+  |  (ghash)  |
+    +-----------+    |  +-----------+
+                     |
+    +-----------+    | (4)
+    |           | <--+
+    |   cipher  |
+    |   (aes)   |
+    +-----------+
+
+
+
+The following call sequence is applicable when the IPSEC layer triggers
+an encryption operation with the esp_output function. During
+configuration, the administrator set up the use of rfc4106(gcm(aes)) as
+the cipher for ESP. The following call sequence is now depicted in the
+ASCII art above:
+
+1. esp_output() invokes crypto_aead_encrypt() to trigger an
+   encryption operation of the AEAD cipher with IV generator.
+
+   In case of GCM, the SEQIV implementation is registered as GIVCIPHER
+   in crypto_rfc4106_alloc().
+
+   The SEQIV performs its operation to generate an IV where the core
+   function is seqiv_geniv().
+
+2. Now, SEQIV uses the AEAD API function calls to invoke the associated
+   AEAD cipher. In our case, during the instantiation of SEQIV, the
+   cipher handle for GCM is provided to SEQIV. This means that SEQIV
+   invokes AEAD cipher operations with the GCM cipher handle.
+
+   During instantiation of the GCM handle, the CTR(AES) and GHASH
+   ciphers are instantiated. The cipher handles for CTR(AES) and GHASH
+   are retained for later use.
+
+   The GCM implementation is responsible to invoke the CTR mode AES and
+   the GHASH cipher in the right manner to implement the GCM
+   specification.
+
+3. The GCM AEAD cipher type implementation now invokes the SKCIPHER API
+   with the instantiated CTR(AES) cipher handle.
+
+   During instantiation of the CTR(AES) cipher, the CIPHER type
+   implementation of AES is instantiated. The cipher handle for AES is
+   retained.
+
+   That means that the SKCIPHER implementation of CTR(AES) only
+   implements the CTR block chaining mode. After performing the block
+   chaining operation, the CIPHER implementation of AES is invoked.
+
+4. The SKCIPHER of CTR(AES) now invokes the CIPHER API with the AES
+   cipher handle to encrypt one block.
+
+5. The GCM AEAD implementation also invokes the GHASH cipher
+   implementation via the AHASH API.
+
+When the IPSEC layer triggers the esp_input() function, the same call
+sequence is followed with the only difference that the operation starts
+with step (2).
+
+Generic Block Cipher Structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Generic block ciphers follow the same concept as depicted with the ASCII
+art picture above.
+
+For example, CBC(AES) is implemented with cbc.c, and aes-generic.c. The
+ASCII art picture above applies as well with the difference that only
+step (4) is used and the SKCIPHER block chaining mode is CBC.
+
+Generic Keyed Message Digest Structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Keyed message digest implementations again follow the same concept as
+depicted in the ASCII art picture above.
+
+For example, HMAC(SHA256) is implemented with hmac.c and
+sha256_generic.c. The following ASCII art illustrates the
+implementation:
+
+::
+
+
+    kernel crypto API            |       Caller
+                                 |
+    +-----------+         (1)    |
+    |           | <------------------  some_function
+    |   ahash   |
+    |   (hmac)  | ---+
+    +-----------+    |
+                     | (2)
+    +-----------+    |
+    |           | <--+
+    |   shash   |
+    |  (sha256) |
+    +-----------+
+
+
+
+The following call sequence is applicable when a caller triggers an HMAC
+operation:
+
+1. The AHASH API functions are invoked by the caller. The HMAC
+   implementation performs its operation as needed.
+
+   During initialization of the HMAC cipher, the SHASH cipher type of
+   SHA256 is instantiated. The cipher handle for the SHA256 instance is
+   retained.
+
+   At one time, the HMAC implementation requires a SHA256 operation
+   where the SHA256 cipher handle is used.
+
+2. The HMAC instance now invokes the SHASH API with the SHA256 cipher
+   handle to calculate the message digest.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/devel-algos.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/devel-algos.rst
--- linux-libre-4.9-gnu/Documentation/crypto/devel-algos.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/devel-algos.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,247 @@
+Developing Cipher Algorithms
+============================
+
+Registering And Unregistering Transformation
+--------------------------------------------
+
+There are three distinct types of registration functions in the Crypto
+API. One is used to register a generic cryptographic transformation,
+while the other two are specific to HASH transformations and
+COMPRESSion. We will discuss the latter two in a separate chapter, here
+we will only look at the generic ones.
+
+Before discussing the register functions, the data structure to be
+filled with each, struct crypto_alg, must be considered -- see below
+for a description of this data structure.
+
+The generic registration functions can be found in
+include/linux/crypto.h and their definition can be seen below. The
+former function registers a single transformation, while the latter
+works on an array of transformation descriptions. The latter is useful
+when registering transformations in bulk, for example when a driver
+implements multiple transformations.
+
+::
+
+       int crypto_register_alg(struct crypto_alg *alg);
+       int crypto_register_algs(struct crypto_alg *algs, int count);
+
+
+The counterparts to those functions are listed below.
+
+::
+
+       int crypto_unregister_alg(struct crypto_alg *alg);
+       int crypto_unregister_algs(struct crypto_alg *algs, int count);
+
+
+Notice that both registration and unregistration functions do return a
+value, so make sure to handle errors. A return code of zero implies
+success. Any return code < 0 implies an error.
+
+The bulk registration/unregistration functions register/unregister each
+transformation in the given array of length count. They handle errors as
+follows:
+
+-  crypto_register_algs() succeeds if and only if it successfully
+   registers all the given transformations. If an error occurs partway
+   through, then it rolls back successful registrations before returning
+   the error code. Note that if a driver needs to handle registration
+   errors for individual transformations, then it will need to use the
+   non-bulk function crypto_register_alg() instead.
+
+-  crypto_unregister_algs() tries to unregister all the given
+   transformations, continuing on error. It logs errors and always
+   returns zero.
+
+Single-Block Symmetric Ciphers [CIPHER]
+---------------------------------------
+
+Example of transformations: aes, arc4, ...
+
+This section describes the simplest of all transformation
+implementations, that being the CIPHER type used for symmetric ciphers.
+The CIPHER type is used for transformations which operate on exactly one
+block at a time and there are no dependencies between blocks at all.
+
+Registration specifics
+~~~~~~~~~~~~~~~~~~~~~~
+
+The registration of [CIPHER] algorithm is specific in that struct
+crypto_alg field .cra_type is empty. The .cra_u.cipher has to be
+filled in with proper callbacks to implement this transformation.
+
+See struct cipher_alg below.
+
+Cipher Definition With struct cipher_alg
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Struct cipher_alg defines a single block cipher.
+
+Here are schematics of how these functions are called when operated from
+other part of the kernel. Note that the .cia_setkey() call might happen
+before or after any of these schematics happen, but must not happen
+during any of these are in-flight.
+
+::
+
+             KEY ---.    PLAINTEXT ---.
+                    v                 v
+              .cia_setkey() -> .cia_encrypt()
+                                      |
+                                      '-----> CIPHERTEXT
+
+
+Please note that a pattern where .cia_setkey() is called multiple times
+is also valid:
+
+::
+
+
+      KEY1 --.    PLAINTEXT1 --.         KEY2 --.    PLAINTEXT2 --.
+             v                 v                v                 v
+       .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt()
+                               |                                  |
+                               '---> CIPHERTEXT1                  '---> CIPHERTEXT2
+
+
+Multi-Block Ciphers
+-------------------
+
+Example of transformations: cbc(aes), ecb(arc4), ...
+
+This section describes the multi-block cipher transformation
+implementations. The multi-block ciphers are used for transformations
+which operate on scatterlists of data supplied to the transformation
+functions. They output the result into a scatterlist of data as well.
+
+Registration Specifics
+~~~~~~~~~~~~~~~~~~~~~~
+
+The registration of multi-block cipher algorithms is one of the most
+standard procedures throughout the crypto API.
+
+Note, if a cipher implementation requires a proper alignment of data,
+the caller should use the functions of crypto_skcipher_alignmask() to
+identify a memory alignment mask. The kernel crypto API is able to
+process requests that are unaligned. This implies, however, additional
+overhead as the kernel crypto API needs to perform the realignment of
+the data which may imply moving of data.
+
+Cipher Definition With struct blkcipher_alg and ablkcipher_alg
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Struct blkcipher_alg defines a synchronous block cipher whereas struct
+ablkcipher_alg defines an asynchronous block cipher.
+
+Please refer to the single block cipher description for schematics of
+the block cipher usage.
+
+Specifics Of Asynchronous Multi-Block Cipher
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are a couple of specifics to the asynchronous interface.
+
+First of all, some of the drivers will want to use the Generic
+ScatterWalk in case the hardware needs to be fed separate chunks of the
+scatterlist which contains the plaintext and will contain the
+ciphertext. Please refer to the ScatterWalk interface offered by the
+Linux kernel scatter / gather list implementation.
+
+Hashing [HASH]
+--------------
+
+Example of transformations: crc32, md5, sha1, sha256,...
+
+Registering And Unregistering The Transformation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are multiple ways to register a HASH transformation, depending on
+whether the transformation is synchronous [SHASH] or asynchronous
+[AHASH] and the amount of HASH transformations we are registering. You
+can find the prototypes defined in include/crypto/internal/hash.h:
+
+::
+
+       int crypto_register_ahash(struct ahash_alg *alg);
+
+       int crypto_register_shash(struct shash_alg *alg);
+       int crypto_register_shashes(struct shash_alg *algs, int count);
+
+
+The respective counterparts for unregistering the HASH transformation
+are as follows:
+
+::
+
+       int crypto_unregister_ahash(struct ahash_alg *alg);
+
+       int crypto_unregister_shash(struct shash_alg *alg);
+       int crypto_unregister_shashes(struct shash_alg *algs, int count);
+
+
+Cipher Definition With struct shash_alg and ahash_alg
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here are schematics of how these functions are called when operated from
+other part of the kernel. Note that the .setkey() call might happen
+before or after any of these schematics happen, but must not happen
+during any of these are in-flight. Please note that calling .init()
+followed immediately by .finish() is also a perfectly valid
+transformation.
+
+::
+
+       I)   DATA -----------.
+                            v
+             .init() -> .update() -> .final()      ! .update() might not be called
+                         ^    |         |            at all in this scenario.
+                         '----'         '---> HASH
+
+       II)  DATA -----------.-----------.
+                            v           v
+             .init() -> .update() -> .finup()      ! .update() may not be called
+                         ^    |         |            at all in this scenario.
+                         '----'         '---> HASH
+
+       III) DATA -----------.
+                            v
+                        .digest()                  ! The entire process is handled
+                            |                        by the .digest() call.
+                            '---------------> HASH
+
+
+Here is a schematic of how the .export()/.import() functions are called
+when used from another part of the kernel.
+
+::
+
+       KEY--.                 DATA--.
+            v                       v                  ! .update() may not be called
+        .setkey() -> .init() -> .update() -> .export()   at all in this scenario.
+                                 ^     |         |
+                                 '-----'         '--> PARTIAL_HASH
+
+       ----------- other transformations happen here -----------
+
+       PARTIAL_HASH--.   DATA1--.
+                     v          v
+                 .import -> .update() -> .final()     ! .update() may not be called
+                             ^    |         |           at all in this scenario.
+                             '----'         '--> HASH1
+
+       PARTIAL_HASH--.   DATA2-.
+                     v         v
+                 .import -> .finup()
+                               |
+                               '---------------> HASH2
+
+
+Specifics Of Asynchronous HASH Transformation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Some of the drivers will want to use the Generic ScatterWalk in case the
+implementation needs to be fed separate chunks of the scatterlist which
+contains the input data. The buffer containing the resulting hash will
+always be properly aligned to .cra_alignmask so there is no need to
+worry about this.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/index.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/index.rst
--- linux-libre-4.9-gnu/Documentation/crypto/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,24 @@
+=======================
+Linux Kernel Crypto API
+=======================
+
+:Author: Stephan Mueller
+:Author: Marek Vasut
+
+This documentation outlines the Linux kernel crypto API with its
+concepts, details about developing cipher implementations, employment of the API
+for cryptographic use cases, as well as programming examples.
+
+.. class:: toc-title
+
+	   Table of contents
+
+.. toctree::
+   :maxdepth: 2
+
+   intro
+   architecture
+   devel-algos
+   userspace-if
+   api
+   api-samples
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/intro.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/intro.rst
--- linux-libre-4.9-gnu/Documentation/crypto/intro.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/intro.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,74 @@
+Kernel Crypto API Interface Specification
+=========================================
+
+Introduction
+------------
+
+The kernel crypto API offers a rich set of cryptographic ciphers as well
+as other data transformation mechanisms and methods to invoke these.
+This document contains a description of the API and provides example
+code.
+
+To understand and properly use the kernel crypto API a brief explanation
+of its structure is given. Based on the architecture, the API can be
+separated into different components. Following the architecture
+specification, hints to developers of ciphers are provided. Pointers to
+the API function call documentation are given at the end.
+
+The kernel crypto API refers to all algorithms as "transformations".
+Therefore, a cipher handle variable usually has the name "tfm". Besides
+cryptographic operations, the kernel crypto API also knows compression
+transformations and handles them the same way as ciphers.
+
+The kernel crypto API serves the following entity types:
+
+-  consumers requesting cryptographic services
+
+-  data transformation implementations (typically ciphers) that can be
+   called by consumers using the kernel crypto API
+
+This specification is intended for consumers of the kernel crypto API as
+well as for developers implementing ciphers. This API specification,
+however, does not discuss all API calls available to data transformation
+implementations (i.e. implementations of ciphers and other
+transformations (such as CRC or even compression algorithms) that can
+register with the kernel crypto API).
+
+Note: The terms "transformation" and cipher algorithm are used
+interchangeably.
+
+Terminology
+-----------
+
+The transformation implementation is an actual code or interface to
+hardware which implements a certain transformation with precisely
+defined behavior.
+
+The transformation object (TFM) is an instance of a transformation
+implementation. There can be multiple transformation objects associated
+with a single transformation implementation. Each of those
+transformation objects is held by a crypto API consumer or another
+transformation. Transformation object is allocated when a crypto API
+consumer requests a transformation implementation. The consumer is then
+provided with a structure, which contains a transformation object (TFM).
+
+The structure that contains transformation objects may also be referred
+to as a "cipher handle". Such a cipher handle is always subject to the
+following phases that are reflected in the API calls applicable to such
+a cipher handle:
+
+1. Initialization of a cipher handle.
+
+2. Execution of all intended cipher operations applicable for the handle
+   where the cipher handle must be furnished to every API call.
+
+3. Destruction of a cipher handle.
+
+When using the initialization API calls, a cipher handle is created and
+returned to the consumer. Therefore, please refer to all initialization
+API calls that refer to the data structure type a consumer is expected
+to receive and subsequently to use. The initialization API calls have
+all the same naming conventions of crypto_alloc\*.
+
+The transformation context is private data associated with the
+transformation object.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/crypto/userspace-if.rst linux-libre-4.10-rc8-gnu/Documentation/crypto/userspace-if.rst
--- linux-libre-4.9-gnu/Documentation/crypto/userspace-if.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/crypto/userspace-if.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,387 @@
+User Space Interface
+====================
+
+Introduction
+------------
+
+The concepts of the kernel crypto API visible to kernel space is fully
+applicable to the user space interface as well. Therefore, the kernel
+crypto API high level discussion for the in-kernel use cases applies
+here as well.
+
+The major difference, however, is that user space can only act as a
+consumer and never as a provider of a transformation or cipher
+algorithm.
+
+The following covers the user space interface exported by the kernel
+crypto API. A working example of this description is libkcapi that can
+be obtained from [1]. That library can be used by user space
+applications that require cryptographic services from the kernel.
+
+Some details of the in-kernel kernel crypto API aspects do not apply to
+user space, however. This includes the difference between synchronous
+and asynchronous invocations. The user space API call is fully
+synchronous.
+
+[1] http://www.chronox.de/libkcapi.html
+
+User Space API General Remarks
+------------------------------
+
+The kernel crypto API is accessible from user space. Currently, the
+following ciphers are accessible:
+
+-  Message digest including keyed message digest (HMAC, CMAC)
+
+-  Symmetric ciphers
+
+-  AEAD ciphers
+
+-  Random Number Generators
+
+The interface is provided via socket type using the type AF_ALG. In
+addition, the setsockopt option type is SOL_ALG. In case the user space
+header files do not export these flags yet, use the following macros:
+
+::
+
+    #ifndef AF_ALG
+    #define AF_ALG 38
+    #endif
+    #ifndef SOL_ALG
+    #define SOL_ALG 279
+    #endif
+
+
+A cipher is accessed with the same name as done for the in-kernel API
+calls. This includes the generic vs. unique naming schema for ciphers as
+well as the enforcement of priorities for generic names.
+
+To interact with the kernel crypto API, a socket must be created by the
+user space application. User space invokes the cipher operation with the
+send()/write() system call family. The result of the cipher operation is
+obtained with the read()/recv() system call family.
+
+The following API calls assume that the socket descriptor is already
+opened by the user space application and discusses only the kernel
+crypto API specific invocations.
+
+To initialize the socket interface, the following sequence has to be
+performed by the consumer:
+
+1. Create a socket of type AF_ALG with the struct sockaddr_alg
+   parameter specified below for the different cipher types.
+
+2. Invoke bind with the socket descriptor
+
+3. Invoke accept with the socket descriptor. The accept system call
+   returns a new file descriptor that is to be used to interact with the
+   particular cipher instance. When invoking send/write or recv/read
+   system calls to send data to the kernel or obtain data from the
+   kernel, the file descriptor returned by accept must be used.
+
+In-place Cipher operation
+-------------------------
+
+Just like the in-kernel operation of the kernel crypto API, the user
+space interface allows the cipher operation in-place. That means that
+the input buffer used for the send/write system call and the output
+buffer used by the read/recv system call may be one and the same. This
+is of particular interest for symmetric cipher operations where a
+copying of the output data to its final destination can be avoided.
+
+If a consumer on the other hand wants to maintain the plaintext and the
+ciphertext in different memory locations, all a consumer needs to do is
+to provide different memory pointers for the encryption and decryption
+operation.
+
+Message Digest API
+------------------
+
+The message digest type to be used for the cipher operation is selected
+when invoking the bind syscall. bind requires the caller to provide a
+filled struct sockaddr data structure. This data structure must be
+filled as follows:
+
+::
+
+    struct sockaddr_alg sa = {
+        .salg_family = AF_ALG,
+        .salg_type = "hash", /* this selects the hash logic in the kernel */
+        .salg_name = "sha1" /* this is the cipher name */
+    };
+
+
+The salg_type value "hash" applies to message digests and keyed message
+digests. Though, a keyed message digest is referenced by the appropriate
+salg_name. Please see below for the setsockopt interface that explains
+how the key can be set for a keyed message digest.
+
+Using the send() system call, the application provides the data that
+should be processed with the message digest. The send system call allows
+the following flags to be specified:
+
+-  MSG_MORE: If this flag is set, the send system call acts like a
+   message digest update function where the final hash is not yet
+   calculated. If the flag is not set, the send system call calculates
+   the final message digest immediately.
+
+With the recv() system call, the application can read the message digest
+from the kernel crypto API. If the buffer is too small for the message
+digest, the flag MSG_TRUNC is set by the kernel.
+
+In order to set a message digest key, the calling application must use
+the setsockopt() option of ALG_SET_KEY. If the key is not set the HMAC
+operation is performed without the initial HMAC state change caused by
+the key.
+
+Symmetric Cipher API
+--------------------
+
+The operation is very similar to the message digest discussion. During
+initialization, the struct sockaddr data structure must be filled as
+follows:
+
+::
+
+    struct sockaddr_alg sa = {
+        .salg_family = AF_ALG,
+        .salg_type = "skcipher", /* this selects the symmetric cipher */
+        .salg_name = "cbc(aes)" /* this is the cipher name */
+    };
+
+
+Before data can be sent to the kernel using the write/send system call
+family, the consumer must set the key. The key setting is described with
+the setsockopt invocation below.
+
+Using the sendmsg() system call, the application provides the data that
+should be processed for encryption or decryption. In addition, the IV is
+specified with the data structure provided by the sendmsg() system call.
+
+The sendmsg system call parameter of struct msghdr is embedded into the
+struct cmsghdr data structure. See recv(2) and cmsg(3) for more
+information on how the cmsghdr data structure is used together with the
+send/recv system call family. That cmsghdr data structure holds the
+following information specified with a separate header instances:
+
+-  specification of the cipher operation type with one of these flags:
+
+   -  ALG_OP_ENCRYPT - encryption of data
+
+   -  ALG_OP_DECRYPT - decryption of data
+
+-  specification of the IV information marked with the flag ALG_SET_IV
+
+The send system call family allows the following flag to be specified:
+
+-  MSG_MORE: If this flag is set, the send system call acts like a
+   cipher update function where more input data is expected with a
+   subsequent invocation of the send system call.
+
+Note: The kernel reports -EINVAL for any unexpected data. The caller
+must make sure that all data matches the constraints given in
+/proc/crypto for the selected cipher.
+
+With the recv() system call, the application can read the result of the
+cipher operation from the kernel crypto API. The output buffer must be
+at least as large as to hold all blocks of the encrypted or decrypted
+data. If the output data size is smaller, only as many blocks are
+returned that fit into that output buffer size.
+
+AEAD Cipher API
+---------------
+
+The operation is very similar to the symmetric cipher discussion. During
+initialization, the struct sockaddr data structure must be filled as
+follows:
+
+::
+
+    struct sockaddr_alg sa = {
+        .salg_family = AF_ALG,
+        .salg_type = "aead", /* this selects the symmetric cipher */
+        .salg_name = "gcm(aes)" /* this is the cipher name */
+    };
+
+
+Before data can be sent to the kernel using the write/send system call
+family, the consumer must set the key. The key setting is described with
+the setsockopt invocation below.
+
+In addition, before data can be sent to the kernel using the write/send
+system call family, the consumer must set the authentication tag size.
+To set the authentication tag size, the caller must use the setsockopt
+invocation described below.
+
+Using the sendmsg() system call, the application provides the data that
+should be processed for encryption or decryption. In addition, the IV is
+specified with the data structure provided by the sendmsg() system call.
+
+The sendmsg system call parameter of struct msghdr is embedded into the
+struct cmsghdr data structure. See recv(2) and cmsg(3) for more
+information on how the cmsghdr data structure is used together with the
+send/recv system call family. That cmsghdr data structure holds the
+following information specified with a separate header instances:
+
+-  specification of the cipher operation type with one of these flags:
+
+   -  ALG_OP_ENCRYPT - encryption of data
+
+   -  ALG_OP_DECRYPT - decryption of data
+
+-  specification of the IV information marked with the flag ALG_SET_IV
+
+-  specification of the associated authentication data (AAD) with the
+   flag ALG_SET_AEAD_ASSOCLEN. The AAD is sent to the kernel together
+   with the plaintext / ciphertext. See below for the memory structure.
+
+The send system call family allows the following flag to be specified:
+
+-  MSG_MORE: If this flag is set, the send system call acts like a
+   cipher update function where more input data is expected with a
+   subsequent invocation of the send system call.
+
+Note: The kernel reports -EINVAL for any unexpected data. The caller
+must make sure that all data matches the constraints given in
+/proc/crypto for the selected cipher.
+
+With the recv() system call, the application can read the result of the
+cipher operation from the kernel crypto API. The output buffer must be
+at least as large as defined with the memory structure below. If the
+output data size is smaller, the cipher operation is not performed.
+
+The authenticated decryption operation may indicate an integrity error.
+Such breach in integrity is marked with the -EBADMSG error code.
+
+AEAD Memory Structure
+~~~~~~~~~~~~~~~~~~~~~
+
+The AEAD cipher operates with the following information that is
+communicated between user and kernel space as one data stream:
+
+-  plaintext or ciphertext
+
+-  associated authentication data (AAD)
+
+-  authentication tag
+
+The sizes of the AAD and the authentication tag are provided with the
+sendmsg and setsockopt calls (see there). As the kernel knows the size
+of the entire data stream, the kernel is now able to calculate the right
+offsets of the data components in the data stream.
+
+The user space caller must arrange the aforementioned information in the
+following order:
+
+-  AEAD encryption input: AAD \|\| plaintext
+
+-  AEAD decryption input: AAD \|\| ciphertext \|\| authentication tag
+
+The output buffer the user space caller provides must be at least as
+large to hold the following data:
+
+-  AEAD encryption output: ciphertext \|\| authentication tag
+
+-  AEAD decryption output: plaintext
+
+Random Number Generator API
+---------------------------
+
+Again, the operation is very similar to the other APIs. During
+initialization, the struct sockaddr data structure must be filled as
+follows:
+
+::
+
+    struct sockaddr_alg sa = {
+        .salg_family = AF_ALG,
+        .salg_type = "rng", /* this selects the symmetric cipher */
+        .salg_name = "drbg_nopr_sha256" /* this is the cipher name */
+    };
+
+
+Depending on the RNG type, the RNG must be seeded. The seed is provided
+using the setsockopt interface to set the key. For example, the
+ansi_cprng requires a seed. The DRBGs do not require a seed, but may be
+seeded.
+
+Using the read()/recvmsg() system calls, random numbers can be obtained.
+The kernel generates at most 128 bytes in one call. If user space
+requires more data, multiple calls to read()/recvmsg() must be made.
+
+WARNING: The user space caller may invoke the initially mentioned accept
+system call multiple times. In this case, the returned file descriptors
+have the same state.
+
+Zero-Copy Interface
+-------------------
+
+In addition to the send/write/read/recv system call family, the AF_ALG
+interface can be accessed with the zero-copy interface of
+splice/vmsplice. As the name indicates, the kernel tries to avoid a copy
+operation into kernel space.
+
+The zero-copy operation requires data to be aligned at the page
+boundary. Non-aligned data can be used as well, but may require more
+operations of the kernel which would defeat the speed gains obtained
+from the zero-copy interface.
+
+The system-interent limit for the size of one zero-copy operation is 16
+pages. If more data is to be sent to AF_ALG, user space must slice the
+input into segments with a maximum size of 16 pages.
+
+Zero-copy can be used with the following code example (a complete
+working example is provided with libkcapi):
+
+::
+
+    int pipes[2];
+
+    pipe(pipes);
+    /* input data in iov */
+    vmsplice(pipes[1], iov, iovlen, SPLICE_F_GIFT);
+    /* opfd is the file descriptor returned from accept() system call */
+    splice(pipes[0], NULL, opfd, NULL, ret, 0);
+    read(opfd, out, outlen);
+
+
+Setsockopt Interface
+--------------------
+
+In addition to the read/recv and send/write system call handling to send
+and retrieve data subject to the cipher operation, a consumer also needs
+to set the additional information for the cipher operation. This
+additional information is set using the setsockopt system call that must
+be invoked with the file descriptor of the open cipher (i.e. the file
+descriptor returned by the accept system call).
+
+Each setsockopt invocation must use the level SOL_ALG.
+
+The setsockopt interface allows setting the following data using the
+mentioned optname:
+
+-  ALG_SET_KEY -- Setting the key. Key setting is applicable to:
+
+   -  the skcipher cipher type (symmetric ciphers)
+
+   -  the hash cipher type (keyed message digests)
+
+   -  the AEAD cipher type
+
+   -  the RNG cipher type to provide the seed
+
+-  ALG_SET_AEAD_AUTHSIZE -- Setting the authentication tag size for
+   AEAD ciphers. For a encryption operation, the authentication tag of
+   the given size will be generated. For a decryption operation, the
+   provided ciphertext is assumed to contain an authentication tag of
+   the given size (see section about AEAD memory layout below).
+
+User space API example
+----------------------
+
+Please see [1] for libkcapi which provides an easy-to-use wrapper around
+the aforementioned Netlink kernel interface. [1] also contains a test
+application that invokes all libkcapi API calls.
+
+[1] http://www.chronox.de/libkcapi.html
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/1.Intro.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/1.Intro.rst
--- linux-libre-4.9-gnu/Documentation/development-process/1.Intro.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/1.Intro.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,266 +0,0 @@
-Introdution
-===========
-
-Executive summary
------------------
-
-The rest of this section covers the scope of the kernel development process
-and the kinds of frustrations that developers and their employers can
-encounter there.  There are a great many reasons why kernel code should be
-merged into the official ("mainline") kernel, including automatic
-availability to users, community support in many forms, and the ability to
-influence the direction of kernel development.  Code contributed to the
-Linux kernel must be made available under a GPL-compatible license.
-
-:ref:`development_process` introduces the development process, the kernel
-release cycle, and the mechanics of the merge window.  The various phases in
-the patch development, review, and merging cycle are covered.  There is some
-discussion of tools and mailing lists.  Developers wanting to get started
-with kernel development are encouraged to track down and fix bugs as an
-initial exercise.
-
-:ref:`development_early_stage` covers early-stage project planning, with an
-emphasis on involving the development community as soon as possible.
-
-:ref:`development_coding` is about the coding process; several pitfalls which
-have been encountered by other developers are discussed.  Some requirements for
-patches are covered, and there is an introduction to some of the tools
-which can help to ensure that kernel patches are correct.
-
-:ref:`development_posting` talks about the process of posting patches for
-review. To be taken seriously by the development community, patches must be
-properly formatted and described, and they must be sent to the right place.
-Following the advice in this section should help to ensure the best
-possible reception for your work.
-
-:ref:`development_followthrough` covers what happens after posting patches; the
-job is far from done at that point.  Working with reviewers is a crucial part
-of the development process; this section offers a number of tips on how to
-avoid problems at this important stage.  Developers are cautioned against
-assuming that the job is done when a patch is merged into the mainline.
-
-:ref:`development_advancedtopics` introduces a couple of "advanced" topics:
-managing patches with git and reviewing patches posted by others.
-
-:ref:`development_conclusion` concludes the document with pointers to sources
-for more information on kernel development.
-
-What this document is about
----------------------------
-
-The Linux kernel, at over 8 million lines of code and well over 1000
-contributors to each release, is one of the largest and most active free
-software projects in existence.  Since its humble beginning in 1991, this
-kernel has evolved into a best-of-breed operating system component which
-runs on pocket-sized digital music players, desktop PCs, the largest
-supercomputers in existence, and all types of systems in between.  It is a
-robust, efficient, and scalable solution for almost any situation.
-
-With the growth of Linux has come an increase in the number of developers
-(and companies) wishing to participate in its development.  Hardware
-vendors want to ensure that Linux supports their products well, making
-those products attractive to Linux users.  Embedded systems vendors, who
-use Linux as a component in an integrated product, want Linux to be as
-capable and well-suited to the task at hand as possible.  Distributors and
-other software vendors who base their products on Linux have a clear
-interest in the capabilities, performance, and reliability of the Linux
-kernel.  And end users, too, will often wish to change Linux to make it
-better suit their needs.
-
-One of the most compelling features of Linux is that it is accessible to
-these developers; anybody with the requisite skills can improve Linux and
-influence the direction of its development.  Proprietary products cannot
-offer this kind of openness, which is a characteristic of the free software
-process.  But, if anything, the kernel is even more open than most other
-free software projects.  A typical three-month kernel development cycle can
-involve over 1000 developers working for more than 100 different companies
-(or for no company at all).
-
-Working with the kernel development community is not especially hard.  But,
-that notwithstanding, many potential contributors have experienced
-difficulties when trying to do kernel work.  The kernel community has
-evolved its own distinct ways of operating which allow it to function
-smoothly (and produce a high-quality product) in an environment where
-thousands of lines of code are being changed every day.  So it is not
-surprising that Linux kernel development process differs greatly from
-proprietary development methods.
-
-The kernel's development process may come across as strange and
-intimidating to new developers, but there are good reasons and solid
-experience behind it.  A developer who does not understand the kernel
-community's ways (or, worse, who tries to flout or circumvent them) will
-have a frustrating experience in store.  The development community, while
-being helpful to those who are trying to learn, has little time for those
-who will not listen or who do not care about the development process.
-
-It is hoped that those who read this document will be able to avoid that
-frustrating experience.  There is a lot of material here, but the effort
-involved in reading it will be repaid in short order.  The development
-community is always in need of developers who will help to make the kernel
-better; the following text should help you - or those who work for you -
-join our community.
-
-Credits
--------
-
-This document was written by Jonathan Corbet, corbet@lwn.net.  It has been
-improved by comments from Johannes Berg, James Berry, Alex Chiang, Roland
-Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh,
-Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata, and
-Jochen Voß.
-
-This work was supported by the Linux Foundation; thanks especially to
-Amanda McPherson, who saw the value of this effort and made it all happen.
-
-The importance of getting code into the mainline
-------------------------------------------------
-
-Some companies and developers occasionally wonder why they should bother
-learning how to work with the kernel community and get their code into the
-mainline kernel (the "mainline" being the kernel maintained by Linus
-Torvalds and used as a base by Linux distributors).  In the short term,
-contributing code can look like an avoidable expense; it seems easier to
-just keep the code separate and support users directly.  The truth of the
-matter is that keeping code separate ("out of tree") is a false economy.
-
-As a way of illustrating the costs of out-of-tree code, here are a few
-relevant aspects of the kernel development process; most of these will be
-discussed in greater detail later in this document.  Consider:
-
-- Code which has been merged into the mainline kernel is available to all
-  Linux users.  It will automatically be present on all distributions which
-  enable it.  There is no need for driver disks, downloads, or the hassles
-  of supporting multiple versions of multiple distributions; it all just
-  works, for the developer and for the user.  Incorporation into the
-  mainline solves a large number of distribution and support problems.
-
-- While kernel developers strive to maintain a stable interface to user
-  space, the internal kernel API is in constant flux.  The lack of a stable
-  internal interface is a deliberate design decision; it allows fundamental
-  improvements to be made at any time and results in higher-quality code.
-  But one result of that policy is that any out-of-tree code requires
-  constant upkeep if it is to work with new kernels.  Maintaining
-  out-of-tree code requires significant amounts of work just to keep that
-  code working.
-
-  Code which is in the mainline, instead, does not require this work as the
-  result of a simple rule requiring any developer who makes an API change
-  to also fix any code that breaks as the result of that change.  So code
-  which has been merged into the mainline has significantly lower
-  maintenance costs.
-
-- Beyond that, code which is in the kernel will often be improved by other
-  developers.  Surprising results can come from empowering your user
-  community and customers to improve your product.
-
-- Kernel code is subjected to review, both before and after merging into
-  the mainline.  No matter how strong the original developer's skills are,
-  this review process invariably finds ways in which the code can be
-  improved.  Often review finds severe bugs and security problems.  This is
-  especially true for code which has been developed in a closed
-  environment; such code benefits strongly from review by outside
-  developers.  Out-of-tree code is lower-quality code.
-
-- Participation in the development process is your way to influence the
-  direction of kernel development.  Users who complain from the sidelines
-  are heard, but active developers have a stronger voice - and the ability
-  to implement changes which make the kernel work better for their needs.
-
-- When code is maintained separately, the possibility that a third party
-  will contribute a different implementation of a similar feature always
-  exists.  Should that happen, getting your code merged will become much
-  harder - to the point of impossibility.  Then you will be faced with the
-  unpleasant alternatives of either (1) maintaining a nonstandard feature
-  out of tree indefinitely, or (2) abandoning your code and migrating your
-  users over to the in-tree version.
-
-- Contribution of code is the fundamental action which makes the whole
-  process work.  By contributing your code you can add new functionality to
-  the kernel and provide capabilities and examples which are of use to
-  other kernel developers.  If you have developed code for Linux (or are
-  thinking about doing so), you clearly have an interest in the continued
-  success of this platform; contributing code is one of the best ways to
-  help ensure that success.
-
-All of the reasoning above applies to any out-of-tree kernel code,
-including code which is distributed in proprietary, binary-only form.
-There are, however, additional factors which should be taken into account
-before considering any sort of binary-only kernel code distribution.  These
-include:
-
-- The legal issues around the distribution of proprietary kernel modules
-  are cloudy at best; quite a few kernel copyright holders believe that
-  most binary-only modules are derived products of the kernel and that, as
-  a result, their distribution is a violation of the GNU General Public
-  license (about which more will be said below).  Your author is not a
-  lawyer, and nothing in this document can possibly be considered to be
-  legal advice.  The true legal status of closed-source modules can only be
-  determined by the courts.  But the uncertainty which haunts those modules
-  is there regardless.
-
-- Binary modules greatly increase the difficulty of debugging kernel
-  problems, to the point that most kernel developers will not even try.  So
-  the distribution of binary-only modules will make it harder for your
-  users to get support from the community.
-
-- Support is also harder for distributors of binary-only modules, who must
-  provide a version of the module for every distribution and every kernel
-  version they wish to support.  Dozens of builds of a single module can
-  be required to provide reasonably comprehensive coverage, and your users
-  will have to upgrade your module separately every time they upgrade their
-  kernel.
-
-- Everything that was said above about code review applies doubly to
-  closed-source code.  Since this code is not available at all, it cannot
-  have been reviewed by the community and will, beyond doubt, have serious
-  problems.
-
-Makers of embedded systems, in particular, may be tempted to disregard much
-of what has been said in this section in the belief that they are shipping
-a self-contained product which uses a frozen kernel version and requires no
-more development after its release.  This argument misses the value of
-widespread code review and the value of allowing your users to add
-capabilities to your product.  But these products, too, have a limited
-commercial life, after which a new version must be released.  At that
-point, vendors whose code is in the mainline and well maintained will be
-much better positioned to get the new product ready for market quickly.
-
-Licensing
----------
-
-Code is contributed to the Linux kernel under a number of licenses, but all
-code must be compatible with version 2 of the GNU General Public License
-(GPLv2), which is the license covering the kernel distribution as a whole.
-In practice, that means that all code contributions are covered either by
-GPLv2 (with, optionally, language allowing distribution under later
-versions of the GPL) or the three-clause BSD license.  Any contributions
-which are not covered by a compatible license will not be accepted into the
-kernel.
-
-Copyright assignments are not required (or requested) for code contributed
-to the kernel.  All code merged into the mainline kernel retains its
-original ownership; as a result, the kernel now has thousands of owners.
-
-One implication of this ownership structure is that any attempt to change
-the licensing of the kernel is doomed to almost certain failure.  There are
-few practical scenarios where the agreement of all copyright holders could
-be obtained (or their code removed from the kernel).  So, in particular,
-there is no prospect of a migration to version 3 of the GPL in the
-foreseeable future.
-
-It is imperative that all code contributed to the kernel be legitimately
-free software.  For that reason, code from anonymous (or pseudonymous)
-contributors will not be accepted.  All contributors are required to "sign
-off" on their code, stating that the code can be distributed with the
-kernel under the GPL.  Code which has not been licensed as free software by
-its owner, or which risks creating copyright-related problems for the
-kernel (such as code which derives from reverse-engineering efforts lacking
-proper safeguards) cannot be contributed.
-
-Questions about copyright-related issues are common on Linux development
-mailing lists.  Such questions will normally receive no shortage of
-answers, but one should bear in mind that the people answering those
-questions are not lawyers and cannot provide legal advice.  If you have
-legal questions relating to Linux source code, there is no substitute for
-talking with a lawyer who understands this field.  Relying on answers
-obtained on technical mailing lists is a risky affair.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/2.Process.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/2.Process.rst
--- linux-libre-4.9-gnu/Documentation/development-process/2.Process.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/2.Process.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,497 +0,0 @@
-.. _development_process:
-
-How the development process works
-=================================
-
-Linux kernel development in the early 1990's was a pretty loose affair,
-with relatively small numbers of users and developers involved.  With a
-user base in the millions and with some 2,000 developers involved over the
-course of one year, the kernel has since had to evolve a number of
-processes to keep development happening smoothly.  A solid understanding of
-how the process works is required in order to be an effective part of it.
-
-The big picture
----------------
-
-The kernel developers use a loosely time-based release process, with a new
-major kernel release happening every two or three months.  The recent
-release history looks like this:
-
-	======  =================
-	2.6.38	March 14, 2011
-	2.6.37	January 4, 2011
-	2.6.36	October 20, 2010
-	2.6.35	August 1, 2010
-	2.6.34	May 15, 2010
-	2.6.33	February 24, 2010
-	======  =================
-
-Every 2.6.x release is a major kernel release with new features, internal
-API changes, and more.  A typical 2.6 release can contain nearly 10,000
-changesets with changes to several hundred thousand lines of code.  2.6 is
-thus the leading edge of Linux kernel development; the kernel uses a
-rolling development model which is continually integrating major changes.
-
-A relatively straightforward discipline is followed with regard to the
-merging of patches for each release.  At the beginning of each development
-cycle, the "merge window" is said to be open.  At that time, code which is
-deemed to be sufficiently stable (and which is accepted by the development
-community) is merged into the mainline kernel.  The bulk of changes for a
-new development cycle (and all of the major changes) will be merged during
-this time, at a rate approaching 1,000 changes ("patches," or "changesets")
-per day.
-
-(As an aside, it is worth noting that the changes integrated during the
-merge window do not come out of thin air; they have been collected, tested,
-and staged ahead of time.  How that process works will be described in
-detail later on).
-
-The merge window lasts for approximately two weeks.  At the end of this
-time, Linus Torvalds will declare that the window is closed and release the
-first of the "rc" kernels.  For the kernel which is destined to be 2.6.40,
-for example, the release which happens at the end of the merge window will
-be called 2.6.40-rc1.  The -rc1 release is the signal that the time to
-merge new features has passed, and that the time to stabilize the next
-kernel has begun.
-
-Over the next six to ten weeks, only patches which fix problems should be
-submitted to the mainline.  On occasion a more significant change will be
-allowed, but such occasions are rare; developers who try to merge new
-features outside of the merge window tend to get an unfriendly reception.
-As a general rule, if you miss the merge window for a given feature, the
-best thing to do is to wait for the next development cycle.  (An occasional
-exception is made for drivers for previously-unsupported hardware; if they
-touch no in-tree code, they cannot cause regressions and should be safe to
-add at any time).
-
-As fixes make their way into the mainline, the patch rate will slow over
-time.  Linus releases new -rc kernels about once a week; a normal series
-will get up to somewhere between -rc6 and -rc9 before the kernel is
-considered to be sufficiently stable and the final 2.6.x release is made.
-At that point the whole process starts over again.
-
-As an example, here is how the 2.6.38 development cycle went (all dates in
-2011):
-
-	==============  ===============================
-	January 4	2.6.37 stable release
-	January 18	2.6.38-rc1, merge window closes
-	January 21	2.6.38-rc2
-	February 1	2.6.38-rc3
-	February 7	2.6.38-rc4
-	February 15	2.6.38-rc5
-	February 21	2.6.38-rc6
-	March 1		2.6.38-rc7
-	March 7		2.6.38-rc8
-	March 14	2.6.38 stable release
-	==============  ===============================
-
-How do the developers decide when to close the development cycle and create
-the stable release?  The most significant metric used is the list of
-regressions from previous releases.  No bugs are welcome, but those which
-break systems which worked in the past are considered to be especially
-serious.  For this reason, patches which cause regressions are looked upon
-unfavorably and are quite likely to be reverted during the stabilization
-period.
-
-The developers' goal is to fix all known regressions before the stable
-release is made.  In the real world, this kind of perfection is hard to
-achieve; there are just too many variables in a project of this size.
-There comes a point where delaying the final release just makes the problem
-worse; the pile of changes waiting for the next merge window will grow
-larger, creating even more regressions the next time around.  So most 2.6.x
-kernels go out with a handful of known regressions though, hopefully, none
-of them are serious.
-
-Once a stable release is made, its ongoing maintenance is passed off to the
-"stable team," currently consisting of Greg Kroah-Hartman.  The stable team
-will release occasional updates to the stable release using the 2.6.x.y
-numbering scheme.  To be considered for an update release, a patch must (1)
-fix a significant bug, and (2) already be merged into the mainline for the
-next development kernel.  Kernels will typically receive stable updates for
-a little more than one development cycle past their initial release.  So,
-for example, the 2.6.36 kernel's history looked like:
-
-	==============  ===============================
-	October 10	2.6.36 stable release
-	November 22	2.6.36.1
-	December 9	2.6.36.2
-	January 7	2.6.36.3
-	February 17	2.6.36.4
-	==============  ===============================
-
-2.6.36.4 was the final stable update for the 2.6.36 release.
-
-Some kernels are designated "long term" kernels; they will receive support
-for a longer period.  As of this writing, the current long term kernels
-and their maintainers are:
-
-	======  ======================  ===========================
-	2.6.27	Willy Tarreau		(Deep-frozen stable kernel)
-	2.6.32	Greg Kroah-Hartman
-	2.6.35	Andi Kleen		(Embedded flag kernel)
-	======  ======================  ===========================
-
-The selection of a kernel for long-term support is purely a matter of a
-maintainer having the need and the time to maintain that release.  There
-are no known plans for long-term support for any specific upcoming
-release.
-
-
-The lifecycle of a patch
-------------------------
-
-Patches do not go directly from the developer's keyboard into the mainline
-kernel.  There is, instead, a somewhat involved (if somewhat informal)
-process designed to ensure that each patch is reviewed for quality and that
-each patch implements a change which is desirable to have in the mainline.
-This process can happen quickly for minor fixes, or, in the case of large
-and controversial changes, go on for years.  Much developer frustration
-comes from a lack of understanding of this process or from attempts to
-circumvent it.
-
-In the hopes of reducing that frustration, this document will describe how
-a patch gets into the kernel.  What follows below is an introduction which
-describes the process in a somewhat idealized way.  A much more detailed
-treatment will come in later sections.
-
-The stages that a patch goes through are, generally:
-
- - Design.  This is where the real requirements for the patch - and the way
-   those requirements will be met - are laid out.  Design work is often
-   done without involving the community, but it is better to do this work
-   in the open if at all possible; it can save a lot of time redesigning
-   things later.
-
- - Early review.  Patches are posted to the relevant mailing list, and
-   developers on that list reply with any comments they may have.  This
-   process should turn up any major problems with a patch if all goes
-   well.
-
- - Wider review.  When the patch is getting close to ready for mainline
-   inclusion, it should be accepted by a relevant subsystem maintainer -
-   though this acceptance is not a guarantee that the patch will make it
-   all the way to the mainline.  The patch will show up in the maintainer's
-   subsystem tree and into the -next trees (described below).  When the
-   process works, this step leads to more extensive review of the patch and
-   the discovery of any problems resulting from the integration of this
-   patch with work being done by others.
-
--  Please note that most maintainers also have day jobs, so merging
-   your patch may not be their highest priority.  If your patch is
-   getting feedback about changes that are needed, you should either
-   make those changes or justify why they should not be made.  If your
-   patch has no review complaints but is not being merged by its
-   appropriate subsystem or driver maintainer, you should be persistent
-   in updating the patch to the current kernel so that it applies cleanly
-   and keep sending it for review and merging.
-
- - Merging into the mainline.  Eventually, a successful patch will be
-   merged into the mainline repository managed by Linus Torvalds.  More
-   comments and/or problems may surface at this time; it is important that
-   the developer be responsive to these and fix any issues which arise.
-
- - Stable release.  The number of users potentially affected by the patch
-   is now large, so, once again, new problems may arise.
-
- - Long-term maintenance.  While it is certainly possible for a developer
-   to forget about code after merging it, that sort of behavior tends to
-   leave a poor impression in the development community.  Merging code
-   eliminates some of the maintenance burden, in that others will fix
-   problems caused by API changes.  But the original developer should
-   continue to take responsibility for the code if it is to remain useful
-   in the longer term.
-
-One of the largest mistakes made by kernel developers (or their employers)
-is to try to cut the process down to a single "merging into the mainline"
-step.  This approach invariably leads to frustration for everybody
-involved.
-
-How patches get into the Kernel
--------------------------------
-
-There is exactly one person who can merge patches into the mainline kernel
-repository: Linus Torvalds.  But, of the over 9,500 patches which went
-into the 2.6.38 kernel, only 112 (around 1.3%) were directly chosen by Linus
-himself.  The kernel project has long since grown to a size where no single
-developer could possibly inspect and select every patch unassisted.  The
-way the kernel developers have addressed this growth is through the use of
-a lieutenant system built around a chain of trust.
-
-The kernel code base is logically broken down into a set of subsystems:
-networking, specific architecture support, memory management, video
-devices, etc.  Most subsystems have a designated maintainer, a developer
-who has overall responsibility for the code within that subsystem.  These
-subsystem maintainers are the gatekeepers (in a loose way) for the portion
-of the kernel they manage; they are the ones who will (usually) accept a
-patch for inclusion into the mainline kernel.
-
-Subsystem maintainers each manage their own version of the kernel source
-tree, usually (but certainly not always) using the git source management
-tool.  Tools like git (and related tools like quilt or mercurial) allow
-maintainers to track a list of patches, including authorship information
-and other metadata.  At any given time, the maintainer can identify which
-patches in his or her repository are not found in the mainline.
-
-When the merge window opens, top-level maintainers will ask Linus to "pull"
-the patches they have selected for merging from their repositories.  If
-Linus agrees, the stream of patches will flow up into his repository,
-becoming part of the mainline kernel.  The amount of attention that Linus
-pays to specific patches received in a pull operation varies.  It is clear
-that, sometimes, he looks quite closely.  But, as a general rule, Linus
-trusts the subsystem maintainers to not send bad patches upstream.
-
-Subsystem maintainers, in turn, can pull patches from other maintainers.
-For example, the networking tree is built from patches which accumulated
-first in trees dedicated to network device drivers, wireless networking,
-etc.  This chain of repositories can be arbitrarily long, though it rarely
-exceeds two or three links.  Since each maintainer in the chain trusts
-those managing lower-level trees, this process is known as the "chain of
-trust."
-
-Clearly, in a system like this, getting patches into the kernel depends on
-finding the right maintainer.  Sending patches directly to Linus is not
-normally the right way to go.
-
-
-Next trees
-----------
-
-The chain of subsystem trees guides the flow of patches into the kernel,
-but it also raises an interesting question: what if somebody wants to look
-at all of the patches which are being prepared for the next merge window?
-Developers will be interested in what other changes are pending to see
-whether there are any conflicts to worry about; a patch which changes a
-core kernel function prototype, for example, will conflict with any other
-patches which use the older form of that function.  Reviewers and testers
-want access to the changes in their integrated form before all of those
-changes land in the mainline kernel.  One could pull changes from all of
-the interesting subsystem trees, but that would be a big and error-prone
-job.
-
-The answer comes in the form of -next trees, where subsystem trees are
-collected for testing and review.  The older of these trees, maintained by
-Andrew Morton, is called "-mm" (for memory management, which is how it got
-started).  The -mm tree integrates patches from a long list of subsystem
-trees; it also has some patches aimed at helping with debugging.
-
-Beyond that, -mm contains a significant collection of patches which have
-been selected by Andrew directly.  These patches may have been posted on a
-mailing list, or they may apply to a part of the kernel for which there is
-no designated subsystem tree.  As a result, -mm operates as a sort of
-subsystem tree of last resort; if there is no other obvious path for a
-patch into the mainline, it is likely to end up in -mm.  Miscellaneous
-patches which accumulate in -mm will eventually either be forwarded on to
-an appropriate subsystem tree or be sent directly to Linus.  In a typical
-development cycle, approximately 5-10% of the patches going into the
-mainline get there via -mm.
-
-The current -mm patch is available in the "mmotm" (-mm of the moment)
-directory at:
-
-	http://www.ozlabs.org/~akpm/mmotm/
-
-Use of the MMOTM tree is likely to be a frustrating experience, though;
-there is a definite chance that it will not even compile.
-
-The primary tree for next-cycle patch merging is linux-next, maintained by
-Stephen Rothwell.  The linux-next tree is, by design, a snapshot of what
-the mainline is expected to look like after the next merge window closes.
-Linux-next trees are announced on the linux-kernel and linux-next mailing
-lists when they are assembled; they can be downloaded from:
-
-	http://www.kernel.org/pub/linux/kernel/next/
-
-Linux-next has become an integral part of the kernel development process;
-all patches merged during a given merge window should really have found
-their way into linux-next some time before the merge window opens.
-
-
-Staging trees
--------------
-
-The kernel source tree contains the drivers/staging/ directory, where
-many sub-directories for drivers or filesystems that are on their way to
-being added to the kernel tree live.  They remain in drivers/staging while
-they still need more work; once complete, they can be moved into the
-kernel proper.  This is a way to keep track of drivers that aren't
-up to Linux kernel coding or quality standards, but people may want to use
-them and track development.
-
-Greg Kroah-Hartman currently maintains the staging tree.  Drivers that
-still need work are sent to him, with each driver having its own
-subdirectory in drivers/staging/.  Along with the driver source files, a
-TODO file should be present in the directory as well.  The TODO file lists
-the pending work that the driver needs for acceptance into the kernel
-proper, as well as a list of people that should be Cc'd for any patches to
-the driver.  Current rules require that drivers contributed to staging
-must, at a minimum, compile properly.
-
-Staging can be a relatively easy way to get new drivers into the mainline
-where, with luck, they will come to the attention of other developers and
-improve quickly.  Entry into staging is not the end of the story, though;
-code in staging which is not seeing regular progress will eventually be
-removed.  Distributors also tend to be relatively reluctant to enable
-staging drivers.  So staging is, at best, a stop on the way toward becoming
-a proper mainline driver.
-
-
-Tools
------
-
-As can be seen from the above text, the kernel development process depends
-heavily on the ability to herd collections of patches in various
-directions.  The whole thing would not work anywhere near as well as it
-does without suitably powerful tools.  Tutorials on how to use these tools
-are well beyond the scope of this document, but there is space for a few
-pointers.
-
-By far the dominant source code management system used by the kernel
-community is git.  Git is one of a number of distributed version control
-systems being developed in the free software community.  It is well tuned
-for kernel development, in that it performs quite well when dealing with
-large repositories and large numbers of patches.  It also has a reputation
-for being difficult to learn and use, though it has gotten better over
-time.  Some sort of familiarity with git is almost a requirement for kernel
-developers; even if they do not use it for their own work, they'll need git
-to keep up with what other developers (and the mainline) are doing.
-
-Git is now packaged by almost all Linux distributions.  There is a home
-page at:
-
-	http://git-scm.com/
-
-That page has pointers to documentation and tutorials.
-
-Among the kernel developers who do not use git, the most popular choice is
-almost certainly Mercurial:
-
-	http://www.selenic.com/mercurial/
-
-Mercurial shares many features with git, but it provides an interface which
-many find easier to use.
-
-The other tool worth knowing about is Quilt:
-
-	http://savannah.nongnu.org/projects/quilt/
-
-Quilt is a patch management system, rather than a source code management
-system.  It does not track history over time; it is, instead, oriented
-toward tracking a specific set of changes against an evolving code base.
-Some major subsystem maintainers use quilt to manage patches intended to go
-upstream.  For the management of certain kinds of trees (-mm, for example),
-quilt is the best tool for the job.
-
-
-Mailing lists
--------------
-
-A great deal of Linux kernel development work is done by way of mailing
-lists.  It is hard to be a fully-functioning member of the community
-without joining at least one list somewhere.  But Linux mailing lists also
-represent a potential hazard to developers, who risk getting buried under a
-load of electronic mail, running afoul of the conventions used on the Linux
-lists, or both.
-
-Most kernel mailing lists are run on vger.kernel.org; the master list can
-be found at:
-
-	http://vger.kernel.org/vger-lists.html
-
-There are lists hosted elsewhere, though; a number of them are at
-lists.redhat.com.
-
-The core mailing list for kernel development is, of course, linux-kernel.
-This list is an intimidating place to be; volume can reach 500 messages per
-day, the amount of noise is high, the conversation can be severely
-technical, and participants are not always concerned with showing a high
-degree of politeness.  But there is no other place where the kernel
-development community comes together as a whole; developers who avoid this
-list will miss important information.
-
-There are a few hints which can help with linux-kernel survival:
-
-- Have the list delivered to a separate folder, rather than your main
-  mailbox.  One must be able to ignore the stream for sustained periods of
-  time.
-
-- Do not try to follow every conversation - nobody else does.  It is
-  important to filter on both the topic of interest (though note that
-  long-running conversations can drift away from the original subject
-  without changing the email subject line) and the people who are
-  participating.
-
-- Do not feed the trolls.  If somebody is trying to stir up an angry
-  response, ignore them.
-
-- When responding to linux-kernel email (or that on other lists) preserve
-  the Cc: header for all involved.  In the absence of a strong reason (such
-  as an explicit request), you should never remove recipients.  Always make
-  sure that the person you are responding to is in the Cc: list.  This
-  convention also makes it unnecessary to explicitly ask to be copied on
-  replies to your postings.
-
-- Search the list archives (and the net as a whole) before asking
-  questions.  Some developers can get impatient with people who clearly
-  have not done their homework.
-
-- Avoid top-posting (the practice of putting your answer above the quoted
-  text you are responding to).  It makes your response harder to read and
-  makes a poor impression.
-
-- Ask on the correct mailing list.  Linux-kernel may be the general meeting
-  point, but it is not the best place to find developers from all
-  subsystems.
-
-The last point - finding the correct mailing list - is a common place for
-beginning developers to go wrong.  Somebody who asks a networking-related
-question on linux-kernel will almost certainly receive a polite suggestion
-to ask on the netdev list instead, as that is the list frequented by most
-networking developers.  Other lists exist for the SCSI, video4linux, IDE,
-filesystem, etc. subsystems.  The best place to look for mailing lists is
-in the MAINTAINERS file packaged with the kernel source.
-
-
-Getting started with Kernel development
----------------------------------------
-
-Questions about how to get started with the kernel development process are
-common - from both individuals and companies.  Equally common are missteps
-which make the beginning of the relationship harder than it has to be.
-
-Companies often look to hire well-known developers to get a development
-group started.  This can, in fact, be an effective technique.  But it also
-tends to be expensive and does not do much to grow the pool of experienced
-kernel developers.  It is possible to bring in-house developers up to speed
-on Linux kernel development, given the investment of a bit of time.  Taking
-this time can endow an employer with a group of developers who understand
-the kernel and the company both, and who can help to train others as well.
-Over the medium term, this is often the more profitable approach.
-
-Individual developers are often, understandably, at a loss for a place to
-start.  Beginning with a large project can be intimidating; one often wants
-to test the waters with something smaller first.  This is the point where
-some developers jump into the creation of patches fixing spelling errors or
-minor coding style issues.  Unfortunately, such patches create a level of
-noise which is distracting for the development community as a whole, so,
-increasingly, they are looked down upon.  New developers wishing to
-introduce themselves to the community will not get the sort of reception
-they wish for by these means.
-
-Andrew Morton gives this advice for aspiring kernel developers
-
-::
-
-	The #1 project for all kernel beginners should surely be "make sure
-	that the kernel runs perfectly at all times on all machines which
-	you can lay your hands on".  Usually the way to do this is to work
-	with others on getting things fixed up (this can require
-	persistence!) but that's fine - it's a part of kernel development.
-
-(http://lwn.net/Articles/283982/).
-
-In the absence of obvious problems to fix, developers are advised to look
-at the current lists of regressions and open bugs in general.  There is
-never any shortage of issues in need of fixing; by addressing these issues,
-developers will gain experience with the process while, at the same time,
-building respect with the rest of the development community.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/3.Early-stage.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/3.Early-stage.rst
--- linux-libre-4.9-gnu/Documentation/development-process/3.Early-stage.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/3.Early-stage.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-.. _development_early_stage:
-
-Early-stage planning
-====================
-
-When contemplating a Linux kernel development project, it can be tempting
-to jump right in and start coding.  As with any significant project,
-though, much of the groundwork for success is best laid before the first
-line of code is written.  Some time spent in early planning and
-communication can save far more time later on.
-
-
-Specifying the problem
-----------------------
-
-Like any engineering project, a successful kernel enhancement starts with a
-clear description of the problem to be solved.  In some cases, this step is
-easy: when a driver is needed for a specific piece of hardware, for
-example.  In others, though, it is tempting to confuse the real problem
-with the proposed solution, and that can lead to difficulties.
-
-Consider an example: some years ago, developers working with Linux audio
-sought a way to run applications without dropouts or other artifacts caused
-by excessive latency in the system.  The solution they arrived at was a
-kernel module intended to hook into the Linux Security Module (LSM)
-framework; this module could be configured to give specific applications
-access to the realtime scheduler.  This module was implemented and sent to
-the linux-kernel mailing list, where it immediately ran into problems.
-
-To the audio developers, this security module was sufficient to solve their
-immediate problem.  To the wider kernel community, though, it was seen as a
-misuse of the LSM framework (which is not intended to confer privileges
-onto processes which they would not otherwise have) and a risk to system
-stability.  Their preferred solutions involved realtime scheduling access
-via the rlimit mechanism for the short term, and ongoing latency reduction
-work in the long term.
-
-The audio community, however, could not see past the particular solution
-they had implemented; they were unwilling to accept alternatives.  The
-resulting disagreement left those developers feeling disillusioned with the
-entire kernel development process; one of them went back to an audio list
-and posted this:
-
-	There are a number of very good Linux kernel developers, but they
-	tend to get outshouted by a large crowd of arrogant fools. Trying
-	to communicate user requirements to these people is a waste of
-	time. They are much too "intelligent" to listen to lesser mortals.
-
-(http://lwn.net/Articles/131776/).
-
-The reality of the situation was different; the kernel developers were far
-more concerned about system stability, long-term maintenance, and finding
-the right solution to the problem than they were with a specific module.
-The moral of the story is to focus on the problem - not a specific solution
-- and to discuss it with the development community before investing in the
-creation of a body of code.
-
-So, when contemplating a kernel development project, one should obtain
-answers to a short set of questions:
-
- - What, exactly, is the problem which needs to be solved?
-
- - Who are the users affected by this problem?  Which use cases should the
-   solution address?
-
- - How does the kernel fall short in addressing that problem now?
-
-Only then does it make sense to start considering possible solutions.
-
-
-Early discussion
-----------------
-
-When planning a kernel development project, it makes great sense to hold
-discussions with the community before launching into implementation.  Early
-communication can save time and trouble in a number of ways:
-
- - It may well be that the problem is addressed by the kernel in ways which
-   you have not understood.  The Linux kernel is large and has a number of
-   features and capabilities which are not immediately obvious.  Not all
-   kernel capabilities are documented as well as one might like, and it is
-   easy to miss things.  Your author has seen the posting of a complete
-   driver which duplicated an existing driver that the new author had been
-   unaware of.  Code which reinvents existing wheels is not only wasteful;
-   it will also not be accepted into the mainline kernel.
-
- - There may be elements of the proposed solution which will not be
-   acceptable for mainline merging.  It is better to find out about
-   problems like this before writing the code.
-
- - It's entirely possible that other developers have thought about the
-   problem; they may have ideas for a better solution, and may be willing
-   to help in the creation of that solution.
-
-Years of experience with the kernel development community have taught a
-clear lesson: kernel code which is designed and developed behind closed
-doors invariably has problems which are only revealed when the code is
-released into the community.  Sometimes these problems are severe,
-requiring months or years of effort before the code can be brought up to
-the kernel community's standards.  Some examples include:
-
- - The Devicescape network stack was designed and implemented for
-   single-processor systems.  It could not be merged into the mainline
-   until it was made suitable for multiprocessor systems.  Retrofitting
-   locking and such into code is a difficult task; as a result, the merging
-   of this code (now called mac80211) was delayed for over a year.
-
- - The Reiser4 filesystem included a number of capabilities which, in the
-   core kernel developers' opinion, should have been implemented in the
-   virtual filesystem layer instead.  It also included features which could
-   not easily be implemented without exposing the system to user-caused
-   deadlocks.  The late revelation of these problems - and refusal to
-   address some of them - has caused Reiser4 to stay out of the mainline
-   kernel.
-
- - The AppArmor security module made use of internal virtual filesystem
-   data structures in ways which were considered to be unsafe and
-   unreliable.  This concern (among others) kept AppArmor out of the
-   mainline for years.
-
-In each of these cases, a great deal of pain and extra work could have been
-avoided with some early discussion with the kernel developers.
-
-
-Who do you talk to?
--------------------
-
-When developers decide to take their plans public, the next question will
-be: where do we start?  The answer is to find the right mailing list(s) and
-the right maintainer.  For mailing lists, the best approach is to look in
-the MAINTAINERS file for a relevant place to post.  If there is a suitable
-subsystem list, posting there is often preferable to posting on
-linux-kernel; you are more likely to reach developers with expertise in the
-relevant subsystem and the environment may be more supportive.
-
-Finding maintainers can be a bit harder.  Again, the MAINTAINERS file is
-the place to start.  That file tends to not always be up to date, though,
-and not all subsystems are represented there.  The person listed in the
-MAINTAINERS file may, in fact, not be the person who is actually acting in
-that role currently.  So, when there is doubt about who to contact, a
-useful trick is to use git (and "git log" in particular) to see who is
-currently active within the subsystem of interest.  Look at who is writing
-patches, and who, if anybody, is attaching Signed-off-by lines to those
-patches.  Those are the people who will be best placed to help with a new
-development project.
-
-The task of finding the right maintainer is sometimes challenging enough
-that the kernel developers have added a script to ease the process:
-
-::
-
-	.../scripts/get_maintainer.pl
-
-This script will return the current maintainer(s) for a given file or
-directory when given the "-f" option.  If passed a patch on the
-command line, it will list the maintainers who should probably receive
-copies of the patch.  There are a number of options regulating how hard
-get_maintainer.pl will search for maintainers; please be careful about
-using the more aggressive options as you may end up including developers
-who have no real interest in the code you are modifying.
-
-If all else fails, talking to Andrew Morton can be an effective way to
-track down a maintainer for a specific piece of code.
-
-
-When to post?
--------------
-
-If possible, posting your plans during the early stages can only be
-helpful.  Describe the problem being solved and any plans that have been
-made on how the implementation will be done.  Any information you can
-provide can help the development community provide useful input on the
-project.
-
-One discouraging thing which can happen at this stage is not a hostile
-reaction, but, instead, little or no reaction at all.  The sad truth of the
-matter is (1) kernel developers tend to be busy, (2) there is no shortage
-of people with grand plans and little code (or even prospect of code) to
-back them up, and (3) nobody is obligated to review or comment on ideas
-posted by others.  Beyond that, high-level designs often hide problems
-which are only reviewed when somebody actually tries to implement those
-designs; for that reason, kernel developers would rather see the code.
-
-If a request-for-comments posting yields little in the way of comments, do
-not assume that it means there is no interest in the project.
-Unfortunately, you also cannot assume that there are no problems with your
-idea.  The best thing to do in this situation is to proceed, keeping the
-community informed as you go.
-
-
-Getting official buy-in
------------------------
-
-If your work is being done in a corporate environment - as most Linux
-kernel work is - you must, obviously, have permission from suitably
-empowered managers before you can post your company's plans or code to a
-public mailing list.  The posting of code which has not been cleared for
-release under a GPL-compatible license can be especially problematic; the
-sooner that a company's management and legal staff can agree on the posting
-of a kernel development project, the better off everybody involved will be.
-
-Some readers may be thinking at this point that their kernel work is
-intended to support a product which does not yet have an officially
-acknowledged existence.  Revealing their employer's plans on a public
-mailing list may not be a viable option.  In cases like this, it is worth
-considering whether the secrecy is really necessary; there is often no real
-need to keep development plans behind closed doors.
-
-That said, there are also cases where a company legitimately cannot
-disclose its plans early in the development process.  Companies with
-experienced kernel developers may choose to proceed in an open-loop manner
-on the assumption that they will be able to avoid serious integration
-problems later.  For companies without that sort of in-house expertise, the
-best option is often to hire an outside developer to review the plans under
-a non-disclosure agreement.  The Linux Foundation operates an NDA program
-designed to help with this sort of situation; more information can be found
-at:
-
-    http://www.linuxfoundation.org/en/NDA_program
-
-This kind of review is often enough to avoid serious problems later on
-without requiring public disclosure of the project.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/4.Coding.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/4.Coding.rst
--- linux-libre-4.9-gnu/Documentation/development-process/4.Coding.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/4.Coding.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,413 +0,0 @@
-.. _development_coding:
-
-Getting the code right
-======================
-
-While there is much to be said for a solid and community-oriented design
-process, the proof of any kernel development project is in the resulting
-code.  It is the code which will be examined by other developers and merged
-(or not) into the mainline tree.  So it is the quality of this code which
-will determine the ultimate success of the project.
-
-This section will examine the coding process.  We'll start with a look at a
-number of ways in which kernel developers can go wrong.  Then the focus
-will shift toward doing things right and the tools which can help in that
-quest.
-
-
-Pitfalls
----------
-
-Coding style
-************
-
-The kernel has long had a standard coding style, described in
-Documentation/CodingStyle.  For much of that time, the policies described
-in that file were taken as being, at most, advisory.  As a result, there is
-a substantial amount of code in the kernel which does not meet the coding
-style guidelines.  The presence of that code leads to two independent
-hazards for kernel developers.
-
-The first of these is to believe that the kernel coding standards do not
-matter and are not enforced.  The truth of the matter is that adding new
-code to the kernel is very difficult if that code is not coded according to
-the standard; many developers will request that the code be reformatted
-before they will even review it.  A code base as large as the kernel
-requires some uniformity of code to make it possible for developers to
-quickly understand any part of it.  So there is no longer room for
-strangely-formatted code.
-
-Occasionally, the kernel's coding style will run into conflict with an
-employer's mandated style.  In such cases, the kernel's style will have to
-win before the code can be merged.  Putting code into the kernel means
-giving up a degree of control in a number of ways - including control over
-how the code is formatted.
-
-The other trap is to assume that code which is already in the kernel is
-urgently in need of coding style fixes.  Developers may start to generate
-reformatting patches as a way of gaining familiarity with the process, or
-as a way of getting their name into the kernel changelogs - or both.  But
-pure coding style fixes are seen as noise by the development community;
-they tend to get a chilly reception.  So this type of patch is best
-avoided.  It is natural to fix the style of a piece of code while working
-on it for other reasons, but coding style changes should not be made for
-their own sake.
-
-The coding style document also should not be read as an absolute law which
-can never be transgressed.  If there is a good reason to go against the
-style (a line which becomes far less readable if split to fit within the
-80-column limit, for example), just do it.
-
-
-Abstraction layers
-******************
-
-Computer Science professors teach students to make extensive use of
-abstraction layers in the name of flexibility and information hiding.
-Certainly the kernel makes extensive use of abstraction; no project
-involving several million lines of code could do otherwise and survive.
-But experience has shown that excessive or premature abstraction can be
-just as harmful as premature optimization.  Abstraction should be used to
-the level required and no further.
-
-At a simple level, consider a function which has an argument which is
-always passed as zero by all callers.  One could retain that argument just
-in case somebody eventually needs to use the extra flexibility that it
-provides.  By that time, though, chances are good that the code which
-implements this extra argument has been broken in some subtle way which was
-never noticed - because it has never been used.  Or, when the need for
-extra flexibility arises, it does not do so in a way which matches the
-programmer's early expectation.  Kernel developers will routinely submit
-patches to remove unused arguments; they should, in general, not be added
-in the first place.
-
-Abstraction layers which hide access to hardware - often to allow the bulk
-of a driver to be used with multiple operating systems - are especially
-frowned upon.  Such layers obscure the code and may impose a performance
-penalty; they do not belong in the Linux kernel.
-
-On the other hand, if you find yourself copying significant amounts of code
-from another kernel subsystem, it is time to ask whether it would, in fact,
-make sense to pull out some of that code into a separate library or to
-implement that functionality at a higher level.  There is no value in
-replicating the same code throughout the kernel.
-
-
-#ifdef and preprocessor use in general
-**************************************
-
-The C preprocessor seems to present a powerful temptation to some C
-programmers, who see it as a way to efficiently encode a great deal of
-flexibility into a source file.  But the preprocessor is not C, and heavy
-use of it results in code which is much harder for others to read and
-harder for the compiler to check for correctness.  Heavy preprocessor use
-is almost always a sign of code which needs some cleanup work.
-
-Conditional compilation with #ifdef is, indeed, a powerful feature, and it
-is used within the kernel.  But there is little desire to see code which is
-sprinkled liberally with #ifdef blocks.  As a general rule, #ifdef use
-should be confined to header files whenever possible.
-Conditionally-compiled code can be confined to functions which, if the code
-is not to be present, simply become empty.  The compiler will then quietly
-optimize out the call to the empty function.  The result is far cleaner
-code which is easier to follow.
-
-C preprocessor macros present a number of hazards, including possible
-multiple evaluation of expressions with side effects and no type safety.
-If you are tempted to define a macro, consider creating an inline function
-instead.  The code which results will be the same, but inline functions are
-easier to read, do not evaluate their arguments multiple times, and allow
-the compiler to perform type checking on the arguments and return value.
-
-
-Inline functions
-****************
-
-Inline functions present a hazard of their own, though.  Programmers can
-become enamored of the perceived efficiency inherent in avoiding a function
-call and fill a source file with inline functions.  Those functions,
-however, can actually reduce performance.  Since their code is replicated
-at each call site, they end up bloating the size of the compiled kernel.
-That, in turn, creates pressure on the processor's memory caches, which can
-slow execution dramatically.  Inline functions, as a rule, should be quite
-small and relatively rare.  The cost of a function call, after all, is not
-that high; the creation of large numbers of inline functions is a classic
-example of premature optimization.
-
-In general, kernel programmers ignore cache effects at their peril.  The
-classic time/space tradeoff taught in beginning data structures classes
-often does not apply to contemporary hardware.  Space *is* time, in that a
-larger program will run slower than one which is more compact.
-
-More recent compilers take an increasingly active role in deciding whether
-a given function should actually be inlined or not.  So the liberal
-placement of "inline" keywords may not just be excessive; it could also be
-irrelevant.
-
-
-Locking
-*******
-
-In May, 2006, the "Devicescape" networking stack was, with great
-fanfare, released under the GPL and made available for inclusion in the
-mainline kernel.  This donation was welcome news; support for wireless
-networking in Linux was considered substandard at best, and the Devicescape
-stack offered the promise of fixing that situation.  Yet, this code did not
-actually make it into the mainline until June, 2007 (2.6.22).  What
-happened?
-
-This code showed a number of signs of having been developed behind
-corporate doors.  But one large problem in particular was that it was not
-designed to work on multiprocessor systems.  Before this networking stack
-(now called mac80211) could be merged, a locking scheme needed to be
-retrofitted onto it.
-
-Once upon a time, Linux kernel code could be developed without thinking
-about the concurrency issues presented by multiprocessor systems.  Now,
-however, this document is being written on a dual-core laptop.  Even on
-single-processor systems, work being done to improve responsiveness will
-raise the level of concurrency within the kernel.  The days when kernel
-code could be written without thinking about locking are long past.
-
-Any resource (data structures, hardware registers, etc.) which could be
-accessed concurrently by more than one thread must be protected by a lock.
-New code should be written with this requirement in mind; retrofitting
-locking after the fact is a rather more difficult task.  Kernel developers
-should take the time to understand the available locking primitives well
-enough to pick the right tool for the job.  Code which shows a lack of
-attention to concurrency will have a difficult path into the mainline.
-
-
-Regressions
-***********
-
-One final hazard worth mentioning is this: it can be tempting to make a
-change (which may bring big improvements) which causes something to break
-for existing users.  This kind of change is called a "regression," and
-regressions have become most unwelcome in the mainline kernel.  With few
-exceptions, changes which cause regressions will be backed out if the
-regression cannot be fixed in a timely manner.  Far better to avoid the
-regression in the first place.
-
-It is often argued that a regression can be justified if it causes things
-to work for more people than it creates problems for.  Why not make a
-change if it brings new functionality to ten systems for each one it
-breaks?  The best answer to this question was expressed by Linus in July,
-2007:
-
-::
-
-	So we don't fix bugs by introducing new problems.  That way lies
-	madness, and nobody ever knows if you actually make any real
-	progress at all. Is it two steps forwards, one step back, or one
-	step forward and two steps back?
-
-(http://lwn.net/Articles/243460/).
-
-An especially unwelcome type of regression is any sort of change to the
-user-space ABI.  Once an interface has been exported to user space, it must
-be supported indefinitely.  This fact makes the creation of user-space
-interfaces particularly challenging: since they cannot be changed in
-incompatible ways, they must be done right the first time.  For this
-reason, a great deal of thought, clear documentation, and wide review for
-user-space interfaces is always required.
-
-
-Code checking tools
--------------------
-
-For now, at least, the writing of error-free code remains an ideal that few
-of us can reach.  What we can hope to do, though, is to catch and fix as
-many of those errors as possible before our code goes into the mainline
-kernel.  To that end, the kernel developers have put together an impressive
-array of tools which can catch a wide variety of obscure problems in an
-automated way.  Any problem caught by the computer is a problem which will
-not afflict a user later on, so it stands to reason that the automated
-tools should be used whenever possible.
-
-The first step is simply to heed the warnings produced by the compiler.
-Contemporary versions of gcc can detect (and warn about) a large number of
-potential errors.  Quite often, these warnings point to real problems.
-Code submitted for review should, as a rule, not produce any compiler
-warnings.  When silencing warnings, take care to understand the real cause
-and try to avoid "fixes" which make the warning go away without addressing
-its cause.
-
-Note that not all compiler warnings are enabled by default.  Build the
-kernel with "make EXTRA_CFLAGS=-W" to get the full set.
-
-The kernel provides several configuration options which turn on debugging
-features; most of these are found in the "kernel hacking" submenu.  Several
-of these options should be turned on for any kernel used for development or
-testing purposes.  In particular, you should turn on:
-
- - ENABLE_WARN_DEPRECATED, ENABLE_MUST_CHECK, and FRAME_WARN to get an
-   extra set of warnings for problems like the use of deprecated interfaces
-   or ignoring an important return value from a function.  The output
-   generated by these warnings can be verbose, but one need not worry about
-   warnings from other parts of the kernel.
-
- - DEBUG_OBJECTS will add code to track the lifetime of various objects
-   created by the kernel and warn when things are done out of order.  If
-   you are adding a subsystem which creates (and exports) complex objects
-   of its own, consider adding support for the object debugging
-   infrastructure.
-
- - DEBUG_SLAB can find a variety of memory allocation and use errors; it
-   should be used on most development kernels.
-
- - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, and DEBUG_MUTEXES will find a
-   number of common locking errors.
-
-There are quite a few other debugging options, some of which will be
-discussed below.  Some of them have a significant performance impact and
-should not be used all of the time.  But some time spent learning the
-available options will likely be paid back many times over in short order.
-
-One of the heavier debugging tools is the locking checker, or "lockdep."
-This tool will track the acquisition and release of every lock (spinlock or
-mutex) in the system, the order in which locks are acquired relative to
-each other, the current interrupt environment, and more.  It can then
-ensure that locks are always acquired in the same order, that the same
-interrupt assumptions apply in all situations, and so on.  In other words,
-lockdep can find a number of scenarios in which the system could, on rare
-occasion, deadlock.  This kind of problem can be painful (for both
-developers and users) in a deployed system; lockdep allows them to be found
-in an automated manner ahead of time.  Code with any sort of non-trivial
-locking should be run with lockdep enabled before being submitted for
-inclusion.
-
-As a diligent kernel programmer, you will, beyond doubt, check the return
-status of any operation (such as a memory allocation) which can fail.  The
-fact of the matter, though, is that the resulting failure recovery paths
-are, probably, completely untested.  Untested code tends to be broken code;
-you could be much more confident of your code if all those error-handling
-paths had been exercised a few times.
-
-The kernel provides a fault injection framework which can do exactly that,
-especially where memory allocations are involved.  With fault injection
-enabled, a configurable percentage of memory allocations will be made to
-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.txt for more information on
-how to use this facility.
-
-Other kinds of errors can be found with the "sparse" static analysis tool.
-With sparse, the programmer can be warned about confusion between
-user-space and kernel-space addresses, mixture of big-endian and
-small-endian quantities, the passing of integer values where a set of bit
-flags is expected, and so on.  Sparse must be installed separately (it can
-be found at https://sparse.wiki.kernel.org/index.php/Main_Page if your
-distributor does not package it); it can then be run on the code by adding
-"C=1" to your make command.
-
-The "Coccinelle" tool (http://coccinelle.lip6.fr/) is able to find a wide
-variety of potential coding problems; it can also propose fixes for those
-problems.  Quite a few "semantic patches" for the kernel have been packaged
-under the scripts/coccinelle directory; running "make coccicheck" will run
-through those semantic patches and report on any problems found.  See
-Documentation/coccinelle.txt for more information.
-
-Other kinds of portability errors are best found by compiling your code for
-other architectures.  If you do not happen to have an S/390 system or a
-Blackfin development board handy, you can still perform the compilation
-step.  A large set of cross compilers for x86 systems can be found at
-
-	http://www.kernel.org/pub/tools/crosstool/
-
-Some time spent installing and using these compilers will help avoid
-embarrassment later.
-
-
-Documentation
--------------
-
-Documentation has often been more the exception than the rule with kernel
-development.  Even so, adequate documentation will help to ease the merging
-of new code into the kernel, make life easier for other developers, and
-will be helpful for your users.  In many cases, the addition of
-documentation has become essentially mandatory.
-
-The first piece of documentation for any patch is its associated
-changelog.  Log entries should describe the problem being solved, the form
-of the solution, the people who worked on the patch, any relevant
-effects on performance, and anything else that might be needed to
-understand the patch.  Be sure that the changelog says *why* the patch is
-worth applying; a surprising number of developers fail to provide that
-information.
-
-Any code which adds a new user-space interface - including new sysfs or
-/proc files - should include documentation of that interface which enables
-user-space developers to know what they are working with.  See
-Documentation/ABI/README for a description of how this documentation should
-be formatted and what information needs to be provided.
-
-The file Documentation/kernel-parameters.txt describes all of the kernel's
-boot-time parameters.  Any patch which adds new parameters should add the
-appropriate entries to this file.
-
-Any new configuration options must be accompanied by help text which
-clearly explains the options and when the user might want to select them.
-
-Internal API information for many subsystems is documented by way of
-specially-formatted comments; these comments can be extracted and formatted
-in a number of ways by the "kernel-doc" script.  If you are working within
-a subsystem which has kerneldoc comments, you should maintain them and add
-them, as appropriate, for externally-available functions.  Even in areas
-which have not been so documented, there is no harm in adding kerneldoc
-comments for the future; indeed, this can be a useful activity for
-beginning kernel developers.  The format of these comments, along with some
-information on how to create kerneldoc templates can be found in the file
-Documentation/kernel-documentation.rst.
-
-Anybody who reads through a significant amount of existing kernel code will
-note that, often, comments are most notable by their absence.  Once again,
-the expectations for new code are higher than they were in the past;
-merging uncommented code will be harder.  That said, there is little desire
-for verbosely-commented code.  The code should, itself, be readable, with
-comments explaining the more subtle aspects.
-
-Certain things should always be commented.  Uses of memory barriers should
-be accompanied by a line explaining why the barrier is necessary.  The
-locking rules for data structures generally need to be explained somewhere.
-Major data structures need comprehensive documentation in general.
-Non-obvious dependencies between separate bits of code should be pointed
-out.  Anything which might tempt a code janitor to make an incorrect
-"cleanup" needs a comment saying why it is done the way it is.  And so on.
-
-
-Internal API changes
---------------------
-
-The binary interface provided by the kernel to user space cannot be broken
-except under the most severe circumstances.  The kernel's internal
-programming interfaces, instead, are highly fluid and can be changed when
-the need arises.  If you find yourself having to work around a kernel API,
-or simply not using a specific functionality because it does not meet your
-needs, that may be a sign that the API needs to change.  As a kernel
-developer, you are empowered to make such changes.
-
-There are, of course, some catches.  API changes can be made, but they need
-to be well justified.  So any patch making an internal API change should be
-accompanied by a description of what the change is and why it is
-necessary.  This kind of change should also be broken out into a separate
-patch, rather than buried within a larger patch.
-
-The other catch is that a developer who changes an internal API is
-generally charged with the task of fixing any code within the kernel tree
-which is broken by the change.  For a widely-used function, this duty can
-lead to literally hundreds or thousands of changes - many of which are
-likely to conflict with work being done by other developers.  Needless to
-say, this can be a large job, so it is best to be sure that the
-justification is solid.  Note that the Coccinelle tool can help with
-wide-ranging API changes.
-
-When making an incompatible API change, one should, whenever possible,
-ensure that code which has not been updated is caught by the compiler.
-This will help you to be sure that you have found all in-tree uses of that
-interface.  It will also alert developers of out-of-tree code that there is
-a change that they need to respond to.  Supporting out-of-tree code is not
-something that kernel developers need to be worried about, but we also do
-not have to make life harder for out-of-tree developers than it needs to
-be.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/5.Posting.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/5.Posting.rst
--- linux-libre-4.9-gnu/Documentation/development-process/5.Posting.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/5.Posting.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,321 +0,0 @@
-.. _development_posting:
-
-Posting patches
-===============
-
-Sooner or later, the time comes when your work is ready to be presented to
-the community for review and, eventually, inclusion into the mainline
-kernel.  Unsurprisingly, the kernel development community has evolved a set
-of conventions and procedures which are used in the posting of patches;
-following them will make life much easier for everybody involved.  This
-document will attempt to cover these expectations in reasonable detail;
-more information can also be found in the files SubmittingPatches,
-SubmittingDrivers, and SubmitChecklist in the kernel documentation
-directory.
-
-
-When to post
-------------
-
-There is a constant temptation to avoid posting patches before they are
-completely "ready."  For simple patches, that is not a problem.  If the
-work being done is complex, though, there is a lot to be gained by getting
-feedback from the community before the work is complete.  So you should
-consider posting in-progress work, or even making a git tree available so
-that interested developers can catch up with your work at any time.
-
-When posting code which is not yet considered ready for inclusion, it is a
-good idea to say so in the posting itself.  Also mention any major work
-which remains to be done and any known problems.  Fewer people will look at
-patches which are known to be half-baked, but those who do will come in
-with the idea that they can help you drive the work in the right direction.
-
-
-Before creating patches
------------------------
-
-There are a number of things which should be done before you consider
-sending patches to the development community.  These include:
-
- - Test the code to the extent that you can.  Make use of the kernel's
-   debugging tools, ensure that the kernel will build with all reasonable
-   combinations of configuration options, use cross-compilers to build for
-   different architectures, etc.
-
- - Make sure your code is compliant with the kernel coding style
-   guidelines.
-
- - Does your change have performance implications?  If so, you should run
-   benchmarks showing what the impact (or benefit) of your change is; a
-   summary of the results should be included with the patch.
-
- - Be sure that you have the right to post the code.  If this work was done
-   for an employer, the employer likely has a right to the work and must be
-   agreeable with its release under the GPL.
-
-As a general rule, putting in some extra thought before posting code almost
-always pays back the effort in short order.
-
-
-Patch preparation
------------------
-
-The preparation of patches for posting can be a surprising amount of work,
-but, once again, attempting to save time here is not generally advisable
-even in the short term.
-
-Patches must be prepared against a specific version of the kernel.  As a
-general rule, a patch should be based on the current mainline as found in
-Linus's git tree.  When basing on mainline, start with a well-known release
-point - a stable or -rc release - rather than branching off the mainline at
-an arbitrary spot.
-
-It may become necessary to make versions against -mm, linux-next, or a
-subsystem tree, though, to facilitate wider testing and review.  Depending
-on the area of your patch and what is going on elsewhere, basing a patch
-against these other trees can require a significant amount of work
-resolving conflicts and dealing with API changes.
-
-Only the most simple changes should be formatted as a single patch;
-everything else should be made as a logical series of changes.  Splitting
-up patches is a bit of an art; some developers spend a long time figuring
-out how to do it in the way that the community expects.  There are a few
-rules of thumb, however, which can help considerably:
-
- - The patch series you post will almost certainly not be the series of
-   changes found in your working revision control system.  Instead, the
-   changes you have made need to be considered in their final form, then
-   split apart in ways which make sense.  The developers are interested in
-   discrete, self-contained changes, not the path you took to get to those
-   changes.
-
- - Each logically independent change should be formatted as a separate
-   patch.  These changes can be small ("add a field to this structure") or
-   large (adding a significant new driver, for example), but they should be
-   conceptually small and amenable to a one-line description.  Each patch
-   should make a specific change which can be reviewed on its own and
-   verified to do what it says it does.
-
- - As a way of restating the guideline above: do not mix different types of
-   changes in the same patch.  If a single patch fixes a critical security
-   bug, rearranges a few structures, and reformats the code, there is a
-   good chance that it will be passed over and the important fix will be
-   lost.
-
- - Each patch should yield a kernel which builds and runs properly; if your
-   patch series is interrupted in the middle, the result should still be a
-   working kernel.  Partial application of a patch series is a common
-   scenario when the "git bisect" tool is used to find regressions; if the
-   result is a broken kernel, you will make life harder for developers and
-   users who are engaging in the noble work of tracking down problems.
-
- - Do not overdo it, though.  One developer once posted a set of edits
-   to a single file as 500 separate patches - an act which did not make him
-   the most popular person on the kernel mailing list.  A single patch can
-   be reasonably large as long as it still contains a single *logical*
-   change.
-
- - It can be tempting to add a whole new infrastructure with a series of
-   patches, but to leave that infrastructure unused until the final patch
-   in the series enables the whole thing.  This temptation should be
-   avoided if possible; if that series adds regressions, bisection will
-   finger the last patch as the one which caused the problem, even though
-   the real bug is elsewhere.  Whenever possible, a patch which adds new
-   code should make that code active immediately.
-
-Working to create the perfect patch series can be a frustrating process
-which takes quite a bit of time and thought after the "real work" has been
-done.  When done properly, though, it is time well spent.
-
-
-Patch formatting and changelogs
--------------------------------
-
-So now you have a perfect series of patches for posting, but the work is
-not done quite yet.  Each patch needs to be formatted into a message which
-quickly and clearly communicates its purpose to the rest of the world.  To
-that end, each patch will be composed of the following:
-
- - An optional "From" line naming the author of the patch.  This line is
-   only necessary if you are passing on somebody else's patch via email,
-   but it never hurts to add it when in doubt.
-
- - A one-line description of what the patch does.  This message should be
-   enough for a reader who sees it with no other context to figure out the
-   scope of the patch; it is the line that will show up in the "short form"
-   changelogs.  This message is usually formatted with the relevant
-   subsystem name first, followed by the purpose of the patch.  For
-   example:
-
-   ::
-
-	gpio: fix build on CONFIG_GPIO_SYSFS=n
-
- - A blank line followed by a detailed description of the contents of the
-   patch.  This description can be as long as is required; it should say
-   what the patch does and why it should be applied to the kernel.
-
- - One or more tag lines, with, at a minimum, one Signed-off-by: line from
-   the author of the patch.  Tags will be described in more detail below.
-
-The items above, together, form the changelog for the patch.  Writing good
-changelogs is a crucial but often-neglected art; it's worth spending
-another moment discussing this issue.  When writing a changelog, you should
-bear in mind that a number of different people will be reading your words.
-These include subsystem maintainers and reviewers who need to decide
-whether the patch should be included, distributors and other maintainers
-trying to decide whether a patch should be backported to other kernels, bug
-hunters wondering whether the patch is responsible for a problem they are
-chasing, users who want to know how the kernel has changed, and more.  A
-good changelog conveys the needed information to all of these people in the
-most direct and concise way possible.
-
-To that end, the summary line should describe the effects of and motivation
-for the change as well as possible given the one-line constraint.  The
-detailed description can then amplify on those topics and provide any
-needed additional information.  If the patch fixes a bug, cite the commit
-which introduced the bug if possible (and please provide both the commit ID
-and the title when citing commits).  If a problem is associated with
-specific log or compiler output, include that output to help others
-searching for a solution to the same problem.  If the change is meant to
-support other changes coming in later patch, say so.  If internal APIs are
-changed, detail those changes and how other developers should respond.  In
-general, the more you can put yourself into the shoes of everybody who will
-be reading your changelog, the better that changelog (and the kernel as a
-whole) will be.
-
-Needless to say, the changelog should be the text used when committing the
-change to a revision control system.  It will be followed by:
-
- - The patch itself, in the unified ("-u") patch format.  Using the "-p"
-   option to diff will associate function names with changes, making the
-   resulting patch easier for others to read.
-
-You should avoid including changes to irrelevant files (those generated by
-the build process, for example, or editor backup files) in the patch.  The
-file "dontdiff" in the Documentation directory can help in this regard;
-pass it to diff with the "-X" option.
-
-The tags mentioned above are used to describe how various developers have
-been associated with the development of this patch.  They are described in
-detail in the SubmittingPatches document; what follows here is a brief
-summary.  Each of these lines has the format:
-
-::
-
-	tag: Full Name <email address>  optional-other-stuff
-
-The tags in common use are:
-
- - Signed-off-by: this is a developer's certification that he or she has
-   the right to submit the patch for inclusion into the kernel.  It is an
-   agreement to the Developer's Certificate of Origin, the full text of
-   which can be found in Documentation/SubmittingPatches.  Code without a
-   proper signoff cannot be merged into the mainline.
-
- - Acked-by: indicates an agreement by another developer (often a
-   maintainer of the relevant code) that the patch is appropriate for
-   inclusion into the kernel.
-
- - Tested-by: states that the named person has tested the patch and found
-   it to work.
-
- - Reviewed-by: the named developer has reviewed the patch for correctness;
-   see the reviewer's statement in Documentation/SubmittingPatches for more
-   detail.
-
- - Reported-by: names a user who reported a problem which is fixed by this
-   patch; this tag is used to give credit to the (often underappreciated)
-   people who test our code and let us know when things do not work
-   correctly.
-
- - Cc: the named person received a copy of the patch and had the
-   opportunity to comment on it.
-
-Be careful in the addition of tags to your patches: only Cc: is appropriate
-for addition without the explicit permission of the person named.
-
-
-Sending the patch
------------------
-
-Before you mail your patches, there are a couple of other things you should
-take care of:
-
- - Are you sure that your mailer will not corrupt the patches?  Patches
-   which have had gratuitous white-space changes or line wrapping performed
-   by the mail client will not apply at the other end, and often will not
-   be examined in any detail.  If there is any doubt at all, mail the patch
-   to yourself and convince yourself that it shows up intact.
-
-   Documentation/email-clients.txt has some helpful hints on making
-   specific mail clients work for sending patches.
-
- - Are you sure your patch is free of silly mistakes?  You should always
-   run patches through scripts/checkpatch.pl and address the complaints it
-   comes up with.  Please bear in mind that checkpatch.pl, while being the
-   embodiment of a fair amount of thought about what kernel patches should
-   look like, is not smarter than you.  If fixing a checkpatch.pl complaint
-   would make the code worse, don't do it.
-
-Patches should always be sent as plain text.  Please do not send them as
-attachments; that makes it much harder for reviewers to quote sections of
-the patch in their replies.  Instead, just put the patch directly into your
-message.
-
-When mailing patches, it is important to send copies to anybody who might
-be interested in it.  Unlike some other projects, the kernel encourages
-people to err on the side of sending too many copies; don't assume that the
-relevant people will see your posting on the mailing lists.  In particular,
-copies should go to:
-
- - The maintainer(s) of the affected subsystem(s).  As described earlier,
-   the MAINTAINERS file is the first place to look for these people.
-
- - Other developers who have been working in the same area - especially
-   those who might be working there now.  Using git to see who else has
-   modified the files you are working on can be helpful.
-
- - If you are responding to a bug report or a feature request, copy the
-   original poster as well.
-
- - Send a copy to the relevant mailing list, or, if nothing else applies,
-   the linux-kernel list.
-
- - If you are fixing a bug, think about whether the fix should go into the
-   next stable update.  If so, stable@vger.kernel.org should get a copy of
-   the patch.  Also add a "Cc: stable@vger.kernel.org" to the tags within
-   the patch itself; that will cause the stable team to get a notification
-   when your fix goes into the mainline.
-
-When selecting recipients for a patch, it is good to have an idea of who
-you think will eventually accept the patch and get it merged.  While it
-is possible to send patches directly to Linus Torvalds and have him merge
-them, things are not normally done that way.  Linus is busy, and there are
-subsystem maintainers who watch over specific parts of the kernel.  Usually
-you will be wanting that maintainer to merge your patches.  If there is no
-obvious maintainer, Andrew Morton is often the patch target of last resort.
-
-Patches need good subject lines.  The canonical format for a patch line is
-something like:
-
-::
-
-	[PATCH nn/mm] subsys: one-line description of the patch
-
-where "nn" is the ordinal number of the patch, "mm" is the total number of
-patches in the series, and "subsys" is the name of the affected subsystem.
-Clearly, nn/mm can be omitted for a single, standalone patch.
-
-If you have a significant series of patches, it is customary to send an
-introductory description as part zero.  This convention is not universally
-followed though; if you use it, remember that information in the
-introduction does not make it into the kernel changelogs.  So please ensure
-that the patches, themselves, have complete changelog information.
-
-In general, the second and following parts of a multi-part patch should be
-sent as a reply to the first part so that they all thread together at the
-receiving end.  Tools like git and quilt have commands to mail out a set of
-patches with the proper threading.  If you have a long series, though, and
-are using git, please stay away from the --chain-reply-to option to avoid
-creating exceptionally deep nesting.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/6.Followthrough.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/6.Followthrough.rst
--- linux-libre-4.9-gnu/Documentation/development-process/6.Followthrough.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/6.Followthrough.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,212 +0,0 @@
-.. _development_followthrough:
-
-Followthrough
-=============
-
-At this point, you have followed the guidelines given so far and, with the
-addition of your own engineering skills, have posted a perfect series of
-patches.  One of the biggest mistakes that even experienced kernel
-developers can make is to conclude that their work is now done.  In truth,
-posting patches indicates a transition into the next stage of the process,
-with, possibly, quite a bit of work yet to be done.
-
-It is a rare patch which is so good at its first posting that there is no
-room for improvement.  The kernel development process recognizes this fact,
-and, as a result, is heavily oriented toward the improvement of posted
-code.  You, as the author of that code, will be expected to work with the
-kernel community to ensure that your code is up to the kernel's quality
-standards.  A failure to participate in this process is quite likely to
-prevent the inclusion of your patches into the mainline.
-
-
-Working with reviewers
-----------------------
-
-A patch of any significance will result in a number of comments from other
-developers as they review the code.  Working with reviewers can be, for
-many developers, the most intimidating part of the kernel development
-process.  Life can be made much easier, though, if you keep a few things in
-mind:
-
- - If you have explained your patch well, reviewers will understand its
-   value and why you went to the trouble of writing it.  But that value
-   will not keep them from asking a fundamental question: what will it be
-   like to maintain a kernel with this code in it five or ten years later?
-   Many of the changes you may be asked to make - from coding style tweaks
-   to substantial rewrites - come from the understanding that Linux will
-   still be around and under development a decade from now.
-
- - Code review is hard work, and it is a relatively thankless occupation;
-   people remember who wrote kernel code, but there is little lasting fame
-   for those who reviewed it.  So reviewers can get grumpy, especially when
-   they see the same mistakes being made over and over again.  If you get a
-   review which seems angry, insulting, or outright offensive, resist the
-   impulse to respond in kind.  Code review is about the code, not about
-   the people, and code reviewers are not attacking you personally.
-
- - Similarly, code reviewers are not trying to promote their employers'
-   agendas at the expense of your own.  Kernel developers often expect to
-   be working on the kernel years from now, but they understand that their
-   employer could change.  They truly are, almost without exception,
-   working toward the creation of the best kernel they can; they are not
-   trying to create discomfort for their employers' competitors.
-
-What all of this comes down to is that, when reviewers send you comments,
-you need to pay attention to the technical observations that they are
-making.  Do not let their form of expression or your own pride keep that
-from happening.  When you get review comments on a patch, take the time to
-understand what the reviewer is trying to say.  If possible, fix the things
-that the reviewer is asking you to fix.  And respond back to the reviewer:
-thank them, and describe how you will answer their questions.
-
-Note that you do not have to agree with every change suggested by
-reviewers.  If you believe that the reviewer has misunderstood your code,
-explain what is really going on.  If you have a technical objection to a
-suggested change, describe it and justify your solution to the problem.  If
-your explanations make sense, the reviewer will accept them.  Should your
-explanation not prove persuasive, though, especially if others start to
-agree with the reviewer, take some time to think things over again.  It can
-be easy to become blinded by your own solution to a problem to the point
-that you don't realize that something is fundamentally wrong or, perhaps,
-you're not even solving the right problem.
-
-Andrew Morton has suggested that every review comment which does not result
-in a code change should result in an additional code comment instead; that
-can help future reviewers avoid the questions which came up the first time
-around.
-
-One fatal mistake is to ignore review comments in the hope that they will
-go away.  They will not go away.  If you repost code without having
-responded to the comments you got the time before, you're likely to find
-that your patches go nowhere.
-
-Speaking of reposting code: please bear in mind that reviewers are not
-going to remember all the details of the code you posted the last time
-around.  So it is always a good idea to remind reviewers of previously
-raised issues and how you dealt with them; the patch changelog is a good
-place for this kind of information.  Reviewers should not have to search
-through list archives to familiarize themselves with what was said last
-time; if you help them get a running start, they will be in a better mood
-when they revisit your code.
-
-What if you've tried to do everything right and things still aren't going
-anywhere?  Most technical disagreements can be resolved through discussion,
-but there are times when somebody simply has to make a decision.  If you
-honestly believe that this decision is going against you wrongly, you can
-always try appealing to a higher power.  As of this writing, that higher
-power tends to be Andrew Morton.  Andrew has a great deal of respect in the
-kernel development community; he can often unjam a situation which seems to
-be hopelessly blocked.  Appealing to Andrew should not be done lightly,
-though, and not before all other alternatives have been explored.  And bear
-in mind, of course, that he may not agree with you either.
-
-
-What happens next
------------------
-
-If a patch is considered to be a good thing to add to the kernel, and once
-most of the review issues have been resolved, the next step is usually
-entry into a subsystem maintainer's tree.  How that works varies from one
-subsystem to the next; each maintainer has his or her own way of doing
-things.  In particular, there may be more than one tree - one, perhaps,
-dedicated to patches planned for the next merge window, and another for
-longer-term work.
-
-For patches applying to areas for which there is no obvious subsystem tree
-(memory management patches, for example), the default tree often ends up
-being -mm.  Patches which affect multiple subsystems can also end up going
-through the -mm tree.
-
-Inclusion into a subsystem tree can bring a higher level of visibility to a
-patch.  Now other developers working with that tree will get the patch by
-default.  Subsystem trees typically feed linux-next as well, making their
-contents visible to the development community as a whole.  At this point,
-there's a good chance that you will get more comments from a new set of
-reviewers; these comments need to be answered as in the previous round.
-
-What may also happen at this point, depending on the nature of your patch,
-is that conflicts with work being done by others turn up.  In the worst
-case, heavy patch conflicts can result in some work being put on the back
-burner so that the remaining patches can be worked into shape and merged.
-Other times, conflict resolution will involve working with the other
-developers and, possibly, moving some patches between trees to ensure that
-everything applies cleanly.  This work can be a pain, but count your
-blessings: before the advent of the linux-next tree, these conflicts often
-only turned up during the merge window and had to be addressed in a hurry.
-Now they can be resolved at leisure, before the merge window opens.
-
-Some day, if all goes well, you'll log on and see that your patch has been
-merged into the mainline kernel.  Congratulations!  Once the celebration is
-complete (and you have added yourself to the MAINTAINERS file), though, it
-is worth remembering an important little fact: the job still is not done.
-Merging into the mainline brings its own challenges.
-
-To begin with, the visibility of your patch has increased yet again.  There
-may be a new round of comments from developers who had not been aware of
-the patch before.  It may be tempting to ignore them, since there is no
-longer any question of your code being merged.  Resist that temptation,
-though; you still need to be responsive to developers who have questions or
-suggestions.
-
-More importantly, though: inclusion into the mainline puts your code into
-the hands of a much larger group of testers.  Even if you have contributed
-a driver for hardware which is not yet available, you will be surprised by
-how many people will build your code into their kernels.  And, of course,
-where there are testers, there will be bug reports.
-
-The worst sort of bug reports are regressions.  If your patch causes a
-regression, you'll find an uncomfortable number of eyes upon you;
-regressions need to be fixed as soon as possible.  If you are unwilling or
-unable to fix the regression (and nobody else does it for you), your patch
-will almost certainly be removed during the stabilization period.  Beyond
-negating all of the work you have done to get your patch into the mainline,
-having a patch pulled as the result of a failure to fix a regression could
-well make it harder for you to get work merged in the future.
-
-After any regressions have been dealt with, there may be other, ordinary
-bugs to deal with.  The stabilization period is your best opportunity to
-fix these bugs and ensure that your code's debut in a mainline kernel
-release is as solid as possible.  So, please, answer bug reports, and fix
-the problems if at all possible.  That's what the stabilization period is
-for; you can start creating cool new patches once any problems with the old
-ones have been taken care of.
-
-And don't forget that there are other milestones which may also create bug
-reports: the next mainline stable release, when prominent distributors pick
-up a version of the kernel containing your patch, etc.  Continuing to
-respond to these reports is a matter of basic pride in your work.  If that
-is insufficient motivation, though, it's also worth considering that the
-development community remembers developers who lose interest in their code
-after it's merged.  The next time you post a patch, they will be evaluating
-it with the assumption that you will not be around to maintain it
-afterward.
-
-
-Other things that can happen
------------------------------
-
-One day, you may open your mail client and see that somebody has mailed you
-a patch to your code.  That is one of the advantages of having your code
-out there in the open, after all.  If you agree with the patch, you can
-either forward it on to the subsystem maintainer (be sure to include a
-proper From: line so that the attribution is correct, and add a signoff of
-your own), or send an Acked-by: response back and let the original poster
-send it upward.
-
-If you disagree with the patch, send a polite response explaining why.  If
-possible, tell the author what changes need to be made to make the patch
-acceptable to you.  There is a certain resistance to merging patches which
-are opposed by the author and maintainer of the code, but it only goes so
-far.  If you are seen as needlessly blocking good work, those patches will
-eventually flow around you and get into the mainline anyway.  In the Linux
-kernel, nobody has absolute veto power over any code.  Except maybe Linus.
-
-On very rare occasion, you may see something completely different: another
-developer posts a different solution to your problem.  At that point,
-chances are that one of the two patches will not be merged, and "mine was
-here first" is not considered to be a compelling technical argument.  If
-somebody else's patch displaces yours and gets into the mainline, there is
-really only one way to respond: be pleased that your problem got solved and
-get on with your work.  Having one's work shoved aside in this manner can
-be hurtful and discouraging, but the community will remember your reaction
-long after they have forgotten whose patch actually got merged.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/7.AdvancedTopics.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/7.AdvancedTopics.rst
--- linux-libre-4.9-gnu/Documentation/development-process/7.AdvancedTopics.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/7.AdvancedTopics.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,180 +0,0 @@
-.. _development_advancedtopics:
-
-Advanced topics
-===============
-
-At this point, hopefully, you have a handle on how the development process
-works.  There is still more to learn, however!  This section will cover a
-number of topics which can be helpful for developers wanting to become a
-regular part of the Linux kernel development process.
-
-Managing patches with git
--------------------------
-
-The use of distributed version control for the kernel began in early 2002,
-when Linus first started playing with the proprietary BitKeeper
-application.  While BitKeeper was controversial, the approach to software
-version management it embodied most certainly was not.  Distributed version
-control enabled an immediate acceleration of the kernel development
-project.  In current times, there are several free alternatives to
-BitKeeper.  For better or for worse, the kernel project has settled on git
-as its tool of choice.
-
-Managing patches with git can make life much easier for the developer,
-especially as the volume of those patches grows.  Git also has its rough
-edges and poses certain hazards; it is a young and powerful tool which is
-still being civilized by its developers.  This document will not attempt to
-teach the reader how to use git; that would be sufficient material for a
-long document in its own right.  Instead, the focus here will be on how git
-fits into the kernel development process in particular.  Developers who
-wish to come up to speed with git will find more information at:
-
-	http://git-scm.com/
-
-	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
-
-and on various tutorials found on the web.
-
-The first order of business is to read the above sites and get a solid
-understanding of how git works before trying to use it to make patches
-available to others.  A git-using developer should be able to obtain a copy
-of the mainline repository, explore the revision history, commit changes to
-the tree, use branches, etc.  An understanding of git's tools for the
-rewriting of history (such as rebase) is also useful.  Git comes with its
-own terminology and concepts; a new user of git should know about refs,
-remote branches, the index, fast-forward merges, pushes and pulls, detached
-heads, etc.  It can all be a little intimidating at the outset, but the
-concepts are not that hard to grasp with a bit of study.
-
-Using git to generate patches for submission by email can be a good
-exercise while coming up to speed.
-
-When you are ready to start putting up git trees for others to look at, you
-will, of course, need a server that can be pulled from.  Setting up such a
-server with git-daemon is relatively straightforward if you have a system
-which is accessible to the Internet.  Otherwise, free, public hosting sites
-(Github, for example) are starting to appear on the net.  Established
-developers can get an account on kernel.org, but those are not easy to come
-by; see http://kernel.org/faq/ for more information.
-
-The normal git workflow involves the use of a lot of branches.  Each line
-of development can be separated into a separate "topic branch" and
-maintained independently.  Branches in git are cheap, there is no reason to
-not make free use of them.  And, in any case, you should not do your
-development in any branch which you intend to ask others to pull from.
-Publicly-available branches should be created with care; merge in patches
-from development branches when they are in complete form and ready to go -
-not before.
-
-Git provides some powerful tools which can allow you to rewrite your
-development history.  An inconvenient patch (one which breaks bisection,
-say, or which has some other sort of obvious bug) can be fixed in place or
-made to disappear from the history entirely.  A patch series can be
-rewritten as if it had been written on top of today's mainline, even though
-you have been working on it for months.  Changes can be transparently
-shifted from one branch to another.  And so on.  Judicious use of git's
-ability to revise history can help in the creation of clean patch sets with
-fewer problems.
-
-Excessive use of this capability can lead to other problems, though, beyond
-a simple obsession for the creation of the perfect project history.
-Rewriting history will rewrite the changes contained in that history,
-turning a tested (hopefully) kernel tree into an untested one.  But, beyond
-that, developers cannot easily collaborate if they do not have a shared
-view of the project history; if you rewrite history which other developers
-have pulled into their repositories, you will make life much more difficult
-for those developers.  So a simple rule of thumb applies here: history
-which has been exported to others should generally be seen as immutable
-thereafter.
-
-So, once you push a set of changes to your publicly-available server, those
-changes should not be rewritten.  Git will attempt to enforce this rule if
-you try to push changes which do not result in a fast-forward merge
-(i.e. changes which do not share the same history).  It is possible to
-override this check, and there may be times when it is necessary to rewrite
-an exported tree.  Moving changesets between trees to avoid conflicts in
-linux-next is one example.  But such actions should be rare.  This is one
-of the reasons why development should be done in private branches (which
-can be rewritten if necessary) and only moved into public branches when
-it's in a reasonably advanced state.
-
-As the mainline (or other tree upon which a set of changes is based)
-advances, it is tempting to merge with that tree to stay on the leading
-edge.  For a private branch, rebasing can be an easy way to keep up with
-another tree, but rebasing is not an option once a tree is exported to the
-world.  Once that happens, a full merge must be done.  Merging occasionally
-makes good sense, but overly frequent merges can clutter the history
-needlessly.  Suggested technique in this case is to merge infrequently, and
-generally only at specific release points (such as a mainline -rc
-release).  If you are nervous about specific changes, you can always
-perform test merges in a private branch.  The git "rerere" tool can be
-useful in such situations; it remembers how merge conflicts were resolved
-so that you don't have to do the same work twice.
-
-One of the biggest recurring complaints about tools like git is this: the
-mass movement of patches from one repository to another makes it easy to
-slip in ill-advised changes which go into the mainline below the review
-radar.  Kernel developers tend to get unhappy when they see that kind of
-thing happening; putting up a git tree with unreviewed or off-topic patches
-can affect your ability to get trees pulled in the future.  Quoting Linus:
-
-::
-
-	You can send me patches, but for me to pull a git patch from you, I
-	need to know that you know what you're doing, and I need to be able
-	to trust things *without* then having to go and check every
-	individual change by hand.
-
-(http://lwn.net/Articles/224135/).
-
-To avoid this kind of situation, ensure that all patches within a given
-branch stick closely to the associated topic; a "driver fixes" branch
-should not be making changes to the core memory management code.  And, most
-importantly, do not use a git tree to bypass the review process.  Post an
-occasional summary of the tree to the relevant list, and, when the time is
-right, request that the tree be included in linux-next.
-
-If and when others start to send patches for inclusion into your tree,
-don't forget to review them.  Also ensure that you maintain the correct
-authorship information; the git "am" tool does its best in this regard, but
-you may have to add a "From:" line to the patch if it has been relayed to
-you via a third party.
-
-When requesting a pull, be sure to give all the relevant information: where
-your tree is, what branch to pull, and what changes will result from the
-pull.  The git request-pull command can be helpful in this regard; it will
-format the request as other developers expect, and will also check to be
-sure that you have remembered to push those changes to the public server.
-
-
-Reviewing patches
------------------
-
-Some readers will certainly object to putting this section with "advanced
-topics" on the grounds that even beginning kernel developers should be
-reviewing patches.  It is certainly true that there is no better way to
-learn how to program in the kernel environment than by looking at code
-posted by others.  In addition, reviewers are forever in short supply; by
-looking at code you can make a significant contribution to the process as a
-whole.
-
-Reviewing code can be an intimidating prospect, especially for a new kernel
-developer who may well feel nervous about questioning code - in public -
-which has been posted by those with more experience.  Even code written by
-the most experienced developers can be improved, though.  Perhaps the best
-piece of advice for reviewers (all reviewers) is this: phrase review
-comments as questions rather than criticisms.  Asking "how does the lock
-get released in this path?" will always work better than stating "the
-locking here is wrong."
-
-Different developers will review code from different points of view.  Some
-are mostly concerned with coding style and whether code lines have trailing
-white space.  Others will focus primarily on whether the change implemented
-by the patch as a whole is a good thing for the kernel or not.  Yet others
-will check for problematic locking, excessive stack usage, possible
-security issues, duplication of code found elsewhere, adequate
-documentation, adverse effects on performance, user-space ABI changes, etc.
-All types of review, if they lead to better code going into the kernel, are
-welcome and worthwhile.
-
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/8.Conclusion.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/8.Conclusion.rst
--- linux-libre-4.9-gnu/Documentation/development-process/8.Conclusion.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/8.Conclusion.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-.. _development_conclusion:
-
-For more information
-====================
-
-There are numerous sources of information on Linux kernel development and
-related topics.  First among those will always be the Documentation
-directory found in the kernel source distribution.  The top-level HOWTO
-file is an important starting point; SubmittingPatches and
-SubmittingDrivers are also something which all kernel developers should
-read.  Many internal kernel APIs are documented using the kerneldoc
-mechanism; "make htmldocs" or "make pdfdocs" can be used to generate those
-documents in HTML or PDF format (though the version of TeX shipped by some
-distributions runs into internal limits and fails to process the documents
-properly).
-
-Various web sites discuss kernel development at all levels of detail.  Your
-author would like to humbly suggest http://lwn.net/ as a source;
-information on many specific kernel topics can be found via the LWN kernel
-index at:
-
-	http://lwn.net/Kernel/Index/
-
-Beyond that, a valuable resource for kernel developers is:
-
-	http://kernelnewbies.org/
-
-And, of course, one should not forget http://kernel.org/, the definitive
-location for kernel release information.
-
-There are a number of books on kernel development:
-
-	Linux Device Drivers, 3rd Edition (Jonathan Corbet, Alessandro
-	Rubini, and Greg Kroah-Hartman).  Online at
-	http://lwn.net/Kernel/LDD3/.
-
-	Linux Kernel Development (Robert Love).
-
-	Understanding the Linux Kernel (Daniel Bovet and Marco Cesati).
-
-All of these books suffer from a common fault, though: they tend to be
-somewhat obsolete by the time they hit the shelves, and they have been on
-the shelves for a while now.  Still, there is quite a bit of good
-information to be found there.
-
-Documentation for git can be found at:
-
-	http://www.kernel.org/pub/software/scm/git/docs/
-
-	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
-
-
-Conclusion
-==========
-
-Congratulations to anybody who has made it through this long-winded
-document.  Hopefully it has provided a helpful understanding of how the
-Linux kernel is developed and how you can participate in that process.
-
-In the end, it's the participation that matters.  Any open source software
-project is no more than the sum of what its contributors put into it.  The
-Linux kernel has progressed as quickly and as well as it has because it has
-been helped by an impressively large group of developers, all of whom are
-working to make it better.  The kernel is a premier example of what can be
-done when thousands of people work together toward a common goal.
-
-The kernel can always benefit from a larger developer base, though.  There
-is always more work to do.  But, just as importantly, most other
-participants in the Linux ecosystem can benefit through contributing to the
-kernel.  Getting code into the mainline is the key to higher code quality,
-lower maintenance and distribution costs, a higher level of influence over
-the direction of kernel development, and more.  It is a situation where
-everybody involved wins.  Fire up your editor and come join us; you will be
-more than welcome.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/conf.py linux-libre-4.10-rc8-gnu/Documentation/development-process/conf.py
--- linux-libre-4.9-gnu/Documentation/development-process/conf.py	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/conf.py	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-# -*- coding: utf-8; mode: python -*-
-
-project = 'Linux Kernel Development Documentation'
-
-tags.add("subproject")
-
-latex_documents = [
-    ('index', 'development-process.tex', 'Linux Kernel Development Documentation',
-     'The kernel development community', 'manual'),
-]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/development-process.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/development-process.rst
--- linux-libre-4.9-gnu/Documentation/development-process/development-process.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/development-process.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-.. _development_process_main:
-
-A guide to the Kernel Development Process
-=========================================
-
-Contents:
-
-.. toctree::
-   :numbered:
-   :maxdepth: 2
-
-   1.Intro
-   2.Process
-   3.Early-stage
-   4.Coding
-   5.Posting
-   6.Followthrough
-   7.AdvancedTopics
-   8.Conclusion
-
-The purpose of this document is to help developers (and their managers)
-work with the development community with a minimum of frustration.  It is
-an attempt to document how this community works in a way which is
-accessible to those who are not intimately familiar with Linux kernel
-development (or, indeed, free software development in general).  While
-there is some technical material here, this is very much a process-oriented
-discussion which does not require a deep knowledge of kernel programming to
-understand.
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/development-process/index.rst linux-libre-4.10-rc8-gnu/Documentation/development-process/index.rst
--- linux-libre-4.9-gnu/Documentation/development-process/index.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/development-process/index.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-Linux Kernel Development Documentation
-======================================
-
-Contents:
-
-.. toctree::
-   :maxdepth: 2
-
-   development-process
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/device-mapper/delay.txt linux-libre-4.10-rc8-gnu/Documentation/device-mapper/delay.txt
--- linux-libre-4.9-gnu/Documentation/device-mapper/delay.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/device-mapper/delay.txt	2017-02-12 16:03:20.000000000 -0500
@@ -16,12 +16,12 @@ Example scripts
 [[
 #!/bin/sh
 # Create device delaying rw operation for 500ms
-echo "0 `blockdev --getsize $1` delay $1 0 500" | dmsetup create delayed
+echo "0 `blockdev --getsz $1` delay $1 0 500" | dmsetup create delayed
 ]]
 
 [[
 #!/bin/sh
 # Create device delaying only write operation for 500ms and
 # splitting reads and writes to different devices $1 $2
-echo "0 `blockdev --getsize $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
+echo "0 `blockdev --getsz $1` delay $1 0 0 $2 0 500" | dmsetup create delayed
 ]]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/device-mapper/dm-crypt.txt linux-libre-4.10-rc8-gnu/Documentation/device-mapper/dm-crypt.txt
--- linux-libre-4.9-gnu/Documentation/device-mapper/dm-crypt.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/device-mapper/dm-crypt.txt	2017-02-12 16:03:20.000000000 -0500
@@ -21,13 +21,30 @@ Parameters: <cipher> <key> <iv_offset> <
     /proc/crypto contains supported crypto modes
 
 <key>
-    Key used for encryption. It is encoded as a hexadecimal number.
+    Key used for encryption. It is encoded either as a hexadecimal number
+    or it can be passed as <key_string> prefixed with single colon
+    character (':') for keys residing in kernel keyring service.
     You can only use key sizes that are valid for the selected cipher
     in combination with the selected iv mode.
     Note that for some iv modes the key string can contain additional
     keys (for example IV seed) so the key contains more parts concatenated
     into a single string.
 
+<key_string>
+    The kernel keyring key is identified by string in following format:
+    <key_size>:<key_type>:<key_description>.
+
+<key_size>
+    The encryption key size in bytes. The kernel key payload size must match
+    the value passed in <key_size>.
+
+<key_type>
+    Either 'logon' or 'user' kernel key type.
+
+<key_description>
+    The kernel keyring key description crypt target should look for
+    when loading key of <key_type>.
+
 <keycount>
     Multi-key compatibility mode. You can define <keycount> keys and
     then sectors are encrypted according to their offsets (sector 0 uses key0;
@@ -85,7 +102,13 @@ https://gitlab.com/cryptsetup/cryptsetup
 [[
 #!/bin/sh
 # Create a crypt device using dmsetup
-dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
+dmsetup create crypt1 --table "0 `blockdev --getsz $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
+]]
+
+[[
+#!/bin/sh
+# Create a crypt device using dmsetup when encryption key is stored in keyring service
+dmsetup create crypt2 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 :32:logon:my_prefix:my_key 0 $1 0"
 ]]
 
 [[
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/device-mapper/dm-raid.txt linux-libre-4.10-rc8-gnu/Documentation/device-mapper/dm-raid.txt
--- linux-libre-4.9-gnu/Documentation/device-mapper/dm-raid.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/device-mapper/dm-raid.txt	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@ The target is named "raid" and it accept
   raid0		RAID0 striping (no resilience)
   raid1		RAID1 mirroring
   raid4		RAID4 with dedicated last parity disk
-  raid5_n 	RAID5 with dedicated last parity disk suporting takeover
+  raid5_n 	RAID5 with dedicated last parity disk supporting takeover
 		Same as raid4
 		-Transitory layout
   raid5_la	RAID5 left asymmetric
@@ -36,7 +36,7 @@ The target is named "raid" and it accept
 		- rotating parity N (right-to-left) with data continuation
   raid6_n_6	RAID6 with dedicate parity disks
 		- parity and Q-syndrome on the last 2 disks;
-		  laylout for takeover from/to raid4/raid5_n
+		  layout for takeover from/to raid4/raid5_n
   raid6_la_6	Same as "raid_la" plus dedicated last Q-syndrome disk
 		- layout for takeover from raid5_la from/to raid6
   raid6_ra_6	Same as "raid5_ra" dedicated last Q-syndrome disk
@@ -137,8 +137,8 @@ The target is named "raid" and it accept
 		device removal (negative value) or device addition (positive
 		value) to any reshape supporting raid levels 4/5/6 and 10.
 		RAID levels 4/5/6 allow for addition of devices (metadata
-		and data device tupel), raid10_near and raid10_offset only
-		allow for device addtion. raid10_far does not support any
+		and data device tuple), raid10_near and raid10_offset only
+		allow for device addition. raid10_far does not support any
 		reshaping at all.
 		A minimum of devices have to be kept to enforce resilience,
 		which is 3 devices for raid4/5 and 4 devices for raid6.
@@ -242,6 +242,10 @@ recovery.  Here is a fuller description
 			in RAID1/10 or wrong parity values found in RAID4/5/6.
 			This value is valid only after a "check" of the array
 			is performed.  A healthy array has a 'mismatch_cnt' of 0.
+	<data_offset>   The current data offset to the start of the user data on
+			each component device of a raid set (see the respective
+			raid parameter to support out-of-place reshaping).
+
 
 Message Interface
 -----------------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/device-mapper/linear.txt linux-libre-4.10-rc8-gnu/Documentation/device-mapper/linear.txt
--- linux-libre-4.9-gnu/Documentation/device-mapper/linear.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/device-mapper/linear.txt	2017-02-12 16:03:20.000000000 -0500
@@ -16,15 +16,15 @@ Example scripts
 [[
 #!/bin/sh
 # Create an identity mapping for a device
-echo "0 `blockdev --getsize $1` linear $1 0" | dmsetup create identity
+echo "0 `blockdev --getsz $1` linear $1 0" | dmsetup create identity
 ]]
 
 
 [[
 #!/bin/sh
 # Join 2 devices together
-size1=`blockdev --getsize $1`
-size2=`blockdev --getsize $2`
+size1=`blockdev --getsz $1`
+size2=`blockdev --getsz $2`
 echo "0 $size1 linear $1 0
 $size1 $size2 linear $2 0" | dmsetup create joined
 ]]
@@ -44,7 +44,7 @@ if (!defined($dev)) {
         die("Please specify a device.\n");
 }
 
-my $dev_size = `blockdev --getsize $dev`;
+my $dev_size = `blockdev --getsz $dev`;
 my $extents = int($dev_size / $extent_size) -
               (($dev_size % $extent_size) ? 1 : 0);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/device-mapper/striped.txt linux-libre-4.10-rc8-gnu/Documentation/device-mapper/striped.txt
--- linux-libre-4.9-gnu/Documentation/device-mapper/striped.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/device-mapper/striped.txt	2017-02-12 16:03:20.000000000 -0500
@@ -37,9 +37,9 @@ if (!$num_devs) {
         die("Specify at least one device\n");
 }
 
-$min_dev_size = `blockdev --getsize $devs[0]`;
+$min_dev_size = `blockdev --getsz $devs[0]`;
 for ($i = 1; $i < $num_devs; $i++) {
-        my $this_size = `blockdev --getsize $devs[$i]`;
+        my $this_size = `blockdev --getsz $devs[$i]`;
         $min_dev_size = ($min_dev_size < $this_size) ?
                         $min_dev_size : $this_size;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/device-mapper/switch.txt linux-libre-4.10-rc8-gnu/Documentation/device-mapper/switch.txt
--- linux-libre-4.9-gnu/Documentation/device-mapper/switch.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/device-mapper/switch.txt	2017-02-12 16:03:20.000000000 -0500
@@ -123,7 +123,7 @@ Assume that you have volumes vg1/switch0
 the same size.
 
 Create a switch device with 64kB region size:
-    dmsetup create switch --table "0 `blockdev --getsize /dev/vg1/switch0`
+    dmsetup create switch --table "0 `blockdev --getsz /dev/vg1/switch0`
 	switch 3 128 0 /dev/vg1/switch0 0 /dev/vg1/switch1 0 /dev/vg1/switch2 0"
 
 Set mappings for the first 7 entries to point to devices switch0, switch1,
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devices.txt linux-libre-4.10-rc8-gnu/Documentation/devices.txt
--- linux-libre-4.9-gnu/Documentation/devices.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devices.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,3325 +0,0 @@
-
-		    LINUX ALLOCATED DEVICES (4.x+ version)
-
-This list is the Linux Device List, the official registry of allocated
-device numbers and /dev directory nodes for the Linux operating
-system.
-
-The LaTeX version of this document is no longer maintained, nor is
-the document that used to reside at lanana.org.  This version in the
-mainline Linux kernel is the master document.  Updates shall be sent
-as patches to the kernel maintainers (see the SubmittingPatches document).
-Specifically explore the sections titled "CHAR and MISC DRIVERS", and
-"BLOCK LAYER" in the MAINTAINERS file to find the right maintainers
-to involve for character and block devices.
-
-This document is included by reference into the Filesystem Hierarchy
-Standard (FHS).	 The FHS is available from http://www.pathname.com/fhs/.
-
-Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga
-platform only.	Allocations marked (68k/Atari) apply to Linux/68k on
-the Atari platform only.
-
-This document is in the public domain.	The authors requests, however,
-that semantically altered versions are not distributed without
-permission of the authors, assuming the authors can be contacted without
-an unreasonable effort.
-
-
-	  **** DEVICE DRIVERS AUTHORS PLEASE READ THIS ****
-
-Linux now has extensive support for dynamic allocation of device numbering
-and can use sysfs and udev (systemd) to handle the naming needs. There are
-still some exceptions in the serial and boot device area. Before asking
-for a device number make sure you actually need one.
-
-To have a major number allocated, or a minor number in situations
-where that applies (e.g. busmice), please submit a patch and send to
-the authors as indicated above.
-
-Keep the description of the device *in the same format
-as this list*.	The reason for this is that it is the only way we have
-found to ensure we have all the requisite information to publish your
-device and avoid conflicts.
-
-Finally, sometimes we have to play "namespace police."  Please don't be
-offended.  We often get submissions for /dev names that would be bound
-to cause conflicts down the road.  We are trying to avoid getting in a
-situation where we would have to suffer an incompatible forward
-change.  Therefore, please consult with us *before* you make your
-device names and numbers in any way public, at least to the point
-where it would be at all difficult to get them changed.
-
-Your cooperation is appreciated.
-
-
-  0		Unnamed devices (e.g. non-device mounts)
-		  0 = reserved as null device number
-		See block major 144, 145, 146 for expansion areas.
-
-  1 char	Memory devices
-		  1 = /dev/mem		Physical memory access
-		  2 = /dev/kmem		Kernel virtual memory access
-		  3 = /dev/null		Null device
-		  4 = /dev/port		I/O port access
-		  5 = /dev/zero		Null byte source
-		  6 = /dev/core		OBSOLETE - replaced by /proc/kcore
-		  7 = /dev/full		Returns ENOSPC on write
-		  8 = /dev/random	Nondeterministic random number gen.
-		  9 = /dev/urandom	Faster, less secure random number gen.
-		 10 = /dev/aio		Asynchronous I/O notification interface
-		 11 = /dev/kmsg		Writes to this come out as printk's, reads
-					export the buffered printk records.
-		 12 = /dev/oldmem	OBSOLETE - replaced by /proc/vmcore
-
-  1 block	RAM disk
-		  0 = /dev/ram0		First RAM disk
-		  1 = /dev/ram1		Second RAM disk
-		    ...
-		250 = /dev/initrd	Initial RAM disk
-
-		Older kernels had /dev/ramdisk (1, 1) here.
-		/dev/initrd refers to a RAM disk which was preloaded
-		by the boot loader; newer kernels use /dev/ram0 for
-		the initrd.
-
-  2 char	Pseudo-TTY masters
-		  0 = /dev/ptyp0	First PTY master
-		  1 = /dev/ptyp1	Second PTY master
-		    ...
-		255 = /dev/ptyef	256th PTY master
-
-		Pseudo-tty's are named as follows:
-		* Masters are "pty", slaves are "tty";
-		* the fourth letter is one of pqrstuvwxyzabcde indicating
-		  the 1st through 16th series of 16 pseudo-ttys each, and
-		* the fifth letter is one of 0123456789abcdef indicating
-		  the position within the series.
-
-		These are the old-style (BSD) PTY devices; Unix98
-		devices are on major 128 and above and use the PTY
-		master multiplex (/dev/ptmx) to acquire a PTY on
-		demand.
-
-  2 block	Floppy disks
-		  0 = /dev/fd0		Controller 0, drive 0, autodetect
-		  1 = /dev/fd1		Controller 0, drive 1, autodetect
-		  2 = /dev/fd2		Controller 0, drive 2, autodetect
-		  3 = /dev/fd3		Controller 0, drive 3, autodetect
-		128 = /dev/fd4		Controller 1, drive 0, autodetect
-		129 = /dev/fd5		Controller 1, drive 1, autodetect
-		130 = /dev/fd6		Controller 1, drive 2, autodetect
-		131 = /dev/fd7		Controller 1, drive 3, autodetect
-
-		To specify format, add to the autodetect device number:
-		  0 = /dev/fd?		Autodetect format
-		  4 = /dev/fd?d360	5.25"  360K in a 360K  drive(1)
-		 20 = /dev/fd?h360	5.25"  360K in a 1200K drive(1)
-		 48 = /dev/fd?h410	5.25"  410K in a 1200K drive
-		 64 = /dev/fd?h420	5.25"  420K in a 1200K drive
-		 24 = /dev/fd?h720	5.25"  720K in a 1200K drive
-		 80 = /dev/fd?h880	5.25"  880K in a 1200K drive(1)
-		  8 = /dev/fd?h1200	5.25" 1200K in a 1200K drive(1)
-		 40 = /dev/fd?h1440	5.25" 1440K in a 1200K drive(1)
-		 56 = /dev/fd?h1476	5.25" 1476K in a 1200K drive
-		 72 = /dev/fd?h1494	5.25" 1494K in a 1200K drive
-		 92 = /dev/fd?h1600	5.25" 1600K in a 1200K drive(1)
-
-		 12 = /dev/fd?u360	3.5"   360K Double Density(2)
-		 16 = /dev/fd?u720	3.5"   720K Double Density(1)
-		120 = /dev/fd?u800	3.5"   800K Double Density(2)
-		 52 = /dev/fd?u820	3.5"   820K Double Density
-		 68 = /dev/fd?u830	3.5"   830K Double Density
-		 84 = /dev/fd?u1040	3.5"  1040K Double Density(1)
-		 88 = /dev/fd?u1120	3.5"  1120K Double Density(1)
-		 28 = /dev/fd?u1440	3.5"  1440K High Density(1)
-		124 = /dev/fd?u1600	3.5"  1600K High Density(1)
-		 44 = /dev/fd?u1680	3.5"  1680K High Density(3)
-		 60 = /dev/fd?u1722	3.5"  1722K High Density
-		 76 = /dev/fd?u1743	3.5"  1743K High Density
-		 96 = /dev/fd?u1760	3.5"  1760K High Density
-		116 = /dev/fd?u1840	3.5"  1840K High Density(3)
-		100 = /dev/fd?u1920	3.5"  1920K High Density(1)
-		 32 = /dev/fd?u2880	3.5"  2880K Extra Density(1)
-		104 = /dev/fd?u3200	3.5"  3200K Extra Density
-		108 = /dev/fd?u3520	3.5"  3520K Extra Density
-		112 = /dev/fd?u3840	3.5"  3840K Extra Density(1)
-
-		 36 = /dev/fd?CompaQ	Compaq 2880K drive; obsolete?
-
-		(1) Autodetectable format
-		(2) Autodetectable format in a Double Density (720K) drive only
-		(3) Autodetectable format in a High Density (1440K) drive only
-
-		NOTE: The letter in the device name (d, q, h or u)
-		signifies the type of drive: 5.25" Double Density (d),
-		5.25" Quad Density (q), 5.25" High Density (h) or 3.5"
-		(any model, u).	 The use of the capital letters D, H
-		and E for the 3.5" models have been deprecated, since
-		the drive type is insignificant for these devices.
-
-  3 char	Pseudo-TTY slaves
-		  0 = /dev/ttyp0	First PTY slave
-		  1 = /dev/ttyp1	Second PTY slave
-		    ...
-		255 = /dev/ttyef	256th PTY slave
-
-		These are the old-style (BSD) PTY devices; Unix98
-		devices are on major 136 and above.
-
-  3 block	First MFM, RLL and IDE hard disk/CD-ROM interface
-		  0 = /dev/hda		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdb		Slave: whole disk (or CD-ROM)
-
-		For partitions, add to the whole disk device number:
-		  0 = /dev/hd?		Whole disk
-		  1 = /dev/hd?1		First partition
-		  2 = /dev/hd?2		Second partition
-		    ...
-		 63 = /dev/hd?63	63rd partition
-
-		For Linux/i386, partitions 1-4 are the primary
-		partitions, and 5 and above are logical partitions.
-		Other versions of Linux use partitioning schemes
-		appropriate to their respective architectures.
-
-  4 char	TTY devices
-		  0 = /dev/tty0		Current virtual console
-
-		  1 = /dev/tty1		First virtual console
-		    ...
-		 63 = /dev/tty63	63rd virtual console
-		 64 = /dev/ttyS0	First UART serial port
-		    ...
-		255 = /dev/ttyS191	192nd UART serial port
-
-		UART serial ports refer to 8250/16450/16550 series devices.
-
-		Older versions of the Linux kernel used this major
-		number for BSD PTY devices.  As of Linux 2.1.115, this
-		is no longer supported.	 Use major numbers 2 and 3.
-
-  4 block	Aliases for dynamically allocated major devices to be used
-		when its not possible to create the real device nodes
-		because the root filesystem is mounted read-only.
-
-                  0 = /dev/root
-
-  5 char	Alternate TTY devices
-		  0 = /dev/tty		Current TTY device
-		  1 = /dev/console	System console
-		  2 = /dev/ptmx		PTY master multiplex
-		  3 = /dev/ttyprintk	User messages via printk TTY device
-		 64 = /dev/cua0		Callout device for ttyS0
-		    ...
-		255 = /dev/cua191	Callout device for ttyS191
-
-		(5,1) is /dev/console starting with Linux 2.1.71.  See
-		the section on terminal devices for more information
-		on /dev/console.
-
-  6 char	Parallel printer devices
-		  0 = /dev/lp0		Parallel printer on parport0
-		  1 = /dev/lp1		Parallel printer on parport1
-		    ...
-
-		Current Linux kernels no longer have a fixed mapping
-		between parallel ports and I/O addresses.  Instead,
-		they are redirected through the parport multiplex layer.
-
-  7 char	Virtual console capture devices
-		  0 = /dev/vcs		Current vc text contents
-		  1 = /dev/vcs1		tty1 text contents
-		    ...
-		 63 = /dev/vcs63	tty63 text contents
-		128 = /dev/vcsa		Current vc text/attribute contents
-		129 = /dev/vcsa1	tty1 text/attribute contents
-		    ...
-		191 = /dev/vcsa63	tty63 text/attribute contents
-
-		NOTE: These devices permit both read and write access.
-
-  7 block	Loopback devices
-		  0 = /dev/loop0	First loop device
-		  1 = /dev/loop1	Second loop device
-		    ...
-
-		The loop devices are used to mount filesystems not
-		associated with block devices.	The binding to the
-		loop devices is handled by mount(8) or losetup(8).
-
-  8 block	SCSI disk devices (0-15)
-		  0 = /dev/sda		First SCSI disk whole disk
-		 16 = /dev/sdb		Second SCSI disk whole disk
-		 32 = /dev/sdc		Third SCSI disk whole disk
-		    ...
-		240 = /dev/sdp		Sixteenth SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-  9 char	SCSI tape devices
-		  0 = /dev/st0		First SCSI tape, mode 0
-		  1 = /dev/st1		Second SCSI tape, mode 0
-		    ...
-		 32 = /dev/st0l		First SCSI tape, mode 1
-		 33 = /dev/st1l		Second SCSI tape, mode 1
-		    ...
-		 64 = /dev/st0m		First SCSI tape, mode 2
-		 65 = /dev/st1m		Second SCSI tape, mode 2
-		    ...
-		 96 = /dev/st0a		First SCSI tape, mode 3
-		 97 = /dev/st1a		Second SCSI tape, mode 3
-		      ...
-		128 = /dev/nst0		First SCSI tape, mode 0, no rewind
-		129 = /dev/nst1		Second SCSI tape, mode 0, no rewind
-		    ...
-		160 = /dev/nst0l	First SCSI tape, mode 1, no rewind
-		161 = /dev/nst1l	Second SCSI tape, mode 1, no rewind
-		    ...
-		192 = /dev/nst0m	First SCSI tape, mode 2, no rewind
-		193 = /dev/nst1m	Second SCSI tape, mode 2, no rewind
-		    ...
-		224 = /dev/nst0a	First SCSI tape, mode 3, no rewind
-		225 = /dev/nst1a	Second SCSI tape, mode 3, no rewind
-		    ...
-
-		"No rewind" refers to the omission of the default
-		automatic rewind on device close.  The MTREW or MTOFFL
-		ioctl()'s can be used to rewind the tape regardless of
-		the device used to access it.
-
-  9 block	Metadisk (RAID) devices
-		  0 = /dev/md0		First metadisk group
-		  1 = /dev/md1		Second metadisk group
-		    ...
-
-		The metadisk driver is used to span a
-		filesystem across multiple physical disks.
-
- 10 char	Non-serial mice, misc features
-		  0 = /dev/logibm	Logitech bus mouse
-		  1 = /dev/psaux	PS/2-style mouse port
-		  2 = /dev/inportbm	Microsoft Inport bus mouse
-		  3 = /dev/atibm	ATI XL bus mouse
-		  4 = /dev/jbm		J-mouse
-		  4 = /dev/amigamouse	Amiga mouse (68k/Amiga)
-		  5 = /dev/atarimouse	Atari mouse
-		  6 = /dev/sunmouse	Sun mouse
-		  7 = /dev/amigamouse1	Second Amiga mouse
-		  8 = /dev/smouse	Simple serial mouse driver
-		  9 = /dev/pc110pad	IBM PC-110 digitizer pad
-		 10 = /dev/adbmouse	Apple Desktop Bus mouse
-		 11 = /dev/vrtpanel	Vr41xx embedded touch panel
-		 13 = /dev/vpcmouse	Connectix Virtual PC Mouse
-		 14 = /dev/touchscreen/ucb1x00  UCB 1x00 touchscreen
-		 15 = /dev/touchscreen/mk712	MK712 touchscreen
-		128 = /dev/beep		Fancy beep device
-		129 =
-		130 = /dev/watchdog	Watchdog timer port
-		131 = /dev/temperature	Machine internal temperature
-		132 = /dev/hwtrap	Hardware fault trap
-		133 = /dev/exttrp	External device trap
-		134 = /dev/apm_bios	Advanced Power Management BIOS
-		135 = /dev/rtc		Real Time Clock
-		137 = /dev/vhci		Bluetooth virtual HCI driver
-		139 = /dev/openprom	SPARC OpenBoot PROM
-		140 = /dev/relay8	Berkshire Products Octal relay card
-		141 = /dev/relay16	Berkshire Products ISO-16 relay card
-		142 =
-		143 = /dev/pciconf	PCI configuration space
-		144 = /dev/nvram	Non-volatile configuration RAM
-		145 = /dev/hfmodem	Soundcard shortwave modem control
-		146 = /dev/graphics	Linux/SGI graphics device
-		147 = /dev/opengl	Linux/SGI OpenGL pipe
-		148 = /dev/gfx		Linux/SGI graphics effects device
-		149 = /dev/input/mouse	Linux/SGI Irix emulation mouse
-		150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard
-		151 = /dev/led		Front panel LEDs
-		152 = /dev/kpoll	Kernel Poll Driver
-		153 = /dev/mergemem	Memory merge device
-		154 = /dev/pmu		Macintosh PowerBook power manager
-		155 = /dev/isictl	MultiTech ISICom serial control
-		156 = /dev/lcd		Front panel LCD display
-		157 = /dev/ac		Applicom Intl Profibus card
-		158 = /dev/nwbutton	Netwinder external button
-		159 = /dev/nwdebug	Netwinder debug interface
-		160 = /dev/nwflash	Netwinder flash memory
-		161 = /dev/userdma	User-space DMA access
-		162 = /dev/smbus	System Management Bus
-		163 = /dev/lik		Logitech Internet Keyboard
-		164 = /dev/ipmo		Intel Intelligent Platform Management
-		165 = /dev/vmmon	VMware virtual machine monitor
-		166 = /dev/i2o/ctl	I2O configuration manager
-		167 = /dev/specialix_sxctl Specialix serial control
-		168 = /dev/tcldrv	Technology Concepts serial control
-		169 = /dev/specialix_rioctl Specialix RIO serial control
-		170 = /dev/thinkpad/thinkpad	IBM Thinkpad devices
-		171 = /dev/srripc	QNX4 API IPC manager
-		172 = /dev/usemaclone	Semaphore clone device
-		173 = /dev/ipmikcs	Intelligent Platform Management
-		174 = /dev/uctrl	SPARCbook 3 microcontroller
-		175 = /dev/agpgart	AGP Graphics Address Remapping Table
-		176 = /dev/gtrsc	Gorgy Timing radio clock
-		177 = /dev/cbm		Serial CBM bus
-		178 = /dev/jsflash	JavaStation OS flash SIMM
-		179 = /dev/xsvc		High-speed shared-mem/semaphore service
-		180 = /dev/vrbuttons	Vr41xx button input device
-		181 = /dev/toshiba	Toshiba laptop SMM support
-		182 = /dev/perfctr	Performance-monitoring counters
-		183 = /dev/hwrng	Generic random number generator
-		184 = /dev/cpu/microcode CPU microcode update interface
-		186 = /dev/atomicps	Atomic shapshot of process state data
-		187 = /dev/irnet	IrNET device
-		188 = /dev/smbusbios	SMBus BIOS
-		189 = /dev/ussp_ctl	User space serial port control
-		190 = /dev/crash	Mission Critical Linux crash dump facility
-		191 = /dev/pcl181	<information missing>
-		192 = /dev/nas_xbus	NAS xbus LCD/buttons access
-		193 = /dev/d7s		SPARC 7-segment display
-		194 = /dev/zkshim	Zero-Knowledge network shim control
-		195 = /dev/elographics/e2201	Elographics touchscreen E271-2201
-		196 = /dev/vfio/vfio	VFIO userspace driver interface
-		197 = /dev/pxa3xx-gcu	PXA3xx graphics controller unit driver
-		198 = /dev/sexec	Signed executable interface
-		199 = /dev/scanners/cuecat :CueCat barcode scanner
-		200 = /dev/net/tun	TAP/TUN network device
-		201 = /dev/button/gulpb	Transmeta GULP-B buttons
-		202 = /dev/emd/ctl	Enhanced Metadisk RAID (EMD) control
-		203 = /dev/cuse		Cuse (character device in user-space)
-		204 = /dev/video/em8300		EM8300 DVD decoder control
-		205 = /dev/video/em8300_mv	EM8300 DVD decoder video
-		206 = /dev/video/em8300_ma	EM8300 DVD decoder audio
-		207 = /dev/video/em8300_sp	EM8300 DVD decoder subpicture
-		208 = /dev/compaq/cpqphpc	Compaq PCI Hot Plug Controller
-		209 = /dev/compaq/cpqrid	Compaq Remote Insight Driver
-		210 = /dev/impi/bt	IMPI coprocessor block transfer
-		211 = /dev/impi/smic	IMPI coprocessor stream interface
-		212 = /dev/watchdogs/0	First watchdog device
-		213 = /dev/watchdogs/1	Second watchdog device
-		214 = /dev/watchdogs/2	Third watchdog device
-		215 = /dev/watchdogs/3	Fourth watchdog device
-		216 = /dev/fujitsu/apanel	Fujitsu/Siemens application panel
-		217 = /dev/ni/natmotn		National Instruments Motion
-		218 = /dev/kchuid	Inter-process chuid control
-		219 = /dev/modems/mwave	MWave modem firmware upload
-		220 = /dev/mptctl	Message passing technology (MPT) control
-		221 = /dev/mvista/hssdsi	Montavista PICMG hot swap system driver
-		222 = /dev/mvista/hasi		Montavista PICMG high availability
-		223 = /dev/input/uinput		User level driver support for input
-		224 = /dev/tpm		TCPA TPM driver
-		225 = /dev/pps		Pulse Per Second driver
-		226 = /dev/systrace	Systrace device
-		227 = /dev/mcelog	X86_64 Machine Check Exception driver
-		228 = /dev/hpet		HPET driver
-		229 = /dev/fuse		Fuse (virtual filesystem in user-space)
-		230 = /dev/midishare	MidiShare driver
-		231 = /dev/snapshot	System memory snapshot device
-		232 = /dev/kvm		Kernel-based virtual machine (hardware virtualization extensions)
-		233 = /dev/kmview	View-OS A process with a view
-		234 = /dev/btrfs-control	Btrfs control device
-		235 = /dev/autofs	Autofs control device
-		236 = /dev/mapper/control	Device-Mapper control device
-		237 = /dev/loop-control Loopback control device
-		238 = /dev/vhost-net	Host kernel accelerator for virtio net
-		239 = /dev/uhid		User-space I/O driver support for HID subsystem
-
-		240-254			Reserved for local use
-		255			Reserved for MISC_DYNAMIC_MINOR
-
- 11 char	Raw keyboard device	(Linux/SPARC only)
-		  0 = /dev/kbd		Raw keyboard device
-
- 11 char	Serial Mux device	(Linux/PA-RISC only)
-		  0 = /dev/ttyB0	First mux port
-		  1 = /dev/ttyB1	Second mux port
-		    ...
-
- 11 block	SCSI CD-ROM devices
-		  0 = /dev/scd0		First SCSI CD-ROM
-		  1 = /dev/scd1		Second SCSI CD-ROM
-		    ...
-
-		The prefix /dev/sr (instead of /dev/scd) has been deprecated.
-
- 12 char	QIC-02 tape
-		  2 = /dev/ntpqic11	QIC-11, no rewind-on-close
-		  3 = /dev/tpqic11	QIC-11, rewind-on-close
-		  4 = /dev/ntpqic24	QIC-24, no rewind-on-close
-		  5 = /dev/tpqic24	QIC-24, rewind-on-close
-		  6 = /dev/ntpqic120	QIC-120, no rewind-on-close
-		  7 = /dev/tpqic120	QIC-120, rewind-on-close
-		  8 = /dev/ntpqic150	QIC-150, no rewind-on-close
-		  9 = /dev/tpqic150	QIC-150, rewind-on-close
-
-		The device names specified are proposed -- if there
-		are "standard" names for these devices, please let me know.
-
- 12 block
-
- 13 char	Input core
-		  0 = /dev/input/js0	First joystick
-		  1 = /dev/input/js1	Second joystick
-		    ...
-		 32 = /dev/input/mouse0	First mouse
-		 33 = /dev/input/mouse1	Second mouse
-		    ...
-		 63 = /dev/input/mice	Unified mouse
-		 64 = /dev/input/event0	First event queue
-		 65 = /dev/input/event1	Second event queue
-		    ...
-
-		Each device type has 5 bits (32 minors).
-
- 13 block	Previously used for the XT disk (/dev/xdN)
-		Deleted in kernel v3.9.
-
- 14 char	Open Sound System (OSS)
-		  0 = /dev/mixer	Mixer control
-		  1 = /dev/sequencer	Audio sequencer
-		  2 = /dev/midi00	First MIDI port
-		  3 = /dev/dsp		Digital audio
-		  4 = /dev/audio	Sun-compatible digital audio
-		  6 =
-		  7 = /dev/audioctl	SPARC audio control device
-		  8 = /dev/sequencer2	Sequencer -- alternate device
-		 16 = /dev/mixer1	Second soundcard mixer control
-		 17 = /dev/patmgr0	Sequencer patch manager
-		 18 = /dev/midi01	Second MIDI port
-		 19 = /dev/dsp1		Second soundcard digital audio
-		 20 = /dev/audio1	Second soundcard Sun digital audio
-		 33 = /dev/patmgr1	Sequencer patch manager
-		 34 = /dev/midi02	Third MIDI port
-		 50 = /dev/midi03	Fourth MIDI port
-
- 14 block
-
- 15 char	Joystick
-		  0 = /dev/js0		First analog joystick
-		  1 = /dev/js1		Second analog joystick
-		    ...
-		128 = /dev/djs0		First digital joystick
-		129 = /dev/djs1		Second digital joystick
-		    ...
- 15 block	Sony CDU-31A/CDU-33A CD-ROM
-		  0 = /dev/sonycd	Sony CDU-31a CD-ROM
-
- 16 char	Non-SCSI scanners
-		  0 = /dev/gs4500	Genius 4500 handheld scanner
-
- 16 block	GoldStar CD-ROM
-		  0 = /dev/gscd		GoldStar CD-ROM
-
- 17 char	OBSOLETE (was Chase serial card)
-		  0 = /dev/ttyH0	First Chase port
-		  1 = /dev/ttyH1	Second Chase port
-		    ...
- 17 block	Optics Storage CD-ROM
-		  0 = /dev/optcd	Optics Storage CD-ROM
-
- 18 char	OBSOLETE (was Chase serial card - alternate devices)
-		  0 = /dev/cuh0		Callout device for ttyH0
-		  1 = /dev/cuh1		Callout device for ttyH1
-		    ...
- 18 block	Sanyo CD-ROM
-		  0 = /dev/sjcd		Sanyo CD-ROM
-
- 19 char	Cyclades serial card
-		  0 = /dev/ttyC0	First Cyclades port
-		    ...
-		 31 = /dev/ttyC31	32nd Cyclades port
-
- 19 block	"Double" compressed disk
-		  0 = /dev/double0	First compressed disk
-		    ...
-		  7 = /dev/double7	Eighth compressed disk
-		128 = /dev/cdouble0	Mirror of first compressed disk
-		    ...
-		135 = /dev/cdouble7	Mirror of eighth compressed disk
-
-		See the Double documentation for the meaning of the
-		mirror devices.
-
- 20 char	Cyclades serial card - alternate devices
-		  0 = /dev/cub0		Callout device for ttyC0
-		    ...
-		 31 = /dev/cub31	Callout device for ttyC31
-
- 20 block	Hitachi CD-ROM (under development)
-		  0 = /dev/hitcd	Hitachi CD-ROM
-
- 21 char	Generic SCSI access
-		  0 = /dev/sg0		First generic SCSI device
-		  1 = /dev/sg1		Second generic SCSI device
-		    ...
-
-		Most distributions name these /dev/sga, /dev/sgb...;
-		this sets an unnecessary limit of 26 SCSI devices in
-		the system and is counter to standard Linux
-		device-naming practice.
-
- 21 block	Acorn MFM hard drive interface
-		  0 = /dev/mfma		First MFM drive whole disk
-		 64 = /dev/mfmb		Second MFM drive whole disk
-
-		This device is used on the ARM-based Acorn RiscPC.
-		Partitions are handled the same way as for IDE disks
-		(see major number 3).
-
- 22 char	Digiboard serial card
-		  0 = /dev/ttyD0	First Digiboard port
-		  1 = /dev/ttyD1	Second Digiboard port
-		    ...
- 22 block	Second IDE hard disk/CD-ROM interface
-		  0 = /dev/hdc		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdd		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 23 char	Digiboard serial card - alternate devices
-		  0 = /dev/cud0		Callout device for ttyD0
-		  1 = /dev/cud1		Callout device for ttyD1
-		      ...
- 23 block	Mitsumi proprietary CD-ROM
-		  0 = /dev/mcd		Mitsumi CD-ROM
-
- 24 char	Stallion serial card
-		  0 = /dev/ttyE0	Stallion port 0 card 0
-		  1 = /dev/ttyE1	Stallion port 1 card 0
-		    ...
-		 64 = /dev/ttyE64	Stallion port 0 card 1
-		 65 = /dev/ttyE65	Stallion port 1 card 1
-		      ...
-		128 = /dev/ttyE128	Stallion port 0 card 2
-		129 = /dev/ttyE129	Stallion port 1 card 2
-		    ...
-		192 = /dev/ttyE192	Stallion port 0 card 3
-		193 = /dev/ttyE193	Stallion port 1 card 3
-		    ...
- 24 block	Sony CDU-535 CD-ROM
-		  0 = /dev/cdu535	Sony CDU-535 CD-ROM
-
- 25 char	Stallion serial card - alternate devices
-		  0 = /dev/cue0		Callout device for ttyE0
-		  1 = /dev/cue1		Callout device for ttyE1
-		    ...
-		 64 = /dev/cue64	Callout device for ttyE64
-		 65 = /dev/cue65	Callout device for ttyE65
-		    ...
-		128 = /dev/cue128	Callout device for ttyE128
-		129 = /dev/cue129	Callout device for ttyE129
-		    ...
-		192 = /dev/cue192	Callout device for ttyE192
-		193 = /dev/cue193	Callout device for ttyE193
-		      ...
- 25 block	First Matsushita (Panasonic/SoundBlaster) CD-ROM
-		  0 = /dev/sbpcd0	Panasonic CD-ROM controller 0 unit 0
-		  1 = /dev/sbpcd1	Panasonic CD-ROM controller 0 unit 1
-		  2 = /dev/sbpcd2	Panasonic CD-ROM controller 0 unit 2
-		  3 = /dev/sbpcd3	Panasonic CD-ROM controller 0 unit 3
-
- 26 char
-
- 26 block	Second Matsushita (Panasonic/SoundBlaster) CD-ROM
-		  0 = /dev/sbpcd4	Panasonic CD-ROM controller 1 unit 0
-		  1 = /dev/sbpcd5	Panasonic CD-ROM controller 1 unit 1
-		  2 = /dev/sbpcd6	Panasonic CD-ROM controller 1 unit 2
-		  3 = /dev/sbpcd7	Panasonic CD-ROM controller 1 unit 3
-
- 27 char	QIC-117 tape
-		  0 = /dev/qft0		Unit 0, rewind-on-close
-		  1 = /dev/qft1		Unit 1, rewind-on-close
-		  2 = /dev/qft2		Unit 2, rewind-on-close
-		  3 = /dev/qft3		Unit 3, rewind-on-close
-		  4 = /dev/nqft0	Unit 0, no rewind-on-close
-		  5 = /dev/nqft1	Unit 1, no rewind-on-close
-		  6 = /dev/nqft2	Unit 2, no rewind-on-close
-		  7 = /dev/nqft3	Unit 3, no rewind-on-close
-		 16 = /dev/zqft0	Unit 0, rewind-on-close, compression
-		 17 = /dev/zqft1	Unit 1, rewind-on-close, compression
-		 18 = /dev/zqft2	Unit 2, rewind-on-close, compression
-		 19 = /dev/zqft3	Unit 3, rewind-on-close, compression
-		 20 = /dev/nzqft0	Unit 0, no rewind-on-close, compression
-		 21 = /dev/nzqft1	Unit 1, no rewind-on-close, compression
-		 22 = /dev/nzqft2	Unit 2, no rewind-on-close, compression
-		 23 = /dev/nzqft3	Unit 3, no rewind-on-close, compression
-		 32 = /dev/rawqft0	Unit 0, rewind-on-close, no file marks
-		 33 = /dev/rawqft1	Unit 1, rewind-on-close, no file marks
-		 34 = /dev/rawqft2	Unit 2, rewind-on-close, no file marks
-		 35 = /dev/rawqft3	Unit 3, rewind-on-close, no file marks
-		 36 = /dev/nrawqft0	Unit 0, no rewind-on-close, no file marks
-		 37 = /dev/nrawqft1	Unit 1, no rewind-on-close, no file marks
-		 38 = /dev/nrawqft2	Unit 2, no rewind-on-close, no file marks
-		 39 = /dev/nrawqft3	Unit 3, no rewind-on-close, no file marks
-
- 27 block	Third Matsushita (Panasonic/SoundBlaster) CD-ROM
-		  0 = /dev/sbpcd8	Panasonic CD-ROM controller 2 unit 0
-		  1 = /dev/sbpcd9	Panasonic CD-ROM controller 2 unit 1
-		  2 = /dev/sbpcd10	Panasonic CD-ROM controller 2 unit 2
-		  3 = /dev/sbpcd11	Panasonic CD-ROM controller 2 unit 3
-
- 28 char	Stallion serial card - card programming
-		  0 = /dev/staliomem0	First Stallion card I/O memory
-		  1 = /dev/staliomem1	Second Stallion card I/O memory
-		  2 = /dev/staliomem2	Third Stallion card I/O memory
-		  3 = /dev/staliomem3	Fourth Stallion card I/O memory
-
- 28 char	Atari SLM ACSI laser printer (68k/Atari)
-		  0 = /dev/slm0		First SLM laser printer
-		  1 = /dev/slm1		Second SLM laser printer
-		    ...
- 28 block	Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
-		  0 = /dev/sbpcd12	Panasonic CD-ROM controller 3 unit 0
-		  1 = /dev/sbpcd13	Panasonic CD-ROM controller 3 unit 1
-		  2 = /dev/sbpcd14	Panasonic CD-ROM controller 3 unit 2
-		  3 = /dev/sbpcd15	Panasonic CD-ROM controller 3 unit 3
-
- 28 block	ACSI disk (68k/Atari)
-		  0 = /dev/ada		First ACSI disk whole disk
-		 16 = /dev/adb		Second ACSI disk whole disk
-		 32 = /dev/adc		Third ACSI disk whole disk
-		    ...
-		240 = /dev/adp		16th ACSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15, like SCSI.
-
- 29 char	Universal frame buffer
-		  0 = /dev/fb0		First frame buffer
-		  1 = /dev/fb1		Second frame buffer
-		    ...
-		 31 = /dev/fb31		32nd frame buffer
-
- 29 block	Aztech/Orchid/Okano/Wearnes CD-ROM
-		  0 = /dev/aztcd	Aztech CD-ROM
-
- 30 char	iBCS-2 compatibility devices
-		  0 = /dev/socksys	Socket access
-		  1 = /dev/spx		SVR3 local X interface
-		 32 = /dev/inet/ip	Network access
-		 33 = /dev/inet/icmp
-		 34 = /dev/inet/ggp
-		 35 = /dev/inet/ipip
-		 36 = /dev/inet/tcp
-		 37 = /dev/inet/egp
-		 38 = /dev/inet/pup
-		 39 = /dev/inet/udp
-		 40 = /dev/inet/idp
-		 41 = /dev/inet/rawip
-
-		Additionally, iBCS-2 requires the following links:
-
-		/dev/ip -> /dev/inet/ip
-		/dev/icmp -> /dev/inet/icmp
-		/dev/ggp -> /dev/inet/ggp
-		/dev/ipip -> /dev/inet/ipip
-		/dev/tcp -> /dev/inet/tcp
-		/dev/egp -> /dev/inet/egp
-		/dev/pup -> /dev/inet/pup
-		/dev/udp -> /dev/inet/udp
-		/dev/idp -> /dev/inet/idp
-		/dev/rawip -> /dev/inet/rawip
-		/dev/inet/arp -> /dev/inet/udp
-		/dev/inet/rip -> /dev/inet/udp
-		/dev/nfsd -> /dev/socksys
-		/dev/X0R -> /dev/null (? apparently not required ?)
-
- 30 block	Philips LMS CM-205 CD-ROM
-		  0 = /dev/cm205cd	Philips LMS CM-205 CD-ROM
-
-		/dev/lmscd is an older name for this device.  This
-		driver does not work with the CM-205MS CD-ROM.
-
- 31 char	MPU-401 MIDI
-		  0 = /dev/mpu401data	MPU-401 data port
-		  1 = /dev/mpu401stat	MPU-401 status port
-
- 31 block	ROM/flash memory card
-		  0 = /dev/rom0		First ROM card (rw)
-		      ...
-		  7 = /dev/rom7		Eighth ROM card (rw)
-		  8 = /dev/rrom0	First ROM card (ro)
-		    ...
-		 15 = /dev/rrom7	Eighth ROM card (ro)
-		 16 = /dev/flash0	First flash memory card (rw)
-		    ...
-		 23 = /dev/flash7	Eighth flash memory card (rw)
-		 24 = /dev/rflash0	First flash memory card (ro)
-		    ...
-		 31 = /dev/rflash7	Eighth flash memory card (ro)
-
-		The read-write (rw) devices support back-caching
-		written data in RAM, as well as writing to flash RAM
-		devices.  The read-only devices (ro) support reading
-		only.
-
- 32 char	Specialix serial card
-		  0 = /dev/ttyX0	First Specialix port
-		  1 = /dev/ttyX1	Second Specialix port
-		    ...
- 32 block	Philips LMS CM-206 CD-ROM
-		  0 = /dev/cm206cd	Philips LMS CM-206 CD-ROM
-
- 33 char	Specialix serial card - alternate devices
-		  0 = /dev/cux0		Callout device for ttyX0
-		  1 = /dev/cux1		Callout device for ttyX1
-		    ...
- 33 block	Third IDE hard disk/CD-ROM interface
-		  0 = /dev/hde		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdf		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 34 char	Z8530 HDLC driver
-		  0 = /dev/scc0		First Z8530, first port
-		  1 = /dev/scc1		First Z8530, second port
-		  2 = /dev/scc2		Second Z8530, first port
-		  3 = /dev/scc3		Second Z8530, second port
-		    ...
-
-		In a previous version these devices were named
-		/dev/sc1 for /dev/scc0, /dev/sc2 for /dev/scc1, and so
-		on.
-
- 34 block	Fourth IDE hard disk/CD-ROM interface
-		  0 = /dev/hdg		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdh		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 35 char	tclmidi MIDI driver
-		  0 = /dev/midi0	First MIDI port, kernel timed
-		  1 = /dev/midi1	Second MIDI port, kernel timed
-		  2 = /dev/midi2	Third MIDI port, kernel timed
-		  3 = /dev/midi3	Fourth MIDI port, kernel timed
-		 64 = /dev/rmidi0	First MIDI port, untimed
-		 65 = /dev/rmidi1	Second MIDI port, untimed
-		 66 = /dev/rmidi2	Third MIDI port, untimed
-		 67 = /dev/rmidi3	Fourth MIDI port, untimed
-		128 = /dev/smpte0	First MIDI port, SMPTE timed
-		129 = /dev/smpte1	Second MIDI port, SMPTE timed
-		130 = /dev/smpte2	Third MIDI port, SMPTE timed
-		131 = /dev/smpte3	Fourth MIDI port, SMPTE timed
-
- 35 block	Slow memory ramdisk
-		  0 = /dev/slram	Slow memory ramdisk
-
- 36 char	Netlink support
-		  0 = /dev/route	Routing, device updates, kernel to user
-		  1 = /dev/skip		enSKIP security cache control
-		  3 = /dev/fwmonitor	Firewall packet copies
-		 16 = /dev/tap0		First Ethertap device
-		    ...
-		 31 = /dev/tap15	16th Ethertap device
-
- 36 block	OBSOLETE (was MCA ESDI hard disk)
-
- 37 char	IDE tape
-		  0 = /dev/ht0		First IDE tape
-		  1 = /dev/ht1		Second IDE tape
-		    ...
-		128 = /dev/nht0		First IDE tape, no rewind-on-close
-		129 = /dev/nht1		Second IDE tape, no rewind-on-close
-		    ...
-
-		Currently, only one IDE tape drive is supported.
-
- 37 block	Zorro II ramdisk
-		  0 = /dev/z2ram	Zorro II ramdisk
-
- 38 char	Myricom PCI Myrinet board
-		  0 = /dev/mlanai0	First Myrinet board
-		  1 = /dev/mlanai1	Second Myrinet board
-		    ...
-
-		This device is used for status query, board control
-		and "user level packet I/O."  This board is also
-		accessible as a standard networking "eth" device.
-
- 38 block	OBSOLETE (was Linux/AP+)
-
- 39 char	ML-16P experimental I/O board
-		  0 = /dev/ml16pa-a0	First card, first analog channel
-		  1 = /dev/ml16pa-a1	First card, second analog channel
-		    ...
-		 15 = /dev/ml16pa-a15	First card, 16th analog channel
-		 16 = /dev/ml16pa-d	First card, digital lines
-		 17 = /dev/ml16pa-c0	First card, first counter/timer
-		 18 = /dev/ml16pa-c1	First card, second counter/timer
-		 19 = /dev/ml16pa-c2	First card, third counter/timer
-		 32 = /dev/ml16pb-a0	Second card, first analog channel
-		 33 = /dev/ml16pb-a1	Second card, second analog channel
-		    ...
-		 47 = /dev/ml16pb-a15	Second card, 16th analog channel
-		 48 = /dev/ml16pb-d	Second card, digital lines
-		 49 = /dev/ml16pb-c0	Second card, first counter/timer
-		 50 = /dev/ml16pb-c1	Second card, second counter/timer
-		 51 = /dev/ml16pb-c2	Second card, third counter/timer
-		      ...
- 39 block
-
- 40 char
-
- 40 block
-
- 41 char	Yet Another Micro Monitor
-		  0 = /dev/yamm		Yet Another Micro Monitor
-
- 41 block
-
- 42 char	Demo/sample use
-
- 42 block	Demo/sample use
-
-		This number is intended for use in sample code, as
-		well as a general "example" device number.  It
-		should never be used for a device driver that is being
-		distributed; either obtain an official number or use
-		the local/experimental range.  The sudden addition or
-		removal of a driver with this number should not cause
-		ill effects to the system (bugs excepted.)
-
-		IN PARTICULAR, ANY DISTRIBUTION WHICH CONTAINS A
-		DEVICE DRIVER USING MAJOR NUMBER 42 IS NONCOMPLIANT.
-
- 43 char	isdn4linux virtual modem
-		  0 = /dev/ttyI0	First virtual modem
-		    ...
-		 63 = /dev/ttyI63	64th virtual modem
-
- 43 block	Network block devices
-		  0 = /dev/nb0		First network block device
-		  1 = /dev/nb1		Second network block device
-		    ...
-
-		Network Block Device is somehow similar to loopback
-		devices: If you read from it, it sends packet across
-		network asking server for data. If you write to it, it
-		sends packet telling server to write. It could be used
-		to mounting filesystems over the net, swapping over
-		the net, implementing block device in userland etc.
-
- 44 char	isdn4linux virtual modem - alternate devices
-		  0 = /dev/cui0		Callout device for ttyI0
-		    ...
-		 63 = /dev/cui63	Callout device for ttyI63
-
- 44 block	Flash Translation Layer (FTL) filesystems
-		  0 = /dev/ftla		FTL on first Memory Technology Device
-		 16 = /dev/ftlb		FTL on second Memory Technology Device
-		 32 = /dev/ftlc		FTL on third Memory Technology Device
-		    ...
-		240 = /dev/ftlp		FTL on 16th Memory Technology Device
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the partition
-		limit is 15 rather than 63 per disk (same as SCSI.)
-
- 45 char	isdn4linux ISDN BRI driver
-		  0 = /dev/isdn0	First virtual B channel raw data
-		    ...
-		 63 = /dev/isdn63	64th virtual B channel raw data
-		 64 = /dev/isdnctrl0	First channel control/debug
-		    ...
-		127 = /dev/isdnctrl63	64th channel control/debug
-
-		128 = /dev/ippp0	First SyncPPP device
-		    ...
-		191 = /dev/ippp63	64th SyncPPP device
-
-		255 = /dev/isdninfo	ISDN monitor interface
-
- 45 block	Parallel port IDE disk devices
-		  0 = /dev/pda		First parallel port IDE disk
-		 16 = /dev/pdb		Second parallel port IDE disk
-		 32 = /dev/pdc		Third parallel port IDE disk
-		 48 = /dev/pdd		Fourth parallel port IDE disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the partition
-		limit is 15 rather than 63 per disk.
-
- 46 char	Comtrol Rocketport serial card
-		  0 = /dev/ttyR0	First Rocketport port
-		  1 = /dev/ttyR1	Second Rocketport port
-		    ...
- 46 block	Parallel port ATAPI CD-ROM devices
-		  0 = /dev/pcd0		First parallel port ATAPI CD-ROM
-		  1 = /dev/pcd1		Second parallel port ATAPI CD-ROM
-		  2 = /dev/pcd2		Third parallel port ATAPI CD-ROM
-		  3 = /dev/pcd3		Fourth parallel port ATAPI CD-ROM
-
- 47 char	Comtrol Rocketport serial card - alternate devices
-		  0 = /dev/cur0		Callout device for ttyR0
-		  1 = /dev/cur1		Callout device for ttyR1
-		    ...
- 47 block	Parallel port ATAPI disk devices
-		  0 = /dev/pf0		First parallel port ATAPI disk
-		  1 = /dev/pf1		Second parallel port ATAPI disk
-		  2 = /dev/pf2		Third parallel port ATAPI disk
-		  3 = /dev/pf3		Fourth parallel port ATAPI disk
-
-		This driver is intended for floppy disks and similar
-		devices and hence does not support partitioning.
-
- 48 char	SDL RISCom serial card
-		  0 = /dev/ttyL0	First RISCom port
-		  1 = /dev/ttyL1	Second RISCom port
-		    ...
- 48 block	Mylex DAC960 PCI RAID controller; first controller
-		  0 = /dev/rd/c0d0	First disk, whole disk
-		  8 = /dev/rd/c0d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c0d31	32nd disk, whole disk
-
-		For partitions add:
-		  0 = /dev/rd/c?d?	Whole disk
-		  1 = /dev/rd/c?d?p1	First partition
-		    ...
-		  7 = /dev/rd/c?d?p7	Seventh partition
-
- 49 char	SDL RISCom serial card - alternate devices
-		  0 = /dev/cul0		Callout device for ttyL0
-		  1 = /dev/cul1		Callout device for ttyL1
-		    ...
- 49 block	Mylex DAC960 PCI RAID controller; second controller
-		  0 = /dev/rd/c1d0	First disk, whole disk
-		  8 = /dev/rd/c1d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c1d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
- 50 char	Reserved for GLINT
-
- 50 block	Mylex DAC960 PCI RAID controller; third controller
-		  0 = /dev/rd/c2d0	First disk, whole disk
-		  8 = /dev/rd/c2d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c2d31	32nd disk, whole disk
-
- 51 char	Baycom radio modem OR Radio Tech BIM-XXX-RS232 radio modem
-		  0 = /dev/bc0		First Baycom radio modem
-		  1 = /dev/bc1		Second Baycom radio modem
-		    ...
- 51 block	Mylex DAC960 PCI RAID controller; fourth controller
-		  0 = /dev/rd/c3d0	First disk, whole disk
-		  8 = /dev/rd/c3d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c3d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
- 52 char	Spellcaster DataComm/BRI ISDN card
-		  0 = /dev/dcbri0	First DataComm card
-		  1 = /dev/dcbri1	Second DataComm card
-		  2 = /dev/dcbri2	Third DataComm card
-		  3 = /dev/dcbri3	Fourth DataComm card
-
- 52 block	Mylex DAC960 PCI RAID controller; fifth controller
-		  0 = /dev/rd/c4d0	First disk, whole disk
-		  8 = /dev/rd/c4d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c4d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
- 53 char	BDM interface for remote debugging MC683xx microcontrollers
-		  0 = /dev/pd_bdm0	PD BDM interface on lp0
-		  1 = /dev/pd_bdm1	PD BDM interface on lp1
-		  2 = /dev/pd_bdm2	PD BDM interface on lp2
-		  4 = /dev/icd_bdm0	ICD BDM interface on lp0
-		  5 = /dev/icd_bdm1	ICD BDM interface on lp1
-		  6 = /dev/icd_bdm2	ICD BDM interface on lp2
-
-		This device is used for the interfacing to the MC683xx
-		microcontrollers via Background Debug Mode by use of a
-		Parallel Port interface. PD is the Motorola Public
-		Domain Interface and ICD is the commercial interface
-		by P&E.
-
- 53 block	Mylex DAC960 PCI RAID controller; sixth controller
-		  0 = /dev/rd/c5d0	First disk, whole disk
-		  8 = /dev/rd/c5d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c5d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
- 54 char	Electrocardiognosis Holter serial card
-		  0 = /dev/holter0	First Holter port
-		  1 = /dev/holter1	Second Holter port
-		  2 = /dev/holter2	Third Holter port
-
-		A custom serial card used by Electrocardiognosis SRL
-		<mseritan@ottonel.pub.ro> to transfer data from Holter
-		24-hour heart monitoring equipment.
-
- 54 block	Mylex DAC960 PCI RAID controller; seventh controller
-		  0 = /dev/rd/c6d0	First disk, whole disk
-		  8 = /dev/rd/c6d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c6d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
- 55 char	DSP56001 digital signal processor
-		  0 = /dev/dsp56k	First DSP56001
-
- 55 block	Mylex DAC960 PCI RAID controller; eighth controller
-		  0 = /dev/rd/c7d0	First disk, whole disk
-		  8 = /dev/rd/c7d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c7d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
- 56 char	Apple Desktop Bus
-		  0 = /dev/adb		ADB bus control
-
-		Additional devices will be added to this number, all
-		starting with /dev/adb.
-
- 56 block	Fifth IDE hard disk/CD-ROM interface
-		  0 = /dev/hdi		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdj		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 57 char	Hayes ESP serial card
-		  0 = /dev/ttyP0	First ESP port
-		  1 = /dev/ttyP1	Second ESP port
-		    ...
-
- 57 block	Sixth IDE hard disk/CD-ROM interface
-		  0 = /dev/hdk		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdl		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 58 char	Hayes ESP serial card - alternate devices
-		  0 = /dev/cup0		Callout device for ttyP0
-		  1 = /dev/cup1		Callout device for ttyP1
-		    ...
-
- 58 block	Reserved for logical volume manager
-
- 59 char	sf firewall package
-		  0 = /dev/firewall	Communication with sf kernel module
-
- 59 block	Generic PDA filesystem device
-		  0 = /dev/pda0		First PDA device
-		  1 = /dev/pda1		Second PDA device
-		    ...
-
-		The pda devices are used to mount filesystems on
-		remote pda's (basically slow handheld machines with
-		proprietary OS's and limited memory and storage
-		running small fs translation drivers) through serial /
-		IRDA / parallel links.
-
-		NAMING CONFLICT -- PROPOSED REVISED NAME /dev/rpda0 etc
-
- 60-63 char	LOCAL/EXPERIMENTAL USE
-
- 60-63 block	LOCAL/EXPERIMENTAL USE
-		Allocated for local/experimental use.  For devices not
-		assigned official numbers, these ranges should be
-		used in order to avoid conflicting with future assignments.
-
- 64 char	ENskip kernel encryption package
-		  0 = /dev/enskip	Communication with ENskip kernel module
-
- 64 block	Scramdisk/DriveCrypt encrypted devices
-		  0 = /dev/scramdisk/master    Master node for ioctls
-		  1 = /dev/scramdisk/1         First encrypted device
-		  2 = /dev/scramdisk/2         Second encrypted device
-		  ...
-		255 = /dev/scramdisk/255       255th encrypted device
-
-		The filename of the encrypted container and the passwords
-		are sent via ioctls (using the sdmount tool) to the master
-		node which then activates them via one of the
-		/dev/scramdisk/x nodes for loop mounting (all handled
-		through the sdmount tool).
-
-		Requested by: andy@scramdisklinux.org
-
- 65 char	Sundance "plink" Transputer boards (obsolete, unused)
-		  0 = /dev/plink0	First plink device
-		  1 = /dev/plink1	Second plink device
-		  2 = /dev/plink2	Third plink device
-		  3 = /dev/plink3	Fourth plink device
-		 64 = /dev/rplink0	First plink device, raw
-		 65 = /dev/rplink1	Second plink device, raw
-		 66 = /dev/rplink2	Third plink device, raw
-		 67 = /dev/rplink3	Fourth plink device, raw
-		128 = /dev/plink0d	First plink device, debug
-		129 = /dev/plink1d	Second plink device, debug
-		130 = /dev/plink2d	Third plink device, debug
-		131 = /dev/plink3d	Fourth plink device, debug
-		192 = /dev/rplink0d	First plink device, raw, debug
-		193 = /dev/rplink1d	Second plink device, raw, debug
-		194 = /dev/rplink2d	Third plink device, raw, debug
-		195 = /dev/rplink3d	Fourth plink device, raw, debug
-
-		This is a commercial driver; contact James Howes
-		<jth@prosig.demon.co.uk> for information.
-
- 65 block	SCSI disk devices (16-31)
-		  0 = /dev/sdq		17th SCSI disk whole disk
-		 16 = /dev/sdr		18th SCSI disk whole disk
-		 32 = /dev/sds		19th SCSI disk whole disk
-		    ...
-		240 = /dev/sdaf		32nd SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 66 char	YARC PowerPC PCI coprocessor card
-		  0 = /dev/yppcpci0	First YARC card
-		  1 = /dev/yppcpci1	Second YARC card
-		    ...
-
- 66 block	SCSI disk devices (32-47)
-		  0 = /dev/sdag		33th SCSI disk whole disk
-		 16 = /dev/sdah		34th SCSI disk whole disk
-		 32 = /dev/sdai		35th SCSI disk whole disk
-		    ...
-		240 = /dev/sdav		48nd SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 67 char	Coda network file system
-		  0 = /dev/cfs0		Coda cache manager
-
-		See http://www.coda.cs.cmu.edu for information about Coda.
-
- 67 block	SCSI disk devices (48-63)
-		  0 = /dev/sdaw		49th SCSI disk whole disk
-		 16 = /dev/sdax		50th SCSI disk whole disk
-		 32 = /dev/sday		51st SCSI disk whole disk
-		    ...
-		240 = /dev/sdbl		64th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 68 char	CAPI 2.0 interface
-		  0 = /dev/capi20	Control device
-		  1 = /dev/capi20.00	First CAPI 2.0 application
-		  2 = /dev/capi20.01	Second CAPI 2.0 application
-		    ...
-		 20 = /dev/capi20.19	19th CAPI 2.0 application
-
-		ISDN CAPI 2.0 driver for use with CAPI 2.0
-		applications; currently supports the AVM B1 card.
-
- 68 block	SCSI disk devices (64-79)
-		  0 = /dev/sdbm		65th SCSI disk whole disk
-		 16 = /dev/sdbn		66th SCSI disk whole disk
-		 32 = /dev/sdbo		67th SCSI disk whole disk
-		    ...
-		240 = /dev/sdcb		80th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 69 char	MA16 numeric accelerator card
-		  0 = /dev/ma16		Board memory access
-
- 69 block	SCSI disk devices (80-95)
-		  0 = /dev/sdcc		81st SCSI disk whole disk
-		 16 = /dev/sdcd		82nd SCSI disk whole disk
-		 32 = /dev/sdce		83th SCSI disk whole disk
-		    ...
-		240 = /dev/sdcr		96th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 70 char	SpellCaster Protocol Services Interface
-		  0 = /dev/apscfg	Configuration interface
-		  1 = /dev/apsauth	Authentication interface
-		  2 = /dev/apslog	Logging interface
-		  3 = /dev/apsdbg	Debugging interface
-		 64 = /dev/apsisdn	ISDN command interface
-		 65 = /dev/apsasync	Async command interface
-		128 = /dev/apsmon	Monitor interface
-
- 70 block	SCSI disk devices (96-111)
-		  0 = /dev/sdcs		97th SCSI disk whole disk
-		 16 = /dev/sdct		98th SCSI disk whole disk
-		 32 = /dev/sdcu		99th SCSI disk whole disk
-		    ...
-		240 = /dev/sddh		112nd SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 71 char	Computone IntelliPort II serial card
-		  0 = /dev/ttyF0	IntelliPort II board 0, port 0
-		  1 = /dev/ttyF1	IntelliPort II board 0, port 1
-		    ...
-		 63 = /dev/ttyF63	IntelliPort II board 0, port 63
-		 64 = /dev/ttyF64	IntelliPort II board 1, port 0
-		 65 = /dev/ttyF65	IntelliPort II board 1, port 1
-		    ...
-		127 = /dev/ttyF127	IntelliPort II board 1, port 63
-		128 = /dev/ttyF128	IntelliPort II board 2, port 0
-		129 = /dev/ttyF129	IntelliPort II board 2, port 1
-		    ...
-		191 = /dev/ttyF191	IntelliPort II board 2, port 63
-		192 = /dev/ttyF192	IntelliPort II board 3, port 0
-		193 = /dev/ttyF193	IntelliPort II board 3, port 1
-		    ...
-		255 = /dev/ttyF255	IntelliPort II board 3, port 63
-
- 71 block	SCSI disk devices (112-127)
-		  0 = /dev/sddi		113th SCSI disk whole disk
-		 16 = /dev/sddj		114th SCSI disk whole disk
-		 32 = /dev/sddk		115th SCSI disk whole disk
-		    ...
-		240 = /dev/sddx		128th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 72 char	Computone IntelliPort II serial card - alternate devices
-		  0 = /dev/cuf0		Callout device for ttyF0
-		  1 = /dev/cuf1		Callout device for ttyF1
-		    ...
-		 63 = /dev/cuf63	Callout device for ttyF63
-		 64 = /dev/cuf64	Callout device for ttyF64
-		 65 = /dev/cuf65	Callout device for ttyF65
-		    ...
-		127 = /dev/cuf127	Callout device for ttyF127
-		128 = /dev/cuf128	Callout device for ttyF128
-		129 = /dev/cuf129	Callout device for ttyF129
-		    ...
-		191 = /dev/cuf191	Callout device for ttyF191
-		192 = /dev/cuf192	Callout device for ttyF192
-		193 = /dev/cuf193	Callout device for ttyF193
-		    ...
-		255 = /dev/cuf255	Callout device for ttyF255
-
- 72 block	Compaq Intelligent Drive Array, first controller
-		  0 = /dev/ida/c0d0	First logical drive whole disk
-		 16 = /dev/ida/c0d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c0d15	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
- 73 char	Computone IntelliPort II serial card - control devices
-		  0 = /dev/ip2ipl0	Loadware device for board 0
-		  1 = /dev/ip2stat0	Status device for board 0
-		  4 = /dev/ip2ipl1	Loadware device for board 1
-		  5 = /dev/ip2stat1	Status device for board 1
-		  8 = /dev/ip2ipl2	Loadware device for board 2
-		  9 = /dev/ip2stat2	Status device for board 2
-		 12 = /dev/ip2ipl3	Loadware device for board 3
-		 13 = /dev/ip2stat3	Status device for board 3
-
- 73 block	Compaq Intelligent Drive Array, second controller
-		  0 = /dev/ida/c1d0	First logical drive whole disk
-		 16 = /dev/ida/c1d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c1d15	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
- 74 char	SCI bridge
-		  0 = /dev/SCI/0	SCI device 0
-		  1 = /dev/SCI/1	SCI device 1
-		    ...
-
-		Currently for Dolphin Interconnect Solutions' PCI-SCI
-		bridge.
-
- 74 block	Compaq Intelligent Drive Array, third controller
-		  0 = /dev/ida/c2d0	First logical drive whole disk
-		 16 = /dev/ida/c2d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c2d15	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
- 75 char	Specialix IO8+ serial card
-		  0 = /dev/ttyW0	First IO8+ port, first card
-		  1 = /dev/ttyW1	Second IO8+ port, first card
-		    ...
-		  8 = /dev/ttyW8	First IO8+ port, second card
-		    ...
-
- 75 block	Compaq Intelligent Drive Array, fourth controller
-		  0 = /dev/ida/c3d0	First logical drive whole disk
-		 16 = /dev/ida/c3d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c3d15	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
- 76 char	Specialix IO8+ serial card - alternate devices
-		  0 = /dev/cuw0		Callout device for ttyW0
-		  1 = /dev/cuw1		Callout device for ttyW1
-		    ...
-		  8 = /dev/cuw8		Callout device for ttyW8
-		    ...
-
- 76 block	Compaq Intelligent Drive Array, fifth controller
-		  0 = /dev/ida/c4d0	First logical drive whole disk
-		 16 = /dev/ida/c4d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c4d15	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-
- 77 char	ComScire Quantum Noise Generator
-		  0 = /dev/qng		ComScire Quantum Noise Generator
-
- 77 block	Compaq Intelligent Drive Array, sixth controller
-		  0 = /dev/ida/c5d0	First logical drive whole disk
-		 16 = /dev/ida/c5d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c5d15	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
- 78 char	PAM Software's multimodem boards
-		  0 = /dev/ttyM0	First PAM modem
-		  1 = /dev/ttyM1	Second PAM modem
-		    ...
-
- 78 block	Compaq Intelligent Drive Array, seventh controller
-		  0 = /dev/ida/c6d0	First logical drive whole disk
-		 16 = /dev/ida/c6d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c6d15	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
- 79 char	PAM Software's multimodem boards - alternate devices
-		  0 = /dev/cum0		Callout device for ttyM0
-		  1 = /dev/cum1		Callout device for ttyM1
-		    ...
-
- 79 block	Compaq Intelligent Drive Array, eighth controller
-		  0 = /dev/ida/c7d0	First logical drive whole disk
-		 16 = /dev/ida/c7d1	Second logical drive whole disk
-		    ...
-		240 = /dev/ida/c715	16th logical drive whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
- 80 char	Photometrics AT200 CCD camera
-		  0 = /dev/at200	Photometrics AT200 CCD camera
-
- 80 block	I2O hard disk
-		  0 = /dev/i2o/hda	First I2O hard disk, whole disk
-		 16 = /dev/i2o/hdb	Second I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hdp	16th I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 81 char	video4linux
-		  0 = /dev/video0	Video capture/overlay device
-		    ...
-		 63 = /dev/video63	Video capture/overlay device
-		 64 = /dev/radio0	Radio device
-		    ...
-		127 = /dev/radio63	Radio device
-		128 = /dev/swradio0	Software Defined Radio device
-		    ...
-		191 = /dev/swradio63	Software Defined Radio device
-		224 = /dev/vbi0		Vertical blank interrupt
-		    ...
-		255 = /dev/vbi31	Vertical blank interrupt
-
-		Minor numbers are allocated dynamically unless
-		CONFIG_VIDEO_FIXED_MINOR_RANGES (default n)
-		configuration option is set.
-
- 81 block	I2O hard disk
-		  0 = /dev/i2o/hdq	17th I2O hard disk, whole disk
-		 16 = /dev/i2o/hdr	18th I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hdaf	32nd I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 82 char	WiNRADiO communications receiver card
-		  0 = /dev/winradio0	First WiNRADiO card
-		  1 = /dev/winradio1	Second WiNRADiO card
-		    ...
-
-		The driver and documentation may be obtained from
-		http://www.winradio.com/
-
- 82 block	I2O hard disk
-		  0 = /dev/i2o/hdag	33rd I2O hard disk, whole disk
-		 16 = /dev/i2o/hdah	34th I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hdav	48th I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 83 char	Matrox mga_vid video driver
- 		 0 = /dev/mga_vid0	1st video card
-		 1 = /dev/mga_vid1	2nd video card
-		 2 = /dev/mga_vid2	3rd video card
-		  ...
-	        15 = /dev/mga_vid15	16th video card
-
- 83 block	I2O hard disk
-		  0 = /dev/i2o/hdaw	49th I2O hard disk, whole disk
-		 16 = /dev/i2o/hdax	50th I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hdbl	64th I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 84 char	Ikon 1011[57] Versatec Greensheet Interface
-		  0 = /dev/ihcp0	First Greensheet port
-		  1 = /dev/ihcp1	Second Greensheet port
-
- 84 block	I2O hard disk
-		  0 = /dev/i2o/hdbm	65th I2O hard disk, whole disk
-		 16 = /dev/i2o/hdbn	66th I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hdcb	80th I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 85 char	Linux/SGI shared memory input queue
-		  0 = /dev/shmiq	Master shared input queue
-		  1 = /dev/qcntl0	First device pushed
-		  2 = /dev/qcntl1	Second device pushed
-		    ...
-
- 85 block	I2O hard disk
-		  0 = /dev/i2o/hdcc	81st I2O hard disk, whole disk
-		 16 = /dev/i2o/hdcd	82nd I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hdcr	96th I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 86 char	SCSI media changer
-		  0 = /dev/sch0		First SCSI media changer
-		  1 = /dev/sch1		Second SCSI media changer
-		    ...
-
- 86 block	I2O hard disk
-		  0 = /dev/i2o/hdcs	97th I2O hard disk, whole disk
-		 16 = /dev/i2o/hdct	98th I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hddh	112th I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 87 char	Sony Control-A1 stereo control bus
-		  0 = /dev/controla0	First device on chain
-		  1 = /dev/controla1	Second device on chain
-		    ...
-
- 87 block	I2O hard disk
-		  0 = /dev/i2o/hddi	113rd I2O hard disk, whole disk
-		 16 = /dev/i2o/hddj	114th I2O hard disk, whole disk
-		    ...
-		240 = /dev/i2o/hddx	128th I2O hard disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 88 char	COMX synchronous serial card
-		  0 = /dev/comx0	COMX channel 0
-		  1 = /dev/comx1	COMX channel 1
-		    ...
-
- 88 block	Seventh IDE hard disk/CD-ROM interface
-		  0 = /dev/hdm		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdn		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 89 char	I2C bus interface
-		  0 = /dev/i2c-0	First I2C adapter
-		  1 = /dev/i2c-1	Second I2C adapter
-		    ...
-
- 89 block	Eighth IDE hard disk/CD-ROM interface
-		  0 = /dev/hdo		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdp		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 90 char	Memory Technology Device (RAM, ROM, Flash)
-		  0 = /dev/mtd0		First MTD (rw)
-		  1 = /dev/mtdr0	First MTD (ro)
-		    ...
-		 30 = /dev/mtd15	16th MTD (rw)
-		 31 = /dev/mtdr15	16th MTD (ro)
-
- 90 block	Ninth IDE hard disk/CD-ROM interface
-		  0 = /dev/hdq		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdr		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 91 char	CAN-Bus devices
-		  0 = /dev/can0		First CAN-Bus controller
-		  1 = /dev/can1		Second CAN-Bus controller
-		    ...
-
- 91 block	Tenth IDE hard disk/CD-ROM interface
-		  0 = /dev/hds		Master: whole disk (or CD-ROM)
-		 64 = /dev/hdt		Slave: whole disk (or CD-ROM)
-
-		Partitions are handled the same way as for the first
-		interface (see major number 3).
-
- 92 char	Reserved for ith Kommunikationstechnik MIC ISDN card
-
- 92 block	PPDD encrypted disk driver
-		  0 = /dev/ppdd0	First encrypted disk
-		  1 = /dev/ppdd1	Second encrypted disk
-		    ...
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
- 93 char
-
- 93 block	NAND Flash Translation Layer filesystem
-		  0 = /dev/nftla	First NFTL layer
-		 16 = /dev/nftlb	Second NFTL layer
-		    ...
-		240 = /dev/nftlp	16th NTFL layer
-
- 94 char
-
- 94 block	IBM S/390 DASD block storage
-    		  0 = /dev/dasda First DASD device, major
-    		  1 = /dev/dasda1 First DASD device, block 1
-	    	  2 = /dev/dasda2 First DASD device, block 2
-    		  3 = /dev/dasda3 First DASD device, block 3
-    		  4 = /dev/dasdb Second DASD device, major
-    		  5 = /dev/dasdb1 Second DASD device, block 1
-    		  6 = /dev/dasdb2 Second DASD device, block 2
-    		  7 = /dev/dasdb3 Second DASD device, block 3
-		    ...
-
- 95 char	IP filter
-		  0 = /dev/ipl		Filter control device/log file
-		  1 = /dev/ipnat	NAT control device/log file
-		  2 = /dev/ipstate	State information log file
-		  3 = /dev/ipauth	Authentication control device/log file
-		    ...
-
- 96 char	Parallel port ATAPI tape devices
-		  0 = /dev/pt0		First parallel port ATAPI tape
-		  1 = /dev/pt1		Second parallel port ATAPI tape
-		    ...
-		128 = /dev/npt0		First p.p. ATAPI tape, no rewind
-		129 = /dev/npt1		Second p.p. ATAPI tape, no rewind
-		    ...
-
- 96 block	Inverse NAND Flash Translation Layer
-		  0 = /dev/inftla First INFTL layer
-		 16 = /dev/inftlb Second INFTL layer
-		    ...
-		240 = /dev/inftlp	16th INTFL layer
-
- 97 char	Parallel port generic ATAPI interface
-		  0 = /dev/pg0		First parallel port ATAPI device
-		  1 = /dev/pg1		Second parallel port ATAPI device
-		  2 = /dev/pg2		Third parallel port ATAPI device
-		  3 = /dev/pg3		Fourth parallel port ATAPI device
-
-		These devices support the same API as the generic SCSI
-		devices.
-
- 98 char	Control and Measurement Device (comedi)
-		  0 = /dev/comedi0	First comedi device
-		  1 = /dev/comedi1	Second comedi device
-		    ...
-
-		See http://stm.lbl.gov/comedi.
-
- 98 block	User-mode virtual block device
-		  0 = /dev/ubda		First user-mode block device
-		 16 = /dev/udbb		Second user-mode block device
-		    ...
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-		This device is used by the user-mode virtual kernel port.
-
- 99 char	Raw parallel ports
-		  0 = /dev/parport0	First parallel port
-		  1 = /dev/parport1	Second parallel port
-		    ...
-
- 99 block	JavaStation flash disk
-		  0 = /dev/jsfd		JavaStation flash disk
-
-100 char	Telephony for Linux
-		  0 = /dev/phone0	First telephony device
-		  1 = /dev/phone1	Second telephony device
-		    ...
-
-101 char	Motorola DSP 56xxx board
-		  0 = /dev/mdspstat	Status information
-		  1 = /dev/mdsp1	First DSP board I/O controls
-		    ...
-		 16 = /dev/mdsp16	16th DSP board I/O controls
-
-101 block	AMI HyperDisk RAID controller
-		  0 = /dev/amiraid/ar0	First array whole disk
-		 16 = /dev/amiraid/ar1	Second array whole disk
-		    ...
-		240 = /dev/amiraid/ar15	16th array whole disk
-
-		For each device, partitions are added as:
-		  0 = /dev/amiraid/ar?	  Whole disk
-		  1 = /dev/amiraid/ar?p1  First partition
-		  2 = /dev/amiraid/ar?p2  Second partition
-		    ...
-		 15 = /dev/amiraid/ar?p15 15th partition
-
-102 char
-
-102 block	Compressed block device
-		  0 = /dev/cbd/a	First compressed block device, whole device
-		 16 = /dev/cbd/b	Second compressed block device, whole device
-		    ...
-		240 = /dev/cbd/p	16th compressed block device, whole device
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-103 char	Arla network file system
-		  0 = /dev/nnpfs0	First NNPFS device
-		  1 = /dev/nnpfs1	Second NNPFS device
-
-		Arla is a free clone of the Andrew File System, AFS.
-		The NNPFS device gives user mode filesystem
-		implementations a kernel presence for caching and easy
-		mounting.  For more information about the project,
-		write to <arla-drinkers@stacken.kth.se> or see
-		http://www.stacken.kth.se/project/arla/
-
-103 block	Audit device
-		  0 = /dev/audit	Audit device
-
-104 char	Flash BIOS support
-
-104 block	Compaq Next Generation Drive Array, first controller
-		  0 = /dev/cciss/c0d0	First logical drive, whole disk
-		 16 = /dev/cciss/c0d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c0d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-105 char	Comtrol VS-1000 serial controller
-		  0 = /dev/ttyV0	First VS-1000 port
-		  1 = /dev/ttyV1	Second VS-1000 port
-		    ...
-
-105 block	Compaq Next Generation Drive Array, second controller
-		  0 = /dev/cciss/c1d0	First logical drive, whole disk
-		 16 = /dev/cciss/c1d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c1d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-106 char	Comtrol VS-1000 serial controller - alternate devices
-		  0 = /dev/cuv0		First VS-1000 port
-		  1 = /dev/cuv1		Second VS-1000 port
-		    ...
-
-106 block	Compaq Next Generation Drive Array, third controller
-		  0 = /dev/cciss/c2d0	First logical drive, whole disk
-		 16 = /dev/cciss/c2d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c2d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-107 char	3Dfx Voodoo Graphics device
-		  0 = /dev/3dfx		Primary 3Dfx graphics device
-
-107 block	Compaq Next Generation Drive Array, fourth controller
-		  0 = /dev/cciss/c3d0	First logical drive, whole disk
-		 16 = /dev/cciss/c3d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c3d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-108 char	Device independent PPP interface
-		  0 = /dev/ppp		Device independent PPP interface
-
-108 block	Compaq Next Generation Drive Array, fifth controller
-		  0 = /dev/cciss/c4d0	First logical drive, whole disk
-		 16 = /dev/cciss/c4d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c4d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-109 char	Reserved for logical volume manager
-
-109 block	Compaq Next Generation Drive Array, sixth controller
-		  0 = /dev/cciss/c5d0	First logical drive, whole disk
-		 16 = /dev/cciss/c5d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c5d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-110 char	miroMEDIA Surround board
-		  0 = /dev/srnd0	First miroMEDIA Surround board
-		  1 = /dev/srnd1	Second miroMEDIA Surround board
-		    ...
-
-110 block	Compaq Next Generation Drive Array, seventh controller
-		  0 = /dev/cciss/c6d0	First logical drive, whole disk
-		 16 = /dev/cciss/c6d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c6d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-111 char
-
-111 block	Compaq Next Generation Drive Array, eighth controller
-		  0 = /dev/cciss/c7d0	First logical drive, whole disk
-		 16 = /dev/cciss/c7d1	Second logical drive, whole disk
-		    ...
-		240 = /dev/cciss/c7d15	16th logical drive, whole disk
-
-		Partitions are handled the same way as for Mylex
-		DAC960 (see major number 48) except that the limit on
-		partitions is 15.
-
-112 char	ISI serial card
-		  0 = /dev/ttyM0	First ISI port
-		  1 = /dev/ttyM1	Second ISI port
-		    ...
-
-		There is currently a device-naming conflict between
-		these and PAM multimodems (major 78).
-
-112 block	IBM iSeries virtual disk
-		  0 = /dev/iseries/vda	First virtual disk, whole disk
-		  8 = /dev/iseries/vdb	Second virtual disk, whole disk
-		    ...
-		200 = /dev/iseries/vdz	26th virtual disk, whole disk
-		208 = /dev/iseries/vdaa	27th virtual disk, whole disk
-		    ...
-		248 = /dev/iseries/vdaf	32nd virtual disk, whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 7.
-
-113 char	ISI serial card - alternate devices
-		  0 = /dev/cum0		Callout device for ttyM0
-		  1 = /dev/cum1		Callout device for ttyM1
-		    ...
-
-113 block	IBM iSeries virtual CD-ROM
-		  0 = /dev/iseries/vcda	First virtual CD-ROM
-		  1 = /dev/iseries/vcdb	Second virtual CD-ROM
-		    ...
-
-114 char	Picture Elements ISE board
-		  0 = /dev/ise0		First ISE board
-		  1 = /dev/ise1		Second ISE board
-		    ...
-		128 = /dev/isex0	Control node for first ISE board
-		129 = /dev/isex1	Control node for second ISE board
-		    ...
-
-		The ISE board is an embedded computer, optimized for
-		image processing. The /dev/iseN nodes are the general
-		I/O access to the board, the /dev/isex0 nodes command
-		nodes used to control the board.
-
-114 block       IDE BIOS powered software RAID interfaces such as the
-                Promise Fastrak
-
-                  0 = /dev/ataraid/d0
-                  1 = /dev/ataraid/d0p1
-                  2 = /dev/ataraid/d0p2
-                  ...
-                 16 = /dev/ataraid/d1
-                 17 = /dev/ataraid/d1p1
-                 18 = /dev/ataraid/d1p2
-                  ...
-                255 = /dev/ataraid/d15p15
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-115 char	TI link cable devices (115 was formerly the console driver speaker)
-		  0 = /dev/tipar0    Parallel cable on first parallel port
-		  ...
-		  7 = /dev/tipar7    Parallel cable on seventh parallel port
-
-		  8 = /dev/tiser0    Serial cable on first serial port
-		  ...
-		 15 = /dev/tiser7    Serial cable on seventh serial port
-
-		 16 = /dev/tiusb0    First USB cable
-		  ...
-		 47 = /dev/tiusb31   32nd USB cable
-
-115 block       NetWare (NWFS) Devices (0-255)
-
-                The NWFS (NetWare) devices are used to present a
-                collection of NetWare Mirror Groups or NetWare
-                Partitions as a logical storage segment for
-                use in mounting NetWare volumes.  A maximum of
-                256 NetWare volumes can be supported in a single
-                machine.
-
-                http://cgfa.telepac.pt/ftp2/kernel.org/linux/kernel/people/jmerkey/nwfs/
-
-                0 = /dev/nwfs/v0    First NetWare (NWFS) Logical Volume
-                1 = /dev/nwfs/v1    Second NetWare (NWFS) Logical Volume
-                2 = /dev/nwfs/v2    Third NetWare (NWFS) Logical Volume
-                      ...
-                255 = /dev/nwfs/v255    Last NetWare (NWFS) Logical Volume
-
-116 char	Advanced Linux Sound Driver (ALSA)
-
-116 block       MicroMemory battery backed RAM adapter (NVRAM)
-                Supports 16 boards, 15 partitions each.
-                Requested by neilb at cse.unsw.edu.au.
-
-		 0 = /dev/umem/d0      Whole of first board
-		 1 = /dev/umem/d0p1    First partition of first board
-		 2 = /dev/umem/d0p2    Second partition of first board
-		15 = /dev/umem/d0p15   15th partition of first board
-
-		16 = /dev/umem/d1      Whole of second board
-		17 = /dev/umem/d1p1    First partition of second board
-		    ...
-		255= /dev/umem/d15p15  15th partition of 16th board.
-
-117 char	COSA/SRP synchronous serial card
-		  0 = /dev/cosa0c0	1st board, 1st channel
-		  1 = /dev/cosa0c1	1st board, 2nd channel
-		    ...
-		 16 = /dev/cosa1c0	2nd board, 1st channel
-		 17 = /dev/cosa1c1	2nd board, 2nd channel
-		    ...
-
-117 block       Enterprise Volume Management System (EVMS)
-
-                The EVMS driver uses a layered, plug-in model to provide
-                unparalleled flexibility and extensibility in managing
-                storage.  This allows for easy expansion or customization
-                of various levels of volume management.  Requested by
-                Mark Peloquin (peloquin at us.ibm.com).
-
-                Note: EVMS populates and manages all the devnodes in
-                /dev/evms.
-
-                http://sf.net/projects/evms
-
-                  0 = /dev/evms/block_device   EVMS block device
-                  1 = /dev/evms/legacyname1    First EVMS legacy device
-                  2 = /dev/evms/legacyname2    Second EVMS legacy device
-                    ...
-                    Both ranges can grow (down or up) until they meet.
-                    ...
-                254 = /dev/evms/EVMSname2      Second EVMS native device
-                255 = /dev/evms/EVMSname1      First EVMS native device
-
-                Note: legacyname(s) are derived from the normal legacy
-                device names.  For example, /dev/hda5 would become
-                /dev/evms/hda5.
-
-118 char	IBM Cryptographic Accelerator
-		  0 = /dev/ica	Virtual interface to all IBM Crypto Accelerators
-		  1 = /dev/ica0	IBMCA Device 0
-		  2 = /dev/ica1	IBMCA Device 1
-		    ...
-
-119 char	VMware virtual network control
-		  0 = /dev/vnet0	1st virtual network
-		  1 = /dev/vnet1	2nd virtual network
-		    ...
-
-120-127 char	LOCAL/EXPERIMENTAL USE
-
-120-127 block	LOCAL/EXPERIMENTAL USE
-		Allocated for local/experimental use.  For devices not
-		assigned official numbers, these ranges should be
-		used in order to avoid conflicting with future assignments.
-
-128-135 char	Unix98 PTY masters
-
-		These devices should not have corresponding device
-		nodes; instead they should be accessed through the
-		/dev/ptmx cloning interface.
-
-128 block       SCSI disk devices (128-143)
-                  0 = /dev/sddy         129th SCSI disk whole disk
-                 16 = /dev/sddz         130th SCSI disk whole disk
-                 32 = /dev/sdea         131th SCSI disk whole disk
-                    ...
-                240 = /dev/sden         144th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-129 block       SCSI disk devices (144-159)
-                  0 = /dev/sdeo         145th SCSI disk whole disk
-                 16 = /dev/sdep         146th SCSI disk whole disk
-                 32 = /dev/sdeq         147th SCSI disk whole disk
-                    ...
-                240 = /dev/sdfd         160th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-130 char 	(Misc devices)
-
-130 block       SCSI disk devices (160-175)
-                  0 = /dev/sdfe         161st SCSI disk whole disk
-                 16 = /dev/sdff         162nd SCSI disk whole disk
-                 32 = /dev/sdfg         163rd SCSI disk whole disk
-                    ...
-                240 = /dev/sdft         176th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-131 block       SCSI disk devices (176-191)
-                  0 = /dev/sdfu         177th SCSI disk whole disk
-                 16 = /dev/sdfv         178th SCSI disk whole disk
-                 32 = /dev/sdfw         179th SCSI disk whole disk
-                    ...
-                240 = /dev/sdgj         192nd SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-132 block       SCSI disk devices (192-207)
-                  0 = /dev/sdgk         193rd SCSI disk whole disk
-                 16 = /dev/sdgl         194th SCSI disk whole disk
-                 32 = /dev/sdgm         195th SCSI disk whole disk
-                    ...
-                240 = /dev/sdgz         208th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-133 block       SCSI disk devices (208-223)
-                  0 = /dev/sdha         209th SCSI disk whole disk
-                 16 = /dev/sdhb         210th SCSI disk whole disk
-                 32 = /dev/sdhc         211th SCSI disk whole disk
-                    ...
-                240 = /dev/sdhp         224th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-134 block       SCSI disk devices (224-239)
-                  0 = /dev/sdhq         225th SCSI disk whole disk
-                 16 = /dev/sdhr         226th SCSI disk whole disk
-                 32 = /dev/sdhs         227th SCSI disk whole disk
-                    ...
-                240 = /dev/sdif         240th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-135 block       SCSI disk devices (240-255)
-                  0 = /dev/sdig         241st SCSI disk whole disk
-                 16 = /dev/sdih         242nd SCSI disk whole disk
-                 32 = /dev/sdih         243rd SCSI disk whole disk
-                    ...
-                240 = /dev/sdiv         256th SCSI disk whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-136-143 char	Unix98 PTY slaves
-		  0 = /dev/pts/0	First Unix98 pseudo-TTY
-		  1 = /dev/pts/1	Second Unix98 pseudo-TTY
-		    ...
-
-		These device nodes are automatically generated with
-		the proper permissions and modes by mounting the
-		devpts filesystem onto /dev/pts with the appropriate
-		mount options (distribution dependent, however, on
-		*most* distributions the appropriate options are
-		"mode=0620,gid=<gid of the "tty" group>".)
-
-136 block	Mylex DAC960 PCI RAID controller; ninth controller
-		  0 = /dev/rd/c8d0	First disk, whole disk
-		  8 = /dev/rd/c8d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c8d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-137 block	Mylex DAC960 PCI RAID controller; tenth controller
-		  0 = /dev/rd/c9d0	First disk, whole disk
-		  8 = /dev/rd/c9d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c9d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-138 block	Mylex DAC960 PCI RAID controller; eleventh controller
-		  0 = /dev/rd/c10d0	First disk, whole disk
-		  8 = /dev/rd/c10d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c10d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-139 block	Mylex DAC960 PCI RAID controller; twelfth controller
-		  0 = /dev/rd/c11d0	First disk, whole disk
-		  8 = /dev/rd/c11d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c11d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-140 block	Mylex DAC960 PCI RAID controller; thirteenth controller
-		  0 = /dev/rd/c12d0	First disk, whole disk
-		  8 = /dev/rd/c12d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c12d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-141 block	Mylex DAC960 PCI RAID controller; fourteenth controller
-		  0 = /dev/rd/c13d0	First disk, whole disk
-		  8 = /dev/rd/c13d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c13d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-142 block	Mylex DAC960 PCI RAID controller; fifteenth controller
-		  0 = /dev/rd/c14d0	First disk, whole disk
-		  8 = /dev/rd/c14d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c14d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-143 block	Mylex DAC960 PCI RAID controller; sixteenth controller
-		  0 = /dev/rd/c15d0	First disk, whole disk
-		  8 = /dev/rd/c15d1	Second disk, whole disk
-		    ...
-		248 = /dev/rd/c15d31	32nd disk, whole disk
-
-		Partitions are handled as for major 48.
-
-144 char	Encapsulated PPP
-		  0 = /dev/pppox0	First PPP over Ethernet
-		    ...
-		 63 = /dev/pppox63	64th PPP over Ethernet
-
-		This is primarily used for ADSL.
-
-		The SST 5136-DN DeviceNet interface driver has been
-		relocated to major 183 due to an unfortunate conflict.
-
-144 block	Expansion Area #1 for more non-device (e.g. NFS) mounts
-		  0 = mounted device 256
-		255 = mounted device 511
-
-145 char	SAM9407-based soundcard
-		  0 = /dev/sam0_mixer
-		  1 = /dev/sam0_sequencer
-		  2 = /dev/sam0_midi00
-		  3 = /dev/sam0_dsp
-		  4 = /dev/sam0_audio
-		  6 = /dev/sam0_sndstat
-		 18 = /dev/sam0_midi01
-		 34 = /dev/sam0_midi02
-		 50 = /dev/sam0_midi03
-		 64 = /dev/sam1_mixer
-		    ...
-		128 = /dev/sam2_mixer
-		    ...
-		192 = /dev/sam3_mixer
-		    ...
-
-		Device functions match OSS, but offer a number of
-		addons, which are sam9407 specific.  OSS can be
-		operated simultaneously, taking care of the codec.
-
-145 block	Expansion Area #2 for more non-device (e.g. NFS) mounts
-		  0 = mounted device 512
-		255 = mounted device 767
-
-146 char	SYSTRAM SCRAMNet mirrored-memory network
-		  0 = /dev/scramnet0	First SCRAMNet device
-		  1 = /dev/scramnet1	Second SCRAMNet device
-		    ...
-
-146 block	Expansion Area #3 for more non-device (e.g. NFS) mounts
-		  0 = mounted device 768
-		255 = mounted device 1023
-
-147 char	Aureal Semiconductor Vortex Audio device
-		  0 = /dev/aureal0	First Aureal Vortex
-		  1 = /dev/aureal1	Second Aureal Vortex
-		    ...
-
-147 block	Distributed Replicated Block Device (DRBD)
-		  0 = /dev/drbd0	First DRBD device
-		  1 = /dev/drbd1	Second DRBD device
-		    ...
-
-148 char	Technology Concepts serial card
-		  0 = /dev/ttyT0	First TCL port
-		  1 = /dev/ttyT1	Second TCL port
-		    ...
-
-149 char	Technology Concepts serial card - alternate devices
-		  0 = /dev/cut0		Callout device for ttyT0
-		  1 = /dev/cut0		Callout device for ttyT1
-		    ...
-
-150 char	Real-Time Linux FIFOs
-		  0 = /dev/rtf0		First RTLinux FIFO
-		  1 = /dev/rtf1		Second RTLinux FIFO
-		    ...
-
-151 char	DPT I2O SmartRaid V controller
-		  0 = /dev/dpti0	First DPT I2O adapter
-		  1 = /dev/dpti1	Second DPT I2O adapter
-		    ...
-
-152 char	EtherDrive Control Device
-		  0 = /dev/etherd/ctl	Connect/Disconnect an EtherDrive
-		  1 = /dev/etherd/err	Monitor errors
-		  2 = /dev/etherd/raw	Raw AoE packet monitor
-
-152 block	EtherDrive Block Devices
-		  0 = /dev/etherd/0	EtherDrive 0
-		    ...
-		255 = /dev/etherd/255	EtherDrive 255
-
-153 char	SPI Bus Interface (sometimes referred to as MicroWire)
-		  0 = /dev/spi0		First SPI device on the bus
-		  1 = /dev/spi1		Second SPI device on the bus
-		    ...
-		 15 = /dev/spi15	Sixteenth SPI device on the bus
-
-153 block	Enhanced Metadisk RAID (EMD) storage units
-		  0 = /dev/emd/0	First unit
-		  1 = /dev/emd/0p1	Partition 1 on First unit
-		  2 = /dev/emd/0p2	Partition 2 on First unit
-		    ...
-		 15 = /dev/emd/0p15	Partition 15 on First unit
-
-		 16 = /dev/emd/1	Second unit
-		 32 = /dev/emd/2	Third unit
-		    ...
-		240 = /dev/emd/15	Sixteenth unit
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 15.
-
-154 char	Specialix RIO serial card
-		  0 = /dev/ttySR0	First RIO port
-		    ...
-		255 = /dev/ttySR255	256th RIO port
-
-155 char	Specialix RIO serial card - alternate devices
-		  0 = /dev/cusr0	Callout device for ttySR0
-		    ...
-		255 = /dev/cusr255	Callout device for ttySR255
-
-156 char	Specialix RIO serial card
-		  0 = /dev/ttySR256	257th RIO port
-		    ...
-		255 = /dev/ttySR511	512th RIO port
-
-157 char	Specialix RIO serial card - alternate devices
-		  0 = /dev/cusr256	Callout device for ttySR256
-		    ...
-		255 = /dev/cusr511	Callout device for ttySR511
-
-158 char	Dialogic GammaLink fax driver
-		  0 = /dev/gfax0	GammaLink channel 0
-		  1 = /dev/gfax1	GammaLink channel 1
-		    ...
-
-159 char	RESERVED
-
-159 block	RESERVED
-
-160 char	General Purpose Instrument Bus (GPIB)
-		  0 = /dev/gpib0	First GPIB bus
-		  1 = /dev/gpib1	Second GPIB bus
-		    ...
-
-160 block       Carmel 8-port SATA Disks on First Controller
-		  0 = /dev/carmel/0     SATA disk 0 whole disk
-		  1 = /dev/carmel/0p1   SATA disk 0 partition 1
-		    ...
-		 31 = /dev/carmel/0p31  SATA disk 0 partition 31
-
-		 32 = /dev/carmel/1     SATA disk 1 whole disk
-		 64 = /dev/carmel/2     SATA disk 2 whole disk
-		    ...
-		224 = /dev/carmel/7     SATA disk 7 whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 31.
-
-161 char	IrCOMM devices (IrDA serial/parallel emulation)
-		  0 = /dev/ircomm0	First IrCOMM device
-		  1 = /dev/ircomm1	Second IrCOMM device
-		    ...
-		 16 = /dev/irlpt0	First IrLPT device
-		 17 = /dev/irlpt1	Second IrLPT device
-		    ...
-
-161 block       Carmel 8-port SATA Disks on Second Controller
-		  0 = /dev/carmel/8     SATA disk 8 whole disk
-		  1 = /dev/carmel/8p1   SATA disk 8 partition 1
-		    ...
-		 31 = /dev/carmel/8p31  SATA disk 8 partition 31
-
-		 32 = /dev/carmel/9     SATA disk 9 whole disk
-		 64 = /dev/carmel/10    SATA disk 10 whole disk
-		    ...
-		224 = /dev/carmel/15    SATA disk 15 whole disk
-
-		Partitions are handled in the same way as for IDE
-		disks (see major number 3) except that the limit on
-		partitions is 31.
-
-162 char	Raw block device interface
-		  0 = /dev/rawctl	Raw I/O control device
-		  1 = /dev/raw/raw1	First raw I/O device
-		  2 = /dev/raw/raw2	Second raw I/O device
-		    ...
-                 max minor number of raw device is set by kernel config
-                 MAX_RAW_DEVS or raw module parameter 'max_raw_devs'
-
-163 char
-
-164 char	Chase Research AT/PCI-Fast serial card
-		  0 = /dev/ttyCH0	AT/PCI-Fast board 0, port 0
-		    ...
-		 15 = /dev/ttyCH15	AT/PCI-Fast board 0, port 15
-		 16 = /dev/ttyCH16	AT/PCI-Fast board 1, port 0
-		    ...
-		 31 = /dev/ttyCH31	AT/PCI-Fast board 1, port 15
-		 32 = /dev/ttyCH32	AT/PCI-Fast board 2, port 0
-		    ...
-		 47 = /dev/ttyCH47	AT/PCI-Fast board 2, port 15
-		 48 = /dev/ttyCH48	AT/PCI-Fast board 3, port 0
-		    ...
-		 63 = /dev/ttyCH63	AT/PCI-Fast board 3, port 15
-
-165 char	Chase Research AT/PCI-Fast serial card - alternate devices
-		  0 = /dev/cuch0	Callout device for ttyCH0
-		    ...
-		 63 = /dev/cuch63	Callout device for ttyCH63
-
-166 char	ACM USB modems
-		  0 = /dev/ttyACM0	First ACM modem
-		  1 = /dev/ttyACM1	Second ACM modem
-		    ...
-
-167 char	ACM USB modems - alternate devices
-		  0 = /dev/cuacm0	Callout device for ttyACM0
-		  1 = /dev/cuacm1	Callout device for ttyACM1
-		    ...
-
-168 char	Eracom CSA7000 PCI encryption adaptor
-		  0 = /dev/ecsa0	First CSA7000
-		  1 = /dev/ecsa1	Second CSA7000
-		    ...
-
-169 char	Eracom CSA8000 PCI encryption adaptor
-		  0 = /dev/ecsa8-0	First CSA8000
-		  1 = /dev/ecsa8-1	Second CSA8000
-		    ...
-
-170 char	AMI MegaRAC remote access controller
-		  0 = /dev/megarac0	First MegaRAC card
-		  1 = /dev/megarac1	Second MegaRAC card
-		    ...
-
-171 char	Reserved for IEEE 1394 (Firewire)
-
-172 char	Moxa Intellio serial card
-		  0 = /dev/ttyMX0	First Moxa port
-		  1 = /dev/ttyMX1	Second Moxa port
-		    ...
-		127 = /dev/ttyMX127	128th Moxa port
-		128 = /dev/moxactl	Moxa control port
-
-173 char	Moxa Intellio serial card - alternate devices
-		  0 = /dev/cumx0	Callout device for ttyMX0
-		  1 = /dev/cumx1	Callout device for ttyMX1
-		    ...
-		127 = /dev/cumx127	Callout device for ttyMX127
-
-174 char	SmartIO serial card
-		  0 = /dev/ttySI0	First SmartIO port
-		  1 = /dev/ttySI1	Second SmartIO port
-		    ...
-
-175 char	SmartIO serial card - alternate devices
-		  0 = /dev/cusi0	Callout device for ttySI0
-		  1 = /dev/cusi1	Callout device for ttySI1
-		    ...
-
-176 char	nCipher nFast PCI crypto accelerator
-		  0 = /dev/nfastpci0	First nFast PCI device
-		  1 = /dev/nfastpci1	First nFast PCI device
-		    ...
-
-177 char	TI PCILynx memory spaces
-		  0 = /dev/pcilynx/aux0	 AUX space of first PCILynx card
-		    ...
-		 15 = /dev/pcilynx/aux15 AUX space of 16th PCILynx card
-		 16 = /dev/pcilynx/rom0	 ROM space of first PCILynx card
-		    ...
-		 31 = /dev/pcilynx/rom15 ROM space of 16th PCILynx card
-		 32 = /dev/pcilynx/ram0	 RAM space of first PCILynx card
-		    ...
-		 47 = /dev/pcilynx/ram15 RAM space of 16th PCILynx card
-
-178 char	Giganet cLAN1xxx virtual interface adapter
-		  0 = /dev/clanvi0	First cLAN adapter
-		  1 = /dev/clanvi1	Second cLAN adapter
-		    ...
-
-179 block       MMC block devices
-		  0 = /dev/mmcblk0      First SD/MMC card
-		  1 = /dev/mmcblk0p1    First partition on first MMC card
-		  8 = /dev/mmcblk1      Second SD/MMC card
-		    ...
-
-		The start of next SD/MMC card can be configured with
-		CONFIG_MMC_BLOCK_MINORS, or overridden at boot/modprobe
-		time using the mmcblk.perdev_minors option. That would
-		bump the offset between each card to be the configured
-		value instead of the default 8.
-
-179 char	CCube DVXChip-based PCI products
-		  0 = /dev/dvxirq0	First DVX device
-		  1 = /dev/dvxirq1	Second DVX device
-		    ...
-
-180 char	USB devices
-		  0 = /dev/usb/lp0	First USB printer
-		    ...
-		 15 = /dev/usb/lp15	16th USB printer
-		 48 = /dev/usb/scanner0	First USB scanner
-		    ...
-		 63 = /dev/usb/scanner15 16th USB scanner
-		 64 = /dev/usb/rio500	Diamond Rio 500
-		 65 = /dev/usb/usblcd	USBLCD Interface (info@usblcd.de)
-		 66 = /dev/usb/cpad0	Synaptics cPad (mouse/LCD)
-		 96 = /dev/usb/hiddev0	1st USB HID device
-		    ...
-		111 = /dev/usb/hiddev15	16th USB HID device
-		112 = /dev/usb/auer0	1st auerswald ISDN device
-		    ...
-		127 = /dev/usb/auer15	16th auerswald ISDN device
-		128 = /dev/usb/brlvgr0	First Braille Voyager device
-		    ...
-		131 = /dev/usb/brlvgr3	Fourth Braille Voyager device
-		132 = /dev/usb/idmouse	ID Mouse (fingerprint scanner) device
-		133 = /dev/usb/sisusbvga1	First SiSUSB VGA device
-		    ...
-		140 = /dev/usb/sisusbvga8	Eighth SISUSB VGA device
-		144 = /dev/usb/lcd	USB LCD device
-		160 = /dev/usb/legousbtower0	1st USB Legotower device
-		    ...
-		175 = /dev/usb/legousbtower15	16th USB Legotower device
-		176 = /dev/usb/usbtmc1	First USB TMC device
-		   ...
-		191 = /dev/usb/usbtmc16	16th USB TMC device
-		192 = /dev/usb/yurex1	First USB Yurex device
-		   ...
-		209 = /dev/usb/yurex16	16th USB Yurex device
-
-180 block	USB block devices
-		  0 = /dev/uba		First USB block device
-		  8 = /dev/ubb		Second USB block device
-		 16 = /dev/ubc		Third USB block device
- 		    ...
-
-181 char	Conrad Electronic parallel port radio clocks
-		  0 = /dev/pcfclock0	First Conrad radio clock
-		  1 = /dev/pcfclock1	Second Conrad radio clock
-		    ...
-
-182 char	Picture Elements THR2 binarizer
-		  0 = /dev/pethr0	First THR2 board
-		  1 = /dev/pethr1	Second THR2 board
-		    ...
-
-183 char	SST 5136-DN DeviceNet interface
-		  0 = /dev/ss5136dn0	First DeviceNet interface
-		  1 = /dev/ss5136dn1	Second DeviceNet interface
-		    ...
-
-		This device used to be assigned to major number 144.
-		It had to be moved due to an unfortunate conflict.
-
-184 char	Picture Elements' video simulator/sender
-		  0 = /dev/pevss0	First sender board
-		  1 = /dev/pevss1	Second sender board
-		    ...
-
-185 char	InterMezzo high availability file system
-		  0 = /dev/intermezzo0	First cache manager
-		  1 = /dev/intermezzo1	Second cache manager
-		    ...
-
-		See http://web.archive.org/web/20080115195241/
-		http://inter-mezzo.org/index.html
-
-186 char	Object-based storage control device
-		  0 = /dev/obd0		First obd control device
-		  1 = /dev/obd1		Second obd control device
-		    ...
-
-		See ftp://ftp.lustre.org/pub/obd for code and information.
-
-187 char	DESkey hardware encryption device
-		  0 = /dev/deskey0	First DES key
-		  1 = /dev/deskey1	Second DES key
-		    ...
-
-188 char	USB serial converters
-		  0 = /dev/ttyUSB0	First USB serial converter
-		  1 = /dev/ttyUSB1	Second USB serial converter
-		    ...
-
-189 char	USB serial converters - alternate devices
-		  0 = /dev/cuusb0	Callout device for ttyUSB0
-		  1 = /dev/cuusb1	Callout device for ttyUSB1
-		    ...
-
-190 char	Kansas City tracker/tuner card
-		  0 = /dev/kctt0	First KCT/T card
-		  1 = /dev/kctt1	Second KCT/T card
-		    ...
-
-191 char	Reserved for PCMCIA
-
-192 char	Kernel profiling interface
-		  0 = /dev/profile	Profiling control device
-		  1 = /dev/profile0	Profiling device for CPU 0
-		  2 = /dev/profile1	Profiling device for CPU 1
-		    ...
-
-193 char	Kernel event-tracing interface
-		  0 = /dev/trace	Tracing control device
-		  1 = /dev/trace0	Tracing device for CPU 0
-		  2 = /dev/trace1	Tracing device for CPU 1
-		    ...
-
-194 char	linVideoStreams (LINVS)
-		  0 = /dev/mvideo/status0	Video compression status
-		  1 = /dev/mvideo/stream0	Video stream
-		  2 = /dev/mvideo/frame0	Single compressed frame
-		  3 = /dev/mvideo/rawframe0	Raw uncompressed frame
-		  4 = /dev/mvideo/codec0	Direct codec access
-		  5 = /dev/mvideo/video4linux0	Video4Linux compatibility
-
-		 16 = /dev/mvideo/status1	Second device
-		    ...
-		 32 = /dev/mvideo/status2	Third device
-		    ...
-		    ...
-		240 = /dev/mvideo/status15	16th device
-		    ...
-
-195 char	Nvidia graphics devices
-		  0 = /dev/nvidia0		First Nvidia card
-		  1 = /dev/nvidia1		Second Nvidia card
-		    ...
-		255 = /dev/nvidiactl		Nvidia card control device
-
-196 char	Tormenta T1 card
-		  0 = /dev/tor/0		Master control channel for all cards
-		  1 = /dev/tor/1		First DS0
-		  2 = /dev/tor/2		Second DS0
-		    ...
-		 48 = /dev/tor/48		48th DS0
-		 49 = /dev/tor/49		First pseudo-channel
-		 50 = /dev/tor/50		Second pseudo-channel
-		    ...
-
-197 char	OpenTNF tracing facility
-		  0 = /dev/tnf/t0		Trace 0 data extraction
-		  1 = /dev/tnf/t1		Trace 1 data extraction
-		    ...
-		128 = /dev/tnf/status		Tracing facility status
-		130 = /dev/tnf/trace		Tracing device
-
-198 char	Total Impact TPMP2 quad coprocessor PCI card
-		  0 = /dev/tpmp2/0		First card
-		  1 = /dev/tpmp2/1		Second card
-		    ...
-
-199 char	Veritas volume manager (VxVM) volumes
-		  0 = /dev/vx/rdsk/*/*		First volume
-		  1 = /dev/vx/rdsk/*/*		Second volume
-		    ...
-
-199 block	Veritas volume manager (VxVM) volumes
-		  0 = /dev/vx/dsk/*/*		First volume
-		  1 = /dev/vx/dsk/*/*		Second volume
-		    ...
-
-		The namespace in these directories is maintained by
-		the user space VxVM software.
-
-200 char	Veritas VxVM configuration interface
-                  0 = /dev/vx/config		Configuration access node
-                  1 = /dev/vx/trace		Volume i/o trace access node
-                  2 = /dev/vx/iod		Volume i/o daemon access node
-                  3 = /dev/vx/info		Volume information access node
-                  4 = /dev/vx/task		Volume tasks access node
-                  5 = /dev/vx/taskmon		Volume tasks monitor daemon
-
-201 char	Veritas VxVM dynamic multipathing driver
-		  0 = /dev/vx/rdmp/*		First multipath device
-		  1 = /dev/vx/rdmp/*		Second multipath device
-		    ...
-201 block	Veritas VxVM dynamic multipathing driver
-		  0 = /dev/vx/dmp/*		First multipath device
-		  1 = /dev/vx/dmp/*		Second multipath device
-		    ...
-
-		The namespace in these directories is maintained by
-		the user space VxVM software.
-
-202 char	CPU model-specific registers
-		  0 = /dev/cpu/0/msr		MSRs on CPU 0
-		  1 = /dev/cpu/1/msr		MSRs on CPU 1
-		    ...
-
-202 block	Xen Virtual Block Device
-		  0 = /dev/xvda       First Xen VBD whole disk
-		  16 = /dev/xvdb      Second Xen VBD whole disk
-		  32 = /dev/xvdc      Third Xen VBD whole disk
-		    ...
-		  240 = /dev/xvdp     Sixteenth Xen VBD whole disk
-
-                Partitions are handled in the same way as for IDE
-                disks (see major number 3) except that the limit on
-                partitions is 15.
-
-203 char	CPU CPUID information
-		  0 = /dev/cpu/0/cpuid		CPUID on CPU 0
-		  1 = /dev/cpu/1/cpuid		CPUID on CPU 1
-		    ...
-
-204 char	Low-density serial ports
-		  0 = /dev/ttyLU0		LinkUp Systems L72xx UART - port 0
-		  1 = /dev/ttyLU1		LinkUp Systems L72xx UART - port 1
-		  2 = /dev/ttyLU2		LinkUp Systems L72xx UART - port 2
-		  3 = /dev/ttyLU3		LinkUp Systems L72xx UART - port 3
-		  4 = /dev/ttyFB0		Intel Footbridge (ARM)
-		  5 = /dev/ttySA0		StrongARM builtin serial port 0
-		  6 = /dev/ttySA1		StrongARM builtin serial port 1
-		  7 = /dev/ttySA2		StrongARM builtin serial port 2
-		  8 = /dev/ttySC0		SCI serial port (SuperH) - port 0
-		  9 = /dev/ttySC1		SCI serial port (SuperH) - port 1
-		 10 = /dev/ttySC2		SCI serial port (SuperH) - port 2
-		 11 = /dev/ttySC3		SCI serial port (SuperH) - port 3
-		 12 = /dev/ttyFW0		Firmware console - port 0
-		 13 = /dev/ttyFW1		Firmware console - port 1
-		 14 = /dev/ttyFW2		Firmware console - port 2
-		 15 = /dev/ttyFW3		Firmware console - port 3
-		 16 = /dev/ttyAM0		ARM "AMBA" serial port 0
-		    ...
-		 31 = /dev/ttyAM15		ARM "AMBA" serial port 15
-		 32 = /dev/ttyDB0		DataBooster serial port 0
-		    ...
-		 39 = /dev/ttyDB7		DataBooster serial port 7
-		 40 = /dev/ttySG0		SGI Altix console port
-		 41 = /dev/ttySMX0		Motorola i.MX - port 0
-		 42 = /dev/ttySMX1		Motorola i.MX - port 1
-		 43 = /dev/ttySMX2		Motorola i.MX - port 2
-		 44 = /dev/ttyMM0		Marvell MPSC - port 0
-		 45 = /dev/ttyMM1		Marvell MPSC - port 1
-		 46 = /dev/ttyCPM0		PPC CPM (SCC or SMC) - port 0
-		    ...
-		 47 = /dev/ttyCPM5		PPC CPM (SCC or SMC) - port 5
-		 50 = /dev/ttyIOC0		Altix serial card
-		    ...
-		 81 = /dev/ttyIOC31		Altix serial card
-		 82 = /dev/ttyVR0		NEC VR4100 series SIU
-		 83 = /dev/ttyVR1		NEC VR4100 series DSIU
-		 84 = /dev/ttyIOC84		Altix ioc4 serial card
-		    ...
-		 115 = /dev/ttyIOC115		Altix ioc4 serial card
-		 116 = /dev/ttySIOC0		Altix ioc3 serial card
-		    ...
-		 147 = /dev/ttySIOC31		Altix ioc3 serial card
-		 148 = /dev/ttyPSC0		PPC PSC - port 0
-		    ...
-		 153 = /dev/ttyPSC5		PPC PSC - port 5
-		 154 = /dev/ttyAT0		ATMEL serial port 0
-		    ...
-		 169 = /dev/ttyAT15		ATMEL serial port 15
-		 170 = /dev/ttyNX0		Hilscher netX serial port 0
-		    ...
-		 185 = /dev/ttyNX15		Hilscher netX serial port 15
-		 186 = /dev/ttyJ0		JTAG1 DCC protocol based serial port emulation
-		 187 = /dev/ttyUL0		Xilinx uartlite - port 0
-		    ...
-		 190 = /dev/ttyUL3		Xilinx uartlite - port 3
-		 191 = /dev/xvc0		Xen virtual console - port 0
-		 192 = /dev/ttyPZ0		pmac_zilog - port 0
-		    ...
-		 195 = /dev/ttyPZ3		pmac_zilog - port 3
-		 196 = /dev/ttyTX0		TX39/49 serial port 0
-		    ...
-		 204 = /dev/ttyTX7		TX39/49 serial port 7
-		 205 = /dev/ttySC0		SC26xx serial port 0
-		 206 = /dev/ttySC1		SC26xx serial port 1
-		 207 = /dev/ttySC2		SC26xx serial port 2
-		 208 = /dev/ttySC3		SC26xx serial port 3
-		 209 = /dev/ttyMAX0		MAX3100 serial port 0
-		 210 = /dev/ttyMAX1		MAX3100 serial port 1
-		 211 = /dev/ttyMAX2		MAX3100 serial port 2
-		 212 = /dev/ttyMAX3		MAX3100 serial port 3
-
-205 char	Low-density serial ports (alternate device)
-		  0 = /dev/culu0		Callout device for ttyLU0
-		  1 = /dev/culu1		Callout device for ttyLU1
-		  2 = /dev/culu2		Callout device for ttyLU2
-		  3 = /dev/culu3		Callout device for ttyLU3
-		  4 = /dev/cufb0		Callout device for ttyFB0
-		  5 = /dev/cusa0		Callout device for ttySA0
-		  6 = /dev/cusa1		Callout device for ttySA1
-		  7 = /dev/cusa2		Callout device for ttySA2
-		  8 = /dev/cusc0		Callout device for ttySC0
-		  9 = /dev/cusc1		Callout device for ttySC1
-		 10 = /dev/cusc2		Callout device for ttySC2
-		 11 = /dev/cusc3		Callout device for ttySC3
-		 12 = /dev/cufw0		Callout device for ttyFW0
-		 13 = /dev/cufw1		Callout device for ttyFW1
-		 14 = /dev/cufw2		Callout device for ttyFW2
-		 15 = /dev/cufw3		Callout device for ttyFW3
-		 16 = /dev/cuam0		Callout device for ttyAM0
-		    ...
-		 31 = /dev/cuam15		Callout device for ttyAM15
-		 32 = /dev/cudb0		Callout device for ttyDB0
-		    ...
-		 39 = /dev/cudb7		Callout device for ttyDB7
-		 40 = /dev/cusg0		Callout device for ttySG0
-		 41 = /dev/ttycusmx0		Callout device for ttySMX0
-		 42 = /dev/ttycusmx1		Callout device for ttySMX1
-		 43 = /dev/ttycusmx2		Callout device for ttySMX2
-		 46 = /dev/cucpm0		Callout device for ttyCPM0
-		    ...
-		 49 = /dev/cucpm5		Callout device for ttyCPM5
-		 50 = /dev/cuioc40		Callout device for ttyIOC40
-		    ...
-		 81 = /dev/cuioc431		Callout device for ttyIOC431
-		 82 = /dev/cuvr0		Callout device for ttyVR0
-		 83 = /dev/cuvr1		Callout device for ttyVR1
-
-206 char	OnStream SC-x0 tape devices
-		  0 = /dev/osst0		First OnStream SCSI tape, mode 0
-		  1 = /dev/osst1		Second OnStream SCSI tape, mode 0
-		    ...
-		 32 = /dev/osst0l		First OnStream SCSI tape, mode 1
-		 33 = /dev/osst1l		Second OnStream SCSI tape, mode 1
-		    ...
-		 64 = /dev/osst0m		First OnStream SCSI tape, mode 2
-		 65 = /dev/osst1m		Second OnStream SCSI tape, mode 2
-		    ...
-		 96 = /dev/osst0a		First OnStream SCSI tape, mode 3
-		 97 = /dev/osst1a		Second OnStream SCSI tape, mode 3
-		    ...
-		128 = /dev/nosst0		No rewind version of /dev/osst0
-		129 = /dev/nosst1		No rewind version of /dev/osst1
-		    ...
-		160 = /dev/nosst0l		No rewind version of /dev/osst0l
-		161 = /dev/nosst1l		No rewind version of /dev/osst1l
-		    ...
-		192 = /dev/nosst0m		No rewind version of /dev/osst0m
-		193 = /dev/nosst1m		No rewind version of /dev/osst1m
-		    ...
-		224 = /dev/nosst0a		No rewind version of /dev/osst0a
-		225 = /dev/nosst1a		No rewind version of /dev/osst1a
-		    ...
-
-		The OnStream SC-x0 SCSI tapes do not support the
-		standard SCSI SASD command set and therefore need
-		their own driver "osst". Note that the IDE, USB (and
-		maybe ParPort) versions may be driven via ide-scsi or
-		usb-storage SCSI emulation and this osst device and
-		driver as well.  The ADR-x0 drives are QIC-157
-		compliant and don't need osst.
-
-207 char	Compaq ProLiant health feature indicate
-		  0 = /dev/cpqhealth/cpqw	Redirector interface
-		  1 = /dev/cpqhealth/crom	EISA CROM
-		  2 = /dev/cpqhealth/cdt	Data Table
-		  3 = /dev/cpqhealth/cevt	Event Log
-		  4 = /dev/cpqhealth/casr	Automatic Server Recovery
-		  5 = /dev/cpqhealth/cecc	ECC Memory
-		  6 = /dev/cpqhealth/cmca	Machine Check Architecture
-		  7 = /dev/cpqhealth/ccsm	Deprecated CDT
-		  8 = /dev/cpqhealth/cnmi	NMI Handling
-		  9 = /dev/cpqhealth/css	Sideshow Management
-		 10 = /dev/cpqhealth/cram	CMOS interface
-		 11 = /dev/cpqhealth/cpci	PCI IRQ interface
-
-208 char	User space serial ports
-		  0 = /dev/ttyU0		First user space serial port
-		  1 = /dev/ttyU1		Second user space serial port
-		    ...
-
-209 char	User space serial ports (alternate devices)
-		  0 = /dev/cuu0			Callout device for ttyU0
-		  1 = /dev/cuu1			Callout device for ttyU1
-		    ...
-
-210 char	SBE, Inc. sync/async serial card
-		  0 = /dev/sbei/wxcfg0		Configuration device for board 0
-		  1 = /dev/sbei/dld0		Download device for board 0
-		  2 = /dev/sbei/wan00		WAN device, port 0, board 0
-		  3 = /dev/sbei/wan01		WAN device, port 1, board 0
-		  4 = /dev/sbei/wan02		WAN device, port 2, board 0
-		  5 = /dev/sbei/wan03		WAN device, port 3, board 0
-		  6 = /dev/sbei/wanc00		WAN clone device, port 0, board 0
-		  7 = /dev/sbei/wanc01		WAN clone device, port 1, board 0
-		  8 = /dev/sbei/wanc02		WAN clone device, port 2, board 0
-		  9 = /dev/sbei/wanc03		WAN clone device, port 3, board 0
-		 10 = /dev/sbei/wxcfg1		Configuration device for board 1
-		 11 = /dev/sbei/dld1		Download device for board 1
-		 12 = /dev/sbei/wan10		WAN device, port 0, board 1
-		 13 = /dev/sbei/wan11		WAN device, port 1, board 1
-		 14 = /dev/sbei/wan12		WAN device, port 2, board 1
-		 15 = /dev/sbei/wan13		WAN device, port 3, board 1
-		 16 = /dev/sbei/wanc10		WAN clone device, port 0, board 1
-		 17 = /dev/sbei/wanc11		WAN clone device, port 1, board 1
-		 18 = /dev/sbei/wanc12		WAN clone device, port 2, board 1
-		 19 = /dev/sbei/wanc13		WAN clone device, port 3, board 1
-		    ...
-
-		Yes, each board is really spaced 10 (decimal) apart.
-
-211 char	Addinum CPCI1500 digital I/O card
-		  0 = /dev/addinum/cpci1500/0	First CPCI1500 card
-		  1 = /dev/addinum/cpci1500/1	Second CPCI1500 card
-		    ...
-
-212 char	LinuxTV.org DVB driver subsystem
-		  0 = /dev/dvb/adapter0/video0    first video decoder of first card
-		  1 = /dev/dvb/adapter0/audio0    first audio decoder of first card
-		  2 = /dev/dvb/adapter0/sec0      (obsolete/unused)
-		  3 = /dev/dvb/adapter0/frontend0 first frontend device of first card
-		  4 = /dev/dvb/adapter0/demux0    first demux device of first card
-		  5 = /dev/dvb/adapter0/dvr0      first digital video recoder device of first card
-		  6 = /dev/dvb/adapter0/ca0       first common access port of first card
-		  7 = /dev/dvb/adapter0/net0      first network device of first card
-		  8 = /dev/dvb/adapter0/osd0      first on-screen-display device of first card
-		  9 = /dev/dvb/adapter0/video1    second video decoder of first card
-		    ...
-		 64 = /dev/dvb/adapter1/video0    first video decoder of second card
-		    ...
-		128 = /dev/dvb/adapter2/video0    first video decoder of third card
-		    ...
-		196 = /dev/dvb/adapter3/video0    first video decoder of fourth card
-
-216 char	Bluetooth RFCOMM TTY devices
-		  0 = /dev/rfcomm0		First Bluetooth RFCOMM TTY device
-		  1 = /dev/rfcomm1		Second Bluetooth RFCOMM TTY device
-		    ...
-
-217 char	Bluetooth RFCOMM TTY devices (alternate devices)
-		  0 = /dev/curf0		Callout device for rfcomm0
-		  1 = /dev/curf1		Callout device for rfcomm1
-		    ...
-
-218 char	The Logical Company bus Unibus/Qbus adapters
-		  0 = /dev/logicalco/bci/0	First bus adapter
-		  1 = /dev/logicalco/bci/1	First bus adapter
-		    ...
-
-219 char	The Logical Company DCI-1300 digital I/O card
-		  0 = /dev/logicalco/dci1300/0	First DCI-1300 card
-		  1 = /dev/logicalco/dci1300/1	Second DCI-1300 card
-		    ...
-
-220 char	Myricom Myrinet "GM" board
-		  0 = /dev/myricom/gm0		First Myrinet GM board
-		  1 = /dev/myricom/gmp0		First board "root access"
-		  2 = /dev/myricom/gm1		Second Myrinet GM board
-		  3 = /dev/myricom/gmp1		Second board "root access"
-		    ...
-
-221 char	VME bus
-		  0 = /dev/bus/vme/m0		First master image
-		  1 = /dev/bus/vme/m1		Second master image
-		  2 = /dev/bus/vme/m2		Third master image
-		  3 = /dev/bus/vme/m3		Fourth master image
-		  4 = /dev/bus/vme/s0		First slave image
-		  5 = /dev/bus/vme/s1		Second slave image
-		  6 = /dev/bus/vme/s2		Third slave image
-		  7 = /dev/bus/vme/s3		Fourth slave image
-		  8 = /dev/bus/vme/ctl		Control
-
-		It is expected that all VME bus drivers will use the
-		same interface.  For interface documentation see
-		http://www.vmelinux.org/.
-
-224 char	A2232 serial card
-		  0 = /dev/ttyY0		First A2232 port
-		  1 = /dev/ttyY1		Second A2232 port
-		    ...
-
-225 char	A2232 serial card (alternate devices)
-		  0 = /dev/cuy0			Callout device for ttyY0
-		  1 = /dev/cuy1			Callout device for ttyY1
-		    ...
-
-226 char	Direct Rendering Infrastructure (DRI)
-		  0 = /dev/dri/card0		First graphics card
-		  1 = /dev/dri/card1		Second graphics card
-		    ...
-
-227 char	IBM 3270 terminal Unix tty access
-		  1 = /dev/3270/tty1		First 3270 terminal
-		  2 = /dev/3270/tty2		Seconds 3270 terminal
-		    ...
-
-228 char	IBM 3270 terminal block-mode access
-		  0 = /dev/3270/tub		Controlling interface
-		  1 = /dev/3270/tub1		First 3270 terminal
-		  2 = /dev/3270/tub2		Second 3270 terminal
-		    ...
-
-229 char	IBM iSeries/pSeries virtual console
-		  0 = /dev/hvc0			First console port
-		  1 = /dev/hvc1			Second console port
-		    ...
-
-230 char	IBM iSeries virtual tape
-		  0 = /dev/iseries/vt0		First virtual tape, mode 0
-		  1 = /dev/iseries/vt1		Second virtual tape, mode 0
-		    ...
-		 32 = /dev/iseries/vt0l		First virtual tape, mode 1
-		 33 = /dev/iseries/vt1l		Second virtual tape, mode 1
-		    ...
-		 64 = /dev/iseries/vt0m		First virtual tape, mode 2
-		 65 = /dev/iseries/vt1m		Second virtual tape, mode 2
-		    ...
-		 96 = /dev/iseries/vt0a		First virtual tape, mode 3
-		 97 = /dev/iseries/vt1a		Second virtual tape, mode 3
-		      ...
-		128 = /dev/iseries/nvt0		First virtual tape, mode 0, no rewind
-		129 = /dev/iseries/nvt1		Second virtual tape, mode 0, no rewind
-		    ...
-		160 = /dev/iseries/nvt0l	First virtual tape, mode 1, no rewind
-		161 = /dev/iseries/nvt1l	Second virtual tape, mode 1, no rewind
-		    ...
-		192 = /dev/iseries/nvt0m	First virtual tape, mode 2, no rewind
-		193 = /dev/iseries/nvt1m	Second virtual tape, mode 2, no rewind
-		    ...
-		224 = /dev/iseries/nvt0a	First virtual tape, mode 3, no rewind
-		225 = /dev/iseries/nvt1a	Second virtual tape, mode 3, no rewind
-		    ...
-
-		"No rewind" refers to the omission of the default
-		automatic rewind on device close.  The MTREW or MTOFFL
-		ioctl()'s can be used to rewind the tape regardless of
-		the device used to access it.
-
-231 char	InfiniBand
-		0 = /dev/infiniband/umad0
-		1 = /dev/infiniband/umad1
-		  ...
-		63 = /dev/infiniband/umad63    63rd InfiniBandMad device
-		64 = /dev/infiniband/issm0     First InfiniBand IsSM device
-		65 = /dev/infiniband/issm1     Second InfiniBand IsSM device
-		  ...
-		127 = /dev/infiniband/issm63    63rd InfiniBand IsSM device
-		128 = /dev/infiniband/uverbs0   First InfiniBand verbs device
-		129 = /dev/infiniband/uverbs1   Second InfiniBand verbs device
-		  ...
-		159 = /dev/infiniband/uverbs31  31st InfiniBand verbs device
-
-232 char	Biometric Devices
-		0 = /dev/biometric/sensor0/fingerprint	first fingerprint sensor on first device
-		1 = /dev/biometric/sensor0/iris		first iris sensor on first device
-		2 = /dev/biometric/sensor0/retina	first retina sensor on first device
-		3 = /dev/biometric/sensor0/voiceprint	first voiceprint sensor on first device
-		4 = /dev/biometric/sensor0/facial	first facial sensor on first device
-		5 = /dev/biometric/sensor0/hand		first hand sensor on first device
-		  ...
-		10 = /dev/biometric/sensor1/fingerprint	first fingerprint sensor on second device
-		  ...
-		20 = /dev/biometric/sensor2/fingerprint	first fingerprint sensor on third device
-		  ...
-
-233 char	PathScale InfiniPath interconnect
-		0 = /dev/ipath        Primary device for programs (any unit)
-		1 = /dev/ipath0       Access specifically to unit 0
-		2 = /dev/ipath1       Access specifically to unit 1
-		  ...
-		4 = /dev/ipath3       Access specifically to unit 3
-		129 = /dev/ipath_sma    Device used by Subnet Management Agent
-		130 = /dev/ipath_diag   Device used by diagnostics programs
-
-234-254	char	RESERVED FOR DYNAMIC ASSIGNMENT
-		Character devices that request a dynamic allocation of major number will
-		take numbers starting from 254 and downward.
-
-240-254 block	LOCAL/EXPERIMENTAL USE
-		Allocated for local/experimental use.  For devices not
-		assigned official numbers, these ranges should be
-		used in order to avoid conflicting with future assignments.
-
-255 char	RESERVED
-
-255 block	RESERVED
-
-		This major is reserved to assist the expansion to a
-		larger number space.  No device nodes with this major
-		should ever be created on the filesystem.
-		(This is probably not true anymore, but I'll leave it
-		for now /Torben)
-
----LARGE MAJORS!!!!!---
-
-256 char	Equinox SST multi-port serial boards
-		   0 = /dev/ttyEQ0	First serial port on first Equinox SST board
-		 127 = /dev/ttyEQ127	Last serial port on first Equinox SST board
-		 128 = /dev/ttyEQ128	First serial port on second Equinox SST board
-		  ...
-		1027 = /dev/ttyEQ1027	Last serial port on eighth Equinox SST board
-
-256 block	Resident Flash Disk Flash Translation Layer
-		  0 = /dev/rfda		First RFD FTL layer
-		 16 = /dev/rfdb		Second RFD FTL layer
-		  ...
-		240 = /dev/rfdp		16th RFD FTL layer
-
-257 char	Phoenix Technologies Cryptographic Services Driver
-		  0 = /dev/ptlsec	Crypto Services Driver
-
-257 block	SSFDC Flash Translation Layer filesystem
-		  0 = /dev/ssfdca	First SSFDC layer
-		  8 = /dev/ssfdcb	Second SSFDC layer
-		 16 = /dev/ssfdcc	Third SSFDC layer
-		 24 = /dev/ssfdcd	4th SSFDC layer
-		 32 = /dev/ssfdce	5th SSFDC layer
-		 40 = /dev/ssfdcf	6th SSFDC layer
-		 48 = /dev/ssfdcg	7th SSFDC layer
-		 56 = /dev/ssfdch	8th SSFDC layer
-
-258 block	ROM/Flash read-only translation layer
-		  0 = /dev/blockrom0	First ROM card's translation layer interface
-		  1 = /dev/blockrom1	Second ROM card's translation layer interface
-		  ...
-
-259 block	Block Extended Major
-		  Used dynamically to hold additional partition minor
-		  numbers and allow large numbers of partitions per device
-
-259 char	FPGA configuration interfaces
-		  0 = /dev/icap0	First Xilinx internal configuration
-		  1 = /dev/icap1	Second Xilinx internal configuration
-
-260 char	OSD (Object-based-device) SCSI Device
-		  0 = /dev/osd0		First OSD Device
-		  1 = /dev/osd1		Second OSD Device
-		  ...
-		  255 = /dev/osd255	256th OSD Device
-
- ****	ADDITIONAL /dev DIRECTORY ENTRIES
-
-This section details additional entries that should or may exist in
-the /dev directory.  It is preferred that symbolic links use the same
-form (absolute or relative) as is indicated here.  Links are
-classified as "hard" or "symbolic" depending on the preferred type of
-link; if possible, the indicated type of link should be used.
-
-
-	Compulsory links
-
-These links should exist on all systems:
-
-/dev/fd		/proc/self/fd	symbolic	File descriptors
-/dev/stdin	fd/0		symbolic	stdin file descriptor
-/dev/stdout	fd/1		symbolic	stdout file descriptor
-/dev/stderr	fd/2		symbolic	stderr file descriptor
-/dev/nfsd	socksys		symbolic	Required by iBCS-2
-/dev/X0R	null		symbolic	Required by iBCS-2
-
-Note: /dev/X0R is <letter X>-<digit 0>-<letter R>.
-
-	Recommended links
-
-It is recommended that these links exist on all systems:
-
-/dev/core	/proc/kcore	symbolic	Backward compatibility
-/dev/ramdisk	ram0		symbolic	Backward compatibility
-/dev/ftape	qft0		symbolic	Backward compatibility
-/dev/bttv0	video0		symbolic	Backward compatibility
-/dev/radio	radio0		symbolic	Backward compatibility
-/dev/i2o*	/dev/i2o/*	symbolic	Backward compatibility
-/dev/scd?	sr?		hard		Alternate SCSI CD-ROM name
-
-	Locally defined links
-
-The following links may be established locally to conform to the
-configuration of the system.  This is merely a tabulation of existing
-practice, and does not constitute a recommendation.  However, if they
-exist, they should have the following uses.
-
-/dev/mouse	mouse port	symbolic	Current mouse device
-/dev/tape	tape device	symbolic	Current tape device
-/dev/cdrom	CD-ROM device	symbolic	Current CD-ROM device
-/dev/cdwriter	CD-writer	symbolic	Current CD-writer device
-/dev/scanner	scanner		symbolic	Current scanner device
-/dev/modem	modem port	symbolic	Current dialout device
-/dev/root	root device	symbolic	Current root filesystem
-/dev/swap	swap device	symbolic	Current swap device
-
-/dev/modem should not be used for a modem which supports dialin as
-well as dialout, as it tends to cause lock file problems.  If it
-exists, /dev/modem should point to the appropriate primary TTY device
-(the use of the alternate callout devices is deprecated).
-
-For SCSI devices, /dev/tape and /dev/cdrom should point to the
-``cooked'' devices (/dev/st* and /dev/sr*, respectively), whereas
-/dev/cdwriter and /dev/scanner should point to the appropriate generic
-SCSI devices (/dev/sg*).
-
-/dev/mouse may point to a primary serial TTY device, a hardware mouse
-device, or a socket for a mouse driver program (e.g. /dev/gpmdata).
-
-	Sockets and pipes
-
-Non-transient sockets and named pipes may exist in /dev.  Common entries are:
-
-/dev/printer	socket		lpd local socket
-/dev/log	socket		syslog local socket
-/dev/gpmdata	socket		gpm mouse multiplexer
-
-	Mount points
-
-The following names are reserved for mounting special filesystems
-under /dev.  These special filesystems provide kernel interfaces that
-cannot be provided with standard device nodes.
-
-/dev/pts	devpts		PTY slave filesystem
-/dev/shm	tmpfs		POSIX shared memory maintenance access
-
- ****	TERMINAL DEVICES
-
-Terminal, or TTY devices are a special class of character devices.  A
-terminal device is any device that could act as a controlling terminal
-for a session; this includes virtual consoles, serial ports, and
-pseudoterminals (PTYs).
-
-All terminal devices share a common set of capabilities known as line
-disciplines; these include the common terminal line discipline as well
-as SLIP and PPP modes.
-
-All terminal devices are named similarly; this section explains the
-naming and use of the various types of TTYs.  Note that the naming
-conventions include several historical warts; some of these are
-Linux-specific, some were inherited from other systems, and some
-reflect Linux outgrowing a borrowed convention.
-
-A hash mark (#) in a device name is used here to indicate a decimal
-number without leading zeroes.
-
-	Virtual consoles and the console device
-
-Virtual consoles are full-screen terminal displays on the system video
-monitor.  Virtual consoles are named /dev/tty#, with numbering
-starting at /dev/tty1; /dev/tty0 is the current virtual console.
-/dev/tty0 is the device that should be used to access the system video
-card on those architectures for which the frame buffer devices
-(/dev/fb*) are not applicable.	Do not use /dev/console
-for this purpose.
-
-The console device, /dev/console, is the device to which system
-messages should be sent, and on which logins should be permitted in
-single-user mode.  Starting with Linux 2.1.71, /dev/console is managed
-by the kernel; for previous versions it should be a symbolic link to
-either /dev/tty0, a specific virtual console such as /dev/tty1, or to
-a serial port primary (tty*, not cu*) device, depending on the
-configuration of the system.
-
-	Serial ports
-
-Serial ports are RS-232 serial ports and any device which simulates
-one, either in hardware (such as internal modems) or in software (such
-as the ISDN driver.)  Under Linux, each serial ports has two device
-names, the primary or callin device and the alternate or callout one.
-Each kind of device is indicated by a different letter.	 For any
-letter X, the names of the devices are /dev/ttyX# and /dev/cux#,
-respectively; for historical reasons, /dev/ttyS# and /dev/ttyC#
-correspond to /dev/cua# and /dev/cub#.	In the future, it should be
-expected that multiple letters will be used; all letters will be upper
-case for the "tty" device (e.g. /dev/ttyDP#) and lower case for the
-"cu" device (e.g. /dev/cudp#).
-
-The names /dev/ttyQ# and /dev/cuq# are reserved for local use.
-
-The alternate devices provide for kernel-based exclusion and somewhat
-different defaults than the primary devices.  Their main purpose is to
-allow the use of serial ports with programs with no inherent or broken
-support for serial ports.  Their use is deprecated, and they may be
-removed from a future version of Linux.
-
-Arbitration of serial ports is provided by the use of lock files with
-the names /var/lock/LCK..ttyX#.	 The contents of the lock file should
-be the PID of the locking process as an ASCII number.
-
-It is common practice to install links such as /dev/modem
-which point to serial ports.  In order to ensure proper locking in the
-presence of these links, it is recommended that software chase
-symlinks and lock all possible names; additionally, it is recommended
-that a lock file be installed with the corresponding alternate
-device.	 In order to avoid deadlocks, it is recommended that the locks
-are acquired in the following order, and released in the reverse:
-
-	1. The symbolic link name, if any (/var/lock/LCK..modem)
-	2. The "tty" name (/var/lock/LCK..ttyS2)
-	3. The alternate device name (/var/lock/LCK..cua2)
-
-In the case of nested symbolic links, the lock files should be
-installed in the order the symlinks are resolved.
-
-Under no circumstances should an application hold a lock while waiting
-for another to be released.  In addition, applications which attempt
-to create lock files for the corresponding alternate device names
-should take into account the possibility of being used on a non-serial
-port TTY, for which no alternate device would exist.
-
-	Pseudoterminals (PTYs)
-
-Pseudoterminals, or PTYs, are used to create login sessions or provide
-other capabilities requiring a TTY line discipline (including SLIP or
-PPP capability) to arbitrary data-generation processes.	 Each PTY has
-a master side, named /dev/pty[p-za-e][0-9a-f], and a slave side, named
-/dev/tty[p-za-e][0-9a-f].  The kernel arbitrates the use of PTYs by
-allowing each master side to be opened only once.
-
-Once the master side has been opened, the corresponding slave device
-can be used in the same manner as any TTY device.  The master and
-slave devices are connected by the kernel, generating the equivalent
-of a bidirectional pipe with TTY capabilities.
-
-Recent versions of the Linux kernels and GNU libc contain support for
-the System V/Unix98 naming scheme for PTYs, which assigns a common
-device, /dev/ptmx, to all the masters (opening it will automatically
-give you a previously unassigned PTY) and a subdirectory, /dev/pts,
-for the slaves; the slaves are named with decimal integers (/dev/pts/#
-in our notation).  This removes the problem of exhausting the
-namespace and enables the kernel to automatically create the device
-nodes for the slaves on demand using the "devpts" filesystem.
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/amlogic,scpi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/amlogic,scpi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/amlogic,scpi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/amlogic,scpi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+System Control and Power Interface (SCPI) Message Protocol
+(in addition to the standard binding in [0])
+----------------------------------------------------------
+Required properties
+
+- compatible : should be "amlogic,meson-gxbb-scpi"
+
+AMLOGIC SRAM and Shared Memory for SCPI
+------------------------------------
+
+Required properties:
+- compatible : should be "amlogic,meson-gxbb-sram"
+
+Each sub-node represents the reserved area for SCPI.
+
+Required sub-node properties:
+- compatible : should be "amlogic,meson-gxbb-scp-shmem" for SRAM based shared
+		memory on Amlogic GXBB SoC.
+
+[0] Documentation/devicetree/bindings/arm/arm,scpi.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/amlogic.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/amlogic.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/amlogic.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/amlogic.txt	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,18 @@ Boards with the Amlogic Meson GXBaby SoC
   Required root node property:
     compatible: "amlogic,meson-gxbb";
 
+Boards with the Amlogic Meson GXL S905X SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,s905x", "amlogic,meson-gxl";
+
+Boards with the Amlogic Meson GXL S905D SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,s905d", "amlogic,meson-gxl";
+
+Boards with the Amlogic Meson GXM S912 SoC shall have the following properties:
+  Required root node property:
+    compatible: "amlogic,s912", "amlogic,meson-gxm";
+
 Board compatible values:
   - "geniatech,atv1200" (Meson6)
   - "minix,neo-x8" (Meson8)
@@ -28,3 +40,10 @@ Board compatible values:
   - "hardkernel,odroid-c2" (Meson gxbb)
   - "amlogic,p200" (Meson gxbb)
   - "amlogic,p201" (Meson gxbb)
+  - "amlogic,p212" (Meson gxl s905x)
+  - "amlogic,p230" (Meson gxl s905d)
+  - "amlogic,p231" (Meson gxl s905d)
+  - "amlogic,q200" (Meson gxm s912)
+  - "amlogic,q201" (Meson gxm s912)
+  - "nexbox,a95x" (Meson gxbb or Meson gxl s905x)
+  - "nexbox,a1" (Meson gxm s912)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/arch_timer.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/arch_timer.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/arch_timer.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/arch_timer.txt	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,11 @@ to deliver its interrupts via SPIs.
   architecturally-defined reset values. Only supported for 32-bit
   systems which follow the ARMv7 architected reset values.
 
+- arm,no-tick-in-suspend : The main counter does not tick when the system is in
+  low-power system suspend on some SoCs. This behavior does not match the
+  Architecture Reference Manual's specification that the system counter "must
+  be implemented in an always-on power domain."
+
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/arm-boards linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/arm-boards
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/arm-boards	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/arm-boards	2017-02-12 16:03:20.000000000 -0500
@@ -148,11 +148,12 @@ Example:
 
 /dts-v1/;
 #include <dt-bindings/interrupt-controller/irq.h>
-#include "skeleton.dtsi"
 
 / {
 	model = "ARM RealView PB1176 with device tree";
 	compatible = "arm,realview-pb1176";
+	#address-cells = <1>;
+	#size-cells = <1>;
 
 	soc {
 		#address-cells = <1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/arm,scpi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/arm,scpi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/arm,scpi.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/arm,scpi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,10 @@ by Linux to initiate various system cont
 
 Required properties:
 
-- compatible : should be "arm,scpi"
+- compatible : should be
+	* "arm,scpi" : For implementations complying to SCPI v1.0 or above
+	* "arm,scpi-pre-1.0" : For implementations complying to all
+		unversioned releases prior to SCPI v1.0
 - mboxes: List of phandle and mailbox channel specifiers
 	  All the channels reserved by remote SCP firmware for use by
 	  SCPI message protocol should be specified in any order
@@ -59,18 +62,14 @@ SRAM and Shared Memory for SCPI
 A small area of SRAM is reserved for SCPI communication between application
 processors and SCP.
 
-Required properties:
-- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
-
-The rest of the properties should follow the generic mmio-sram description
-found in ../../sram/sram.txt
+The properties should follow the generic mmio-sram description found in [3]
 
 Each sub-node represents the reserved area for SCPI.
 
 Required sub-node properties:
 - reg : The base offset and size of the reserved area with the SRAM
-- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
-	       shared memory on Juno platforms
+- compatible : should be "arm,scp-shmem" for Non-secure SRAM based
+	       shared memory
 
 Sensor bindings for the sensors based on SCPI Message Protocol
 --------------------------------------------------------------
@@ -81,11 +80,9 @@ Required properties:
 - #thermal-sensor-cells: should be set to 1. This property follows the
 			 thermal device tree bindings[2].
 
-			 Valid cell values are raw identifiers (Sensor
-			 ID) as used by the firmware. Refer to
-			 platform documentation for your
-			 implementation for the IDs to use. For Juno
-			 R0 and Juno R1 refer to [3].
+			 Valid cell values are raw identifiers (Sensor ID)
+			 as used by the firmware. Refer to  platform details
+			 for your implementation for the IDs to use.
 
 Power domain bindings for the power domains based on SCPI Message Protocol
 ------------------------------------------------------------
@@ -112,7 +109,7 @@ Required properties:
 [0] http://infocenter.arm.com/help/topic/com.arm.doc.dui0922b/index.html
 [1] Documentation/devicetree/bindings/clock/clock-bindings.txt
 [2] Documentation/devicetree/bindings/thermal/thermal.txt
-[3] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/apas03s22.html
+[3] Documentation/devicetree/bindings/sram/sram.txt
 [4] Documentation/devicetree/bindings/power/power_domain.txt
 
 Example:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/atmel-at91.txt	2017-02-12 16:03:20.000000000 -0500
@@ -225,3 +225,19 @@ required properties:
 		compatible = "atmel,sama5d3-sfr", "syscon";
 		reg = <0xf0038000 0x60>;
 	};
+
+Security Module (SECUMOD)
+
+The Security Module macrocell provides all necessary secure functions to avoid
+voltage, temperature, frequency and mechanical attacks on the chip. It also
+embeds secure memories that can be scrambled
+
+required properties:
+- compatible: Should be "atmel,<chip>-secumod", "syscon".
+  <chip> can be "sama5d2".
+- reg: Should contain registers location and length
+
+	secumod@fc040000 {
+		compatible = "atmel,sama5d2-secumod", "syscon";
+		reg = <0xfc040000 0x100>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/bcm/brcm,ns2.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,9 @@
+Broadcom North Star 2 (NS2) device tree bindings
+------------------------------------------------
+
+Boards with NS2 shall have the following properties:
+
+Required root node property:
+
+NS2 SVK board
+compatible = "brcm,ns2-svk", "brcm,ns2";
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/bcm/ns2.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/bcm/ns2.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/bcm/ns2.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/bcm/ns2.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-Broadcom North Star 2 (NS2) device tree bindings
-------------------------------------------------
-
-Boards with NS2 shall have the following properties:
-
-Required root node property:
-
-NS2 SVK board
-compatible = "brcm,ns2-svk", "brcm,ns2";
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/cpu-capacity.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/cpu-capacity.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/cpu-capacity.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/cpu-capacity.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,236 @@
+==========================================
+ARM CPUs capacity bindings
+==========================================
+
+==========================================
+1 - Introduction
+==========================================
+
+ARM systems may be configured to have cpus with different power/performance
+characteristics within the same chip. In this case, additional information has
+to be made available to the kernel for it to be aware of such differences and
+take decisions accordingly.
+
+==========================================
+2 - CPU capacity definition
+==========================================
+
+CPU capacity is a number that provides the scheduler information about CPUs
+heterogeneity. Such heterogeneity can come from micro-architectural differences
+(e.g., ARM big.LITTLE systems) or maximum frequency at which CPUs can run
+(e.g., SMP systems with multiple frequency domains). Heterogeneity in this
+context is about differing performance characteristics; this binding tries to
+capture a first-order approximation of the relative performance of CPUs.
+
+CPU capacities are obtained by running a suitable benchmark. This binding makes
+no guarantees on the validity or suitability of any particular benchmark, the
+final capacity should, however, be:
+
+* A "single-threaded" or CPU affine benchmark
+* Divided by the running frequency of the CPU executing the benchmark
+* Not subject to dynamic frequency scaling of the CPU
+
+For the time being we however advise usage of the Dhrystone benchmark. What
+above thus becomes:
+
+CPU capacities are obtained by running the Dhrystone benchmark on each CPU at
+max frequency (with caches enabled). The obtained DMIPS score is then divided
+by the frequency (in MHz) at which the benchmark has been run, so that
+DMIPS/MHz are obtained.  Such values are then normalized w.r.t. the highest
+score obtained in the system.
+
+==========================================
+3 - capacity-dmips-mhz
+==========================================
+
+capacity-dmips-mhz is an optional cpu node [1] property: u32 value
+representing CPU capacity expressed in normalized DMIPS/MHz. At boot time, the
+maximum frequency available to the cpu is then used to calculate the capacity
+value internally used by the kernel.
+
+capacity-dmips-mhz property is all-or-nothing: if it is specified for a cpu
+node, it has to be specified for every other cpu nodes, or the system will
+fall back to the default capacity value for every CPU. If cpufreq is not
+available, final capacities are calculated by directly using capacity-dmips-
+mhz values (normalized w.r.t. the highest value found while parsing the DT).
+
+===========================================
+4 - Examples
+===========================================
+
+Example 1 (ARM 64-bit, 6-cpu system, two clusters):
+capacities-dmips-mhz are scaled w.r.t. 1024 (cpu@0 and cpu@1)
+supposing cluster0@max-freq=1100 and custer1@max-freq=850,
+final capacities are 1024 for cluster0 and 446 for cluster1
+
+cpus {
+	#address-cells = <2>;
+	#size-cells = <0>;
+
+	cpu-map {
+		cluster0 {
+			core0 {
+				cpu = <&A57_0>;
+			};
+			core1 {
+				cpu = <&A57_1>;
+			};
+		};
+
+		cluster1 {
+			core0 {
+				cpu = <&A53_0>;
+			};
+			core1 {
+				cpu = <&A53_1>;
+			};
+			core2 {
+				cpu = <&A53_2>;
+			};
+			core3 {
+				cpu = <&A53_3>;
+			};
+		};
+	};
+
+	idle-states {
+		entry-method = "arm,psci";
+
+		CPU_SLEEP_0: cpu-sleep-0 {
+			compatible = "arm,idle-state";
+			arm,psci-suspend-param = <0x0010000>;
+			local-timer-stop;
+			entry-latency-us = <100>;
+			exit-latency-us = <250>;
+			min-residency-us = <150>;
+		};
+
+		CLUSTER_SLEEP_0: cluster-sleep-0 {
+			compatible = "arm,idle-state";
+			arm,psci-suspend-param = <0x1010000>;
+			local-timer-stop;
+			entry-latency-us = <800>;
+			exit-latency-us = <700>;
+			min-residency-us = <2500>;
+		};
+	};
+
+	A57_0: cpu@0 {
+		compatible = "arm,cortex-a57","arm,armv8";
+		reg = <0x0 0x0>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A57_L2>;
+		clocks = <&scpi_dvfs 0>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		capacity-dmips-mhz = <1024>;
+	};
+
+	A57_1: cpu@1 {
+		compatible = "arm,cortex-a57","arm,armv8";
+		reg = <0x0 0x1>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A57_L2>;
+		clocks = <&scpi_dvfs 0>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		capacity-dmips-mhz = <1024>;
+	};
+
+	A53_0: cpu@100 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x100>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		capacity-dmips-mhz = <578>;
+	};
+
+	A53_1: cpu@101 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x101>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		capacity-dmips-mhz = <578>;
+	};
+
+	A53_2: cpu@102 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x102>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		capacity-dmips-mhz = <578>;
+	};
+
+	A53_3: cpu@103 {
+		compatible = "arm,cortex-a53","arm,armv8";
+		reg = <0x0 0x103>;
+		device_type = "cpu";
+		enable-method = "psci";
+		next-level-cache = <&A53_L2>;
+		clocks = <&scpi_dvfs 1>;
+		cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
+		capacity-dmips-mhz = <578>;
+	};
+
+	A57_L2: l2-cache0 {
+		compatible = "cache";
+	};
+
+	A53_L2: l2-cache1 {
+		compatible = "cache";
+	};
+};
+
+Example 2 (ARM 32-bit, 4-cpu system, two clusters,
+	   cpus 0,1@1GHz, cpus 2,3@500MHz):
+capacities-dmips-mhz are scaled w.r.t. 2 (cpu@0 and cpu@1), this means that first
+cpu@0 and cpu@1 are twice fast than cpu@2 and cpu@3 (at the same frequency)
+
+cpus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpu0: cpu@0 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0>;
+		capacity-dmips-mhz = <2>;
+	};
+
+	cpu1: cpu@1 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <1>;
+		capacity-dmips-mhz = <2>;
+	};
+
+	cpu2: cpu@2 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x100>;
+		capacity-dmips-mhz = <1>;
+	};
+
+	cpu3: cpu@3 {
+		device_type = "cpu";
+		compatible = "arm,cortex-a15";
+		reg = <0x101>;
+		capacity-dmips-mhz = <1>;
+	};
+};
+
+===========================================
+5 - References
+===========================================
+
+[1] ARM Linux Kernel documentation - CPUs bindings
+    Documentation/devicetree/bindings/arm/cpus.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/cpus.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/cpus.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/cpus.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/cpus.txt	2017-02-12 16:03:20.000000000 -0500
@@ -178,6 +178,7 @@ nodes to be present and contain the prop
 			    "marvell,pj4b"
 			    "marvell,sheeva-v5"
 			    "nvidia,tegra132-denver"
+			    "nvidia,tegra186-denver"
 			    "qcom,krait"
 			    "qcom,kryo"
 			    "qcom,scorpion"
@@ -241,6 +242,14 @@ nodes to be present and contain the prop
 			# List of phandles to idle state nodes supported
 			  by this cpu [3].
 
+	- capacity-dmips-mhz
+		Usage: Optional
+		Value type: <u32>
+		Definition:
+			# u32 value representing CPU capacity [3] in
+			  DMIPS/MHz, relative to highest capacity-dmips-mhz
+			  in the system.
+
 	- rockchip,pmu
 		Usage: optional for systems that have an "enable-method"
 		       property value of "rockchip,rk3066-smp"
@@ -464,3 +473,5 @@ cpus {
 [2] arm/msm/qcom,kpss-acc.txt
 [3] ARM Linux kernel documentation - idle states bindings
     Documentation/devicetree/bindings/arm/idle-states.txt
+[3] ARM Linux kernel documentation - cpu capacity bindings
+    Documentation/devicetree/bindings/arm/cpu-capacity.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/fsl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/fsl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/fsl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/fsl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -97,7 +97,7 @@ Freescale LS1021A Platform Device Tree B
 Required root node compatible properties:
   - compatible = "fsl,ls1021a";
 
-Freescale LS1021A SoC-specific Device Tree Bindings
+Freescale SoC-specific Device Tree Bindings
 -------------------------------------------
 
 Freescale SCFG
@@ -105,7 +105,11 @@ Freescale SCFG
 configuration and status registers for the chip. Such as getting PEX port
 status.
   Required properties:
-  - compatible: should be "fsl,ls1021a-scfg"
+  - compatible: Should contain a chip-specific compatible string,
+	Chip-specific strings are of the form "fsl,<chip>-scfg",
+	The following <chip>s are known to be supported:
+	ls1021a, ls1043a, ls1046a, ls2080a.
+
   - reg: should contain base address and length of SCFG memory-mapped registers
 
 Example:
@@ -119,7 +123,11 @@ Freescale DCFG
 configuration and status for the device. Such as setting the secondary
 core start address and release the secondary core from holdoff and startup.
   Required properties:
-  - compatible: should be "fsl,ls1021a-dcfg"
+  - compatible: Should contain a chip-specific compatible string,
+	Chip-specific strings are of the form "fsl,<chip>-dcfg",
+	The following <chip>s are known to be supported:
+	ls1021a, ls1043a, ls1046a, ls2080a.
+
   - reg : should contain base address and length of DCFG memory-mapped registers
 
 Example:
@@ -131,6 +139,10 @@ Example:
 Freescale ARMv8 based Layerscape SoC family Device Tree Bindings
 ----------------------------------------------------------------
 
+LS1043A SoC
+Required root node properties:
+    - compatible = "fsl,ls1043a";
+
 LS1043A ARMv8 based RDB Board
 Required root node properties:
     - compatible = "fsl,ls1043a-rdb", "fsl,ls1043a";
@@ -139,6 +151,22 @@ LS1043A ARMv8 based QDS Board
 Required root node properties:
     - compatible = "fsl,ls1043a-qds", "fsl,ls1043a";
 
+LS1046A SoC
+Required root node properties:
+    - compatible = "fsl,ls1046a";
+
+LS1046A ARMv8 based QDS Board
+Required root node properties:
+    - compatible = "fsl,ls1046a-qds", "fsl,ls1046a";
+
+LS1046A ARMv8 based RDB Board
+Required root node properties:
+    - compatible = "fsl,ls1046a-rdb", "fsl,ls1046a";
+
+LS2080A SoC
+Required root node properties:
+    - compatible = "fsl,ls2080a";
+
 LS2080A ARMv8 based Simulator model
 Required root node properties:
     - compatible = "fsl,ls2080a-simu", "fsl,ls2080a";
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,10 @@ HiP06 D03 Board
 Required root node properties:
 	- compatible = "hisilicon,hip06-d03";
 
+HiP07 D05 Board
+Required root node properties:
+	- compatible = "hisilicon,hip07-d05";
+
 Hisilicon system controller
 
 Required properties:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/juno,scpi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/juno,scpi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/juno,scpi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/juno,scpi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,26 @@
+System Control and Power Interface (SCPI) Message Protocol
+(in addition to the standard binding in [0])
+
+Juno SRAM and Shared Memory for SCPI
+------------------------------------
+
+Required properties:
+- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM
+
+Each sub-node represents the reserved area for SCPI.
+
+Required sub-node properties:
+- reg : The base offset and size of the reserved area with the SRAM
+- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
+	       shared memory on Juno platforms
+
+Sensor bindings for the sensors based on SCPI Message Protocol
+--------------------------------------------------------------
+Required properties:
+- compatible : should be "arm,scpi-sensors".
+- #thermal-sensor-cells: should be set to 1.
+			 For Juno R0 and Juno R1 refer to [1] for the
+			 sensor identifiers
+
+[0] Documentation/devicetree/bindings/arm/arm,scpi.txt
+[1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/apas03s22.html
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/keystone/ti,sci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,81 @@
+Texas Instruments System Control Interface (TI-SCI) Message Protocol
+--------------------------------------------------------------------
+
+Texas Instrument's processors including those belonging to Keystone generation
+of processors have separate hardware entity which is now responsible for the
+management of the System on Chip (SoC) system. These include various system
+level functions as well.
+
+An example of such an SoC is K2G, which contains the system control hardware
+block called Power Management Micro Controller (PMMC). This hardware block is
+initialized early into boot process and provides services to Operating Systems
+on multiple processors including ones running Linux.
+
+See http://processors.wiki.ti.com/index.php/TISCI for protocol definition.
+
+TI-SCI controller Device Node:
+=============================
+
+The TI-SCI node describes the Texas Instrument's System Controller entity node.
+This parent node may optionally have additional children nodes which describe
+specific functionality such as clocks, power domain, reset or additional
+functionality as may be required for the SoC. This hierarchy also describes the
+relationship between the TI-SCI parent node to the child node.
+
+Required properties:
+-------------------
+- compatible: should be "ti,k2g-sci"
+- mbox-names:
+	"rx" - Mailbox corresponding to receive path
+	"tx" - Mailbox corresponding to transmit path
+
+- mboxes: Mailboxes corresponding to the mbox-names. Each value of the mboxes
+	  property should contain a phandle to the mailbox controller device
+	  node and an args specifier that will be the phandle to the intended
+	  sub-mailbox child node to be used for communication.
+
+See Documentation/devicetree/bindings/mailbox/mailbox.txt for more details
+about the generic mailbox controller and client driver bindings. Also see
+Documentation/devicetree/bindings/mailbox/ti,message-manager.txt for typical
+controller that is used to communicate with this System controllers.
+
+Optional Properties:
+-------------------
+- reg-names:
+	debug_messages - Map the Debug message region
+- reg:  register space corresponding to the debug_messages
+- ti,system-reboot-controller: If system reboot can be triggered by SoC reboot
+
+Example (K2G):
+-------------
+	pmmc: pmmc {
+		compatible = "ti,k2g-sci";
+		mbox-names = "rx", "tx";
+		mboxes= <&msgmgr &msgmgr_proxy_pmmc_rx>,
+			<&msgmgr &msgmgr_proxy_pmmc_tx>;
+		reg-names = "debug_messages";
+		reg = <0x02921800 0x800>;
+	};
+
+
+TI-SCI Client Device Node:
+=========================
+
+Client nodes are maintained as children of the relevant TI-SCI device node.
+
+Example (K2G):
+-------------
+	pmmc: pmmc {
+		compatible = "ti,k2g-sci";
+		...
+
+		my_clk_node: clk_node {
+			...
+			...
+		};
+
+		my_pd_node: pd_node {
+			...
+			...
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/omap/omap.txt	2017-02-12 16:03:20.000000000 -0500
@@ -86,6 +86,9 @@ SoCs:
 - DRA722
   compatible = "ti,dra722", "ti,dra72", "ti,dra7"
 
+- DRA718
+  compatible = "ti,dra718", "ti,dra722", "ti,dra72", "ti,dra7"
+
 - AM5728
   compatible = "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"
 
@@ -175,12 +178,18 @@ Boards:
 - AM5728 IDK
   compatible = "ti,am5728-idk", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7"
 
+- AM5718 IDK
+  compatible = "ti,am5718-idk", "ti,am5718", "ti,dra7"
+
 - DRA742 EVM:  Software Development Board for DRA742
   compatible = "ti,dra7-evm", "ti,dra742", "ti,dra74", "ti,dra7"
 
 - DRA722 EVM: Software Development Board for DRA722
   compatible = "ti,dra72-evm", "ti,dra722", "ti,dra72", "ti,dra7"
 
+- DRA718 EVM: Software Development Board for DRA718
+  compatible = "ti,dra718-evm", "ti,dra718", "ti,dra722", "ti,dra72", "ti,dra7"
+
 - DM3730 Logic PD Torpedo + Wireless: Commercial System on Module with WiFi and Bluetooth
   compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap3630", "ti,omap3"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/oxnas.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/oxnas.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/oxnas.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/oxnas.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,5 +5,10 @@ Boards with the OX810SE SoC shall have t
   Required root node property:
     compatible: "oxsemi,ox810se"
 
+Boards with the OX820 SoC shall have the following properties:
+  Required root node property:
+    compatible: "oxsemi,ox820"
+
 Board compatible values:
   - "wd,mbwe" (OX810SE)
+  - "cloudengines,pogoplugv3" (OX820)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/qcom.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/qcom.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/qcom.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/qcom.txt	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,10 @@ The 'SoC' element must be one of the fol
 	apq8096
 	msm8916
 	msm8974
+	msm8992
+	msm8994
 	msm8996
+	mdm9615
 
 The 'board' element must be one of the following strings:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/rockchip.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/rockchip.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/rockchip.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/rockchip.txt	2017-02-12 16:03:20.000000000 -0500
@@ -25,6 +25,10 @@ Rockchip platforms device tree bindings
     Required root node properties:
       - compatible = "radxa,rock2-square", "rockchip,rk3288";
 
+- Rikomagic MK808 v1 board:
+    Required root node properties:
+      - compatible = "rikomagic,mk808", "rockchip,rk3066a";
+
 - Firefly Firefly-RK3288 board:
     Required root node properties:
       - compatible = "firefly,firefly-rk3288", "rockchip,rk3288";
@@ -99,6 +103,18 @@ Rockchip platforms device tree bindings
     Required root node properties:
       - compatible = "mqmaker,miqi", "rockchip,rk3288";
 
+- Rockchip PX3 Evaluation board:
+    Required root node properties:
+      - compatible = "rockchip,px3-evb", "rockchip,px3", "rockchip,rk3188";
+
+- Rockchip PX5 Evaluation board:
+    Required root node properties:
+      - compatible = "rockchip,px5-evb", "rockchip,px5", "rockchip,rk3368";
+
+- Rockchip RK1108 Evaluation board
+    Required root node properties:
+      - compatible = "rockchip,rk1108-evb", "rockchip,rk1108";
+
 - Rockchip RK3368 evb:
     Required root node properties:
       - compatible = "rockchip,rk3368-evb-act8846", "rockchip,rk3368";
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,8 @@ Required root node properties:
 	- "samsung,xyref5260"	- for Exynos5260-based Samsung board.
 	- "samsung,smdk5410"	- for Exynos5410-based Samsung SMDK5410 eval board.
 	- "samsung,smdk5420"	- for Exynos5420-based Samsung SMDK5420 eval board.
+	- "samsung,tm2"		- for Exynos5433-based Samsung TM2 board.
+	- "samsung,tm2e"	- for Exynos5433-based Samsung TM2E board.
 	- "samsung,sd5v1"	- for Exynos5440-based Samsung board.
 	- "samsung,ssdk5440"	- for Exynos5440-based Samsung board.
 
@@ -22,6 +24,9 @@ Required root node properties:
   * FriendlyARM
 	- "friendlyarm,tiny4412"  - for Exynos4412-based FriendlyARM
 				    TINY4412 board.
+  * TOPEET
+	- "topeet,itop4412-elite" - for Exynos4412-based TOPEET
+                                    Elite base board.
 
   * Google
 	- "google,pi"		- for Exynos5800-based Google Peach Pi
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/shmobile.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/shmobile.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/shmobile.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/shmobile.txt	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,10 @@ SoCs:
     compatible = "renesas,r8a73a4"
   - R-Mobile A1 (R8A77400)
     compatible = "renesas,r8a7740"
+  - RZ/G1M (R8A77430)
+    compatible = "renesas,r8a7743"
+  - RZ/G1E (R8A77450)
+    compatible = "renesas,r8a7745"
   - R-Car M1A (R8A77781)
     compatible = "renesas,r8a7778"
   - R-Car H1 (R8A77790)
@@ -35,7 +39,7 @@ SoCs:
 
 Boards:
 
-  - Alt
+  - Alt (RTP0RC7794SEB00010S)
     compatible = "renesas,alt", "renesas,r8a7794"
   - APE6-EVM
     compatible = "renesas,ape6evm", "renesas,r8a73a4"
@@ -47,9 +51,9 @@ Boards:
     compatible = "renesas,bockw", "renesas,r8a7778"
   - Genmai (RTK772100BC00000BR)
     compatible = "renesas,genmai", "renesas,r7s72100"
-  - Gose
+  - Gose (RTP0RC7793SEB00010S)
     compatible = "renesas,gose", "renesas,r8a7793"
-  - H3ULCB (RTP0RC7795SKB00010S)
+  - H3ULCB (R-Car Starter Kit Premier, RTP0RC7795SKB00010S)
     compatible = "renesas,h3ulcb", "renesas,r8a7795";
   - Henninger
     compatible = "renesas,henninger", "renesas,r8a7791"
@@ -61,7 +65,9 @@ Boards:
     compatible = "renesas,kzm9g", "renesas,sh73a0"
   - Lager (RTP0RC7790SEB00010S)
     compatible = "renesas,lager", "renesas,r8a7790"
-  - Marzen
+  - M3ULCB (R-Car Starter Kit Pro, RTP0RC7796SKB00010S)
+    compatible = "renesas,m3ulcb", "renesas,r8a7796";
+  - Marzen (R0P7779A00010S)
     compatible = "renesas,marzen", "renesas,r8a7779"
   - Porter (M2-LCDP)
     compatible = "renesas,porter", "renesas,r8a7791"
@@ -73,5 +79,27 @@ Boards:
     compatible = "renesas,salvator-x", "renesas,r8a7796";
   - SILK (RTP0RC7794LCB00011S)
     compatible = "renesas,silk", "renesas,r8a7794"
+  - SK-RZG1E (YR8A77450S000BE)
+    compatible = "renesas,sk-rzg1e", "renesas,r8a7745"
+  - SK-RZG1M (YR8A77430S000BE)
+    compatible = "renesas,sk-rzg1m", "renesas,r8a7743"
   - Wheat
     compatible = "renesas,wheat", "renesas,r8a7792"
+
+
+Most Renesas ARM SoCs have a Product Register that allows to retrieve SoC
+product and revision information.  If present, a device node for this register
+should be added.
+
+Required properties:
+  - compatible: Must be "renesas,prr".
+  - reg: Base address and length of the register block.
+
+
+Examples
+--------
+
+	prr: chipid@ff000044 {
+		compatible = "renesas,prr";
+		reg = <0 0xff000044 0 4>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/sunxi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/sunxi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/sunxi.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/sunxi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -14,4 +14,5 @@ using one of the following compatible st
   allwinner,sun8i-a83t
   allwinner,sun8i-h3
   allwinner,sun9i-a80
+  allwinner,sun50i-a64
   nextthing,gr8
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/swir.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/swir.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/arm/swir.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/arm/swir.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,12 @@
+Sierra Wireless Modules device tree bindings
+--------------------------------------------
+
+Supported Modules :
+ - WP8548 : Includes MDM9615 and PM8018 in a module
+
+Sierra Wireless modules shall have the following properties :
+  Required root node property
+   - compatible: "swir,wp8548" for the WP8548 CF3 Module
+
+Board compatible values:
+  - "swir,mangoh-green-wp8548" for the mangOH green board with the WP8548 module
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/ata/ahci-fsl-qoriq.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@ Binding for Freescale QorIQ AHCI SATA Co
 Required properties:
   - reg: Physical base address and size of the controller's register area.
   - compatible: Compatibility string. Must be 'fsl,<chip>-ahci', where
-    chip could be ls1021a, ls2080a, ls1043a etc.
+    chip could be ls1021a, ls1043a, ls1046a, ls2080a etc.
   - clocks: Input clock specifier. Refer to common clock bindings.
   - interrupts: Interrupt specifier. Refer to interrupt binding.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/ata/ahci-st.txt	2017-02-12 16:03:20.000000000 -0500
@@ -18,21 +18,6 @@ Optional properties:
 
 Example:
 
-	/* Example for stih416 */
-	sata0: sata@fe380000 {
-		compatible	= "st,ahci";
-		reg		= <0xfe380000 0x1000>;
-		interrupts	= <GIC_SPI 157 IRQ_TYPE_NONE>;
-		interrupt-names	= "hostc";
-		phys		= <&phy_port0 PHY_TYPE_SATA>;
-		phy-names	= "ahci_phy";
-		resets		= <&powerdown STIH416_SATA0_POWERDOWN>,
-				  <&softreset STIH416_SATA0_SOFTRESET>;
-		reset-names	= "pwr-dwn", "sw-rst";
-		clocks		= <&clk_s_a0_ls CLK_ICN_REG>;
-		clock-names	= "ahci_clk";
-	};
-
 	/* Example for stih407 family silicon */
 	sata0: sata@9b20000 {
 		compatible	= "st,ahci";
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/bus/nvidia,tegra20-gmi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/bus/nvidia,tegra20-gmi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/bus/nvidia,tegra20-gmi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/bus/nvidia,tegra20-gmi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,132 @@
+Device tree bindings for NVIDIA Tegra Generic Memory Interface bus
+
+The Generic Memory Interface bus enables memory transfers between internal and
+external memory. Can be used to attach various high speed devices such as
+synchronous/asynchronous NOR, FPGA, UARTS and more.
+
+The actual devices are instantiated from the child nodes of a GMI node.
+
+Required properties:
+ - compatible : Should contain one of the following:
+        For Tegra20 must contain "nvidia,tegra20-gmi".
+        For Tegra30 must contain "nvidia,tegra30-gmi".
+ - reg: Should contain GMI controller registers location and length.
+ - clocks: Must contain an entry for each entry in clock-names.
+ - clock-names: Must include the following entries: "gmi"
+ - resets : Must contain an entry for each entry in reset-names.
+ - reset-names : Must include the following entries: "gmi"
+ - #address-cells: The number of cells used to represent physical base
+   addresses in the GMI address space. Should be 2.
+ - #size-cells: The number of cells used to represent the size of an address
+   range in the GMI address space. Should be 1.
+ - ranges: Must be set up to reflect the memory layout with three integer values
+   for each chip-select line in use (only one entry is supported, see below
+   comments):
+   <cs-number> <offset> <physical address of mapping> <size>
+
+Note that the GMI controller does not have any internal chip-select address
+decoding, because of that chip-selects either need to be managed via software
+or by employing external chip-select decoding logic.
+
+If external chip-select logic is used to support multiple devices it is assumed
+that the devices use the same timing and so are probably the same type. It also
+assumes that they can fit in the 256MB address range. In this case only one
+child device is supported which represents the active chip-select line, see
+examples for more insight.
+
+The chip-select number is decoded from the child nodes second address cell of
+'ranges' property, if 'ranges' property is not present or empty chip-select will
+then be decoded from the first cell of the 'reg' property.
+
+Optional child cs node properties:
+
+ - nvidia,snor-data-width-32bit: Use 32bit data-bus, default is 16bit.
+ - nvidia,snor-mux-mode: Enable address/data MUX mode.
+ - nvidia,snor-rdy-active-before-data: Assert RDY signal one cycle before data.
+   If omitted it will be asserted with data.
+ - nvidia,snor-rdy-active-high: RDY signal is active high
+ - nvidia,snor-adv-active-high: ADV signal is active high
+ - nvidia,snor-oe-active-high: WE/OE signal is active high
+ - nvidia,snor-cs-active-high: CS signal is active high
+
+  Note that there is some special handling for the timing values.
+  From Tegra TRM:
+  Programming 0 means 1 clock cycle: actual cycle = programmed cycle + 1
+
+ - nvidia,snor-muxed-width: Number of cycles MUX address/data asserted on the
+   bus. Valid values are 0-15, default is 1
+ - nvidia,snor-hold-width: Number of cycles CE stays asserted after the
+   de-assertion of WR_N (in case of SLAVE/MASTER Request) or OE_N
+   (in case of MASTER Request). Valid values are 0-15, default is 1
+ - nvidia,snor-adv-width: Number of cycles during which ADV stays asserted.
+   Valid values are 0-15, default is 1.
+ - nvidia,snor-ce-width: Number of cycles before CE is asserted.
+   Valid values are 0-15, default is 4
+ - nvidia,snor-we-width: Number of cycles during which WE stays asserted.
+   Valid values are 0-15, default is 1
+ - nvidia,snor-oe-width: Number of cycles during which OE stays asserted.
+   Valid values are 0-255, default is 1
+ - nvidia,snor-wait-width: Number of cycles before READY is asserted.
+   Valid values are 0-255, default is 3
+
+Example with two SJA1000 CAN controllers connected to the GMI bus. We wrap the
+controllers with a simple-bus node since they are all connected to the same
+chip-select (CS4), in this example external address decoding is provided:
+
+gmi@70090000 {
+	compatible = "nvidia,tegra20-gmi";
+	reg = <0x70009000 0x1000>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+	clocks = <&tegra_car TEGRA20_CLK_NOR>;
+	clock-names = "gmi";
+	resets = <&tegra_car 42>;
+	reset-names = "gmi";
+	ranges = <4 0 0xd0000000 0xfffffff>;
+
+	status = "okay";
+
+	bus@4,0 {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 4 0 0x40100>;
+
+		nvidia,snor-mux-mode;
+		nvidia,snor-adv-active-high;
+
+		can@0 {
+			reg = <0 0x100>;
+			...
+		};
+
+		can@40000 {
+			reg = <0x40000 0x100>;
+			...
+		};
+	};
+};
+
+Example with one SJA1000 CAN controller connected to the GMI bus
+on CS4:
+
+gmi@70090000 {
+	compatible = "nvidia,tegra20-gmi";
+	reg = <0x70009000 0x1000>;
+	#address-cells = <2>;
+	#size-cells = <1>;
+	clocks = <&tegra_car TEGRA20_CLK_NOR>;
+	clock-names = "gmi";
+	resets = <&tegra_car 42>;
+	reset-names = "gmi";
+	ranges = <4 0 0xd0000000 0xfffffff>;
+
+	status = "okay";
+
+	can@4,0 {
+		reg = <4 0 0x100>;
+		nvidia,snor-mux-mode;
+		nvidia,snor-adv-active-high;
+		...
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/bus/ti,da850-mstpri.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/bus/ti,da850-mstpri.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/bus/ti,da850-mstpri.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/bus/ti,da850-mstpri.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+* Device tree bindings for Texas Instruments da8xx master peripheral
+  priority driver
+
+DA8XX SoCs feature a set of registers allowing to change the priority of all
+peripherals classified as masters.
+
+Documentation:
+OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh82c/spruh82c.pdf
+
+Required properties:
+
+- compatible:		"ti,da850-mstpri" - for da850 based boards
+- reg:			offset and length of the mstpri registers
+
+Example for da850-lcdk is shown below.
+
+mstpri {
+	compatible = "ti,da850-mstpri";
+	reg = <0x14110 0x0c>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/exynos5433-clock.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/exynos5433-clock.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/exynos5433-clock.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/exynos5433-clock.txt	2017-02-12 16:03:20.000000000 -0500
@@ -79,7 +79,7 @@ Required Properties:
 	Input clocks for fsys clock controller:
 		- oscclk
 		- sclk_ufs_mphy
-		- div_aclk_fsys_200
+		- aclk_fsys_200
 		- sclk_pcie_100_fsys
 		- sclk_ufsunipro_fsys
 		- sclk_mmc2_fsys
@@ -104,6 +104,10 @@ Required Properties:
 		- sclk_decon_tv_vclk_disp
 		- aclk_disp_333
 
+	Input clocks for audio clock controller:
+		- oscclk
+		- fout_aud_pll
+
 	Input clocks for bus0 clock controller:
 		- aclk_bus0_400
 
@@ -235,7 +239,7 @@ Example 2: Examples of clock controller
 
 		clock-names = "oscclk",
 			"sclk_ufs_mphy",
-			"div_aclk_fsys_200",
+			"aclk_fsys_200",
 			"sclk_pcie_100_fsys",
 			"sclk_ufsunipro_fsys",
 			"sclk_mmc2_fsys",
@@ -245,7 +249,7 @@ Example 2: Examples of clock controller
 			"sclk_usbdrd30_fsys";
 		clocks = <&xxti>,
 		       <&cmu_cpif CLK_SCLK_UFS_MPHY>,
-		       <&cmu_top CLK_DIV_ACLK_FSYS_200>,
+		       <&cmu_top CLK_ACLK_FSYS_200>,
 		       <&cmu_top CLK_SCLK_PCIE_100_FSYS>,
 		       <&cmu_top CLK_SCLK_UFSUNIPRO_FSYS>,
 		       <&cmu_top CLK_SCLK_MMC2_FSYS>,
@@ -297,6 +301,9 @@ Example 2: Examples of clock controller
 		compatible = "samsung,exynos5433-cmu-aud";
 		reg = <0x114c0000 0x0b04>;
 		#clock-cells = <1>;
+
+		clock-names = "oscclk", "fout_aud_pll";
+		clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>;
 	};
 
 	cmu_bus0: clock-controller@13600000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/hi3519-crg.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-* Hisilicon Hi3519 Clock and Reset Generator(CRG)
-
-The Hi3519 CRG module provides clock and reset signals to various
-controllers within the SoC.
-
-This binding uses the following bindings:
-    Documentation/devicetree/bindings/clock/clock-bindings.txt
-    Documentation/devicetree/bindings/reset/reset.txt
-
-Required Properties:
-
-- compatible: should be one of the following.
-  - "hisilicon,hi3519-crg" - controller compatible with Hi3519 SoC.
-
-- reg: physical base address of the controller and length of memory mapped
-  region.
-
-- #clock-cells: should be 1.
-
-Each clock is assigned an identifier and client nodes use this identifier
-to specify the clock which they consume.
-
-All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.
-
-- #reset-cells: should be 2.
-
-A reset signal can be controlled by writing a bit register in the CRG module.
-The reset specifier consists of two cells. The first cell represents the
-register offset relative to the base address. The second cell represents the
-bit index in the register.
-
-Example: CRG nodes
-CRG: clock-reset-controller@12010000 {
-	compatible = "hisilicon,hi3519-crg";
-	reg = <0x12010000 0x10000>;
-	#clock-cells = <1>;
-	#reset-cells = <2>;
-};
-
-Example: consumer nodes
-i2c0: i2c@12110000 {
-	compatible = "hisilicon,hi3519-i2c";
-	reg = <0x12110000 0x1000>;
-	clocks = <&CRG HI3519_I2C0_RST>;
-	resets = <&CRG 0xe4 0>;
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/hisi-crg.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/hisi-crg.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/hisi-crg.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/hisi-crg.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,50 @@
+* HiSilicon Clock and Reset Generator(CRG)
+
+The CRG module provides clock and reset signals to various
+modules within the SoC.
+
+This binding uses the following bindings:
+    Documentation/devicetree/bindings/clock/clock-bindings.txt
+    Documentation/devicetree/bindings/reset/reset.txt
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "hisilicon,hi3516cv300-crg"
+  - "hisilicon,hi3516cv300-sysctrl"
+  - "hisilicon,hi3519-crg"
+  - "hisilicon,hi3798cv200-crg"
+  - "hisilicon,hi3798cv200-sysctrl"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in <dt-bindings/clock/hi3519-clock.h>.
+
+- #reset-cells: should be 2.
+
+A reset signal can be controlled by writing a bit register in the CRG module.
+The reset specifier consists of two cells. The first cell represents the
+register offset relative to the base address. The second cell represents the
+bit index in the register.
+
+Example: CRG nodes
+CRG: clock-reset-controller@12010000 {
+	compatible = "hisilicon,hi3519-crg";
+	reg = <0x12010000 0x10000>;
+	#clock-cells = <1>;
+	#reset-cells = <2>;
+};
+
+Example: consumer nodes
+i2c0: i2c@12110000 {
+	compatible = "hisilicon,hi3519-i2c";
+	reg = <0x12110000 0x1000>;
+	clocks = <&CRG HI3519_I2C0_RST>;
+	resets = <&CRG 0xe4 0>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/imx31-clock.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/imx31-clock.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/imx31-clock.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/imx31-clock.txt	2017-02-12 16:03:20.000000000 -0500
@@ -77,7 +77,7 @@ Examples:
 clks: ccm@53f80000{
 	compatible = "fsl,imx31-ccm";
 	reg = <0x53f80000 0x4000>;
-	interrupts = <0 31 0x04 0 53 0x04>;
+	interrupts = <31>, <53>;
 	#clock-cells = <1>;
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/oxnas,stdclk.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,22 +5,15 @@ Please also refer to clock-bindings.txt
 bindings usage.
 
 Required properties:
-- compatible: Should be "oxsemi,ox810se-stdclk"
+- compatible: For OX810SE, should be "oxsemi,ox810se-stdclk"
+	      For OX820, should be "oxsemi,ox820-stdclk"
 - #clock-cells: 1, see below
 
 Parent node should have the following properties :
-- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
-
-For OX810SE, the clock indices are :
- - 0: LEON
- - 1: DMA_SGDMA
- - 2: CIPHER
- - 3: SATA
- - 4: AUDIO
- - 5: USBMPH
- - 6: ETHA
- - 7: PCIA
- - 8: NAND
+- compatible: For OX810SE, should be
+		"oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+	      For OX820, should be
+		"oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd"
 
 example:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/qcom,gcc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@ Required properties :
 			"qcom,gcc-msm8974"
 			"qcom,gcc-msm8974pro"
 			"qcom,gcc-msm8974pro-ac"
+			"qcom,gcc-msm8994"
 			"qcom,gcc-msm8996"
 			"qcom,gcc-mdm9615"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,37 @@
+Qualcomm RPM Clock Controller Binding
+------------------------------------------------
+The RPM is a dedicated hardware engine for managing the shared
+SoC resources in order to keep the lowest power profile. It
+communicates with other hardware subsystems via shared memory
+and accepts clock requests, aggregates the requests and turns
+the clocks on/off or scales them on demand.
+
+Required properties :
+- compatible : shall contain only one of the following. The generic
+               compatible "qcom,rpmcc" should be also included.
+
+			"qcom,rpmcc-msm8916", "qcom,rpmcc"
+			"qcom,rpmcc-apq8064", "qcom,rpmcc"
+
+- #clock-cells : shall contain 1
+
+Example:
+	smd {
+		compatible = "qcom,smd";
+
+		rpm {
+			interrupts = <0 168 1>;
+			qcom,ipc = <&apcs 8 0>;
+			qcom,smd-edge = <15>;
+
+			rpm_requests {
+				compatible = "qcom,rpm-msm8916";
+				qcom,smd-channels = "rpm_requests";
+
+				rpmcc: clock-controller {
+					compatible = "qcom,rpmcc-msm8916", "qcom,rpmcc";
+					#clock-cells = <1>;
+				};
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/qoriq-clock.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/qoriq-clock.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/qoriq-clock.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/qoriq-clock.txt	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,9 @@ Required properties:
 	* "fsl,b4420-clockgen"
 	* "fsl,b4860-clockgen"
 	* "fsl,ls1021a-clockgen"
+	* "fsl,ls1043a-clockgen"
+	* "fsl,ls1046a-clockgen"
+	* "fsl,ls2080a-clockgen"
 	Chassis-version clock strings include:
 	* "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
 	* "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.txt	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,8 @@ They provide the following functionaliti
 
 Required Properties:
   - compatible: Must be one of:
+      - "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
+      - "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
       - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
       - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
 
@@ -22,8 +24,9 @@ Required Properties:
   - clocks: References to external parent clocks, one entry for each entry in
     clock-names
   - clock-names: List of external parent clock names. Valid names are:
-      - "extal" (r8a7795, r8a7796)
+      - "extal" (r8a7743, r8a7745, r8a7795, r8a7796)
       - "extalr" (r8a7795, r8a7796)
+      - "usb_extal" (r8a7743, r8a7745)
 
   - #clock-cells: Must be 2
       - For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,59 @@
+* Rockchip RK1108 Clock and Reset Unit
+
+The RK1108 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk1108-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changeable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk1108-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "ext_vip" - external VIP clock - optional
+ - "ext_i2s" - external I2S clock - optional
+ - "ext_gmac" - external GMAC clock - optional
+ - "hdmiphy" - external clock input derived from HDMI PHY - optional
+ - "usbphy" - external clock input derived from USB PHY - optional
+
+Example: Clock controller node:
+
+	cru: cru@20200000 {
+		compatible = "rockchip,rk1108-cru";
+		reg = <0x20200000 0x1000>;
+		rockchip,grf = <&grf>;
+
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+	uart0: serial@10230000 {
+		compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+		reg = <0x10230000 0x100>;
+		interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+		reg-shift = <2>;
+		reg-io-width = <4>;
+		clocks = <&cru SCLK_UART0>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,9 @@ Please refer to clock-bindings.txt for c
 Please also refer to reset.txt for common reset controller binding usage.
 
 Required properties:
-- compatible: Should be "st,stm32f42xx-rcc"
+- compatible: Should be:
+  "st,stm32f42xx-rcc"
+  "st,stm32f469-rcc"
 - reg: should be register base and length as documented in the
   datasheet
 - #reset-cells: 1, see below
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/sunxi-ccu.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/sunxi-ccu.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/clock/sunxi-ccu.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/clock/sunxi-ccu.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@ Required properties :
 		- "allwinner,sun8i-a23-ccu"
 		- "allwinner,sun8i-a33-ccu"
 		- "allwinner,sun8i-h3-ccu"
+		- "allwinner,sun50i-a64-ccu"
 
 - reg: Must contain the registers base address and length
 - clocks: phandle to the oscillators feeding the CCU. Two are needed:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/cpufreq/brcm,stb-avs-cpu-freq.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,78 @@
+Broadcom AVS mail box and interrupt register bindings
+=====================================================
+
+A total of three DT nodes are required. One node (brcm,avs-cpu-data-mem)
+references the mailbox register used to communicate with the AVS CPU[1]. The
+second node (brcm,avs-cpu-l2-intr) is required to trigger an interrupt on
+the AVS CPU. The interrupt tells the AVS CPU that it needs to process a
+command sent to it by a driver. Interrupting the AVS CPU is mandatory for
+commands to be processed.
+
+The interface also requires a reference to the AVS host interrupt controller,
+so a driver can react to interrupts generated by the AVS CPU whenever a command
+has been processed. See [2] for more information on the brcm,l2-intc node.
+
+[1] The AVS CPU is an independent co-processor that runs proprietary
+firmware. On some SoCs, this firmware supports DFS and DVFS in addition to
+Adaptive Voltage Scaling.
+
+[2] Documentation/devicetree/bindings/interrupt-controller/brcm,l2-intc.txt
+
+
+Node brcm,avs-cpu-data-mem
+--------------------------
+
+Required properties:
+- compatible: must include: brcm,avs-cpu-data-mem and
+              should include: one of brcm,bcm7271-avs-cpu-data-mem or
+                              brcm,bcm7268-avs-cpu-data-mem
+- reg: Specifies base physical address and size of the registers.
+- interrupts: The interrupt that the AVS CPU will use to interrupt the host
+              when a command completed.
+- interrupt-parent: The interrupt controller the above interrupt is routed
+                    through.
+- interrupt-names: The name of the interrupt used to interrupt the host.
+
+Optional properties:
+- None
+
+Node brcm,avs-cpu-l2-intr
+-------------------------
+
+Required properties:
+- compatible: must include: brcm,avs-cpu-l2-intr and
+              should include: one of brcm,bcm7271-avs-cpu-l2-intr or
+                              brcm,bcm7268-avs-cpu-l2-intr
+- reg: Specifies base physical address and size of the registers.
+
+Optional properties:
+- None
+
+
+Example
+=======
+
+	avs_host_l2_intc: interrupt-controller@f04d1200 {
+		#interrupt-cells = <1>;
+		compatible = "brcm,l2-intc";
+		interrupt-parent = <&intc>;
+		reg = <0xf04d1200 0x48>;
+		interrupt-controller;
+		interrupts = <0x0 0x19 0x0>;
+		interrupt-names = "avs";
+	};
+
+	avs-cpu-data-mem@f04c4000 {
+		compatible = "brcm,bcm7271-avs-cpu-data-mem",
+				"brcm,avs-cpu-data-mem";
+		reg = <0xf04c4000 0x60>;
+		interrupts = <0x1a>;
+		interrupt-parent = <&avs_host_l2_intc>;
+		interrupt-names = "sw_intr";
+	};
+
+	avs-cpu-l2-intr@f04d1100 {
+		compatible = "brcm,bcm7271-avs-cpu-l2-intr",
+				"brcm,avs-cpu-l2-intr";
+		reg = <0xf04d1100 0x10>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/crypto/fsl-sec4.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/crypto/fsl-sec4.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/crypto/fsl-sec4.txt	2017-02-12 16:03:20.000000000 -0500
@@ -123,6 +123,9 @@ PROPERTIES
 
 
 EXAMPLE
+
+iMX6QDL/SX requires four clocks
+
 	crypto@300000 {
 		compatible = "fsl,sec-v4.0";
 		fsl,sec-era = <2>;
@@ -139,6 +142,23 @@ EXAMPLE
 		clock-names = "mem", "aclk", "ipg", "emi_slow";
 	};
 
+
+iMX6UL does only require three clocks
+
+	crypto: caam@2140000 {
+		compatible = "fsl,sec-v4.0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x2140000 0x3c000>;
+		ranges = <0 0x2140000 0x3c000>;
+		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+
+		clocks = <&clks IMX6UL_CLK_CAAM_MEM>,
+			 <&clks IMX6UL_CLK_CAAM_ACLK>,
+			 <&clks IMX6UL_CLK_CAAM_IPG>;
+		clock-names = "mem", "aclk", "ipg";
+	};
+
 =====================================================================
 Job Ring (JR) Node
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,112 @@
+Amlogic Meson Display Controller
+================================
+
+The Amlogic Meson Display controller is composed of several components
+that are going to be documented below:
+
+DMC|---------------VPU (Video Processing Unit)----------------|------HHI------|
+   | vd1   _______     _____________    _________________     |               |
+D  |-------|      |----|            |   |                |    |   HDMI PLL    |
+D  | vd2   | VIU  |    | Video Post |   | Video Encoders |<---|-----VCLK      |
+R  |-------|      |----| Processing |   |                |    |               |
+   | osd2  |      |    |            |---| Enci ----------|----|-----VDAC------|
+R  |-------| CSC  |----| Scalers    |   | Encp ----------|----|----HDMI-TX----|
+A  | osd1  |      |    | Blenders   |   | Encl ----------|----|---------------|
+M  |-------|______|----|____________|   |________________|    |               |
+___|__________________________________________________________|_______________|
+
+
+VIU: Video Input Unit
+---------------------
+
+The Video Input Unit is in charge of the pixel scanout from the DDR memory.
+It fetches the frames addresses, stride and parameters from the "Canvas" memory.
+This part is also in charge of the CSC (Colorspace Conversion).
+It can handle 2 OSD Planes and 2 Video Planes.
+
+VPP: Video Post Processing
+--------------------------
+
+The Video Post Processing is in charge of the scaling and blending of the
+various planes into a single pixel stream.
+There is a special "pre-blending" used by the video planes with a dedicated
+scaler and a "post-blending" to merge with the OSD Planes.
+The OSD planes also have a dedicated scaler for one of the OSD.
+
+VENC: Video Encoders
+--------------------
+
+The VENC is composed of the multiple pixel encoders :
+ - ENCI : Interlace Video encoder for CVBS and Interlace HDMI
+ - ENCP : Progressive Video Encoder for HDMI
+ - ENCL : LCD LVDS Encoder
+The VENC Unit gets a Pixel Clocks (VCLK) from a dedicated HDMI PLL and clock
+tree and provides the scanout clock to the VPP and VIU.
+The ENCI is connected to a single VDAC for Composite Output.
+The ENCI and ENCP are connected to an on-chip HDMI Transceiver.
+
+Device Tree Bindings:
+---------------------
+
+VPU: Video Processing Unit
+--------------------------
+
+Required properties:
+- compatible: value should be different for each SoC family as :
+	- GXBB (S905) : "amlogic,meson-gxbb-vpu"
+	- GXL (S905X, S905D) : "amlogic,meson-gxl-vpu"
+	- GXM (S912) : "amlogic,meson-gxm-vpu"
+	followed by the common "amlogic,meson-gx-vpu"
+- reg: base address and size of he following memory-mapped regions :
+	- vpu
+	- hhi
+	- dmc
+- reg-names: should contain the names of the previous memory regions
+- interrupts: should contain the VENC Vsync interrupt number
+
+Required nodes:
+
+The connections to the VPU output video ports are modeled using the OF graph
+bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+The following table lists for each supported model the port number
+corresponding to each VPU output.
+
+		Port 0		Port 1
+-----------------------------------------
+ S905 (GXBB)	CVBS VDAC	HDMI-TX
+ S905X (GXL)	CVBS VDAC	HDMI-TX
+ S905D (GXL)	CVBS VDAC	HDMI-TX
+ S912 (GXM)	CVBS VDAC	HDMI-TX
+
+Example:
+
+tv-connector {
+	compatible = "composite-video-connector";
+
+	port {
+		tv_connector_in: endpoint {
+			remote-endpoint = <&cvbs_vdac_out>;
+		};
+	};
+};
+
+vpu: vpu@d0100000 {
+	compatible = "amlogic,meson-gxbb-vpu";
+	reg = <0x0 0xd0100000 0x0 0x100000>,
+	      <0x0 0xc883c000 0x0 0x1000>,
+	      <0x0 0xc8838000 0x0 0x1000>;
+	reg-names = "vpu", "hhi", "dmc";
+	interrupts = <GIC_SPI 3 IRQ_TYPE_EDGE_RISING>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* CVBS VDAC output port */
+	port@0 {
+		reg = <0>;
+
+		cvbs_vdac_out: endpoint {
+			remote-endpoint = <&tv_connector_in>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,13 @@ Required properties for DPI:
 - port:		Port node with a single endpoint connecting to the panel
 		  device, as defined in [1]
 
+Required properties for VEC:
+- compatible:	Should be "brcm,bcm2835-vec"
+- reg:		Physical base address and length of the registers
+- clocks:	The core clock the unit runs on
+- interrupts:	The interrupt number
+		  See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
+
 Required properties for V3D:
 - compatible:	Should be "brcm,bcm2835-v3d"
 - reg:		Physical base address and length of the V3D's registers
@@ -92,6 +99,13 @@ dpi: dpi@7e208000 {
 	};
 };
 
+vec: vec@7e806000 {
+	compatible = "brcm,bcm2835-vec";
+	reg = <0x7e806000 0x1000>;
+	clocks = <&clocks BCM2835_CLOCK_VEC>;
+	interrupts = <2 27>;
+};
+
 v3d: v3d@7ec00000 {
 	compatible = "brcm,bcm2835-v3d";
 	reg = <0x7ec00000 0x1000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,8 @@ graph bindings specified in Documentatio
 - Video port 0 for RGB input
 - Video port 1 for VGA output
 
+Optional properties:
+- vdd-supply: Power supply for DAC
 
 Example
 -------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,9 @@ Required properties:
 
 Optional properties
 - reg-io-width: the width of the reg:1,4, default set to 1 if not present
-- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
+- ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing,
+  if the property is omitted, a functionally reduced I2C bus
+  controller on DW HDMI is probed
 - clocks, clock-names: phandle to the HDMI CEC clock, name should be "cec"
 
 Example:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/bridge/ti,tfp410.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,46 @@
+TFP410 DPI to DVI encoder
+=========================
+
+Required properties:
+- compatible: "ti,tfp410"
+
+Optional properties:
+- powerdown-gpios: power-down gpio
+- reg: I2C address. If and only if present the device node
+       should be placed into the i2c controller node where the
+       tfp410 i2c is connected to.
+
+Required nodes:
+- Video port 0 for DPI input [1].
+- Video port 1 for DVI output [1].
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example
+-------
+
+tfp410: encoder@0 {
+	compatible = "ti,tfp410";
+	powerdown-gpios = <&twl_gpio 2 GPIO_ACTIVE_LOW>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			tfp410_in: endpoint@0 {
+				remote-endpoint = <&dpi_out>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			tfp410_out: endpoint@0 {
+				remote-endpoint = <&dvi_connector_in>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/ht16k33.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/ht16k33.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/ht16k33.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/ht16k33.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,42 @@
+Holtek ht16k33 RAM mapping 16*8 LED controller driver with keyscan
+-------------------------------------------------------------------------------
+
+Required properties:
+- compatible:		"holtek,ht16k33"
+- reg:			I2C slave address of the chip.
+- interrupt-parent:	A phandle pointing to the interrupt controller
+			serving the interrupt for this chip.
+- interrupts:		Interrupt specification for the key pressed interrupt.
+- refresh-rate-hz:	Display update interval in HZ.
+- debounce-delay-ms:	Debouncing interval time in milliseconds.
+- linux,keymap: 	The keymap for keys as described in the binding
+			document (devicetree/bindings/input/matrix-keymap.txt).
+
+Optional properties:
+- linux,no-autorepeat:	Disable keyrepeat.
+- default-brightness-level: Initial brightness level [0-15] (default: 15).
+
+Example:
+
+&i2c1 {
+	ht16k33: ht16k33@70 {
+		compatible = "holtek,ht16k33";
+		reg = <0x70>;
+		refresh-rate-hz = <20>;
+		debounce-delay-ms = <50>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <5 (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING)>;
+		linux,keymap = <
+			MATRIX_KEY(2, 0, KEY_F6)
+			MATRIX_KEY(3, 0, KEY_F8)
+			MATRIX_KEY(4, 0, KEY_F10)
+			MATRIX_KEY(5, 0, KEY_F4)
+			MATRIX_KEY(6, 0, KEY_F2)
+			MATRIX_KEY(2, 1, KEY_F5)
+			MATRIX_KEY(3, 1, KEY_F7)
+			MATRIX_KEY(4, 1, KEY_F9)
+			MATRIX_KEY(5, 1, KEY_F3)
+			MATRIX_KEY(6, 1, KEY_F1)
+		>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/mxsfb.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/mxsfb.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/mxsfb.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/mxsfb.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,20 +1,57 @@
 * Freescale MXS LCD Interface (LCDIF)
 
+New bindings:
+=============
 Required properties:
-- compatible: Should be "fsl,<chip>-lcdif".  Supported chips include
-  imx23 and imx28.
-- reg: Address and length of the register set for lcdif
-- interrupts: Should contain lcdif interrupts
-- display : phandle to display node (see below for details)
+- compatible:	Should be "fsl,imx23-lcdif" for i.MX23.
+		Should be "fsl,imx28-lcdif" for i.MX28.
+		Should be "fsl,imx6sx-lcdif" for i.MX6SX.
+- reg:		Address and length of the register set for LCDIF
+- interrupts:	Should contain LCDIF interrupt
+- clocks:	A list of phandle + clock-specifier pairs, one for each
+		entry in 'clock-names'.
+- clock-names:	A list of clock names. For MXSFB it should contain:
+    - "pix" for the LCDIF block clock
+    - (MX6SX-only) "axi", "disp_axi" for the bus interface clock
+
+Required sub-nodes:
+  - port: The connection to an encoder chip.
+
+Example:
+
+	lcdif1: display-controller@2220000 {
+		compatible = "fsl,imx6sx-lcdif", "fsl,imx28-lcdif";
+		reg = <0x02220000 0x4000>;
+		interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clks IMX6SX_CLK_LCDIF1_PIX>,
+			 <&clks IMX6SX_CLK_LCDIF_APB>,
+			 <&clks IMX6SX_CLK_DISPLAY_AXI>;
+		clock-names = "pix", "axi", "disp_axi";
+
+		port {
+			parallel_out: endpoint {
+				remote-endpoint = <&panel_in_parallel>;
+			};
+		};
+	};
+
+Deprecated bindings:
+====================
+Required properties:
+- compatible:	Should be "fsl,imx23-lcdif" for i.MX23.
+		Should be "fsl,imx28-lcdif" for i.MX28.
+- reg:		Address and length of the register set for LCDIF
+- interrupts:	Should contain LCDIF interrupts
+- display:	phandle to display node (see below for details)
 
 * display node
 
 Required properties:
-- bits-per-pixel : <16> for RGB565, <32> for RGB888/666.
-- bus-width : number of data lines.  Could be <8>, <16>, <18> or <24>.
+- bits-per-pixel:	<16> for RGB565, <32> for RGB888/666.
+- bus-width:		number of data lines.  Could be <8>, <16>, <18> or <24>.
 
 Required sub-node:
-- display-timings : Refer to binding doc display-timing.txt for details.
+- display-timings:	Refer to binding doc display-timing.txt for details.
 
 Examples:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/auo,g133han01.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/auo,g133han01.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/auo,g133han01.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/auo,g133han01.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+AU Optronics Corporation 13.3" FHD (1920x1080) TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,g133han01"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/auo,g185han01.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/auo,g185han01.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/auo,g185han01.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/auo,g185han01.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+AU Optronics Corporation 18.5" FHD (1920x1080) TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,g185han01"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/auo,t215hvn01.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+AU Optronics Corporation 21.5" FHD (1920x1080) color TFT LCD panel
+
+Required properties:
+- compatible: should be "auo,t215hvn01"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/chunghwa,claa070wp03xg.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+Chunghwa Picture Tubes Ltd. 7" WXGA TFT LCD panel
+
+Required properties:
+- compatible: should be "chunghwa,claa070wp03xg"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/display-timing.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/display-timing.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/display-timing.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/display-timing.txt	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,14 @@ optional properties:
 			- active low  = drive pixel data on falling edge/
 					sample data on rising edge
 			- ignored     = ignored
+ - syncclk-active: with
+			- active high = drive sync on rising edge/
+					sample sync on falling edge of pixel
+					clock
+			- active low  = drive sync on falling edge/
+					sample sync on rising edge of pixel
+					clock
+			- omitted     = same configuration as pixelclk-active
  - interlaced (bool): boolean to enable interlaced mode
  - doublescan (bool): boolean to enable doublescan mode
  - doubleclk (bool): boolean to enable doubleclock mode
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/nvd,9128.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/nvd,9128.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/nvd,9128.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/nvd,9128.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+New Vision Display 7.0" 800 RGB x 480 TFT LCD panel
+
+Required properties:
+- compatible: should be "nvd,9128"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/panel/sharp,lq150x1lg11.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,36 @@
+Sharp 15" LQ150X1LG11 XGA TFT LCD panel
+
+Required properties:
+- compatible: should be "sharp,lq150x1lg11"
+- power-supply: regulator to provide the VCC supply voltage (3.3 volts)
+
+Optional properties:
+- backlight: phandle of the backlight device
+- rlud-gpios: a single GPIO for the RL/UD (rotate 180 degrees) pin.
+- sellvds-gpios: a single GPIO for the SELLVDS pin.
+
+If rlud-gpios and/or sellvds-gpios are not specified, the RL/UD and/or SELLVDS
+pins are assumed to be handled appropriately by the hardware.
+
+Example:
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 100000>;                      /* VBR */
+
+		brightness-levels = <0 20 40 60 80 100>;
+		default-brightness-level = <2>;
+
+		power-supply = <&vdd_12v_reg>;               /* VDD */
+		enable-gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;  /* XSTABY */
+	};
+
+	panel {
+		compatible = "sharp,lq150x1lg11";
+
+		power-supply = <&vcc_3v3_reg>;               /* VCC */
+
+		backlight = <&backlight>;
+		rlud-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;    /* RL/UD */
+		sellvds-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>; /* SELLVDS */
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/renesas,du.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/renesas,du.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/renesas,du.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/renesas,du.txt	2017-02-12 16:03:20.000000000 -0500
@@ -6,9 +6,11 @@ Required Properties:
     - "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
     - "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
     - "renesas,du-r8a7791" for R8A7791 (R-Car M2-W) compatible DU
+    - "renesas,du-r8a7792" for R8A7792 (R-Car V2H) compatible DU
     - "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
     - "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
     - "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
+    - "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU
 
   - reg: A list of base address and length of each memory resource, one for
     each entry in the reg-names property.
@@ -25,10 +27,10 @@ Required Properties:
   - clock-names: Name of the clocks. This property is model-dependent.
     - R8A7779 uses a single functional clock. The clock doesn't need to be
       named.
-    - R8A779[01345] use one functional clock per channel and one clock per LVDS
-      encoder (if available). The functional clocks must be named "du.x" with
-      "x" being the channel numerical index. The LVDS clocks must be named
-      "lvds.x" with "x" being the LVDS encoder numerical index.
+    - R8A779[0123456] use one functional clock per channel and one clock per
+      LVDS encoder (if available). The functional clocks must be named "du.x"
+      with "x" being the channel numerical index. The LVDS clocks must be
+      named "lvds.x" with "x" being the LVDS encoder numerical index.
     - In addition to the functional and encoder clocks, all DU versions also
       support externally supplied pixel clocks. Those clocks are optional.
       When supplied they must be named "dclkin.x" with "x" being the input
@@ -47,9 +49,11 @@ corresponding to each DU output.
  R8A7779 (H1)	DPAD 0		DPAD 1		-		-
  R8A7790 (H2)	DPAD		LVDS 0		LVDS 1		-
  R8A7791 (M2-W)	DPAD		LVDS 0		-		-
+ R8A7792 (V2H)	DPAD 0		DPAD 1		-		-
  R8A7793 (M2-N)	DPAD		LVDS 0		-		-
  R8A7794 (E2)	DPAD 0		DPAD 1		-		-
  R8A7795 (H3)	DPAD		HDMI 0		HDMI 1		LVDS
+ R8A7796 (M3-W)	DPAD		HDMI		LVDS		-
 
 
 Example: R8A7790 (R-Car H2) DU
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,8 @@ The TCON acts as a timing controller for
 Required properties:
  - compatible: value must be either:
    * allwinner,sun5i-a13-tcon
+   * allwinner,sun6i-a31-tcon
+   * allwinner,sun6i-a31s-tcon
    * allwinner,sun8i-a33-tcon
  - reg: base address and size of memory-mapped region
  - interrupts: interrupt associated to this IP
@@ -50,7 +52,7 @@ Required properties:
   second the block connected to the TCON channel 1 (usually the TV
   encoder)
 
-On the A13, there is one more clock required:
+On SoCs other than the A33, there is one more clock required:
    - 'tcon-ch1': The clock driving the TCON channel 1
 
 DRC
@@ -64,6 +66,8 @@ adaptive backlight control.
 
 Required properties:
   - compatible: value must be one of:
+    * allwinner,sun6i-a31-drc
+    * allwinner,sun6i-a31s-drc
     * allwinner,sun8i-a33-drc
   - reg: base address and size of the memory-mapped region.
   - interrupts: interrupt associated to this IP
@@ -87,6 +91,7 @@ system.
 Required properties:
   - compatible: value must be one of:
     * allwinner,sun5i-a13-display-backend
+    * allwinner,sun6i-a31-display-backend
     * allwinner,sun8i-a33-display-backend
   - reg: base address and size of the memory-mapped region.
   - clocks: phandles to the clocks feeding the frontend and backend
@@ -117,6 +122,7 @@ deinterlacing and color space conversion
 Required properties:
   - compatible: value must be one of:
     * allwinner,sun5i-a13-display-frontend
+    * allwinner,sun6i-a31-display-frontend
     * allwinner,sun8i-a33-display-frontend
   - reg: base address and size of the memory-mapped region.
   - interrupts: interrupt associated to this IP
@@ -142,6 +148,8 @@ extra node.
 Required properties:
   - compatible: value must be one of:
     * allwinner,sun5i-a13-display-engine
+    * allwinner,sun6i-a31-display-engine
+    * allwinner,sun6i-a31s-display-engine
     * allwinner,sun8i-a33-display-engine
 
   - allwinner,pipelines: list of phandle to the display engine
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/ti/ti,tfp410.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/ti/ti,tfp410.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/ti/ti,tfp410.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/ti/ti,tfp410.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-TFP410 DPI to DVI encoder
-=========================
-
-Required properties:
-- compatible: "ti,tfp410"
-
-Optional properties:
-- powerdown-gpios: power-down gpio
-
-Required nodes:
-- Video port 0 for DPI input
-- Video port 1 for DVI output
-
-Example
--------
-
-tfp410: encoder@0 {
-	compatible = "ti,tfp410";
-	powerdown-gpios = <&twl_gpio 2 GPIO_ACTIVE_LOW>;
-
-	ports {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		port@0 {
-			reg = <0>;
-
-			tfp410_in: endpoint@0 {
-				remote-endpoint = <&dpi_out>;
-			};
-		};
-
-		port@1 {
-			reg = <1>;
-
-			tfp410_out: endpoint@0 {
-				remote-endpoint = <&dvi_connector_in>;
-			};
-		};
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/tilcdc/tilcdc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,9 @@
 Device-Tree bindings for tilcdc DRM driver
 
 Required properties:
- - compatible: value should be "ti,am33xx-tilcdc".
+ - compatible: value should be one of the following:
+    - "ti,am33xx-tilcdc" for AM335x based boards
+    - "ti,da850-tilcdc" for DA850/AM18x/OMAP-L138 based boards
  - interrupts: the interrupt number
  - reg: base address and size of the LCDC device
 
@@ -51,7 +53,7 @@ Optional nodes:
 Example:
 
 	fb: fb@4830e000 {
-		compatible = "ti,am33xx-tilcdc";
+		compatible = "ti,am33xx-tilcdc", "ti,da850-tilcdc";
 		reg = <0x4830e000 0x1000>;
 		interrupt-parent = <&intc>;
 		interrupts = <36>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/zte,vou.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/zte,vou.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/display/zte,vou.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/display/zte,vou.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,84 @@
+ZTE VOU Display Controller
+
+This is a display controller found on ZTE ZX296718 SoC.  It includes multiple
+Graphic Layer (GL) and Video Layer (VL), two Mixers/Channels, and a few blocks
+handling scaling, color space conversion etc.  VOU also integrates the support
+for typical output devices, like HDMI, TV Encoder, VGA, and RGB LCD.
+
+* Master VOU node
+
+It must be the parent node of all the sub-device nodes.
+
+Required properties:
+ - compatible: should be "zte,zx296718-vou"
+ - #address-cells: should be <1>
+ - #size-cells: should be <1>
+ - ranges: list of address translations between VOU and sub-devices
+
+* VOU DPC device
+
+Required properties:
+ - compatible: should be "zte,zx296718-dpc"
+ - reg: Physical base address and length of DPC register regions, one for each
+   entry in 'reg-names'
+ - reg-names: The names of register regions. The following regions are required:
+	"osd"
+	"timing_ctrl"
+	"dtrc"
+	"vou_ctrl"
+	"otfppu"
+ - interrupts: VOU DPC interrupt number to CPU
+ - clocks: A list of phandle + clock-specifier pairs, one for each entry
+   in 'clock-names'
+ - clock-names: A list of clock names.  The following clocks are required:
+	"aclk"
+	"ppu_wclk"
+	"main_wclk"
+	"aux_wclk"
+
+* HDMI output device
+
+Required properties:
+ - compatible: should be "zte,zx296718-hdmi"
+ - reg: Physical base address and length of the HDMI device IO region
+ - interrupts : HDMI interrupt number to CPU
+ - clocks: A list of phandle + clock-specifier pairs, one for each entry
+   in 'clock-names'
+ - clock-names: A list of clock names.  The following clocks are required:
+	"osc_cec"
+	"osc_clk"
+	"xclk"
+
+Example:
+
+vou: vou@1440000 {
+	compatible = "zte,zx296718-vou";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0x1440000 0x10000>;
+
+	dpc: dpc@0 {
+		compatible = "zte,zx296718-dpc";
+		reg = <0x0000 0x1000>, <0x1000 0x1000>,
+		      <0x5000 0x1000>, <0x6000 0x1000>,
+		      <0xa000 0x1000>;
+		reg-names = "osd", "timing_ctrl",
+			    "dtrc", "vou_ctrl",
+			    "otfppu";
+		interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&topcrm VOU_ACLK>, <&topcrm VOU_PPU_WCLK>,
+			 <&topcrm VOU_MAIN_WCLK>, <&topcrm VOU_AUX_WCLK>;
+		clock-names = "aclk", "ppu_wclk",
+			      "main_wclk", "aux_wclk";
+	};
+
+	hdmi: hdmi@c000 {
+		compatible = "zte,zx296718-hdmi";
+		reg = <0xc000 0x4000>;
+		interrupts = <GIC_SPI 82 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&topcrm HDMI_OSC_CEC>,
+			 <&topcrm HDMI_OSC_CLK>,
+			 <&topcrm HDMI_XCLK>;
+		clock-names = "osc_cec", "osc_clk", "xclk";
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/nbpfaxi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,14 @@ Required properties
 #define NBPF_SLAVE_RQ_LEVEL	4
 
 Optional properties:
+- max-burst-mem-read:	limit burst size for memory reads
+  (DMA_MEM_TO_MEM/DMA_MEM_TO_DEV) to this value, specified in bytes, rather
+  than using the maximum burst size allowed by the hardware's buffer size.
+- max-burst-mem-write:	limit burst size for memory writes
+  (DMA_DEV_TO_MEM/DMA_MEM_TO_MEM) to this value, specified in bytes, rather
+  than using the maximum burst size allowed by the hardware's buffer size.
+  If both max-burst-mem-read and max-burst-mem-write are set, DMA_MEM_TO_MEM
+  will use the lower value.
 
 You can use dma-channels and dma-requests as described in dma.txt, although they
 won't be used, this information is derived from the compatibility string.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/qcom_hidma_mgmt.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,13 +5,13 @@ memcpy and memset capabilities. It has b
 environments.
 
 Each HIDMA HW instance consists of multiple DMA channels. These channels
-share the same bandwidth. The bandwidth utilization can be parititioned
+share the same bandwidth. The bandwidth utilization can be partitioned
 among channels based on the priority and weight assignments.
 
 There are only two priority levels and 15 weigh assignments possible.
 
 Other parameters here determine how much of the system bus this HIDMA
-instance can use like maximum read/write request and and number of bytes to
+instance can use like maximum read/write request and number of bytes to
 read/write in a single burst.
 
 Main node required properties:
@@ -47,12 +47,18 @@ When the OS is not in control of the man
 the channel nodes appear on their own, not under a management node.
 
 Required properties:
-- compatible: must contain "qcom,hidma-1.0"
+- compatible: must contain "qcom,hidma-1.0" for initial HW or "qcom,hidma-1.1"
+for MSI capable HW.
 - reg: Addresses for the transfer and event channel
 - interrupts: Should contain the event interrupt
 - desc-count: Number of asynchronous requests this channel can handle
 - iommus: required a iommu node
 
+Optional properties for MSI:
+- msi-parent : See the generic MSI binding described in
+ devicetree/bindings/interrupt-controller/msi.txt for a description of the
+ msi-parent property.
+
 Example:
 
 Hypervisor OS configuration:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@ Required Properties:
 		- "renesas,dmac-r8a7793" (R-Car M2-N)
 		- "renesas,dmac-r8a7794" (R-Car E2)
 		- "renesas,dmac-r8a7795" (R-Car H3)
+		- "renesas,dmac-r8a7796" (R-Car M3-W)
 
 - reg: base address and length of the registers block for the DMAC
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/snps-dma.txt	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,8 @@ Optional properties:
   that services interrupts for this device
 - is_private: The device channels should be marked as private and not for by the
   general purpose DMA channel allocator. False if not passed.
+- multi-block: Multi block transfers supported by hardware. Array property with
+  one cell per channel. 0: not supported, 1 (default): supported.
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/st_fdma.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/st_fdma.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/dma/st_fdma.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/dma/st_fdma.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,87 @@
+* STMicroelectronics Flexible Direct Memory Access Device Tree bindings
+
+The FDMA is a general-purpose direct memory access controller capable of
+supporting 16 independent DMA channels. It accepts up to 32 DMA requests.
+The FDMA is based on a Slim processor which requires a firmware.
+
+* FDMA Controller
+
+Required properties:
+- compatible	: Should be one of
+		 - st,stih407-fdma-mpe31-11, "st,slim-rproc";
+		 - st,stih407-fdma-mpe31-12, "st,slim-rproc";
+		 - st,stih407-fdma-mpe31-13, "st,slim-rproc";
+- reg		: Should contain an entry for each name in reg-names
+- reg-names	: Must contain "slimcore", "dmem", "peripherals", "imem" entries
+- interrupts	: Should contain one interrupt shared by all channels
+- dma-channels	: Number of channels supported by the controller
+- #dma-cells	: Must be <3>. See DMA client section below
+- clocks	: Must contain an entry for each clock
+See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+
+Example:
+
+	fdma0: dma-controller@8e20000 {
+		compatible = "st,stih407-fdma-mpe31-11", "st,slim-rproc";
+		reg = <0x8e20000 0x8000>,
+		      <0x8e30000 0x3000>,
+		      <0x8e37000 0x1000>,
+		      <0x8e38000 0x8000>;
+		reg-names = "slimcore", "dmem", "peripherals", "imem";
+		clocks = <&clk_s_c0_flexgen CLK_FDMA>,
+			 <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+			 <&clk_s_c0_flexgen CLK_EXT2F_A9>,
+			 <&clk_s_c0_flexgen CLK_EXT2F_A9>;
+		interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>;
+		dma-channels = <16>;
+		#dma-cells = <3>;
+	};
+
+* DMA client
+
+Required properties:
+- dmas: Comma separated list of dma channel requests
+- dma-names: Names of the aforementioned requested channels
+
+Each dmas request consists of 4 cells:
+1. A phandle pointing to the FDMA controller
+2. The request line number
+3. A 32bit mask specifying (see include/linux/platform_data/dma-st-fdma.h)
+ -bit 2-0: Holdoff value, dreq will be masked for
+	0x0: 0-0.5us
+	0x1: 0.5-1us
+	0x2: 1-1.5us
+ -bit 17: data swap
+	0x0: disabled
+	0x1: enabled
+ -bit 21: Increment Address
+	0x0: no address increment between transfers
+	0x1: increment address between transfers
+ -bit 22: 2 STBus Initiator Coprocessor interface
+	0x0: high priority port
+	0x1: low priority port
+4. transfers type
+ 0 free running
+ 1 paced
+
+Example:
+
+	sti_uni_player2: sti-uni-player@2 {
+		compatible = "st,sti-uni-player";
+		status = "disabled";
+		#sound-dai-cells = <0>;
+		st,syscfg = <&syscfg_core>;
+		clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+		assigned-clocks = <&clk_s_d0_flexgen CLK_PCM_2>;
+		assigned-clock-parents = <&clk_s_d0_quadfs 2>;
+		assigned-clock-rates = <50000000>;
+		reg = <0x8D82000 0x158>;
+		interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
+		dmas = <&fdma0 4 0 1>;
+		dai-name = "Uni Player #1 (DAC)";
+		dma-names = "tx";
+		st,uniperiph-id = <2>;
+		st,version = <5>;
+		st,mode = "PCM";
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/extcon/extcon-usb-gpio.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,10 @@ connected to a GPIO pin.
 
 Required properties:
 - compatible: Should be "linux,extcon-usb-gpio"
+
+Either one of id-gpio or vbus-gpio must be present. Both can be present as well.
 - id-gpio: gpio for USB ID pin. See gpio binding.
+- vbus-gpio: gpio for USB VBUS pin.
 
 Example: Examples of extcon-usb-gpio node in dra7-evm.dts as listed below:
 	extcon_usb1 {
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,108 @@
+NVIDIA Tegra Boot and Power Management Processor (BPMP)
+
+The BPMP is a specific processor in Tegra chip, which is designed for
+booting process handling and offloading the power management, clock
+management, and reset control tasks from the CPU. The binding document
+defines the resources that would be used by the BPMP firmware driver,
+which can create the interprocessor communication (IPC) between the CPU
+and BPMP.
+
+Required properties:
+- name : Should be bpmp
+- compatible
+    Array of strings
+    One of:
+    - "nvidia,tegra186-bpmp"
+- mboxes : The phandle of mailbox controller and the mailbox specifier.
+- shmem : List of the phandle of the TX and RX shared memory area that
+	  the IPC between CPU and BPMP is based on.
+- #clock-cells : Should be 1.
+- #power-domain-cells : Should be 1.
+- #reset-cells : Should be 1.
+
+This node is a mailbox consumer. See the following files for details of
+the mailbox subsystem, and the specifiers implemented by the relevant
+provider(s):
+
+- .../mailbox/mailbox.txt
+- .../mailbox/nvidia,tegra186-hsp.txt
+
+This node is a clock, power domain, and reset provider. See the following
+files for general documentation of those features, and the specifiers
+implemented by this node:
+
+- .../clock/clock-bindings.txt
+- <dt-bindings/clock/tegra186-clock.h>
+- ../power/power_domain.txt
+- <dt-bindings/power/tegra186-powergate.h>
+- .../reset/reset.txt
+- <dt-bindings/reset/tegra186-reset.h>
+
+The BPMP implements some services which must be represented by separate nodes.
+For example, it can provide access to certain I2C controllers, and the I2C
+bindings represent each I2C controller as a device tree node. Such nodes should
+be nested directly inside the main BPMP node.
+
+Software can determine whether a child node of the BPMP node represents a device
+by checking for a compatible property. Any node with a compatible property
+represents a device that can be instantiated. Nodes without a compatible
+property may be used to provide configuration information regarding the BPMP
+itself, although no such configuration nodes are currently defined by this
+binding.
+
+The BPMP firmware defines no single global name-/numbering-space for such
+services. Put another way, the numbering scheme for I2C buses is distinct from
+the numbering scheme for any other service the BPMP may provide (e.g. a future
+hypothetical SPI bus service). As such, child device nodes will have no reg
+property, and the BPMP node will have no #address-cells or #size-cells property.
+
+The shared memory bindings for BPMP
+-----------------------------------
+
+The shared memory area for the IPC TX and RX between CPU and BPMP are
+predefined and work on top of sysram, which is an SRAM inside the chip.
+
+See ".../sram/sram.txt" for the bindings.
+
+Example:
+
+hsp_top0: hsp@03c00000 {
+	...
+	#mbox-cells = <2>;
+};
+
+sysram@30000000 {
+	compatible = "nvidia,tegra186-sysram", "mmio-sram";
+	reg = <0x0 0x30000000 0x0 0x50000>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
+
+	cpu_bpmp_tx: shmem@4e000 {
+		compatible = "nvidia,tegra186-bpmp-shmem";
+		reg = <0x0 0x4e000 0x0 0x1000>;
+		label = "cpu-bpmp-tx";
+		pool;
+	};
+
+	cpu_bpmp_rx: shmem@4f000 {
+		compatible = "nvidia,tegra186-bpmp-shmem";
+		reg = <0x0 0x4f000 0x0 0x1000>;
+		label = "cpu-bpmp-rx";
+		pool;
+	};
+};
+
+bpmp {
+	compatible = "nvidia,tegra186-bpmp";
+	mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB TEGRA_HSP_DB_MASTER_BPMP>;
+	shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>;
+	#clock-cells = <1>;
+	#power-domain-cells = <1>;
+	#reset-cells = <1>;
+
+	i2c {
+		compatible = "...";
+		...
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/firmware/qcom,scm.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/firmware/qcom,scm.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/firmware/qcom,scm.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/firmware/qcom,scm.txt	2017-02-12 16:03:20.000000000 -0500
@@ -10,8 +10,10 @@ Required properties:
  * "qcom,scm-apq8064" for APQ8064 platforms
  * "qcom,scm-msm8660" for MSM8660 platforms
  * "qcom,scm-msm8690" for MSM8690 platforms
+ * "qcom,scm-msm8996" for MSM8996 platforms
  * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc)
 - clocks: One to three clocks may be required based on compatible.
+ * No clock required for "qcom,scm-msm8996"
  * Only core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660", and "qcom,scm-msm8960"
  * Core, iface, and bus clocks required for "qcom,scm"
 - clock-names: Must contain "core" for the core clock, "iface" for the interface
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-fpga2sdram-bridge.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,16 @@
+Altera FPGA To SDRAM Bridge Driver
+
+Required properties:
+- compatible		: Should contain "altr,socfpga-fpga2sdram-bridge"
+
+Optional properties:
+- bridge-enable		: 0 if driver should disable bridge at startup
+			  1 if driver should enable bridge at startup
+			  Default is to leave bridge in current state.
+
+Example:
+	fpga_bridge3: fpga-bridge@ffc25080 {
+		compatible = "altr,socfpga-fpga2sdram-bridge";
+		reg = <0xffc25080 0x4>;
+		bridge-enable = <0>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-freeze-bridge.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,23 @@
+Altera Freeze Bridge Controller Driver
+
+The Altera Freeze Bridge Controller manages one or more freeze bridges.
+The controller can freeze/disable the bridges which prevents signal
+changes from passing through the bridge.  The controller can also
+unfreeze/enable the bridges which allows traffic to pass through the
+bridge normally.
+
+Required properties:
+- compatible		: Should contain "altr,freeze-bridge-controller"
+- regs			: base address and size for freeze bridge module
+
+Optional properties:
+- bridge-enable		: 0 if driver should disable bridge at startup
+			  1 if driver should enable bridge at startup
+			  Default is to leave bridge in current state.
+
+Example:
+	freeze-controller@100000450 {
+		compatible = "altr,freeze-bridge-controller";
+		regs = <0x1000 0x10>;
+		bridge-enable = <0>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-hps2fpga-bridge.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,39 @@
+Altera FPGA/HPS Bridge Driver
+
+Required properties:
+- regs		: base address and size for AXI bridge module
+- compatible	: Should contain one of:
+		  "altr,socfpga-lwhps2fpga-bridge",
+		  "altr,socfpga-hps2fpga-bridge", or
+		  "altr,socfpga-fpga2hps-bridge"
+- resets	: Phandle and reset specifier for this bridge's reset
+- clocks	: Clocks used by this module.
+
+Optional properties:
+- bridge-enable	: 0 if driver should disable bridge at startup.
+		  1 if driver should enable bridge at startup.
+		  Default is to leave bridge in its current state.
+
+Example:
+	fpga_bridge0: fpga-bridge@ff400000 {
+		compatible = "altr,socfpga-lwhps2fpga-bridge";
+		reg = <0xff400000 0x100000>;
+		resets = <&rst LWHPS2FPGA_RESET>;
+		clocks = <&l4_main_clk>;
+		bridge-enable = <0>;
+	};
+
+	fpga_bridge1: fpga-bridge@ff500000 {
+		compatible = "altr,socfpga-hps2fpga-bridge";
+		reg = <0xff500000 0x10000>;
+		resets = <&rst HPS2FPGA_RESET>;
+		clocks = <&l4_main_clk>;
+		bridge-enable = <1>;
+	};
+
+	fpga_bridge2: fpga-bridge@ff600000 {
+		compatible = "altr,socfpga-fpga2hps-bridge";
+		reg = <0xff600000 0x100000>;
+		resets = <&rst FPGA2HPS_RESET>;
+		clocks = <&l4_main_clk>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/altera-socfpga-a10-fpga-mgr.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,19 @@
+Altera SOCFPGA Arria10 FPGA Manager
+
+Required properties:
+- compatible : should contain "altr,socfpga-a10-fpga-mgr"
+- reg        : base address and size for memory mapped io.
+               - The first index is for FPGA manager register access.
+               - The second index is for writing FPGA configuration data.
+- resets     : Phandle and reset specifier for the device's reset.
+- clocks     : Clocks used by the device.
+
+Example:
+
+	fpga_mgr: fpga-mgr@ffd03000 {
+		compatible = "altr,socfpga-a10-fpga-mgr";
+		reg = <0xffd03000 0x100
+		       0xffcfe400 0x20>;
+		clocks = <&l4_mp_clk>;
+		resets = <&rst FPGAMGR_RESET>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/fpga-region.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/fpga-region.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/fpga/fpga-region.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/fpga/fpga-region.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,494 @@
+FPGA Region Device Tree Binding
+
+Alan Tull 2016
+
+ CONTENTS
+ - Introduction
+ - Terminology
+ - Sequence
+ - FPGA Region
+ - Supported Use Models
+ - Device Tree Examples
+ - Constraints
+
+
+Introduction
+============
+
+FPGA Regions represent FPGA's and partial reconfiguration regions of FPGA's in
+the Device Tree.  FPGA Regions provide a way to program FPGAs under device tree
+control.
+
+This device tree binding document hits some of the high points of FPGA usage and
+attempts to include terminology used by both major FPGA manufacturers.  This
+document isn't a replacement for any manufacturers specifications for FPGA
+usage.
+
+
+Terminology
+===========
+
+Full Reconfiguration
+ * The entire FPGA is programmed.
+
+Partial Reconfiguration (PR)
+ * A section of an FPGA is reprogrammed while the rest of the FPGA is not
+   affected.
+ * Not all FPGA's support PR.
+
+Partial Reconfiguration Region (PRR)
+ * Also called a "reconfigurable partition"
+ * A PRR is a specific section of a FPGA reserved for reconfiguration.
+ * A base (or static) FPGA image may create a set of PRR's that later may
+   be independently reprogrammed many times.
+ * The size and specific location of each PRR is fixed.
+ * The connections at the edge of each PRR are fixed.  The image that is loaded
+   into a PRR must fit and must use a subset of the region's connections.
+ * The busses within the FPGA are split such that each region gets its own
+   branch that may be gated independently.
+
+Persona
+ * Also called a "partial bit stream"
+ * An FPGA image that is designed to be loaded into a PRR.  There may be
+   any number of personas designed to fit into a PRR, but only one at at time
+   may be loaded.
+ * A persona may create more regions.
+
+FPGA Bridge
+ * FPGA Bridges gate bus signals between a host and FPGA.
+ * FPGA Bridges should be disabled while the FPGA is being programmed to
+   prevent spurious signals on the cpu bus and to the soft logic.
+ * FPGA bridges may be actual hardware or soft logic on an FPGA.
+ * During Full Reconfiguration, hardware bridges between the host and FPGA
+   will be disabled.
+ * During Partial Reconfiguration of a specific region, that region's bridge
+   will be used to gate the busses.  Traffic to other regions is not affected.
+ * In some implementations, the FPGA Manager transparantly handles gating the
+   buses, eliminating the need to show the hardware FPGA bridges in the
+   device tree.
+ * An FPGA image may create a set of reprogrammable regions, each having its
+   own bridge and its own split of the busses in the FPGA.
+
+FPGA Manager
+ * An FPGA Manager is a hardware block that programs an FPGA under the control
+   of a host processor.
+
+Base Image
+ * Also called the "static image"
+ * An FPGA image that is designed to do full reconfiguration of the FPGA.
+ * A base image may set up a set of partial reconfiguration regions that may
+   later be reprogrammed.
+
+    ----------------       ----------------------------------
+    |  Host CPU    |       |             FPGA               |
+    |              |       |                                |
+    |          ----|       |       -----------    --------  |
+    |          | H |       |   |==>| Bridge0 |<==>| PRR0 |  |
+    |          | W |       |   |   -----------    --------  |
+    |          |   |       |   |                            |
+    |          | B |<=====>|<==|   -----------    --------  |
+    |          | R |       |   |==>| Bridge1 |<==>| PRR1 |  |
+    |          | I |       |   |   -----------    --------  |
+    |          | D |       |   |                            |
+    |          | G |       |   |   -----------    --------  |
+    |          | E |       |   |==>| Bridge2 |<==>| PRR2 |  |
+    |          ----|       |       -----------    --------  |
+    |              |       |                                |
+    ----------------       ----------------------------------
+
+Figure 1: An FPGA set up with a base image that created three regions.  Each
+region (PRR0-2) gets its own split of the busses that is independently gated by
+a soft logic bridge (Bridge0-2) in the FPGA.  The contents of each PRR can be
+reprogrammed independently while the rest of the system continues to function.
+
+
+Sequence
+========
+
+When a DT overlay that targets a FPGA Region is applied, the FPGA Region will
+do the following:
+
+ 1. Disable appropriate FPGA bridges.
+ 2. Program the FPGA using the FPGA manager.
+ 3. Enable the FPGA bridges.
+ 4. The Device Tree overlay is accepted into the live tree.
+ 5. Child devices are populated.
+
+When the overlay is removed, the child nodes will be removed and the FPGA Region
+will disable the bridges.
+
+
+FPGA Region
+===========
+
+FPGA Regions represent FPGA's and FPGA PR regions in the device tree.  An FPGA
+Region brings together the elements needed to program on a running system and
+add the child devices:
+
+ * FPGA Manager
+ * FPGA Bridges
+ * image-specific information needed to to the programming.
+ * child nodes
+
+The intended use is that a Device Tree overlay (DTO) can be used to reprogram an
+FPGA while an operating system is running.
+
+An FPGA Region that exists in the live Device Tree reflects the current state.
+If the live tree shows a "firmware-name" property or child nodes under a FPGA
+Region, the FPGA already has been programmed.  A DTO that targets a FPGA Region
+and adds the "firmware-name" property is taken as a request to reprogram the
+FPGA.  After reprogramming is successful, the overlay is accepted into the live
+tree.
+
+The base FPGA Region in the device tree represents the FPGA and supports full
+reconfiguration.  It must include a phandle to an FPGA Manager.  The base
+FPGA region will be the child of one of the hardware bridges (the bridge that
+allows register access) between the cpu and the FPGA.  If there are more than
+one bridge to control during FPGA programming, the region will also contain a
+list of phandles to the additional hardware FPGA Bridges.
+
+For partial reconfiguration (PR), each PR region will have an FPGA Region.
+These FPGA regions are children of FPGA bridges which are then children of the
+base FPGA region.  The "Full Reconfiguration to add PRR's" example below shows
+this.
+
+If an FPGA Region does not specify a FPGA Manager, it will inherit the FPGA
+Manager specified by its ancestor FPGA Region.  This supports both the case
+where the same FPGA Manager is used for all of a FPGA as well the case where
+a different FPGA Manager is used for each region.
+
+FPGA Regions do not inherit their ancestor FPGA regions' bridges.  This prevents
+shutting down bridges that are upstream from the other active regions while one
+region is getting reconfigured (see Figure 1 above).  During PR, the FPGA's
+hardware bridges remain enabled.  The PR regions' bridges will be FPGA bridges
+within the static image of the FPGA.
+
+Required properties:
+- compatible : should contain "fpga-region"
+- fpga-mgr : should contain a phandle to an FPGA Manager.  Child FPGA Regions
+	inherit this property from their ancestor regions.  A fpga-mgr property
+	in a region will override any inherited FPGA manager.
+- #address-cells, #size-cells, ranges : must be present to handle address space
+	mapping for child nodes.
+
+Optional properties:
+- firmware-name : should contain the name of an FPGA image file located on the
+	firmware search path.  If this property shows up in a live device tree
+	it indicates that the FPGA has already been programmed with this image.
+	If this property is in an overlay targeting a FPGA region, it is a
+	request to program the FPGA with that image.
+- fpga-bridges : should contain a list of phandles to FPGA Bridges that must be
+	controlled during FPGA programming along with the parent FPGA bridge.
+	This property is optional if the FPGA Manager handles the bridges.
+        If the fpga-region is  the child of a fpga-bridge, the list should not
+        contain the parent bridge.
+- partial-fpga-config : boolean, set if partial reconfiguration is to be done,
+	otherwise full reconfiguration is done.
+- external-fpga-config : boolean, set if the FPGA has already been configured
+	prior to OS boot up.
+- region-unfreeze-timeout-us : The maximum time in microseconds to wait for
+	bridges to successfully become enabled after the region has been
+	programmed.
+- region-freeze-timeout-us : The maximum time in microseconds to wait for
+	bridges to successfully become disabled before the region has been
+	programmed.
+- child nodes : devices in the FPGA after programming.
+
+In the example below, when an overlay is applied targeting fpga-region0,
+fpga_mgr is used to program the FPGA.  Two bridges are controlled during
+programming: the parent fpga_bridge0 and fpga_bridge1.  Because the region is
+the child of fpga_bridge0, only fpga_bridge1 needs to be specified in the
+fpga-bridges property.  During programming, these bridges are disabled, the
+firmware specified in the overlay is loaded to the FPGA using the FPGA manager
+specified in the region.  If FPGA programming succeeds, the bridges are
+reenabled and the overlay makes it into the live device tree.  The child devices
+are then populated.  If FPGA programming fails, the bridges are left disabled
+and the overlay is rejected.  The overlay's ranges property maps the lwhps
+bridge's region (0xff200000) and the hps bridge's region (0xc0000000) for use by
+the two child devices.
+
+Example:
+Base tree contains:
+
+	fpga_mgr: fpga-mgr@ff706000 {
+		compatible = "altr,socfpga-fpga-mgr";
+		reg = <0xff706000 0x1000
+		       0xffb90000 0x20>;
+		interrupts = <0 175 4>;
+	};
+
+	fpga_bridge0: fpga-bridge@ff400000 {
+		compatible = "altr,socfpga-lwhps2fpga-bridge";
+		reg = <0xff400000 0x100000>;
+		resets = <&rst LWHPS2FPGA_RESET>;
+		clocks = <&l4_main_clk>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		fpga_region0: fpga-region0 {
+			compatible = "fpga-region";
+			fpga-mgr = <&fpga_mgr>;
+		};
+	};
+
+	fpga_bridge1: fpga-bridge@ff500000 {
+		compatible = "altr,socfpga-hps2fpga-bridge";
+		reg = <0xff500000 0x10000>;
+		resets = <&rst HPS2FPGA_RESET>;
+		clocks = <&l4_main_clk>;
+	};
+
+Overlay contains:
+
+/dts-v1/ /plugin/;
+/ {
+	fragment@0 {
+		target = <&fpga_region0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			firmware-name = "soc_system.rbf";
+			fpga-bridges = <&fpga_bridge1>;
+			ranges = <0x20000 0xff200000 0x100000>,
+				 <0x0 0xc0000000 0x20000000>;
+
+			gpio@10040 {
+				compatible = "altr,pio-1.0";
+				reg = <0x10040 0x20>;
+				altr,gpio-bank-width = <4>;
+				#gpio-cells = <2>;
+				clocks = <2>;
+				gpio-controller;
+			};
+
+			onchip-memory {
+				device_type = "memory";
+				compatible = "altr,onchipmem-15.1";
+				reg = <0x0 0x10000>;
+			};
+		};
+	};
+};
+
+
+Supported Use Models
+====================
+
+In all cases the live DT must have the FPGA Manager, FPGA Bridges (if any), and
+a FPGA Region.  The target of the Device Tree Overlay is the FPGA Region.  Some
+uses are specific to a FPGA device.
+
+ * No FPGA Bridges
+   In this case, the FPGA Manager which programs the FPGA also handles the
+   bridges behind the scenes.  No FPGA Bridge devices are needed for full
+   reconfiguration.
+
+ * Full reconfiguration with hardware bridges
+   In this case, there are hardware bridges between the processor and FPGA that
+   need to be controlled during full reconfiguration.  Before the overlay is
+   applied, the live DT must include the FPGA Manager, FPGA Bridges, and a
+   FPGA Region.  The FPGA Region is the child of the bridge that allows
+   register access to the FPGA.  Additional bridges may be listed in a
+   fpga-bridges property in the FPGA region or in the device tree overlay.
+
+ * Partial reconfiguration with bridges in the FPGA
+   In this case, the FPGA will have one or more PRR's that may be programmed
+   separately while the rest of the FPGA can remain active.  To manage this,
+   bridges need to exist in the FPGA that can gate the buses going to each FPGA
+   region while the buses are enabled for other sections.  Before any partial
+   reconfiguration can be done, a base FPGA image must be loaded which includes
+   PRR's with FPGA bridges.  The device tree should have a FPGA region for each
+   PRR.
+
+Device Tree Examples
+====================
+
+The intention of this section is to give some simple examples, focusing on
+the placement of the elements detailed above, especially:
+ * FPGA Manager
+ * FPGA Bridges
+ * FPGA Region
+ * ranges
+ * target-path or target
+
+For the purposes of this section, I'm dividing the Device Tree into two parts,
+each with its own requirements.  The two parts are:
+ * The live DT prior to the overlay being added
+ * The DT overlay
+
+The live Device Tree must contain an FPGA Region, an FPGA Manager, and any FPGA
+Bridges.  The FPGA Region's "fpga-mgr" property specifies the manager by phandle
+to handle programming the FPGA.  If the FPGA Region is the child of another FPGA
+Region, the parent's FPGA Manager is used.  If FPGA Bridges need to be involved,
+they are specified in the FPGA Region by the "fpga-bridges" property.  During
+FPGA programming, the FPGA Region will disable the bridges that are in its
+"fpga-bridges" list and will re-enable them after FPGA programming has
+succeeded.
+
+The Device Tree Overlay will contain:
+ * "target-path" or "target"
+   The insertion point where the the contents of the overlay will go into the
+   live tree.  target-path is a full path, while target is a phandle.
+ * "ranges"
+    The address space mapping from processor to FPGA bus(ses).
+ * "firmware-name"
+   Specifies the name of the FPGA image file on the firmware search
+   path.  The search path is described in the firmware class documentation.
+ * "partial-fpga-config"
+   This binding is a boolean and should be present if partial reconfiguration
+   is to be done.
+ * child nodes corresponding to hardware that will be loaded in this region of
+   the FPGA.
+
+Device Tree Example: Full Reconfiguration without Bridges
+=========================================================
+
+Live Device Tree contains:
+	fpga_mgr0: fpga-mgr@f8007000 {
+		compatible = "xlnx,zynq-devcfg-1.0";
+		reg = <0xf8007000 0x100>;
+		interrupt-parent = <&intc>;
+		interrupts = <0 8 4>;
+		clocks = <&clkc 12>;
+		clock-names = "ref_clk";
+		syscon = <&slcr>;
+	};
+
+	fpga_region0: fpga-region0 {
+		compatible = "fpga-region";
+		fpga-mgr = <&fpga_mgr0>;
+		#address-cells = <0x1>;
+		#size-cells = <0x1>;
+		ranges;
+	};
+
+DT Overlay contains:
+/dts-v1/ /plugin/;
+/ {
+fragment@0 {
+	target = <&fpga_region0>;
+	#address-cells = <1>;
+	#size-cells = <1>;
+	__overlay__ {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		firmware-name = "zynq-gpio.bin";
+
+		gpio1: gpio@40000000 {
+			compatible = "xlnx,xps-gpio-1.00.a";
+			reg = <0x40000000 0x10000>;
+			gpio-controller;
+			#gpio-cells = <0x2>;
+			xlnx,gpio-width= <0x6>;
+		};
+	};
+};
+
+Device Tree Example: Full Reconfiguration to add PRR's
+======================================================
+
+The base FPGA Region is specified similar to the first example above.
+
+This example programs the FPGA to have two regions that can later be partially
+configured.  Each region has its own bridge in the FPGA fabric.
+
+DT Overlay contains:
+/dts-v1/ /plugin/;
+/ {
+	fragment@0 {
+		target = <&fpga_region0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			firmware-name = "base.rbf";
+
+			fpga-bridge@4400 {
+				compatible = "altr,freeze-bridge";
+				reg = <0x4400 0x10>;
+
+				fpga_region1: fpga-region1 {
+					compatible = "fpga-region";
+					#address-cells = <0x1>;
+					#size-cells = <0x1>;
+					ranges;
+				};
+			};
+
+			fpga-bridge@4420 {
+				compatible = "altr,freeze-bridge";
+				reg = <0x4420 0x10>;
+
+				fpga_region2: fpga-region2 {
+					compatible = "fpga-region";
+					#address-cells = <0x1>;
+					#size-cells = <0x1>;
+					ranges;
+				};
+			};
+		};
+	};
+};
+
+Device Tree Example: Partial Reconfiguration
+============================================
+
+This example reprograms one of the PRR's set up in the previous example.
+
+The sequence that occurs when this overlay is similar to the above, the only
+differences are that the FPGA is partially reconfigured due to the
+"partial-fpga-config" boolean and the only bridge that is controlled during
+programming is the FPGA based bridge of fpga_region1.
+
+/dts-v1/ /plugin/;
+/ {
+	fragment@0 {
+		target = <&fpga_region1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		__overlay__ {
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			firmware-name = "soc_image2.rbf";
+			partial-fpga-config;
+
+			gpio@10040 {
+				compatible = "altr,pio-1.0";
+				reg = <0x10040 0x20>;
+				clocks = <0x2>;
+				altr,gpio-bank-width = <0x4>;
+				resetvalue = <0x0>;
+				#gpio-cells = <0x2>;
+				gpio-controller;
+			};
+		};
+	};
+};
+
+Constraints
+===========
+
+It is beyond the scope of this document to fully describe all the FPGA design
+constraints required to make partial reconfiguration work[1] [2] [3], but a few
+deserve quick mention.
+
+A persona must have boundary connections that line up with those of the partion
+or region it is designed to go into.
+
+During programming, transactions through those connections must be stopped and
+the connections must be held at a fixed logic level.  This can be achieved by
+FPGA Bridges that exist on the FPGA fabric prior to the partial reconfiguration.
+
+--
+[1] www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_partrecon.pdf
+[2] tspace.library.utoronto.ca/bitstream/1807/67932/1/Byma_Stuart_A_201411_MAS_thesis.pdf
+[3] http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_1/ug702.pdf
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
 Please refer to gpio.txt for generic information regarding GPIO bindings.
 
 Required properties:
- - compatible: "oxsemi,ox810se-gpio"
+ - compatible: "oxsemi,ox810se-gpio" or "oxsemi,ox820-gpio"
  - reg: Base address and length for the device.
  - interrupts: The port interrupt shared by all pins.
  - gpio-controller: Marks the port as GPIO controller.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/gpio/gpio-sx150x.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-SEMTECH SX150x GPIO expander bindings
-
-
-Required properties:
-
-- compatible: should be "semtech,sx1506q",
-			"semtech,sx1508q",
-			"semtech,sx1509q",
-			"semtech,sx1502q".
-
-- reg: The I2C slave address for this device.
-
-- interrupt-parent: phandle of the parent interrupt controller.
-
-- interrupts: Interrupt specifier for the controllers interrupt.
-
-- #gpio-cells: Should be 2. The first cell is the GPIO number and the
-		second cell is used to specify optional parameters:
-		bit 0: polarity (0: normal, 1: inverted)
-
-- gpio-controller: Marks the device as a GPIO controller.
-
-- interrupt-controller: Marks the device as a interrupt controller.
-
-The GPIO expander can optionally be used as an interrupt controller, in
-which case it uses the default two cell specifier as described in
-Documentation/devicetree/bindings/interrupt-controller/interrupts.txt.
-
-Example:
-
-	i2c_gpio_expander@20{
-		#gpio-cells = <2>;
-		#interrupt-cells = <2>;
-		compatible = "semtech,sx1506q";
-		reg = <0x20>;
-		interrupt-parent = <&gpio_1>;
-		interrupts = <16 0>;
-
-		gpio-controller;
-		interrupt-controller;
-	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/gpio/mrvl-gpio.txt	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,9 @@ Required properties:
 - #interrupt-cells: Specifies the number of cells needed to encode an
   interrupt source.
 - gpio-controller : Marks the device node as a gpio controller.
-- #gpio-cells : Should be one.  It is the pin number.
+- #gpio-cells : Should be two.  The first cell is the pin number and
+  the second cell is used to specify flags. See gpio.txt for possible
+  values.
 
 Example for a MMP platform:
 
@@ -27,7 +29,7 @@ Example for a MMP platform:
 		interrupts = <49>;
 		interrupt-names = "gpio_mux";
 		gpio-controller;
-		#gpio-cells = <1>;
+		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <1>;
       };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/hwmon/mcp3021.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/hwmon/mcp3021.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/hwmon/mcp3021.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/hwmon/mcp3021.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,21 @@
+mcp3021 properties
+
+Required properties:
+- compatible: Must be one of the following:
+	- "microchip,mcp3021" for mcp3021
+	- "microchip,mcp3221" for mcp3221
+- reg: I2C address
+
+Optional properties:
+
+- reference-voltage-microvolt
+	Reference voltage in microvolt (uV)
+
+Example:
+
+mcp3021@4d {
+	compatible = "microchip,mcp3021";
+	reg = <0x4d>;
+
+	reference-voltage-microvolt = <4500000>; /* 4.5 V */
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/hwmon/tmp108.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/hwmon/tmp108.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/hwmon/tmp108.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/hwmon/tmp108.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,14 @@
+TMP108 temperature sensor
+-------------------------
+
+This device supports I2C only.
+
+Requires node properties:
+- compatible : "ti,tmp108"
+- reg : the I2C address of the device. This is 0x48, 0x49, 0x4a, or 0x4b.
+
+Example:
+	tmp108@48 {
+		compatible = "ti,tmp108";
+		reg = <0x48>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+* Freescale Low Power Inter IC (LPI2C) for i.MX
+
+Required properties:
+- compatible :
+  - "fsl,imx7ulp-lpi2c" for LPI2C compatible with the one integrated on i.MX7ULP soc
+  - "fsl,imx8dv-lpi2c" for LPI2C compatible with the one integrated on i.MX8DV soc
+- reg : address and length of the lpi2c master registers
+- interrupt-parent : core interrupt controller
+- interrupts : lpi2c interrupt
+- clocks : lpi2c clock specifier
+
+Examples:
+
+lpi2c7: lpi2c7@40A50000 {
+	compatible = "fsl,imx8dv-lpi2c";
+	reg = <0x40A50000 0x10000>;
+	interrupt-parent = <&intc>;
+	interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&clks IMX7ULP_CLK_LPI2C7>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-pxa.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-pxa.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-pxa.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-pxa.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@ Required properties :
    compatible processor, e.g. pxa168, pxa910, mmp2, mmp3.
    For the pxa2xx/pxa3xx, an additional node "mrvl,pxa-i2c" is required
    as shown in the example below.
+   For the Armada 3700, the compatible should be "marvell,armada-3700-i2c".
 
 Recommended properties :
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-rcar.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,17 +1,25 @@
 I2C for R-Car platforms
 
 Required properties:
-- compatible: Must be one of
-	"renesas,i2c-rcar"
-	"renesas,i2c-r8a7778"
-	"renesas,i2c-r8a7779"
-	"renesas,i2c-r8a7790"
-	"renesas,i2c-r8a7791"
-	"renesas,i2c-r8a7792"
-	"renesas,i2c-r8a7793"
-	"renesas,i2c-r8a7794"
-	"renesas,i2c-r8a7795"
-	"renesas,i2c-r8a7796"
+- compatible:
+	"renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC.
+	"renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC.
+	"renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC.
+	"renesas,i2c-r8a7791" if the device is a part of a R8A7791 SoC.
+	"renesas,i2c-r8a7792" if the device is a part of a R8A7792 SoC.
+	"renesas,i2c-r8a7793" if the device is a part of a R8A7793 SoC.
+	"renesas,i2c-r8a7794" if the device is a part of a R8A7794 SoC.
+	"renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC.
+	"renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
+	"renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
+	"renesas,rcar-gen2-i2c" for a generic R-Car Gen2 compatible device.
+	"renesas,rcar-gen3-i2c" for a generic R-Car Gen3 compatible device.
+	"renesas,i2c-rcar" (deprecated)
+
+	When compatible with the generic version, nodes must list the
+	SoC-specific version corresponding to the platform first followed
+	by the generic version.
+
 - reg: physical base address of the controller and length of memory mapped
   region.
 - interrupts: interrupt specifier.
@@ -33,7 +41,7 @@ Examples :
 i2c0: i2c@e6508000 {
 	#address-cells = <1>;
 	#size-cells = <0>;
-	compatible = "renesas,i2c-r8a7791";
+	compatible = "renesas,i2c-r8a7791", "renesas,rcar-gen2-i2c";
 	reg = <0 0xe6508000 0 0x40>;
 	interrupts = <0 287 IRQ_TYPE_LEVEL_HIGH>;
 	clocks = <&mstp9_clks R8A7791_CLK_I2C0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c-sh_mobile.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,8 +1,7 @@
 Device tree configuration for Renesas IIC (sh_mobile) driver
 
 Required properties:
-- compatible      : "renesas,iic-<soctype>". "renesas,rmobile-iic" as fallback
-		     Examples with soctypes are:
+- compatible      :
 			- "renesas,iic-r8a73a4" (R-Mobile APE6)
 			- "renesas,iic-r8a7740" (R-Mobile A1)
 			- "renesas,iic-r8a7790" (R-Car H2)
@@ -12,6 +11,17 @@ Required properties:
 			- "renesas,iic-r8a7794" (R-Car E2)
 			- "renesas,iic-r8a7795" (R-Car H3)
 			- "renesas,iic-sh73a0" (SH-Mobile AG5)
+			- "renesas,rcar-gen2-iic" (generic R-Car Gen2 compatible device)
+			- "renesas,rcar-gen3-iic" (generic R-Car Gen3 compatible device)
+			- "renesas,rmobile-iic" (generic device)
+
+			When compatible with a generic R-Car version, nodes
+			must list the SoC-specific version corresponding to
+			the platform first followed by the generic R-Car
+			version.
+
+			renesas,rmobile-iic must always follow.
+
 - reg             : address start and address range size of device
 - interrupts      : interrupt of device
 - clocks          : clock for device
@@ -31,7 +41,8 @@ Pinctrl properties might be needed, too.
 Example:
 
 	iic0: i2c@e6500000 {
-		compatible = "renesas,iic-r8a7790", "renesas,rmobile-iic";
+		compatible = "renesas,iic-r8a7790", "renesas,rcar-gen2-iic",
+			     "renesas,rmobile-iic";
 		reg = <0 0xe6500000 0 0x425>;
 		interrupts = <0 174 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A7790_CLK_IIC0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/i2c.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/i2c.txt	2017-02-12 16:03:20.000000000 -0500
@@ -62,6 +62,9 @@ wants to support one of the below featur
 	"irq" and "wakeup" names are recognized by I2C core, other names are
 	left to individual drivers.
 
+- host-notify
+	device uses SMBus host notify protocol instead of interrupt line.
+
 - multi-master
 	states that there is another master active on this bus. The OS can use
 	this information to adapt power management to keep the arbitration awake
@@ -81,6 +84,11 @@ Binding may contain optional "interrupts
 used by the device. I2C core will assign "irq" interrupt (or the very first
 interrupt if not using interrupt names) as primary interrupt for the slave.
 
+Alternatively, devices supporting SMbus Host Notify, and connected to
+adapters that support this feature, may use "host-notify" property. I2C
+core will create a virtual interrupt for Host Notify and assign it as
+primary interrupt for the slave.
+
 Also, if device is marked as a wakeup source, I2C core will set up "wakeup"
 interrupt for the device. If "wakeup" interrupt name is not present in the
 binding, then primary interrupt will be used as wakeup interrupt.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/i2c/trivial-devices.txt	2017-02-12 16:03:20.000000000 -0500
@@ -39,11 +39,13 @@ dallas,ds75		Digital Thermometer and The
 dlg,da9053		DA9053: flexible system level PMIC with multicore support
 dlg,da9063		DA9063: system PMIC for quad-core application processors
 domintech,dmard09	DMARD09: 3-axis Accelerometer
+domintech,dmard10	DMARD10: 3-axis Accelerometer
 epson,rx8010		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
 epson,rx8025		High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE
 epson,rx8581		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
 fsl,mag3110		MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
 fsl,mc13892		MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
+fsl,mma7660		MMA7660FC: 3-Axis Orientation/Motion Detection Sensor
 fsl,mma8450		MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
 fsl,mpl3115		MPL3115: Absolute Digital Pressure Sensor
 fsl,mpr121		MPR121: Proximity Capacitive Touch Sensor Controller
@@ -57,6 +59,7 @@ maxim,max1237		Low-Power, 4-/12-Channel,
 maxim,max6625		9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
 mc,rv3029c2		Real Time Clock Module with I2C-Bus
 mcube,mc3230		mCube 3-axis 8-bit digital accelerometer
+memsic,mxc6225		MEMSIC 2-axis 8-bit digital accelerometer
 microchip,mcp4531-502	Microchip 7-bit Single I2C Digital Potentiometer (5k)
 microchip,mcp4531-103	Microchip 7-bit Single I2C Digital Potentiometer (10k)
 microchip,mcp4531-503	Microchip 7-bit Single I2C Digital Potentiometer (50k)
@@ -121,6 +124,11 @@ microchip,mcp4662-502	Microchip 8-bit Du
 microchip,mcp4662-103	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
 microchip,mcp4662-503	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
 microchip,mcp4662-104	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
+microchip,tc654		PWM Fan Speed Controller With Fan Fault Detection
+microchip,tc655		PWM Fan Speed Controller With Fan Fault Detection
+miramems,da226		MiraMEMS DA226 2-axis 14-bit digital accelerometer
+miramems,da280		MiraMEMS DA280 3-axis 14-bit digital accelerometer
+miramems,da311		MiraMEMS DA311 3-axis 12-bit digital accelerometer
 national,lm63		Temperature sensor with integrated fan control
 national,lm75		I2C TEMP SENSOR
 national,lm80		Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
@@ -130,6 +138,8 @@ nuvoton,npct501		i2c trusted platform mo
 nuvoton,npct601		i2c trusted platform module (TPM2)
 nxp,pca9556		Octal SMBus and I2C registered interface
 nxp,pca9557		8-bit I2C-bus and SMBus I/O port with reset
+nxp,pcf2127		Real-time clock
+nxp,pcf2129		Real-time clock
 nxp,pcf8563		Real-time clock/calendar
 nxp,pcf85063		Tiny Real-Time Clock
 oki,ml86v7667		OKI ML86V7667 video decoder
@@ -146,6 +156,7 @@ ricoh,rv5c387a		I2C bus SERIAL INTERFACE
 samsung,24ad0xd1	S524AD0XF1 (128K/256K-bit Serial EEPROM for Low Power)
 sgx,vz89x		SGX Sensortech VZ89X Sensors
 sii,s35390a		2-wire CMOS real-time clock
+silabs,si7020		Relative Humidity and Temperature Sensors
 skyworks,sky81452	Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
 st,24c256		i2c serial eeprom  (24cxx)
 st,m41t00		Serial real-time clock (RTC)
@@ -158,4 +169,5 @@ ti,tsc2003		I2C Touch-Screen Controller
 ti,tmp102		Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
 ti,tmp103		Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface
 ti,tmp275		Digital Temperature Sensor
+winbond,w83793		Winbond/Nuvoton H/W Monitor
 winbond,wpct301		i2c trusted platform module (TPM)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/adc/envelope-detector.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/adc/envelope-detector.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/adc/envelope-detector.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/adc/envelope-detector.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,54 @@
+Bindings for ADC envelope detector using a DAC and a comparator
+
+The DAC is used to find the peak level of an alternating voltage input
+signal by a binary search using the output of a comparator wired to
+an interrupt pin. Like so:
+                          _
+                         | \
+    input +------>-------|+ \
+                         |   \
+           .-------.     |    }---.
+           |       |     |   /    |
+           |    dac|-->--|- /     |
+           |       |     |_/      |
+           |       |              |
+           |       |              |
+           |    irq|------<-------'
+           |       |
+           '-------'
+
+Required properties:
+- compatible: Should be "axentia,tse850-envelope-detector"
+- io-channels: Channel node of the dac to be used for comparator input.
+- io-channel-names: Should be "dac".
+- interrupt specification for one client interrupt,
+  see ../../interrupt-controller/interrupts.txt for details.
+- interrupt-names: Should be "comp".
+
+Example:
+
+	&i2c {
+		dpot: mcp4651-104@28 {
+			compatible = "microchip,mcp4651-104";
+			reg = <0x28>;
+			#io-channel-cells = <1>;
+		};
+	};
+
+	dac: dac {
+		compatible = "dpot-dac";
+		vref-supply = <&reg_3v3>;
+		io-channels = <&dpot 0>;
+		io-channel-names = "dpot";
+		#io-channel-cells = <1>;
+	};
+
+	envelope-detector {
+		compatible = "axentia,tse850-envelope-detector";
+		io-channels = <&dac 0>;
+		io-channel-names = "dac";
+
+		interrupt-parent = <&gpio>;
+		interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-names = "comp";
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,83 @@
+STMicroelectronics STM32 ADC device driver
+
+STM32 ADC is a successive approximation analog-to-digital converter.
+It has several multiplexed input channels. Conversions can be performed
+in single, continuous, scan or discontinuous mode. Result of the ADC is
+stored in a left-aligned or right-aligned 32-bit data register.
+Conversions can be launched in software or using hardware triggers.
+
+The analog watchdog feature allows the application to detect if the input
+voltage goes beyond the user-defined, higher or lower thresholds.
+
+Each STM32 ADC block can have up to 3 ADC instances.
+
+Each instance supports two contexts to manage conversions, each one has its
+own configurable sequence and trigger:
+- regular conversion can be done in sequence, running in background
+- injected conversions have higher priority, and so have the ability to
+  interrupt regular conversion sequence (either triggered in SW or HW).
+  Regular sequence is resumed, in case it has been interrupted.
+
+Contents of a stm32 adc root node:
+-----------------------------------
+Required properties:
+- compatible: Should be "st,stm32f4-adc-core".
+- reg: Offset and length of the ADC block register set.
+- interrupts: Must contain the interrupt for ADC block.
+- clocks: Clock for the analog circuitry (common to all ADCs).
+- clock-names: Must be "adc".
+- interrupt-controller: Identifies the controller node as interrupt-parent
+- vref-supply: Phandle to the vref input analog reference voltage.
+- #interrupt-cells = <1>;
+- #address-cells = <1>;
+- #size-cells = <0>;
+
+Optional properties:
+- A pinctrl state named "default" for each ADC channel may be defined to set
+  inX ADC pins in mode of operation for analog input on external pin.
+
+Contents of a stm32 adc child node:
+-----------------------------------
+An ADC block node should contain at least one subnode, representing an
+ADC instance available on the machine.
+
+Required properties:
+- compatible: Should be "st,stm32f4-adc".
+- reg: Offset of ADC instance in ADC block (e.g. may be 0x0, 0x100, 0x200).
+- clocks: Input clock private to this ADC instance.
+- interrupt-parent: Phandle to the parent interrupt controller.
+- interrupts: IRQ Line for the ADC (e.g. may be 0 for adc@0, 1 for adc@100 or
+  2 for adc@200).
+- st,adc-channels: List of single-ended channels muxed for this ADC.
+  It can have up to 16 channels, numbered from 0 to 15 (resp. for in0..in15).
+- #io-channel-cells = <1>: See the IIO bindings section "IIO consumers" in
+  Documentation/devicetree/bindings/iio/iio-bindings.txt
+
+Example:
+	adc: adc@40012000 {
+		compatible = "st,stm32f4-adc-core";
+		reg = <0x40012000 0x400>;
+		interrupts = <18>;
+		clocks = <&rcc 0 168>;
+		clock-names = "adc";
+		vref-supply = <&reg_vref>;
+		interrupt-controller;
+		pinctrl-names = "default";
+		pinctrl-0 = <&adc3_in8_pin>;
+
+		#interrupt-cells = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		adc@0 {
+			compatible = "st,stm32f4-adc";
+			#io-channel-cells = <1>;
+			reg = <0x0>;
+			clocks = <&rcc 0 168>;
+			interrupt-parent = <&adc>;
+			interrupts = <0>;
+			st,adc-channels = <8>;
+		};
+		...
+		other adc child nodes follow...
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/adc/ti-adc161s626.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,6 +3,7 @@
 Required properties:
  - compatible: Should be "ti,adc141s626" or "ti,adc161s626"
  - reg: spi chip select number for the device
+ - vdda-supply: supply voltage to VDDA pin
 
 Recommended properties:
  - spi-max-frequency: Definition as per
@@ -11,6 +12,7 @@ Recommended properties:
 Example:
 adc@0 {
 	compatible = "ti,adc161s626";
+	vdda-supply = <&vdda_fixed>;
 	reg = <0>;
 	spi-max-frequency = <4300000>;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/dac/dpot-dac.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/dac/dpot-dac.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/dac/dpot-dac.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/dac/dpot-dac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+Bindings for DAC emulation using a digital potentiometer
+
+It is assumed that the dpot is used as a voltage divider between the
+current dpot wiper setting and the maximum resistance of the dpot. The
+divided voltage is provided by a vref regulator.
+
+                  .------.
+   .-----------.  |      |
+   | vref      |--'    .---.
+   | regulator |--.    |   |
+   '-----------'  |    | d |
+                  |    | p |
+                  |    | o |  wiper
+                  |    | t |<---------+
+                  |    |   |
+                  |    '---'       dac output voltage
+                  |      |
+                  '------+------------+
+
+Required properties:
+- compatible: Should be "dpot-dac"
+- vref-supply: The regulator supplying the voltage divider.
+- io-channels: Channel node of the dpot to be used for the voltage division.
+- io-channel-names: Should be "dpot".
+
+Example:
+
+	&i2c {
+		dpot: mcp4651-503@28 {
+			compatible = "microchip,mcp4651-503";
+			reg = <0x28>;
+			#io-channel-cells = <1>;
+		};
+	};
+
+	dac {
+		compatible = "dpot-dac";
+		vref-supply = <&reg_3v3>;
+		io-channels = <&dpot 0>;
+		io-channel-names = "dpot";
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/dac/mcp4725.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/dac/mcp4725.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/dac/mcp4725.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/dac/mcp4725.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,35 @@
+Microchip mcp4725 and mcp4726 DAC device driver
+
+Required properties:
+	- compatible: Must be "microchip,mcp4725" or "microchip,mcp4726"
+	- reg: Should contain the DAC I2C address
+	- vdd-supply: Phandle to the Vdd power supply. This supply is used as a
+	  voltage reference on mcp4725. It is used as a voltage reference on
+	  mcp4726 if there is no vref-supply specified.
+
+Optional properties (valid only for mcp4726):
+	- vref-supply: Optional phandle to the Vref power supply. Vref pin is
+	  used as a voltage reference when this supply is specified.
+	- microchip,vref-buffered: Boolean to enable buffering of the external
+	  Vref pin. This boolean is not valid without the vref-supply. Quoting
+	  the datasheet: This is offered in cases where the reference voltage
+	  does not have the current capability not to drop its voltage when
+	  connected to the internal resistor ladder circuit.
+
+Examples:
+
+	/* simple mcp4725 */
+	mcp4725@60 {
+		compatible = "microchip,mcp4725";
+		reg = <0x60>;
+		vdd-supply = <&vdac_vdd>;
+	};
+
+	/* mcp4726 with the buffered external reference voltage */
+	mcp4726@60 {
+		compatible = "microchip,mcp4726";
+		reg = <0x60>;
+		vdd-supply = <&vdac_vdd>;
+		vref-supply = <&vdac_vref>;
+		microchip,vref-buffered;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,46 @@
+Invensense MPU-3050 Gyroscope device tree bindings
+
+Required properties:
+  - compatible : should be "invensense,mpu3050"
+  - reg : the I2C address of the sensor
+
+Optional properties:
+  - interrupt-parent : should be the phandle for the interrupt controller
+  - interrupts : interrupt mapping for the trigger interrupt from the
+    internal oscillator. The following IRQ modes are supported:
+    IRQ_TYPE_EDGE_RISING, IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_LEVEL_HIGH and
+    IRQ_TYPE_LEVEL_LOW. The driver should detect and configure the hardware
+    for the desired interrupt type.
+  - vdd-supply : supply regulator for the main power voltage.
+  - vlogic-supply : supply regulator for the signal voltage.
+  - mount-matrix : see iio/mount-matrix.txt
+
+Optional subnodes:
+  - The MPU-3050 will pass through and forward the I2C signals from the
+    incoming I2C bus, alternatively drive traffic to a slave device (usually
+    an accelerometer) on its own initiative. Therefore is supports a subnode
+    i2c gate node. For details see: i2c/i2c-gate.txt
+
+Example:
+
+mpu3050@68 {
+	compatible = "invensense,mpu3050";
+	reg = <0x68>;
+	interrupt-parent = <&foo>;
+	interrupts = <12 IRQ_TYPE_EDGE_FALLING>;
+	vdd-supply = <&bar>;
+	vlogic-supply = <&baz>;
+
+	/* External I2C interface */
+	i2c-gate {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		fnord@18 {
+			compatible = "fnord";
+			reg = <0x18>;
+			interrupt-parent = <&foo>;
+			interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/humidity/hts221.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/humidity/hts221.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/humidity/hts221.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/humidity/hts221.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,22 @@
+* HTS221 STM humidity + temperature sensor
+
+Required properties:
+- compatible: should be "st,hts221"
+- reg: i2c address of the sensor / spi cs line
+
+Optional properties:
+- interrupt-parent: should be the phandle for the interrupt controller
+- interrupts: interrupt mapping for IRQ. It should be configured with
+  flags IRQ_TYPE_LEVEL_HIGH or IRQ_TYPE_EDGE_RISING.
+
+  Refer to interrupt-controller/interrupts.txt for generic interrupt
+  client node bindings.
+
+Example:
+
+hts221@5f {
+	compatible = "st,hts221";
+	reg = <0x5f>;
+	interrupt-parent = <&gpio0>;
+	interrupts = <0 IRQ_TYPE_EDGE_RISING>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/light/isl29018.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/light/isl29018.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/light/isl29018.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/light/isl29018.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,28 @@
+* ISL 29018/29023/29035 I2C ALS, Proximity, and Infrared sensor
+
+Required properties:
+
+  - compatible: Should be one of
+		"isil,isl29018"
+		"isil,isl29023"
+		"isil,isl29035"
+  - reg: the I2C address of the device
+
+Optional properties:
+
+  - interrupt-parent: should be the phandle for the interrupt controller
+  - interrupts: the sole interrupt generated by the device
+
+  Refer to interrupt-controller/interrupts.txt for generic interrupt client
+  node bindings.
+
+  - vcc-supply: phandle to the regulator that provides power to the sensor.
+
+Example:
+
+isl29018@44 {
+	compatible = "isil,isl29018";
+	reg = <0x44>;
+	interrupt-parent = <&gpio>;
+	interrupts = <TEGRA_GPIO(Z, 2) IRQ_TYPE_LEVEL_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/light/tsl2583.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/light/tsl2583.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/light/tsl2583.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/light/tsl2583.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,26 @@
+* TAOS TSL 2580/2581/2583 ALS sensor
+
+Required properties:
+
+  - compatible: Should be one of
+		"amstaos,tsl2580"
+		"amstaos,tsl2581"
+		"amstaos,tsl2583"
+  - reg: the I2C address of the device
+
+Optional properties:
+
+  - interrupt-parent: should be the phandle for the interrupt controller
+  - interrupts: the sole interrupt generated by the device
+
+  Refer to interrupt-controller/interrupts.txt for generic interrupt client
+  node bindings.
+
+  - vcc-supply: phandle to the regulator that provides power to the sensor.
+
+Example:
+
+tsl2581@29 {
+	compatible = "amstaos,tsl2581";
+	reg = <0x29>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/potentiostat/lmp91000.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,30 @@
+* Texas Instruments LMP91000 potentiostat
+
+http://www.ti.com/lit/ds/symlink/lmp91000.pdf
+
+Required properties:
+
+  - compatible: should be "ti,lmp91000"
+  - reg: the I2C address of the device
+  - io-channels: the phandle of the iio provider
+
+  - ti,external-tia-resistor: if the property ti,tia-gain-ohm is not defined this
+    needs to be set to signal that an external resistor value is being used.
+
+Optional properties:
+
+  - ti,tia-gain-ohm: ohm value of the internal resistor for the transimpedance
+    amplifier. Must be 2750, 3500, 7000, 14000, 35000, 120000, or 350000 ohms.
+
+  - ti,rload-ohm: ohm value of the internal resistor load applied to the gas
+    sensor. Must be 10, 33, 50, or 100 (default) ohms.
+
+Example:
+
+lmp91000@48 {
+	compatible = "ti,lmp91000";
+	reg = <0x48>;
+	ti,tia-gain-ohm = <7500>;
+	ti,rload = <100>;
+	io-channels = <&adc>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/iio/st-sensors.txt	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,7 @@ Accelerometers:
 - st,lsm303agr-accel
 - st,lis2dh12-accel
 - st,h3lis331dl-accel
+- st,lng2dm-accel
 
 Gyroscopes:
 - st,l3g4200d-gyro
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/da9062-onkey.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/da9062-onkey.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/da9062-onkey.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/da9062-onkey.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,32 +1,47 @@
-* Dialog DA9062/63 OnKey Module
+* Dialog DA9061/62/63 OnKey Module
 
-This module is part of the DA9062/DA9063. For more details about entire
-chips see Documentation/devicetree/bindings/mfd/da9062.txt and
-Documentation/devicetree/bindings/mfd/da9063.txt
+This module is part of the DA9061/DA9062/DA9063. For more details about entire
+DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
+For DA9063 see Documentation/devicetree/bindings/mfd/da9063.txt
 
-This module provides KEY_POWER, KEY_SLEEP and events.
+This module provides the KEY_POWER event.
 
 Required properties:
 
-- compatible: should be one of:
-	dlg,da9062-onkey
-	dlg,da9063-onkey
+- compatible: should be one of the following valid compatible string lines:
+	"dlg,da9061-onkey", "dlg,da9062-onkey"
+	"dlg,da9062-onkey"
+	"dlg,da9063-onkey"
 
 Optional properties:
 
-  - dlg,disable-key-power : Disable power-down using a long key-press. If this
+- dlg,disable-key-power : Disable power-down using a long key-press. If this
     entry exists the OnKey driver will remove support for the KEY_POWER key
-    press. If this entry does not exist then by default the key-press
-    triggered power down is enabled and the OnKey will support both KEY_POWER
-    and KEY_SLEEP.
-
-Example:
+    press when triggered using a long press of the OnKey.
 
-	pmic0: da9062@58 {
+Example: DA9063
 
+	pmic0: da9063@58 {
 		onkey {
 			compatible = "dlg,da9063-onkey";
 			dlg,disable-key-power;
 		};
+	};
+
+Example: DA9062
+
+	pmic0: da9062@58 {
+		onkey {
+			compatible = "dlg,da9062-onkey";
+			dlg,disable-key-power;
+		};
+	};
+
+Example: DA9061 using a fall-back compatible for the DA9062 onkey driver
 
+	pmic0: da9061@58 {
+		onkey {
+			compatible = "dlg,da9061-onkey", "dlg,da9062-onkey";
+			dlg,disable-key-power;
+		};
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/touchscreen/imx6ul_tsc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,8 @@ Optional properties:
   This value depends on the touch screen.
 - pre-charge-time: the touch screen need some time to precharge.
   This value depends on the touch screen.
+- touchscreen-average-samples: Number of data samples which are averaged for
+  each read. Valid values are 1, 4, 8, 16 and 32.
 
 Example:
 	tsc: tsc@02040000 {
@@ -32,5 +34,6 @@ Example:
 		xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
 		measure-delay-time = <0xfff>;
 		pre-charge-time = <0xffff>;
+		touchscreen-average-samples = <32>;
 		status = "okay";
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/touchscreen/silead_gsl1680.txt	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@ Optional properties:
 - touchscreen-inverted-y  : See touchscreen.txt
 - touchscreen-swapped-x-y : See touchscreen.txt
 - silead,max-fingers	  : maximum number of fingers the touchscreen can detect
+- vddio-supply		  : regulator phandle for controller VDDIO
+- avdd-supply		  : regulator phandle for controller AVDD
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,9 @@ Optional properties for Touchscreens:
  - touchscreen-fuzz-pressure	: pressure noise value of the absolute input
 				  device (arbitrary range dependent on the
 				  controller)
+ - touchscreen-average-samples : Number of data samples which are averaged
+				  for each read (valid values dependent on the
+				  controller)
  - touchscreen-inverted-x	: X axis is inverted (boolean)
  - touchscreen-inverted-y	: Y axis is inverted (boolean)
  - touchscreen-swapped-x-y	: X and Y axis are swapped (boolean)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/input/tps65218-pwrbutton.txt	2017-02-12 16:03:20.000000000 -0500
@@ -8,8 +8,9 @@ This driver provides a simple power butt
 Required properties:
 - compatible: should be "ti,tps65217-pwrbutton" or "ti,tps65218-pwrbutton"
 
-Required properties for TPS65218:
+Required properties:
 - interrupts: should be one of the following
+   - <2>: For controllers compatible with tps65217
    - <3 IRQ_TYPE_EDGE_BOTH>: For controllers compatible with tps65218
 
 Examples:
@@ -17,6 +18,7 @@ Examples:
 &tps {
 	tps65217-pwrbutton {
 		compatible = "ti,tps65217-pwrbutton";
+		interrupts = <2>;
 	};
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/interrupt-controller/snps,archs-idu-intc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,9 @@ Properties:
   Second cell specifies the irq distribution mode to cores
      0=Round Robin; 1=cpu0, 2=cpu1, 4=cpu2, 8=cpu3
 
+  The second cell in interrupts property is deprecated and may be ignored by
+  the kernel.
+
   intc accessed via the special ARC AUX register interface, hence "reg" property
   is not specified.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/leds/pca963x.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/leds/pca963x.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/leds/pca963x.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/leds/pca963x.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,9 @@ Optional properties:
 - nxp,totem-pole : use totem pole (push-pull) instead of open-drain (pca9632 defaults
   to open-drain, newer chips to totem pole)
 - nxp,hw-blink : use hardware blinking instead of software blinking
+- nxp,period-scale : In some configurations, the chip blinks faster than expected.
+		     This parameter provides a scaling ratio (fixed point, decimal divided
+		     by 1000) to compensate, e.g. 1300=1.3x and 750=0.75x.
 
 Each led is represented as a sub-node of the nxp,pca963x device.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mailbox/brcm,bcm2835-mbox.txt	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ Required properties:
 
 Example:
 
-mailbox: mailbox@7e00b800 {
+mailbox: mailbox@7e00b880 {
 	compatible = "brcm,bcm2835-mbox";
 	reg = <0x7e00b880 0x40>;
 	interrupts = <0 1>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,52 @@
+NVIDIA Tegra Hardware Synchronization Primitives (HSP)
+
+The HSP modules are used for the processors to share resources and communicate
+together. It provides a set of hardware synchronization primitives for
+interprocessor communication. So the interprocessor communication (IPC)
+protocols can use hardware synchronization primitives, when operating between
+two processors not in an SMP relationship.
+
+The features that HSP supported are shared mailboxes, shared semaphores,
+arbitrated semaphores and doorbells.
+
+Required properties:
+- name : Should be hsp
+- compatible
+    Array of strings.
+    one of:
+    - "nvidia,tegra186-hsp"
+- reg : Offset and length of the register set for the device.
+- interrupt-names
+    Array of strings.
+    Contains a list of names for the interrupts described by the interrupt
+    property. May contain the following entries, in any order:
+    - "doorbell"
+    Users of this binding MUST look up entries in the interrupt property
+    by name, using this interrupt-names property to do so.
+- interrupts
+    Array of interrupt specifiers.
+    Must contain one entry per entry in the interrupt-names property,
+    in a matching order.
+- #mbox-cells : Should be 2.
+
+The mbox specifier of the "mboxes" property in the client node should
+contain two data. The first one should be the HSP type and the second
+one should be the ID that the client is going to use. Those information
+can be found in the following file.
+
+- <dt-bindings/mailbox/tegra186-hsp.h>.
+
+Example:
+
+hsp_top0: hsp@3c00000 {
+	compatible = "nvidia,tegra186-hsp";
+	reg = <0x0 0x03c00000 0x0 0xa0000>;
+	interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+	interrupt-names = "doorbell";
+	#mbox-cells = <2>;
+};
+
+client {
+	...
+	mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB TEGRA_HSP_DB_MASTER_XXX>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/exynos5-gsc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/exynos5-gsc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/exynos5-gsc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/exynos5-gsc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,8 @@
 G-Scaler is used for scaling and color space conversion on EXYNOS5 SoCs.
 
 Required properties:
-- compatible: should be "samsung,exynos5-gsc"
+- compatible: should be "samsung,exynos5-gsc" (for Exynos 5250, 5420 and
+	      5422 SoCs) or "samsung,exynos5433-gsc" (Exynos 5433)
 - reg: should contain G-Scaler physical address location and length.
 - interrupts: should contain G-Scaler interrupt number
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/hix5hd2-ir.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/hix5hd2-ir.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/hix5hd2-ir.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/hix5hd2-ir.txt	2017-02-12 16:03:20.000000000 -0500
@@ -8,10 +8,11 @@ Required properties:
 	  the device. The interrupt specifier format depends on the interrupt
 	  controller parent.
 	- clocks: clock phandle and specifier pair.
-	- hisilicon,power-syscon: phandle of syscon used to control power.
 
 Optional properties:
 	- linux,rc-map-name : Remote control map name.
+	- hisilicon,power-syscon: DEPRECATED. Don't use this in new dts files.
+		Provide correct clocks instead.
 
 Example node:
 
@@ -19,7 +20,6 @@ Example node:
 		compatible = "hisilicon,hix5hd2-ir";
 		reg = <0xf8001000 0x1000>;
 		interrupts = <0 47 4>;
-		clocks = <&clock HIX5HD2_FIXED_24M>;
-		hisilicon,power-syscon = <&sysctrl>;
+		clocks = <&clock HIX5HD2_IR_CLOCK>;
 		linux,rc-map-name = "rc-tivo";
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/i2c/adv7604.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/i2c/adv7604.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/i2c/adv7604.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/i2c/adv7604.txt	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,7 @@ The digital output port node must contai
 Optional Properties:
 
   - reset-gpios: Reference to the GPIO connected to the device's reset pin.
+  - default-input: Select which input is selected after reset.
 
 Optional Endpoint Properties:
 
@@ -47,8 +48,6 @@ Optional Endpoint Properties:
   If none of hsync-active, vsync-active and pclk-sample is specified the
   endpoint will use embedded BT.656 synchronization.
 
-  - default-input: Select which input is selected after reset.
-
 Example:
 
 	hdmi_receiver@4c {
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/mediatek-mdp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/mediatek-mdp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/mediatek-mdp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/mediatek-mdp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,109 @@
+* Mediatek Media Data Path
+
+Media Data Path is used for scaling and color space conversion.
+
+Required properties (controller (parent) node):
+- compatible: "mediatek,mt8173-mdp"
+- mediatek,vpu: the node of video processor unit, see
+  Documentation/devicetree/bindings/media/mediatek-vpu.txt for details.
+
+Required properties (all function blocks, child node):
+- compatible: Should be one of
+        "mediatek,mt8173-mdp-rdma"  - read DMA
+        "mediatek,mt8173-mdp-rsz"   - resizer
+        "mediatek,mt8173-mdp-wdma"  - write DMA
+        "mediatek,mt8173-mdp-wrot"  - write DMA with rotation
+- reg: Physical base address and length of the function block register space
+- clocks: device clocks, see
+  Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
+- power-domains: a phandle to the power domain, see
+  Documentation/devicetree/bindings/power/power_domain.txt for details.
+
+Required properties (DMA function blocks, child node):
+- compatible: Should be one of
+        "mediatek,mt8173-mdp-rdma"
+        "mediatek,mt8173-mdp-wdma"
+        "mediatek,mt8173-mdp-wrot"
+- iommus: should point to the respective IOMMU block with master port as
+  argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+  for details.
+- mediatek,larb: must contain the local arbiters in the current Socs, see
+  Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+  for details.
+
+Example:
+mdp {
+	compatible = "mediatek,mt8173-mdp";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges;
+	mediatek,vpu = <&vpu>;
+
+	mdp_rdma0: rdma@14001000 {
+		compatible = "mediatek,mt8173-mdp-rdma";
+		reg = <0 0x14001000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_RDMA0>,
+			 <&mmsys CLK_MM_MUTEX_32K>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+		iommus = <&iommu M4U_PORT_MDP_RDMA0>;
+		mediatek,larb = <&larb0>;
+	};
+
+	mdp_rdma1: rdma@14002000 {
+		compatible = "mediatek,mt8173-mdp-rdma";
+		reg = <0 0x14002000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_RDMA1>,
+			 <&mmsys CLK_MM_MUTEX_32K>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+		iommus = <&iommu M4U_PORT_MDP_RDMA1>;
+		mediatek,larb = <&larb4>;
+	};
+
+	mdp_rsz0: rsz@14003000 {
+		compatible = "mediatek,mt8173-mdp-rsz";
+		reg = <0 0x14003000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_RSZ0>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	};
+
+	mdp_rsz1: rsz@14004000 {
+		compatible = "mediatek,mt8173-mdp-rsz";
+		reg = <0 0x14004000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_RSZ1>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	};
+
+	mdp_rsz2: rsz@14005000 {
+		compatible = "mediatek,mt8173-mdp-rsz";
+		reg = <0 0x14005000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_RSZ2>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+	};
+
+	mdp_wdma0: wdma@14006000 {
+		compatible = "mediatek,mt8173-mdp-wdma";
+		reg = <0 0x14006000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_WDMA>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+		iommus = <&iommu M4U_PORT_MDP_WDMA>;
+		mediatek,larb = <&larb0>;
+	};
+
+	mdp_wrot0: wrot@14007000 {
+		compatible = "mediatek,mt8173-mdp-wrot";
+		reg = <0 0x14007000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_WROT0>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+		iommus = <&iommu M4U_PORT_MDP_WROT0>;
+		mediatek,larb = <&larb0>;
+	};
+
+	mdp_wrot1: wrot@14008000 {
+		compatible = "mediatek,mt8173-mdp-wrot";
+		reg = <0 0x14008000 0 0x1000>;
+		clocks = <&mmsys CLK_MM_MDP_WROT1>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>;
+		iommus = <&iommu M4U_PORT_MDP_WROT1>;
+		mediatek,larb = <&larb4>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/mediatek-vcodec.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/mediatek-vcodec.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/mediatek-vcodec.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/mediatek-vcodec.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,74 @@
 Mediatek Video Codec
 
 Mediatek Video Codec is the video codec hw present in Mediatek SoCs which
-supports high resolution encoding functionalities.
+supports high resolution encoding and decoding functionalities.
 
 Required properties:
 - compatible : "mediatek,mt8173-vcodec-enc" for encoder
+  "mediatek,mt8173-vcodec-dec" for decoder.
 - reg : Physical base address of the video codec registers and length of
   memory mapped region.
 - interrupts : interrupt number to the cpu.
 - mediatek,larb : must contain the local arbiters in the current Socs.
 - clocks : list of clock specifiers, corresponding to entries in
   the clock-names property.
-- clock-names: encoder must contain "venc_sel_src", "venc_sel",
-- "venc_lt_sel_src", "venc_lt_sel".
+- clock-names: encoder must contain "venc_sel_src", "venc_sel",,
+  "venc_lt_sel_src", "venc_lt_sel", decoder must contain "vcodecpll",
+  "univpll_d2", "clk_cci400_sel", "vdec_sel", "vdecpll", "vencpll",
+  "venc_lt_sel", "vdec_bus_clk_src".
 - iommus : should point to the respective IOMMU block with master port as
   argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
   for details.
 - mediatek,vpu : the node of video processor unit
 
+
 Example:
-vcodec_enc: vcodec@0x18002000 {
+
+vcodec_dec: vcodec@16000000 {
+    compatible = "mediatek,mt8173-vcodec-dec";
+    reg = <0 0x16000000 0 0x100>,   /*VDEC_SYS*/
+          <0 0x16020000 0 0x1000>,  /*VDEC_MISC*/
+          <0 0x16021000 0 0x800>,   /*VDEC_LD*/
+          <0 0x16021800 0 0x800>,   /*VDEC_TOP*/
+          <0 0x16022000 0 0x1000>,  /*VDEC_CM*/
+          <0 0x16023000 0 0x1000>,  /*VDEC_AD*/
+          <0 0x16024000 0 0x1000>,  /*VDEC_AV*/
+          <0 0x16025000 0 0x1000>,  /*VDEC_PP*/
+          <0 0x16026800 0 0x800>,   /*VP8_VD*/
+          <0 0x16027000 0 0x800>,   /*VP6_VD*/
+          <0 0x16027800 0 0x800>,   /*VP8_VL*/
+          <0 0x16028400 0 0x400>;   /*VP9_VD*/
+    interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_LOW>;
+    mediatek,larb = <&larb1>;
+    iommus = <&iommu M4U_PORT_HW_VDEC_MC_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PP_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_AVC_MV_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PRED_RD_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_PRED_WR_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_UFO_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
+             <&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
+    mediatek,vpu = <&vpu>;
+    power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
+    clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
+             <&topckgen CLK_TOP_UNIVPLL_D2>,
+             <&topckgen CLK_TOP_CCI400_SEL>,
+             <&topckgen CLK_TOP_VDEC_SEL>,
+             <&topckgen CLK_TOP_VCODECPLL>,
+             <&apmixedsys CLK_APMIXED_VENCPLL>,
+             <&topckgen CLK_TOP_VENC_LT_SEL>,
+             <&topckgen CLK_TOP_VCODECPLL_370P5>;
+    clock-names = "vcodecpll",
+                  "univpll_d2",
+                  "clk_cci400_sel",
+                  "vdec_sel",
+                  "vdecpll",
+                  "vencpll",
+                  "venc_lt_sel",
+                  "vdec_bus_clk_src";
+  };
+
+  vcodec_enc: vcodec@0x18002000 {
     compatible = "mediatek,mt8173-vcodec-enc";
     reg = <0 0x18002000 0 0x1000>,    /*VENC_SYS*/
           <0 0x19002000 0 0x1000>;    /*VENC_LT_SYS*/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/renesas,fcp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/renesas,fcp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/renesas,fcp.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/renesas,fcp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -11,15 +11,9 @@ are paired with. These DT bindings curre
 
  - compatible: Must be one or more of the following
 
-   - "renesas,r8a7795-fcpv" for R8A7795 (R-Car H3) compatible 'FCP for VSP'
-   - "renesas,r8a7795-fcpf" for R8A7795 (R-Car H3) compatible 'FCP for FDP'
    - "renesas,fcpv" for generic compatible 'FCP for VSP'
    - "renesas,fcpf" for generic compatible 'FCP for FDP'
 
-   When compatible with the generic version, nodes must list the
-   SoC-specific version corresponding to the platform first, followed by the
-   family-specific and/or generic versions.
-
  - reg: the register base and size for the device registers
  - clocks: Reference to the functional clock
 
@@ -32,7 +26,7 @@ Device node example
 -------------------
 
 	fcpvd1: fcp@fea2f000 {
-		compatible = "renesas,r8a7795-fcpv", "renesas,fcpv";
+		compatible = "renesas,fcpv";
 		reg = <0 0xfea2f000 0 0x200>;
 		clocks = <&cpg CPG_MOD 602>;
 		power-domains = <&sysc R8A7795_PD_A3VP>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/renesas,fdp1.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/renesas,fdp1.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/renesas,fdp1.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/renesas,fdp1.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,37 @@
+Renesas R-Car Fine Display Processor (FDP1)
+-------------------------------------------
+
+The FDP1 is a de-interlacing module which converts interlaced video to
+progressive video. It is capable of performing pixel format conversion between
+YCbCr/YUV formats and RGB formats. Only YCbCr/YUV formats are supported as
+an input to the module.
+
+Required properties:
+
+ - compatible: must be "renesas,fdp1"
+ - reg: the register base and size for the device registers
+ - interrupts : interrupt specifier for the FDP1 instance
+ - clocks: reference to the functional clock
+
+Optional properties:
+
+ - power-domains: reference to the power domain that the FDP1 belongs to, if
+                  any.
+ - renesas,fcp: a phandle referencing the FCP that handles memory accesses
+                for the FDP1. Not needed on Gen2, mandatory on Gen3.
+
+Please refer to the binding documentation for the clock and/or power domain
+providers for more details.
+
+
+Device node example
+-------------------
+
+	fdp1@fe940000 {
+		compatible = "renesas,fdp1";
+		reg = <0 0xfe940000 0 0x2400>;
+		interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cpg CPG_MOD 119>;
+		power-domains = <&sysc R8A7795_PD_A3VP>;
+		renesas,fcp = <&fcpf0>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/s5p-mfc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/s5p-mfc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/media/s5p-mfc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/media/s5p-mfc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@ Required properties:
 	(b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs
 	(c) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC
 	(d) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC
+	(e) "samsung,exynos5433-mfc" for MFC v8 present in Exynos5433 SoC
 
   - reg : Physical base address of the IP registers and length of memory
 	  mapped region.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/memory-controllers/ti-da8xx-ddrctl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+* Device tree bindings for Texas Instruments da8xx DDR2/mDDR memory controller
+
+The DDR2/mDDR memory controller present on Texas Instruments da8xx SoCs features
+a set of registers which allow to tweak the controller's behavior.
+
+Documentation:
+OMAP-L138 (DA850) - http://www.ti.com/lit/ug/spruh82c/spruh82c.pdf
+
+Required properties:
+
+- compatible:		"ti,da850-ddr-controller" - for da850 SoC based boards
+- reg:			a tuple containing the base address of the memory
+			controller and the size of the memory area to map
+
+Example for da850 shown below.
+
+ddrctl {
+	compatible = "ti,da850-ddr-controller";
+	reg = <0xb0000000 0xe8>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/altera-a10sr.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/altera-a10sr.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/altera-a10sr.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/altera-a10sr.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,46 @@
+* Altera Arria10 Development Kit System Resource Chip
+
+Required parent device properties:
+- compatible		: "altr,a10sr"
+- spi-max-frequency	: Maximum SPI frequency.
+- reg			: The SPI Chip Select address for the Arria10
+			  System Resource chip
+- interrupt-parent	: The parent interrupt controller.
+- interrupts		: The interrupt line the device is connected to.
+- interrupt-controller	: Marks the device node as an interrupt controller.
+- #interrupt-cells	: The number of cells to describe an IRQ, should be 2.
+			    The first cell is the IRQ number.
+			    The second cell is the flags, encoded as trigger
+			    masks from ../interrupt-controller/interrupts.txt.
+
+The A10SR consists of these sub-devices:
+
+Device                   Description
+------                   ----------
+a10sr_gpio               GPIO Controller
+
+Arria10 GPIO
+Required Properties:
+- compatible        : Should be "altr,a10sr-gpio"
+- gpio-controller   : Marks the device node as a GPIO Controller.
+- #gpio-cells       : Should be two.  The first cell is the pin number and
+                      the second cell is used to specify flags.
+                      See ../gpio/gpio.txt for more information.
+
+Example:
+
+        resource-manager@0 {
+		compatible = "altr,a10sr";
+		reg = <0>;
+		spi-max-frequency = <100000>;
+		interrupt-parent = <&portb>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		a10sr_gpio: gpio-controller {
+			compatible = "altr,a10sr-gpio";
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/lp873x.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/lp873x.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/lp873x.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/lp873x.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,9 @@ Required properties:
   - #gpio-cells:	Should be two.  The first cell is the pin number and
 			the second cell is used to specify flags.
 			See ../gpio/gpio.txt for more information.
+  - xxx-in-supply:	Phandle to parent supply node of each regulator
+			populated under regulators node. xxx can be
+			buck0, buck1, ldo0 or ldo1.
   - regulators:	List of child nodes that specify the regulator
 			initialization data.
 Example:
@@ -17,6 +20,11 @@ pmic: lp8733@60 {
 	gpio-controller;
 	#gpio-cells = <2>;
 
+	buck0-in-supply = <&vsys_3v3>;
+	buck1-in-supply = <&vsys_3v3>;
+	ldo0-in-supply = <&vsys_3v3>;
+	ldo1-in-supply = <&vsys_3v3>;
+
 	regulators {
 		lp8733_buck0: buck0 {
 			regulator-name = "lp8733-buck0";
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/max77620.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/max77620.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/max77620.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/max77620.txt	2017-02-12 16:03:20.000000000 -0500
@@ -106,6 +106,18 @@ Here supported time periods by device in
 MAX77620 supports 40, 80, 160, 320, 640, 1280, 2560 and 5120 microseconds.
 MAX20024 supports 20, 40, 80, 160, 320, 640, 1280 and 2540 microseconds.
 
+-maxim,power-ok-control: configure map power ok bit
+			1: Enables POK(Power OK) to control nRST_IO and GPIO1
+			POK function.
+			0: Disables POK control.
+			if property missing, do not configure MPOK bit.
+			If POK mapping is enabled for GPIO1/nRST_IO then,
+			GPIO1/nRST_IO pins are HIGH only if all rails
+			that have POK control enabled are HIGH.
+			If any of the rails goes down(which are enabled for POK
+			control) then, GPIO1/nRST_IO goes LOW.
+			this property is valid for max20024 only.
+
 For DT binding details of different sub modules like GPIO, pincontrol,
 regulator, power, please refer respective device-tree binding document
 under their respective sub-system directories.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@ voltages and other various functionality
 	Value type: <string>
 	Definition: must be one of:
 		    "qcom,pm8058"
+		    "qcom,pm8821"
 		    "qcom,pm8921"
 
 - #address-cells:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/rn5t618.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/rn5t618.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/rn5t618.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/rn5t618.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,21 +1,25 @@
 * Ricoh RN5T567/RN5T618 PMIC
 
-Ricoh RN5T567/RN5T618 is a power management IC family which integrates
-3 to 4 step-down DCDC converters, 7 low-dropout regulators, GPIOs and
-a watchdog timer. The RN5T618 provides additionally a Li-ion battery
-charger, fuel gauge and an ADC. It can be controlled through an I2C
-interface.
+Ricoh RN5T567/RN5T618/RC5T619 is a power management IC family which
+integrates 3 to 5 step-down DCDC converters, 7 to 10 low-dropout regulators,
+GPIOs, and a watchdog timer. It can be controlled through an I2C interface.
+The RN5T618/RC5T619 provides additionally a Li-ion battery charger,
+fuel gauge, and an ADC.
+The RC5T619 additionnally includes USB charger detection and an RTC.
 
 Required properties:
  - compatible: must be one of
 		"ricoh,rn5t567"
 		"ricoh,rn5t618"
+		"ricoh,rc5t619"
  - reg: the I2C slave address of the device
 
 Sub-nodes:
  - regulators: the node is required if the regulator functionality is
    needed. The valid regulator names are: DCDC1, DCDC2, DCDC3, DCDC4
-   (RN5T567), LDO1, LDO2, LDO3, LDO4, LDO5, LDORTC1 and LDORTC2.
+   (RN5T567/RC5T619), LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7, LDO8,
+   LDO9, LDO10, LDORTC1 and LDORTC2.
+   LDO7-10 are specific to RC5T619.
    The common bindings for each individual regulator can be found in:
    Documentation/devicetree/bindings/regulator/regulator.txt
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/tps65086.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/tps65086.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mfd/tps65086.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mfd/tps65086.txt	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@ Required properties:
                             defined below.
 
 Optional regulator properties:
- - ti,regulator-step-size-25mv	: This is applicable for buck[1,2,6], set this
+ - ti,regulator-step-size-25mv	: This is applicable for buck[1-6], set this
 				    if the regulator is factory set with a 25mv
 				    step voltage mapping.
  - ti,regulator-decay		: This is applicable for buck[1-6], set this if
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/amlogic,meson-gx.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,32 @@
+Amlogic SD / eMMC controller for S905/GXBB family SoCs
+
+The MMC 5.1 compliant host controller on Amlogic provides the
+interface for SD, eMMC and SDIO devices.
+
+This file documents the properties in addition to those available in
+the MMC core bindings, documented by mmc.txt.
+
+Required properties:
+- compatible : contains one of:
+  - "amlogic,meson-gx-mmc"
+  - "amlogic,meson-gxbb-mmc"
+  - "amlogic,meson-gxl-mmc"
+  - "amlogic,meson-gxm-mmc"
+- clocks     : A list of phandle + clock-specifier pairs for the clocks listed in clock-names.
+- clock-names: Should contain the following:
+	"core" - Main peripheral bus clock
+	"clkin0" - Parent clock of internal mux
+	"clkin1" - Other parent clock of internal mux
+  The driver has an interal mux clock which switches between clkin0 and clkin1 depending on the
+  clock rate requested by the MMC core.
+
+Example:
+
+	sd_emmc_a: mmc@70000 {
+		compatible = "amlogic,meson-gxbb-mmc";
+		reg = <0x0 0x70000 0x0 0x2000>;
+		interrupts = < GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&clkc CLKID_SD_EMMC_A>, <&xtal>, <&clkc CLKID_FCLK_DIV2>;
+		clock-names = "core", "clkin0", "clkin1";
+		pinctrl-0 = <&emmc_pins>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,15 @@ Required properties:
 - compatible : Should be one of the following
 	       "brcm,bcm2835-sdhci"
 	       "brcm,sdhci-iproc-cygnus"
+	       "brcm,sdhci-iproc"
+
+Use brcm2835-sdhci for Rasperry PI.
+
+Use sdhci-iproc-cygnus for Broadcom SDHCI Controllers
+restricted to 32bit host accesses to SDHCI registers.
+
+Use sdhci-iproc for Broadcom SDHCI Controllers that allow standard
+8, 16, 32-bit host access to SDHCI register.
 
 - clocks : The clock feeding the SDHCI controller.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt	2017-02-12 16:03:20.000000000 -0500
@@ -8,11 +8,14 @@ Required properties:
 
 - compatible: should be "renesas,mmcif-<soctype>", "renesas,sh-mmcif" as a
   fallback. Examples with <soctype> are:
+	- "renesas,mmcif-r8a73a4" for the MMCIF found in r8a73a4 SoCs
 	- "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs
+	- "renesas,mmcif-r8a7778" for the MMCIF found in r8a7778 SoCs
 	- "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs
 	- "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs
 	- "renesas,mmcif-r8a7793" for the MMCIF found in r8a7793 SoCs
 	- "renesas,mmcif-r8a7794" for the MMCIF found in r8a7794 SoCs
+	- "renesas,mmcif-sh73a0" for the MMCIF found in sh73a0 SoCs
 
 - clocks: reference to the functional clock
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@ Required Properties:
 	- "rockchip,rk2928-dw-mshc": for Rockchip RK2928 and following,
 							before RK3288
 	- "rockchip,rk3288-dw-mshc": for Rockchip RK3288
+	- "rockchip,rk1108-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK1108
 	- "rockchip,rk3036-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3036
 	- "rockchip,rk3368-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3368
 	- "rockchip,rk3399-dw-mshc", "rockchip,rk3288-dw-mshc": for Rockchip RK3399
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/sdhci-cadence.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,32 @@
+* Cadence SD/SDIO/eMMC Host Controller
+
+Required properties:
+- compatible: should be one of the following:
+    "cdns,sd4hc"               - default of the IP
+    "socionext,uniphier-sd4hc" - for Socionext UniPhier SoCs
+- reg: offset and length of the register set for the device.
+- interrupts: a single interrupt specifier.
+- clocks: phandle to the input clock.
+
+Optional properties:
+For eMMC configuration, supported speed modes are not indicated by the SDHCI
+Capabilities Register.  Instead, the following properties should be specified
+if supported.  See mmc.txt for details.
+- mmc-ddr-1_8v
+- mmc-ddr-1_2v
+- mmc-hs200-1_8v
+- mmc-hs200-1_2v
+- mmc-hs400-1_8v
+- mmc-hs400-1_2v
+
+Example:
+	emmc: sdhci@5a000000 {
+		compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
+		reg = <0x5a000000 0x400>;
+		interrupts = <0 78 4>;
+		clocks = <&clk 4>;
+		bus-width = <8>;
+		mmc-ddr-1_8v;
+		mmc-hs200-1_8v;
+		mmc-hs400-1_8v;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/sdhci-msm.txt	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@ Required properties:
 	"iface" - Main peripheral bus clock (PCLK/HCLK - AHB Bus clock) (required)
 	"core"	- SDC MMC clock (MCLK) (required)
 	"bus"	- SDCC bus voter clock (optional)
+	"xo"	- TCXO clock (optional)
 
 Example:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/sdhci.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/sdhci.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/sdhci.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/sdhci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,13 @@
+The properties specific for SD host controllers. For properties shared by MMC
+host controllers refer to the mmc[1] bindings.
+
+  [1] Documentation/devicetree/bindings/mmc/mmc.txt
+
+Optional properties:
+- sdhci-caps-mask: The sdhci capabilities register is incorrect. This 64bit
+  property corresponds to the bits in the sdhci capabilty register. If the bit
+  is on in the mask then the bit is incorrect in the register and should be
+  turned off, before applying sdhci-caps.
+- sdhci-caps: The sdhci capabilities register is incorrect. This 64bit
+  property corresponds to the bits in the sdhci capability register. If the
+  bit is on in the property then the bit should be turned on.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -59,8 +59,9 @@ Optional properties:
   is specified and the ciu clock is specified then we'll try to set the ciu
   clock to this at probe time.
 
-* clock-freq-min-max: Minimum and Maximum clock frequency for card output
+* clock-freq-min-max (DEPRECATED): Minimum and Maximum clock frequency for card output
   clock(cclk_out). If it's not specified, max is 200MHZ and min is 400KHz by default.
+	  (Use the "max-frequency" instead of "clock-freq-min-max".)
 
 * num-slots: specifies the number of slots supported by the controller.
   The number of physical slots actually used could be equal or less than the
@@ -74,11 +75,6 @@ Optional properties:
 * card-detect-delay: Delay in milli-seconds before detecting card after card
   insert event. The default value is 0.
 
-* supports-highspeed (DEPRECATED): Enables support for high speed cards (up to 50MHz)
-			   (use "cap-mmc-highspeed" or "cap-sd-highspeed" instead)
-
-* broken-cd: as documented in mmc core bindings.
-
 * vmmc-supply: The phandle to the regulator to use for vmmc.  If this is
   specified we'll defer probe until we can find this regulator.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mmc/tmio_mmc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -11,8 +11,8 @@ optional bindings can be used.
 
 Required properties:
 - compatible:	"renesas,sdhi-shmobile" - a generic sh-mobile SDHI unit
-		"renesas,sdhi-sh7372" - SDHI IP on SH7372 SoC
 		"renesas,sdhi-sh73a0" - SDHI IP on SH73A0 SoC
+		"renesas,sdhi-r7s72100" - SDHI IP on R7S72100 SoC
 		"renesas,sdhi-r8a73a4" - SDHI IP on R8A73A4 SoC
 		"renesas,sdhi-r8a7740" - SDHI IP on R8A7740 SoC
 		"renesas,sdhi-r8a7778" - SDHI IP on R8A7778 SoC
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mtd/oxnas-nand.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mtd/oxnas-nand.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mtd/oxnas-nand.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mtd/oxnas-nand.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+* Oxford Semiconductor OXNAS NAND Controller
+
+Please refer to nand.txt for generic information regarding MTD NAND bindings.
+
+Required properties:
+ - compatible: "oxsemi,ox820-nand"
+ - reg: Base address and length for NAND mapped memory.
+
+Optional Properties:
+ - clocks: phandle to the NAND gate clock if needed.
+ - resets: phandle to the NAND reset control if needed.
+
+Example:
+
+nandc: nand-controller@41000000 {
+	compatible = "oxsemi,ox820-nand";
+	reg = <0x41000000 0x100000>;
+	clocks = <&stdclk CLK_820_NAND>;
+	resets = <&reset RESET_NAND>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	nand@0 {
+		reg = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		nand-ecc-mode = "soft";
+		nand-ecc-algo = "hamming";
+
+		partition@0 {
+			label = "boot";
+			reg = <0x00000000 0x00e00000>;
+			read-only;
+		};
+
+		partition@e00000 {
+			label = "ubi";
+			reg = <0x00e00000 0x07200000>;
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mtd/samsung-s3c2410.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,56 @@
+* Samsung S3C2410 and compatible NAND flash controller
+
+Required properties:
+- compatible : The possible values are:
+	"samsung,s3c2410-nand"
+	"samsung,s3c2412-nand"
+	"samsung,s3c2440-nand"
+- reg : register's location and length.
+- #address-cells, #size-cells : see nand.txt
+- clocks : phandle to the nand controller clock
+- clock-names : must contain "nand"
+
+Optional child nodes:
+Child nodes representing the available nand chips.
+
+Optional child properties:
+- nand-ecc-mode : see nand.txt
+- nand-on-flash-bbt : see nand.txt
+
+Each child device node may optionally contain a 'partitions' sub-node,
+which further contains sub-nodes describing the flash partition mapping.
+See partition.txt for more detail.
+
+Example:
+
+nand-controller@4e000000 {
+	compatible = "samsung,s3c2440-nand";
+	reg = <0x4e000000 0x40>;
+
+	#address-cells = <1>;
+        #size-cells = <0>;
+
+	clocks = <&clocks HCLK_NAND>;
+	clock-names = "nand";
+
+	nand {
+		nand-ecc-mode = "soft";
+		nand-on-flash-bbt;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "u-boot";
+				reg = <0 0x040000>;
+			};
+
+			partition@40000 {
+				label = "kernel";
+				reg = <0x040000 0x500000>;
+			};
+		};
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/mtd/tango-nand.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mtd/tango-nand.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/mtd/tango-nand.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/mtd/tango-nand.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+Sigma Designs Tango4 NAND Flash Controller (NFC)
+
+Required properties:
+
+- compatible: "sigma,smp8758-nand"
+- reg: address/size of nfc_reg, nfc_mem, and pbus_reg
+- dmas: reference to the DMA channel used by the controller
+- dma-names: "rxtx"
+- clocks: reference to the system clock
+- #address-cells: <1>
+- #size-cells: <0>
+
+Children nodes represent the available NAND chips.
+See Documentation/devicetree/bindings/mtd/nand.txt for generic bindings.
+
+Example:
+
+	nandc: nand-controller@2c000 {
+		compatible = "sigma,smp8758-nand";
+		reg = <0x2c000 0x30>, <0x2d000 0x800>, <0x20000 0x1000>;
+		dmas = <&dma0 3>;
+		dma-names = "rxtx";
+		clocks = <&clkgen SYS_CLK>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		nand@0 {
+			reg = <0>; /* CS0 */
+			nand-ecc-strength = <14>;
+			nand-ecc-step-size = <1024>;
+		};
+
+		nand@1 {
+			reg = <1>; /* CS1 */
+			nand-ecc-strength = <14>;
+			nand-ecc-step-size = <1024>;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/brcm,amac.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/brcm,amac.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/brcm,amac.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/brcm,amac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -2,11 +2,17 @@ Broadcom AMAC Ethernet Controller Device
 -------------------------------------------------------------
 
 Required properties:
- - compatible:	"brcm,amac" or "brcm,nsp-amac"
- - reg:		Address and length of the GMAC registers,
-		Address and length of the GMAC IDM registers
- - reg-names:	Names of the registers.  Must have both "amac_base" and
-		"idm_base"
+ - compatible:	"brcm,amac"
+		"brcm,nsp-amac"
+		"brcm,ns2-amac"
+ - reg:		Address and length of the register set for the device. It
+		contains the information of registers in the same order as
+		described by reg-names
+ - reg-names:	Names of the registers.
+		"amac_base":	Address and length of the GMAC registers
+		"idm_base":	Address and length of the GMAC IDM registers
+		"nicpm_base":	Address and length of the NIC Port Manager
+				registers (required for Northstar2)
  - interrupts:	Interrupt number
 
 Optional properties:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/can/rcar_canfd.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/can/rcar_canfd.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/can/rcar_canfd.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/can/rcar_canfd.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,13 +5,14 @@ Required properties:
 - compatible: Must contain one or more of the following:
   - "renesas,rcar-gen3-canfd" for R-Car Gen3 compatible controller.
   - "renesas,r8a7795-canfd" for R8A7795 (R-Car H3) compatible controller.
+  - "renesas,r8a7796-canfd" for R8A7796 (R-Car M3) compatible controller.
 
   When compatible with the generic version, nodes must list the
   SoC-specific version corresponding to the platform first, followed by the
   family-specific and/or generic versions.
 
 - reg: physical base address and size of the R-Car CAN FD register map.
-- interrupts: interrupt specifier for the Global & Channel interrupts
+- interrupts: interrupt specifiers for the Channel & Global interrupts
 - clocks: phandles and clock specifiers for 3 clock inputs.
 - clock-names: 3 clock input name strings: "fck", "canfd", "can_clk".
 - pinctrl-0: pin control group to be used for this controller.
@@ -23,11 +24,12 @@ The name of the child nodes are "channel
 child node supports the "status" property only, which is used to
 enable/disable the respective channel.
 
-Required properties for "renesas,r8a7795-canfd" compatible:
-In R8A7795 SoC, canfd clock is a div6 clock and can be used by both CAN
-and CAN FD controller at the same time. It needs to be scaled to maximum
-frequency if any of these controllers use it. This is done using the
-below properties.
+Required properties for "renesas,r8a7795-canfd" and "renesas,r8a7796-canfd"
+compatible:
+In R8A7795 and R8A7796 SoCs, canfd clock is a div6 clock and can be used by both
+CAN and CAN FD controller at the same time. It needs to be scaled to maximum
+frequency if any of these controllers use it. This is done using the below
+properties:
 
 - assigned-clocks: phandle of canfd clock.
 - assigned-clock-rates: maximum frequency of this clock.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/can/rcar_can.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/can/rcar_can.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/can/rcar_can.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/can/rcar_can.txt	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@ Required properties:
 	      "renesas,can-r8a7793" if CAN controller is a part of R8A7793 SoC.
 	      "renesas,can-r8a7794" if CAN controller is a part of R8A7794 SoC.
 	      "renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC.
+	      "renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC.
 	      "renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device.
 	      "renesas,rcar-gen2-can" for a generic R-Car Gen2 compatible device.
 	      "renesas,rcar-gen3-can" for a generic R-Car Gen3 compatible device.
@@ -24,11 +25,12 @@ Required properties:
 - pinctrl-0: pin control group to be used for this controller.
 - pinctrl-names: must be "default".
 
-Required properties for "renesas,can-r8a7795" compatible:
-In R8A7795 SoC, "clkp2" can be CANFD clock. This is a div6 clock and can be
-used by both CAN and CAN FD controller at the same time. It needs to be scaled
-to maximum frequency if any of these controllers use it. This is done using
-the below properties.
+Required properties for "renesas,can-r8a7795" and "renesas,can-r8a7796"
+compatible:
+In R8A7795 and R8A7796 SoCs, "clkp2" can be CANFD clock. This is a div6 clock
+and can be used by both CAN and CAN FD controller at the same time. It needs to
+be scaled to maximum frequency if any of these controllers use it. This is done
+using the below properties:
 
 - assigned-clocks: phandle of clkp2(CANFD) clock.
 - assigned-clock-rates: maximum frequency of this clock.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/cpsw.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/cpsw.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/cpsw.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/cpsw.txt	2017-02-12 16:03:20.000000000 -0500
@@ -20,8 +20,6 @@ Required properties:
 - slaves		: Specifies number for slaves
 - active_slave		: Specifies the slave to use for time stamping,
 			  ethtool and SIOCGMIIPHY
-- cpts_clock_mult	: Numerator to convert input clock ticks into nanoseconds
-- cpts_clock_shift	: Denominator to convert input clock ticks into nanoseconds
 
 Optional properties:
 - ti,hwmods		: Must be "cpgmac0"
@@ -35,7 +33,11 @@ Optional properties:
 			  For example in dra72x-evm, pcf gpio has to be
 			  driven low so that cpsw slave 0 and phy data
 			  lines are connected via mux.
-
+- cpts_clock_mult	: Numerator to convert input clock ticks into nanoseconds
+- cpts_clock_shift	: Denominator to convert input clock ticks into nanoseconds
+			  Mult and shift will be calculated basing on CPTS
+			  rftclk frequency if both cpts_clock_shift and
+			  cpts_clock_mult properties are not provided.
 
 Slave Properties:
 Required properties:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/dsa/marvell.txt	2017-02-12 16:03:20.000000000 -0500
@@ -14,22 +14,42 @@ The properties described here are those
 Additional required and optional properties can be found in dsa.txt.
 
 Required properties:
-- compatible           : Should be one of "marvell,mv88e6085",
+- compatible	       : Should be one of "marvell,mv88e6085" or
+			 "marvell,mv88e6190"
 - reg                  : Address on the MII bus for the switch.
 
 Optional properties:
 
 - reset-gpios		: Should be a gpio specifier for a reset line
-
+- interrupt-parent	: Parent interrupt controller
+- interrupts		: Interrupt from the switch
+- interrupt-controller	: Indicates the switch is itself an interrupt
+			  controller. This is used for the PHY interrupts.
+#interrupt-cells = <2>	: Controller uses two cells, number and flag
+- mdio			: container of PHY and devices on the switches MDIO
+			  bus
 Example:
 
        mdio {
                #address-cells = <1>;
                #size-cells = <0>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
 
                switch0: switch@0 {
                        compatible = "marvell,mv88e6085";
                        reg = <0>;
 		       reset-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
                };
+               mdio {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       switch1phy0: switch1phy0@0 {
+                               reg = <0>;
+                               interrupt-parent = <&switch0>;
+                               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
        };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/hisilicon-hix5hd2-gmac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,15 @@
 Hisilicon hix5hd2 gmac controller
 
 Required properties:
-- compatible: should be "hisilicon,hix5hd2-gmac".
+- compatible: should contain one of the following SoC strings:
+	* "hisilicon,hix5hd2-gmac"
+	* "hisilicon,hi3798cv200-gmac"
+	* "hisilicon,hi3516a-gmac"
+	and one of the following version string:
+	* "hisilicon,hisi-gmac-v1"
+	* "hisilicon,hisi-gmac-v2"
+  The version v1 includes SoCs hix5hd2.
+  The version v2 includes SoCs hi3798cv200, hi3516a.
 - reg: specifies base physical address(s) and size of the device registers.
   The first region is the MAC register base and size.
   The second region is external interface control register.
@@ -12,6 +20,16 @@ Required properties:
 - phy-handle: see ethernet.txt [1].
 - mac-address: see ethernet.txt [1].
 - clocks: clock phandle and specifier pair.
+- clock-names: contain the clock name "mac_core"(required) and "mac_ifc"(optional).
+- resets: should contain the phandle to the MAC core reset signal(optional),
+	the MAC interface reset signal(optional)
+	and the PHY reset signal(optional).
+- reset-names: contain the reset signal name "mac_core"(optional),
+	"mac_ifc"(optional) and "phy"(optional).
+- hisilicon,phy-reset-delays-us: triplet of delays if PHY reset signal given.
+	The 1st cell is reset pre-delay in micro seconds.
+	The 2nd cell is reset pulse in micro seconds.
+	The 3rd cell is reset post-delay in micro seconds.
 
 - PHY subnode: inherits from phy binding [2]
 
@@ -20,15 +38,19 @@ Required properties:
 
 Example:
 	gmac0: ethernet@f9840000 {
-		compatible = "hisilicon,hix5hd2-gmac";
+		compatible = "hisilicon,hi3798cv200-gmac", "hisilicon,hisi-gmac-v2";
 		reg = <0xf9840000 0x1000>,<0xf984300c 0x4>;
 		interrupts = <0 71 4>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		phy-mode = "mii";
+		phy-mode = "rgmii";
 		phy-handle = <&phy2>;
 		mac-address = [00 00 00 00 00 00];
-		clocks = <&clock HIX5HD2_MAC0_CLK>;
+		clocks = <&crg HISTB_ETH0_MAC_CLK>, <&crg HISTB_ETH0_MACIF_CLK>;
+		clock-names = "mac_core", "mac_ifc";
+		resets = <&crg 0xcc 8>, <&crg 0xcc 10>, <&crg 0xcc 12>;
+		reset-names = "mac_core", "mac_ifc", "phy";
+		hisilicon,phy-reset-delays-us = <10000 10000 30000>;
 
 		phy2: ethernet-phy@2 {
 			reg = <2>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt	2017-02-12 16:03:20.000000000 -0500
@@ -45,6 +45,12 @@ Required properties:
   depends on the hardware user manual.
 - port-mode-offset: is offset of port mode field for each port in dsaf. Its
   value depends on the hardware user manual.
+- mc-mac-mask: mask of multicast address, determines bit in multicast address
+  to set:
+  1 stands for this bit will be precisely matched, TCAM will check this bit of
+    MAC address.
+  0 stands for this bit will be fuzzy matched, TCAM won't care about this bit
+    of MAC address.
 
 [1] Documentation/devicetree/bindings/net/phy.txt
 
@@ -74,10 +80,12 @@ dsaf0: dsa@c7000000 {
 		reg = 0;
 		phy-handle = <&phy0>;
 		serdes-syscon = <&serdes>;
+		mc-mac-mask = [ff f0 00 00 00 00];
 	};
 
 	port@1 {
                 reg = 1;
                 serdes-syscon = <&serdes>;
+		mc-mac-mask = [ff f0 00 00 00 00];
         };
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/marvell-armada-370-neta.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,10 @@
-* Marvell Armada 370 / Armada XP Ethernet Controller (NETA)
+* Marvell Armada 370 / Armada XP / Armada 3700 Ethernet Controller (NETA)
 
 Required properties:
-- compatible: "marvell,armada-370-neta" or "marvell,armada-xp-neta".
+- compatible: could be one of the followings
+	"marvell,armada-370-neta"
+	"marvell,armada-xp-neta"
+	"marvell,armada-3700-neta"
 - reg: address and length of the register set for the device.
 - interrupts: interrupt for the device
 - phy: See ethernet.txt file in the same directory.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/mdio-mux-mmioreg.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@ Properties for an MDIO bus multiplexer c
 This is a special case of a MDIO bus multiplexer.  A memory-mapped device,
 like an FPGA, is used to control which child bus is connected.  The mdio-mux
 node must be a child of the memory-mapped device.  The driver currently only
-supports devices with eight-bit registers.
+supports devices with 8, 16 or 32-bit registers.
 
 Required properties in addition to the generic multiplexer properties:
 
@@ -11,7 +11,7 @@ Required properties in addition to the g
 
 - reg : integer, contains the offset of the register that controls the bus
 	multiplexer.  The size field in the 'reg' property is the size of
-	register, and must therefore be 1.
+	register, and must therefore be 1, 2, or 4.
 
 - mux-mask : integer, contains an eight-bit mask that specifies which
 	bits in the register control the actual bus multiplexer.  The
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/mediatek-net.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@ have dual GMAC each represented by a chi
 * Ethernet controller node
 
 Required properties:
-- compatible: Should be "mediatek,mt7623-eth"
+- compatible: Should be "mediatek,mt2701-eth"
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the three frame engines interrupts in numeric
 	order. These are fe_int0, fe_int1 and fe_int2.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt	2017-02-12 16:03:20.000000000 -0500
@@ -6,22 +6,27 @@ Required properties:
 		  Documentation/devicetree/bindings/net/phy.txt
 
 Optional properties:
-- vsc8531,vddmac	: The vddmac in mV.
+- vsc8531,vddmac	: The vddmac in mV. Allowed values is listed
+			  in the first row of Table 1 (below).
+			  This property is only used in combination
+			  with the 'edge-slowdown' property.
+			  Default value is 3300.
 - vsc8531,edge-slowdown	: % the edge should be slowed down relative to
-			  the fastest possible edge time. Native sign
-			  need not enter.
+			  the fastest possible edge time.
 			  Edge rate sets the drive strength of the MAC
-			  interface output signals.  Changing the drive
-			  strength will affect the edge rate of the output
-			  signal.  The goal of this setting is to help
-			  reduce electrical emission (EMI) by being able
-			  to reprogram drive strength and in effect slow
-			  down the edge rate if desired.  Table 1 shows the
-			  impact to the edge rate per VDDMAC supply for each
-			  drive strength setting.
-			  Ref: Table:1 - Edge rate change below.
-
-Note: see dt-bindings/net/mscc-phy-vsc8531.h for applicable values
+			  interface output signals.  Changing the
+			  drive strength will affect the edge rate of
+			  the output signal.  The goal of this setting
+			  is to help reduce electrical emission (EMI)
+			  by being able to reprogram drive strength
+			  and in effect slow down the edge rate if
+			  desired.
+			  To adjust the edge-slowdown, the 'vddmac'
+			  must be specified. Table 1 lists the
+			  supported edge-slowdown values for a given
+			  'vddmac'.
+			  Default value is 0%.
+			  Ref: Table:1 - Edge rate change (below).
 
 Table: 1 - Edge rate change
 ----------------------------------------------------------------|
@@ -29,23 +34,23 @@ Table: 1 - Edge rate change
 |								|
 | 3300 mV	2500 mV		1800 mV		1500 mV		|
 |---------------------------------------------------------------|
-| Default	Deafult		Default		Default		|
+| 0%		0%		0%		0%		|
 | (Fastest)			(recommended)	(recommended)	|
 |---------------------------------------------------------------|
-| -2%		-3%		-5%		-6%		|
+| 2%		3%		5%		6%		|
 |---------------------------------------------------------------|
-| -4%		-6%		-9%		-14%		|
+| 4%		6%		9%		14%		|
 |---------------------------------------------------------------|
-| -7%		-10%		-16%		-21%		|
+| 7%		10%		16%		21%		|
 |(recommended)	(recommended)					|
 |---------------------------------------------------------------|
-| -10%		-14%		-23%		-29%		|
+| 10%		14%		23%		29%		|
 |---------------------------------------------------------------|
-| -17%		-23%		-35%		-42%		|
+| 17%		23%		35%		42%		|
 |---------------------------------------------------------------|
-| -29%		-37%		-52%		-58%		|
+| 29%		37%		52%		58%		|
 |---------------------------------------------------------------|
-| -53%		-63%		-76%		-77%		|
+| 53%		63%		76%		77%		|
 | (slowest)							|
 |---------------------------------------------------------------|
 
@@ -54,5 +59,5 @@ Example:
         vsc8531_0: ethernet-phy@0 {
                 compatible = "ethernet-phy-id0007.0570";
                 vsc8531,vddmac		= <3300>;
-                vsc8531,edge-slowdown	= <21>;
+                vsc8531,edge-slowdown	= <7>;
         };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/oxnas-dwmac.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/oxnas-dwmac.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/oxnas-dwmac.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/oxnas-dwmac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,39 @@
+* Oxford Semiconductor OXNAS DWMAC Ethernet controller
+
+The device inherits all the properties of the dwmac/stmmac devices
+described in the file stmmac.txt in the current directory with the
+following changes.
+
+Required properties on all platforms:
+
+- compatible:	For the OX820 SoC, it should be :
+		- "oxsemi,ox820-dwmac" to select glue
+		- "snps,dwmac-3.512" to select IP version.
+
+- clocks: Should contain phandles to the following clocks
+- clock-names:	Should contain the following:
+		- "stmmaceth" for the host clock - see stmmac.txt
+		- "gmac" for the peripheral gate clock
+
+- oxsemi,sys-ctrl: a phandle to the system controller syscon node
+
+Example :
+
+etha: ethernet@40400000 {
+	compatible = "oxsemi,ox820-dwmac", "snps,dwmac-3.512";
+	reg = <0x40400000 0x2000>;
+	interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+		     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+	interrupt-names = "macirq", "eth_wake_irq";
+	mac-address = [000000000000]; /* Filled in by U-Boot */
+	phy-mode = "rgmii";
+
+	clocks = <&stdclk CLK_820_ETHA>, <&gmacclk>;
+	clock-names = "gmac", "stmmaceth";
+	resets = <&reset RESET_MAC>;
+
+	/* Regmap for sys registers */
+	oxsemi,sys-ctrl = <&sys>;
+
+	status = "disabled";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/phy.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/phy.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/phy.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/phy.txt	2017-02-12 16:03:20.000000000 -0500
@@ -19,8 +19,9 @@ Optional Properties:
   specifications. If neither of these are specified, the default is to
   assume clause 22.
 
-  If the phy's identifier is known then the list may contain an entry
-  of the form: "ethernet-phy-idAAAA.BBBB" where
+  If the PHY reports an incorrect ID (or none at all) then the
+  "compatible" list may contain an entry with the correct PHY ID in the
+  form: "ethernet-phy-idAAAA.BBBB" where
      AAAA - The value of the 16 bit Phy Identifier 1 register as
             4 hex digits. This is the chip vendor OUI bits 3:18
      BBBB - The value of the 16 bit Phy Identifier 2 register as
@@ -35,6 +36,18 @@ Optional Properties:
 - broken-turn-around: If set, indicates the PHY device does not correctly
   release the turn around line low at the end of a MDIO transaction.
 
+- enet-phy-lane-swap: If set, indicates the PHY will swap the TX/RX lanes to
+  compensate for the board being designed with the lanes swapped.
+
+- eee-broken-100tx:
+- eee-broken-1000t:
+- eee-broken-10gt:
+- eee-broken-1000kx:
+- eee-broken-10gkx4:
+- eee-broken-10gkr:
+  Mark the corresponding energy efficient ethernet mode as broken and
+  request the ethernet to stop advertising it.
+
 Example:
 
 ethernet-phy@0 {
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/smsc-lan91c111.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/smsc-lan91c111.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/smsc-lan91c111.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/smsc-lan91c111.txt	2017-02-12 16:03:20.000000000 -0500
@@ -13,3 +13,5 @@ Optional properties:
   16-bit access only.
 - power-gpios: GPIO to control the PWRDWN pin
 - reset-gpios: GPIO to control the RESET pin
+- pxa-u16-align4 : Boolean, put in place the workaround the force all
+		   u16 writes to be 32 bits aligned
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/stmmac.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/stmmac.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/stmmac.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/stmmac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 * STMicroelectronics 10/100/1000 Ethernet driver (GMAC)
 
 Required properties:
-- compatible: Should be "snps,dwmac-<ip_version>" "snps,dwmac"
+- compatible: Should be "snps,dwmac-<ip_version>", "snps,dwmac"
 	For backwards compatibility: "st,spear600-gmac" is also supported.
 - reg: Address and length of the register set for the device
 - interrupt-parent: Should be the phandle for the interrupt controller
@@ -34,7 +34,13 @@ Optional properties:
   platforms.
 - tx-fifo-depth: See ethernet.txt file in the same directory
 - rx-fifo-depth: See ethernet.txt file in the same directory
-- snps,pbl		Programmable Burst Length
+- snps,pbl		Programmable Burst Length (tx and rx)
+- snps,txpbl		Tx Programmable Burst Length. Only for GMAC and newer.
+			If set, DMA tx will use this value rather than snps,pbl.
+- snps,rxpbl		Rx Programmable Burst Length. Only for GMAC and newer.
+			If set, DMA rx will use this value rather than snps,pbl.
+- snps,no-pbl-x8	Don't multiply the pbl/txpbl/rxpbl values by 8.
+			For core rev < 3.50, don't multiply the values by 4.
 - snps,aal		Address-Aligned Beats
 - snps,fixed-burst	Program the DMA to use the fixed burst mode
 - snps,mixed-burst	Program the DMA to use the mixed burst mode
@@ -50,6 +56,8 @@ Optional properties:
 - snps,ps-speed: port selection speed that can be passed to the core when
 		 PCS is supported. For example, this is used in case of SGMII
 		 and MAC2MAC connection.
+- snps,tso: this enables the TSO feature otherwise it will be managed by
+		 MAC HW capability register. Only for GMAC4 and newer.
 - AXI BUS Mode parameters: below the list of all the parameters to program the
 			   AXI register inside the DMA module:
 	- snps,lpi_en: enable Low Power Interface
@@ -62,8 +70,6 @@ Optional properties:
 	- snps,fb: fixed-burst
 	- snps,mb: mixed-burst
 	- snps,rb: rebuild INCRx Burst
-	- snps,tso: this enables the TSO feature otherwise it will be managed by
-	    MAC HW capability register.
 - mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus.
 
 Examples:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/ti,dp83867.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,12 +3,26 @@
 Required properties:
 	- reg - The ID number for the phy, usually a small integer
 	- ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
-		for applicable values
+		for applicable values. Required only if interface type is
+		PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_RXID
 	- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
-		for applicable values
+		for applicable values. Required only if interface type is
+		PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID
 	- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
 		for applicable values
 
+Optional property:
+	- ti,min-output-impedance - MAC Interface Impedance control to set
+				    the programmable output impedance to
+				    minimum value (35 ohms).
+	- ti,max-output-impedance - MAC Interface Impedance control to set
+				    the programmable output impedance to
+				    maximum value (70 ohms).
+
+Note: ti,min-output-impedance and ti,max-output-impedance are mutually
+      exclusive. When both properties are present ti,max-output-impedance
+      takes precedence.
+
 Default child nodes are standard Ethernet PHY device
 nodes as described in Documentation/devicetree/bindings/net/phy.txt
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,65 @@
+Marvell 8897/8997 (sd8897/sd8997/pcie8997) SDIO/PCIE devices
+------
+
+This node provides properties for controlling the Marvell SDIO/PCIE wireless device.
+The node is expected to be specified as a child node to the SDIO/PCIE controller that
+connects the device to the system.
+
+Required properties:
+
+  - compatible : should be one of the following:
+	* "marvell,sd8897"
+	* "marvell,sd8997"
+	* "pci11ab,2b42"
+	* "pci1b4b,2b42"
+
+Optional properties:
+
+  - marvell,caldata* : A series of properties with marvell,caldata prefix,
+		      represent calibration data downloaded to the device during
+		      initialization. This is an array of unsigned 8-bit values.
+		      the properties should follow below property name and
+		      corresponding array length:
+	"marvell,caldata-txpwrlimit-2g" (length = 566).
+	"marvell,caldata-txpwrlimit-5g-sub0" (length = 502).
+	"marvell,caldata-txpwrlimit-5g-sub1" (length = 688).
+	"marvell,caldata-txpwrlimit-5g-sub2" (length = 750).
+	"marvell,caldata-txpwrlimit-5g-sub3" (length = 502).
+  - marvell,wakeup-pin : a wakeup pin number of wifi chip which will be configured
+		      to firmware. Firmware will wakeup the host using this pin
+		      during suspend/resume.
+  - interrupt-parent: phandle of the parent interrupt controller
+  - interrupts : interrupt pin number to the cpu. driver will request an irq based on
+		 this interrupt number. during system suspend, the irq will be enabled
+		 so that the wifi chip can wakeup host platform under certain condition.
+		 during system resume, the irq will be disabled to make sure
+		 unnecessary interrupt is not received.
+
+Example:
+
+Tx power limit calibration data is configured in below example.
+The calibration data is an array of unsigned values, the length
+can vary between hw versions.
+IRQ pin 38 is used as system wakeup source interrupt. wakeup pin 3 is configured
+so that firmware can wakeup host using this device side pin.
+
+&mmc3 {
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	cap-power-off-card;
+	keep-power-in-suspend;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	mwifiex: wifi@1 {
+		compatible = "marvell,sd8897";
+		reg = <1>;
+		interrupt-parent = <&pio>;
+		interrupts = <38 IRQ_TYPE_LEVEL_LOW>;
+
+		marvell,caldata_00_txpwrlimit_2g_cfg_set = /bits/ 8 <
+	0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01>;
+		marvell,wakeup-pin = <3>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/wireless/marvell-sd8xxx.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-Marvell 8897/8997 (sd8897/sd8997) SDIO devices
-------
-
-This node provides properties for controlling the marvell sdio wireless device.
-The node is expected to be specified as a child node to the SDIO controller that
-connects the device to the system.
-
-Required properties:
-
-  - compatible : should be one of the following:
-	* "marvell,sd8897"
-	* "marvell,sd8997"
-
-Optional properties:
-
-  - marvell,caldata* : A series of properties with marvell,caldata prefix,
-		      represent calibration data downloaded to the device during
-		      initialization. This is an array of unsigned 8-bit values.
-		      the properties should follow below property name and
-		      corresponding array length:
-	"marvell,caldata-txpwrlimit-2g" (length = 566).
-	"marvell,caldata-txpwrlimit-5g-sub0" (length = 502).
-	"marvell,caldata-txpwrlimit-5g-sub1" (length = 688).
-	"marvell,caldata-txpwrlimit-5g-sub2" (length = 750).
-	"marvell,caldata-txpwrlimit-5g-sub3" (length = 502).
-  - marvell,wakeup-pin : a wakeup pin number of wifi chip which will be configured
-		      to firmware. Firmware will wakeup the host using this pin
-		      during suspend/resume.
-  - interrupt-parent: phandle of the parent interrupt controller
-  - interrupts : interrupt pin number to the cpu. driver will request an irq based on
-		 this interrupt number. during system suspend, the irq will be enabled
-		 so that the wifi chip can wakeup host platform under certain condition.
-		 during system resume, the irq will be disabled to make sure
-		 unnecessary interrupt is not received.
-
-Example:
-
-Tx power limit calibration data is configured in below example.
-The calibration data is an array of unsigned values, the length
-can vary between hw versions.
-IRQ pin 38 is used as system wakeup source interrupt. wakeup pin 3 is configured
-so that firmware can wakeup host using this device side pin.
-
-&mmc3 {
-	status = "okay";
-	vmmc-supply = <&wlan_en_reg>;
-	bus-width = <4>;
-	cap-power-off-card;
-	keep-power-in-suspend;
-
-	#address-cells = <1>;
-	#size-cells = <0>;
-	mwifiex: wifi@1 {
-		compatible = "marvell,sd8897";
-		reg = <1>;
-		interrupt-parent = <&pio>;
-		interrupts = <38 IRQ_TYPE_LEVEL_LOW>;
-
-		marvell,caldata_00_txpwrlimit_2g_cfg_set = /bits/ 8 <
-	0x01 0x00 0x06 0x00 0x08 0x02 0x89 0x01>;
-		marvell,wakeup-pin = <3>;
-	};
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,48 @@
+* Qualcomm Atheros ath9k wireless devices
+
+This node provides properties for configuring the ath9k wireless device. The
+node is expected to be specified as a child node of the PCI controller to
+which the wireless chip is connected.
+
+Required properties:
+- compatible: For PCI and PCIe devices this should be an identifier following
+		the format as defined in "PCI Bus Binding to Open Firmware"
+		Revision 2.1. One of the possible formats is "pciVVVV,DDDD"
+		where VVVV is the PCI vendor ID and DDDD is PCI device ID.
+		Typically QCA's PCI vendor ID 168c is used while the PCI device
+		ID depends on the chipset - see the following (possibly
+		incomplete) list:
+			- 0023 for AR5416
+			- 0024 for AR5418
+			- 0027 for AR9160
+			- 0029 for AR9220 and AR9223
+			- 002a for AR9280 and AR9283
+			- 002b for AR9285
+			- 002c for AR2427
+			- 002d for AR9227
+			- 002e for AR9287
+			- 0030 for AR9380, AR9381 and AR9382
+			- 0032 for AR9485
+			- 0033 for AR9580 and AR9590
+			- 0034 for AR9462
+			- 0036 for AR9565
+			- 0037 for AR9485
+- reg: Address and length of the register set for the device.
+
+Optional properties:
+- qca,no-eeprom: Indicates that there is no physical EEPROM connected to the
+			ath9k wireless chip (in this case the calibration /
+			EEPROM data will be loaded from userspace using the
+			kernel firmware loader).
+- mac-address: See ethernet.txt in the parent directory
+- local-mac-address: See ethernet.txt in the parent directory
+
+
+In this example, the node is defined as child node of the PCI controller:
+&pci0 {
+	wifi@168c,002d {
+		compatible = "pci168c,002d";
+		reg = <0x7000 0 0 0 0x1000>;
+		qca,no-eeprom;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/nvmem/brcm,ocotp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,17 @@
+Broadcom OTP memory controller
+
+Required Properties:
+- compatible: "brcm,ocotp" for the first generation Broadcom OTPC which is used
+  in Cygnus and supports 32 bit read/write. Use "brcm,ocotp-v2" for the second
+  generation Broadcom OTPC which is used in SoC's such as Stingray and supports
+  64-bit read/write.
+- reg: Base address of the OTP controller.
+- brcm,ocotp-size: Amount of memory available, in 32 bit words
+
+Example:
+
+otp: otp@0301c800 {
+	compatible = "brcm,ocotp";
+	reg = <0x0301c800 0x2c>;
+	brcm,ocotp-size = <2048>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/nvmem/lpc1850-otp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/nvmem/lpc1850-otp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/nvmem/lpc1850-otp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/nvmem/lpc1850-otp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+* NXP LPC18xx OTP memory
+
+Internal OTP (One Time Programmable) memory for NXP LPC18xx/43xx devices.
+
+Required properties:
+  - compatible: Should be "nxp,lpc1850-otp"
+  - reg: Must contain an entry with the physical base address and length
+    for each entry in reg-names.
+  - address-cells: must be set to 1.
+  - size-cells: must be set to 1.
+
+See nvmem.txt for more information.
+
+Example:
+  otp: otp@40045000 {
+    compatible = "nxp,lpc1850-otp";
+    reg = <0x40045000 0x1000>;
+    #address-cells = <1>;
+    #size-cells = <1>;
+  };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/opp/opp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/opp/opp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/opp/opp.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/opp/opp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -86,8 +86,14 @@ Optional properties:
   Single entry is for target voltage and three entries are for <target min max>
   voltages.
 
-  Entries for multiple regulators must be present in the same order as
-  regulators are specified in device's DT node.
+  Entries for multiple regulators shall be provided in the same field separated
+  by angular brackets <>. The OPP binding doesn't provide any provisions to
+  relate the values to their power supplies or the order in which the supplies
+  need to be configured and that is left for the implementation specific
+  binding.
+
+  Entries for all regulators shall be of the same size, i.e. either all use a
+  single value or triplets.
 
 - opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to
   the above opp-microvolt property, but allows multiple voltage ranges to be
@@ -104,10 +110,13 @@ Optional properties:
 
   Should only be set if opp-microvolt is set for the OPP.
 
-  Entries for multiple regulators must be present in the same order as
-  regulators are specified in device's DT node. If this property isn't required
-  for few regulators, then this should be marked as zero for them. If it isn't
-  required for any regulator, then this property need not be present.
+  Entries for multiple regulators shall be provided in the same field separated
+  by angular brackets <>. If current values aren't required for a regulator,
+  then it shall be filled with 0. If current values aren't required for any of
+  the regulators, then this field is not required. The OPP binding doesn't
+  provide any provisions to relate the values to their power supplies or the
+  order in which the supplies need to be configured and that is left for the
+  implementation specific binding.
 
 - opp-microamp-<name>: Named opp-microamp property. Similar to
   opp-microvolt-<name> property, but for microamp instead.
@@ -386,10 +395,12 @@ Example 4: Handling multiple regulators
 / {
 	cpus {
 		cpu@0 {
-			compatible = "arm,cortex-a7";
+			compatible = "vendor,cpu-type";
 			...
 
-			cpu-supply = <&cpu_supply0>, <&cpu_supply1>, <&cpu_supply2>;
+			vcc0-supply = <&cpu_supply0>;
+			vcc1-supply = <&cpu_supply1>;
+			vcc2-supply = <&cpu_supply2>;
 			operating-points-v2 = <&cpu0_opp_table>;
 		};
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,10 +1,17 @@
 * Broadcom iProc PCIe controller with the platform bus interface
 
 Required properties:
-- compatible: Must be "brcm,iproc-pcie" for PAXB, or "brcm,iproc-pcie-paxc"
-  for PAXC.  PAXB-based root complex is used for external endpoint devices.
-  PAXC-based root complex is connected to emulated endpoint devices
-  internal to the ASIC
+- compatible:
+      "brcm,iproc-pcie" for the first generation of PAXB based controller,
+used in SoCs including NSP, Cygnus, NS2, and Pegasus
+      "brcm,iproc-pcie-paxb-v2" for the second generation of PAXB-based
+controllers, used in Stingray
+      "brcm,iproc-pcie-paxc" for the first generation of PAXC based
+controller, used in NS2
+      "brcm,iproc-pcie-paxc-v2" for the second generation of PAXC based
+controller, used in Stingray
+  PAXB-based root complex is used for external endpoint devices. PAXC-based
+root complex is connected to emulated endpoint devices internal to the ASIC
 - reg: base address and length of the PCIe controller I/O register space
 - #interrupt-cells: set to <1>
 - interrupt-map-mask and interrupt-map, standard PCI properties to define the
@@ -19,6 +26,10 @@ Required properties:
 Optional properties:
 - phys: phandle of the PCIe PHY device
 - phy-names: must be "pcie-phy"
+- dma-coherent: present if DMA operations are coherent
+- dma-ranges: Some PAXB-based root complexes do not have inbound mapping done
+  by the ASIC after power on reset.  In this case, SW is required to configure
+the mapping, based on inbound memory regions specified by this property.
 
 - brcm,pcie-ob: Some iProc SoCs do not have the outbound address mapping done
 by the ASIC after power on reset. In this case, SW needs to configure it
@@ -29,11 +40,6 @@ effective:
 Required:
 - brcm,pcie-ob-axi-offset: The offset from the AXI address to the internal
 address used by the iProc PCIe core (not the PCIe address)
-- brcm,pcie-ob-window-size: The outbound address mapping window size (in MB)
-
-Optional:
-- brcm,pcie-ob-oarr-size: Some iProc SoCs need the OARR size bit to be set to
-increase the outbound window size
 
 MSI support (optional):
 
@@ -41,10 +47,19 @@ For older platforms without MSI integrat
 an event queue based MSI support.  The iProc MSI uses host memories to store
 MSI posted writes in the event queues
 
-- msi-parent: Link to the device node of the MSI controller.  On newer iProc
-platforms, the MSI controller may be gicv2m or gicv3-its.  On older iProc
-platforms without MSI support in its interrupt controller, one may use the
-event queue based MSI support integrated within the iProc PCIe core.
+On newer iProc platforms, gicv2m or gicv3-its based MSI support should be used
+
+- msi-map: Maps a Requester ID to an MSI controller and associated MSI
+sideband data
+
+- msi-parent: Link to the device node of the MSI controller, used when no MSI
+sideband data is passed between the iProc PCIe controller and the MSI
+controller
+
+Refer to the following binding documents for more detailed description on
+the use of 'msi-map' and 'msi-parent':
+  Documentation/devicetree/bindings/pci/pci-msi.txt
+  Documentation/devicetree/bindings/interrupt-controller/msi.txt
 
 When the iProc event queue based MSI is used, one needs to define the
 following properties in the MSI device node:
@@ -80,9 +95,7 @@ Example:
 		phy-names = "pcie-phy";
 
 		brcm,pcie-ob;
-		brcm,pcie-ob-oarr-size;
 		brcm,pcie-ob-axi-offset = <0x00000000>;
-		brcm,pcie-ob-window-size = <256>;
 
 		msi-parent = <&msi0>;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/layerscape-pci.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/layerscape-pci.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/layerscape-pci.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/layerscape-pci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@ Required properties:
 - compatible: should contain the platform identifier such as:
         "fsl,ls1021a-pcie", "snps,dw-pcie"
         "fsl,ls2080a-pcie", "fsl,ls2085a-pcie", "snps,dw-pcie"
+        "fsl,ls1046a-pcie"
 - reg: base addresses and lengths of the PCIe controller
 - interrupts: A list of interrupt outputs of the controller. Must contain an
   entry for each entry in the interrupt-names property.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt	2017-02-12 16:03:20.000000000 -0500
@@ -110,6 +110,20 @@ Power supplies for Tegra124:
   - avdd-pll-erefe-supply: Power supply for PLLE (shared with USB3). Must
     supply 1.05 V.
 
+Power supplies for Tegra210:
+- Required:
+  - avdd-pll-uerefe-supply: Power supply for PLLE (shared with USB3). Must
+    supply 1.05 V.
+  - hvddio-pex-supply: High-voltage supply for PCIe I/O and PCIe output
+    clocks. Must supply 1.8 V.
+  - dvddio-pex-supply: Power supply for digital PCIe I/O. Must supply 1.05 V.
+  - dvdd-pex-pll-supply: Power supply for dedicated (internal) PCIe PLL. Must
+    supply 1.05 V.
+  - hvdd-pex-pll-e-supply: High-voltage supply for PLLE (shared with USB3).
+    Must supply 3.3 V.
+  - vddio-pex-ctl-supply: Power supply for PCIe control I/O partition. Must
+    supply 1.8 V.
+
 Root ports are defined as subnodes of the PCIe controller node.
 
 Required properties:
@@ -435,4 +449,100 @@ Board DTS:
 			phy-names = "pcie-0";
 			status = "okay";
 		};
+	};
+
+Tegra210:
+---------
+
+SoC DTSI:
+
+	pcie-controller@01003000 {
+		compatible = "nvidia,tegra210-pcie";
+		device_type = "pci";
+		reg = <0x0 0x01003000 0x0 0x00000800   /* PADS registers */
+		       0x0 0x01003800 0x0 0x00000800   /* AFI registers */
+		       0x0 0x02000000 0x0 0x10000000>; /* configuration space */
+		reg-names = "pads", "afi", "cs";
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>, /* controller interrupt */
+			     <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>; /* MSI interrupt */
+		interrupt-names = "intr", "msi";
+
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 0>;
+		interrupt-map = <0 0 0 0 &gic GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+
+		bus-range = <0x00 0xff>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+
+		ranges = <0x82000000 0 0x01000000 0x0 0x01000000 0 0x00001000   /* port 0 configuration space */
+			  0x82000000 0 0x01001000 0x0 0x01001000 0 0x00001000   /* port 1 configuration space */
+			  0x81000000 0 0x0        0x0 0x12000000 0 0x00010000   /* downstream I/O (64 KiB) */
+			  0x82000000 0 0x13000000 0x0 0x13000000 0 0x0d000000   /* non-prefetchable memory (208 MiB) */
+			  0xc2000000 0 0x20000000 0x0 0x20000000 0 0x20000000>; /* prefetchable memory (512 MiB) */
+
+		clocks = <&tegra_car TEGRA210_CLK_PCIE>,
+			 <&tegra_car TEGRA210_CLK_AFI>,
+			 <&tegra_car TEGRA210_CLK_PLL_E>,
+			 <&tegra_car TEGRA210_CLK_CML0>;
+		clock-names = "pex", "afi", "pll_e", "cml";
+		resets = <&tegra_car 70>,
+			 <&tegra_car 72>,
+			 <&tegra_car 74>;
+		reset-names = "pex", "afi", "pcie_x";
+		status = "disabled";
+
+		pci@1,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82000800 0 0x01000000 0 0x1000>;
+			reg = <0x000800 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <4>;
+		};
+
+		pci@2,0 {
+			device_type = "pci";
+			assigned-addresses = <0x82001000 0 0x01001000 0 0x1000>;
+			reg = <0x001000 0 0 0 0>;
+			status = "disabled";
+
+			#address-cells = <3>;
+			#size-cells = <2>;
+			ranges;
+
+			nvidia,num-lanes = <1>;
+		};
+	};
+
+Board DTS:
+
+	pcie-controller@01003000 {
+		status = "okay";
+
+		avdd-pll-uerefe-supply = <&avdd_1v05_pll>;
+		hvddio-pex-supply = <&vdd_1v8>;
+		dvddio-pex-supply = <&vdd_pex_1v05>;
+		dvdd-pex-pll-supply = <&vdd_pex_1v05>;
+		hvdd-pex-pll-e-supply = <&vdd_1v8>;
+		vddio-pex-ctl-supply = <&vdd_1v8>;
+
+		pci@1,0 {
+			phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-0}>,
+			       <&{/padctl@7009f000/pads/pcie/lanes/pcie-1}>,
+			       <&{/padctl@7009f000/pads/pcie/lanes/pcie-2}>,
+			       <&{/padctl@7009f000/pads/pcie/lanes/pcie-3}>;
+			phy-names = "pcie-0", "pcie-1", "pcie-2", "pcie-3";
+			status = "okay";
+		};
+
+		pci@2,0 {
+			phys = <&{/padctl@7009f000/pads/pcie/lanes/pcie-4}>;
+			phy-names = "pcie-0";
+			status = "okay";
+		};
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/pci.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/pci.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/pci.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/pci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -18,3 +18,9 @@ driver implementation may support the fo
    host bridges in the system, otherwise potentially conflicting domain numbers
    may be assigned to root buses behind different host bridges.  The domain
    number for each host bridge in the system must be unique.
+- max-link-speed:
+   If present this property specifies PCI gen for link capability.  Host
+   drivers could add this as a strategy to avoid unnecessary operation for
+   unsupported link speed, for instance, trying to do training for
+   unsupported link speed, etc.  Must be '4' for gen4, '3' for gen3, '2'
+   for gen2, and '1' for gen1. Any other values are invalid.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/qcom,pcie.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/qcom,pcie.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/qcom,pcie.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/qcom,pcie.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
 			- "qcom,pcie-ipq8064" for ipq8064
 			- "qcom,pcie-apq8064" for apq8064
 			- "qcom,pcie-apq8084" for apq8084
+			- "qcom,pcie-msm8996" for msm8996 or apq8096
 
 - reg:
 	Usage: required
@@ -92,6 +93,17 @@
 			- "aux"		Auxiliary (AUX) clock
 			- "bus_master"	Master AXI clock
 			- "bus_slave"	Slave AXI clock
+
+- clock-names:
+	Usage: required for msm8996/apq8096
+	Value type: <stringlist>
+	Definition: Should contain the following entries
+			- "pipe"	Pipe Clock driving internal logic
+			- "aux"		Auxiliary (AUX) clock
+			- "cfg"		Configuration clock
+			- "bus_master"	Master AXI clock
+			- "bus_slave"	Slave AXI clock
+
 - resets:
 	Usage: required
 	Value type: <prop-encoded-array>
@@ -115,7 +127,7 @@
 			- "core" Core reset
 
 - power-domains:
-	Usage: required for apq8084
+	Usage: required for apq8084 and msm8996/apq8096
 	Value type: <prop-encoded-array>
 	Definition: A phandle and power domain specifier pair to the
 		    power domain which is responsible for collapsing
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/rcar-pci.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/rcar-pci.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pci/rcar-pci.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pci/rcar-pci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@ compatible: "renesas,pcie-r8a7779" for t
 	    "renesas,pcie-r8a7793" for the R8A7793 SoC;
 	    "renesas,pcie-r8a7795" for the R8A7795 SoC;
 	    "renesas,pcie-rcar-gen2" for a generic R-Car Gen2 compatible device.
+	    "renesas,pcie-rcar-gen3" for a generic R-Car Gen3 compatible device.
 
 	    When compatible with the generic version, nodes must list the
 	    SoC-specific version corresponding to the platform first
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/phy/meson8b-usb2-phy.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,27 @@
+* Amlogic Meson8b and GXBB USB2 PHY
+
+Required properties:
+- compatible:	Depending on the platform this should be one of:
+	"amlogic,meson8b-usb2-phy"
+	"amlogic,meson-gxbb-usb2-phy"
+- reg:		The base address and length of the registers
+- #phys-cells:	should be 0 (see phy-bindings.txt in this directory)
+- clocks:	phandle and clock identifier for the phy clocks
+- clock-names:	"usb_general" and "usb"
+
+Optional properties:
+- resets:	reference to the reset controller
+- phy-supply:	see phy-bindings.txt in this directory
+
+
+Example:
+
+usb0_phy: usb-phy@c0000000 {
+	compatible = "amlogic,meson-gxbb-usb2-phy";
+	#phy-cells = <0>;
+	reg = <0x0 0xc0000000 0x0 0x20>;
+	resets = <&reset RESET_USB_OTG>;
+	clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
+	clock-names = "usb_general", "usb";
+	phy-supply = <&usb_vbus>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/phy/meson-usb2-phy.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-* Amlogic USB2 PHY
-
-Required properties:
-- compatible:	Depending on the platform this should be one of:
-	"amlogic,meson8b-usb2-phy"
-	"amlogic,meson-gxbb-usb2-phy"
-- reg:		The base address and length of the registers
-- #phys-cells:	should be 0 (see phy-bindings.txt in this directory)
-- clocks:	phandle and clock identifier for the phy clocks
-- clock-names:	"usb_general" and "usb"
-
-Optional properties:
-- resets:	reference to the reset controller
-- phy-supply:	see phy-bindings.txt in this directory
-
-
-Example:
-
-usb0_phy: usb_phy@0 {
-	compatible = "amlogic,meson-gxbb-usb2-phy";
-	#phy-cells = <0>;
-	reg = <0x0 0x0 0x0 0x20>;
-	resets = <&reset RESET_USB_OTG>;
-	clocks = <&clkc CLKID_USB>, <&clkc CLKID_USB0>;
-	clock-names = "usb_general", "usb";
-	phy-supply = <&usb_vbus>;
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,20 @@ Required properties:
 - reg: Should contain the register physical address and length for the
   pin controller.
 
+- clocks: phandle to the clocks feeding the pin controller:
+  - "apb": the gated APB parent clock
+  - "hosc": the high frequency oscillator in the system
+  - "losc": the low frequency oscillator in the system
+
+Note: For backward compatibility reasons, the hosc and losc clocks are only
+required if you need to use the optional input-debounce property. Any new
+device tree should set them.
+
+Optional properties:
+  - input-debounce: Array of debouncing periods in microseconds. One period per
+    irq bank found in the controller. 0 if no setup required.
+
+
 Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices.
 
@@ -37,6 +51,22 @@ pins it needs, and how they should be co
 configuration, drive strength and pullups. If one of these options is
 not set, its actual value will be unspecified.
 
+This driver supports the generic pin multiplexing and configuration
+bindings. For details on each properties, you can refer to
+./pinctrl-bindings.txt.
+
+Required sub-node properties:
+  - pins
+  - function
+
+Optional sub-node properties:
+  - bias-disable
+  - bias-pull-up
+  - bias-pull-down
+  - drive-strength
+
+*** Deprecated pin configuration and multiplexing binding
+
 Required subnode-properties:
 
 - allwinner,pins: List of strings containing the pin name.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -98,6 +98,8 @@ DRIVE_STRENGTH (3 << 5): indicate the dr
 				01 - Low
 				10 - Medium
 				11 - High
+OUTPUT		(1 << 7): indicate this pin need to be configured as an output.
+OUTPUT_VAL	(1 << 8): output val (1 = high, 0 = low)
 DEBOUNCE	(1 << 16): indicate this pin needs debounce.
 DEBOUNCE_VAL	(0x3fff << 17): debounce value.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,8 @@ Required properties for the root node:
 		      "amlogic,meson8b-aobus-pinctrl"
 		      "amlogic,meson-gxbb-periphs-pinctrl"
 		      "amlogic,meson-gxbb-aobus-pinctrl"
+		      "amlogic,meson-gxl-periphs-pinctrl"
+		      "amlogic,meson-gxl-aobus-pinctrl"
  - reg: address and size of registers controlling irq functionality
 
 === GPIO sub-nodes ===
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@ used for a specific device or function.
 pins, optional function, and optional mux related configuration.
 
 Required properties for pin controller node:
- - compatible: "oxsemi,ox810se-pinctrl"
+ - compatible: "oxsemi,ox810se-pinctrl" or "oxsemi,ox820-pinctrl"
  - oxsemi,sys-ctrl: a phandle to the system controller syscon node
 
 Required properties for pin configuration sub-nodes:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt	2017-02-12 16:03:20.000000000 -0500
@@ -97,6 +97,11 @@ For example:
 	};
 
 == Pin controller devices ==
+Required properties: See the pin controller driver specific documentation
+
+Optional properties:
+#pinctrl-cells:	Number of pin control cells in addition to the index within the
+		pin controller device instance
 
 Pin controller devices should contain the pin configuration nodes that client
 devices reference.
@@ -119,7 +124,8 @@ For example:
 
 The contents of each of those pin configuration child nodes is defined
 entirely by the binding for the individual pin controller device. There
-exists no common standard for this content.
+exists no common standard for this content. The pinctrl framework only
+provides generic helper bindings that the pin controller driver can use.
 
 The pin configuration nodes need not be direct children of the pin controller
 device; they may be grandchildren, for example. Whether this is legal, and
@@ -156,6 +162,42 @@ state_2_node_a {
 	pins = "mfio29", "mfio30";
 };
 
+Optionally an altenative binding can be used if more suitable depending on the
+pin controller hardware. For hardaware where there is a large number of identical
+pin controller instances, naming each pin and function can easily become
+unmaintainable. This is especially the case if the same controller is used for
+different pins and functions depending on the SoC revision and packaging.
+
+For cases like this, the pin controller driver may use pinctrl-pin-array helper
+binding with a hardware based index and a number of pin configuration values:
+
+pincontroller {
+	... /* Standard DT properties for the device itself elided */
+	#pinctrl-cells = <2>;
+
+	state_0_node_a {
+		pinctrl-pin-array = <
+			0 A_DELAY_PS(0) G_DELAY_PS(120)
+			4 A_DELAY_PS(0) G_DELAY_PS(360)
+			...
+		>;
+	};
+	...
+};
+
+Above #pinctrl-cells specifies the number of value cells in addition to the
+index of the registers. This is similar to the interrupts-extended binding with
+one exception. There is no need to specify the phandle for each entry as that
+is already known as the defined pins are always children of the pin controller
+node. Further having the phandle pointing to another pin controller would not
+currently work as the pinctrl framework uses named modes to group pins for each
+pin control device.
+
+The index for pinctrl-pin-array must relate to the hardware for the pinctrl
+registers, and must not be a virtual index of pin instances. The reason for
+this is to avoid mapping of the index in the dts files and the pin controller
+driver as it can change.
+
 == Generic pin configuration node content ==
 
 Many data items that are represented in a pin configuration node are common
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-palmas.txt	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,15 @@ Optional properties:
 - ti,palmas-enable-dvfs2: Enable DVFS2. Configure pins for DVFS2 mode.
 	Selection primary or secondary function associated to GPADC_START
 	and SYSEN2 pin/pad for DVFS2 interface
+- ti,palmas-override-powerhold: This is applicable for PMICs for which
+	GPIO7 is configured in POWERHOLD mode which has higher priority
+	over DEV_ON bit and keeps the PMIC supplies on even after the DEV_ON
+	bit is turned off. This property enables driver to over ride the
+	POWERHOLD value to GPIO7 so as to turn off the PMIC in power off
+	scenarios. So for GPIO7 if ti,palmas-override-powerhold is set
+	then the GPIO_7 field should never be muxed to anything else.
+	It should be set to POWERHOLD by default and only in case of
+	power off scenarios the driver will over ride the mux value.
 
 This binding uses the following generic properties as defined in
 pinctrl-bindings.txt:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,9 @@ Required properties:
 
 - reg : offset and length of the register set for the mux registers
 
+- #pinctrl-cells : number of cells in addition to the index, set to 1
+  for pinctrl-single,pins and 2 for pinctrl-single,bits
+
 - pinctrl-single,register-width : pinmux register access width in bits
 
 - pinctrl-single,function-mask : mask of allowed pinmux function bits
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,74 @@
+SEMTECH SX150x GPIO expander bindings
+
+Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and
+../interrupt-controller/interrupts.txt for generic information regarding
+pin controller, GPIO, and interrupt bindings.
+
+Required properties:
+- compatible: should be one of :
+			"semtech,sx1501q",
+			"semtech,sx1502q",
+			"semtech,sx1503q",
+			"semtech,sx1504q",
+			"semtech,sx1505q",
+			"semtech,sx1506q",
+			"semtech,sx1507q",
+			"semtech,sx1508q",
+			"semtech,sx1509q".
+
+- reg: The I2C slave address for this device.
+
+- #gpio-cells: Should be 2. The first cell is the GPIO number and the
+		second cell is used to specify optional parameters:
+		bit 0: polarity (0: normal, 1: inverted)
+
+- gpio-controller: Marks the device as a GPIO controller.
+
+Optional properties :
+- interrupt-parent: phandle of the parent interrupt controller.
+
+- interrupts: Interrupt specifier for the controllers interrupt.
+
+- interrupt-controller: Marks the device as a interrupt controller.
+
+- semtech,probe-reset: Will trigger a reset of the GPIO expander on probe,
+		only for sx1507q, sx1508q and sx1509q
+
+The GPIO expander can optionally be used as an interrupt controller, in
+which case it uses the default two cell specifier.
+
+Required properties for pin configuration sub-nodes:
+ - pins: List of pins to which the configuration applies.
+
+Optional properties for pin configuration sub-nodes:
+----------------------------------------------------
+ - bias-disable: disable any pin bias, except the OSCIO pin
+ - bias-pull-up: pull up the pin, except the OSCIO pin
+ - bias-pull-down: pull down the pin, except the OSCIO pin
+ - bias-pull-pin-default: use pin-default pull state, except the OSCIO pin
+ - drive-push-pull: drive actively high and low
+ - drive-open-drain: drive with open drain only for sx1507q, sx1508q and sx1509q and except the OSCIO pin
+ - output-low: set the pin to output mode with low level
+ - output-high: set the pin to output mode with high level
+
+Example:
+
+	i2c0gpio-expander@20{
+		#gpio-cells = <2>;
+		#interrupt-cells = <2>;
+		compatible = "semtech,sx1506q";
+		reg = <0x20>;
+		interrupt-parent = <&gpio_1>;
+		interrupts = <16 0>;
+
+		gpio-controller;
+		interrupt-controller;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio1_cfg_pins>;
+
+		gpio1_cfg_pins: gpio1-cfg {
+			pins = "gpio1";
+			bias-pull-up;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,177 @@
+Qualcomm MSM8994 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8994 platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: Should contain one of:
+		    "qcom,msm8992-pinctrl",
+		    "qcom,msm8994-pinctrl".
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+	Usage: required
+	Value type: <string-array>
+	Definition: List of gpio pins affected by the properties specified in
+		    this subnode.
+
+		    Valid pins are:
+		      gpio0-gpio145
+		        Supports mux, bias and drive-strength
+
+		      sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk,
+		      sdc2_cmd, sdc2_data
+		        Supports bias and drive-strength
+
+- function:
+	Usage: required
+	Value type: <string>
+	Definition: Specify the alternative function to be configured for the
+		    specified pins. Functions are only valid for gpio pins.
+		    Valid values are:
+
+		    audio_ref_clk,  blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
+		    blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11,
+		    blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3,
+		    blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3,
+		    blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9,
+		    blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11,
+		    blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5,
+		    blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11,
+		    blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5,
+		    blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11,
+		    blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b,
+		    blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3,
+		    cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1,
+		    cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4,
+		    gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a,
+		    gcc_gp3_clk_b, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk,
+		    gp1_clk, gps_tx, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, hdmi_rcv,
+		    mdp_vsync, mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a,
+		    qdss_cti_trig_in_b, qdss_cti_trig_in_c, qdss_cti_trig_in_d,
+		    qdss_cti_trig_out_a, qdss_cti_trig_out_b, qdss_cti_trig_out_c,
+		    qdss_cti_trig_out_d, qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
+		    qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0,
+		    pci_e1, pri_mi2s, sdc4, sec_mi2s, slimbus, spkr_i2s, ter_mi2s, tsif1,
+		    tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4, gpio
+
+- bias-disable:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull up.
+
+- output-high:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    high.
+		    Not valid for sdc pins.
+
+- output-low:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    low.
+		    Not valid for sdc pins.
+
+- drive-strength:
+	Usage: optional
+	Value type: <u32>
+	Definition: Selects the drive strength for the specified pins, in mA.
+		    Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+	msmgpio: pinctrl@fd510000 {
+		compatible = "qcom,msm8994-pinctrl";
+		reg = <0xfd510000 0x4000>;
+		interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		blsp1_uart2_default: blsp1_uart2_default {
+			pinmux {
+				pins = "gpio4", "gpio5";
+				function = "blsp_uart2";
+			};
+			pinconf {
+				pins = "gpio4", "gpio5";
+				drive-strength = <16>;
+				bias-disable;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -19,10 +19,11 @@ The pins are grouped into up to 5 indivi
 defined as gpio sub-nodes of the pinmux controller.
 
 Required properties for iomux controller:
-  - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
-		       "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
-		       "rockchip,rk3228-pinctrl", "rockchip,rk3288-pinctrl"
-		       "rockchip,rk3368-pinctrl", "rockchip,rk3399-pinctrl"
+  - compatible: one of "rockchip,rk1108-pinctrl", "rockchip,rk2928-pinctrl"
+		       "rockchip,rk3066a-pinctrl", "rockchip,rk3066b-pinctrl"
+		       "rockchip,rk3188-pinctrl", "rockchip,rk3228-pinctrl"
+		       "rockchip,rk3288-pinctrl", "rockchip,rk3368-pinctrl"
+		       "rockchip,rk3399-pinctrl"
   - rockchip,grf: phandle referencing a syscon providing the
 	 "general register files"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -19,11 +19,30 @@ Required Properties:
   - "samsung,exynos5260-pinctrl": for Exynos5260 compatible pin-controller.
   - "samsung,exynos5410-pinctrl": for Exynos5410 compatible pin-controller.
   - "samsung,exynos5420-pinctrl": for Exynos5420 compatible pin-controller.
+  - "samsung,exynos5433-pinctrl": for Exynos5433 compatible pin-controller.
   - "samsung,exynos7-pinctrl": for Exynos7 compatible pin-controller.
 
 - reg: Base address of the pin controller hardware module and length of
   the address space it occupies.
 
+  - reg: Second base address of the pin controller if the specific registers
+  of the pin controller are separated into the different base address.
+
+	Eg: GPF[1-5] of Exynos5433 are separated into the two base address.
+	- First base address is for GPAx and GPF[1-5] external interrupt
+	  registers.
+	- Second base address is for GPF[1-5] pinctrl registers.
+
+	pinctrl_0: pinctrl@10580000 {
+		compatible = "samsung,exynos5433-pinctrl";
+		reg = <0x10580000 0x1a20>, <0x11090000 0x100>;
+
+		wakeup-interrupt-controller {
+			compatible = "samsung,exynos7-wakeup-eint";
+			interrupts = <0 16 0>;
+		};
+	};
+
 - Pin banks as child nodes: Pin banks of the controller are represented by child
   nodes of the controller node. Bank name is taken from name of the node. Each
   bank node must contain following properties:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pinctrl/ti,da850-pupd.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,55 @@
+* Pin configuration for TI DA850/OMAP-L138/AM18x
+
+These SoCs have a separate controller for setting bias (internal pullup/down).
+Bias can only be selected for groups rather than individual pins.
+
+Required Properties:
+
+  - compatible: Must be "ti,da850-pupd"
+  - reg: Base address and length of the memory resource used by the pullup/down
+    controller hardware module.
+
+The controller node also acts as a container for pin group configuration nodes.
+The names of these groups are ignored.
+
+Pin Group Node Properties:
+
+- groups: An array of strings, each string containing the name of a pin group.
+          Valid names are "cp0".."cp31".
+
+The pin configuration parameters use the generic pinconf bindings defined in
+pinctrl-bindings.txt in this directory. The supported parameters are
+bias-disable, bias-pull-up, bias-pull-down.
+
+
+Example
+-------
+
+In common dtsi file:
+
+	pinconf: pin-controller@22c00c {
+		compatible = "ti,da850-pupd";
+		reg = <0x22c00c 0x8>;
+	};
+
+In board-specific file:
+
+	&pinconf {
+		pinctrl-0 = <&pinconf_bias_groups>;
+		pinctrl-names = "default";
+
+		pinconf_bias_groups: bias-groups {
+			pull-up {
+				groups = "cp30", "cp31";
+				bias-pull-up;
+			};
+			pull-down {
+				groups = "cp29", "cp28";
+				bias-pull-down;
+			};
+			disable {
+				groups = "cp27", "cp26";
+				bias-disable;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/domain-idle-state.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/domain-idle-state.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/domain-idle-state.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/domain-idle-state.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,33 @@
+PM Domain Idle State Node:
+
+A domain idle state node represents the state parameters that will be used to
+select the state when there are no active components in the domain.
+
+The state node has the following parameters -
+
+- compatible:
+	Usage: Required
+	Value type: <string>
+	Definition: Must be "domain-idle-state".
+
+- entry-latency-us
+	Usage: Required
+	Value type: <prop-encoded-array>
+	Definition: u32 value representing worst case latency in
+		    microseconds required to enter the idle state.
+		    The exit-latency-us duration may be guaranteed
+		    only after entry-latency-us has passed.
+
+- exit-latency-us
+	Usage: Required
+	Value type: <prop-encoded-array>
+	Definition: u32 value representing worst case latency
+		    in microseconds required to exit the idle state.
+
+- min-residency-us
+	Usage: Required
+	Value type: <prop-encoded-array>
+	Definition: u32 value representing minimum residency duration
+		    in microseconds after which the idle state will yield
+		    power benefits after overcoming the overhead in entering
+i		    the idle state.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/power_domain.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/power_domain.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/power_domain.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/power_domain.txt	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,15 @@ Optional properties:
    specified by this binding. More details about power domain specifier are
    available in the next section.
 
+- domain-idle-states : A phandle of an idle-state that shall be soaked into a
+                generic domain power state. The idle state definitions are
+                compatible with domain-idle-state specified in [1].
+  The domain-idle-state property reflects the idle state of this PM domain and
+  not the idle states of the devices or sub-domains in the PM domain. Devices
+  and sub-domains have their own idle-states independent of the parent
+  domain's idle states. In the absence of this property, the domain would be
+  considered as capable of being powered-on or powered-off.
+
 Example:
 
 	power: power-controller@12340000 {
@@ -59,6 +68,38 @@ The nodes above define two power control
 Domains created by the 'child' power controller are subdomains of '0' power
 domain provided by the 'parent' power controller.
 
+Example 3:
+	parent: power-controller@12340000 {
+		compatible = "foo,power-controller";
+		reg = <0x12340000 0x1000>;
+		#power-domain-cells = <0>;
+		domain-idle-states = <&DOMAIN_RET>, <&DOMAIN_PWR_DN>;
+	};
+
+	child: power-controller@12341000 {
+		compatible = "foo,power-controller";
+		reg = <0x12341000 0x1000>;
+		power-domains = <&parent 0>;
+		#power-domain-cells = <0>;
+		domain-idle-states = <&DOMAIN_PWR_DN>;
+	};
+
+	DOMAIN_RET: state@0 {
+		compatible = "domain-idle-state";
+		reg = <0x0>;
+		entry-latency-us = <1000>;
+		exit-latency-us = <2000>;
+		min-residency-us = <10000>;
+	};
+
+	DOMAIN_PWR_DN: state@1 {
+		compatible = "domain-idle-state";
+		reg = <0x1>;
+		entry-latency-us = <5000>;
+		exit-latency-us = <8000>;
+		min-residency-us = <7000>;
+	};
+
 ==PM domain consumers==
 
 Required properties:
@@ -76,3 +117,5 @@ Example:
 The node above defines a typical PM domain consumer device, which is located
 inside a PM domain with index 0 of a power controller represented by a node
 with the label "power".
+
+[1]. Documentation/devicetree/bindings/power/domain-idle-state.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,12 +1,14 @@
-DT bindings for the Renesas R-Car System Controller
+DT bindings for the Renesas R-Car (RZ/G) System Controller
 
 == System Controller Node ==
 
-The R-Car System Controller provides power management for the CPU cores and
-various coprocessors.
+The R-Car (RZ/G) System Controller provides power management for the CPU cores
+and various coprocessors.
 
 Required properties:
   - compatible: Must contain exactly one of the following:
+      - "renesas,r8a7743-sysc" (RZ/G1M)
+      - "renesas,r8a7745-sysc" (RZ/G1E)
       - "renesas,r8a7779-sysc" (R-Car H1)
       - "renesas,r8a7790-sysc" (R-Car H2)
       - "renesas,r8a7791-sysc" (R-Car M2-W)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/supply/tps65217_charger.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/supply/tps65217_charger.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/power/supply/tps65217_charger.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/power/supply/tps65217_charger.txt	2017-02-12 16:03:20.000000000 -0500
@@ -2,11 +2,16 @@ TPS65217 Charger
 
 Required Properties:
 -compatible: "ti,tps65217-charger"
+-interrupts: TPS65217 interrupt numbers for the AC and USB charger input change.
+             Should be <0> for the USB charger and <1> for the AC adapter.
+-interrupt-names: Should be "USB" and "AC"
 
 This node is a subnode of the tps65217 PMIC.
 
 Example:
 
 	tps65217-charger {
-		compatible = "ti,tps65090-charger";
+		compatible = "ti,tps65217-charger";
+		interrupts = <0>, <1>;
+		interrupt-names = "USB", "AC";
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/powerpc/fsl/guts.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/powerpc/fsl/guts.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/powerpc/fsl/guts.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/powerpc/fsl/guts.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-* Global Utilities Block
-
-The global utilities block controls power management, I/O device
-enabling, power-on-reset configuration monitoring, general-purpose
-I/O signal configuration, alternate function selection for multiplexed
-signals, and clock control.
-
-Required properties:
-
- - compatible : Should define the compatible device type for
-   global-utilities.
-   Possible compatibles:
-	"fsl,qoriq-device-config-1.0"
-	"fsl,qoriq-device-config-2.0"
-	"fsl,<chip>-device-config"
-	"fsl,<chip>-guts"
- - reg : Offset and length of the register set for the device.
-
-Recommended properties:
-
- - fsl,has-rstcr : Indicates that the global utilities register set
-   contains a functioning "reset control register" (i.e. the board
-   is wired to reset upon setting the HRESET_REQ bit in this register).
-
- - fsl,liodn-bits : Indicates the number of defined bits in the LIODN
-   registers, for those SOCs that have a PAMU device.
-
-Examples:
-	global-utilities@e0000 {	/* global utilities block */
-		compatible = "fsl,mpc8548-guts";
-		reg = <e0000 1000>;
-		fsl,has-rstcr;
-	};
-
-	guts: global-utilities@e0000 {
-		compatible = "fsl,qoriq-device-config-1.0";
-		reg = <0xe0000 0xe00>;
-		fsl,has-rstcr;
-		#sleep-cells = <1>;
-		fsl,liodn-bits = <12>;
-	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pwm/pwm-bcm2835.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@ BCM2835 PWM controller (Raspberry Pi con
 Required properties:
 - compatible: should be "brcm,bcm2835-pwm"
 - reg: physical base address and length of the controller's registers
-- clock: This clock defines the base clock frequency of the PWM hardware
+- clocks: This clock defines the base clock frequency of the PWM hardware
   system, the period and the duty_cycle of the PWM signal is a multiple of
   the base period.
 - #pwm-cells: Should be 2. See pwm.txt in this directory for a description of
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/pwm/pwm-hibvt.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,21 @@
+Hisilicon PWM controller
+
+Required properties:
+-compatible: should contain one SoC specific compatible string
+ The SoC specific strings supported including:
+	"hisilicon,hi3516cv300-pwm"
+	"hisilicon,hi3519v100-pwm"
+- reg: physical base address and length of the controller's registers.
+- clocks: phandle and clock specifier of the PWM reference clock.
+- resets: phandle and reset specifier for the PWM controller reset.
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
+  the cells format.
+
+Example:
+	pwm: pwm@12130000 {
+		compatible = "hisilicon,hi3516cv300-pwm";
+		reg = <0x12130000 0x10000>;
+		clocks = <&crg_ctrl HI3516CV300_PWM_CLK>;
+		resets = <&crg_ctrl 0x38 0>;
+		#pwm-cells = <3>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/regulator/pwm-regulator.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/regulator/pwm-regulator.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/regulator/pwm-regulator.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/regulator/pwm-regulator.txt	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@ Any property defined as part of the core
 
 Continuous Voltage With Enable GPIO Example:
 	pwm_regulator {
-		compatible = "pwm-regulator;
+		compatible = "pwm-regulator";
 		pwms = <&pwm1 0 8448 0>;
 		enable-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>;
 		regulator-min-microvolt = <1016000>;
@@ -76,7 +76,7 @@ Continuous Voltage With Enable GPIO Exam
 
 Voltage Table Example:
 	pwm_regulator {
-		compatible = "pwm-regulator;
+		compatible = "pwm-regulator";
 		pwms = <&pwm1 0 8448 0>;
 		regulator-min-microvolt = <1016000>;
 		regulator-max-microvolt = <1114000>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/regulator/tps65218.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,23 +1,78 @@
 TPS65218 family of regulators
 
 Required properties:
-For tps65218 regulators/LDOs
-- compatible:
-  - "ti,tps65218-dcdc1" for DCDC1
-  - "ti,tps65218-dcdc2" for DCDC2
-  - "ti,tps65218-dcdc3" for DCDC3
-  - "ti,tps65218-dcdc4" for DCDC4
-  - "ti,tps65218-dcdc5" for DCDC5
-  - "ti,tps65218-dcdc6" for DCDC6
-  - "ti,tps65218-ldo1" for LDO1
+- compatible: "ti,tps65218"
+- reg: I2C slave address
 
-Optional properties:
-- Any optional property defined in bindings/regulator/regulator.txt
+- List of regulators provided by this controller, must be named
+  after their hardware counterparts: dcdc[1-6] and ldo1
+- This is the list of child nodes that specify the regulator
+  initialization data for defined regulators. Not all regulators for the given
+  device need to be present. The definition for each of these nodes is defined
+  using the standard binding for regulators found at ./regulator.txt.
+
+  The valid names for regulators are:
+  tps65217: regulator-dcdc1, regulator-dcdc2, regulator-dcdc3, regulator-dcdc4,
+  regulator-dcdc5, regulator-dcdc6, regulator-ldo1, regulator-ls3.
+  Each regulator is defined using the standard binding for regulators.
 
 Example:
+tps65218: tps65218@24 {
+	reg = <0x24>;
+	compatible = "ti,tps65218";
+	interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+	interrupt-controller;
+	#interrupt-cells = <2>;
 
-	xyz: regulator@0 {
-		compatible = "ti,tps65218-dcdc1";
-		regulator-min-microvolt  = <1000000>;
-		regulator-max-microvolt  = <3000000>;
+	dcdc1: regulator-dcdc1 {
+		regulator-name = "vdd_core";
+		regulator-min-microvolt = <912000>;
+		regulator-max-microvolt = <1144000>;
+		regulator-boot-on;
+		regulator-always-on;
 	};
+
+	dcdc2: regulator-dcdc2 {
+		regulator-name = "vdd_mpu";
+		regulator-min-microvolt = <912000>;
+		regulator-max-microvolt = <1378000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	dcdc3: regulator-dcdc3 {
+		regulator-name = "vdcdc3";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	dcdc5: regulator-dcdc5 {
+		regulator-name = "v1_0bat";
+		regulator-min-microvolt = <1000000>;
+		regulator-max-microvolt = <1000000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	dcdc6: regulator-dcdc6 {
+		regulator-name = "v1_8bat";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	ldo1: regulator-ldo1 {
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
+		regulator-always-on;
+	};
+
+	ls3: regulator-ls3 {
+		regulator-min-microvolt = <100000>;
+		regulator-max-microvolt = <1000000>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/remoteproc/qcom,adsp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,98 @@
+Qualcomm ADSP Peripheral Image Loader
+
+This document defines the binding for a component that loads and boots firmware
+on the Qualcomm ADSP Hexagon core.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be one of:
+		    "qcom,msm8974-adsp-pil"
+		    "qcom,msm8996-adsp-pil"
+
+- interrupts-extended:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: must list the watchdog, fatal IRQs ready, handover and
+		    stop-ack IRQs
+
+- interrupt-names:
+	Usage: required
+	Value type: <stringlist>
+	Definition: must be "wdog", "fatal", "ready", "handover", "stop-ack"
+
+- clocks:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: reference to the xo clock to be held on behalf of the
+		    booting Hexagon core
+
+- clock-names:
+	Usage: required
+	Value type: <stringlist>
+	Definition: must be "xo"
+
+- cx-supply:
+	Usage: required
+	Value type: <phandle>
+	Definition: reference to the regulator to be held on behalf of the
+		    booting Hexagon core
+
+- memory-region:
+	Usage: required
+	Value type: <phandle>
+	Definition: reference to the reserved-memory for the ADSP
+
+- qcom,smem-states:
+	Usage: required
+	Value type: <phandle>
+	Definition: reference to the smem state for requesting the ADSP to
+		    shut down
+
+- qcom,smem-state-names:
+	Usage: required
+	Value type: <stringlist>
+	Definition: must be "stop"
+
+
+= SUBNODES
+The adsp node may have an subnode named "smd-edge" that describes the SMD edge,
+channels and devices related to the ADSP.  See ../soc/qcom/qcom,smd.txt for
+details on how to describe the SMD edge.
+
+
+= EXAMPLE
+The following example describes the resources needed to boot control the
+ADSP, as it is found on MSM8974 boards.
+
+	adsp {
+		compatible = "qcom,msm8974-adsp-pil";
+
+		interrupts-extended = <&intc 0 162 IRQ_TYPE_EDGE_RISING>,
+				      <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+				      <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+				      <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+				      <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "wdog",
+				  "fatal",
+				  "ready",
+				  "handover",
+				  "stop-ack";
+
+		clocks = <&rpmcc RPM_CXO_CLK>;
+		clock-names = "xo";
+
+		cx-supply = <&pm8841_s2>;
+
+		memory-region = <&adsp_region>;
+
+		qcom,smem-states = <&adsp_smp2p_out 0>;
+		qcom,smem-state-names = "stop";
+
+		smd-edge {
+			interrupts = <0 156 IRQ_TYPE_EDGE_RISING>;
+
+			qcom,ipc = <&apcs 8 8>;
+			qcom,smd-edge = <1>;
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.txt	2017-02-12 16:03:20.000000000 -0500
@@ -60,8 +60,8 @@ on the Qualcomm WCNSS core.
 		    see ../reserved-memory/reserved-memory.txt
 
 = SUBNODES
-A single subnode of the WCNSS PIL describes the attached rf module and its
-resource dependencies.
+A required subnode of the WCNSS PIL is used to describe the attached rf module
+and its resource dependencies. It is described by the following properties:
 
 - compatible:
 	Usage: required
@@ -90,6 +90,11 @@ resource dependencies.
 	Definition: reference to the regulators to be held on behalf of the
 		    booting of the WCNSS core
 
+
+The wcnss node can also have an subnode named "smd-edge" that describes the SMD
+edge, channels and devices related to the WCNSS.
+See ../soc/qcom/qcom,smd.txt for details on how to describe the SMD edge.
+
 = EXAMPLE
 The following example describes the resources needed to boot control the WCNSS,
 with attached WCN3680, as it is commonly found on MSM8974 boards.
@@ -129,4 +134,25 @@ pronto@fb204000 {
 		vddpa-supply = <&pm8941_l19>;
 		vdddig-supply = <&pm8941_s3>;
 	};
+
+	smd-edge {
+		interrupts = <0 142 1>;
+
+		qcom,ipc = <&apcs 8 17>;
+		qcom,smd-edge = <6>;
+		qcom,remote-pid = <4>;
+
+		label = "pronto";
+
+		wcnss {
+			compatible = "qcom,wcnss";
+			qcom,smd-channels = "WCNSS_CTRL";
+
+			qcom,mmio = <&pronto>;
+
+			bt {
+				compatible = "qcom,wcnss-bt";
+			};
+		};
+	};
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/reserved-memory/ramoops.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reserved-memory/ramoops.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/reserved-memory/ramoops.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reserved-memory/ramoops.txt	2017-02-12 16:03:20.000000000 -0500
@@ -46,3 +46,6 @@ Optional properties:
   (defaults to buffered mappings)
 
 - no-dump-oops: if present, only dump panics (defaults to panics and oops)
+
+- flags: if present, pass ramoops behavioral flags (defaults to 0,
+  see include/linux/pstore_ram.h RAMOOPS_FLAG_* for flag values).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/oxnas,reset.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,45 +5,19 @@ Please also refer to reset.txt in this d
 controller binding usage.
 
 Required properties:
-- compatible: Should be "oxsemi,ox810se-reset"
+- compatible: For OX810SE, should be "oxsemi,ox810se-reset"
+	      For OX820, should be "oxsemi,ox820-reset"
 - #reset-cells: 1, see below
 
 Parent node should have the following properties :
-- compatible: Should be "oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+- compatible: For OX810SE, should be :
+			"oxsemi,ox810se-sys-ctrl", "syscon", "simple-mfd"
+	      For OX820, should be :
+			"oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd"
 
-For OX810SE, the indices are :
- - 0 : ARM
- - 1 : COPRO
- - 2 : Reserved
- - 3 : Reserved
- - 4 : USBHS
- - 5 : USBHSPHY
- - 6 : MAC
- - 7 : PCI
- - 8 : DMA
- - 9 : DPE
- - 10 : DDR
- - 11 : SATA
- - 12 : SATA_LINK
- - 13 : SATA_PHY
- - 14 : Reserved
- - 15 : NAND
- - 16 : GPIO
- - 17 : UART1
- - 18 : UART2
- - 19 : MISC
- - 20 : I2S
- - 21 : AHB_MON
- - 22 : UART3
- - 23 : UART4
- - 24 : SGDMA
- - 25 : Reserved
- - 26 : Reserved
- - 27 : Reserved
- - 28 : Reserved
- - 29 : Reserved
- - 30 : Reserved
- - 31 : BUS
+Reset indices are in dt-bindings include files :
+- For OX810SE: include/dt-bindings/reset/oxsemi,ox810se.h
+- For OX820: include/dt-bindings/reset/oxsemi,ox820.h
 
 example:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/renesas,rst.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/renesas,rst.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/renesas,rst.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/renesas,rst.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,37 @@
+DT bindings for the Renesas R-Car and RZ/G Reset Controllers
+
+The R-Car and RZ/G Reset Controllers provide reset control, and implement the
+following functions:
+  - Latching of the levels on mode pins when PRESET# is negated,
+  - Mode monitoring register,
+  - Reset control of peripheral devices (on R-Car Gen1),
+  - Watchdog timer (on R-Car Gen1),
+  - Register-based reset control and boot address registers for the various CPU
+    cores (on R-Car Gen2 and Gen3, and on RZ/G).
+
+
+Required properties:
+  - compatible: Should be
+		  - "renesas,<soctype>-reset-wdt" for R-Car Gen1,
+		  - "renesas,<soctype>-rst" for R-Car Gen2 and Gen3, and RZ/G
+		Examples with soctypes are:
+		  - "renesas,r8a7743-rst" (RZ/G1M)
+		  - "renesas,r8a7745-rst" (RZ/G1E)
+		  - "renesas,r8a7778-reset-wdt" (R-Car M1A)
+		  - "renesas,r8a7779-reset-wdt" (R-Car H1)
+		  - "renesas,r8a7790-rst" (R-Car H2)
+		  - "renesas,r8a7791-rst" (R-Car M2-W)
+		  - "renesas,r8a7792-rst" (R-Car V2H
+		  - "renesas,r8a7793-rst" (R-Car M2-N)
+		  - "renesas,r8a7794-rst" (R-Car E2)
+		  - "renesas,r8a7795-rst" (R-Car H3)
+		  - "renesas,r8a7796-rst" (R-Car M3-W)
+  - reg: Address start and address range for the device.
+
+
+Example:
+
+	rst: reset-controller@e6160000 {
+		compatible = "renesas,r8a7795-rst";
+		reg = <0 0xe6160000 0 0x0200>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt	2017-02-12 16:03:20.000000000 -0500
@@ -16,15 +16,14 @@ Please refer to reset.txt in this direct
 controller binding usage.
 
 Required properties:
-- compatible: Should be "st,<chip>-powerdown"
-	ex: "st,stih415-powerdown", "st,stih416-powerdown"
+- compatible: Should be "st,stih407-powerdown"
 - #reset-cells: 1, see below
 
 example:
 
 	powerdown: powerdown-controller {
+		compatible = "st,stih407-powerdown";
 		#reset-cells = <1>;
-		compatible = "st,stih415-powerdown";
 	};
 
 
@@ -37,11 +36,10 @@ index specifying which channel to use, a
 
 example:
 
-	usb1: usb@fe200000 {
-		resets	= <&powerdown STIH41X_USB1_POWERDOWN>;
+	st_dwc3: dwc3@8f94000 {
+		resets          = <&powerdown STIH407_USB3_POWERDOWN>,
 	};
 
 Macro definitions for the supported reset channels can be found in:
 
-include/dt-bindings/reset/stih415-resets.h
-include/dt-bindings/reset/stih416-resets.h
+include/dt-bindings/reset/stih407-resets.h
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/st,sti-softreset.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/st,sti-softreset.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/reset/st,sti-softreset.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/reset/st,sti-softreset.txt	2017-02-12 16:03:20.000000000 -0500
@@ -15,15 +15,14 @@ Please refer to reset.txt in this direct
 controller binding usage.
 
 Required properties:
-- compatible: Should be "st,<chip>-softreset" example:
-	"st,stih415-softreset" or "st,stih416-softreset";
+- compatible: Should be st,stih407-softreset";
 - #reset-cells: 1, see below
 
 example:
 
 	softreset: softreset-controller {
 		#reset-cells = <1>;
-		compatible = "st,stih415-softreset";
+		compatible = "st,stih407-softreset";
 	};
 
 
@@ -42,5 +41,4 @@ example:
 
 Macro definitions for the supported reset channels can be found in:
 
-include/dt-bindings/reset/stih415-resets.h
-include/dt-bindings/reset/stih416-resets.h
+include/dt-bindings/reset/stih407-resets.h
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/rng/omap_rng.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rng/omap_rng.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/rng/omap_rng.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rng/omap_rng.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-OMAP SoC HWRNG Module
+OMAP SoC and Inside-Secure HWRNG Module
 
 Required properties:
 
@@ -6,11 +6,13 @@ Required properties:
   RNG versions:
   - "ti,omap2-rng" for OMAP2.
   - "ti,omap4-rng" for OMAP4, OMAP5 and AM33XX.
+  - "inside-secure,safexcel-eip76" for SoCs with EIP76 IP block
   Note that these two versions are incompatible.
 - ti,hwmods: Name of the hwmod associated with the RNG module
 - reg : Offset and length of the register set for the module
 - interrupts : the interrupt number for the RNG module.
-		Only used for "ti,omap4-rng".
+		Used for "ti,omap4-rng" and "inside-secure,safexcel-eip76"
+- clocks: the trng clock source
 
 Example:
 /* AM335x */
@@ -20,3 +22,11 @@ rng: rng@48310000 {
 	reg = <0x48310000 0x2000>;
 	interrupts = <111>;
 };
+
+/* SafeXcel IP-76 */
+trng: rng@f2760000 {
+	compatible = "inside-secure,safexcel-eip76";
+	reg = <0xf2760000 0x7d>;
+	interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&cpm_syscon0 1 25>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/epson,rtc7301.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/epson,rtc7301.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/epson,rtc7301.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/epson,rtc7301.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,16 @@
+EPSON TOYOCOM RTC-7301SF/DG
+
+Required properties:
+
+- compatible: Should be "epson,rtc7301sf" or "epson,rtc7301dg"
+- reg: Specifies base physical address and size of the registers.
+- interrupts: A single interrupt specifier.
+
+Example:
+
+rtc: rtc@44a00000 {
+	compatible = "epson,rtc7301dg";
+	reg = <0x44a00000 0x10000>;
+	interrupt-parent = <&axi_intc_0>;
+	interrupts = <3 2>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/ingenic,jz4740-rtc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,37 @@
+JZ4740 and similar SoCs real-time clock driver
+
+Required properties:
+
+- compatible: One of:
+  - "ingenic,jz4740-rtc" - for use with the JZ4740 SoC
+  - "ingenic,jz4780-rtc" - for use with the JZ4780 SoC
+- reg: Address range of rtc register set
+- interrupts: IRQ number for the alarm interrupt
+- clocks: phandle to the "rtc" clock
+- clock-names: must be "rtc"
+
+Optional properties:
+- system-power-controller: To use this component as the
+  system power controller
+- reset-pin-assert-time-ms: Reset pin low-level assertion
+  time after wakeup (default 60ms; range 0-125ms if RTC clock
+  at 32 kHz)
+- min-wakeup-pin-assert-time-ms: Minimum wakeup pin assertion
+  time (default 100ms; range 0-2s if RTC clock at 32 kHz)
+
+Example:
+
+rtc@10003000 {
+	compatible = "ingenic,jz4740-rtc";
+	reg = <0x10003000 0x40>;
+
+	interrupt-parent = <&intc>;
+	interrupts = <32>;
+
+	clocks = <&rtc_clock>;
+	clock-names = "rtc";
+
+	system-power-controller;
+	reset-pin-assert-time-ms = <60>;
+	min-wakeup-pin-assert-time-ms = <100>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/maxim,ds3231.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 * Maxim DS3231 Real Time Clock
 
 Required properties:
-see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst
 
 Optional property:
 - #clock-cells: Should be 1.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/pcf8563.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/pcf8563.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/pcf8563.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/pcf8563.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
 Philips PCF8563/Epson RTC8564 Real Time Clock
 
 Required properties:
-see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
+see: Documentation/devicetree/bindings/i2c/trivial-admin-guide/devices.rst
 
 Optional property:
 - #clock-cells: Should be 0.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/twl-rtc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/twl-rtc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/rtc/twl-rtc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/rtc/twl-rtc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,12 +1,11 @@
-* TI twl RTC
-
-The TWL family (twl4030/6030) contains a RTC.
+* Texas Instruments TWL4030/6030 RTC
 
 Required properties:
-- compatible : Should be twl4030-rtc
-
-Examples:
+- compatible : Should be "ti,twl4030-rtc"
+- interrupts : Should be the interrupt number.
 
-rtc@0 {
-    compatible = "ti,twl4030-rtc";
-};
+Example:
+	rtc {
+		compatible = "ti,twl4030-rtc";
+		interrupts = <11>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,7 @@ Main node required properties:
   - compatible : value should be as follows:
 	(a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset
 	(b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset
+	(c) "hisilicon,hip07-sas-v2" for v2 hw in hip07 chipset
   - sas-addr : array of 8 bytes for host SAS address
   - reg : Address and length of the SAS register
   - hisilicon,sas-syscon: phandle of syscon used for sas control
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/security/tpm/ibmvtpm.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/security/tpm/ibmvtpm.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/security/tpm/ibmvtpm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/security/tpm/ibmvtpm.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+* Device Tree Bindings for IBM Virtual Trusted Platform Module(vtpm)
+
+Required properties:
+
+- compatible            : property name that conveys the platform architecture
+                          identifiers, as 'IBM,vtpm'
+- device_type           : specifies type of virtual device
+- interrupts            : property specifying the interrupt source number and
+                          sense code associated with this virtual I/O Adapters
+- ibm,my-drc-index      : integer index for the connector between the device
+                          and its parent - present only if Dynamic
+                          Reconfiguration(DR) Connector is enabled
+- ibm,#dma-address-cells: specifies the number of cells that are used to
+                          encode the physical address field of dma-window
+                          properties
+- ibm,#dma-size-cells   : specifies the number of cells that are used to
+                          encode the size field of dma-window properties
+- ibm,my-dma-window     : specifies DMA window associated with this virtual
+                          IOA
+- ibm,loc-code          : specifies the unique and persistent location code
+                          associated with this virtual I/O Adapters
+- linux,sml-base        : 64-bit base address of the reserved memory allocated
+                          for the firmware event log
+- linux,sml-size        : size of the memory allocated for the firmware event log
+
+Example (IBM Virtual Trusted Platform Module)
+---------------------------------------------
+
+                vtpm@30000003 {
+                        ibm,#dma-size-cells = <0x2>;
+                        compatible = "IBM,vtpm";
+                        device_type = "IBM,vtpm";
+                        ibm,my-drc-index = <0x30000003>;
+                        ibm,#dma-address-cells = <0x2>;
+                        linux,sml-base = <0xc60e 0x0>;
+                        interrupts = <0xa0003 0x0>;
+                        ibm,my-dma-window = <0x10000003 0x0 0x0 0x0 0x10000000>;
+                        ibm,loc-code = "U8286.41A.10082DV-V3-C3";
+                        reg = <0x30000003>;
+                        linux,sml-size = <0xbce10200>;
+                };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/security/tpm/tpm-i2c.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/security/tpm/tpm-i2c.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/security/tpm/tpm-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/security/tpm/tpm-i2c.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,21 @@
+* Device Tree Bindings for I2C based Trusted Platform Module(TPM)
+
+Required properties:
+
+- compatible     : 'manufacturer,model', eg. nuvoton,npct650
+- label          : human readable string describing the device, eg. "tpm"
+- linux,sml-base : 64-bit base address of the reserved memory allocated for
+                   the firmware event log
+- linux,sml-size : size of the memory allocated for the firmware event log
+
+Example (for OpenPower Systems with Nuvoton TPM 2.0 on I2C)
+----------------------------------------------------------
+
+tpm@57 {
+	reg = <0x57>;
+	label = "tpm";
+	compatible = "nuvoton,npct650", "nuvoton,npct601";
+	linux,sml-base = <0x7f 0xfd450000>;
+	linux,sml-size = <0x10000>;
+	status = "okay";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,25 @@
+Trusted Computing Group MMIO Trusted Platform Module
+
+The TCG defines multi vendor standard for accessing a TPM chip, this
+is the standard protocol defined to access the TPM via MMIO. Typically
+this interface will be implemented over Intel's LPC bus.
+
+Refer to the 'TCG PC Client Specific TPM Interface Specification (TIS)' TCG
+publication for the specification.
+
+Required properties:
+
+- compatible: should contain a string below for the chip, followed by
+              "tcg,tpm-tis-mmio". Valid chip strings are:
+	          * "atmel,at97sc3204"
+- reg: The location of the MMIO registers, should be at least 0x5000 bytes
+- interrupt-parent/interrupts: An optional interrupt indicating command completion.
+
+Example:
+
+	tpm_tis@90000 {
+				compatible = "atmel,at97sc3204", "tcg,tpm-tis-mmio";
+				reg = <0x90000 0x5000>;
+				interrupt-parent = <&EIC0>;
+				interrupts = <1 2>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/serial/nvidia,tegra20-hsuart.txt	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@ Required properties:
   See ../reset/reset.txt for details.
 - reset-names : Must include the following entries:
   - serial
-- dmas : Must contain an entry for each entry in clock-names.
+- dmas : Must contain an entry for each entry in dma-names.
   See ../dma/dma.txt for details.
 - dma-names : Must include the following entries:
   - rx
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/soc/fsl/guts.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/soc/fsl/guts.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/soc/fsl/guts.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/soc/fsl/guts.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,44 @@
+* Global Utilities Block
+
+The global utilities block controls power management, I/O device
+enabling, power-on-reset configuration monitoring, general-purpose
+I/O signal configuration, alternate function selection for multiplexed
+signals, and clock control.
+
+Required properties:
+
+ - compatible : Should define the compatible device type for
+   global-utilities.
+   Possible compatibles:
+	"fsl,qoriq-device-config-1.0"
+	"fsl,qoriq-device-config-2.0"
+	"fsl,<chip>-device-config"
+	"fsl,<chip>-guts"
+ - reg : Offset and length of the register set for the device.
+
+Recommended properties:
+
+ - fsl,has-rstcr : Indicates that the global utilities register set
+   contains a functioning "reset control register" (i.e. the board
+   is wired to reset upon setting the HRESET_REQ bit in this register).
+
+ - fsl,liodn-bits : Indicates the number of defined bits in the LIODN
+   registers, for those SOCs that have a PAMU device.
+
+ - little-endian : Indicates that the global utilities block is little
+   endian. The default is big endian.
+
+Examples:
+	global-utilities@e0000 {	/* global utilities block */
+		compatible = "fsl,mpc8548-guts";
+		reg = <e0000 1000>;
+		fsl,has-rstcr;
+	};
+
+	guts: global-utilities@e0000 {
+		compatible = "fsl,qoriq-device-config-1.0";
+		reg = <0xe0000 0xe00>;
+		fsl,has-rstcr;
+		#sleep-cells = <1>;
+		fsl,liodn-bits = <12>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/soc/mediatek/scpsys.txt	2017-02-12 16:03:20.000000000 -0500
@@ -9,17 +9,20 @@ domain control.
 
 The driver implements the Generic PM domain bindings described in
 power/power_domain.txt. It provides the power domains defined in
-include/dt-bindings/power/mt8173-power.h.
+include/dt-bindings/power/mt8173-power.h and mt2701-power.h.
 
 Required properties:
-- compatible: Must be "mediatek,mt8173-scpsys"
+- compatible: Should be one of:
+	- "mediatek,mt2701-scpsys"
+	- "mediatek,mt8173-scpsys"
 - #power-domain-cells: Must be 1
 - reg: Address range of the SCPSYS unit
 - infracfg: must contain a phandle to the infracfg controller
 - clock, clock-names: clocks according to the common clock binding.
-                      The clocks needed "mm", "mfg", "venc" and "venc_lt".
-		      These are the clocks which hardware needs to be enabled
-		      before enabling certain power domains.
+                      These are clocks which hardware needs to be
+                      enabled before enabling certain power domains.
+	Required clocks for MT2701: "mm", "mfg", "ethif"
+	Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
 
 Optional properties:
 - vdec-supply: Power supply for the vdec power domain
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,13 @@ The edge is described by the following p
 	Definition: the identifier for the remote processor as known by the rest
 		    of the system.
 
+- label:
+	Usage: optional
+	Value type: <string>
+	Definition: name of the edge, used for debugging and identification
+		    purposes. The node name will be used if this is not
+		    present.
+
 = SMD DEVICES
 
 In turn, subnodes of the "edges" represent devices tied to SMD channels on that
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/axentia,tse850-pcm5142.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,88 @@
+Devicetree bindings for the Axentia TSE-850 audio complex
+
+Required properties:
+  - compatible: "axentia,tse850-pcm5142"
+  - axentia,ssc-controller: The phandle of the atmel SSC controller used as
+    cpu dai.
+  - axentia,audio-codec: The phandle of the PCM5142 codec.
+  - axentia,add-gpios: gpio specifier that controls the mixer.
+  - axentia,loop1-gpios: gpio specifier that controls loop relays on channel 1.
+  - axentia,loop2-gpios: gpio specifier that controls loop relays on channel 2.
+  - axentia,ana-supply: Regulator that supplies the output amplifier. Must
+    support voltages in the 2V - 20V range, in 1V steps.
+
+The schematics explaining the gpios are as follows:
+
+               loop1 relays
+   IN1 +---o  +------------+  o---+ OUT1
+            \                /
+             +              +
+             |   /          |
+             +--o  +--.     |
+             |  add   |     |
+             |        V     |
+             |      .---.   |
+   DAC +----------->|Sum|---+
+             |      '---'   |
+             |              |
+             +              +
+
+   IN2 +---o--+------------+--o---+ OUT2
+               loop2 relays
+
+The 'loop1' gpio pin controlls two relays, which are either in loop position,
+meaning that input and output are directly connected, or they are in mixer
+position, meaning that the signal is passed through the 'Sum' mixer. Similarly
+for 'loop2'.
+
+In the above, the 'loop1' relays are inactive, thus feeding IN1 to the mixer
+(if 'add' is active) and feeding the mixer output to OUT1. The 'loop2' relays
+are active, short-cutting the TSE-850 from channel 2. IN1, IN2, OUT1 and OUT2
+are TSE-850 connectors and DAC is the PCB name of the (filtered) output from
+the PCM5142 codec.
+
+Example:
+
+	&i2c {
+		codec: pcm5142@4c {
+			compatible = "ti,pcm5142";
+
+			reg = <0x4c>;
+
+			AVDD-supply = <&reg_3v3>;
+			DVDD-supply = <&reg_3v3>;
+			CPVDD-supply = <&reg_3v3>;
+
+			clocks = <&sck>;
+
+			pll-in = <3>;
+			pll-out = <6>;
+		};
+	};
+
+	ana: ana-reg {
+		compatible = "pwm-regulator";
+
+		regulator-name = "ANA";
+
+		pwms = <&pwm0 2 1000 PWM_POLARITY_INVERTED>;
+		pwm-dutycycle-unit = <1000>;
+		pwm-dutycycle-range = <100 1000>;
+
+		regulator-min-microvolt = <2000000>;
+		regulator-max-microvolt = <20000000>;
+		regulator-ramp-delay = <1000>;
+	};
+
+	sound {
+		compatible = "axentia,tse850-pcm5142";
+
+		axentia,ssc-controller = <&ssc0>;
+		axentia,audio-codec = <&codec>;
+
+		axentia,add-gpios = <&pioA 8 GPIO_ACTIVE_LOW>;
+		axentia,loop1-gpios = <&pioA 10 GPIO_ACTIVE_LOW>;
+		axentia,loop2-gpios = <&pioA 11 GPIO_ACTIVE_LOW>;
+
+		axentia,ana-supply = <&ana>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/cs35l34.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/cs35l34.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/cs35l34.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/cs35l34.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+CS35L34 Speaker Amplifier
+
+Required properties:
+
+  - compatible : "cirrus,cs35l34"
+
+  - reg : the I2C address of the device for I2C.
+
+  - VA-supply, VP-supply : power supplies for the device,
+    as covered in
+    Documentation/devicetree/bindings/regulator/regulator.txt.
+
+  - cirrus,boost-vtge-millivolt : Boost Voltage Value.  Configures the boost
+    converter's output voltage in mV. The range is from VP to 8V with
+    increments of 100mV.
+
+  - cirrus,boost-nanohenry: Inductor value for boost converter. The value is
+    in nH and they can be values of 1000nH, 1100nH, 1200nH, 1500nH, and 2200nH.
+
+Optional properties:
+
+  - reset-gpios: GPIO used to reset the amplifier.
+
+  - interrupt-parent : Specifies the phandle of the interrupt controller to
+    which the IRQs from CS35L34 are delivered to.
+  - interrupts : IRQ line info CS35L34.
+    (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+    for further information relating to interrupt properties)
+
+  - cirrus,boost-peak-milliamp : Boost converter peak current limit in mA. The
+    range starts at 1200mA and goes to a maximum of 3840mA with increments of
+    80mA. The default value is 2480mA.
+
+  - cirrus,i2s-sdinloc : ADSP SDIN I2S channel location. Indicates whether the
+    received mono data is in the left or right portion of the I2S frame
+    according to the AD0 pin or directly via this configuration.
+    0x0 (Default) = Selected by AD0 input (if AD0 = LOW, use left channel),
+    0x2 = Left,
+    0x1 = Selected by the inversion of the AD0 input (if AD0 = LOW, use right
+    channel),
+    0x3 = Right.
+
+  - cirrus,gain-zc-disable: Boolean property. If set, the gain change will take
+    effect without waiting for a zero cross.
+
+  - cirrus,tdm-rising-edge: Boolean property. If set, data is on the rising edge of
+    SCLK. Otherwise, data is on the falling edge of SCLK.
+
+
+Example:
+
+cs35l34: cs35l34@40 {
+	compatible = "cirrus,cs35l34";
+	reg = <0x40>;
+
+	interrupt-parent = <&gpio8>;
+	interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+
+	reset-gpios = <&gpio 10 0>;
+
+	cirrus,boost-vtge-milltvolt = <8000>; /* 8V */
+	cirrus,boost-ind-nanohenry = <1000>; /* 1uH */
+	cirrus,boost-peak-milliamp = <3000>; /* 3A */
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/cs42l42.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/cs42l42.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/cs42l42.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/cs42l42.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,110 @@
+CS42L42 audio CODEC
+
+Required properties:
+
+  - compatible : "cirrus,cs42l42"
+
+  - reg : the I2C address of the device for I2C.
+
+  - VP-supply, VCP-supply, VD_FILT-supply, VL-supply, VA-supply :
+  power supplies for the device, as covered in
+  Documentation/devicetree/bindings/regulator/regulator.txt.
+
+Optional properties:
+
+  - reset-gpios : a GPIO spec for the reset pin. If specified, it will be
+  deasserted before communication to the codec starts.
+
+  - interrupt-parent : Specifies the phandle of the interrupt controller to
+  which the IRQs from CS42L42 are delivered to.
+
+  - interrupts : IRQ line info CS42L42.
+  (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+  for further information relating to interrupt properties)
+
+  - cirrus,ts-inv : Boolean property. For jacks that invert the tip sense
+  polarity. Normal jacks will short tip sense pin to HS1 when headphones are
+  plugged in and leave tip sense floating when not plugged in. Inverting jacks
+  short tip sense when unplugged and float when plugged in.
+
+  0 = (Default) Non-inverted
+  1 = Inverted
+
+  - cirrus,ts-dbnc-rise : Debounce the rising edge of TIP_SENSE_PLUG. With no
+  debounce, the tip sense pin might be noisy on a plug event.
+
+  0 - 0ms,
+  1 - 125ms,
+  2 - 250ms,
+  3 - 500ms,
+  4 - 750ms,
+  5 - (Default) 1s,
+  6 - 1.25s,
+  7 - 1.5s,
+
+  - cirrus,ts-dbnc-fall : Debounce the falling edge of TIP_SENSE_UNPLUG.
+  With no debounce, the tip sense pin might be noisy on an unplug event.
+
+  0 - 0ms,
+  1 - 125ms,
+  2 - 250ms,
+  3 - 500ms,
+  4 - 750ms,
+  5 - (Default) 1s,
+  6 - 1.25s,
+  7 - 1.5s,
+
+  - cirrus,btn-det-init-dbnce : This sets how long the driver sleeps after
+  enabling button detection interrupts. After auto-detection and before
+  servicing button interrupts, the HS bias needs time to settle. If you
+  don't wait, there is possibility for erroneous button interrupt.
+
+  0ms - 200ms,
+  Default = 100ms
+
+  - cirrus,btn-det-event-dbnce : This sets how long the driver delays after
+  receiving a button press interrupt. With level detect interrupts, you want
+  to wait a small amount of time to make sure the button press is making a
+  clean connection with the bias resistors.
+
+  0ms - 20ms,
+  Default = 10ms
+
+  - cirrus,bias-lvls : For a level-detect headset button scheme, each button
+  will bias the mic pin to a certain voltage. To determine which button was
+  pressed, the driver will compare this biased voltage to sequential,
+  decreasing voltages and will stop when a comparator is tripped,
+  indicating a comparator voltage < bias voltage. This value represents a
+  percentage of the internally generated HS bias voltage. For different
+  hardware setups, a designer might want to tweak this. This is an array of
+  descending values for the comparator voltage.
+
+  Array of 4 values
+  Each 0-63
+  < x1 x2 x3 x4 >
+  Default = < 15 8 4 1>
+
+
+Example:
+
+cs42l42: cs42l42@48 {
+	compatible = "cirrus,cs42l42";
+	reg = <0x48>;
+	VA-supply = <&dummy_vreg>;
+	VP-supply = <&dummy_vreg>;
+	VCP-supply = <&dummy_vreg>;
+	VD_FILT-supply = <&dummy_vreg>;
+	VL-supply = <&dummy_vreg>;
+
+	reset-gpios = <&axi_gpio_0 1 0>;
+	interrupt-parent = <&gpio0>;
+	interrupts = <55 8>
+
+	cirrus,ts-inv = <0x00>;
+	cirrus,ts-dbnc-rise = <0x05>;
+	cirrus,ts-dbnc-fall = <0x00>;
+	cirrus,btn-det-init-dbnce = <100>;
+	cirrus,btn-det-event-dbnce = <10>;
+	cirrus,bias-lvls = <0x0F 0x08 0x04 0x01>;
+	cirrus,hs-bias-ramp-rate = <0x02>;
+};
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@ mcbsp0: mcbsp@1d10000 {
 		<0x00310000 0x1000>;
 	reg-names = "mpu", "dat";
 	interrupts = <97 98>;
-	interrupts-names = "rx", "tx";
+	interrupt-names = "rx", "tx";
 	dmas = <&edma0 3 1
 		&edma0 2 1>;
 	dma-names = "tx", "rx";
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/qcom,apq8016-sbc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -44,8 +44,7 @@ Required dai-link subnodes:
 Required CPU/CODEC subnodes properties:
 
 -link-name		: Name of the dai link.
--sound-dai		: phandle and port of CPU/CODEC
--capture-dai		: phandle and port of CPU/CODEC
+-sound-dai		: phandle/s and port of CPU/CODEC
 
 Example:
 
@@ -73,7 +72,7 @@ sound: sound {
 			sound-dai = <&lpass MI2S_PRIMARY>;
 		};
 		codec {
-			sound-dai = <&wcd_codec 0>;
+			sound-dai = <&lpass_codec 0>, <&wcd_codec 0>;
 		};
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-analog.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,85 @@
+msm8916 analog audio CODEC
+
+Bindings for codec Analog IP which is integrated in pmic pm8916,
+
+## Bindings for codec core on pmic:
+
+Required properties
+ - compatible = "qcom,pm8916-wcd-analog-codec";
+ - reg: represents the slave base address provided to the peripheral.
+ - interrupt-parent : The parent interrupt controller.
+ - interrupts: List of interrupts in given SPMI peripheral.
+ - interrupt-names: Names specified to above list of interrupts in same
+		    order. List of supported interrupt names are:
+  "cdc_spk_cnp_int" - Speaker click and pop interrupt.
+  "cdc_spk_clip_int" - Speaker clip interrupt.
+  "cdc_spk_ocp_int" - Speaker over current protect interrupt.
+  "mbhc_ins_rem_det1" - jack insert removal detect interrupt 1.
+  "mbhc_but_rel_det" - button release interrupt.
+  "mbhc_but_press_det" - button press event
+  "mbhc_ins_rem_det" - jack insert removal detect interrupt.
+  "mbhc_switch_int"	- multi button headset interrupt.
+  "cdc_ear_ocp_int" - Earphone over current protect interrupt.
+  "cdc_hphr_ocp_int" - Headphone R over current protect interrupt.
+  "cdc_hphl_ocp_det" - Headphone L over current protect interrupt.
+  "cdc_ear_cnp_int" - earphone cnp interrupt.
+  "cdc_hphr_cnp_int" - hphr click and pop interrupt.
+  "cdc_hphl_cnp_int" - hphl click and pop interrupt.
+
+ - clocks: Handle to mclk.
+ - clock-names: should be "mclk"
+ - vdd-cdc-io-supply: phandle to VDD_CDC_IO regulator DT node.
+ - vdd-cdc-tx-rx-cx-supply: phandle to VDD_CDC_TX/RX/CX regulator DT node.
+ - vdd-micbias-supply: phandle of VDD_MICBIAS supply's regulator DT node.
+
+Optional Properties:
+- qcom,micbias1-ext-cap: boolean, present if micbias1 has external capacitor
+			 connected.
+- qcom,micbias2-ext-cap: boolean, present if micbias2 has external capacitor
+			 connected.
+
+Example:
+
+spmi_bus {
+	...
+	audio-codec@f000{
+		compatible = "qcom,pm8916-wcd-analog-codec";
+		reg = <0xf000 0x200>;
+		reg-names = "pmic-codec-core";
+		clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
+		clock-names = "mclk";
+		interrupt-parent = <&spmi_bus>;
+		interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+			     <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+			     <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+			     <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+			     <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+			     <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+			     <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+			     <0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+			     <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+			     <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+			     <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+			     <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+			     <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+			     <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+		interrupt-names = "cdc_spk_cnp_int",
+				  "cdc_spk_clip_int",
+				  "cdc_spk_ocp_int",
+				  "mbhc_ins_rem_det1",
+				  "mbhc_but_rel_det",
+				  "mbhc_but_press_det",
+				  "mbhc_ins_rem_det",
+				  "mbhc_switch_int",
+				  "cdc_ear_ocp_int",
+				  "cdc_hphr_ocp_int",
+				  "cdc_hphl_ocp_det",
+				  "cdc_ear_cnp_int",
+				  "cdc_hphr_cnp_int",
+				  "cdc_hphl_cnp_int";
+	               VDD-CDC-IO-supply = <&pm8916_l5>;
+	               VDD-CDC-TX-RX-CX-supply = <&pm8916_l5>;
+	               VDD-MICBIAS-supply = <&pm8916_l13>;
+	               #sound-dai-cells = <1>;
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/qcom,msm8916-wcd-digital.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+msm8916 digital audio CODEC
+
+## Bindings for codec core in lpass:
+
+Required properties
+ - compatible = "qcom,msm8916-wcd-digital-codec";
+ - reg: address space for lpass codec.
+ - clocks: Handle to mclk and ahbclk
+ - clock-names: should be "mclk", "ahbix-clk".
+
+Example:
+
+audio-codec@771c000{
+	compatible = "qcom,msm8916-wcd-digital-codec";
+	reg = <0x0771c000 0x400>;
+	clocks = <&gcc GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK>,
+		 <&gcc GCC_CODEC_DIGCODEC_CLK>;
+	clock-names = "ahbix-clk", "mclk";
+	#sound-dai-cells = <1>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/rt5514.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/rt5514.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/rt5514.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/rt5514.txt	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,9 @@ Optional properties:
 - clocks: The phandle of the master clock to the CODEC
 - clock-names: Should be "mclk"
 
+- realtek,dmic-init-delay-ms
+  Set the DMIC initial delay (ms) to wait it ready.
+
 Pins on the device (for linking into audio routes) for RT5514:
 
   * DMIC1L
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/rt5663.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/rt5663.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/rt5663.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/rt5663.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,10 +1,10 @@
-RT5663/RT5668 audio CODEC
+RT5663 audio CODEC
 
 This device supports I2C only.
 
 Required properties:
 
-- compatible : One of "realtek,rt5663" or "realtek,rt5668".
+- compatible : "realtek,rt5663".
 
 - reg : The I2C address of the device.
 
@@ -12,7 +12,7 @@ Required properties:
 
 Optional properties:
 
-Pins on the device (for linking into audio routes) for RT5663/RT5668:
+Pins on the device (for linking into audio routes) for RT5663:
 
   * IN1P
   * IN1N
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/rt5665.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/rt5665.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/rt5665.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/rt5665.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,68 @@
+RT5665/RT5666/RT5668 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+- compatible : One of "realtek,rt5665", "realtek,rt5666" or "realtek,rt5668".
+
+- reg : The I2C address of the device.
+
+- interrupts : The CODEC's interrupt output.
+
+Optional properties:
+
+- realtek,in1-differential
+- realtek,in2-differential
+- realtek,in3-differential
+- realtek,in4-differential
+  Boolean. Indicate MIC1/2/3/4 input are differential, rather than single-ended.
+
+- realtek,dmic1-data-pin
+  0: dmic1 is not used
+  1: using GPIO4 pin as dmic1 data pin
+  2: using IN2N pin as dmic2 data pin
+
+- realtek,dmic2-data-pin
+  0: dmic2 is not used
+  1: using GPIO5 pin as dmic2 data pin
+  2: using IN2P pin as dmic2 data pin
+
+- realtek,jd-src
+  0: No JD is used
+  1: using JD1 as JD source
+
+- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
+
+Pins on the device (for linking into audio routes) for RT5659/RT5658:
+
+  * DMIC L1
+  * DMIC R1
+  * DMIC L2
+  * DMIC R2
+  * IN1P
+  * IN1N
+  * IN2P
+  * IN2N
+  * IN3P
+  * IN3N
+  * IN4P
+  * IN4N
+  * HPOL
+  * HPOR
+  * LOUTL
+  * LOUTR
+  * MONOOUT
+  * PDML
+  * PDMR
+
+Example:
+
+rt5659 {
+	compatible = "realtek,rt5665";
+	reg = <0x1b>;
+	interrupt-parent = <&gpio>;
+	interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
+	realtek,ldo1-en-gpios =
+		<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/samsung,tm2-audio.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+Samsung Exynos5433 TM2(E) audio complex with WM5110 codec
+
+Required properties:
+
+ - compatible		 : "samsung,tm2-audio"
+ - model		 : the user-visible name of this sound complex
+ - audio-codec		 : the phandle of the wm5110 audio codec node,
+			   as described in ../mfd/arizona.txt
+ - i2s-controller	 : the phandle of the I2S controller
+ - audio-amplifier	 : the phandle of the MAX98504 amplifier
+ - samsung,audio-routing : a list of the connections between audio components;
+			   each entry is a pair of strings, the first being the
+			   connection's sink, the second being the connection's
+			   source; valid names for sources and sinks are the
+			   WM5110's and MAX98504's pins and the jacks on the
+			   board: HP, SPK, Main Mic, Sub Mic, Third Mic,
+			   Headset Mic
+ - mic-bias-gpios	 : GPIO pin that enables the Main Mic bias regulator
+
+
+Example:
+
+sound {
+	compatible = "samsung,tm2-audio";
+	audio-codec = <&wm5110>;
+	i2s-controller = <&i2s0>;
+	audio-amplifier = <&max98504>;
+	mic-bias-gpios = <&gpr3 2 0>;
+	model = "wm5110";
+	samsung,audio-routing =
+		"HP", "HPOUT1L",
+		"HP", "HPOUT1R",
+		"SPK", "SPKOUT",
+		"SPKOUT", "HPOUT2L",
+		"SPKOUT", "HPOUT2R",
+		"Main Mic", "MICBIAS2",
+		"IN1R", "Main Mic";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/sun4i-codec.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/sun4i-codec.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/sun4i-codec.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/sun4i-codec.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,8 +1,12 @@
 * Allwinner A10 Codec
 
 Required properties:
-- compatible: must be either "allwinner,sun4i-a10-codec" or
-  "allwinner,sun7i-a20-codec"
+- compatible: must be one of the following compatibles:
+		- "allwinner,sun4i-a10-codec"
+		- "allwinner,sun6i-a31-codec"
+		- "allwinner,sun7i-a20-codec"
+		- "allwinner,sun8i-a23-codec"
+		- "allwinner,sun8i-h3-codec"
 - reg: must contain the registers location and length
 - interrupts: must contain the codec interrupt
 - dmas: DMA channels for tx and rx dma. See the DMA client binding,
@@ -17,6 +21,43 @@ Required properties:
 Optional properties:
 - allwinner,pa-gpios: gpio to enable external amplifier
 
+Required properties for the following compatibles:
+		- "allwinner,sun6i-a31-codec"
+		- "allwinner,sun8i-a23-codec"
+		- "allwinner,sun8i-h3-codec"
+- resets: phandle to the reset control for this device
+- allwinner,audio-routing: A list of the connections between audio components.
+			   Each entry is a pair of strings, the first being the
+			   connection's sink, the second being the connection's
+			   source. Valid names include:
+
+			   Audio pins on the SoC:
+			   "HP"
+			   "HPCOM"
+			   "LINEIN"
+			   "LINEOUT"	(not on sun8i-a23)
+			   "MIC1"
+			   "MIC2"
+			   "MIC3"	(sun6i-a31 only)
+
+			   Microphone biases from the SoC:
+			   "HBIAS"
+			   "MBIAS"
+
+			   Board connectors:
+			   "Headphone"
+			   "Headset Mic"
+			   "Line In"
+			   "Line Out"
+			   "Mic"
+			   "Speaker"
+
+Required properties for the following compatibles:
+		- "allwinner,sun8i-a23-codec"
+		- "allwinner,sun8i-h3-codec"
+- allwinner,codec-analog-controls: A phandle to the codec analog controls
+				   block in the PRCM.
+
 Example:
 codec: codec@01c22c00 {
 	#sound-dai-cells = <0>;
@@ -28,3 +69,23 @@ codec: codec@01c22c00 {
 	dmas = <&dma 0 19>, <&dma 0 19>;
 	dma-names = "rx", "tx";
 };
+
+codec: codec@01c22c00 {
+	#sound-dai-cells = <0>;
+	compatible = "allwinner,sun6i-a31-codec";
+	reg = <0x01c22c00 0x98>;
+	interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&ccu CLK_APB1_CODEC>, <&ccu CLK_CODEC>;
+	clock-names = "apb", "codec";
+	resets = <&ccu RST_APB1_CODEC>;
+	dmas = <&dma 15>, <&dma 15>;
+	dma-names = "rx", "tx";
+	allwinner,audio-routing =
+		"Headphone", "HP",
+		"Speaker", "LINEOUT",
+		"LINEIN", "Line In",
+		"MIC1",	"MBIAS",
+		"MIC1", "Mic",
+		"MIC2", "HBIAS",
+		"MIC2", "Headset Mic";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,16 @@
+* Allwinner Codec Analog Controls
+
+Required properties:
+- compatible: must be one of the following compatibles:
+		- "allwinner,sun8i-a23-codec-analog"
+		- "allwinner,sun8i-h3-codec-analog"
+
+Required properties if not a sub-node of the PRCM node:
+- reg: must contain the registers location and length
+
+Example:
+prcm: prcm@01f01400 {
+	codec_analog: codec-analog {
+		compatible = "allwinner,sun8i-a23-codec-analog";
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/tlv320aic31xx.txt	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@ Required properties:
     "ti,tlv320aic3120" - TLV320AIC3120 (mono speaker amp, MiniDSP)
     "ti,tlv320aic3111" - TLV320AIC3111 (stereo speaker amp, MiniDSP)
     "ti,tlv320dac3100" - TLV320DAC3100 (no ADC, mono speaker amp, no MiniDSP)
+    "ti,tlv320dac3101" - TLV320DAC3101 (no ADC, stereo speaker amp, no MiniDSP)
 
 - reg - <int> -  I2C slave address
 - HPVDD-supply, SPRVDD-supply, SPLVDD-supply, AVDD-supply, IOVDD-supply,
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/wm8580.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/wm8580.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sound/wm8580.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sound/wm8580.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,10 +1,10 @@
-WM8580 audio CODEC
+WM8580 and WM8581 audio CODEC
 
 This device supports I2C only.
 
 Required properties:
 
-  - compatible : "wlf,wm8580"
+  - compatible : "wlf,wm8580", "wlf,wm8581"
 
   - reg : the I2C address of the device.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/sh-msiof.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/sh-msiof.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/sh-msiof.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/sh-msiof.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,16 +1,23 @@
 Renesas MSIOF spi controller
 
 Required properties:
-- compatible           : "renesas,msiof-<soctype>" for SoCs,
-			 "renesas,sh-msiof" for SuperH, or
-			 "renesas,sh-mobile-msiof" for SH Mobile series.
-			 Examples with soctypes are:
-			 "renesas,msiof-r8a7790" (R-Car H2)
+- compatible           : "renesas,msiof-r8a7790" (R-Car H2)
 			 "renesas,msiof-r8a7791" (R-Car M2-W)
 			 "renesas,msiof-r8a7792" (R-Car V2H)
 			 "renesas,msiof-r8a7793" (R-Car M2-N)
 			 "renesas,msiof-r8a7794" (R-Car E2)
+			 "renesas,msiof-r8a7796" (R-Car M3-W)
 			 "renesas,msiof-sh73a0" (SH-Mobile AG5)
+			 "renesas,sh-mobile-msiof" (generic SH-Mobile compatibile device)
+			 "renesas,rcar-gen2-msiof" (generic R-Car Gen2 compatible device)
+			 "renesas,rcar-gen3-msiof" (generic R-Car Gen3 compatible device)
+			 "renesas,sh-msiof"      (deprecated)
+
+			 When compatible with the generic version, nodes
+			 must list the SoC-specific version corresponding
+			 to the platform first followed by the generic
+			 version.
+
 - reg                  : A list of offsets and lengths of the register sets for
 			 the device.
 			 If only one register set is present, it is to be used
@@ -60,7 +67,8 @@ Documentation/devicetree/bindings/pinctr
 Example:
 
 	msiof0: spi@e6e20000 {
-		compatible = "renesas,msiof-r8a7791";
+		compatible = "renesas,msiof-r8a7791",
+			     "renesas,rcar-gen2-msiof";
 		reg = <0 0xe6e20000 0 0x0064>;
 		interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp0_clks R8A7791_CLK_MSIOF0>;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/spi-armada-3700.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/spi-armada-3700.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/spi-armada-3700.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/spi-armada-3700.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,25 @@
+* Marvell Armada 3700 SPI Controller
+
+Required Properties:
+
+- compatible: should be "marvell,armada-3700-spi"
+- reg: physical base address of the controller and length of memory mapped
+       region.
+- interrupts: The interrupt number. The interrupt specifier format depends on
+	      the interrupt controller and of its driver.
+- clocks: Must contain the clock source, usually from the North Bridge clocks.
+- num-cs: The number of chip selects that is supported by this SPI Controller
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+
+Example:
+
+	spi0: spi@10600 {
+		compatible = "marvell,armada-3700-spi";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x10600 0x5d>;
+		clocks = <&nb_perih_clk 7>;
+		interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+		num-cs = <4>;
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,19 @@
+* Freescale Low Power SPI (LPSPI) for i.MX
+
+Required properties:
+- compatible :
+  - "fsl,imx7ulp-spi" for LPSPI compatible with the one integrated on i.MX7ULP soc
+- reg : address and length of the lpspi master registers
+- interrupt-parent : core interrupt controller
+- interrupts : lpspi interrupt
+- clocks : lpspi clock specifier
+
+Examples:
+
+lpspi2: lpspi@40290000 {
+	compatible = "fsl,imx7ulp-spi";
+	reg = <0x40290000 0x10000>;
+	interrupt-parent = <&intc>;
+	interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&clks IMX7ULP_CLK_LPSPI2>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/spi-sun6i.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/spi-sun6i.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/spi/spi-sun6i.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/spi/spi-sun6i.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
-Allwinner A31 SPI controller
+Allwinner A31/H3 SPI controller
 
 Required properties:
-- compatible: Should be "allwinner,sun6i-a31-spi".
+- compatible: Should be "allwinner,sun6i-a31-spi" or "allwinner,sun8i-h3-spi".
 - reg: Should contain register location and length.
 - interrupts: Should contain interrupt.
 - clocks: phandle to the clocks feeding the SPI controller. Two are
@@ -12,6 +12,11 @@ Required properties:
 - resets: phandle to the reset controller asserting this device in
           reset
 
+Optional properties:
+- dmas: DMA specifiers for rx and tx dma. See the DMA client binding,
+	Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request names should include "rx" and "tx" if present.
+
 Example:
 
 spi1: spi@01c69000 {
@@ -22,3 +27,19 @@ spi1: spi@01c69000 {
 	clock-names = "ahb", "mod";
 	resets = <&ahb1_rst 21>;
 };
+
+spi0: spi@01c68000 {
+	compatible = "allwinner,sun8i-h3-spi";
+	reg = <0x01c68000 0x1000>;
+	interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+	clock-names = "ahb", "mod";
+	dmas = <&dma 23>, <&dma 23>;
+	dma-names = "rx", "tx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&spi0_pins>;
+	resets = <&ccu RST_BUS_SPI0>;
+	status = "disabled";
+	#address-cells = <1>;
+	#size-cells = <0>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/sram/sram.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sram/sram.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/sram/sram.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/sram/sram.txt	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@ Simple IO memory regions to be managed b
 
 Required properties:
 
-- compatible : mmio-sram
+- compatible : mmio-sram or atmel,sama5d2-securam
 
 - reg : SRAM iomem address range
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/submitting-patches.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/submitting-patches.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/submitting-patches.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/submitting-patches.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
 
 I. For patch submitters
 
-  0) Normal patch submission rules from Documentation/SubmittingPatches
+  0) Normal patch submission rules from Documentation/process/submitting-patches.rst
      applies.
 
   1) The Documentation/ portion of the patch should be a separate patch.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,17 @@
+Binding for Thermal Sensor driver for BCM2835 SoCs.
+
+Required parameters:
+-------------------
+
+compatible: 	should be one of: "brcm,bcm2835-thermal",
+		"brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
+reg:		Address range of the thermal registers.
+clocks: 	Phandle of the clock used by the thermal sensor.
+
+Example:
+
+thermal: thermal@7e212000 {
+	compatible = "brcm,bcm2835-thermal";
+	reg = <0x7e212000 0x8>;
+	clocks = <&clocks BCM2835_CLOCK_TSENS>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt	2017-02-12 16:03:20.000000000 -0500
@@ -22,10 +22,13 @@ Required properties:
 	      TSADC controller.
 - pinctrl-2 : The "sleep" pinctrl state, it will be in for suspend.
 - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+
+Optional properties:
 - rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
 - rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO.
 - rockchip,hw-tshut-polarity : The hardware-controlled active polarity 0:LOW
 			       1:HIGH.
+- rockchip,grf : The phandle of the syscon node for the general register file.
 
 Exiample:
 tsadc: tsadc@ff280000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/thermal/st-thermal.txt	2017-02-12 16:03:20.000000000 -0500
@@ -3,17 +3,8 @@ Binding for Thermal Sensor driver for ST
 Required parameters:
 -------------------
 
-compatible : 	st,<SoC>-<module>-thermal; should be one of:
-		  "st,stih415-sas-thermal",
-		  "st,stih415-mpe-thermal",
-		  "st,stih416-sas-thermal"
-		  "st,stih416-mpe-thermal"
-		  "st,stid127-thermal" or
-		  "st,stih407-thermal"
-		according to the SoC type (stih415, stih416, stid127, stih407)
-		and module type (sas or mpe). On stid127 & stih407 there is only
-		one die/module, so there is no module type in the compatible
-		string.
+compatible : 	Should be "st,stih407-thermal"
+
 clock-names : 	Should be "thermal".
 		  See: Documentation/devicetree/bindings/resource-names.txt
 clocks : 	Phandle of the clock used by the thermal sensor.
@@ -25,18 +16,17 @@ Optional parameters:
 reg : 		For non-sysconf based sensors, this should be the physical base
 		address and length of the sensor's registers.
 interrupts :	Standard way to define interrupt number.
-		Interrupt is mandatory to be defined when compatible is
-		"stih416-mpe-thermal".
 		  NB: For thermal sensor's for which no interrupt has been
 		  defined, a polling delay of 1000ms will be used to read the
 		  temperature from device.
 
 Example:
 
-	temp1@fdfe8000 {
-		compatible	= "st,stih416-mpe-thermal";
-		reg		= <0xfdfe8000 0x10>;
-		clock-names	= "thermal";
-		clocks		= <&clk_m_mpethsens>;
-		interrupts	= <GIC_SPI 23 IRQ_TYPE_NONE>;
+	temp0@91a0000 {
+		compatible = "st,stih407-thermal";
+		reg = <0x91a0000 0x28>;
+		clock-names = "thermal";
+		clocks = <&CLK_SYSIN>;
+		interrupts = <GIC_SPI 205 IRQ_TYPE_EDGE_RISING>;
+		st,passive_cooling_temp = <110>;
 	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer0.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,17 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer0"
+
+Clocks required for compatible = "ezchip,nps400-timer0":
+- interrupts : The interrupt of the first timer
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer0";
+	interrupts = <3>;
+	clocks = <&sysclk>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer1.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,15 @@
+NPS Network Processor
+
+Required properties:
+
+- compatible :	should be "ezchip,nps400-timer1"
+
+Clocks required for compatible = "ezchip,nps400-timer1":
+- clocks : Must contain a single entry describing the clock input
+
+Example:
+
+timer {
+	compatible = "ezchip,nps400-timer1";
+	clocks = <&sysclk>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/timer/ezchip,nps400-timer.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-NPS Network Processor
-
-Required properties:
-
-- compatible :	should be "ezchip,nps400-timer"
-
-Clocks required for compatible = "ezchip,nps400-timer":
-- clocks : Must contain a single entry describing the clock input
-
-Example:
-
-timer {
-	compatible = "ezchip,nps400-timer";
-	clocks = <&sysclk>;
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/ufs/ufs-qcom.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/ufs/ufs-qcom.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/ufs/ufs-qcom.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,8 +7,11 @@ To bind UFS PHY with UFS host controller
 contain a phandle reference to UFS PHY node.
 
 Required properties:
-- compatible        : compatible list, contains "qcom,ufs-phy-qmp-20nm"
-		      or "qcom,ufs-phy-qmp-14nm" according to the relevant phy in use.
+- compatible        : compatible list, contains one of the following -
+			"qcom,ufs-phy-qmp-20nm" for 20nm ufs phy,
+			"qcom,ufs-phy-qmp-14nm" for legacy 14nm ufs phy,
+			"qcom,msm8996-ufs-phy-qmp-14nm" for 14nm ufs phy
+			 present on MSM8996 chipset.
 - reg               : should contain PHY register address space (mandatory),
 - reg-names         : indicates various resources passed to driver (via reg proptery) by name.
                       Required "reg-names" is "phy_mem".
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/atmel-usb.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/atmel-usb.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/atmel-usb.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/atmel-usb.txt	2017-02-12 16:03:20.000000000 -0500
@@ -6,9 +6,9 @@ Required properties:
  - compatible: Should be "atmel,at91rm9200-ohci" for USB controllers
    used in host mode.
  - reg: Address and length of the register set for the device
- - interrupts: Should contain ehci interrupt
+ - interrupts: Should contain ohci interrupt
  - clocks: Should reference the peripheral, host and system clocks
- - clock-names: Should contains two strings
+ - clock-names: Should contain three strings
 		"ohci_clk" for the peripheral clock
 		"hclk" for the host clock
 		"uhpck" for the system clock
@@ -35,7 +35,7 @@ Required properties:
  - reg: Address and length of the register set for the device
  - interrupts: Should contain ehci interrupt
  - clocks: Should reference the peripheral and the UTMI clocks
- - clock-names: Should contains two strings
+ - clock-names: Should contain two strings
 		"ehci_clk" for the peripheral clock
 		"usb_clk" for the UTMI clock
 
@@ -58,7 +58,7 @@ Required properties:
  - reg: Address and length of the register set for the device
  - interrupts: Should contain macb interrupt
  - clocks: Should reference the peripheral and the AHB clocks
- - clock-names: Should contains two strings
+ - clock-names: Should contain two strings
 		"pclk" for the peripheral clock
 		"hclk" for the AHB clock
 
@@ -85,7 +85,7 @@ Required properties:
  - reg: Address and length of the register set for the device
  - interrupts: Should contain usba interrupt
  - clocks: Should reference the peripheral and host clocks
- - clock-names: Should contains two strings
+ - clock-names: Should contain two strings
 		"pclk" for the peripheral clock
 		"hclk" for the host clock
  - ep childnode: To specify the number of endpoints and their properties.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/da8xx-usb.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/da8xx-usb.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/da8xx-usb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/da8xx-usb.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,43 @@
+TI DA8xx MUSB
+~~~~~~~~~~~~~
+For DA8xx/OMAP-L1x/AM17xx/AM18xx platforms.
+
+Required properties:
+~~~~~~~~~~~~~~~~~~~~
+ - compatible : Should be set to "ti,da830-musb".
+
+ - reg: Offset and length of the USB controller register set.
+
+ - interrupts: The USB interrupt number.
+
+ - interrupt-names: Should be set to "mc".
+
+ - dr_mode: The USB operation mode. Should be one of "host", "peripheral" or "otg".
+
+ - phys: Phandle for the PHY device
+
+ - phy-names: Should be "usb-phy"
+
+Optional properties:
+~~~~~~~~~~~~~~~~~~~~
+ - vbus-supply: Phandle to a regulator providing the USB bus power.
+
+Example:
+	usb_phy: usb-phy {
+		compatible = "ti,da830-usb-phy";
+		#phy-cells = <0>;
+		status = "okay";
+	};
+	usb0: usb@200000 {
+		compatible = "ti,da830-musb";
+		reg =   <0x00200000 0x10000>;
+		interrupts = <58>;
+		interrupt-names = "mc";
+
+		dr_mode = "host";
+		vbus-supply = <&usb_vbus>;
+		phys = <&usb_phy 0>;
+		phy-names = "usb-phy";
+
+		status = "okay";
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/dwc2.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/dwc2.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/dwc2.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/dwc2.txt	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@ Required properties:
   - "lantiq,xrx200-usb": The DWC2 USB controller instance in Lantiq XRX SoCs;
   - "amlogic,meson8b-usb": The DWC2 USB controller instance in Amlogic Meson8b SoCs;
   - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs;
+  - "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs;
   - snps,dwc2: A generic DWC2 USB controller with default parameters.
 - reg : Should contain 1 register range (address and length)
 - interrupts : Should contain 1 interrupt
@@ -25,11 +26,13 @@ Optional properties:
 Refer to phy/phy-bindings.txt for generic phy consumer properties
 - dr_mode: shall be one of "host", "peripheral" and "otg"
   Refer to usb/generic.txt
-- g-use-dma: enable dma usage in gadget driver.
 - g-rx-fifo-size: size of rx fifo size in gadget mode.
 - g-np-tx-fifo-size: size of non-periodic tx fifo size in gadget mode.
 - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
 
+Deprecated properties:
+- g-use-dma: gadget DMA mode is automatically detected
+
 Example:
 
         usb@101c0000 {
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/mt8173-mtu3.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,87 @@
+The device node for Mediatek USB3.0 DRD controller
+
+Required properties:
+ - compatible : should be "mediatek,mt8173-mtu3"
+ - reg : specifies physical base address and size of the registers
+ - reg-names: should be "mac" for device IP and "ippc" for IP port control
+ - interrupts : interrupt used by the device IP
+ - power-domains : a phandle to USB power domain node to control USB's
+	mtcmos
+ - vusb33-supply : regulator of USB avdd3.3v
+ - clocks : a list of phandle + clock-specifier pairs, one for each
+	entry in clock-names
+ - clock-names : must contain "sys_ck" for clock of controller;
+	"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
+	depends on "mediatek,enable-wakeup"
+ - phys : a list of phandle + phy specifier pairs
+ - dr_mode : should be one of "host", "peripheral" or "otg",
+	refer to usb/generic.txt
+
+Optional properties:
+ - #address-cells, #size-cells : should be '2' if the device has sub-nodes
+	with 'reg' property
+ - ranges : allows valid 1:1 translation between child's address space and
+	parent's address space
+ - extcon : external connector for vbus and idpin changes detection, needed
+	when supports dual-role mode.
+ - vbus-supply : reference to the VBUS regulator, needed when supports
+	dual-role mode.
+ - pinctl-names : a pinctrl state named "default" must be defined,
+	"id_float" and "id_ground" are optinal which depends on
+	"mediatek,enable-manual-drd"
+ - pinctrl-0 : pin control group
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+
+ - maximum-speed : valid arguments are "super-speed", "high-speed" and
+	"full-speed"; refer to usb/generic.txt
+ - enable-manual-drd : supports manual dual-role switch via debugfs; usually
+	used when receptacle is TYPE-A and also wants to support dual-role
+	mode.
+ - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
+ - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
+	control register, it depends on "mediatek,enable-wakeup".
+
+Sub-nodes:
+The xhci should be added as subnode to mtu3 as shown in the following example
+if host mode is enabled. The DT binding details of xhci can be found in:
+Documentation/devicetree/bindings/usb/mt8173-xhci.txt
+
+Example:
+ssusb: usb@11271000 {
+	compatible = "mediatek,mt8173-mtu3";
+	reg = <0 0x11271000 0 0x3000>,
+	      <0 0x11280700 0 0x0100>;
+	reg-names = "mac", "ippc";
+	interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_LOW>;
+	phys = <&phy_port0 PHY_TYPE_USB3>,
+	       <&phy_port1 PHY_TYPE_USB2>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+	clocks = <&topckgen CLK_TOP_USB30_SEL>,
+		 <&pericfg CLK_PERI_USB0>,
+		 <&pericfg CLK_PERI_USB1>;
+	clock-names = "sys_ck",
+		      "wakeup_deb_p0",
+		      "wakeup_deb_p1";
+	vusb33-supply = <&mt6397_vusb_reg>;
+	vbus-supply = <&usb_p0_vbus>;
+	extcon = <&extcon_usb>;
+	dr_mode = "otg";
+	mediatek,enable-wakeup;
+	mediatek,syscon-wakeup = <&pericfg>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+	ranges;
+	status = "disabled";
+
+	usb_host: xhci@11270000 {
+		compatible = "mediatek,mt8173-xhci";
+		reg = <0 0x11270000 0 0x1000>;
+		reg-names = "mac";
+		interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+		power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+		clocks = <&topckgen CLK_TOP_USB30_SEL>;
+		clock-names = "sys_ck";
+		vusb33-supply = <&mt6397_vusb_reg>;
+		status = "disabled";
+	};
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/mt8173-xhci.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/mt8173-xhci.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/mt8173-xhci.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/mt8173-xhci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -2,10 +2,18 @@ MT8173 xHCI
 
 The device node for Mediatek SOC USB3.0 host controller
 
+There are two scenarios: the first one only supports xHCI driver;
+the second one supports dual-role mode, and the host is based on xHCI
+driver. Take account of backward compatibility, we divide bindings
+into two parts.
+
+1st: only supports xHCI driver
+------------------------------------------------------------------------
+
 Required properties:
  - compatible : should contain "mediatek,mt8173-xhci"
- - reg : specifies physical base address and size of the registers,
-	the first one for MAC, the second for IPPC
+ - reg : specifies physical base address and size of the registers
+ - reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control
  - interrupts : interrupt used by the controller
  - power-domains : a phandle to USB power domain node to control USB's
 	mtcmos
@@ -27,12 +35,16 @@ Optional properties:
 	control register, it depends on "mediatek,wakeup-src".
  - vbus-supply : reference to the VBUS regulator;
  - usb3-lpm-capable : supports USB3.0 LPM
+ - pinctrl-names : a pinctrl state named "default" must be defined
+ - pinctrl-0 : pin control group
+	See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
 
 Example:
 usb30: usb@11270000 {
 	compatible = "mediatek,mt8173-xhci";
 	reg = <0 0x11270000 0 0x1000>,
 	      <0 0x11280700 0 0x0100>;
+	reg-names = "mac", "ippc";
 	interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
 	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
 	clocks = <&topckgen CLK_TOP_USB30_SEL>,
@@ -49,3 +61,41 @@ usb30: usb@11270000 {
 	mediatek,syscon-wakeup = <&pericfg>;
 	mediatek,wakeup-src = <1>;
 };
+
+2nd: dual-role mode with xHCI driver
+------------------------------------------------------------------------
+
+In the case, xhci is added as subnode to mtu3. An example and the DT binding
+details of mtu3 can be found in:
+Documentation/devicetree/bindings/usb/mtu3.txt
+
+Required properties:
+ - compatible : should contain "mediatek,mt8173-xhci"
+ - reg : specifies physical base address and size of the registers
+ - reg-names: should be "mac" for xHCI MAC
+ - interrupts : interrupt used by the host controller
+ - power-domains : a phandle to USB power domain node to control USB's
+	mtcmos
+ - vusb33-supply : regulator of USB avdd3.3v
+
+ - clocks : a list of phandle + clock-specifier pairs, one for each
+	entry in clock-names
+ - clock-names : must be
+	"sys_ck": for clock of xHCI MAC
+
+Optional properties:
+ - vbus-supply : reference to the VBUS regulator;
+ - usb3-lpm-capable : supports USB3.0 LPM
+
+Example:
+usb30: usb@11270000 {
+	compatible = "mediatek,mt8173-xhci";
+	reg = <0 0x11270000 0 0x1000>;
+	reg-names = "mac";
+	interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_LOW>;
+	power-domains = <&scpsys MT8173_POWER_DOMAIN_USB>;
+	clocks = <&topckgen CLK_TOP_USB30_SEL>;
+	clock-names = "sys_ck";
+	vusb33-supply = <&mt6397_vusb_reg>;
+	usb3-lpm-capable;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/ohci-da8xx.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/ohci-da8xx.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/ohci-da8xx.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/ohci-da8xx.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,23 @@
+DA8XX USB OHCI controller
+
+Required properties:
+
+ - compatible: Should be "ti,da830-ohci"
+ - reg:        Should contain one register range i.e. start and length
+ - interrupts: Description of the interrupt line
+ - phys:       Phandle for the PHY device
+ - phy-names:  Should be "usb-phy"
+
+Optional properties:
+ - vbus-supply: phandle of regulator that controls vbus power / over-current
+
+Example:
+
+ohci: usb@0225000 {
+        compatible = "ti,da830-ohci";
+        reg = <0x225000 0x1000>;
+        interrupts = <59>;
+        phys = <&usb_phy 1>;
+        phy-names = "usb-phy";
+        vbus-supply = <&reg_usb_ohci>;
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/s3c2410-usb.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/s3c2410-usb.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/s3c2410-usb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/s3c2410-usb.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,22 @@
+Samsung S3C2410 and compatible SoC USB controller
+
+OHCI
+
+Required properties:
+ - compatible: should be "samsung,s3c2410-ohci" for USB host controller
+ - reg: address and lenght of the controller memory mapped region
+ - interrupts: interrupt number for the USB OHCI controller
+ - clocks: Should reference the bus and host clocks
+ - clock-names: Should contain two strings
+		"usb-bus-host" for the USB bus clock
+		"usb-host" for the USB host clock
+
+Example:
+
+usb0: ohci@49000000 {
+	compatible = "samsung,s3c2410-ohci";
+	reg = <0x49000000 0x100>;
+	interrupts = <0 0 26 3>;
+	clocks = <&clocks UCLK>, <&clocks HCLK_USBH>;
+	clock-names = "usb-bus-host", "usb-host";
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/usb/usb-xhci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@ Required properties:
     - "renesas,xhci-r8a7791" for r8a7791 SoC
     - "renesas,xhci-r8a7793" for r8a7793 SoC
     - "renesas,xhci-r8a7795" for r8a7795 SoC
+    - "renesas,xhci-r8a7796" for r8a7796 SoC
     - "renesas,rcar-gen2-xhci" for a generic R-Car Gen2 compatible device
     - "renesas,rcar-gen3-xhci" for a generic R-Car Gen3 compatible device
     - "xhci-platform" (deprecated)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/vendor-prefixes.txt	2017-02-12 16:03:20.000000000 -0500
@@ -24,9 +24,11 @@ ampire	Ampire Co., Ltd.
 ams	AMS AG
 amstaos	AMS-Taos Inc.
 analogix	Analogix Semiconductor, Inc.
+andestech	Andes Technology Corporation
 apm	Applied Micro Circuits Corporation (APM)
 aptina	Aptina Imaging
 arasan	Arasan Chip Systems
+aries	Aries Embedded GmbH
 arm	ARM Ltd.
 armadeus	ARMadeus Systems SARL
 arrow	Arrow Electronics
@@ -39,6 +41,7 @@ auo	AU Optronics Corporation
 auvidea Auvidea GmbH
 avago	Avago Technologies
 avic	Shanghai AVIC Optoelectronics Co., Ltd.
+axentia	Axentia Technologies AB
 axis	Axis Communications AB
 boe	BOE Technology Group Co., Ltd.
 bosch	Bosch Sensortec GmbH
@@ -67,6 +70,7 @@ creative	Creative Technology Ltd
 crystalfontz	Crystalfontz America, Inc.
 cubietech	Cubietech, Ltd.
 cypress	Cypress Semiconductor Corporation
+cznic	CZ.NIC, z.s.p.o.
 dallas	Maxim Integrated Products (formerly Dallas Semiconductor)
 davicom	DAVICOM Semiconductor, Inc.
 delta	Delta Electronics, Inc.
@@ -126,6 +130,7 @@ hitex	Hitex Development Tools
 holt	Holt Integrated Circuits, Inc.
 honeywell	Honeywell
 hp	Hewlett Packard
+holtek	Holtek Semiconductor, Inc.
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
@@ -135,6 +140,7 @@ infineon Infineon Technologies
 inforce	Inforce Computing
 ingenic	Ingenic Semiconductor
 innolux	Innolux Corporation
+inside-secure	INSIDE Secure
 intel	Intel Corporation
 intercontrol	Inter Control Group
 invensense	InvenSense Inc.
@@ -158,18 +164,22 @@ lg	LG Corporation
 linux	Linux-specific binding
 lltc	Linear Technology Corporation
 lsi	LSI Corp. (LSI Logic)
+macnica	Macnica Americas
 marvell	Marvell Technology Group Ltd.
 maxim	Maxim Integrated Products
+mcube	mCube
 meas	Measurement Specialties
 mediatek	MediaTek Inc.
 melexis	Melexis N.V.
 melfas	MELFAS Inc.
+memsic	MEMSIC Inc.
 merrii	Merrii Technology Co., Ltd.
 micrel	Micrel Inc.
 microchip	Microchip Technology Inc.
 microcrystal	Micro Crystal AG
 micron	Micron Technology Inc.
 minix	MINIX Technology Ltd.
+miramems	MiraMEMS Sensing Technology Co., Ltd.
 mitsubishi	Mitsubishi Electric Corporation
 mosaixtech	Mosaix Technologies, Inc.
 moxa	Moxa
@@ -180,19 +190,24 @@ mti	Imagination Technologies Ltd. (forme
 mundoreader	Mundo Reader S.L.
 murata	Murata Manufacturing Co., Ltd.
 mxicy	Macronix International Co., Ltd.
+myir	MYIR Tech Limited
 national	National Semiconductor
 nec	NEC LCD Technologies, Ltd.
 neonode		Neonode Inc.
 netgear	NETGEAR
 netlogic	Broadcom Corporation (formerly NetLogic Microsystems)
 netxeon		Shenzhen Netxeon Technology CO., LTD
+nexbox	Nexbox
 newhaven	Newhaven Display International
+ni	National Instruments
 nintendo	Nintendo
 nokia	Nokia
 nuvoton	Nuvoton Technology Corporation
+nvd	New Vision Display
 nvidia	NVIDIA
 nxp	NXP Semiconductors
 okaya	Okaya Electric America, Inc.
+oki	Oki Electric Industry Co., Ltd.
 olimex	OLIMEX Ltd.
 onion	Onion Corporation
 onnn	ON Semiconductor Corp.
@@ -208,6 +223,7 @@ parade	Parade Technologies Inc.
 pericom	Pericom Technology Inc.
 phytec	PHYTEC Messtechnik GmbH
 picochip	Picochip Ltd
+pine64	Pine64
 pixcir  PIXCIR MICROELECTRONICS Co., Ltd
 plathome	Plat'Home Co., Ltd.
 plda	PLDA
@@ -229,8 +245,10 @@ realtek Realtek Semiconductor Corp.
 renesas	Renesas Electronics Corporation
 richtek	Richtek Technology Corporation
 ricoh	Ricoh Co. Ltd.
+rikomagic	Rikomagic Tech Corp. Ltd
 rockchip	Fuzhou Rockchip Electronics Co., Ltd
 samsung	Samsung Semiconductor
+samtec	Samtec/Softing company
 sandisk	Sandisk Corporation
 sbs	Smart Battery System
 schindler	Schindler
@@ -275,6 +293,7 @@ tcg	Trusted Computing Group
 tcl	Toby Churchill Ltd.
 technexion	TechNexion
 technologic	Technologic Systems
+terasic	Terasic Inc.
 thine	THine Electronics, Inc.
 ti	Texas Instruments
 tlm	Trusted Logic Mobility
@@ -289,6 +308,7 @@ tronfy	Tronfy
 tronsmart	Tronsmart
 truly	Truly Semiconductors Limited
 tyan	Tyan Computer Corporation
+udoo	Udoo
 uniwest	United Western Technologies Corp (UniWest)
 upisemi	uPI Semiconductor Corp.
 urt	United Radiant Technology Corporation
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/bindings/video/bridge/sil-sii8620.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,33 @@
+Silicon Image SiI8620 HDMI/MHL bridge bindings
+
+Required properties:
+	- compatible: "sil,sii8620"
+	- reg: i2c address of the bridge
+	- cvcc10-supply: Digital Core Supply Voltage (1.0V)
+	- iovcc18-supply: I/O Supply Voltage (1.8V)
+	- interrupts, interrupt-parent: interrupt specifier of INT pin
+	- reset-gpios: gpio specifier of RESET pin
+	- clocks, clock-names: specification and name of "xtal" clock
+	- video interfaces: Device node can contain video interface port
+			    node for HDMI encoder according to [1].
+
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt
+
+Example:
+	sii8620@39 {
+		reg = <0x39>;
+		compatible = "sil,sii8620";
+		cvcc10-supply = <&ldo36_reg>;
+		iovcc18-supply = <&ldo34_reg>;
+		interrupt-parent = <&gpf0>;
+		interrupts = <2 0>;
+		reset-gpio = <&gpv7 0 0>;
+		clocks = <&pmu_system_controller 0>;
+		clock-names = "xtal";
+
+		port {
+			mhl_to_hdmi: endpoint {
+				remote-endpoint = <&hdmi_to_mhl>;
+			};
+		};
+	};
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/devicetree/booting-without-of.txt linux-libre-4.10-rc8-gnu/Documentation/devicetree/booting-without-of.txt
--- linux-libre-4.9-gnu/Documentation/devicetree/booting-without-of.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/devicetree/booting-without-of.txt	2017-02-12 16:03:20.000000000 -0500
@@ -974,6 +974,13 @@ compatibility.
       4Gb. Some vendors prefer splitting those ranges into smaller
       segments, but the kernel doesn't care.
 
+  Additional properties:
+
+    - hotpluggable : The presence of this property provides an explicit
+      hint to the operating system that this memory may potentially be
+      removed later. The kernel can take this into consideration when
+      doing nonmovable allocations and when laying out memory zones.
+
   e) The /chosen node
 
   This node is a bit "special". Normally, that's where Open Firmware
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dev-tools/conf.py linux-libre-4.10-rc8-gnu/Documentation/dev-tools/conf.py
--- linux-libre-4.9-gnu/Documentation/dev-tools/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dev-tools/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "Development tools for the kernel"
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'dev-tools.tex', project,
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dev-tools/gcov.rst linux-libre-4.10-rc8-gnu/Documentation/dev-tools/gcov.rst
--- linux-libre-4.9-gnu/Documentation/dev-tools/gcov.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dev-tools/gcov.rst	2017-02-12 16:03:20.000000000 -0500
@@ -201,7 +201,9 @@ Appendix A: gather_on_build.sh
 ------------------------------
 
 Sample script to gather coverage meta files on the build machine
-(see 6a)::
+(see 6a):
+
+.. code-block:: sh
 
     #!/bin/bash
 
@@ -232,7 +234,9 @@ Appendix B: gather_on_test.sh
 -----------------------------
 
 Sample script to gather coverage data files on the test machine
-(see 6b)::
+(see 6b):
+
+.. code-block:: sh
 
     #!/bin/bash -e
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dev-tools/index.rst linux-libre-4.10-rc8-gnu/Documentation/dev-tools/index.rst
--- linux-libre-4.9-gnu/Documentation/dev-tools/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dev-tools/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,33 @@
+================================
+Development tools for the kernel
+================================
+
+This document is a collection of documents about development tools that can
+be used to work on the kernel.  For now, the documents have been pulled
+together without any significant effot to integrate them into a coherent
+whole; patches welcome!
+
+.. class:: toc-title
+
+	   Table of contents
+
+.. toctree::
+   :maxdepth: 2
+
+   coccinelle
+   sparse
+   kcov
+   gcov
+   kasan
+   ubsan
+   kmemleak
+   kmemcheck
+   gdb-kernel-debugging
+
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dev-tools/kcov.rst linux-libre-4.10-rc8-gnu/Documentation/dev-tools/kcov.rst
--- linux-libre-4.9-gnu/Documentation/dev-tools/kcov.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dev-tools/kcov.rst	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,9 @@ Profiling data will only become accessib
 
         mount -t debugfs none /sys/kernel/debug
 
-The following program demonstrates kcov usage from within a test program::
+The following program demonstrates kcov usage from within a test program:
+
+.. code-block:: c
 
     #include <stdio.h>
     #include <stddef.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dev-tools/sparse.rst linux-libre-4.10-rc8-gnu/Documentation/dev-tools/sparse.rst
--- linux-libre-4.9-gnu/Documentation/dev-tools/sparse.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dev-tools/sparse.rst	2017-02-12 16:03:20.000000000 -0500
@@ -51,13 +51,6 @@ sure that bitwise types don't get mixed
 vs cpu-endian vs whatever), and there the constant "0" really _is_
 special.
 
-__bitwise__ - to be used for relatively compact stuff (gfp_t, etc.) that
-is mostly warning-free and is supposed to stay that way.  Warnings will
-be generated without __CHECK_ENDIAN__.
-
-__bitwise - noisy stuff; in particular, __le*/__be* are that.  We really
-don't want to drown in noise unless we'd explicitly asked for it.
-
 Using sparse for lock checking
 ------------------------------
 
@@ -109,9 +102,4 @@ be recompiled or not.  The latter is a f
 have already built it.
 
 The optional make variable CF can be used to pass arguments to sparse.  The
-build system passes -Wbitwise to sparse automatically.  To perform endianness
-checks, you may define __CHECK_ENDIAN__::
-
-        make C=2 CF="-D__CHECK_ENDIAN__"
-
-These checks are disabled by default as they generate a host of warnings.
+build system passes -Wbitwise to sparse automatically.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dev-tools/tools.rst linux-libre-4.10-rc8-gnu/Documentation/dev-tools/tools.rst
--- linux-libre-4.9-gnu/Documentation/dev-tools/tools.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dev-tools/tools.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-================================
-Development tools for the kernel
-================================
-
-This document is a collection of documents about development tools that can
-be used to work on the kernel.  For now, the documents have been pulled
-together without any significant effot to integrate them into a coherent
-whole; patches welcome!
-
-.. class:: toc-title
-
-	   Table of contents
-
-.. toctree::
-   :maxdepth: 2
-
-   coccinelle
-   sparse
-   kcov
-   gcov
-   kasan
-   ubsan
-   kmemleak
-   kmemcheck
-   gdb-kernel-debugging
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dmaengine/client.txt linux-libre-4.10-rc8-gnu/Documentation/dmaengine/client.txt
--- linux-libre-4.9-gnu/Documentation/dmaengine/client.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dmaengine/client.txt	2017-02-12 16:03:20.000000000 -0500
@@ -37,8 +37,8 @@ The slave DMA usage consists of followin
 2. Set slave and controller specific parameters
 
    Next step is always to pass some specific information to the DMA
-   driver.  Most of the generic information which a slave DMA can use
-   is in struct dma_slave_config.  This allows the clients to specify
+   driver. Most of the generic information which a slave DMA can use
+   is in struct dma_slave_config. This allows the clients to specify
    DMA direction, DMA addresses, bus widths, DMA burst lengths etc
    for the peripheral.
 
@@ -52,7 +52,7 @@ The slave DMA usage consists of followin
 				  struct dma_slave_config *config)
 
    Please see the dma_slave_config structure definition in dmaengine.h
-   for a detailed explanation of the struct members.  Please note
+   for a detailed explanation of the struct members. Please note
    that the 'direction' member will be going away as it duplicates the
    direction given in the prepare call.
 
@@ -101,7 +101,7 @@ The slave DMA usage consists of followin
 	desc = dmaengine_prep_slave_sg(chan, sgl, nr_sg, direction, flags);
 
    Once a descriptor has been obtained, the callback information can be
-   added and the descriptor must then be submitted.  Some DMA engine
+   added and the descriptor must then be submitted. Some DMA engine
    drivers may hold a spinlock between a successful preparation and
    submission so it is important that these two operations are closely
    paired.
@@ -138,7 +138,7 @@ The slave DMA usage consists of followin
    activity via other DMA engine calls not covered in this document.
 
    dmaengine_submit() will not start the DMA operation, it merely adds
-   it to the pending queue.  For this, see step 5, dma_async_issue_pending.
+   it to the pending queue. For this, see step 5, dma_async_issue_pending.
 
 5. Issue pending DMA requests and wait for callback notification
 
@@ -184,13 +184,13 @@ Further APIs:
 
 3. int dmaengine_resume(struct dma_chan *chan)
 
-   Resume a previously paused DMA channel.  It is invalid to resume a
+   Resume a previously paused DMA channel. It is invalid to resume a
    channel which is not currently paused.
 
 4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan,
         dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
 
-   This can be used to check the status of the channel.  Please see
+   This can be used to check the status of the channel. Please see
    the documentation in include/linux/dmaengine.h for a more complete
    description of this API.
 
@@ -200,7 +200,7 @@ Further APIs:
 
    Note:
 	Not all DMA engine drivers can return reliable information for
-	a running DMA channel.  It is recommended that DMA engine users
+	a running DMA channel. It is recommended that DMA engine users
 	pause or stop (via dmaengine_terminate_all()) the channel before
 	using this API.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dmaengine/dmatest.txt linux-libre-4.10-rc8-gnu/Documentation/dmaengine/dmatest.txt
--- linux-libre-4.9-gnu/Documentation/dmaengine/dmatest.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dmaengine/dmatest.txt	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@ command:
 	% ls -1 /sys/class/dma/
 
 Once started a message like "dmatest: Started 1 threads using dma0chan0" is
-emitted.  After that only test failure messages are reported until the test
+emitted. After that only test failure messages are reported until the test
 stops.
 
 Note that running a new test will not stop any in progress test.
@@ -43,11 +43,11 @@ The following command returns the state
 	% cat /sys/module/dmatest/parameters/run
 
 To wait for test completion userpace can poll 'run' until it is false, or use
-the wait parameter.  Specifying 'wait=1' when loading the module causes module
+the wait parameter. Specifying 'wait=1' when loading the module causes module
 initialization to pause until a test run has completed, while reading
 /sys/module/dmatest/parameters/wait waits for any running test to complete
-before returning.  For example, the following scripts wait for 42 tests
-to complete before exiting.  Note that if 'iterations' is set to 'infinite' then
+before returning. For example, the following scripts wait for 42 tests
+to complete before exiting. Note that if 'iterations' is set to 'infinite' then
 waiting is disabled.
 
 Example:
@@ -81,7 +81,7 @@ Example of output:
 
 The message format is unified across the different types of errors. A number in
 the parens represents additional information, e.g. error code, error counter,
-or status.  A test thread also emits a summary line at completion listing the
+or status. A test thread also emits a summary line at completion listing the
 number of tests executed, number that failed, and a result code.
 
 Example:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dmaengine/provider.txt linux-libre-4.10-rc8-gnu/Documentation/dmaengine/provider.txt
--- linux-libre-4.9-gnu/Documentation/dmaengine/provider.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dmaengine/provider.txt	2017-02-12 16:03:20.000000000 -0500
@@ -384,7 +384,7 @@ where to put them)
     - The descriptor should be prepared for reuse by invoking
       dmaengine_desc_set_reuse() which will set DMA_CTRL_REUSE.
     - dmaengine_desc_set_reuse() will succeed only when channel support
-      reusable descriptor as exhibited by capablities
+      reusable descriptor as exhibited by capabilities
     - As a consequence, if a device driver wants to skip the dma_map_sg() and
       dma_unmap_sg() in between 2 transfers, because the DMA'd data wasn't used,
       it can resubmit the transfer right after its completion.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dmaengine/pxa_dma.txt linux-libre-4.10-rc8-gnu/Documentation/dmaengine/pxa_dma.txt
--- linux-libre-4.9-gnu/Documentation/dmaengine/pxa_dma.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dmaengine/pxa_dma.txt	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@ Constraints
 
   d) Bandwidth guarantee
      The PXA architecture has 4 levels of DMAs priorities : high, normal, low.
-     The high prorities get twice as much bandwidth as the normal, which get twice
+     The high priorities get twice as much bandwidth as the normal, which get twice
      as much as the low priorities.
      A driver should be able to request a priority, especially the real-time
      ones such as pxa_camera with (big) throughputs.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/alsa-driver-api.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/alsa-driver-api.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/alsa-driver-api.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/alsa-driver-api.tmpl	1969-12-31 19:00:00.000000000 -0500
@@ -1,142 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<!-- ****************************************************** -->
-<!-- Header  -->
-<!-- ****************************************************** -->
-<book id="ALSA-Driver-API">
-  <bookinfo>
-    <title>The ALSA Driver API</title>
-
-    <legalnotice>
-    <para>
-    This document is free; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version. 
-    </para>
-
-    <para>
-    This document is distributed in the hope that it will be useful,
-    but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
-    implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
-    PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
-    for more details.
-    </para>
-
-    <para>
-    You should have received a copy of the GNU General Public
-    License along with this program; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-    MA 02111-1307 USA
-    </para>
-    </legalnotice>
-
-  </bookinfo>
-
-<toc></toc>
-
-  <chapter><title>Management of Cards and Devices</title>
-     <sect1><title>Card Management</title>
-!Esound/core/init.c
-     </sect1>
-     <sect1><title>Device Components</title>
-!Esound/core/device.c
-     </sect1>
-     <sect1><title>Module requests and Device File Entries</title>
-!Esound/core/sound.c
-     </sect1>
-     <sect1><title>Memory Management Helpers</title>
-!Esound/core/memory.c
-!Esound/core/memalloc.c
-     </sect1>
-  </chapter>
-  <chapter><title>PCM API</title>
-     <sect1><title>PCM Core</title>
-!Esound/core/pcm.c
-!Esound/core/pcm_lib.c
-!Esound/core/pcm_native.c
-!Iinclude/sound/pcm.h
-     </sect1>
-     <sect1><title>PCM Format Helpers</title>
-!Esound/core/pcm_misc.c
-     </sect1>
-     <sect1><title>PCM Memory Management</title>
-!Esound/core/pcm_memory.c
-     </sect1>
-     <sect1><title>PCM DMA Engine API</title>
-!Esound/core/pcm_dmaengine.c
-!Iinclude/sound/dmaengine_pcm.h
-     </sect1>
-  </chapter>
-  <chapter><title>Control/Mixer API</title>
-     <sect1><title>General Control Interface</title>
-!Esound/core/control.c
-     </sect1>
-     <sect1><title>AC97 Codec API</title>
-!Esound/pci/ac97/ac97_codec.c
-!Esound/pci/ac97/ac97_pcm.c
-     </sect1>
-     <sect1><title>Virtual Master Control API</title>
-!Esound/core/vmaster.c
-!Iinclude/sound/control.h
-     </sect1>
-  </chapter>
-  <chapter><title>MIDI API</title>
-     <sect1><title>Raw MIDI API</title>
-!Esound/core/rawmidi.c
-     </sect1>
-     <sect1><title>MPU401-UART API</title>
-!Esound/drivers/mpu401/mpu401_uart.c
-     </sect1>
-  </chapter>
-  <chapter><title>Proc Info API</title>
-     <sect1><title>Proc Info Interface</title>
-!Esound/core/info.c
-     </sect1>
-  </chapter>
-  <chapter><title>Compress Offload</title>
-     <sect1><title>Compress Offload API</title>
-!Esound/core/compress_offload.c
-!Iinclude/uapi/sound/compress_offload.h
-!Iinclude/uapi/sound/compress_params.h
-!Iinclude/sound/compress_driver.h
-     </sect1>
-  </chapter>
-  <chapter><title>ASoC</title>
-     <sect1><title>ASoC Core API</title>
-!Iinclude/sound/soc.h
-!Esound/soc/soc-core.c
-<!-- !Esound/soc/soc-cache.c no docbook comments here -->
-!Esound/soc/soc-devres.c
-!Esound/soc/soc-io.c
-!Esound/soc/soc-pcm.c
-!Esound/soc/soc-ops.c
-!Esound/soc/soc-compress.c
-     </sect1>
-     <sect1><title>ASoC DAPM API</title>
-!Esound/soc/soc-dapm.c
-     </sect1>
-     <sect1><title>ASoC DMA Engine API</title>
-!Esound/soc/soc-generic-dmaengine-pcm.c
-     </sect1>
-  </chapter>
-  <chapter><title>Miscellaneous Functions</title>
-     <sect1><title>Hardware-Dependent Devices API</title>
-!Esound/core/hwdep.c
-     </sect1>
-     <sect1><title>Jack Abstraction Layer API</title>
-!Iinclude/sound/jack.h
-!Esound/core/jack.c
-!Esound/soc/soc-jack.c
-     </sect1>
-     <sect1><title>ISA DMA Helpers</title>
-!Esound/core/isadma.c
-     </sect1>
-     <sect1><title>Other Helper Macros</title>
-!Iinclude/sound/core.h
-     </sect1>
-  </chapter>
-
-</book>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/crypto-API.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/crypto-API.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/crypto-API.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/crypto-API.tmpl	1969-12-31 19:00:00.000000000 -0500
@@ -1,2092 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="KernelCryptoAPI">
- <bookinfo>
-  <title>Linux Kernel Crypto API</title>
-
-  <authorgroup>
-   <author>
-    <firstname>Stephan</firstname>
-    <surname>Mueller</surname>
-    <affiliation>
-     <address>
-      <email>smueller@chronox.de</email>
-     </address>
-    </affiliation>
-   </author>
-   <author>
-    <firstname>Marek</firstname>
-    <surname>Vasut</surname>
-    <affiliation>
-     <address>
-      <email>marek@denx.de</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>2014</year>
-   <holder>Stephan Mueller</holder>
-  </copyright>
-
-
-  <legalnotice>
-   <para>
-     This documentation is free software; you can redistribute
-     it and/or modify it under the terms of the GNU General Public
-     License as published by the Free Software Foundation; either
-     version 2 of the License, or (at your option) any later
-     version.
-   </para>
-
-   <para>
-     This program is distributed in the hope that it will be
-     useful, but WITHOUT ANY WARRANTY; without even the implied
-     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-     See the GNU General Public License for more details.
-   </para>
-
-   <para>
-     You should have received a copy of the GNU General Public
-     License along with this program; if not, write to the Free
-     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-     MA 02111-1307 USA
-   </para>
-
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
- <toc></toc>
-
- <chapter id="Intro">
-  <title>Kernel Crypto API Interface Specification</title>
-
-   <sect1><title>Introduction</title>
-
-    <para>
-     The kernel crypto API offers a rich set of cryptographic ciphers as
-     well as other data transformation mechanisms and methods to invoke
-     these. This document contains a description of the API and provides
-     example code.
-    </para>
-
-    <para>
-     To understand and properly use the kernel crypto API a brief
-     explanation of its structure is given. Based on the architecture,
-     the API can be separated into different components. Following the
-     architecture specification, hints to developers of ciphers are
-     provided. Pointers to the API function call  documentation are
-     given at the end.
-    </para>
-
-    <para>
-     The kernel crypto API refers to all algorithms as "transformations".
-     Therefore, a cipher handle variable usually has the name "tfm".
-     Besides cryptographic operations, the kernel crypto API also knows
-     compression transformations and handles them the same way as ciphers.
-    </para>
-
-    <para>
-     The kernel crypto API serves the following entity types:
-
-     <itemizedlist>
-      <listitem>
-       <para>consumers requesting cryptographic services</para>
-      </listitem>
-      <listitem>
-      <para>data transformation implementations (typically ciphers)
-       that can be called by consumers using the kernel crypto
-       API</para>
-      </listitem>
-     </itemizedlist>
-    </para>
-
-    <para>
-     This specification is intended for consumers of the kernel crypto
-     API as well as for developers implementing ciphers. This API
-     specification, however, does not discuss all API calls available
-     to data transformation implementations (i.e. implementations of
-     ciphers and other transformations (such as CRC or even compression
-     algorithms) that can register with the kernel crypto API).
-    </para>
-
-    <para>
-     Note: The terms "transformation" and cipher algorithm are used
-     interchangeably.
-    </para>
-   </sect1>
-
-   <sect1><title>Terminology</title>
-    <para>
-     The transformation implementation is an actual code or interface
-     to hardware which implements a certain transformation with precisely
-     defined behavior.
-    </para>
-
-    <para>
-     The transformation object (TFM) is an instance of a transformation
-     implementation. There can be multiple transformation objects
-     associated with a single transformation implementation. Each of
-     those transformation objects is held by a crypto API consumer or
-     another transformation. Transformation object is allocated when a
-     crypto API consumer requests a transformation implementation.
-     The consumer is then provided with a structure, which contains
-     a transformation object (TFM).
-    </para>
-
-    <para>
-     The structure that contains transformation objects may also be
-     referred to as a "cipher handle". Such a cipher handle is always
-     subject to the following phases that are reflected in the API calls
-     applicable to such a cipher handle:
-    </para>
-
-    <orderedlist>
-     <listitem>
-      <para>Initialization of a cipher handle.</para>
-     </listitem>
-     <listitem>
-      <para>Execution of all intended cipher operations applicable
-      for the handle where the cipher handle must be furnished to
-      every API call.</para>
-     </listitem>
-     <listitem>
-      <para>Destruction of a cipher handle.</para>
-     </listitem>
-    </orderedlist>
-
-    <para>
-     When using the initialization API calls, a cipher handle is
-     created and returned to the consumer. Therefore, please refer
-     to all initialization API calls that refer to the data
-     structure type a consumer is expected to receive and subsequently
-     to use. The initialization API calls have all the same naming
-     conventions of crypto_alloc_*.
-    </para>
-
-    <para>
-     The transformation context is private data associated with
-     the transformation object.
-    </para>
-   </sect1>
-  </chapter>
-
-  <chapter id="Architecture"><title>Kernel Crypto API Architecture</title>
-   <sect1><title>Cipher algorithm types</title>
-    <para>
-     The kernel crypto API provides different API calls for the
-     following cipher types:
-
-     <itemizedlist>
-      <listitem><para>Symmetric ciphers</para></listitem>
-      <listitem><para>AEAD ciphers</para></listitem>
-      <listitem><para>Message digest, including keyed message digest</para></listitem>
-      <listitem><para>Random number generation</para></listitem>
-      <listitem><para>User space interface</para></listitem>
-     </itemizedlist>
-    </para>
-   </sect1>
-
-   <sect1><title>Ciphers And Templates</title>
-    <para>
-     The kernel crypto API provides implementations of single block
-     ciphers and message digests. In addition, the kernel crypto API
-     provides numerous "templates" that can be used in conjunction
-     with the single block ciphers and message digests. Templates
-     include all types of block chaining mode, the HMAC mechanism, etc.
-    </para>
-
-    <para>
-     Single block ciphers and message digests can either be directly
-     used by a caller or invoked together with a template to form
-     multi-block ciphers or keyed message digests.
-    </para>
-
-    <para>
-     A single block cipher may even be called with multiple templates.
-     However, templates cannot be used without a single cipher.
-    </para>
-
-    <para>
-     See /proc/crypto and search for "name". For example:
-
-     <itemizedlist>
-      <listitem><para>aes</para></listitem>
-      <listitem><para>ecb(aes)</para></listitem>
-      <listitem><para>cmac(aes)</para></listitem>
-      <listitem><para>ccm(aes)</para></listitem>
-      <listitem><para>rfc4106(gcm(aes))</para></listitem>
-      <listitem><para>sha1</para></listitem>
-      <listitem><para>hmac(sha1)</para></listitem>
-      <listitem><para>authenc(hmac(sha1),cbc(aes))</para></listitem>
-     </itemizedlist>
-    </para>
-
-    <para>
-     In these examples, "aes" and "sha1" are the ciphers and all
-     others are the templates.
-    </para>
-   </sect1>
-
-   <sect1><title>Synchronous And Asynchronous Operation</title>
-    <para>
-     The kernel crypto API provides synchronous and asynchronous
-     API operations.
-    </para>
-
-    <para>
-     When using the synchronous API operation, the caller invokes
-     a cipher operation which is performed synchronously by the
-     kernel crypto API. That means, the caller waits until the
-     cipher operation completes. Therefore, the kernel crypto API
-     calls work like regular function calls. For synchronous
-     operation, the set of API calls is small and conceptually
-     similar to any other crypto library.
-    </para>
-
-    <para>
-     Asynchronous operation is provided by the kernel crypto API
-     which implies that the invocation of a cipher operation will
-     complete almost instantly. That invocation triggers the
-     cipher operation but it does not signal its completion. Before
-     invoking a cipher operation, the caller must provide a callback
-     function the kernel crypto API can invoke to signal the
-     completion of the cipher operation. Furthermore, the caller
-     must ensure it can handle such asynchronous events by applying
-     appropriate locking around its data. The kernel crypto API
-     does not perform any special serialization operation to protect
-     the caller's data integrity.
-    </para>
-   </sect1>
-
-   <sect1><title>Crypto API Cipher References And Priority</title>
-    <para>
-     A cipher is referenced by the caller with a string. That string
-     has the following semantics:
-
-     <programlisting>
-	template(single block cipher)
-     </programlisting>
-
-     where "template" and "single block cipher" is the aforementioned
-     template and single block cipher, respectively. If applicable,
-     additional templates may enclose other templates, such as
-
-      <programlisting>
-	template1(template2(single block cipher)))
-      </programlisting>
-    </para>
-
-    <para>
-     The kernel crypto API may provide multiple implementations of a
-     template or a single block cipher. For example, AES on newer
-     Intel hardware has the following implementations: AES-NI,
-     assembler implementation, or straight C. Now, when using the
-     string "aes" with the kernel crypto API, which cipher
-     implementation is used? The answer to that question is the
-     priority number assigned to each cipher implementation by the
-     kernel crypto API. When a caller uses the string to refer to a
-     cipher during initialization of a cipher handle, the kernel
-     crypto API looks up all implementations providing an
-     implementation with that name and selects the implementation
-     with the highest priority.
-    </para>
-
-    <para>
-     Now, a caller may have the need to refer to a specific cipher
-     implementation and thus does not want to rely on the
-     priority-based selection. To accommodate this scenario, the
-     kernel crypto API allows the cipher implementation to register
-     a unique name in addition to common names. When using that
-     unique name, a caller is therefore always sure to refer to
-     the intended cipher implementation.
-    </para>
-
-    <para>
-     The list of available ciphers is given in /proc/crypto. However,
-     that list does not specify all possible permutations of
-     templates and ciphers. Each block listed in /proc/crypto may
-     contain the following information -- if one of the components
-     listed as follows are not applicable to a cipher, it is not
-     displayed:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>name: the generic name of the cipher that is subject
-       to the priority-based selection -- this name can be used by
-       the cipher allocation API calls (all names listed above are
-       examples for such generic names)</para>
-     </listitem>
-     <listitem>
-      <para>driver: the unique name of the cipher -- this name can
-       be used by the cipher allocation API calls</para>
-     </listitem>
-     <listitem>
-      <para>module: the kernel module providing the cipher
-       implementation (or "kernel" for statically linked ciphers)</para>
-     </listitem>
-     <listitem>
-      <para>priority: the priority value of the cipher implementation</para>
-     </listitem>
-     <listitem>
-      <para>refcnt: the reference count of the respective cipher
-       (i.e. the number of current consumers of this cipher)</para>
-     </listitem>
-     <listitem>
-      <para>selftest: specification whether the self test for the
-       cipher passed</para>
-     </listitem>
-     <listitem>
-      <para>type:
-       <itemizedlist>
-        <listitem>
-         <para>skcipher for symmetric key ciphers</para>
-        </listitem>
-        <listitem>
-         <para>cipher for single block ciphers that may be used with
-          an additional template</para>
-        </listitem>
-        <listitem>
-         <para>shash for synchronous message digest</para>
-        </listitem>
-        <listitem>
-         <para>ahash for asynchronous message digest</para>
-        </listitem>
-        <listitem>
-         <para>aead for AEAD cipher type</para>
-        </listitem>
-        <listitem>
-         <para>compression for compression type transformations</para>
-        </listitem>
-        <listitem>
-         <para>rng for random number generator</para>
-        </listitem>
-        <listitem>
-         <para>givcipher for cipher with associated IV generator
-          (see the geniv entry below for the specification of the
-          IV generator type used by the cipher implementation)</para>
-        </listitem>
-       </itemizedlist>
-      </para>
-     </listitem>
-     <listitem>
-      <para>blocksize: blocksize of cipher in bytes</para>
-     </listitem>
-     <listitem>
-      <para>keysize: key size in bytes</para>
-     </listitem>
-     <listitem>
-      <para>ivsize: IV size in bytes</para>
-     </listitem>
-     <listitem>
-      <para>seedsize: required size of seed data for random number
-       generator</para>
-     </listitem>
-     <listitem>
-      <para>digestsize: output size of the message digest</para>
-     </listitem>
-     <listitem>
-      <para>geniv: IV generation type:
-       <itemizedlist>
-        <listitem>
-         <para>eseqiv for encrypted sequence number based IV
-          generation</para>
-        </listitem>
-        <listitem>
-         <para>seqiv for sequence number based IV generation</para>
-        </listitem>
-        <listitem>
-         <para>chainiv for chain iv generation</para>
-        </listitem>
-        <listitem>
-         <para>&lt;builtin&gt; is a marker that the cipher implements
-          IV generation and handling as it is specific to the given
-          cipher</para>
-        </listitem>
-       </itemizedlist>
-      </para>
-     </listitem>
-    </itemizedlist>
-   </sect1>
-
-   <sect1><title>Key Sizes</title>
-    <para>
-     When allocating a cipher handle, the caller only specifies the
-     cipher type. Symmetric ciphers, however, typically support
-     multiple key sizes (e.g. AES-128 vs. AES-192 vs. AES-256).
-     These key sizes are determined with the length of the provided
-     key. Thus, the kernel crypto API does not provide a separate
-     way to select the particular symmetric cipher key size.
-    </para>
-   </sect1>
-
-   <sect1><title>Cipher Allocation Type And Masks</title>
-    <para>
-     The different cipher handle allocation functions allow the
-     specification of a type and mask flag. Both parameters have
-     the following meaning (and are therefore not covered in the
-     subsequent sections).
-    </para>
-
-    <para>
-     The type flag specifies the type of the cipher algorithm.
-     The caller usually provides a 0 when the caller wants the
-     default handling. Otherwise, the caller may provide the
-     following selections which match the aforementioned cipher
-     types:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_CIPHER Single block cipher</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_COMPRESS Compression</para>
-     </listitem>
-     <listitem>
-     <para>CRYPTO_ALG_TYPE_AEAD Authenticated Encryption with
-      Associated Data (MAC)</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_BLKCIPHER Synchronous multi-block cipher</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_ABLKCIPHER Asynchronous multi-block cipher</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_GIVCIPHER Asynchronous multi-block
-       cipher packed together with an IV generator (see geniv field
-       in the /proc/crypto listing for the known IV generators)</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_DIGEST Raw message digest</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_HASH Alias for CRYPTO_ALG_TYPE_DIGEST</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_SHASH Synchronous multi-block hash</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_AHASH Asynchronous multi-block hash</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_RNG Random Number Generation</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_AKCIPHER Asymmetric cipher</para>
-     </listitem>
-     <listitem>
-      <para>CRYPTO_ALG_TYPE_PCOMPRESS Enhanced version of
-       CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression /
-       decompression instead of performing the operation on one
-       segment only. CRYPTO_ALG_TYPE_PCOMPRESS is intended to replace
-       CRYPTO_ALG_TYPE_COMPRESS once existing consumers are converted.</para>
-     </listitem>
-    </itemizedlist>
-
-    <para>
-     The mask flag restricts the type of cipher. The only allowed
-     flag is CRYPTO_ALG_ASYNC to restrict the cipher lookup function
-     to asynchronous ciphers. Usually, a caller provides a 0 for the
-     mask flag.
-    </para>
-
-    <para>
-     When the caller provides a mask and type specification, the
-     caller limits the search the kernel crypto API can perform for
-     a suitable cipher implementation for the given cipher name.
-     That means, even when a caller uses a cipher name that exists
-     during its initialization call, the kernel crypto API may not
-     select it due to the used type and mask field.
-    </para>
-   </sect1>
-
-   <sect1><title>Internal Structure of Kernel Crypto API</title>
-
-    <para>
-     The kernel crypto API has an internal structure where a cipher
-     implementation may use many layers and indirections. This section
-     shall help to clarify how the kernel crypto API uses
-     various components to implement the complete cipher.
-    </para>
-
-    <para>
-     The following subsections explain the internal structure based
-     on existing cipher implementations. The first section addresses
-     the most complex scenario where all other scenarios form a logical
-     subset.
-    </para>
-
-    <sect2><title>Generic AEAD Cipher Structure</title>
-
-     <para>
-      The following ASCII art decomposes the kernel crypto API layers
-      when using the AEAD cipher with the automated IV generation. The
-      shown example is used by the IPSEC layer.
-     </para>
-
-     <para>
-      For other use cases of AEAD ciphers, the ASCII art applies as
-      well, but the caller may not use the AEAD cipher with a separate
-      IV generator. In this case, the caller must generate the IV.
-     </para>
-
-     <para>
-      The depicted example decomposes the AEAD cipher of GCM(AES) based
-      on the generic C implementations (gcm.c, aes-generic.c, ctr.c,
-      ghash-generic.c, seqiv.c). The generic implementation serves as an
-      example showing the complete logic of the kernel crypto API.
-     </para>
-
-     <para>
-      It is possible that some streamlined cipher implementations (like
-      AES-NI) provide implementations merging aspects which in the view
-      of the kernel crypto API cannot be decomposed into layers any more.
-      In case of the AES-NI implementation, the CTR mode, the GHASH
-      implementation and the AES cipher are all merged into one cipher
-      implementation registered with the kernel crypto API. In this case,
-      the concept described by the following ASCII art applies too. However,
-      the decomposition of GCM into the individual sub-components
-      by the kernel crypto API is not done any more.
-     </para>
-
-     <para>
-      Each block in the following ASCII art is an independent cipher
-      instance obtained from the kernel crypto API. Each block
-      is accessed by the caller or by other blocks using the API functions
-      defined by the kernel crypto API for the cipher implementation type.
-     </para>
-
-     <para>
-      The blocks below indicate the cipher type as well as the specific
-      logic implemented in the cipher.
-     </para>
-
-     <para>
-      The ASCII art picture also indicates the call structure, i.e. who
-      calls which component. The arrows point to the invoked block
-      where the caller uses the API applicable to the cipher type
-      specified for the block.
-     </para>
-
-     <programlisting>
-<![CDATA[
-kernel crypto API                                |   IPSEC Layer
-                                                 |
-+-----------+                                    |
-|           |            (1)
-|   aead    | <-----------------------------------  esp_output
-|  (seqiv)  | ---+
-+-----------+    |
-                 | (2)
-+-----------+    |
-|           | <--+                (2)
-|   aead    | <-----------------------------------  esp_input
-|   (gcm)   | ------------+
-+-----------+             |
-      | (3)               | (5)
-      v                   v
-+-----------+       +-----------+
-|           |       |           |
-|  skcipher |       |   ahash   |
-|   (ctr)   | ---+  |  (ghash)  |
-+-----------+    |  +-----------+
-                 |
-+-----------+    | (4)
-|           | <--+
-|   cipher  |
-|   (aes)   |
-+-----------+
-]]>
-     </programlisting>
-
-     <para>
-      The following call sequence is applicable when the IPSEC layer
-      triggers an encryption operation with the esp_output function. During
-      configuration, the administrator set up the use of rfc4106(gcm(aes)) as
-      the cipher for ESP. The following call sequence is now depicted in the
-      ASCII art above:
-     </para>
-
-     <orderedlist>
-      <listitem>
-       <para>
-        esp_output() invokes crypto_aead_encrypt() to trigger an encryption
-        operation of the AEAD cipher with IV generator.
-       </para>
-
-       <para>
-        In case of GCM, the SEQIV implementation is registered as GIVCIPHER
-        in crypto_rfc4106_alloc().
-       </para>
-
-       <para>
-        The SEQIV performs its operation to generate an IV where the core
-        function is seqiv_geniv().
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        Now, SEQIV uses the AEAD API function calls to invoke the associated
-        AEAD cipher. In our case, during the instantiation of SEQIV, the
-        cipher handle for GCM is provided to SEQIV. This means that SEQIV
-        invokes AEAD cipher operations with the GCM cipher handle.
-       </para>
-
-       <para>
-        During instantiation of the GCM handle, the CTR(AES) and GHASH
-        ciphers are instantiated. The cipher handles for CTR(AES) and GHASH
-        are retained for later use.
-       </para>
-
-       <para>
-        The GCM implementation is responsible to invoke the CTR mode AES and
-        the GHASH cipher in the right manner to implement the GCM
-        specification.
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        The GCM AEAD cipher type implementation now invokes the SKCIPHER API
-        with the instantiated CTR(AES) cipher handle.
-       </para>
-
-       <para>
-	During instantiation of the CTR(AES) cipher, the CIPHER type
-	implementation of AES is instantiated. The cipher handle for AES is
-	retained.
-       </para>
-
-       <para>
-        That means that the SKCIPHER implementation of CTR(AES) only
-        implements the CTR block chaining mode. After performing the block
-        chaining operation, the CIPHER implementation of AES is invoked.
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        The SKCIPHER of CTR(AES) now invokes the CIPHER API with the AES
-        cipher handle to encrypt one block.
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        The GCM AEAD implementation also invokes the GHASH cipher
-        implementation via the AHASH API.
-       </para>
-      </listitem>
-     </orderedlist>
-
-     <para>
-      When the IPSEC layer triggers the esp_input() function, the same call
-      sequence is followed with the only difference that the operation starts
-      with step (2).
-     </para>
-    </sect2>
-
-    <sect2><title>Generic Block Cipher Structure</title>
-     <para>
-      Generic block ciphers follow the same concept as depicted with the ASCII
-      art picture above.
-     </para>
-
-     <para>
-      For example, CBC(AES) is implemented with cbc.c, and aes-generic.c. The
-      ASCII art picture above applies as well with the difference that only
-      step (4) is used and the SKCIPHER block chaining mode is CBC.
-     </para>
-    </sect2>
-
-    <sect2><title>Generic Keyed Message Digest Structure</title>
-     <para>
-      Keyed message digest implementations again follow the same concept as
-      depicted in the ASCII art picture above.
-     </para>
-
-     <para>
-      For example, HMAC(SHA256) is implemented with hmac.c and
-      sha256_generic.c. The following ASCII art illustrates the
-      implementation:
-     </para>
-
-     <programlisting>
-<![CDATA[
-kernel crypto API            |       Caller
-                             |
-+-----------+         (1)    |
-|           | <------------------  some_function
-|   ahash   |
-|   (hmac)  | ---+
-+-----------+    |
-                 | (2)
-+-----------+    |
-|           | <--+
-|   shash   |
-|  (sha256) |
-+-----------+
-]]>
-     </programlisting>
-
-     <para>
-      The following call sequence is applicable when a caller triggers
-      an HMAC operation:
-     </para>
-
-     <orderedlist>
-      <listitem>
-       <para>
-        The AHASH API functions are invoked by the caller. The HMAC
-        implementation performs its operation as needed.
-       </para>
-
-       <para>
-        During initialization of the HMAC cipher, the SHASH cipher type of
-        SHA256 is instantiated. The cipher handle for the SHA256 instance is
-        retained.
-       </para>
-
-       <para>
-        At one time, the HMAC implementation requires a SHA256 operation
-        where the SHA256 cipher handle is used.
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        The HMAC instance now invokes the SHASH API with the SHA256
-        cipher handle to calculate the message digest.
-       </para>
-      </listitem>
-     </orderedlist>
-    </sect2>
-   </sect1>
-  </chapter>
-
-  <chapter id="Development"><title>Developing Cipher Algorithms</title>
-   <sect1><title>Registering And Unregistering Transformation</title>
-    <para>
-     There are three distinct types of registration functions in
-     the Crypto API. One is used to register a generic cryptographic
-     transformation, while the other two are specific to HASH
-     transformations and COMPRESSion. We will discuss the latter
-     two in a separate chapter, here we will only look at the
-     generic ones.
-    </para>
-
-    <para>
-     Before discussing the register functions, the data structure
-     to be filled with each, struct crypto_alg, must be considered
-     -- see below for a description of this data structure.
-    </para>
-
-    <para>
-     The generic registration functions can be found in
-     include/linux/crypto.h and their definition can be seen below.
-     The former function registers a single transformation, while
-     the latter works on an array of transformation descriptions.
-     The latter is useful when registering transformations in bulk,
-     for example when a driver implements multiple transformations.
-    </para>
-
-    <programlisting>
-   int crypto_register_alg(struct crypto_alg *alg);
-   int crypto_register_algs(struct crypto_alg *algs, int count);
-    </programlisting>
-
-    <para>
-     The counterparts to those functions are listed below.
-    </para>
-
-    <programlisting>
-   int crypto_unregister_alg(struct crypto_alg *alg);
-   int crypto_unregister_algs(struct crypto_alg *algs, int count);
-    </programlisting>
-
-    <para>
-     Notice that both registration and unregistration functions
-     do return a value, so make sure to handle errors. A return
-     code of zero implies success. Any return code &lt; 0 implies
-     an error.
-    </para>
-
-    <para>
-     The bulk registration/unregistration functions
-     register/unregister each transformation in the given array of
-     length count.  They handle errors as follows:
-    </para>
-    <itemizedlist>
-     <listitem>
-      <para>
-       crypto_register_algs() succeeds if and only if it
-       successfully registers all the given transformations. If an
-       error occurs partway through, then it rolls back successful
-       registrations before returning the error code. Note that if
-       a driver needs to handle registration errors for individual
-       transformations, then it will need to use the non-bulk
-       function crypto_register_alg() instead.
-      </para>
-     </listitem>
-     <listitem>
-      <para>
-       crypto_unregister_algs() tries to unregister all the given
-       transformations, continuing on error. It logs errors and
-       always returns zero.
-      </para>
-     </listitem>
-    </itemizedlist>
-
-   </sect1>
-
-   <sect1><title>Single-Block Symmetric Ciphers [CIPHER]</title>
-    <para>
-     Example of transformations: aes, arc4, ...
-    </para>
-
-    <para>
-     This section describes the simplest of all transformation
-     implementations, that being the CIPHER type used for symmetric
-     ciphers. The CIPHER type is used for transformations which
-     operate on exactly one block at a time and there are no
-     dependencies between blocks at all.
-    </para>
-
-    <sect2><title>Registration specifics</title>
-     <para>
-      The registration of [CIPHER] algorithm is specific in that
-      struct crypto_alg field .cra_type is empty. The .cra_u.cipher
-      has to be filled in with proper callbacks to implement this
-      transformation.
-     </para>
-
-     <para>
-      See struct cipher_alg below.
-     </para>
-    </sect2>
-
-    <sect2><title>Cipher Definition With struct cipher_alg</title>
-     <para>
-      Struct cipher_alg defines a single block cipher.
-     </para>
-
-     <para>
-      Here are schematics of how these functions are called when
-      operated from other part of the kernel. Note that the
-      .cia_setkey() call might happen before or after any of these
-      schematics happen, but must not happen during any of these
-      are in-flight.
-     </para>
-
-     <para>
-      <programlisting>
-         KEY ---.    PLAINTEXT ---.
-                v                 v
-          .cia_setkey() -&gt; .cia_encrypt()
-                                  |
-                                  '-----&gt; CIPHERTEXT
-      </programlisting>
-     </para>
-
-     <para>
-      Please note that a pattern where .cia_setkey() is called
-      multiple times is also valid:
-     </para>
-
-     <para>
-      <programlisting>
-
-  KEY1 --.    PLAINTEXT1 --.         KEY2 --.    PLAINTEXT2 --.
-         v                 v                v                 v
-   .cia_setkey() -&gt; .cia_encrypt() -&gt; .cia_setkey() -&gt; .cia_encrypt()
-                           |                                  |
-                           '---&gt; CIPHERTEXT1                  '---&gt; CIPHERTEXT2
-      </programlisting>
-     </para>
-
-    </sect2>
-   </sect1>
-
-   <sect1><title>Multi-Block Ciphers</title>
-    <para>
-     Example of transformations: cbc(aes), ecb(arc4), ...
-    </para>
-
-    <para>
-     This section describes the multi-block cipher transformation
-     implementations. The multi-block ciphers are
-     used for transformations which operate on scatterlists of
-     data supplied to the transformation functions. They output
-     the result into a scatterlist of data as well.
-    </para>
-
-    <sect2><title>Registration Specifics</title>
-
-     <para>
-      The registration of multi-block cipher algorithms
-      is one of the most standard procedures throughout the crypto API.
-     </para>
-
-     <para>
-      Note, if a cipher implementation requires a proper alignment
-      of data, the caller should use the functions of
-      crypto_skcipher_alignmask() to identify a memory alignment mask.
-      The kernel crypto API is able to process requests that are unaligned.
-      This implies, however, additional overhead as the kernel
-      crypto API needs to perform the realignment of the data which
-      may imply moving of data.
-     </para>
-    </sect2>
-
-    <sect2><title>Cipher Definition With struct blkcipher_alg and ablkcipher_alg</title>
-     <para>
-      Struct blkcipher_alg defines a synchronous block cipher whereas
-      struct ablkcipher_alg defines an asynchronous block cipher.
-     </para>
-
-     <para>
-      Please refer to the single block cipher description for schematics
-      of the block cipher usage.
-     </para>
-    </sect2>
-
-    <sect2><title>Specifics Of Asynchronous Multi-Block Cipher</title>
-     <para>
-      There are a couple of specifics to the asynchronous interface.
-     </para>
-
-     <para>
-      First of all, some of the drivers will want to use the
-      Generic ScatterWalk in case the hardware needs to be fed
-      separate chunks of the scatterlist which contains the
-      plaintext and will contain the ciphertext. Please refer
-      to the ScatterWalk interface offered by the Linux kernel
-      scatter / gather list implementation.
-     </para>
-    </sect2>
-   </sect1>
-
-   <sect1><title>Hashing [HASH]</title>
-
-    <para>
-     Example of transformations: crc32, md5, sha1, sha256,...
-    </para>
-
-    <sect2><title>Registering And Unregistering The Transformation</title>
-
-     <para>
-      There are multiple ways to register a HASH transformation,
-      depending on whether the transformation is synchronous [SHASH]
-      or asynchronous [AHASH] and the amount of HASH transformations
-      we are registering. You can find the prototypes defined in
-      include/crypto/internal/hash.h:
-     </para>
-
-     <programlisting>
-   int crypto_register_ahash(struct ahash_alg *alg);
-
-   int crypto_register_shash(struct shash_alg *alg);
-   int crypto_register_shashes(struct shash_alg *algs, int count);
-     </programlisting>
-
-     <para>
-      The respective counterparts for unregistering the HASH
-      transformation are as follows:
-     </para>
-
-     <programlisting>
-   int crypto_unregister_ahash(struct ahash_alg *alg);
-
-   int crypto_unregister_shash(struct shash_alg *alg);
-   int crypto_unregister_shashes(struct shash_alg *algs, int count);
-     </programlisting>
-    </sect2>
-
-    <sect2><title>Cipher Definition With struct shash_alg and ahash_alg</title>
-     <para>
-      Here are schematics of how these functions are called when
-      operated from other part of the kernel. Note that the .setkey()
-      call might happen before or after any of these schematics happen,
-      but must not happen during any of these are in-flight. Please note
-      that calling .init() followed immediately by .finish() is also a
-      perfectly valid transformation.
-     </para>
-
-     <programlisting>
-   I)   DATA -----------.
-                        v
-         .init() -&gt; .update() -&gt; .final()      ! .update() might not be called
-                     ^    |         |            at all in this scenario.
-                     '----'         '---&gt; HASH
-
-   II)  DATA -----------.-----------.
-                        v           v
-         .init() -&gt; .update() -&gt; .finup()      ! .update() may not be called
-                     ^    |         |            at all in this scenario.
-                     '----'         '---&gt; HASH
-
-   III) DATA -----------.
-                        v
-                    .digest()                  ! The entire process is handled
-                        |                        by the .digest() call.
-                        '---------------&gt; HASH
-     </programlisting>
-
-     <para>
-      Here is a schematic of how the .export()/.import() functions are
-      called when used from another part of the kernel.
-     </para>
-
-     <programlisting>
-   KEY--.                 DATA--.
-        v                       v                  ! .update() may not be called
-    .setkey() -&gt; .init() -&gt; .update() -&gt; .export()   at all in this scenario.
-                             ^     |         |
-                             '-----'         '--&gt; PARTIAL_HASH
-
-   ----------- other transformations happen here -----------
-
-   PARTIAL_HASH--.   DATA1--.
-                 v          v
-             .import -&gt; .update() -&gt; .final()     ! .update() may not be called
-                         ^    |         |           at all in this scenario.
-                         '----'         '--&gt; HASH1
-
-   PARTIAL_HASH--.   DATA2-.
-                 v         v
-             .import -&gt; .finup()
-                           |
-                           '---------------&gt; HASH2
-     </programlisting>
-    </sect2>
-
-    <sect2><title>Specifics Of Asynchronous HASH Transformation</title>
-     <para>
-      Some of the drivers will want to use the Generic ScatterWalk
-      in case the implementation needs to be fed separate chunks of the
-      scatterlist which contains the input data. The buffer containing
-      the resulting hash will always be properly aligned to
-      .cra_alignmask so there is no need to worry about this.
-     </para>
-    </sect2>
-   </sect1>
-  </chapter>
-
-  <chapter id="User"><title>User Space Interface</title>
-   <sect1><title>Introduction</title>
-    <para>
-     The concepts of the kernel crypto API visible to kernel space is fully
-     applicable to the user space interface as well. Therefore, the kernel
-     crypto API high level discussion for the in-kernel use cases applies
-     here as well.
-    </para>
-
-    <para>
-     The major difference, however, is that user space can only act as a
-     consumer and never as a provider of a transformation or cipher algorithm.
-    </para>
-
-    <para>
-     The following covers the user space interface exported by the kernel
-     crypto API. A working example of this description is libkcapi that
-     can be obtained from [1]. That library can be used by user space
-     applications that require cryptographic services from the kernel.
-    </para>
-
-    <para>
-     Some details of the in-kernel kernel crypto API aspects do not
-     apply to user space, however. This includes the difference between
-     synchronous and asynchronous invocations. The user space API call
-     is fully synchronous.
-    </para>
-
-    <para>
-     [1] <ulink url="http://www.chronox.de/libkcapi.html">http://www.chronox.de/libkcapi.html</ulink>
-    </para>
-
-   </sect1>
-
-   <sect1><title>User Space API General Remarks</title>
-    <para>
-     The kernel crypto API is accessible from user space. Currently,
-     the following ciphers are accessible:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>Message digest including keyed message digest (HMAC, CMAC)</para>
-     </listitem>
-
-     <listitem>
-      <para>Symmetric ciphers</para>
-     </listitem>
-
-     <listitem>
-      <para>AEAD ciphers</para>
-     </listitem>
-
-     <listitem>
-      <para>Random Number Generators</para>
-     </listitem>
-    </itemizedlist>
-
-    <para>
-     The interface is provided via socket type using the type AF_ALG.
-     In addition, the setsockopt option type is SOL_ALG. In case the
-     user space header files do not export these flags yet, use the
-     following macros:
-    </para>
-
-    <programlisting>
-#ifndef AF_ALG
-#define AF_ALG 38
-#endif
-#ifndef SOL_ALG
-#define SOL_ALG 279
-#endif
-    </programlisting>
-
-    <para>
-     A cipher is accessed with the same name as done for the in-kernel
-     API calls. This includes the generic vs. unique naming schema for
-     ciphers as well as the enforcement of priorities for generic names.
-    </para>
-
-    <para>
-     To interact with the kernel crypto API, a socket must be
-     created by the user space application. User space invokes the cipher
-     operation with the send()/write() system call family. The result of the
-     cipher operation is obtained with the read()/recv() system call family.
-    </para>
-
-    <para>
-     The following API calls assume that the socket descriptor
-     is already opened by the user space application and discusses only
-     the kernel crypto API specific invocations.
-    </para>
-
-    <para>
-     To initialize the socket interface, the following sequence has to
-     be performed by the consumer:
-    </para>
-
-    <orderedlist>
-     <listitem>
-      <para>
-       Create a socket of type AF_ALG with the struct sockaddr_alg
-       parameter specified below for the different cipher types.
-      </para>
-     </listitem>
-
-     <listitem>
-      <para>
-       Invoke bind with the socket descriptor
-      </para>
-     </listitem>
-
-     <listitem>
-      <para>
-       Invoke accept with the socket descriptor. The accept system call
-       returns a new file descriptor that is to be used to interact with
-       the particular cipher instance. When invoking send/write or recv/read
-       system calls to send data to the kernel or obtain data from the
-       kernel, the file descriptor returned by accept must be used.
-      </para>
-     </listitem>
-    </orderedlist>
-   </sect1>
-
-   <sect1><title>In-place Cipher operation</title>
-    <para>
-     Just like the in-kernel operation of the kernel crypto API, the user
-     space interface allows the cipher operation in-place. That means that
-     the input buffer used for the send/write system call and the output
-     buffer used by the read/recv system call may be one and the same.
-     This is of particular interest for symmetric cipher operations where a
-     copying of the output data to its final destination can be avoided.
-    </para>
-
-    <para>
-     If a consumer on the other hand wants to maintain the plaintext and
-     the ciphertext in different memory locations, all a consumer needs
-     to do is to provide different memory pointers for the encryption and
-     decryption operation.
-    </para>
-   </sect1>
-
-   <sect1><title>Message Digest API</title>
-    <para>
-     The message digest type to be used for the cipher operation is
-     selected when invoking the bind syscall. bind requires the caller
-     to provide a filled struct sockaddr data structure. This data
-     structure must be filled as follows:
-    </para>
-
-    <programlisting>
-struct sockaddr_alg sa = {
-	.salg_family = AF_ALG,
-	.salg_type = "hash", /* this selects the hash logic in the kernel */
-	.salg_name = "sha1" /* this is the cipher name */
-};
-    </programlisting>
-
-    <para>
-     The salg_type value "hash" applies to message digests and keyed
-     message digests. Though, a keyed message digest is referenced by
-     the appropriate salg_name. Please see below for the setsockopt
-     interface that explains how the key can be set for a keyed message
-     digest.
-    </para>
-
-    <para>
-     Using the send() system call, the application provides the data that
-     should be processed with the message digest. The send system call
-     allows the following flags to be specified:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>
-       MSG_MORE: If this flag is set, the send system call acts like a
-       message digest update function where the final hash is not
-       yet calculated. If the flag is not set, the send system call
-       calculates the final message digest immediately.
-      </para>
-     </listitem>
-    </itemizedlist>
-
-    <para>
-     With the recv() system call, the application can read the message
-     digest from the kernel crypto API. If the buffer is too small for the
-     message digest, the flag MSG_TRUNC is set by the kernel.
-    </para>
-
-    <para>
-     In order to set a message digest key, the calling application must use
-     the setsockopt() option of ALG_SET_KEY. If the key is not set the HMAC
-     operation is performed without the initial HMAC state change caused by
-     the key.
-    </para>
-   </sect1>
-
-   <sect1><title>Symmetric Cipher API</title>
-    <para>
-     The operation is very similar to the message digest discussion.
-     During initialization, the struct sockaddr data structure must be
-     filled as follows:
-    </para>
-
-    <programlisting>
-struct sockaddr_alg sa = {
-	.salg_family = AF_ALG,
-	.salg_type = "skcipher", /* this selects the symmetric cipher */
-	.salg_name = "cbc(aes)" /* this is the cipher name */
-};
-    </programlisting>
-
-    <para>
-     Before data can be sent to the kernel using the write/send system
-     call family, the consumer must set the key. The key setting is
-     described with the setsockopt invocation below.
-    </para>
-
-    <para>
-     Using the sendmsg() system call, the application provides the data that should be processed for encryption or decryption. In addition, the IV is
-     specified with the data structure provided by the sendmsg() system call.
-    </para>
-
-    <para>
-     The sendmsg system call parameter of struct msghdr is embedded into the
-     struct cmsghdr data structure. See recv(2) and cmsg(3) for more
-     information on how the cmsghdr data structure is used together with the
-     send/recv system call family. That cmsghdr data structure holds the
-     following information specified with a separate header instances:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>
-       specification of the cipher operation type with one of these flags:
-      </para>
-      <itemizedlist>
-       <listitem>
-        <para>ALG_OP_ENCRYPT - encryption of data</para>
-       </listitem>
-       <listitem>
-        <para>ALG_OP_DECRYPT - decryption of data</para>
-       </listitem>
-      </itemizedlist>
-     </listitem>
-
-     <listitem>
-      <para>
-       specification of the IV information marked with the flag ALG_SET_IV
-      </para>
-     </listitem>
-    </itemizedlist>
-
-    <para>
-     The send system call family allows the following flag to be specified:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>
-       MSG_MORE: If this flag is set, the send system call acts like a
-       cipher update function where more input data is expected
-       with a subsequent invocation of the send system call.
-      </para>
-     </listitem>
-    </itemizedlist>
-
-    <para>
-     Note: The kernel reports -EINVAL for any unexpected data. The caller
-     must make sure that all data matches the constraints given in
-     /proc/crypto for the selected cipher.
-    </para>
-
-    <para>
-     With the recv() system call, the application can read the result of
-     the cipher operation from the kernel crypto API. The output buffer
-     must be at least as large as to hold all blocks of the encrypted or
-     decrypted data. If the output data size is smaller, only as many
-     blocks are returned that fit into that output buffer size.
-    </para>
-   </sect1>
-
-   <sect1><title>AEAD Cipher API</title>
-    <para>
-     The operation is very similar to the symmetric cipher discussion.
-     During initialization, the struct sockaddr data structure must be
-     filled as follows:
-    </para>
-
-    <programlisting>
-struct sockaddr_alg sa = {
-	.salg_family = AF_ALG,
-	.salg_type = "aead", /* this selects the symmetric cipher */
-	.salg_name = "gcm(aes)" /* this is the cipher name */
-};
-    </programlisting>
-
-    <para>
-     Before data can be sent to the kernel using the write/send system
-     call family, the consumer must set the key. The key setting is
-     described with the setsockopt invocation below.
-    </para>
-
-    <para>
-     In addition, before data can be sent to the kernel using the
-     write/send system call family, the consumer must set the authentication
-     tag size. To set the authentication tag size, the caller must use the
-     setsockopt invocation described below.
-    </para>
-
-    <para>
-     Using the sendmsg() system call, the application provides the data that should be processed for encryption or decryption. In addition, the IV is
-     specified with the data structure provided by the sendmsg() system call.
-    </para>
-
-    <para>
-     The sendmsg system call parameter of struct msghdr is embedded into the
-     struct cmsghdr data structure. See recv(2) and cmsg(3) for more
-     information on how the cmsghdr data structure is used together with the
-     send/recv system call family. That cmsghdr data structure holds the
-     following information specified with a separate header instances:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>
-       specification of the cipher operation type with one of these flags:
-      </para>
-      <itemizedlist>
-       <listitem>
-        <para>ALG_OP_ENCRYPT - encryption of data</para>
-       </listitem>
-       <listitem>
-        <para>ALG_OP_DECRYPT - decryption of data</para>
-       </listitem>
-      </itemizedlist>
-     </listitem>
-
-     <listitem>
-      <para>
-       specification of the IV information marked with the flag ALG_SET_IV
-      </para>
-     </listitem>
-
-     <listitem>
-      <para>
-       specification of the associated authentication data (AAD) with the
-       flag ALG_SET_AEAD_ASSOCLEN. The AAD is sent to the kernel together
-       with the plaintext / ciphertext. See below for the memory structure.
-      </para>
-     </listitem>
-    </itemizedlist>
-
-    <para>
-     The send system call family allows the following flag to be specified:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>
-       MSG_MORE: If this flag is set, the send system call acts like a
-       cipher update function where more input data is expected
-       with a subsequent invocation of the send system call.
-      </para>
-     </listitem>
-    </itemizedlist>
-
-    <para>
-     Note: The kernel reports -EINVAL for any unexpected data. The caller
-     must make sure that all data matches the constraints given in
-     /proc/crypto for the selected cipher.
-    </para>
-
-    <para>
-     With the recv() system call, the application can read the result of
-     the cipher operation from the kernel crypto API. The output buffer
-     must be at least as large as defined with the memory structure below.
-     If the output data size is smaller, the cipher operation is not performed.
-    </para>
-
-    <para>
-     The authenticated decryption operation may indicate an integrity error.
-     Such breach in integrity is marked with the -EBADMSG error code.
-    </para>
-
-    <sect2><title>AEAD Memory Structure</title>
-     <para>
-      The AEAD cipher operates with the following information that
-      is communicated between user and kernel space as one data stream:
-     </para>
-
-     <itemizedlist>
-      <listitem>
-       <para>plaintext or ciphertext</para>
-      </listitem>
-
-      <listitem>
-       <para>associated authentication data (AAD)</para>
-      </listitem>
-
-      <listitem>
-       <para>authentication tag</para>
-      </listitem>
-     </itemizedlist>
-
-     <para>
-      The sizes of the AAD and the authentication tag are provided with
-      the sendmsg and setsockopt calls (see there). As the kernel knows
-      the size of the entire data stream, the kernel is now able to
-      calculate the right offsets of the data components in the data
-      stream.
-     </para>
-
-     <para>
-      The user space caller must arrange the aforementioned information
-      in the following order:
-     </para>
-
-     <itemizedlist>
-      <listitem>
-       <para>
-        AEAD encryption input: AAD || plaintext
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        AEAD decryption input: AAD || ciphertext || authentication tag
-       </para>
-      </listitem>
-     </itemizedlist>
-
-     <para>
-      The output buffer the user space caller provides must be at least as
-      large to hold the following data:
-     </para>
-
-     <itemizedlist>
-      <listitem>
-       <para>
-        AEAD encryption output: ciphertext || authentication tag
-       </para>
-      </listitem>
-
-      <listitem>
-       <para>
-        AEAD decryption output: plaintext
-       </para>
-      </listitem>
-     </itemizedlist>
-    </sect2>
-   </sect1>
-
-   <sect1><title>Random Number Generator API</title>
-    <para>
-     Again, the operation is very similar to the other APIs.
-     During initialization, the struct sockaddr data structure must be
-     filled as follows:
-    </para>
-
-    <programlisting>
-struct sockaddr_alg sa = {
-	.salg_family = AF_ALG,
-	.salg_type = "rng", /* this selects the symmetric cipher */
-	.salg_name = "drbg_nopr_sha256" /* this is the cipher name */
-};
-    </programlisting>
-
-    <para>
-     Depending on the RNG type, the RNG must be seeded. The seed is provided
-     using the setsockopt interface to set the key. For example, the
-     ansi_cprng requires a seed. The DRBGs do not require a seed, but
-     may be seeded.
-    </para>
-
-    <para>
-     Using the read()/recvmsg() system calls, random numbers can be obtained.
-     The kernel generates at most 128 bytes in one call. If user space
-     requires more data, multiple calls to read()/recvmsg() must be made.
-    </para>
-
-    <para>
-     WARNING: The user space caller may invoke the initially mentioned
-     accept system call multiple times. In this case, the returned file
-     descriptors have the same state.
-    </para>
-
-   </sect1>
-
-   <sect1><title>Zero-Copy Interface</title>
-    <para>
-     In addition to the send/write/read/recv system call family, the AF_ALG
-     interface can be accessed with the zero-copy interface of splice/vmsplice.
-     As the name indicates, the kernel tries to avoid a copy operation into
-     kernel space.
-    </para>
-
-    <para>
-     The zero-copy operation requires data to be aligned at the page boundary.
-     Non-aligned data can be used as well, but may require more operations of
-     the kernel which would defeat the speed gains obtained from the zero-copy
-     interface.
-    </para>
-
-    <para>
-     The system-interent limit for the size of one zero-copy operation is
-     16 pages. If more data is to be sent to AF_ALG, user space must slice
-     the input into segments with a maximum size of 16 pages.
-    </para>
-
-    <para>
-     Zero-copy can be used with the following code example (a complete working
-     example is provided with libkcapi):
-    </para>
-
-    <programlisting>
-int pipes[2];
-
-pipe(pipes);
-/* input data in iov */
-vmsplice(pipes[1], iov, iovlen, SPLICE_F_GIFT);
-/* opfd is the file descriptor returned from accept() system call */
-splice(pipes[0], NULL, opfd, NULL, ret, 0);
-read(opfd, out, outlen);
-    </programlisting>
-
-   </sect1>
-
-   <sect1><title>Setsockopt Interface</title>
-    <para>
-     In addition to the read/recv and send/write system call handling
-     to send and retrieve data subject to the cipher operation, a consumer
-     also needs to set the additional information for the cipher operation.
-     This additional information is set using the setsockopt system call
-     that must be invoked with the file descriptor of the open cipher
-     (i.e. the file descriptor returned by the accept system call).
-    </para>
-
-    <para>
-     Each setsockopt invocation must use the level SOL_ALG.
-    </para>
-
-    <para>
-     The setsockopt interface allows setting the following data using
-     the mentioned optname:
-    </para>
-
-    <itemizedlist>
-     <listitem>
-      <para>
-       ALG_SET_KEY -- Setting the key. Key setting is applicable to:
-      </para>
-      <itemizedlist>
-       <listitem>
-        <para>the skcipher cipher type (symmetric ciphers)</para>
-       </listitem>
-       <listitem>
-        <para>the hash cipher type (keyed message digests)</para>
-       </listitem>
-       <listitem>
-        <para>the AEAD cipher type</para>
-       </listitem>
-       <listitem>
-        <para>the RNG cipher type to provide the seed</para>
-       </listitem>
-      </itemizedlist>
-     </listitem>
-
-     <listitem>
-      <para>
-       ALG_SET_AEAD_AUTHSIZE -- Setting the authentication tag size
-       for AEAD ciphers. For a encryption operation, the authentication
-       tag of the given size will be generated. For a decryption operation,
-       the provided ciphertext is assumed to contain an authentication tag
-       of the given size (see section about AEAD memory layout below).
-      </para>
-     </listitem>
-    </itemizedlist>
-
-   </sect1>
-
-   <sect1><title>User space API example</title>
-    <para>
-     Please see [1] for libkcapi which provides an easy-to-use wrapper
-     around the aforementioned Netlink kernel interface. [1] also contains
-     a test application that invokes all libkcapi API calls.
-    </para>
-
-    <para>
-     [1] <ulink url="http://www.chronox.de/libkcapi.html">http://www.chronox.de/libkcapi.html</ulink>
-    </para>
-
-   </sect1>
-
-  </chapter>
-
-  <chapter id="API"><title>Programming Interface</title>
-   <para>
-    Please note that the kernel crypto API contains the AEAD givcrypt
-    API (crypto_aead_giv* and aead_givcrypt_* function calls in
-    include/crypto/aead.h). This API is obsolete and will be removed
-    in the future. To obtain the functionality of an AEAD cipher with
-    internal IV generation, use the IV generator as a regular cipher.
-    For example, rfc4106(gcm(aes)) is the AEAD cipher with external
-    IV generation and seqniv(rfc4106(gcm(aes))) implies that the kernel
-    crypto API generates the IV. Different IV generators are available.
-   </para>
-   <sect1><title>Block Cipher Context Data Structures</title>
-!Pinclude/linux/crypto.h Block Cipher Context Data Structures
-!Finclude/crypto/aead.h aead_request
-   </sect1>
-   <sect1><title>Block Cipher Algorithm Definitions</title>
-!Pinclude/linux/crypto.h Block Cipher Algorithm Definitions
-!Finclude/linux/crypto.h crypto_alg
-!Finclude/linux/crypto.h ablkcipher_alg
-!Finclude/crypto/aead.h aead_alg
-!Finclude/linux/crypto.h blkcipher_alg
-!Finclude/linux/crypto.h cipher_alg
-!Finclude/crypto/rng.h rng_alg
-   </sect1>
-   <sect1><title>Symmetric Key Cipher API</title>
-!Pinclude/crypto/skcipher.h Symmetric Key Cipher API
-!Finclude/crypto/skcipher.h crypto_alloc_skcipher
-!Finclude/crypto/skcipher.h crypto_free_skcipher
-!Finclude/crypto/skcipher.h crypto_has_skcipher
-!Finclude/crypto/skcipher.h crypto_skcipher_ivsize
-!Finclude/crypto/skcipher.h crypto_skcipher_blocksize
-!Finclude/crypto/skcipher.h crypto_skcipher_setkey
-!Finclude/crypto/skcipher.h crypto_skcipher_reqtfm
-!Finclude/crypto/skcipher.h crypto_skcipher_encrypt
-!Finclude/crypto/skcipher.h crypto_skcipher_decrypt
-   </sect1>
-   <sect1><title>Symmetric Key Cipher Request Handle</title>
-!Pinclude/crypto/skcipher.h Symmetric Key Cipher Request Handle
-!Finclude/crypto/skcipher.h crypto_skcipher_reqsize
-!Finclude/crypto/skcipher.h skcipher_request_set_tfm
-!Finclude/crypto/skcipher.h skcipher_request_alloc
-!Finclude/crypto/skcipher.h skcipher_request_free
-!Finclude/crypto/skcipher.h skcipher_request_set_callback
-!Finclude/crypto/skcipher.h skcipher_request_set_crypt
-   </sect1>
-   <sect1><title>Asynchronous Block Cipher API - Deprecated</title>
-!Pinclude/linux/crypto.h Asynchronous Block Cipher API
-!Finclude/linux/crypto.h crypto_alloc_ablkcipher
-!Finclude/linux/crypto.h crypto_free_ablkcipher
-!Finclude/linux/crypto.h crypto_has_ablkcipher
-!Finclude/linux/crypto.h crypto_ablkcipher_ivsize
-!Finclude/linux/crypto.h crypto_ablkcipher_blocksize
-!Finclude/linux/crypto.h crypto_ablkcipher_setkey
-!Finclude/linux/crypto.h crypto_ablkcipher_reqtfm
-!Finclude/linux/crypto.h crypto_ablkcipher_encrypt
-!Finclude/linux/crypto.h crypto_ablkcipher_decrypt
-   </sect1>
-   <sect1><title>Asynchronous Cipher Request Handle - Deprecated</title>
-!Pinclude/linux/crypto.h Asynchronous Cipher Request Handle
-!Finclude/linux/crypto.h crypto_ablkcipher_reqsize
-!Finclude/linux/crypto.h ablkcipher_request_set_tfm
-!Finclude/linux/crypto.h ablkcipher_request_alloc
-!Finclude/linux/crypto.h ablkcipher_request_free
-!Finclude/linux/crypto.h ablkcipher_request_set_callback
-!Finclude/linux/crypto.h ablkcipher_request_set_crypt
-   </sect1>
-   <sect1><title>Authenticated Encryption With Associated Data (AEAD) Cipher API</title>
-!Pinclude/crypto/aead.h Authenticated Encryption With Associated Data (AEAD) Cipher API
-!Finclude/crypto/aead.h crypto_alloc_aead
-!Finclude/crypto/aead.h crypto_free_aead
-!Finclude/crypto/aead.h crypto_aead_ivsize
-!Finclude/crypto/aead.h crypto_aead_authsize
-!Finclude/crypto/aead.h crypto_aead_blocksize
-!Finclude/crypto/aead.h crypto_aead_setkey
-!Finclude/crypto/aead.h crypto_aead_setauthsize
-!Finclude/crypto/aead.h crypto_aead_encrypt
-!Finclude/crypto/aead.h crypto_aead_decrypt
-   </sect1>
-   <sect1><title>Asynchronous AEAD Request Handle</title>
-!Pinclude/crypto/aead.h Asynchronous AEAD Request Handle
-!Finclude/crypto/aead.h crypto_aead_reqsize
-!Finclude/crypto/aead.h aead_request_set_tfm
-!Finclude/crypto/aead.h aead_request_alloc
-!Finclude/crypto/aead.h aead_request_free
-!Finclude/crypto/aead.h aead_request_set_callback
-!Finclude/crypto/aead.h aead_request_set_crypt
-!Finclude/crypto/aead.h aead_request_set_ad
-   </sect1>
-   <sect1><title>Synchronous Block Cipher API - Deprecated</title>
-!Pinclude/linux/crypto.h Synchronous Block Cipher API
-!Finclude/linux/crypto.h crypto_alloc_blkcipher
-!Finclude/linux/crypto.h crypto_free_blkcipher
-!Finclude/linux/crypto.h crypto_has_blkcipher
-!Finclude/linux/crypto.h crypto_blkcipher_name
-!Finclude/linux/crypto.h crypto_blkcipher_ivsize
-!Finclude/linux/crypto.h crypto_blkcipher_blocksize
-!Finclude/linux/crypto.h crypto_blkcipher_setkey
-!Finclude/linux/crypto.h crypto_blkcipher_encrypt
-!Finclude/linux/crypto.h crypto_blkcipher_encrypt_iv
-!Finclude/linux/crypto.h crypto_blkcipher_decrypt
-!Finclude/linux/crypto.h crypto_blkcipher_decrypt_iv
-!Finclude/linux/crypto.h crypto_blkcipher_set_iv
-!Finclude/linux/crypto.h crypto_blkcipher_get_iv
-   </sect1>
-   <sect1><title>Single Block Cipher API</title>
-!Pinclude/linux/crypto.h Single Block Cipher API
-!Finclude/linux/crypto.h crypto_alloc_cipher
-!Finclude/linux/crypto.h crypto_free_cipher
-!Finclude/linux/crypto.h crypto_has_cipher
-!Finclude/linux/crypto.h crypto_cipher_blocksize
-!Finclude/linux/crypto.h crypto_cipher_setkey
-!Finclude/linux/crypto.h crypto_cipher_encrypt_one
-!Finclude/linux/crypto.h crypto_cipher_decrypt_one
-   </sect1>
-   <sect1><title>Message Digest Algorithm Definitions</title>
-!Pinclude/crypto/hash.h Message Digest Algorithm Definitions
-!Finclude/crypto/hash.h hash_alg_common
-!Finclude/crypto/hash.h ahash_alg
-!Finclude/crypto/hash.h shash_alg
-   </sect1>
-   <sect1><title>Asynchronous Message Digest API</title>
-!Pinclude/crypto/hash.h Asynchronous Message Digest API
-!Finclude/crypto/hash.h crypto_alloc_ahash
-!Finclude/crypto/hash.h crypto_free_ahash
-!Finclude/crypto/hash.h crypto_ahash_init
-!Finclude/crypto/hash.h crypto_ahash_digestsize
-!Finclude/crypto/hash.h crypto_ahash_reqtfm
-!Finclude/crypto/hash.h crypto_ahash_reqsize
-!Finclude/crypto/hash.h crypto_ahash_setkey
-!Finclude/crypto/hash.h crypto_ahash_finup
-!Finclude/crypto/hash.h crypto_ahash_final
-!Finclude/crypto/hash.h crypto_ahash_digest
-!Finclude/crypto/hash.h crypto_ahash_export
-!Finclude/crypto/hash.h crypto_ahash_import
-   </sect1>
-   <sect1><title>Asynchronous Hash Request Handle</title>
-!Pinclude/crypto/hash.h Asynchronous Hash Request Handle
-!Finclude/crypto/hash.h ahash_request_set_tfm
-!Finclude/crypto/hash.h ahash_request_alloc
-!Finclude/crypto/hash.h ahash_request_free
-!Finclude/crypto/hash.h ahash_request_set_callback
-!Finclude/crypto/hash.h ahash_request_set_crypt
-   </sect1>
-   <sect1><title>Synchronous Message Digest API</title>
-!Pinclude/crypto/hash.h Synchronous Message Digest API
-!Finclude/crypto/hash.h crypto_alloc_shash
-!Finclude/crypto/hash.h crypto_free_shash
-!Finclude/crypto/hash.h crypto_shash_blocksize
-!Finclude/crypto/hash.h crypto_shash_digestsize
-!Finclude/crypto/hash.h crypto_shash_descsize
-!Finclude/crypto/hash.h crypto_shash_setkey
-!Finclude/crypto/hash.h crypto_shash_digest
-!Finclude/crypto/hash.h crypto_shash_export
-!Finclude/crypto/hash.h crypto_shash_import
-!Finclude/crypto/hash.h crypto_shash_init
-!Finclude/crypto/hash.h crypto_shash_update
-!Finclude/crypto/hash.h crypto_shash_final
-!Finclude/crypto/hash.h crypto_shash_finup
-   </sect1>
-   <sect1><title>Crypto API Random Number API</title>
-!Pinclude/crypto/rng.h Random number generator API
-!Finclude/crypto/rng.h crypto_alloc_rng
-!Finclude/crypto/rng.h crypto_rng_alg
-!Finclude/crypto/rng.h crypto_free_rng
-!Finclude/crypto/rng.h crypto_rng_generate
-!Finclude/crypto/rng.h crypto_rng_get_bytes
-!Finclude/crypto/rng.h crypto_rng_reset
-!Finclude/crypto/rng.h crypto_rng_seedsize
-!Cinclude/crypto/rng.h
-   </sect1>
-   <sect1><title>Asymmetric Cipher API</title>
-!Pinclude/crypto/akcipher.h Generic Public Key API
-!Finclude/crypto/akcipher.h akcipher_alg
-!Finclude/crypto/akcipher.h akcipher_request
-!Finclude/crypto/akcipher.h crypto_alloc_akcipher
-!Finclude/crypto/akcipher.h crypto_free_akcipher
-!Finclude/crypto/akcipher.h crypto_akcipher_set_pub_key
-!Finclude/crypto/akcipher.h crypto_akcipher_set_priv_key
-   </sect1>
-   <sect1><title>Asymmetric Cipher Request Handle</title>
-!Finclude/crypto/akcipher.h akcipher_request_alloc
-!Finclude/crypto/akcipher.h akcipher_request_free
-!Finclude/crypto/akcipher.h akcipher_request_set_callback
-!Finclude/crypto/akcipher.h akcipher_request_set_crypt
-!Finclude/crypto/akcipher.h crypto_akcipher_maxsize
-!Finclude/crypto/akcipher.h crypto_akcipher_encrypt
-!Finclude/crypto/akcipher.h crypto_akcipher_decrypt
-!Finclude/crypto/akcipher.h crypto_akcipher_sign
-!Finclude/crypto/akcipher.h crypto_akcipher_verify
-   </sect1>
-  </chapter>
-
-  <chapter id="Code"><title>Code Examples</title>
-   <sect1><title>Code Example For Symmetric Key Cipher Operation</title>
-    <programlisting>
-
-struct tcrypt_result {
-	struct completion completion;
-	int err;
-};
-
-/* tie all data structures together */
-struct skcipher_def {
-	struct scatterlist sg;
-	struct crypto_skcipher *tfm;
-	struct skcipher_request *req;
-	struct tcrypt_result result;
-};
-
-/* Callback function */
-static void test_skcipher_cb(struct crypto_async_request *req, int error)
-{
-	struct tcrypt_result *result = req-&gt;data;
-
-	if (error == -EINPROGRESS)
-		return;
-	result-&gt;err = error;
-	complete(&amp;result-&gt;completion);
-	pr_info("Encryption finished successfully\n");
-}
-
-/* Perform cipher operation */
-static unsigned int test_skcipher_encdec(struct skcipher_def *sk,
-					 int enc)
-{
-	int rc = 0;
-
-	if (enc)
-		rc = crypto_skcipher_encrypt(sk-&gt;req);
-	else
-		rc = crypto_skcipher_decrypt(sk-&gt;req);
-
-	switch (rc) {
-	case 0:
-		break;
-	case -EINPROGRESS:
-	case -EBUSY:
-		rc = wait_for_completion_interruptible(
-			&amp;sk-&gt;result.completion);
-		if (!rc &amp;&amp; !sk-&gt;result.err) {
-			reinit_completion(&amp;sk-&gt;result.completion);
-			break;
-		}
-	default:
-		pr_info("skcipher encrypt returned with %d result %d\n",
-			rc, sk-&gt;result.err);
-		break;
-	}
-	init_completion(&amp;sk-&gt;result.completion);
-
-	return rc;
-}
-
-/* Initialize and trigger cipher operation */
-static int test_skcipher(void)
-{
-	struct skcipher_def sk;
-	struct crypto_skcipher *skcipher = NULL;
-	struct skcipher_request *req = NULL;
-	char *scratchpad = NULL;
-	char *ivdata = NULL;
-	unsigned char key[32];
-	int ret = -EFAULT;
-
-	skcipher = crypto_alloc_skcipher("cbc-aes-aesni", 0, 0);
-	if (IS_ERR(skcipher)) {
-		pr_info("could not allocate skcipher handle\n");
-		return PTR_ERR(skcipher);
-	}
-
-	req = skcipher_request_alloc(skcipher, GFP_KERNEL);
-	if (!req) {
-		pr_info("could not allocate skcipher request\n");
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-				      test_skcipher_cb,
-				      &amp;sk.result);
-
-	/* AES 256 with random key */
-	get_random_bytes(&amp;key, 32);
-	if (crypto_skcipher_setkey(skcipher, key, 32)) {
-		pr_info("key could not be set\n");
-		ret = -EAGAIN;
-		goto out;
-	}
-
-	/* IV will be random */
-	ivdata = kmalloc(16, GFP_KERNEL);
-	if (!ivdata) {
-		pr_info("could not allocate ivdata\n");
-		goto out;
-	}
-	get_random_bytes(ivdata, 16);
-
-	/* Input data will be random */
-	scratchpad = kmalloc(16, GFP_KERNEL);
-	if (!scratchpad) {
-		pr_info("could not allocate scratchpad\n");
-		goto out;
-	}
-	get_random_bytes(scratchpad, 16);
-
-	sk.tfm = skcipher;
-	sk.req = req;
-
-	/* We encrypt one block */
-	sg_init_one(&amp;sk.sg, scratchpad, 16);
-	skcipher_request_set_crypt(req, &amp;sk.sg, &amp;sk.sg, 16, ivdata);
-	init_completion(&amp;sk.result.completion);
-
-	/* encrypt data */
-	ret = test_skcipher_encdec(&amp;sk, 1);
-	if (ret)
-		goto out;
-
-	pr_info("Encryption triggered successfully\n");
-
-out:
-	if (skcipher)
-		crypto_free_skcipher(skcipher);
-	if (req)
-		skcipher_request_free(req);
-	if (ivdata)
-		kfree(ivdata);
-	if (scratchpad)
-		kfree(scratchpad);
-	return ret;
-}
-    </programlisting>
-   </sect1>
-
-   <sect1><title>Code Example For Use of Operational State Memory With SHASH</title>
-    <programlisting>
-
-struct sdesc {
-	struct shash_desc shash;
-	char ctx[];
-};
-
-static struct sdescinit_sdesc(struct crypto_shash *alg)
-{
-	struct sdescsdesc;
-	int size;
-
-	size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
-	sdesc = kmalloc(size, GFP_KERNEL);
-	if (!sdesc)
-		return ERR_PTR(-ENOMEM);
-	sdesc-&gt;shash.tfm = alg;
-	sdesc-&gt;shash.flags = 0x0;
-	return sdesc;
-}
-
-static int calc_hash(struct crypto_shashalg,
-		     const unsigned chardata, unsigned int datalen,
-		     unsigned chardigest) {
-	struct sdescsdesc;
-	int ret;
-
-	sdesc = init_sdesc(alg);
-	if (IS_ERR(sdesc)) {
-		pr_info("trusted_key: can't alloc %s\n", hash_alg);
-		return PTR_ERR(sdesc);
-	}
-
-	ret = crypto_shash_digest(&amp;sdesc-&gt;shash, data, datalen, digest);
-	kfree(sdesc);
-	return ret;
-}
-    </programlisting>
-   </sect1>
-
-   <sect1><title>Code Example For Random Number Generator Usage</title>
-    <programlisting>
-
-static int get_random_numbers(u8 *buf, unsigned int len)
-{
-	struct crypto_rngrng = NULL;
-	chardrbg = "drbg_nopr_sha256"; /* Hash DRBG with SHA-256, no PR */
-	int ret;
-
-	if (!buf || !len) {
-		pr_debug("No output buffer provided\n");
-		return -EINVAL;
-	}
-
-	rng = crypto_alloc_rng(drbg, 0, 0);
-	if (IS_ERR(rng)) {
-		pr_debug("could not allocate RNG handle for %s\n", drbg);
-		return -PTR_ERR(rng);
-	}
-
-	ret = crypto_rng_get_bytes(rng, buf, len);
-	if (ret &lt; 0)
-		pr_debug("generation of random numbers failed\n");
-	else if (ret == 0)
-		pr_debug("RNG returned no data");
-	else
-		pr_debug("RNG returned %d bytes of data\n", ret);
-
-out:
-	crypto_free_rng(rng);
-	return ret;
-}
-    </programlisting>
-   </sect1>
-  </chapter>
- </book>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/debugobjects.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/debugobjects.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/debugobjects.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/debugobjects.tmpl	1969-12-31 19:00:00.000000000 -0500
@@ -1,443 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="debug-objects-guide">
- <bookinfo>
-  <title>Debug objects life time</title>
-
-  <authorgroup>
-   <author>
-    <firstname>Thomas</firstname>
-    <surname>Gleixner</surname>
-    <affiliation>
-     <address>
-      <email>tglx@linutronix.de</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-
-  <copyright>
-   <year>2008</year>
-   <holder>Thomas Gleixner</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation is free software; you can redistribute
-     it and/or modify it under the terms of the GNU General Public
-     License version 2 as published by the Free Software Foundation.
-   </para>
-
-   <para>
-     This program is distributed in the hope that it will be
-     useful, but WITHOUT ANY WARRANTY; without even the implied
-     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-     See the GNU General Public License for more details.
-   </para>
-
-   <para>
-     You should have received a copy of the GNU General Public
-     License along with this program; if not, write to the Free
-     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-     MA 02111-1307 USA
-   </para>
-
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
-  <chapter id="intro">
-    <title>Introduction</title>
-    <para>
-      debugobjects is a generic infrastructure to track the life time
-      of kernel objects and validate the operations on those.
-    </para>
-    <para>
-      debugobjects is useful to check for the following error patterns:
-	<itemizedlist>
-	  <listitem><para>Activation of uninitialized objects</para></listitem>
-	  <listitem><para>Initialization of active objects</para></listitem>
-	  <listitem><para>Usage of freed/destroyed objects</para></listitem>
-	</itemizedlist>
-    </para>
-    <para>
-      debugobjects is not changing the data structure of the real
-      object so it can be compiled in with a minimal runtime impact
-      and enabled on demand with a kernel command line option.
-    </para>
-  </chapter>
-
-  <chapter id="howto">
-    <title>Howto use debugobjects</title>
-    <para>
-      A kernel subsystem needs to provide a data structure which
-      describes the object type and add calls into the debug code at
-      appropriate places. The data structure to describe the object
-      type needs at minimum the name of the object type. Optional
-      functions can and should be provided to fixup detected problems
-      so the kernel can continue to work and the debug information can
-      be retrieved from a live system instead of hard core debugging
-      with serial consoles and stack trace transcripts from the
-      monitor.
-    </para>
-    <para>
-      The debug calls provided by debugobjects are:
-      <itemizedlist>
-	<listitem><para>debug_object_init</para></listitem>
-	<listitem><para>debug_object_init_on_stack</para></listitem>
-	<listitem><para>debug_object_activate</para></listitem>
-	<listitem><para>debug_object_deactivate</para></listitem>
-	<listitem><para>debug_object_destroy</para></listitem>
-	<listitem><para>debug_object_free</para></listitem>
-	<listitem><para>debug_object_assert_init</para></listitem>
-      </itemizedlist>
-      Each of these functions takes the address of the real object and
-      a pointer to the object type specific debug description
-      structure.
-    </para>
-    <para>
-      Each detected error is reported in the statistics and a limited
-      number of errors are printk'ed including a full stack trace.
-    </para>
-    <para>
-      The statistics are available via /sys/kernel/debug/debug_objects/stats.
-      They provide information about the number of warnings and the
-      number of successful fixups along with information about the
-      usage of the internal tracking objects and the state of the
-      internal tracking objects pool.
-    </para>
-  </chapter>
-  <chapter id="debugfunctions">
-    <title>Debug functions</title>
-    <sect1 id="prototypes">
-      <title>Debug object function reference</title>
-!Elib/debugobjects.c
-    </sect1>
-    <sect1 id="debug_object_init">
-      <title>debug_object_init</title>
-      <para>
-	This function is called whenever the initialization function
-	of a real object is called.
-      </para>
-      <para>
-	When the real object is already tracked by debugobjects it is
-	checked, whether the object can be initialized.  Initializing
-	is not allowed for active and destroyed objects. When
-	debugobjects detects an error, then it calls the fixup_init
-	function of the object type description structure if provided
-	by the caller. The fixup function can correct the problem
-	before the real initialization of the object happens. E.g. it
-	can deactivate an active object in order to prevent damage to
-	the subsystem.
-      </para>
-      <para>
-	When the real object is not yet tracked by debugobjects,
-	debugobjects allocates a tracker object for the real object
-	and sets the tracker object state to ODEBUG_STATE_INIT. It
-	verifies that the object is not on the callers stack. If it is
-	on the callers stack then a limited number of warnings
-	including a full stack trace is printk'ed. The calling code
-	must use debug_object_init_on_stack() and remove the object
-	before leaving the function which allocated it. See next
-	section.
-      </para>
-    </sect1>
-
-    <sect1 id="debug_object_init_on_stack">
-      <title>debug_object_init_on_stack</title>
-      <para>
-	This function is called whenever the initialization function
-	of a real object which resides on the stack is called.
-      </para>
-      <para>
-	When the real object is already tracked by debugobjects it is
-	checked, whether the object can be initialized. Initializing
-	is not allowed for active and destroyed objects. When
-	debugobjects detects an error, then it calls the fixup_init
-	function of the object type description structure if provided
-	by the caller. The fixup function can correct the problem
-	before the real initialization of the object happens. E.g. it
-	can deactivate an active object in order to prevent damage to
-	the subsystem.
-      </para>
-      <para>
-	When the real object is not yet tracked by debugobjects
-	debugobjects allocates a tracker object for the real object
-	and sets the tracker object state to ODEBUG_STATE_INIT. It
-	verifies that the object is on the callers stack.
-      </para>
-      <para>
-	An object which is on the stack must be removed from the
-	tracker by calling debug_object_free() before the function
-	which allocates the object returns. Otherwise we keep track of
-	stale objects.
-      </para>
-    </sect1>
-
-    <sect1 id="debug_object_activate">
-      <title>debug_object_activate</title>
-      <para>
-	This function is called whenever the activation function of a
-	real object is called.
-      </para>
-      <para>
-	When the real object is already tracked by debugobjects it is
-	checked, whether the object can be activated.  Activating is
-	not allowed for active and destroyed objects. When
-	debugobjects detects an error, then it calls the
-	fixup_activate function of the object type description
-	structure if provided by the caller. The fixup function can
-	correct the problem before the real activation of the object
-	happens. E.g. it can deactivate an active object in order to
-	prevent damage to the subsystem.
-      </para>
-      <para>
-	When the real object is not yet tracked by debugobjects then
-	the fixup_activate function is called if available. This is
-	necessary to allow the legitimate activation of statically
-	allocated and initialized objects. The fixup function checks
-	whether the object is valid and calls the debug_objects_init()
-	function to initialize the tracking of this object.
-      </para>
-      <para>
-	When the activation is legitimate, then the state of the
-	associated tracker object is set to ODEBUG_STATE_ACTIVE.
-      </para>
-    </sect1>
-
-    <sect1 id="debug_object_deactivate">
-      <title>debug_object_deactivate</title>
-      <para>
-	This function is called whenever the deactivation function of
-	a real object is called.
-      </para>
-      <para>
-	When the real object is tracked by debugobjects it is checked,
-	whether the object can be deactivated. Deactivating is not
-	allowed for untracked or destroyed objects.
-      </para>
-      <para>
-	When the deactivation is legitimate, then the state of the
-	associated tracker object is set to ODEBUG_STATE_INACTIVE.
-      </para>
-    </sect1>
-
-    <sect1 id="debug_object_destroy">
-      <title>debug_object_destroy</title>
-      <para>
-	This function is called to mark an object destroyed. This is
-	useful to prevent the usage of invalid objects, which are
-	still available in memory: either statically allocated objects
-	or objects which are freed later.
-      </para>
-      <para>
-	When the real object is tracked by debugobjects it is checked,
-	whether the object can be destroyed. Destruction is not
-	allowed for active and destroyed objects. When debugobjects
-	detects an error, then it calls the fixup_destroy function of
-	the object type description structure if provided by the
-	caller. The fixup function can correct the problem before the
-	real destruction of the object happens. E.g. it can deactivate
-	an active object in order to prevent damage to the subsystem.
-      </para>
-      <para>
-	When the destruction is legitimate, then the state of the
-	associated tracker object is set to ODEBUG_STATE_DESTROYED.
-      </para>
-    </sect1>
-
-    <sect1 id="debug_object_free">
-      <title>debug_object_free</title>
-      <para>
-	This function is called before an object is freed.
-      </para>
-      <para>
-	When the real object is tracked by debugobjects it is checked,
-	whether the object can be freed. Free is not allowed for
-	active objects. When debugobjects detects an error, then it
-	calls the fixup_free function of the object type description
-	structure if provided by the caller. The fixup function can
-	correct the problem before the real free of the object
-	happens. E.g. it can deactivate an active object in order to
-	prevent damage to the subsystem.
-      </para>
-      <para>
-	Note that debug_object_free removes the object from the
-	tracker. Later usage of the object is detected by the other
-	debug checks.
-      </para>
-    </sect1>
-
-    <sect1 id="debug_object_assert_init">
-      <title>debug_object_assert_init</title>
-      <para>
-	This function is called to assert that an object has been
-	initialized.
-      </para>
-      <para>
-	When the real object is not tracked by debugobjects, it calls
-	fixup_assert_init of the object type description structure
-	provided by the caller, with the hardcoded object state
-	ODEBUG_NOT_AVAILABLE. The fixup function can correct the problem
-	by calling debug_object_init and other specific initializing
-	functions.
-      </para>
-      <para>
-	When the real object is already tracked by debugobjects it is
-	ignored.
-      </para>
-    </sect1>
-  </chapter>
-  <chapter id="fixupfunctions">
-    <title>Fixup functions</title>
-    <sect1 id="debug_obj_descr">
-      <title>Debug object type description structure</title>
-!Iinclude/linux/debugobjects.h
-    </sect1>
-    <sect1 id="fixup_init">
-      <title>fixup_init</title>
-      <para>
-	This function is called from the debug code whenever a problem
-	in debug_object_init is detected. The function takes the
-	address of the object and the state which is currently
-	recorded in the tracker.
-      </para>
-      <para>
-	Called from debug_object_init when the object state is:
-	<itemizedlist>
-	  <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
-	</itemizedlist>
-      </para>
-      <para>
-	The function returns true when the fixup was successful,
-	otherwise false. The return value is used to update the
-	statistics.
-      </para>
-      <para>
-	Note, that the function needs to call the debug_object_init()
-	function again, after the damage has been repaired in order to
-	keep the state consistent.
-      </para>
-    </sect1>
-
-    <sect1 id="fixup_activate">
-      <title>fixup_activate</title>
-      <para>
-	This function is called from the debug code whenever a problem
-	in debug_object_activate is detected.
-      </para>
-      <para>
-	Called from debug_object_activate when the object state is:
-	<itemizedlist>
-	  <listitem><para>ODEBUG_STATE_NOTAVAILABLE</para></listitem>
-	  <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
-	</itemizedlist>
-      </para>
-      <para>
-	The function returns true when the fixup was successful,
-	otherwise false. The return value is used to update the
-	statistics.
-      </para>
-      <para>
-	Note that the function needs to call the debug_object_activate()
-	function again after the damage has been repaired in order to
-	keep the state consistent.
-      </para>
-      <para>
-	The activation of statically initialized objects is a special
-	case. When debug_object_activate() has no tracked object for
-	this object address then fixup_activate() is called with
-	object state ODEBUG_STATE_NOTAVAILABLE. The fixup function
-	needs to check whether this is a legitimate case of a
-	statically initialized object or not. In case it is it calls
-	debug_object_init() and debug_object_activate() to make the
-	object known to the tracker and marked active. In this case
-	the function should return false because this is not a real
-	fixup.
-      </para>
-    </sect1>
-
-    <sect1 id="fixup_destroy">
-      <title>fixup_destroy</title>
-      <para>
-	This function is called from the debug code whenever a problem
-	in debug_object_destroy is detected.
-      </para>
-      <para>
-	Called from debug_object_destroy when the object state is:
-	<itemizedlist>
-	  <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
-	</itemizedlist>
-      </para>
-      <para>
-	The function returns true when the fixup was successful,
-	otherwise false. The return value is used to update the
-	statistics.
-      </para>
-    </sect1>
-    <sect1 id="fixup_free">
-      <title>fixup_free</title>
-      <para>
-	This function is called from the debug code whenever a problem
-	in debug_object_free is detected. Further it can be called
-	from the debug checks in kfree/vfree, when an active object is
-	detected from the debug_check_no_obj_freed() sanity checks.
-      </para>
-      <para>
-	Called from debug_object_free() or debug_check_no_obj_freed()
-	when the object state is:
-	<itemizedlist>
-	  <listitem><para>ODEBUG_STATE_ACTIVE</para></listitem>
-	</itemizedlist>
-      </para>
-      <para>
-	The function returns true when the fixup was successful,
-	otherwise false. The return value is used to update the
-	statistics.
-      </para>
-    </sect1>
-    <sect1 id="fixup_assert_init">
-      <title>fixup_assert_init</title>
-      <para>
-	This function is called from the debug code whenever a problem
-	in debug_object_assert_init is detected.
-      </para>
-      <para>
-	Called from debug_object_assert_init() with a hardcoded state
-	ODEBUG_STATE_NOTAVAILABLE when the object is not found in the
-	debug bucket.
-      </para>
-      <para>
-	The function returns true when the fixup was successful,
-	otherwise false. The return value is used to update the
-	statistics.
-      </para>
-      <para>
-	Note, this function should make sure debug_object_init() is
-	called before returning.
-      </para>
-      <para>
-	The handling of statically initialized objects is a special
-	case. The fixup function should check if this is a legitimate
-	case of a statically initialized object or not. In this case only
-	debug_object_init() should be called to make the object known to
-	the tracker. Then the function should return false because this
-	is not
-	a real fixup.
-      </para>
-    </sect1>
-  </chapter>
-  <chapter id="bugs">
-    <title>Known Bugs And Assumptions</title>
-    <para>
-	None (knock on wood).
-    </para>
-  </chapter>
-</book>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/kernel-hacking.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/kernel-hacking.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/kernel-hacking.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/kernel-hacking.tmpl	2017-02-12 16:03:20.000000000 -0500
@@ -1208,8 +1208,8 @@ static struct block_device_operations op
    
    <listitem>
     <para>
-     Finally, don't forget to read <filename>Documentation/SubmittingPatches</filename>
-     and possibly <filename>Documentation/SubmittingDrivers</filename>.
+     Finally, don't forget to read <filename>Documentation/process/submitting-patches.rst</filename>
+     and possibly <filename>Documentation/process/submitting-drivers.rst</filename>.
     </para>
    </listitem>
   </itemizedlist>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/Makefile linux-libre-4.10-rc8-gnu/Documentation/DocBook/Makefile
--- linux-libre-4.9-gnu/Documentation/DocBook/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -9,13 +9,11 @@
 DOCBOOKS := z8530book.xml  \
 	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
 	    writing_usb_driver.xml networking.xml \
-	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
+	    kernel-api.xml filesystems.xml lsm.xml kgdb.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
-	    debugobjects.xml sh.xml regulator.xml \
-	    alsa-driver-api.xml writing-an-alsa-driver.xml \
-	    tracepoint.xml w1.xml \
-	    writing_musb_glue_layer.xml crypto-API.xml iio.xml
+	    sh.xml regulator.xml w1.xml \
+	    writing_musb_glue_layer.xml iio.xml
 
 ifeq ($(DOCBOOKS),)
 
@@ -264,6 +262,7 @@ clean-files := $(DOCBOOKS) \
 	$(patsubst %.xml, %.aux.xml, $(DOCBOOKS)) \
 	$(patsubst %.xml, %.xml.db,  $(DOCBOOKS)) \
 	$(patsubst %.xml, %.xml,     $(DOCBOOKS)) \
+	$(patsubst %.xml, .%.xml.cmd, $(DOCBOOKS)) \
 	$(index)
 
 clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/tracepoint.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/tracepoint.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/tracepoint.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/tracepoint.tmpl	1969-12-31 19:00:00.000000000 -0500
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="Tracepoints">
- <bookinfo>
-  <title>The Linux Kernel Tracepoint API</title>
-
-  <authorgroup>
-   <author>
-    <firstname>Jason</firstname>
-    <surname>Baron</surname>
-    <affiliation>
-     <address>
-      <email>jbaron@redhat.com</email>
-     </address>
-    </affiliation>
-   </author>
-   <author>
-    <firstname>William</firstname>
-    <surname>Cohen</surname>
-    <affiliation>
-     <address>
-      <email>wcohen@redhat.com</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-
-  <legalnotice>
-   <para>
-     This documentation is free software; you can redistribute
-     it and/or modify it under the terms of the GNU General Public
-     License as published by the Free Software Foundation; either
-     version 2 of the License, or (at your option) any later
-     version.
-   </para>
-
-   <para>
-     This program is distributed in the hope that it will be
-     useful, but WITHOUT ANY WARRANTY; without even the implied
-     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-     See the GNU General Public License for more details.
-   </para>
-
-   <para>
-     You should have received a copy of the GNU General Public
-     License along with this program; if not, write to the Free
-     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-     MA 02111-1307 USA
-   </para>
-
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
- <toc></toc>
-  <chapter id="intro">
-   <title>Introduction</title>
-   <para>
-     Tracepoints are static probe points that are located in strategic points
-     throughout the kernel. 'Probes' register/unregister with tracepoints
-     via a callback mechanism. The 'probes' are strictly typed functions that
-     are passed a unique set of parameters defined by each tracepoint.
-   </para>
-
-   <para>
-     From this simple callback mechanism, 'probes' can be used to profile, debug,
-     and understand kernel behavior. There are a number of tools that provide a
-     framework for using 'probes'. These tools include Systemtap, ftrace, and
-     LTTng.
-   </para>
-
-   <para>
-     Tracepoints are defined in a number of header files via various macros. Thus,
-     the purpose of this document is to provide a clear accounting of the available
-     tracepoints. The intention is to understand not only what tracepoints are
-     available but also to understand where future tracepoints might be added.
-   </para>
-
-   <para>
-     The API presented has functions of the form:
-     <function>trace_tracepointname(function parameters)</function>. These are the
-     tracepoints callbacks that are found throughout the code. Registering and
-     unregistering probes with these callback sites is covered in the
-     <filename>Documentation/trace/*</filename> directory.
-   </para>
-  </chapter>
-
-  <chapter id="irq">
-   <title>IRQ</title>
-!Iinclude/trace/events/irq.h
-  </chapter>
-
-  <chapter id="signal">
-   <title>SIGNAL</title>
-!Iinclude/trace/events/signal.h
-  </chapter>
-
-  <chapter id="block">
-   <title>Block IO</title>
-!Iinclude/trace/events/block.h
-  </chapter>
-
-  <chapter id="workqueue">
-   <title>Workqueue</title>
-!Iinclude/trace/events/workqueue.h
-  </chapter>
-</book>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/uio-howto.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/uio-howto.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/uio-howto.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/uio-howto.tmpl	2017-02-12 16:03:20.000000000 -0500
@@ -46,6 +46,13 @@ GPL version 2.
 
 <revhistory>
 	<revision>
+	<revnumber>0.10</revnumber>
+	<date>2016-10-17</date>
+	<authorinitials>sch</authorinitials>
+	<revremark>Added generic hyperv driver
+		</revremark>
+	</revision>
+	<revision>
 	<revnumber>0.9</revnumber>
 	<date>2009-07-16</date>
 	<authorinitials>mst</authorinitials>
@@ -1033,6 +1040,61 @@ int main()
 
 </chapter>
 
+<chapter id="uio_hv_generic" xreflabel="Using Generic driver for Hyper-V VMBUS">
+<?dbhtml filename="uio_hv_generic.html"?>
+<title>Generic Hyper-V UIO driver</title>
+	<para>
+	The generic driver is a kernel module named uio_hv_generic.
+	It supports devices on the Hyper-V VMBus similar to uio_pci_generic
+	on PCI bus.
+	</para>
+
+<sect1 id="uio_hv_generic_binding">
+<title>Making the driver recognize the device</title>
+	<para>
+Since the driver does not declare any device GUID's, it will not get loaded
+automatically and will not automatically bind to any devices, you must load it
+and allocate id to the driver yourself. For example, to use the network device
+GUID:
+	<programlisting>
+ modprobe uio_hv_generic
+ echo &quot;f8615163-df3e-46c5-913f-f2d2f965ed0e&quot; &gt; /sys/bus/vmbus/drivers/uio_hv_generic/new_id
+	</programlisting>
+	</para>
+	<para>
+If there already is a hardware specific kernel driver for the device, the
+generic driver still won't bind to it, in this case if you want to use the
+generic driver (why would you?) you'll have to manually unbind the hardware
+specific driver and bind the generic driver, like this:
+	<programlisting>
+	  echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 &gt; /sys/bus/vmbus/drivers/hv_netvsc/unbind
+	  echo -n vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3 &gt; /sys/bus/vmbus/drivers/uio_hv_generic/bind
+	</programlisting>
+	</para>
+	<para>
+You can verify that the device has been bound to the driver
+by looking for it in sysfs, for example like the following:
+	<programlisting>
+    ls -l /sys/bus/vmbus/devices/vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3/driver
+	</programlisting>
+Which if successful should print
+	<programlisting>
+  .../vmbus-ed963694-e847-4b2a-85af-bc9cfc11d6f3/driver -&gt; ../../../bus/vmbus/drivers/uio_hv_generic
+	</programlisting>
+	</para>
+</sect1>
+
+<sect1 id="uio_hv_generic_internals">
+<title>Things to know about uio_hv_generic</title>
+	<para>
+On each interrupt, uio_hv_generic sets the Interrupt Disable bit.
+This prevents the device from generating further interrupts
+until the bit is cleared. The userspace driver should clear this
+bit before blocking and waiting for more interrupts.
+	</para>
+</sect1>
+</chapter>
+
 <appendix id="app1">
 <title>Further information</title>
 <itemizedlist>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/usb.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/usb.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/usb.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/usb.tmpl	1969-12-31 19:00:00.000000000 -0500
@@ -1,992 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="Linux-USB-API">
- <bookinfo>
-  <title>The Linux-USB Host Side API</title>
-  
-  <legalnotice>
-   <para>
-     This documentation is free software; you can redistribute
-     it and/or modify it under the terms of the GNU General Public
-     License as published by the Free Software Foundation; either
-     version 2 of the License, or (at your option) any later
-     version.
-   </para>
-      
-   <para>
-     This program is distributed in the hope that it will be
-     useful, but WITHOUT ANY WARRANTY; without even the implied
-     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-     See the GNU General Public License for more details.
-   </para>
-      
-   <para>
-     You should have received a copy of the GNU General Public
-     License along with this program; if not, write to the Free
-     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-     MA 02111-1307 USA
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
- </bookinfo>
-
-<toc></toc>
-
-<chapter id="intro">
-    <title>Introduction to USB on Linux</title>
-
-    <para>A Universal Serial Bus (USB) is used to connect a host,
-    such as a PC or workstation, to a number of peripheral
-    devices.  USB uses a tree structure, with the host as the
-    root (the system's master), hubs as interior nodes, and
-    peripherals as leaves (and slaves).
-    Modern PCs support several such trees of USB devices, usually
-    one USB 2.0 tree (480 Mbit/sec each) with
-    a few USB 1.1 trees (12 Mbit/sec each) that are used when you
-    connect a USB 1.1 device directly to the machine's "root hub".
-    </para>
-
-    <para>That master/slave asymmetry was designed-in for a number of
-    reasons, one being ease of use.  It is not physically possible to
-    assemble (legal) USB cables incorrectly:  all upstream "to the host"
-    connectors are the rectangular type (matching the sockets on
-    root hubs), and all downstream connectors are the squarish type
-    (or they are built into the peripheral).
-    Also, the host software doesn't need to deal with distributed
-    auto-configuration since the pre-designated master node manages all that.
-    And finally, at the electrical level, bus protocol overhead is reduced by
-    eliminating arbitration and moving scheduling into the host software.
-    </para>
-
-    <para>USB 1.0 was announced in January 1996 and was revised
-    as USB 1.1 (with improvements in hub specification and
-    support for interrupt-out transfers) in September 1998.
-    USB 2.0 was released in April 2000, adding high-speed
-    transfers and transaction-translating hubs (used for USB 1.1
-    and 1.0 backward compatibility).
-    </para>
-
-    <para>Kernel developers added USB support to Linux early in the 2.2 kernel
-    series, shortly before 2.3 development forked.  Updates from 2.3 were
-    regularly folded back into 2.2 releases, which improved reliability and
-    brought <filename>/sbin/hotplug</filename> support as well more drivers.
-    Such improvements were continued in the 2.5 kernel series, where they added
-    USB 2.0 support, improved performance, and made the host controller drivers
-    (HCDs) more consistent.  They also simplified the API (to make bugs less
-    likely) and added internal "kerneldoc" documentation.
-    </para>
-
-    <para>Linux can run inside USB devices as well as on
-    the hosts that control the devices.
-    But USB device drivers running inside those peripherals
-    don't do the same things as the ones running inside hosts,
-    so they've been given a different name:
-    <emphasis>gadget drivers</emphasis>.
-    This document does not cover gadget drivers.
-    </para>
-
-    </chapter>
-
-<chapter id="host">
-    <title>USB Host-Side API Model</title>
-
-    <para>Host-side drivers for USB devices talk to the "usbcore" APIs.
-    There are two.  One is intended for
-    <emphasis>general-purpose</emphasis> drivers (exposed through
-    driver frameworks), and the other is for drivers that are
-    <emphasis>part of the core</emphasis>.
-    Such core drivers include the <emphasis>hub</emphasis> driver
-    (which manages trees of USB devices) and several different kinds
-    of <emphasis>host controller drivers</emphasis>,
-    which control individual busses.
-    </para>
-
-    <para>The device model seen by USB drivers is relatively complex.
-    </para>
-     
-    <itemizedlist>
-
-	<listitem><para>USB supports four kinds of data transfers
-	(control, bulk, interrupt, and isochronous).  Two of them (control
-	and bulk) use bandwidth as it's available,
-	while the other two (interrupt and isochronous)
-	are scheduled to provide guaranteed bandwidth.
-	</para></listitem>
-
-	<listitem><para>The device description model includes one or more
-	"configurations" per device, only one of which is active at a time.
-	Devices that are capable of high-speed operation must also support
-	full-speed configurations, along with a way to ask about the
-	"other speed" configurations which might be used.
-	</para></listitem>
-
-	<listitem><para>Configurations have one or more "interfaces", each
-	of which may have "alternate settings".  Interfaces may be
-	standardized by USB "Class" specifications, or may be specific to
-	a vendor or device.</para>
-
-	<para>USB device drivers actually bind to interfaces, not devices.
-	Think of them as "interface drivers", though you
-	may not see many devices where the distinction is important.
-	<emphasis>Most USB devices are simple, with only one configuration,
-	one interface, and one alternate setting.</emphasis>
-	</para></listitem>
-
-	<listitem><para>Interfaces have one or more "endpoints", each of
-	which supports one type and direction of data transfer such as
-	"bulk out" or "interrupt in".  The entire configuration may have
-	up to sixteen endpoints in each direction, allocated as needed
-	among all the interfaces.
-	</para></listitem>
-
-	<listitem><para>Data transfer on USB is packetized; each endpoint
-	has a maximum packet size.
-	Drivers must often be aware of conventions such as flagging the end
-	of bulk transfers using "short" (including zero length) packets.
-	</para></listitem>
-
-	<listitem><para>The Linux USB API supports synchronous calls for
-	control and bulk messages.
-	It also supports asynchronous calls for all kinds of data transfer,
-	using request structures called "URBs" (USB Request Blocks).
-	</para></listitem>
-
-    </itemizedlist>
-
-    <para>Accordingly, the USB Core API exposed to device drivers
-    covers quite a lot of territory.  You'll probably need to consult
-    the USB 2.0 specification, available online from www.usb.org at
-    no cost, as well as class or device specifications.
-    </para>
-
-    <para>The only host-side drivers that actually touch hardware
-    (reading/writing registers, handling IRQs, and so on) are the HCDs.
-    In theory, all HCDs provide the same functionality through the same
-    API.  In practice, that's becoming more true on the 2.5 kernels,
-    but there are still differences that crop up especially with
-    fault handling.  Different controllers don't necessarily report
-    the same aspects of failures, and recovery from faults (including
-    software-induced ones like unlinking an URB) isn't yet fully
-    consistent.
-    Device driver authors should make a point of doing disconnect
-    testing (while the device is active) with each different host
-    controller driver, to make sure drivers don't have bugs of
-    their own as well as to make sure they aren't relying on some
-    HCD-specific behavior.
-    (You will need external USB 1.1 and/or
-    USB 2.0 hubs to perform all those tests.)
-    </para>
-
-    </chapter>
-
-<chapter id="types"><title>USB-Standard Types</title>
-
-    <para>In <filename>&lt;linux/usb/ch9.h&gt;</filename> you will find
-    the USB data types defined in chapter 9 of the USB specification.
-    These data types are used throughout USB, and in APIs including
-    this host side API, gadget APIs, and usbfs.
-    </para>
-
-!Iinclude/linux/usb/ch9.h
-
-    </chapter>
-
-<chapter id="hostside"><title>Host-Side Data Types and Macros</title>
-
-    <para>The host side API exposes several layers to drivers, some of
-    which are more necessary than others.
-    These support lifecycle models for host side drivers
-    and devices, and support passing buffers through usbcore to
-    some HCD that performs the I/O for the device driver.
-    </para>
-
-
-!Iinclude/linux/usb.h
-
-    </chapter>
-
-    <chapter id="usbcore"><title>USB Core APIs</title>
-
-    <para>There are two basic I/O models in the USB API.
-    The most elemental one is asynchronous:  drivers submit requests
-    in the form of an URB, and the URB's completion callback
-    handle the next step.
-    All USB transfer types support that model, although there
-    are special cases for control URBs (which always have setup
-    and status stages, but may not have a data stage) and
-    isochronous URBs (which allow large packets and include
-    per-packet fault reports).
-    Built on top of that is synchronous API support, where a
-    driver calls a routine that allocates one or more URBs,
-    submits them, and waits until they complete.
-    There are synchronous wrappers for single-buffer control
-    and bulk transfers (which are awkward to use in some
-    driver disconnect scenarios), and for scatterlist based
-    streaming i/o (bulk or interrupt).
-    </para>
-
-    <para>USB drivers need to provide buffers that can be
-    used for DMA, although they don't necessarily need to
-    provide the DMA mapping themselves.
-    There are APIs to use used when allocating DMA buffers,
-    which can prevent use of bounce buffers on some systems.
-    In some cases, drivers may be able to rely on 64bit DMA
-    to eliminate another kind of bounce buffer.
-    </para>
-
-!Edrivers/usb/core/urb.c
-!Edrivers/usb/core/message.c
-!Edrivers/usb/core/file.c
-!Edrivers/usb/core/driver.c
-!Edrivers/usb/core/usb.c
-!Edrivers/usb/core/hub.c
-    </chapter>
-
-    <chapter id="hcd"><title>Host Controller APIs</title>
-
-    <para>These APIs are only for use by host controller drivers,
-    most of which implement standard register interfaces such as
-    EHCI, OHCI, or UHCI.
-    UHCI was one of the first interfaces, designed by Intel and
-    also used by VIA; it doesn't do much in hardware.
-    OHCI was designed later, to have the hardware do more work
-    (bigger transfers, tracking protocol state, and so on).
-    EHCI was designed with USB 2.0; its design has features that
-    resemble OHCI (hardware does much more work) as well as
-    UHCI (some parts of ISO support, TD list processing).
-    </para>
-
-    <para>There are host controllers other than the "big three",
-    although most PCI based controllers (and a few non-PCI based
-    ones) use one of those interfaces.
-    Not all host controllers use DMA; some use PIO, and there
-    is also a simulator.
-    </para>
-
-    <para>The same basic APIs are available to drivers for all
-    those controllers.  
-    For historical reasons they are in two layers:
-    <structname>struct usb_bus</structname> is a rather thin
-    layer that became available in the 2.2 kernels, while
-    <structname>struct usb_hcd</structname> is a more featureful
-    layer (available in later 2.4 kernels and in 2.5) that
-    lets HCDs share common code, to shrink driver size
-    and significantly reduce hcd-specific behaviors.
-    </para>
-
-!Edrivers/usb/core/hcd.c
-!Edrivers/usb/core/hcd-pci.c
-!Idrivers/usb/core/buffer.c
-    </chapter>
-
-    <chapter id="usbfs">
-	<title>The USB Filesystem (usbfs)</title>
-
-	<para>This chapter presents the Linux <emphasis>usbfs</emphasis>.
-	You may prefer to avoid writing new kernel code for your
-	USB driver; that's the problem that usbfs set out to solve.
-	User mode device drivers are usually packaged as applications
-	or libraries, and may use usbfs through some programming library
-	that wraps it.  Such libraries include
-	<ulink url="http://libusb.sourceforge.net">libusb</ulink>
-	for C/C++, and
-	<ulink url="http://jUSB.sourceforge.net">jUSB</ulink> for Java.
-	</para>
-
-	<note><title>Unfinished</title>
-	    <para>This particular documentation is incomplete,
-	    especially with respect to the asynchronous mode.
-	    As of kernel 2.5.66 the code and this (new) documentation
-	    need to be cross-reviewed.
-	    </para>
-	    </note>
-
-	<para>Configure usbfs into Linux kernels by enabling the
-	<emphasis>USB filesystem</emphasis> option (CONFIG_USB_DEVICEFS),
-	and you get basic support for user mode USB device drivers.
-	Until relatively recently it was often (confusingly) called
-	<emphasis>usbdevfs</emphasis> although it wasn't solving what
-	<emphasis>devfs</emphasis> was.
-	Every USB device will appear in usbfs, regardless of whether or
-	not it has a kernel driver.
-	</para>
-
-	<sect1 id="usbfs-files">
-	    <title>What files are in "usbfs"?</title>
-
-	    <para>Conventionally mounted at
-	    <filename>/proc/bus/usb</filename>, usbfs 
-	    features include:
-	    <itemizedlist>
-		<listitem><para><filename>/proc/bus/usb/devices</filename>
-		    ... a text file
-		    showing each of the USB devices on known to the kernel,
-		    and their configuration descriptors.
-		    You can also poll() this to learn about new devices.
-		    </para></listitem>
-		<listitem><para><filename>/proc/bus/usb/BBB/DDD</filename>
-		    ... magic files
-		    exposing the each device's configuration descriptors, and
-		    supporting a series of ioctls for making device requests,
-		    including I/O to devices.  (Purely for access by programs.)
-		    </para></listitem>
-	    </itemizedlist>
-	    </para>
-
-	    <para> Each bus is given a number (BBB) based on when it was
-	    enumerated; within each bus, each device is given a similar
-	    number (DDD).
-	    Those BBB/DDD paths are not "stable" identifiers;
-	    expect them to change even if you always leave the devices
-	    plugged in to the same hub port.
-	    <emphasis>Don't even think of saving these in application
-	    configuration files.</emphasis>
-	    Stable identifiers are available, for user mode applications
-	    that want to use them.  HID and networking devices expose
-	    these stable IDs, so that for example you can be sure that
-	    you told the right UPS to power down its second server.
-	    "usbfs" doesn't (yet) expose those IDs.
-	    </para>
-
-	</sect1>
-
-	<sect1 id="usbfs-fstab">
-	    <title>Mounting and Access Control</title>
-
-	    <para>There are a number of mount options for usbfs, which will
-	    be of most interest to you if you need to override the default
-	    access control policy.
-	    That policy is that only root may read or write device files
-	    (<filename>/proc/bus/BBB/DDD</filename>) although anyone may read
-	    the <filename>devices</filename>
-	    or <filename>drivers</filename> files.
-	    I/O requests to the device also need the CAP_SYS_RAWIO capability,
-	    </para>
-
-	    <para>The significance of that is that by default, all user mode
-	    device drivers need super-user privileges.
-	    You can change modes or ownership in a driver setup
-	    when the device hotplugs, or maye just start the
-	    driver right then, as a privileged server (or some activity
-	    within one).
-	    That's the most secure approach for multi-user systems,
-	    but for single user systems ("trusted" by that user)
-	    it's more convenient just to grant everyone all access
-	    (using the <emphasis>devmode=0666</emphasis> option)
-	    so the driver can start whenever it's needed.
-	    </para>
-
-	    <para>The mount options for usbfs, usable in /etc/fstab or
-	    in command line invocations of <emphasis>mount</emphasis>, are:
-
-	    <variablelist>
-		<varlistentry>
-		    <term><emphasis>busgid</emphasis>=NNNNN</term>
-		    <listitem><para>Controls the GID used for the
-		    /proc/bus/usb/BBB
-		    directories.  (Default: 0)</para></listitem></varlistentry>
-		<varlistentry><term><emphasis>busmode</emphasis>=MMM</term>
-		    <listitem><para>Controls the file mode used for the
-		    /proc/bus/usb/BBB
-		    directories.  (Default: 0555)
-		    </para></listitem></varlistentry>
-		<varlistentry><term><emphasis>busuid</emphasis>=NNNNN</term>
-		    <listitem><para>Controls the UID used for the
-		    /proc/bus/usb/BBB
-		    directories.  (Default: 0)</para></listitem></varlistentry>
-
-		<varlistentry><term><emphasis>devgid</emphasis>=NNNNN</term>
-		    <listitem><para>Controls the GID used for the
-		    /proc/bus/usb/BBB/DDD
-		    files.  (Default: 0)</para></listitem></varlistentry>
-		<varlistentry><term><emphasis>devmode</emphasis>=MMM</term>
-		    <listitem><para>Controls the file mode used for the
-		    /proc/bus/usb/BBB/DDD
-		    files.  (Default: 0644)</para></listitem></varlistentry>
-		<varlistentry><term><emphasis>devuid</emphasis>=NNNNN</term>
-		    <listitem><para>Controls the UID used for the
-		    /proc/bus/usb/BBB/DDD
-		    files.  (Default: 0)</para></listitem></varlistentry>
-
-		<varlistentry><term><emphasis>listgid</emphasis>=NNNNN</term>
-		    <listitem><para>Controls the GID used for the
-		    /proc/bus/usb/devices and drivers files.
-		    (Default: 0)</para></listitem></varlistentry>
-		<varlistentry><term><emphasis>listmode</emphasis>=MMM</term>
-		    <listitem><para>Controls the file mode used for the
-		    /proc/bus/usb/devices and drivers files.
-		    (Default: 0444)</para></listitem></varlistentry>
-		<varlistentry><term><emphasis>listuid</emphasis>=NNNNN</term>
-		    <listitem><para>Controls the UID used for the
-		    /proc/bus/usb/devices and drivers files.
-		    (Default: 0)</para></listitem></varlistentry>
-	    </variablelist>
-
-	    </para>
-
-	    <para>Note that many Linux distributions hard-wire the mount options
-	    for usbfs in their init scripts, such as
-	    <filename>/etc/rc.d/rc.sysinit</filename>,
-	    rather than making it easy to set this per-system
-	    policy in <filename>/etc/fstab</filename>.
-	    </para>
-
-	</sect1>
-
-	<sect1 id="usbfs-devices">
-	    <title>/proc/bus/usb/devices</title>
-
-	    <para>This file is handy for status viewing tools in user
-	    mode, which can scan the text format and ignore most of it.
-	    More detailed device status (including class and vendor
-	    status) is available from device-specific files.
-	    For information about the current format of this file,
-	    see the
-	    <filename>Documentation/usb/proc_usb_info.txt</filename>
-	    file in your Linux kernel sources.
-	    </para>
-
-	    <para>This file, in combination with the poll() system call, can
-	    also be used to detect when devices are added or removed:
-<programlisting>int fd;
-struct pollfd pfd;
-
-fd = open("/proc/bus/usb/devices", O_RDONLY);
-pfd = { fd, POLLIN, 0 };
-for (;;) {
-	/* The first time through, this call will return immediately. */
-	poll(&amp;pfd, 1, -1);
-
-	/* To see what's changed, compare the file's previous and current
-	   contents or scan the filesystem.  (Scanning is more precise.) */
-}</programlisting>
-	    Note that this behavior is intended to be used for informational
-	    and debug purposes.  It would be more appropriate to use programs
-	    such as udev or HAL to initialize a device or start a user-mode
-	    helper program, for instance.
-	    </para>
-	</sect1>
-
-	<sect1 id="usbfs-bbbddd">
-	    <title>/proc/bus/usb/BBB/DDD</title>
-
-	    <para>Use these files in one of these basic ways:
-	    </para>
-
-	    <para><emphasis>They can be read,</emphasis>
-	    producing first the device descriptor
-	    (18 bytes) and then the descriptors for the current configuration.
-	    See the USB 2.0 spec for details about those binary data formats.
-	    You'll need to convert most multibyte values from little endian
-	    format to your native host byte order, although a few of the
-	    fields in the device descriptor (both of the BCD-encoded fields,
-	    and the vendor and product IDs) will be byteswapped for you.
-	    Note that configuration descriptors include descriptors for
-	    interfaces, altsettings, endpoints, and maybe additional
-	    class descriptors.
-	    </para>
-
-	    <para><emphasis>Perform USB operations</emphasis> using 
-	    <emphasis>ioctl()</emphasis> requests to make endpoint I/O
-	    requests (synchronously or asynchronously) or manage
-	    the device.
-	    These requests need the CAP_SYS_RAWIO capability,
-	    as well as filesystem access permissions.
-	    Only one ioctl request can be made on one of these
-	    device files at a time.
-	    This means that if you are synchronously reading an endpoint
-	    from one thread, you won't be able to write to a different
-	    endpoint from another thread until the read completes.
-	    This works for <emphasis>half duplex</emphasis> protocols,
-	    but otherwise you'd use asynchronous i/o requests. 
-	    </para>
-
-	    </sect1>
-
-
-	<sect1 id="usbfs-lifecycle">
-	    <title>Life Cycle of User Mode Drivers</title>
-
-	    <para>Such a driver first needs to find a device file
-	    for a device it knows how to handle.
-	    Maybe it was told about it because a
-	    <filename>/sbin/hotplug</filename> event handling agent
-	    chose that driver to handle the new device.
-	    Or maybe it's an application that scans all the
-	    /proc/bus/usb device files, and ignores most devices.
-	    In either case, it should <function>read()</function> all
-	    the descriptors from the device file,
-	    and check them against what it knows how to handle.
-	    It might just reject everything except a particular
-	    vendor and product ID, or need a more complex policy.
-	    </para>
-
-	    <para>Never assume there will only be one such device
-	    on the system at a time!
-	    If your code can't handle more than one device at
-	    a time, at least detect when there's more than one, and
-	    have your users choose which device to use.
-	    </para>
-
-	    <para>Once your user mode driver knows what device to use,
-	    it interacts with it in either of two styles.
-	    The simple style is to make only control requests; some
-	    devices don't need more complex interactions than those.
-	    (An example might be software using vendor-specific control
-	    requests for some initialization or configuration tasks,
-	    with a kernel driver for the rest.)
-	    </para>
-
-	    <para>More likely, you need a more complex style driver:
-	    one using non-control endpoints, reading or writing data
-	    and claiming exclusive use of an interface.
-	    <emphasis>Bulk</emphasis> transfers are easiest to use,
-	    but only their sibling <emphasis>interrupt</emphasis> transfers 
-	    work with low speed devices.
-	    Both interrupt and <emphasis>isochronous</emphasis> transfers
-	    offer service guarantees because their bandwidth is reserved.
-	    Such "periodic" transfers are awkward to use through usbfs,
-	    unless you're using the asynchronous calls.  However, interrupt
-	    transfers can also be used in a synchronous "one shot" style.
-	    </para>
-
-	    <para>Your user-mode driver should never need to worry
-	    about cleaning up request state when the device is
-	    disconnected, although it should close its open file
-	    descriptors as soon as it starts seeing the ENODEV
-	    errors.
-	    </para>
-
-	    </sect1>
-
-	<sect1 id="usbfs-ioctl"><title>The ioctl() Requests</title>
-
-	    <para>To use these ioctls, you need to include the following
-	    headers in your userspace program:
-<programlisting>#include &lt;linux/usb.h&gt;
-#include &lt;linux/usbdevice_fs.h&gt;
-#include &lt;asm/byteorder.h&gt;</programlisting>
-	    The standard USB device model requests, from "Chapter 9" of
-	    the USB 2.0 specification, are automatically included from
-	    the <filename>&lt;linux/usb/ch9.h&gt;</filename> header.
-	    </para>
-
-	    <para>Unless noted otherwise, the ioctl requests
-	    described here will
-	    update the modification time on the usbfs file to which
-	    they are applied (unless they fail).
-	    A return of zero indicates success; otherwise, a
-	    standard USB error code is returned.  (These are
-	    documented in
-	    <filename>Documentation/usb/error-codes.txt</filename>
-	    in your kernel sources.)
-	    </para>
-
-	    <para>Each of these files multiplexes access to several
-	    I/O streams, one per endpoint.
-	    Each device has one control endpoint (endpoint zero)
-	    which supports a limited RPC style RPC access.
-	    Devices are configured
-	    by hub_wq (in the kernel) setting a device-wide
-	    <emphasis>configuration</emphasis> that affects things
-	    like power consumption and basic functionality.
-	    The endpoints are part of USB <emphasis>interfaces</emphasis>,
-	    which may have <emphasis>altsettings</emphasis>
-	    affecting things like which endpoints are available.
-	    Many devices only have a single configuration and interface,
-	    so drivers for them will ignore configurations and altsettings.
-	    </para>
-
-
-	    <sect2 id="usbfs-mgmt">
-		<title>Management/Status Requests</title>
-
-		<para>A number of usbfs requests don't deal very directly
-		with device I/O.
-		They mostly relate to device management and status.
-		These are all synchronous requests.
-		</para>
-
-		<variablelist>
-
-		<varlistentry><term>USBDEVFS_CLAIMINTERFACE</term>
-		    <listitem><para>This is used to force usbfs to
-		    claim a specific interface,
-		    which has not previously been claimed by usbfs or any other
-		    kernel driver.
-		    The ioctl parameter is an integer holding the number of
-		    the interface (bInterfaceNumber from descriptor).
-		    </para><para>
-		    Note that if your driver doesn't claim an interface
-		    before trying to use one of its endpoints, and no
-		    other driver has bound to it, then the interface is
-		    automatically claimed by usbfs.
-		    </para><para>
-		    This claim will be released by a RELEASEINTERFACE ioctl,
-		    or by closing the file descriptor.
-		    File modification time is not updated by this request.
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_CONNECTINFO</term>
-		    <listitem><para>Says whether the device is lowspeed.
-		    The ioctl parameter points to a structure like this:
-<programlisting>struct usbdevfs_connectinfo {
-        unsigned int   devnum;
-        unsigned char  slow;
-}; </programlisting>
-		    File modification time is not updated by this request.
-		    </para><para>
-		    <emphasis>You can't tell whether a "not slow"
-		    device is connected at high speed (480 MBit/sec)
-		    or just full speed (12 MBit/sec).</emphasis>
-		    You should know the devnum value already,
-		    it's the DDD value of the device file name.
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_GETDRIVER</term>
-		    <listitem><para>Returns the name of the kernel driver
-		    bound to a given interface (a string).  Parameter
-		    is a pointer to this structure, which is modified:
-<programlisting>struct usbdevfs_getdriver {
-        unsigned int  interface;
-        char          driver[USBDEVFS_MAXDRIVERNAME + 1];
-};</programlisting>
-		    File modification time is not updated by this request.
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_IOCTL</term>
-		    <listitem><para>Passes a request from userspace through
-		    to a kernel driver that has an ioctl entry in the
-		    <emphasis>struct usb_driver</emphasis> it registered.
-<programlisting>struct usbdevfs_ioctl {
-        int     ifno;
-        int     ioctl_code;
-        void    *data;
-};
-
-/* user mode call looks like this.
- * 'request' becomes the driver->ioctl() 'code' parameter.
- * the size of 'param' is encoded in 'request', and that data
- * is copied to or from the driver->ioctl() 'buf' parameter.
- */
-static int
-usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
-{
-        struct usbdevfs_ioctl	wrapper;
-
-        wrapper.ifno = ifno;
-        wrapper.ioctl_code = request;
-        wrapper.data = param;
-
-        return ioctl (fd, USBDEVFS_IOCTL, &amp;wrapper);
-} </programlisting>
-		    File modification time is not updated by this request.
-		    </para><para>
-		    This request lets kernel drivers talk to user mode code
-		    through filesystem operations even when they don't create
-		    a character or block special device.
-		    It's also been used to do things like ask devices what
-		    device special file should be used.
-		    Two pre-defined ioctls are used
-		    to disconnect and reconnect kernel drivers, so
-		    that user mode code can completely manage binding
-		    and configuration of devices.
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_RELEASEINTERFACE</term>
-		    <listitem><para>This is used to release the claim usbfs
-		    made on interface, either implicitly or because of a
-		    USBDEVFS_CLAIMINTERFACE call, before the file
-		    descriptor is closed.
-		    The ioctl parameter is an integer holding the number of
-		    the interface (bInterfaceNumber from descriptor);
-		    File modification time is not updated by this request.
-		    </para><warning><para>
-		    <emphasis>No security check is made to ensure
-		    that the task which made the claim is the one
-		    which is releasing it.
-		    This means that user mode driver may interfere
-		    other ones.  </emphasis>
-		    </para></warning></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_RESETEP</term>
-		    <listitem><para>Resets the data toggle value for an endpoint
-		    (bulk or interrupt) to DATA0.
-		    The ioctl parameter is an integer endpoint number
-		    (1 to 15, as identified in the endpoint descriptor),
-		    with USB_DIR_IN added if the device's endpoint sends
-		    data to the host.
-		    </para><warning><para>
-		    <emphasis>Avoid using this request.
-		    It should probably be removed.</emphasis>
-		    Using it typically means the device and driver will lose
-		    toggle synchronization.  If you really lost synchronization,
-		    you likely need to completely handshake with the device,
-		    using a request like CLEAR_HALT
-		    or SET_INTERFACE.
-		    </para></warning></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_DROP_PRIVILEGES</term>
-		    <listitem><para>This is used to relinquish the ability
-		    to do certain operations which are considered to be
-		    privileged on a usbfs file descriptor.
-		    This includes claiming arbitrary interfaces, resetting
-		    a device on which there are currently claimed interfaces
-		    from other users, and issuing USBDEVFS_IOCTL calls.
-		    The ioctl parameter is a 32 bit mask of interfaces
-		    the user is allowed to claim on this file descriptor.
-		    You may issue this ioctl more than one time to narrow
-		    said mask.
-		    </para></listitem></varlistentry>
-		</variablelist>
-
-		</sect2>
-
-	    <sect2 id="usbfs-sync">
-		<title>Synchronous I/O Support</title>
-
-		<para>Synchronous requests involve the kernel blocking
-		until the user mode request completes, either by
-		finishing successfully or by reporting an error.
-		In most cases this is the simplest way to use usbfs,
-		although as noted above it does prevent performing I/O
-		to more than one endpoint at a time.
-		</para>
-
-		<variablelist>
-
-		<varlistentry><term>USBDEVFS_BULK</term>
-		    <listitem><para>Issues a bulk read or write request to the
-		    device.
-		    The ioctl parameter is a pointer to this structure:
-<programlisting>struct usbdevfs_bulktransfer {
-        unsigned int  ep;
-        unsigned int  len;
-        unsigned int  timeout; /* in milliseconds */
-        void          *data;
-};</programlisting>
-		    </para><para>The "ep" value identifies a
-		    bulk endpoint number (1 to 15, as identified in an endpoint
-		    descriptor),
-		    masked with USB_DIR_IN when referring to an endpoint which
-		    sends data to the host from the device.
-		    The length of the data buffer is identified by "len";
-		    Recent kernels support requests up to about 128KBytes.
-		    <emphasis>FIXME say how read length is returned,
-		    and how short reads are handled.</emphasis>.
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_CLEAR_HALT</term>
-		    <listitem><para>Clears endpoint halt (stall) and
-		    resets the endpoint toggle.  This is only
-		    meaningful for bulk or interrupt endpoints.
-		    The ioctl parameter is an integer endpoint number
-		    (1 to 15, as identified in an endpoint descriptor),
-		    masked with USB_DIR_IN when referring to an endpoint which
-		    sends data to the host from the device.
-		    </para><para>
-		    Use this on bulk or interrupt endpoints which have
-		    stalled, returning <emphasis>-EPIPE</emphasis> status
-		    to a data transfer request.
-		    Do not issue the control request directly, since
-		    that could invalidate the host's record of the
-		    data toggle.
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_CONTROL</term>
-		    <listitem><para>Issues a control request to the device.
-		    The ioctl parameter points to a structure like this:
-<programlisting>struct usbdevfs_ctrltransfer {
-        __u8   bRequestType;
-        __u8   bRequest;
-        __u16  wValue;
-        __u16  wIndex;
-        __u16  wLength;
-        __u32  timeout;  /* in milliseconds */
-        void   *data;
-};</programlisting>
-		    </para><para>
-		    The first eight bytes of this structure are the contents
-		    of the SETUP packet to be sent to the device; see the
-		    USB 2.0 specification for details.
-		    The bRequestType value is composed by combining a
-		    USB_TYPE_* value, a USB_DIR_* value, and a
-		    USB_RECIP_* value (from
-		    <emphasis>&lt;linux/usb.h&gt;</emphasis>).
-		    If wLength is nonzero, it describes the length of the data
-		    buffer, which is either written to the device
-		    (USB_DIR_OUT) or read from the device (USB_DIR_IN).
-		    </para><para>
-		    At this writing, you can't transfer more than 4 KBytes
-		    of data to or from a device; usbfs has a limit, and
-		    some host controller drivers have a limit.
-		    (That's not usually a problem.)
-		    <emphasis>Also</emphasis> there's no way to say it's
-		    not OK to get a short read back from the device.
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_RESET</term>
-		    <listitem><para>Does a USB level device reset.
-		    The ioctl parameter is ignored.
-		    After the reset, this rebinds all device interfaces.
-		    File modification time is not updated by this request.
-		    </para><warning><para>
-		    <emphasis>Avoid using this call</emphasis>
-		    until some usbcore bugs get fixed,
-		    since it does not fully synchronize device, interface,
-		    and driver (not just usbfs) state.
-		    </para></warning></listitem></varlistentry>
-	    
-		<varlistentry><term>USBDEVFS_SETINTERFACE</term>
-		    <listitem><para>Sets the alternate setting for an
-		    interface.  The ioctl parameter is a pointer to a
-		    structure like this:
-<programlisting>struct usbdevfs_setinterface {
-        unsigned int  interface;
-        unsigned int  altsetting;
-}; </programlisting>
-		    File modification time is not updated by this request.
-		    </para><para>
-		    Those struct members are from some interface descriptor
-		    applying to the current configuration.
-		    The interface number is the bInterfaceNumber value, and
-		    the altsetting number is the bAlternateSetting value.
-		    (This resets each endpoint in the interface.)
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_SETCONFIGURATION</term>
-		    <listitem><para>Issues the
-		    <function>usb_set_configuration</function> call
-		    for the device.
-		    The parameter is an integer holding the number of
-		    a configuration (bConfigurationValue from descriptor).
-		    File modification time is not updated by this request.
-		    </para><warning><para>
-		    <emphasis>Avoid using this call</emphasis>
-		    until some usbcore bugs get fixed,
-		    since it does not fully synchronize device, interface,
-		    and driver (not just usbfs) state.
-		    </para></warning></listitem></varlistentry>
-
-		</variablelist>
-	    </sect2>
-
-	    <sect2 id="usbfs-async">
-		<title>Asynchronous I/O Support</title>
-
-		<para>As mentioned above, there are situations where it may be
-		important to initiate concurrent operations from user mode code.
-		This is particularly important for periodic transfers
-		(interrupt and isochronous), but it can be used for other
-		kinds of USB requests too.
-		In such cases, the asynchronous requests described here
-		are essential.  Rather than submitting one request and having
-		the kernel block until it completes, the blocking is separate.
-		</para>
-
-		<para>These requests are packaged into a structure that
-		resembles the URB used by kernel device drivers.
-		(No POSIX Async I/O support here, sorry.)
-		It identifies the endpoint type (USBDEVFS_URB_TYPE_*),
-		endpoint (number, masked with USB_DIR_IN as appropriate),
-		buffer and length, and a user "context" value serving to
-		uniquely identify each request.
-		(It's usually a pointer to per-request data.)
-		Flags can modify requests (not as many as supported for
-		kernel drivers).
-		</para>
-
-		<para>Each request can specify a realtime signal number
-		(between SIGRTMIN and SIGRTMAX, inclusive) to request a
-		signal be sent when the request completes.
-		</para>
-
-		<para>When usbfs returns these urbs, the status value
-		is updated, and the buffer may have been modified.
-		Except for isochronous transfers, the actual_length is
-		updated to say how many bytes were transferred; if the
-		USBDEVFS_URB_DISABLE_SPD flag is set
-		("short packets are not OK"), if fewer bytes were read
-		than were requested then you get an error report.
-		</para>
-
-<programlisting>struct usbdevfs_iso_packet_desc {
-        unsigned int                     length;
-        unsigned int                     actual_length;
-        unsigned int                     status;
-};
-
-struct usbdevfs_urb {
-        unsigned char                    type;
-        unsigned char                    endpoint;
-        int                              status;
-        unsigned int                     flags;
-        void                             *buffer;
-        int                              buffer_length;
-        int                              actual_length;
-        int                              start_frame;
-        int                              number_of_packets;
-        int                              error_count;
-        unsigned int                     signr;
-        void                             *usercontext;
-        struct usbdevfs_iso_packet_desc  iso_frame_desc[];
-};</programlisting>
-
-		<para> For these asynchronous requests, the file modification
-		time reflects when the request was initiated.
-		This contrasts with their use with the synchronous requests,
-		where it reflects when requests complete.
-		</para>
-
-		<variablelist>
-
-		<varlistentry><term>USBDEVFS_DISCARDURB</term>
-		    <listitem><para>
-		    <emphasis>TBS</emphasis>
-		    File modification time is not updated by this request.
-		    </para><para>
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_DISCSIGNAL</term>
-		    <listitem><para>
-		    <emphasis>TBS</emphasis>
-		    File modification time is not updated by this request.
-		    </para><para>
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_REAPURB</term>
-		    <listitem><para>
-		    <emphasis>TBS</emphasis>
-		    File modification time is not updated by this request.
-		    </para><para>
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_REAPURBNDELAY</term>
-		    <listitem><para>
-		    <emphasis>TBS</emphasis>
-		    File modification time is not updated by this request.
-		    </para><para>
-		    </para></listitem></varlistentry>
-
-		<varlistentry><term>USBDEVFS_SUBMITURB</term>
-		    <listitem><para>
-		    <emphasis>TBS</emphasis>
-		    </para><para>
-		    </para></listitem></varlistentry>
-
-		</variablelist>
-	    </sect2>
-
-	</sect1>
-
-    </chapter>
-
-</book>
-<!-- vim:syntax=sgml:sw=4
--->
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl linux-libre-4.10-rc8-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl
--- linux-libre-4.9-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl	1969-12-31 19:00:00.000000000 -0500
@@ -1,6206 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<!-- ****************************************************** -->
-<!-- Header  -->
-<!-- ****************************************************** -->
-<book id="Writing-an-ALSA-Driver">
-  <bookinfo>
-    <title>Writing an ALSA Driver</title>
-    <author>
-      <firstname>Takashi</firstname>
-      <surname>Iwai</surname>
-      <affiliation>
-        <address>
-          <email>tiwai@suse.de</email>
-        </address>
-      </affiliation>
-     </author>
-
-     <date>Oct 15, 2007</date>
-     <edition>0.3.7</edition>
-
-    <abstract>
-      <para>
-        This document describes how to write an ALSA (Advanced Linux
-        Sound Architecture) driver.
-      </para>
-    </abstract>
-
-    <legalnotice>
-    <para>
-    Copyright (c) 2002-2005  Takashi Iwai <email>tiwai@suse.de</email>
-    </para>
-
-    <para>
-    This document is free; you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version. 
-    </para>
-
-    <para>
-    This document is distributed in the hope that it will be useful,
-    but <emphasis>WITHOUT ANY WARRANTY</emphasis>; without even the
-    implied warranty of <emphasis>MERCHANTABILITY or FITNESS FOR A
-    PARTICULAR PURPOSE</emphasis>. See the GNU General Public License
-    for more details.
-    </para>
-
-    <para>
-    You should have received a copy of the GNU General Public
-    License along with this program; if not, write to the Free
-    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-    MA 02111-1307 USA
-    </para>
-    </legalnotice>
-
-  </bookinfo>
-
-<!-- ****************************************************** -->
-<!-- Preface  -->
-<!-- ****************************************************** -->
-  <preface id="preface">
-    <title>Preface</title>
-    <para>
-      This document describes how to write an
-      <ulink url="http://www.alsa-project.org/"><citetitle>
-      ALSA (Advanced Linux Sound Architecture)</citetitle></ulink>
-      driver. The document focuses mainly on PCI soundcards.
-      In the case of other device types, the API might
-      be different, too. However, at least the ALSA kernel API is
-      consistent, and therefore it would be still a bit help for
-      writing them.
-    </para>
-
-    <para>
-    This document targets people who already have enough
-    C language skills and have basic linux kernel programming
-    knowledge.  This document doesn't explain the general
-    topic of linux kernel coding and doesn't cover low-level
-    driver implementation details. It only describes
-    the standard way to write a PCI sound driver on ALSA.
-    </para>
-
-    <para>
-      If you are already familiar with the older ALSA ver.0.5.x API, you
-    can check the drivers such as <filename>sound/pci/es1938.c</filename> or
-    <filename>sound/pci/maestro3.c</filename> which have also almost the same
-    code-base in the ALSA 0.5.x tree, so you can compare the differences.
-    </para>
-
-    <para>
-      This document is still a draft version. Any feedback and
-    corrections, please!!
-    </para>
-  </preface>
-
-
-<!-- ****************************************************** -->
-<!-- File Tree Structure  -->
-<!-- ****************************************************** -->
-  <chapter id="file-tree">
-    <title>File Tree Structure</title>
-
-    <section id="file-tree-general">
-      <title>General</title>
-      <para>
-        The ALSA drivers are provided in two ways.
-      </para>
-
-      <para>
-        One is the trees provided as a tarball or via cvs from the
-      ALSA's ftp site, and another is the 2.6 (or later) Linux kernel
-      tree. To synchronize both, the ALSA driver tree is split into
-      two different trees: alsa-kernel and alsa-driver. The former
-      contains purely the source code for the Linux 2.6 (or later)
-      tree. This tree is designed only for compilation on 2.6 or
-      later environment. The latter, alsa-driver, contains many subtle
-      files for compiling ALSA drivers outside of the Linux kernel tree,
-      wrapper functions for older 2.2 and 2.4 kernels, to adapt the latest kernel API,
-      and additional drivers which are still in development or in
-      tests.  The drivers in alsa-driver tree will be moved to
-      alsa-kernel (and eventually to the 2.6 kernel tree) when they are
-      finished and confirmed to work fine.
-      </para>
-
-      <para>
-        The file tree structure of ALSA driver is depicted below. Both
-        alsa-kernel and alsa-driver have almost the same file
-        structure, except for <quote>core</quote> directory. It's
-        named as <quote>acore</quote> in alsa-driver tree. 
-
-        <example>
-          <title>ALSA File Tree Structure</title>
-          <literallayout>
-        sound
-                /core
-                        /oss
-                        /seq
-                                /oss
-                                /instr
-                /ioctl32
-                /include
-                /drivers
-                        /mpu401
-                        /opl3
-                /i2c
-                        /l3
-                /synth
-                        /emux
-                /pci
-                        /(cards)
-                /isa
-                        /(cards)
-                /arm
-                /ppc
-                /sparc
-                /usb
-                /pcmcia /(cards)
-                /oss
-          </literallayout>
-        </example>
-      </para>
-    </section>
-
-    <section id="file-tree-core-directory">
-      <title>core directory</title>
-      <para>
-        This directory contains the middle layer which is the heart
-      of ALSA drivers. In this directory, the native ALSA modules are
-      stored. The sub-directories contain different modules and are
-      dependent upon the kernel config. 
-      </para>
-
-      <section id="file-tree-core-directory-oss">
-        <title>core/oss</title>
-
-        <para>
-          The codes for PCM and mixer OSS emulation modules are stored
-        in this directory. The rawmidi OSS emulation is included in
-        the ALSA rawmidi code since it's quite small. The sequencer
-        code is stored in <filename>core/seq/oss</filename> directory (see
-        <link linkend="file-tree-core-directory-seq-oss"><citetitle>
-        below</citetitle></link>).
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-ioctl32">
-        <title>core/ioctl32</title>
-
-        <para>
-          This directory contains the 32bit-ioctl wrappers for 64bit
-        architectures such like x86-64, ppc64 and sparc64. For 32bit
-        and alpha architectures, these are not compiled. 
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-seq">
-        <title>core/seq</title>
-        <para>
-          This directory and its sub-directories are for the ALSA
-        sequencer. This directory contains the sequencer core and
-        primary sequencer modules such like snd-seq-midi,
-        snd-seq-virmidi, etc. They are compiled only when
-        <constant>CONFIG_SND_SEQUENCER</constant> is set in the kernel
-        config. 
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-seq-oss">
-        <title>core/seq/oss</title>
-        <para>
-          This contains the OSS sequencer emulation codes.
-        </para>
-      </section>
-
-      <section id="file-tree-core-directory-deq-instr">
-        <title>core/seq/instr</title>
-        <para>
-          This directory contains the modules for the sequencer
-        instrument layer. 
-        </para>
-      </section>
-    </section>
-
-    <section id="file-tree-include-directory">
-      <title>include directory</title>
-      <para>
-        This is the place for the public header files of ALSA drivers,
-      which are to be exported to user-space, or included by
-      several files at different directories. Basically, the private
-      header files should not be placed in this directory, but you may
-      still find files there, due to historical reasons :) 
-      </para>
-    </section>
-
-    <section id="file-tree-drivers-directory">
-      <title>drivers directory</title>
-      <para>
-        This directory contains code shared among different drivers
-      on different architectures.  They are hence supposed not to be
-      architecture-specific.
-      For example, the dummy pcm driver and the serial MIDI
-      driver are found in this directory. In the sub-directories,
-      there is code for components which are independent from
-      bus and cpu architectures. 
-      </para>
-
-      <section id="file-tree-drivers-directory-mpu401">
-        <title>drivers/mpu401</title>
-        <para>
-          The MPU401 and MPU401-UART modules are stored here.
-        </para>
-      </section>
-
-      <section id="file-tree-drivers-directory-opl3">
-        <title>drivers/opl3 and opl4</title>
-        <para>
-          The OPL3 and OPL4 FM-synth stuff is found here.
-        </para>
-      </section>
-    </section>
-
-    <section id="file-tree-i2c-directory">
-      <title>i2c directory</title>
-      <para>
-        This contains the ALSA i2c components.
-      </para>
-
-      <para>
-        Although there is a standard i2c layer on Linux, ALSA has its
-      own i2c code for some cards, because the soundcard needs only a
-      simple operation and the standard i2c API is too complicated for
-      such a purpose. 
-      </para>
-
-      <section id="file-tree-i2c-directory-l3">
-        <title>i2c/l3</title>
-        <para>
-          This is a sub-directory for ARM L3 i2c.
-        </para>
-      </section>
-    </section>
-
-    <section id="file-tree-synth-directory">
-        <title>synth directory</title>
-        <para>
-          This contains the synth middle-level modules.
-        </para>
-
-        <para>
-          So far, there is only Emu8000/Emu10k1 synth driver under
-        the <filename>synth/emux</filename> sub-directory. 
-        </para>
-    </section>
-
-    <section id="file-tree-pci-directory">
-      <title>pci directory</title>
-      <para>
-        This directory and its sub-directories hold the top-level card modules
-      for PCI soundcards and the code specific to the PCI BUS.
-      </para>
-
-      <para>
-        The drivers compiled from a single file are stored directly
-      in the pci directory, while the drivers with several source files are
-      stored on their own sub-directory (e.g. emu10k1, ice1712). 
-      </para>
-    </section>
-
-    <section id="file-tree-isa-directory">
-      <title>isa directory</title>
-      <para>
-        This directory and its sub-directories hold the top-level card modules
-      for ISA soundcards. 
-      </para>
-    </section>
-
-    <section id="file-tree-arm-ppc-sparc-directories">
-      <title>arm, ppc, and sparc directories</title>
-      <para>
-        They are used for top-level card modules which are
-      specific to one of these architectures. 
-      </para>
-    </section>
-
-    <section id="file-tree-usb-directory">
-      <title>usb directory</title>
-      <para>
-        This directory contains the USB-audio driver. In the latest version, the
-      USB MIDI driver is integrated in the usb-audio driver. 
-      </para>
-    </section>
-
-    <section id="file-tree-pcmcia-directory">
-      <title>pcmcia directory</title>
-      <para>
-        The PCMCIA, especially PCCard drivers will go here. CardBus
-      drivers will be in the pci directory, because their API is identical
-      to that of standard PCI cards. 
-      </para>
-    </section>
-
-    <section id="file-tree-oss-directory">
-      <title>oss directory</title>
-      <para>
-        The OSS/Lite source files are stored here in Linux 2.6 (or
-      later) tree. In the ALSA driver tarball, this directory is empty,
-      of course :) 
-      </para>
-    </section>
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Basic Flow for PCI Drivers  -->
-<!-- ****************************************************** -->
-  <chapter id="basic-flow">
-    <title>Basic Flow for PCI Drivers</title>
-
-    <section id="basic-flow-outline">
-      <title>Outline</title>
-      <para>
-        The minimum flow for PCI soundcards is as follows:
-
-        <itemizedlist>
-          <listitem><para>define the PCI ID table (see the section
-          <link linkend="pci-resource-entries"><citetitle>PCI Entries
-          </citetitle></link>).</para></listitem> 
-          <listitem><para>create <function>probe()</function> callback.</para></listitem>
-          <listitem><para>create <function>remove()</function> callback.</para></listitem>
-          <listitem><para>create a <structname>pci_driver</structname> structure
-	  containing the three pointers above.</para></listitem>
-          <listitem><para>create an <function>init()</function> function just calling
-	  the <function>pci_register_driver()</function> to register the pci_driver table
-	  defined above.</para></listitem>
-          <listitem><para>create an <function>exit()</function> function to call
-	  the <function>pci_unregister_driver()</function> function.</para></listitem>
-        </itemizedlist>
-      </para>
-    </section>
-
-    <section id="basic-flow-example">
-      <title>Full Code Example</title>
-      <para>
-        The code example is shown below. Some parts are kept
-      unimplemented at this moment but will be filled in the
-      next sections. The numbers in the comment lines of the
-      <function>snd_mychip_probe()</function> function
-      refer to details explained in the following section. 
-
-        <example>
-          <title>Basic Flow for PCI Drivers - Example</title>
-          <programlisting>
-<![CDATA[
-  #include <linux/init.h>
-  #include <linux/pci.h>
-  #include <linux/slab.h>
-  #include <sound/core.h>
-  #include <sound/initval.h>
-
-  /* module parameters (see "Module Parameters") */
-  /* SNDRV_CARDS: maximum number of cards supported by this module */
-  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-  static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-
-  /* definition of the chip-specific record */
-  struct mychip {
-          struct snd_card *card;
-          /* the rest of the implementation will be in section
-           * "PCI Resource Management"
-           */
-  };
-
-  /* chip-specific destructor
-   * (see "PCI Resource Management")
-   */
-  static int snd_mychip_free(struct mychip *chip)
-  {
-          .... /* will be implemented later... */
-  }
-
-  /* component-destructor
-   * (see "Management of Cards and Components")
-   */
-  static int snd_mychip_dev_free(struct snd_device *device)
-  {
-          return snd_mychip_free(device->device_data);
-  }
-
-  /* chip-specific constructor
-   * (see "Management of Cards and Components")
-   */
-  static int snd_mychip_create(struct snd_card *card,
-                               struct pci_dev *pci,
-                               struct mychip **rchip)
-  {
-          struct mychip *chip;
-          int err;
-          static struct snd_device_ops ops = {
-                 .dev_free = snd_mychip_dev_free,
-          };
-
-          *rchip = NULL;
-
-          /* check PCI availability here
-           * (see "PCI Resource Management")
-           */
-          ....
-
-          /* allocate a chip-specific data with zero filled */
-          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-          if (chip == NULL)
-                  return -ENOMEM;
-
-          chip->card = card;
-
-          /* rest of initialization here; will be implemented
-           * later, see "PCI Resource Management"
-           */
-          ....
-
-          err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-          if (err < 0) {
-                  snd_mychip_free(chip);
-                  return err;
-          }
-
-          *rchip = chip;
-          return 0;
-  }
-
-  /* constructor -- see "Constructor" sub-section */
-  static int snd_mychip_probe(struct pci_dev *pci,
-                              const struct pci_device_id *pci_id)
-  {
-          static int dev;
-          struct snd_card *card;
-          struct mychip *chip;
-          int err;
-
-          /* (1) */
-          if (dev >= SNDRV_CARDS)
-                  return -ENODEV;
-          if (!enable[dev]) {
-                  dev++;
-                  return -ENOENT;
-          }
-
-          /* (2) */
-          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                             0, &card);
-          if (err < 0)
-                  return err;
-
-          /* (3) */
-          err = snd_mychip_create(card, pci, &chip);
-          if (err < 0) {
-                  snd_card_free(card);
-                  return err;
-          }
-
-          /* (4) */
-          strcpy(card->driver, "My Chip");
-          strcpy(card->shortname, "My Own Chip 123");
-          sprintf(card->longname, "%s at 0x%lx irq %i",
-                  card->shortname, chip->ioport, chip->irq);
-
-          /* (5) */
-          .... /* implemented later */
-
-          /* (6) */
-          err = snd_card_register(card);
-          if (err < 0) {
-                  snd_card_free(card);
-                  return err;
-          }
-
-          /* (7) */
-          pci_set_drvdata(pci, card);
-          dev++;
-          return 0;
-  }
-
-  /* destructor -- see the "Destructor" sub-section */
-  static void snd_mychip_remove(struct pci_dev *pci)
-  {
-          snd_card_free(pci_get_drvdata(pci));
-          pci_set_drvdata(pci, NULL);
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="basic-flow-constructor">
-      <title>Constructor</title>
-      <para>
-        The real constructor of PCI drivers is the <function>probe</function> callback.
-      The <function>probe</function> callback and other component-constructors which are called
-      from the <function>probe</function> callback cannot be used with
-      the <parameter>__init</parameter> prefix
-      because any PCI device could be a hotplug device. 
-      </para>
-
-      <para>
-        In the <function>probe</function> callback, the following scheme is often used.
-      </para>
-
-      <section id="basic-flow-constructor-device-index">
-        <title>1) Check and increment the device index.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int dev;
-  ....
-  if (dev >= SNDRV_CARDS)
-          return -ENODEV;
-  if (!enable[dev]) {
-          dev++;
-          return -ENOENT;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-        where enable[dev] is the module option.
-        </para>
-
-        <para>
-          Each time the <function>probe</function> callback is called, check the
-        availability of the device. If not available, simply increment
-        the device index and returns. dev will be incremented also
-        later (<link
-        linkend="basic-flow-constructor-set-pci"><citetitle>step
-        7</citetitle></link>). 
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-create-card">
-        <title>2) Create a card instance</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct snd_card *card;
-  int err;
-  ....
-  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                     0, &card);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          The details will be explained in the section
-          <link linkend="card-management-card-instance"><citetitle>
-          Management of Cards and Components</citetitle></link>.
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-create-main">
-        <title>3) Create a main component</title>
-        <para>
-          In this part, the PCI resources are allocated.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct mychip *chip;
-  ....
-  err = snd_mychip_create(card, pci, &chip);
-  if (err < 0) {
-          snd_card_free(card);
-          return err;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-          The details will be explained in the section <link
-        linkend="pci-resource"><citetitle>PCI Resource
-        Management</citetitle></link>.
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-main-component">
-        <title>4) Set the driver ID and name strings.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  strcpy(card->driver, "My Chip");
-  strcpy(card->shortname, "My Own Chip 123");
-  sprintf(card->longname, "%s at 0x%lx irq %i",
-          card->shortname, chip->ioport, chip->irq);
-]]>
-            </programlisting>
-          </informalexample>
-
-          The driver field holds the minimal ID string of the
-        chip. This is used by alsa-lib's configurator, so keep it
-        simple but unique. 
-          Even the same driver can have different driver IDs to
-        distinguish the functionality of each chip type. 
-        </para>
-
-        <para>
-          The shortname field is a string shown as more verbose
-        name. The longname field contains the information
-        shown in <filename>/proc/asound/cards</filename>. 
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-create-other">
-        <title>5) Create other components, such as mixer, MIDI, etc.</title>
-        <para>
-          Here you define the basic components such as
-          <link linkend="pcm-interface"><citetitle>PCM</citetitle></link>,
-          mixer (e.g. <link linkend="api-ac97"><citetitle>AC97</citetitle></link>),
-          MIDI (e.g. <link linkend="midi-interface"><citetitle>MPU-401</citetitle></link>),
-          and other interfaces.
-          Also, if you want a <link linkend="proc-interface"><citetitle>proc
-        file</citetitle></link>, define it here, too.
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-register-card">
-        <title>6) Register the card instance.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  err = snd_card_register(card);
-  if (err < 0) {
-          snd_card_free(card);
-          return err;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          Will be explained in the section <link
-        linkend="card-management-registration"><citetitle>Management
-        of Cards and Components</citetitle></link>, too. 
-        </para>
-      </section>
-
-      <section id="basic-flow-constructor-set-pci">
-        <title>7) Set the PCI driver data and return zero.</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-        pci_set_drvdata(pci, card);
-        dev++;
-        return 0;
-]]>
-            </programlisting>
-          </informalexample>
-
-          In the above, the card record is stored. This pointer is
-        used in the remove callback and power-management
-        callbacks, too. 
-        </para>
-      </section>
-    </section>
-
-    <section id="basic-flow-destructor">
-      <title>Destructor</title>
-      <para>
-        The destructor, remove callback, simply releases the card
-      instance. Then the ALSA middle layer will release all the
-      attached components automatically. 
-      </para>
-
-      <para>
-        It would be typically like the following:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_mychip_remove(struct pci_dev *pci)
-  {
-          snd_card_free(pci_get_drvdata(pci));
-          pci_set_drvdata(pci, NULL);
-  }
-]]>
-          </programlisting>
-        </informalexample>
-
-        The above code assumes that the card pointer is set to the PCI
-	driver data.
-      </para>
-    </section>
-
-    <section id="basic-flow-header-files">
-      <title>Header Files</title>
-      <para>
-        For the above example, at least the following include files
-      are necessary. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  #include <linux/init.h>
-  #include <linux/pci.h>
-  #include <linux/slab.h>
-  #include <sound/core.h>
-  #include <sound/initval.h>
-]]>
-          </programlisting>
-        </informalexample>
-
-	where the last one is necessary only when module options are
-      defined in the source file.  If the code is split into several
-      files, the files without module options don't need them.
-      </para>
-
-      <para>
-        In addition to these headers, you'll need
-      <filename>&lt;linux/interrupt.h&gt;</filename> for interrupt
-      handling, and <filename>&lt;asm/io.h&gt;</filename> for I/O
-      access. If you use the <function>mdelay()</function> or
-      <function>udelay()</function> functions, you'll need to include
-      <filename>&lt;linux/delay.h&gt;</filename> too. 
-      </para>
-
-      <para>
-      The ALSA interfaces like the PCM and control APIs are defined in other
-      <filename>&lt;sound/xxx.h&gt;</filename> header files.
-      They have to be included after
-      <filename>&lt;sound/core.h&gt;</filename>.
-      </para>
-
-    </section>
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Management of Cards and Components  -->
-<!-- ****************************************************** -->
-  <chapter id="card-management">
-    <title>Management of Cards and Components</title>
-
-    <section id="card-management-card-instance">
-      <title>Card Instance</title>
-      <para>
-      For each soundcard, a <quote>card</quote> record must be allocated.
-      </para>
-
-      <para>
-      A card record is the headquarters of the soundcard.  It manages
-      the whole list of devices (components) on the soundcard, such as
-      PCM, mixers, MIDI, synthesizer, and so on.  Also, the card
-      record holds the ID and the name strings of the card, manages
-      the root of proc files, and controls the power-management states
-      and hotplug disconnections.  The component list on the card
-      record is used to manage the correct release of resources at
-      destruction. 
-      </para>
-
-      <para>
-        As mentioned above, to create a card instance, call
-      <function>snd_card_new()</function>.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_card *card;
-  int err;
-  err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The function takes six arguments: the parent device pointer,
-        the card-index number, the id string, the module pointer (usually
-        <constant>THIS_MODULE</constant>),
-        the size of extra-data space, and the pointer to return the
-        card instance.  The extra_size argument is used to
-        allocate card-&gt;private_data for the
-        chip-specific data.  Note that these data
-        are allocated by <function>snd_card_new()</function>.
-      </para>
-
-      <para>
-	The first argument, the pointer of struct
-	<structname>device</structname>, specifies the parent device.
-	For PCI devices, typically &amp;pci-&gt; is passed there.
-      </para>
-    </section>
-
-    <section id="card-management-component">
-      <title>Components</title>
-      <para>
-        After the card is created, you can attach the components
-      (devices) to the card instance. In an ALSA driver, a component is
-      represented as a struct <structname>snd_device</structname> object.
-      A component can be a PCM instance, a control interface, a raw
-      MIDI interface, etc.  Each such instance has one component
-      entry.
-      </para>
-
-      <para>
-        A component can be created via
-        <function>snd_device_new()</function> function. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        This takes the card pointer, the device-level
-      (<constant>SNDRV_DEV_XXX</constant>), the data pointer, and the
-      callback pointers (<parameter>&amp;ops</parameter>). The
-      device-level defines the type of components and the order of
-      registration and de-registration.  For most components, the
-      device-level is already defined.  For a user-defined component,
-      you can use <constant>SNDRV_DEV_LOWLEVEL</constant>.
-      </para>
-
-      <para>
-      This function itself doesn't allocate the data space. The data
-      must be allocated manually beforehand, and its pointer is passed
-      as the argument. This pointer (<parameter>chip</parameter> in the
-      above example) is used as the identifier for the instance.
-      </para>
-
-      <para>
-        Each pre-defined ALSA component such as ac97 and pcm calls
-      <function>snd_device_new()</function> inside its
-      constructor. The destructor for each component is defined in the
-      callback pointers.  Hence, you don't need to take care of
-      calling a destructor for such a component.
-      </para>
-
-      <para>
-        If you wish to create your own component, you need to
-      set the destructor function to the dev_free callback in
-      the <parameter>ops</parameter>, so that it can be released
-      automatically via <function>snd_card_free()</function>.
-      The next example will show an implementation of chip-specific
-      data.
-      </para>
-    </section>
-
-    <section id="card-management-chip-specific">
-      <title>Chip-Specific Data</title>
-      <para>
-      Chip-specific information, e.g. the I/O port address, its
-      resource pointer, or the irq number, is stored in the
-      chip-specific record.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          ....
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        In general, there are two ways of allocating the chip record.
-      </para>
-
-      <section id="card-management-chip-specific-snd-card-new">
-        <title>1. Allocating via <function>snd_card_new()</function>.</title>
-        <para>
-          As mentioned above, you can pass the extra-data-length
-	  to the 5th argument of <function>snd_card_new()</function>, i.e.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                     sizeof(struct mychip), &card);
-]]>
-            </programlisting>
-          </informalexample>
-
-          struct <structname>mychip</structname> is the type of the chip record.
-        </para>
-
-        <para>
-          In return, the allocated record can be accessed as
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct mychip *chip = card->private_data;
-]]>
-            </programlisting>
-          </informalexample>
-
-          With this method, you don't have to allocate twice.
-          The record is released together with the card instance.
-        </para>
-      </section>
-
-      <section id="card-management-chip-specific-allocate-extra">
-        <title>2. Allocating an extra device.</title>
-
-        <para>
-          After allocating a card instance via
-          <function>snd_card_new()</function> (with
-          <constant>0</constant> on the 4th arg), call
-          <function>kzalloc()</function>. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct snd_card *card;
-  struct mychip *chip;
-  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                     0, &card);
-  .....
-  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          The chip record should have the field to hold the card
-          pointer at least, 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  struct mychip {
-          struct snd_card *card;
-          ....
-  };
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          Then, set the card pointer in the returned chip instance.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  chip->card = card;
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          Next, initialize the fields, and register this chip
-          record as a low-level device with a specified
-          <parameter>ops</parameter>, 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static struct snd_device_ops ops = {
-          .dev_free =        snd_mychip_dev_free,
-  };
-  ....
-  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-]]>
-            </programlisting>
-          </informalexample>
-
-          <function>snd_mychip_dev_free()</function> is the
-        device-destructor function, which will call the real
-        destructor. 
-        </para>
-
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_mychip_dev_free(struct snd_device *device)
-  {
-          return snd_mychip_free(device->device_data);
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-          where <function>snd_mychip_free()</function> is the real destructor.
-        </para>
-      </section>
-    </section>
-
-    <section id="card-management-registration">
-      <title>Registration and Release</title>
-      <para>
-        After all components are assigned, register the card instance
-      by calling <function>snd_card_register()</function>. Access
-      to the device files is enabled at this point. That is, before
-      <function>snd_card_register()</function> is called, the
-      components are safely inaccessible from external side. If this
-      call fails, exit the probe function after releasing the card via
-      <function>snd_card_free()</function>. 
-      </para>
-
-      <para>
-        For releasing the card instance, you can call simply
-      <function>snd_card_free()</function>. As mentioned earlier, all
-      components are released automatically by this call. 
-      </para>
-
-      <para>
-      For a device which allows hotplugging, you can use
-      <function>snd_card_free_when_closed</function>.  This one will
-      postpone the destruction until all devices are closed.
-      </para>
-
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- PCI Resource Management  -->
-<!-- ****************************************************** -->
-  <chapter id="pci-resource">
-    <title>PCI Resource Management</title>
-
-    <section id="pci-resource-example">
-      <title>Full Code Example</title>
-      <para>
-        In this section, we'll complete the chip-specific constructor,
-      destructor and PCI entries. Example code is shown first,
-      below. 
-
-        <example>
-          <title>PCI Resource Management Example</title>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          struct snd_card *card;
-          struct pci_dev *pci;
-
-          unsigned long port;
-          int irq;
-  };
-
-  static int snd_mychip_free(struct mychip *chip)
-  {
-          /* disable hardware here if any */
-          .... /* (not implemented in this document) */
-
-          /* release the irq */
-          if (chip->irq >= 0)
-                  free_irq(chip->irq, chip);
-          /* release the I/O ports & memory */
-          pci_release_regions(chip->pci);
-          /* disable the PCI entry */
-          pci_disable_device(chip->pci);
-          /* release the data */
-          kfree(chip);
-          return 0;
-  }
-
-  /* chip-specific constructor */
-  static int snd_mychip_create(struct snd_card *card,
-                               struct pci_dev *pci,
-                               struct mychip **rchip)
-  {
-          struct mychip *chip;
-          int err;
-          static struct snd_device_ops ops = {
-                 .dev_free = snd_mychip_dev_free,
-          };
-
-          *rchip = NULL;
-
-          /* initialize the PCI entry */
-          err = pci_enable_device(pci);
-          if (err < 0)
-                  return err;
-          /* check PCI availability (28bit DMA) */
-          if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
-              pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
-                  printk(KERN_ERR "error to set 28bit mask DMA\n");
-                  pci_disable_device(pci);
-                  return -ENXIO;
-          }
-
-          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-          if (chip == NULL) {
-                  pci_disable_device(pci);
-                  return -ENOMEM;
-          }
-
-          /* initialize the stuff */
-          chip->card = card;
-          chip->pci = pci;
-          chip->irq = -1;
-
-          /* (1) PCI resource allocation */
-          err = pci_request_regions(pci, "My Chip");
-          if (err < 0) {
-                  kfree(chip);
-                  pci_disable_device(pci);
-                  return err;
-          }
-          chip->port = pci_resource_start(pci, 0);
-          if (request_irq(pci->irq, snd_mychip_interrupt,
-                          IRQF_SHARED, KBUILD_MODNAME, chip)) {
-                  printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
-                  snd_mychip_free(chip);
-                  return -EBUSY;
-          }
-          chip->irq = pci->irq;
-
-          /* (2) initialization of the chip hardware */
-          .... /*   (not implemented in this document) */
-
-          err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
-          if (err < 0) {
-                  snd_mychip_free(chip);
-                  return err;
-          }
-
-          *rchip = chip;
-          return 0;
-  }        
-
-  /* PCI IDs */
-  static struct pci_device_id snd_mychip_ids[] = {
-          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
-            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-          ....
-          { 0, }
-  };
-  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
-
-  /* pci_driver definition */
-  static struct pci_driver driver = {
-          .name = KBUILD_MODNAME,
-          .id_table = snd_mychip_ids,
-          .probe = snd_mychip_probe,
-          .remove = snd_mychip_remove,
-  };
-
-  /* module initialization */
-  static int __init alsa_card_mychip_init(void)
-  {
-          return pci_register_driver(&driver);
-  }
-
-  /* module clean up */
-  static void __exit alsa_card_mychip_exit(void)
-  {
-          pci_unregister_driver(&driver);
-  }
-
-  module_init(alsa_card_mychip_init)
-  module_exit(alsa_card_mychip_exit)
-
-  EXPORT_NO_SYMBOLS; /* for old kernels only */
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="pci-resource-some-haftas">
-      <title>Some Hafta's</title>
-      <para>
-        The allocation of PCI resources is done in the
-      <function>probe()</function> function, and usually an extra
-      <function>xxx_create()</function> function is written for this
-      purpose.
-      </para>
-
-      <para>
-        In the case of PCI devices, you first have to call
-      the <function>pci_enable_device()</function> function before
-      allocating resources. Also, you need to set the proper PCI DMA
-      mask to limit the accessed I/O range. In some cases, you might
-      need to call <function>pci_set_master()</function> function,
-      too.
-      </para>
-
-      <para>
-        Suppose the 28bit mask, and the code to be added would be like:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  err = pci_enable_device(pci);
-  if (err < 0)
-          return err;
-  if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
-      pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
-          printk(KERN_ERR "error to set 28bit mask DMA\n");
-          pci_disable_device(pci);
-          return -ENXIO;
-  }
-  
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-    <section id="pci-resource-resource-allocation">
-      <title>Resource Allocation</title>
-      <para>
-        The allocation of I/O ports and irqs is done via standard kernel
-      functions. Unlike ALSA ver.0.5.x., there are no helpers for
-      that. And these resources must be released in the destructor
-      function (see below). Also, on ALSA 0.9.x, you don't need to
-      allocate (pseudo-)DMA for PCI like in ALSA 0.5.x.
-      </para>
-
-      <para>
-        Now assume that the PCI device has an I/O port with 8 bytes
-        and an interrupt. Then struct <structname>mychip</structname> will have the
-        following fields:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          struct snd_card *card;
-
-          unsigned long port;
-          int irq;
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        For an I/O port (and also a memory region), you need to have
-      the resource pointer for the standard resource management. For
-      an irq, you have to keep only the irq number (integer). But you
-      need to initialize this number as -1 before actual allocation,
-      since irq 0 is valid. The port address and its resource pointer
-      can be initialized as null by
-      <function>kzalloc()</function> automatically, so you
-      don't have to take care of resetting them. 
-      </para>
-
-      <para>
-        The allocation of an I/O port is done like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  err = pci_request_regions(pci, "My Chip");
-  if (err < 0) { 
-          kfree(chip);
-          pci_disable_device(pci);
-          return err;
-  }
-  chip->port = pci_resource_start(pci, 0);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        <!-- obsolete -->
-        It will reserve the I/O port region of 8 bytes of the given
-      PCI device. The returned value, chip-&gt;res_port, is allocated
-      via <function>kmalloc()</function> by
-      <function>request_region()</function>. The pointer must be
-      released via <function>kfree()</function>, but there is a
-      problem with this. This issue will be explained later.
-      </para>
-
-      <para>
-        The allocation of an interrupt source is done like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (request_irq(pci->irq, snd_mychip_interrupt,
-                  IRQF_SHARED, KBUILD_MODNAME, chip)) {
-          printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
-          snd_mychip_free(chip);
-          return -EBUSY;
-  }
-  chip->irq = pci->irq;
-]]>
-          </programlisting>
-        </informalexample>
-
-        where <function>snd_mychip_interrupt()</function> is the
-      interrupt handler defined <link
-      linkend="pcm-interface-interrupt-handler"><citetitle>later</citetitle></link>.
-      Note that chip-&gt;irq should be defined
-      only when <function>request_irq()</function> succeeded.
-      </para>
-
-      <para>
-      On the PCI bus, interrupts can be shared. Thus,
-      <constant>IRQF_SHARED</constant> is used as the interrupt flag of
-      <function>request_irq()</function>. 
-      </para>
-
-      <para>
-        The last argument of <function>request_irq()</function> is the
-      data pointer passed to the interrupt handler. Usually, the
-      chip-specific record is used for that, but you can use what you
-      like, too. 
-      </para>
-
-      <para>
-        I won't give details about the interrupt handler at this
-        point, but at least its appearance can be explained now. The
-        interrupt handler looks usually like the following: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
-  {
-          struct mychip *chip = dev_id;
-          ....
-          return IRQ_HANDLED;
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Now let's write the corresponding destructor for the resources
-      above. The role of destructor is simple: disable the hardware
-      (if already activated) and release the resources. So far, we
-      have no hardware part, so the disabling code is not written here. 
-      </para>
-
-      <para>
-        To release the resources, the <quote>check-and-release</quote>
-        method is a safer way. For the interrupt, do like this: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (chip->irq >= 0)
-          free_irq(chip->irq, chip);
-]]>
-          </programlisting>
-        </informalexample>
-
-        Since the irq number can start from 0, you should initialize
-        chip-&gt;irq with a negative value (e.g. -1), so that you can
-        check the validity of the irq number as above.
-      </para>
-
-      <para>
-        When you requested I/O ports or memory regions via
-	<function>pci_request_region()</function> or
-	<function>pci_request_regions()</function> like in this example,
-	release the resource(s) using the corresponding function,
-	<function>pci_release_region()</function> or
-	<function>pci_release_regions()</function>.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  pci_release_regions(chip->pci);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-	When you requested manually via <function>request_region()</function>
-	or <function>request_mem_region</function>, you can release it via
-	<function>release_resource()</function>.  Suppose that you keep
-	the resource pointer returned from <function>request_region()</function>
-	in chip-&gt;res_port, the release procedure looks like:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  release_and_free_resource(chip->res_port);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      Don't forget to call <function>pci_disable_device()</function>
-      before the end.
-      </para>
-
-      <para>
-        And finally, release the chip-specific record.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  kfree(chip);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      We didn't implement the hardware disabling part in the above.
-      If you need to do this, please note that the destructor may be
-      called even before the initialization of the chip is completed.
-      It would be better to have a flag to skip hardware disabling
-      if the hardware was not initialized yet.
-      </para>
-
-      <para>
-      When the chip-data is assigned to the card using
-      <function>snd_device_new()</function> with
-      <constant>SNDRV_DEV_LOWLELVEL</constant> , its destructor is 
-      called at the last.  That is, it is assured that all other
-      components like PCMs and controls have already been released.
-      You don't have to stop PCMs, etc. explicitly, but just
-      call low-level hardware stopping.
-      </para>
-
-      <para>
-        The management of a memory-mapped region is almost as same as
-        the management of an I/O port. You'll need three fields like
-        the following: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mychip {
-          ....
-          unsigned long iobase_phys;
-          void __iomem *iobase_virt;
-  };
-]]>
-          </programlisting>
-        </informalexample>
-
-        and the allocation would be like below:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if ((err = pci_request_regions(pci, "My Chip")) < 0) {
-          kfree(chip);
-          return err;
-  }
-  chip->iobase_phys = pci_resource_start(pci, 0);
-  chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
-                                      pci_resource_len(pci, 0));
-]]>
-          </programlisting>
-        </informalexample>
-        
-        and the corresponding destructor would be:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int snd_mychip_free(struct mychip *chip)
-  {
-          ....
-          if (chip->iobase_virt)
-                  iounmap(chip->iobase_virt);
-          ....
-          pci_release_regions(chip->pci);
-          ....
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-    </section>
-
-    <section id="pci-resource-entries">
-      <title>PCI Entries</title>
-      <para>
-        So far, so good. Let's finish the missing PCI
-      stuff. At first, we need a
-      <structname>pci_device_id</structname> table for this
-      chipset. It's a table of PCI vendor/device ID number, and some
-      masks. 
-      </para>
-
-      <para>
-        For example,
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct pci_device_id snd_mychip_ids[] = {
-          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
-            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-          ....
-          { 0, }
-  };
-  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first and second fields of
-      the <structname>pci_device_id</structname> structure are the vendor and
-      device IDs. If you have no reason to filter the matching
-      devices, you can leave the remaining fields as above. The last
-      field of the <structname>pci_device_id</structname> struct contains
-      private data for this entry. You can specify any value here, for
-      example, to define specific operations for supported device IDs.
-      Such an example is found in the intel8x0 driver. 
-      </para>
-
-      <para>
-        The last entry of this list is the terminator. You must
-      specify this all-zero entry. 
-      </para>
-
-      <para>
-        Then, prepare the <structname>pci_driver</structname> record:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct pci_driver driver = {
-          .name = KBUILD_MODNAME,
-          .id_table = snd_mychip_ids,
-          .probe = snd_mychip_probe,
-          .remove = snd_mychip_remove,
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The <structfield>probe</structfield> and
-      <structfield>remove</structfield> functions have already
-      been defined in the previous sections.
-      The <structfield>name</structfield>
-      field is the name string of this device. Note that you must not
-      use a slash <quote>/</quote> in this string. 
-      </para>
-
-      <para>
-        And at last, the module entries:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int __init alsa_card_mychip_init(void)
-  {
-          return pci_register_driver(&driver);
-  }
-
-  static void __exit alsa_card_mychip_exit(void)
-  {
-          pci_unregister_driver(&driver);
-  }
-
-  module_init(alsa_card_mychip_init)
-  module_exit(alsa_card_mychip_exit)
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Note that these module entries are tagged with
-      <parameter>__init</parameter> and 
-      <parameter>__exit</parameter> prefixes.
-      </para>
-
-      <para>
-        Oh, one thing was forgotten. If you have no exported symbols,
-        you need to declare it in 2.2 or 2.4 kernels (it's not necessary in 2.6 kernels).
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  EXPORT_NO_SYMBOLS;
-]]>
-          </programlisting>
-        </informalexample>
-
-        That's all!
-      </para>
-    </section>
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- PCM Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="pcm-interface">
-    <title>PCM Interface</title>
-
-    <section id="pcm-interface-general">
-      <title>General</title>
-      <para>
-        The PCM middle layer of ALSA is quite powerful and it is only
-      necessary for each driver to implement the low-level functions
-      to access its hardware.
-      </para>
-
-      <para>
-        For accessing to the PCM layer, you need to include
-      <filename>&lt;sound/pcm.h&gt;</filename> first. In addition,
-      <filename>&lt;sound/pcm_params.h&gt;</filename> might be needed
-      if you access to some functions related with hw_param. 
-      </para>
-
-      <para>
-        Each card device can have up to four pcm instances. A pcm
-      instance corresponds to a pcm device file. The limitation of
-      number of instances comes only from the available bit size of
-      the Linux's device numbers. Once when 64bit device number is
-      used, we'll have more pcm instances available. 
-      </para>
-
-      <para>
-        A pcm instance consists of pcm playback and capture streams,
-      and each pcm stream consists of one or more pcm substreams. Some
-      soundcards support multiple playback functions. For example,
-      emu10k1 has a PCM playback of 32 stereo substreams. In this case, at
-      each open, a free substream is (usually) automatically chosen
-      and opened. Meanwhile, when only one substream exists and it was
-      already opened, the successful open will either block
-      or error with <constant>EAGAIN</constant> according to the
-      file open mode. But you don't have to care about such details in your
-      driver. The PCM middle layer will take care of such work.
-      </para>
-    </section>
-
-    <section id="pcm-interface-example">
-      <title>Full Code Example</title>
-      <para>
-      The example code below does not include any hardware access
-      routines but shows only the skeleton, how to build up the PCM
-      interfaces.
-
-        <example>
-          <title>PCM Example Code</title>
-          <programlisting>
-<![CDATA[
-  #include <sound/pcm.h>
-  ....
-
-  /* hardware definition */
-  static struct snd_pcm_hardware snd_mychip_playback_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_8000_48000,
-          .rate_min =         8000,
-          .rate_max =         48000,
-          .channels_min =     2,
-          .channels_max =     2,
-          .buffer_bytes_max = 32768,
-          .period_bytes_min = 4096,
-          .period_bytes_max = 32768,
-          .periods_min =      1,
-          .periods_max =      1024,
-  };
-
-  /* hardware definition */
-  static struct snd_pcm_hardware snd_mychip_capture_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_8000_48000,
-          .rate_min =         8000,
-          .rate_max =         48000,
-          .channels_min =     2,
-          .channels_max =     2,
-          .buffer_bytes_max = 32768,
-          .period_bytes_min = 4096,
-          .period_bytes_max = 32768,
-          .periods_min =      1,
-          .periods_max =      1024,
-  };
-
-  /* open callback */
-  static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          runtime->hw = snd_mychip_playback_hw;
-          /* more hardware-initialization will be done here */
-          ....
-          return 0;
-  }
-
-  /* close callback */
-  static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          /* the hardware-specific codes will be here */
-          ....
-          return 0;
-
-  }
-
-  /* open callback */
-  static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          runtime->hw = snd_mychip_capture_hw;
-          /* more hardware-initialization will be done here */
-          ....
-          return 0;
-  }
-
-  /* close callback */
-  static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          /* the hardware-specific codes will be here */
-          ....
-          return 0;
-
-  }
-
-  /* hw_params callback */
-  static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params)
-  {
-          return snd_pcm_lib_malloc_pages(substream,
-                                     params_buffer_bytes(hw_params));
-  }
-
-  /* hw_free callback */
-  static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
-  {
-          return snd_pcm_lib_free_pages(substream);
-  }
-
-  /* prepare callback */
-  static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          /* set up the hardware with the current configuration
-           * for example...
-           */
-          mychip_set_sample_format(chip, runtime->format);
-          mychip_set_sample_rate(chip, runtime->rate);
-          mychip_set_channels(chip, runtime->channels);
-          mychip_set_dma_setup(chip, runtime->dma_addr,
-                               chip->buffer_size,
-                               chip->period_size);
-          return 0;
-  }
-
-  /* trigger callback */
-  static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
-                                    int cmd)
-  {
-          switch (cmd) {
-          case SNDRV_PCM_TRIGGER_START:
-                  /* do something to start the PCM engine */
-                  ....
-                  break;
-          case SNDRV_PCM_TRIGGER_STOP:
-                  /* do something to stop the PCM engine */
-                  ....
-                  break;
-          default:
-                  return -EINVAL;
-          }
-  }
-
-  /* pointer callback */
-  static snd_pcm_uframes_t
-  snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          unsigned int current_ptr;
-
-          /* get the current hardware pointer */
-          current_ptr = mychip_get_hw_pointer(chip);
-          return current_ptr;
-  }
-
-  /* operators */
-  static struct snd_pcm_ops snd_mychip_playback_ops = {
-          .open =        snd_mychip_playback_open,
-          .close =       snd_mychip_playback_close,
-          .ioctl =       snd_pcm_lib_ioctl,
-          .hw_params =   snd_mychip_pcm_hw_params,
-          .hw_free =     snd_mychip_pcm_hw_free,
-          .prepare =     snd_mychip_pcm_prepare,
-          .trigger =     snd_mychip_pcm_trigger,
-          .pointer =     snd_mychip_pcm_pointer,
-  };
-
-  /* operators */
-  static struct snd_pcm_ops snd_mychip_capture_ops = {
-          .open =        snd_mychip_capture_open,
-          .close =       snd_mychip_capture_close,
-          .ioctl =       snd_pcm_lib_ioctl,
-          .hw_params =   snd_mychip_pcm_hw_params,
-          .hw_free =     snd_mychip_pcm_hw_free,
-          .prepare =     snd_mychip_pcm_prepare,
-          .trigger =     snd_mychip_pcm_trigger,
-          .pointer =     snd_mychip_pcm_pointer,
-  };
-
-  /*
-   *  definitions of capture are omitted here...
-   */
-
-  /* create a pcm device */
-  static int snd_mychip_new_pcm(struct mychip *chip)
-  {
-          struct snd_pcm *pcm;
-          int err;
-
-          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
-          if (err < 0) 
-                  return err;
-          pcm->private_data = chip;
-          strcpy(pcm->name, "My Chip");
-          chip->pcm = pcm;
-          /* set operators */
-          snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                          &snd_mychip_playback_ops);
-          snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                          &snd_mychip_capture_ops);
-          /* pre-allocation of buffers */
-          /* NOTE: this may fail */
-          snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                snd_dma_pci_data(chip->pci),
-                                                64*1024, 64*1024);
-          return 0;
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="pcm-interface-constructor">
-      <title>Constructor</title>
-      <para>
-        A pcm instance is allocated by the <function>snd_pcm_new()</function>
-      function. It would be better to create a constructor for pcm,
-      namely, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int snd_mychip_new_pcm(struct mychip *chip)
-  {
-          struct snd_pcm *pcm;
-          int err;
-
-          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
-          if (err < 0) 
-                  return err;
-          pcm->private_data = chip;
-          strcpy(pcm->name, "My Chip");
-          chip->pcm = pcm;
-	  ....
-          return 0;
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The <function>snd_pcm_new()</function> function takes four
-      arguments. The first argument is the card pointer to which this
-      pcm is assigned, and the second is the ID string. 
-      </para>
-
-      <para>
-        The third argument (<parameter>index</parameter>, 0 in the
-      above) is the index of this new pcm. It begins from zero. If
-      you create more than one pcm instances, specify the
-      different numbers in this argument. For example,
-      <parameter>index</parameter> = 1 for the second PCM device.  
-      </para>
-
-      <para>
-        The fourth and fifth arguments are the number of substreams
-      for playback and capture, respectively. Here 1 is used for
-      both arguments. When no playback or capture substreams are available,
-      pass 0 to the corresponding argument.
-      </para>
-
-      <para>
-        If a chip supports multiple playbacks or captures, you can
-      specify more numbers, but they must be handled properly in
-      open/close, etc. callbacks.  When you need to know which
-      substream you are referring to, then it can be obtained from
-      struct <structname>snd_pcm_substream</structname> data passed to each callback
-      as follows: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_pcm_substream *substream;
-  int index = substream->number;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        After the pcm is created, you need to set operators for each
-        pcm stream. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
-                  &snd_mychip_playback_ops);
-  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                  &snd_mychip_capture_ops);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The operators are defined typically like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct snd_pcm_ops snd_mychip_playback_ops = {
-          .open =        snd_mychip_pcm_open,
-          .close =       snd_mychip_pcm_close,
-          .ioctl =       snd_pcm_lib_ioctl,
-          .hw_params =   snd_mychip_pcm_hw_params,
-          .hw_free =     snd_mychip_pcm_hw_free,
-          .prepare =     snd_mychip_pcm_prepare,
-          .trigger =     snd_mychip_pcm_trigger,
-          .pointer =     snd_mychip_pcm_pointer,
-  };
-]]>
-          </programlisting>
-        </informalexample>
-
-        All the callbacks are described in the
-        <link linkend="pcm-interface-operators"><citetitle>
-        Operators</citetitle></link> subsection.
-      </para>
-
-      <para>
-        After setting the operators, you probably will want to
-        pre-allocate the buffer. For the pre-allocation, simply call
-        the following: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                        snd_dma_pci_data(chip->pci),
-                                        64*1024, 64*1024);
-]]>
-          </programlisting>
-        </informalexample>
-
-        It will allocate a buffer up to 64kB as default.
-      Buffer management details will be described in the later section <link
-      linkend="buffer-and-memory"><citetitle>Buffer and Memory
-      Management</citetitle></link>. 
-      </para>
-
-      <para>
-        Additionally, you can set some extra information for this pcm
-        in pcm-&gt;info_flags.
-        The available values are defined as
-        <constant>SNDRV_PCM_INFO_XXX</constant> in
-        <filename>&lt;sound/asound.h&gt;</filename>, which is used for
-        the hardware definition (described later). When your soundchip
-        supports only half-duplex, specify like this: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-    <section id="pcm-interface-destructor">
-      <title>... And the Destructor?</title>
-      <para>
-        The destructor for a pcm instance is not always
-      necessary. Since the pcm device will be released by the middle
-      layer code automatically, you don't have to call the destructor
-      explicitly.
-      </para>
-
-      <para>
-        The destructor would be necessary if you created
-        special records internally and needed to release them. In such a
-        case, set the destructor function to
-        pcm-&gt;private_free: 
-
-        <example>
-          <title>PCM Instance with a Destructor</title>
-          <programlisting>
-<![CDATA[
-  static void mychip_pcm_free(struct snd_pcm *pcm)
-  {
-          struct mychip *chip = snd_pcm_chip(pcm);
-          /* free your own data */
-          kfree(chip->my_private_pcm_data);
-          /* do what you like else */
-          ....
-  }
-
-  static int snd_mychip_new_pcm(struct mychip *chip)
-  {
-          struct snd_pcm *pcm;
-          ....
-          /* allocate your own data */
-          chip->my_private_pcm_data = kmalloc(...);
-          /* set the destructor */
-          pcm->private_data = chip;
-          pcm->private_free = mychip_pcm_free;
-          ....
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="pcm-interface-runtime">
-      <title>Runtime Pointer - The Chest of PCM Information</title>
-	<para>
-	  When the PCM substream is opened, a PCM runtime instance is
-	allocated and assigned to the substream. This pointer is
-	accessible via <constant>substream-&gt;runtime</constant>.
-	This runtime pointer holds most information you need
-	to control the PCM: the copy of hw_params and sw_params configurations, the buffer
-	pointers, mmap records, spinlocks, etc.
-	</para>
-
-	<para>
-	The definition of runtime instance is found in
-	<filename>&lt;sound/pcm.h&gt;</filename>.  Here are
-       the contents of this file:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-struct _snd_pcm_runtime {
-	/* -- Status -- */
-	struct snd_pcm_substream *trigger_master;
-	snd_timestamp_t trigger_tstamp;	/* trigger timestamp */
-	int overrange;
-	snd_pcm_uframes_t avail_max;
-	snd_pcm_uframes_t hw_ptr_base;	/* Position at buffer restart */
-	snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
-
-	/* -- HW params -- */
-	snd_pcm_access_t access;	/* access mode */
-	snd_pcm_format_t format;	/* SNDRV_PCM_FORMAT_* */
-	snd_pcm_subformat_t subformat;	/* subformat */
-	unsigned int rate;		/* rate in Hz */
-	unsigned int channels;		/* channels */
-	snd_pcm_uframes_t period_size;	/* period size */
-	unsigned int periods;		/* periods */
-	snd_pcm_uframes_t buffer_size;	/* buffer size */
-	unsigned int tick_time;		/* tick time */
-	snd_pcm_uframes_t min_align;	/* Min alignment for the format */
-	size_t byte_align;
-	unsigned int frame_bits;
-	unsigned int sample_bits;
-	unsigned int info;
-	unsigned int rate_num;
-	unsigned int rate_den;
-
-	/* -- SW params -- */
-	struct timespec tstamp_mode;	/* mmap timestamp is updated */
-  	unsigned int period_step;
-	unsigned int sleep_min;		/* min ticks to sleep */
-	snd_pcm_uframes_t start_threshold;
-	snd_pcm_uframes_t stop_threshold;
-	snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
-						noise is nearest than this */
-	snd_pcm_uframes_t silence_size;	/* Silence filling size */
-	snd_pcm_uframes_t boundary;	/* pointers wrap point */
-
-	snd_pcm_uframes_t silenced_start;
-	snd_pcm_uframes_t silenced_size;
-
-	snd_pcm_sync_id_t sync;		/* hardware synchronization ID */
-
-	/* -- mmap -- */
-	volatile struct snd_pcm_mmap_status *status;
-	volatile struct snd_pcm_mmap_control *control;
-	atomic_t mmap_count;
-
-	/* -- locking / scheduling -- */
-	spinlock_t lock;
-	wait_queue_head_t sleep;
-	struct timer_list tick_timer;
-	struct fasync_struct *fasync;
-
-	/* -- private section -- */
-	void *private_data;
-	void (*private_free)(struct snd_pcm_runtime *runtime);
-
-	/* -- hardware description -- */
-	struct snd_pcm_hardware hw;
-	struct snd_pcm_hw_constraints hw_constraints;
-
-	/* -- timer -- */
-	unsigned int timer_resolution;	/* timer resolution */
-
-	/* -- DMA -- */           
-	unsigned char *dma_area;	/* DMA area */
-	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
-	size_t dma_bytes;		/* size of DMA area */
-
-	struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
-
-#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
-	/* -- OSS things -- */
-	struct snd_pcm_oss_runtime oss;
-#endif
-};
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	  For the operators (callbacks) of each sound driver, most of
-	these records are supposed to be read-only.  Only the PCM
-	middle-layer changes / updates them.  The exceptions are
-	the hardware description (hw) DMA buffer information and the
-	private data.  Besides, if you use the standard buffer allocation
-	method via <function>snd_pcm_lib_malloc_pages()</function>,
-	you don't need to set the DMA buffer information by yourself.
-	</para>
-
-	<para>
-	In the sections below, important records are explained.
-	</para>
-
-	<section id="pcm-interface-runtime-hw">
-	<title>Hardware Description</title>
-	<para>
-	  The hardware descriptor (struct <structname>snd_pcm_hardware</structname>)
-	contains the definitions of the fundamental hardware
-	configuration.  Above all, you'll need to define this in
-	<link linkend="pcm-interface-operators-open-callback"><citetitle>
-	the open callback</citetitle></link>.
-	Note that the runtime instance holds the copy of the
-	descriptor, not the pointer to the existing descriptor.  That
-	is, in the open callback, you can modify the copied descriptor
-	(<constant>runtime-&gt;hw</constant>) as you need.  For example, if the maximum
-	number of channels is 1 only on some chip models, you can
-	still use the same hardware descriptor and change the
-	channels_max later:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-          struct snd_pcm_runtime *runtime = substream->runtime;
-          ...
-          runtime->hw = snd_mychip_playback_hw; /* common definition */
-          if (chip->model == VERY_OLD_ONE)
-                  runtime->hw.channels_max = 1;
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	  Typically, you'll have a hardware descriptor as below:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static struct snd_pcm_hardware snd_mychip_playback_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_8000_48000,
-          .rate_min =         8000,
-          .rate_max =         48000,
-          .channels_min =     2,
-          .channels_max =     2,
-          .buffer_bytes_max = 32768,
-          .period_bytes_min = 4096,
-          .period_bytes_max = 32768,
-          .periods_min =      1,
-          .periods_max =      1024,
-  };
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-	<itemizedlist>
-	<listitem><para>
-          The <structfield>info</structfield> field contains the type and
-        capabilities of this pcm. The bit flags are defined in
-        <filename>&lt;sound/asound.h&gt;</filename> as
-        <constant>SNDRV_PCM_INFO_XXX</constant>. Here, at least, you
-        have to specify whether the mmap is supported and which
-        interleaved format is supported.
-        When the hardware supports mmap, add the
-        <constant>SNDRV_PCM_INFO_MMAP</constant> flag here. When the
-        hardware supports the interleaved or the non-interleaved
-        formats, <constant>SNDRV_PCM_INFO_INTERLEAVED</constant> or
-        <constant>SNDRV_PCM_INFO_NONINTERLEAVED</constant> flag must
-        be set, respectively. If both are supported, you can set both,
-        too. 
-        </para>
-
-        <para>
-          In the above example, <constant>MMAP_VALID</constant> and
-        <constant>BLOCK_TRANSFER</constant> are specified for the OSS mmap
-        mode. Usually both are set. Of course,
-        <constant>MMAP_VALID</constant> is set only if the mmap is
-        really supported. 
-        </para>
-
-        <para>
-          The other possible flags are
-        <constant>SNDRV_PCM_INFO_PAUSE</constant> and
-        <constant>SNDRV_PCM_INFO_RESUME</constant>. The
-        <constant>PAUSE</constant> bit means that the pcm supports the
-        <quote>pause</quote> operation, while the
-        <constant>RESUME</constant> bit means that the pcm supports
-        the full <quote>suspend/resume</quote> operation.
-	If the <constant>PAUSE</constant> flag is set,
-	the <structfield>trigger</structfield> callback below
-        must handle the corresponding (pause push/release) commands.
-	The suspend/resume trigger commands can be defined even without
-	the <constant>RESUME</constant> flag.  See <link
-	linkend="power-management"><citetitle>
-	Power Management</citetitle></link> section for details.
-        </para>
-
-	<para>
-	  When the PCM substreams can be synchronized (typically,
-	synchronized start/stop of a playback and a capture streams),
-	you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
-	too.  In this case, you'll need to check the linked-list of
-	PCM substreams in the trigger callback.  This will be
-	described in the later section.
-	</para>
-	</listitem>
-
-	<listitem>
-        <para>
-          <structfield>formats</structfield> field contains the bit-flags
-        of supported formats (<constant>SNDRV_PCM_FMTBIT_XXX</constant>).
-        If the hardware supports more than one format, give all or'ed
-        bits.  In the example above, the signed 16bit little-endian
-        format is specified.
-        </para>
-	</listitem>
-
-	<listitem>
-        <para>
-        <structfield>rates</structfield> field contains the bit-flags of
-        supported rates (<constant>SNDRV_PCM_RATE_XXX</constant>).
-        When the chip supports continuous rates, pass
-        <constant>CONTINUOUS</constant> bit additionally.
-        The pre-defined rate bits are provided only for typical
-	rates. If your chip supports unconventional rates, you need to add
-        the <constant>KNOT</constant> bit and set up the hardware
-        constraint manually (explained later).
-        </para>
-	</listitem>
-
-	<listitem>
-	<para>
-	<structfield>rate_min</structfield> and
-	<structfield>rate_max</structfield> define the minimum and
-	maximum sample rate.  This should correspond somehow to
-	<structfield>rates</structfield> bits.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	<structfield>channel_min</structfield> and
-	<structfield>channel_max</structfield> 
-	define, as you might already expected, the minimum and maximum
-	number of channels.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	<structfield>buffer_bytes_max</structfield> defines the
-	maximum buffer size in bytes.  There is no
-	<structfield>buffer_bytes_min</structfield> field, since
-	it can be calculated from the minimum period size and the
-	minimum number of periods.
-	Meanwhile, <structfield>period_bytes_min</structfield> and
-	define the minimum and maximum size of the period in bytes.
-	<structfield>periods_max</structfield> and
-	<structfield>periods_min</structfield> define the maximum and
-	minimum number of periods in the buffer.
-        </para>
-
-	<para>
-	The <quote>period</quote> is a term that corresponds to
-	a fragment in the OSS world. The period defines the size at
-	which a PCM interrupt is generated. This size strongly
-	depends on the hardware. 
-	Generally, the smaller period size will give you more
-	interrupts, that is, more controls. 
-	In the case of capture, this size defines the input latency.
-	On the other hand, the whole buffer size defines the
-	output latency for the playback direction.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	There is also a field <structfield>fifo_size</structfield>.
-	This specifies the size of the hardware FIFO, but currently it
-	is neither used in the driver nor in the alsa-lib.  So, you
-	can ignore this field.
-	</para>
-	</listitem>
-	</itemizedlist>
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-config">
-	<title>PCM Configurations</title>
-	<para>
-	Ok, let's go back again to the PCM runtime records.
-	The most frequently referred records in the runtime instance are
-	the PCM configurations.
-	The PCM configurations are stored in the runtime instance
-	after the application sends <type>hw_params</type> data via
-	alsa-lib.  There are many fields copied from hw_params and
-	sw_params structs.  For example,
-	<structfield>format</structfield> holds the format type
-	chosen by the application.  This field contains the enum value
-	<constant>SNDRV_PCM_FORMAT_XXX</constant>.
-	</para>
-
-	<para>
-	One thing to be noted is that the configured buffer and period
-	sizes are stored in <quote>frames</quote> in the runtime.
-        In the ALSA world, 1 frame = channels * samples-size.
-	For conversion between frames and bytes, you can use the
-	<function>frames_to_bytes()</function> and
-          <function>bytes_to_frames()</function> helper functions. 
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  period_bytes = frames_to_bytes(runtime, runtime->period_size);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-	<para>
-	Also, many software parameters (sw_params) are
-	stored in frames, too.  Please check the type of the field.
-	<type>snd_pcm_uframes_t</type> is for the frames as unsigned
-	integer while <type>snd_pcm_sframes_t</type> is for the frames
-	as signed integer.
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-dma">
-	<title>DMA Buffer Information</title>
-	<para>
-	The DMA buffer is defined by the following four fields,
-	<structfield>dma_area</structfield>,
-	<structfield>dma_addr</structfield>,
-	<structfield>dma_bytes</structfield> and
-	<structfield>dma_private</structfield>.
-	The <structfield>dma_area</structfield> holds the buffer
-	pointer (the logical address).  You can call
-	<function>memcpy</function> from/to 
-	this pointer.  Meanwhile, <structfield>dma_addr</structfield>
-	holds the physical address of the buffer.  This field is
-	specified only when the buffer is a linear buffer.
-	<structfield>dma_bytes</structfield> holds the size of buffer
-	in bytes.  <structfield>dma_private</structfield> is used for
-	the ALSA DMA allocator.
-	</para>
-
-	<para>
-	If you use a standard ALSA function,
-	<function>snd_pcm_lib_malloc_pages()</function>, for
-	allocating the buffer, these fields are set by the ALSA middle
-	layer, and you should <emphasis>not</emphasis> change them by
-	yourself.  You can read them but not write them.
-	On the other hand, if you want to allocate the buffer by
-	yourself, you'll need to manage it in hw_params callback.
-	At least, <structfield>dma_bytes</structfield> is mandatory.
-	<structfield>dma_area</structfield> is necessary when the
-	buffer is mmapped.  If your driver doesn't support mmap, this
-	field is not necessary.  <structfield>dma_addr</structfield>
-	is also optional.  You can use
-	<structfield>dma_private</structfield> as you like, too.
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-status">
-	<title>Running Status</title>
-	<para>
-	The running status can be referred via <constant>runtime-&gt;status</constant>.
-	This is the pointer to the struct <structname>snd_pcm_mmap_status</structname>
-	record.  For example, you can get the current DMA hardware
-	pointer via <constant>runtime-&gt;status-&gt;hw_ptr</constant>.
-	</para>
-
-	<para>
-	The DMA application pointer can be referred via
-	<constant>runtime-&gt;control</constant>, which points to the
-	struct <structname>snd_pcm_mmap_control</structname> record.
-	However, accessing directly to this value is not recommended.
-	</para>
-	</section>
-
-	<section id="pcm-interface-runtime-private">
-	<title>Private Data</title> 
-	<para>
-	You can allocate a record for the substream and store it in
-	<constant>runtime-&gt;private_data</constant>.  Usually, this
-	is done in
-	<link linkend="pcm-interface-operators-open-callback"><citetitle>
-	the open callback</citetitle></link>.
-	Don't mix this with <constant>pcm-&gt;private_data</constant>.
-	The <constant>pcm-&gt;private_data</constant> usually points to the
-	chip instance assigned statically at the creation of PCM, while the 
-	<constant>runtime-&gt;private_data</constant> points to a dynamic
-	data structure created at the PCM open callback.
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_pcm_substream *substream)
-  {
-          struct my_pcm_data *data;
-          ....
-          data = kmalloc(sizeof(*data), GFP_KERNEL);
-          substream->runtime->private_data = data;
-          ....
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          The allocated object must be released in
-	<link linkend="pcm-interface-operators-open-callback"><citetitle>
-	the close callback</citetitle></link>.
-        </para>
-	</section>
-
-    </section>
-
-    <section id="pcm-interface-operators">
-      <title>Operators</title>
-      <para>
-        OK, now let me give details about each pcm callback
-      (<parameter>ops</parameter>). In general, every callback must
-      return 0 if successful, or a negative error number
-      such as <constant>-EINVAL</constant>. To choose an appropriate
-      error number, it is advised to check what value other parts of
-      the kernel return when the same kind of request fails.
-      </para>
-
-      <para>
-        The callback function takes at least the argument with
-        <structname>snd_pcm_substream</structname> pointer. To retrieve
-        the chip record from the given substream instance, you can use the
-        following macro. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  int xxx() {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          ....
-  }
-]]>
-          </programlisting>
-        </informalexample>
-
-	The macro reads <constant>substream-&gt;private_data</constant>,
-	which is a copy of <constant>pcm-&gt;private_data</constant>.
-	You can override the former if you need to assign different data
-	records per PCM substream.  For example, the cmi8330 driver assigns
-	different private_data for playback and capture directions,
-	because it uses two different codecs (SB- and AD-compatible) for
-	different directions.
-      </para>
-
-      <section id="pcm-interface-operators-open-callback">
-        <title>open callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-
-          This is called when a pcm substream is opened.
-        </para>
-
-        <para>
-          At least, here you have to initialize the runtime-&gt;hw
-          record. Typically, this is done by like this: 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_pcm_substream *substream)
-  {
-          struct mychip *chip = snd_pcm_substream_chip(substream);
-          struct snd_pcm_runtime *runtime = substream->runtime;
-
-          runtime->hw = snd_mychip_playback_hw;
-          return 0;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-
-          where <parameter>snd_mychip_playback_hw</parameter> is the
-          pre-defined hardware description.
-	</para>
-
-	<para>
-	You can allocate a private data in this callback, as described
-	in <link linkend="pcm-interface-runtime-private"><citetitle>
-	Private Data</citetitle></link> section.
-	</para>
-
-	<para>
-	If the hardware configuration needs more constraints, set the
-	hardware constraints here, too.
-	See <link linkend="pcm-interface-constraints"><citetitle>
-	Constraints</citetitle></link> for more details.
-	</para>
-      </section>
-
-      <section id="pcm-interface-operators-close-callback">
-        <title>close callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_close(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-
-          Obviously, this is called when a pcm substream is closed.
-        </para>
-
-        <para>
-          Any private instance for a pcm substream allocated in the
-          open callback will be released here. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_close(struct snd_pcm_substream *substream)
-  {
-          ....
-          kfree(substream->runtime->private_data);
-          ....
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-ioctl-callback">
-        <title>ioctl callback</title>
-        <para>
-          This is used for any special call to pcm ioctls. But
-        usually you can pass a generic ioctl callback, 
-        <function>snd_pcm_lib_ioctl</function>.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-hw-params-callback">
-        <title>hw_params callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This is called when the hardware parameter
-        (<structfield>hw_params</structfield>) is set
-        up by the application, 
-        that is, once when the buffer size, the period size, the
-        format, etc. are defined for the pcm substream. 
-        </para>
-
-        <para>
-          Many hardware setups should be done in this callback,
-        including the allocation of buffers. 
-        </para>
-
-        <para>
-          Parameters to be initialized are retrieved by
-          <function>params_xxx()</function> macros. To allocate
-          buffer, you can call a helper function, 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-]]>
-            </programlisting>
-          </informalexample>
-
-          <function>snd_pcm_lib_malloc_pages()</function> is available
-	  only when the DMA buffers have been pre-allocated.
-	  See the section <link
-	  linkend="buffer-and-memory-buffer-types"><citetitle>
-	  Buffer Types</citetitle></link> for more details.
-        </para>
-
-        <para>
-          Note that this and <structfield>prepare</structfield> callbacks
-        may be called multiple times per initialization.
-        For example, the OSS emulation may
-        call these callbacks at each change via its ioctl. 
-        </para>
-
-        <para>
-          Thus, you need to be careful not to allocate the same buffers
-        many times, which will lead to memory leaks!  Calling the
-        helper function above many times is OK. It will release the
-        previous buffer automatically when it was already allocated. 
-        </para>
-
-        <para>
-          Another note is that this callback is non-atomic
-        (schedulable) as default, i.e. when no
-	<structfield>nonatomic</structfield> flag set.
-	This is important, because the
-        <structfield>trigger</structfield> callback 
-        is atomic (non-schedulable). That is, mutexes or any
-        schedule-related functions are not available in
-        <structfield>trigger</structfield> callback.
-	Please see the subsection
-	<link linkend="pcm-interface-atomicity"><citetitle>
-	Atomicity</citetitle></link> for details.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-hw-free-callback">
-        <title>hw_free callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This is called to release the resources allocated via
-          <structfield>hw_params</structfield>. For example, releasing the
-          buffer via 
-          <function>snd_pcm_lib_malloc_pages()</function> is done by
-          calling the following: 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  snd_pcm_lib_free_pages(substream);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This function is always called before the close callback is called.
-          Also, the callback may be called multiple times, too.
-          Keep track whether the resource was already released. 
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-prepare-callback">
-       <title>prepare callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_prepare(struct snd_pcm_substream *substream);
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          This callback is called when the pcm is
-        <quote>prepared</quote>. You can set the format type, sample
-        rate, etc. here. The difference from
-        <structfield>hw_params</structfield> is that the 
-        <structfield>prepare</structfield> callback will be called each
-        time 
-        <function>snd_pcm_prepare()</function> is called, i.e. when
-        recovering after underruns, etc. 
-        </para>
-
-        <para>
-	Note that this callback is now non-atomic.
-	You can use schedule-related functions safely in this callback.
-        </para>
-
-        <para>
-          In this and the following callbacks, you can refer to the
-        values via the runtime record,
-        substream-&gt;runtime.
-        For example, to get the current
-        rate, format or channels, access to
-        runtime-&gt;rate,
-        runtime-&gt;format or
-        runtime-&gt;channels, respectively. 
-        The physical address of the allocated buffer is set to
-	runtime-&gt;dma_area.  The buffer and period sizes are
-	in runtime-&gt;buffer_size and runtime-&gt;period_size,
-	respectively.
-        </para>
-
-        <para>
-          Be careful that this callback will be called many times at
-        each setup, too. 
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-trigger-callback">
-        <title>trigger callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);
-]]>
-            </programlisting>
-          </informalexample>
-
-          This is called when the pcm is started, stopped or paused.
-        </para>
-
-        <para>
-          Which action is specified in the second argument,
-          <constant>SNDRV_PCM_TRIGGER_XXX</constant> in
-          <filename>&lt;sound/pcm.h&gt;</filename>. At least,
-          the <constant>START</constant> and <constant>STOP</constant>
-          commands must be defined in this callback. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  switch (cmd) {
-  case SNDRV_PCM_TRIGGER_START:
-          /* do something to start the PCM engine */
-          break;
-  case SNDRV_PCM_TRIGGER_STOP:
-          /* do something to stop the PCM engine */
-          break;
-  default:
-          return -EINVAL;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-          When the pcm supports the pause operation (given in the info
-        field of the hardware table), the <constant>PAUSE_PUSH</constant>
-        and <constant>PAUSE_RELEASE</constant> commands must be
-        handled here, too. The former is the command to pause the pcm,
-        and the latter to restart the pcm again. 
-        </para>
-
-        <para>
-          When the pcm supports the suspend/resume operation,
-	regardless of full or partial suspend/resume support,
-        the <constant>SUSPEND</constant> and <constant>RESUME</constant>
-        commands must be handled, too.
-        These commands are issued when the power-management status is
-        changed.  Obviously, the <constant>SUSPEND</constant> and
-        <constant>RESUME</constant> commands
-        suspend and resume the pcm substream, and usually, they
-        are identical to the <constant>STOP</constant> and
-        <constant>START</constant> commands, respectively.
-	  See the <link linkend="power-management"><citetitle>
-	Power Management</citetitle></link> section for details.
-        </para>
-
-        <para>
-          As mentioned, this callback is atomic as default unless
-	  <structfield>nonatomic</structfield> flag set, and
-	  you cannot call functions which may sleep.
-	  The trigger callback should be as minimal as possible,
-	  just really triggering the DMA.  The other stuff should be
-	  initialized hw_params and prepare callbacks properly
-	  beforehand.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-pointer-callback">
-        <title>pointer callback</title>
-        <para>
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)
-]]>
-            </programlisting>
-          </informalexample>
-
-          This callback is called when the PCM middle layer inquires
-        the current hardware position on the buffer. The position must
-        be returned in frames,
-        ranging from 0 to buffer_size - 1.
-        </para>
-
-        <para>
-          This is called usually from the buffer-update routine in the
-        pcm middle layer, which is invoked when
-        <function>snd_pcm_period_elapsed()</function> is called in the
-        interrupt routine. Then the pcm middle layer updates the
-        position and calculates the available space, and wakes up the
-        sleeping poll threads, etc. 
-        </para>
-
-        <para>
-          This callback is also atomic as default.
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-copy-silence">
-        <title>copy and silence callbacks</title>
-        <para>
-          These callbacks are not mandatory, and can be omitted in
-        most cases. These callbacks are used when the hardware buffer
-        cannot be in the normal memory space. Some chips have their
-        own buffer on the hardware which is not mappable. In such a
-        case, you have to transfer the data manually from the memory
-        buffer to the hardware buffer. Or, if the buffer is
-        non-contiguous on both physical and virtual memory spaces,
-        these callbacks must be defined, too. 
-        </para>
-
-        <para>
-          If these two callbacks are defined, copy and set-silence
-        operations are done by them. The detailed will be described in
-        the later section <link
-        linkend="buffer-and-memory"><citetitle>Buffer and Memory
-        Management</citetitle></link>. 
-        </para>
-      </section>
-
-      <section id="pcm-interface-operators-ack">
-        <title>ack callback</title>
-        <para>
-          This callback is also not mandatory. This callback is called
-        when the appl_ptr is updated in read or write operations.
-        Some drivers like emu10k1-fx and cs46xx need to track the
-	current appl_ptr for the internal buffer, and this callback
-	is useful only for such a purpose.
-	</para>
-	<para>
-	  This callback is atomic as default.
-	</para>
-      </section>
-
-      <section id="pcm-interface-operators-page-callback">
-        <title>page callback</title>
-
-        <para>
-          This callback is optional too. This callback is used
-        mainly for non-contiguous buffers. The mmap calls this
-        callback to get the page address. Some examples will be
-        explained in the later section <link
-        linkend="buffer-and-memory"><citetitle>Buffer and Memory
-        Management</citetitle></link>, too. 
-        </para>
-      </section>
-    </section>
-
-    <section id="pcm-interface-interrupt-handler">
-      <title>Interrupt Handler</title>
-      <para>
-        The rest of pcm stuff is the PCM interrupt handler. The
-      role of PCM interrupt handler in the sound driver is to update
-      the buffer position and to tell the PCM middle layer when the
-      buffer position goes across the prescribed period size. To
-      inform this, call the <function>snd_pcm_period_elapsed()</function>
-      function. 
-      </para>
-
-      <para>
-        There are several types of sound chips to generate the interrupts.
-      </para>
-
-      <section id="pcm-interface-interrupt-handler-boundary">
-        <title>Interrupts at the period (fragment) boundary</title>
-        <para>
-          This is the most frequently found type:  the hardware
-        generates an interrupt at each period boundary.
-	In this case, you can call
-        <function>snd_pcm_period_elapsed()</function> at each 
-        interrupt. 
-        </para>
-
-        <para>
-          <function>snd_pcm_period_elapsed()</function> takes the
-        substream pointer as its argument. Thus, you need to keep the
-        substream pointer accessible from the chip instance. For
-        example, define substream field in the chip record to hold the
-        current running substream pointer, and set the pointer value
-        at open callback (and reset at close callback). 
-        </para>
-
-        <para>
-          If you acquire a spinlock in the interrupt handler, and the
-        lock is used in other pcm callbacks, too, then you have to
-        release the lock before calling
-        <function>snd_pcm_period_elapsed()</function>, because
-        <function>snd_pcm_period_elapsed()</function> calls other pcm
-        callbacks inside. 
-        </para>
-
-        <para>
-          Typical code would be like:
-
-          <example>
-	    <title>Interrupt Handler Case #1</title>
-            <programlisting>
-<![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
-  {
-          struct mychip *chip = dev_id;
-          spin_lock(&chip->lock);
-          ....
-          if (pcm_irq_invoked(chip)) {
-                  /* call updater, unlock before it */
-                  spin_unlock(&chip->lock);
-                  snd_pcm_period_elapsed(chip->substream);
-                  spin_lock(&chip->lock);
-                  /* acknowledge the interrupt if necessary */
-          }
-          ....
-          spin_unlock(&chip->lock);
-          return IRQ_HANDLED;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-      </section>
-
-      <section id="pcm-interface-interrupt-handler-timer">
-        <title>High frequency timer interrupts</title>
-        <para>
-	This happens when the hardware doesn't generate interrupts
-        at the period boundary but issues timer interrupts at a fixed
-        timer rate (e.g. es1968 or ymfpci drivers). 
-        In this case, you need to check the current hardware
-        position and accumulate the processed sample length at each
-        interrupt.  When the accumulated size exceeds the period
-        size, call 
-        <function>snd_pcm_period_elapsed()</function> and reset the
-        accumulator. 
-        </para>
-
-        <para>
-          Typical code would be like the following.
-
-          <example>
-	    <title>Interrupt Handler Case #2</title>
-            <programlisting>
-<![CDATA[
-  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
-  {
-          struct mychip *chip = dev_id;
-          spin_lock(&chip->lock);
-          ....
-          if (pcm_irq_invoked(chip)) {
-                  unsigned int last_ptr, size;
-                  /* get the current hardware pointer (in frames) */
-                  last_ptr = get_hw_ptr(chip);
-                  /* calculate the processed frames since the
-                   * last update
-                   */
-                  if (last_ptr < chip->last_ptr)
-                          size = runtime->buffer_size + last_ptr 
-                                   - chip->last_ptr; 
-                  else
-                          size = last_ptr - chip->last_ptr;
-                  /* remember the last updated point */
-                  chip->last_ptr = last_ptr;
-                  /* accumulate the size */
-                  chip->size += size;
-                  /* over the period boundary? */
-                  if (chip->size >= runtime->period_size) {
-                          /* reset the accumulator */
-                          chip->size %= runtime->period_size;
-                          /* call updater */
-                          spin_unlock(&chip->lock);
-                          snd_pcm_period_elapsed(substream);
-                          spin_lock(&chip->lock);
-                  }
-                  /* acknowledge the interrupt if necessary */
-          }
-          ....
-          spin_unlock(&chip->lock);
-          return IRQ_HANDLED;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-      </section>
-
-      <section id="pcm-interface-interrupt-handler-both">
-        <title>On calling <function>snd_pcm_period_elapsed()</function></title>
-        <para>
-          In both cases, even if more than one period are elapsed, you
-        don't have to call
-        <function>snd_pcm_period_elapsed()</function> many times. Call
-        only once. And the pcm layer will check the current hardware
-        pointer and update to the latest status. 
-        </para>
-      </section>
-    </section>
-
-    <section id="pcm-interface-atomicity">
-      <title>Atomicity</title>
-      <para>
-      One of the most important (and thus difficult to debug) problems
-      in kernel programming are race conditions.
-      In the Linux kernel, they are usually avoided via spin-locks, mutexes
-      or semaphores.  In general, if a race condition can happen
-      in an interrupt handler, it has to be managed atomically, and you
-      have to use a spinlock to protect the critical session. If the
-      critical section is not in interrupt handler code and
-      if taking a relatively long time to execute is acceptable, you
-      should use mutexes or semaphores instead.
-      </para>
-
-      <para>
-      As already seen, some pcm callbacks are atomic and some are
-      not.  For example, the <parameter>hw_params</parameter> callback is
-      non-atomic, while <parameter>trigger</parameter> callback is
-      atomic.  This means, the latter is called already in a spinlock
-      held by the PCM middle layer. Please take this atomicity into
-      account when you choose a locking scheme in the callbacks.
-      </para>
-
-      <para>
-      In the atomic callbacks, you cannot use functions which may call
-      <function>schedule</function> or go to
-      <function>sleep</function>.  Semaphores and mutexes can sleep,
-      and hence they cannot be used inside the atomic callbacks
-      (e.g. <parameter>trigger</parameter> callback).
-      To implement some delay in such a callback, please use
-      <function>udelay()</function> or <function>mdelay()</function>.
-      </para>
-
-      <para>
-      All three atomic callbacks (trigger, pointer, and ack) are
-      called with local interrupts disabled.
-      </para>
-
-      <para>
-      The recent changes in PCM core code, however, allow all PCM
-      operations to be non-atomic.  This assumes that the all caller
-      sides are in non-atomic contexts.  For example, the function
-      <function>snd_pcm_period_elapsed()</function> is called
-      typically from the interrupt handler.  But, if you set up the
-      driver to use a threaded interrupt handler, this call can be in
-      non-atomic context, too.  In such a case, you can set
-      <structfield>nonatomic</structfield> filed of
-      <structname>snd_pcm</structname> object after creating it.
-      When this flag is set, mutex and rwsem are used internally in
-      the PCM core instead of spin and rwlocks, so that you can call
-      all PCM functions safely in a non-atomic context.
-      </para>
-
-    </section>
-    <section id="pcm-interface-constraints">
-      <title>Constraints</title>
-      <para>
-        If your chip supports unconventional sample rates, or only the
-      limited samples, you need to set a constraint for the
-      condition. 
-      </para>
-
-      <para>
-        For example, in order to restrict the sample rates in the some
-        supported values, use
-	<function>snd_pcm_hw_constraint_list()</function>.
-	You need to call this function in the open callback.
-
-        <example>
-	  <title>Example of Hardware Constraints</title>
-          <programlisting>
-<![CDATA[
-  static unsigned int rates[] =
-          {4000, 10000, 22050, 44100};
-  static struct snd_pcm_hw_constraint_list constraints_rates = {
-          .count = ARRAY_SIZE(rates),
-          .list = rates,
-          .mask = 0,
-  };
-
-  static int snd_mychip_pcm_open(struct snd_pcm_substream *substream)
-  {
-          int err;
-          ....
-          err = snd_pcm_hw_constraint_list(substream->runtime, 0,
-                                           SNDRV_PCM_HW_PARAM_RATE,
-                                           &constraints_rates);
-          if (err < 0)
-                  return err;
-          ....
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-
-      <para>
-        There are many different constraints.
-        Look at <filename>sound/pcm.h</filename> for a complete list.
-        You can even define your own constraint rules.
-        For example, let's suppose my_chip can manage a substream of 1 channel
-        if and only if the format is S16_LE, otherwise it supports any format
-        specified in the <structname>snd_pcm_hardware</structname> structure (or in any
-        other constraint_list). You can build a rule like this:
-
-        <example>
-	  <title>Example of Hardware Constraints for Channels</title>
-	  <programlisting>
-<![CDATA[
-  static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params,
-                                        struct snd_pcm_hw_rule *rule)
-  {
-          struct snd_interval *c = hw_param_interval(params,
-                        SNDRV_PCM_HW_PARAM_CHANNELS);
-          struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-          struct snd_interval ch;
-
-          snd_interval_any(&ch);
-          if (f->bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
-                  ch.min = ch.max = 1;
-                  ch.integer = 1;
-                  return snd_interval_refine(c, &ch);
-          }
-          return 0;
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
- 
-      <para>
-        Then you need to call this function to add your rule:
-
-       <informalexample>
-	 <programlisting>
-<![CDATA[
-  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-                      hw_rule_channels_by_format, NULL,
-                      SNDRV_PCM_HW_PARAM_FORMAT, -1);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The rule function is called when an application sets the PCM
-	format, and it refines the number of channels accordingly.
-        But an application may set the number of channels before
-	setting the format. Thus you also need to define the inverse rule:
-
-       <example>
-	 <title>Example of Hardware Constraints for Formats</title>
-	 <programlisting>
-<![CDATA[
-  static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params,
-                                        struct snd_pcm_hw_rule *rule)
-  {
-          struct snd_interval *c = hw_param_interval(params,
-                SNDRV_PCM_HW_PARAM_CHANNELS);
-          struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
-          struct snd_mask fmt;
-
-          snd_mask_any(&fmt);    /* Init the struct */
-          if (c->min < 2) {
-                  fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_LE;
-                  return snd_mask_refine(f, &fmt);
-          }
-          return 0;
-  }
-]]>
-          </programlisting>
-        </example>
-      </para>
-
-      <para>
-      ...and in the open callback:
-       <informalexample>
-	 <programlisting>
-<![CDATA[
-  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
-                      hw_rule_format_by_channels, NULL,
-                      SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        I won't give more details here, rather I
-        would like to say, <quote>Luke, use the source.</quote>
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Control Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="control-interface">
-    <title>Control Interface</title>
-
-    <section id="control-interface-general">
-      <title>General</title>
-      <para>
-        The control interface is used widely for many switches,
-      sliders, etc. which are accessed from user-space. Its most
-      important use is the mixer interface. In other words, since ALSA
-      0.9.x, all the mixer stuff is implemented on the control kernel API.
-      </para>
-
-      <para>
-        ALSA has a well-defined AC97 control module. If your chip
-      supports only the AC97 and nothing else, you can skip this
-      section. 
-      </para>
-
-      <para>
-        The control API is defined in
-      <filename>&lt;sound/control.h&gt;</filename>.
-      Include this file if you want to add your own controls.
-      </para>
-    </section>
-
-    <section id="control-interface-definition">
-      <title>Definition of Controls</title>
-      <para>
-        To create a new control, you need to define the
-	following three
-      callbacks: <structfield>info</structfield>,
-      <structfield>get</structfield> and
-      <structfield>put</structfield>. Then, define a
-      struct <structname>snd_kcontrol_new</structname> record, such as: 
-
-        <example>
-	  <title>Definition of a Control</title>
-          <programlisting>
-<![CDATA[
-  static struct snd_kcontrol_new my_control = {
-          .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-          .name = "PCM Playback Switch",
-          .index = 0,
-          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-          .private_value = 0xffff,
-          .info = my_control_info,
-          .get = my_control_get,
-          .put = my_control_put
-  };
-]]>
-          </programlisting>
-        </example>
-      </para>
-
-      <para>
-        The <structfield>iface</structfield> field specifies the control
-      type, <constant>SNDRV_CTL_ELEM_IFACE_XXX</constant>, which
-      is usually <constant>MIXER</constant>.
-      Use <constant>CARD</constant> for global controls that are not
-      logically part of the mixer.
-      If the control is closely associated with some specific device on
-      the sound card, use <constant>HWDEP</constant>,
-      <constant>PCM</constant>, <constant>RAWMIDI</constant>,
-      <constant>TIMER</constant>, or <constant>SEQUENCER</constant>, and
-      specify the device number with the
-      <structfield>device</structfield> and
-      <structfield>subdevice</structfield> fields.
-      </para>
-
-      <para>
-        The <structfield>name</structfield> is the name identifier
-      string. Since ALSA 0.9.x, the control name is very important,
-      because its role is classified from its name. There are
-      pre-defined standard control names. The details are described in
-      the <link linkend="control-interface-control-names"><citetitle>
-      Control Names</citetitle></link> subsection.
-      </para>
-
-      <para>
-        The <structfield>index</structfield> field holds the index number
-      of this control. If there are several different controls with
-      the same name, they can be distinguished by the index
-      number. This is the case when 
-      several codecs exist on the card. If the index is zero, you can
-      omit the definition above. 
-      </para>
-
-      <para>
-        The <structfield>access</structfield> field contains the access
-      type of this control. Give the combination of bit masks,
-      <constant>SNDRV_CTL_ELEM_ACCESS_XXX</constant>, there.
-      The details will be explained in
-      the <link linkend="control-interface-access-flags"><citetitle>
-      Access Flags</citetitle></link> subsection.
-      </para>
-
-      <para>
-        The <structfield>private_value</structfield> field contains
-      an arbitrary long integer value for this record. When using
-      the generic <structfield>info</structfield>,
-      <structfield>get</structfield> and
-      <structfield>put</structfield> callbacks, you can pass a value 
-      through this field. If several small numbers are necessary, you can
-      combine them in bitwise. Or, it's possible to give a pointer
-      (casted to unsigned long) of some record to this field, too. 
-      </para>
-
-      <para>
-      The <structfield>tlv</structfield> field can be used to provide
-      metadata about the control; see the
-      <link linkend="control-interface-tlv">
-      <citetitle>Metadata</citetitle></link> subsection.
-      </para>
-
-      <para>
-        The other three are
-	<link linkend="control-interface-callbacks"><citetitle>
-	callback functions</citetitle></link>.
-      </para>
-    </section>
-
-    <section id="control-interface-control-names">
-      <title>Control Names</title>
-      <para>
-        There are some standards to define the control names. A
-      control is usually defined from the three parts as
-      <quote>SOURCE DIRECTION FUNCTION</quote>. 
-      </para>
-
-      <para>
-        The first, <constant>SOURCE</constant>, specifies the source
-      of the control, and is a string such as <quote>Master</quote>,
-      <quote>PCM</quote>, <quote>CD</quote> and
-      <quote>Line</quote>. There are many pre-defined sources. 
-      </para>
-
-      <para>
-        The second, <constant>DIRECTION</constant>, is one of the
-      following strings according to the direction of the control:
-      <quote>Playback</quote>, <quote>Capture</quote>, <quote>Bypass
-      Playback</quote> and <quote>Bypass Capture</quote>. Or, it can
-      be omitted, meaning both playback and capture directions. 
-      </para>
-
-      <para>
-        The third, <constant>FUNCTION</constant>, is one of the
-      following strings according to the function of the control:
-      <quote>Switch</quote>, <quote>Volume</quote> and
-      <quote>Route</quote>. 
-      </para>
-
-      <para>
-        The example of control names are, thus, <quote>Master Capture
-      Switch</quote> or <quote>PCM Playback Volume</quote>. 
-      </para>
-
-      <para>
-        There are some exceptions:
-      </para>
-
-      <section id="control-interface-control-names-global">
-        <title>Global capture and playback</title>
-        <para>
-          <quote>Capture Source</quote>, <quote>Capture Switch</quote>
-        and <quote>Capture Volume</quote> are used for the global
-        capture (input) source, switch and volume. Similarly,
-        <quote>Playback Switch</quote> and <quote>Playback
-        Volume</quote> are used for the global output gain switch and
-        volume. 
-        </para>
-      </section>
-
-      <section id="control-interface-control-names-tone">
-        <title>Tone-controls</title>
-        <para>
-          tone-control switch and volumes are specified like
-        <quote>Tone Control - XXX</quote>, e.g. <quote>Tone Control -
-        Switch</quote>, <quote>Tone Control - Bass</quote>,
-        <quote>Tone Control - Center</quote>.  
-        </para>
-      </section>
-
-      <section id="control-interface-control-names-3d">
-        <title>3D controls</title>
-        <para>
-          3D-control switches and volumes are specified like <quote>3D
-        Control - XXX</quote>, e.g. <quote>3D Control -
-        Switch</quote>, <quote>3D Control - Center</quote>, <quote>3D
-        Control - Space</quote>. 
-        </para>
-      </section>
-
-      <section id="control-interface-control-names-mic">
-        <title>Mic boost</title>
-        <para>
-          Mic-boost switch is set as <quote>Mic Boost</quote> or
-        <quote>Mic Boost (6dB)</quote>. 
-        </para>
-
-        <para>
-          More precise information can be found in
-        <filename>Documentation/sound/alsa/ControlNames.txt</filename>.
-        </para>
-      </section>
-    </section>
-
-    <section id="control-interface-access-flags">
-      <title>Access Flags</title>
-
-      <para>
-      The access flag is the bitmask which specifies the access type
-      of the given control.  The default access type is
-      <constant>SNDRV_CTL_ELEM_ACCESS_READWRITE</constant>, 
-      which means both read and write are allowed to this control.
-      When the access flag is omitted (i.e. = 0), it is
-      considered as <constant>READWRITE</constant> access as default. 
-      </para>
-
-      <para>
-      When the control is read-only, pass
-      <constant>SNDRV_CTL_ELEM_ACCESS_READ</constant> instead.
-      In this case, you don't have to define
-      the <structfield>put</structfield> callback.
-      Similarly, when the control is write-only (although it's a rare
-      case), you can use the <constant>WRITE</constant> flag instead, and
-      you don't need the <structfield>get</structfield> callback.
-      </para>
-
-      <para>
-      If the control value changes frequently (e.g. the VU meter),
-      <constant>VOLATILE</constant> flag should be given.  This means
-      that the control may be changed without
-      <link linkend="control-interface-change-notification"><citetitle>
-      notification</citetitle></link>. Applications should poll such
-      a control constantly.
-      </para>
-
-      <para>
-      When the control is inactive, set
-      the <constant>INACTIVE</constant> flag, too.
-      There are <constant>LOCK</constant> and
-      <constant>OWNER</constant> flags to change the write
-      permissions.
-      </para>
-
-    </section>
-
-    <section id="control-interface-callbacks">
-      <title>Callbacks</title>
-
-      <section id="control-interface-callbacks-info">
-        <title>info callback</title>
-        <para>
-          The <structfield>info</structfield> callback is used to get
-        detailed information on this control. This must store the
-        values of the given struct <structname>snd_ctl_elem_info</structname>
-        object. For example, for a boolean control with a single
-        element: 
-
-          <example>
-	    <title>Example of info callback</title>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_info *uinfo)
-  {
-          uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-          uinfo->count = 1;
-          uinfo->value.integer.min = 0;
-          uinfo->value.integer.max = 1;
-          return 0;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-
-        <para>
-          The <structfield>type</structfield> field specifies the type
-        of the control. There are <constant>BOOLEAN</constant>,
-        <constant>INTEGER</constant>, <constant>ENUMERATED</constant>,
-        <constant>BYTES</constant>, <constant>IEC958</constant> and
-        <constant>INTEGER64</constant>. The
-        <structfield>count</structfield> field specifies the 
-        number of elements in this control. For example, a stereo
-        volume would have count = 2. The
-        <structfield>value</structfield> field is a union, and 
-        the values stored are depending on the type. The boolean and
-        integer types are identical. 
-        </para>
-
-        <para>
-          The enumerated type is a bit different from others.  You'll
-          need to set the string for the currently given item index. 
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_info *uinfo)
-  {
-          static char *texts[4] = {
-                  "First", "Second", "Third", "Fourth"
-          };
-          uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-          uinfo->count = 1;
-          uinfo->value.enumerated.items = 4;
-          if (uinfo->value.enumerated.item > 3)
-                  uinfo->value.enumerated.item = 3;
-          strcpy(uinfo->value.enumerated.name,
-                 texts[uinfo->value.enumerated.item]);
-          return 0;
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-	  The above callback can be simplified with a helper function,
-	  <function>snd_ctl_enum_info</function>.  The final code
-	  looks like below.
-	  (You can pass ARRAY_SIZE(texts) instead of 4 in the third
-	   argument; it's a matter of taste.)
-
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
-                          struct snd_ctl_elem_info *uinfo)
-  {
-          static char *texts[4] = {
-                  "First", "Second", "Third", "Fourth"
-          };
-          return snd_ctl_enum_info(uinfo, 1, 4, texts);
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-	  Some common info callbacks are available for your convenience:
-	<function>snd_ctl_boolean_mono_info()</function> and
-	<function>snd_ctl_boolean_stereo_info()</function>.
-	Obviously, the former is an info callback for a mono channel
-	boolean item, just like <function>snd_myctl_mono_info</function>
-	above, and the latter is for a stereo channel boolean item.
-	</para>
-
-      </section>
-
-      <section id="control-interface-callbacks-get">
-        <title>get callback</title>
-
-        <para>
-          This callback is used to read the current value of the
-        control and to return to user-space. 
-        </para>
-
-        <para>
-          For example,
-
-          <example>
-	    <title>Example of get callback</title>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_get(struct snd_kcontrol *kcontrol,
-                           struct snd_ctl_elem_value *ucontrol)
-  {
-          struct mychip *chip = snd_kcontrol_chip(kcontrol);
-          ucontrol->value.integer.value[0] = get_some_value(chip);
-          return 0;
-  }
-]]>
-            </programlisting>
-          </example>
-        </para>
-
-        <para>
-	The <structfield>value</structfield> field depends on 
-        the type of control as well as on the info callback.  For example,
-	the sb driver uses this field to store the register offset,
-        the bit-shift and the bit-mask.  The
-        <structfield>private_value</structfield> field is set as follows:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  .private_value = reg | (shift << 16) | (mask << 24)
-]]>
-            </programlisting>
-          </informalexample>
-	and is retrieved in callbacks like
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
-                                    struct snd_ctl_elem_value *ucontrol)
-  {
-          int reg = kcontrol->private_value & 0xff;
-          int shift = (kcontrol->private_value >> 16) & 0xff;
-          int mask = (kcontrol->private_value >> 24) & 0xff;
-          ....
-  }
-]]>
-            </programlisting>
-          </informalexample>
-	</para>
-
-	<para>
-	In the <structfield>get</structfield> callback,
-	you have to fill all the elements if the
-        control has more than one elements,
-        i.e. <structfield>count</structfield> &gt; 1.
-	In the example above, we filled only one element
-        (<structfield>value.integer.value[0]</structfield>) since it's
-        assumed as <structfield>count</structfield> = 1.
-        </para>
-      </section>
-
-      <section id="control-interface-callbacks-put">
-        <title>put callback</title>
-
-        <para>
-          This callback is used to write a value from user-space.
-        </para>
-
-        <para>
-          For example,
-
-          <example>
-	    <title>Example of put callback</title>
-            <programlisting>
-<![CDATA[
-  static int snd_myctl_put(struct snd_kcontrol *kcontrol,
-                           struct snd_ctl_elem_value *ucontrol)
-  {
-          struct mychip *chip = snd_kcontrol_chip(kcontrol);
-          int changed = 0;
-          if (chip->current_value !=
-               ucontrol->value.integer.value[0]) {
-                  change_current_value(chip,
-                              ucontrol->value.integer.value[0]);
-                  changed = 1;
-          }
-          return changed;
-  }
-]]>
-            </programlisting>
-          </example>
-
-          As seen above, you have to return 1 if the value is
-        changed. If the value is not changed, return 0 instead. 
-	If any fatal error happens, return a negative error code as
-        usual.
-        </para>
-
-        <para>
-	As in the <structfield>get</structfield> callback,
-	when the control has more than one elements,
-	all elements must be evaluated in this callback, too.
-        </para>
-      </section>
-
-      <section id="control-interface-callbacks-all">
-        <title>Callbacks are not atomic</title>
-        <para>
-          All these three callbacks are basically not atomic.
-        </para>
-      </section>
-    </section>
-
-    <section id="control-interface-constructor">
-      <title>Constructor</title>
-      <para>
-        When everything is ready, finally we can create a new
-      control. To create a control, there are two functions to be
-      called, <function>snd_ctl_new1()</function> and
-      <function>snd_ctl_add()</function>. 
-      </para>
-
-      <para>
-        In the simplest way, you can do like this:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip));
-  if (err < 0)
-          return err;
-]]>
-          </programlisting>
-        </informalexample>
-
-        where <parameter>my_control</parameter> is the
-      struct <structname>snd_kcontrol_new</structname> object defined above, and chip
-      is the object pointer to be passed to
-      kcontrol-&gt;private_data 
-      which can be referred to in callbacks. 
-      </para>
-
-      <para>
-        <function>snd_ctl_new1()</function> allocates a new
-      <structname>snd_kcontrol</structname> instance,
-      and <function>snd_ctl_add</function> assigns the given
-      control component to the card. 
-      </para>
-    </section>
-
-    <section id="control-interface-change-notification">
-      <title>Change Notification</title>
-      <para>
-        If you need to change and update a control in the interrupt
-      routine, you can call <function>snd_ctl_notify()</function>. For
-      example, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer);
-]]>
-          </programlisting>
-        </informalexample>
-
-        This function takes the card pointer, the event-mask, and the
-      control id pointer for the notification. The event-mask
-      specifies the types of notification, for example, in the above
-      example, the change of control values is notified.
-      The id pointer is the pointer of struct <structname>snd_ctl_elem_id</structname>
-      to be notified.
-      You can find some examples in <filename>es1938.c</filename> or
-      <filename>es1968.c</filename> for hardware volume interrupts. 
-      </para>
-    </section>
-
-    <section id="control-interface-tlv">
-      <title>Metadata</title>
-      <para>
-      To provide information about the dB values of a mixer control, use
-      on of the <constant>DECLARE_TLV_xxx</constant> macros from
-      <filename>&lt;sound/tlv.h&gt;</filename> to define a variable
-      containing this information, set the<structfield>tlv.p
-      </structfield> field to point to this variable, and include the
-      <constant>SNDRV_CTL_ELEM_ACCESS_TLV_READ</constant> flag in the
-      <structfield>access</structfield> field; like this:
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
-
-  static struct snd_kcontrol_new my_control = {
-          ...
-          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
-                    SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-          ...
-          .tlv.p = db_scale_my_control,
-  };
-]]>
-        </programlisting>
-      </informalexample>
-      </para>
-
-      <para>
-      The <function>DECLARE_TLV_DB_SCALE</function> macro defines
-      information about a mixer control where each step in the control's
-      value changes the dB value by a constant dB amount.
-      The first parameter is the name of the variable to be defined.
-      The second parameter is the minimum value, in units of 0.01 dB.
-      The third parameter is the step size, in units of 0.01 dB.
-      Set the fourth parameter to 1 if the minimum value actually mutes
-      the control.
-      </para>
-
-      <para>
-      The <function>DECLARE_TLV_DB_LINEAR</function> macro defines
-      information about a mixer control where the control's value affects
-      the output linearly.
-      The first parameter is the name of the variable to be defined.
-      The second parameter is the minimum value, in units of 0.01 dB.
-      The third parameter is the maximum value, in units of 0.01 dB.
-      If the minimum value mutes the control, set the second parameter to
-      <constant>TLV_DB_GAIN_MUTE</constant>.
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- API for AC97 Codec  -->
-<!-- ****************************************************** -->
-  <chapter id="api-ac97">
-    <title>API for AC97 Codec</title>
-
-    <section>
-      <title>General</title>
-      <para>
-        The ALSA AC97 codec layer is a well-defined one, and you don't
-      have to write much code to control it. Only low-level control
-      routines are necessary. The AC97 codec API is defined in
-      <filename>&lt;sound/ac97_codec.h&gt;</filename>. 
-      </para>
-    </section>
-
-    <section id="api-ac97-example">
-      <title>Full Code Example</title>
-      <para>
-          <example>
-	    <title>Example of AC97 Interface</title>
-            <programlisting>
-<![CDATA[
-  struct mychip {
-          ....
-          struct snd_ac97 *ac97;
-          ....
-  };
-
-  static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
-                                             unsigned short reg)
-  {
-          struct mychip *chip = ac97->private_data;
-          ....
-          /* read a register value here from the codec */
-          return the_register_value;
-  }
-
-  static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
-                                   unsigned short reg, unsigned short val)
-  {
-          struct mychip *chip = ac97->private_data;
-          ....
-          /* write the given register value to the codec */
-  }
-
-  static int snd_mychip_ac97(struct mychip *chip)
-  {
-          struct snd_ac97_bus *bus;
-          struct snd_ac97_template ac97;
-          int err;
-          static struct snd_ac97_bus_ops ops = {
-                  .write = snd_mychip_ac97_write,
-                  .read = snd_mychip_ac97_read,
-          };
-
-          err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
-          if (err < 0)
-                  return err;
-          memset(&ac97, 0, sizeof(ac97));
-          ac97.private_data = chip;
-          return snd_ac97_mixer(bus, &ac97, &chip->ac97);
-  }
-
-]]>
-          </programlisting>
-        </example>
-      </para>
-    </section>
-
-    <section id="api-ac97-constructor">
-      <title>Constructor</title>
-      <para>
-        To create an ac97 instance, first call <function>snd_ac97_bus</function>
-      with an <type>ac97_bus_ops_t</type> record with callback functions.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_ac97_bus *bus;
-  static struct snd_ac97_bus_ops ops = {
-        .write = snd_mychip_ac97_write,
-        .read = snd_mychip_ac97_read,
-  };
-
-  snd_ac97_bus(card, 0, &ops, NULL, &pbus);
-]]>
-          </programlisting>
-        </informalexample>
-
-      The bus record is shared among all belonging ac97 instances.
-      </para>
-
-      <para>
-      And then call <function>snd_ac97_mixer()</function> with an
-      struct <structname>snd_ac97_template</structname>
-      record together with the bus pointer created above.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_ac97_template ac97;
-  int err;
-
-  memset(&ac97, 0, sizeof(ac97));
-  ac97.private_data = chip;
-  snd_ac97_mixer(bus, &ac97, &chip->ac97);
-]]>
-          </programlisting>
-        </informalexample>
-
-        where chip-&gt;ac97 is a pointer to a newly created
-        <type>ac97_t</type> instance.
-        In this case, the chip pointer is set as the private data, so that
-        the read/write callback functions can refer to this chip instance.
-        This instance is not necessarily stored in the chip
-	record.  If you need to change the register values from the
-        driver, or need the suspend/resume of ac97 codecs, keep this
-        pointer to pass to the corresponding functions.
-      </para>
-    </section>
-
-    <section id="api-ac97-callbacks">
-      <title>Callbacks</title>
-      <para>
-        The standard callbacks are <structfield>read</structfield> and
-      <structfield>write</structfield>. Obviously they 
-      correspond to the functions for read and write accesses to the
-      hardware low-level codes. 
-      </para>
-
-      <para>
-        The <structfield>read</structfield> callback returns the
-        register value specified in the argument. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
-                                             unsigned short reg)
-  {
-          struct mychip *chip = ac97->private_data;
-          ....
-          return the_register_value;
-  }
-]]>
-          </programlisting>
-        </informalexample>
-
-        Here, the chip can be cast from ac97-&gt;private_data.
-      </para>
-
-      <para>
-        Meanwhile, the <structfield>write</structfield> callback is
-        used to set the register value. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
-                       unsigned short reg, unsigned short val)
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      These callbacks are non-atomic like the control API callbacks.
-      </para>
-
-      <para>
-        There are also other callbacks:
-      <structfield>reset</structfield>,
-      <structfield>wait</structfield> and
-      <structfield>init</structfield>. 
-      </para>
-
-      <para>
-        The <structfield>reset</structfield> callback is used to reset
-      the codec. If the chip requires a special kind of reset, you can
-      define this callback. 
-      </para>
-
-      <para>
-        The <structfield>wait</structfield> callback is used to
-      add some waiting time in the standard initialization of the codec. If the
-      chip requires the extra waiting time, define this callback. 
-      </para>
-
-      <para>
-        The <structfield>init</structfield> callback is used for
-      additional initialization of the codec.
-      </para>
-    </section>
-
-    <section id="api-ac97-updating-registers">
-      <title>Updating Registers in The Driver</title>
-      <para>
-        If you need to access to the codec from the driver, you can
-      call the following functions:
-      <function>snd_ac97_write()</function>,
-      <function>snd_ac97_read()</function>,
-      <function>snd_ac97_update()</function> and
-      <function>snd_ac97_update_bits()</function>. 
-      </para>
-
-      <para>
-        Both <function>snd_ac97_write()</function> and
-        <function>snd_ac97_update()</function> functions are used to
-        set a value to the given register
-        (<constant>AC97_XXX</constant>). The difference between them is
-        that <function>snd_ac97_update()</function> doesn't write a
-        value if the given value has been already set, while
-        <function>snd_ac97_write()</function> always rewrites the
-        value. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ac97_write(ac97, AC97_MASTER, 0x8080);
-  snd_ac97_update(ac97, AC97_MASTER, 0x8080);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        <function>snd_ac97_read()</function> is used to read the value
-        of the given register. For example, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  value = snd_ac97_read(ac97, AC97_MASTER);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        <function>snd_ac97_update_bits()</function> is used to update
-        some bits in the given register.  
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ac97_update_bits(ac97, reg, mask, value);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Also, there is a function to change the sample rate (of a
-        given register such as
-        <constant>AC97_PCM_FRONT_DAC_RATE</constant>) when VRA or
-        DRA is supported by the codec:
-        <function>snd_ac97_set_rate()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The following registers are available to set the rate:
-      <constant>AC97_PCM_MIC_ADC_RATE</constant>,
-      <constant>AC97_PCM_FRONT_DAC_RATE</constant>,
-      <constant>AC97_PCM_LR_ADC_RATE</constant>,
-      <constant>AC97_SPDIF</constant>. When
-      <constant>AC97_SPDIF</constant> is specified, the register is
-      not really changed but the corresponding IEC958 status bits will
-      be updated. 
-      </para>
-    </section>
-
-    <section id="api-ac97-clock-adjustment">
-      <title>Clock Adjustment</title>
-      <para>
-        In some chips, the clock of the codec isn't 48000 but using a
-      PCI clock (to save a quartz!). In this case, change the field
-      bus-&gt;clock to the corresponding
-      value. For example, intel8x0 
-      and es1968 drivers have their own function to read from the clock.
-      </para>
-    </section>
-
-    <section id="api-ac97-proc-files">
-      <title>Proc Files</title>
-      <para>
-        The ALSA AC97 interface will create a proc file such as
-      <filename>/proc/asound/card0/codec97#0/ac97#0-0</filename> and
-      <filename>ac97#0-0+regs</filename>. You can refer to these files to
-      see the current status and registers of the codec. 
-      </para>
-    </section>
-
-    <section id="api-ac97-multiple-codecs">
-      <title>Multiple Codecs</title>
-      <para>
-        When there are several codecs on the same card, you need to
-      call <function>snd_ac97_mixer()</function> multiple times with
-      ac97.num=1 or greater. The <structfield>num</structfield> field
-      specifies the codec number. 
-      </para>
-
-      <para>
-        If you set up multiple codecs, you either need to write
-      different callbacks for each codec or check
-      ac97-&gt;num in the callback routines. 
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- MIDI (MPU401-UART) Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="midi-interface">
-    <title>MIDI (MPU401-UART) Interface</title>
-
-    <section id="midi-interface-general">
-      <title>General</title>
-      <para>
-        Many soundcards have built-in MIDI (MPU401-UART)
-      interfaces. When the soundcard supports the standard MPU401-UART
-      interface, most likely you can use the ALSA MPU401-UART API. The
-      MPU401-UART API is defined in
-      <filename>&lt;sound/mpu401.h&gt;</filename>. 
-      </para>
-
-      <para>
-        Some soundchips have a similar but slightly different
-      implementation of mpu401 stuff. For example, emu10k1 has its own
-      mpu401 routines. 
-      </para>
-    </section>
-
-    <section id="midi-interface-constructor">
-      <title>Constructor</title>
-      <para>
-        To create a rawmidi object, call
-      <function>snd_mpu401_uart_new()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi *rmidi;
-  snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
-                      irq, &rmidi);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first argument is the card pointer, and the second is the
-      index of this component. You can create up to 8 rawmidi
-      devices. 
-      </para>
-
-      <para>
-        The third argument is the type of the hardware,
-      <constant>MPU401_HW_XXX</constant>. If it's not a special one,
-      you can use <constant>MPU401_HW_MPU401</constant>. 
-      </para>
-
-      <para>
-        The 4th argument is the I/O port address. Many
-      backward-compatible MPU401 have an I/O port such as 0x330. Or, it
-      might be a part of its own PCI I/O region. It depends on the
-      chip design. 
-      </para>
-
-      <para>
-	The 5th argument is a bitflag for additional information.
-        When the I/O port address above is part of the PCI I/O
-      region, the MPU401 I/O port might have been already allocated
-      (reserved) by the driver itself. In such a case, pass a bit flag
-      <constant>MPU401_INFO_INTEGRATED</constant>,
-      and the mpu401-uart layer will allocate the I/O ports by itself. 
-      </para>
-
-	<para>
-	When the controller supports only the input or output MIDI stream,
-	pass the <constant>MPU401_INFO_INPUT</constant> or
-	<constant>MPU401_INFO_OUTPUT</constant> bitflag, respectively.
-	Then the rawmidi instance is created as a single stream.
-	</para>
-
-	<para>
-	<constant>MPU401_INFO_MMIO</constant> bitflag is used to change
-	the access method to MMIO (via readb and writeb) instead of
-	iob and outb. In this case, you have to pass the iomapped address
-	to <function>snd_mpu401_uart_new()</function>.
-	</para>
-
-	<para>
-	When <constant>MPU401_INFO_TX_IRQ</constant> is set, the output
-	stream isn't checked in the default interrupt handler.  The driver
-	needs to call <function>snd_mpu401_uart_interrupt_tx()</function>
-	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
-        the <structfield>cport</structfield> field of
-        struct <structname>snd_mpu401</structname> manually 
-        afterward. However, <structname>snd_mpu401</structname> pointer is not
-        returned explicitly by
-        <function>snd_mpu401_uart_new()</function>. You need to cast
-        rmidi-&gt;private_data to
-        <structname>snd_mpu401</structname> explicitly, 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_mpu401 *mpu;
-  mpu = rmidi->private_data;
-]]>
-          </programlisting>
-        </informalexample>
-
-        and reset the cport as you like:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  mpu->cport = my_own_control_port;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-	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>
-
-    <section id="midi-interface-interrupt-handler">
-      <title>Interrupt Handler</title>
-      <para>
-        When the interrupt is allocated in
-      <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>
-        In this case, you need to pass the private_data of the
-        returned rawmidi object from
-        <function>snd_mpu401_uart_new()</function> as the second
-        argument of <function>snd_mpu401_uart_interrupt()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- RawMIDI Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="rawmidi-interface">
-    <title>RawMIDI Interface</title>
-
-    <section id="rawmidi-interface-overview">
-      <title>Overview</title>
-
-      <para>
-      The raw MIDI interface is used for hardware MIDI ports that can
-      be accessed as a byte stream.  It is not used for synthesizer
-      chips that do not directly understand MIDI.
-      </para>
-
-      <para>
-      ALSA handles file and buffer management.  All you have to do is
-      to write some code to move data between the buffer and the
-      hardware.
-      </para>
-
-      <para>
-      The rawmidi API is defined in
-      <filename>&lt;sound/rawmidi.h&gt;</filename>.
-      </para>
-    </section>
-
-    <section id="rawmidi-interface-constructor">
-      <title>Constructor</title>
-
-      <para>
-      To create a rawmidi device, call the
-      <function>snd_rawmidi_new</function> function:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi *rmidi;
-  err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
-  if (err < 0)
-          return err;
-  rmidi->private_data = chip;
-  strcpy(rmidi->name, "My MIDI");
-  rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
-                      SNDRV_RAWMIDI_INFO_INPUT |
-                      SNDRV_RAWMIDI_INFO_DUPLEX;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      The first argument is the card pointer, the second argument is
-      the ID string.
-      </para>
-
-      <para>
-      The third argument is the index of this component.  You can
-      create up to 8 rawmidi devices.
-      </para>
-
-      <para>
-      The fourth and fifth arguments are the number of output and
-      input substreams, respectively, of this device (a substream is
-      the equivalent of a MIDI port).
-      </para>
-
-      <para>
-      Set the <structfield>info_flags</structfield> field to specify
-      the capabilities of the device.
-      Set <constant>SNDRV_RAWMIDI_INFO_OUTPUT</constant> if there is
-      at least one output port,
-      <constant>SNDRV_RAWMIDI_INFO_INPUT</constant> if there is at
-      least one input port,
-      and <constant>SNDRV_RAWMIDI_INFO_DUPLEX</constant> if the device
-      can handle output and input at the same time.
-      </para>
-
-      <para>
-      After the rawmidi device is created, you need to set the
-      operators (callbacks) for each substream.  There are helper
-      functions to set the operators for all the substreams of a device:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
-  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-      The operators are usually defined like this:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static struct snd_rawmidi_ops snd_mymidi_output_ops = {
-          .open =    snd_mymidi_output_open,
-          .close =   snd_mymidi_output_close,
-          .trigger = snd_mymidi_output_trigger,
-  };
-]]>
-          </programlisting>
-        </informalexample>
-      These callbacks are explained in the <link
-      linkend="rawmidi-interface-callbacks"><citetitle>Callbacks</citetitle></link>
-      section.
-      </para>
-
-      <para>
-      If there are more than one substream, you should give a
-      unique name to each of them:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi_substream *substream;
-  list_for_each_entry(substream,
-                      &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
-                      list {
-          sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
-  }
-  /* same for SNDRV_RAWMIDI_STREAM_INPUT */
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-    <section id="rawmidi-interface-callbacks">
-      <title>Callbacks</title>
-
-      <para>
-      In all the callbacks, the private data that you've set for the
-      rawmidi device can be accessed as
-      substream-&gt;rmidi-&gt;private_data.
-      <!-- <code> isn't available before DocBook 4.3 -->
-      </para>
-
-      <para>
-      If there is more than one port, your callbacks can determine the
-      port index from the struct snd_rawmidi_substream data passed to each
-      callback:
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_rawmidi_substream *substream;
-  int index = substream->number;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <section id="rawmidi-interface-op-open">
-      <title><function>open</function> callback</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int snd_xxx_open(struct snd_rawmidi_substream *substream);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is called when a substream is opened.
-        You can initialize the hardware here, but you shouldn't
-        start transmitting/receiving data yet.
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-close">
-      <title><function>close</function> callback</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int snd_xxx_close(struct snd_rawmidi_substream *substream);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        Guess what.
-        </para>
-
-        <para>
-        The <function>open</function> and <function>close</function>
-        callbacks of a rawmidi device are serialized with a mutex,
-        and can sleep.
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-trigger-out">
-      <title><function>trigger</function> callback for output
-      substreams</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_xxx_output_trigger(struct snd_rawmidi_substream *substream, int up);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is called with a nonzero <parameter>up</parameter>
-        parameter when there is some data in the substream buffer that
-        must be transmitted.
-        </para>
-
-        <para>
-        To read data from the buffer, call
-        <function>snd_rawmidi_transmit_peek</function>.  It will
-        return the number of bytes that have been read; this will be
-        less than the number of bytes requested when there are no more
-        data in the buffer.
-        After the data have been transmitted successfully, call
-        <function>snd_rawmidi_transmit_ack</function> to remove the
-        data from the substream buffer:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  unsigned char data;
-  while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
-          if (snd_mychip_try_to_transmit(data))
-                  snd_rawmidi_transmit_ack(substream, 1);
-          else
-                  break; /* hardware FIFO full */
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-        If you know beforehand that the hardware will accept data, you
-        can use the <function>snd_rawmidi_transmit</function> function
-        which reads some data and removes them from the buffer at once:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  while (snd_mychip_transmit_possible()) {
-          unsigned char data;
-          if (snd_rawmidi_transmit(substream, &data, 1) != 1)
-                  break; /* no more data */
-          snd_mychip_transmit(data);
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-
-        <para>
-        If you know beforehand how many bytes you can accept, you can
-        use a buffer size greater than one with the
-        <function>snd_rawmidi_transmit*</function> functions.
-        </para>
-
-        <para>
-        The <function>trigger</function> callback must not sleep.  If
-        the hardware FIFO is full before the substream buffer has been
-        emptied, you have to continue transmitting data later, either
-        in an interrupt handler, or with a timer if the hardware
-        doesn't have a MIDI transmit interrupt.
-        </para>
-
-        <para>
-        The <function>trigger</function> callback is called with a
-        zero <parameter>up</parameter> parameter when the transmission
-        of data should be aborted.
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-trigger-in">
-      <title><function>trigger</function> callback for input
-      substreams</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_xxx_input_trigger(struct snd_rawmidi_substream *substream, int up);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is called with a nonzero <parameter>up</parameter>
-        parameter to enable receiving data, or with a zero
-        <parameter>up</parameter> parameter do disable receiving data.
-        </para>
-
-        <para>
-        The <function>trigger</function> callback must not sleep; the
-        actual reading of data from the device is usually done in an
-        interrupt handler.
-        </para>
-
-        <para>
-        When data reception is enabled, your interrupt handler should
-        call <function>snd_rawmidi_receive</function> for all received
-        data:
-          <informalexample>
-            <programlisting>
-<![CDATA[
-  void snd_mychip_midi_interrupt(...)
-  {
-          while (mychip_midi_available()) {
-                  unsigned char data;
-                  data = mychip_midi_read();
-                  snd_rawmidi_receive(substream, &data, 1);
-          }
-  }
-]]>
-            </programlisting>
-          </informalexample>
-        </para>
-      </section>
-
-      <section id="rawmidi-interface-op-drain">
-      <title><function>drain</function> callback</title>
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void snd_xxx_drain(struct snd_rawmidi_substream *substream);
-]]>
-          </programlisting>
-        </informalexample>
-
-        <para>
-        This is only used with output substreams.  This function should wait
-        until all data read from the substream buffer have been transmitted.
-        This ensures that the device can be closed and the driver unloaded
-        without losing data.
-        </para>
-
-        <para>
-        This callback is optional. If you do not set
-        <structfield>drain</structfield> in the struct snd_rawmidi_ops
-        structure, ALSA will simply wait for 50&nbsp;milliseconds
-        instead.
-        </para>
-      </section>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Miscellaneous Devices  -->
-<!-- ****************************************************** -->
-  <chapter id="misc-devices">
-    <title>Miscellaneous Devices</title>
-
-    <section id="misc-devices-opl3">
-      <title>FM OPL3</title>
-      <para>
-        The FM OPL3 is still used in many chips (mainly for backward
-      compatibility). ALSA has a nice OPL3 FM control layer, too. The
-      OPL3 API is defined in
-      <filename>&lt;sound/opl3.h&gt;</filename>. 
-      </para>
-
-      <para>
-        FM registers can be directly accessed through the direct-FM API,
-      defined in <filename>&lt;sound/asound_fm.h&gt;</filename>. In
-      ALSA native mode, FM registers are accessed through
-      the Hardware-Dependent Device direct-FM extension API, whereas in
-      OSS compatible mode, FM registers can be accessed with the OSS
-      direct-FM compatible API in <filename>/dev/dmfmX</filename> device. 
-      </para>
-
-      <para>
-        To create the OPL3 component, you have two functions to
-        call. The first one is a constructor for the <type>opl3_t</type>
-        instance. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_opl3 *opl3;
-  snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,
-                  integrated, &opl3);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first argument is the card pointer, the second one is the
-      left port address, and the third is the right port address. In
-      most cases, the right port is placed at the left port + 2. 
-      </para>
-
-      <para>
-        The fourth argument is the hardware type.
-      </para>
-
-      <para>
-        When the left and right ports have been already allocated by
-      the card driver, pass non-zero to the fifth argument
-      (<parameter>integrated</parameter>). Otherwise, the opl3 module will
-      allocate the specified ports by itself. 
-      </para>
-
-      <para>
-        When the accessing the hardware requires special method
-        instead of the standard I/O access, you can create opl3 instance
-        separately with <function>snd_opl3_new()</function>.
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_opl3 *opl3;
-  snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-	Then set <structfield>command</structfield>,
-	<structfield>private_data</structfield> and
-	<structfield>private_free</structfield> for the private
-	access function, the private data and the destructor.
-	The l_port and r_port are not necessarily set.  Only the
-	command must be set properly.  You can retrieve the data
-	from the opl3-&gt;private_data field.
-      </para>
-
-      <para>
-	After creating the opl3 instance via <function>snd_opl3_new()</function>,
-	call <function>snd_opl3_init()</function> to initialize the chip to the
-	proper state. Note that <function>snd_opl3_create()</function> always
-	calls it internally.
-      </para>
-
-      <para>
-        If the opl3 instance is created successfully, then create a
-        hwdep device for this opl3. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_hwdep *opl3hwdep;
-  snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The first argument is the <type>opl3_t</type> instance you
-      created, and the second is the index number, usually 0. 
-      </para>
-
-      <para>
-        The third argument is the index-offset for the sequencer
-      client assigned to the OPL3 port. When there is an MPU401-UART,
-      give 1 for here (UART always takes 0). 
-      </para>
-    </section>
-
-    <section id="misc-devices-hardware-dependent">
-      <title>Hardware-Dependent Devices</title>
-      <para>
-        Some chips need user-space access for special
-      controls or for loading the micro code. In such a case, you can
-      create a hwdep (hardware-dependent) device. The hwdep API is
-      defined in <filename>&lt;sound/hwdep.h&gt;</filename>. You can
-      find examples in opl3 driver or
-      <filename>isa/sb/sb16_csp.c</filename>. 
-      </para>
-
-      <para>
-        The creation of the <type>hwdep</type> instance is done via
-        <function>snd_hwdep_new()</function>. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_hwdep *hw;
-  snd_hwdep_new(card, "My HWDEP", 0, &hw);
-]]>
-          </programlisting>
-        </informalexample>
-
-        where the third argument is the index number.
-      </para>
-
-      <para>
-        You can then pass any pointer value to the
-        <parameter>private_data</parameter>.
-        If you assign a private data, you should define the
-        destructor, too. The destructor function is set in
-        the <structfield>private_free</structfield> field.  
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);
-  hw->private_data = p;
-  hw->private_free = mydata_free;
-]]>
-          </programlisting>
-        </informalexample>
-
-        and the implementation of the destructor would be:
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static void mydata_free(struct snd_hwdep *hw)
-  {
-          struct mydata *p = hw->private_data;
-          kfree(p);
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The arbitrary file operations can be defined for this
-        instance. The file operators are defined in
-        the <parameter>ops</parameter> table. For example, assume that
-        this chip needs an ioctl. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  hw->ops.open = mydata_open;
-  hw->ops.ioctl = mydata_ioctl;
-  hw->ops.release = mydata_release;
-]]>
-          </programlisting>
-        </informalexample>
-
-        And implement the callback functions as you like.
-      </para>
-    </section>
-
-    <section id="misc-devices-IEC958">
-      <title>IEC958 (S/PDIF)</title>
-      <para>
-        Usually the controls for IEC958 devices are implemented via
-      the control interface. There is a macro to compose a name string for
-      IEC958 controls, <function>SNDRV_CTL_NAME_IEC958()</function>
-      defined in <filename>&lt;include/asound.h&gt;</filename>.  
-      </para>
-
-      <para>
-        There are some standard controls for IEC958 status bits. These
-      controls use the type <type>SNDRV_CTL_ELEM_TYPE_IEC958</type>,
-      and the size of element is fixed as 4 bytes array
-      (value.iec958.status[x]). For the <structfield>info</structfield>
-      callback, you don't specify 
-      the value field for this type (the count field must be set,
-      though). 
-      </para>
-
-      <para>
-        <quote>IEC958 Playback Con Mask</quote> is used to return the
-      bit-mask for the IEC958 status bits of consumer mode. Similarly,
-      <quote>IEC958 Playback Pro Mask</quote> returns the bitmask for
-      professional mode. They are read-only controls, and are defined
-      as MIXER controls (iface =
-      <constant>SNDRV_CTL_ELEM_IFACE_MIXER</constant>).  
-      </para>
-
-      <para>
-        Meanwhile, <quote>IEC958 Playback Default</quote> control is
-      defined for getting and setting the current default IEC958
-      bits. Note that this one is usually defined as a PCM control
-      (iface = <constant>SNDRV_CTL_ELEM_IFACE_PCM</constant>),
-      although in some places it's defined as a MIXER control. 
-      </para>
-
-      <para>
-        In addition, you can define the control switches to
-      enable/disable or to set the raw bit mode. The implementation
-      will depend on the chip, but the control should be named as
-      <quote>IEC958 xxx</quote>, preferably using
-      the <function>SNDRV_CTL_NAME_IEC958()</function> macro. 
-      </para>
-
-      <para>
-        You can find several cases, for example,
-      <filename>pci/emu10k1</filename>,
-      <filename>pci/ice1712</filename>, or
-      <filename>pci/cmipci.c</filename>.  
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Buffer and Memory Management  -->
-<!-- ****************************************************** -->
-  <chapter id="buffer-and-memory">
-    <title>Buffer and Memory Management</title>
-
-    <section id="buffer-and-memory-buffer-types">
-      <title>Buffer Types</title>
-      <para>
-        ALSA provides several different buffer allocation functions
-      depending on the bus and the architecture. All these have a
-      consistent API. The allocation of physically-contiguous pages is
-      done via 
-      <function>snd_malloc_xxx_pages()</function> function, where xxx
-      is the bus type. 
-      </para>
-
-      <para>
-        The allocation of pages with fallback is
-      <function>snd_malloc_xxx_pages_fallback()</function>. This
-      function tries to allocate the specified pages but if the pages
-      are not available, it tries to reduce the page sizes until
-      enough space is found.
-      </para>
-
-      <para>
-      The release the pages, call
-      <function>snd_free_xxx_pages()</function> function. 
-      </para>
-
-      <para>
-      Usually, ALSA drivers try to allocate and reserve
-       a large contiguous physical space
-       at the time the module is loaded for the later use.
-       This is called <quote>pre-allocation</quote>.
-       As already written, you can call the following function at 
-       pcm instance construction time (in the case of PCI bus). 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                        snd_dma_pci_data(pci), size, max);
-]]>
-          </programlisting>
-        </informalexample>
-
-        where <parameter>size</parameter> is the byte size to be
-      pre-allocated and the <parameter>max</parameter> is the maximum
-      size to be changed via the <filename>prealloc</filename> proc file.
-      The allocator will try to get an area as large as possible
-      within the given size. 
-      </para>
-
-      <para>
-      The second argument (type) and the third argument (device pointer)
-      are dependent on the bus.
-      In the case of the ISA bus, pass <function>snd_dma_isa_data()</function>
-      as the third argument with <constant>SNDRV_DMA_TYPE_DEV</constant> type.
-      For the continuous buffer unrelated to the bus can be pre-allocated
-      with <constant>SNDRV_DMA_TYPE_CONTINUOUS</constant> type and the
-      <function>snd_dma_continuous_data(GFP_KERNEL)</function> device pointer,
-      where <constant>GFP_KERNEL</constant> is the kernel allocation flag to
-      use.
-      For the PCI scatter-gather buffers, use
-      <constant>SNDRV_DMA_TYPE_DEV_SG</constant> with
-      <function>snd_dma_pci_data(pci)</function>
-      (see the 
-          <link linkend="buffer-and-memory-non-contiguous"><citetitle>Non-Contiguous Buffers
-          </citetitle></link> section).
-      </para>
-
-      <para>
-        Once the buffer is pre-allocated, you can use the
-        allocator in the <structfield>hw_params</structfield> callback: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_pcm_lib_malloc_pages(substream, size);
-]]>
-          </programlisting>
-        </informalexample>
-
-        Note that you have to pre-allocate to use this function.
-      </para>
-    </section>
-
-    <section id="buffer-and-memory-external-hardware">
-      <title>External Hardware Buffers</title>
-      <para>
-        Some chips have their own hardware buffers and the DMA
-      transfer from the host memory is not available. In such a case,
-      you need to either 1) copy/set the audio data directly to the
-      external hardware buffer, or 2) make an intermediate buffer and
-      copy/set the data from it to the external hardware buffer in
-      interrupts (or in tasklets, preferably).
-      </para>
-
-      <para>
-        The first case works fine if the external hardware buffer is large
-      enough.  This method doesn't need any extra buffers and thus is
-      more effective. You need to define the
-      <structfield>copy</structfield> and
-      <structfield>silence</structfield> callbacks for 
-      the data transfer. However, there is a drawback: it cannot
-      be mmapped. The examples are GUS's GF1 PCM or emu8000's
-      wavetable PCM. 
-      </para>
-
-      <para>
-        The second case allows for mmap on the buffer, although you have
-      to handle an interrupt or a tasklet to transfer the data
-      from the intermediate buffer to the hardware buffer. You can find an
-      example in the vxpocket driver. 
-      </para>
-
-      <para>
-        Another case is when the chip uses a PCI memory-map
-      region for the buffer instead of the host memory. In this case,
-      mmap is available only on certain architectures like the Intel one.
-      In non-mmap mode, the data cannot be transferred as in the normal
-      way. Thus you need to define the <structfield>copy</structfield> and
-      <structfield>silence</structfield> callbacks as well, 
-      as in the cases above. The examples are found in
-      <filename>rme32.c</filename> and <filename>rme96.c</filename>. 
-      </para>
-
-      <para>
-        The implementation of the <structfield>copy</structfield> and
-        <structfield>silence</structfield> callbacks depends upon 
-        whether the hardware supports interleaved or non-interleaved
-        samples. The <structfield>copy</structfield> callback is
-        defined like below, a bit 
-        differently depending whether the direction is playback or
-        capture: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int playback_copy(struct snd_pcm_substream *substream, int channel,
-               snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
-  static int capture_copy(struct snd_pcm_substream *substream, int channel,
-               snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        In the case of interleaved samples, the second argument
-      (<parameter>channel</parameter>) is not used. The third argument
-      (<parameter>pos</parameter>) points the 
-      current position offset in frames. 
-      </para>
-
-      <para>
-        The meaning of the fourth argument is different between
-      playback and capture. For playback, it holds the source data
-      pointer, and for capture, it's the destination data pointer. 
-      </para>
-
-      <para>
-        The last argument is the number of frames to be copied.
-      </para>
-
-      <para>
-        What you have to do in this callback is again different
-        between playback and capture directions. In the
-        playback case, you copy the given amount of data
-        (<parameter>count</parameter>) at the specified pointer
-        (<parameter>src</parameter>) to the specified offset
-        (<parameter>pos</parameter>) on the hardware buffer. When
-        coded like memcpy-like way, the copy would be like: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
-            frames_to_bytes(runtime, count));
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        For the capture direction, you copy the given amount of
-        data (<parameter>count</parameter>) at the specified offset
-        (<parameter>pos</parameter>) on the hardware buffer to the
-        specified pointer (<parameter>dst</parameter>). 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
-            frames_to_bytes(runtime, count));
-]]>
-          </programlisting>
-        </informalexample>
-
-        Note that both the position and the amount of data are given
-      in frames. 
-      </para>
-
-      <para>
-        In the case of non-interleaved samples, the implementation
-      will be a bit more complicated. 
-      </para>
-
-      <para>
-        You need to check the channel argument, and if it's -1, copy
-      the whole channels. Otherwise, you have to copy only the
-      specified channel. Please check
-      <filename>isa/gus/gus_pcm.c</filename> as an example. 
-      </para>
-
-      <para>
-        The <structfield>silence</structfield> callback is also
-        implemented in a similar way. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  static int silence(struct snd_pcm_substream *substream, int channel,
-                     snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        The meanings of arguments are the same as in the
-      <structfield>copy</structfield> 
-      callback, although there is no <parameter>src/dst</parameter>
-      argument. In the case of interleaved samples, the channel
-      argument has no meaning, as well as on
-      <structfield>copy</structfield> callback.  
-      </para>
-
-      <para>
-        The role of <structfield>silence</structfield> callback is to
-        set the given amount 
-        (<parameter>count</parameter>) of silence data at the
-        specified offset (<parameter>pos</parameter>) on the hardware
-        buffer. Suppose that the data format is signed (that is, the
-        silent-data is 0), and the implementation using a memset-like
-        function would be like: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0,
-            frames_to_bytes(runtime, count));
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        In the case of non-interleaved samples, again, the
-      implementation becomes a bit more complicated. See, for example,
-      <filename>isa/gus/gus_pcm.c</filename>. 
-      </para>
-    </section>
-
-    <section id="buffer-and-memory-non-contiguous">
-      <title>Non-Contiguous Buffers</title>
-      <para>
-        If your hardware supports the page table as in emu10k1 or the
-      buffer descriptors as in via82xx, you can use the scatter-gather
-      (SG) DMA. ALSA provides an interface for handling SG-buffers.
-      The API is provided in <filename>&lt;sound/pcm.h&gt;</filename>. 
-      </para>
-
-      <para>
-        For creating the SG-buffer handler, call
-        <function>snd_pcm_lib_preallocate_pages()</function> or
-        <function>snd_pcm_lib_preallocate_pages_for_all()</function>
-        with <constant>SNDRV_DMA_TYPE_DEV_SG</constant>
-	in the PCM constructor like other PCI pre-allocator.
-        You need to pass <function>snd_dma_pci_data(pci)</function>,
-        where pci is the struct <structname>pci_dev</structname> pointer
-        of the chip as well.
-        The <type>struct snd_sg_buf</type> instance is created as
-        substream-&gt;dma_private. You can cast
-        the pointer like: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        Then call <function>snd_pcm_lib_malloc_pages()</function>
-      in the <structfield>hw_params</structfield> callback
-      as well as in the case of normal PCI buffer.
-      The SG-buffer handler will allocate the non-contiguous kernel
-      pages of the given size and map them onto the virtually contiguous
-      memory.  The virtual pointer is addressed in runtime-&gt;dma_area.
-      The physical address (runtime-&gt;dma_addr) is set to zero,
-      because the buffer is physically non-contiguous.
-      The physical address table is set up in sgbuf-&gt;table.
-      You can get the physical address at a certain offset via
-      <function>snd_pcm_sgbuf_get_addr()</function>. 
-      </para>
-
-      <para>
-        When a SG-handler is used, you need to set
-      <function>snd_pcm_sgbuf_ops_page</function> as
-      the <structfield>page</structfield> callback.
-      (See <link linkend="pcm-interface-operators-page-callback">
-      <citetitle>page callback section</citetitle></link>.)
-      </para>
-
-      <para>
-        To release the data, call
-      <function>snd_pcm_lib_free_pages()</function> in the
-      <structfield>hw_free</structfield> callback as usual.
-      </para>
-    </section>
-
-    <section id="buffer-and-memory-vmalloced">
-      <title>Vmalloc'ed Buffers</title>
-      <para>
-        It's possible to use a buffer allocated via
-      <function>vmalloc</function>, for example, for an intermediate
-      buffer. Since the allocated pages are not contiguous, you need
-      to set the <structfield>page</structfield> callback to obtain
-      the physical address at every offset. 
-      </para>
-
-      <para>
-        The implementation of <structfield>page</structfield> callback
-        would be like this: 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  #include <linux/vmalloc.h>
-
-  /* get the physical page pointer on the given offset */
-  static struct page *mychip_page(struct snd_pcm_substream *substream,
-                                  unsigned long offset)
-  {
-          void *pageptr = substream->runtime->dma_area + offset;
-          return vmalloc_to_page(pageptr);
-  }
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Proc Interface  -->
-<!-- ****************************************************** -->
-  <chapter id="proc-interface">
-    <title>Proc Interface</title>
-    <para>
-      ALSA provides an easy interface for procfs. The proc files are
-      very useful for debugging. I recommend you set up proc files if
-      you write a driver and want to get a running status or register
-      dumps. The API is found in
-      <filename>&lt;sound/info.h&gt;</filename>. 
-    </para>
-
-    <para>
-      To create a proc file, call
-      <function>snd_card_proc_new()</function>. 
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  struct snd_info_entry *entry;
-  int err = snd_card_proc_new(card, "my-file", &entry);
-]]>
-        </programlisting>
-      </informalexample>
-
-      where the second argument specifies the name of the proc file to be
-    created. The above example will create a file
-    <filename>my-file</filename> under the card directory,
-    e.g. <filename>/proc/asound/card0/my-file</filename>. 
-    </para>
-
-    <para>
-    Like other components, the proc entry created via
-    <function>snd_card_proc_new()</function> will be registered and
-    released automatically in the card registration and release
-    functions.
-    </para>
-
-    <para>
-      When the creation is successful, the function stores a new
-    instance in the pointer given in the third argument.
-    It is initialized as a text proc file for read only.  To use
-    this proc file as a read-only text file as it is, set the read
-    callback with a private data via 
-     <function>snd_info_set_text_ops()</function>.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  snd_info_set_text_ops(entry, chip, my_proc_read);
-]]>
-        </programlisting>
-      </informalexample>
-    
-    where the second argument (<parameter>chip</parameter>) is the
-    private data to be used in the callbacks. The third parameter
-    specifies the read buffer size and the fourth
-    (<parameter>my_proc_read</parameter>) is the callback function, which
-    is defined like
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static void my_proc_read(struct snd_info_entry *entry,
-                           struct snd_info_buffer *buffer);
-]]>
-        </programlisting>
-      </informalexample>
-    
-    </para>
-
-    <para>
-    In the read callback, use <function>snd_iprintf()</function> for
-    output strings, which works just like normal
-    <function>printf()</function>.  For example,
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static void my_proc_read(struct snd_info_entry *entry,
-                           struct snd_info_buffer *buffer)
-  {
-          struct my_chip *chip = entry->private_data;
-
-          snd_iprintf(buffer, "This is my chip!\n");
-          snd_iprintf(buffer, "Port = %ld\n", chip->port);
-  }
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-    The file permissions can be changed afterwards.  As default, it's
-    set as read only for all users.  If you want to add write
-    permission for the user (root as default), do as follows:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
- entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-]]>
-        </programlisting>
-      </informalexample>
-
-    and set the write buffer size and the callback
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  entry->c.text.write = my_proc_write;
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      For the write callback, you can use
-    <function>snd_info_get_line()</function> to get a text line, and
-    <function>snd_info_get_str()</function> to retrieve a string from
-    the line. Some examples are found in
-    <filename>core/oss/mixer_oss.c</filename>, core/oss/and
-    <filename>pcm_oss.c</filename>. 
-    </para>
-
-    <para>
-      For a raw-data proc-file, set the attributes as follows:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static struct snd_info_entry_ops my_file_io_ops = {
-          .read = my_file_io_read,
-  };
-
-  entry->content = SNDRV_INFO_CONTENT_DATA;
-  entry->private_data = chip;
-  entry->c.ops = &my_file_io_ops;
-  entry->size = 4096;
-  entry->mode = S_IFREG | S_IRUGO;
-]]>
-        </programlisting>
-      </informalexample>
-
-      For the raw data, <structfield>size</structfield> field must be
-      set properly.  This specifies the maximum size of the proc file access.
-    </para>
-
-    <para>
-      The read/write callbacks of raw mode are more direct than the text mode.
-      You need to use a low-level I/O functions such as
-      <function>copy_from/to_user()</function> to transfer the
-      data.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static ssize_t my_file_io_read(struct snd_info_entry *entry,
-                              void *file_private_data,
-                              struct file *file,
-                              char *buf,
-                              size_t count,
-                              loff_t pos)
-  {
-          if (copy_to_user(buf, local_data + pos, count))
-                  return -EFAULT;
-          return count;
-  }
-]]>
-        </programlisting>
-      </informalexample>
-
-      If the size of the info entry has been set up properly,
-      <structfield>count</structfield> and <structfield>pos</structfield> are
-      guaranteed to fit within 0 and the given size.
-      You don't have to check the range in the callbacks unless any
-      other condition is required.
-
-    </para>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Power Management  -->
-<!-- ****************************************************** -->
-  <chapter id="power-management">
-    <title>Power Management</title>
-    <para>
-      If the chip is supposed to work with suspend/resume
-      functions, you need to add power-management code to the
-      driver. The additional code for power-management should be
-      <function>ifdef</function>'ed with
-      <constant>CONFIG_PM</constant>. 
-    </para>
-
-	<para>
-	If the driver <emphasis>fully</emphasis> supports suspend/resume
-	that is, the device can be
-	properly resumed to its state when suspend was called,
-	you can set the <constant>SNDRV_PCM_INFO_RESUME</constant> flag
-	in the pcm info field.  Usually, this is possible when the
-	registers of the chip can be safely saved and restored to
-	RAM. If this is set, the trigger callback is called with
-	<constant>SNDRV_PCM_TRIGGER_RESUME</constant> after the resume
-	callback completes. 
-	</para>
-
-	<para>
-	Even if the driver doesn't support PM fully but 
-	partial suspend/resume is still possible, it's still worthy to
-	implement suspend/resume callbacks. In such a case, applications
-	would reset the status by calling
-	<function>snd_pcm_prepare()</function> and restart the stream
-	appropriately.  Hence, you can define suspend/resume callbacks
-	below but don't set <constant>SNDRV_PCM_INFO_RESUME</constant>
-	info flag to the PCM.
-	</para>
-	
-	<para>
-	Note that the trigger with SUSPEND can always be called when
-	<function>snd_pcm_suspend_all</function> is called,
-	regardless of the <constant>SNDRV_PCM_INFO_RESUME</constant> flag.
-	The <constant>RESUME</constant> flag affects only the behavior
-	of <function>snd_pcm_resume()</function>.
-	(Thus, in theory,
-	<constant>SNDRV_PCM_TRIGGER_RESUME</constant> isn't needed
-	to be handled in the trigger callback when no
-	<constant>SNDRV_PCM_INFO_RESUME</constant> flag is set.  But,
-	it's better to keep it for compatibility reasons.)
-	</para>
-    <para>
-      In the earlier version of ALSA drivers, a common
-      power-management layer was provided, but it has been removed.
-      The driver needs to define the suspend/resume hooks according to
-      the bus the device is connected to.  In the case of PCI drivers, the
-      callbacks look like below:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  #ifdef CONFIG_PM
-  static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
-  {
-          .... /* do things for suspend */
-          return 0;
-  }
-  static int snd_my_resume(struct pci_dev *pci)
-  {
-          .... /* do things for suspend */
-          return 0;
-  }
-  #endif
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      The scheme of the real suspend job is as follows.
-
-      <orderedlist>
-        <listitem><para>Retrieve the card and the chip data.</para></listitem>
-        <listitem><para>Call <function>snd_power_change_state()</function> with
-	  <constant>SNDRV_CTL_POWER_D3hot</constant> to change the
-	  power status.</para></listitem>
-        <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem>
-	<listitem><para>If AC97 codecs are used, call
-	<function>snd_ac97_suspend()</function> for each codec.</para></listitem>
-        <listitem><para>Save the register values if necessary.</para></listitem>
-        <listitem><para>Stop the hardware if necessary.</para></listitem>
-        <listitem><para>Disable the PCI device by calling
-	  <function>pci_disable_device()</function>.  Then, call
-          <function>pci_save_state()</function> at last.</para></listitem>
-      </orderedlist>
-    </para>
-
-    <para>
-      A typical code would be like:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int mychip_suspend(struct pci_dev *pci, pm_message_t state)
-  {
-          /* (1) */
-          struct snd_card *card = pci_get_drvdata(pci);
-          struct mychip *chip = card->private_data;
-          /* (2) */
-          snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-          /* (3) */
-          snd_pcm_suspend_all(chip->pcm);
-          /* (4) */
-          snd_ac97_suspend(chip->ac97);
-          /* (5) */
-          snd_mychip_save_registers(chip);
-          /* (6) */
-          snd_mychip_stop_hardware(chip);
-          /* (7) */
-          pci_disable_device(pci);
-          pci_save_state(pci);
-          return 0;
-  }
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-    The scheme of the real resume job is as follows.
-
-    <orderedlist>
-    <listitem><para>Retrieve the card and the chip data.</para></listitem>
-    <listitem><para>Set up PCI. First, call <function>pci_restore_state()</function>.
-    	Then enable the pci device again by calling <function>pci_enable_device()</function>.
-	Call <function>pci_set_master()</function> if necessary, too.</para></listitem>
-    <listitem><para>Re-initialize the chip.</para></listitem>
-    <listitem><para>Restore the saved registers if necessary.</para></listitem>
-    <listitem><para>Resume the mixer, e.g. calling
-    <function>snd_ac97_resume()</function>.</para></listitem>
-    <listitem><para>Restart the hardware (if any).</para></listitem>
-    <listitem><para>Call <function>snd_power_change_state()</function> with
-	<constant>SNDRV_CTL_POWER_D0</constant> to notify the processes.</para></listitem>
-    </orderedlist>
-    </para>
-
-    <para>
-    A typical code would be like:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int mychip_resume(struct pci_dev *pci)
-  {
-          /* (1) */
-          struct snd_card *card = pci_get_drvdata(pci);
-          struct mychip *chip = card->private_data;
-          /* (2) */
-          pci_restore_state(pci);
-          pci_enable_device(pci);
-          pci_set_master(pci);
-          /* (3) */
-          snd_mychip_reinit_chip(chip);
-          /* (4) */
-          snd_mychip_restore_registers(chip);
-          /* (5) */
-          snd_ac97_resume(chip->ac97);
-          /* (6) */
-          snd_mychip_restart_chip(chip);
-          /* (7) */
-          snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-          return 0;
-  }
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-	As shown in the above, it's better to save registers after
-	suspending the PCM operations via
-	<function>snd_pcm_suspend_all()</function> or
-	<function>snd_pcm_suspend()</function>.  It means that the PCM
-	streams are already stopped when the register snapshot is
-	taken.  But, remember that you don't have to restart the PCM
-	stream in the resume callback. It'll be restarted via 
-	trigger call with <constant>SNDRV_PCM_TRIGGER_RESUME</constant>
-	when necessary.
-    </para>
-
-    <para>
-      OK, we have all callbacks now. Let's set them up. In the
-      initialization of the card, make sure that you can get the chip
-      data from the card instance, typically via
-      <structfield>private_data</structfield> field, in case you
-      created the chip data individually.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int snd_mychip_probe(struct pci_dev *pci,
-                              const struct pci_device_id *pci_id)
-  {
-          ....
-          struct snd_card *card;
-          struct mychip *chip;
-          int err;
-          ....
-          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                             0, &card);
-          ....
-          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-          ....
-          card->private_data = chip;
-          ....
-  }
-]]>
-        </programlisting>
-      </informalexample>
-
-	When you created the chip data with
-	<function>snd_card_new()</function>, it's anyway accessible
-	via <structfield>private_data</structfield> field.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int snd_mychip_probe(struct pci_dev *pci,
-                              const struct pci_device_id *pci_id)
-  {
-          ....
-          struct snd_card *card;
-          struct mychip *chip;
-          int err;
-          ....
-          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
-                             sizeof(struct mychip), &card);
-          ....
-          chip = card->private_data;
-          ....
-  }
-]]>
-        </programlisting>
-      </informalexample>
-
-    </para>
-
-    <para>
-      If you need a space to save the registers, allocate the
-	buffer for it here, too, since it would be fatal
-    if you cannot allocate a memory in the suspend phase.
-    The allocated buffer should be released in the corresponding
-    destructor.
-    </para>
-
-    <para>
-      And next, set suspend/resume callbacks to the pci_driver.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static struct pci_driver driver = {
-          .name = KBUILD_MODNAME,
-          .id_table = snd_my_ids,
-          .probe = snd_my_probe,
-          .remove = snd_my_remove,
-  #ifdef CONFIG_PM
-          .suspend = snd_my_suspend,
-          .resume = snd_my_resume,
-  #endif
-  };
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Module Parameters  -->
-<!-- ****************************************************** -->
-  <chapter id="module-parameters">
-    <title>Module Parameters</title>
-    <para>
-      There are standard module options for ALSA. At least, each
-      module should have the <parameter>index</parameter>,
-      <parameter>id</parameter> and <parameter>enable</parameter>
-      options. 
-    </para>
-
-    <para>
-      If the module supports multiple cards (usually up to
-      8 = <constant>SNDRV_CARDS</constant> cards), they should be
-      arrays. The default initial values are defined already as
-      constants for easier programming:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-  static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      If the module supports only a single card, they could be single
-    variables, instead.  <parameter>enable</parameter> option is not
-    always necessary in this case, but it would be better to have a
-    dummy option for compatibility.
-    </para>
-
-    <para>
-      The module parameters must be declared with the standard
-    <function>module_param()()</function>,
-    <function>module_param_array()()</function> and
-    <function>MODULE_PARM_DESC()</function> macros.
-    </para>
-
-    <para>
-      The typical coding would be like below:
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  #define CARD_NAME "My Chip"
-
-  module_param_array(index, int, NULL, 0444);
-  MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
-  module_param_array(id, charp, NULL, 0444);
-  MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
-  module_param_array(enable, bool, NULL, 0444);
-  MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
-      Also, don't forget to define the module description, classes,
-      license and devices. Especially, the recent modprobe requires to
-      define the module license as GPL, etc., otherwise the system is
-      shown as <quote>tainted</quote>. 
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  MODULE_DESCRIPTION("My Chip");
-  MODULE_LICENSE("GPL");
-  MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- How To Put Your Driver  -->
-<!-- ****************************************************** -->
-  <chapter id="how-to-put-your-driver">
-    <title>How To Put Your Driver Into ALSA Tree</title>
-	<section>
-	<title>General</title>
-	<para>
-	So far, you've learned how to write the driver codes.
-	And you might have a question now: how to put my own
-	driver into the ALSA driver tree?
-	Here (finally :) the standard procedure is described briefly.
-	</para>
-
-	<para>
-	Suppose that you create a new PCI driver for the card
-	<quote>xyz</quote>.  The card module name would be
-	snd-xyz.  The new driver is usually put into the alsa-driver
-	tree, <filename>alsa-driver/pci</filename> directory in
-	the case of PCI cards.
-	Then the driver is evaluated, audited and tested
-	by developers and users.  After a certain time, the driver
-	will go to the alsa-kernel tree (to the corresponding directory,
-	such as <filename>alsa-kernel/pci</filename>) and eventually
- 	will be integrated into the Linux 2.6 tree (the directory would be
-	<filename>linux/sound/pci</filename>).
-	</para>
-
-	<para>
-	In the following sections, the driver code is supposed
-	to be put into alsa-driver tree. The two cases are covered:
-	a driver consisting of a single source file and one consisting
-	of several source files.
-	</para>
-	</section>
-
-	<section>
-	<title>Driver with A Single Source File</title>
-	<para>
-	<orderedlist>
-	<listitem>
-	<para>
-	Modify alsa-driver/pci/Makefile
-	</para>
-
-	<para>
-	Suppose you have a file xyz.c.  Add the following
-	two lines
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  snd-xyz-objs := xyz.o
-  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
-]]>
-        </programlisting>
-      </informalexample>
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Create the Kconfig entry
-	</para>
-
-	<para>
-	Add the new entry of Kconfig for your xyz driver.
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  config SND_XYZ
-          tristate "Foobar XYZ"
-          depends on SND
-          select SND_PCM
-          help
-            Say Y here to include support for Foobar XYZ soundcard.
-
-            To compile this driver as a module, choose M here: the module
-            will be called snd-xyz.
-]]>
-        </programlisting>
-      </informalexample>
-
-	the line, select SND_PCM, specifies that the driver xyz supports
-	PCM.  In addition to SND_PCM, the following components are
-	supported for select command:
-	SND_RAWMIDI, SND_TIMER, SND_HWDEP, SND_MPU401_UART,
-	SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB, SND_AC97_CODEC.
-	Add the select command for each supported component.
-	</para>
-
-	<para>
-	Note that some selections imply the lowlevel selections.
-	For example, PCM includes TIMER, MPU401_UART includes RAWMIDI,
-	AC97_CODEC includes PCM, and OPL3_LIB includes HWDEP.
-	You don't need to give the lowlevel selections again.
-	</para>
-
-	<para>
-	For the details of Kconfig script, refer to the kbuild
-	documentation.
-	</para>
-
-	</listitem>
-
-	<listitem>
-	<para>
-	Run cvscompile script to re-generate the configure script and
-	build the whole stuff again.
-	</para>
-	</listitem>
-	</orderedlist>
-	</para>
-	</section>
-
-	<section>
-	<title>Drivers with Several Source Files</title>
-	<para>
-	Suppose that the driver snd-xyz have several source files.
-	They are located in the new subdirectory,
-	pci/xyz.
-
-	<orderedlist>
-	<listitem>
-	<para>
-	Add a new directory (<filename>xyz</filename>) in
-	<filename>alsa-driver/pci/Makefile</filename> as below
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  obj-$(CONFIG_SND) += xyz/
-]]>
-        </programlisting>
-      </informalexample>
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Under the directory <filename>xyz</filename>, create a Makefile
-
-      <example>
-	<title>Sample Makefile for a driver xyz</title>
-        <programlisting>
-<![CDATA[
-  ifndef SND_TOPDIR
-  SND_TOPDIR=../..
-  endif
-
-  include $(SND_TOPDIR)/toplevel.config
-  include $(SND_TOPDIR)/Makefile.conf
-
-  snd-xyz-objs := xyz.o abc.o def.o
-
-  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
-
-  include $(SND_TOPDIR)/Rules.make
-]]>
-        </programlisting>
-      </example>
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Create the Kconfig entry
-	</para>
-
-	<para>
-	This procedure is as same as in the last section.
-	</para>
-	</listitem>
-
-	<listitem>
-	<para>
-	Run cvscompile script to re-generate the configure script and
-	build the whole stuff again.
-	</para>
-	</listitem>
-	</orderedlist>
-	</para>
-	</section>
-
-  </chapter>
-
-<!-- ****************************************************** -->
-<!-- Useful Functions  -->
-<!-- ****************************************************** -->
-  <chapter id="useful-functions">
-    <title>Useful Functions</title>
-
-    <section id="useful-functions-snd-printk">
-      <title><function>snd_printk()</function> and friends</title>
-      <para>
-        ALSA provides a verbose version of the
-      <function>printk()</function> function. If a kernel config
-      <constant>CONFIG_SND_VERBOSE_PRINTK</constant> is set, this
-      function prints the given message together with the file name
-      and the line of the caller. The <constant>KERN_XXX</constant>
-      prefix is processed as 
-      well as the original <function>printk()</function> does, so it's
-      recommended to add this prefix, e.g. 
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\n");
-]]>
-          </programlisting>
-        </informalexample>
-      </para>
-
-      <para>
-        There are also <function>printk()</function>'s for
-      debugging. <function>snd_printd()</function> can be used for
-      general debugging purposes. If
-      <constant>CONFIG_SND_DEBUG</constant> is set, this function is
-      compiled, and works just like
-      <function>snd_printk()</function>. If the ALSA is compiled
-      without the debugging flag, it's ignored. 
-      </para>
-
-      <para>
-        <function>snd_printdd()</function> is compiled in only when
-      <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is set. Please note
-      that <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is not set as default
-      even if you configure the alsa-driver with
-      <option>--with-debug=full</option> option. You need to give
-      explicitly <option>--with-debug=detect</option> option instead. 
-      </para>
-    </section>
-
-    <section id="useful-functions-snd-bug">
-      <title><function>snd_BUG()</function></title>
-      <para>
-        It shows the <computeroutput>BUG?</computeroutput> message and
-      stack trace as well as <function>snd_BUG_ON</function> at the point.
-      It's useful to show that a fatal error happens there. 
-      </para>
-      <para>
-	 When no debug flag is set, this macro is ignored. 
-      </para>
-    </section>
-
-    <section id="useful-functions-snd-bug-on">
-      <title><function>snd_BUG_ON()</function></title>
-      <para>
-        <function>snd_BUG_ON()</function> macro is similar with
-	<function>WARN_ON()</function> macro. For example,  
-
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  snd_BUG_ON(!pointer);
-]]>
-          </programlisting>
-        </informalexample>
-
-	or it can be used as the condition,
-        <informalexample>
-          <programlisting>
-<![CDATA[
-  if (snd_BUG_ON(non_zero_is_bug))
-          return -EINVAL;
-]]>
-          </programlisting>
-        </informalexample>
-
-      </para>
-
-      <para>
-        The macro takes an conditional expression to evaluate.
-	When <constant>CONFIG_SND_DEBUG</constant>, is set, if the
-	expression is non-zero, it shows the warning message such as
-	<computeroutput>BUG? (xxx)</computeroutput>
-	normally followed by stack trace.
-
-	In both cases it returns the evaluated value.
-      </para>
-
-    </section>
-
-  </chapter>
-
-
-<!-- ****************************************************** -->
-<!-- Acknowledgments  -->
-<!-- ****************************************************** -->
-  <chapter id="acknowledgments">
-    <title>Acknowledgments</title>
-    <para>
-      I would like to thank Phil Kerr for his help for improvement and
-      corrections of this document. 
-    </para>
-    <para>
-    Kevin Conder reformatted the original plain-text to the
-    DocBook format.
-    </para>
-    <para>
-    Giuliano Pochini corrected typos and contributed the example codes
-    in the hardware constraints section.
-    </para>
-  </chapter>
-</book>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/doc-guide/conf.py linux-libre-4.10-rc8-gnu/Documentation/doc-guide/conf.py
--- linux-libre-4.9-gnu/Documentation/doc-guide/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/doc-guide/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel Documentation Guide'
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'kernel-doc-guide.tex', 'Linux Kernel Documentation Guide',
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/doc-guide/docbook.rst linux-libre-4.10-rc8-gnu/Documentation/doc-guide/docbook.rst
--- linux-libre-4.9-gnu/Documentation/doc-guide/docbook.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/doc-guide/docbook.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,90 @@
+DocBook XML [DEPRECATED]
+========================
+
+.. attention::
+
+   This section describes the deprecated DocBook XML toolchain. Please do not
+   create new DocBook XML template files. Please consider converting existing
+   DocBook XML templates files to Sphinx/reStructuredText.
+
+Converting DocBook to Sphinx
+----------------------------
+
+Over time, we expect all of the documents under ``Documentation/DocBook`` to be
+converted to Sphinx and reStructuredText. For most DocBook XML documents, a good
+enough solution is to use the simple ``Documentation/sphinx/tmplcvt`` script,
+which uses ``pandoc`` under the hood. For example::
+
+  $ cd Documentation/sphinx
+  $ ./tmplcvt ../DocBook/in.tmpl ../out.rst
+
+Then edit the resulting rst files to fix any remaining issues, and add the
+document in the ``toctree`` in ``Documentation/index.rst``.
+
+Components of the kernel-doc system
+-----------------------------------
+
+Many places in the source tree have extractable documentation in the form of
+block comments above functions. The components of this system are:
+
+- ``scripts/kernel-doc``
+
+  This is a perl script that hunts for the block comments and can mark them up
+  directly into reStructuredText, DocBook, man, text, and HTML. (No, not
+  texinfo.)
+
+- ``Documentation/DocBook/*.tmpl``
+
+  These are XML template files, which are normal XML files with special
+  place-holders for where the extracted documentation should go.
+
+- ``scripts/docproc.c``
+
+  This is a program for converting XML template files into XML files. When a
+  file is referenced it is searched for symbols exported (EXPORT_SYMBOL), to be
+  able to distinguish between internal and external functions.
+
+  It invokes kernel-doc, giving it the list of functions that are to be
+  documented.
+
+  Additionally it is used to scan the XML template files to locate all the files
+  referenced herein. This is used to generate dependency information as used by
+  make.
+
+- ``Makefile``
+
+  The targets 'xmldocs', 'psdocs', 'pdfdocs', and 'htmldocs' are used to build
+  DocBook XML files, PostScript files, PDF files, and html files in
+  Documentation/DocBook. The older target 'sgmldocs' is equivalent to 'xmldocs'.
+
+- ``Documentation/DocBook/Makefile``
+
+  This is where C files are associated with SGML templates.
+
+How to use kernel-doc comments in DocBook XML template files
+------------------------------------------------------------
+
+DocBook XML template files (\*.tmpl) are like normal XML files, except that they
+can contain escape sequences where extracted documentation should be inserted.
+
+``!E<filename>`` is replaced by the documentation, in ``<filename>``, for
+functions that are exported using ``EXPORT_SYMBOL``: the function list is
+collected from files listed in ``Documentation/DocBook/Makefile``.
+
+``!I<filename>`` is replaced by the documentation for functions that are **not**
+exported using ``EXPORT_SYMBOL``.
+
+``!D<filename>`` is used to name additional files to search for functions
+exported using ``EXPORT_SYMBOL``.
+
+``!F<filename> <function [functions...]>`` is replaced by the documentation, in
+``<filename>``, for the functions listed.
+
+``!P<filename> <section title>`` is replaced by the contents of the ``DOC:``
+section titled ``<section title>`` from ``<filename>``. Spaces are allowed in
+``<section title>``; do not quote the ``<section title>``.
+
+``!C<filename>`` is replaced by nothing, but makes the tools check that all DOC:
+sections and documented functions, symbols, etc. are used. This makes sense to
+use when you use ``!F`` or ``!P`` only and want to verify that all documentation
+is included.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/doc-guide/index.rst linux-libre-4.10-rc8-gnu/Documentation/doc-guide/index.rst
--- linux-libre-4.9-gnu/Documentation/doc-guide/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/doc-guide/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+.. _doc_guide:
+
+=================================
+How to write kernel documentation
+=================================
+
+.. toctree::
+   :maxdepth: 1
+
+   sphinx.rst
+   kernel-doc.rst
+   parse-headers.rst
+   docbook.rst
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/doc-guide/kernel-doc.rst linux-libre-4.10-rc8-gnu/Documentation/doc-guide/kernel-doc.rst
--- linux-libre-4.9-gnu/Documentation/doc-guide/kernel-doc.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/doc-guide/kernel-doc.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,368 @@
+Including kernel-doc comments
+=============================
+
+The Linux kernel source files may contain structured documentation comments, or
+kernel-doc comments to describe the functions and types and design of the
+code. The documentation comments may be included to any of the reStructuredText
+documents using a dedicated kernel-doc Sphinx directive extension.
+
+The kernel-doc directive is of the format::
+
+  .. kernel-doc:: source
+     :option:
+
+The *source* is the path to a source file, relative to the kernel source
+tree. The following directive options are supported:
+
+export: *[source-pattern ...]*
+  Include documentation for all functions in *source* that have been exported
+  using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL`` either in *source* or in any
+  of the files specified by *source-pattern*.
+
+  The *source-pattern* is useful when the kernel-doc comments have been placed
+  in header files, while ``EXPORT_SYMBOL`` and ``EXPORT_SYMBOL_GPL`` are next to
+  the function definitions.
+
+  Examples::
+
+    .. kernel-doc:: lib/bitmap.c
+       :export:
+
+    .. kernel-doc:: include/net/mac80211.h
+       :export: net/mac80211/*.c
+
+internal: *[source-pattern ...]*
+  Include documentation for all functions and types in *source* that have
+  **not** been exported using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL`` either
+  in *source* or in any of the files specified by *source-pattern*.
+
+  Example::
+
+    .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
+       :internal:
+
+doc: *title*
+  Include documentation for the ``DOC:`` paragraph identified by *title* in
+  *source*. Spaces are allowed in *title*; do not quote the *title*. The *title*
+  is only used as an identifier for the paragraph, and is not included in the
+  output. Please make sure to have an appropriate heading in the enclosing
+  reStructuredText document.
+
+  Example::
+
+    .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
+       :doc: High Definition Audio over HDMI and Display Port
+
+functions: *function* *[...]*
+  Include documentation for each *function* in *source*.
+
+  Example::
+
+    .. kernel-doc:: lib/bitmap.c
+       :functions: bitmap_parselist bitmap_parselist_user
+
+Without options, the kernel-doc directive includes all documentation comments
+from the source file.
+
+The kernel-doc extension is included in the kernel source tree, at
+``Documentation/sphinx/kernel-doc.py``. Internally, it uses the
+``scripts/kernel-doc`` script to extract the documentation comments from the
+source.
+
+.. _kernel_doc:
+
+Writing kernel-doc comments
+===========================
+
+In order to provide embedded, "C" friendly, easy to maintain, but consistent and
+extractable overview, function and type documentation, the Linux kernel has
+adopted a consistent style for documentation comments. The format for this
+documentation is called the kernel-doc format, described below. This style
+embeds the documentation within the source files, using a few simple conventions
+for adding documentation paragraphs and documenting functions and their
+parameters, structures and unions and their members, enumerations, and typedefs.
+
+.. note:: The kernel-doc format is deceptively similar to gtk-doc or Doxygen,
+   yet distinctively different, for historical reasons. The kernel source
+   contains tens of thousands of kernel-doc comments. Please stick to the style
+   described here.
+
+The ``scripts/kernel-doc`` script is used by the Sphinx kernel-doc extension in
+the documentation build to extract this embedded documentation into the various
+HTML, PDF, and other format documents.
+
+In order to provide good documentation of kernel functions and data structures,
+please use the following conventions to format your kernel-doc comments in the
+Linux kernel source.
+
+How to format kernel-doc comments
+---------------------------------
+
+The opening comment mark ``/**`` is reserved for kernel-doc comments. Only
+comments so marked will be considered by the ``kernel-doc`` tool. Use it only
+for comment blocks that contain kernel-doc formatted comments. The usual ``*/``
+should be used as the closing comment marker. The lines in between should be
+prefixed by `` * `` (space star space).
+
+The function and type kernel-doc comments should be placed just before the
+function or type being described. The overview kernel-doc comments may be freely
+placed at the top indentation level.
+
+Example kernel-doc function comment::
+
+  /**
+   * foobar() - Brief description of foobar.
+   * @arg: Description of argument of foobar.
+   *
+   * Longer description of foobar.
+   *
+   * Return: Description of return value of foobar.
+   */
+  int foobar(int arg)
+
+The format is similar for documentation for structures, enums, paragraphs,
+etc. See the sections below for details.
+
+The kernel-doc structure is extracted from the comments, and proper `Sphinx C
+Domain`_ function and type descriptions with anchors are generated for them. The
+descriptions are filtered for special kernel-doc highlights and
+cross-references. See below for details.
+
+.. _Sphinx C Domain: http://www.sphinx-doc.org/en/stable/domains.html
+
+Highlights and cross-references
+-------------------------------
+
+The following special patterns are recognized in the kernel-doc comment
+descriptive text and converted to proper reStructuredText markup and `Sphinx C
+Domain`_ references.
+
+.. attention:: The below are **only** recognized within kernel-doc comments,
+	       **not** within normal reStructuredText documents.
+
+``funcname()``
+  Function reference.
+
+``@parameter``
+  Name of a function parameter. (No cross-referencing, just formatting.)
+
+``%CONST``
+  Name of a constant. (No cross-referencing, just formatting.)
+
+``$ENVVAR``
+  Name of an environment variable. (No cross-referencing, just formatting.)
+
+``&struct name``
+  Structure reference.
+
+``&enum name``
+  Enum reference.
+
+``&typedef name``
+  Typedef reference.
+
+``&struct_name->member`` or ``&struct_name.member``
+  Structure or union member reference. The cross-reference will be to the struct
+  or union definition, not the member directly.
+
+``&name``
+  A generic type reference. Prefer using the full reference described above
+  instead. This is mostly for legacy comments.
+
+Cross-referencing from reStructuredText
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To cross-reference the functions and types defined in the kernel-doc comments
+from reStructuredText documents, please use the `Sphinx C Domain`_
+references. For example::
+
+  See function :c:func:`foo` and struct/union/enum/typedef :c:type:`bar`.
+
+While the type reference works with just the type name, without the
+struct/union/enum/typedef part in front, you may want to use::
+
+  See :c:type:`struct foo <foo>`.
+  See :c:type:`union bar <bar>`.
+  See :c:type:`enum baz <baz>`.
+  See :c:type:`typedef meh <meh>`.
+
+This will produce prettier links, and is in line with how kernel-doc does the
+cross-references.
+
+For further details, please refer to the `Sphinx C Domain`_ documentation.
+
+Function documentation
+----------------------
+
+The general format of a function and function-like macro kernel-doc comment is::
+
+  /**
+   * function_name() - Brief description of function.
+   * @arg1: Describe the first argument.
+   * @arg2: Describe the second argument.
+   *        One can provide multiple line descriptions
+   *        for arguments.
+   *
+   * A longer description, with more discussion of the function function_name()
+   * that might be useful to those using or modifying it. Begins with an
+   * empty comment line, and may include additional embedded empty
+   * comment lines.
+   *
+   * The longer description may have multiple paragraphs.
+   *
+   * Return: Describe the return value of foobar.
+   *
+   * The return value description can also have multiple paragraphs, and should
+   * be placed at the end of the comment block.
+   */
+
+The brief description following the function name may span multiple lines, and
+ends with an ``@argument:`` description, a blank comment line, or the end of the
+comment block.
+
+The kernel-doc function comments describe each parameter to the function, in
+order, with the ``@argument:`` descriptions. The ``@argument:`` descriptions
+must begin on the very next line following the opening brief function
+description line, with no intervening blank comment lines. The ``@argument:``
+descriptions may span multiple lines. The continuation lines may contain
+indentation. If a function parameter is ``...`` (varargs), it should be listed
+in kernel-doc notation as: ``@...:``.
+
+The return value, if any, should be described in a dedicated section at the end
+of the comment starting with "Return:".
+
+Structure, union, and enumeration documentation
+-----------------------------------------------
+
+The general format of a struct, union, and enum kernel-doc comment is::
+
+  /**
+   * struct struct_name - Brief description.
+   * @member_name: Description of member member_name.
+   *
+   * Description of the structure.
+   */
+
+Below, "struct" is used to mean structs, unions and enums, and "member" is used
+to mean struct and union members as well as enumerations in an enum.
+
+The brief description following the structure name may span multiple lines, and
+ends with a ``@member:`` description, a blank comment line, or the end of the
+comment block.
+
+The kernel-doc data structure comments describe each member of the structure, in
+order, with the ``@member:`` descriptions. The ``@member:`` descriptions must
+begin on the very next line following the opening brief function description
+line, with no intervening blank comment lines. The ``@member:`` descriptions may
+span multiple lines. The continuation lines may contain indentation.
+
+In-line member documentation comments
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The structure members may also be documented in-line within the definition.
+There are two styles, single-line comments where both the opening ``/**`` and
+closing ``*/`` are on the same line, and multi-line comments where they are each
+on a line of their own, like all other kernel-doc comments::
+
+  /**
+   * struct foo - Brief description.
+   * @foo: The Foo member.
+   */
+  struct foo {
+        int foo;
+        /**
+         * @bar: The Bar member.
+         */
+        int bar;
+        /**
+         * @baz: The Baz member.
+         *
+         * Here, the member description may contain several paragraphs.
+         */
+        int baz;
+        /** @foobar: Single line description. */
+        int foobar;
+  }
+
+Private members
+~~~~~~~~~~~~~~~
+
+Inside a struct description, you can use the "private:" and "public:" comment
+tags. Structure fields that are inside a "private:" area are not listed in the
+generated output documentation.  The "private:" and "public:" tags must begin
+immediately following a ``/*`` comment marker.  They may optionally include
+comments between the ``:`` and the ending ``*/`` marker.
+
+Example::
+
+  /**
+   * struct my_struct - short description
+   * @a: first member
+   * @b: second member
+   *
+   * Longer description
+   */
+  struct my_struct {
+      int a;
+      int b;
+  /* private: internal use only */
+      int c;
+  };
+
+
+Typedef documentation
+---------------------
+
+The general format of a typedef kernel-doc comment is::
+
+  /**
+   * typedef type_name - Brief description.
+   *
+   * Description of the type.
+   */
+
+Overview documentation comments
+-------------------------------
+
+To facilitate having source code and comments close together, you can include
+kernel-doc documentation blocks that are free-form comments instead of being
+kernel-doc for functions, structures, unions, enums, or typedefs. This could be
+used for something like a theory of operation for a driver or library code, for
+example.
+
+This is done by using a ``DOC:`` section keyword with a section title.
+
+The general format of an overview or high-level documentation comment is::
+
+  /**
+   * DOC: Theory of Operation
+   *
+   * The whizbang foobar is a dilly of a gizmo. It can do whatever you
+   * want it to do, at any time. It reads your mind. Here's how it works.
+   *
+   * foo bar splat
+   *
+   * The only drawback to this gizmo is that is can sometimes damage
+   * hardware, software, or its subject(s).
+   */
+
+The title following ``DOC:`` acts as a heading within the source file, but also
+as an identifier for extracting the documentation comment. Thus, the title must
+be unique within the file.
+
+Recommendations
+---------------
+
+We definitely need kernel-doc formatted documentation for functions that are
+exported to loadable modules using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL``.
+
+We also look to provide kernel-doc formatted documentation for functions
+externally visible to other kernel files (not marked "static").
+
+We also recommend providing kernel-doc formatted documentation for private (file
+"static") routines, for consistency of kernel source code layout. But this is
+lower priority and at the discretion of the MAINTAINER of that kernel source
+file.
+
+Data structures visible in kernel include files should also be documented using
+kernel-doc formatted comments.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/doc-guide/parse-headers.rst linux-libre-4.10-rc8-gnu/Documentation/doc-guide/parse-headers.rst
--- linux-libre-4.9-gnu/Documentation/doc-guide/parse-headers.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/doc-guide/parse-headers.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,192 @@
+===========================
+Including uAPI header files
+===========================
+
+Sometimes, it is useful to include header files and C example codes in
+order to describe the userspace API and to generate cross-references
+between the code and the documentation. Adding cross-references for
+userspace API files has an additional vantage: Sphinx will generate warnings
+if a symbol is not found at the documentation. That helps to keep the
+uAPI documentation in sync with the Kernel changes.
+The :ref:`parse_headers.pl <parse_headers>` provide a way to generate such
+cross-references. It has to be called via Makefile, while building the
+documentation. Please see ``Documentation/media/Makefile`` for an example
+about how to use it inside the Kernel tree.
+
+.. _parse_headers:
+
+parse_headers.pl
+^^^^^^^^^^^^^^^^
+
+NAME
+****
+
+
+parse_headers.pl - parse a C file, in order to identify functions, structs,
+enums and defines and create cross-references to a Sphinx book.
+
+
+SYNOPSIS
+********
+
+
+\ **parse_headers.pl**\  [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
+
+Where <options> can be: --debug, --help or --man.
+
+
+OPTIONS
+*******
+
+
+
+\ **--debug**\
+
+ Put the script in verbose mode, useful for debugging.
+
+
+
+\ **--usage**\
+
+ Prints a brief help message and exits.
+
+
+
+\ **--help**\
+
+ Prints a more detailed help message and exits.
+
+
+DESCRIPTION
+***********
+
+
+Convert a C header or source file (C_FILE), into a ReStructured Text
+included via ..parsed-literal block with cross-references for the
+documentation files that describe the API. It accepts an optional
+EXCEPTIONS_FILE with describes what elements will be either ignored or
+be pointed to a non-default reference.
+
+The output is written at the (OUT_FILE).
+
+It is capable of identifying defines, functions, structs, typedefs,
+enums and enum symbols and create cross-references for all of them.
+It is also capable of distinguish #define used for specifying a Linux
+ioctl.
+
+The EXCEPTIONS_FILE contain two types of statements: \ **ignore**\  or \ **replace**\ .
+
+The syntax for the ignore tag is:
+
+
+ignore \ **type**\  \ **name**\
+
+The \ **ignore**\  means that it won't generate cross references for a
+\ **name**\  symbol of type \ **type**\ .
+
+The syntax for the replace tag is:
+
+
+replace \ **type**\  \ **name**\  \ **new_value**\
+
+The \ **replace**\  means that it will generate cross references for a
+\ **name**\  symbol of type \ **type**\ , but, instead of using the default
+replacement rule, it will use \ **new_value**\ .
+
+For both statements, \ **type**\  can be either one of the following:
+
+
+\ **ioctl**\
+
+ The ignore or replace statement will apply to ioctl definitions like:
+
+ #define	VIDIOC_DBG_S_REGISTER 	 _IOW('V', 79, struct v4l2_dbg_register)
+
+
+
+\ **define**\
+
+ The ignore or replace statement will apply to any other #define found
+ at C_FILE.
+
+
+
+\ **typedef**\
+
+ The ignore or replace statement will apply to typedef statements at C_FILE.
+
+
+
+\ **struct**\
+
+ The ignore or replace statement will apply to the name of struct statements
+ at C_FILE.
+
+
+
+\ **enum**\
+
+ The ignore or replace statement will apply to the name of enum statements
+ at C_FILE.
+
+
+
+\ **symbol**\
+
+ The ignore or replace statement will apply to the name of enum statements
+ at C_FILE.
+
+ For replace statements, \ **new_value**\  will automatically use :c:type:
+ references for \ **typedef**\ , \ **enum**\  and \ **struct**\  types. It will use :ref:
+ for \ **ioctl**\ , \ **define**\  and \ **symbol**\  types. The type of reference can
+ also be explicitly defined at the replace statement.
+
+
+
+EXAMPLES
+********
+
+
+ignore define _VIDEODEV2_H
+
+
+Ignore a #define _VIDEODEV2_H at the C_FILE.
+
+ignore symbol PRIVATE
+
+
+On a struct like:
+
+enum foo { BAR1, BAR2, PRIVATE };
+
+It won't generate cross-references for \ **PRIVATE**\ .
+
+replace symbol BAR1 :c:type:\`foo\`
+replace symbol BAR2 :c:type:\`foo\`
+
+
+On a struct like:
+
+enum foo { BAR1, BAR2, PRIVATE };
+
+It will make the BAR1 and BAR2 enum symbols to cross reference the foo
+symbol at the C domain.
+
+
+BUGS
+****
+
+
+Report bugs to Mauro Carvalho Chehab <mchehab@s-opensource.com>
+
+
+COPYRIGHT
+*********
+
+
+Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@s-opensource.com>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/doc-guide/sphinx.rst linux-libre-4.10-rc8-gnu/Documentation/doc-guide/sphinx.rst
--- linux-libre-4.9-gnu/Documentation/doc-guide/sphinx.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/doc-guide/sphinx.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,219 @@
+Introduction
+============
+
+The Linux kernel uses `Sphinx`_ to generate pretty documentation from
+`reStructuredText`_ files under ``Documentation``. To build the documentation in
+HTML or PDF formats, use ``make htmldocs`` or ``make pdfdocs``. The generated
+documentation is placed in ``Documentation/output``.
+
+.. _Sphinx: http://www.sphinx-doc.org/
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
+
+The reStructuredText files may contain directives to include structured
+documentation comments, or kernel-doc comments, from source files. Usually these
+are used to describe the functions and types and design of the code. The
+kernel-doc comments have some special structure and formatting, but beyond that
+they are also treated as reStructuredText.
+
+There is also the deprecated DocBook toolchain to generate documentation from
+DocBook XML template files under ``Documentation/DocBook``. The DocBook files
+are to be converted to reStructuredText, and the toolchain is slated to be
+removed.
+
+Finally, there are thousands of plain text documentation files scattered around
+``Documentation``. Some of these will likely be converted to reStructuredText
+over time, but the bulk of them will remain in plain text.
+
+Sphinx Build
+============
+
+The usual way to generate the documentation is to run ``make htmldocs`` or
+``make pdfdocs``. There are also other formats available, see the documentation
+section of ``make help``. The generated documentation is placed in
+format-specific subdirectories under ``Documentation/output``.
+
+To generate documentation, Sphinx (``sphinx-build``) must obviously be
+installed. For prettier HTML output, the Read the Docs Sphinx theme
+(``sphinx_rtd_theme``) is used if available. For PDF output, ``rst2pdf`` is also
+needed. All of these are widely available and packaged in distributions.
+
+To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make
+variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose
+output.
+
+To remove the generated documentation, run ``make cleandocs``.
+
+Writing Documentation
+=====================
+
+Adding new documentation can be as simple as:
+
+1. Add a new ``.rst`` file somewhere under ``Documentation``.
+2. Refer to it from the Sphinx main `TOC tree`_ in ``Documentation/index.rst``.
+
+.. _TOC tree: http://www.sphinx-doc.org/en/stable/markup/toctree.html
+
+This is usually good enough for simple documentation (like the one you're
+reading right now), but for larger documents it may be advisable to create a
+subdirectory (or use an existing one). For example, the graphics subsystem
+documentation is under ``Documentation/gpu``, split to several ``.rst`` files,
+and has a separate ``index.rst`` (with a ``toctree`` of its own) referenced from
+the main index.
+
+See the documentation for `Sphinx`_ and `reStructuredText`_ on what you can do
+with them. In particular, the Sphinx `reStructuredText Primer`_ is a good place
+to get started with reStructuredText. There are also some `Sphinx specific
+markup constructs`_.
+
+.. _reStructuredText Primer: http://www.sphinx-doc.org/en/stable/rest.html
+.. _Sphinx specific markup constructs: http://www.sphinx-doc.org/en/stable/markup/index.html
+
+Specific guidelines for the kernel documentation
+------------------------------------------------
+
+Here are some specific guidelines for the kernel documentation:
+
+* Please don't go overboard with reStructuredText markup. Keep it simple.
+
+* Please stick to this order of heading adornments:
+
+  1. ``=`` with overline for document title::
+
+       ==============
+       Document title
+       ==============
+
+  2. ``=`` for chapters::
+
+       Chapters
+       ========
+
+  3. ``-`` for sections::
+
+       Section
+       -------
+
+  4. ``~`` for subsections::
+
+       Subsection
+       ~~~~~~~~~~
+
+  Although RST doesn't mandate a specific order ("Rather than imposing a fixed
+  number and order of section title adornment styles, the order enforced will be
+  the order as encountered."), having the higher levels the same overall makes
+  it easier to follow the documents.
+
+
+the C domain
+------------
+
+The `Sphinx C Domain`_ (name c) is suited for documentation of C API. E.g. a
+function prototype:
+
+.. code-block:: rst
+
+    .. c:function:: int ioctl( int fd, int request )
+
+The C domain of the kernel-doc has some additional features. E.g. you can
+*rename* the reference name of a function with a common name like ``open`` or
+``ioctl``:
+
+.. code-block:: rst
+
+     .. c:function:: int ioctl( int fd, int request )
+        :name: VIDIOC_LOG_STATUS
+
+The func-name (e.g. ioctl) remains in the output but the ref-name changed from
+``ioctl`` to ``VIDIOC_LOG_STATUS``. The index entry for this function is also
+changed to ``VIDIOC_LOG_STATUS`` and the function can now referenced by:
+
+.. code-block:: rst
+
+     :c:func:`VIDIOC_LOG_STATUS`
+
+
+list tables
+-----------
+
+We recommend the use of *list table* formats. The *list table* formats are
+double-stage lists. Compared to the ASCII-art they might not be as
+comfortable for
+readers of the text files. Their advantage is that they are easy to
+create or modify and that the diff of a modification is much more meaningful,
+because it is limited to the modified content.
+
+The ``flat-table`` is a double-stage list similar to the ``list-table`` with
+some additional features:
+
+* column-span: with the role ``cspan`` a cell can be extended through
+  additional columns
+
+* row-span: with the role ``rspan`` a cell can be extended through
+  additional rows
+
+* auto span rightmost cell of a table row over the missing cells on the right
+  side of that table-row.  With Option ``:fill-cells:`` this behavior can
+  changed from *auto span* to *auto fill*, which automatically inserts (empty)
+  cells instead of spanning the last cell.
+
+options:
+
+* ``:header-rows:``   [int] count of header rows
+* ``:stub-columns:``  [int] count of stub columns
+* ``:widths:``        [[int] [int] ... ] widths of columns
+* ``:fill-cells:``    instead of auto-spanning missing cells, insert missing cells
+
+roles:
+
+* ``:cspan:`` [int] additional columns (*morecols*)
+* ``:rspan:`` [int] additional rows (*morerows*)
+
+The example below shows how to use this markup.  The first level of the staged
+list is the *table-row*. In the *table-row* there is only one markup allowed,
+the list of the cells in this *table-row*. Exceptions are *comments* ( ``..`` )
+and *targets* (e.g. a ref to ``:ref:`last row <last row>``` / :ref:`last row
+<last row>`).
+
+.. code-block:: rst
+
+   .. flat-table:: table title
+      :widths: 2 1 1 3
+
+      * - head col 1
+        - head col 2
+        - head col 3
+        - head col 4
+
+      * - column 1
+        - field 1.1
+        - field 1.2 with autospan
+
+      * - column 2
+        - field 2.1
+        - :rspan:`1` :cspan:`1` field 2.2 - 3.3
+
+      * .. _`last row`:
+
+        - column 3
+
+Rendered as:
+
+   .. flat-table:: table title
+      :widths: 2 1 1 3
+
+      * - head col 1
+        - head col 2
+        - head col 3
+        - head col 4
+
+      * - column 1
+        - field 1.1
+        - field 1.2 with autospan
+
+      * - column 2
+        - field 2.1
+        - :rspan:`1` :cspan:`1` field 2.2 - 3.3
+
+      * .. _`last row`:
+
+        - column 3
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dontdiff linux-libre-4.10-rc8-gnu/Documentation/dontdiff
--- linux-libre-4.9-gnu/Documentation/dontdiff	2016-12-11 17:40:30.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dontdiff	2017-02-12 17:22:54.000000000 -0500
@@ -139,7 +139,6 @@ hpet_example
 hugepage-mmap
 hugepage-shm
 ihex2fw
-ikconfig.h*
 inat-tables.c
 initramfs_list
 int16.c
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/80211/cfg80211.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/cfg80211.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/80211/cfg80211.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/cfg80211.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,345 @@
+==================
+cfg80211 subsystem
+==================
+
+Device registration
+===================
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: Device registration
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_channel_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_channel
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_rate_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_rate
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_sta_ht_cap
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_supported_band
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_signal_type
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_params_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wireless_dev
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_new
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_register
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_unregister
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_free
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_name
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_dev
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_priv
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: priv_to_wiphy
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: set_wiphy_dev
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wdev_priv
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_iface_limit
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_iface_combination
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_check_combinations
+
+Actions and configuration
+=========================
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: Actions and configuration
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_ops
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: vif_params
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: key_params
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: survey_info_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: survey_info
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_beacon_data
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_ap_settings
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: station_parameters
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: rate_info_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: rate_info
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: station_info
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: monitor_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: mpath_info_flags
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: mpath_info
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: bss_parameters
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_txq_params
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_crypto_settings
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_auth_request
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_assoc_request
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_deauth_request
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_disassoc_request
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_ibss_params
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_connect_params
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_pmksa
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_rx_mlme_mgmt
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_auth_timeout
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_rx_assoc_resp
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_assoc_timeout
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_tx_mlme_mgmt
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_ibss_joined
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_connect_result
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_connect_bss
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_connect_timeout
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_roamed
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_disconnected
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_ready_on_channel
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_remain_on_channel_expired
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_new_sta
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_rx_mgmt
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_mgmt_tx_status
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_cqm_rssi_notify
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_cqm_pktloss_notify
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_michael_mic_failure
+
+Scanning and BSS list handling
+==============================
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: Scanning and BSS list handling
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_ssid
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_scan_request
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_scan_done
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_bss
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_inform_bss
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_inform_bss_frame_data
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_inform_bss_data
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_unlink_bss
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_find_ie
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_bss_get_ie
+
+Utility functions
+=================
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: Utility functions
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_channel_to_frequency
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_frequency_to_channel
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_get_channel
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_get_response_rate
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_hdrlen
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_get_hdrlen_from_skb
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_radiotap_iterator
+
+Data path helpers
+=================
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: Data path helpers
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_data_to_8023
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_data_from_8023
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: ieee80211_amsdu_to_8023s
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_classify8021d
+
+Regulatory enforcement infrastructure
+=====================================
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: Regulatory enforcement infrastructure
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: regulatory_hint
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_apply_custom_regulatory
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: freq_reg_info
+
+RFkill integration
+==================
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: RFkill integration
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_rfkill_set_hw_state
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_rfkill_start_polling
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: wiphy_rfkill_stop_polling
+
+Test mode
+=========
+
+.. kernel-doc:: include/net/cfg80211.h
+   :doc: Test mode
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_testmode_alloc_reply_skb
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_testmode_reply
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_testmode_alloc_event_skb
+
+.. kernel-doc:: include/net/cfg80211.h
+   :functions: cfg80211_testmode_event
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/80211/conf.py linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/conf.py
--- linux-libre-4.9-gnu/Documentation/driver-api/80211/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "Linux 802.11 Driver Developer's Guide"
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', '80211.tex', project,
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/80211/index.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/index.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/80211/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,17 @@
+=====================================
+Linux 802.11 Driver Developer's Guide
+=====================================
+
+.. toctree::
+
+   introduction
+   cfg80211
+   mac80211
+   mac80211-advanced
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/80211/introduction.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/introduction.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/80211/introduction.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/introduction.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,17 @@
+============
+Introduction
+============
+
+Explaining wireless 802.11 networking in the Linux kernel
+
+Copyright 2007-2009 Johannes Berg
+
+These books attempt to give a description of the various subsystems
+that play a role in 802.11 wireless networking in Linux. Since these
+books are for kernel developers they attempts to document the
+structures and functions used in the kernel as well as giving a
+higher-level overview.
+
+The reader is expected to be familiar with the 802.11 standard as
+published by the IEEE in 802.11-2007 (or possibly later versions).
+References to this standard will be given as "802.11-2007 8.1.5".
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/80211/mac80211-advanced.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/mac80211-advanced.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/80211/mac80211-advanced.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/mac80211-advanced.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,295 @@
+=============================
+mac80211 subsystem (advanced)
+=============================
+
+Information contained within this part of the book is of interest only
+for advanced interaction of mac80211 with drivers to exploit more
+hardware capabilities and improve performance.
+
+LED support
+===========
+
+Mac80211 supports various ways of blinking LEDs. Wherever possible,
+device LEDs should be exposed as LED class devices and hooked up to the
+appropriate trigger, which will then be triggered appropriately by
+mac80211.
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_tx_led_name
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_rx_led_name
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_assoc_led_name
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_radio_led_name
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tpt_blink
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tpt_led_trigger_flags
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_create_tpt_led_trigger
+
+Hardware crypto acceleration
+============================
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: Hardware crypto acceleration
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: set_key_cmd
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_key_conf
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_key_flags
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_tkip_p1k
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_tkip_p1k_iv
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_tkip_p2k
+
+Powersave support
+=================
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: Powersave support
+
+Beacon filter support
+=====================
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: Beacon filter support
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_beacon_loss
+
+Multiple queues and QoS support
+===============================
+
+TBD
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_queue_params
+
+Access point mode support
+=========================
+
+TBD
+
+Some parts of the if_conf should be discussed here instead
+
+Insert notes about VLAN interfaces with hw crypto here or in the hw
+crypto chapter.
+
+support for powersaving clients
+-------------------------------
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: AP support for powersaving clients
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_get_buffered_bc
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_beacon_get
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_sta_eosp
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_frame_release_type
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_sta_ps_transition
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_sta_ps_transition_ni
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_sta_set_buffered
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_sta_block_awake
+
+Supporting multiple virtual interfaces
+======================================
+
+TBD
+
+Note: WDS with identical MAC address should almost always be OK
+
+Insert notes about having multiple virtual interfaces with different MAC
+addresses here, note which configurations are supported by mac80211, add
+notes about supporting hw crypto with it.
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_iterate_active_interfaces
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_iterate_active_interfaces_atomic
+
+Station handling
+================
+
+TODO
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_sta
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: sta_notify_cmd
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_find_sta
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_find_sta_by_ifaddr
+
+Hardware scan offload
+=====================
+
+TBD
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_scan_completed
+
+Aggregation
+===========
+
+TX A-MPDU aggregation
+---------------------
+
+.. kernel-doc:: net/mac80211/agg-tx.c
+   :doc: TX A-MPDU aggregation
+
+.. WARNING: DOCPROC directive not supported: !Cnet/mac80211/agg-tx.c
+
+RX A-MPDU aggregation
+---------------------
+
+.. kernel-doc:: net/mac80211/agg-rx.c
+   :doc: RX A-MPDU aggregation
+
+.. WARNING: DOCPROC directive not supported: !Cnet/mac80211/agg-rx.c
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_ampdu_mlme_action
+
+Spatial Multiplexing Powersave (SMPS)
+=====================================
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: Spatial multiplexing power save
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_request_smps
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_smps_mode
+
+TBD
+
+This part of the book describes the rate control algorithm interface and
+how it relates to mac80211 and drivers.
+
+Rate Control API
+================
+
+TBD
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_start_tx_ba_session
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_start_tx_ba_cb_irqsafe
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_stop_tx_ba_session
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_stop_tx_ba_cb_irqsafe
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_rate_control_changed
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_rate_control
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: rate_control_send_low
+
+TBD
+
+This part of the book describes mac80211 internals.
+
+Key handling
+============
+
+Key handling basics
+-------------------
+
+.. kernel-doc:: net/mac80211/key.c
+   :doc: Key handling basics
+
+MORE TBD
+--------
+
+TBD
+
+Receive processing
+==================
+
+TBD
+
+Transmit processing
+===================
+
+TBD
+
+Station info handling
+=====================
+
+Programming information
+-----------------------
+
+.. kernel-doc:: net/mac80211/sta_info.h
+   :functions: sta_info
+
+.. kernel-doc:: net/mac80211/sta_info.h
+   :functions: ieee80211_sta_info_flags
+
+STA information lifetime rules
+------------------------------
+
+.. kernel-doc:: net/mac80211/sta_info.c
+   :doc: STA information lifetime rules
+
+Aggregation
+===========
+
+.. kernel-doc:: net/mac80211/sta_info.h
+   :functions: sta_ampdu_mlme
+
+.. kernel-doc:: net/mac80211/sta_info.h
+   :functions: tid_ampdu_tx
+
+.. kernel-doc:: net/mac80211/sta_info.h
+   :functions: tid_ampdu_rx
+
+Synchronisation
+===============
+
+TBD
+
+Locking, lots of RCU
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/80211/mac80211.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/mac80211.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/80211/mac80211.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/80211/mac80211.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,216 @@
+===========================
+mac80211 subsystem (basics)
+===========================
+
+You should read and understand the information contained within this
+part of the book while implementing a mac80211 driver. In some chapters,
+advanced usage is noted, those may be skipped if this isn't needed.
+
+This part of the book only covers station and monitor mode
+functionality, additional information required to implement the other
+modes is covered in the second part of the book.
+
+Basic hardware handling
+=======================
+
+TBD
+
+This chapter shall contain information on getting a hw struct allocated
+and registered with mac80211.
+
+Since it is required to allocate rates/modes before registering a hw
+struct, this chapter shall also contain information on setting up the
+rate/mode structs.
+
+Additionally, some discussion about the callbacks and the general
+programming model should be in here, including the definition of
+ieee80211_ops which will be referred to a lot.
+
+Finally, a discussion of hardware capabilities should be done with
+references to other parts of the book.
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_hw
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_hw_flags
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: SET_IEEE80211_DEV
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: SET_IEEE80211_PERM_ADDR
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_ops
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_alloc_hw
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_register_hw
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_unregister_hw
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_free_hw
+
+PHY configuration
+=================
+
+TBD
+
+This chapter should describe PHY handling including start/stop callbacks
+and the various structures used.
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_conf
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_conf_flags
+
+Virtual interfaces
+==================
+
+TBD
+
+This chapter should describe virtual interface basics that are relevant
+to the driver (VLANs, MGMT etc are not.) It should explain the use of
+the add_iface/remove_iface callbacks as well as the interface
+configuration callbacks.
+
+Things related to AP mode should be discussed there.
+
+Things related to supporting multiple interfaces should be in the
+appropriate chapter, a BIG FAT note should be here about this though and
+the recommendation to allow only a single interface in STA mode at
+first!
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_vif
+
+Receive and transmit processing
+===============================
+
+what should be here
+-------------------
+
+TBD
+
+This should describe the receive and transmit paths in mac80211/the
+drivers as well as transmit status handling.
+
+Frame format
+------------
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: Frame format
+
+Packet alignment
+----------------
+
+.. kernel-doc:: net/mac80211/rx.c
+   :doc: Packet alignment
+
+Calling into mac80211 from interrupts
+-------------------------------------
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: Calling mac80211 from interrupts
+
+functions/definitions
+---------------------
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_rx_status
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: mac80211_rx_flags
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: mac80211_tx_info_flags
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: mac80211_tx_control_flags
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: mac80211_rate_control_flags
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_rate
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_info
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_info_clear_status
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_rx
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_rx_ni
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_rx_irqsafe
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_status
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_status_ni
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_tx_status_irqsafe
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_rts_get
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_rts_duration
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_ctstoself_get
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_ctstoself_duration
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_generic_frame_duration
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_wake_queue
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_stop_queue
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_wake_queues
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_stop_queues
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_queue_stopped
+
+Frame filtering
+===============
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: Frame filtering
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_filter_flags
+
+The mac80211 workqueue
+======================
+
+.. kernel-doc:: include/net/mac80211.h
+   :doc: mac80211 workqueue
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_queue_work
+
+.. kernel-doc:: include/net/mac80211.h
+   :functions: ieee80211_queue_delayed_work
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/conf.py linux-libre-4.10-rc8-gnu/Documentation/driver-api/conf.py
--- linux-libre-4.9-gnu/Documentation/driver-api/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = "The Linux driver implementer's API guide"
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'driver-api.tex', project,
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/device_link.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/device_link.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/device_link.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/device_link.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,279 @@
+============
+Device links
+============
+
+By default, the driver core only enforces dependencies between devices
+that are borne out of a parent/child relationship within the device
+hierarchy: When suspending, resuming or shutting down the system, devices
+are ordered based on this relationship, i.e. children are always suspended
+before their parent, and the parent is always resumed before its children.
+
+Sometimes there is a need to represent device dependencies beyond the
+mere parent/child relationship, e.g. between siblings, and have the
+driver core automatically take care of them.
+
+Secondly, the driver core by default does not enforce any driver presence
+dependencies, i.e. that one device must be bound to a driver before
+another one can probe or function correctly.
+
+Often these two dependency types come together, so a device depends on
+another one both with regards to driver presence *and* with regards to
+suspend/resume and shutdown ordering.
+
+Device links allow representation of such dependencies in the driver core.
+
+In its standard form, a device link combines *both* dependency types:
+It guarantees correct suspend/resume and shutdown ordering between a
+"supplier" device and its "consumer" devices, and it guarantees driver
+presence on the supplier.  The consumer devices are not probed before the
+supplier is bound to a driver, and they're unbound before the supplier
+is unbound.
+
+When driver presence on the supplier is irrelevant and only correct
+suspend/resume and shutdown ordering is needed, the device link may
+simply be set up with the ``DL_FLAG_STATELESS`` flag.  In other words,
+enforcing driver presence on the supplier is optional.
+
+Another optional feature is runtime PM integration:  By setting the
+``DL_FLAG_PM_RUNTIME`` flag on addition of the device link, the PM core
+is instructed to runtime resume the supplier and keep it active
+whenever and for as long as the consumer is runtime resumed.
+
+Usage
+=====
+
+The earliest point in time when device links can be added is after
+:c:func:`device_add()` has been called for the supplier and
+:c:func:`device_initialize()` has been called for the consumer.
+
+It is legal to add them later, but care must be taken that the system
+remains in a consistent state:  E.g. a device link cannot be added in
+the midst of a suspend/resume transition, so either commencement of
+such a transition needs to be prevented with :c:func:`lock_system_sleep()`,
+or the device link needs to be added from a function which is guaranteed
+not to run in parallel to a suspend/resume transition, such as from a
+device ``->probe`` callback or a boot-time PCI quirk.
+
+Another example for an inconsistent state would be a device link that
+represents a driver presence dependency, yet is added from the consumer's
+``->probe`` callback while the supplier hasn't probed yet:  Had the driver
+core known about the device link earlier, it wouldn't have probed the
+consumer in the first place.  The onus is thus on the consumer to check
+presence of the supplier after adding the link, and defer probing on
+non-presence.
+
+If a device link is added in the ``->probe`` callback of the supplier or
+consumer driver, it is typically deleted in its ``->remove`` callback for
+symmetry.  That way, if the driver is compiled as a module, the device
+link is added on module load and orderly deleted on unload.  The same
+restrictions that apply to device link addition (e.g. exclusion of a
+parallel suspend/resume transition) apply equally to deletion.
+
+Several flags may be specified on device link addition, two of which
+have already been mentioned above:  ``DL_FLAG_STATELESS`` to express that no
+driver presence dependency is needed (but only correct suspend/resume and
+shutdown ordering) and ``DL_FLAG_PM_RUNTIME`` to express that runtime PM
+integration is desired.
+
+Two other flags are specifically targeted at use cases where the device
+link is added from the consumer's ``->probe`` callback:  ``DL_FLAG_RPM_ACTIVE``
+can be specified to runtime resume the supplier upon addition of the
+device link.  ``DL_FLAG_AUTOREMOVE`` causes the device link to be automatically
+purged when the consumer fails to probe or later unbinds.  This obviates
+the need to explicitly delete the link in the ``->remove`` callback or in
+the error path of the ``->probe`` callback.
+
+Limitations
+===========
+
+Driver authors should be aware that a driver presence dependency (i.e. when
+``DL_FLAG_STATELESS`` is not specified on link addition) may cause probing of
+the consumer to be deferred indefinitely.  This can become a problem if the
+consumer is required to probe before a certain initcall level is reached.
+Worse, if the supplier driver is blacklisted or missing, the consumer will
+never be probed.
+
+Sometimes drivers depend on optional resources.  They are able to operate
+in a degraded mode (reduced feature set or performance) when those resources
+are not present.  An example is an SPI controller that can use a DMA engine
+or work in PIO mode.  The controller can determine presence of the optional
+resources at probe time but on non-presence there is no way to know whether
+they will become available in the near future (due to a supplier driver
+probing) or never.  Consequently it cannot be determined whether to defer
+probing or not.  It would be possible to notify drivers when optional
+resources become available after probing, but it would come at a high cost
+for drivers as switching between modes of operation at runtime based on the
+availability of such resources would be much more complex than a mechanism
+based on probe deferral.  In any case optional resources are beyond the
+scope of device links.
+
+Examples
+========
+
+* An MMU device exists alongside a busmaster device, both are in the same
+  power domain.  The MMU implements DMA address translation for the busmaster
+  device and shall be runtime resumed and kept active whenever and as long
+  as the busmaster device is active.  The busmaster device's driver shall
+  not bind before the MMU is bound.  To achieve this, a device link with
+  runtime PM integration is added from the busmaster device (consumer)
+  to the MMU device (supplier).  The effect with regards to runtime PM
+  is the same as if the MMU was the parent of the master device.
+
+  The fact that both devices share the same power domain would normally
+  suggest usage of a :c:type:`struct dev_pm_domain` or :c:type:`struct
+  generic_pm_domain`, however these are not independent devices that
+  happen to share a power switch, but rather the MMU device serves the
+  busmaster device and is useless without it.  A device link creates a
+  synthetic hierarchical relationship between the devices and is thus
+  more apt.
+
+* A Thunderbolt host controller comprises a number of PCIe hotplug ports
+  and an NHI device to manage the PCIe switch.  On resume from system sleep,
+  the NHI device needs to re-establish PCI tunnels to attached devices
+  before the hotplug ports can resume.  If the hotplug ports were children
+  of the NHI, this resume order would automatically be enforced by the
+  PM core, but unfortunately they're aunts.  The solution is to add
+  device links from the hotplug ports (consumers) to the NHI device
+  (supplier).  A driver presence dependency is not necessary for this
+  use case.
+
+* Discrete GPUs in hybrid graphics laptops often feature an HDA controller
+  for HDMI/DP audio.  In the device hierarchy the HDA controller is a sibling
+  of the VGA device, yet both share the same power domain and the HDA
+  controller is only ever needed when an HDMI/DP display is attached to the
+  VGA device.  A device link from the HDA controller (consumer) to the
+  VGA device (supplier) aptly represents this relationship.
+
+* ACPI allows definition of a device start order by way of _DEP objects.
+  A classical example is when ACPI power management methods on one device
+  are implemented in terms of I\ :sup:`2`\ C accesses and require a specific
+  I\ :sup:`2`\ C controller to be present and functional for the power
+  management of the device in question to work.
+
+* In some SoCs a functional dependency exists from display, video codec and
+  video processing IP cores on transparent memory access IP cores that handle
+  burst access and compression/decompression.
+
+Alternatives
+============
+
+* A :c:type:`struct dev_pm_domain` can be used to override the bus,
+  class or device type callbacks.  It is intended for devices sharing
+  a single on/off switch, however it does not guarantee a specific
+  suspend/resume ordering, this needs to be implemented separately.
+  It also does not by itself track the runtime PM status of the involved
+  devices and turn off the power switch only when all of them are runtime
+  suspended.  Furthermore it cannot be used to enforce a specific shutdown
+  ordering or a driver presence dependency.
+
+* A :c:type:`struct generic_pm_domain` is a lot more heavyweight than a
+  device link and does not allow for shutdown ordering or driver presence
+  dependencies.  It also cannot be used on ACPI systems.
+
+Implementation
+==============
+
+The device hierarchy, which -- as the name implies -- is a tree,
+becomes a directed acyclic graph once device links are added.
+
+Ordering of these devices during suspend/resume is determined by the
+dpm_list.  During shutdown it is determined by the devices_kset.  With
+no device links present, the two lists are a flattened, one-dimensional
+representations of the device tree such that a device is placed behind
+all its ancestors.  That is achieved by traversing the ACPI namespace
+or OpenFirmware device tree top-down and appending devices to the lists
+as they are discovered.
+
+Once device links are added, the lists need to satisfy the additional
+constraint that a device is placed behind all its suppliers, recursively.
+To ensure this, upon addition of the device link the consumer and the
+entire sub-graph below it (all children and consumers of the consumer)
+are moved to the end of the list.  (Call to :c:func:`device_reorder_to_tail()`
+from :c:func:`device_link_add()`.)
+
+To prevent introduction of dependency loops into the graph, it is
+verified upon device link addition that the supplier is not dependent
+on the consumer or any children or consumers of the consumer.
+(Call to :c:func:`device_is_dependent()` from :c:func:`device_link_add()`.)
+If that constraint is violated, :c:func:`device_link_add()` will return
+``NULL`` and a ``WARNING`` will be logged.
+
+Notably this also prevents the addition of a device link from a parent
+device to a child.  However the converse is allowed, i.e. a device link
+from a child to a parent.  Since the driver core already guarantees
+correct suspend/resume and shutdown ordering between parent and child,
+such a device link only makes sense if a driver presence dependency is
+needed on top of that.  In this case driver authors should weigh
+carefully if a device link is at all the right tool for the purpose.
+A more suitable approach might be to simply use deferred probing or
+add a device flag causing the parent driver to be probed before the
+child one.
+
+State machine
+=============
+
+.. kernel-doc:: include/linux/device.h
+   :functions: device_link_state
+
+::
+
+                 .=============================.
+                 |                             |
+                 v                             |
+ DORMANT <=> AVAILABLE <=> CONSUMER_PROBE => ACTIVE
+    ^                                          |
+    |                                          |
+    '============ SUPPLIER_UNBIND <============'
+
+* The initial state of a device link is automatically determined by
+  :c:func:`device_link_add()` based on the driver presence on the supplier
+  and consumer.  If the link is created before any devices are probed, it
+  is set to ``DL_STATE_DORMANT``.
+
+* When a supplier device is bound to a driver, links to its consumers
+  progress to ``DL_STATE_AVAILABLE``.
+  (Call to :c:func:`device_links_driver_bound()` from
+  :c:func:`driver_bound()`.)
+
+* Before a consumer device is probed, presence of supplier drivers is
+  verified by checking that links to suppliers are in ``DL_STATE_AVAILABLE``
+  state.  The state of the links is updated to ``DL_STATE_CONSUMER_PROBE``.
+  (Call to :c:func:`device_links_check_suppliers()` from
+  :c:func:`really_probe()`.)
+  This prevents the supplier from unbinding.
+  (Call to :c:func:`wait_for_device_probe()` from
+  :c:func:`device_links_unbind_consumers()`.)
+
+* If the probe fails, links to suppliers revert back to ``DL_STATE_AVAILABLE``.
+  (Call to :c:func:`device_links_no_driver()` from :c:func:`really_probe()`.)
+
+* If the probe succeeds, links to suppliers progress to ``DL_STATE_ACTIVE``.
+  (Call to :c:func:`device_links_driver_bound()` from :c:func:`driver_bound()`.)
+
+* When the consumer's driver is later on removed, links to suppliers revert
+  back to ``DL_STATE_AVAILABLE``.
+  (Call to :c:func:`__device_links_no_driver()` from
+  :c:func:`device_links_driver_cleanup()`, which in turn is called from
+  :c:func:`__device_release_driver()`.)
+
+* Before a supplier's driver is removed, links to consumers that are not
+  bound to a driver are updated to ``DL_STATE_SUPPLIER_UNBIND``.
+  (Call to :c:func:`device_links_busy()` from
+  :c:func:`__device_release_driver()`.)
+  This prevents the consumers from binding.
+  (Call to :c:func:`device_links_check_suppliers()` from
+  :c:func:`really_probe()`.)
+  Consumers that are bound are freed from their driver; consumers that are
+  probing are waited for until they are done.
+  (Call to :c:func:`device_links_unbind_consumers()` from
+  :c:func:`__device_release_driver()`.)
+  Once all links to consumers are in ``DL_STATE_SUPPLIER_UNBIND`` state,
+  the supplier driver is released and the links revert to ``DL_STATE_DORMANT``.
+  (Call to :c:func:`device_links_driver_cleanup()` from
+  :c:func:`__device_release_driver()`.)
+
+API
+===
+
+.. kernel-doc:: drivers/base/core.c
+   :functions: device_link_add device_link_del
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/dma-buf.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/dma-buf.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/dma-buf.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/dma-buf.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,73 @@
+Buffer Sharing and Synchronization
+==================================
+
+The dma-buf subsystem provides the framework for sharing buffers for
+hardware (DMA) access across multiple device drivers and subsystems, and
+for synchronizing asynchronous hardware access.
+
+This is used, for example, by drm "prime" multi-GPU support, but is of
+course not limited to GPU use cases.
+
+The three main components of this are: (1) dma-buf, representing a
+sg_table and exposed to userspace as a file descriptor to allow passing
+between devices, (2) fence, which provides a mechanism to signal when
+one device as finished access, and (3) reservation, which manages the
+shared or exclusive fence(s) associated with the buffer.
+
+Shared DMA Buffers
+------------------
+
+.. kernel-doc:: drivers/dma-buf/dma-buf.c
+   :export:
+
+.. kernel-doc:: include/linux/dma-buf.h
+   :internal:
+
+Reservation Objects
+-------------------
+
+.. kernel-doc:: drivers/dma-buf/reservation.c
+   :doc: Reservation Object Overview
+
+.. kernel-doc:: drivers/dma-buf/reservation.c
+   :export:
+
+.. kernel-doc:: include/linux/reservation.h
+   :internal:
+
+DMA Fences
+----------
+
+.. kernel-doc:: drivers/dma-buf/dma-fence.c
+   :export:
+
+.. kernel-doc:: include/linux/dma-fence.h
+   :internal:
+
+Seqno Hardware Fences
+~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/seqno-fence.c
+   :export:
+
+.. kernel-doc:: include/linux/seqno-fence.h
+   :internal:
+
+DMA Fence Array
+~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/dma-fence-array.c
+   :export:
+
+.. kernel-doc:: include/linux/dma-fence-array.h
+   :internal:
+
+DMA Fence uABI/Sync File
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/sync_file.c
+   :export:
+
+.. kernel-doc:: include/linux/sync_file.h
+   :internal:
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/edac.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/edac.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/edac.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/edac.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,178 @@
+Error Detection And Correction (EDAC) Devices
+=============================================
+
+Main Concepts used at the EDAC subsystem
+----------------------------------------
+
+There are several things to be aware of that aren't at all obvious, like
+*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 DRAM chips on a memory stick.  These devices commonly
+output 4 and 8 bits each (x4, x8). Grouping several of these in parallel
+provides the number of bits that the memory controller expects:
+typically 72 bits, in order to provide 64 bits + 8 bits of ECC data.
+
+* Memory Stick
+
+A printed circuit board that aggregates multiple memory devices in
+parallel.  In general, this is the Field Replaceable Unit (FRU) which
+gets replaced, in the case of excessive errors. Most often it is also
+called DIMM (Dual Inline Memory Module).
+
+* Memory Socket
+
+A physical connector on the motherboard that accepts a single memory
+stick. Also called as "slot" on several datasheets.
+
+* Channel
+
+A memory controller channel, responsible to communicate with a group of
+DIMMs. Each channel has its own independent control (command) and data
+bus, and can be used independently or grouped with other channels.
+
+* Branch
+
+It is typically the highest hierarchy on a Fully-Buffered DIMM memory
+controller. Typically, it contains two channels. Two channels at the
+same branch can be used in single mode or in lockstep mode. When
+lockstep is enabled, the cacheline is doubled, but it generally brings
+some performance penalty. Also, it is generally not possible to point to
+just one memory stick when an error occurs, as the error correction code
+is calculated using two DIMMs instead of one. Due to that, it is capable
+of correcting more errors than on single mode.
+
+* Single-channel
+
+The data accessed by the memory controller is contained into one dimm
+only. E. g. if the data is 64 bits-wide, the data flows to the CPU using
+one 64 bits parallel access. Typically used with SDR, DDR, DDR2 and DDR3
+memories. FB-DIMM and RAMBUS use a different concept for channel, so
+this concept doesn't apply there.
+
+* Double-channel
+
+The data size accessed by the memory controller is interlaced into two
+dimms, accessed at the same time. E. g. if the DIMM is 64 bits-wide (72
+bits with ECC), the data flows to the CPU using a 128 bits parallel
+access.
+
+* Chip-select row
+
+This is the name of the DRAM signal used to select the DRAM ranks to be
+accessed. Common chip-select rows for single channel are 64 bits, for
+dual channel 128 bits. It may not be visible by the memory controller,
+as some DIMM types have a memory buffer that can hide direct access to
+it from the Memory Controller.
+
+* 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.
+
+.. _doubleranked:
+
+* 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 :ref:`Double-Ranked stick <doubleranked>`.
+
+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.
+
+
+Memory Controllers
+------------------
+
+Most of the EDAC core is focused on doing Memory Controller error detection.
+The :c:func:`edac_mc_alloc`. It uses internally the struct ``mem_ctl_info``
+to describe the memory controllers, with is an opaque struct for the EDAC
+drivers. Only the EDAC core is allowed to touch it.
+
+.. kernel-doc:: include/linux/edac.h
+
+.. kernel-doc:: drivers/edac/edac_mc.h
+
+PCI Controllers
+---------------
+
+The EDAC subsystem provides a mechanism to handle PCI controllers by calling
+the :c:func:`edac_pci_alloc_ctl_info`. It will use the struct
+:c:type:`edac_pci_ctl_info` to describe the PCI controllers.
+
+.. kernel-doc:: drivers/edac/edac_pci.h
+
+EDAC Blocks
+-----------
+
+The EDAC subsystem also provides a generic mechanism to report errors on
+other parts of the hardware via :c:func:`edac_device_alloc_ctl_info` function.
+
+The structures :c:type:`edac_dev_sysfs_block_attribute`,
+:c:type:`edac_device_block`, :c:type:`edac_device_instance` and
+:c:type:`edac_device_ctl_info` provide a generic or abstract 'edac_device'
+representation at sysfs.
+
+This set of structures and the code that implements the APIs for the same, provide for registering EDAC type devices which are NOT standard memory or
+PCI, like:
+
+- CPU caches (L1 and L2)
+- DMA engines
+- Core CPU switches
+- Fabric switch units
+- PCIe interface controllers
+- other EDAC/ECC type devices that can be monitored for
+  errors, etc.
+
+It allows for a 2 level set of hierarchy.
+
+For example, a cache could be composed of L1, L2 and L3 levels of cache.
+Each CPU core would have its own L1 cache, while sharing L2 and maybe L3
+caches. On such case, those can be represented via the following sysfs
+nodes::
+
+	/sys/devices/system/edac/..
+
+	pci/		<existing pci directory (if available)>
+	mc/		<existing memory device directory>
+	cpu/cpu0/..	<L1 and L2 block directory>
+		/L1-cache/ce_count
+			 /ue_count
+		/L2-cache/ce_count
+			 /ue_count
+	cpu/cpu1/..	<L1 and L2 block directory>
+		/L1-cache/ce_count
+			 /ue_count
+		/L2-cache/ce_count
+			 /ue_count
+	...
+
+	the L1 and L2 directories would be "edac_device_block's"
+
+.. kernel-doc:: drivers/edac/edac_device.h
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/index.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/index.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/index.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -16,11 +16,24 @@ available subsections can be seen below.
 
    basics
    infrastructure
+   dma-buf
+   device_link
    message-based
    sound
    frame-buffer
    input
+   usb
    spi
    i2c
    hsi
+   edac
    miscellaneous
+   vme
+   80211/index
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/infrastructure.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/infrastructure.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/infrastructure.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/infrastructure.rst	2017-02-12 16:03:20.000000000 -0500
@@ -46,76 +46,6 @@ Device Drivers Base
 .. kernel-doc:: drivers/base/bus.c
    :export:
 
-Buffer Sharing and Synchronization
-----------------------------------
-
-The dma-buf subsystem provides the framework for sharing buffers for
-hardware (DMA) access across multiple device drivers and subsystems, and
-for synchronizing asynchronous hardware access.
-
-This is used, for example, by drm "prime" multi-GPU support, but is of
-course not limited to GPU use cases.
-
-The three main components of this are: (1) dma-buf, representing a
-sg_table and exposed to userspace as a file descriptor to allow passing
-between devices, (2) fence, which provides a mechanism to signal when
-one device as finished access, and (3) reservation, which manages the
-shared or exclusive fence(s) associated with the buffer.
-
-dma-buf
-~~~~~~~
-
-.. kernel-doc:: drivers/dma-buf/dma-buf.c
-   :export:
-
-.. kernel-doc:: include/linux/dma-buf.h
-   :internal:
-
-reservation
-~~~~~~~~~~~
-
-.. kernel-doc:: drivers/dma-buf/reservation.c
-   :doc: Reservation Object Overview
-
-.. kernel-doc:: drivers/dma-buf/reservation.c
-   :export:
-
-.. kernel-doc:: include/linux/reservation.h
-   :internal:
-
-fence
-~~~~~
-
-.. kernel-doc:: drivers/dma-buf/fence.c
-   :export:
-
-.. kernel-doc:: include/linux/fence.h
-   :internal:
-
-.. kernel-doc:: drivers/dma-buf/seqno-fence.c
-   :export:
-
-.. kernel-doc:: include/linux/seqno-fence.h
-   :internal:
-
-.. kernel-doc:: drivers/dma-buf/fence-array.c
-   :export:
-
-.. kernel-doc:: include/linux/fence-array.h
-   :internal:
-
-.. kernel-doc:: drivers/dma-buf/reservation.c
-   :export:
-
-.. kernel-doc:: include/linux/reservation.h
-   :internal:
-
-.. kernel-doc:: drivers/dma-buf/sync_file.c
-   :export:
-
-.. kernel-doc:: include/linux/sync_file.h
-   :internal:
-
 Device Drivers DMA Management
 -----------------------------
 
@@ -125,21 +55,6 @@ Device Drivers DMA Management
 .. kernel-doc:: drivers/base/dma-mapping.c
    :export:
 
-Device Drivers Power Management
--------------------------------
-
-.. kernel-doc:: drivers/base/power/main.c
-   :export:
-
-Device Drivers ACPI Support
----------------------------
-
-.. kernel-doc:: drivers/acpi/scan.c
-   :export:
-
-.. kernel-doc:: drivers/acpi/scan.c
-   :internal:
-
 Device drivers PnP support
 --------------------------
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/usb.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/usb.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/usb.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/usb.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,748 @@
+===========================
+The Linux-USB Host Side API
+===========================
+
+Introduction to USB on Linux
+============================
+
+A Universal Serial Bus (USB) is used to connect a host, such as a PC or
+workstation, to a number of peripheral devices. USB uses a tree
+structure, with the host as the root (the system's master), hubs as
+interior nodes, and peripherals as leaves (and slaves). Modern PCs
+support several such trees of USB devices, usually
+a few USB 3.0 (5 GBit/s) or USB 3.1 (10 GBit/s) and some legacy
+USB 2.0 (480 MBit/s) busses just in case.
+
+That master/slave asymmetry was designed-in for a number of reasons, one
+being ease of use. It is not physically possible to mistake upstream and
+downstream or it does not matter with a type C plug (or they are built into the
+peripheral). Also, the host software doesn't need to deal with
+distributed auto-configuration since the pre-designated master node
+manages all that.
+
+Kernel developers added USB support to Linux early in the 2.2 kernel
+series and have been developing it further since then. Besides support
+for each new generation of USB, various host controllers gained support,
+new drivers for peripherals have been added and advanced features for latency
+measurement and improved power management introduced.
+
+Linux can run inside USB devices as well as on the hosts that control
+the devices. But USB device drivers running inside those peripherals
+don't do the same things as the ones running inside hosts, so they've
+been given a different name: *gadget drivers*. This document does not
+cover gadget drivers.
+
+USB Host-Side API Model
+=======================
+
+Host-side drivers for USB devices talk to the "usbcore" APIs. There are
+two. One is intended for *general-purpose* drivers (exposed through
+driver frameworks), and the other is for drivers that are *part of the
+core*. Such core drivers include the *hub* driver (which manages trees
+of USB devices) and several different kinds of *host controller
+drivers*, which control individual busses.
+
+The device model seen by USB drivers is relatively complex.
+
+-  USB supports four kinds of data transfers (control, bulk, interrupt,
+   and isochronous). Two of them (control and bulk) use bandwidth as
+   it's available, while the other two (interrupt and isochronous) are
+   scheduled to provide guaranteed bandwidth.
+
+-  The device description model includes one or more "configurations"
+   per device, only one of which is active at a time. Devices are supposed
+   to be capable of operating at lower than their top
+   speeds and may provide a BOS descriptor showing the lowest speed they
+   remain fully operational at.
+
+-  From USB 3.0 on configurations have one or more "functions", which
+   provide a common functionality and are grouped together for purposes
+   of power management.
+
+-  Configurations or functions have one or more "interfaces", each of which may have
+   "alternate settings". Interfaces may be standardized by USB "Class"
+   specifications, or may be specific to a vendor or device.
+
+   USB device drivers actually bind to interfaces, not devices. Think of
+   them as "interface drivers", though you may not see many devices
+   where the distinction is important. *Most USB devices are simple,
+   with only one function, one configuration, one interface, and one alternate
+   setting.*
+
+-  Interfaces have one or more "endpoints", each of which supports one
+   type and direction of data transfer such as "bulk out" or "interrupt
+   in". The entire configuration may have up to sixteen endpoints in
+   each direction, allocated as needed among all the interfaces.
+
+-  Data transfer on USB is packetized; each endpoint has a maximum
+   packet size. Drivers must often be aware of conventions such as
+   flagging the end of bulk transfers using "short" (including zero
+   length) packets.
+
+-  The Linux USB API supports synchronous calls for control and bulk
+   messages. It also supports asynchronous calls for all kinds of data
+   transfer, using request structures called "URBs" (USB Request
+   Blocks).
+
+Accordingly, the USB Core API exposed to device drivers covers quite a
+lot of territory. You'll probably need to consult the USB 3.0
+specification, available online from www.usb.org at no cost, as well as
+class or device specifications.
+
+The only host-side drivers that actually touch hardware (reading/writing
+registers, handling IRQs, and so on) are the HCDs. In theory, all HCDs
+provide the same functionality through the same API. In practice, that's
+becoming more true, but there are still differences
+that crop up especially with fault handling on the less common controllers.
+Different controllers don't
+necessarily report the same aspects of failures, and recovery from
+faults (including software-induced ones like unlinking an URB) isn't yet
+fully consistent. Device driver authors should make a point of doing
+disconnect testing (while the device is active) with each different host
+controller driver, to make sure drivers don't have bugs of their own as
+well as to make sure they aren't relying on some HCD-specific behavior.
+
+USB-Standard Types
+==================
+
+In ``<linux/usb/ch9.h>`` you will find the USB data types defined in
+chapter 9 of the USB specification. These data types are used throughout
+USB, and in APIs including this host side API, gadget APIs, and usbfs.
+
+.. kernel-doc:: include/linux/usb/ch9.h
+   :internal:
+
+Host-Side Data Types and Macros
+===============================
+
+The host side API exposes several layers to drivers, some of which are
+more necessary than others. These support lifecycle models for host side
+drivers and devices, and support passing buffers through usbcore to some
+HCD that performs the I/O for the device driver.
+
+.. kernel-doc:: include/linux/usb.h
+   :internal:
+
+USB Core APIs
+=============
+
+There are two basic I/O models in the USB API. The most elemental one is
+asynchronous: drivers submit requests in the form of an URB, and the
+URB's completion callback handles the next step. All USB transfer types
+support that model, although there are special cases for control URBs
+(which always have setup and status stages, but may not have a data
+stage) and isochronous URBs (which allow large packets and include
+per-packet fault reports). Built on top of that is synchronous API
+support, where a driver calls a routine that allocates one or more URBs,
+submits them, and waits until they complete. There are synchronous
+wrappers for single-buffer control and bulk transfers (which are awkward
+to use in some driver disconnect scenarios), and for scatterlist based
+streaming i/o (bulk or interrupt).
+
+USB drivers need to provide buffers that can be used for DMA, although
+they don't necessarily need to provide the DMA mapping themselves. There
+are APIs to use used when allocating DMA buffers, which can prevent use
+of bounce buffers on some systems. In some cases, drivers may be able to
+rely on 64bit DMA to eliminate another kind of bounce buffer.
+
+.. kernel-doc:: drivers/usb/core/urb.c
+   :export:
+
+.. kernel-doc:: drivers/usb/core/message.c
+   :export:
+
+.. kernel-doc:: drivers/usb/core/file.c
+   :export:
+
+.. kernel-doc:: drivers/usb/core/driver.c
+   :export:
+
+.. kernel-doc:: drivers/usb/core/usb.c
+   :export:
+
+.. kernel-doc:: drivers/usb/core/hub.c
+   :export:
+
+Host Controller APIs
+====================
+
+These APIs are only for use by host controller drivers, most of which
+implement standard register interfaces such as XHCI, EHCI, OHCI, or UHCI. UHCI
+was one of the first interfaces, designed by Intel and also used by VIA;
+it doesn't do much in hardware. OHCI was designed later, to have the
+hardware do more work (bigger transfers, tracking protocol state, and so
+on). EHCI was designed with USB 2.0; its design has features that
+resemble OHCI (hardware does much more work) as well as UHCI (some parts
+of ISO support, TD list processing). XHCI was designed with USB 3.0. It
+continues to shift support for functionality into hardware.
+
+There are host controllers other than the "big three", although most PCI
+based controllers (and a few non-PCI based ones) use one of those
+interfaces. Not all host controllers use DMA; some use PIO, and there is
+also a simulator and a virtual host controller to pipe USB over the network.
+
+The same basic APIs are available to drivers for all those controllers.
+For historical reasons they are in two layers: :c:type:`struct
+usb_bus <usb_bus>` is a rather thin layer that became available
+in the 2.2 kernels, while :c:type:`struct usb_hcd <usb_hcd>`
+is a more featureful layer
+that lets HCDs share common code, to shrink driver size and
+significantly reduce hcd-specific behaviors.
+
+.. kernel-doc:: drivers/usb/core/hcd.c
+   :export:
+
+.. kernel-doc:: drivers/usb/core/hcd-pci.c
+   :export:
+
+.. kernel-doc:: drivers/usb/core/buffer.c
+   :internal:
+
+The USB Filesystem (usbfs)
+==========================
+
+This chapter presents the Linux *usbfs*. You may prefer to avoid writing
+new kernel code for your USB driver; that's the problem that usbfs set
+out to solve. User mode device drivers are usually packaged as
+applications or libraries, and may use usbfs through some programming
+library that wraps it. Such libraries include
+`libusb <http://libusb.sourceforge.net>`__ for C/C++, and
+`jUSB <http://jUSB.sourceforge.net>`__ for Java.
+
+    **Note**
+
+    This particular documentation is incomplete, especially with respect
+    to the asynchronous mode. As of kernel 2.5.66 the code and this
+    (new) documentation need to be cross-reviewed.
+
+Configure usbfs into Linux kernels by enabling the *USB filesystem*
+option (CONFIG_USB_DEVICEFS), and you get basic support for user mode
+USB device drivers. Until relatively recently it was often (confusingly)
+called *usbdevfs* although it wasn't solving what *devfs* was. Every USB
+device will appear in usbfs, regardless of whether or not it has a
+kernel driver.
+
+What files are in "usbfs"?
+--------------------------
+
+Conventionally mounted at ``/proc/bus/usb``, usbfs features include:
+
+-  ``/proc/bus/usb/devices`` ... a text file showing each of the USB
+   devices on known to the kernel, and their configuration descriptors.
+   You can also poll() this to learn about new devices.
+
+-  ``/proc/bus/usb/BBB/DDD`` ... magic files exposing the each device's
+   configuration descriptors, and supporting a series of ioctls for
+   making device requests, including I/O to devices. (Purely for access
+   by programs.)
+
+Each bus is given a number (BBB) based on when it was enumerated; within
+each bus, each device is given a similar number (DDD). Those BBB/DDD
+paths are not "stable" identifiers; expect them to change even if you
+always leave the devices plugged in to the same hub port. *Don't even
+think of saving these in application configuration files.* Stable
+identifiers are available, for user mode applications that want to use
+them. HID and networking devices expose these stable IDs, so that for
+example you can be sure that you told the right UPS to power down its
+second server. "usbfs" doesn't (yet) expose those IDs.
+
+Mounting and Access Control
+---------------------------
+
+There are a number of mount options for usbfs, which will be of most
+interest to you if you need to override the default access control
+policy. That policy is that only root may read or write device files
+(``/proc/bus/BBB/DDD``) although anyone may read the ``devices`` or
+``drivers`` files. I/O requests to the device also need the
+CAP_SYS_RAWIO capability,
+
+The significance of that is that by default, all user mode device
+drivers need super-user privileges. You can change modes or ownership in
+a driver setup when the device hotplugs, or maye just start the driver
+right then, as a privileged server (or some activity within one). That's
+the most secure approach for multi-user systems, but for single user
+systems ("trusted" by that user) it's more convenient just to grant
+everyone all access (using the *devmode=0666* option) so the driver can
+start whenever it's needed.
+
+The mount options for usbfs, usable in /etc/fstab or in command line
+invocations of *mount*, are:
+
+*busgid*\ =NNNNN
+    Controls the GID used for the /proc/bus/usb/BBB directories.
+    (Default: 0)
+
+*busmode*\ =MMM
+    Controls the file mode used for the /proc/bus/usb/BBB directories.
+    (Default: 0555)
+
+*busuid*\ =NNNNN
+    Controls the UID used for the /proc/bus/usb/BBB directories.
+    (Default: 0)
+
+*devgid*\ =NNNNN
+    Controls the GID used for the /proc/bus/usb/BBB/DDD files. (Default:
+    0)
+
+*devmode*\ =MMM
+    Controls the file mode used for the /proc/bus/usb/BBB/DDD files.
+    (Default: 0644)
+
+*devuid*\ =NNNNN
+    Controls the UID used for the /proc/bus/usb/BBB/DDD files. (Default:
+    0)
+
+*listgid*\ =NNNNN
+    Controls the GID used for the /proc/bus/usb/devices and drivers
+    files. (Default: 0)
+
+*listmode*\ =MMM
+    Controls the file mode used for the /proc/bus/usb/devices and
+    drivers files. (Default: 0444)
+
+*listuid*\ =NNNNN
+    Controls the UID used for the /proc/bus/usb/devices and drivers
+    files. (Default: 0)
+
+Note that many Linux distributions hard-wire the mount options for usbfs
+in their init scripts, such as ``/etc/rc.d/rc.sysinit``, rather than
+making it easy to set this per-system policy in ``/etc/fstab``.
+
+/proc/bus/usb/devices
+---------------------
+
+This file is handy for status viewing tools in user mode, which can scan
+the text format and ignore most of it. More detailed device status
+(including class and vendor status) is available from device-specific
+files. For information about the current format of this file, see the
+``Documentation/usb/proc_usb_info.txt`` file in your Linux kernel
+sources.
+
+This file, in combination with the poll() system call, can also be used
+to detect when devices are added or removed:
+
+::
+
+    int fd;
+    struct pollfd pfd;
+
+    fd = open("/proc/bus/usb/devices", O_RDONLY);
+    pfd = { fd, POLLIN, 0 };
+    for (;;) {
+        /* The first time through, this call will return immediately. */
+        poll(&pfd, 1, -1);
+
+        /* To see what's changed, compare the file's previous and current
+           contents or scan the filesystem.  (Scanning is more precise.) */
+    }
+
+Note that this behavior is intended to be used for informational and
+debug purposes. It would be more appropriate to use programs such as
+udev or HAL to initialize a device or start a user-mode helper program,
+for instance.
+
+/proc/bus/usb/BBB/DDD
+---------------------
+
+Use these files in one of these basic ways:
+
+*They can be read,* producing first the device descriptor (18 bytes) and
+then the descriptors for the current configuration. See the USB 2.0 spec
+for details about those binary data formats. You'll need to convert most
+multibyte values from little endian format to your native host byte
+order, although a few of the fields in the device descriptor (both of
+the BCD-encoded fields, and the vendor and product IDs) will be
+byteswapped for you. Note that configuration descriptors include
+descriptors for interfaces, altsettings, endpoints, and maybe additional
+class descriptors.
+
+*Perform USB operations* using *ioctl()* requests to make endpoint I/O
+requests (synchronously or asynchronously) or manage the device. These
+requests need the CAP_SYS_RAWIO capability, as well as filesystem
+access permissions. Only one ioctl request can be made on one of these
+device files at a time. This means that if you are synchronously reading
+an endpoint from one thread, you won't be able to write to a different
+endpoint from another thread until the read completes. This works for
+*half duplex* protocols, but otherwise you'd use asynchronous i/o
+requests.
+
+Life Cycle of User Mode Drivers
+-------------------------------
+
+Such a driver first needs to find a device file for a device it knows
+how to handle. Maybe it was told about it because a ``/sbin/hotplug``
+event handling agent chose that driver to handle the new device. Or
+maybe it's an application that scans all the /proc/bus/usb device files,
+and ignores most devices. In either case, it should :c:func:`read()`
+all the descriptors from the device file, and check them against what it
+knows how to handle. It might just reject everything except a particular
+vendor and product ID, or need a more complex policy.
+
+Never assume there will only be one such device on the system at a time!
+If your code can't handle more than one device at a time, at least
+detect when there's more than one, and have your users choose which
+device to use.
+
+Once your user mode driver knows what device to use, it interacts with
+it in either of two styles. The simple style is to make only control
+requests; some devices don't need more complex interactions than those.
+(An example might be software using vendor-specific control requests for
+some initialization or configuration tasks, with a kernel driver for the
+rest.)
+
+More likely, you need a more complex style driver: one using non-control
+endpoints, reading or writing data and claiming exclusive use of an
+interface. *Bulk* transfers are easiest to use, but only their sibling
+*interrupt* transfers work with low speed devices. Both interrupt and
+*isochronous* transfers offer service guarantees because their bandwidth
+is reserved. Such "periodic" transfers are awkward to use through usbfs,
+unless you're using the asynchronous calls. However, interrupt transfers
+can also be used in a synchronous "one shot" style.
+
+Your user-mode driver should never need to worry about cleaning up
+request state when the device is disconnected, although it should close
+its open file descriptors as soon as it starts seeing the ENODEV errors.
+
+The ioctl() Requests
+--------------------
+
+To use these ioctls, you need to include the following headers in your
+userspace program:
+
+::
+
+    #include <linux/usb.h>
+    #include <linux/usbdevice_fs.h>
+    #include <asm/byteorder.h>
+
+The standard USB device model requests, from "Chapter 9" of the USB 2.0
+specification, are automatically included from the ``<linux/usb/ch9.h>``
+header.
+
+Unless noted otherwise, the ioctl requests described here will update
+the modification time on the usbfs file to which they are applied
+(unless they fail). A return of zero indicates success; otherwise, a
+standard USB error code is returned. (These are documented in
+``Documentation/usb/error-codes.txt`` in your kernel sources.)
+
+Each of these files multiplexes access to several I/O streams, one per
+endpoint. Each device has one control endpoint (endpoint zero) which
+supports a limited RPC style RPC access. Devices are configured by
+hub_wq (in the kernel) setting a device-wide *configuration* that
+affects things like power consumption and basic functionality. The
+endpoints are part of USB *interfaces*, which may have *altsettings*
+affecting things like which endpoints are available. Many devices only
+have a single configuration and interface, so drivers for them will
+ignore configurations and altsettings.
+
+Management/Status Requests
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A number of usbfs requests don't deal very directly with device I/O.
+They mostly relate to device management and status. These are all
+synchronous requests.
+
+USBDEVFS_CLAIMINTERFACE
+    This is used to force usbfs to claim a specific interface, which has
+    not previously been claimed by usbfs or any other kernel driver. The
+    ioctl parameter is an integer holding the number of the interface
+    (bInterfaceNumber from descriptor).
+
+    Note that if your driver doesn't claim an interface before trying to
+    use one of its endpoints, and no other driver has bound to it, then
+    the interface is automatically claimed by usbfs.
+
+    This claim will be released by a RELEASEINTERFACE ioctl, or by
+    closing the file descriptor. File modification time is not updated
+    by this request.
+
+USBDEVFS_CONNECTINFO
+    Says whether the device is lowspeed. The ioctl parameter points to a
+    structure like this:
+
+    ::
+
+        struct usbdevfs_connectinfo {
+                unsigned int   devnum;
+                unsigned char  slow;
+        };
+
+    File modification time is not updated by this request.
+
+    *You can't tell whether a "not slow" device is connected at high
+    speed (480 MBit/sec) or just full speed (12 MBit/sec).* You should
+    know the devnum value already, it's the DDD value of the device file
+    name.
+
+USBDEVFS_GETDRIVER
+    Returns the name of the kernel driver bound to a given interface (a
+    string). Parameter is a pointer to this structure, which is
+    modified:
+
+    ::
+
+        struct usbdevfs_getdriver {
+                unsigned int  interface;
+                char          driver[USBDEVFS_MAXDRIVERNAME + 1];
+        };
+
+    File modification time is not updated by this request.
+
+USBDEVFS_IOCTL
+    Passes a request from userspace through to a kernel driver that has
+    an ioctl entry in the *struct usb_driver* it registered.
+
+    ::
+
+        struct usbdevfs_ioctl {
+                int     ifno;
+                int     ioctl_code;
+                void    *data;
+        };
+
+        /* user mode call looks like this.
+         * 'request' becomes the driver->ioctl() 'code' parameter.
+         * the size of 'param' is encoded in 'request', and that data
+         * is copied to or from the driver->ioctl() 'buf' parameter.
+         */
+        static int
+        usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
+        {
+                struct usbdevfs_ioctl   wrapper;
+
+                wrapper.ifno = ifno;
+                wrapper.ioctl_code = request;
+                wrapper.data = param;
+
+                return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
+        }
+
+    File modification time is not updated by this request.
+
+    This request lets kernel drivers talk to user mode code through
+    filesystem operations even when they don't create a character or
+    block special device. It's also been used to do things like ask
+    devices what device special file should be used. Two pre-defined
+    ioctls are used to disconnect and reconnect kernel drivers, so that
+    user mode code can completely manage binding and configuration of
+    devices.
+
+USBDEVFS_RELEASEINTERFACE
+    This is used to release the claim usbfs made on interface, either
+    implicitly or because of a USBDEVFS_CLAIMINTERFACE call, before the
+    file descriptor is closed. The ioctl parameter is an integer holding
+    the number of the interface (bInterfaceNumber from descriptor); File
+    modification time is not updated by this request.
+
+        **Warning**
+
+        *No security check is made to ensure that the task which made
+        the claim is the one which is releasing it. This means that user
+        mode driver may interfere other ones.*
+
+USBDEVFS_RESETEP
+    Resets the data toggle value for an endpoint (bulk or interrupt) to
+    DATA0. The ioctl parameter is an integer endpoint number (1 to 15,
+    as identified in the endpoint descriptor), with USB_DIR_IN added
+    if the device's endpoint sends data to the host.
+
+        **Warning**
+
+        *Avoid using this request. It should probably be removed.* Using
+        it typically means the device and driver will lose toggle
+        synchronization. If you really lost synchronization, you likely
+        need to completely handshake with the device, using a request
+        like CLEAR_HALT or SET_INTERFACE.
+
+USBDEVFS_DROP_PRIVILEGES
+    This is used to relinquish the ability to do certain operations
+    which are considered to be privileged on a usbfs file descriptor.
+    This includes claiming arbitrary interfaces, resetting a device on
+    which there are currently claimed interfaces from other users, and
+    issuing USBDEVFS_IOCTL calls. The ioctl parameter is a 32 bit mask
+    of interfaces the user is allowed to claim on this file descriptor.
+    You may issue this ioctl more than one time to narrow said mask.
+
+Synchronous I/O Support
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Synchronous requests involve the kernel blocking until the user mode
+request completes, either by finishing successfully or by reporting an
+error. In most cases this is the simplest way to use usbfs, although as
+noted above it does prevent performing I/O to more than one endpoint at
+a time.
+
+USBDEVFS_BULK
+    Issues a bulk read or write request to the device. The ioctl
+    parameter is a pointer to this structure:
+
+    ::
+
+        struct usbdevfs_bulktransfer {
+                unsigned int  ep;
+                unsigned int  len;
+                unsigned int  timeout; /* in milliseconds */
+                void          *data;
+        };
+
+    The "ep" value identifies a bulk endpoint number (1 to 15, as
+    identified in an endpoint descriptor), masked with USB_DIR_IN when
+    referring to an endpoint which sends data to the host from the
+    device. The length of the data buffer is identified by "len"; Recent
+    kernels support requests up to about 128KBytes. *FIXME say how read
+    length is returned, and how short reads are handled.*.
+
+USBDEVFS_CLEAR_HALT
+    Clears endpoint halt (stall) and resets the endpoint toggle. This is
+    only meaningful for bulk or interrupt endpoints. The ioctl parameter
+    is an integer endpoint number (1 to 15, as identified in an endpoint
+    descriptor), masked with USB_DIR_IN when referring to an endpoint
+    which sends data to the host from the device.
+
+    Use this on bulk or interrupt endpoints which have stalled,
+    returning *-EPIPE* status to a data transfer request. Do not issue
+    the control request directly, since that could invalidate the host's
+    record of the data toggle.
+
+USBDEVFS_CONTROL
+    Issues a control request to the device. The ioctl parameter points
+    to a structure like this:
+
+    ::
+
+        struct usbdevfs_ctrltransfer {
+                __u8   bRequestType;
+                __u8   bRequest;
+                __u16  wValue;
+                __u16  wIndex;
+                __u16  wLength;
+                __u32  timeout;  /* in milliseconds */
+                void   *data;
+        };
+
+    The first eight bytes of this structure are the contents of the
+    SETUP packet to be sent to the device; see the USB 2.0 specification
+    for details. The bRequestType value is composed by combining a
+    USB_TYPE_\* value, a USB_DIR_\* value, and a USB_RECIP_\*
+    value (from *<linux/usb.h>*). If wLength is nonzero, it describes
+    the length of the data buffer, which is either written to the device
+    (USB_DIR_OUT) or read from the device (USB_DIR_IN).
+
+    At this writing, you can't transfer more than 4 KBytes of data to or
+    from a device; usbfs has a limit, and some host controller drivers
+    have a limit. (That's not usually a problem.) *Also* there's no way
+    to say it's not OK to get a short read back from the device.
+
+USBDEVFS_RESET
+    Does a USB level device reset. The ioctl parameter is ignored. After
+    the reset, this rebinds all device interfaces. File modification
+    time is not updated by this request.
+
+        **Warning**
+
+        *Avoid using this call* until some usbcore bugs get fixed, since
+        it does not fully synchronize device, interface, and driver (not
+        just usbfs) state.
+
+USBDEVFS_SETINTERFACE
+    Sets the alternate setting for an interface. The ioctl parameter is
+    a pointer to a structure like this:
+
+    ::
+
+        struct usbdevfs_setinterface {
+                unsigned int  interface;
+                unsigned int  altsetting;
+        };
+
+    File modification time is not updated by this request.
+
+    Those struct members are from some interface descriptor applying to
+    the current configuration. The interface number is the
+    bInterfaceNumber value, and the altsetting number is the
+    bAlternateSetting value. (This resets each endpoint in the
+    interface.)
+
+USBDEVFS_SETCONFIGURATION
+    Issues the :c:func:`usb_set_configuration()` call for the
+    device. The parameter is an integer holding the number of a
+    configuration (bConfigurationValue from descriptor). File
+    modification time is not updated by this request.
+
+        **Warning**
+
+        *Avoid using this call* until some usbcore bugs get fixed, since
+        it does not fully synchronize device, interface, and driver (not
+        just usbfs) state.
+
+Asynchronous I/O Support
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+As mentioned above, there are situations where it may be important to
+initiate concurrent operations from user mode code. This is particularly
+important for periodic transfers (interrupt and isochronous), but it can
+be used for other kinds of USB requests too. In such cases, the
+asynchronous requests described here are essential. Rather than
+submitting one request and having the kernel block until it completes,
+the blocking is separate.
+
+These requests are packaged into a structure that resembles the URB used
+by kernel device drivers. (No POSIX Async I/O support here, sorry.) It
+identifies the endpoint type (USBDEVFS_URB_TYPE_\*), endpoint
+(number, masked with USB_DIR_IN as appropriate), buffer and length,
+and a user "context" value serving to uniquely identify each request.
+(It's usually a pointer to per-request data.) Flags can modify requests
+(not as many as supported for kernel drivers).
+
+Each request can specify a realtime signal number (between SIGRTMIN and
+SIGRTMAX, inclusive) to request a signal be sent when the request
+completes.
+
+When usbfs returns these urbs, the status value is updated, and the
+buffer may have been modified. Except for isochronous transfers, the
+actual_length is updated to say how many bytes were transferred; if the
+USBDEVFS_URB_DISABLE_SPD flag is set ("short packets are not OK"), if
+fewer bytes were read than were requested then you get an error report.
+
+::
+
+    struct usbdevfs_iso_packet_desc {
+            unsigned int                     length;
+            unsigned int                     actual_length;
+            unsigned int                     status;
+    };
+
+    struct usbdevfs_urb {
+            unsigned char                    type;
+            unsigned char                    endpoint;
+            int                              status;
+            unsigned int                     flags;
+            void                             *buffer;
+            int                              buffer_length;
+            int                              actual_length;
+            int                              start_frame;
+            int                              number_of_packets;
+            int                              error_count;
+            unsigned int                     signr;
+            void                             *usercontext;
+            struct usbdevfs_iso_packet_desc  iso_frame_desc[];
+    };
+
+For these asynchronous requests, the file modification time reflects
+when the request was initiated. This contrasts with their use with the
+synchronous requests, where it reflects when requests complete.
+
+USBDEVFS_DISCARDURB
+    *TBS* File modification time is not updated by this request.
+
+USBDEVFS_DISCSIGNAL
+    *TBS* File modification time is not updated by this request.
+
+USBDEVFS_REAPURB
+    *TBS* File modification time is not updated by this request.
+
+USBDEVFS_REAPURBNDELAY
+    *TBS* File modification time is not updated by this request.
+
+USBDEVFS_SUBMITURB
+    *TBS*
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-api/vme.rst linux-libre-4.10-rc8-gnu/Documentation/driver-api/vme.rst
--- linux-libre-4.9-gnu/Documentation/driver-api/vme.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-api/vme.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,474 @@
+VME Device Drivers
+==================
+
+Driver registration
+-------------------
+
+As with other subsystems within the Linux kernel, VME device drivers register
+with the VME subsystem, typically called from the devices init routine.  This is
+achieved via a call to the following function:
+
+.. code-block:: c
+
+	int vme_register_driver (struct vme_driver *driver, unsigned int ndevs);
+
+If driver registration is successful this function returns zero, if an error
+occurred a negative error code will be returned.
+
+A pointer to a structure of type 'vme_driver' must be provided to the
+registration function. Along with ndevs, which is the number of devices your
+driver is able to support. The structure is as follows:
+
+.. code-block:: c
+
+	struct vme_driver {
+		struct list_head node;
+		const char *name;
+		int (*match)(struct vme_dev *);
+		int (*probe)(struct vme_dev *);
+		int (*remove)(struct vme_dev *);
+		void (*shutdown)(void);
+		struct device_driver driver;
+		struct list_head devices;
+		unsigned int ndev;
+	};
+
+At the minimum, the '.name', '.match' and '.probe' elements of this structure
+should be correctly set. The '.name' element is a pointer to a string holding
+the device driver's name.
+
+The '.match' function allows control over which VME devices should be registered
+with the driver. The match function should return 1 if a device should be
+probed and 0 otherwise. This example match function (from vme_user.c) limits
+the number of devices probed to one:
+
+.. code-block:: c
+
+	#define USER_BUS_MAX	1
+	...
+	static int vme_user_match(struct vme_dev *vdev)
+	{
+		if (vdev->id.num >= USER_BUS_MAX)
+			return 0;
+		return 1;
+	}
+
+The '.probe' element should contain a pointer to the probe routine. The
+probe routine is passed a 'struct vme_dev' pointer as an argument. The
+'struct vme_dev' structure looks like the following:
+
+.. code-block:: c
+
+	struct vme_dev {
+		int num;
+		struct vme_bridge *bridge;
+		struct device dev;
+		struct list_head drv_list;
+		struct list_head bridge_list;
+	};
+
+Here, the 'num' field refers to the sequential device ID for this specific
+driver. The bridge number (or bus number) can be accessed using
+dev->bridge->num.
+
+A function is also provided to unregister the driver from the VME core and is
+usually called from the device driver's exit routine:
+
+.. code-block:: c
+
+	void vme_unregister_driver (struct vme_driver *driver);
+
+
+Resource management
+-------------------
+
+Once a driver has registered with the VME core the provided match routine will
+be called the number of times specified during the registration. If a match
+succeeds, a non-zero value should be returned. A zero return value indicates
+failure. For all successful matches, the probe routine of the corresponding
+driver is called. The probe routine is passed a pointer to the devices
+device structure. This pointer should be saved, it will be required for
+requesting VME resources.
+
+The driver can request ownership of one or more master windows, slave windows
+and/or dma channels. Rather than allowing the device driver to request a
+specific window or DMA channel (which may be used by a different driver) this
+driver allows a resource to be assigned based on the required attributes of the
+driver in question:
+
+.. code-block:: c
+
+	struct vme_resource * vme_master_request(struct vme_dev *dev,
+		u32 aspace, u32 cycle, u32 width);
+
+	struct vme_resource * vme_slave_request(struct vme_dev *dev, u32 aspace,
+		u32 cycle);
+
+	struct vme_resource *vme_dma_request(struct vme_dev *dev, u32 route);
+
+For slave windows these attributes are split into the VME address spaces that
+need to be accessed in 'aspace' and VME bus cycle types required in 'cycle'.
+Master windows add a further set of attributes in 'width' specifying the
+required data transfer widths. These attributes are defined as bitmasks and as
+such any combination of the attributes can be requested for a single window,
+the core will assign a window that meets the requirements, returning a pointer
+of type vme_resource that should be used to identify the allocated resource
+when it is used. For DMA controllers, the request function requires the
+potential direction of any transfers to be provided in the route attributes.
+This is typically VME-to-MEM and/or MEM-to-VME, though some hardware can
+support VME-to-VME and MEM-to-MEM transfers as well as test pattern generation.
+If an unallocated window fitting the requirements can not be found a NULL
+pointer will be returned.
+
+Functions are also provided to free window allocations once they are no longer
+required. These functions should be passed the pointer to the resource provided
+during resource allocation:
+
+.. code-block:: c
+
+	void vme_master_free(struct vme_resource *res);
+
+	void vme_slave_free(struct vme_resource *res);
+
+	void vme_dma_free(struct vme_resource *res);
+
+
+Master windows
+--------------
+
+Master windows provide access from the local processor[s] out onto the VME bus.
+The number of windows available and the available access modes is dependent on
+the underlying chipset. A window must be configured before it can be used.
+
+
+Master window configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once a master window has been assigned the following functions can be used to
+configure it and retrieve the current settings:
+
+.. code-block:: c
+
+	int vme_master_set (struct vme_resource *res, int enabled,
+		unsigned long long base, unsigned long long size, u32 aspace,
+		u32 cycle, u32 width);
+
+	int vme_master_get (struct vme_resource *res, int *enabled,
+		unsigned long long *base, unsigned long long *size, u32 *aspace,
+		u32 *cycle, u32 *width);
+
+The address spaces, transfer widths and cycle types are the same as described
+under resource management, however some of the options are mutually exclusive.
+For example, only one address space may be specified.
+
+These functions return 0 on success or an error code should the call fail.
+
+
+Master window access
+~~~~~~~~~~~~~~~~~~~~
+
+The following functions can be used to read from and write to configured master
+windows. These functions return the number of bytes copied:
+
+.. code-block:: c
+
+	ssize_t vme_master_read(struct vme_resource *res, void *buf,
+		size_t count, loff_t offset);
+
+	ssize_t vme_master_write(struct vme_resource *res, void *buf,
+		size_t count, loff_t offset);
+
+In addition to simple reads and writes, a function is provided to do a
+read-modify-write transaction. This function returns the original value of the
+VME bus location :
+
+.. code-block:: c
+
+	unsigned int vme_master_rmw (struct vme_resource *res,
+		unsigned int mask, unsigned int compare, unsigned int swap,
+		loff_t offset);
+
+This functions by reading the offset, applying the mask. If the bits selected in
+the mask match with the values of the corresponding bits in the compare field,
+the value of swap is written the specified offset.
+
+Parts of a VME window can be mapped into user space memory using the following
+function:
+
+.. code-block:: c
+
+	int vme_master_mmap(struct vme_resource *resource,
+		struct vm_area_struct *vma)
+
+
+Slave windows
+-------------
+
+Slave windows provide devices on the VME bus access into mapped portions of the
+local memory. The number of windows available and the access modes that can be
+used is dependent on the underlying chipset. A window must be configured before
+it can be used.
+
+
+Slave window configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once a slave window has been assigned the following functions can be used to
+configure it and retrieve the current settings:
+
+.. code-block:: c
+
+	int vme_slave_set (struct vme_resource *res, int enabled,
+		unsigned long long base, unsigned long long size,
+		dma_addr_t mem, u32 aspace, u32 cycle);
+
+	int vme_slave_get (struct vme_resource *res, int *enabled,
+		unsigned long long *base, unsigned long long *size,
+		dma_addr_t *mem, u32 *aspace, u32 *cycle);
+
+The address spaces, transfer widths and cycle types are the same as described
+under resource management, however some of the options are mutually exclusive.
+For example, only one address space may be specified.
+
+These functions return 0 on success or an error code should the call fail.
+
+
+Slave window buffer allocation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Functions are provided to allow the user to allocate and free a contiguous
+buffers which will be accessible by the VME bridge. These functions do not have
+to be used, other methods can be used to allocate a buffer, though care must be
+taken to ensure that they are contiguous and accessible by the VME bridge:
+
+.. code-block:: c
+
+	void * vme_alloc_consistent(struct vme_resource *res, size_t size,
+		dma_addr_t *mem);
+
+	void vme_free_consistent(struct vme_resource *res, size_t size,
+		void *virt,	dma_addr_t mem);
+
+
+Slave window access
+~~~~~~~~~~~~~~~~~~~
+
+Slave windows map local memory onto the VME bus, the standard methods for
+accessing memory should be used.
+
+
+DMA channels
+------------
+
+The VME DMA transfer provides the ability to run link-list DMA transfers. The
+API introduces the concept of DMA lists. Each DMA list is a link-list which can
+be passed to a DMA controller. Multiple lists can be created, extended,
+executed, reused and destroyed.
+
+
+List Management
+~~~~~~~~~~~~~~~
+
+The following functions are provided to create and destroy DMA lists. Execution
+of a list will not automatically destroy the list, thus enabling a list to be
+reused for repetitive tasks:
+
+.. code-block:: c
+
+	struct vme_dma_list *vme_new_dma_list(struct vme_resource *res);
+
+	int vme_dma_list_free(struct vme_dma_list *list);
+
+
+List Population
+~~~~~~~~~~~~~~~
+
+An item can be added to a list using the following function ( the source and
+destination attributes need to be created before calling this function, this is
+covered under "Transfer Attributes"):
+
+.. code-block:: c
+
+	int vme_dma_list_add(struct vme_dma_list *list,
+		struct vme_dma_attr *src, struct vme_dma_attr *dest,
+		size_t count);
+
+.. note::
+
+	The detailed attributes of the transfers source and destination
+	are not checked until an entry is added to a DMA list, the request
+	for a DMA channel purely checks the directions in which the
+	controller is expected to transfer data. As a result it is
+	possible for this call to return an error, for example if the
+	source or destination is in an unsupported VME address space.
+
+Transfer Attributes
+~~~~~~~~~~~~~~~~~~~
+
+The attributes for the source and destination are handled separately from adding
+an item to a list. This is due to the diverse attributes required for each type
+of source and destination. There are functions to create attributes for PCI, VME
+and pattern sources and destinations (where appropriate):
+
+Pattern source:
+
+.. code-block:: c
+
+	struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type);
+
+PCI source or destination:
+
+.. code-block:: c
+
+	struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t mem);
+
+VME source or destination:
+
+.. code-block:: c
+
+	struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long base,
+		u32 aspace, u32 cycle, u32 width);
+
+The following function should be used to free an attribute:
+
+.. code-block:: c
+
+	void vme_dma_free_attribute(struct vme_dma_attr *attr);
+
+
+List Execution
+~~~~~~~~~~~~~~
+
+The following function queues a list for execution. The function will return
+once the list has been executed:
+
+.. code-block:: c
+
+	int vme_dma_list_exec(struct vme_dma_list *list);
+
+
+Interrupts
+----------
+
+The VME API provides functions to attach and detach callbacks to specific VME
+level and status ID combinations and for the generation of VME interrupts with
+specific VME level and status IDs.
+
+
+Attaching Interrupt Handlers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following functions can be used to attach and free a specific VME level and
+status ID combination. Any given combination can only be assigned a single
+callback function. A void pointer parameter is provided, the value of which is
+passed to the callback function, the use of this pointer is user undefined:
+
+.. code-block:: c
+
+	int vme_irq_request(struct vme_dev *dev, int level, int statid,
+		void (*callback)(int, int, void *), void *priv);
+
+	void vme_irq_free(struct vme_dev *dev, int level, int statid);
+
+The callback parameters are as follows. Care must be taken in writing a callback
+function, callback functions run in interrupt context:
+
+.. code-block:: c
+
+	void callback(int level, int statid, void *priv);
+
+
+Interrupt Generation
+~~~~~~~~~~~~~~~~~~~~
+
+The following function can be used to generate a VME interrupt at a given VME
+level and VME status ID:
+
+.. code-block:: c
+
+	int vme_irq_generate(struct vme_dev *dev, int level, int statid);
+
+
+Location monitors
+-----------------
+
+The VME API provides the following functionality to configure the location
+monitor.
+
+
+Location Monitor Management
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following functions are provided to request the use of a block of location
+monitors and to free them after they are no longer required:
+
+.. code-block:: c
+
+	struct vme_resource * vme_lm_request(struct vme_dev *dev);
+
+	void vme_lm_free(struct vme_resource * res);
+
+Each block may provide a number of location monitors, monitoring adjacent
+locations. The following function can be used to determine how many locations
+are provided:
+
+.. code-block:: c
+
+	int vme_lm_count(struct vme_resource * res);
+
+
+Location Monitor Configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once a bank of location monitors has been allocated, the following functions
+are provided to configure the location and mode of the location monitor:
+
+.. code-block:: c
+
+	int vme_lm_set(struct vme_resource *res, unsigned long long base,
+		u32 aspace, u32 cycle);
+
+	int vme_lm_get(struct vme_resource *res, unsigned long long *base,
+		u32 *aspace, u32 *cycle);
+
+
+Location Monitor Use
+~~~~~~~~~~~~~~~~~~~~
+
+The following functions allow a callback to be attached and detached from each
+location monitor location. Each location monitor can monitor a number of
+adjacent locations:
+
+.. code-block:: c
+
+	int vme_lm_attach(struct vme_resource *res, int num,
+		void (*callback)(void *));
+
+	int vme_lm_detach(struct vme_resource *res, int num);
+
+The callback function is declared as follows.
+
+.. code-block:: c
+
+	void callback(void *data);
+
+
+Slot Detection
+--------------
+
+This function returns the slot ID of the provided bridge.
+
+.. code-block:: c
+
+	int vme_slot_num(struct vme_dev *dev);
+
+
+Bus Detection
+-------------
+
+This function returns the bus ID of the provided bridge.
+
+.. code-block:: c
+
+	int vme_bus_num(struct vme_dev *dev);
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/driver-model/devres.txt linux-libre-4.10-rc8-gnu/Documentation/driver-model/devres.txt
--- linux-libre-4.9-gnu/Documentation/driver-model/devres.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/driver-model/devres.txt	2017-02-12 16:03:20.000000000 -0500
@@ -332,6 +332,10 @@ MEM
 MFD
  devm_mfd_add_devices()
 
+PER-CPU MEM
+  devm_alloc_percpu()
+  devm_free_percpu()
+
 PCI
   pcim_enable_device()	: after success, all PCI ops become managed
   pcim_pin_device()	: keep PCI device enabled after release
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/dynamic-debug-howto.txt linux-libre-4.10-rc8-gnu/Documentation/dynamic-debug-howto.txt
--- linux-libre-4.9-gnu/Documentation/dynamic-debug-howto.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/dynamic-debug-howto.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,340 +0,0 @@
-
-Introduction
-============
-
-This document describes how to use the dynamic debug (dyndbg) feature.
-
-Dynamic debug is designed to allow you to dynamically enable/disable
-kernel code to obtain additional kernel information.  Currently, if
-CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() and
-print_hex_dump_debug()/print_hex_dump_bytes() calls can be dynamically
-enabled per-callsite.
-
-If CONFIG_DYNAMIC_DEBUG is not set, print_hex_dump_debug() is just
-shortcut for print_hex_dump(KERN_DEBUG).
-
-For print_hex_dump_debug()/print_hex_dump_bytes(), format string is
-its 'prefix_str' argument, if it is constant string; or "hexdump"
-in case 'prefix_str' is build dynamically.
-
-Dynamic debug has even more useful features:
-
- * Simple query language allows turning on and off debugging
-   statements by matching any combination of 0 or 1 of:
-
-   - source filename
-   - function name
-   - line number (including ranges of line numbers)
-   - module name
-   - format string
-
- * Provides a debugfs control file: <debugfs>/dynamic_debug/control
-   which can be read to display the complete list of known debug
-   statements, to help guide you
-
-Controlling dynamic debug Behaviour
-===================================
-
-The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a
-control file in the 'debugfs' filesystem. Thus, you must first mount
-the debugfs filesystem, in order to make use of this feature.
-Subsequently, we refer to the control file as:
-<debugfs>/dynamic_debug/control. For example, if you want to enable
-printing from source file 'svcsock.c', line 1603 you simply do:
-
-nullarbor:~ # echo 'file svcsock.c line 1603 +p' >
-				<debugfs>/dynamic_debug/control
-
-If you make a mistake with the syntax, the write will fail thus:
-
-nullarbor:~ # echo 'file svcsock.c wtf 1 +p' >
-				<debugfs>/dynamic_debug/control
--bash: echo: write error: Invalid argument
-
-Viewing Dynamic Debug Behaviour
-===========================
-
-You can view the currently configured behaviour of all the debug
-statements via:
-
-nullarbor:~ # cat <debugfs>/dynamic_debug/control
-# filename:lineno [module]function flags format
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ "SVCRDMA Module Removed, deregister RPC RDMA transport\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ "\011max_inline       : %d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ "\011sq_depth         : %d\012"
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ "\011max_requests     : %d\012"
-...
-
-
-You can also apply standard Unix text manipulation filters to this
-data, e.g.
-
-nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control  | wc -l
-62
-
-nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l
-42
-
-The third column shows the currently enabled flags for each debug
-statement callsite (see below for definitions of the flags).  The
-default value, with no flags enabled, is "=_".  So you can view all
-the debug statement callsites with any non-default flags:
-
-nullarbor:~ # awk '$3 != "=_"' <debugfs>/dynamic_debug/control
-# filename:lineno [module]function flags format
-/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p "svc_process: st_sendto returned %d\012"
-
-
-Command Language Reference
-==========================
-
-At the lexical level, a command comprises a sequence of words separated
-by spaces or tabs.  So these are all equivalent:
-
-nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' >
-				<debugfs>/dynamic_debug/control
-nullarbor:~ # echo -c '  file   svcsock.c     line  1603 +p  ' >
-				<debugfs>/dynamic_debug/control
-nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
-				<debugfs>/dynamic_debug/control
-
-Command submissions are bounded by a write() system call.
-Multiple commands can be written together, separated by ';' or '\n'.
-
-  ~# echo "func pnpacpi_get_resources +p; func pnp_assign_mem +p" \
-     > <debugfs>/dynamic_debug/control
-
-If your query set is big, you can batch them too:
-
-  ~# cat query-batch-file > <debugfs>/dynamic_debug/control
-
-A another way is to use wildcard. The match rule support '*' (matches
-zero or more characters) and '?' (matches exactly one character).For
-example, you can match all usb drivers:
-
-  ~# echo "file drivers/usb/* +p" > <debugfs>/dynamic_debug/control
-
-At the syntactical level, a command comprises a sequence of match
-specifications, followed by a flags change specification.
-
-command ::= match-spec* flags-spec
-
-The match-spec's are used to choose a subset of the known pr_debug()
-callsites to which to apply the flags-spec.  Think of them as a query
-with implicit ANDs between each pair.  Note that an empty list of
-match-specs will select all debug statement callsites.
-
-A match specification comprises a keyword, which controls the
-attribute of the callsite to be compared, and a value to compare
-against.  Possible keywords are:
-
-match-spec ::= 'func' string |
-	       'file' string |
-	       'module' string |
-	       'format' string |
-	       'line' line-range
-
-line-range ::= lineno |
-	       '-'lineno |
-	       lineno'-' |
-	       lineno'-'lineno
-// Note: line-range cannot contain space, e.g.
-// "1-30" is valid range but "1 - 30" is not.
-
-lineno ::= unsigned-int
-
-The meanings of each keyword are:
-
-func
-    The given string is compared against the function name
-    of each callsite.  Example:
-
-    func svc_tcp_accept
-
-file
-    The given string is compared against either the full pathname, the
-    src-root relative pathname, or the basename of the source file of
-    each callsite.  Examples:
-
-    file svcsock.c
-    file kernel/freezer.c
-    file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c
-
-module
-    The given string is compared against the module name
-    of each callsite.  The module name is the string as
-    seen in "lsmod", i.e. without the directory or the .ko
-    suffix and with '-' changed to '_'.  Examples:
-
-    module sunrpc
-    module nfsd
-
-format
-    The given string is searched for in the dynamic debug format
-    string.  Note that the string does not need to match the
-    entire format, only some part.  Whitespace and other
-    special characters can be escaped using C octal character
-    escape \ooo notation, e.g. the space character is \040.
-    Alternatively, the string can be enclosed in double quote
-    characters (") or single quote characters (').
-    Examples:
-
-    format svcrdma:	    // many of the NFS/RDMA server pr_debugs
-    format readahead	    // some pr_debugs in the readahead cache
-    format nfsd:\040SETATTR // one way to match a format with whitespace
-    format "nfsd: SETATTR"  // a neater way to match a format with whitespace
-    format 'nfsd: SETATTR'  // yet another way to match a format with whitespace
-
-line
-    The given line number or range of line numbers is compared
-    against the line number of each pr_debug() callsite.  A single
-    line number matches the callsite line number exactly.  A
-    range of line numbers matches any callsite between the first
-    and last line number inclusive.  An empty first number means
-    the first line in the file, an empty line number means the
-    last number in the file.  Examples:
-
-    line 1603	    // exactly line 1603
-    line 1600-1605  // the six lines from line 1600 to line 1605
-    line -1605	    // the 1605 lines from line 1 to line 1605
-    line 1600-	    // all lines from line 1600 to the end of the file
-
-The flags specification comprises a change operation followed
-by one or more flag characters.  The change operation is one
-of the characters:
-
-  -    remove the given flags
-  +    add the given flags
-  =    set the flags to the given flags
-
-The flags are:
-
-  p    enables the pr_debug() callsite.
-  f    Include the function name in the printed message
-  l    Include line number in the printed message
-  m    Include module name in the printed message
-  t    Include thread ID in messages not generated from interrupt context
-  _    No flags are set. (Or'd with others on input)
-
-For print_hex_dump_debug() and print_hex_dump_bytes(), only 'p' flag
-have meaning, other flags ignored.
-
-For display, the flags are preceded by '='
-(mnemonic: what the flags are currently equal to).
-
-Note the regexp ^[-+=][flmpt_]+$ matches a flags specification.
-To clear all flags at once, use "=_" or "-flmpt".
-
-
-Debug messages during Boot Process
-==================================
-
-To activate debug messages for core code and built-in modules during
-the boot process, even before userspace and debugfs exists, use
-dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY"
-(ddebug_query is obsoleted by dyndbg, and deprecated).  QUERY follows
-the syntax described above, but must not exceed 1023 characters.  Your
-bootloader may impose lower limits.
-
-These dyndbg params are processed just after the ddebug tables are
-processed, as part of the arch_initcall.  Thus you can enable debug
-messages in all code run after this arch_initcall via this boot
-parameter.
-
-On an x86 system for example ACPI enablement is a subsys_initcall and
-   dyndbg="file ec.c +p"
-will show early Embedded Controller transactions during ACPI setup if
-your machine (typically a laptop) has an Embedded Controller.
-PCI (or other devices) initialization also is a hot candidate for using
-this boot parameter for debugging purposes.
-
-If foo module is not built-in, foo.dyndbg will still be processed at
-boot time, without effect, but will be reprocessed when module is
-loaded later.  dyndbg_query= and bare dyndbg= are only processed at
-boot.
-
-
-Debug Messages at Module Initialization Time
-============================================
-
-When "modprobe foo" is called, modprobe scans /proc/cmdline for
-foo.params, strips "foo.", and passes them to the kernel along with
-params given in modprobe args or /etc/modprob.d/*.conf files,
-in the following order:
-
-1. # parameters given via /etc/modprobe.d/*.conf
-   options foo dyndbg=+pt
-   options foo dyndbg # defaults to +p
-
-2. # foo.dyndbg as given in boot args, "foo." is stripped and passed
-   foo.dyndbg=" func bar +p; func buz +mp"
-
-3. # args to modprobe
-   modprobe foo dyndbg==pmf # override previous settings
-
-These dyndbg queries are applied in order, with last having final say.
-This allows boot args to override or modify those from /etc/modprobe.d
-(sensible, since 1 is system wide, 2 is kernel or boot specific), and
-modprobe args to override both.
-
-In the foo.dyndbg="QUERY" form, the query must exclude "module foo".
-"foo" is extracted from the param-name, and applied to each query in
-"QUERY", and only 1 match-spec of each type is allowed.
-
-The dyndbg option is a "fake" module parameter, which means:
-
-- modules do not need to define it explicitly
-- every module gets it tacitly, whether they use pr_debug or not
-- it doesn't appear in /sys/module/$module/parameters/
-  To see it, grep the control file, or inspect /proc/cmdline.
-
-For CONFIG_DYNAMIC_DEBUG kernels, any settings given at boot-time (or
-enabled by -DDEBUG flag during compilation) can be disabled later via
-the sysfs interface if the debug messages are no longer needed:
-
-   echo "module module_name -p" > <debugfs>/dynamic_debug/control
-
-Examples
-========
-
-// enable the message at line 1603 of file svcsock.c
-nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
-				<debugfs>/dynamic_debug/control
-
-// enable all the messages in file svcsock.c
-nullarbor:~ # echo -n 'file svcsock.c +p' >
-				<debugfs>/dynamic_debug/control
-
-// enable all the messages in the NFS server module
-nullarbor:~ # echo -n 'module nfsd +p' >
-				<debugfs>/dynamic_debug/control
-
-// enable all 12 messages in the function svc_process()
-nullarbor:~ # echo -n 'func svc_process +p' >
-				<debugfs>/dynamic_debug/control
-
-// disable all 12 messages in the function svc_process()
-nullarbor:~ # echo -n 'func svc_process -p' >
-				<debugfs>/dynamic_debug/control
-
-// enable messages for NFS calls READ, READLINK, READDIR and READDIR+.
-nullarbor:~ # echo -n 'format "nfsd: READ" +p' >
-				<debugfs>/dynamic_debug/control
-
-// enable messages in files of which the paths include string "usb"
-nullarbor:~ # echo -n '*usb* +p' > <debugfs>/dynamic_debug/control
-
-// enable all messages
-nullarbor:~ # echo -n '+p' > <debugfs>/dynamic_debug/control
-
-// add module, function to all enabled messages
-nullarbor:~ # echo -n '+mf' > <debugfs>/dynamic_debug/control
-
-// boot-args example, with newlines and comments for readability
-Kernel command line: ...
-  // see whats going on in dyndbg=value processing
-  dynamic_debug.verbose=1
-  // enable pr_debugs in 2 builtins, #cmt is stripped
-  dyndbg="module params +p #cmt ; module sys +p"
-  // enable pr_debugs in 2 functions in a module loaded later
-  pc87360.dyndbg="func pc87360_init_device +p; func pc87360_find +p"
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/edac.txt linux-libre-4.10-rc8-gnu/Documentation/edac.txt
--- linux-libre-4.9-gnu/Documentation/edac.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/edac.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,812 +0,0 @@
-EDAC - Error Detection And Correction
-=====================================
-
-"bluesmoke" was the name for this device driver when it
-was "out-of-tree" and maintained at sourceforge.net -
-bluesmoke.sourceforge.net. That site is mostly archaic now and can be
-used only for historical purposes.
-
-When the subsystem was pushed into 2.6.16 for the first time, it was
-renamed to 'EDAC'.
-
-PURPOSE
--------
-
-The 'edac' kernel module's goal is to detect and report hardware errors
-that occur within the computer system running under linux.
-
-MEMORY
-------
-
-Memory Correctable Errors (CE) and Uncorrectable Errors (UE) are the
-primary errors being harvested. These types of errors are harvested by
-the 'edac_mc' device.
-
-Detecting CE events, then harvesting those events and reporting them,
-*can* but must not necessarily be a predictor of future UE events. With
-CE events only, the system can and will continue to operate as no data
-has been damaged yet.
-
-However, preventive maintenance and proactive part replacement of memory
-DIMMs exhibiting CEs can reduce the likelihood of the dreaded UE events
-and system panics.
-
-OTHER HARDWARE ELEMENTS
------------------------
-
-A new feature for EDAC, the edac_device class of device, was added in
-the 2.6.23 version of the kernel.
-
-This new device type allows for non-memory type of ECC hardware detectors
-to have their states harvested and presented to userspace via the sysfs
-interface.
-
-Some architectures have ECC detectors for L1, L2 and L3 caches,
-along with DMA engines, fabric switches, main data path switches,
-interconnections, and various other hardware data paths. If the hardware
-reports it, then a edac_device device probably can be constructed to
-harvest and present that to userspace.
-
-
-PCI BUS SCANNING
-----------------
-
-In addition, PCI devices are scanned for PCI Bus Parity and SERR Errors
-in order to determine if errors are occurring during data transfers.
-
-The presence of PCI Parity errors must be examined with a grain of salt.
-There are several add-in adapters that do *not* follow the PCI specification
-with regards to Parity generation and reporting. The specification says
-the vendor should tie the parity status bits to 0 if they do not intend
-to generate parity.  Some vendors do not do this, and thus the parity bit
-can "float" giving false positives.
-
-There is a PCI device attribute located in sysfs that is checked by
-the EDAC PCI scanning code. If that attribute is set, PCI parity/error
-scanning is skipped for that device. The attribute is:
-
-	broken_parity_status
-
-and is located in /sys/devices/pci<XXX>/0000:XX:YY.Z directories for
-PCI devices.
-
-
-VERSIONING
-----------
-
-EDAC is composed of a "core" module (edac_core.ko) and several Memory
-Controller (MC) driver modules. On a given system, the CORE is loaded
-and one MC driver will be loaded. Both the CORE and the MC driver (or
-edac_device driver) have individual versions that reflect current
-release level of their respective modules.
-
-Thus, to "report" on what version a system is running, one must report
-both the CORE's and the MC driver's versions.
-
-
-LOADING
--------
-
-If 'edac' was statically linked with the kernel then no loading
-is necessary. If 'edac' was built as modules then simply modprobe
-the 'edac' pieces that you need. You should be able to modprobe
-hardware-specific modules and have the dependencies load the necessary
-core modules.
-
-Example:
-
-$> modprobe amd76x_edac
-
-loads both the amd76x_edac.ko memory controller module and the edac_mc.ko
-core module.
-
-
-SYSFS INTERFACE
----------------
-
-EDAC presents a 'sysfs' interface for control and reporting purposes. It
-lives in the /sys/devices/system/edac directory.
-
-Within this directory there currently reside 2 components:
-
-	mc	memory controller(s) system
-	pci	PCI control and status system
-
-
-
-Memory Controller (mc) Model
-----------------------------
-
-Each 'mc' device controls a set of DIMM memory modules. These modules
-are laid out in a Chip-Select Row (csrowX) and Channel table (chX).
-There can be multiple csrows and multiple channels.
-
-Memory controllers allow for several csrows, with 8 csrows being a
-typical value. Yet, the actual number of csrows depends on the layout of
-a given motherboard, memory controller and DIMM characteristics.
-
-Dual channels allows for 128 bit data transfers to/from the CPU from/to
-memory. Some newer chipsets allow for more than 2 channels, like Fully
-Buffered DIMMs (FB-DIMMs). The following example will assume 2 channels:
-
-
-		Channel 0	Channel 1
-	===================================
-	csrow0	| DIMM_A0	| DIMM_B0 |
-	csrow1	| DIMM_A0	| DIMM_B0 |
-	===================================
-
-	===================================
-	csrow2	| DIMM_A1	| DIMM_B1 |
-	csrow3	| DIMM_A1	| DIMM_B1 |
-	===================================
-
-In the above example table there are 4 physical slots on the motherboard
-for memory DIMMs:
-
-	DIMM_A0
-	DIMM_B0
-	DIMM_A1
-	DIMM_B1
-
-Labels for these slots are usually silk-screened on the motherboard.
-Slots labeled 'A' are channel 0 in this example. Slots labeled 'B' are
-channel 1. Notice that there are two csrows possible on a physical DIMM.
-These csrows are allocated their csrow assignment based on the slot into
-which the memory DIMM is placed. Thus, when 1 DIMM is placed in each
-Channel, the csrows cross both DIMMs.
-
-Memory DIMMs come single or dual "ranked". A rank is a populated csrow.
-Thus, 2 single ranked DIMMs, placed in slots DIMM_A0 and DIMM_B0 above
-will have 1 csrow, csrow0. csrow1 will be empty. On the other hand,
-when 2 dual ranked DIMMs are similarly placed, then both csrow0 and
-csrow1 will be populated. The pattern repeats itself for csrow2 and
-csrow3.
-
-The representation of the above is reflected in the directory
-tree in EDAC's sysfs interface. Starting in directory
-/sys/devices/system/edac/mc each memory controller will be represented
-by its own 'mcX' directory, where 'X' is the index of the MC.
-
-
-	..../edac/mc/
-		   |
-		   |->mc0
-		   |->mc1
-		   |->mc2
-		   ....
-
-Under each 'mcX' directory each 'csrowX' is again represented by a
-'csrowX', where 'X' is the csrow index:
-
-
-	.../mc/mc0/
-		|
-		|->csrow0
-		|->csrow2
-		|->csrow3
-		....
-
-Notice that there is no csrow1, which indicates that csrow0 is composed
-of a single ranked DIMMs. This should also apply in both Channels, in
-order to have dual-channel mode be operational. Since both csrow2 and
-csrow3 are populated, this indicates a dual ranked set of DIMMs for
-channels 0 and 1.
-
-
-Within each of the 'mcX' and 'csrowX' directories are several EDAC
-control and attribute files.
-
-
-'mcX' directories
------------------
-
-In 'mcX' directories are EDAC control and attribute files for
-this 'X' instance of the memory controllers.
-
-For a description of the sysfs API, please see:
-	Documentation/ABI/testing/sysfs-devices-edac
-
-
-
-'csrowX' directories
---------------------
-
-When CONFIG_EDAC_LEGACY_SYSFS is enabled, sysfs will contain the csrowX
-directories. As this API doesn't work properly for Rambus, FB-DIMMs and
-modern Intel Memory Controllers, this is being deprecated in favor of
-dimmX directories.
-
-In the 'csrowX' directories are EDAC control and attribute files for
-this 'X' instance of csrow:
-
-
-Total Uncorrectable Errors count attribute file:
-
-	'ue_count'
-
-	This attribute file displays the total count of uncorrectable
-	errors that have occurred on this csrow. If panic_on_ue is set
-	this counter will not have a chance to increment, since EDAC
-	will panic the system.
-
-
-Total Correctable Errors count attribute file:
-
-	'ce_count'
-
-	This attribute file displays the total count of correctable
-	errors that have occurred on this csrow. This count is very
-	important to examine. CEs provide early indications that a
-	DIMM is beginning to fail. This count field should be
-	monitored for non-zero values and report such information
-	to the system administrator.
-
-
-Total memory managed by this csrow attribute file:
-
-	'size_mb'
-
-	This attribute file displays, in count of megabytes, the memory
-	that this csrow contains.
-
-
-Memory Type attribute file:
-
-	'mem_type'
-
-	This attribute file will display what type of memory is currently
-	on this csrow. Normally, either buffered or unbuffered memory.
-	Examples:
-		Registered-DDR
-		Unbuffered-DDR
-
-
-EDAC Mode of operation attribute file:
-
-	'edac_mode'
-
-	This attribute file will display what type of Error detection
-	and correction is being utilized.
-
-
-Device type attribute file:
-
-	'dev_type'
-
-	This attribute file will display what type of DRAM device is
-	being utilized on this DIMM.
-	Examples:
-		x1
-		x2
-		x4
-		x8
-
-
-Channel 0 CE Count attribute file:
-
-	'ch0_ce_count'
-
-	This attribute file will display the count of CEs on this
-	DIMM located in channel 0.
-
-
-Channel 0 UE Count attribute file:
-
-	'ch0_ue_count'
-
-	This attribute file will display the count of UEs on this
-	DIMM located in channel 0.
-
-
-Channel 0 DIMM Label control file:
-
-	'ch0_dimm_label'
-
-	This control file allows this DIMM to have a label assigned
-	to it. With this label in the module, when errors occur
-	the output can provide the DIMM label in the system log.
-	This becomes vital for panic events to isolate the
-	cause of the UE event.
-
-	DIMM Labels must be assigned after booting, with information
-	that correctly identifies the physical slot with its
-	silk screen label. This information is currently very
-	motherboard specific and determination of this information
-	must occur in userland at this time.
-
-
-Channel 1 CE Count attribute file:
-
-	'ch1_ce_count'
-
-	This attribute file will display the count of CEs on this
-	DIMM located in channel 1.
-
-
-Channel 1 UE Count attribute file:
-
-	'ch1_ue_count'
-
-	This attribute file will display the count of UEs on this
-	DIMM located in channel 0.
-
-
-Channel 1 DIMM Label control file:
-
-	'ch1_dimm_label'
-
-	This control file allows this DIMM to have a label assigned
-	to it. With this label in the module, when errors occur
-	the output can provide the DIMM label in the system log.
-	This becomes vital for panic events to isolate the
-	cause of the UE event.
-
-	DIMM Labels must be assigned after booting, with information
-	that correctly identifies the physical slot with its
-	silk screen label. This information is currently very
-	motherboard specific and determination of this information
-	must occur in userland at this time.
-
-
-
-SYSTEM LOGGING
---------------
-
-If logging for UEs and CEs is enabled, then system logs will contain
-information indicating that errors have been detected:
-
-EDAC MC0: CE page 0x283, offset 0xce0, grain 8, syndrome 0x6ec3, row 0,
-channel 1 "DIMM_B1": amd76x_edac
-
-EDAC MC0: CE page 0x1e5, offset 0xfb0, grain 8, syndrome 0xb741, row 0,
-channel 1 "DIMM_B1": amd76x_edac
-
-
-The structure of the message is:
-	the memory controller			(MC0)
-	Error type				(CE)
-	memory page				(0x283)
-	offset in the page			(0xce0)
-	the byte granularity 			(grain 8)
-		or resolution of the error
-	the error syndrome			(0xb741)
-	memory row				(row 0)
-	memory channel				(channel 1)
-	DIMM label, if set prior		(DIMM B1
-	and then an optional, driver-specific message that may
-		have additional information.
-
-Both UEs and CEs with no info will lack all but memory controller, error
-type, a notice of "no info" and then an optional, driver-specific error
-message.
-
-
-PCI Bus Parity Detection
-------------------------
-
-On Header Type 00 devices, the primary status is looked at for any
-parity error regardless of whether parity is enabled on the device or
-not. (The spec indicates parity is generated in some cases). On Header
-Type 01 bridges, the secondary status register is also looked at to see
-if parity occurred on the bus on the other side of the bridge.
-
-
-SYSFS CONFIGURATION
--------------------
-
-Under /sys/devices/system/edac/pci are control and attribute files as follows:
-
-
-Enable/Disable PCI Parity checking control file:
-
-	'check_pci_parity'
-
-
-	This control file enables or disables the PCI Bus Parity scanning
-	operation. Writing a 1 to this file enables the scanning. Writing
-	a 0 to this file disables the scanning.
-
-	Enable:
-	echo "1" >/sys/devices/system/edac/pci/check_pci_parity
-
-	Disable:
-	echo "0" >/sys/devices/system/edac/pci/check_pci_parity
-
-
-Parity Count:
-
-	'pci_parity_count'
-
-	This attribute file will display the number of parity errors that
-	have been detected.
-
-
-
-MODULE PARAMETERS
------------------
-
-Panic on UE control file:
-
-	'edac_mc_panic_on_ue'
-
-	An uncorrectable error will cause a machine panic.  This is usually
-	desirable.  It is a bad idea to continue when an uncorrectable error
-	occurs - it is indeterminate what was uncorrected and the operating
-	system context might be so mangled that continuing will lead to further
-	corruption. If the kernel has MCE configured, then EDAC will never
-	notice the UE.
-
-	LOAD TIME: module/kernel parameter: edac_mc_panic_on_ue=[0|1]
-
-	RUN TIME:  echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue
-
-
-Log UE control file:
-
-	'edac_mc_log_ue'
-
-	Generate kernel messages describing uncorrectable errors.  These errors
-	are reported through the system message log system.  UE statistics
-	will be accumulated even when UE logging is disabled.
-
-	LOAD TIME: module/kernel parameter: edac_mc_log_ue=[0|1]
-
-	RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue
-
-
-Log CE control file:
-
-	'edac_mc_log_ce'
-
-	Generate kernel messages describing correctable errors.  These
-	errors are reported through the system message log system.
-	CE statistics will be accumulated even when CE logging is disabled.
-
-	LOAD TIME: module/kernel parameter: edac_mc_log_ce=[0|1]
-
-	RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce
-
-
-Polling period control file:
-
-	'edac_mc_poll_msec'
-
-	The time period, in milliseconds, for polling for error information.
-	Too small a value wastes resources.  Too large a value might delay
-	necessary handling of errors and might loose valuable information for
-	locating the error.  1000 milliseconds (once each second) is the current
-	default. Systems which require all the bandwidth they can get, may
-	increase this.
-
-	LOAD TIME: module/kernel parameter: edac_mc_poll_msec=[0|1]
-
-	RUN TIME: echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec
-
-
-Panic on PCI PARITY Error:
-
-	'panic_on_pci_parity'
-
-
-	This control file enables or disables panicking when a parity
-	error has been detected.
-
-
-	module/kernel parameter: edac_panic_on_pci_pe=[0|1]
-
-	Enable:
-	echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
-
-	Disable:
-	echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
-
-
-
-EDAC device type
-----------------
-
-In the header file, edac_core.h, there is a series of edac_device structures
-and APIs for the EDAC_DEVICE.
-
-User space access to an edac_device is through the sysfs interface.
-
-At the location /sys/devices/system/edac (sysfs) new edac_device devices will
-appear.
-
-There is a three level tree beneath the above 'edac' directory. For example,
-the 'test_device_edac' device (found at the bluesmoke.sourceforget.net website)
-installs itself as:
-
-	/sys/devices/systm/edac/test-instance
-
-in this directory are various controls, a symlink and one or more 'instance'
-directories.
-
-The standard default controls are:
-
-	log_ce		boolean to log CE events
-	log_ue		boolean to log UE events
-	panic_on_ue	boolean to 'panic' the system if an UE is encountered
-			(default off, can be set true via startup script)
-	poll_msec	time period between POLL cycles for events
-
-The test_device_edac device adds at least one of its own custom control:
-
-	test_bits	which in the current test driver does nothing but
-			show how it is installed. A ported driver can
-			add one or more such controls and/or attributes
-			for specific uses.
-			One out-of-tree driver uses controls here to allow
-			for ERROR INJECTION operations to hardware
-			injection registers
-
-The symlink points to the 'struct dev' that is registered for this edac_device.
-
-INSTANCES
----------
-
-One or more instance directories are present. For the 'test_device_edac' case:
-
-	test-instance0
-
-
-In this directory there are two default counter attributes, which are totals of
-counter in deeper subdirectories.
-
-	ce_count	total of CE events of subdirectories
-	ue_count	total of UE events of subdirectories
-
-BLOCKS
-------
-
-At the lowest directory level is the 'block' directory. There can be 0, 1
-or more blocks specified in each instance.
-
-	test-block0
-
-
-In this directory the default attributes are:
-
-	ce_count	which is counter of CE events for this 'block'
-			of hardware being monitored
-	ue_count	which is counter of UE events for this 'block'
-			of hardware being monitored
-
-
-The 'test_device_edac' device adds 4 attributes and 1 control:
-
-	test-block-bits-0	for every POLL cycle this counter
-				is incremented
-	test-block-bits-1	every 10 cycles, this counter is bumped once,
-				and test-block-bits-0 is set to 0
-	test-block-bits-2	every 100 cycles, this counter is bumped once,
-				and test-block-bits-1 is set to 0
-	test-block-bits-3	every 1000 cycles, this counter is bumped once,
-				and test-block-bits-2 is set to 0
-
-
-	reset-counters		writing ANY thing to this control will
-				reset all the above counters.
-
-
-Use of the 'test_device_edac' driver should enable any others to create their own
-unique drivers for their hardware systems.
-
-The 'test_device_edac' sample driver is located at the
-bluesmoke.sourceforge.net project site for EDAC.
-
-
-NEHALEM USAGE OF EDAC APIs
---------------------------
-
-This chapter documents some EXPERIMENTAL mappings for EDAC API to handle
-Nehalem EDAC driver. They will likely be changed on future versions
-of the driver.
-
-Due to the way Nehalem exports Memory Controller data, some adjustments
-were done at i7core_edac driver. This chapter will cover those differences
-
-1) On Nehalem, there is one Memory Controller per Quick Patch Interconnect
-   (QPI). At the driver, the term "socket" means one QPI. This is
-   associated with a physical CPU socket.
-
-   Each MC have 3 physical read channels, 3 physical write channels and
-   3 logic channels. The driver currently sees it as just 3 channels.
-   Each channel can have up to 3 DIMMs.
-
-   The minimum known unity is DIMMs. There are no information about csrows.
-   As EDAC API maps the minimum unity is csrows, the driver sequentially
-   maps channel/dimm into different csrows.
-
-   For example, supposing the following layout:
-	Ch0 phy rd0, wr0 (0x063f4031): 2 ranks, UDIMMs
-	  dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
-	  dimm 1 1024 Mb offset: 4, bank: 8, rank: 1, row: 0x4000, col: 0x400
-        Ch1 phy rd1, wr1 (0x063f4031): 2 ranks, UDIMMs
-	  dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
-	Ch2 phy rd3, wr3 (0x063f4031): 2 ranks, UDIMMs
-	  dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
-   The driver will map it as:
-	csrow0: channel 0, dimm0
-	csrow1: channel 0, dimm1
-	csrow2: channel 1, dimm0
-	csrow3: channel 2, dimm0
-
-exports one
-   DIMM per csrow.
-
-   Each QPI is exported as a different memory controller.
-
-2) Nehalem MC has the ability to generate errors. The driver implements this
-   functionality via some error injection nodes:
-
-   For injecting a memory error, there are some sysfs nodes, under
-   /sys/devices/system/edac/mc/mc?/:
-
-   inject_addrmatch/*:
-      Controls the error injection mask register. It is possible to specify
-      several characteristics of the address to match an error code:
-         dimm = the affected dimm. Numbers are relative to a channel;
-         rank = the memory rank;
-         channel = the channel that will generate an error;
-         bank = the affected bank;
-         page = the page address;
-         column (or col) = the address column.
-      each of the above values can be set to "any" to match any valid value.
-
-      At driver init, all values are set to any.
-
-      For example, to generate an error at rank 1 of dimm 2, for any channel,
-      any bank, any page, any column:
-		echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
-		echo 1 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
-
-	To return to the default behaviour of matching any, you can do:
-		echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/dimm
-		echo any >/sys/devices/system/edac/mc/mc0/inject_addrmatch/rank
-
-   inject_eccmask:
-       specifies what bits will have troubles,
-
-   inject_section:
-       specifies what ECC cache section will get the error:
-		3 for both
-		2 for the highest
-		1 for the lowest
-
-   inject_type:
-       specifies the type of error, being a combination of the following bits:
-		bit 0 - repeat
-		bit 1 - ecc
-		bit 2 - parity
-
-       inject_enable starts the error generation when something different
-       than 0 is written.
-
-   All inject vars can be read. root permission is needed for write.
-
-   Datasheet states that the error will only be generated after a write on an
-   address that matches inject_addrmatch. It seems, however, that reading will
-   also produce an error.
-
-   For example, the following code will generate an error for any write access
-   at socket 0, on any DIMM/address on channel 2:
-
-   echo 2 >/sys/devices/system/edac/mc/mc0/inject_addrmatch/channel
-   echo 2 >/sys/devices/system/edac/mc/mc0/inject_type
-   echo 64 >/sys/devices/system/edac/mc/mc0/inject_eccmask
-   echo 3 >/sys/devices/system/edac/mc/mc0/inject_section
-   echo 1 >/sys/devices/system/edac/mc/mc0/inject_enable
-   dd if=/dev/mem of=/dev/null seek=16k bs=4k count=1 >& /dev/null
-
-   For socket 1, it is needed to replace "mc0" by "mc1" at the above
-   commands.
-
-   The generated error message will look like:
-
-   EDAC MC0: UE row 0, channel-a= 0 channel-b= 0 labels "-": NON_FATAL (addr = 0x0075b980, socket=0, Dimm=0, Channel=2, syndrome=0x00000040, count=1, Err=8c0000400001009f:4000080482 (read error: read ECC error))
-
-3) Nehalem specific Corrected Error memory counters
-
-   Nehalem have some registers to count memory errors. The driver uses those
-   registers to report Corrected Errors on devices with Registered Dimms.
-
-   However, those counters don't work with Unregistered Dimms. As the chipset
-   offers some counters that also work with UDIMMS (but with a worse level of
-   granularity than the default ones), the driver exposes those registers for
-   UDIMM memories.
-
-   They can be read by looking at the contents of all_channel_counts/
-
-   $ for i in /sys/devices/system/edac/mc/mc0/all_channel_counts/*; do echo $i; cat $i; done
-	/sys/devices/system/edac/mc/mc0/all_channel_counts/udimm0
-	0
-	/sys/devices/system/edac/mc/mc0/all_channel_counts/udimm1
-	0
-	/sys/devices/system/edac/mc/mc0/all_channel_counts/udimm2
-	0
-
-   What happens here is that errors on different csrows, but at the same
-   dimm number will increment the same counter.
-   So, in this memory mapping:
-	csrow0: channel 0, dimm0
-	csrow1: channel 0, dimm1
-	csrow2: channel 1, dimm0
-	csrow3: channel 2, dimm0
-   The hardware will increment udimm0 for an error at the first dimm at either
-	csrow0, csrow2  or csrow3;
-   The hardware will increment udimm1 for an error at the second dimm at either
-	csrow0, csrow2  or csrow3;
-   The hardware will increment udimm2 for an error at the third dimm at either
-	csrow0, csrow2  or csrow3;
-
-4) Standard error counters
-
-   The standard error counters are generated when an mcelog error is received
-   by the driver. Since, with udimm, this is counted by software, it is
-   possible that some errors could be lost. With rdimm's, they display the
-   contents of the registers
-
-AMD64_EDAC REFERENCE DOCUMENTS USED
------------------------------------
-amd64_edac module is based on the following documents
-(available from http://support.amd.com/en-us/search/tech-docs):
-
-1. Title:  BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD
-	   Opteron Processors
-   AMD publication #: 26094
-   Revision: 3.26
-   Link: http://support.amd.com/TechDocs/26094.PDF
-
-2. Title:  BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh
-	   Processors
-   AMD publication #: 32559
-   Revision: 3.00
-   Issue Date: May 2006
-   Link: http://support.amd.com/TechDocs/32559.pdf
-
-3. Title:  BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h
-	   Processors
-   AMD publication #: 31116
-   Revision: 3.00
-   Issue Date: September 07, 2007
-   Link: http://support.amd.com/TechDocs/31116.pdf
-
-4. Title: BIOS and Kernel Developer's Guide (BKDG) for AMD Family 15h
-	  Models 30h-3Fh Processors
-   AMD publication #: 49125
-   Revision: 3.06
-   Issue Date: 2/12/2015 (latest release)
-   Link: http://support.amd.com/TechDocs/49125_15h_Models_30h-3Fh_BKDG.pdf
-
-5. Title: BIOS and Kernel Developer's Guide (BKDG) for AMD Family 15h
-	  Models 60h-6Fh Processors
-   AMD publication #: 50742
-   Revision: 3.01
-   Issue Date: 7/23/2015 (latest release)
-   Link: http://support.amd.com/TechDocs/50742_15h_Models_60h-6Fh_BKDG.pdf
-
-6. Title: BIOS and Kernel Developer's Guide (BKDG) for AMD Family 16h
-	  Models 00h-0Fh Processors
-   AMD publication #: 48751
-   Revision: 3.03
-   Issue Date: 2/23/2015 (latest release)
-   Link: http://support.amd.com/TechDocs/48751_16h_bkdg.pdf
-
-CREDITS:
-========
-
-Written by Doug Thompson <dougthompson@xmission.com>
-7 Dec 2005
-17 Jul 2007	Updated
-
-(c) Mauro Carvalho Chehab
-05 Aug 2009	Nehalem interface
-
-EDAC authors/maintainers:
-
-	Doug Thompson, Dave Jiang, Dave Peterson et al,
-	Mauro Carvalho Chehab
-	Borislav Petkov
-	original author: Thayne Harbaugh
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/email-clients.txt linux-libre-4.10-rc8-gnu/Documentation/email-clients.txt
--- linux-libre-4.9-gnu/Documentation/email-clients.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/email-clients.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,319 +0,0 @@
-.. _email_clients:
-
-Email clients info for Linux
-============================
-
-Git
----
-
-These days most developers use ``git send-email`` instead of regular
-email clients.  The man page for this is quite good.  On the receiving
-end, maintainers use ``git am`` to apply the patches.
-
-If you are new to ``git`` then send your first patch to yourself.  Save it
-as raw text including all the headers.  Run ``git am raw_email.txt`` and
-then review the changelog with ``git log``.  When that works then send
-the patch to the appropriate mailing list(s).
-
-General Preferences
--------------------
-
-Patches for the Linux kernel are submitted via email, preferably as
-inline text in the body of the email.  Some maintainers accept
-attachments, but then the attachments should have content-type
-``text/plain``.  However, attachments are generally frowned upon because
-it makes quoting portions of the patch more difficult in the patch
-review process.
-
-Email clients that are used for Linux kernel patches should send the
-patch text untouched.  For example, they should not modify or delete tabs
-or spaces, even at the beginning or end of lines.
-
-Don't send patches with ``format=flowed``.  This can cause unexpected
-and unwanted line breaks.
-
-Don't let your email client do automatic word wrapping for you.
-This can also corrupt your patch.
-
-Email clients should not modify the character set encoding of the text.
-Emailed patches should be in ASCII or UTF-8 encoding only.
-If you configure your email client to send emails with UTF-8 encoding,
-you avoid some possible charset problems.
-
-Email clients should generate and maintain References: or In-Reply-To:
-headers so that mail threading is not broken.
-
-Copy-and-paste (or cut-and-paste) usually does not work for patches
-because tabs are converted to spaces.  Using xclipboard, xclip, and/or
-xcutsel may work, but it's best to test this for yourself or just avoid
-copy-and-paste.
-
-Don't use PGP/GPG signatures in mail that contains patches.
-This breaks many scripts that read and apply the patches.
-(This should be fixable.)
-
-It's a good idea to send a patch to yourself, save the received message,
-and successfully apply it with 'patch' before sending patches to Linux
-mailing lists.
-
-
-Some email client (MUA) hints
------------------------------
-
-Here are some specific MUA configuration hints for editing and sending
-patches for the Linux kernel.  These are not meant to be complete
-software package configuration summaries.
-
-
-Legend:
-
-- TUI = text-based user interface
-- GUI = graphical user interface
-
-Alpine (TUI)
-************
-
-Config options:
-
-In the :menuselection:`Sending Preferences` section:
-
-- :menuselection:`Do Not Send Flowed Text` must be ``enabled``
-- :menuselection:`Strip Whitespace Before Sending` must be ``disabled``
-
-When composing the message, the cursor should be placed where the patch
-should appear, and then pressing :kbd:`CTRL-R` let you specify the patch file
-to insert into the message.
-
-Claws Mail (GUI)
-****************
-
-Works. Some people use this successfully for patches.
-
-To insert a patch use :menuselection:`Message-->Insert` File (:kbd:`CTRL-I`)
-or an external editor.
-
-If the inserted patch has to be edited in the Claws composition window
-"Auto wrapping" in
-:menuselection:`Configuration-->Preferences-->Compose-->Wrapping` should be
-disabled.
-
-Evolution (GUI)
-***************
-
-Some people use this successfully for patches.
-
-When composing mail select: Preformat
-  from :menuselection:`Format-->Paragraph Style-->Preformatted` (:kbd:`CTRL-7`)
-  or the toolbar
-
-Then use:
-:menuselection:`Insert-->Text File...` (:kbd:`ALT-N x`)
-to insert the patch.
-
-You can also ``diff -Nru old.c new.c | xclip``, select
-:menuselection:`Preformat`, then paste with the middle button.
-
-Kmail (GUI)
-***********
-
-Some people use Kmail successfully for patches.
-
-The default setting of not composing in HTML is appropriate; do not
-enable it.
-
-When composing an email, under options, uncheck "word wrap". The only
-disadvantage is any text you type in the email will not be word-wrapped
-so you will have to manually word wrap text before the patch. The easiest
-way around this is to compose your email with word wrap enabled, then save
-it as a draft. Once you pull it up again from your drafts it is now hard
-word-wrapped and you can uncheck "word wrap" without losing the existing
-wrapping.
-
-At the bottom of your email, put the commonly-used patch delimiter before
-inserting your patch:  three hyphens (``---``).
-
-Then from the :menuselection:`Message` menu item, select insert file and
-choose your patch.
-As an added bonus you can customise the message creation toolbar menu
-and put the :menuselection:`insert file` icon there.
-
-Make the composer window wide enough so that no lines wrap. As of
-KMail 1.13.5 (KDE 4.5.4), KMail will apply word wrapping when sending
-the email if the lines wrap in the composer window. Having word wrapping
-disabled in the Options menu isn't enough. Thus, if your patch has very
-long lines, you must make the composer window very wide before sending
-the email. See: https://bugs.kde.org/show_bug.cgi?id=174034
-
-You can safely GPG sign attachments, but inlined text is preferred for
-patches so do not GPG sign them.  Signing patches that have been inserted
-as inlined text will make them tricky to extract from their 7-bit encoding.
-
-If you absolutely must send patches as attachments instead of inlining
-them as text, right click on the attachment and select properties, and
-highlight :menuselection:`Suggest automatic display` to make the attachment
-inlined to make it more viewable.
-
-When saving patches that are sent as inlined text, select the email that
-contains the patch from the message list pane, right click and select
-:menuselection:`save as`.  You can use the whole email unmodified as a patch
-if it was properly composed.  There is no option currently to save the email
-when you are actually viewing it in its own window -- there has been a request
-filed at kmail's bugzilla and hopefully this will be addressed.  Emails are
-saved as read-write for user only so you will have to chmod them to make them
-group and world readable if you copy them elsewhere.
-
-Lotus Notes (GUI)
-*****************
-
-Run away from it.
-
-Mutt (TUI)
-**********
-
-Plenty of Linux developers use ``mutt``, so it must work pretty well.
-
-Mutt doesn't come with an editor, so whatever editor you use should be
-used in a way that there are no automatic linebreaks.  Most editors have
-an :menuselection:`insert file` option that inserts the contents of a file
-unaltered.
-
-To use ``vim`` with mutt::
-
-  set editor="vi"
-
-If using xclip, type the command::
-
-  :set paste
-
-before middle button or shift-insert or use::
-
-  :r filename
-
-if you want to include the patch inline.
-(a)ttach works fine without ``set paste``.
-
-You can also generate patches with ``git format-patch`` and then use Mutt
-to send them::
-
-    $ mutt -H 0001-some-bug-fix.patch
-
-Config options:
-
-It should work with default settings.
-However, it's a good idea to set the ``send_charset`` to::
-
-  set send_charset="us-ascii:utf-8"
-
-Mutt is highly customizable. Here is a minimum configuration to start
-using Mutt to send patches through Gmail::
-
-  # .muttrc
-  # ================  IMAP ====================
-  set imap_user = 'yourusername@gmail.com'
-  set imap_pass = 'yourpassword'
-  set spoolfile = imaps://imap.gmail.com/INBOX
-  set folder = imaps://imap.gmail.com/
-  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
-  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
-  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
-
-  # ================  SMTP  ====================
-  set smtp_url = "smtp://username@smtp.gmail.com:587/"
-  set smtp_pass = $imap_pass
-  set ssl_force_tls = yes # Require encrypted connection
-
-  # ================  Composition  ====================
-  set editor = `echo \$EDITOR`
-  set edit_headers = yes  # See the headers when editing
-  set charset = UTF-8     # value of $LANG; also fallback for send_charset
-  # Sender, email address, and sign-off line must match
-  unset use_domain        # because joe@localhost is just embarrassing
-  set realname = "YOUR NAME"
-  set from = "username@gmail.com"
-  set use_from = yes
-
-The Mutt docs have lots more information:
-
-    http://dev.mutt.org/trac/wiki/UseCases/Gmail
-
-    http://dev.mutt.org/doc/manual.html
-
-Pine (TUI)
-**********
-
-Pine has had some whitespace truncation issues in the past, but these
-should all be fixed now.
-
-Use alpine (pine's successor) if you can.
-
-Config options:
-
-- ``quell-flowed-text`` is needed for recent versions
-- the ``no-strip-whitespace-before-send`` option is needed
-
-
-Sylpheed (GUI)
-**************
-
-- Works well for inlining text (or using attachments).
-- Allows use of an external editor.
-- Is slow on large folders.
-- Won't do TLS SMTP auth over a non-SSL connection.
-- Has a helpful ruler bar in the compose window.
-- Adding addresses to address book doesn't understand the display name
-  properly.
-
-Thunderbird (GUI)
-*****************
-
-Thunderbird is an Outlook clone that likes to mangle text, but there are ways
-to coerce it into behaving.
-
-- Allow use of an external editor:
-  The easiest thing to do with Thunderbird and patches is to use an
-  "external editor" extension and then just use your favorite ``$EDITOR``
-  for reading/merging patches into the body text.  To do this, download
-  and install the extension, then add a button for it using
-  :menuselection:`View-->Toolbars-->Customize...` and finally just click on it
-  when in the :menuselection:`Compose` dialog.
-
-  Please note that "external editor" requires that your editor must not
-  fork, or in other words, the editor must not return before closing.
-  You may have to pass additional flags or change the settings of your
-  editor. Most notably if you are using gvim then you must pass the -f
-  option to gvim by putting ``/usr/bin/gvim -f`` (if the binary is in
-  ``/usr/bin``) to the text editor field in :menuselection:`external editor`
-  settings. If you are using some other editor then please read its manual
-  to find out how to do this.
-
-To beat some sense out of the internal editor, do this:
-
-- Edit your Thunderbird config settings so that it won't use ``format=flowed``.
-  Go to :menuselection:`edit-->preferences-->advanced-->config editor` to bring up
-  the thunderbird's registry editor.
-
-- Set ``mailnews.send_plaintext_flowed`` to ``false``
-
-- Set ``mailnews.wraplength`` from ``72`` to ``0``
-
-- :menuselection:`View-->Message Body As-->Plain Text`
-
-- :menuselection:`View-->Character Encoding-->Unicode (UTF-8)`
-
-TkRat (GUI)
-***********
-
-Works.  Use "Insert file..." or external editor.
-
-Gmail (Web GUI)
-***************
-
-Does not work for sending patches.
-
-Gmail web client converts tabs to spaces automatically.
-
-At the same time it wraps lines every 78 chars with CRLF style line breaks
-although tab2space problem can be solved with external editor.
-
-Another problem is that Gmail will base64-encode any message that has a
-non-ASCII character. That includes things like European names.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/features/io/dma-api-debug/arch-support.txt linux-libre-4.10-rc8-gnu/Documentation/features/io/dma-api-debug/arch-support.txt
--- linux-libre-4.9-gnu/Documentation/features/io/dma-api-debug/arch-support.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/features/io/dma-api-debug/arch-support.txt	2017-02-12 16:03:20.000000000 -0500
@@ -36,5 +36,5 @@
     |          um: | TODO |
     |   unicore32: | TODO |
     |         x86: |  ok  |
-    |      xtensa: | TODO |
+    |      xtensa: |  ok  |
     -----------------------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/features/io/dma-contiguous/arch-support.txt linux-libre-4.10-rc8-gnu/Documentation/features/io/dma-contiguous/arch-support.txt
--- linux-libre-4.9-gnu/Documentation/features/io/dma-contiguous/arch-support.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/features/io/dma-contiguous/arch-support.txt	2017-02-12 16:03:20.000000000 -0500
@@ -36,5 +36,5 @@
     |          um: | TODO |
     |   unicore32: | TODO |
     |         x86: |  ok  |
-    |      xtensa: | TODO |
+    |      xtensa: |  ok  |
     -----------------------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/features/io/sg-chain/arch-support.txt linux-libre-4.10-rc8-gnu/Documentation/features/io/sg-chain/arch-support.txt
--- linux-libre-4.9-gnu/Documentation/features/io/sg-chain/arch-support.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/features/io/sg-chain/arch-support.txt	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@
     |         arch |status|
     -----------------------
     |       alpha: | TODO |
-    |         arc: | TODO |
+    |         arc: |  ok  |
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |       avr32: | TODO |
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/00-INDEX linux-libre-4.10-rc8-gnu/Documentation/filesystems/00-INDEX
--- linux-libre-4.9-gnu/Documentation/filesystems/00-INDEX	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/00-INDEX	2017-02-12 16:03:20.000000000 -0500
@@ -87,8 +87,6 @@ jfs.txt
 	- info and mount options for the JFS filesystem.
 locks.txt
 	- info on file locking implementations, flock() vs. fcntl(), etc.
-logfs.txt
-	- info on the LogFS flash filesystem.
 mandatory-locking.txt
 	- info on the Linux implementation of Sys V mandatory file locking.
 ncpfs.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/configfs/configfs.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/configfs/configfs.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/configfs/configfs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/configfs/configfs.txt	2017-02-12 16:03:20.000000000 -0500
@@ -174,7 +174,7 @@ among other things.  For that, it needs
 		void (*release)(struct config_item *);
 		int (*allow_link)(struct config_item *src,
 				  struct config_item *target);
-		int (*drop_link)(struct config_item *src,
+		void (*drop_link)(struct config_item *src,
 				 struct config_item *target);
 	};
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/dax.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/dax.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/dax.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/dax.txt	2017-02-12 16:03:20.000000000 -0500
@@ -58,22 +58,22 @@ Implementation Tips for Filesystem Write
 Filesystem support consists of
 - adding support to mark inodes as being DAX by setting the S_DAX flag in
   i_flags
-- implementing the direct_IO address space operation, and calling
-  dax_do_io() instead of blockdev_direct_IO() if S_DAX is set
+- implementing ->read_iter and ->write_iter operations which use dax_iomap_rw()
+  when inode has S_DAX flag set
 - implementing an mmap file operation for DAX files which sets the
   VM_MIXEDMAP and VM_HUGEPAGE flags on the VMA, and setting the vm_ops to
-  include handlers for fault, pmd_fault and page_mkwrite (which should
-  probably call dax_fault(), dax_pmd_fault() and dax_mkwrite(), passing the
-  appropriate get_block() callback)
-- calling dax_truncate_page() instead of block_truncate_page() for DAX files
-- calling dax_zero_page_range() instead of zero_user() for DAX files
+  include handlers for fault, pmd_fault, page_mkwrite, pfn_mkwrite. These
+  handlers should probably call dax_iomap_fault() (for fault and page_mkwrite
+  handlers), dax_iomap_pmd_fault(), dax_pfn_mkwrite() passing the appropriate
+  iomap operations.
+- calling iomap_zero_range() passing appropriate iomap operations instead of
+  block_truncate_page() for DAX files
 - ensuring that there is sufficient locking between reads, writes,
   truncates and page faults
 
-The get_block() callback passed to the DAX functions may return
-uninitialised extents.  If it does, it must ensure that simultaneous
-calls to get_block() (for example by a page-fault racing with a read()
-or a write()) work correctly.
+The iomap handlers for allocating blocks must make sure that allocated blocks
+are zeroed out and converted to written extents before being returned to avoid
+exposure of uninitialized data through mmap.
 
 These filesystems may be used for inspiration:
 - ext2: see Documentation/filesystems/ext2.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/ext4.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/ext4.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/ext4.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/ext4.txt	2017-02-12 16:03:20.000000000 -0500
@@ -351,14 +351,13 @@ nouid32			Disables 32-bit UIDs and GIDs.
 			interoperability  with  older kernels which only
 			store and expect 16-bit values.
 
-block_validity		This options allows to enables/disables the in-kernel
+block_validity(*)	These options enable or disable the in-kernel
 noblock_validity	facility for tracking filesystem metadata blocks
-			within internal data structures. This allows multi-
-			block allocator and other routines to quickly locate
-			extents which might overlap with filesystem metadata
-			blocks. This option is intended for debugging
-			purposes and since it negatively affects the
-			performance, it is off by default.
+			within internal data structures.  This allows multi-
+			block allocator and other routines to notice
+			bugs or corrupted allocation bitmaps which cause
+			blocks to be allocated which overlap with
+			filesystem metadata blocks.
 
 dioread_lock		Controls whether or not ext4 should use the DIO read
 dioread_nolock		locking. If the dioread_nolock option is specified
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/Locking linux-libre-4.10-rc8-gnu/Documentation/filesystems/Locking
--- linux-libre-4.9-gnu/Documentation/filesystems/Locking	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/Locking	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@ prototypes:
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
 	struct vfsmount *(*d_automount)(struct path *path);
-	int (*d_manage)(struct dentry *, bool);
+	int (*d_manage)(const struct path *, bool);
 	struct dentry *(*d_real)(struct dentry *, const struct inode *,
 				 unsigned int);
 
@@ -556,7 +556,7 @@ till "end_pgoff". ->map_pages() is calle
 not block.  If it's not possible to reach a page without blocking,
 filesystem should skip it. Filesystem should use do_set_pte() to setup
 page table entry. Pointer to entry associated with the page is passed in
-"pte" field in fault_env structure. Pointers to entries for other offsets
+"pte" field in vm_fault structure. Pointers to entries for other offsets
 should be calculated relative to "pte".
 
 	->page_mkwrite() is called when a previously read-only pte is
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/locks.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/locks.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/locks.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/locks.txt	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@ forever.
 
 This should not cause problems for anybody, since everybody using a
 2.1.x kernel should have updated their C library to a suitable version
-anyway (see the file "Documentation/Changes".)
+anyway (see the file "Documentation/process/changes.rst".)
 
 1.2 Allow Mixed Locks Again
 ---------------------------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/logfs.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/logfs.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/logfs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/logfs.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,241 +0,0 @@
-
-The LogFS Flash Filesystem
-==========================
-
-Specification
-=============
-
-Superblocks
------------
-
-Two superblocks exist at the beginning and end of the filesystem.
-Each superblock is 256 Bytes large, with another 3840 Bytes reserved
-for future purposes, making a total of 4096 Bytes.
-
-Superblock locations may differ for MTD and block devices.  On MTD the
-first non-bad block contains a superblock in the first 4096 Bytes and
-the last non-bad block contains a superblock in the last 4096 Bytes.
-On block devices, the first 4096 Bytes of the device contain the first
-superblock and the last aligned 4096 Byte-block contains the second
-superblock.
-
-For the most part, the superblocks can be considered read-only.  They
-are written only to correct errors detected within the superblocks,
-move the journal and change the filesystem parameters through tunefs.
-As a result, the superblock does not contain any fields that require
-constant updates, like the amount of free space, etc.
-
-Segments
---------
-
-The space in the device is split up into equal-sized segments.
-Segments are the primary write unit of LogFS.  Within each segments,
-writes happen from front (low addresses) to back (high addresses.  If
-only a partial segment has been written, the segment number, the
-current position within and optionally a write buffer are stored in
-the journal.
-
-Segments are erased as a whole.  Therefore Garbage Collection may be
-required to completely free a segment before doing so.
-
-Journal
---------
-
-The journal contains all global information about the filesystem that
-is subject to frequent change.  At mount time, it has to be scanned
-for the most recent commit entry, which contains a list of pointers to
-all currently valid entries.
-
-Object Store
-------------
-
-All space except for the superblocks and journal is part of the object
-store.  Each segment contains a segment header and a number of
-objects, each consisting of the object header and the payload.
-Objects are either inodes, directory entries (dentries), file data
-blocks or indirect blocks.
-
-Levels
-------
-
-Garbage collection (GC) may fail if all data is written
-indiscriminately.  One requirement of GC is that data is separated
-roughly according to the distance between the tree root and the data.
-Effectively that means all file data is on level 0, indirect blocks
-are on levels 1, 2, 3 4 or 5 for 1x, 2x, 3x, 4x or 5x indirect blocks,
-respectively.  Inode file data is on level 6 for the inodes and 7-11
-for indirect blocks.
-
-Each segment contains objects of a single level only.  As a result,
-each level requires its own separate segment to be open for writing.
-
-Inode File
-----------
-
-All inodes are stored in a special file, the inode file.  Single
-exception is the inode file's inode (master inode) which for obvious
-reasons is stored in the journal instead.  Instead of data blocks, the
-leaf nodes of the inode files are inodes.
-
-Aliases
--------
-
-Writes in LogFS are done by means of a wandering tree.  A naïve
-implementation would require that for each write or a block, all
-parent blocks are written as well, since the block pointers have
-changed.  Such an implementation would not be very efficient.
-
-In LogFS, the block pointer changes are cached in the journal by means
-of alias entries.  Each alias consists of its logical address - inode
-number, block index, level and child number (index into block) - and
-the changed data.  Any 8-byte word can be changes in this manner.
-
-Currently aliases are used for block pointers, file size, file used
-bytes and the height of an inodes indirect tree.
-
-Segment Aliases
----------------
-
-Related to regular aliases, these are used to handle bad blocks.
-Initially, bad blocks are handled by moving the affected segment
-content to a spare segment and noting this move in the journal with a
-segment alias, a simple (to, from) tupel.  GC will later empty this
-segment and the alias can be removed again.  This is used on MTD only.
-
-Vim
----
-
-By cleverly predicting the life time of data, it is possible to
-separate long-living data from short-living data and thereby reduce
-the GC overhead later.  Each type of distinc life expectency (vim) can
-have a separate segment open for writing.  Each (level, vim) tupel can
-be open just once.  If an open segment with unknown vim is encountered
-at mount time, it is closed and ignored henceforth.
-
-Indirect Tree
--------------
-
-Inodes in LogFS are similar to FFS-style filesystems with direct and
-indirect block pointers.  One difference is that LogFS uses a single
-indirect pointer that can be either a 1x, 2x, etc. indirect pointer.
-A height field in the inode defines the height of the indirect tree
-and thereby the indirection of the pointer.
-
-Another difference is the addressing of indirect blocks.  In LogFS,
-the first 16 pointers in the first indirect block are left empty,
-corresponding to the 16 direct pointers in the inode.  In ext2 (maybe
-others as well) the first pointer in the first indirect block
-corresponds to logical block 12, skipping the 12 direct pointers.
-So where ext2 is using arithmetic to better utilize space, LogFS keeps
-arithmetic simple and uses compression to save space.
-
-Compression
------------
-
-Both file data and metadata can be compressed.  Compression for file
-data can be enabled with chattr +c and disabled with chattr -c.  Doing
-so has no effect on existing data, but new data will be stored
-accordingly.  New inodes will inherit the compression flag of the
-parent directory.
-
-Metadata is always compressed.  However, the space accounting ignores
-this and charges for the uncompressed size.  Failing to do so could
-result in GC failures when, after moving some data, indirect blocks
-compress worse than previously.  Even on a 100% full medium, GC may
-not consume any extra space, so the compression gains are lost space
-to the user.
-
-However, they are not lost space to the filesystem internals.  By
-cheating the user for those bytes, the filesystem gained some slack
-space and GC will run less often and faster.
-
-Garbage Collection and Wear Leveling
-------------------------------------
-
-Garbage collection is invoked whenever the number of free segments
-falls below a threshold.  The best (known) candidate is picked based
-on the least amount of valid data contained in the segment.  All
-remaining valid data is copied elsewhere, thereby invalidating it.
-
-The GC code also checks for aliases and writes then back if their
-number gets too large.
-
-Wear leveling is done by occasionally picking a suboptimal segment for
-garbage collection.  If a stale segments erase count is significantly
-lower than the active segments' erase counts, it will be picked.  Wear
-leveling is rate limited, so it will never monopolize the device for
-more than one segment worth at a time.
-
-Values for "occasionally", "significantly lower" are compile time
-constants.
-
-Hashed directories
-------------------
-
-To satisfy efficient lookup(), directory entries are hashed and
-located based on the hash.  In order to both support large directories
-and not be overly inefficient for small directories, several hash
-tables of increasing size are used.  For each table, the hash value
-modulo the table size gives the table index.
-
-Tables sizes are chosen to limit the number of indirect blocks with a
-fully populated table to 0, 1, 2 or 3 respectively.  So the first
-table contains 16 entries, the second 512-16, etc.
-
-The last table is special in several ways.  First its size depends on
-the effective 32bit limit on telldir/seekdir cookies.  Since logfs
-uses the upper half of the address space for indirect blocks, the size
-is limited to 2^31.  Secondly the table contains hash buckets with 16
-entries each.
-
-Using single-entry buckets would result in birthday "attacks".  At
-just 2^16 used entries, hash collisions would be likely (P >= 0.5).
-My math skills are insufficient to do the combinatorics for the 17x
-collisions necessary to overflow a bucket, but testing showed that in
-10,000 runs the lowest directory fill before a bucket overflow was
-188,057,130 entries with an average of 315,149,915 entries.  So for
-directory sizes of up to a million, bucket overflows should be
-virtually impossible under normal circumstances.
-
-With carefully chosen filenames, it is obviously possible to cause an
-overflow with just 21 entries (4 higher tables + 16 entries + 1).  So
-there may be a security concern if a malicious user has write access
-to a directory.
-
-Open For Discussion
-===================
-
-Device Address Space
---------------------
-
-A device address space is used for caching.  Both block devices and
-MTD provide functions to either read a single page or write a segment.
-Partial segments may be written for data integrity, but where possible
-complete segments are written for performance on simple block device
-flash media.
-
-Meta Inodes
------------
-
-Inodes are stored in the inode file, which is just a regular file for
-most purposes.  At umount time, however, the inode file needs to
-remain open until all dirty inodes are written.  So
-generic_shutdown_super() may not close this inode, but shouldn't
-complain about remaining inodes due to the inode file either.  Same
-goes for mapping inode of the device address space.
-
-Currently logfs uses a hack that essentially copies part of fs/inode.c
-code over.  A general solution would be preferred.
-
-Indirect block mapping
-----------------------
-
-With compression, the block device (or mapping inode) cannot be used
-to cache indirect blocks.  Some other place is required.  Currently
-logfs uses the top half of each inode's address space.  The low 8TB
-(on 32bit) are filled with file data, the high 8TB are used for
-indirect blocks.
-
-One problem is that 16TB files created on 64bit systems actually have
-data in the top 8TB.  But files >16TB would cause problems anyway, so
-only the limit has changed.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/nfs/nfsroot.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/nfs/nfsroot.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/nfs/nfsroot.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/nfs/nfsroot.txt	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@ Updated 2006 by Horms <horms@verge.net.a
 In order to use a diskless system, such as an X-terminal or printer server
 for example, it is necessary for the root filesystem to be present on a
 non-disk device. This may be an initramfs (see Documentation/filesystems/
-ramfs-rootfs-initramfs.txt), a ramdisk (see Documentation/initrd.txt) or a
+ramfs-rootfs-initramfs.txt), a ramdisk (see Documentation/admin-guide/initrd.rst) or a
 filesystem mounted via NFS. The following text describes on how to use NFS
 for the root filesystem. For the rest of this text 'client' means the
 diskless system, and 'server' means the NFS server.
@@ -284,7 +284,7 @@ They depend on various facilities being
 	"kernel <relative-path-below /tftpboot>". The nfsroot parameters
 	are passed to the kernel by adding them to the "append" line.
 	It is common to use serial console in conjunction with pxeliunx,
-	see Documentation/serial-console.txt for more information.
+	see Documentation/admin-guide/serial-console.rst for more information.
 
 	For more information on isolinux, including how to create bootdisks
 	for prebuilt kernels, see http://syslinux.zytor.com/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/overlayfs.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/overlayfs.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/overlayfs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/overlayfs.txt	2017-02-12 16:03:20.000000000 -0500
@@ -66,7 +66,7 @@ At mount time, the two directories given
 "upperdir" are combined into a merged directory:
 
   mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\
-workdir=/work /merged
+  workdir=/work /merged
 
 The "workdir" needs to be an empty directory on the same filesystem
 as upperdir.
@@ -118,6 +118,7 @@ programs.
 
 seek offsets are assigned sequentially when the directories are read.
 Thus if
+
   - read part of a directory
   - remember an offset, and close the directory
   - re-open the directory some time later
@@ -130,6 +131,23 @@ directory.
 Readdir on directories that are not merged is simply handled by the
 underlying directory (upper or lower).
 
+renaming directories
+--------------------
+
+When renaming a directory that is on the lower layer or merged (i.e. the
+directory was not created on the upper layer to start with) overlayfs can
+handle it in two different ways:
+
+1. return EXDEV error: this error is returned by rename(2) when trying to
+   move a file or directory across filesystem boundaries.  Hence
+   applications are usually prepared to hande this error (mv(1) for example
+   recursively copies the directory tree).  This is the default behavior.
+
+2. If the "redirect_dir" feature is enabled, then the directory will be
+   copied up (but not the contents).  Then the "trusted.overlay.redirect"
+   extended attribute is set to the path of the original location from the
+   root of the overlay.  Finally the directory is moved to the new
+   location.
 
 Non-directories
 ---------------
@@ -185,13 +203,13 @@ filesystem, so both st_dev and st_ino of
 
 Any open files referring to this inode will access the old data.
 
-Any file locks (and leases) obtained before copy_up will not apply
-to the copied up file.
-
 If a file with multiple hard links is copied up, then this will
 "break" the link.  Changes will not be propagated to other names
 referring to the same inode.
 
+Unless "redirect_dir" feature is enabled, rename(2) on a lower or merged
+directory will fail with EXDEV.
+
 Changes to underlying filesystems
 ---------------------------------
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/porting linux-libre-4.10-rc8-gnu/Documentation/filesystems/porting
--- linux-libre-4.9-gnu/Documentation/filesystems/porting	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/porting	2017-02-12 16:03:20.000000000 -0500
@@ -596,3 +596,7 @@ in your dentry operations instead.
 [mandatory]
 	->rename() has an added flags argument.  Any flags not handled by the
         filesystem should result in EINVAL being returned.
+--
+[recommended]
+	->readlink is optional for symlinks.  Don't set, unless filesystem needs
+	to fake something for readlink(2).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/proc.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/proc.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/proc.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/proc.txt	2017-02-12 16:03:20.000000000 -0500
@@ -191,6 +191,7 @@ read the file /proc/PID/status:
   CapPrm: 0000000000000000
   CapEff: 0000000000000000
   CapBnd: ffffffffffffffff
+  NoNewPrivs:     0
   Seccomp:        0
   voluntary_ctxt_switches:        0
   nonvoluntary_ctxt_switches:     1
@@ -211,10 +212,11 @@ asynchronous manner and the value may no
 snapshot of a moment, you can see /proc/<pid>/smaps file and scan page table.
 It's slow but very precise.
 
-Table 1-2: Contents of the status files (as of 4.1)
+Table 1-2: Contents of the status files (as of 4.8)
 ..............................................................................
  Field                       Content
  Name                        filename of the executable
+ Umask                       file mode creation mask
  State                       state (R is running, S is sleeping, D is sleeping
                              in an uninterruptible wait, Z is zombie,
 			     T is traced or stopped)
@@ -225,7 +227,6 @@ Table 1-2: Contents of the status files
  TracerPid                   PID of process tracing this process (0 if not)
  Uid                         Real, effective, saved set, and  file system UIDs
  Gid                         Real, effective, saved set, and  file system GIDs
- Umask                       file mode creation mask
  FDSize                      number of file descriptor slots currently allocated
  Groups                      supplementary group list
  NStgid                      descendant namespace thread group ID hierarchy
@@ -235,6 +236,7 @@ Table 1-2: Contents of the status files
  VmPeak                      peak virtual memory size
  VmSize                      total program size
  VmLck                       locked memory size
+ VmPin                       pinned memory size
  VmHWM                       peak resident set size ("high water mark")
  VmRSS                       size of memory portions. It contains the three
                              following parts (VmRSS = RssAnon + RssFile + RssShmem)
@@ -262,6 +264,7 @@ Table 1-2: Contents of the status files
  CapPrm                      bitmap of permitted capabilities
  CapEff                      bitmap of effective capabilities
  CapBnd                      bitmap of capabilities bounding set
+ NoNewPrivs                  no_new_privs, like prctl(PR_GET_NO_NEW_PRIV, ...)
  Seccomp                     seccomp mode, like prctl(PR_GET_SECCOMP, ...)
  Cpus_allowed                mask of CPUs on which this process may run
  Cpus_allowed_list           Same as previous, but in "list format"
@@ -1305,7 +1308,16 @@ second).  The meanings of the columns ar
 - nice: niced processes executing in user mode
 - system: processes executing in kernel mode
 - idle: twiddling thumbs
-- iowait: waiting for I/O to complete
+- iowait: In a word, iowait stands for waiting for I/O to complete. But there
+  are several problems:
+  1. Cpu will not wait for I/O to complete, iowait is the time that a task is
+     waiting for I/O to complete. When cpu goes into idle state for
+     outstanding task io, another task will be scheduled on this CPU.
+  2. In a multi-core CPU, the task waiting for I/O to complete is not running
+     on any CPU, so the iowait of each CPU is difficult to calculate.
+  3. The value of iowait field in /proc/stat will decrease in certain
+     conditions.
+  So, the iowait is not reliable by reading from /proc/stat.
 - irq: servicing interrupts
 - softirq: servicing softirqs
 - steal: involuntary wait
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/sysfs-pci.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/sysfs-pci.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/sysfs-pci.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/sysfs-pci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@ that support it.  For example, a given b
      |   |-- resource0
      |   |-- resource1
      |   |-- resource2
+     |   |-- revision
      |   |-- rom
      |   |-- subsystem_device
      |   |-- subsystem_vendor
@@ -41,6 +42,7 @@ files, each with their own function.
        resource		   PCI resource host addresses (ascii, ro)
        resource0..N	   PCI resource N, if present (binary, mmap, rw[1])
        resource0_wc..N_wc  PCI WC map resource N, if prefetchable (binary, mmap)
+       revision		   PCI revision (ascii, ro)
        rom		   PCI ROM resource, if present (binary, ro)
        subsystem_device	   PCI subsystem device (ascii, ro)
        subsystem_vendor	   PCI subsystem vendor (ascii, ro)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/vfs.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/vfs.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/vfs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/vfs.txt	2017-02-12 16:03:20.000000000 -0500
@@ -451,9 +451,6 @@ otherwise noted.
 	exist; this is checked by the VFS.  Unlike plain rename,
 	source and target may be of different type.
 
-  readlink: called by the readlink(2) system call. Only required if
-	you want to support reading symbolic links
-
   get_link: called by the VFS to follow a symbolic link to the
 	inode it points to.  Only required if you want to support
 	symbolic links.  This method returns the symlink body
@@ -468,6 +465,12 @@ otherwise noted.
 	argument.  If request can't be handled without leaving RCU mode,
 	have it return ERR_PTR(-ECHILD).
 
+  readlink: this is now just an override for use by readlink(2) for the
+	cases when ->get_link uses nd_jump_link() or object is not in
+	fact a symlink.  Normally filesystems should only implement
+	->get_link for symlinks and readlink(2) will automatically use
+	that.
+
   permission: called by the VFS to check for access rights on a POSIX-like
   	filesystem.
 
@@ -948,7 +951,7 @@ struct dentry_operations {
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)(struct dentry *, char *, int);
 	struct vfsmount *(*d_automount)(struct path *);
-	int (*d_manage)(struct dentry *, bool);
+	int (*d_manage)(const struct path *, bool);
 	struct dentry *(*d_real)(struct dentry *, const struct inode *,
 				 unsigned int);
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/filesystems/xfs.txt linux-libre-4.10-rc8-gnu/Documentation/filesystems/xfs.txt
--- linux-libre-4.9-gnu/Documentation/filesystems/xfs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/filesystems/xfs.txt	2017-02-12 16:03:20.000000000 -0500
@@ -51,13 +51,6 @@ default behaviour.
 	CRC enabled filesystems always use the attr2 format, and so
 	will reject the noattr2 mount option if it is set.
 
-  barrier (*)
-  nobarrier
-	Enables/disables the use of block layer write barriers for
-	writes into the journal and for data integrity operations.
-	This allows for drive level write caching to be enabled, for
-	devices that support write barriers.
-
   discard
   nodiscard (*)
 	Enable/disable the issuing of commands to let the block
@@ -228,7 +221,10 @@ default behaviour.
 Deprecated Mount Options
 ========================
 
-None at present.
+  Name				Removal Schedule
+  ----				----------------
+  barrier			no earlier than v4.15
+  nobarrier			no earlier than v4.15
 
 
 Removed Mount Options
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/fpga/fpga-mgr.txt linux-libre-4.10-rc8-gnu/Documentation/fpga/fpga-mgr.txt
--- linux-libre-4.9-gnu/Documentation/fpga/fpga-mgr.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/fpga/fpga-mgr.txt	2017-02-12 16:03:20.000000000 -0500
@@ -18,31 +18,37 @@ API Functions:
 To program the FPGA from a file or from a buffer:
 -------------------------------------------------
 
-	int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags,
+	int fpga_mgr_buf_load(struct fpga_manager *mgr,
+			      struct fpga_image_info *info,
 		              const char *buf, size_t count);
 
 Load the FPGA from an image which exists as a buffer in memory.
 
-	int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags,
+	int fpga_mgr_firmware_load(struct fpga_manager *mgr,
+				   struct fpga_image_info *info,
 		                   const char *image_name);
 
 Load the FPGA from an image which exists as a file.  The image file must be on
-the firmware search path (see the firmware class documentation).
-
-For both these functions, flags == 0 for normal full reconfiguration or
-FPGA_MGR_PARTIAL_RECONFIG for partial reconfiguration.  If successful, the FPGA
-ends up in operating mode.  Return 0 on success or a negative error code.
+the firmware search path (see the firmware class documentation).  If successful,
+the FPGA ends up in operating mode.  Return 0 on success or a negative error
+code.
 
+A FPGA design contained in a FPGA image file will likely have particulars that
+affect how the image is programmed to the FPGA.  These are contained in struct
+fpga_image_info.  Currently the only such particular is a single flag bit
+indicating whether the image is for full or partial reconfiguration.
 
 To get/put a reference to a FPGA manager:
 -----------------------------------------
 
 	struct fpga_manager *of_fpga_mgr_get(struct device_node *node);
+	struct fpga_manager *fpga_mgr_get(struct device *dev);
+
+Given a DT node or device, get an exclusive reference to a FPGA manager.
 
 	void fpga_mgr_put(struct fpga_manager *mgr);
 
-Given a DT node, get an exclusive reference to a FPGA manager or release
-the reference.
+Release the reference.
 
 
 To register or unregister the low level FPGA-specific driver:
@@ -70,8 +76,11 @@ struct device_node *mgr_node = ...
 char *buf = ...
 int count = ...
 
+/* struct with information about the FPGA image to program. */
+struct fpga_image_info info;
+
 /* flags indicates whether to do full or partial reconfiguration */
-int flags = 0;
+info.flags = 0;
 
 int ret;
 
@@ -79,7 +88,7 @@ int ret;
 struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node);
 
 /* Load the buffer to the FPGA */
-ret = fpga_mgr_buf_load(mgr, flags, buf, count);
+ret = fpga_mgr_buf_load(mgr, &info, buf, count);
 
 /* Release the FPGA manager */
 fpga_mgr_put(mgr);
@@ -96,8 +105,11 @@ struct device_node *mgr_node = ...
 /* FPGA image is in this file which is in the firmware search path */
 const char *path = "fpga-image-9.rbf"
 
+/* struct with information about the FPGA image to program. */
+struct fpga_image_info info;
+
 /* flags indicates whether to do full or partial reconfiguration */
-int flags = 0;
+info.flags = 0;
 
 int ret;
 
@@ -105,7 +117,7 @@ int ret;
 struct fpga_manager *mgr = of_fpga_mgr_get(mgr_node);
 
 /* Get the firmware image (path) and load it to the FPGA */
-ret = fpga_mgr_firmware_load(mgr, flags, path);
+ret = fpga_mgr_firmware_load(mgr, &info, path);
 
 /* Release the FPGA manager */
 fpga_mgr_put(mgr);
@@ -157,7 +169,10 @@ The programming sequence is:
  2. .write (may be called once or multiple times)
  3. .write_complete
 
-The .write_init function will prepare the FPGA to receive the image data.
+The .write_init function will prepare the FPGA to receive the image data.  The
+buffer passed into .write_init will be atmost .initial_header_size bytes long,
+if the whole bitstream is not immediately available then the core code will
+buffer up at least this much before starting.
 
 The .write function writes a buffer to the FPGA. The buffer may be contain the
 whole FPGA image or may be a smaller chunk of an FPGA image.  In the latter
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/frv/booting.txt linux-libre-4.10-rc8-gnu/Documentation/frv/booting.txt
--- linux-libre-4.9-gnu/Documentation/frv/booting.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/frv/booting.txt	2017-02-12 16:03:20.000000000 -0500
@@ -119,7 +119,7 @@ separated by spaces:
 	253:0		Device with major 253 and minor 0
 
       Authoritative information can be found in
-      "Documentation/kernel-parameters.txt".
+      "Documentation/admin-guide/kernel-parameters.rst".
 
   (*) rw
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpio/driver.txt linux-libre-4.10-rc8-gnu/Documentation/gpio/driver.txt
--- linux-libre-4.9-gnu/Documentation/gpio/driver.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpio/driver.txt	2017-02-12 16:03:20.000000000 -0500
@@ -175,8 +175,8 @@ The IRQ portions of the GPIO block are i
 the header <linux/irq.h>. So basically such a driver is utilizing two sub-
 systems simultaneously: gpio and irq.
 
-RT_FULL: GPIO driver should not use spinlock_t or any sleepable APIs
-(like PM runtime) as part of its irq_chip implementation on -RT.
+RT_FULL: a realtime compliant GPIO driver should not use spinlock_t or any
+sleepable APIs (like PM runtime) as part of its irq_chip implementation.
 - spinlock_t should be replaced with raw_spinlock_t [1].
 - If sleepable APIs have to be used, these can be done from the .irq_bus_lock()
   and .irq_bus_unlock() callbacks, as these are the only slowpath callbacks
@@ -185,33 +185,32 @@ RT_FULL: GPIO driver should not use spin
 GPIO irqchips usually fall in one of two categories:
 
 * CHAINED GPIO irqchips: these are usually the type that is embedded on
-  an SoC. This means that there is a fast IRQ handler for the GPIOs that
+  an SoC. This means that there is a fast IRQ flow handler for the GPIOs that
   gets called in a chain from the parent IRQ handler, most typically the
-  system interrupt controller. This means the GPIO irqchip is registered
-  using irq_set_chained_handler() or the corresponding
-  gpiochip_set_chained_irqchip() helper function, and the GPIO irqchip
-  handler will be called immediately from the parent irqchip, while
-  holding the IRQs disabled. The GPIO irqchip will then end up calling
-  something like this sequence in its interrupt handler:
+  system interrupt controller. This means that the GPIO irqchip handler will
+  be called immediately from the parent irqchip, while holding the IRQs
+  disabled. The GPIO irqchip will then end up calling something like this
+  sequence in its interrupt handler:
 
-  static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+  static irqreturn_t foo_gpio_irq(int irq, void *data)
       chained_irq_enter(...);
       generic_handle_irq(...);
       chained_irq_exit(...);
 
   Chained GPIO irqchips typically can NOT set the .can_sleep flag on
-  struct gpio_chip, as everything happens directly in the callbacks.
+  struct gpio_chip, as everything happens directly in the callbacks: no
+  slow bus traffic like I2C can be used.
 
   RT_FULL: Note, chained IRQ handlers will not be forced threaded on -RT.
   As result, spinlock_t or any sleepable APIs (like PM runtime) can't be used
   in chained IRQ handler.
-  if required (and if it can't be converted to the nested threaded GPIO irqchip)
-  - chained IRQ handler can be converted to generic irq handler and this way
-  it will be threaded IRQ handler on -RT and hard IRQ handler on non-RT
+  If required (and if it can't be converted to the nested threaded GPIO irqchip)
+  a chained IRQ handler can be converted to generic irq handler and this way
+  it will be a threaded IRQ handler on -RT and a hard IRQ handler on non-RT
   (for example, see [3]).
   Know W/A: The generic_handle_irq() is expected to be called with IRQ disabled,
-  so IRQ core will complain if it will be called from IRQ handler which is
-  forced thread. The "fake?" raw lock can be used to W/A this problem:
+  so the IRQ core will complain if it is called from an IRQ handler which is
+  forced to a thread. The "fake?" raw lock can be used to W/A this problem:
 
 	raw_spinlock_t wa_lock;
 	static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
@@ -243,7 +242,7 @@ GPIO irqchips usually fall in one of two
   by the driver. The hallmark of this driver is to call something like
   this in its interrupt handler:
 
-  static irqreturn_t tc3589x_gpio_irq(int irq, void *data)
+  static irqreturn_t foo_gpio_irq(int irq, void *data)
       ...
       handle_nested_irq(irq);
 
@@ -256,23 +255,31 @@ associated irqdomain and resource alloca
 some helpers that can be enabled by selecting the GPIOLIB_IRQCHIP Kconfig
 symbol:
 
-* gpiochip_irqchip_add(): adds an irqchip to a gpiochip. It will pass
+* gpiochip_irqchip_add(): adds a chained irqchip to a gpiochip. It will pass
   the struct gpio_chip* for the chip to all IRQ callbacks, so the callbacks
   need to embed the gpio_chip in its state container and obtain a pointer
   to the container using container_of().
   (See Documentation/driver-model/design-patterns.txt)
 
-  If there is a need to exclude certain GPIOs from the IRQ domain, one can
-  set .irq_need_valid_mask of the gpiochip before gpiochip_add_data() is
-  called. This allocates .irq_valid_mask with as many bits set as there are
-  GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this
-  mask. The mask must be filled in before gpiochip_irqchip_add() is called.
+* gpiochip_irqchip_add_nested(): adds a nested irqchip to a gpiochip.
+  Apart from that it works exactly like the chained irqchip.
 
 * gpiochip_set_chained_irqchip(): sets up a chained irq handler for a
   gpio_chip from a parent IRQ and passes the struct gpio_chip* as handler
   data. (Notice handler data, since the irqchip data is likely used by the
-  parent irqchip!) This is for the chained type of chip. This is also used
-  to set up a nested irqchip if NULL is passed as handler.
+  parent irqchip!).
+
+* gpiochip_set_nested_irqchip(): sets up a nested irq handler for a
+  gpio_chip from a parent IRQ. As the parent IRQ has usually been
+  explicitly requested by the driver, this does very little more than
+  mark all the child IRQs as having the other IRQ as parent.
+
+If there is a need to exclude certain GPIOs from the IRQ domain, you can
+set .irq_need_valid_mask of the gpiochip before gpiochip_add_data() is
+called. This allocates an .irq_valid_mask with as many bits set as there
+are GPIOs in the chip. Drivers can exclude GPIOs by clearing bits from this
+mask. The mask must be filled in before gpiochip_irqchip_add() or
+gpiochip_irqchip_add_nested() is called.
 
 To use the helpers please keep the following in mind:
 
@@ -323,6 +330,9 @@ When implementing an irqchip inside a GP
 typically be called in the .startup() and .shutdown() callbacks from the
 irqchip.
 
+When using the gpiolib irqchip helpers, these callback are automatically
+assigned.
+
 Real-Time compliance for GPIO IRQ chips
 ---------------------------------------
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/conf.py linux-libre-4.10-rc8-gnu/Documentation/gpu/conf.py
--- linux-libre-4.9-gnu/Documentation/gpu/conf.py	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -3,3 +3,8 @@
 project = "Linux GPU Driver Developer's Guide"
 
 tags.add("subproject")
+
+latex_documents = [
+    ('index', 'gpu.tex', project,
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/drm-internals.rst linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-internals.rst
--- linux-libre-4.9-gnu/Documentation/gpu/drm-internals.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-internals.rst	2017-02-12 16:03:20.000000000 -0500
@@ -143,6 +143,9 @@ Device Instance and Driver Handling
 .. kernel-doc:: drivers/gpu/drm/drm_drv.c
    :export:
 
+.. kernel-doc:: include/drm/drm_drv.h
+   :internal:
+
 Driver Load
 -----------
 
@@ -350,6 +353,23 @@ how the ioctl is allowed to be called.
 .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
    :export:
 
+
+Misc Utilities
+==============
+
+Printer
+-------
+
+.. kernel-doc:: include/drm/drm_print.h
+   :doc: print
+
+.. kernel-doc:: include/drm/drm_print.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_print.c
+   :export:
+
+
 Legacy Support Code
 ===================
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/drm-kms-helpers.rst linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-kms-helpers.rst
--- linux-libre-4.9-gnu/Documentation/gpu/drm-kms-helpers.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-kms-helpers.rst	2017-02-12 16:03:20.000000000 -0500
@@ -63,6 +63,9 @@ Atomic State Reset and Initialization
 .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
    :doc: atomic state reset and initialization
 
+Helper Functions Reference
+--------------------------
+
 .. kernel-doc:: include/drm/drm_atomic_helper.h
    :internal:
 
@@ -261,14 +264,6 @@ Plane Helper Reference
 .. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
    :export:
 
-Tile group
-==========
-
-# FIXME: This should probably be moved into a property documentation section
-
-.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
-   :doc: Tile group
-
 Auxiliary Modeset Helpers
 =========================
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/drm-kms.rst linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-kms.rst
--- linux-libre-4.9-gnu/Documentation/gpu/drm-kms.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-kms.rst	2017-02-12 16:03:20.000000000 -0500
@@ -15,25 +15,24 @@ be setup by initializing the following f
 -  struct drm_mode_config_funcs \*funcs;
    Mode setting functions.
 
-Modeset Base Object Abstraction
-===============================
+Mode Configuration
 
-.. kernel-doc:: include/drm/drm_mode_object.h
-   :internal:
+KMS Core Structures and Functions
+=================================
 
-.. kernel-doc:: drivers/gpu/drm/drm_mode_object.c
+.. kernel-doc:: drivers/gpu/drm/drm_mode_config.c
    :export:
 
-KMS Data Structures
-===================
-
-.. kernel-doc:: include/drm/drm_crtc.h
+.. kernel-doc:: include/drm/drm_mode_config.h
    :internal:
 
-KMS API Functions
-=================
+Modeset Base Object Abstraction
+===============================
 
-.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
+.. kernel-doc:: include/drm/drm_mode_object.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_mode_object.c
    :export:
 
 Atomic Mode Setting Function Reference
@@ -45,6 +44,15 @@ Atomic Mode Setting Function Reference
 .. kernel-doc:: include/drm/drm_atomic.h
    :internal:
 
+CRTC Abstraction
+================
+
+.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
+   :export:
+
+.. kernel-doc:: include/drm/drm_crtc.h
+   :internal:
+
 Frame Buffer Abstraction
 ========================
 
@@ -63,52 +71,17 @@ Frame Buffer Functions Reference
 DRM Format Handling
 ===================
 
+.. kernel-doc:: include/drm/drm_fourcc.h
+   :internal:
+
 .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c
    :export:
 
 Dumb Buffer Objects
 ===================
 
-The KMS API doesn't standardize backing storage object creation and
-leaves it to driver-specific ioctls. Furthermore actually creating a
-buffer object even for GEM-based drivers is done through a
-driver-specific ioctl - GEM only has a common userspace interface for
-sharing and destroying objects. While not an issue for full-fledged
-graphics stacks that include device-specific userspace components (in
-libdrm for instance), this limit makes DRM-based early boot graphics
-unnecessarily complex.
-
-Dumb objects partly alleviate the problem by providing a standard API to
-create dumb buffers suitable for scanout, which can then be used to
-create KMS frame buffers.
-
-To support dumb objects drivers must implement the dumb_create,
-dumb_destroy and dumb_map_offset operations.
-
--  int (\*dumb_create)(struct drm_file \*file_priv, struct
-   drm_device \*dev, struct drm_mode_create_dumb \*args);
-   The dumb_create operation creates a driver object (GEM or TTM
-   handle) suitable for scanout based on the width, height and depth
-   from the struct :c:type:`struct drm_mode_create_dumb
-   <drm_mode_create_dumb>` argument. It fills the argument's
-   handle, pitch and size fields with a handle for the newly created
-   object and its line pitch and size in bytes.
-
--  int (\*dumb_destroy)(struct drm_file \*file_priv, struct
-   drm_device \*dev, uint32_t handle);
-   The dumb_destroy operation destroys a dumb object created by
-   dumb_create.
-
--  int (\*dumb_map_offset)(struct drm_file \*file_priv, struct
-   drm_device \*dev, uint32_t handle, uint64_t \*offset);
-   The dumb_map_offset operation associates an mmap fake offset with
-   the object given by the handle and returns it. Drivers must use the
-   :c:func:`drm_gem_create_mmap_offset()` function to associate
-   the fake offset as described in ?.
-
-Note that dumb objects may not be used for gpu acceleration, as has been
-attempted on some ARM embedded platforms. Such drivers really must have
-a hardware-specific ioctl to allocate suitable buffer objects.
+.. kernel-doc:: drivers/gpu/drm/drm_dumb_buffers.c
+   :doc: overview
 
 Plane Abstraction
 =================
@@ -215,7 +188,7 @@ Connectors state change detection must b
 Output discovery and initialization example
 -------------------------------------------
 
-::
+.. code-block:: c
 
     void intel_crt_init(struct drm_device *dev)
     {
@@ -287,6 +260,12 @@ Property Types and Blob Property Support
 .. kernel-doc:: drivers/gpu/drm/drm_property.c
    :export:
 
+Standard Connector Properties
+-----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_connector.c
+   :doc: standard connector properties
+
 Plane Composition Properties
 ----------------------------
 
@@ -308,6 +287,18 @@ Color Management Properties
 .. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
    :export:
 
+Tile Group Property
+-------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_connector.c
+   :doc: Tile group
+
+Explicit Fencing Properties
+---------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
+   :doc: explicit fencing properties
+
 Existing KMS Properties
 -----------------------
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/drm-mm.rst linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-mm.rst
--- linux-libre-4.9-gnu/Documentation/gpu/drm-mm.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-mm.rst	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@ the radeon_ttm.c file for an example of
 
 The ttm_global_reference structure is made up of several fields:
 
-::
+.. code-block:: c
 
               struct ttm_global_reference {
                       enum ttm_global_types global_type;
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/drm-uapi.rst linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-uapi.rst
--- linux-libre-4.9-gnu/Documentation/gpu/drm-uapi.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/drm-uapi.rst	2017-02-12 16:03:20.000000000 -0500
@@ -216,3 +216,9 @@ interfaces. Especially since all hardwar
 userspace are driver specific for efficiency and other reasons these
 interfaces can be rather substantial. Hence every driver has its own
 chapter.
+
+Testing and validation
+======================
+
+.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
+   :doc: CRC ABI
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/i915.rst linux-libre-4.10-rc8-gnu/Documentation/gpu/i915.rst
--- linux-libre-4.9-gnu/Documentation/gpu/i915.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/i915.rst	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,15 @@ Intel GVT-g Guest Support(vGPU)
 .. kernel-doc:: drivers/gpu/drm/i915/i915_vgpu.c
    :internal:
 
+Intel GVT-g Host Support(vGPU device model)
+-------------------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c
+   :doc: Intel GVT-g host support
+
+.. kernel-doc:: drivers/gpu/drm/i915/intel_gvt.c
+   :internal:
+
 Display Hardware Handling
 =========================
 
@@ -180,7 +189,7 @@ Display Refresh Rate Switching (DRRS)
 DPIO
 ----
 
-.. kernel-doc:: drivers/gpu/drm/i915/i915_reg.h
+.. kernel-doc:: drivers/gpu/drm/i915/intel_dpio_phy.c
    :doc: DPIO
 
 CSR firmware support for DMC
@@ -249,19 +258,19 @@ Global GTT views
 GTT Fences and Swizzling
 ------------------------
 
-.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence.c
+.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence_reg.c
    :internal:
 
 Global GTT Fence Handling
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence.c
+.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence_reg.c
    :doc: fence register handling
 
 Hardware Tiling and Swizzling Details
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence.c
+.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_fence_reg.c
    :doc: tiling swizzling details
 
 Object Tiling IOCTLs
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/gpu/index.rst linux-libre-4.10-rc8-gnu/Documentation/gpu/index.rst
--- linux-libre-4.9-gnu/Documentation/gpu/index.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/gpu/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@ Linux GPU Driver Developer's Guide
    vga-switcheroo
    vgaarbiter
 
-.. only::  subproject
+.. only::  subproject and html
 
    Indices
    =======
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/HOWTO linux-libre-4.10-rc8-gnu/Documentation/HOWTO
--- linux-libre-4.9-gnu/Documentation/HOWTO	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/HOWTO	1969-12-31 19:00:00.000000000 -0500
@@ -1,652 +0,0 @@
-HOWTO do Linux kernel development
-=================================
-
-This is the be-all, end-all document on this topic.  It contains
-instructions on how to become a Linux kernel developer and how to learn
-to work with the Linux kernel development community.  It tries to not
-contain anything related to the technical aspects of kernel programming,
-but will help point you in the right direction for that.
-
-If anything in this document becomes out of date, please send in patches
-to the maintainer of this file, who is listed at the bottom of the
-document.
-
-
-Introduction
-------------
-
-So, you want to learn how to become a Linux kernel developer?  Or you
-have been told by your manager, "Go write a Linux driver for this
-device."  This document's goal is to teach you everything you need to
-know to achieve this by describing the process you need to go through,
-and hints on how to work with the community.  It will also try to
-explain some of the reasons why the community works like it does.
-
-The kernel is written mostly in C, with some architecture-dependent
-parts written in assembly. A good understanding of C is required for
-kernel development.  Assembly (any architecture) is not required unless
-you plan to do low-level development for that architecture.  Though they
-are not a good substitute for a solid C education and/or years of
-experience, the following books are good for, if anything, reference:
-
- - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
- - "Practical C Programming" by Steve Oualline [O'Reilly]
- - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
-
-The kernel is written using GNU C and the GNU toolchain.  While it
-adheres to the ISO C89 standard, it uses a number of extensions that are
-not featured in the standard.  The kernel is a freestanding C
-environment, with no reliance on the standard C library, so some
-portions of the C standard are not supported.  Arbitrary long long
-divisions and floating point are not allowed.  It can sometimes be
-difficult to understand the assumptions the kernel has on the toolchain
-and the extensions that it uses, and unfortunately there is no
-definitive reference for them.  Please check the gcc info pages (`info
-gcc`) for some information on them.
-
-Please remember that you are trying to learn how to work with the
-existing development community.  It is a diverse group of people, with
-high standards for coding, style and procedure.  These standards have
-been created over time based on what they have found to work best for
-such a large and geographically dispersed team.  Try to learn as much as
-possible about these standards ahead of time, as they are well
-documented; do not expect people to adapt to you or your company's way
-of doing things.
-
-
-Legal Issues
-------------
-
-The Linux kernel source code is released under the GPL.  Please see the
-file, COPYING, in the main directory of the source tree, for details on
-the license.  If you have further questions about the license, please
-contact a lawyer, and do not ask on the Linux kernel mailing list.  The
-people on the mailing lists are not lawyers, and you should not rely on
-their statements on legal matters.
-
-For common questions and answers about the GPL, please see:
-
-	https://www.gnu.org/licenses/gpl-faq.html
-
-
-Documentation
--------------
-
-The Linux kernel source tree has a large range of documents that are
-invaluable for learning how to interact with the kernel community.  When
-new features are added to the kernel, it is recommended that new
-documentation files are also added which explain how to use the feature.
-When a kernel change causes the interface that the kernel exposes to
-userspace to change, it is recommended that you send the information or
-a patch to the manual pages explaining the change to the manual pages
-maintainer at mtk.manpages@gmail.com, and CC the list
-linux-api@vger.kernel.org.
-
-Here is a list of files that are in the kernel source tree that are
-required reading:
-
-  README
-    This file gives a short background on the Linux kernel and describes
-    what is necessary to do to configure and build the kernel.  People
-    who are new to the kernel should start here.
-
-  :ref:`Documentation/Changes <changes>`
-    This file gives a list of the minimum levels of various software
-    packages that are necessary to build and run the kernel
-    successfully.
-
-  :ref:`Documentation/CodingStyle <codingstyle>`
-    This describes the Linux kernel coding style, and some of the
-    rationale behind it. All new code is expected to follow the
-    guidelines in this document. Most maintainers will only accept
-    patches if these rules are followed, and many people will only
-    review code if it is in the proper style.
-
-  :ref:`Documentation/SubmittingPatches <submittingpatches>` and :ref:`Documentation/SubmittingDrivers <submittingdrivers>`
-    These files describe in explicit detail how to successfully create
-    and send a patch, including (but not limited to):
-
-       - Email contents
-       - Email format
-       - Who to send it to
-
-    Following these rules will not guarantee success (as all patches are
-    subject to scrutiny for content and style), but not following them
-    will almost always prevent it.
-
-    Other excellent descriptions of how to create patches properly are:
-
-	"The Perfect Patch"
-		https://www.ozlabs.org/~akpm/stuff/tpp.txt
-
-	"Linux kernel patch submission format"
-		http://linux.yyz.us/patch-format.html
-
-  :ref:`Documentation/stable_api_nonsense.txt <stable_api_nonsense>`
-    This file describes the rationale behind the conscious decision to
-    not have a stable API within the kernel, including things like:
-
-      - Subsystem shim-layers (for compatibility?)
-      - Driver portability between Operating Systems.
-      - Mitigating rapid change within the kernel source tree (or
-	preventing rapid change)
-
-    This document is crucial for understanding the Linux development
-    philosophy and is very important for people moving to Linux from
-    development on other Operating Systems.
-
-  :ref:`Documentation/SecurityBugs <securitybugs>`
-    If you feel you have found a security problem in the Linux kernel,
-    please follow the steps in this document to help notify the kernel
-    developers, and help solve the issue.
-
-  :ref:`Documentation/ManagementStyle <managementstyle>`
-    This document describes how Linux kernel maintainers operate and the
-    shared ethos behind their methodologies.  This is important reading
-    for anyone new to kernel development (or anyone simply curious about
-    it), as it resolves a lot of common misconceptions and confusion
-    about the unique behavior of kernel maintainers.
-
-  :ref:`Documentation/stable_kernel_rules.txt <stable_kernel_rules>`
-    This file describes the rules on how the stable kernel releases
-    happen, and what to do if you want to get a change into one of these
-    releases.
-
-  :ref:`Documentation/kernel-docs.txt <kernel_docs>`
-    A list of external documentation that pertains to kernel
-    development.  Please consult this list if you do not find what you
-    are looking for within the in-kernel documentation.
-
-  :ref:`Documentation/applying-patches.txt <applying_patches>`
-    A good introduction describing exactly what a patch is and how to
-    apply it to the different development branches of the kernel.
-
-The kernel also has a large number of documents that can be
-automatically generated from the source code itself or from
-ReStructuredText markups (ReST), like this one. This includes a
-full description of the in-kernel API, and rules on how to handle
-locking properly.
-
-All such documents can be generated as PDF or HTML by running::
-
-	make pdfdocs
-	make htmldocs
-
-respectively from the main kernel source directory.
-
-The documents that uses ReST markup will be generated at Documentation/output.
-They can also be generated on LaTeX and ePub formats with::
-
-	make latexdocs
-	make epubdocs
-
-Currently, there are some documents written on DocBook that are in
-the process of conversion to ReST. Such documents will be created in the
-Documentation/DocBook/ directory and can be generated also as
-Postscript or man pages by running::
-
-	make psdocs
-	make mandocs
-
-Becoming A Kernel Developer
----------------------------
-
-If you do not know anything about Linux kernel development, you should
-look at the Linux KernelNewbies project:
-
-	https://kernelnewbies.org
-
-It consists of a helpful mailing list where you can ask almost any type
-of basic kernel development question (make sure to search the archives
-first, before asking something that has already been answered in the
-past.)  It also has an IRC channel that you can use to ask questions in
-real-time, and a lot of helpful documentation that is useful for
-learning about Linux kernel development.
-
-The website has basic information about code organization, subsystems,
-and current projects (both in-tree and out-of-tree). It also describes
-some basic logistical information, like how to compile a kernel and
-apply a patch.
-
-If you do not know where you want to start, but you want to look for
-some task to start doing to join into the kernel development community,
-go to the Linux Kernel Janitor's project:
-
-	https://kernelnewbies.org/KernelJanitors
-
-It is a great place to start.  It describes a list of relatively simple
-problems that need to be cleaned up and fixed within the Linux kernel
-source tree.  Working with the developers in charge of this project, you
-will learn the basics of getting your patch into the Linux kernel tree,
-and possibly be pointed in the direction of what to go work on next, if
-you do not already have an idea.
-
-If you already have a chunk of code that you want to put into the kernel
-tree, but need some help getting it in the proper form, the
-kernel-mentors project was created to help you out with this.  It is a
-mailing list, and can be found at:
-
-	https://selenic.com/mailman/listinfo/kernel-mentors
-
-Before making any actual modifications to the Linux kernel code, it is
-imperative to understand how the code in question works.  For this
-purpose, nothing is better than reading through it directly (most tricky
-bits are commented well), perhaps even with the help of specialized
-tools.  One such tool that is particularly recommended is the Linux
-Cross-Reference project, which is able to present source code in a
-self-referential, indexed webpage format. An excellent up-to-date
-repository of the kernel code may be found at:
-
-	http://lxr.free-electrons.com/
-
-
-The development process
------------------------
-
-Linux kernel development process currently consists of a few different
-main kernel "branches" and lots of different subsystem-specific kernel
-branches.  These different branches are:
-
-  - main 4.x kernel tree
-  - 4.x.y -stable kernel tree
-  - 4.x -git kernel patches
-  - subsystem specific kernel trees and patches
-  - the 4.x -next kernel tree for integration tests
-
-4.x kernel tree
------------------
-4.x kernels are maintained by Linus Torvalds, and can be found on
-https://kernel.org in the pub/linux/kernel/v4.x/ directory.  Its development
-process is as follows:
-
-  - As soon as a new kernel is released a two weeks window is open,
-    during this period of time maintainers can submit big diffs to
-    Linus, usually the patches that have already been included in the
-    -next kernel for a few weeks.  The preferred way to submit big changes
-    is using git (the kernel's source management tool, more information
-    can be found at https://git-scm.com/) but plain patches are also just
-    fine.
-  - After two weeks a -rc1 kernel is released it is now possible to push
-    only patches that do not include new features that could affect the
-    stability of the whole kernel.  Please note that a whole new driver
-    (or filesystem) might be accepted after -rc1 because there is no
-    risk of causing regressions with such a change as long as the change
-    is self-contained and does not affect areas outside of the code that
-    is being added.  git can be used to send patches to Linus after -rc1
-    is released, but the patches need to also be sent to a public
-    mailing list for review.
-  - A new -rc is released whenever Linus deems the current git tree to
-    be in a reasonably sane state adequate for testing.  The goal is to
-    release a new -rc kernel every week.
-  - Process continues until the kernel is considered "ready", the
-    process should last around 6 weeks.
-
-It is worth mentioning what Andrew Morton wrote on the linux-kernel
-mailing list about kernel releases:
-
-	*"Nobody knows when a kernel will be released, because it's
-	released according to perceived bug status, not according to a
-	preconceived timeline."*
-
-4.x.y -stable kernel tree
--------------------------
-Kernels with 3-part versions are -stable kernels. They contain
-relatively small and critical fixes for security problems or significant
-regressions discovered in a given 4.x kernel.
-
-This is the recommended branch for users who want the most recent stable
-kernel and are not interested in helping test development/experimental
-versions.
-
-If no 4.x.y kernel is available, then the highest numbered 4.x
-kernel is the current stable kernel.
-
-4.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
-are released as needs dictate.  The normal release period is approximately
-two weeks, but it can be longer if there are no pressing problems.  A
-security-related problem, instead, can cause a release to happen almost
-instantly.
-
-The file Documentation/stable_kernel_rules.txt in the kernel tree
-documents what kinds of changes are acceptable for the -stable tree, and
-how the release process works.
-
-4.x -git patches
-----------------
-These are daily snapshots of Linus' kernel tree which are managed in a
-git repository (hence the name.) These patches are usually released
-daily and represent the current state of Linus' tree.  They are more
-experimental than -rc kernels since they are generated automatically
-without even a cursory glance to see if they are sane.
-
-Subsystem Specific kernel trees and patches
--------------------------------------------
-The maintainers of the various kernel subsystems --- and also many
-kernel subsystem developers --- expose their current state of
-development in source repositories.  That way, others can see what is
-happening in the different areas of the kernel.  In areas where
-development is rapid, a developer may be asked to base his submissions
-onto such a subsystem kernel tree so that conflicts between the
-submission and other already ongoing work are avoided.
-
-Most of these repositories are git trees, but there are also other SCMs
-in use, or patch queues being published as quilt series.  Addresses of
-these subsystem repositories are listed in the MAINTAINERS file.  Many
-of them can be browsed at https://git.kernel.org/.
-
-Before a proposed patch is committed to such a subsystem tree, it is
-subject to review which primarily happens on mailing lists (see the
-respective section below).  For several kernel subsystems, this review
-process is tracked with the tool patchwork.  Patchwork offers a web
-interface which shows patch postings, any comments on a patch or
-revisions to it, and maintainers can mark patches as under review,
-accepted, or rejected.  Most of these patchwork sites are listed at
-https://patchwork.kernel.org/.
-
-4.x -next kernel tree for integration tests
--------------------------------------------
-Before updates from subsystem trees are merged into the mainline 4.x
-tree, they need to be integration-tested.  For this purpose, a special
-testing repository exists into which virtually all subsystem trees are
-pulled on an almost daily basis:
-
-	https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
-
-This way, the -next kernel gives a summary outlook onto what will be
-expected to go into the mainline kernel at the next merge period.
-Adventurous testers are very welcome to runtime-test the -next kernel.
-
-
-Bug Reporting
--------------
-
-https://bugzilla.kernel.org is where the Linux kernel developers track kernel
-bugs.  Users are encouraged to report all bugs that they find in this
-tool.  For details on how to use the kernel bugzilla, please see:
-
-	https://bugzilla.kernel.org/page.cgi?id=faq.html
-
-The file REPORTING-BUGS in the main kernel source directory has a good
-template for how to report a possible kernel bug, and details what kind
-of information is needed by the kernel developers to help track down the
-problem.
-
-
-Managing bug reports
---------------------
-
-One of the best ways to put into practice your hacking skills is by fixing
-bugs reported by other people. Not only you will help to make the kernel
-more stable, you'll learn to fix real world problems and you will improve
-your skills, and other developers will be aware of your presence. Fixing
-bugs is one of the best ways to get merits among other developers, because
-not many people like wasting time fixing other people's bugs.
-
-To work in the already reported bug reports, go to https://bugzilla.kernel.org.
-If you want to be advised of the future bug reports, you can subscribe to the
-bugme-new mailing list (only new bug reports are mailed here) or to the
-bugme-janitor mailing list (every change in the bugzilla is mailed here)
-
-	https://lists.linux-foundation.org/mailman/listinfo/bugme-new
-
-	https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
-
-
-
-Mailing lists
--------------
-
-As some of the above documents describe, the majority of the core kernel
-developers participate on the Linux Kernel Mailing list.  Details on how
-to subscribe and unsubscribe from the list can be found at:
-
-	http://vger.kernel.org/vger-lists.html#linux-kernel
-
-There are archives of the mailing list on the web in many different
-places.  Use a search engine to find these archives.  For example:
-
-	http://dir.gmane.org/gmane.linux.kernel
-
-It is highly recommended that you search the archives about the topic
-you want to bring up, before you post it to the list. A lot of things
-already discussed in detail are only recorded at the mailing list
-archives.
-
-Most of the individual kernel subsystems also have their own separate
-mailing list where they do their development efforts.  See the
-MAINTAINERS file for a list of what these lists are for the different
-groups.
-
-Many of the lists are hosted on kernel.org. Information on them can be
-found at:
-
-	http://vger.kernel.org/vger-lists.html
-
-Please remember to follow good behavioral habits when using the lists.
-Though a bit cheesy, the following URL has some simple guidelines for
-interacting with the list (or any list):
-
-	http://www.albion.com/netiquette/
-
-If multiple people respond to your mail, the CC: list of recipients may
-get pretty large. Don't remove anybody from the CC: list without a good
-reason, or don't reply only to the list address. Get used to receiving the
-mail twice, one from the sender and the one from the list, and don't try
-to tune that by adding fancy mail-headers, people will not like it.
-
-Remember to keep the context and the attribution of your replies intact,
-keep the "John Kernelhacker wrote ...:" lines at the top of your reply, and
-add your statements between the individual quoted sections instead of
-writing at the top of the mail.
-
-If you add patches to your mail, make sure they are plain readable text
-as stated in Documentation/SubmittingPatches.
-Kernel developers don't want to deal with
-attachments or compressed patches; they may want to comment on
-individual lines of your patch, which works only that way. Make sure you
-use a mail program that does not mangle spaces and tab characters. A
-good first test is to send the mail to yourself and try to apply your
-own patch by yourself. If that doesn't work, get your mail program fixed
-or change it until it works.
-
-Above all, please remember to show respect to other subscribers.
-
-
-Working with the community
---------------------------
-
-The goal of the kernel community is to provide the best possible kernel
-there is.  When you submit a patch for acceptance, it will be reviewed
-on its technical merits and those alone.  So, what should you be
-expecting?
-
-  - criticism
-  - comments
-  - requests for change
-  - requests for justification
-  - silence
-
-Remember, this is part of getting your patch into the kernel.  You have
-to be able to take criticism and comments about your patches, evaluate
-them at a technical level and either rework your patches or provide
-clear and concise reasoning as to why those changes should not be made.
-If there are no responses to your posting, wait a few days and try
-again, sometimes things get lost in the huge volume.
-
-What should you not do?
-
-  - expect your patch to be accepted without question
-  - become defensive
-  - ignore comments
-  - resubmit the patch without making any of the requested changes
-
-In a community that is looking for the best technical solution possible,
-there will always be differing opinions on how beneficial a patch is.
-You have to be cooperative, and willing to adapt your idea to fit within
-the kernel.  Or at least be willing to prove your idea is worth it.
-Remember, being wrong is acceptable as long as you are willing to work
-toward a solution that is right.
-
-It is normal that the answers to your first patch might simply be a list
-of a dozen things you should correct.  This does **not** imply that your
-patch will not be accepted, and it is **not** meant against you
-personally.  Simply correct all issues raised against your patch and
-resend it.
-
-
-Differences between the kernel community and corporate structures
------------------------------------------------------------------
-
-The kernel community works differently than most traditional corporate
-development environments.  Here are a list of things that you can try to
-do to avoid problems:
-
-  Good things to say regarding your proposed changes:
-
-    - "This solves multiple problems."
-    - "This deletes 2000 lines of code."
-    - "Here is a patch that explains what I am trying to describe."
-    - "I tested it on 5 different architectures..."
-    - "Here is a series of small patches that..."
-    - "This increases performance on typical machines..."
-
-  Bad things you should avoid saying:
-
-    - "We did it this way in AIX/ptx/Solaris, so therefore it must be
-      good..."
-    - "I've being doing this for 20 years, so..."
-    - "This is required for my company to make money"
-    - "This is for our Enterprise product line."
-    - "Here is my 1000 page design document that describes my idea"
-    - "I've been working on this for 6 months..."
-    - "Here's a 5000 line patch that..."
-    - "I rewrote all of the current mess, and here it is..."
-    - "I have a deadline, and this patch needs to be applied now."
-
-Another way the kernel community is different than most traditional
-software engineering work environments is the faceless nature of
-interaction.  One benefit of using email and irc as the primary forms of
-communication is the lack of discrimination based on gender or race.
-The Linux kernel work environment is accepting of women and minorities
-because all you are is an email address.  The international aspect also
-helps to level the playing field because you can't guess gender based on
-a person's name. A man may be named Andrea and a woman may be named Pat.
-Most women who have worked in the Linux kernel and have expressed an
-opinion have had positive experiences.
-
-The language barrier can cause problems for some people who are not
-comfortable with English.  A good grasp of the language can be needed in
-order to get ideas across properly on mailing lists, so it is
-recommended that you check your emails to make sure they make sense in
-English before sending them.
-
-
-Break up your changes
----------------------
-
-The Linux kernel community does not gladly accept large chunks of code
-dropped on it all at once.  The changes need to be properly introduced,
-discussed, and broken up into tiny, individual portions.  This is almost
-the exact opposite of what companies are used to doing.  Your proposal
-should also be introduced very early in the development process, so that
-you can receive feedback on what you are doing.  It also lets the
-community feel that you are working with them, and not simply using them
-as a dumping ground for your feature.  However, don't send 50 emails at
-one time to a mailing list, your patch series should be smaller than
-that almost all of the time.
-
-The reasons for breaking things up are the following:
-
-1) Small patches increase the likelihood that your patches will be
-   applied, since they don't take much time or effort to verify for
-   correctness.  A 5 line patch can be applied by a maintainer with
-   barely a second glance. However, a 500 line patch may take hours to
-   review for correctness (the time it takes is exponentially
-   proportional to the size of the patch, or something).
-
-   Small patches also make it very easy to debug when something goes
-   wrong.  It's much easier to back out patches one by one than it is
-   to dissect a very large patch after it's been applied (and broken
-   something).
-
-2) It's important not only to send small patches, but also to rewrite
-   and simplify (or simply re-order) patches before submitting them.
-
-Here is an analogy from kernel developer Al Viro:
-
-	*"Think of a teacher grading homework from a math student.  The
-	teacher does not want to see the student's trials and errors
-	before they came up with the solution. They want to see the
-	cleanest, most elegant answer.  A good student knows this, and
-	would never submit her intermediate work before the final
-	solution.*
-
-	*The same is true of kernel development. The maintainers and
-	reviewers do not want to see the thought process behind the
-	solution to the problem one is solving. They want to see a
-	simple and elegant solution."*
-
-It may be challenging to keep the balance between presenting an elegant
-solution and working together with the community and discussing your
-unfinished work. Therefore it is good to get early in the process to
-get feedback to improve your work, but also keep your changes in small
-chunks that they may get already accepted, even when your whole task is
-not ready for inclusion now.
-
-Also realize that it is not acceptable to send patches for inclusion
-that are unfinished and will be "fixed up later."
-
-
-Justify your change
--------------------
-
-Along with breaking up your patches, it is very important for you to let
-the Linux community know why they should add this change.  New features
-must be justified as being needed and useful.
-
-
-Document your change
---------------------
-
-When sending in your patches, pay special attention to what you say in
-the text in your email.  This information will become the ChangeLog
-information for the patch, and will be preserved for everyone to see for
-all time.  It should describe the patch completely, containing:
-
-  - why the change is necessary
-  - the overall design approach in the patch
-  - implementation details
-  - testing results
-
-For more details on what this should all look like, please see the
-ChangeLog section of the document:
-
-  "The Perfect Patch"
-      http://www.ozlabs.org/~akpm/stuff/tpp.txt
-
-
-All of these things are sometimes very hard to do. It can take years to
-perfect these practices (if at all). It's a continuous process of
-improvement that requires a lot of patience and determination. But
-don't give up, it's possible. Many have done it before, and each had to
-start exactly where you are now.
-
-
-
-
-----------
-
-Thanks to Paolo Ciarrocchi who allowed the "Development Process"
-(https://lwn.net/Articles/94386/) section
-to be based on text he had written, and to Randy Dunlap and Gerrit
-Huizenga for some of the list of things you should and should not say.
-Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
-Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi
-Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
-David A. Wheeler, Junio Hamano, Michael Kerrisk, and Alex Shepard for
-their review, comments, and contributions.  Without their help, this
-document would not have been possible.
-
-
-
-Maintainer: Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/hwmon/hwmon-kernel-api.txt linux-libre-4.10-rc8-gnu/Documentation/hwmon/hwmon-kernel-api.txt
--- linux-libre-4.9-gnu/Documentation/hwmon/hwmon-kernel-api.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/hwmon/hwmon-kernel-api.txt	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,6 @@ Each hardware monitoring driver must #in
 cases, <linux/hwmon-sysfs.h>. linux/hwmon.h declares the following
 register/unregister functions:
 
-struct device *hwmon_device_register(struct device *dev);
 struct device *
 hwmon_device_register_with_groups(struct device *dev, const char *name,
 				  void *drvdata,
@@ -38,36 +37,31 @@ struct device *
 hwmon_device_register_with_info(struct device *dev,
 				const char *name, void *drvdata,
 				const struct hwmon_chip_info *info,
-				const struct attribute_group **groups);
+				const struct attribute_group **extra_groups);
 
 struct device *
 devm_hwmon_device_register_with_info(struct device *dev,
-				     const char *name,
-				     void *drvdata,
-				     const struct hwmon_chip_info *info,
-				     const struct attribute_group **groups);
+				const char *name,
+				void *drvdata,
+				const struct hwmon_chip_info *info,
+				const struct attribute_group **extra_groups);
 
 void hwmon_device_unregister(struct device *dev);
 void devm_hwmon_device_unregister(struct device *dev);
 
-hwmon_device_register registers a hardware monitoring device. The parameter
-of this function is a pointer to the parent device.
-This function returns a pointer to the newly created hardware monitoring device
-or PTR_ERR for failure. If this registration function is used, hardware
-monitoring sysfs attributes are expected to have been created and attached to
-the parent device prior to calling hwmon_device_register. A name attribute must
-have been created by the caller.
-
-hwmon_device_register_with_groups is similar to hwmon_device_register. However,
-it has additional parameters. The name parameter is a pointer to the hwmon
-device name. The registration function wil create a name sysfs attribute
-pointing to this name. The drvdata parameter is the pointer to the local
-driver data.  hwmon_device_register_with_groups will attach this pointer
-to the newly allocated hwmon device. The pointer can be retrieved by the driver
-using dev_get_drvdata() on the hwmon device pointer. The groups parameter is
+hwmon_device_register_with_groups registers a hardware monitoring device.
+The first parameter of this function is a pointer to the parent device.
+The name parameter is a pointer to the hwmon device name. The registration
+function wil create a name sysfs attribute pointing to this name.
+The drvdata parameter is the pointer to the local driver data.
+hwmon_device_register_with_groups will attach this pointer to the newly
+allocated hwmon device. The pointer can be retrieved by the driver using
+dev_get_drvdata() on the hwmon device pointer. The groups parameter is
 a pointer to a list of sysfs attribute groups. The list must be NULL terminated.
 hwmon_device_register_with_groups creates the hwmon device with name attribute
 as well as all sysfs attributes attached to the hwmon device.
+This function returns a pointer to the newly created hardware monitoring device
+or PTR_ERR for failure.
 
 devm_hwmon_device_register_with_groups is similar to
 hwmon_device_register_with_groups. However, it is device managed, meaning the
@@ -87,13 +81,13 @@ hwmon_device_unregister deregisters a re
 The parameter of this function is the pointer to the registered hardware
 monitoring device structure. This function must be called from the driver
 remove function if the hardware monitoring device was registered with
-hwmon_device_register, hwmon_device_register_with_groups, or
-hwmon_device_register_with_info.
+hwmon_device_register_with_groups or hwmon_device_register_with_info.
 
 devm_hwmon_device_unregister does not normally have to be called. It is only
 needed for error handling, and only needed if the driver probe fails after
-the call to devm_hwmon_device_register_with_groups and if the automatic
-(device managed) removal would be too late.
+the call to devm_hwmon_device_register_with_groups or
+hwmon_device_register_with_info and if the automatic (device managed)
+removal would be too late.
 
 Using devm_hwmon_device_register_with_info()
 --------------------------------------------
@@ -106,9 +100,9 @@ const char *name	Device name
 void *drvdata		Driver private data
 const struct hwmon_chip_info *info
 			Pointer to chip description.
-const struct attribute_group **groups
-			Null-terminated list of additional sysfs attribute
-			groups.
+const struct attribute_group **extra_groups
+			Null-terminated list of additional non-standard
+			sysfs attribute groups.
 
 This function returns a pointer to the created hardware monitoring device
 on success and a negative error code for failure.
@@ -160,7 +154,7 @@ It contains following fields:
 * type: The hardware monitoring sensor type.
   Supported sensor types are
   * hwmon_chip		A virtual sensor type, used to describe attributes
-			which apply to the entire chip.
+  *			which are not bound to a specific input or output
   * hwmon_temp		Temperature sensor
   * hwmon_in		Voltage sensor
   * hwmon_curr		Current sensor
@@ -293,9 +287,9 @@ Driver-provided sysfs attributes
 
 If the hardware monitoring device is registered with
 hwmon_device_register_with_info or devm_hwmon_device_register_with_info,
-it is most likely not necessary to provide sysfs attributes. Only non-standard
-sysfs attributes need to be provided when one of those registration functions
-is used.
+it is most likely not necessary to provide sysfs attributes. Only additional
+non-standard sysfs attributes need to be provided when one of those registration
+functions is used.
 
 The header file linux/hwmon-sysfs.h provides a number of useful macros to
 declare and use hardware monitoring sysfs attributes.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/hwmon/submitting-patches linux-libre-4.10-rc8-gnu/Documentation/hwmon/submitting-patches
--- linux-libre-4.9-gnu/Documentation/hwmon/submitting-patches	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/hwmon/submitting-patches	2017-02-12 16:03:20.000000000 -0500
@@ -10,10 +10,10 @@ increase the chances of your change bein
 ----------
 
 * It should be unnecessary to mention, but please read and follow
-    Documentation/SubmitChecklist
-    Documentation/SubmittingDrivers
-    Documentation/SubmittingPatches
-    Documentation/CodingStyle
+    Documentation/process/submit-checklist.rst
+    Documentation/process/submitting-drivers.rst
+    Documentation/process/submitting-patches.rst
+    Documentation/process/coding-style.rst
 
 * Please run your patch through 'checkpatch --strict'. There should be no
   errors, no warnings, and few if any check messages. If there are any
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/hwmon/tc654 linux-libre-4.10-rc8-gnu/Documentation/hwmon/tc654
--- linux-libre-4.9-gnu/Documentation/hwmon/tc654	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/hwmon/tc654	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,31 @@
+Kernel driver tc654
+===================
+
+Supported chips:
+  * Microship TC654 and TC655
+    Prefix: 'tc654'
+    Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/20001734C.pdf
+
+Authors:
+        Chris Packham <chris.packham@alliedtelesis.co.nz>
+        Masahiko Iwamoto <iwamoto@allied-telesis.co.jp>
+
+Description
+-----------
+This driver implements support for the Microchip TC654 and TC655.
+
+The TC654 uses the 2-wire interface compatible with the SMBUS 2.0
+specification. The TC654 has two (2) inputs for measuring fan RPM and
+one (1) PWM output which can be used for fan control.
+
+Configuration Notes
+-------------------
+Ordinarily the pwm1_mode ABI is used for controlling the pwm output
+mode.  However, for this chip the output is always pwm, and the
+pwm1_mode determines if the pwm output is controlled via the pwm1 value
+or via the Vin analog input.
+
+
+Setting pwm1_mode to 1 will cause the pwm output to be driven based on
+the pwm1 value. Setting pwm1_mode to 0 will cause the pwm output to be
+driven based on the Vin input.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/hwmon/tmp108 linux-libre-4.10-rc8-gnu/Documentation/hwmon/tmp108
--- linux-libre-4.9-gnu/Documentation/hwmon/tmp108	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/hwmon/tmp108	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,36 @@
+Kernel driver tmp108
+====================
+
+Supported chips:
+  * Texas Instruments TMP108
+    Prefix: 'tmp108'
+    Addresses scanned: none
+    Datasheet: http://www.ti.com/product/tmp108
+
+Author:
+	John Muir <john@jmuir.com>
+
+Description
+-----------
+
+The Texas Instruments TMP108 implements one temperature sensor. An alert pin
+can be set when temperatures exceed minimum or maximum values plus or minus a
+hysteresis value. (This driver does not support interrupts for the alert pin,
+and the device runs in comparator mode.)
+
+The sensor is accurate to 0.75C over the range of -25 to +85 C, and to 1.0
+degree from -40 to +125 C. Resolution of the sensor is 0.0625 degree. The
+operating temperature has a minimum of -55 C and a maximum of +150 C.
+Hysteresis values can be set to 0, 1, 2, or 4C.
+
+The TMP108 has a programmable update rate that can select between 8, 4, 1, and
+0.5 Hz.
+
+By default the TMP108 reads the temperature continuously. To conserve power,
+the TMP108 has a one-shot mode where the device is normally shut-down. When a
+one shot is requested the temperature is read, the result can be retrieved,
+and then the device is shut down automatically. (This driver only supports
+continuous mode.)
+
+The driver provides the common sysfs-interface for temperatures (see
+Documentation/hwmon/sysfs-interface under Temperatures).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/i2c/busses/i2c-mlxcpld linux-libre-4.10-rc8-gnu/Documentation/i2c/busses/i2c-mlxcpld
--- linux-libre-4.9-gnu/Documentation/i2c/busses/i2c-mlxcpld	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/i2c/busses/i2c-mlxcpld	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,47 @@
+Driver i2c-mlxcpld
+
+Author: Michael Shych <michaelsh@mellanox.com>
+
+This is the Mellanox I2C controller logic, implemented in Lattice CPLD
+device.
+Device supports:
+ - Master mode.
+ - One physical bus.
+ - Polling mode.
+
+This controller is equipped within the next Mellanox systems:
+"msx6710", "msx6720", "msb7700", "msn2700", "msx1410", "msn2410", "msb7800",
+"msn2740", "msn2100".
+
+The next transaction types are supported:
+ - Receive Byte/Block.
+ - Send Byte/Block.
+ - Read Byte/Block.
+ - Write Byte/Block.
+
+Registers:
+CTRL		0x1 - control reg.
+			Resets all the registers.
+HALF_CYC	0x4 - cycle reg.
+			Configure the width of I2C SCL half clock cycle (in 4 LPC_CLK
+			units).
+I2C_HOLD	0x5 - hold reg.
+			OE (output enable) is delayed by value set to this register
+			(in LPC_CLK units)
+CMD			0x6 - command reg.
+			Bit 0, 0 = write, 1 = read.
+			Bits [7:1] - the 7bit Address of the I2C device.
+			It should be written last as it triggers an I2C transaction.
+NUM_DATA	0x7 - data size reg.
+			Number of data bytes to write in read transaction
+NUM_ADDR	0x8 - address reg.
+			Number of address bytes to write in read transaction.
+STATUS		0x9 - status reg.
+			Bit 0 - transaction is completed.
+			Bit 4 - ACK/NACK.
+DATAx		0xa - 0x54  - 68 bytes data buffer regs.
+			For write transaction address is specified in four first bytes
+			(DATA1 - DATA4), data starting from DATA4.
+			For read transactions address is sent in a separate transaction and
+			specified in the four first bytes (DATA0 - DATA3). Data is read
+			starting from DATA0.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/i2c/smbus-protocol linux-libre-4.10-rc8-gnu/Documentation/i2c/smbus-protocol
--- linux-libre-4.9-gnu/Documentation/i2c/smbus-protocol	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/i2c/smbus-protocol	2017-02-12 16:03:20.000000000 -0500
@@ -200,10 +200,14 @@ alerting device's address.
 [S] [HostAddr] [Wr] A [DevAddr] A [DataLow] A [DataHigh] A [P]
 
 This is implemented in the following way in the Linux kernel:
-* I2C bus drivers which support SMBus Host Notify should call
-  i2c_setup_smbus_host_notify() to setup SMBus Host Notify support.
-* I2C drivers for devices which can trigger SMBus Host Notify should implement
-  the optional alert() callback.
+* I2C bus drivers which support SMBus Host Notify should report
+  I2C_FUNC_SMBUS_HOST_NOTIFY.
+* I2C bus drivers trigger SMBus Host Notify by a call to
+  i2c_handle_smbus_host_notify().
+* I2C drivers for devices which can trigger SMBus Host Notify will have
+  client->irq assigned to a Host Notify IRQ if noone else specified an other.
+
+There is currently no way to retrieve the data parameter from the client.
 
 
 Packet Error Checking (PEC)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/index.rst linux-libre-4.10-rc8-gnu/Documentation/index.rst
--- linux-libre-4.9-gnu/Documentation/index.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -3,21 +3,70 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to The Linux Kernel's documentation!
-============================================
+Welcome to The Linux Kernel's documentation
+===========================================
 
-Contents:
+This is the top level of the kernel's documentation tree.  Kernel
+documentation, like the kernel itself, is very much a work in progress;
+that is especially true as we work to integrate our many scattered
+documents into a coherent whole.  Please note that improvements to the
+documentation are welcome; join the linux-doc list at vger.kernel.org if
+you want to help out.
+
+User-oriented documentation
+---------------------------
+
+The following manuals are written for *users* of the kernel — those who are
+trying to get it to work optimally on a given system.
+
+.. toctree::
+   :maxdepth: 2
+
+   admin-guide/index
+
+Introduction to kernel development
+----------------------------------
+
+These manuals contain overall information about how to develop the kernel.
+The kernel community is quite large, with thousands of developers
+contributing over the course of a year.  As with any large community,
+knowing how things are done will make the process of getting your changes
+merged much easier.
+
+.. toctree::
+   :maxdepth: 2
+
+   process/index
+   dev-tools/index
+   doc-guide/index
+
+Kernel API documentation
+------------------------
+
+These books get into the details of how specific kernel subsystems work
+from the point of view of a kernel developer.  Much of the information here
+is taken directly from the kernel source, with supplemental material added
+as needed (or at least as we managed to add it — probably *not* all that is
+needed). 
 
 .. toctree::
    :maxdepth: 2
 
-   kernel-documentation
-   development-process/index
-   dev-tools/tools
    driver-api/index
+   core-api/index
    media/index
    gpu/index
-   80211/index
+   security/index
+   sound/index
+   crypto/index
+
+Korean translations
+-------------------
+
+.. toctree::
+   :maxdepth: 1
+
+   translations/ko_KR/index
 
 Indices and tables
 ==================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/initrd.txt linux-libre-4.10-rc8-gnu/Documentation/initrd.txt
--- linux-libre-4.9-gnu/Documentation/initrd.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/initrd.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,366 +0,0 @@
-Using the initial RAM disk (initrd)
-===================================
-
-Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch> and
-                     Hans Lermen <lermen@fgan.de>
-
-
-initrd provides the capability to load a RAM disk by the boot loader.
-This RAM disk can then be mounted as the root file system and programs
-can be run from it. Afterwards, a new root file system can be mounted
-from a different device. The previous root (from initrd) is then moved
-to a directory and can be subsequently unmounted.
-
-initrd is mainly designed to allow system startup to occur in two phases,
-where the kernel comes up with a minimum set of compiled-in drivers, and
-where additional modules are loaded from initrd.
-
-This document gives a brief overview of the use of initrd. A more detailed
-discussion of the boot process can be found in [1].
-
-
-Operation
----------
-
-When using initrd, the system typically boots as follows:
-
-  1) the boot loader loads the kernel and the initial RAM disk
-  2) the kernel converts initrd into a "normal" RAM disk and
-     frees the memory used by initrd
-  3) if the root device is not /dev/ram0, the old (deprecated)
-     change_root procedure is followed. see the "Obsolete root change
-     mechanism" section below.
-  4) root device is mounted. if it is /dev/ram0, the initrd image is
-     then mounted as root
-  5) /sbin/init is executed (this can be any valid executable, including
-     shell scripts; it is run with uid 0 and can do basically everything
-     init can do).
-  6) init mounts the "real" root file system
-  7) init places the root file system at the root directory using the
-     pivot_root system call
-  8) init execs the /sbin/init on the new root filesystem, performing
-     the usual boot sequence
-  9) the initrd file system is removed
-
-Note that changing the root directory does not involve unmounting it.
-It is therefore possible to leave processes running on initrd during that
-procedure. Also note that file systems mounted under initrd continue to
-be accessible.
-
-
-Boot command-line options
--------------------------
-
-initrd adds the following new options:
-
-  initrd=<path>    (e.g. LOADLIN)
-
-    Loads the specified file as the initial RAM disk. When using LILO, you
-    have to specify the RAM disk image file in /etc/lilo.conf, using the
-    INITRD configuration variable.
-
-  noinitrd
-
-    initrd data is preserved but it is not converted to a RAM disk and
-    the "normal" root file system is mounted. initrd data can be read
-    from /dev/initrd. Note that the data in initrd can have any structure
-    in this case and doesn't necessarily have to be a file system image.
-    This option is used mainly for debugging.
-
-    Note: /dev/initrd is read-only and it can only be used once. As soon
-    as the last process has closed it, all data is freed and /dev/initrd
-    can't be opened anymore.
-
-  root=/dev/ram0
-
-    initrd is mounted as root, and the normal boot procedure is followed,
-    with the RAM disk mounted as root.
-
-Compressed cpio images
-----------------------
-
-Recent kernels have support for populating a ramdisk from a compressed cpio
-archive. On such systems, the creation of a ramdisk image doesn't need to
-involve special block devices or loopbacks; you merely create a directory on
-disk with the desired initrd content, cd to that directory, and run (as an
-example):
-
-find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img
-
-Examining the contents of an existing image file is just as simple:
-
-mkdir /tmp/imagefile
-cd /tmp/imagefile
-gzip -cd /boot/imagefile.img | cpio -imd --quiet
-
-Installation
-------------
-
-First, a directory for the initrd file system has to be created on the
-"normal" root file system, e.g.
-
-# mkdir /initrd
-
-The name is not relevant. More details can be found on the pivot_root(2)
-man page.
-
-If the root file system is created during the boot procedure (i.e. if
-you're building an install floppy), the root file system creation
-procedure should create the /initrd directory.
-
-If initrd will not be mounted in some cases, its content is still
-accessible if the following device has been created:
-
-# mknod /dev/initrd b 1 250 
-# chmod 400 /dev/initrd
-
-Second, the kernel has to be compiled with RAM disk support and with
-support for the initial RAM disk enabled. Also, at least all components
-needed to execute programs from initrd (e.g. executable format and file
-system) must be compiled into the kernel.
-
-Third, you have to create the RAM disk image. This is done by creating a
-file system on a block device, copying files to it as needed, and then
-copying the content of the block device to the initrd file. With recent
-kernels, at least three types of devices are suitable for that:
-
- - a floppy disk (works everywhere but it's painfully slow)
- - a RAM disk (fast, but allocates physical memory)
- - a loopback device (the most elegant solution)
-
-We'll describe the loopback device method:
-
- 1) make sure loopback block devices are configured into the kernel
- 2) create an empty file system of the appropriate size, e.g.
-    # dd if=/dev/zero of=initrd bs=300k count=1
-    # mke2fs -F -m0 initrd
-    (if space is critical, you may want to use the Minix FS instead of Ext2)
- 3) mount the file system, e.g.
-    # mount -t ext2 -o loop initrd /mnt
- 4) create the console device:
-    # mkdir /mnt/dev
-    # mknod /mnt/dev/console c 5 1
- 5) copy all the files that are needed to properly use the initrd
-    environment. Don't forget the most important file, /sbin/init
-    Note that /sbin/init's permissions must include "x" (execute).
- 6) correct operation the initrd environment can frequently be tested
-    even without rebooting with the command
-    # chroot /mnt /sbin/init
-    This is of course limited to initrds that do not interfere with the
-    general system state (e.g. by reconfiguring network interfaces,
-    overwriting mounted devices, trying to start already running demons,
-    etc. Note however that it is usually possible to use pivot_root in
-    such a chroot'ed initrd environment.)
- 7) unmount the file system
-    # umount /mnt
- 8) the initrd is now in the file "initrd". Optionally, it can now be
-    compressed
-    # gzip -9 initrd
-
-For experimenting with initrd, you may want to take a rescue floppy and
-only add a symbolic link from /sbin/init to /bin/sh. Alternatively, you
-can try the experimental newlib environment [2] to create a small
-initrd.
-
-Finally, you have to boot the kernel and load initrd. Almost all Linux
-boot loaders support initrd. Since the boot process is still compatible
-with an older mechanism, the following boot command line parameters
-have to be given:
-
-  root=/dev/ram0 rw
-
-(rw is only necessary if writing to the initrd file system.)
-
-With LOADLIN, you simply execute
-
-     LOADLIN <kernel> initrd=<disk_image>
-e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 rw
-
-With LILO, you add the option INITRD=<path> to either the global section
-or to the section of the respective kernel in /etc/lilo.conf, and pass
-the options using APPEND, e.g.
-
-  image = /bzImage
-    initrd = /boot/initrd.gz
-    append = "root=/dev/ram0 rw"
-
-and run /sbin/lilo
-
-For other boot loaders, please refer to the respective documentation.
-
-Now you can boot and enjoy using initrd.
-
-
-Changing the root device
-------------------------
-
-When finished with its duties, init typically changes the root device
-and proceeds with starting the Linux system on the "real" root device.
-
-The procedure involves the following steps:
- - mounting the new root file system
- - turning it into the root file system
- - removing all accesses to the old (initrd) root file system
- - unmounting the initrd file system and de-allocating the RAM disk
-
-Mounting the new root file system is easy: it just needs to be mounted on
-a directory under the current root. Example:
-
-# mkdir /new-root
-# mount -o ro /dev/hda1 /new-root
-
-The root change is accomplished with the pivot_root system call, which
-is also available via the pivot_root utility (see pivot_root(8) man
-page; pivot_root is distributed with util-linux version 2.10h or higher
-[3]). pivot_root moves the current root to a directory under the new
-root, and puts the new root at its place. The directory for the old root
-must exist before calling pivot_root. Example:
-
-# cd /new-root
-# mkdir initrd
-# pivot_root . initrd
-
-Now, the init process may still access the old root via its
-executable, shared libraries, standard input/output/error, and its
-current root directory. All these references are dropped by the
-following command:
-
-# exec chroot . what-follows <dev/console >dev/console 2>&1
-
-Where what-follows is a program under the new root, e.g. /sbin/init
-If the new root file system will be used with udev and has no valid
-/dev directory, udev must be initialized before invoking chroot in order
-to provide /dev/console.
-
-Note: implementation details of pivot_root may change with time. In order
-to ensure compatibility, the following points should be observed:
-
- - before calling pivot_root, the current directory of the invoking
-   process should point to the new root directory
- - use . as the first argument, and the _relative_ path of the directory
-   for the old root as the second argument
- - a chroot program must be available under the old and the new root
- - chroot to the new root afterwards
- - use relative paths for dev/console in the exec command
-
-Now, the initrd can be unmounted and the memory allocated by the RAM
-disk can be freed:
-
-# umount /initrd
-# blockdev --flushbufs /dev/ram0
-
-It is also possible to use initrd with an NFS-mounted root, see the
-pivot_root(8) man page for details.
-
-
-Usage scenarios
----------------
-
-The main motivation for implementing initrd was to allow for modular
-kernel configuration at system installation. The procedure would work
-as follows:
-
-  1) system boots from floppy or other media with a minimal kernel
-     (e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and
-     loads initrd
-  2) /sbin/init determines what is needed to (1) mount the "real" root FS
-     (i.e. device type, device drivers, file system) and (2) the
-     distribution media (e.g. CD-ROM, network, tape, ...). This can be
-     done by asking the user, by auto-probing, or by using a hybrid
-     approach.
-  3) /sbin/init loads the necessary kernel modules
-  4) /sbin/init creates and populates the root file system (this doesn't
-     have to be a very usable system yet)
-  5) /sbin/init invokes pivot_root to change the root file system and
-     execs - via chroot - a program that continues the installation
-  6) the boot loader is installed
-  7) the boot loader is configured to load an initrd with the set of
-     modules that was used to bring up the system (e.g. /initrd can be
-     modified, then unmounted, and finally, the image is written from
-     /dev/ram0 or /dev/rd/0 to a file)
-  8) now the system is bootable and additional installation tasks can be
-     performed
-
-The key role of initrd here is to re-use the configuration data during
-normal system operation without requiring the use of a bloated "generic"
-kernel or re-compiling or re-linking the kernel.
-
-A second scenario is for installations where Linux runs on systems with
-different hardware configurations in a single administrative domain. In
-such cases, it is desirable to generate only a small set of kernels
-(ideally only one) and to keep the system-specific part of configuration
-information as small as possible. In this case, a common initrd could be
-generated with all the necessary modules. Then, only /sbin/init or a file
-read by it would have to be different.
-
-A third scenario is more convenient recovery disks, because information
-like the location of the root FS partition doesn't have to be provided at
-boot time, but the system loaded from initrd can invoke a user-friendly
-dialog and it can also perform some sanity checks (or even some form of
-auto-detection).
-
-Last not least, CD-ROM distributors may use it for better installation
-from CD, e.g. by using a boot floppy and bootstrapping a bigger RAM disk
-via initrd from CD; or by booting via a loader like LOADLIN or directly
-from the CD-ROM, and loading the RAM disk from CD without need of
-floppies. 
-
-
-Obsolete root change mechanism
-------------------------------
-
-The following mechanism was used before the introduction of pivot_root.
-Current kernels still support it, but you should _not_ rely on its
-continued availability.
-
-It works by mounting the "real" root device (i.e. the one set with rdev
-in the kernel image or with root=... at the boot command line) as the
-root file system when linuxrc exits. The initrd file system is then
-unmounted, or, if it is still busy, moved to a directory /initrd, if
-such a directory exists on the new root file system.
-
-In order to use this mechanism, you do not have to specify the boot
-command options root, init, or rw. (If specified, they will affect
-the real root file system, not the initrd environment.)
-  
-If /proc is mounted, the "real" root device can be changed from within
-linuxrc by writing the number of the new root FS device to the special
-file /proc/sys/kernel/real-root-dev, e.g.
-
-  # echo 0x301 >/proc/sys/kernel/real-root-dev
-
-Note that the mechanism is incompatible with NFS and similar file
-systems.
-
-This old, deprecated mechanism is commonly called "change_root", while
-the new, supported mechanism is called "pivot_root".
-
-
-Mixed change_root and pivot_root mechanism
-------------------------------------------
-
-In case you did not want to use root=/dev/ram0 to trigger the pivot_root
-mechanism, you may create both /linuxrc and /sbin/init in your initrd image.
-
-/linuxrc would contain only the following:
-
-#! /bin/sh
-mount -n -t proc proc /proc
-echo 0x0100 >/proc/sys/kernel/real-root-dev
-umount -n /proc
-
-Once linuxrc exited, the kernel would mount again your initrd as root,
-this time executing /sbin/init. Again, it would be the duty of this init
-to build the right environment (maybe using the root= device passed on
-the cmdline) before the final execution of the real /sbin/init.
-
-
-Resources
----------
-
-[1] Almesberger, Werner; "Booting Linux: The History and the Future"
-    http://www.almesberger.net/cv/papers/ols2k-9.ps.gz
-[2] newlib package (experimental), with initrd example
-    http://sources.redhat.com/newlib/
-[3] util-linux: Miscellaneous utilities for Linux
-    http://www.kernel.org/pub/linux/utils/util-linux/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/init.txt linux-libre-4.10-rc8-gnu/Documentation/init.txt
--- linux-libre-4.9-gnu/Documentation/init.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/init.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-Explaining the dreaded "No init found." boot hang message
-=========================================================
-
-OK, so you've got this pretty unintuitive message (currently located
-in init/main.c) and are wondering what the H*** went wrong.
-Some high-level reasons for failure (listed roughly in order of execution)
-to load the init binary are:
-A) Unable to mount root FS
-B) init binary doesn't exist on rootfs
-C) broken console device
-D) binary exists but dependencies not available
-E) binary cannot be loaded
-
-Detailed explanations:
-0) Set "debug" kernel parameter (in bootloader config file or CONFIG_CMDLINE)
-   to get more detailed kernel messages.
-A) make sure you have the correct root FS type
-   (and root= kernel parameter points to the correct partition),
-   required drivers such as storage hardware (such as SCSI or USB!)
-   and filesystem (ext3, jffs2 etc.) are builtin (alternatively as modules,
-   to be pre-loaded by an initrd)
-C) Possibly a conflict in console= setup --> initial console unavailable.
-   E.g. some serial consoles are unreliable due to serial IRQ issues (e.g.
-   missing interrupt-based configuration).
-   Try using a different console= device or e.g. netconsole= .
-D) e.g. required library dependencies of the init binary such as
-   /lib/ld-linux.so.2 missing or broken. Use readelf -d <INIT>|grep NEEDED
-   to find out which libraries are required.
-E) make sure the binary's architecture matches your hardware.
-   E.g. i386 vs. x86_64 mismatch, or trying to load x86 on ARM hardware.
-   In case you tried loading a non-binary file here (shell script?),
-   you should make sure that the script specifies an interpreter in its shebang
-   header line (#!/...) that is fully working (including its library
-   dependencies). And before tackling scripts, better first test a simple
-   non-script binary such as /bin/sh and confirm its successful execution.
-   To find out more, add code to init/main.c to display kernel_execve()s
-   return values.
-
-Please extend this explanation whenever you find new failure causes
-(after all loading the init binary is a CRITICAL and hard transition step
-which needs to be made as painless as possible), then submit patch to LKML.
-Further TODOs:
-- Implement the various run_init_process() invocations via a struct array
-  which can then store the kernel_execve() result value and on failure
-  log it all by iterating over _all_ results (very important usability fix).
-- try to make the implementation itself more helpful in general,
-  e.g. by providing additional error messages at affected places.
-
-Andreas Mohr <andi at lisas period de>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/IPMI.txt linux-libre-4.10-rc8-gnu/Documentation/IPMI.txt
--- linux-libre-4.9-gnu/Documentation/IPMI.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/IPMI.txt	2017-02-12 16:03:20.000000000 -0500
@@ -111,6 +111,8 @@ ipmi_ssif - A driver for accessing BMCs
 I2C kernel driver's SMBus interfaces to send and receive IPMI messages
 over the SMBus.
 
+ipmi_powernv - A driver for access BMCs on POWERNV systems.
+
 ipmi_watchdog - IPMI requires systems to have a very capable watchdog
 timer.  This driver implements the standard Linux watchdog timer
 interface on top of the IPMI message handler.
@@ -118,17 +120,15 @@ interface on top of the IPMI message han
 ipmi_poweroff - Some systems support the ability to be turned off via
 IPMI commands.
 
-These are all individually selectable via configuration options.
+bt-bmc - This is not part of the main driver, but instead a driver for
+accessing a BMC-side interface of a BT interface.  It is used on BMCs
+running Linux to provide an interface to the host.
 
-Note that the KCS-only interface has been removed.  The af_ipmi driver
-is no longer supported and has been removed because it was impossible
-to do 32 bit emulation on 64-bit kernels with it.
+These are all individually selectable via configuration options.
 
 Much documentation for the interface is in the include files.  The
 IPMI include files are:
 
-net/af_ipmi.h - Contains the socket interface.
-
 linux/ipmi.h - Contains the user interface and IOCTL interface for IPMI.
 
 linux/ipmi_smi.h - Contains the interface for system management interfaces
@@ -245,6 +245,16 @@ addressed (because some boards actually
 and the user should not have to care what type of SMI is below them.
 
 
+Watching For Interfaces
+
+When your code comes up, the IPMI driver may or may not have detected
+if IPMI devices exist.  So you might have to defer your setup until
+the device is detected, or you might be able to do it immediately.
+To handle this, and to allow for discovery, you register an SMI
+watcher with ipmi_smi_watcher_register() to iterate over interfaces
+and tell you when they come and go.
+
+
 Creating the User
 
 To user the message handler, you must first create a user using
@@ -263,7 +273,7 @@ closing the device automatically destroy
 
 Messaging
 
-To send a message from kernel-land, the ipmi_request() call does
+To send a message from kernel-land, the ipmi_request_settime() call does
 pretty much all message handling.  Most of the parameter are
 self-explanatory.  However, it takes a "msgid" parameter.  This is NOT
 the sequence number of messages.  It is simply a long value that is
@@ -352,11 +362,12 @@ that for more details.
 The SI Driver
 -------------
 
-The SI driver allows up to 4 KCS or SMIC interfaces to be configured
-in the system.  By default, scan the ACPI tables for interfaces, and
-if it doesn't find any the driver will attempt to register one KCS
-interface at the spec-specified I/O port 0xca2 without interrupts.
-You can change this at module load time (for a module) with:
+The SI driver allows KCS, BT, and SMIC interfaces to be configured
+in the system.  It discovers interfaces through a host of different
+methods, depending on the system.
+
+You can specify up to four interfaces on the module load line and
+control some module parameters:
 
   modprobe ipmi_si.o type=<type1>,<type2>....
        ports=<port1>,<port2>... addrs=<addr1>,<addr2>...
@@ -367,7 +378,7 @@ You can change this at module load time
        force_kipmid=<enable1>,<enable2>,...
        kipmid_max_busy_us=<ustime1>,<ustime2>,...
        unload_when_empty=[0|1]
-       trydefaults=[0|1] trydmi=[0|1] tryacpi=[0|1]
+       trydmi=[0|1] tryacpi=[0|1]
        tryplatform=[0|1] trypci=[0|1]
 
 Each of these except try... items is a list, the first item for the
@@ -386,10 +397,6 @@ use the I/O port given as the device add
 If you specify irqs as non-zero for an interface, the driver will
 attempt to use the given interrupt for the device.
 
-trydefaults sets whether the standard IPMI interface at 0xca2 and
-any interfaces specified by ACPE are tried.  By default, the driver
-tries it, set this value to zero to turn this off.
-
 The other try... items disable discovery by their corresponding
 names.  These are all enabled by default, set them to zero to disable
 them.  The tryplatform disables openfirmware.
@@ -434,7 +441,7 @@ kernel command line as:
 
   ipmi_si.type=<type1>,<type2>...
        ipmi_si.ports=<port1>,<port2>... ipmi_si.addrs=<addr1>,<addr2>...
-       ipmi_si.irqs=<irq1>,<irq2>... ipmi_si.trydefaults=[0|1]
+       ipmi_si.irqs=<irq1>,<irq2>...
        ipmi_si.regspacings=<sp1>,<sp2>,...
        ipmi_si.regsizes=<size1>,<size2>,...
        ipmi_si.regshifts=<shift1>,<shift2>,...
@@ -444,11 +451,6 @@ kernel command line as:
 
 It works the same as the module parameters of the same names.
 
-By default, the driver will attempt to detect any device specified by
-ACPI, and if none of those then a KCS device at the spec-specified
-0xca2.  If you want to turn this off, set the "trydefaults" option to
-false.
-
 If your IPMI interface does not support interrupts and is a KCS or
 SMIC interface, the IPMI driver will start a kernel thread for the
 interface to help speed things up.  This is a low-priority kernel
@@ -500,7 +502,8 @@ at module load time (for a module) with:
 	addr=<i2caddr1>[,<i2caddr2>[,...]]
 	adapter=<adapter1>[,<adapter2>[...]]
 	dbg=<flags1>,<flags2>...
-        slave_addrs=<addr1>,<addr2>,...
+	slave_addrs=<addr1>,<addr2>,...
+	tryacpi=[0|1] trydmi=[0|1]
 	[dbg_probe=1]
 
 The addresses are normal I2C addresses.  The adapter is the string
@@ -513,6 +516,9 @@ spaces in kernel parameters.
 The debug flags are bit flags for each BMC found, they are:
 IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
 
+The tryxxx parameters can be used to disable detecting interfaces
+from various sources.
+
 Setting dbg_probe to 1 will enable debugging of the probing and
 detection process for BMCs on the SMBusses.
 
@@ -535,7 +541,8 @@ kernel command line as:
 	ipmi_ssif.adapter=<adapter1>[,<adapter2>[...]]
 	ipmi_ssif.dbg=<flags1>[,<flags2>[...]]
 	ipmi_ssif.dbg_probe=1
-        ipmi_ssif.slave_addrs=<addr1>[,<addr2>[...]]
+	ipmi_ssif.slave_addrs=<addr1>[,<addr2>[...]]
+	ipmi_ssif.tryacpi=[0|1] ipmi_ssif.trydmi=[0|1]
 
 These are the same options as on the module command line.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/isdn/README linux-libre-4.10-rc8-gnu/Documentation/isdn/README
--- linux-libre-4.9-gnu/Documentation/isdn/README	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/isdn/README	2017-02-12 16:03:20.000000000 -0500
@@ -332,7 +332,7 @@ README for the ISDN-subsystem
 4. Device-inodes
 
    The major and minor numbers and their names are described in
-   Documentation/devices.txt. The major numbers are:
+   Documentation/admin-guide/devices.rst. The major numbers are:
 
      43 for the ISDN-tty's.
      44 for the ISDN-callout-tty's.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ja_JP/HOWTO linux-libre-4.10-rc8-gnu/Documentation/ja_JP/HOWTO
--- linux-libre-4.9-gnu/Documentation/ja_JP/HOWTO	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ja_JP/HOWTO	1969-12-31 19:00:00.000000000 -0500
@@ -1,637 +0,0 @@
-NOTE:
-This is a version of Documentation/HOWTO translated into Japanese.
-This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
-and the JF Project team <www.linux.or.jp/JF>.
-If you find any difference between this document and the original file
-or a problem with the translation,
-please contact the maintainer of this file or JF project.
-
-Please also note that the purpose of this file is to be easier to read
-for non English (read: Japanese) speakers and is not intended as a
-fork. So if you have any comments or updates for this file, please try
-to update the original English file first.
-
-Last Updated: 2013/07/19
-==================================
-これは、
-linux-3.10/Documentation/HOWTO
-の和訳です。
-
-翻訳団体： JF プロジェクト < http://linuxjf.sourceforge.jp/ >
-翻訳日： 2013/7/19
-翻訳者： Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
-校正者： 松倉さん <nbh--mats at nifty dot com>
-         小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
-         武井伸光さん、<takei at webmasters dot gr dot jp>
-         かねこさん (Seiji Kaneko) <skaneko at a2 dot mbn dot or dot jp>
-         野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
-         河内さん (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com>
-         岩本さん (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp>
-         内田さん (Satoshi Uchida) <s-uchida at ap dot jp dot nec dot com>
-==================================
-
-Linux カーネル開発のやり方
--------------------------------
-
-これは上のトピック( Linux カーネル開発のやり方)の重要な事柄を網羅した
-ドキュメントです。ここには Linux カーネル開発者になるための方法と
-Linux カーネル開発コミュニティと共に活動するやり方を学ぶ方法が含まれて
-います。カーネルプログラミングに関する技術的な項目に関することは何も含
-めないようにしていますが、カーネル開発者となるための正しい方向に向かう
-手助けになります。
-
-もし、このドキュメントのどこかが古くなっていた場合には、このドキュメン
-トの最後にリストしたメンテナにパッチを送ってください。
-
-はじめに
----------
-
-あなたは　Linux カーネルの開発者になる方法を学びたいのでしょうか？　そ
-れともあなたは上司から「このデバイスの Linux ドライバを書くように」と
-言われているのでしょうか？　
-この文書の目的は、あなたが踏むべき手順と、コミュニティと一緒にうまく働
-くヒントを書き下すことで、あなたが知るべき全てのことを教えることです。
-また、このコミュニティがなぜ今うまくまわっているのかという理由の一部も
-説明しようと試みています。
-
-
-カーネルは 少量のアーキテクチャ依存部分がアセンブリ言語で書かれている
-以外は大部分は C 言語で書かれています。C言語をよく理解していることはカー
-ネル開発者には必要です。アーキテクチャ向けの低レベル部分の開発をするの
-でなければ、(どんなアーキテクチャでも)アセンブリ(訳注: 言語)は必要あり
-ません。以下の本は、C 言語の十分な知識や何年もの経験に取って代わるもの
-ではありませんが、少なくともリファレンスとしては良い本です。
- - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
- -『プログラミング言語Ｃ第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版]
- - "Practical C Programming" by Steve Oualline [O'Reilly]
- - 『C実践プログラミング第3版』(Steve Oualline著 望月康司監訳 谷口功訳) [オライリージャパン]
- - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
- - 『新・詳説 C 言語 H&S リファレンス』
-       (サミュエル P ハービソン/ガイ L スティール共著 斉藤 信男監訳)[ソフトバンク]
-
-カーネルは GNU C と GNU ツールチェインを使って書かれています。カーネル
-は ISO C89 仕様に準拠して書く一方で、標準には無い言語拡張を多く使って
-います。カーネルは標準 C ライブラリとは関係がないといった、C 言語フリー
-スタンディング環境です。そのため、C の標準で使えないものもあります。任
-意の long long の除算や浮動小数点は使えません。
-ときどき、カーネルがツールチェインや C 言語拡張に置いている前提がどう
-なっているのかわかりにくいことがあり、また、残念なことに決定的なリファ
-レンスは存在しません。情報を得るには、gcc の info ページ( info gcc )を
-見てください。
-
-あなたは既存の開発コミュニティと一緒に作業する方法を学ぼうとしているこ
-とに留意してください。そのコミュニティは、コーディング、スタイル、
-開発手順について高度な標準を持つ、多様な人の集まりです。
-地理的に分散した大規模なチームに対してもっともうまくいくとわかったこと
-をベースにしながら、これらの標準は長い時間をかけて築かれてきました。
-これらはきちんと文書化されていますから、事前にこれらの標準についてでき
-るだけたくさん学んでください。また皆があなたやあなたの会社のやり方に合わ
-せてくれると思わないでください。
-
-法的問題
-------------
-
-Linux カーネルのソースコードは GPL ライセンスの下でリリースされていま
-す。ライセンスの詳細については、ソースツリーのメインディレクトリに存在
-する、COPYING のファイルを見てください。もしライセンスについてさらに質
-問があれば、Linux Kernel メーリングリストに質問するのではなく、どうぞ
-法律家に相談してください。メーリングリストの人達は法律家ではなく、法的
-問題については彼らの声明はあてにするべきではありません。
-
-GPL に関する共通の質問や回答については、以下を参照してください。
-	http://www.gnu.org/licenses/gpl-faq.html
-
-ドキュメント
-------------
-
-Linux カーネルソースツリーは幅広い範囲のドキュメントを含んでおり、それ
-らはカーネルコミュニティと会話する方法を学ぶのに非常に貴重なものです。
-新しい機能がカーネルに追加される場合、その機能の使い方について説明した
-新しいドキュメントファイルも追加することを勧めます。
-カーネルの変更が、カーネルがユーザ空間に公開しているインターフェイスの
-変更を引き起こす場合、その変更を説明するマニュアルページのパッチや情報
-をマニュアルページのメンテナ mtk.manpages@gmail.com に送り、CC を
-linux-api@ver.kernel.org に送ることを勧めます。
-
-以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で
-す-
-
-  README
-    このファイルは Linuxカーネルの簡単な背景とカーネルを設定(訳注
-    configure )し、生成(訳注 build )するために必要なことは何かが書かれ
-    ています。カーネルに関して初めての人はここからスタートすると良いで
-    しょう。
-
-  Documentation/Changes
-     このファイルはカーネルをうまく生成(訳注 build )し、走らせるのに最
-     小限のレベルで必要な数々のソフトウェアパッケージの一覧を示してい
-     ます。
-
-  Documentation/CodingStyle
-    これは Linux カーネルのコーディングスタイルと背景にある理由を記述
-    しています。全ての新しいコードはこのドキュメントにあるガイドライン
-    に従っていることを期待されています。大部分のメンテナはこれらのルー
-    ルに従っているものだけを受け付け、多くの人は正しいスタイルのコード
-    だけをレビューします。
-
-  Documentation/SubmittingPatches
-  Documentation/SubmittingDrivers
-     これらのファイルには、どうやってうまくパッチを作って投稿するかに
-     ついて非常に詳しく書かれており、以下を含みます(これだけに限らない
-     けれども)
-        - Email に含むこと
-        - Email の形式
-        - だれに送るか
-     これらのルールに従えばうまくいくことを保証することではありません
-     が (すべてのパッチは内容とスタイルについて精査を受けるので)、
-     ルールに従わなければ間違いなくうまくいかないでしょう。
-
-     この他にパッチを作る方法についてのよくできた記述は-
-
-	"The Perfect Patch"
-		http://www.ozlabs.org/~akpm/stuff/tpp.txt
-	"Linux kernel patch submission format"
-		http://linux.yyz.us/patch-format.html
-
-  Documentation/stable_api_nonsense.txt
-     このファイルはカーネルの中に不変のAPIを持たないことにした意識的な
-     決断の背景にある理由について書かれています。以下のようなことを含
-     んでいます-
-       - サブシステムとの間に層を作ること(コンパチビリティのため?)
-       - オペレーティングシステム間のドライバの移植性
-       - カーネルソースツリーの素早い変更を遅らせる(もしくは素早い変更
-         を妨げる)
-     このドキュメントは Linux 開発の思想を理解するのに非常に重要です。
-     そして、他のOSでの開発者が Linux に移る時にとても重要です。
-
-  Documentation/SecurityBugs
-    もし Linux カーネルでセキュリティ問題を発見したように思ったら、こ
-    のドキュメントのステップに従ってカーネル開発者に連絡し、問題解決を
-    支援してください。
-
-  Documentation/ManagementStyle
-    このドキュメントは Linux カーネルのメンテナ達がどう行動するか、
-    彼らの手法の背景にある共有されている精神について記述しています。こ
-    れはカーネル開発の初心者なら（もしくは、単に興味があるだけの人でも）
-    重要です。なぜならこのドキュメントは、カーネルメンテナ達の独特な
-    行動についての多くの誤解や混乱を解消するからです。
-
-  Documentation/stable_kernel_rules.txt
-    このファイルはどのように stable カーネルのリリースが行われるかのルー
-    ルが記述されています。そしてこれらのリリースの中のどこかで変更を取
-    り入れてもらいたい場合に何をすれば良いかが示されています。
-
-  Documentation/kernel-docs.txt
-　　カーネル開発に付随する外部ドキュメントのリストです。もしあなたが
-    探しているものがカーネル内のドキュメントでみつからなかった場合、
-    このリストをあたってみてください。
-
-  Documentation/applying-patches.txt
-    パッチとはなにか、パッチをどうやって様々なカーネルの開発ブランチに
-    適用するのかについて正確に記述した良い入門書です。
-
-カーネルはソースコードから自動的に生成可能な多数のドキュメントを自分自
-身でもっています。これにはカーネル内 API のすべての記述や、どう正しく
-ロックをかけるかの規則が含まれます。このドキュメントは
-Documentation/DocBook/ ディレクトリに作られ、以下のように
-	make pdfdocs
-	make psdocs
-	make htmldocs
-	make mandocs
-コマンドを実行するとメインカーネルのソースディレクトリから
-それぞれ、PDF, Postscript, HTML, man page の形式で生成されます。
-
-カーネル開発者になるには
----------------------------
-
-もしあなたが、Linux カーネル開発について何も知らないならば、
-KernelNewbies プロジェクトを見るべきです
-	http://kernelnewbies.org
-
-このサイトには役に立つメーリングリストがあり、基本的なカーネル開発に関
-するほとんどどんな種類の質問もできます (既に回答されているようなことを
-聞く前にまずはアーカイブを調べてください)。
-またここには、リアルタイムで質問を聞くことができる IRC チャネルや、Linux
-カーネルの開発に関して学ぶのに便利なたくさんの役に立つドキュメントがあ
-ります。
-
-web サイトには、コードの構成、サブシステム、現在存在するプロジェクト(ツ
-リーにあるもの無いものの両方)の基本的な管理情報があります。
-ここには、また、カーネルのコンパイルのやり方やパッチの当て方などの間接
-的な基本情報も記述されています。
-
-あなたがどこからスタートして良いかわからないが、Linux カーネル開発コミュ
-ニティに参加して何かすることをさがしている場合には、Linux kernel
-Janitor's プロジェクトにいけば良いでしょう -
-	http://kernelnewbies.org/KernelJanitors
-ここはそのようなスタートをするのにうってつけの場所です。ここには、
-Linux カーネルソースツリーの中に含まれる、きれいにし、修正しなければな
-らない、単純な問題のリストが記述されています。このプロジェクトに関わる
-開発者と一緒に作業することで、あなたのパッチを Linuxカーネルツリーに入
-れるための基礎を学ぶことができ、そしてもしあなたがまだアイディアを持っ
-ていない場合には、次にやる仕事の方向性が見えてくるかもしれません。
-
-もしあなたが、すでにひとまとまりコードを書いていて、カーネルツリーに入
-れたいと思っていたり、それに関する適切な支援を求めたい場合、カーネル
-メンターズプロジェクトはそのような皆さんを助けるためにできました。
-ここにはメーリングリストがあり、以下から参照できます
-	http://selenic.com/mailman/listinfo/kernel-mentors
-
-実際に Linux カーネルのコードについて修正を加える前に、どうやってその
-コードが動作するのかを理解することが必要です。そのためには、特別なツー
-ルの助けを借りてでも、それを直接よく読むことが最良の方法です(ほとんど
-のトリッキーな部分は十分にコメントしてありますから)。そういうツールで
-特におすすめなのは、Linux クロスリファレンスプロジェクトです。これは、
-自己参照方式で、索引がついた web 形式で、ソースコードを参照することが
-できます。この最新の素晴しいカーネルコードのリポジトリは以下で見つかり
-ます-
-	http://lxr.free-electrons.com/
-
-開発プロセス
------------------------
-
-Linux カーネルの開発プロセスは現在幾つかの異なるメインカーネル「ブラン
-チ」と多数のサブシステム毎のカーネルブランチから構成されます。
-これらのブランチとは-
-  - メインの 3.x カーネルツリー
-  - 3.x.y -stable カーネルツリー
-  - 3.x -git カーネルパッチ
-  - サブシステム毎のカーネルツリーとパッチ
-  - 統合テストのための 3.x -next カーネルツリー
-
-3.x カーネルツリー
------------------
-
-3.x カーネルは Linus Torvalds によってメンテナンスされ、kernel.org
-の pub/linux/kernel/v3.x/ ディレクトリに存在します。この開発プロセスは
-以下のとおり-
-
-  - 新しいカーネルがリリースされた直後に、2週間の特別期間が設けられ、
-    この期間中に、メンテナ達は Linus に大きな差分を送ることができます。
-    このような差分は通常 -next カーネルに数週間含まれてきたパッチです。
-    大きな変更は git(カーネルのソース管理ツール、詳細は
-    http://git-scm.com/ 参照) を使って送るのが好ましいやり方ですが、パッ
-    チファイルの形式のまま送るのでも十分です。
-
-  - 2週間後、-rc1 カーネルがリリースされ、この後にはカーネル全体の安定
-    性に影響をあたえるような新機能は含まない類のパッチしか取り込むこと
-    はできません。新しいドライバ(もしくはファイルシステム)のパッチは
-    -rc1 の後で受け付けられることもあることを覚えておいてください。な
-    ぜなら、変更が独立していて、追加されたコードの外の領域に影響を与え
-    ない限り、退行のリスクは無いからです。-rc1 がリリースされた後、
-    Linus へパッチを送付するのに git を使うこともできますが、パッチは
-    レビューのために、パブリックなメーリングリストへも同時に送る必要が
-    あります。
-
-  - 新しい -rc は Linus が、最新の git ツリーがテスト目的であれば十分
-    に安定した状態にあると判断したときにリリースされます。目標は毎週新
-    しい -rc カーネルをリリースすることです。
-
-  - このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
-    す。このプロセスはだいたい 6週間継続します。
-
-Andrew Morton が Linux-kernel メーリングリストにカーネルリリースについ
-て書いたことをここで言っておくことは価値があります-
-  「カーネルがいつリリースされるかは誰も知りません。なぜなら、これは現
-  実に認識されたバグの状況によりリリースされるのであり、前もって決めら
-  れた計画によってリリースされるものではないからです。」
-
-3.x.y -stable カーネルツリー
----------------------------
-
-バージョン番号が3つの数字に分かれているカーネルは -stable カーネルです。
-これには、3.x カーネルで見つかったセキュリティ問題や重大な後戻りに対
-する比較的小さい重要な修正が含まれます。
-
-これは、開発/実験的バージョンのテストに協力することに興味が無く、
-最新の安定したカーネルを使いたいユーザに推奨するブランチです。
-
-もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が
-最新の安定版カーネルです。
-
-3.x.y は "stable" チーム <stable@vger.kernel.org> でメンテされており、必
-要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
-た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
-の場合はこれに対してだいたいの場合、すぐにリリースがされます。
-
-カーネルツリーに入っている、Documentation/stable_kernel_rules.txt ファ
-イルにはどのような種類の変更が -stable ツリーに受け入れ可能か、またリ
-リースプロセスがどう動くかが記述されています。
-
-3.x -git パッチ
-------------------
-
-git リポジトリで管理されているLinus のカーネルツリーの毎日のスナップ
-ショットがあります。(だから -git という名前がついています)。これらのパッ
-チはおおむね毎日リリースされており、Linus のツリーの現状を表します。こ
-れは -rc カーネルと比べて、パッチが大丈夫かどうかも確認しないで自動的
-に生成されるので、より実験的です。
-
-サブシステム毎のカーネルツリーとパッチ
--------------------------------------------
-
-それぞれのカーネルサブシステムのメンテナ達は --- そして多くのカーネル
-サブシステムの開発者達も --- 各自の最新の開発状況をソースリポジトリに
-公開しています。そのため、自分とは異なる領域のカーネルで何が起きている
-かを他の人が見られるようになっています。開発が早く進んでいる領域では、
-開発者は自身の投稿がどのサブシステムカーネルツリーを元にしているか質問
-されるので、その投稿とすでに進行中の他の作業との衝突が避けられます。
-
-大部分のこれらのリポジトリは git ツリーです。しかしその他の SCM や
-quilt シリーズとして公開されているパッチキューも使われています。これら
-のサブシステムリポジトリのアドレスは MAINTAINERS ファイルにリストされ
-ています。これらの多くは http://git.kernel.org/ で参照することができま
-す。
-
-提案されたパッチがこのようなサブシステムツリーにコミットされる前に、メー
-リングリストで事前にレビューにかけられます（以下の対応するセクションを
-参照）。いくつかのカーネルサブシステムでは、このレビューは patchwork
-というツールによって追跡されます。Patchwork は web インターフェイスに
-よってパッチ投稿の表示、パッチへのコメント付けや改訂などができ、そして
-メンテナはパッチに対して、レビュー中、受付済み、拒否というようなマーク
-をつけることができます。大部分のこれらの patchwork のサイトは
-http://patchwork.kernel.org/ でリストされています。
-
-統合テストのための 3.x -next カーネルツリー
----------------------------------------------
-
-サブシステムツリーの更新内容がメインラインの 3.x ツリーにマージされ
-る前に、それらは統合テストされる必要があります。この目的のため、実質的
-に全サブシステムツリーからほぼ毎日プルされてできる特別なテスト用のリ
-ポジトリが存在します-
-       http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
-
-このやり方によって、-next カーネルは次のマージ機会でどんなものがメイン
-ラインカーネルにマージされるか、おおまかなの展望を提供します。-next 
-カーネルの実行テストを行う冒険好きなテスターは大いに歓迎されます
-
-バグレポート
--------------
-
-bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを追跡する
-場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。
-どう kernel bugzilla を使うかの詳細は、以下を参照してください-
-	http://bugzilla.kernel.org/page.cgi?id=faq.html
-メインカーネルソースディレクトリにあるファイル REPORTING-BUGS はカーネ
-ルバグらしいものについてどうレポートするかの良いテンプレートであり、問
-題の追跡を助けるためにカーネル開発者にとってどんな情報が必要なのかの詳
-細が書かれています。
-
-バグレポートの管理
--------------------
-
-あなたのハッキングのスキルを訓練する最高の方法のひとつに、他人がレポー
-トしたバグを修正することがあります。あなたがカーネルをより安定化させる
-こに寄与するということだけでなく、あなたは 現実の問題を修正することを
-学び、自分のスキルも強化でき、また他の開発者があなたの存在に気がつき
-ます。バグを修正することは、多くの開発者の中から自分が功績をあげる最善
-の道です、なぜなら多くの人は他人のバグの修正に時間を浪費することを好ま
-ないからです。
-
-すでにレポートされたバグのために仕事をするためには、
-http://bugzilla.kernel.org に行ってください。もし今後のバグレポートに
-ついてアドバイスを受けたいのであれば、bugme-new メーリングリスト(新し
-いバグレポートだけがここにメールされる) または bugme-janitor メーリン
-グリスト(bugzilla の変更毎にここにメールされる)を購読できます。
-
-	http://lists.linux-foundation.org/mailman/listinfo/bugme-new
-	http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
-
-メーリングリスト
--------------
-
-上のいくつかのドキュメントで述べていますが、コアカーネル開発者の大部分
-は Linux kernel メーリングリストに参加しています。このリストの登録/脱
-退の方法については以下を参照してください-
-	http://vger.kernel.org/vger-lists.html#linux-kernel
-
-このメーリングリストのアーカイブは web 上の多数の場所に存在します。こ
-れらのアーカイブを探すにはサーチエンジンを使いましょう。例えば-
-	http://dir.gmane.org/gmane.linux.kernel
-
-リストに投稿する前にすでにその話題がアーカイブに存在するかどうかを検索
-することを是非やってください。多数の事がすでに詳細に渡って議論されて
-おり、アーカイブにのみ記録されています。
-
-大部分のカーネルサブシステムも自分の個別の開発を実施するメーリングリス
-トを持っています。個々のグループがどんなリストを持っているかは、
-MAINTAINERS ファイルにリストがありますので参照してください。
-
-多くのリストは kernel.org でホストされています。これらの情報は以下にあ
-ります-
-	http://vger.kernel.org/vger-lists.html
-
-メーリングリストを使う場合、良い行動習慣に従うようにしましょう。
-少し安っぽいが、以下の URL は上のリスト(や他のリスト)で会話する場合の
-シンプルなガイドラインを示しています-
-	http://www.albion.com/netiquette/
-
-もし複数の人があなたのメールに返事をした場合、CC: で受ける人のリストは
-だいぶ多くなるでしょう。良い理由がない場合、CC: リストから誰かを削除を
-しないように、また、メーリングリストのアドレスだけにリプライすることの
-ないようにしましょう。1つは送信者から、もう1つはリストからのように、メー
-ルを2回受けることになってもそれに慣れ、しゃれたメールヘッダーを追加し
-てこの状態を変えようとしないように。人々はそのようなことは好みません。
-
-今までのメールでのやりとりとその間のあなたの発言はそのまま残し、
-"John Kernelhacker wrote ...:" の行をあなたのリプライの先頭行にして、
-メールの先頭でなく、各引用行の間にあなたの言いたいことを追加するべきで
-す。
-
-もしパッチをメールに付ける場合は、Documentation/SubmittingPatches に提
-示されているように、それは プレーンな可読テキストにすることを忘れない
-ようにしましょう。カーネル開発者は 添付や圧縮したパッチを扱いたがりま
-せん-
-彼らはあなたのパッチの行毎にコメントを入れたいので、そのためにはそうす
-るしかありません。あなたのメールプログラムが空白やタブを圧縮しないよう
-に確認した方が良いです。最初の良いテストとしては、自分にメールを送って
-みて、そのパッチを自分で当ててみることです。もしそれがうまく行かないな
-ら、あなたのメールプログラムを直してもらうか、正しく動くように変えるべ
-きです。
-
-とりわけ、他の登録者に対する尊敬を表すようにすることを覚えておいてくだ
-さい。
-
-コミュニティと共に働くこと
---------------------------
-
-カーネルコミュニティのゴールは可能なかぎり最高のカーネルを提供すること
-です。あなたがパッチを受け入れてもらうために投稿した場合、それは、技術
-的メリットだけがレビューされます。その際、あなたは何を予想すべきでしょ
-うか?
-  - 批判
-  - コメント
-  - 変更の要求
-  - パッチの正当性の証明要求
-  - 沈黙
-
-思い出してください、ここはあなたのパッチをカーネルに入れる話です。あ
-なたは、あなたのパッチに対する批判とコメントを受け入れるべきで、それら
-を技術的レベルで評価して、パッチを再作成するか、なぜそれらの変更をすべ
-きでないかを明確で簡潔な理由の説明を提供してください。
-もし、あなたのパッチに何も反応がない場合、たまにはメールの山に埋もれて
-見逃され、あなたの投稿が忘れられてしまうこともあるので、数日待って再度
-投稿してください。
-
-あなたがやるべきでないものは?
-  - 質問なしにあなたのパッチが受け入れられると想像すること
-  - 守りに入ること
-  - コメントを無視すること
-  - 要求された変更を何もしないでパッチを出し直すこと
-
-可能な限り最高の技術的解決を求めているコミュニティでは、パッチがどのく
-らい有益なのかについては常に異なる意見があります。あなたは協調的である
-べきですし、また、あなたのアイディアをカーネルに対してうまく合わせるよ
-うにすることが望まれています。もしくは、最低限あなたのアイディアがそれ
-だけの価値があるとすすんで証明するようにしなければなりません。
-正しい解決に向かって進もうという意志がある限り、間違うことがあっても許
-容されることを忘れないでください。
-
-あなたの最初のパッチに単に 1ダースもの修正を求めるリストの返答になるこ
-とも普通のことです。これはあなたのパッチが受け入れられないということで
-は *ありません*、そしてあなた自身に反対することを意味するのでも *ありま
-せん*。単に自分のパッチに対して指摘された問題を全て修正して再送すれば
-良いのです。
-
-
-カーネルコミュニティと企業組織のちがい
------------------------------------------------------------------
-
-カーネルコミュニティは大部分の伝統的な会社の開発環境とは異ったやり方で
-動いています。以下は問題を避けるためにできると良いことのリストです-
-
-  あなたの提案する変更について言うときのうまい言い方：
-
-    - "これは複数の問題を解決します"
-    - "これは2000行のコードを削除します"
-    - "以下のパッチは、私が言おうとしていることを説明するものです"
-    - "私はこれを5つの異なるアーキテクチャでテストしたのですが..."
-    - "以下は一連の小さなパッチ群ですが..."
-    - "これは典型的なマシンでの性能を向上させます.."
-
-  やめた方が良い悪い言い方：
-
-    - このやり方で AIX/ptx/Solaris ではできたので、できるはずだ
-    - 私はこれを20年もの間やってきた、だから
-    - これは、私の会社が金儲けをするために必要だ
-    - これは我々のエンタープライズ向け商品ラインのためである
-    - これは 私が自分のアイディアを記述した、1000ページの設計資料である
-    - 私はこれについて、6ケ月作業している。
-    - 以下は ... に関する5000行のパッチです
-    - 私は現在のぐちゃぐちゃを全部書き直した、それが以下です...
-    - 私は〆切がある、そのためこのパッチは今すぐ適用される必要がある
-
-カーネルコミュニティが大部分の伝統的なソフトウェアエンジニアリングの労
-働環境と異なるもう一つの点は、やりとりに顔を合わせないということです。
-email と irc を第一のコミュニケーションの形とする一つの利点は、性別や
-民族の差別がないことです。Linux カーネルの職場環境は女性や少数民族を受
-容します。なぜなら、email アドレスによってのみあなたが認識されるからで
-す。
-国際的な側面からも活動領域を均等にするようにします。なぜならば、あなた
-は人の名前で性別を想像できないからです。ある男性が アンドレアという名
-前で、女性の名前は パット かもしれません (訳注 Andrea は米国では女性、
-それ以外(欧州など)では男性名として使われることが多い。同様に、Pat は
-Patricia (主に女性名)や Patrick (主に男性名)の略称)。
-Linux カーネルの活動をして、意見を表明したことがある大部分の女性は、前
-向きな経験をもっています。
-
-言葉の壁は英語が得意でない一部の人には問題になります。
-メーリングリストの中できちんとアイディアを交換するには、相当うまく英語
-を操れる必要があることもあります。そのため、あなたは自分のメール
-を送る前に英語で意味が通じているかをチェックすることをお薦めします。
-
-変更を分割する
----------------------
-
-Linux カーネルコミュニティは、一度に大量のコードの塊を喜んで受容するこ
-とはありません。変更は正確に説明される必要があり、議論され、小さい、個
-別の部分に分割する必要があります。これはこれまで多くの会社がやり慣れて
-きたことと全く正反対のことです。あなたのプロポーザルは、開発プロセスのと
-ても早い段階から紹介されるべきです。そうすれば あなたは自分のやってい
-ることにフィードバックを得られます。これは、コミュニティからみれば、あ
-なたが彼らと一緒にやっているように感じられ、単にあなたの提案する機能の
-ゴミ捨て場として使っているのではない、と感じられるでしょう。
-しかし、一度に 50 もの email をメーリングリストに送りつけるようなことは
-やってはいけません、あなたのパッチ群はいつもどんな時でもそれよりは小さ
-くなければなりません。
-
-パッチを分割する理由は以下です-
-
-1) 小さいパッチはあなたのパッチが適用される見込みを大きくします、カー
-   ネルの人達はパッチが正しいかどうかを確認する時間や労力をかけないか
-   らです。5行のパッチはメンテナがたった1秒見るだけで適用できます。
-   しかし、500行のパッチは、正しいことをレビューするのに数時間かかるか
-   もしれません(時間はパッチのサイズなどにより指数関数に比例してかかり
-   ます)
-
-   小さいパッチは何かあったときにデバッグもとても簡単になります。パッ
-   チを1個1個取り除くのは、とても大きなパッチを当てた後に(かつ、何かお
-   かしくなった後で)解剖するのに比べればとても簡単です。
-
-2) 小さいパッチを送るだけでなく、送るまえに、書き直して、シンプルにす
-   る(もしくは、単に順番を変えるだけでも)ことも、とても重要です。
-
-以下はカーネル開発者の Al Viro のたとえ話です：
-
-        "生徒の数学の宿題を採点する先生のことを考えてみてください、先
-        生は生徒が解に到達するまでの試行錯誤を見たいとは思わないでしょ
-        う。先生は簡潔な最高の解を見たいのです。良い生徒はこれを知って
-        おり、そして最終解の前の中間作業を提出することは決してないので
-        す"
-
-        カーネル開発でもこれは同じです。メンテナ達とレビューア達は、
-        問題を解決する解の背後になる思考プロセスを見たいとは思いません。
-        彼らは単純であざやかな解決方法を見たいのです。
-
-あざやかな解を説明するのと、コミュニティと共に仕事をし、未解決の仕事を
-議論することのバランスをキープするのは難しいかもしれません。
-ですから、開発プロセスの早期段階で改善のためのフィードバックをもらうよ
-うにするのも良いですが、変更点を小さい部分に分割して全体ではまだ完成し
-ていない仕事を(部分的に)取り込んでもらえるようにすることも良いことです。
-
-また、でき上がっていないものや、"将来直す" ようなパッチを、本流に含め
-てもらうように送っても、それは受け付けられないことを理解してください。
-
-あなたの変更を正当化する
--------------------
-
-あなたのパッチを分割するのと同時に、なぜその変更を追加しなければならな
-いかを Linux コミュニティに知らせることはとても重要です。新機能は必要
-性と有用性で正当化されなければなりません。
-
-あなたの変更の説明
---------------------
-
-あなたのパッチを送付する場合には、メールの中のテキストで何を言うかにつ
-いて、特別に注意を払ってください。この情報はパッチの ChangeLog に使わ
-れ、いつも皆がみられるように保管されます。これは次のような項目を含め、
-パッチを完全に記述するべきです-
-
-  - なぜ変更が必要か
-  - パッチ全体の設計アプローチ
-  - 実装の詳細
-  - テスト結果
-
-これについて全てがどのようにあるべきかについての詳細は、以下のドキュメ
-ントの ChangeLog セクションを見てください-
-  "The Perfect Patch"
-      http://www.ozlabs.org/~akpm/stuff/tpp.txt
-
-これらのどれもが、時にはとても困難です。これらの慣例を完璧に実施するに
-は数年かかるかもしれません。これは継続的な改善のプロセスであり、そのた
-めには多数の忍耐と決意を必要とするものです。でも、諦めないで、これは可
-能なことです。多数の人がすでにできていますし、彼らも皆最初はあなたと同
-じところからスタートしたのですから。
-
-Paolo Ciarrocchi に感謝、彼は彼の書いた "Development Process"
-(http://lwn.net/Articles/94386/) セクションをこのテキストの原型にする
-ことを許可してくれました。Rundy Dunlap と Gerrit Huizenga はメーリング
-リストでやるべきこととやってはいけないことのリストを提供してくれました。
-以下の人々のレビュー、コメント、貢献に感謝。
-Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
-Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi
-Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
-David A. Wheeler, Junio Hamano, Michael Kerrisk, と Alex Shepard
-彼らの支援なしでは、このドキュメントはできなかったでしょう。
-
-Maintainer: Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ja_JP/stable_api_nonsense.txt linux-libre-4.10-rc8-gnu/Documentation/ja_JP/stable_api_nonsense.txt
--- linux-libre-4.9-gnu/Documentation/ja_JP/stable_api_nonsense.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ja_JP/stable_api_nonsense.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,263 +0,0 @@
-NOTE:
-This is a version of Documentation/stable_api_nonsense.txt into Japanese.
-This document is maintained by IKEDA, Munehiro <m-ikeda@ds.jp.nec.com>
-and the JF Project team <http://www.linux.or.jp/JF/>.
-If you find any difference between this document and the original file
-or a problem with the translation,
-please contact the maintainer of this file or JF project.
-
-Please also note that the purpose of this file is to be easier to read
-for non English (read: Japanese) speakers and is not intended as a
-fork. So if you have any comments or updates of this file, please try
-to update the original English file first.
-
-Last Updated: 2007/07/18
-==================================
-これは、
-linux-2.6.22-rc4/Documentation/stable_api_nonsense.txt の和訳
-です。
-翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日 ： 2007/06/11
-原著作者: Greg Kroah-Hartman < greg at kroah dot com >
-翻訳者 ： 池田 宗広 < m-ikeda at ds dot jp dot nec dot com >
-校正者 ： Masanori Kobayashi さん < zap03216 at nifty dot ne dot jp >
-          Seiji Kaneko さん < skaneko at a2 dot mbn dot or dot jp >
-==================================
-
-
-
-Linux カーネルのドライバインターフェース
-（あなたの質問すべてに対する回答とその他諸々）
-
-Greg Kroah-Hartman <greg at kroah dot com>
-
-
-この文書は、なぜ Linux ではバイナリカーネルインターフェースが定義
-されていないのか、またはなぜ不変のカーネルインターフェースを持たな
-いのか、ということを説明するために書かれた。ここでの話題は「カーネ
-ル内部の」インターフェースについてであり、ユーザー空間とのインター
-フェースではないことを理解してほしい。カーネルとユーザー空間とのイ
-ンターフェースとはアプリケーションプログラムが使用するものであり、
-つまりシステムコールのインターフェースがこれに当たる。これは今まで
-長きに渡り、かつ今後も「まさしく」不変である。私は確か 0.9 か何か
-より前のカーネルを使ってビルドした古いプログラムを持っているが、そ
-れは最新の 2.6 カーネルでもきちんと動作する。ユーザー空間とのイン
-ターフェースは、ユーザーとアプリケーションプログラマが不変性を信頼
-してよいものの一つである。
-
-
-要旨
-----
-
-あなたは不変のカーネルインターフェースが必要だと考えているかもしれ
-ないが、実際のところはそうではない。あなたは必要としているものが分
-かっていない。あなたが必要としているものは安定して動作するドライバ
-であり、それはドライバがメインのカーネルツリーに含まれる場合のみ得
-ることができる。ドライバがメインのカーネルツリーに含まれていると、
-他にも多くの良いことがある。それは、Linux をより強固で、安定な、成
-熟したオペレーティングシステムにすることができるということだ。これ
-こそ、そもそもあなたが Linux を使う理由のはずだ。
-
-
-はじめに
---------
-
-カーネル内部のインターフェース変更を心配しなければならないドライバ
-を書きたいなどというのは、変わり者だけだ。この世界のほとんどの人は、
-そのようなドライバがどんなインターフェースを使っているかなど知らな
-いし、そんなドライバのことなど全く気にもかけていない。
-
-
-まず初めに、クローズソースとか、ソースコードの隠蔽とか、バイナリの
-みが配布される使い物にならない代物[訳注(1)]とか、実体はバイナリ
-コードでそれを読み込むためのラッパー部分のみソースコードが公開され
-ているとか、その他用語は何であれ GPL の下にソースコードがリリース
-されていないカーネルドライバに関する法的な問題について、私は「いか
-なる議論も」行うつもりがない。法的な疑問があるのならば、プログラマ
-である私ではなく、弁護士に相談して欲しい。ここでは単に、技術的な問
-題について述べることにする。（法的な問題を軽視しているわけではない。
-それらは実際に存在するし、あなたはそれをいつも気にかけておく必要が
-ある）
-
-訳注(1)
-「使い物にならない代物」の原文は "blob"
-
-
-さてここでは、バイナリカーネルインターフェースについてと、ソースレ
-ベルでのインターフェースの不変性について、という二つの話題を取り上
-げる。この二つは互いに依存する関係にあるが、まずはバイナリインター
-フェースについて議論を行いやっつけてしまおう。
-
-
-バイナリカーネルインターフェース
---------------------------------
-
-もしソースレベルでのインターフェースが不変ならば、バイナリインター
-フェースも当然のように不変である、というのは正しいだろうか？正しく
-ない。Linux カーネルに関する以下の事実を考えてみてほしい。
-  - あなたが使用するＣコンパイラのバージョンによって、カーネル内部
-    の構造体の配置構造は異なったものになる。また、関数は異なった方
-    法でカーネルに含まれることになるかもしれない（例えばインライン
-    関数として扱われたり、扱われなかったりする）。個々の関数がどの
-    ようにコンパイルされるかはそれほど重要ではないが、構造体のパデ
-    ィングが異なるというのは非常に重要である。
-  - あなたがカーネルのビルドオプションをどのように設定するかによっ
-    て、カーネルには広い範囲で異なった事態が起こり得る。
-      - データ構造は異なるデータフィールドを持つかもしれない
-      - いくつかの関数は全く実装されていない状態になり得る
-        （例：SMP向けではないビルドでは、いくつかのロックは中身が
-          カラにコンパイルされる）
-      - カーネル内のメモリは、異なった方法で配置され得る。これはビ
-        ルドオプションに依存している。
-  - Linux は様々な異なるプロセッサアーキテクチャ上で動作する。
-    あるアーキテクチャ用のバイナリドライバを、他のアーキテクチャで
-    正常に動作させる方法はない。
-
-
-ある特定のカーネル設定を使用し、カーネルをビルドしたのと正確に同じ
-Ｃコンパイラを使用して単にカーネルモジュールをコンパイルするだけで
-も、あなたはこれらいくつもの問題に直面することになる。ある特定の
-Linux ディストリビューションの、ある特定のリリースバージョン用にモ
-ジュールを提供しようと思っただけでも、これらの問題を引き起こすには
-十分である。にも関わらず Linux ディストリビューションの数と、サ
-ポートするディストリビューションのリリース数を掛け算し、それら一つ
-一つについてビルドを行ったとしたら、今度はリリースごとのビルドオプ
-ションの違いという悪夢にすぐさま悩まされることになる。また、ディス
-トリビューションの各リリースバージョンには、異なるハードウェア（プ
-ロセッサタイプや種々のオプション）に対応するため、何種類かのカーネ
-ルが含まれているということも理解して欲しい。従って、ある一つのリ
-リースバージョンだけのためにモジュールを作成する場合でも、あなたは
-何バージョンものモジュールを用意しなければならない。
-
-
-信じて欲しい。このような方法でサポートを続けようとするなら、あなた
-はいずれ正気を失うだろう。遠い昔、私はそれがいかに困難なことか、身
-をもって学んだのだ・・・
-
-
-不変のカーネルソースレベルインターフェース
-------------------------------------------
-
-メインカーネルツリーに含まれていない Linux カーネルドライバを継続
-してサポートしていこうとしている人たちとの議論においては、これは極
-めて「引火性の高い」話題である。[訳注(2)]
-
-訳注(2)
-「引火性の高い」の原文は "volatile"。
-volatile には「揮発性の」「爆発しやすい」という意味の他、「変わり
-やすい」「移り気な」という意味がある。
-「（この話題は）爆発的に激しい論争を巻き起こしかねない」ということ
-を、「（カーネルのソースレベルインターフェースは）移ろい行くもので
-ある」ということを連想させる "volatile" という単語で表現している。
-
-
-Linux カーネルの開発は継続的に速いペースで行われ、決して歩みを緩め
-ることがない。その中でカーネル開発者達は、現状のインターフェースに
-あるバグを見つけ、より良い方法を考え出す。彼らはやがて、現状のイン
-ターフェースがより正しく動作するように修正を行う。その過程で関数の
-名前は変更されるかもしれず、構造体は大きく、または小さくなるかもし
-れず、関数の引数は検討しなおされるかもしれない。そのような場合、引
-き続き全てが正常に動作するよう、カーネル内でこれらのインターフェー
-スを使用している個所も全て同時に修正される。
-
-
-具体的な例として、カーネル内の USB インターフェースを挙げる。USB
-サブシステムはこれまでに少なくとも３回の書き直しが行われ、その結果
-インターフェースが変更された。これらの書き直しはいくつかの異なった
-問題を修正するために行われた。
-  - 同期的データストリームが非同期に変更された。これにより多数のド
-    ライバを単純化でき、全てのドライバのスループットが向上した。今
-    やほとんど全ての USB デバイスは、考えられる最高の速度で動作し
-    ている。
-  - USB ドライバが USB サブシステムのコアから行う、データパケット
-    用のメモリ確保方法が変更された。これに伴い、いくつもの文書化さ
-    れたデッドロック条件を回避するため、全ての USB ドライバはより
-    多くの情報を USB コアに提供しなければならないようになっている。
-
-
-このできごとは、数多く存在するクローズソースのオペレーティングシス
-テムとは全く対照的だ。それらは長期に渡り古い USB インターフェース
-をメンテナンスしなければならない。古いインターフェースが残ることで、
-新たな開発者が偶然古いインターフェースを使い、正しくない方法で開発
-を行ってしまう可能性が生じる。これによりシステムの安定性は危険にさ
-らされることになる。
-
-
-上に挙げたどちらの例においても、開発者達はその変更が重要かつ必要で
-あることに合意し、比較的楽にそれを実行した。もし Linux がソースレ
-ベルでインターフェースの不変性を保証しなければならないとしたら、新
-しいインターフェースを作ると同時に、古い、問題のある方を今後ともメ
-ンテナンスするという余計な仕事を USB の開発者にさせなければならな
-い。Linux の USB 開発者は、自分の時間を使って仕事をしている。よっ
-て、価値のない余計な仕事を報酬もなしに実行しろと言うことはできない。
-
-
-セキュリティ問題も、Linux にとっては非常に重要である。ひとたびセキ
-ュリティに関する問題が発見されれば、それは極めて短期間のうちに修正
-される。セキュリティ問題の発生を防ぐための修正は、カーネルの内部イ
-ンターフェースの変更を何度も引き起こしてきた。その際同時に、変更さ
-れたインターフェースを使用する全てのドライバもまた変更された。これ
-により問題が解消し、将来偶然に問題が再発してしまわないことが保証さ
-れる。もし内部インターフェースの変更が許されないとしたら、このよう
-にセキュリティ問題を修正し、将来再発しないことを保証することなど不
-可能なのだ。
-
-
-カーネルのインターフェースは時が経つにつれクリーンナップを受ける。
-誰も使っていないインターフェースは削除される。これにより、可能な限
-りカーネルが小さく保たれ、現役の全てのインターフェースが可能な限り
-テストされることを保証しているのだ。（使われていないインターフェー
-スの妥当性をテストすることは不可能と言っていいだろう）
-
-
-
-これから何をすべきか
------------------------
-
-では、もしメインのカーネルツリーに含まれない Linux カーネルドライ
-バがあったとして、あなたは、つまり開発者は何をするべきだろうか？全
-てのディストリビューションの全てのカーネルバージョン向けにバイナリ
-のドライバを供給することは悪夢であり、カーネルインターフェースの変
-更を追いかけ続けることもまた過酷な仕事だ。
-
-
-答えは簡単。そのドライバをメインのカーネルツリーに入れてしまえばよ
-い。（ここで言及しているのは、GPL に従って公開されるドライバのこと
-だということに注意してほしい。あなたのコードがそれに該当しないなら
-ば、さよなら。幸運を祈ります。ご自分で何とかしてください。Andrew
-と Linus からのコメント＜Andrew と Linus のコメントへのリンクをこ
-こに置く＞をどうぞ）ドライバがメインツリーに入れば、カーネルのイン
-ターフェースが変更された場合、変更を行った開発者によってドライバも
-修正されることになるだろう。あなたはほとんど労力を払うことなしに、
-常にビルド可能できちんと動作するドライバを手に入れることができる。
-
-
-ドライバをメインのカーネルツリーに入れると、非常に好ましい以下の効
-果がある。
-  - ドライバの品質が向上する一方で、（元の開発者にとっての）メンテ
-    ナンスコストは下がる。
-  - あなたのドライバに他の開発者が機能を追加してくれる。
-  - 誰かがあなたのドライバにあるバグを見つけ、修正してくれる。
-  - 誰かがあなたのドライバにある改善点を見つけてくれる。
-  - 外部インターフェースが変更されドライバの更新が必要になった場合、
-    誰かがあなたの代わりに更新してくれる。
-  - ドライバを入れてくれとディストロに頼まなくても、そのドライバは
-    全ての Linux ディストリビューションに自動的に含まれてリリース
-    される。
-
-
-Linux では、他のどのオペレーティングシステムよりも数多くのデバイス
-が「そのまま」使用できるようになった。また Linux は、どのオペレー
-ティングシステムよりも数多くのプロセッサアーキテクチャ上でそれらの
-デバイスを使用することができるようにもなった。このように、Linux の
-開発モデルは実証されており、今後も間違いなく正しい方向へと進んでい
-くだろう。:)
-
-
-
-------
-
-この文書の初期の草稿に対し、Randy Dunlap, Andrew Morton, David
-Brownell, Hanna Linder, Robert Love, Nishanth Aravamudan から査読
-と助言を頂きました。感謝申し上げます。
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ja_JP/stable_kernel_rules.txt linux-libre-4.10-rc8-gnu/Documentation/ja_JP/stable_kernel_rules.txt
--- linux-libre-4.9-gnu/Documentation/ja_JP/stable_kernel_rules.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ja_JP/stable_kernel_rules.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-NOTE:
-This is Japanese translated version of "Documentation/stable_kernel_rules.txt".
-This one is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
-and JF Project team <www.linux.or.jp/JF>.
-If you find difference with original file or problem in translation,
-please contact maintainer of this file or JF project.
-
-Please also note that purpose of this file is easier to read for non
-English natives and do no intended to fork. So, if you have any
-comment or update of this file, please try to update Original(English)
-file at first.
-
-==================================
-これは、
-linux-2.6.29/Documentation/stable_kernel_rules.txt
-の和訳です。
-
-翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日： 2009/1/14
-翻訳者： Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
-校正者： 武井伸光さん、<takei at webmasters dot gr dot jp>
-         かねこさん (Seiji Kaneko) <skaneko at a2 dot mbn dot or dot jp>
-         小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
-         野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
-         神宮信太郎さん <jin at libjingu dot jp>
-==================================
-
-ずっと知りたかった Linux 2.6 -stable リリースの全て
-
-"-stable" ツリーにどのような種類のパッチが受け入れられるか、どのような
-ものが受け入れられないか、についての規則-
-
- - 明らかに正しく、テストされているものでなければならない。
- - 文脈(変更行の前後)を含めて 100 行より大きくてはいけない。
- - ただ一個のことだけを修正しているべき。
- - 皆を悩ませている本物のバグを修正しなければならない。("これはバグで
-   あるかもしれないが..." のようなものではない)
- - ビルドエラー(CONFIG_BROKENになっているものを除く), oops, ハング、デー
-   タ破壊、現実のセキュリティ問題、その他 "ああ、これはダメだね"という
-   ようなものを修正しなければならない。短く言えば、重大な問題。
- - 新しい device ID とクオークも受け入れられる。
- - どのように競合状態が発生するかの説明も一緒に書かれていない限り、
-   "理論的には競合状態になる"ようなものは不可。
- - いかなる些細な修正も含めることはできない。(スペルの修正、空白のクリー
-   ンアップなど)
- - Documentation/SubmittingPatches の規則に従ったものでなければならない。
- - パッチ自体か同等の修正が Linus のツリーに既に存在しなければならない。
-　 Linus のツリーでのコミットID を -stable へのパッチ投稿の際に引用す
-   ること。
-
--stable ツリーにパッチを送付する手続き-
-
- - 上記の規則に従っているかを確認した後に、stable@vger.kernel.org にパッチ
-   を送る。
- - 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合
-   には NAK を受け取る。この反応は開発者たちのスケジュールによって、数
-   日かかる場合がある。
- - もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの
-   メンテナーによるレビューのために -stable キューに追加される。
- - パッチに stable@vger.kernel.org のアドレスが付加されているときには、それ
-   が Linus のツリーに入る時に自動的に stable チームに email される。
- - セキュリティパッチはこのエイリアス (stable@vger.kernel.org) に送られるべ
-   きではなく、代わりに security@kernel.org のアドレスに送られる。
-
-レビューサイクル-
-
- - -stable メンテナがレビューサイクルを決めるとき、パッチはレビュー委
-   員会とパッチが影響する領域のメンテナ(提供者がその領域のメンテナで無
-   い限り)に送られ、linux-kernel メーリングリストにCCされる。
- - レビュー委員会は 48時間の間に ACK か NAK を出す。
- - もしパッチが委員会のメンバから却下されるか、メンテナ達やメンバが気付
-   かなかった問題が持ちあがり、linux-kernel メンバがパッチに異議を唱え
-   た場合には、パッチはキューから削除される。
- - レビューサイクルの最後に、ACK を受けたパッチは最新の -stable リリー
-   スに追加され、その後に新しい -stable リリースが行われる。
- - セキュリティパッチは、通常のレビューサイクルを通らず、セキュリティ
-   カーネルチームから直接 -stable ツリーに受け付けられる。
-   この手続きの詳細については kernel security チームに問い合わせること。
-
-レビュー委員会-
-
- - この委員会は、このタスクについて活動する多くのボランティアと、少数の
-   非ボランティアのカーネル開発者達で構成されている。
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ja_JP/SubmitChecklist linux-libre-4.10-rc8-gnu/Documentation/ja_JP/SubmitChecklist
--- linux-libre-4.9-gnu/Documentation/ja_JP/SubmitChecklist	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ja_JP/SubmitChecklist	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-NOTE:
-This is a version of Documentation/SubmitChecklist into Japanese.
-This document is maintained by Takenori Nagano <t-nagano@ah.jp.nec.com>
-and the JF Project team <http://www.linux.or.jp/JF/>.
-If you find any difference between this document and the original file
-or a problem with the translation,
-please contact the maintainer of this file or JF project.
-
-Please also note that the purpose of this file is to be easier to read
-for non English (read: Japanese) speakers and is not intended as a
-fork. So if you have any comments or updates of this file, please try
-to update the original English file first.
-
-Last Updated: 2008/07/14
-==================================
-これは、
-linux-2.6.26/Documentation/SubmitChecklist の和訳です。
-
-翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日： 2008/07/14
-翻訳者： Takenori Nagano <t-nagano at ah dot jp dot nec dot com>
-校正者： Masanori Kobayashi さん <zap03216 at nifty dot ne dot jp>
-==================================
-
-
-Linux カーネルパッチ投稿者向けチェックリスト
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-本書では、パッチをより素早く取り込んでもらいたい開発者が実践すべき基本的な事柄
-をいくつか紹介します。ここにある全ての事柄は、Documentation/SubmittingPatches
-などのLinuxカーネルパッチ投稿に際しての心得を補足するものです。
-
- 1: 妥当なCONFIGオプションや変更されたCONFIGオプション、つまり =y, =m, =n
-    全てで正しくビルドできることを確認してください。その際、gcc及びリンカが
-    warningやerrorを出していないことも確認してください。
-
- 2: allnoconfig, allmodconfig オプションを用いて正しくビルドできることを
-    確認してください。
-
- 3: 手許のクロスコンパイルツールやOSDLのPLMのようなものを用いて、複数の
-    アーキテクチャにおいても正しくビルドできることを確認してください。
-
- 4: 64bit長の'unsigned long'を使用しているppc64は、クロスコンパイルでの
-    チェックに適当なアーキテクチャです。
-
- 5: カーネルコーディングスタイルに準拠しているかどうか確認してください(!)
-
- 6: CONFIGオプションの追加・変更をした場合には、CONFIGメニューが壊れていない
-    ことを確認してください。
-
- 7: 新しくKconfigのオプションを追加する際には、必ずそのhelpも記述してください。
-
- 8: 適切なKconfigの依存関係を考えながら慎重にチェックしてください。
-    ただし、この作業はマシンを使ったテストできちんと行うのがとても困難です。
-    うまくやるには、自分の頭で考えることです。
-
- 9: sparseを利用してちゃんとしたコードチェックをしてください。
-
-10: 'make checkstack' と 'make namespacecheck' を利用し、問題が発見されたら
-    修正してください。'make checkstack' は明示的に問題を示しませんが、どれか
-    １つの関数が512バイトより大きいスタックを使っていれば、修正すべき候補と
-    なります。
-
-11: グローバルなkernel API を説明する kernel-doc をソースの中に含めてください。
-    ( staticな関数においては必須ではありませんが、含めてもらっても結構です )
-    そして、'make htmldocs' もしくは 'make mandocs' を利用して追記した
-    ドキュメントのチェックを行い、問題が見つかった場合には修正を行ってください。
-
-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: もしパッチがディスクのI/O性能などに影響を与えるようであれば、
-    'CONFIG_LBDAF'オプションを有効にした場合と無効にした場合の両方で
-    テストを実施してみてください。
-
-15: lockdepの機能を全て有効にした上で、全てのコードパスを評価してください。
-
-16: /proc に新しいエントリを追加した場合には、Documentation/ 配下に
-    必ずドキュメントを追加してください。
-
-17: 新しいブートパラメータを追加した場合には、
-    必ずDocumentation/kernel-parameters.txt に説明を追加してください。
-
-18: 新しくmoduleにパラメータを追加した場合には、MODULE_PARM_DESC()を
-    利用して必ずその説明を記述してください。
-
-19: 新しいuserspaceインタフェースを作成した場合には、Documentation/ABI/ に
-    Documentation/ABI/README を参考にして必ずドキュメントを追加してください。
-
-20: 'make headers_check'を実行して全く問題がないことを確認してください。
-
-21: 少なくともslabアロケーションとpageアロケーションに失敗した場合の
-    挙動について、fault-injectionを利用して確認してください。
-    Documentation/fault-injection/ を参照してください。
-
-    追加したコードがかなりの量であったならば、サブシステム特有の
-    fault-injectionを追加したほうが良いかもしれません。
-
-22: 新たに追加したコードは、`gcc -W'でコンパイルしてください。
-    このオプションは大量の不要なメッセージを出力しますが、
-    "warning: comparison between signed and unsigned" のようなメッセージは、
-    バグを見つけるのに役に立ちます。
-
-23: 投稿したパッチが -mm パッチセットにマージされた後、全ての既存のパッチや
-    VM, VFS およびその他のサブシステムに関する様々な変更と、現時点でも共存
-    できることを確認するテストを行ってください。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ja_JP/SubmittingPatches linux-libre-4.10-rc8-gnu/Documentation/ja_JP/SubmittingPatches
--- linux-libre-4.9-gnu/Documentation/ja_JP/SubmittingPatches	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ja_JP/SubmittingPatches	1969-12-31 19:00:00.000000000 -0500
@@ -1,719 +0,0 @@
-NOTE:
-This is a version of Documentation/SubmittingPatches into Japanese.
-This document is maintained by Keiichi KII <k-keiichi@bx.jp.nec.com>
-and the JF Project team <http://www.linux.or.jp/JF/>.
-If you find any difference between this document and the original file
-or a problem with the translation,
-please contact the maintainer of this file or JF project.
-
-Please also note that the purpose of this file is to be easier to read
-for non English (read: Japanese) speakers and is not intended as a
-fork. So if you have any comments or updates of this file, please try
-to update the original English file first.
-
-Last Updated: 2011/06/09
-
-==================================
-これは、
-linux-2.6.39/Documentation/SubmittingPatches の和訳
-です。
-翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
-翻訳日： 2011/06/09
-翻訳者： Keiichi Kii <k-keiichi at bx dot jp dot nec dot com>
-校正者： Masanari Kobayashi さん <zap03216 at nifty dot ne dot jp>
-         Matsukura さん <nbh--mats at nifty dot com>
-         Takeshi Hamasaki さん <hmatrjp at users dot sourceforge dot jp>
-==================================
-
-        Linux カーネルに変更を加えるための Howto
-        又は
-        かの Linus Torvalds の取り扱い説明書
-
-Linux カーネルに変更を加えたいと思っている個人又は会社にとって、パッ
-チの投稿に関連した仕組みに慣れていなければ、その過程は時々みなさんを
-おじけづかせることもあります。この文章はあなたの変更を大いに受け入れ
-てもらえやすくする提案を集めたものです。
-
-コードを投稿する前に、Documentation/SubmitChecklist の項目リストに目
-を通してチェックしてください。もしあなたがドライバーを投稿しようとし
-ているなら、Documentation/SubmittingDrivers にも目を通してください。
-
---------------------------------------------
-セクション1 パッチの作り方と送り方
---------------------------------------------
-
-1) 「 diff -up 」
-------------
-
-パッチの作成には「 diff -up 」又は「 diff -uprN 」を使ってください。
-
-Linux カーネルに対する全ての変更は diff(1) コマンドによるパッチの形式で
-生成してください。パッチを作成するときには、diff(1) コマンドに「 -u 」引
-数を指定して、unified 形式のパッチを作成することを確認してください。また、
-変更がどの C 関数で行われたのかを表示する「 -p 」引数を使ってください。
-この引数は生成した差分をずっと読みやすくしてくれます。パッチは Linux
-カーネルソースの中のサブディレクトリではなく Linux カーネルソースのルート
-ディレクトリを基準にしないといけません。
-
-1個のファイルについてのパッチを作成するためには、ほとんどの場合、
-以下の作業を行えば十分です。
-
-	SRCTREE= linux-2.6
-	MYFILE=  drivers/net/mydriver.c
-
-	cd $SRCTREE
-	cp $MYFILE $MYFILE.orig
-	vi $MYFILE	# make your change
-	cd ..
-	diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
-
-複数のファイルについてのパッチを作成するためには、素の( vanilla )、す
-なわち変更を加えてない Linux カーネルを展開し、自分の Linux カーネル
-ソースとの差分を生成しないといけません。例えば、
-
-	MYSRC= /devel/linux-2.6
-
-	tar xvfz linux-2.6.12.tar.gz
-	mv linux-2.6.12 linux-2.6.12-vanilla
-	diff -uprN -X linux-2.6.12-vanilla/Documentation/dontdiff \
-		linux-2.6.12-vanilla $MYSRC > /tmp/patch
-
-dontdiff ファイルには Linux カーネルのビルドプロセスの過程で生成された
-ファイルの一覧がのっています。そして、それらはパッチを生成する diff(1)
-コマンドで無視されるべきです。dontdiff ファイルは 2.6.12 以後のバージョ
-ンの Linux カーネルソースツリーに含まれています。それより前のバージョン
-の Linux カーネルソースツリーに対する dontdiff ファイルは、
-<http://www.xenotime.net/linux/doc/dontdiff>から取得することができます。
-
-投稿するパッチの中に関係のない余分なファイルが含まれていないことを確
-認してください。diff(1) コマンドで生成したパッチがあなたの意図したとお
-りのものであることを確認してください。
-
-もしあなたのパッチが多くの差分を生み出すのであれば、あなたはパッチ
-を意味のあるひとまとまりごとに分けたいと思うかもしれません。
-これは他のカーネル開発者にとってレビューしやすくなるので、あなたの
-パッチを受け入れてもらうためにはとても重要なことです。これを補助でき
-る多くのスクリプトがあります。
-
-Quilt:
-http://savannah.nongnu.org/projects/quilt
-
-2) パッチに対する説明
-
-パッチの中の変更点に対する技術的な詳細について説明してください。
-
-説明はできる限り具体的に。もっとも悪い説明は「ドライバー X を更新」、
-「ドライバー X に対するバグフィックス」あるいは「このパッチはサブシス
-テム X に対する更新を含んでいます。どうか取り入れてください。」などです。
-
-パッチの説明を Linux カーネルのソースコードマネジメントシステム「 git 」の
-コミットログとして簡単に引用できる形で書けば、メンテナから感謝されるでしょう。
-以下の #15 を見てください。
-
-説明が長くなりだしたのであれば、おそらくそれはパッチを分ける必要がある
-という兆候です。次の #3 を見てください。
-
-パッチ(シリーズ)を(再)投稿する時、十分なパッチの説明とそのパッチが必要な理由を
-パッチに含めてください。ただ「これはパッチ(シリーズ)のバージョン N」とだけ
-書かないでください。そして、パッチをマージする人にパッチの説明を探させそれを
-パッチに追記させるため、過去のバージョンのパッチやそのパッチの URL を参照する
-手間をかけさせないでください。
-つまり、パッチシリーズとその説明は一緒にあるべきです。これはパッチをマージする
-人、レビューする人、どちらのためにもなります。レビューする人の中には、おそらく
-過去のバージョンのパッチを受け取ってもいない人がいます。
-
-登録済みのバグエントリを修正するパッチであれば、そのバグエントリを示すバグ ID
-や URL を明記してください。
-
-3) パッチの分割
-
-意味のあるひとまとまりごとに変更を個々のパッチファイルに分けてください。
-
-例えば、もし1つのドライバーに対するバグフィックスとパフォーマンス強
-化の両方の変更を含んでいるのであれば、その変更を2つ以上のパッチに分
-けてください。もし変更箇所に API の更新と、その新しい API を使う新たな
-ドライバーが含まれているなら、2つのパッチに分けてください。
-
-一方で、もしあなたが多数のファイルに対して意味的に同じ1つの変更を加え
-るのであれば、その変更を1つのパッチにまとめてください。言いかえると、
-意味的に同じ1つの変更は1つのパッチの中に含まれます。
-
-あるパッチが変更を完結させるために他のパッチに依存していたとしても、
-それは問題ありません。パッチの説明の中で「このパッチはパッチ X に依存
-している」と簡単に注意書きをつけてください。
-
-もしパッチをより小さなパッチの集合に凝縮することができないなら、まずは
-15かそこらのパッチを送り、そのレビューと統合を待って下さい。
-
-4) パッチのスタイルチェック
-
-あなたのパッチが基本的な( Linux カーネルの)コーディングスタイルに違反し
-ていないかをチェックして下さい。その詳細を Documentation/CodingStyle で
-見つけることができます。コーディングスタイルの違反はレビューする人の
-時間を無駄にするだけなので、恐らくあなたのパッチは読まれることすらなく
-拒否されるでしょう。
-
-あなたはパッチを投稿する前に最低限パッチスタイルチェッカー
-( scripts/checkpatch.pl )を利用してパッチをチェックすべきです。
-もしパッチに違反がのこっているならば、それらの全てについてあなたは正当な
-理由を示せるようにしておく必要があります。
-
-5) 電子メールの宛先の選び方
-
-MAINTAINERS ファイルとソースコードに目を通してください。そして、その変
-更がメンテナのいる特定のサブシステムに加えられるものであることが分か
-れば、その人に電子メールを送ってください。
-
-もし、メンテナが載っていなかったり、メンテナからの応答がないなら、
-LKML ( linux-kernel@vger.kernel.org )へパッチを送ってください。ほとんど
-のカーネル開発者はこのメーリングリストに目を通しており、変更に対して
-コメントを得ることができます。
-
-15個より多くのパッチを同時に vger.kernel.org のメーリングリストへ送らな
-いでください!!!
-
-Linus Torvalds は Linux カーネルに入る全ての変更に対する最終的な意思決定者
-です。電子メールアドレスは torvalds@linux-foundation.org になります。彼は
-多くの電子メールを受け取っているため、できる限り彼に電子メールを送るのは
-避けるべきです。
-
-バグフィックスであったり、自明な変更であったり、話し合いをほとんど
-必要としないパッチは Linus へ電子メールを送るか CC しなければなりません。
-話し合いを必要としたり、明確なアドバンテージがないパッチは、通常まず
-は LKML へ送られるべきです。パッチが議論された後にだけ、そのパッチを
-Linus へ送るべきです。
-
-6) CC (カーボンコピー)先の選び方
-
-特に理由がないなら、LKML にも CC してください。
-
-Linus 以外のカーネル開発者は変更に気づく必要があり、その結果、彼らはそ
-の変更に対してコメントをくれたり、コードに対してレビューや提案をくれ
-るかもしれません。LKML とは Linux カーネル開発者にとって一番中心的なメー
-リングリストです。USB やフレームバッファデバイスや VFS や SCSI サブシステ
-ムなどの特定のサブシステムに関するメーリングリストもあります。あなた
-の変更に、はっきりと関連のあるメーリングリストについて知りたければ
-MAINTAINERS ファイルを参照してください。
-
-VGER.KERNEL.ORG でホスティングされているメーリングリストの一覧が下記の
-サイトに載っています。
-<http://vger.kernel.org/vger-lists.html>
-
-もし、変更がユーザランドのカーネルインタフェースに影響を与え
-るのであれば、MAN-PAGES のメンテナ( MAINTAINERS ファイルに一覧
-があります)に man ページのパッチを送ってください。少なくとも
-情報がマニュアルページの中に入ってくるように、変更が起きたという
-通知を送ってください。
-
-たとえ、メンテナが #5 で反応がなかったとしても、メンテナのコードに変更を
-加えたときには、いつもメンテナに CC するのを忘れないようにしてください。
-
-小さなパッチであれば、Trivial Patch Monkey(ちょっとしたパッチを集めている)
-<trivial@kernel.org>に CC してもいいです。その現管理者については MAINTAINERS
-ファイルを見てください。ちょっとしたパッチとは以下のルールのどれか1つを満たして
-いなければなりません。
- ・ドキュメントのスペルミスの修正
- ・grep(1) コマンドによる検索を困難にしているスペルの修正
- ・コンパイル時の警告の修正(無駄な警告が散乱することは好ましくないた
-   めです)
- ・コンパイル問題の修正(それらの修正が本当に正しい場合に限る)
- ・実行時の問題の修正(それらの修正が本当に問題を修正している場合に限る)
- ・廃止予定の関数やマクロを使用しているコードの除去(例 check_region )
- ・問い合わせ先やドキュメントの修正
- ・移植性のないコードから移植性のあるコードへの置き換え(小さい範囲で
-   あればアーキテクチャ特有のことでも他の人がコピーできます)
- ・作者やメンテナによる修正(すなわち patch monkey の再転送モード)
-
-7) MIME やリンクや圧縮ファイルや添付ファイルではなくプレインテキストのみ
-
-Linus や他のカーネル開発者はあなたが投稿した変更を読んで、コメントでき
-る必要があります。カーネル開発者にとって、あなたが書いたコードの特定の
-部分にコメントをするために、標準的な電子メールクライアントで変更が引用
-できることは重要です。
-
-上記の理由で、すべてのパッチは文中に含める形式の電子メールで投稿さ
-れるべきです。警告：あなたがパッチをコピー&ペーストする際には、パッ
-チを改悪するエディターの折り返し機能に注意してください。
-
-パッチを圧縮の有無に関わらず MIME 形式で添付しないでください。多くのポ
-ピュラーな電子メールクライアントは MIME 形式の添付ファイルをプレーンテ
-キストとして送信するとは限らないでしょう。そうなると、電子メールクラ
-イアントがコードに対するコメントを付けることをできなくします。また、
-MIME 形式の添付ファイルは Linus に手間を取らせることになり、その変更を
-受け入れてもらう可能性が低くなってしまいます。
-
-例外：お使いの電子メールクライアントがパッチをめちゃくちゃにするので
-あれば、誰かが MIME 形式のパッチを再送するよう求めるかもしれません。
-
-余計な変更を加えずにあなたのパッチを送信するための電子メールクライアントの設定
-のヒントについては Documentation/email-clients.txt を参照してください。
-
-8) 電子メールのサイズ
-
-パッチを Linus へ送るときは常に #7 の手順に従ってください。
-
-大きなパッチはメーリングリストやメンテナにとって不親切です。パッチが
-未圧縮で 300KB を超えるようであるなら、インターネット上のアクセス可能な
-サーバに保存し、保存場所を示す URL を伝えるほうが適切です。
-
-9) カーネルバージョンの明記
-
-パッチが対象とするカーネルのバージョンをパッチの概要か電子メールの
-サブジェクトに付けることが重要です。
-
-パッチが最新バージョンのカーネルに正しく適用できなければ、Linus は
-そのパッチを採用しないでしょう。
-
-10) がっかりせず再投稿
-
-パッチを投稿した後は、辛抱強く待っていてください。Linus があなたのパッ
-チを気に入って採用すれば、Linus がリリースする次のバージョンのカーネル
-の中で姿を見せるでしょう。
-
-しかし、パッチが次のバージョンのカーネルに入っていないなら、いくつもの
-理由があるのでしょう。その原因を絞り込み、間違っているものを正し、更新
-したパッチを投稿するのはあなたの仕事です。
-
-Linus があなたのパッチに対して何のコメントもなく不採用にすることは極め
-て普通のことです。それは自然な姿です。もし、Linus があなたのパッチを受
-け取っていないのであれば、以下の理由が考えられます。
-* パッチが最新バージョンの Linux カーネルにきちんと適用できなかった
-* パッチが LKML で十分に議論されていなかった
-* スタイルの問題(セクション2を参照)
-* 電子メールフォーマットの問題(このセクションを参照)
-* パッチに対する技術的な問題
-* Linus はたくさんの電子メールを受け取っているので、どさくさに紛れて見
-  失った
-* 不愉快にさせている
-
-判断できない場合は、LKML にコメントを頼んでください。
-
-11) サブジェクトに「 PATCH 」
-
-Linus や LKML への大量の電子メールのために、サブジェクトのプレフィックスに
-「 [PATCH] 」を付けることが慣習となっています。これによって Linus や他の
-カーネル開発者がパッチであるのか、又は、他の議論に関する電子メールであるの
-かをより簡単に識別できます。
-
-12) パッチへの署名
-
-誰が何をしたのかを追いかけやすくするために (特に、パッチが何人かの
-メンテナを経て最終的に Linux カーネルに取り込まれる場合のために)、電子
-メールでやり取りされるパッチに対して「 sign-off 」という手続きを導入し
-ました。
-
-「 sign-off 」とは、パッチがあなたの書いたものであるか、あるいは、
-あなたがそのパッチをオープンソースとして提供する権利を保持している、
-という証明をパッチの説明の末尾に一行記載するというものです。
-ルールはとても単純です。以下の項目を確認して下さい。
-
-        原作者の証明書( DCO ) 1.1
-
-        このプロジェクトに寄与するものとして、以下のことを証明する。
-
-        (a) 本寄与は私が全体又は一部作成したものであり、私がそのファイ
-            ル中に明示されたオープンソースライセンスの下で公開する権利
-            を持っている。もしくは、
-
-        (b) 本寄与は、私が知る限り、適切なオープンソースライセンスでカバ
-            ーされている既存の作品を元にしている。同時に、私はそのライセ
-            ンスの下で、私が全体又は一部作成した修正物を、ファイル中で示
-            される同一のオープンソースライセンスで(異なるライセンスの下で
-            投稿することが許可されている場合を除いて)投稿する権利を持って
-            いる。もしくは、
-
-        (c) 本寄与は(a)、(b)、(c)を証明する第3者から私へ直接提供された
-            ものであり、私はそれに変更を加えていない。
-
-        (d) 私はこのプロジェクトと本寄与が公のものであることに理解及び同意す
-            る。同時に、関与した記録(投稿の際の全ての個人情報と sign-off を
-            含む)が無期限に保全されることと、当該プロジェクト又は関連する
-            オープンソースライセンスに沿った形で再配布されることに理解及び
-            同意する。
-
-もしこれに同意できるなら、以下のような1行を追加してください。
-
-	Signed-off-by: Random J Developer <random@developer.example.org>
-
-実名を使ってください。(残念ですが、偽名や匿名による寄与はできません。)
-
-人によっては sign-off の近くに追加のタグを付加しています。それらは今のところ
-無視されますが、あなたはそのタグを社内の手続きに利用したり、sign-off に特別
-な情報を示したりすることができます。
-
-あなたがサブシステムまたはブランチのメンテナであれば、受け取ったパッチを自身の
-ツリーにマージするために、わずかに変更が必要となる場合があります。なぜなら
-あなたのツリーの中のコードと投稿者のツリーの中のコードは同一ではないためです。
-もし、あなたが厳密に上記ルール(c)にこだわるのであれば、投稿者に再度差分を
-とるよう依頼すべきです。しかし、これは時間とエネルギーを非生産的に浪費する
-ことになります。ルール(b)はあなたにコードを修正する権利を与えてくれます。
-しかし、投稿者のコードを修正し、その修正によるバグを投稿者に押し付けてしまう
-ことはとても失礼なことです。この問題を解決するために、末尾の投稿者の
-Signed-off-by とあなたがその末尾に追加する Signed-off-by の間に、修正を
-加えたことを示す1行を追加することが推奨されています。
-(その1行の書き方に)決まりはありませんが、大括弧の中に電子メールアドレスや氏名
-と修正内容を記載するやり方は目につきやすく、最終段階での変更の責任があなたに
-あることを明確にするのに十分な方法のようです。例えば、
-
-	Signed-off-by: Random J Developer <random@developer.example.org>
-	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
-	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
-
-あなたが安定版のブランチを管理しており、作成者のクレジット、変更の追跡、
-修正のマージ、と同時に苦情からの投稿者の保護を行いたい場合、この慣習は特に
-有用となります。いかなる事情があってもチェンジログに出てくる作成者の
-アイデンティティ情報(From ヘッダ)は変更できないことに注意してください。
-
-バックポートする人のための特別な注意事項。追跡を容易に行うために、コミット
-メッセージのトップ(サブジェクト行のすぐ後)にパッチの起源を示す情報を記述する
-ことは一般的で有用な慣習です。例えば、これは 2.6-stable ツリーでの一例です。    
-
-    Date:   Tue May 13 19:10:30 2008 +0000
-
-        SCSI: libiscsi regression in 2.6.25: fix nop timer handling
-
-        commit 4cf1043593db6a337f10e006c23c69e5fc93e722 upstream
-
-そして、これは 2.4 ツリーでの一例です。
-
-    Date:   Tue May 13 22:12:27 2008 +0200
-
-        wireless, airo: waitbusy() won't delay
-
-        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
-
-どんな形式であれ、この情報はあなたのツリーを追跡する人やあなたのツリーのバグを
-解決しようとしている人にとって価値のある支援となります。
-
-13) いつ Acked-by: と Cc: を使うのか
-
-「 Signed-off-by: 」タグはその署名者がパッチの開発に関わっていたことやパッチ
-の伝播パスにいたことを示しています。
-
-ある人が直接パッチの準備や作成に関わっていないけれど、その人のパッチに対す
-る承認を記録し、示したいとします。その場合、その人を示すのに Acked-by: が使
-えます。Acked-by: はパッチのチェンジログにも追加されます。
-
-パッチの影響を受けるコードのメンテナがパッチに関わっていなかったり、パッチ
-の伝播パスにいなかった時にも、メンテナは Acked-by: をしばしば利用します。
-
-Acked-by: は Signed-off-by: のように公式なタグではありません。それはメンテナが
-少なくともパッチをレビューし、同意を示しているという記録です。そのような
-ことからパッチをマージする人がメンテナの「うん、良いと思うよ」という発言を
-Acked-by: へ置き換えることがあります。
-
-Acked-by: が必ずしもパッチ全体の承認を示しているわけではありません。例えば、
-あるパッチが複数のサブシステムへ影響を与えており、その中の1つのサブシステム
-のメンテナからの Acked-by: を持っているとします。その場合、Acked-by: は通常
-そのメンテナのコードに影響を与える一部分だけに対する承認を示しています。
-この点は、ご自分で判断してください。(その Acked-by: が)疑わしい場合は、
-メーリングリストアーカイブの中の大元の議論を参照すべきです。
-
-パッチにコメントする機会を持っていたが、その時にコメントしなかった人がいれば、
-その人を指す「Cc:」タグを任意で追加してもかまいません。これは指定された人からの
-明確なアクションなしに付与できる唯一のタグです。
-このタグはパッチに関心があると思われる人達がそのパッチの議論に含まれていたこと
-を明文化します。
-
-14) Reported-by と Tested-by: と Reviewed-by: の利用
-
-他の誰かによって報告された問題を修正するパッチであれば、問題報告者という寄与を
-クレジットするために、Reported-by: タグを追加することを検討してください。
-こまめにバグ報告者をクレジットしていくことで、うまくいけばその人たちが将来再び
-コミュニティの力となってくれるでしょう。
-ただし、報告者の許可無くこのタグを追加しないように注意してください。特に、
-問題が公の場で報告されていなかったのであれば。
-
-Tested-by: タグはタグで指定された人によって(ある環境下で)パッチのテストに成功
-していることを示します。このタグはメンテナにテストが実施済みであることを
-知らせ、将来の関連パッチのテスト協力者を見つける方法を提供し、テスト実施者に
-対するクレジットを保証します。
-
-Reviewed-by: タグは、それとは異なり、下記のレビューア宣言の下にレビューされ、
-受け入れ可能とみなされたパッチであることを示します。
-
-        レビューアによる監督宣言
-
-        私は Reviewed-by: タグを提示することによって、以下のことを明言する。
-
-        (a) 私はメインラインカーネルへの統合に向け、その妥当性及び「即応性
-            (訳注)」を検証し、技術的側面からパッチをレビュー済みである。
-
-        訳注:
-        「即応性」の原文は "readiness"。
-        パッチが十分な品質を持っており、メインラインカーネルへの統合を即座に
-        行うことができる状態であるかどうかを "readiness" という単語で表現
-        している。
-
-        (b) パッチに関するあらゆる問題、懸念、あるいは、疑問は投稿者へ伝達済み
-            である。私はそれらのコメントに対する投稿者の返答に満足している。
-
-        (c) 投稿に伴い改良されるコードがある一方で、現時点で、私は(1)それが
-            カーネルにとって価値のある変更であること、そして、(2)統合に際して
-            議論になり得るような問題はないものと確信している。
-
-        (d) 私はパッチをレビューし適切であると確信している一方で、あらゆる
-            状況においてその宣言した目的や機能が正しく実現することに関して、
-            いかなる保証もしない(特にどこかで明示しない限り)。
-
-Reviewd-by タグはそのパッチがカーネルに対して適切な修正であって、深刻な技術的
-問題を残していないという意見の宣言です。興味のあるレビューアは誰でも(レビュー
-作業を終えたら)パッチに対して Reviewed-by タグを提示できます。このタグは
-レビューアの寄与をクレジットする働き、レビューの進捗の度合いをメンテナに
-知らせる働きを持ちます。そのパッチの領域に詳しく、そして、しっかりとした
-レビューを実施したレビューアによって提供される時、Reviewed-by: タグがあなたの
-パッチをカーネルにマージする可能性を高めるでしょう。
-
-15) 標準的なパッチのフォーマット
-
-標準的なパッチのサブジェクトは以下のとおりです。
-
-    Subject: [PATCH 001/123] subsystem: summary phrase
-
-標準的なパッチの、電子メールのボディは以下の項目を含んでいます。
-
-  - パッチの作成者を明記する「 from 」行
-
-  - 空行
-
-  - 説明本体。これはこのパッチを説明するために無期限のチェンジログ
-    (変更履歴)にコピーされます。
-
-  - 上述した「 Signed-off-by: 」行。これも説明本体と同じくチェン
-    ジログ内にコピーされます。
-
-  - マーカー行は単純に「 --- 」です。
-
-  - 余計なコメントは、チェンジログには不適切です。
-
-  - 実際のパッチ(差分出力)
-
-サブジェクト行のフォーマットは、アルファベット順で電子メールをとても
-ソートしやすいものになっています。(ほとんどの電子メールクライアント
-はソートをサポートしています)パッチのサブジェクトの連番は0詰めであ
-るため、数字でのソートとアルファベットでのソートは同じ結果になります。
-
-電子メールのサブジェクト内のサブシステム表記は、パッチが適用される
-分野またはサブシステムを識別できるようにすべきです。
-
-電子メールのサブジェクトの「summary phrase」はそのパッチの概要を正確
-に表現しなければなりません。「summary phrase」をファイル名にしてはい
-けません。パッチシリーズ中でそれぞれのパッチは同じ「summary phrase」を
-使ってはいけません(「パッチシリーズ」とは順序付けられた関連のある複数の
-パッチ群です)。
-
-あなたの電子メールの「summary phrase」がそのパッチにとって世界で唯一の識別子に
-なるように心がけてください。「summary phrase」は git のチェンジログの中へ
-ずっと伝播していきます。「summary phrase」は、開発者が後でパッチを参照する
-ために議論の中で利用するかもしれません。
-人々はそのパッチに関連した議論を読むために「summary phrase」を使って google で
-検索したがるでしょう。それはまた2、3ヶ月あとで、人々が「gitk」や
-「git log --oneline」のようなツールを使用して何千ものパッチに目を通す時、
-唯一目にとまる情報となるでしょう。
-
-これらの理由のため、「summary phrase」はなぜパッチが必要であるか、パッチが何を
-変更するかの2つの情報をせいぜい70〜75文字で表現していなければなりません。
-「summary phrase」は簡潔であり説明的である表現を目指しつつ、うまく
-まとめられている概要となるべきです。
-
-「summary phrase」は「Subject: [PATCH tag] <summary phrase>」のように、
-大括弧で閉じられたタグを接頭辞として付加してもかまいません。このタグは
-「summary phrase」の一部とは考えませんが、パッチをどのように取り扱うべきかを
-表現します。
-一般的には「v1, v2, v3」のようなバージョン情報を表すタグ(過去のパッチに対する
-コメントを反映するために複数のバージョンのパッチが投稿されているのであれば)、
-「RFC」のようなコメントを要求するタグが挙げられます。パッチシリーズとして4つの
-パッチがあれば、個々のパッチに「1/4, 2/4, 3/4, 4/4」のように番号を付けても
-かまいません。これは開発者がパッチを適用する順番を確実に把握するためです。
-そして、開発者がパッチシリーズの中のすべてのパッチをもらさずレビュー或いは
-適用するのを保証するためです。
-
-サブジェクトの例を二つ
-
-    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
-    Subject: [PATCHv2 001/207] x86: fix eflags tracking
-
-「 from 」行は電子メールのボディの一番最初の行でなければなりません。
-その形式は以下のとおりです。
-
-        From: Original Author <author@example.com>
-
-「 from 」行はチェンジログの中で、そのパッチの作成者としてクレジットされ
-ている人を特定するものです。「 from 」行がかけていると、電子メールのヘッ
-ダーの「 From: 」が、チェンジログの中でパッチの作成者を決定するために使わ
-れるでしょう。
-
-説明本体は無期限のソースのチェンジログにコミットされます。なので、説明
-本体はそのパッチに至った議論の詳細を忘れているある程度の技量を持っている人
-がその詳細を思い出すことができるものでなければなりません。パッチが対処する
-障害の症状(カーネルログメッセージや oops メッセージ等)を記載することは問題に
-対処可能なパッチを求めてコミットログを検索する人々にとって特に有用です。
-パッチがコンパイル問題を解決するのであれば、そのパッチを探している人が見つける
-ことができる情報だけで十分であり、コンパイル時の全てのエラーを含める必要は
-ありません。「summary phrase」と同様に、簡潔であり説明的であることが重要です。
-
-「 --- 」マーカー行はパッチ処理ツールに対して、チェンジログメッセージの終端
-部分を認識させるという重要な役目を果たします。
-
-「 --- 」マーカー行の後の追加コメントの良い使用方法の1つに diffstat コマンド
-があります。diffstat コマンドとは何のファイルが変更され、1ファイル当たり何行
-追加され何行消されたかを示すものです。diffstat コマンドは特に大きなパッチに
-おいて役立ちます。その時点でだけ又はメンテナにとってのみ関係のあるコメント
-は無期限に保存されるチェンジログにとって適切ではありません。そのため、この
-ようなコメントもマーカー行の後に書かれるべきです。
-このようなコメントの良い例として、v1 と v2 のバージョン間で何が変更されたかを
-表す「パッチの変更履歴」が挙げられます。
-
-「 --- 」マーカー行の後に diffstat コマンドの結果を含めるのであれば、ファイル
-名はカーネルソースツリーのトップディレクトリからの表記で列記されるため、横方向
-のスペースをとり過ぎないように、diffstat コマンドにオプション「 -p 1 -w 70 」
-を指定してください(インデントを含めてちょうど80列に合うでしょう)。
-
-適切なパッチのフォーマットの詳細についてはセクション3の参考文献を参照して
-ください。
-
-16) 「git pull」要求の送り方(Linus の電子メールから)
-
-間違ったブランチから引っ張るのを防ぐために、git リポジトリのアドレスと
-ブランチ名を同じ行に1行で記載してください。そうすることで、3回の連続クリック
-で全て選択できます。
-
-正しい形式は下記の通りです。
-
-	"Please pull from
-
-		git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
-
-	 to get these changes:"
-
-その結果、アドレスを自分自身でタイピングして間違えることはなくなります(実際に、
-何度か間違ったブランチから引っ張ってきてしまい、その時に diffstat の結果を
-検証して間違っていることに気づいたことがあります。どこから何を引っ張るべきかを
-「探したり」、正しいブランチ名かどうかを重ねてチェックしたりする必要が
-なくなればより快適になるでしょう)。
-
-diffstat の結果を生成するために「 git diff -M --stat --summary 」を使って
-ください。-M オプションはファイル名の変更を検知でき、--summary オプションは
-新規ファイル、削除されたファイル、名前が変更されたファイルの概要を生成します。
-
--M オプション(ファイル名の変更検知)を指定すると、diffstat の結果はかなり
-異なってきます。git は大規模な変更(追加と削除のペア)をファイル名の変更と
-判断するためです。
-
-------------------------------------
-セクション2 - ヒントとTIPSと小技
-------------------------------------
-
-このセクションは Linux カーネルに変更を適用することに関係のある一般的な
-「お約束」の多くを載せています。物事には例外というものがあります。しか
-し例外を適用するには、本当に妥当な理由が不可欠です。あなたは恐らくこの
-セクションを Linus のコンピュータ・サイエンス101と呼ぶでしょう。
-
-1) Documentation/CodingStyleを参照
-
-言うまでもなく、あなたのコードがこのコーディングスタイルからあまりに
-も逸脱していると、レビューやコメントなしに受け取ってもらえないかもし
-れません。
-
-特筆すべき例外は、コードをあるファイルから別のファイルに移動
-するときです。この場合、コードを移動するパッチでは、移動されるコード
-に関して移動以外の変更を一切加えるべきではありません。これにより、
-コードの移動とあなたが行ったコードの修正を明確に区別できるようにな
-ります。これは実際に何が変更されたかをレビューする際の大きな助けに
-なるとともに、ツールにコードの履歴を追跡させることも容易になります。
-
-投稿するより前にパッチのスタイルチェッカー( scripts/checkpatch.pl )で
-あなたのパッチをチェックしてください。このスタイルチェッカーは最終結
-論としてではなく、指標としてみるべきです。もし、あなたのコードが違反
-はしているが修正するより良く見えるのであれば、おそらくそのままにする
-のがベストです。
-
-スタイルチェッカーによる3段階のレポート:
- - エラー: 間違っている可能性が高い
- - 警告：注意してレビューする必要がある
- - チェック：考慮する必要がある
-
-あなたはパッチに残っている全ての違反について、それがなぜ必要なのか正当な
-理由を示せるようにしておく必要があります。
-
-2) #ifdefは見苦しい
-
-ifdef が散乱したコードは、読むのもメンテナンスするのも面倒です。コードの中
-で ifdef を使わないでください。代わりに、ヘッダファイルの中に ifdef を入れて、
-条件付きで、コードの中で使われる関数を「 static inline 」関数かマクロで定義し
-てください。後はコンパイラが、何もしない箇所を最適化して取り去ってくれるで
-しょう。
-
-まずいコードの簡単な例
-
-	dev = alloc_etherdev (sizeof(struct funky_private));
-	if (!dev)
-		return -ENODEV;
-	#ifdef CONFIG_NET_FUNKINESS
-	init_funky_net(dev);
-	#endif
-
-クリーンアップしたコードの例
-
-(in header)
-	#ifndef CONFIG_NET_FUNKINESS
-	static inline void init_funky_net (struct net_device *d) {}
-	#endif
-
-(in the code itself)
-	dev = alloc_etherdev (sizeof(struct funky_private));
-	if (!dev)
-		return -ENODEV;
-	init_funky_net(dev);
-
-3) マクロより「 static inline 」を推奨
-
-「 static inline 」関数はマクロよりもずっと推奨されています。それらは、
-型安全性があり、長さにも制限が無く、フォーマットの制限もありません。
-gcc においては、マクロと同じくらい軽いです。
-
-マクロは「 static inline 」が明らかに不適切であると分かる場所(高速化パスの
-いくつかの特定のケース)や「 static inline 」関数を使うことができないような
-場所(マクロの引数の文字列連結のような)にだけ使われるべきです。
-
-「 static inline 」は「 static __inline__ 」や「 extern inline 」や
-「 extern __inline__ 」よりも適切です。
-
-4) 設計に凝りすぎるな
-
-それが有用になるかどうか分からないような不明瞭な将来を見越した設計
-をしないでください。「できる限り簡単に、そして、それ以上簡単になら
-ないような設計をしてください。」
-
-----------------------
-セクション3 参考文献
-----------------------
-
-Andrew Morton, "The perfect patch" (tpp).
-  <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
-
-Jeff Garzik, "Linux kernel patch submission format".
-  <http://linux.yyz.us/patch-format.html>
-
-Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
-  <http://www.kroah.com/log/2005/03/31/>
-  <http://www.kroah.com/log/2005/07/08/>
-  <http://www.kroah.com/log/2005/10/19/>
-  <http://www.kroah.com/log/2006/01/11/>
-
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
-  <https://lkml.org/lkml/2005/7/11/336>
-
-Kernel Documentation/CodingStyle:
-  <http://users.sosdg.org/~qiyong/lxr/source/Documentation/CodingStyle>
-
-Linus Torvalds's mail on the canonical patch format:
-  <http://lkml.org/lkml/2005/4/7/183>
-
-Andi Kleen, "On submitting kernel patches"
-  Some strategies to get difficult or controversial changes in.
-  http://halobates.de/on-submitting-patches.pdf
-
---
-
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/java.txt linux-libre-4.10-rc8-gnu/Documentation/java.txt
--- linux-libre-4.9-gnu/Documentation/java.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/java.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,404 +0,0 @@
-               Java(tm) Binary Kernel Support for Linux v1.03
-               ----------------------------------------------
-
-Linux beats them ALL! While all other OS's are TALKING about direct
-support of Java Binaries in the OS, Linux is doing it!
-
-You can execute Java applications and Java Applets just like any
-other program after you have done the following:
-
-1) You MUST FIRST install the Java Developers Kit for Linux.
-   The Java on Linux HOWTO gives the details on getting and
-   installing this. This HOWTO can be found at:
-
-	ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO/Java-HOWTO
-
-   You should also set up a reasonable CLASSPATH environment
-   variable to use Java applications that make use of any
-   nonstandard classes (not included in the same directory
-   as the application itself).
-
-2) You have to compile BINFMT_MISC either as a module or into
-   the kernel (CONFIG_BINFMT_MISC) and set it up properly.
-   If you choose to compile it as a module, you will have
-   to insert it manually with modprobe/insmod, as kmod
-   cannot easily be supported with binfmt_misc. 
-   Read the file 'binfmt_misc.txt' in this directory to know
-   more about the configuration process.
-
-3) Add the following configuration items to binfmt_misc
-   (you should really have read binfmt_misc.txt now):
-   support for Java applications:
-     ':Java:M::\xca\xfe\xba\xbe::/usr/local/bin/javawrapper:'
-   support for executable Jar files:
-     ':ExecutableJAR:E::jar::/usr/local/bin/jarwrapper:'
-   support for Java Applets:
-     ':Applet:E::html::/usr/bin/appletviewer:'
-   or the following, if you want to be more selective:
-     ':Applet:M::<!--applet::/usr/bin/appletviewer:'
-
-   Of course you have to fix the path names. The path/file names given in this
-   document match the Debian 2.1 system. (i.e. jdk installed in /usr,
-   custom wrappers from this document in /usr/local)
-
-   Note, that for the more selective applet support you have to modify
-   existing html-files to contain <!--applet--> in the first line
-   ('<' has to be the first character!) to let this work!
-
-   For the compiled Java programs you need a wrapper script like the
-   following (this is because Java is broken in case of the filename
-   handling), again fix the path names, both in the script and in the
-   above given configuration string.
-
-   You, too, need the little program after the script. Compile like
-   gcc -O2 -o javaclassname javaclassname.c
-   and stick it to /usr/local/bin.
-
-   Both the javawrapper shellscript and the javaclassname program
-   were supplied by Colin J. Watson <cjw44@cam.ac.uk>.
-
-====================== Cut here ===================
-#!/bin/bash
-# /usr/local/bin/javawrapper - the wrapper for binfmt_misc/java
-
-if [ -z "$1" ]; then
-	exec 1>&2
-	echo Usage: $0 class-file
-	exit 1
-fi
-
-CLASS=$1
-FQCLASS=`/usr/local/bin/javaclassname $1`
-FQCLASSN=`echo $FQCLASS | sed -e 's/^.*\.\([^.]*\)$/\1/'`
-FQCLASSP=`echo $FQCLASS | sed -e 's-\.-/-g' -e 's-^[^/]*$--' -e 's-/[^/]*$--'`
-
-# for example:
-# CLASS=Test.class
-# FQCLASS=foo.bar.Test
-# FQCLASSN=Test
-# FQCLASSP=foo/bar
-
-unset CLASSBASE
-
-declare -i LINKLEVEL=0
-
-while :; do
-	if [ "`basename $CLASS .class`" == "$FQCLASSN" ]; then
-		# See if this directory works straight off
-		cd -L `dirname $CLASS`
-		CLASSDIR=$PWD
-		cd $OLDPWD
-		if echo $CLASSDIR | grep -q "$FQCLASSP$"; then
-			CLASSBASE=`echo $CLASSDIR | sed -e "s.$FQCLASSP$.."`
-			break;
-		fi
-		# Try dereferencing the directory name
-		cd -P `dirname $CLASS`
-		CLASSDIR=$PWD
-		cd $OLDPWD
-		if echo $CLASSDIR | grep -q "$FQCLASSP$"; then
-			CLASSBASE=`echo $CLASSDIR | sed -e "s.$FQCLASSP$.."`
-			break;
-		fi
-		# If no other possible filename exists
-		if [ ! -L $CLASS ]; then
-			exec 1>&2
-			echo $0:
-			echo "  $CLASS should be in a" \
-			     "directory tree called $FQCLASSP"
-			exit 1
-		fi
-	fi
-	if [ ! -L $CLASS ]; then break; fi
-	# Go down one more level of symbolic links
-	let LINKLEVEL+=1
-	if [ $LINKLEVEL -gt 5 ]; then
-		exec 1>&2
-		echo $0:
-		echo "  Too many symbolic links encountered"
-		exit 1
-	fi
-	CLASS=`ls --color=no -l $CLASS | sed -e 's/^.* \([^ ]*\)$/\1/'`
-done
-
-if [ -z "$CLASSBASE" ]; then
-	if [ -z "$FQCLASSP" ]; then
-		GOODNAME=$FQCLASSN.class
-	else
-		GOODNAME=$FQCLASSP/$FQCLASSN.class
-	fi
-	exec 1>&2
-	echo $0:
-	echo "  $FQCLASS should be in a file called $GOODNAME"
-	exit 1
-fi
-
-if ! echo $CLASSPATH | grep -q "^\(.*:\)*$CLASSBASE\(:.*\)*"; then
-	# class is not in CLASSPATH, so prepend dir of class to CLASSPATH
-	if [ -z "${CLASSPATH}" ] ; then
-		export CLASSPATH=$CLASSBASE
-	else
-		export CLASSPATH=$CLASSBASE:$CLASSPATH
-	fi
-fi
-
-shift
-/usr/bin/java $FQCLASS "$@"
-====================== Cut here ===================
-
-
-====================== Cut here ===================
-/* javaclassname.c
- *
- * Extracts the class name from a Java class file; intended for use in a Java
- * wrapper of the type supported by the binfmt_misc option in the Linux kernel.
- *
- * Copyright (C) 1999 Colin J. Watson <cjw44@cam.ac.uk>.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <sys/types.h>
-
-/* From Sun's Java VM Specification, as tag entries in the constant pool. */
-
-#define CP_UTF8 1
-#define CP_INTEGER 3
-#define CP_FLOAT 4
-#define CP_LONG 5
-#define CP_DOUBLE 6
-#define CP_CLASS 7
-#define CP_STRING 8
-#define CP_FIELDREF 9
-#define CP_METHODREF 10
-#define CP_INTERFACEMETHODREF 11
-#define CP_NAMEANDTYPE 12
-#define CP_METHODHANDLE 15
-#define CP_METHODTYPE 16
-#define CP_INVOKEDYNAMIC 18
-
-/* Define some commonly used error messages */
-
-#define seek_error() error("%s: Cannot seek\n", program)
-#define corrupt_error() error("%s: Class file corrupt\n", program)
-#define eof_error() error("%s: Unexpected end of file\n", program)
-#define utf8_error() error("%s: Only ASCII 1-255 supported\n", program);
-
-char *program;
-
-long *pool;
-
-u_int8_t read_8(FILE *classfile);
-u_int16_t read_16(FILE *classfile);
-void skip_constant(FILE *classfile, u_int16_t *cur);
-void error(const char *format, ...);
-int main(int argc, char **argv);
-
-/* Reads in an unsigned 8-bit integer. */
-u_int8_t read_8(FILE *classfile)
-{
-	int b = fgetc(classfile);
-	if(b == EOF)
-		eof_error();
-	return (u_int8_t)b;
-}
-
-/* Reads in an unsigned 16-bit integer. */
-u_int16_t read_16(FILE *classfile)
-{
-	int b1, b2;
-	b1 = fgetc(classfile);
-	if(b1 == EOF)
-		eof_error();
-	b2 = fgetc(classfile);
-	if(b2 == EOF)
-		eof_error();
-	return (u_int16_t)((b1 << 8) | b2);
-}
-
-/* Reads in a value from the constant pool. */
-void skip_constant(FILE *classfile, u_int16_t *cur)
-{
-	u_int16_t len;
-	int seekerr = 1;
-	pool[*cur] = ftell(classfile);
-	switch(read_8(classfile))
-	{
-	case CP_UTF8:
-		len = read_16(classfile);
-		seekerr = fseek(classfile, len, SEEK_CUR);
-		break;
-	case CP_CLASS:
-	case CP_STRING:
-	case CP_METHODTYPE:
-		seekerr = fseek(classfile, 2, SEEK_CUR);
-		break;
-	case CP_METHODHANDLE:
-		seekerr = fseek(classfile, 3, SEEK_CUR);
-		break;
-	case CP_INTEGER:
-	case CP_FLOAT:
-	case CP_FIELDREF:
-	case CP_METHODREF:
-	case CP_INTERFACEMETHODREF:
-	case CP_NAMEANDTYPE:
-	case CP_INVOKEDYNAMIC:
-		seekerr = fseek(classfile, 4, SEEK_CUR);
-		break;
-	case CP_LONG:
-	case CP_DOUBLE:
-		seekerr = fseek(classfile, 8, SEEK_CUR);
-		++(*cur);
-		break;
-	default:
-		corrupt_error();
-	}
-	if(seekerr)
-		seek_error();
-}
-
-void error(const char *format, ...)
-{
-	va_list ap;
-	va_start(ap, format);
-	vfprintf(stderr, format, ap);
-	va_end(ap);
-	exit(1);
-}
-
-int main(int argc, char **argv)
-{
-	FILE *classfile;
-	u_int16_t cp_count, i, this_class, classinfo_ptr;
-	u_int8_t length;
-
-	program = argv[0];
-
-	if(!argv[1])
-		error("%s: Missing input file\n", program);
-	classfile = fopen(argv[1], "rb");
-	if(!classfile)
-		error("%s: Error opening %s\n", program, argv[1]);
-
-	if(fseek(classfile, 8, SEEK_SET))  /* skip magic and version numbers */
-		seek_error();
-	cp_count = read_16(classfile);
-	pool = calloc(cp_count, sizeof(long));
-	if(!pool)
-		error("%s: Out of memory for constant pool\n", program);
-
-	for(i = 1; i < cp_count; ++i)
-		skip_constant(classfile, &i);
-	if(fseek(classfile, 2, SEEK_CUR))	/* skip access flags */
-		seek_error();
-
-	this_class = read_16(classfile);
-	if(this_class < 1 || this_class >= cp_count)
-		corrupt_error();
-	if(!pool[this_class] || pool[this_class] == -1)
-		corrupt_error();
-	if(fseek(classfile, pool[this_class] + 1, SEEK_SET))
-		seek_error();
-
-	classinfo_ptr = read_16(classfile);
-	if(classinfo_ptr < 1 || classinfo_ptr >= cp_count)
-		corrupt_error();
-	if(!pool[classinfo_ptr] || pool[classinfo_ptr] == -1)
-		corrupt_error();
-	if(fseek(classfile, pool[classinfo_ptr] + 1, SEEK_SET))
-		seek_error();
-
-	length = read_16(classfile);
-	for(i = 0; i < length; ++i)
-	{
-		u_int8_t x = read_8(classfile);
-		if((x & 0x80) || !x)
-		{
-			if((x & 0xE0) == 0xC0)
-			{
-				u_int8_t y = read_8(classfile);
-				if((y & 0xC0) == 0x80)
-				{
-					int c = ((x & 0x1f) << 6) + (y & 0x3f);
-					if(c) putchar(c);
-					else utf8_error();
-				}
-				else utf8_error();
-			}
-			else utf8_error();
-		}
-		else if(x == '/') putchar('.');
-		else putchar(x);
-	}
-	putchar('\n');
-	free(pool);
-	fclose(classfile);
-	return 0;
-}
-====================== Cut here ===================
-
-
-====================== Cut here ===================
-#!/bin/bash
-# /usr/local/java/bin/jarwrapper - the wrapper for binfmt_misc/jar
-
-java -jar $1
-====================== Cut here ===================
-
-
-Now simply chmod +x the .class, .jar and/or .html files you want to execute.
-To add a Java program to your path best put a symbolic link to the main
-.class file into /usr/bin (or another place you like) omitting the .class
-extension. The directory containing the original .class file will be
-added to your CLASSPATH during execution.
-
-
-To test your new setup, enter in the following simple Java app, and name
-it "HelloWorld.java":
-
-	class HelloWorld {
-		public static void main(String args[]) {
-			System.out.println("Hello World!");
-		}
-	}
-
-Now compile the application with:
-	javac HelloWorld.java
-
-Set the executable permissions of the binary file, with:
-	chmod 755 HelloWorld.class
-
-And then execute it:
-	./HelloWorld.class
-
-
-To execute Java Jar files, simple chmod the *.jar files to include
-the execution bit, then just do
-       ./Application.jar
-
-
-To execute Java Applets, simple chmod the *.html files to include
-the execution bit, then just do
-	./Applet.html
-
-
-originally by Brian A. Lantz, brian@lantz.com
-heavily edited for binfmt_misc by Richard Günther
-new scripts by Colin J. Watson <cjw44@cam.ac.uk>
-added executable Jar file support by Kurt Huwig <kurt@iku-netz.de>
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/kbuild/kconfig-language.txt linux-libre-4.10-rc8-gnu/Documentation/kbuild/kconfig-language.txt
--- linux-libre-4.9-gnu/Documentation/kbuild/kconfig-language.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/kbuild/kconfig-language.txt	2017-02-12 16:03:20.000000000 -0500
@@ -113,6 +113,34 @@ applicable everywhere (see syntax).
 	That will limit the usefulness but on the other hand avoid
 	the illegal configurations all over.
 
+- weak reverse dependencies: "imply" <symbol> ["if" <expr>]
+  This is similar to "select" as it enforces a lower limit on another
+  symbol except that the "implied" symbol's value may still be set to n
+  from a direct dependency or with a visible prompt.
+
+  Given the following example:
+
+  config FOO
+	tristate
+	imply BAZ
+
+  config BAZ
+	tristate
+	depends on BAR
+
+  The following values are possible:
+
+	FOO		BAR		BAZ's default	choice for BAZ
+	---		---		-------------	--------------
+	n		y		n		N/m/y
+	m		y		m		M/y/n
+	y		y		y		Y/n
+	y		n		*		N
+
+  This is useful e.g. with multiple drivers that want to indicate their
+  ability to hook into a secondary subsystem while allowing the user to
+  configure that subsystem out without also having to unset these drivers.
+
 - limiting menu display: "visible if" <expr>
   This attribute is only applicable to menu blocks, if the condition is
   false, the menu block is not displayed to the user (the symbols
@@ -481,6 +509,7 @@ historical issues resolved through these
   b) Match dependency semantics:
 	b1) Swap all "select FOO" to "depends on FOO" or,
 	b2) Swap all "depends on FOO" to "select FOO"
+  c) Consider the use of "imply" instead of "select"
 
 The resolution to a) can be tested with the sample Kconfig file
 Documentation/kbuild/Kconfig.recursion-issue-01 through the removal
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/kernel-doc-nano-HOWTO.txt linux-libre-4.10-rc8-gnu/Documentation/kernel-doc-nano-HOWTO.txt
--- linux-libre-4.9-gnu/Documentation/kernel-doc-nano-HOWTO.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/kernel-doc-nano-HOWTO.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 NOTE: this document is outdated and will eventually be removed.  See
-Documentation/kernel-documentation.rst for current information.
+Documentation/doc-guide/ for current information.
 
 kernel-doc nano-HOWTO
 =====================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/kernel-docs.txt linux-libre-4.10-rc8-gnu/Documentation/kernel-docs.txt
--- linux-libre-4.9-gnu/Documentation/kernel-docs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/kernel-docs.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,652 +0,0 @@
-.. _kernel_docs:
-
-Index of Documentation for People Interested in Writing and/or Understanding the Linux Kernel
-=============================================================================================
-
-          Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
-
-The need for a document like this one became apparent in the
-linux-kernel mailing list as the same questions, asking for pointers
-to information, appeared again and again.
-
-Fortunately, as more and more people get to GNU/Linux, more and more
-get interested in the Kernel. But reading the sources is not always
-enough. It is easy to understand the code, but miss the concepts, the
-philosophy and design decisions behind this code.
-
-Unfortunately, not many documents are available for beginners to
-start. And, even if they exist, there was no "well-known" place which
-kept track of them. These lines try to cover this lack. All documents
-available on line known by the author are listed, while some reference
-books are also mentioned.
-
-PLEASE, if you know any paper not listed here or write a new document,
-send me an e-mail, and I'll include a reference to it here. Any
-corrections, ideas or comments are also welcomed.
-
-The papers that follow are listed in no particular order. All are
-cataloged with the following fields: the document's "Title", the
-"Author"/s, the "URL" where they can be found, some "Keywords" helpful
-when searching for specific topics, and a brief "Description" of the
-Document.
-
-Enjoy!
-
-.. note::
-
-   The documents on each section of this document are ordered by its
-   published date, from the newest to the oldest.
-
-Docs at the Linux Kernel tree
------------------------------
-
-The DocBook books should be built with ``make {htmldocs | psdocs | pdfdocs}``.
-The Sphinx books should be built with ``make {htmldocs | pdfdocs | epubdocs}``.
-
-    * Name: **linux/Documentation**
-
-      :Author: Many.
-      :Location: Documentation/
-      :Keywords: text files, Sphinx, DocBook.
-      :Description: Documentation that comes with the kernel sources,
-        inside the Documentation directory. Some pages from this document
-        (including this document itself) have been moved there, and might
-        be more up to date than the web version.
-
-    * Title: **The Kernel Hacking HOWTO**
-
-      :Author: Various Talented People, and Rusty.
-      :Location: Documentation/DocBook/kernel-hacking.tmpl
-      :Keywords: HOWTO, kernel contexts, deadlock, locking, modules,
-        symbols, return conventions.
-      :Description: From the Introduction: "Please understand that I
-        never wanted to write this document, being grossly underqualified,
-        but I always wanted to read it, and this was the only way. I
-        simply explain some best practices, and give reading entry-points
-        into the kernel sources. I avoid implementation details: that's
-        what the code is for, and I ignore whole tracts of useful
-        routines. This document assumes familiarity with C, and an
-        understanding of what the kernel is, and how it is used. It was
-        originally written for the 2.3 kernels, but nearly all of it
-        applies to 2.2 too; 2.0 is slightly different".
-
-    * Title: **Linux Kernel Locking HOWTO**
-
-      :Author: Various Talented People, and Rusty.
-      :Location: Documentation/DocBook/kernel-locking.tmpl
-      :Keywords: locks, locking, spinlock, semaphore, atomic, race
-        condition, bottom halves, tasklets, softirqs.
-      :Description: The title says it all: document describing the
-        locking system in the Linux Kernel either in uniprocessor or SMP
-        systems.
-      :Notes: "It was originally written for the later (>2.3.47) 2.3
-        kernels, but most of it applies to 2.2 too; 2.0 is slightly
-        different". Freely redistributable under the conditions of the GNU
-        General Public License.
-
-On-line docs
-------------
-
-    * Title: **Linux Kernel Mailing List Glossary**
-
-      :Author: various
-      :URL: http://kernelnewbies.org/glossary/
-      :Date: rolling version
-      :Keywords: glossary, terms, linux-kernel.
-      :Description: From the introduction: "This glossary is intended as
-        a brief description of some of the acronyms and terms you may hear
-        during discussion of the Linux kernel".
-
-    * Title: **Tracing the Way of Data in a TCP Connection through the Linux Kernel**
-
-      :Author: Richard Sailer
-      :URL: https://archive.org/details/linux_kernel_data_flow_short_paper
-      :Date: 2016
-      :Keywords: Linux Kernel Networking, TCP, tracing, ftrace
-      :Description: A seminar paper explaining ftrace and how to use it for
-        understanding linux kernel internals,
-        illustrated at tracing the way of a TCP packet through the kernel.
-      :Abstract: *This short paper outlines the usage of ftrace a tracing framework
-        as a tool to understand a running Linux system.
-        Having obtained a trace-log a kernel hacker can read and understand
-        source code more determined and with context.
-        In a detailed example this approach is demonstrated in tracing
-        and the way of data in a TCP Connection through the kernel.
-        Finally this trace-log is used as base for more a exact conceptual
-        exploration and description of the Linux TCP/IP implementation.*
-
-    * Title: **On submitting kernel Patches**
-
-      :Author: Andi Kleen
-      :URL: http://halobates.de/on-submitting-kernel-patches.pdf
-      :Date: 2008
-      :Keywords: patches, review process, types of submissions, basic rules, case studies
-      :Description: This paper gives several experience values on what types of patches
-        there are and how likley they get merged.
-      :Abstract:
-        [...]. This paper examines some common problems for
-        submitting larger changes and some strategies to avoid problems.
-
-    * Title: **Overview of the Virtual File System**
-
-      :Author: Richard Gooch.
-      :URL: http://www.mjmwired.net/kernel/Documentation/filesystems/vfs.txt
-      :Date: 2007
-      :Keywords: VFS, File System, mounting filesystems, opening files,
-        dentries, dcache.
-      :Description: Brief introduction to the Linux Virtual File System.
-        What is it, how it works, operations taken when opening a file or
-        mounting a file system and description of important data
-        structures explaining the purpose of each of their entries.
-
-    * Title: **Linux Device Drivers, Third Edition**
-
-      :Author: Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
-      :URL: http://lwn.net/Kernel/LDD3/
-      :Date: 2005
-      :Description: A 600-page book covering the (2.6.10) driver
-        programming API and kernel hacking in general.  Available under the
-        Creative Commons Attribution-ShareAlike 2.0 license.
-      :note: You can also :ref:`purchase a copy from O'Reilly or elsewhere  <ldd3_published>`.
-
-    * Title: **Writing an ALSA Driver**
-
-      :Author: Takashi Iwai <tiwai@suse.de>
-      :URL: http://www.alsa-project.org/~iwai/writing-an-alsa-driver/index.html
-      :Date: 2005
-      :Keywords: ALSA, sound, soundcard, driver, lowlevel, hardware.
-      :Description: Advanced Linux Sound Architecture for developers,
-        both at kernel and user-level sides. ALSA is the Linux kernel
-        sound architecture in the 2.6 kernel version.
-
-    * Title: **Linux PCMCIA Programmer's Guide**
-
-      :Author: David Hinds.
-      :URL: http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html
-      :Date: 2003
-      :Keywords: PCMCIA.
-      :Description: "This document describes how to write kernel device
-        drivers for the Linux PCMCIA Card Services interface. It also
-        describes how to write user-mode utilities for communicating with
-        Card Services.
-
-    * Title: **Linux Kernel Module Programming Guide**
-
-      :Author: Ori Pomerantz.
-      :URL: http://tldp.org/LDP/lkmpg/2.6/html/index.html
-      :Date: 2001
-      :Keywords: modules, GPL book, /proc, ioctls, system calls,
-        interrupt handlers .
-      :Description: Very nice 92 pages GPL book on the topic of modules
-        programming. Lots of examples.
-
-    * Title: **Global spinlock list and usage**
-
-      :Author: Rick Lindsley.
-      :URL: http://lse.sourceforge.net/lockhier/global-spin-lock
-      :Date: 2001
-      :Keywords: spinlock.
-      :Description: This is an attempt to document both the existence and
-        usage of the spinlocks in the Linux 2.4.5 kernel. Comprehensive
-        list of spinlocks showing when they are used, which functions
-        access them, how each lock is acquired, under what conditions it
-        is held, whether interrupts can occur or not while it is held...
-
-    * Title: **A Linux vm README**
-
-      :Author: Kanoj Sarcar.
-      :URL: http://kos.enix.org/pub/linux-vmm.html
-      :Date: 2001
-      :Keywords: virtual memory, mm, pgd, vma, page, page flags, page
-        cache, swap cache, kswapd.
-      :Description: Telegraphic, short descriptions and definitions
-        relating the Linux virtual memory implementation.
-
-    * Title: **Video4linux Drivers, Part 1: Video-Capture Device**
-
-      :Author: Alan Cox.
-      :URL: http://www.linux-mag.com/id/406
-      :Date: 2000
-      :Keywords: video4linux, driver, video capture, capture devices,
-        camera driver.
-      :Description: The title says it all.
-
-    * Title: **Video4linux Drivers, Part 2: Video-capture Devices**
-
-      :Author: Alan Cox.
-      :URL: http://www.linux-mag.com/id/429
-      :Date: 2000
-      :Keywords: video4linux, driver, video capture, capture devices,
-        camera driver, control, query capabilities, capability, facility.
-      :Description: The title says it all.
-
-    * Title: **Linux IP Networking. A Guide to the Implementation and Modification of the Linux Protocol Stack.**
-
-      :Author: Glenn Herrin.
-      :URL: http://www.cs.unh.edu/cnrg/gherrin
-      :Date: 2000
-      :Keywords: network, networking, protocol, IP, UDP, TCP, connection,
-        socket, receiving, transmitting, forwarding, routing, packets,
-        modules, /proc, sk_buff, FIB, tags.
-      :Description: Excellent paper devoted to the Linux IP Networking,
-        explaining anything from the kernel's to the user space
-        configuration tools' code. Very good to get a general overview of
-        the kernel networking implementation and understand all steps
-        packets follow from the time they are received at the network
-        device till they are delivered to applications. The studied kernel
-        code is from 2.2.14 version. Provides code for a working packet
-        dropper example.
-
-    * Title: **How To Make Sure Your Driver Will Work On The Power Macintosh**
-
-      :Author: Paul Mackerras.
-      :URL: http://www.linux-mag.com/id/261
-      :Date: 1999
-      :Keywords: Mac, Power Macintosh, porting, drivers, compatibility.
-      :Description: The title says it all.
-
-    * Title: **An Introduction to SCSI Drivers**
-
-      :Author: Alan Cox.
-      :URL: http://www.linux-mag.com/id/284
-      :Date: 1999
-      :Keywords: SCSI, device, driver.
-      :Description: The title says it all.
-
-    * Title: **Advanced SCSI Drivers And Other Tales**
-
-      :Author: Alan Cox.
-      :URL: http://www.linux-mag.com/id/307
-      :Date: 1999
-      :Keywords: SCSI, device, driver, advanced.
-      :Description: The title says it all.
-
-    * Title: **Writing Linux Mouse Drivers**
-
-      :Author: Alan Cox.
-      :URL: http://www.linux-mag.com/id/330
-      :Date: 1999
-      :Keywords: mouse, driver, gpm.
-      :Description: The title says it all.
-
-    * Title: **More on Mouse Drivers**
-
-      :Author: Alan Cox.
-      :URL: http://www.linux-mag.com/id/356
-      :Date: 1999
-      :Keywords: mouse, driver, gpm, races, asynchronous I/O.
-      :Description: The title still says it all.
-
-    * Title: **Writing Video4linux Radio Driver**
-
-      :Author: Alan Cox.
-      :URL: http://www.linux-mag.com/id/381
-      :Date: 1999
-      :Keywords: video4linux, driver, radio, radio devices.
-      :Description: The title says it all.
-
-    * Title: **I/O Event Handling Under Linux**
-
-      :Author: Richard Gooch.
-      :URL: http://web.mit.edu/~yandros/doc/io-events.html
-      :Date: 1999
-      :Keywords: IO, I/O, select(2), poll(2), FDs, aio_read(2), readiness
-        event queues.
-      :Description: From the Introduction: "I/O Event handling is about
-        how your Operating System allows you to manage a large number of
-        open files (file descriptors in UNIX/POSIX, or FDs) in your
-        application. You want the OS to notify you when FDs become active
-        (have data ready to be read or are ready for writing). Ideally you
-        want a mechanism that is scalable. This means a large number of
-        inactive FDs cost very little in memory and CPU time to manage".
-
-    * Title: **(nearly) Complete Linux Loadable Kernel Modules. The definitive guide for hackers, virus coders and system administrators.**
-
-      :Author: pragmatic/THC.
-      :URL: http://packetstormsecurity.org/docs/hack/LKM_HACKING.html
-      :Date: 1999
-      :Keywords: syscalls, intercept, hide, abuse, symbol table.
-      :Description: Interesting paper on how to abuse the Linux kernel in
-        order to intercept and modify syscalls, make
-        files/directories/processes invisible, become root, hijack ttys,
-        write kernel modules based virus... and solutions for admins to
-        avoid all those abuses.
-      :Notes: For 2.0.x kernels. Gives guidances to port it to 2.2.x
-        kernels.
-
-    * Name: **Linux Virtual File System**
-
-      :Author: Peter J. Braam.
-      :URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/
-      :Date: 1998
-      :Keywords: slides, VFS, inode, superblock, dentry, dcache.
-      :Description: Set of slides, presumably from a presentation on the
-        Linux VFS layer. Covers version 2.1.x, with dentries and the
-        dcache.
-
-    * Title: **The Venus kernel interface**
-
-      :Author: Peter J. Braam.
-      :URL: http://www.coda.cs.cmu.edu/doc/html/kernel-venus-protocol.html
-      :Date: 1998
-      :Keywords: coda, filesystem, venus, cache manager.
-      :Description: "This document describes the communication between
-        Venus and kernel level file system code needed for the operation
-        of the Coda filesystem. This version document is meant to describe
-        the current interface (version 1.0) as well as improvements we
-        envisage".
-
-    * Title: **Design and Implementation of the Second Extended Filesystem**
-
-      :Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
-      :URL: http://web.mit.edu/tytso/www/linux/ext2intro.html
-      :Date: 1998
-      :Keywords: ext2, linux fs history, inode, directory, link, devices,
-        VFS, physical structure, performance, benchmarks, ext2fs library,
-        ext2fs tools, e2fsck.
-      :Description: Paper written by three of the top ext2 hackers.
-        Covers Linux filesystems history, ext2 motivation, ext2 features,
-        design, physical structure on disk, performance, benchmarks,
-        e2fsck's passes description... A must read!
-      :Notes: This paper was first published in the Proceedings of the
-        First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
-
-    * Title: **The Linux RAID-1, 4, 5 Code**
-
-      :Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
-      :URL: http://www.linuxjournal.com/article.php?sid=2391
-      :Date: 1997
-      :Keywords: RAID, MD driver.
-      :Description: Linux Journal Kernel Korner article. Here is its
-      :Abstract: *A description of the implementation of the RAID-1,
-        RAID-4 and RAID-5 personalities of the MD device driver in the
-        Linux kernel, providing users with high performance and reliable,
-        secondary-storage capability using software*.
-
-    * Title: **Linux Kernel Hackers' Guide**
-
-      :Author: Michael K. Johnson.
-      :URL: http://www.tldp.org/LDP/khg/HyperNews/get/khg.html
-      :Date: 1997
-      :Keywords: device drivers, files, VFS, kernel interface, character vs
-        block devices, hardware interrupts, scsi, DMA, access to user memory,
-        memory allocation, timers.
-      :Description: A guide designed to help you get up to speed on the
-        concepts that are not intuitevly obvious, and to document the internal
-        structures of Linux.
-
-    * Title: **Dynamic Kernels: Modularized Device Drivers**
-
-      :Author: Alessandro Rubini.
-      :URL: http://www.linuxjournal.com/article.php?sid=1219
-      :Date: 1996
-      :Keywords: device driver, module, loading/unloading modules,
-        allocating resources.
-      :Description: Linux Journal Kernel Korner article. Here is its
-      :Abstract: *This is the first of a series of four articles
-        co-authored by Alessandro Rubini and Georg Zezchwitz which present
-        a practical approach to writing Linux device drivers as kernel
-        loadable modules. This installment presents an introduction to the
-        topic, preparing the reader to understand next month's
-        installment*.
-
-    * Title: **Dynamic Kernels: Discovery**
-
-      :Author: Alessandro Rubini.
-      :URL: http://www.linuxjournal.com/article.php?sid=1220
-      :Date: 1996
-      :Keywords: character driver, init_module, clean_up module,
-        autodetection, mayor number, minor number, file operations,
-        open(), close().
-      :Description: Linux Journal Kernel Korner article. Here is its
-      :Abstract: *This article, the second of four, introduces part of
-        the actual code to create custom module implementing a character
-        device driver. It describes the code for module initialization and
-        cleanup, as well as the open() and close() system calls*.
-
-    * Title: **The Devil's in the Details**
-
-      :Author: Georg v. Zezschwitz and Alessandro Rubini.
-      :URL: http://www.linuxjournal.com/article.php?sid=1221
-      :Date: 1996
-      :Keywords: read(), write(), select(), ioctl(), blocking/non
-        blocking mode, interrupt handler.
-      :Description: Linux Journal Kernel Korner article. Here is its
-      :Abstract: *This article, the third of four on writing character
-        device drivers, introduces concepts of reading, writing, and using
-        ioctl-calls*.
-
-    * Title: **Dissecting Interrupts and Browsing DMA**
-
-      :Author: Alessandro Rubini and Georg v. Zezschwitz.
-      :URL: http://www.linuxjournal.com/article.php?sid=1222
-      :Date: 1996
-      :Keywords: interrupts, irqs, DMA, bottom halves, task queues.
-      :Description: Linux Journal Kernel Korner article. Here is its
-      :Abstract: *This is the fourth in a series of articles about
-        writing character device drivers as loadable kernel modules. This
-        month, we further investigate the field of interrupt handling.
-        Though it is conceptually simple, practical limitations and
-        constraints make this an ''interesting'' part of device driver
-        writing, and several different facilities have been provided for
-        different situations. We also investigate the complex topic of
-        DMA*.
-
-    * Title: **Device Drivers Concluded**
-
-      :Author: Georg v. Zezschwitz.
-      :URL: http://www.linuxjournal.com/article.php?sid=1287
-      :Date: 1996
-      :Keywords: address spaces, pages, pagination, page management,
-        demand loading, swapping, memory protection, memory mapping, mmap,
-        virtual memory areas (VMAs), vremap, PCI.
-      :Description: Finally, the above turned out into a five articles
-        series. This latest one's introduction reads: "This is the last of
-        five articles about character device drivers. In this final
-        section, Georg deals with memory mapping devices, beginning with
-        an overall description of the Linux memory management concepts".
-
-    * Title: **Network Buffers And Memory Management**
-
-      :Author: Alan Cox.
-      :URL: http://www.linuxjournal.com/article.php?sid=1312
-      :Date: 1996
-      :Keywords: sk_buffs, network devices, protocol/link layer
-        variables, network devices flags, transmit, receive,
-        configuration, multicast.
-      :Description: Linux Journal Kernel Korner.
-      :Abstract: *Writing a network device driver for Linux is fundamentally
-        simple---most of the complexity (other than talking to the
-        hardware) involves managing network packets in memory*.
-
-    * Title: **Analysis of the Ext2fs structure**
-
-      :Author: Louis-Dominique Dubeau.
-      :URL: http://teaching.csse.uwa.edu.au/units/CITS2002/fs-ext2/
-      :Date: 1994
-      :Keywords: ext2, filesystem, ext2fs.
-      :Description: Description of ext2's blocks, directories, inodes,
-        bitmaps, invariants...
-
-Published books
----------------
-
-    * Title: **Linux Treiber entwickeln**
-
-      :Author: Jürgen Quade, Eva-Katharina Kunst
-      :Publisher: dpunkt.verlag
-      :Date: Oct 2015 (4th edition)
-      :Pages: 688
-      :ISBN: 978-3-86490-288-8
-      :Note: German. The third edition from 2011 is
-         much cheaper and still quite up-to-date.
-
-    * Title: **Linux Kernel Networking: Implementation and Theory**
-
-      :Author: Rami Rosen
-      :Publisher: Apress
-      :Date: December 22, 2013
-      :Pages: 648
-      :ISBN: 978-1430261964
-
-    * Title: **Embedded Linux Primer: A practical Real-World Approach, 2nd Edition**
-
-      :Author: Christopher Hallinan
-      :Publisher: Pearson
-      :Date: November, 2010
-      :Pages: 656
-      :ISBN: 978-0137017836
-
-    * Title: **Linux Kernel Development, 3rd Edition**
-
-      :Author: Robert Love
-      :Publisher: Addison-Wesley
-      :Date: July, 2010
-      :Pages: 440
-      :ISBN: 978-0672329463
-
-    * Title: **Essential Linux Device Drivers**
-
-      :Author: Sreekrishnan Venkateswaran
-      :Published: Prentice Hall
-      :Date: April, 2008
-      :Pages: 744
-      :ISBN: 978-0132396554
-
-.. _ldd3_published:
-
-    * Title: **Linux Device Drivers, 3rd Edition**
-
-      :Authors: Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
-      :Publisher: O'Reilly & Associates
-      :Date: 2005
-      :Pages: 636
-      :ISBN: 0-596-00590-3
-      :Notes: Further information in
-        http://www.oreilly.com/catalog/linuxdrive3/
-        PDF format, URL: http://lwn.net/Kernel/LDD3/
-
-    * Title: **Linux Kernel Internals**
-
-      :Author: Michael Beck
-      :Publisher: Addison-Wesley
-      :Date: 1997
-      :ISBN: 0-201-33143-8 (second edition)
-
-    * Title: **Programmation Linux 2.0 API systeme et fonctionnement du noyau**
-
-      :Author: Remy Card, Eric Dumas, Franck Mevel
-      :Publisher: Eyrolles
-      :Date: 1997
-      :Pages: 520
-      :ISBN: 2-212-08932-5
-      :Notes: French
-
-    * Title: **The Design and Implementation of the 4.4 BSD UNIX Operating System**
-
-      :Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
-        John S. Quarterman
-      :Publisher: Addison-Wesley
-      :Date: 1996
-      :ISBN: 0-201-54979-4
-
-    * Title: **Unix internals -- the new frontiers**
-
-      :Author: Uresh Vahalia
-      :Publisher: Prentice Hall
-      :Date: 1996
-      :Pages: 600
-      :ISBN: 0-13-101908-2
-
-    * Title: **Programming for the real world - POSIX.4**
-
-      :Author: Bill O. Gallmeister
-      :Publisher: O'Reilly & Associates, Inc
-      :Date: 1995
-      :Pages: 552
-      :ISBN: I-56592-074-0
-      :Notes: Though not being directly about Linux, Linux aims to be
-        POSIX. Good reference.
-
-    * Title:  **UNIX  Systems  for  Modern Architectures: Symmetric Multiprocessing and Caching for Kernel Programmers**
-
-      :Author: Curt Schimmel
-      :Publisher: Addison Wesley
-      :Date: June, 1994
-      :Pages: 432
-      :ISBN: 0-201-63338-8
-
-    * Title: **The Design and Implementation of the 4.3 BSD UNIX Operating System**
-
-      :Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J
-        Karels, John S. Quarterman
-      :Publisher: Addison-Wesley
-      :Date: 1989 (reprinted with corrections on October, 1990)
-      :ISBN: 0-201-06196-1
-
-    * Title: **The Design of the UNIX Operating System**
-
-      :Author: Maurice J. Bach
-      :Publisher: Prentice Hall
-      :Date: 1986
-      :Pages: 471
-      :ISBN: 0-13-201757-1
-
-Miscellaneous
--------------
-
-    * Name: **Cross-Referencing Linux**
-
-      :URL: http://lxr.free-electrons.com/
-      :Keywords: Browsing source code.
-      :Description: Another web-based Linux kernel source code browser.
-        Lots of cross references to variables and functions. You can see
-        where they are defined and where they are used.
-
-    * Name: **Linux Weekly News**
-
-      :URL: http://lwn.net
-      :Keywords: latest kernel news.
-      :Description: The title says it all. There's a fixed kernel section
-        summarizing developers' work, bug fixes, new features and versions
-        produced during the week. Published every Thursday.
-
-    * Name: **The home page of Linux-MM**
-
-      :Author: The Linux-MM team.
-      :URL: http://linux-mm.org/
-      :Keywords: memory management, Linux-MM, mm patches, TODO, docs,
-        mailing list.
-      :Description: Site devoted to Linux Memory Management development.
-        Memory related patches, HOWTOs, links, mm developers... Don't miss
-        it if you are interested in memory management development!
-
-    * Name: **Kernel Newbies IRC Channel and Website**
-
-      :URL: http://www.kernelnewbies.org
-      :Keywords: IRC, newbies, channel, asking doubts.
-      :Description: #kernelnewbies on irc.oftc.net.
-        #kernelnewbies is an IRC network dedicated to the 'newbie'
-        kernel hacker. The audience mostly consists of people who are
-        learning about the kernel, working on kernel projects or
-        professional kernel hackers that want to help less seasoned kernel
-        people.
-        #kernelnewbies is on the OFTC IRC Network.
-        Try irc.oftc.net as your server and then /join #kernelnewbies.
-        The kernelnewbies website also hosts articles, documents, FAQs...
-
-    * Name: **linux-kernel mailing list archives and search engines**
-
-      :URL: http://vger.kernel.org/vger-lists.html
-      :URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html
-      :URL: http://groups.google.com/group/mlist.linux.kernel
-      :Keywords: linux-kernel, archives, search.
-      :Description: Some of the linux-kernel mailing list archivers. If
-        you have a better/another one, please let me know.
-
--------
-
-Document last updated on Tue 2016-Sep-20
-
-This document is based on:
- http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/kernel-documentation.rst linux-libre-4.10-rc8-gnu/Documentation/kernel-documentation.rst
--- linux-libre-4.9-gnu/Documentation/kernel-documentation.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/kernel-documentation.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,679 +0,0 @@
-==========================
-Linux Kernel Documentation
-==========================
-
-Introduction
-============
-
-The Linux kernel uses `Sphinx`_ to generate pretty documentation from
-`reStructuredText`_ files under ``Documentation``. To build the documentation in
-HTML or PDF formats, use ``make htmldocs`` or ``make pdfdocs``. The generated
-documentation is placed in ``Documentation/output``.
-
-.. _Sphinx: http://www.sphinx-doc.org/
-.. _reStructuredText: http://docutils.sourceforge.net/rst.html
-
-The reStructuredText files may contain directives to include structured
-documentation comments, or kernel-doc comments, from source files. Usually these
-are used to describe the functions and types and design of the code. The
-kernel-doc comments have some special structure and formatting, but beyond that
-they are also treated as reStructuredText.
-
-There is also the deprecated DocBook toolchain to generate documentation from
-DocBook XML template files under ``Documentation/DocBook``. The DocBook files
-are to be converted to reStructuredText, and the toolchain is slated to be
-removed.
-
-Finally, there are thousands of plain text documentation files scattered around
-``Documentation``. Some of these will likely be converted to reStructuredText
-over time, but the bulk of them will remain in plain text.
-
-Sphinx Build
-============
-
-The usual way to generate the documentation is to run ``make htmldocs`` or
-``make pdfdocs``. There are also other formats available, see the documentation
-section of ``make help``. The generated documentation is placed in
-format-specific subdirectories under ``Documentation/output``.
-
-To generate documentation, Sphinx (``sphinx-build``) must obviously be
-installed. For prettier HTML output, the Read the Docs Sphinx theme
-(``sphinx_rtd_theme``) is used if available. For PDF output, ``rst2pdf`` is also
-needed. All of these are widely available and packaged in distributions.
-
-To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make
-variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose
-output.
-
-To remove the generated documentation, run ``make cleandocs``.
-
-Writing Documentation
-=====================
-
-Adding new documentation can be as simple as:
-
-1. Add a new ``.rst`` file somewhere under ``Documentation``.
-2. Refer to it from the Sphinx main `TOC tree`_ in ``Documentation/index.rst``.
-
-.. _TOC tree: http://www.sphinx-doc.org/en/stable/markup/toctree.html
-
-This is usually good enough for simple documentation (like the one you're
-reading right now), but for larger documents it may be advisable to create a
-subdirectory (or use an existing one). For example, the graphics subsystem
-documentation is under ``Documentation/gpu``, split to several ``.rst`` files,
-and has a separate ``index.rst`` (with a ``toctree`` of its own) referenced from
-the main index.
-
-See the documentation for `Sphinx`_ and `reStructuredText`_ on what you can do
-with them. In particular, the Sphinx `reStructuredText Primer`_ is a good place
-to get started with reStructuredText. There are also some `Sphinx specific
-markup constructs`_.
-
-.. _reStructuredText Primer: http://www.sphinx-doc.org/en/stable/rest.html
-.. _Sphinx specific markup constructs: http://www.sphinx-doc.org/en/stable/markup/index.html
-
-Specific guidelines for the kernel documentation
-------------------------------------------------
-
-Here are some specific guidelines for the kernel documentation:
-
-* Please don't go overboard with reStructuredText markup. Keep it simple.
-
-* Please stick to this order of heading adornments:
-
-  1. ``=`` with overline for document title::
-
-       ==============
-       Document title
-       ==============
-
-  2. ``=`` for chapters::
-
-       Chapters
-       ========
-
-  3. ``-`` for sections::
-
-       Section
-       -------
-
-  4. ``~`` for subsections::
-
-       Subsection
-       ~~~~~~~~~~
-
-  Although RST doesn't mandate a specific order ("Rather than imposing a fixed
-  number and order of section title adornment styles, the order enforced will be
-  the order as encountered."), having the higher levels the same overall makes
-  it easier to follow the documents.
-
-
-the C domain
-------------
-
-The `Sphinx C Domain`_ (name c) is suited for documentation of C API. E.g. a
-function prototype:
-
-.. code-block:: rst
-
-    .. c:function:: int ioctl( int fd, int request )
-
-The C domain of the kernel-doc has some additional features. E.g. you can
-*rename* the reference name of a function with a common name like ``open`` or
-``ioctl``:
-
-.. code-block:: rst
-
-     .. c:function:: int ioctl( int fd, int request )
-        :name: VIDIOC_LOG_STATUS
-
-The func-name (e.g. ioctl) remains in the output but the ref-name changed from
-``ioctl`` to ``VIDIOC_LOG_STATUS``. The index entry for this function is also
-changed to ``VIDIOC_LOG_STATUS`` and the function can now referenced by:
-
-.. code-block:: rst
-
-     :c:func:`VIDIOC_LOG_STATUS`
-
-
-list tables
------------
-
-We recommend the use of *list table* formats. The *list table* formats are
-double-stage lists. Compared to the ASCII-art they might not be as
-comfortable for 
-readers of the text files. Their advantage is that they are easy to
-create or modify and that the diff of a modification is much more meaningful,
-because it is limited to the modified content.
-
-The ``flat-table`` is a double-stage list similar to the ``list-table`` with
-some additional features:
-
-* column-span: with the role ``cspan`` a cell can be extended through
-  additional columns
-
-* row-span: with the role ``rspan`` a cell can be extended through
-  additional rows
-
-* auto span rightmost cell of a table row over the missing cells on the right
-  side of that table-row.  With Option ``:fill-cells:`` this behavior can
-  changed from *auto span* to *auto fill*, which automatically inserts (empty)
-  cells instead of spanning the last cell.
-
-options:
-
-* ``:header-rows:``   [int] count of header rows
-* ``:stub-columns:``  [int] count of stub columns
-* ``:widths:``        [[int] [int] ... ] widths of columns
-* ``:fill-cells:``    instead of auto-spanning missing cells, insert missing cells
-
-roles:
-
-* ``:cspan:`` [int] additional columns (*morecols*)
-* ``:rspan:`` [int] additional rows (*morerows*)
-
-The example below shows how to use this markup.  The first level of the staged
-list is the *table-row*. In the *table-row* there is only one markup allowed,
-the list of the cells in this *table-row*. Exceptions are *comments* ( ``..`` )
-and *targets* (e.g. a ref to ``:ref:`last row <last row>``` / :ref:`last row
-<last row>`).
-
-.. code-block:: rst
-
-   .. flat-table:: table title
-      :widths: 2 1 1 3
-
-      * - head col 1
-        - head col 2
-        - head col 3
-        - head col 4
-
-      * - column 1
-        - field 1.1
-        - field 1.2 with autospan
-
-      * - column 2
-        - field 2.1
-        - :rspan:`1` :cspan:`1` field 2.2 - 3.3
-
-      * .. _`last row`:
-
-        - column 3
-
-Rendered as:
-
-   .. flat-table:: table title
-      :widths: 2 1 1 3
-
-      * - head col 1
-        - head col 2
-        - head col 3
-        - head col 4
-
-      * - column 1
-        - field 1.1
-        - field 1.2 with autospan
-
-      * - column 2
-        - field 2.1
-        - :rspan:`1` :cspan:`1` field 2.2 - 3.3
-
-      * .. _`last row`:
-
-        - column 3
-
-
-Including kernel-doc comments
-=============================
-
-The Linux kernel source files may contain structured documentation comments, or
-kernel-doc comments to describe the functions and types and design of the
-code. The documentation comments may be included to any of the reStructuredText
-documents using a dedicated kernel-doc Sphinx directive extension.
-
-The kernel-doc directive is of the format::
-
-  .. kernel-doc:: source
-     :option:
-
-The *source* is the path to a source file, relative to the kernel source
-tree. The following directive options are supported:
-
-export: *[source-pattern ...]*
-  Include documentation for all functions in *source* that have been exported
-  using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL`` either in *source* or in any
-  of the files specified by *source-pattern*.
-
-  The *source-pattern* is useful when the kernel-doc comments have been placed
-  in header files, while ``EXPORT_SYMBOL`` and ``EXPORT_SYMBOL_GPL`` are next to
-  the function definitions.
-
-  Examples::
-
-    .. kernel-doc:: lib/bitmap.c
-       :export:
-
-    .. kernel-doc:: include/net/mac80211.h
-       :export: net/mac80211/*.c
-
-internal: *[source-pattern ...]*
-  Include documentation for all functions and types in *source* that have
-  **not** been exported using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL`` either
-  in *source* or in any of the files specified by *source-pattern*.
-
-  Example::
-
-    .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
-       :internal:
-
-doc: *title*
-  Include documentation for the ``DOC:`` paragraph identified by *title* in
-  *source*. Spaces are allowed in *title*; do not quote the *title*. The *title*
-  is only used as an identifier for the paragraph, and is not included in the
-  output. Please make sure to have an appropriate heading in the enclosing
-  reStructuredText document.
-
-  Example::
-
-    .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
-       :doc: High Definition Audio over HDMI and Display Port
-
-functions: *function* *[...]*
-  Include documentation for each *function* in *source*.
-
-  Example::
-
-    .. kernel-doc:: lib/bitmap.c
-       :functions: bitmap_parselist bitmap_parselist_user
-
-Without options, the kernel-doc directive includes all documentation comments
-from the source file.
-
-The kernel-doc extension is included in the kernel source tree, at
-``Documentation/sphinx/kernel-doc.py``. Internally, it uses the
-``scripts/kernel-doc`` script to extract the documentation comments from the
-source.
-
-.. _kernel_doc:
-
-Writing kernel-doc comments
-===========================
-
-In order to provide embedded, "C" friendly, easy to maintain, but consistent and
-extractable overview, function and type documentation, the Linux kernel has
-adopted a consistent style for documentation comments. The format for this
-documentation is called the kernel-doc format, described below. This style
-embeds the documentation within the source files, using a few simple conventions
-for adding documentation paragraphs and documenting functions and their
-parameters, structures and unions and their members, enumerations, and typedefs.
-
-.. note:: The kernel-doc format is deceptively similar to gtk-doc or Doxygen,
-   yet distinctively different, for historical reasons. The kernel source
-   contains tens of thousands of kernel-doc comments. Please stick to the style
-   described here.
-
-The ``scripts/kernel-doc`` script is used by the Sphinx kernel-doc extension in
-the documentation build to extract this embedded documentation into the various
-HTML, PDF, and other format documents.
-
-In order to provide good documentation of kernel functions and data structures,
-please use the following conventions to format your kernel-doc comments in the
-Linux kernel source.
-
-How to format kernel-doc comments
----------------------------------
-
-The opening comment mark ``/**`` is reserved for kernel-doc comments. Only
-comments so marked will be considered by the ``kernel-doc`` tool. Use it only
-for comment blocks that contain kernel-doc formatted comments. The usual ``*/``
-should be used as the closing comment marker. The lines in between should be
-prefixed by `` * `` (space star space).
-
-The function and type kernel-doc comments should be placed just before the
-function or type being described. The overview kernel-doc comments may be freely
-placed at the top indentation level.
-
-Example kernel-doc function comment::
-
-  /**
-   * foobar() - Brief description of foobar.
-   * @arg: Description of argument of foobar.
-   *
-   * Longer description of foobar.
-   *
-   * Return: Description of return value of foobar.
-   */
-  int foobar(int arg)
-
-The format is similar for documentation for structures, enums, paragraphs,
-etc. See the sections below for details.
-
-The kernel-doc structure is extracted from the comments, and proper `Sphinx C
-Domain`_ function and type descriptions with anchors are generated for them. The
-descriptions are filtered for special kernel-doc highlights and
-cross-references. See below for details.
-
-.. _Sphinx C Domain: http://www.sphinx-doc.org/en/stable/domains.html
-
-Highlights and cross-references
--------------------------------
-
-The following special patterns are recognized in the kernel-doc comment
-descriptive text and converted to proper reStructuredText markup and `Sphinx C
-Domain`_ references.
-
-.. attention:: The below are **only** recognized within kernel-doc comments,
-	       **not** within normal reStructuredText documents.
-
-``funcname()``
-  Function reference.
-
-``@parameter``
-  Name of a function parameter. (No cross-referencing, just formatting.)
-
-``%CONST``
-  Name of a constant. (No cross-referencing, just formatting.)
-
-``$ENVVAR``
-  Name of an environment variable. (No cross-referencing, just formatting.)
-
-``&struct name``
-  Structure reference.
-
-``&enum name``
-  Enum reference.
-
-``&typedef name``
-  Typedef reference.
-
-``&struct_name->member`` or ``&struct_name.member``
-  Structure or union member reference. The cross-reference will be to the struct
-  or union definition, not the member directly.
-
-``&name``
-  A generic type reference. Prefer using the full reference described above
-  instead. This is mostly for legacy comments.
-
-Cross-referencing from reStructuredText
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To cross-reference the functions and types defined in the kernel-doc comments
-from reStructuredText documents, please use the `Sphinx C Domain`_
-references. For example::
-
-  See function :c:func:`foo` and struct/union/enum/typedef :c:type:`bar`.
-
-While the type reference works with just the type name, without the
-struct/union/enum/typedef part in front, you may want to use::
-
-  See :c:type:`struct foo <foo>`.
-  See :c:type:`union bar <bar>`.
-  See :c:type:`enum baz <baz>`.
-  See :c:type:`typedef meh <meh>`.
-
-This will produce prettier links, and is in line with how kernel-doc does the
-cross-references.
-
-For further details, please refer to the `Sphinx C Domain`_ documentation.
-
-Function documentation
-----------------------
-
-The general format of a function and function-like macro kernel-doc comment is::
-
-  /**
-   * function_name() - Brief description of function.
-   * @arg1: Describe the first argument.
-   * @arg2: Describe the second argument.
-   *        One can provide multiple line descriptions
-   *        for arguments.
-   *
-   * A longer description, with more discussion of the function function_name()
-   * that might be useful to those using or modifying it. Begins with an
-   * empty comment line, and may include additional embedded empty
-   * comment lines.
-   *
-   * The longer description may have multiple paragraphs.
-   *
-   * Return: Describe the return value of foobar.
-   *
-   * The return value description can also have multiple paragraphs, and should
-   * be placed at the end of the comment block.
-   */
-
-The brief description following the function name may span multiple lines, and
-ends with an ``@argument:`` description, a blank comment line, or the end of the
-comment block.
-
-The kernel-doc function comments describe each parameter to the function, in
-order, with the ``@argument:`` descriptions. The ``@argument:`` descriptions
-must begin on the very next line following the opening brief function
-description line, with no intervening blank comment lines. The ``@argument:``
-descriptions may span multiple lines. The continuation lines may contain
-indentation. If a function parameter is ``...`` (varargs), it should be listed
-in kernel-doc notation as: ``@...:``.
-
-The return value, if any, should be described in a dedicated section at the end
-of the comment starting with "Return:".
-
-Structure, union, and enumeration documentation
------------------------------------------------
-
-The general format of a struct, union, and enum kernel-doc comment is::
-
-  /**
-   * struct struct_name - Brief description.
-   * @member_name: Description of member member_name.
-   *
-   * Description of the structure.
-   */
-
-Below, "struct" is used to mean structs, unions and enums, and "member" is used
-to mean struct and union members as well as enumerations in an enum.
-
-The brief description following the structure name may span multiple lines, and
-ends with a ``@member:`` description, a blank comment line, or the end of the
-comment block.
-
-The kernel-doc data structure comments describe each member of the structure, in
-order, with the ``@member:`` descriptions. The ``@member:`` descriptions must
-begin on the very next line following the opening brief function description
-line, with no intervening blank comment lines. The ``@member:`` descriptions may
-span multiple lines. The continuation lines may contain indentation.
-
-In-line member documentation comments
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The structure members may also be documented in-line within the definition::
-
-  /**
-   * struct foo - Brief description.
-   * @foo: The Foo member.
-   */
-  struct foo {
-        int foo;
-        /**
-         * @bar: The Bar member.
-         */
-        int bar;
-        /**
-         * @baz: The Baz member.
-         *
-         * Here, the member description may contain several paragraphs.
-         */
-        int baz;
-  }
-
-Private members
-~~~~~~~~~~~~~~~
-
-Inside a struct description, you can use the "private:" and "public:" comment
-tags. Structure fields that are inside a "private:" area are not listed in the
-generated output documentation.  The "private:" and "public:" tags must begin
-immediately following a ``/*`` comment marker.  They may optionally include
-comments between the ``:`` and the ending ``*/`` marker.
-
-Example::
-
-  /**
-   * struct my_struct - short description
-   * @a: first member
-   * @b: second member
-   *
-   * Longer description
-   */
-  struct my_struct {
-      int a;
-      int b;
-  /* private: internal use only */
-      int c;
-  };
-
-
-Typedef documentation
----------------------
-
-The general format of a typedef kernel-doc comment is::
-
-  /**
-   * typedef type_name - Brief description.
-   *
-   * Description of the type.
-   */
-
-Overview documentation comments
--------------------------------
-
-To facilitate having source code and comments close together, you can include
-kernel-doc documentation blocks that are free-form comments instead of being
-kernel-doc for functions, structures, unions, enums, or typedefs. This could be
-used for something like a theory of operation for a driver or library code, for
-example.
-
-This is done by using a ``DOC:`` section keyword with a section title.
-
-The general format of an overview or high-level documentation comment is::
-
-  /**
-   * DOC: Theory of Operation
-   *
-   * The whizbang foobar is a dilly of a gizmo. It can do whatever you
-   * want it to do, at any time. It reads your mind. Here's how it works.
-   *
-   * foo bar splat
-   *
-   * The only drawback to this gizmo is that is can sometimes damage
-   * hardware, software, or its subject(s).
-   */
-
-The title following ``DOC:`` acts as a heading within the source file, but also
-as an identifier for extracting the documentation comment. Thus, the title must
-be unique within the file.
-
-Recommendations
----------------
-
-We definitely need kernel-doc formatted documentation for functions that are
-exported to loadable modules using ``EXPORT_SYMBOL`` or ``EXPORT_SYMBOL_GPL``.
-
-We also look to provide kernel-doc formatted documentation for functions
-externally visible to other kernel files (not marked "static").
-
-We also recommend providing kernel-doc formatted documentation for private (file
-"static") routines, for consistency of kernel source code layout. But this is
-lower priority and at the discretion of the MAINTAINER of that kernel source
-file.
-
-Data structures visible in kernel include files should also be documented using
-kernel-doc formatted comments.
-
-DocBook XML [DEPRECATED]
-========================
-
-.. attention::
-
-   This section describes the deprecated DocBook XML toolchain. Please do not
-   create new DocBook XML template files. Please consider converting existing
-   DocBook XML templates files to Sphinx/reStructuredText.
-
-Converting DocBook to Sphinx
-----------------------------
-
-Over time, we expect all of the documents under ``Documentation/DocBook`` to be
-converted to Sphinx and reStructuredText. For most DocBook XML documents, a good
-enough solution is to use the simple ``Documentation/sphinx/tmplcvt`` script,
-which uses ``pandoc`` under the hood. For example::
-
-  $ cd Documentation/sphinx
-  $ ./tmplcvt ../DocBook/in.tmpl ../out.rst
-
-Then edit the resulting rst files to fix any remaining issues, and add the
-document in the ``toctree`` in ``Documentation/index.rst``.
-
-Components of the kernel-doc system
------------------------------------
-
-Many places in the source tree have extractable documentation in the form of
-block comments above functions. The components of this system are:
-
-- ``scripts/kernel-doc``
-
-  This is a perl script that hunts for the block comments and can mark them up
-  directly into reStructuredText, DocBook, man, text, and HTML. (No, not
-  texinfo.)
-
-- ``Documentation/DocBook/*.tmpl``
-
-  These are XML template files, which are normal XML files with special
-  place-holders for where the extracted documentation should go.
-
-- ``scripts/docproc.c``
-
-  This is a program for converting XML template files into XML files. When a
-  file is referenced it is searched for symbols exported (EXPORT_SYMBOL), to be
-  able to distinguish between internal and external functions.
-
-  It invokes kernel-doc, giving it the list of functions that are to be
-  documented.
-
-  Additionally it is used to scan the XML template files to locate all the files
-  referenced herein. This is used to generate dependency information as used by
-  make.
-
-- ``Makefile``
-
-  The targets 'xmldocs', 'psdocs', 'pdfdocs', and 'htmldocs' are used to build
-  DocBook XML files, PostScript files, PDF files, and html files in
-  Documentation/DocBook. The older target 'sgmldocs' is equivalent to 'xmldocs'.
-
-- ``Documentation/DocBook/Makefile``
-
-  This is where C files are associated with SGML templates.
-
-How to use kernel-doc comments in DocBook XML template files
-------------------------------------------------------------
-
-DocBook XML template files (\*.tmpl) are like normal XML files, except that they
-can contain escape sequences where extracted documentation should be inserted.
-
-``!E<filename>`` is replaced by the documentation, in ``<filename>``, for
-functions that are exported using ``EXPORT_SYMBOL``: the function list is
-collected from files listed in ``Documentation/DocBook/Makefile``.
-
-``!I<filename>`` is replaced by the documentation for functions that are **not**
-exported using ``EXPORT_SYMBOL``.
-
-``!D<filename>`` is used to name additional files to search for functions
-exported using ``EXPORT_SYMBOL``.
-
-``!F<filename> <function [functions...]>`` is replaced by the documentation, in
-``<filename>``, for the functions listed.
-
-``!P<filename> <section title>`` is replaced by the contents of the ``DOC:``
-section titled ``<section title>`` from ``<filename>``. Spaces are allowed in
-``<section title>``; do not quote the ``<section title>``.
-
-``!C<filename>`` is replaced by nothing, but makes the tools check that all DOC:
-sections and documented functions, symbols, etc. are used. This makes sense to
-use when you use ``!F`` or ``!P`` only and want to verify that all documentation
-is included.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/kernel-parameters.txt linux-libre-4.10-rc8-gnu/Documentation/kernel-parameters.txt
--- linux-libre-4.9-gnu/Documentation/kernel-parameters.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/kernel-parameters.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,4572 +0,0 @@
-                          Kernel Parameters
-                          ~~~~~~~~~~~~~~~~~
-
-The following is a consolidated list of the kernel parameters as
-implemented by the __setup(), core_param() and module_param() macros
-and sorted into English Dictionary order (defined as ignoring all
-punctuation and sorting digits before letters in a case insensitive
-manner), and with descriptions where known.
-
-The kernel parses parameters from the kernel command line up to "--";
-if it doesn't recognize a parameter and it doesn't contain a '.', the
-parameter gets passed to init: parameters with '=' go into init's
-environment, others are passed as command line arguments to init.
-Everything after "--" is passed as an argument to init.
-
-Module parameters can be specified in two ways: via the kernel command
-line with a module name prefix, or via modprobe, e.g.:
-
-	(kernel command line) usbcore.blinkenlights=1
-	(modprobe command line) modprobe usbcore blinkenlights=1
-
-Parameters for modules which are built into the kernel need to be
-specified on the kernel command line.  modprobe looks through the
-kernel command line (/proc/cmdline) and collects module parameters
-when it loads a module, so the kernel command line can be used for
-loadable modules too.
-
-Hyphens (dashes) and underscores are equivalent in parameter names, so
-	log_buf_len=1M print-fatal-signals=1
-can also be entered as
-	log-buf-len=1M print_fatal_signals=1
-
-Double-quotes can be used to protect spaces in values, e.g.:
-	param="spaces in here"
-
-cpu lists:
-----------
-
-Some kernel parameters take a list of CPUs as a value, e.g.  isolcpus,
-nohz_full, irqaffinity, rcu_nocbs.  The format of this list is:
-
-	<cpu number>,...,<cpu number>
-
-or
-
-	<cpu number>-<cpu number>
-	(must be a positive range in ascending order)
-
-or a mixture
-
-<cpu number>,...,<cpu number>-<cpu number>
-
-Note that for the special case of a range one can split the range into equal
-sized groups and for each group use some amount from the beginning of that
-group:
-
-	<cpu number>-cpu number>:<used size>/<group size>
-
-For example one can add to the command line following parameter:
-
-	isolcpus=1,2,10-20,100-2000:2/25
-
-where the final item represents CPUs 100,101,125,126,150,151,...
-
-
-
-This document may not be entirely up to date and comprehensive. The command
-"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
-module. Loadable modules, after being loaded into the running kernel, also
-reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
-parameters may be changed at runtime by the command
-"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
-
-The parameters listed below are only valid if certain kernel build options were
-enabled and if respective hardware is present. The text in square brackets at
-the beginning of each description states the restrictions within which a
-parameter is applicable:
-
-	ACPI	ACPI support is enabled.
-	AGP	AGP (Accelerated Graphics Port) is enabled.
-	ALSA	ALSA sound support is enabled.
-	APIC	APIC support is enabled.
-	APM	Advanced Power Management support is enabled.
-	ARM	ARM architecture is enabled.
-	AVR32	AVR32 architecture is enabled.
-	AX25	Appropriate AX.25 support is enabled.
-	BLACKFIN Blackfin architecture is enabled.
-	CLK	Common clock infrastructure is enabled.
-	CMA	Contiguous Memory Area support is enabled.
-	DRM	Direct Rendering Management support is enabled.
-	DYNAMIC_DEBUG Build in debug messages and enable them at runtime
-	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.
-	HW	Appropriate hardware is enabled.
-	IA-64	IA-64 architecture is enabled.
-	IMA     Integrity measurement architecture is enabled.
-	IOSCHED	More than one I/O scheduler is enabled.
-	IP_PNP	IP DHCP, BOOTP, or RARP is enabled.
-	IPV6	IPv6 support is enabled.
-	ISAPNP	ISA PnP code is enabled.
-	ISDN	Appropriate ISDN support is enabled.
-	JOY	Appropriate joystick support is enabled.
-	KGDB	Kernel debugger support is enabled.
-	KVM	Kernel Virtual Machine support is enabled.
-	LIBATA  Libata driver is enabled
-	LP	Printer support is enabled.
-	LOOP	Loopback device support is enabled.
-	M68k	M68k architecture is enabled.
-			These options have more detailed description inside of
-			Documentation/m68k/kernel-options.txt.
-	MDA	MDA console support is enabled.
-	MIPS	MIPS architecture is enabled.
-	MOUSE	Appropriate mouse support is enabled.
-	MSI	Message Signaled Interrupts (PCI).
-	MTD	MTD (Memory Technology Device) support is enabled.
-	NET	Appropriate network support is enabled.
-	NUMA	NUMA support is enabled.
-	NFS	Appropriate NFS support is enabled.
-	OSS	OSS sound support is enabled.
-	PV_OPS	A paravirtualized kernel is enabled.
-	PARIDE	The ParIDE (parallel port IDE) subsystem is enabled.
-	PARISC	The PA-RISC architecture is enabled.
-	PCI	PCI bus support is enabled.
-	PCIE	PCI Express support is enabled.
-	PCMCIA	The PCMCIA subsystem is enabled.
-	PNP	Plug & Play support is enabled.
-	PPC	PowerPC architecture is enabled.
-	PPT	Parallel port support is enabled.
-	PS2	Appropriate PS/2 support is enabled.
-	RAM	RAM disk support is enabled.
-	S390	S390 architecture is enabled.
-	SCSI	Appropriate SCSI support is enabled.
-			A lot of drivers have their options described inside
-			the Documentation/scsi/ sub-directory.
-	SECURITY Different security models are enabled.
-	SELINUX SELinux support is enabled.
-	APPARMOR AppArmor support is enabled.
-	SERIAL	Serial support is enabled.
-	SH	SuperH architecture is enabled.
-	SMP	The kernel is an SMP kernel.
-	SPARC	Sparc architecture is enabled.
-	SWSUSP	Software suspend (hibernation) is enabled.
-	SUSPEND	System suspend states are enabled.
-	TPM	TPM drivers are enabled.
-	TS	Appropriate touchscreen support is enabled.
-	UMS	USB Mass Storage support is enabled.
-	USB	USB support is enabled.
-	USBHID	USB Human Interface Device support is enabled.
-	V4L	Video For Linux support is enabled.
-	VMMIO   Driver for memory mapped virtio devices is enabled.
-	VGA	The VGA console has been enabled.
-	VT	Virtual terminal support is enabled.
-	WDT	Watchdog support is enabled.
-	XT	IBM PC/XT MFM hard disk support is enabled.
-	X86-32	X86-32, aka i386 architecture is enabled.
-	X86-64	X86-64 architecture is enabled.
-			More X86-64 boot options can be found in
-			Documentation/x86/x86_64/boot-options.txt .
-	X86	Either 32-bit or 64-bit x86 (same as X86-32+X86-64)
-	X86_UV	SGI UV support is enabled.
-	XEN	Xen support is enabled
-
-In addition, the following text indicates that the option:
-
-	BUGS=	Relates to possible processor bugs on the said processor.
-	KNL	Is a kernel start-up parameter.
-	BOOT	Is a boot loader parameter.
-
-Parameters denoted with BOOT are actually interpreted by the boot
-loader, and have no meaning to the kernel directly.
-Do not modify the syntax of boot loader parameters without extreme
-need or coordination with <Documentation/x86/boot.txt>.
-
-There are also arch-specific kernel-parameters not documented here.
-See for example <Documentation/x86/x86_64/boot-options.txt>.
-
-Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
-a trailing = on the name of any parameter states that that parameter will
-be entered as an environment variable, whereas its absence indicates that
-it will appear as a kernel argument readable via /proc/cmdline by programs
-running once the system is up.
-
-The number of kernel parameters is not limited, but the length of the
-complete command line (parameters including spaces etc.) is limited to
-a fixed number of characters. This limit depends on the architecture
-and is between 256 and 4096 characters. It is defined in the file
-./include/asm/setup.h as COMMAND_LINE_SIZE.
-
-Finally, the [KMG] suffix is commonly described after a number of kernel
-parameter values. These 'K', 'M', and 'G' letters represent the _binary_
-multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
-bytes respectively. Such letter suffixes can also be entirely omitted.
-
-
-	acpi=		[HW,ACPI,X86,ARM64]
-			Advanced Configuration and Power Interface
-			Format: { force | on | off | strict | noirq | rsdt |
-				  copy_dsdt }
-			force -- enable ACPI if default was off
-			on -- enable ACPI but allow fallback to DT [arm64]
-			off -- disable ACPI if default was on
-			noirq -- do not use ACPI for IRQ routing
-			strict -- Be less tolerant of platforms that are not
-				strictly ACPI specification compliant.
-			rsdt -- prefer RSDT over (default) XSDT
-			copy_dsdt -- copy DSDT to memory
-			For ARM64, ONLY "acpi=off", "acpi=on" or "acpi=force"
-			are available
-
-			See also Documentation/power/runtime_pm.txt, pci=noacpi
-
-	acpi_apic_instance=	[ACPI, IOAPIC]
-			Format: <int>
-			2: use 2nd APIC table, if available
-			1,0: use 1st APIC table
-			default: 0
-
-	acpi_backlight=	[HW,ACPI]
-			acpi_backlight=vendor
-			acpi_backlight=video
-			If set to vendor, prefer vendor specific driver
-			(e.g. thinkpad_acpi, sony_acpi, etc.) instead
-			of the ACPI video.ko driver.
-
-	acpi_force_32bit_fadt_addr
-			force FADT to use 32 bit addresses rather than the
-			64 bit X_* addresses. Some firmware have broken 64
-			bit addresses for force ACPI ignore these and use
-			the older legacy 32 bit addresses.
-
-	acpica_no_return_repair [HW, ACPI]
-			Disable AML predefined validation mechanism
-			This mechanism can repair the evaluation result to make
-			the return objects more ACPI specification compliant.
-			This option is useful for developers to identify the
-			root cause of an AML interpreter issue when the issue
-			has something to do with the repair mechanism.
-
-	acpi.debug_layer=	[HW,ACPI,ACPI_DEBUG]
-	acpi.debug_level=	[HW,ACPI,ACPI_DEBUG]
-			Format: <int>
-			CONFIG_ACPI_DEBUG must be enabled to produce any ACPI
-			debug output.  Bits in debug_layer correspond to a
-			_COMPONENT in an ACPI source file, e.g.,
-			    #define _COMPONENT ACPI_PCI_COMPONENT
-			Bits in debug_level correspond to a level in
-			ACPI_DEBUG_PRINT statements, e.g.,
-			    ACPI_DEBUG_PRINT((ACPI_DB_INFO, ...
-			The debug_level mask defaults to "info".  See
-			Documentation/acpi/debug.txt for more information about
-			debug layers and levels.
-
-			Enable processor driver info messages:
-			    acpi.debug_layer=0x20000000
-			Enable PCI/PCI interrupt routing info messages:
-			    acpi.debug_layer=0x400000
-			Enable AML "Debug" output, i.e., stores to the Debug
-			object while interpreting AML:
-			    acpi.debug_layer=0xffffffff acpi.debug_level=0x2
-			Enable all messages related to ACPI hardware:
-			    acpi.debug_layer=0x2 acpi.debug_level=0xffffffff
-
-			Some values produce so much output that the system is
-			unusable.  The "log_buf_len" parameter may be useful
-			if you need to capture more output.
-
-	acpi_enforce_resources=	[ACPI]
-			{ strict | lax | no }
-			Check for resource conflicts between native drivers
-			and ACPI OperationRegions (SystemIO and SystemMemory
-			only). IO ports and memory declared in ACPI might be
-			used by the ACPI subsystem in arbitrary AML code and
-			can interfere with legacy drivers.
-			strict (default): access to resources claimed by ACPI
-			is denied; legacy drivers trying to access reserved
-			resources will fail to bind to device using them.
-			lax: access to resources claimed by ACPI is allowed;
-			legacy drivers trying to access reserved resources
-			will bind successfully but a warning message is logged.
-			no: ACPI OperationRegions are not marked as reserved,
-			no further checks are performed.
-
-	acpi_force_table_verification	[HW,ACPI]
-			Enable table checksum verification during early stage.
-			By default, this is disabled due to x86 early mapping
-			size limitation.
-
-	acpi_irq_balance [HW,ACPI]
-			ACPI will balance active IRQs
-			default in APIC mode
-
-	acpi_irq_nobalance [HW,ACPI]
-			ACPI will not move active IRQs (default)
-			default in PIC mode
-
-	acpi_irq_isa=	[HW,ACPI] If irq_balance, mark listed IRQs used by ISA
-			Format: <irq>,<irq>...
-
-	acpi_irq_pci=	[HW,ACPI] If irq_balance, clear listed IRQs for
-			use by PCI
-			Format: <irq>,<irq>...
-
-	acpi_no_auto_serialize	[HW,ACPI]
-			Disable auto-serialization of AML methods
-			AML control methods that contain the opcodes to create
-			named objects will be marked as "Serialized" by the
-			auto-serialization feature.
-			This feature is enabled by default.
-			This option allows to turn off the feature.
-
-	acpi_no_memhotplug [ACPI] Disable memory hotplug.  Useful for kdump
-			   kernels.
-
-	acpi_no_static_ssdt	[HW,ACPI]
-			Disable installation of static SSDTs at early boot time
-			By default, SSDTs contained in the RSDT/XSDT will be
-			installed automatically and they will appear under
-			/sys/firmware/acpi/tables.
-			This option turns off this feature.
-			Note that specifying this option does not affect
-			dynamic table installation which will install SSDT
-			tables to /sys/firmware/acpi/tables/dynamic.
-
-	acpi_rsdp=	[ACPI,EFI,KEXEC]
-			Pass the RSDP address to the kernel, mostly used
-			on machines running EFI runtime service to boot the
-			second kernel for kdump.
-
-	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
-			Format: To spoof as Windows 98: ="Microsoft Windows"
-
-	acpi_rev_override [ACPI] Override the _REV object to return 5 (instead
-			of 2 which is mandated by ACPI 6) as the supported ACPI
-			specification revision (when using this switch, it may
-			be necessary to carry out a cold reboot _twice_ in a
-			row to make it take effect on the platform firmware).
-
-	acpi_osi=	[HW,ACPI] Modify list of supported OS interface strings
-			acpi_osi="string1"	# add string1
-			acpi_osi="!string2"	# remove string2
-			acpi_osi=!*		# remove all strings
-			acpi_osi=!		# disable all built-in OS vendor
-						  strings
-			acpi_osi=!!		# enable all built-in OS vendor
-						  strings
-			acpi_osi=		# disable all strings
-
-			'acpi_osi=!' can be used in combination with single or
-			multiple 'acpi_osi="string1"' to support specific OS
-			vendor string(s).  Note that such command can only
-			affect the default state of the OS vendor strings, thus
-			it cannot affect the default state of the feature group
-			strings and the current state of the OS vendor strings,
-			specifying it multiple times through kernel command line
-			is meaningless.  This command is useful when one do not
-			care about the state of the feature group strings which
-			should be controlled by the OSPM.
-			Examples:
-			  1. 'acpi_osi=! acpi_osi="Windows 2000"' is equivalent
-			     to 'acpi_osi="Windows 2000" acpi_osi=!', they all
-			     can make '_OSI("Windows 2000")' TRUE.
-
-			'acpi_osi=' cannot be used in combination with other
-			'acpi_osi=' command lines, the _OSI method will not
-			exist in the ACPI namespace.  NOTE that such command can
-			only affect the _OSI support state, thus specifying it
-			multiple times through kernel command line is also
-			meaningless.
-			Examples:
-			  1. 'acpi_osi=' can make 'CondRefOf(_OSI, Local1)'
-			     FALSE.
-
-			'acpi_osi=!*' can be used in combination with single or
-			multiple 'acpi_osi="string1"' to support specific
-			string(s).  Note that such command can affect the
-			current state of both the OS vendor strings and the
-			feature group strings, thus specifying it multiple times
-			through kernel command line is meaningful.  But it may
-			still not able to affect the final state of a string if
-			there are quirks related to this string.  This command
-			is useful when one want to control the state of the
-			feature group strings to debug BIOS issues related to
-			the OSPM features.
-			Examples:
-			  1. 'acpi_osi="Module Device" acpi_osi=!*' can make
-			     '_OSI("Module Device")' FALSE.
-			  2. 'acpi_osi=!* acpi_osi="Module Device"' can make
-			     '_OSI("Module Device")' TRUE.
-			  3. 'acpi_osi=! acpi_osi=!* acpi_osi="Windows 2000"' is
-			     equivalent to
-			     'acpi_osi=!* acpi_osi=! acpi_osi="Windows 2000"'
-			     and
-			     'acpi_osi=!* acpi_osi="Windows 2000" acpi_osi=!',
-			     they all will make '_OSI("Windows 2000")' TRUE.
-
-	acpi_pm_good	[X86]
-			Override the pmtimer bug detection: force the kernel
-			to assume that this machine's pmtimer latches its value
-			and always returns good values.
-
-	acpi_sci=	[HW,ACPI] ACPI System Control Interrupt trigger mode
-			Format: { level | edge | high | low }
-
-	acpi_skip_timer_override [HW,ACPI]
-			Recognize and ignore IRQ0/pin2 Interrupt Override.
-			For broken nForce2 BIOS resulting in XT-PIC timer.
-
-	acpi_sleep=	[HW,ACPI] Sleep options
-			Format: { s3_bios, s3_mode, s3_beep, s4_nohwsig,
-				  old_ordering, nonvs, sci_force_enable }
-			See Documentation/power/video.txt for information on
-			s3_bios and s3_mode.
-			s3_beep is for debugging; it makes the PC's speaker beep
-			as soon as the kernel's real-mode entry point is called.
-			s4_nohwsig prevents ACPI hardware signature from being
-			used during resume from hibernation.
-			old_ordering causes the ACPI 1.0 ordering of the _PTS
-			control method, with respect to putting devices into
-			low power states, to be enforced (the ACPI 2.0 ordering
-			of _PTS is used by default).
-			nonvs prevents the kernel from saving/restoring the
-			ACPI NVS memory during suspend/hibernation and resume.
-			sci_force_enable causes the kernel to set SCI_EN directly
-			on resume from S1/S3 (which is against the ACPI spec,
-			but some broken systems don't work without it).
-
-	acpi_use_timer_override [HW,ACPI]
-			Use timer override. For some broken Nvidia NF5 boards
-			that require a timer override, but don't have HPET
-
-	add_efi_memmap	[EFI; X86] Include EFI memory map in
-			kernel's map of available physical RAM.
-
-	agp=		[AGP]
-			{ off | try_unsupported }
-			off: disable AGP support
-			try_unsupported: try to drive unsupported chipsets
-				(may crash computer or cause data corruption)
-
-	ALSA		[HW,ALSA]
-			See Documentation/sound/alsa/alsa-parameters.txt
-
-	alignment=	[KNL,ARM]
-			Allow the default userspace alignment fault handler
-			behaviour to be specified.  Bit 0 enables warnings,
-			bit 1 enables fixups, and bit 2 sends a segfault.
-
-	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
-
-	alloc_snapshot	[FTRACE]
-			Allocate the ftrace snapshot buffer on boot up when the
-			main buffer is allocated. This is handy if debugging
-			and you need to use tracing_snapshot() on boot up, and
-			do not want to use tracing_snapshot_alloc() as it needs
-			to be done where GFP_KERNEL allocations are allowed.
-
-	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
-				    they are unmapped. Otherwise they are
-				    flushed before they will be reused, which
-				    is a lot of faster
-			off	  - do not initialize any AMD IOMMU found in
-				    the system
-			force_isolation - Force device isolation for all
-					  devices. The IOMMU driver is not
-					  allowed anymore to lift isolation
-					  requirements as needed. This option
-					  does not override iommu=pt
-
-	amd_iommu_dump=	[HW,X86-64]
-			Enable AMD IOMMU driver option to dump the ACPI table
-			for AMD IOMMU. With this option enabled, AMD IOMMU
-			driver will print ACPI tables for AMD IOMMU during
-			IOMMU initialization.
-
-	amd_iommu_intr=	[HW,X86-64]
-			Specifies one of the following AMD IOMMU interrupt
-			remapping modes:
-			legacy     - Use legacy interrupt remapping mode.
-			vapic      - Use virtual APIC mode, which allows IOMMU
-			             to inject interrupts directly into guest.
-			             This mode requires kvm-amd.avic=1.
-			             (Default when IOMMU HW support is present.)
-
-	amijoy.map=	[HW,JOY] Amiga joystick support
-			Map of devices attached to JOY0DAT and JOY1DAT
-			Format: <a>,<b>
-			See also Documentation/input/joystick.txt
-
-	analog.map=	[HW,JOY] Analog joystick and gamepad support
-			Specifies type or capabilities of an analog joystick
-			connected to one of 16 gameports
-			Format: <type1>,<type2>,..<type16>
-
-	apc=		[HW,SPARC]
-			Power management functions (SPARCstation-4/5 + deriv.)
-			Format: noidle
-			Disable APC CPU standby support. SPARCstation-Fox does
-			not play well with APC CPU idle - disable it if you have
-			APC and your system crashes randomly.
-
-	apic=		[APIC,X86-32] Advanced Programmable Interrupt Controller
-			Change the output verbosity whilst booting
-			Format: { quiet (default) | verbose | debug }
-			Change the amount of debugging information output
-			when initialising the APIC and IO-APIC components.
-
-	apic_extnmi=	[APIC,X86] External NMI delivery setting
-			Format: { bsp (default) | all | none }
-			bsp:  External NMI is delivered only to CPU 0
-			all:  External NMIs are broadcast to all CPUs as a
-			      backup of CPU 0
-			none: External NMI is masked for all CPUs. This is
-			      useful so that a dump capture kernel won't be
-			      shot down by NMI
-
-	autoconf=	[IPV6]
-			See Documentation/networking/ipv6.txt.
-
-	show_lapic=	[APIC,X86] Advanced Programmable Interrupt Controller
-			Limit apic dumping. The parameter defines the maximal
-			number of local apics being dumped. Also it is possible
-			to set it to "all" by meaning -- no limit here.
-			Format: { 1 (default) | 2 | ... | all }.
-			The parameter valid if only apic=debug or
-			apic=verbose is specified.
-			Example: apic=debug show_lapic=all
-
-	apm=		[APM] Advanced Power Management
-			See header of arch/x86/kernel/apm_32.c.
-
-	arcrimi=	[HW,NET] ARCnet - "RIM I" (entirely mem-mapped) cards
-			Format: <io>,<irq>,<nodeID>
-
-	ataflop=	[HW,M68k]
-
-	atarimouse=	[HW,MOUSE] Atari Mouse
-
-	atkbd.extra=	[HW] Enable extra LEDs and keys on IBM RapidAccess,
-			EzKey and similar keyboards
-
-	atkbd.reset=	[HW] Reset keyboard during initialization
-
-	atkbd.set=	[HW] Select keyboard code set
-			Format: <int> (2 = AT (default), 3 = PS/2)
-
-	atkbd.scroll=	[HW] Enable scroll wheel on MS Office and similar
-			keyboards
-
-	atkbd.softraw=	[HW] Choose between synthetic and real raw mode
-			Format: <bool> (0 = real, 1 = synthetic (default))
-
-	atkbd.softrepeat= [HW]
-			Use software keyboard repeat
-
-	audit=		[KNL] Enable the audit sub-system
-			Format: { "0" | "1" } (0 = disabled, 1 = enabled)
-			0 - kernel audit is disabled and can not be enabled
-			    until the next reboot
-			unset - kernel audit is initialized but disabled and
-			    will be fully enabled by the userspace auditd.
-			1 - kernel audit is initialized and partially enabled,
-			    storing at most audit_backlog_limit messages in
-			    RAM until it is fully enabled by the userspace
-			    auditd.
-			Default: unset
-
-	audit_backlog_limit= [KNL] Set the audit queue size limit.
-			Format: <int> (must be >=0)
-			Default: 64
-
-	bau=		[X86_UV] Enable the BAU on SGI UV.  The default
-			behavior is to disable the BAU (i.e. bau=0).
-			Format: { "0" | "1" }
-			0 - Disable the BAU.
-			1 - Enable the BAU.
-			unset - Disable the BAU.
-
-	baycom_epp=	[HW,AX25]
-			Format: <io>,<mode>
-
-	baycom_par=	[HW,AX25] BayCom Parallel Port AX.25 Modem
-			Format: <io>,<mode>
-			See header of drivers/net/hamradio/baycom_par.c.
-
-	baycom_ser_fdx=	[HW,AX25]
-			BayCom Serial Port AX.25 Modem (Full Duplex Mode)
-			Format: <io>,<irq>,<mode>[,<baud>]
-			See header of drivers/net/hamradio/baycom_ser_fdx.c.
-
-	baycom_ser_hdx=	[HW,AX25]
-			BayCom Serial Port AX.25 Modem (Half Duplex Mode)
-			Format: <io>,<irq>,<mode>
-			See header of drivers/net/hamradio/baycom_ser_hdx.c.
-
-	blkdevparts=	Manual partition parsing of block device(s) for
-			embedded devices based on command line input.
-			See Documentation/block/cmdline-partition.txt
-
-	boot_delay=	Milliseconds to delay each printk during boot.
-			Values larger than 10 seconds (10000) are changed to
-			no delay (0).
-			Format: integer
-
-	bootmem_debug	[KNL] Enable bootmem allocator debug messages.
-
-	bert_disable	[ACPI]
-			Disable BERT OS support on buggy BIOSes.
-
-	bttv.card=	[HW,V4L] bttv (bt848 + bt878 based grabber cards)
-	bttv.radio=	Most important insmod options are available as
-			kernel args too.
-	bttv.pll=	See Documentation/video4linux/bttv/Insmod-options
-	bttv.tuner=
-
-	bulk_remove=off	[PPC]  This parameter disables the use of the pSeries
-			firmware feature for flushing multiple hpte entries
-			at a time.
-
-	c101=		[NET] Moxa C101 synchronous serial card
-
-	cachesize=	[BUGS=X86-32] Override level 2 CPU cache size detection.
-			Sometimes CPU hardware bugs make them report the cache
-			size incorrectly. The kernel will attempt work arounds
-			to fix known problems, but for some CPUs it is not
-			possible to determine what the correct size should be.
-			This option provides an override for these situations.
-
-	ca_keys=	[KEYS] This parameter identifies a specific key(s) on
-			the system trusted keyring to be used for certificate
-			trust validation.
-			format: { id:<keyid> | builtin }
-
-	cca=		[MIPS] Override the kernel pages' cache coherency
-			algorithm.  Accepted values range from 0 to 7
-			inclusive. See arch/mips/include/asm/pgtable-bits.h
-			for platform specific values (SB1, Loongson3 and
-			others).
-
-	ccw_timeout_log [S390]
-			See Documentation/s390/CommonIO for details.
-
-	cgroup_disable= [KNL] Disable a particular controller
-			Format: {name of the controller(s) to disable}
-			The effects of cgroup_disable=foo are:
-			- foo isn't auto-mounted if you mount all cgroups in
-			  a single hierarchy
-			- foo isn't visible as an individually mountable
-			  subsystem
-			{Currently only "memory" controller deal with this and
-			cut the overhead, others just disable the usage. So
-			only cgroup_disable=memory is actually worthy}
-
-	cgroup_no_v1=	[KNL] Disable one, multiple, all cgroup controllers in v1
-			Format: { controller[,controller...] | "all" }
-			Like cgroup_disable, but only applies to cgroup v1;
-			the blacklisted controllers remain available in cgroup2.
-
-	cgroup.memory=	[KNL] Pass options to the cgroup memory controller.
-			Format: <string>
-			nosocket -- Disable socket memory accounting.
-			nokmem -- Disable kernel memory accounting.
-
-	checkreqprot	[SELINUX] Set initial checkreqprot flag value.
-			Format: { "0" | "1" }
-			See security/selinux/Kconfig help text.
-			0 -- check protection applied by kernel (includes
-				any implied execute protection).
-			1 -- check protection requested by application.
-			Default value is set via a kernel config option.
-			Value can be changed at runtime via
-				/selinux/checkreqprot.
-
-	cio_ignore=	[S390]
-			See Documentation/s390/CommonIO for details.
-	clk_ignore_unused
-			[CLK]
-			Prevents the clock framework from automatically gating
-			clocks that have not been explicitly enabled by a Linux
-			device driver but are enabled in hardware at reset or
-			by the bootloader/firmware. Note that this does not
-			force such clocks to be always-on nor does it reserve
-			those clocks in any way. This parameter is useful for
-			debug and development, but should not be needed on a
-			platform with proper driver support.  For more
-			information, see Documentation/clk.txt.
-
-	clock=		[BUGS=X86-32, HW] gettimeofday clocksource override.
-			[Deprecated]
-			Forces specified clocksource (if available) to be used
-			when calculating gettimeofday(). If specified
-			clocksource is not available, it defaults to PIT.
-			Format: { pit | tsc | cyclone | pmtmr }
-
-	clocksource=	Override the default clocksource
-			Format: <string>
-			Override the default clocksource and use the clocksource
-			with the name specified.
-			Some clocksource names to choose from, depending on
-			the platform:
-			[all] jiffies (this is the base, fallback clocksource)
-			[ACPI] acpi_pm
-			[ARM] imx_timer1,OSTS,netx_timer,mpu_timer2,
-				pxa_timer,timer3,32k_counter,timer0_1
-			[AVR32] avr32
-			[X86-32] pit,hpet,tsc;
-				scx200_hrt on Geode; cyclone on IBM x440
-			[MIPS] MIPS
-			[PARISC] cr16
-			[S390] tod
-			[SH] SuperH
-			[SPARC64] tick
-			[X86-64] hpet,tsc
-
-	clocksource.arm_arch_timer.evtstrm=
-			[ARM,ARM64]
-			Format: <bool>
-			Enable/disable the eventstream feature of the ARM
-			architected timer so that code using WFE-based polling
-			loops can be debugged more effectively on production
-			systems.
-
-	clocksource.arm_arch_timer.fsl-a008585=
-			[ARM64]
-			Format: <bool>
-			Enable/disable the workaround of Freescale/NXP
-			erratum A-008585.  This can be useful for KVM
-			guests, if the guest device tree doesn't show the
-			erratum.  If unspecified, the workaround is
-			enabled based on the device tree.
-
-	clearcpuid=BITNUM [X86]
-			Disable CPUID feature X for the kernel. See
-			arch/x86/include/asm/cpufeatures.h for the valid bit
-			numbers. Note the Linux specific bits are not necessarily
-			stable over kernel options, but the vendor specific
-			ones should be.
-			Also note that user programs calling CPUID directly
-			or using the feature without checking anything
-			will still see it. This just prevents it from
-			being used by the kernel or shown in /proc/cpuinfo.
-			Also note the kernel might malfunction if you disable
-			some critical bits.
-
-	cma=nn[MG]@[start[MG][-end[MG]]]
-			[ARM,X86,KNL]
-			Sets the size of kernel global memory area for
-			contiguous memory allocations and optionally the
-			placement constraint by the physical address range of
-			memory allocations. A value of 0 disables CMA
-			altogether. For more information, see
-			include/linux/dma-contiguous.h
-
-	cmo_free_hint=	[PPC] Format: { yes | no }
-			Specify whether pages are marked as being inactive
-			when they are freed.  This is used in CMO environments
-			to determine OS memory pressure for page stealing by
-			a hypervisor.
-			Default: yes
-
-	coherent_pool=nn[KMG]	[ARM,KNL]
-			Sets the size of memory pool for coherent, atomic dma
-			allocations, by default set to 256K.
-
-	code_bytes	[X86] How many bytes of object code to print
-			in an oops report.
-			Range: 0 - 8192
-			Default: 64
-
-	com20020=	[HW,NET] ARCnet - COM20020 chipset
-			Format:
-			<io>[,<irq>[,<nodeID>[,<backplane>[,<ckp>[,<timeout>]]]]]
-
-	com90io=	[HW,NET] ARCnet - COM90xx chipset (IO-mapped buffers)
-			Format: <io>[,<irq>]
-
-	com90xx=	[HW,NET]
-			ARCnet - COM90xx chipset (memory-mapped buffers)
-			Format: <io>[,<irq>[,<memstart>]]
-
-	condev=		[HW,S390] console device
-	conmode=
-
-	console=	[KNL] Output console device and options.
-
-		tty<n>	Use the virtual console device <n>.
-
-		ttyS<n>[,options]
-		ttyUSB0[,options]
-			Use the specified serial port.  The options are of
-			the form "bbbbpnf", where "bbbb" is the baud rate,
-			"p" is parity ("n", "o", or "e"), "n" is number of
-			bits, and "f" is flow control ("r" for RTS or
-			omit it).  Default is "9600n8".
-
-			See Documentation/serial-console.txt for more
-			information.  See
-			Documentation/networking/netconsole.txt for an
-			alternative.
-
-		uart[8250],io,<addr>[,options]
-		uart[8250],mmio,<addr>[,options]
-		uart[8250],mmio16,<addr>[,options]
-		uart[8250],mmio32,<addr>[,options]
-		uart[8250],0x<addr>[,options]
-			Start an early, polled-mode console on the 8250/16550
-			UART at the specified I/O port or MMIO address,
-			switching to the matching ttyS device later.
-			MMIO inter-register address stride is either 8-bit
-			(mmio), 16-bit (mmio16), or 32-bit (mmio32).
-			If none of [io|mmio|mmio16|mmio32], <addr> is assumed
-			to be equivalent to 'mmio'. 'options' are specified in
-			the same format described for ttyS above; if unspecified,
-			the h/w is not re-initialized.
-
-		hvc<n>	Use the hypervisor console device <n>. This is for
-			both Xen and PowerPC hypervisors.
-
-                If the device connected to the port is not a TTY but a braille
-                device, prepend "brl," before the device type, for instance
-			console=brl,ttyS0
-		For now, only VisioBraille is supported.
-
-	consoleblank=	[KNL] The console blank (screen saver) timeout in
-			seconds. Defaults to 10*60 = 10mins. A value of 0
-			disables the blank timer.
-
-	coredump_filter=
-			[KNL] Change the default value for
-			/proc/<pid>/coredump_filter.
-			See also Documentation/filesystems/proc.txt.
-
-	cpuidle.off=1	[CPU_IDLE]
-			disable the cpuidle sub-system
-
-	cpu_init_udelay=N
-			[X86] Delay for N microsec between assert and de-assert
-			of APIC INIT to start processors.  This delay occurs
-			on every CPU online, such as boot, and resume from suspend.
-			Default: 10000
-
-	cpcihp_generic=	[HW,PCI] Generic port I/O CompactPCI driver
-			Format:
-			<first_slot>,<last_slot>,<port>,<enum_bit>[,<debug>]
-
-	crashkernel=size[KMG][@offset[KMG]]
-			[KNL] Using kexec, Linux can switch to a 'crash kernel'
-			upon panic. This parameter reserves the physical
-			memory region [offset, offset + size] for that kernel
-			image. If '@offset' is omitted, then a suitable offset
-			is selected automatically. Check
-			Documentation/kdump/kdump.txt for further details.
-
-	crashkernel=range1:size1[,range2:size2,...][@offset]
-			[KNL] Same as above, but depends on the memory
-			in the running system. The syntax of range is
-			start-[end] where start and end are both
-			a memory unit (amount[KMG]). See also
-			Documentation/kdump/kdump.txt for an example.
-
-	crashkernel=size[KMG],high
-			[KNL, x86_64] range could be above 4G. Allow kernel
-			to allocate physical memory region from top, so could
-			be above 4G if system have more than 4G ram installed.
-			Otherwise memory region will be allocated below 4G, if
-			available.
-			It will be ignored if crashkernel=X is specified.
-	crashkernel=size[KMG],low
-			[KNL, x86_64] range under 4G. When crashkernel=X,high
-			is passed, kernel could allocate physical memory region
-			above 4G, that cause second kernel crash on system
-			that require some amount of low memory, e.g. swiotlb
-			requires at least 64M+32K low memory, also enough extra
-			low memory is needed to make sure DMA buffers for 32-bit
-			devices won't run out. Kernel would try to allocate at
-			at least 256M below 4G automatically.
-			This one let user to specify own low range under 4G
-			for second kernel instead.
-			0: to disable low allocation.
-			It will be ignored when crashkernel=X,high is not used
-			or memory reserved is below 4G.
-
-	cryptomgr.notests
-                        [KNL] Disable crypto self-tests
-
-	cs89x0_dma=	[HW,NET]
-			Format: <dma>
-
-	cs89x0_media=	[HW,NET]
-			Format: { rj45 | aui | bnc }
-
-	dasd=		[HW,NET]
-			See header of drivers/s390/block/dasd_devmap.c.
-
-	db9.dev[2|3]=	[HW,JOY] Multisystem joystick support via parallel port
-			(one device per port)
-			Format: <port#>,<type>
-			See also Documentation/input/joystick-parport.txt
-
-	ddebug_query=   [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot
-			time. See Documentation/dynamic-debug-howto.txt for
-			details.  Deprecated, see dyndbg.
-
-	debug		[KNL] Enable kernel debugging (events log level).
-
-	debug_locks_verbose=
-			[KNL] verbose self-tests
-			Format=<0|1>
-			Print debugging info while doing the locking API
-			self-tests.
-			We default to 0 (no extra messages), setting it to
-			1 will print _a lot_ more information - normally
-			only useful to kernel developers.
-
-	debug_objects	[KNL] Enable object debugging
-
-	no_debug_objects
-			[KNL] Disable object debugging
-
-	debug_guardpage_minorder=
-			[KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
-			parameter allows control of the order of pages that will
-			be intentionally kept free (and hence protected) by the
-			buddy allocator. Bigger value increase the probability
-			of catching random memory corruption, but reduce the
-			amount of memory for normal system use. The maximum
-			possible value is MAX_ORDER/2.  Setting this parameter
-			to 1 or 2 should be enough to identify most random
-			memory corruption problems caused by bugs in kernel or
-			driver code when a CPU writes to (or reads from) a
-			random memory location. Note that there exists a class
-			of memory corruptions problems caused by buggy H/W or
-			F/W or by drivers badly programing DMA (basically when
-			memory is written at bus level and the CPU MMU is
-			bypassed) which are not detectable by
-			CONFIG_DEBUG_PAGEALLOC, hence this option will not help
-			tracking down these problems.
-
-	debug_pagealloc=
-			[KNL] When CONFIG_DEBUG_PAGEALLOC is set, this
-			parameter enables the feature at boot time. In
-			default, it is disabled. We can avoid allocating huge
-			chunk of memory for debug pagealloc if we don't enable
-			it at boot time and the system will work mostly same
-			with the kernel built without CONFIG_DEBUG_PAGEALLOC.
-			on: enable the feature
-
-	debugpat	[X86] Enable PAT debugging
-
-	decnet.addr=	[HW,NET]
-			Format: <area>[,<node>]
-			See also Documentation/networking/decnet.txt.
-
-	default_hugepagesz=
-			[same as hugepagesz=] The size of the default
-			HugeTLB page size. This is the size represented by
-			the legacy /proc/ hugepages APIs, used for SHM, and
-			default size when mounting hugetlbfs filesystems.
-			Defaults to the default architecture's huge page size
-			if not specified.
-
-	dhash_entries=	[KNL]
-			Set number of hash buckets for dentry cache.
-
-	disable_1tb_segments [PPC]
-			Disables the use of 1TB hash page table segments. This
-			causes the kernel to fall back to 256MB segments which
-			can be useful when debugging issues that require an SLB
-			miss to occur.
-
-	disable=	[IPV6]
-			See Documentation/networking/ipv6.txt.
-
-	disable_radix	[PPC]
-			Disable RADIX MMU mode on POWER9
-
-	disable_cpu_apicid= [X86,APIC,SMP]
-			Format: <int>
-			The number of initial APIC ID for the
-			corresponding CPU to be disabled at boot,
-			mostly used for the kdump 2nd kernel to
-			disable BSP to wake up multiple CPUs without
-			causing system reset or hang due to sending
-			INIT from AP to BSP.
-
-	disable_ddw     [PPC/PSERIES]
-			Disable Dynamic DMA Window support. Use this if
-			to workaround buggy firmware.
-
-	disable_ipv6=	[IPV6]
-			See Documentation/networking/ipv6.txt.
-
-	disable_mtrr_cleanup [X86]
-			The kernel tries to adjust MTRR layout from continuous
-			to discrete, to make X server driver able to add WB
-			entry later. This parameter disables that.
-
-	disable_mtrr_trim [X86, Intel and AMD only]
-			By default the kernel will trim any uncacheable
-			memory out of your available memory pool based on
-			MTRR settings.  This parameter disables that behavior,
-			possibly causing your machine to run very slowly.
-
-	disable_timer_pin_1 [X86]
-			Disable PIN 1 of APIC timer
-			Can be useful to work around chipset bugs.
-
-	dis_ucode_ldr	[X86] Disable the microcode loader.
-
-	dma_debug=off	If the kernel is compiled with DMA_API_DEBUG support,
-			this option disables the debugging code at boot.
-
-	dma_debug_entries=<number>
-			This option allows to tune the number of preallocated
-			entries for DMA-API debugging code. One entry is
-			required per DMA-API allocation. Use this if the
-			DMA-API debugging code disables itself because the
-			architectural default is too low.
-
-	dma_debug_driver=<driver_name>
-			With this option the DMA-API debugging driver
-			filter feature can be enabled at boot time. Just
-			pass the driver to filter for as the parameter.
-			The filter can be disabled or changed to another
-			driver later using sysfs.
-
-	drm_kms_helper.edid_firmware=[<connector>:]<file>[,[<connector>:]<file>]
-			Broken monitors, graphic adapters, KVMs and EDIDless
-			panels may send no or incorrect EDID data sets.
-			This parameter allows to specify an EDID data sets
-			in the /lib/firmware directory that are used instead.
-			Generic built-in EDID data sets are used, if one of
-			edid/1024x768.bin, edid/1280x1024.bin,
-			edid/1680x1050.bin, or edid/1920x1080.bin is given
-			and no file with the same name exists. Details and
-			instructions how to build your own EDID data are
-			available in Documentation/EDID/HOWTO.txt. An EDID
-			data set will only be used for a particular connector,
-			if its name and a colon are prepended to the EDID
-			name. Each connector may use a unique EDID data
-			set by separating the files with a comma.  An EDID
-			data set with no connector name will be used for
-			any connectors not explicitly specified.
-
-	dscc4.setup=	[NET]
-
-	dyndbg[="val"]		[KNL,DYNAMIC_DEBUG]
-	module.dyndbg[="val"]
-			Enable debug messages at boot time.  See
-			Documentation/dynamic-debug-howto.txt for details.
-
-	nompx		[X86] Disables Intel Memory Protection Extensions.
-			See Documentation/x86/intel_mpx.txt for more
-			information about the feature.
-
-	nopku		[X86] Disable Memory Protection Keys CPU feature found
-			in some Intel CPUs.
-
-	eagerfpu=	[X86]
-			on	enable eager fpu restore
-			off	disable eager fpu restore
-			auto	selects the default scheme, which automatically
-				enables eagerfpu restore for xsaveopt.
-
-	module.async_probe [KNL]
-			Enable asynchronous probe on this module.
-
-	early_ioremap_debug [KNL]
-			Enable debug messages in early_ioremap support. This
-			is useful for tracking down temporary early mappings
-			which are not unmapped.
-
-	earlycon=	[KNL] Output early console device and options.
-
-			When used with no options, the early console is
-			determined by the stdout-path property in device
-			tree's chosen node.
-
-		cdns,<addr>[,options]
-			Start an early, polled-mode console on a Cadence
-			(xuartps) serial port at the specified address. Only
-			supported option is baud rate. If baud rate is not
-			specified, the serial port must already be setup and
-			configured.
-
-		uart[8250],io,<addr>[,options]
-		uart[8250],mmio,<addr>[,options]
-		uart[8250],mmio32,<addr>[,options]
-		uart[8250],mmio32be,<addr>[,options]
-		uart[8250],0x<addr>[,options]
-			Start an early, polled-mode console on the 8250/16550
-			UART at the specified I/O port or MMIO address.
-			MMIO inter-register address stride is either 8-bit
-			(mmio) or 32-bit (mmio32 or mmio32be).
-			If none of [io|mmio|mmio32|mmio32be], <addr> is assumed
-			to be equivalent to 'mmio'. 'options' are specified
-			in the same format described for "console=ttyS<n>"; if
-			unspecified, the h/w is not initialized.
-
-		pl011,<addr>
-		pl011,mmio32,<addr>
-			Start an early, polled-mode console on a pl011 serial
-			port at the specified address. The pl011 serial port
-			must already be setup and configured. Options are not
-			yet supported.  If 'mmio32' is specified, then only
-			the driver will use only 32-bit accessors to read/write
-			the device registers.
-
-		meson,<addr>
-			Start an early, polled-mode console on a meson serial
-			port at the specified address. The serial port must
-			already be setup and configured. Options are not yet
-			supported.
-
-		msm_serial,<addr>
-			Start an early, polled-mode console on an msm serial
-			port at the specified address. The serial port
-			must already be setup and configured. Options are not
-			yet supported.
-
-		msm_serial_dm,<addr>
-			Start an early, polled-mode console on an msm serial
-			dm port at the specified address. The serial port
-			must already be setup and configured. Options are not
-			yet supported.
-
-		smh	Use ARM semihosting calls for early console.
-
-		s3c2410,<addr>
-		s3c2412,<addr>
-		s3c2440,<addr>
-		s3c6400,<addr>
-		s5pv210,<addr>
-		exynos4210,<addr>
-			Use early console provided by serial driver available
-			on Samsung SoCs, requires selecting proper type and
-			a correct base address of the selected UART port. The
-			serial port must already be setup and configured.
-			Options are not yet supported.
-
-		lpuart,<addr>
-		lpuart32,<addr>
-			Use early console provided by Freescale LP UART driver
-			found on Freescale Vybrid and QorIQ LS1021A processors.
-			A valid base address must be provided, and the serial
-			port must already be setup and configured.
-
-		armada3700_uart,<addr>
-			Start an early, polled-mode console on the
-			Armada 3700 serial port at the specified
-			address. The serial port must already be setup
-			and configured. Options are not yet supported.
-
-	earlyprintk=	[X86,SH,BLACKFIN,ARM,M68k]
-			earlyprintk=vga
-			earlyprintk=efi
-			earlyprintk=xen
-			earlyprintk=serial[,ttySn[,baudrate]]
-			earlyprintk=serial[,0x...[,baudrate]]
-			earlyprintk=ttySn[,baudrate]
-			earlyprintk=dbgp[debugController#]
-			earlyprintk=pciserial,bus:device.function[,baudrate]
-
-			earlyprintk is useful when the kernel crashes before
-			the normal console is initialized. It is not enabled by
-			default because it has some cosmetic problems.
-
-			Append ",keep" to not disable it when the real console
-			takes over.
-
-			Only one of vga, efi, serial, or usb debug port can
-			be used at a time.
-
-			Currently only ttyS0 and ttyS1 may be specified by
-			name.  Other I/O ports may be explicitly specified
-			on some architectures (x86 and arm at least) by
-			replacing ttySn with an I/O port address, like this:
-				earlyprintk=serial,0x1008,115200
-			You can find the port for a given device in
-			/proc/tty/driver/serial:
-				2: uart:ST16650V2 port:00001008 irq:18 ...
-
-			Interaction with the standard serial driver is not
-			very good.
-
-			The VGA and EFI output is eventually overwritten by
-			the real console.
-
-			The xen output can only be used by Xen PV guests.
-
-	edac_report=	[HW,EDAC] Control how to report EDAC event
-			Format: {"on" | "off" | "force"}
-			on: enable EDAC to report H/W event. May be overridden
-			by other higher priority error reporting module.
-			off: disable H/W event reporting through EDAC.
-			force: enforce the use of EDAC to report H/W event.
-			default: on.
-
-	ekgdboc=	[X86,KGDB] Allow early kernel console debugging
-			ekgdboc=kbd
-
-			This is designed to be used in conjunction with
-			the boot argument: earlyprintk=vga
-
-	edd=		[EDD]
-			Format: {"off" | "on" | "skip[mbr]"}
-
-	efi=		[EFI]
-			Format: { "old_map", "nochunk", "noruntime", "debug" }
-			old_map [X86-64]: switch to the old ioremap-based EFI
-			runtime services mapping. 32-bit still uses this one by
-			default.
-			nochunk: disable reading files in "chunks" in the EFI
-			boot stub, as chunking can cause problems with some
-			firmware implementations.
-			noruntime : disable EFI runtime services support
-			debug: enable misc debug output
-
-	efi_no_storage_paranoia [EFI; X86]
-			Using this parameter you can use more than 50% of
-			your efi variable storage. Use this parameter only if
-			you are really sure that your UEFI does sane gc and
-			fulfills the spec otherwise your board may brick.
-
-	efi_fake_mem=	nn[KMG]@ss[KMG]:aa[,nn[KMG]@ss[KMG]:aa,..] [EFI; X86]
-			Add arbitrary attribute to specific memory range by
-			updating original EFI memory map.
-			Region of memory which aa attribute is added to is
-			from ss to ss+nn.
-			If efi_fake_mem=2G@4G:0x10000,2G@0x10a0000000:0x10000
-			is specified, EFI_MEMORY_MORE_RELIABLE(0x10000)
-			attribute is added to range 0x100000000-0x180000000 and
-			0x10a0000000-0x1120000000.
-
-			Using this parameter you can do debugging of EFI memmap
-			related feature. For example, you can do debugging of
-			Address Range Mirroring feature even if your box
-			doesn't support it.
-
-	efivar_ssdt=	[EFI; X86] Name of an EFI variable that contains an SSDT
-			that is to be dynamically loaded by Linux. If there are
-			multiple variables with the same name but with different
-			vendor GUIDs, all of them will be loaded. See
-			Documentation/acpi/ssdt-overlays.txt for details.
-
-
-	eisa_irq_edge=	[PARISC,HW]
-			See header of drivers/parisc/eisa.c.
-
-	elanfreq=	[X86-32]
-			See comment before function elanfreq_setup() in
-			arch/x86/kernel/cpu/cpufreq/elanfreq.c.
-
-	elevator=	[IOSCHED]
-			Format: {"cfq" | "deadline" | "noop"}
-			See Documentation/block/cfq-iosched.txt and
-			Documentation/block/deadline-iosched.txt for details.
-
-	elfcorehdr=[size[KMG]@]offset[KMG] [IA64,PPC,SH,X86,S390]
-			Specifies physical address of start of kernel core
-			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]
-			The kernel tries to adjust MTRR layout from continuous
-			to discrete, to make X server driver able to add WB
-			entry later. This parameter enables that.
-
-	enable_timer_pin_1 [X86]
-			Enable PIN 1 of APIC timer
-			Can be useful to work around chipset bugs
-			(in particular on some ATI chipsets).
-			The kernel tries to set a reasonable default.
-
-	enforcing	[SELINUX] Set initial enforcing status.
-			Format: {"0" | "1"}
-			See security/selinux/Kconfig help text.
-			0 -- permissive (log only, no denials).
-			1 -- enforcing (deny and log).
-			Default value is 0.
-			Value can be changed at runtime via /selinux/enforce.
-
-	erst_disable	[ACPI]
-			Disable Error Record Serialization Table (ERST)
-			support.
-
-	ether=		[HW,NET] Ethernet cards parameters
-			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/.
-
-	floppy=		[HW]
-			See Documentation/blockdev/floppy.txt.
-
-	force_pal_cache_flush
-			[IA-64] Avoid check_sal_cache_flush which may hang on
-			buggy SAL_CACHE_FLUSH implementations. Using this
-			parameter will force ia64_sal_cache_flush to call
-			ia64_pal_cache_flush instead of SAL_CACHE_FLUSH.
-
-	forcepae [X86-32]
-			Forcefully enable Physical Address Extension (PAE).
-			Many Pentium M systems disable PAE but may have a
-			functionally usable PAE implementation.
-			Warning: use of this parameter will taint the kernel
-			and may cause unknown problems.
-
-	ftrace=[tracer]
-			[FTRACE] will set and start the specified tracer
-			as early as possible in order to facilitate early
-			boot debugging.
-
-	ftrace_dump_on_oops[=orig_cpu]
-			[FTRACE] will dump the trace buffers on oops.
-			If no parameter is passed, ftrace will dump
-			buffers of all CPUs, but if you pass orig_cpu, it will
-			dump only the buffer of the CPU that triggered the
-			oops.
-
-	ftrace_filter=[function-list]
-			[FTRACE] Limit the functions traced by the function
-			tracer at boot up. function-list is a comma separated
-			list of functions. This list can be changed at run
-			time by the set_ftrace_filter file in the debugfs
-			tracing directory.
-
-	ftrace_notrace=[function-list]
-			[FTRACE] Do not trace the functions specified in
-			function-list. This list can be changed at run time
-			by the set_ftrace_notrace file in the debugfs
-			tracing directory.
-
-	ftrace_graph_filter=[function-list]
-			[FTRACE] Limit the top level callers functions traced
-			by the function graph tracer at boot up.
-			function-list is a comma separated list of functions
-			that can be changed at run time by the
-			set_graph_function file in the debugfs tracing directory.
-
-	ftrace_graph_notrace=[function-list]
-			[FTRACE] Do not trace from the functions specified in
-			function-list.  This list is a comma separated list of
-			functions that can be changed at run time by the
-			set_graph_notrace file in the debugfs tracing directory.
-
-	gamecon.map[2|3]=
-			[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
-			support via parallel port (up to 5 devices per port)
-			Format: <port#>,<pad1>,<pad2>,<pad3>,<pad4>,<pad5>
-			See also Documentation/input/joystick-parport.txt
-
-	gamma=		[HW,DRM]
-
-	gart_fix_e820=  [X86_64] disable the fix e820 for K8 GART
-			Format: off | on
-			default: on
-
-	gcov_persist=	[GCOV] When non-zero (default), profiling data for
-			kernel modules is saved and remains accessible via
-			debugfs, even when the module is unloaded/reloaded.
-			When zero, profiling data is discarded and associated
-			debugfs files are removed at module unload time.
-
-	gpt		[EFI] Forces disk with valid GPT signature but
-			invalid Protective MBR to be treated as GPT. If the
-			primary GPT is corrupted, it enables the backup/alternate
-			GPT to be used instead.
-
-	grcan.enable0=	[HW] Configuration of physical interface 0. Determines
-			the "Enable 0" bit of the configuration register.
-			Format: 0 | 1
-			Default: 0
-	grcan.enable1=	[HW] Configuration of physical interface 1. Determines
-			the "Enable 0" bit of the configuration register.
-			Format: 0 | 1
-			Default: 0
-	grcan.select=	[HW] Select which physical interface to use.
-			Format: 0 | 1
-			Default: 0
-	grcan.txsize=	[HW] Sets the size of the tx buffer.
-			Format: <unsigned int> such that (txsize & ~0x1fffc0) == 0.
-			Default: 1024
-	grcan.rxsize=	[HW] Sets the size of the rx buffer.
-			Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
-			Default: 1024
-
-	gpio-mockup.gpio_mockup_ranges
-			[HW] Sets the ranges of gpiochip of for this device.
-			Format: <start1>,<end1>,<start2>,<end2>...
-
-	hardlockup_all_cpu_backtrace=
-			[KNL] Should the hard-lockup detector generate
-			backtraces on all cpus.
-			Format: <integer>
-
-	hashdist=	[KNL,NUMA] Large hashes allocated during boot
-			are distributed across NUMA nodes.  Defaults on
-			for 64-bit NUMA, off otherwise.
-			Format: 0 | 1 (for off | on)
-
-	hcl=		[IA-64] SGI's Hardware Graph compatibility layer
-
-	hd=		[EIDE] (E)IDE hard drive subsystem geometry
-			Format: <cyl>,<head>,<sect>
-
-	hest_disable	[ACPI]
-			Disable Hardware Error Source Table (HEST) support;
-			corresponding firmware-first mode error processing
-			logic will be disabled.
-
-	highmem=nn[KMG]	[KNL,BOOT] forces the highmem zone to have an exact
-			size of <nn>. This works even on boxes that have no
-			highmem otherwise. This also works to reduce highmem
-			size on bigger boxes.
-
-	highres=	[KNL] Enable/disable high resolution timer mode.
-			Valid parameters: "on", "off"
-			Default: "on"
-
-	hisax=		[HW,ISDN]
-			See Documentation/isdn/README.HiSax.
-
-	hlt		[BUGS=ARM,SH]
-
-	hpet=		[X86-32,HPET] option to control HPET usage
-			Format: { enable (default) | disable | force |
-				verbose }
-			disable: disable HPET and use PIT instead
-			force: allow force enabled of undocumented chips (ICH4,
-				VIA, nVidia)
-			verbose: show contents of HPET registers during setup
-
-	hpet_mmap=	[X86, HPET_MMAP] Allow userspace to mmap HPET
-			registers.  Default set by CONFIG_HPET_MMAP_DEFAULT.
-
-	hugepages=	[HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
-	hugepagesz=	[HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
-			On x86-64 and powerpc, this option can be specified
-			multiple times interleaved with hugepages= to reserve
-			huge pages of different sizes. Valid pages sizes on
-			x86-64 are 2M (when the CPU supports "pse") and 1G
-			(when the CPU supports the "pdpe1gb" cpuinfo flag).
-
-	hvc_iucv=	[S390] Number of z/VM IUCV hypervisor console (HVC)
-			       terminal devices. Valid values: 0..8
-	hvc_iucv_allow=	[S390] Comma-separated list of z/VM user IDs.
-			       If specified, z/VM IUCV HVC accepts connections
-			       from listed z/VM user IDs only.
-
-	hwthread_map=	[METAG] Comma-separated list of Linux cpu id to
-			        hardware thread id mappings.
-				Format: <cpu>:<hwthread>
-
-	keep_bootcon	[KNL]
-			Do not unregister boot console at start. This is only
-			useful for debugging when something happens in the window
-			between unregistering the boot console and initializing
-			the real console.
-
-	i2c_bus=	[HW] Override the default board specific I2C bus speed
-			     or register an additional I2C bus that is not
-			     registered from board initialization code.
-			     Format:
-			     <bus_id>,<clkrate>
-
-	i8042.debug	[HW] Toggle i8042 debug mode
-	i8042.unmask_kbd_data
-			[HW] Enable printing of interrupt data from the KBD port
-			     (disabled by default, and as a pre-condition
-			     requires that i8042.debug=1 be enabled)
-	i8042.direct	[HW] Put keyboard port into non-translated mode
-	i8042.dumbkbd	[HW] Pretend that controller can only read data from
-			     keyboard and cannot control its state
-			     (Don't attempt to blink the leds)
-	i8042.noaux	[HW] Don't check for auxiliary (== mouse) port
-	i8042.nokbd	[HW] Don't check/create keyboard port
-	i8042.noloop	[HW] Disable the AUX Loopback command while probing
-			     for the AUX port
-	i8042.nomux	[HW] Don't check presence of an active multiplexing
-			     controller
-	i8042.nopnp	[HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
-			     controllers
-	i8042.notimeout	[HW] Ignore timeout condition signalled by controller
-	i8042.reset	[HW] Reset the controller during init, cleanup and
-			     suspend-to-ram transitions, only during s2r
-			     transitions, or never reset
-			Format: { 1 | Y | y | 0 | N | n }
-			1, Y, y: always reset controller
-			0, N, n: don't ever reset controller
-			Default: only on s2r transitions on x86; most other
-			architectures force reset to be always executed
-	i8042.unlock	[HW] Unlock (ignore) the keylock
-	i8042.kbdreset  [HW] Reset device connected to KBD port
-
-	i810=		[HW,DRM]
-
-	i8k.ignore_dmi	[HW] Continue probing hardware even if DMI data
-			indicates that the driver is running on unsupported
-			hardware.
-	i8k.force	[HW] Activate i8k driver even if SMM BIOS signature
-			does not match list of supported models.
-	i8k.power_status
-			[HW] Report power status in /proc/i8k
-			(disabled by default)
-	i8k.restricted	[HW] Allow controlling fans only if SYS_ADMIN
-			capability is set.
-
-	i915.invert_brightness=
-			[DRM] Invert the sense of the variable that is used to
-			set the brightness of the panel backlight. Normally a
-			brightness value of 0 indicates backlight switched off,
-			and the maximum of the brightness value sets the backlight
-			to maximum brightness. If this parameter is set to 0
-			(default) and the machine requires it, or this parameter
-			is set to 1, a brightness value of 0 sets the backlight
-			to maximum brightness, and the maximum of the brightness
-			value switches the backlight off.
-			-1 -- never invert brightness
-			 0 -- machine default
-			 1 -- force brightness inversion
-
-	icn=		[HW,ISDN]
-			Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]]
-
-	ide-core.nodma=	[HW] (E)IDE subsystem
-			Format: =0.0 to prevent dma on hda, =0.1 hdb =1.0 hdc
-			.vlb_clock .pci_clock .noflush .nohpa .noprobe .nowerr
-			.cdrom .chs .ignore_cable are additional options
-			See Documentation/ide/ide.txt.
-
-	ide-generic.probe-mask= [HW] (E)IDE subsystem
-			Format: <int>
-			Probe mask for legacy ISA IDE ports.  Depending on
-			platform up to 6 ports are supported, enabled by
-			setting corresponding bits in the mask to 1.  The
-			default value is 0x0, which has a special meaning.
-			On systems that have PCI, it triggers scanning the
-			PCI bus for the first and the second port, which
-			are then probed.  On systems without PCI the value
-			of 0x0 enables probing the two first ports as if it
-			was 0x3.
-
-	ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
-			Claim all unknown PCI IDE storage controllers.
-
-	idle=		[X86]
-			Format: idle=poll, idle=halt, idle=nomwait
-			Poll forces a polling idle loop that can slightly
-			improve the performance of waking up a idle CPU, but
-			will use a lot of power and make the system run hot.
-			Not recommended.
-			idle=halt: Halt is forced to be used for CPU idle.
-			In such case C2/C3 won't be used again.
-			idle=nomwait: Disable mwait for CPU C-states
-
-	ieee754=	[MIPS] Select IEEE Std 754 conformance mode
-			Format: { strict | legacy | 2008 | relaxed }
-			Default: strict
-
-			Choose which programs will be accepted for execution
-			based on the IEEE 754 NaN encoding(s) supported by
-			the FPU and the NaN encoding requested with the value
-			of an ELF file header flag individually set by each
-			binary.  Hardware implementations are permitted to
-			support either or both of the legacy and the 2008 NaN
-			encoding mode.
-
-			Available settings are as follows:
-			strict	accept binaries that request a NaN encoding
-				supported by the FPU
-			legacy	only accept legacy-NaN binaries, if supported
-				by the FPU
-			2008	only accept 2008-NaN binaries, if supported
-				by the FPU
-			relaxed	accept any binaries regardless of whether
-				supported by the FPU
-
-			The FPU emulator is always able to support both NaN
-			encodings, so if no FPU hardware is present or it has
-			been disabled with 'nofpu', then the settings of
-			'legacy' and '2008' strap the emulator accordingly,
-			'relaxed' straps the emulator for both legacy-NaN and
-			2008-NaN, whereas 'strict' enables legacy-NaN only on
-			legacy processors and both NaN encodings on MIPS32 or
-			MIPS64 CPUs.
-
-			The setting for ABS.fmt/NEG.fmt instruction execution
-			mode generally follows that for the NaN encoding,
-			except where unsupported by hardware.
-
-	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.
-
-	ignore_rlimit_data
-			Ignore RLIMIT_DATA setting for data mappings,
-			print warning at first misuse.  Can be changed via
-			/sys/module/kernel/parameters/ignore_rlimit_data.
-
-	ihash_entries=	[KNL]
-			Set number of hash buckets for inode cache.
-
-	ima_appraise=	[IMA] appraise integrity measurements
-			Format: { "off" | "enforce" | "fix" | "log" }
-			default: "enforce"
-
-	ima_appraise_tcb [IMA]
-			The builtin appraise policy appraises all files
-			owned by uid=0.
-
-	ima_hash=	[IMA]
-			Format: { md5 | sha1 | rmd160 | sha256 | sha384
-				   | sha512 | ... }
-			default: "sha1"
-
-			The list of supported hash algorithms is defined
-			in crypto/hash_info.h.
-
-	ima_policy=	[IMA]
-			The builtin measurement policy to load during IMA
-			setup.  Specyfing "tcb" as the value, measures all
-			programs exec'd, files mmap'd for exec, and all files
-			opened with the read mode bit set by either the
-			effective uid (euid=0) or uid=0.
-			Format: "tcb"
-
-	ima_tcb		[IMA] Deprecated.  Use ima_policy= instead.
-			Load a policy which meets the needs of the Trusted
-			Computing Base.  This means IMA will measure all
-			programs exec'd, files mmap'd for exec, and all files
-			opened for read by uid=0.
-
-	ima_template=   [IMA]
-			Select one of defined IMA measurements template formats.
-			Formats: { "ima" | "ima-ng" | "ima-sig" }
-			Default: "ima-ng"
-
-	ima_template_fmt=
-	                [IMA] Define a custom template format.
-			Format: { "field1|...|fieldN" }
-
-	ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
-			Format: <min_file_size>
-			Set the minimal file size for using asynchronous hash.
-			If left unspecified, ahash usage is disabled.
-
-			ahash performance varies for different data sizes on
-			different crypto accelerators. This option can be used
-			to achieve the best performance for a particular HW.
-
-	ima.ahash_bufsize= [IMA] Asynchronous hash buffer size
-			Format: <bufsize>
-			Set hashing buffer size. Default: 4k.
-
-			ahash performance varies for different chunk sizes on
-			different crypto accelerators. This option can be used
-			to achieve best performance for particular HW.
-
-	init=		[KNL]
-			Format: <full_path>
-			Run specified binary instead of /sbin/init as init
-			process.
-
-	initcall_debug	[KNL] Trace initcalls as they are executed.  Useful
-			for working out where the kernel is dying during
-			startup.
-
-	initcall_blacklist=  [KNL] Do not execute a comma-separated list of
-			initcall functions.  Useful for debugging built-in
-			modules and initcalls.
-
-	initrd=		[BOOT] Specify the location of the initial ramdisk
-
-	init_pkru=	[x86] Specify the default memory protection keys rights
-			register contents for all processes.  0x55555554 by
-			default (disallow access to all but pkey 0).  Can
-			override in debugfs after boot.
-
-	inport.irq=	[HW] Inport (ATI XL and Microsoft) busmouse driver
-			Format: <irq>
-
-	int_pln_enable  [x86] Enable power limit notification interrupt
-
-	integrity_audit=[IMA]
-			Format: { "0" | "1" }
-			0 -- basic integrity auditing messages. (Default)
-			1 -- additional integrity auditing messages.
-
-	intel_iommu=	[DMAR] Intel IOMMU driver (DMAR) option
-		on
-			Enable intel iommu driver.
-		off
-			Disable intel iommu driver.
-		igfx_off [Default Off]
-			By default, gfx is mapped as normal device. If a gfx
-			device has a dedicated DMAR unit, the DMAR unit is
-			bypassed by not enabling DMAR with this option. In
-			this case, gfx device will use physical address for
-			DMA.
-		forcedac [x86_64]
-			With this option iommu will not optimize to look
-			for io virtual address below 32-bit forcing dual
-			address cycle on pci bus for cards supporting greater
-			than 32-bit addressing. The default is to look
-			for translation below 32-bit and if not available
-			then look in the higher range.
-		strict [Default Off]
-			With this option on every unmap_single operation will
-			result in a hardware IOTLB flush operation as opposed
-			to batching them for performance.
-		sp_off [Default Off]
-			By default, super page will be supported if Intel IOMMU
-			has the capability. With this option, super page will
-			not be supported.
-		ecs_off [Default Off]
-			By default, extended context tables will be supported if
-			the hardware advertises that it has support both for the
-			extended tables themselves, and also PASID support. With
-			this option set, extended tables will not be used even
-			on hardware which claims to support them.
-
-	intel_idle.max_cstate=	[KNL,HW,ACPI,X86]
-			0	disables intel_idle and fall back on acpi_idle.
-			1 to 9	specify maximum depth of C-state.
-
-	intel_pstate=  [X86]
-		       disable
-		         Do not enable intel_pstate as the default
-		         scaling driver for the supported processors
-		       force
-			 Enable intel_pstate on systems that prohibit it by default
-			 in favor of acpi-cpufreq. Forcing the intel_pstate driver
-			 instead of acpi-cpufreq may disable platform features, such
-			 as thermal controls and power capping, that rely on ACPI
-			 P-States information being indicated to OSPM and therefore
-			 should be used with caution. This option does not work with
-			 processors that aren't supported by the intel_pstate driver
-			 or on platforms that use pcc-cpufreq instead of acpi-cpufreq.
-		       no_hwp
-		         Do not enable hardware P state control (HWP)
-			 if available.
-		hwp_only
-			Only load intel_pstate on systems which support
-			hardware P state control (HWP) if available.
-		support_acpi_ppc
-			Enforce ACPI _PPC performance limits. If the Fixed ACPI
-			Description Table, specifies preferred power management
-			profile as "Enterprise Server" or "Performance Server",
-			then this feature is turned on by default.
-
-	intremap=	[X86-64, Intel-IOMMU]
-			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
-			nopost	disable Interrupt Posting
-
-	iomem=		Disable strict checking of access to MMIO memory
-		strict	regions from userspace.
-		relaxed
-
-	iommu=		[x86]
-		off
-		force
-		noforce
-		biomerge
-		panic
-		nopanic
-		merge
-		nomerge
-		forcesac
-		soft
-		pt		[x86, IA-64]
-		nobypass	[PPC/POWERNV]
-			Disable IOMMU bypass, using IOMMU for PCI devices.
-
-
-	io7=		[HW] IO7 for Marvel based alpha systems
-			See comment before marvel_specify_io7 in
-			arch/alpha/kernel/core_marvel.c.
-
-	io_delay=	[X86] I/O delay method
-		0x80
-			Standard port 0x80 based delay
-		0xed
-			Alternate port 0xed based delay (needed on some systems)
-		udelay
-			Simple two microseconds delay
-		none
-			No delay
-
-	ip=		[IP_PNP]
-			See Documentation/filesystems/nfs/nfsroot.txt.
-
-	irqaffinity=	[SMP] Set the default irq affinity mask
-			The argument is a cpu list, as described above.
-
-	irqfixup	[HW]
-			When an interrupt is not handled search all handlers
-			for it. Intended to get systems with badly broken
-			firmware running.
-
-	irqpoll		[HW]
-			When an interrupt is not handled search all handlers
-			for it. Also check all handlers each timer
-			interrupt. Intended to get systems with badly broken
-			firmware running.
-
-	isapnp=		[ISAPNP]
-			Format: <RDP>,<reset>,<pci_scan>,<verbosity>
-
-	isolcpus=	[KNL,SMP] Isolate CPUs from the general scheduler.
-			The argument is a cpu list, as described above.
-
-			This option can be used to specify one or more CPUs
-			to isolate from the general SMP balancing and scheduling
-			algorithms. You can move a process onto or off an
-			"isolated" CPU via the CPU affinity syscalls or cpuset.
-			<cpu number> begins at 0 and the maximum value is
-			"number of CPUs in system - 1".
-
-			This option is the preferred way to isolate CPUs. The
-			alternative -- manually setting the CPU mask of all
-			tasks in the system -- can cause problems and
-			suboptimal load balancer performance.
-
-	iucv=		[HW,NET]
-
-	ivrs_ioapic	[HW,X86_64]
-			Provide an override to the IOAPIC-ID<->DEVICE-ID
-			mapping provided in the IVRS ACPI table. For
-			example, to map IOAPIC-ID decimal 10 to
-			PCI device 00:14.0 write the parameter as:
-				ivrs_ioapic[10]=00:14.0
-
-	ivrs_hpet	[HW,X86_64]
-			Provide an override to the HPET-ID<->DEVICE-ID
-			mapping provided in the IVRS ACPI table. For
-			example, to map HPET-ID decimal 0 to
-			PCI device 00:14.0 write the parameter as:
-				ivrs_hpet[0]=00:14.0
-
-	ivrs_acpihid	[HW,X86_64]
-			Provide an override to the ACPI-HID:UID<->DEVICE-ID
-			mapping provided in the IVRS ACPI table. For
-			example, to map UART-HID:UID AMD0020:0 to
-			PCI device 00:14.5 write the parameter as:
-				ivrs_acpihid[00:14.5]=AMD0020:0
-
-	js=		[HW,JOY] Analog joystick
-			See Documentation/input/joystick.txt.
-
-	nokaslr		[KNL]
-			When CONFIG_RANDOMIZE_BASE is set, this disables
-			kernel and module base offset ASLR (Address Space
-			Layout Randomization).
-
-	keepinitrd	[HW,ARM]
-
-	kernelcore=	[KNL,X86,IA-64,PPC]
-			Format: nn[KMGTPE] | "mirror"
-			This parameter
-			specifies the amount of memory usable by the kernel
-			for non-movable allocations.  The requested amount is
-			spread evenly throughout all nodes in the system. The
-			remaining memory in each node is used for Movable
-			pages. In the event, a node is too small to have both
-			kernelcore and Movable pages, kernelcore pages will
-			take priority and other nodes will have a larger number
-			of Movable pages.  The Movable zone is used for the
-			allocation of pages that may be reclaimed or moved
-			by the page migration subsystem.  This means that
-			HugeTLB pages may not be allocated from this zone.
-			Note that allocations like PTEs-from-HighMem still
-			use the HighMem zone if it exists, and the Normal
-			zone if it does not.
-
-			Instead of specifying the amount of memory (nn[KMGTPE]),
-			you can specify "mirror" option. In case "mirror"
-			option is specified, mirrored (reliable) memory is used
-			for non-movable allocations and remaining memory is used
-			for Movable pages. nn[KMGTPE] and "mirror" are exclusive,
-			so you can NOT specify nn[KMGTPE] and "mirror" at the same
-			time.
-
-	kgdbdbgp=	[KGDB,HW] kgdb over EHCI usb debug port.
-			Format: <Controller#>[,poll interval]
-			The controller # is the number of the ehci usb debug
-			port as it is probed via PCI.  The poll interval is
-			optional and is the number seconds in between
-			each poll cycle to the debug port in case you need
-			the functionality for interrupting the kernel with
-			gdb or control-c on the dbgp connection.  When
-			not using this parameter you use sysrq-g to break into
-			the kernel debugger.
-
-	kgdboc=		[KGDB,HW] kgdb over consoles.
-			Requires a tty driver that supports console polling,
-			or a supported polling keyboard driver (non-usb).
-			 Serial only format: <serial_device>[,baud]
-			 keyboard only format: kbd
-			 keyboard and serial format: kbd,<serial_device>[,baud]
-			Optional Kernel mode setting:
-			 kms, kbd format: kms,kbd
-			 kms, kbd and serial format: kms,kbd,<ser_dev>[,baud]
-
-	kgdbwait	[KGDB] Stop kernel execution and enter the
-			kernel debugger at the earliest opportunity.
-
-	kmac=		[MIPS] korina ethernet MAC address.
-			Configure the RouterBoard 532 series on-chip
-			Ethernet adapter MAC address.
-
-	kmemleak=	[KNL] Boot-time kmemleak enable/disable
-			Valid arguments: on, off
-			Default: on
-			Built with CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y,
-			the default is off.
-
-	kmemcheck=	[X86] Boot-time kmemcheck enable/disable/one-shot mode
-			Valid arguments: 0, 1, 2
-			kmemcheck=0 (disabled)
-			kmemcheck=1 (enabled)
-			kmemcheck=2 (one-shot mode)
-			Default: 2 (one-shot mode)
-
-	kstack=N	[X86] Print N words from the kernel stack
-			in oops dumps.
-
-	kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
-			Default is 0 (don't ignore, but inject #GP)
-
-	kvm.mmu_audit=	[KVM] This is a R/W parameter which allows audit
-			KVM MMU at runtime.
-			Default is 0 (off)
-
-	kvm-amd.nested=	[KVM,AMD] Allow nested virtualization in KVM/SVM.
-			Default is 1 (enabled)
-
-	kvm-amd.npt=	[KVM,AMD] Disable nested paging (virtualized MMU)
-			for all guests.
-			Default is 1 (enabled) if in 64-bit or 32-bit PAE mode.
-
-	kvm-intel.ept=	[KVM,Intel] Disable extended page tables
-			(virtualized MMU) support on capable Intel chips.
-			Default is 1 (enabled)
-
-	kvm-intel.emulate_invalid_guest_state=
-			[KVM,Intel] Enable emulation of invalid guest states
-			Default is 0 (disabled)
-
-	kvm-intel.flexpriority=
-			[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
-			Intel chips. Default is 1 (enabled)
-
-	kvm-intel.vpid=	[KVM,Intel] Disable Virtual Processor Identification
-			feature (tagged TLBs) on capable Intel chips.
-			Default is 1 (enabled)
-
-	l2cr=		[PPC]
-
-	l3cr=		[PPC]
-
-	lapic		[X86-32,APIC] Enable the local APIC even if BIOS
-			disabled it.
-
-	lapic=		[x86,APIC] "notscdeadline" Do not use TSC deadline
-			value for LAPIC timer one-shot implementation. Default
-			back to the programmable timer unit in the LAPIC.
-
-	lapic_timer_c2_ok	[X86,APIC] trust the local apic timer
-			in C2 power state.
-
-	libata.dma=	[LIBATA] DMA control
-			libata.dma=0	  Disable all PATA and SATA DMA
-			libata.dma=1	  PATA and SATA Disk DMA only
-			libata.dma=2	  ATAPI (CDROM) DMA only
-			libata.dma=4	  Compact Flash DMA only
-			Combinations also work, so libata.dma=3 enables DMA
-			for disks and CDROMs, but not CFs.
-
-	libata.ignore_hpa=	[LIBATA] Ignore HPA limit
-			libata.ignore_hpa=0	  keep BIOS limits (default)
-			libata.ignore_hpa=1	  ignore limits, using full disk
-
-	libata.noacpi	[LIBATA] Disables use of ACPI in libata suspend/resume
-			when set.
-			Format: <int>
-
-	libata.force=	[LIBATA] Force configurations.  The format is comma
-			separated list of "[ID:]VAL" where ID is
-			PORT[.DEVICE].  PORT and DEVICE are decimal numbers
-			matching port, link or device.  Basically, it matches
-			the ATA ID string printed on console by libata.  If
-			the whole ID part is omitted, the last PORT and DEVICE
-			values are used.  If ID hasn't been specified yet, the
-			configuration applies to all ports, links and devices.
-
-			If only DEVICE is omitted, the parameter applies to
-			the port and all links and devices behind it.  DEVICE
-			number of 0 either selects the first device or the
-			first fan-out link behind PMP device.  It does not
-			select the host link.  DEVICE number of 15 selects the
-			host link and device attached to it.
-
-			The VAL specifies the configuration to force.  As long
-			as there's no ambiguity shortcut notation is allowed.
-			For example, both 1.5 and 1.5G would work for 1.5Gbps.
-			The following configurations can be forced.
-
-			* Cable type: 40c, 80c, short40c, unk, ign or sata.
-			  Any ID with matching PORT is used.
-
-			* SATA link speed limit: 1.5Gbps or 3.0Gbps.
-
-			* Transfer mode: pio[0-7], mwdma[0-4] and udma[0-7].
-			  udma[/][16,25,33,44,66,100,133] notation is also
-			  allowed.
-
-			* [no]ncq: Turn on or off NCQ.
-
-			* [no]ncqtrim: Turn off queued DSM TRIM.
-
-			* nohrst, nosrst, norst: suppress hard, soft
-                          and both resets.
-
-			* rstonce: only attempt one reset during
-			  hot-unplug link recovery
-
-			* dump_id: dump IDENTIFY data.
-
-			* atapi_dmadir: Enable ATAPI DMADIR bridge support
-
-			* disable: Disable this device.
-
-			If there are multiple matching configurations changing
-			the same attribute, the last one is used.
-
-	memblock=debug	[KNL] Enable memblock debug messages.
-
-	load_ramdisk=	[RAM] List of ramdisks to load from floppy
-			See Documentation/blockdev/ramdisk.txt.
-
-	lockd.nlm_grace_period=P  [NFS] Assign grace period.
-			Format: <integer>
-
-	lockd.nlm_tcpport=N	[NFS] Assign TCP port.
-			Format: <integer>
-
-	lockd.nlm_timeout=T	[NFS] Assign timeout value.
-			Format: <integer>
-
-	lockd.nlm_udpport=M	[NFS] Assign UDP port.
-			Format: <integer>
-
-	locktorture.nreaders_stress= [KNL]
-			Set the number of locking read-acquisition kthreads.
-			Defaults to being automatically set based on the
-			number of online CPUs.
-
-	locktorture.nwriters_stress= [KNL]
-			Set the number of locking write-acquisition kthreads.
-
-	locktorture.onoff_holdoff= [KNL]
-			Set time (s) after boot for CPU-hotplug testing.
-
-	locktorture.onoff_interval= [KNL]
-			Set time (s) between CPU-hotplug operations, or
-			zero to disable CPU-hotplug testing.
-
-	locktorture.shuffle_interval= [KNL]
-			Set task-shuffle interval (jiffies).  Shuffling
-			tasks allows some CPUs to go into dyntick-idle
-			mode during the locktorture test.
-
-	locktorture.shutdown_secs= [KNL]
-			Set time (s) after boot system shutdown.  This
-			is useful for hands-off automated testing.
-
-	locktorture.stat_interval= [KNL]
-			Time (s) between statistics printk()s.
-
-	locktorture.stutter= [KNL]
-			Time (s) to stutter testing, for example,
-			specifying five seconds causes the test to run for
-			five seconds, wait for five seconds, and so on.
-			This tests the locking primitive's ability to
-			transition abruptly to and from idle.
-
-	locktorture.torture_runnable= [BOOT]
-			Start locktorture running at boot time.
-
-	locktorture.torture_type= [KNL]
-			Specify the locking implementation to test.
-
-	locktorture.verbose= [KNL]
-			Enable additional printk() statements.
-
-	logibm.irq=	[HW,MOUSE] Logitech Bus Mouse Driver
-			Format: <irq>
-
-	loglevel=	All Kernel Messages with a loglevel smaller than the
-			console loglevel will be printed to the console. It can
-			also be changed with klogd or other programs. The
-			loglevels are defined as follows:
-
-			0 (KERN_EMERG)		system is unusable
-			1 (KERN_ALERT)		action must be taken immediately
-			2 (KERN_CRIT)		critical conditions
-			3 (KERN_ERR)		error conditions
-			4 (KERN_WARNING)	warning conditions
-			5 (KERN_NOTICE)		normal but significant condition
-			6 (KERN_INFO)		informational
-			7 (KERN_DEBUG)		debug-level messages
-
-	log_buf_len=n[KMG]	Sets the size of the printk ring buffer,
-			in bytes.  n must be a power of two and greater
-			than the minimal size. The minimal size is defined
-			by LOG_BUF_SHIFT kernel config parameter. There is
-			also CONFIG_LOG_CPU_MAX_BUF_SHIFT config parameter
-			that allows to increase the default size depending on
-			the number of CPUs. See init/Kconfig for more details.
-
-	logo.nologo	[FB] Disables display of the built-in Linux logo.
-			This may be used to provide more screen space for
-			kernel log messages and is useful when debugging
-			kernel boot problems.
-
-	lp=0		[LP]	Specify parallel ports to use, e.g,
-	lp=port[,port...]	lp=none,parport0 (lp0 not configured, lp1 uses
-	lp=reset		first parallel port). 'lp=0' disables the
-	lp=auto			printer driver. 'lp=reset' (which can be
-				specified in addition to the ports) causes
-				attached printers to be reset. Using
-				lp=port1,port2,... specifies the parallel ports
-				to associate lp devices with, starting with
-				lp0. A port specification may be 'none' to skip
-				that lp device, or a parport name such as
-				'parport0'. Specifying 'lp=auto' instead of a
-				port specification list means that device IDs
-				from each port should be examined, to see if
-				an IEEE 1284-compliant printer is attached; if
-				so, the driver will manage that printer.
-				See also header of drivers/char/lp.c.
-
-	lpj=n		[KNL]
-			Sets loops_per_jiffy to given constant, thus avoiding
-			time-consuming boot-time autodetection (up to 250 ms per
-			CPU). 0 enables autodetection (default). To determine
-			the correct value for your kernel, boot with normal
-			autodetection and see what value is printed. Note that
-			on SMP systems the preset will be applied to all CPUs,
-			which is likely to cause problems if your CPUs need
-			significantly divergent settings. An incorrect value
-			will cause delays in the kernel to be wrong, leading to
-			unpredictable I/O errors and other breakage. Although
-			unlikely, in the extreme case this might damage your
-			hardware.
-
-	ltpc=		[NET]
-			Format: <io>,<irq>,<dma>
-
-	machvec=	[IA-64] Force the use of a particular machine-vector
-			(machvec) in a generic kernel.
-			Example: machvec=hpzx1_swiotlb
-
-	machtype=	[Loongson] Share the same kernel image file between different
-			 yeeloong laptop.
-			Example: machtype=lemote-yeeloong-2f-7inch
-
-	max_addr=nn[KMG]	[KNL,BOOT,ia64] All physical memory greater
-			than or equal to this physical address is ignored.
-
-	maxcpus=	[SMP] Maximum number of processors that	an SMP kernel
-			will bring up during bootup.  maxcpus=n : n >= 0 limits
-			the kernel to bring up 'n' processors. Surely after
-			bootup you can bring up the other plugged cpu by executing
-			"echo 1 > /sys/devices/system/cpu/cpuX/online". So maxcpus
-			only takes effect during system bootup.
-			While n=0 is a special case, it is equivalent to "nosmp",
-			which also disables the IO APIC.
-
-	max_loop=	[LOOP] The number of loop block devices that get
-	(loop.max_loop)	unconditionally pre-created at init time. The default
-			number is configured by BLK_DEV_LOOP_MIN_COUNT. Instead
-			of statically allocating a predefined number, loop
-			devices can be requested on-demand with the
-			/dev/loop-control interface.
-
-	mce		[X86-32] Machine Check Exception
-
-	mce=option	[X86-64] See Documentation/x86/x86_64/boot-options.txt
-
-	md=		[HW] RAID subsystems devices and level
-			See Documentation/md.txt.
-
-	mdacon=		[MDA]
-			Format: <first>,<last>
-			Specifies range of consoles to be captured by the MDA.
-
-	mem=nn[KMG]	[KNL,BOOT] Force usage of a specific amount of memory
-			Amount of memory to be used when the kernel is not able
-			to see the whole system memory or for test.
-			[X86] Work as limiting max address. Use together
-			with memmap= to avoid physical address space collisions.
-			Without memmap= PCI devices could be placed at addresses
-			belonging to unused RAM.
-
-	mem=nopentium	[BUGS=X86-32] Disable usage of 4MB pages for kernel
-			memory.
-
-	memchunk=nn[KMG]
-			[KNL,SH] Allow user to override the default size for
-			per-device physically contiguous DMA buffers.
-
-        memhp_default_state=online/offline
-			[KNL] Set the initial state for the memory hotplug
-			onlining policy. If not specified, the default value is
-			set according to the
-			CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE kernel config
-			option.
-			See Documentation/memory-hotplug.txt.
-
-	memmap=exactmap	[KNL,X86] Enable setting of an exact
-			E820 memory map, as specified by the user.
-			Such memmap=exactmap lines can be constructed based on
-			BIOS output or other requirements. See the memmap=nn@ss
-			option description.
-
-	memmap=nn[KMG]@ss[KMG]
-			[KNL] Force usage of a specific region of memory.
-			Region of memory to be used is from ss to ss+nn.
-
-	memmap=nn[KMG]#ss[KMG]
-			[KNL,ACPI] Mark specific memory as ACPI data.
-			Region of memory to be marked is from ss to ss+nn.
-
-	memmap=nn[KMG]$ss[KMG]
-			[KNL,ACPI] Mark specific memory as reserved.
-			Region of memory to be reserved is from ss to ss+nn.
-			Example: Exclude memory from 0x18690000-0x1869ffff
-			         memmap=64K$0x18690000
-			         or
-			         memmap=0x10000$0x18690000
-
-	memmap=nn[KMG]!ss[KMG]
-			[KNL,X86] Mark specific memory as protected.
-			Region of memory to be used, from ss to ss+nn.
-			The memory region may be marked as e820 type 12 (0xc)
-			and is NVDIMM or ADR memory.
-
-	memory_corruption_check=0/1 [X86]
-			Some BIOSes seem to corrupt the first 64k of
-			memory when doing things like suspend/resume.
-			Setting this option will scan the memory
-			looking for corruption.  Enabling this will
-			both detect corruption and prevent the kernel
-			from using the memory being corrupted.
-			However, its intended as a diagnostic tool; if
-			repeatable BIOS-originated corruption always
-			affects the same memory, you can use memmap=
-			to prevent the kernel from using that memory.
-
-	memory_corruption_check_size=size [X86]
-			By default it checks for corruption in the low
-			64k, making this memory unavailable for normal
-			use.  Use this parameter to scan for
-			corruption in more or less memory.
-
-	memory_corruption_check_period=seconds [X86]
-			By default it checks for corruption every 60
-			seconds.  Use this parameter to check at some
-			other rate.  0 disables periodic checking.
-
-	memtest=	[KNL,X86,ARM] Enable memtest
-			Format: <integer>
-			default : 0 <disable>
-			Specifies the number of memtest passes to be
-			performed. Each pass selects another test
-			pattern from a given set of patterns. Memtest
-			fills the memory with this pattern, validates
-			memory contents and reserves bad memory
-			regions that are detected.
-
-	meye.*=		[HW] Set MotionEye Camera parameters
-			See Documentation/video4linux/meye.txt.
-
-	mfgpt_irq=	[IA-32] Specify the IRQ to use for the
-			Multi-Function General Purpose Timers on AMD Geode
-			platforms.
-
-	mfgptfix	[X86-32] Fix MFGPT timers on AMD Geode platforms when
-			the BIOS has incorrectly applied a workaround. TinyBIOS
-			version 0.98 is known to be affected, 0.99 fixes the
-			problem by letting the user disable the workaround.
-
-	mga=		[HW,DRM]
-
-	min_addr=nn[KMG]	[KNL,BOOT,ia64] All physical memory below this
-			physical address is ignored.
-
-	mini2440=	[ARM,HW,KNL]
-			Format:[0..2][b][c][t]
-			Default: "0tb"
-			MINI2440 configuration specification:
-			0 - The attached screen is the 3.5" TFT
-			1 - The attached screen is the 7" TFT
-			2 - The VGA Shield is attached (1024x768)
-			Leaving out the screen size parameter will not load
-			the TFT driver, and the framebuffer will be left
-			unconfigured.
-			b - Enable backlight. The TFT backlight pin will be
-			linked to the kernel VESA blanking code and a GPIO
-			LED. This parameter is not necessary when using the
-			VGA shield.
-			c - Enable the s3c camera interface.
-			t - Reserved for enabling touchscreen support. The
-			touchscreen support is not enabled in the mainstream
-			kernel as of 2.6.30, a preliminary port can be found
-			in the "bleeding edge" mini2440 support kernel at
-			http://repo.or.cz/w/linux-2.6/mini2440.git
-
-	mminit_loglevel=
-			[KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
-			parameter allows control of the logging verbosity for
-			the additional memory initialisation checks. A value
-			of 0 disables mminit logging and a level of 4 will
-			log everything. Information is printed at KERN_DEBUG
-			so loglevel=8 may also need to be specified.
-
-	module.sig_enforce
-			[KNL] When CONFIG_MODULE_SIG is set, this means that
-			modules without (valid) signatures will fail to load.
-			Note that if CONFIG_MODULE_SIG_FORCE is set, that
-			is always true, so this option does nothing.
-
-	module_blacklist=  [KNL] Do not load a comma-separated list of
-			modules.  Useful for debugging problem modules.
-
-	mousedev.tap_time=
-			[MOUSE] Maximum time between finger touching and
-			leaving touchpad surface for touch to be considered
-			a tap and be reported as a left button click (for
-			touchpads working in absolute mode only).
-			Format: <msecs>
-	mousedev.xres=	[MOUSE] Horizontal screen resolution, used for devices
-			reporting absolute coordinates, such as tablets
-	mousedev.yres=	[MOUSE] Vertical screen resolution, used for devices
-			reporting absolute coordinates, such as tablets
-
-	movablecore=nn[KMG]	[KNL,X86,IA-64,PPC] This parameter
-			is similar to kernelcore except it specifies the
-			amount of memory used for migratable allocations.
-			If both kernelcore and movablecore is specified,
-			then kernelcore will be at *least* the specified
-			value but may be more. If movablecore on its own
-			is specified, the administrator must be careful
-			that the amount of memory usable for all allocations
-			is not too small.
-
-	movable_node	[KNL,X86] Boot-time switch to enable the effects
-			of CONFIG_MOVABLE_NODE=y. See mm/Kconfig for details.
-
-	MTD_Partition=	[MTD]
-			Format: <name>,<region-number>,<size>,<offset>
-
-	MTD_Region=	[MTD] Format:
-			<name>,<region-number>[,<base>,<size>,<buswidth>,<altbuswidth>]
-
-	mtdparts=	[MTD]
-			See drivers/mtd/cmdlinepart.c.
-
-	multitce=off	[PPC]  This parameter disables the use of the pSeries
-			firmware feature for updating multiple TCE entries
-			at a time.
-
-	onenand.bdry=	[HW,MTD] Flex-OneNAND Boundary Configuration
-
-			Format: [die0_boundary][,die0_lock][,die1_boundary][,die1_lock]
-
-			boundary - index of last SLC block on Flex-OneNAND.
-				   The remaining blocks are configured as MLC blocks.
-			lock	 - Configure if Flex-OneNAND boundary should be locked.
-				   Once locked, the boundary cannot be changed.
-				   1 indicates lock status, 0 indicates unlock status.
-
-	mtdset=		[ARM]
-			ARM/S3C2412 JIVE boot control
-
-			See arch/arm/mach-s3c2412/mach-jive.c
-
-	mtouchusb.raw_coordinates=
-			[HW] Make the MicroTouch USB driver use raw coordinates
-			('y', default) or cooked coordinates ('n')
-
-	mtrr_chunk_size=nn[KMG] [X86]
-			used for mtrr cleanup. It is largest continuous chunk
-			that could hold holes aka. UC entries.
-
-	mtrr_gran_size=nn[KMG] [X86]
-			Used for mtrr cleanup. It is granularity of mtrr block.
-			Default is 1.
-			Large value could prevent small alignment from
-			using up MTRRs.
-
-	mtrr_spare_reg_nr=n [X86]
-			Format: <integer>
-			Range: 0,7 : spare reg number
-			Default : 1
-			Used for mtrr cleanup. It is spare mtrr entries number.
-			Set to 2 or more if your graphical card needs more.
-
-	n2=		[NET] SDL Inc. RISCom/N2 synchronous serial card
-
-	netdev=		[NET] Network devices parameters
-			Format: <irq>,<io>,<mem_start>,<mem_end>,<name>
-			Note that mem_start is often overloaded to mean
-			something different and driver-specific.
-			This usage is only documented in each driver source
-			file if at all.
-
-	nf_conntrack.acct=
-			[NETFILTER] Enable connection tracking flow accounting
-			0 to disable accounting
-			1 to enable accounting
-			Default value is 0.
-
-	nfsaddrs=	[NFS] Deprecated.  Use ip= instead.
-			See Documentation/filesystems/nfs/nfsroot.txt.
-
-	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
-			See Documentation/filesystems/nfs/nfsroot.txt.
-
-	nfsrootdebug	[NFS] enable nfsroot debugging messages.
-			See Documentation/filesystems/nfs/nfsroot.txt.
-
-	nfs.callback_nr_threads=
-			[NFSv4] set the total number of threads that the
-			NFS client will assign to service NFSv4 callback
-			requests.
-
-	nfs.callback_tcpport=
-			[NFS] set the TCP port on which the NFSv4 callback
-			channel should listen.
-
-	nfs.cache_getent=
-			[NFS] sets the pathname to the program which is used
-			to update the NFS client cache entries.
-
-	nfs.cache_getent_timeout=
-			[NFS] sets the timeout after which an attempt to
-			update a cache entry is deemed to have failed.
-
-	nfs.idmap_cache_timeout=
-			[NFS] set the maximum lifetime for idmapper cache
-			entries.
-
-	nfs.enable_ino64=
-			[NFS] enable 64-bit inode numbers.
-			If zero, the NFS client will fake up a 32-bit inode
-			number for the readdir() and stat() syscalls instead
-			of returning the full 64-bit number.
-			The default is to return 64-bit inode numbers.
-
-	nfs.max_session_cb_slots=
-			[NFSv4.1] Sets the maximum number of session
-			slots the client will assign to the callback
-			channel. This determines the maximum number of
-			callbacks the client will process in parallel for
-			a particular server.
-
-	nfs.max_session_slots=
-			[NFSv4.1] Sets the maximum number of session slots
-			the client will attempt to negotiate with the server.
-			This limits the number of simultaneous RPC requests
-			that the client can send to the NFSv4.1 server.
-			Note that there is little point in setting this
-			value higher than the max_tcp_slot_table_limit.
-
-	nfs.nfs4_disable_idmapping=
-			[NFSv4] When set to the default of '1', this option
-			ensures that both the RPC level authentication
-			scheme and the NFS level operations agree to use
-			numeric uids/gids if the mount is using the
-			'sec=sys' security flavour. In effect it is
-			disabling idmapping, which can make migration from
-			legacy NFSv2/v3 systems to NFSv4 easier.
-			Servers that do not support this mode of operation
-			will be autodetected by the client, and it will fall
-			back to using the idmapper.
-			To turn off this behaviour, set the value to '0'.
-	nfs.nfs4_unique_id=
-			[NFS4] Specify an additional fixed unique ident-
-			ification string that NFSv4 clients can insert into
-			their nfs_client_id4 string.  This is typically a
-			UUID that is generated at system install time.
-
-	nfs.send_implementation_id =
-			[NFSv4.1] Send client implementation identification
-			information in exchange_id requests.
-			If zero, no implementation identification information
-			will be sent.
-			The default is to send the implementation identification
-			information.
-	
-	nfs.recover_lost_locks =
-			[NFSv4] Attempt to recover locks that were lost due
-			to a lease timeout on the server. Please note that
-			doing this risks data corruption, since there are
-			no guarantees that the file will remain unchanged
-			after the locks are lost.
-			If you want to enable the kernel legacy behaviour of
-			attempting to recover these locks, then set this
-			parameter to '1'.
-			The default parameter value of '0' causes the kernel
-			not to attempt recovery of lost locks.
-
-	nfs4.layoutstats_timer =
-			[NFSv4.2] Change the rate at which the kernel sends
-			layoutstats to the pNFS metadata server.
-
-			Setting this to value to 0 causes the kernel to use
-			whatever value is the default set by the layout
-			driver. A non-zero value sets the minimum interval
-			in seconds between layoutstats transmissions.
-
-	nfsd.nfs4_disable_idmapping=
-			[NFSv4] When set to the default of '1', the NFSv4
-			server will return only numeric uids and gids to
-			clients using auth_sys, and will accept numeric uids
-			and gids from such clients.  This is intended to ease
-			migration from NFSv2/v3.
-
-	objlayoutdriver.osd_login_prog=
-			[NFS] [OBJLAYOUT] sets the pathname to the program which
-			is used to automatically discover and login into new
-			osd-targets. Please see:
-			Documentation/filesystems/pnfs.txt for more explanations
-
-	nmi_debug=	[KNL,AVR32,SH] Specify one or more actions to take
-			when a NMI is triggered.
-			Format: [state][,regs][,debounce][,die]
-
-	nmi_watchdog=	[KNL,BUGS=X86] Debugging features for SMP kernels
-			Format: [panic,][nopanic,][num]
-			Valid num: 0 or 1
-			0 - turn hardlockup detector in nmi_watchdog off
-			1 - turn hardlockup detector in nmi_watchdog on
-			When panic is specified, panic when an NMI watchdog
-			timeout occurs (or 'nopanic' to override the opposite
-			default). To disable both hard and soft lockup detectors,
-			please see 'nowatchdog'.
-			This is useful when you use a panic=... timeout and
-			need the box quickly up again.
-
-	netpoll.carrier_timeout=
-			[NET] Specifies amount of time (in seconds) that
-			netpoll should wait for a carrier. By default netpoll
-			waits 4 seconds.
-
-	no387		[BUGS=X86-32] Tells the kernel to use the 387 maths
-			emulation library even if a 387 maths coprocessor
-			is present.
-
-	no_console_suspend
-			[HW] Never suspend the console
-			Disable suspending of consoles during suspend and
-			hibernate operations.  Once disabled, debugging
-			messages can reach various consoles while the rest
-			of the system is being put to sleep (ie, while
-			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,
-			but will impact performance.
-
-	noalign		[KNL,ARM]
-
-	noapic		[SMP,APIC] Tells the kernel to not make use of any
-			IOAPICs that may be present in the system.
-
-	noautogroup	Disable scheduler automatic task group creation.
-
-	nobats		[PPC] Do not use BATs for mapping kernel lowmem
-			on "Classic" PPC cores.
-
-	nocache		[ARM]
-
-	noclflush	[BUGS=X86] Don't use the CLFLUSH instruction
-
-	nodelayacct	[KNL] Disable per-task delay accounting
-
-	nodsp		[SH] Disable hardware DSP at boot time.
-
-	noefi		Disable EFI runtime services support.
-
-	noexec		[IA-64]
-
-	noexec		[X86]
-			On X86-32 available only on PAE configured kernels.
-			noexec=on: enable non-executable mappings (default)
-			noexec=off: disable non-executable mappings
-
-	nosmap		[X86]
-			Disable SMAP (Supervisor Mode Access Prevention)
-			even if it is supported by processor.
-
-	nosmep		[X86]
-			Disable SMEP (Supervisor Mode Execution Prevention)
-			even if it is supported by processor.
-
-	noexec32	[X86-64]
-			This affects only 32-bit executables.
-			noexec32=on: enable non-executable mappings (default)
-				read doesn't imply executable mappings
-			noexec32=off: disable non-executable mappings
-				read implies executable mappings
-
-	nofpu		[MIPS,SH] Disable hardware FPU at boot time.
-
-	nofxsr		[BUGS=X86-32] Disables x86 floating point extended
-			register save and restore. The kernel will only save
-			legacy floating-point registers on task switch.
-
-	nohugeiomap	[KNL,x86] Disable kernel huge I/O mappings.
-
-	nosmt		[KNL,S390] Disable symmetric multithreading (SMT).
-			Equivalent to smt=1.
-
-	noxsave		[BUGS=X86] Disables x86 extended register state save
-			and restore using xsave. The kernel will fallback to
-			enabling legacy floating-point and sse state.
-
-	noxsaveopt	[X86] Disables xsaveopt used in saving x86 extended
-			register states. The kernel will fall back to use
-			xsave to save the states. By using this parameter,
-			performance of saving the states is degraded because
-			xsave doesn't support modified optimization while
-			xsaveopt supports it on xsaveopt enabled systems.
-
-	noxsaves	[X86] Disables xsaves and xrstors used in saving and
-			restoring x86 extended register state in compacted
-			form of xsave area. The kernel will fall back to use
-			xsaveopt and xrstor to save and restore the states
-			in standard form of xsave area. By using this
-			parameter, xsave area per process might occupy more
-			memory on xsaves enabled systems.
-
-	nohlt		[BUGS=ARM,SH] Tells the kernel that the sleep(SH) or
-			wfi(ARM) instruction doesn't work correctly and not to
-			use it. This is also useful when using JTAG debugger.
-
-	no_file_caps	Tells the kernel not to honor file capabilities.  The
-			only way then for a file to be executed with privilege
-			is to be setuid root or executed by root.
-
-	nohalt		[IA-64] Tells the kernel not to use the power saving
-			function PAL_HALT_LIGHT when idle. This increases
-			power-consumption. On the positive side, it reduces
-			interrupt wake-up latency, which may improve performance
-			in certain environments such as networked servers or
-			real-time systems.
-
-	nohibernate	[HIBERNATION] Disable hibernation and resume.
-
-	nohz=		[KNL] Boottime enable/disable dynamic ticks
-			Valid arguments: on, off
-			Default: on
-
-	nohz_full=	[KNL,BOOT]
-			The argument is a cpu list, as described above.
-			In kernels built with CONFIG_NO_HZ_FULL=y, set
-			the specified list of CPUs whose tick will be stopped
-			whenever possible. The boot CPU will be forced outside
-			the range to maintain the timekeeping.
-			The CPUs in this range must also be included in the
-			rcu_nocbs= set.
-
-	noiotrap	[SH] Disables trapped I/O port accesses.
-
-	noirqdebug	[X86-32] Disables the code which attempts to detect and
-			disable unhandled interrupt sources.
-
-	no_timer_check	[X86,APIC] Disables the code which tests for
-			broken timer IRQ sources.
-
-	noisapnp	[ISAPNP] Disables ISA PnP code.
-
-	noinitrd	[RAM] Tells the kernel not to load any configured
-			initial RAM disk.
-
-	nointremap	[X86-64, Intel-IOMMU] Do not enable interrupt
-			remapping.
-			[Deprecated - use intremap=off]
-
-	nointroute	[IA-64]
-
-	noinvpcid	[X86] Disable the INVPCID cpu feature.
-
-	nojitter	[IA-64] Disables jitter checking for ITC timers.
-
-	no-kvmclock	[X86,KVM] Disable paravirtualized KVM clock driver
-
-	no-kvmapf	[X86,KVM] Disable paravirtualized asynchronous page
-			fault handling.
-
-	no-steal-acc    [X86,KVM] Disable paravirtualized steal time accounting.
-			steal time is computed, but won't influence scheduler
-			behaviour
-
-	nolapic		[X86-32,APIC] Do not enable or use the local APIC.
-
-	nolapic_timer	[X86-32,APIC] Do not use the local APIC timer.
-
-	noltlbs		[PPC] Do not use large page/tlb entries for kernel
-			lowmem mapping on PPC40x and PPC8xx
-
-	nomca		[IA-64] Disable machine check abort handling
-
-	nomce		[X86-32] Disable Machine Check Exception
-
-	nomfgpt		[X86-32] Disable Multi-Function General Purpose
-			Timer usage (for AMD Geode machines).
-
-	nonmi_ipi	[X86] Disable using NMI IPIs during panic/reboot to
-			shutdown the other cpus.  Instead use the REBOOT_VECTOR
-			irq.
-
-	nomodule	Disable module load
-
-	nopat		[X86] Disable PAT (page attribute table extension of
-			pagetables) support.
-
-	norandmaps	Don't use address space randomization.  Equivalent to
-			echo 0 > /proc/sys/kernel/randomize_va_space
-
-	noreplace-paravirt	[X86,IA-64,PV_OPS] Don't patch paravirt_ops
-
-	noreplace-smp	[X86-32,SMP] Don't replace SMP instructions
-			with UP alternatives
-
-	nordrand	[X86] Disable kernel use of the RDRAND and
-			RDSEED instructions even if they are supported
-			by the processor.  RDRAND and RDSEED are still
-			available to user space applications.
-
-	noresume	[SWSUSP] Disables resume and restores original swap
-			space.
-
-	no-scroll	[VGA] Disables scrollback.
-			This is required for the Braillex ib80-piezo Braille
-			reader made by F.H. Papenmeier (Germany).
-
-	nosbagart	[IA-64]
-
-	nosep		[BUGS=X86-32] Disables x86 SYSENTER/SYSEXIT support.
-
-	nosmp		[SMP] Tells an SMP kernel to act as a UP kernel,
-			and disable the IO APIC.  legacy for "maxcpus=0".
-
-	nosoftlockup	[KNL] Disable the soft-lockup detector.
-
-	nosync		[HW,M68K] Disables sync negotiation for all devices.
-
-	notsc		[BUGS=X86-32] Disable Time Stamp Counter
-
-	nowatchdog	[KNL] Disable both lockup detectors, i.e.
-                        soft-lockup and NMI watchdog (hard-lockup).
-
-	nowb		[ARM]
-
-	nox2apic	[X86-64,APIC] Do not enable x2APIC mode.
-
-	cpu0_hotplug	[X86] Turn on CPU0 hotplug feature when
-			CONFIG_BOOTPARAM_HOTPLUG_CPU0 is off.
-			Some features depend on CPU0. Known dependencies are:
-			1. Resume from suspend/hibernate depends on CPU0.
-			Suspend/hibernate will fail if CPU0 is offline and you
-			need to online CPU0 before suspend/hibernate.
-			2. PIC interrupts also depend on CPU0. CPU0 can't be
-			removed if a PIC interrupt is detected.
-			It's said poweroff/reboot may depend on CPU0 on some
-			machines although I haven't seen such issues so far
-			after CPU0 is offline on a few tested machines.
-			If the dependencies are under your control, you can
-			turn on cpu0_hotplug.
-
-	nptcg=		[IA-64] Override max number of concurrent global TLB
-			purges which is reported from either PAL_VM_SUMMARY or
-			SAL PALO.
-
-	nr_cpus=	[SMP] Maximum number of processors that	an SMP kernel
-			could support.  nr_cpus=n : n >= 1 limits the kernel to
-			support 'n' processors. It could be larger than the
-			number of already plugged CPU during bootup, later in
-			runtime you can physically add extra cpu until it reaches
-			n. So during boot up some boot time memory for per-cpu
-			variables need be pre-allocated for later physical cpu
-			hot plugging.
-
-	nr_uarts=	[SERIAL] maximum number of UARTs to be registered.
-
-	numa_balancing=	[KNL,X86] Enable or disable automatic NUMA balancing.
-			Allowed values are enable and disable
-
-	numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA.
-			one of ['zone', 'node', 'default'] can be specified
-			This can be set from sysctl after boot.
-			See Documentation/sysctl/vm.txt for details.
-
-	ohci1394_dma=early	[HW] enable debugging via the ohci1394 driver.
-			See Documentation/debugging-via-ohci1394.txt for more
-			info.
-
-	olpc_ec_timeout= [OLPC] ms delay when issuing EC commands
-			Rather than timing out after 20 ms if an EC
-			command is not properly ACKed, override the length
-			of the timeout.  We have interrupts disabled while
-			waiting for the ACK, so if this is set too high
-			interrupts *may* be lost!
-
-	omap_mux=	[OMAP] Override bootloader pin multiplexing.
-			Format: <mux_mode0.mode_name=value>...
-			For example, to override I2C bus2:
-			omap_mux=i2c2_scl.i2c2_scl=0x100,i2c2_sda.i2c2_sda=0x100
-
-	oprofile.timer=	[HW]
-			Use timer interrupt instead of performance counters
-
-	oprofile.cpu_type=	Force an oprofile cpu type
-			This might be useful if you have an older oprofile
-			userland or if you want common events.
-			Format: { arch_perfmon }
-			arch_perfmon: [X86] Force use of architectural
-				perfmon on Intel CPUs instead of the
-				CPU specific event set.
-			timer: [X86] Force use of architectural NMI
-				timer mode (see also oprofile.timer
-				for generic hr timer mode)
-
-	oops=panic	Always panic on oopses. Default is to just kill the
-			process, but there is a small probability of
-			deadlocking the machine.
-			This will also cause panics on machine check exceptions.
-			Useful together with panic=30 to trigger a reboot.
-
-	OSS		[HW,OSS]
-			See Documentation/sound/oss/oss-parameters.txt
-
-	page_owner=	[KNL] Boot-time page_owner enabling option.
-			Storage of the information about who allocated
-			each page is disabled in default. With this switch,
-			we can turn it on.
-			on: enable the feature
-
-	page_poison=	[KNL] Boot-time parameter changing the state of
-			poisoning on the buddy allocator.
-			off: turn off poisoning
-			on: turn on poisoning
-
-	panic=		[KNL] Kernel behaviour on panic: delay <timeout>
-			timeout > 0: seconds before rebooting
-			timeout = 0: wait forever
-			timeout < 0: reboot immediately
-			Format: <timeout>
-
-	panic_on_warn	panic() instead of WARN().  Useful to cause kdump
-			on a WARN().
-
-	crash_kexec_post_notifiers
-			Run kdump after running panic-notifiers and dumping
-			kmsg. This only for the users who doubt kdump always
-			succeeds in any situation.
-			Note that this also increases risks of kdump failure,
-			because some panic notifiers can make the crashed
-			kernel more unstable.
-
-	parkbd.port=	[HW] Parallel port number the keyboard adapter is
-			connected to, default is 0.
-			Format: <parport#>
-	parkbd.mode=	[HW] Parallel port keyboard adapter mode of operation,
-			0 for XT, 1 for AT (default is AT).
-			Format: <mode>
-
-	parport=	[HW,PPT] Specify parallel ports. 0 disables.
-			Format: { 0 | auto | 0xBBB[,IRQ[,DMA]] }
-			Use 'auto' to force the driver to use any
-			IRQ/DMA settings detected (the default is to
-			ignore detected IRQ/DMA settings because of
-			possible conflicts). You can specify the base
-			address, IRQ, and DMA settings; IRQ and DMA
-			should be numbers, or 'auto' (for using detected
-			settings on that particular port), or 'nofifo'
-			(to avoid using a FIFO even if it is detected).
-			Parallel ports are assigned in the order they
-			are specified on the command line, starting
-			with parport0.
-
-	parport_init_mode=	[HW,PPT]
-			Configure VIA parallel port to operate in
-			a specific mode. This is necessary on Pegasos
-			computer where firmware has no options for setting
-			up parallel port mode and sets it to spp.
-			Currently this function knows 686a and 8231 chips.
-			Format: [spp|ps2|epp|ecp|ecpepp]
-
-	pause_on_oops=
-			Halt all CPUs after the first oops has been printed for
-			the specified number of seconds.  This is to be used if
-			your oopses keep scrolling off the screen.
-
-	pcbit=		[HW,ISDN]
-
-	pcd.		[PARIDE]
-			See header of drivers/block/paride/pcd.c.
-			See also Documentation/blockdev/paride.txt.
-
-	pci=option[,option...]	[PCI] various PCI subsystem options:
-		earlydump	[X86] dump PCI config space before the kernel
-			        changes anything
-		off		[X86] don't probe for the PCI bus
-		bios		[X86-32] force use of PCI BIOS, don't access
-				the hardware directly. Use this if your machine
-				has a non-standard PCI host bridge.
-		nobios		[X86-32] disallow use of PCI BIOS, only direct
-				hardware access methods are allowed. Use this
-				if you experience crashes upon bootup and you
-				suspect they are caused by the BIOS.
-		conf1		[X86] Force use of PCI Configuration Access
-				Mechanism 1 (config address in IO port 0xCF8,
-				data in IO port 0xCFC, both 32-bit).
-		conf2		[X86] Force use of PCI Configuration Access
-				Mechanism 2 (IO port 0xCF8 is an 8-bit port for
-				the function, IO port 0xCFA, also 8-bit, sets
-				bus number. The config space is then accessed
-				through ports 0xC000-0xCFFF).
-				See http://wiki.osdev.org/PCI for more info
-				on the configuration access mechanisms.
-		noaer		[PCIE] If the PCIEAER kernel config parameter is
-				enabled, this kernel boot option can be used to
-				disable the use of PCIE advanced error reporting.
-		nodomains	[PCI] Disable support for multiple PCI
-				root domains (aka PCI segments, in ACPI-speak).
-		nommconf	[X86] Disable use of MMCONFIG for PCI
-				Configuration
-		check_enable_amd_mmconf [X86] check for and enable
-				properly configured MMIO access to PCI
-				config space on AMD family 10h CPU
-		nomsi		[MSI] If the PCI_MSI kernel config parameter is
-				enabled, this kernel boot option can be used to
-				disable the use of MSI interrupts system-wide.
-		noioapicquirk	[APIC] Disable all boot interrupt quirks.
-				Safety option to keep boot IRQs enabled. This
-				should never be necessary.
-		ioapicreroute	[APIC] Enable rerouting of boot IRQs to the
-				primary IO-APIC for bridges that cannot disable
-				boot IRQs. This fixes a source of spurious IRQs
-				when the system masks IRQs.
-		noioapicreroute	[APIC] Disable workaround that uses the
-				boot IRQ equivalent of an IRQ that connects to
-				a chipset where boot IRQs cannot be disabled.
-				The opposite of ioapicreroute.
-		biosirq		[X86-32] Use PCI BIOS calls to get the interrupt
-				routing table. These calls are known to be buggy
-				on several machines and they hang the machine
-				when used, but on other computers it's the only
-				way to get the interrupt routing table. Try
-				this option if the kernel is unable to allocate
-				IRQs or discover secondary PCI buses on your
-				motherboard.
-		rom		[X86] Assign address space to expansion ROMs.
-				Use with caution as certain devices share
-				address decoders between ROMs and other
-				resources.
-		norom		[X86] Do not assign address space to
-				expansion ROMs that do not already have
-				BIOS assigned address ranges.
-		nobar		[X86] Do not assign address space to the
-				BARs that weren't assigned by the BIOS.
-		irqmask=0xMMMM	[X86] Set a bit mask of IRQs allowed to be
-				assigned automatically to PCI devices. You can
-				make the kernel exclude IRQs of your ISA cards
-				this way.
-		pirqaddr=0xAAAAA	[X86] Specify the physical address
-				of the PIRQ table (normally generated
-				by the BIOS) if it is outside the
-				F0000h-100000h range.
-		lastbus=N	[X86] Scan all buses thru bus #N. Can be
-				useful if the kernel is unable to find your
-				secondary buses and you want to tell it
-				explicitly which ones they are.
-		assign-busses	[X86] Always assign all PCI bus
-				numbers ourselves, overriding
-				whatever the firmware may have done.
-		usepirqmask	[X86] Honor the possible IRQ mask stored
-				in the BIOS $PIR table. This is needed on
-				some systems with broken BIOSes, notably
-				some HP Pavilion N5400 and Omnibook XE3
-				notebooks. This will have no effect if ACPI
-				IRQ routing is enabled.
-		noacpi		[X86] Do not use ACPI for IRQ routing
-				or for PCI scanning.
-		use_crs		[X86] Use PCI host bridge window information
-				from ACPI.  On BIOSes from 2008 or later, this
-				is enabled by default.  If you need to use this,
-				please report a bug.
-		nocrs		[X86] Ignore PCI host bridge windows from ACPI.
-			        If you need to use this, please report a bug.
-		routeirq	Do IRQ routing for all PCI devices.
-				This is normally done in pci_enable_device(),
-				so this option is a temporary workaround
-				for broken drivers that don't call it.
-		skip_isa_align	[X86] do not align io start addr, so can
-				handle more pci cards
-		noearly		[X86] Don't do any early type 1 scanning.
-				This might help on some broken boards which
-				machine check when some devices' config space
-				is read. But various workarounds are disabled
-				and some IOMMU drivers will not work.
-		bfsort		Sort PCI devices into breadth-first order.
-				This sorting is done to get a device
-				order compatible with older (<= 2.4) kernels.
-		nobfsort	Don't sort PCI devices into breadth-first order.
-		pcie_bus_tune_off	Disable PCIe MPS (Max Payload Size)
-				tuning and use the BIOS-configured MPS defaults.
-		pcie_bus_safe	Set every device's MPS to the largest value
-				supported by all devices below the root complex.
-		pcie_bus_perf	Set device MPS to the largest allowable MPS
-				based on its parent bus. Also set MRRS (Max
-				Read Request Size) to the largest supported
-				value (no larger than the MPS that the device
-				or bus can support) for best performance.
-		pcie_bus_peer2peer	Set every device's MPS to 128B, which
-				every device is guaranteed to support. This
-				configuration allows peer-to-peer DMA between
-				any pair of devices, possibly at the cost of
-				reduced performance.  This also guarantees
-				that hot-added devices will work.
-		cbiosize=nn[KMG]	The fixed amount of bus space which is
-				reserved for the CardBus bridge's IO window.
-				The default value is 256 bytes.
-		cbmemsize=nn[KMG]	The fixed amount of bus space which is
-				reserved for the CardBus bridge's memory
-				window. The default value is 64 megabytes.
-		resource_alignment=
-				Format:
-				[<order of align>@][<domain>:]<bus>:<slot>.<func>[; ...]
-				[<order of align>@]pci:<vendor>:<device>\
-						[:<subvendor>:<subdevice>][; ...]
-				Specifies alignment and device to reassign
-				aligned memory resources.
-				If <order of align> is not specified,
-				PAGE_SIZE is used as alignment.
-				PCI-PCI bridge can be specified, if resource
-				windows need to be expanded.
-				To specify the alignment for several
-				instances of a device, the PCI vendor,
-				device, subvendor, and subdevice may be
-				specified, e.g., 4096@pci:8086:9c22:103c:198f
-		ecrc=		Enable/disable PCIe ECRC (transaction layer
-				end-to-end CRC checking).
-				bios: Use BIOS/firmware settings. This is the
-				the default.
-				off: Turn ECRC off
-				on: Turn ECRC on.
-		hpiosize=nn[KMG]	The fixed amount of bus space which is
-				reserved for hotplug bridge's IO window.
-				Default size is 256 bytes.
-		hpmemsize=nn[KMG]	The fixed amount of bus space which is
-				reserved for hotplug bridge's memory window.
-				Default size is 2 megabytes.
-		hpbussize=nn	The minimum amount of additional bus numbers
-				reserved for buses below a hotplug bridge.
-				Default is 1.
-		realloc=	Enable/disable reallocating PCI bridge resources
-				if allocations done by BIOS are too small to
-				accommodate resources required by all child
-				devices.
-				off: Turn realloc off
-				on: Turn realloc on
-		realloc		same as realloc=on
-		noari		do not use PCIe ARI.
-		pcie_scan_all	Scan all possible PCIe devices.  Otherwise we
-				only look for one device below a PCIe downstream
-				port.
-
-	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
-			Management.
-		off	Disable ASPM.
-		force	Enable ASPM even on devices that claim not to support it.
-			WARNING: Forcing ASPM on may cause system lockups.
-
-	pcie_hp=	[PCIE] PCI Express Hotplug driver options:
-		nomsi	Do not use MSI for PCI Express Native Hotplug (this
-			makes all PCIe ports use INTx for hotplug services).
-
-	pcie_ports=	[PCIE] PCIe ports handling:
-		auto	Ask the BIOS whether or not to use native PCIe services
-			associated with PCIe ports (PME, hot-plug, AER).  Use
-			them only if that is allowed by the BIOS.
-		native	Use native PCIe services associated with PCIe ports
-			unconditionally.
-		compat	Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
-			ports driver.
-
-	pcie_port_pm=	[PCIE] PCIe port power management handling:
-		off	Disable power management of all PCIe ports
-		force	Forcibly enable power management of all PCIe ports
-
-	pcie_pme=	[PCIE,PM] Native PCIe PME signaling options:
-		nomsi	Do not use MSI for native PCIe PME signaling (this makes
-			all PCIe root ports use INTx for all services).
-
-	pcmv=		[HW,PCMCIA] BadgePAD 4
-
-	pd_ignore_unused
-			[PM]
-			Keep all power-domains already enabled by bootloader on,
-			even if no driver has claimed them. This is useful
-			for debug and development, but should not be
-			needed on a platform with proper driver support.
-
-	pd.		[PARIDE]
-			See Documentation/blockdev/paride.txt.
-
-	pdcchassis=	[PARISC,HW] Disable/Enable PDC Chassis Status codes at
-			boot time.
-			Format: { 0 | 1 }
-			See arch/parisc/kernel/pdc_chassis.c
-
-	percpu_alloc=	Select which percpu first chunk allocator to use.
-			Currently supported values are "embed" and "page".
-			Archs may support subset or none of the	selections.
-			See comments in mm/percpu.c for details on each
-			allocator.  This parameter is primarily	for debugging
-			and performance comparison.
-
-	pf.		[PARIDE]
-			See Documentation/blockdev/paride.txt.
-
-	pg.		[PARIDE]
-			See Documentation/blockdev/paride.txt.
-
-	pirq=		[SMP,APIC] Manual mp-table setup
-			See Documentation/x86/i386/IO-APIC.txt.
-
-	plip=		[PPT,NET] Parallel port network link
-			Format: { parport<nr> | timid | 0 }
-			See also Documentation/parport.txt.
-
-	pmtmr=		[X86] Manual setup of pmtmr I/O Port.
-			Override pmtimer IOPort with a hex value.
-			e.g. pmtmr=0x508
-
-	pnp.debug=1	[PNP]
-			Enable PNP debug messages (depends on the
-			CONFIG_PNP_DEBUG_MESSAGES option).  Change at run-time
-			via /sys/module/pnp/parameters/debug.  We always show
-			current resource usage; turning this on also shows
-			possible settings and some assignment information.
-
-	pnpacpi=	[ACPI]
-			{ off }
-
-	pnpbios=	[ISAPNP]
-			{ on | off | curr | res | no-curr | no-res }
-
-	pnp_reserve_irq=
-			[ISAPNP] Exclude IRQs for the autoconfiguration
-
-	pnp_reserve_dma=
-			[ISAPNP] Exclude DMAs for the autoconfiguration
-
-	pnp_reserve_io=	[ISAPNP] Exclude I/O ports for the autoconfiguration
-			Ranges are in pairs (I/O port base and size).
-
-	pnp_reserve_mem=
-			[ISAPNP] Exclude memory regions for the
-			autoconfiguration.
-			Ranges are in pairs (memory base and size).
-
-	ports=		[IP_VS_FTP] IPVS ftp helper module
-			Default is 21.
-			Up to 8 (IP_VS_APP_MAX_PORTS) ports
-			may be specified.
-			Format: <port>,<port>....
-
-	ppc_strict_facility_enable
-			[PPC] This option catches any kernel floating point,
-			Altivec, VSX and SPE outside of regions specifically
-			allowed (eg kernel_enable_fpu()/kernel_disable_fpu()).
-			There is some performance impact when enabling this.
-
-	print-fatal-signals=
-			[KNL] debug: print fatal signals
-
-			If enabled, warn about various signal handling
-			related application anomalies: too many signals,
-			too many POSIX.1 timers, fatal signals causing a
-			coredump - etc.
-
-			If you hit the warning due to signal overflow,
-			you might want to try "ulimit -i unlimited".
-
-			default: off.
-
-	printk.always_kmsg_dump=
-			Trigger kmsg_dump for cases other than kernel oops or
-			panics
-			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
-			default: disabled
-
-	printk.devkmsg={on,off,ratelimit}
-			Control writing to /dev/kmsg.
-			on - unlimited logging to /dev/kmsg from userspace
-			off - logging to /dev/kmsg disabled
-			ratelimit - ratelimit the logging
-			Default: ratelimit
-
-	printk.time=	Show timing data prefixed to each printk message line
-			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
-
-	processor.max_cstate=	[HW,ACPI]
-			Limit processor to maximum C-state
-			max_cstate=9 overrides any DMI blacklist limit.
-
-	processor.nocst	[HW,ACPI]
-			Ignore the _CST method to determine C-states,
-			instead using the legacy FADT method
-
-	profile=	[KNL] Enable kernel profiling via /proc/profile
-			Format: [schedule,]<number>
-			Param: "schedule" - profile schedule points.
-			Param: <number> - step/bucket size as a power of 2 for
-				statistical time based profiling.
-			Param: "sleep" - profile D-state sleeping (millisecs).
-				Requires CONFIG_SCHEDSTATS
-			Param: "kvm" - profile VM exits.
-
-	prompt_ramdisk=	[RAM] List of RAM disks to prompt for floppy disk
-			before loading.
-			See Documentation/blockdev/ramdisk.txt.
-
-	psmouse.proto=	[HW,MOUSE] Highest PS2 mouse protocol extension to
-			probe for; one of (bare|imps|exps|lifebook|any).
-	psmouse.rate=	[HW,MOUSE] Set desired mouse report rate, in reports
-			per second.
-	psmouse.resetafter=	[HW,MOUSE]
-			Try to reset the device after so many bad packets
-			(0 = never).
-	psmouse.resolution=
-			[HW,MOUSE] Set desired mouse resolution, in dpi.
-	psmouse.smartscroll=
-			[HW,MOUSE] Controls Logitech smartscroll autorepeat.
-			0 = disabled, 1 = enabled (default).
-
-	pstore.backend=	Specify the name of the pstore backend to use
-
-	pt.		[PARIDE]
-			See Documentation/blockdev/paride.txt.
-
-	pty.legacy_count=
-			[KNL] Number of legacy pty's. Overwrites compiled-in
-			default number.
-
-	quiet		[KNL] Disable most log messages
-
-	r128=		[HW,DRM]
-
-	raid=		[HW,RAID]
-			See Documentation/md.txt.
-
-	ramdisk_size=	[RAM] Sizes of RAM disks in kilobytes
-			See Documentation/blockdev/ramdisk.txt.
-
-	rcu_nocbs=	[KNL]
-			The argument is a cpu list, as described above.
-
-			In kernels built with CONFIG_RCU_NOCB_CPU=y, set
-			the specified list of CPUs to be no-callback CPUs.
-			Invocation of these CPUs' RCU callbacks will
-			be offloaded to "rcuox/N" kthreads created for
-			that purpose, where "x" is "b" for RCU-bh, "p"
-			for RCU-preempt, and "s" for RCU-sched, and "N"
-			is the CPU number.  This reduces OS jitter on the
-			offloaded CPUs, which can be useful for HPC and
-			real-time workloads.  It can also improve energy
-			efficiency for asymmetric multiprocessors.
-
-	rcu_nocb_poll	[KNL]
-			Rather than requiring that offloaded CPUs
-			(specified by rcu_nocbs= above) explicitly
-			awaken the corresponding "rcuoN" kthreads,
-			make these kthreads poll for callbacks.
-			This improves the real-time response for the
-			offloaded CPUs by relieving them of the need to
-			wake up the corresponding kthread, but degrades
-			energy efficiency by requiring that the kthreads
-			periodically wake up to do the polling.
-
-	rcutree.blimit=	[KNL]
-			Set maximum number of finished RCU callbacks to
-			process in one batch.
-
-	rcutree.dump_tree=	[KNL]
-			Dump the structure of the rcu_node combining tree
-			out at early boot.  This is used for diagnostic
-			purposes, to verify correct tree setup.
-
-	rcutree.gp_cleanup_delay=	[KNL]
-			Set the number of jiffies to delay each step of
-			RCU grace-period cleanup.  This only has effect
-			when CONFIG_RCU_TORTURE_TEST_SLOW_CLEANUP is set.
-
-	rcutree.gp_init_delay=	[KNL]
-			Set the number of jiffies to delay each step of
-			RCU grace-period initialization.  This only has
-			effect when CONFIG_RCU_TORTURE_TEST_SLOW_INIT
-			is set.
-
-	rcutree.gp_preinit_delay=	[KNL]
-			Set the number of jiffies to delay each step of
-			RCU grace-period pre-initialization, that is,
-			the propagation of recent CPU-hotplug changes up
-			the rcu_node combining tree.  This only has effect
-			when CONFIG_RCU_TORTURE_TEST_SLOW_PREINIT is set.
-
-	rcutree.rcu_fanout_exact= [KNL]
-			Disable autobalancing of the rcu_node combining
-			tree.  This is used by rcutorture, and might
-			possibly be useful for architectures having high
-			cache-to-cache transfer latencies.
-
-	rcutree.rcu_fanout_leaf= [KNL]
-			Change the number of CPUs assigned to each
-			leaf rcu_node structure.  Useful for very
-			large systems, which will choose the value 64,
-			and for NUMA systems with large remote-access
-			latencies, which will choose a value aligned
-			with the appropriate hardware boundaries.
-
-	rcutree.jiffies_till_sched_qs= [KNL]
-			Set required age in jiffies for a
-			given grace period before RCU starts
-			soliciting quiescent-state help from
-			rcu_note_context_switch().
-
-	rcutree.jiffies_till_first_fqs= [KNL]
-			Set delay from grace-period initialization to
-			first attempt to force quiescent states.
-			Units are jiffies, minimum value is zero,
-			and maximum value is HZ.
-
-	rcutree.jiffies_till_next_fqs= [KNL]
-			Set delay between subsequent attempts to force
-			quiescent states.  Units are jiffies, minimum
-			value is one, and maximum value is HZ.
-
-	rcutree.kthread_prio= 	 [KNL,BOOT]
-			Set the SCHED_FIFO priority of the RCU per-CPU
-			kthreads (rcuc/N). This value is also used for
-			the priority of the RCU boost threads (rcub/N)
-			and for the RCU grace-period kthreads (rcu_bh,
-			rcu_preempt, and rcu_sched). If RCU_BOOST is
-			set, valid values are 1-99 and the default is 1
-			(the least-favored priority).  Otherwise, when
-			RCU_BOOST is not set, valid values are 0-99 and
-			the default is zero (non-realtime operation).
-
-	rcutree.rcu_nocb_leader_stride= [KNL]
-			Set the number of NOCB kthread groups, which
-			defaults to the square root of the number of
-			CPUs.  Larger numbers reduces the wakeup overhead
-			on the per-CPU grace-period kthreads, but increases
-			that same overhead on each group's leader.
-
-	rcutree.qhimark= [KNL]
-			Set threshold of queued RCU callbacks beyond which
-			batch limiting is disabled.
-
-	rcutree.qlowmark= [KNL]
-			Set threshold of queued RCU callbacks below which
-			batch limiting is re-enabled.
-
-	rcutree.rcu_idle_gp_delay= [KNL]
-			Set wakeup interval for idle CPUs that have
-			RCU callbacks (RCU_FAST_NO_HZ=y).
-
-	rcutree.rcu_idle_lazy_gp_delay= [KNL]
-			Set wakeup interval for idle CPUs that have
-			only "lazy" RCU callbacks (RCU_FAST_NO_HZ=y).
-			Lazy RCU callbacks are those which RCU can
-			prove do nothing more than free memory.
-
-	rcuperf.gp_exp= [KNL]
-			Measure performance of expedited synchronous
-			grace-period primitives.
-
-	rcuperf.holdoff= [KNL]
-			Set test-start holdoff period.  The purpose of
-			this parameter is to delay the start of the
-			test until boot completes in order to avoid
-			interference.
-
-	rcuperf.nreaders= [KNL]
-			Set number of RCU readers.  The value -1 selects
-			N, where N is the number of CPUs.  A value
-			"n" less than -1 selects N-n+1, where N is again
-			the number of CPUs.  For example, -2 selects N
-			(the number of CPUs), -3 selects N+1, and so on.
-			A value of "n" less than or equal to -N selects
-			a single reader.
-
-	rcuperf.nwriters= [KNL]
-			Set number of RCU writers.  The values operate
-			the same as for rcuperf.nreaders.
-			N, where N is the number of CPUs
-
-	rcuperf.perf_runnable= [BOOT]
-			Start rcuperf running at boot time.
-
-	rcuperf.shutdown= [KNL]
-			Shut the system down after performance tests
-			complete.  This is useful for hands-off automated
-			testing.
-
-	rcuperf.perf_type= [KNL]
-			Specify the RCU implementation to test.
-
-	rcuperf.verbose= [KNL]
-			Enable additional printk() statements.
-
-	rcutorture.cbflood_inter_holdoff= [KNL]
-			Set holdoff time (jiffies) between successive
-			callback-flood tests.
-
-	rcutorture.cbflood_intra_holdoff= [KNL]
-			Set holdoff time (jiffies) between successive
-			bursts of callbacks within a given callback-flood
-			test.
-
-	rcutorture.cbflood_n_burst= [KNL]
-			Set the number of bursts making up a given
-			callback-flood test.  Set this to zero to
-			disable callback-flood testing.
-
-	rcutorture.cbflood_n_per_burst= [KNL]
-			Set the number of callbacks to be registered
-			in a given burst of a callback-flood test.
-
-	rcutorture.fqs_duration= [KNL]
-			Set duration of force_quiescent_state bursts
-			in microseconds.
-
-	rcutorture.fqs_holdoff= [KNL]
-			Set holdoff time within force_quiescent_state bursts
-			in microseconds.
-
-	rcutorture.fqs_stutter= [KNL]
-			Set wait time between force_quiescent_state bursts
-			in seconds.
-
-	rcutorture.gp_cond= [KNL]
-			Use conditional/asynchronous update-side
-			primitives, if available.
-
-	rcutorture.gp_exp= [KNL]
-			Use expedited update-side primitives, if available.
-
-	rcutorture.gp_normal= [KNL]
-			Use normal (non-expedited) asynchronous
-			update-side primitives, if available.
-
-	rcutorture.gp_sync= [KNL]
-			Use normal (non-expedited) synchronous
-			update-side primitives, if available.  If all
-			of rcutorture.gp_cond=, rcutorture.gp_exp=,
-			rcutorture.gp_normal=, and rcutorture.gp_sync=
-			are zero, rcutorture acts as if is interpreted
-			they are all non-zero.
-
-	rcutorture.n_barrier_cbs= [KNL]
-			Set callbacks/threads for rcu_barrier() testing.
-
-	rcutorture.nfakewriters= [KNL]
-			Set number of concurrent RCU writers.  These just
-			stress RCU, they don't participate in the actual
-			test, hence the "fake".
-
-	rcutorture.nreaders= [KNL]
-			Set number of RCU readers.  The value -1 selects
-			N-1, where N is the number of CPUs.  A value
-			"n" less than -1 selects N-n-2, where N is again
-			the number of CPUs.  For example, -2 selects N
-			(the number of CPUs), -3 selects N+1, and so on.
-
-	rcutorture.object_debug= [KNL]
-			Enable debug-object double-call_rcu() testing.
-
-	rcutorture.onoff_holdoff= [KNL]
-			Set time (s) after boot for CPU-hotplug testing.
-
-	rcutorture.onoff_interval= [KNL]
-			Set time (s) between CPU-hotplug operations, or
-			zero to disable CPU-hotplug testing.
-
-	rcutorture.shuffle_interval= [KNL]
-			Set task-shuffle interval (s).  Shuffling tasks
-			allows some CPUs to go into dyntick-idle mode
-			during the rcutorture test.
-
-	rcutorture.shutdown_secs= [KNL]
-			Set time (s) after boot system shutdown.  This
-			is useful for hands-off automated testing.
-
-	rcutorture.stall_cpu= [KNL]
-			Duration of CPU stall (s) to test RCU CPU stall
-			warnings, zero to disable.
-
-	rcutorture.stall_cpu_holdoff= [KNL]
-			Time to wait (s) after boot before inducing stall.
-
-	rcutorture.stat_interval= [KNL]
-			Time (s) between statistics printk()s.
-
-	rcutorture.stutter= [KNL]
-			Time (s) to stutter testing, for example, specifying
-			five seconds causes the test to run for five seconds,
-			wait for five seconds, and so on.  This tests RCU's
-			ability to transition abruptly to and from idle.
-
-	rcutorture.test_boost= [KNL]
-			Test RCU priority boosting?  0=no, 1=maybe, 2=yes.
-			"Maybe" means test if the RCU implementation
-			under test support RCU priority boosting.
-
-	rcutorture.test_boost_duration= [KNL]
-			Duration (s) of each individual boost test.
-
-	rcutorture.test_boost_interval= [KNL]
-			Interval (s) between each boost test.
-
-	rcutorture.test_no_idle_hz= [KNL]
-			Test RCU's dyntick-idle handling.  See also the
-			rcutorture.shuffle_interval parameter.
-
-	rcutorture.torture_runnable= [BOOT]
-			Start rcutorture running at boot time.
-
-	rcutorture.torture_type= [KNL]
-			Specify the RCU implementation to test.
-
-	rcutorture.verbose= [KNL]
-			Enable additional printk() statements.
-
-	rcupdate.rcu_cpu_stall_suppress= [KNL]
-			Suppress RCU CPU stall warning messages.
-
-	rcupdate.rcu_cpu_stall_timeout= [KNL]
-			Set timeout for RCU CPU stall warning messages.
-
-	rcupdate.rcu_expedited= [KNL]
-			Use expedited grace-period primitives, for
-			example, synchronize_rcu_expedited() instead
-			of synchronize_rcu().  This reduces latency,
-			but can increase CPU utilization, degrade
-			real-time latency, and degrade energy efficiency.
-			No effect on CONFIG_TINY_RCU kernels.
-
-	rcupdate.rcu_normal= [KNL]
-			Use only normal grace-period primitives,
-			for example, synchronize_rcu() instead of
-			synchronize_rcu_expedited().  This improves
-			real-time latency, CPU utilization, and
-			energy efficiency, but can expose users to
-			increased grace-period latency.  This parameter
-			overrides rcupdate.rcu_expedited.  No effect on
-			CONFIG_TINY_RCU kernels.
-
-	rcupdate.rcu_normal_after_boot= [KNL]
-			Once boot has completed (that is, after
-			rcu_end_inkernel_boot() has been invoked), use
-			only normal grace-period primitives.  No effect
-			on CONFIG_TINY_RCU kernels.
-
-	rcupdate.rcu_task_stall_timeout= [KNL]
-			Set timeout in jiffies for RCU task stall warning
-			messages.  Disable with a value less than or equal
-			to zero.
-
-	rcupdate.rcu_self_test= [KNL]
-			Run the RCU early boot self tests
-
-	rcupdate.rcu_self_test_bh= [KNL]
-			Run the RCU bh early boot self tests
-
-	rcupdate.rcu_self_test_sched= [KNL]
-			Run the RCU sched early boot self tests
-
-	rdinit=		[KNL]
-			Format: <full_path>
-			Run specified binary instead of /init from the ramdisk,
-			used for early userspace startup. See initrd.
-
-	reboot=		[KNL]
-			Format (x86 or x86_64):
-				[w[arm] | c[old] | h[ard] | s[oft] | g[pio]] \
-				[[,]s[mp]#### \
-				[[,]b[ios] | a[cpi] | k[bd] | t[riple] | e[fi] | p[ci]] \
-				[[,]f[orce]
-			Where reboot_mode is one of warm (soft) or cold (hard) or gpio,
-			      reboot_type is one of bios, acpi, kbd, triple, efi, or pci,
-			      reboot_force is either force or not specified,
-			      reboot_cpu is s[mp]#### with #### being the processor
-					to be used for rebooting.
-
-	relax_domain_level=
-			[KNL, SMP] Set scheduler's default relax_domain_level.
-			See Documentation/cgroup-v1/cpusets.txt.
-
-	relative_sleep_states=
-			[SUSPEND] Use sleep state labeling where the deepest
-			state available other than hibernation is always "mem".
-			Format: { "0" | "1" }
-			0 -- Traditional sleep state labels.
-			1 -- Relative sleep state labels.
-
-	reserve=	[KNL,BUGS] Force the kernel to ignore some iomem area
-
-	reservetop=	[X86-32]
-			Format: nn[KMG]
-			Reserves a hole at the top of the kernel virtual
-			address space.
-
-	reservelow=	[X86]
-			Format: nn[K]
-			Set the amount of memory to reserve for BIOS at
-			the bottom of the address space.
-
-	reset_devices	[KNL] Force drivers to reset the underlying device
-			during initialization.
-
-	resume=		[SWSUSP]
-			Specify the partition device for software suspend
-			Format:
-			{/dev/<dev> | PARTUUID=<uuid> | <int>:<int> | <hex>}
-
-	resume_offset=	[SWSUSP]
-			Specify the offset from the beginning of the partition
-			given by "resume=" at which the swap header is located,
-			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.
-		nocompress	Don't compress/decompress hibernation images.
-		no		Disable hibernation and resume.
-		protect_image	Turn on image protection during restoration
-				(that will set all pages holding image data
-				during restoration read-only).
-
-	retain_initrd	[RAM] Keep initrd memory after extraction
-
-	rfkill.default_state=
-		0	"airplane mode".  All wifi, bluetooth, wimax, gps, fm,
-			etc. communication is blocked by default.
-		1	Unblocked.
-
-	rfkill.master_switch_mode=
-		0	The "airplane mode" button does nothing.
-		1	The "airplane mode" button toggles between everything
-			blocked and the previous configuration.
-		2	The "airplane mode" button toggles between everything
-			blocked and everything unblocked.
-
-	rhash_entries=	[KNL,NET]
-			Set number of hash buckets for route cache
-
-	ro		[KNL] Mount root device read-only on boot
-
-	rodata=		[KNL]
-		on	Mark read-only kernel memory as read-only (default).
-		off	Leave read-only kernel memory writable for debugging.
-
-	rockchip.usb_uart
-			Enable the uart passthrough on the designated usb port
-			on Rockchip SoCs. When active, the signals of the
-			debug-uart get routed to the D+ and D- pins of the usb
-			port and the regular usb controller gets disabled.
-
-	root=		[KNL] Root filesystem
-			See name_to_dev_t comment in init/do_mounts.c.
-
-	rootdelay=	[KNL] Delay (in seconds) to pause before attempting to
-			mount the root filesystem
-
-	rootflags=	[KNL] Set root filesystem mount option string
-
-	rootfstype=	[KNL] Set root filesystem type
-
-	rootwait	[KNL] Wait (indefinitely) for root device to show up.
-			Useful for devices that are detected asynchronously
-			(e.g. USB and MMC devices).
-
-	rproc_mem=nn[KMG][@address]
-			[KNL,ARM,CMA] Remoteproc physical memory block.
-			Memory area to be used by remote processor image,
-			managed by CMA.
-
-	rw		[KNL] Mount root device read-write on boot
-
-	S		[KNL] Run init in single mode
-
-	s390_iommu=	[HW,S390]
-			Set s390 IOTLB flushing mode
-		strict
-			With strict flushing every unmap operation will result in
-			an IOTLB flush. Default is lazy flushing before reuse,
-			which is faster.
-
-	sa1100ir	[NET]
-			See drivers/net/irda/sa1100_ir.c.
-
-	sbni=		[NET] Granch SBNI12 leased line adapter
-
-	sched_debug	[KNL] Enables verbose scheduler debug messages.
-
-	schedstats=	[KNL,X86] Enable or disable scheduled statistics.
-			Allowed values are enable and disable. This feature
-			incurs a small amount of overhead in the scheduler
-			but is useful for debugging and performance tuning.
-
-	skew_tick=	[KNL] Offset the periodic timer tick per cpu to mitigate
-			xtime_lock contention on larger systems, and/or RCU lock
-			contention on all systems with CONFIG_MAXSMP set.
-			Format: { "0" | "1" }
-			0 -- disable. (may be 1 via CONFIG_CMDLINE="skew_tick=1"
-			1 -- enable.
-			Note: increases power consumption, thus should only be
-			enabled if running jitter sensitive (HPC/RT) workloads.
-
-	security=	[SECURITY] Choose a security module to enable at boot.
-			If this boot parameter is not specified, only the first
-			security module asking for security registration will be
-			loaded. An invalid security module name will be treated
-			as if no module has been chosen.
-
-	selinux=	[SELINUX] Disable or enable SELinux at boot time.
-			Format: { "0" | "1" }
-			See security/selinux/Kconfig help text.
-			0 -- disable.
-			1 -- enable.
-			Default value is set via kernel config option.
-			If enabled at boot time, /selinux/disable can be used
-			later to disable prior to initial policy load.
-
-	apparmor=	[APPARMOR] Disable or enable AppArmor at boot time
-			Format: { "0" | "1" }
-			See security/apparmor/Kconfig help text
-			0 -- disable.
-			1 -- enable.
-			Default value is set via kernel config option.
-
-	serialnumber	[BUGS=X86-32]
-
-	shapers=	[NET]
-			Maximal number of shapers.
-
-	show_msr=	[x86] show boot-time MSR settings
-			Format: { <integer> }
-			Show boot-time (BIOS-initialized) MSR settings.
-			The parameter means the number of CPUs to show,
-			for example 1 means boot CPU only.
-
-	simeth=		[IA-64]
-	simscsi=
-
-	slram=		[HW,MTD]
-
-	slab_nomerge	[MM]
-			Disable merging of slabs with similar size. May be
-			necessary if there is some reason to distinguish
-			allocs to different slabs. Debug options disable
-			merging on their own.
-			For more information see Documentation/vm/slub.txt.
-
-	slab_max_order=	[MM, SLAB]
-			Determines the maximum allowed order for slabs.
-			A high setting may cause OOMs due to memory
-			fragmentation.  Defaults to 1 for systems with
-			more than 32MB of RAM, 0 otherwise.
-
-	slub_debug[=options[,slabs]]	[MM, SLUB]
-			Enabling slub_debug allows one to determine the
-			culprit if slab objects become corrupted. Enabling
-			slub_debug can create guard zones around objects and
-			may poison objects when not in use. Also tracks the
-			last alloc / free. For more information see
-			Documentation/vm/slub.txt.
-
-	slub_max_order= [MM, SLUB]
-			Determines the maximum allowed order for slabs.
-			A high setting may cause OOMs due to memory
-			fragmentation. For more information see
-			Documentation/vm/slub.txt.
-
-	slub_min_objects=	[MM, SLUB]
-			The minimum number of objects per slab. SLUB will
-			increase the slab order up to slub_max_order to
-			generate a sufficiently large slab able to contain
-			the number of objects indicated. The higher the number
-			of objects the smaller the overhead of tracking slabs
-			and the less frequently locks need to be acquired.
-			For more information see Documentation/vm/slub.txt.
-
-	slub_min_order=	[MM, SLUB]
-			Determines the minimum page order for slabs. Must be
-			lower than slub_max_order.
-			For more information see Documentation/vm/slub.txt.
-
-	slub_nomerge	[MM, SLUB]
-			Same with slab_nomerge. This is supported for legacy.
-			See slab_nomerge for more information.
-
-	smart2=		[HW]
-			Format: <io1>[,<io2>[,...,<io8>]]
-
-	smsc-ircc2.nopnp	[HW] Don't use PNP to discover SMC devices
-	smsc-ircc2.ircc_cfg=	[HW] Device configuration I/O port
-	smsc-ircc2.ircc_sir=	[HW] SIR base I/O port
-	smsc-ircc2.ircc_fir=	[HW] FIR base I/O port
-	smsc-ircc2.ircc_irq=	[HW] IRQ line
-	smsc-ircc2.ircc_dma=	[HW] DMA channel
-	smsc-ircc2.ircc_transceiver= [HW] Transceiver type:
-				0: Toshiba Satellite 1800 (GP data pin select)
-				1: Fast pin select (default)
-				2: ATC IRMode
-
-	smt		[KNL,S390] Set the maximum number of threads (logical
-			CPUs) to use per physical CPU on systems capable of
-			symmetric multithreading (SMT). Will be capped to the
-			actual hardware limit.
-			Format: <integer>
-			Default: -1 (no limit)
-
-	softlockup_panic=
-			[KNL] Should the soft-lockup detector generate panics.
-			Format: <integer>
-
-	softlockup_all_cpu_backtrace=
-			[KNL] Should the soft-lockup detector generate
-			backtraces on all cpus.
-			Format: <integer>
-
-	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
-			See Documentation/laptops/sonypi.txt
-
-	spia_io_base=	[HW,MTD]
-	spia_fio_base=
-	spia_pedr=
-	spia_peddr=
-
-	stacktrace	[FTRACE]
-			Enabled the stack tracer on boot up.
-
-	stacktrace_filter=[function-list]
-			[FTRACE] Limit the functions that the stack tracer
-			will trace at boot up. function-list is a comma separated
-			list of functions. This list can be changed at run
-			time by the stack_trace_filter file in the debugfs
-			tracing directory. Note, this enables stack tracing
-			and the stacktrace above is not needed.
-
-	sti=		[PARISC,HW]
-			Format: <num>
-			Set the STI (builtin display/keyboard on the HP-PARISC
-			machines) console (graphic card) which should be used
-			as the initial boot-console.
-			See also comment in drivers/video/console/sticore.c.
-
-	sti_font=	[HW]
-			See comment in drivers/video/console/sticore.c.
-
-	stifb=		[HW]
-			Format: bpp:<bpp1>[:<bpp2>[:<bpp3>...]]
-
-	sunrpc.min_resvport=
-	sunrpc.max_resvport=
-			[NFS,SUNRPC]
-			SunRPC servers often require that client requests
-			originate from a privileged port (i.e. a port in the
-			range 0 < portnr < 1024).
-			An administrator who wishes to reserve some of these
-			ports for other uses may adjust the range that the
-			kernel's sunrpc client considers to be privileged
-			using these two parameters to set the minimum and
-			maximum port values.
-
-	sunrpc.svc_rpc_per_connection_limit=
-			[NFS,SUNRPC]
-			Limit the number of requests that the server will
-			process in parallel from a single connection.
-			The default value is 0 (no limit).
-
-	sunrpc.pool_mode=
-			[NFS]
-			Control how the NFS server code allocates CPUs to
-			service thread pools.  Depending on how many NICs
-			you have and where their interrupts are bound, this
-			option will affect which CPUs will do NFS serving.
-			Note: this parameter cannot be changed while the
-			NFS server is running.
-
-			auto	    the server chooses an appropriate mode
-				    automatically using heuristics
-			global	    a single global pool contains all CPUs
-			percpu	    one pool for each CPU
-			pernode	    one pool for each NUMA node (equivalent
-				    to global on non-NUMA machines)
-
-	sunrpc.tcp_slot_table_entries=
-	sunrpc.udp_slot_table_entries=
-			[NFS,SUNRPC]
-			Sets the upper limit on the number of simultaneous
-			RPC calls that can be sent from the client to a
-			server. Increasing these values may allow you to
-			improve throughput, but will also increase the
-			amount of memory reserved for use by the client.
-
-	suspend.pm_test_delay=
-			[SUSPEND]
-			Sets the number of seconds to remain in a suspend test
-			mode before resuming the system (see
-			/sys/power/pm_test). Only available when CONFIG_PM_DEBUG
-			is set. Default value is 5.
-
-	swapaccount=[0|1]
-			[KNL] Enable accounting of swap in memory resource
-			controller if no parameter or 1 is given or disable
-			it if 0 is given (See Documentation/cgroup-v1/memory.txt)
-
-	swiotlb=	[ARM,IA-64,PPC,MIPS,X86]
-			Format: { <int> | force }
-			<int> -- Number of I/O TLB slabs
-			force -- force using of bounce buffers even if they
-			         wouldn't be automatically used by the kernel
-
-	switches=	[HW,M68k]
-
-	sysfs.deprecated=0|1 [KNL]
-			Enable/disable old style sysfs layout for old udev
-			on older distributions. When this option is enabled
-			very new udev will not work anymore. When this option
-			is disabled (or CONFIG_SYSFS_DEPRECATED not compiled)
-			in older udev will not work anymore.
-			Default depends on CONFIG_SYSFS_DEPRECATED_V2 set in
-			the kernel configuration.
-
-	sysrq_always_enabled
-			[KNL]
-			Ignore sysrq setting - this boot parameter will
-			neutralize any effect of /proc/sys/kernel/sysrq.
-			Useful for debugging.
-
-	tcpmhash_entries= [KNL,NET]
-			Set the number of tcp_metrics_hash slots.
-			Default value is 8192 or 16384 depending on total
-			ram pages. This is used to specify the TCP metrics
-			cache size. See Documentation/networking/ip-sysctl.txt
-			"tcp_no_metrics_save" section for more details.
-
-	tdfx=		[HW,DRM]
-
-	test_suspend=	[SUSPEND][,N]
-			Specify "mem" (for Suspend-to-RAM) or "standby" (for
-			standby suspend) or "freeze" (for suspend type freeze)
-			as the system sleep state during system startup with
-			the optional capability to repeat N number of times.
-			The system is woken from this state using a
-			wakeup-capable RTC alarm.
-
-	thash_entries=	[KNL,NET]
-			Set number of hash buckets for TCP connection
-
-	thermal.act=	[HW,ACPI]
-			-1: disable all active trip points in all thermal zones
-			<degrees C>: override all lowest active trip points
-
-	thermal.crt=	[HW,ACPI]
-			-1: disable all critical trip points in all thermal zones
-			<degrees C>: override all critical trip points
-
-	thermal.nocrt=	[HW,ACPI]
-			Set to disable actions on ACPI thermal zone
-			critical and hot trip points.
-
-	thermal.off=	[HW,ACPI]
-			1: disable ACPI thermal control
-
-	thermal.psv=	[HW,ACPI]
-			-1: disable all passive trip points
-			<degrees C>: override all passive trip points to this
-			value
-
-	thermal.tzp=	[HW,ACPI]
-			Specify global default ACPI thermal zone polling rate
-			<deci-seconds>: poll all this frequency
-			0: no polling (default)
-
-	threadirqs	[KNL]
-			Force threading of all interrupt handlers except those
-			marked explicitly IRQF_NO_THREAD.
-
-	tmem		[KNL,XEN]
-			Enable the Transcendent memory driver if built-in.
-
-	tmem.cleancache=0|1 [KNL, XEN]
-			Default is on (1). Disable the usage of the cleancache
-			API to send anonymous pages to the hypervisor.
-
-	tmem.frontswap=0|1 [KNL, XEN]
-			Default is on (1). Disable the usage of the frontswap
-			API to send swap pages to the hypervisor. If disabled
-			the selfballooning and selfshrinking are force disabled.
-
-	tmem.selfballooning=0|1 [KNL, XEN]
-			Default is on (1). Disable the driving of swap pages
-			to the hypervisor.
-
-	tmem.selfshrinking=0|1 [KNL, XEN]
-			Default is on (1). Partial swapoff that immediately
-			transfers pages from Xen hypervisor back to the
-			kernel based on different criteria.
-
-	topology=	[S390]
-			Format: {off | on}
-			Specify if the kernel should make use of the cpu
-			topology information if the hardware supports this.
-			The scheduler will make use of this information and
-			e.g. base its process migration decisions on it.
-			Default is on.
-
-	topology_updates= [KNL, PPC, NUMA]
-			Format: {off}
-			Specify if the kernel should ignore (off)
-			topology updates sent by the hypervisor to this
-			LPAR.
-
-	tp720=		[HW,PS2]
-
-	tpm_suspend_pcr=[HW,TPM]
-			Format: integer pcr id
-			Specify that at suspend time, the tpm driver
-			should extend the specified pcr with zeros,
-			as a workaround for some chips which fail to
-			flush the last written pcr on TPM_SaveState.
-			This will guarantee that all the other pcrs
-			are saved.
-
-	trace_buf_size=nn[KMG]
-			[FTRACE] will set tracing buffer size on each cpu.
-
-	trace_event=[event-list]
-			[FTRACE] Set and start specified trace events in order
-			to facilitate early boot debugging. The event-list is a
-			comma separated list of trace events to enable. See
-			also Documentation/trace/events.txt
-
-	trace_options=[option-list]
-			[FTRACE] Enable or disable tracer options at boot.
-			The option-list is a comma delimited list of options
-			that can be enabled or disabled just as if you were
-			to echo the option name into
-
-			    /sys/kernel/debug/tracing/trace_options
-
-			For example, to enable stacktrace option (to dump the
-			stack trace of each event), add to the command line:
-
-			      trace_options=stacktrace
-
-			See also Documentation/trace/ftrace.txt "trace options"
-			section.
-
-	tp_printk[FTRACE]
-			Have the tracepoints sent to printk as well as the
-			tracing ring buffer. This is useful for early boot up
-			where the system hangs or reboots and does not give the
-			option for reading the tracing buffer or performing a
-			ftrace_dump_on_oops.
-
-			To turn off having tracepoints sent to printk,
-			 echo 0 > /proc/sys/kernel/tracepoint_printk
-			Note, echoing 1 into this file without the
-			tracepoint_printk kernel cmdline option has no effect.
-
-			** CAUTION **
-
-			Having tracepoints sent to printk() and activating high
-			frequency tracepoints such as irq or sched, can cause
-			the system to live lock.
-
-	traceoff_on_warning
-			[FTRACE] enable this option to disable tracing when a
-			warning is hit. This turns off "tracing_on". Tracing can
-			be enabled again by echoing '1' into the "tracing_on"
-			file located in /sys/kernel/debug/tracing/
-
-			This option is useful, as it disables the trace before
-			the WARNING dump is called, which prevents the trace to
-			be filled with content caused by the warning output.
-
-			This option can also be set at run time via the sysctl
-			option:  kernel/traceoff_on_warning
-
-	transparent_hugepage=
-			[KNL]
-			Format: [always|madvise|never]
-			Can be used to control the default behavior of the system
-			with respect to transparent hugepages.
-			See Documentation/vm/transhuge.txt for more details.
-
-	tsc=		Disable clocksource stability checks for TSC.
-			Format: <string>
-			[x86] reliable: mark tsc clocksource as reliable, this
-			disables clocksource verification at runtime, as well
-			as the stability checks done at bootup.	Used to enable
-			high-resolution timer mode on older hardware, and in
-			virtualized environment.
-			[x86] noirqtime: Do not use TSC to do irq accounting.
-			Used to run time disable IRQ_TIME_ACCOUNTING on any
-			platforms where RDTSC is slow and this accounting
-			can add overhead.
-
-	turbografx.map[2|3]=	[HW,JOY]
-			TurboGraFX parallel port interface
-			Format:
-			<port#>,<js1>,<js2>,<js3>,<js4>,<js5>,<js6>,<js7>
-			See also Documentation/input/joystick-parport.txt
-
-	udbg-immortal	[PPC] When debugging early kernel crashes that
-			happen after console_init() and before a proper 
-			console driver takes over, this boot options might
-			help "seeing" what's going on.
-
-	uhash_entries=	[KNL,NET]
-			Set number of hash buckets for UDP/UDP-Lite connections
-
-	uhci-hcd.ignore_oc=
-			[USB] Ignore overcurrent events (default N).
-			Some badly-designed motherboards generate lots of
-			bogus events, for ports that aren't wired to
-			anything.  Set this parameter to avoid log spamming.
-			Note that genuine overcurrent events won't be
-			reported either.
-
-	unknown_nmi_panic
-			[X86] Cause panic on unknown NMI.
-
-	usbcore.authorized_default=
-			[USB] Default USB device authorization:
-			(default -1 = authorized except for wireless USB,
-			0 = not authorized, 1 = authorized)
-
-	usbcore.autosuspend=
-			[USB] The autosuspend time delay (in seconds) used
-			for newly-detected USB devices (default 2).  This
-			is the time required before an idle device will be
-			autosuspended.  Devices for which the delay is set
-			to a negative value won't be autosuspended at all.
-
-	usbcore.usbfs_snoop=
-			[USB] Set to log all usbfs traffic (default 0 = off).
-
-	usbcore.usbfs_snoop_max=
-			[USB] Maximum number of bytes to snoop in each URB
-			(default = 65536).
-
-	usbcore.blinkenlights=
-			[USB] Set to cycle leds on hubs (default 0 = off).
-
-	usbcore.old_scheme_first=
-			[USB] Start with the old device initialization
-			scheme (default 0 = off).
-
-	usbcore.usbfs_memory_mb=
-			[USB] Memory limit (in MB) for buffers allocated by
-			usbfs (default = 16, 0 = max = 2047).
-
-	usbcore.use_both_schemes=
-			[USB] Try the other device initialization scheme
-			if the first one fails (default 1 = enabled).
-
-	usbcore.initial_descriptor_timeout=
-			[USB] Specifies timeout for the initial 64-byte
-                        USB_REQ_GET_DESCRIPTOR request in milliseconds
-			(default 5000 = 5.0 seconds).
-
-	usbcore.nousb	[USB] Disable the USB subsystem
-
-	usbhid.mousepoll=
-			[USBHID] The interval which mice are to be polled at.
-
-	usb-storage.delay_use=
-			[UMS] The delay in seconds before a new device is
-			scanned for Logical Units (default 1).
-
-	usb-storage.quirks=
-			[UMS] A list of quirks entries to supplement or
-			override the built-in unusual_devs list.  List
-			entries are separated by commas.  Each entry has
-			the form VID:PID:Flags where VID and PID are Vendor
-			and Product ID values (4-digit hex numbers) and
-			Flags is a set of characters, each corresponding
-			to a common usb-storage quirk flag as follows:
-				a = SANE_SENSE (collect more than 18 bytes
-					of sense data);
-				b = BAD_SENSE (don't collect more than 18
-					bytes of sense data);
-				c = FIX_CAPACITY (decrease the reported
-					device capacity by one sector);
-				d = NO_READ_DISC_INFO (don't use
-					READ_DISC_INFO command);
-				e = NO_READ_CAPACITY_16 (don't use
-					READ_CAPACITY_16 command);
-				f = NO_REPORT_OPCODES (don't use report opcodes
-					command, uas only);
-				g = MAX_SECTORS_240 (don't transfer more than
-					240 sectors at a time, uas only);
-				h = CAPACITY_HEURISTICS (decrease the
-					reported device capacity by one
-					sector if the number is odd);
-				i = IGNORE_DEVICE (don't bind to this
-					device);
-				j = NO_REPORT_LUNS (don't use report luns
-					command, uas only);
-				l = NOT_LOCKABLE (don't try to lock and
-					unlock ejectable media);
-				m = MAX_SECTORS_64 (don't transfer more
-					than 64 sectors = 32 KB at a time);
-				n = INITIAL_READ10 (force a retry of the
-					initial READ(10) command);
-				o = CAPACITY_OK (accept the capacity
-					reported by the device);
-				p = WRITE_CACHE (the device cache is ON
-					by default);
-				r = IGNORE_RESIDUE (the device reports
-					bogus residue values);
-				s = SINGLE_LUN (the device has only one
-					Logical Unit);
-				t = NO_ATA_1X (don't allow ATA(12) and ATA(16)
-					commands, uas only);
-				u = IGNORE_UAS (don't bind to the uas driver);
-				w = NO_WP_DETECT (don't test whether the
-					medium is write-protected).
-				y = ALWAYS_SYNC (issue a SYNCHRONIZE_CACHE
-					even if the device claims no cache)
-			Example: quirks=0419:aaf5:rl,0421:0433:rc
-
-	user_debug=	[KNL,ARM]
-			Format: <int>
-			See arch/arm/Kconfig.debug help text.
-				 1 - undefined instruction events
-				 2 - system calls
-				 4 - invalid data aborts
-				 8 - SIGSEGV faults
-				16 - SIGBUS faults
-			Example: user_debug=31
-
-	userpte=
-			[X86] Flags controlling user PTE allocations.
-
-				nohigh = do not allocate PTE pages in
-					HIGHMEM regardless of setting
-					of CONFIG_HIGHPTE.
-
-	vdso=		[X86,SH]
-			On X86_32, this is an alias for vdso32=.  Otherwise:
-
-			vdso=1: enable VDSO (the default)
-			vdso=0: disable VDSO mapping
-
-	vdso32=		[X86] Control the 32-bit vDSO
-			vdso32=1: enable 32-bit VDSO
-			vdso32=0 or vdso32=2: disable 32-bit VDSO
-
-			See the help text for CONFIG_COMPAT_VDSO for more
-			details.  If CONFIG_COMPAT_VDSO is set, the default is
-			vdso32=0; otherwise, the default is vdso32=1.
-
-			For compatibility with older kernels, vdso32=2 is an
-			alias for vdso32=0.
-
-			Try vdso32=0 if you encounter an error that says:
-			dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!
-
-	vector=		[IA-64,SMP]
-			vector=percpu: enable percpu vector domain
-
-	video=		[FB] Frame buffer configuration
-			See Documentation/fb/modedb.txt.
-
-	video.brightness_switch_enabled= [0,1]
-			If set to 1, on receiving an ACPI notify event
-			generated by hotkey, video driver will adjust brightness
-			level and then send out the event to user space through
-			the allocated input device; If set to 0, video driver
-			will only send out the event without touching backlight
-			brightness level.
-			default: 1
-
-	virtio_mmio.device=
-			[VMMIO] Memory mapped virtio (platform) device.
-
-				<size>@<baseaddr>:<irq>[:<id>]
-			where:
-				<size>     := size (can use standard suffixes
-						like K, M and G)
-				<baseaddr> := physical base address
-				<irq>      := interrupt number (as passed to
-						request_irq())
-				<id>       := (optional) platform device id
-			example:
-				virtio_mmio.device=1K@0x100b0000:48:7
-
-			Can be used multiple times for multiple devices.
-
-	vga=		[BOOT,X86-32] Select a particular video mode
-			See Documentation/x86/boot.txt and
-			Documentation/svga.txt.
-			Use vga=ask for menu.
-			This is actually a boot loader parameter; the value is
-			passed to the kernel using a special protocol.
-
-	vmalloc=nn[KMG]	[KNL,BOOT] Forces the vmalloc area to have an exact
-			size of <nn>. This can be used to increase the
-			minimum size (128MB on x86). It can also be used to
-			decrease the size and leave more room for directly
-			mapped kernel RAM.
-
-	vmhalt=		[KNL,S390] Perform z/VM CP command after system halt.
-			Format: <command>
-
-	vmpanic=	[KNL,S390] Perform z/VM CP command after kernel panic.
-			Format: <command>
-
-	vmpoff=		[KNL,S390] Perform z/VM CP command after power off.
-			Format: <command>
-
-	vsyscall=	[X86-64]
-			Controls the behavior of vsyscalls (i.e. calls to
-			fixed addresses of 0xffffffffff600x00 from legacy
-			code).  Most statically-linked binaries and older
-			versions of glibc use these calls.  Because these
-			functions are at fixed addresses, they make nice
-			targets for exploits that can control RIP.
-
-			emulate     [default] Vsyscalls turn into traps and are
-			            emulated reasonably safely.
-
-			native      Vsyscalls are native syscall instructions.
-			            This is a little bit faster than trapping
-			            and makes a few dynamic recompilers work
-			            better than they would in emulation mode.
-			            It also makes exploits much easier to write.
-
-			none        Vsyscalls don't work at all.  This makes
-			            them quite hard to use for exploits but
-			            might break your system.
-
-	vt.color=	[VT] Default text color.
-			Format: 0xYX, X = foreground, Y = background.
-			Default: 0x07 = light gray on black.
-
-	vt.cur_default=	[VT] Default cursor shape.
-			Format: 0xCCBBAA, where AA, BB, and CC are the same as
-			the parameters of the <Esc>[?A;B;Cc escape sequence;
-			see VGA-softcursor.txt. Default: 2 = underline.
-
-	vt.default_blu=	[VT]
-			Format: <blue0>,<blue1>,<blue2>,...,<blue15>
-			Change the default blue palette of the console.
-			This is a 16-member array composed of values
-			ranging from 0-255.
-
-	vt.default_grn=	[VT]
-			Format: <green0>,<green1>,<green2>,...,<green15>
-			Change the default green palette of the console.
-			This is a 16-member array composed of values
-			ranging from 0-255.
-
-	vt.default_red=	[VT]
-			Format: <red0>,<red1>,<red2>,...,<red15>
-			Change the default red palette of the console.
-			This is a 16-member array composed of values
-			ranging from 0-255.
-
-	vt.default_utf8=
-			[VT]
-			Format=<0|1>
-			Set system-wide default UTF-8 mode for all tty's.
-			Default is 1, i.e. UTF-8 mode is enabled for all
-			newly opened terminals.
-
-	vt.global_cursor_default=
-			[VT]
-			Format=<-1|0|1>
-			Set system-wide default for whether a cursor
-			is shown on new VTs. Default is -1,
-			i.e. cursors will be created by default unless
-			overridden by individual drivers. 0 will hide
-			cursors, 1 will display them.
-
-	vt.italic=	[VT] Default color for italic text; 0-15.
-			Default: 2 = green.
-
-	vt.underline=	[VT] Default color for underlined text; 0-15.
-			Default: 3 = cyan.
-
-	watchdog timers	[HW,WDT] For information on watchdog timers,
-			see Documentation/watchdog/watchdog-parameters.txt
-			or other driver-specific files in the
-			Documentation/watchdog/ directory.
-
-	workqueue.watchdog_thresh=
-			If CONFIG_WQ_WATCHDOG is configured, workqueue can
-			warn stall conditions and dump internal state to
-			help debugging.  0 disables workqueue stall
-			detection; otherwise, it's the stall threshold
-			duration in seconds.  The default value is 30 and
-			it can be updated at runtime by writing to the
-			corresponding sysfs file.
-
-	workqueue.disable_numa
-			By default, all work items queued to unbound
-			workqueues are affine to the NUMA nodes they're
-			issued on, which results in better behavior in
-			general.  If NUMA affinity needs to be disabled for
-			whatever reason, this option can be used.  Note
-			that this also can be controlled per-workqueue for
-			workqueues visible under /sys/bus/workqueue/.
-
-	workqueue.power_efficient
-			Per-cpu workqueues are generally preferred because
-			they show better performance thanks to cache
-			locality; unfortunately, per-cpu workqueues tend to
-			be more power hungry than unbound workqueues.
-
-			Enabling this makes the per-cpu workqueues which
-			were observed to contribute significantly to power
-			consumption unbound, leading to measurably lower
-			power usage at the cost of small performance
-			overhead.
-
-			The default value of this parameter is determined by
-			the config option CONFIG_WQ_POWER_EFFICIENT_DEFAULT.
-
-	workqueue.debug_force_rr_cpu
-			Workqueue used to implicitly guarantee that work
-			items queued without explicit CPU specified are put
-			on the local CPU.  This guarantee is no longer true
-			and while local CPU is still preferred work items
-			may be put on foreign CPUs.  This debug option
-			forces round-robin CPU selection to flush out
-			usages which depend on the now broken guarantee.
-			When enabled, memory and cache locality will be
-			impacted.
-
-	x2apic_phys	[X86-64,APIC] Use x2apic physical mode instead of
-			default x2apic cluster mode on platforms
-			supporting x2apic.
-
-	x86_intel_mid_timer= [X86-32,APBT]
-			Choose timer option for x86 Intel MID platform.
-			Two valid options are apbt timer only and lapic timer
-			plus one apbt timer for broadcast timer.
-			x86_intel_mid_timer=apbt_only | lapic_and_apbt
-
-	xen_512gb_limit		[KNL,X86-64,XEN]
-			Restricts the kernel running paravirtualized under Xen
-			to use only up to 512 GB of RAM. The reason to do so is
-			crash analysis tools and Xen tools for doing domain
-			save/restore/migration must be enabled to handle larger
-			domains.
-
-	xen_emul_unplug=		[HW,X86,XEN]
-			Unplug Xen emulated devices
-			Format: [unplug0,][unplug1]
-			ide-disks -- unplug primary master IDE devices
-			aux-ide-disks -- unplug non-primary-master IDE devices
-			nics -- unplug network devices
-			all -- unplug all emulated devices (NICs and IDE disks)
-			unnecessary -- unplugging emulated devices is
-				unnecessary even if the host did not respond to
-				the unplug protocol
-			never -- do not unplug even if version check succeeds
-
-	xen_nopvspin	[X86,XEN]
-			Disables the ticketlock slowpath using Xen PV
-			optimizations.
-
-	xen_nopv	[X86]
-			Disables the PV optimizations forcing the HVM guest to
-			run as generic HVM guest with no PV drivers.
-
-	xirc2ps_cs=	[NET,PCMCIA]
-			Format:
-			<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
-
-______________________________________________________________________
-
-TODO:
-
-	Add more DRM drivers.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/kernel-per-CPU-kthreads.txt linux-libre-4.10-rc8-gnu/Documentation/kernel-per-CPU-kthreads.txt
--- linux-libre-4.9-gnu/Documentation/kernel-per-CPU-kthreads.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/kernel-per-CPU-kthreads.txt	2017-02-12 16:03:20.000000000 -0500
@@ -264,7 +264,7 @@ To reduce its OS jitter, do at least one
 	kthreads from being created in the first place.
 2.	Boot with "nosoftlockup=0", which will also prevent these kthreads
 	from being created.  Other related watchdog and softlockup boot
-	parameters may be found in Documentation/kernel-parameters.txt
+	parameters may be found in Documentation/admin-guide/kernel-parameters.rst
 	and Documentation/watchdog/watchdog-parameters.txt.
 3.	Echo a zero to /proc/sys/kernel/watchdog to disable the
 	watchdog timer.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ko_KR/HOWTO linux-libre-4.10-rc8-gnu/Documentation/ko_KR/HOWTO
--- linux-libre-4.9-gnu/Documentation/ko_KR/HOWTO	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ko_KR/HOWTO	1969-12-31 19:00:00.000000000 -0500
@@ -1,585 +0,0 @@
-NOTE:
-This is a version of Documentation/HOWTO translated into korean
-This document is maintained by Minchan Kim <minchan@kernel.org>
-If you find any difference between this document and the original file or
-a problem with the translation, please contact the maintainer of this file.
-
-Please also note that the purpose of this file is to be easier to
-read for non English (read: korean) speakers and is not intended as
-a fork. So if you have any comments or updates for this file please
-try to update the original English file first.
-
-==================================
-이 문서는
-Documentation/HOWTO
-의 한글 번역입니다.
-
-역자： 김민찬 <minchan@kernel.org>
-감수： 이제이미 <jamee.lee@samsung.com>
-==================================
-
-어떻게 리눅스 커널 개발을 하는가
----------------------------------
-
-이 문서는 커널 개발에 있어 가장 중요한 문서이다. 이 문서는
-리눅스 커널 개발자가 되는 법과 리눅스 커널 개발 커뮤니티와 일하는
-법을 담고있다. 커널 프로그래밍의 기술적인 측면과 관련된 내용들은
-포함하지 않으려고 하였지만 올바른 길로 여러분을 안내하는 데는 도움이
-될 것이다.
-
-이 문서에서 오래된 것을 발견하면 문서의 아래쪽에 나열된 메인테이너에게
-패치를 보내달라.
-
-
-소개
-----
-
-자, 여러분은 리눅스 커널 개발자가 되는 법을 배우고 싶은가? 아니면
-상사로부터"이 장치를 위한 리눅스 드라이버를 작성하시오"라는 말을
-들었는가? 이 문서의 목적은 여러분이 겪게 될 과정과 커뮤니티와 협력하는
-법을 조언하여 여러분의 목적을 달성하기 위해 필요한 것 모두를 알려주기
-위함이다.
-
-커널은 대부분은 C로 작성되어 있고 몇몇 아키텍쳐의 의존적인 부분은
-어셈블리로 작성되어 있다. 커널 개발을 위해 C를 잘 이해하고 있어야 한다.
-여러분이 특정 아키텍쳐의 low-level 개발을 할 것이 아니라면
-어셈블리(특정 아키텍쳐)는 잘 알아야 할 필요는 없다.
-다음의 참고서적들은 기본에 충실한 C 교육이나 수년간의 경험에 견주지는
-못하지만 적어도 참고 용도로는 좋을 것이다
- - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
- - "Practical C Programming" by Steve Oualline [O'Reilly]
- - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
-
-커널은 GNU C와 GNU 툴체인을 사용하여 작성되었다. 이 툴들은 ISO C89 표준을
-따르는 반면 표준에 있지 않은 많은 확장기능도 가지고 있다. 커널은 표준 C
-라이브러리와는 관계없이 freestanding C 환경이어서 C 표준의 일부는
-지원되지 않는다. 임의의 long long 나누기나 floating point는 지원되지 않는다.
-때론 이런 이유로 커널이 그런 확장 기능을 가진 툴체인을 가지고 만들어졌다는
-것이 이해하기 어려울 수도 있고 게다가 불행하게도 그런 것을 정확하게 설명하는
-어떤 참고문서도 있지 않다. 정보를 얻기 위해서는 gcc info (`info gcc`)페이지를
-살펴보라.
-
-여러분은 기존의 개발 커뮤니티와 협력하는 법을 배우려고 하고 있다는 것을
-기억하라. 코딩, 스타일, 함수에 관한 훌륭한 표준을 가진 사람들이 모인
-다양한 그룹이 있다. 이 표준들은 오랜동안 크고 지역적으로 분산된 팀들에
-의해 가장 좋은 방법으로 일하기 위하여 찾은 것을 기초로 만들어져 왔다.
-그 표준들은 문서화가 잘 되어있기 때문에 가능한한 미리 많은 표준들에
-관하여 배우려고 시도하라. 다른 사람들은 여러분이나 여러분의 회사가
-일하는 방식에 적응하는 것을 원하지는 않는다.
-
-
-법적 문제
----------
-
-리눅스 커널 소스 코드는 GPL로 배포(release)되었다. 소스트리의 메인
-디렉토리에 있는 라이센스에 관하여 상세하게 쓰여 있는 COPYING이라는
-파일을 봐라. 여러분이 라이센스에 관한 더 깊은 문제를 가지고 있다면
-리눅스 커널 메일링 리스트에 묻지말고 변호사와 연락하라. 메일링
-리스트들에 있는 사람들은 변호사가 아니기 때문에 법적 문제에 관하여
-그들의 말에 의지해서는 안된다.
-
-GPL에 관한 잦은 질문들과 답변들은 다음을 참조하라.
-    http://www.gnu.org/licenses/gpl-faq.html
-
-
-문서
-----
-
-리눅스 커널 소스 트리는 커널 커뮤니티와 협력하는 법을 배우기위해 훌륭한
-다양한 문서들을 가지고 있다. 새로운 기능들이 커널에 들어가게 될 때,
-그 기능을 어떻게 사용하는지에 관한 설명을 위하여 새로운 문서 파일을
-추가하는 것을 권장한다. 커널이 유저스페이스로 노출하는 인터페이스를
-변경하게 되면 변경을 설명하는 메뉴얼 페이지들에 대한 패치나 정보를
-mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다.
-
-다음은 커널 소스 트리에 있는 읽어야 할 파일들의 리스트이다.
-  README
-    이 파일은 리눅스 커널에 관하여 간단한 배경 설명과 커널을 설정하고
-    빌드하기 위해 필요한 것을 설명한다. 커널에 입문하는 사람들은 여기서
-    시작해야 한다.
-
-  Documentation/Changes
-    이 파일은 커널을 성공적으로 빌드하고 실행시키기 위해 필요한 다양한
-    소프트웨어 패키지들의 최소 버젼을 나열한다.
-
-  Documentation/CodingStyle
-    이 문서는 리눅스 커널 코딩 스타일과 그렇게 한 몇몇 이유를 설명한다.
-    모든 새로운 코드는 이 문서에 가이드라인들을 따라야 한다. 대부분의
-    메인테이너들은 이 규칙을 따르는 패치들만을 받아들일 것이고 많은 사람들이
-    그 패치가 올바른 스타일일 경우만 코드를 검토할 것이다.
-
-  Documentation/SubmittingPatches
-  Documentation/SubmittingDrivers
-    이 파일들은 성공적으로 패치를 만들고 보내는 법을 다음의 내용들로
-    굉장히 상세히 설명하고 있다(그러나 다음으로 한정되진 않는다).
-       - Email 내용들
-       - Email 양식
-       - 그것을 누구에게 보낼지
-    이러한 규칙들을 따르는 것이 성공(역자주: 패치가 받아들여 지는 것)을
-    보장하진 않는다(왜냐하면 모든 패치들은 내용과 스타일에 관하여
-    면밀히 검토되기 때문이다). 그러나 규칙을 따르지 않는다면 거의
-    성공하지도 못할 것이다.
-
-    올바른 패치들을 만드는 법에 관한 훌륭한 다른 문서들이 있다.
-    "The Perfect Patch"
-        http://www.ozlabs.org/~akpm/stuff/tpp.txt
-    "Linux kernel patch submission format"
-        http://linux.yyz.us/patch-format.html
-
-   Documentation/stable_api_nonsense.txt
-    이 문서는 의도적으로 커널이 불변하는 API를 갖지 않도록 결정한
-    이유를 설명하며 다음과 같은 것들을 포함한다.
-       - 서브시스템 shim-layer(호환성을 위해?)
-       - 운영체제들간의 드라이버 이식성
-       - 커널 소스 트리내에 빠른 변화를 늦추는 것(또는 빠른 변화를 막는 것)
-    이 문서는 리눅스 개발 철학을 이해하는데 필수적이며 다른 운영체제에서
-    리눅스로 전향하는 사람들에게는 매우 중요하다.
-
-
-  Documentation/SecurityBugs
-    여러분들이 리눅스 커널의 보안 문제를 발견했다고 생각한다면 이 문서에
-    나온 단계에 따라서 커널 개발자들에게 알리고 그 문제를 해결할 수 있도록
-    도와 달라.
-
-  Documentation/ManagementStyle
-    이 문서는 리눅스 커널 메인테이너들이 그들의 방법론에 녹아 있는
-    정신을 어떻게 공유하고 운영하는지를 설명한다. 이것은 커널 개발에 입문하는
-    모든 사람들(또는 커널 개발에 작은 호기심이라도 있는 사람들)이
-    읽어야 할 중요한 문서이다. 왜냐하면 이 문서는 커널 메인테이너들의
-    독특한 행동에 관하여 흔히 있는 오해들과 혼란들을 해소하고 있기
-    때문이다.
-
-  Documentation/stable_kernel_rules.txt
-    이 문서는 안정적인 커널 배포가 이루어지는 규칙을 설명하고 있으며
-    여러분들이 이러한 배포들 중 하나에 변경을 하길 원한다면
-    무엇을 해야 하는지를 설명한다.
-
-  Documentation/kernel-docs.txt
-    커널 개발에 관계된 외부 문서의 리스트이다. 커널 내의 포함된 문서들
-    중에 여러분이 찾고 싶은 문서를 발견하지 못할 경우 이 리스트를
-    살펴보라.
-
-  Documentation/applying-patches.txt
-    패치가 무엇이며 그것을 커널의 다른 개발 브랜치들에 어떻게
-    적용하는지에 관하여 자세히 설명하고 있는 좋은 입문서이다.
-
-커널은 소스 코드 그 자체에서 자동적으로 만들어질 수 있는 많은 문서들을
-가지고 있다. 이것은 커널 내의 API에 대한 모든 설명, 그리고 락킹을
-올바르게 처리하는 법에 관한 규칙을 포함하고 있다. 이 문서는
-Documentation/DocBook/ 디렉토리 내에서 만들어지며 PDF, Postscript, HTML,
-그리고 man 페이지들로 다음과 같이 실행하여 만들어 진다.
-         make pdfdocs
-         make psdocs
-         make htmldocs
-         make mandocs
-각각의 명령을 메인 커널 소스 디렉토리로부터 실행한다.
-
-
-커널 개발자가 되는 것
----------------------
-
-여러분이 리눅스 커널 개발에 관하여 아무것도 모른다면 Linux KernelNewbies
-프로젝트를 봐야 한다.
-    http://kernelnewbies.org
-그곳은 거의 모든 종류의 기본적인 커널 개발 질문들(질문하기 전에 먼저
-아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할 수 있는 도움이
-될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할 수 있는 IRC 채널도
-가지고 있으며 리눅스 커널 개발을 배우는 데 유용한 문서들을 보유하고 있다.
-
-웹사이트는 코드구성, 서브시스템들, 그리고 현재 프로젝트들
-(트리 내, 외부에 존재하는)에 관한 기본적인 정보들을 가지고 있다. 또한
-그곳은 커널 컴파일이나 패치를 하는 법과 같은 기본적인 것들을  설명한다.
-
-여러분이 어디서 시작해야 할진 모르지만 커널 개발 커뮤니티에 참여할 수
-있는 일들을 찾길 원한다면 리눅스 커널 Janitor 프로젝트를 살펴봐라.
-	http://kernelnewbies.org/KernelJanitors
-그곳은 시작하기에 훌륭한 장소이다. 그곳은 리눅스 커널 소스 트리내에
-간단히 정리되고 수정될 수 있는 문제들에 관하여 설명한다. 여러분은 이
-프로젝트를 대표하는 개발자들과 일하면서 자신의 패치를 리눅스 커널 트리에
-반영하기 위한 기본적인 것들을 배우게 될것이며 여러분이 아직 아이디어를
-가지고 있지 않다면 다음에 무엇을 해야할지에 관한 방향을 배울 수 있을
-것이다.
-
-여러분들이 이미 커널 트리에 반영하길 원하는 코드 묶음을 가지고 있지만
-올바른 포맷으로 포장하는데 도움이 필요하다면 그러한 문제를 돕기 위해
-만들어진 kernel-mentors 프로젝트가 있다. 그곳은 메일링 리스트이며
-다음에서 참조할 수 있다.
-         http://selenic.com/mailman/listinfo/kernel-mentors
-
-리눅스 커널 코드에 실제 변경을 하기 전에 반드시 그 코드가 어떻게
-동작하는지 이해하고 있어야 한다. 코드를 분석하기 위하여 특정한 툴의
-도움을 빌려서라도 코드를 직접 읽는 것보다 좋은 것은 없다(대부분의
-자잘한 부분들은 잘 코멘트되어 있다). 그런 툴들 중에 특히 추천할만한
-것은 Linux Cross-Reference project이며 그것은 자기 참조 방식이며
-소스코드를 인덱스된 웹 페이지들의 형태로 보여준다. 최신의 멋진 커널
-코드 저장소는 다음을 통하여 참조할 수 있다.
-      http://lxr.free-electrons.com/
-
-
-개발 프로세스
--------------
-
-리눅스 커널 개발 프로세스는 현재 몇몇 다른 메인 커널 "브랜치들"과
-서브시스템에 특화된 커널 브랜치들로 구성된다. 몇몇 다른 메인
-브랜치들은 다음과 같다.
-  - main 4.x 커널 트리
-  - 4.x.y - 안정된 커널 트리
-  - 4.x -git 커널 패치들
-  - 서브시스템을 위한 커널 트리들과 패치들
-  - 4.x - 통합 테스트를 위한 next 커널 트리
-
-4.x 커널 트리
----------------
-
-4.x 커널들은 Linux Torvalds가 관리하며 kernel.org의 pub/linux/kernel/v4.x/
-디렉토리에서 참조될 수 있다.개발 프로세스는 다음과 같다.
-  - 새로운 커널이 배포되자마자 2주의 시간이 주어진다. 이 기간동은
-    메인테이너들은 큰 diff들을 Linus에게 제출할 수 있다. 대개 이 패치들은
-    몇 주 동안 -next 커널내에 이미 있었던 것들이다. 큰 변경들을 제출하는 데
-    선호되는 방법은  git(커널의 소스 관리 툴, 더 많은 정보들은
-    http://git-scm.com/ 에서 참조할 수 있다)를 사용하는 것이지만 순수한
-    패치파일의 형식으로 보내는 것도 무관하다.
-  - 2주 후에 -rc1 커널이 배포되며 지금부터는 전체 커널의 안정성에 영향을
-    미칠수 있는 새로운 기능들을 포함하지 않는 패치들만이 추가될 수 있다.
-    완전히 새로운 드라이버(혹은 파일시스템)는 -rc1 이후에만 받아들여진다는
-    것을 기억해라. 왜냐하면 변경이 자체내에서만 발생하고 추가된 코드가
-    드라이버 외부의 다른 부분에는 영향을 주지 않으므로 그런 변경은
-    회귀(역자주: 이전에는 존재하지 않았지만 새로운 기능추가나 변경으로 인해
-    생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이
-    배포된 이후에 git를 사용하여 패치들을 Linus에게 보낼수 있지만 패치들은
-    공식적인 메일링 리스트로 보내서 검토를 받을 필요가 있다.
-  - 새로운 -rc는 Linus가 현재 git tree가 테스트 하기에 충분히 안정된 상태에
-    있다고 판단될 때마다 배포된다. 목표는 새로운 -rc 커널을 매주 배포하는
-    것이다.
-  - 이러한 프로세스는 커널이 "준비(ready)"되었다고 여겨질때까지 계속된다.
-    프로세스는 대체로 6주간 지속된다.
-
-커널 배포에 있어서 언급할만한 가치가 있는 리눅스 커널 메일링 리스트의
-Andrew Morton의 글이 있다.
-        "커널이 언제 배포될지는 아무도 모른다. 왜냐하면 배포는 알려진
-         버그의 상황에 따라 배포되는 것이지 미리정해 놓은 시간에 따라
-         배포되는 것은 아니기 때문이다."
-
-4.x.y - 안정 커널 트리
-------------------------
-
-3 자리 숫자로 이루어진 버젼의 커널들은 -stable 커널들이다. 그것들은 4.x
-커널에서 발견된 큰 회귀들이나 보안 문제들 중 비교적 작고 중요한 수정들을
-포함한다.
-
-이것은 가장 최근의 안정적인 커널을 원하는 사용자에게 추천되는 브랜치이며,
-개발/실험적 버젼을 테스트하는 것을 돕고자 하는 사용자들과는 별로 관련이 없다.
-
-어떤 4.x.y 커널도 사용할 수 없다면 그때는 가장 높은 숫자의 4.x
-커널이 현재의 안정 커널이다.
-
-4.x.y는 "stable" 팀<stable@vger.kernel.org>에 의해 관리되며 거의 매번 격주로
-배포된다.
-
-커널 트리 문서들 내에 Documentation/stable_kernel_rules.txt 파일은 어떤
-종류의 변경들이 -stable 트리로 들어왔는지와 배포 프로세스가 어떻게
-진행되는지를 설명한다.
-
-
-4.x -git 패치들
-------------------
-git 저장소(그러므로 -git이라는 이름이 붙음)에는 날마다 관리되는 Linus의
-커널 트리의 snapshot 들이 있다. 이 패치들은 일반적으로 날마다 배포되며
-Linus의 트리의 현재 상태를 나타낸다. 이 패치들은 정상적인지 조금도
-살펴보지 않고 자동적으로 생성된 것이므로 -rc 커널들 보다도 더 실험적이다.
-
-서브시스템 커널 트리들과 패치들
--------------------------------
-다양한 커널 서브시스템의 메인테이너들 --- 그리고 많은 커널 서브시스템 개발자들
---- 은 그들의 현재 개발 상태를 소스 저장소로 노출한다. 이를 통해 다른 사람들도
-커널의 다른 영역에 어떤 변화가 이루어지고 있는지 알 수 있다. 급속히 개발이
-진행되는 영역이 있고 그렇지 않은 영역이 있으므로, 개발자는 다른 개발자가 제출한
-수정 사항과 자신의 수정사항의 충돌이나 동일한 일을 동시에 두사람이 따로
-진행하는 사태를 방지하기 위해 급속히 개발이 진행되고 있는 영역에 작업의
-베이스를 맞춰줄 것이 요구된다.
-
-대부분의 이러한 저장소는 git 트리지만, git이 아닌 SCM으로 관리되거나, quilt
-시리즈로 제공되는 패치들도 존재한다. 이러한 서브시스템 저장소들은 MAINTAINERS
-파일에 나열되어 있다. 대부분은 http://git.kernel.org 에서 볼 수 있다.
-
-제안된 패치는 서브시스템 트리에 커밋되기 전에 메일링 리스트를 통해
-리뷰된다(아래의 관련 섹션을 참고하기 바란다). 일부 커널 서브시스템의 경우, 이
-리뷰 프로세스는 patchwork라는 도구를 통해 추적된다. patchwork은 등록된 패치와
-패치에 대한 코멘트, 패치의 버전을 볼 수 있는 웹 인터페이스를 제공하고,
-메인테이너는 패치를 리뷰 중, 리뷰 통과, 또는 반려됨으로 표시할 수 있다.
-대부분의 이러한 patchwork 사이트는 http://patchwork.kernel.org/ 또는
-http://patchwork.ozlabs.org/ 에 나열되어 있다.
-
-4.x - 통합 테스트를 위한 next 커널 트리
------------------------------------------
-서브시스템 트리들의 변경사항들은 mainline 4.x 트리로 들어오기 전에 통합
-테스트를 거쳐야 한다. 이런 목적으로, 모든 서브시스템 트리의 변경사항을 거의
-매일 받아가는 특수한 테스트 저장소가 존재한다:
-       http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
-
-이런 식으로, -next 커널을 통해 다음 머지 기간에 메인라인 커널에 어떤 변경이
-가해질 것인지 간략히 알 수 있다. 모험심 강한 테스터라면 -next 커널에서 테스트를
-수행하는 것도 좋을 것이다.
-
-버그 보고
----------
-bugzilla.kernel.org는 리눅스 커널 개발자들이 커널의 버그를 추적하는 곳이다.
-사용자들은 발견한 모든 버그들을 보고하기 위하여 이 툴을 사용할 것을 권장한다.
-kernel bugzilla를 사용하는 자세한 방법은 다음을 참조하라.
-    http://test.kernel.org/bugzilla/faq.html
-
-메인 커널 소스 디렉토리에 있는 REPORTING-BUGS 파일은 커널 버그라고 생각되는
-것을 보고하는 방법에 관한 좋은 템플릿이며 문제를 추적하기 위해서 커널
-개발자들이 필요로 하는 정보가 무엇들인지를 상세히 설명하고 있다.
-
-
-버그 리포트들의 관리
---------------------
-
-여러분의 해킹 기술을 연습하는 가장 좋은 방법 중의 하는 다른 사람들이
-보고한 버그들을 수정하는 것이다. 여러분은 커널을 더욱 안정화시키는데
-도움을 줄 뿐만이 아니라 실제있는 문제들을 수정하는 법을 배우게 되고
-그와 함께 여러분들의 기술은 향상될 것이며 다른 개발자들이 여러분의
-존재에 대해 알게 될 것이다. 버그를 수정하는 것은 개발자들  사이에서
-점수를 얻을 수 있는 가장 좋은 방법중의 하나이다. 왜냐하면 많은 사람들은
-다른 사람들의 버그들을 수정하기 위하여 시간을 낭비하지 않기 때문이다.
-
-이미 보고된 버그 리포트들을 가지고 작업하기 위해서 http://bugzilla.kernel.org를
-참조하라. 여러분이 앞으로 생겨날 버그 리포트들의 조언자가 되길 원한다면
-bugme-new 메일링 리스트나(새로운 버그 리포트들만이 이곳에서 메일로 전해진다)
-bugme-janitor 메일링 리스트(bugzilla에 모든 변화들이 여기서 메일로 전해진다)
-에 등록하면 된다.
-
-      https://lists.linux-foundation.org/mailman/listinfo/bugme-new
-      https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
-
-
-
-메일링 리스트들
----------------
-
-위의 몇몇 문서들이 설명하였지만 핵심 커널 개발자들의 대다수는
-리눅스 커널 메일링 리스트에 참여하고 있다. 리스트에 등록하고 해지하는
-방법에 관한 자세한 사항은 다음에서 참조할 수 있다.
-    http://vger.kernel.org/vger-lists.html#linux-kernel
-웹상의 많은 다른 곳에도 메일링 리스트의 아카이브들이 있다.
-이러한 아카이브들을 찾으려면 검색 엔진을 사용하라. 예를 들어:
-      http://dir.gmane.org/gmane.linux.kernel
-여러분이 새로운 문제에 관해 리스트에 올리기 전에 말하고 싶은 주제에 관한
-것을 아카이브에서 먼저 찾아보기를 강력히 권장한다. 이미 상세하게 토론된 많은
-것들이 메일링 리스트의 아카이브에 기록되어 있다.
-
-각각의 커널 서브시스템들의 대부분은 자신들의 개발에 관한 노력들로 이루어진
-분리된 메일링 리스트를 따로 가지고 있다. 다른 그룹들이 무슨 리스트를 가지고
-있는지는 MAINTAINERS 파일을 참조하라.
-
-많은 리스트들은 kernel.org에서 호스트되고 있다. 그 정보들은 다음에서 참조될 수 있다.
-         http://vger.kernel.org/vger-lists.html
-
-리스트들을 사용할 때는 올바른 예절을 따를 것을 유념해라.
-대단하진 않지만 다음 URL은 리스트(혹은 모든 리스트)와 대화하는 몇몇 간단한
-가이드라인을 가지고 있다.
-         http://www.albion.com/netiquette/
-
-여러 사람들이 여러분의 메일에 응답한다면 CC: 즉 수신 리스트는 꽤 커지게
-될 것이다. 아무 이유없이 CC에서 어떤 사람도 제거하거나 리스트 주소로만
-회신하지 마라. 메일을 보낸 사람으로서 하나를 받고 리스트로부터 또
-하나를 받아 두번 받는 것에 익숙하여 있으니 mail-header를 조작하려고 하지
-말아라. 사람들은 그런 것을 좋아하지 않을 것이다.
-
-여러분의 회신의 문맥을 원래대로 유지해야 한다. 여러분들의 회신의 윗부분에
-"John 커널해커는 작성했다...."를 유지하며 여러분들의 의견을 그 메일의 윗부분에
-작성하지 말고 각 인용한 단락들 사이에 넣어라.
-
-여러분들이 패치들을 메일에 넣는다면 그것들은 Documentation/SubmittingPatches에
-나와있는데로 명백히(plain) 읽을 수 있는 텍스트여야 한다. 커널 개발자들은
-첨부파일이나 압축된 패치들을 원하지 않는다. 그들은 여러분들의 패치의
-각 라인 단위로 코멘트를 하길 원하며 압축하거나 첨부하지 않고 보내는 것이
-그렇게 할 수 있는 유일한 방법이다. 여러분들이 사용하는 메일 프로그램이
-스페이스나 탭 문자들을 조작하지 않는지 확인하라. 가장 좋은 첫 테스트는
-메일을 자신에게 보내보고 스스로 그 패치를 적용해보라. 그것이 동작하지
-않는다면 여러분의 메일 프로그램을 고치던가 제대로 동작하는 프로그램으로
-바꾸어라.
-
-무엇보다도 메일링 리스트의 다른 구독자들에게 보여주려 한다는 것을 기억하라.
-
-
-커뮤니티와 협력하는 법
---------------------
-
-커널 커뮤니티의 목적은 가능한한 가장 좋은 커널을 제공하는 것이다. 여러분이
-받아들여질 패치를 제출하게 되면 그 패치의 기술적인 이점으로 검토될 것이다.
-그럼 여러분들은 무엇을 기대하고 있어야 하는가?
- - 비판
- - 의견
- - 변경을 위한 요구
- - 당위성을 위한 요구
- - 침묵
-
-기억하라. 이것들은 여러분의 패치가 커널로 들어가기 위한 과정이다. 여러분의
-패치들은 비판과 다른 의견을 받을 수 있고 그것들을 기술적인 레벨로 평가하고
-재작업하거나 또는 왜 수정하면 안되는지에 관하여 명료하고 간결한 이유를
-말할 수 있어야 한다. 여러분이 제출한 것에 어떤 응답도 있지 않다면 몇 일을
-기다려보고 다시 시도해라. 때론 너무 많은 메일들 속에 묻혀버리기도 한다.
-
-여러분은 무엇을 해서는 안되는가?
- - 여러분의 패치가 아무 질문 없이 받아들여지기를 기대하는 것
- - 방어적이 되는 것
- - 의견을 무시하는 것
- - 요청된 변경을 하지 않고 패치를 다시 제출하는 것
-
-가능한한 가장 좋은 기술적인 해답을 찾고 있는 커뮤니티에서는 항상
-어떤 패치가 얼마나 좋은지에 관하여 다른 의견들이 있을 수 있다. 여러분은
-협조적이어야 하고 기꺼이 여러분의 생각을 커널 내에 맞추어야 한다. 아니면
-적어도 여러분의 것이 가치있다는 것을 증명하여야 한다. 잘못된 것도 여러분이
-올바른 방향의 해결책으로 이끌어갈 의지가 있다면 받아들여질 것이라는 점을
-기억하라.
-
-여러분의 첫 패치에 여러분이 수정해야하는 십여개 정도의 회신이 오는
-경우도 흔하다. 이것은 여러분의 패치가 받아들여지지 않을 것이라는 것을
-의미하는 것이 아니고 개인적으로 여러분에게 감정이 있어서 그러는 것도
-아니다. 간단히 여러분의 패치에 제기된 문제들을 수정하고 그것을 다시
-보내라.
-
-
-커널 커뮤니티와 기업 조직간의 차이점
------------------------------------------------------------------
-커널 커뮤니티는 가장 전통적인 회사의 개발 환경과는 다르다. 여기에 여러분들의
-문제를 피하기 위한 목록이 있다.
-  여러분들이 제안한 변경들에 관하여 말할 때 좋은 것들 :
-    - "이것은 여러 문제들을 해결합니다."
-    - "이것은 2000 라인의 코드를 줄입니다."
-    - "이것은 내가 말하려는 것에 관해 설명하는 패치입니다."
-    - "나는 5개의 다른 아키텍쳐에서 그것을 테스트 했으므로..."
-    - "여기에 일련의 작은 패치들이 있으므로..."
-    - "이것은 일반적인 머신에서 성능을 향상함으로..."
-
-  여러분들이 말할 때 피해야 할 좋지 않은 것들 :
-    - "우리는 그것을 AIX/ptx/Solaris에서 이러한 방법으로 했다. 그러므로 그것은 좋은 것임에 틀림없다..."
-    - "나는 20년동안 이것을 해왔다. 그러므로..."
-    - "이것은 돈을 벌기위해 나의 회사가 필요로 하는 것이다."
-    - "이것은 우리의 엔터프라이즈 상품 라인을 위한 것이다."
-    - "여기에 나의 생각을 말하고 있는 1000 페이지 설계 문서가 있다."
-    - "나는 6달동안 이것을 했으니..."
-    - "여기에 5000 라인 짜리 패치가 있으니..."
-    - "나는 현재 뒤죽박죽인 것을 재작성했다. 그리고 여기에..."
-    - "나는 마감시한을 가지고 있으므로 이 패치는 지금 적용될 필요가 있다."
-
-커널 커뮤니티가 전통적인 소프트웨어 엔지니어링 개발 환경들과
-또 다른 점은 얼굴을 보지 않고 일한다는 점이다. 이메일과 irc를 대화의
-주요수단으로 사용하는 것의 한가지 장점은 성별이나 인종의 차별이
-없다는 것이다. 리눅스 커널의 작업 환경에서는 단지 이메일 주소만
-알수 있기 때문에 여성과 소수 민족들도 모두 받아들여진다. 국제적으로
-일하게 되는 측면은 사람의 이름에 근거하여 성별을 추측할 수 없게
-하기때문에 차별을 없애는 데 도움을 준다. Andrea라는 이름을 가진 남자와
-Pat이라는 이름을 가진 여자가 있을 수도 있는 것이다. 리눅스 커널에서
-작업하며 생각을 표현해왔던 대부분의 여성들은 긍정적인 경험을 가지고
-있다.
-
-언어 장벽은 영어에 익숙하지 않은 몇몇 사람들에게 문제가 될 수도 있다.
-언어의 훌륭한 구사는 메일링 리스트에서 올바르게 자신의 생각을
-표현하기 위하여 필요하다. 그래서 여러분은 이메일을 보내기 전에
-영어를 올바르게 사용하고 있는지를 체크하는 것이 바람직하다.
-
-
-여러분의 변경을 나누어라
-------------------------
-
-리눅스 커널 커뮤니티는 한꺼번에 굉장히 큰 코드의 묶음(chunk)을 쉽게
-받아들이지 않는다. 변경은 적절하게 소개되고, 검토되고, 각각의
-부분으로 작게 나누어져야 한다. 이것은 회사에서 하는 것과는 정확히
-반대되는 것이다. 여러분들의 제안은 개발 초기에 일찍이 소개되야 한다.
-그래서 여러분들은 자신이 하고 있는 것에 관하여 피드백을 받을 수 있게
-된다. 커뮤니티가 여러분들이 커뮤니티와 함께 일하고 있다는 것을
-느끼도록 만들고 커뮤니티가 여러분의 기능을 위한 쓰레기 장으로써
-사용되지 않고 있다는 것을 느끼게 하자. 그러나 메일링 리스트에 한번에
-50개의 이메일을 보내지는 말아라. 여러분들의 일련의 패치들은 항상
-더 작아야 한다.
-
-패치를 나누는 이유는 다음과 같다.
-
-1) 작은 패치들은 여러분의 패치들이 적용될 수 있는 확률을 높여준다.
-   왜냐하면 다른 사람들은 정확성을 검증하기 위하여 많은 시간과 노력을
-   들이기를 원하지 않는다. 5줄의 패치는 메인테이너가 거의 몇 초간 힐끗
-   보면 적용될 수 있다. 그러나 500 줄의 패치는 정확성을 검토하기 위하여
-   몇시간이 걸릴 수도 있다(걸리는 시간은 패치의 크기 혹은 다른 것에
-   비례하여 기하급수적으로 늘어난다).
-
-   패치를 작게 만드는 것은 무엇인가 잘못되었을 때 디버그하는 것을
-   쉽게 만든다. 즉, 그렇게 만드는 것은 매우 큰 패치를 적용한 후에
-   조사하는 것 보다 작은 패치를 적용한 후에 (그리고 몇몇의 것이
-   깨졌을 때) 하나씩 패치들을 제거해가며 디버그 하기 쉽도록 만들어 준다.
-
-2) 작은 패치들을 보내는 것뿐만 아니라 패치들을 제출하기전에 재작성하고
-   간단하게(혹은 간단한게 재배치하여) 하는 것도 중요하다.
-
-여기에 커널 개발자 Al Viro의 이야기가 있다.
-    "학생의 수학 숙제를 채점하는 선생님을 생각해보라. 선생님은 학생들이
-    답을 얻을때까지 겪은 시행착오를 보길 원하지 않는다. 선생님들은
-    간결하고 가장 뛰어난 답을 보길 원한다. 훌륭한 학생은 이것을 알고
-    마지막으로 답을 얻기 전 중간 과정들을 제출하진 않는다.
-
-    커널 개발도 마찬가지이다. 메인테이너들과 검토하는 사람들은 문제를
-    풀어나가는 과정속에 숨겨진 과정을 보길 원하진 않는다. 그들은
-    간결하고 멋진 답을 보길 원한다."
-
-커뮤니티와 협력하며 뛰어난 답을 찾는 것과 여러분들의 끝마치지 못한 작업들
-사이에 균형을 유지해야 하는 것은 어려울지도 모른다. 그러므로 프로세스의
-초반에 여러분의 작업을 향상시키기위한 피드백을 얻는 것 뿐만 아니라
-여러분들의 변경들을 작은 묶음으로 유지해서 심지어는 여러분의 작업의
-모든 부분이 지금은 포함될 준비가 되어있지 않지만 작은 부분은 벌써
-받아들여질 수 있도록 유지하는 것이 바람직하다.
-
-또한 완성되지 않았고 "나중에 수정될 것이다." 와 같은 것들을 포함하는
-패치들은 받아들여지지 않을 것이라는 점을 유념하라.
-
-
-변경을 정당화해라
------------------
-
-여러분들의 나누어진 패치들을 리눅스 커뮤니티가 왜 반영해야 하는지를
-알도록 하는 것은 매우 중요하다. 새로운 기능들이 필요하고 유용하다는
-것은 반드시 그에 합당한 이유가 있어야 한다.
-
-
-변경을 문서화해라
------------------
-
-여러분이 패치를 보내려 할때는 여러분이 무엇을 말하려고 하는지를 충분히
-생각하여 이메일을 작성해야 한다. 이 정보는 패치를 위한 ChangeLog가 될
-것이다. 그리고 항상 그 내용을 보길 원하는 모든 사람들을 위해 보존될
-것이다. 패치는 완벽하게 다음과 같은 내용들을 포함하여 설명해야 한다.
-  - 변경이 왜 필요한지
-  - 패치에 관한 전체 설계 접근(approach)
-  - 구현 상세들
-  - 테스트 결과들
-
-이것이 무엇인지 더 자세한 것을 알고 싶다면 다음 문서의 ChageLog 항을 봐라.
-   "The Perfect Patch"
-    http://www.ozlabs.org/~akpm/stuff/tpp.txt
-
-
-
-
-이 모든 것을 하는 것은 매우 어려운 일이다. 완벽히 소화하는 데는 적어도 몇년이
-걸릴 수도 있다. 많은 인내와 결심이 필요한 계속되는 개선의 과정이다. 그러나
-가능한한 포기하지 말라. 많은 사람들은 이전부터 해왔던 것이고 그 사람들도
-정확하게 여러분들이 지금 서 있는 그 곳부터  시작했었다.
-
-
-
-
-----------
-"개발 프로세스"(http://lwn.net/Articles/94386/) 섹션을
-작성하는데 있어 참고할 문서를 사용하도록 허락해준 Paolo Ciarrocchi에게
-감사한다. 여러분들이 말해야 할 것과 말해서는 안되는 것의 목록 중 일부를 제공해준
-Randy Dunlap과 Gerrit Huizenga에게 감사한다. 또한 검토와 의견 그리고
-공헌을 아끼지 않은 Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
-Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi Kleen,
-Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
-David A. Wheeler, Junio Hamano, Michael Kerrisk, and Alex Shepard에게도 감사를 전한다.
-그들의 도움이 없었다면 이 문서는 존재하지 않았을 것이다.
-
-
-
-메인테이너: Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ko_KR/memory-barriers.txt linux-libre-4.10-rc8-gnu/Documentation/ko_KR/memory-barriers.txt
--- linux-libre-4.9-gnu/Documentation/ko_KR/memory-barriers.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ko_KR/memory-barriers.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,3135 +0,0 @@
-NOTE:
-This is a version of Documentation/memory-barriers.txt translated into Korean.
-This document is maintained by SeongJae Park <sj38.park@gmail.com>.
-If you find any difference between this document and the original file or
-a problem with the translation, please contact the maintainer of this file.
-
-Please also note that the purpose of this file is to be easier to
-read for non English (read: Korean) speakers and is not intended as
-a fork.  So if you have any comments or updates for this file please
-update the original English file first.  The English version is
-definitive, and readers should look there if they have any doubt.
-
-===================================
-이 문서는
-Documentation/memory-barriers.txt
-의 한글 번역입니다.
-
-역자： 박성재 <sj38.park@gmail.com>
-===================================
-
-
-			 =========================
-			 리눅스 커널 메모리 배리어
-			 =========================
-
-저자: David Howells <dhowells@redhat.com>
-      Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-      Will Deacon <will.deacon@arm.com>
-      Peter Zijlstra <peterz@infradead.org>
-
-========
-면책조항
-========
-
-이 문서는 명세서가 아닙니다; 이 문서는 완벽하지 않은데, 간결성을 위해 의도된
-부분도 있고, 의도하진 않았지만 사람에 의해 쓰였다보니 불완전한 부분도 있습니다.
-이 문서는 리눅스에서 제공하는 다양한 메모리 배리어들을 사용하기 위한
-안내서입니다만, 뭔가 이상하다 싶으면 (그런게 많을 겁니다) 질문을 부탁드립니다.
-
-다시 말하지만, 이 문서는 리눅스가 하드웨어에 기대하는 사항에 대한 명세서가
-아닙니다.
-
-이 문서의 목적은 두가지입니다:
-
- (1) 어떤 특정 배리어에 대해 기대할 수 있는 최소한의 기능을 명세하기 위해서,
-     그리고
-
- (2) 사용 가능한 배리어들에 대해 어떻게 사용해야 하는지에 대한 안내를 제공하기
-     위해서.
-
-어떤 아키텍쳐는 특정한 배리어들에 대해서는 여기서 이야기하는 최소한의
-요구사항들보다 많은 기능을 제공할 수도 있습니다만, 여기서 이야기하는
-요구사항들을 충족하지 않는 아키텍쳐가 있다면 그 아키텍쳐가 잘못된 것이란 점을
-알아두시기 바랍니다.
-
-또한, 특정 아키텍쳐에서 일부 배리어는 해당 아키텍쳐의 특수한 동작 방식으로 인해
-해당 배리어의 명시적 사용이 불필요해서 no-op 이 될수도 있음을 알아두시기
-바랍니다.
-
-역자: 본 번역 역시 완벽하지 않은데, 이 역시 부분적으로는 의도된 것이기도
-합니다.  여타 기술 문서들이 그렇듯 완벽한 이해를 위해서는 번역문과 원문을 함께
-읽으시되 번역문을 하나의 가이드로 활용하시길 추천드리며, 발견되는 오역 등에
-대해서는 언제든 의견을 부탁드립니다.  과한 번역으로 인한 오해를 최소화하기 위해
-애매한 부분이 있을 경우에는 어색함이 있더라도 원래의 용어를 차용합니다.
-
-
-=====
-목차:
-=====
-
- (*) 추상 메모리 액세스 모델.
-
-     - 디바이스 오퍼레이션.
-     - 보장사항.
-
- (*) 메모리 배리어란 무엇인가?
-
-     - 메모리 배리어의 종류.
-     - 메모리 배리어에 대해 가정해선 안될 것.
-     - 데이터 의존성 배리어.
-     - 컨트롤 의존성.
-     - SMP 배리어 짝맞추기.
-     - 메모리 배리어 시퀀스의 예.
-     - 읽기 메모리 배리어 vs 로드 예측.
-     - 이행성
-
- (*) 명시적 커널 배리어.
-
-     - 컴파일러 배리어.
-     - CPU 메모리 배리어.
-     - MMIO 쓰기 배리어.
-
- (*) 암묵적 커널 메모리 배리어.
-
-     - 락 Acquisition 함수.
-     - 인터럽트 비활성화 함수.
-     - 슬립과 웨이크업 함수.
-     - 그외의 함수들.
-
- (*) CPU 간 ACQUIRING 배리어의 효과.
-
-     - Acquire vs 메모리 액세스.
-     - Acquire vs I/O 액세스.
-
- (*) 메모리 배리어가 필요한 곳
-
-     - 프로세서간 상호 작용.
-     - 어토믹 오퍼레이션.
-     - 디바이스 액세스.
-     - 인터럽트.
-
- (*) 커널 I/O 배리어의 효과.
-
- (*) 가정되는 가장 완화된 실행 순서 모델.
-
- (*) CPU 캐시의 영향.
-
-     - 캐시 일관성.
-     - 캐시 일관성 vs DMA.
-     - 캐시 일관성 vs MMIO.
-
- (*) CPU 들이 저지르는 일들.
-
-     - 그리고, Alpha 가 있다.
-     - 가상 머신 게스트.
-
- (*) 사용 예.
-
-     - 순환식 버퍼.
-
- (*) 참고 문헌.
-
-
-=======================
-추상 메모리 액세스 모델
-=======================
-
-다음과 같이 추상화된 시스템 모델을 생각해 봅시다:
-
-		            :                :
-		            :                :
-		            :                :
-		+-------+   :   +--------+   :   +-------+
-		|       |   :   |        |   :   |       |
-		|       |   :   |        |   :   |       |
-		| CPU 1 |<----->| Memory |<----->| CPU 2 |
-		|       |   :   |        |   :   |       |
-		|       |   :   |        |   :   |       |
-		+-------+   :   +--------+   :   +-------+
-		    ^       :       ^        :       ^
-		    |       :       |        :       |
-		    |       :       |        :       |
-		    |       :       v        :       |
-		    |       :   +--------+   :       |
-		    |       :   |        |   :       |
-		    |       :   |        |   :       |
-		    +---------->| Device |<----------+
-		            :   |        |   :
-		            :   |        |   :
-		            :   +--------+   :
-		            :                :
-
-프로그램은 여러 메모리 액세스 오퍼레이션을 발생시키고, 각각의 CPU 는 그런
-프로그램들을 실행합니다.  추상화된 CPU 모델에서 메모리 오퍼레이션들의 순서는
-매우 완화되어 있고, CPU 는 프로그램이 인과관계를 어기지 않는 상태로 관리된다고
-보일 수만 있다면 메모리 오퍼레이션을 자신이 원하는 어떤 순서대로든 재배치해
-동작시킬 수 있습니다.  비슷하게, 컴파일러 또한 프로그램의 정상적 동작을 해치지
-않는 한도 내에서는 어떤 순서로든 자신이 원하는 대로 인스트럭션을 재배치 할 수
-있습니다.
-
-따라서 위의 다이어그램에서 한 CPU가 동작시키는 메모리 오퍼레이션이 만들어내는
-변화는 해당 오퍼레이션이 CPU 와 시스템의 다른 부분들 사이의 인터페이스(점선)를
-지나가면서 시스템의 나머지 부분들에 인지됩니다.
-
-
-예를 들어, 다음의 일련의 이벤트들을 생각해 봅시다:
-
-	CPU 1		CPU 2
-	===============	===============
-	{ A == 1; B == 2 }
-	A = 3;		x = B;
-	B = 4;		y = A;
-
-다이어그램의 가운데에 위치한 메모리 시스템에 보여지게 되는 액세스들은 다음의 총
-24개의 조합으로 재구성될 수 있습니다:
-
-	STORE A=3,	STORE B=4,	y=LOAD A->3,	x=LOAD B->4
-	STORE A=3,	STORE B=4,	x=LOAD B->4,	y=LOAD A->3
-	STORE A=3,	y=LOAD A->3,	STORE B=4,	x=LOAD B->4
-	STORE A=3,	y=LOAD A->3,	x=LOAD B->2,	STORE B=4
-	STORE A=3,	x=LOAD B->2,	STORE B=4,	y=LOAD A->3
-	STORE A=3,	x=LOAD B->2,	y=LOAD A->3,	STORE B=4
-	STORE B=4,	STORE A=3,	y=LOAD A->3,	x=LOAD B->4
-	STORE B=4, ...
-	...
-
-따라서 다음의 네가지 조합의 값들이 나올 수 있습니다:
-
-	x == 2, y == 1
-	x == 2, y == 3
-	x == 4, y == 1
-	x == 4, y == 3
-
-
-한발 더 나아가서, 한 CPU 가 메모리 시스템에 반영한 스토어 오퍼레이션들의 결과는
-다른 CPU 에서의 로드 오퍼레이션을 통해 인지되는데, 이 때 스토어가 반영된 순서와
-다른 순서로 인지될 수도 있습니다.
-
-
-예로, 아래의 일련의 이벤트들을 생각해 봅시다:
-
-	CPU 1		CPU 2
-	===============	===============
-	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
-	B = 4;		Q = P;
-	P = &B		D = *Q;
-
-D 로 읽혀지는 값은 CPU 2 에서 P 로부터 읽혀진 주소값에 의존적이기 때문에 여기엔
-분명한 데이터 의존성이 있습니다.  하지만 이 이벤트들의 실행 결과로는 아래의
-결과들이 모두 나타날 수 있습니다:
-
-	(Q == &A) and (D == 1)
-	(Q == &B) and (D == 2)
-	(Q == &B) and (D == 4)
-
-CPU 2 는 *Q 의 로드를 요청하기 전에 P 를 Q 에 넣기 때문에 D 에 C 를 집어넣는
-일은 없음을 알아두세요.
-
-
-디바이스 오퍼레이션
--------------------
-
-일부 디바이스는 자신의 컨트롤 인터페이스를 메모리의 특정 영역으로 매핑해서
-제공하는데(Memory mapped I/O), 해당 컨트롤 레지스터에 접근하는 순서는 매우
-중요합니다.  예를 들어, 어드레스 포트 레지스터 (A) 와 데이터 포트 레지스터 (D)
-를 통해 접근되는 내부 레지스터 집합을 갖는 이더넷 카드를 생각해 봅시다.  내부의
-5번 레지스터를 읽기 위해 다음의 코드가 사용될 수 있습니다:
-
-	*A = 5;
-	x = *D;
-
-하지만, 이건 다음의 두 조합 중 하나로 만들어질 수 있습니다:
-
-	STORE *A = 5, x = LOAD *D
-	x = LOAD *D, STORE *A = 5
-
-두번째 조합은 데이터를 읽어온 _후에_ 주소를 설정하므로, 오동작을 일으킬 겁니다.
-
-
-보장사항
---------
-
-CPU 에게 기대할 수 있는 최소한의 보장사항 몇가지가 있습니다:
-
- (*) 어떤 CPU 든, 의존성이 존재하는 메모리 액세스들은 해당 CPU 자신에게
-     있어서는 순서대로 메모리 시스템에 수행 요청됩니다. 즉, 다음에 대해서:
-
-	Q = READ_ONCE(P); smp_read_barrier_depends(); D = READ_ONCE(*Q);
-
-     CPU 는 다음과 같은 메모리 오퍼레이션 시퀀스를 수행 요청합니다:
-
-	Q = LOAD P, D = LOAD *Q
-
-     그리고 그 시퀀스 내에서의 순서는 항상 지켜집니다.  대부분의 시스템에서
-     smp_read_barrier_depends() 는 아무일도 안하지만 DEC Alpha 에서는
-     명시적으로 사용되어야 합니다.  보통의 경우에는 smp_read_barrier_depends()
-     를 직접 사용하는 대신 rcu_dereference() 같은 것들을 사용해야 함을
-     알아두세요.
-
- (*) 특정 CPU 내에서 겹치는 영역의 메모리에 행해지는 로드와 스토어 들은 해당
-     CPU 안에서는 순서가 바뀌지 않은 것으로 보여집니다.  즉, 다음에 대해서:
-
-	a = READ_ONCE(*X); WRITE_ONCE(*X, b);
-
-     CPU 는 다음의 메모리 오퍼레이션 시퀀스만을 메모리에 요청할 겁니다:
-
-	a = LOAD *X, STORE *X = b
-
-     그리고 다음에 대해서는:
-
-	WRITE_ONCE(*X, c); d = READ_ONCE(*X);
-
-     CPU 는 다음의 수행 요청만을 만들어 냅니다:
-
-	STORE *X = c, d = LOAD *X
-
-     (로드 오퍼레이션과 스토어 오퍼레이션이 겹치는 메모리 영역에 대해
-     수행된다면 해당 오퍼레이션들은 겹친다고 표현됩니다).
-
-그리고 _반드시_ 또는 _절대로_ 가정하거나 가정하지 말아야 하는 것들이 있습니다:
-
- (*) 컴파일러가 READ_ONCE() 나 WRITE_ONCE() 로 보호되지 않은 메모리 액세스를
-     당신이 원하는 대로 할 것이라는 가정은 _절대로_ 해선 안됩니다.  그것들이
-     없다면, 컴파일러는 컴파일러 배리어 섹션에서 다루게 될, 모든 "창의적인"
-     변경들을 만들어낼 권한을 갖게 됩니다.
-
- (*) 개별적인 로드와 스토어들이 주어진 순서대로 요청될 것이라는 가정은 _절대로_
-     하지 말아야 합니다.  이 말은 곧:
-
-	X = *A; Y = *B; *D = Z;
-
-     는 다음의 것들 중 어느 것으로든 만들어질 수 있다는 의미입니다:
-
-	X = LOAD *A,  Y = LOAD *B,  STORE *D = Z
-	X = LOAD *A,  STORE *D = Z, Y = LOAD *B
-	Y = LOAD *B,  X = LOAD *A,  STORE *D = Z
-	Y = LOAD *B,  STORE *D = Z, X = LOAD *A
-	STORE *D = Z, X = LOAD *A,  Y = LOAD *B
-	STORE *D = Z, Y = LOAD *B,  X = LOAD *A
-
- (*) 겹치는 메모리 액세스들은 합쳐지거나 버려질 수 있음을 _반드시_ 가정해야
-     합니다.  다음의 코드는:
-
-	X = *A; Y = *(A + 4);
-
-     다음의 것들 중 뭐든 될 수 있습니다:
-
-	X = LOAD *A; Y = LOAD *(A + 4);
-	Y = LOAD *(A + 4); X = LOAD *A;
-	{X, Y} = LOAD {*A, *(A + 4) };
-
-     그리고:
-
-	*A = X; *(A + 4) = Y;
-
-     는 다음 중 뭐든 될 수 있습니다:
-
-	STORE *A = X; STORE *(A + 4) = Y;
-	STORE *(A + 4) = Y; STORE *A = X;
-	STORE {*A, *(A + 4) } = {X, Y};
-
-그리고 보장사항에 반대되는 것들(anti-guarantees)이 있습니다:
-
- (*) 이 보장사항들은 bitfield 에는 적용되지 않는데, 컴파일러들은 bitfield 를
-     수정하는 코드를 생성할 때 원자성 없는(non-atomic) 읽고-수정하고-쓰는
-     인스트럭션들의 조합을 만드는 경우가 많기 때문입니다.  병렬 알고리즘의
-     동기화에 bitfield 를 사용하려 하지 마십시오.
-
- (*) bitfield 들이 여러 락으로 보호되는 경우라 하더라도, 하나의 bitfield 의
-     모든 필드들은 하나의 락으로 보호되어야 합니다.  만약 한 bitfield 의 두
-     필드가 서로 다른 락으로 보호된다면, 컴파일러의 원자성 없는
-     읽고-수정하고-쓰는 인스트럭션 조합은 한 필드에의 업데이트가 근처의
-     필드에도 영향을 끼치게 할 수 있습니다.
-
- (*) 이 보장사항들은 적절하게 정렬되고 크기가 잡힌 스칼라 변수들에 대해서만
-     적용됩니다.  "적절하게 크기가 잡힌" 이라함은 현재로써는 "char", "short",
-     "int" 그리고 "long" 과 같은 크기의 변수들을 의미합니다.  "적절하게 정렬된"
-     은 자연스런 정렬을 의미하는데, 따라서 "char" 에 대해서는 아무 제약이 없고,
-     "short" 에 대해서는 2바이트 정렬을, "int" 에는 4바이트 정렬을, 그리고
-     "long" 에 대해서는 32-bit 시스템인지 64-bit 시스템인지에 따라 4바이트 또는
-     8바이트 정렬을 의미합니다.  이 보장사항들은 C11 표준에서 소개되었으므로,
-     C11 전의 오래된 컴파일러(예를 들어, gcc 4.6) 를 사용할 때엔 주의하시기
-     바랍니다.  표준에 이 보장사항들은 "memory location" 을 정의하는 3.14
-     섹션에 다음과 같이 설명되어 있습니다:
-     (역자: 인용문이므로 번역하지 않습니다)
-
-	memory location
-		either an object of scalar type, or a maximal sequence
-		of adjacent bit-fields all having nonzero width
-
-		NOTE 1: Two threads of execution can update and access
-		separate memory locations without interfering with
-		each other.
-
-		NOTE 2: A bit-field and an adjacent non-bit-field member
-		are in separate memory locations. The same applies
-		to two bit-fields, if one is declared inside a nested
-		structure declaration and the other is not, or if the two
-		are separated by a zero-length bit-field declaration,
-		or if they are separated by a non-bit-field member
-		declaration. It is not safe to concurrently update two
-		bit-fields in the same structure if all members declared
-		between them are also bit-fields, no matter what the
-		sizes of those intervening bit-fields happen to be.
-
-
-=========================
-메모리 배리어란 무엇인가?
-=========================
-
-앞에서 봤듯이, 상호간 의존성이 없는 메모리 오퍼레이션들은 실제로는 무작위적
-순서로 수행될 수 있으며, 이는 CPU 와 CPU 간의 상호작용이나 I/O 에 문제가 될 수
-있습니다.  따라서 컴파일러와 CPU 가 순서를 바꾸는데 제약을 걸 수 있도록 개입할
-수 있는 어떤 방법이 필요합니다.
-
-메모리 배리어는 그런 개입 수단입니다.  메모리 배리어는 배리어를 사이에 둔 앞과
-뒤 양측의 메모리 오퍼레이션들 간에 부분적 순서가 존재하도록 하는 효과를 줍니다.
-
-시스템의 CPU 들과 여러 디바이스들은 성능을 올리기 위해 명령어 재배치, 실행
-유예, 메모리 오퍼레이션들의 조합, 예측적 로드(speculative load), 브랜치
-예측(speculative branch prediction), 다양한 종류의 캐싱(caching) 등의 다양한
-트릭을 사용할 수 있기 때문에 이런 강제력은 중요합니다.  메모리 배리어들은 이런
-트릭들을 무효로 하거나 억제하는 목적으로 사용되어져서 코드가 여러 CPU 와
-디바이스들 간의 상호작용을 정상적으로 제어할 수 있게 해줍니다.
-
-
-메모리 배리어의 종류
---------------------
-
-메모리 배리어는 네개의 기본 타입으로 분류됩니다:
-
- (1) 쓰기 (또는 스토어) 메모리 배리어.
-
-     쓰기 메모리 배리어는 시스템의 다른 컴포넌트들에 해당 배리어보다 앞서
-     명시된 모든 STORE 오퍼레이션들이 해당 배리어 뒤에 명시된 모든 STORE
-     오퍼레이션들보다 먼저 수행된 것으로 보일 것을 보장합니다.
-
-     쓰기 배리어는 스토어 오퍼레이션들에 대한 부분적 순서 세우기입니다; 로드
-     오퍼레이션들에 대해서는 어떤 영향도 끼치지 않습니다.
-
-     CPU 는 시간의 흐름에 따라 메모리 시스템에 일련의 스토어 오퍼레이션들을
-     하나씩 요청해 집어넣습니다.  쓰기 배리어 앞의 모든 스토어 오퍼레이션들은
-     쓰기 배리어 뒤의 모든 스토어 오퍼레이션들보다 _앞서_ 수행될 겁니다.
-
-     [!] 쓰기 배리어들은 읽기 또는 데이터 의존성 배리어와 함께 짝을 맞춰
-     사용되어야만 함을 알아두세요; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요.
-
-
- (2) 데이터 의존성 배리어.
-
-     데이터 의존성 배리어는 읽기 배리어의 보다 완화된 형태입니다.  두개의 로드
-     오퍼레이션이 있고 두번째 것이 첫번째 것의 결과에 의존하고 있을 때(예:
-     두번째 로드가 참조할 주소를 첫번째 로드가 읽는 경우), 두번째 로드가 읽어올
-     데이터는 첫번째 로드에 의해 그 주소가 얻어지기 전에 업데이트 되어 있음을
-     보장하기 위해서 데이터 의존성 배리어가 필요할 수 있습니다.
-
-     데이터 의존성 배리어는 상호 의존적인 로드 오퍼레이션들 사이의 부분적 순서
-     세우기입니다; 스토어 오퍼레이션들이나 독립적인 로드들, 또는 중복되는
-     로드들에 대해서는 어떤 영향도 끼치지 않습니다.
-
-     (1) 에서 언급했듯이, 시스템의 CPU 들은 메모리 시스템에 일련의 스토어
-     오퍼레이션들을 던져 넣고 있으며, 거기에 관심이 있는 다른 CPU 는 그
-     오퍼레이션들을 메모리 시스템이 실행한 결과를 인지할 수 있습니다.  이처럼
-     다른 CPU 의 스토어 오퍼레이션의 결과에 관심을 두고 있는 CPU 가 수행 요청한
-     데이터 의존성 배리어는, 배리어 앞의 어떤 로드 오퍼레이션이 다른 CPU 에서
-     던져 넣은 스토어 오퍼레이션과 같은 영역을 향했다면, 그런 스토어
-     오퍼레이션들이 만들어내는 결과가 데이터 의존성 배리어 뒤의 로드
-     오퍼레이션들에게는 보일 것을 보장합니다.
-
-     이 순서 세우기 제약에 대한 그림을 보기 위해선 "메모리 배리어 시퀀스의 예"
-     서브섹션을 참고하시기 바랍니다.
-
-     [!] 첫번째 로드는 반드시 _데이터_ 의존성을 가져야지 컨트롤 의존성을 가져야
-     하는게 아님을 알아두십시오.  만약 두번째 로드를 위한 주소가 첫번째 로드에
-     의존적이지만 그 의존성은 조건적이지 그 주소 자체를 가져오는게 아니라면,
-     그것은 _컨트롤_ 의존성이고, 이 경우에는 읽기 배리어나 그보다 강력한
-     무언가가 필요합니다.  더 자세한 내용을 위해서는 "컨트롤 의존성" 서브섹션을
-     참고하시기 바랍니다.
-
-     [!] 데이터 의존성 배리어는 보통 쓰기 배리어들과 함께 짝을 맞춰 사용되어야
-     합니다; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요.
-
-
- (3) 읽기 (또는 로드) 메모리 배리어.
-
-     읽기 배리어는 데이터 의존성 배리어 기능의 보장사항에 더해서 배리어보다
-     앞서 명시된 모든 LOAD 오퍼레이션들이 배리어 뒤에 명시되는 모든 LOAD
-     오퍼레이션들보다 먼저 행해진 것으로 시스템의 다른 컴포넌트들에 보여질 것을
-     보장합니다.
-
-     읽기 배리어는 로드 오퍼레이션에 행해지는 부분적 순서 세우기입니다; 스토어
-     오퍼레이션에 대해서는 어떤 영향도 끼치지 않습니다.
-
-     읽기 메모리 배리어는 데이터 의존성 배리어를 내장하므로 데이터 의존성
-     배리어를 대신할 수 있습니다.
-
-     [!] 읽기 배리어는 일반적으로 쓰기 배리어들과 함께 짝을 맞춰 사용되어야
-     합니다; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요.
-
-
- (4) 범용 메모리 배리어.
-
-     범용(general) 메모리 배리어는 배리어보다 앞서 명시된 모든 LOAD 와 STORE
-     오퍼레이션들이 배리어 뒤에 명시된 모든 LOAD 와 STORE 오퍼레이션들보다
-     먼저 수행된 것으로 시스템의 나머지 컴포넌트들에 보이게 됨을 보장합니다.
-
-     범용 메모리 배리어는 로드와 스토어 모두에 대한 부분적 순서 세우기입니다.
-
-     범용 메모리 배리어는 읽기 메모리 배리어, 쓰기 메모리 배리어 모두를
-     내장하므로, 두 배리어를 모두 대신할 수 있습니다.
-
-
-그리고 두개의 명시적이지 않은 타입이 있습니다:
-
- (5) ACQUIRE 오퍼레이션.
-
-     이 타입의 오퍼레이션은 단방향의 투과성 배리어처럼 동작합니다.  ACQUIRE
-     오퍼레이션 뒤의 모든 메모리 오퍼레이션들이 ACQUIRE 오퍼레이션 후에
-     일어난 것으로 시스템의 나머지 컴포넌트들에 보이게 될 것이 보장됩니다.
-     LOCK 오퍼레이션과 smp_load_acquire(), smp_cond_acquire() 오퍼레이션도
-     ACQUIRE 오퍼레이션에 포함됩니다.  smp_cond_acquire() 오퍼레이션은 컨트롤
-     의존성과 smp_rmb() 를 사용해서 ACQUIRE 의 의미적 요구사항(semantic)을
-     충족시킵니다.
-
-     ACQUIRE 오퍼레이션 앞의 메모리 오퍼레이션들은 ACQUIRE 오퍼레이션 완료 후에
-     수행된 것처럼 보일 수 있습니다.
-
-     ACQUIRE 오퍼레이션은 거의 항상 RELEASE 오퍼레이션과 짝을 지어 사용되어야
-     합니다.
-
-
- (6) RELEASE 오퍼레이션.
-
-     이 타입의 오퍼레이션들도 단방향 투과성 배리어처럼 동작합니다.  RELEASE
-     오퍼레이션 앞의 모든 메모리 오퍼레이션들은 RELEASE 오퍼레이션 전에 완료된
-     것으로 시스템의 다른 컴포넌트들에 보여질 것이 보장됩니다.  UNLOCK 류의
-     오퍼레이션들과 smp_store_release() 오퍼레이션도 RELEASE 오퍼레이션의
-     일종입니다.
-
-     RELEASE 오퍼레이션 뒤의 메모리 오퍼레이션들은 RELEASE 오퍼레이션이
-     완료되기 전에 행해진 것처럼 보일 수 있습니다.
-
-     ACQUIRE 와 RELEASE 오퍼레이션의 사용은 일반적으로 다른 메모리 배리어의
-     필요성을 없앱니다 (하지만 "MMIO 쓰기 배리어" 서브섹션에서 설명되는 예외를
-     알아두세요).  또한, RELEASE+ACQUIRE 조합은 범용 메모리 배리어처럼 동작할
-     것을 보장하지 -않습니다-.  하지만, 어떤 변수에 대한 RELEASE 오퍼레이션을
-     앞서는 메모리 액세스들의 수행 결과는 이 RELEASE 오퍼레이션을 뒤이어 같은
-     변수에 대해 수행된 ACQUIRE 오퍼레이션을 뒤따르는 메모리 액세스에는 보여질
-     것이 보장됩니다.  다르게 말하자면, 주어진 변수의 크리티컬 섹션에서는, 해당
-     변수에 대한 앞의 크리티컬 섹션에서의 모든 액세스들이 완료되었을 것을
-     보장합니다.
-
-     즉, ACQUIRE 는 최소한의 "취득" 동작처럼, 그리고 RELEASE 는 최소한의 "공개"
-     처럼 동작한다는 의미입니다.
-
-atomic_ops.txt 에서 설명되는 어토믹 오퍼레이션들 중에는 완전히 순서잡힌 것들과
-(배리어를 사용하지 않는) 완화된 순서의 것들 외에 ACQUIRE 와 RELEASE 부류의
-것들도 존재합니다.  로드와 스토어를 모두 수행하는 조합된 어토믹 오퍼레이션에서,
-ACQUIRE 는 해당 오퍼레이션의 로드 부분에만 적용되고 RELEASE 는 해당
-오퍼레이션의 스토어 부분에만 적용됩니다.
-
-메모리 배리어들은 두 CPU 간, 또는 CPU 와 디바이스 간에 상호작용의 가능성이 있을
-때에만 필요합니다.  만약 어떤 코드에 그런 상호작용이 없을 것이 보장된다면, 해당
-코드에서는 메모리 배리어를 사용할 필요가 없습니다.
-
-
-이것들은 _최소한의_ 보장사항들임을 알아두세요.  다른 아키텍쳐에서는 더 강력한
-보장사항을 제공할 수도 있습니다만, 그런 보장사항은 아키텍쳐 종속적 코드 이외의
-부분에서는 신뢰되지 _않을_ 겁니다.
-
-
-메모리 배리어에 대해 가정해선 안될 것
--------------------------------------
-
-리눅스 커널 메모리 배리어들이 보장하지 않는 것들이 있습니다:
-
- (*) 메모리 배리어 앞에서 명시된 어떤 메모리 액세스도 메모리 배리어 명령의 수행
-     완료 시점까지 _완료_ 될 것이란 보장은 없습니다; 배리어가 하는 일은 CPU 의
-     액세스 큐에 특정 타입의 액세스들은 넘을 수 없는 선을 긋는 것으로 생각될 수
-     있습니다.
-
- (*) 한 CPU 에서 메모리 배리어를 수행하는게 시스템의 다른 CPU 나 하드웨어에
-     어떤 직접적인 영향을 끼친다는 보장은 존재하지 않습니다.  배리어 수행이
-     만드는 간접적 영향은 두번째 CPU 가 첫번째 CPU 의 액세스들의 결과를
-     바라보는 순서가 됩니다만, 다음 항목을 보세요:
-
- (*) 첫번째 CPU 가 두번째 CPU 의 메모리 액세스들의 결과를 바라볼 때, _설령_
-     두번째 CPU 가 메모리 배리어를 사용한다 해도, 첫번째 CPU _또한_ 그에 맞는
-     메모리 배리어를 사용하지 않는다면 ("SMP 배리어 짝맞추기" 서브섹션을
-     참고하세요) 그 결과가 올바른 순서로 보여진다는 보장은 없습니다.
-
- (*) CPU 바깥의 하드웨어[*] 가 메모리 액세스들의 순서를 바꾸지 않는다는 보장은
-     존재하지 않습니다.  CPU 캐시 일관성 메커니즘은 메모리 배리어의 간접적
-     영향을 CPU 사이에 전파하긴 하지만, 순서대로 전파하지는 않을 수 있습니다.
-
-	[*] 버스 마스터링 DMA 와 일관성에 대해서는 다음을 참고하시기 바랍니다:
-
-	    Documentation/PCI/pci.txt
-	    Documentation/DMA-API-HOWTO.txt
-	    Documentation/DMA-API.txt
-
-
-데이터 의존성 배리어
---------------------
-
-데이터 의존성 배리어의 사용에 있어 지켜야 하는 사항들은 약간 미묘하고, 데이터
-의존성 배리어가 사용되어야 하는 상황도 항상 명백하지는 않습니다.  설명을 위해
-다음의 이벤트 시퀀스를 생각해 봅시다:
-
-	CPU 1		      CPU 2
-	===============	      ===============
-	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
-	B = 4;
-	<쓰기 배리어>
-	WRITE_ONCE(P, &B)
-			      Q = READ_ONCE(P);
-			      D = *Q;
-
-여기엔 분명한 데이터 의존성이 존재하므로, 이 시퀀스가 끝났을 때 Q 는 &A 또는 &B
-일 것이고, 따라서:
-
-	(Q == &A) 는 (D == 1) 를,
-	(Q == &B) 는 (D == 4) 를 의미합니다.
-
-하지만!  CPU 2 는 B 의 업데이트를 인식하기 전에 P 의 업데이트를 인식할 수 있고,
-따라서 다음의 결과가 가능합니다:
-
-	(Q == &B) and (D == 2) ????
-
-이런 결과는 일관성이나 인과 관계 유지가 실패한 것처럼 보일 수도 있겠지만,
-그렇지 않습니다, 그리고 이 현상은 (DEC Alpha 와 같은) 여러 CPU 에서 실제로
-발견될 수 있습니다.
-
-이 문제 상황을 제대로 해결하기 위해, 데이터 의존성 배리어나 그보다 강화된
-무언가가 주소를 읽어올 때와 데이터를 읽어올 때 사이에 추가되어야만 합니다:
-
-	CPU 1		      CPU 2
-	===============	      ===============
-	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
-	B = 4;
-	<쓰기 배리어>
-	WRITE_ONCE(P, &B);
-			      Q = READ_ONCE(P);
-			      <데이터 의존성 배리어>
-			      D = *Q;
-
-이 변경은 앞의 처음 두가지 결과 중 하나만이 발생할 수 있고, 세번째의 결과는
-발생할 수 없도록 합니다.
-
-데이터 의존성 배리어는 의존적 쓰기에 대해서도 순서를 잡아줍니다:
-
-	CPU 1		      CPU 2
-	===============	      ===============
-	{ A == 1, B == 2, C = 3, P == &A, Q == &C }
-	B = 4;
-	<쓰기 배리어>
-	WRITE_ONCE(P, &B);
-			      Q = READ_ONCE(P);
-			      <데이터 의존성 배리어>
-			      *Q = 5;
-
-이 데이터 의존성 배리어는 Q 로의 읽기가 *Q 로의 스토어와 순서를 맞추게
-해줍니다.  이는 다음과 같은 결과를 막습니다:
-
-	(Q == &B) && (B == 4)
-
-이런 패턴은 드물게 사용되어야 함을 알아 두시기 바랍니다.  무엇보다도, 의존성
-순서 규칙의 의도는 쓰기 작업을 -예방- 해서 그로 인해 발생하는 비싼 캐시 미스도
-없애려는 것입니다.  이 패턴은 드물게 발생하는 에러 조건 같은것들을 기록하는데
-사용될 수 있고, 이렇게 배리어를 사용해 순서를 지키게 함으로써 그런 기록이
-사라지는 것을 막습니다.
-
-
-[!] 상당히 비직관적인 이 상황은 분리된 캐시를 가진 기계, 예를 들어 한 캐시
-뱅크가 짝수번 캐시 라인을 처리하고 다른 뱅크는 홀수번 캐시 라인을 처리하는 기계
-등에서 가장 잘 발생합니다.  포인터 P 는 홀수 번호의 캐시 라인에 있고, 변수 B 는
-짝수 번호 캐시 라인에 있다고 생각해 봅시다.  그런 상태에서 읽기 작업을 하는 CPU
-의 짝수번 뱅크는 할 일이 쌓여 매우 바쁘지만 홀수번 뱅크는 할 일이 없어 아무
-일도 하지 않고  있었다면, 포인터 P 는 새 값 (&B) 을, 그리고 변수 B 는 옛날 값
-(2) 을 가지고 있는 상태가 보여질 수도 있습니다.
-
-
-데이터 의존성 배리어는 매우 중요한데, 예를 들어 RCU 시스템에서 그렇습니다.
-include/linux/rcupdate.h 의 rcu_assign_pointer() 와 rcu_dereference() 를
-참고하세요.  여기서 데이터 의존성 배리어는 RCU 로 관리되는 포인터의 타겟을 현재
-타겟에서 수정된 새로운 타겟으로 바꾸는 작업에서 새로 수정된 타겟이 초기화가
-완료되지 않은 채로 보여지는 일이 일어나지 않게 해줍니다.
-
-더 많은 예를 위해선 "캐시 일관성" 서브섹션을 참고하세요.
-
-
-컨트롤 의존성
--------------
-
-로드-로드 컨트롤 의존성은 데이터 의존성 배리어만으로는 정확히 동작할 수가
-없어서 읽기 메모리 배리어를 필요로 합니다.  아래의 코드를 봅시다:
-
-	q = READ_ONCE(a);
-	if (q) {
-		<데이터 의존성 배리어>  /* BUG: No data dependency!!! */
-		p = READ_ONCE(b);
-	}
-
-이 코드는 원하는 대로의 효과를 내지 못할 수 있는데, 이 코드에는 데이터 의존성이
-아니라 컨트롤 의존성이 존재하기 때문으로, 이런 상황에서 CPU 는 실행 속도를 더
-빠르게 하기 위해 분기 조건의 결과를 예측하고 코드를 재배치 할 수 있어서 다른
-CPU 는 b 로부터의 로드 오퍼레이션이 a 로부터의 로드 오퍼레이션보다 먼저 발생한
-걸로 인식할 수 있습니다.  여기에 정말로 필요했던 건 다음과 같습니다:
-
-	q = READ_ONCE(a);
-	if (q) {
-		<읽기 배리어>
-		p = READ_ONCE(b);
-	}
-
-하지만, 스토어 오퍼레이션은 예측적으로 수행되지 않습니다.  즉, 다음 예에서와
-같이 로드-스토어 컨트롤 의존성이 존재하는 경우에는 순서가 -지켜진다-는
-의미입니다.
-
-	q = READ_ONCE(a);
-	if (q) {
-		WRITE_ONCE(b, p);
-	}
-
-컨트롤 의존성은 보통 다른 타입의 배리어들과 짝을 맞춰 사용됩니다.  그렇다곤
-하나, READ_ONCE() 는 반드시 사용해야 함을 부디 명심하세요!  READ_ONCE() 가
-없다면, 컴파일러가 'a' 로부터의 로드를 'a' 로부터의 또다른 로드와, 'b' 로의
-스토어를 'b' 로의 또다른 스토어와 조합해 버려 매우 비직관적인 결과를 초래할 수
-있습니다.
-
-이걸로 끝이 아닌게, 컴파일러가 변수 'a' 의 값이 항상 0이 아니라고 증명할 수
-있다면, 앞의 예에서 "if" 문을 없애서 다음과 같이 최적화 할 수도 있습니다:
-
-	q = a;
-	b = p;  /* BUG: Compiler and CPU can both reorder!!! */
-
-그러니 READ_ONCE() 를 반드시 사용하세요.
-
-다음과 같이 "if" 문의 양갈래 브랜치에 모두 존재하는 동일한 스토어에 대해 순서를
-강제하고 싶은 경우가 있을 수 있습니다:
-
-	q = READ_ONCE(a);
-	if (q) {
-		barrier();
-		WRITE_ONCE(b, p);
-		do_something();
-	} else {
-		barrier();
-		WRITE_ONCE(b, p);
-		do_something_else();
-	}
-
-안타깝게도, 현재의 컴파일러들은 높은 최적화 레벨에서는 이걸 다음과 같이
-바꿔버립니다:
-
-	q = READ_ONCE(a);
-	barrier();
-	WRITE_ONCE(b, p);  /* BUG: No ordering vs. load from a!!! */
-	if (q) {
-		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
-		do_something();
-	} else {
-		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
-		do_something_else();
-	}
-
-이제 'a' 에서의 로드와 'b' 로의 스토어 사이에는 조건적 관계가 없기 때문에 CPU
-는 이들의 순서를 바꿀 수 있게 됩니다: 이런 경우에 조건적 관계는 반드시
-필요한데, 모든 컴파일러 최적화가 이루어지고 난 후의 어셈블리 코드에서도
-마찬가지입니다.  따라서, 이 예에서 순서를 지키기 위해서는 smp_store_release()
-와 같은 명시적 메모리 배리어가 필요합니다:
-
-	q = READ_ONCE(a);
-	if (q) {
-		smp_store_release(&b, p);
-		do_something();
-	} else {
-		smp_store_release(&b, p);
-		do_something_else();
-	}
-
-반면에 명시적 메모리 배리어가 없다면, 이런 경우의 순서는 스토어 오퍼레이션들이
-서로 다를 때에만 보장되는데, 예를 들면 다음과 같은 경우입니다:
-
-	q = READ_ONCE(a);
-	if (q) {
-		WRITE_ONCE(b, p);
-		do_something();
-	} else {
-		WRITE_ONCE(b, r);
-		do_something_else();
-	}
-
-처음의 READ_ONCE() 는 컴파일러가 'a' 의 값을 증명해내는 것을 막기 위해 여전히
-필요합니다.
-
-또한, 로컬 변수 'q' 를 가지고 하는 일에 대해 주의해야 하는데, 그러지 않으면
-컴파일러는 그 값을 추측하고 또다시 필요한 조건관계를 없애버릴 수 있습니다.
-예를 들면:
-
-	q = READ_ONCE(a);
-	if (q % MAX) {
-		WRITE_ONCE(b, p);
-		do_something();
-	} else {
-		WRITE_ONCE(b, r);
-		do_something_else();
-	}
-
-만약 MAX 가 1 로 정의된 상수라면, 컴파일러는 (q % MAX) 는 0이란 것을 알아채고,
-위의 코드를 아래와 같이 바꿔버릴 수 있습니다:
-
-	q = READ_ONCE(a);
-	WRITE_ONCE(b, p);
-	do_something_else();
-
-이렇게 되면, CPU 는 변수 'a' 로부터의 로드와 변수 'b' 로의 스토어 사이의 순서를
-지켜줄 필요가 없어집니다.  barrier() 를 추가해 해결해 보고 싶겠지만, 그건
-도움이 안됩니다.  조건 관계는 사라졌고, barrier() 는 이를 되돌리지 못합니다.
-따라서, 이 순서를 지켜야 한다면, MAX 가 1 보다 크다는 것을, 다음과 같은 방법을
-사용해 분명히 해야 합니다:
-
-	q = READ_ONCE(a);
-	BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */
-	if (q % MAX) {
-		WRITE_ONCE(b, p);
-		do_something();
-	} else {
-		WRITE_ONCE(b, r);
-		do_something_else();
-	}
-
-'b' 로의 스토어들은 여전히 서로 다름을 알아두세요.  만약 그것들이 동일하면,
-앞에서 이야기했듯, 컴파일러가 그 스토어 오퍼레이션들을 'if' 문 바깥으로
-끄집어낼 수 있습니다.
-
-또한 이진 조건문 평가에 너무 의존하지 않도록 조심해야 합니다.  다음의 예를
-봅시다:
-
-	q = READ_ONCE(a);
-	if (q || 1 > 0)
-		WRITE_ONCE(b, 1);
-
-첫번째 조건만으로는 브랜치 조건 전체를 거짓으로 만들 수 없고 두번째 조건은 항상
-참이기 때문에, 컴파일러는 이 예를 다음과 같이 바꿔서 컨트롤 의존성을 없애버릴
-수 있습니다:
-
-	q = READ_ONCE(a);
-	WRITE_ONCE(b, 1);
-
-이 예는 컴파일러가 코드를 추측으로 수정할 수 없도록 분명히 해야 한다는 점을
-강조합니다.  조금 더 일반적으로 말해서, READ_ONCE() 는 컴파일러에게 주어진 로드
-오퍼레이션을 위한 코드를 정말로 만들도록 하지만, 컴파일러가 그렇게 만들어진
-코드의 수행 결과를 사용하도록 강제하지는 않습니다.
-
-마지막으로, 컨트롤 의존성은 이행성 (transitivity) 을 제공하지 -않습니다-.  이건
-x 와 y 가 둘 다 0 이라는 초기값을 가졌다는 가정 하의 두개의 예제로
-보이겠습니다:
-
-	CPU 0                     CPU 1
-	=======================   =======================
-	r1 = READ_ONCE(x);        r2 = READ_ONCE(y);
-	if (r1 > 0)               if (r2 > 0)
-	  WRITE_ONCE(y, 1);         WRITE_ONCE(x, 1);
-
-	assert(!(r1 == 1 && r2 == 1));
-
-이 두 CPU 예제에서 assert() 의 조건은 항상 참일 것입니다.  그리고, 만약 컨트롤
-의존성이 이행성을 (실제로는 그러지 않지만) 보장한다면, 다음의 CPU 가 추가되어도
-아래의 assert() 조건은 참이 될것입니다:
-
-	CPU 2
-	=====================
-	WRITE_ONCE(x, 2);
-
-	assert(!(r1 == 2 && r2 == 1 && x == 2)); /* FAILS!!! */
-
-하지만 컨트롤 의존성은 이행성을 제공하지 -않기- 때문에, 세개의 CPU 예제가 실행
-완료된 후에 위의 assert() 의 조건은 거짓으로 평가될 수 있습니다.  세개의 CPU
-예제가 순서를 지키길 원한다면, CPU 0 와 CPU 1 코드의 로드와 스토어 사이, "if"
-문 바로 다음에 smp_mb()를 넣어야 합니다.  더 나아가서, 최초의 두 CPU 예제는
-매우 위험하므로 사용되지 않아야 합니다.
-
-이 두개의 예제는 다음 논문:
-http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf 와
-이 사이트: https://www.cl.cam.ac.uk/~pes20/ppcmem/index.html 에 나온 LB 와 WWC
-리트머스 테스트입니다.
-
-요약하자면:
-
-  (*) 컨트롤 의존성은 앞의 로드들을 뒤의 스토어들에 대해 순서를 맞춰줍니다.
-      하지만, 그 외의 어떤 순서도 보장하지 -않습니다-: 앞의 로드와 뒤의 로드들
-      사이에도, 앞의 스토어와 뒤의 스토어들 사이에도요.  이런 다른 형태의
-      순서가 필요하다면 smp_rmb() 나 smp_wmb()를, 또는, 앞의 스토어들과 뒤의
-      로드들 사이의 순서를 위해서는 smp_mb() 를 사용하세요.
-
-  (*) "if" 문의 양갈래 브랜치가 같은 변수에의 동일한 스토어로 시작한다면, 그
-      스토어들은 각 스토어 앞에 smp_mb() 를 넣거나 smp_store_release() 를
-      사용해서 스토어를 하는 식으로 순서를 맞춰줘야 합니다.  이 문제를 해결하기
-      위해 "if" 문의 양갈래 브랜치의 시작 지점에 barrier() 를 넣는 것만으로는
-      충분한 해결이 되지 않는데, 이는 앞의 예에서 본것과 같이, 컴파일러의
-      최적화는 barrier() 가 의미하는 바를 지키면서도 컨트롤 의존성을 손상시킬
-      수 있기 때문이라는 점을 부디 알아두시기 바랍니다.
-
-  (*) 컨트롤 의존성은 앞의 로드와 뒤의 스토어 사이에 최소 하나의, 실행
-      시점에서의 조건관계를 필요로 하며, 이 조건관계는 앞의 로드와 관계되어야
-      합니다.  만약 컴파일러가 조건 관계를 최적화로 없앨수 있다면, 순서도
-      최적화로 없애버렸을 겁니다.  READ_ONCE() 와 WRITE_ONCE() 의 주의 깊은
-      사용은 주어진 조건 관계를 유지하는데 도움이 될 수 있습니다.
-
-  (*) 컨트롤 의존성을 위해선 컴파일러가 조건관계를 없애버리는 것을 막아야
-      합니다.  주의 깊은 READ_ONCE() 나 atomic{,64}_read() 의 사용이 컨트롤
-      의존성이 사라지지 않게 하는데 도움을 줄 수 있습니다.  더 많은 정보를
-      위해선 "컴파일러 배리어" 섹션을 참고하시기 바랍니다.
-
-  (*) 컨트롤 의존성은 보통 다른 타입의 배리어들과 짝을 맞춰 사용됩니다.
-
-  (*) 컨트롤 의존성은 이행성을 제공하지 -않습니다-.  이행성이 필요하다면,
-      smp_mb() 를 사용하세요.
-
-
-SMP 배리어 짝맞추기
---------------------
-
-CPU 간 상호작용을 다룰 때에 일부 타입의 메모리 배리어는 항상 짝을 맞춰
-사용되어야 합니다.  적절하게 짝을 맞추지 않은 코드는 사실상 에러에 가깝습니다.
-
-범용 배리어들은 범용 배리어끼리도 짝을 맞추지만 이행성이 없는 대부분의 다른
-타입의 배리어들과도 짝을 맞춥니다.  ACQUIRE 배리어는 RELEASE 배리어와 짝을
-맞춥니다만, 둘 다 범용 배리어를 포함해 다른 배리어들과도 짝을 맞출 수 있습니다.
-쓰기 배리어는 데이터 의존성 배리어나 컨트롤 의존성, ACQUIRE 배리어, RELEASE
-배리어, 읽기 배리어, 또는 범용 배리어와 짝을 맞춥니다.  비슷하게 읽기 배리어나
-컨트롤 의존성, 또는 데이터 의존성 배리어는 쓰기 배리어나 ACQUIRE 배리어,
-RELEASE 배리어, 또는 범용 배리어와 짝을 맞추는데, 다음과 같습니다:
-
-	CPU 1		      CPU 2
-	===============	      ===============
-	WRITE_ONCE(a, 1);
-	<쓰기 배리어>
-	WRITE_ONCE(b, 2);     x = READ_ONCE(b);
-			      <읽기 배리어>
-			      y = READ_ONCE(a);
-
-또는:
-
-	CPU 1		      CPU 2
-	===============	      ===============================
-	a = 1;
-	<쓰기 배리어>
-	WRITE_ONCE(b, &a);    x = READ_ONCE(b);
-			      <데이터 의존성 배리어>
-			      y = *x;
-
-또는:
-
-	CPU 1		      CPU 2
-	===============	      ===============================
-	r1 = READ_ONCE(y);
-	<범용 배리어>
-	WRITE_ONCE(y, 1);     if (r2 = READ_ONCE(x)) {
-			         <묵시적 컨트롤 의존성>
-			         WRITE_ONCE(y, 1);
-			      }
-
-	assert(r1 == 0 || r2 == 0);
-
-기본적으로, 여기서의 읽기 배리어는 "더 완화된" 타입일 순 있어도 항상 존재해야
-합니다.
-
-[!] 쓰기 배리어 앞의 스토어 오퍼레이션은 일반적으로 읽기 배리어나 데이터
-의존성 배리어 뒤의 로드 오퍼레이션과 매치될 것이고, 반대도 마찬가지입니다:
-
-	CPU 1                               CPU 2
-	===================                 ===================
-	WRITE_ONCE(a, 1);    }----   --->{  v = READ_ONCE(c);
-	WRITE_ONCE(b, 2);    }    \ /    {  w = READ_ONCE(d);
-	<쓰기 배리어>              \        <읽기 배리어>
-	WRITE_ONCE(c, 3);    }    / \    {  x = READ_ONCE(a);
-	WRITE_ONCE(d, 4);    }----   --->{  y = READ_ONCE(b);
-
-
-메모리 배리어 시퀀스의 예
--------------------------
-
-첫째, 쓰기 배리어는 스토어 오퍼레이션들의 부분적 순서 세우기로 동작합니다.
-아래의 이벤트 시퀀스를 보세요:
-
-	CPU 1
-	=======================
-	STORE A = 1
-	STORE B = 2
-	STORE C = 3
-	<쓰기 배리어>
-	STORE D = 4
-	STORE E = 5
-
-이 이벤트 시퀀스는 메모리 일관성 시스템에 원소끼리의 순서가 존재하지 않는 집합
-{ STORE A, STORE B, STORE C } 가 역시 원소끼리의 순서가 존재하지 않는 집합
-{ STORE D, STORE E } 보다 먼저 일어난 것으로 시스템의 나머지 요소들에 보이도록
-전달됩니다:
-
-	+-------+       :      :
-	|       |       +------+
-	|       |------>| C=3  |     }     /\
-	|       |  :    +------+     }-----  \  -----> 시스템의 나머지 요소에
-	|       |  :    | A=1  |     }        \/       보여질 수 있는 이벤트들
-	|       |  :    +------+     }
-	| CPU 1 |  :    | B=2  |     }
-	|       |       +------+     }
-	|       |   wwwwwwwwwwwwwwww }   <--- 여기서 쓰기 배리어는 배리어 앞의
-	|       |       +------+     }        모든 스토어가 배리어 뒤의 스토어
-	|       |  :    | E=5  |     }        전에 메모리 시스템에 전달되도록
-	|       |  :    +------+     }        합니다
-	|       |------>| D=4  |     }
-	|       |       +------+
-	+-------+       :      :
-	                   |
-	                   | CPU 1 에 의해 메모리 시스템에 전달되는
-	                   | 일련의 스토어 오퍼레이션들
-	                   V
-
-
-둘째, 데이터 의존성 배리어는 데이터 의존적 로드 오퍼레이션들의 부분적 순서
-세우기로 동작합니다.  다음 일련의 이벤트들을 보세요:
-
-	CPU 1			CPU 2
-	=======================	=======================
-		{ B = 7; X = 9; Y = 8; C = &Y }
-	STORE A = 1
-	STORE B = 2
-	<쓰기 배리어>
-	STORE C = &B		LOAD X
-	STORE D = 4		LOAD C (gets &B)
-				LOAD *C (reads B)
-
-여기에 별다른 개입이 없다면, CPU 1 의 쓰기 배리어에도 불구하고 CPU 2 는 CPU 1
-의 이벤트들을 완전히 무작위적 순서로 인지하게 됩니다:
-
-	+-------+       :      :                :       :
-	|       |       +------+                +-------+  | CPU 2 에 인지되는
-	|       |------>| B=2  |-----       --->| Y->8  |  | 업데이트 이벤트
-	|       |  :    +------+     \          +-------+  | 시퀀스
-	| CPU 1 |  :    | A=1  |      \     --->| C->&Y |  V
-	|       |       +------+       |        +-------+
-	|       |   wwwwwwwwwwwwwwww   |        :       :
-	|       |       +------+       |        :       :
-	|       |  :    | C=&B |---    |        :       :       +-------+
-	|       |  :    +------+   \   |        +-------+       |       |
-	|       |------>| D=4  |    ----------->| C->&B |------>|       |
-	|       |       +------+       |        +-------+       |       |
-	+-------+       :      :       |        :       :       |       |
-	                               |        :       :       |       |
-	                               |        :       :       | CPU 2 |
-	                               |        +-------+       |       |
-	    분명히 잘못된        --->  |        | B->7  |------>|       |
-	    B 의 값 인지 (!)           |        +-------+       |       |
-	                               |        :       :       |       |
-	                               |        +-------+       |       |
-	    X 의 로드가 B 의    --->    \       | X->9  |------>|       |
-	    일관성 유지를                \      +-------+       |       |
-	    지연시킴                      ----->| B->2  |       +-------+
-	                                        +-------+
-	                                        :       :
-
-
-앞의 예에서, CPU 2 는 (B 의 값이 될) *C 의 값 읽기가 C 의 LOAD 뒤에 이어짐에도
-B 가 7 이라는 결과를 얻습니다.
-
-하지만, 만약 데이터 의존성 배리어가 C 의 로드와 *C (즉, B) 의 로드 사이에
-있었다면:
-
-	CPU 1			CPU 2
-	=======================	=======================
-		{ B = 7; X = 9; Y = 8; C = &Y }
-	STORE A = 1
-	STORE B = 2
-	<쓰기 배리어>
-	STORE C = &B		LOAD X
-	STORE D = 4		LOAD C (gets &B)
-				<데이터 의존성 배리어>
-				LOAD *C (reads B)
-
-다음과 같이 됩니다:
-
-	+-------+       :      :                :       :
-	|       |       +------+                +-------+
-	|       |------>| B=2  |-----       --->| Y->8  |
-	|       |  :    +------+     \          +-------+
-	| CPU 1 |  :    | A=1  |      \     --->| C->&Y |
-	|       |       +------+       |        +-------+
-	|       |   wwwwwwwwwwwwwwww   |        :       :
-	|       |       +------+       |        :       :
-	|       |  :    | C=&B |---    |        :       :       +-------+
-	|       |  :    +------+   \   |        +-------+       |       |
-	|       |------>| D=4  |    ----------->| C->&B |------>|       |
-	|       |       +------+       |        +-------+       |       |
-	+-------+       :      :       |        :       :       |       |
-	                               |        :       :       |       |
-	                               |        :       :       | CPU 2 |
-	                               |        +-------+       |       |
-	                               |        | X->9  |------>|       |
-	                               |        +-------+       |       |
-	  C 로의 스토어 앞의     --->   \   ddddddddddddddddd   |       |
-	  모든 이벤트 결과가             \      +-------+       |       |
-	  뒤의 로드에게                   ----->| B->2  |------>|       |
-	  보이게 강제한다                       +-------+       |       |
-	                                        :       :       +-------+
-
-
-셋째, 읽기 배리어는 로드 오퍼레이션들에의 부분적 순서 세우기로 동작합니다.
-아래의 일련의 이벤트를 봅시다:
-
-	CPU 1			CPU 2
-	=======================	=======================
-		{ A = 0, B = 9 }
-	STORE A=1
-	<쓰기 배리어>
-	STORE B=2
-				LOAD B
-				LOAD A
-
-CPU 1 은 쓰기 배리어를 쳤지만, 별다른 개입이 없다면 CPU 2 는 CPU 1 에서 행해진
-이벤트의 결과를 무작위적 순서로 인지하게 됩니다.
-
-	+-------+       :      :                :       :
-	|       |       +------+                +-------+
-	|       |------>| A=1  |------      --->| A->0  |
-	|       |       +------+      \         +-------+
-	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
-	|       |       +------+        |       +-------+
-	|       |------>| B=2  |---     |       :       :
-	|       |       +------+   \    |       :       :       +-------+
-	+-------+       :      :    \   |       +-------+       |       |
-	                             ---------->| B->2  |------>|       |
-	                                |       +-------+       | CPU 2 |
-	                                |       | A->0  |------>|       |
-	                                |       +-------+       |       |
-	                                |       :       :       +-------+
-	                                 \      :       :
-	                                  \     +-------+
-	                                   ---->| A->1  |
-	                                        +-------+
-	                                        :       :
-
-
-하지만, 만약 읽기 배리어가 B 의 로드와 A 의 로드 사이에 존재한다면:
-
-	CPU 1			CPU 2
-	=======================	=======================
-		{ A = 0, B = 9 }
-	STORE A=1
-	<쓰기 배리어>
-	STORE B=2
-				LOAD B
-				<읽기 배리어>
-				LOAD A
-
-CPU 1 에 의해 만들어진 부분적 순서가 CPU 2 에도 그대로 인지됩니다:
-
-	+-------+       :      :                :       :
-	|       |       +------+                +-------+
-	|       |------>| A=1  |------      --->| A->0  |
-	|       |       +------+      \         +-------+
-	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
-	|       |       +------+        |       +-------+
-	|       |------>| B=2  |---     |       :       :
-	|       |       +------+   \    |       :       :       +-------+
-	+-------+       :      :    \   |       +-------+       |       |
-	                             ---------->| B->2  |------>|       |
-	                                |       +-------+       | CPU 2 |
-	                                |       :       :       |       |
-	                                |       :       :       |       |
-	  여기서 읽기 배리어는   ---->   \  rrrrrrrrrrrrrrrrr   |       |
-	  B 로의 스토어 전의              \     +-------+       |       |
-	  모든 결과를 CPU 2 에             ---->| A->1  |------>|       |
-	  보이도록 한다                         +-------+       |       |
-	                                        :       :       +-------+
-
-
-더 완벽한 설명을 위해, A 의 로드가 읽기 배리어 앞과 뒤에 있으면 어떻게 될지
-생각해 봅시다:
-
-	CPU 1			CPU 2
-	=======================	=======================
-		{ A = 0, B = 9 }
-	STORE A=1
-	<쓰기 배리어>
-	STORE B=2
-				LOAD B
-				LOAD A [first load of A]
-				<읽기 배리어>
-				LOAD A [second load of A]
-
-A 의 로드 두개가 모두 B 의 로드 뒤에 있지만, 서로 다른 값을 얻어올 수
-있습니다:
-
-	+-------+       :      :                :       :
-	|       |       +------+                +-------+
-	|       |------>| A=1  |------      --->| A->0  |
-	|       |       +------+      \         +-------+
-	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
-	|       |       +------+        |       +-------+
-	|       |------>| B=2  |---     |       :       :
-	|       |       +------+   \    |       :       :       +-------+
-	+-------+       :      :    \   |       +-------+       |       |
-	                             ---------->| B->2  |------>|       |
-	                                |       +-------+       | CPU 2 |
-	                                |       :       :       |       |
-	                                |       :       :       |       |
-	                                |       +-------+       |       |
-	                                |       | A->0  |------>| 1st   |
-	                                |       +-------+       |       |
-	  여기서 읽기 배리어는   ---->   \  rrrrrrrrrrrrrrrrr   |       |
-	  B 로의 스토어 전의              \     +-------+       |       |
-	  모든 결과를 CPU 2 에             ---->| A->1  |------>| 2nd   |
-	  보이도록 한다                         +-------+       |       |
-	                                        :       :       +-------+
-
-
-하지만 CPU 1 에서의 A 업데이트는 읽기 배리어가 완료되기 전에도 보일 수도
-있긴 합니다:
-
-	+-------+       :      :                :       :
-	|       |       +------+                +-------+
-	|       |------>| A=1  |------      --->| A->0  |
-	|       |       +------+      \         +-------+
-	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
-	|       |       +------+        |       +-------+
-	|       |------>| B=2  |---     |       :       :
-	|       |       +------+   \    |       :       :       +-------+
-	+-------+       :      :    \   |       +-------+       |       |
-	                             ---------->| B->2  |------>|       |
-	                                |       +-------+       | CPU 2 |
-	                                |       :       :       |       |
-	                                 \      :       :       |       |
-	                                  \     +-------+       |       |
-	                                   ---->| A->1  |------>| 1st   |
-	                                        +-------+       |       |
-	                                    rrrrrrrrrrrrrrrrr   |       |
-	                                        +-------+       |       |
-	                                        | A->1  |------>| 2nd   |
-	                                        +-------+       |       |
-	                                        :       :       +-------+
-
-
-여기서 보장되는 건, 만약 B 의 로드가 B == 2 라는 결과를 봤다면, A 에의 두번째
-로드는 항상 A == 1 을 보게 될 것이라는 겁니다.  A 에의 첫번째 로드에는 그런
-보장이 없습니다; A == 0 이거나 A == 1 이거나 둘 중 하나의 결과를 보게 될겁니다.
-
-
-읽기 메모리 배리어 VS 로드 예측
--------------------------------
-
-많은 CPU들이 로드를 예측적으로 (speculatively) 합니다: 어떤 데이터를 메모리에서
-로드해야 하게 될지 예측을 했다면, 해당 데이터를 로드하는 인스트럭션을 실제로는
-아직 만나지 않았더라도 다른 로드 작업이 없어 버스 (bus) 가 아무 일도 하고 있지
-않다면, 그 데이터를 로드합니다.  이후에 실제 로드 인스트럭션이 실행되면 CPU 가
-이미 그 값을 가지고 있기 때문에 그 로드 인스트럭션은 즉시 완료됩니다.
-
-해당 CPU 는 실제로는 그 값이 필요치 않았다는 사실이 나중에 드러날 수도 있는데 -
-해당 로드 인스트럭션이 브랜치로 우회되거나 했을 수 있겠죠 - , 그렇게 되면 앞서
-읽어둔 값을 버리거나 나중의 사용을 위해 캐시에 넣어둘 수 있습니다.
-
-다음을 생각해 봅시다:
-
-	CPU 1			CPU 2
-	=======================	=======================
-				LOAD B
-				DIVIDE		} 나누기 명령은 일반적으로
-				DIVIDE		} 긴 시간을 필요로 합니다
-				LOAD A
-
-는 이렇게 될 수 있습니다:
-
-	                                        :       :       +-------+
-	                                        +-------+       |       |
-	                                    --->| B->2  |------>|       |
-	                                        +-------+       | CPU 2 |
-	                                        :       :DIVIDE |       |
-	                                        +-------+       |       |
-	나누기 하느라 바쁜       --->       --->| A->0  |~~~~   |       |
-	CPU 는 A 의 LOAD 를                     +-------+   ~   |       |
-	예측해서 수행한다                       :       :   ~   |       |
-	                                        :       :DIVIDE |       |
-	                                        :       :   ~   |       |
-	나누기가 끝나면       --->     --->     :       :   ~-->|       |
-	CPU 는 해당 LOAD 를                     :       :       |       |
-	즉각 완료한다                           :       :       +-------+
-
-
-읽기 배리어나 데이터 의존성 배리어를 두번째 로드 직전에 놓는다면:
-
-	CPU 1			CPU 2
-	=======================	=======================
-				LOAD B
-				DIVIDE
-				DIVIDE
-				<읽기 배리어>
-				LOAD A
-
-예측으로 얻어진 값은 사용된 배리어의 타입에 따라서 해당 값이 옳은지 검토되게
-됩니다.  만약 해당 메모리 영역에 변화가 없었다면, 예측으로 얻어두었던 값이
-사용됩니다:
-
-	                                        :       :       +-------+
-	                                        +-------+       |       |
-	                                    --->| B->2  |------>|       |
-	                                        +-------+       | CPU 2 |
-	                                        :       :DIVIDE |       |
-	                                        +-------+       |       |
-	나누기 하느라 바쁜       --->       --->| A->0  |~~~~   |       |
-	CPU 는 A 의 LOAD 를                     +-------+   ~   |       |
-	예측한다                                :       :   ~   |       |
-	                                        :       :DIVIDE |       |
-	                                        :       :   ~   |       |
-	                                        :       :   ~   |       |
-	                                    rrrrrrrrrrrrrrrr~   |       |
-	                                        :       :   ~   |       |
-	                                        :       :   ~-->|       |
-	                                        :       :       |       |
-	                                        :       :       +-------+
-
-
-하지만 다른 CPU 에서 업데이트나 무효화가 있었다면, 그 예측은 무효화되고 그 값은
-다시 읽혀집니다:
-
-	                                        :       :       +-------+
-	                                        +-------+       |       |
-	                                    --->| B->2  |------>|       |
-	                                        +-------+       | CPU 2 |
-	                                        :       :DIVIDE |       |
-	                                        +-------+       |       |
-	나누기 하느라 바쁜       --->       --->| A->0  |~~~~   |       |
-	CPU 는 A 의 LOAD 를                     +-------+   ~   |       |
-	예측한다                                :       :   ~   |       |
-	                                        :       :DIVIDE |       |
-	                                        :       :   ~   |       |
-	                                        :       :   ~   |       |
-	                                    rrrrrrrrrrrrrrrrr   |       |
-	                                        +-------+       |       |
-	예측성 동작은 무효화 되고    --->   --->| A->1  |------>|       |
-	업데이트된 값이 다시 읽혀진다           +-------+       |       |
-	                                        :       :       +-------+
-
-
-이행성
-------
-
-이행성(transitivity)은 실제의 컴퓨터 시스템에서 항상 제공되지는 않는, 순서
-맞추기에 대한 상당히 직관적인 개념입니다.  다음의 예가 이행성을 보여줍니다:
-
-	CPU 1			CPU 2			CPU 3
-	=======================	=======================	=======================
-		{ X = 0, Y = 0 }
-	STORE X=1		LOAD X			STORE Y=1
-				<범용 배리어>		<범용 배리어>
-				LOAD Y			LOAD X
-
-CPU 2 의 X 로드가 1을 리턴했고 Y 로드가 0을 리턴했다고 해봅시다.  이는 CPU 2 의
-X 로드가 CPU 1 의 X 스토어 뒤에 이루어졌고 CPU 2 의 Y 로드는 CPU 3 의 Y 스토어
-전에 이루어졌음을 의미합니다.  그럼 "CPU 3 의 X 로드는 0을 리턴할 수 있나요?"
-
-CPU 2 의 X 로드는 CPU 1 의 스토어 후에 이루어졌으니, CPU 3 의 X 로드는 1을
-리턴하는게 자연스럽습니다.  이런 생각이 이행성의 한 예입니다: CPU A 에서 실행된
-로드가 CPU B 에서의 같은 변수에 대한 로드를 뒤따른다면, CPU A 의 로드는 CPU B
-의 로드가 내놓은 값과 같거나 그 후의 값을 내놓아야 합니다.
-
-리눅스 커널에서 범용 배리어의 사용은 이행성을 보장합니다.  따라서, 앞의 예에서
-CPU 2 의 X 로드가 1을, Y 로드는 0을 리턴했다면, CPU 3 의 X 로드는 반드시 1을
-리턴합니다.
-
-하지만, 읽기나 쓰기 배리어에 대해서는 이행성이 보장되지 -않습니다-.  예를 들어,
-앞의 예에서 CPU 2 의 범용 배리어가 아래처럼 읽기 배리어로 바뀐 경우를 생각해
-봅시다:
-
-	CPU 1			CPU 2			CPU 3
-	=======================	=======================	=======================
-		{ X = 0, Y = 0 }
-	STORE X=1		LOAD X			STORE Y=1
-				<읽기 배리어>		<범용 배리어>
-				LOAD Y			LOAD X
-
-이 코드는 이행성을 갖지 않습니다: 이 예에서는, CPU 2 의 X 로드가 1을
-리턴하고, Y 로드는 0을 리턴하지만 CPU 3 의 X 로드가 0을 리턴하는 것도 완전히
-합법적입니다.
-
-CPU 2 의 읽기 배리어가 자신의 읽기는 순서를 맞춰줘도, CPU 1 의 스토어와의
-순서를 맞춰준다고는 보장할 수 없다는게 핵심입니다.  따라서, CPU 1 과 CPU 2 가
-버퍼나 캐시를 공유하는 시스템에서 이 예제 코드가 실행된다면, CPU 2 는 CPU 1 이
-쓴 값에 좀 빨리 접근할 수 있을 것입니다.  따라서 CPU 1 과 CPU 2 의 접근으로
-조합된 순서를 모든 CPU 가 동의할 수 있도록 하기 위해 범용 배리어가 필요합니다.
-
-범용 배리어는 "글로벌 이행성"을 제공해서, 모든 CPU 들이 오퍼레이션들의 순서에
-동의하게 할 것입니다.  반면, release-acquire 조합은 "로컬 이행성" 만을
-제공해서, 해당 조합이 사용된 CPU 들만이 해당 액세스들의 조합된 순서에 동의함이
-보장됩니다.  예를 들어, 존경스런 Herman Hollerith 의 C 코드로 보면:
-
-	int u, v, x, y, z;
-
-	void cpu0(void)
-	{
-		r0 = smp_load_acquire(&x);
-		WRITE_ONCE(u, 1);
-		smp_store_release(&y, 1);
-	}
-
-	void cpu1(void)
-	{
-		r1 = smp_load_acquire(&y);
-		r4 = READ_ONCE(v);
-		r5 = READ_ONCE(u);
-		smp_store_release(&z, 1);
-	}
-
-	void cpu2(void)
-	{
-		r2 = smp_load_acquire(&z);
-		smp_store_release(&x, 1);
-	}
-
-	void cpu3(void)
-	{
-		WRITE_ONCE(v, 1);
-		smp_mb();
-		r3 = READ_ONCE(u);
-	}
-
-cpu0(), cpu1(), 그리고 cpu2() 는 smp_store_release()/smp_load_acquire() 쌍의
-연결을 통한 로컬 이행성에 동참하고 있으므로, 다음과 같은 결과는 나오지 않을
-겁니다:
-
-	r0 == 1 && r1 == 1 && r2 == 1
-
-더 나아가서, cpu0() 와 cpu1() 사이의 release-acquire 관계로 인해, cpu1() 은
-cpu0() 의 쓰기를 봐야만 하므로, 다음과 같은 결과도 없을 겁니다:
-
-	r1 == 1 && r5 == 0
-
-하지만, release-acquire 타동성은 동참한 CPU 들에만 적용되므로 cpu3() 에는
-적용되지 않습니다.  따라서, 다음과 같은 결과가 가능합니다:
-
-	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
-
-비슷하게, 다음과 같은 결과도 가능합니다:
-
-	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 && r5 == 1
-
-cpu0(), cpu1(), 그리고 cpu2() 는 그들의 읽기와 쓰기를 순서대로 보게 되지만,
-release-acquire 체인에 관여되지 않은 CPU 들은 그 순서에 이견을 가질 수
-있습니다.  이런 이견은 smp_load_acquire() 와 smp_store_release() 의 구현에
-사용되는 완화된 메모리 배리어 인스트럭션들은 항상 배리어 앞의 스토어들을 뒤의
-로드들에 앞세울 필요는 없다는 사실에서 기인합니다.  이 말은 cpu3() 는 cpu0() 의
-u 로의 스토어를 cpu1() 의 v 로부터의 로드 뒤에 일어난 것으로 볼 수 있다는
-뜻입니다, cpu0() 와 cpu1() 은 이 두 오퍼레이션이 의도된 순서대로 일어났음에
-모두 동의하는데도 말입니다.
-
-하지만, smp_load_acquire() 는 마술이 아님을 명심하시기 바랍니다.  구체적으로,
-이 함수는 단순히 순서 규칙을 지키며 인자로부터의 읽기를 수행합니다.  이것은
-어떤 특정한 값이 읽힐 것인지는 보장하지 -않습니다-.  따라서, 다음과 같은 결과도
-가능합니다:
-
-	r0 == 0 && r1 == 0 && r2 == 0 && r5 == 0
-
-이런 결과는 어떤 것도 재배치 되지 않는, 순차적 일관성을 가진 가상의
-시스템에서도 일어날 수 있음을 기억해 두시기 바랍니다.
-
-다시 말하지만, 당신의 코드가 글로벌 이행성을 필요로 한다면, 범용 배리어를
-사용하십시오.
-
-
-==================
-명시적 커널 배리어
-==================
-
-리눅스 커널은 서로 다른 단계에서 동작하는 다양한 배리어들을 가지고 있습니다:
-
-  (*) 컴파일러 배리어.
-
-  (*) CPU 메모리 배리어.
-
-  (*) MMIO 쓰기 배리어.
-
-
-컴파일러 배리어
----------------
-
-리눅스 커널은 컴파일러가 메모리 액세스를 재배치 하는 것을 막아주는 명시적인
-컴파일러 배리어를 가지고 있습니다:
-
-	barrier();
-
-이건 범용 배리어입니다 -- barrier() 의 읽기-읽기 나 쓰기-쓰기 변종은 없습니다.
-하지만, READ_ONCE() 와 WRITE_ONCE() 는 특정 액세스들에 대해서만 동작하는
-barrier() 의 완화된 형태로 볼 수 있습니다.
-
-barrier() 함수는 다음과 같은 효과를 갖습니다:
-
- (*) 컴파일러가 barrier() 뒤의 액세스들이 barrier() 앞의 액세스보다 앞으로
-     재배치되지 못하게 합니다.  예를 들어, 인터럽트 핸들러 코드와 인터럽트 당한
-     코드 사이의 통신을 신중히 하기 위해 사용될 수 있습니다.
-
- (*) 루프에서, 컴파일러가 루프 조건에 사용된 변수를 매 이터레이션마다
-     메모리에서 로드하지 않아도 되도록 최적화 하는걸 방지합니다.
-
-READ_ONCE() 와 WRITE_ONCE() 함수는 싱글 쓰레드 코드에서는 문제 없지만 동시성이
-있는 코드에서는 문제가 될 수 있는 모든 최적화를 막습니다.  이런 류의 최적화에
-대한 예를 몇가지 들어보면 다음과 같습니다:
-
- (*) 컴파일러는 같은 변수에 대한 로드와 스토어를 재배치 할 수 있고, 어떤
-     경우에는 CPU가 같은 변수로부터의 로드들을 재배치할 수도 있습니다.  이는
-     다음의 코드가:
-
-	a[0] = x;
-	a[1] = x;
-
-     x 의 예전 값이 a[1] 에, 새 값이 a[0] 에 있게 할 수 있다는 뜻입니다.
-     컴파일러와 CPU가 이런 일을 못하게 하려면 다음과 같이 해야 합니다:
-
-	a[0] = READ_ONCE(x);
-	a[1] = READ_ONCE(x);
-
-     즉, READ_ONCE() 와 WRITE_ONCE() 는 여러 CPU 에서 하나의 변수에 가해지는
-     액세스들에 캐시 일관성을 제공합니다.
-
- (*) 컴파일러는 같은 변수에 대한 연속적인 로드들을 병합할 수 있습니다.  그런
-     병합 작업으로 컴파일러는 다음의 코드를:
-
-	while (tmp = a)
-		do_something_with(tmp);
-
-     다음과 같이, 싱글 쓰레드 코드에서는 말이 되지만 개발자의 의도와 전혀 맞지
-     않는 방향으로 "최적화" 할 수 있습니다:
-
-	if (tmp = a)
-		for (;;)
-			do_something_with(tmp);
-
-     컴파일러가 이런 짓을 하지 못하게 하려면 READ_ONCE() 를 사용하세요:
-
-	while (tmp = READ_ONCE(a))
-		do_something_with(tmp);
-
- (*) 예컨대 레지스터 사용량이 많아 컴파일러가 모든 데이터를 레지스터에 담을 수
-     없는 경우, 컴파일러는 변수를 다시 로드할 수 있습니다.  따라서 컴파일러는
-     앞의 예에서 변수 'tmp' 사용을 최적화로 없애버릴 수 있습니다:
-
-	while (tmp = a)
-		do_something_with(tmp);
-
-     이 코드는 다음과 같이 싱글 쓰레드에서는 완벽하지만 동시성이 존재하는
-     경우엔 치명적인 코드로 바뀔 수 있습니다:
-
-	while (a)
-		do_something_with(a);
-
-     예를 들어, 최적화된 이 코드는 변수 a 가 다른 CPU 에 의해 "while" 문과
-     do_something_with() 호출 사이에 바뀌어 do_something_with() 에 0을 넘길
-     수도 있습니다.
-
-     이번에도, 컴파일러가 그런 짓을 하는걸 막기 위해 READ_ONCE() 를 사용하세요:
-
-	while (tmp = READ_ONCE(a))
-		do_something_with(tmp);
-
-     레지스터가 부족한 상황을 겪는 경우, 컴파일러는 tmp 를 스택에 저장해둘 수도
-     있습니다.  컴파일러가 변수를 다시 읽어들이는건 이렇게 저장해두고 후에 다시
-     읽어들이는데 드는 오버헤드 때문입니다.  그렇게 하는게 싱글 쓰레드
-     코드에서는 안전하므로, 안전하지 않은 경우에는 컴파일러에게 직접 알려줘야
-     합니다.
-
- (*) 컴파일러는 그 값이 무엇일지 알고 있다면 로드를 아예 안할 수도 있습니다.
-     예를 들어, 다음의 코드는 변수 'a' 의 값이 항상 0임을 증명할 수 있다면:
-
-	while (tmp = a)
-		do_something_with(tmp);
-
-     이렇게 최적화 되어버릴 수 있습니다:
-
-	do { } while (0);
-
-     이 변환은 싱글 쓰레드 코드에서는 도움이 되는데 로드와 브랜치를 제거했기
-     때문입니다.  문제는 컴파일러가 'a' 의 값을 업데이트 하는건 현재의 CPU 하나
-     뿐이라는 가정 위에서 증명을 했다는데 있습니다.  만약 변수 'a' 가 공유되어
-     있다면, 컴파일러의 증명은 틀린 것이 될겁니다.  컴파일러는 그 자신이
-     생각하는 것만큼 많은 것을 알고 있지 못함을 컴파일러에게 알리기 위해
-     READ_ONCE() 를 사용하세요:
-
-	while (tmp = READ_ONCE(a))
-		do_something_with(tmp);
-
-     하지만 컴파일러는 READ_ONCE() 뒤에 나오는 값에 대해서도 눈길을 두고 있음을
-     기억하세요.  예를 들어, 다음의 코드에서 MAX 는 전처리기 매크로로, 1의 값을
-     갖는다고 해봅시다:
-
-	while ((tmp = READ_ONCE(a)) % MAX)
-		do_something_with(tmp);
-
-     이렇게 되면 컴파일러는 MAX 를 가지고 수행되는 "%" 오퍼레이터의 결과가 항상
-     0이라는 것을 알게 되고, 컴파일러가 코드를 실질적으로는 존재하지 않는
-     것처럼 최적화 하는 것이 허용되어 버립니다.  ('a' 변수의 로드는 여전히
-     행해질 겁니다.)
-
- (*) 비슷하게, 컴파일러는 변수가 저장하려 하는 값을 이미 가지고 있다는 것을
-     알면 스토어 자체를 제거할 수 있습니다.  이번에도, 컴파일러는 현재의 CPU
-     만이 그 변수에 값을 쓰는 오로지 하나의 존재라고 생각하여 공유된 변수에
-     대해서는 잘못된 일을 하게 됩니다.  예를 들어, 다음과 같은 경우가 있을 수
-     있습니다:
-
-	a = 0;
-	... 변수 a 에 스토어를 하지 않는 코드 ...
-	a = 0;
-
-     컴파일러는 변수 'a' 의 값은 이미 0이라는 것을 알고, 따라서 두번째 스토어를
-     삭제할 겁니다.  만약 다른 CPU 가 그 사이 변수 'a' 에 다른 값을 썼다면
-     황당한 결과가 나올 겁니다.
-
-     컴파일러가 그런 잘못된 추측을 하지 않도록 WRITE_ONCE() 를 사용하세요:
-
-	WRITE_ONCE(a, 0);
-	... 변수 a 에 스토어를 하지 않는 코드 ...
-	WRITE_ONCE(a, 0);
-
- (*) 컴파일러는 하지 말라고 하지 않으면 메모리 액세스들을 재배치 할 수
-     있습니다.  예를 들어, 다음의 프로세스 레벨 코드와 인터럽트 핸들러 사이의
-     상호작용을 생각해 봅시다:
-
-	void process_level(void)
-	{
-		msg = get_message();
-		flag = true;
-	}
-
-	void interrupt_handler(void)
-	{
-		if (flag)
-			process_message(msg);
-	}
-
-     이 코드에는 컴파일러가 process_level() 을 다음과 같이 변환하는 것을 막을
-     수단이 없고, 이런 변환은 싱글쓰레드에서라면 실제로 훌륭한 선택일 수
-     있습니다:
-
-	void process_level(void)
-	{
-		flag = true;
-		msg = get_message();
-	}
-
-     이 두개의 문장 사이에 인터럽트가 발생한다면, interrupt_handler() 는 의미를
-     알 수 없는 메세지를 받을 수도 있습니다.  이걸 막기 위해 다음과 같이
-     WRITE_ONCE() 를 사용하세요:
-
-	void process_level(void)
-	{
-		WRITE_ONCE(msg, get_message());
-		WRITE_ONCE(flag, true);
-	}
-
-	void interrupt_handler(void)
-	{
-		if (READ_ONCE(flag))
-			process_message(READ_ONCE(msg));
-	}
-
-     interrupt_handler() 안에서도 중첩된 인터럽트나 NMI 와 같이 인터럽트 핸들러
-     역시 'flag' 와 'msg' 에 접근하는 또다른 무언가에 인터럽트 될 수 있다면
-     READ_ONCE() 와 WRITE_ONCE() 를 사용해야 함을 기억해 두세요.  만약 그런
-     가능성이 없다면, interrupt_handler() 안에서는 문서화 목적이 아니라면
-     READ_ONCE() 와 WRITE_ONCE() 는 필요치 않습니다.  (근래의 리눅스 커널에서
-     중첩된 인터럽트는 보통 잘 일어나지 않음도 기억해 두세요, 실제로, 어떤
-     인터럽트 핸들러가 인터럽트가 활성화된 채로 리턴하면 WARN_ONCE() 가
-     실행됩니다.)
-
-     컴파일러는 READ_ONCE() 와 WRITE_ONCE() 뒤의 READ_ONCE() 나 WRITE_ONCE(),
-     barrier(), 또는 비슷한 것들을 담고 있지 않은 코드를 움직일 수 있을 것으로
-     가정되어야 합니다.
-
-     이 효과는 barrier() 를 통해서도 만들 수 있지만, READ_ONCE() 와
-     WRITE_ONCE() 가 좀 더 안목 높은 선택입니다: READ_ONCE() 와 WRITE_ONCE()는
-     컴파일러에 주어진 메모리 영역에 대해서만 최적화 가능성을 포기하도록
-     하지만, barrier() 는 컴파일러가 지금까지 기계의 레지스터에 캐시해 놓은
-     모든 메모리 영역의 값을 버려야 하게 하기 때문입니다.  물론, 컴파일러는
-     READ_ONCE() 와 WRITE_ONCE() 가 일어난 순서도 지켜줍니다, CPU 는 당연히
-     그 순서를 지킬 의무가 없지만요.
-
- (*) 컴파일러는 다음의 예에서와 같이 변수에의 스토어를 날조해낼 수도 있습니다:
-
-	if (a)
-		b = a;
-	else
-		b = 42;
-
-     컴파일러는 아래와 같은 최적화로 브랜치를 줄일 겁니다:
-
-	b = 42;
-	if (a)
-		b = a;
-
-     싱글 쓰레드 코드에서 이 최적화는 안전할 뿐 아니라 브랜치 갯수를
-     줄여줍니다.  하지만 안타깝게도, 동시성이 있는 코드에서는 이 최적화는 다른
-     CPU 가 'b' 를 로드할 때, -- 'a' 가 0이 아닌데도 -- 가짜인 값, 42를 보게
-     되는 경우를 가능하게 합니다.  이걸 방지하기 위해 WRITE_ONCE() 를
-     사용하세요:
-
-	if (a)
-		WRITE_ONCE(b, a);
-	else
-		WRITE_ONCE(b, 42);
-
-     컴파일러는 로드를 만들어낼 수도 있습니다.  일반적으로는 문제를 일으키지
-     않지만, 캐시 라인 바운싱을 일으켜 성능과 확장성을 떨어뜨릴 수 있습니다.
-     날조된 로드를 막기 위해선 READ_ONCE() 를 사용하세요.
-
- (*) 정렬된 메모리 주소에 위치한, 한번의 메모리 참조 인스트럭션으로 액세스
-     가능한 크기의 데이터는 하나의 큰 액세스가 여러개의 작은 액세스들로
-     대체되는 "로드 티어링(load tearing)" 과 "스토어 티어링(store tearing)" 을
-     방지합니다.  예를 들어, 주어진 아키텍쳐가 7-bit imeediate field 를 갖는
-     16-bit 스토어 인스트럭션을 제공한다면, 컴파일러는 다음의 32-bit 스토어를
-     구현하는데에 두개의 16-bit store-immediate 명령을 사용하려 할겁니다:
-
-	p = 0x00010002;
-
-     스토어 할 상수를 만들고 그 값을 스토어 하기 위해 두개가 넘는 인스트럭션을
-     사용하게 되는, 이런 종류의 최적화를 GCC 는 실제로 함을 부디 알아 두십시오.
-     이 최적화는 싱글 쓰레드 코드에서는 성공적인 최적화 입니다.  실제로, 근래에
-     발생한 (그리고 고쳐진) 버그는 GCC 가 volatile 스토어에 비정상적으로 이
-     최적화를 사용하게 했습니다.  그런 버그가 없다면, 다음의 예에서
-     WRITE_ONCE() 의 사용은 스토어 티어링을 방지합니다:
-
-	WRITE_ONCE(p, 0x00010002);
-
-     Packed 구조체의 사용 역시 다음의 예처럼  로드 / 스토어 티어링을 유발할 수
-     있습니다:
-
-	struct __attribute__((__packed__)) foo {
-		short a;
-		int b;
-		short c;
-	};
-	struct foo foo1, foo2;
-	...
-
-	foo2.a = foo1.a;
-	foo2.b = foo1.b;
-	foo2.c = foo1.c;
-
-     READ_ONCE() 나 WRITE_ONCE() 도 없고 volatile 마킹도 없기 때문에,
-     컴파일러는 이 세개의 대입문을 두개의 32-bit 로드와 두개의 32-bit 스토어로
-     변환할 수 있습니다.  이는 'foo1.b' 의 값의 로드 티어링과 'foo2.b' 의
-     스토어 티어링을 초래할 겁니다.  이 예에서도 READ_ONCE() 와 WRITE_ONCE()
-     가 티어링을 막을 수 있습니다:
-
-	foo2.a = foo1.a;
-	WRITE_ONCE(foo2.b, READ_ONCE(foo1.b));
-	foo2.c = foo1.c;
-
-그렇지만, volatile 로 마크된 변수에 대해서는 READ_ONCE() 와 WRITE_ONCE() 가
-필요치 않습니다.  예를 들어, 'jiffies' 는 volatile 로 마크되어 있기 때문에,
-READ_ONCE(jiffies) 라고 할 필요가 없습니다.  READ_ONCE() 와 WRITE_ONCE() 가
-실은 volatile 캐스팅으로 구현되어 있어서 인자가 이미 volatile 로 마크되어
-있다면 또다른 효과를 내지는 않기 때문입니다.
-
-이 컴파일러 배리어들은 CPU 에는 직접적 효과를 전혀 만들지 않기 때문에, 결국은
-재배치가 일어날 수도 있음을 부디 기억해 두십시오.
-
-
-CPU 메모리 배리어
------------------
-
-리눅스 커널은 다음의 여덟개 기본 CPU 메모리 배리어를 가지고 있습니다:
-
-	TYPE		MANDATORY		SMP CONDITIONAL
-	===============	=======================	===========================
-	범용		mb()			smp_mb()
-	쓰기		wmb()			smp_wmb()
-	읽기		rmb()			smp_rmb()
-	데이터 의존성	read_barrier_depends()	smp_read_barrier_depends()
-
-
-데이터 의존성 배리어를 제외한 모든 메모리 배리어는 컴파일러 배리어를
-포함합니다.  데이터 의존성은 컴파일러에의 추가적인 순서 보장을 포함하지
-않습니다.
-
-방백: 데이터 의존성이 있는 경우, 컴파일러는 해당 로드를 올바른 순서로 일으킬
-것으로 (예: `a[b]` 는 a[b] 를 로드 하기 전에 b 의 값을 먼저 로드한다)
-기대되지만, C 언어 사양에는 컴파일러가 b 의 값을 추측 (예: 1 과 같음) 해서
-b  로드 전에 a 로드를 하는 코드 (예: tmp = a[1]; if (b != 1) tmp = a[b]; ) 를
-만들지 않아야 한다는 내용 같은 건 없습니다.  또한 컴파일러는 a[b] 를 로드한
-후에 b 를 또다시 로드할 수도 있어서, a[b] 보다 최신 버전의 b 값을 가질 수도
-있습니다.  이런 문제들의 해결책에 대한 의견 일치는 아직 없습니다만, 일단
-READ_ONCE() 매크로부터 보기 시작하는게 좋은 시작이 될겁니다.
-
-SMP 메모리 배리어들은 유니프로세서로 컴파일된 시스템에서는 컴파일러 배리어로
-바뀌는데, 하나의 CPU 는 스스로 일관성을 유지하고, 겹치는 액세스들 역시 올바른
-순서로 행해질 것으로 생각되기 때문입니다.  하지만, 아래의 "Virtual Machine
-Guests" 서브섹션을 참고하십시오.
-
-[!] SMP 시스템에서 공유메모리로의 접근들을 순서 세워야 할 때, SMP 메모리
-배리어는 _반드시_ 사용되어야 함을 기억하세요, 그대신 락을 사용하는 것으로도
-충분하긴 하지만 말이죠.
-
-Mandatory 배리어들은 SMP 시스템에서도 UP 시스템에서도 SMP 효과만 통제하기에는
-불필요한 오버헤드를 갖기 때문에 SMP 효과만 통제하면 되는 곳에는 사용되지 않아야
-합니다.  하지만, 느슨한 순서 규칙의 메모리 I/O 윈도우를 통한 MMIO 의 효과를
-통제할 때에는 mandatory 배리어들이 사용될 수 있습니다.  이 배리어들은
-컴파일러와 CPU 모두 재배치를 못하도록 함으로써 메모리 오퍼레이션들이 디바이스에
-보여지는 순서에도 영향을 주기 때문에, SMP 가 아닌 시스템이라 할지라도 필요할 수
-있습니다.
-
-
-일부 고급 배리어 함수들도 있습니다:
-
- (*) smp_store_mb(var, value)
-
-     이 함수는 특정 변수에 특정 값을 대입하고 범용 메모리 배리어를 칩니다.
-     UP 컴파일에서는 컴파일러 배리어보다 더한 것을 친다고는 보장되지 않습니다.
-
-
- (*) smp_mb__before_atomic();
- (*) smp_mb__after_atomic();
-
-     이것들은 값을 리턴하지 않는 (더하기, 빼기, 증가, 감소와 같은) 어토믹
-     함수들을 위한, 특히 그것들이 레퍼런스 카운팅에 사용될 때를 위한
-     함수들입니다.  이 함수들은 메모리 배리어를 내포하고 있지는 않습니다.
-
-     이것들은 값을 리턴하지 않으며 어토믹한 (set_bit 과 clear_bit 같은) 비트
-     연산에도 사용될 수 있습니다.
-
-     한 예로, 객체 하나를 무효한 것으로 표시하고 그 객체의 레퍼런스 카운트를
-     감소시키는 다음 코드를 보세요:
-
-	obj->dead = 1;
-	smp_mb__before_atomic();
-	atomic_dec(&obj->ref_count);
-
-     이 코드는 객체의 업데이트된 death 마크가 레퍼런스 카운터 감소 동작
-     *전에* 보일 것을 보장합니다.
-
-     더 많은 정보를 위해선 Documentation/atomic_ops.txt 문서를 참고하세요.
-     어디서 이것들을 사용해야 할지 궁금하다면 "어토믹 오퍼레이션" 서브섹션을
-     참고하세요.
-
-
- (*) lockless_dereference();
-
-     이 함수는 smp_read_barrier_depends() 데이터 의존성 배리어를 사용하는
-     포인터 읽어오기 래퍼(wrapper) 함수로 생각될 수 있습니다.
-
-     객체의 라이프타임이 RCU 외의 메커니즘으로 관리된다는 점을 제외하면
-     rcu_dereference() 와도 유사한데, 예를 들면 객체가 시스템이 꺼질 때에만
-     제거되는 경우 등입니다.  또한, lockless_dereference() 은 RCU 와 함께
-     사용될수도, RCU 없이 사용될 수도 있는 일부 데이터 구조에 사용되고
-     있습니다.
-
-
- (*) dma_wmb();
- (*) dma_rmb();
-
-     이것들은 CPU 와 DMA 가능한 디바이스에서 모두 액세스 가능한 공유 메모리의
-     읽기, 쓰기 작업들의 순서를 보장하기 위해 consistent memory 에서 사용하기
-     위한 것들입니다.
-
-     예를 들어, 디바이스와 메모리를 공유하며, 디스크립터 상태 값을 사용해
-     디스크립터가 디바이스에 속해 있는지 아니면 CPU 에 속해 있는지 표시하고,
-     공지용 초인종(doorbell) 을 사용해 업데이트된 디스크립터가 디바이스에 사용
-     가능해졌음을 공지하는 디바이스 드라이버를 생각해 봅시다:
-
-	if (desc->status != DEVICE_OWN) {
-		/* 디스크립터를 소유하기 전에는 데이터를 읽지 않음 */
-		dma_rmb();
-
-		/* 데이터를 읽고 씀 */
-		read_data = desc->data;
-		desc->data = write_data;
-
-		/* 상태 업데이트 전 수정사항을 반영 */
-		dma_wmb();
-
-		/* 소유권을 수정 */
-		desc->status = DEVICE_OWN;
-
-		/* MMIO 를 통해 디바이스에 공지를 하기 전에 메모리를 동기화 */
-		wmb();
-
-		/* 업데이트된 디스크립터의 디바이스에 공지 */
-		writel(DESC_NOTIFY, doorbell);
-	}
-
-     dma_rmb() 는 디스크립터로부터 데이터를 읽어오기 전에 디바이스가 소유권을
-     내놓았음을 보장하게 하고, dma_wmb() 는 디바이스가 자신이 소유권을 다시
-     가졌음을 보기 전에 디스크립터에 데이터가 쓰였음을 보장합니다.  wmb() 는
-     캐시 일관성이 없는 (cache incoherent) MMIO 영역에 쓰기를 시도하기 전에
-     캐시 일관성이 있는 메모리 (cache coherent memory) 쓰기가 완료되었음을
-     보장해주기 위해 필요합니다.
-
-     consistent memory 에 대한 자세한 내용을 위해선 Documentation/DMA-API.txt
-     문서를 참고하세요.
-
-
-MMIO 쓰기 배리어
-----------------
-
-리눅스 커널은 또한 memory-mapped I/O 쓰기를 위한 특별한 배리어도 가지고
-있습니다:
-
-	mmiowb();
-
-이것은 mandatory 쓰기 배리어의 변종으로, 완화된 순서 규칙의 I/O 영역에으로의
-쓰기가 부분적으로 순서를 맞추도록 해줍니다.  이 함수는 CPU->하드웨어 사이를
-넘어서 실제 하드웨어에까지 일부 수준의 영향을 끼칩니다.
-
-더 많은 정보를 위해선 "Acquire vs I/O 액세스" 서브섹션을 참고하세요.
-
-
-=========================
-암묵적 커널 메모리 배리어
-=========================
-
-리눅스 커널의 일부 함수들은 메모리 배리어를 내장하고 있는데, 락(lock)과
-스케쥴링 관련 함수들이 대부분입니다.
-
-여기선 _최소한의_ 보장을 설명합니다; 특정 아키텍쳐에서는 이 설명보다 더 많은
-보장을 제공할 수도 있습니다만 해당 아키텍쳐에 종속적인 코드 외의 부분에서는
-그런 보장을 기대해선 안될겁니다.
-
-
-락 ACQUISITION 함수
--------------------
-
-리눅스 커널은 다양한 락 구성체를 가지고 있습니다:
-
- (*) 스핀 락
- (*) R/W 스핀 락
- (*) 뮤텍스
- (*) 세마포어
- (*) R/W 세마포어
-
-각 구성체마다 모든 경우에 "ACQUIRE" 오퍼레이션과 "RELEASE" 오퍼레이션의 변종이
-존재합니다.  이 오퍼레이션들은 모두 적절한 배리어를 내포하고 있습니다:
-
- (1) ACQUIRE 오퍼레이션의 영향:
-
-     ACQUIRE 뒤에서 요청된 메모리 오퍼레이션은 ACQUIRE 오퍼레이션이 완료된
-     뒤에 완료됩니다.
-
-     ACQUIRE 앞에서 요청된 메모리 오퍼레이션은 ACQUIRE 오퍼레이션이 완료된 후에
-     완료될 수 있습니다.  smp_mb__before_spinlock() 뒤에 ACQUIRE 가 실행되는
-     코드 블록은 블록 앞의 스토어를 블록 뒤의 로드와 스토어에 대해 순서
-     맞춥니다.  이건 smp_mb() 보다 완화된 것임을 기억하세요!  많은 아키텍쳐에서
-     smp_mb__before_spinlock() 은 사실 아무일도 하지 않습니다.
-
- (2) RELEASE 오퍼레이션의 영향:
-
-     RELEASE 앞에서 요청된 메모리 오퍼레이션은 RELEASE 오퍼레이션이 완료되기
-     전에 완료됩니다.
-
-     RELEASE 뒤에서 요청된 메모리 오퍼레이션은 RELEASE 오퍼레이션 완료 전에
-     완료될 수 있습니다.
-
- (3) ACQUIRE vs ACQUIRE 영향:
-
-     어떤 ACQUIRE 오퍼레이션보다 앞에서 요청된 모든 ACQUIRE 오퍼레이션은 그
-     ACQUIRE 오퍼레이션 전에 완료됩니다.
-
- (4) ACQUIRE vs RELEASE implication:
-
-     어떤 RELEASE 오퍼레이션보다 앞서 요청된 ACQUIRE 오퍼레이션은 그 RELEASE
-     오퍼레이션보다 먼저 완료됩니다.
-
- (5) 실패한 조건적 ACQUIRE 영향:
-
-     ACQUIRE 오퍼레이션의 일부 락(lock) 변종은 락이 곧바로 획득하기에는
-     불가능한 상태이거나 락이 획득 가능해지도록 기다리는 도중 시그널을 받거나
-     해서 실패할 수 있습니다.  실패한 락은 어떤 배리어도 내포하지 않습니다.
-
-[!] 참고: 락 ACQUIRE 와 RELEASE 가 단방향 배리어여서 나타나는 현상 중 하나는
-크리티컬 섹션 바깥의 인스트럭션의 영향이 크리티컬 섹션 내부로도 들어올 수
-있다는 것입니다.
-
-RELEASE 후에 요청되는 ACQUIRE 는 전체 메모리 배리어라 여겨지면 안되는데,
-ACQUIRE 앞의 액세스가 ACQUIRE 후에 수행될 수 있고, RELEASE 후의 액세스가
-RELEASE 전에 수행될 수도 있으며, 그 두개의 액세스가 서로를 지나칠 수도 있기
-때문입니다:
-
-	*A = a;
-	ACQUIRE M
-	RELEASE M
-	*B = b;
-
-는 다음과 같이 될 수도 있습니다:
-
-	ACQUIRE M, STORE *B, STORE *A, RELEASE M
-
-ACQUIRE 와 RELEASE 가 락 획득과 해제라면, 그리고 락의 ACQUIRE 와 RELEASE 가
-같은 락 변수에 대한 것이라면, 해당 락을 쥐고 있지 않은 다른 CPU 의 시야에는
-이와 같은 재배치가 일어나는 것으로 보일 수 있습니다.  요약하자면, ACQUIRE 에
-이어 RELEASE 오퍼레이션을 순차적으로 실행하는 행위가 전체 메모리 배리어로
-생각되어선 -안됩니다-.
-
-비슷하게, 앞의 반대 케이스인 RELEASE 와 ACQUIRE 두개 오퍼레이션의 순차적 실행
-역시 전체 메모리 배리어를 내포하지 않습니다.  따라서, RELEASE, ACQUIRE 로
-규정되는 크리티컬 섹션의 CPU 수행은 RELEASE 와 ACQUIRE 를 가로지를 수 있으므로,
-다음과 같은 코드는:
-
-	*A = a;
-	RELEASE M
-	ACQUIRE N
-	*B = b;
-
-다음과 같이 수행될 수 있습니다:
-
-	ACQUIRE N, STORE *B, STORE *A, RELEASE M
-
-이런 재배치는 데드락을 일으킬 수도 있을 것처럼 보일 수 있습니다.  하지만, 그런
-데드락의 조짐이 있다면 RELEASE 는 단순히 완료될 것이므로 데드락은 존재할 수
-없습니다.
-
-	이게 어떻게 올바른 동작을 할 수 있을까요?
-
-	우리가 이야기 하고 있는건 재배치를 하는 CPU 에 대한 이야기이지,
-	컴파일러에 대한 것이 아니란 점이 핵심입니다.  컴파일러 (또는, 개발자)
-	가 오퍼레이션들을 이렇게 재배치하면, 데드락이 일어날 수 -있습-니다.
-
-	하지만 CPU 가 오퍼레이션들을 재배치 했다는걸 생각해 보세요.  이 예에서,
-	어셈블리 코드 상으로는 언락이 락을 앞서게 되어 있습니다.  CPU 가 이를
-	재배치해서 뒤의 락 오퍼레이션을 먼저 실행하게 됩니다.  만약 데드락이
-	존재한다면, 이 락 오퍼레이션은 그저 스핀을 하며 계속해서 락을
-	시도합니다 (또는, 한참 후에겠지만, 잠듭니다).  CPU 는 언젠가는
-	(어셈블리 코드에서는 락을 앞서는) 언락 오퍼레이션을 실행하는데, 이 언락
-	오퍼레이션이 잠재적 데드락을 해결하고, 락 오퍼레이션도 뒤이어 성공하게
-	됩니다.
-
-	하지만 만약 락이 잠을 자는 타입이었다면요?  그런 경우에 코드는
-	스케쥴러로 들어가려 할 거고, 여기서 결국은 메모리 배리어를 만나게
-	되는데, 이 메모리 배리어는 앞의 언락 오퍼레이션이 완료되도록 만들고,
-	데드락은 이번에도 해결됩니다.  잠을 자는 행위와 언락 사이의 경주 상황
-	(race) 도 있을 수 있겠습니다만, 락 관련 기능들은 그런 경주 상황을 모든
-	경우에 제대로 해결할 수 있어야 합니다.
-
-락과 세마포어는 UP 컴파일된 시스템에서의 순서에 대해 보장을 하지 않기 때문에,
-그런 상황에서 인터럽트 비활성화 오퍼레이션과 함께가 아니라면 어떤 일에도 - 특히
-I/O 액세스와 관련해서는 - 제대로 사용될 수 없을 겁니다.
-
-"CPU 간 ACQUIRING 배리어 효과" 섹션도 참고하시기 바랍니다.
-
-
-예를 들어, 다음과 같은 코드를 생각해 봅시다:
-
-	*A = a;
-	*B = b;
-	ACQUIRE
-	*C = c;
-	*D = d;
-	RELEASE
-	*E = e;
-	*F = f;
-
-여기선 다음의 이벤트 시퀀스가 생길 수 있습니다:
-
-	ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
-
-	[+] {*F,*A} 는 조합된 액세스를 의미합니다.
-
-하지만 다음과 같은 건 불가능하죠:
-
-	{*F,*A}, *B,	ACQUIRE, *C, *D,	RELEASE, *E
-	*A, *B, *C,	ACQUIRE, *D,		RELEASE, *E, *F
-	*A, *B,		ACQUIRE, *C,		RELEASE, *D, *E, *F
-	*B,		ACQUIRE, *C, *D,	RELEASE, {*F,*A}, *E
-
-
-
-인터럽트 비활성화 함수
-----------------------
-
-인터럽트를 비활성화 하는 함수 (ACQUIRE 와 동일) 와 인터럽트를 활성화 하는 함수
-(RELEASE 와 동일) 는 컴파일러 배리어처럼만 동작합니다.  따라서, 별도의 메모리
-배리어나 I/O 배리어가 필요한 상황이라면 그 배리어들은 인터럽트 비활성화 함수
-외의 방법으로 제공되어야만 합니다.
-
-
-슬립과 웨이크업 함수
---------------------
-
-글로벌 데이터에 표시된 이벤트에 의해 프로세스를 잠에 빠트리는 것과 깨우는 것은
-해당 이벤트를 기다리는 태스크의 태스크 상태와 그 이벤트를 알리기 위해 사용되는
-글로벌 데이터, 두 데이터간의 상호작용으로 볼 수 있습니다.  이것이 옳은 순서대로
-일어남을 분명히 하기 위해, 프로세스를 잠에 들게 하는 기능과 깨우는 기능은
-몇가지 배리어를 내포합니다.
-
-먼저, 잠을 재우는 쪽은 일반적으로 다음과 같은 이벤트 시퀀스를 따릅니다:
-
-	for (;;) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (event_indicated)
-			break;
-		schedule();
-	}
-
-set_current_state() 에 의해, 태스크 상태가 바뀐 후 범용 메모리 배리어가
-자동으로 삽입됩니다:
-
-	CPU 1
-	===============================
-	set_current_state();
-	  smp_store_mb();
-	    STORE current->state
-	    <범용 배리어>
-	LOAD event_indicated
-
-set_current_state() 는 다음의 것들로 감싸질 수도 있습니다:
-
-	prepare_to_wait();
-	prepare_to_wait_exclusive();
-
-이것들 역시 상태를 설정한 후 범용 메모리 배리어를 삽입합니다.
-앞의 전체 시퀀스는 다음과 같은 함수들로 한번에 수행 가능한데, 이것들은 모두
-올바른 장소에 메모리 배리어를 삽입합니다:
-
-	wait_event();
-	wait_event_interruptible();
-	wait_event_interruptible_exclusive();
-	wait_event_interruptible_timeout();
-	wait_event_killable();
-	wait_event_timeout();
-	wait_on_bit();
-	wait_on_bit_lock();
-
-
-두번째로, 깨우기를 수행하는 코드는 일반적으로 다음과 같을 겁니다:
-
-	event_indicated = 1;
-	wake_up(&event_wait_queue);
-
-또는:
-
-	event_indicated = 1;
-	wake_up_process(event_daemon);
-
-wake_up() 류에 의해 쓰기 메모리 배리어가 내포됩니다.  만약 그것들이 뭔가를
-깨운다면요.  이 배리어는 태스크 상태가 지워지기 전에 수행되므로, 이벤트를
-알리기 위한 STORE 와 태스크 상태를 TASK_RUNNING 으로 설정하는 STORE 사이에
-위치하게 됩니다.
-
-	CPU 1				CPU 2
-	===============================	===============================
-	set_current_state();		STORE event_indicated
-	  smp_store_mb();		wake_up();
-	    STORE current->state	  <쓰기 배리어>
-	    <범용 배리어>		  STORE current->state
-	LOAD event_indicated
-
-한번더 말합니다만, 이 쓰기 메모리 배리어는 이 코드가 정말로 뭔가를 깨울 때에만
-실행됩니다.  이걸 설명하기 위해, X 와 Y 는 모두 0 으로 초기화 되어 있다는 가정
-하에 아래의 이벤트 시퀀스를 생각해 봅시다:
-
-	CPU 1				CPU 2
-	===============================	===============================
-	X = 1;				STORE event_indicated
-	smp_mb();			wake_up();
-	Y = 1;				wait_event(wq, Y == 1);
-	wake_up();			  load from Y sees 1, no memory barrier
-					load from X might see 0
-
-위 예제에서의 경우와 달리 깨우기가 정말로 행해졌다면, CPU 2 의 X 로드는 1 을
-본다고 보장될 수 있을 겁니다.
-
-사용 가능한 깨우기류 함수들로 다음과 같은 것들이 있습니다:
-
-	complete();
-	wake_up();
-	wake_up_all();
-	wake_up_bit();
-	wake_up_interruptible();
-	wake_up_interruptible_all();
-	wake_up_interruptible_nr();
-	wake_up_interruptible_poll();
-	wake_up_interruptible_sync();
-	wake_up_interruptible_sync_poll();
-	wake_up_locked();
-	wake_up_locked_poll();
-	wake_up_nr();
-	wake_up_poll();
-	wake_up_process();
-
-
-[!] 잠재우는 코드와 깨우는 코드에 내포되는 메모리 배리어들은 깨우기 전에
-이루어진 스토어를 잠재우는 코드가 set_current_state() 를 호출한 후에 행하는
-로드에 대해 순서를 맞추지 _않는다는_ 점을 기억하세요.  예를 들어, 잠재우는
-코드가 다음과 같고:
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (event_indicated)
-		break;
-	__set_current_state(TASK_RUNNING);
-	do_something(my_data);
-
-깨우는 코드는 다음과 같다면:
-
-	my_data = value;
-	event_indicated = 1;
-	wake_up(&event_wait_queue);
-
-event_indecated 에의 변경이 잠재우는 코드에게 my_data 에의 변경 후에 이루어진
-것으로 인지될 것이라는 보장이 없습니다.  이런 경우에는 양쪽 코드 모두 각각의
-데이터 액세스 사이에 메모리 배리어를 직접 쳐야 합니다.  따라서 앞의 재우는
-코드는 다음과 같이:
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (event_indicated) {
-		smp_rmb();
-		do_something(my_data);
-	}
-
-그리고 깨우는 코드는 다음과 같이 되어야 합니다:
-
-	my_data = value;
-	smp_wmb();
-	event_indicated = 1;
-	wake_up(&event_wait_queue);
-
-
-그외의 함수들
--------------
-
-그외의 배리어를 내포하는 함수들은 다음과 같습니다:
-
- (*) schedule() 과 그 유사한 것들이 완전한 메모리 배리어를 내포합니다.
-
-
-==============================
-CPU 간 ACQUIRING 배리어의 효과
-==============================
-
-SMP 시스템에서의 락 기능들은 더욱 강력한 형태의 배리어를 제공합니다: 이
-배리어는 동일한 락을 사용하는 다른 CPU 들의 메모리 액세스 순서에도 영향을
-끼칩니다.
-
-
-ACQUIRE VS 메모리 액세스
-------------------------
-
-다음의 예를 생각해 봅시다: 시스템은 두개의 스핀락 (M) 과 (Q), 그리고 세개의 CPU
-를 가지고 있습니다; 여기에 다음의 이벤트 시퀀스가 발생합니다:
-
-	CPU 1				CPU 2
-	===============================	===============================
-	WRITE_ONCE(*A, a);		WRITE_ONCE(*E, e);
-	ACQUIRE M			ACQUIRE Q
-	WRITE_ONCE(*B, b);		WRITE_ONCE(*F, f);
-	WRITE_ONCE(*C, c);		WRITE_ONCE(*G, g);
-	RELEASE M			RELEASE Q
-	WRITE_ONCE(*D, d);		WRITE_ONCE(*H, h);
-
-*A 로의 액세스부터 *H 로의 액세스까지가 어떤 순서로 CPU 3 에게 보여질지에
-대해서는 각 CPU 에서의 락 사용에 의해 내포되어 있는 제약을 제외하고는 어떤
-보장도 존재하지 않습니다.  예를 들어, CPU 3 에게 다음과 같은 순서로 보여지는
-것이 가능합니다:
-
-	*E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
-
-하지만 다음과 같이 보이지는 않을 겁니다:
-
-	*B, *C or *D preceding ACQUIRE M
-	*A, *B or *C following RELEASE M
-	*F, *G or *H preceding ACQUIRE Q
-	*E, *F or *G following RELEASE Q
-
-
-
-ACQUIRE VS I/O 액세스
-----------------------
-
-특정한 (특히 NUMA 가 관련된) 환경 하에서 두개의 CPU 에서 동일한 스핀락으로
-보호되는 두개의 크리티컬 섹션 안의 I/O 액세스는 PCI 브릿지에 겹쳐진 I/O
-액세스로 보일 수 있는데, PCI 브릿지는 캐시 일관성 프로토콜과 합을 맞춰야 할
-의무가 없으므로, 필요한 읽기 메모리 배리어가 요청되지 않기 때문입니다.
-
-예를 들어서:
-
-	CPU 1				CPU 2
-	===============================	===============================
-	spin_lock(Q)
-	writel(0, ADDR)
-	writel(1, DATA);
-	spin_unlock(Q);
-					spin_lock(Q);
-					writel(4, ADDR);
-					writel(5, DATA);
-					spin_unlock(Q);
-
-는 PCI 브릿지에 다음과 같이 보일 수 있습니다:
-
-	STORE *ADDR = 0, STORE *ADDR = 4, STORE *DATA = 1, STORE *DATA = 5
-
-이렇게 되면 하드웨어의 오동작을 일으킬 수 있습니다.
-
-
-이런 경우엔 잡아둔 스핀락을 내려놓기 전에 mmiowb() 를 수행해야 하는데, 예를
-들면 다음과 같습니다:
-
-	CPU 1				CPU 2
-	===============================	===============================
-	spin_lock(Q)
-	writel(0, ADDR)
-	writel(1, DATA);
-	mmiowb();
-	spin_unlock(Q);
-					spin_lock(Q);
-					writel(4, ADDR);
-					writel(5, DATA);
-					mmiowb();
-					spin_unlock(Q);
-
-이 코드는 CPU 1 에서 요청된 두개의 스토어가 PCI 브릿지에 CPU 2 에서 요청된
-스토어들보다 먼저 보여짐을 보장합니다.
-
-
-또한, 같은 디바이스에서 스토어를 이어 로드가 수행되면 이 로드는 로드가 수행되기
-전에 스토어가 완료되기를 강제하므로 mmiowb() 의 필요가 없어집니다:
-
-	CPU 1				CPU 2
-	===============================	===============================
-	spin_lock(Q)
-	writel(0, ADDR)
-	a = readl(DATA);
-	spin_unlock(Q);
-					spin_lock(Q);
-					writel(4, ADDR);
-					b = readl(DATA);
-					spin_unlock(Q);
-
-
-더 많은 정보를 위해선 Documenataion/DocBook/deviceiobook.tmpl 을 참고하세요.
-
-
-=========================
-메모리 배리어가 필요한 곳
-=========================
-
-설령 SMP 커널을 사용하더라도 싱글 쓰레드로 동작하는 코드는 올바르게 동작하는
-것으로 보여질 것이기 때문에, 평범한 시스템 운영중에 메모리 오퍼레이션 재배치는
-일반적으로 문제가 되지 않습니다.  하지만, 재배치가 문제가 _될 수 있는_ 네가지
-환경이 있습니다:
-
- (*) 프로세서간 상호 작용.
-
- (*) 어토믹 오퍼레이션.
-
- (*) 디바이스 액세스.
-
- (*) 인터럽트.
-
-
-프로세서간 상호 작용
---------------------
-
-두개 이상의 프로세서를 가진 시스템이 있다면, 시스템의 두개 이상의 CPU 는 동시에
-같은 데이터에 대한 작업을 할 수 있습니다.  이는 동기화 문제를 일으킬 수 있고,
-이 문제를 해결하는 일반적 방법은 락을 사용하는 것입니다.  하지만, 락은 상당히
-비용이 비싸서 가능하면 락을 사용하지 않고 일을 처리하는 것이 낫습니다.  이런
-경우, 두 CPU 모두에 영향을 끼치는 오퍼레이션들은 오동작을 막기 위해 신중하게
-순서가 맞춰져야 합니다.
-
-예를 들어, R/W 세마포어의 느린 수행경로 (slow path) 를 생각해 봅시다.
-세마포어를 위해 대기를 하는 하나의 프로세스가 자신의 스택 중 일부를 이
-세마포어의 대기 프로세스 리스트에 링크한 채로 있습니다:
-
-	struct rw_semaphore {
-		...
-		spinlock_t lock;
-		struct list_head waiters;
-	};
-
-	struct rwsem_waiter {
-		struct list_head list;
-		struct task_struct *task;
-	};
-
-특정 대기 상태 프로세스를 깨우기 위해, up_read() 나 up_write() 함수는 다음과
-같은 일을 합니다:
-
- (1) 다음 대기 상태 프로세스 레코드는 어디있는지 알기 위해 이 대기 상태
-     프로세스 레코드의 next 포인터를 읽습니다;
-
- (2) 이 대기 상태 프로세스의 task 구조체로의 포인터를 읽습니다;
-
- (3) 이 대기 상태 프로세스가 세마포어를 획득했음을 알리기 위해 task
-     포인터를 초기화 합니다;
-
- (4) 해당 태스크에 대해 wake_up_process() 를 호출합니다; 그리고
-
- (5) 해당 대기 상태 프로세스의 task 구조체를 잡고 있던 레퍼런스를 해제합니다.
-
-달리 말하자면, 다음 이벤트 시퀀스를 수행해야 합니다:
-
-	LOAD waiter->list.next;
-	LOAD waiter->task;
-	STORE waiter->task;
-	CALL wakeup
-	RELEASE task
-
-그리고 이 이벤트들이 다른 순서로 수행된다면, 오동작이 일어날 수 있습니다.
-
-한번 세마포어의 대기줄에 들어갔고 세마포어 락을 놓았다면, 해당 대기 프로세스는
-락을 다시는 잡지 않습니다; 대신 자신의 task 포인터가 초기화 되길 기다립니다.
-그 레코드는 대기 프로세스의 스택에 있기 때문에, 리스트의 next 포인터가 읽혀지기
-_전에_ task 포인터가 지워진다면, 다른 CPU 는 해당 대기 프로세스를 시작해 버리고
-up*() 함수가 next 포인터를 읽기 전에 대기 프로세스의 스택을 마구 건드릴 수
-있습니다.
-
-그렇게 되면 위의 이벤트 시퀀스에 어떤 일이 일어나는지 생각해 보죠:
-
-	CPU 1				CPU 2
-	===============================	===============================
-					down_xxx()
-					Queue waiter
-					Sleep
-	up_yyy()
-	LOAD waiter->task;
-	STORE waiter->task;
-					Woken up by other event
-	<preempt>
-					Resume processing
-					down_xxx() returns
-					call foo()
-					foo() clobbers *waiter
-	</preempt>
-	LOAD waiter->list.next;
-	--- OOPS ---
-
-이 문제는 세마포어 락의 사용으로 해결될 수도 있겠지만, 그렇게 되면 깨어난 후에
-down_xxx() 함수가 불필요하게 스핀락을 또다시 얻어야만 합니다.
-
-이 문제를 해결하는 방법은 범용 SMP 메모리 배리어를 추가하는 겁니다:
-
-	LOAD waiter->list.next;
-	LOAD waiter->task;
-	smp_mb();
-	STORE waiter->task;
-	CALL wakeup
-	RELEASE task
-
-이 경우에, 배리어는 시스템의 나머지 CPU 들에게 모든 배리어 앞의 메모리 액세스가
-배리어 뒤의 메모리 액세스보다 앞서 일어난 것으로 보이게 만듭니다.  배리어 앞의
-메모리 액세스들이 배리어 명령 자체가 완료되는 시점까지 완료된다고는 보장하지
-_않습니다_.
-
-(이게 문제가 되지 않을) 단일 프로세서 시스템에서 smp_mb() 는 실제로는 그저
-컴파일러가 CPU 안에서의 순서를 바꾸거나 하지 않고 주어진 순서대로 명령을
-내리도록 하는 컴파일러 배리어일 뿐입니다.  오직 하나의 CPU 만 있으니, CPU 의
-의존성 순서 로직이 그 외의 모든것을 알아서 처리할 겁니다.
-
-
-어토믹 오퍼레이션
------------------
-
-어토믹 오퍼레이션은 기술적으로 프로세서간 상호작용으로 분류되며 그 중 일부는
-전체 메모리 배리어를 내포하고 또 일부는 내포하지 않지만, 커널에서 상당히
-의존적으로 사용하는 기능 중 하나입니다.
-
-메모리의 어떤 상태를 수정하고 해당 상태에 대한 (예전의 또는 최신의) 정보를
-리턴하는 어토믹 오퍼레이션은 모두 SMP-조건적 범용 메모리 배리어(smp_mb())를
-실제 오퍼레이션의 앞과 뒤에 내포합니다.  이런 오퍼레이션은 다음의 것들을
-포함합니다:
-
-	xchg();
-	atomic_xchg();			atomic_long_xchg();
-	atomic_inc_return();		atomic_long_inc_return();
-	atomic_dec_return();		atomic_long_dec_return();
-	atomic_add_return();		atomic_long_add_return();
-	atomic_sub_return();		atomic_long_sub_return();
-	atomic_inc_and_test();		atomic_long_inc_and_test();
-	atomic_dec_and_test();		atomic_long_dec_and_test();
-	atomic_sub_and_test();		atomic_long_sub_and_test();
-	atomic_add_negative();		atomic_long_add_negative();
-	test_and_set_bit();
-	test_and_clear_bit();
-	test_and_change_bit();
-
-	/* exchange 조건이 성공할 때 */
-	cmpxchg();
-	atomic_cmpxchg();		atomic_long_cmpxchg();
-	atomic_add_unless();		atomic_long_add_unless();
-
-이것들은 메모리 배리어 효과가 필요한 ACQUIRE 부류와 RELEASE 부류 오퍼레이션들을
-구현할 때, 그리고 객체 해제를 위해 레퍼런스 카운터를 조정할 때, 암묵적 메모리
-배리어 효과가 필요한 곳 등에 사용됩니다.
-
-
-다음의 오퍼레이션들은 메모리 배리어를 내포하지 _않기_ 때문에 문제가 될 수
-있지만, RELEASE 부류의 오퍼레이션들과 같은 것들을 구현할 때 사용될 수도
-있습니다:
-
-	atomic_set();
-	set_bit();
-	clear_bit();
-	change_bit();
-
-이것들을 사용할 때에는 필요하다면 적절한 (예를 들면 smp_mb__before_atomic()
-같은) 메모리 배리어가 명시적으로 함께 사용되어야 합니다.
-
-
-아래의 것들도 메모리 배리어를 내포하지 _않기_ 때문에, 일부 환경에서는 (예를
-들면 smp_mb__before_atomic() 과 같은) 명시적인 메모리 배리어 사용이 필요합니다.
-
-	atomic_add();
-	atomic_sub();
-	atomic_inc();
-	atomic_dec();
-
-이것들이 통계 생성을 위해 사용된다면, 그리고 통계 데이터 사이에 관계가 존재하지
-않는다면 메모리 배리어는 필요치 않을 겁니다.
-
-객체의 수명을 관리하기 위해 레퍼런스 카운팅 목적으로 사용된다면, 레퍼런스
-카운터는 락으로 보호되는 섹션에서만 조정되거나 호출하는 쪽이 이미 충분한
-레퍼런스를 잡고 있을 것이기 때문에 메모리 배리어는 아마 필요 없을 겁니다.
-
-만약 어떤 락을 구성하기 위해 사용된다면, 락 관련 동작은 일반적으로 작업을 특정
-순서대로 진행해야 하므로 메모리 배리어가 필요할 수 있습니다.
-
-기본적으로, 각 사용처에서는 메모리 배리어가 필요한지 아닌지 충분히 고려해야
-합니다.
-
-아래의 오퍼레이션들은 특별한 락 관련 동작들입니다:
-
-	test_and_set_bit_lock();
-	clear_bit_unlock();
-	__clear_bit_unlock();
-
-이것들은 ACQUIRE 류와 RELEASE 류의 오퍼레이션들을 구현합니다.  락 관련 도구를
-구현할 때에는 이것들을 좀 더 선호하는 편이 나은데, 이것들의 구현은 많은
-아키텍쳐에서 최적화 될 수 있기 때문입니다.
-
-[!] 이런 상황에 사용할 수 있는 특수한 메모리 배리어 도구들이 있습니다만, 일부
-CPU 에서는 사용되는 어토믹 인스트럭션 자체에 메모리 배리어가 내포되어 있어서
-어토믹 오퍼레이션과 메모리 배리어를 함께 사용하는 게 불필요한 일이 될 수
-있는데, 그런 경우에 이 특수 메모리 배리어 도구들은 no-op 이 되어 실질적으로
-아무일도 하지 않습니다.
-
-더 많은 내용을 위해선 Documentation/atomic_ops.txt 를 참고하세요.
-
-
-디바이스 액세스
----------------
-
-많은 디바이스가 메모리 매핑 기법으로 제어될 수 있는데, 그렇게 제어되는
-디바이스는 CPU 에는 단지 특정 메모리 영역의 집합처럼 보이게 됩니다.  드라이버는
-그런 디바이스를 제어하기 위해 정확히 올바른 순서로 올바른 메모리 액세스를
-만들어야 합니다.
-
-하지만, 액세스들을 재배치 하거나 조합하거나 병합하는게 더 효율적이라 판단하는
-영리한 CPU 나 컴파일러들을 사용하면 드라이버 코드의 조심스럽게 순서 맞춰진
-액세스들이 디바이스에는 요청된 순서대로 도착하지 못하게 할 수 있는 - 디바이스가
-오동작을 하게 할 - 잠재적 문제가 생길 수 있습니다.
-
-리눅스 커널 내부에서, I/O 는 어떻게 액세스들을 적절히 순차적이게 만들 수 있는지
-알고 있는, - inb() 나 writel() 과 같은 - 적절한 액세스 루틴을 통해 이루어져야만
-합니다.  이것들은 대부분의 경우에는 명시적 메모리 배리어 와 함께 사용될 필요가
-없습니다만, 다음의 두가지 상황에서는 명시적 메모리 배리어가 필요할 수 있습니다:
-
- (1) 일부 시스템에서 I/O 스토어는 모든 CPU 에 일관되게 순서 맞춰지지 않는데,
-     따라서 _모든_ 일반적인 드라이버들에 락이 사용되어야만 하고 이 크리티컬
-     섹션을 빠져나오기 전에 mmiowb() 가 꼭 호출되어야 합니다.
-
- (2) 만약 액세스 함수들이 완화된 메모리 액세스 속성을 갖는 I/O 메모리 윈도우를
-     사용한다면, 순서를 강제하기 위해선 _mandatory_ 메모리 배리어가 필요합니다.
-
-더 많은 정보를 위해선 Documentation/DocBook/deviceiobook.tmpl 을 참고하십시오.
-
-
-인터럽트
---------
-
-드라이버는 자신의 인터럽트 서비스 루틴에 의해 인터럽트 당할 수 있기 때문에
-드라이버의 이 두 부분은 서로의 디바이스 제어 또는 액세스 부분과 상호 간섭할 수
-있습니다.
-
-스스로에게 인터럽트 당하는 걸 불가능하게 하고, 드라이버의 크리티컬한
-오퍼레이션들을 모두 인터럽트가 불가능하게 된 영역에 집어넣거나 하는 방법 (락의
-한 형태) 으로 이런 상호 간섭을 - 최소한 부분적으로라도 - 줄일 수 있습니다.
-드라이버의 인터럽트 루틴이 실행 중인 동안, 해당 드라이버의 코어는 같은 CPU 에서
-수행되지 않을 것이며, 현재의 인터럽트가 처리되는 중에는 또다시 인터럽트가
-일어나지 못하도록 되어 있으니 인터럽트 핸들러는 그에 대해서는 락을 잡지 않아도
-됩니다.
-
-하지만, 어드레스 레지스터와 데이터 레지스터를 갖는 이더넷 카드를 다루는
-드라이버를 생각해 봅시다.  만약 이 드라이버의 코어가 인터럽트를 비활성화시킨
-채로 이더넷 카드와 대화하고 드라이버의 인터럽트 핸들러가 호출되었다면:
-
-	LOCAL IRQ DISABLE
-	writew(ADDR, 3);
-	writew(DATA, y);
-	LOCAL IRQ ENABLE
-	<interrupt>
-	writew(ADDR, 4);
-	q = readw(DATA);
-	</interrupt>
-
-만약 순서 규칙이 충분히 완화되어 있다면 데이터 레지스터에의 스토어는 어드레스
-레지스터에 두번째로 행해지는 스토어 뒤에 일어날 수도 있습니다:
-
-	STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA
-
-
-만약 순서 규칙이 충분히 완화되어 있고 묵시적으로든 명시적으로든 배리어가
-사용되지 않았다면 인터럽트 비활성화 섹션에서 일어난 액세스가 바깥으로 새어서
-인터럽트 내에서 일어난 액세스와 섞일 수 있다고 - 그리고 그 반대도 - 가정해야만
-합니다.
-
-그런 영역 안에서 일어나는 I/O 액세스들은 엄격한 순서 규칙의 I/O 레지스터에
-묵시적 I/O 배리어를 형성하는 동기적 (synchronous) 로드 오퍼레이션을 포함하기
-때문에 일반적으로는 이런게 문제가 되지 않습니다.  만약 이걸로는 충분치 않다면
-mmiowb() 가 명시적으로 사용될 필요가 있습니다.
-
-
-하나의 인터럽트 루틴과 별도의 CPU 에서 수행중이며 서로 통신을 하는 두 루틴
-사이에도 비슷한 상황이 일어날 수 있습니다.  만약 그런 경우가 발생할 가능성이
-있다면, 순서를 보장하기 위해 인터럽트 비활성화 락이 사용되어져야만 합니다.
-
-
-======================
-커널 I/O 배리어의 효과
-======================
-
-I/O 메모리에 액세스할 때, 드라이버는 적절한 액세스 함수를 사용해야 합니다:
-
- (*) inX(), outX():
-
-     이것들은 메모리 공간보다는 I/O 공간에 이야기를 하려는 의도로
-     만들어졌습니다만, 그건 기본적으로 CPU 마다 다른 컨셉입니다.  i386 과
-     x86_64 프로세서들은 특별한 I/O 공간 액세스 사이클과 명령어를 실제로 가지고
-     있지만, 다른 많은 CPU 들에는 그런 컨셉이 존재하지 않습니다.
-
-     다른 것들 중에서도 PCI 버스가 I/O 공간 컨셉을 정의하는데, 이는 - i386 과
-     x86_64 같은 CPU 에서 - CPU 의 I/O 공간 컨셉으로 쉽게 매치됩니다.  하지만,
-     대체할 I/O 공간이 없는 CPU 에서는 CPU 의 메모리 맵의 가상 I/O 공간으로
-     매핑될 수도 있습니다.
-
-     이 공간으로의 액세스는 (i386 등에서는) 완전하게 동기화 됩니다만, 중간의
-     (PCI 호스트 브리지와 같은) 브리지들은 이를 완전히 보장하진 않을수도
-     있습니다.
-
-     이것들의 상호간의 순서는 완전하게 보장됩니다.
-
-     다른 타입의 메모리 오퍼레이션, I/O 오퍼레이션에 대한 순서는 완전하게
-     보장되지는 않습니다.
-
- (*) readX(), writeX():
-
-     이것들이 수행 요청되는 CPU 에서 서로에게 완전히 순서가 맞춰지고 독립적으로
-     수행되는지에 대한 보장 여부는 이들이 액세스 하는 메모리 윈도우에 정의된
-     특성에 의해 결정됩니다.  예를 들어, 최신의 i386 아키텍쳐 머신에서는 MTRR
-     레지스터로 이 특성이 조정됩니다.
-
-     일반적으로는, 프리페치 (prefetch) 가능한 디바이스를 액세스 하는게
-     아니라면, 이것들은 완전히 순서가 맞춰지고 결합되지 않게 보장될 겁니다.
-
-     하지만, (PCI 브리지와 같은) 중간의 하드웨어는 자신이 원한다면 집행을
-     연기시킬 수 있습니다; 스토어 명령을 실제로 하드웨어로 내려보내기(flush)
-     위해서는 같은 위치로부터 로드를 하는 방법이 있습니다만[*], PCI 의 경우는
-     같은 디바이스나 환경 구성 영역에서의 로드만으로도 충분할 겁니다.
-
-     [*] 주의! 쓰여진 것과 같은 위치로부터의 로드를 시도하는 것은 오동작을
-	 일으킬 수도 있습니다 - 예로 16650 Rx/Tx 시리얼 레지스터를 생각해
-	 보세요.
-
-     프리페치 가능한 I/O 메모리가 사용되면, 스토어 명령들이 순서를 지키도록
-     하기 위해 mmiowb() 배리어가 필요할 수 있습니다.
-
-     PCI 트랜잭션 사이의 상호작용에 대해 더 많은 정보를 위해선 PCI 명세서를
-     참고하시기 바랍니다.
-
- (*) readX_relaxed(), writeX_relaxed()
-
-     이것들은 readX() 와 writeX() 랑 비슷하지만, 더 완화된 메모리 순서 보장을
-     제공합니다.  구체적으로, 이것들은 일반적 메모리 액세스 (예: DMA 버퍼) 에도
-     LOCK 이나 UNLOCK 오퍼레이션들에도 순서를 보장하지 않습니다.  LOCK 이나
-     UNLOCK 오퍼레이션들에 맞춰지는 순서가 필요하다면, mmiowb() 배리어가 사용될
-     수 있습니다.  같은 주변 장치에의 완화된 액세스끼리는 순서가 지켜짐을 알아
-     두시기 바랍니다.
-
- (*) ioreadX(), iowriteX()
-
-     이것들은 inX()/outX() 나 readX()/writeX() 처럼 실제로 수행하는 액세스의
-     종류에 따라 적절하게 수행될 것입니다.
-
-
-===================================
-가정되는 가장 완화된 실행 순서 모델
-===================================
-
-컨셉적으로 CPU 는 주어진 프로그램에 대해 프로그램 그 자체에는 인과성 (program
-causality) 을 지키는 것처럼 보이게 하지만 일반적으로는 순서를 거의 지켜주지
-않는다고 가정되어야만 합니다.  (i386 이나 x86_64 같은) 일부 CPU 들은 코드
-재배치에 (powerpc 나 frv 와 같은) 다른 것들에 비해 강한 제약을 갖지만, 아키텍쳐
-종속적 코드 이외의 코드에서는 순서에 대한 제약이 가장 완화된 경우 (DEC Alpha)
-를 가정해야 합니다.
-
-이 말은, CPU 에게 주어지는 인스트럭션 스트림 내의 한 인스트럭션이 앞의
-인스트럭션에 종속적이라면 앞의 인스트럭션은 뒤의 종속적 인스트럭션이 실행되기
-전에 완료[*]될 수 있어야 한다는 제약 (달리 말해서, 인과성이 지켜지는 것으로
-보이게 함) 외에는 자신이 원하는 순서대로 - 심지어 병렬적으로도 - 그 스트림을
-실행할 수 있음을 의미합니다
-
- [*] 일부 인스트럭션은 하나 이상의 영향 - 조건 코드를 바꾼다던지, 레지스터나
-     메모리를 바꾼다던지 - 을 만들어내며, 다른 인스트럭션은 다른 효과에
-     종속적일 수 있습니다.
-
-CPU 는 최종적으로 아무 효과도 만들지 않는 인스트럭션 시퀀스는 없애버릴 수도
-있습니다.  예를 들어, 만약 두개의 연속되는 인스트럭션이 둘 다 같은 레지스터에
-직접적인 값 (immediate value) 을 집어넣는다면, 첫번째 인스트럭션은 버려질 수도
-있습니다.
-
-
-비슷하게, 컴파일러 역시 프로그램의 인과성만 지켜준다면 인스트럭션 스트림을
-자신이 보기에 올바르다 생각되는대로 재배치 할 수 있습니다.
-
-
-===============
-CPU 캐시의 영향
-===============
-
-캐시된 메모리 오퍼레이션들이 시스템 전체에 어떻게 인지되는지는 CPU 와 메모리
-사이에 존재하는 캐시들, 그리고 시스템 상태의 일관성을 관리하는 메모리 일관성
-시스템에 상당 부분 영향을 받습니다.
-
-한 CPU 가 시스템의 다른 부분들과 캐시를 통해 상호작용한다면, 메모리 시스템은
-CPU 의 캐시들을 포함해야 하며, CPU 와 CPU 자신의 캐시 사이에서의 동작을 위한
-메모리 배리어를 가져야 합니다. (메모리 배리어는 논리적으로는 다음 그림의
-점선에서 동작합니다):
-
-	    <--- CPU --->         :       <----------- Memory ----------->
-	                          :
-	+--------+    +--------+  :   +--------+    +-----------+
-	|        |    |        |  :   |        |    |           |    +--------+
-	|  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
-	|  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
-	|        |    | Queue  |  :   |        |    |           |--->| Memory |
-	|        |    |        |  :   |        |    |           |    |        |
-	+--------+    +--------+  :   +--------+    |           |    |        |
-	                          :                 | Cache     |    +--------+
-	                          :                 | Coherency |
-	                          :                 | Mechanism |    +--------+
-	+--------+    +--------+  :   +--------+    |           |    |	      |
-	|        |    |        |  :   |        |    |           |    |        |
-	|  CPU   |    | Memory |  :   | CPU    |    |           |--->| Device |
-	|  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
-	|        |    | Queue  |  :   |        |    |           |    |        |
-	|        |    |        |  :   |        |    |           |    +--------+
-	+--------+    +--------+  :   +--------+    +-----------+
-	                          :
-	                          :
-
-특정 로드나 스토어는 해당 오퍼레이션을 요청한 CPU 의 캐시 내에서 동작을 완료할
-수도 있기 때문에 해당 CPU 의 바깥에는 보이지 않을 수 있지만, 다른 CPU 가 관심을
-갖는다면 캐시 일관성 메커니즘이 해당 캐시라인을 해당 CPU 에게 전달하고, 해당
-메모리 영역에 대한 오퍼레이션이 발생할 때마다 그 영향을 전파시키기 때문에, 해당
-오퍼레이션은 메모리에 실제로 액세스를 한것처럼 나타날 것입니다.
-
-CPU 코어는 프로그램의 인과성이 유지된다고만 여겨진다면 인스트럭션들을 어떤
-순서로든 재배치해서 수행할 수 있습니다.  일부 인스트럭션들은 로드나 스토어
-오퍼레이션을 만드는데 이 오퍼레이션들은 이후 수행될 메모리 액세스 큐에 들어가게
-됩니다.  코어는 이 오퍼레이션들을 해당 큐에 어떤 순서로든 원하는대로 넣을 수
-있고, 다른 인스트럭션의 완료를 기다리도록 강제되기 전까지는 수행을 계속합니다.
-
-메모리 배리어가 하는 일은 CPU 쪽에서 메모리 쪽으로 넘어가는 액세스들의 순서,
-그리고 그 액세스의 결과가 시스템의 다른 관찰자들에게 인지되는 순서를 제어하는
-것입니다.
-
-[!] CPU 들은 항상 그들 자신의 로드와 스토어는 프로그램 순서대로 일어난 것으로
-보기 때문에, 주어진 CPU 내에서는 메모리 배리어를 사용할 필요가 _없습니다_.
-
-[!] MMIO 나 다른 디바이스 액세스들은 캐시 시스템을 우회할 수도 있습니다.  우회
-여부는 디바이스가 액세스 되는 메모리 윈도우의 특성에 의해 결정될 수도 있고, CPU
-가 가지고 있을 수 있는 특수한 디바이스 통신 인스트럭션의 사용에 의해서 결정될
-수도 있습니다.
-
-
-캐시 일관성
------------
-
-하지만 삶은 앞에서 이야기한 것처럼 단순하지 않습니다: 캐시들은 일관적일 것으로
-기대되지만, 그 일관성이 순서에도 적용될 거라는 보장은 없습니다.  한 CPU 에서
-만들어진 변경 사항은 최종적으로는 시스템의 모든 CPU 에게 보여지게 되지만, 다른
-CPU 들에게도 같은 순서로 보이게 될 거라는 보장은 없다는 뜻입니다.
-
-
-두개의 CPU (1 & 2) 가 달려 있고, 각 CPU 에 두개의 데이터 캐시(CPU 1 은 A/B 를,
-CPU 2 는 C/D 를 갖습니다)가 병렬로 연결되어 있는 시스템을 다룬다고 생각해
-봅시다:
-
-	            :
-	            :                          +--------+
-	            :      +---------+         |        |
-	+--------+  : +--->| Cache A |<------->|        |
-	|        |  : |    +---------+         |        |
-	|  CPU 1 |<---+                        |        |
-	|        |  : |    +---------+         |        |
-	+--------+  : +--->| Cache B |<------->|        |
-	            :      +---------+         |        |
-	            :                          | Memory |
-	            :      +---------+         | System |
-	+--------+  : +--->| Cache C |<------->|        |
-	|        |  : |    +---------+         |        |
-	|  CPU 2 |<---+                        |        |
-	|        |  : |    +---------+         |        |
-	+--------+  : +--->| Cache D |<------->|        |
-	            :      +---------+         |        |
-	            :                          +--------+
-	            :
-
-이 시스템이 다음과 같은 특성을 갖는다 생각해 봅시다:
-
- (*) 홀수번 캐시라인은 캐시 A, 캐시 C 또는 메모리에 위치할 수 있음;
-
- (*) 짝수번 캐시라인은 캐시 B, 캐시 D 또는 메모리에 위치할 수 있음;
-
- (*) CPU 코어가 한개의 캐시에 접근하는 동안, 다른 캐시는 - 더티 캐시라인을
-     메모리에 내리거나 추측성 로드를 하거나 하기 위해 - 시스템의 다른 부분에
-     액세스 하기 위해 버스를 사용할 수 있음;
-
- (*) 각 캐시는 시스템의 나머지 부분들과 일관성을 맞추기 위해 해당 캐시에
-     적용되어야 할 오퍼레이션들의 큐를 가짐;
-
- (*) 이 일관성 큐는 캐시에 이미 존재하는 라인에 가해지는 평범한 로드에 의해서는
-     비워지지 않는데, 큐의 오퍼레이션들이 이 로드의 결과에 영향을 끼칠 수 있다
-     할지라도 그러함.
-
-이제, 첫번째 CPU 에서 두개의 쓰기 오퍼레이션을 만드는데, 해당 CPU 의 캐시에
-요청된 순서로 오퍼레이션이 도달됨을 보장하기 위해 두 오퍼레이션 사이에 쓰기
-배리어를 사용하는 상황을 상상해 봅시다:
-
-	CPU 1		CPU 2		COMMENT
-	===============	===============	=======================================
-					u == 0, v == 1 and p == &u, q == &u
-	v = 2;
-	smp_wmb();			v 의 변경이 p 의 변경 전에 보일 것을
-					 분명히 함
-	<A:modify v=2>			v 는 이제 캐시 A 에 독점적으로 존재함
-	p = &v;
-	<B:modify p=&v>			p 는 이제 캐시 B 에 독점적으로 존재함
-
-여기서의 쓰기 메모리 배리어는 CPU 1 의 캐시가 올바른 순서로 업데이트 된 것으로
-시스템의 다른 CPU 들이 인지하게 만듭니다.  하지만, 이제 두번째 CPU 가 그 값들을
-읽으려 하는 상황을 생각해 봅시다:
-
-	CPU 1		CPU 2		COMMENT
-	===============	===============	=======================================
-	...
-			q = p;
-			x = *q;
-
-위의 두개의 읽기 오퍼레이션은 예상된 순서로 일어나지 못할 수 있는데, 두번째 CPU
-의 한 캐시에 다른 캐시 이벤트가 발생해 v 를 담고 있는 캐시라인의 해당 캐시에의
-업데이트가 지연되는 사이, p 를 담고 있는 캐시라인은 두번째 CPU 의 다른 캐시에
-업데이트 되어버렸을 수 있기 때문입니다.
-
-	CPU 1		CPU 2		COMMENT
-	===============	===============	=======================================
-					u == 0, v == 1 and p == &u, q == &u
-	v = 2;
-	smp_wmb();
-	<A:modify v=2>	<C:busy>
-			<C:queue v=2>
-	p = &v;		q = p;
-			<D:request p>
-	<B:modify p=&v>	<D:commit p=&v>
-			<D:read p>
-			x = *q;
-			<C:read *q>	캐시에 업데이트 되기 전의 v 를 읽음
-			<C:unbusy>
-			<C:commit v=2>
-
-기본적으로, 두개의 캐시라인 모두 CPU 2 에 최종적으로는 업데이트 될 것이지만,
-별도의 개입 없이는, 업데이트의 순서가 CPU 1 에서 만들어진 순서와 동일할
-것이라는 보장이 없습니다.
-
-
-여기에 개입하기 위해선, 데이터 의존성 배리어나 읽기 배리어를 로드 오퍼레이션들
-사이에 넣어야 합니다.  이렇게 함으로써 캐시가 다음 요청을 처리하기 전에 일관성
-큐를 처리하도록 강제하게 됩니다.
-
-	CPU 1		CPU 2		COMMENT
-	===============	===============	=======================================
-					u == 0, v == 1 and p == &u, q == &u
-	v = 2;
-	smp_wmb();
-	<A:modify v=2>	<C:busy>
-			<C:queue v=2>
-	p = &v;		q = p;
-			<D:request p>
-	<B:modify p=&v>	<D:commit p=&v>
-			<D:read p>
-			smp_read_barrier_depends()
-			<C:unbusy>
-			<C:commit v=2>
-			x = *q;
-			<C:read *q>	캐시에 업데이트 된 v 를 읽음
-
-
-이런 부류의 문제는 DEC Alpha 계열 프로세서들에서 발견될 수 있는데, 이들은
-데이터 버스를 좀 더 잘 사용해 성능을 개선할 수 있는, 분할된 캐시를 가지고 있기
-때문입니다.  대부분의 CPU 는 하나의 읽기 오퍼레이션의 메모리 액세스가 다른 읽기
-오퍼레이션에 의존적이라면 데이터 의존성 배리어를 내포시킵니다만, 모두가 그런건
-아니기 때문에 이점에 의존해선 안됩니다.
-
-다른 CPU 들도 분할된 캐시를 가지고 있을 수 있지만, 그런 CPU 들은 평범한 메모리
-액세스를 위해서도 이 분할된 캐시들 사이의 조정을 해야만 합니다.  Alpha 는 가장
-약한 메모리 순서 시맨틱 (semantic) 을 선택함으로써 메모리 배리어가 명시적으로
-사용되지 않았을 때에는 그런 조정이 필요하지 않게 했습니다.
-
-
-캐시 일관성 VS DMA
-------------------
-
-모든 시스템이 DMA 를 하는 디바이스에 대해서까지 캐시 일관성을 유지하지는
-않습니다.  그런 경우, DMA 를 시도하는 디바이스는 RAM 으로부터 잘못된 데이터를
-읽을 수 있는데, 더티 캐시 라인이 CPU 의 캐시에 머무르고 있고, 바뀐 값이 아직
-RAM 에 써지지 않았을 수 있기 때문입니다.  이 문제를 해결하기 위해선, 커널의
-적절한 부분에서 각 CPU 캐시의 문제되는 비트들을 플러시 (flush) 시켜야만 합니다
-(그리고 그것들을 무효화 - invalidation - 시킬 수도 있겠죠).
-
-또한, 디바이스에 의해 RAM 에 DMA 로 쓰여진 값은 디바이스가 쓰기를 완료한 후에
-CPU 의 캐시에서 RAM 으로 쓰여지는 더티 캐시 라인에 의해 덮어써질 수도 있고, CPU
-의 캐시에 존재하는 캐시 라인이 해당 캐시에서 삭제되고 다시 값을 읽어들이기
-전까지는 RAM 이 업데이트 되었다는 사실 자체가 숨겨져 버릴 수도 있습니다.  이
-문제를 해결하기 위해선, 커널의 적절한 부분에서 각 CPU 의 캐시 안의 문제가 되는
-비트들을 무효화 시켜야 합니다.
-
-캐시 관리에 대한 더 많은 정보를 위해선 Documentation/cachetlb.txt 를
-참고하세요.
-
-
-캐시 일관성 VS MMIO
--------------------
-
-Memory mapped I/O 는 일반적으로 CPU 의 메모리 공간 내의 한 윈도우의 특정 부분
-내의 메모리 지역에 이루어지는데, 이 윈도우는 일반적인, RAM 으로 향하는
-윈도우와는 다른 특성을 갖습니다.
-
-그런 특성 가운데 하나는, 일반적으로 그런 액세스는 캐시를 완전히 우회하고
-디바이스 버스로 곧바로 향한다는 것입니다.  이 말은 MMIO 액세스는 먼저
-시작되어서 캐시에서 완료된 메모리 액세스를 추월할 수 있다는 뜻입니다.  이런
-경우엔 메모리 배리어만으로는 충분치 않고, 만약 캐시된 메모리 쓰기 오퍼레이션과
-MMIO 액세스가 어떤 방식으로든 의존적이라면 해당 캐시는 두 오퍼레이션 사이에
-비워져(flush)야만 합니다.
-
-
-======================
-CPU 들이 저지르는 일들
-======================
-
-프로그래머는 CPU 가 메모리 오퍼레이션들을 정확히 요청한대로 수행해 줄 것이라고
-생각하는데, 예를 들어 다음과 같은 코드를 CPU 에게 넘긴다면:
-
-	a = READ_ONCE(*A);
-	WRITE_ONCE(*B, b);
-	c = READ_ONCE(*C);
-	d = READ_ONCE(*D);
-	WRITE_ONCE(*E, e);
-
-CPU 는 다음 인스트럭션을 처리하기 전에 현재의 인스트럭션을 위한 메모리
-오퍼레이션을 완료할 것이라 생각하고, 따라서 시스템 외부에서 관찰하기에도 정해진
-순서대로 오퍼레이션이 수행될 것으로 예상합니다:
-
-	LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E.
-
-
-당연하지만, 실제로는 훨씬 엉망입니다.  많은 CPU 와 컴파일러에서 앞의 가정은
-성립하지 못하는데 그 이유는 다음과 같습니다:
-
- (*) 로드 오퍼레이션들은 실행을 계속 해나가기 위해 곧바로 완료될 필요가 있는
-     경우가 많은 반면, 스토어 오퍼레이션들은 종종 별다른 문제 없이 유예될 수
-     있습니다;
-
- (*) 로드 오퍼레이션들은 예측적으로 수행될 수 있으며, 필요없는 로드였다고
-     증명된 예측적 로드의 결과는 버려집니다;
-
- (*) 로드 오퍼레이션들은 예측적으로 수행될 수 있으므로, 예상된 이벤트의
-     시퀀스와 다른 시간에 로드가 이뤄질 수 있습니다;
-
- (*) 메모리 액세스 순서는 CPU 버스와 캐시를 좀 더 잘 사용할 수 있도록 재배치
-     될 수 있습니다;
-
- (*) 로드와 스토어는 인접한 위치에의 액세스들을 일괄적으로 처리할 수 있는
-     메모리나 I/O 하드웨어 (메모리와 PCI 디바이스 둘 다 이게 가능할 수
-     있습니다) 에 대해 요청되는 경우, 개별 오퍼레이션을 위한 트랜잭션 설정
-     비용을 아끼기 위해 조합되어 실행될 수 있습니다; 그리고
-
- (*) 해당 CPU 의 데이터 캐시가 순서에 영향을 끼칠 수도 있고, 캐시 일관성
-     메커니즘이 - 스토어가 실제로 캐시에 도달한다면 - 이 문제를 완화시킬 수는
-     있지만 이 일관성 관리가 다른 CPU 들에도 같은 순서로 전달된다는 보장은
-     없습니다.
-
-따라서, 앞의 코드에 대해 다른 CPU 가 보는 결과는 다음과 같을 수 있습니다:
-
-	LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B
-
-	("LOAD {*C,*D}" 는 조합된 로드입니다)
-
-
-하지만, CPU 는 스스로는 일관적일 것을 보장합니다: CPU _자신_ 의 액세스들은
-자신에게는 메모리 배리어가 없음에도 불구하고 정확히 순서 세워진 것으로 보여질
-것입니다.  예를 들어 다음의 코드가 주어졌다면:
-
-	U = READ_ONCE(*A);
-	WRITE_ONCE(*A, V);
-	WRITE_ONCE(*A, W);
-	X = READ_ONCE(*A);
-	WRITE_ONCE(*A, Y);
-	Z = READ_ONCE(*A);
-
-그리고 외부의 영향에 의한 간섭이 없다고 가정하면, 최종 결과는 다음과 같이
-나타날 것이라고 예상될 수 있습니다:
-
-	U == *A 의 최초 값
-	X == W
-	Z == Y
-	*A == Y
-
-앞의 코드는 CPU 가 다음의 메모리 액세스 시퀀스를 만들도록 할겁니다:
-
-	U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A
-
-하지만, 별다른 개입이 없고 프로그램의 시야에 이 세상이 여전히 일관적이라고
-보인다는 보장만 지켜진다면 이 시퀀스는 어떤 조합으로든 재구성될 수 있으며, 각
-액세스들은 합쳐지거나 버려질 수 있습니다.  일부 아키텍쳐에서 CPU 는 같은 위치에
-대한 연속적인 로드 오퍼레이션들을 재배치 할 수 있기 때문에 앞의 예에서의
-READ_ONCE() 와 WRITE_ONCE() 는 반드시 존재해야 함을 알아두세요.  그런 종류의
-아키텍쳐에서 READ_ONCE() 와 WRITE_ONCE() 는 이 문제를 막기 위해 필요한 일을
-뭐가 됐든지 하게 되는데, 예를 들어 Itanium 에서는 READ_ONCE() 와 WRITE_ONCE()
-가 사용하는 volatile 캐스팅은 GCC 가 그런 재배치를 방지하는 특수 인스트럭션인
-ld.acq 와 stl.rel 인스트럭션을 각각 만들어 내도록 합니다.
-
-컴파일러 역시 이 시퀀스의 액세스들을 CPU 가 보기도 전에 합치거나 버리거나 뒤로
-미뤄버릴 수 있습니다.
-
-예를 들어:
-
-	*A = V;
-	*A = W;
-
-는 다음과 같이 변형될 수 있습니다:
-
-	*A = W;
-
-따라서, 쓰기 배리어나 WRITE_ONCE() 가 없다면 *A 로의 V 값의 저장의 효과는
-사라진다고 가정될 수 있습니다.  비슷하게:
-
-	*A = Y;
-	Z = *A;
-
-는, 메모리 배리어나 READ_ONCE() 와 WRITE_ONCE() 없이는 다음과 같이 변형될 수
-있습니다:
-
-	*A = Y;
-	Z = Y;
-
-그리고 이 LOAD 오퍼레이션은 CPU 바깥에는 아예 보이지 않습니다.
-
-
-그리고, ALPHA 가 있다
----------------------
-
-DEC Alpha CPU 는 가장 완화된 메모리 순서의 CPU 중 하나입니다.  뿐만 아니라,
-Alpha CPU 의 일부 버전은 분할된 데이터 캐시를 가지고 있어서, 의미적으로
-관계되어 있는 두개의 캐시 라인이 서로 다른 시간에 업데이트 되는게 가능합니다.
-이게 데이터 의존성 배리어가 정말 필요해지는 부분인데, 데이터 의존성 배리어는
-메모리 일관성 시스템과 함께 두개의 캐시를 동기화 시켜서, 포인터 변경과 새로운
-데이터의 발견을 올바른 순서로 일어나게 하기 때문입니다.
-
-리눅스 커널의 메모리 배리어 모델은 Alpha 에 기초해서 정의되었습니다.
-
-위의 "캐시 일관성" 서브섹션을 참고하세요.
-
-
-가상 머신 게스트
-----------------
-
-가상 머신에서 동작하는 게스트들은 게스트 자체는 SMP 지원 없이 컴파일 되었다
-해도 SMP 영향을 받을 수 있습니다.  이건 UP 커널을 사용하면서 SMP 호스트와
-결부되어 발생하는 부작용입니다.  이 경우에는 mandatory 배리어를 사용해서 문제를
-해결할 수 있겠지만 그런 해결은 대부분의 경우 최적의 해결책이 아닙니다.
-
-이 문제를 완벽하게 해결하기 위해, 로우 레벨의 virt_mb() 등의 매크로를 사용할 수
-있습니다. 이것들은 SMP 가 활성화 되어 있다면 smp_mb() 등과 동일한 효과를
-갖습니다만, SMP 와 SMP 아닌 시스템 모두에 대해 동일한 코드를 만들어냅니다.
-예를 들어, 가상 머신 게스트들은 (SMP 일 수 있는) 호스트와 동기화를 할 때에는
-smp_mb() 가 아니라 virt_mb() 를 사용해야 합니다.
-
-이것들은 smp_mb() 류의 것들과 모든 부분에서 동일하며, 특히, MMIO 의 영향에
-대해서는 간여하지 않습니다: MMIO 의 영향을 제어하려면, mandatory 배리어를
-사용하시기 바랍니다.
-
-
-=======
-사용 예
-=======
-
-순환식 버퍼
------------
-
-메모리 배리어는 순환식 버퍼를 생성자(producer)와 소비자(consumer) 사이의
-동기화에 락을 사용하지 않고 구현하는데에 사용될 수 있습니다.  더 자세한 내용을
-위해선 다음을 참고하세요:
-
-	Documentation/circular-buffers.txt
-
-
-=========
-참고 문헌
-=========
-
-Alpha AXP Architecture Reference Manual, Second Edition (Sites & Witek,
-Digital Press)
-	Chapter 5.2: Physical Address Space Characteristics
-	Chapter 5.4: Caches and Write Buffers
-	Chapter 5.5: Data Sharing
-	Chapter 5.6: Read/Write Ordering
-
-AMD64 Architecture Programmer's Manual Volume 2: System Programming
-	Chapter 7.1: Memory-Access Ordering
-	Chapter 7.4: Buffering and Combining Memory Writes
-
-IA-32 Intel Architecture Software Developer's Manual, Volume 3:
-System Programming Guide
-	Chapter 7.1: Locked Atomic Operations
-	Chapter 7.2: Memory Ordering
-	Chapter 7.4: Serializing Instructions
-
-The SPARC Architecture Manual, Version 9
-	Chapter 8: Memory Models
-	Appendix D: Formal Specification of the Memory Models
-	Appendix J: Programming with the Memory Models
-
-UltraSPARC Programmer Reference Manual
-	Chapter 5: Memory Accesses and Cacheability
-	Chapter 15: Sparc-V9 Memory Models
-
-UltraSPARC III Cu User's Manual
-	Chapter 9: Memory Models
-
-UltraSPARC IIIi Processor User's Manual
-	Chapter 8: Memory Models
-
-UltraSPARC Architecture 2005
-	Chapter 9: Memory
-	Appendix D: Formal Specifications of the Memory Models
-
-UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
-	Chapter 8: Memory Models
-	Appendix F: Caches and Cache Coherency
-
-Solaris Internals, Core Kernel Architecture, p63-68:
-	Chapter 3.3: Hardware Considerations for Locks and
-			Synchronization
-
-Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching
-for Kernel Programmers:
-	Chapter 13: Other Memory Models
-
-Intel Itanium Architecture Software Developer's Manual: Volume 1:
-	Section 2.6: Speculation
-	Section 4.4: Memory Access
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ko_KR/stable_api_nonsense.txt linux-libre-4.10-rc8-gnu/Documentation/ko_KR/stable_api_nonsense.txt
--- linux-libre-4.9-gnu/Documentation/ko_KR/stable_api_nonsense.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ko_KR/stable_api_nonsense.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,195 +0,0 @@
-NOTE:
-This is a version of Documentation/stable_api_nonsense.txt translated
-into korean
-This document is maintained by Minchan Kim <minchan@kernel.org>
-If you find any difference between this document and the original file or
-a problem with the translation, please contact the maintainer of this file.
-
-Please also note that the purpose of this file is to be easier to
-read for non English (read: korean) speakers and is not intended as
-a fork. So if you have any comments or updates for this file please
-try to update the original English file first.
-
-==================================
-이 문서는
-Documentation/stable_api_nonsense.txt
-의 한글 번역입니다.
-
-역자： 김민찬 <minchan@kernel.org>
-감수： 이제이미 <jamee.lee@samsung.com>
-==================================
-
-리눅스 커널 드라이버 인터페이스
-(여러분들의 모든 질문에 대한 답 그리고 다른 몇가지)
-
-Greg Kroah-Hartman <greg@kroah.com>
-
-이 문서는 리눅스가 왜 바이너리 커널 인터페이스를 갖지 않는지, 왜 변하지
-않는(stable) 커널 인터페이스를 갖지 않는지를 설명하기 위해 쓰여졌다.
-이 문서는 커널과 유저공간 사이의 인터페이스가 아니라 커널 내부의
-인터페이스들을 설명하고 있다는 것을 유념하라. 커널과 유저공간 사이의
-인터페이스는 응용프로그램이 사용하는 syscall 인터페이스이다. 그 인터페이스는
-오랫동안 거의 변하지 않았고 앞으로도 변하지 않을 것이다. 나는 pre 0.9에서
-만들어졌지만 최신의 2.6 커널 배포에서도 잘 동작하는 프로그램을 가지고
-있다. 이 인터페이스는 사용자와 응용프로그램 개발자들이 변하지 않을 것이라고
-여길수 있는 것이다.
-
-
-초록
-----
-여러분은 변하지 않는 커널 인터페이스를 원한다고 생각하지만 실제로는
-그렇지 않으며 심지어는 그것을 알아채지 못한다. 여러분이 원하는 것은
-안정되게 실행되는 드라이버이며 드라이버가 메인 커널 트리에 있을 때
-그런 안정적인 드라이버를 얻을 수 있게 된다. 또한 여러분의 드라이버가
-메인 커널 트리에 있다면 다른 많은 좋은 이점들을 얻게 된다. 그러한 것들이
-리눅스를 강건하고, 안정적이며, 성숙한 운영체제로 만들어 놓음으로써
-여러분들로 하여금 바로 리눅스를 사용하게 만드는 이유이다.
-
-
-소개
-----
-
-커널 내부의 인터페이스가 바뀌는 것을 걱정하며 커널 드라이버를 작성하고
-싶어하는 사람은 정말 이상한 사람이다. 세상의 대다수의 사람들은 이 인터페이스를
-보지못할 것이며 전혀 걱정하지도 않는다.
-
-먼저, 나는 closed 소스, hidden 소스, binary blobs, 소스 wrappers, 또는 GPL로
-배포되었지만 소스 코드를 갖고 있지 않은 커널 드라이버들을 설명하는 어떤 다른
-용어들에 관한 어떤 법적인 문제에 관해서는 언급하지 않을 것이다. 어떤 법적인
-질문들을 가지고 있다면 변호사와 연락하라. 나는 프로그래머이므로 여기서 기술적인
-문제들만을 설명하려고 한다. (법적인 문제를 경시하는 것은 아니다. 그런 문제들은
-엄연히 현실에 있고 여러분들은 항상 그 문제들을 인식하고 있을 필요는 있다.)
-
-자, 두가지의 주요 주제가 있다. 바이너리 커널 인터페이스들과 변하지 않는
-커널 소스 인터페이들. 그것들은 서로 의존성을 가지고 있지만 바이너리
-문제를 먼저 풀고 넘어갈 것이다.
-
-
-
-바이너리 커널 인터페이스
-------------------------
-우리가 변하지 않는 커널 소스 인터페이스를 가지고 있다고 가정하자. 그러면
-바이너리 인터페이스 또한 자연적으로 변하지 않을까? 틀렸다. 리눅스 커널에
-관한 다음 사실들을 생각해보라.
-   - 여러분들이 사용하는 C 컴파일러의 버젼에 따라 다른 커널 자료 구조들은
-     다른 alignmnet들을 갖게 될것이고 다른 방법으로(함수들을 inline으로
-     했느냐, 아니냐) 다른 함수들을 포함하는 것도 가능한다. 중요한 것은
-     개별적인 함수 구성이 아니라 자료 구조 패딩이 달라진다는 점이다.
-   - 여러분이 선택한 커널 빌드 옵션에 따라서 커널은 다양한 것들을 가정할
-     수 있다.
-      - 다른 구조체들은 다른 필드들을 포함할 수 있다.
-      - 몇몇 함수들은 전혀 구현되지 않을 수도 있다(즉, 몇몇 lock들은
-        non-SMP 빌드에서는 사라져 버릴수도 있다).
-      - 커널내에 메모리는 build optoin들에 따라 다른 방법으로 align될수
-        있다.
-      - 리눅스는 많은 다양한 프로세서 아키텍쳐에서 실행된다. 한 아키텍쳐의
-        바이너리 드라이버를 다른 아키텍쳐에서 정상적으로 실행시킬 방법은
-        없다.
-
-커널을 빌드했던 C 컴파일러와 정확하게 같은 것을 사용하고 정확하게 같은
-커널 구성(configuration)을 사용하여 여러분들의 모듈을 빌드하면 간단히
-많은 문제들을 해결할 수 있다. 이렇게 하는 것은 여러분들이 하나의 리눅스
-배포판의 하나의 배포 버젼을 위한 모듈만을 제공한다면 별일 아닐 것이다.
-그러나 각기 다른 리눅스 배포판마다 한번씩 빌드하는 수를 각 리눅스 배포판마다
-제공하는 다른 릴리즈의 수와 곱하게 되면 이번에는 각 릴리즈들의 다른 빌드
-옵션의 악몽과 마주하게  것이다. 또한 각 리눅스 배포판들은 다른 하드웨어
-종류에(다른 프로세서 타입과 다른 옵션들) 맞춰져 있는 많은 다른 커널들을
-배포한다. 그러므로 한번의 배포에서조차 여러분들의 모듈은 여러 버젼을
-만들 필요가 있다.
-
-나를 믿어라. 여러분들은 이러한 종류의 배포를 지원하려고 시도한다면 시간이
-지나면 미칠지경이 될 것이다. 난 이러한 것을 오래전에 아주 어렵게 배웠다...
-
-
-
-변하지않는 커널 소스 인터페이스들
----------------------------------
-
-리눅스 커널 드라이버를 계속해서 메인 커널 트리에 반영하지 않고
-유지보수하려고 하는 사람들과 이 문제를 논의하게 되면 훨씬 더
-"논란의 여지가 많은" 주제가 될 것이다.
-
-리눅스 커널 개발은 끊임없이 빠른 속도로 이루어지고 있으며 결코
-느슨해진 적이 없다. 커널 개발자들이 현재 인터페이스들에서 버그를
-발견하거나 무엇인가 할 수 있는 더 좋은 방법을 찾게 되었다고 하자.
-그들이 발견한 것을 실행한다면 아마도 더 잘 동작하도록 현재 인터페이스들을
-수정하게 될 것이다. 그들이 그런 일을 하게되면 함수 이름들은 변하게 되고,
-구조체들은 늘어나거나 줄어들게 되고, 함수 파라미터들은 재작업될 것이다.
-이러한 일이 발생되면 커널 내에 이 인터페이스를 사용했던 인스턴스들이 동시에
-수정될 것이며 이러한 과정은 모든 것이 계속해서 올바르게 동작할 것이라는
-것을 보장한다.
-
-이러한 것의 한 예로써, 커널 내부의 USB 인터페이스들은 이 서브시스템이
-생긴 이후로 적어도 3번의 다른 재작업을 겪었다. 이 재작업들은 많은 다른
-문제들을 풀었다.
-   - 데이터 스트림들의 동기적인 모델에서 비동기적인 모델로의 변화. 이것은
-     많은 드라이버들의 복잡성을 줄이고 처리량을 향상시켜 현재는 거의 모든
-     USB 장치들의 거의 최대 속도로 실행되고 있다.
-   - USB 드라이버가 USB 코어로부터 데이터 패킷들을 할당받로록 한 변경으로
-     인해서 지금의 모든 드라이버들은 많은 문서화된 데드락을 수정하기 위하여
-     USB 코어에게 더 많은 정보를 제공해야만 한다.
-
-이것은 오랫동안 자신의 오래된 USB 인터페이스들을 유지해야 하는 closed 운영체제들과는
-완전히 반대되는 것이다. closed된 운영체제들은 새로운 개발자들에게 우연히 낡은
-인터페이스를 사용하게 할 기회를 주게되며, 적절하지 못한 방법으로 처리하게 되어
-운영체제의 안정성을 해치는 문제를 야기하게 된다.
-
-이 두가지의 예들 모두, 모든 개발자들은 꼭 이루어져야 하는 중요한 변화들이라고
-동의를 하였고 비교적 적은 고통으로 변경되어졌다. 리눅스가 변하지 않는 소스
-인터페이스를 고집한다면, 새로운 인터페이스가 만들어지게 되며 반면 기존의 오래된
-것들, 그리고 깨진 것들은 계속해서 유지되어야 하며 이러한 일들은 USB 개발자들에게
-또 다른 일거리를 주게 된다. 모든 리눅스 USB 개발자들에게 자신의 그들의 업무를
-마친 후 시간을 투자하여 아무 득도 없는 무료 봉사를 해달라고 하는 것은 가능성이
-희박한 일이다.
-
-보안 문제 역시 리눅스에게는 매우 중요하다. 보안 문제가 발견되면 그것은
-매우 짧은 시간 안에 수정된다. 보안 문제는 그 문제를 해결하기 위하여
-여러번 내부 커널 인터페이스들을 재작업하게 만들었다. 이러한 문제가
-발생하였을 때 그 인터페이스들을 사용하는 모든 드라이버들도 동시에
-수정되어 보안 문제가 앞으로 갑작스럽게 생기지는 않을 것이라는 것을
-보장한다. 내부 인터페이스들의 변경이 허락되지 않으면 이러한 종류의 보안
-문제를 수정하고 그것이 다시 발생하지 않을 것이라고 보장하는 것은 가능하지
-않을 것이다.
-
-커널 인터페이스들은 계속해서 정리되고 있다. 현재 인터페이스를 사용하는
-사람이 한명도 없다면 그것은 삭제된다. 이것은 커널이 가능한한 가장 작게
-유지되며 존재하는 모든 가능성이 있는 인터페이스들이 테스트된다는 것을
-보장한다(사용되지 않는 인터페이스들은 유효성 검증을 하기가 거의 불가능하다).
-
-
-무엇을 해야 하나
----------------
-자, 여러분이 메인 커널 트리에 있지 않은 리눅스 커널 드라이버를 가지고
-있다면 여러분은 즉, 개발자는 무엇을 해야 하나? 모든 배포판마다 다른
-커널 버젼을 위한 바이너리 드라이버를 배포하는 것은 악몽이며 계속해서
-변하고 있는 커널 인터페이스들의 맞처 유지보수하려고 시도하는 것은 힘든
-일이다.
-
-간단하다. 여러분의 커널 드라이버를 메인 커널 트리에 반영하라(우리는 여기서
-GPL을 따르는 배포 드라이버에 관해 얘기하고 있다는 것을 상기하라. 여러분의
-코드가 이러한 분류에 해당되지 않는다면 행운을 빈다. 여러분 스스로 어떻게든
-해야만 한다). 여러분의 드라이버가 트리에 있게되면 커널 인터페이스가
-변경되더라도 가장 먼저 커널에 변경을 가했던 사람에 의해서 수정될 것이다.
-이것은 여러분의 드라이버가 여러분의 별다른 노력없이 항상 빌드가 가능하며
-동작하는 것을 보장한다.
-
-메인 커널 트리에 여러분의 드라이버를 반영하면 얻게 되는 장점들은 다음과 같다.
-   - 관리에 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다.
-   - 다른 개발자들이 여러분의 드라이버에 기능들을 추가 할 것이다.
-   - 다른 사람들은 여러분의 드라이버에 버그를 발견하고 수정할 것이다.
-   - 다른 사람들은 여러분의 드라이버의 개선점을 찾을 줄 것이다.
-   - 외부 인터페이스 변경으로 인해 여러분의 드라이버의 수정이 필요하다면 다른
-     사람들이 드라이버를 업데이트할 것이다.
-   - 여러분의 드라이버는 별다른 노력 없이 모든 리눅스 배포판에  자동적으로
-     추가될 것이다.
-
-리눅스는 다른 운영 체제보다 "쉽게 쓸수 있는(out of the box)" 많은 다른 장치들을
-지원하고 어떤 다른 운영 체제보다 다양한 아키텍쳐위에서 이러한 장치들을 지원하기 때문에
-이러한 증명된 개발 모델은 틀림없이 바로 가고 있는 것이다.
-
-
-
-------
-
-이 문서의 초안을 검토해주고 코멘트 해준 Randy Dunlap, Andrew Morton, David Brownell,
-Hanna Linder, Robert Love, 그리고 Nishanth Aravamudan에게 감사한다.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/kselftest.txt linux-libre-4.10-rc8-gnu/Documentation/kselftest.txt
--- linux-libre-4.9-gnu/Documentation/kselftest.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/kselftest.txt	2017-02-12 16:03:20.000000000 -0500
@@ -70,6 +70,17 @@ To install selftests in an user specifie
    $ cd tools/testing/selftests
    $ ./kselftest_install.sh install_dir
 
+Running installed selftests
+===========================
+
+Kselftest install as well as the Kselftest tarball provide a script
+named "run_kselftest.sh" to run the tests.
+
+You can simply do the following to run the installed Kselftests. Please
+note some tests will require root privileges.
+
+cd kselftest
+./run_kselftest.sh
 
 Contributing new tests
 ======================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/laptops/thinkpad-acpi.txt linux-libre-4.10-rc8-gnu/Documentation/laptops/thinkpad-acpi.txt
--- linux-libre-4.9-gnu/Documentation/laptops/thinkpad-acpi.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/laptops/thinkpad-acpi.txt	2017-02-12 16:03:20.000000000 -0500
@@ -540,6 +540,7 @@ Events that are propagated by the driver
 0x6022		ALARM: a sensor is extremely hot
 0x6030		System thermal table changed
 0x6040		Nvidia Optimus/AC adapter related (TO BE VERIFIED)
+0x60C0		X1 Yoga 2016, Tablet mode status changed
 
 Battery nearly empty alarms are a last resort attempt to get the
 operating system to hibernate or shutdown cleanly (0x2313), or shutdown
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/leds/leds-lp5523.txt linux-libre-4.10-rc8-gnu/Documentation/leds/leds-lp5523.txt
--- linux-libre-4.9-gnu/Documentation/leds/leds-lp5523.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/leds/leds-lp5523.txt	2017-02-12 16:03:20.000000000 -0500
@@ -34,8 +34,8 @@ There are two ways to run LED patterns.
   Control interface for the engines:
   x is 1 .. 3
   enginex_mode : disabled, load, run
-  enginex_load : microcode load (visible only in load mode)
-  enginex_leds : led mux control (visible only in load mode)
+  enginex_load : microcode load
+  enginex_leds : led mux control
 
   cd /sys/class/leds/lp5523:channel2/device
   echo "load" > engine3_mode
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/leds/uleds.txt linux-libre-4.10-rc8-gnu/Documentation/leds/uleds.txt
--- linux-libre-4.9-gnu/Documentation/leds/uleds.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/leds/uleds.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,36 @@
+Userspace LEDs
+==============
+
+The uleds driver supports userspace LEDs. This can be useful for testing
+triggers and can also be used to implement virtual LEDs.
+
+
+Usage
+=====
+
+When the driver is loaded, a character device is created at /dev/uleds. To
+create a new LED class device, open /dev/uleds and write a uleds_user_dev
+structure to it (found in kernel public header file linux/uleds.h).
+
+    #define LED_MAX_NAME_SIZE 64
+
+    struct uleds_user_dev {
+        char name[LED_MAX_NAME_SIZE];
+    };
+
+A new LED class device will be created with the name given. The name can be
+any valid sysfs device node name, but consider using the LED class naming
+convention of "devicename:color:function".
+
+The current brightness is found by reading a single byte from the character
+device. Values are unsigned: 0 to 255. Reading will block until the brightness
+changes. The device node can also be polled to notify when the brightness value
+changes.
+
+The LED class device will be removed when the open file handle to /dev/uleds
+is closed.
+
+Multiple LED class devices are created by opening additional file handles to
+/dev/uleds.
+
+See tools/leds/uledmon.c for an example userspace program.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/livepatch/livepatch.txt linux-libre-4.10-rc8-gnu/Documentation/livepatch/livepatch.txt
--- linux-libre-4.9-gnu/Documentation/livepatch/livepatch.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/livepatch/livepatch.txt	2017-02-12 16:03:20.000000000 -0500
@@ -87,7 +87,7 @@ The theory about how to apply functions
 The aim is to define a so-called consistency model. It attempts to define
 conditions when the new implementation could be used so that the system
 stays consistent. The theory is not yet finished. See the discussion at
-http://thread.gmane.org/gmane.linux.kernel/1823033/focus=1828189
+https://lkml.kernel.org/r/20141107140458.GA21774@suse.cz
 
 The current consistency model is very simple. It guarantees that either
 the old or the new function is called. But various functions get redirected
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/local_ops.txt linux-libre-4.10-rc8-gnu/Documentation/local_ops.txt
--- linux-libre-4.9-gnu/Documentation/local_ops.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/local_ops.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,191 +0,0 @@
-	     Semantics and Behavior of Local Atomic Operations
-
-			    Mathieu Desnoyers
-
-
-	This document explains the purpose of the local atomic operations, how
-to implement them for any given architecture and shows how they can be used
-properly. It also stresses on the precautions that must be taken when reading
-those local variables across CPUs when the order of memory writes matters.
-
-Note that local_t based operations are not recommended for general kernel use.
-Please use the this_cpu operations instead unless there is really a special purpose.
-Most uses of local_t in the kernel have been replaced by this_cpu operations.
-this_cpu operations combine the relocation with the local_t like semantics in
-a single instruction and yield more compact and faster executing code.
-
-
-* Purpose of local atomic operations
-
-Local atomic operations are meant to provide fast and highly reentrant per CPU
-counters. They minimize the performance cost of standard atomic operations by
-removing the LOCK prefix and memory barriers normally required to synchronize
-across CPUs.
-
-Having fast per CPU atomic counters is interesting in many cases : it does not
-require disabling interrupts to protect from interrupt handlers and it permits
-coherent counters in NMI handlers. It is especially useful for tracing purposes
-and for various performance monitoring counters.
-
-Local atomic operations only guarantee variable modification atomicity wrt the
-CPU which owns the data. Therefore, care must taken to make sure that only one
-CPU writes to the local_t data. This is done by using per cpu data and making
-sure that we modify it from within a preemption safe context. It is however
-permitted to read local_t data from any CPU : it will then appear to be written
-out of order wrt other memory writes by the owner CPU.
-
-
-* Implementation for a given architecture
-
-It can be done by slightly modifying the standard atomic operations : only
-their UP variant must be kept. It typically means removing LOCK prefix (on
-i386 and x86_64) and any SMP synchronization barrier. If the architecture does
-not have a different behavior between SMP and UP, including asm-generic/local.h
-in your architecture's local.h is sufficient.
-
-The local_t type is defined as an opaque signed long by embedding an
-atomic_long_t inside a structure. This is made so a cast from this type to a
-long fails. The definition looks like :
-
-typedef struct { atomic_long_t a; } local_t;
-
-
-* Rules to follow when using local atomic operations
-
-- Variables touched by local ops must be per cpu variables.
-- _Only_ the CPU owner of these variables must write to them.
-- This CPU can use local ops from any context (process, irq, softirq, nmi, ...)
-  to update its local_t variables.
-- Preemption (or interrupts) must be disabled when using local ops in
-  process context to   make sure the process won't be migrated to a
-  different CPU between getting the per-cpu variable and doing the
-  actual local op.
-- When using local ops in interrupt context, no special care must be
-  taken on a mainline kernel, since they will run on the local CPU with
-  preemption already disabled. I suggest, however, to explicitly
-  disable preemption anyway to make sure it will still work correctly on
-  -rt kernels.
-- Reading the local cpu variable will provide the current copy of the
-  variable.
-- Reads of these variables can be done from any CPU, because updates to
-  "long", aligned, variables are always atomic. Since no memory
-  synchronization is done by the writer CPU, an outdated copy of the
-  variable can be read when reading some _other_ cpu's variables.
-
-
-* How to use local atomic operations
-
-#include <linux/percpu.h>
-#include <asm/local.h>
-
-static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
-
-
-* Counting
-
-Counting is done on all the bits of a signed long.
-
-In preemptible context, use get_cpu_var() and put_cpu_var() around local atomic
-operations : it makes sure that preemption is disabled around write access to
-the per cpu variable. For instance :
-
-	local_inc(&get_cpu_var(counters));
-	put_cpu_var(counters);
-
-If you are already in a preemption-safe context, you can use
-this_cpu_ptr() instead.
-
-	local_inc(this_cpu_ptr(&counters));
-
-
-
-* Reading the counters
-
-Those local counters can be read from foreign CPUs to sum the count. Note that
-the data seen by local_read across CPUs must be considered to be out of order
-relatively to other memory writes happening on the CPU that owns the data.
-
-	long sum = 0;
-	for_each_online_cpu(cpu)
-		sum += local_read(&per_cpu(counters, cpu));
-
-If you want to use a remote local_read to synchronize access to a resource
-between CPUs, explicit smp_wmb() and smp_rmb() memory barriers must be used
-respectively on the writer and the reader CPUs. It would be the case if you use
-the local_t variable as a counter of bytes written in a buffer : there should
-be a smp_wmb() between the buffer write and the counter increment and also a
-smp_rmb() between the counter read and the buffer read.
-
-
-Here is a sample module which implements a basic per cpu counter using local.h.
-
---- BEGIN ---
-/* test-local.c
- *
- * Sample module for local.h usage.
- */
-
-
-#include <asm/local.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-
-static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0);
-
-static struct timer_list test_timer;
-
-/* IPI called on each CPU. */
-static void test_each(void *info)
-{
-	/* Increment the counter from a non preemptible context */
-	printk("Increment on cpu %d\n", smp_processor_id());
-	local_inc(this_cpu_ptr(&counters));
-
-	/* This is what incrementing the variable would look like within a
-	 * preemptible context (it disables preemption) :
-	 *
-	 * local_inc(&get_cpu_var(counters));
-	 * put_cpu_var(counters);
-	 */
-}
-
-static void do_test_timer(unsigned long data)
-{
-	int cpu;
-
-	/* Increment the counters */
-	on_each_cpu(test_each, NULL, 1);
-	/* Read all the counters */
-	printk("Counters read from CPU %d\n", smp_processor_id());
-	for_each_online_cpu(cpu) {
-		printk("Read : CPU %d, count %ld\n", cpu,
-			local_read(&per_cpu(counters, cpu)));
-	}
-	del_timer(&test_timer);
-	test_timer.expires = jiffies + 1000;
-	add_timer(&test_timer);
-}
-
-static int __init test_init(void)
-{
-	/* initialize the timer that will increment the counter */
-	init_timer(&test_timer);
-	test_timer.function = do_test_timer;
-	test_timer.expires = jiffies + 1;
-	add_timer(&test_timer);
-
-	return 0;
-}
-
-static void __exit test_exit(void)
-{
-	del_timer_sync(&test_timer);
-}
-
-module_init(test_init);
-module_exit(test_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mathieu Desnoyers");
-MODULE_DESCRIPTION("Local Atomic Ops");
---- END ---
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/lockup-watchdogs.txt linux-libre-4.10-rc8-gnu/Documentation/lockup-watchdogs.txt
--- linux-libre-4.9-gnu/Documentation/lockup-watchdogs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/lockup-watchdogs.txt	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@ details), without giving other tasks a c
 stack trace is displayed upon detection and, by default, the system
 will stay locked up. Alternatively, the kernel can be configured to
 panic; a sysctl, "kernel.softlockup_panic", a kernel parameter,
-"softlockup_panic" (see "Documentation/kernel-parameters.txt" for
+"softlockup_panic" (see "Documentation/admin-guide/kernel-parameters.rst" for
 details), and a compile option, "BOOTPARAM_SOFTLOCKUP_PANIC", are
 provided for this.
 
@@ -23,7 +23,7 @@ upon detection and the system will stay
 behavior is changed, which can be done through a sysctl,
 'hardlockup_panic', a compile time knob, "BOOTPARAM_HARDLOCKUP_PANIC",
 and a kernel parameter, "nmi_watchdog"
-(see "Documentation/kernel-parameters.txt" for details).
+(see "Documentation/admin-guide/kernel-parameters.rst" for details).
 
 The panic option can be used in combination with panic_timeout (this
 timeout is set through the confusingly named "kernel.panic" sysctl),
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/m68k/kernel-options.txt linux-libre-4.10-rc8-gnu/Documentation/m68k/kernel-options.txt
--- linux-libre-4.9-gnu/Documentation/m68k/kernel-options.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/m68k/kernel-options.txt	2017-02-12 16:03:20.000000000 -0500
@@ -139,7 +139,7 @@ follows:
   PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF/PARTNROFF=-2
 
 Authoritative information can be found in
-"Documentation/kernel-parameters.txt".
+"Documentation/admin-guide/kernel-parameters.rst".
 
 
 2.2) ro, rw
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/magic-number.txt linux-libre-4.10-rc8-gnu/Documentation/magic-number.txt
--- linux-libre-4.9-gnu/Documentation/magic-number.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/magic-number.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,158 +0,0 @@
-This file is a registry of magic numbers which are in use.  When you
-add a magic number to a structure, you should also add it to this
-file, since it is best if the magic numbers used by various structures
-are unique.
-
-It is a *very* good idea to protect kernel data structures with magic
-numbers.  This allows you to check at run time whether (a) a structure
-has been clobbered, or (b) you've passed the wrong structure to a
-routine.  This last is especially useful --- particularly when you are
-passing pointers to structures via a void * pointer.  The tty code,
-for example, does this frequently to pass driver-specific and line
-discipline-specific structures back and forth.
-
-The way to use magic numbers is to declare then at the beginning of
-the structure, like so:
-
-struct tty_ldisc {
-	int	magic;
-	...
-};
-
-Please follow this discipline when you are adding future enhancements
-to the kernel!  It has saved me countless hours of debugging,
-especially in the screwy cases where an array has been overrun and
-structures following the array have been overwritten.  Using this
-discipline, these cases get detected quickly and safely.
-
-					Theodore Ts'o
-					31 Mar 94
-
-The magic table is current to Linux 2.1.55.
-
-					Michael Chastain
-					<mailto:mec@shout.net>
-					22 Sep 1997
-
-Now it should be up to date with Linux 2.1.112. Because
-we are in feature freeze time it is very unlikely that
-something will change before 2.2.x. The entries are
-sorted by number field.
-
-					Krzysztof G. Baranowski
-					<mailto: kgb@knm.org.pl>
-					29 Jul 1998
-
-Updated the magic table to Linux 2.5.45. Right over the feature freeze,
-but it is possible that some new magic numbers will sneak into the
-kernel before 2.6.x yet.
-
-					Petr Baudis
-					<pasky@ucw.cz>
-					03 Nov 2002
-
-Updated the magic table to Linux 2.5.74.
-
-					Fabian Frederick
-					<ffrederick@users.sourceforge.net>
-					09 Jul 2003
-
-
-Magic Name            Number      Structure            File
-===========================================================================
-PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
-CMAGIC                0x0111      user              include/linux/a.out.h
-MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
-HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
-APM_BIOS_MAGIC        0x4101      apm_user          arch/x86/kernel/apm_32.c
-CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
-DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
-DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
-FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
-FF_MAGIC              0x4646      fc_info           drivers/net/iph5526_novram.c
-ISICOM_MAGIC          0x4d54      isi_port          include/linux/isicom.h
-PTY_MAGIC             0x5001                        drivers/char/pty.c
-PPP_MAGIC             0x5002      ppp               include/linux/if_pppvar.h
-SERIAL_MAGIC          0x5301      async_struct      include/linux/serial.h
-SSTATE_MAGIC          0x5302      serial_state      include/linux/serial.h
-SLIP_MAGIC            0x5302      slip              drivers/net/slip.h
-STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
-X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
-SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
-AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
-TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
-MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
-TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
-MGSLPC_MAGIC          0x5402      mgslpc_info       drivers/char/pcmcia/synclink_cs.c
-TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
-USB_SERIAL_MAGIC      0x6702      usb_serial        drivers/usb/serial/usb-serial.h
-FULL_DUPLEX_MAGIC     0x6969                        drivers/net/ethernet/dec/tulip/de2104x.c
-USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
-RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
-USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
-CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
-RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
-LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
-GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
-RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
-NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
-RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
-BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
-ISDN_X25IFACE_MAGIC   0x1e75a2b9  isdn_x25iface_proto_data
-                                                    drivers/isdn/isdn_x25iface.h
-ECP_MAGIC             0x21504345  cdkecpsig         include/linux/cdk.h
-LSOMAGIC              0x27091997  lso               drivers/fc4/fc.c
-LSMAGIC               0x2a3b4d2a  ls                drivers/fc4/fc.c
-WANPIPE_MAGIC         0x414C4453  sdla_{dump,exec}  include/linux/wanpipe.h
-CS_CARD_MAGIC         0x43525553  cs_card           sound/oss/cs46xx.c
-LABELCL_MAGIC         0x4857434c  labelcl_info_s    include/asm/ia64/sn/labelcl.h
-ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
-CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
-ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
-SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
-CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
-SLAB_C_MAGIC          0x4f17a36d  kmem_cache        mm/slab.c
-COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
-I810_CARD_MAGIC       0x5072696E  i810_card         sound/oss/i810_audio.c
-TRIDENT_CARD_MAGIC    0x5072696E  trident_card      sound/oss/trident.c
-ROUTER_MAGIC          0x524d4157  wan_device        [in wanrouter.h pre 3.9]
-SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
-GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
-RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
-EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
-HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
-PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
-KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
-I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
-TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
-M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
-FW_HEADER_MAGIC       0x65726F66  fw_header         drivers/atm/fore200e.h
-SLOT_MAGIC            0x67267321  slot              drivers/hotplug/cpqphp.h
-SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
-LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
-OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
-M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
-VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
-KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
-PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
-NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
-ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
-CODA_MAGIC            0xC0DAC0DA  coda_file_info    fs/coda/coda_fs_i.h
-DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
-YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
-CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
-QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
-QUEUE_MAGIC_USED      0xf7e1cc33  queue_entry       drivers/scsi/arm/queue.c
-HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
-NMI_MAGIC             0x48414d4d455201 nmi_s        arch/mips/include/asm/sn/nmi.h
-
-Note that there are also defined special per-driver magic numbers in sound
-memory management. See include/sound/sndmagic.h for complete list of them. Many
-OSS sound drivers have their magic numbers constructed from the soundcard PCI
-ID - these are not listed here as well.
-
-IrDA subsystem also uses large number of own magic numbers, see
-include/net/irda/irda.h for a complete list of them.
-
-HFS is another larger user of magic numbers - you can find them in
-fs/hfs/hfs.h.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/Makefile.sphinx linux-libre-4.10-rc8-gnu/Documentation/Makefile.sphinx
--- linux-libre-4.9-gnu/Documentation/Makefile.sphinx	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/Makefile.sphinx	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,8 @@ _SPHINXDIRS   = $(patsubst $(srctree)/Do
 SPHINX_CONF   = conf.py
 PAPER         =
 BUILDDIR      = $(obj)/output
+PDFLATEX      = xelatex
+LATEXOPTS     = -interaction=batchmode
 
 # User-friendly check for sphinx-build
 HAVE_SPHINX := $(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi)
@@ -29,7 +31,7 @@ else ifneq ($(DOCBOOKS),)
 else # HAVE_SPHINX
 
 # User-friendly check for pdflatex
-HAVE_PDFLATEX := $(shell if which xelatex >/dev/null 2>&1; then echo 1; else echo 0; fi)
+HAVE_PDFLATEX := $(shell if which $(PDFLATEX) >/dev/null 2>&1; then echo 1; else echo 0; fi)
 
 # Internal variables.
 PAPEROPT_a4     = -D latex_paper_size=a4
@@ -51,8 +53,8 @@ loop_cmd = $(echo-cmd) $(cmd_$(1))
 # $5 reST source folder relative to $(srctree)/$(src),
 #    e.g. "media" for the linux-tv book-set at ./Documentation/media
 
-quiet_cmd_sphinx = SPHINX  $@ --> file://$(abspath $(BUILDDIR)/$3/$4);
-      cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media all;\
+quiet_cmd_sphinx = SPHINX  $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
+      cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media $2;\
 	BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
 	$(SPHINXBUILD) \
 	-b $2 \
@@ -67,16 +69,19 @@ htmldocs:
 	@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
 
 latexdocs:
+	@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
+
 ifeq ($(HAVE_PDFLATEX),0)
-	$(warning The 'xelatex' command was not found. Make sure you have it installed and in PATH to produce PDF output.)
+
+pdfdocs:
+	$(warning The '$(PDFLATEX)' command was not found. Make sure you have it installed and in PATH to produce PDF output.)
 	@echo "  SKIP    Sphinx $@ target."
+
 else # HAVE_PDFLATEX
-	@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
-endif # HAVE_PDFLATEX
 
 pdfdocs: latexdocs
-ifneq ($(HAVE_PDFLATEX),0)
-	$(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=xelatex LATEXOPTS="-interaction=nonstopmode" -C $(BUILDDIR)/$(var)/latex)
+	$(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex;)
+
 endif # HAVE_PDFLATEX
 
 epubdocs:
@@ -93,6 +98,7 @@ installmandocs:
 
 cleandocs:
 	$(Q)rm -rf $(BUILDDIR)
+	$(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) -C Documentation/media clean
 
 endif # HAVE_SPHINX
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ManagementStyle linux-libre-4.10-rc8-gnu/Documentation/ManagementStyle
--- linux-libre-4.9-gnu/Documentation/ManagementStyle	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ManagementStyle	1969-12-31 19:00:00.000000000 -0500
@@ -1,288 +0,0 @@
-.. _managementstyle:
-
-Linux kernel management style
-=============================
-
-This is a short document describing the preferred (or made up, depending
-on who you ask) management style for the linux kernel.  It's meant to
-mirror the CodingStyle document to some degree, and mainly written to
-avoid answering [#f1]_  the same (or similar) questions over and over again.
-
-Management style is very personal and much harder to quantify than
-simple coding style rules, so this document may or may not have anything
-to do with reality.  It started as a lark, but that doesn't mean that it
-might not actually be true. You'll have to decide for yourself.
-
-Btw, when talking about "kernel manager", it's all about the technical
-lead persons, not the people who do traditional management inside
-companies.  If you sign purchase orders or you have any clue about the
-budget of your group, you're almost certainly not a kernel manager.
-These suggestions may or may not apply to you.
-
-First off, I'd suggest buying "Seven Habits of Highly Effective
-People", and NOT read it.  Burn it, it's a great symbolic gesture.
-
-.. [#f1] This document does so not so much by answering the question, but by
-  making it painfully obvious to the questioner that we don't have a clue
-  to what the answer is.
-
-Anyway, here goes:
-
-.. _decisions:
-
-1) Decisions
-------------
-
-Everybody thinks managers make decisions, and that decision-making is
-important.  The bigger and more painful the decision, the bigger the
-manager must be to make it.  That's very deep and obvious, but it's not
-actually true.
-
-The name of the game is to **avoid** having to make a decision.  In
-particular, if somebody tells you "choose (a) or (b), we really need you
-to decide on this", you're in trouble as a manager.  The people you
-manage had better know the details better than you, so if they come to
-you for a technical decision, you're screwed.  You're clearly not
-competent to make that decision for them.
-
-(Corollary:if the people you manage don't know the details better than
-you, you're also screwed, although for a totally different reason.
-Namely that you are in the wrong job, and that **they** should be managing
-your brilliance instead).
-
-So the name of the game is to **avoid** decisions, at least the big and
-painful ones.  Making small and non-consequential decisions is fine, and
-makes you look like you know what you're doing, so what a kernel manager
-needs to do is to turn the big and painful ones into small things where
-nobody really cares.
-
-It helps to realize that the key difference between a big decision and a
-small one is whether you can fix your decision afterwards.  Any decision
-can be made small by just always making sure that if you were wrong (and
-you **will** be wrong), you can always undo the damage later by
-backtracking.  Suddenly, you get to be doubly managerial for making
-**two** inconsequential decisions - the wrong one **and** the right one.
-
-And people will even see that as true leadership (*cough* bullshit
-*cough*).
-
-Thus the key to avoiding big decisions becomes to just avoiding to do
-things that can't be undone.  Don't get ushered into a corner from which
-you cannot escape.  A cornered rat may be dangerous - a cornered manager
-is just pitiful.
-
-It turns out that since nobody would be stupid enough to ever really let
-a kernel manager have huge fiscal responsibility **anyway**, it's usually
-fairly easy to backtrack.  Since you're not going to be able to waste
-huge amounts of money that you might not be able to repay, the only
-thing you can backtrack on is a technical decision, and there
-back-tracking is very easy: just tell everybody that you were an
-incompetent nincompoop, say you're sorry, and undo all the worthless
-work you had people work on for the last year.  Suddenly the decision
-you made a year ago wasn't a big decision after all, since it could be
-easily undone.
-
-It turns out that some people have trouble with this approach, for two
-reasons:
-
- - admitting you were an idiot is harder than it looks.  We all like to
-   maintain appearances, and coming out in public to say that you were
-   wrong is sometimes very hard indeed.
- - having somebody tell you that what you worked on for the last year
-   wasn't worthwhile after all can be hard on the poor lowly engineers
-   too, and while the actual **work** was easy enough to undo by just
-   deleting it, you may have irrevocably lost the trust of that
-   engineer.  And remember: "irrevocable" was what we tried to avoid in
-   the first place, and your decision ended up being a big one after
-   all.
-
-Happily, both of these reasons can be mitigated effectively by just
-admitting up-front that you don't have a friggin' clue, and telling
-people ahead of the fact that your decision is purely preliminary, and
-might be the wrong thing.  You should always reserve the right to change
-your mind, and make people very **aware** of that.  And it's much easier
-to admit that you are stupid when you haven't **yet** done the really
-stupid thing.
-
-Then, when it really does turn out to be stupid, people just roll their
-eyes and say "Oops, he did it again".
-
-This preemptive admission of incompetence might also make the people who
-actually do the work also think twice about whether it's worth doing or
-not.  After all, if **they** aren't certain whether it's a good idea, you
-sure as hell shouldn't encourage them by promising them that what they
-work on will be included.  Make them at least think twice before they
-embark on a big endeavor.
-
-Remember: they'd better know more about the details than you do, and
-they usually already think they have the answer to everything.  The best
-thing you can do as a manager is not to instill confidence, but rather a
-healthy dose of critical thinking on what they do.
-
-Btw, another way to avoid a decision is to plaintively just whine "can't
-we just do both?" and look pitiful.  Trust me, it works.  If it's not
-clear which approach is better, they'll eventually figure it out.  The
-answer may end up being that both teams get so frustrated by the
-situation that they just give up.
-
-That may sound like a failure, but it's usually a sign that there was
-something wrong with both projects, and the reason the people involved
-couldn't decide was that they were both wrong.  You end up coming up
-smelling like roses, and you avoided yet another decision that you could
-have screwed up on.
-
-
-2) People
----------
-
-Most people are idiots, and being a manager means you'll have to deal
-with it, and perhaps more importantly, that **they** have to deal with
-**you**.
-
-It turns out that while it's easy to undo technical mistakes, it's not
-as easy to undo personality disorders.  You just have to live with
-theirs - and yours.
-
-However, in order to prepare yourself as a kernel manager, it's best to
-remember not to burn any bridges, bomb any innocent villagers, or
-alienate too many kernel developers. It turns out that alienating people
-is fairly easy, and un-alienating them is hard. Thus "alienating"
-immediately falls under the heading of "not reversible", and becomes a
-no-no according to :ref:`decisions`.
-
-There's just a few simple rules here:
-
- (1) don't call people d*ckheads (at least not in public)
- (2) learn how to apologize when you forgot rule (1)
-
-The problem with #1 is that it's very easy to do, since you can say
-"you're a d*ckhead" in millions of different ways [#f2]_, sometimes without
-even realizing it, and almost always with a white-hot conviction that
-you are right.
-
-And the more convinced you are that you are right (and let's face it,
-you can call just about **anybody** a d*ckhead, and you often **will** be
-right), the harder it ends up being to apologize afterwards.
-
-To solve this problem, you really only have two options:
-
- - get really good at apologies
- - spread the "love" out so evenly that nobody really ends up feeling
-   like they get unfairly targeted.  Make it inventive enough, and they
-   might even be amused.
-
-The option of being unfailingly polite really doesn't exist. Nobody will
-trust somebody who is so clearly hiding his true character.
-
-.. [#f2] Paul Simon sang "Fifty Ways to Leave Your Lover", because quite
-  frankly, "A Million Ways to Tell a Developer He Is a D*ckhead" doesn't
-  scan nearly as well.  But I'm sure he thought about it.
-
-
-3) People II - the Good Kind
-----------------------------
-
-While it turns out that most people are idiots, the corollary to that is
-sadly that you are one too, and that while we can all bask in the secure
-knowledge that we're better than the average person (let's face it,
-nobody ever believes that they're average or below-average), we should
-also admit that we're not the sharpest knife around, and there will be
-other people that are less of an idiot than you are.
-
-Some people react badly to smart people.  Others take advantage of them.
-
-Make sure that you, as a kernel maintainer, are in the second group.
-Suck up to them, because they are the people who will make your job
-easier. In particular, they'll be able to make your decisions for you,
-which is what the game is all about.
-
-So when you find somebody smarter than you are, just coast along.  Your
-management responsibilities largely become ones of saying "Sounds like a
-good idea - go wild", or "That sounds good, but what about xxx?".  The
-second version in particular is a great way to either learn something
-new about "xxx" or seem **extra** managerial by pointing out something the
-smarter person hadn't thought about.  In either case, you win.
-
-One thing to look out for is to realize that greatness in one area does
-not necessarily translate to other areas.  So you might prod people in
-specific directions, but let's face it, they might be good at what they
-do, and suck at everything else.  The good news is that people tend to
-naturally gravitate back to what they are good at, so it's not like you
-are doing something irreversible when you **do** prod them in some
-direction, just don't push too hard.
-
-
-4) Placing blame
-----------------
-
-Things will go wrong, and people want somebody to blame. Tag, you're it.
-
-It's not actually that hard to accept the blame, especially if people
-kind of realize that it wasn't **all** your fault.  Which brings us to the
-best way of taking the blame: do it for another guy. You'll feel good
-for taking the fall, he'll feel good about not getting blamed, and the
-guy who lost his whole 36GB porn-collection because of your incompetence
-will grudgingly admit that you at least didn't try to weasel out of it.
-
-Then make the developer who really screwed up (if you can find him) know
-**in_private** that he screwed up.  Not just so he can avoid it in the
-future, but so that he knows he owes you one.  And, perhaps even more
-importantly, he's also likely the person who can fix it.  Because, let's
-face it, it sure ain't you.
-
-Taking the blame is also why you get to be manager in the first place.
-It's part of what makes people trust you, and allow you the potential
-glory, because you're the one who gets to say "I screwed up".  And if
-you've followed the previous rules, you'll be pretty good at saying that
-by now.
-
-
-5) Things to avoid
-------------------
-
-There's one thing people hate even more than being called "d*ckhead",
-and that is being called a "d*ckhead" in a sanctimonious voice.  The
-first you can apologize for, the second one you won't really get the
-chance.  They likely will no longer be listening even if you otherwise
-do a good job.
-
-We all think we're better than anybody else, which means that when
-somebody else puts on airs, it **really** rubs us the wrong way.  You may
-be morally and intellectually superior to everybody around you, but
-don't try to make it too obvious unless you really **intend** to irritate
-somebody [#f3]_.
-
-Similarly, don't be too polite or subtle about things. Politeness easily
-ends up going overboard and hiding the problem, and as they say, "On the
-internet, nobody can hear you being subtle". Use a big blunt object to
-hammer the point in, because you can't really depend on people getting
-your point otherwise.
-
-Some humor can help pad both the bluntness and the moralizing.  Going
-overboard to the point of being ridiculous can drive a point home
-without making it painful to the recipient, who just thinks you're being
-silly.  It can thus help get through the personal mental block we all
-have about criticism.
-
-.. [#f3] Hint: internet newsgroups that are not directly related to your work
-  are great ways to take out your frustrations at other people. Write
-  insulting posts with a sneer just to get into a good flame every once in
-  a while, and you'll feel cleansed. Just don't crap too close to home.
-
-
-6) Why me?
-----------
-
-Since your main responsibility seems to be to take the blame for other
-peoples mistakes, and make it painfully obvious to everybody else that
-you're incompetent, the obvious question becomes one of why do it in the
-first place?
-
-First off, while you may or may not get screaming teenage girls (or
-boys, let's not be judgmental or sexist here) knocking on your dressing
-room door, you **will** get an immense feeling of personal accomplishment
-for being "in charge".  Never mind the fact that you're really leading
-by trying to keep up with everybody else and running after them as fast
-as you can.  Everybody will still think you're the person in charge.
-
-It's a great job if you can hack it.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/md.txt linux-libre-4.10-rc8-gnu/Documentation/md.txt
--- linux-libre-4.9-gnu/Documentation/md.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/md.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,613 +0,0 @@
-Tools that manage md devices can be found at
-   http://www.kernel.org/pub/linux/utils/raid/ 
-
-
-Boot time assembly of RAID arrays
----------------------------------
-
-You can boot with your md device with the following kernel command
-lines:
-
-for old raid arrays without persistent superblocks:
-  md=<md device no.>,<raid level>,<chunk size factor>,<fault level>,dev0,dev1,...,devn
-
-for raid arrays with persistent superblocks
-  md=<md device no.>,dev0,dev1,...,devn
-or, to assemble a partitionable array:
-  md=d<md device no.>,dev0,dev1,...,devn
-  
-md device no. = the number of the md device ... 
-              0 means md0, 
-	      1 md1,
-	      2 md2,
-	      3 md3,
-	      4 md4
-
-raid level = -1 linear mode
-              0 striped mode
-	      other modes are only supported with persistent super blocks
-
-chunk size factor = (raid-0 and raid-1 only)
-              Set  the chunk size as 4k << n.
-	      
-fault level = totally ignored
-			    
-dev0-devn: e.g. /dev/hda1,/dev/hdc1,/dev/sda1,/dev/sdb1
-			    
-A possible loadlin line (Harald Hoyer <HarryH@Royal.Net>)  looks like this:
-
-e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
-
-
-Boot time autodetection of RAID arrays
---------------------------------------
-
-When md is compiled into the kernel (not as module), partitions of
-type 0xfd are scanned and automatically assembled into RAID arrays.
-This autodetection may be suppressed with the kernel parameter
-"raid=noautodetect".  As of kernel 2.6.9, only drives with a type 0
-superblock can be autodetected and run at boot time.
-
-The kernel parameter "raid=partitionable" (or "raid=part") means
-that all auto-detected arrays are assembled as partitionable.
-
-Boot time assembly of degraded/dirty arrays
--------------------------------------------
-
-If a raid5 or raid6 array is both dirty and degraded, it could have
-undetectable data corruption.  This is because the fact that it is
-'dirty' means that the parity cannot be trusted, and the fact that it
-is degraded means that some datablocks are missing and cannot reliably
-be reconstructed (due to no parity).
-
-For this reason, md will normally refuse to start such an array.  This
-requires the sysadmin to take action to explicitly start the array
-despite possible corruption.  This is normally done with
-   mdadm --assemble --force ....
-
-This option is not really available if the array has the root
-filesystem on it.  In order to support this booting from such an
-array, md supports a module parameter "start_dirty_degraded" which,
-when set to 1, bypassed the checks and will allows dirty degraded
-arrays to be started.
-
-So, to boot with a root filesystem of a dirty degraded raid[56], use
-
-   md-mod.start_dirty_degraded=1
-
-
-Superblock formats
-------------------
-
-The md driver can support a variety of different superblock formats.
-Currently, it supports superblock formats "0.90.0" and the "md-1" format
-introduced in the 2.5 development series.
-
-The kernel will autodetect which format superblock is being used.
-
-Superblock format '0' is treated differently to others for legacy
-reasons - it is the original superblock format.
-
-
-General Rules - apply for all superblock formats
-------------------------------------------------
-
-An array is 'created' by writing appropriate superblocks to all
-devices.
-
-It is 'assembled' by associating each of these devices with an
-particular md virtual device.  Once it is completely assembled, it can
-be accessed.
-
-An array should be created by a user-space tool.  This will write
-superblocks to all devices.  It will usually mark the array as
-'unclean', or with some devices missing so that the kernel md driver
-can create appropriate redundancy (copying in raid1, parity
-calculation in raid4/5).
-
-When an array is assembled, it is first initialized with the
-SET_ARRAY_INFO ioctl.  This contains, in particular, a major and minor
-version number.  The major version number selects which superblock
-format is to be used.  The minor number might be used to tune handling
-of the format, such as suggesting where on each device to look for the
-superblock.
-
-Then each device is added using the ADD_NEW_DISK ioctl.  This
-provides, in particular, a major and minor number identifying the
-device to add.
-
-The array is started with the RUN_ARRAY ioctl.
-
-Once started, new devices can be added.  They should have an
-appropriate superblock written to them, and then be passed in with
-ADD_NEW_DISK.
-
-Devices that have failed or are not yet active can be detached from an
-array using HOT_REMOVE_DISK.
-
-
-Specific Rules that apply to format-0 super block arrays, and
-       arrays with no superblock (non-persistent).
--------------------------------------------------------------
-
-An array can be 'created' by describing the array (level, chunksize
-etc) in a SET_ARRAY_INFO ioctl.  This must have major_version==0 and
-raid_disks != 0.
-
-Then uninitialized devices can be added with ADD_NEW_DISK.  The
-structure passed to ADD_NEW_DISK must specify the state of the device
-and its role in the array.
-
-Once started with RUN_ARRAY, uninitialized spares can be added with
-HOT_ADD_DISK.
-
-
-
-MD devices in sysfs
--------------------
-md devices appear in sysfs (/sys) as regular block devices,
-e.g.
-   /sys/block/md0
-
-Each 'md' device will contain a subdirectory called 'md' which
-contains further md-specific information about the device.
-
-All md devices contain:
-  level
-     a text file indicating the 'raid level'. e.g. raid0, raid1,
-     raid5, linear, multipath, faulty.
-     If no raid level has been set yet (array is still being
-     assembled), the value will reflect whatever has been written
-     to it, which may be a name like the above, or may be a number
-     such as '0', '5', etc.
-
-  raid_disks
-     a text file with a simple number indicating the number of devices
-     in a fully functional array.  If this is not yet known, the file
-     will be empty.  If an array is being resized this will contain
-     the new number of devices.
-     Some raid levels allow this value to be set while the array is
-     active.  This will reconfigure the array.   Otherwise it can only
-     be set while assembling an array.
-     A change to this attribute will not be permitted if it would
-     reduce the size of the array.  To reduce the number of drives
-     in an e.g. raid5, the array size must first be reduced by
-     setting the 'array_size' attribute.
-
-  chunk_size
-     This is the size in bytes for 'chunks' and is only relevant to
-     raid levels that involve striping (0,4,5,6,10). The address space
-     of the array is conceptually divided into chunks and consecutive
-     chunks are striped onto neighbouring devices.
-     The size should be at least PAGE_SIZE (4k) and should be a power
-     of 2.  This can only be set while assembling an array
-
-  layout
-     The "layout" for the array for the particular level.  This is
-     simply a number that is interpretted differently by different
-     levels.  It can be written while assembling an array.
-
-  array_size
-     This can be used to artificially constrain the available space in
-     the array to be less than is actually available on the combined
-     devices.  Writing a number (in Kilobytes) which is less than
-     the available size will set the size.  Any reconfiguration of the
-     array (e.g. adding devices) will not cause the size to change.
-     Writing the word 'default' will cause the effective size of the
-     array to be whatever size is actually available based on
-     'level', 'chunk_size' and 'component_size'.
-
-     This can be used to reduce the size of the array before reducing
-     the number of devices in a raid4/5/6, or to support external
-     metadata formats which mandate such clipping.
-
-  reshape_position
-     This is either "none" or a sector number within the devices of
-     the array where "reshape" is up to.  If this is set, the three
-     attributes mentioned above (raid_disks, chunk_size, layout) can
-     potentially have 2 values, an old and a new value.  If these
-     values differ, reading the attribute returns
-        new (old)
-     and writing will effect the 'new' value, leaving the 'old'
-     unchanged.
-
-  component_size
-     For arrays with data redundancy (i.e. not raid0, linear, faulty,
-     multipath), all components must be the same size - or at least
-     there must a size that they all provide space for.  This is a key
-     part or the geometry of the array.  It is measured in sectors
-     and can be read from here.  Writing to this value may resize
-     the array if the personality supports it (raid1, raid5, raid6),
-     and if the component drives are large enough.
-
-  metadata_version
-     This indicates the format that is being used to record metadata
-     about the array.  It can be 0.90 (traditional format), 1.0, 1.1,
-     1.2 (newer format in varying locations) or "none" indicating that
-     the kernel isn't managing metadata at all.
-     Alternately it can be "external:" followed by a string which
-     is set by user-space.  This indicates that metadata is managed
-     by a user-space program.  Any device failure or other event that
-     requires a metadata update will cause array activity to be
-     suspended until the event is acknowledged.
-
-  resync_start
-     The point at which resync should start.  If no resync is needed,
-     this will be a very large number (or 'none' since 2.6.30-rc1).  At
-     array creation it will default to 0, though starting the array as
-     'clean' will set it much larger.
-
-   new_dev
-     This file can be written but not read.  The value written should
-     be a block device number as major:minor.  e.g. 8:0
-     This will cause that device to be attached to the array, if it is
-     available.  It will then appear at md/dev-XXX (depending on the
-     name of the device) and further configuration is then possible.
-
-   safe_mode_delay
-     When an md array has seen no write requests for a certain period
-     of time, it will be marked as 'clean'.  When another write
-     request arrives, the array is marked as 'dirty' before the write
-     commences.  This is known as 'safe_mode'.
-     The 'certain period' is controlled by this file which stores the
-     period as a number of seconds.  The default is 200msec (0.200).
-     Writing a value of 0 disables safemode.
-
-   array_state
-     This file contains a single word which describes the current
-     state of the array.  In many cases, the state can be set by
-     writing the word for the desired state, however some states
-     cannot be explicitly set, and some transitions are not allowed.
-
-     Select/poll works on this file.  All changes except between
-     	active_idle and active (which can be frequent and are not
-	very interesting) are notified.  active->active_idle is
-	reported if the metadata is externally managed.
-
-     clear
-         No devices, no size, no level
-         Writing is equivalent to STOP_ARRAY ioctl
-     inactive
-         May have some settings, but array is not active
-            all IO results in error
-         When written, doesn't tear down array, but just stops it
-     suspended (not supported yet)
-         All IO requests will block. The array can be reconfigured.
-         Writing this, if accepted, will block until array is quiessent
-     readonly
-         no resync can happen.  no superblocks get written.
-         write requests fail
-     read-auto
-         like readonly, but behaves like 'clean' on a write request.
-
-     clean - no pending writes, but otherwise active.
-         When written to inactive array, starts without resync
-         If a write request arrives then
-           if metadata is known, mark 'dirty' and switch to 'active'.
-           if not known, block and switch to write-pending
-         If written to an active array that has pending writes, then fails.
-     active
-         fully active: IO and resync can be happening.
-         When written to inactive array, starts with resync
-
-     write-pending
-         clean, but writes are blocked waiting for 'active' to be written.
-
-     active-idle
-         like active, but no writes have been seen for a while (safe_mode_delay).
-
-  bitmap/location
-     This indicates where the write-intent bitmap for the array is
-     stored.
-     It can be one of "none", "file" or "[+-]N".
-     "file" may later be extended to "file:/file/name"
-     "[+-]N" means that many sectors from the start of the metadata.
-       This is replicated on all devices.  For arrays with externally
-       managed metadata, the offset is from the beginning of the
-       device.
-  bitmap/chunksize
-     The size, in bytes, of the chunk which will be represented by a
-     single bit.  For RAID456, it is a portion of an individual
-     device. For RAID10, it is a portion of the array.  For RAID1, it
-     is both (they come to the same thing).
-  bitmap/time_base
-     The time, in seconds, between looking for bits in the bitmap to
-     be cleared. In the current implementation, a bit will be cleared
-     between 2 and 3 times "time_base" after all the covered blocks
-     are known to be in-sync.
-  bitmap/backlog
-     When write-mostly devices are active in a RAID1, write requests
-     to those devices proceed in the background - the filesystem (or
-     other user of the device) does not have to wait for them.
-     'backlog' sets a limit on the number of concurrent background
-     writes.  If there are more than this, new writes will by
-     synchronous.
-  bitmap/metadata
-     This can be either 'internal' or 'external'.
-     'internal' is the default and means the metadata for the bitmap
-     is stored in the first 256 bytes of the allocated space and is
-     managed by the md module.
-     'external' means that bitmap metadata is managed externally to
-     the kernel (i.e. by some userspace program)
-  bitmap/can_clear
-     This is either 'true' or 'false'.  If 'true', then bits in the
-     bitmap will be cleared when the corresponding blocks are thought
-     to be in-sync.  If 'false', bits will never be cleared.
-     This is automatically set to 'false' if a write happens on a
-     degraded array, or if the array becomes degraded during a write.
-     When metadata is managed externally, it should be set to true
-     once the array becomes non-degraded, and this fact has been
-     recorded in the metadata.
-     
-     
-     
-
-As component devices are added to an md array, they appear in the 'md'
-directory as new directories named
-      dev-XXX
-where XXX is a name that the kernel knows for the device, e.g. hdb1.
-Each directory contains:
-
-      block
-        a symlink to the block device in /sys/block, e.g.
-	     /sys/block/md0/md/dev-hdb1/block -> ../../../../block/hdb/hdb1
-
-      super
-        A file containing an image of the superblock read from, or
-        written to, that device.
-
-      state
-	A file recording the current state of the device in the array
-	which can be a comma separated list of
-	      faulty   - device has been kicked from active use due to
-			 a detected fault, or it has unacknowledged bad
-			 blocks
-	      in_sync  - device is a fully in-sync member of the array
-	      writemostly - device will only be subject to read
-			 requests if there are no other options.
-			 This applies only to raid1 arrays.
-	      blocked  - device has failed, and the failure hasn't been
-			 acknowledged yet by the metadata handler.
-			 Writes that would write to this device if
-			 it were not faulty are blocked.
-	      spare    - device is working, but not a full member.
-			 This includes spares that are in the process
-			 of being recovered to
-	      write_error - device has ever seen a write error.
-	      want_replacement - device is (mostly) working but probably
-			 should be replaced, either due to errors or
-			 due to user request.
-	      replacement - device is a replacement for another active
-			 device with same raid_disk.
-
-
-	This list may grow in future.
-	This can be written to.
-	Writing "faulty"  simulates a failure on the device.
-	Writing "remove" removes the device from the array.
-	Writing "writemostly" sets the writemostly flag.
-	Writing "-writemostly" clears the writemostly flag.
-	Writing "blocked" sets the "blocked" flag.
-	Writing "-blocked" clears the "blocked" flags and allows writes
-		to complete and possibly simulates an error.
-	Writing "in_sync" sets the in_sync flag.
-	Writing "write_error" sets writeerrorseen flag.
-	Writing "-write_error" clears writeerrorseen flag.
-	Writing "want_replacement" is allowed at any time except to a
-		replacement device or a spare.  It sets the flag.
-	Writing "-want_replacement" is allowed at any time.  It clears
-		the flag.
-	Writing "replacement" or "-replacement" is only allowed before
-		starting the array.  It sets or clears the flag.
-
-
-	This file responds to select/poll. Any change to 'faulty'
-	or 'blocked' causes an event.
-
-      errors
-	An approximate count of read errors that have been detected on
-	this device but have not caused the device to be evicted from
-	the array (either because they were corrected or because they
-	happened while the array was read-only).  When using version-1
-	metadata, this value persists across restarts of the array.
-
-	This value can be written while assembling an array thus
-	providing an ongoing count for arrays with metadata managed by
-	userspace.
-
-      slot
-        This gives the role that the device has in the array.  It will
-	either be 'none' if the device is not active in the array
-        (i.e. is a spare or has failed) or an integer less than the
-	'raid_disks' number for the array indicating which position
-	it currently fills.  This can only be set while assembling an
-	array.  A device for which this is set is assumed to be working.
-
-      offset
-        This gives the location in the device (in sectors from the
-        start) where data from the array will be stored.  Any part of
-        the device before this offset is not touched, unless it is
-        used for storing metadata (Formats 1.1 and 1.2).
-
-      size
-        The amount of the device, after the offset, that can be used
-        for storage of data.  This will normally be the same as the
-	component_size.  This can be written while assembling an
-        array.  If a value less than the current component_size is
-        written, it will be rejected.
-
-      recovery_start
-        When the device is not 'in_sync', this records the number of
-	sectors from the start of the device which are known to be
-	correct.  This is normally zero, but during a recovery
-	operation it will steadily increase, and if the recovery is
-	interrupted, restoring this value can cause recovery to
-	avoid repeating the earlier blocks.  With v1.x metadata, this
-	value is saved and restored automatically.
-
-	This can be set whenever the device is not an active member of
-	the array, either before the array is activated, or before
-	the 'slot' is set.
-
-	Setting this to 'none' is equivalent to setting 'in_sync'.
-	Setting to any other value also clears the 'in_sync' flag.
-	
-      bad_blocks
-	This gives the list of all known bad blocks in the form of
-	start address and length (in sectors respectively). If output
-	is too big to fit in a page, it will be truncated. Writing
-	"sector length" to this file adds new acknowledged (i.e.
-	recorded to disk safely) bad blocks.
-
-      unacknowledged_bad_blocks
-	This gives the list of known-but-not-yet-saved-to-disk bad
-	blocks in the same form of 'bad_blocks'. If output is too big
-	to fit in a page, it will be truncated. Writing to this file
-	adds bad blocks without acknowledging them. This is largely
-	for testing.
-
-
-
-An active md device will also contain an entry for each active device
-in the array.  These are named
-
-    rdNN
-
-where 'NN' is the position in the array, starting from 0.
-So for a 3 drive array there will be rd0, rd1, rd2.
-These are symbolic links to the appropriate 'dev-XXX' entry.
-Thus, for example,
-       cat /sys/block/md*/md/rd*/state
-will show 'in_sync' on every line.
-
-
-
-Active md devices for levels that support data redundancy (1,4,5,6,10)
-also have
-
-   sync_action
-     a text file that can be used to monitor and control the rebuild
-     process.  It contains one word which can be one of:
-       resync        - redundancy is being recalculated after unclean
-                       shutdown or creation
-       recover       - a hot spare is being built to replace a
-                       failed/missing device
-       idle          - nothing is happening
-       check         - A full check of redundancy was requested and is
-                       happening.  This reads all blocks and checks
-                       them. A repair may also happen for some raid
-                       levels.
-       repair        - A full check and repair is happening.  This is
-                       similar to 'resync', but was requested by the
-                       user, and the write-intent bitmap is NOT used to
-		       optimise the process.
-
-      This file is writable, and each of the strings that could be
-      read are meaningful for writing.
-
-       'idle' will stop an active resync/recovery etc.  There is no
-           guarantee that another resync/recovery may not be automatically
-	   started again, though some event will be needed to trigger
-           this.
-	'resync' or 'recovery' can be used to restart the
-           corresponding operation if it was stopped with 'idle'.
-	'check' and 'repair' will start the appropriate process
-           providing the current state is 'idle'.
-
-      This file responds to select/poll.  Any important change in the value
-      triggers a poll event.  Sometimes the value will briefly be
-      "recover" if a recovery seems to be needed, but cannot be
-      achieved. In that case, the transition to "recover" isn't
-      notified, but the transition away is.
-
-   degraded
-      This contains a count of the number of devices by which the
-      arrays is degraded.  So an optimal array will show '0'.  A
-      single failed/missing drive will show '1', etc.
-      This file responds to select/poll, any increase or decrease
-      in the count of missing devices will trigger an event.
-
-   mismatch_count
-      When performing 'check' and 'repair', and possibly when
-      performing 'resync', md will count the number of errors that are
-      found.  The count in 'mismatch_cnt' is the number of sectors
-      that were re-written, or (for 'check') would have been
-      re-written.  As most raid levels work in units of pages rather
-      than sectors, this may be larger than the number of actual errors
-      by a factor of the number of sectors in a page.
-
-   bitmap_set_bits
-      If the array has a write-intent bitmap, then writing to this
-      attribute can set bits in the bitmap, indicating that a resync
-      would need to check the corresponding blocks. Either individual
-      numbers or start-end pairs can be written.  Multiple numbers
-      can be separated by a space.
-      Note that the numbers are 'bit' numbers, not 'block' numbers.
-      They should be scaled by the bitmap_chunksize.
-
-   sync_speed_min
-   sync_speed_max
-     This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
-     however they only apply to the particular array.
-     If no value has been written to these, or if the word 'system'
-     is written, then the system-wide value is used.  If a value,
-     in kibibytes-per-second is written, then it is used.
-     When the files are read, they show the currently active value
-     followed by "(local)" or "(system)" depending on whether it is
-     a locally set or system-wide value.
-
-   sync_completed
-     This shows the number of sectors that have been completed of
-     whatever the current sync_action is, followed by the number of
-     sectors in total that could need to be processed.  The two
-     numbers are separated by a '/'  thus effectively showing one
-     value, a fraction of the process that is complete.
-     A 'select' on this attribute will return when resync completes,
-     when it reaches the current sync_max (below) and possibly at
-     other times.
-
-   sync_speed
-     This shows the current actual speed, in K/sec, of the current
-     sync_action.  It is averaged over the last 30 seconds.
-
-   suspend_lo
-   suspend_hi
-     The two values, given as numbers of sectors, indicate a range
-     within the array where IO will be blocked.  This is currently
-     only supported for raid4/5/6.
-
-   sync_min
-   sync_max
-     The two values, given as numbers of sectors, indicate a range
-     within the array where 'check'/'repair' will operate. Must be
-     a multiple of chunk_size. When it reaches "sync_max" it will
-     pause, rather than complete.
-     You can use 'select' or 'poll' on "sync_completed" to wait for
-     that number to reach sync_max.  Then you can either increase
-     "sync_max", or can write 'idle' to "sync_action".
-
-     The value of 'max' for "sync_max" effectively disables the limit.
-     When a resync is active, the value can only ever be increased,
-     never decreased.
-     The value of '0' is the minimum for "sync_min".
-
-
-
-Each active md device may also have attributes specific to the
-personality module that manages it.
-These are specific to the implementation of the module and could
-change substantially if the implementation changes.
-
-These currently include
-
-  stripe_cache_size  (currently raid5 only)
-      number of entries in the stripe cache.  This is writable, but
-      there are upper and lower limits (32768, 17).  Default is 256.
-  strip_cache_active (currently raid5 only)
-      number of active entries in the stripe cache
-  preread_bypass_threshold (currently raid5 only)
-      number of times a stripe requiring preread will be bypassed by
-      a stripe that does not require preread.  For fairness defaults
-      to 1.  Setting this to 0 disables bypass accounting and
-      requires preread stripes to wait until all full-width stripe-
-      writes are complete.  Valid values are 0 to stripe_cache_size.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/dvb-drivers/intro.rst linux-libre-4.10-rc8-gnu/Documentation/media/dvb-drivers/intro.rst
--- linux-libre-4.9-gnu/Documentation/media/dvb-drivers/intro.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/dvb-drivers/intro.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
-Introdution
-===========
+Introduction
+============
 
 The main development site and GIT repository for these
 drivers is https://linuxtv.org.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/.gitignore linux-libre-4.10-rc8-gnu/Documentation/media/.gitignore
--- linux-libre-4.9-gnu/Documentation/media/.gitignore	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/.gitignore	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3 @@
+*.pdf
+# Files generated from *.dot
+uapi/v4l/pipeline.svg
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/index.rst linux-libre-4.10-rc8-gnu/Documentation/media/index.rst
--- linux-libre-4.9-gnu/Documentation/media/index.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,11 +1,6 @@
 Linux Media Subsystem Documentation
 ===================================
 
-.. Sphinx 1.4.x has a definition for DUrole that doesn't work on alltt blocks
-.. raw:: latex
-
-	\renewcommand*{\DUrole}[2]{ #2 }
-
 Contents:
 
 .. toctree::
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/intro.rst linux-libre-4.10-rc8-gnu/Documentation/media/intro.rst
--- linux-libre-4.9-gnu/Documentation/media/intro.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/intro.rst	2017-02-12 16:03:20.000000000 -0500
@@ -13,8 +13,8 @@ A typical media device hardware is shown
 
 .. _typical_media_device:
 
-.. figure::  media_api_files/typical_media_device.*
-    :alt:    typical_media_device.svg
+.. figure::  typical_media_device.*
+    :alt:    typical_media_device.pdf / typical_media_device.svg
     :align:  center
 
     Typical Media Device
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/kapi/cec-core.rst linux-libre-4.10-rc8-gnu/Documentation/media/kapi/cec-core.rst
--- linux-libre-4.9-gnu/Documentation/media/kapi/cec-core.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/kapi/cec-core.rst	2017-02-12 16:03:20.000000000 -0500
@@ -37,9 +37,8 @@ The struct cec_adapter represents the CE
 calling cec_allocate_adapter() and deleted by calling cec_delete_adapter():
 
 .. c:function::
-   struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
-	       void *priv, const char *name, u32 caps, u8 available_las,
-	       struct device *parent);
+   struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, void *priv,
+   const char *name, u32 caps, u8 available_las);
 
 .. c:function::
    void cec_delete_adapter(struct cec_adapter *adap);
@@ -66,20 +65,19 @@ available_las:
 	the number of simultaneous logical addresses that this
 	adapter can handle. Must be 1 <= available_las <= CEC_MAX_LOG_ADDRS.
 
-parent:
-	the parent device.
-
 
 To register the /dev/cecX device node and the remote control device (if
 CEC_CAP_RC is set) you call:
 
 .. c:function::
-	int cec_register_adapter(struct cec_adapter \*adap);
+	int cec_register_adapter(struct cec_adapter *adap, struct device *parent);
+
+where parent is the parent device.
 
 To unregister the devices call:
 
 .. c:function::
-	void cec_unregister_adapter(struct cec_adapter \*adap);
+	void cec_unregister_adapter(struct cec_adapter *adap);
 
 Note: if cec_register_adapter() fails, then call cec_delete_adapter() to
 clean up. But if cec_register_adapter() succeeded, then only call
@@ -106,13 +104,13 @@ your driver:
 		int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
 		int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
 				      u32 signal_free_time, struct cec_msg *msg);
-		void (\*adap_log_status)(struct cec_adapter *adap);
+		void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
 
 		/* High-level callbacks */
 		...
 	};
 
-The three low-level ops deal with various aspects of controlling the CEC adapter
+The five low-level ops deal with various aspects of controlling the CEC adapter
 hardware:
 
 
@@ -238,6 +236,18 @@ When a CEC message was received:
 
 Speaks for itself.
 
+Implementing the interrupt handler
+----------------------------------
+
+Typically the CEC hardware provides interrupts that signal when a transmit
+finished and whether it was successful or not, and it provides and interrupt
+when a CEC message was received.
+
+The CEC driver should always process the transmit interrupts first before
+handling the receive interrupt. The framework expects to see the cec_transmit_done
+call before the cec_received_msg call, otherwise it can get confused if the
+received message was in reply to the transmitted message.
+
 Implementing the High-Level CEC Adapter
 ---------------------------------------
 
@@ -247,11 +257,11 @@ CEC protocol driven. The following high-
 .. code-block:: none
 
 	struct cec_adap_ops {
-		/\* Low-level callbacks \*/
+		/* Low-level callbacks */
 		...
 
-		/\* High-level CEC message callback \*/
-		int (\*received)(struct cec_adapter \*adap, struct cec_msg \*msg);
+		/* High-level CEC message callback */
+		int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
 	};
 
 The received() callback allows the driver to optionally handle a newly
@@ -263,7 +273,7 @@ received CEC message
 If the driver wants to process a CEC message, then it can implement this
 callback. If it doesn't want to handle this message, then it should return
 -ENOMSG, otherwise the CEC framework assumes it processed this message and
-it will not no anything with it.
+it will not do anything with it.
 
 
 CEC framework functions
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/kapi/csi2.rst linux-libre-4.10-rc8-gnu/Documentation/media/kapi/csi2.rst
--- linux-libre-4.9-gnu/Documentation/media/kapi/csi2.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/kapi/csi2.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,61 @@
+MIPI CSI-2
+==========
+
+CSI-2 is a data bus intended for transferring images from cameras to
+the host SoC. It is defined by the `MIPI alliance`_.
+
+.. _`MIPI alliance`: http://www.mipi.org/
+
+Transmitter drivers
+-------------------
+
+CSI-2 transmitter, such as a sensor or a TV tuner, drivers need to
+provide the CSI-2 receiver with information on the CSI-2 bus
+configuration. These include the V4L2_CID_LINK_FREQ and
+V4L2_CID_PIXEL_RATE controls and
+(:c:type:`v4l2_subdev_video_ops`->s_stream() callback). These
+interface elements must be present on the sub-device represents the
+CSI-2 transmitter.
+
+The V4L2_CID_LINK_FREQ control is used to tell the receiver driver the
+frequency (and not the symbol rate) of the link. The
+V4L2_CID_PIXEL_RATE is may be used by the receiver to obtain the pixel
+rate the transmitter uses. The
+:c:type:`v4l2_subdev_video_ops`->s_stream() callback provides an
+ability to start and stop the stream.
+
+The value of the V4L2_CID_PIXEL_RATE is calculated as follows::
+
+	pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
+
+where
+
+.. list-table:: variables in pixel rate calculation
+   :header-rows: 1
+
+   * - variable or constant
+     - description
+   * - link_freq
+     - The value of the V4L2_CID_LINK_FREQ integer64 menu item.
+   * - nr_of_lanes
+     - Number of data lanes used on the CSI-2 link. This can
+       be obtained from the OF endpoint configuration.
+   * - 2
+     - Two bits are transferred per clock cycle per lane.
+   * - bits_per_sample
+     - Number of bits per sample.
+
+The transmitter drivers must configure the CSI-2 transmitter to *LP-11
+mode* whenever the transmitter is powered on but not active. Some
+transmitters do this automatically but some have to be explicitly
+programmed to do so.
+
+Receiver drivers
+----------------
+
+Before the receiver driver may enable the CSI-2 transmitter by using
+the :c:type:`v4l2_subdev_video_ops`->s_stream(), it must have powered
+the transmitter up by using the
+:c:type:`v4l2_subdev_core_ops`->s_power() callback. This may take
+place either indirectly by using :c:func:`v4l2_pipeline_pm_use` or
+directly.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/kapi/dtv-core.rst linux-libre-4.10-rc8-gnu/Documentation/media/kapi/dtv-core.rst
--- linux-libre-4.9-gnu/Documentation/media/kapi/dtv-core.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/kapi/dtv-core.rst	2017-02-12 16:03:20.000000000 -0500
@@ -8,14 +8,6 @@ Digital TV Common functions
 
 .. kernel-doc:: drivers/media/dvb-core/dvbdev.h
 
-
-
-.. kernel-doc:: drivers/media/dvb-core/dvb_math.h
-   :export: drivers/media/dvb-core/dvb_math.c
-
-.. kernel-doc:: drivers/media/dvb-core/dvbdev.h
-   :export: drivers/media/dvb-core/dvbdev.c
-
 Digital TV Ring buffer
 ----------------------
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/Makefile linux-libre-4.10-rc8-gnu/Documentation/media/Makefile
--- linux-libre-4.9-gnu/Documentation/media/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,23 +1,60 @@
-# Generate the *.h.rst files from uAPI headers
+# Rules to convert DOT and SVG to Sphinx images
+
+SRC_DIR=$(srctree)/Documentation/media
+
+DOTS = \
+	uapi/v4l/pipeline.dot \
+
+IMAGES = \
+	typical_media_device.svg \
+	uapi/dvb/dvbstb.svg \
+	uapi/v4l/bayer.svg \
+	uapi/v4l/constraints.svg \
+	uapi/v4l/crop.svg \
+	uapi/v4l/fieldseq_bt.svg \
+	uapi/v4l/fieldseq_tb.svg \
+	uapi/v4l/nv12mt.svg \
+	uapi/v4l/nv12mt_example.svg \
+	uapi/v4l/pipeline.svg \
+	uapi/v4l/selection.svg \
+	uapi/v4l/subdev-image-processing-full.svg \
+	uapi/v4l/subdev-image-processing-scaling-multi-source.svg \
+	uapi/v4l/subdev-image-processing-crop.svg \
+	uapi/v4l/vbi_525.svg \
+	uapi/v4l/vbi_625.svg \
+	uapi/v4l/vbi_hsync.svg \
+
+DOTTGT := $(patsubst %.dot,%.svg,$(DOTS))
+IMGDOT := $(patsubst %,$(SRC_DIR)/%,$(DOTTGT))
+
+IMGTGT := $(patsubst %.svg,%.pdf,$(IMAGES))
+IMGPDF := $(patsubst %,$(SRC_DIR)/%,$(IMGTGT))
+
+cmd = $(echo-cmd) $(cmd_$(1))
+
+quiet_cmd_genpdf = GENPDF  $2
+      cmd_genpdf = convert $2 $3
+
+quiet_cmd_gendot = DOT     $2
+      cmd_gendot = dot -Tsvg $2 > $3
+
+%.pdf: %.svg
+	@$(call cmd,genpdf,$<,$@)
+
+%.svg: %.dot
+	@$(call cmd,gendot,$<,$@)
+
+# Rules to convert a .h file to inline RST documentation
 
 PARSER = $(srctree)/Documentation/sphinx/parse-headers.pl
 UAPI = $(srctree)/include/uapi/linux
 KAPI = $(srctree)/include/linux
-SRC_DIR=$(srctree)/Documentation/media
 
 FILES = audio.h.rst ca.h.rst dmx.h.rst frontend.h.rst net.h.rst video.h.rst \
 	  videodev2.h.rst media.h.rst cec.h.rst lirc.h.rst
 
 TARGETS := $(addprefix $(BUILDDIR)/, $(FILES))
 
-.PHONY: all
-all: $(BUILDDIR) ${TARGETS}
-
-$(BUILDDIR):
-	$(Q)mkdir -p $@
-
-# Rule to convert a .h file to inline RST documentation
-
 gen_rst = \
 	echo ${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions; \
 	${PARSER} $< $@ $(SRC_DIR)/$(notdir $@).exceptions
@@ -51,11 +88,24 @@ $(BUILDDIR)/videodev2.h.rst: ${UAPI}/vid
 $(BUILDDIR)/media.h.rst: ${UAPI}/media.h ${PARSER} $(SRC_DIR)/media.h.rst.exceptions
 	@$($(quiet)gen_rst)
 
-$(BUILDDIR)/cec.h.rst: ${KAPI}/cec.h ${PARSER} $(SRC_DIR)/cec.h.rst.exceptions
+$(BUILDDIR)/cec.h.rst: ${UAPI}/cec.h ${PARSER} $(SRC_DIR)/cec.h.rst.exceptions
 	@$($(quiet)gen_rst)
 
 $(BUILDDIR)/lirc.h.rst: ${UAPI}/lirc.h ${PARSER} $(SRC_DIR)/lirc.h.rst.exceptions
 	@$($(quiet)gen_rst)
 
-cleandocs:
-	-rm ${TARGETS}
+# Media build rules
+
+.PHONY: all html epub xml latex
+
+all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
+html: all
+epub: all
+xml: all
+latex: $(IMGPDF) all
+
+clean:
+	-rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null
+
+$(BUILDDIR):
+	$(Q)mkdir -p $@
Binary files linux-libre-4.9-gnu/Documentation/media/media_api_files/typical_media_device.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/media_api_files/typical_media_device.pdf differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/media_api_files/typical_media_device.svg linux-libre-4.10-rc8-gnu/Documentation/media/media_api_files/typical_media_device.svg
--- linux-libre-4.9-gnu/Documentation/media/media_api_files/typical_media_device.svg	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/media_api_files/typical_media_device.svg	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg stroke-linejoin="round" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" clip-path="url(#a)" xml:space="preserve" fill-rule="evenodd" height="178.78mm" viewBox="0 0 24285.662 17877.829" width="251.99mm" version="1.2" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" preserveAspectRatio="xMidYMid" stroke-width="28.222"><defs><clipPath id="a" clipPathUnits="userSpaceOnUse"><rect y="0" x="0" width="28000" height="21000"/></clipPath></defs><g transform="matrix(1.004 0 0 1 -2185.6 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#fcf" d="m12231 4800c-516 0-1031 515-1031 1031v4124c0 516 515 1032 1031 1032h8538c516 0 1032-516 1032-1032v-4124c0-516-516-1031-1032-1031h-8538z"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#ffc" d="m3595 15607c-293 0-585 292-585 585v2340c0 293 292 586 585 586h3275c293 0 586-293 586-586v-2340c0-293-293-585-586-585h-3275z"/></g><g transform="translate(-2197.3 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#e6e6e6" d="m2663 2186c-461 0-922 461-922 922v11169c0 461 461 923 922 923h3692c461 0 922-462 922-923v-11169c0-461-461-922-922-922h-3692z"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4461 8602h-2260v-1086h4520v1086h-2260z"/><path fill="none" d="m4461 8602h-2260v-1086h4520v1086h-2260z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="8275" x="2579" class="TextPosition"><tspan fill="#000000">Audio decoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4461 11772h-2260v-1270h4520v1270h-2260z"/><path fill="none" d="m4461 11772h-2260v-1270h4520v1270h-2260z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="11353" x="2617" class="TextPosition"><tspan fill="#000000">Video decoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4453 10217h-2269v-1224h4537v1224h-2268z"/><path fill="none" d="m4453 10217h-2269v-1224h4537v1224h-2268z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="9821" x="2571" class="TextPosition"><tspan fill="#000000">Audio encoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.RectangleShape"><path fill="#cfc" d="m15711 12832h-3810v-1281h7620v1281h-3810z"/><path fill="none" d="m15711 12832h-3810v-1281h7620v1281h-3810z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="12407" x="12377" class="TextPosition"><tspan fill="#000000">Button Key/IR input logic</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2411.8)" class="com.sun.star.drawing.RectangleShape"><path fill="#cfe7f5" d="m14169 14572h-2268v-1412h4536v1412h-2268z"/><path fill="none" d="m14169 14572h-2268v-1412h4536v1412h-2268z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="14082" x="12882" class="TextPosition"><tspan fill="#000000">EEPROM</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#fc9" d="m5140 17662h-1563v-1715h3126v1715h-1563z"/><path fill="none" d="m5140 17662h-1563v-1715h3126v1715h-1563z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="17020" x="4276" class="TextPosition"><tspan fill="#000000">Sensor</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6719 8030 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z"/><path fill="none" d="m6719 8030 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6719 9612 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z"/><path fill="none" d="m6719 9612 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6721 11100 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m6721 11100 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2411.8)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 13854 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m9962 13854 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 12163 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m9962 12163 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 17158 670-353v176h2028v-176l671 353-671 354v-177h-2028v177l-670-354z"/><path fill="none" d="m9962 17158 670-353v176h2028v-176l671 353-671 354v-177h-2028v177l-670-354z" stroke="#3465af"/></g><g transform="matrix(0 .83339 -1.0005 0 30268 -5276.3)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m23229 12779 1009-978 1009 978h-505v2959h505l-1009 979-1009-979h504v-2959h-504z"/><path fill="none" d="m23229 12779 1009-978 1009 978h-505v2959h505l-1009 979-1009-979h504v-2959h-504z" stroke="#3465af"/></g><g transform="translate(-9973.6 -666.6)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="706px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="15832" x="24341" class="TextPosition" transform="matrix(0,-1,1,0,8509,40173)"><tspan fill="#000000">System Bus</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#cff" d="m13151 9262h-1250v-875h2499v875h-1249z"/><path fill="none" d="m13151 9262h-1250v-875h2499v875h-1249z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="9040" x="12215" class="TextPosition"><tspan fill="#000000">Demux</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9996 8765 373-357v178h1130v-178l374 357-374 358v-179h-1130v179l-373-358z"/><path fill="none" d="m9996 8765 373-357v178h1130v-178l374 357-374 358v-179h-1130v179l-373-358z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9996 7378 373-358v179h1130v-179l374 358-374 358v-179h-1130v179l-373-358z"/><path fill="none" d="m9996 7378 373-358v179h1130v-179l374 358-374 358v-179h-1130v179l-373-358z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#cff" d="m16322 7992h-4421v-1270h8841v1270h-4420z"/><path fill="none" d="m16322 7992h-4421v-1270h8841v1270h-4420z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="7573" x="12786" class="TextPosition"><tspan fill="#000000">Conditional Access Module</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m4445 13287h-2269v-1224h4537v1224h-2268z"/><path fill="none" d="m4445 13287h-2269v-1224h4537v1224h-2268z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="12891" x="2601" class="TextPosition"><tspan fill="#000000">Video encoder</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6721 12634 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m6721 12634 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m20791 7545 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m20791 7545 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2028 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="14478" x="1990" class="TextPosition"><tspan fill="#000000">Radio / Analog TV</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="700" class="TextParagraph"><tspan y="10724" x="14956" class="TextPosition"><tspan fill="#000000">Digital TV</tspan></tspan></tspan></text>
-</g><g transform="translate(-8970.5 -1395.8)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="494px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="19167" x="14724" class="TextPosition"><tspan fill="#000000">PS.: picture is not complete: other blocks may be present</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="18561" x="4199" class="TextPosition"><tspan fill="#000000">Webcam</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.RectangleShape"><path fill="#f90" d="m14552 16372h-2650v-1412h5299v1412h-2649z"/><path fill="none" d="m14552 16372h-2650v-1412h5299v1412h-2649z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="15882" x="12265" class="TextPosition"><tspan fill="#000000">Processing blocks</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2468.2)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9962 15654 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z"/><path fill="none" d="m9962 15654 385-353v176h1166v-176l386 353-386 354v-177h-1166v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6702 16954 397-353v176h1201v-176l398 353-398 354v-177h-1201v177l-397-354z"/><path fill="none" d="m6702 16954 397-353v176h1201v-176l398 353-398 354v-177h-1201v177l-397-354z" stroke="#3465af"/></g><g transform="translate(-2479.5 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="8792" x="22850" class="TextPosition"><tspan fill="#000000">Smartcard</tspan></tspan></tspan></text>
-</g><g transform="matrix(1.0048 0 0 1 -2207.4 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#fcf" d="m2766 2600c-333 0-666 333-666 666v2668c0 333 333 666 666 666h18368c333 0 667-333 667-666v-2668c0-333-334-666-667-666h-18368z"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#ff8080" d="m5121 5155h-1614v-1816h3227v1816h-1613z"/><path fill="none" d="m5121 5155h-1614v-1816h3227v1816h-1613z" stroke="#3465af"/><text font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextShape"><tspan class="TextParagraph"><tspan y="4111" x="4374" class="TextPosition"><tspan fill="#000000">Tuner</tspan></tspan></tspan><tspan class="TextParagraph"><tspan y="4814" x="4151" class="TextPosition"><tspan fill="#000000">FM/TV</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#ff8080" d="m2902 3702c0 111 40 202 88 202h530c48 0 89-91 89-202 0-110-41-202-89-202h-530c-48 0-88 92-88 202z"/><path fill="none" d="m2902 3702c0 111 40 202 88 202h530c48 0 89-91 89-202 0-110-41-202-89-202h-530c-48 0-88 92-88 202z" stroke="#3465af"/><path fill="#ffb3b3" d="m2902 3702c0 111 40 202 88 202s88-91 88-202c0-110-40-202-88-202s-88 92-88 202z"/><path fill="none" d="m2902 3702c0 111 40 202 88 202s88-91 88-202c0-110-40-202-88-202s-88 92-88 202z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#ff8080" d="m2903 4267c0 110 40 202 88 202h530c48 0 89-92 89-202s-41-203-89-203h-530c-48 0-88 93-88 203z"/><path fill="none" d="m2903 4267c0 110 40 202 88 202h530c48 0 89-92 89-202s-41-203-89-203h-530c-48 0-88 93-88 203z" stroke="#3465af"/><path fill="#ffb3b3" d="m2903 4267c0 110 40 202 88 202s88-92 88-202-40-203-88-203-88 93-88 203z"/><path fill="none" d="m2903 4267c0 110 40 202 88 202s88-92 88-202-40-203-88-203-88 93-88 203z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m6719 4196 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z"/><path fill="none" d="m6719 4196 385-353v176h1167v-176l386 353-386 354v-177h-1167v177l-385-354z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9979 4150 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z"/><path fill="none" d="m9979 4150 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z" stroke="#3465af"/></g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.RectangleShape"><path fill="#cff" d="m16500 6189h-4500v-1389h9e3v1389h-4500z"/><path fill="none" d="m16500 6189h-4500v-1389h9e3v1389h-4500z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="5710" x="12051" class="TextPosition"><tspan fill="#000000">Satellite Equipment Control (SEC)</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#cff" d="m13400 4600h-1400v-1e3h2800v1e3h-1400z"/><path fill="none" d="m13400 4600h-1400v-1e3h2800v1e3h-1400z" stroke="#3465af"/><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="4316" x="12465" class="TextPosition"><tspan fill="#000000">Demod</tspan></tspan></tspan></text>
-</g><g transform="translate(-2140.9 -2186)" class="com.sun.star.drawing.CustomShape"><path fill="#729fcf" d="m9979 5451 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z"/><path fill="none" d="m9979 5451 402-368v184h1217v-184l403 368-403 369v-185h-1217v185l-402-369z" stroke="#3465af"/></g><path fill="#ff9" d="m7855.1 9099v7302h-1270v-14605h1270v7303z"/><path fill="none" d="m7855.1 9099v7302h-1270v-14605h1270v7303z" stroke="#3465af"/><text y="-6640.4663" x="-20770.572" transform="rotate(-90)" class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="7409.5396" x="-11193.634" class="TextPosition" transform="matrix(0,-1,1,0,-4473,23627)"><tspan fill="#000000">I2C Bus (control bus)</tspan></tspan></tspan></text>
-<g transform="translate(-2197.3 -2186)" class="com.sun.star.drawing.TextShape"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="3278" x="9391" class="TextPosition"><tspan fill="#000000">Digital TV Frontend</tspan></tspan></tspan></text>
-</g><g transform="matrix(1.015 0 0 .99994 -2233.3 -2185.7)" class="com.sun.star.drawing.CustomShape"><g stroke="#3465af" fill="none"><path d="m3e3 2800c-18 0-35 1-53 3"/><path d="m2915 2808c-17 3-35 7-52 12"/><path d="m2832 2830c-16 6-33 12-49 20"/><path d="m2754 2864c-15 8-31 17-46 27"/><path d="m2681 2909c-14 10-28 21-42 32"/><path d="m2614 2962c-13 12-26 24-38 37"/><path d="m2554 3023c-11 13-22 27-33 41"/><path d="m2502 3091c-10 14-19 29-28 45"/><path d="m2459 3164c-8 16-15 32-22 49"/><path d="m2426 3243c-5 17-10 34-14 51"/><path d="m2406 3326c-3 18-5 35-6 53"/><path d="m2400 3411v53"/><path d="m2400 3497v53"/><path d="m2400 3582v53"/><path d="m2400 3668v53"/><path d="m2400 3753v53"/><path d="m2400 3839v53"/><path d="m2400 3924v53"/><path d="m2400 4009v54"/><path d="m2400 4095v53"/><path d="m2400 4180v53"/><path d="m2400 4266v53"/><path d="m2400 4351v53"/><path d="m2400 4437v53"/><path d="m2400 4522v53"/><path d="m2400 4607v54"/><path d="m2400 4693v53"/><path d="m2400 4778v53"/><path d="m2400 4864v53"/><path d="m2400 4949v53"/><path d="m2400 5035v53"/><path d="m2400 5120v53"/><path d="m2400 5205v54"/><path d="m2400 5291v53"/><path d="m2400 5376v53"/><path d="m2400 5462v53"/><path d="m2400 5547v53"/><path d="m2400 5633v53"/><path d="m2400 5718v53"/><path d="m2400 5803c0 18 1 36 3 53"/><path d="m2408 5888c4 18 8 35 13 52"/><path d="m2431 5971c6 16 13 33 20 49"/><path d="m2466 6049c8 15 17 31 27 46"/><path d="m2511 6122c10 14 21 28 32 42"/><path d="m2564 6188c12 13 25 26 38 38"/><path d="m2626 6248c13 11 27 23 41 33"/><path d="m2694 6300c14 10 29 19 45 27"/><path d="m2768 6343c15 7 32 15 48 21"/><path d="m2847 6375c17 5 34 10 51 14"/><path d="m2930 6395c17 2 35 4 53 5"/><path d="m3015 6400h53"/><path d="m3100 6400h53"/><path d="m3186 6400h53"/><path d="m3271 6400h53"/><path d="m3357 6400h53"/><path d="m3442 6400h53"/><path d="m3527 6400h54"/><path d="m3613 6400h53"/><path d="m3698 6400h53"/><path d="m3784 6400h53"/><path d="m3869 6400h53"/><path d="m3955 6400h53"/><path d="m4040 6400h53"/><path d="m4125 6400h54"/><path d="m4211 6400h53"/><path d="m4296 6400h53"/><path d="m4382 6400h53"/><path d="m4467 6400h53"/><path d="m4553 6400h53"/><path d="m4638 6400h53"/><path d="m4723 6400h54"/><path d="m4809 6400h53"/><path d="m4894 6400h53"/><path d="m4980 6400h53"/><path d="m5065 6400h53"/><path d="m5151 6400h53"/><path d="m5236 6400h53"/><path d="m5322 6400h53"/><path d="m5407 6400h53"/><path d="m5492 6400h53"/><path d="m5578 6400h53"/><path d="m5663 6400h53"/><path d="m5749 6400h53"/><path d="m5834 6400h53"/><path d="m5920 6400h53"/><path d="m6005 6400h53"/><path d="m6090 6400h53"/><path d="m6176 6400h53"/><path d="m6261 6400h53"/><path d="m6347 6400h53"/><path d="m6432 6400h53"/><path d="m6518 6400h53"/><path d="m6603 6400h53"/><path d="m6688 6400h54"/><path d="m6774 6400h53"/><path d="m6859 6400h53"/><path d="m6945 6400h53"/><path d="m7030 6400h53"/><path d="m7116 6400h53"/><path d="m7201 6400h53"/><path d="m7286 6400h54"/><path d="m7372 6400h53"/><path d="m7457 6400h53"/><path d="m7543 6400h53"/><path d="m7628 6400h53"/><path d="m7714 6400h53"/><path d="m7799 6400h53"/><path d="m7884 6400h54"/><path d="m7970 6400h53"/><path d="m8055 6400h53"/><path d="m8141 6400h53"/><path d="m8226 6400h53"/><path d="m8312 6400h53"/><path d="m8397 6400h53"/><path d="m8482 6400h54"/><path d="m8568 6400h53"/><path d="m8653 6400h53"/><path d="m8739 6400h53"/><path d="m8824 6400h53"/><path d="m8910 6400h53"/><path d="m8995 6400h53"/><path d="m9081 6400h53"/><path d="m9166 6400h53"/><path d="m9251 6400h53"/><path d="m9337 6400h53"/><path d="m9422 6400h53"/><path d="m9508 6400h53"/><path d="m9593 6400h53"/><path d="m9679 6400h53"/><path d="m9764 6400h53"/><path d="m9849 6400h53"/><path d="m9935 6400h53"/><path d="m10020 6400h53"/><path d="m10106 6400h53"/><path d="m10191 6400h53"/><path d="m10277 6400h53"/><path d="m10362 6400h53"/><path d="m10447 6400h53"/><path d="m10533 6400h53"/><path d="m10618 6400h53"/><path d="m10704 6400h53"/><path d="m10789 6400h53"/><path d="m10875 6400h53"/><path d="m10960 6400h53"/><path d="m11045 6400h54"/><path d="m11131 6400h53"/><path d="m11216 6400h53"/><path d="m11302 6400h53"/><path d="m11387 6400h53"/><path d="m11473 6400h53"/><path d="m11558 6400h53"/><path d="m11643 6400h54"/><path d="m11729 6400h53"/><path d="m11814 6400h53"/><path d="m11900 6400h53"/><path d="m11985 6400h53"/><path d="m12071 6400h53"/><path d="m12156 6400h53"/><path d="m12241 6400h54"/><path d="m12327 6400h53"/><path d="m12412 6400h53"/><path d="m12498 6400h53"/><path d="m12583 6400h53"/><path d="m12669 6400h53"/><path d="m12754 6400h53"/><path d="m12839 6400h54"/><path d="m12925 6400h53"/><path d="m13010 6400h53"/><path d="m13096 6400h53"/><path d="m13181 6400h53"/><path d="m13267 6400h53"/><path d="m13352 6400h53"/><path d="m13438 6400h53"/><path d="m13523 6400h53"/><path d="m13608 6400h53"/><path d="m13694 6400h53"/><path d="m13779 6400h53"/><path d="m13865 6400h53"/><path d="m13950 6400h53"/><path d="m14036 6400h53"/><path d="m14121 6400h53"/><path d="m14206 6400h53"/><path d="m14292 6400h53"/><path d="m14377 6400h53"/><path d="m14463 6400h53"/><path d="m14548 6400h53"/><path d="m14634 6400h53"/><path d="m14719 6400h53"/><path d="m14804 6400h54"/><path d="m14890 6400h53"/><path d="m14975 6400h53"/><path d="m15061 6400h53"/><path d="m15146 6400h53"/><path d="m15232 6400h53"/><path d="m15317 6400h53"/><path d="m15402 6400h54"/><path d="m15488 6400h53"/><path d="m15573 6400h53"/><path d="m15659 6400h53"/><path d="m15744 6400h53"/><path d="m15830 6400h53"/><path d="m15915 6400h53"/><path d="m16000 6400h54"/><path d="m16086 6400h53"/><path d="m16171 6400h53"/><path d="m16257 6400h53"/><path d="m16342 6400h53"/><path d="m16428 6400h53"/><path d="m16513 6400h53"/><path d="m16598 6400h54"/><path d="m16684 6400h53"/><path d="m16769 6400h53"/><path d="m16855 6400h53"/><path d="m16940 6400h53"/><path d="m17026 6400h53"/><path d="m17111 6400h53"/><path d="m17196 6400h54"/><path d="m17282 6400h53"/><path d="m17367 6400h53"/><path d="m17453 6400h53"/><path d="m17538 6400h53"/><path d="m17624 6400h53"/><path d="m17709 6400h53"/><path d="m17795 6400h53"/><path d="m17880 6400h53"/><path d="m17965 6400h53"/><path d="m18051 6400h53"/><path d="m18136 6400h53"/><path d="m18222 6400h53"/><path d="m18307 6400h53"/><path d="m18393 6400h53"/><path d="m18478 6400h53"/><path d="m18563 6400h53"/><path d="m18649 6400h53"/><path d="m18734 6400h53"/><path d="m18820 6400h53"/><path d="m18905 6400h53"/><path d="m18991 6400h53"/><path d="m19076 6400h53"/><path d="m19161 6400h54"/><path d="m19247 6400h53"/><path d="m19332 6400h53"/><path d="m19418 6400h53"/><path d="m19503 6400h53"/><path d="m19589 6400h53"/><path d="m19674 6400h53"/><path d="m19759 6400h54"/><path d="m19845 6400h53"/><path d="m19930 6400h53"/><path d="m20016 6400h53"/><path d="m20101 6400h53"/><path d="m20187 6400h53"/><path d="m20272 6400h53"/><path d="m20357 6400h54"/><path d="m20443 6400h53"/><path d="m20528 6400h53"/><path d="m20614 6400c17-1 35-2 53-5"/><path d="m20699 6390c17-4 34-9 51-14"/><path d="m20781 6365c16-6 32-13 48-21"/><path d="m20858 6329c15-8 31-17 45-27"/><path d="m20930 6283c14-10 28-21 42-32"/><path d="m20996 6229c13-12 25-25 37-38"/><path d="m21055 6167c11-14 22-28 33-42"/><path d="m21106 6098c10-15 19-30 27-45"/><path d="m21148 6024c7-16 14-33 20-49"/><path d="m21179 5944c5-17 9-34 13-51"/><path d="m21197 5861c2-18 4-35 4-53"/><path d="m21201 5776v-54"/><path d="m21201 5690v-53"/><path d="m21201 5605v-53"/><path d="m21201 5519v-53"/><path d="m21201 5434v-53"/><path d="m21201 5348v-53"/><path d="m21201 5263v-53"/><path d="m21201 5178v-54"/><path d="m21201 5092v-53"/><path d="m21201 5007v-53"/><path d="m21201 4921v-53"/><path d="m21201 4836v-53"/><path d="m21201 4750v-53"/><path d="m21201 4665v-53"/><path d="m21201 4579v-53"/><path d="m21201 4494v-53"/><path d="m21201 4409v-53"/><path d="m21201 4323v-53"/><path d="m21201 4238v-53"/><path d="m21201 4152v-53"/><path d="m21201 4067v-53"/><path d="m21201 3981v-53"/><path d="m21201 3896v-53"/><path d="m21201 3811v-53"/><path d="m21201 3725v-53"/><path d="m21201 3640v-53"/><path d="m21201 3554v-53"/><path d="m21201 3469v-53"/><path d="m21201 3383c-1-17-3-35-5-52"/><path d="m21190 3299c-4-17-8-35-14-51"/><path d="m21165 3217c-6-16-13-33-21-49"/><path d="m21129 3140c-9-16-18-31-28-46"/><path d="m21082 3068c-10-14-21-28-33-42"/><path d="m21027 3002c-12-13-24-25-37-37"/><path d="m20965 2944c-14-12-28-22-42-33"/><path d="m20896 2893c-15-9-30-18-46-27"/><path d="m20821 2852c-16-8-32-14-49-20"/><path d="m20741 2821c-17-5-34-9-51-12"/><path d="m20658 2804c-18-3-35-4-53-4"/><path d="m20573 2800h-53"/><path d="m20487 2800h-53"/><path d="m20402 2800h-53"/><path d="m20316 2800h-53"/><path d="m20231 2800h-53"/><path d="m20146 2800h-54"/><path d="m20060 2800h-53"/><path d="m19975 2800h-53"/><path d="m19889 2800h-53"/><path d="m19804 2800h-53"/><path d="m19718 2800h-53"/><path d="m19633 2800h-53"/><path d="m19548 2800h-54"/><path d="m19462 2800h-53"/><path d="m19377 2800h-53"/><path d="m19291 2800h-53"/><path d="m19206 2800h-53"/><path d="m19120 2800h-53"/><path d="m19035 2800h-53"/><path d="m18950 2800h-54"/><path d="m18864 2800h-53"/><path d="m18779 2800h-53"/><path d="m18693 2800h-53"/><path d="m18608 2800h-53"/><path d="m18522 2800h-53"/><path d="m18437 2800h-53"/><path d="m18352 2800h-54"/><path d="m18266 2800h-53"/><path d="m18181 2800h-53"/><path d="m18095 2800h-53"/><path d="m18010 2800h-53"/><path d="m17924 2800h-53"/><path d="m17839 2800h-53"/><path d="m17753 2800h-53"/><path d="m17668 2800h-53"/><path d="m17583 2800h-53"/><path d="m17497 2800h-53"/><path d="m17412 2800h-53"/><path d="m17326 2800h-53"/><path d="m17241 2800h-53"/><path d="m17155 2800h-53"/><path d="m17070 2800h-53"/><path d="m16985 2800h-53"/><path d="m16899 2800h-53"/><path d="m16814 2800h-53"/><path d="m16728 2800h-53"/><path d="m16643 2800h-53"/><path d="m16557 2800h-53"/><path d="m16472 2800h-53"/><path d="m16387 2800h-54"/><path d="m16301 2800h-53"/><path d="m16216 2800h-53"/><path d="m16130 2800h-53"/><path d="m16045 2800h-53"/><path d="m15959 2800h-53"/><path d="m15874 2800h-53"/><path d="m15789 2800h-54"/><path d="m15703 2800h-53"/><path d="m15618 2800h-53"/><path d="m15532 2800h-53"/><path d="m15447 2800h-53"/><path d="m15361 2800h-53"/><path d="m15276 2800h-53"/><path d="m15191 2800h-54"/><path d="m15105 2800h-53"/><path d="m15020 2800h-53"/><path d="m14934 2800h-53"/><path d="m14849 2800h-53"/><path d="m14763 2800h-53"/><path d="m14678 2800h-53"/><path d="m14593 2800h-54"/><path d="m14507 2800h-53"/><path d="m14422 2800h-53"/><path d="m14336 2800h-53"/><path d="m14251 2800h-53"/><path d="m14165 2800h-53"/><path d="m14080 2800h-53"/><path d="m13994 2800h-53"/><path d="m13909 2800h-53"/><path d="m13824 2800h-53"/><path d="m13738 2800h-53"/><path d="m13653 2800h-53"/><path d="m13567 2800h-53"/><path d="m13482 2800h-53"/><path d="m13396 2800h-53"/><path d="m13311 2800h-53"/><path d="m13226 2800h-53"/><path d="m13140 2800h-53"/><path d="m13055 2800h-53"/><path d="m12969 2800h-53"/><path d="m12884 2800h-53"/><path d="m12798 2800h-53"/><path d="m12713 2800h-53"/><path d="m12628 2800h-53"/><path d="m12542 2800h-53"/><path d="m12457 2800h-53"/><path d="m12371 2800h-53"/><path d="m12286 2800h-53"/><path d="m12200 2800h-53"/><path d="m12115 2800h-53"/><path d="m12030 2800h-54"/><path d="m11944 2800h-53"/><path d="m11859 2800h-53"/><path d="m11773 2800h-53"/><path d="m11688 2800h-53"/><path d="m11602 2800h-53"/><path d="m11517 2800h-53"/><path d="m11432 2800h-54"/><path d="m11346 2800h-53"/><path d="m11261 2800h-53"/><path d="m11175 2800h-53"/><path d="m11090 2800h-53"/><path d="m11004 2800h-53"/><path d="m10919 2800h-53"/><path d="m10834 2800h-54"/><path d="m10748 2800h-53"/><path d="m10663 2800h-53"/><path d="m10577 2800h-53"/><path d="m10492 2800h-53"/><path d="m10406 2800h-53"/><path d="m10321 2800h-53"/><path d="m10236 2800h-54"/><path d="m10150 2800h-53"/><path d="m10065 2800h-53"/><path d="m9979 2800h-53"/><path d="m9894 2800h-53"/><path d="m9808 2800h-53"/><path d="m9723 2800h-53"/><path d="m9637 2800h-53"/><path d="m9552 2800h-53"/><path d="m9467 2800h-53"/><path d="m9381 2800h-53"/><path d="m9296 2800h-53"/><path d="m9210 2800h-53"/><path d="m9125 2800h-53"/><path d="m9039 2800h-53"/><path d="m8954 2800h-53"/><path d="m8869 2800h-53"/><path d="m8783 2800h-53"/><path d="m8698 2800h-53"/><path d="m8612 2800h-53"/><path d="m8527 2800h-53"/><path d="m8441 2800h-53"/><path d="m8356 2800h-53"/><path d="m8271 2800h-54"/><path d="m8185 2800h-53"/><path d="m8100 2800h-53"/><path d="m8014 2800h-53"/><path d="m7929 2800h-53"/><path d="m7843 2800h-53"/><path d="m7758 2800h-53"/><path d="m7673 2800h-54"/><path d="m7587 2800h-53"/><path d="m7502 2800h-53"/><path d="m7416 2800h-53"/><path d="m7331 2800h-53"/><path d="m7245 2800h-53"/><path d="m7160 2800h-53"/><path d="m7075 2800h-54"/><path d="m6989 2800h-53"/><path d="m6904 2800h-53"/><path d="m6818 2800h-53"/><path d="m6733 2800h-53"/><path d="m6647 2800h-53"/><path d="m6562 2800h-53"/><path d="m6477 2800h-54"/><path d="m6391 2800h-53"/><path d="m6306 2800h-53"/><path d="m6220 2800h-53"/><path d="m6135 2800h-53"/><path d="m6049 2800h-53"/><path d="m5964 2800h-53"/><path d="m5879 2800h-54"/><path d="m5793 2800h-53"/><path d="m5708 2800h-53"/><path d="m5622 2800h-53"/><path d="m5537 2800h-53"/><path d="m5451 2800h-53"/><path d="m5366 2800h-53"/><path d="m5280 2800h-53"/><path d="m5195 2800h-53"/><path d="m5110 2800h-53"/><path d="m5024 2800h-53"/><path d="m4939 2800h-53"/><path d="m4853 2800h-53"/><path d="m4768 2800h-53"/><path d="m4682 2800h-53"/><path d="m4597 2800h-53"/><path d="m4512 2800h-53"/><path d="m4426 2800h-53"/><path d="m4341 2800h-53"/><path d="m4255 2800h-53"/><path d="m4170 2800h-53"/><path d="m4084 2800h-53"/><path d="m3999 2800h-53"/><path d="m3914 2800h-54"/><path d="m3828 2800h-53"/><path d="m3743 2800h-53"/><path d="m3657 2800h-53"/><path d="m3572 2800h-53"/><path d="m3486 2800h-53"/><path d="m3401 2800h-53"/><path d="m3316 2800h-54"/><path d="m3230 2800h-53"/><path d="m3145 2800h-53"/><path d="m3059 2800h-53"/></g></g><g transform="translate(-2197.3 -2186)"><rect height="1100.7" width="1213.6" y="6917.1" x="23255" fill="#f3e777"/><path fill="#ca4677" d="m22802 7700.4v-405.46l150.7-169.16c82.886-93.039 170.53-186.62 194.77-207.96l44.069-38.798 783.23-0.086 783.23-0.086v613.5 613.5h-978-978v-405.46zm1027.7 136.98v-78.372l-169.91 4.925-169.91 4.9249-5.09 45.854c-8.249 74.303 46.711 101.04 207.69 101.04h137.21v-78.372zm235.86-262.94 4.495-341.31 207.2-8.6408 207.2-8.6408 5.144-46.443c9.596-86.615-41.863-102.05-322.02-96.607l-246.71 4.7956-4.438 419.08-4.439 419.08h74.537 74.538l4.494-341.31zm391.3 313.72c26.41-19.286 36.255-41.399 32.697-73.447l-5.09-45.854h-174.05-174.05l-5.38 48.984c-9.97 90.771 0.993 97.91 150.36 97.91 99.305 0 148.27-7.6982 175.52-27.594zm-627.16-274.84v-77.768h-174.05-174.05v66.246c0 36.436 4.973 71.431 11.051 77.768 6.078 6.3366 84.401 11.521 174.05 11.521h163v-77.768zm659.89-4.9154 5.125-74.042-179.18 4.9155-179.18 4.9155-5.38 48.984c-10.473 95.348-2.259 99.57 183.28 94.197l170.2-4.9284 5.125-74.042zm-659.89-237.63v-78.372l-169.91 4.925-169.91 4.925-5.097 73.447-5.097 73.447h175 175v-78.372zm659.86 4.925-5.097-73.447h-174.05-174.05l-5.38 48.984c-10.289 93.673-2.146 97.91 188.15 97.91h175.52l-5.097-73.447zm-659.86-228.98v-77.768h-137.21c-97.358 0-147.91 7.8138-174.05 26.902-34.952 25.523-49.645 92.242-25.79 117.11 6.078 6.3366 84.401 11.521 174.05 11.521h163v-77.768z"/></g><g transform="matrix(.84874 0 0 .76147 2408.1 3615.3)"><rect height="3076.2" width="2734.3" y="13264" x="19249" fill="#6076b3"/><g stroke-linejoin="round" fill-rule="evenodd" stroke-width="28.222" fill="#e0ee2c"><rect y="13369" width="356.65" x="18937" height="180.95"/><rect y="13708" width="356.65" x="18937" height="180.95"/><rect y="14048" width="356.65" x="18937" height="180.95"/><rect y="14387" width="356.65" x="18937" height="180.95"/><rect y="14726" width="356.65" x="18937" height="180.95"/><rect y="15066" width="356.65" x="18937" height="180.95"/><rect y="15405" width="356.65" x="18937" height="180.95"/><rect y="15744" width="356.65" x="18937" height="180.95"/><rect y="16083" width="356.65" x="18937" height="180.95"/><rect y="13324" width="356.65" x="21939" height="180.95"/><rect y="13663" width="356.65" x="21939" height="180.95"/><rect y="14002" width="356.65" x="21939" height="180.95"/><rect y="14342" width="356.65" x="21939" height="180.95"/><rect y="14681" width="356.65" x="21939" height="180.95"/><rect y="15020" width="356.65" x="21939" height="180.95"/><rect y="15360" width="356.65" x="21939" height="180.95"/><rect y="15699" width="356.65" x="21939" height="180.95"/><rect y="16038" width="356.65" x="21939" height="180.95"/></g><g stroke-linejoin="round" fill-rule="evenodd" transform="matrix(.98702 0 0 .90336 -2675 7020.8)" class="com.sun.star.drawing.TextShape" stroke-width="28.222"><text class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"/></text>
-<text style="word-spacing:0px;letter-spacing:0px" xml:space="preserve" font-size="1128.9px" y="9042.0264" x="22439.668" font-family="Sans" line-height="125%" fill="#000000"><tspan y="9042.0264" x="22439.668">CPU</tspan></text>
-</g></g><g stroke-linejoin="round" fill-rule="evenodd" transform="translate(-11752 543.6)" class="com.sun.star.drawing.TextShape" stroke-width="28.222"><text class="TextShape"><tspan font-size="706px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="15832" x="24341" class="TextPosition" transform="matrix(0,-1,1,0,8509,40173)"><tspan fill="#000000">PCI, USB, SPI, I2C, ...</tspan></tspan></tspan></text>
-</g><g stroke-linejoin="round" fill-rule="evenodd" transform="translate(-655.31 963.83)" class="com.sun.star.drawing.RectangleShape" stroke-width="28.222"><g transform="matrix(.49166 0 0 1.0059 6045.6 -82.24)"><path fill="#cfe7f5" d="m14169 14572h-2268v-1412h4536v1412h-2268z"/><path fill="none" d="m14169 14572h-2268v-1412h4536v1412h-2268z" stroke="#3465af"/></g><text y="-395.11282" x="-790.22229" class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="13686.9" x="12091.779" class="TextPosition"><tspan fill="#000000">Bridge</tspan></tspan></tspan></text>
-<text y="338.66486" x="-846.66675" class="TextShape"><tspan font-size="635px" font-family="&apos;Times New Roman&apos;, serif" font-weight="400" class="TextParagraph"><tspan y="14420.677" x="12035.335" class="TextPosition"><tspan fill="#000000"> DMA</tspan></tspan></tspan></text>
-</g></svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/media_kapi.rst linux-libre-4.10-rc8-gnu/Documentation/media/media_kapi.rst
--- linux-libre-4.9-gnu/Documentation/media/media_kapi.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/media_kapi.rst	2017-02-12 16:03:20.000000000 -0500
@@ -33,3 +33,4 @@ For more details see the file COPYING in
     kapi/rc-core
     kapi/mc-core
     kapi/cec-core
+    kapi/csi2
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/typical_media_device.svg linux-libre-4.10-rc8-gnu/Documentation/media/typical_media_device.svg
--- linux-libre-4.9-gnu/Documentation/media/typical_media_device.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/typical_media_device.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2948 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   clip-path="url(#a)"
+   xml:space="preserve"
+   height="179mm"
+   viewBox="0 0 22648.239 17899.829"
+   width="235mm"
+   version="1.2"
+   preserveAspectRatio="xMidYMid"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="typical_media_device.svg"
+   style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+     id="metadata1533"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview1531"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="1.2707744"
+     inkscape:cx="410.32614"
+     inkscape:cy="316.736"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" /><defs
+     id="defs4"><clipPath
+       id="a"
+       clipPathUnits="userSpaceOnUse"><rect
+         y="0"
+         x="0"
+         width="28000"
+         height="21000"
+         id="rect7" /></clipPath></defs><path
+     style="fill:#ffccff"
+     inkscape:connector-curvature="0"
+     id="path11"
+     d="m 10145.77,2636.013 c -518.0641,0 -1035.1241,515 -1035.1241,1031 l 0,4124 c 0,516 517.06,1032 1035.1241,1032 l 8572.152,0 c 518.064,0 1036.128,-516 1036.128,-1032 l 0,-4124 c 0,-516 -518.064,-1031 -1036.128,-1031 l -8572.152,0 z" /><path
+     style="fill:#ffffcc"
+     inkscape:connector-curvature="0"
+     id="path15"
+     d="m 1505.5459,13443.013 c -293,0 -585,292 -585,585 l 0,2340 c 0,293 292,586 585,586 l 3275,0 c 293,0 586,-293 586,-586 l 0,-2340 c 0,-293 -293,-585 -586,-585 l -3275,0 z" /><path
+     style="fill:#e6e6e6"
+     inkscape:connector-curvature="0"
+     id="path19"
+     d="m 517.1459,22.013 c -461,0 -922,461 -922,922 l 0,11169 c 0,461 461,923 922,923 l 3692,0 c 461,0 922,-462 922,-923 l 0,-11169 c 0,-461 -461,-922 -922,-922 l -3692,0 z" /><path
+     style="fill:#ff8080"
+     inkscape:connector-curvature="0"
+     id="path23"
+     d="m 2371.5459,6438.013 -2260,0 0,-1086 4520,0 0,1086 -2260,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path25"
+     d="m 2371.5459,6438.013 -2260,0 0,-1086 4520,0 0,1086 -2260,0 z" /><text
+     id="text27"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan29"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan31"
+         class="TextPosition"
+         x="489.5459"
+         y="6111.0132"><tspan
+           style="fill:#000000"
+           id="tspan33">Audio decoder</tspan></tspan></tspan></text>
+<path
+     style="fill:#ff8080"
+     inkscape:connector-curvature="0"
+     id="path37"
+     d="m 2371.5459,9608.013 -2260,0 0,-1270 4520,0 0,1270 -2260,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path39"
+     d="m 2371.5459,9608.013 -2260,0 0,-1270 4520,0 0,1270 -2260,0 z" /><text
+     id="text41"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan43"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan45"
+         class="TextPosition"
+         x="527.5459"
+         y="9189.0127"><tspan
+           style="fill:#000000"
+           id="tspan47">Video decoder</tspan></tspan></tspan></text>
+<path
+     style="fill:#ff8080"
+     inkscape:connector-curvature="0"
+     id="path51"
+     d="m 2363.5459,8053.013 -2269,0 0,-1224 4537,0 0,1224 -2268,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path53"
+     d="m 2363.5459,8053.013 -2269,0 0,-1224 4537,0 0,1224 -2268,0 z" /><text
+     id="text55"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan57"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan59"
+         class="TextPosition"
+         x="481.5459"
+         y="7657.0132"><tspan
+           style="fill:#000000"
+           id="tspan61">Audio encoder</tspan></tspan></tspan></text>
+<path
+     style="fill:#ccffcc"
+     inkscape:connector-curvature="0"
+     id="path65"
+     d="m 13621.546,10385.813 -3810.0001,0 0,-1281 7620.0001,0 0,1281 -3810,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path67"
+     d="m 13621.546,10385.813 -3810.0001,0 0,-1281 7620.0001,0 0,1281 -3810,0 z" /><text
+     id="text69"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2446.187"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan71"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan73"
+         class="TextPosition"
+         x="10287.546"
+         y="9960.8135"><tspan
+           style="fill:#000000"
+           id="tspan75">Button Key/IR input logic</tspan></tspan></tspan></text>
+<path
+     style="fill:#cfe7f5"
+     inkscape:connector-curvature="0"
+     id="path79"
+     d="m 12079.546,12182.213 -2268.0001,0 0,-1412 4536.0001,0 0,1412 -2268,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path81"
+     d="m 12079.546,12182.213 -2268.0001,0 0,-1412 4536.0001,0 0,1412 -2268,0 z" /><text
+     id="text83"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2389.7871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan85"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan87"
+         class="TextPosition"
+         x="10792.546"
+         y="11692.213"><tspan
+           style="fill:#000000"
+           id="tspan89">EEPROM</tspan></tspan></tspan></text>
+<path
+     style="fill:#ffcc99"
+     inkscape:connector-curvature="0"
+     id="path93"
+     d="m 3050.5459,15498.013 -1563,0 0,-1715 3126,0 0,1715 -1563,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path95"
+     d="m 3050.5459,15498.013 -1563,0 0,-1715 3126,0 0,1715 -1563,0 z" /><text
+     id="text97"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan99"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan101"
+         class="TextPosition"
+         x="2186.5459"
+         y="14856.013"><tspan
+           style="fill:#000000"
+           id="tspan103">Sensor</tspan></tspan></tspan></text>
+<path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path107"
+     d="m 4629.5459,5866.013 385,-353 0,176 1167,0 0,-176 386,353 -386,354 0,-177 -1167,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path109"
+     d="m 4629.5459,5866.013 385,-353 0,176 1167,0 0,-176 386,353 -386,354 0,-177 -1167,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path113"
+     d="m 4629.5459,7448.013 385,-353 0,176 1167,0 0,-176 386,353 -386,354 0,-177 -1167,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path115"
+     d="m 4629.5459,7448.013 385,-353 0,176 1167,0 0,-176 386,353 -386,354 0,-177 -1167,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path119"
+     d="m 4631.5459,8936.013 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path121"
+     d="m 4631.5459,8936.013 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path125"
+     d="m 7872.5459,11464.213 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path127"
+     d="m 7872.5459,11464.213 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path131"
+     d="m 7872.5459,9716.813 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path133"
+     d="m 7872.5459,9716.813 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path137"
+     d="m 7872.5459,14994.013 670,-353 0,176 2028.0001,0 0,-176 671,353 -671,354 0,-177 -2028.0001,0 0,177 -670,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path139"
+     d="m 7872.5459,14994.013 670,-353 0,176 2028.0001,0 0,-176 671,353 -671,354 0,-177 -2028.0001,0 0,177 -670,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path143"
+     d="m 17534.058,14104.529 978.488,840.891 -978.488,840.89 0,-420.862 -2960.48,0 0,420.862 -979.489,-840.89 979.489,-840.891 0,420.029 2960.48,0 0,-420.029 z" /><path
+     style="fill:none;stroke:#3465af;stroke-width:25.77035904"
+     inkscape:connector-curvature="0"
+     id="path145"
+     d="m 17534.058,14104.529 978.488,840.891 -978.488,840.89 0,-420.862 -2960.48,0 0,420.862 -979.489,-840.89 979.489,-840.891 0,420.029 2960.48,0 0,-420.029 z" /><text
+     id="text149"
+     class="TextShape"
+     x="-9922.1533"
+     y="-644.58704"><tspan
+       style="font-weight:400;font-size:706px;font-family:'Times New Roman', serif"
+       id="tspan151"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="706px"><tspan
+         id="tspan153"
+         transform="matrix(0,-1,1,0,8509,40173)"
+         class="TextPosition"
+         x="14418.847"
+         y="15187.413"><tspan
+           style="fill:#000000"
+           id="tspan155">System Bus</tspan></tspan></tspan></text>
+<path
+     style="fill:#ccffff"
+     inkscape:connector-curvature="0"
+     id="path159"
+     d="m 11061.546,7098.013 -1250.0001,0 0,-875 2499.0001,0 0,875 -1249,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path161"
+     d="m 11061.546,7098.013 -1250.0001,0 0,-875 2499.0001,0 0,875 -1249,0 z" /><text
+     id="text163"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan165"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan167"
+         class="TextPosition"
+         x="10125.546"
+         y="6876.0132"><tspan
+           style="fill:#000000"
+           id="tspan169">Demux</tspan></tspan></tspan></text>
+<path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path173"
+     d="m 7906.5459,6601.013 373,-357 0,178 1130,0 0,-178 374,357 -374,358 0,-179 -1130,0 0,179 -373,-358 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path175"
+     d="m 7906.5459,6601.013 373,-357 0,178 1130,0 0,-178 374,357 -374,358 0,-179 -1130,0 0,179 -373,-358 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path179"
+     d="m 7906.5459,5214.013 373,-358 0,179 1130,0 0,-179 374,358 -374,358 0,-179 -1130,0 0,179 -373,-358 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path181"
+     d="m 7906.5459,5214.013 373,-358 0,179 1130,0 0,-179 374,358 -374,358 0,-179 -1130,0 0,179 -373,-358 z" /><path
+     style="fill:#ccffff"
+     inkscape:connector-curvature="0"
+     id="path185"
+     d="m 14232.546,5828.013 -4421.0001,0 0,-1270 8841.0001,0 0,1270 -4420,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path187"
+     d="m 14232.546,5828.013 -4421.0001,0 0,-1270 8841.0001,0 0,1270 -4420,0 z" /><text
+     id="text189"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan191"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan193"
+         class="TextPosition"
+         x="10696.546"
+         y="5409.0132"><tspan
+           style="fill:#000000"
+           id="tspan195">Conditional Access Module</tspan></tspan></tspan></text>
+<path
+     style="fill:#ff8080"
+     inkscape:connector-curvature="0"
+     id="path199"
+     d="m 2355.5459,11123.013 -2269,0 0,-1224 4537,0 0,1224 -2268,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path201"
+     d="m 2355.5459,11123.013 -2269,0 0,-1224 4537,0 0,1224 -2268,0 z" /><text
+     id="text203"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan205"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan207"
+         class="TextPosition"
+         x="511.5459"
+         y="10727.013"><tspan
+           style="fill:#000000"
+           id="tspan209">Video encoder</tspan></tspan></tspan></text>
+<path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path213"
+     d="m 4631.5459,10470.013 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path215"
+     d="m 4631.5459,10470.013 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path219"
+     d="m 18701.546,5381.013 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path221"
+     d="m 18701.546,5381.013 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><text
+     id="text225"
+     class="TextShape"
+     x="-1976.5541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan227"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan229"
+         class="TextPosition"
+         x="13.4459"
+         y="12314.013"><tspan
+           style="fill:#000000"
+           id="tspan231">Radio / Analog TV</tspan></tspan></tspan></text>
+<text
+     id="text235"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:700;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan237"
+       class="TextParagraph"
+       font-weight="700"
+       font-size="635px"><tspan
+         id="tspan239"
+         class="TextPosition"
+         x="12866.546"
+         y="8560.0127"><tspan
+           style="fill:#000000"
+           id="tspan241">Digital TV</tspan></tspan></tspan></text>
+<text
+     id="text245"
+     class="TextShape"
+     x="-8919.0537"
+     y="-1373.787"><tspan
+       style="font-weight:400;font-size:494px;font-family:'Times New Roman', serif"
+       id="tspan247"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="494px"><tspan
+         id="tspan249"
+         class="TextPosition"
+         x="5804.9458"
+         y="17793.213"><tspan
+           style="fill:#000000"
+           id="tspan251">PS.: picture is not complete: other blocks may be present</tspan></tspan></tspan></text>
+<text
+     id="text255"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan257"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan259"
+         class="TextPosition"
+         x="2109.5459"
+         y="16397.014"><tspan
+           style="fill:#000000"
+           id="tspan261">Webcam</tspan></tspan></tspan></text>
+<path
+     style="fill:#ff9900"
+     inkscape:connector-curvature="0"
+     id="path265"
+     d="m 12462.546,13925.813 -2650.0001,0 0,-1412 5299.0001,0 0,1412 -2649,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path267"
+     d="m 12462.546,13925.813 -2650.0001,0 0,-1412 5299.0001,0 0,1412 -2649,0 z" /><text
+     id="text269"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2446.187"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan271"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan273"
+         class="TextPosition"
+         x="10175.546"
+         y="13435.813"><tspan
+           style="fill:#000000"
+           id="tspan275">Processing blocks</tspan></tspan></tspan></text>
+<path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path279"
+     d="m 7872.5459,13207.813 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path281"
+     d="m 7872.5459,13207.813 385,-353 0,176 1166,0 0,-176 386,353 -386,354 0,-177 -1166,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path285"
+     d="m 4612.5459,14790.013 397,-353 0,176 1201,0 0,-176 398,353 -398,354 0,-177 -1201,0 0,177 -397,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path287"
+     d="m 4612.5459,14790.013 397,-353 0,176 1201,0 0,-176 398,353 -398,354 0,-177 -1201,0 0,177 -397,-354 z" /><text
+     id="text291"
+     class="TextShape"
+     x="-2428.0542"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan293"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan295"
+         class="TextPosition"
+         x="20421.945"
+         y="6628.0132"><tspan
+           style="fill:#000000"
+           id="tspan297">Smartcard</tspan></tspan></tspan></text>
+<path
+     style="fill:#ffccff"
+     inkscape:connector-curvature="0"
+     id="path301"
+     d="m 623.3227,436.013 c -334.5984,0 -669.1968,333 -669.1968,666 l 0,2668 c 0,333 334.5984,666 669.1968,666 l 18456.1663,0 c 334.598,0 670.202,-333 670.202,-666 l 0,-2668 c 0,-333 -335.604,-666 -670.202,-666 l -18456.1663,0 z" /><path
+     style="fill:#ff8080"
+     inkscape:connector-curvature="0"
+     id="path305"
+     d="m 3031.5459,2991.013 -1614,0 0,-1816 3227,0 0,1816 -1613,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path307"
+     d="m 3031.5459,2991.013 -1614,0 0,-1816 3227,0 0,1816 -1613,0 z" /><text
+     style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+     id="text309"
+     class="TextShape"
+     font-weight="400"
+     font-size="635px"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       id="tspan311"
+       class="TextParagraph"><tspan
+         id="tspan313"
+         class="TextPosition"
+         x="2284.5459"
+         y="1947.0129"><tspan
+           style="fill:#000000"
+           id="tspan315">Tuner</tspan></tspan></tspan><tspan
+       id="tspan317"
+       class="TextParagraph"><tspan
+         id="tspan319"
+         class="TextPosition"
+         x="2061.5459"
+         y="2650.0129"><tspan
+           style="fill:#000000"
+           id="tspan321">FM/TV</tspan></tspan></tspan></text>
+<path
+     style="fill:#ff8080"
+     inkscape:connector-curvature="0"
+     id="path325"
+     d="m 812.5459,1538.013 c 0,111 40,202 88,202 l 530,0 c 48,0 89,-91 89,-202 0,-110 -41,-202 -89,-202 l -530,0 c -48,0 -88,92 -88,202 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path327"
+     d="m 812.5459,1538.013 c 0,111 40,202 88,202 l 530,0 c 48,0 89,-91 89,-202 0,-110 -41,-202 -89,-202 l -530,0 c -48,0 -88,92 -88,202 z" /><path
+     style="fill:#ffb3b3"
+     inkscape:connector-curvature="0"
+     id="path329"
+     d="m 812.5459,1538.013 c 0,111 40,202 88,202 48,0 88,-91 88,-202 0,-110 -40,-202 -88,-202 -48,0 -88,92 -88,202 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path331"
+     d="m 812.5459,1538.013 c 0,111 40,202 88,202 48,0 88,-91 88,-202 0,-110 -40,-202 -88,-202 -48,0 -88,92 -88,202 z" /><path
+     style="fill:#ff8080"
+     inkscape:connector-curvature="0"
+     id="path335"
+     d="m 813.5459,2103.013 c 0,110 40,202 88,202 l 530,0 c 48,0 89,-92 89,-202 0,-110 -41,-203 -89,-203 l -530,0 c -48,0 -88,93 -88,203 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path337"
+     d="m 813.5459,2103.013 c 0,110 40,202 88,202 l 530,0 c 48,0 89,-92 89,-202 0,-110 -41,-203 -89,-203 l -530,0 c -48,0 -88,93 -88,203 z" /><path
+     style="fill:#ffb3b3"
+     inkscape:connector-curvature="0"
+     id="path339"
+     d="m 813.5459,2103.013 c 0,110 40,202 88,202 48,0 88,-92 88,-202 0,-110 -40,-203 -88,-203 -48,0 -88,93 -88,203 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path341"
+     d="m 813.5459,2103.013 c 0,110 40,202 88,202 48,0 88,-92 88,-202 0,-110 -40,-203 -88,-203 -48,0 -88,93 -88,203 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path345"
+     d="m 4629.5459,2032.013 385,-353 0,176 1167,0 0,-176 386,353 -386,354 0,-177 -1167,0 0,177 -385,-354 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path347"
+     d="m 4629.5459,2032.013 385,-353 0,176 1167,0 0,-176 386,353 -386,354 0,-177 -1167,0 0,177 -385,-354 z" /><path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path351"
+     d="m 7889.5459,1986.013 402,-368 0,184 1217,0 0,-184 403,368 -403,369 0,-185 -1217,0 0,185 -402,-369 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path353"
+     d="m 7889.5459,1986.013 402,-368 0,184 1217,0 0,-184 403,368 -403,369 0,-185 -1217,0 0,185 -402,-369 z" /><path
+     style="fill:#ccffff"
+     inkscape:connector-curvature="0"
+     id="path357"
+     d="m 14410.546,4025.013 -4500.0001,0 0,-1389 9000.0001,0 0,1389 -4500,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path359"
+     d="m 14410.546,4025.013 -4500.0001,0 0,-1389 9000.0001,0 0,1389 -4500,0 z" /><text
+     id="text361"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan363"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan365"
+         class="TextPosition"
+         x="9961.5459"
+         y="3546.0129"><tspan
+           style="fill:#000000"
+           id="tspan367">Satellite Equipment Control (SEC)</tspan></tspan></tspan></text>
+<path
+     style="fill:#ccffff"
+     inkscape:connector-curvature="0"
+     id="path371"
+     d="m 11310.546,2436.013 -1400.0001,0 0,-1000 2800.0001,0 0,1000 -1400,0 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path373"
+     d="m 11310.546,2436.013 -1400.0001,0 0,-1000 2800.0001,0 0,1000 -1400,0 z" /><text
+     id="text375"
+     class="TextShape"
+     x="-2089.4541"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan377"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan379"
+         class="TextPosition"
+         x="10375.546"
+         y="2152.0129"><tspan
+           style="fill:#000000"
+           id="tspan381">Demod</tspan></tspan></tspan></text>
+<path
+     style="fill:#729fcf"
+     inkscape:connector-curvature="0"
+     id="path385"
+     d="m 7889.5459,3287.013 402,-368 0,184 1217,0 0,-184 403,368 -403,369 0,-185 -1217,0 0,185 -402,-369 z" /><path
+     style="fill:none;stroke:#3465af"
+     inkscape:connector-curvature="0"
+     id="path387"
+     d="m 7889.5459,3287.013 402,-368 0,184 1217,0 0,-184 403,368 -403,369 0,-185 -1217,0 0,185 -402,-369 z" /><path
+     d="m 7906.5459,9121.013 0,7302 -1270,0 0,-14605 1270,0 0,7303 z"
+     id="path389"
+     inkscape:connector-curvature="0"
+     style="fill:#ffff99" /><path
+     d="m 7906.5459,9121.013 0,7302 -1270,0 0,-14605 1270,0 0,7303 z"
+     id="path391"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#3465af" /><text
+     y="-6589.021"
+     x="-20792.584"
+     transform="matrix(0,-1,1,0,0,0)"
+     class="TextShape"
+     id="text393"><tspan
+       font-size="635px"
+       font-weight="400"
+       class="TextParagraph"
+       id="tspan395"
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"><tspan
+         y="7460.9849"
+         x="-11215.646"
+         class="TextPosition"
+         transform="matrix(0,-1,1,0,-4473,23627)"
+         id="tspan397"><tspan
+           id="tspan399"
+           style="fill:#000000">I2C Bus (control bus)</tspan></tspan></tspan></text>
+<text
+     id="text403"
+     class="TextShape"
+     x="-2145.854"
+     y="-2163.9871"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan405"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan407"
+         class="TextPosition"
+         x="7245.146"
+         y="1114.0129"><tspan
+           style="fill:#000000"
+           id="tspan409">Digital TV Frontend</tspan></tspan></tspan></text>
+<path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 863.1459,636.145 c -18.27,0 -35.525,0.99994 -53.795,2.99982"
+     id="path415"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 776.8709,644.14452 c -17.255,2.99982 -35.525,6.99958 -52.78,11.99928"
+     id="path417"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 692.6259,666.1432 c -16.24,5.99964 -33.495,11.99928 -49.735,19.9988"
+     id="path419"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 613.4559,700.14116 c -15.225,7.99952 -31.465,16.99898 -46.69,26.99838"
+     id="path421"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 539.3609,745.13846 c -14.21,9.9994 -28.42,20.99874 -42.63,31.99808"
+     id="path423"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 471.3559,798.13528 c -13.195,11.99928 -26.39,23.99856 -38.57,36.99778"
+     id="path425"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 410.4559,859.13162 c -11.165,12.99922 -22.33,26.99838 -33.495,40.99754"
+     id="path427"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 357.6759,927.12754 c -10.15,13.99916 -19.285,28.99826 -28.42,44.9973"
+     id="path429"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 314.0309,1000.1232 c -8.12,15.999 -15.225,31.998 -22.33,48.997"
+     id="path431"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 280.5359,1079.1184 c -5.075,16.999 -10.15,33.998 -14.21,50.997"
+     id="path433"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 260.2359,1162.1134 c -3.045,17.999 -5.075,34.9979 -6.09,52.9969"
+     id="path435"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1247.1083 0,52.9969"
+     id="path437"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1333.1032 0,52.9968"
+     id="path439"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1418.0981 0,52.9968"
+     id="path441"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1504.0929 0,52.9968"
+     id="path443"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1589.0878 0,52.9968"
+     id="path445"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1675.0827 0,52.9968"
+     id="path447"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1760.0776 0,52.9968"
+     id="path449"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1845.0725 0,53.9967"
+     id="path451"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,1931.0673 0,52.9968"
+     id="path453"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2016.0622 0,52.9968"
+     id="path455"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2102.057 0,52.9969"
+     id="path457"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2187.0519 0,52.9969"
+     id="path459"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2273.0468 0,52.9968"
+     id="path461"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2358.0417 0,52.9968"
+     id="path463"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2443.0366 0,53.9967"
+     id="path465"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2529.0314 0,52.9968"
+     id="path467"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2614.0263 0,52.9968"
+     id="path469"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2700.0212 0,52.9968"
+     id="path471"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2785.0161 0,52.9968"
+     id="path473"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2871.0109 0,52.9968"
+     id="path475"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,2956.0058 0,52.9968"
+     id="path477"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3041.0007 0,53.9968"
+     id="path479"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3126.9955 0,52.9969"
+     id="path481"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3211.9904 0,52.9969"
+     id="path483"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3297.9853 0,52.9968"
+     id="path485"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3382.9802 0,52.9968"
+     id="path487"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3468.975 0,52.9968"
+     id="path489"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3553.9699 0,52.9968"
+     id="path491"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 254.1459,3638.9648 c 0,17.9989 1.015,35.9979 3.045,52.9968"
+     id="path493"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 262.2659,3723.9597 c 4.06,17.9989 8.12,34.9979 13.195,51.9969"
+     id="path495"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 285.6109,3806.9547 c 6.09,15.9991 13.195,32.9981 20.3,48.9971"
+     id="path497"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 321.1359,3884.9501 c 8.12,14.9991 17.255,30.9981 27.405,45.9972"
+     id="path499"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 366.8109,3957.9457 c 10.15,13.9991 21.315,27.9983 32.48,41.9975"
+     id="path501"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 420.6059,4023.9417 c 12.18,12.9992 25.375,25.9985 38.57,37.9977"
+     id="path503"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 483.5359,4083.9381 c 13.195,10.9994 27.405,22.9986 41.615,32.998"
+     id="path505"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 552.5559,4135.935 c 14.21,9.9994 29.435,18.9989 45.675,26.9984"
+     id="path507"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 627.6659,4178.9324 c 15.225,6.9996 32.48,14.9991 48.72,20.9988"
+     id="path509"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 707.8509,4210.9305 c 17.255,4.9997 34.51,9.9994 51.765,13.9992"
+     id="path511"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 792.0959,4230.9293 c 17.255,1.9999 35.525,3.9998 53.795,4.9997"
+     id="path513"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 878.3709,4235.929 53.795,0"
+     id="path515"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 964.6459,4235.929 53.795,0"
+     id="path517"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1051.9359,4235.929 53.795,0"
+     id="path519"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1138.2109,4235.929 53.795,0"
+     id="path521"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1225.5009,4235.929 53.795,0"
+     id="path523"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1311.7759,4235.929 53.795,0"
+     id="path525"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1398.0509,4235.929 54.81,0"
+     id="path527"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1485.3409,4235.929 53.795,0"
+     id="path529"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1571.6159,4235.929 53.795,0"
+     id="path531"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1658.9059,4235.929 53.795,0"
+     id="path533"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1745.1809,4235.929 53.795,0"
+     id="path535"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1832.4709,4235.929 53.795,0"
+     id="path537"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1918.7459,4235.929 53.795,0"
+     id="path539"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2005.0209,4235.929 54.81,0"
+     id="path541"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2092.3109,4235.929 53.795,0"
+     id="path543"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2178.5859,4235.929 53.795,0"
+     id="path545"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2265.8759,4235.929 53.795,0"
+     id="path547"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2352.1509,4235.929 53.795,0"
+     id="path549"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2439.4409,4235.929 53.795,0"
+     id="path551"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2525.7159,4235.929 53.795,0"
+     id="path553"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2611.9909,4235.929 54.81,0"
+     id="path555"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2699.2809,4235.929 53.795,0"
+     id="path557"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2785.5559,4235.929 53.795,0"
+     id="path559"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2872.8459,4235.929 53.795,0"
+     id="path561"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2959.1209,4235.929 53.795,0"
+     id="path563"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3046.4109,4235.929 53.795,0"
+     id="path565"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3132.6859,4235.929 53.795,0"
+     id="path567"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3219.9759,4235.929 53.795,0"
+     id="path569"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3306.2509,4235.929 53.795,0"
+     id="path571"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3392.5259,4235.929 53.795,0"
+     id="path573"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3479.8159,4235.929 53.795,0"
+     id="path575"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3566.0909,4235.929 53.795,0"
+     id="path577"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3653.3809,4235.929 53.795,0"
+     id="path579"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3739.6559,4235.929 53.795,0"
+     id="path581"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3826.9459,4235.929 53.795,0"
+     id="path583"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3913.2209,4235.929 53.795,0"
+     id="path585"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3999.4959,4235.929 53.795,0"
+     id="path587"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4086.7859,4235.929 53.795,0"
+     id="path589"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4173.0609,4235.929 53.795,0"
+     id="path591"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4260.3509,4235.929 53.795,0"
+     id="path593"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4346.6259,4235.929 53.795,0"
+     id="path595"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4433.9159,4235.929 53.795,0"
+     id="path597"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4520.1909,4235.929 53.795,0"
+     id="path599"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4606.4659,4235.929 54.81,0"
+     id="path601"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4693.7559,4235.929 53.795,0"
+     id="path603"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4780.0309,4235.929 53.795,0"
+     id="path605"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4867.3209,4235.929 53.795,0"
+     id="path607"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4953.5959,4235.929 53.795,0"
+     id="path609"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5040.8859,4235.929 53.795,0"
+     id="path611"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5127.1609,4235.929 53.795,0"
+     id="path613"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5213.4359,4235.929 54.81,0"
+     id="path615"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5300.7259,4235.929 53.795,0"
+     id="path617"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5387.0009,4235.929 53.795,0"
+     id="path619"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5474.2909,4235.929 53.795,0"
+     id="path621"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5560.5659,4235.929 53.795,0"
+     id="path623"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5647.8559,4235.929 53.795,0"
+     id="path625"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5734.1309,4235.929 53.795,0"
+     id="path627"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5820.4059,4235.929 54.81,0"
+     id="path629"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5907.6959,4235.929 53.795,0"
+     id="path631"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5993.9709,4235.929 53.795,0"
+     id="path633"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6081.2609,4235.929 53.795,0"
+     id="path635"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6167.5359,4235.929 53.795,0"
+     id="path637"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6254.8259,4235.929 53.795,0"
+     id="path639"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6341.1009,4235.929 53.795,0"
+     id="path641"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6427.3759,4235.929 54.81,0"
+     id="path643"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6514.6659,4235.929 53.795,0"
+     id="path645"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6600.9409,4235.929 53.795,0"
+     id="path647"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6688.2309,4235.929 53.795,0"
+     id="path649"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6774.5059,4235.929 53.795,0"
+     id="path651"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6861.7959,4235.929 53.795,0"
+     id="path653"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6948.0709,4235.929 53.795,0"
+     id="path655"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7035.3609,4235.929 53.795,0"
+     id="path657"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7121.6359,4235.929 53.795,0"
+     id="path659"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7207.9109,4235.929 53.795,0"
+     id="path661"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7295.2009,4235.929 53.795,0"
+     id="path663"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7381.4759,4235.929 53.795,0"
+     id="path665"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7468.7659,4235.929 53.795,0"
+     id="path667"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7555.0409,4235.929 53.795,0"
+     id="path669"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7642.3309,4235.929 53.795,0"
+     id="path671"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7728.6059,4235.929 53.795,0"
+     id="path673"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7814.8809,4235.929 53.795,0"
+     id="path675"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7902.1709,4235.929 53.795,0"
+     id="path677"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7988.4459,4235.929 53.795,0"
+     id="path679"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8075.7359,4235.929 53.795,0"
+     id="path681"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8162.0109,4235.929 53.795,0"
+     id="path683"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8249.3009,4235.929 53.795,0"
+     id="path685"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8335.5759,4235.929 53.795,0"
+     id="path687"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8421.8509,4235.929 53.795,0"
+     id="path689"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8509.1409,4235.929 53.795,0"
+     id="path691"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8595.4159,4235.929 53.795,0"
+     id="path693"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8682.7059,4235.929 53.795,0"
+     id="path695"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8768.9809,4235.929 53.795,0"
+     id="path697"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8856.2709,4235.929 53.795,0"
+     id="path699"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8942.5459,4235.929 53.795,0"
+     id="path701"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9028.8209,4235.929 54.81,0"
+     id="path703"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9116.1109,4235.929 53.795,0"
+     id="path705"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9202.3859,4235.929 53.795,0"
+     id="path707"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9289.6759,4235.929 53.795,0"
+     id="path709"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9375.9509,4235.929 53.795,0"
+     id="path711"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9463.2409,4235.929 53.795,0"
+     id="path713"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9549.5159,4235.929 53.795,0"
+     id="path715"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9635.7909,4235.929 54.81,0"
+     id="path717"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9723.0809,4235.929 53.795,0"
+     id="path719"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9809.3559,4235.929 53.795,0"
+     id="path721"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9896.6459,4235.929 53.795,0"
+     id="path723"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9982.9209,4235.929 53.7951,0"
+     id="path725"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10070.211,4235.929 53.795,0"
+     id="path727"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10156.486,4235.929 53.795,0"
+     id="path729"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10242.761,4235.929 54.81,0"
+     id="path731"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10330.051,4235.929 53.795,0"
+     id="path733"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10416.326,4235.929 53.795,0"
+     id="path735"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10503.616,4235.929 53.795,0"
+     id="path737"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10589.891,4235.929 53.795,0"
+     id="path739"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10677.181,4235.929 53.795,0"
+     id="path741"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10763.456,4235.929 53.795,0"
+     id="path743"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10849.731,4235.929 54.81,0"
+     id="path745"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10937.021,4235.929 53.795,0"
+     id="path747"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11023.296,4235.929 53.795,0"
+     id="path749"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11110.586,4235.929 53.795,0"
+     id="path751"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11196.861,4235.929 53.795,0"
+     id="path753"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11284.151,4235.929 53.795,0"
+     id="path755"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11370.426,4235.929 53.795,0"
+     id="path757"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11457.716,4235.929 53.795,0"
+     id="path759"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11543.991,4235.929 53.795,0"
+     id="path761"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11630.266,4235.929 53.795,0"
+     id="path763"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11717.556,4235.929 53.795,0"
+     id="path765"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11803.831,4235.929 53.795,0"
+     id="path767"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11891.121,4235.929 53.795,0"
+     id="path769"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11977.396,4235.929 53.795,0"
+     id="path771"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12064.686,4235.929 53.795,0"
+     id="path773"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12150.961,4235.929 53.795,0"
+     id="path775"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12237.236,4235.929 53.795,0"
+     id="path777"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12324.526,4235.929 53.795,0"
+     id="path779"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12410.801,4235.929 53.795,0"
+     id="path781"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12498.091,4235.929 53.795,0"
+     id="path783"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12584.366,4235.929 53.795,0"
+     id="path785"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12671.656,4235.929 53.795,0"
+     id="path787"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12757.931,4235.929 53.795,0"
+     id="path789"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12844.206,4235.929 54.81,0"
+     id="path791"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12931.496,4235.929 53.795,0"
+     id="path793"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13017.771,4235.929 53.795,0"
+     id="path795"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13105.061,4235.929 53.795,0"
+     id="path797"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13191.336,4235.929 53.795,0"
+     id="path799"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13278.626,4235.929 53.795,0"
+     id="path801"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13364.901,4235.929 53.795,0"
+     id="path803"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13451.176,4235.929 54.81,0"
+     id="path805"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13538.466,4235.929 53.795,0"
+     id="path807"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13624.741,4235.929 53.795,0"
+     id="path809"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13712.031,4235.929 53.795,0"
+     id="path811"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13798.306,4235.929 53.795,0"
+     id="path813"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13885.596,4235.929 53.795,0"
+     id="path815"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13971.871,4235.929 53.795,0"
+     id="path817"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14058.146,4235.929 54.81,0"
+     id="path819"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14145.436,4235.929 53.795,0"
+     id="path821"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14231.711,4235.929 53.795,0"
+     id="path823"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14319.001,4235.929 53.795,0"
+     id="path825"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14405.276,4235.929 53.795,0"
+     id="path827"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14492.566,4235.929 53.795,0"
+     id="path829"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14578.841,4235.929 53.795,0"
+     id="path831"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14665.116,4235.929 54.81,0"
+     id="path833"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14752.406,4235.929 53.795,0"
+     id="path835"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14838.681,4235.929 53.795,0"
+     id="path837"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14925.971,4235.929 53.795,0"
+     id="path839"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15012.246,4235.929 53.795,0"
+     id="path841"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15099.536,4235.929 53.795,0"
+     id="path843"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15185.811,4235.929 53.795,0"
+     id="path845"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15272.086,4235.929 54.81,0"
+     id="path847"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15359.376,4235.929 53.795,0"
+     id="path849"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15445.651,4235.929 53.795,0"
+     id="path851"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15532.941,4235.929 53.795,0"
+     id="path853"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15619.216,4235.929 53.795,0"
+     id="path855"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15706.506,4235.929 53.795,0"
+     id="path857"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15792.781,4235.929 53.795,0"
+     id="path859"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15880.071,4235.929 53.795,0"
+     id="path861"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15966.346,4235.929 53.795,0"
+     id="path863"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16052.621,4235.929 53.795,0"
+     id="path865"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16139.911,4235.929 53.795,0"
+     id="path867"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16226.186,4235.929 53.795,0"
+     id="path869"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16313.476,4235.929 53.795,0"
+     id="path871"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16399.751,4235.929 53.795,0"
+     id="path873"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16487.041,4235.929 53.795,0"
+     id="path875"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16573.316,4235.929 53.795,0"
+     id="path877"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16659.591,4235.929 53.795,0"
+     id="path879"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16746.881,4235.929 53.795,0"
+     id="path881"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16833.156,4235.929 53.795,0"
+     id="path883"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16920.446,4235.929 53.795,0"
+     id="path885"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17006.721,4235.929 53.795,0"
+     id="path887"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17094.011,4235.929 53.795,0"
+     id="path889"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17180.286,4235.929 53.795,0"
+     id="path891"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17266.561,4235.929 54.81,0"
+     id="path893"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17353.851,4235.929 53.795,0"
+     id="path895"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17440.126,4235.929 53.795,0"
+     id="path897"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17527.416,4235.929 53.795,0"
+     id="path899"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17613.691,4235.929 53.795,0"
+     id="path901"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17700.981,4235.929 53.795,0"
+     id="path903"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17787.256,4235.929 53.795,0"
+     id="path905"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17873.531,4235.929 54.81,0"
+     id="path907"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17960.821,4235.929 53.795,0"
+     id="path909"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18047.096,4235.929 53.795,0"
+     id="path911"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18134.386,4235.929 53.795,0"
+     id="path913"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18220.661,4235.929 53.795,0"
+     id="path915"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18307.951,4235.929 53.795,0"
+     id="path917"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18394.226,4235.929 53.795,0"
+     id="path919"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18480.501,4235.929 54.81,0"
+     id="path921"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18567.791,4235.929 53.795,0"
+     id="path923"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18654.066,4235.929 53.795,0"
+     id="path925"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18741.356,4235.929 c 17.255,-0.9999 35.525,-1.9999 53.795,-4.9997"
+     id="path927"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18827.631,4225.9296 c 17.255,-3.9998 34.51,-8.9995 51.765,-13.9992"
+     id="path929"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18910.861,4200.9311 c 16.24,-5.9996 32.48,-12.9992 48.72,-20.9987"
+     id="path931"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18989.016,4164.9333 c 15.225,-7.9996 31.465,-16.999 45.675,-26.9984"
+     id="path933"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19062.096,4118.936 c 14.21,-9.9994 28.42,-20.9987 42.63,-31.9981"
+     id="path935"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19129.086,4064.9393 c 13.195,-11.9993 25.375,-24.9985 37.555,-37.9978"
+     id="path937"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19188.971,4002.943 c 11.165,-13.9992 22.33,-27.9983 33.495,-41.9975"
+     id="path939"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19240.736,3933.9471 c 10.15,-14.9991 19.285,-29.9982 27.405,-44.9973"
+     id="path941"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19283.366,3859.9516 c 7.105,-15.9991 14.21,-32.9981 20.3,-48.9971"
+     id="path943"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19314.831,3779.9564 c 5.075,-16.999 9.135,-33.998 13.195,-50.997"
+     id="path945"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19333.101,3696.9613 c 2.03,-17.9989 4.06,-34.9979 4.06,-52.9968"
+     id="path947"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3611.9664 0,-53.9967"
+     id="path949"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3525.9716 0,-52.9968"
+     id="path951"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3440.9767 0,-52.9968"
+     id="path953"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3354.9819 0,-52.9969"
+     id="path955"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3269.987 0,-52.9969"
+     id="path957"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3183.9921 0,-52.9968"
+     id="path959"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3098.9972 0,-52.9968"
+     id="path961"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,3014.0023 0,-53.9967"
+     id="path963"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2928.0075 0,-52.9968"
+     id="path965"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2843.0126 0,-52.9968"
+     id="path967"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2757.0177 0,-52.9968"
+     id="path969"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2672.0228 0,-52.9968"
+     id="path971"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2586.028 0,-52.9968"
+     id="path973"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2501.0331 0,-52.9968"
+     id="path975"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2415.0383 0,-52.9969"
+     id="path977"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2330.0434 0,-52.9969"
+     id="path979"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2245.0485 0,-52.9969"
+     id="path981"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2159.0536 0,-52.9968"
+     id="path983"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,2074.0587 0,-52.9968"
+     id="path985"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1988.0639 0,-52.9968"
+     id="path987"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1903.069 0,-52.9968"
+     id="path989"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1817.0741 0,-52.9968"
+     id="path991"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1732.0792 0,-52.9968"
+     id="path993"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1647.0843 0,-52.9968"
+     id="path995"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1561.0895 0,-52.9968"
+     id="path997"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1476.0946 0,-52.9968"
+     id="path999"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1390.0998 0,-52.9969"
+     id="path1001"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1305.1049 0,-52.9969"
+     id="path1003"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19337.161,1219.11 c -1.015,-16.999 -3.045,-34.9979 -5.075,-51.9969"
+     id="path1005"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19325.996,1135.1151 c -4.06,-16.999 -8.12,-34.9979 -14.21,-50.997"
+     id="path1007"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19300.621,1053.12 c -6.09,-15.9991 -13.195,-32.998 -21.315,-48.9971"
+     id="path1009"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19264.081,976.1246 c -9.135,-15.99904 -18.27,-30.99814 -28.42,-45.99724"
+     id="path1011"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19216.376,904.12892 c -10.15,-13.99916 -21.315,-27.99832 -33.495,-41.99748"
+     id="path1013"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19160.551,838.13288 c -12.18,-12.99922 -24.36,-24.9985 -37.555,-36.99778"
+     id="path1015"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19097.621,780.13636 c -14.21,-11.99928 -28.42,-21.99868 -42.63,-32.99802"
+     id="path1017"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 19027.586,729.13942 c -15.225,-8.99946 -30.45,-17.99892 -46.69,-26.99838"
+     id="path1019"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18951.461,688.14188 c -16.24,-7.99952 -32.48,-13.99916 -49.735,-19.9988"
+     id="path1021"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18870.261,657.14374 c -17.255,-4.9997 -34.51,-8.99946 -51.765,-11.99928"
+     id="path1023"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18786.016,640.14476 c -18.27,-2.99982 -35.525,-3.99976 -53.795,-3.99976"
+     id="path1025"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18699.741,636.145 -53.795,0"
+     id="path1027"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18612.451,636.145 -53.795,0"
+     id="path1029"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18526.176,636.145 -53.795,0"
+     id="path1031"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18438.886,636.145 -53.795,0"
+     id="path1033"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18352.611,636.145 -53.795,0"
+     id="path1035"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18266.336,636.145 -54.81,0"
+     id="path1037"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18179.046,636.145 -53.795,0"
+     id="path1039"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18092.771,636.145 -53.795,0"
+     id="path1041"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 18005.481,636.145 -53.795,0"
+     id="path1043"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17919.206,636.145 -53.795,0"
+     id="path1045"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17831.916,636.145 -53.795,0"
+     id="path1047"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17745.641,636.145 -53.795,0"
+     id="path1049"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17659.366,636.145 -54.81,0"
+     id="path1051"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17572.076,636.145 -53.795,0"
+     id="path1053"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17485.801,636.145 -53.795,0"
+     id="path1055"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17398.511,636.145 -53.795,0"
+     id="path1057"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17312.236,636.145 -53.795,0"
+     id="path1059"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17224.946,636.145 -53.795,0"
+     id="path1061"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17138.671,636.145 -53.795,0"
+     id="path1063"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 17052.396,636.145 -54.81,0"
+     id="path1065"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16965.106,636.145 -53.795,0"
+     id="path1067"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16878.831,636.145 -53.795,0"
+     id="path1069"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16791.541,636.145 -53.795,0"
+     id="path1071"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16705.266,636.145 -53.795,0"
+     id="path1073"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16617.976,636.145 -53.795,0"
+     id="path1075"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16531.701,636.145 -53.795,0"
+     id="path1077"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16445.426,636.145 -54.81,0"
+     id="path1079"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16358.136,636.145 -53.795,0"
+     id="path1081"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16271.861,636.145 -53.795,0"
+     id="path1083"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16184.571,636.145 -53.795,0"
+     id="path1085"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16098.296,636.145 -53.795,0"
+     id="path1087"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 16011.006,636.145 -53.795,0"
+     id="path1089"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15924.731,636.145 -53.795,0"
+     id="path1091"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15837.441,636.145 -53.795,0"
+     id="path1093"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15751.166,636.145 -53.795,0"
+     id="path1095"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15664.891,636.145 -53.795,0"
+     id="path1097"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15577.601,636.145 -53.795,0"
+     id="path1099"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15491.326,636.145 -53.795,0"
+     id="path1101"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15404.036,636.145 -53.795,0"
+     id="path1103"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15317.761,636.145 -53.795,0"
+     id="path1105"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15230.471,636.145 -53.795,0"
+     id="path1107"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15144.196,636.145 -53.795,0"
+     id="path1109"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 15057.921,636.145 -53.795,0"
+     id="path1111"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14970.631,636.145 -53.795,0"
+     id="path1113"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14884.356,636.145 -53.795,0"
+     id="path1115"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14797.066,636.145 -53.795,0"
+     id="path1117"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14710.791,636.145 -53.795,0"
+     id="path1119"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14623.501,636.145 -53.795,0"
+     id="path1121"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14537.226,636.145 -53.795,0"
+     id="path1123"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14450.951,636.145 -54.81,0"
+     id="path1125"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14363.661,636.145 -53.795,0"
+     id="path1127"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14277.386,636.145 -53.795,0"
+     id="path1129"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14190.096,636.145 -53.795,0"
+     id="path1131"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14103.821,636.145 -53.795,0"
+     id="path1133"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 14016.531,636.145 -53.795,0"
+     id="path1135"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13930.256,636.145 -53.795,0"
+     id="path1137"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13843.981,636.145 -54.81,0"
+     id="path1139"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13756.691,636.145 -53.795,0"
+     id="path1141"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13670.416,636.145 -53.795,0"
+     id="path1143"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13583.126,636.145 -53.795,0"
+     id="path1145"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13496.851,636.145 -53.795,0"
+     id="path1147"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13409.561,636.145 -53.795,0"
+     id="path1149"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13323.286,636.145 -53.795,0"
+     id="path1151"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13237.011,636.145 -54.81,0"
+     id="path1153"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13149.721,636.145 -53.795,0"
+     id="path1155"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 13063.446,636.145 -53.795,0"
+     id="path1157"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12976.156,636.145 -53.795,0"
+     id="path1159"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12889.881,636.145 -53.795,0"
+     id="path1161"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12802.591,636.145 -53.795,0"
+     id="path1163"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12716.316,636.145 -53.795,0"
+     id="path1165"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12630.041,636.145 -54.81,0"
+     id="path1167"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12542.751,636.145 -53.795,0"
+     id="path1169"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12456.476,636.145 -53.795,0"
+     id="path1171"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12369.186,636.145 -53.795,0"
+     id="path1173"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12282.911,636.145 -53.795,0"
+     id="path1175"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12195.621,636.145 -53.795,0"
+     id="path1177"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12109.346,636.145 -53.795,0"
+     id="path1179"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 12022.056,636.145 -53.795,0"
+     id="path1181"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11935.781,636.145 -53.795,0"
+     id="path1183"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11849.506,636.145 -53.795,0"
+     id="path1185"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11762.216,636.145 -53.795,0"
+     id="path1187"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11675.941,636.145 -53.795,0"
+     id="path1189"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11588.651,636.145 -53.795,0"
+     id="path1191"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11502.376,636.145 -53.795,0"
+     id="path1193"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11415.086,636.145 -53.795,0"
+     id="path1195"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11328.811,636.145 -53.795,0"
+     id="path1197"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11242.536,636.145 -53.795,0"
+     id="path1199"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11155.246,636.145 -53.795,0"
+     id="path1201"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 11068.971,636.145 -53.795,0"
+     id="path1203"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10981.681,636.145 -53.795,0"
+     id="path1205"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10895.406,636.145 -53.795,0"
+     id="path1207"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10808.116,636.145 -53.795,0"
+     id="path1209"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10721.841,636.145 -53.795,0"
+     id="path1211"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10635.566,636.145 -53.795,0"
+     id="path1213"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10548.276,636.145 -53.795,0"
+     id="path1215"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10462.001,636.145 -53.795,0"
+     id="path1217"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10374.711,636.145 -53.795,0"
+     id="path1219"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10288.436,636.145 -53.795,0"
+     id="path1221"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10201.146,636.145 -53.795,0"
+     id="path1223"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10114.871,636.145 -53.795,0"
+     id="path1225"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 10028.596,636.145 -54.8101,0"
+     id="path1227"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9941.3059,636.145 -53.795,0"
+     id="path1229"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9855.0309,636.145 -53.795,0"
+     id="path1231"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9767.7409,636.145 -53.795,0"
+     id="path1233"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9681.4659,636.145 -53.795,0"
+     id="path1235"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9594.1759,636.145 -53.795,0"
+     id="path1237"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9507.9009,636.145 -53.795,0"
+     id="path1239"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9421.6259,636.145 -54.81,0"
+     id="path1241"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9334.3359,636.145 -53.795,0"
+     id="path1243"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9248.0609,636.145 -53.795,0"
+     id="path1245"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9160.7709,636.145 -53.795,0"
+     id="path1247"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 9074.4959,636.145 -53.795,0"
+     id="path1249"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8987.2059,636.145 -53.795,0"
+     id="path1251"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8900.9309,636.145 -53.795,0"
+     id="path1253"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8814.6559,636.145 -54.81,0"
+     id="path1255"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8727.3659,636.145 -53.795,0"
+     id="path1257"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8641.0909,636.145 -53.795,0"
+     id="path1259"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8553.8009,636.145 -53.795,0"
+     id="path1261"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8467.5259,636.145 -53.795,0"
+     id="path1263"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8380.2359,636.145 -53.795,0"
+     id="path1265"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8293.9609,636.145 -53.795,0"
+     id="path1267"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8207.6859,636.145 -54.81,0"
+     id="path1269"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8120.3959,636.145 -53.795,0"
+     id="path1271"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 8034.1209,636.145 -53.795,0"
+     id="path1273"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7946.8309,636.145 -53.795,0"
+     id="path1275"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7860.5559,636.145 -53.795,0"
+     id="path1277"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7773.2659,636.145 -53.795,0"
+     id="path1279"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7686.9909,636.145 -53.795,0"
+     id="path1281"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7599.7009,636.145 -53.795,0"
+     id="path1283"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7513.4259,636.145 -53.795,0"
+     id="path1285"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7427.1509,636.145 -53.795,0"
+     id="path1287"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7339.8609,636.145 -53.795,0"
+     id="path1289"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7253.5859,636.145 -53.795,0"
+     id="path1291"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7166.2959,636.145 -53.795,0"
+     id="path1293"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 7080.0209,636.145 -53.795,0"
+     id="path1295"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6992.7309,636.145 -53.795,0"
+     id="path1297"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6906.4559,636.145 -53.795,0"
+     id="path1299"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6820.1809,636.145 -53.795,0"
+     id="path1301"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6732.8909,636.145 -53.795,0"
+     id="path1303"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6646.6159,636.145 -53.795,0"
+     id="path1305"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6559.3259,636.145 -53.795,0"
+     id="path1307"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6473.0509,636.145 -53.795,0"
+     id="path1309"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6385.7609,636.145 -53.795,0"
+     id="path1311"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6299.4859,636.145 -53.795,0"
+     id="path1313"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6213.2109,636.145 -54.81,0"
+     id="path1315"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6125.9209,636.145 -53.795,0"
+     id="path1317"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 6039.6459,636.145 -53.795,0"
+     id="path1319"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5952.3559,636.145 -53.795,0"
+     id="path1321"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5866.0809,636.145 -53.795,0"
+     id="path1323"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5778.7909,636.145 -53.795,0"
+     id="path1325"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5692.5159,636.145 -53.795,0"
+     id="path1327"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5606.2409,636.145 -54.81,0"
+     id="path1329"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5518.9509,636.145 -53.795,0"
+     id="path1331"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5432.6759,636.145 -53.795,0"
+     id="path1333"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5345.3859,636.145 -53.795,0"
+     id="path1335"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5259.1109,636.145 -53.795,0"
+     id="path1337"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5171.8209,636.145 -53.795,0"
+     id="path1339"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 5085.5459,636.145 -53.795,0"
+     id="path1341"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4999.2709,636.145 -54.81,0"
+     id="path1343"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4911.9809,636.145 -53.795,0"
+     id="path1345"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4825.7059,636.145 -53.795,0"
+     id="path1347"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4738.4159,636.145 -53.795,0"
+     id="path1349"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4652.1409,636.145 -53.795,0"
+     id="path1351"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4564.8509,636.145 -53.795,0"
+     id="path1353"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4478.5759,636.145 -53.795,0"
+     id="path1355"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4392.3009,636.145 -54.81,0"
+     id="path1357"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4305.0109,636.145 -53.795,0"
+     id="path1359"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4218.7359,636.145 -53.795,0"
+     id="path1361"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4131.4459,636.145 -53.795,0"
+     id="path1363"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 4045.1709,636.145 -53.795,0"
+     id="path1365"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3957.8809,636.145 -53.795,0"
+     id="path1367"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3871.6059,636.145 -53.795,0"
+     id="path1369"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3785.3309,636.145 -54.81,0"
+     id="path1371"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3698.0409,636.145 -53.795,0"
+     id="path1373"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3611.7659,636.145 -53.795,0"
+     id="path1375"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3524.4759,636.145 -53.795,0"
+     id="path1377"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3438.2009,636.145 -53.795,0"
+     id="path1379"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3350.9109,636.145 -53.795,0"
+     id="path1381"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3264.6359,636.145 -53.795,0"
+     id="path1383"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3177.3459,636.145 -53.795,0"
+     id="path1385"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3091.0709,636.145 -53.795,0"
+     id="path1387"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 3004.7959,636.145 -53.795,0"
+     id="path1389"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2917.5059,636.145 -53.795,0"
+     id="path1391"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2831.2309,636.145 -53.795,0"
+     id="path1393"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2743.9409,636.145 -53.795,0"
+     id="path1395"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2657.6659,636.145 -53.795,0"
+     id="path1397"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2570.3759,636.145 -53.795,0"
+     id="path1399"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2484.1009,636.145 -53.795,0"
+     id="path1401"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2397.8259,636.145 -53.795,0"
+     id="path1403"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2310.5359,636.145 -53.795,0"
+     id="path1405"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2224.2609,636.145 -53.795,0"
+     id="path1407"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2136.9709,636.145 -53.795,0"
+     id="path1409"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 2050.6959,636.145 -53.795,0"
+     id="path1411"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1963.4059,636.145 -53.795,0"
+     id="path1413"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1877.1309,636.145 -53.795,0"
+     id="path1415"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1790.8559,636.145 -54.81,0"
+     id="path1417"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1703.5659,636.145 -53.795,0"
+     id="path1419"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1617.2909,636.145 -53.795,0"
+     id="path1421"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1530.0009,636.145 -53.795,0"
+     id="path1423"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1443.7259,636.145 -53.795,0"
+     id="path1425"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1356.4359,636.145 -53.795,0"
+     id="path1427"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1270.1609,636.145 -53.795,0"
+     id="path1429"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1183.8859,636.145 -54.81,0"
+     id="path1431"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1096.5959,636.145 -53.795,0"
+     id="path1433"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 1010.3209,636.145 -53.795,0"
+     id="path1435"
+     inkscape:connector-curvature="0" /><path
+     style="fill:none;stroke:#3465af;stroke-width:28.432024"
+     d="m 923.0309,636.145 -53.795,0"
+     id="path1437"
+     inkscape:connector-curvature="0" /><g
+     id="g4044"><rect
+       height="1100.7"
+       width="1213.6"
+       y="4753.1133"
+       x="21109.146"
+       id="rect1441"
+       style="fill:#f3e777" /><path
+       d="m 20656.146,5536.413 0,-405.46 150.7,-169.16 c 82.886,-93.039 170.53,-186.62 194.77,-207.96 l 44.069,-38.798 783.23,-0.086 783.23,-0.086 0,613.5 0,613.5 -978,0 -978,0 0,-405.46 z m 1027.7,136.98 0,-78.372 -169.91,4.925 -169.91,4.9249 -5.09,45.854 c -8.249,74.303 46.711,101.04 207.69,101.04 l 137.21,0 0,-78.372 z m 235.86,-262.94 4.495,-341.31 207.2,-8.6408 207.2,-8.6408 5.144,-46.443 c 9.596,-86.615 -41.863,-102.05 -322.02,-96.607 l -246.71,4.7956 -4.438,419.08 -4.439,419.08 74.537,0 74.538,0 4.494,-341.31 z m 391.3,313.72 c 26.41,-19.286 36.255,-41.399 32.697,-73.447 l -5.09,-45.854 -174.05,0 -174.05,0 -5.38,48.984 c -9.97,90.771 0.993,97.91 150.36,97.91 99.305,0 148.27,-7.6982 175.52,-27.594 z m -627.16,-274.84 0,-77.768 -174.05,0 -174.05,0 0,66.246 c 0,36.436 4.973,71.431 11.051,77.768 6.078,6.3366 84.401,11.521 174.05,11.521 l 163,0 0,-77.768 z m 659.89,-4.9154 5.125,-74.042 -179.18,4.9155 -179.18,4.9155 -5.38,48.984 c -10.473,95.348 -2.259,99.57 183.28,94.197 l 170.2,-4.9284 5.125,-74.042 z m -659.89,-237.63 0,-78.372 -169.91,4.925 -169.91,4.925 -5.097,73.447 -5.097,73.447 175,0 175,0 0,-78.372 z m 659.86,4.925 -5.097,-73.447 -174.05,0 -174.05,0 -5.38,48.984 c -10.289,93.673 -2.146,97.91 188.15,97.91 l 175.52,0 -5.097,-73.447 z m -659.86,-228.98 0,-77.768 -137.21,0 c -97.358,0 -147.91,7.8138 -174.05,26.902 -34.952,25.523 -49.645,92.242 -25.79,117.11 6.078,6.3366 84.401,11.521 174.05,11.521 l 163,0 0,-77.768 z"
+       id="path1443"
+       inkscape:connector-curvature="0"
+       style="fill:#ca4677" /></g><text
+     style="font-size:9.10937119px;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"
+     class="TextShape"
+     id="text1489"
+     transform="scale(1.1035537,0.9061634)"
+     x="171.41566"
+     y="9913.7109"><tspan
+       font-size="635px"
+       font-weight="400"
+       class="TextParagraph"
+       id="tspan1491"
+       style="font-weight:400;font-size:482.03753662px;font-family:'Times New Roman', serif" /></text>
+<g
+     id="g4048"><rect
+       height="2342.4341"
+       width="2320.7097"
+       y="13737.451"
+       x="18796.941"
+       id="rect1447"
+       style="fill:#6076b3" /><rect
+       id="rect1451"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="13817.405"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1453"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="14075.544"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1455"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="14334.443"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1457"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="14592.582"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1459"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="14850.721"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1461"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="15109.62"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1463"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="15367.759"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1465"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="15625.896"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1467"
+       height="137.78799"
+       x="18532.135"
+       width="302.70312"
+       y="15884.035"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1469"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="13783.14"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1471"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="14041.277"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1473"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="14299.416"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1475"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="14558.315"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1477"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="14816.454"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1479"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="15074.593"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1481"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="15333.492"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1483"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="15591.631"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><rect
+       id="rect1485"
+       height="137.78799"
+       x="21080.053"
+       width="302.70312"
+       y="15849.769"
+       style="fill:#e0ee2c;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><text
+       transform="scale(1.1035537,0.9061634)"
+       sodipodi:linespacing="125%"
+       id="text1493"
+       line-height="125%"
+       x="17205.688"
+       y="16777.641"
+       font-size="1128.9px"
+       xml:space="preserve"
+       style="font-size:856.96411133px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><tspan
+         id="tspan1495"
+         x="17205.688"
+         y="16777.641">CPU</tspan></text>
+</g><text
+     style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"
+     id="text1499"
+     class="TextShape"
+     x="-11700.553"
+     y="565.61298"><tspan
+       style="font-weight:400;font-size:706px;font-family:'Times New Roman', serif"
+       id="tspan1501"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="706px"><tspan
+         id="tspan1503"
+         transform="matrix(0,-1,1,0,8509,40173)"
+         class="TextPosition"
+         x="12640.447"
+         y="16397.613"><tspan
+           style="fill:#000000"
+           id="tspan1505">PCI, USB, SPI, I2C, ...</tspan></tspan></tspan></text>
+<path
+     d="m 12408.066,15561.578 -1115.084,0 0,-1420.331 2230.169,0 0,1420.331 -1115.085,0 z"
+     id="path1511"
+     inkscape:connector-curvature="0"
+     style="fill:#cfe7f5;fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round" /><path
+     d="m 12408.066,15561.578 -1115.084,0 0,-1420.331 2230.169,0 0,1420.331 -1115.085,0 z"
+     id="path1513"
+     inkscape:connector-curvature="0"
+     style="fill:none;fill-rule:evenodd;stroke:#3465af;stroke-width:19.84712601;stroke-linejoin:round" /><text
+     style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"
+     id="text1515"
+     class="TextShape"
+     x="-1394.0863"
+     y="590.73016"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan1517"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan1519"
+         class="TextPosition"
+         x="11487.915"
+         y="14672.743"><tspan
+           style="fill:#000000"
+           id="tspan1521">Bridge</tspan></tspan></tspan></text>
+<text
+     style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"
+     id="text1523"
+     class="TextShape"
+     x="-1450.5308"
+     y="1324.5078"><tspan
+       style="font-weight:400;font-size:635px;font-family:'Times New Roman', serif"
+       id="tspan1525"
+       class="TextParagraph"
+       font-weight="400"
+       font-size="635px"><tspan
+         id="tspan1527"
+         class="TextPosition"
+         x="11431.471"
+         y="15406.52"><tspan
+           style="fill:#000000"
+           id="tspan1529"> DMA</tspan></tspan></tspan></text>
+</svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-close.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-close.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-close.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-close.rst	2017-02-12 16:03:20.000000000 -0500
@@ -33,11 +33,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 Closes the cec device. Resources associated with the file descriptor are
 freed. The device configuration remain unchanged.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-ioctl.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-ioctl.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-ioctl.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-ioctl.rst	2017-02-12 16:03:20.000000000 -0500
@@ -39,11 +39,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 The :c:func:`ioctl()` function manipulates cec device parameters. The
 argument ``fd`` must be an open file descriptor.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-open.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-open.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-open.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-open.rst	2017-02-12 16:03:20.000000000 -0500
@@ -46,11 +46,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To open a cec device applications call :c:func:`open()` with the
 desired device name. The function has no side effects; the device
 configuration remain unchanged.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-poll.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-poll.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-func-poll.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-func-poll.rst	2017-02-12 16:03:20.000000000 -0500
@@ -39,11 +39,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 With the :c:func:`poll()` function applications can wait for CEC
 events.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-intro.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-intro.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-intro.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-intro.rst	2017-02-12 16:03:20.000000000 -0500
@@ -3,11 +3,6 @@
 Introduction
 ============
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 HDMI connectors provide a single pin for use by the Consumer Electronics
 Control protocol. This protocol allows different devices connected by an
 HDMI cable to communicate. The protocol for CEC version 1.4 is defined
@@ -31,3 +26,15 @@ control just the CEC pin.
 Drivers that support CEC will create a CEC device node (/dev/cecX) to
 give userspace access to the CEC adapter. The
 :ref:`CEC_ADAP_G_CAPS` ioctl will tell userspace what it is allowed to do.
+
+In order to check the support and test it, it is suggested to download
+the `v4l-utils <https://git.linuxtv.org/v4l-utils.git/>`_ package. It
+provides three tools to handle CEC:
+
+- cec-ctl: the Swiss army knife of CEC. Allows you to configure, transmit
+  and monitor CEC messages.
+
+- cec-compliance: does a CEC compliance test of a remote CEC device to
+  determine how compliant the CEC implementation is.
+
+- cec-follower: emulates a CEC follower.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-caps.rst	2017-02-12 16:03:20.000000000 -0500
@@ -29,11 +29,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 All cec devices must support :ref:`ioctl CEC_ADAP_G_CAPS <CEC_ADAP_G_CAPS>`. To query
 device information, applications call the ioctl with a pointer to a
 struct :c:type:`cec_caps`. The driver fills the structure and
@@ -48,41 +43,21 @@ returns the information to the applicati
     :stub-columns: 0
     :widths:       1 1 16
 
-
-    -  .. row 1
-
-       -  char
-
-       -  ``driver[32]``
-
-       -  The name of the cec adapter driver.
-
-    -  .. row 2
-
-       -  char
-
-       -  ``name[32]``
-
-       -  The name of this CEC adapter. The combination ``driver`` and
-	  ``name`` must be unique.
-
-    -  .. row 3
-
-       -  __u32
-
-       -  ``capabilities``
-
-       -  The capabilities of the CEC adapter, see
-	  :ref:`cec-capabilities`.
-
-    -  .. row 4
-
-       -  __u32
-
-       -  ``version``
-
-       -  CEC Framework API version, formatted with the ``KERNEL_VERSION()``
-	  macro.
+    * - char
+      - ``driver[32]``
+      - The name of the cec adapter driver.
+    * - char
+      - ``name[32]``
+      - The name of this CEC adapter. The combination ``driver`` and
+	``name`` must be unique.
+    * - __u32
+      - ``capabilities``
+      - The capabilities of the CEC adapter, see
+	:ref:`cec-capabilities`.
+    * - __u32
+      - ``version``
+      - CEC Framework API version, formatted with the ``KERNEL_VERSION()``
+	macro.
 
 
 .. tabularcolumns:: |p{4.4cm}|p{2.5cm}|p{10.6cm}|
@@ -94,68 +69,50 @@ returns the information to the applicati
     :stub-columns: 0
     :widths:       3 1 8
 
+    * .. _`CEC-CAP-PHYS-ADDR`:
 
-    -  .. _`CEC-CAP-PHYS-ADDR`:
-
-       -  ``CEC_CAP_PHYS_ADDR``
-
-       -  0x00000001
-
-       -  Userspace has to configure the physical address by calling
-	  :ref:`ioctl CEC_ADAP_S_PHYS_ADDR <CEC_ADAP_S_PHYS_ADDR>`. If
-	  this capability isn't set, then setting the physical address is
-	  handled by the kernel whenever the EDID is set (for an HDMI
-	  receiver) or read (for an HDMI transmitter).
-
-    -  .. _`CEC-CAP-LOG-ADDRS`:
-
-       -  ``CEC_CAP_LOG_ADDRS``
-
-       -  0x00000002
-
-       -  Userspace has to configure the logical addresses by calling
-	  :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`. If
-	  this capability isn't set, then the kernel will have configured
-	  this.
-
-    -  .. _`CEC-CAP-TRANSMIT`:
-
-       -  ``CEC_CAP_TRANSMIT``
-
-       -  0x00000004
-
-       -  Userspace can transmit CEC messages by calling
-	  :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`. This implies that
-	  userspace can be a follower as well, since being able to transmit
-	  messages is a prerequisite of becoming a follower. If this
-	  capability isn't set, then the kernel will handle all CEC
-	  transmits and process all CEC messages it receives.
-
-    -  .. _`CEC-CAP-PASSTHROUGH`:
-
-       -  ``CEC_CAP_PASSTHROUGH``
-
-       -  0x00000008
-
-       -  Userspace can use the passthrough mode by calling
-	  :ref:`ioctl CEC_S_MODE <CEC_S_MODE>`.
-
-    -  .. _`CEC-CAP-RC`:
-
-       -  ``CEC_CAP_RC``
-
-       -  0x00000010
+      - ``CEC_CAP_PHYS_ADDR``
+      - 0x00000001
+      - Userspace has to configure the physical address by calling
+	:ref:`ioctl CEC_ADAP_S_PHYS_ADDR <CEC_ADAP_S_PHYS_ADDR>`. If
+	this capability isn't set, then setting the physical address is
+	handled by the kernel whenever the EDID is set (for an HDMI
+	receiver) or read (for an HDMI transmitter).
+    * .. _`CEC-CAP-LOG-ADDRS`:
 
-       -  This adapter supports the remote control protocol.
+      - ``CEC_CAP_LOG_ADDRS``
+      - 0x00000002
+      - Userspace has to configure the logical addresses by calling
+	:ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`. If
+	this capability isn't set, then the kernel will have configured
+	this.
+    * .. _`CEC-CAP-TRANSMIT`:
 
-    -  .. _`CEC-CAP-MONITOR-ALL`:
+      - ``CEC_CAP_TRANSMIT``
+      - 0x00000004
+      - Userspace can transmit CEC messages by calling
+	:ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`. This implies that
+	userspace can be a follower as well, since being able to transmit
+	messages is a prerequisite of becoming a follower. If this
+	capability isn't set, then the kernel will handle all CEC
+	transmits and process all CEC messages it receives.
+    * .. _`CEC-CAP-PASSTHROUGH`:
 
-       -  ``CEC_CAP_MONITOR_ALL``
+      - ``CEC_CAP_PASSTHROUGH``
+      - 0x00000008
+      - Userspace can use the passthrough mode by calling
+	:ref:`ioctl CEC_S_MODE <CEC_S_MODE>`.
+    * .. _`CEC-CAP-RC`:
 
-       -  0x00000020
+      - ``CEC_CAP_RC``
+      - 0x00000010
+      - This adapter supports the remote control protocol.
+    * .. _`CEC-CAP-MONITOR-ALL`:
 
-       -  The CEC hardware can monitor all messages, not just directed and
-	  broadcast messages.
+      - ``CEC_CAP_MONITOR_ALL``
+      - 0x00000020
+      - The CEC hardware can monitor all messages, not just directed and
+	broadcast messages.
 
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-log-addrs.rst	2017-02-12 16:03:20.000000000 -0500
@@ -35,11 +35,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To query the current CEC logical addresses, applications call
 :ref:`ioctl CEC_ADAP_G_LOG_ADDRS <CEC_ADAP_G_LOG_ADDRS>` with a pointer to a
 struct :c:type:`cec_log_addrs` where the driver stores the logical addresses.
@@ -77,134 +72,79 @@ logical address types are already define
     :stub-columns: 0
     :widths:       1 1 16
 
-
-    -  .. row 1
-
-       -  __u8
-
-       -  ``log_addr[CEC_MAX_LOG_ADDRS]``
-
-       -  The actual logical addresses that were claimed. This is set by the
-	  driver. If no logical address could be claimed, then it is set to
-	  ``CEC_LOG_ADDR_INVALID``. If this adapter is Unregistered, then
-	  ``log_addr[0]`` is set to 0xf and all others to
-	  ``CEC_LOG_ADDR_INVALID``.
-
-    -  .. row 2
-
-       -  __u16
-
-       -  ``log_addr_mask``
-
-       -  The bitmask of all logical addresses this adapter has claimed. If
-	  this adapter is Unregistered then ``log_addr_mask`` sets bit 15
-	  and clears all other bits. If this adapter is not configured at
-	  all, then ``log_addr_mask`` is set to 0. Set by the driver.
-
-    -  .. row 3
-
-       -  __u8
-
-       -  ``cec_version``
-
-       -  The CEC version that this adapter shall use. See
-	  :ref:`cec-versions`. Used to implement the
-	  ``CEC_MSG_CEC_VERSION`` and ``CEC_MSG_REPORT_FEATURES`` messages.
-	  Note that :ref:`CEC_OP_CEC_VERSION_1_3A <CEC-OP-CEC-VERSION-1-3A>` is not allowed by the CEC
-	  framework.
-
-    -  .. row 4
-
-       -  __u8
-
-       -  ``num_log_addrs``
-
-       -  Number of logical addresses to set up. Must be ≤
-	  ``available_log_addrs`` as returned by
-	  :ref:`CEC_ADAP_G_CAPS`. All arrays in
-	  this structure are only filled up to index
-	  ``available_log_addrs``-1. The remaining array elements will be
-	  ignored. Note that the CEC 2.0 standard allows for a maximum of 2
-	  logical addresses, although some hardware has support for more.
-	  ``CEC_MAX_LOG_ADDRS`` is 4. The driver will return the actual
-	  number of logical addresses it could claim, which may be less than
-	  what was requested. If this field is set to 0, then the CEC
-	  adapter shall clear all claimed logical addresses and all other
-	  fields will be ignored.
-
-    -  .. row 5
-
-       -  __u32
-
-       -  ``vendor_id``
-
-       -  The vendor ID is a 24-bit number that identifies the specific
-	  vendor or entity. Based on this ID vendor specific commands may be
-	  defined. If you do not want a vendor ID then set it to
-	  ``CEC_VENDOR_ID_NONE``.
-
-    -  .. row 6
-
-       -  __u32
-
-       -  ``flags``
-
-       -  Flags. See :ref:`cec-log-addrs-flags` for a list of available flags.
-
-    -  .. row 7
-
-       -  char
-
-       -  ``osd_name[15]``
-
-       -  The On-Screen Display name as is returned by the
-	  ``CEC_MSG_SET_OSD_NAME`` message.
-
-    -  .. row 8
-
-       -  __u8
-
-       -  ``primary_device_type[CEC_MAX_LOG_ADDRS]``
-
-       -  Primary device type for each logical address. See
-	  :ref:`cec-prim-dev-types` for possible types.
-
-    -  .. row 9
-
-       -  __u8
-
-       -  ``log_addr_type[CEC_MAX_LOG_ADDRS]``
-
-       -  Logical address types. See :ref:`cec-log-addr-types` for
-	  possible types. The driver will update this with the actual
-	  logical address type that it claimed (e.g. it may have to fallback
-	  to :ref:`CEC_LOG_ADDR_TYPE_UNREGISTERED <CEC-LOG-ADDR-TYPE-UNREGISTERED>`).
-
-    -  .. row 10
-
-       -  __u8
-
-       -  ``all_device_types[CEC_MAX_LOG_ADDRS]``
-
-       -  CEC 2.0 specific: the bit mask of all device types. See
-	  :ref:`cec-all-dev-types-flags`. It is used in the CEC 2.0
-	  ``CEC_MSG_REPORT_FEATURES`` message. For CEC 1.4 you can either leave
-	  this field to 0, or fill it in according to the CEC 2.0 guidelines to
-	  give the CEC framework more information about the device type, even
-	  though the framework won't use it directly in the CEC message.
-
-    -  .. row 11
-
-       -  __u8
-
-       -  ``features[CEC_MAX_LOG_ADDRS][12]``
-
-       -  Features for each logical address. It is used in the CEC 2.0
-	  ``CEC_MSG_REPORT_FEATURES`` message. The 12 bytes include both the
-	  RC Profile and the Device Features. For CEC 1.4 you can either leave
-          this field to all 0, or fill it in according to the CEC 2.0 guidelines to
-          give the CEC framework more information about the device type, even
-          though the framework won't use it directly in the CEC message.
+    * - __u8
+      - ``log_addr[CEC_MAX_LOG_ADDRS]``
+      - The actual logical addresses that were claimed. This is set by the
+	driver. If no logical address could be claimed, then it is set to
+	``CEC_LOG_ADDR_INVALID``. If this adapter is Unregistered, then
+	``log_addr[0]`` is set to 0xf and all others to
+	``CEC_LOG_ADDR_INVALID``.
+    * - __u16
+      - ``log_addr_mask``
+      - The bitmask of all logical addresses this adapter has claimed. If
+	this adapter is Unregistered then ``log_addr_mask`` sets bit 15
+	and clears all other bits. If this adapter is not configured at
+	all, then ``log_addr_mask`` is set to 0. Set by the driver.
+    * - __u8
+      - ``cec_version``
+      - The CEC version that this adapter shall use. See
+	:ref:`cec-versions`. Used to implement the
+	``CEC_MSG_CEC_VERSION`` and ``CEC_MSG_REPORT_FEATURES`` messages.
+	Note that :ref:`CEC_OP_CEC_VERSION_1_3A <CEC-OP-CEC-VERSION-1-3A>` is not allowed by the CEC
+	framework.
+    * - __u8
+      - ``num_log_addrs``
+      - Number of logical addresses to set up. Must be ≤
+	``available_log_addrs`` as returned by
+	:ref:`CEC_ADAP_G_CAPS`. All arrays in
+	this structure are only filled up to index
+	``available_log_addrs``-1. The remaining array elements will be
+	ignored. Note that the CEC 2.0 standard allows for a maximum of 2
+	logical addresses, although some hardware has support for more.
+	``CEC_MAX_LOG_ADDRS`` is 4. The driver will return the actual
+	number of logical addresses it could claim, which may be less than
+	what was requested. If this field is set to 0, then the CEC
+	adapter shall clear all claimed logical addresses and all other
+	fields will be ignored.
+    * - __u32
+      - ``vendor_id``
+      - The vendor ID is a 24-bit number that identifies the specific
+	vendor or entity. Based on this ID vendor specific commands may be
+	defined. If you do not want a vendor ID then set it to
+	``CEC_VENDOR_ID_NONE``.
+    * - __u32
+      - ``flags``
+      - Flags. See :ref:`cec-log-addrs-flags` for a list of available flags.
+    * - char
+      - ``osd_name[15]``
+      - The On-Screen Display name as is returned by the
+	``CEC_MSG_SET_OSD_NAME`` message.
+    * - __u8
+      - ``primary_device_type[CEC_MAX_LOG_ADDRS]``
+      - Primary device type for each logical address. See
+	:ref:`cec-prim-dev-types` for possible types.
+    * - __u8
+      - ``log_addr_type[CEC_MAX_LOG_ADDRS]``
+      - Logical address types. See :ref:`cec-log-addr-types` for
+	possible types. The driver will update this with the actual
+	logical address type that it claimed (e.g. it may have to fallback
+	to :ref:`CEC_LOG_ADDR_TYPE_UNREGISTERED <CEC-LOG-ADDR-TYPE-UNREGISTERED>`).
+    * - __u8
+      - ``all_device_types[CEC_MAX_LOG_ADDRS]``
+      - CEC 2.0 specific: the bit mask of all device types. See
+	:ref:`cec-all-dev-types-flags`. It is used in the CEC 2.0
+	``CEC_MSG_REPORT_FEATURES`` message. For CEC 1.4 you can either leave
+	this field to 0, or fill it in according to the CEC 2.0 guidelines to
+	give the CEC framework more information about the device type, even
+	though the framework won't use it directly in the CEC message.
+    * - __u8
+      - ``features[CEC_MAX_LOG_ADDRS][12]``
+      - Features for each logical address. It is used in the CEC 2.0
+	``CEC_MSG_REPORT_FEATURES`` message. The 12 bytes include both the
+	RC Profile and the Device Features. For CEC 1.4 you can either leave
+        this field to all 0, or fill it in according to the CEC 2.0 guidelines to
+        give the CEC framework more information about the device type, even
+        though the framework won't use it directly in the CEC message.
 
 .. _cec-log-addrs-flags:
 
@@ -213,17 +153,33 @@ logical address types are already define
     :stub-columns: 0
     :widths:       3 1 4
 
+    * .. _`CEC-LOG-ADDRS-FL-ALLOW-UNREG-FALLBACK`:
 
-    -  .. _`CEC-LOG-ADDRS-FL-ALLOW-UNREG-FALLBACK`:
+      - ``CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK``
+      - 1
+      - By default if no logical address of the requested type can be claimed, then
+	it will go back to the unconfigured state. If this flag is set, then it will
+	fallback to the Unregistered logical address. Note that if the Unregistered
+	logical address was explicitly requested, then this flag has no effect.
+    * .. _`CEC-LOG-ADDRS-FL-ALLOW-RC-PASSTHRU`:
 
-       -  ``CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK``
+      - ``CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU``
+      - 2
+      - By default the ``CEC_MSG_USER_CONTROL_PRESSED`` and ``CEC_MSG_USER_CONTROL_RELEASED``
+        messages are only passed on to the follower(s), if any. If this flag is set,
+	then these messages are also passed on to the remote control input subsystem
+	and will appear as keystrokes. This features needs to be enabled explicitly.
+	If CEC is used to enter e.g. passwords, then you may not want to enable this
+	to avoid trivial snooping of the keystrokes.
+    * .. _`CEC-LOG-ADDRS-FL-CDC-ONLY`:
 
-       -  1
+      - `CEC_LOG_ADDRS_FL_CDC_ONLY`
+      - 4
+      - If this flag is set, then the device is CDC-Only. CDC-Only CEC devices
+	are CEC devices that can only handle CDC messages.
+
+	All other messages are ignored.
 
-       -  By default if no logical address of the requested type can be claimed, then
-	  it will go back to the unconfigured state. If this flag is set, then it will
-	  fallback to the Unregistered logical address. Note that if the Unregistered
-	  logical address was explicitly requested, then this flag has no effect.
 
 .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
 
@@ -234,30 +190,21 @@ logical address types are already define
     :stub-columns: 0
     :widths:       3 1 4
 
+    * .. _`CEC-OP-CEC-VERSION-1-3A`:
 
-    -  .. _`CEC-OP-CEC-VERSION-1-3A`:
-
-       -  ``CEC_OP_CEC_VERSION_1_3A``
-
-       -  4
-
-       -  CEC version according to the HDMI 1.3a standard.
-
-    -  .. _`CEC-OP-CEC-VERSION-1-4B`:
-
-       -  ``CEC_OP_CEC_VERSION_1_4B``
-
-       -  5
-
-       -  CEC version according to the HDMI 1.4b standard.
-
-    -  .. _`CEC-OP-CEC-VERSION-2-0`:
-
-       -  ``CEC_OP_CEC_VERSION_2_0``
+      - ``CEC_OP_CEC_VERSION_1_3A``
+      - 4
+      - CEC version according to the HDMI 1.3a standard.
+    * .. _`CEC-OP-CEC-VERSION-1-4B`:
 
-       -  6
+      - ``CEC_OP_CEC_VERSION_1_4B``
+      - 5
+      - CEC version according to the HDMI 1.4b standard.
+    * .. _`CEC-OP-CEC-VERSION-2-0`:
 
-       -  CEC version according to the HDMI 2.0 standard.
+      - ``CEC_OP_CEC_VERSION_2_0``
+      - 6
+      - CEC version according to the HDMI 2.0 standard.
 
 
 .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
@@ -269,62 +216,41 @@ logical address types are already define
     :stub-columns: 0
     :widths:       3 1 4
 
+    * .. _`CEC-OP-PRIM-DEVTYPE-TV`:
 
-    -  .. _`CEC-OP-PRIM-DEVTYPE-TV`:
-
-       -  ``CEC_OP_PRIM_DEVTYPE_TV``
-
-       -  0
-
-       -  Use for a TV.
-
-    -  .. _`CEC-OP-PRIM-DEVTYPE-RECORD`:
-
-       -  ``CEC_OP_PRIM_DEVTYPE_RECORD``
-
-       -  1
-
-       -  Use for a recording device.
-
-    -  .. _`CEC-OP-PRIM-DEVTYPE-TUNER`:
-
-       -  ``CEC_OP_PRIM_DEVTYPE_TUNER``
-
-       -  3
-
-       -  Use for a device with a tuner.
-
-    -  .. _`CEC-OP-PRIM-DEVTYPE-PLAYBACK`:
-
-       -  ``CEC_OP_PRIM_DEVTYPE_PLAYBACK``
-
-       -  4
-
-       -  Use for a playback device.
-
-    -  .. _`CEC-OP-PRIM-DEVTYPE-AUDIOSYSTEM`:
-
-       -  ``CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM``
-
-       -  5
-
-       -  Use for an audio system (e.g. an audio/video receiver).
-
-    -  .. _`CEC-OP-PRIM-DEVTYPE-SWITCH`:
-
-       -  ``CEC_OP_PRIM_DEVTYPE_SWITCH``
+      - ``CEC_OP_PRIM_DEVTYPE_TV``
+      - 0
+      - Use for a TV.
+    * .. _`CEC-OP-PRIM-DEVTYPE-RECORD`:
 
-       -  6
+      - ``CEC_OP_PRIM_DEVTYPE_RECORD``
+      - 1
+      - Use for a recording device.
+    * .. _`CEC-OP-PRIM-DEVTYPE-TUNER`:
 
-       -  Use for a CEC switch.
+      - ``CEC_OP_PRIM_DEVTYPE_TUNER``
+      - 3
+      - Use for a device with a tuner.
+    * .. _`CEC-OP-PRIM-DEVTYPE-PLAYBACK`:
 
-    -  .. _`CEC-OP-PRIM-DEVTYPE-VIDEOPROC`:
+      - ``CEC_OP_PRIM_DEVTYPE_PLAYBACK``
+      - 4
+      - Use for a playback device.
+    * .. _`CEC-OP-PRIM-DEVTYPE-AUDIOSYSTEM`:
 
-       -  ``CEC_OP_PRIM_DEVTYPE_VIDEOPROC``
+      - ``CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM``
+      - 5
+      - Use for an audio system (e.g. an audio/video receiver).
+    * .. _`CEC-OP-PRIM-DEVTYPE-SWITCH`:
 
-       -  7
+      - ``CEC_OP_PRIM_DEVTYPE_SWITCH``
+      - 6
+      - Use for a CEC switch.
+    * .. _`CEC-OP-PRIM-DEVTYPE-VIDEOPROC`:
 
-       -  Use for a video processor device.
+      - ``CEC_OP_PRIM_DEVTYPE_VIDEOPROC``
+      - 7
+      - Use for a video processor device.
 
 
 .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
@@ -336,64 +262,43 @@ logical address types are already define
     :stub-columns: 0
     :widths:       3 1 16
 
+    * .. _`CEC-LOG-ADDR-TYPE-TV`:
 
-    -  .. _`CEC-LOG-ADDR-TYPE-TV`:
-
-       -  ``CEC_LOG_ADDR_TYPE_TV``
-
-       -  0
-
-       -  Use for a TV.
-
-    -  .. _`CEC-LOG-ADDR-TYPE-RECORD`:
-
-       -  ``CEC_LOG_ADDR_TYPE_RECORD``
-
-       -  1
-
-       -  Use for a recording device.
-
-    -  .. _`CEC-LOG-ADDR-TYPE-TUNER`:
-
-       -  ``CEC_LOG_ADDR_TYPE_TUNER``
-
-       -  2
-
-       -  Use for a tuner device.
-
-    -  .. _`CEC-LOG-ADDR-TYPE-PLAYBACK`:
-
-       -  ``CEC_LOG_ADDR_TYPE_PLAYBACK``
-
-       -  3
-
-       -  Use for a playback device.
-
-    -  .. _`CEC-LOG-ADDR-TYPE-AUDIOSYSTEM`:
-
-       -  ``CEC_LOG_ADDR_TYPE_AUDIOSYSTEM``
-
-       -  4
-
-       -  Use for an audio system device.
-
-    -  .. _`CEC-LOG-ADDR-TYPE-SPECIFIC`:
-
-       -  ``CEC_LOG_ADDR_TYPE_SPECIFIC``
+      - ``CEC_LOG_ADDR_TYPE_TV``
+      - 0
+      - Use for a TV.
+    * .. _`CEC-LOG-ADDR-TYPE-RECORD`:
 
-       -  5
+      - ``CEC_LOG_ADDR_TYPE_RECORD``
+      - 1
+      - Use for a recording device.
+    * .. _`CEC-LOG-ADDR-TYPE-TUNER`:
 
-       -  Use for a second TV or for a video processor device.
+      - ``CEC_LOG_ADDR_TYPE_TUNER``
+      - 2
+      - Use for a tuner device.
+    * .. _`CEC-LOG-ADDR-TYPE-PLAYBACK`:
 
-    -  .. _`CEC-LOG-ADDR-TYPE-UNREGISTERED`:
+      - ``CEC_LOG_ADDR_TYPE_PLAYBACK``
+      - 3
+      - Use for a playback device.
+    * .. _`CEC-LOG-ADDR-TYPE-AUDIOSYSTEM`:
 
-       -  ``CEC_LOG_ADDR_TYPE_UNREGISTERED``
+      - ``CEC_LOG_ADDR_TYPE_AUDIOSYSTEM``
+      - 4
+      - Use for an audio system device.
+    * .. _`CEC-LOG-ADDR-TYPE-SPECIFIC`:
 
-       -  6
+      - ``CEC_LOG_ADDR_TYPE_SPECIFIC``
+      - 5
+      - Use for a second TV or for a video processor device.
+    * .. _`CEC-LOG-ADDR-TYPE-UNREGISTERED`:
 
-       -  Use this if you just want to remain unregistered. Used for pure
-	  CEC switches or CDC-only devices (CDC: Capability Discovery and
-	  Control).
+      - ``CEC_LOG_ADDR_TYPE_UNREGISTERED``
+      - 6
+      - Use this if you just want to remain unregistered. Used for pure
+	CEC switches or CDC-only devices (CDC: Capability Discovery and
+	Control).
 
 
 
@@ -406,54 +311,36 @@ logical address types are already define
     :stub-columns: 0
     :widths:       3 1 4
 
+    * .. _`CEC-OP-ALL-DEVTYPE-TV`:
 
-    -  .. _`CEC-OP-ALL-DEVTYPE-TV`:
-
-       -  ``CEC_OP_ALL_DEVTYPE_TV``
-
-       -  0x80
-
-       -  This supports the TV type.
-
-    -  .. _`CEC-OP-ALL-DEVTYPE-RECORD`:
-
-       -  ``CEC_OP_ALL_DEVTYPE_RECORD``
-
-       -  0x40
-
-       -  This supports the Recording type.
-
-    -  .. _`CEC-OP-ALL-DEVTYPE-TUNER`:
-
-       -  ``CEC_OP_ALL_DEVTYPE_TUNER``
-
-       -  0x20
-
-       -  This supports the Tuner type.
-
-    -  .. _`CEC-OP-ALL-DEVTYPE-PLAYBACK`:
-
-       -  ``CEC_OP_ALL_DEVTYPE_PLAYBACK``
-
-       -  0x10
-
-       -  This supports the Playback type.
-
-    -  .. _`CEC-OP-ALL-DEVTYPE-AUDIOSYSTEM`:
-
-       -  ``CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM``
-
-       -  0x08
+      - ``CEC_OP_ALL_DEVTYPE_TV``
+      - 0x80
+      - This supports the TV type.
+    * .. _`CEC-OP-ALL-DEVTYPE-RECORD`:
 
-       -  This supports the Audio System type.
+      - ``CEC_OP_ALL_DEVTYPE_RECORD``
+      - 0x40
+      - This supports the Recording type.
+    * .. _`CEC-OP-ALL-DEVTYPE-TUNER`:
 
-    -  .. _`CEC-OP-ALL-DEVTYPE-SWITCH`:
+      - ``CEC_OP_ALL_DEVTYPE_TUNER``
+      - 0x20
+      - This supports the Tuner type.
+    * .. _`CEC-OP-ALL-DEVTYPE-PLAYBACK`:
 
-       -  ``CEC_OP_ALL_DEVTYPE_SWITCH``
+      - ``CEC_OP_ALL_DEVTYPE_PLAYBACK``
+      - 0x10
+      - This supports the Playback type.
+    * .. _`CEC-OP-ALL-DEVTYPE-AUDIOSYSTEM`:
 
-       -  0x04
+      - ``CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM``
+      - 0x08
+      - This supports the Audio System type.
+    * .. _`CEC-OP-ALL-DEVTYPE-SWITCH`:
 
-       -  This supports the CEC Switch or Video Processing type.
+      - ``CEC_OP_ALL_DEVTYPE_SWITCH``
+      - 0x04
+      - This supports the CEC Switch or Video Processing type.
 
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-phys-addr.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-phys-addr.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-phys-addr.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-adap-g-phys-addr.rst	2017-02-12 16:03:20.000000000 -0500
@@ -35,11 +35,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To query the current physical address applications call
 :ref:`ioctl CEC_ADAP_G_PHYS_ADDR <CEC_ADAP_G_PHYS_ADDR>` with a pointer to a __u16 where the
 driver stores the physical address.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-dqevent.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-dqevent.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-dqevent.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-dqevent.rst	2017-02-12 16:03:20.000000000 -0500
@@ -30,11 +30,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 CEC devices can send asynchronous events. These can be retrieved by
 calling :c:func:`CEC_DQEVENT`. If the file descriptor is in
 non-blocking mode and no event is pending, then it will return -1 and
@@ -58,26 +53,16 @@ it is guaranteed that the state did chan
     :stub-columns: 0
     :widths:       1 1 8
 
-
-    -  .. row 1
-
-       -  __u16
-
-       -  ``phys_addr``
-
-       -  The current physical address. This is ``CEC_PHYS_ADDR_INVALID`` if no
+    * - __u16
+      - ``phys_addr``
+      - The current physical address. This is ``CEC_PHYS_ADDR_INVALID`` if no
           valid physical address is set.
-
-    -  .. row 2
-
-       -  __u16
-
-       -  ``log_addr_mask``
-
-       -  The current set of claimed logical addresses. This is 0 if no logical
-          addresses are claimed or if ``phys_addr`` is ``CEC_PHYS_ADDR_INVALID``.
-	  If bit 15 is set (``1 << CEC_LOG_ADDR_UNREGISTERED``) then this device
-	  has the unregistered logical address. In that case all other bits are 0.
+    * - __u16
+      - ``log_addr_mask``
+      - The current set of claimed logical addresses. This is 0 if no logical
+        addresses are claimed or if ``phys_addr`` is ``CEC_PHYS_ADDR_INVALID``.
+	If bit 15 is set (``1 << CEC_LOG_ADDR_UNREGISTERED``) then this device
+	has the unregistered logical address. In that case all other bits are 0.
 
 
 .. c:type:: cec_event_lost_msgs
@@ -89,22 +74,17 @@ it is guaranteed that the state did chan
     :stub-columns: 0
     :widths:       1 1 16
 
-
-    -  .. row 1
-
-       -  __u32
-
-       -  ``lost_msgs``
-
-       -  Set to the number of lost messages since the filehandle was opened
-	  or since the last time this event was dequeued for this
-	  filehandle. The messages lost are the oldest messages. So when a
-	  new message arrives and there is no more room, then the oldest
-	  message is discarded to make room for the new one. The internal
-	  size of the message queue guarantees that all messages received in
-	  the last two seconds will be stored. Since messages should be
-	  replied to within a second according to the CEC specification,
-	  this is more than enough.
+    * - __u32
+      - ``lost_msgs``
+      - Set to the number of lost messages since the filehandle was opened
+	or since the last time this event was dequeued for this
+	filehandle. The messages lost are the oldest messages. So when a
+	new message arrives and there is no more room, then the oldest
+	message is discarded to make room for the new one. The internal
+	size of the message queue guarantees that all messages received in
+	the last two seconds will be stored. Since messages should be
+	replied to within a second according to the CEC specification,
+	this is more than enough.
 
 
 .. tabularcolumns:: |p{1.0cm}|p{4.2cm}|p{2.5cm}|p{8.8cm}|
@@ -116,62 +96,32 @@ it is guaranteed that the state did chan
     :stub-columns: 0
     :widths:       1 1 1 8
 
+    * - __u64
+      - ``ts``
+      - :cspan:`1` Timestamp of the event in ns.
 
-    -  .. row 1
-
-       -  __u64
-
-       -  ``ts``
-
-       -  :cspan:`1` Timestamp of the event in ns.
-
-	  The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
-	  the same clock from userspace use :c:func:`clock_gettime`.
-
-    -  .. row 2
-
-       -  __u32
-
-       -  ``event``
-
-       -  :cspan:`1` The CEC event type, see :ref:`cec-events`.
-
-    -  .. row 3
-
-       -  __u32
-
-       -  ``flags``
-
-       -  :cspan:`1` Event flags, see :ref:`cec-event-flags`.
-
-    -  .. row 4
-
-       -  union
-
-       -  (anonymous)
-
-       -
-       -
-
-    -  .. row 5
-
-       -
-       -  struct cec_event_state_change
-
-       -  ``state_change``
-
-       -  The new adapter state as sent by the :ref:`CEC_EVENT_STATE_CHANGE <CEC-EVENT-STATE-CHANGE>`
-	  event.
-
-    -  .. row 6
-
-       -
-       -  struct cec_event_lost_msgs
-
-       -  ``lost_msgs``
-
-       -  The number of lost messages as sent by the :ref:`CEC_EVENT_LOST_MSGS <CEC-EVENT-LOST-MSGS>`
-	  event.
+	The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
+	the same clock from userspace use :c:func:`clock_gettime`.
+    * - __u32
+      - ``event``
+      - :cspan:`1` The CEC event type, see :ref:`cec-events`.
+    * - __u32
+      - ``flags``
+      - :cspan:`1` Event flags, see :ref:`cec-event-flags`.
+    * - union
+      - (anonymous)
+      -
+      -
+    * -
+      - struct cec_event_state_change
+      - ``state_change``
+      - The new adapter state as sent by the :ref:`CEC_EVENT_STATE_CHANGE <CEC-EVENT-STATE-CHANGE>`
+	event.
+    * -
+      - struct cec_event_lost_msgs
+      - ``lost_msgs``
+      - The number of lost messages as sent by the :ref:`CEC_EVENT_LOST_MSGS <CEC-EVENT-LOST-MSGS>`
+	event.
 
 
 .. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}|
@@ -183,25 +133,19 @@ it is guaranteed that the state did chan
     :stub-columns: 0
     :widths:       3 1 16
 
+    * .. _`CEC-EVENT-STATE-CHANGE`:
 
-    -  .. _`CEC-EVENT-STATE-CHANGE`:
-
-       -  ``CEC_EVENT_STATE_CHANGE``
-
-       -  1
-
-       -  Generated when the CEC Adapter's state changes. When open() is
-	  called an initial event will be generated for that filehandle with
-	  the CEC Adapter's state at that time.
-
-    -  .. _`CEC-EVENT-LOST-MSGS`:
-
-       -  ``CEC_EVENT_LOST_MSGS``
-
-       -  2
+      - ``CEC_EVENT_STATE_CHANGE``
+      - 1
+      - Generated when the CEC Adapter's state changes. When open() is
+	called an initial event will be generated for that filehandle with
+	the CEC Adapter's state at that time.
+    * .. _`CEC-EVENT-LOST-MSGS`:
 
-       -  Generated if one or more CEC messages were lost because the
-	  application didn't dequeue CEC messages fast enough.
+      - ``CEC_EVENT_LOST_MSGS``
+      - 2
+      - Generated if one or more CEC messages were lost because the
+	application didn't dequeue CEC messages fast enough.
 
 
 .. tabularcolumns:: |p{6.0cm}|p{0.6cm}|p{10.9cm}|
@@ -213,17 +157,14 @@ it is guaranteed that the state did chan
     :stub-columns: 0
     :widths:       3 1 8
 
+    * .. _`CEC-EVENT-FL-INITIAL-VALUE`:
 
-    -  .. _`CEC-EVENT-FL-INITIAL-VALUE`:
-
-       -  ``CEC_EVENT_FL_INITIAL_VALUE``
-
-       -  1
-
-       -  Set for the initial events that are generated when the device is
-	  opened. See the table above for which events do this. This allows
-	  applications to learn the initial state of the CEC adapter at
-	  open() time.
+      - ``CEC_EVENT_FL_INITIAL_VALUE``
+      - 1
+      - Set for the initial events that are generated when the device is
+	opened. See the table above for which events do this. This allows
+	applications to learn the initial state of the CEC adapter at
+	open() time.
 
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-g-mode.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-g-mode.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-g-mode.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-g-mode.rst	2017-02-12 16:03:20.000000000 -0500
@@ -31,11 +31,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 By default any filehandle can use :ref:`CEC_TRANSMIT`, but in order to prevent
 applications from stepping on each others toes it must be possible to
 obtain exclusive access to the CEC adapter. This ioctl sets the
@@ -83,37 +78,28 @@ Available initiator modes are:
     :stub-columns: 0
     :widths:       3 1 16
 
+    * .. _`CEC-MODE-NO-INITIATOR`:
 
-    -  .. _`CEC-MODE-NO-INITIATOR`:
-
-       -  ``CEC_MODE_NO_INITIATOR``
-
-       -  0x0
-
-       -  This is not an initiator, i.e. it cannot transmit CEC messages or
-	  make any other changes to the CEC adapter.
-
-    -  .. _`CEC-MODE-INITIATOR`:
-
-       -  ``CEC_MODE_INITIATOR``
-
-       -  0x1
-
-       -  This is an initiator (the default when the device is opened) and
-	  it can transmit CEC messages and make changes to the CEC adapter,
-	  unless there is an exclusive initiator.
-
-    -  .. _`CEC-MODE-EXCL-INITIATOR`:
-
-       -  ``CEC_MODE_EXCL_INITIATOR``
+      - ``CEC_MODE_NO_INITIATOR``
+      - 0x0
+      - This is not an initiator, i.e. it cannot transmit CEC messages or
+	make any other changes to the CEC adapter.
+    * .. _`CEC-MODE-INITIATOR`:
 
-       -  0x2
+      - ``CEC_MODE_INITIATOR``
+      - 0x1
+      - This is an initiator (the default when the device is opened) and
+	it can transmit CEC messages and make changes to the CEC adapter,
+	unless there is an exclusive initiator.
+    * .. _`CEC-MODE-EXCL-INITIATOR`:
 
-       -  This is an exclusive initiator and this file descriptor is the
-	  only one that can transmit CEC messages and make changes to the
-	  CEC adapter. If someone else is already the exclusive initiator
-	  then an attempt to become one will return the ``EBUSY`` error code
-	  error.
+      - ``CEC_MODE_EXCL_INITIATOR``
+      - 0x2
+      - This is an exclusive initiator and this file descriptor is the
+	only one that can transmit CEC messages and make changes to the
+	CEC adapter. If someone else is already the exclusive initiator
+	then an attempt to become one will return the ``EBUSY`` error code
+	error.
 
 
 Available follower modes are:
@@ -127,86 +113,68 @@ Available follower modes are:
     :stub-columns: 0
     :widths:       3 1 16
 
+    * .. _`CEC-MODE-NO-FOLLOWER`:
 
-    -  .. _`CEC-MODE-NO-FOLLOWER`:
-
-       -  ``CEC_MODE_NO_FOLLOWER``
-
-       -  0x00
-
-       -  This is not a follower (the default when the device is opened).
-
-    -  .. _`CEC-MODE-FOLLOWER`:
-
-       -  ``CEC_MODE_FOLLOWER``
-
-       -  0x10
-
-       -  This is a follower and it will receive CEC messages unless there
-	  is an exclusive follower. You cannot become a follower if
-	  :ref:`CEC_CAP_TRANSMIT <CEC-CAP-TRANSMIT>` is not set or if :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`
-	  was specified, the ``EINVAL`` error code is returned in that case.
-
-    -  .. _`CEC-MODE-EXCL-FOLLOWER`:
-
-       -  ``CEC_MODE_EXCL_FOLLOWER``
-
-       -  0x20
-
-       -  This is an exclusive follower and only this file descriptor will
-	  receive CEC messages for processing. If someone else is already
-	  the exclusive follower then an attempt to become one will return
-	  the ``EBUSY`` error code. You cannot become a follower if
-	  :ref:`CEC_CAP_TRANSMIT <CEC-CAP-TRANSMIT>` is not set or if :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`
-	  was specified, the ``EINVAL`` error code is returned in that case.
-
-    -  .. _`CEC-MODE-EXCL-FOLLOWER-PASSTHRU`:
-
-       -  ``CEC_MODE_EXCL_FOLLOWER_PASSTHRU``
-
-       -  0x30
-
-       -  This is an exclusive follower and only this file descriptor will
-	  receive CEC messages for processing. In addition it will put the
-	  CEC device into passthrough mode, allowing the exclusive follower
-	  to handle most core messages instead of relying on the CEC
-	  framework for that. If someone else is already the exclusive
-	  follower then an attempt to become one will return the ``EBUSY`` error
-	  code. You cannot become a follower if :ref:`CEC_CAP_TRANSMIT <CEC-CAP-TRANSMIT>`
-	  is not set or if :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>` was specified,
-	  the ``EINVAL`` error code is returned in that case.
-
-    -  .. _`CEC-MODE-MONITOR`:
-
-       -  ``CEC_MODE_MONITOR``
-
-       -  0xe0
+      - ``CEC_MODE_NO_FOLLOWER``
+      - 0x00
+      - This is not a follower (the default when the device is opened).
+    * .. _`CEC-MODE-FOLLOWER`:
 
-       -  Put the file descriptor into monitor mode. Can only be used in
-	  combination with :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`, otherwise EINVAL error
-	  code will be returned. In monitor mode all messages this CEC
-	  device transmits and all messages it receives (both broadcast
-	  messages and directed messages for one its logical addresses) will
-	  be reported. This is very useful for debugging. This is only
-	  allowed if the process has the ``CAP_NET_ADMIN`` capability. If
-	  that is not set, then the ``EPERM`` error code is returned.
+      - ``CEC_MODE_FOLLOWER``
+      - 0x10
+      - This is a follower and it will receive CEC messages unless there
+	is an exclusive follower. You cannot become a follower if
+	:ref:`CEC_CAP_TRANSMIT <CEC-CAP-TRANSMIT>` is not set or if :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`
+	was specified, the ``EINVAL`` error code is returned in that case.
+    * .. _`CEC-MODE-EXCL-FOLLOWER`:
 
-    -  .. _`CEC-MODE-MONITOR-ALL`:
+      - ``CEC_MODE_EXCL_FOLLOWER``
+      - 0x20
+      - This is an exclusive follower and only this file descriptor will
+	receive CEC messages for processing. If someone else is already
+	the exclusive follower then an attempt to become one will return
+	the ``EBUSY`` error code. You cannot become a follower if
+	:ref:`CEC_CAP_TRANSMIT <CEC-CAP-TRANSMIT>` is not set or if :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`
+	was specified, the ``EINVAL`` error code is returned in that case.
+    * .. _`CEC-MODE-EXCL-FOLLOWER-PASSTHRU`:
 
-       -  ``CEC_MODE_MONITOR_ALL``
+      - ``CEC_MODE_EXCL_FOLLOWER_PASSTHRU``
+      - 0x30
+      - This is an exclusive follower and only this file descriptor will
+	receive CEC messages for processing. In addition it will put the
+	CEC device into passthrough mode, allowing the exclusive follower
+	to handle most core messages instead of relying on the CEC
+	framework for that. If someone else is already the exclusive
+	follower then an attempt to become one will return the ``EBUSY`` error
+	code. You cannot become a follower if :ref:`CEC_CAP_TRANSMIT <CEC-CAP-TRANSMIT>`
+	is not set or if :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>` was specified,
+	the ``EINVAL`` error code is returned in that case.
+    * .. _`CEC-MODE-MONITOR`:
 
-       -  0xf0
+      - ``CEC_MODE_MONITOR``
+      - 0xe0
+      - Put the file descriptor into monitor mode. Can only be used in
+	combination with :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`, otherwise EINVAL error
+	code will be returned. In monitor mode all messages this CEC
+	device transmits and all messages it receives (both broadcast
+	messages and directed messages for one its logical addresses) will
+	be reported. This is very useful for debugging. This is only
+	allowed if the process has the ``CAP_NET_ADMIN`` capability. If
+	that is not set, then the ``EPERM`` error code is returned.
+    * .. _`CEC-MODE-MONITOR-ALL`:
 
-       -  Put the file descriptor into 'monitor all' mode. Can only be used
-	  in combination with :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`, otherwise
-	  the ``EINVAL`` error code will be returned. In 'monitor all' mode all messages
-	  this CEC device transmits and all messages it receives, including
-	  directed messages for other CEC devices will be reported. This is
-	  very useful for debugging, but not all devices support this. This
-	  mode requires that the :ref:`CEC_CAP_MONITOR_ALL <CEC-CAP-MONITOR-ALL>` capability is set,
-	  otherwise the ``EINVAL`` error code is returned. This is only allowed if
-	  the process has the ``CAP_NET_ADMIN`` capability. If that is not
-	  set, then the ``EPERM`` error code is returned.
+      - ``CEC_MODE_MONITOR_ALL``
+      - 0xf0
+      - Put the file descriptor into 'monitor all' mode. Can only be used
+	in combination with :ref:`CEC_MODE_NO_INITIATOR <CEC-MODE-NO-INITIATOR>`, otherwise
+	the ``EINVAL`` error code will be returned. In 'monitor all' mode all messages
+	this CEC device transmits and all messages it receives, including
+	directed messages for other CEC devices will be reported. This is
+	very useful for debugging, but not all devices support this. This
+	mode requires that the :ref:`CEC_CAP_MONITOR_ALL <CEC-CAP-MONITOR-ALL>` capability is set,
+	otherwise the ``EINVAL`` error code is returned. This is only allowed if
+	the process has the ``CAP_NET_ADMIN`` capability. If that is not
+	set, then the ``EPERM`` error code is returned.
 
 
 Core message processing details:
@@ -220,76 +188,58 @@ Core message processing details:
     :stub-columns: 0
     :widths: 1 8
 
+    * .. _`CEC-MSG-GET-CEC-VERSION`:
 
-    -  .. _`CEC-MSG-GET-CEC-VERSION`:
-
-       -  ``CEC_MSG_GET_CEC_VERSION``
-
-       -  When in passthrough mode this message has to be handled by
-	  userspace, otherwise the core will return the CEC version that was
-	  set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`.
-
-    -  .. _`CEC-MSG-GIVE-DEVICE-VENDOR-ID`:
-
-       -  ``CEC_MSG_GIVE_DEVICE_VENDOR_ID``
-
-       -  When in passthrough mode this message has to be handled by
-	  userspace, otherwise the core will return the vendor ID that was
-	  set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`.
-
-    -  .. _`CEC-MSG-ABORT`:
-
-       -  ``CEC_MSG_ABORT``
-
-       -  When in passthrough mode this message has to be handled by
-	  userspace, otherwise the core will return a feature refused
-	  message as per the specification.
-
-    -  .. _`CEC-MSG-GIVE-PHYSICAL-ADDR`:
-
-       -  ``CEC_MSG_GIVE_PHYSICAL_ADDR``
-
-       -  When in passthrough mode this message has to be handled by
-	  userspace, otherwise the core will report the current physical
-	  address.
-
-    -  .. _`CEC-MSG-GIVE-OSD-NAME`:
-
-       -  ``CEC_MSG_GIVE_OSD_NAME``
-
-       -  When in passthrough mode this message has to be handled by
-	  userspace, otherwise the core will report the current OSD name as
-	  was set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`.
-
-    -  .. _`CEC-MSG-GIVE-FEATURES`:
-
-       -  ``CEC_MSG_GIVE_FEATURES``
-
-       -  When in passthrough mode this message has to be handled by
-	  userspace, otherwise the core will report the current features as
-	  was set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
-	  or the message is ignored if the CEC version was older than 2.0.
-
-    -  .. _`CEC-MSG-USER-CONTROL-PRESSED`:
+      - ``CEC_MSG_GET_CEC_VERSION``
+      - When in passthrough mode this message has to be handled by
+	userspace, otherwise the core will return the CEC version that was
+	set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`.
+    * .. _`CEC-MSG-GIVE-DEVICE-VENDOR-ID`:
 
-       -  ``CEC_MSG_USER_CONTROL_PRESSED``
+      - ``CEC_MSG_GIVE_DEVICE_VENDOR_ID``
+      - When in passthrough mode this message has to be handled by
+	userspace, otherwise the core will return the vendor ID that was
+	set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`.
+    * .. _`CEC-MSG-ABORT`:
 
-       -  If :ref:`CEC_CAP_RC <CEC-CAP-RC>` is set, then generate a remote control key
-	  press. This message is always passed on to userspace.
+      - ``CEC_MSG_ABORT``
+      - When in passthrough mode this message has to be handled by
+	userspace, otherwise the core will return a feature refused
+	message as per the specification.
+    * .. _`CEC-MSG-GIVE-PHYSICAL-ADDR`:
 
-    -  .. _`CEC-MSG-USER-CONTROL-RELEASED`:
+      - ``CEC_MSG_GIVE_PHYSICAL_ADDR``
+      - When in passthrough mode this message has to be handled by
+	userspace, otherwise the core will report the current physical
+	address.
+    * .. _`CEC-MSG-GIVE-OSD-NAME`:
 
-       -  ``CEC_MSG_USER_CONTROL_RELEASED``
+      - ``CEC_MSG_GIVE_OSD_NAME``
+      - When in passthrough mode this message has to be handled by
+	userspace, otherwise the core will report the current OSD name as
+	was set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`.
+    * .. _`CEC-MSG-GIVE-FEATURES`:
 
-       -  If :ref:`CEC_CAP_RC <CEC-CAP-RC>` is set, then generate a remote control key
-	  release. This message is always passed on to userspace.
+      - ``CEC_MSG_GIVE_FEATURES``
+      - When in passthrough mode this message has to be handled by
+	userspace, otherwise the core will report the current features as
+	was set with :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
+	or the message is ignored if the CEC version was older than 2.0.
+    * .. _`CEC-MSG-USER-CONTROL-PRESSED`:
 
-    -  .. _`CEC-MSG-REPORT-PHYSICAL-ADDR`:
+      - ``CEC_MSG_USER_CONTROL_PRESSED``
+      - If :ref:`CEC_CAP_RC <CEC-CAP-RC>` is set, then generate a remote control key
+	press. This message is always passed on to userspace.
+    * .. _`CEC-MSG-USER-CONTROL-RELEASED`:
 
-       -  ``CEC_MSG_REPORT_PHYSICAL_ADDR``
+      - ``CEC_MSG_USER_CONTROL_RELEASED``
+      - If :ref:`CEC_CAP_RC <CEC-CAP-RC>` is set, then generate a remote control key
+	release. This message is always passed on to userspace.
+    * .. _`CEC-MSG-REPORT-PHYSICAL-ADDR`:
 
-       -  The CEC framework will make note of the reported physical address
-	  and then just pass the message on to userspace.
+      - ``CEC_MSG_REPORT_PHYSICAL_ADDR``
+      - The CEC framework will make note of the reported physical address
+	and then just pass the message on to userspace.
 
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-receive.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-receive.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/cec/cec-ioc-receive.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/cec/cec-ioc-receive.rst	2017-02-12 16:03:20.000000000 -0500
@@ -34,11 +34,6 @@ Arguments
 Description
 ===========
 
-.. note::
-
-   This documents the proposed CEC API. This API is not yet finalized
-   and is currently only available as a staging kernel module.
-
 To receive a CEC message the application has to fill in the
 ``timeout`` field of struct :c:type:`cec_msg` and pass it to
 :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
@@ -86,173 +81,126 @@ result.
     :stub-columns: 0
     :widths:       1 1 16
 
+    * - __u64
+      - ``tx_ts``
+      - Timestamp in ns of when the last byte of the message was transmitted.
+	The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
+	the same clock from userspace use :c:func:`clock_gettime`.
+    * - __u64
+      - ``rx_ts``
+      - Timestamp in ns of when the last byte of the message was received.
+	The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
+	the same clock from userspace use :c:func:`clock_gettime`.
+    * - __u32
+      - ``len``
+      - The length of the message. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in
+	by the application. The driver will fill this in for
+	:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be
+	filled in by the driver with the length of the reply message if ``reply`` was set.
+    * - __u32
+      - ``timeout``
+      - The timeout in milliseconds. This is the time the device will wait
+	for a message to be received before timing out. If it is set to 0,
+	then it will wait indefinitely when it is called by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
+	If it is 0 and it is called by :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`,
+	then it will be replaced by 1000 if the ``reply`` is non-zero or
+	ignored if ``reply`` is 0.
+    * - __u32
+      - ``sequence``
+      - A non-zero sequence number is automatically assigned by the CEC framework
+	for all transmitted messages. It is used by the CEC framework when it queues
+	the transmit result (when transmit was called in non-blocking mode). This
+	allows the application to associate the received message with the original
+	transmit.
+    * - __u32
+      - ``flags``
+      - Flags. See :ref:`cec-msg-flags` for a list of available flags.
+    * - __u8
+      - ``tx_status``
+      - The status bits of the transmitted message. See
+	:ref:`cec-tx-status` for the possible status values. It is 0 if
+	this messages was received, not transmitted.
+    * - __u8
+      - ``msg[16]``
+      - The message payload. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in by the
+	application. The driver will fill this in for :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
+	For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be filled in by the driver with
+	the payload of the reply message if ``timeout`` was set.
+    * - __u8
+      - ``reply``
+      - Wait until this message is replied. If ``reply`` is 0 and the
+	``timeout`` is 0, then don't wait for a reply but return after
+	transmitting the message. Ignored by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
+	The case where ``reply`` is 0 (this is the opcode for the Feature Abort
+	message) and ``timeout`` is non-zero is specifically allowed to make it
+	possible to send a message and wait up to ``timeout`` milliseconds for a
+	Feature Abort reply. In this case ``rx_status`` will either be set
+	to :ref:`CEC_RX_STATUS_TIMEOUT <CEC-RX-STATUS-TIMEOUT>` or
+	:ref:`CEC_RX_STATUS_FEATURE_ABORT <CEC-RX-STATUS-FEATURE-ABORT>`.
 
-    -  .. row 1
-
-       -  __u64
-
-       -  ``tx_ts``
-
-       -  Timestamp in ns of when the last byte of the message was transmitted.
-	  The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
-	  the same clock from userspace use :c:func:`clock_gettime`.
-
-    -  .. row 2
-
-       -  __u64
-
-       -  ``rx_ts``
-
-       -  Timestamp in ns of when the last byte of the message was received.
-	  The timestamp has been taken from the ``CLOCK_MONOTONIC`` clock. To access
-	  the same clock from userspace use :c:func:`clock_gettime`.
-
-    -  .. row 3
-
-       -  __u32
-
-       -  ``len``
-
-       -  The length of the message. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in
-	  by the application. The driver will fill this in for
-	  :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be
-	  filled in by the driver with the length of the reply message if ``reply`` was set.
-
-    -  .. row 4
-
-       -  __u32
-
-       -  ``timeout``
-
-       -  The timeout in milliseconds. This is the time the device will wait
-	  for a message to be received before timing out. If it is set to 0,
-	  then it will wait indefinitely when it is called by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
-	  If it is 0 and it is called by :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`,
-	  then it will be replaced by 1000 if the ``reply`` is non-zero or
-	  ignored if ``reply`` is 0.
-
-    -  .. row 5
-
-       -  __u32
-
-       -  ``sequence``
-
-       -  A non-zero sequence number is automatically assigned by the CEC framework
-	  for all transmitted messages. It is used by the CEC framework when it queues
-	  the transmit result (when transmit was called in non-blocking mode). This
-	  allows the application to associate the received message with the original
-	  transmit.
-
-    -  .. row 6
-
-       -  __u32
-
-       -  ``flags``
-
-       -  Flags. No flags are defined yet, so set this to 0.
-
-    -  .. row 7
-
-       -  __u8
-
-       -  ``tx_status``
-
-       -  The status bits of the transmitted message. See
-	  :ref:`cec-tx-status` for the possible status values. It is 0 if
-	  this messages was received, not transmitted.
-
-    -  .. row 8
-
-       -  __u8
-
-       -  ``msg[16]``
-
-       -  The message payload. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in by the
-	  application. The driver will fill this in for :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
-	  For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` it will be filled in by the driver with
-	  the payload of the reply message if ``timeout`` was set.
-
-    -  .. row 8
-
-       -  __u8
-
-       -  ``reply``
-
-       -  Wait until this message is replied. If ``reply`` is 0 and the
-	  ``timeout`` is 0, then don't wait for a reply but return after
-	  transmitting the message. Ignored by :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
-	  The case where ``reply`` is 0 (this is the opcode for the Feature Abort
-	  message) and ``timeout`` is non-zero is specifically allowed to make it
-	  possible to send a message and wait up to ``timeout`` milliseconds for a
-	  Feature Abort reply. In this case ``rx_status`` will either be set
-	  to :ref:`CEC_RX_STATUS_TIMEOUT <CEC-RX-STATUS-TIMEOUT>` or
-	  :ref:`CEC_RX_STATUS_FEATURE_ABORT <CEC-RX-STATUS-FEATURE-ABORT>`.
-
-    -  .. row 9
-
-       -  __u8
-
-       -  ``rx_status``
-
-       -  The status bits of the received message. See
-	  :ref:`cec-rx-status` for the possible status values. It is 0 if
-	  this message was transmitted, not received, unless this is the
-	  reply to a transmitted message. In that case both ``rx_status``
-	  and ``tx_status`` are set.
-
-    -  .. row 10
-
-       -  __u8
-
-       -  ``tx_status``
-
-       -  The status bits of the transmitted message. See
-	  :ref:`cec-tx-status` for the possible status values. It is 0 if
-	  this messages was received, not transmitted.
-
-    -  .. row 11
-
-       -  __u8
-
-       -  ``tx_arb_lost_cnt``
-
-       -  A counter of the number of transmit attempts that resulted in the
-	  Arbitration Lost error. This is only set if the hardware supports
-	  this, otherwise it is always 0. This counter is only valid if the
-	  :ref:`CEC_TX_STATUS_ARB_LOST <CEC-TX-STATUS-ARB-LOST>` status bit is set.
-
-    -  .. row 12
-
-       -  __u8
-
-       -  ``tx_nack_cnt``
-
-       -  A counter of the number of transmit attempts that resulted in the
-	  Not Acknowledged error. This is only set if the hardware supports
-	  this, otherwise it is always 0. This counter is only valid if the
-	  :ref:`CEC_TX_STATUS_NACK <CEC-TX-STATUS-NACK>` status bit is set.
-
-    -  .. row 13
-
-       -  __u8
-
-       -  ``tx_low_drive_cnt``
+	If the transmitter message is ``CEC_MSG_INITIATE_ARC`` then the ``reply``
+	values ``CEC_MSG_REPORT_ARC_INITIATED`` and ``CEC_MSG_REPORT_ARC_TERMINATED``
+	are processed differently: either value will match both possible replies.
+	The reason is that the ``CEC_MSG_INITIATE_ARC`` message is the only CEC
+	message that has two possible replies other than Feature Abort. The
+	``reply`` field will be updated with the actual reply so that it is
+	synchronized with the contents of the received message.
+    * - __u8
+      - ``rx_status``
+      - The status bits of the received message. See
+	:ref:`cec-rx-status` for the possible status values. It is 0 if
+	this message was transmitted, not received, unless this is the
+	reply to a transmitted message. In that case both ``rx_status``
+	and ``tx_status`` are set.
+    * - __u8
+      - ``tx_status``
+      - The status bits of the transmitted message. See
+	:ref:`cec-tx-status` for the possible status values. It is 0 if
+	this messages was received, not transmitted.
+    * - __u8
+      - ``tx_arb_lost_cnt``
+      - A counter of the number of transmit attempts that resulted in the
+	Arbitration Lost error. This is only set if the hardware supports
+	this, otherwise it is always 0. This counter is only valid if the
+	:ref:`CEC_TX_STATUS_ARB_LOST <CEC-TX-STATUS-ARB-LOST>` status bit is set.
+    * - __u8
+      - ``tx_nack_cnt``
+      - A counter of the number of transmit attempts that resulted in the
+	Not Acknowledged error. This is only set if the hardware supports
+	this, otherwise it is always 0. This counter is only valid if the
+	:ref:`CEC_TX_STATUS_NACK <CEC-TX-STATUS-NACK>` status bit is set.
+    * - __u8
+      - ``tx_low_drive_cnt``
+      - A counter of the number of transmit attempts that resulted in the
+	Arbitration Lost error. This is only set if the hardware supports
+	this, otherwise it is always 0. This counter is only valid if the
+	:ref:`CEC_TX_STATUS_LOW_DRIVE <CEC-TX-STATUS-LOW-DRIVE>` status bit is set.
+    * - __u8
+      - ``tx_error_cnt``
+      - A counter of the number of transmit errors other than Arbitration
+	Lost or Not Acknowledged. This is only set if the hardware
+	supports this, otherwise it is always 0. This counter is only
+	valid if the :ref:`CEC_TX_STATUS_ERROR <CEC-TX-STATUS-ERROR>` status bit is set.
 
-       -  A counter of the number of transmit attempts that resulted in the
-	  Arbitration Lost error. This is only set if the hardware supports
-	  this, otherwise it is always 0. This counter is only valid if the
-	  :ref:`CEC_TX_STATUS_LOW_DRIVE <CEC-TX-STATUS-LOW-DRIVE>` status bit is set.
 
-    -  .. row 14
+.. _cec-msg-flags:
 
-       -  __u8
+.. flat-table:: Flags for struct cec_msg
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       3 1 4
 
-       -  ``tx_error_cnt``
+    * .. _`CEC-MSG-FL-REPLY-TO-FOLLOWERS`:
 
-       -  A counter of the number of transmit errors other than Arbitration
-	  Lost or Not Acknowledged. This is only set if the hardware
-	  supports this, otherwise it is always 0. This counter is only
-	  valid if the :ref:`CEC_TX_STATUS_ERROR <CEC-TX-STATUS-ERROR>` status bit is set.
+      - ``CEC_MSG_FL_REPLY_TO_FOLLOWERS``
+      - 1
+      - If a CEC transmit expects a reply, then by default that reply is only sent to
+	the filehandle that called :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`. If this
+	flag is set, then the reply is also sent to all followers, if any. If the
+	filehandle that called :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is also a
+	follower, then that filehandle will receive the reply twice: once as the
+	result of the :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`, and once via
+	:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
 
 
 .. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}|
@@ -264,64 +212,46 @@ result.
     :stub-columns: 0
     :widths:       3 1 16
 
+    * .. _`CEC-TX-STATUS-OK`:
 
-    -  .. _`CEC-TX-STATUS-OK`:
-
-       -  ``CEC_TX_STATUS_OK``
-
-       -  0x01
-
-       -  The message was transmitted successfully. This is mutually
-	  exclusive with :ref:`CEC_TX_STATUS_MAX_RETRIES <CEC-TX-STATUS-MAX-RETRIES>`. Other bits can still
-	  be set if earlier attempts met with failure before the transmit
-	  was eventually successful.
-
-    -  .. _`CEC-TX-STATUS-ARB-LOST`:
-
-       -  ``CEC_TX_STATUS_ARB_LOST``
-
-       -  0x02
-
-       -  CEC line arbitration was lost.
-
-    -  .. _`CEC-TX-STATUS-NACK`:
-
-       -  ``CEC_TX_STATUS_NACK``
-
-       -  0x04
-
-       -  Message was not acknowledged.
-
-    -  .. _`CEC-TX-STATUS-LOW-DRIVE`:
-
-       -  ``CEC_TX_STATUS_LOW_DRIVE``
-
-       -  0x08
-
-       -  Low drive was detected on the CEC bus. This indicates that a
-	  follower detected an error on the bus and requests a
-	  retransmission.
-
-    -  .. _`CEC-TX-STATUS-ERROR`:
-
-       -  ``CEC_TX_STATUS_ERROR``
-
-       -  0x10
+      - ``CEC_TX_STATUS_OK``
+      - 0x01
+      - The message was transmitted successfully. This is mutually
+	exclusive with :ref:`CEC_TX_STATUS_MAX_RETRIES <CEC-TX-STATUS-MAX-RETRIES>`. Other bits can still
+	be set if earlier attempts met with failure before the transmit
+	was eventually successful.
+    * .. _`CEC-TX-STATUS-ARB-LOST`:
 
-       -  Some error occurred. This is used for any errors that do not fit
-	  the previous two, either because the hardware could not tell which
-	  error occurred, or because the hardware tested for other
-	  conditions besides those two.
+      - ``CEC_TX_STATUS_ARB_LOST``
+      - 0x02
+      - CEC line arbitration was lost.
+    * .. _`CEC-TX-STATUS-NACK`:
 
-    -  .. _`CEC-TX-STATUS-MAX-RETRIES`:
+      - ``CEC_TX_STATUS_NACK``
+      - 0x04
+      - Message was not acknowledged.
+    * .. _`CEC-TX-STATUS-LOW-DRIVE`:
 
-       -  ``CEC_TX_STATUS_MAX_RETRIES``
+      - ``CEC_TX_STATUS_LOW_DRIVE``
+      - 0x08
+      - Low drive was detected on the CEC bus. This indicates that a
+	follower detected an error on the bus and requests a
+	retransmission.
+    * .. _`CEC-TX-STATUS-ERROR`:
 
-       -  0x20
+      - ``CEC_TX_STATUS_ERROR``
+      - 0x10
+      - Some error occurred. This is used for any errors that do not fit
+	the previous two, either because the hardware could not tell which
+	error occurred, or because the hardware tested for other
+	conditions besides those two.
+    * .. _`CEC-TX-STATUS-MAX-RETRIES`:
 
-       -  The transmit failed after one or more retries. This status bit is
-	  mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`. Other bits can still
-	  be set to explain which failures were seen.
+      - ``CEC_TX_STATUS_MAX_RETRIES``
+      - 0x20
+      - The transmit failed after one or more retries. This status bit is
+	mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`. Other bits can still
+	be set to explain which failures were seen.
 
 
 .. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}|
@@ -333,32 +263,23 @@ result.
     :stub-columns: 0
     :widths:       3 1 16
 
+    * .. _`CEC-RX-STATUS-OK`:
 
-    -  .. _`CEC-RX-STATUS-OK`:
-
-       -  ``CEC_RX_STATUS_OK``
-
-       -  0x01
-
-       -  The message was received successfully.
-
-    -  .. _`CEC-RX-STATUS-TIMEOUT`:
-
-       -  ``CEC_RX_STATUS_TIMEOUT``
-
-       -  0x02
-
-       -  The reply to an earlier transmitted message timed out.
-
-    -  .. _`CEC-RX-STATUS-FEATURE-ABORT`:
-
-       -  ``CEC_RX_STATUS_FEATURE_ABORT``
+      - ``CEC_RX_STATUS_OK``
+      - 0x01
+      - The message was received successfully.
+    * .. _`CEC-RX-STATUS-TIMEOUT`:
 
-       -  0x04
+      - ``CEC_RX_STATUS_TIMEOUT``
+      - 0x02
+      - The reply to an earlier transmitted message timed out.
+    * .. _`CEC-RX-STATUS-FEATURE-ABORT`:
 
-       -  The message was received successfully but the reply was
-	  ``CEC_MSG_FEATURE_ABORT``. This status is only set if this message
-	  was the reply to an earlier transmitted message.
+      - ``CEC_RX_STATUS_FEATURE_ABORT``
+      - 0x04
+      - The message was received successfully but the reply was
+	``CEC_MSG_FEATURE_ABORT``. This status is only set if this message
+	was the reply to an earlier transmitted message.
 
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/dvb/dvbstb.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/dvb/dvbstb.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/dvb/dvbstb.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/dvb/dvbstb.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,651 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.2"
+   width="237.70221mm"
+   height="126.28221mm"
+   viewBox="0 0 23770.221 12628.221"
+   preserveAspectRatio="xMidYMid"
+   xml:space="preserve"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="dvbstb.svg"
+   style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+     id="metadata519"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview517"
+     showgrid="false"
+     inkscape:zoom="1.0818519"
+     inkscape:cx="411.31718"
+     inkscape:cy="274.87517"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" /><defs
+     class="ClipPathGroup"
+     id="defs4" /><defs
+     id="defs9" /><defs
+     id="defs90" /><defs
+     id="defs113" /><defs
+     class="TextShapeIndex"
+     id="defs124" /><defs
+     class="EmbeddedBulletChars"
+     id="defs128" /><defs
+     class="TextEmbeddedBitmaps"
+     id="defs157" /><rect
+     class="BoundingBox"
+     x="5355.1108"
+     y="13.111"
+     width="18403"
+     height="9603"
+     id="rect197"
+     style="fill:none;stroke:none" /><path
+     d="m 14556.111,9614.111 -9200,0 0,-9600 18400,0 0,9600 -9200,0 z"
+     id="path199"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 14556.111,9614.111 -9200,0 0,-9600 18400,0 0,9600 -9200,0 z"
+     id="path201"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><rect
+     class="BoundingBox"
+     x="13.111"
+     y="4013.1111"
+     width="4544"
+     height="2403"
+     id="rect206"
+     style="fill:none;stroke:none" /><path
+     d="m 2285.111,6414.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path208"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 2285.111,6414.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path210"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text212"
+     y="-4585.8892"
+     x="-2443.8889"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan214"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="1281.111"
+         y="5435.1108"
+         id="tspan216"><tspan
+           id="tspan218"
+           style="fill:#000000;stroke:none">Antena</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="6213.1108"
+     y="1813.111"
+     width="4544"
+     height="2403"
+     id="rect223"
+     style="fill:none;stroke:none" /><path
+     d="m 8485.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path225"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 8485.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path227"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text229"
+     x="-2443.8889"
+     y="-4585.8892"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan231"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="7217.1108"
+         y="3235.1111"
+         id="tspan233"><tspan
+           id="tspan235"
+           style="fill:#000000;stroke:none">Frontend</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="12113.111"
+     y="1813.111"
+     width="4544"
+     height="2403"
+     id="rect240"
+     style="fill:none;stroke:none" /><path
+     d="m 14385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path242"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 14385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path244"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text246"
+     x="-2443.8889"
+     y="-4585.8892"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan248"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="13944.111"
+         y="3235.1111"
+         id="tspan250"><tspan
+           id="tspan252"
+           style="fill:#000000;stroke:none">CA</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="18113.111"
+     y="1813.111"
+     width="4544"
+     height="2403"
+     id="rect257"
+     style="fill:none;stroke:none" /><path
+     d="m 20385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path259"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 20385.111,4214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path261"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text263"
+     x="-2443.8889"
+     y="-4585.8892"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan265"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="19384.111"
+         y="3235.1111"
+         id="tspan267"><tspan
+           id="tspan269"
+           style="fill:#000000;stroke:none">Demux</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="6113.1108"
+     y="5813.1108"
+     width="4544"
+     height="2403"
+     id="rect274"
+     style="fill:none;stroke:none" /><path
+     d="m 8385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path276"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 8385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path278"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text280"
+     x="-2443.8889"
+     y="-4585.8892"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan282"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="7733.1108"
+         y="7235.1108"
+         id="tspan284"><tspan
+           id="tspan286"
+           style="fill:#000000;stroke:none">SEC</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="12213.111"
+     y="5813.1108"
+     width="4544"
+     height="2403"
+     id="rect291"
+     style="fill:none;stroke:none" /><path
+     d="m 14485.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path293"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 14485.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path295"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text297"
+     x="-2443.8889"
+     y="-4585.8892"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan299"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="13676.111"
+         y="7235.1108"
+         id="tspan301"><tspan
+           id="tspan303"
+           style="fill:#000000;stroke:none">Audio</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="18113.111"
+     y="5813.1108"
+     width="4544"
+     height="2403"
+     id="rect308"
+     style="fill:none;stroke:none" /><path
+     d="m 20385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path310"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 20385.111,8214.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path312"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text314"
+     x="-2443.8889"
+     y="-4585.8892"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan316"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="19583.111"
+         y="7235.1108"
+         id="tspan318"><tspan
+           id="tspan320"
+           style="fill:#000000;stroke:none">Video</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="15213.111"
+     y="10213.111"
+     width="4544"
+     height="2403"
+     id="rect325"
+     style="fill:none;stroke:none" /><path
+     d="m 17485.111,12614.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path327"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 17485.111,12614.111 -2271,0 0,-2400 4541,0 0,2400 -2270,0 z"
+     id="path329"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><text
+     class="TextShape"
+     id="text331"
+     x="-2443.8889"
+     y="-4585.8892"><tspan
+       class="TextParagraph"
+       font-size="635px"
+       font-weight="400"
+       id="tspan333"
+       style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="17076.111"
+         y="11635.111"
+         id="tspan335"><tspan
+           id="tspan337"
+           style="fill:#000000;stroke:none">TV</tspan></tspan></tspan></text>
+<rect
+     class="BoundingBox"
+     x="4555.1108"
+     y="3014.1111"
+     width="1661"
+     height="2202"
+     id="rect342"
+     style="fill:none;stroke:none" /><path
+     d="m 4556.111,5214.111 1400,-1857"
+     id="path344"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 6215.111,3014.111 -391,269 240,181 151,-450 z"
+     id="path346"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /><rect
+     class="BoundingBox"
+     x="4555.1108"
+     y="5213.1108"
+     width="1561"
+     height="1802"
+     id="rect351"
+     style="fill:none;stroke:none" /><path
+     d="m 4556.111,5214.111 1277,1475"
+     id="path353"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 6115.111,7014.111 -181,-438 -227,196 408,242 z"
+     id="path355"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /><rect
+     class="BoundingBox"
+     x="10755.111"
+     y="2864.1111"
+     width="1361"
+     height="301"
+     id="rect360"
+     style="fill:none;stroke:none" /><path
+     d="m 10756.111,3014.111 929,0"
+     id="path362"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 12115.111,3014.111 -450,-150 0,300 450,-150 z"
+     id="path364"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /><rect
+     class="BoundingBox"
+     x="16655.111"
+     y="2864.1111"
+     width="1461"
+     height="301"
+     id="rect369"
+     style="fill:none;stroke:none" /><path
+     d="m 16656.111,3014.111 1029,0"
+     id="path371"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18115.111,3014.111 -450,-150 0,300 450,-150 z"
+     id="path373"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /><rect
+     class="BoundingBox"
+     x="20235.111"
+     y="4213.1108"
+     width="301"
+     height="1602"
+     id="rect378"
+     style="fill:none;stroke:none" /><path
+     d="m 20385.111,4214.111 0,1170"
+     id="path380"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 20385.111,5814.111 150,-450 -300,0 150,450 z"
+     id="path382"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /><rect
+     class="BoundingBox"
+     x="17485.111"
+     y="8213.1113"
+     width="2902"
+     height="2002"
+     id="rect387"
+     style="fill:none;stroke:none" /><path
+     d="m 20385.111,8214.111 -2546,1756"
+     id="path389"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17485.111,10214.111 456,-132 -171,-247 -285,379 z"
+     id="path391"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /><rect
+     class="BoundingBox"
+     x="14484.111"
+     y="8213.1113"
+     width="3002"
+     height="2002"
+     id="rect396"
+     style="fill:none;stroke:none" /><path
+     d="m 14485.111,8214.111 2642,1761"
+     id="path398"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17485.111,10214.111 -291,-374 -167,249 458,125 z"
+     id="path400"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /><rect
+     class="BoundingBox"
+     x="14485.111"
+     y="4213.1108"
+     width="5902"
+     height="1629"
+     id="rect405"
+     style="fill:none;stroke:none" /><path
+     d="m 20385.111,4214.111 -51,14"
+     id="path407"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 20283.111,4242.111 -52,14"
+     id="path409"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 20180.111,4270.111 -51,13"
+     id="path411"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 20078.111,4297.111 -52,14"
+     id="path413"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19975.111,4325.111 -51,14"
+     id="path415"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19873.111,4353.111 -52,14"
+     id="path417"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19770.111,4381.111 -51,14"
+     id="path419"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19668.111,4409.111 -52,13"
+     id="path421"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19565.111,4436.111 -51,14"
+     id="path423"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19463.111,4464.111 -52,14"
+     id="path425"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19360.111,4492.111 -51,14"
+     id="path427"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19258.111,4520.111 -52,14"
+     id="path429"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19155.111,4547.111 -51,14"
+     id="path431"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 19053.111,4575.111 -52,14"
+     id="path433"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18950.111,4603.111 -51,14"
+     id="path435"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18848.111,4631.111 -51,14"
+     id="path437"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18745.111,4659.111 -51,14"
+     id="path439"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18643.111,4686.111 -51,14"
+     id="path441"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18540.111,4714.111 -51,14"
+     id="path443"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18438.111,4742.111 -51,14"
+     id="path445"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18335.111,4770.111 -51,14"
+     id="path447"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18233.111,4798.111 -51,14"
+     id="path449"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18130.111,4825.111 -51,14"
+     id="path451"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 18028.111,4853.111 -51,14"
+     id="path453"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17925.111,4881.111 -51,14"
+     id="path455"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17823.111,4909.111 -51,14"
+     id="path457"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17720.111,4937.111 -51,13"
+     id="path459"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17618.111,4964.111 -51,14"
+     id="path461"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17516.111,4992.111 -52,14"
+     id="path463"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17413.111,5020.111 -51,14"
+     id="path465"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17311.111,5048.111 -52,14"
+     id="path467"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17208.111,5076.111 -51,13"
+     id="path469"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17106.111,5103.111 -52,14"
+     id="path471"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 17003.111,5131.111 -51,14"
+     id="path473"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16901.111,5159.111 -52,14"
+     id="path475"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16798.111,5187.111 -51,14"
+     id="path477"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16696.111,5214.111 -52,14"
+     id="path479"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16593.111,5242.111 -51,14"
+     id="path481"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16491.111,5270.111 -52,14"
+     id="path483"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16388.111,5298.111 -51,14"
+     id="path485"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16286.111,5326.111 -52,14"
+     id="path487"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16183.111,5353.111 -51,14"
+     id="path489"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 16081.111,5381.111 -51,14"
+     id="path491"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15978.111,5409.111 -51,14"
+     id="path493"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15876.111,5437.111 -51,14"
+     id="path495"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15773.111,5465.111 -51,14"
+     id="path497"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15671.111,5492.111 -51,14"
+     id="path499"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15568.111,5520.111 -51,14"
+     id="path501"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15466.111,5548.111 -51,14"
+     id="path503"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15363.111,5576.111 -51,14"
+     id="path505"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15261.111,5604.111 -51,13"
+     id="path507"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15158.111,5631.111 -51,14"
+     id="path509"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 15056.111,5659.111 -51,14"
+     id="path511"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 14953.111,5687.111 -51,14"
+     id="path513"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000" /><path
+     d="m 14485.111,5814.111 474,27 -79,-290 -395,263 z"
+     id="path515"
+     inkscape:connector-curvature="0"
+     style="fill:#000000;stroke:none" /></svg>
\ No newline at end of file
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/dvb/intro_files/dvbstb.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/dvb/intro_files/dvbstb.pdf differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/dvb/intro_files/dvbstb.png and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/dvb/intro_files/dvbstb.png differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/dvb/intro.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/dvb/intro.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/dvb/intro.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/dvb/intro.rst	2017-02-12 16:03:20.000000000 -0500
@@ -55,8 +55,8 @@ Overview
 
 .. _stb_components:
 
-.. figure::  intro_files/dvbstb.*
-    :alt:    dvbstb.pdf / dvbstb.png
+.. figure::  dvbstb.*
+    :alt:    dvbstb.pdf / dvbstb.svg
     :align:  center
 
     Components of a DVB card/STB
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/bayer.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/bayer.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/bayer.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/bayer.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,984 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.2"
+   width="164.15334mm"
+   height="46.771107mm"
+   viewBox="0 0 16415.333 4677.1107"
+   preserveAspectRatio="xMidYMid"
+   xml:space="preserve"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="bayer.svg"
+   style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+     id="metadata652"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview650"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="2.4000866"
+     inkscape:cx="290.82284"
+     inkscape:cy="82.862197"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" /><defs
+     class="ClipPathGroup"
+     id="defs4" /><defs
+     id="defs9" /><defs
+     id="defs82" /><defs
+     id="defs105" /><defs
+     class="TextShapeIndex"
+     id="defs116" /><defs
+     class="EmbeddedBulletChars"
+     id="defs120" /><defs
+     class="TextEmbeddedBitmaps"
+     id="defs149" /><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g186"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id6"><rect
+         class="BoundingBox"
+         x="3299"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect189"
+         style="fill:none;stroke:none" /><path
+         d="m 3950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path191"
+         inkscape:connector-curvature="0"
+         style="fill:#0000ff;stroke:none" /><path
+         d="m 3950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path193"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text195"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan197"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="3739"
+             y="4021"
+             id="tspan199"><tspan
+               id="tspan201"
+               style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g203"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id7"><rect
+         class="BoundingBox"
+         x="4599"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect206"
+         style="fill:none;stroke:none" /><path
+         d="m 5250,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path208"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 5250,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path210"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text212"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan214"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="5003"
+             y="4021"
+             id="tspan216"><tspan
+               id="tspan218"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g220"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id8"><rect
+         class="BoundingBox"
+         x="3299"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect223"
+         style="fill:none;stroke:none" /><path
+         d="m 3950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path225"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 3950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path227"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text229"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan231"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="3703"
+             y="5221"
+             id="tspan233"><tspan
+               id="tspan235"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g237"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id9"><rect
+         class="BoundingBox"
+         x="4599"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect240"
+         style="fill:none;stroke:none" /><path
+         d="m 5250,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path242"
+         inkscape:connector-curvature="0"
+         style="fill:#ff0000;stroke:none" /><path
+         d="m 5250,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path244"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text246"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan248"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="5022"
+             y="5221"
+             id="tspan250"><tspan
+               id="tspan252"
+               style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g254"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id10"><rect
+         class="BoundingBox"
+         x="5999"
+         y="3299"
+         width="1003"
+         height="1003"
+         id="rect257"
+         style="fill:none;stroke:none" /><path
+         d="m 6500,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path259"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#0000ff" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g261"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id11"><rect
+         class="BoundingBox"
+         x="4699"
+         y="5699"
+         width="1003"
+         height="1003"
+         id="rect264"
+         style="fill:none;stroke:none" /><path
+         d="m 5200,6700 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path266"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.TextShape"
+     id="g268"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id12"><rect
+         class="BoundingBox"
+         x="4000"
+         y="6900"
+         width="2374"
+         height="963"
+         id="rect271"
+         style="fill:none;stroke:none" /><text
+         class="TextShape"
+         id="text273"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan275"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="4250"
+             y="7601"
+             id="tspan277"><tspan
+               id="tspan279"
+               style="fill:#000000;stroke:none">BGGR</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g281"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id13"><rect
+         class="BoundingBox"
+         x="8799"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect284"
+         style="fill:none;stroke:none" /><path
+         d="m 9450,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path286"
+         inkscape:connector-curvature="0"
+         style="fill:#0000ff;stroke:none" /><path
+         d="m 9450,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path288"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text290"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan292"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="9239"
+             y="4021"
+             id="tspan294"><tspan
+               id="tspan296"
+               style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g298"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id14"><rect
+         class="BoundingBox"
+         x="7499"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect301"
+         style="fill:none;stroke:none" /><path
+         d="m 8150,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path303"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 8150,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path305"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text307"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan309"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="7903"
+             y="4021"
+             id="tspan311"><tspan
+               id="tspan313"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g315"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id15"><rect
+         class="BoundingBox"
+         x="8799"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect318"
+         style="fill:none;stroke:none" /><path
+         d="m 9450,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path320"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 9450,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path322"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text324"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan326"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="9203"
+             y="5221"
+             id="tspan328"><tspan
+               id="tspan330"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g332"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id16"><rect
+         class="BoundingBox"
+         x="7499"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect335"
+         style="fill:none;stroke:none" /><path
+         d="m 8150,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path337"
+         inkscape:connector-curvature="0"
+         style="fill:#ff0000;stroke:none" /><path
+         d="m 8150,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path339"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text341"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan343"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="7922"
+             y="5221"
+             id="tspan345"><tspan
+               id="tspan347"
+               style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.TextShape"
+     id="g349"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id17"><rect
+         class="BoundingBox"
+         x="8200"
+         y="6900"
+         width="2374"
+         height="963"
+         id="rect352"
+         style="fill:none;stroke:none" /><text
+         class="TextShape"
+         id="text354"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan356"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="8450"
+             y="7601"
+             id="tspan358"><tspan
+               id="tspan360"
+               style="fill:#000000;stroke:none">GBRG</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g362"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id18"><rect
+         class="BoundingBox"
+         x="17299"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect365"
+         style="fill:none;stroke:none" /><path
+         d="m 17950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path367"
+         inkscape:connector-curvature="0"
+         style="fill:#0000ff;stroke:none" /><path
+         d="m 17950,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path369"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text371"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan373"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="17739"
+             y="5221"
+             id="tspan375"><tspan
+               id="tspan377"
+               style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g379"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id19"><rect
+         class="BoundingBox"
+         x="17299"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect382"
+         style="fill:none;stroke:none" /><path
+         d="m 17950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path384"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 17950,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path386"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text388"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan390"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="17703"
+             y="4021"
+             id="tspan392"><tspan
+               id="tspan394"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g396"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id20"><rect
+         class="BoundingBox"
+         x="15999"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect399"
+         style="fill:none;stroke:none" /><path
+         d="m 16650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path401"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 16650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path403"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text405"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan407"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="16403"
+             y="5221"
+             id="tspan409"><tspan
+               id="tspan411"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g413"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id21"><rect
+         class="BoundingBox"
+         x="15999"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect416"
+         style="fill:none;stroke:none" /><path
+         d="m 16650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path418"
+         inkscape:connector-curvature="0"
+         style="fill:#ff0000;stroke:none" /><path
+         d="m 16650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path420"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text422"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan424"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="16422"
+             y="4021"
+             id="tspan426"><tspan
+               id="tspan428"
+               style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.TextShape"
+     id="g430"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id22"><rect
+         class="BoundingBox"
+         x="16700"
+         y="6900"
+         width="2374"
+         height="963"
+         id="rect433"
+         style="fill:none;stroke:none" /><text
+         class="TextShape"
+         id="text435"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan437"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="16950"
+             y="7601"
+             id="tspan439"><tspan
+               id="tspan441"
+               style="fill:#000000;stroke:none">RGGB</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g443"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id23"><rect
+         class="BoundingBox"
+         x="11699"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect446"
+         style="fill:none;stroke:none" /><path
+         d="m 12350,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path448"
+         inkscape:connector-curvature="0"
+         style="fill:#0000ff;stroke:none" /><path
+         d="m 12350,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path450"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text452"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan454"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="12139"
+             y="5221"
+             id="tspan456"><tspan
+               id="tspan458"
+               style="fill:#ffffff;stroke:none">B</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g460"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id24"><rect
+         class="BoundingBox"
+         x="11699"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect463"
+         style="fill:none;stroke:none" /><path
+         d="m 12350,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path465"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 12350,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path467"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text469"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan471"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="12103"
+             y="4021"
+             id="tspan473"><tspan
+               id="tspan475"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g477"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id25"><rect
+         class="BoundingBox"
+         x="12999"
+         y="4399"
+         width="1303"
+         height="1203"
+         id="rect480"
+         style="fill:none;stroke:none" /><path
+         d="m 13650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path482"
+         inkscape:connector-curvature="0"
+         style="fill:#00cc00;stroke:none" /><path
+         d="m 13650,5600 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path484"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text486"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan488"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="13403"
+             y="5221"
+             id="tspan490"><tspan
+               id="tspan492"
+               style="fill:#ffffff;stroke:none">G</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g494"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id26"><rect
+         class="BoundingBox"
+         x="12999"
+         y="3199"
+         width="1303"
+         height="1203"
+         id="rect497"
+         style="fill:none;stroke:none" /><path
+         d="m 13650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path499"
+         inkscape:connector-curvature="0"
+         style="fill:#ff0000;stroke:none" /><path
+         d="m 13650,4400 -650,0 0,-1200 1300,0 0,1200 -650,0 z"
+         id="path501"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text503"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan505"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="13422"
+             y="4021"
+             id="tspan507"><tspan
+               id="tspan509"
+               style="fill:#ffffff;stroke:none">R</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.TextShape"
+     id="g511"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id27"><rect
+         class="BoundingBox"
+         x="12400"
+         y="6900"
+         width="2374"
+         height="963"
+         id="rect514"
+         style="fill:none;stroke:none" /><text
+         class="TextShape"
+         id="text516"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan518"
+           style="font-weight:400;font-size:635px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="12650"
+             y="7601"
+             id="tspan520"><tspan
+               id="tspan522"
+               style="fill:#000000;stroke:none">GRBG</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g524"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id28"><rect
+         class="BoundingBox"
+         x="5999"
+         y="5699"
+         width="1003"
+         height="1003"
+         id="rect527"
+         style="fill:none;stroke:none" /><path
+         d="m 6500,6700 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path529"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#0000ff" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g531"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id29"><rect
+         class="BoundingBox"
+         x="3399"
+         y="5699"
+         width="1003"
+         height="1003"
+         id="rect534"
+         style="fill:none;stroke:none" /><path
+         d="m 3900,6700 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path536"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#0000ff" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g538"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id30"><rect
+         class="BoundingBox"
+         x="5999"
+         y="4499"
+         width="1003"
+         height="1003"
+         id="rect541"
+         style="fill:none;stroke:none" /><path
+         d="m 6500,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path543"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g545"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id31"><rect
+         class="BoundingBox"
+         x="7599"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect548"
+         style="fill:none;stroke:none" /><path
+         d="m 8100,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path550"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g552"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id32"><rect
+         class="BoundingBox"
+         x="10199"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect555"
+         style="fill:none;stroke:none" /><path
+         d="m 10700,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path557"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g559"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id33"><rect
+         class="BoundingBox"
+         x="8899"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect562"
+         style="fill:none;stroke:none" /><path
+         d="m 9400,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path564"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#0000ff" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g566"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id34"><rect
+         class="BoundingBox"
+         x="10199"
+         y="4499"
+         width="1003"
+         height="1003"
+         id="rect569"
+         style="fill:none;stroke:none" /><path
+         d="m 10700,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path571"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff0000" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g573"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id35"><rect
+         class="BoundingBox"
+         x="10199"
+         y="3299"
+         width="1003"
+         height="1003"
+         id="rect576"
+         style="fill:none;stroke:none" /><path
+         d="m 10700,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path578"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g580"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id36"><rect
+         class="BoundingBox"
+         x="14399"
+         y="3299"
+         width="1003"
+         height="1003"
+         id="rect583"
+         style="fill:none;stroke:none" /><path
+         d="m 14900,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path585"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g587"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id37"><rect
+         class="BoundingBox"
+         x="14399"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect590"
+         style="fill:none;stroke:none" /><path
+         d="m 14900,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path592"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g594"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id38"><rect
+         class="BoundingBox"
+         x="11799"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect597"
+         style="fill:none;stroke:none" /><path
+         d="m 12300,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path599"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g601"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id39"><rect
+         class="BoundingBox"
+         x="14399"
+         y="4499"
+         width="1003"
+         height="1003"
+         id="rect604"
+         style="fill:none;stroke:none" /><path
+         d="m 14900,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path606"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#0000ff" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g608"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id40"><rect
+         class="BoundingBox"
+         x="13099"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect611"
+         style="fill:none;stroke:none" /><path
+         d="m 13600,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path613"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff0000" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g615"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id41"><rect
+         class="BoundingBox"
+         x="16099"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect618"
+         style="fill:none;stroke:none" /><path
+         d="m 16600,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path620"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff0000" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g622"
+     transform="translate(-3398.7778,-3185.889)"><g
+       id="id42"><rect
+         class="BoundingBox"
+         x="18799"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect625"
+         style="fill:none;stroke:none" /><path
+         d="m 19300,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path627"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff0000" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g629"
+     transform="translate(-3398.7778,-3185.889)"><g
+       id="id43"><rect
+         class="BoundingBox"
+         x="18799"
+         y="3299"
+         width="1003"
+         height="1003"
+         id="rect632"
+         style="fill:none;stroke:none" /><path
+         d="m 19300,4300 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path634"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff0000" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g636"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id44"><rect
+         class="BoundingBox"
+         x="17399"
+         y="5799"
+         width="1003"
+         height="1003"
+         id="rect639"
+         style="fill:none;stroke:none" /><path
+         d="m 17900,6800 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path641"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g643"
+     transform="translate(-3398.7778,-3185.889)"><g
+       id="id45"><rect
+         class="BoundingBox"
+         x="18799"
+         y="4499"
+         width="1003"
+         height="1003"
+         id="rect646"
+         style="fill:none;stroke:none" /><path
+         d="m 19300,5500 -500,0 0,-1000 1000,0 0,1000 -500,0 z"
+         id="path648"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#00cc00" /></g></g></svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/constraints.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/constraints.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/constraints.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/constraints.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,346 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.2"
+   width="249.00998mm"
+   height="143.00999mm"
+   viewBox="0 0 24900.998 14300.999"
+   preserveAspectRatio="xMidYMid"
+   xml:space="preserve"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="constraints.svg"
+   style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+     id="metadata325"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview323"
+     showgrid="false"
+     inkscape:zoom="1.0818519"
+     inkscape:cx="270.29272"
+     inkscape:cy="249.83854"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" /><defs
+     class="ClipPathGroup"
+     id="defs4"><marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker6261"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mend"><path
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         id="path6263"
+         inkscape:connector-curvature="0" /></marker><marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker6125"
+       style="overflow:visible"
+       inkscape:isstock="true"
+       inkscape:collect="always"><path
+         id="path6127"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         inkscape:connector-curvature="0" /></marker><marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker6001"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mend"
+       inkscape:collect="always"><path
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         id="path6003"
+         inkscape:connector-curvature="0" /></marker><marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5693"
+       style="overflow:visible"
+       inkscape:isstock="true"
+       inkscape:collect="always"><path
+         id="path5695"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#ff0000;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         inkscape:connector-curvature="0" /></marker><marker
+       inkscape:isstock="true"
+       style="overflow:visible"
+       id="marker5575"
+       refX="0"
+       refY="0"
+       orient="auto"
+       inkscape:stockid="Arrow1Mend"
+       inkscape:collect="always"><path
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         id="path5577"
+         inkscape:connector-curvature="0" /></marker><marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5469"
+       style="overflow:visible"
+       inkscape:isstock="true"
+       inkscape:collect="always"><path
+         id="path5471"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         inkscape:connector-curvature="0" /></marker><marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5259"
+       style="overflow:visible"
+       inkscape:isstock="true"><path
+         id="path5261"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.4,0,0,-0.4,-4,0)"
+         inkscape:connector-curvature="0" /></marker><marker
+       inkscape:stockid="Arrow2Mend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Mend"
+       style="overflow:visible"
+       inkscape:isstock="true"><path
+         id="path4241"
+         style="fill:#000080;fill-opacity:1;fill-rule:evenodd;stroke:#000080;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="scale(-0.6,-0.6)"
+         inkscape:connector-curvature="0" /></marker></defs><defs
+     id="defs9" /><defs
+     id="defs100" /><defs
+     id="defs123" /><defs
+     class="TextShapeIndex"
+     id="defs134" /><defs
+     class="EmbeddedBulletChars"
+     id="defs138" /><defs
+     class="TextEmbeddedBitmaps"
+     id="defs167" /><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g204"
+     transform="translate(-1350,-3250)"><g
+       id="id6"><rect
+         class="BoundingBox"
+         x="1350"
+         y="3250"
+         width="24901"
+         height="14301"
+         id="rect207"
+         style="fill:none;stroke:none" /><path
+         d="m 13800,17500 -12400,0 0,-14200 24800,0 0,14200 -12400,0 z"
+         id="path209"
+         inkscape:connector-curvature="0"
+         style="fill:#ffffff;stroke:none" /><path
+         d="m 13800,17500 -12400,0 0,-14200 24800,0 0,14200 -12400,0 z"
+         id="path211"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff0000;stroke-width:100;stroke-linejoin:round" /><text
+         class="TextShape"
+         id="text213"><tspan
+           class="TextParagraph"
+           font-size="846px"
+           font-weight="400"
+           id="tspan215"
+           style="font-weight:400;font-size:846px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="1652"
+             y="17093"
+             id="tspan217"><tspan
+               id="tspan219"
+               style="fill:#ff0000;stroke:none" /><tspan
+               id="tspan221"
+               style="fill:#ff0000;stroke:none">V4L2_SEL_FLAG_GE</tspan></tspan></tspan></text>
+</g></g><rect
+     class="BoundingBox"
+     x="3000"
+     y="2200"
+     width="18101"
+     height="10101"
+     id="rect226"
+     style="fill:none;stroke:none" /><path
+     d="m 12050,12250 -9000,0 0,-10000 18000,0 0,10000 -9000,0 z"
+     id="path228"
+     inkscape:connector-curvature="0"
+     style="fill:#ffffff;stroke:none" /><path
+     d="m 12050,12250 -9000,0 0,-10000 18000,0 0,10000 -9000,0 z"
+     id="path230"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000000;stroke-width:100;stroke-linejoin:round" /><text
+     class="TextShape"
+     id="text232"
+     x="-1350"
+     y="-3250"><tspan
+       class="TextParagraph"
+       font-size="987px"
+       font-weight="400"
+       id="tspan234"
+       style="font-weight:400;font-size:987px;font-family:'Liberation Sans', sans-serif"><tspan
+         class="TextPosition"
+         x="3227"
+         y="11503"
+         id="tspan236"><tspan
+           id="tspan238"
+           style="fill:#000000;stroke:none" /><tspan
+           id="tspan240"
+           style="fill:#000000;stroke:none">ORIGINAL</tspan></tspan></tspan></text>
+<g
+     class="com.sun.star.drawing.CustomShape"
+     id="g242"
+     transform="translate(-1350,-3250)"><g
+       id="id8"><rect
+         class="BoundingBox"
+         x="7050"
+         y="7950"
+         width="7901"
+         height="5501"
+         id="rect245"
+         style="fill:none;stroke:none" /><path
+         d="m 11000,13400 -3900,0 0,-5400 7800,0 0,5400 -3900,0 z"
+         id="path247"
+         inkscape:connector-curvature="0"
+         style="fill:#ffffff;stroke:none" /><path
+         d="m 11000,13400 -3900,0 0,-5400 7800,0 0,5400 -3900,0 z"
+         id="path249"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4;stroke-width:100;stroke-linejoin:round" /><text
+         class="TextShape"
+         id="text251"><tspan
+           class="TextParagraph"
+           font-size="776px"
+           font-weight="400"
+           id="tspan253"
+           style="font-weight:400;font-size:776px;font-family:'Liberation Sans', sans-serif"><tspan
+             class="TextPosition"
+             x="7228"
+             y="10969"
+             id="tspan255"><tspan
+               id="tspan257"
+               style="fill:#000080;stroke:none">V4L2_SEL_FLAG_LE</tspan></tspan></tspan></text>
+</g></g><rect
+     class="BoundingBox"
+     x="13700"
+     y="7100"
+     width="7101"
+     height="101"
+     id="rect262"
+     style="fill:none;stroke:none" /><path
+     d="m 20750,7150 -7000,0"
+     id="path264"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000080;stroke-width:99.99134064;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#Arrow2Mend)" /><rect
+     class="BoundingBox"
+     x="3400"
+     y="7100"
+     width="2101"
+     height="101"
+     id="rect269"
+     style="fill:none;stroke:none" /><path
+     d="m 3450,7150 2000,0"
+     id="path271"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000080;stroke-width:100;stroke-linejoin:round;marker-end:url(#marker5575)" /><rect
+     class="BoundingBox"
+     x="9800"
+     y="2900"
+     width="101"
+     height="1501"
+     id="rect276"
+     style="fill:none;stroke:none" /><path
+     d="m 9850,2950 0,1400"
+     id="path278"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000080;stroke-width:100;stroke-linejoin:round;marker-end:url(#marker5259)" /><rect
+     class="BoundingBox"
+     x="9600"
+     y="10600"
+     width="101"
+     height="1301"
+     id="rect283"
+     style="fill:none;stroke:none" /><path
+     d="m 9650,11850 0,-1200"
+     id="path285"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#000080;stroke-width:100;stroke-linejoin:round;marker-end:url(#marker5469)" /><rect
+     class="BoundingBox"
+     x="450"
+     y="6850"
+     width="2051"
+     height="601"
+     id="rect290"
+     style="fill:none;stroke:none" /><path
+     d="m 2450,7150 -2000.8696,0"
+     id="path292"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#ff0000;stroke-width:132.48202515;stroke-linejoin:round;marker-end:url(#marker6125)" /><rect
+     class="BoundingBox"
+     x="21600"
+     y="6750"
+     width="2651"
+     height="601"
+     id="rect299"
+     style="fill:none;stroke:none" /><path
+     d="m 21650,7050 2522.609,0"
+     id="path301"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#ff0000;stroke-width:120.40660858;stroke-linejoin:round;marker-end:url(#marker6001)" /><rect
+     class="BoundingBox"
+     x="9550"
+     y="550"
+     width="601"
+     height="1451"
+     id="rect308"
+     style="fill:none;stroke:none" /><path
+     d="m 9836.957,1950 0,-1453.0435"
+     id="path310"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#ff0000;stroke-width:164.03721619;stroke-linejoin:round;marker-end:url(#marker6261)" /><rect
+     class="BoundingBox"
+     x="9350"
+     y="12500"
+     width="601"
+     height="1451"
+     id="rect317"
+     style="fill:none;stroke:none" /><path
+     d="m 9650,12550 0,1505.217"
+     id="path319"
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#ff0000;stroke-width:166.95626831;stroke-linejoin:round;marker-end:url(#marker5693)" /></svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/control.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/control.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/control.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/control.rst	2017-02-12 16:03:20.000000000 -0500
@@ -312,21 +312,20 @@ more menu type controls.
 
 .. _enum_all_controls:
 
-Example: Enumerating all user controls
-======================================
+Example: Enumerating all controls
+=================================
 
 .. code-block:: c
 
-
     struct v4l2_queryctrl queryctrl;
     struct v4l2_querymenu querymenu;
 
-    static void enumerate_menu(void)
+    static void enumerate_menu(__u32 id)
     {
 	printf("  Menu items:\\n");
 
 	memset(&querymenu, 0, sizeof(querymenu));
-	querymenu.id = queryctrl.id;
+	querymenu.id = id;
 
 	for (querymenu.index = queryctrl.minimum;
 	     querymenu.index <= queryctrl.maximum;
@@ -339,6 +338,55 @@ Example: Enumerating all user controls
 
     memset(&queryctrl, 0, sizeof(queryctrl));
 
+    queryctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL;
+    while (0 == ioctl(fd, VIDIOC_QUERYCTRL, &queryctrl)) {
+	if (!(queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)) {
+	    printf("Control %s\\n", queryctrl.name);
+
+	    if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+	        enumerate_menu(queryctrl.id);
+        }
+
+	queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+    }
+    if (errno != EINVAL) {
+	perror("VIDIOC_QUERYCTRL");
+	exit(EXIT_FAILURE);
+    }
+
+Example: Enumerating all controls including compound controls
+=============================================================
+
+.. code-block:: c
+
+    struct v4l2_query_ext_ctrl query_ext_ctrl;
+
+    memset(&query_ext_ctrl, 0, sizeof(query_ext_ctrl));
+
+    query_ext_ctrl.id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
+    while (0 == ioctl(fd, VIDIOC_QUERY_EXT_CTRL, &query_ext_ctrl)) {
+	if (!(query_ext_ctrl.flags & V4L2_CTRL_FLAG_DISABLED)) {
+	    printf("Control %s\\n", query_ext_ctrl.name);
+
+	    if (query_ext_ctrl.type == V4L2_CTRL_TYPE_MENU)
+	        enumerate_menu(query_ext_ctrl.id);
+        }
+
+	query_ext_ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
+    }
+    if (errno != EINVAL) {
+	perror("VIDIOC_QUERY_EXT_CTRL");
+	exit(EXIT_FAILURE);
+    }
+
+Example: Enumerating all user controls (old style)
+==================================================
+
+.. code-block:: c
+
+
+    memset(&queryctrl, 0, sizeof(queryctrl));
+
     for (queryctrl.id = V4L2_CID_BASE;
 	 queryctrl.id < V4L2_CID_LASTP1;
 	 queryctrl.id++) {
@@ -349,7 +397,7 @@ Example: Enumerating all user controls
 	    printf("Control %s\\n", queryctrl.name);
 
 	    if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
-		enumerate_menu();
+		enumerate_menu(queryctrl.id);
 	} else {
 	    if (errno == EINVAL)
 		continue;
@@ -368,7 +416,7 @@ Example: Enumerating all user controls
 	    printf("Control %s\\n", queryctrl.name);
 
 	    if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
-		enumerate_menu();
+		enumerate_menu(queryctrl.id);
 	} else {
 	    if (errno == EINVAL)
 		break;
@@ -379,32 +427,6 @@ Example: Enumerating all user controls
     }
 
 
-Example: Enumerating all user controls (alternative)
-====================================================
-
-.. code-block:: c
-
-    memset(&queryctrl, 0, sizeof(queryctrl));
-
-    queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
-    while (0 == ioctl(fd, VIDIOC_QUERYCTRL, &queryctrl)) {
-	if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
-	    break;
-	if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
-	    continue;
-
-	printf("Control %s\\n", queryctrl.name);
-
-	if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
-	    enumerate_menu();
-
-	queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
-    }
-    if (errno != EINVAL) {
-	perror("VIDIOC_QUERYCTRL");
-	exit(EXIT_FAILURE);
-    }
-
 Example: Changing controls
 ==========================
 
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/crop_files/crop.gif and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/crop_files/crop.gif differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/crop_files/crop.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/crop_files/crop.pdf differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/crop.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/crop.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/crop.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/crop.rst	2017-02-12 16:03:20.000000000 -0500
@@ -53,8 +53,8 @@ Cropping Structures
 
 .. _crop-scale:
 
-.. figure::  crop_files/crop.*
-    :alt:    crop.pdf / crop.gif
+.. figure::  crop.*
+    :alt:    crop.pdf / crop.svg
     :align:  center
 
     Image Cropping, Insertion and Scaling
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/crop.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/crop.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/crop.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/crop.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   xml:space="preserve"
+   width="208.59436mm"
+   height="95.859146mm"
+   viewBox="0 0 739.11388 339.6584"
+   sodipodi:docname="crop.svg"><metadata
+     id="metadata8"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs6"><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath44"><path
+         d="m 0,0 0,1895 4118,0 L 4118,0 0,0 Z m 3051.62,250.48 8.19,17.01 -46.93,23.31 29.61,-25.515 -38.12,8.505 47.25,-23.31 z m -1559.25,800.73 -8.5,-17.01 46.93,-23.31 -29.29,25.2 37.8,-8.19 -46.94,23.31 z"
+         id="path46"
+         inkscape:connector-curvature="0"
+         style="clip-rule:evenodd" /></clipPath><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath64"><path
+         d="m 0,0 0,1895 4118,0 0,-1626 -1,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -1,0 0,-1 1,0 0,-1 1,0 0,-1 2,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 2,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 2,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 1,0 0,-1 -4,0 0,1 -5,0 0,1 -4,0 0,1 -5,0 0,1 -4,0 0,1 -4,0 0,1 -4,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 1,0 0,3 1,0 0,2 1,0 0,2 1,0 L 4118,0 0,0 Z m 4074,272 0,-1 1,0 0,1 -1,0 z m -1486,743 0,-1 1,0 0,1 -1,0 z m -2,1 0,-1 1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -2,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -2,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -1,0 0,1 -2,0 0,1 -1,0 0,2 2,0 0,-1 4,0 0,-1 5,0 0,-1 4,0 0,-1 5,0 0,-1 5,0 0,-1 4,0 0,-1 3,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -3,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,1 -2,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 -1,0 0,-2 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 0,-1 2,0 z"
+         id="path66"
+         inkscape:connector-curvature="0"
+         style="clip-rule:evenodd" /></clipPath><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath84"><path
+         d="m 0,0 0,1895 4118,0 0,-136 -3,0 0,-1 -11,0 0,-1 -11,0 0,-1 -11,0 0,-1 -11,0 0,-1 5,0 0,-1 6,0 0,-1 7,0 0,-1 6,0 0,-1 6,0 0,-1 4,0 0,-1 -1,0 0,-1 -3,0 0,-1 -3,0 0,-1 -2,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 -3,0 0,-1 7,0 0,1 11,0 0,1 11,0 0,1 11,0 0,1 3,0 L 4118,0 0,0 Z m 2552,1599 0,-1 2,0 0,1 11,0 0,1 11,0 0,1 11,0 0,1 11,0 0,1 -4,0 0,1 -7,0 0,1 -6,0 0,1 -7,0 0,1 -6,0 0,1 -3,0 0,1 2,0 0,1 2,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 2,0 0,1 3,0 0,1 3,0 0,1 3,0 0,1 -7,0 0,-1 -12,0 0,-1 -11,0 0,-1 -11,0 0,-1 -4,0 0,-1 1,0 0,-12 1,0 0,-4 z"
+         id="path86"
+         inkscape:connector-curvature="0"
+         style="clip-rule:evenodd" /></clipPath><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath104"><path
+         d="m 0,0 0,1895 4118,0 L 4118,0 0,0 Z m 3056.98,1740.43 -1.58,18.9 -52.6,-4.72 38.74,-6.3 -36.85,-12.6 52.29,4.72 z m -1570.28,-123.79 1.58,-18.9 52.6,4.72 -38.43,5.99 36.54,12.91 -52.29,-4.72 z"
+         id="path106"
+         inkscape:connector-curvature="0"
+         style="clip-rule:evenodd" /></clipPath></defs><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview4"
+     showgrid="false"
+     inkscape:zoom="0.99625351"
+     inkscape:cx="-73.227122"
+     inkscape:cy="114.17568"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g10"
+     units="mm"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" /><g
+     id="g10"
+     inkscape:groupmode="layer"
+     inkscape:label="crop"
+     transform="matrix(1.25,0,0,-1.25,-0.35237428,339.91141)"><path
+       d="m 411.08474,0.37218832 0,271.38551168 -37.17867,0 0,-1.94649 -205.3611,1.94649 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,-264.3219406 -17.977663,0 0,-2.58119108 193.135216,0 0,2.58119108 -137.934309,0 0,264.3219406 333.650679,0 0,-264.3219406 -177.10547,0 0,-1.947197 149.52695,0 0,-0.63399408"
+       style="fill:#7f7f7f;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path16"
+       inkscape:connector-curvature="0" /><path
+       d="m 411.08474,0.37218832 0,271.38551168 -37.17867,0 0,-1.94649 -205.3611,1.94649 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,-264.3219406 -17.977663,0 0,-2.58119108 193.135216,0 0,2.58119108 -137.934309,0 0,264.3219406 333.650679,0 0,-264.3219406 -177.10547,0 0,-1.947197 149.52695,0 0,-0.63399408 37.17867,0 z"
+       style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path18"
+       inkscape:connector-curvature="0" /><path
+       d="m 40.256106,6.8024838 366.979524,0 0,253.4078762 -366.979524,0 0,-253.4078762 z"
+       style="fill:none;stroke:#ff0000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path20"
+       inkscape:connector-curvature="0" /><path
+       d="m 77.434066,7.4364707 316.352284,0 0,244.4416893 -316.352284,0 0,-244.4416893 z"
+       style="fill:none;stroke:#0000ff;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path22"
+       inkscape:connector-curvature="0" /><path
+       d="m 214.41669,149.49157 152.83195,0 0,81.51075 -152.83195,0 0,-81.51075 z"
+       style="fill:none;stroke:#00b000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path24"
+       inkscape:connector-curvature="0" /><path
+       d="m 438.57126,37.414285 152.83194,0 0,213.966445 -152.83194,0 0,-213.966445 z"
+       style="fill:none;stroke:#d100d1;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path26"
+       inkscape:connector-curvature="0" /><path
+       d="m 0.45168907,271.7577 168.09328093,0 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,0 0,-264.3219406 -17.977663,0 0,-2.58119108 -12.18131493,0"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path28"
+       inkscape:connector-curvature="0" /><path
+       d="m 0.45168907,271.7577 168.09328093,0 0,-2.58046 -155.911966,0 0,-1.90192 17.977663,0 0,-264.3219406 -17.977663,0 0,-2.58119108 -12.18131493,0 0,271.38551168 z"
+       style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path30"
+       inkscape:connector-curvature="0" /><path
+       d="m 373.90607,0.37218832 0,0.63399408 -149.52695,0 0,1.947197 -18.6109,0 0,-2.58119108"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path32"
+       inkscape:connector-curvature="0" /><path
+       d="m 373.90607,0.37218832 0,0.63399408 -149.52695,0 0,1.947197 -18.6109,0 0,-2.58119108 168.13785,0 z"
+       style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path34"
+       inkscape:connector-curvature="0" /><path
+       d="m 205.76822,271.7577 168.13785,0 0,-1.94649 -149.52695,0 0,-2.53589 -18.6109,0"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path36"
+       inkscape:connector-curvature="0" /><path
+       d="m 205.76822,271.7577 168.13785,0 0,-1.94649 -149.52695,0 0,-2.53589 -18.6109,0 0,4.48238 z"
+       style="fill:none;stroke:#000000;stroke-width:0.33962813;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path38"
+       inkscape:connector-curvature="0" /><g
+       id="g40"
+       transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+         clip-path="url(#clipPath44)"
+         id="g42"><path
+           inkscape:connector-curvature="0"
+           id="path48"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="M 1492.37,1040.5 3051.62,260.875" /></g></g><g
+       id="g50"
+       transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><path
+         inkscape:connector-curvature="0"
+         id="path52"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1539.31,1027.9 -37.8,8.19 29.29,-25.2 8.51,17.01" /><path
+         inkscape:connector-curvature="0"
+         id="path54"
+         style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1539.31,1027.9 -37.8,8.19 29.29,-25.2 8.51,17.01 z" /><path
+         inkscape:connector-curvature="0"
+         id="path56"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 3004.37,273.79 38.12,-8.505 -29.61,25.515 -8.51,-17.01" /><path
+         inkscape:connector-curvature="0"
+         id="path58"
+         style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 3004.37,273.79 38.12,-8.505 -29.61,25.515 -8.51,-17.01 z" /></g><g
+       id="g60"
+       transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+         clip-path="url(#clipPath64)"
+         id="g62"><path
+           inkscape:connector-curvature="0"
+           id="path68"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="M 2555.5,1040.5 4114.75,260.875" /></g></g><g
+       id="g70"
+       transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><path
+         inkscape:connector-curvature="0"
+         id="path72"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2602.43,1027.9 -37.8,8.19 29.3,-25.2 8.5,17.01" /><path
+         inkscape:connector-curvature="0"
+         id="path74"
+         style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2602.43,1027.9 -37.8,8.19 29.3,-25.2 8.5,17.01 z" /><path
+         inkscape:connector-curvature="0"
+         id="path76"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 4067.5,273.79 38.11,-8.505 -29.61,25.515 -8.5,-17.01" /><path
+         inkscape:connector-curvature="0"
+         id="path78"
+         style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4067.5,273.79 38.11,-8.505 -29.61,25.515 -8.5,-17.01 z" /></g><g
+       id="g80"
+       transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+         clip-path="url(#clipPath84)"
+         id="g82"><path
+           inkscape:connector-curvature="0"
+           id="path88"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="m 2555.5,1607.5 1559.25,141.75" /></g></g><g
+       id="g90"
+       transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><path
+         inkscape:connector-curvature="0"
+         id="path92"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 2602.12,1621.36 -36.54,-12.91 38.43,-5.99 -1.89,18.9" /><path
+         inkscape:connector-curvature="0"
+         id="path94"
+         style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2602.12,1621.36 -36.54,-12.91 38.43,-5.99 -1.89,18.9 z" /><path
+         inkscape:connector-curvature="0"
+         id="path96"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 4067.81,1735.71 36.86,12.6 -38.75,6.3 1.89,-18.9" /><path
+         inkscape:connector-curvature="0"
+         id="path98"
+         style="fill:none;stroke:#000000;stroke-width:4.7249999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4067.81,1735.71 36.86,12.6 -38.75,6.3 1.89,-18.9 z" /></g><g
+       id="g100"
+       transform="matrix(0.14375794,0,0,0.14375794,-0.12334269,-0.08856738)"><g
+         clip-path="url(#clipPath104)"
+         id="g102"><path
+           inkscape:connector-curvature="0"
+           id="path108"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="m 1492.37,1607.5 1559.25,141.75" /></g></g><path
+       d="m 221.11869,232.99481 -5.25292,-1.85592 5.52462,-0.86111 -0.2717,2.71703"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path112"
+       inkscape:connector-curvature="0" /><path
+       d="m 221.11869,232.99481 -5.25292,-1.85592 5.52462,-0.86111 -0.2717,2.71703 z"
+       style="fill:none;stroke:#000000;stroke-width:0.67925626;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path114"
+       inkscape:connector-curvature="0" /><path
+       d="m 431.8247,249.43353 5.29748,1.81135 -5.56918,0.90567 0.2717,-2.71702"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path116"
+       inkscape:connector-curvature="0" /><path
+       d="m 431.8247,249.43353 5.29748,1.81135 -5.56918,0.90567 0.2717,-2.71702 z"
+       style="fill:none;stroke:#000000;stroke-width:0.67925626;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path118"
+       inkscape:connector-curvature="0" /><g
+       id="g120"
+       transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+         transform="matrix(1,0,0,-1,204.52,9.07751)"
+         style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#d10000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="text122"><tspan
+           x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 19.11735 21.320145 24.998085 28.676025 31.983524 35.661465 39.339405 41.178375 44.856316 48.534256 52.212196 55.890137 59.568073"
+           y="0"
+           sodipodi:role="line"
+           id="tspan124">v4l2_cropcap.bounds</tspan></text>
+</g><g
+       id="g126"
+       transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+         transform="matrix(1,0,0,-1,58.5175,166.42)"
+         style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#0000d1;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="text128"><tspan
+           x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 19.11735 21.320145 24.998085 28.676025 31.983524 35.661465 39.339405 41.178375 44.856316 48.534256 50.373226 52.576019 56.25396 59.561459"
+           y="0"
+           sodipodi:role="line"
+           id="tspan130">v4l2_cropcap.defrect</tspan></text>
+</g><g
+       id="g132"
+       transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+         transform="matrix(1,0,0,-1,153.49,152.245)"
+         style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#008f00;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="text134"><tspan
+           x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 19.11735 21.320145 24.998085 28.676025 30.514996"
+           y="0"
+           sodipodi:role="line"
+           id="tspan136">v4l2_crop.c</tspan></text>
+</g><g
+       id="g138"
+       transform="matrix(1.4375794,0,0,1.4375794,-0.12334269,-0.08856738)"><text
+         transform="matrix(1,0,0,-1,309.415,30.34)"
+         style="font-variant:normal;font-weight:normal;font-size:6.61499977px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#b000b0;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="text140"><tspan
+           x="0 3.3074999 6.9854398 8.45397 12.13191 15.80985 17.648821 21.326759 23.529554 29.03985 32.717789"
+           y="0"
+           sodipodi:role="line"
+           id="tspan142">v4l2_format</tspan></text>
+</g><text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:32px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="-99.291145"
+       y="-239.49893"
+       id="text3396"
+       sodipodi:linespacing="125%"
+       transform="scale(1,-1)"><tspan
+         sodipodi:role="line"
+         id="tspan3398"
+         x="-99.291145"
+         y="-239.49893"></tspan><tspan
+         sodipodi:role="line"
+         x="-99.291145"
+         y="-199.49893"
+         id="tspan3400" /></text>
+</g></svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-codec.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-codec.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-codec.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-codec.rst	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@ parameters
    The MPEG controls actually support many more codecs than
    just MPEG. See :ref:`mpeg-controls`.
 
-Memory-to-memory devices can often be used as a shared resource: you can
+Memory-to-memory devices function as a shared resource: you can
 open the video node multiple times, each application setting up their
 own codec properties that are local to the file handle, and each can use
 it independently from the others. The driver will arbitrate access to
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.gif and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.gif differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_525.pdf differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.gif and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.gif differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_625.pdf differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.gif and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.gif differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi_files/vbi_hsync.pdf differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-raw-vbi.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-raw-vbi.rst	2017-02-12 16:03:20.000000000 -0500
@@ -221,8 +221,8 @@ and always returns default parameters as
 
 .. _vbi-hsync:
 
-.. figure::  dev-raw-vbi_files/vbi_hsync.*
-    :alt:    vbi_hsync.pdf / vbi_hsync.gif
+.. figure::  vbi_hsync.*
+    :alt:    vbi_hsync.pdf / vbi_hsync.svg
     :align:  center
 
     **Figure 4.1. Line synchronization**
@@ -230,8 +230,8 @@ and always returns default parameters as
 
 .. _vbi-525:
 
-.. figure::  dev-raw-vbi_files/vbi_525.*
-    :alt:    vbi_525.pdf / vbi_525.gif
+.. figure::  vbi_525.*
+    :alt:    vbi_525.pdf / vbi_525.svg
     :align:  center
 
     **Figure 4.2. ITU-R 525 line numbering (M/NTSC and M/PAL)**
@@ -240,8 +240,8 @@ and always returns default parameters as
 
 .. _vbi-625:
 
-.. figure::  dev-raw-vbi_files/vbi_625.*
-    :alt:    vbi_625.pdf / vbi_625.gif
+.. figure::  vbi_625.*
+    :alt:    vbi_625.pdf / vbi_625.svg
     :align:  center
 
     **Figure 4.3. ITU-R 625 line numbering**
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.pdf differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.png and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/pipeline.png differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.pdf differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-crop.svg	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="43cm" height="10cm" viewBox="-194 128 844 196" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-  <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="469.774" height="193"/>
-  <g>
-    <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/>
-  </g>
-  <g>
-    <rect style="fill: #ffffff" x="63.5" y="211" width="94" height="77"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="63.5" y="211" width="94" height="77"/>
-  </g>
-  <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="74.5" y="227.75">
-    <tspan x="74.5" y="227.75">sink</tspan>
-    <tspan x="74.5" y="243.75">crop</tspan>
-    <tspan x="74.5" y="259.75">selection</tspan>
-  </text>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158">
-    <tspan x="29.5" y="158"></tspan>
-  </text>
-  <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914">
-    <tspan x="8.53836" y="157.914">sink media</tspan>
-    <tspan x="8.53836" y="173.914">bus format</tspan>
-  </text>
-  <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="349.774" y="155">
-    <tspan x="349.774" y="155">source media</tspan>
-    <tspan x="349.774" y="171">bus format</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="350.488" y="190.834" width="93.2863" height="75.166"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="350.488" y="190.834" width="93.2863" height="75.166"/>
-  </g>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="266" x2="63.5" y2="288"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="350.488" y1="190.834" x2="63.5" y2="211"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="266" x2="157.5" y2="288"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="443.774" y1="190.834" x2="157.5" y2="211"/>
-  <g>
-    <ellipse style="fill: #ffffff" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="473.1" cy="219.984" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="481.6" y1="219.984" x2="637.934" y2="220.012"/>
-    <polygon style="fill: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="645.434,220.014 635.433,225.012 637.934,220.012 635.435,215.012 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="506.908" y="209.8">
-    <tspan x="506.908" y="209.8">pad 1 (source)</tspan>
-  </text>
-  <g>
-    <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/>
-    <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8">
-    <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan>
-  </text>
-</svg>
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.pdf differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-full.svg	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="59cm" height="18cm" viewBox="-186 71 1178 346" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-  <g>
-    <rect style="fill: #ffffff" x="318.9" y="129" width="208.1" height="249"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #ff765a" x="318.9" y="129" width="208.1" height="249"/>
-  </g>
-  <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-2" y="73" width="806" height="343"/>
-  <g>
-    <ellipse style="fill: #ffffff" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.5" cy="166.712" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <ellipse style="fill: #ffffff" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.232" cy="205.184" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.5" y1="167" x2="-30.7361" y2="166.729"/>
-    <polygon style="fill: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-23.2361,166.716 -33.2272,171.734 -30.7361,166.729 -33.2449,161.734 "/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.732" y1="205.184" x2="980.066" y2="205.212"/>
-    <polygon style="fill: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.566,205.214 977.565,210.212 980.066,205.212 977.567,200.212 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139.96" y="155">
-    <tspan x="-139.96" y="155">pad 0 (sink)</tspan>
-  </text>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.04" y="195">
-    <tspan x="849.04" y="195">pad 2 (source)</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="5.5" y="120" width="159" height="104"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="5.5" y="120" width="159" height="104"/>
-  </g>
-  <g>
-    <rect style="fill: #ffffff" x="62.5" y="136" width="94" height="77"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="62.5" y="136" width="94" height="77"/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="30.5" y="89">
-    <tspan x="30.5" y="89"></tspan>
-  </text>
-  <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="9.53836" y="88.9138">
-    <tspan x="9.53836" y="88.9138">sink media</tspan>
-    <tspan x="9.53836" y="104.914">bus format</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/>
-  </g>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="62.5" y2="213"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="62.5" y2="136"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="156.5" y2="213"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="156.5" y2="136"/>
-  <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442">
-    <tspan x="334.704" y="149.442">sink compose</tspan>
-    <tspan x="334.704" y="165.442">selection (scaling)</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="409.322" y="194.565" width="100.186" height="71.4523"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="409.322" y="194.565" width="100.186" height="71.4523"/>
-  </g>
-  <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="689.5" y="105.128">
-    <tspan x="689.5" y="105.128">source media</tspan>
-    <tspan x="689.5" y="121.128">bus format</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="688.488" y="173.834" width="100.186" height="71.4523"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="688.488" y="173.834" width="100.186" height="71.4523"/>
-  </g>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="245.286" x2="409.322" y2="266.018"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="688.488" y1="173.834" x2="409.322" y2="194.565"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="245.286" x2="509.508" y2="266.018"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="788.674" y1="173.834" x2="509.508" y2="194.565"/>
-  <text style="fill: #ff765a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="325" y="103">
-    <tspan x="325" y="103">sink compose</tspan>
-    <tspan x="325" y="119">bounds selection</tspan>
-  </text>
-  <g>
-    <ellipse style="fill: #ffffff" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-12.0982" cy="341.512" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-184.098" y1="341.8" x2="-30.3343" y2="341.529"/>
-    <polygon style="fill: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-22.8343,341.516 -32.8254,346.534 -30.3343,341.529 -32.8431,336.534 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-139" y="329">
-    <tspan x="-139" y="329">pad 1 (sink)</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="7.80824" y="292.8" width="112.092" height="82.2"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="7.80824" y="292.8" width="112.092" height="82.2"/>
-  </g>
-  <g>
-    <rect style="fill: #ffffff" x="52.9" y="314.8" width="58.1" height="50.2"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="52.9" y="314.8" width="58.1" height="50.2"/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="31.9" y="259.8">
-    <tspan x="31.9" y="259.8"></tspan>
-  </text>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="251.9" x2="52.9" y2="314.8"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="358.9" y1="316" x2="52.9" y2="365"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="316" x2="111" y2="365"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="434" y1="251.9" x2="111" y2="314.8"/>
-  <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="358.9" y="251.9" width="75.1" height="64.1"/>
-  <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="443.262" y="284.466" width="64.738" height="48.534"/>
-  <g>
-    <rect style="fill: #ffffff" x="693.428" y="324.734" width="63.572" height="49.266"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="693.428" y="324.734" width="63.572" height="49.266"/>
-  </g>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="374" x2="443.262" y2="333"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="693.428" y1="324.734" x2="443.262" y2="284.466"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="374" x2="508" y2="333"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="757" y1="324.734" x2="508" y2="284.466"/>
-  <g>
-    <ellipse style="fill: #ffffff" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="815.44" cy="343.984" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="823.94" y1="343.984" x2="980.274" y2="344.012"/>
-    <polygon style="fill: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="987.774,344.014 977.773,349.012 980.274,344.012 977.775,339.012 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="849.248" y="333.8">
-    <tspan x="849.248" y="333.8">pad 3 (source)</tspan>
-  </text>
-  <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="197" y="91">
-    <tspan x="197" y="91">sink</tspan>
-    <tspan x="197" y="107">crop</tspan>
-    <tspan x="197" y="123">selection</tspan>
-  </text>
-  <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="553" y="95">
-    <tspan x="553" y="95">source</tspan>
-    <tspan x="553" y="111">crop</tspan>
-    <tspan x="553" y="127">selection</tspan>
-  </text>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="211" y1="132" x2="166.21" y2="135.287"/>
-    <polygon style="fill: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="158.73,135.836 168.337,130.118 166.21,135.287 169.069,140.091 "/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x1="209" y1="131" x2="115.581" y2="306.209"/>
-    <polygon style="fill: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" points="112.052,312.827 112.345,301.65 115.581,306.209 121.169,306.355 "/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.492" y1="133.214" x2="514.916" y2="186.469"/>
-    <polygon style="fill: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="510.75,192.706 512.147,181.613 514.916,186.469 520.463,187.168 "/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="550.072" y1="133.787" x2="510.618" y2="275.089"/>
-    <polygon style="fill: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="508.601,282.312 506.475,271.336 510.618,275.089 516.106,274.025 "/>
-  </g>
-</svg>
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.pdf differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev_files/subdev-image-processing-scaling-multi-source.svg	1969-12-31 19:00:00.000000000 -0500
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
-<svg width="59cm" height="17cm" viewBox="-194 128 1179 330" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-  <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x="-8" y="130" width="806" height="327"/>
-  <g>
-    <rect style="fill: #ffffff" x="4.5" y="189" width="159" height="104"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a52a2a" x="4.5" y="189" width="159" height="104"/>
-  </g>
-  <g>
-    <rect style="fill: #ffffff" x="49.5" y="204" width="94" height="77"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #0000ff" x="49.5" y="204" width="94" height="77"/>
-  </g>
-  <text style="fill: #0000ff;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="60" y="224">
-    <tspan x="60" y="224">sink</tspan>
-    <tspan x="60" y="240">crop</tspan>
-    <tspan x="60" y="256">selection</tspan>
-  </text>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="29.5" y="158">
-    <tspan x="29.5" y="158"></tspan>
-  </text>
-  <text style="fill: #a52a2a;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="8.53836" y="157.914">
-    <tspan x="8.53836" y="157.914">sink media</tspan>
-    <tspan x="8.53836" y="173.914">bus format</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="333.644" y="185.65" width="165.2" height="172.478"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #00ff00" x="333.644" y="185.65" width="165.2" height="172.478"/>
-  </g>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="358.128" x2="49.5" y2="281"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="333.644" y1="185.65" x2="49.5" y2="204"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="358.128" x2="143.5" y2="281"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="498.844" y1="185.65" x2="143.5" y2="204"/>
-  <text style="fill: #00ff00;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="334.704" y="149.442">
-    <tspan x="334.704" y="149.442">sink compose</tspan>
-    <tspan x="334.704" y="165.442">selection (scaling)</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="382.322" y="199.565" width="100.186" height="71.4523"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="382.322" y="199.565" width="100.186" height="71.4523"/>
-  </g>
-  <text style="fill: #a020f0;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="543.322" y="149.442">
-    <tspan x="543.322" y="149.442">source</tspan>
-    <tspan x="543.322" y="165.442">crop</tspan>
-    <tspan x="543.322" y="181.442">selection</tspan>
-  </text>
-  <text style="fill: #8b6914;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="691.5" y="157.128">
-    <tspan x="691.5" y="157.128">source media</tspan>
-    <tspan x="691.5" y="173.128">bus format</tspan>
-  </text>
-  <g>
-    <rect style="fill: #ffffff" x="690.488" y="225.834" width="100.186" height="71.4523"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="690.488" y="225.834" width="100.186" height="71.4523"/>
-  </g>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="297.286" x2="382.322" y2="271.018"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="690.488" y1="225.834" x2="382.322" y2="199.565"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="297.286" x2="482.508" y2="271.018"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.674" y1="225.834" x2="482.508" y2="199.565"/>
-  <g>
-    <ellipse style="fill: #ffffff" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="808.1" cy="249.984" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="816.6" y1="249.984" x2="972.934" y2="250.012"/>
-    <polygon style="fill: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="980.434,250.014 970.433,255.012 972.934,250.012 970.435,245.012 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="841.908" y="239.8">
-    <tspan x="841.908" y="239.8">pad 1 (source)</tspan>
-  </text>
-  <g>
-    <ellipse style="fill: #ffffff" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="-20.3982" cy="241.512" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="-192.398" y1="241.8" x2="-38.6343" y2="241.529"/>
-    <polygon style="fill: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="-31.1343,241.516 -41.1254,246.534 -38.6343,241.529 -41.1431,236.534 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="-147.858" y="229.8">
-    <tspan x="-147.858" y="229.8">pad 0 (sink)</tspan>
-  </text>
-  <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x="389.822" y="276.666" width="100.186" height="71.4523"/>
-  <g>
-    <rect style="fill: #ffffff" x="689.988" y="345.934" width="100.186" height="71.4523"/>
-    <rect style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #8b6914" x="689.988" y="345.934" width="100.186" height="71.4523"/>
-  </g>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="417.386" x2="389.822" y2="348.118"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="689.988" y1="345.934" x2="389.822" y2="276.666"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="417.386" x2="490.008" y2="348.118"/>
-  <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke-dasharray: 4; stroke: #e60505" x1="790.174" y1="345.934" x2="490.008" y2="276.666"/>
-  <g>
-    <ellipse style="fill: #ffffff" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
-    <ellipse style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" cx="805.6" cy="384.084" rx="8.5" ry="8.5"/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" x1="814.1" y1="384.084" x2="970.434" y2="384.112"/>
-    <polygon style="fill: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #000000" points="977.934,384.114 967.933,389.112 970.434,384.112 967.935,379.112 "/>
-  </g>
-  <text style="fill: #000000;text-anchor:start;font-size:12.8;font-family:sanserif;font-style:normal;font-weight:normal" x="839.408" y="373.9">
-    <tspan x="839.408" y="373.9">pad 2 (source)</tspan>
-  </text>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546" y1="191" x2="492.157" y2="198.263"/>
-    <polygon style="fill: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="484.724,199.266 493.966,192.974 492.157,198.263 495.303,202.884 "/>
-  </g>
-  <g>
-    <line style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" x1="546.908" y1="190.725" x2="495.383" y2="268.548"/>
-    <polygon style="fill: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/>
-    <polygon style="fill: none; fill-opacity:0; stroke-width: 2; stroke: #a020f0" points="491.242,274.802 492.594,263.703 495.383,268.548 500.932,269.224 "/>
-  </g>
-</svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/dev-subdev.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/dev-subdev.rst	2017-02-12 16:03:20.000000000 -0500
@@ -99,8 +99,8 @@ the video sensor and the host image proc
 
 .. _pipeline-scaling:
 
-.. figure::  dev-subdev_files/pipeline.*
-    :alt:    pipeline.pdf / pipeline.png
+.. figure::  pipeline.*
+    :alt:    pipeline.pdf / pipeline.svg
     :align:  center
 
     Image Format Negotiation on Pipelines
@@ -404,8 +404,8 @@ selection will refer to the sink pad for
 
 .. _subdev-image-processing-crop:
 
-.. figure::  dev-subdev_files/subdev-image-processing-crop.*
-    :alt:    subdev-image-processing-crop.svg
+.. figure::  subdev-image-processing-crop.*
+    :alt:    subdev-image-processing-crop.pdf / subdev-image-processing-crop.svg
     :align:  center
 
     **Figure 4.5. Image processing in subdevs: simple crop example**
@@ -421,8 +421,8 @@ pad.
 
 .. _subdev-image-processing-scaling-multi-source:
 
-.. figure::  dev-subdev_files/subdev-image-processing-scaling-multi-source.*
-    :alt:    subdev-image-processing-scaling-multi-source.svg
+.. figure::  subdev-image-processing-scaling-multi-source.*
+    :alt:    subdev-image-processing-scaling-multi-source.pdf / subdev-image-processing-scaling-multi-source.svg
     :align:  center
 
     **Figure 4.6. Image processing in subdevs: scaling with multiple sources**
@@ -437,8 +437,8 @@ an area at location specified by the sou
 
 .. _subdev-image-processing-full:
 
-.. figure::  dev-subdev_files/subdev-image-processing-full.*
-    :alt:    subdev-image-processing-full.svg
+.. figure::  subdev-image-processing-full.*
+    :alt:    subdev-image-processing-full.pdf / subdev-image-processing-full.svg
     :align:  center
 
     **Figure 4.7. Image processing in subdevs: scaling and composition with multiple sinks and sources**
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/diff-v4l.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/diff-v4l.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/diff-v4l.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/diff-v4l.rst	2017-02-12 16:03:20.000000000 -0500
@@ -648,12 +648,12 @@ microcode programming. A new interface f
 devices is documented in :ref:`extended-controls`.
 
 .. [#f1]
-   According to Documentation/devices.txt these should be symbolic links
+   According to Documentation/admin-guide/devices.rst these should be symbolic links
    to ``/dev/video0``. Note the original bttv interface is not
    compatible with V4L or V4L2.
 
 .. [#f2]
-   According to ``Documentation/devices.txt`` a symbolic link to
+   According to ``Documentation/admin-guide/devices.rst`` a symbolic link to
    ``/dev/radio0``.
 
 .. [#f3]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/extended-controls.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/extended-controls.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/extended-controls.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/extended-controls.rst	2017-02-12 16:03:20.000000000 -0500
@@ -2846,7 +2846,7 @@ JPEG Control IDs
     input image is sampled, in respect to maximum sample rate in each
     spatial dimension. See :ref:`itu-t81`, clause A.1.1. for more
     details. The ``V4L2_CID_JPEG_CHROMA_SUBSAMPLING`` control determines
-    how Cb and Cr components are downsampled after coverting an input
+    how Cb and Cr components are downsampled after converting an input
     image from RGB to Y'CbCr color space.
 
 .. tabularcolumns:: |p{7.0cm}|p{10.5cm}|
@@ -3017,6 +3017,10 @@ Image Process Control IDs
     test pattern images. These hardware specific test patterns can be
     used to test if a device is working properly.
 
+``V4L2_CID_DEINTERLACING_MODE (menu)``
+    The video deinterlacing mode (such as Bob, Weave, ...). The menu items are
+    driver specific and are documented in :ref:`v4l-drivers`.
+
 
 .. _dv-controls:
 
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.gif and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.gif differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.pdf and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_bt.pdf differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.gif and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.gif differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdf linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdf
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdf	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/field-order_files/fieldseq_tb.pdf	1969-12-31 19:00:00.000000000 -0500
@@ -1,151 +0,0 @@
-%PDF-1.4
-%�쏢
-5 0 obj
-<</Length 6 0 R/Filter /FlateDecode>>
-stream
-x���Qoܸ���+��$�Q"E�oI�.�p7�̠}�A���v�q�ݿ_j����>�@`��./|i��n����ϗ��7�}�����wC�w/_�o�2�!�6�؇��S��з�9汽:kΟ5C�ihkv���w�x�feƾ�)��@���S4"
-�(��dDQ�9�Q���_����}4�嗦������5
-mnbel5�RR(��3mVF���@���C(}�!���!�#1�<��&ƞ�@�ƞ�6<�u%�8�����i���)=�AM�Cw�x�|�� ��
�ɟ�!c	c6=D!uCF�d(�}�J�&�p�h�/�[��V)
�n"�}�Z�>
��يC ��z1�Q��Ō�1xcs
-��BQ7�\�!�>�\�!�a���C�s��=}��Z[���L���x���M!�p吸�!����h�#�%-���{XR-�G�F=$Z�klGS>pH�8M1�.*($Z<�a�z�1��y���b�B��5���w-s��� 3�a�̈QLuȘy�C�K���E)�6�<a��M="�M=t������C����=*�zH�XeS��l�!�b�M=$Z����D�U6��h�Ȧ��U��C��"�zH�XeSAfP��C��D6���C�M=�g��������:�c�m��!�آ�C(�z[�sD%&[�q���m�!����b�(�z1wk��5��<�~��}�!�>��T�yDj�y�H�=a���!���!���Ğ��0�/zW�Ph�)�Abr>�@�u���C�h����3�`�<��s����P�%3yqh�)���Oa�Q�!�&��C�HF��@���C�G"�,�kX"�<7���C�G���C�&.����f����Ҧn.K�59y�s�߮�O}���2��I�܇~��=�w5yv�)c�/χ;��!�o�4��!ł�C�v�<|k���S��4��>�ԩrux<�Z������Z��_K1wk�S��}�f��7+��="��!�}@�H�'{�H�'{�H�'{Eb?�C�F�}�!�oU�yD��<�"�g���>c�Cxkb�yDj�yH�-��5���eP#��="��!�j�C R{��>{��>{���J��{h�{��!�=x�H��[oL��{Eb�C�Cb�C�Cb�C��
-y�r*7�*���D1s��j��c?�)tw���P�J5VLFڬ���=�"1�yDj������!��C R�@�f
�HM�B��~<���LoԈY�C(%��@��C�H�ZEr5�C(K��Z������@�ַ=�"���!��r�H�JxV��K$�+S��ׇ�k$�/�Hh��T/[�q�[�Н���Z�4��*cBb���E���)�����S���:�^�!Xѝ�PǭYҥ�*�fw��C �]���#Ag��b�Y��tv����sh�le<yDyjmG��%G�>Rq�!�8�t��#Ag�8����
-��<��AmV���ۈx����o�@�'���S��cf\�)P�;�����!�tN�
-=�VqjU2��0�q�@�#��8��$���)P���*N���lK�AP��\B[%�Uu���JP����X=�>JX���R�����p
��8�*X�*J�
-�1��R����*�����pٓ�=�PK�BE)T��PQ
-T���U�B,�
-�@���D!�ڮ0Q
-��m��)T��PQ
-T���U�B�p�@�kt
-
-U���[�)T�:�PQ
-T���U��2~���RX&�atQ'S
-e8�/
-eJa�_B�2��P�o`�B�R���������p�������F;�/�N)P�9<n��:U�N)�t8�':�R����#U	
-Tx@��8*<D�U���
-O�t,(��K}�<�к��2�H4"
-�(O�bf��C(�e9Έ�Z�ԇdD�0�IQͶ��XQ�-4��@r��C�����!�=�Hm�xDjK�C�Gb'�C�Gb�C(�VZE2?yD*?yD*?yE"?yD*?yD*?yD*?yD*?yh�Ƒ�#�Hő�@���C(q�!�8��TyD*�<"G_8S9�C�k�r��@�r��P$r��@�ja�Z�Cxk���T-�!(�J�`��q��!�/fy��4�ө���y�����⹌��������s��9w�!uc����
-�=��!�OYg2N��N���p���d��D8y�(N�9J���P$��C8ىp��"�<�ŷ�"a�̣�2X1�(�V�"�<���"�HD����Q�M�Mc�u��z�h�8�_v��h>4�L�RQ�i.Kqs٤i��8ݾr��2�ZX//���_�J���RF�V�������z�q(eZ�e���)S�	A�i^��y�`���5��cc�Ӈ}���_�x��o?~�l_n��o����<������ǡc��T��rn��3%�������I���������ՏO��n���������o_��n_����^|q�=~�Ë�q}}��09��^4�~!G������E��_����]��g�X��Pr�����q�IGq.]��s����~�-i�����U���˝=��\_����޶g��|�zw�~�:=��}{���vw���W_���w��^~��>;mzrއ��w�|q��ӥrk��w�}s����e���%c����"`��P�ɋ?�Vo�����w�:;���o�U�0����ۇ��Ut����u�_�q�0endstream
-endobj
-6 0 obj
-2760
-endobj
-4 0 obj
-<</Type/Page/MediaBox [0 0 566 600]
-/Parent 3 0 R
-/Resources<</ProcSet[/PDF /Text]
-/ExtGState 10 0 R
-/Font 11 0 R
->>
-/Contents 5 0 R
->>
-endobj
-3 0 obj
-<< /Type /Pages /Kids [
-4 0 R
-] /Count 1
->>
-endobj
-1 0 obj
-<</Type /Catalog /Pages 3 0 R
-/Metadata 13 0 R
->>
-endobj
-7 0 obj
-<</Type/ExtGState
-/OPM 1>>endobj
-10 0 obj
-<</R7
-7 0 R>>
-endobj
-11 0 obj
-<</R8
-8 0 R>>
-endobj
-8 0 obj
-<</BaseFont/SEXXTC+Helvetica/FontDescriptor 9 0 R/Type/Font
-/FirstChar 32/LastChar 118/Widths[
-278 0 0 0 0 0 0 0 333 333 0 0 278 0 278 278
-0 0 556 0 556 0 0 0 0 0 278 0 0 0 0 0
-0 667 667 722 722 667 611 778 0 278 0 0 556 833 722 778
-667 778 722 667 611 0 667 0 0 0 0 0 0 0 0 556
-0 556 556 0 556 556 278 556 0 222 0 0 222 833 556 556
-556 0 333 500 278 556 500]
-/Encoding/WinAnsiEncoding/Subtype/Type1>>
-endobj
-9 0 obj
-<</Type/FontDescriptor/FontName/SEXXTC+Helvetica/FontBBox[-22 -218 762 741]/Flags 4
-/Ascent 741
-/CapHeight 741
-/Descent -218
-/ItalicAngle 0
-/StemV 114
-/MissingWidth 278
-/CharSet(/A/B/C/D/E/F/G/I/L/M/N/O/P/Q/R/S/T/V/a/b/colon/comma/d/e/f/four/g/i/l/m/n/o/p/parenleft/parenright/period/r/s/slash/space/t/two/u/underscore/v)/FontFile3 12 0 R>>
-endobj
-12 0 obj
-<</Filter/FlateDecode
-/Subtype/Type1C/Length 2959>>stream
-x��ViTW����>�� Q$���� ��
-��(�l*� �q�b���bL4n�����[4�
-�F0��6`78m�(	���y͙y
f&ɯ9�ϩ~U�n������e�~˲�!����˖&�Vx�����$9De�mȓc����� K�¡��@� ���d�X��g����y�)٫��G;dd�e-KM�v�����$ρ>�\�\���!:Q��!�!*95'=1�O7�����0�k�TUĴ��Ȁ�䙁)���RgO_��,:gNhnz�\�Og�Q��&����Gf&��gf1A�;���f�3�GL03��D3!�'3���x1�L�x3s���3��`�1�H&��1��1gXfc�a2S7
-%c���ֽ�v4���b����wQ�_�$)�t�M0K0;,u��^��rk���8>��	r�W�r�d���'��3�c���̻��Y�Y8[Z,�Ȅ"+\�4^�>�K`�A)��(q��9+�;R��&�f�
-2�'$C�ő���Xr�`�R��k�)|�$�uXB��O��l��[aw�����ƂV�¿�]�����p9�wv�a�G�em~(V�h�������f���>���B"�t%y��cM�
�R"�(u8Xj�)M
���:�M����z;Yw�-h�:t���+�ԷP�--w+d�aѹ�'7����2NO��B�7�)��q)�
-B^��V�nMY��߂8=Wv#��k�\+���X$�^�$���(pn�):���V��_��'�d�lw��F����Q��	�4���=��[-�O!�@Npi��g��@�z�L"A/�?�8]}M1�1O��D��ʗؐ�'y�G>+������ʐ҇�S��$�h</��3�z�N:0�ݴ�)��Z�^�K.�*�vo"�h�M���:sD,K�j�f���3����/�!F���_�y�Uzxd�D��G� @���U�d)�fZq Z�g$*5��iSa"�M���uQ��p��S��	0T,L���Џ(��@�")Bh�e��9X.��ǉd����������Y{_ ��Y�lѓ��ח�w�T��Y�p%2�L�pg�l��@1�˞����B��ܢ��®Zq��Z��v7ԕ�x��z|H/���<�$G�F֐<���Bj{��w�KA��B��D�d���<%$�:K��É
-!B~����h�}
ۮ�C��v[8�A8HA�!����D(�9N�3D��a
-NO]H$���B�VPD�D�;���(l!�TO��5�L���;zQ.�܇v�c;�:~͞Ow�E�L�(~��us2}�1��q�N�{Q_��~
�R��%4��"�qU�ڑ��^:V�
-0lb#q������C�`?����N�4w���Or�5�^�vPۘm"�Pc��c�qu��8���4���6u�v����Fp�G?�^����'���Sh����߹������X�'������J��%؃n��'ޏ=Lkm?��d�� �c�o��Dը�Li��ɣ�͉�ʜ��(-ߟ}4����[��q�~��Y`���Ó�\�~�����x�&B�(�L�Ƞ��^sL���l��+5+w���uO�����8R��TB9B���7Hm�{��]y���$�qQ�㈄��[�=q�9<���2&xtV@L$�6��T�	T�ԐN
-��Ƹ�T	+��τJ��Y+�a�J��[�2�b���s%	*Mk�/�E)���OKH>P�+_w�C[/
-^�2�v6��Z�����Iǂ�����￭}X���K��+PjrVV��f�(�@�r�R�t�bGZ�e�A�=H��[Nm�,����\�[j�Ư�Ġ�^9�Q?���\M���܇*l��i
{U�7h$�X,����Vs��cWb?5�ti�|�-�u�+��H�E���?s+�����I�dGō�#RD��
Èľi.i~$/t�ޥ,,�n�.�6�P�Q��>���Ƃ������H���bU5mH���]g�
-���m��0�.u�W%
- �����EY��mS�:�F�m����F2(��;��TFI�����1K�D��yty�U����#�����Y�K�B�W]NAQ�()wiz�*wѦY��;�z)�h}��RZ��3$�L.x�<ҢG��ⲋE��ꈮq>Mf�
�:���-<�.�'��>�)7f^���n�=-S�P�����`��;Dy�&^z ���3�]��\v���.���4���t|g"B��X�[z��^g2����$0�6��+A)6k�,\��E�@��g�q�~�/����6ֶJ`4�8�GI�y�5`�F�+Z8Hq���+7o�mE��C�p��� ��"sSR�+37�o�Z�}�p�		O/g�*rx���.4����nK�8#ky
-d�G���WMya�]��`���+�E_�:��>"# XD�k����/�d��+��tT�8���A��3M㡶��~�9���C���H�9�wr��ԓi��ɞ�>�h����j�O���ߗ���BMK<�skTPb���ۉ'�MF��VƇ��?�-pK+����(�<�/E�������L�q�D0?sV���0���������
-m�>�[+�s��|W����b𛊛
H+��[��;T5{�<3i���S����g�>~���ӕHx�c�����S������|�a��M�o�U�
�%�)Mt$�'a��A��	{K%Z�y������W���Q�����g:	<�������'Pw~b����p�Y$Yd����@�s����o���!��3�F��0�ӑ�e��	�x- ~^�~�N���]��[�����ǣ�V�m�����^(���B���ûz��u],��7����fV�f�G�K6�l�Vr�ɰ�4	��,~BlD��X����.�j�P�rM�mM{--��[`����6
-endstream
-endobj
-13 0 obj
-<</Type/Metadata
-/Subtype/XML/Length 1388>>stream
-<?xpacket begin='﻿' id='W5M0MpCehiHzreSzNTczkc9d'?>
-<?adobe-xap-filters esc="CRLF"?>
-<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 2.9.1-13, framework 1.6'>
-<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>
-<rdf:Description rdf:about='b1aeaa8f-72ef-11e7-0000-51c8be12fc20' xmlns:pdf='http://ns.adobe.com/pdf/1.3/' pdf:Producer='GNU Ghostscript 8.56'/>
-<rdf:Description rdf:about='b1aeaa8f-72ef-11e7-0000-51c8be12fc20' xmlns:xap='http://ns.adobe.com/xap/1.0/' xap:ModifyDate='2007-07-25T17:19:05Z' xap:CreateDate='2007-07-25T17:19:05Z'><xap:CreatorTool>fig2dev Version 3.2 Patchlevel 5-alpha7</xap:CreatorTool></rdf:Description>
-<rdf:Description rdf:about='b1aeaa8f-72ef-11e7-0000-51c8be12fc20' xmlns:xapMM='http://ns.adobe.com/xap/1.0/mm/' xapMM:DocumentID='b1aeaa8f-72ef-11e7-0000-51c8be12fc20'/>
-<rdf:Description rdf:about='b1aeaa8f-72ef-11e7-0000-51c8be12fc20' xmlns:dc='http://purl.org/dc/elements/1.1/' dc:format='application/pdf'><dc:title><rdf:Alt><rdf:li xml:lang='x-default'>fieldseq_tb.fig</rdf:li></rdf:Alt></dc:title><dc:creator><rdf:Seq><rdf:li>michael@localhost \(\)</rdf:li></rdf:Seq></dc:creator></rdf:Description>
-</rdf:RDF>
-</x:xmpmeta>
-                                                                        
-                                                                        
-<?xpacket end='w'?>
-endstream
-endobj
-2 0 obj
-<</Producer(GNU Ghostscript 8.56)
-/CreationDate(D:20070725171905Z)
-/ModDate(D:20070725171905Z)
-/Title(fieldseq_tb.fig)
-/Creator(fig2dev Version 3.2 Patchlevel 5-alpha7)
-/Author(michael@localhost \(\))>>endobj
-xref
-0 14
-0000000000 65535 f 
-0000003075 00000 n 
-0000008523 00000 n 
-0000003016 00000 n 
-0000002865 00000 n 
-0000000015 00000 n 
-0000002845 00000 n 
-0000003140 00000 n 
-0000003241 00000 n 
-0000003658 00000 n 
-0000003181 00000 n 
-0000003211 00000 n 
-0000004014 00000 n 
-0000007058 00000 n 
-trailer
-<< /Size 14 /Root 1 0 R /Info 2 0 R
-/ID [<9348BD7CCE2B07175ADFEF4DF463CEA4><9348BD7CCE2B07175ADFEF4DF463CEA4>]
->>
-startxref
-8740
-%%EOF
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/field-order.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/field-order.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/field-order.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/field-order.rst	2017-02-12 16:03:20.000000000 -0500
@@ -141,8 +141,8 @@ enum v4l2_field
 Field Order, Top Field First Transmitted
 ========================================
 
-.. figure::  field-order_files/fieldseq_tb.*
-    :alt:    fieldseq_tb.pdf / fieldseq_tb.gif
+.. figure::  fieldseq_tb.*
+    :alt:    fieldseq_tb.pdf / fieldseq_tb.svg
     :align:  center
 
 
@@ -151,7 +151,7 @@ Field Order, Top Field First Transmitted
 Field Order, Bottom Field First Transmitted
 ===========================================
 
-.. figure::  field-order_files/fieldseq_bt.*
-    :alt:    fieldseq_bt.pdf / fieldseq_bt.gif
+.. figure::  fieldseq_bt.*
+    :alt:    fieldseq_bt.pdf / fieldseq_bt.svg
     :align:  center
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/fieldseq_bt.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/fieldseq_bt.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/fieldseq_bt.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/fieldseq_bt.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2613 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg3619"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   xml:space="preserve"
+   width="198.48296mm"
+   height="211.89406mm"
+   viewBox="0 0 703.28606 750.80571"
+   sodipodi:docname="fieldseq_bt.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview3621"
+     showgrid="false"
+     units="mm"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="1.0721815"
+     inkscape:cx="8.4175633"
+     inkscape:cy="371.67214"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g3627" /><metadata
+     id="metadata3625"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs3623"><clipPath
+       id="clipPath4301"
+       clipPathUnits="userSpaceOnUse"><path
+         style="clip-rule:evenodd"
+         inkscape:connector-curvature="0"
+         id="path4303"
+         d="M 0,6040 0,0 l 5650,0 0,6040 -5650,0 z m 4786.76,-99.89 103.92,0 0,56.69 -103.92,0 0,0 85.03,-28.35 -85.03,-28.34 z" /></clipPath></defs><g
+     transform="matrix(1.25,0,0,-1.25,-1.0537,751.94632)"
+     inkscape:label="fieldseq_bt"
+     inkscape:groupmode="layer"
+     id="g3627"><path
+       d="m 188.622,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3631"
+       inkscape:connector-curvature="0" /><path
+       d="m 375.693,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3633"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,346.001 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3635"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3637"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3639"
+       inkscape:connector-curvature="0" /><path
+       d="m 1.55156,346.001 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3641"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,482.052 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3643"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,482.052 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3645"
+       inkscape:connector-curvature="0" /><path
+       d="m 1.55156,414.027 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3647"
+       inkscape:connector-curvature="0" /><path
+       d="m 188.622,414.027 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3649"
+       inkscape:connector-curvature="0" /><path
+       d="m 375.693,414.027 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3651"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,214.201 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3653"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3655"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3657"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3659"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3661"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3663"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3665"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3667"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3669"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3671"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3673"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3675"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3677"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3679"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3681"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3683"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3685"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,482.052 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3687"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3689"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3691"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3693"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3695"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3697"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3699"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3701"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3703"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3705"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3707"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3709"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3711"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3713"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3715"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3717"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3719"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3721"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3723"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3725"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3727"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3729"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3731"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3733"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3735"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3737"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3739"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3741"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3743"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3745"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3747"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3749"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3751"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3753"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3755"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3757"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3759"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3761"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3763"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3765"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3767"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3769"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3771"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3773"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3775"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3777"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3779"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3781"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3783"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3785"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3787"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3789"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3791"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3793"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3795"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3797"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3799"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3801"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3803"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3805"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3807"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3809"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3811"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3813"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3815"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3817"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3819"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3821"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3823"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3825"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3827"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3829"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3831"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3833"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3835"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3837"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3839"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3841"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3843"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3845"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3847"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,380.014 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3849"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,380.014 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3851"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,371.511 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3853"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,371.511 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3855"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,363.007 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3857"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,363.007 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3859"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,354.504 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3861"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,354.504 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3863"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,358.755 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3865"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,358.755 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3867"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,350.252 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3869"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,350.252 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3871"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,367.259 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3873"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,367.259 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3875"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,375.762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3877"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,375.762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3879"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3881"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3883"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3885"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3887"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3889"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3891"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3893"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3895"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3897"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3899"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3901"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3903"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3905"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3907"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3909"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3911"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3913"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,375.762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3915"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3917"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,367.259 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3919"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3921"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,358.755 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3923"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3925"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,350.252 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3927"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3929"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,380.014 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3931"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3933"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,371.511 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3935"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3937"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,363.007 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3939"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3941"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,354.504 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3943"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3945"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3947"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3949"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3951"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3953"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3955"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3957"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3959"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3961"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3963"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3965"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3967"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3969"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3971"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3973"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3975"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3977"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3979"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3981"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3983"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3985"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3987"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3989"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3991"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3993"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3995"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3997"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path3999"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4001"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4003"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4005"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4007"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4009"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,448.039 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4011"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4013"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,439.536 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4015"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4017"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,431.033 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4019"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4021"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,422.53 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4023"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4025"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,443.788 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4027"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4029"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,435.284 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4031"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4033"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,426.781 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4035"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4037"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,418.278 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4039"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4041"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4043"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4045"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4047"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4049"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4051"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4053"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4055"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4057"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4059"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4061"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4063"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4065"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4067"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4069"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4071"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,516.065 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4073"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,516.065 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4075"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,507.562 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4077"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,507.562 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4079"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,499.059 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4081"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,499.059 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4083"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,490.555 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4085"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,490.555 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4087"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,494.807 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4089"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,494.807 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4091"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,486.304 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4093"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,486.304 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4095"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,503.31 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4097"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,503.31 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4099"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,511.813 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4101"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,511.813 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4103"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4105"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,511.813 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4107"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4109"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,503.31 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4111"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4113"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,494.807 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4115"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4117"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,486.304 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4119"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4121"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,516.065 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4123"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4125"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,507.562 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4127"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4129"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,499.059 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4131"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4133"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,490.555 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4135"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4137"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4139"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4141"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4143"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4145"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4147"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4149"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4151"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4153"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4155"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4157"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4159"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4161"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4163"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4165"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4167"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,579.839 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4169"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,579.839 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4171"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,571.336 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4173"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,571.336 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4175"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,562.832 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4177"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,562.832 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4179"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,554.329 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4181"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,554.329 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4183"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,558.581 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4185"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,558.581 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4187"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,550.078 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4189"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,550.078 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4191"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,567.084 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4193"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,567.084 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4195"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,575.587 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4197"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,575.587 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4199"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4201"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4203"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4205"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4207"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4209"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4211"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4213"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4215"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4217"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4219"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4221"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4223"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4225"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4227"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4229"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4231"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4233"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4235"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4237"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4239"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4241"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4243"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4245"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4247"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4249"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4251"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4253"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4255"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4257"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4259"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4261"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4263"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4265"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,579.839 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4267"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4269"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,571.336 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4271"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4273"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,562.832 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4275"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4277"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,554.329 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4279"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4281"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,575.587 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4283"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4285"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,567.084 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4287"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4289"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,558.581 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4291"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4293"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,550.078 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4295"
+       inkscape:connector-curvature="0" /><g
+       transform="scale(0.1,0.1)"
+       id="g4297"
+       style=""><g
+         id="g4299"
+         clip-path="url(#clipPath4301)"
+         style=""><path
+           d="m 3778.18,5968.45 1105.42,0"
+           style="fill:none;stroke:#000000;stroke-width:14.17199993;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           id="path4305"
+           inkscape:connector-curvature="0" /></g></g><path
+       d="m 478.676,594.011 8.503,2.834 -8.503,2.835 0,-5.669"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4307"
+       inkscape:connector-curvature="0" /><path
+       d="m 478.676,594.011 8.503,2.834 -8.503,2.835 0,-5.669 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4309"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,1.62109 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4311"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,1.62109 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4313"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,1.62109 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4315"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4317"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4319"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4321"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4323"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4325"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4327"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4329"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4331"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4333"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4335"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4337"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4339"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4341"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4343"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4345"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4347"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4349"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,10.1242 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4351"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4353"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,18.6277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4355"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4357"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,27.1309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4359"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4361"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,35.634 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4363"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4365"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,5.87266 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4367"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4369"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,14.3762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4371"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4373"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,22.8793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4375"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4377"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,31.3824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4379"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,69.6469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4381"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,69.6469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4383"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,65.3953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4385"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,65.3953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4387"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,61.1438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4389"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,61.1438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4391"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,56.8922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4393"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,56.8922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4395"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,52.6402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4397"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,52.6402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4399"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,48.3887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4401"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,48.3887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4403"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,44.1371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4405"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,44.1371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4407"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,5.87266 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4409"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,5.87266 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4411"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,10.1242 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4413"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,10.1242 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4415"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,14.3762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4417"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,14.3762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4419"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,18.6277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4421"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,18.6277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4423"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,22.8793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4425"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,22.8793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4427"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,27.1309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4429"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,27.1309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4431"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,31.3824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4433"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,31.3824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4435"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,39.8855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4437"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,39.8855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4439"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,35.634 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4441"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,35.634 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4443"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4445"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4447"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4449"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4451"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4453"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4455"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4457"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4459"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4461"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4463"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4465"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4467"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4469"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4471"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4473"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4475"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4477"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,39.8855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4479"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4481"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,48.3887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4483"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4485"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,56.8922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4487"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4489"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,65.3953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4491"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4493"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,44.1371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4495"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4497"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,52.6402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4499"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4501"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,61.1438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4503"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4505"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,69.6469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4507"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4509"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4511"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4513"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4515"
+       inkscape:connector-curvature="0" /><path
+       d="m 188.622,107.911 93.5352,0 0,76.5285 -93.5352,0 0,-76.5285 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4517"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4519"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4521"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4523"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4525"
+       inkscape:connector-curvature="0" /><path
+       d="m 375.693,107.911 93.5352,0 0,76.5285 -93.5352,0 0,-76.5285 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4527"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4529"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,116.414 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4531"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4533"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,112.163 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4535"
+       inkscape:connector-curvature="0" /><path
+       d="m 1.55156,107.911 93.5352,0 0,76.5285 -93.5352,0 0,-76.5285 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4537"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4539"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4541"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4543"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4545"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4547"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4549"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4551"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4553"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4555"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4557"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4559"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4561"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4563"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4565"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4567"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4569"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4571"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4573"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4575"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4577"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4579"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4581"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4583"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4585"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4587"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4589"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4591"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4593"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4595"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4597"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4599"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4601"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4603"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4605"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4607"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4609"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4611"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4613"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4615"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4617"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4619"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4621"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4623"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4625"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4627"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4629"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4631"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4633"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4635"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4637"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4639"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4641"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4643"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4645"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4647"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4649"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4651"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,175.937 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4653"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4655"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,167.434 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4657"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4659"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,158.93 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4661"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4663"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,150.427 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4665"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4667"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,141.924 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4669"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4671"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,133.421 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4673"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4675"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,124.918 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4677"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4679"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,171.685 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4681"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4683"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,163.182 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4685"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4687"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,154.679 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4689"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4691"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,146.176 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4693"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4695"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,137.672 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4697"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4699"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,129.169 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4701"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4703"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,120.666 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4705"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,214.201 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4707"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4709"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,222.704 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4711"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4713"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,231.207 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4715"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4717"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,226.956 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4719"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4721"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,239.711 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4723"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4725"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,235.459 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4727"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4729"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,248.214 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4731"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4733"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,243.962 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4735"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4737"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,256.717 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4739"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4741"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,252.466 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4743"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4745"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,265.22 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4747"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4749"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,260.969 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4751"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4753"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,273.723 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4755"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4757"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,269.472 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4759"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4761"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,277.975 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4763"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4765"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,218.453 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4767"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4769"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,282.227 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4771"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,214.201 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4773"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,277.975 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4775"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,277.975 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4777"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,282.227 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4779"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,282.227 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4781"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,273.723 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4783"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,273.723 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4785"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,248.214 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4787"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,248.214 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4789"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,239.711 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4791"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,239.711 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4793"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,231.207 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4795"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,231.207 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4797"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,222.704 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4799"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,222.704 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4801"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,269.472 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4803"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,269.472 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4805"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,256.717 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4807"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,256.717 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4809"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,265.22 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4811"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,265.22 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4813"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,260.969 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4815"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,260.969 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4817"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,252.466 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4819"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,252.466 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4821"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,243.962 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4823"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,243.962 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4825"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,235.459 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4827"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,235.459 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4829"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,226.956 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4831"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,226.956 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4833"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,218.453 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path4835"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,218.453 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path4837"
+       inkscape:connector-curvature="0" /><text
+       y="-533.07098"
+       x="5.8031301"
+       id="text4841"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4843"
+         sodipodi:role="line"
+         y="-533.07098"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan><tspan
+         id="tspan4845"
+         sodipodi:role="line"
+         y="-465.04559"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan><tspan
+         id="tspan4847"
+         sodipodi:role="line"
+         y="-397.0202"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+       y="-316.23969"
+       x="103.58983"
+       id="text4849"
+       style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4851"
+         sodipodi:role="line"
+         y="-316.23969"
+         x="103.58983 109.09226 113.67899 118.26572 122.85246 127.43919 132.47964 134.77301 140.27545 144.86218 150.81833 155.40506 160.44553 166.86365 188.62184 194.12427 198.711 203.29774 207.88448 212.47121 217.51166 219.80502 225.30746 229.8942 235.85034 240.43707 245.9395 252.35764 257.3981 262.43854 268.85669 375.69293 381.19534 385.78207 390.3688 394.95554 399.54227 404.58273 406.8761 412.37854 416.96527 422.92142 427.50815 433.01059 439.42871 444.46918 449.50961 455.92776 1.551828 7.0542617 11.640993 16.227724 20.814463 25.401194 30.441652 32.735016 38.237442 42.824177 48.780331 53.367065 58.869492 65.287621 70.328079 75.368538 81.786659">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOM</tspan><tspan
+         id="tspan4853"
+         sodipodi:role="line"
+         y="-328.99481"
+         x="10.054964 14.17972 18.766451 20.597849 25.18458 29.771311 34.358047 38.944778 41.238144 43.531509 48.118244 50.865334 53.158699 55.452068 57.283459 61.870193 63.701588 68.288322">v4l2_buffer.field:</tspan></text>
+<text
+       y="-592.59381"
+       x="5.8034"
+       id="text4855"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4857"
+         sodipodi:role="line"
+         y="-592.59381"
+         x="5.8034 13.134789 19.806232 29.801399 36.472843 43.144287 47.139954 53.811398 56.475174 59.810898 66.482346 70.478004 77.149452 83.820892 87.816566 91.152283 94.488007 101.15945 107.83089 111.16662 114.50233 121.17377 131.16895 134.50468 137.84041 140.50418 147.17563 149.8394 156.51085 159.84657 163.1823 165.84607 169.84174 175.84123 179.17696 182.51268 185.8484 189.84407 196.51552 203.18695 209.18646 219.18163 221.8454 225.18112 228.51685 235.18829 241.85973 245.19545 249.19112 255.86256 259.19827 265.86972 269.20544 272.54117 282.53635 285.87207 294.53534 301.86673 309.87006 318.53336">Temporal order, bottom field first transmitted (e.g. M/NTSC)</tspan></text>
+<text
+       y="-316.23981"
+       x="290.6604"
+       id="text4859"
+       style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4861"
+         sodipodi:role="line"
+         y="-316.23981"
+         x="290.6604 296.16284 300.74957 305.3363 309.92303 314.50977 319.55023 321.8436 327.34601 331.93274 337.88889 342.47565 347.51608 353.9342 477.73062 483.23306 487.81979 492.40652 496.99326 501.57999 506.62045 508.91382 514.41626 519.00299 524.95911 529.5459 534.5863 541.00446">V4L2_FIELD_TOPV4L2_FIELD_TOP</tspan></text>
+<text
+       y="-299.23349"
+       x="5.8034"
+       id="text4863"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4865"
+         sodipodi:role="line"
+         y="-299.23349"
+         x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 84.504837 93.168114 100.4995 108.50284 117.16611 123.83755 131.8409 140.50418 148.50751 157.17079 160.50652 163.84224 167.17796 175.18129 181.85274 188.52419 195.19562 201.86707 209.19846 212.53418 220.53751 227.20895 235.87224 242.54367 245.87939 254.54268 261.87405 269.87741 278.54068 285.21213 293.21545 301.87872 309.88205 318.54535 325.2168 333.22012">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_BT</tspan><tspan
+         id="tspan4867"
+         sodipodi:role="line"
+         y="-192.9435"
+         x="1.5518398 9.5551729 16.226616 22.898062 29.569506 36.240948 43.572334 46.908058 54.911392 61.582836 70.246117 76.917557 80.253281 88.916557 96.247948 104.25128 112.91456 119.586 127.58932 136.25262 144.25595 152.91924 159.59067 166.92206 174.9254 178.26112 182.25679 192.25195 194.91573 200.91524 207.58667 210.25046 212.91423 219.58568 226.25713 232.92856 239.60001">V4L2_FIELD_INTERLACED_TB (misaligned)</tspan><tspan
+         id="tspan4869"
+         sodipodi:role="line"
+         y="-86.653496"
+         x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 89.172447 97.175781 106.511 113.18245 121.18579">V4L2_FIELD_SEQ_BT</tspan></text>
+<text
+       y="-533.07098"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464"
+       id="text4592"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4594"
+         sodipodi:role="line"
+         y="-533.07098"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan></text>
+<text
+       y="-465.04559"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054"
+       id="text4596"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4598"
+         sodipodi:role="line"
+         y="-465.04559"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan></text>
+<text
+       y="-397.0202"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963"
+       id="text4600"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4602"
+         sodipodi:role="line"
+         y="-397.0202"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+       y="-299.23349"
+       x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 84.504837 93.168114 100.4995 108.50284 117.16611 123.83755 131.8409 140.50418 148.50751 157.17079 160.50652 163.84224 167.17796 175.18129 181.85274 188.52419 195.19562 201.86707 209.19846 212.53418 220.53751 227.20895 235.87224 242.54367 245.87939 254.54268 261.87405 269.87741 278.54068 285.21213 293.21545 301.87872 309.88205 318.54535 325.2168 333.22012"
+       id="text5862"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan5864"
+         sodipodi:role="line"
+         y="-299.23349"
+         x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 84.504837 93.168114 100.4995 108.50284 117.16611 123.83755 131.8409 140.50418 148.50751 157.17079 160.50652 163.84224 167.17796 175.18129 181.85274 188.52419 195.19562 201.86707 209.19846 212.53418 220.53751 227.20895 235.87224 242.54367 245.87939 254.54268 261.87405 269.87741 278.54068 285.21213 293.21545 301.87872 309.88205 318.54535 325.2168 333.22012">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_BT</tspan></text>
+<text
+       y="-192.9435"
+       x="1.5518398 9.5551729 16.226616 22.898062 29.569506 36.240948 43.572334 46.908058 54.911392 61.582836 70.246117 76.917557 80.253281 88.916557 96.247948 104.25128 112.91456 119.586 127.58932 136.25262 144.25595 152.91924 159.59067 166.92206 174.9254 178.26112 182.25679 192.25195 194.91573 200.91524 207.58667 210.25046 212.91423 219.58568 226.25713 232.92856 239.60001"
+       id="text5866"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan5868"
+         sodipodi:role="line"
+         y="-192.9435"
+         x="1.5518398 9.5551729 16.226616 22.898062 29.569506 36.240948 43.572334 46.908058 54.911392 61.582836 70.246117 76.917557 80.253281 88.916557 96.247948 104.25128 112.91456 119.586 127.58932 136.25262 144.25595 152.91924 159.59067 166.92206 174.9254 178.26112 182.25679 192.25195 194.91573 200.91524 207.58667 210.25046 212.91423 219.58568 226.25713 232.92856 239.60001">V4L2_FIELD_INTERLACED_TB (misaligned)</tspan></text>
+<text
+       y="-86.653496"
+       x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 89.172447 97.175781 106.511 113.18245 121.18579"
+       id="text5870"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan5872"
+         sodipodi:role="line"
+         y="-86.653496"
+         x="5.8034 13.806733 20.478176 27.149622 33.821064 40.492508 47.823895 51.159618 59.162952 65.834396 74.497673 81.169121 89.172447 97.175781 106.511 113.18245 121.18579">V4L2_FIELD_SEQ_BT</tspan></text>
+<text
+       y="-316.23969"
+       x="103.58983 109.09226 113.67899 118.26572 122.85246 127.43919 132.47964 134.77301 140.27545 144.86218 150.81833 155.40506 160.44553 166.86365 188.62184 194.12427 198.711 203.29774 207.88448 212.47121 217.51166 219.80502 225.30746 229.8942 235.85034 240.43707 245.9395 252.35764 257.3981 262.43854 268.85669 375.69293 381.19534 385.78207 390.3688 394.95554 399.54227 404.58273 406.8761 412.37854 416.96527 422.92142 427.50815 433.01059 439.42871 444.46918 449.50961 455.92776 1.551828 7.0542617 11.640993 16.227724 20.814463 25.401194 30.441652 32.735016 38.237442 42.824177 48.780331 53.367065 58.869492 65.287621 70.328079 75.368538 81.786659"
+       id="text7144"
+       style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan7146"
+         sodipodi:role="line"
+         y="-316.23969"
+         x="103.58983 109.09226 113.67899 118.26572 122.85246 127.43919 132.47964 134.77301 140.27545 144.86218 150.81833 155.40506 160.44553 166.86365 188.62184 194.12427 198.711 203.29774 207.88448 212.47121 217.51166 219.80502 225.30746 229.8942 235.85034 240.43707 245.9395 252.35764 257.3981 262.43854 268.85669 375.69293 381.19534 385.78207 390.3688 394.95554 399.54227 404.58273 406.8761 412.37854 416.96527 422.92142 427.50815 433.01059 439.42871 444.46918 449.50961 455.92776 1.551828 7.0542617 11.640993 16.227724 20.814463 25.401194 30.441652 32.735016 38.237442 42.824177 48.780331 53.367065 58.869492 65.287621 70.328079 75.368538 81.786659">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOMV4L2_FIELD_BOTTOM</tspan></text>
+<text
+       y="-328.99481"
+       x="10.054964 14.17972 18.766451 20.597849 25.18458 29.771311 34.358047 38.944778 41.238144 43.531509 48.118244 50.865334 53.158699 55.452068 57.283459 61.870193 63.701588 68.288322"
+       id="text7148"
+       style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan7150"
+         sodipodi:role="line"
+         y="-328.99481"
+         x="10.054964 14.17972 18.766451 20.597849 25.18458 29.771311 34.358047 38.944778 41.238144 43.531509 48.118244 50.865334 53.158699 55.452068 57.283459 61.870193 63.701588 68.288322">v4l2_buffer.field:</tspan></text>
+</g></svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/fieldseq_tb.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/fieldseq_tb.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/fieldseq_tb.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/fieldseq_tb.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2607 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg5543"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   xml:space="preserve"
+   width="198.48296mm"
+   height="210.39415mm"
+   viewBox="0 0 703.28607 745.49109"
+   sodipodi:docname="fieldseq_tb.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview5545"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     units="mm"
+     inkscape:zoom="1.0733333"
+     inkscape:cx="9.8391479"
+     inkscape:cy="370.19322"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g5551" /><metadata
+     id="metadata5549"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs5547"><clipPath
+       id="clipPath6753"
+       clipPathUnits="userSpaceOnUse"><path
+         style="clip-rule:evenodd"
+         inkscape:connector-curvature="0"
+         id="path6755"
+         d="M 0,6000 0,0 l 5660,0 0,6000 -5660,0 z m 4786.76,-102.89 103.92,0 0,56.69 -103.92,0 0,0 85.03,-28.35 -85.03,-28.34 z" /></clipPath></defs><g
+     transform="matrix(1.25,0,0,-1.25,-1.0537,746.57119)"
+     inkscape:label="fieldseq_tb"
+     inkscape:groupmode="layer"
+     id="g5551"><path
+       d="m 379.944,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5555"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5557"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5559"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5561"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5563"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5565"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5567"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5569"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5571"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5573"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5575"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5577"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5579"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5581"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5583"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5585"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5587"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5589"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5591"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5593"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5595"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5597"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5599"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5601"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5603"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5605"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5607"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5609"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5611"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5613"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5615"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5617"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5619"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5621"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5623"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5625"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5627"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5629"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5631"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5633"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5635"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5637"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5639"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5641"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5643"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5645"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5647"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5649"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5651"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5653"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5655"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5657"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5659"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5661"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5663"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5665"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5667"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5669"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5671"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5673"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5675"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5677"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5679"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5681"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5683"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5685"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5687"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5689"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5691"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5693"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5695"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5697"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5699"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5701"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5703"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5705"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5707"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5709"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5711"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5713"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5715"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5717"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5719"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5721"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5723"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5725"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5727"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5729"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5731"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5733"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5735"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5737"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5739"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5741"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5743"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5745"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5747"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,218.404 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5749"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5751"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,226.907 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5753"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5755"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,222.656 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5757"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5759"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,235.411 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5761"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5763"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,231.159 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5765"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5767"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,243.914 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5769"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5771"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,239.662 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5773"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5775"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,252.417 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5777"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5779"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,248.166 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5781"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5783"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,260.92 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5785"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5787"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,256.669 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5789"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5791"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,269.423 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5793"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5795"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,265.172 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5797"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5799"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,273.675 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5801"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5803"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,214.153 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5805"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5807"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,277.927 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5809"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5811"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5813"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5815"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5817"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5819"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5821"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5823"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5825"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5827"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5829"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5831"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5833"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5835"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5837"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5839"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5841"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5843"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5845"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5847"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5849"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5851"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5853"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5855"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5857"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5859"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5861"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5863"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5865"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5867"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5869"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5871"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5873"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5875"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5877"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5879"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5881"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5883"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5885"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5887"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5889"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5891"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5893"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5895"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5897"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5899"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5901"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5903"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5905"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5907"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,35.5855 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5909"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5911"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,27.0824 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5913"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5915"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,18.5793 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5917"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5919"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,10.0762 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5921"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5923"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,31.334 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5925"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5927"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,22.8309 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5929"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5931"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,14.3277 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5933"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5935"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,5.82422 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5937"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,409.727 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5939"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,409.727 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5941"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,409.727 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5943"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,209.901 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5945"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,209.901 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5947"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,209.901 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5949"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5951"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,341.701 93.5355,0 0,42.516 -93.5355,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5953"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5955"
+       inkscape:connector-curvature="0" /><path
+       d="m 1.55156,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5957"
+       inkscape:connector-curvature="0" /><path
+       d="m 188.622,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5959"
+       inkscape:connector-curvature="0" /><path
+       d="m 375.693,341.701 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5961"
+       inkscape:connector-curvature="0" /><path
+       d="m 1.55156,477.752 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5963"
+       inkscape:connector-curvature="0" /><path
+       d="m 188.622,477.752 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5965"
+       inkscape:connector-curvature="0" /><path
+       d="m 375.693,477.752 93.5352,0 0,42.516 -93.5352,0 0,-42.516 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5967"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5969"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5971"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5973"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5975"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5977"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5979"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5981"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5983"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5985"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5987"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5989"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5991"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5993"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5995"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path5997"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path5999"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6001"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6003"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6005"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6007"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6009"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6011"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6013"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6015"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6017"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6019"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6021"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6023"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6025"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6027"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6029"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6031"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6033"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6035"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6037"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6039"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6041"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6043"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6045"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6047"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6049"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6051"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6053"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6055"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6057"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6059"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6061"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6063"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6065"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,443.739 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6067"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6069"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,435.236 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6071"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6073"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,426.733 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6075"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6077"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,418.23 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6079"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6081"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,439.488 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6083"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6085"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,430.984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6087"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6089"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,422.481 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6091"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6093"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,413.978 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6095"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6097"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,575.539 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6099"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,575.539 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6101"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,575.539 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6103"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6105"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,571.287 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6107"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6109"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,567.036 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6111"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6113"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,562.784 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6115"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6117"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,558.532 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6119"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6121"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,554.281 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6123"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6125"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,550.029 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6127"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6129"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,545.778 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6131"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6133"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,511.765 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6135"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6137"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,507.513 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6139"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6141"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,503.262 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6143"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6145"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,499.01 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6147"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6149"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,494.759 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6151"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6153"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,490.507 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6155"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6157"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,486.255 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6159"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6161"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,482.004 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6163"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6165"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6167"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6169"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6171"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6173"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6175"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6177"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6179"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6181"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6183"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6185"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6187"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6189"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6191"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6193"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6195"
+       inkscape:connector-curvature="0" /><path
+       d="m 1.55156,107.863 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6197"
+       inkscape:connector-curvature="0" /><path
+       d="m 188.622,107.863 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6199"
+       inkscape:connector-curvature="0" /><path
+       d="m 375.693,107.863 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6201"
+       inkscape:connector-curvature="0" /><path
+       d="m 95.0867,1.57266 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6203"
+       inkscape:connector-curvature="0" /><path
+       d="m 282.157,1.57266 93.5355,0 0,76.5289 -93.5355,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6205"
+       inkscape:connector-curvature="0" /><path
+       d="m 469.228,1.57266 93.5352,0 0,76.5289 -93.5352,0 0,-76.5289 z"
+       style="fill:none;stroke:#000000;stroke-width:1.41719997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6207"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6209"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6211"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6213"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6215"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6217"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6219"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6221"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6223"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6225"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6227"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6229"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6231"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6233"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6235"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6237"
+       inkscape:connector-curvature="0" /><path
+       d="m 473.479,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6239"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6241"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,65.3469 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6243"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6245"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,56.8438 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6247"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6249"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,48.3402 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6251"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6253"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,39.8371 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6255"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6257"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,69.5984 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6259"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6261"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,61.0953 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6263"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6265"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,52.5922 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6267"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6269"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,44.0887 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6271"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,277.927 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6273"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,277.927 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6275"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,269.423 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6277"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,269.423 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6279"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,260.92 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6281"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,260.92 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6283"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,252.417 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6285"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,252.417 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6287"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,243.914 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6289"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,243.914 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6291"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,235.411 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6293"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,235.411 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6295"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,226.907 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6297"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,226.907 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6299"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,218.404 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6301"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,218.404 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6303"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,69.5984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6305"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,69.5984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6307"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,65.3469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6309"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,65.3469 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6311"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,61.0953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6313"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,61.0953 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6315"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,56.8438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6317"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,56.8438 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6319"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,52.5922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6321"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,52.5922 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6323"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,48.3402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6325"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,48.3402 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6327"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,44.0887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6329"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,44.0887 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6331"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,39.8371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6333"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,39.8371 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6335"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,571.287 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6337"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,571.287 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6339"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,567.036 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6341"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,567.036 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6343"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,562.784 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6345"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,562.784 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6347"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,558.532 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6349"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,558.532 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6351"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,554.281 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6353"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,554.281 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6355"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,550.029 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6357"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,550.029 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6359"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,545.778 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6361"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,545.778 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6363"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,443.739 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6365"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,443.739 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6367"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,439.488 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6369"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,439.488 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6371"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,435.236 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6373"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,435.236 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6375"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,430.984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6377"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,430.984 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6379"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,426.733 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6381"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,426.733 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6383"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,422.481 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6385"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,422.481 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6387"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,418.23 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6389"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,418.23 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6391"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,413.978 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6393"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,413.978 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6395"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,375.714 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6397"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,375.714 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6399"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,371.462 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6401"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,371.462 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6403"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,367.211 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6405"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,367.211 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6407"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,362.959 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6409"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,362.959 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6411"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,358.707 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6413"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,358.707 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6415"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,354.455 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6417"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,354.455 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6419"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,350.204 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6421"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,350.204 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6423"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,345.952 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6425"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,345.952 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6427"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,273.675 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6429"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,273.675 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6431"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,265.172 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6433"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,265.172 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6435"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,256.669 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6437"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,256.669 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6439"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,248.166 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6441"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,248.166 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6443"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,239.662 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6445"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,239.662 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6447"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,231.159 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6449"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,231.159 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6451"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,222.656 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6453"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,222.656 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6455"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,214.153 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6457"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,214.153 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6459"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,35.5855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6461"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,35.5855 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6463"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,31.334 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6465"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,31.334 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6467"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,27.0824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6469"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,27.0824 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6471"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,22.8309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6473"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,22.8309 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6475"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,18.5793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6477"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,18.5793 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6479"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,14.3277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6481"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,14.3277 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6483"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,10.0762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6485"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,10.0762 85.0316,0 0,4.25156 -85.0316,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6487"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,5.82422 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6489"
+       inkscape:connector-curvature="0" /><path
+       d="m 286.409,5.82422 85.0316,0 0,4.25195 -85.0316,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6491"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6493"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6495"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6497"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6499"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6501"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6503"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6505"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6507"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6509"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6511"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6513"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6515"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6517"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6519"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#008f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6521"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6523"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6525"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6527"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6529"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6531"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6533"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6535"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6537"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6539"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6541"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6543"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6545"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6547"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6549"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6551"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6553"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6555"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6557"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6559"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6561"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6563"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6565"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6567"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6569"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6571"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6573"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6575"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6577"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6579"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6581"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6583"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6585"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6587"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6589"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,175.888 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6591"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6593"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,167.385 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6595"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6597"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,158.882 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6599"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6601"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,150.379 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6603"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6605"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,141.876 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6607"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6609"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,133.372 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6611"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6613"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,124.869 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6615"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#d10000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6617"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,116.366 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6619"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6621"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,375.714 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6623"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6625"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,367.211 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6627"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6629"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,358.707 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6631"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6633"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,350.204 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6635"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6637"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,371.462 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6639"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6641"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,362.959 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6643"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6645"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,354.455 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6647"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6649"
+       inkscape:connector-curvature="0" /><path
+       d="m 99.3383,345.952 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6651"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6653"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6655"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6657"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6659"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6661"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6663"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6665"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6667"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6669"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6671"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6673"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6675"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6677"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6679"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#0000d1;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6681"
+       inkscape:connector-curvature="0" /><path
+       d="m 192.873,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6683"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6685"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6687"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6689"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6691"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6693"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6695"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6697"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6699"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6701"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6703"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6705"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6707"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6709"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6711"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6713"
+       inkscape:connector-curvature="0" /><path
+       d="m 379.944,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6715"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6717"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,171.637 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6719"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6721"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,163.134 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6723"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6725"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,154.63 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6727"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6729"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,146.127 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6731"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6733"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,137.624 85.032,0 0,4.25195 -85.032,0 0,-4.25195 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6735"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6737"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,129.121 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6739"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6741"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,120.618 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6743"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6745"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.80312,112.114 85.032,0 0,4.25156 -85.032,0 0,-4.25156 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6747"
+       inkscape:connector-curvature="0" /><g
+       transform="scale(0.1,0.1)"
+       id="g6749"
+       style=""><g
+         id="g6751"
+         clip-path="url(#clipPath6753)"
+         style=""><path
+           d="m 3778.18,5925.45 1105.42,0"
+           style="fill:none;stroke:#000000;stroke-width:14.17199993;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           id="path6757"
+           inkscape:connector-curvature="0" /></g></g><path
+       d="m 478.676,589.711 8.503,2.834 -8.503,2.835 0,-5.669"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path6759"
+       inkscape:connector-curvature="0" /><path
+       d="m 478.676,589.711 8.503,2.834 -8.503,2.835 0,-5.669 z"
+       style="fill:none;stroke:#000000;stroke-width:0.35429999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path6761"
+       inkscape:connector-curvature="0" /><text
+       y="-528.771"
+       x="5.8031301"
+       id="text6765"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan6767"
+         sodipodi:role="line"
+         y="-528.771"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan><tspan
+         id="tspan6769"
+         sodipodi:role="line"
+         y="-460.74561"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan><tspan
+         id="tspan6771"
+         sodipodi:role="line"
+         y="-392.72021"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+       y="-324.69479"
+       x="10.05469"
+       id="text6773"
+       style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan6775"
+         sodipodi:role="line"
+         y="-324.69479"
+         x="10.05469 14.17945 18.766184 20.597576 25.184309 29.771042 34.357777 38.944508 41.237877 43.531242 48.117977 50.865067 53.158432 55.451801 57.283192 61.869926 63.701321 68.288048">v4l2_buffer.field:</tspan><tspan
+         id="tspan6777"
+         sodipodi:role="line"
+         y="-311.9397"
+         x="10.05469 15.55712 20.143852 24.730585 29.317318 33.904053 38.944508 41.237877 46.740307 51.327042 57.283192 61.869926 66.910378 73.328506 95.0867 100.58913 105.17586 109.7626 114.34933 118.93606 123.97652 126.26987 131.77232 136.35905 142.3152 146.90193 152.40436 158.82249 163.86295 168.9034 175.32153 197.12534 202.62778 207.21451 211.80124 216.38797 220.9747 226.01515 228.30853 233.81096 238.39769 244.35384 248.94058 253.98103 260.39917 282.15695 287.65936 292.24609 296.83282 301.41956 306.00629 311.04675 313.34012 318.84256 323.42929 329.38544 333.97217 339.47461 345.89273 350.9332 355.97363 362.39175 384.19559 389.698 394.28473 398.87149 403.45822 408.04495 413.08539 415.37875 420.8812 425.46793 431.42407 436.0108 441.05127 447.46939 469.2276 474.73001 479.31674 483.90347 488.49023 493.07697 498.1174 500.41077 505.91321 510.49994 516.45612 521.04285 526.54523 532.96338 538.00385 543.04431 549.4624">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOM</tspan></text>
+<text
+       y="-588.2937"
+       x="5.8031301"
+       id="text6779"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan6781"
+         sodipodi:role="line"
+         y="-588.2937"
+         x="5.8031301 13.134519 19.805964 29.801128 36.472572 43.14402 47.139687 53.811131 56.474907 59.810631 66.482071 70.477737 77.149185 83.820625 87.816299 91.152016 94.48774 97.823463 104.4949 111.16635 114.50207 117.83779 120.50157 127.17302 129.83679 136.50824 139.84396 143.17969 145.84346 149.83913 155.83862 159.17435 162.51007 165.84579 169.84146 176.51291 183.18434 189.18385 199.17902 201.84279 205.17851 208.51424 215.18568 221.85713 225.19284 229.18851 235.85995 239.19568 245.86713 249.20285 252.53857 260.5419 269.87714 273.21286 281.21619 289.21951 295.89096">Temporal order, top field first transmitted (e.g. BG/PAL)</tspan><tspan
+         id="tspan6783"
+         sodipodi:role="line"
+         y="-86.604706"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 97.175514 106.51073 113.18218 120.51357">V4L2_FIELD_SEQ_TB</tspan><tspan
+         id="tspan6785"
+         sodipodi:role="line"
+         y="-192.89471"
+         x="10.05469 18.058023 24.729465 31.400909 38.072357 44.743801 52.075188 55.410912 63.414246 70.085686 78.748962 85.42041 88.756134 97.419411 104.7508 112.75413 121.41741 128.08885 136.09219 144.75546 152.7588 161.42207 168.09352 176.09685 183.42824 186.76396 190.75963 200.75479 203.41858 209.41808 216.08952 218.7533 221.41707 228.08852 234.75996 241.43141 248.10286">V4L2_FIELD_INTERLACED_BT (misaligned)</tspan><tspan
+         id="tspan6787"
+         sodipodi:role="line"
+         y="-294.93271"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 84.50457 93.167847 100.49924 108.50257 117.16585 123.83729 131.84062 140.50391 148.50723 157.17052 160.50624 163.84196 167.17769 175.18102 181.85246 188.52391 195.19534 201.86679 209.19818 212.53391 220.53723 227.20868 235.87196 242.5434 245.87912 254.5424 261.87378 269.87714 278.54041 285.21185 293.21518 301.87845 309.88177 318.54507 325.21652 332.54791">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_TB</tspan></text>
+<text
+       y="-528.771"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464"
+       id="text4583"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4585"
+         sodipodi:role="line"
+         y="-528.771"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 88.500237 97.835464">V4L2_FIELD_TOP</tspan></text>
+<text
+       y="-460.74561"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054"
+       id="text4587"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4589"
+         sodipodi:role="line"
+         y="-460.74561"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 98.507408 105.83879 113.17018 122.5054">V4L2_FIELD_BOTTOM</tspan></text>
+<text
+       y="-392.72021"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963"
+       id="text4591"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan4593"
+         sodipodi:role="line"
+         y="-392.72021"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 95.843628 103.17502 111.17835 119.84163 128.5049 136.50824 143.83963">V4L2_FIELD_ALTERNATE</tspan></text>
+<text
+       y="-588.2937"
+       x="5.8031301 13.134519 19.805964 29.801128 36.472572 43.14402 47.139687 53.811131 56.474907 59.810631 66.482071 70.477737 77.149185 83.820625 87.816299 91.152016 94.48774 97.823463 104.4949 111.16635 114.50207 117.83779 120.50157 127.17302 129.83679 136.50824 139.84396 143.17969 145.84346 149.83913 155.83862 159.17435 162.51007 165.84579 169.84146 176.51291 183.18434 189.18385 199.17902 201.84279 205.17851 208.51424 215.18568 221.85713 225.19284 229.18851 235.85995 239.19568 245.86713 249.20285 252.53857 260.5419 269.87714 273.21286 281.21619 289.21951 295.89096"
+       id="text5847"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan5849"
+         sodipodi:role="line"
+         y="-588.2937"
+         x="5.8031301 13.134519 19.805964 29.801128 36.472572 43.14402 47.139687 53.811131 56.474907 59.810631 66.482071 70.477737 77.149185 83.820625 87.816299 91.152016 94.48774 97.823463 104.4949 111.16635 114.50207 117.83779 120.50157 127.17302 129.83679 136.50824 139.84396 143.17969 145.84346 149.83913 155.83862 159.17435 162.51007 165.84579 169.84146 176.51291 183.18434 189.18385 199.17902 201.84279 205.17851 208.51424 215.18568 221.85713 225.19284 229.18851 235.85995 239.19568 245.86713 249.20285 252.53857 260.5419 269.87714 273.21286 281.21619 289.21951 295.89096">Temporal order, top field first transmitted (e.g. BG/PAL)</tspan></text>
+<text
+       y="-86.604706"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 97.175514 106.51073 113.18218 120.51357"
+       id="text5851"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan5853"
+         sodipodi:role="line"
+         y="-86.604706"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 89.17218 97.175514 106.51073 113.18218 120.51357">V4L2_FIELD_SEQ_TB</tspan></text>
+<text
+       y="-192.89471"
+       x="10.05469 18.058023 24.729465 31.400909 38.072357 44.743801 52.075188 55.410912 63.414246 70.085686 78.748962 85.42041 88.756134 97.419411 104.7508 112.75413 121.41741 128.08885 136.09219 144.75546 152.7588 161.42207 168.09352 176.09685 183.42824 186.76396 190.75963 200.75479 203.41858 209.41808 216.08952 218.7533 221.41707 228.08852 234.75996 241.43141 248.10286"
+       id="text5855"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan5857"
+         sodipodi:role="line"
+         y="-192.89471"
+         x="10.05469 18.058023 24.729465 31.400909 38.072357 44.743801 52.075188 55.410912 63.414246 70.085686 78.748962 85.42041 88.756134 97.419411 104.7508 112.75413 121.41741 128.08885 136.09219 144.75546 152.7588 161.42207 168.09352 176.09685 183.42824 186.76396 190.75963 200.75479 203.41858 209.41808 216.08952 218.7533 221.41707 228.08852 234.75996 241.43141 248.10286">V4L2_FIELD_INTERLACED_BT (misaligned)</tspan></text>
+<text
+       y="-294.93271"
+       x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 84.50457 93.167847 100.49924 108.50257 117.16585 123.83729 131.84062 140.50391 148.50723 157.17052 160.50624 163.84196 167.17769 175.18102 181.85246 188.52391 195.19534 201.86679 209.19818 212.53391 220.53723 227.20868 235.87196 242.5434 245.87912 254.5424 261.87378 269.87714 278.54041 285.21185 293.21518 301.87845 309.88177 318.54507 325.21652 332.54791"
+       id="text5859"
+       style="font-variant:normal;font-weight:normal;font-size:11.9989996px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan5861"
+         sodipodi:role="line"
+         y="-294.93271"
+         x="5.8031301 13.806463 20.477907 27.149351 33.820797 40.492241 47.823627 51.159351 59.162685 65.834129 74.497406 81.168854 84.50457 93.167847 100.49924 108.50257 117.16585 123.83729 131.84062 140.50391 148.50723 157.17052 160.50624 163.84196 167.17769 175.18102 181.85246 188.52391 195.19534 201.86679 209.19818 212.53391 220.53723 227.20868 235.87196 242.5434 245.87912 254.5424 261.87378 269.87714 278.54041 285.21185 293.21518 301.87845 309.88177 318.54507 325.21652 332.54791">V4L2_FIELD_INTERLACED / V4L2_FIELD_INTERLACED_TB</tspan></text>
+<text
+       y="-324.69479"
+       x="10.05469 14.17945 18.766184 20.597576 25.184309 29.771042 34.357777 38.944508 41.237877 43.531242 48.117977 50.865067 53.158432 55.451801 57.283192 61.869926 63.701321 68.288048"
+       id="text7131"
+       style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan7133"
+         sodipodi:role="line"
+         y="-324.69479"
+         x="10.05469 14.17945 18.766184 20.597576 25.184309 29.771042 34.357777 38.944508 41.237877 43.531242 48.117977 50.865067 53.158432 55.451801 57.283192 61.869926 63.701321 68.288048">v4l2_buffer.field:</tspan></text>
+<text
+       y="-311.9397"
+       x="10.05469 15.55712 20.143852 24.730585 29.317318 33.904053 38.944508 41.237877 46.740307 51.327042 57.283192 61.869926 66.910378 73.328506 95.0867 100.58913 105.17586 109.7626 114.34933 118.93606 123.97652 126.26987 131.77232 136.35905 142.3152 146.90193 152.40436 158.82249 163.86295 168.9034 175.32153 197.12534 202.62778 207.21451 211.80124 216.38797 220.9747 226.01515 228.30853 233.81096 238.39769 244.35384 248.94058 253.98103 260.39917 282.15695 287.65936 292.24609 296.83282 301.41956 306.00629 311.04675 313.34012 318.84256 323.42929 329.38544 333.97217 339.47461 345.89273 350.9332 355.97363 362.39175 384.19559 389.698 394.28473 398.87149 403.45822 408.04495 413.08539 415.37875 420.8812 425.46793 431.42407 436.0108 441.05127 447.46939 469.2276 474.73001 479.31674 483.90347 488.49023 493.07697 498.1174 500.41077 505.91321 510.49994 516.45612 521.04285 526.54523 532.96338 538.00385 543.04431 549.4624"
+       id="text7135"
+       style="font-variant:normal;font-weight:normal;font-size:8.2495203px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan7137"
+         sodipodi:role="line"
+         y="-311.9397"
+         x="10.05469 15.55712 20.143852 24.730585 29.317318 33.904053 38.944508 41.237877 46.740307 51.327042 57.283192 61.869926 66.910378 73.328506 95.0867 100.58913 105.17586 109.7626 114.34933 118.93606 123.97652 126.26987 131.77232 136.35905 142.3152 146.90193 152.40436 158.82249 163.86295 168.9034 175.32153 197.12534 202.62778 207.21451 211.80124 216.38797 220.9747 226.01515 228.30853 233.81096 238.39769 244.35384 248.94058 253.98103 260.39917 282.15695 287.65936 292.24609 296.83282 301.41956 306.00629 311.04675 313.34012 318.84256 323.42929 329.38544 333.97217 339.47461 345.89273 350.9332 355.97363 362.39175 384.19559 389.698 394.28473 398.87149 403.45822 408.04495 413.08539 415.37875 420.8812 425.46793 431.42407 436.0108 441.05127 447.46939 469.2276 474.73001 479.31674 483.90347 488.49023 493.07697 498.1174 500.41077 505.91321 510.49994 516.45612 521.04285 526.54523 532.96338 538.00385 543.04431 549.4624">V4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOMV4L2_FIELD_TOPV4L2_FIELD_BOTTOM</tspan></text>
+</g></svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/hsv-formats.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/hsv-formats.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/hsv-formats.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/hsv-formats.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,19 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _hsv-formats:
+
+***********
+HSV Formats
+***********
+
+These formats store the color information of the image
+in a geometrical representation. The colors are mapped into a
+cylinder, where the angle is the HUE, the height is the VALUE
+and the distance to the center is the SATURATION. This is a very
+useful format for image segmentation algorithms.
+
+
+.. toctree::
+    :maxdepth: 1
+
+    pixfmt-packed-hsv
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/nv12mt_example.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/nv12mt_example.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/nv12mt_example.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/nv12mt_example.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1589 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.2"
+   width="144.28223mm"
+   height="70.282227mm"
+   viewBox="0 0 14428.222 7028.2226"
+   preserveAspectRatio="xMidYMid"
+   xml:space="preserve"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="nv12mt_example.svg"
+   style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+     id="metadata953"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview951"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="2.7306359"
+     inkscape:cx="255.61812"
+     inkscape:cy="124.51576"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" /><defs
+     class="ClipPathGroup"
+     id="defs4" /><defs
+     id="defs9" /><defs
+     id="defs84" /><defs
+     id="defs107" /><defs
+     class="TextShapeIndex"
+     id="defs118" /><defs
+     class="EmbeddedBulletChars"
+     id="defs122" /><defs
+     class="TextEmbeddedBitmaps"
+     id="defs151" /><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g188"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id6"><rect
+         class="BoundingBox"
+         x="3299"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect191"
+         style="fill:none;stroke:none" /><path
+         d="m 4500,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path193"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text195"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan197"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="4325"
+             y="4121"
+             id="tspan199"><tspan
+               id="tspan201"
+               style="fill:#000000;stroke:none">0</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g203"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id7"><rect
+         class="BoundingBox"
+         x="5699"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect206"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path208"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g210"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id8"><rect
+         class="BoundingBox"
+         x="8099"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect213"
+         style="fill:none;stroke:none" /><path
+         d="m 9300,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path215"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text217"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan219"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="9125"
+             y="4121"
+             id="tspan221"><tspan
+               id="tspan223"
+               style="fill:#000000;stroke:none">6</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g225"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id9"><rect
+         class="BoundingBox"
+         x="5699"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect228"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path230"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text232"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan234"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="6725"
+             y="4121"
+             id="tspan236"><tspan
+               id="tspan238"
+               style="fill:#000000;stroke:none">1</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g240"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id10"><rect
+         class="BoundingBox"
+         x="10499"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect243"
+         style="fill:none;stroke:none" /><path
+         d="m 11700,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path245"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text247"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan249"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="11525"
+             y="4121"
+             id="tspan251"><tspan
+               id="tspan253"
+               style="fill:#000000;stroke:none">7</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g255"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id11"><rect
+         class="BoundingBox"
+         x="12899"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect258"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path260"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g262"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id12"><rect
+         class="BoundingBox"
+         x="15299"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect265"
+         style="fill:none;stroke:none" /><path
+         d="m 16500,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path267"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text269"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan271"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="16325"
+             y="4121"
+             id="tspan273"><tspan
+               id="tspan275"
+               style="fill:#000000;stroke:none">9</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g277"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id13"><rect
+         class="BoundingBox"
+         x="12899"
+         y="3199"
+         width="2403"
+         height="1403"
+         id="rect280"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path282"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text284"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan286"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="13925"
+             y="4121"
+             id="tspan288"><tspan
+               id="tspan290"
+               style="fill:#000000;stroke:none">8</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g292"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id14"><rect
+         class="BoundingBox"
+         x="3299"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect295"
+         style="fill:none;stroke:none" /><path
+         d="m 4500,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path297"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text299"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan301"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="4325"
+             y="5521"
+             id="tspan303"><tspan
+               id="tspan305"
+               style="fill:#000000;stroke:none">2</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g307"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id15"><rect
+         class="BoundingBox"
+         x="5699"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect310"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path312"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g314"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id16"><rect
+         class="BoundingBox"
+         x="8099"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect317"
+         style="fill:none;stroke:none" /><path
+         d="m 9300,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path319"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text321"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan323"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="9125"
+             y="5521"
+             id="tspan325"><tspan
+               id="tspan327"
+               style="fill:#000000;stroke:none">4</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g329"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id17"><rect
+         class="BoundingBox"
+         x="5699"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect332"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path334"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text336"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan338"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="6725"
+             y="5521"
+             id="tspan340"><tspan
+               id="tspan342"
+               style="fill:#000000;stroke:none">3</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g344"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id18"><rect
+         class="BoundingBox"
+         x="10499"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect347"
+         style="fill:none;stroke:none" /><path
+         d="m 11700,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path349"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text351"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan353"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="11525"
+             y="5521"
+             id="tspan355"><tspan
+               id="tspan357"
+               style="fill:#000000;stroke:none">5</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g359"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id19"><rect
+         class="BoundingBox"
+         x="12899"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect362"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path364"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g366"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id20"><rect
+         class="BoundingBox"
+         x="15299"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect369"
+         style="fill:none;stroke:none" /><path
+         d="m 16500,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path371"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text373"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan375"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="16149"
+             y="5521"
+             id="tspan377"><tspan
+               id="tspan379"
+               style="fill:#000000;stroke:none">11</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g381"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id21"><rect
+         class="BoundingBox"
+         x="12899"
+         y="4599"
+         width="2403"
+         height="1403"
+         id="rect384"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path386"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text388"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan390"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="13749"
+             y="5521"
+             id="tspan392"><tspan
+               id="tspan394"
+               style="fill:#000000;stroke:none">10</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g396"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id22"><rect
+         class="BoundingBox"
+         x="3299"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect399"
+         style="fill:none;stroke:none" /><path
+         d="m 4500,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path401"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text403"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan405"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="4149"
+             y="6921"
+             id="tspan407"><tspan
+               id="tspan409"
+               style="fill:#000000;stroke:none">12</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g411"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id23"><rect
+         class="BoundingBox"
+         x="5699"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect414"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path416"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g418"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id24"><rect
+         class="BoundingBox"
+         x="8099"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect421"
+         style="fill:none;stroke:none" /><path
+         d="m 9300,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path423"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text425"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan427"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="8949"
+             y="6921"
+             id="tspan429"><tspan
+               id="tspan431"
+               style="fill:#000000;stroke:none">18</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g433"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id25"><rect
+         class="BoundingBox"
+         x="5699"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect436"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path438"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text440"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan442"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="6549"
+             y="6921"
+             id="tspan444"><tspan
+               id="tspan446"
+               style="fill:#000000;stroke:none">13</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g448"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id26"><rect
+         class="BoundingBox"
+         x="10499"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect451"
+         style="fill:none;stroke:none" /><path
+         d="m 11700,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path453"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text455"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan457"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="11349"
+             y="6921"
+             id="tspan459"><tspan
+               id="tspan461"
+               style="fill:#000000;stroke:none">19</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g463"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id27"><rect
+         class="BoundingBox"
+         x="12899"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect466"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path468"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g470"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id28"><rect
+         class="BoundingBox"
+         x="15299"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect473"
+         style="fill:none;stroke:none" /><path
+         d="m 16500,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path475"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text477"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan479"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="16149"
+             y="6921"
+             id="tspan481"><tspan
+               id="tspan483"
+               style="fill:#000000;stroke:none">21</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g485"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id29"><rect
+         class="BoundingBox"
+         x="12899"
+         y="5999"
+         width="2403"
+         height="1403"
+         id="rect488"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,7400 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path490"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text492"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan494"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="13749"
+             y="6921"
+             id="tspan496"><tspan
+               id="tspan498"
+               style="fill:#000000;stroke:none">20</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g500"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id30"><rect
+         class="BoundingBox"
+         x="3299"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect503"
+         style="fill:none;stroke:none" /><path
+         d="m 4500,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path505"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text507"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan509"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="4149"
+             y="8321"
+             id="tspan511"><tspan
+               id="tspan513"
+               style="fill:#000000;stroke:none">14</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g515"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id31"><rect
+         class="BoundingBox"
+         x="5699"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect518"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path520"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g522"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id32"><rect
+         class="BoundingBox"
+         x="8099"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect525"
+         style="fill:none;stroke:none" /><path
+         d="m 9300,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path527"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text529"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan531"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="8949"
+             y="8321"
+             id="tspan533"><tspan
+               id="tspan535"
+               style="fill:#000000;stroke:none">16</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g537"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id33"><rect
+         class="BoundingBox"
+         x="5699"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect540"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path542"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text544"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan546"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="6549"
+             y="8321"
+             id="tspan548"><tspan
+               id="tspan550"
+               style="fill:#000000;stroke:none">15</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g552"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id34"><rect
+         class="BoundingBox"
+         x="10499"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect555"
+         style="fill:none;stroke:none" /><path
+         d="m 11700,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path557"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text559"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan561"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="11349"
+             y="8321"
+             id="tspan563"><tspan
+               id="tspan565"
+               style="fill:#000000;stroke:none">17</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g567"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id35"><rect
+         class="BoundingBox"
+         x="12899"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect570"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path572"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g574"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id36"><rect
+         class="BoundingBox"
+         x="15299"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect577"
+         style="fill:none;stroke:none" /><path
+         d="m 16500,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path579"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text581"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan583"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="16149"
+             y="8321"
+             id="tspan585"><tspan
+               id="tspan587"
+               style="fill:#000000;stroke:none">23</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g589"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id37"><rect
+         class="BoundingBox"
+         x="12899"
+         y="7399"
+         width="2403"
+         height="1403"
+         id="rect592"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,8800 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path594"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text596"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan598"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="13749"
+             y="8321"
+             id="tspan600"><tspan
+               id="tspan602"
+               style="fill:#000000;stroke:none">22</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g604"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id38"><rect
+         class="BoundingBox"
+         x="3299"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect607"
+         style="fill:none;stroke:none" /><path
+         d="m 4500,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path609"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text611"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan613"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="4149"
+             y="9721"
+             id="tspan615"><tspan
+               id="tspan617"
+               style="fill:#000000;stroke:none">24</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g619"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id39"><rect
+         class="BoundingBox"
+         x="5699"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect622"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path624"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g626"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id40"><rect
+         class="BoundingBox"
+         x="8099"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect629"
+         style="fill:none;stroke:none" /><path
+         d="m 9300,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path631"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text633"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan635"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="8949"
+             y="9721"
+             id="tspan637"><tspan
+               id="tspan639"
+               style="fill:#000000;stroke:none">26</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g641"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id41"><rect
+         class="BoundingBox"
+         x="5699"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect644"
+         style="fill:none;stroke:none" /><path
+         d="m 6900,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path646"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text648"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan650"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="6549"
+             y="9721"
+             id="tspan652"><tspan
+               id="tspan654"
+               style="fill:#000000;stroke:none">25</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g656"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id42"><rect
+         class="BoundingBox"
+         x="10499"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect659"
+         style="fill:none;stroke:none" /><path
+         d="m 11700,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path661"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text663"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan665"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="11349"
+             y="9721"
+             id="tspan667"><tspan
+               id="tspan669"
+               style="fill:#000000;stroke:none">27</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g671"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id43"><rect
+         class="BoundingBox"
+         x="12899"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect674"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path676"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /></g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g678"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id44"><rect
+         class="BoundingBox"
+         x="15299"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect681"
+         style="fill:none;stroke:none" /><path
+         d="m 16500,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path683"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text685"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan687"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="16149"
+             y="9721"
+             id="tspan689"><tspan
+               id="tspan691"
+               style="fill:#000000;stroke:none">29</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.CustomShape"
+     id="g693"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id45"><rect
+         class="BoundingBox"
+         x="12899"
+         y="8799"
+         width="2403"
+         height="1403"
+         id="rect696"
+         style="fill:none;stroke:none" /><path
+         d="m 14100,10200 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+         id="path698"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#3465a4" /><text
+         class="TextShape"
+         id="text700"><tspan
+           class="TextParagraph"
+           font-size="635px"
+           font-weight="400"
+           id="tspan702"
+           style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+             class="TextPosition"
+             x="13749"
+             y="9721"
+             id="tspan704"><tspan
+               id="tspan706"
+               style="fill:#000000;stroke:none">28</tspan></tspan></tspan></text>
+</g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g708"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id46"><rect
+         class="BoundingBox"
+         x="5199"
+         y="3850"
+         width="1402"
+         height="301"
+         id="rect711"
+         style="fill:none;stroke:none" /><path
+         d="m 5200,4000 970,0"
+         id="path713"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 6600,4000 -450,-150 0,300 450,-150 z"
+         id="path715"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g717"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id47"><rect
+         class="BoundingBox"
+         x="5000"
+         y="4299"
+         width="1202"
+         height="802"
+         id="rect720"
+         style="fill:none;stroke:none" /><path
+         d="m 6200,4300 -842,561"
+         id="path722"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 5000,5100 458,-125 -167,-249 -291,374 z"
+         id="path724"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g726"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id48"><rect
+         class="BoundingBox"
+         x="5399"
+         y="5250"
+         width="1202"
+         height="301"
+         id="rect729"
+         style="fill:none;stroke:none" /><path
+         d="m 5400,5400 770,0"
+         id="path731"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 6600,5400 -450,-150 0,300 450,-150 z"
+         id="path733"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g735"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id49"><rect
+         class="BoundingBox"
+         x="7599"
+         y="5250"
+         width="1202"
+         height="301"
+         id="rect738"
+         style="fill:none;stroke:none" /><path
+         d="m 7600,5400 770,0"
+         id="path740"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 8800,5400 -450,-150 0,300 450,-150 z"
+         id="path742"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g744"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id50"><rect
+         class="BoundingBox"
+         x="9799"
+         y="5250"
+         width="1402"
+         height="301"
+         id="rect747"
+         style="fill:none;stroke:none" /><path
+         d="m 9800,5400 970,0"
+         id="path749"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 11200,5400 -450,-150 0,300 450,-150 z"
+         id="path751"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g753"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id51"><rect
+         class="BoundingBox"
+         x="9900"
+         y="4200"
+         width="1202"
+         height="802"
+         id="rect756"
+         style="fill:none;stroke:none" /><path
+         d="m 11100,5000 -842,-561"
+         id="path758"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 9900,4200 291,374 167,-249 -458,-125 z"
+         id="path760"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g762"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id52"><rect
+         class="BoundingBox"
+         x="9999"
+         y="3850"
+         width="1402"
+         height="301"
+         id="rect765"
+         style="fill:none;stroke:none" /><path
+         d="m 10000,4000 970,0"
+         id="path767"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 11400,4000 -450,-150 0,300 450,-150 z"
+         id="path769"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g771"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id53"><rect
+         class="BoundingBox"
+         x="12399"
+         y="3850"
+         width="1202"
+         height="301"
+         id="rect774"
+         style="fill:none;stroke:none" /><path
+         d="m 12400,4000 770,0"
+         id="path776"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 13600,4000 -450,-150 0,300 450,-150 z"
+         id="path778"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g780"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id54"><rect
+         class="BoundingBox"
+         x="14799"
+         y="3850"
+         width="1202"
+         height="301"
+         id="rect783"
+         style="fill:none;stroke:none" /><path
+         d="m 14800,4000 770,0"
+         id="path785"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 16000,4000 -450,-150 0,300 450,-150 z"
+         id="path787"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g789"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id55"><rect
+         class="BoundingBox"
+         x="14400"
+         y="4399"
+         width="1402"
+         height="602"
+         id="rect792"
+         style="fill:none;stroke:none" /><path
+         d="m 15800,4400 -1005,431"
+         id="path794"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 14400,5000 473,-39 -118,-276 -355,315 z"
+         id="path796"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g798"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id56"><rect
+         class="BoundingBox"
+         x="14599"
+         y="5250"
+         width="1402"
+         height="301"
+         id="rect801"
+         style="fill:none;stroke:none" /><path
+         d="m 14600,5400 970,0"
+         id="path803"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 16000,5400 -450,-150 0,300 450,-150 z"
+         id="path805"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g807"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id57"><rect
+         class="BoundingBox"
+         x="5199"
+         y="6550"
+         width="1402"
+         height="301"
+         id="rect810"
+         style="fill:none;stroke:none" /><path
+         d="m 5200,6700 970,0"
+         id="path812"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 6600,6700 -450,-150 0,300 450,-150 z"
+         id="path814"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g816"
+     transform="translate(-3285.889,-3129.4446)"><g
+       id="id58"><rect
+         class="BoundingBox"
+         x="5000"
+         y="6999"
+         width="1202"
+         height="802"
+         id="rect819"
+         style="fill:none;stroke:none" /><path
+         d="m 6200,7000 -842,561"
+         id="path821"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 5000,7800 458,-125 -167,-249 -291,374 z"
+         id="path823"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g825"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id59"><rect
+         class="BoundingBox"
+         x="5399"
+         y="7950"
+         width="1202"
+         height="301"
+         id="rect828"
+         style="fill:none;stroke:none" /><path
+         d="m 5400,8100 770,0"
+         id="path830"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 6600,8100 -450,-150 0,300 450,-150 z"
+         id="path832"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g834"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id60"><rect
+         class="BoundingBox"
+         x="7599"
+         y="7950"
+         width="1202"
+         height="301"
+         id="rect837"
+         style="fill:none;stroke:none" /><path
+         d="m 7600,8100 770,0"
+         id="path839"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 8800,8100 -450,-150 0,300 450,-150 z"
+         id="path841"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g843"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id61"><rect
+         class="BoundingBox"
+         x="9799"
+         y="7950"
+         width="1402"
+         height="301"
+         id="rect846"
+         style="fill:none;stroke:none" /><path
+         d="m 9800,8100 970,0"
+         id="path848"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 11200,8100 -450,-150 0,300 450,-150 z"
+         id="path850"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g852"
+     transform="translate(-3285.889,-3129.4446)"><g
+       id="id62"><rect
+         class="BoundingBox"
+         x="9900"
+         y="6900"
+         width="1202"
+         height="802"
+         id="rect855"
+         style="fill:none;stroke:none" /><path
+         d="m 11100,7700 -842,-561"
+         id="path857"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 9900,6900 291,374 167,-249 -458,-125 z"
+         id="path859"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g861"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id63"><rect
+         class="BoundingBox"
+         x="9999"
+         y="6550"
+         width="1402"
+         height="301"
+         id="rect864"
+         style="fill:none;stroke:none" /><path
+         d="m 10000,6700 970,0"
+         id="path866"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 11400,6700 -450,-150 0,300 450,-150 z"
+         id="path868"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g870"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id64"><rect
+         class="BoundingBox"
+         x="12399"
+         y="6550"
+         width="1202"
+         height="301"
+         id="rect873"
+         style="fill:none;stroke:none" /><path
+         d="m 12400,6700 770,0"
+         id="path875"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 13600,6700 -450,-150 0,300 450,-150 z"
+         id="path877"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g879"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id65"><rect
+         class="BoundingBox"
+         x="14799"
+         y="6550"
+         width="1202"
+         height="301"
+         id="rect882"
+         style="fill:none;stroke:none" /><path
+         d="m 14800,6700 770,0"
+         id="path884"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 16000,6700 -450,-150 0,300 450,-150 z"
+         id="path886"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g888"
+     transform="translate(-3285.889,-3129.4446)"><g
+       id="id66"><rect
+         class="BoundingBox"
+         x="14400"
+         y="7099"
+         width="1402"
+         height="602"
+         id="rect891"
+         style="fill:none;stroke:none" /><path
+         d="m 15800,7100 -1005,431"
+         id="path893"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 14400,7700 473,-39 -118,-276 -355,315 z"
+         id="path895"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g897"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id67"><rect
+         class="BoundingBox"
+         x="14599"
+         y="7950"
+         width="1402"
+         height="301"
+         id="rect900"
+         style="fill:none;stroke:none" /><path
+         d="m 14600,8100 970,0"
+         id="path902"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 16000,8100 -450,-150 0,300 450,-150 z"
+         id="path904"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g906"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id68"><rect
+         class="BoundingBox"
+         x="5399"
+         y="9450"
+         width="1202"
+         height="301"
+         id="rect909"
+         style="fill:none;stroke:none" /><path
+         d="m 5400,9600 770,0"
+         id="path911"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 6600,9600 -450,-150 0,300 450,-150 z"
+         id="path913"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g915"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id69"><rect
+         class="BoundingBox"
+         x="7599"
+         y="9450"
+         width="1202"
+         height="301"
+         id="rect918"
+         style="fill:none;stroke:none" /><path
+         d="m 7600,9600 770,0"
+         id="path920"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 8800,9600 -450,-150 0,300 450,-150 z"
+         id="path922"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g924"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id70"><rect
+         class="BoundingBox"
+         x="9999"
+         y="9450"
+         width="1202"
+         height="301"
+         id="rect927"
+         style="fill:none;stroke:none" /><path
+         d="m 10000,9600 770,0"
+         id="path929"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 11200,9600 -450,-150 0,300 450,-150 z"
+         id="path931"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g933"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id71"><rect
+         class="BoundingBox"
+         x="12399"
+         y="9450"
+         width="1202"
+         height="301"
+         id="rect936"
+         style="fill:none;stroke:none" /><path
+         d="m 12400,9600 770,0"
+         id="path938"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 13600,9600 -450,-150 0,300 450,-150 z"
+         id="path940"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g><g
+     class="com.sun.star.drawing.LineShape"
+     id="g942"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="id72"><rect
+         class="BoundingBox"
+         x="14799"
+         y="9450"
+         width="1202"
+         height="301"
+         id="rect945"
+         style="fill:none;stroke:none" /><path
+         d="m 14800,9600 770,0"
+         id="path947"
+         inkscape:connector-curvature="0"
+         style="fill:none;stroke:#ff3333" /><path
+         d="m 16000,9600 -450,-150 0,300 450,-150 z"
+         id="path949"
+         inkscape:connector-curvature="0"
+         style="fill:#ff3333;stroke:none" /></g></g></svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/nv12mt.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/nv12mt.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/nv12mt.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/nv12mt.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,450 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.2"
+   width="96.282211mm"
+   height="28.282219mm"
+   viewBox="0 0 9628.2211 2828.2219"
+   preserveAspectRatio="xMidYMid"
+   xml:space="preserve"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="nv12mt.svg"
+   style="fill-rule:evenodd;stroke-width:28.22200012;stroke-linejoin:round"><metadata
+     id="metadata383"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview381"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="4.0919524"
+     inkscape:cx="170.57872"
+     inkscape:cy="50.106293"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" /><defs
+     class="ClipPathGroup"
+     id="defs4"><clipPath
+       id="presentation_clip_path"
+       clipPathUnits="userSpaceOnUse"><rect
+         x="0"
+         y="0"
+         width="28000"
+         height="21000"
+         id="rect7" /></clipPath></defs><defs
+     id="defs9" /><defs
+     id="defs80" /><defs
+     id="defs103" /><defs
+     class="TextShapeIndex"
+     id="defs114" /><defs
+     class="EmbeddedBulletChars"
+     id="defs118" /><defs
+     class="TextEmbeddedBitmaps"
+     id="defs147" /><g
+     class="SlideGroup"
+     id="g177"
+     transform="translate(-3285.889,-3185.889)"><g
+       id="g179"><g
+         id="id1"
+         class="Slide"
+         clip-path="url(#presentation_clip_path)"><g
+           class="Page"
+           id="g182"><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g184"><g
+               id="id6"><rect
+                 class="BoundingBox"
+                 x="3299"
+                 y="3199"
+                 width="2403"
+                 height="1403"
+                 id="rect187"
+                 style="fill:none;stroke:none" /><path
+                 d="m 4500,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path189"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text191"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan193"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="4325"
+                     y="4121"
+                     id="tspan195"><tspan
+                       id="tspan197"
+                       style="fill:#000000;stroke:none">0</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g199"><g
+               id="id7"><rect
+                 class="BoundingBox"
+                 x="5699"
+                 y="3199"
+                 width="2403"
+                 height="1403"
+                 id="rect202"
+                 style="fill:none;stroke:none" /><path
+                 d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path204"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /></g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g206"><g
+               id="id8"><rect
+                 class="BoundingBox"
+                 x="8099"
+                 y="3199"
+                 width="2403"
+                 height="1403"
+                 id="rect209"
+                 style="fill:none;stroke:none" /><path
+                 d="m 9300,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path211"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text213"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan215"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="9125"
+                     y="4121"
+                     id="tspan217"><tspan
+                       id="tspan219"
+                       style="fill:#000000;stroke:none">6</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g221"><g
+               id="id9"><rect
+                 class="BoundingBox"
+                 x="5699"
+                 y="3199"
+                 width="2403"
+                 height="1403"
+                 id="rect224"
+                 style="fill:none;stroke:none" /><path
+                 d="m 6900,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path226"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text228"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan230"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="6725"
+                     y="4121"
+                     id="tspan232"><tspan
+                       id="tspan234"
+                       style="fill:#000000;stroke:none">1</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g236"><g
+               id="id10"><rect
+                 class="BoundingBox"
+                 x="10499"
+                 y="3199"
+                 width="2403"
+                 height="1403"
+                 id="rect239"
+                 style="fill:none;stroke:none" /><path
+                 d="m 11700,4600 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path241"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text243"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan245"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="11525"
+                     y="4121"
+                     id="tspan247"><tspan
+                       id="tspan249"
+                       style="fill:#000000;stroke:none">7</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g251"><g
+               id="id11"><rect
+                 class="BoundingBox"
+                 x="3299"
+                 y="4599"
+                 width="2403"
+                 height="1403"
+                 id="rect254"
+                 style="fill:none;stroke:none" /><path
+                 d="m 4500,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path256"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text258"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan260"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="4325"
+                     y="5521"
+                     id="tspan262"><tspan
+                       id="tspan264"
+                       style="fill:#000000;stroke:none">2</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g266"><g
+               id="id12"><rect
+                 class="BoundingBox"
+                 x="5699"
+                 y="4599"
+                 width="2403"
+                 height="1403"
+                 id="rect269"
+                 style="fill:none;stroke:none" /><path
+                 d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path271"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /></g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g273"><g
+               id="id13"><rect
+                 class="BoundingBox"
+                 x="8099"
+                 y="4599"
+                 width="2403"
+                 height="1403"
+                 id="rect276"
+                 style="fill:none;stroke:none" /><path
+                 d="m 9300,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path278"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text280"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan282"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="9125"
+                     y="5521"
+                     id="tspan284"><tspan
+                       id="tspan286"
+                       style="fill:#000000;stroke:none">4</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g288"><g
+               id="id14"><rect
+                 class="BoundingBox"
+                 x="5699"
+                 y="4599"
+                 width="2403"
+                 height="1403"
+                 id="rect291"
+                 style="fill:none;stroke:none" /><path
+                 d="m 6900,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path293"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text295"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan297"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="6725"
+                     y="5521"
+                     id="tspan299"><tspan
+                       id="tspan301"
+                       style="fill:#000000;stroke:none">3</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.CustomShape"
+             id="g303"><g
+               id="id15"><rect
+                 class="BoundingBox"
+                 x="10499"
+                 y="4599"
+                 width="2403"
+                 height="1403"
+                 id="rect306"
+                 style="fill:none;stroke:none" /><path
+                 d="m 11700,6000 -1200,0 0,-1400 2400,0 0,1400 -1200,0 z"
+                 id="path308"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#3465a4" /><text
+                 class="TextShape"
+                 id="text310"><tspan
+                   class="TextParagraph"
+                   font-size="635px"
+                   font-weight="400"
+                   id="tspan312"
+                   style="font-weight:400;font-size:635px;font-family:sans-serif"><tspan
+                     class="TextPosition"
+                     x="11525"
+                     y="5521"
+                     id="tspan314"><tspan
+                       id="tspan316"
+                       style="fill:#000000;stroke:none">5</tspan></tspan></tspan></text>
+</g></g><g
+             class="com.sun.star.drawing.LineShape"
+             id="g318"><g
+               id="id16"><rect
+                 class="BoundingBox"
+                 x="5199"
+                 y="3850"
+                 width="1402"
+                 height="301"
+                 id="rect321"
+                 style="fill:none;stroke:none" /><path
+                 d="m 5200,4000 970,0"
+                 id="path323"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#ff3333" /><path
+                 d="m 6600,4000 -450,-150 0,300 450,-150 z"
+                 id="path325"
+                 inkscape:connector-curvature="0"
+                 style="fill:#ff3333;stroke:none" /></g></g><g
+             class="com.sun.star.drawing.LineShape"
+             id="g327"><g
+               id="id17"><rect
+                 class="BoundingBox"
+                 x="5000"
+                 y="4299"
+                 width="1202"
+                 height="802"
+                 id="rect330"
+                 style="fill:none;stroke:none" /><path
+                 d="m 6200,4300 -842,561"
+                 id="path332"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#ff3333" /><path
+                 d="m 5000,5100 458,-125 -167,-249 -291,374 z"
+                 id="path334"
+                 inkscape:connector-curvature="0"
+                 style="fill:#ff3333;stroke:none" /></g></g><g
+             class="com.sun.star.drawing.LineShape"
+             id="g336"><g
+               id="id18"><rect
+                 class="BoundingBox"
+                 x="5399"
+                 y="5250"
+                 width="1202"
+                 height="301"
+                 id="rect339"
+                 style="fill:none;stroke:none" /><path
+                 d="m 5400,5400 770,0"
+                 id="path341"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#ff3333" /><path
+                 d="m 6600,5400 -450,-150 0,300 450,-150 z"
+                 id="path343"
+                 inkscape:connector-curvature="0"
+                 style="fill:#ff3333;stroke:none" /></g></g><g
+             class="com.sun.star.drawing.LineShape"
+             id="g345"><g
+               id="id19"><rect
+                 class="BoundingBox"
+                 x="7599"
+                 y="5250"
+                 width="1202"
+                 height="301"
+                 id="rect348"
+                 style="fill:none;stroke:none" /><path
+                 d="m 7600,5400 770,0"
+                 id="path350"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#ff3333" /><path
+                 d="m 8800,5400 -450,-150 0,300 450,-150 z"
+                 id="path352"
+                 inkscape:connector-curvature="0"
+                 style="fill:#ff3333;stroke:none" /></g></g><g
+             class="com.sun.star.drawing.LineShape"
+             id="g354"><g
+               id="id20"><rect
+                 class="BoundingBox"
+                 x="9799"
+                 y="5250"
+                 width="1402"
+                 height="301"
+                 id="rect357"
+                 style="fill:none;stroke:none" /><path
+                 d="m 9800,5400 970,0"
+                 id="path359"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#ff3333" /><path
+                 d="m 11200,5400 -450,-150 0,300 450,-150 z"
+                 id="path361"
+                 inkscape:connector-curvature="0"
+                 style="fill:#ff3333;stroke:none" /></g></g><g
+             class="com.sun.star.drawing.LineShape"
+             id="g363"><g
+               id="id21"><rect
+                 class="BoundingBox"
+                 x="9900"
+                 y="4200"
+                 width="1202"
+                 height="802"
+                 id="rect366"
+                 style="fill:none;stroke:none" /><path
+                 d="m 11100,5000 -842,-561"
+                 id="path368"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#ff3333" /><path
+                 d="m 9900,4200 291,374 167,-249 -458,-125 z"
+                 id="path370"
+                 inkscape:connector-curvature="0"
+                 style="fill:#ff3333;stroke:none" /></g></g><g
+             class="com.sun.star.drawing.LineShape"
+             id="g372"><g
+               id="id22"><rect
+                 class="BoundingBox"
+                 x="9999"
+                 y="3850"
+                 width="1402"
+                 height="301"
+                 id="rect375"
+                 style="fill:none;stroke:none" /><path
+                 d="m 10000,4000 970,0"
+                 id="path377"
+                 inkscape:connector-curvature="0"
+                 style="fill:none;stroke:#ff3333" /><path
+                 d="m 11400,4000 -450,-150 0,300 450,-150 z"
+                 id="path379"
+                 inkscape:connector-curvature="0"
+                 style="fill:#ff3333;stroke:none" /></g></g></g></g></g></g></svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pipeline.dot linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pipeline.dot
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pipeline.dot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pipeline.dot	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,12 @@
+digraph board {
+	rankdir=TB
+	colorscheme=x11
+	scaler [label="{<scaler_0> 0} | Host\nScaler | {<scaler_1> 1} ", shape=Mrecord, style=filled, fillcolor=lightblue]
+	frontend [label="{<frontend_0> 0} | Host\nFrontend | {<frontend_1> 1}", shape=Mrecord, style=filled, fillcolor=lightblue]
+	sensor [label="Sensor | {<sensor_0> 0}", shape=Mrecord, style=filled, fillcolor=aquamarine]
+	io [label="{<io_0> 0} | V4L I/O", shape=Mrecord, style=filled, fillcolor=aquamarine]
+
+	sensor:sensor_0 -> frontend:frontend_0 [color=blue, label="HQ: 2592x1968\nHS: 1296x984"]
+	frontend:frontend_1 -> scaler:scaler_0 [color=blue, label="HQ: 2592x1968\nHS: 1296x984"]
+	scaler:scaler_1 -> io:io_0 [color=blue, label="HQ: 1280x720\nHS: 1280x720"]
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-002.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-002.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-002.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-002.rst	2017-02-12 16:03:20.000000000 -0500
@@ -121,6 +121,11 @@ Single-planar format structure
       - This information supplements the ``colorspace`` and must be set by
 	the driver for capture streams and by the application for output
 	streams, see :ref:`colorspaces`.
+    * - enum :c:type:`v4l2_hsv_encoding`
+      - ``hsv_enc``
+      - This information supplements the ``colorspace`` and must be set by
+	the driver for capture streams and by the application for output
+	streams, see :ref:`colorspaces`.
     * - enum :c:type:`v4l2_quantization`
       - ``quantization``
       - This information supplements the ``colorspace`` and must be set by
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-003.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-003.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-003.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-003.rst	2017-02-12 16:03:20.000000000 -0500
@@ -78,6 +78,11 @@ describing all planes of that format.
       - This information supplements the ``colorspace`` and must be set by
 	the driver for capture streams and by the application for output
 	streams, see :ref:`colorspaces`.
+    * - enum :c:type:`v4l2_hsv_encoding`
+      - ``hsv_enc``
+      - This information supplements the ``colorspace`` and must be set by
+	the driver for capture streams and by the application for output
+	streams, see :ref:`colorspaces`.
     * - enum :c:type:`v4l2_quantization`
       - ``quantization``
       - This information supplements the ``colorspace`` and must be set by
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-006.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-006.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-006.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-006.rst	2017-02-12 16:03:20.000000000 -0500
@@ -19,9 +19,16 @@ colorspace field of struct :c:type:`v4l2
 or struct :c:type:`v4l2_pix_format_mplane`
 needs to be filled in.
 
-.. note::
+.. _hsv-colorspace:
 
-   The default R'G'B' quantization is full range for all
+On :ref:`HSV formats <hsv-formats>` the *Hue* is defined as the angle on
+the cylindrical color representation. Usually this angle is measured in
+degrees, i.e. 0-360. When we map this angle value into 8 bits, there are
+two basic ways to do it: Divide the angular value by 2 (0-179), or use the
+whole range, 0-255, dividing the angular value by 1.41. The enum
+:c:type:`v4l2_hsv_encoding` specifies which encoding is used.
+
+.. note:: The default R'G'B' quantization is full range for all
    colorspaces except for BT.2020 which uses limited range R'G'B'
    quantization.
 
@@ -123,6 +130,24 @@ needs to be filled in.
 
 
 
+.. c:type:: v4l2_hsv_encoding
+
+.. tabularcolumns:: |p{6.5cm}|p{11.0cm}|
+
+.. flat-table:: V4L2 HSV Encodings
+    :header-rows:  1
+    :stub-columns: 0
+
+    * - Identifier
+      - Details
+    * - ``V4L2_HSV_ENC_180``
+      - For the Hue, each LSB is two degrees.
+    * - ``V4L2_HSV_ENC_256``
+      - For the Hue, the 360 degrees are mapped into 8 bits, i.e. each
+	LSB is roughly 1.41 degrees.
+
+
+
 .. c:type:: v4l2_quantization
 
 .. tabularcolumns:: |p{6.5cm}|p{11.0cm}|
@@ -136,7 +161,7 @@ needs to be filled in.
     * - ``V4L2_QUANTIZATION_DEFAULT``
       - Use the default quantization encoding as defined by the
 	colorspace. This is always full range for R'G'B' (except for the
-	BT.2020 colorspace) and usually limited range for Y'CbCr.
+	BT.2020 colorspace) and HSV. It is usually limited range for Y'CbCr.
     * - ``V4L2_QUANTIZATION_FULL_RANGE``
       - Use the full range quantization encoding. I.e. the range [0…1] is
 	mapped to [0…255] (with possible clipping to [1…254] to avoid the
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-013.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-013.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-013.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-013.rst	2017-02-12 16:03:20.000000000 -0500
@@ -85,3 +85,8 @@ Compressed Formats
       - ``V4L2_PIX_FMT_VP8``
       - 'VP80'
       - VP8 video elementary stream.
+    * .. _V4L2-PIX-FMT-VP9:
+
+      - ``V4L2_PIX_FMT_VP9``
+      - 'VP90'
+      - VP9 video elementary stream.
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt_example.png and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt_example.png differ
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt.png and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt_files/nv12mt.png differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-nv12mt.rst	2017-02-12 16:03:20.000000000 -0500
@@ -33,8 +33,8 @@ Layout of macroblocks in memory is prese
 
 .. _nv12mt:
 
-.. figure::  pixfmt-nv12mt_files/nv12mt.*
-    :alt:    nv12mt.png
+.. figure::  nv12mt.*
+    :alt:    nv12mt.pdf / nv12mt.svg
     :align:  center
 
     V4L2_PIX_FMT_NV12MT macroblock Z shape memory layout
@@ -50,8 +50,8 @@ interleaved. Height of the buffer is ali
 
 .. _nv12mt_ex:
 
-.. figure::  pixfmt-nv12mt_files/nv12mt_example.*
-    :alt:    nv12mt_example.png
+.. figure::  nv12mt_example.*
+    :alt:    nv12mt_example.pdf / nv12mt_example.svg
     :align:  center
 
     Example V4L2_PIX_FMT_NV12MT memory layout of macroblocks
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-packed-hsv.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,157 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _packed-hsv:
+
+******************
+Packed HSV formats
+******************
+
+Description
+===========
+
+The *hue* (h) is measured in degrees, the equivalence between degrees and LSBs
+depends on the hsv-encoding used, see :ref:`colorspaces`.
+The *saturation* (s) and the *value* (v) are measured in percentage of the
+cylinder: 0 being the smallest value and 255 the maximum.
+
+
+The values are packed in 24 or 32 bit formats.
+
+.. raw:: latex
+
+    \newline\begin{adjustbox}{width=\columnwidth}
+
+.. tabularcolumns:: |p{4.2cm}|p{1.0cm}|p{0.7cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.2cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.2cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.2cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{0.4cm}|p{1.7cm}|
+
+.. _packed-hsv-formats:
+
+.. flat-table:: Packed HSV Image Formats
+    :header-rows:  2
+    :stub-columns: 0
+
+    * - Identifier
+      - Code
+      -
+      - :cspan:`7` Byte 0 in memory
+      -
+      - :cspan:`7` Byte 1
+      -
+      - :cspan:`7` Byte 2
+      -
+      - :cspan:`7` Byte 3
+    * -
+      -
+      - Bit
+      - 7
+      - 6
+      - 5
+      - 4
+      - 3
+      - 2
+      - 1
+      - 0
+      -
+      - 7
+      - 6
+      - 5
+      - 4
+      - 3
+      - 2
+      - 1
+      - 0
+      -
+      - 7
+      - 6
+      - 5
+      - 4
+      - 3
+      - 2
+      - 1
+      - 0
+      -
+      - 7
+      - 6
+      - 5
+      - 4
+      - 3
+      - 2
+      - 1
+      - 0
+    * .. _V4L2-PIX-FMT-HSV32:
+
+      - ``V4L2_PIX_FMT_HSV32``
+      - 'HSV4'
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - h\ :sub:`7`
+      - h\ :sub:`6`
+      - h\ :sub:`5`
+      - h\ :sub:`4`
+      - h\ :sub:`3`
+      - h\ :sub:`2`
+      - h\ :sub:`1`
+      - h\ :sub:`0`
+      -
+      - s\ :sub:`7`
+      - s\ :sub:`6`
+      - s\ :sub:`5`
+      - s\ :sub:`4`
+      - s\ :sub:`3`
+      - s\ :sub:`2`
+      - s\ :sub:`1`
+      - s\ :sub:`0`
+      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * .. _V4L2-PIX-FMT-HSV24:
+
+      - ``V4L2_PIX_FMT_HSV24``
+      - 'HSV3'
+      -
+      - h\ :sub:`7`
+      - h\ :sub:`6`
+      - h\ :sub:`5`
+      - h\ :sub:`4`
+      - h\ :sub:`3`
+      - h\ :sub:`2`
+      - h\ :sub:`1`
+      - h\ :sub:`0`
+      -
+      - s\ :sub:`7`
+      - s\ :sub:`6`
+      - s\ :sub:`5`
+      - s\ :sub:`4`
+      - s\ :sub:`3`
+      - s\ :sub:`2`
+      - s\ :sub:`1`
+      - s\ :sub:`0`
+      -
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      -
+      -
+.. raw:: latex
+
+    \end{adjustbox}\newline\newline
+
+Bit 7 is the most significant bit.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-reserved.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-reserved.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-reserved.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-reserved.rst	2017-02-12 16:03:20.000000000 -0500
@@ -234,7 +234,15 @@ please make a proposal on the linux-medi
 	repeated for each line, i.e. the number of entries in the pointer
 	array. Anything what's in between the UYVY lines is JPEG data and
 	should be concatenated to form the JPEG stream.
+    * .. _V4L2-PIX-FMT-MT21C:
 
+      - ``V4L2_PIX_FMT_MT21C``
+      - 'MT21'
+      - Compressed two-planar YVU420 format used by Mediatek MT8173.
+	The compression is lossless.
+	It is an opaque intermediate format and the MDP hardware must be
+	used to convert ``V4L2_PIX_FMT_MT21C`` to ``V4L2_PIX_FMT_NV12M``,
+	``V4L2_PIX_FMT_YUV420M`` or ``V4L2_PIX_FMT_YVU420``.
 
 
 .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-rgb.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-rgb.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-rgb.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-rgb.rst	2017-02-12 16:03:20.000000000 -0500
@@ -12,9 +12,9 @@ RGB Formats
 
     pixfmt-packed-rgb
     pixfmt-srggb8
-    pixfmt-sbggr16
     pixfmt-srggb10
     pixfmt-srggb10p
     pixfmt-srggb10alaw8
     pixfmt-srggb10dpcm8
     pixfmt-srggb12
+    pixfmt-srggb16
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt.rst	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,7 @@ see also :ref:`VIDIOC_G_FBUF <VIDIOC_G_F
     pixfmt-indexed
     pixfmt-rgb
     yuv-formats
+    hsv-formats
     depth-formats
     pixfmt-013
     sdr-formats
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-sbggr16.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-sbggr16.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-sbggr16.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-sbggr16.rst	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-.. -*- coding: utf-8; mode: rst -*-
-
-.. _V4L2-PIX-FMT-SBGGR16:
-
-*****************************
-V4L2_PIX_FMT_SBGGR16 ('BYR2')
-*****************************
-
-Bayer RGB format
-
-
-Description
-===========
-
-This format is similar to
-:ref:`V4L2_PIX_FMT_SBGGR8 <V4L2-PIX-FMT-SBGGR8>`, except each pixel
-has a depth of 16 bits. The least significant byte is stored at lower
-memory addresses (little-endian).
-
-**Byte Order.**
-Each cell is one byte.
-
-.. flat-table::
-    :header-rows:  0
-    :stub-columns: 0
-
-    * - start + 0:
-      - B\ :sub:`00low`
-      - B\ :sub:`00high`
-      - G\ :sub:`01low`
-      - G\ :sub:`01high`
-      - B\ :sub:`02low`
-      - B\ :sub:`02high`
-      - G\ :sub:`03low`
-      - G\ :sub:`03high`
-    * - start + 8:
-      - G\ :sub:`10low`
-      - G\ :sub:`10high`
-      - R\ :sub:`11low`
-      - R\ :sub:`11high`
-      - G\ :sub:`12low`
-      - G\ :sub:`12high`
-      - R\ :sub:`13low`
-      - R\ :sub:`13high`
-    * - start + 16:
-      - B\ :sub:`20low`
-      - B\ :sub:`20high`
-      - G\ :sub:`21low`
-      - G\ :sub:`21high`
-      - B\ :sub:`22low`
-      - B\ :sub:`22high`
-      - G\ :sub:`23low`
-      - G\ :sub:`23high`
-    * - start + 24:
-      - G\ :sub:`30low`
-      - G\ :sub:`30high`
-      - R\ :sub:`31low`
-      - R\ :sub:`31high`
-      - G\ :sub:`32low`
-      - G\ :sub:`32high`
-      - R\ :sub:`33low`
-      - R\ :sub:`33high`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb10p.rst	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@ bits of each pixel, in the same order.
 Each n-pixel row contains n/2 green samples and n/2 blue or red samples,
 with alternating green-red and green-blue rows. They are conventionally
 described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example
-of one of these formats:
+of a small V4L2_PIX_FMT_SBGGR10P image:
 
 **Byte Order.**
 Each cell is one byte.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb12.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb12.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb12.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb12.rst	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@ high bits filled with zeros. Each n-pixe
 and n/2 blue or red samples, with alternating red and blue rows. Bytes
 are stored in memory in little endian order. They are conventionally
 described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example
-of one of these formats:
+of a small V4L2_PIX_FMT_SBGGR12 image:
 
 **Byte Order.**
 Each cell is one byte, the 4 most significant bits in the high bytes are
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb16.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb16.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb16.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb16.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+.. -*- coding: utf-8; mode: rst -*-
+
+.. _V4L2-PIX-FMT-SRGGB16:
+.. _v4l2-pix-fmt-sbggr16:
+.. _v4l2-pix-fmt-sgbrg16:
+.. _v4l2-pix-fmt-sgrbg16:
+
+
+***************************************************************************************************************************
+V4L2_PIX_FMT_SRGGB16 ('RG16'), V4L2_PIX_FMT_SGRBG16 ('GR16'), V4L2_PIX_FMT_SGBRG16 ('GB16'), V4L2_PIX_FMT_SBGGR16 ('BYR2'),
+***************************************************************************************************************************
+
+
+16-bit Bayer formats
+
+
+Description
+===========
+
+These four pixel formats are raw sRGB / Bayer formats with 16 bits per
+sample. Each sample is stored in a 16-bit word. Each n-pixel row contains
+n/2 green samples and n/2 blue or red samples, with alternating red and blue
+rows. Bytes are stored in memory in little endian order. They are
+conventionally described as GRGR... BGBG..., RGRG... GBGB..., etc. Below is
+an example of a small V4L2_PIX_FMT_SBGGR16 image:
+
+**Byte Order.**
+Each cell is one byte.
+
+.. flat-table::
+    :header-rows:  0
+    :stub-columns: 0
+
+    * - start + 0:
+      - B\ :sub:`00low`
+      - B\ :sub:`00high`
+      - G\ :sub:`01low`
+      - G\ :sub:`01high`
+      - B\ :sub:`02low`
+      - B\ :sub:`02high`
+      - G\ :sub:`03low`
+      - G\ :sub:`03high`
+    * - start + 8:
+      - G\ :sub:`10low`
+      - G\ :sub:`10high`
+      - R\ :sub:`11low`
+      - R\ :sub:`11high`
+      - G\ :sub:`12low`
+      - G\ :sub:`12high`
+      - R\ :sub:`13low`
+      - R\ :sub:`13high`
+    * - start + 16:
+      - B\ :sub:`20low`
+      - B\ :sub:`20high`
+      - G\ :sub:`21low`
+      - G\ :sub:`21high`
+      - B\ :sub:`22low`
+      - B\ :sub:`22high`
+      - G\ :sub:`23low`
+      - G\ :sub:`23high`
+    * - start + 24:
+      - G\ :sub:`30low`
+      - G\ :sub:`30high`
+      - R\ :sub:`31low`
+      - R\ :sub:`31high`
+      - G\ :sub:`32low`
+      - G\ :sub:`32high`
+      - R\ :sub:`33low`
+      - R\ :sub:`33high`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb8.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb8.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/pixfmt-srggb8.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/pixfmt-srggb8.rst	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@ These four pixel formats are raw sRGB /
 sample. Each sample is stored in a byte. Each n-pixel row contains n/2
 green samples and n/2 blue or red samples, with alternating red and
 blue rows. They are conventionally described as GRGR... BGBG...,
-RGRG... GBGB..., etc. Below is an example of one of these formats:
+RGRG... GBGB..., etc. Below is an example of a small V4L2_PIX_FMT_SBGGR8 image:
 
 **Byte Order.**
 Each cell is one byte.
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/selection-api-003_files/selection.png and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/selection-api-003_files/selection.png differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/selection-api-003.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/selection-api-003.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/selection-api-003.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/selection-api-003.rst	2017-02-12 16:03:20.000000000 -0500
@@ -7,8 +7,8 @@ Selection targets
 
 .. _sel-targets-capture:
 
-.. figure::  selection-api-003_files/selection.*
-    :alt:    selection.png
+.. figure::  selection.*
+    :alt:    selection.pdf / selection.svg
     :align:  center
 
     Cropping and composing targets
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/selection.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/selection.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/selection.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/selection.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,5812 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="4226.3345"
+   height="1686.8481"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="selection.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   version="1.0"
+   style="display:inline;enable-background:new"
+   inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_final.png"
+   inkscape:export-xdpi="100.03588"
+   inkscape:export-ydpi="100.03588">
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.32297491"
+     inkscape:cx="2113.1672"
+     inkscape:cy="843.42407"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer16"
+     showgrid="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     showguides="false"
+     inkscape:guide-bbox="true"
+     units="mm"
+     inkscape:window-maximized="1"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <defs
+     id="defs4">
+    <pattern
+       inkscape:collect="always"
+       xlink:href="#Strips1_1"
+       id="pattern5557"
+       patternTransform="matrix(5.4431804,0,0,10.10048,1808.3554,-48.222348)" />
+    <marker
+       inkscape:stockid="Arrow1Send"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Send"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         id="path7188"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.2,0,0,-0.2,-1.2,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <pattern
+       inkscape:isstock="true"
+       inkscape:stockid="Stripes 1:1"
+       id="Strips1_1"
+       patternTransform="translate(0,0) scale(10,10)"
+       height="1"
+       width="2"
+       patternUnits="userSpaceOnUse"
+       inkscape:collect="always">
+      <rect
+         id="rect5945"
+         height="2"
+         width="1"
+         y="-0.5"
+         x="0"
+         style="fill:#f815bb;stroke:none" />
+    </pattern>
+    <linearGradient
+       id="linearGradient10954"
+       osb:paint="solid">
+      <stop
+         style="stop-color:#d9f90b;stop-opacity:1;"
+         offset="0"
+         id="stop10956" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9165"
+       osb:paint="solid">
+      <stop
+         style="stop-color:#000000;stop-opacity:0.31330472;"
+         offset="0"
+         id="stop9167" />
+    </linearGradient>
+    <filter
+       inkscape:collect="always"
+       x="-0.084654994"
+       width="1.16931"
+       y="-0.36592469"
+       height="1.7318494"
+       id="filter11361">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="4.5740586"
+         id="feGaussianBlur11363" />
+    </filter>
+    <linearGradient
+       id="linearGradient7622">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop7624" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop7626" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4113">
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="0"
+         id="stop4115" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop4117" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3660">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3662" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3664" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3627">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3629" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop3631" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2843">
+      <stop
+         id="stop2845"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0.02188784"
+         id="stop2847" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0.75866222"
+         id="stop2849" />
+      <stop
+         id="stop2851"
+         offset="0.88508981"
+         style="stop-color:#232323;stop-opacity:1;" />
+      <stop
+         id="stop2853"
+         offset="1"
+         style="stop-color:#595959;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8964">
+      <stop
+         style="stop-color:#1a1a1a;stop-opacity:1;"
+         offset="0"
+         id="stop8966" />
+      <stop
+         style="stop-color:#1a1a1a;stop-opacity:0;"
+         offset="1"
+         id="stop8968" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient8952">
+      <stop
+         style="stop-color:#0a0c0c;stop-opacity:1;"
+         offset="0"
+         id="stop8954" />
+      <stop
+         style="stop-color:#1f2727;stop-opacity:0;"
+         offset="1"
+         id="stop8956" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient8430">
+      <stop
+         style="stop-color:#1e2323;stop-opacity:1;"
+         offset="0"
+         id="stop8432" />
+      <stop
+         id="stop8438"
+         offset="0.55992389"
+         style="stop-color:#181d1d;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop8434" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient8398">
+      <stop
+         style="stop-color:#283131;stop-opacity:0;"
+         offset="0"
+         id="stop8400" />
+      <stop
+         id="stop8402"
+         offset="0.5125587"
+         style="stop-color:#1e2424;stop-opacity:0;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop8404" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4870">
+      <stop
+         style="stop-color:#c7bd80;stop-opacity:1;"
+         offset="0"
+         id="stop4872" />
+      <stop
+         style="stop-color:#c7bd80;stop-opacity:0;"
+         offset="1"
+         id="stop4874" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4862">
+      <stop
+         style="stop-color:#e2e2e2;stop-opacity:1;"
+         offset="0"
+         id="stop4864" />
+      <stop
+         style="stop-color:#e2e2e2;stop-opacity:0;"
+         offset="1"
+         id="stop4866" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4478">
+      <stop
+         style="stop-color:#f9eed3;stop-opacity:1;"
+         offset="0"
+         id="stop4480" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4482" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4106">
+      <stop
+         style="stop-color:#d9e002;stop-opacity:1;"
+         offset="0"
+         id="stop4108" />
+      <stop
+         id="stop4114"
+         offset="0.5"
+         style="stop-color:#a9ae01;stop-opacity:1;" />
+      <stop
+         style="stop-color:#717501;stop-opacity:1;"
+         offset="1"
+         id="stop4110" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4084">
+      <stop
+         style="stop-color:#7d7d00;stop-opacity:1;"
+         offset="0"
+         id="stop4086" />
+      <stop
+         id="stop4088"
+         offset="0.3636601"
+         style="stop-color:#c6c700;stop-opacity:1;" />
+      <stop
+         style="stop-color:#f6f800;stop-opacity:1;"
+         offset="1"
+         id="stop4090" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4041">
+      <stop
+         id="stop4043"
+         offset="0"
+         style="stop-color:#ffff00;stop-opacity:1;" />
+      <stop
+         id="stop4045"
+         offset="1"
+         style="stop-color:#ffff00;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4025">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop4027" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop4031" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4013">
+      <stop
+         style="stop-color:#ffff00;stop-opacity:1;"
+         offset="0"
+         id="stop4015" />
+      <stop
+         style="stop-color:#b2b200;stop-opacity:1;"
+         offset="1"
+         id="stop4017" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3985">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop3987" />
+      <stop
+         style="stop-color:#1d1d1d;stop-opacity:1;"
+         offset="1"
+         id="stop3989" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3961">
+      <stop
+         style="stop-color:#283131;stop-opacity:0;"
+         offset="0"
+         id="stop3963" />
+      <stop
+         id="stop3965"
+         offset="0.5"
+         style="stop-color:#1e2424;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop3967" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3951">
+      <stop
+         id="stop3953"
+         offset="0"
+         style="stop-color:#344040;stop-opacity:1;" />
+      <stop
+         style="stop-color:#222929;stop-opacity:1;"
+         offset="0.5"
+         id="stop3955" />
+      <stop
+         id="stop3957"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:1;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3909">
+      <stop
+         style="stop-color:#283131;stop-opacity:1;"
+         offset="0"
+         id="stop3911" />
+      <stop
+         id="stop3917"
+         offset="0.5"
+         style="stop-color:#1e2424;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="1"
+         id="stop3913" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3537">
+      <stop
+         style="stop-color:#ada469;stop-opacity:1;"
+         offset="0"
+         id="stop3539" />
+      <stop
+         id="stop3545"
+         offset="0.81132078"
+         style="stop-color:#ada469;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="1"
+         id="stop3541" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3317">
+      <stop
+         style="stop-color:#cfc690;stop-opacity:1"
+         offset="0"
+         id="stop3319" />
+      <stop
+         id="stop3321"
+         offset="0.21161865"
+         style="stop-color:#afa775;stop-opacity:1;" />
+      <stop
+         id="stop3323"
+         offset="0.53408515"
+         style="stop-color:#615c3a;stop-opacity:1;" />
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0.76504093"
+         id="stop3325" />
+      <stop
+         id="stop3327"
+         offset="1"
+         style="stop-color:#403518;stop-opacity:1;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3317"
+       id="radialGradient3315"
+       cx="543.6698"
+       cy="147.3131"
+       fx="543.6698"
+       fy="147.3131"
+       r="47.863216"
+       gradientTransform="matrix(2.1382256,0,0,2.3382884,-77.03847,-101.68704)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3537"
+       id="radialGradient3543"
+       cx="385"
+       cy="237.00504"
+       fx="385"
+       fy="237.00504"
+       r="86.928574"
+       gradientTransform="matrix(1,0,0,0.8562038,0,34.080427)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3909"
+       id="radialGradient3915"
+       cx="418.30365"
+       cy="342.47794"
+       fx="418.30365"
+       fy="342.47794"
+       r="131.4509"
+       gradientTransform="matrix(1.3957347,0.6211056,-0.4244067,0.9537174,-15.061913,-227.96711)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3951"
+       id="radialGradient3933"
+       cx="397.16388"
+       cy="336.95245"
+       fx="397.16388"
+       fy="336.95245"
+       r="36.75"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.9449972,2.4894837e-7,-2.4894833e-7,1.9449969,-375.31868,-318.41912)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3961"
+       id="linearGradient3959"
+       x1="398.21429"
+       y1="343.52289"
+       x2="379.28571"
+       y2="265.30862"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)" />
+    <filter
+       inkscape:collect="always"
+       id="filter3981"
+       x="-0.30000001"
+       width="1.6"
+       y="-0.30000001"
+       height="1.6">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2"
+         id="feGaussianBlur3983" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3985"
+       id="radialGradient3991"
+       cx="402.48898"
+       cy="317.23578"
+       fx="402.48898"
+       fy="317.23578"
+       r="23.714285"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(4.3776616,0,0,4.3776616,-1358.3025,-1070.7357)" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3999">
+      <path
+         style="display:inline;opacity:1;fill:#f5ff04;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 12.61031,-67.04463 3.21429,-93.92857 -9.43424,-26.99328 -34.96741,-59.12448 -66.42857,-69.64285 -31.03327,-10.37532 -65.01776,-4.84837 -84.28571,5.71428 z"
+         id="path4001"
+         sodipodi:nodetypes="czzczzzzc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4013"
+       id="radialGradient4056"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+       cx="228.81355"
+       cy="440.26971"
+       fx="228.81355"
+       fy="440.26971"
+       r="119.17509" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4041"
+       id="radialGradient4060"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+       cx="275.4422"
+       cy="335.34866"
+       fx="275.4422"
+       fy="335.34866"
+       r="36.75" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4025"
+       id="radialGradient4062"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+       cx="275.4422"
+       cy="335.34866"
+       fx="275.4422"
+       fy="335.34866"
+       r="36.75" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4084"
+       id="linearGradient4082"
+       gradientUnits="userSpaceOnUse"
+       x1="182.35046"
+       y1="256.11136"
+       x2="145.53348"
+       y2="542.20502" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4100">
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9000755px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 265.93541,126.68393 -18.76721,168.86308 174.10543,-73.12068 61.9544,88.65883 57.8844,-31.9903 -37.53442,-180.059677 -237.6426,27.648747 z"
+         id="path4102"
+         sodipodi:nodetypes="ccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4106"
+       id="radialGradient4112"
+       cx="250.22678"
+       cy="475.09763"
+       fx="250.22678"
+       fy="475.09763"
+       r="95.98877"
+       gradientTransform="matrix(1.2259004,-0.7077739,0.1413989,0.2449102,322.22326,608.91815)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4484"
+       x1="412.08926"
+       y1="404.91574"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4486"
+       x1="411.91071"
+       y1="404.91577"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4488"
+       x1="411.91071"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4490"
+       x1="412.08926"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient4492"
+       x1="411.73212"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4862"
+       id="radialGradient4868"
+       cx="429.56738"
+       cy="377.42877"
+       fx="429.56738"
+       fy="377.42877"
+       r="72.079735"
+       gradientTransform="matrix(1,0,0,0.618034,0,144.16496)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4870"
+       id="radialGradient4876"
+       cx="437.6991"
+       cy="391.21735"
+       fx="437.6991"
+       fy="391.21735"
+       r="36.611931"
+       gradientTransform="matrix(1,0,0,0.618034,0,149.43174)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4013"
+       id="radialGradient3585"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+       cx="228.81355"
+       cy="440.26971"
+       fx="228.81355"
+       fy="440.26971"
+       r="119.17509" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4084"
+       id="linearGradient3587"
+       gradientUnits="userSpaceOnUse"
+       x1="182.35046"
+       y1="256.11136"
+       x2="145.53348"
+       y2="542.20502" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8514">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8516"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8604">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8606"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8610">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8612"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8616">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8618"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8622">
+      <path
+         style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 821.64329,477.88997 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+         id="path8624"
+         sodipodi:nodetypes="czzzzzzczczczczzzc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8642">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+         id="path8644"
+         sodipodi:nodetypes="czzcczcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8658">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0b0b0b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -99.77493,25.9619 -142.85715,35.7143 -43.08222,9.7524 -117.26443,34.816 -156.91262,27.2654 -39.64818,-7.5506 -89.51595,-64.4083 -89.51595,-64.4083 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+         id="path8660"
+         sodipodi:nodetypes="czzzcczzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8802"
+       x="-0.35311759"
+       width="1.7062352"
+       y="-0.1817714"
+       height="1.3635428">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="48.038491"
+         id="feGaussianBlur8804" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8806"
+       x="-0.61142862"
+       width="2.2228572"
+       y="-0.14930232"
+       height="1.2986046">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="37.830213"
+         id="feGaussianBlur8808" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8810"
+       x="-0.23519406"
+       width="1.4703881"
+       y="-0.24500646"
+       height="1.4900129">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="58.328041"
+         id="feGaussianBlur8812" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8814"
+       x="-0.20466694"
+       width="1.4093339"
+       y="-0.29007819"
+       height="1.5801564">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="22.300169"
+         id="feGaussianBlur8816" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8818"
+       x="-0.34381232"
+       width="1.6876246"
+       y="-0.18433961"
+       height="1.3686792">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="34.542167"
+         id="feGaussianBlur8820" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8822"
+       x="-0.2742857"
+       width="1.5485713"
+       y="-0.21333334"
+       height="1.4266667">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="11.313708"
+         id="feGaussianBlur8824" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8826"
+       x="-0.25894088"
+       width="1.5178818"
+       y="-0.2236412"
+       height="1.4472824">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.631544"
+         id="feGaussianBlur8828" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8856"
+       x="-0.3253231"
+       width="1.6506462"
+       y="-0.19013336"
+       height="1.3802667">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="28.712591"
+         id="feGaussianBlur8858" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8860"
+       x="-0.38093024"
+       width="1.7618605"
+       y="-0.17518716"
+       height="1.3503743">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.304015"
+         id="feGaussianBlur8862" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8888"
+       x="-0.2112188"
+       width="1.4224375"
+       y="-0.16808605"
+       height="1.3361721">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="8.3693583"
+         id="feGaussianBlur8890" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8892"
+       x="-0.18692794"
+       width="1.3738559"
+       y="-0.23646873"
+       height="1.4729375">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="31.21228"
+         id="feGaussianBlur8894" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8906">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8908"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8940"
+       x="-0.25152978"
+       width="1.5030596"
+       y="-0.053035267"
+       height="1.1060705">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="13.024603"
+         id="feGaussianBlur8942" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8952"
+       id="linearGradient8958"
+       x1="609.31244"
+       y1="239.46866"
+       x2="560.83142"
+       y2="262.86206"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8964"
+       id="linearGradient8970"
+       x1="603.84064"
+       y1="627.85303"
+       x2="616.24396"
+       y2="585.42664"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)" />
+    <filter
+       inkscape:collect="always"
+       id="filter9020"
+       x="-0.32861114"
+       width="1.6572223"
+       y="-0.182"
+       height="1.364">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="20.912684"
+         id="feGaussianBlur9022" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9024"
+       x="-0.55453134"
+       width="2.1090627"
+       y="-0.51434779"
+       height="2.0286956">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="20.912684"
+         id="feGaussianBlur9026" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9044"
+       x="-0.32631579"
+       width="1.6526316"
+       y="-0.84545463"
+       height="2.6909094">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="21.92031"
+         id="feGaussianBlur9046" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9048"
+       x="-0.40879121"
+       width="1.8175824"
+       y="-0.71538466"
+       height="2.4307692">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="21.92031"
+         id="feGaussianBlur9050" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter3587"
+       x="-0.1">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="8.881432"
+         id="feGaussianBlur3589" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3602">
+      <path
+         sodipodi:nodetypes="czzzzzzczczczczzzc"
+         id="path3604"
+         d="m 647.61204,540.04601 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+         style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4120"
+       x="-0.2770822"
+       width="1.5541644"
+       y="-0.32482043"
+       height="1.6496409">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.956289"
+         id="feGaussianBlur4122" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3631">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         id="path3633"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3665">
+      <path
+         sodipodi:nodetypes="czzcczcc"
+         id="path3667"
+         d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3677">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         id="path3679"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter3898">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.892985"
+         id="feGaussianBlur3900" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4130"
+       x="-0.49509686"
+       width="1.9901937"
+       y="-0.26708817"
+       height="1.5341763">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.730622"
+         id="feGaussianBlur4132" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4141"
+       x="-0.40611032"
+       width="1.8122206"
+       y="-0.30260596"
+       height="1.6052119">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="9.8586086"
+         id="feGaussianBlur4143" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4177">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path4179"
+         d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4185">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="3.6164709"
+         id="feGaussianBlur4187" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4105">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="3.8640966"
+         id="feGaussianBlur4107" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath2833">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#292929;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+         id="path2835"
+         sodipodi:nodetypes="czzzcczzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2843"
+       id="linearGradient2841"
+       gradientUnits="userSpaceOnUse"
+       x1="347.89655"
+       y1="1070.2124"
+       x2="275.58191"
+       y2="867.97992" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3627"
+       id="linearGradient3688"
+       gradientUnits="userSpaceOnUse"
+       x1="699.32867"
+       y1="269.76755"
+       x2="698.97504"
+       y2="346.1351" />
+    <mask
+       maskUnits="userSpaceOnUse"
+       id="mask3684">
+      <ellipse
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient3688);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.43724918px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         id="path3686"
+         transform="translate(-174.03125,62.156036)"
+         cx="579.474"
+         cy="260.57516"
+         rx="192.6866"
+         ry="164.04877" />
+    </mask>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3622">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 266.27183,924.57186 c -1.40727,18.80121 -1.1449,32.75103 2.08174,49.30328 3.22665,16.55234 16.40608,45.90736 20.3344,63.18376 3.92622,17.2671 2.69413,38.3096 -12.45944,51.1482 -15.31761,12.9774 -42.05127,21.5989 -67.8323,15.7338 -25.78106,-5.8653 -69.54907,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045183,939.86194 41.867508,909.43681 27.689836,879.01169 29.207903,872.71824 33.747793,863.90708 24.381071,839.38658 21.334081,813.84027 0.03533552,788.33044 30.360815,791.44488 43.915625,815.28677 60.161025,835.47019 54.631129,787.39416 42.10631,771.05369 31.787073,744.74589 c 29.994295,6.08166 50.57936,31.8724 63.979783,72.7125 9.554154,-3.91791 18.237764,-9.37294 30.187414,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.687255,-101.06994 53.441965,5.67033 83.657025,80.63932 78.971425,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24896,-38.34702 -21.04781,-76.8679 -3.65971,-118.64818 0,0 48.28678,65.43687 54.38966,85.80577 6.10287,20.36891 1.51881,38.70052 1.51881,38.70052 0,0 16.95957,31.08529 20.29392,51.09413 3.3731,20.24135 -3.53269,59.10332 -4.94582,77.98324 z"
+         id="path3624"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3636">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         id="path3638"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3660"
+       id="linearGradient3666"
+       x1="1255.7386"
+       y1="667.09216"
+       x2="893.69995"
+       y2="858.01099"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       inkscape:collect="always"
+       id="filter3779"
+       x="-0.087980822"
+       width="1.1759616"
+       y="-0.17728332"
+       height="1.3545666">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="16.340344"
+         id="feGaussianBlur3781" />
+    </filter>
+    <filter
+       id="filter3785"
+       inkscape:label="White Fur">
+      <feTurbulence
+         id="feTurbulence3787"
+         type="fractalNoise"
+         baseFrequency="0.24044943820224721"
+         numOctaves="10"
+         seed="655"
+         result="result0" />
+      <feDisplacementMap
+         id="feDisplacementMap3789"
+         in="SourceGraphic"
+         in2="result0"
+         scale="62"
+         xChannelSelector="B"
+         yChannelSelector="G" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter3677">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.0397518"
+         id="feGaussianBlur3679" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3722">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+         id="path3724"
+         sodipodi:nodetypes="czzzzzzzzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3986">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+         id="path3988"
+         sodipodi:nodetypes="czzzzzzzzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3992">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+         id="path3994"
+         sodipodi:nodetypes="czzzzzzzzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3998">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 178.21428,274.14789 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401287 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.3574 -122.78647,50.053 -187.06988,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path4000"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4002"
+       x="-0.24334238"
+       width="1.4866848"
+       y="-0.39104807"
+       height="1.7820961">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="14.589518"
+         id="feGaussianBlur4004" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4010"
+       x="-0.14577261"
+       width="1.2915452"
+       y="-0.23523259"
+       height="1.4704652">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="4.4442907"
+         id="feGaussianBlur4012" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4053">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.6062947"
+         id="feGaussianBlur4055" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4079">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="6.5887624"
+         id="feGaussianBlur4081" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4083">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.5052066"
+         id="feGaussianBlur4085" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4113"
+       id="radialGradient4119"
+       cx="296.33783"
+       cy="427.17749"
+       fx="296.33783"
+       fy="427.17749"
+       r="19.704132"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.9797125,0,0,2.9797125,-599.28727,-827.0855)" />
+    <filter
+       inkscape:collect="always"
+       id="filter6949"
+       x="-0.10294895"
+       width="1.2058979"
+       y="-0.34224695"
+       height="1.6844939">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6951" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6953"
+       x="-0.098320946"
+       width="1.1966419"
+       y="-0.19750816"
+       height="1.3950163">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6955" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6957"
+       x="-0.098213427"
+       width="1.1964267"
+       y="-0.19838208"
+       height="1.3967642">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6959" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6961"
+       x="-0.09919104"
+       width="1.1983821"
+       y="-0.22643611"
+       height="1.4528722">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6963" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6965"
+       x="-0.099081434"
+       width="1.1981629"
+       y="-0.22529824"
+       height="1.4505965">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6967" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6969"
+       x="-0.10450897"
+       width="1.2090179"
+       y="-0.40468886"
+       height="1.8093777">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6971" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6973"
+       x="-0.10330495"
+       width="1.2066098"
+       y="-0.36439717"
+       height="1.7287945">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6975" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6977"
+       x="-0.10224481"
+       width="1.2044896"
+       y="-0.32371372"
+       height="1.6474274">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6979" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6981"
+       x="-0.10052545"
+       width="1.2010509"
+       y="-0.2742162"
+       height="1.5484324">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6983" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6985"
+       x="-0.098428868"
+       width="1.1968577"
+       y="-0.20853186"
+       height="1.4170637">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6987" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6989"
+       x="-0.098428868"
+       width="1.1968577"
+       y="-0.20287035"
+       height="1.4057407">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6991" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6993"
+       x="-0.098213255"
+       width="1.1964265"
+       y="-0.19838208"
+       height="1.3967642">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6995" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6997">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6999" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7001">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur7003" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7285"
+       x="-0.030884685"
+       width="1.0617694"
+       y="-0.10267408"
+       height="1.2053483">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7287" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7289">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7291" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7293">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7295" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7297">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7299" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7301">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7303" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7305">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7307" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7309">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7311" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7313">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7315" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7317">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7319" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7321">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7323" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7325"
+       x="-0.031352691"
+       width="1.0627054"
+       y="-0.12140666"
+       height="1.2428133">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7327" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7329"
+       x="-0.030991485"
+       width="1.061983"
+       y="-0.10931916"
+       height="1.2186383">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7331" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7333">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7335" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7337">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7339" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7345">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.7233839"
+         id="feGaussianBlur7347" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7421">
+      <path
+         sodipodi:type="inkscape:offset"
+         inkscape:radius="0"
+         inkscape:original="M 1111.4062 -285.9375 L 1107.4688 -284.0625 C 1107.4283 -284.05228 1107.3692 -284.04201 1107.3438 -284.03125 C 1106.925 -283.8184 1107.1791 -283.93067 1106.6875 -283.71875 C 1106.2014 -283.50919 1104.9499 -283.13456 1102.5938 -282.25 C 1099.2626 -280.99942 1096.7895 -280.10016 1095.5938 -279.1875 C 1094.0576 -279.16623 1091.8733 -278.95419 1089.9375 -278.46875 C 1086.956 -277.72108 1085.0823 -277.29474 1083.1875 -276.875 C 1081.2927 -276.45527 1081.512 -276.23281 1080.3125 -276 C 1079.0159 -275.74833 1078.5911 -276.00899 1074.875 -275.21875 C 1071.3851 -274.4766 1065.9802 -273.28768 1064.7188 -272.53125 C 1063.1348 -272.71203 1060.8513 -272.85303 1058.875 -272.5625 C 1055.8346 -272.11554 1053.9588 -271.88974 1052.0312 -271.65625 C 1051.3758 -271.57687 1050.9902 -271.45547 1050.6875 -271.375 C 1050.2613 -271.24334 1050.0017 -271.11498 1049.3125 -271.03125 C 1048.0009 -270.87188 1047.5503 -271.18808 1043.7812 -270.75 C 1040.2273 -270.33691 1034.7758 -269.47718 1033.5312 -268.8125 C 1031.9322 -269.10979 1029.6735 -269.34669 1027.6875 -269.15625 C 1024.6287 -268.86293 1022.7155 -268.67226 1020.7812 -268.5 C 1018.847 -268.32773 1019.0926 -268.07763 1017.875 -267.96875 C 1016.5588 -267.85105 1016.1152 -268.13238 1012.3438 -267.71875 C 1008.8017 -267.3303 1003.3359 -266.50948 1002.0625 -265.84375 C 1000.4636 -266.13844 998.1753 -266.35076 996.1875 -266.15625 C 993.12921 -265.857 991.2463 -265.67601 989.3125 -265.5 C 988.65501 -265.44015 988.27245 -265.32144 987.96875 -265.25 C 987.54105 -265.13104 987.28525 -265.03193 986.59375 -264.96875 C 985.27775 -264.84849 984.834 -265.16363 981.0625 -264.75 C 977.50631 -264.35998 972.0569 -263.51084 970.8125 -262.84375 C 969.21381 -263.13793 966.95265 -263.36747 964.96875 -263.15625 C 961.91305 -262.83092 959.9947 -262.63001 958.0625 -262.4375 C 956.13031 -262.24499 956.37275 -261.99662 955.15625 -261.875 C 953.84137 -261.74353 953.3932 -262.03954 949.625 -261.59375 C 946.08611 -261.17509 940.6473 -260.30158 939.375 -259.625 C 937.77741 -259.90604 935.51505 -260.04543 933.53125 -259.8125 C 930.47927 -259.45413 928.58625 -259.24464 926.65625 -259.03125 C 926.00007 -258.95869 925.6156 -258.85856 925.3125 -258.78125 C 924.88571 -258.65402 924.6276 -258.51405 923.9375 -258.4375 C 922.62411 -258.29181 922.17015 -258.61152 918.40625 -258.125 C 914.85737 -257.66624 909.4276 -256.70598 908.1875 -256 C 906.59441 -256.24424 904.3537 -256.38135 902.375 -256.125 C 899.32741 -255.73018 897.4243 -255.47655 895.5 -255.21875 C 893.57571 -254.96096 893.7739 -254.72522 892.5625 -254.5625 C 891.25301 -254.3866 890.8153 -254.66688 887.0625 -254.09375 C 883.53821 -253.55551 878.1393 -252.39458 876.875 -251.65625 C 875.28751 -251.85979 873.0295 -251.91098 871.0625 -251.5625 C 868.03631 -251.02638 866.1636 -250.70081 864.25 -250.375 C 863.59941 -250.26423 863.2363 -250.10406 862.9375 -250 C 862.51681 -249.83512 862.27405 -249.6687 861.59375 -249.53125 C 860.29905 -249.26966 859.86665 -249.53745 856.15625 -248.71875 C 852.65777 -247.9468 847.31035 -246.33582 846.09375 -245.5 C 844.53085 -245.57745 842.33625 -245.41472 840.40625 -244.90625 C 837.43387 -244.12312 835.58855 -243.67416 833.71875 -243.15625 C 831.84875 -242.63835 832.0521 -242.38897 830.875 -242.0625 C 829.60251 -241.7096 829.17795 -241.95541 825.53125 -240.875 C 822.10657 -239.86037 816.88185 -237.94183 815.65625 -237.03125 C 814.11747 -237.01851 811.93645 -236.75903 810.03125 -236.15625 C 807.10027 -235.22891 805.2809 -234.69783 803.4375 -234.09375 C 802.81071 -233.88837 802.44585 -233.70117 802.15625 -233.5625 C 801.74867 -233.34889 801.50295 -233.15375 800.84375 -232.9375 C 799.58925 -232.52596 799.1576 -232.74846 795.5625 -231.5 C 792.17261 -230.32283 786.96755 -228.2863 785.78125 -227.34375 C 784.25737 -227.28408 782.1312 -226.94888 780.25 -226.28125 C 777.35261 -225.25296 775.55095 -224.60577 773.71875 -223.96875 C 771.88655 -223.33174 772.0909 -223.12021 770.9375 -222.71875 C 769.69071 -222.28479 769.27395 -222.51903 765.71875 -221.15625 C 762.38005 -219.87645 757.23165 -217.6737 756.03125 -216.6875 C 754.52407 -216.57981 752.39555 -216.1887 750.53125 -215.46875 C 747.66307 -214.36115 745.90735 -213.68719 744.09375 -213 C 743.47705 -212.76637 743.0973 -212.55797 742.8125 -212.40625 C 742.81251 -212.40625 742.8125 -212.37673 742.8125 -212.375 L 734.8125 -209.1875 L 736.625 -194.46875 C 736.36701 -194.52956 742.8125 -191.15625 742.8125 -191.15625 C 743.03891 -191.30093 743.26145 -191.42886 743.53125 -191.53125 C 744.61177 -191.94123 745.70285 -191.74702 749.53125 -193.21875 C 753.35977 -194.69049 754.7553 -195.22373 755.4375 -195.625 C 756.11711 -196.02478 757.04925 -196.50437 757.65625 -197.15625 C 759.48317 -197.294 761.22705 -197.64948 762.59375 -198.15625 C 765.56175 -199.25677 767.4691 -199.96244 769.375 -200.625 C 771.28081 -201.28754 771.72915 -202.03987 772.78125 -202.40625 C 773.87287 -202.78636 774.97635 -202.57163 778.84375 -203.9375 C 782.71115 -205.30336 784.1269 -205.76458 784.8125 -206.15625 C 785.51361 -206.55677 786.5133 -207.08923 787.125 -207.75 C 789.09581 -207.80466 790.94195 -208.13463 792.40625 -208.625 C 795.40777 -209.63008 797.3324 -210.24671 799.25 -210.875 C 800.78861 -211.3791 801.42415 -211.92177 802.15625 -212.3125 C 802.38647 -212.44681 802.63215 -212.56623 802.90625 -212.65625 C 804.00457 -213.01673 805.0877 -212.73762 809 -213.96875 C 812.91231 -215.19988 814.366 -215.6417 815.0625 -216 C 815.75641 -216.35697 816.6926 -216.79261 817.3125 -217.40625 C 819.17771 -217.42891 820.94835 -217.67308 822.34375 -218.09375 C 825.37415 -219.00729 827.33615 -219.52385 829.28125 -220.0625 C 831.22637 -220.60114 831.70745 -221.32702 832.78125 -221.625 C 833.89527 -221.93415 835.00125 -221.61761 838.96875 -222.65625 C 842.93625 -223.69488 844.38625 -224.08898 845.09375 -224.40625 C 845.82855 -224.73584 846.90765 -225.15997 847.53125 -225.78125 C 849.52907 -225.66525 851.3887 -225.80134 852.875 -226.15625 C 855.95311 -226.89125 857.9584 -227.25719 859.9375 -227.65625 C 861.52541 -227.97643 862.1818 -228.4468 862.9375 -228.75 C 863.17501 -228.8568 863.4044 -228.94276 863.6875 -229 C 864.82091 -229.22919 865.99215 -228.79107 870.03125 -229.5 C 874.07067 -230.20893 875.5315 -230.42709 876.25 -230.6875 C 876.96581 -230.94694 877.95435 -231.25474 878.59375 -231.78125 C 880.51795 -231.54176 882.34165 -231.55672 883.78125 -231.78125 C 886.90767 -232.26887 888.9358 -232.48192 890.9375 -232.75 C 892.93921 -233.01807 893.42625 -233.69514 894.53125 -233.84375 C 895.67767 -233.99793 896.8071 -233.54218 900.875 -234.0625 C 904.94281 -234.58282 906.43525 -234.75823 907.15625 -235 C 907.89337 -235.24714 908.95435 -235.58623 909.59375 -236.125 C 911.64375 -235.78947 913.56745 -235.72704 915.09375 -235.90625 C 918.23595 -236.27521 920.27375 -236.46561 922.28125 -236.6875 C 923.89207 -236.86552 924.5459 -237.2957 925.3125 -237.53125 C 925.55341 -237.61677 925.80655 -237.68685 926.09375 -237.71875 C 927.24345 -237.84647 928.39505 -237.3721 932.46875 -237.84375 C 936.54245 -238.3154 938.0278 -238.45435 938.75 -238.6875 C 939.46941 -238.91977 940.45025 -239.16096 941.09375 -239.65625 C 943.03005 -239.32279 944.8638 -239.25201 946.3125 -239.40625 C 949.45851 -239.7412 951.49 -239.92484 953.5 -240.125 C 955.50991 -240.32514 955.98415 -240.95139 957.09375 -241.0625 C 958.24485 -241.17778 959.39025 -240.69744 963.46875 -241.125 C 967.54725 -241.55256 969.05765 -241.68709 969.78125 -241.90625 C 970.52047 -242.13011 971.57685 -242.4195 972.21875 -242.9375 C 974.27575 -242.53883 976.2206 -242.4441 977.75 -242.59375 C 980.89871 -242.90185 982.9258 -243.067 984.9375 -243.25 C 986.55151 -243.39682 987.20055 -243.81055 987.96875 -244.03125 C 988.21005 -244.11211 988.4623 -244.16116 988.75 -244.1875 C 989.90211 -244.29295 991.0429 -243.79475 995.125 -244.1875 C 999.20711 -244.58025 1000.7139 -244.71834 1001.4375 -244.9375 C 1002.1584 -245.15583 1003.1371 -245.3852 1003.7812 -245.875 C 1005.7193 -245.52501 1007.5501 -245.42062 1009 -245.5625 C 1012.1487 -245.8706 1014.1758 -246.03575 1016.1875 -246.21875 C 1018.1991 -246.40174 1018.7017 -247.05677 1019.8125 -247.15625 C 1020.9648 -247.25948 1022.1047 -246.77142 1026.1875 -247.15625 C 1030.2704 -247.54107 1031.7762 -247.65725 1032.5 -247.875 C 1033.2393 -248.09743 1034.2956 -248.38949 1034.9375 -248.90625 C 1036.9949 -248.50448 1038.9404 -248.40292 1040.4688 -248.5625 C 1043.6153 -248.89102 1045.6458 -249.0852 1047.6562 -249.28125 C 1049.2692 -249.43854 1049.9219 -249.91273 1050.6875 -250.15625 C 1050.9282 -250.24429 1051.1507 -250.27762 1051.4375 -250.3125 C 1052.5858 -250.4522 1053.7542 -249.97259 1057.8125 -250.5625 C 1061.8708 -251.15242 1063.3743 -251.33964 1064.0938 -251.59375 C 1064.8104 -251.84691 1065.7684 -252.15182 1066.4062 -252.6875 C 1068.3259 -252.47556 1070.1262 -252.53609 1071.5625 -252.78125 C 1074.6816 -253.31365 1076.6741 -253.70986 1078.6562 -254.09375 C 1080.6383 -254.47762 1081.1305 -255.1334 1082.2188 -255.375 C 1083.3475 -255.62566 1084.489 -255.25871 1088.4688 -256.25 C 1092.4483 -257.24127 1093.8983 -257.6693 1094.5938 -258.03125 C 1095.316 -258.40725 1096.3555 -258.90183 1096.9688 -259.5625 C 1098.9317 -259.57454 1100.7625 -259.85355 1102.1875 -260.40625 C 1105.1387 -261.55085 1107.0607 -262.27567 1108.875 -263.15625 C 1110.3307 -263.86277 1111.1941 -264.85828 1111.4062 -265.15625 C 1111.6185 -265.4542 1111.5051 -265.8848 1111.5312 -265.90625 C 1111.5742 -265.94148 1111.8716 -266.00028 1112.0312 -266.34375 C 1112.8902 -268.19082 1114.3544 -271.97139 1114.4688 -272.65625 C 1114.5825 -273.33839 1114.6368 -274.00902 1114.6875 -274.40625 C 1114.7169 -274.63575 1114.5404 -275.28515 1114.5625 -275.34375 C 1114.5934 -275.42579 1114.8508 -275.59432 1114.9062 -275.84375 C 1115.1725 -277.04206 1114.9953 -278.05111 1114.7812 -279.46875 C 1114.5673 -280.88638 1113.8096 -284.08338 1113.1562 -284.9375 C 1112.4973 -285.79922 1111.9314 -285.94801 1111.4062 -285.9375 z "
+         style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         id="path7423"
+         d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 1.8125,14.71875 c -0.25799,-0.0608 6.1875,3.3125 6.1875,3.3125 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+         transform="translate(0.08004571,-0.03125)" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter7578"
+       x="-0.08160872"
+       width="1.1632174"
+       y="-0.22659944"
+       height="1.4531989">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.437399"
+         id="feGaussianBlur7580" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7594"
+       x="-0.040804356"
+       width="1.0816087"
+       y="-0.11329972"
+       height="1.2265995">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.2186995"
+         id="feGaussianBlur7596" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7606">
+      <path
+         id="path7608"
+         d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+         style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter7610"
+       x="-0.021942979"
+       width="1.0438859"
+       y="-0.10017137"
+       height="1.2003427">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.57530213"
+         id="feGaussianBlur7612" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7616">
+      <path
+         id="path7618"
+         d="m 205.47016,-408.97318 -0.0901,0.002 c -1.44563,0.78566 -6.69921,1.14335 -7.27625,9.03857 -0.54134,7.40553 13.78595,18.09566 15.85433,19.24481 1.66964,0.92764 3.48475,1.65551 5.27345,2.09115 l 1.41867,0.31834 c 1.90027,0.34514 3.70042,0.41015 5.15031,0.26563 3.1486,-0.31384 5.16386,-0.57031 7.16789,-0.8152 2.00402,-0.24488 2.5407,-0.86478 3.64319,-1.02999 1.14342,-0.17143 2.25659,0.27414 6.29577,-0.43753 4.03888,-0.71169 5.51507,-1.03768 6.23419,-1.3503 0.74664,-0.32479 1.81806,-0.74575 2.47589,-1.3621 1.95897,0.12471 3.80476,-0.0261 5.2648,-0.47819 3.02376,-0.93627 4.99157,-1.52544 6.8628,-2.27751 1.50138,-0.60342 2.43202,-1.53636 2.66436,-1.81883 0.23254,-0.28245 0.14951,-0.71989 0.17694,-0.73948 0.0453,-0.0322 0.34622,-0.0701 0.52926,-0.40161 0.98557,-1.78276 2.70955,-5.45215 2.87137,-6.12738 0.16094,-0.67257 0.26182,-1.33778 0.34007,-1.73051 0.0453,-0.22691 -0.0855,-0.88701 -0.0594,-0.94393 0.0365,-0.0797 0.30505,-0.22988 0.37769,-0.47485 0.34913,-1.17686 0.24274,-2.19578 0.1278,-3.6249 -0.11463,-1.42909 -0.64781,-4.6711 -1.24013,-5.56865 -0.38017,-0.57646 -0.74215,-0.84625 -1.09026,-0.98459 -0.0657,-0.0219 -0.12035,-0.0553 -0.1827,-0.0754 -0.0207,-0.005 -0.0418,2.3e-4 -0.0623,-0.004 -0.30559,-0.097 -0.59597,-0.20067 -1.13816,-0.29875 -0.97557,-0.1765 -2.40074,-0.42766 -3.94175,-0.52584 -0.51366,-0.0327 -1.0379,-0.0247 -1.56523,-0.0153 -3.57201,0.0636 -9.05695,0.3611 -10.30707,0.90928 -1.60587,-0.44697 -3.89597,-0.88576 -5.89053,-0.8812 -3.07195,0.007 -4.97947,-0.005 -6.92207,-0.0134 -1.94251,-0.009 -1.70908,0.27025 -2.9318,0.26518 -1.32192,-0.005 -1.76701,-0.34717 -5.55562,-0.29393 -3.55782,0.05 -9.02796,0.36522 -10.30706,0.90927 -1.60614,-0.44747 -3.89367,-0.88575 -5.89043,-0.88118 -3.07215,0.007 -4.98175,0.0265 -6.92426,0.0177 -0.66059,-0.003 -1.0485,0.051 -1.35359,0.0934 z"
+         style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7622"
+       id="linearGradient7708"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-19.091883,4.2426407)"
+       x1="774.97668"
+       y1="-211.87105"
+       x2="755.11584"
+       y2="-202.67865" />
+    <mask
+       maskUnits="userSpaceOnUse"
+       id="mask7704">
+      <path
+         style="fill:url(#linearGradient7708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 718.40812,-224.31217 33.25,56 275.99998,-24 159.5,-48.25 -66.5,-82.75 -402.24998,99 z"
+         id="path7706"
+         inkscape:connector-curvature="0" />
+    </mask>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8430"
+       id="radialGradient7904"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.3324832,0.9022288,-0.9582407,-0.3531242,305.29227,19.909497)"
+       cx="142.95833"
+       cy="107.09234"
+       fx="142.95833"
+       fy="107.09234"
+       r="66.981766" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3317"
+       id="radialGradient7906"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-160.53487,-96.205369)"
+       cx="317.78754"
+       cy="129.65378"
+       fx="317.78754"
+       fy="129.65378"
+       r="47.863216" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8398"
+       id="radialGradient7908"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-550.77432,-65.728909)"
+       cx="325.30847"
+       cy="80.909554"
+       fx="325.30847"
+       fy="80.909554"
+       r="26.937988" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8209">
+      <path
+         sodipodi:nodetypes="czcc"
+         id="path8211"
+         d="m 734.03125,519.49186 c 0,0 16.75513,37.01806 28.70141,53.95395 11.94629,16.93589 52.72716,56.04605 52.72716,56.04605 l 0.59717,-138.58975"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8225">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.661912"
+         id="feGaussianBlur8227" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8333">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="7.18"
+         id="feGaussianBlur8335" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8338">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8340"
+         d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8354">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="6.82"
+         id="feGaussianBlur8356" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8359">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8361"
+         d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8379"
+       x="-0.14413793"
+       width="1.288276"
+       y="-0.10278689"
+       height="1.2055738">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="7.389266"
+         id="feGaussianBlur8381" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8392">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8394"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8404"
+       x="-0.090268657"
+       width="1.1805373"
+       y="-0.10250848"
+       height="1.205017">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="5.3457272"
+         id="feGaussianBlur8406" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8417">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8419"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       x="-0.084654994"
+       width="1.16931"
+       y="-0.36592469"
+       height="1.7318494"
+       id="filter11361-3">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="4.5740586"
+         id="feGaussianBlur11363-6" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8430"
+       id="radialGradient7904-7"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.3324832,0.9022288,-0.9582407,-0.3531242,305.29227,19.909497)"
+       cx="142.95833"
+       cy="107.09234"
+       fx="142.95833"
+       fy="107.09234"
+       r="66.981766" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3317"
+       id="radialGradient7906-6"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.0036478,-1.0345492e-7,1.7124628e-7,1.6613125,-160.53487,-96.205369)"
+       cx="317.78754"
+       cy="129.65378"
+       fx="317.78754"
+       fy="129.65378"
+       r="47.863216" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8398"
+       id="radialGradient7908-0"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.0747661,-0.1577957,0.2382425,3.1325183,-550.77432,-65.728909)"
+       cx="325.30847"
+       cy="80.909554"
+       fx="325.30847"
+       fy="80.909554"
+       r="26.937988" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8658-06">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0b0b0b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -99.77493,25.9619 -142.85715,35.7143 -43.08222,9.7524 -117.26443,34.816 -156.91262,27.2654 -39.64818,-7.5506 -89.51595,-64.4083 -89.51595,-64.4083 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+         id="path8660-2"
+         sodipodi:nodetypes="czzzcczzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8888-6"
+       x="-0.2112188"
+       width="1.4224375"
+       y="-0.16808605"
+       height="1.3361721">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="8.3693583"
+         id="feGaussianBlur8890-1" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath2833-2">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#292929;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 569.03125,1018.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.28571 c 0,0 85.88551,-16.20094 112.14285,-33.57143 26.25735,-17.37049 45.58238,-49.66598 59.28572,-71.42857 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+         id="path2835-3"
+         sodipodi:nodetypes="czzzcczzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8892-7"
+       x="-0.18692794"
+       width="1.3738559"
+       y="-0.23646873"
+       height="1.4729375">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="31.21228"
+         id="feGaussianBlur8894-5" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3665-9">
+      <path
+         sodipodi:nodetypes="czzcczcc"
+         id="path3667-2"
+         d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8856-2"
+       x="-0.3253231"
+       width="1.6506462"
+       y="-0.19013336"
+       height="1.3802667">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="28.712591"
+         id="feGaussianBlur8858-8" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8642-9">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 366.88839,504.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57144 -62.5,123.57144 l 76.07143,18.21428 c 0,0 11.80712,-12.82335 31.07142,-46.07143 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+         id="path8644-7"
+         sodipodi:nodetypes="czzcczcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8860-3"
+       x="-0.38093024"
+       width="1.7618605"
+       y="-0.17518716"
+       height="1.3503743">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.304015"
+         id="feGaussianBlur8862-6" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7616-1">
+      <path
+         id="path7618-2"
+         d="m 205.47016,-408.97318 -0.0901,0.002 c -1.44563,0.78566 -6.69921,1.14335 -7.27625,9.03857 -0.54134,7.40553 13.78595,18.09566 15.85433,19.24481 1.66964,0.92764 3.48475,1.65551 5.27345,2.09115 l 1.41867,0.31834 c 1.90027,0.34514 3.70042,0.41015 5.15031,0.26563 3.1486,-0.31384 5.16386,-0.57031 7.16789,-0.8152 2.00402,-0.24488 2.5407,-0.86478 3.64319,-1.02999 1.14342,-0.17143 2.25659,0.27414 6.29577,-0.43753 4.03888,-0.71169 5.51507,-1.03768 6.23419,-1.3503 0.74664,-0.32479 1.81806,-0.74575 2.47589,-1.3621 1.95897,0.12471 3.80476,-0.0261 5.2648,-0.47819 3.02376,-0.93627 4.99157,-1.52544 6.8628,-2.27751 1.50138,-0.60342 2.43202,-1.53636 2.66436,-1.81883 0.23254,-0.28245 0.14951,-0.71989 0.17694,-0.73948 0.0453,-0.0322 0.34622,-0.0701 0.52926,-0.40161 0.98557,-1.78276 2.70955,-5.45215 2.87137,-6.12738 0.16094,-0.67257 0.26182,-1.33778 0.34007,-1.73051 0.0453,-0.22691 -0.0855,-0.88701 -0.0594,-0.94393 0.0365,-0.0797 0.30505,-0.22988 0.37769,-0.47485 0.34913,-1.17686 0.24274,-2.19578 0.1278,-3.6249 -0.11463,-1.42909 -0.64781,-4.6711 -1.24013,-5.56865 -0.38017,-0.57646 -0.74215,-0.84625 -1.09026,-0.98459 -0.0657,-0.0219 -0.12035,-0.0553 -0.1827,-0.0754 -0.0207,-0.005 -0.0418,2.3e-4 -0.0623,-0.004 -0.30559,-0.097 -0.59597,-0.20067 -1.13816,-0.29875 -0.97557,-0.1765 -2.40074,-0.42766 -3.94175,-0.52584 -0.51366,-0.0327 -1.0379,-0.0247 -1.56523,-0.0153 -3.57201,0.0636 -9.05695,0.3611 -10.30707,0.90928 -1.60587,-0.44697 -3.89597,-0.88576 -5.89053,-0.8812 -3.07195,0.007 -4.97947,-0.005 -6.92207,-0.0134 -1.94251,-0.009 -1.70908,0.27025 -2.9318,0.26518 -1.32192,-0.005 -1.76701,-0.34717 -5.55562,-0.29393 -3.55782,0.05 -9.02796,0.36522 -10.30706,0.90927 -1.60614,-0.44747 -3.89367,-0.88575 -5.89043,-0.88118 -3.07215,0.007 -4.98175,0.0265 -6.92426,0.0177 -0.66059,-0.003 -1.0485,0.051 -1.35359,0.0934 z"
+         style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter7610-9"
+       x="-0.021942979"
+       width="1.0438859"
+       y="-0.10017137"
+       height="1.2003427">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.57530213"
+         id="feGaussianBlur7612-3" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7606-1">
+      <path
+         id="path7608-9"
+         d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+         style="display:inline;opacity:0.82448976;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter7578-4"
+       x="-0.08160872"
+       width="1.1632174"
+       y="-0.22659944"
+       height="1.4531989">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.437399"
+         id="feGaussianBlur7580-7" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7594-8"
+       x="-0.040804356"
+       width="1.0816087"
+       y="-0.11329972"
+       height="1.2265995">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.2186995"
+         id="feGaussianBlur7596-4" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8616-5">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8618-0"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8940-3"
+       x="-0.25152978"
+       width="1.5030596"
+       y="-0.053035267"
+       height="1.1060705">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="13.024603"
+         id="feGaussianBlur8942-6" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8209-6">
+      <path
+         sodipodi:nodetypes="czcc"
+         id="path8211-3"
+         d="m 734.03125,519.49186 c 0,0 16.75513,37.01806 28.70141,53.95395 11.94629,16.93589 52.72716,56.04605 52.72716,56.04605 l 0.59717,-138.58975"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#1a1a1a;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8822-2"
+       x="-0.2742857"
+       width="1.5485713"
+       y="-0.21333334"
+       height="1.4266667">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="11.313708"
+         id="feGaussianBlur8824-0" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3998-6">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 178.21428,274.14789 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401287 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.3574 -122.78647,50.053 -187.06988,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path4000-1"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter3677-5">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2.0397518"
+         id="feGaussianBlur3679-5" />
+    </filter>
+    <filter
+       id="filter3785-4"
+       inkscape:label="White Fur">
+      <feTurbulence
+         id="feTurbulence3787-7"
+         type="fractalNoise"
+         baseFrequency="0.24044943820224721"
+         numOctaves="10"
+         seed="655"
+         result="result0" />
+      <feDisplacementMap
+         id="feDisplacementMap3789-65"
+         in="SourceGraphic"
+         in2="result0"
+         scale="62"
+         xChannelSelector="B"
+         yChannelSelector="G" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8604-69">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8606-3"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8802-7"
+       x="-0.35311759"
+       width="1.7062352"
+       y="-0.1817714"
+       height="1.3635428">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="48.038491"
+         id="feGaussianBlur8804-4" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3317"
+       id="radialGradient3315-5"
+       cx="543.6698"
+       cy="147.3131"
+       fx="543.6698"
+       fy="147.3131"
+       r="47.863216"
+       gradientTransform="matrix(2.1382256,0,0,2.3382884,-77.03847,-101.68704)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3537"
+       id="radialGradient3543-4"
+       cx="385"
+       cy="237.00504"
+       fx="385"
+       fy="237.00504"
+       r="86.928574"
+       gradientTransform="matrix(1,0,0,0.8562038,0,34.080427)"
+       gradientUnits="userSpaceOnUse" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4100-3">
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.9000755px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 265.93541,126.68393 -18.76721,168.86308 174.10543,-73.12068 61.9544,88.65883 57.8844,-31.9903 -37.53442,-180.059677 -237.6426,27.648747 z"
+         id="path4102-0"
+         sodipodi:nodetypes="ccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4120-7"
+       x="-0.2770822"
+       width="1.5541644"
+       y="-0.32482043"
+       height="1.6496409">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.956289"
+         id="feGaussianBlur4122-8" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3961"
+       id="radialGradient3915-6"
+       cx="418.30365"
+       cy="342.47794"
+       fx="418.30365"
+       fy="342.47794"
+       r="131.4509"
+       gradientTransform="matrix(1.3957347,0.6211056,-0.4244067,0.9537174,-15.061913,-227.96711)"
+       gradientUnits="userSpaceOnUse" />
+    <mask
+       maskUnits="userSpaceOnUse"
+       id="mask3684-3">
+      <ellipse
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient3688);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.43724918px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         id="path3686-1"
+         transform="translate(-174.03125,62.156036)"
+         cx="579.474"
+         cy="260.57516"
+         rx="192.6866"
+         ry="164.04877" />
+    </mask>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3951"
+       id="radialGradient3933-8"
+       cx="397.16388"
+       cy="336.95245"
+       fx="397.16388"
+       fy="336.95245"
+       r="36.75"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.9449972,2.4894837e-7,-2.4894833e-7,1.9449969,-375.31868,-318.41912)" />
+    <filter
+       inkscape:collect="always"
+       id="filter8806-6"
+       x="-0.61142862"
+       width="2.2228572"
+       y="-0.14930232"
+       height="1.2986046">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="37.830213"
+         id="feGaussianBlur8808-4" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter8826-9"
+       x="-0.25894088"
+       width="1.5178818"
+       y="-0.2236412"
+       height="1.4472824">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="19.631544"
+         id="feGaussianBlur8828-5" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3985"
+       id="radialGradient3991-0"
+       cx="402.48898"
+       cy="317.23578"
+       fx="402.48898"
+       fy="317.23578"
+       r="23.714285"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(4.3776616,0,0,4.3776616,-1358.3025,-1070.7357)" />
+    <filter
+       inkscape:collect="always"
+       id="filter3981-7"
+       x="-0.30000001"
+       width="1.6"
+       y="-0.30000001"
+       height="1.6">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="2"
+         id="feGaussianBlur3983-1" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4106"
+       id="radialGradient4112-7"
+       cx="250.22678"
+       cy="475.09763"
+       fx="250.22678"
+       fy="475.09763"
+       r="95.98877"
+       gradientTransform="matrix(1.2259004,-0.7077739,0.1413989,0.2449102,322.22326,608.91815)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4013"
+       id="radialGradient3585-2"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+       cx="228.81355"
+       cy="440.26971"
+       fx="228.81355"
+       fy="440.26971"
+       r="119.17509" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3999-0">
+      <path
+         style="display:inline;opacity:1;fill:#f5ff04;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 12.61031,-67.04463 3.21429,-93.92857 -9.43424,-26.99328 -34.96741,-59.12448 -66.42857,-69.64285 -31.03327,-10.37532 -65.01776,-4.84837 -84.28571,5.71428 z"
+         id="path4001-61"
+         sodipodi:nodetypes="czzczzzzc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4041"
+       id="radialGradient4060-5"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+       cx="275.4422"
+       cy="335.34866"
+       fx="275.4422"
+       fy="335.34866"
+       r="36.75" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient7622"
+       id="radialGradient4062-9"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.05911206,2.6869855,-0.7234268,0.01591495,408.72779,-424.56452)"
+       cx="275.4422"
+       cy="335.34866"
+       fx="275.4422"
+       fy="335.34866"
+       r="36.75" />
+    <filter
+       inkscape:collect="always"
+       id="filter4079-1">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="6.5887624"
+         id="feGaussianBlur4081-1" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4013"
+       id="radialGradient4056-5"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.1323239,0.7659488,-1.4550286,2.1510098,588.75376,-711.79716)"
+       cx="228.81355"
+       cy="440.26971"
+       fx="228.81355"
+       fy="440.26971"
+       r="119.17509" />
+    <filter
+       inkscape:collect="always"
+       id="filter4083-9">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.5052066"
+         id="feGaussianBlur4085-7" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4113"
+       id="radialGradient4119-7"
+       cx="296.33783"
+       cy="427.17749"
+       fx="296.33783"
+       fy="427.17749"
+       r="19.704132"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.9797125,0,0,2.9797125,-599.28727,-827.0855)" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4862"
+       id="radialGradient4868-3"
+       cx="429.56738"
+       cy="377.42877"
+       fx="429.56738"
+       fy="377.42877"
+       r="72.079735"
+       gradientTransform="matrix(1,0,0,0.618034,0,144.16496)"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       inkscape:collect="always"
+       id="filter4002-6"
+       x="-0.24334238"
+       width="1.4866848"
+       y="-0.39104807"
+       height="1.7820961">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="14.589518"
+         id="feGaussianBlur4004-3" />
+    </filter>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4870"
+       id="radialGradient4876-9"
+       cx="437.6991"
+       cy="391.21735"
+       fx="437.6991"
+       fy="391.21735"
+       r="36.611931"
+       gradientTransform="matrix(1,0,0,0.618034,0,149.43174)"
+       gradientUnits="userSpaceOnUse" />
+    <filter
+       inkscape:collect="always"
+       id="filter4010-1"
+       x="-0.14577261"
+       width="1.2915452"
+       y="-0.23523259"
+       height="1.4704652">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="4.4442907"
+         id="feGaussianBlur4012-2" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4053-9">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.6062947"
+         id="feGaussianBlur4055-3" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8514-8">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8516-8"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8814-5"
+       x="-0.20466694"
+       width="1.4093339"
+       y="-0.29007819"
+       height="1.5801564">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="22.300169"
+         id="feGaussianBlur8816-0" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8610-9">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8612-6"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8810-3"
+       x="-0.23519406"
+       width="1.4703881"
+       y="-0.24500646"
+       height="1.4900129">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="58.328041"
+         id="feGaussianBlur8812-8" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8622-5">
+      <path
+         style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 821.64329,477.88997 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+         id="path8624-61"
+         sodipodi:nodetypes="czzzzzzczczczczzzc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8818-1"
+       x="-0.34381232"
+       width="1.6876246"
+       y="-0.18433961"
+       height="1.3686792">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="34.542167"
+         id="feGaussianBlur8820-5" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8906-9">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#262f2f;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 352.24553,211.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.554046 36.34702,-65.295835 116.94091,-84.694685 185.93466,-91.465427 86.92239,-11.016801 184.91267,17.940072 233.37134,95.401283 54.12402,75.7333 56.67476,172.53912 80.61204,259.52795 29.43779,127.1276 54.77914,256.21414 60.39224,386.85035 -3.06348,78.18185 -8.42634,165.18415 -60.50321,228.13413 -48.02654,50.35744 -122.78647,50.05304 -187.06988,59.00234 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.19824 -64.77564,-37.94001 -95.73019,-113.47863 -97.2794,-186.01958 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         id="path8908-8"
+         sodipodi:nodetypes="cscccccccccccc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3602-4">
+      <path
+         sodipodi:nodetypes="czzzzzzczczczczzzc"
+         id="path3604-8"
+         d="m 647.61204,540.04601 c 0,0 22.61947,-6.50681 35.74275,-5.87273 13.12328,0.63409 30.64158,1.93862 43.70885,12.18619 13.06727,10.24756 25.06774,27.14007 34.11239,58.36965 9.04465,31.22958 1.69832,99.25201 -6.17603,143.34735 -7.87435,44.09534 -28.2651,106.11298 -45,140 -16.7349,33.88702 -49.79771,77.4952 -60.56943,89.87616 -11.36422,13.06197 -56.20589,36.42617 -79.43057,42.26667 5.3033,-10.6066 48.89976,-50.58884 35,-60.71426 -14.01897,-10.21226 -45.76009,45.98236 -84.29315,29.03317 21.38231,-13.13212 41.7794,-51.18606 34.04061,-66.59445 -7.84025,-15.61039 -30.70493,48.75757 -93.53554,37.01288 30.05204,-27.52666 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.29315 -60.46175,54.29315 0,0 -2.8219,-41.70118 13.7732,-68.60732 16.63935,-26.97787 79.65297,-81.61527 99.55313,-111.70342 19.90015,-30.08814 33.61256,-66.00902 42.13542,-92.51794 8.52286,-26.50892 15.80094,-77.09954 15.80094,-77.09954"
+         style="display:inline;opacity:1;fill:#202020;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter3587-1"
+       x="-0.1">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="8.881432"
+         id="feGaussianBlur3589-0" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3992-4">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+         id="path3994-4"
+         sodipodi:nodetypes="czzzzzzzzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter3779-4"
+       x="-0.087980822"
+       width="1.1759616"
+       y="-0.17728332"
+       height="1.3545666">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="16.340344"
+         id="feGaussianBlur3781-4" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3986-7">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+         id="path3988-6"
+         sodipodi:nodetypes="czzzzzzzzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3722-3">
+      <path
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         d="m 709.28572,844.50504 c 54.28571,-1.42857 126.035,-15.05199 170,-26.78572 44.05271,-11.75714 125.88628,-36.34724 175.35708,-57.85714 49.3393,-21.45272 113.6037,-59.2816 154.2858,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7143,-33.57143 8.3691,22.36779 -16.407,56.32562 -37.8572,81.07143 -21.6041,24.9234 -52.7313,52.70533 -98.9286,89.28571 C 1086.6598,841.08542 976.77458,906.08967 920,933.07647 c -57.06606,27.12536 -128.20334,58.23842 -172.14286,72.50003 -43.93952,14.2616 -131.42857,31.0714 -131.42857,31.0714 l 92.85715,-192.14286 z"
+         id="path3724-1"
+         sodipodi:nodetypes="czzzzzzzzcc"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8225-7">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.661912"
+         id="feGaussianBlur8227-5" />
+    </filter>
+    <mask
+       maskUnits="userSpaceOnUse"
+       id="mask7704-9">
+      <path
+         style="fill:url(#linearGradient7708);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 718.40812,-224.31217 33.25,56 275.99998,-24 159.5,-48.25 -66.5,-82.75 -402.24998,99 z"
+         id="path7706-6"
+         inkscape:connector-curvature="0" />
+    </mask>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath7421-7">
+      <path
+         sodipodi:type="inkscape:offset"
+         inkscape:radius="0"
+         inkscape:original="M 1111.4062 -285.9375 L 1107.4688 -284.0625 C 1107.4283 -284.05228 1107.3692 -284.04201 1107.3438 -284.03125 C 1106.925 -283.8184 1107.1791 -283.93067 1106.6875 -283.71875 C 1106.2014 -283.50919 1104.9499 -283.13456 1102.5938 -282.25 C 1099.2626 -280.99942 1096.7895 -280.10016 1095.5938 -279.1875 C 1094.0576 -279.16623 1091.8733 -278.95419 1089.9375 -278.46875 C 1086.956 -277.72108 1085.0823 -277.29474 1083.1875 -276.875 C 1081.2927 -276.45527 1081.512 -276.23281 1080.3125 -276 C 1079.0159 -275.74833 1078.5911 -276.00899 1074.875 -275.21875 C 1071.3851 -274.4766 1065.9802 -273.28768 1064.7188 -272.53125 C 1063.1348 -272.71203 1060.8513 -272.85303 1058.875 -272.5625 C 1055.8346 -272.11554 1053.9588 -271.88974 1052.0312 -271.65625 C 1051.3758 -271.57687 1050.9902 -271.45547 1050.6875 -271.375 C 1050.2613 -271.24334 1050.0017 -271.11498 1049.3125 -271.03125 C 1048.0009 -270.87188 1047.5503 -271.18808 1043.7812 -270.75 C 1040.2273 -270.33691 1034.7758 -269.47718 1033.5312 -268.8125 C 1031.9322 -269.10979 1029.6735 -269.34669 1027.6875 -269.15625 C 1024.6287 -268.86293 1022.7155 -268.67226 1020.7812 -268.5 C 1018.847 -268.32773 1019.0926 -268.07763 1017.875 -267.96875 C 1016.5588 -267.85105 1016.1152 -268.13238 1012.3438 -267.71875 C 1008.8017 -267.3303 1003.3359 -266.50948 1002.0625 -265.84375 C 1000.4636 -266.13844 998.1753 -266.35076 996.1875 -266.15625 C 993.12921 -265.857 991.2463 -265.67601 989.3125 -265.5 C 988.65501 -265.44015 988.27245 -265.32144 987.96875 -265.25 C 987.54105 -265.13104 987.28525 -265.03193 986.59375 -264.96875 C 985.27775 -264.84849 984.834 -265.16363 981.0625 -264.75 C 977.50631 -264.35998 972.0569 -263.51084 970.8125 -262.84375 C 969.21381 -263.13793 966.95265 -263.36747 964.96875 -263.15625 C 961.91305 -262.83092 959.9947 -262.63001 958.0625 -262.4375 C 956.13031 -262.24499 956.37275 -261.99662 955.15625 -261.875 C 953.84137 -261.74353 953.3932 -262.03954 949.625 -261.59375 C 946.08611 -261.17509 940.6473 -260.30158 939.375 -259.625 C 937.77741 -259.90604 935.51505 -260.04543 933.53125 -259.8125 C 930.47927 -259.45413 928.58625 -259.24464 926.65625 -259.03125 C 926.00007 -258.95869 925.6156 -258.85856 925.3125 -258.78125 C 924.88571 -258.65402 924.6276 -258.51405 923.9375 -258.4375 C 922.62411 -258.29181 922.17015 -258.61152 918.40625 -258.125 C 914.85737 -257.66624 909.4276 -256.70598 908.1875 -256 C 906.59441 -256.24424 904.3537 -256.38135 902.375 -256.125 C 899.32741 -255.73018 897.4243 -255.47655 895.5 -255.21875 C 893.57571 -254.96096 893.7739 -254.72522 892.5625 -254.5625 C 891.25301 -254.3866 890.8153 -254.66688 887.0625 -254.09375 C 883.53821 -253.55551 878.1393 -252.39458 876.875 -251.65625 C 875.28751 -251.85979 873.0295 -251.91098 871.0625 -251.5625 C 868.03631 -251.02638 866.1636 -250.70081 864.25 -250.375 C 863.59941 -250.26423 863.2363 -250.10406 862.9375 -250 C 862.51681 -249.83512 862.27405 -249.6687 861.59375 -249.53125 C 860.29905 -249.26966 859.86665 -249.53745 856.15625 -248.71875 C 852.65777 -247.9468 847.31035 -246.33582 846.09375 -245.5 C 844.53085 -245.57745 842.33625 -245.41472 840.40625 -244.90625 C 837.43387 -244.12312 835.58855 -243.67416 833.71875 -243.15625 C 831.84875 -242.63835 832.0521 -242.38897 830.875 -242.0625 C 829.60251 -241.7096 829.17795 -241.95541 825.53125 -240.875 C 822.10657 -239.86037 816.88185 -237.94183 815.65625 -237.03125 C 814.11747 -237.01851 811.93645 -236.75903 810.03125 -236.15625 C 807.10027 -235.22891 805.2809 -234.69783 803.4375 -234.09375 C 802.81071 -233.88837 802.44585 -233.70117 802.15625 -233.5625 C 801.74867 -233.34889 801.50295 -233.15375 800.84375 -232.9375 C 799.58925 -232.52596 799.1576 -232.74846 795.5625 -231.5 C 792.17261 -230.32283 786.96755 -228.2863 785.78125 -227.34375 C 784.25737 -227.28408 782.1312 -226.94888 780.25 -226.28125 C 777.35261 -225.25296 775.55095 -224.60577 773.71875 -223.96875 C 771.88655 -223.33174 772.0909 -223.12021 770.9375 -222.71875 C 769.69071 -222.28479 769.27395 -222.51903 765.71875 -221.15625 C 762.38005 -219.87645 757.23165 -217.6737 756.03125 -216.6875 C 754.52407 -216.57981 752.39555 -216.1887 750.53125 -215.46875 C 747.66307 -214.36115 745.90735 -213.68719 744.09375 -213 C 743.47705 -212.76637 743.0973 -212.55797 742.8125 -212.40625 C 742.81251 -212.40625 742.8125 -212.37673 742.8125 -212.375 L 734.8125 -209.1875 L 736.625 -194.46875 C 736.36701 -194.52956 742.8125 -191.15625 742.8125 -191.15625 C 743.03891 -191.30093 743.26145 -191.42886 743.53125 -191.53125 C 744.61177 -191.94123 745.70285 -191.74702 749.53125 -193.21875 C 753.35977 -194.69049 754.7553 -195.22373 755.4375 -195.625 C 756.11711 -196.02478 757.04925 -196.50437 757.65625 -197.15625 C 759.48317 -197.294 761.22705 -197.64948 762.59375 -198.15625 C 765.56175 -199.25677 767.4691 -199.96244 769.375 -200.625 C 771.28081 -201.28754 771.72915 -202.03987 772.78125 -202.40625 C 773.87287 -202.78636 774.97635 -202.57163 778.84375 -203.9375 C 782.71115 -205.30336 784.1269 -205.76458 784.8125 -206.15625 C 785.51361 -206.55677 786.5133 -207.08923 787.125 -207.75 C 789.09581 -207.80466 790.94195 -208.13463 792.40625 -208.625 C 795.40777 -209.63008 797.3324 -210.24671 799.25 -210.875 C 800.78861 -211.3791 801.42415 -211.92177 802.15625 -212.3125 C 802.38647 -212.44681 802.63215 -212.56623 802.90625 -212.65625 C 804.00457 -213.01673 805.0877 -212.73762 809 -213.96875 C 812.91231 -215.19988 814.366 -215.6417 815.0625 -216 C 815.75641 -216.35697 816.6926 -216.79261 817.3125 -217.40625 C 819.17771 -217.42891 820.94835 -217.67308 822.34375 -218.09375 C 825.37415 -219.00729 827.33615 -219.52385 829.28125 -220.0625 C 831.22637 -220.60114 831.70745 -221.32702 832.78125 -221.625 C 833.89527 -221.93415 835.00125 -221.61761 838.96875 -222.65625 C 842.93625 -223.69488 844.38625 -224.08898 845.09375 -224.40625 C 845.82855 -224.73584 846.90765 -225.15997 847.53125 -225.78125 C 849.52907 -225.66525 851.3887 -225.80134 852.875 -226.15625 C 855.95311 -226.89125 857.9584 -227.25719 859.9375 -227.65625 C 861.52541 -227.97643 862.1818 -228.4468 862.9375 -228.75 C 863.17501 -228.8568 863.4044 -228.94276 863.6875 -229 C 864.82091 -229.22919 865.99215 -228.79107 870.03125 -229.5 C 874.07067 -230.20893 875.5315 -230.42709 876.25 -230.6875 C 876.96581 -230.94694 877.95435 -231.25474 878.59375 -231.78125 C 880.51795 -231.54176 882.34165 -231.55672 883.78125 -231.78125 C 886.90767 -232.26887 888.9358 -232.48192 890.9375 -232.75 C 892.93921 -233.01807 893.42625 -233.69514 894.53125 -233.84375 C 895.67767 -233.99793 896.8071 -233.54218 900.875 -234.0625 C 904.94281 -234.58282 906.43525 -234.75823 907.15625 -235 C 907.89337 -235.24714 908.95435 -235.58623 909.59375 -236.125 C 911.64375 -235.78947 913.56745 -235.72704 915.09375 -235.90625 C 918.23595 -236.27521 920.27375 -236.46561 922.28125 -236.6875 C 923.89207 -236.86552 924.5459 -237.2957 925.3125 -237.53125 C 925.55341 -237.61677 925.80655 -237.68685 926.09375 -237.71875 C 927.24345 -237.84647 928.39505 -237.3721 932.46875 -237.84375 C 936.54245 -238.3154 938.0278 -238.45435 938.75 -238.6875 C 939.46941 -238.91977 940.45025 -239.16096 941.09375 -239.65625 C 943.03005 -239.32279 944.8638 -239.25201 946.3125 -239.40625 C 949.45851 -239.7412 951.49 -239.92484 953.5 -240.125 C 955.50991 -240.32514 955.98415 -240.95139 957.09375 -241.0625 C 958.24485 -241.17778 959.39025 -240.69744 963.46875 -241.125 C 967.54725 -241.55256 969.05765 -241.68709 969.78125 -241.90625 C 970.52047 -242.13011 971.57685 -242.4195 972.21875 -242.9375 C 974.27575 -242.53883 976.2206 -242.4441 977.75 -242.59375 C 980.89871 -242.90185 982.9258 -243.067 984.9375 -243.25 C 986.55151 -243.39682 987.20055 -243.81055 987.96875 -244.03125 C 988.21005 -244.11211 988.4623 -244.16116 988.75 -244.1875 C 989.90211 -244.29295 991.0429 -243.79475 995.125 -244.1875 C 999.20711 -244.58025 1000.7139 -244.71834 1001.4375 -244.9375 C 1002.1584 -245.15583 1003.1371 -245.3852 1003.7812 -245.875 C 1005.7193 -245.52501 1007.5501 -245.42062 1009 -245.5625 C 1012.1487 -245.8706 1014.1758 -246.03575 1016.1875 -246.21875 C 1018.1991 -246.40174 1018.7017 -247.05677 1019.8125 -247.15625 C 1020.9648 -247.25948 1022.1047 -246.77142 1026.1875 -247.15625 C 1030.2704 -247.54107 1031.7762 -247.65725 1032.5 -247.875 C 1033.2393 -248.09743 1034.2956 -248.38949 1034.9375 -248.90625 C 1036.9949 -248.50448 1038.9404 -248.40292 1040.4688 -248.5625 C 1043.6153 -248.89102 1045.6458 -249.0852 1047.6562 -249.28125 C 1049.2692 -249.43854 1049.9219 -249.91273 1050.6875 -250.15625 C 1050.9282 -250.24429 1051.1507 -250.27762 1051.4375 -250.3125 C 1052.5858 -250.4522 1053.7542 -249.97259 1057.8125 -250.5625 C 1061.8708 -251.15242 1063.3743 -251.33964 1064.0938 -251.59375 C 1064.8104 -251.84691 1065.7684 -252.15182 1066.4062 -252.6875 C 1068.3259 -252.47556 1070.1262 -252.53609 1071.5625 -252.78125 C 1074.6816 -253.31365 1076.6741 -253.70986 1078.6562 -254.09375 C 1080.6383 -254.47762 1081.1305 -255.1334 1082.2188 -255.375 C 1083.3475 -255.62566 1084.489 -255.25871 1088.4688 -256.25 C 1092.4483 -257.24127 1093.8983 -257.6693 1094.5938 -258.03125 C 1095.316 -258.40725 1096.3555 -258.90183 1096.9688 -259.5625 C 1098.9317 -259.57454 1100.7625 -259.85355 1102.1875 -260.40625 C 1105.1387 -261.55085 1107.0607 -262.27567 1108.875 -263.15625 C 1110.3307 -263.86277 1111.1941 -264.85828 1111.4062 -265.15625 C 1111.6185 -265.4542 1111.5051 -265.8848 1111.5312 -265.90625 C 1111.5742 -265.94148 1111.8716 -266.00028 1112.0312 -266.34375 C 1112.8902 -268.19082 1114.3544 -271.97139 1114.4688 -272.65625 C 1114.5825 -273.33839 1114.6368 -274.00902 1114.6875 -274.40625 C 1114.7169 -274.63575 1114.5404 -275.28515 1114.5625 -275.34375 C 1114.5934 -275.42579 1114.8508 -275.59432 1114.9062 -275.84375 C 1115.1725 -277.04206 1114.9953 -278.05111 1114.7812 -279.46875 C 1114.5673 -280.88638 1113.8096 -284.08338 1113.1562 -284.9375 C 1112.4973 -285.79922 1111.9314 -285.94801 1111.4062 -285.9375 z "
+         style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         id="path7423-8"
+         d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 1.8125,14.71875 c -0.25799,-0.0608 6.1875,3.3125 6.1875,3.3125 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+         transform="translate(0.08004571,-0.03125)" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter7001-5">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur7003-7" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6949-4"
+       x="-0.10294895"
+       width="1.2058979"
+       y="-0.34224695"
+       height="1.6844939">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6951-1" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6961-8"
+       x="-0.09919104"
+       width="1.1983821"
+       y="-0.22643611"
+       height="1.4528722">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6963-5" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6957-9"
+       x="-0.098213427"
+       width="1.1964267"
+       y="-0.19838208"
+       height="1.3967642">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6959-7" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6997-5">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6999-3" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6953-8"
+       x="-0.098320946"
+       width="1.1966419"
+       y="-0.19750816"
+       height="1.3950163">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6955-8" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6993-3"
+       x="-0.098213255"
+       width="1.1964265"
+       y="-0.19838208"
+       height="1.3967642">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6995-1" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6989-8"
+       x="-0.098428868"
+       width="1.1968577"
+       y="-0.20287035"
+       height="1.4057407">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6991-9" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6985-6"
+       x="-0.098428868"
+       width="1.1968577"
+       y="-0.20853186"
+       height="1.4170637">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6987-4" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6965-3"
+       x="-0.099081434"
+       width="1.1981629"
+       y="-0.22529824"
+       height="1.4505965">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6967-3" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6981-3"
+       x="-0.10052545"
+       width="1.2010509"
+       y="-0.2742162"
+       height="1.5484324">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6983-8" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6977-6"
+       x="-0.10224481"
+       width="1.2044896"
+       y="-0.32371372"
+       height="1.6474274">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6979-0" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6973-4"
+       x="-0.10330495"
+       width="1.2066098"
+       y="-0.36439717"
+       height="1.7287945">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6975-8" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter6969-8"
+       x="-0.10450897"
+       width="1.2090179"
+       y="-0.40468886"
+       height="1.8093777">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.1675612"
+         id="feGaussianBlur6971-8" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7345-9">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="1.7233839"
+         id="feGaussianBlur7347-7" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7333-7">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7335-6" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7285-4"
+       x="-0.030884685"
+       width="1.0617694"
+       y="-0.10267408"
+       height="1.2053483">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7287-3" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7289-0">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7291-3" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7293-0">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7295-9" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7337-2">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7339-5" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7297-4">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7299-0" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7301-5">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7303-9" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7305-4">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7307-6" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7309-9">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7311-2" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7313-2">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7315-4" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7317-7">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7319-7" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7321-5">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7323-4" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7329-8"
+       x="-0.030991485"
+       width="1.061983"
+       y="-0.10931916"
+       height="1.2186383">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7331-1" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter7325-2"
+       x="-0.031352691"
+       width="1.0627054"
+       y="-0.12140666"
+       height="1.2428133">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.35026836"
+         id="feGaussianBlur7327-8" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9048-9"
+       x="-0.40879121"
+       width="1.8175824"
+       y="-0.71538466"
+       height="2.4307692">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="21.92031"
+         id="feGaussianBlur9050-3" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3631-6">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         id="path3633-8"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3677-0">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         id="path3679-2"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter3898-1">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.892985"
+         id="feGaussianBlur3900-0" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3622-5">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 266.27183,924.57186 c -1.40727,18.80121 -1.1449,32.75103 2.08174,49.30328 3.22665,16.55234 16.40608,45.90736 20.3344,63.18376 3.92622,17.2671 2.69413,38.3096 -12.45944,51.1482 -15.31761,12.9774 -42.05127,21.5989 -67.8323,15.7338 -25.78106,-5.8653 -69.54907,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045183,939.86194 41.867508,909.43681 27.689836,879.01169 29.207903,872.71824 33.747793,863.90708 24.381071,839.38658 21.334081,813.84027 0.03533552,788.33044 30.360815,791.44488 43.915625,815.28677 60.161025,835.47019 54.631129,787.39416 42.10631,771.05369 31.787073,744.74589 c 29.994295,6.08166 50.57936,31.8724 63.979783,72.7125 9.554154,-3.91791 18.237764,-9.37294 30.187414,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.687255,-101.06994 53.441965,5.67033 83.657025,80.63932 78.971425,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24896,-38.34702 -21.04781,-76.8679 -3.65971,-118.64818 0,0 48.28678,65.43687 54.38966,85.80577 6.10287,20.36891 1.51881,38.70052 1.51881,38.70052 0,0 16.95957,31.08529 20.29392,51.09413 3.3731,20.24135 -3.53269,59.10332 -4.94582,77.98324 z"
+         id="path3624-1"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter9024-1"
+       x="-0.55453134"
+       width="2.1090627"
+       y="-0.51434779"
+       height="2.0286956">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="20.912684"
+         id="feGaussianBlur9026-0" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9020-8"
+       x="-0.32861114"
+       width="1.6572223"
+       y="-0.182"
+       height="1.364">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="20.912684"
+         id="feGaussianBlur9022-5" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter9044-0"
+       x="-0.32631579"
+       width="1.6526316"
+       y="-0.84545463"
+       height="2.6909094">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="21.92031"
+         id="feGaussianBlur9046-6" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4177-4">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path4179-6"
+         d="m 586.13271,997.98981 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.9123 -3.78268,51.8008 -2.90046,70.6561 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.0839 38.76107,-114.49733 44.6608,-149.76855 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4105-2">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="3.8640966"
+         id="feGaussianBlur4107-5" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4130-8"
+       x="-0.49509686"
+       width="1.9901937"
+       y="-0.26708817"
+       height="1.5341763">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="10.730622"
+         id="feGaussianBlur4132-6" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       id="filter4141-2"
+       x="-0.40611032"
+       width="1.8122206"
+       y="-0.30260596"
+       height="1.6052119">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="9.8586086"
+         id="feGaussianBlur4143-8" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8338-4">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8340-7"
+         d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8333-2">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="7.18"
+         id="feGaussianBlur8335-4" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8359-0">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8361-6"
+         d="m 266.27183,924.57185 c -1.40727,18.80122 -1.1449,32.75104 2.08174,49.30328 3.22666,16.55238 16.40609,45.90737 20.33441,63.18377 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1482 -15.31761,12.9775 -42.05127,21.599 -67.8323,15.7338 -25.78106,-5.8653 -69.54908,-49.2234 -88.59019,-70.2283 C 100.6939,1012.6293 56.045182,939.86193 41.867507,909.4368 27.689835,879.01168 29.207902,872.71823 33.747792,863.90708 24.38107,839.38658 21.33408,813.84026 0.03533448,788.33044 30.360814,791.44487 43.915624,815.28676 60.161024,835.47019 54.631128,787.39416 42.106309,771.05368 31.787072,744.74589 c 29.994295,6.08165 50.57936,31.87239 63.979783,72.7125 9.554155,-3.91792 18.237765,-9.37294 30.187415,-9.0612 -11.2975,-41.6958 -17.94947,-69.91585 -36.687256,-101.06994 53.441966,5.67032 83.657026,80.63932 78.971426,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34703 -21.04782,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38965,85.80578 6.10288,20.3689 1.51882,38.70051 1.51882,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24134 -3.53269,59.10331 -4.94582,77.98323 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8354-2">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="6.82"
+         id="feGaussianBlur8356-9" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath3636-90">
+      <path
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         id="path3638-8"
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter4185-1">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="3.6164709"
+         id="feGaussianBlur4187-3" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8392-1">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8394-1"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8379-0"
+       x="-0.14413793"
+       width="1.288276"
+       y="-0.10278689"
+       height="1.2055738">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="7.389266"
+         id="feGaussianBlur8381-3" />
+    </filter>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath8417-4">
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8419-03"
+         d="m 760.16396,935.83377 c 6.7941,18.90279 10.49369,33.29969 11.8903,51.21189 1.39662,17.91234 -3.78268,51.80084 -2.90046,70.65614 0.88175,18.8452 8.13369,40.099 27.34463,48.9689 19.41887,8.9658 49.31924,10.2113 74.11984,-3.1456 24.8006,-13.357 57.40102,-70.3255 70.97426,-97.3087 13.62385,-27.08394 38.76107,-114.49737 44.6608,-149.76859 5.89973,-35.27121 2.55054,-41.30077 -4.61748,-49.05549 2.6403,-27.84015 -1.49972,-54.93543 13.10969,-87.18618 -30.24901,11.8257 -37.38229,40.1607 -48.31889,65.50508 -8.00091,-50.93293 0.20916,-71.27319 3.31889,-101.21936 -29.06476,14.77791 -42.86151,47.11402 -45,92.85714 -10.92395,-1.3042 -21.39144,-4.43423 -33.57143,-0.71429 -0.26404,-46.02334 -1.46356,-76.88941 8.91063,-114.20649 -53.25547,21.02686 -62.94728,106.5941 -56.05349,112.77792 -10.88282,0.535 -21.37108,-1.2973 -32.85714,2.85715 0.63892,-42.57135 -0.26046,-84.90861 -30,-122.85715 0,0 -30.95806,80.92234 -31.42857,103.57143 -0.47051,22.64909 9.45159,40.16588 9.45159,40.16588 0,0 -8.56807,36.74051 -6.29859,58.23223 2.29585,21.74146 20.4429,59.67617 27.26542,78.65809 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+    </clipPath>
+    <filter
+       inkscape:collect="always"
+       id="filter8404-9"
+       x="-0.090268657"
+       width="1.1805373"
+       y="-0.10250848"
+       height="1.205017">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="5.3457272"
+         id="feGaussianBlur8406-1" />
+    </filter>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2843"
+       id="linearGradient6951"
+       gradientUnits="userSpaceOnUse"
+       x1="347.89655"
+       y1="1070.2124"
+       x2="275.58191"
+       y2="867.97992" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8964"
+       id="linearGradient6953"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)"
+       x1="603.84064"
+       y1="627.85303"
+       x2="616.24396"
+       y2="585.42664" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8952"
+       id="linearGradient6955"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)"
+       x1="609.31244"
+       y1="239.46866"
+       x2="560.83142"
+       y2="262.86206" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3961"
+       id="linearGradient6957"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(450.03125,73.843964)"
+       x1="398.21429"
+       y1="343.52289"
+       x2="379.28571"
+       y2="265.30862" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4084"
+       id="linearGradient6959"
+       gradientUnits="userSpaceOnUse"
+       x1="182.35046"
+       y1="256.11136"
+       x2="145.53348"
+       y2="542.20502" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4084"
+       id="linearGradient6961"
+       gradientUnits="userSpaceOnUse"
+       x1="182.35046"
+       y1="256.11136"
+       x2="145.53348"
+       y2="542.20502" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient6963"
+       gradientUnits="userSpaceOnUse"
+       x1="412.08926"
+       y1="404.91574"
+       x2="417.375"
+       y2="401.82648" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient6965"
+       gradientUnits="userSpaceOnUse"
+       x1="411.91071"
+       y1="404.91577"
+       x2="417.375"
+       y2="401.82648" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient6967"
+       gradientUnits="userSpaceOnUse"
+       x1="411.91071"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient6969"
+       gradientUnits="userSpaceOnUse"
+       x1="412.08926"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4478"
+       id="linearGradient6971"
+       gradientUnits="userSpaceOnUse"
+       x1="411.73212"
+       y1="405.54077"
+       x2="417.375"
+       y2="401.82648" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3660"
+       id="linearGradient6973"
+       gradientUnits="userSpaceOnUse"
+       x1="1255.7386"
+       y1="667.09216"
+       x2="893.69995"
+       y2="858.01099" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath6975">
+      <rect
+         id="rect6977"
+         width="440"
+         height="376"
+         x="547.99994"
+         y="205.32277"
+         style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#f8d615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new" />
+    </clipPath>
+    <marker
+       inkscape:stockid="Arrow1Send"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Send-4"
+       style="overflow:visible"
+       inkscape:isstock="true">
+      <path
+         inkscape:connector-curvature="0"
+         id="path7188-9"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
+         style="fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:1pt;stroke-opacity:1"
+         transform="matrix(-0.2,0,0,-0.2,-1.2,0)" />
+    </marker>
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer1"
+     inkscape:label="Shadow"
+     transform="translate(48.571445,195.53053)" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer20"
+     inkscape:label="New Ear"
+     transform="translate(48.571445,195.53053)" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer21"
+     inkscape:label="Rendered2"
+     style="display:inline"
+     transform="translate(48.571445,195.53053)" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer15"
+     inkscape:label="Feet"
+     style="display:inline"
+     transform="translate(48.571445,195.53053)" />
+  <g
+     inkscape:groupmode="layer"
+     id="layer16"
+     inkscape:label="Left Foot"
+     style="display:inline"
+     transform="translate(48.571445,195.53053)">
+    <rect
+       style="display:inline;opacity:1;fill:#a8a8a8;fill-opacity:1;stroke:#000000;stroke-width:20.89992332;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
+       id="rect6676-3-7-5"
+       width="1876.7191"
+       height="1562.9667"
+       x="-38.121483"
+       y="-86.153076" />
+    <rect
+       style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:20.92477036;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
+       id="rect6676-3-7"
+       width="1878.7875"
+       height="1564.9603"
+       x="2288.5129"
+       y="-84.10511" />
+    <rect
+       style="display:inline;opacity:1;fill:#a8a8a8;fill-opacity:1;stroke:#f83615;stroke-width:20.39127541;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;enable-background:new"
+       id="rect6676-3"
+       width="1833.4282"
+       height="1522.9458"
+       x="2309.7717"
+       y="-62.567806" />
+    <g
+       id="g4303">
+      <path
+         inkscape:export-ydpi="142.10527"
+         inkscape:export-xdpi="142.10527"
+         inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_new.png"
+         transform="matrix(10.726753,0,0,10.726753,-2882.1235,-4565.4583)"
+         sodipodi:nodetypes="cccccccccsccccccccccc"
+         id="path10326"
+         d="m 304.64285,526.6479 c -10,0.35715 -18.21428,2.85714 -18.21428,2.85714 l 7.5,6.07143 10.35714,3.57143 16.07143,0.35714 22.5,-5.35714 7.85714,1.07143 20.35715,-2.14286 -10.35715,6.78572 c 5.45923,-1.02361 17.39329,3.56911 9.64286,5.35714 -1.74,0.40142 13.92857,-4.64285 13.92857,-4.64285 l 2.5,-4.64287 3.57143,-9.28571 11.42857,0 18.21428,-4.64286 3.57144,-4.99999 -16.07144,1.07142 -12.14285,2.14286 -14.64286,-5 -70.6921,16.70774 -5.37933,-5.27917 z"
+         style="display:inline;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter11361);enable-background:new"
+         inkscape:connector-curvature="0" />
+      <g
+         transform="matrix(0.71084,-0.1937433,0.262963,0.9648058,503.68027,136.48399)"
+         id="g7882"
+         style="display:inline;opacity:1;enable-background:new">
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7904);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 245.12255,100.05344 c 0,0 -47.12811,-31.646921 -67.21465,-35.800939 -20.03792,-4.143963 -38.4729,-3.317578 -51.93364,13.607323 -13.46074,16.924901 -12.07739,61.265196 -13.53554,86.969546 -1.45815,25.70435 2.54945,70.17701 17.6046,88.66552 15.05516,18.4885 45.88634,13.58502 49.92695,21.4137 2.21283,4.28736 65.15228,-174.85515 65.15228,-174.85515 z"
+           id="path7876"
+           sodipodi:nodetypes="czzzzcc"
+           inkscape:connector-curvature="0" />
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7906);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 135.37935,82.017807 c 0,0 26.34355,1.938783 37.63307,13.903188 11.41494,12.097335 13.73457,21.331515 15.29586,37.734585 1.56337,16.42499 -0.84957,28.41812 -7.81382,36.03734 -6.96425,7.61922 -1.00429,19.58332 -25.91605,12.07107 -24.91176,-7.51225 -27.03224,-27.78298 -26.51523,-46.30475 0.51721,-18.52898 7.31617,-53.441433 7.31617,-53.441433 z"
+           id="path7878"
+           sodipodi:nodetypes="czzzzzc"
+           inkscape:connector-curvature="0" />
+        <path
+           style="display:inline;opacity:1;fill:url(#radialGradient7908);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 135.648,81.927211 c 0,0 -4.64465,16.365075 0.58825,28.563099 5.48794,12.79254 27.22425,44.26007 27.22425,54.65565 l 22.65625,-5 c 2.54218,-6.96644 3.21052,-15.75206 2.1875,-26.5 -1.56129,-16.40307 -3.8663,-25.62141 -15.28125,-37.718749 -9.65488,-10.232047 -31.59311,-13.374857 -37.375,-14 z"
+           id="path7880"
+           sodipodi:nodetypes="czccssc"
+           inkscape:connector-curvature="0" />
+      </g>
+      <path
+         sodipodi:nodetypes="czzzcczzcc"
+         id="path7917"
+         d="m 845.03125,1154.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.2857 c 0,0 85.88551,-16.2009 112.14285,-33.5714 26.25735,-17.3705 45.58238,-49.66602 59.28572,-71.42861 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         sodipodi:nodetypes="ccccc"
+         clip-path="url(#clipPath8658)"
+         id="path7919"
+         d="m 332.34019,898.38549 -32.73181,-61.29956 -37.61734,45.10646 c 2.17675,1.31711 5.77425,-20.85603 45.6004,-64.41708 l 24.74875,80.61018 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8888);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         sodipodi:nodetypes="cccccc"
+         clip-path="url(#clipPath2833)"
+         id="path7923"
+         d="m 200.81833,863.03015 146.3711,-51.61879 243.95184,226.27414 -241.83052,140.0072 -181.01934,-87.6813 32.52692,-226.98125 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient2841);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8892);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzcczcc"
+         id="path7921"
+         d="m 642.88839,640.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57145 -62.5,123.57145 l 76.07143,18.2143 c 0,0 11.80712,-12.8234 31.07142,-46.07146 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath3665)"
+         sodipodi:nodetypes="ccccccc"
+         id="path7925"
+         d="m 430.28131,381.94122 c -7.07106,2.82843 -236.18124,32.15181 -236.18124,32.15181 l -39.63961,359.83304 90.19849,92.63961 52.3259,-114.5513 100.46804,-186.39192 32.82842,-183.68124 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8856);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzzzcc"
+         id="path7927"
+         d="m 969.67051,1164.0346 c 0,0 23.25628,11.3937 36.06779,20.4761 12.6974,9.0015 29.4724,24.6491 41.6924,37.3605 12.3055,12.8002 20.1127,22.5987 41.5327,24.1608 21.4322,1.5629 53.2824,-8.7876 73.296,-24.6642 20.0135,-15.8766 45.6469,-69.2328 45.6469,-69.2328 l -127.1608,-143.0717"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         sodipodi:nodetypes="ccccc"
+         clip-path="url(#clipPath8642)"
+         id="path7929"
+         d="M 331.34019,641.50471 216.17367,835.36467 260.2153,925.96265 357.79603,732.21539 331.34019,641.50471 Z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8860);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <g
+         inkscape:transform-center-y="-28.255779"
+         inkscape:transform-center-x="-347.89063"
+         transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+         id="g7931"
+         style="display:inline;opacity:1;enable-background:new">
+        <path
+           id="path7933"
+           d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+           style="display:inline;opacity:1;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           inkscape:connector-curvature="0" />
+        <g
+           transform="matrix(0.9975712,-0.06965428,0.06965428,0.9975712,872.72062,140.02502)"
+           id="g7935"
+           style="display:inline;filter:url(#filter7610);enable-background:new"
+           clip-path="url(#clipPath7616)">
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+             d="m 229.94262,-409.12268 c -3.55781,0.05 -9.0242,0.36009 -10.30334,0.90414 -1.60609,-0.44747 -3.90316,-0.88131 -5.89995,-0.87674 -3.07199,0.007 -4.96469,0.009 -6.90727,0 -0.66047,-0.003 -1.04759,0.0672 -1.35267,0.10959 0,0 0,1.09593 0,1.09593 0.11972,-0.17947 0.39252,-0.69046 0.94975,-0.76715 0.74758,-0.10289 5.16928,-0.15123 7.31019,-0.1096 1.7746,0.0345 4.45523,0.27427 6.38921,0.95895 0.3214,0.11378 0.61925,0.27378 0.89219,0.41097 1.96342,0.98693 7.94336,4.30154 7.94336,4.30154 0,0 -6.63275,-3.94768 -7.48287,-4.43853 -0.20331,-0.11739 -0.57464,-0.25769 -1.03609,-0.41098 1.22063,-0.44779 5.07597,-0.61971 7.82823,-0.71235 3.0245,-0.10182 3.34776,-0.0896 5.41069,0.19179 2.12931,0.29043 3.33851,0.60276 3.33851,0.60276 -1e-5,0 -0.0784,-0.64118 1.03609,-0.79455 0.74757,-0.10289 5.16929,-0.15123 7.31019,-0.1096 2.0695,0.0403 5.36605,0.40716 7.2814,1.36992 1.00332,0.50433 3.03564,1.56863 4.79535,2.53571 l 0.0956,-0.0194 c 0,0 -3.58034,-2.16242 -4.43047,-2.65327 -0.20331,-0.11739 -0.57463,-0.25769 -1.03609,-0.41098 1.22062,-0.44779 5.04719,-0.61971 7.79945,-0.71235 3.0245,-0.10182 3.34775,-0.0896 5.41069,0.19179 1.95316,0.2664 3.01292,0.53006 3.19461,0.57536 0,0 -0.0271,-0.31146 -0.0271,-0.31146 -0.40903,-0.13645 -0.71424,-0.23335 -1.40038,-0.35748 -1.30081,-0.23533 -3.39912,-0.60156 -5.50857,-0.56398 -3.57195,0.0636 -9.05328,0.35596 -10.30334,0.90414 -1.60583,-0.44695 -3.87662,-0.8813 -5.87117,-0.87674 -3.07199,0.007 -4.99348,0.009 -6.93605,0 -1.94256,-0.009 -1.71268,0.27907 -2.93558,0.27398 -1.32191,-0.005 -1.76612,-0.35463 -5.55459,-0.30138 0,0 0,0 0,0"
+             id="path7937"
+             sodipodi:nodetypes="ccssscsssscscsscsssccscssccsscssscc"
+             inkscape:connector-curvature="0" />
+          <path
+             sodipodi:nodetypes="cssccsscc"
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+             d="m 206.1989,-407.47878 c 1.92021,0.81706 4.57715,2.19283 6.15897,3.39739 1.58184,1.20456 2.90757,1.77368 5.55459,3.91795 0.88557,0.71738 1.74865,1.34985 2.59193,1.92174 l 0.54057,-0.19011 c -0.71323,-0.48339 -1.46776,-1.02031 -2.26909,-1.62203 -2.82223,-2.11921 -3.62655,-2.80973 -6.01507,-4.27414 -2.38854,-1.4644 -4.09948,-2.36576 -6.5619,-3.1508 0,0 0,0 0,0"
+             id="path7939"
+             inkscape:connector-curvature="0" />
+          <path
+             sodipodi:nodetypes="csccscc"
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+             d="m 237.79963,-407.47878 c 1.92021,0.81706 4.60594,2.19283 6.18775,3.39739 0.81307,0.61916 1.55849,1.07042 2.45046,1.65401 l 0.649,-0.11666 c -0.79831,-0.57637 -1.57177,-1.09435 -2.69653,-1.78394 -2.38854,-1.4644 -4.12826,-2.36576 -6.59068,-3.1508 0,0 0,0 0,0"
+             id="path7941"
+             inkscape:connector-curvature="0" />
+        </g>
+        <g
+           id="g7943"
+           clip-path="url(#clipPath7606)">
+          <path
+             sodipodi:nodetypes="czzzzzzzzzzzzzz"
+             id="path7945"
+             d="m 1056.25,-278.80481 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+             style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7578);enable-background:new"
+             inkscape:connector-curvature="0" />
+          <path
+             sodipodi:nodetypes="czzzzzzzzzzzzzz"
+             id="path7947"
+             d="m 1058.5,-275.42981 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+             style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7594);enable-background:new"
+             inkscape:connector-curvature="0" />
+        </g>
+      </g>
+      <path
+         sodipodi:nodetypes="cscccccccccccc"
+         id="path7949"
+         d="m 628.24553,347.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.29583 116.94091,-84.69468 185.93466,-91.46542 86.92239,-11.0168 184.91267,17.94007 233.37138,95.40128 54.124,75.7333 56.6747,172.53912 80.612,259.52795 29.4378,127.1276 54.7791,256.21414 60.3922,386.85035 -3.0634,78.18185 -8.4263,165.18417 -60.5032,228.13417 -48.0265,50.3574 -122.7864,50.053 -187.06985,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94 -95.73019,-113.47867 -97.2794,-186.01962 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#101414;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8616)"
+         sodipodi:nodetypes="ccccczzzcc"
+         id="path7951"
+         d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 -38.61152,-142.95988 -39.24264,-189.11984 -0.63145,-46.18445 10.83034,-108.60786 30.67767,-158.29647 20.04835,-50.19188 36.89674,-44.84642 42.12489,-92.59293 5.22815,-47.74651 -17.4264,-149.39192 -17.4264,-149.39192 l -55.86144,39.59798 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8940);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czcc"
+         id="path7953"
+         d="m 1010.0312,655.49186 c 0,0 16.7552,37.01806 28.7015,53.95395 11.9462,16.93589 52.7271,56.04605 52.7271,56.04605 l 52.5972,-127.58975"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient8970);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8209)"
+         sodipodi:nodetypes="cccc"
+         id="path7955"
+         d="m 730.31998,536.56864 c 0,8.48528 42.54774,58.46803 42.54774,58.46803 l 12.60659,-28.76954 -55.15433,-29.69849 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8822);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <g
+         clip-path="url(#clipPath3998)"
+         id="g7957"
+         style="display:inline;opacity:1;enable-background:new"
+         transform="translate(450.03125,73.843964)">
+        <g
+           id="g7959"
+           style="filter:url(#filter3677)"
+           transform="translate(-174.03125,62.156036)">
+          <g
+             style="filter:url(#filter3785)"
+             id="g7961">
+            <path
+               style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+               id="path7963"
+               sodipodi:nodetypes="czzzzzzzzzz"
+               inkscape:connector-curvature="0" />
+            <rect
+               style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+               id="rect7965"
+               width="381.83765"
+               height="181.01935"
+               x="343.6539"
+               y="412.60312" />
+          </g>
+          <g
+             style="filter:url(#filter3785)"
+             id="g7967">
+            <path
+               transform="translate(174.03125,-62.156036)"
+               style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+               id="path7969"
+               sodipodi:nodetypes="czzzcc"
+               inkscape:connector-curvature="0" />
+            <rect
+               style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+               id="rect7971"
+               width="207.8894"
+               height="162.63455"
+               x="702.86414"
+               y="344.82138" />
+          </g>
+        </g>
+        <g
+           id="g7973"
+           style="display:inline;opacity:0.18000004;enable-background:new"
+           transform="translate(-174.03125,62.156036)">
+          <g
+             style="filter:url(#filter3785)"
+             id="g7975">
+            <path
+               style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+               id="path7977"
+               sodipodi:nodetypes="czzzzzzzzzz"
+               inkscape:connector-curvature="0" />
+            <rect
+               style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+               id="rect7979"
+               width="381.83765"
+               height="181.01935"
+               x="343.6539"
+               y="412.60312" />
+          </g>
+          <g
+             style="filter:url(#filter3785)"
+             id="g7981">
+            <path
+               transform="translate(174.03125,-62.156036)"
+               style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+               id="path7983"
+               sodipodi:nodetypes="czzzcc"
+               inkscape:connector-curvature="0" />
+            <rect
+               style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+               id="rect7985"
+               width="207.8894"
+               height="162.63455"
+               x="702.86414"
+               y="344.82138" />
+          </g>
+        </g>
+      </g>
+      <path
+         transform="translate(276,136)"
+         sodipodi:nodetypes="cccccscc"
+         clip-path="url(#clipPath8604)"
+         id="path7987"
+         d="M 582.65599,-7.4183011 695.79307,78.848726 804.68752,337.64981 842.87128,545.5392 963.07944,637.46308 c 0,0 -12.72793,-287.08535 -19.799,-313.95541 C 936.20938,296.63761 793.37381,-69.643698 793.37381,-69.643698 L 582.65599,-7.4183011 Z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8802);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzzzzzc"
+         id="path7989"
+         d="m 964.13839,239.599 c 0,0 8.67732,10.89662 24.10715,11.96428 15.42986,1.06766 49.72166,-39.95267 70.17856,-52.14285 20.4793,-12.20353 47.0464,-26.60225 63.9286,-20.35714 16.8821,6.2451 22.1578,26.43609 27.8571,48.03571 5.6994,21.59961 6.7186,61.81389 -2.6785,92.85715 -9.3972,31.04325 -50.5033,73.10375 -65.3572,103.39285 -14.8539,30.2891 -11.6071,39.82143 -11.6071,39.82143"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient8958);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzzzc"
+         id="path7991"
+         d="m 1124.4955,207.63471 c -15.8928,-0.89286 -49.7188,12.10583 -66.0714,24.28572 -16.4386,12.2439 -29.2209,24.1144 -29.2857,52.14285 -0.065,28.20604 13.1191,39.07641 29.1071,46.96429 15.988,7.88789 33.6862,7.11928 51.9643,-11.78571 18.2782,-18.905 14.2857,-111.60715 14.2857,-111.60715 z"
+         style="display:inline;opacity:1;fill:url(#radialGradient3315);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <ellipse
+         clip-path="url(#clipPath4100)"
+         transform="matrix(0.9434749,-0.1239943,0.1440089,1.0957669,451.94827,134.5988)"
+         id="path7993"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:url(#radialGradient3543);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4120);enable-background:accumulate"
+         cx="385"
+         cy="237.00504"
+         rx="86.428574"
+         ry="73.928574" />
+      <path
+         mask="url(#mask3684)"
+         sodipodi:nodetypes="csczzc"
+         id="path7995"
+         d="m 527.60588,407.44884 c 0,0 -122.04144,38.40348 -187.51434,9.63181 -65.47289,-28.77166 -74.37725,-124.71847 -74.37725,-124.71847 0,0 73.38158,-80.50393 129.92078,-83.61476 55.82705,-3.07164 90.57386,20.14332 114.87001,65.85171 24.352,45.81348 17.1008,132.84971 17.1008,132.84971 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3915);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         transform="translate(450.03125,73.843964)"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czcc"
+         id="path7997"
+         d="m 772.17411,393.349 c 0,0 36.21754,-27.38247 51.60714,-35.89286 15.17734,-8.39301 25.71428,-11.60714 35.89285,-11.60714 l -15.53571,66.96428"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient3959);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <circle
+         transform="translate(449.49554,74.915393)"
+         id="path7999"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3933);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         cx="409.28571"
+         cy="306.64789"
+         r="36.25" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8616)"
+         sodipodi:nodetypes="cccccccccc"
+         id="path8001"
+         d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 8.68161,-72.36764 -31.24264,-223.11984 l 17.67767,-69.29647 72.12489,-138.59293 -42.4264,-158.39192 -55.86144,39.59798 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8806);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzcc"
+         id="path8003"
+         d="m 635.21025,581.13004 c -14.14214,12.72792 39.23347,34.58015 76.36753,24.04163 37.13406,-10.53852 104.64487,-35.56437 103.23759,-79.19596 -1.40728,-43.63158 -76.36753,-128.69343 -76.36753,-128.69343 L 635.21025,581.13004 Z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8826);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <circle
+         transform="translate(449.67411,74.915393)"
+         id="path8005"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3991);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         cx="410"
+         cy="306.64789"
+         r="23.214285" />
+      <circle
+         transform="translate(451.99554,73.486821)"
+         id="path8007"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3981);enable-background:accumulate"
+         cx="414.28571"
+         cy="303.07648"
+         r="7.5" />
+      <path
+         sodipodi:nodetypes="czzzczc"
+         id="path8009"
+         d="m 789.31696,478.349 c 0,0 7.02281,19.56859 -1.07143,35 -8.09424,15.43141 -42.32317,38.98822 -67.49999,50 -25.30972,11.06991 -85.473,32.96393 -101.78572,41.96428 -16.46148,9.08243 -18.21428,12.67857 -18.21428,12.67857 0,0 -7.14693,-19.06441 28.74999,-51.7857 36.17211,-32.97214 142.02712,-48.0495 159.82143,-87.85715 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4112);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <g
+         transform="translate(780.74553,74.55825)"
+         id="g8011"
+         style="display:inline;opacity:1;enable-background:new">
+        <path
+           style="display:inline;opacity:1;fill:url(#radialGradient3585);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+           d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+           id="path8013"
+           sodipodi:nodetypes="czzczzzszc"
+           clip-path="url(#clipPath3999)"
+           transform="translate(-329.81481,0)"
+           inkscape:connector-curvature="0" />
+        <ellipse
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4060);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8015"
+           transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-166.62245,2.387362)"
+           cx="183.57143"
+           cy="338.07648"
+           rx="64.715881"
+           ry="134.00607" />
+        <ellipse
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4062);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8017"
+           transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-162.19388,-18.755495)"
+           cx="183.57143"
+           cy="338.07648"
+           rx="64.715881"
+           ry="134.00607" />
+        <path
+           style="display:inline;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3587);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4079);enable-background:new"
+           d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+           id="path8019"
+           sodipodi:nodetypes="czzczzzszc"
+           clip-path="url(#clipPath3999)"
+           transform="translate(-329.81481,3e-7)"
+           inkscape:connector-curvature="0" />
+      </g>
+      <circle
+         transform="translate(452.55663,72.581273)"
+         id="path8021"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         cx="310.71429"
+         cy="398.07648"
+         r="19.704132" />
+      <circle
+         transform="translate(450.55663,72.581273)"
+         id="path8023"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4056);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4082);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4083);enable-background:accumulate"
+         cx="310.71429"
+         cy="398.07648"
+         r="19.704132" />
+      <circle
+         transform="translate(450.55663,72.581273)"
+         id="path8025"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4119);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         cx="310.71429"
+         cy="398.07648"
+         r="19.704132" />
+      <ellipse
+         inkscape:transform-center-y="-3.6935079"
+         inkscape:transform-center-x="-47.231976"
+         transform="matrix(0.9969564,-0.07796167,0.07796167,0.9969564,436.61877,125.29509)"
+         id="path8027"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4868);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4002);enable-background:accumulate"
+         cx="429.56738"
+         cy="377.42877"
+         rx="72.079735"
+         ry="44.547726" />
+      <ellipse
+         inkscape:transform-center-y="-13.056625"
+         inkscape:transform-center-x="-20.955902"
+         transform="matrix(1.4357951,-0.06999104,0.06999104,1.4357951,235.18065,-63.86546)"
+         id="path8029"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4876);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4010);enable-background:accumulate"
+         cx="437.6991"
+         cy="391.21735"
+         rx="36.611931"
+         ry="22.627417" />
+      <g
+         style="display:inline;opacity:1;filter:url(#filter4053);enable-background:new"
+         id="g8031"
+         transform="translate(450.03125,73.843964)">
+        <circle
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4484);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8033"
+           cx="413.66071"
+           cy="401.82648"
+           r="3.2142856" />
+        <circle
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4486);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8035"
+           transform="translate(13.125009,8.1249913)"
+           cx="413.66071"
+           cy="401.82648"
+           r="3.2142856" />
+        <circle
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4488);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8037"
+           transform="translate(32.946437,7.4999913)"
+           cx="413.66071"
+           cy="401.82648"
+           r="3.2142856" />
+        <circle
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4490);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8039"
+           transform="translate(24.910723,-10.267866)"
+           cx="413.66071"
+           cy="401.82648"
+           r="3.2142856" />
+        <circle
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4492);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8041"
+           transform="translate(47.589294,-0.6250087)"
+           cx="413.66071"
+           cy="401.82648"
+           r="3.2142856" />
+      </g>
+      <path
+         sodipodi:nodetypes="ccccccccc"
+         id="path8043"
+         d="m 896.20301,482.92837 c 0.98509,4.35008 4.53707,6.17948 7.38673,7.89182 4.46068,2.51292 6.52016,1.52211 9.15451,-0.75761 1.60195,-1.92117 10.68311,-4.69865 15.59423,-7.07107 4.32961,-1.45891 8.9033,-5.35873 13.38452,-8.33376 3.39514,-1.62724 5.34664,0.35464 7.82868,1.01015 2.94412,0.71661 4.41117,2.17175 6.06092,3.53554 2.39616,1.17519 -0.9279,3.14313 3.283,4.29314 1.19091,0.21794 2.41695,0.57645 3.28299,-0.50507"
+         style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="cccccccccccc"
+         id="path8045"
+         d="m 910.85021,475.35223 c 2.31494,-0.032 3.17778,0.64253 5.49271,-0.82075 3.45564,-3.08113 5.40254,-3.14477 7.95495,-4.41942 3.02657,-1.31523 6.5357,8.15169 10.10153,9.84899 2.39509,-0.82142 1.28914,1.79379 1.45209,2.65165 0.0571,2.64684 2.80694,3.67806 4.35628,5.42957 3.31604,2.25549 7.37523,6.29546 11.11168,5.3033 6.44525,-2.93107 10.27922,-1.28146 16.28871,-7.38674 0.70405,-1.18134 -0.58425,-6.8946 3.09359,-7.19734 2.52399,0.25338 4.16667,0.0502 6.06092,0.56822 5.441,2.11719 7.73778,6.45 14.71034,7.95495 6.1829,0.96639 7.61264,3.79426 13.88959,5.05076"
+         style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccccccccccccc"
+         id="path8047"
+         d="m 876.98133,483.52197 c 2.39858,-0.7938 6.10613,4.1921 8.17313,7.04568 0.59281,2.67952 1.15377,5.48645 0.75761,12.12183 0.78513,2.41754 2.68049,3.03095 4.79823,3.283 3.11745,-0.53678 5.87669,-1.3243 7.3236,-3.03046 1.8716,-1.94167 5.31253,2.39394 8.08122,4.04061 3.61009,1.91209 7.77378,1.97886 11.8693,2.27284 1.70358,-0.23064 2.3704,4.51515 3.28299,8.08123 0.38414,4.37806 -0.88544,6.89569 -1.76776,9.84898 -0.2943,2.49655 2.9885,3.52974 6.31345,4.54569 3.18244,0.74124 6.54424,1.66184 9.09137,1.76777 5.14186,0.87491 8.08874,2.69052 12.12183,4.04061 2.23914,0.81655 3.26019,2.24216 4.54569,3.53553"
+         style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8514)"
+         id="path8049"
+         d="m 332,187.69519 c 0,0 57.5,-25.5 57.5,-28 0,-2.5 5.5,-52 5.5,-52 0,0 91,-48.500001 91.5,-50.500001 0.5,-2 86,-62.0000004 86,-62.0000004 L 386.5,17.195189 311,123.19519 l 21,64.5 z"
+         style="display:inline;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter8814);enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path8051"
+         d="m 1697.2846,722.5514 c 0,0 -115.9655,73.5391 -123.0365,77.78174 -7.0711,4.24264 -230.5169,137.17872 -230.5169,137.17872 l 4.2427,39.59798 216.3747,-100.40917 117.3797,-101.82337 15.5563,-52.3259 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         sodipodi:nodetypes="cccccscccc"
+         clip-path="url(#clipPath8610)"
+         id="path8053"
+         d="m 528.91587,556.85291 c -5.65685,-1.41421 -181.01933,74.95332 -181.01933,74.95332 l -33.94113,181.01934 51.09546,193.94823 257.2031,67.6813 c 0,0 206.47518,152.735 212.13203,148.4924 5.65686,-4.2426 168.2914,-193.7473 168.2914,-193.7473 L 842.87128,845.35248 796.20224,667.16157 528.91587,556.85291 Z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzzzzzczczczczzzc"
+         id="path8055"
+         d="m 1097.6433,613.88997 c 0,0 22.6195,-6.50681 35.7427,-5.87273 13.1233,0.63409 30.6416,1.93862 43.7089,12.18619 13.0673,10.24756 25.0677,27.14007 34.1124,58.36965 9.0446,31.22958 1.6983,99.25201 -6.1761,143.34735 -7.8743,44.09534 -28.2651,106.11298 -45,140 -16.7348,33.88702 -49.7977,77.49517 -60.5694,89.87617 -11.3642,13.062 -56.2059,36.4262 -79.4306,42.2667 5.3034,-10.6066 48.8998,-50.5889 35,-60.7143 -14.0189,-10.2123 -45.76,45.9824 -84.2931,29.0332 21.38231,-13.1321 41.7794,-51.1861 34.0406,-66.59448 -7.84024,-15.61039 -30.70492,48.75758 -93.53553,37.01288 30.05204,-27.5267 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.2932 -60.46175,54.2932 0,0 -2.8219,-41.70123 13.7732,-68.60737 16.63935,-26.97787 79.65297,-81.61527 99.55308,-111.70342 19.9002,-30.08814 33.6126,-66.00902 42.1355,-92.51794 8.5228,-26.50892 15.8009,-77.09954 15.8009,-77.09954"
+         style="display:inline;opacity:1;fill:#0c0c0c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         sodipodi:nodetypes="cccccccccc"
+         clip-path="url(#clipPath8622)"
+         id="path8057"
+         d="m 770.74639,609.17881 -50.91169,97.58074 -79.90307,111.01576 34.64824,71.41778 42.42641,79.19597 72.12489,-45.25484 14.14214,-192.33305 21.2132,-138.59292 -14.14214,-90.15612 -39.59798,107.12668 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8818);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         sodipodi:nodetypes="cczcccccc"
+         clip-path="url(#clipPath8906)"
+         id="path8059"
+         d="m 295,846.19519 6.64488,-68.92285 c 0,0 90.31951,89.00457 162.35512,122.92285 72.03561,33.91828 308,62 308,62 l 154,-26 -36,162.00001 -286,26 -298,-89 -11,-189.00001 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         clip-path="url(#clipPath3602)"
+         sodipodi:nodetypes="cccccccccccc"
+         id="path8061"
+         d="m 405.79629,845.99023 74.95332,65.05383 2.49963,16.8804 19.40336,10.15891 6.49204,23.05109 31.70905,-8.3711 14.84924,48.08324 c 12.25652,12.7279 89.79344,-113.1097 55.86143,38.1838 l -60.81118,16.2635 -89.20292,-94.69286 -62.82503,-53.79963 7.07106,-60.81118 z"
+         style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3587);enable-background:new"
+         transform="translate(450.03125,73.843964)"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzzzzzzzcc"
+         id="path8063"
+         d="m 1159.317,918.349 c 54.2857,-1.42857 126.035,-15.05199 170,-26.78572 44.0527,-11.75714 125.8863,-36.34724 175.357,-57.85714 49.3393,-21.45272 113.6038,-59.2816 154.2859,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7142,-33.57143 8.3691,22.36779 -16.4069,56.32562 -37.8571,81.07143 -21.6042,24.9234 -52.7314,52.70533 -98.9287,89.28571 -46.1973,36.58038 -156.0825,101.58463 -212.8571,128.5714 -57.066,27.1254 -128.2033,58.2385 -172.1428,72.5001 -43.9395,14.2616 -131.4286,31.0714 -131.4286,31.0714 L 1159.317,918.349 Z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         clip-path="url(#clipPath3992)"
+         sodipodi:nodetypes="czczzcc"
+         id="path8065"
+         d="m 1241.5965,652.95007 c 0,0 -64.7215,54.33706 -145.6639,98.99494 -82.0244,45.25484 -284.25704,93.3381 -284.25704,93.3381 0,0 -15.10137,21.05196 45.25489,28.28428 60.35626,7.23232 224.08195,-53.30069 278.60015,-96.16654 54.5182,-42.86585 120.2081,-111.72286 120.2081,-111.72286 l -14.1422,-12.72792 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:url(#linearGradient3666);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3779);enable-background:accumulate"
+         transform="translate(450.03125,73.843964)"
+         inkscape:connector-curvature="0" />
+      <g
+         clip-path="url(#clipPath3986)"
+         id="g8067"
+         style="display:inline;opacity:1;enable-background:new"
+         transform="translate(450.03125,73.843964)">
+        <g
+           id="g8069"
+           style="filter:url(#filter3677)"
+           transform="translate(-174.03125,62.156036)">
+          <g
+             id="g8071"
+             style="filter:url(#filter3785)">
+            <path
+               transform="translate(174.03125,-62.156036)"
+               style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+               id="path8073"
+               sodipodi:nodetypes="czzccccc"
+               inkscape:connector-curvature="0" />
+            <rect
+               style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+               id="rect8075"
+               width="333.75412"
+               height="309.71277"
+               x="1197.8389"
+               y="486.14224" />
+          </g>
+        </g>
+        <g
+           id="g8077"
+           style="display:inline;opacity:0.18000004;enable-background:new"
+           transform="translate(-174.03125,62.156036)">
+          <g
+             id="g8079"
+             style="filter:url(#filter3785)">
+            <path
+               transform="translate(174.03125,-62.156036)"
+               style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+               id="path8081"
+               sodipodi:nodetypes="czzccccc"
+               inkscape:connector-curvature="0" />
+            <rect
+               style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+               id="rect8083"
+               width="333.75412"
+               height="309.71277"
+               x="1197.8389"
+               y="486.14224" />
+          </g>
+        </g>
+      </g>
+      <path
+         sodipodi:nodetypes="cssssccccccssssssssccssssssccssssc"
+         clip-path="url(#clipPath3722)"
+         id="path8085"
+         d="m 1264.1875,605 c -4.4911,0.73268 -8.157,3.45509 -11.9375,6.40625 -10.0813,7.86976 -28.1695,34.42524 -48.0312,50.46875 -39.8674,32.20316 -103.996,69.97701 -152.5626,91.09375 -48.614,21.13738 -130.54122,45.81801 -174.31245,57.5 -43.39821,11.58246 -115.04403,25.13107 -168.25,26.53125 l -4.5625,0.125 -2,4.125 -92.84375,192.125 -6.5,13.4688 14.65625,-2.8438 c 0,0 87.26968,-16.6514 132.34375,-31.2812 44.7252,-14.51667 115.79086,-45.66683 173.03125,-72.87505 C 980.82199,912.46306 1090.1551,847.86412 1137.5,810.375 c 46.3608,-36.70982 77.8049,-64.71682 99.9375,-90.25 10.9011,-12.576 22.7448,-27.53144 31.0313,-42.75 8.2864,-15.21856 19.1597,-44.21808 13.6874,-58.84375 -1.2177,-3.25474 -2.5514,-6.0613 -4.5937,-8.5 -2.0423,-2.4387 -8.4747,-1.57199 -8.5625,-5.03125 -0.2098,-8.26482 -3.3155,-0.24423 -4.8125,0 z m 2.1563,15.21875 c 0.4148,0.58574 1.0311,1.55766 1.7812,3.5625 2.8968,7.74213 -1.4407,31.89875 -8.8125,45.4375 -7.3718,13.53875 -22.6384,28.92394 -33.1875,41.09375 -21.0754,24.31356 -51.9037,51.86156 -97.9375,88.3125 -45.0496,35.67159 -155.46033,101.09459 -211.40625,127.6875 -56.89173,27.04249 -128.09616,58.1184 -171.25,72.125 -36.36491,11.8031 -95.84471,23.8338 -115.71875,27.7813 L 714.09375,851.75 c 54.70691,-2.0493 123.79259,-15.21635 167.125,-26.78125 44.33422,-11.83225 126.07865,-36.33633 176.40625,-58.21875 50.112,-21.78871 112.5344,-61.16816 154.0312,-94.6875 20.6464,-16.67721 41.7449,-42.54588 49.8126,-48.84375 2.437,-1.90242 4.0806,-2.6358 4.875,-3 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.83300003;fill:#050505;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter8225);enable-background:accumulate"
+         transform="translate(450.03125,73.843964)"
+         inkscape:connector-curvature="0" />
+      <g
+         inkscape:transform-center-y="-12.859654"
+         inkscape:transform-center-x="-185.09603"
+         transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+         mask="url(#mask7704)"
+         id="g8087"
+         style="display:inline;opacity:1;enable-background:new">
+        <path
+           sodipodi:nodetypes="ccssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssscccccssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssssssssc"
+           id="path8089"
+           d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 -12.4759,3.49189 7.92966,19.27772 c -0.59163,1.97357 12.54624,-4.73836 12.54624,-4.73836 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+           style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           transform="translate(0.08004571,-0.03125)"
+           inkscape:connector-curvature="0" />
+        <g
+           id="g8091"
+           clip-path="url(#clipPath7421)">
+          <path
+             sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc"
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7001);enable-background:new"
+             d="m 1107.409,-284.04961 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88717,-0.50701 -5.875,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0725 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0774 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,10e-6 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 10e-6,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0532 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 10e-6,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0728,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 10e-6,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0773,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.4497,-0.12571 6.375,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -10e-5,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -1e-4,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+             id="path8093"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6949);enable-background:new"
+             d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+             id="path8095"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6961);enable-background:new"
+             d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+             id="path8097"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6957);enable-background:new"
+             d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+             id="path8099"
+             inkscape:connector-curvature="0" />
+          <path
+             sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc"
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6997);enable-background:new"
+             d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.4428,3.93956 1.5794,5.38995 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.9442,0.42864 -1.2366,0.49452 0.531,0.18589 0.8908,0.21322 0.9524,1.05768 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.9524,0.18199 -1.288,0.0511 z"
+             id="path8101"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6953);enable-background:new"
+             d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+             id="path8103"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6993);enable-background:new"
+             d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+             id="path8105"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6989);enable-background:new"
+             d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+             id="path8107"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6985);enable-background:new"
+             d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+             id="path8109"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6965);enable-background:new"
+             d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+             id="path8111"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6981);enable-background:new"
+             d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+             id="path8113"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6977);enable-background:new"
+             d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+             id="path8115"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6973);enable-background:new"
+             d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+             id="path8117"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6969);enable-background:new"
+             d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+             id="path8119"
+             inkscape:connector-curvature="0" />
+          <g
+             style="fill:#ffffff;fill-opacity:1;filter:url(#filter7345)"
+             id="g8121">
+            <path
+               style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+               d="m 744.9375,-212.11731 c 0,0 7.22229,-3.22318 9.0625,-3.5 1.84021,-0.27682 3.35225,-0.003 6,0.5625 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 5.3125,3.5625 5.3125,3.5625 0,0 -7.14644,-2.78019 -10.1875,-3.5625 -3.04106,-0.78231 -7.64461,-2.08374 -10.375,-2.3125 -2.73039,-0.22876 -11,1.875 -11,1.875 z"
+               id="path8123"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 735.46875,-206.95416 c 0,0 3.65979,-2.22318 5.5,-2.5 1.84021,-0.27682 3.66475,0.24677 6.3125,0.8125 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 6.5625,2.125 6.5625,2.125 0,0 -8.39644,-1.34269 -11.4375,-2.125 -3.04106,-0.78231 -7.95711,-2.33374 -10.6875,-2.5625 -2.73039,-0.22876 -7.4375,0.875 -7.4375,0.875 z"
+               id="path8125"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 759.85042,-217.61116 c 0,0 8.5437,-3.29857 10.39778,-3.45786 1.85409,-0.1593 3.64166,0.4792 6.2481,1.21208 2.60644,0.73288 8.57724,2.76594 10.95036,4.07925 2.37312,1.31331 6.41417,2.53782 6.41417,2.53782 0,0 -8.29413,-1.87365 -11.27931,-2.84767 -2.98519,-0.97402 -7.79269,-2.83478 -10.50302,-3.23662 -2.71033,-0.40184 -12.22808,1.713 -12.22808,1.713 z"
+               id="path8127"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 775.19813,-223.2266 c 0,0 7.77133,-2.78244 9.62831,-2.90349 1.85697,-0.12104 3.631,0.55417 6.22178,1.34062 2.59077,0.78645 8.5184,2.94217 10.86394,4.30412 2.34555,1.36195 6.36049,2.6695 6.36049,2.6695 0,0 -8.25373,-2.04423 -11.21821,-3.07958 -2.96447,-1.03535 -7.73259,-2.99481 -10.43406,-3.45243 -2.70147,-0.45763 -11.42225,1.12126 -11.42225,1.12126 z"
+               id="path8129"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 789.64298,-227.95417 c 0,0 8.68256,-3.52031 10.54154,-3.60535 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.3006,1.78871 -12.3006,1.78871 z"
+               id="path8131"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.852145"
+               inkscape:transform-center-y="-4.3190906"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 804.49513,-233.32948 c 0,0 7.80756,-2.58281 9.66654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -11.4256,0.85121 -11.4256,0.85121 z"
+               id="path8133"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.852145"
+               inkscape:transform-center-y="-4.3190906"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 819.55763,-237.57948 c 0,0 8.55756,-2.58281 10.41654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.1756,0.85121 -12.1756,0.85121 z"
+               id="path8135"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.852145"
+               inkscape:transform-center-y="-4.3190906"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 836.23395,-242.60125 c 0,0 6.96702,-1.98723 8.82784,-1.96757 1.86081,0.0197 3.57873,0.82702 6.10265,1.80705 2.52393,0.98 8.27166,3.57758 10.50756,5.11291 2.2359,1.53535 6.14053,3.14261 6.14053,3.14261 0,0 -8.07561,-2.66222 -10.95336,-3.91866 -2.87774,-1.25645 -7.48412,-3.5707 -10.14328,-4.23121 -2.65915,-0.66049 -10.48194,0.0549 -10.48194,0.0549 z"
+               id="path8137"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.64141"
+               inkscape:transform-center-y="-4.9269042"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 850.73028,-246.00461 c 0,0 7.68784,-2.02768 9.54782,-1.96854 1.85997,0.0592 3.56038,0.90279 6.06293,1.93616 2.50255,1.03334 8.19387,3.75232 10.39668,5.33475 2.20282,1.58245 6.07245,3.2722 6.07245,3.2722 0,0 -8.01729,-2.83298 -10.86772,-4.15022 -2.85043,-1.31723 -7.40666,-3.72872 -10.0512,-4.4455 -2.64454,-0.71678 -11.16096,0.0211 -11.16096,0.0211 z"
+               id="path8139"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.55068"
+               inkscape:transform-center-y="-5.1542119"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 864.82496,-249.21081 c 0,0 8.16952,-1.96906 10.02688,-1.85396 1.85735,0.11512 3.53158,1.00956 6.0019,2.11779 2.47031,1.10821 8.0772,3.99727 10.23138,5.64531 2.15418,1.64804 5.9712,3.45352 5.9712,3.45352 0,0 -7.92839,-3.07306 -10.73787,-4.4755 -2.80949,-1.40244 -7.29106,-3.94999 -9.91283,-4.74606 -2.62176,-0.79606 -11.58066,-0.1411 -11.58066,-0.1411 z"
+               id="path8141"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.41151"
+               inkscape:transform-center-y="-5.4740887"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 881.38485,-251.60282 c 0,0 8.08536,-1.90809 9.93837,-1.73664 1.853,0.17147 3.4993,1.11633 5.93482,2.29908 2.43553,1.18271 7.95209,4.2407 10.05523,5.95339 2.10314,1.7127 5.86357,3.63326 5.86357,3.63326 0,0 -7.8314,-3.3124 -10.597,-4.7995 -2.76561,-1.48712 -7.16775,-4.16959 -9.76414,-5.04491 -2.59637,-0.87531 -11.43085,-0.30468 -11.43085,-0.30468 z"
+               id="path8143"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.258805"
+               inkscape:transform-center-y="-5.79376"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 896.58415,-254.34724 c 0,0 7.64166,-1.4277 9.49547,-1.26515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-0.76897 -10.99774,-0.76897 z"
+               id="path8145"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 911.45328,-255.98544 c 0,0 8.64166,-1.5527 10.49547,-1.39015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.99774,-0.64397 -11.99774,-0.64397 z"
+               id="path8147"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 927.70328,-258.29794 c 0,0 7.64166,-0.8652 9.49547,-0.70265 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-1.33147 -10.99774,-1.33147 z"
+               id="path8149"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 942.82828,-259.48544 c 0,0 8.57916,-1.4902 10.43297,-1.32765 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.93524,-0.70647 -11.93524,-0.70647 z"
+               id="path8151"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 959.07828,-261.54794 c 0,0 7.82916,-0.8027 9.68297,-0.64015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.18524,-1.39397 -11.18524,-1.39397 z"
+               id="path8153"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 974.45328,-262.79794 c 0,0 8.39166,-1.1777 10.24547,-1.01515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08376,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.84721,-3.27474 -10.61993,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.74774,-1.01897 -11.74774,-1.01897 z"
+               id="path8155"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 990.64078,-264.86044 c 0,0 6.89166,-0.9902 8.74547,-0.82765 1.85385,0.16256 3.50465,1.0995 5.94575,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.60053,-0.86282 -10.24772,-1.20647 -10.24772,-1.20647 z"
+               id="path8157"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1007.7658,-265.79794 c 0,0 6.8291,-1.1777 8.683,-1.01515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -10.1852,-1.01897 -10.1852,-1.01897 z"
+               id="path8159"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1023.8908,-267.79794 c 0,0 6.0791,-0.4277 7.933,-0.26515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.4352,-1.76897 -9.4352,-1.76897 z"
+               id="path8161"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1039.7033,-269.17294 c 0,0 6.4541,-0.6777 8.308,-0.51515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.8102,-1.51897 -9.8102,-1.51897 z"
+               id="path8163"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.28378"
+               inkscape:transform-center-y="-5.7433893"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1055.2718,-271.03319 c 0,0 5.4976,-0.90945 7.3578,-0.85348 1.8601,0.056 3.5619,0.89674 6.0661,1.92586 2.5044,1.0291 8.2003,3.7384 10.4058,5.31709 2.2055,1.57871 6.078,3.2619 6.078,3.2619 0,0 -8.022,-2.81939 -10.8748,-4.13178 -2.8526,-1.31238 -7.4129,-3.71613 -10.0587,-4.42843 -2.6457,-0.71228 -8.9742,-1.09116 -8.9742,-1.09116 z"
+               id="path8165"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.55813"
+               inkscape:transform-center-y="-5.1360724"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1072.7007,-273.48537 c 0,0 4.5472,-1.15581 6.408,-1.18621 1.8607,-0.0304 3.5996,0.73049 6.1489,1.64231 2.5494,0.91177 8.3649,3.35386 10.6414,4.8285 2.2763,1.47468 6.2227,2.97636 6.2227,2.97636 0,0 -8.1442,-2.44411 -11.0547,-3.62272 -2.9105,-1.1786 -7.5774,-3.36815 -10.2534,-3.95691 -2.6759,-0.58875 -8.1129,-0.68133 -8.1129,-0.68133 z"
+               id="path8167"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.74758"
+               inkscape:transform-center-y="-4.6370147"
+               inkscape:connector-curvature="0" />
+            <path
+               style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               d="m 1087.1585,-276.5244 c 0,0 5.96,-1.77355 7.8202,-1.83024 1.86,-0.0567 3.6096,0.67955 6.1715,1.55525 2.562,0.87566 2.5226,0.85713 5.3335,1.49015 2.7969,0.62986 7.0767,1.51313 7.0767,1.51313 0,0 -3.6155,-0.0163 -6.7923,-0.46614 -3.1155,-0.44119 -7.3743,-1.69825 -10.0584,-2.24913 -2.6839,-0.55088 -9.5512,-0.013 -9.5512,-0.013 z"
+               id="path8169"
+               sodipodi:nodetypes="czzzczzc"
+               inkscape:transform-center-x="13.79933"
+               inkscape:transform-center-y="-4.4842392"
+               inkscape:connector-curvature="0" />
+            <path
+               style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+               d="m 1099.25,-279.92981 c 0.1612,0.26862 11.2081,-4.60046 12.1875,-4.6875 0.9794,-0.087 2,3.125 2,3.125 0,0 -0.7751,-1.50434 -2.875,-1.0625 -2.0999,0.44184 -11.3009,2.67141 -11.3125,2.625 z"
+               id="path8171"
+               sodipodi:nodetypes="czczc"
+               inkscape:connector-curvature="0" />
+          </g>
+          <path
+             sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc"
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7333);enable-background:new"
+             d="m 1107.4532,-284.0938 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88718,-0.50701 -5.87501,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0726 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0775 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,1e-5 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 1e-5,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0533 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 1e-5,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0727,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 1e-5,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0772,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.44971,-0.12571 6.37501,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -1e-4,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -10e-5,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+             id="path8173"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7285);enable-background:new"
+             d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+             id="path8175"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7289);enable-background:new"
+             d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+             id="path8177"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7293);enable-background:new"
+             d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+             id="path8179"
+             inkscape:connector-curvature="0" />
+          <path
+             sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc"
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7337);enable-background:new"
+             d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.2218,3.85117 1.3584,5.30156 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.7232,0.51703 -1.0156,0.58291 0.531,0.18589 0.6698,0.12483 0.7314,0.96929 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.7314,0.27038 -1.067,0.13944 z"
+             id="path8181"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7297);enable-background:new"
+             d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+             id="path8183"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7301);enable-background:new"
+             d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+             id="path8185"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7305);enable-background:new"
+             d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+             id="path8187"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7309);enable-background:new"
+             d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+             id="path8189"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7313);enable-background:new"
+             d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+             id="path8191"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7317);enable-background:new"
+             d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+             id="path8193"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7321);enable-background:new"
+             d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+             id="path8195"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7329);enable-background:new"
+             d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+             id="path8197"
+             inkscape:connector-curvature="0" />
+          <path
+             style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7325);enable-background:new"
+             d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+             id="path8199"
+             inkscape:connector-curvature="0" />
+        </g>
+      </g>
+      <path
+         sodipodi:nodetypes="ccccccccc"
+         id="path8201"
+         d="m 863.87812,475.6679 c 1.64212,-3.218 3.51781,-5.73529 4.86136,-9.84898 0.79872,-3.65789 3.31204,-2.03073 7.26047,-8.3969 1.40193,-2.2395 5.47653,0.39136 8.9651,-2.39911 1.27072,-0.80319 2.88488,-0.40431 4.48256,-0.0631 3.76539,1.31896 5.82576,3.70355 8.33376,5.80837 6.13906,5.97023 20.53414,7.94327 23.48604,6.31346 1.43405,-2.90474 7.88128,-5.40888 12.37437,-11.11168 0.74811,-1.12267 11.72936,-8.74446 14.64721,-6.56599"
+         style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccccccccccc"
+         id="path8203"
+         d="m 888.50059,465.25071 c 7.36341,-3.23297 13.8109,-8.9084 20.70813,-13.38452 3.31057,-1.96954 6.86983,3.21601 10.796,3.59866 2.29773,-0.21813 3.7129,1.20259 5.68211,1.6415 5.15636,1.31779 2.39793,3.86488 9.97526,6.43972 6.15561,1.7204 8.9074,-6.79847 14.89975,-7.3236 4.87739,-0.50299 8.09892,-0.31603 11.61675,-0.25254 3.92696,0.13889 4.07855,-3.4976 6.06092,-5.3033 2.98056,-2.80522 7.15561,-1.84972 10.14485,-4.7409 1.01754,-1.38468 1.95458,-3.01085 2.73459,-5.10809 0.88201,-2.00034 3.04006,0.30598 4.79823,1.26269"
+         style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path8994"
+         d="m 403.27922,1056.3058 56.56854,-42.4264 72.12489,14.1421 -46.66904,52.3259 -53.74012,7.0711 -28.28427,-31.1127 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9048);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path4189"
+         d="m 542.27183,1060.5719 c -1.40727,18.8012 -1.1449,32.751 2.08174,49.3033 3.22666,16.5523 16.40609,45.9073 20.33441,63.1837 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1483 -15.31761,12.9774 -42.05128,21.5989 -67.83231,15.7337 -25.78105,-5.8652 -69.54907,-49.2234 -88.59019,-70.2283 -19.11214,-21.0833 -63.76086,-93.8506 -77.93853,-124.2758 -14.17767,-30.4251 -12.65961,-36.7186 -8.11972,-45.52972 -9.36672,-24.5205 -12.41371,-50.06681 -33.71245,-75.57664 30.32547,3.11444 43.88028,26.95633 60.12568,47.13975 -5.52989,-48.07603 -18.05471,-64.4165 -28.37395,-90.7243 29.9943,6.08165 50.57936,31.87239 63.97979,72.7125 9.55415,-3.91791 18.23776,-9.37294 30.18741,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.68725,-101.06994 53.44196,5.67033 83.65702,80.63932 78.97142,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34702 -21.04781,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38966,85.80578 6.10287,20.3689 1.51881,38.70051 1.51881,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24138 -3.53269,59.10328 -4.94582,77.98328 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)"
+         clip-path="url(#clipPath3631)"
+         sodipodi:nodetypes="cccccccccccccccccccccc"
+         id="path4191"
+         d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)"
+         sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
+         clip-path="url(#clipPath3677)"
+         id="path4193"
+         d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.84562,77.83981 -43.7404,101.4864 -6.60491,13.1304 -18.52833,57.4859 -31.12335,76.2465 -12.59502,18.7605 -28.53137,39.7673 -37.17204,44.4209 -21.49052,11.5742 -44.55594,25.5059 -60.61889,18.0895 -14.37486,-6.637 -23.03969,-21.1927 -23.81407,-37.7433 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+         style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898);enable-background:new"
+         inkscape:connector-curvature="0" />
+      <g
+         transform="translate(276,136)"
+         clip-path="url(#clipPath3622)"
+         id="g3617"
+         style="display:inline;enable-background:new">
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024);enable-background:accumulate"
+           d="m -15.66751,843.48852 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+           id="path4195"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-52.200498,74.09707)"
+           inkscape:connector-curvature="0" />
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020);enable-background:accumulate"
+           d="m 118.70648,859.93048 -55.154328,-46.66904 -43.84062,36.76955 33.94113,53.74011 -13.596814,85.46203 -39.44536579,28.29217 -41.01220021,11.3137 -2.82842,46.669 56.56854,25.4559 18.943987,-69.65 23.45655,-58.85663 46.347541,-72.61491 16.62,-39.91188 z"
+           id="path4197"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-46.92842,75.511284)"
+           sodipodi:nodetypes="ccccccccccccc"
+           inkscape:connector-curvature="0" />
+      </g>
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,229.07158,211.51128)"
+         id="path4199"
+         d="m -70.82184,932.58397 60.81118,-26.87005 100.40916,31.1127 -63.63961,31.11269 -82.02438,-16.97056 -15.55635,-18.38478 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)"
+         clip-path="url(#clipPath4177)"
+         sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+         id="path4201"
+         d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -7.17516,44.14234 -8.78421,66.21911 -8.78379,2.34171 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 4.66299,24.40472 3.63165,36.35334 -7.06405,45.03355 -22.14231,87.36194 -35.95355,130.6798 -12.07476,32.9493 -27.3742,58.8525 -47.88808,87.2015 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -44.20676,10.8769 -62.59956,0.046 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 4.93886,-28.5121 4.4106,-43.4918 -0.53824,-15.2629 -2.29135,-30.5647 -6.54261,-46.8663 -4.25126,-16.30162 -9.04325,-24.91794 -16.11906,-41.57338 -7.24111,-17.04456 -15.07015,-36.74863 -18.20542,-56.28842 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+         style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4105);enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)"
+         clip-path="url(#clipPath3631)"
+         sodipodi:nodetypes="cccccccc"
+         id="path4203"
+         d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)"
+         clip-path="url(#clipPath3631)"
+         sodipodi:nodetypes="cccccccc"
+         id="path4205"
+         d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <g
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8338)"
+         style="display:inline;filter:url(#filter8333);enable-background:new"
+         id="g8317">
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+           id="path4209"
+           sodipodi:nodetypes="ccccc"
+           clip-path="none"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+           inkscape:connector-curvature="0" />
+        <rect
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="rect8315"
+           width="182"
+           height="177"
+           x="-55"
+           y="757.19519" />
+      </g>
+      <g
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8359)"
+         style="display:inline;filter:url(#filter8354);enable-background:new"
+         id="g8346">
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+           id="path4207"
+           sodipodi:nodetypes="ccccccc"
+           clip-path="none"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+           inkscape:connector-curvature="0" />
+        <rect
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="rect8344"
+           width="165"
+           height="176"
+           x="-22"
+           y="696.19519" />
+      </g>
+      <path
+         sodipodi:nodetypes="czzzzzzcccccccccczczz"
+         id="path8848"
+         d="m 1036.164,1071.8338 c 6.7941,18.9028 10.4937,33.2997 11.8903,51.2119 1.3966,17.9123 -3.7827,51.8008 -2.9005,70.6561 0.8818,18.8452 8.1337,40.099 27.3446,48.9689 19.4189,8.9658 49.3193,10.2113 74.1199,-3.1456 24.8006,-13.357 57.401,-70.3255 70.9742,-97.3087 13.6239,-27.0839 38.7611,-114.4974 44.6608,-149.76859 5.8998,-35.27121 2.5506,-41.30077 -4.6174,-49.05549 2.6403,-27.84015 -1.4998,-54.93543 13.1096,-87.18618 -30.249,11.8257 -37.3823,40.1607 -48.3189,65.50508 -8.0009,-50.93293 0.2092,-71.27319 3.3189,-101.21936 -29.0647,14.77791 -42.8615,47.11402 -45,92.85714 -10.9239,-1.3042 -21.3914,-4.43423 -33.5714,-0.71429 -0.264,-46.02334 -1.4635,-76.88941 8.9106,-114.20649 -53.2554,21.02686 -62.9472,106.5941 -56.0535,112.77792 -10.8828,0.535 -21.371,-1.2973 -32.8571,2.85715 0.6389,-42.57135 -0.2605,-84.90861 -30,-122.85715 0,0 -30.958,80.92234 -31.4286,103.57143 -0.4705,22.64909 9.4516,40.16588 9.4516,40.16588 0,0 -8.568,36.74051 -6.2986,58.23223 2.2959,21.74142 20.4429,59.67622 27.2655,78.65812 z"
+         style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath3631)"
+         sodipodi:nodetypes="cccccccccccccccccccccc"
+         id="path3635"
+         d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
+         clip-path="url(#clipPath3677)"
+         id="path3669"
+         d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.79272,123.1659 -43.6875,146.8125 -6.60491,13.1304 -18.02998,33.8957 -30.625,52.6563 -12.59502,18.7605 -27.35933,35.5338 -36,40.1874 -21.49052,11.5742 -48.7808,10.2602 -64.84375,2.8438 -14.37486,-6.637 -20.53812,-23.4494 -21.3125,-40 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+         style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898);enable-background:new"
+         transform="translate(450.03125,73.843964)"
+         inkscape:connector-curvature="0" />
+      <g
+         transform="translate(276,136)"
+         clip-path="url(#clipPath3636)"
+         id="g3628">
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024);enable-background:accumulate"
+           d="m 824.48651,818.48242 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+           id="path8988"
+           inkscape:connector-curvature="0" />
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020);enable-background:accumulate"
+           d="m 964.49365,855.25197 -55.15433,-46.66904 -43.84062,36.76955 33.94113,53.74011 7.07106,66.46804 -50.91168,35.35537 -41.0122,11.3137 -2.82842,46.669 56.56854,25.4559 63.63961,-76.3676 24.04163,-94.75227 8.48528,-57.98276 z"
+           id="path8990"
+           inkscape:connector-curvature="0" />
+      </g>
+      <path
+         id="path8992"
+         d="m 1045.3322,1043.5779 60.8112,-26.8701 100.4091,31.1127 -63.6396,31.1127 -82.0244,-16.9706 -15.5563,-18.3847 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         clip-path="url(#clipPath4177)"
+         sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+         id="path4149"
+         d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -3.2972,44.17323 -4.90625,66.25 -1.31238,1.37679 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 3.12294,24.83149 2.0916,36.78011 -7.06405,45.03355 -21.76553,88.37934 -35.57677,131.69714 -12.07476,32.9493 -30.7197,63.08 -51.23358,91.429 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -43.57595,5.1744 -61.96875,-5.6562 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 2.37211,-27.8008 7.91747,-42.8053 5.54535,-15.0045 2.47105,-31.3317 -1.78021,-47.6333 -4.25126,-16.3016 -12.17903,-26.26002 -21.82158,-42.20417 -9.64255,-15.94415 -17.6369,-36.03734 -20.77217,-55.57713 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+         style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4185);enable-background:new"
+         transform="translate(450.03125,73.843964)"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath3631)"
+         sodipodi:nodetypes="cccccccc"
+         id="path3902"
+         d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <path
+         transform="translate(276,136)"
+         clip-path="url(#clipPath3631)"
+         sodipodi:nodetypes="cccccccc"
+         id="path4135"
+         d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+         style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141);enable-background:accumulate"
+         inkscape:connector-curvature="0" />
+      <g
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8392)"
+         style="filter:url(#filter8379)"
+         id="g8367">
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+           id="path4145"
+           sodipodi:nodetypes="ccccccc"
+           clip-path="none"
+           inkscape:connector-curvature="0" />
+        <rect
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="rect8365"
+           width="123.03658"
+           height="172.53406"
+           x="877.51953"
+           y="650.19098" />
+      </g>
+      <g
+         transform="translate(276,136)"
+         clip-path="url(#clipPath8417)"
+         style="filter:url(#filter8404)"
+         id="g8400">
+        <path
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+           id="path4147"
+           sodipodi:nodetypes="ccccc"
+           clip-path="none"
+           inkscape:connector-curvature="0" />
+        <rect
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="rect8398"
+           width="142.12846"
+           height="125.1579"
+           x="924.89569"
+           y="677.06104" />
+      </g>
+    </g>
+    <rect
+       id="rect6247"
+       width="440"
+       height="376"
+       x="548"
+       y="205.32275"
+       style="opacity:1;fill:none;fill-opacity:1;stroke:#f8d615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <rect
+       style="opacity:1;fill:none;fill-opacity:1;stroke:#f83615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect6676"
+       width="1684"
+       height="1292"
+       x="56"
+       y="53.322754" />
+    <rect
+       style="opacity:1;fill:url(#pattern5557);fill-opacity:1;stroke:#f815bb;stroke-width:13.34657478;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect6731"
+       width="522.56604"
+       height="1182.4679"
+       x="3493.3721"
+       y="87.178711" />
+    <g
+       id="g7477"
+       transform="matrix(0.53474256,0,0,1,1882.7509,3.0962157)">
+      <rect
+         y="99.705269"
+         x="3039.4895"
+         height="902.66437"
+         width="818.51605"
+         id="rect6979"
+         style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#f8d615;stroke-width:18;stroke-linejoin:miter;stroke-miterlimit:1;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <g
+         clip-path="url(#clipPath6975)"
+         id="g4303-9"
+         style="display:inline;enable-background:new"
+         transform="matrix(1.8806916,0,0,2.3994874,1997.8763,-394.32602)">
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter11361-3);enable-background:new"
+           d="m 304.64285,526.6479 c -10,0.35715 -18.21428,2.85714 -18.21428,2.85714 l 7.5,6.07143 10.35714,3.57143 16.07143,0.35714 22.5,-5.35714 7.85714,1.07143 20.35715,-2.14286 -10.35715,6.78572 c 5.45923,-1.02361 17.39329,3.56911 9.64286,5.35714 -1.74,0.40142 13.92857,-4.64285 13.92857,-4.64285 l 2.5,-4.64287 3.57143,-9.28571 11.42857,0 18.21428,-4.64286 3.57144,-4.99999 -16.07144,1.07142 -12.14285,2.14286 -14.64286,-5 -70.6921,16.70774 -5.37933,-5.27917 z"
+           id="path10326-6"
+           sodipodi:nodetypes="cccccccccsccccccccccc"
+           transform="matrix(10.726753,0,0,10.726753,-2882.1235,-4565.4583)"
+           inkscape:export-filename="/home/cheeseness/Documents/LCA09/mascot/tuz_new.png"
+           inkscape:export-xdpi="142.10527"
+           inkscape:export-ydpi="142.10527" />
+        <g
+           style="display:inline;opacity:1;enable-background:new"
+           id="g7882-9"
+           transform="matrix(0.71084,-0.1937433,0.262963,0.9648058,503.68027,136.48399)">
+          <path
+             inkscape:connector-curvature="0"
+             sodipodi:nodetypes="czzzzcc"
+             id="path7876-3"
+             d="m 245.12255,100.05344 c 0,0 -47.12811,-31.646921 -67.21465,-35.800939 -20.03792,-4.143963 -38.4729,-3.317578 -51.93364,13.607323 -13.46074,16.924901 -12.07739,61.265196 -13.53554,86.969546 -1.45815,25.70435 2.54945,70.17701 17.6046,88.66552 15.05516,18.4885 45.88634,13.58502 49.92695,21.4137 2.21283,4.28736 65.15228,-174.85515 65.15228,-174.85515 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7904-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <path
+             inkscape:connector-curvature="0"
+             sodipodi:nodetypes="czzzzzc"
+             id="path7878-3"
+             d="m 135.37935,82.017807 c 0,0 26.34355,1.938783 37.63307,13.903188 11.41494,12.097335 13.73457,21.331515 15.29586,37.734585 1.56337,16.42499 -0.84957,28.41812 -7.81382,36.03734 -6.96425,7.61922 -1.00429,19.58332 -25.91605,12.07107 -24.91176,-7.51225 -27.03224,-27.78298 -26.51523,-46.30475 0.51721,-18.52898 7.31617,-53.441433 7.31617,-53.441433 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient7906-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <path
+             inkscape:connector-curvature="0"
+             sodipodi:nodetypes="czccssc"
+             id="path7880-8"
+             d="m 135.648,81.927211 c 0,0 -4.64465,16.365075 0.58825,28.563099 5.48794,12.79254 27.22425,44.26007 27.22425,54.65565 l 22.65625,-5 c 2.54218,-6.96644 3.21052,-15.75206 2.1875,-26.5 -1.56129,-16.40307 -3.8663,-25.62141 -15.28125,-37.718749 -9.65488,-10.232047 -31.59311,-13.374857 -37.375,-14 z"
+             style="display:inline;opacity:1;fill:url(#radialGradient7908-0);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 845.03125,1154.7776 c -4.28571,0.7143 -27.62815,3.6181 -57.85714,10 -30.22899,6.3819 -57.31395,4.9661 -135.78608,17.3296 -79.85178,12.5808 -94.06436,42.5423 -108.12225,47.0643 -14.70014,4.7286 -145.37739,-65.8225 -145.37739,-65.8225 l 4.28572,-94.2857 c 0,0 85.88551,-16.2009 112.14285,-33.5714 26.25735,-17.3705 45.58238,-49.66602 59.28572,-71.42861 13.70334,-21.76259 32.85714,-71.42858 32.85714,-71.42858 l 238.57143,262.14289 z"
+           id="path7917-0"
+           sodipodi:nodetypes="czzzcczzcc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8888-6);enable-background:accumulate"
+           d="m 332.34019,898.38549 -32.73181,-61.29956 -37.61734,45.10646 c 2.17675,1.31711 5.77425,-20.85603 45.6004,-64.41708 l 24.74875,80.61018 z"
+           id="path7919-5"
+           clip-path="url(#clipPath8658-06)"
+           sodipodi:nodetypes="ccccc"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6951);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8892-7);enable-background:accumulate"
+           d="m 200.81833,863.03015 146.3711,-51.61879 243.95184,226.27414 -241.83052,140.0072 -181.01934,-87.6813 32.52692,-226.98125 z"
+           id="path7923-6"
+           clip-path="url(#clipPath2833-2)"
+           sodipodi:nodetypes="cccccc"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#0f0f0f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 642.88839,640.13471 c 0,0 -29.55406,40.57305 -47.85714,74.28571 -18.30309,33.71267 -58.62109,126.35694 -70.35714,171.07143 -11.7594,44.80344 -62.5,123.57145 -62.5,123.57145 l 76.07143,18.2143 c 0,0 11.80712,-12.8234 31.07142,-46.07146 19.2643,-33.24808 60.35715,-138.57143 60.35715,-138.57143 l 13.21428,-202.5 z"
+           id="path7921-6"
+           sodipodi:nodetypes="czzcczcc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.4;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8856-2);enable-background:accumulate"
+           d="m 430.28131,381.94122 c -7.07106,2.82843 -236.18124,32.15181 -236.18124,32.15181 l -39.63961,359.83304 90.19849,92.63961 52.3259,-114.5513 100.46804,-186.39192 32.82842,-183.68124 z"
+           id="path7925-4"
+           sodipodi:nodetypes="ccccccc"
+           clip-path="url(#clipPath3665-9)"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 969.67051,1164.0346 c 0,0 23.25628,11.3937 36.06779,20.4761 12.6974,9.0015 29.4724,24.6491 41.6924,37.3605 12.3055,12.8002 20.1127,22.5987 41.5327,24.1608 21.4322,1.5629 53.2824,-8.7876 73.296,-24.6642 20.0135,-15.8766 45.6469,-69.2328 45.6469,-69.2328 l -127.1608,-143.0717"
+           id="path7927-0"
+           sodipodi:nodetypes="czzzzcc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8860-3);enable-background:accumulate"
+           d="M 331.34019,641.50471 216.17367,835.36467 260.2153,925.96265 357.79603,732.21539 331.34019,641.50471 Z"
+           id="path7929-0"
+           clip-path="url(#clipPath8642-9)"
+           sodipodi:nodetypes="ccccc"
+           transform="translate(276,136)" />
+        <g
+           style="display:inline;opacity:1;enable-background:new"
+           id="g7931-4"
+           transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+           inkscape:transform-center-x="-347.89063"
+           inkscape:transform-center-y="-28.255779">
+          <path
+             inkscape:connector-curvature="0"
+             style="display:inline;opacity:1;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+             d="m 1049.205,-282.26672 -0.09,0.008 c -1.3874,0.88445 -6.6033,1.6072 -6.629,9.52344 -0.024,7.42525 15.0129,17.09146 17.1563,18.09375 1.7302,0.80909 3.5916,1.40876 5.4063,1.71875 l 1.4374,0.21875 c 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99128 5.4294,-1.4193 6.125,-1.78125 0.7222,-0.37601 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3191,-1.70203 2.5312,-2 0.2123,-0.29796 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3405,-0.094 0.5,-0.4375 0.859,-1.84708 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68215 0.168,-1.35277 0.2187,-1.75 0.029,-0.22951 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19832 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41764 -0.9716,-4.61463 -1.625,-5.46875 -0.4194,-0.54857 -0.7993,-0.7925 -1.1562,-0.90625 -0.067,-0.0173 -0.1239,-0.0467 -0.1875,-0.0625 -0.021,-0.004 -0.042,0.003 -0.062,0 -0.3116,-0.0755 -0.6085,-0.15867 -1.1562,-0.21875 -0.9855,-0.10812 -2.4247,-0.2594 -3.9688,-0.25 -0.5147,0.003 -1.0371,0.0476 -1.5625,0.0937 -3.5589,0.31228 -9.0098,0.99108 -10.2187,1.625 -1.6331,-0.33402 -3.9482,-0.61223 -5.9376,-0.46875 -3.064,0.22097 -4.9677,0.34219 -6.9062,0.46875 -1.9384,0.12655 -1.6861,0.38864 -2.9062,0.46875 -1.3191,0.0866 -1.7869,-0.22325 -5.5626,0.0937 -3.5457,0.29772 -8.9806,0.99317 -10.2187,1.625 -1.6334,-0.33451 -3.9459,-0.61239 -5.9375,-0.46875 -3.0642,0.22098 -4.9678,0.37344 -6.9062,0.5 -0.6592,0.043 -1.0424,0.12393 -1.3438,0.1875 z"
+             id="path7933-6" />
+          <g
+             clip-path="url(#clipPath7616-1)"
+             style="display:inline;filter:url(#filter7610-9);enable-background:new"
+             id="g7935-2"
+             transform="matrix(0.9975712,-0.06965428,0.06965428,0.9975712,872.72062,140.02502)">
+            <path
+               inkscape:connector-curvature="0"
+               sodipodi:nodetypes="ccssscsssscscsscsssccscssccsscssscc"
+               id="path7937-6"
+               d="m 229.94262,-409.12268 c -3.55781,0.05 -9.0242,0.36009 -10.30334,0.90414 -1.60609,-0.44747 -3.90316,-0.88131 -5.89995,-0.87674 -3.07199,0.007 -4.96469,0.009 -6.90727,0 -0.66047,-0.003 -1.04759,0.0672 -1.35267,0.10959 0,0 0,1.09593 0,1.09593 0.11972,-0.17947 0.39252,-0.69046 0.94975,-0.76715 0.74758,-0.10289 5.16928,-0.15123 7.31019,-0.1096 1.7746,0.0345 4.45523,0.27427 6.38921,0.95895 0.3214,0.11378 0.61925,0.27378 0.89219,0.41097 1.96342,0.98693 7.94336,4.30154 7.94336,4.30154 0,0 -6.63275,-3.94768 -7.48287,-4.43853 -0.20331,-0.11739 -0.57464,-0.25769 -1.03609,-0.41098 1.22063,-0.44779 5.07597,-0.61971 7.82823,-0.71235 3.0245,-0.10182 3.34776,-0.0896 5.41069,0.19179 2.12931,0.29043 3.33851,0.60276 3.33851,0.60276 -1e-5,0 -0.0784,-0.64118 1.03609,-0.79455 0.74757,-0.10289 5.16929,-0.15123 7.31019,-0.1096 2.0695,0.0403 5.36605,0.40716 7.2814,1.36992 1.00332,0.50433 3.03564,1.56863 4.79535,2.53571 l 0.0956,-0.0194 c 0,0 -3.58034,-2.16242 -4.43047,-2.65327 -0.20331,-0.11739 -0.57463,-0.25769 -1.03609,-0.41098 1.22062,-0.44779 5.04719,-0.61971 7.79945,-0.71235 3.0245,-0.10182 3.34775,-0.0896 5.41069,0.19179 1.95316,0.2664 3.01292,0.53006 3.19461,0.57536 0,0 -0.0271,-0.31146 -0.0271,-0.31146 -0.40903,-0.13645 -0.71424,-0.23335 -1.40038,-0.35748 -1.30081,-0.23533 -3.39912,-0.60156 -5.50857,-0.56398 -3.57195,0.0636 -9.05328,0.35596 -10.30334,0.90414 -1.60583,-0.44695 -3.87662,-0.8813 -5.87117,-0.87674 -3.07199,0.007 -4.99348,0.009 -6.93605,0 -1.94256,-0.009 -1.71268,0.27907 -2.93558,0.27398 -1.32191,-0.005 -1.76612,-0.35463 -5.55459,-0.30138 0,0 0,0 0,0"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path7939-7"
+               d="m 206.1989,-407.47878 c 1.92021,0.81706 4.57715,2.19283 6.15897,3.39739 1.58184,1.20456 2.90757,1.77368 5.55459,3.91795 0.88557,0.71738 1.74865,1.34985 2.59193,1.92174 l 0.54057,-0.19011 c -0.71323,-0.48339 -1.46776,-1.02031 -2.26909,-1.62203 -2.82223,-2.11921 -3.62655,-2.80973 -6.01507,-4.27414 -2.38854,-1.4644 -4.09948,-2.36576 -6.5619,-3.1508 0,0 0,0 0,0"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               sodipodi:nodetypes="cssccsscc" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path7941-5"
+               d="m 237.79963,-407.47878 c 1.92021,0.81706 4.60594,2.19283 6.18775,3.39739 0.81307,0.61916 1.55849,1.07042 2.45046,1.65401 l 0.649,-0.11666 c -0.79831,-0.57637 -1.57177,-1.09435 -2.69653,-1.78394 -2.38854,-1.4644 -4.12826,-2.36576 -6.59068,-3.1508 0,0 0,0 0,0"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+               sodipodi:nodetypes="csccscc" />
+          </g>
+          <g
+             clip-path="url(#clipPath7606-1)"
+             id="g7943-6">
+            <path
+               inkscape:connector-curvature="0"
+               style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7578-4);enable-background:new"
+               d="m 1056.25,-278.80481 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+               id="path7945-9"
+               sodipodi:nodetypes="czzzzzzzzzzzzzz" />
+            <path
+               inkscape:connector-curvature="0"
+               style="display:inline;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7594-8);enable-background:new"
+               d="m 1058.5,-275.42981 c 4.1446,-1.47877 10,3.125 10,3.125 0.899,0.28092 2.7251,-0.89447 2.6243,-1.68614 0,0 -1.5503,-1.86062 -0.3743,-2.93886 1.176,-1.07824 5.296,1.50738 7.5,1.625 2.204,0.11762 5.5621,-0.22941 7,-0.75 1.4379,-0.52059 1.1129,-1.42459 2.625,-1.75 1.5121,-0.32541 5.1189,1.03754 7.0605,1.16883 1.9416,0.13129 4.6481,0.33427 5.8145,-0.16883 1.1664,-0.5031 0.1782,-1.15921 1.875,-1.875 1.6968,-0.71579 7.7602,-0.95662 9.625,-0.125 1.8648,0.83162 1.8099,0.5192 2.625,3 0.8151,2.4808 7.4398,5.16285 -1.125,13.375 -8.5648,8.21215 -59.3779,13.78594 -65.625,2.75 -6.2471,-11.03594 6.2304,-14.27123 10.375,-15.75 z"
+               id="path7947-8"
+               sodipodi:nodetypes="czzzzzzzzzzzzzz" />
+          </g>
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#101414;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 628.24553,347.99185 c -3.80443,-25.26423 -16.80972,-50.63802 -17.1568,-75.52523 -0.18626,-13.35552 3.27285,-26.57091 13.75553,-39.55405 36.34702,-65.29583 116.94091,-84.69468 185.93466,-91.46542 86.92239,-11.0168 184.91267,17.94007 233.37138,95.40128 54.124,75.7333 56.6747,172.53912 80.612,259.52795 29.4378,127.1276 54.7791,256.21414 60.3922,386.85035 -3.0634,78.18185 -8.4263,165.18417 -60.5032,228.13417 -48.0265,50.3574 -122.7864,50.053 -187.06985,59.0023 -90.55539,4.655 -184.35153,-16.1458 -261.7839,-64.1982 -64.77564,-37.94 -95.73019,-113.47867 -97.2794,-186.01962 -8.38917,-79.87516 26.39152,-153.80851 51.6204,-227.15961 7.47061,-82.76107 9.41286,-166.24775 9.65334,-249.38484 -0.83682,-32.19544 -7.08953,-63.81733 -11.54636,-95.60908 z"
+           id="path7949-7"
+           sodipodi:nodetypes="cscccccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8940-3);enable-background:accumulate"
+           d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 -38.61152,-142.95988 -39.24264,-189.11984 -0.63145,-46.18445 10.83034,-108.60786 30.67767,-158.29647 20.04835,-50.19188 36.89674,-44.84642 42.12489,-92.59293 5.22815,-47.74651 -17.4264,-149.39192 -17.4264,-149.39192 l -55.86144,39.59798 z"
+           id="path7951-2"
+           sodipodi:nodetypes="ccccczzzcc"
+           clip-path="url(#clipPath8616-5)"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6953);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 1010.0312,655.49186 c 0,0 16.7552,37.01806 28.7015,53.95395 11.9462,16.93589 52.7271,56.04605 52.7271,56.04605 l 52.5972,-127.58975"
+           id="path7953-8"
+           sodipodi:nodetypes="czcc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.07999998;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8822-2);enable-background:accumulate"
+           d="m 730.31998,536.56864 c 0,8.48528 42.54774,58.46803 42.54774,58.46803 l 12.60659,-28.76954 -55.15433,-29.69849 z"
+           id="path7955-2"
+           sodipodi:nodetypes="cccc"
+           clip-path="url(#clipPath8209-6)"
+           transform="translate(276,136)" />
+        <g
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;opacity:1;enable-background:new"
+           id="g7957-9"
+           clip-path="url(#clipPath3998-6)">
+          <g
+             transform="translate(-174.03125,62.156036)"
+             style="filter:url(#filter3677-5)"
+             id="g7959-9">
+            <g
+               id="g7961-6"
+               style="filter:url(#filter3785-4)">
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzzzzzzzz"
+                 id="path7963-0"
+                 d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+                 style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <rect
+                 y="412.60312"
+                 x="343.6539"
+                 height="181.01935"
+                 width="381.83765"
+                 id="rect7965-2"
+                 style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+            </g>
+            <g
+               id="g7967-7"
+               style="filter:url(#filter3785-4)">
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzcc"
+                 id="path7969-6"
+                 d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+                 style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+                 transform="translate(174.03125,-62.156036)" />
+              <rect
+                 y="344.82138"
+                 x="702.86414"
+                 height="162.63455"
+                 width="207.8894"
+                 id="rect7971-1"
+                 style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+            </g>
+          </g>
+          <g
+             transform="translate(-174.03125,62.156036)"
+             style="display:inline;opacity:0.18000004;enable-background:new"
+             id="g7973-3">
+            <g
+               id="g7975-2"
+               style="filter:url(#filter3785-4)">
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzzzzzzzz"
+                 id="path7977-1"
+                 d="m 425.88244,476.99186 c 10.80543,-1.47866 24.74401,3.35451 44.64286,3.21428 19.89885,-0.14023 57.45322,-16.91122 82.14285,-17.14286 24.68963,-0.23164 62.7517,12.28406 79.28572,15 16.53402,2.71594 22.84832,-0.15852 27.49999,7.85715 4.65167,8.01567 1.92671,10.74724 -10.35714,20.71429 -12.28385,9.96705 -40.78968,12.63632 -66.07143,12.85714 -25.28234,0.22082 -70.38129,7.07852 -95.35714,3.92856 -24.97585,-3.14996 -56.93756,-7.82267 -68.92857,-17.85714 -11.99101,-10.03447 -19.85084,-16.73182 -17.5,-23.92857 2.35084,-7.19675 13.83743,-3.16419 24.64286,-4.64285 z"
+                 style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <rect
+                 y="412.60312"
+                 x="343.6539"
+                 height="181.01935"
+                 width="381.83765"
+                 id="rect7979-5"
+                 style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+            </g>
+            <g
+               id="g7981-9"
+               style="filter:url(#filter3785-4)">
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzcc"
+                 id="path7983-9"
+                 d="m 687.14286,452.36218 c -10.46169,9.71443 -86.9796,19.00514 -100.71429,29.28572 -13.73469,10.28058 -14.75252,12.88826 -12.14286,20 2.60966,7.11174 6.54527,9.40572 25.71429,8.57142 19.16902,-0.8343 98.57143,-27.62172 98.57143,-21.42857 l -11.42857,-36.42857 z"
+                 style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+                 transform="translate(174.03125,-62.156036)" />
+              <rect
+                 y="344.82138"
+                 x="702.86414"
+                 height="162.63455"
+                 width="207.8894"
+                 id="rect7985-1"
+                 style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+            </g>
+          </g>
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8802-7);enable-background:accumulate"
+           d="M 582.65599,-7.4183011 695.79307,78.848726 804.68752,337.64981 842.87128,545.5392 963.07944,637.46308 c 0,0 -12.72793,-287.08535 -19.799,-313.95541 C 936.20938,296.63761 793.37381,-69.643698 793.37381,-69.643698 L 582.65599,-7.4183011 Z"
+           id="path7987-4"
+           clip-path="url(#clipPath8604-69)"
+           sodipodi:nodetypes="cccccscc"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6955);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 964.13839,239.599 c 0,0 8.67732,10.89662 24.10715,11.96428 15.42986,1.06766 49.72166,-39.95267 70.17856,-52.14285 20.4793,-12.20353 47.0464,-26.60225 63.9286,-20.35714 16.8821,6.2451 22.1578,26.43609 27.8571,48.03571 5.6994,21.59961 6.7186,61.81389 -2.6785,92.85715 -9.3972,31.04325 -50.5033,73.10375 -65.3572,103.39285 -14.8539,30.2891 -11.6071,39.82143 -11.6071,39.82143"
+           id="path7989-9"
+           sodipodi:nodetypes="czzzzzzc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:url(#radialGradient3315-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 1124.4955,207.63471 c -15.8928,-0.89286 -49.7188,12.10583 -66.0714,24.28572 -16.4386,12.2439 -29.2209,24.1144 -29.2857,52.14285 -0.065,28.20604 13.1191,39.07641 29.1071,46.96429 15.988,7.88789 33.6862,7.11928 51.9643,-11.78571 18.2782,-18.905 14.2857,-111.60715 14.2857,-111.60715 z"
+           id="path7991-1"
+           sodipodi:nodetypes="czzzzc" />
+        <ellipse
+           ry="73.928574"
+           rx="86.428574"
+           cy="237.00504"
+           cx="385"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.75;fill:url(#radialGradient3543-4);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4120-7);enable-background:accumulate"
+           id="path7993-0"
+           transform="matrix(0.9434749,-0.1239943,0.1440089,1.0957669,451.94827,134.5988)"
+           clip-path="url(#clipPath4100-3)" />
+        <path
+           inkscape:connector-curvature="0"
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3915-6);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 527.60588,407.44884 c 0,0 -122.04144,38.40348 -187.51434,9.63181 -65.47289,-28.77166 -74.37725,-124.71847 -74.37725,-124.71847 0,0 73.38158,-80.50393 129.92078,-83.61476 55.82705,-3.07164 90.57386,20.14332 114.87001,65.85171 24.352,45.81348 17.1008,132.84971 17.1008,132.84971 z"
+           id="path7995-7"
+           sodipodi:nodetypes="csczzc"
+           mask="url(#mask3684-3)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#linearGradient6957);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 772.17411,393.349 c 0,0 36.21754,-27.38247 51.60714,-35.89286 15.17734,-8.39301 25.71428,-11.60714 35.89285,-11.60714 l -15.53571,66.96428"
+           id="path7997-5"
+           sodipodi:nodetypes="czcc" />
+        <circle
+           r="36.25"
+           cy="306.64789"
+           cx="409.28571"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3933-8);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path7999-8"
+           transform="translate(449.49554,74.915393)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.3;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8806-6);enable-background:accumulate"
+           d="m 311.83409,415.43155 9.8995,121.62237 -60.10408,136.47161 15.55635,174.65537 c 15.61326,61.8792 32.18545,98.66905 74.37615,117.05383 4.31911,-36.23998 8.68161,-72.36764 -31.24264,-223.11984 l 17.67767,-69.29647 72.12489,-138.59293 -42.4264,-158.39192 -55.86144,39.59798 z"
+           id="path8001-7"
+           sodipodi:nodetypes="cccccccccc"
+           clip-path="url(#clipPath8616-5)"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8826-9);enable-background:accumulate"
+           d="m 635.21025,581.13004 c -14.14214,12.72792 39.23347,34.58015 76.36753,24.04163 37.13406,-10.53852 104.64487,-35.56437 103.23759,-79.19596 -1.40728,-43.63158 -76.36753,-128.69343 -76.36753,-128.69343 L 635.21025,581.13004 Z"
+           id="path8003-0"
+           sodipodi:nodetypes="czzcc" />
+        <circle
+           r="23.214285"
+           cy="306.64789"
+           cx="410"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient3991-0);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8005-4"
+           transform="translate(449.67411,74.915393)" />
+        <circle
+           r="7.5"
+           cy="303.07648"
+           cx="414.28571"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3981-7);enable-background:accumulate"
+           id="path8007-8"
+           transform="translate(451.99554,73.486821)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4112-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 789.31696,478.349 c 0,0 7.02281,19.56859 -1.07143,35 -8.09424,15.43141 -42.32317,38.98822 -67.49999,50 -25.30972,11.06991 -85.473,32.96393 -101.78572,41.96428 -16.46148,9.08243 -18.21428,12.67857 -18.21428,12.67857 0,0 -7.14693,-19.06441 28.74999,-51.7857 36.17211,-32.97214 142.02712,-48.0495 159.82143,-87.85715 z"
+           id="path8009-0"
+           sodipodi:nodetypes="czzzczc" />
+        <g
+           style="display:inline;opacity:1;enable-background:new"
+           id="g8011-4"
+           transform="translate(780.74553,74.55825)">
+          <path
+             inkscape:connector-curvature="0"
+             transform="translate(-329.81481,0)"
+             clip-path="url(#clipPath3999-0)"
+             sodipodi:nodetypes="czzczzzszc"
+             id="path8013-2"
+             d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+             style="display:inline;opacity:1;fill:url(#radialGradient3585-2);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+          <ellipse
+             ry="134.00607"
+             rx="64.715881"
+             cy="338.07648"
+             cx="183.57143"
+             transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-166.62245,2.387362)"
+             id="path8015-9"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4060-5);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <ellipse
+             ry="134.00607"
+             rx="64.715881"
+             cy="338.07648"
+             cx="183.57143"
+             transform="matrix(0.8823874,0.4705236,-0.4705236,0.8823874,-162.19388,-18.755495)"
+             id="path8017-6"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4062-9);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <path
+             inkscape:connector-curvature="0"
+             transform="translate(-329.81481,3e-7)"
+             clip-path="url(#clipPath3999-0)"
+             sodipodi:nodetypes="czzczzzszc"
+             id="path8019-1"
+             d="m 179.64286,267.36218 c -22.41044,39.70292 -60.6161,115.78029 -69.28571,149.64286 -8.64721,33.7751 -8.77199,66.41654 -0.35715,86.42858 8.3602,19.88213 26.16398,35.6328 40.71428,41.42856 -0.59638,-14.37587 14.37295,-43.28583 72.85715,-72.5 58.62627,-29.28514 78.38163,-27.13086 103.57142,-47.14286 25.63006,-20.36176 8.20587,-79.64664 3.21429,-93.92857 -4.99158,-14.28193 -1.23663,-3.37974 -1.94602,-5.09301 -10.68928,-25.81592 -34.21432,-54.4303 -64.48255,-64.54984 -30.26823,-10.11954 -65.01776,-4.84837 -84.28571,5.71428 z"
+             style="display:inline;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6959);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4079-1);enable-background:new" />
+        </g>
+        <circle
+           r="19.704132"
+           cy="398.07648"
+           cx="310.71429"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8021-0"
+           transform="translate(452.55663,72.581273)" />
+        <circle
+           r="19.704132"
+           cy="398.07648"
+           cx="310.71429"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4056-5);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6961);stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4083-9);enable-background:accumulate"
+           id="path8023-4"
+           transform="translate(450.55663,72.581273)" />
+        <circle
+           r="19.704132"
+           cy="398.07648"
+           cx="310.71429"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4119-7);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           id="path8025-2"
+           transform="translate(450.55663,72.581273)" />
+        <ellipse
+           ry="44.547726"
+           rx="72.079735"
+           cy="377.42877"
+           cx="429.56738"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4868-3);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4002-6);enable-background:accumulate"
+           id="path8027-2"
+           transform="matrix(0.9969564,-0.07796167,0.07796167,0.9969564,436.61877,125.29509)"
+           inkscape:transform-center-x="-47.231976"
+           inkscape:transform-center-y="-3.6935079" />
+        <ellipse
+           ry="22.627417"
+           rx="36.611931"
+           cy="391.21735"
+           cx="437.6991"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:url(#radialGradient4876-9);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4010-1);enable-background:accumulate"
+           id="path8029-2"
+           transform="matrix(1.4357951,-0.06999104,0.06999104,1.4357951,235.18065,-63.86546)"
+           inkscape:transform-center-x="-20.955902"
+           inkscape:transform-center-y="-13.056625" />
+        <g
+           transform="translate(450.03125,73.843964)"
+           id="g8031-0"
+           style="display:inline;opacity:1;filter:url(#filter4053-9);enable-background:new">
+          <circle
+             r="3.2142856"
+             cy="401.82648"
+             cx="413.66071"
+             id="path8033-5"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6963);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <circle
+             r="3.2142856"
+             cy="401.82648"
+             cx="413.66071"
+             transform="translate(13.125009,8.1249913)"
+             id="path8035-5"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6965);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <circle
+             r="3.2142856"
+             cy="401.82648"
+             cx="413.66071"
+             transform="translate(32.946437,7.4999913)"
+             id="path8037-2"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6967);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <circle
+             r="3.2142856"
+             cy="401.82648"
+             cx="413.66071"
+             transform="translate(24.910723,-10.267866)"
+             id="path8039-9"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6969);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <circle
+             r="3.2142856"
+             cy="401.82648"
+             cx="413.66071"
+             transform="translate(47.589294,-0.6250087)"
+             id="path8041-0"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient6971);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 896.20301,482.92837 c 0.98509,4.35008 4.53707,6.17948 7.38673,7.89182 4.46068,2.51292 6.52016,1.52211 9.15451,-0.75761 1.60195,-1.92117 10.68311,-4.69865 15.59423,-7.07107 4.32961,-1.45891 8.9033,-5.35873 13.38452,-8.33376 3.39514,-1.62724 5.34664,0.35464 7.82868,1.01015 2.94412,0.71661 4.41117,2.17175 6.06092,3.53554 2.39616,1.17519 -0.9279,3.14313 3.283,4.29314 1.19091,0.21794 2.41695,0.57645 3.28299,-0.50507"
+           id="path8043-2"
+           sodipodi:nodetypes="ccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 910.85021,475.35223 c 2.31494,-0.032 3.17778,0.64253 5.49271,-0.82075 3.45564,-3.08113 5.40254,-3.14477 7.95495,-4.41942 3.02657,-1.31523 6.5357,8.15169 10.10153,9.84899 2.39509,-0.82142 1.28914,1.79379 1.45209,2.65165 0.0571,2.64684 2.80694,3.67806 4.35628,5.42957 3.31604,2.25549 7.37523,6.29546 11.11168,5.3033 6.44525,-2.93107 10.27922,-1.28146 16.28871,-7.38674 0.70405,-1.18134 -0.58425,-6.8946 3.09359,-7.19734 2.52399,0.25338 4.16667,0.0502 6.06092,0.56822 5.441,2.11719 7.73778,6.45 14.71034,7.95495 6.1829,0.96639 7.61264,3.79426 13.88959,5.05076"
+           id="path8045-8"
+           sodipodi:nodetypes="cccccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 876.98133,483.52197 c 2.39858,-0.7938 6.10613,4.1921 8.17313,7.04568 0.59281,2.67952 1.15377,5.48645 0.75761,12.12183 0.78513,2.41754 2.68049,3.03095 4.79823,3.283 3.11745,-0.53678 5.87669,-1.3243 7.3236,-3.03046 1.8716,-1.94167 5.31253,2.39394 8.08122,4.04061 3.61009,1.91209 7.77378,1.97886 11.8693,2.27284 1.70358,-0.23064 2.3704,4.51515 3.28299,8.08123 0.38414,4.37806 -0.88544,6.89569 -1.76776,9.84898 -0.2943,2.49655 2.9885,3.52974 6.31345,4.54569 3.18244,0.74124 6.54424,1.66184 9.09137,1.76777 5.14186,0.87491 8.08874,2.69052 12.12183,4.04061 2.23914,0.81655 3.26019,2.24216 4.54569,3.53553"
+           id="path8047-3"
+           sodipodi:nodetypes="ccccccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter8814-5);enable-background:new"
+           d="m 332,187.69519 c 0,0 57.5,-25.5 57.5,-28 0,-2.5 5.5,-52 5.5,-52 0,0 91,-48.500001 91.5,-50.500001 0.5,-2 86,-62.0000004 86,-62.0000004 L 386.5,17.195189 311,123.19519 l 21,64.5 z"
+           id="path8049-8"
+           clip-path="url(#clipPath8514-8)"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 1697.2846,722.5514 c 0,0 -115.9655,73.5391 -123.0365,77.78174 -7.0711,4.24264 -230.5169,137.17872 -230.5169,137.17872 l 4.2427,39.59798 216.3747,-100.40917 117.3797,-101.82337 15.5563,-52.3259 z"
+           id="path8051-0" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810-3);enable-background:accumulate"
+           d="m 528.91587,556.85291 c -5.65685,-1.41421 -181.01933,74.95332 -181.01933,74.95332 l -33.94113,181.01934 51.09546,193.94823 257.2031,67.6813 c 0,0 206.47518,152.735 212.13203,148.4924 5.65686,-4.2426 168.2914,-193.7473 168.2914,-193.7473 L 842.87128,845.35248 796.20224,667.16157 528.91587,556.85291 Z"
+           id="path8053-4"
+           clip-path="url(#clipPath8610-9)"
+           sodipodi:nodetypes="cccccscccc"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:#0c0c0c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 1097.6433,613.88997 c 0,0 22.6195,-6.50681 35.7427,-5.87273 13.1233,0.63409 30.6416,1.93862 43.7089,12.18619 13.0673,10.24756 25.0677,27.14007 34.1124,58.36965 9.0446,31.22958 1.6983,99.25201 -6.1761,143.34735 -7.8743,44.09534 -28.2651,106.11298 -45,140 -16.7348,33.88702 -49.7977,77.49517 -60.5694,89.87617 -11.3642,13.062 -56.2059,36.4262 -79.4306,42.2667 5.3034,-10.6066 48.8998,-50.5889 35,-60.7143 -14.0189,-10.2123 -45.76,45.9824 -84.2931,29.0332 21.38231,-13.1321 41.7794,-51.1861 34.0406,-66.59448 -7.84024,-15.61039 -30.70492,48.75758 -93.53553,37.01288 30.05204,-27.5267 55.40706,-70.90401 41.2627,-82.9797 -14.41516,-12.30687 -60.46175,54.2932 -60.46175,54.2932 0,0 -2.8219,-41.70123 13.7732,-68.60737 16.63935,-26.97787 79.65297,-81.61527 99.55308,-111.70342 19.9002,-30.08814 33.6126,-66.00902 42.1355,-92.51794 8.5228,-26.50892 15.8009,-77.09954 15.8009,-77.09954"
+           id="path8055-0"
+           sodipodi:nodetypes="czzzzzzczczczczzzc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8818-1);enable-background:accumulate"
+           d="m 770.74639,609.17881 -50.91169,97.58074 -79.90307,111.01576 34.64824,71.41778 42.42641,79.19597 72.12489,-45.25484 14.14214,-192.33305 21.2132,-138.59292 -14.14214,-90.15612 -39.59798,107.12668 z"
+           id="path8057-9"
+           clip-path="url(#clipPath8622-5)"
+           sodipodi:nodetypes="cccccccccc"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter8810-3);enable-background:accumulate"
+           d="m 295,846.19519 6.64488,-68.92285 c 0,0 90.31951,89.00457 162.35512,122.92285 72.03561,33.91828 308,62 308,62 l 154,-26 -36,162.00001 -286,26 -298,-89 -11,-189.00001 z"
+           id="path8059-1"
+           clip-path="url(#clipPath8906-9)"
+           sodipodi:nodetypes="cczcccccc"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3587-1);enable-background:new"
+           d="m 405.79629,845.99023 74.95332,65.05383 2.49963,16.8804 19.40336,10.15891 6.49204,23.05109 31.70905,-8.3711 14.84924,48.08324 c 12.25652,12.7279 89.79344,-113.1097 55.86143,38.1838 l -60.81118,16.2635 -89.20292,-94.69286 -62.82503,-53.79963 7.07106,-60.81118 z"
+           id="path8061-9"
+           sodipodi:nodetypes="cccccccccccc"
+           clip-path="url(#clipPath3602-4)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate"
+           d="m 1159.317,918.349 c 54.2857,-1.42857 126.035,-15.05199 170,-26.78572 44.0527,-11.75714 125.8863,-36.34724 175.357,-57.85714 49.3393,-21.45272 113.6038,-59.2816 154.2859,-92.14285 40.5081,-32.72069 52.3899,-55.81981 60.7142,-33.57143 8.3691,22.36779 -16.4069,56.32562 -37.8571,81.07143 -21.6042,24.9234 -52.7314,52.70533 -98.9287,89.28571 -46.1973,36.58038 -156.0825,101.58463 -212.8571,128.5714 -57.066,27.1254 -128.2033,58.2385 -172.1428,72.5001 -43.9395,14.2616 -131.4286,31.0714 -131.4286,31.0714 L 1159.317,918.349 Z"
+           id="path8063-6"
+           sodipodi:nodetypes="czzzzzzzzcc" />
+        <path
+           inkscape:connector-curvature="0"
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:url(#linearGradient6973);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3779-4);enable-background:accumulate"
+           d="m 1241.5965,652.95007 c 0,0 -64.7215,54.33706 -145.6639,98.99494 -82.0244,45.25484 -284.25704,93.3381 -284.25704,93.3381 0,0 -15.10137,21.05196 45.25489,28.28428 60.35626,7.23232 224.08195,-53.30069 278.60015,-96.16654 54.5182,-42.86585 120.2081,-111.72286 120.2081,-111.72286 l -14.1422,-12.72792 z"
+           id="path8065-2"
+           sodipodi:nodetypes="czczzcc"
+           clip-path="url(#clipPath3992-4)" />
+        <g
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;opacity:1;enable-background:new"
+           id="g8067-5"
+           clip-path="url(#clipPath3986-7)">
+          <g
+             transform="translate(-174.03125,62.156036)"
+             style="filter:url(#filter3677-5)"
+             id="g8069-4">
+            <g
+               style="filter:url(#filter3785-4)"
+               id="g8071-4">
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzccccc"
+                 id="path8073-9"
+                 d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+                 style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+                 transform="translate(174.03125,-62.156036)" />
+              <rect
+                 y="486.14224"
+                 x="1197.8389"
+                 height="309.71277"
+                 width="333.75412"
+                 id="rect8075-9"
+                 style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+            </g>
+          </g>
+          <g
+             transform="translate(-174.03125,62.156036)"
+             style="display:inline;opacity:0.18000004;enable-background:new"
+             id="g8077-3">
+            <g
+               style="filter:url(#filter3785-4)"
+               id="g8079-6">
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzccccc"
+                 id="path8081-0"
+                 d="m 1094.2857,725.93361 c 0,0 -0.2961,26.16091 4.6428,37.85715 4.9389,11.69624 20.0381,26.48665 28.5715,31.42857 8.5334,4.94192 18.9286,8.57142 18.9286,8.57142 l 117.8571,-115 17.8572,-75.71428 -96.4286,38.57143 -91.4286,74.28571 z"
+                 style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+                 transform="translate(174.03125,-62.156036)" />
+              <rect
+                 y="486.14224"
+                 x="1197.8389"
+                 height="309.71277"
+                 width="333.75412"
+                 id="rect8083-5"
+                 style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+            </g>
+          </g>
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.83300003;fill:#050505;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:15;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;filter:url(#filter8225-7);enable-background:accumulate"
+           d="m 1264.1875,605 c -4.4911,0.73268 -8.157,3.45509 -11.9375,6.40625 -10.0813,7.86976 -28.1695,34.42524 -48.0312,50.46875 -39.8674,32.20316 -103.996,69.97701 -152.5626,91.09375 -48.614,21.13738 -130.54122,45.81801 -174.31245,57.5 -43.39821,11.58246 -115.04403,25.13107 -168.25,26.53125 l -4.5625,0.125 -2,4.125 -92.84375,192.125 -6.5,13.4688 14.65625,-2.8438 c 0,0 87.26968,-16.6514 132.34375,-31.2812 44.7252,-14.51667 115.79086,-45.66683 173.03125,-72.87505 C 980.82199,912.46306 1090.1551,847.86412 1137.5,810.375 c 46.3608,-36.70982 77.8049,-64.71682 99.9375,-90.25 10.9011,-12.576 22.7448,-27.53144 31.0313,-42.75 8.2864,-15.21856 19.1597,-44.21808 13.6874,-58.84375 -1.2177,-3.25474 -2.5514,-6.0613 -4.5937,-8.5 -2.0423,-2.4387 -8.4747,-1.57199 -8.5625,-5.03125 -0.2098,-8.26482 -3.3155,-0.24423 -4.8125,0 z m 2.1563,15.21875 c 0.4148,0.58574 1.0311,1.55766 1.7812,3.5625 2.8968,7.74213 -1.4407,31.89875 -8.8125,45.4375 -7.3718,13.53875 -22.6384,28.92394 -33.1875,41.09375 -21.0754,24.31356 -51.9037,51.86156 -97.9375,88.3125 -45.0496,35.67159 -155.46033,101.09459 -211.40625,127.6875 -56.89173,27.04249 -128.09616,58.1184 -171.25,72.125 -36.36491,11.8031 -95.84471,23.8338 -115.71875,27.7813 L 714.09375,851.75 c 54.70691,-2.0493 123.79259,-15.21635 167.125,-26.78125 44.33422,-11.83225 126.07865,-36.33633 176.40625,-58.21875 50.112,-21.78871 112.5344,-61.16816 154.0312,-94.6875 20.6464,-16.67721 41.7449,-42.54588 49.8126,-48.84375 2.437,-1.90242 4.0806,-2.6358 4.875,-3 z"
+           id="path8085-0"
+           clip-path="url(#clipPath3722-3)"
+           sodipodi:nodetypes="cssssccccccssssssssccssssssccssssc" />
+        <g
+           style="display:inline;opacity:1;enable-background:new"
+           id="g8087-2"
+           mask="url(#mask7704-9)"
+           transform="matrix(0.9934486,0.1142802,-0.1142802,0.9934486,-9.24324,588.09054)"
+           inkscape:transform-center-x="-185.09603"
+           inkscape:transform-center-y="-12.859654">
+          <path
+             inkscape:connector-curvature="0"
+             transform="translate(0.08004571,-0.03125)"
+             style="display:inline;fill:#bcb786;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+             d="m 1111.4062,-285.9375 -3.9374,1.875 c -0.041,0.0102 -0.1,0.0205 -0.125,0.0312 -0.4188,0.21285 -0.1647,0.10058 -0.6563,0.3125 -0.4861,0.20956 -1.7376,0.58419 -4.0937,1.46875 -3.3312,1.25058 -5.8043,2.14984 -7,3.0625 -1.5362,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74767 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41973 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25167 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74215 -8.8948,1.93107 -10.1562,2.6875 -1.584,-0.18078 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44696 -4.9162,0.67276 -6.8438,0.90625 -0.6554,0.0794 -1.041,0.20078 -1.3437,0.28125 -0.4262,0.13166 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15937 -1.7622,-0.15683 -5.5313,0.28125 -3.5539,0.41309 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.29729 -3.8577,-0.53419 -5.8437,-0.34375 -3.0588,0.29332 -4.972,0.48399 -6.9063,0.65625 -1.9342,0.17227 -1.6886,0.42237 -2.9062,0.53125 -1.3162,0.1177 -1.7598,-0.16363 -5.5312,0.25 -3.5421,0.38845 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.29469 -3.8872,-0.50701 -5.875,-0.3125 -3.05829,0.29925 -4.9412,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04005,0.17856 -1.34375,0.25 -0.4277,0.11896 -0.6835,0.21807 -1.375,0.28125 -1.316,0.12026 -1.75975,-0.19488 -5.53125,0.21875 -3.55619,0.39002 -9.0056,1.23916 -10.25,1.90625 -1.59869,-0.29418 -3.85985,-0.52372 -5.84375,-0.3125 -3.0557,0.32533 -4.97405,0.52624 -6.90625,0.71875 -1.93219,0.19251 -1.68975,0.44088 -2.90625,0.5625 -1.31488,0.13147 -1.76305,-0.16454 -5.53125,0.28125 -3.53889,0.41866 -8.9777,1.29217 -10.25,1.96875 -1.59759,-0.28104 -3.85995,-0.42043 -5.84375,-0.1875 -3.05198,0.35837 -4.945,0.56786 -6.875,0.78125 -0.65618,0.0726 -1.04065,0.17269 -1.34375,0.25 -0.42679,0.12723 -0.6849,0.2672 -1.375,0.34375 -1.31339,0.14569 -1.76735,-0.17402 -5.53125,0.3125 -3.54888,0.45876 -8.97865,1.41902 -10.21875,2.125 -1.59309,-0.24424 -3.8338,-0.38135 -5.8125,-0.125 -3.04759,0.39482 -4.9507,0.64845 -6.875,0.90625 -1.92429,0.25779 -1.7261,0.49353 -2.9375,0.65625 -1.30949,0.1759 -1.7472,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.9232,1.69917 -10.1875,2.4375 -1.58749,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02619,0.53612 -4.8989,0.86169 -6.8125,1.1875 -0.65059,0.11077 -1.0137,0.27094 -1.3125,0.375 -0.42069,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.2947,0.26159 -1.7271,-0.006 -5.4375,0.8125 -3.49848,0.77195 -8.8459,2.38293 -10.0625,3.21875 -1.5629,-0.0774 -3.7575,0.0853 -5.6875,0.59375 -2.97238,0.78313 -4.8177,1.23209 -6.6875,1.75 -1.87,0.5179 -1.66665,0.76728 -2.84375,1.09375 -1.27249,0.3529 -1.69705,0.10709 -5.34375,1.1875 -3.42468,1.01463 -8.6494,2.93317 -9.875,3.84375 -1.53878,0.0127 -3.7198,0.27222 -5.625,0.875 -2.93098,0.92734 -4.75035,1.45842 -6.59375,2.0625 -0.62679,0.20538 -0.99165,0.39258 -1.28125,0.53125 -0.40758,0.21361 -0.6533,0.40875 -1.3125,0.625 -1.2545,0.41154 -1.68615,0.18904 -5.28125,1.4375 -3.38989,1.17717 -8.59495,3.2137 -9.78125,4.15625 -1.52388,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69905,1.67548 -6.53125,2.3125 -1.8322,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24679,0.43396 -1.66355,0.19972 -5.21875,1.5625 -3.3387,1.2798 -8.4871,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.6357,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6239,1.78156 -6.4375,2.46875 -0.6167,0.23363 -0.99645,0.44203 -1.28125,0.59375 10e-6,0 0,0.0295 0,0.0312 l -8,3.1875 -12.4759,3.49189 7.92966,19.27772 c -0.59163,1.97357 12.54624,-4.73836 12.54624,-4.73836 0.22641,-0.14468 0.44895,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.1716,-0.21577 6,-1.6875 3.82852,-1.47174 5.22405,-2.00498 5.90625,-2.40625 0.67961,-0.39978 1.61175,-0.87937 2.21875,-1.53125 1.82692,-0.13775 3.5708,-0.49323 4.9375,-1 2.968,-1.10052 4.87535,-1.80619 6.78125,-2.46875 1.90581,-0.66254 2.35415,-1.41487 3.40625,-1.78125 1.09162,-0.38011 2.1951,-0.16538 6.0625,-1.53125 3.8674,-1.36586 5.28315,-1.82708 5.96875,-2.21875 0.70111,-0.40052 1.7008,-0.93298 2.3125,-1.59375 1.97081,-0.0547 3.81695,-0.38463 5.28125,-0.875 3.00152,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.53861,-0.5041 2.17415,-1.04677 2.90625,-1.4375 0.23022,-0.13431 0.4759,-0.25373 0.75,-0.34375 1.09832,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91231,-1.23113 5.366,-1.67295 6.0625,-2.03125 0.69391,-0.35697 1.6301,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63585,-0.26683 5.03125,-0.6875 3.0304,-0.91354 4.9924,-1.4301 6.9375,-1.96875 1.94512,-0.53864 2.4262,-1.26452 3.5,-1.5625 1.11402,-0.30915 2.22,0.007 6.1875,-1.03125 3.9675,-1.03863 5.4175,-1.43273 6.125,-1.75 0.7348,-0.32959 1.8139,-0.75372 2.4375,-1.375 1.99782,0.116 3.85745,-0.0201 5.34375,-0.375 3.07811,-0.735 5.0834,-1.10094 7.0625,-1.5 1.58791,-0.32018 2.2443,-0.79055 3,-1.09375 0.23751,-0.1068 0.4669,-0.19276 0.75,-0.25 1.13341,-0.22919 2.30465,0.20893 6.34375,-0.5 4.03942,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71581,-0.25944 1.70435,-0.56724 2.34375,-1.09375 1.9242,0.23949 3.7479,0.22453 5.1875,0 3.12642,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48875,-0.94514 3.59375,-1.09375 1.14642,-0.15418 2.27585,0.30157 6.34375,-0.21875 4.06781,-0.52032 5.56025,-0.69573 6.28125,-0.9375 0.73712,-0.24714 1.7981,-0.58623 2.4375,-1.125 2.05,0.33553 3.9737,0.39796 5.5,0.21875 3.1422,-0.36896 5.18,-0.55936 7.1875,-0.78125 1.61082,-0.17802 2.26465,-0.6082 3.03125,-0.84375 0.24091,-0.0855 0.49405,-0.1556 0.78125,-0.1875 1.1497,-0.12772 2.3013,0.34665 6.375,-0.125 4.0737,-0.47165 5.55905,-0.6106 6.28125,-0.84375 0.71941,-0.23227 1.70025,-0.47346 2.34375,-0.96875 1.9363,0.33346 3.77005,0.40424 5.21875,0.25 3.14601,-0.33495 5.1775,-0.51859 7.1875,-0.71875 2.00991,-0.20014 2.48415,-0.82639 3.59375,-0.9375 1.1511,-0.11528 2.2965,0.36506 6.375,-0.0625 4.0785,-0.42756 5.5889,-0.56209 6.3125,-0.78125 0.73922,-0.22386 1.7956,-0.51325 2.4375,-1.03125 2.057,0.39867 4.00185,0.4934 5.53125,0.34375 3.14871,-0.3081 5.1758,-0.47325 7.1875,-0.65625 1.61401,-0.14682 2.26305,-0.56055 3.03125,-0.78125 0.2413,-0.0809 0.49355,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.2929,0.39275 6.375,0 4.08211,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6996,-0.4477 2.3437,-0.9375 1.9381,0.34999 3.7689,0.45438 5.2188,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1465,-0.32852 5.177,-0.5227 7.1874,-0.71875 1.613,-0.15729 2.2657,-0.63148 3.0313,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7166,-0.25316 1.6746,-0.55807 2.3124,-1.09375 1.9197,0.21194 3.72,0.15141 5.1563,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0937,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5626,-1.28125 1.1287,-0.25066 2.2702,0.11629 6.25,-0.875 3.9795,-0.99127 5.4295,-1.4193 6.125,-1.78125 0.7222,-0.376 1.7617,-0.87058 2.375,-1.53125 1.9629,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.1446 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70652 2.3191,-1.70203 2.5312,-2 0.2123,-0.29795 0.099,-0.72855 0.125,-0.75 0.043,-0.0352 0.3404,-0.094 0.5,-0.4375 0.859,-1.84707 2.3232,-5.62764 2.4376,-6.3125 0.1137,-0.68214 0.168,-1.35277 0.2187,-1.75 0.029,-0.2295 -0.1471,-0.8789 -0.125,-0.9375 0.031,-0.082 0.2883,-0.25057 0.3437,-0.5 0.2663,-1.19831 0.089,-2.20736 -0.125,-3.625 -0.2139,-1.41763 -0.9716,-4.61463 -1.625,-5.46875 -0.6589,-0.86172 -1.2248,-1.01051 -1.75,-1 z"
+             id="path8089-9"
+             sodipodi:nodetypes="ccssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssscccccssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssssssssc" />
+          <g
+             clip-path="url(#clipPath7421-7)"
+             id="g8091-4">
+            <path
+               inkscape:connector-curvature="0"
+               id="path8093-3"
+               d="m 1107.409,-284.04961 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88717,-0.50701 -5.875,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0725 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0774 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,10e-6 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 10e-6,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0532 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 10e-6,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0728,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 10e-6,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0773,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.4497,-0.12571 6.375,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -10e-5,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -1e-4,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7001-5);enable-background:new"
+               sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8095-5"
+               d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6949-4);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8097-1"
+               d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6961-8);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8099-7"
+               d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6957-9);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8101-4"
+               d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.4428,3.93956 1.5794,5.38995 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.9442,0.42864 -1.2366,0.49452 0.531,0.18589 0.8908,0.21322 0.9524,1.05768 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.9524,0.18199 -1.288,0.0511 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6997-5);enable-background:new"
+               sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8103-3"
+               d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6953-8);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8105-1"
+               d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6993-3);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8107-4"
+               d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6989-8);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8109-6"
+               d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6985-6);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8111-9"
+               d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6965-3);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8113-4"
+               d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6981-3);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8115-2"
+               d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6977-6);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8117-2"
+               d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6973-4);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8119-6"
+               d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+               style="display:inline;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter6969-8);enable-background:new" />
+            <g
+               id="g8121-4"
+               style="fill:#ffffff;fill-opacity:1;filter:url(#filter7345-9)">
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8123-1"
+                 d="m 744.9375,-212.11731 c 0,0 7.22229,-3.22318 9.0625,-3.5 1.84021,-0.27682 3.35225,-0.003 6,0.5625 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 5.3125,3.5625 5.3125,3.5625 0,0 -7.14644,-2.78019 -10.1875,-3.5625 -3.04106,-0.78231 -7.64461,-2.08374 -10.375,-2.3125 -2.73039,-0.22876 -11,1.875 -11,1.875 z"
+                 style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8125-2"
+                 d="m 735.46875,-206.95416 c 0,0 3.65979,-2.22318 5.5,-2.5 1.84021,-0.27682 3.66475,0.24677 6.3125,0.8125 2.64775,0.56573 8.7357,2.21518 11.1875,3.375 2.4518,1.15982 6.5625,2.125 6.5625,2.125 0,0 -8.39644,-1.34269 -11.4375,-2.125 -3.04106,-0.78231 -7.95711,-2.33374 -10.6875,-2.5625 -2.73039,-0.22876 -7.4375,0.875 -7.4375,0.875 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8127-8"
+                 d="m 759.85042,-217.61116 c 0,0 8.5437,-3.29857 10.39778,-3.45786 1.85409,-0.1593 3.64166,0.4792 6.2481,1.21208 2.60644,0.73288 8.57724,2.76594 10.95036,4.07925 2.37312,1.31331 6.41417,2.53782 6.41417,2.53782 0,0 -8.29413,-1.87365 -11.27931,-2.84767 -2.98519,-0.97402 -7.79269,-2.83478 -10.50302,-3.23662 -2.71033,-0.40184 -12.22808,1.713 -12.22808,1.713 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8129-8"
+                 d="m 775.19813,-223.2266 c 0,0 7.77133,-2.78244 9.62831,-2.90349 1.85697,-0.12104 3.631,0.55417 6.22178,1.34062 2.59077,0.78645 8.5184,2.94217 10.86394,4.30412 2.34555,1.36195 6.36049,2.6695 6.36049,2.6695 0,0 -8.25373,-2.04423 -11.21821,-3.07958 -2.96447,-1.03535 -7.73259,-2.99481 -10.43406,-3.45243 -2.70147,-0.45763 -11.42225,1.12126 -11.42225,1.12126 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-4.3190906"
+                 inkscape:transform-center-x="13.852145"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8131-9"
+                 d="m 789.64298,-227.95417 c 0,0 8.68256,-3.52031 10.54154,-3.60535 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.3006,1.78871 -12.3006,1.78871 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-4.3190906"
+                 inkscape:transform-center-x="13.852145"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8133-2"
+                 d="m 804.49513,-233.32948 c 0,0 7.80756,-2.58281 9.66654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -11.4256,0.85121 -11.4256,0.85121 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-4.3190906"
+                 inkscape:transform-center-x="13.852145"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8135-8"
+                 d="m 819.55763,-237.57948 c 0,0 8.55756,-2.58281 10.41654,-2.66785 1.85897,-0.085 3.61958,0.62442 6.19463,1.46093 2.57505,0.83649 8.45979,3.10666 10.77851,4.5138 2.31872,1.40715 6.30757,2.79224 6.30757,2.79224 0,0 -8.21257,-2.20377 -11.15643,-3.29636 -2.94386,-1.09259 -7.67312,-3.14408 -10.36522,-3.65397 -2.69209,-0.50988 -12.1756,0.85121 -12.1756,0.85121 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-4.9269042"
+                 inkscape:transform-center-x="13.64141"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8137-8"
+                 d="m 836.23395,-242.60125 c 0,0 6.96702,-1.98723 8.82784,-1.96757 1.86081,0.0197 3.57873,0.82702 6.10265,1.80705 2.52393,0.98 8.27166,3.57758 10.50756,5.11291 2.2359,1.53535 6.14053,3.14261 6.14053,3.14261 0,0 -8.07561,-2.66222 -10.95336,-3.91866 -2.87774,-1.25645 -7.48412,-3.5707 -10.14328,-4.23121 -2.65915,-0.66049 -10.48194,0.0549 -10.48194,0.0549 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.1542119"
+                 inkscape:transform-center-x="13.55068"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8139-8"
+                 d="m 850.73028,-246.00461 c 0,0 7.68784,-2.02768 9.54782,-1.96854 1.85997,0.0592 3.56038,0.90279 6.06293,1.93616 2.50255,1.03334 8.19387,3.75232 10.39668,5.33475 2.20282,1.58245 6.07245,3.2722 6.07245,3.2722 0,0 -8.01729,-2.83298 -10.86772,-4.15022 -2.85043,-1.31723 -7.40666,-3.72872 -10.0512,-4.4455 -2.64454,-0.71678 -11.16096,0.0211 -11.16096,0.0211 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.4740887"
+                 inkscape:transform-center-x="13.41151"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8141-6"
+                 d="m 864.82496,-249.21081 c 0,0 8.16952,-1.96906 10.02688,-1.85396 1.85735,0.11512 3.53158,1.00956 6.0019,2.11779 2.47031,1.10821 8.0772,3.99727 10.23138,5.64531 2.15418,1.64804 5.9712,3.45352 5.9712,3.45352 0,0 -7.92839,-3.07306 -10.73787,-4.4755 -2.80949,-1.40244 -7.29106,-3.94999 -9.91283,-4.74606 -2.62176,-0.79606 -11.58066,-0.1411 -11.58066,-0.1411 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.79376"
+                 inkscape:transform-center-x="13.258805"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8143-8"
+                 d="m 881.38485,-251.60282 c 0,0 8.08536,-1.90809 9.93837,-1.73664 1.853,0.17147 3.4993,1.11633 5.93482,2.29908 2.43553,1.18271 7.95209,4.2407 10.05523,5.95339 2.10314,1.7127 5.86357,3.63326 5.86357,3.63326 0,0 -7.8314,-3.3124 -10.597,-4.7995 -2.76561,-1.48712 -7.16775,-4.16959 -9.76414,-5.04491 -2.59637,-0.87531 -11.43085,-0.30468 -11.43085,-0.30468 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8145-3"
+                 d="m 896.58415,-254.34724 c 0,0 7.64166,-1.4277 9.49547,-1.26515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-0.76897 -10.99774,-0.76897 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8147-8"
+                 d="m 911.45328,-255.98544 c 0,0 8.64166,-1.5527 10.49547,-1.39015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.99774,-0.64397 -11.99774,-0.64397 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8149-3"
+                 d="m 927.70328,-258.29794 c 0,0 7.64166,-0.8652 9.49547,-0.70265 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -10.99774,-1.33147 -10.99774,-1.33147 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8151-3"
+                 d="m 942.82828,-259.48544 c 0,0 8.57916,-1.4902 10.43297,-1.32765 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.93524,-0.70647 -11.93524,-0.70647 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8153-3"
+                 d="m 959.07828,-261.54794 c 0,0 7.82916,-0.8027 9.68297,-0.64015 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08372,5.90502 2.11134,1.70258 5.88096,3.60505 5.88096,3.60505 0,0 -7.84723,-3.27474 -10.61995,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.18524,-1.39397 -11.18524,-1.39397 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8155-8"
+                 d="m 974.45328,-262.79794 c 0,0 8.39166,-1.1777 10.24547,-1.01515 1.8538,0.16256 3.50462,1.0995 5.94579,2.27053 2.44118,1.171 7.97238,4.20246 10.08376,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.84721,-3.27474 -10.61993,-4.74855 -2.77271,-1.4738 -7.18769,-4.13509 -9.78825,-4.99793 -2.60055,-0.86282 -11.74774,-1.01897 -11.74774,-1.01897 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8157-0"
+                 d="m 990.64078,-264.86044 c 0,0 6.89166,-0.9902 8.74547,-0.82765 1.85385,0.16256 3.50465,1.0995 5.94575,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.60053,-0.86282 -10.24772,-1.20647 -10.24772,-1.20647 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8159-4"
+                 d="m 1007.7658,-265.79794 c 0,0 6.8291,-1.1777 8.683,-1.01515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -10.1852,-1.01897 -10.1852,-1.01897 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8161-7"
+                 d="m 1023.8908,-267.79794 c 0,0 6.0791,-0.4277 7.933,-0.26515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.4352,-1.76897 -9.4352,-1.76897 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.7433893"
+                 inkscape:transform-center-x="13.28378"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8163-6"
+                 d="m 1039.7033,-269.17294 c 0,0 6.4541,-0.6777 8.308,-0.51515 1.8538,0.16256 3.5046,1.0995 5.9457,2.27053 2.4412,1.171 7.9724,4.20246 10.0838,5.90502 2.1113,1.70258 5.8809,3.60505 5.8809,3.60505 0,0 -7.8472,-3.27474 -10.6199,-4.74855 -2.7727,-1.4738 -7.1877,-4.13509 -9.7883,-4.99793 -2.6005,-0.86282 -9.8102,-1.51897 -9.8102,-1.51897 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-5.1360724"
+                 inkscape:transform-center-x="13.55813"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8165-8"
+                 d="m 1055.2718,-271.03319 c 0,0 5.4976,-0.90945 7.3578,-0.85348 1.8601,0.056 3.5619,0.89674 6.0661,1.92586 2.5044,1.0291 8.2003,3.7384 10.4058,5.31709 2.2055,1.57871 6.078,3.2619 6.078,3.2619 0,0 -8.022,-2.81939 -10.8748,-4.13178 -2.8526,-1.31238 -7.4129,-3.71613 -10.0587,-4.42843 -2.6457,-0.71228 -8.9742,-1.09116 -8.9742,-1.09116 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-4.6370147"
+                 inkscape:transform-center-x="13.74758"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8167-9"
+                 d="m 1072.7007,-273.48537 c 0,0 4.5472,-1.15581 6.408,-1.18621 1.8607,-0.0304 3.5996,0.73049 6.1489,1.64231 2.5494,0.91177 8.3649,3.35386 10.6414,4.8285 2.2763,1.47468 6.2227,2.97636 6.2227,2.97636 0,0 -8.1442,-2.44411 -11.0547,-3.62272 -2.9105,-1.1786 -7.5774,-3.36815 -10.2534,-3.95691 -2.6759,-0.58875 -8.1129,-0.68133 -8.1129,-0.68133 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 inkscape:transform-center-y="-4.4842392"
+                 inkscape:transform-center-x="13.79933"
+                 sodipodi:nodetypes="czzzczzc"
+                 id="path8169-0"
+                 d="m 1087.1585,-276.5244 c 0,0 5.96,-1.77355 7.8202,-1.83024 1.86,-0.0567 3.6096,0.67955 6.1715,1.55525 2.562,0.87566 2.5226,0.85713 5.3335,1.49015 2.7969,0.62986 7.0767,1.51313 7.0767,1.51313 0,0 -3.6155,-0.0163 -6.7923,-0.46614 -3.1155,-0.44119 -7.3743,-1.69825 -10.0584,-2.24913 -2.6839,-0.55088 -9.5512,-0.013 -9.5512,-0.013 z"
+                 style="display:inline;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new" />
+              <path
+                 inkscape:connector-curvature="0"
+                 sodipodi:nodetypes="czczc"
+                 id="path8171-6"
+                 d="m 1099.25,-279.92981 c 0.1612,0.26862 11.2081,-4.60046 12.1875,-4.6875 0.9794,-0.087 2,3.125 2,3.125 0,0 -0.7751,-1.50434 -2.875,-1.0625 -2.0999,0.44184 -11.3009,2.67141 -11.3125,2.625 z"
+                 style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+            </g>
+            <path
+               inkscape:connector-curvature="0"
+               id="path8173-8"
+               d="m 1107.4532,-284.0938 c -0.4187,0.21283 -0.1556,0.0939 -0.6472,0.30581 -0.4861,0.20954 -1.7234,0.57439 -4.0796,1.45895 -3.3311,1.25057 -5.8302,2.15344 -7.0259,3.0661 -1.5361,0.0213 -3.7205,0.23331 -5.6563,0.71875 -2.9815,0.74766 -4.8552,1.17401 -6.75,1.59375 -1.8948,0.41972 -1.6755,0.64219 -2.875,0.875 -1.2966,0.25166 -1.7214,-0.009 -5.4375,0.78125 -3.4899,0.74214 -8.8948,1.93107 -10.1562,2.6875 -1.5839,-0.18079 -3.8675,-0.32178 -5.8438,-0.0312 -3.0404,0.44695 -4.9162,0.67276 -6.8437,0.90625 -0.6554,0.0794 -1.0411,0.20078 -1.3438,0.28125 -0.4262,0.13165 -0.6858,0.26002 -1.375,0.34375 -1.3116,0.15936 -1.7622,-0.15683 -5.5312,0.28125 -3.5539,0.41308 -9.0054,1.27282 -10.25,1.9375 -1.599,-0.2973 -3.8578,-0.53419 -5.8438,-0.34375 -3.0588,0.29331 -4.972,0.48399 -6.9062,0.65625 -1.9343,0.17226 -1.6887,0.42237 -2.9063,0.53125 -1.3162,0.11769 -1.7598,-0.16363 -5.5312,0.25 -3.5419,0.38844 -9.0079,1.20927 -10.2813,1.875 -1.5989,-0.2947 -3.88718,-0.50701 -5.87501,-0.3125 -3.05824,0.29924 -4.94113,0.48024 -6.875,0.65625 -0.65749,0.0598 -1.04004,0.17856 -1.34375,0.25 -0.42765,0.11895 -0.68351,0.21807 -1.375,0.28125 -1.31596,0.12025 -1.75976,-0.19488 -5.53125,0.21875 -3.55614,0.39001 -9.00554,1.23916 -10.25,1.90625 -1.59863,-0.29419 -3.85984,-0.52372 -5.84375,-0.3125 -3.0556,0.32532 -4.97404,0.52624 -6.90625,0.71875 -1.93221,0.1925 -1.68987,0.44088 -2.90625,0.5625 -1.31488,0.13146 -1.76298,-0.16454 -5.53125,0.28125 -3.53887,0.41865 -8.97768,1.29217 -10.25,1.96875 -1.59755,-0.28105 -3.85996,-0.42043 -5.84375,-0.1875 -3.05198,0.35836 -4.94508,0.56786 -6.875,0.78125 -0.6562,0.0726 -1.04066,0.17269 -1.34375,0.25 -0.42677,0.12722 -0.68491,0.2672 -1.375,0.34375 -1.31333,0.14568 -1.76746,-0.17402 -5.53125,0.3125 -3.54889,0.45875 -8.97863,1.41902 -10.21875,2.125 -1.59305,-0.24424 -3.83381,-0.38135 -5.8125,-0.125 -3.04759,0.39481 -4.95071,0.64845 -6.875,0.90625 -1.92428,0.25779 -1.72611,0.49353 -2.9375,0.65625 -1.30946,0.1759 -1.74719,-0.10438 -5.5,0.46875 -3.52429,0.53824 -8.92315,1.69917 -10.1875,2.4375 -1.5875,-0.20354 -3.8455,-0.25473 -5.8125,0.0937 -3.02617,0.53612 -4.89889,0.86169 -6.8125,1.1875 -0.65061,0.11077 -1.01371,0.27094 -1.3125,0.375 -0.42067,0.16488 -0.66345,0.3313 -1.34375,0.46875 -1.29465,0.26159 -1.72712,-0.006 -5.4375,0.8125 -3.49853,0.77195 -8.84595,2.38293 -10.0625,3.21875 -1.56278,-0.0775 -3.75758,0.0853 -5.6875,0.59375 -2.97244,0.78313 -4.81761,1.23209 -6.6875,1.75 -1.86988,0.5179 -1.6666,0.76728 -2.84375,1.09375 -1.27246,0.3529 -1.69703,0.10709 -5.34375,1.1875 -3.4247,1.01463 -8.64944,2.93317 -9.875,3.84375 -1.53883,0.0127 -3.71983,0.27222 -5.625,0.875 -2.93106,0.92734 -4.75031,1.45842 -6.59375,2.0625 -0.62676,0.20538 -0.99173,0.39258 -1.28125,0.53125 -0.40763,0.21361 -0.65334,0.40875 -1.3125,0.625 -1.25446,0.41154 -1.68611,0.18904 -5.28125,1.4375 -3.38985,1.17717 -8.59498,3.2137 -9.78125,4.15625 -1.52389,0.0597 -3.65005,0.39487 -5.53125,1.0625 -2.89739,1.02829 -4.69908,1.67548 -6.53125,2.3125 -1.83217,0.63701 -1.62785,0.84854 -2.78125,1.25 -1.24678,0.43396 -1.66361,0.19972 -5.21875,1.5625 -3.33867,1.2798 -8.48715,3.48255 -9.6875,4.46875 -1.50718,0.10769 -3.63569,0.4988 -5.5,1.21875 -2.86818,1.1076 -4.6238,1.78156 -6.4375,2.46875 -0.61666,0.23363 -0.99641,0.44203 -1.28125,0.59375 0,0 0,1.09375 0,1.09375 0.11178,-0.22236 0.38599,-0.81743 0.90625,-1.09375 0.69797,-0.37072 4.81363,-1.99337 6.8125,-2.71875 1.65686,-0.60125 4.15389,-1.32868 5.96875,-1.3125 0.30162,0.003 0.58762,0.0509 0.84375,0.0937 1.84249,0.30825 7.46875,1.5625 7.46875,1.5625 -10e-6,0 -6.23349,-1.64675 -7.03125,-1.84375 -0.19079,-0.0471 -0.53572,-0.0687 -0.96875,-0.0625 1.14546,-0.86971 4.761,-2.39351 7.34375,-3.4375 2.83822,-1.14727 3.11681,-1.25182 5.0625,-1.65625 2.0083,-0.41744 3.15625,-0.5 3.15625,-0.5 0,1e-5 -0.0824,-0.60114 0.96875,-1.125 0.7051,-0.35141 4.88702,-1.8924 6.90625,-2.5625 1.9519,-0.64773 5.0574,-1.3585 6.875,-1 1.86323,0.3675 7.53125,1.8125 7.53125,1.8125 1e-5,0 -6.287,-1.87111 -7.09375,-2.09375 -0.19292,-0.0533 -0.53084,-0.086 -0.96875,-0.0937 1.15834,-0.83288 4.79444,-2.19532 7.40625,-3.15625 2.87016,-1.05601 3.16734,-1.1618 5.125,-1.53125 1.85349,-0.34979 2.85884,-0.42548 3.03125,-0.4375 0.1136,-0.21724 0.37745,-0.81002 0.90625,-1.0625 0.70944,-0.33874 4.92607,-1.71275 6.96875,-2.3125 1.69317,-0.49711 4.24077,-1.03677 6.09375,-0.90625 0.30795,0.0217 0.61349,0.0973 0.875,0.15625 1.88118,0.42432 7.59375,2.03125 7.59375,2.03125 1e-5,0 -6.34174,-2.06525 -7.15625,-2.3125 -0.19479,-0.0591 -0.55788,-0.10394 -1,-0.125 1.16949,-0.79755 4.86302,-2.05622 7.5,-2.9375 2.89781,-0.96847 3.23301,-1.00332 5.21875,-1.28125 2.04965,-0.28689 3.1875,-0.3125 3.1875,-0.3125 -2e-5,0 -0.0727,-0.60697 1,-1.0625 0.7196,-0.30557 4.99098,-1.50075 7.0625,-2 2.00244,-0.48258 5.19849,-0.92829 7.0625,-0.40625 1.91078,0.53515 7.71875,2.5 7.71875,2.5 0,0 -6.42266,-2.42351 -7.25,-2.71875 -0.19784,-0.0706 -0.58216,-0.14039 -1.03125,-0.1875 1.1879,-0.72865 4.91527,-1.77408 7.59375,-2.5 2.94342,-0.79775 3.29208,-0.77083 5.3125,-0.90625 1.91289,-0.12823 2.94705,-0.0711 3.125,-0.0625 0.11728,-0.20366 0.39176,-0.77948 0.9375,-0.96875 0.73219,-0.25394 5.07852,-1.04789 7.1875,-1.375 1.74813,-0.27111 4.40088,-0.4847 6.3125,-0.0937 0.31766,0.065 0.60522,0.18551 0.875,0.28125 1.94074,0.68873 7.84375,3.09375 7.84375,3.09375 1e-5,0 -6.53471,-2.95077 -7.375,-3.3125 -0.20097,-0.0865 -0.57513,-0.16679 -1.03125,-0.25 1.2065,-0.63318 5.02956,-1.3956 7.75,-1.90625 2.98953,-0.56119 3.30023,-0.52954 5.34375,-0.53125 2.10926,-0.002 3.3125,0.125 3.3125,0.125 0,1e-5 -0.0727,-0.63119 1.03125,-0.9375 0.74052,-0.20547 5.12612,-0.83387 7.25,-1.0625 2.05302,-0.22099 5.31863,-0.25222 7.21875,0.46875 1.94779,0.73907 7.84375,3.375 7.84375,3.375 2e-5,0 -6.56288,-3.17897 -7.40625,-3.5625 -0.20168,-0.0917 -0.54221,-0.18621 -1,-0.28125 1.21092,-0.60188 4.98442,-1.24884 7.71875,-1.65625 3.0048,-0.44772 3.32551,-0.4517 5.375,-0.40625 1.94045,0.043 3.00699,0.19423 3.1875,0.21875 0.11892,-0.19316 0.3839,-0.76583 0.9375,-0.90625 0.74271,-0.18838 5.15429,-0.73428 7.28125,-0.9375 1.76303,-0.16842 4.42009,-0.23429 6.34375,0.25 0.31968,0.0805 0.60351,0.20359 0.875,0.3125 1.95293,0.78349 7.90625,3.46875 7.90625,3.46875 -2e-5,0 -6.59191,-3.25348 -7.4375,-3.65625 -0.20222,-0.0963 -0.57226,-0.20703 -1.03125,-0.3125 1.21414,-0.57427 5.04366,-1.12219 7.78125,-1.5 3.00838,-0.4152 3.32307,-0.44263 5.375,-0.375 2.11798,0.0698 3.3125,0.25 3.3125,0.25 -2e-5,0 -0.0772,-0.63741 1.03125,-0.90625 0.74362,-0.18035 5.15176,-0.66355 7.28125,-0.84375 2.05847,-0.17417 5.34324,-0.12432 7.25,0.65625 1.95459,0.80016 7.875,3.53125 7.875,3.53125 -2e-5,0 -6.55993,-3.30876 -7.40625,-3.71875 -0.20237,-0.0981 -0.57186,-0.2031 -1.03125,-0.3125 1.21517,-0.5639 5.01008,-1.1143 7.75,-1.46875 3.01091,-0.38952 3.32131,-0.39765 5.375,-0.3125 1.94439,0.0806 3.00663,0.25324 3.1875,0.28125 0.11916,-0.19086 0.38277,-0.74531 0.9375,-0.875 0.74426,-0.174 5.14993,-0.65047 7.28125,-0.8125 1.76662,-0.13427 4.44971,-0.12571 6.37501,0.375 0.32,0.0832 0.6033,0.20127 0.875,0.3125 1.9546,0.80016 7.9063,3.5625 7.9063,3.5625 -1e-4,0 -6.5912,-3.34001 -7.4375,-3.75 -0.2024,-0.0981 -0.5719,-0.20311 -1.0313,-0.3125 1.2151,-0.5639 5.0413,-1.08306 7.7813,-1.4375 3.0109,-0.38953 3.3525,-0.4289 5.4062,-0.34375 2.1197,0.0879 3.3125,0.3125 3.3125,0.3125 0,0 -0.078,-0.64902 1.0313,-0.90625 0.7443,-0.17256 5.1495,-0.62336 7.2812,-0.78125 2.0606,-0.1526 5.3429,-0.0968 7.25,0.6875 1.955,0.80395 7.875,3.5 7.875,3.5 0,0 -6.5598,-3.27587 -7.4062,-3.6875 -0.2025,-0.0984 -0.5718,-0.20222 -1.0313,-0.3125 1.2154,-0.56154 5.0119,-1.12778 7.75,-1.5 3.009,-0.40905 3.3227,-0.41558 5.375,-0.34375 1.9431,0.068 3.0072,0.16485 3.1875,0.1875 0.1188,-0.1944 0.3846,-0.72881 0.9375,-0.875 0.7418,-0.19612 5.1311,-0.82878 7.25,-1.09375 1.7564,-0.21961 4.4053,-0.33231 6.3125,0.0312 0.3169,0.0604 0.6058,0.18938 0.875,0.28125 1.9362,0.66092 7.8438,2.9375 7.8438,2.9375 -10e-5,0 -6.5367,-2.80655 -7.375,-3.15625 -0.2005,-0.0836 -0.5762,-0.17333 -1.0313,-0.25 1.2037,-0.65046 5.0191,-1.37195 7.7188,-2 2.9667,-0.6902 3.2889,-0.75507 5.3125,-0.875 2.0886,-0.1238 3.2812,-0.0312 3.2812,-0.0312 0,1e-5 -0.087,-0.63205 1,-1.03125 0.7292,-0.2678 5.0472,-1.33797 7.125,-1.8125 2.0085,-0.45869 5.1679,-1.0293 7,-0.625 1.8781,0.41446 13.5782,3.01563 13.5782,3.01563 0,0 -12.3275,-3.02266 -13.1407,-3.26563 -0.1945,-0.0581 -0.5586,-0.10626 -1,-0.125 1.1676,-0.80369 3.5142,-1.6873 6.1094,-2.70312 1.6814,-0.65818 0.9237,-0.37659 2.7759,-1.0036 1.7536,-0.59366 2.4854,-1.01071 2.6304,-1.11299 0.3461,-0.20651 -0.356,-0.12188 -0.5442,-0.0424 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7333-7);enable-background:new"
+               sodipodi:nodetypes="czscsssscssssscsssscssssscsssscssssscsssscssssscsssscssssscsssscssccsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscsssscscsscssscscsscc" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8175-7"
+               d="m 1082.625,-275.125 c 1.873,0.39348 4.4961,1.14555 6.0313,1.96875 1.5352,0.82319 2.8222,1.056 5.375,2.5 2.5266,1.42926 4.7958,2.00696 6.9687,2.53125 2.3476,0.56642 5.4354,0.71523 8.8438,1.1875 -1.0889,-0.83975 -6.6074,-1.17245 -8.4063,-1.5625 -1.7989,-0.39006 -3.8941,-1.01616 -6.5937,-2.3125 -2.6997,-1.29634 -3.4944,-1.79896 -5.8125,-2.6875 -2.3182,-0.88854 -4.0044,-1.38314 -6.4063,-1.625 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7285-4);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8177-9"
+               d="m 1051.4688,-270 c 1.9053,0.57759 4.5281,1.61572 6.0937,2.59375 1.5656,0.97802 2.8802,1.35981 5.5,3.125 2.593,1.74716 4.9859,2.70927 7.25,3.59375 2.4461,0.95557 5.6826,1.65713 9.4063,3.0625 -1.1896,-1.13784 -7.0631,-2.68675 -8.9375,-3.375 -1.8745,-0.68825 -4.0818,-1.5662 -6.875,-3.28125 -2.7933,-1.71504 -3.5736,-2.2839 -5.9375,-3.40625 -2.3641,-1.12234 -4.0567,-1.83455 -6.5,-2.3125 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7289-0);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8179-0"
+               d="m 1020.2188,-266.84375 c 1.9119,0.63811 4.5812,1.75536 6.1562,2.8125 1.5751,1.05715 2.8956,1.50867 5.5313,3.40625 2.6086,1.87821 5.0284,3.03003 7.3125,4.0625 2.4677,1.11545 5.7645,2.1733 9.5312,3.84375 -1.2033,-1.22253 -7.2028,-3.31423 -9.0937,-4.125 -1.891,-0.81077 -4.0649,-1.89379 -6.875,-3.75 -2.8102,-1.8562 -3.6218,-2.47693 -6,-3.71875 -2.3783,-1.2418 -4.1107,-1.97569 -6.5625,-2.53125 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7293-0);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8181-3"
+               d="m 1110.1719,-266.89063 c 0.1508,0.0486 0.688,0.631 0.1094,1.48438 -0.8101,1.19459 -5.7049,3.32429 -8.5625,4.125 -2.8449,0.79712 -6.2901,0.97774 -10.5625,-0.375 -4.3016,-1.36195 -5.4697,-2.46872 -10.6563,-4.3125 4.664,2.11517 6.1953,3.95233 10.125,5.34375 1.6207,0.57387 3.3671,0.9396 5.0625,1.03125 -0.4451,0.32563 -1.5303,0.9833 -3.5625,1.59375 -2.7955,0.83969 -6.6491,1.53378 -8.25,1.625 -1.5146,0.0863 -3.142,-0.51249 -3.4375,-0.625 0.1667,0.10308 0.3732,0.37734 -0.25,1.03125 -0.8993,0.94363 -6.1474,1.923 -9.125,2.25 -2.9643,0.32555 -6.5216,-0.016 -10.9062,-1.90625 -3.978,-1.71497 -5.339,-2.91536 -9.4063,-4.75 0,0 0,0.15625 0,0.15625 3.6431,2.09529 5.284,3.88327 8.875,5.5625 1.7302,0.80909 3.5917,1.40876 5.4063,1.71875 -0.5349,0.28676 -1.5578,0.71151 -3.4375,1.03125 -2.869,0.48796 -6.809,0.81614 -8.4375,0.75 -0.8507,-0.0345 -1.7286,-0.18437 -2.4063,-0.40625 -0.6848,-0.21488 -1.1897,-0.44467 -1.3125,-0.5 0.1694,0.10721 0.4311,0.40288 -0.2187,1.03125 -0.9097,0.87962 -6.2461,1.33638 -9.25,1.46875 -2.9905,0.13179 -6.5889,-0.45063 -11,-2.5625 -4.4412,-2.12626 -5.6415,-3.4016 -10.9063,-5.78125 4.7343,2.59704 6.2865,4.6291 10.3438,6.71875 1.6733,0.86185 3.4852,1.49425 5.25,1.9375 -0.4633,0.23332 -1.5894,0.68814 -3.6875,0.9375 -2.8863,0.34298 -6.8346,0.49288 -8.4688,0.375 -1.5462,-0.1115 -3.2312,-0.85696 -3.5312,-1 0.1691,0.12029 0.4138,0.41048 -0.2188,1 -0.9128,0.85073 -6.2441,1.26212 -9.25,1.375 -2.9925,0.11237 -6.5897,-0.49043 -11,-2.59375 -4.00125,-1.90823 -5.38803,-3.13783 -9.46875,-5.09375 -3e-5,0 0,0.15625 0,0.15625 3.65506,2.20392 5.29421,4.05255 8.90625,5.90625 1.74029,0.89315 3.637,1.52827 5.4688,1.96875 -0.54,0.2483 -1.5781,0.61533 -3.4688,0.84375 -2.88568,0.34858 -6.86605,0.52095 -8.5,0.40625 -0.85345,-0.0599 -1.72631,-0.25791 -2.40625,-0.5 -0.6871,-0.2353 -1.18935,-0.47226 -1.3125,-0.53125 0.16998,0.11227 0.46448,0.42225 -0.1875,1.03125 -0.91265,0.8525 -6.27533,1.29337 -9.28125,1.40625 -2.99246,0.11237 -6.59346,-0.52805 -11,-2.59375 -4.43653,-2.07978 -5.64688,-3.33171 -10.90625,-5.65625 4.72938,2.54749 6.29074,4.5778 10.34375,6.625 1.67155,0.84433 3.48554,1.46643 5.25,1.90625 -0.46323,0.23422 -1.5897,0.68407 -3.6875,0.9375 -2.88569,0.34858 -6.8362,0.56952 -8.46875,0.46875 -1.54456,-0.0953 -3.20031,-0.82885 -3.5,-0.96875 0.16899,0.11853 0.38192,0.40385 -0.25,1 -0.91186,0.86028 -6.24665,1.33025 -9.25,1.46875 -2.98995,0.1379 -6.56745,-0.45068 -10.96875,-2.46875 -3.99308,-1.83089 -5.36511,-3.0292 -9.4375,-4.90625 -2e-5,0 0,0.15625 0,0.15625 3.64761,2.13327 5.27033,3.93487 8.875,5.71875 1.73675,0.85951 3.60727,1.45014 5.4375,1.875 -0.53947,0.2529 -1.55063,0.64129 -3.4375,0.90625 -2.87978,0.40436 -6.83813,0.64562 -8.46875,0.5625 -0.85172,-0.0434 -1.7277,-0.20855 -2.40625,-0.4375 -0.68569,-0.22201 -1.1896,-0.44339 -1.3125,-0.5 0.16959,0.10899 0.4319,0.40965 -0.21875,1.03125 -0.91079,0.87014 -6.25021,1.39152 -9.25,1.5625 -2.98633,0.17021 -6.57381,-0.31577 -10.96875,-2.28125 -4.42489,-1.97888 -5.60596,-3.22819 -10.84375,-5.375 4.70997,2.38767 6.27017,4.38873 10.3125,6.34375 1.66715,0.80631 3.46043,1.39658 5.21875,1.78125 -0.46163,0.2487 -1.597,0.71225 -3.6875,1.03125 -2.8756,0.43876 -6.7804,0.7331 -8.40625,0.6875 -1.53823,-0.0431 -3.2328,-0.74522 -3.53125,-0.875 0.16833,0.11282 0.41057,0.41375 -0.21875,1.03125 -0.90812,0.8911 -6.20295,1.52825 -9.1875,1.8125 -2.97118,0.28298 -6.57342,-0.1758 -10.9375,-1.9375 -3.95934,-1.59831 -5.32915,-2.79487 -9.34375,-4.3125 3e-5,0 0,0.15625 0,0.15625 3.5959,1.81135 5.23831,3.58233 8.8125,5.15625 1.72207,0.75835 3.58748,1.28895 5.40625,1.625 -0.53609,0.27908 -1.56658,0.68763 -3.4375,1.0625 -2.85539,0.5721 -6.78942,1.01939 -8.40625,1.03125 -0.84451,0.006 -1.70608,-0.0809 -2.375,-0.25 -0.67591,-0.16151 -1.16009,-0.32923 -1.28125,-0.375 0.16722,0.094 0.42267,0.38348 -0.21875,1.0625 -0.89787,0.95052 -6.18648,1.91708 -9.125,2.4375 -2.92534,0.51809 -6.43215,0.37424 -10.71875,-1.03125 -4.3158,-1.41507 -5.47277,-2.52994 -10.5625,-3.96875 4.57685,1.75101 6.08855,3.56006 10.03125,5 1.62608,0.59389 3.36885,0.95565 5.09375,1.15625 -0.45285,0.29702 -1.55478,0.88339 -3.59375,1.46875 -2.80472,0.80517 -6.63886,1.57583 -8.21875,1.75 -1.49475,0.1648 -3.11623,-0.31681 -3.40625,-0.40625 0.16356,0.0901 0.39278,0.35993 -0.21875,1.0625 -0.88247,1.01385 -6.04452,2.37165 -8.9375,3.0625 -2.88002,0.68778 -6.3356,0.76002 -10.5625,-0.4375 -3.83485,-1.08645 -5.17258,-2.07237 -9.0625,-3.125 -10e-6,0 0,0.15625 0,0.15625 3.48418,1.39485 5.06941,2.9194 8.53125,4.03125 1.66793,0.53572 3.45578,0.78674 5.21875,0.875 -0.51964,0.35212 -1.50039,0.91452 -3.3125,1.53125 -2.76566,0.94125 -6.59024,1.93537 -8.15625,2.15625 -0.81794,0.11539 -1.6331,0.12283 -2.28125,0.0312 -0.65496,-0.0832 -1.1326,-0.21827 -1.25,-0.25 0.16204,0.0746 0.43399,0.34044 -0.1875,1.09375 -0.87,1.05453 -6.00963,2.65925 -8.875,3.4375 -2.85253,0.77476 -6.25912,0.9582 -10.4375,-0.0937 -4.20683,-1.05913 -5.35669,-2.04166 -10.34375,-3.15625 4.48454,1.45946 5.96935,3.13523 9.8125,4.25 1.58504,0.45977 3.28679,0.63825 4.96875,0.6875 -0.44157,0.33676 -1.51251,1.02773 -3.5,1.78125 -2.73393,1.03649 -6.45198,2.16269 -8,2.4375 -1.46462,0.26002 -3.05958,-0.11654 -3.34375,-0.1875 0.16025,0.0796 0.38044,0.32098 -0.21875,1.0625 -0.86466,1.07006 -5.91652,2.81815 -8.75,3.6875 -2.8208,0.86547 -6.2075,1.15631 -10.34375,0.21875 -3.75259,-0.85061 -5.04785,-1.71647 -8.875,-2.59375 0,0 0,0.15625 0,0.15625 3.42796,1.23779 4.98741,2.6323 8.375,3.53125 1.63216,0.43314 3.36704,0.58301 5.09375,0.5625 -0.50893,0.38417 -1.47675,1.02182 -3.25,1.75 -2.70634,1.11134 -6.43633,2.30781 -7.96875,2.625 -0.8004,0.16569 -1.61231,0.21862 -2.25,0.15625 0,0 0,0.51552 0,0.92229 0,0.26507 0,0.48396 0,0.48396 0.22645,-0.14468 0.44891,-0.27261 0.71875,-0.375 1.08052,-0.40998 2.17161,-0.21577 6,-1.6875 3.82843,-1.47174 5.22412,-2.00498 5.90625,-2.40625 0.6796,-0.39978 1.61165,-0.87937 2.21875,-1.53125 1.82685,-0.13775 3.57075,-0.49323 4.9375,-1 2.96812,-1.10052 4.87537,-1.80619 6.78125,-2.46875 1.90586,-0.66254 2.35409,-1.41487 3.40625,-1.78125 1.09155,-0.38011 2.19511,-0.16538 6.0625,-1.53125 3.86745,-1.36586 5.28316,-1.82708 5.96875,-2.21875 0.70109,-0.40052 1.70081,-0.93298 2.3125,-1.59375 1.9708,-0.0547 3.81685,-0.38463 5.28125,-0.875 3.00148,-1.00508 4.92615,-1.62171 6.84375,-2.25 1.5386,-0.5041 2.17402,-1.04677 2.90625,-1.4375 0.23016,-0.13431 0.47574,-0.25373 0.75,-0.34375 1.09823,-0.36048 2.18145,-0.0814 6.09375,-1.3125 3.91233,-1.23113 5.36605,-1.67295 6.0625,-2.03125 0.69388,-0.35697 1.63015,-0.79261 2.25,-1.40625 1.86521,-0.0227 3.63581,-0.26683 5.03125,-0.6875 3.03043,-0.91354 4.99238,-1.4301 6.9375,-1.96875 1.94511,-0.53864 2.42618,-1.26452 3.5,-1.5625 1.11401,-0.30915 2.21994,0.007 6.1875,-1.03125 3.96761,-1.03863 5.41758,-1.43273 6.125,-1.75 0.73487,-0.32959 1.81383,-0.75372 2.4375,-1.375 1.99774,0.116 3.85743,-0.0201 5.34375,-0.375 3.07811,-0.735 5.08344,-1.10094 7.0625,-1.5 1.58792,-0.32018 2.24429,-0.79055 3,-1.09375 0.23757,-0.1068 0.46695,-0.19276 0.75,-0.25 1.13347,-0.22919 2.30448,0.20893 6.34375,-0.5 4.03933,-0.70893 5.50025,-0.92709 6.21875,-1.1875 0.71586,-0.25944 1.70428,-0.56724 2.34375,-1.09375 1.92427,0.23949 3.74788,0.22453 5.1875,0 3.12633,-0.48762 5.15455,-0.70067 7.15625,-0.96875 2.00171,-0.26807 2.48869,-0.94514 3.59375,-1.09375 1.14639,-0.15418 2.27592,0.30157 6.34375,-0.21875 4.06784,-0.52032 5.56013,-0.69573 6.28125,-0.9375 0.7371,-0.24714 1.79809,-0.58623 2.4375,-1.125 2.05007,0.33553 3.97378,0.39796 5.5,0.21875 3.14231,-0.36896 5.17994,-0.55936 7.1875,-0.78125 1.61076,-0.17802 2.26467,-0.6082 3.03125,-0.84375 0.24094,-0.0855 0.49412,-0.1556 0.78125,-0.1875 1.14978,-0.12772 2.30129,0.34665 6.375,-0.125 4.07374,-0.47165 5.55909,-0.6106 6.28125,-0.84375 0.71946,-0.23227 1.70024,-0.47346 2.34375,-0.96875 1.93637,0.33346 3.77006,0.40424 5.21875,0.25 3.14602,-0.33495 5.17756,-0.51859 7.1875,-0.71875 2.00996,-0.20014 2.48414,-0.82639 3.59375,-0.9375 1.15114,-0.11528 2.29643,0.36506 6.375,-0.0625 4.07861,-0.42756 5.58886,-0.56209 6.3125,-0.78125 0.73915,-0.22386 1.79572,-0.51325 2.4375,-1.03125 2.0571,0.39867 4.00187,0.4934 5.53125,0.34375 3.14873,-0.3081 5.17584,-0.47325 7.1875,-0.65625 1.61407,-0.14682 2.2631,-0.56055 3.03125,-0.78125 0.24142,-0.0809 0.49353,-0.12991 0.78125,-0.15625 1.15211,-0.10545 2.29296,0.39275 6.375,0 4.08208,-0.39275 5.5889,-0.53084 6.3125,-0.75 0.7209,-0.21833 1.6997,-0.4477 2.3438,-0.9375 1.938,0.34999 3.7688,0.45438 5.2187,0.3125 3.1487,-0.3081 5.1758,-0.47325 7.1875,-0.65625 2.0116,-0.18299 2.5142,-0.83802 3.625,-0.9375 1.1523,-0.10323 2.2922,0.38483 6.375,0 4.0829,-0.38482 5.5887,-0.501 6.3125,-0.71875 0.7393,-0.22243 1.7956,-0.51449 2.4375,-1.03125 2.0574,0.40177 4.0029,0.50333 5.5313,0.34375 3.1466,-0.32852 5.1771,-0.5227 7.1875,-0.71875 1.613,-0.15729 2.2656,-0.63148 3.0312,-0.875 0.2407,-0.088 0.4632,-0.12137 0.75,-0.15625 1.1483,-0.1397 2.3167,0.33991 6.375,-0.25 4.0583,-0.58992 5.5618,-0.77714 6.2813,-1.03125 0.7167,-0.25316 1.6745,-0.55807 2.3125,-1.09375 1.9197,0.21194 3.7199,0.15141 5.1562,-0.0937 3.1191,-0.5324 5.1116,-0.92861 7.0938,-1.3125 1.9821,-0.38387 2.4743,-1.03965 3.5625,-1.28125 1.1288,-0.25066 2.2703,0.11629 6.25,-0.875 3.9796,-0.99128 5.4296,-1.4193 6.125,-1.78125 0.7223,-0.37601 1.7619,-0.87058 2.375,-1.53125 1.963,-0.012 3.7937,-0.29105 5.2187,-0.84375 2.9512,-1.14461 4.8732,-1.86942 6.6875,-2.75 1.4557,-0.70653 2.3348,-1.68641 2.5469,-1.98438 0.2122,-0.29796 0.1118,-0.7453 0.1379,-0.76675 0.043,-0.0352 0.3193,-0.085 0.479,-0.42844 0.8589,-1.84708 2.321,-5.64459 2.4352,-6.32945 0.1137,-0.68216 0.1638,-1.34774 0.2145,-1.74497 0.029,-0.22952 -0.1467,-0.86544 -0.1246,-0.92404 0.031,-0.0821 0.3045,-0.26528 0.3599,-0.51471 0.2663,-1.19833 0.089,-2.19129 -0.1251,-3.60893 -0.214,-1.41764 -0.9837,-4.62214 -1.6369,-5.47626 -0.6589,-0.86172 -1.2229,-1.01117 -1.7479,-1.00066 -0.2086,0.26976 0.1368,0.26309 0.1626,0.31261 0.6806,0.0508 0.934,0.36864 1.4192,0.89662 0.4852,0.52798 1.2218,3.85117 1.3584,5.30156 0.1366,1.45039 0.19,2.8602 -0.088,3.46864 -0.2781,0.60845 -0.7232,0.51703 -1.0156,0.58291 0.531,0.18589 0.6698,0.12483 0.7314,0.96929 0.059,0.81338 -0.1332,1.63969 -0.5198,2.80562 -0.3912,1.18001 -1.8452,4.34998 -2.2857,4.59877 -0.4523,0.25551 -0.7314,0.27038 -1.067,0.13944 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7337-2);enable-background:new"
+               sodipodi:nodetypes="cssscscsscsssccscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssscscssssssscscsscsssccscsscscssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsssssscssssscsszsszssszzcczzzczzzc" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8183-3"
+               d="m 988.75,-263.84375 c 1.91161,0.6344 4.55027,1.75841 6.125,2.8125 1.57477,1.05409 2.8961,1.48252 5.5313,3.375 2.6082,1.87314 5.0269,3.01522 7.3125,4.0625 2.4693,1.13147 5.7521,2.15474 9.5312,3.9375 -1.2072,-1.2584 -7.139,-3.36445 -9.0312,-4.1875 -1.8922,-0.82304 -4.128,-1.93049 -6.9375,-3.78125 -2.80961,-1.85075 -3.62224,-2.48154 -6.00005,-3.71875 -2.37782,-1.23719 -4.07988,-1.9492 -6.53125,-2.5 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7297-4);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8185-3"
+               d="m 957.5,-260.78125 c 1.91,0.6181 4.58288,1.70934 6.15625,2.75 1.57339,1.04066 2.89608,1.48252 5.53125,3.375 2.60823,1.87315 5.02692,3.01521 7.3125,4.0625 2.46931,1.13147 5.75213,2.15475 9.53125,3.9375 -1.20728,-1.2584 -7.20154,-3.3957 -9.09375,-4.21875 -1.89217,-0.82304 -4.09666,-1.9305 -6.90625,-3.78125 -2.80958,-1.85075 -3.59295,-2.43932 -5.96875,-3.65625 -2.37578,-1.21691 -4.11321,-1.93885 -6.5625,-2.46875 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7301-5);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8187-7"
+               d="m 926.09375,-257.375 c 1.90772,0.59745 4.55348,1.66384 6.125,2.6875 1.5715,1.02365 2.87022,1.43971 5.5,3.28125 2.60291,1.82273 5.02887,2.9722 7.3125,4 2.4672,1.11041 5.75535,2.09323 9.53125,3.84375 -1.20623,-1.2481 -7.1719,-3.31809 -9.0625,-4.125 -1.89058,-0.8069 -4.10242,-1.89104 -6.90625,-3.6875 -2.80385,-1.79644 -3.62704,-2.40251 -6,-3.59375 -2.37297,-1.19124 -4.05362,-1.90283 -6.5,-2.40625 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7305-4);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8189-3"
+               d="m 894.90625,-253.5625 c 1.90213,0.55355 4.58701,1.58887 6.15625,2.59375 1.56923,1.00487 2.87401,1.40864 5.5,3.21875 2.59912,1.79164 5.00034,2.87189 7.28125,3.875 2.46428,1.08374 5.75984,2.04029 9.53125,3.75 -1.2048,-1.23507 -7.17416,-3.24478 -9.0625,-4.03125 -1.88832,-0.78647 -4.0752,-1.8308 -6.875,-3.59375 -2.79977,-1.76294 -3.59919,-2.36836 -5.96875,-3.53125 -2.36957,-1.16288 -4.12325,-1.83412 -6.5625,-2.28125 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7309-9);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8191-2"
+               d="m 863.71875,-248.65625 c 1.88062,0.42909 4.50427,1.38038 6.0625,2.3125 1.55823,0.93211 2.85233,1.25776 5.46875,3 2.58971,1.72444 4.98067,2.70802 7.25,3.625 2.45176,0.99069 5.73959,1.87707 9.5,3.5 -1.20131,-1.20734 -7.15249,-3.06609 -9.03125,-3.78125 -1.87875,-0.71517 -4.0854,-1.68442 -6.875,-3.375 -2.78963,-1.69057 -3.58461,-2.22822 -5.9375,-3.28125 -2.35292,-1.05301 -4.02584,-1.71248 -6.4375,-2 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7313-2);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8193-6"
+               d="m 833.15625,-241.375 c 1.84836,0.29644 4.46945,0.97632 6,1.78125 1.53058,0.80493 2.81374,1.05573 5.375,2.53125 2.53504,1.46046 4.89068,2.32509 7.125,3.0625 2.41399,0.79668 5.65711,1.46689 9.375,2.84375 -1.18771,-1.12873 -7.08772,-2.58975 -8.9375,-3.15625 -1.84977,-0.5665 -4.00342,-1.37392 -6.75,-2.84375 -2.74657,-1.46983 -3.50136,-1.92028 -5.8125,-2.78125 -2.31115,-0.86095 -4.00471,-1.32009 -6.375,-1.4375 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7317-7);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8195-5"
+               d="m 802.90625,-232.3125 c 1.8222,0.21127 4.36576,0.80057 5.875,1.53125 1.50925,0.73066 2.75568,0.92998 5.28125,2.28125 2.49976,1.33746 4.83154,2.04843 7.03125,2.65625 2.37653,0.65667 5.56464,1.07288 9.21875,2.1875 -1.16735,-1.04496 -6.92888,-2.10329 -8.75,-2.5625 -1.82111,-0.45921 -3.95225,-1.12696 -6.65625,-2.4375 -2.70403,-1.31052 -3.47106,-1.7199 -5.75,-2.46875 -2.27895,-0.74883 -3.91325,-1.17931 -6.25,-1.1875 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7321-5);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8197-2"
+               d="m 773.1875,-222.1875 c 1.81109,0.1787 4.32059,0.66506 5.8125,1.34375 1.49194,0.67869 2.7534,0.79822 5.25,2.0625 2.47107,1.25138 4.79005,1.89614 6.96875,2.4375 2.35387,0.58488 5.49134,0.89752 9.09375,1.84375 -1.15084,-0.99116 -6.85251,-1.7833 -8.65625,-2.1875 -1.80372,-0.4042 -3.91553,-1.02116 -6.59375,-2.25 -2.67818,-1.22884 -3.40345,-1.61089 -5.65625,-2.28125 -2.25279,-0.67034 -3.89627,-1.00232 -6.21875,-0.96875 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7329-8);enable-background:new" />
+            <path
+               inkscape:connector-curvature="0"
+               id="path8199-6"
+               d="m 743.5625,-211.1875 c 1.79281,0.12911 4.27313,0.54965 5.75,1.1875 1.4769,0.63785 2.7161,0.74156 5.1875,1.9375 2.44618,1.18372 4.72054,1.74666 6.875,2.21875 2.32767,0.51003 5.4196,0.68064 9,1.5625 -1.14379,-0.9706 -6.74759,-1.59065 -8.53125,-1.9375 -1.78367,-0.34684 -3.88285,-0.88756 -6.53125,-2.03125 -2.64841,-1.14368 -3.39495,-1.51631 -5.625,-2.125 -2.23008,-0.60868 -3.82594,-0.90966 -6.125,-0.8125 z"
+               style="display:inline;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7325-2);enable-background:new" />
+          </g>
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 863.87812,475.6679 c 1.64212,-3.218 3.51781,-5.73529 4.86136,-9.84898 0.79872,-3.65789 3.31204,-2.03073 7.26047,-8.3969 1.40193,-2.2395 5.47653,0.39136 8.9651,-2.39911 1.27072,-0.80319 2.88488,-0.40431 4.48256,-0.0631 3.76539,1.31896 5.82576,3.70355 8.33376,5.80837 6.13906,5.97023 20.53414,7.94327 23.48604,6.31346 1.43405,-2.90474 7.88128,-5.40888 12.37437,-11.11168 0.74811,-1.12267 11.72936,-8.74446 14.64721,-6.56599"
+           id="path8201-5"
+           sodipodi:nodetypes="ccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 888.50059,465.25071 c 7.36341,-3.23297 13.8109,-8.9084 20.70813,-13.38452 3.31057,-1.96954 6.86983,3.21601 10.796,3.59866 2.29773,-0.21813 3.7129,1.20259 5.68211,1.6415 5.15636,1.31779 2.39793,3.86488 9.97526,6.43972 6.15561,1.7204 8.9074,-6.79847 14.89975,-7.3236 4.87739,-0.50299 8.09892,-0.31603 11.61675,-0.25254 3.92696,0.13889 4.07855,-3.4976 6.06092,-5.3033 2.98056,-2.80522 7.15561,-1.84972 10.14485,-4.7409 1.01754,-1.38468 1.95458,-3.01085 2.73459,-5.10809 0.88201,-2.00034 3.04006,0.30598 4.79823,1.26269"
+           id="path8203-8"
+           sodipodi:nodetypes="ccccccccccc" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9048-9);enable-background:accumulate"
+           d="m 403.27922,1056.3058 56.56854,-42.4264 72.12489,14.1421 -46.66904,52.3259 -53.74012,7.0711 -28.28427,-31.1127 z"
+           id="path8994-7" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 542.27183,1060.5719 c -1.40727,18.8012 -1.1449,32.751 2.08174,49.3033 3.22666,16.5523 16.40609,45.9073 20.33441,63.1837 3.92621,17.2671 2.69413,38.3097 -12.45944,51.1483 -15.31761,12.9774 -42.05128,21.5989 -67.83231,15.7337 -25.78105,-5.8652 -69.54907,-49.2234 -88.59019,-70.2283 -19.11214,-21.0833 -63.76086,-93.8506 -77.93853,-124.2758 -14.17767,-30.4251 -12.65961,-36.7186 -8.11972,-45.52972 -9.36672,-24.5205 -12.41371,-50.06681 -33.71245,-75.57664 30.32547,3.11444 43.88028,26.95633 60.12568,47.13975 -5.52989,-48.07603 -18.05471,-64.4165 -28.37395,-90.7243 29.9943,6.08165 50.57936,31.87239 63.97979,72.7125 9.55415,-3.91791 18.23776,-9.37294 30.18741,-9.0612 -11.2975,-41.6958 -17.94946,-69.91584 -36.68725,-101.06994 53.44196,5.67033 83.65702,80.63932 78.97142,87.9608 9.97797,-2.24399 19.00565,-6.53038 30.43653,-5.65167 -11.24897,-38.34702 -21.04781,-76.8679 -3.65971,-118.64819 0,0 48.28678,65.43688 54.38966,85.80578 6.10287,20.3689 1.51881,38.70051 1.51881,38.70051 0,0 16.95957,31.0853 20.29392,51.09414 3.3731,20.24138 -3.53269,59.10328 -4.94582,77.98328 z"
+           id="path4189-9"
+           sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587-1);enable-background:accumulate"
+           d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+           id="path4191-6"
+           sodipodi:nodetypes="cccccccccccccccccccccc"
+           clip-path="url(#clipPath3631-6)"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898-1);enable-background:new"
+           d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.84562,77.83981 -43.7404,101.4864 -6.60491,13.1304 -18.52833,57.4859 -31.12335,76.2465 -12.59502,18.7605 -28.53137,39.7673 -37.17204,44.4209 -21.49052,11.5742 -44.55594,25.5059 -60.61889,18.0895 -14.37486,-6.637 -23.03969,-21.1927 -23.81407,-37.7433 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+           id="path4193-0"
+           clip-path="url(#clipPath3677-0)"
+           sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
+        <g
+           style="display:inline;enable-background:new"
+           id="g3617-4"
+           clip-path="url(#clipPath3622-5)"
+           transform="translate(276,136)">
+          <path
+             inkscape:connector-curvature="0"
+             transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-52.200498,74.09707)"
+             id="path4195-1"
+             d="m -15.66751,843.48852 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024-1);enable-background:accumulate" />
+          <path
+             inkscape:connector-curvature="0"
+             sodipodi:nodetypes="ccccccccccccc"
+             transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,-46.92842,75.511284)"
+             id="path4197-0"
+             d="m 118.70648,859.93048 -55.154328,-46.66904 -43.84062,36.76955 33.94113,53.74011 -13.596814,85.46203 -39.44536579,28.29217 -41.01220021,11.3137 -2.82842,46.669 56.56854,25.4559 18.943987,-69.65 23.45655,-58.85663 46.347541,-72.61491 16.62,-39.91188 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020-8);enable-background:accumulate" />
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044-0);enable-background:accumulate"
+           d="m -70.82184,932.58397 60.81118,-26.87005 100.40916,31.1127 -63.63961,31.11269 -82.02438,-16.97056 -15.55635,-18.38478 z"
+           id="path4199-4"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,229.07158,211.51128)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4105-2);enable-background:new"
+           d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -7.17516,44.14234 -8.78421,66.21911 -8.78379,2.34171 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 4.66299,24.40472 3.63165,36.35334 -7.06405,45.03355 -22.14231,87.36194 -35.95355,130.6798 -12.07476,32.9493 -27.3742,58.8525 -47.88808,87.2015 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -44.20676,10.8769 -62.59956,0.046 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 4.93886,-28.5121 4.4106,-43.4918 -0.53824,-15.2629 -2.29135,-30.5647 -6.54261,-46.8663 -4.25126,-16.30162 -9.04325,-24.91794 -16.11906,-41.57338 -7.24111,-17.04456 -15.07015,-36.74863 -18.20542,-56.28842 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+           id="path4201-8"
+           sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+           clip-path="url(#clipPath4177-4)"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,822.28931,10.93589)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130-8);enable-background:accumulate"
+           d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+           id="path4203-7"
+           sodipodi:nodetypes="cccccccc"
+           clip-path="url(#clipPath3631-6)"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141-2);enable-background:accumulate"
+           d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+           id="path4205-0"
+           sodipodi:nodetypes="cccccccc"
+           clip-path="url(#clipPath3631-6)"
+           transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,995.28646,23.53493)" />
+        <g
+           id="g8317-8"
+           style="display:inline;filter:url(#filter8333-2);enable-background:new"
+           clip-path="url(#clipPath8338-4)"
+           transform="translate(276,136)">
+          <path
+             inkscape:connector-curvature="0"
+             transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+             clip-path="none"
+             sodipodi:nodetypes="ccccc"
+             id="path4209-6"
+             d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <rect
+             y="757.19519"
+             x="-55"
+             height="177"
+             width="182"
+             id="rect8315-2"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+        </g>
+        <g
+           id="g8346-4"
+           style="display:inline;filter:url(#filter8354-2);enable-background:new"
+           clip-path="url(#clipPath8359-0)"
+           transform="translate(276,136)">
+          <path
+             inkscape:connector-curvature="0"
+             transform="matrix(-0.9045327,0.2506626,0.2506626,0.9045327,719.28646,-112.46507)"
+             clip-path="none"
+             sodipodi:nodetypes="ccccccc"
+             id="path4207-7"
+             d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <rect
+             y="696.19519"
+             x="-22"
+             height="176"
+             width="165"
+             id="rect8344-9"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;opacity:1;fill:#ada469;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+           d="m 1036.164,1071.8338 c 6.7941,18.9028 10.4937,33.2997 11.8903,51.2119 1.3966,17.9123 -3.7827,51.8008 -2.9005,70.6561 0.8818,18.8452 8.1337,40.099 27.3446,48.9689 19.4189,8.9658 49.3193,10.2113 74.1199,-3.1456 24.8006,-13.357 57.401,-70.3255 70.9742,-97.3087 13.6239,-27.0839 38.7611,-114.4974 44.6608,-149.76859 5.8998,-35.27121 2.5506,-41.30077 -4.6174,-49.05549 2.6403,-27.84015 -1.4998,-54.93543 13.1096,-87.18618 -30.249,11.8257 -37.3823,40.1607 -48.3189,65.50508 -8.0009,-50.93293 0.2092,-71.27319 3.3189,-101.21936 -29.0647,14.77791 -42.8615,47.11402 -45,92.85714 -10.9239,-1.3042 -21.3914,-4.43423 -33.5714,-0.71429 -0.264,-46.02334 -1.4635,-76.88941 8.9106,-114.20649 -53.2554,21.02686 -62.9472,106.5941 -56.0535,112.77792 -10.8828,0.535 -21.371,-1.2973 -32.8571,2.85715 0.6389,-42.57135 -0.2605,-84.90861 -30,-122.85715 0,0 -30.958,80.92234 -31.4286,103.57143 -0.4705,22.64909 9.4516,40.16588 9.4516,40.16588 0,0 -8.568,36.74051 -6.2986,58.23223 2.2959,21.74142 20.4429,59.67622 27.2655,78.65812 z"
+           id="path8848-3"
+           sodipodi:nodetypes="czzzzzzcccccccccczczz" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter3587-1);enable-background:accumulate"
+           d="m 719.5,738.69519 18.31177,15.43196 44.41103,-15.38821 23.2772,-25.54375 11.46397,19.22065 30.67161,12.78354 25.09737,5.72837 L 892,723.19519 908.02309,747.02126 947,752.19519 l 10.24541,-6.19852 6.75471,8.6982 25.49988,11.00032 2,-40.5 L 955.94866,710.6576 923.45591,689.1305 883.0038,677.66492 861.69668,662.13148 840,685.19519 755.02878,638.61208 722,676.69519 l -2.5,62 z"
+           id="path3635-9"
+           sodipodi:nodetypes="cccccccccccccccccccccc"
+           clip-path="url(#clipPath3631-6)"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3898-1);enable-background:new"
+           d="m 584,696.5 -6.5625,17.15625 c 0,0 -7.81152,20.36488 -15.6875,43.65625 -3.93799,11.64568 -7.88302,24.04145 -10.9375,35.125 -3.05448,11.08355 -5.33586,20.37986 -5.5,28.28125 -0.39807,19.16196 5.74653,34.8883 8.9375,41.75 -0.77153,3.55523 -1.99137,9.45432 -3.34375,18.09375 -1.92042,12.26821 -3.71827,27.15441 -2.375,39.875 1.38209,13.08835 6.81222,28.18765 12.59375,43.03125 5.78153,14.8436 12.05435,29.22711 15.21875,38.03125 6.63206,18.4519 9.99296,31.5763 11.3125,48.5 0.58135,7.4561 -0.24227,20.336 -1.25,33.375 -1.00773,13.039 -2.18661,26.3014 -1.6875,36.9688 0.98911,21.1398 9.32798,46.8347 33.375,57.9374 22.77483,10.5154 55.32682,11.7022 83.4375,-3.4374 16.15992,-8.7034 30.07634,-27.0976 43.375,-46.9063 13.29866,-19.8087 24.96917,-41.0534 31.9375,-54.9063 15.35292,-30.5212 39.39353,-115.46418 45.625,-152.7187 3.01859,-18.04653 3.92166,-29.06555 2.625,-38.03125 -0.97853,-6.76604 -3.82819,-12.1474 -6.875,-16.21875 2.04274,-27.50791 -0.73207,-51.36878 11.96875,-79.40625 L 840.75,763.375 l -23.8125,9.3125 c -17.48975,6.83753 -28.90164,19.04536 -36.59375,32.0625 -0.32251,0.54577 -0.56314,1.10776 -0.875,1.65625 0.22203,-22.51521 4.40784,-37.63759 6.59375,-58.6875 l 1.96875,-19 L 771,737.375 c -30.59449,15.55571 -45.69489,48.19321 -49.71875,90.21875 -4.24532,-0.62547 -8.8314,-1.01965 -13.8125,-0.84375 -0.29149,-39.18036 -0.39629,-67.03685 8.59375,-99.375 l 5.59375,-20.125 -19.4375,7.65625 c -30.90937,12.20394 -47.85954,41.93073 -56.625,68.375 -4.38273,13.22214 -6.74582,25.80121 -7.59375,35.9375 -0.23203,2.77373 -0.31106,5.31132 -0.3125,7.71875 -3.24187,-0.0364 -6.42052,0.13589 -10.0625,0.5 0.0416,-39.00473 -3.48424,-79.75415 -32.28125,-116.5 L 584,696.5 Z m 5.8125,43.8125 c 16.80691,30.64383 17.47451,63.96728 16.9375,99.75 l -0.21875,15.0625 12.03493,-6.53921 c 8.66205,-3.13302 19.56058,-0.22752 31.93382,-0.83579 l 14.67465,9.3566 -6.3309,-25.7941 c -0.0897,-0.22997 -0.22046,-0.41669 -0.25,-0.71875 -0.19951,-2.03986 -0.22232,-5.47307 0.125,-9.625 0.69464,-8.30386 2.78957,-19.58524 6.625,-31.15625 5.15532,-15.55294 13.48801,-31.19248 25.125,-42.53125 -4.68381,28.63798 -3.21559,60.25934 -3.01164,95.80514 l -2.76593,13.26164 15.49632,-7.59803 c 9.0294,-2.75771 17.18897,-0.34996 29.28125,1.09375 l 13.24632,9.44423 L 741.09375,840 c 1.44793,-30.97177 8.22149,-53.67808 20.71875,-68.875 -2.98688,19.77884 -5.43043,41.7848 0.3125,78.34375 l 1.06552,6.37318 -2.93815,11.51685 10.61711,-8.16818 9.18973,10.22198 -1.54828,-10.4636 L 781.9375,852 c 5.70102,-13.21149 10.17282,-26.21337 16.34375,-36.65625 0.95986,-1.62434 2.03153,-3.06436 3.0625,-4.5625 -3.68066,21.15535 -2.42716,40.20815 -4.09375,57.78125 l -4.68014,7.80698 7.39889,0.22427 c 3.22005,3.48361 3.8675,3.85068 4.5625,8.65625 0.695,4.80557 0.31862,14.40035 -2.5625,31.625 -5.56799,33.28792 -31.79272,123.1659 -43.6875,146.8125 -6.60491,13.1304 -18.02998,33.8957 -30.625,52.6563 -12.59502,18.7605 -27.35933,35.5338 -36,40.1874 -21.49052,11.5742 -48.7808,10.2602 -64.84375,2.8438 -14.37486,-6.637 -20.53812,-23.4494 -21.3125,-40 -0.38311,-8.188 0.61279,-21.3092 1.625,-34.4062 1.01221,-13.0971 11.28891,-22.5708 15.42339,-36.5626 5.37229,-18.1808 -1.44687,-36.5944 -12.5,-53.93745 -6.48655,-10.17778 -23.9768,-24.2579 -29.54839,-38.5625 -5.57159,-14.3046 -10.36751,-29.00315 -11.28125,-37.65625 -0.92621,-8.77113 0.4225,-23.02502 2.21875,-34.5 1.79625,-11.47497 3.84375,-20.28125 3.84375,-20.28125 l 9.42278,-3.6152 -10.48528,-3.8848 c 0,0 -8.49889,-15.3101 -8.09375,-34.8125 0.0711,-3.42316 1.83626,-12.72805 4.71875,-23.1875 2.88249,-10.45945 6.76466,-22.55271 10.625,-33.96875 3.04439,-9.00308 5.78063,-16.60345 8.34375,-23.6875 z"
+           id="path3669-2"
+           clip-path="url(#clipPath3677-0)"
+           sodipodi:nodetypes="ccssscsssssssssssssccccscccccccccsscccccccccccssscccccccccccccccsccccssssssssssssscccsssc" />
+        <g
+           id="g3628-8"
+           clip-path="url(#clipPath3636-90)"
+           transform="translate(276,136)">
+          <path
+             inkscape:connector-curvature="0"
+             id="path8988-3"
+             d="m 824.48651,818.48242 -49.49748,-15.55635 -26.87005,52.3259 41.01219,45.25484 49.49747,-38.18377 -14.14213,-43.84062 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9024-1);enable-background:accumulate" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path8990-0"
+             d="m 964.49365,855.25197 -55.15433,-46.66904 -43.84062,36.76955 33.94113,53.74011 7.07106,66.46804 -50.91168,35.35537 -41.0122,11.3137 -2.82842,46.669 56.56854,25.4559 63.63961,-76.3676 24.04163,-94.75227 8.48528,-57.98276 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9020-8);enable-background:accumulate" />
+        </g>
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:0.25;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter9044-0);enable-background:accumulate"
+           d="m 1045.3322,1043.5779 60.8112,-26.8701 100.4091,31.1127 -63.6396,31.1127 -82.0244,-16.9706 -15.5563,-18.3847 z"
+           id="path8992-1" />
+        <path
+           inkscape:connector-curvature="0"
+           transform="translate(450.03125,73.843964)"
+           style="display:inline;opacity:0.58775509;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:20.79999924;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4185-1);enable-background:new"
+           d="m 583.0625,715.75 c -12.10609,34.44974 -26.7145,68.53333 -31.75,104.84375 -0.83208,14.92867 4.58915,29.15943 8.84375,43.0625 -5.91624,27.20126 -10.13681,56.89995 1.15625,83.125 13.51717,38.16085 35.00147,75.68215 32.42279,117.46825 -0.9483,29.2942 -9.01444,60.9941 5.38971,88.2817 10.19864,19.3348 33.13956,27.3117 53.96785,27.6676 27.86219,1.1741 56.46261,-11.6216 72.0009,-35.2613 22.59549,-29.3717 41.80051,-61.4973 55.23865,-96.0598 16.89053,-45.506 29.6718,-92.56072 37.93402,-140.3989 1.8244,-12.94106 3.10108,-27.46985 -4.57892,-38.82255 -3.43115,-7.33632 0.0421,-15.56014 -0.68457,-23.30977 0.674,-24.99466 4.01232,-50.66376 16.65332,-72.59648 -17.73313,6.4446 -35.07268,16.55971 -44.00307,33.86425 -3.93508,6.70955 -7.60482,13.57413 -11.37193,20.38575 -3.54999,-30.01408 3.71963,-59.64828 6.78125,-89.28125 -20.16604,9.05463 -36.87672,25.65522 -44.17495,46.682 -6.30463,15.58003 -8.80222,32.31718 -10.26255,49.03675 -8.25334,-1.51925 -16.68447,-2.10155 -25.0625,-1.5 -0.96308,-38.69787 -0.46696,-79.40715 10.96875,-115.90625 -18.68113,6.21776 -35.16621,18.73551 -45.62803,35.38723 -13.85254,20.87979 -21.2614,45.75395 -23.05947,70.61277 0.58534,4.32454 -0.0613,11.84009 -6.34375,9.875 -5.33118,0.0176 -10.62908,0.67883 -15.9375,1.09375 1.14784,-39.38148 -3.34144,-81.6282 -27.0625,-114.21875 -3.06071,-3.63717 -5.63685,-7.68438 -8.625,-11.34375 -0.9375,2.4375 -1.875,4.875 -2.8125,7.3125 z m 7.75,13.84375 c 18.56527,29.29629 22.4825,64.82012 22.125,98.875 0.20409,5.17526 -0.51656,11.8292 0.125,16.0625 12.31856,-6.10275 26.73912,-2.4399 39.78125,-2.1875 2.31712,1.22325 3.1921,1.65243 1.90625,-1.40625 -4.16455,-13.95285 -1.84828,-28.613 1.80504,-42.40764 6.36687,-26.29064 20.62828,-51.08798 42.81996,-67.02986 -8.61709,37.23706 -5.71658,76.56161 -6.09375,113.96875 12.25344,-6.9099 27.27879,-3.44613 40.03125,-0.25 3.39222,3.5348 2.28935,-0.72948 2.1875,-3.8125 -0.48309,-21.37058 4.13133,-43.06963 13.6875,-62.15625 5.96266,-10.68727 14.24338,-19.80379 22.4375,-28.875 -7.87156,33.8381 -9.2029,69.33593 -2.71875,103.5 1.72485,-1.41118 4.60681,-0.45414 5.65625,-0.375 9.68369,-21.23682 16.35112,-45.38062 34.89016,-60.74185 1.87329,-0.37122 -1.44818,8.52495 -1.48391,11.8981 -3.53488,21.84581 -3.2972,44.17323 -4.90625,66.25 -1.31238,1.37679 2.84835,2.32354 3.46875,4.0625 7.92311,10.5658 3.12294,24.83149 2.0916,36.78011 -7.06405,45.03355 -21.76553,88.37934 -35.57677,131.69714 -12.07476,32.9493 -30.7197,63.08 -51.23358,91.429 -10.95257,13.5514 -23.24472,27.8513 -40.84375,32.5 -20.15601,6.2413 -43.57595,5.1744 -61.96875,-5.6562 -17.28966,-12.3414 -21.02393,-35.7089 -19.26226,-55.6864 0.0488,-15.8262 2.37211,-27.8008 7.91747,-42.8053 5.54535,-15.0045 2.47105,-31.3317 -1.78021,-47.6333 -4.25126,-16.3016 -12.17903,-26.26002 -21.82158,-42.20417 -9.64255,-15.94415 -17.6369,-36.03734 -20.77217,-55.57713 -1.74948,-18.62714 2.89171,-37.12262 5.78125,-55.25 3.29623,-2.83696 -1.59799,-5.19659 -2.3125,-8.1875 -7.60113,-17.01508 -8.40747,-36.7749 -2.74234,-54.55998 7.1302,-25.0723 15.76087,-49.63241 24.67984,-74.12752 0.70833,1.30208 1.41667,2.60417 2.125,3.90625 z"
+           id="path4149-7"
+           sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccczzzcccccc"
+           clip-path="url(#clipPath4177-4)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4130-8);enable-background:accumulate"
+           d="m 735.05635,733.03834 2.75542,21.08881 44.41103,-15.38821 4.85063,-22.38975 -3.93617,-22.05222 -22.45163,-36.59301 -8.28004,30.30494 -17.34924,45.02944 z"
+           id="path3902-8"
+           sodipodi:nodetypes="cccccccc"
+           clip-path="url(#clipPath3631-6)"
+           transform="translate(276,136)" />
+        <path
+           inkscape:connector-curvature="0"
+           style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;filter:url(#filter4141-2);enable-background:accumulate"
+           d="m 831.81321,730.29452 15.82237,14.90486 20.85473,2.89994 -1.59029,-39.92598 8.32561,-30.50842 -7.16499,-6.34106 -21.69669,20.9424 -14.55074,38.02826 z"
+           id="path4135-9"
+           sodipodi:nodetypes="cccccccc"
+           clip-path="url(#clipPath3631-6)"
+           transform="translate(276,136)" />
+        <g
+           id="g8367-1"
+           style="filter:url(#filter8379-0)"
+           clip-path="url(#clipPath8392-1)"
+           transform="translate(276,136)">
+          <path
+             inkscape:connector-curvature="0"
+             clip-path="none"
+             sodipodi:nodetypes="ccccccc"
+             id="path4145-5"
+             d="m 910.14441,746.31415 32.61295,5.17393 -0.36119,-23.87619 7.18853,-29.68221 -8.45112,-5.26365 -21.82194,26.51077 -9.16723,27.13735 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <rect
+             y="650.19098"
+             x="877.51953"
+             height="172.53406"
+             width="123.03658"
+             id="rect8365-4"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+        </g>
+        <g
+           id="g8400-9"
+           style="filter:url(#filter8404-9)"
+           clip-path="url(#clipPath8417-4)"
+           transform="translate(276,136)">
+          <path
+             inkscape:connector-curvature="0"
+             clip-path="none"
+             sodipodi:nodetypes="ccccc"
+             id="path4147-2"
+             d="m 964.00012,754.69487 18.42881,7.46479 9.07107,-36.96447 -14.87031,4.83886 -12.62957,24.66082 z"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+          <rect
+             y="677.06104"
+             x="924.89569"
+             height="125.1579"
+             width="142.12846"
+             id="rect8398-5"
+             style="display:inline;overflow:visible;visibility:visible;opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" />
+        </g>
+      </g>
+    </g>
+    <path
+       style="fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:17.84425545;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Send)"
+       d="M 544.23337,203.09259 3443.746,100.92806"
+       id="path7167"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="display:inline;fill:#f8d615;fill-opacity:1;fill-rule:evenodd;stroke:#f8d615;stroke-width:18;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Send-4);enable-background:new"
+       d="M 527.91203,584.39421 3442.4188,1000.8355"
+       id="path7167-9"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#f83615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="80.219048"
+       y="107.38741"
+       id="text8200"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan8202"
+         x="80.219048"
+         y="107.38741"
+         style="font-size:50px;fill:#f83615;fill-opacity:1">CROP_DEFAULT</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f80000;fill-opacity:0;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="3861.3669"
+       y="1281.7198"
+       id="text8200-4"
+       sodipodi:linespacing="125%"
+       transform="scale(0.96105877,1.0405191)"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5"
+         x="3861.3669"
+         y="1281.7198"
+         style="font-size:56.64243317px;fill:#f80000;fill-opacity:0">COMPOSE_PADDED</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f8d615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="3615.1545"
+       y="49.156631"
+       id="text8200-4-9"
+       sodipodi:linespacing="125%"
+       transform="scale(0.96105877,1.0405191)"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3"
+         x="3615.1545"
+         y="49.156631"
+         style="font-size:50px;fill:#f8d615;fill-opacity:1">COMPOSE_ACTIVE</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f83615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="2429.1526"
+       y="-3.1657715"
+       id="text8200-4-5"
+       sodipodi:linespacing="125%"
+       transform="scale(0.96105878,1.0405191)"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-7"
+         x="2429.1526"
+         y="-3.1657715"
+         style="font-size:49.99999958px;fill:#f83615;fill-opacity:1">COMPOSE_DEFAULT</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f815bb;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="3681.5449"
+       y="1289.9539"
+       id="text8200-4-9-3"
+       sodipodi:linespacing="125%"
+       transform="scale(0.96105877,1.0405191)"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3-6"
+         x="3681.5449"
+         y="1289.9539"
+         style="font-size:50px;fill:#f815bb;fill-opacity:1">COMPOSE_PADDED</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:50px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new;"
+       x="2438.0618"
+       y="1368.4291"
+       id="text8200-4-9-3-5"
+       sodipodi:linespacing="125%"
+       transform="scale(0.96105877,1.0405191)"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3-6-3"
+         x="2438.0618"
+         y="1368.4291"
+         style="font-size:50px;fill:#000000;fill-opacity:1;">COMPOSE_BONDS</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="8.0815096"
+       y="1438.8961"
+       id="text8200-4-9-3-5-6"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3-6-3-2"
+         x="8.0815096"
+         y="1438.8961"
+         style="font-size:50px;fill:#000000;fill-opacity:1">CROP_BONDS</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="1455.4426"
+       y="-26.808125"
+       id="text8200-4-9-3-5-6-9"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3-6-3-2-1"
+         x="1455.4426"
+         y="-26.808125"
+         style="font-size:50px;fill:#000000;fill-opacity:1">overscan area</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#f8d615;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="179.63055"
+       y="385.38785"
+       id="text8200-4-9-2"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3-7"
+         x="179.63055"
+         y="385.38785"
+         style="font-size:50px;fill:#f8d615;fill-opacity:1">CROP_ACTIVE</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="636.67419"
+       y="-138.84549"
+       id="text8200-4-9-3-5-6-0"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3-6-3-2-9"
+         x="636.67419"
+         y="-138.84549"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:70px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1">DATA SOURCE</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-weight:normal;font-size:45.31394196px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;enable-background:new"
+       x="3178.7151"
+       y="-129.06131"
+       id="text8200-4-9-3-5-6-0-3"
+       sodipodi:linespacing="125%"
+       transform="scale(0.96105877,1.0405191)"><tspan
+         sodipodi:role="line"
+         id="tspan8202-5-3-6-3-2-9-6"
+         x="3178.7151"
+         y="-129.06131"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:69.99999978px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';fill:#000000;fill-opacity:1">DATA SINK</tspan></text>
+    <flowRoot
+       xml:space="preserve"
+       id="flowRoot7469"
+       style="fill:black;stroke:none;stroke-opacity:1;stroke-width:1px;stroke-linejoin:miter;stroke-linecap:butt;fill-opacity:1;font-family:sans-serif;font-style:normal;font-weight:normal;font-size:57.5px;line-height:125%;letter-spacing:0px;word-spacing:0px;"><flowRegion
+         id="flowRegion7471"><rect
+           id="rect7473"
+           width="4297.5474"
+           height="1851.537"
+           x="-52.635666"
+           y="70.623535"
+           style="font-size:57.5px;" /></flowRegion><flowPara
+         id="flowPara7475"></flowPara></flowRoot>  </g>
+</svg>
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-formats_files/bayer.png and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-formats_files/bayer.png differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-formats.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-formats.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-formats.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-formats.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1514,23 +1514,28 @@ be named ``MEDIA_BUS_FMT_SRGGB10_2X8_PAD
 
 .. _bayer-patterns:
 
-.. figure::  subdev-formats_files/bayer.*
-    :alt:    bayer.png
+.. figure::  bayer.*
+    :alt:    bayer.pdf / bayer.svg
     :align:  center
 
     **Figure 4.8 Bayer Patterns**
 
-
-
 The following table lists existing packed Bayer formats. The data
 organization is given as an example for the first pixel only.
 
 
+.. HACK: ideally, we would be using adjustbox here. However, Sphinx
+.. is a very bad behaviored guy: if the table has more than 30 cols,
+.. it switches to long table, and there's no way to override it.
+
+
 .. raw:: latex
 
-    \newline\newline\begin{adjustbox}{width=\columnwidth}
+    \begingroup
+    \tiny
+    \setlength{\tabcolsep}{2pt}
 
-.. tabularcolumns:: |p{7.6cm}|p{1.6cm}|p{0.7cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|p{0.5cm}|
+.. tabularcolumns:: |p{4.0cm}|p{0.7cm}|p{0.3cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|p{0.22cm}|
 
 .. _v4l2-mbus-pixelcode-bayer:
 
@@ -2314,7 +2319,7 @@ organization is given as an example for
 
 .. raw:: latex
 
-    \end{adjustbox}\newline\newline
+    \endgroup
 
 
 Packed YUV Formats
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-image-processing-crop.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-image-processing-crop.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-image-processing-crop.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-image-processing-crop.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="42.799767cm"
+   height="9.9348345cm"
+   viewBox="-194 128 840.06984 194.72276"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="subdev-image-processing-crop.svg">
+  <metadata
+     id="metadata100">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs98" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview96"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="0.3649199"
+     inkscape:cx="764.40286"
+     inkscape:cy="176.91347"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <rect
+     style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+     x="-9.6002426"
+     y="128.86047"
+     width="469.77399"
+     height="193"
+     id="rect4" />
+  <g
+     id="g6"
+     transform="translate(-1.6002426,-1.1395339)">
+    <rect
+       style="fill:#ffffff"
+       x="4.5"
+       y="189"
+       width="159"
+       height="104"
+       id="rect8" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#a52a2a;stroke-width:2"
+       x="4.5"
+       y="189"
+       width="159"
+       height="104"
+       id="rect10" />
+  </g>
+  <g
+     id="g12"
+     transform="translate(-1.6002426,-1.1395339)">
+    <rect
+       style="fill:#ffffff"
+       x="63.5"
+       y="211"
+       width="94"
+       height="77"
+       id="rect14" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       x="63.5"
+       y="211"
+       width="94"
+       height="77"
+       id="rect16" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#0000ff"
+     x="72.899757"
+     y="226.61047"
+     id="text18">
+    <tspan
+       x="72.899757"
+       y="226.61047"
+       id="tspan20">sink</tspan>
+    <tspan
+       x="72.899757"
+       y="242.61047"
+       id="tspan22">crop</tspan>
+    <tspan
+       x="72.899757"
+       y="258.61047"
+       id="tspan24">selection</tspan>
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="27.899757"
+     y="156.86047"
+     id="text26">
+    <tspan
+       x="27.899757"
+       y="156.86047"
+       id="tspan28" />
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#a52a2a"
+     x="6.938117"
+     y="156.77448"
+     id="text30">
+    <tspan
+       x="6.938117"
+       y="156.77448"
+       id="tspan32">sink media</tspan>
+    <tspan
+       x="6.938117"
+       y="172.77448"
+       id="tspan34">bus format</tspan>
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#8b6914"
+     x="348.17374"
+     y="153.86047"
+     id="text36">
+    <tspan
+       x="348.17374"
+       y="153.86047"
+       id="tspan38">source media</tspan>
+    <tspan
+       x="348.17374"
+       y="169.86047"
+       id="tspan40">bus format</tspan>
+  </text>
+  <g
+     id="g42"
+     transform="translate(-1.6002426,-1.1395339)">
+    <rect
+       style="fill:#ffffff"
+       x="350.48801"
+       y="190.834"
+       width="93.286301"
+       height="75.166"
+       id="rect44" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#8b6914;stroke-width:2"
+       x="350.48801"
+       y="190.834"
+       width="93.286301"
+       height="75.166"
+       id="rect46" />
+  </g>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="348.88776"
+     y1="264.86047"
+     x2="61.899757"
+     y2="286.86047"
+     id="line48" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="348.88776"
+     y1="189.69447"
+     x2="61.899757"
+     y2="209.86047"
+     id="line50" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="442.17374"
+     y1="264.86047"
+     x2="155.89977"
+     y2="286.86047"
+     id="line52" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="442.17374"
+     y1="189.69447"
+     x2="155.89977"
+     y2="209.86047"
+     id="line54" />
+  <g
+     id="g56"
+     transform="translate(-1.6002426,-1.1395339)">
+    <circle
+       style="fill:#ffffff"
+       cx="473.10001"
+       cy="219.98399"
+       id="ellipse58"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="473.10001"
+       cy="219.98399"
+       id="ellipse60"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="473.10001"
+       cy="219.98399"
+       id="ellipse62"
+       r="8.5" />
+  </g>
+  <g
+     id="g64"
+     transform="translate(-1.6002426,-1.1395339)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="481.60001"
+       y1="219.98399"
+       x2="637.93402"
+       y2="220.01199"
+       id="line66" />
+    <polygon
+       style="fill:#000000"
+       points="635.435,215.012 645.434,220.014 635.433,225.012 637.934,220.012 "
+       id="polygon68" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="635.435,215.012 645.434,220.014 635.433,225.012 637.934,220.012 "
+       id="polygon70" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="505.30774"
+     y="208.66048"
+     id="text72">
+    <tspan
+       x="505.30774"
+       y="208.66048"
+       id="tspan74">pad 1 (source)</tspan>
+  </text>
+  <g
+     id="g76"
+     transform="translate(-1.6002426,-1.1395339)">
+    <circle
+       style="fill:#ffffff"
+       cx="-20.398199"
+       cy="241.51199"
+       id="ellipse78"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-20.398199"
+       cy="241.51199"
+       id="ellipse80"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-20.398199"
+       cy="241.51199"
+       id="ellipse82"
+       r="8.5" />
+  </g>
+  <g
+     id="g84"
+     transform="translate(-1.6002426,-1.1395339)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="-192.39799"
+       y1="241.8"
+       x2="-38.6343"
+       y2="241.52901"
+       id="line86" />
+    <polygon
+       style="fill:#000000"
+       points="-41.1431,236.534 -31.1343,241.516 -41.1254,246.534 -38.6343,241.529 "
+       id="polygon88" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="-41.1431,236.534 -31.1343,241.516 -41.1254,246.534 -38.6343,241.529 "
+       id="polygon90" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="-149.45824"
+     y="228.66048"
+     id="text92">
+    <tspan
+       x="-149.45824"
+       y="228.66048"
+       id="tspan94">pad 0 (sink)</tspan>
+  </text>
+</svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-image-processing-full.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-image-processing-full.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-image-processing-full.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-image-processing-full.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,742 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="58.825298cm"
+   height="17.279287cm"
+   viewBox="-186 71 1174.5119 332.1463"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="subdev-image-processing-full.svg">
+  <metadata
+     id="metadata260">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs258" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview256"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="0.26595857"
+     inkscape:cx="1050.1367"
+     inkscape:cy="307.01645"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <g
+     id="g4"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="318.89999"
+       y="129"
+       width="208.10001"
+       height="249"
+       id="rect6" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#ff765a;stroke-width:2"
+       x="318.89999"
+       y="129"
+       width="208.10001"
+       height="249"
+       id="rect8" />
+  </g>
+  <rect
+     style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+     x="-3.4982376"
+     y="65.305092"
+     width="806"
+     height="343"
+     id="rect10" />
+  <g
+     id="g12"
+     transform="translate(-1.4982376,-7.6949076)">
+    <circle
+       style="fill:#ffffff"
+       cx="-12.5"
+       cy="166.71201"
+       id="ellipse14"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-12.5"
+       cy="166.71201"
+       id="ellipse16"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-12.5"
+       cy="166.71201"
+       id="ellipse18"
+       r="8.5" />
+  </g>
+  <g
+     id="g20"
+     transform="translate(-1.4982376,-7.6949076)">
+    <circle
+       style="fill:#ffffff"
+       cx="815.23199"
+       cy="205.18401"
+       id="ellipse22"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="815.23199"
+       cy="205.18401"
+       id="ellipse24"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="815.23199"
+       cy="205.18401"
+       id="ellipse26"
+       r="8.5" />
+  </g>
+  <g
+     id="g28"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="-184.5"
+       y1="167"
+       x2="-30.736099"
+       y2="166.729"
+       id="line30" />
+    <polygon
+       style="fill:#000000"
+       points="-33.2449,161.734 -23.2361,166.716 -33.2272,171.734 -30.7361,166.729 "
+       id="polygon32" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="-33.2449,161.734 -23.2361,166.716 -33.2272,171.734 -30.7361,166.729 "
+       id="polygon34" />
+  </g>
+  <g
+     id="g36"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="823.73199"
+       y1="205.18401"
+       x2="980.06598"
+       y2="205.21201"
+       id="line38" />
+    <polygon
+       style="fill:#000000"
+       points="977.567,200.212 987.566,205.214 977.565,210.212 980.066,205.212 "
+       id="polygon40" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="977.567,200.212 987.566,205.214 977.565,210.212 980.066,205.212 "
+       id="polygon42" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="-141.45824"
+     y="147.3051"
+     id="text44">
+    <tspan
+       x="-141.45824"
+       y="147.3051"
+       id="tspan46">pad 0 (sink)</tspan>
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="847.54175"
+     y="187.3051"
+     id="text48">
+    <tspan
+       x="847.54175"
+       y="187.3051"
+       id="tspan50">pad 2 (source)</tspan>
+  </text>
+  <g
+     id="g52"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="5.5"
+       y="120"
+       width="159"
+       height="104"
+       id="rect54" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#a52a2a;stroke-width:2"
+       x="5.5"
+       y="120"
+       width="159"
+       height="104"
+       id="rect56" />
+  </g>
+  <g
+     id="g58"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="62.5"
+       y="136"
+       width="94"
+       height="77"
+       id="rect60" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       x="62.5"
+       y="136"
+       width="94"
+       height="77"
+       id="rect62" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="29.001762"
+     y="81.305092"
+     id="text64">
+    <tspan
+       x="29.001762"
+       y="81.305092"
+       id="tspan66" />
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#a52a2a"
+     x="8.040122"
+     y="81.218895"
+     id="text68">
+    <tspan
+       x="8.040122"
+       y="81.218895"
+       id="tspan70">sink media</tspan>
+    <tspan
+       x="8.040122"
+       y="97.219093"
+       id="tspan72">bus format</tspan>
+  </text>
+  <g
+     id="g74"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="333.64401"
+       y="185.64999"
+       width="165.2"
+       height="172.478"
+       id="rect76" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#00ff00;stroke-width:2"
+       x="333.64401"
+       y="185.64999"
+       width="165.2"
+       height="172.478"
+       id="rect78" />
+  </g>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="332.14578"
+     y1="350.43307"
+     x2="61.001762"
+     y2="205.3051"
+     id="line80" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="332.14578"
+     y1="177.95509"
+     x2="61.001762"
+     y2="128.3051"
+     id="line82" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="497.34576"
+     y1="350.43307"
+     x2="155.00177"
+     y2="205.3051"
+     id="line84" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="497.34576"
+     y1="177.95509"
+     x2="155.00177"
+     y2="128.3051"
+     id="line86" />
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#00ff00"
+     x="333.20578"
+     y="141.7471"
+     id="text88">
+    <tspan
+       x="333.20578"
+       y="141.7471"
+       id="tspan90">sink compose</tspan>
+    <tspan
+       x="333.20578"
+       y="157.7471"
+       id="tspan92">selection (scaling)</tspan>
+  </text>
+  <g
+     id="g94"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="409.32199"
+       y="194.565"
+       width="100.186"
+       height="71.452301"
+       id="rect96" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       x="409.32199"
+       y="194.565"
+       width="100.186"
+       height="71.452301"
+       id="rect98" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#8b6914"
+     x="688.00177"
+     y="97.43309"
+     id="text100">
+    <tspan
+       x="688.00177"
+       y="97.43309"
+       id="tspan102">source media</tspan>
+    <tspan
+       x="688.00177"
+       y="113.43309"
+       id="tspan104">bus format</tspan>
+  </text>
+  <g
+     id="g106"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="688.48798"
+       y="173.834"
+       width="100.186"
+       height="71.452301"
+       id="rect108" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#8b6914;stroke-width:2"
+       x="688.48798"
+       y="173.834"
+       width="100.186"
+       height="71.452301"
+       id="rect110" />
+  </g>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="686.98975"
+     y1="237.59109"
+     x2="407.82376"
+     y2="258.32309"
+     id="line112" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="686.98975"
+     y1="166.1391"
+     x2="407.82376"
+     y2="186.8701"
+     id="line114" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="787.17578"
+     y1="237.59109"
+     x2="508.00977"
+     y2="258.32309"
+     id="line116" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="787.17578"
+     y1="166.1391"
+     x2="508.00977"
+     y2="186.8701"
+     id="line118" />
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#ff765a"
+     x="323.50177"
+     y="95.305092"
+     id="text120">
+    <tspan
+       x="323.50177"
+       y="95.305092"
+       id="tspan122">sink compose</tspan>
+    <tspan
+       x="323.50177"
+       y="111.30509"
+       id="tspan124">bounds selection</tspan>
+  </text>
+  <g
+     id="g126"
+     transform="translate(-1.4982376,-7.6949076)">
+    <circle
+       style="fill:#ffffff"
+       cx="-12.0982"
+       cy="341.51199"
+       id="ellipse128"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-12.0982"
+       cy="341.51199"
+       id="ellipse130"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-12.0982"
+       cy="341.51199"
+       id="ellipse132"
+       r="8.5" />
+  </g>
+  <g
+     id="g134"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="-184.09801"
+       y1="341.79999"
+       x2="-30.334299"
+       y2="341.52899"
+       id="line136" />
+    <polygon
+       style="fill:#000000"
+       points="-32.8431,336.534 -22.8343,341.516 -32.8254,346.534 -30.3343,341.529 "
+       id="polygon138" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="-32.8431,336.534 -22.8343,341.516 -32.8254,346.534 -30.3343,341.529 "
+       id="polygon140" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="-140.49823"
+     y="321.30508"
+     id="text142">
+    <tspan
+       x="-140.49823"
+       y="321.30508"
+       id="tspan144">pad 1 (sink)</tspan>
+  </text>
+  <g
+     id="g146"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="7.8082399"
+       y="292.79999"
+       width="112.092"
+       height="82.199997"
+       id="rect148" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#a52a2a;stroke-width:2"
+       x="7.8082399"
+       y="292.79999"
+       width="112.092"
+       height="82.199997"
+       id="rect150" />
+  </g>
+  <g
+     id="g152"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="52.900002"
+       y="314.79999"
+       width="58.099998"
+       height="50.200001"
+       id="rect154" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       x="52.900002"
+       y="314.79999"
+       width="58.099998"
+       height="50.200001"
+       id="rect156" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="30.401762"
+     y="252.10509"
+     id="text158">
+    <tspan
+       x="30.401762"
+       y="252.10509"
+       id="tspan160" />
+  </text>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="357.40176"
+     y1="244.20509"
+     x2="51.401764"
+     y2="307.10507"
+     id="line162" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="357.40176"
+     y1="308.30508"
+     x2="51.401764"
+     y2="357.30508"
+     id="line164" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="432.50177"
+     y1="308.30508"
+     x2="109.50176"
+     y2="357.30508"
+     id="line166" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="432.50177"
+     y1="244.20509"
+     x2="109.50176"
+     y2="307.10507"
+     id="line168" />
+  <rect
+     style="fill:none;fill-opacity:0;stroke:#00ff00;stroke-width:2"
+     x="357.40176"
+     y="244.20509"
+     width="75.099998"
+     height="64.099998"
+     id="rect170" />
+  <rect
+     style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+     x="441.76376"
+     y="276.77109"
+     width="64.737999"
+     height="48.534"
+     id="rect172" />
+  <g
+     id="g174"
+     transform="translate(-1.4982376,-7.6949076)">
+    <rect
+       style="fill:#ffffff"
+       x="693.42798"
+       y="324.73401"
+       width="63.571999"
+       height="49.265999"
+       id="rect176" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#8b6914;stroke-width:2"
+       x="693.42798"
+       y="324.73401"
+       width="63.571999"
+       height="49.265999"
+       id="rect178" />
+  </g>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="691.92975"
+     y1="366.30508"
+     x2="441.76376"
+     y2="325.30508"
+     id="line180" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="691.92975"
+     y1="317.03909"
+     x2="441.76376"
+     y2="276.77109"
+     id="line182" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="755.50177"
+     y1="366.30508"
+     x2="506.50177"
+     y2="325.30508"
+     id="line184" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="755.50177"
+     y1="317.03909"
+     x2="506.50177"
+     y2="276.77109"
+     id="line186" />
+  <g
+     id="g188"
+     transform="translate(-1.4982376,-7.6949076)">
+    <circle
+       style="fill:#ffffff"
+       cx="815.44"
+       cy="343.98401"
+       id="ellipse190"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="815.44"
+       cy="343.98401"
+       id="ellipse192"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="815.44"
+       cy="343.98401"
+       id="ellipse194"
+       r="8.5" />
+  </g>
+  <g
+     id="g196"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="823.94"
+       y1="343.98401"
+       x2="980.27399"
+       y2="344.01199"
+       id="line198" />
+    <polygon
+       style="fill:#000000"
+       points="977.775,339.012 987.774,344.014 977.773,349.012 980.274,344.012 "
+       id="polygon200" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="977.775,339.012 987.774,344.014 977.773,349.012 980.274,344.012 "
+       id="polygon202" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="847.74976"
+     y="326.10507"
+     id="text204">
+    <tspan
+       x="847.74976"
+       y="326.10507"
+       id="tspan206">pad 3 (source)</tspan>
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#0000ff"
+     x="195.50177"
+     y="83.305092"
+     id="text208">
+    <tspan
+       x="195.50177"
+       y="83.305092"
+       id="tspan210">sink</tspan>
+    <tspan
+       x="195.50177"
+       y="99.305092"
+       id="tspan212">crop</tspan>
+    <tspan
+       x="195.50177"
+       y="115.30509"
+       id="tspan214">selection</tspan>
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#a020f0"
+     x="551.50177"
+     y="87.305092"
+     id="text216">
+    <tspan
+       x="551.50177"
+       y="87.305092"
+       id="tspan218">source</tspan>
+    <tspan
+       x="551.50177"
+       y="103.30509"
+       id="tspan220">crop</tspan>
+    <tspan
+       x="551.50177"
+       y="119.30509"
+       id="tspan222">selection</tspan>
+  </text>
+  <g
+     id="g224"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       x1="211"
+       y1="132"
+       x2="166.21001"
+       y2="135.287"
+       id="line226" />
+    <polygon
+       style="fill:#0000ff"
+       points="169.069,140.091 158.73,135.836 168.337,130.118 166.21,135.287 "
+       id="polygon228" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       points="169.069,140.091 158.73,135.836 168.337,130.118 166.21,135.287 "
+       id="polygon230" />
+  </g>
+  <g
+     id="g232"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       x1="209"
+       y1="131"
+       x2="115.581"
+       y2="306.20901"
+       id="line234" />
+    <polygon
+       style="fill:#0000ff"
+       points="121.169,306.355 112.052,312.827 112.345,301.65 115.581,306.209 "
+       id="polygon236" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       points="121.169,306.355 112.052,312.827 112.345,301.65 115.581,306.209 "
+       id="polygon238" />
+  </g>
+  <g
+     id="g240"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       x1="550.492"
+       y1="133.214"
+       x2="514.91602"
+       y2="186.46899"
+       id="line242" />
+    <polygon
+       style="fill:#a020f0"
+       points="520.463,187.168 510.75,192.706 512.147,181.613 514.916,186.469 "
+       id="polygon244" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       points="520.463,187.168 510.75,192.706 512.147,181.613 514.916,186.469 "
+       id="polygon246" />
+  </g>
+  <g
+     id="g248"
+     transform="translate(-1.4982376,-7.6949076)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       x1="550.07202"
+       y1="133.787"
+       x2="510.61801"
+       y2="275.08899"
+       id="line250" />
+    <polygon
+       style="fill:#a020f0"
+       points="516.106,274.025 508.601,282.312 506.475,271.336 510.618,275.089 "
+       id="polygon252" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       points="516.106,274.025 508.601,282.312 506.475,271.336 510.618,275.089 "
+       id="polygon254" />
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/subdev-image-processing-scaling-multi-source.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,540 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="58.803326cm"
+   height="16.463955cm"
+   viewBox="-194 128 1175.0698 319.59442"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="subdev-image-processing-scaling-multi-source.svg">
+  <metadata
+     id="metadata186">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs184" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview182"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="0.26595857"
+     inkscape:cx="1049.9581"
+     inkscape:cy="292.5708"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <rect
+     style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+     x="-9.6002426"
+     y="124.14409"
+     width="806"
+     height="327"
+     id="rect4" />
+  <g
+     id="g6"
+     transform="translate(-1.6002426,-5.8559115)">
+    <rect
+       style="fill:#ffffff"
+       x="4.5"
+       y="189"
+       width="159"
+       height="104"
+       id="rect8" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#a52a2a;stroke-width:2"
+       x="4.5"
+       y="189"
+       width="159"
+       height="104"
+       id="rect10" />
+  </g>
+  <g
+     id="g12"
+     transform="translate(-1.6002426,-5.8559115)">
+    <rect
+       style="fill:#ffffff"
+       x="49.5"
+       y="204"
+       width="94"
+       height="77"
+       id="rect14" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#0000ff;stroke-width:2"
+       x="49.5"
+       y="204"
+       width="94"
+       height="77"
+       id="rect16" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#0000ff"
+     x="58.399757"
+     y="218.14409"
+     id="text18">
+    <tspan
+       x="58.399757"
+       y="218.14409"
+       id="tspan20">sink</tspan>
+    <tspan
+       x="58.399757"
+       y="234.14409"
+       id="tspan22">crop</tspan>
+    <tspan
+       x="58.399757"
+       y="250.14409"
+       id="tspan24">selection</tspan>
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="27.899757"
+     y="152.14409"
+     id="text26">
+    <tspan
+       x="27.899757"
+       y="152.14409"
+       id="tspan28" />
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#a52a2a"
+     x="6.938117"
+     y="152.05809"
+     id="text30">
+    <tspan
+       x="6.938117"
+       y="152.05809"
+       id="tspan32">sink media</tspan>
+    <tspan
+       x="6.938117"
+       y="168.05809"
+       id="tspan34">bus format</tspan>
+  </text>
+  <g
+     id="g36"
+     transform="translate(-1.6002426,-5.8559115)">
+    <rect
+       style="fill:#ffffff"
+       x="333.64401"
+       y="185.64999"
+       width="165.2"
+       height="172.478"
+       id="rect38" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#00ff00;stroke-width:2"
+       x="333.64401"
+       y="185.64999"
+       width="165.2"
+       height="172.478"
+       id="rect40" />
+  </g>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="332.04376"
+     y1="352.27206"
+     x2="47.899757"
+     y2="275.14407"
+     id="line42" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="332.04376"
+     y1="179.79408"
+     x2="47.899757"
+     y2="198.14409"
+     id="line44" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="497.24374"
+     y1="352.27206"
+     x2="141.89977"
+     y2="275.14407"
+     id="line46" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="497.24374"
+     y1="179.79408"
+     x2="141.89977"
+     y2="198.14409"
+     id="line48" />
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#00ff00"
+     x="333.10376"
+     y="143.58609"
+     id="text50">
+    <tspan
+       x="333.10376"
+       y="143.58609"
+       id="tspan52">sink compose</tspan>
+    <tspan
+       x="333.10376"
+       y="159.58609"
+       id="tspan54">selection (scaling)</tspan>
+  </text>
+  <g
+     id="g56"
+     transform="translate(-1.6002426,-5.8559115)">
+    <rect
+       style="fill:#ffffff"
+       x="382.32199"
+       y="199.565"
+       width="100.186"
+       height="71.452301"
+       id="rect58" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       x="382.32199"
+       y="199.565"
+       width="100.186"
+       height="71.452301"
+       id="rect60" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#a020f0"
+     x="541.7218"
+     y="143.58609"
+     id="text62">
+    <tspan
+       x="541.7218"
+       y="143.58609"
+       id="tspan64">source</tspan>
+    <tspan
+       x="541.7218"
+       y="159.58609"
+       id="tspan66">crop</tspan>
+    <tspan
+       x="541.7218"
+       y="175.58609"
+       id="tspan68">selection</tspan>
+  </text>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#8b6914"
+     x="689.89978"
+     y="151.27209"
+     id="text70">
+    <tspan
+       x="689.89978"
+       y="151.27209"
+       id="tspan72">source media</tspan>
+    <tspan
+       x="689.89978"
+       y="167.27209"
+       id="tspan74">bus format</tspan>
+  </text>
+  <g
+     id="g76"
+     transform="translate(-1.6002426,-5.8559115)">
+    <rect
+       style="fill:#ffffff"
+       x="690.48798"
+       y="225.834"
+       width="100.186"
+       height="71.452301"
+       id="rect78" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#8b6914;stroke-width:2"
+       x="690.48798"
+       y="225.834"
+       width="100.186"
+       height="71.452301"
+       id="rect80" />
+  </g>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="688.88776"
+     y1="291.43008"
+     x2="380.72174"
+     y2="265.16208"
+     id="line82" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="688.88776"
+     y1="219.97809"
+     x2="380.72174"
+     y2="193.70909"
+     id="line84" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="789.07379"
+     y1="291.43008"
+     x2="480.90775"
+     y2="265.16208"
+     id="line86" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="789.07379"
+     y1="219.97809"
+     x2="480.90775"
+     y2="193.70909"
+     id="line88" />
+  <g
+     id="g90"
+     transform="translate(-1.6002426,-5.8559115)">
+    <circle
+       style="fill:#ffffff"
+       cx="808.09998"
+       cy="249.98399"
+       id="ellipse92"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="808.09998"
+       cy="249.98399"
+       id="ellipse94"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="808.09998"
+       cy="249.98399"
+       id="ellipse96"
+       r="8.5" />
+  </g>
+  <g
+     id="g98"
+     transform="translate(-1.6002426,-5.8559115)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="816.59998"
+       y1="249.98399"
+       x2="972.93402"
+       y2="250.01199"
+       id="line100" />
+    <polygon
+       style="fill:#000000"
+       points="970.435,245.012 980.434,250.014 970.433,255.012 972.934,250.012 "
+       id="polygon102" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="970.435,245.012 980.434,250.014 970.433,255.012 972.934,250.012 "
+       id="polygon104" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="840.3078"
+     y="233.94409"
+     id="text106">
+    <tspan
+       x="840.3078"
+       y="233.94409"
+       id="tspan108">pad 1 (source)</tspan>
+  </text>
+  <g
+     id="g110"
+     transform="translate(-1.6002426,-5.8559115)">
+    <circle
+       style="fill:#ffffff"
+       cx="-20.398199"
+       cy="241.51199"
+       id="ellipse112"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-20.398199"
+       cy="241.51199"
+       id="ellipse114"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="-20.398199"
+       cy="241.51199"
+       id="ellipse116"
+       r="8.5" />
+  </g>
+  <g
+     id="g118"
+     transform="translate(-1.6002426,-5.8559115)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="-192.39799"
+       y1="241.8"
+       x2="-38.6343"
+       y2="241.52901"
+       id="line120" />
+    <polygon
+       style="fill:#000000"
+       points="-41.1431,236.534 -31.1343,241.516 -41.1254,246.534 -38.6343,241.529 "
+       id="polygon122" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="-41.1431,236.534 -31.1343,241.516 -41.1254,246.534 -38.6343,241.529 "
+       id="polygon124" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="-149.45824"
+     y="223.94409"
+     id="text126">
+    <tspan
+       x="-149.45824"
+       y="223.94409"
+       id="tspan128">pad 0 (sink)</tspan>
+  </text>
+  <rect
+     style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+     x="388.22174"
+     y="270.81006"
+     width="100.186"
+     height="71.452301"
+     id="rect130" />
+  <g
+     id="g132"
+     transform="translate(-1.6002426,-5.8559115)">
+    <rect
+       style="fill:#ffffff"
+       x="689.98798"
+       y="345.93399"
+       width="100.186"
+       height="71.452301"
+       id="rect134" />
+    <rect
+       style="fill:none;fill-opacity:0;stroke:#8b6914;stroke-width:2"
+       x="689.98798"
+       y="345.93399"
+       width="100.186"
+       height="71.452301"
+       id="rect136" />
+  </g>
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="688.38776"
+     y1="411.53006"
+     x2="388.22174"
+     y2="342.26208"
+     id="line138" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="688.38776"
+     y1="340.07806"
+     x2="388.22174"
+     y2="270.81006"
+     id="line140" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="788.57379"
+     y1="411.53006"
+     x2="488.40775"
+     y2="342.26208"
+     id="line142" />
+  <line
+     style="fill:none;fill-opacity:0;stroke:#e60505;stroke-width:2;stroke-dasharray:4"
+     x1="788.57379"
+     y1="340.07806"
+     x2="488.40775"
+     y2="270.81006"
+     id="line144" />
+  <g
+     id="g146"
+     transform="translate(-1.6002426,-5.8559115)">
+    <circle
+       style="fill:#ffffff"
+       cx="805.59998"
+       cy="384.08401"
+       id="ellipse148"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="805.59998"
+       cy="384.08401"
+       id="ellipse150"
+       r="8.5" />
+    <circle
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       cx="805.59998"
+       cy="384.08401"
+       id="ellipse152"
+       r="8.5" />
+  </g>
+  <g
+     id="g154"
+     transform="translate(-1.6002426,-5.8559115)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       x1="814.09998"
+       y1="384.08401"
+       x2="970.43402"
+       y2="384.112"
+       id="line156" />
+    <polygon
+       style="fill:#000000"
+       points="967.935,379.112 977.934,384.114 967.933,389.112 970.434,384.112 "
+       id="polygon158" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#000000;stroke-width:2"
+       points="967.935,379.112 977.934,384.114 967.933,389.112 970.434,384.112 "
+       id="polygon160" />
+  </g>
+  <text
+     style="font-style:normal;font-weight:normal;font-size:12.80000019px;font-family:sanserif;text-anchor:start;fill:#000000"
+     x="837.8078"
+     y="368.04407"
+     id="text162">
+    <tspan
+       x="837.8078"
+       y="368.04407"
+       id="tspan164">pad 2 (source)</tspan>
+  </text>
+  <g
+     id="g166"
+     transform="translate(-1.6002426,-5.8559115)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       x1="546"
+       y1="191"
+       x2="492.15701"
+       y2="198.263"
+       id="line168" />
+    <polygon
+       style="fill:#a020f0"
+       points="495.303,202.884 484.724,199.266 493.966,192.974 492.157,198.263 "
+       id="polygon170" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       points="495.303,202.884 484.724,199.266 493.966,192.974 492.157,198.263 "
+       id="polygon172" />
+  </g>
+  <g
+     id="g174"
+     transform="translate(-1.6002426,-5.8559115)">
+    <line
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       x1="546.90802"
+       y1="190.72501"
+       x2="495.383"
+       y2="268.548"
+       id="line176" />
+    <polygon
+       style="fill:#a020f0"
+       points="500.932,269.224 491.242,274.802 492.594,263.703 495.383,268.548 "
+       id="polygon178" />
+    <polygon
+       style="fill:none;fill-opacity:0;stroke:#a020f0;stroke-width:2"
+       points="500.932,269.224 491.242,274.802 492.594,263.703 495.383,268.548 "
+       id="polygon180" />
+  </g>
+</svg>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/v4l2.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/v4l2.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/v4l2.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/v4l2.rst	2017-02-12 16:03:20.000000000 -0500
@@ -68,6 +68,10 @@ Authors, in alphabetical order:
 
   - SDR API.
 
+- Ribalda, Ricardo
+
+  - Introduce HSV formats and other minor changes.
+
 - Rubli, Martin
 
   - Designed and documented the VIDIOC_ENUM_FRAMESIZES and VIDIOC_ENUM_FRAMEINTERVALS ioctls.
@@ -89,6 +93,11 @@ part can be used and distributed without
 Revision History
 ****************
 
+:revision: 4.10 / 2016-07-15 (*rr*)
+
+Introduce HSV formats.
+
+
 :revision: 4.5 / 2015-10-29 (*rr*)
 
 Extend VIDIOC_G_EXT_CTRLS;. Replace ctrl_class with a new union with
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vbi_525.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vbi_525.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vbi_525.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vbi_525.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,811 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   xml:space="preserve"
+   width="208.73068mm"
+   height="51.395489mm"
+   viewBox="0 0 739.59691 182.11"
+   sodipodi:docname="vbi_525.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview4"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="1.5350601"
+     inkscape:cx="264.23387"
+     inkscape:cy="44.916942"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g10"
+     units="mm" /><metadata
+     id="metadata8"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs6"><clipPath
+       id="clipPath20"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path22"
+         d="m 0,0 5950,0 0,3922 L 0,3922 0,0 Z m 0,3922 5950,0 0,1 -5950,0 0,-1 z m 0,1 1359,0 0,1 -1359,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1363,0 0,1 -1363,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1367,0 0,1 -1367,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1371,0 0,1 -1371,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1375,0 0,1 -1375,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1379,0 0,1 -1379,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1383,0 0,1 -1383,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1387,0 0,1 -1387,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1391,0 0,1 -1391,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1390,0 0,1 -1390,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1386,0 0,1 -1386,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1382,0 0,1 -1382,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1378,0 0,1 -1378,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1374,0 0,1 -1374,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1370,0 0,1 -1370,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1366,0 0,1 -1366,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1362,0 0,1 -1362,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1358,0 0,1 -1358,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,4478 -5950,0 0,-4478 z" /></clipPath><clipPath
+       id="clipPath98"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path100"
+         d="m 0,0 5950,0 0,4546 L 0,4546 0,0 Z m 0,4546 5950,0 0,1 -5950,0 0,-1 z m 0,1 1360,0 0,1 -1360,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1364,0 0,1 -1364,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1368,0 0,1 -1368,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1372,0 0,1 -1372,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1376,0 0,1 -1376,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1380,0 0,1 -1380,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1384,0 0,1 -1384,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1388,0 0,1 -1388,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1391,0 0,1 -1391,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1389,0 0,1 -1389,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1385,0 0,1 -1385,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1381,0 0,1 -1381,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1377,0 0,1 -1377,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1373,0 0,1 -1373,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1369,0 0,1 -1369,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1365,0 0,1 -1365,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1361,0 0,1 -1361,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 1357,0 0,1 -1357,0 0,-1 z m 1399,0 4551,0 0,1 -4551,0 0,-1 z m -1399,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,3854 -5950,0 0,-3854 z" /></clipPath></defs><g
+     transform="matrix(0.125,0,0,-0.125,-87.571875,638.05691)"
+     inkscape:label="vbi_525"
+     inkscape:groupmode="layer"
+     id="g10"><g
+       transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+       id="g12"
+       style=""><path
+         inkscape:connector-curvature="0"
+         id="path14"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1281.75,3974.45 0,-85.05" /></g><g
+       transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+       id="g16"
+       style=""><g
+         clip-path="url(#clipPath20)"
+         id="g18"
+         style=""><path
+           inkscape:connector-curvature="0"
+           id="path24"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="m 1281.75,3931.93 113.4,0" /></g></g><g
+       transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+       id="g26"
+       style=""><path
+         inkscape:connector-curvature="0"
+         id="path28"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 1352.31,3922.48 37.8,9.45 -37.8,9.45 0,-18.9" /><path
+         inkscape:connector-curvature="0"
+         id="path30"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1352.31,3922.48 37.8,9.45 -37.8,9.45 0,-18.9 z" /><path
+         inkscape:connector-curvature="0"
+         id="path32"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4683.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path34"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4400.25,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path36"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4116.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path38"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 3833.25,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path40"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 3549.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path42"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 3266.25,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path44"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2982.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path46"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2699.25,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path48"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2415.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path50"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2132.25,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path52"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1848.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path54"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1565.25,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path56"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1281.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path58"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 998.25,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path60"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 714.75,4059.5 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path62"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4683.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path64"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4400.25,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path66"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 4116.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path68"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 3833.25,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path70"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 3549.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path72"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 3266.25,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path74"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2982.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path76"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2699.25,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path78"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2415.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path80"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 2132.25,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path82"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1848.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path84"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1565.25,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path86"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1281.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path88"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 998.25,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path90"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 714.75,4144.55 0,-56.7" /><path
+         inkscape:connector-curvature="0"
+         id="path92"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1281.75,4598.15 0,-85.05" /></g><g
+       transform="matrix(1.3000026,0,0,1.3000026,-210.17435,-1094.2823)"
+       id="g94"
+       style=""><g
+         clip-path="url(#clipPath98)"
+         id="g96"
+         style=""><path
+           inkscape:connector-curvature="0"
+           id="path102"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="m 1281.75,4555.63 113.4,0" /></g></g><path
+       d="m 1547.8322,4815.7637 49.1401,12.2851 -49.1401,12.285 0,-24.5701"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path106"
+       inkscape:connector-curvature="0" /><path
+       d="m 1547.8322,4815.7637 49.1401,12.2851 -49.1401,12.285 0,-24.5701 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path108"
+       inkscape:connector-curvature="0" /><path
+       d="m 1456.104,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path110"
+       inkscape:connector-curvature="0" /><path
+       d="m 1824.6548,5030.7452 0,73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path112"
+       inkscape:connector-curvature="0" /><path
+       d="m 2193.2055,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path114"
+       inkscape:connector-curvature="0" /><path
+       d="m 2561.7563,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path116"
+       inkscape:connector-curvature="0" /><path
+       d="m 2930.307,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path118"
+       inkscape:connector-curvature="0" /><path
+       d="m 3298.8578,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path120"
+       inkscape:connector-curvature="0" /><path
+       d="m 3667.4085,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path122"
+       inkscape:connector-curvature="0" /><path
+       d="m 4035.9593,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path124"
+       inkscape:connector-curvature="0" /><path
+       d="m 4404.51,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path126"
+       inkscape:connector-curvature="0" /><path
+       d="m 4773.0608,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path128"
+       inkscape:connector-curvature="0" /><path
+       d="m 5141.6115,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path130"
+       inkscape:connector-curvature="0" /><path
+       d="m 5510.1623,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path132"
+       inkscape:connector-curvature="0" /><path
+       d="m 5878.713,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path134"
+       inkscape:connector-curvature="0" /><path
+       d="m 1456.104,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path136"
+       inkscape:connector-curvature="0" /><path
+       d="m 1824.6548,4920.1799 0,73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path138"
+       inkscape:connector-curvature="0" /><path
+       d="m 2193.2055,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path140"
+       inkscape:connector-curvature="0" /><path
+       d="m 2561.7563,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path142"
+       inkscape:connector-curvature="0" /><path
+       d="m 2930.307,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path144"
+       inkscape:connector-curvature="0" /><path
+       d="m 3298.8578,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path146"
+       inkscape:connector-curvature="0" /><path
+       d="m 3667.4085,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path148"
+       inkscape:connector-curvature="0" /><path
+       d="m 4035.9593,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path150"
+       inkscape:connector-curvature="0" /><path
+       d="m 4404.51,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path152"
+       inkscape:connector-curvature="0" /><path
+       d="m 4773.0608,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path154"
+       inkscape:connector-curvature="0" /><path
+       d="m 5141.6115,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path156"
+       inkscape:connector-curvature="0" /><path
+       d="m 5510.1623,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path158"
+       inkscape:connector-curvature="0" /><path
+       d="m 5878.713,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path160"
+       inkscape:connector-curvature="0" /><path
+       d="m 719.00254,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path162"
+       inkscape:connector-curvature="0" /><path
+       d="m 719.00254,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path164"
+       inkscape:connector-curvature="0" /><path
+       d="m 1087.5533,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path166"
+       inkscape:connector-curvature="0" /><path
+       d="m 1087.5533,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path168"
+       inkscape:connector-curvature="0" /><path
+       d="m 700.575,4735.9046 18.42754,0 0,-110.5653 36.85507,0 0,110.5653 18.42754,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path170"
+       inkscape:connector-curvature="0" /><path
+       d="m 774.28515,4680.6285 18.42754,0 0,110.5652 -18.42754,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path172"
+       inkscape:connector-curvature="0" /><path
+       d="m 792.71269,4735.9046 18.42753,0 0,92.1442 18.42754,-18.4341 18.42754,36.8551 18.42754,-36.8551 18.42753,36.8551 18.42754,-55.2761 18.42754,55.2761 18.42754,-18.421 18.42753,55.2761 18.42754,-55.2761 18.42754,18.421 18.4275,36.8551 18.4276,-92.1312 18.4275,55.2761 18.4275,-55.2761 0,-55.2891"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path174"
+       inkscape:connector-curvature="0" /><path
+       d="m 1069.1257,4735.9046 18.4276,0 0,-110.5653 36.8551,0 0,110.5653 18.421,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path176"
+       inkscape:connector-curvature="0" /><path
+       d="m 1142.8294,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path178"
+       inkscape:connector-curvature="0" /><path
+       d="m 1456.104,4735.9046 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 18.421,0 0,110.5653 165.8543,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 147.4203,0 0,110.5653 36.855,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 147.4203,0 0,110.5653 36.855,0 0,-110.5653 147.4203,0 0,110.5653 36.8551,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 18.421,0 0,110.5653 165.8543,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.4211,0 0,110.5653 165.8543,0 0,-110.5653 18.421,0 0,110.5653 165.8544,0 0,-110.5653 36.855,0 0,110.5653 18.4211,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path180"
+       inkscape:connector-curvature="0" /><path
+       d="m 1161.2634,4735.9046 294.8406,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path182"
+       inkscape:connector-curvature="0" /><path
+       d="m 6320.9739,4735.9046 18.421,0 0,92.1442 18.4341,-18.4341 18.421,73.7102 18.4341,-55.2761 18.421,36.855 18.434,-18.434 18.4211,36.8551 18.434,-36.8551 18.421,36.8551 18.4341,-36.8551 18.421,18.434 18.4341,-36.855 18.421,36.855 18.434,-36.855 18.4211,-18.4341 0,-73.7101 18.434,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path184"
+       inkscape:connector-curvature="0" /><path
+       d="m 4828.3369,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path186"
+       inkscape:connector-curvature="0" /><path
+       d="m 4846.7709,4735.9046 294.8406,0 0,-110.5653 36.8551,0 0,110.5653 18.421,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path188"
+       inkscape:connector-curvature="0" /><path
+       d="m 5196.8876,4680.6285 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path190"
+       inkscape:connector-curvature="0" /><path
+       d="m 5565.4384,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path192"
+       inkscape:connector-curvature="0" /><path
+       d="m 5933.9891,4680.6285 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path194"
+       inkscape:connector-curvature="0" /><path
+       d="m 5952.4232,4735.9046 294.8406,0 0,-110.5653 36.855,0 0,110.5653 18.4211,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path196"
+       inkscape:connector-curvature="0" /><path
+       d="m 6302.5399,4680.6285 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path198"
+       inkscape:connector-curvature="0" /><path
+       d="m 5786.5688,4735.9046 92.1442,0 0,-110.5653 36.8551,0 0,110.5653 18.421,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path200"
+       inkscape:connector-curvature="0" /><path
+       d="m 5805.0029,4791.1937 -36.8551,-110.5652"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path202"
+       inkscape:connector-curvature="0" /><path
+       d="m 5583.8724,4735.9046 165.8414,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path204"
+       inkscape:connector-curvature="0" /><path
+       d="m 5768.1478,4791.1937 -36.8551,-110.5652"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path206"
+       inkscape:connector-curvature="0" /><path
+       d="m 5215.3217,4735.9046 294.8406,0 0,-110.5653 36.855,0 0,110.5653 18.4211,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path208"
+       inkscape:connector-curvature="0" /><path
+       d="m 6247.2638,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path210"
+       inkscape:connector-curvature="0" /><path
+       d="m 6247.2638,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path212"
+       inkscape:connector-curvature="0" /><path
+       d="m 6615.8145,5104.4553 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path214"
+       inkscape:connector-curvature="0" /><path
+       d="m 6615.8145,4993.8901 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path216"
+       inkscape:connector-curvature="0" /><path
+       d="m 700.575,3925.0929 18.42754,0 0,-110.5652 36.85507,0 0,110.5652 18.42754,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path218"
+       inkscape:connector-curvature="0" /><path
+       d="m 774.28515,3869.8168 18.42754,0 0,110.5652 -18.42754,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path220"
+       inkscape:connector-curvature="0" /><path
+       d="m 1142.8294,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path222"
+       inkscape:connector-curvature="0" /><path
+       d="m 792.71269,3925.0929 18.42753,0 0,110.5652 18.42754,-36.855 18.42754,18.434 18.42754,-36.8551 18.42753,36.8551 0,-92.1442 202.70293,0 0,-110.5652 36.8551,0 0,110.5652 18.421,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path224"
+       inkscape:connector-curvature="0" /><path
+       d="m 1161.2634,3925.0929 110.5653,0 0,-110.5652 18.421,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.421,0 0,110.5652 165.8544,0 0,-110.5652 18.421,0 0,110.5652 165.8544,0 0,-110.5652 18.421,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.855,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.8551,0 0,-110.5652 147.4203,0 0,110.5652 36.855,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.421,0 0,110.5652 165.8544,0 0,-110.5652 18.421,0 0,110.5652 165.8543,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path226"
+       inkscape:connector-curvature="0" /><path
+       d="m 4220.2346,3925.0929 0,-110.5652 18.4211,0 0,110.5652 165.8543,0 0,-110.5652 18.4211,0 0,110.5652 55.2891,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path228"
+       inkscape:connector-curvature="0" /><path
+       d="m 4478.2202,3925.0929 294.8406,0 0,-110.5652 36.855,0 0,110.5652 18.4211,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path230"
+       inkscape:connector-curvature="0" /><path
+       d="m 5952.4232,3925.0929 128.9862,0 0,73.7102 18.4341,36.855 18.421,-18.421 18.434,36.8551 18.4211,-36.8551 18.434,18.421 18.421,-36.855 18.4341,18.434 18.421,-36.8551 0,-55.2891 18.4341,0 0,-110.5652 36.855,0 0,110.5652 18.4211,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path232"
+       inkscape:connector-curvature="0" /><path
+       d="m 6302.5399,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path234"
+       inkscape:connector-curvature="0" /><path
+       d="m 6320.9739,3925.0929 18.421,0 0,73.7102 18.4341,36.855 18.421,-36.855 18.4341,36.855 18.421,-18.421 18.434,0 18.4211,-36.8551 18.434,55.2761 18.421,-18.421 0,36.8551 18.4341,-18.4341 18.421,18.4341 18.4341,-36.8551 18.421,18.421 18.434,-55.2761 18.4211,18.4211 0,-73.7102 18.434,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path236"
+       inkscape:connector-curvature="0" /><path
+       d="m 5933.9891,3869.8168 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path238"
+       inkscape:connector-curvature="0" /><path
+       d="m 5786.5688,3925.0929 92.1442,0 0,-110.5652 36.8551,0 0,110.5652 18.421,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path240"
+       inkscape:connector-curvature="0" /><path
+       d="m 5805.0029,3980.382 -36.8551,-110.5652"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path242"
+       inkscape:connector-curvature="0" /><path
+       d="m 5768.1478,3980.382 -36.8551,-110.5652"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path244"
+       inkscape:connector-curvature="0" /><path
+       d="m 4828.3369,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path246"
+       inkscape:connector-curvature="0" /><path
+       d="m 5583.8724,3925.0929 165.8414,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path248"
+       inkscape:connector-curvature="0" /><path
+       d="m 4846.7709,3925.0929 294.8406,0 0,-110.5652 36.8551,0 0,110.5652 18.421,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path250"
+       inkscape:connector-curvature="0" /><path
+       d="m 5196.8876,3869.8168 18.4276,0 0,110.5652 -18.4276,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path252"
+       inkscape:connector-curvature="0" /><path
+       d="m 5215.3217,3925.0929 294.8406,0 0,-110.5652 36.855,0 0,110.5652 18.4211,0"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path254"
+       inkscape:connector-curvature="0" /><path
+       d="m 5565.4384,3869.8168 18.4275,0 0,110.5652 -18.4275,0 0,-110.5652 z"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path256"
+       inkscape:connector-curvature="0" /><path
+       d="m 6247.2638,4293.6437 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path258"
+       inkscape:connector-curvature="0" /><path
+       d="m 6247.2638,4183.0784 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path260"
+       inkscape:connector-curvature="0" /><path
+       d="m 6615.8145,4293.6437 0,-73.7102"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path262"
+       inkscape:connector-curvature="0" /><path
+       d="m 6615.8145,4183.0784 0,-73.7101"
+       style="fill:none;stroke:#000000;stroke-width:3.07125616;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path264"
+       inkscape:connector-curvature="0" /><text
+       y="-4035.6582"
+       x="1621.9453"
+       id="text268"
+       style="font-variant:normal;font-weight:normal;font-size:61.42512512px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan270"
+         sodipodi:role="line"
+         y="-4035.6582"
+         x="1621.9453 1642.3999 1676.5522">(1)</tspan></text>
+<text
+       y="-4127.7959"
+       x="4199.7334"
+       id="text272"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan274"
+         sodipodi:role="line"
+         y="-4127.7959"
+         x="4199.7334 3831.1829 2725.5305 3112.509 3462.6321 4568.2842 4916.3442 4957.3271 5653.4458 5694.4287 5284.895 5325.8779 2356.9773 1988.4264 1210.3424 1251.3252 1292.3081 1619.8759 841.79163 882.77454 923.75732">874569101211322631262</tspan><tspan
+         id="tspan276"
+         sodipodi:role="line"
+         y="-4238.3613"
+         x="4158.748 4199.7314 4240.7144 3790.1975 3831.1807 3872.1633 2684.5457 2725.5283 2766.5112 3071.5237 3112.5063 3153.4895 3421.647 3462.6299 3503.6125 4527.2988 4568.2822 4609.2646 4895.8496 4936.833 4977.8154 5632.9517 5673.9341 5714.917 5264.4009 5305.3833 5346.3662 2315.9946 2356.9775 2397.9604 1947.444 1988.4269 2029.4097 1210.3424 1251.3252 1292.3081 1578.8931 1619.876 1660.8589 841.79163 882.77454 923.75732">271270267268269272273275274266265263264262</tspan><tspan
+         id="tspan278"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="2725.5347 4568.2881 1988.4331 2356.9839 1619.8822 3094.0852 3462.636 4916.3506 4957.334 5284.9019 5325.8843 5653.4526 5694.4351 3812.7656 4181.3164">492315610111278</tspan><tspan
+         id="tspan280"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="2725.5474 4568.3013 1988.446 2356.9966 1619.8953 3094.0981 3462.6489 4916.3638 4957.3472 5284.9146 5325.8975 5653.4653 5694.4482 3812.7788 4181.3296">492315610111278</tspan><tspan
+         id="tspan282"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="841.81781 882.8006 923.78326">524</tspan><tspan
+         id="tspan284"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="841.81781 882.8006 923.78326">261</tspan><tspan
+         id="tspan286"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="1210.3684 1251.3512 1292.3342">525</tspan><tspan
+         id="tspan288"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="1210.3684 1251.3512 1292.3342">262</tspan><tspan
+         id="tspan290"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="6022.0161 6062.999">22</tspan><tspan
+         id="tspan292"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="6022.0161 6062.999">22</tspan><tspan
+         id="tspan294"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="6390.5669 6431.5498">23</tspan><tspan
+         id="tspan296"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="6390.5669 6431.5498">23</tspan><tspan
+         id="tspan298"
+         sodipodi:role="line"
+         y="-4238.3623"
+         x="6001.5244 6042.5068 6083.4902">285</tspan><tspan
+         id="tspan300"
+         sodipodi:role="line"
+         y="-4127.7964"
+         x="6022.0156 6062.9985">22</tspan><tspan
+         id="tspan302"
+         sodipodi:role="line"
+         y="-4238.3623"
+         x="6370.0747 6411.0571 6452.04">286</tspan><tspan
+         id="tspan304"
+         sodipodi:role="line"
+         y="-4127.7964"
+         x="6390.5664 6431.5493">23</tspan><tspan
+         id="tspan306"
+         sodipodi:role="line"
+         y="-4459.4922"
+         x="3540.4146 3581.3972 3618.2522 3638.7437 3659.2354 3679.7266 3696.0901 3737.073 3753.4365">1st field</tspan><tspan
+         id="tspan308"
+         sodipodi:role="line"
+         y="-3648.6809"
+         x="3528.1047 3569.0876 3610.0703 3651.0532 3671.5447 3692.0361 3708.3999 3749.3826 3765.7463">2nd field</tspan></text>
+<text
+       y="-4127.7959"
+       x="4199.7334 3831.1829 2725.5305 3112.509 3462.6321 4568.2842 4916.3442 4957.3271 5653.4458 5694.4287 5284.895 5325.8779 2356.9773 1988.4264 1210.3424 1251.3252 1292.3081 1619.8759 841.79163 882.77454 923.75732"
+       id="text3632"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3634"
+         sodipodi:role="line"
+         y="-4127.7959"
+         x="4199.7334 3831.1829 2725.5305 3112.509 3462.6321 4568.2842 4916.3442 4957.3271 5653.4458 5694.4287 5284.895 5325.8779 2356.9773 1988.4264 1210.3424 1251.3252 1292.3081 1619.8759 841.79163 882.77454 923.75732">874569101211322631262</tspan></text>
+<text
+       y="-4238.3613"
+       x="4158.748 4199.7314 4240.7144 3790.1975 3831.1807 3872.1633 2684.5457 2725.5283 2766.5112 3071.5237 3112.5063 3153.4895 3421.647 3462.6299 3503.6125 4527.2988 4568.2822 4609.2646 4895.8496 4936.833 4977.8154 5632.9517 5673.9341 5714.917 5264.4009 5305.3833 5346.3662 2315.9946 2356.9775 2397.9604 1947.444 1988.4269 2029.4097 1210.3424 1251.3252 1292.3081 1578.8931 1619.876 1660.8589 841.79163 882.77454 923.75732"
+       id="text3636"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3638"
+         sodipodi:role="line"
+         y="-4238.3613"
+         x="4158.748 4199.7314 4240.7144 3790.1975 3831.1807 3872.1633 2684.5457 2725.5283 2766.5112 3071.5237 3112.5063 3153.4895 3421.647 3462.6299 3503.6125 4527.2988 4568.2822 4609.2646 4895.8496 4936.833 4977.8154 5632.9517 5673.9341 5714.917 5264.4009 5305.3833 5346.3662 2315.9946 2356.9775 2397.9604 1947.444 1988.4269 2029.4097 1210.3424 1251.3252 1292.3081 1578.8931 1619.876 1660.8589 841.79163 882.77454 923.75732">271270267268269272273275274266265263264262</tspan></text>
+<text
+       y="-5049.1729"
+       x="2725.5347 4568.2881 1988.4331 2356.9839 1619.8822 3094.0852 3462.636 4916.3506 4957.334 5284.9019 5325.8843 5653.4526 5694.4351 3812.7656 4181.3164"
+       id="text3640"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3642"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="2725.5347 4568.2881 1988.4331 2356.9839 1619.8822 3094.0852 3462.636 4916.3506 4957.334 5284.9019 5325.8843 5653.4526 5694.4351 3812.7656 4181.3164">492315610111278</tspan></text>
+<text
+       y="-4938.6074"
+       x="2725.5474 4568.3013 1988.446 2356.9966 1619.8953 3094.0981 3462.6489 4916.3638 4957.3472 5284.9146 5325.8975 5653.4653 5694.4482 3812.7788 4181.3296"
+       id="text3644"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3646"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="2725.5474 4568.3013 1988.446 2356.9966 1619.8953 3094.0981 3462.6489 4916.3638 4957.3472 5284.9146 5325.8975 5653.4653 5694.4482 3812.7788 4181.3296">492315610111278</tspan></text>
+<text
+       y="-5049.1729"
+       x="841.81781 882.8006 923.78326"
+       id="text3648"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3650"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="841.81781 882.8006 923.78326">524</tspan></text>
+<text
+       y="-4938.6074"
+       x="841.81781 882.8006 923.78326"
+       id="text3652"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3654"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="841.81781 882.8006 923.78326">261</tspan></text>
+<text
+       y="-5049.1729"
+       x="1210.3684 1251.3512 1292.3342"
+       id="text3656"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3658"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="1210.3684 1251.3512 1292.3342">525</tspan></text>
+<text
+       y="-4938.6074"
+       x="1210.3684 1251.3512 1292.3342"
+       id="text3660"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3662"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="1210.3684 1251.3512 1292.3342">262</tspan></text>
+<text
+       y="-5049.1729"
+       x="6022.0161 6062.999"
+       id="text3664"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3666"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="6022.0161 6062.999">22</tspan></text>
+<text
+       y="-4938.6074"
+       x="6022.0161 6062.999"
+       id="text3668"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3670"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="6022.0161 6062.999">22</tspan></text>
+<text
+       y="-5049.1729"
+       x="6390.5669 6431.5498"
+       id="text3672"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3674"
+         sodipodi:role="line"
+         y="-5049.1729"
+         x="6390.5669 6431.5498">23</tspan></text>
+<text
+       y="-4938.6074"
+       x="6390.5669 6431.5498"
+       id="text3676"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3678"
+         sodipodi:role="line"
+         y="-4938.6074"
+         x="6390.5669 6431.5498">23</tspan></text>
+<text
+       y="-4238.3623"
+       x="6001.5244 6042.5068 6083.4902"
+       id="text3680"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3682"
+         sodipodi:role="line"
+         y="-4238.3623"
+         x="6001.5244 6042.5068 6083.4902">285</tspan></text>
+<text
+       y="-4127.7964"
+       x="6022.0156 6062.9985"
+       id="text3684"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3686"
+         sodipodi:role="line"
+         y="-4127.7964"
+         x="6022.0156 6062.9985">22</tspan></text>
+<text
+       y="-4238.3623"
+       x="6370.0747 6411.0571 6452.04"
+       id="text3688"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3690"
+         sodipodi:role="line"
+         y="-4238.3623"
+         x="6370.0747 6411.0571 6452.04">286</tspan></text>
+<text
+       y="-4127.7964"
+       x="6390.5664 6431.5493"
+       id="text3692"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3694"
+         sodipodi:role="line"
+         y="-4127.7964"
+         x="6390.5664 6431.5493">23</tspan></text>
+<text
+       y="-4459.4922"
+       x="3540.4146 3581.3972 3618.2522 3638.7437 3659.2354 3679.7266 3696.0901 3737.073 3753.4365"
+       id="text3696"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3698"
+         sodipodi:role="line"
+         y="-4459.4922"
+         x="3540.4146 3581.3972 3618.2522 3638.7437 3659.2354 3679.7266 3696.0901 3737.073 3753.4365">1st field</tspan></text>
+<text
+       y="-3648.6809"
+       x="3528.1047 3569.0876 3610.0703 3651.0532 3671.5447 3692.0361 3708.3999 3749.3826 3765.7463"
+       id="text3700"
+       style="font-variant:normal;font-weight:normal;font-size:73.71015167px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"><tspan
+         id="tspan3702"
+         sodipodi:role="line"
+         y="-3648.6809"
+         x="3528.1047 3569.0876 3610.0703 3651.0532 3671.5447 3692.0361 3708.3999 3749.3826 3765.7463">2nd field</tspan></text>
+</g></svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vbi_625.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vbi_625.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vbi_625.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vbi_625.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,858 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   xml:space="preserve"
+   width="209.46608mm"
+   height="51.576824mm"
+   viewBox="0 0 742.20265 182.75252"
+   sodipodi:docname="vbi_625.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview4"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="1.5350601"
+     inkscape:cx="288.91482"
+     inkscape:cy="170.67667"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g10"
+     units="mm" /><metadata
+     id="metadata8"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs6"><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath20"><path
+         d="m 0,0 5950,0 0,4546 L 0,4546 0,0 Z m 0,4546 5950,0 0,1 -5950,0 0,-1 z m 0,1 2211,0 0,1 -2211,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2215,0 0,1 -2215,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2219,0 0,1 -2219,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2223,0 0,1 -2223,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2227,0 0,1 -2227,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2231,0 0,1 -2231,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2235,0 0,1 -2235,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2239,0 0,1 -2239,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2241,0 0,1 -2241,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2240,0 0,1 -2240,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2236,0 0,1 -2236,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2232,0 0,1 -2232,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2228,0 0,1 -2228,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2224,0 0,1 -2224,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2220,0 0,1 -2220,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2216,0 0,1 -2216,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2212,0 0,1 -2212,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2208,0 0,1 -2208,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,3854 -5950,0 0,-3854 z"
+         id="path22"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath98"><path
+         d="m 0,0 5950,0 0,3922 L 0,3922 0,0 Z m 0,3922 5950,0 0,1 -5950,0 0,-1 z m 0,1 2209,0 0,1 -2209,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2213,0 0,1 -2213,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2217,0 0,1 -2217,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2221,0 0,1 -2221,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2225,0 0,1 -2225,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2229,0 0,1 -2229,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2233,0 0,1 -2233,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2237,0 0,1 -2237,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2241,0 0,1 -2241,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2241,0 0,1 -2241,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2237,0 0,1 -2237,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2233,0 0,1 -2233,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2229,0 0,1 -2229,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2225,0 0,1 -2225,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2221,0 0,1 -2221,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2217,0 0,1 -2217,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2213,0 0,1 -2213,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 2209,0 0,1 -2209,0 0,-1 z m 2250,0 3700,0 0,1 -3700,0 0,-1 z m -2250,1 5950,0 0,1 -5950,0 0,-1 z m 0,1 5950,0 0,4478 -5950,0 0,-4478 z"
+         id="path100"
+         inkscape:connector-curvature="0" /></clipPath></defs><g
+     id="g10"
+     inkscape:groupmode="layer"
+     inkscape:label="vbi_625"
+     transform="matrix(0.125,0,0,-0.125,-87.571875,638.69874)"><g
+       id="g12"
+       transform="matrix(1.3045828,0,0,1.3045828,-213.38312,-1110.9872)"
+       style=""><path
+         d="m 2132.25,4598.15 0,-85.05"
+         style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         id="path14"
+         inkscape:connector-curvature="0" /></g><g
+       id="g16"
+       transform="matrix(1.3045828,0,0,1.3045828,-213.38312,-1110.9872)"
+       style=""><g
+         id="g18"
+         clip-path="url(#clipPath20)"
+         style=""><path
+           d="m 2132.25,4555.63 113.4,0"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           id="path24"
+           inkscape:connector-curvature="0" /></g></g><path
+       inkscape:connector-curvature="0"
+       id="path28"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       d="m 2660.3649,4819.881 49.3132,12.3283 -49.3132,12.3283 0,-24.6566" /><path
+       inkscape:connector-curvature="0"
+       id="path30"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2660.3649,4819.881 49.3132,12.3283 -49.3132,12.3283 0,-24.6566 z" /><path
+       inkscape:connector-curvature="0"
+       id="path32"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1828.6151,4924.6651 0,73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path34"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2198.4643,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path36"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2568.3136,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path38"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2938.1628,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path40"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3308.012,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path42"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3677.8612,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path44"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4047.7105,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path46"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4417.5597,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path48"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4787.4089,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path50"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5157.2581,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path52"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5527.1073,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path54"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5896.9566,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path56"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1458.7659,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path58"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1828.6151,5035.6199 0,73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path60"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2198.4643,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path62"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2568.3136,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path64"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2938.1628,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path66"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3308.012,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path68"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3677.8612,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path70"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4047.7105,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path72"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4417.5597,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path74"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4787.4089,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path76"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5157.2581,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path78"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5527.1073,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path80"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5896.9566,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path82"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1458.7659,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path84"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 719.06744,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path86"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 719.06744,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path88"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1088.9167,4998.635 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path90"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1088.9167,5109.5897 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path92"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2568.3136,4074.0119 0,-110.9548" /><g
+       id="g94"
+       transform="matrix(1.3045828,0,0,1.3045828,-213.38312,-1110.9872)"
+       style=""><g
+         id="g96"
+         clip-path="url(#clipPath98)"
+         style=""><path
+           d="m 2132.25,3931.93 113.4,0"
+           style="fill:none;stroke:#000000;stroke-width:2.36249995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           id="path102"
+           inkscape:connector-curvature="0" /></g></g><path
+       inkscape:connector-curvature="0"
+       id="path106"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       d="m 2660.365,4006.2129 49.3132,12.3283 -49.3132,12.3283 0,-24.6566" /><path
+       inkscape:connector-curvature="0"
+       id="path108"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2660.365,4006.2129 49.3132,12.3283 -49.3132,12.3283 0,-24.6566 z" /><path
+       inkscape:connector-curvature="0"
+       id="path110"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6266.806,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path112"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5896.9567,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path114"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5527.1075,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path116"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5157.2583,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path118"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4787.409,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path120"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4417.5598,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path122"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4047.7106,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path124"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3677.8613,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path126"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3308.0121,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path128"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2938.1629,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path130"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2568.3136,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path132"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2198.4644,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path134"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1828.6152,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path136"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1458.7659,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path138"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6266.806,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path140"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5896.9567,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path142"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5527.1075,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path144"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5157.2583,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path146"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4787.409,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path148"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4417.5598,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path150"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4047.7106,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path152"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3677.8613,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path154"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 3308.0121,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path156"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2938.1629,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path158"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2568.3136,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path160"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 2198.4644,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path162"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1828.6152,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path164"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1458.7659,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path166"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 719.06746,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path168"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 719.06746,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path170"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1088.9167,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path172"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1088.9167,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path174"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1144.3876,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+       inkscape:connector-curvature="0"
+       id="path176"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1070.4242,4739.7407 18.4925,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path178"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 700.575,4739.7407 18.49246,0 0,-110.9548 36.98492,0 0,110.9548 18.49247,0" /><path
+       inkscape:connector-curvature="0"
+       id="path180"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 809.886,4739.7407 3.28754,0" /><path
+       inkscape:connector-curvature="0"
+       id="path182"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 809.886,4739.7407 3.28754,0" /><path
+       inkscape:connector-curvature="0"
+       id="path184"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 774.54485,4684.2698 18.49246,0 0,110.9548 -18.49246,0 0,-110.9548 z" /><path
+       inkscape:connector-curvature="0"
+       id="path186"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 793.03731,4739.7407 18.49246,0 18.49246,73.9698 18.49246,-36.9849 18.49246,92.4688 18.49247,-55.4839 18.49246,18.499 18.49246,-36.9849 18.49246,55.4708 18.49246,-73.9698 18.49246,55.4839 18.49247,-73.9699 18.49241,110.9548 18.4925,-92.4688 18.4925,55.4839 18.4924,-55.4839 0,-36.9849" /><path
+       inkscape:connector-curvature="0"
+       id="path188"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1162.8865,4739.7407 18.486,0 0,92.4688 18.499,-18.499 18.4859,36.9849 18.499,-36.9849 18.4859,36.9849 18.499,-55.4708 18.4859,55.4708 18.499,-18.4859 18.486,55.4708 18.499,-55.4708 18.4859,18.4859 18.499,36.9849 18.4859,-73.9698 18.499,36.9849 18.4859,-55.4708 0,-55.4839 18.499,0 0,-110.9548 36.985,0 0,110.9548 18.4859,0 0,55.4839 18.499,36.9849 18.4859,-36.9849 18.499,55.4708 18.4859,-18.4859 18.499,55.4708 18.486,-18.4859 0,-129.4537 18.4989,0 0,-110.9548 18.486,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 147.9397,0 0,110.9548 36.985,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 147.9397,0 0,110.9548 36.9849,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.486,0 0,110.9548 166.4386,0 0,-110.9548 18.486,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 18.4859,0 0,110.9548 166.4387,0 0,-110.9548 36.9849,0 0,110.9548 332.8643,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path190"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 700.575,3926.0723 18.49246,0 0,-110.9547 36.98492,0 0,110.9547 18.49247,0" /><path
+       inkscape:connector-curvature="0"
+       id="path192"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 774.54485,3870.6015 18.49246,0 0,110.9547 -18.49246,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path194"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 793.03731,3926.0723 18.49246,0 0,92.4689 18.49246,-36.985 18.49246,73.9699 18.49246,-73.9699 18.49247,73.9699 18.49246,-36.9849 18.49246,18.4859 18.49246,-73.9698 18.49246,55.4839 18.49246,-18.499 18.49247,36.9849 18.49241,-73.9698 18.4925,92.4688 18.4925,-92.4688 18.4924,55.4839 0,-92.4689" /><path
+       inkscape:connector-curvature="0"
+       id="path196"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1070.4242,3926.0723 18.4925,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path198"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1144.3876,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path200"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 1162.8865,3926.0723 18.486,0 0,55.4839 18.499,92.4558 18.4859,-55.4708 36.9849,36.9849 18.499,-55.4839 18.4859,18.499 18.499,-36.985 18.486,55.4709 18.499,-18.4859 18.4859,-36.985 18.499,18.486 18.4859,36.9849 18.499,-36.9849 18.4859,36.9849 0,-110.9548 18.499,0 0,-110.9547 18.486,0 0,110.9547 166.4386,0 0,-110.9547 18.486,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 147.9397,0 0,110.9547 36.985,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 147.9397,0 0,110.9547 36.9849,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 166.4387,0 0,-110.9547 18.486,0 0,110.9547 166.4386,0 0,-110.9547 18.486,0 0,110.9547 166.4387,0 0,-110.9547 18.4859,0 0,110.9547 351.3633,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path202"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5453.1376,4795.2246 -36.9849,-110.9548" /><path
+       inkscape:connector-curvature="0"
+       id="path204"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5434.6387,4739.7407 92.4688,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path206"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5582.5784,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+       inkscape:connector-curvature="0"
+       id="path208"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5601.0773,4739.7407 295.8794,0 0,-110.9548 36.9849,0 0,110.9548 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path210"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5952.4276,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+       inkscape:connector-curvature="0"
+       id="path212"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5970.9266,4739.7407 129.4407,0 0,147.9396 18.499,-36.9849 18.4859,36.9849 18.499,-36.9849 18.4859,18.499 18.499,-36.9849 18.4859,36.9849 18.499,-36.9849 18.486,-18.499 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path214"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4842.8799,4684.2698 18.4924,0 0,110.9548 -18.4924,0 0,-110.9548 z" /><path
+       inkscape:connector-curvature="0"
+       id="path216"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4861.3789,4739.7407 295.8794,0 0,-110.9548 36.9849,0 0,110.9548 18.4859,0" /><path
+       inkscape:connector-curvature="0"
+       id="path218"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5212.7291,4684.2698 18.4925,0 0,110.9548 -18.4925,0 0,-110.9548 z" /><path
+       inkscape:connector-curvature="0"
+       id="path220"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5231.2281,4739.7407 166.4256,0" /><path
+       inkscape:connector-curvature="0"
+       id="path222"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5416.1527,4795.2246 -36.9849,-110.9548" /><path
+       inkscape:connector-curvature="0"
+       id="path224"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4473.0307,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path226"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4491.5296,3926.0723 295.8794,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path228"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4842.8799,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path230"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 4861.3789,3926.0723 295.8794,0 0,-110.9547 36.9849,0 0,110.9547 18.4859,0" /><path
+       inkscape:connector-curvature="0"
+       id="path232"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5212.7291,3870.6015 18.4925,0 0,110.9547 -18.4925,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path234"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5416.1527,3981.5562 -36.9849,-110.9547" /><path
+       inkscape:connector-curvature="0"
+       id="path236"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5231.2281,3926.0723 166.4256,0" /><path
+       inkscape:connector-curvature="0"
+       id="path238"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5453.1376,3981.5562 -36.9849,-110.9547" /><path
+       inkscape:connector-curvature="0"
+       id="path240"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5434.6387,3926.0723 92.4688,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path242"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5582.5784,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path244"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5601.0773,3926.0723 295.8794,0 0,-110.9547 36.9849,0 0,110.9547 18.486,0" /><path
+       inkscape:connector-curvature="0"
+       id="path246"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5952.4276,3870.6015 18.4924,0 0,110.9547 -18.4924,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path248"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 5970.9266,3926.0723 18.4859,0 0,73.9699 18.499,36.9849 18.4859,-36.9849 18.499,36.9849 18.486,-18.4859 18.4989,0 18.486,-36.985 18.499,55.4709 18.4859,-18.4859 0,36.9849 18.499,-18.499 18.4859,18.499 18.499,-36.9849 18.4859,18.4859 18.499,-55.4709 18.486,18.486 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path250"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6248.307,4739.7407 18.499,0 0,-110.9548 36.9849,0 0,110.9548 18.4859,0" /><path
+       inkscape:connector-curvature="0"
+       id="path252"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6248.307,3926.0723 18.499,0 0,-110.9547 36.9849,0 0,110.9547 18.4859,0" /><path
+       inkscape:connector-curvature="0"
+       id="path254"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6322.2768,3870.6015 18.4925,0 0,110.9547 -18.4925,0 0,-110.9547 z" /><path
+       inkscape:connector-curvature="0"
+       id="path256"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6322.2768,4684.2698 18.4925,0 0,110.9548 -18.4925,0 0,-110.9548 z" /><path
+       inkscape:connector-curvature="0"
+       id="path258"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6340.7758,4739.7407 18.4859,0 0,55.4839 18.499,55.4708 18.486,-92.4558 18.4989,55.4709 18.486,0 18.499,55.4839 18.4859,-73.9698 18.499,36.9849 18.4859,-36.9849 36.985,73.9698 18.4989,-36.9849 18.486,36.9849 18.499,-55.4839 18.4859,36.9849 0,-110.9547 18.499,0" /><path
+       inkscape:connector-curvature="0"
+       id="path260"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6340.7758,3926.0723 18.4859,0 0,129.4538 18.499,-18.499 18.486,18.499 18.4989,-36.9849 18.486,18.4859 18.499,-36.9849 18.4859,18.499 18.499,-18.499 18.4859,55.4839 18.499,-18.499 18.486,36.9849 18.4989,-73.9698 18.486,55.4839 18.499,-55.4839 18.4859,36.9849 0,-110.9548 18.499,0" /><path
+       inkscape:connector-curvature="0"
+       id="path262"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6636.6552,4184.9668 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path264"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6636.6552,4295.9216 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path266"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6266.806,4998.6351 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path268"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6266.806,5109.5899 0,-73.9699" /><path
+       inkscape:connector-curvature="0"
+       id="path270"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6636.6552,4998.6351 0,-73.9698" /><path
+       inkscape:connector-curvature="0"
+       id="path272"
+       style="fill:none;stroke:#000000;stroke-width:3.08207679;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       d="m 6636.6552,5109.5899 0,-73.9699" /><text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text276"
+       x="3550.4165"
+       y="-4462.3472"><tspan
+         x="3550.4165 3591.5437 3628.5286 3649.0923 3669.656 3690.2195 3706.6409 3747.7681 3764.1895"
+         y="-4462.3472"
+         sodipodi:role="line"
+         id="tspan278">1st field</tspan><tspan
+         x="2732.6792 3823.7344 4193.5835 4581.9253 4951.7744 5321.6235 3472.3777 3102.5283 2321.7029 2362.8303 2403.9575 1951.8538 1992.981 2034.1083 1582.0045 1623.132 1664.259 5670.9062 5712.0337"
+         y="-4943.1509"
+         sodipodi:role="line"
+         id="tspan280">1456783231231131022</tspan><tspan
+         x="2732.6726 3823.7278 4193.5771 4581.9189 4951.7681 5321.6172 3472.3711 3102.522 2321.6965 2362.8237 2403.9509 1951.8473 1992.9745 2034.1018 1581.998 1623.1254 1664.2524 5670.8999 5712.0269"
+         y="-5054.1064"
+         sodipodi:role="line"
+         id="tspan282">1456783262562462322</tspan><tspan
+         x="842.29962 883.42694 924.55408"
+         y="-4943.1509"
+         sodipodi:role="line"
+         id="tspan284">308</tspan><tspan
+         x="842.29962 883.42694 924.55408"
+         y="-5054.1064"
+         sodipodi:role="line"
+         id="tspan286">621</tspan><tspan
+         x="1212.1489 1253.276 1294.4033"
+         y="-4943.1509"
+         sodipodi:role="line"
+         id="tspan288">309</tspan><tspan
+         x="1212.1489 1253.276 1294.4033"
+         y="-5054.1064"
+         sodipodi:role="line"
+         id="tspan290">622</tspan><tspan
+         x="3538.0635 3579.1907 3620.3179 3661.4451 3682.0088 3702.5723 3718.9937 3760.1208 3776.5422"
+         y="-3648.6792"
+         sodipodi:role="line"
+         id="tspan292">2nd field</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:61.64153671px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text294"
+       x="2734.751"
+       y="-4037.021"><tspan
+         x="2734.751 2755.2776 2789.5503"
+         y="-4037.021"
+         sodipodi:role="line"
+         id="tspan296">(1)</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text298"
+       x="4951.772"
+       y="-4129.4834"><tspan
+         x="4951.772 4581.9229 4212.0737 3842.2244 3490.8677 3102.5259 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan300">765432313312311</tspan><tspan
+         x="6020.1929 6061.3198 6102.4473 5650.3433 5691.4707 5732.5981 5280.4941 5321.6216 5362.7485 4910.645 4951.7725 4992.8994 4540.7959 4581.9229 4623.0503 4170.9468 4212.0737 4253.2012 3801.0974 3842.2246 3883.3518 3449.7405 3490.8677 3531.9951 3061.3989 3102.5261 3143.6533 2691.5496 2732.677 2773.8042 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan302">336335321320319318317316315314313312311</tspan><tspan
+         x="2732.6765 5321.6211 5670.9062 5712.0337 6040.7554 6081.8828 842.30634 883.43323 924.56055"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan304">182223309</tspan><tspan
+         x="842.30634 883.43323 924.56055"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan306">309</tspan><tspan
+         x="1212.1553 1253.2826 1294.4099"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan308">310</tspan><tspan
+         x="1212.1553 1253.2826 1294.4099"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan310">310</tspan><tspan
+         x="6410.605 6451.7319"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan312">24</tspan><tspan
+         x="6390.041 6431.1685 6472.2954"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan314">337</tspan><tspan
+         x="6040.7559 6081.8833"
+         y="-4943.1504"
+         sodipodi:role="line"
+         id="tspan316">23</tspan><tspan
+         x="6040.7559 6081.8833"
+         y="-5054.106"
+         sodipodi:role="line"
+         id="tspan318">23</tspan><tspan
+         x="6410.605 6451.7324"
+         y="-4943.1504"
+         sodipodi:role="line"
+         id="tspan320">24</tspan><tspan
+         x="6410.605 6451.7324"
+         y="-5054.106"
+         sodipodi:role="line"
+         id="tspan322">24</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3671"
+       x="3550.4165 3591.5437 3628.5286 3649.0923 3669.656 3690.2195 3706.6409 3747.7681 3764.1895"
+       y="-4462.3472"><tspan
+         x="3550.4165 3591.5437 3628.5286 3649.0923 3669.656 3690.2195 3706.6409 3747.7681 3764.1895"
+         y="-4462.3472"
+         sodipodi:role="line"
+         id="tspan3673">1st field</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3675"
+       x="2732.6792 3823.7344 4193.5835 4581.9253 4951.7744 5321.6235 3472.3777 3102.5283 2321.7029 2362.8303 2403.9575 1951.8538 1992.981 2034.1083 1582.0045 1623.132 1664.259 5670.9062 5712.0337"
+       y="-4943.1509"><tspan
+         x="2732.6792 3823.7344 4193.5835 4581.9253 4951.7744 5321.6235 3472.3777 3102.5283 2321.7029 2362.8303 2403.9575 1951.8538 1992.981 2034.1083 1582.0045 1623.132 1664.259 5670.9062 5712.0337"
+         y="-4943.1509"
+         sodipodi:role="line"
+         id="tspan3677">1456783231231131022</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3679"
+       x="2732.6726 3823.7278 4193.5771 4581.9189 4951.7681 5321.6172 3472.3711 3102.522 2321.6965 2362.8237 2403.9509 1951.8473 1992.9745 2034.1018 1581.998 1623.1254 1664.2524 5670.8999 5712.0269"
+       y="-5054.1064"><tspan
+         x="2732.6726 3823.7278 4193.5771 4581.9189 4951.7681 5321.6172 3472.3711 3102.522 2321.6965 2362.8237 2403.9509 1951.8473 1992.9745 2034.1018 1581.998 1623.1254 1664.2524 5670.8999 5712.0269"
+         y="-5054.1064"
+         sodipodi:role="line"
+         id="tspan3681">1456783262562462322</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3683"
+       x="842.29962 883.42694 924.55408"
+       y="-4943.1509"><tspan
+         x="842.29962 883.42694 924.55408"
+         y="-4943.1509"
+         sodipodi:role="line"
+         id="tspan3685">308</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3687"
+       x="842.29962 883.42694 924.55408"
+       y="-5054.1064"><tspan
+         x="842.29962 883.42694 924.55408"
+         y="-5054.1064"
+         sodipodi:role="line"
+         id="tspan3689">621</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3691"
+       x="1212.1489 1253.276 1294.4033"
+       y="-4943.1509"><tspan
+         x="1212.1489 1253.276 1294.4033"
+         y="-4943.1509"
+         sodipodi:role="line"
+         id="tspan3693">309</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3695"
+       x="1212.1489 1253.276 1294.4033"
+       y="-5054.1064"><tspan
+         x="1212.1489 1253.276 1294.4033"
+         y="-5054.1064"
+         sodipodi:role="line"
+         id="tspan3697">622</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text3699"
+       x="3538.0635 3579.1907 3620.3179 3661.4451 3682.0088 3702.5723 3718.9937 3760.1208 3776.5422"
+       y="-3648.6792"><tspan
+         x="3538.0635 3579.1907 3620.3179 3661.4451 3682.0088 3702.5723 3718.9937 3760.1208 3776.5422"
+         y="-3648.6792"
+         sodipodi:role="line"
+         id="tspan3701">2nd field</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4083"
+       x="4951.772 4581.9229 4212.0737 3842.2244 3490.8677 3102.5259 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+       y="-4129.4834"><tspan
+         x="4951.772 4581.9229 4212.0737 3842.2244 3490.8677 3102.5259 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan4085">765432313312311</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4087"
+       x="6020.1929 6061.3198 6102.4473 5650.3433 5691.4707 5732.5981 5280.4941 5321.6216 5362.7485 4910.645 4951.7725 4992.8994 4540.7959 4581.9229 4623.0503 4170.9468 4212.0737 4253.2012 3801.0974 3842.2246 3883.3518 3449.7405 3490.8677 3531.9951 3061.3989 3102.5261 3143.6533 2691.5496 2732.677 2773.8042 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+       y="-4240.4385"><tspan
+         x="6020.1929 6061.3198 6102.4473 5650.3433 5691.4707 5732.5981 5280.4941 5321.6216 5362.7485 4910.645 4951.7725 4992.8994 4540.7959 4581.9229 4623.0503 4170.9468 4212.0737 4253.2012 3801.0974 3842.2246 3883.3518 3449.7405 3490.8677 3531.9951 3061.3989 3102.5261 3143.6533 2691.5496 2732.677 2773.8042 2321.7004 2362.8276 2403.9551 1951.8512 1992.9785 2034.1057 1582.0022 1623.1293 1664.2563"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan4089">336335321320319318317316315314313312311</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4091"
+       x="2732.6765 5321.6211 5670.9062 5712.0337 6040.7554 6081.8828 842.30634 883.43323 924.56055"
+       y="-4129.4834"><tspan
+         x="2732.6765 5321.6211 5670.9062 5712.0337 6040.7554 6081.8828 842.30634 883.43323 924.56055"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan4093">182223309</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4095"
+       x="842.30634 883.43323 924.56055"
+       y="-4240.4385"><tspan
+         x="842.30634 883.43323 924.56055"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan4097">309</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4099"
+       x="1212.1553 1253.2826 1294.4099"
+       y="-4129.4834"><tspan
+         x="1212.1553 1253.2826 1294.4099"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan4101">310</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4103"
+       x="1212.1553 1253.2826 1294.4099"
+       y="-4240.4385"><tspan
+         x="1212.1553 1253.2826 1294.4099"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan4105">310</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4107"
+       x="6410.605 6451.7319"
+       y="-4129.4834"><tspan
+         x="6410.605 6451.7319"
+         y="-4129.4834"
+         sodipodi:role="line"
+         id="tspan4109">24</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4111"
+       x="6390.041 6431.1685 6472.2954"
+       y="-4240.4385"><tspan
+         x="6390.041 6431.1685 6472.2954"
+         y="-4240.4385"
+         sodipodi:role="line"
+         id="tspan4113">337</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4115"
+       x="6040.7559 6081.8833"
+       y="-4943.1504"><tspan
+         x="6040.7559 6081.8833"
+         y="-4943.1504"
+         sodipodi:role="line"
+         id="tspan4117">23</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4119"
+       x="6040.7559 6081.8833"
+       y="-5054.106"><tspan
+         x="6040.7559 6081.8833"
+         y="-5054.106"
+         sodipodi:role="line"
+         id="tspan4121">23</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4123"
+       x="6410.605 6451.7324"
+       y="-4943.1504"><tspan
+         x="6410.605 6451.7324"
+         y="-4943.1504"
+         sodipodi:role="line"
+         id="tspan4125">24</tspan></text>
+<text
+       transform="scale(1,-1)"
+       style="font-variant:normal;font-weight:normal;font-size:73.96984863px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       id="text4127"
+       x="6410.605 6451.7324"
+       y="-5054.106"><tspan
+         x="6410.605 6451.7324"
+         y="-5054.106"
+         sodipodi:role="line"
+         id="tspan4129">24</tspan></text>
+</g></svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vbi_hsync.svg linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vbi_hsync.svg
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vbi_hsync.svg	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vbi_hsync.svg	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   xml:space="preserve"
+   width="192.39857mm"
+   height="146.83536mm"
+   viewBox="0 0 681.72724 520.28277"
+   sodipodi:docname="vbi_hsync.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="997"
+     id="namedview4"
+     showgrid="false"
+     inkscape:zoom="1.5350601"
+     inkscape:cx="131.95463"
+     inkscape:cy="428.88132"
+     inkscape:window-x="1920"
+     inkscape:window-y="30"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="g10"
+     units="mm"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" /><metadata
+     id="metadata8"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs6"><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath30"><path
+         d="m 0,0 0,1163 1544,0 L 1544,0 0,0 Z m 187.184,836.05 0,-19.278 48.517,0 -38.556,9.639 38.556,9.639 -48.517,0 z m 689.189,-19.278 0,19.278 -48.516,0 38.556,-9.639 -38.556,-9.639 48.516,0 z"
+         id="path32"
+         inkscape:connector-curvature="0"
+         style="clip-rule:evenodd" /></clipPath><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath52"><path
+         d="m 0,0 0,1163 1544,0 L 1544,0 0,0 Z m 804.08,79.3887 0,19.2778 -48.516,0 38.556,-9.6389 -38.556,-9.6389 48.516,0 z m -703.647,19.2778 0,-19.2778 48.517,0 -38.556,9.6389 38.556,9.6389 -48.517,0 z"
+         id="path54"
+         inkscape:connector-curvature="0"
+         style="clip-rule:evenodd" /></clipPath><clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath94"><path
+         d="m 0,0 0,1163 1544,0 L 1544,0 0,0 Z m 471.535,195.057 0,19.278 -48.516,0 38.555,-9.639 -38.555,-9.639 48.516,0 z m -284.351,19.278 0,-19.278 48.517,0 -38.556,9.639 38.556,9.639 -48.517,0 z"
+         id="path96"
+         inkscape:connector-curvature="0"
+         style="clip-rule:evenodd" /></clipPath></defs><g
+     id="g10"
+     inkscape:groupmode="layer"
+     inkscape:label="vbi_hsync"
+     transform="matrix(1.25,0,0,-1.25,-0.3625824,520.79867)"><g
+       id="g14"
+       transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+       style=""><path
+         inkscape:connector-curvature="0"
+         id="path16"
+         style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="M 32.9604,580.617 4.04346,493.866" /><path
+         inkscape:connector-curvature="0"
+         id="path18"
+         style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 192.004,855.328 0,-665.091" /><path
+         inkscape:connector-curvature="0"
+         id="path20"
+         style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 466.715,392.656 0,-202.419" /><path
+         inkscape:connector-curvature="0"
+         id="path22"
+         style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 799.261,508.324 0,-433.7549" /><path
+         inkscape:connector-curvature="0"
+         id="path24"
+         style="fill:none;stroke:#000000;stroke-width:4.81949997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 857.095,537.241 231.335,0" /></g><g
+       id="g26"
+       transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+       style=""><g
+         clip-path="url(#clipPath30)"
+         id="g28"
+         style=""><path
+           inkscape:connector-curvature="0"
+           id="path34"
+           style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="m 871.553,826.411 -679.549,0" /></g></g><g
+       id="g36"
+       transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+       style=""><path
+         inkscape:connector-curvature="0"
+         id="path38"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 827.857,816.772 38.556,9.639 -38.556,9.639 0,-19.278" /><path
+         inkscape:connector-curvature="0"
+         id="path40"
+         style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 827.857,816.772 38.556,9.639 -38.556,9.639 0,-19.278 z" /><path
+         inkscape:connector-curvature="0"
+         id="path42"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+         d="m 235.701,836.05 -38.556,-9.639 38.556,-9.639 0,19.278" /><path
+         inkscape:connector-curvature="0"
+         id="path44"
+         style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 235.701,836.05 -38.556,-9.639 38.556,-9.639 0,19.278 z" /><path
+         inkscape:connector-curvature="0"
+         id="path46"
+         style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+         d="m 1073.97,493.866 28.92,86.751" /></g><g
+       id="g48"
+       transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+       style=""><g
+         clip-path="url(#clipPath52)"
+         id="g50"
+         style=""><path
+           inkscape:connector-curvature="0"
+           id="path56"
+           style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="m 105.253,89.0276 694.008,0" /></g></g><path
+       d="m 52.91205,34.475403 -13.891817,-3.472918 13.891817,-3.472918 0,6.945836"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path60"
+       inkscape:connector-curvature="0" /><path
+       d="m 52.91205,34.475403 -13.891817,-3.472918 13.891817,-3.472918 0,6.945836 z"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path62"
+       inkscape:connector-curvature="0" /><path
+       d="m 271.4765,27.529567 13.89182,3.472918 -13.89182,3.472918 0,-6.945836"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path64"
+       inkscape:connector-curvature="0" /><path
+       d="m 271.4765,27.529567 13.89182,3.472918 -13.89182,3.472918 0,-6.945836 z"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path66"
+       inkscape:connector-curvature="0" /><path
+       d="m 5.9113292,192.49483 31.2565888,0 0,-10.41887 26.046978,0 10.418863,-93.769765 88.560511,0 10.41887,93.769765 10.41886,0"
+       style="fill:none;stroke:#000000;stroke-width:1.73647714;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path68"
+       inkscape:connector-curvature="0" /><path
+       d="m 162.19427,88.306195 260.47086,0"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path70"
+       inkscape:connector-curvature="0" /><path
+       d="m 37.167918,182.07596 0,-156.282907"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path72"
+       inkscape:connector-curvature="0" /><path
+       d="m 235.12632,182.07596 52.09431,0 0,10.41887 20.83773,0 10.41886,208.3769 83.35162,0"
+       style="fill:none;stroke:#000000;stroke-width:1.73647714;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path74"
+       inkscape:connector-curvature="0" /><path
+       d="m 391.4089,192.49483 31.25623,0"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path76"
+       inkscape:connector-curvature="0" /><path
+       d="m 401.82884,400.87173 20.83629,0"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path78"
+       inkscape:connector-curvature="0" /><path
+       d="m 328.89608,192.49483 10.41887,208.3769"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path80"
+       inkscape:connector-curvature="0" /><path
+       d="m 349.73381,192.49483 10.41886,208.3769"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path82"
+       inkscape:connector-curvature="0" /><path
+       d="m 370.57262,192.49483 10.41634,208.3769"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path84"
+       inkscape:connector-curvature="0" /><path
+       d="m 396.61887,385.24541 10.41995,31.25623"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path86"
+       inkscape:connector-curvature="0" /><path
+       d="m 183.032,135.19126 52.09432,0 0,93.76977 -52.09432,0 0,-93.76977 z"
+       style="fill:none;stroke:#000000;stroke-width:1.73647714;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path88"
+       inkscape:connector-curvature="0" /><g
+       id="g90"
+       transform="matrix(0.36030235,0,0,0.36030235,-0.75498483,-1.0743684)"
+       style=""><g
+         clip-path="url(#clipPath94)"
+         id="g92"
+         style=""><path
+           inkscape:connector-curvature="0"
+           id="path98"
+           style="fill:none;stroke:#000000;stroke-width:2.40974998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+           d="m 192.004,204.696 274.711,0" /></g></g><path
+       d="m 84.168639,76.151036 -13.891817,-3.472955 13.891817,-3.472954 0,6.945909"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path102"
+       inkscape:connector-curvature="0" /><path
+       d="m 84.168639,76.151036 -13.891817,-3.472955 13.891817,-3.472954 0,6.945909 z"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path104"
+       inkscape:connector-curvature="0" /><path
+       d="m 151.65975,69.205127 13.89146,3.472954 -13.89146,3.472955 0,-6.945909"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path106"
+       inkscape:connector-curvature="0" /><path
+       d="m 151.65975,69.205127 13.89146,3.472954 -13.89146,3.472955 0,-6.945909 z"
+       style="fill:none;stroke:#000000;stroke-width:0.86823857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
+       id="path108"
+       inkscape:connector-curvature="0" /><text
+       id="text112"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="438.29504"
+       y="-187.28558"><tspan
+         id="tspan114"
+         sodipodi:role="line"
+         y="-187.28558"
+         x="438.29504 452.19382 456.81979 468.40555 478.82443 489.24329 495.03619 506.62195 518.2077 528.62659 540.21234">Black Level</tspan><tspan
+         id="tspan116"
+         sodipodi:role="line"
+         y="-83.096947"
+         x="438.29504 452.19382 462.61267 474.19846 484.61731 490.41019 501.99597 513.58173 524.00061 535.58636">Sync Level</tspan><tspan
+         id="tspan118"
+         sodipodi:role="line"
+         y="-395.66284"
+         x="438.29504 457.96585 469.55164 474.17761 479.97049 491.55627 497.34915 508.93494 520.52069 530.93958 542.52533">White Level</tspan></text>
+<text
+       id="text120"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="159.88258"
+       y="-270.63647"><tspan
+         id="tspan122"
+         sodipodi:role="line"
+         y="-270.63647"
+         x="159.88258 172.61443 179.55339 186.49236 198.07812 209.66391">offset</tspan></text>
+<text
+       id="text124"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="46.973549"
+       y="-46.630745"><tspan
+         id="tspan126"
+         sodipodi:role="line"
+         y="-46.630745"
+         x="46.973549 58.559322 63.185299 74.771072 86.35685 92.149734 102.5686 112.98746 124.57324 134.9921 146.57788 153.51685 159.30972 165.10262 176.68839 188.27417 192.90015 203.319">Line synchr. pulse</tspan><tspan
+         id="tspan128"
+         sodipodi:role="line"
+         y="-4.9552913"
+         x="100.80776 112.39354 117.01952 128.60529 140.19107 145.98395 157.56973 162.19569 173.78148 185.36726 195.78612 200.41209 211.99788">Line blanking</tspan></text>
+<text
+       id="text3473"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="46.973549 58.559322 63.185299 74.771072 86.35685 92.149734 102.5686 112.98746 124.57324 134.9921 146.57788 153.51685 159.30972 165.10262 176.68839 188.27417 192.90015 203.319"
+       y="-46.630745"><tspan
+         id="tspan3475"
+         sodipodi:role="line"
+         y="-46.630745"
+         x="46.973549 58.559322 63.185299 74.771072 86.35685 92.149734 102.5686 112.98746 124.57324 134.9921 146.57788 153.51685 159.30972 165.10262 176.68839 188.27417 192.90015 203.319">Line synchr. pulse</tspan></text>
+<text
+       id="text3477"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="100.80776 112.39354 117.01952 128.60529 140.19107 145.98395 157.56973 162.19569 173.78148 185.36726 195.78612 200.41209 211.99788"
+       y="-4.9552913"><tspan
+         id="tspan3479"
+         sodipodi:role="line"
+         y="-4.9552913"
+         x="100.80776 112.39354 117.01952 128.60529 140.19107 145.98395 157.56973 162.19569 173.78148 185.36726 195.78612 200.41209 211.99788">Line blanking</tspan></text>
+<text
+       id="text3607"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="438.29504 452.19382 456.81979 468.40555 478.82443 489.24329 495.03619 506.62195 518.2077 528.62659 540.21234"
+       y="-187.28558"><tspan
+         id="tspan3609"
+         sodipodi:role="line"
+         y="-187.28558"
+         x="438.29504 452.19382 456.81979 468.40555 478.82443 489.24329 495.03619 506.62195 518.2077 528.62659 540.21234">Black Level</tspan></text>
+<text
+       id="text3611"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="438.29504 452.19382 462.61267 474.19846 484.61731 490.41019 501.99597 513.58173 524.00061 535.58636"
+       y="-83.096947"><tspan
+         id="tspan3613"
+         sodipodi:role="line"
+         y="-83.096947"
+         x="438.29504 452.19382 462.61267 474.19846 484.61731 490.41019 501.99597 513.58173 524.00061 535.58636">Sync Level</tspan></text>
+<text
+       id="text3615"
+       style="font-variant:normal;font-weight:normal;font-size:20.83772659px;font-family:sans-serif;-inkscape-font-specification:sans-serif;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-style:normal;font-stretch:normal;"
+       transform="scale(1,-1)"
+       x="438.29504 457.96585 469.55164 474.17761 479.97049 491.55627 497.34915 508.93494 520.52069 530.93958 542.52533"
+       y="-395.66284"><tspan
+         id="tspan3617"
+         sodipodi:role="line"
+         y="-395.66284"
+         x="438.29504 457.96585 469.55164 474.17761 479.97049 491.55627 497.34915 508.93494 520.52069 530.93958 542.52533">White Level</tspan></text>
+</g></svg>
\ No newline at end of file
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vidioc-g-dv-timings.rst	2017-02-12 16:03:20.000000000 -0500
@@ -270,3 +270,14 @@ EBUSY
       - Some formats like SMPTE-125M have an interlaced signal with a odd
 	total height. For these formats, if this flag is set, the first
 	field has the extra line. Else, it is the second field.
+    * - ``V4L2_DV_FL_HAS_PICTURE_ASPECT``
+      - If set, then the picture_aspect field is valid. Otherwise assume that
+        the pixels are square, so the picture aspect ratio is the same as the
+	width to height ratio.
+    * - ``V4L2_DV_FL_HAS_CEA861_VIC``
+      - If set, then the cea861_vic field is valid and contains the Video
+        Identification Code as per the CEA-861 standard.
+    * - ``V4L2_DV_FL_HAS_HDMI_VIC``
+      - If set, then the hdmi_vic field is valid and contains the Video
+        Identification Code as per the HDMI standard (HDMI Vendor Specific
+	InfoFrame).
Binary files linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vidioc-g-selection_files/constraints.png and linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vidioc-g-selection_files/constraints.png differ
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vidioc-g-selection.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vidioc-g-selection.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vidioc-g-selection.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vidioc-g-selection.rst	2017-02-12 16:03:20.000000000 -0500
@@ -129,8 +129,8 @@ Selection targets and flags are document
 
 .. _sel-const-adjust:
 
-.. figure::  vidioc-g-selection_files/constraints.*
-    :alt:    constraints.png
+.. figure::  constraints.*
+    :alt:    constraints.pdf / constraints.svg
     :align:  center
 
     Size adjustments with constraint flags.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vidioc-g-tuner.rst linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vidioc-g-tuner.rst
--- linux-libre-4.9-gnu/Documentation/media/uapi/v4l/vidioc-g-tuner.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/uapi/v4l/vidioc-g-tuner.rst	2017-02-12 16:03:20.000000000 -0500
@@ -201,10 +201,10 @@ To change the radio frequency the
     * - ``V4L2_TUNER_SDR``
       - 4
       - Tuner controls the A/D and/or D/A block of a
-	Sofware Digital Radio (SDR)
+	Software Digital Radio (SDR)
     * - ``V4L2_TUNER_RF``
       - 5
-      - Tuner controls the RF part of a Sofware Digital Radio (SDR)
+      - Tuner controls the RF part of a Software Digital Radio (SDR)
 
 
 .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/au0828-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/au0828-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/au0828-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/au0828-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,11 +1,13 @@
 AU0828 cards list
 =================
 
-.. code-block:: none
-
-	  0 -> Unknown board                            (au0828)
-	  1 -> Hauppauge HVR950Q                        (au0828)        [2040:7200,2040:7210,2040:7217,2040:721b,2040:721e,2040:721f,2040:7280,0fd9:0008,2040:7260,2040:7213,2040:7270]
-	  2 -> Hauppauge HVR850                         (au0828)        [2040:7240]
-	  3 -> DViCO FusionHDTV USB                     (au0828)        [0fe9:d620]
-	  4 -> Hauppauge HVR950Q rev xxF8               (au0828)        [2040:7201,2040:7211,2040:7281]
-	  5 -> Hauppauge Woodbury                       (au0828)        [05e1:0480,2040:8200]
+=========== ========================== =======================================================================================================================
+Card number Card name                  USB IDs
+=========== ========================== =======================================================================================================================
+0           Unknown board
+1           Hauppauge HVR950Q          2040:7200, 2040:7210, 2040:7217, 2040:721b, 2040:721e, 2040:721f, 2040:7280, 0fd9:0008, 2040:7260, 2040:7213, 2040:7270
+2           Hauppauge HVR850           2040:7240
+3           DViCO FusionHDTV USB       0fe9:d620
+4           Hauppauge HVR950Q rev xxF8 2040:7201, 2040:7211, 2040:7281
+5           Hauppauge Woodbury         05e1:0480, 2040:8200
+=========== ========================== =======================================================================================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/bttv-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/bttv-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/bttv-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/bttv-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,172 +1,174 @@
 BTTV cards list
 ===============
 
-.. code-block:: none
-
-	  0 ->  *** UNKNOWN/GENERIC ***
-	  1 -> MIRO PCTV
-	  2 -> Hauppauge (bt848)
-	  3 -> STB, Gateway P/N 6000699 (bt848)
-	  4 -> Intel Create and Share PCI/ Smart Video Recorder III
-	  5 -> Diamond DTV2000
-	  6 -> AVerMedia TVPhone
-	  7 -> MATRIX-Vision MV-Delta
-	  8 -> Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26
-	  9 -> IMS/IXmicro TurboTV
-	 10 -> Hauppauge (bt878)                                   [0070:13eb,0070:3900,2636:10b4]
-	 11 -> MIRO PCTV pro
-	 12 -> ADS Technologies Channel Surfer TV (bt848)
-	 13 -> AVerMedia TVCapture 98                              [1461:0002,1461:0004,1461:0300]
-	 14 -> Aimslab Video Highway Xtreme (VHX)
-	 15 -> Zoltrix TV-Max                                      [a1a0:a0fc]
-	 16 -> Prolink Pixelview PlayTV (bt878)
-	 17 -> Leadtek WinView 601
-	 18 -> AVEC Intercapture
-	 19 -> Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)
-	 20 -> CEI Raffles Card
-	 21 -> Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50
-	 22 -> Askey CPH050/ Phoebe Tv Master + FM                 [14ff:3002]
-	 23 -> Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878 [14c7:0101]
-	 24 -> Askey CPH05X/06X (bt878) [many vendors]             [144f:3002,144f:3005,144f:5000,14ff:3000]
-	 25 -> Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar
-	 26 -> Hauppauge WinCam newer (bt878)
-	 27 -> Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50
-	 28 -> Terratec TerraTV+ Version 1.1 (bt878)               [153b:1127,1852:1852]
-	 29 -> Imagenation PXC200                                  [1295:200a]
-	 30 -> Lifeview FlyVideo 98 LR50                           [1f7f:1850]
-	 31 -> Formac iProTV, Formac ProTV I (bt848)
-	 32 -> Intel Create and Share PCI/ Smart Video Recorder III
-	 33 -> Terratec TerraTValue Version Bt878                  [153b:1117,153b:1118,153b:1119,153b:111a,153b:1134,153b:5018]
-	 34 -> Leadtek WinFast 2000/ WinFast 2000 XP               [107d:6606,107d:6609,6606:217d,f6ff:fff6]
-	 35 -> Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II [1851:1850,1851:a050]
-	 36 -> Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner [1852:1852]
-	 37 -> Prolink PixelView PlayTV pro
-	 38 -> Askey CPH06X TView99                                [144f:3000,144f:a005,a04f:a0fc]
-	 39 -> Pinnacle PCTV Studio/Rave                           [11bd:0012,bd11:1200,bd11:ff00,11bd:ff12]
-	 40 -> STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100 [10b4:2636,10b4:2645,121a:3060]
-	 41 -> AVerMedia TVPhone 98                                [1461:0001,1461:0003]
-	 42 -> ProVideo PV951                                      [aa0c:146c]
-	 43 -> Little OnAir TV
-	 44 -> Sigma TVII-FM
-	 45 -> MATRIX-Vision MV-Delta 2
-	 46 -> Zoltrix Genie TV/FM                                 [15b0:4000,15b0:400a,15b0:400d,15b0:4010,15b0:4016]
-	 47 -> Terratec TV/Radio+                                  [153b:1123]
-	 48 -> Askey CPH03x/ Dynalink Magic TView
-	 49 -> IODATA GV-BCTV3/PCI                                 [10fc:4020]
-	 50 -> Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP
-	 51 -> Eagle Wireless Capricorn2 (bt878A)
-	 52 -> Pinnacle PCTV Studio Pro
-	 53 -> Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS
-	 54 -> Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]
-	 55 -> Askey CPH031/ BESTBUY Easy TV
-	 56 -> Lifeview FlyVideo 98FM LR50                         [a051:41a0]
-	 57 -> GrandTec 'Grand Video Capture' (Bt848)              [4344:4142]
-	 58 -> Askey CPH060/ Phoebe TV Master Only (No FM)
-	 59 -> Askey CPH03x TV Capturer
-	 60 -> Modular Technology MM100PCTV
-	 61 -> AG Electronics GMV1                                 [15cb:0101]
-	 62 -> Askey CPH061/ BESTBUY Easy TV (bt878)
-	 63 -> ATI TV-Wonder                                       [1002:0001]
-	 64 -> ATI TV-Wonder VE                                    [1002:0003]
-	 65 -> Lifeview FlyVideo 2000S LR90
-	 66 -> Terratec TValueRadio                                [153b:1135,153b:ff3b]
-	 67 -> IODATA GV-BCTV4/PCI                                 [10fc:4050]
-	 68 -> 3Dfx VoodooTV FM (Euro)                             [10b4:2637]
-	 69 -> Active Imaging AIMMS
-	 70 -> Prolink Pixelview PV-BT878P+ (Rev.4C,8E)
-	 71 -> Lifeview FlyVideo 98EZ (capture only) LR51          [1851:1851]
-	 72 -> Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM) [1554:4011]
-	 73 -> Sensoray 311/611                                    [6000:0311,6000:0611]
-	 74 -> RemoteVision MX (RV605)
-	 75 -> Powercolor MTV878/ MTV878R/ MTV878F
-	 76 -> Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP) [0e11:0079]
-	 77 -> GrandTec Multi Capture Card (Bt878)
-	 78 -> Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF   [0a01:17de]
-	 79 -> DSP Design TCVIDEO
-	 80 -> Hauppauge WinTV PVR                                 [0070:4500]
-	 81 -> IODATA GV-BCTV5/PCI                                 [10fc:4070,10fc:d018]
-	 82 -> Osprey 100/150 (878)                                [0070:ff00]
-	 83 -> Osprey 100/150 (848)
-	 84 -> Osprey 101 (848)
-	 85 -> Osprey 101/151
-	 86 -> Osprey 101/151 w/ svid
-	 87 -> Osprey 200/201/250/251
-	 88 -> Osprey 200/250                                      [0070:ff01]
-	 89 -> Osprey 210/220/230
-	 90 -> Osprey 500                                          [0070:ff02]
-	 91 -> Osprey 540                                          [0070:ff04]
-	 92 -> Osprey 2000                                         [0070:ff03]
-	 93 -> IDS Eagle
-	 94 -> Pinnacle PCTV Sat                                   [11bd:001c]
-	 95 -> Formac ProTV II (bt878)
-	 96 -> MachTV
-	 97 -> Euresys Picolo
-	 98 -> ProVideo PV150                                      [aa00:1460,aa01:1461,aa02:1462,aa03:1463,aa04:1464,aa05:1465,aa06:1466,aa07:1467]
-	 99 -> AD-TVK503
-	100 -> Hercules Smart TV Stereo
-	101 -> Pace TV & Radio Card
-	102 -> IVC-200                                             [0000:a155,0001:a155,0002:a155,0003:a155,0100:a155,0101:a155,0102:a155,0103:a155,0800:a155,0801:a155,0802:a155,0803:a155]
-	103 -> Grand X-Guard / Trust 814PCI                        [0304:0102]
-	104 -> Nebula Electronics DigiTV                           [0071:0101]
-	105 -> ProVideo PV143                                      [aa00:1430,aa00:1431,aa00:1432,aa00:1433,aa03:1433]
-	106 -> PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)
-	107 -> PHYTEC VD-009-X1 VD-011 Combi (bt878)
-	108 -> PHYTEC VD-009 MiniDIN (bt878)
-	109 -> PHYTEC VD-009 Combi (bt878)
-	110 -> IVC-100                                             [ff00:a132]
-	111 -> IVC-120G                                            [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182]
-	112 -> pcHDTV HD-2000 TV                                   [7063:2000]
-	113 -> Twinhan DST + clones                                [11bd:0026,1822:0001,270f:fc00,1822:0026]
-	114 -> Winfast VC100                                       [107d:6607]
-	115 -> Teppro TEV-560/InterVision IV-560
-	116 -> SIMUS GVC1100                                       [aa6a:82b2]
-	117 -> NGS NGSTV+
-	118 -> LMLBT4
-	119 -> Tekram M205 PRO
-	120 -> Conceptronic CONTVFMi
-	121 -> Euresys Picolo Tetra                                [1805:0105,1805:0106,1805:0107,1805:0108]
-	122 -> Spirit TV Tuner
-	123 -> AVerMedia AVerTV DVB-T 771                          [1461:0771]
-	124 -> AverMedia AverTV DVB-T 761                          [1461:0761]
-	125 -> MATRIX Vision Sigma-SQ
-	126 -> MATRIX Vision Sigma-SLC
-	127 -> APAC Viewcomp 878(AMAX)
-	128 -> DViCO FusionHDTV DVB-T Lite                         [18ac:db10,18ac:db11]
-	129 -> V-Gear MyVCD
-	130 -> Super TV Tuner
-	131 -> Tibet Systems 'Progress DVR' CS16
-	132 -> Kodicom 4400R (master)
-	133 -> Kodicom 4400R (slave)
-	134 -> Adlink RTV24
-	135 -> DViCO FusionHDTV 5 Lite                             [18ac:d500]
-	136 -> Acorp Y878F                                         [9511:1540]
-	137 -> Conceptronic CTVFMi v2                              [036e:109e]
-	138 -> Prolink Pixelview PV-BT878P+ (Rev.2E)
-	139 -> Prolink PixelView PlayTV MPEG2 PV-M4900
-	140 -> Osprey 440                                          [0070:ff07]
-	141 -> Asound Skyeye PCTV
-	142 -> Sabrent TV-FM (bttv version)
-	143 -> Hauppauge ImpactVCB (bt878)                         [0070:13eb]
-	144 -> MagicTV
-	145 -> SSAI Security Video Interface                       [4149:5353]
-	146 -> SSAI Ultrasound Video Interface                     [414a:5353]
-	147 -> VoodooTV 200 (USA)                                  [121a:3000]
-	148 -> DViCO FusionHDTV 2                                  [dbc0:d200]
-	149 -> Typhoon TV-Tuner PCI (50684)
-	150 -> Geovision GV-600                                    [008a:763c]
-	151 -> Kozumi KTV-01C
-	152 -> Encore ENL TV-FM-2                                  [1000:1801]
-	153 -> PHYTEC VD-012 (bt878)
-	154 -> PHYTEC VD-012-X1 (bt878)
-	155 -> PHYTEC VD-012-X2 (bt878)
-	156 -> IVCE-8784                                           [0000:f050,0001:f050,0002:f050,0003:f050]
-	157 -> Geovision GV-800(S) (master)                        [800a:763d]
-	158 -> Geovision GV-800(S) (slave)                         [800b:763d,800c:763d,800d:763d]
-	159 -> ProVideo PV183                                      [1830:1540,1831:1540,1832:1540,1833:1540,1834:1540,1835:1540,1836:1540,1837:1540]
-	160 -> Tongwei Video Technology TD-3116                    [f200:3116]
-	161 -> Aposonic W-DVR                                      [0279:0228]
-	162 -> Adlink MPG24
-	163 -> Bt848 Capture 14MHz
-	164 -> CyberVision CV06 (SV)
-	165 -> Kworld V-Stream Xpert TV PVR878
-	166 -> PCI-8604PW
+=========== ================================================================================= ==============================================================================================================================================================================
+Card number Card name                                                                         PCI IDs
+=========== ================================================================================= ==============================================================================================================================================================================
+0            *** UNKNOWN/GENERIC ***
+1           MIRO PCTV
+2           Hauppauge (bt848)
+3           STB, Gateway P/N 6000699 (bt848)
+4           Intel Create and Share PCI/ Smart Video Recorder III
+5           Diamond DTV2000
+6           AVerMedia TVPhone
+7           MATRIX-Vision MV-Delta
+8           Lifeview FlyVideo II (Bt848) LR26 / MAXI TV Video PCI2 LR26
+9           IMS/IXmicro TurboTV
+10          Hauppauge (bt878)                                                                 0070:13eb, 0070:3900, 2636:10b4
+11          MIRO PCTV pro
+12          ADS Technologies Channel Surfer TV (bt848)
+13          AVerMedia TVCapture 98                                                            1461:0002, 1461:0004, 1461:0300
+14          Aimslab Video Highway Xtreme (VHX)
+15          Zoltrix TV-Max                                                                    a1a0:a0fc
+16          Prolink Pixelview PlayTV (bt878)
+17          Leadtek WinView 601
+18          AVEC Intercapture
+19          Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)
+20          CEI Raffles Card
+21          Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50
+22          Askey CPH050/ Phoebe Tv Master + FM                                               14ff:3002
+23          Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878                      14c7:0101
+24          Askey CPH05X/06X (bt878) [many vendors]                                           144f:3002, 144f:3005, 144f:5000, 14ff:3000
+25          Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar
+26          Hauppauge WinCam newer (bt878)
+27          Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50
+28          Terratec TerraTV+ Version 1.1 (bt878)                                             153b:1127, 1852:1852
+29          Imagenation PXC200                                                                1295:200a
+30          Lifeview FlyVideo 98 LR50                                                         1f7f:1850
+31          Formac iProTV, Formac ProTV I (bt848)
+32          Intel Create and Share PCI/ Smart Video Recorder III
+33          Terratec TerraTValue Version Bt878                                                153b:1117, 153b:1118, 153b:1119, 153b:111a, 153b:1134, 153b:5018
+34          Leadtek WinFast 2000/ WinFast 2000 XP                                             107d:6606, 107d:6609, 6606:217d, f6ff:fff6
+35          Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II                              1851:1850, 1851:a050
+36          Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner                           1852:1852
+37          Prolink PixelView PlayTV pro
+38          Askey CPH06X TView99                                                              144f:3000, 144f:a005, a04f:a0fc
+39          Pinnacle PCTV Studio/Rave                                                         11bd:0012, bd11:1200, bd11:ff00, 11bd:ff12
+40          STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100                     10b4:2636, 10b4:2645, 121a:3060
+41          AVerMedia TVPhone 98                                                              1461:0001, 1461:0003
+42          ProVideo PV951                                                                    aa0c:146c
+43          Little OnAir TV
+44          Sigma TVII-FM
+45          MATRIX-Vision MV-Delta 2
+46          Zoltrix Genie TV/FM                                                               15b0:4000, 15b0:400a, 15b0:400d, 15b0:4010, 15b0:4016
+47          Terratec TV/Radio+                                                                153b:1123
+48          Askey CPH03x/ Dynalink Magic TView
+49          IODATA GV-BCTV3/PCI                                                               10fc:4020
+50          Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP
+51          Eagle Wireless Capricorn2 (bt878A)
+52          Pinnacle PCTV Studio Pro
+53          Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS
+54          Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]
+55          Askey CPH031/ BESTBUY Easy TV
+56          Lifeview FlyVideo 98FM LR50                                                       a051:41a0
+57          GrandTec 'Grand Video Capture' (Bt848)                                            4344:4142
+58          Askey CPH060/ Phoebe TV Master Only (No FM)
+59          Askey CPH03x TV Capturer
+60          Modular Technology MM100PCTV
+61          AG Electronics GMV1                                                               15cb:0101
+62          Askey CPH061/ BESTBUY Easy TV (bt878)
+63          ATI TV-Wonder                                                                     1002:0001
+64          ATI TV-Wonder VE                                                                  1002:0003
+65          Lifeview FlyVideo 2000S LR90
+66          Terratec TValueRadio                                                              153b:1135, 153b:ff3b
+67          IODATA GV-BCTV4/PCI                                                               10fc:4050
+68          3Dfx VoodooTV FM (Euro)                                                           10b4:2637
+69          Active Imaging AIMMS
+70          Prolink Pixelview PV-BT878P+ (Rev.4C,8E)
+71          Lifeview FlyVideo 98EZ (capture only) LR51                                        1851:1851
+72          Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)                       1554:4011
+73          Sensoray 311/611                                                                  6000:0311, 6000:0611
+74          RemoteVision MX (RV605)
+75          Powercolor MTV878/ MTV878R/ MTV878F
+76          Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)                               0e11:0079
+77          GrandTec Multi Capture Card (Bt878)
+78          Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF                                 0a01:17de
+79          DSP Design TCVIDEO
+80          Hauppauge WinTV PVR                                                               0070:4500
+81          IODATA GV-BCTV5/PCI                                                               10fc:4070, 10fc:d018
+82          Osprey 100/150 (878)                                                              0070:ff00
+83          Osprey 100/150 (848)
+84          Osprey 101 (848)
+85          Osprey 101/151
+86          Osprey 101/151 w/ svid
+87          Osprey 200/201/250/251
+88          Osprey 200/250                                                                    0070:ff01
+89          Osprey 210/220/230
+90          Osprey 500                                                                        0070:ff02
+91          Osprey 540                                                                        0070:ff04
+92          Osprey 2000                                                                       0070:ff03
+93          IDS Eagle
+94          Pinnacle PCTV Sat                                                                 11bd:001c
+95          Formac ProTV II (bt878)
+96          MachTV
+97          Euresys Picolo
+98          ProVideo PV150                                                                    aa00:1460, aa01:1461, aa02:1462, aa03:1463, aa04:1464, aa05:1465, aa06:1466, aa07:1467
+99          AD-TVK503
+100         Hercules Smart TV Stereo
+101         Pace TV & Radio Card
+102         IVC-200                                                                           0000:a155, 0001:a155, 0002:a155, 0003:a155, 0100:a155, 0101:a155, 0102:a155, 0103:a155, 0800:a155, 0801:a155, 0802:a155, 0803:a155
+103         Grand X-Guard / Trust 814PCI                                                      0304:0102
+104         Nebula Electronics DigiTV                                                         0071:0101
+105         ProVideo PV143                                                                    aa00:1430, aa00:1431, aa00:1432, aa00:1433, aa03:1433
+106         PHYTEC VD-009-X1 VD-011 MiniDIN (bt878)
+107         PHYTEC VD-009-X1 VD-011 Combi (bt878)
+108         PHYTEC VD-009 MiniDIN (bt878)
+109         PHYTEC VD-009 Combi (bt878)
+110         IVC-100                                                                           ff00:a132
+111         IVC-120G                                                                          ff00:a182, ff01:a182, ff02:a182, ff03:a182, ff04:a182, ff05:a182, ff06:a182, ff07:a182, ff08:a182, ff09:a182, ff0a:a182, ff0b:a182, ff0c:a182, ff0d:a182, ff0e:a182, ff0f:a182
+112         pcHDTV HD-2000 TV                                                                 7063:2000
+113         Twinhan DST + clones                                                              11bd:0026, 1822:0001, 270f:fc00, 1822:0026
+114         Winfast VC100                                                                     107d:6607
+115         Teppro TEV-560/InterVision IV-560
+116         SIMUS GVC1100                                                                     aa6a:82b2
+117         NGS NGSTV+
+118         LMLBT4
+119         Tekram M205 PRO
+120         Conceptronic CONTVFMi
+121         Euresys Picolo Tetra                                                              1805:0105, 1805:0106, 1805:0107, 1805:0108
+122         Spirit TV Tuner
+123         AVerMedia AVerTV DVB-T 771                                                        1461:0771
+124         AverMedia AverTV DVB-T 761                                                        1461:0761
+125         MATRIX Vision Sigma-SQ
+126         MATRIX Vision Sigma-SLC
+127         APAC Viewcomp 878(AMAX)
+128         DViCO FusionHDTV DVB-T Lite                                                       18ac:db10, 18ac:db11
+129         V-Gear MyVCD
+130         Super TV Tuner
+131         Tibet Systems 'Progress DVR' CS16
+132         Kodicom 4400R (master)
+133         Kodicom 4400R (slave)
+134         Adlink RTV24
+135         DViCO FusionHDTV 5 Lite                                                           18ac:d500
+136         Acorp Y878F                                                                       9511:1540
+137         Conceptronic CTVFMi v2                                                            036e:109e
+138         Prolink Pixelview PV-BT878P+ (Rev.2E)
+139         Prolink PixelView PlayTV MPEG2 PV-M4900
+140         Osprey 440                                                                        0070:ff07
+141         Asound Skyeye PCTV
+142         Sabrent TV-FM (bttv version)
+143         Hauppauge ImpactVCB (bt878)                                                       0070:13eb
+144         MagicTV
+145         SSAI Security Video Interface                                                     4149:5353
+146         SSAI Ultrasound Video Interface                                                   414a:5353
+147         VoodooTV 200 (USA)                                                                121a:3000
+148         DViCO FusionHDTV 2                                                                dbc0:d200
+149         Typhoon TV-Tuner PCI (50684)
+150         Geovision GV-600                                                                  008a:763c
+151         Kozumi KTV-01C
+152         Encore ENL TV-FM-2                                                                1000:1801
+153         PHYTEC VD-012 (bt878)
+154         PHYTEC VD-012-X1 (bt878)
+155         PHYTEC VD-012-X2 (bt878)
+156         IVCE-8784                                                                         0000:f050, 0001:f050, 0002:f050, 0003:f050
+157         Geovision GV-800(S) (master)                                                      800a:763d
+158         Geovision GV-800(S) (slave)                                                       800b:763d, 800c:763d, 800d:763d
+159         ProVideo PV183                                                                    1830:1540, 1831:1540, 1832:1540, 1833:1540, 1834:1540, 1835:1540, 1836:1540, 1837:1540
+160         Tongwei Video Technology TD-3116                                                  f200:3116
+161         Aposonic W-DVR                                                                    0279:0228
+162         Adlink MPG24
+163         Bt848 Capture 14MHz
+164         CyberVision CV06 (SV)
+165         Kworld V-Stream Xpert TV PVR878
+166         PCI-8604PW
+=========== ================================================================================= ==============================================================================================================================================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/bttv.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/bttv.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/bttv.rst	2016-12-11 17:47:06.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/bttv.rst	2017-02-12 17:34:03.000000000 -0500
@@ -300,10 +300,10 @@ bug.  It is very helpful if you can tell
 With a hard freeze you probably doesn't find anything in the logfiles.
 The only way to capture any kernel messages is to hook up a serial
 console and let some terminal application log the messages.  /me uses
-screen.  See Documentation/serial-console.txt for details on setting
+screen.  See Documentation/admin-guide/serial-console.rst for details on setting
 up a serial console.
 
-Read Documentation/oops-tracing.txt to learn how to get any useful
+Read Documentation/admin-guide/oops-tracing.rst to learn how to get any useful
 information out of a register+stack dump printed by the kernel on
 protection faults (so-called "kernel oops").
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/cafe_ccic.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/cafe_ccic.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/cafe_ccic.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/cafe_ccic.rst	2017-02-12 16:03:20.000000000 -0500
@@ -3,8 +3,8 @@ The cafe_ccic driver
 
 Author: Jonathan Corbet <corbet@lwn.net>
 
-Introdution
------------
+Introduction
+------------
 
 "cafe_ccic" is a driver for the Marvell 88ALP01 "cafe" CMOS camera
 controller.  This is the controller found in first-generation OLPC systems,
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/cx23885-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/cx23885-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/cx23885-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/cx23885-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,63 +1,65 @@
 cx23885 cards list
 ==================
 
-.. code-block:: none
-
-	  0 -> UNKNOWN/GENERIC                                     [0070:3400]
-	  1 -> Hauppauge WinTV-HVR1800lp                           [0070:7600]
-	  2 -> Hauppauge WinTV-HVR1800                             [0070:7800,0070:7801,0070:7809]
-	  3 -> Hauppauge WinTV-HVR1250                             [0070:7911]
-	  4 -> DViCO FusionHDTV5 Express                           [18ac:d500]
-	  5 -> Hauppauge WinTV-HVR1500Q                            [0070:7790,0070:7797]
-	  6 -> Hauppauge WinTV-HVR1500                             [0070:7710,0070:7717]
-	  7 -> Hauppauge WinTV-HVR1200                             [0070:71d1,0070:71d3]
-	  8 -> Hauppauge WinTV-HVR1700                             [0070:8101]
-	  9 -> Hauppauge WinTV-HVR1400                             [0070:8010]
-	 10 -> DViCO FusionHDTV7 Dual Express                      [18ac:d618]
-	 11 -> DViCO FusionHDTV DVB-T Dual Express                 [18ac:db78]
-	 12 -> Leadtek Winfast PxDVR3200 H                         [107d:6681]
-	 13 -> Compro VideoMate E650F                              [185b:e800]
-	 14 -> TurboSight TBS 6920                                 [6920:8888]
-	 15 -> TeVii S470                                          [d470:9022]
-	 16 -> DVBWorld DVB-S2 2005                                [0001:2005]
-	 17 -> NetUP Dual DVB-S2 CI                                [1b55:2a2c]
-	 18 -> Hauppauge WinTV-HVR1270                             [0070:2211]
-	 19 -> Hauppauge WinTV-HVR1275                             [0070:2215,0070:221d,0070:22f2]
-	 20 -> Hauppauge WinTV-HVR1255                             [0070:2251,0070:22f1]
-	 21 -> Hauppauge WinTV-HVR1210                             [0070:2291,0070:2295,0070:2299,0070:229d,0070:22f0,0070:22f3,0070:22f4,0070:22f5]
-	 22 -> Mygica X8506 DMB-TH                                 [14f1:8651]
-	 23 -> Magic-Pro ProHDTV Extreme 2                         [14f1:8657]
-	 24 -> Hauppauge WinTV-HVR1850                             [0070:8541]
-	 25 -> Compro VideoMate E800                               [1858:e800]
-	 26 -> Hauppauge WinTV-HVR1290                             [0070:8551]
-	 27 -> Mygica X8558 PRO DMB-TH                             [14f1:8578]
-	 28 -> LEADTEK WinFast PxTV1200                            [107d:6f22]
-	 29 -> GoTView X5 3D Hybrid                                [5654:2390]
-	 30 -> NetUP Dual DVB-T/C-CI RF                            [1b55:e2e4]
-	 31 -> Leadtek Winfast PxDVR3200 H XC4000                  [107d:6f39]
-	 32 -> MPX-885
-	 33 -> Mygica X8502/X8507 ISDB-T                           [14f1:8502]
-	 34 -> TerraTec Cinergy T PCIe Dual                        [153b:117e]
-	 35 -> TeVii S471                                          [d471:9022]
-	 36 -> Hauppauge WinTV-HVR1255                             [0070:2259]
-	 37 -> Prof Revolution DVB-S2 8000                         [8000:3034]
-	 38 -> Hauppauge WinTV-HVR4400/HVR5500                     [0070:c108,0070:c138,0070:c1f8]
-	 39 -> AVerTV Hybrid Express Slim HC81R                    [1461:d939]
-	 40 -> TurboSight TBS 6981                                 [6981:8888]
-	 41 -> TurboSight TBS 6980                                 [6980:8888]
-	 42 -> Leadtek Winfast PxPVR2200                           [107d:6f21]
-	 43 -> Hauppauge ImpactVCB-e                               [0070:7133]
-	 44 -> DViCO FusionHDTV DVB-T Dual Express2                [18ac:db98]
-	 45 -> DVBSky T9580                                        [4254:9580]
-	 46 -> DVBSky T980C                                        [4254:980c]
-	 47 -> DVBSky S950C                                        [4254:950c]
-	 48 -> Technotrend TT-budget CT2-4500 CI                   [13c2:3013]
-	 49 -> DVBSky S950                                         [4254:0950]
-	 50 -> DVBSky S952                                         [4254:0952]
-	 51 -> DVBSky T982                                         [4254:0982]
-	 52 -> Hauppauge WinTV-HVR5525                             [0070:f038]
-	 53 -> Hauppauge WinTV Starburst                           [0070:c12a]
-	 54 -> ViewCast 260e                                       [1576:0260]
-	 55 -> ViewCast 460e                                       [1576:0460]
-	 56 -> Hauppauge WinTV-QuadHD-DVB                          [0070:6a28,0070:6b28]
-	 57 -> Hauppauge WinTV-QuadHD-ATSC                         [0070:6a18,0070:6b18]
+=========== ==================================== ======================================================================================
+Card number Card name                            PCI IDs
+=========== ==================================== ======================================================================================
+0           UNKNOWN/GENERIC                      0070:3400
+1           Hauppauge WinTV-HVR1800lp            0070:7600
+2           Hauppauge WinTV-HVR1800              0070:7800, 0070:7801, 0070:7809
+3           Hauppauge WinTV-HVR1250              0070:7911
+4           DViCO FusionHDTV5 Express            18ac:d500
+5           Hauppauge WinTV-HVR1500Q             0070:7790, 0070:7797
+6           Hauppauge WinTV-HVR1500              0070:7710, 0070:7717
+7           Hauppauge WinTV-HVR1200              0070:71d1, 0070:71d3
+8           Hauppauge WinTV-HVR1700              0070:8101
+9           Hauppauge WinTV-HVR1400              0070:8010
+10          DViCO FusionHDTV7 Dual Express       18ac:d618
+11          DViCO FusionHDTV DVB-T Dual Express  18ac:db78
+12          Leadtek Winfast PxDVR3200 H          107d:6681
+13          Compro VideoMate E650F               185b:e800
+14          TurboSight TBS 6920                  6920:8888
+15          TeVii S470                           d470:9022
+16          DVBWorld DVB-S2 2005                 0001:2005
+17          NetUP Dual DVB-S2 CI                 1b55:2a2c
+18          Hauppauge WinTV-HVR1270              0070:2211
+19          Hauppauge WinTV-HVR1275              0070:2215, 0070:221d, 0070:22f2
+20          Hauppauge WinTV-HVR1255              0070:2251, 0070:22f1
+21          Hauppauge WinTV-HVR1210              0070:2291, 0070:2295, 0070:2299, 0070:229d, 0070:22f0, 0070:22f3, 0070:22f4, 0070:22f5
+22          Mygica X8506 DMB-TH                  14f1:8651
+23          Magic-Pro ProHDTV Extreme 2          14f1:8657
+24          Hauppauge WinTV-HVR1850              0070:8541
+25          Compro VideoMate E800                1858:e800
+26          Hauppauge WinTV-HVR1290              0070:8551
+27          Mygica X8558 PRO DMB-TH              14f1:8578
+28          LEADTEK WinFast PxTV1200             107d:6f22
+29          GoTView X5 3D Hybrid                 5654:2390
+30          NetUP Dual DVB-T/C-CI RF             1b55:e2e4
+31          Leadtek Winfast PxDVR3200 H XC4000   107d:6f39
+32          MPX-885
+33          Mygica X8502/X8507 ISDB-T            14f1:8502
+34          TerraTec Cinergy T PCIe Dual         153b:117e
+35          TeVii S471                           d471:9022
+36          Hauppauge WinTV-HVR1255              0070:2259
+37          Prof Revolution DVB-S2 8000          8000:3034
+38          Hauppauge WinTV-HVR4400/HVR5500      0070:c108, 0070:c138, 0070:c1f8
+39          AVerTV Hybrid Express Slim HC81R     1461:d939
+40          TurboSight TBS 6981                  6981:8888
+41          TurboSight TBS 6980                  6980:8888
+42          Leadtek Winfast PxPVR2200            107d:6f21
+43          Hauppauge ImpactVCB-e                0070:7133
+44          DViCO FusionHDTV DVB-T Dual Express2 18ac:db98
+45          DVBSky T9580                         4254:9580
+46          DVBSky T980C                         4254:980c
+47          DVBSky S950C                         4254:950c
+48          Technotrend TT-budget CT2-4500 CI    13c2:3013
+49          DVBSky S950                          4254:0950
+50          DVBSky S952                          4254:0952
+51          DVBSky T982                          4254:0982
+52          Hauppauge WinTV-HVR5525              0070:f038
+53          Hauppauge WinTV Starburst            0070:c12a
+54          ViewCast 260e                        1576:0260
+55          ViewCast 460e                        1576:0460
+56          Hauppauge WinTV-QuadHD-DVB           0070:6a28, 0070:6b28
+57          Hauppauge WinTV-QuadHD-ATSC          0070:6a18, 0070:6b18
+=========== ==================================== ======================================================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/cx88-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/cx88-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/cx88-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/cx88-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,96 +1,98 @@
 CX88 cards list
 ===============
 
-.. code-block:: none
-
-	  0 -> UNKNOWN/GENERIC
-	  1 -> Hauppauge WinTV 34xxx models                        [0070:3400,0070:3401]
-	  2 -> GDI Black Gold                                      [14c7:0106,14c7:0107]
-	  3 -> PixelView                                           [1554:4811]
-	  4 -> ATI TV Wonder Pro                                   [1002:00f8,1002:00f9]
-	  5 -> Leadtek Winfast 2000XP Expert                       [107d:6611,107d:6613]
-	  6 -> AverTV Studio 303 (M126)                            [1461:000b]
-	  7 -> MSI TV-@nywhere Master                              [1462:8606]
-	  8 -> Leadtek Winfast DV2000                              [107d:6620,107d:6621]
-	  9 -> Leadtek PVR 2000                                    [107d:663b,107d:663c,107d:6632,107d:6630,107d:6638,107d:6631,107d:6637,107d:663d]
-	 10 -> IODATA GV-VCP3/PCI                                  [10fc:d003]
-	 11 -> Prolink PlayTV PVR
-	 12 -> ASUS PVR-416                                        [1043:4823,1461:c111]
-	 13 -> MSI TV-@nywhere
-	 14 -> KWorld/VStream XPert DVB-T                          [17de:08a6]
-	 15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
-	 16 -> KWorld LTV883RF
-	 17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810,18ac:d800]
-	 18 -> Hauppauge Nova-T DVB-T                              [0070:9002,0070:9001,0070:9000]
-	 19 -> Conexant DVB-T reference design                     [14f1:0187]
-	 20 -> Provideo PV259                                      [1540:2580]
-	 21 -> DViCO FusionHDTV DVB-T Plus                         [18ac:db10,18ac:db11]
-	 22 -> pcHDTV HD3000 HDTV                                  [7063:3000]
-	 23 -> digitalnow DNTV Live! DVB-T                         [17de:a8a6]
-	 24 -> Hauppauge WinTV 28xxx (Roslyn) models               [0070:2801]
-	 25 -> Digital-Logic MICROSPACE Entertainment Center (MEC) [14f1:0342]
-	 26 -> IODATA GV/BCTV7E                                    [10fc:d035]
-	 27 -> PixelView PlayTV Ultra Pro (Stereo)
-	 28 -> DViCO FusionHDTV 3 Gold-T                           [18ac:d820]
-	 29 -> ADS Tech Instant TV DVB-T PCI                       [1421:0334]
-	 30 -> TerraTec Cinergy 1400 DVB-T                         [153b:1166]
-	 31 -> DViCO FusionHDTV 5 Gold                             [18ac:d500]
-	 32 -> AverMedia UltraTV Media Center PCI 550              [1461:8011]
-	 33 -> Kworld V-Stream Xpert DVD
-	 34 -> ATI HDTV Wonder                                     [1002:a101]
-	 35 -> WinFast DTV1000-T                                   [107d:665f]
-	 36 -> AVerTV 303 (M126)                                   [1461:000a]
-	 37 -> Hauppauge Nova-S-Plus DVB-S                         [0070:9201,0070:9202]
-	 38 -> Hauppauge Nova-SE2 DVB-S                            [0070:9200]
-	 39 -> KWorld DVB-S 100                                    [17de:08b2,1421:0341]
-	 40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid                [0070:9400,0070:9402]
-	 41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
-	 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025,1822:0019]
-	 43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1,12ab:2300]
-	 44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
-	 45 -> KWorld HardwareMpegTV XPert                         [17de:0840,1421:0305]
-	 46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
-	 47 -> pcHDTV HD5500 HDTV                                  [7063:5500]
-	 48 -> Kworld MCE 200 Deluxe                               [17de:0841]
-	 49 -> PixelView PlayTV P7000                              [1554:4813]
-	 50 -> NPG Tech Real TV FM Top 10                          [14f1:0842]
-	 51 -> WinFast DTV2000 H                                   [107d:665e]
-	 52 -> Geniatech DVB-S                                     [14f1:0084]
-	 53 -> Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T  [0070:1404,0070:1400,0070:1401,0070:1402]
-	 54 -> Norwood Micro TV Tuner
-	 55 -> Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM  [c180:c980]
-	 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   [0070:9600,0070:9601,0070:9602]
-	 57 -> ADS Tech Instant Video PCI                          [1421:0390]
-	 58 -> Pinnacle PCTV HD 800i                               [11bd:0051]
-	 59 -> DViCO FusionHDTV 5 PCI nano                         [18ac:d530]
-	 60 -> Pinnacle Hybrid PCTV                                [12ab:1788]
-	 61 -> Leadtek TV2000 XP Global                            [107d:6f18,107d:6618,107d:6619]
-	 62 -> PowerColor RA330                                    [14f1:ea3d]
-	 63 -> Geniatech X8000-MT DVBT                             [14f1:8852]
-	 64 -> DViCO FusionHDTV DVB-T PRO                          [18ac:db30]
-	 65 -> DViCO FusionHDTV 7 Gold                             [18ac:d610]
-	 66 -> Prolink Pixelview MPEG 8000GT                       [1554:4935]
-	 67 -> Kworld PlusTV HD PCI 120 (ATSC 120)                 [17de:08c1]
-	 68 -> Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid           [0070:6900,0070:6904,0070:6902]
-	 69 -> Hauppauge WinTV-HVR4000(Lite) DVB-S/S2              [0070:6905,0070:6906]
-	 70 -> TeVii S460 DVB-S/S2                                 [d460:9022]
-	 71 -> Omicom SS4 DVB-S/S2 PCI                             [A044:2011]
-	 72 -> TBS 8920 DVB-S/S2                                   [8920:8888]
-	 73 -> TeVii S420 DVB-S                                    [d420:9022]
-	 74 -> Prolink Pixelview Global Extreme                    [1554:4976]
-	 75 -> PROF 7300 DVB-S/S2                                  [B033:3033]
-	 76 -> SATTRADE ST4200 DVB-S/S2                            [b200:4200]
-	 77 -> TBS 8910 DVB-S                                      [8910:8888]
-	 78 -> Prof 6200 DVB-S                                     [b022:3022]
-	 79 -> Terratec Cinergy HT PCI MKII                        [153b:1177]
-	 80 -> Hauppauge WinTV-IR Only                             [0070:9290]
-	 81 -> Leadtek WinFast DTV1800 Hybrid                      [107d:6654]
-	 82 -> WinFast DTV2000 H rev. J                            [107d:6f2b]
-	 83 -> Prof 7301 DVB-S/S2                                  [b034:3034]
-	 84 -> Samsung SMT 7020 DVB-S                              [18ac:dc00,18ac:dccd]
-	 85 -> Twinhan VP-1027 DVB-S                               [1822:0023]
-	 86 -> TeVii S464 DVB-S/S2                                 [d464:9022]
-	 87 -> Leadtek WinFast DTV2000 H PLUS                      [107d:6f42]
-	 88 -> Leadtek WinFast DTV1800 H (XC4000)                  [107d:6f38]
-	 89 -> Leadtek TV2000 XP Global (SC4100)                   [107d:6f36]
-	 90 -> Leadtek TV2000 XP Global (XC4100)                   [107d:6f43]
+=========== =================================================== ======================================================================================
+Card number Card name                                           PCI IDs
+=========== =================================================== ======================================================================================
+0           UNKNOWN/GENERIC
+1           Hauppauge WinTV 34xxx models                        0070:3400, 0070:3401
+2           GDI Black Gold                                      14c7:0106, 14c7:0107
+3           PixelView                                           1554:4811
+4           ATI TV Wonder Pro                                   1002:00f8, 1002:00f9
+5           Leadtek Winfast 2000XP Expert                       107d:6611, 107d:6613
+6           AverTV Studio 303 (M126)                            1461:000b
+7           MSI TV-@nywhere Master                              1462:8606
+8           Leadtek Winfast DV2000                              107d:6620, 107d:6621
+9           Leadtek PVR 2000                                    107d:663b, 107d:663c, 107d:6632, 107d:6630, 107d:6638, 107d:6631, 107d:6637, 107d:663d
+10          IODATA GV-VCP3/PCI                                  10fc:d003
+11          Prolink PlayTV PVR
+12          ASUS PVR-416                                        1043:4823, 1461:c111
+13          MSI TV-@nywhere
+14          KWorld/VStream XPert DVB-T                          17de:08a6
+15          DViCO FusionHDTV DVB-T1                             18ac:db00
+16          KWorld LTV883RF
+17          DViCO FusionHDTV 3 Gold-Q                           18ac:d810, 18ac:d800
+18          Hauppauge Nova-T DVB-T                              0070:9002, 0070:9001, 0070:9000
+19          Conexant DVB-T reference design                     14f1:0187
+20          Provideo PV259                                      1540:2580
+21          DViCO FusionHDTV DVB-T Plus                         18ac:db10, 18ac:db11
+22          pcHDTV HD3000 HDTV                                  7063:3000
+23          digitalnow DNTV Live! DVB-T                         17de:a8a6
+24          Hauppauge WinTV 28xxx (Roslyn) models               0070:2801
+25          Digital-Logic MICROSPACE Entertainment Center (MEC) 14f1:0342
+26          IODATA GV/BCTV7E                                    10fc:d035
+27          PixelView PlayTV Ultra Pro (Stereo)
+28          DViCO FusionHDTV 3 Gold-T                           18ac:d820
+29          ADS Tech Instant TV DVB-T PCI                       1421:0334
+30          TerraTec Cinergy 1400 DVB-T                         153b:1166
+31          DViCO FusionHDTV 5 Gold                             18ac:d500
+32          AverMedia UltraTV Media Center PCI 550              1461:8011
+33          Kworld V-Stream Xpert DVD
+34          ATI HDTV Wonder                                     1002:a101
+35          WinFast DTV1000-T                                   107d:665f
+36          AVerTV 303 (M126)                                   1461:000a
+37          Hauppauge Nova-S-Plus DVB-S                         0070:9201, 0070:9202
+38          Hauppauge Nova-SE2 DVB-S                            0070:9200
+39          KWorld DVB-S 100                                    17de:08b2, 1421:0341
+40          Hauppauge WinTV-HVR1100 DVB-T/Hybrid                0070:9400, 0070:9402
+41          Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  0070:9800, 0070:9802
+42          digitalnow DNTV Live! DVB-T Pro                     1822:0025, 1822:0019
+43          KWorld/VStream XPert DVB-T with cx22702             17de:08a1, 12ab:2300
+44          DViCO FusionHDTV DVB-T Dual Digital                 18ac:db50, 18ac:db54
+45          KWorld HardwareMpegTV XPert                         17de:0840, 1421:0305
+46          DViCO FusionHDTV DVB-T Hybrid                       18ac:db40, 18ac:db44
+47          pcHDTV HD5500 HDTV                                  7063:5500
+48          Kworld MCE 200 Deluxe                               17de:0841
+49          PixelView PlayTV P7000                              1554:4813
+50          NPG Tech Real TV FM Top 10                          14f1:0842
+51          WinFast DTV2000 H                                   107d:665e
+52          Geniatech DVB-S                                     14f1:0084
+53          Hauppauge WinTV-HVR3000 TriMode Analog/DVB-S/DVB-T  0070:1404, 0070:1400, 0070:1401, 0070:1402
+54          Norwood Micro TV Tuner
+55          Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM  c180:c980
+56          Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder   0070:9600, 0070:9601, 0070:9602
+57          ADS Tech Instant Video PCI                          1421:0390
+58          Pinnacle PCTV HD 800i                               11bd:0051
+59          DViCO FusionHDTV 5 PCI nano                         18ac:d530
+60          Pinnacle Hybrid PCTV                                12ab:1788
+61          Leadtek TV2000 XP Global                            107d:6f18, 107d:6618, 107d:6619
+62          PowerColor RA330                                    14f1:ea3d
+63          Geniatech X8000-MT DVBT                             14f1:8852
+64          DViCO FusionHDTV DVB-T PRO                          18ac:db30
+65          DViCO FusionHDTV 7 Gold                             18ac:d610
+66          Prolink Pixelview MPEG 8000GT                       1554:4935
+67          Kworld PlusTV HD PCI 120 (ATSC 120)                 17de:08c1
+68          Hauppauge WinTV-HVR4000 DVB-S/S2/T/Hybrid           0070:6900, 0070:6904, 0070:6902
+69          Hauppauge WinTV-HVR4000(Lite) DVB-S/S2              0070:6905, 0070:6906
+70          TeVii S460 DVB-S/S2                                 d460:9022
+71          Omicom SS4 DVB-S/S2 PCI                             A044:2011
+72          TBS 8920 DVB-S/S2                                   8920:8888
+73          TeVii S420 DVB-S                                    d420:9022
+74          Prolink Pixelview Global Extreme                    1554:4976
+75          PROF 7300 DVB-S/S2                                  B033:3033
+76          SATTRADE ST4200 DVB-S/S2                            b200:4200
+77          TBS 8910 DVB-S                                      8910:8888
+78          Prof 6200 DVB-S                                     b022:3022
+79          Terratec Cinergy HT PCI MKII                        153b:1177
+80          Hauppauge WinTV-IR Only                             0070:9290
+81          Leadtek WinFast DTV1800 Hybrid                      107d:6654
+82          WinFast DTV2000 H rev. J                            107d:6f2b
+83          Prof 7301 DVB-S/S2                                  b034:3034
+84          Samsung SMT 7020 DVB-S                              18ac:dc00, 18ac:dccd
+85          Twinhan VP-1027 DVB-S                               1822:0023
+86          TeVii S464 DVB-S/S2                                 d464:9022
+87          Leadtek WinFast DTV2000 H PLUS                      107d:6f42
+88          Leadtek WinFast DTV1800 H (XC4000)                  107d:6f38
+89          Leadtek TV2000 XP Global (SC4100)                   107d:6f36
+90          Leadtek TV2000 XP Global (XC4100)                   107d:6f43
+=========== =================================================== ======================================================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/em28xx-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/em28xx-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/em28xx-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/em28xx-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,105 +1,107 @@
 EM28xx cards list
 =================
 
-.. code-block:: none
-
-	  0 -> Unknown EM2800 video grabber             (em2800)        [eb1a:2800]
-	  1 -> Unknown EM2750/28xx video grabber        (em2820/em2840) [eb1a:2710,eb1a:2820,eb1a:2821,eb1a:2860,eb1a:2861,eb1a:2862,eb1a:2863,eb1a:2870,eb1a:2881,eb1a:2883,eb1a:2868,eb1a:2875]
-	  2 -> Terratec Cinergy 250 USB                 (em2820/em2840) [0ccd:0036]
-	  3 -> Pinnacle PCTV USB 2                      (em2820/em2840) [2304:0208]
-	  4 -> Hauppauge WinTV USB 2                    (em2820/em2840) [2040:4200,2040:4201]
-	  5 -> MSI VOX USB 2.0                          (em2820/em2840)
-	  6 -> Terratec Cinergy 200 USB                 (em2800)
-	  7 -> Leadtek Winfast USB II                   (em2800)        [0413:6023]
-	  8 -> Kworld USB2800                           (em2800)
-	  9 -> Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker  (em2820/em2840) [1b80:e302,1b80:e304,2304:0207,2304:021a,093b:a003]
-	 10 -> Hauppauge WinTV HVR 900                  (em2880)        [2040:6500]
-	 11 -> Terratec Hybrid XS                       (em2880)
-	 12 -> Kworld PVR TV 2800 RF                    (em2820/em2840)
-	 13 -> Terratec Prodigy XS                      (em2880)
-	 14 -> SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0 (em2820/em2840)
-	 15 -> V-Gear PocketTV                          (em2800)
-	 16 -> Hauppauge WinTV HVR 950                  (em2883)        [2040:6513,2040:6517,2040:651b]
-	 17 -> Pinnacle PCTV HD Pro Stick               (em2880)        [2304:0227]
-	 18 -> Hauppauge WinTV HVR 900 (R2)             (em2880)        [2040:6502]
-	 19 -> EM2860/SAA711X Reference Design          (em2860)
-	 20 -> AMD ATI TV Wonder HD 600                 (em2880)        [0438:b002]
-	 21 -> eMPIA Technology, Inc. GrabBeeX+ Video Encoder (em2800)        [eb1a:2801]
-	 22 -> EM2710/EM2750/EM2751 webcam grabber      (em2750)        [eb1a:2750,eb1a:2751]
-	 23 -> Huaqi DLCW-130                           (em2750)
-	 24 -> D-Link DUB-T210 TV Tuner                 (em2820/em2840) [2001:f112]
-	 25 -> Gadmei UTV310                            (em2820/em2840)
-	 26 -> Hercules Smart TV USB 2.0                (em2820/em2840)
-	 27 -> Pinnacle PCTV USB 2 (Philips FM1216ME)   (em2820/em2840)
-	 28 -> Leadtek Winfast USB II Deluxe            (em2820/em2840)
-	 29 -> EM2860/TVP5150 Reference Design          (em2860)
-	 30 -> Videology 20K14XUSB USB2.0               (em2820/em2840)
-	 31 -> Usbgear VD204v9                          (em2821)
-	 32 -> Supercomp USB 2.0 TV                     (em2821)
-	 33 -> Elgato Video Capture                     (em2860)        [0fd9:0033]
-	 34 -> Terratec Cinergy A Hybrid XS             (em2860)        [0ccd:004f]
-	 35 -> Typhoon DVD Maker                        (em2860)
-	 36 -> NetGMBH Cam                              (em2860)
-	 37 -> Gadmei UTV330                            (em2860)        [eb1a:50a6]
-	 38 -> Yakumo MovieMixer                        (em2861)
-	 39 -> KWorld PVRTV 300U                        (em2861)        [eb1a:e300]
-	 40 -> Plextor ConvertX PX-TV100U               (em2861)        [093b:a005]
-	 41 -> Kworld 350 U DVB-T                       (em2870)        [eb1a:e350]
-	 42 -> Kworld 355 U DVB-T                       (em2870)        [eb1a:e355,eb1a:e357,eb1a:e359]
-	 43 -> Terratec Cinergy T XS                    (em2870)
-	 44 -> Terratec Cinergy T XS (MT2060)           (em2870)        [0ccd:0043]
-	 45 -> Pinnacle PCTV DVB-T                      (em2870)
-	 46 -> Compro, VideoMate U3                     (em2870)        [185b:2870]
-	 47 -> KWorld DVB-T 305U                        (em2880)        [eb1a:e305]
-	 48 -> KWorld DVB-T 310U                        (em2880)
-	 49 -> MSI DigiVox A/D                          (em2880)        [eb1a:e310]
-	 50 -> MSI DigiVox A/D II                       (em2880)        [eb1a:e320]
-	 51 -> Terratec Hybrid XS Secam                 (em2880)        [0ccd:004c]
-	 52 -> DNT DA2 Hybrid                           (em2881)
-	 53 -> Pinnacle Hybrid Pro                      (em2881)
-	 54 -> Kworld VS-DVB-T 323UR                    (em2882)        [eb1a:e323]
-	 55 -> Terratec Cinnergy Hybrid T USB XS (em2882) (em2882)        [0ccd:005e,0ccd:0042]
-	 56 -> Pinnacle Hybrid Pro (330e)               (em2882)        [2304:0226]
-	 57 -> Kworld PlusTV HD Hybrid 330              (em2883)        [eb1a:a316]
-	 58 -> Compro VideoMate ForYou/Stereo           (em2820/em2840) [185b:2041]
-	 59 -> Pinnacle PCTV HD Mini                    (em2874)        [2304:023f]
-	 60 -> Hauppauge WinTV HVR 850                  (em2883)        [2040:651f]
-	 61 -> Pixelview PlayTV Box 4 USB 2.0           (em2820/em2840)
-	 62 -> Gadmei TVR200                            (em2820/em2840)
-	 63 -> Kaiomy TVnPC U2                          (em2860)        [eb1a:e303]
-	 64 -> Easy Cap Capture DC-60                   (em2860)        [1b80:e309]
-	 65 -> IO-DATA GV-MVP/SZ                        (em2820/em2840) [04bb:0515]
-	 66 -> Empire dual TV                           (em2880)
-	 67 -> Terratec Grabby                          (em2860)        [0ccd:0096,0ccd:10AF]
-	 68 -> Terratec AV350                           (em2860)        [0ccd:0084]
-	 69 -> KWorld ATSC 315U HDTV TV Box             (em2882)        [eb1a:a313]
-	 70 -> Evga inDtube                             (em2882)
-	 71 -> Silvercrest Webcam 1.3mpix               (em2820/em2840)
-	 72 -> Gadmei UTV330+                           (em2861)
-	 73 -> Reddo DVB-C USB TV Box                   (em2870)
-	 74 -> Actionmaster/LinXcel/Digitus VC211A      (em2800)
-	 75 -> Dikom DK300                              (em2882)
-	 76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]
-	 77 -> EM2874 Leadership ISDBT                  (em2874)
-	 78 -> PCTV nanoStick T2 290e                   (em28174)       [2013:024f]
-	 79 -> Terratec Cinergy H5                      (em2884)        [eb1a:2885,0ccd:10a2,0ccd:10ad,0ccd:10b6]
-	 80 -> PCTV DVB-S2 Stick (460e)                 (em28174)       [2013:024c]
-	 81 -> Hauppauge WinTV HVR 930C                 (em2884)        [2040:1605]
-	 82 -> Terratec Cinergy HTC Stick               (em2884)        [0ccd:00b2]
-	 83 -> Honestech Vidbox NW03                    (em2860)        [eb1a:5006]
-	 84 -> MaxMedia UB425-TC                        (em2874)        [1b80:e425]
-	 85 -> PCTV QuatroStick (510e)                  (em2884)        [2304:0242]
-	 86 -> PCTV QuatroStick nano (520e)             (em2884)        [2013:0251]
-	 87 -> Terratec Cinergy HTC USB XS              (em2884)        [0ccd:008e,0ccd:00ac]
-	 88 -> C3 Tech Digital Duo HDTV/SDTV USB        (em2884)        [1b80:e755]
-	 89 -> Delock 61959                             (em2874)        [1b80:e1cc]
-	 90 -> KWorld USB ATSC TV Stick UB435-Q V2      (em2874)        [1b80:e346]
-	 91 -> SpeedLink Vicious And Devine Laplace webcam (em2765)        [1ae7:9003,1ae7:9004]
-	 92 -> PCTV DVB-S2 Stick (461e)                 (em28178)       [2013:0258]
-	 93 -> KWorld USB ATSC TV Stick UB435-Q V3      (em2874)        [1b80:e34c]
-	 94 -> PCTV tripleStick (292e)                  (em28178)       [2013:025f,2040:0264]
-	 95 -> Leadtek VC100                            (em2861)        [0413:6f07]
-	 96 -> Terratec Cinergy T2 Stick HD             (em28178)       [eb1a:8179]
-	 97 -> Elgato EyeTV Hybrid 2008 INT             (em2884)        [0fd9:0018]
-	 98 -> PLEX PX-BCUD                             (em28178)       [3275:0085]
-	 99 -> Hauppauge WinTV-dualHD DVB               (em28174)       [2040:0265]
+=========== ==================================================================== ================ ==================================================================================================================================
+Card number Card name                                                            Empia Chip       USB IDs
+=========== ==================================================================== ================ ==================================================================================================================================
+0           Unknown EM2800 video grabber                                         em2800           eb1a:2800
+1           Unknown EM2750/28xx video grabber                                    em2820 or em2840 eb1a:2710, eb1a:2820, eb1a:2821, eb1a:2860, eb1a:2861, eb1a:2862, eb1a:2863, eb1a:2870, eb1a:2881, eb1a:2883, eb1a:2868, eb1a:2875
+2           Terratec Cinergy 250 USB                                             em2820 or em2840 0ccd:0036
+3           Pinnacle PCTV USB 2                                                  em2820 or em2840 2304:0208
+4           Hauppauge WinTV USB 2                                                em2820 or em2840 2040:4200, 2040:4201
+5           MSI VOX USB 2.0                                                      em2820 or em2840
+6           Terratec Cinergy 200 USB                                             em2800
+7           Leadtek Winfast USB II                                               em2800           0413:6023
+8           Kworld USB2800                                                       em2800
+9           Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker  em2820 or em2840 1b80:e302, 1b80:e304, 2304:0207, 2304:021a, 093b:a003
+10          Hauppauge WinTV HVR 900                                              em2880           2040:6500
+11          Terratec Hybrid XS                                                   em2880
+12          Kworld PVR TV 2800 RF                                                em2820 or em2840
+13          Terratec Prodigy XS                                                  em2880
+14          SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0                  em2820 or em2840
+15          V-Gear PocketTV                                                      em2800
+16          Hauppauge WinTV HVR 950                                              em2883           2040:6513, 2040:6517, 2040:651b
+17          Pinnacle PCTV HD Pro Stick                                           em2880           2304:0227
+18          Hauppauge WinTV HVR 900 (R2)                                         em2880           2040:6502
+19          EM2860/SAA711X Reference Design                                      em2860
+20          AMD ATI TV Wonder HD 600                                             em2880           0438:b002
+21          eMPIA Technology, Inc. GrabBeeX+ Video Encoder                       em2800           eb1a:2801
+22          EM2710/EM2750/EM2751 webcam grabber                                  em2750           eb1a:2750, eb1a:2751
+23          Huaqi DLCW-130                                                       em2750
+24          D-Link DUB-T210 TV Tuner                                             em2820 or em2840 2001:f112
+25          Gadmei UTV310                                                        em2820 or em2840
+26          Hercules Smart TV USB 2.0                                            em2820 or em2840
+27          Pinnacle PCTV USB 2 (Philips FM1216ME)                               em2820 or em2840
+28          Leadtek Winfast USB II Deluxe                                        em2820 or em2840
+29          EM2860/TVP5150 Reference Design                                      em2860
+30          Videology 20K14XUSB USB2.0                                           em2820 or em2840
+31          Usbgear VD204v9                                                      em2821
+32          Supercomp USB 2.0 TV                                                 em2821
+33          Elgato Video Capture                                                 em2860           0fd9:0033
+34          Terratec Cinergy A Hybrid XS                                         em2860           0ccd:004f
+35          Typhoon DVD Maker                                                    em2860
+36          NetGMBH Cam                                                          em2860
+37          Gadmei UTV330                                                        em2860           eb1a:50a6
+38          Yakumo MovieMixer                                                    em2861
+39          KWorld PVRTV 300U                                                    em2861           eb1a:e300
+40          Plextor ConvertX PX-TV100U                                           em2861           093b:a005
+41          Kworld 350 U DVB-T                                                   em2870           eb1a:e350
+42          Kworld 355 U DVB-T                                                   em2870           eb1a:e355, eb1a:e357, eb1a:e359
+43          Terratec Cinergy T XS                                                em2870
+44          Terratec Cinergy T XS (MT2060)                                       em2870           0ccd:0043
+45          Pinnacle PCTV DVB-T                                                  em2870
+46          Compro, VideoMate U3                                                 em2870           185b:2870
+47          KWorld DVB-T 305U                                                    em2880           eb1a:e305
+48          KWorld DVB-T 310U                                                    em2880
+49          MSI DigiVox A/D                                                      em2880           eb1a:e310
+50          MSI DigiVox A/D II                                                   em2880           eb1a:e320
+51          Terratec Hybrid XS Secam                                             em2880           0ccd:004c
+52          DNT DA2 Hybrid                                                       em2881
+53          Pinnacle Hybrid Pro                                                  em2881
+54          Kworld VS-DVB-T 323UR                                                em2882           eb1a:e323
+55          Terratec Cinnergy Hybrid T USB XS (em2882)                           em2882           0ccd:005e, 0ccd:0042
+56          Pinnacle Hybrid Pro (330e)                                           em2882           2304:0226
+57          Kworld PlusTV HD Hybrid 330                                          em2883           eb1a:a316
+58          Compro VideoMate ForYou/Stereo                                       em2820 or em2840 185b:2041
+59          Pinnacle PCTV HD Mini                                                em2874           2304:023f
+60          Hauppauge WinTV HVR 850                                              em2883           2040:651f
+61          Pixelview PlayTV Box 4 USB 2.0                                       em2820 or em2840
+62          Gadmei TVR200                                                        em2820 or em2840
+63          Kaiomy TVnPC U2                                                      em2860           eb1a:e303
+64          Easy Cap Capture DC-60                                               em2860           1b80:e309
+65          IO-DATA GV-MVP/SZ                                                    em2820 or em2840 04bb:0515
+66          Empire dual TV                                                       em2880
+67          Terratec Grabby                                                      em2860           0ccd:0096, 0ccd:10AF
+68          Terratec AV350                                                       em2860           0ccd:0084
+69          KWorld ATSC 315U HDTV TV Box                                         em2882           eb1a:a313
+70          Evga inDtube                                                         em2882
+71          Silvercrest Webcam 1.3mpix                                           em2820 or em2840
+72          Gadmei UTV330+                                                       em2861
+73          Reddo DVB-C USB TV Box                                               em2870
+74          Actionmaster/LinXcel/Digitus VC211A                                  em2800
+75          Dikom DK300                                                          em2882
+76          KWorld PlusTV 340U or UB435-Q (ATSC)                                 em2870           1b80:a340
+77          EM2874 Leadership ISDBT                                              em2874
+78          PCTV nanoStick T2 290e                                               em28174          2013:024f
+79          Terratec Cinergy H5                                                  em2884           eb1a:2885, 0ccd:10a2, 0ccd:10ad, 0ccd:10b6
+80          PCTV DVB-S2 Stick (460e)                                             em28174          2013:024c
+81          Hauppauge WinTV HVR 930C                                             em2884           2040:1605
+82          Terratec Cinergy HTC Stick                                           em2884           0ccd:00b2
+83          Honestech Vidbox NW03                                                em2860           eb1a:5006
+84          MaxMedia UB425-TC                                                    em2874           1b80:e425
+85          PCTV QuatroStick (510e)                                              em2884           2304:0242
+86          PCTV QuatroStick nano (520e)                                         em2884           2013:0251
+87          Terratec Cinergy HTC USB XS                                          em2884           0ccd:008e, 0ccd:00ac
+88          C3 Tech Digital Duo HDTV/SDTV USB                                    em2884           1b80:e755
+89          Delock 61959                                                         em2874           1b80:e1cc
+90          KWorld USB ATSC TV Stick UB435-Q V2                                  em2874           1b80:e346
+91          SpeedLink Vicious And Devine Laplace webcam                          em2765           1ae7:9003, 1ae7:9004
+92          PCTV DVB-S2 Stick (461e)                                             em28178          2013:0258
+93          KWorld USB ATSC TV Stick UB435-Q V3                                  em2874           1b80:e34c
+94          PCTV tripleStick (292e)                                              em28178          2013:025f, 2040:0264
+95          Leadtek VC100                                                        em2861           0413:6f07
+96          Terratec Cinergy T2 Stick HD                                         em28178          eb1a:8179
+97          Elgato EyeTV Hybrid 2008 INT                                         em2884           0fd9:0018
+98          PLEX PX-BCUD                                                         em28178          3275:0085
+99          Hauppauge WinTV-dualHD DVB                                           em28174          2040:0265
+=========== ==================================================================== ================ ==================================================================================================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/gspca-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/gspca-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/gspca-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/gspca-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -6,407 +6,444 @@ The modules for the gspca webcam drivers
 - gspca_main: main driver
 - gspca\_\ *driver*: subdriver module with *driver* as follows
 
-=========	=========	====================================================================
+=========	=========	===================================================================
 *driver*	vend:prod	Device
-=========	=========	====================================================================
-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
-zc3xx		041e:041e	Creative WebCam Live!
-ov519		041e:4003	Video Blaster WebCam Go Plus
-spca500		041e:400a	Creative PC-CAM 300
-sunplus		041e:400b	Creative PC-CAM 600
-sunplus		041e:4012	PC-Cam350
-sunplus		041e:4013	Creative Pccam750
-zc3xx		041e:4017	Creative Webcam Mobile PD1090
-spca508		041e:4018	Creative Webcam Vista (PD1100)
-spca561		041e:401a	Creative Webcam Vista (PD1100)
-zc3xx		041e:401c	Creative NX
-spca505		041e:401d	Creative Webcam NX ULTRA
-zc3xx		041e:401e	Creative Nx Pro
-zc3xx		041e:401f	Creative Webcam Notebook PD1171
-pac207		041e:4028	Creative Webcam Vista Plus
-zc3xx		041e:4029	Creative WebCam Vista Pro
-zc3xx		041e:4034	Creative Instant P0620
-zc3xx		041e:4035	Creative Instant P0620D
-zc3xx		041e:4036	Creative Live !
-sq930x		041e:4038	Creative Joy-IT
-zc3xx		041e:403a	Creative Nx Pro 2
-spca561		041e:403b	Creative Webcam Vista (VF0010)
-sq930x		041e:403c	Creative Live! Ultra
-sq930x		041e:403d	Creative Live! Ultra for Notebooks
-sq930x		041e:4041	Creative Live! Motion
-zc3xx		041e:4051	Creative Live!Cam Notebook Pro (VF0250)
-ov519		041e:4052	Creative Live! VISTA IM
-zc3xx		041e:4053	Creative Live!Cam Video IM
-vc032x		041e:405b	Creative Live! Cam Notebook Ultra (VC0130)
-ov519		041e:405f	Creative Live! VISTA VF0330
-ov519		041e:4060	Creative Live! VISTA VF0350
-ov519		041e:4061	Creative Live! VISTA VF0400
-ov519		041e:4064	Creative Live! VISTA VF0420
-ov519		041e:4067	Creative Live! Cam Video IM (VF0350)
-ov519		041e:4068	Creative Live! VISTA VF0470
-spca561		0458:7004	Genius VideoCAM Express V2
-sn9c2028	0458:7005	Genius Smart 300, version 2
-sunplus		0458:7006	Genius Dsc 1.3 Smart
-zc3xx		0458:7007	Genius VideoCam V2
-zc3xx		0458:700c	Genius VideoCam V3
-zc3xx		0458:700f	Genius VideoCam Web V2
-sonixj		0458:7025	Genius Eye 311Q
-sn9c20x		0458:7029	Genius Look 320s
-sonixj		0458:702e	Genius Slim 310 NB
-sn9c20x		0458:7045	Genius Look 1320 V2
-sn9c20x		0458:704a	Genius Slim 1320
-sn9c20x		0458:704c	Genius i-Look 1321
-sn9c20x		045e:00f4	LifeCam VX-6000 (SN9C20x + OV9650)
-sonixj		045e:00f5	MicroSoft VX3000
-sonixj		045e:00f7	MicroSoft VX1000
-ov519		045e:028c	Micro$oft xbox cam
-spca508		0461:0815	Micro Innovation IC200
-sunplus		0461:0821	Fujifilm MV-1
-zc3xx		0461:0a00	MicroInnovation WebCam320
-stv06xx		046d:0840	QuickCam Express
-stv06xx		046d:0850	LEGO cam / QuickCam Web
-stv06xx		046d:0870	Dexxa WebCam USB
-spca500		046d:0890	Logitech QuickCam traveler
-vc032x		046d:0892	Logitech Orbicam
-vc032x		046d:0896	Logitech Orbicam
-vc032x		046d:0897	Logitech QuickCam for Dell notebooks
-zc3xx		046d:089d	Logitech QuickCam E2500
-zc3xx		046d:08a0	Logitech QC IM
-zc3xx		046d:08a1	Logitech QC IM 0x08A1 +sound
-zc3xx		046d:08a2	Labtec Webcam Pro
-zc3xx		046d:08a3	Logitech QC Chat
-zc3xx		046d:08a6	Logitech QCim
-zc3xx		046d:08a7	Logitech QuickCam Image
-zc3xx		046d:08a9	Logitech Notebook Deluxe
-zc3xx		046d:08aa	Labtec Webcam Notebook
-zc3xx		046d:08ac	Logitech QuickCam Cool
-zc3xx		046d:08ad	Logitech QCCommunicate STX
-zc3xx		046d:08ae	Logitech QuickCam for Notebooks
-zc3xx		046d:08af	Logitech QuickCam Cool
-zc3xx		046d:08b9	Logitech QuickCam Express
-zc3xx		046d:08d7	Logitech QCam STX
-zc3xx		046d:08d9	Logitech QuickCam IM/Connect
-zc3xx		046d:08d8	Logitech Notebook Deluxe
-zc3xx		046d:08da	Logitech QuickCam Messenger
-zc3xx		046d:08dd	Logitech QuickCam for Notebooks
-spca500		046d:0900	Logitech Inc. ClickSmart 310
-spca500		046d:0901	Logitech Inc. ClickSmart 510
-sunplus		046d:0905	Logitech ClickSmart 820
-tv8532		046d:0920	Logitech QuickCam Express
-tv8532		046d:0921	Labtec Webcam
-spca561		046d:0928	Logitech QC Express Etch2
-spca561		046d:0929	Labtec Webcam Elch2
-spca561		046d:092a	Logitech QC for Notebook
-spca561		046d:092b	Labtec Webcam Plus
-spca561		046d:092c	Logitech QC chat Elch2
-spca561		046d:092d	Logitech QC Elch2
-spca561		046d:092e	Logitech QC Elch2
-spca561		046d:092f	Logitech QuickCam Express Plus
-sunplus		046d:0960	Logitech ClickSmart 420
-nw80x		046d:d001	Logitech QuickCam Pro (dark focus ring)
-sunplus		0471:0322	Philips DMVC1300K
-zc3xx		0471:0325	Philips SPC 200 NC
-zc3xx		0471:0326	Philips SPC 300 NC
-sonixj		0471:0327	Philips SPC 600 NC
-sonixj		0471:0328	Philips SPC 700 NC
-zc3xx		0471:032d	Philips SPC 210 NC
-zc3xx		0471:032e	Philips SPC 315 NC
-sonixj		0471:0330	Philips SPC 710 NC
-spca501		0497:c001	Smile International
-sunplus		04a5:3003	Benq DC 1300
-sunplus		04a5:3008	Benq DC 1500
-sunplus		04a5:300a	Benq DC 3410
-spca500		04a5:300c	Benq DC 1016
-benq		04a5:3035	Benq DC E300
-finepix		04cb:0104	Fujifilm FinePix 4800
-finepix		04cb:0109	Fujifilm FinePix A202
-finepix		04cb:010b	Fujifilm FinePix A203
-finepix		04cb:010f	Fujifilm FinePix A204
-finepix		04cb:0111	Fujifilm FinePix A205
-finepix		04cb:0113	Fujifilm FinePix A210
-finepix		04cb:0115	Fujifilm FinePix A303
-finepix		04cb:0117	Fujifilm FinePix A310
-finepix		04cb:0119	Fujifilm FinePix F401
-finepix		04cb:011b	Fujifilm FinePix F402
-finepix		04cb:011d	Fujifilm FinePix F410
-finepix		04cb:0121	Fujifilm FinePix F601
-finepix		04cb:0123	Fujifilm FinePix F700
-finepix		04cb:0125	Fujifilm FinePix M603
-finepix		04cb:0127	Fujifilm FinePix S300
-finepix		04cb:0129	Fujifilm FinePix S304
-finepix		04cb:012b	Fujifilm FinePix S500
-finepix		04cb:012d	Fujifilm FinePix S602
-finepix		04cb:012f	Fujifilm FinePix S700
-finepix		04cb:0131	Fujifilm FinePix unknown model
-finepix		04cb:013b	Fujifilm FinePix unknown model
-finepix		04cb:013d	Fujifilm FinePix unknown model
-finepix		04cb:013f	Fujifilm FinePix F420
-sunplus		04f1:1001	JVC GC A50
-spca561		04fc:0561	Flexcam 100
-spca1528	04fc:1528	Sunplus MD80 clone
-sunplus		04fc:500c	Sunplus CA500C
-sunplus		04fc:504a	Aiptek Mini PenCam 1.3
-sunplus		04fc:504b	Maxell MaxPocket LE 1.3
-sunplus		04fc:5330	Digitrex 2110
-sunplus		04fc:5360	Sunplus Generic
-spca500		04fc:7333	PalmPixDC85
-sunplus		04fc:ffff	Pure DigitalDakota
-nw80x		0502:d001	DVC V6
-spca501		0506:00df	3Com HomeConnect Lite
-sunplus		052b:1507	Megapixel 5 Pretec DC-1007
-sunplus		052b:1513	Megapix V4
-sunplus		052b:1803	MegaImage VI
-nw80x		052b:d001	EZCam Pro p35u
-tv8532		0545:808b	Veo Stingray
-tv8532		0545:8333	Veo Stingray
-sunplus		0546:3155	Polaroid PDC3070
-sunplus		0546:3191	Polaroid Ion 80
-sunplus		0546:3273	Polaroid PDC2030
-ov519		054c:0154	Sonny toy4
-ov519		054c:0155	Sonny toy5
-cpia1		0553:0002	CPIA CPiA (version1) based cameras
-zc3xx		055f:c005	Mustek Wcam300A
-spca500		055f:c200	Mustek Gsmart 300
-sunplus		055f:c211	Kowa Bs888e Microcamera
-spca500		055f:c220	Gsmart Mini
-sunplus		055f:c230	Mustek Digicam 330K
-sunplus		055f:c232	Mustek MDC3500
-sunplus		055f:c360	Mustek DV4000 Mpeg4
-sunplus		055f:c420	Mustek gSmart Mini 2
-sunplus		055f:c430	Mustek Gsmart LCD 2
-sunplus		055f:c440	Mustek DV 3000
-sunplus		055f:c520	Mustek gSmart Mini 3
-sunplus		055f:c530	Mustek Gsmart LCD 3
-sunplus		055f:c540	Gsmart D30
-sunplus		055f:c630	Mustek MDC4000
-sunplus		055f:c650	Mustek MDC5500Z
-nw80x		055f:d001	Mustek Wcam 300 mini
-zc3xx		055f:d003	Mustek WCam300A
-zc3xx		055f:d004	Mustek WCam300 AN
-conex		0572:0041	Creative Notebook cx11646
-ov519		05a9:0511	Video Blaster WebCam 3/WebCam Plus, D-Link USB Digital Video Camera
-ov519		05a9:0518	Creative WebCam
-ov519		05a9:0519	OV519 Microphone
-ov519		05a9:0530	OmniVision
-ov534_9		05a9:1550	OmniVision VEHO Filmscanner
-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
-sunplus		05da:1018	Digital Dream Enigma 1.3
-stk014		05e1:0893	Syntek DV4000
-gl860		05e3:0503	Genesys Logic PC Camera
-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
-spca500		06bd:0404	Agfa CL20
-spca500		06be:0800	Optimedia
-nw80x		06be:d001	EZCam Pro p35u
-sunplus		06d6:0031	Trust 610 LCD PowerC@m Zoom
-spca506		06e1:a190	ADS Instant VCD
-ov534		06f8:3002	Hercules Blog Webcam
-ov534_9		06f8:3003	Hercules Dualpix HD Weblog
-sonixj		06f8:3004	Hercules Classic Silver
-sonixj		06f8:3008	Hercules Deluxe Optical Glass
-pac7302		06f8:3009	Hercules Classic Link
-pac7302		06f8:301b	Hercules Link
-nw80x		0728:d001	AVerMedia Camguard
-spca508		0733:0110	ViewQuest VQ110
-spca501		0733:0401	Intel Create and Share
-spca501		0733:0402	ViewQuest M318B
-spca505		0733:0430	Intel PC Camera Pro
-sunplus		0733:1311	Digital Dream Epsilon 1.3
-sunplus		0733:1314	Mercury 2.1MEG Deluxe Classic Cam
-sunplus		0733:2211	Jenoptik jdc 21 LCD
-sunplus		0733:2221	Mercury Digital Pro 3.1p
-sunplus		0733:3261	Concord 3045 spca536a
-sunplus		0733:3281	Cyberpix S550V
-spca506		0734:043b	3DeMon USB Capture aka
-cpia1		0813:0001	QX3 camera
-ov519		0813:0002	Dual Mode USB Camera Plus
-spca500		084d:0003	D-Link DSC-350
-spca500		08ca:0103	Aiptek PocketDV
-sunplus		08ca:0104	Aiptek PocketDVII 1.3
-sunplus		08ca:0106	Aiptek Pocket DV3100+
-mr97310a	08ca:0110	Trust Spyc@m 100
-mr97310a	08ca:0111	Aiptek PenCam VGA+
-sunplus		08ca:2008	Aiptek Mini PenCam 2 M
-sunplus		08ca:2010	Aiptek PocketCam 3M
-sunplus		08ca:2016	Aiptek PocketCam 2 Mega
-sunplus		08ca:2018	Aiptek Pencam SD 2M
-sunplus		08ca:2020	Aiptek Slim 3000F
-sunplus		08ca:2022	Aiptek Slim 3200
-sunplus		08ca:2024	Aiptek DV3500 Mpeg4
-sunplus		08ca:2028	Aiptek PocketCam4M
-sunplus		08ca:2040	Aiptek PocketDV4100M
-sunplus		08ca:2042	Aiptek PocketDV5100
-sunplus		08ca:2050	Medion MD 41437
-sunplus		08ca:2060	Aiptek PocketDV5300
-tv8532		0923:010f	ICM532 cams
-mars		093a:050f	Mars-Semi Pc-Camera
-mr97310a	093a:010e	All known CIF cams with this ID
-mr97310a	093a:010f	All known VGA cams with this ID
-pac207		093a:2460	Qtec Webcam 100
-pac207		093a:2461	HP Webcam
-pac207		093a:2463	Philips SPC 220 NC
-pac207		093a:2464	Labtec Webcam 1200
-pac207		093a:2468	Webcam WB-1400T
-pac207		093a:2470	Genius GF112
-pac207		093a:2471	Genius VideoCam ge111
-pac207		093a:2472	Genius VideoCam ge110
-pac207		093a:2474	Genius iLook 111
-pac207		093a:2476	Genius e-Messenger 112
-pac7311		093a:2600	PAC7311 Typhoon
-pac7311		093a:2601	Philips SPC 610 NC
-pac7311		093a:2603	Philips SPC 500 NC
-pac7311		093a:2608	Trust WB-3300p
-pac7311		093a:260e	Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
-pac7311		093a:260f	SnakeCam
-pac7302		093a:2620	Apollo AC-905
-pac7302		093a:2621	PAC731x
-pac7302		093a:2622	Genius Eye 312
-pac7302		093a:2624	PAC7302
-pac7302		093a:2625	Genius iSlim 310
-pac7302		093a:2626	Labtec 2200
-pac7302		093a:2627	Genius FaceCam 300
-pac7302		093a:2628	Genius iLook 300
-pac7302		093a:2629	Genious iSlim 300
-pac7302		093a:262a	Webcam 300k
-pac7302		093a:262c	Philips SPC 230 NC
-jl2005bcd	0979:0227	Various brands, 19 known cameras supported
-jeilinj		0979:0280	Sakar 57379
-jeilinj		0979:0280	Sportscam DV15
-zc3xx		0ac8:0302	Z-star Vimicro zc0302
-vc032x		0ac8:0321	Vimicro generic vc0321
-vc032x		0ac8:0323	Vimicro Vc0323
-vc032x		0ac8:0328	A4Tech PK-130MG
-zc3xx		0ac8:301b	Z-Star zc301b
-zc3xx		0ac8:303b	Vimicro 0x303b
-zc3xx		0ac8:305b	Z-star Vimicro zc0305b
-zc3xx		0ac8:307b	PC Camera (ZS0211)
-vc032x		0ac8:c001	Sony embedded vimicro
-vc032x		0ac8:c002	Sony embedded vimicro
-vc032x		0ac8:c301	Samsung Q1 Ultra Premium
-spca508		0af9:0010	Hama USB Sightcam 100
-spca508		0af9:0011	Hama USB Sightcam 100
-ov519		0b62:0059	iBOT2 Webcam
-sonixb		0c45:6001	Genius VideoCAM NB
-sonixb		0c45:6005	Microdia Sweex Mini Webcam
-sonixb		0c45:6007	Sonix sn9c101 + Tas5110D
-sonixb		0c45:6009	spcaCam@120
-sonixb		0c45:600d	spcaCam@120
-sonixb		0c45:6011	Microdia PC Camera (SN9C102)
-sonixb		0c45:6019	Generic Sonix OV7630
-sonixb		0c45:6024	Generic Sonix Tas5130c
-sonixb		0c45:6025	Xcam Shanga
-sonixb		0c45:6028	Sonix Btc Pc380
-sonixb		0c45:6029	spcaCam@150
-sonixb		0c45:602c	Generic Sonix OV7630
-sonixb		0c45:602d	LIC-200 LG
-sonixb		0c45:602e	Genius VideoCam Messenger
-sonixj		0c45:6040	Speed NVC 350K
-sonixj		0c45:607c	Sonix sn9c102p Hv7131R
-sonixj		0c45:60c0	Sangha Sn535
-sonixj		0c45:60ce	USB-PC-Camera-168 (TALK-5067)
-sonixj		0c45:60ec	SN9C105+MO4000
-sonixj		0c45:60fb	Surfer NoName
-sonixj		0c45:60fc	LG-LIC300
-sonixj		0c45:60fe	Microdia Audio
-sonixj		0c45:6100	PC Camera (SN9C128)
-sonixj		0c45:6102	PC Camera (SN9C128)
-sonixj		0c45:610a	PC Camera (SN9C128)
-sonixj		0c45:610b	PC Camera (SN9C128)
-sonixj		0c45:610c	PC Camera (SN9C128)
-sonixj		0c45:610e	PC Camera (SN9C128)
-sonixj		0c45:6128	Microdia/Sonix SNP325
-sonixj		0c45:612a	Avant Camera
-sonixj		0c45:612b	Speed-Link REFLECT2
-sonixj		0c45:612c	Typhoon Rasy Cam 1.3MPix
-sonixj		0c45:6130	Sonix Pccam
-sonixj		0c45:6138	Sn9c120 Mo4000
-sonixj		0c45:613a	Microdia Sonix PC Camera
-sonixj		0c45:613b	Surfer SN-206
-sonixj		0c45:613c	Sonix Pccam168
-sonixj		0c45:6142	Hama PC-Webcam AC-150
-sonixj		0c45:6143	Sonix Pccam168
-sonixj		0c45:6148	Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia
-sonixj		0c45:614a	Frontech E-Ccam (JIL-2225)
-sn9c20x		0c45:6240	PC Camera (SN9C201 + MT9M001)
-sn9c20x		0c45:6242	PC Camera (SN9C201 + MT9M111)
-sn9c20x		0c45:6248	PC Camera (SN9C201 + OV9655)
-sn9c20x		0c45:624c	PC Camera (SN9C201 + MT9M112)
-sn9c20x		0c45:624e	PC Camera (SN9C201 + SOI968)
-sn9c20x		0c45:624f	PC Camera (SN9C201 + OV9650)
-sn9c20x		0c45:6251	PC Camera (SN9C201 + OV9650)
-sn9c20x		0c45:6253	PC Camera (SN9C201 + OV9650)
-sn9c20x		0c45:6260	PC Camera (SN9C201 + OV7670)
-sn9c20x		0c45:6270	PC Camera (SN9C201 + MT9V011/MT9V111/MT9V112)
-sn9c20x		0c45:627b	PC Camera (SN9C201 + OV7660)
-sn9c20x		0c45:627c	PC Camera (SN9C201 + HV7131R)
-sn9c20x		0c45:627f	PC Camera (SN9C201 + OV9650)
-sn9c20x		0c45:6280	PC Camera (SN9C202 + MT9M001)
-sn9c20x		0c45:6282	PC Camera (SN9C202 + MT9M111)
-sn9c20x		0c45:6288	PC Camera (SN9C202 + OV9655)
-sn9c20x		0c45:628c	PC Camera (SN9C201 + MT9M112)
-sn9c20x		0c45:628e	PC Camera (SN9C202 + SOI968)
-sn9c20x		0c45:628f	PC Camera (SN9C202 + OV9650)
-sn9c20x		0c45:62a0	PC Camera (SN9C202 + OV7670)
-sn9c20x		0c45:62b0	PC Camera (SN9C202 + MT9V011/MT9V111/MT9V112)
-sn9c20x		0c45:62b3	PC Camera (SN9C202 + OV9655)
-sn9c20x		0c45:62bb	PC Camera (SN9C202 + OV7660)
-sn9c20x		0c45:62bc	PC Camera (SN9C202 + HV7131R)
-sn9c2028	0c45:8001	Wild Planet Digital Spy Camera
-sn9c2028	0c45:8003	Sakar #11199, #6637x, #67480 keychain cams
-sn9c2028	0c45:8008	Mini-Shotz ms-350
-sn9c2028	0c45:800a	Vivitar Vivicam 3350B
-sunplus		0d64:0303	Sunplus FashionCam DXG
-ov519		0e96:c001	TRUST 380 USB2 SPACEC@M
-etoms		102c:6151	Qcam Sangha CIF
-etoms		102c:6251	Qcam xxxxxx VGA
-ov519		1046:9967	W9967CF/W9968CF WebCam IC, Video Blaster WebCam Go
-zc3xx		10fd:0128	Typhoon Webshot II USB 300k 0x0128
-spca561		10fd:7e50	FlyCam Usb 100
-zc3xx		10fd:8050	Typhoon Webshot II USB 300k
-ov534		1415:2000	Sony HD Eye for PS3 (SLEH 00201)
-pac207		145f:013a	Trust WB-1300N
-sn9c20x		145f:013d	Trust WB-3600R
-vc032x		15b8:6001	HP 2.0 Megapixel
-vc032x		15b8:6002	HP 2.0 Megapixel rz406aa
-spca501		1776:501c	Arowana 300K CMOS Camera
-t613		17a1:0128	TASCORP JPEG Webcam, NGS Cyclops
-vc032x		17ef:4802	Lenovo Vc0323+MI1310_SOC
-pac207		2001:f115	D-Link DSB-C120
-sq905c		2770:9050	Disney pix micro (CIF)
-sq905c		2770:9051	Lego Bionicle
-sq905c		2770:9052	Disney pix micro 2 (VGA)
-sq905c		2770:905c	All 11 known cameras with this ID
-sq905		2770:9120	All 24 known cameras with this ID
-sq905c		2770:913d	All 4 known cameras with this ID
-sq930x		2770:930b	Sweex Motion Tracking / I-Tec iCam Tracer
-sq930x		2770:930c	Trust WB-3500T / NSG Robbie 2.0
-spca500		2899:012c	Toptro Industrial
-ov519		8020:ef04	ov519
-spca508		8086:0110	Intel Easy PC Camera
-spca500		8086:0630	Intel Pocket PC Camera
-spca506		99fa:8988	Grandtec V.cap
-sn9c20x		a168:0610	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
-sn9c20x		a168:0611	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
-sn9c20x		a168:0613	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
-sn9c20x		a168:0618	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
-sn9c20x		a168:0614	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
-sn9c20x		a168:0615	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
-sn9c20x		a168:0617	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
-spca561		abcd:cdee	Petcam
-=========	=========	====================================================================
+=========	=========	===================================================================
+spca501         0000:0000	MystFromOri Unknown Camera
+spca508         0130:0130	Clone Digital Webcam 11043
+se401           03e8:0004	Endpoints/AoxSE401
+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
+zc3xx           041e:041e	Creative WebCam Live!
+ov519           041e:4003	Video Blaster WebCam Go Plus
+stv0680         041e:4007	Go Mini
+spca500         041e:400a	Creative PC-CAM 300
+sunplus         041e:400b	Creative PC-CAM 600
+sunplus         041e:4012	PC-Cam350
+sunplus         041e:4013	Creative Pccam750
+zc3xx           041e:4017	Creative Webcam Mobile PD1090
+spca508         041e:4018	Creative Webcam Vista (PD1100)
+spca561         041e:401a	Creative Webcam Vista (PD1100)
+zc3xx           041e:401c	Creative NX
+spca505         041e:401d	Creative Webcam NX ULTRA
+zc3xx           041e:401e	Creative Nx Pro
+zc3xx           041e:401f	Creative Webcam Notebook PD1171
+zc3xx           041e:4022	Webcam NX Pro
+pac207          041e:4028	Creative Webcam Vista Plus
+zc3xx           041e:4029	Creative WebCam Vista Pro
+zc3xx           041e:4034	Creative Instant P0620
+zc3xx           041e:4035	Creative Instant P0620D
+zc3xx           041e:4036	Creative Live !
+sq930x          041e:4038	Creative Joy-IT
+zc3xx           041e:403a	Creative Nx Pro 2
+spca561         041e:403b	Creative Webcam Vista (VF0010)
+sq930x          041e:403c	Creative Live! Ultra
+sq930x          041e:403d	Creative Live! Ultra for Notebooks
+sq930x          041e:4041	Creative Live! Motion
+zc3xx           041e:4051	Creative Live!Cam Notebook Pro (VF0250)
+ov519           041e:4052	Creative Live! VISTA IM
+zc3xx           041e:4053	Creative Live!Cam Video IM
+vc032x          041e:405b	Creative Live! Cam Notebook Ultra (VC0130)
+ov519           041e:405f	Creative Live! VISTA VF0330
+ov519           041e:4060	Creative Live! VISTA VF0350
+ov519           041e:4061	Creative Live! VISTA VF0400
+ov519           041e:4064	Creative Live! VISTA VF0420
+ov519           041e:4067	Creative Live! Cam Video IM (VF0350)
+ov519           041e:4068	Creative Live! VISTA VF0470
+sn9c2028        0458:7003	GeniusVideocam Live v2
+spca561         0458:7004	Genius VideoCAM Express V2
+sn9c2028        0458:7005	Genius Smart 300, version 2
+sunplus         0458:7006	Genius Dsc 1.3 Smart
+zc3xx           0458:7007	Genius VideoCam V2
+zc3xx           0458:700c	Genius VideoCam V3
+zc3xx           0458:700f	Genius VideoCam Web V2
+sonixj          0458:7025	Genius Eye 311Q
+sn9c20x         0458:7029	Genius Look 320s
+sonixj          0458:702e	Genius Slim 310 NB
+sn9c20x         0458:7045	Genius Look 1320 V2
+sn9c20x         0458:704a	Genius Slim 1320
+sn9c20x         0458:704c	Genius i-Look 1321
+sn9c20x         045e:00f4	LifeCam VX-6000 (SN9C20x + OV9650)
+sonixj          045e:00f5	MicroSoft VX3000
+sonixj          045e:00f7	MicroSoft VX1000
+ov519           045e:028c	Micro$oft xbox cam
+kinect          045e:02ae	Xbox NUI Camera
+kinect          045e:02bf	Kinect for Windows NUI Camera
+spca561         0461:0815	Micro Innovations IC200 Webcam
+sunplus         0461:0821	Fujifilm MV-1
+zc3xx           0461:0a00	MicroInnovation WebCam320
+stv06xx         046D:08F0	QuickCamMessenger
+stv06xx         046D:08F5	QuickCamCommunicate
+stv06xx         046D:08F6	QuickCamMessenger (new)
+stv06xx         046d:0840	QuickCamExpress
+stv06xx         046d:0850	LEGOcam / QuickCam Web
+stv06xx         046d:0870	DexxaWebCam USB
+spca500         046d:0890	Logitech QuickCam traveler
+vc032x          046d:0892	Logitech Orbicam
+vc032x          046d:0896	Logitech Orbicam
+vc032x          046d:0897	Logitech QuickCam for Dell notebooks
+zc3xx           046d:089d	Logitech QuickCam E2500
+zc3xx           046d:08a0	Logitech QC IM
+zc3xx           046d:08a1	Logitech QC IM 0x08A1 +sound
+zc3xx           046d:08a2	Labtec Webcam Pro
+zc3xx           046d:08a3	Logitech QC Chat
+zc3xx           046d:08a6	Logitech QCim
+zc3xx           046d:08a7	Logitech QuickCam Image
+zc3xx           046d:08a9	Logitech Notebook Deluxe
+zc3xx           046d:08aa	Labtec Webcam Notebook
+zc3xx           046d:08ac	Logitech QuickCam Cool
+zc3xx           046d:08ad	Logitech QCCommunicate STX
+zc3xx           046d:08ae	Logitech QuickCam for Notebooks
+zc3xx           046d:08af	Logitech QuickCam Cool
+zc3xx           046d:08b9	Logitech QuickCam Express
+zc3xx           046d:08d7	Logitech QCam STX
+zc3xx           046d:08d8	Logitech Notebook Deluxe
+zc3xx           046d:08d9	Logitech QuickCam IM/Connect
+zc3xx           046d:08da	Logitech QuickCam Messenger
+zc3xx           046d:08dd	Logitech QuickCam for Notebooks
+spca500         046d:0900	Logitech Inc. ClickSmart 310
+spca500         046d:0901	Logitech Inc. ClickSmart 510
+sunplus         046d:0905	Logitech ClickSmart 820
+tv8532          046d:0920	Logitech QuickCam Express
+tv8532          046d:0921	Labtec Webcam
+spca561         046d:0928	Logitech QC Express Etch2
+spca561         046d:0929	Labtec Webcam Elch2
+spca561         046d:092a	Logitech QC for Notebook
+spca561         046d:092b	Labtec Webcam Plus
+spca561         046d:092c	Logitech QC chat Elch2
+spca561         046d:092d	Logitech QC Elch2
+spca561         046d:092e	Logitech QC Elch2
+spca561         046d:092f	Logitech QuickCam Express Plus
+sunplus         046d:0960	Logitech ClickSmart 420
+nw80x           046d:d001	Logitech QuickCam Pro (dark focus ring)
+se401           0471:030b	PhilipsPCVC665K
+sunplus         0471:0322	Philips DMVC1300K
+zc3xx           0471:0325	Philips SPC 200 NC
+zc3xx           0471:0326	Philips SPC 300 NC
+sonixj          0471:0327	Philips SPC 600 NC
+sonixj          0471:0328	Philips SPC 700 NC
+zc3xx           0471:032d	Philips SPC 210 NC
+zc3xx           0471:032e	Philips SPC 315 NC
+sonixj          0471:0330	Philips SPC 710 NC
+se401           047d:5001	Kensington67014
+se401           047d:5002	Kensington6701(5/7)
+se401           047d:5003	Kensington67016
+spca501         0497:c001	Smile International
+sunplus         04a5:3003	Benq DC 1300
+sunplus         04a5:3008	Benq DC 1500
+sunplus         04a5:300a	Benq DC 3410
+spca500         04a5:300c	Benq DC 1016
+benq            04a5:3035	Benq DC E300
+vicam           04c1:009d	HomeConnect Webcam [vicam]
+konica          04c8:0720	IntelYC 76
+finepix         04cb:0104	Fujifilm FinePix 4800
+finepix         04cb:0109	Fujifilm FinePix A202
+finepix         04cb:010b	Fujifilm FinePix A203
+finepix         04cb:010f	Fujifilm FinePix A204
+finepix         04cb:0111	Fujifilm FinePix A205
+finepix         04cb:0113	Fujifilm FinePix A210
+finepix         04cb:0115	Fujifilm FinePix A303
+finepix         04cb:0117	Fujifilm FinePix A310
+finepix         04cb:0119	Fujifilm FinePix F401
+finepix         04cb:011b	Fujifilm FinePix F402
+finepix         04cb:011d	Fujifilm FinePix F410
+finepix         04cb:0121	Fujifilm FinePix F601
+finepix         04cb:0123	Fujifilm FinePix F700
+finepix         04cb:0125	Fujifilm FinePix M603
+finepix         04cb:0127	Fujifilm FinePix S300
+finepix         04cb:0129	Fujifilm FinePix S304
+finepix         04cb:012b	Fujifilm FinePix S500
+finepix         04cb:012d	Fujifilm FinePix S602
+finepix         04cb:012f	Fujifilm FinePix S700
+finepix         04cb:0131	Fujifilm FinePix unknown model
+finepix         04cb:013b	Fujifilm FinePix unknown model
+finepix         04cb:013d	Fujifilm FinePix unknown model
+finepix         04cb:013f	Fujifilm FinePix F420
+sunplus         04f1:1001	JVC GC A50
+spca561         04fc:0561	Flexcam 100
+spca1528        04fc:1528	Sunplus MD80 clone
+sunplus         04fc:500c	Sunplus CA500C
+sunplus         04fc:504a	Aiptek Mini PenCam 1.3
+sunplus         04fc:504b	Maxell MaxPocket LE 1.3
+sunplus         04fc:5330	Digitrex 2110
+sunplus         04fc:5360	Sunplus Generic
+spca500         04fc:7333	PalmPixDC85
+sunplus         04fc:ffff	Pure DigitalDakota
+nw80x           0502:d001	DVC V6
+spca501         0506:00df	3Com HomeConnect Lite
+sunplus         052b:1507	Megapixel 5 Pretec DC-1007
+sunplus         052b:1513	Megapix V4
+sunplus         052b:1803	MegaImage VI
+nw80x           052b:d001	EZCam Pro p35u
+tv8532          0545:808b	Veo Stingray
+tv8532          0545:8333	Veo Stingray
+sunplus         0546:3155	Polaroid PDC3070
+sunplus         0546:3191	Polaroid Ion 80
+sunplus         0546:3273	Polaroid PDC2030
+touptek         0547:6801	TTUCMOS08000KPB, AS MU800
+dtcs033         0547:7303	Anchor Chips, Inc
+ov519           054c:0154	Sonny toy4
+ov519           054c:0155	Sonny toy5
+cpia1           0553:0002	CPIA CPiA (version1) based cameras
+stv0680         0553:0202	STV0680 Camera
+zc3xx           055f:c005	Mustek Wcam300A
+spca500         055f:c200	Mustek Gsmart 300
+sunplus         055f:c211	Kowa Bs888e Microcamera
+spca500         055f:c220	Gsmart Mini
+sunplus         055f:c230	Mustek Digicam 330K
+sunplus         055f:c232	Mustek MDC3500
+sunplus         055f:c360	Mustek DV4000 Mpeg4
+sunplus         055f:c420	Mustek gSmart Mini 2
+sunplus         055f:c430	Mustek Gsmart LCD 2
+sunplus         055f:c440	Mustek DV 3000
+sunplus         055f:c520	Mustek gSmart Mini 3
+sunplus         055f:c530	Mustek Gsmart LCD 3
+sunplus         055f:c540	Gsmart D30
+sunplus         055f:c630	Mustek MDC4000
+sunplus         055f:c650	Mustek MDC5500Z
+nw80x           055f:d001	Mustek Wcam 300 mini
+zc3xx           055f:d003	Mustek WCam300A
+zc3xx           055f:d004	Mustek WCam300 AN
+conex           0572:0041	Creative Notebook cx11646
+ov519           05a9:0511	Video Blaster WebCam 3/WebCam Plus, D-Link USB Digital Video Camera
+ov519           05a9:0518	Creative WebCam
+ov519           05a9:0519	OV519 Microphone
+ov519           05a9:0530	OmniVision
+ov534_9         05a9:1550	OmniVision VEHO Filmscanner
+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
+sunplus         05da:1018	Digital Dream Enigma 1.3
+stk014          05e1:0893	Syntek DV4000
+gl860           05e3:0503	Genesys Logic PC Camera
+gl860           05e3:f191	Genesys Logic PC Camera
+vicam           0602:1001	ViCam Webcam
+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
+spca500         06bd:0404	Agfa CL20
+spca500         06be:0800	Optimedia
+nw80x           06be:d001	EZCam Pro p35u
+sunplus         06d6:0031	Trust 610 LCD PowerC@m Zoom
+sunplus         06d6:0041	Aashima Technology B.V.
+spca506         06e1:a190	ADS Instant VCD
+ov534           06f8:3002	Hercules Blog Webcam
+ov534_9         06f8:3003	Hercules Dualpix HD Weblog
+sonixj          06f8:3004	Hercules Classic Silver
+sonixj          06f8:3008	Hercules Deluxe Optical Glass
+pac7302         06f8:3009	Hercules Classic Link
+pac7302         06f8:301b	Hercules Link
+nw80x           0728:d001	AVerMedia Camguard
+spca508         0733:0110	ViewQuest VQ110
+spca501         0733:0401	Intel Create and Share
+spca501         0733:0402	ViewQuest M318B
+spca505         0733:0430	Intel PC Camera Pro
+sunplus         0733:1311	Digital Dream Epsilon 1.3
+sunplus         0733:1314	Mercury 2.1MEG Deluxe Classic Cam
+sunplus         0733:2211	Jenoptik jdc 21 LCD
+sunplus         0733:2221	Mercury Digital Pro 3.1p
+sunplus         0733:3261	Concord 3045 spca536a
+sunplus         0733:3281	Cyberpix S550V
+spca506         0734:043b	3DeMon USB Capture aka
+cpia1           0813:0001	QX3 camera
+ov519           0813:0002	Dual Mode USB Camera Plus
+spca500         084d:0003	D-Link DSC-350
+spca500         08ca:0103	Aiptek PocketDV
+sunplus         08ca:0104	Aiptek PocketDVII 1.3
+sunplus         08ca:0106	Aiptek Pocket DV3100+
+mr97310a        08ca:0110	Trust Spyc@m 100
+mr97310a        08ca:0111	Aiptek PenCam VGA+
+sunplus         08ca:2008	Aiptek Mini PenCam 2 M
+sunplus         08ca:2010	Aiptek PocketCam 3M
+sunplus         08ca:2016	Aiptek PocketCam 2 Mega
+sunplus         08ca:2018	Aiptek Pencam SD 2M
+sunplus         08ca:2020	Aiptek Slim 3000F
+sunplus         08ca:2022	Aiptek Slim 3200
+sunplus         08ca:2024	Aiptek DV3500 Mpeg4
+sunplus         08ca:2028	Aiptek PocketCam4M
+sunplus         08ca:2040	Aiptek PocketDV4100M
+sunplus         08ca:2042	Aiptek PocketDV5100
+sunplus         08ca:2050	Medion MD 41437
+sunplus         08ca:2060	Aiptek PocketDV5300
+tv8532          0923:010f	ICM532 cams
+mr97310a        093a:010e	All known CIF cams with this ID
+mr97310a        093a:010f	All known VGA cams with this ID
+mars            093a:050f	Mars-Semi Pc-Camera
+pac207          093a:2460	Qtec Webcam 100
+pac207          093a:2461	HP Webcam
+pac207          093a:2463	Philips SPC 220 NC
+pac207          093a:2464	Labtec Webcam 1200
+pac207          093a:2468	Webcam WB-1400T
+pac207          093a:2470	Genius GF112
+pac207          093a:2471	Genius VideoCam ge111
+pac207          093a:2472	Genius VideoCam ge110
+pac207          093a:2474	Genius iLook 111
+pac207          093a:2476	Genius e-Messenger 112
+pac7311         093a:2600	PAC7311 Typhoon
+pac7311         093a:2601	Philips SPC 610 NC
+pac7311         093a:2603	Philips SPC 500 NC
+pac7311         093a:2608	Trust WB-3300p
+pac7311         093a:260e	Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
+pac7311         093a:260f	SnakeCam
+pac7302         093a:2620	Apollo AC-905
+pac7302         093a:2621	PAC731x
+pac7302         093a:2622	Genius Eye 312
+pac7302         093a:2623	Pixart Imaging, Inc.
+pac7302         093a:2624	PAC7302
+pac7302         093a:2625	Genius iSlim 310
+pac7302         093a:2626	Labtec 2200
+pac7302         093a:2627	Genius FaceCam 300
+pac7302         093a:2628	Genius iLook 300
+pac7302         093a:2629	Genious iSlim 300
+pac7302         093a:262a	Webcam 300k
+pac7302         093a:262c	Philips SPC 230 NC
+jl2005bcd       0979:0227	Various brands, 19 known cameras supported
+jeilinj         0979:0270	Sakar 57379
+jeilinj         0979:0280	Sportscam DV15, Sakar 57379
+zc3xx           0ac8:0301	Web Camera
+zc3xx           0ac8:0302	Z-star Vimicro zc0302
+vc032x          0ac8:0321	Vimicro generic vc0321
+vc032x          0ac8:0323	Vimicro Vc0323
+vc032x          0ac8:0328	A4Tech PK-130MG
+zc3xx           0ac8:301b	Z-Star zc301b
+zc3xx           0ac8:303b	Vimicro 0x303b
+zc3xx           0ac8:305b	Z-star Vimicro zc0305b
+zc3xx           0ac8:307b	PC Camera (ZS0211)
+vc032x          0ac8:c001	Sony embedded vimicro
+vc032x          0ac8:c002	Sony embedded vimicro
+vc032x          0ac8:c301	Samsung Q1 Ultra Premium
+spca508         0af9:0010	Hama USB Sightcam 100
+spca508         0af9:0011	Hama USB Sightcam 100
+ov519           0b62:0059	iBOT2 Webcam
+sonixb          0c45:6001	Genius VideoCAM NB
+sonixb          0c45:6005	Microdia Sweex Mini Webcam
+sonixb          0c45:6007	Sonix sn9c101 + Tas5110D
+sonixb          0c45:6009	spcaCam@120
+sonixb          0c45:600d	spcaCam@120
+sonixb          0c45:6011	Microdia PC Camera (SN9C102)
+sonixb          0c45:6019	Generic Sonix OV7630
+sonixb          0c45:6024	Generic Sonix Tas5130c
+sonixb          0c45:6025	Xcam Shanga
+sonixb          0c45:6027	GeniusEye 310
+sonixb          0c45:6028	Sonix Btc Pc380
+sonixb          0c45:6029	spcaCam@150
+sonixb          0c45:602a	Meade ETX-105EC Camera
+sonixb          0c45:602c	Generic Sonix OV7630
+sonixb          0c45:602d	LIC-200 LG
+sonixb          0c45:602e	Genius VideoCam Messenger
+sonixj          0c45:6040	Speed NVC 350K
+sonixj          0c45:607c	Sonix sn9c102p Hv7131R
+sonixb          0c45:6083	VideoCAM Look
+sonixb          0c45:608c	VideoCAM Look
+sonixb          0c45:608f	PC Camera (SN9C103 + OV7630)
+sonixb          0c45:60a8	VideoCAM Look
+sonixb          0c45:60aa	VideoCAM Look
+sonixb          0c45:60af	VideoCAM Look
+sonixb          0c45:60b0	Genius VideoCam Look
+sonixj          0c45:60c0	Sangha Sn535
+sonixj          0c45:60ce	USB-PC-Camera-168 (TALK-5067)
+sonixj          0c45:60ec	SN9C105+MO4000
+sonixj          0c45:60fb	Surfer NoName
+sonixj          0c45:60fc	LG-LIC300
+sonixj          0c45:60fe	Microdia Audio
+sonixj          0c45:6100	PC Camera (SN9C128)
+sonixj          0c45:6102	PC Camera (SN9C128)
+sonixj          0c45:610a	PC Camera (SN9C128)
+sonixj          0c45:610b	PC Camera (SN9C128)
+sonixj          0c45:610c	PC Camera (SN9C128)
+sonixj          0c45:610e	PC Camera (SN9C128)
+sonixj          0c45:6128	Microdia/Sonix SNP325
+sonixj          0c45:612a	Avant Camera
+sonixj          0c45:612b	Speed-Link REFLECT2
+sonixj          0c45:612c	Typhoon Rasy Cam 1.3MPix
+sonixj          0c45:612e	PC Camera (SN9C110)
+sonixj          0c45:6130	Sonix Pccam
+sonixj          0c45:6138	Sn9c120 Mo4000
+sonixj          0c45:613a	Microdia Sonix PC Camera
+sonixj          0c45:613b	Surfer SN-206
+sonixj          0c45:613c	Sonix Pccam168
+sonixj          0c45:613e	PC Camera (SN9C120)
+sonixj          0c45:6142	Hama PC-Webcam AC-150
+sonixj          0c45:6143	Sonix Pccam168
+sonixj          0c45:6148	Digitus DA-70811/ZSMC USB PC Camera ZS211/Microdia
+sonixj          0c45:614a	Frontech E-Ccam (JIL-2225)
+sn9c20x         0c45:6240	PC Camera (SN9C201 + MT9M001)
+sn9c20x         0c45:6242	PC Camera (SN9C201 + MT9M111)
+sn9c20x         0c45:6248	PC Camera (SN9C201 + OV9655)
+sn9c20x         0c45:624c	PC Camera (SN9C201 + MT9M112)
+sn9c20x         0c45:624e	PC Camera (SN9C201 + SOI968)
+sn9c20x         0c45:624f	PC Camera (SN9C201 + OV9650)
+sn9c20x         0c45:6251	PC Camera (SN9C201 + OV9650)
+sn9c20x         0c45:6253	PC Camera (SN9C201 + OV9650)
+sn9c20x         0c45:6260	PC Camera (SN9C201 + OV7670)
+sn9c20x         0c45:6270	PC Camera (SN9C201 + MT9V011/MT9V111/MT9V112)
+sn9c20x         0c45:627b	PC Camera (SN9C201 + OV7660)
+sn9c20x         0c45:627c	PC Camera (SN9C201 + HV7131R)
+sn9c20x         0c45:627f	PC Camera (SN9C201 + OV9650)
+sn9c20x         0c45:6280	PC Camera (SN9C202 + MT9M001)
+sn9c20x         0c45:6282	PC Camera (SN9C202 + MT9M111)
+sn9c20x         0c45:6288	PC Camera (SN9C202 + OV9655)
+sn9c20x         0c45:628c	PC Camera (SN9C201 + MT9M112)
+sn9c20x         0c45:628e	PC Camera (SN9C202 + SOI968)
+sn9c20x         0c45:628f	PC Camera (SN9C202 + OV9650)
+sn9c20x         0c45:62a0	PC Camera (SN9C202 + OV7670)
+sn9c20x         0c45:62b0	PC Camera (SN9C202 + MT9V011/MT9V111/MT9V112)
+sn9c20x         0c45:62b3	PC Camera (SN9C202 + OV9655)
+sn9c20x         0c45:62bb	PC Camera (SN9C202 + OV7660)
+sn9c20x         0c45:62bc	PC Camera (SN9C202 + HV7131R)
+sn9c2028        0c45:8001	Wild Planet Digital Spy Camera
+sn9c2028        0c45:8003	Sakar #11199, #6637x, #67480 keychain cams
+sn9c2028        0c45:8008	Mini-Shotz ms-350
+sn9c2028        0c45:800a	Vivitar Vivicam 3350B
+sunplus         0d64:0303	Sunplus FashionCam DXG
+ov519           0e96:c001	TRUST 380 USB2 SPACEC@M
+etoms           102c:6151	Qcam Sangha CIF
+etoms           102c:6251	Qcam xxxxxx VGA
+ov519           1046:9967	W9967CF/W9968CF WebCam IC, Video Blaster WebCam Go
+zc3xx           10fd:0128	Typhoon Webshot II USB 300k 0x0128
+spca561         10fd:7e50	FlyCam Usb 100
+zc3xx           10fd:804d	Typhoon Webshot II Webcam [zc0301]
+zc3xx           10fd:8050	Typhoon Webshot II USB 300k
+ov534           1415:2000	Sony HD Eye for PS3 (SLEH 00201)
+pac207          145f:013a	Trust WB-1300N
+pac7302         145f:013c	Trust
+sn9c20x         145f:013d	Trust WB-3600R
+vc032x          15b8:6001	HP 2.0 Megapixel
+vc032x          15b8:6002	HP 2.0 Megapixel rz406aa
+stk1135         174f:6a31	ASUSlaptop, MT9M112 sensor
+spca501         1776:501c	Arowana 300K CMOS Camera
+t613            17a1:0128	TASCORP JPEG Webcam, NGS Cyclops
+vc032x          17ef:4802	Lenovo Vc0323+MI1310_SOC
+pac7302         1ae7:2001	SpeedLinkSnappy Mic SL-6825-SBK
+pac207          2001:f115	D-Link DSB-C120
+sq905c          2770:9050	Disney pix micro (CIF)
+sq905c          2770:9051	Lego Bionicle
+sq905c          2770:9052	Disney pix micro 2 (VGA)
+sq905c          2770:905c	All 11 known cameras with this ID
+sq905           2770:9120	All 24 known cameras with this ID
+sq905c          2770:913d	All 4 known cameras with this ID
+sq930x          2770:930b	Sweex Motion Tracking / I-Tec iCam Tracer
+sq930x          2770:930c	Trust WB-3500T / NSG Robbie 2.0
+spca500         2899:012c	Toptro Industrial
+ov519           8020:ef04	ov519
+spca508         8086:0110	Intel Easy PC Camera
+spca500         8086:0630	Intel Pocket PC Camera
+spca506         99fa:8988	Grandtec V.cap
+sn9c20x         a168:0610	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x         a168:0611	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x         a168:0613	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+sn9c20x         a168:0614	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
+sn9c20x         a168:0615	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
+sn9c20x         a168:0617	Dino-Lite Digital Microscope (SN9C201 + MT9M111)
+sn9c20x         a168:0618	Dino-Lite Digital Microscope (SN9C201 + HV7131R)
+spca561         abcd:cdee	Petcam
+=========	=========	===================================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/index.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/index.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/index.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,8 @@
 
 .. include:: <isonum.txt>
 
+.. _v4l-drivers:
+
 ################################################
 Video4Linux (V4L)  driver-specific documentation
 ################################################
@@ -46,6 +48,7 @@ For more details see the file COPYING in
 	pvrusb2
 	pxa_camera
 	radiotrack
+	rcar-fdp1
 	saa7134
 	sh_mobile_ceu_camera
 	si470x
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/ivtv-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/ivtv-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/ivtv-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/ivtv-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,29 +1,38 @@
 IVTV cards list
 ===============
 
-.. code-block:: none
-
-	 1 -> Hauppauge WinTV PVR-250
-	 2 -> Hauppauge WinTV PVR-350
-	 3 -> Hauppauge WinTV PVR-150 or PVR-500
-	 4 -> AVerMedia M179				[1461:a3ce,1461:a3cf]
-	 5 -> Yuan MPG600/Kuroutoshikou iTVC16-STVLP	[12ab:fff3,12ab:ffff]
-	 6 -> Yuan MPG160/Kuroutoshikou iTVC15-STVLP	[12ab:0000,10fc:40a0]
-	 7 -> Yuan PG600/DiamondMM PVR-550		[ff92:0070,ffab:0600]
-	 8 -> Adaptec AVC-2410				[9005:0093]
-	 9 -> Adaptec AVC-2010				[9005:0092]
-	10 -> NAGASE TRANSGEAR 5000TV			[1461:bfff]
-	11 -> AOpen VA2000MAX-STN6			[0000:ff5f]
-	12 -> YUAN MPG600GR/Kuroutoshikou CX23416GYC-STVLP [12ab:0600,fbab:0600,1154:0523]
-	13 -> I/O Data GV-MVP/RX			[10fc:d01e,10fc:d038,10fc:d039]
-	14 -> I/O Data GV-MVP/RX2E			[10fc:d025]
-	15 -> GOTVIEW PCI DVD (partial support only)	[12ab:0600]
-	16 -> GOTVIEW PCI DVD2 Deluxe			[ffac:0600]
-	17 -> Yuan MPC622				[ff01:d998]
-	18 -> Digital Cowboy DCT-MTVP1			[1461:bfff]
-	19 -> Yuan PG600V2/GotView PCI DVD Lite	[ffab:0600,ffad:0600]
-	20 -> Club3D ZAP-TV1x01				[ffab:0600]
-	21 -> AverTV MCE 116 Plus			[1461:c439]
-	22 -> ASUS Falcon2				[1043:4b66,1043:462e,1043:4b2e]
-	23 -> AverMedia PVR-150 Plus			[1461:c035]
-	24 -> AverMedia EZMaker PCI Deluxe		[1461:c03f]
+=========== ============================================================= ====================================================
+Card number Card name                                                     PCI IDs
+=========== ============================================================= ====================================================
+0           Hauppauge WinTV PVR-250                                       IVTV16 104d:813d
+1           Hauppauge WinTV PVR-350                                       IVTV16 104d:813d
+2           Hauppauge WinTV PVR-150                                       IVTV16 104d:813d
+3           AVerMedia M179                                                IVTV15 1461:a3cf, IVTV15 1461:a3ce
+4           Yuan MPG600, Kuroutoshikou ITVC16-STVLP                       IVTV16 12ab:fff3, IVTV16 12ab:ffff
+5           YUAN MPG160, Kuroutoshikou ITVC15-STVLP, I/O Data GV-M2TV/PCI IVTV15 10fc:40a0
+6           Yuan PG600, Diamond PVR-550                                   IVTV16 ff92:0070, IVTV16 ffab:0600
+7           Adaptec VideOh! AVC-2410                                      IVTV16 9005:0093
+8           Adaptec VideOh! AVC-2010                                      IVTV16 9005:0092
+9           Nagase Transgear 5000TV                                       IVTV16 1461:bfff
+10          AOpen VA2000MAX-SNT6                                          IVTV16 0000:ff5f
+11          Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP                 IVTV16 12ab:0600, IVTV16 fbab:0600, IVTV16 1154:0523
+12          I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)                  IVTV16 10fc:d01e, IVTV16 10fc:d038, IVTV16 10fc:d039
+13          I/O Data GV-MVP/RX2E                                          IVTV16 10fc:d025
+14          GotView PCI DVD                                               IVTV16 12ab:0600
+15          GotView PCI DVD2 Deluxe                                       IVTV16 ffac:0600
+16          Yuan MPC622                                                   IVTV16 ff01:d998
+17          Digital Cowboy DCT-MTVP1                                      IVTV16 1461:bfff
+18          Yuan PG600-2, GotView PCI DVD Lite                            IVTV16 ffab:0600, IVTV16 ffad:0600
+19          Club3D ZAP-TV1x01                                             IVTV16 ffab:0600
+20          AVerTV MCE 116 Plus                                           IVTV16 1461:c439
+21          ASUS Falcon2                                                  IVTV16 1043:4b66, IVTV16 1043:462e, IVTV16 1043:4b2e
+22          AVerMedia PVR-150 Plus / AVerTV M113 Partsnic (Daewoo) Tuner  IVTV16 1461:c034, IVTV16 1461:c035
+23          AVerMedia EZMaker PCI Deluxe                                  IVTV16 1461:c03f
+24          AVerMedia M104                                                IVTV16 1461:c136
+25          Buffalo PC-MV5L/PCI                                           IVTV16 1154:052b
+26          AVerMedia UltraTV 1500 MCE / AVerTV M113 Philips Tuner        IVTV16 1461:c019, IVTV16 1461:c01b
+27          Sony VAIO Giga Pocket (ENX Kikyou)                            IVTV16 104d:813d
+28          Hauppauge WinTV PVR-350 (V1)                                  IVTV16 104d:813d
+29          Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR)         IVTV16 104d:813d
+30          Yuan MPG600GR, Kuroutoshikou CX23416GYC-STVLP (no GR/YCS)     IVTV16 104d:813d
+=========== ============================================================= ====================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/ivtv.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/ivtv.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/ivtv.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/ivtv.rst	2017-02-12 17:57:48.000000000 -0500
@@ -14,7 +14,7 @@ Hauppauge PVR-350.
    #) This driver requires the latest encoder firmware (version 2.06.039, size
       376836 bytes). Get the firmware from here:
 
-      https://linuxtv.org/downloads/firmware/#conexant
+      /*(DEBLOBBED)*/
 
    #) 'normal' TV applications do not work with this driver, you need
       an application that can handle MPEG input such as mplayer, xine, MythTV,
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/rcar-fdp1.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/rcar-fdp1.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/rcar-fdp1.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/rcar-fdp1.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,37 @@
+Renesas R-Car Fine Display Processor (FDP1) Driver
+==================================================
+
+The R-Car FDP1 driver implements driver-specific controls as follows.
+
+``V4L2_CID_DEINTERLACING_MODE (menu)``
+    The video deinterlacing mode (such as Bob, Weave, ...). The R-Car FDP1
+    driver implements the following modes.
+
+.. flat-table::
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 4
+
+    * - ``"Progressive" (0)``
+      - The input image video stream is progressive (not interlaced). No
+        deinterlacing is performed. Apart from (optional) format and encoding
+        conversion output frames are identical to the input frames.
+    * - ``"Adaptive 2D/3D" (1)``
+      - Motion adaptive version of 2D and 3D deinterlacing. Use 3D deinterlacing
+        in the presence of fast motion and 2D deinterlacing with diagonal
+        interpolation otherwise.
+    * - ``"Fixed 2D" (2)``
+      - The current field is scaled vertically by averaging adjacent lines to
+        recover missing lines. This method is also known as blending or Line
+        Averaging (LAV).
+    * - ``"Fixed 3D" (3)``
+      - The previous and next fields are averaged to recover lines missing from
+        the current field. This method is also known as Field Averaging (FAV).
+    * - ``"Previous field" (4)``
+      - The current field is weaved with the previous field, i.e. the previous
+        field is used to fill missing lines from the current field. This method
+        is also known as weave deinterlacing.
+    * - ``"Next field" (5)``
+      - The current field is weaved with the next field, i.e. the next field is
+        used to fill missing lines from the current field. This method is also
+        known as weave deinterlacing.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/saa7134-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/saa7134-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/saa7134-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/saa7134-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,202 +1,204 @@
 SAA7134 cards list
 ==================
 
-.. code-block:: none
-
-	  0 -> UNKNOWN/GENERIC
-	  1 -> Proteus Pro [philips reference design]   [1131:2001,1131:2001]
-	  2 -> LifeView FlyVIDEO3000                    [5168:0138,4e42:0138]
-	  3 -> LifeView/Typhoon FlyVIDEO2000            [5168:0138,4e42:0138]
-	  4 -> EMPRESS                                  [1131:6752]
-	  5 -> SKNet Monster TV                         [1131:4e85]
-	  6 -> Tevion MD 9717
-	  7 -> KNC One TV-Station RDS / Typhoon TV Tuner RDS [1131:fe01,1894:fe01]
-	  8 -> Terratec Cinergy 400 TV                  [153b:1142]
-	  9 -> Medion 5044
-	 10 -> Kworld/KuroutoShikou SAA7130-TVPCI
-	 11 -> Terratec Cinergy 600 TV                  [153b:1143]
-	 12 -> Medion 7134                              [16be:0003,16be:5000]
-	 13 -> Typhoon TV+Radio 90031
-	 14 -> ELSA EX-VISION 300TV                     [1048:226b]
-	 15 -> ELSA EX-VISION 500TV                     [1048:226a]
-	 16 -> ASUS TV-FM 7134                          [1043:4842,1043:4830,1043:4840]
-	 17 -> AOPEN VA1000 POWER                       [1131:7133]
-	 18 -> BMK MPEX No Tuner
-	 19 -> Compro VideoMate TV                      [185b:c100]
-	 20 -> Matrox CronosPlus                        [102B:48d0]
-	 21 -> 10MOONS PCI TV CAPTURE CARD              [1131:2001]
-	 22 -> AverMedia M156 / Medion 2819             [1461:a70b]
-	 23 -> BMK MPEX Tuner
-	 24 -> KNC One TV-Station DVR                   [1894:a006]
-	 25 -> ASUS TV-FM 7133                          [1043:4843]
-	 26 -> Pinnacle PCTV Stereo (saa7134)           [11bd:002b]
-	 27 -> Manli MuchTV M-TV002
-	 28 -> Manli MuchTV M-TV001
-	 29 -> Nagase Sangyo TransGear 3000TV           [1461:050c]
-	 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)  [1019:4cb4]
-	 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
-	 32 -> AVACS SmartTV
-	 33 -> AVerMedia DVD EZMaker                    [1461:10ff]
-	 34 -> Noval Prime TV 7133
-	 35 -> AverMedia AverTV Studio 305              [1461:2115]
-	 36 -> UPMOST PURPLE TV                         [12ab:0800]
-	 37 -> Items MuchTV Plus / IT-005
-	 38 -> Terratec Cinergy 200 TV                  [153b:1152]
-	 39 -> LifeView FlyTV Platinum Mini             [5168:0212,4e42:0212,5169:1502]
-	 40 -> Compro VideoMate TV PVR/FM               [185b:c100]
-	 41 -> Compro VideoMate TV Gold+                [185b:c100]
-	 42 -> Sabrent SBT-TVFM (saa7130)
-	 43 -> :Zolid Xpert TV7134
-	 44 -> Empire PCI TV-Radio LE
-	 45 -> Avermedia AVerTV Studio 307              [1461:9715]
-	 46 -> AVerMedia Cardbus TV/Radio (E500)        [1461:d6ee]
-	 47 -> Terratec Cinergy 400 mobile              [153b:1162]
-	 48 -> Terratec Cinergy 600 TV MK3              [153b:1158]
-	 49 -> Compro VideoMate Gold+ Pal               [185b:c200]
-	 50 -> Pinnacle PCTV 300i DVB-T + PAL           [11bd:002d]
-	 51 -> ProVideo PV952                           [1540:9524]
-	 52 -> AverMedia AverTV/305                     [1461:2108]
-	 53 -> ASUS TV-FM 7135                          [1043:4845]
-	 54 -> LifeView FlyTV Platinum FM / Gold        [5168:0214,5168:5214,1489:0214,5168:0304]
-	 55 -> LifeView FlyDVB-T DUO / MSI TV@nywhere Duo [5168:0306,4E42:0306]
-	 56 -> Avermedia AVerTV 307                     [1461:a70a]
-	 57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
-	 58 -> ADS Tech Instant TV (saa7135)            [1421:0350,1421:0351,1421:0370,1421:1370]
-	 59 -> Kworld/Tevion V-Stream Xpert TV PVR7134
-	 60 -> LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus [5168:0502,4e42:0502,1489:0502]
-	 61 -> Philips TOUGH DVB-T reference design     [1131:2004]
-	 62 -> Compro VideoMate TV Gold+II
-	 63 -> Kworld Xpert TV PVR7134
-	 64 -> FlyTV mini Asus Digimatrix               [1043:0210]
-	 65 -> V-Stream Studio TV Terminator
-	 66 -> Yuan TUN-900 (saa7135)
-	 67 -> Beholder BeholdTV 409 FM                 [0000:4091]
-	 68 -> GoTView 7135 PCI                         [5456:7135]
-	 69 -> Philips EUROPA V3 reference design       [1131:2004]
-	 70 -> Compro Videomate DVB-T300                [185b:c900]
-	 71 -> Compro Videomate DVB-T200                [185b:c901]
-	 72 -> RTD Embedded Technologies VFG7350        [1435:7350]
-	 73 -> RTD Embedded Technologies VFG7330        [1435:7330]
-	 74 -> LifeView FlyTV Platinum Mini2            [14c0:1212]
-	 75 -> AVerMedia AVerTVHD MCE A180              [1461:1044]
-	 76 -> SKNet MonsterTV Mobile                   [1131:4ee9]
-	 77 -> Pinnacle PCTV 40i/50i/110i (saa7133)     [11bd:002e]
-	 78 -> ASUSTeK P7131 Dual                       [1043:4862]
-	 79 -> Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
-	 80 -> ASUS Digimatrix TV                       [1043:0210]
-	 81 -> Philips Tiger reference design           [1131:2018]
-	 82 -> MSI TV@Anywhere plus                     [1462:6231,1462:8624]
-	 83 -> Terratec Cinergy 250 PCI TV              [153b:1160]
-	 84 -> LifeView FlyDVB Trio                     [5168:0319]
-	 85 -> AverTV DVB-T 777                         [1461:2c05,1461:2c05]
-	 86 -> LifeView FlyDVB-T / Genius VideoWonder DVB-T [5168:0301,1489:0301]
-	 87 -> ADS Instant TV Duo Cardbus PTV331        [0331:1421]
-	 88 -> Tevion/KWorld DVB-T 220RF                [17de:7201]
-	 89 -> ELSA EX-VISION 700TV                     [1048:226c]
-	 90 -> Kworld ATSC110/115                       [17de:7350,17de:7352]
-	 91 -> AVerMedia A169 B                         [1461:7360]
-	 92 -> AVerMedia A169 B1                        [1461:6360]
-	 93 -> Medion 7134 Bridge #2                    [16be:0005]
-	 94 -> LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB [5168:3306,5168:3502,5168:3307,4e42:3502]
-	 95 -> LifeView FlyVIDEO3000 (NTSC)             [5169:0138]
-	 96 -> Medion Md8800 Quadro                     [16be:0007,16be:0008,16be:000d]
-	 97 -> LifeView FlyDVB-S /Acorp TV134DS         [5168:0300,4e42:0300]
-	 98 -> Proteus Pro 2309                         [0919:2003]
-	 99 -> AVerMedia TV Hybrid A16AR                [1461:2c00]
-	100 -> Asus Europa2 OEM                         [1043:4860]
-	101 -> Pinnacle PCTV 310i                       [11bd:002f]
-	102 -> Avermedia AVerTV Studio 507              [1461:9715]
-	103 -> Compro Videomate DVB-T200A
-	104 -> Hauppauge WinTV-HVR1110 DVB-T/Hybrid     [0070:6700,0070:6701,0070:6702,0070:6703,0070:6704,0070:6705]
-	105 -> Terratec Cinergy HT PCMCIA               [153b:1172]
-	106 -> Encore ENLTV                             [1131:2342,1131:2341,3016:2344]
-	107 -> Encore ENLTV-FM                          [1131:230f]
-	108 -> Terratec Cinergy HT PCI                  [153b:1175]
-	109 -> Philips Tiger - S Reference design
-	110 -> Avermedia M102                           [1461:f31e]
-	111 -> ASUS P7131 4871                          [1043:4871]
-	112 -> ASUSTeK P7131 Hybrid                     [1043:4876]
-	113 -> Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM) [1019:4cb6]
-	114 -> KWorld DVB-T 210                         [17de:7250]
-	115 -> Sabrent PCMCIA TV-PCB05                  [0919:2003]
-	116 -> 10MOONS TM300 TV Card                    [1131:2304]
-	117 -> Avermedia Super 007                      [1461:f01d]
-	118 -> Beholder BeholdTV 401                    [0000:4016]
-	119 -> Beholder BeholdTV 403                    [0000:4036]
-	120 -> Beholder BeholdTV 403 FM                 [0000:4037]
-	121 -> Beholder BeholdTV 405                    [0000:4050]
-	122 -> Beholder BeholdTV 405 FM                 [0000:4051]
-	123 -> Beholder BeholdTV 407                    [0000:4070]
-	124 -> Beholder BeholdTV 407 FM                 [0000:4071]
-	125 -> Beholder BeholdTV 409                    [0000:4090]
-	126 -> Beholder BeholdTV 505 FM                 [5ace:5050]
-	127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090]
-	128 -> Beholder BeholdTV Columbus TV/FM         [0000:5201]
-	129 -> Beholder BeholdTV 607 FM                 [5ace:6070]
-	130 -> Beholder BeholdTV M6                     [5ace:6190]
-	131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
-	132 -> Genius TVGO AM11MCE
-	133 -> NXP Snake DVB-S reference design
-	134 -> Medion/Creatix CTX953 Hybrid             [16be:0010]
-	135 -> MSI TV@nywhere A/D v1.1                  [1462:8625]
-	136 -> AVerMedia Cardbus TV/Radio (E506R)       [1461:f436]
-	137 -> AVerMedia Hybrid TV/Radio (A16D)         [1461:f936]
-	138 -> Avermedia M115                           [1461:a836]
-	139 -> Compro VideoMate T750                    [185b:c900]
-	140 -> Avermedia DVB-S Pro A700                 [1461:a7a1]
-	141 -> Avermedia DVB-S Hybrid+FM A700           [1461:a7a2]
-	142 -> Beholder BeholdTV H6                     [5ace:6290]
-	143 -> Beholder BeholdTV M63                    [5ace:6191]
-	144 -> Beholder BeholdTV M6 Extra               [5ace:6193]
-	145 -> AVerMedia MiniPCI DVB-T Hybrid M103      [1461:f636,1461:f736]
-	146 -> ASUSTeK P7131 Analog
-	147 -> Asus Tiger 3in1                          [1043:4878]
-	148 -> Encore ENLTV-FM v5.3                     [1a7f:2008]
-	149 -> Avermedia PCI pure analog (M135A)        [1461:f11d]
-	150 -> Zogis Real Angel 220
-	151 -> ADS Tech Instant HDTV                    [1421:0380]
-	152 -> Asus Tiger Rev:1.00                      [1043:4857]
-	153 -> Kworld Plus TV Analog Lite PCI           [17de:7128]
-	154 -> Avermedia AVerTV GO 007 FM Plus          [1461:f31d]
-	155 -> Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid  [0070:6706,0070:6708]
-	156 -> Hauppauge WinTV-HVR1120 DVB-T/Hybrid     [0070:6707,0070:6709,0070:670a]
-	157 -> Avermedia AVerTV Studio 507UA            [1461:a11b]
-	158 -> AVerMedia Cardbus TV/Radio (E501R)       [1461:b7e9]
-	159 -> Beholder BeholdTV 505 RDS                [0000:505B]
-	160 -> Beholder BeholdTV 507 RDS                [0000:5071]
-	161 -> Beholder BeholdTV 507 RDS                [0000:507B]
-	162 -> Beholder BeholdTV 607 FM                 [5ace:6071]
-	163 -> Beholder BeholdTV 609 FM                 [5ace:6090]
-	164 -> Beholder BeholdTV 609 FM                 [5ace:6091]
-	165 -> Beholder BeholdTV 607 RDS                [5ace:6072]
-	166 -> Beholder BeholdTV 607 RDS                [5ace:6073]
-	167 -> Beholder BeholdTV 609 RDS                [5ace:6092]
-	168 -> Beholder BeholdTV 609 RDS                [5ace:6093]
-	169 -> Compro VideoMate S350/S300               [185b:c900]
-	170 -> AverMedia AverTV Studio 505              [1461:a115]
-	171 -> Beholder BeholdTV X7                     [5ace:7595]
-	172 -> RoverMedia TV Link Pro FM                [19d1:0138]
-	173 -> Zolid Hybrid TV Tuner PCI                [1131:2004]
-	174 -> Asus Europa Hybrid OEM                   [1043:4847]
-	175 -> Leadtek Winfast DTV1000S                 [107d:6655]
-	176 -> Beholder BeholdTV 505 RDS                [0000:5051]
-	177 -> Hawell HW-404M7
-	178 -> Beholder BeholdTV H7                     [5ace:7190]
-	179 -> Beholder BeholdTV A7                     [5ace:7090]
-	180 -> Avermedia PCI M733A                      [1461:4155,1461:4255]
-	181 -> TechoTrend TT-budget T-3000              [13c2:2804]
-	182 -> Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid  [17de:b136]
-	183 -> Compro VideoMate Vista M1F               [185b:c900]
-	184 -> Encore ENLTV-FM 3                        [1a7f:2108]
-	185 -> MagicPro ProHDTV Pro2 DMB-TH/Hybrid      [17de:d136]
-	186 -> Beholder BeholdTV 501                    [5ace:5010]
-	187 -> Beholder BeholdTV 503 FM                 [5ace:5030]
-	188 -> Sensoray 811/911                         [6000:0811,6000:0911]
-	189 -> Kworld PC150-U                           [17de:a134]
-	190 -> Asus My Cinema PS3-100                   [1043:48cd]
-	191 -> Hawell HW-9004V1
-	192 -> AverMedia AverTV Satellite Hybrid+FM A706 [1461:2055]
-	193 -> WIS Voyager or compatible                [1905:7007]
-	194 -> AverMedia AverTV/505                     [1461:a10a]
-	195 -> Leadtek Winfast TV2100 FM                [107d:6f3a]
-	196 -> SnaZio* TVPVR PRO                        [1779:13cf]
+=========== ======================================================= ================================================================
+Card number Card name                                               PCI IDs
+=========== ======================================================= ================================================================
+0           UNKNOWN/GENERIC
+1           Proteus Pro [philips reference design]                  1131:2001, 1131:2001
+2           LifeView FlyVIDEO3000                                   5168:0138, 4e42:0138
+3           LifeView/Typhoon FlyVIDEO2000                           5168:0138, 4e42:0138
+4           EMPRESS                                                 1131:6752
+5           SKNet Monster TV                                        1131:4e85
+6           Tevion MD 9717
+7           KNC One TV-Station RDS / Typhoon TV Tuner RDS           1131:fe01, 1894:fe01
+8           Terratec Cinergy 400 TV                                 153b:1142
+9           Medion 5044
+10          Kworld/KuroutoShikou SAA7130-TVPCI
+11          Terratec Cinergy 600 TV                                 153b:1143
+12          Medion 7134                                             16be:0003, 16be:5000
+13          Typhoon TV+Radio 90031
+14          ELSA EX-VISION 300TV                                    1048:226b
+15          ELSA EX-VISION 500TV                                    1048:226a
+16          ASUS TV-FM 7134                                         1043:4842, 1043:4830, 1043:4840
+17          AOPEN VA1000 POWER                                      1131:7133
+18          BMK MPEX No Tuner
+19          Compro VideoMate TV                                     185b:c100
+20          Matrox CronosPlus                                       102B:48d0
+21          10MOONS PCI TV CAPTURE CARD                             1131:2001
+22          AverMedia M156 / Medion 2819                            1461:a70b
+23          BMK MPEX Tuner
+24          KNC One TV-Station DVR                                  1894:a006
+25          ASUS TV-FM 7133                                         1043:4843
+26          Pinnacle PCTV Stereo (saa7134)                          11bd:002b
+27          Manli MuchTV M-TV002
+28          Manli MuchTV M-TV001
+29          Nagase Sangyo TransGear 3000TV                          1461:050c
+30          Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)      1019:4cb4
+31          Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM)       1019:4cb5
+32          AVACS SmartTV
+33          AVerMedia DVD EZMaker                                   1461:10ff
+34          Noval Prime TV 7133
+35          AverMedia AverTV Studio 305                             1461:2115
+36          UPMOST PURPLE TV                                        12ab:0800
+37          Items MuchTV Plus / IT-005
+38          Terratec Cinergy 200 TV                                 153b:1152
+39          LifeView FlyTV Platinum Mini                            5168:0212, 4e42:0212, 5169:1502
+40          Compro VideoMate TV PVR/FM                              185b:c100
+41          Compro VideoMate TV Gold+                               185b:c100
+42          Sabrent SBT-TVFM (saa7130)
+43          :Zolid Xpert TV7134
+44          Empire PCI TV-Radio LE
+45          Avermedia AVerTV Studio 307                             1461:9715
+46          AVerMedia Cardbus TV/Radio (E500)                       1461:d6ee
+47          Terratec Cinergy 400 mobile                             153b:1162
+48          Terratec Cinergy 600 TV MK3                             153b:1158
+49          Compro VideoMate Gold+ Pal                              185b:c200
+50          Pinnacle PCTV 300i DVB-T + PAL                          11bd:002d
+51          ProVideo PV952                                          1540:9524
+52          AverMedia AverTV/305                                    1461:2108
+53          ASUS TV-FM 7135                                         1043:4845
+54          LifeView FlyTV Platinum FM / Gold                       5168:0214, 5168:5214, 1489:0214, 5168:0304
+55          LifeView FlyDVB-T DUO / MSI TV@nywhere Duo              5168:0306, 4E42:0306
+56          Avermedia AVerTV 307                                    1461:a70a
+57          Avermedia AVerTV GO 007 FM                              1461:f31f
+58          ADS Tech Instant TV (saa7135)                           1421:0350, 1421:0351, 1421:0370, 1421:1370
+59          Kworld/Tevion V-Stream Xpert TV PVR7134
+60          LifeView/Typhoon/Genius FlyDVB-T Duo Cardbus            5168:0502, 4e42:0502, 1489:0502
+61          Philips TOUGH DVB-T reference design                    1131:2004
+62          Compro VideoMate TV Gold+II
+63          Kworld Xpert TV PVR7134
+64          FlyTV mini Asus Digimatrix                              1043:0210
+65          V-Stream Studio TV Terminator
+66          Yuan TUN-900 (saa7135)
+67          Beholder BeholdTV 409 FM                                0000:4091
+68          GoTView 7135 PCI                                        5456:7135
+69          Philips EUROPA V3 reference design                      1131:2004
+70          Compro Videomate DVB-T300                               185b:c900
+71          Compro Videomate DVB-T200                               185b:c901
+72          RTD Embedded Technologies VFG7350                       1435:7350
+73          RTD Embedded Technologies VFG7330                       1435:7330
+74          LifeView FlyTV Platinum Mini2                           14c0:1212
+75          AVerMedia AVerTVHD MCE A180                             1461:1044
+76          SKNet MonsterTV Mobile                                  1131:4ee9
+77          Pinnacle PCTV 40i/50i/110i (saa7133)                    11bd:002e
+78          ASUSTeK P7131 Dual                                      1043:4862
+79          Sedna/MuchTV PC TV Cardbus TV/Radio (ITO25 Rev:2B)
+80          ASUS Digimatrix TV                                      1043:0210
+81          Philips Tiger reference design                          1131:2018
+82          MSI TV@Anywhere plus                                    1462:6231, 1462:8624
+83          Terratec Cinergy 250 PCI TV                             153b:1160
+84          LifeView FlyDVB Trio                                    5168:0319
+85          AverTV DVB-T 777                                        1461:2c05, 1461:2c05
+86          LifeView FlyDVB-T / Genius VideoWonder DVB-T            5168:0301, 1489:0301
+87          ADS Instant TV Duo Cardbus PTV331                       0331:1421
+88          Tevion/KWorld DVB-T 220RF                               17de:7201
+89          ELSA EX-VISION 700TV                                    1048:226c
+90          Kworld ATSC110/115                                      17de:7350, 17de:7352
+91          AVerMedia A169 B                                        1461:7360
+92          AVerMedia A169 B1                                       1461:6360
+93          Medion 7134 Bridge #2                                   16be:0005
+94          LifeView FlyDVB-T Hybrid Cardbus/MSI TV @nywhere A/D NB 5168:3306, 5168:3502, 5168:3307, 4e42:3502
+95          LifeView FlyVIDEO3000 (NTSC)                            5169:0138
+96          Medion Md8800 Quadro                                    16be:0007, 16be:0008, 16be:000d
+97          LifeView FlyDVB-S /Acorp TV134DS                        5168:0300, 4e42:0300
+98          Proteus Pro 2309                                        0919:2003
+99          AVerMedia TV Hybrid A16AR                               1461:2c00
+100         Asus Europa2 OEM                                        1043:4860
+101         Pinnacle PCTV 310i                                      11bd:002f
+102         Avermedia AVerTV Studio 507                             1461:9715
+103         Compro Videomate DVB-T200A
+104         Hauppauge WinTV-HVR1110 DVB-T/Hybrid                    0070:6700, 0070:6701, 0070:6702, 0070:6703, 0070:6704, 0070:6705
+105         Terratec Cinergy HT PCMCIA                              153b:1172
+106         Encore ENLTV                                            1131:2342, 1131:2341, 3016:2344
+107         Encore ENLTV-FM                                         1131:230f
+108         Terratec Cinergy HT PCI                                 153b:1175
+109         Philips Tiger - S Reference design
+110         Avermedia M102                                          1461:f31e
+111         ASUS P7131 4871                                         1043:4871
+112         ASUSTeK P7131 Hybrid                                    1043:4876
+113         Elitegroup ECS TVP3XP FM1246 Tuner Card (PAL,FM)        1019:4cb6
+114         KWorld DVB-T 210                                        17de:7250
+115         Sabrent PCMCIA TV-PCB05                                 0919:2003
+116         10MOONS TM300 TV Card                                   1131:2304
+117         Avermedia Super 007                                     1461:f01d
+118         Beholder BeholdTV 401                                   0000:4016
+119         Beholder BeholdTV 403                                   0000:4036
+120         Beholder BeholdTV 403 FM                                0000:4037
+121         Beholder BeholdTV 405                                   0000:4050
+122         Beholder BeholdTV 405 FM                                0000:4051
+123         Beholder BeholdTV 407                                   0000:4070
+124         Beholder BeholdTV 407 FM                                0000:4071
+125         Beholder BeholdTV 409                                   0000:4090
+126         Beholder BeholdTV 505 FM                                5ace:5050
+127         Beholder BeholdTV 507 FM / BeholdTV 509 FM              5ace:5070, 5ace:5090
+128         Beholder BeholdTV Columbus TV/FM                        0000:5201
+129         Beholder BeholdTV 607 FM                                5ace:6070
+130         Beholder BeholdTV M6                                    5ace:6190
+131         Twinhan Hybrid DTV-DVB 3056 PCI                         1822:0022
+132         Genius TVGO AM11MCE
+133         NXP Snake DVB-S reference design
+134         Medion/Creatix CTX953 Hybrid                            16be:0010
+135         MSI TV@nywhere A/D v1.1                                 1462:8625
+136         AVerMedia Cardbus TV/Radio (E506R)                      1461:f436
+137         AVerMedia Hybrid TV/Radio (A16D)                        1461:f936
+138         Avermedia M115                                          1461:a836
+139         Compro VideoMate T750                                   185b:c900
+140         Avermedia DVB-S Pro A700                                1461:a7a1
+141         Avermedia DVB-S Hybrid+FM A700                          1461:a7a2
+142         Beholder BeholdTV H6                                    5ace:6290
+143         Beholder BeholdTV M63                                   5ace:6191
+144         Beholder BeholdTV M6 Extra                              5ace:6193
+145         AVerMedia MiniPCI DVB-T Hybrid M103                     1461:f636, 1461:f736
+146         ASUSTeK P7131 Analog
+147         Asus Tiger 3in1                                         1043:4878
+148         Encore ENLTV-FM v5.3                                    1a7f:2008
+149         Avermedia PCI pure analog (M135A)                       1461:f11d
+150         Zogis Real Angel 220
+151         ADS Tech Instant HDTV                                   1421:0380
+152         Asus Tiger Rev:1.00                                     1043:4857
+153         Kworld Plus TV Analog Lite PCI                          17de:7128
+154         Avermedia AVerTV GO 007 FM Plus                         1461:f31d
+155         Hauppauge WinTV-HVR1150 ATSC/QAM-Hybrid                 0070:6706, 0070:6708
+156         Hauppauge WinTV-HVR1120 DVB-T/Hybrid                    0070:6707, 0070:6709, 0070:670a
+157         Avermedia AVerTV Studio 507UA                           1461:a11b
+158         AVerMedia Cardbus TV/Radio (E501R)                      1461:b7e9
+159         Beholder BeholdTV 505 RDS                               0000:505B
+160         Beholder BeholdTV 507 RDS                               0000:5071
+161         Beholder BeholdTV 507 RDS                               0000:507B
+162         Beholder BeholdTV 607 FM                                5ace:6071
+163         Beholder BeholdTV 609 FM                                5ace:6090
+164         Beholder BeholdTV 609 FM                                5ace:6091
+165         Beholder BeholdTV 607 RDS                               5ace:6072
+166         Beholder BeholdTV 607 RDS                               5ace:6073
+167         Beholder BeholdTV 609 RDS                               5ace:6092
+168         Beholder BeholdTV 609 RDS                               5ace:6093
+169         Compro VideoMate S350/S300                              185b:c900
+170         AverMedia AverTV Studio 505                             1461:a115
+171         Beholder BeholdTV X7                                    5ace:7595
+172         RoverMedia TV Link Pro FM                               19d1:0138
+173         Zolid Hybrid TV Tuner PCI                               1131:2004
+174         Asus Europa Hybrid OEM                                  1043:4847
+175         Leadtek Winfast DTV1000S                                107d:6655
+176         Beholder BeholdTV 505 RDS                               0000:5051
+177         Hawell HW-404M7
+178         Beholder BeholdTV H7                                    5ace:7190
+179         Beholder BeholdTV A7                                    5ace:7090
+180         Avermedia PCI M733A                                     1461:4155, 1461:4255
+181         TechoTrend TT-budget T-3000                             13c2:2804
+182         Kworld PCI SBTVD/ISDB-T Full-Seg Hybrid                 17de:b136
+183         Compro VideoMate Vista M1F                              185b:c900
+184         Encore ENLTV-FM 3                                       1a7f:2108
+185         MagicPro ProHDTV Pro2 DMB-TH/Hybrid                     17de:d136
+186         Beholder BeholdTV 501                                   5ace:5010
+187         Beholder BeholdTV 503 FM                                5ace:5030
+188         Sensoray 811/911                                        6000:0811, 6000:0911
+189         Kworld PC150-U                                          17de:a134
+190         Asus My Cinema PS3-100                                  1043:48cd
+191         Hawell HW-9004V1
+192         AverMedia AverTV Satellite Hybrid+FM A706               1461:2055
+193         WIS Voyager or compatible                               1905:7007
+194         AverMedia AverTV/505                                    1461:a10a
+195         Leadtek Winfast TV2100 FM                               107d:6f3a
+196         SnaZio* TVPVR PRO                                       1779:13cf
+=========== ======================================================= ================================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/saa7164-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/saa7164-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/saa7164-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/saa7164-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,19 +1,21 @@
-SAA7134 cards list
+SAA7164 cards list
 ==================
 
-.. code-block:: none
-
-	  0 -> Unknown
-	  1 -> Generic Rev2
-	  2 -> Generic Rev3
-	  3 -> Hauppauge WinTV-HVR2250                             [0070:8880,0070:8810]
-	  4 -> Hauppauge WinTV-HVR2200                             [0070:8980]
-	  5 -> Hauppauge WinTV-HVR2200                             [0070:8900]
-	  6 -> Hauppauge WinTV-HVR2200                             [0070:8901]
-	  7 -> Hauppauge WinTV-HVR2250                             [0070:8891,0070:8851]
-	  8 -> Hauppauge WinTV-HVR2250                             [0070:88A1]
-	  9 -> Hauppauge WinTV-HVR2200                             [0070:8940]
-	 10 -> Hauppauge WinTV-HVR2200                             [0070:8953]
-	 11 -> Hauppauge WinTV-HVR2255(proto)
-	 12 -> Hauppauge WinTV-HVR2255                             [0070:f111]
-	 13 -> Hauppauge WinTV-HVR2205                             [0070:f123,0070:f120]
+=========== ==================================== ====================
+Card number Card name                            PCI IDs
+=========== ==================================== ====================
+0           Unknown
+1           Generic Rev2
+2           Generic Rev3
+3           Hauppauge WinTV-HVR2250              0070:8880, 0070:8810
+4           Hauppauge WinTV-HVR2200              0070:8980
+5           Hauppauge WinTV-HVR2200              0070:8900
+6           Hauppauge WinTV-HVR2200              0070:8901
+7           Hauppauge WinTV-HVR2250              0070:8891, 0070:8851
+8           Hauppauge WinTV-HVR2250              0070:88A1
+9           Hauppauge WinTV-HVR2200              0070:8940
+10          Hauppauge WinTV-HVR2200              0070:8953
+11          Hauppauge WinTV-HVR2255(proto)       0070:f111
+12          Hauppauge WinTV-HVR2255              0070:f111
+13          Hauppauge WinTV-HVR2205              0070:f123, 0070:f120
+=========== ==================================== ====================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/tm6000-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/tm6000-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/tm6000-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/tm6000-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,21 +1,24 @@
 TM6000 cards list
 =================
 
-.. code-block:: none
-
-	  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]
-
+=========== ================================================= ==========================================
+Card number Card name                                         USB IDs
+=========== ================================================= ==========================================
+0           Unknown tm6000 video grabber
+1           Generic tm5600 board                              6000:0001
+2           Generic tm6000 board
+3           Generic tm6010 board                              6000:0002
+4           10Moons UT 821
+5           10Moons UT 330
+6           ADSTECH Dual TV USB                               06e1:f332
+7           Freecom Hybrid Stick / Moka DVB-T Receiver Dual   14aa:0620
+8           ADSTECH Mini Dual TV USB                          06e1:b339
+9           Hauppauge WinTV HVR-900H / WinTV USB2-Stick       2040:6600, 2040:6601, 2040:6610, 2040:6611
+10          Beholder Wander DVB-T/TV/FM USB2.0                6000:dec0
+11          Beholder Voyager TV/FM USB2.0                     6000:dec1
+12          Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick 0ccd:0086, 0ccd:00A5
+13          Twinhan TU501(704D1)                              13d3:3240, 13d3:3241, 13d3:3243, 13d3:3264
+14          Beholder Wander Lite DVB-T/TV/FM USB2.0           6000:dec2
+15          Beholder Voyager Lite TV/FM USB2.0                6000:dec3
+16          Terratec Grabster AV 150/250 MX                   0ccd:0079
+=========== ================================================= ==========================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/tuner-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/tuner-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/tuner-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/tuner-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,96 +1,98 @@
 Tuner cards list
 ================
 
-.. code-block:: none
-
-	tuner=0 - Temic PAL (4002 FH5)
-	tuner=1 - Philips PAL_I (FI1246 and compatibles)
-	tuner=2 - Philips NTSC (FI1236,FM1236 and compatibles)
-	tuner=3 - Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)
-	tuner=4 - NoTuner
-	tuner=5 - Philips PAL_BG (FI1216 and compatibles)
-	tuner=6 - Temic NTSC (4032 FY5)
-	tuner=7 - Temic PAL_I (4062 FY5)
-	tuner=8 - Temic NTSC (4036 FY5)
-	tuner=9 - Alps HSBH1
-	tuner=10 - Alps TSBE1
-	tuner=11 - Alps TSBB5
-	tuner=12 - Alps TSBE5
-	tuner=13 - Alps TSBC5
-	tuner=14 - Temic PAL_BG (4006FH5)
-	tuner=15 - Alps TSCH6
-	tuner=16 - Temic PAL_DK (4016 FY5)
-	tuner=17 - Philips NTSC_M (MK2)
-	tuner=18 - Temic PAL_I (4066 FY5)
-	tuner=19 - Temic PAL* auto (4006 FN5)
-	tuner=20 - Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)
-	tuner=21 - Temic NTSC (4039 FR5)
-	tuner=22 - Temic PAL/SECAM multi (4046 FM5)
-	tuner=23 - Philips PAL_DK (FI1256 and compatibles)
-	tuner=24 - Philips PAL/SECAM multi (FQ1216ME)
-	tuner=25 - LG PAL_I+FM (TAPC-I001D)
-	tuner=26 - LG PAL_I (TAPC-I701D)
-	tuner=27 - LG NTSC+FM (TPI8NSR01F)
-	tuner=28 - LG PAL_BG+FM (TPI8PSB01D)
-	tuner=29 - LG PAL_BG (TPI8PSB11D)
-	tuner=30 - Temic PAL* auto + FM (4009 FN5)
-	tuner=31 - SHARP NTSC_JP (2U5JF5540)
-	tuner=32 - Samsung PAL TCPM9091PD27
-	tuner=33 - MT20xx universal
-	tuner=34 - Temic PAL_BG (4106 FH5)
-	tuner=35 - Temic PAL_DK/SECAM_L (4012 FY5)
-	tuner=36 - Temic NTSC (4136 FY5)
-	tuner=37 - LG PAL (newer TAPC series)
-	tuner=38 - Philips PAL/SECAM multi (FM1216ME MK3)
-	tuner=39 - LG NTSC (newer TAPC series)
-	tuner=40 - HITACHI V7-J180AT
-	tuner=41 - Philips PAL_MK (FI1216 MK)
-	tuner=42 - Philips FCV1236D ATSC/NTSC dual in
-	tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F)
-	tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
-	tuner=45 - Microtune 4049 FM5
-	tuner=46 - Panasonic VP27s/ENGE4324D
-	tuner=47 - LG NTSC (TAPE series)
-	tuner=48 - Tenna TNF 8831 BGFF)
-	tuner=49 - Microtune 4042 FI5 ATSC/NTSC dual in
-	tuner=50 - TCL 2002N
-	tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
-	tuner=52 - Thomson DTT 7610 (ATSC/NTSC)
-	tuner=53 - Philips FQ1286
-	tuner=54 - Philips/NXP TDA 8290/8295 + 8275/8275A/18271
-	tuner=55 - TCL 2002MB
-	tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
-	tuner=57 - Philips FQ1236A MK4
-	tuner=58 - Ymec TVision TVF-8531MF/8831MF/8731MF
-	tuner=59 - Ymec TVision TVF-5533MF
-	tuner=60 - Thomson DTT 761X (ATSC/NTSC)
-	tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
-	tuner=62 - Philips TEA5767HN FM Radio
-	tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
-	tuner=64 - LG TDVS-H06xF
-	tuner=65 - Ymec TVF66T5-B/DFF
-	tuner=66 - LG TALN series
-	tuner=67 - Philips TD1316 Hybrid Tuner
-	tuner=68 - Philips TUV1236D ATSC/NTSC dual in
-	tuner=69 - Tena TNF 5335 and similar models
-	tuner=70 - Samsung TCPN 2121P30A
-	tuner=71 - Xceive xc2028/xc3028 tuner
-	tuner=72 - Thomson FE6600
-	tuner=73 - Samsung TCPG 6121P30A
-	tuner=75 - Philips TEA5761 FM Radio
-	tuner=76 - Xceive 5000 tuner
-	tuner=77 - TCL tuner MF02GIP-5N-E
-	tuner=78 - Philips FMD1216MEX MK3 Hybrid Tuner
-	tuner=79 - Philips PAL/SECAM multi (FM1216 MK5)
-	tuner=80 - Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
-	tuner=81 - Partsnic (Daewoo) PTI-5NF05
-	tuner=82 - Philips CU1216L
-	tuner=83 - NXP TDA18271
-	tuner=84 - Sony BTF-Pxn01Z
-	tuner=85 - Philips FQ1236 MK5
-	tuner=86 - Tena TNF5337 MFD
-	tuner=87 - Xceive 4000 tuner
-	tuner=88 - Xceive 5000C tuner
-	tuner=89 - Sony BTF-PG472Z PAL/SECAM
-	tuner=90 - Sony BTF-PK467Z NTSC-M-JP
-	tuner=91 - Sony BTF-PB463Z NTSC-M
+============ =====================================================
+Tuner number Card name
+============ =====================================================
+0            Temic PAL (4002 FH5)
+1            Philips PAL_I (FI1246 and compatibles)
+2            Philips NTSC (FI1236,FM1236 and compatibles)
+3            Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)
+4            NoTuner
+5            Philips PAL_BG (FI1216 and compatibles)
+6            Temic NTSC (4032 FY5)
+7            Temic PAL_I (4062 FY5)
+8            Temic NTSC (4036 FY5)
+9            Alps HSBH1
+10           Alps TSBE1
+11           Alps TSBB5
+12           Alps TSBE5
+13           Alps TSBC5
+14           Temic PAL_BG (4006FH5)
+15           Alps TSCH6
+16           Temic PAL_DK (4016 FY5)
+17           Philips NTSC_M (MK2)
+18           Temic PAL_I (4066 FY5)
+19           Temic PAL* auto (4006 FN5)
+20           Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)
+21           Temic NTSC (4039 FR5)
+22           Temic PAL/SECAM multi (4046 FM5)
+23           Philips PAL_DK (FI1256 and compatibles)
+24           Philips PAL/SECAM multi (FQ1216ME)
+25           LG PAL_I+FM (TAPC-I001D)
+26           LG PAL_I (TAPC-I701D)
+27           LG NTSC+FM (TPI8NSR01F)
+28           LG PAL_BG+FM (TPI8PSB01D)
+29           LG PAL_BG (TPI8PSB11D)
+30           Temic PAL* auto + FM (4009 FN5)
+31           SHARP NTSC_JP (2U5JF5540)
+32           Samsung PAL TCPM9091PD27
+33           MT20xx universal
+34           Temic PAL_BG (4106 FH5)
+35           Temic PAL_DK/SECAM_L (4012 FY5)
+36           Temic NTSC (4136 FY5)
+37           LG PAL (newer TAPC series)
+38           Philips PAL/SECAM multi (FM1216ME MK3)
+39           LG NTSC (newer TAPC series)
+40           HITACHI V7-J180AT
+41           Philips PAL_MK (FI1216 MK)
+42           Philips FCV1236D ATSC/NTSC dual in
+43           Philips NTSC MK3 (FM1236MK3 or FM1236/F)
+44           Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
+45           Microtune 4049 FM5
+46           Panasonic VP27s/ENGE4324D
+47           LG NTSC (TAPE series)
+48           Tenna TNF 8831 BGFF)
+49           Microtune 4042 FI5 ATSC/NTSC dual in
+50           TCL 2002N
+51           Philips PAL/SECAM_D (FM 1256 I-H3)
+52           Thomson DTT 7610 (ATSC/NTSC)
+53           Philips FQ1286
+54           Philips/NXP TDA 8290/8295 + 8275/8275A/18271
+55           TCL 2002MB
+56           Philips PAL/SECAM multi (FQ1216AME MK4)
+57           Philips FQ1236A MK4
+58           Ymec TVision TVF-8531MF/8831MF/8731MF
+59           Ymec TVision TVF-5533MF
+60           Thomson DTT 761X (ATSC/NTSC)
+61           Tena TNF9533-D/IF/TNF9533-B/DF
+62           Philips TEA5767HN FM Radio
+63           Philips FMD1216ME MK3 Hybrid Tuner
+64           LG TDVS-H06xF
+65           Ymec TVF66T5-B/DFF
+66           LG TALN series
+67           Philips TD1316 Hybrid Tuner
+68           Philips TUV1236D ATSC/NTSC dual in
+69           Tena TNF 5335 and similar models
+70           Samsung TCPN 2121P30A
+71           Xceive xc2028/xc3028 tuner
+72           Thomson FE6600
+73           Samsung TCPG 6121P30A
+75           Philips TEA5761 FM Radio
+76           Xceive 5000 tuner
+77           TCL tuner MF02GIP-5N-E
+78           Philips FMD1216MEX MK3 Hybrid Tuner
+79           Philips PAL/SECAM multi (FM1216 MK5)
+80           Philips FQ1216LME MK3 PAL/SECAM w/active loopthrough
+81           Partsnic (Daewoo) PTI-5NF05
+82           Philips CU1216L
+83           NXP TDA18271
+84           Sony BTF-Pxn01Z
+85           Philips FQ1236 MK5
+86           Tena TNF5337 MFD
+87           Xceive 4000 tuner
+88           Xceive 5000C tuner
+89           Sony BTF-PG472Z PAL/SECAM
+90           Sony BTF-PK467Z NTSC-M-JP
+91           Sony BTF-PB463Z NTSC-M
+============ =====================================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/v4l-drivers/usbvision-cardlist.rst linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/usbvision-cardlist.rst
--- linux-libre-4.9-gnu/Documentation/media/v4l-drivers/usbvision-cardlist.rst	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/v4l-drivers/usbvision-cardlist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -1,72 +1,74 @@
-Usbvision cards list
+USBvision cards list
 ====================
 
-.. code-block:: none
-
-	  0 -> Xanboo                                                   [0a6f:0400]
-	  1 -> Belkin USB VideoBus II Adapter                           [050d:0106]
-	  2 -> Belkin Components USB VideoBus                           [050d:0207]
-	  3 -> Belkin USB VideoBus II                                   [050d:0208]
-	  4 -> echoFX InterView Lite                                    [0571:0002]
-	  5 -> USBGear USBG-V1 resp. HAMA USB                           [0573:0003]
-	  6 -> D-Link V100                                              [0573:0400]
-	  7 -> X10 USB Camera                                           [0573:2000]
-	  8 -> Hauppauge WinTV USB Live (PAL B/G)                       [0573:2d00]
-	  9 -> Hauppauge WinTV USB Live Pro (NTSC M/N)                  [0573:2d01]
-	 10 -> Zoran Co. PMD (Nogatech) AV-grabber Manhattan            [0573:2101]
-	 11 -> Nogatech USB-TV (NTSC) FM                                [0573:4100]
-	 12 -> PNY USB-TV (NTSC) FM                                     [0573:4110]
-	 13 -> PixelView PlayTv-USB PRO (PAL) FM                        [0573:4450]
-	 14 -> ZTV ZT-721 2.4GHz USB A/V Receiver                       [0573:4550]
-	 15 -> Hauppauge WinTV USB (NTSC M/N)                           [0573:4d00]
-	 16 -> Hauppauge WinTV USB (PAL B/G)                            [0573:4d01]
-	 17 -> Hauppauge WinTV USB (PAL I)                              [0573:4d02]
-	 18 -> Hauppauge WinTV USB (PAL/SECAM L)                        [0573:4d03]
-	 19 -> Hauppauge WinTV USB (PAL D/K)                            [0573:4d04]
-	 20 -> Hauppauge WinTV USB (NTSC FM)                            [0573:4d10]
-	 21 -> Hauppauge WinTV USB (PAL B/G FM)                         [0573:4d11]
-	 22 -> Hauppauge WinTV USB (PAL I FM)                           [0573:4d12]
-	 23 -> Hauppauge WinTV USB (PAL D/K FM)                         [0573:4d14]
-	 24 -> Hauppauge WinTV USB Pro (NTSC M/N)                       [0573:4d2a]
-	 25 -> Hauppauge WinTV USB Pro (NTSC M/N) V2                    [0573:4d2b]
-	 26 -> Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)          [0573:4d2c]
-	 27 -> Hauppauge WinTV USB Pro (NTSC M/N) V3                    [0573:4d20]
-	 28 -> Hauppauge WinTV USB Pro (PAL B/G)                        [0573:4d21]
-	 29 -> Hauppauge WinTV USB Pro (PAL I)                          [0573:4d22]
-	 30 -> Hauppauge WinTV USB Pro (PAL/SECAM L)                    [0573:4d23]
-	 31 -> Hauppauge WinTV USB Pro (PAL D/K)                        [0573:4d24]
-	 32 -> Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)             [0573:4d25]
-	 33 -> Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2          [0573:4d26]
-	 34 -> Hauppauge WinTV USB Pro (PAL B/G) V2                     [0573:4d27]
-	 35 -> Hauppauge WinTV USB Pro (PAL B/G,D/K)                    [0573:4d28]
-	 36 -> Hauppauge WinTV USB Pro (PAL I,D/K)                      [0573:4d29]
-	 37 -> Hauppauge WinTV USB Pro (NTSC M/N FM)                    [0573:4d30]
-	 38 -> Hauppauge WinTV USB Pro (PAL B/G FM)                     [0573:4d31]
-	 39 -> Hauppauge WinTV USB Pro (PAL I FM)                       [0573:4d32]
-	 40 -> Hauppauge WinTV USB Pro (PAL D/K FM)                     [0573:4d34]
-	 41 -> Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM) [0573:4d35]
-	 42 -> Hauppauge WinTV USB Pro (Temic PAL B/G FM)               [0573:4d36]
-	 43 -> Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)       [0573:4d37]
-	 44 -> Hauppauge WinTV USB Pro (NTSC M/N FM) V2                 [0573:4d38]
-	 45 -> Camtel Technology USB TV Genie Pro FM Model TVB330       [0768:0006]
-	 46 -> Digital Video Creator I                                  [07d0:0001]
-	 47 -> Global Village GV-007 (NTSC)                             [07d0:0002]
-	 48 -> Dazzle Fusion Model DVC-50 Rev 1 (NTSC)                  [07d0:0003]
-	 49 -> Dazzle Fusion Model DVC-80 Rev 1 (PAL)                   [07d0:0004]
-	 50 -> Dazzle Fusion Model DVC-90 Rev 1 (SECAM)                 [07d0:0005]
-	 51 -> Eskape Labs MyTV2Go                                      [07f8:9104]
-	 52 -> Pinnacle Studio PCTV USB (PAL)                           [2304:010d]
-	 53 -> Pinnacle Studio PCTV USB (SECAM)                         [2304:0109]
-	 54 -> Pinnacle Studio PCTV USB (PAL) FM                        [2304:0110]
-	 55 -> Miro PCTV USB                                            [2304:0111]
-	 56 -> Pinnacle Studio PCTV USB (NTSC) FM                       [2304:0112]
-	 57 -> Pinnacle Studio PCTV USB (PAL) FM V2                     [2304:0210]
-	 58 -> Pinnacle Studio PCTV USB (NTSC) FM V2                    [2304:0212]
-	 59 -> Pinnacle Studio PCTV USB (PAL) FM V3                     [2304:0214]
-	 60 -> Pinnacle Studio Linx Video input cable (NTSC)            [2304:0300]
-	 61 -> Pinnacle Studio Linx Video input cable (PAL)             [2304:0301]
-	 62 -> Pinnacle PCTV Bungee USB (PAL) FM                        [2304:0419]
-	 63 -> Hauppauge WinTv-USB                                      [2400:4200]
-	 64 -> Pinnacle Studio PCTV USB (NTSC) FM V3                    [2304:0113]
-	 65 -> Nogatech USB MicroCam NTSC (NV3000N)                     [0573:3000]
-	 66 -> Nogatech USB MicroCam PAL (NV3001P)                      [0573:3001]
+=========== ======================================================== =========
+Card number Card name                                                USB IDs
+=========== ======================================================== =========
+0           Xanboo                                                   0a6f:0400
+1           Belkin USB VideoBus II Adapter                           050d:0106
+2           Belkin Components USB VideoBus                           050d:0207
+3           Belkin USB VideoBus II                                   050d:0208
+4           echoFX InterView Lite                                    0571:0002
+5           USBGear USBG-V1 resp. HAMA USB                           0573:0003
+6           D-Link V100                                              0573:0400
+7           X10 USB Camera                                           0573:2000
+8           Hauppauge WinTV USB Live (PAL B/G)                       0573:2d00
+9           Hauppauge WinTV USB Live Pro (NTSC M/N)                  0573:2d01
+10          Zoran Co. PMD (Nogatech) AV-grabber Manhattan            0573:2101
+11          Nogatech USB-TV (NTSC) FM                                0573:4100
+12          PNY USB-TV (NTSC) FM                                     0573:4110
+13          PixelView PlayTv-USB PRO (PAL) FM                        0573:4450
+14          ZTV ZT-721 2.4GHz USB A/V Receiver                       0573:4550
+15          Hauppauge WinTV USB (NTSC M/N)                           0573:4d00
+16          Hauppauge WinTV USB (PAL B/G)                            0573:4d01
+17          Hauppauge WinTV USB (PAL I)                              0573:4d02
+18          Hauppauge WinTV USB (PAL/SECAM L)                        0573:4d03
+19          Hauppauge WinTV USB (PAL D/K)                            0573:4d04
+20          Hauppauge WinTV USB (NTSC FM)                            0573:4d10
+21          Hauppauge WinTV USB (PAL B/G FM)                         0573:4d11
+22          Hauppauge WinTV USB (PAL I FM)                           0573:4d12
+23          Hauppauge WinTV USB (PAL D/K FM)                         0573:4d14
+24          Hauppauge WinTV USB Pro (NTSC M/N)                       0573:4d2a
+25          Hauppauge WinTV USB Pro (NTSC M/N) V2                    0573:4d2b
+26          Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)          0573:4d2c
+27          Hauppauge WinTV USB Pro (NTSC M/N) V3                    0573:4d20
+28          Hauppauge WinTV USB Pro (PAL B/G)                        0573:4d21
+29          Hauppauge WinTV USB Pro (PAL I)                          0573:4d22
+30          Hauppauge WinTV USB Pro (PAL/SECAM L)                    0573:4d23
+31          Hauppauge WinTV USB Pro (PAL D/K)                        0573:4d24
+32          Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)             0573:4d25
+33          Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2          0573:4d26
+34          Hauppauge WinTV USB Pro (PAL B/G) V2                     0573:4d27
+35          Hauppauge WinTV USB Pro (PAL B/G,D/K)                    0573:4d28
+36          Hauppauge WinTV USB Pro (PAL I,D/K)                      0573:4d29
+37          Hauppauge WinTV USB Pro (NTSC M/N FM)                    0573:4d30
+38          Hauppauge WinTV USB Pro (PAL B/G FM)                     0573:4d31
+39          Hauppauge WinTV USB Pro (PAL I FM)                       0573:4d32
+40          Hauppauge WinTV USB Pro (PAL D/K FM)                     0573:4d34
+41          Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM) 0573:4d35
+42          Hauppauge WinTV USB Pro (Temic PAL B/G FM)               0573:4d36
+43          Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)       0573:4d37
+44          Hauppauge WinTV USB Pro (NTSC M/N FM) V2                 0573:4d38
+45          Camtel Technology USB TV Genie Pro FM Model TVB330       0768:0006
+46          Digital Video Creator I                                  07d0:0001
+47          Global Village GV-007 (NTSC)                             07d0:0002
+48          Dazzle Fusion Model DVC-50 Rev 1 (NTSC)                  07d0:0003
+49          Dazzle Fusion Model DVC-80 Rev 1 (PAL)                   07d0:0004
+50          Dazzle Fusion Model DVC-90 Rev 1 (SECAM)                 07d0:0005
+51          Eskape Labs MyTV2Go                                      07f8:9104
+52          Pinnacle Studio PCTV USB (PAL)                           2304:010d
+53          Pinnacle Studio PCTV USB (SECAM)                         2304:0109
+54          Pinnacle Studio PCTV USB (PAL) FM                        2304:0110
+55          Miro PCTV USB                                            2304:0111
+56          Pinnacle Studio PCTV USB (NTSC) FM                       2304:0112
+57          Pinnacle Studio PCTV USB (PAL) FM V2                     2304:0210
+58          Pinnacle Studio PCTV USB (NTSC) FM V2                    2304:0212
+59          Pinnacle Studio PCTV USB (PAL) FM V3                     2304:0214
+60          Pinnacle Studio Linx Video input cable (NTSC)            2304:0300
+61          Pinnacle Studio Linx Video input cable (PAL)             2304:0301
+62          Pinnacle PCTV Bungee USB (PAL) FM                        2304:0419
+63          Hauppauge WinTv-USB                                      2400:4200
+64          Pinnacle Studio PCTV USB (NTSC) FM V3                    2304:0113
+65          Nogatech USB MicroCam NTSC (NV3000N)                     0573:3000
+66          Nogatech USB MicroCam PAL (NV3001P)                      0573:3001
+=========== ======================================================== =========
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/media/videodev2.h.rst.exceptions linux-libre-4.10-rc8-gnu/Documentation/media/videodev2.h.rst.exceptions
--- linux-libre-4.9-gnu/Documentation/media/videodev2.h.rst.exceptions	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/media/videodev2.h.rst.exceptions	2017-02-12 16:03:20.000000000 -0500
@@ -87,6 +87,10 @@ replace symbol V4L2_YCBCR_ENC_XV601 :c:t
 replace symbol V4L2_YCBCR_ENC_XV709 :c:type:`v4l2_ycbcr_encoding`
 replace symbol V4L2_YCBCR_ENC_SMPTE240M :c:type:`v4l2_ycbcr_encoding`
 
+# Documented enum v4l2_hsv_encoding
+replace symbol V4L2_HSV_ENC_180 :c:type:`v4l2_hsv_encoding`
+replace symbol V4L2_HSV_ENC_256 :c:type:`v4l2_hsv_encoding`
+
 # Documented enum v4l2_quantization
 replace symbol V4L2_QUANTIZATION_DEFAULT :c:type:`v4l2_quantization`
 replace symbol V4L2_QUANTIZATION_FULL_RANGE :c:type:`v4l2_quantization`
@@ -276,6 +280,9 @@ replace define V4L2_DV_FL_REDUCED_FPS dv
 replace define V4L2_DV_FL_HALF_LINE dv-bt-standards
 replace define V4L2_DV_FL_IS_CE_VIDEO dv-bt-standards
 replace define V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE dv-bt-standards
+replace define V4L2_DV_FL_HAS_PICTURE_ASPECT dv-bt-standards
+replace define V4L2_DV_FL_HAS_CEA861_VIC dv-bt-standards
+replace define V4L2_DV_FL_HAS_HDMI_VIC dv-bt-standards
 
 replace define V4L2_DV_BT_656_1120 dv-timing-types
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/memory-hotplug.txt linux-libre-4.10-rc8-gnu/Documentation/memory-hotplug.txt
--- linux-libre-4.9-gnu/Documentation/memory-hotplug.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/memory-hotplug.txt	2017-02-12 16:03:20.000000000 -0500
@@ -324,7 +324,7 @@ guarantee that the memory block contains
 Now, a boot option for making a memory block which consists of migratable pages
 is supported. By specifying "kernelcore=" or "movablecore=" boot option, you can
 create ZONE_MOVABLE...a zone which is just used for movable pages.
-(See also Documentation/kernel-parameters.txt)
+(See also Documentation/admin-guide/kernel-parameters.rst)
 
 Assume the system has "TOTAL" amount of memory at boot time, this boot option
 creates ZONE_MOVABLE as following.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/module-signing.txt linux-libre-4.10-rc8-gnu/Documentation/module-signing.txt
--- linux-libre-4.9-gnu/Documentation/module-signing.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/module-signing.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,279 +0,0 @@
-			==============================
-			KERNEL MODULE SIGNING FACILITY
-			==============================
-
-CONTENTS
-
- - Overview.
- - Configuring module signing.
- - Generating signing keys.
- - Public keys in the kernel.
- - Manually signing modules.
- - Signed modules and stripping.
- - Loading signed modules.
- - Non-valid signatures and unsigned modules.
- - Administering/protecting the private key.
-
-
-========
-OVERVIEW
-========
-
-The kernel module signing facility cryptographically signs modules during
-installation and then checks the signature upon loading the module.  This
-allows increased kernel security by disallowing the loading of unsigned modules
-or modules signed with an invalid key.  Module signing increases security by
-making it harder to load a malicious module into the kernel.  The module
-signature checking is done by the kernel so that it is not necessary to have
-trusted userspace bits.
-
-This facility uses X.509 ITU-T standard certificates to encode the public keys
-involved.  The signatures are not themselves encoded in any industrial standard
-type.  The facility currently only supports the RSA public key encryption
-standard (though it is pluggable and permits others to be used).  The possible
-hash algorithms that can be used are SHA-1, SHA-224, SHA-256, SHA-384, and
-SHA-512 (the algorithm is selected by data in the signature).
-
-
-==========================
-CONFIGURING MODULE SIGNING
-==========================
-
-The module signing facility is enabled by going to the "Enable Loadable Module
-Support" section of the kernel configuration and turning on
-
-	CONFIG_MODULE_SIG	"Module signature verification"
-
-This has a number of options available:
-
- (1) "Require modules to be validly signed" (CONFIG_MODULE_SIG_FORCE)
-
-     This specifies how the kernel should deal with a module that has a
-     signature for which the key is not known or a module that is unsigned.
-
-     If this is off (ie. "permissive"), then modules for which the key is not
-     available and modules that are unsigned are permitted, but the kernel will
-     be marked as being tainted, and the concerned modules will be marked as
-     tainted, shown with the character 'E'.
-
-     If this is on (ie. "restrictive"), only modules that have a valid
-     signature that can be verified by a public key in the kernel's possession
-     will be loaded.  All other modules will generate an error.
-
-     Irrespective of the setting here, if the module has a signature block that
-     cannot be parsed, it will be rejected out of hand.
-
-
- (2) "Automatically sign all modules" (CONFIG_MODULE_SIG_ALL)
-
-     If this is on then modules will be automatically signed during the
-     modules_install phase of a build.  If this is off, then the modules must
-     be signed manually using:
-
-	scripts/sign-file
-
-
- (3) "Which hash algorithm should modules be signed with?"
-
-     This presents a choice of which hash algorithm the installation phase will
-     sign the modules with:
-
-	CONFIG_MODULE_SIG_SHA1		"Sign modules with SHA-1"
-	CONFIG_MODULE_SIG_SHA224	"Sign modules with SHA-224"
-	CONFIG_MODULE_SIG_SHA256	"Sign modules with SHA-256"
-	CONFIG_MODULE_SIG_SHA384	"Sign modules with SHA-384"
-	CONFIG_MODULE_SIG_SHA512	"Sign modules with SHA-512"
-
-     The algorithm selected here will also be built into the kernel (rather
-     than being a module) so that modules signed with that algorithm can have
-     their signatures checked without causing a dependency loop.
-
-
- (4) "File name or PKCS#11 URI of module signing key" (CONFIG_MODULE_SIG_KEY)
-
-     Setting this option to something other than its default of
-     "certs/signing_key.pem" will disable the autogeneration of signing keys
-     and allow the kernel modules to be signed with a key of your choosing.
-     The string provided should identify a file containing both a private key
-     and its corresponding X.509 certificate in PEM form, or — on systems where
-     the OpenSSL ENGINE_pkcs11 is functional — a PKCS#11 URI as defined by
-     RFC7512. In the latter case, the PKCS#11 URI should reference both a
-     certificate and a private key.
-
-     If the PEM file containing the private key is encrypted, or if the
-     PKCS#11 token requries a PIN, this can be provided at build time by
-     means of the KBUILD_SIGN_PIN variable.
-
-
- (5) "Additional X.509 keys for default system keyring" (CONFIG_SYSTEM_TRUSTED_KEYS)
-
-     This option can be set to the filename of a PEM-encoded file containing
-     additional certificates which will be included in the system keyring by
-     default.
-
-Note that enabling module signing adds a dependency on the OpenSSL devel
-packages to the kernel build processes for the tool that does the signing.
-
-
-=======================
-GENERATING SIGNING KEYS
-=======================
-
-Cryptographic keypairs are required to generate and check signatures.  A
-private key is used to generate a signature and the corresponding public key is
-used to check it.  The private key is only needed during the build, after which
-it can be deleted or stored securely.  The public key gets built into the
-kernel so that it can be used to check the signatures as the modules are
-loaded.
-
-Under normal conditions, when CONFIG_MODULE_SIG_KEY is unchanged from its
-default, the kernel build will automatically generate a new keypair using
-openssl if one does not exist in the file:
-
-	certs/signing_key.pem
-
-during the building of vmlinux (the public part of the key needs to be built
-into vmlinux) using parameters in the:
-
-	certs/x509.genkey
-
-file (which is also generated if it does not already exist).
-
-It is strongly recommended that you provide your own x509.genkey file.
-
-Most notably, in the x509.genkey file, the req_distinguished_name section
-should be altered from the default:
-
-	[ req_distinguished_name ]
-	#O = Unspecified company
-	CN = Build time autogenerated kernel key
-	#emailAddress = unspecified.user@unspecified.company
-
-The generated RSA key size can also be set with:
-
-	[ req ]
-	default_bits = 4096
-
-
-It is also possible to manually generate the key private/public files using the
-x509.genkey key generation configuration file in the root node of the Linux
-kernel sources tree and the openssl command.  The following is an example to
-generate the public/private key files:
-
-	openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
-	   -config x509.genkey -outform PEM -out kernel_key.pem \
-	   -keyout kernel_key.pem
-
-The full pathname for the resulting kernel_key.pem file can then be specified
-in the CONFIG_MODULE_SIG_KEY option, and the certificate and key therein will
-be used instead of an autogenerated keypair.
-
-
-=========================
-PUBLIC KEYS IN THE KERNEL
-=========================
-
-The kernel contains a ring of public keys that can be viewed by root.  They're
-in a keyring called ".system_keyring" that can be seen by:
-
-	[root@deneb ~]# cat /proc/keys
-	...
-	223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
-	302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
-	...
-
-Beyond the public key generated specifically for module signing, additional
-trusted certificates can be provided in a PEM-encoded file referenced by the
-CONFIG_SYSTEM_TRUSTED_KEYS configuration option.
-
-Further, the architecture code may take public keys from a hardware store and
-add those in also (e.g. from the UEFI key database).
-
-Finally, it is possible to add additional public keys by doing:
-
-	keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]
-
-e.g.:
-
-	keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509
-
-Note, however, that the kernel will only permit keys to be added to
-.system_keyring _if_ the new key's X.509 wrapper is validly signed by a key
-that is already resident in the .system_keyring at the time the key was added.
-
-
-=========================
-MANUALLY SIGNING MODULES
-=========================
-
-To manually sign a module, use the scripts/sign-file tool available in
-the Linux kernel source tree.  The script requires 4 arguments:
-
-	1.  The hash algorithm (e.g., sha256)
-	2.  The private key filename or PKCS#11 URI
-	3.  The public key filename
-	4.  The kernel module to be signed
-
-The following is an example to sign a kernel module:
-
-	scripts/sign-file sha512 kernel-signkey.priv \
-		kernel-signkey.x509 module.ko
-
-The hash algorithm used does not have to match the one configured, but if it
-doesn't, you should make sure that hash algorithm is either built into the
-kernel or can be loaded without requiring itself.
-
-If the private key requires a passphrase or PIN, it can be provided in the
-$KBUILD_SIGN_PIN environment variable.
-
-
-============================
-SIGNED MODULES AND STRIPPING
-============================
-
-A signed module has a digital signature simply appended at the end.  The string
-"~Module signature appended~." at the end of the module's file confirms that a
-signature is present but it does not confirm that the signature is valid!
-
-Signed modules are BRITTLE as the signature is outside of the defined ELF
-container.  Thus they MAY NOT be stripped once the signature is computed and
-attached.  Note the entire module is the signed payload, including any and all
-debug information present at the time of signing.
-
-
-======================
-LOADING SIGNED MODULES
-======================
-
-Modules are loaded with insmod, modprobe, init_module() or finit_module(),
-exactly as for unsigned modules as no processing is done in userspace.  The
-signature checking is all done within the kernel.
-
-
-=========================================
-NON-VALID SIGNATURES AND UNSIGNED MODULES
-=========================================
-
-If CONFIG_MODULE_SIG_FORCE is enabled or module.sig_enforce=1 is supplied on
-the kernel command line, the kernel will only load validly signed modules
-for which it has a public key.   Otherwise, it will also load modules that are
-unsigned.   Any module for which the kernel has a key, but which proves to have
-a signature mismatch will not be permitted to load.
-
-Any module that has an unparseable signature will be rejected.
-
-
-=========================================
-ADMINISTERING/PROTECTING THE PRIVATE KEY
-=========================================
-
-Since the private key is used to sign modules, viruses and malware could use
-the private key to sign modules and compromise the operating system.  The
-private key must be either destroyed or moved to a secure location and not kept
-in the root node of the kernel source tree.
-
-If you use the same private key to sign modules for multiple kernel
-configurations, you must ensure that the module version information is
-sufficient to prevent loading a module into a different kernel.  Either
-set CONFIG_MODVERSIONS=y or ensure that each configuration has a different
-kernel release string by changing EXTRAVERSION or CONFIG_LOCALVERSION.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/mono.txt linux-libre-4.10-rc8-gnu/Documentation/mono.txt
--- linux-libre-4.9-gnu/Documentation/mono.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/mono.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-               Mono(tm) Binary Kernel Support for Linux
-               -----------------------------------------
-
-To configure Linux to automatically execute Mono-based .NET binaries
-(in the form of .exe files) without the need to use the mono CLR
-wrapper, you can use the BINFMT_MISC kernel support.
-
-This will allow you to execute Mono-based .NET binaries just like any
-other program after you have done the following:
-
-1) You MUST FIRST install the Mono CLR support, either by downloading
-   a binary package, a source tarball or by installing from CVS. Binary
-   packages for several distributions can be found at:
-
-	http://go-mono.com/download.html
-
-   Instructions for compiling Mono can be found at:
-
-	http://www.go-mono.com/compiling.html
-
-   Once the Mono CLR support has been installed, just check that
-   /usr/bin/mono (which could be located elsewhere, for example
-   /usr/local/bin/mono) is working.
-
-2) You have to compile BINFMT_MISC either as a module or into
-   the kernel (CONFIG_BINFMT_MISC) and set it up properly.
-   If you choose to compile it as a module, you will have
-   to insert it manually with modprobe/insmod, as kmod
-   cannot be easily supported with binfmt_misc. 
-   Read the file 'binfmt_misc.txt' in this directory to know
-   more about the configuration process.
-
-3) Add the following entries to /etc/rc.local or similar script
-   to be run at system startup:
-
-# Insert BINFMT_MISC module into the kernel
-if [ ! -e /proc/sys/fs/binfmt_misc/register ]; then
-        /sbin/modprobe binfmt_misc
-	# Some distributions, like Fedora Core, perform
-	# the following command automatically when the
-	# binfmt_misc module is loaded into the kernel
-	# or during normal boot up (systemd-based systems).
-	# Thus, it is possible that the following line
-	# is not needed at all.
-	mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
-fi
-
-# Register support for .NET CLR binaries
-if [ -e /proc/sys/fs/binfmt_misc/register ]; then
-	# Replace /usr/bin/mono with the correct pathname to
-	# the Mono CLR runtime (usually /usr/local/bin/mono
-	# when compiling from sources or CVS).
-        echo ':CLR:M::MZ::/usr/bin/mono:' > /proc/sys/fs/binfmt_misc/register
-else
-        echo "No binfmt_misc support"
-        exit 1
-fi
-
-4) Check that .exe binaries can be ran without the need of a
-   wrapper script, simply by launching the .exe file directly
-   from a command prompt, for example:
-
-	/usr/bin/xsd.exe
-
-   NOTE: If this fails with a permission denied error, check
-         that the .exe file has execute permissions.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/batman-adv.txt linux-libre-4.10-rc8-gnu/Documentation/networking/batman-adv.txt
--- linux-libre-4.9-gnu/Documentation/networking/batman-adv.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/batman-adv.txt	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@ compatible interfaces. Once found, it wi
 the /sys directories of each supported interface, e.g.
 
 # ls /sys/class/net/eth0/batman_adv/
-# iface_status  mesh_iface
+# elp_interval  iface_status  mesh_iface  throughput_override
 
 If an interface does not have the "batman_adv" subfolder it prob-
 ably is not supported. Not supported  interfaces  are:  loopback,
@@ -71,17 +71,19 @@ All  mesh  wide  settings  can be found
 folder:
 
 # ls /sys/class/net/bat0/mesh/
-#aggregated_ogms        distributed_arp_table  gw_sel_class    orig_interval
-#ap_isolation           fragmentation          hop_penalty     routing_algo
-#bonding                gw_bandwidth           isolation_mark  vlan0
-#bridge_loop_avoidance  gw_mode                log_level
+# aggregated_ogms        fragmentation  isolation_mark  routing_algo
+# ap_isolation           gw_bandwidth   log_level       vlan0
+# bonding                gw_mode        multicast_mode
+# bridge_loop_avoidance  gw_sel_class   network_coding
+# distributed_arp_table  hop_penalty    orig_interval
 
 There is a special folder for debugging information:
 
 # ls /sys/kernel/debug/batman_adv/bat0/
-# bla_backbone_table  log                 transtable_global
-# bla_claim_table     originators         transtable_local
-# gateways            socket
+# bla_backbone_table  log          neighbors          transtable_local
+# bla_claim_table     mcast_flags  originators
+# dat_cache           nc           socket
+# gateways            nc_nodes     transtable_global
 
 Some of the files contain all sort of status information  regard-
 ing  the  mesh  network.  For  example, you can view the table of
@@ -159,13 +161,16 @@ file in debugfs
 The additional debug output is by default disabled. It can be en-
 abled  during run time. Following log_levels are defined:
 
-0 - All  debug  output  disabled
-1 - Enable messages related to routing / flooding / broadcasting
-2 - Enable messages related to route added / changed / deleted
-4 - Enable messages related to translation table operations
-8 - Enable messages related to bridge loop avoidance
-16 - Enable messaged related to DAT, ARP snooping and parsing
-31 - Enable all messages
+  0 - All  debug  output  disabled
+  1 - Enable messages related to routing / flooding / broadcasting
+  2 - Enable messages related to route added / changed / deleted
+  4 - Enable messages related to translation table operations
+  8 - Enable messages related to bridge loop avoidance
+ 16 - Enable messages related to DAT, ARP snooping and parsing
+ 32 - Enable messages related to network coding
+ 64 - Enable messages related to multicast
+128 - Enable messages related to throughput meter
+255 - Enable all messages
 
 The debug output can be changed at runtime  using  the  file
 /sys/class/net/bat0/mesh/log_level. e.g.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/ieee802154.txt linux-libre-4.10-rc8-gnu/Documentation/networking/ieee802154.txt
--- linux-libre-4.9-gnu/Documentation/networking/ieee802154.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/ieee802154.txt	2017-02-12 16:03:20.000000000 -0500
@@ -4,20 +4,20 @@
 
 Introduction
 ============
-The IEEE 802.15.4 working group focuses on standardization of bottom
-two layers: Medium Access Control (MAC) and Physical (PHY). And there
+The IEEE 802.15.4 working group focuses on standardization of the bottom
+two layers: Medium Access Control (MAC) and Physical access (PHY). And there
 are mainly two options available for upper layers:
  - ZigBee - proprietary protocol from the ZigBee Alliance
  - 6LoWPAN - IPv6 networking over low rate personal area networks
 
-The linux-wpan project goal is to provide a complete implementation
+The goal of the Linux-wpan is to provide a complete implementation
 of the IEEE 802.15.4 and 6LoWPAN protocols. IEEE 802.15.4 is a stack
 of protocols for organizing Low-Rate Wireless Personal Area Networks.
 
 The stack is composed of three main parts:
  - IEEE 802.15.4 layer;  We have chosen to use plain Berkeley socket API,
-   the generic Linux networking stack to transfer IEEE 802.15.4 messages
-   and a special protocol over genetlink for configuration/management
+   the generic Linux networking stack to transfer IEEE 802.15.4 data
+   messages and a special protocol over netlink for configuration/management
  - MAC - provides access to shared channel and reliable data delivery
  - PHY - represents device drivers
 
@@ -33,15 +33,13 @@ include/net/af_ieee802154.h header or in
 in the userspace package (see either http://wpan.cakelab.org/ or the
 git tree at https://github.com/linux-wpan/wpan-tools).
 
-One can use SOCK_RAW for passing raw data towards device xmit function. YMMV.
-
 
 Kernel side
 =============
 
 Like with WiFi, there are several types of devices implementing IEEE 802.15.4.
 1) 'HardMAC'. The MAC layer is implemented in the device itself, the device
-   exports MLME and data API.
+   exports a management (e.g. MLME) and data API.
 2) 'SoftMAC' or just radio. These types of devices are just radio transceivers
    possibly with some kinds of acceleration like automatic CRC computation and
    comparation, automagic ACK handling, address matching, etc.
@@ -106,7 +104,7 @@ Fake drivers
 
 In addition there is a driver available which simulates a real device with
 SoftMAC (fakelb - IEEE 802.15.4 loopback driver) interface. This option
-provides possibility to test and debug stack without usage of real hardware.
+provides a possibility to test and debug the stack without usage of real hardware.
 
 See sources in drivers/net/ieee802154 folder for more details.
 
@@ -125,17 +123,15 @@ to support the IPv6 minimum MTU requirem
 compression for IPv6 datagrams (LOWPAN_HC1 and LOWPAN_HC2) to reduce the
 relatively large IPv6 and UDP headers down to (in the best case) several bytes.
 
-In Semptember 2011 the standard update was published - [RFC6282].
+In September 2011 the standard update was published - [RFC6282].
 It deprecates HC1 and HC2 compression and defines IPHC encoding format which is
 used in this Linux implementation.
 
 All the code related to 6lowpan you may find in files: net/6lowpan/*
 and net/ieee802154/6lowpan/*
 
-To setup 6lowpan interface you need (busybox release > 1.17.0):
-1. Add IEEE802.15.4 interface and initialize PANid;
+To setup a 6LoWPAN interface you need:
+1. Add IEEE802.15.4 interface and set channel and PAN ID;
 2. Add 6lowpan interface by command like:
    # ip link add link wpan0 name lowpan0 type lowpan
-3. Set MAC (if needs):
-   # ip link set lowpan0 address de:ad:be:ef:ca:fe:ba:be
-4. Bring up 'lowpan0' interface
+3. Bring up 'lowpan0' interface
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/ip-sysctl.txt linux-libre-4.10-rc8-gnu/Documentation/networking/ip-sysctl.txt
--- linux-libre-4.9-gnu/Documentation/networking/ip-sysctl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/ip-sysctl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -610,8 +610,13 @@ tcp_syn_retries - INTEGER
 	with the current initial RTO of 1second. With this the final timeout
 	for an active TCP connection attempt will happen after 127seconds.
 
-tcp_timestamps - BOOLEAN
-	Enable timestamps as defined in RFC1323.
+tcp_timestamps - INTEGER
+Enable timestamps as defined in RFC1323.
+	0: Disabled.
+	1: Enable timestamps as defined in RFC1323 and use random offset for
+	each connection rather than only using the current time.
+	2: Like 1, but without random offsets.
+	Default: 1
 
 tcp_min_tso_segs - INTEGER
 	Minimal number of segments per TSO frame.
@@ -967,6 +972,21 @@ igmp_qrv - INTEGER
 	Default: 2 (as specified by RFC2236 8.1)
 	Minimum: 1 (as specified by RFC6636 4.5)
 
+force_igmp_version - INTEGER
+	0 - (default) No enforcement of a IGMP version, IGMPv1/v2 fallback
+	    allowed. Will back to IGMPv3 mode again if all IGMPv1/v2 Querier
+	    Present timer expires.
+	1 - Enforce to use IGMP version 1. Will also reply IGMPv1 report if
+	    receive IGMPv2/v3 query.
+	2 - Enforce to use IGMP version 2. Will fallback to IGMPv1 if receive
+	    IGMPv1 query message. Will reply report if receive IGMPv3 query.
+	3 - Enforce to use IGMP version 3. The same react with default 0.
+
+	Note: this is not the same with force_mld_version because IGMPv3 RFC3376
+	Security Considerations does not have clear description that we could
+	ignore other version messages completely as MLDv2 RFC3810. So make
+	this value as default 0 is recommended.
+
 conf/interface/*  changes special settings per interface (where
 "interface" is the name of your network interface)
 
@@ -1714,6 +1734,15 @@ drop_unsolicited_na - BOOLEAN
 
 	By default this is turned off.
 
+enhanced_dad - BOOLEAN
+	Include a nonce option in the IPv6 neighbor solicitation messages used for
+	duplicate address detection per RFC7527. A received DAD NS will only signal
+	a duplicate address if the nonce is different. This avoids any false
+	detection of duplicates due to loopback of the NS messages that we send.
+	The nonce option will be sent on an interface unless both of
+	conf/{all,interface}/enhanced_dad are set to FALSE.
+	Default: TRUE
+
 icmp/*:
 ratelimit - INTEGER
 	Limit the maximal rates for sending ICMPv6 packets.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/l2tp.txt linux-libre-4.10-rc8-gnu/Documentation/networking/l2tp.txt
--- linux-libre-4.9-gnu/Documentation/networking/l2tp.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/l2tp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -177,10 +177,10 @@ setsockopt on the PPPoX socket to set a
 
 The following debug mask bits are available:
 
-PPPOL2TP_MSG_DEBUG    verbose debug (if compiled in)
-PPPOL2TP_MSG_CONTROL  userspace - kernel interface
-PPPOL2TP_MSG_SEQ      sequence numbers handling
-PPPOL2TP_MSG_DATA     data packets
+L2TP_MSG_DEBUG    verbose debug (if compiled in)
+L2TP_MSG_CONTROL  userspace - kernel interface
+L2TP_MSG_SEQ      sequence numbers handling
+L2TP_MSG_DATA     data packets
 
 If enabled, files under a l2tp debugfs directory can be used to dump
 kernel state about L2TP tunnels and sessions. To access it, the
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/mac80211_hwsim/README linux-libre-4.10-rc8-gnu/Documentation/networking/mac80211_hwsim/README
--- linux-libre-4.9-gnu/Documentation/networking/mac80211_hwsim/README	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/mac80211_hwsim/README	2017-02-12 16:03:20.000000000 -0500
@@ -60,7 +60,7 @@ modprobe mac80211_hwsim
 hostapd hostapd.conf
 
 # Run wpa_supplicant (station) for wlan1
-wpa_supplicant -Dwext -iwlan1 -c wpa_supplicant.conf
+wpa_supplicant -Dnl80211 -iwlan1 -c wpa_supplicant.conf
 
 
 More test cases are available in hostap.git:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/mpls-sysctl.txt linux-libre-4.10-rc8-gnu/Documentation/networking/mpls-sysctl.txt
--- linux-libre-4.9-gnu/Documentation/networking/mpls-sysctl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/mpls-sysctl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -5,8 +5,8 @@ platform_labels - INTEGER
 	possible to configure forwarding for label values equal to or
 	greater than the number of platform labels.
 
-	A dense utliziation of the entries in the platform label table
-	is possible and expected aas the platform labels are locally
+	A dense utilization of the entries in the platform label table
+	is possible and expected as the platform labels are locally
 	allocated.
 
 	If the number of platform label table entries is set to 0 no
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/netconsole.txt linux-libre-4.10-rc8-gnu/Documentation/networking/netconsole.txt
--- linux-libre-4.9-gnu/Documentation/networking/netconsole.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/netconsole.txt	2017-02-12 16:03:20.000000000 -0500
@@ -200,7 +200,7 @@ priority messages to the console. You ca
 or by specifying "debug" on the kernel command line at boot, to send
 all kernel messages to the console. A specific value for this parameter
 can also be set using the "loglevel" kernel boot option. See the
-dmesg(8) man page and Documentation/kernel-parameters.txt for details.
+dmesg(8) man page and Documentation/admin-guide/kernel-parameters.rst for details.
 
 Netconsole was designed to be as instantaneous as possible, to
 enable the logging of even the most critical kernel bugs. It works
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/netdev-FAQ.txt linux-libre-4.10-rc8-gnu/Documentation/networking/netdev-FAQ.txt
--- linux-libre-4.9-gnu/Documentation/networking/netdev-FAQ.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/netdev-FAQ.txt	2017-02-12 16:03:20.000000000 -0500
@@ -136,14 +136,14 @@ A: Normally Greg Kroah-Hartman collects
 
 Q: I see a network patch and I think it should be backported to stable.
    Should I request it via "stable@vger.kernel.org" like the references in
-   the kernel's Documentation/stable_kernel_rules.txt file say?
+   the kernel's Documentation/process/stable-kernel-rules.rst file say?
 
 A: No, not for networking.  Check the stable queues as per above 1st to see
    if it is already queued.  If not, then send a mail to netdev, listing
    the upstream commit ID and why you think it should be a stable candidate.
 
    Before you jump to go do the above, do note that the normal stable rules
-   in Documentation/stable_kernel_rules.txt still apply.  So you need to
+   in Documentation/process/stable-kernel-rules.rst still apply.  So you need to
    explicitly indicate why it is a critical fix and exactly what users are
    impacted.  In addition, you need to convince yourself that you _really_
    think it has been overlooked, vs. having been considered and rejected.
@@ -165,7 +165,7 @@ A: No.  See above answer.  In short, if
 
    If you think there is some valid information relating to it being in
    stable that does _not_ belong in the commit log, then use the three
-   dash marker line as described in Documentation/SubmittingPatches to
+   dash marker line as described in Documentation/process/submitting-patches.rst to
    temporarily embed that information into the patch that you send.
 
 Q: Someone said that the comment style and coding convention is different
@@ -220,5 +220,5 @@ A: Attention to detail.  Re-read your ow
    If it is your first patch, mail it to yourself so you can test apply
    it to an unpatched tree to confirm infrastructure didn't mangle it.
 
-   Finally, go back and read Documentation/SubmittingPatches to be
+   Finally, go back and read Documentation/process/submitting-patches.rst to be
    sure you are not repeating some common mistake documented there.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/nf_conntrack-sysctl.txt linux-libre-4.10-rc8-gnu/Documentation/networking/nf_conntrack-sysctl.txt
--- linux-libre-4.9-gnu/Documentation/networking/nf_conntrack-sysctl.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/nf_conntrack-sysctl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -96,6 +96,17 @@ nf_conntrack_max - INTEGER
 	Size of connection tracking table.  Default value is
 	nf_conntrack_buckets value * 4.
 
+nf_conntrack_default_on - BOOLEAN
+	0 - don't register conntrack in new net namespaces
+	1 - register conntrack in new net namespaces (default)
+
+	This controls wheter newly created network namespaces have connection
+	tracking enabled by default.  It will be enabled automatically
+	regardless of this setting if the new net namespace requires
+	connection tracking, e.g. when NAT rules are created.
+	This setting is only visible in initial user namespace, it has no
+	effect on existing namespaces.
+
 nf_conntrack_tcp_be_liberal - BOOLEAN
 	0 - disabled (default)
 	not 0 - enabled
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/phy.txt linux-libre-4.10-rc8-gnu/Documentation/networking/phy.txt
--- linux-libre-4.9-gnu/Documentation/networking/phy.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/phy.txt	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,83 @@ The MDIO bus
  drivers/net/ethernet/freescale/fsl_pq_mdio.c and an associated DTS file
  for one of the users. (e.g. "git grep fsl,.*-mdio arch/powerpc/boot/dts/")
 
+(RG)MII/electrical interface considerations
+
+ The Reduced Gigabit Medium Independent Interface (RGMII) is a 12-pin
+ electrical signal interface using a synchronous 125Mhz clock signal and several
+ data lines. Due to this design decision, a 1.5ns to 2ns delay must be added
+ between the clock line (RXC or TXC) and the data lines to let the PHY (clock
+ sink) have enough setup and hold times to sample the data lines correctly. The
+ PHY library offers different types of PHY_INTERFACE_MODE_RGMII* values to let
+ the PHY driver and optionally the MAC driver, implement the required delay. The
+ values of phy_interface_t must be understood from the perspective of the PHY
+ device itself, leading to the following:
+
+ * PHY_INTERFACE_MODE_RGMII: the PHY is not responsible for inserting any
+   internal delay by itself, it assumes that either the Ethernet MAC (if capable
+   or the PCB traces) insert the correct 1.5-2ns delay
+
+ * PHY_INTERFACE_MODE_RGMII_TXID: the PHY should insert an internal delay
+   for the transmit data lines (TXD[3:0]) processed by the PHY device
+
+ * PHY_INTERFACE_MODE_RGMII_RXID: the PHY should insert an internal delay
+   for the receive data lines (RXD[3:0]) processed by the PHY device
+
+ * PHY_INTERFACE_MODE_RGMII_ID: the PHY should insert internal delays for
+   both transmit AND receive data lines from/to the PHY device
+
+ Whenever possible, use the PHY side RGMII delay for these reasons:
+
+ * PHY devices may offer sub-nanosecond granularity in how they allow a
+   receiver/transmitter side delay (e.g: 0.5, 1.0, 1.5ns) to be specified. Such
+   precision may be required to account for differences in PCB trace lengths
+
+ * PHY devices are typically qualified for a large range of applications
+   (industrial, medical, automotive...), and they provide a constant and
+   reliable delay across temperature/pressure/voltage ranges
+
+ * PHY device drivers in PHYLIB being reusable by nature, being able to
+   configure correctly a specified delay enables more designs with similar delay
+   requirements to be operate correctly
+
+ For cases where the PHY is not capable of providing this delay, but the
+ Ethernet MAC driver is capable of doing so, the correct phy_interface_t value
+ should be PHY_INTERFACE_MODE_RGMII, and the Ethernet MAC driver should be
+ configured correctly in order to provide the required transmit and/or receive
+ side delay from the perspective of the PHY device. Conversely, if the Ethernet
+ MAC driver looks at the phy_interface_t value, for any other mode but
+ PHY_INTERFACE_MODE_RGMII, it should make sure that the MAC-level delays are
+ disabled.
+
+ In case neither the Ethernet MAC, nor the PHY are capable of providing the
+ required delays, as defined per the RGMII standard, several options may be
+ available:
+
+ * Some SoCs may offer a pin pad/mux/controller capable of configuring a given
+   set of pins'strength, delays, and voltage; and it may be a suitable
+   option to insert the expected 2ns RGMII delay.
+
+ * Modifying the PCB design to include a fixed delay (e.g: using a specifically
+   designed serpentine), which may not require software configuration at all.
+
+Common problems with RGMII delay mismatch
+
+ When there is a RGMII delay mismatch between the Ethernet MAC and the PHY, this
+ will most likely result in the clock and data line signals to be unstable when
+ the PHY or MAC take a snapshot of these signals to translate them into logical
+ 1 or 0 states and reconstruct the data being transmitted/received. Typical
+ symptoms include:
+
+ * Transmission/reception partially works, and there is frequent or occasional
+   packet loss observed
+
+ * Ethernet MAC may report some or all packets ingressing with a FCS/CRC error,
+   or just discard them all
+
+ * Switching to lower speeds such as 10/100Mbits/sec makes the problem go away
+   (since there is enough setup/hold time in that case)
+
+
 Connecting to a PHY
 
  Sometime during startup, the network driver needs to establish a connection
@@ -127,8 +204,9 @@ Letting the PHY Abstraction Layer do Eve
  values pruned from them which don't make sense for your controller (a 10/100
  controller may be connected to a gigabit capable PHY, so you would need to
  mask off SUPPORTED_1000baseT*).  See include/linux/ethtool.h for definitions
- for these bitfields. Note that you should not SET any bits, or the PHY may
- get put into an unsupported state.
+ for these bitfields. Note that you should not SET any bits, except the
+ SUPPORTED_Pause and SUPPORTED_AsymPause bits (see below), or the PHY may get
+ put into an unsupported state.
 
  Lastly, once the controller is ready to handle network traffic, you call
  phy_start(phydev).  This tells the PAL that you are ready, and configures the
@@ -139,6 +217,19 @@ Letting the PHY Abstraction Layer do Eve
  When you want to disconnect from the network (even if just briefly), you call
  phy_stop(phydev).
 
+Pause frames / flow control
+
+ The PHY does not participate directly in flow control/pause frames except by
+ making sure that the SUPPORTED_Pause and SUPPORTED_AsymPause bits are set in
+ MII_ADVERTISE to indicate towards the link partner that the Ethernet MAC
+ controller supports such a thing. Since flow control/pause frames generation
+ involves the Ethernet MAC driver, it is recommended that this driver takes care
+ of properly indicating advertisement and support for such features by setting
+ the SUPPORTED_Pause and SUPPORTED_AsymPause bits accordingly. This can be done
+ either before or after phy_connect() and/or as a result of implementing the
+ ethtool::set_pauseparam feature.
+
+
 Keeping Close Tabs on the PAL
 
  It is possible that the PAL's built-in state machine needs a little help to
@@ -251,39 +342,8 @@ Writing a PHY driver
  PHY_BASIC_FEATURES, but you can look in include/mii.h for other
  features.
 
- Each driver consists of a number of function pointers:
-
-   soft_reset: perform a PHY software reset
-   config_init: configures PHY into a sane state after a reset.
-     For instance, a Davicom PHY requires descrambling disabled.
-   probe: Allocate phy->priv, optionally refuse to bind.
-   PHY may not have been reset or had fixups run yet.
-   suspend/resume: power management
-   config_aneg: Changes the speed/duplex/negotiation settings
-   aneg_done: Determines the auto-negotiation result
-   read_status: Reads the current speed/duplex/negotiation settings
-   ack_interrupt: Clear a pending interrupt
-   did_interrupt: Checks if the PHY generated an interrupt
-   config_intr: Enable or disable interrupts
-   remove: Does any driver take-down
-   ts_info: Queries about the HW timestamping status
-   match_phy_device: used for Clause 45 capable PHYs to match devices
-   in package and ensure they are compatible
-   hwtstamp: Set the PHY HW timestamping configuration
-   rxtstamp: Requests a receive timestamp at the PHY level for a 'skb'
-   txtsamp: Requests a transmit timestamp at the PHY level for a 'skb'
-   set_wol: Enable Wake-on-LAN at the PHY level
-   get_wol: Get the Wake-on-LAN status at the PHY level
-   link_change_notify: called to inform the core is about to change the
-   link state, can be used to work around bogus PHY between state changes
-   read_mmd_indirect: Read PHY MMD indirect register
-   write_mmd_indirect: Write PHY MMD indirect register
-   module_info: Get the size and type of an EEPROM contained in an plug-in
-   module
-   module_eeprom: Get EEPROM information of a plug-in module
-   get_sset_count: Get number of strings sets that get_strings will count
-   get_strings: Get strings from requested objects (statistics)
-   get_stats: Get the extended statistics from the PHY device
+ Each driver consists of a number of function pointers, documented
+ in include/linux/phy.h under the phy_driver structure.
 
  Of these, only config_aneg and read_status are required to be
  assigned by the driver code.  The rest are optional.  Also, it is
@@ -347,3 +407,22 @@ Board Fixups
  The stubs set one of the two matching criteria, and set the other one to
  match anything.
 
+ When phy_register_fixup() or *_for_uid()/*_for_id() is called at module,
+ unregister fixup and free allocate memory are required.
+
+ Call one of following function before unloading module.
+
+ int phy_unregister_fixup(const char *phy_id, u32 phy_uid, u32 phy_uid_mask);
+ int phy_unregister_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask);
+ int phy_register_fixup_for_id(const char *phy_id);
+
+Standards
+
+ IEEE Standard 802.3: CSMA/CD Access Method and Physical Layer Specifications, Section Two:
+ http://standards.ieee.org/getieee802/download/802.3-2008_section2.pdf
+
+ RGMII v1.3:
+ http://web.archive.org/web/20160303212629/http://www.hp.com/rnd/pdfs/RGMIIv1_3.pdf
+
+ RGMII v2.0:
+ http://web.archive.org/web/20160303171328/http://www.hp.com/rnd/pdfs/RGMIIv2_0_final_hp.pdf
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/seg6-sysctl.txt linux-libre-4.10-rc8-gnu/Documentation/networking/seg6-sysctl.txt
--- linux-libre-4.9-gnu/Documentation/networking/seg6-sysctl.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/seg6-sysctl.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,18 @@
+/proc/sys/net/conf/<iface>/seg6_* variables:
+
+seg6_enabled - BOOL
+	Accept or drop SR-enabled IPv6 packets on this interface.
+
+	Relevant packets are those with SRH present and DA = local.
+
+	0 - disabled (default)
+	not 0 - enabled
+
+seg6_require_hmac - INTEGER
+	Define HMAC policy for ingress SR-enabled packets on this interface.
+
+	-1 - Ignore HMAC field
+	0 - Accept SR packets without HMAC, validate SR packets with HMAC
+	1 - Drop SR packets without HMAC, validate SR packets with HMAC
+
+	Default is 0.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/stmmac.txt linux-libre-4.10-rc8-gnu/Documentation/networking/stmmac.txt
--- linux-libre-4.9-gnu/Documentation/networking/stmmac.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/stmmac.txt	2017-02-12 16:03:20.000000000 -0500
@@ -28,8 +28,6 @@ CONFIG_STMMAC_PCI: is to enable the pci
 2) Driver parameters list:
 	debug: message level (0: no output, 16: all);
 	phyaddr: to manually provide the physical address to the PHY device;
-	dma_rxsize: DMA rx ring size;
-	dma_txsize: DMA tx ring size;
 	buf_sz: DMA buffer size;
 	tc: control the HW FIFO threshold;
 	watchdog: transmit timeout (in milliseconds);
@@ -40,31 +38,31 @@ CONFIG_STMMAC_PCI: is to enable the pci
 
 3) Command line options
 Driver parameters can be also passed in command line by using:
-	stmmaceth=dma_rxsize:128,dma_txsize:512
+	stmmaceth=watchdog:100,chain_mode=1
 
 4) Driver information and notes
 
 4.1) Transmit process
 The xmit method is invoked when the kernel needs to transmit a packet; it sets
-the descriptors in the ring and informs the DMA engine that there is a packet
+the descriptors in the ring and informs the DMA engine, that there is a packet
 ready to be transmitted.
 By default, the driver sets the NETIF_F_SG bit in the features field of the
-net_device structure enabling the scatter-gather feature. This is true on
+net_device structure, enabling the scatter-gather feature. This is true on
 chips and configurations where the checksum can be done in hardware.
-Once the controller has finished transmitting the packet, napi will be
+Once the controller has finished transmitting the packet, timer will be
 scheduled to release the transmit resources.
 
 4.2) Receive process
 When one or more packets are received, an interrupt happens. The interrupts
-are not queued so the driver has to scan all the descriptors in the ring during
+are not queued, so the driver has to scan all the descriptors in the ring during
 the receive process.
-This is based on NAPI so the interrupt handler signals only if there is work
+This is based on NAPI, so the interrupt handler signals only if there is work
 to be done, and it exits.
 Then the poll method will be scheduled at some future point.
 The incoming packets are stored, by the DMA, in a list of pre-allocated socket
 buffers in order to avoid the memcpy (zero-copy).
 
-4.3) Interrupt Mitigation
+4.3) Interrupt mitigation
 The driver is able to mitigate the number of its DMA interrupts
 using NAPI for the reception on chips older than the 3.50.
 New chips have an HW RX-Watchdog used for this mitigation.
@@ -88,19 +86,20 @@ the list, hence creating the explicit ch
 whereas such explicit chaining is not possible in RING mode.
 
 4.5.1) Extended descriptors
-	The extended descriptors give us information about the Ethernet payload
-	when it is carrying PTP packets or TCP/UDP/ICMP over IP.
-	These are not available on GMAC Synopsys chips older than the 3.50.
-	At probe time the driver will decide if these can be actually used.
-	This support also is mandatory for PTPv2 because the extra descriptors
-	are used for saving the hardware timestamps and Extended Status.
+The extended descriptors give us information about the Ethernet payload
+when it is carrying PTP packets or TCP/UDP/ICMP over IP.
+These are not available on GMAC Synopsys chips older than the 3.50.
+At probe time the driver will decide if these can be actually used.
+This support also is mandatory for PTPv2 because the extra descriptors
+are used for saving the hardware timestamps and Extended Status.
 
 4.6) Ethtool support
 Ethtool is supported.
 
 For example, driver statistics (including RMON), internal errors can be taken
 using:
-  # ethtool -S ethX command
+  # ethtool -S ethX
+command
 
 4.7) Jumbo and Segmentation Offloading
 Jumbo frames are supported and tested for the GMAC.
@@ -153,8 +152,10 @@ Where:
  o dma_cfg: internal DMA parameters
    o pbl: the Programmable Burst Length is maximum number of beats to
        be transferred in one DMA transaction.
-       GMAC also enables the 4xPBL by default.
-   o fixed_burst/mixed_burst/burst_len
+       GMAC also enables the 4xPBL by default. (8xPBL for GMAC 3.50 and newer)
+   o txpbl/rxpbl: GMAC and newer supports independent DMA pbl for tx/rx.
+   o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
+   o fixed_burst/mixed_burst/aal
  o clk_csr: fixed CSR Clock range selection.
  o has_gmac: uses the GMAC core.
  o enh_desc: if sets the MAC will use the enhanced descriptor structure.
@@ -206,16 +207,24 @@ tuned according to the HW capabilities.
 
 struct stmmac_dma_cfg {
 	int pbl;
+	int txpbl;
+	int rxpbl;
+	bool pblx8;
 	int fixed_burst;
-	int burst_len_supported;
+	int mixed_burst;
+	bool aal;
 };
 
 Where:
- o pbl: Programmable Burst Length
+ o pbl: Programmable Burst Length (tx and rx)
+ o txpbl: Transmit Programmable Burst Length. Only for GMAC and newer.
+	 If set, DMA tx will use this value rather than pbl.
+ o rxpbl: Receive Programmable Burst Length. Only for GMAC and newer.
+	 If set, DMA rx will use this value rather than pbl.
+ o pblx8: Enable 8xPBL (4xPBL for core rev < 3.50). Enabled by default.
  o fixed_burst: program the DMA to use the fixed burst mode
- o burst_len: this is the value we put in the register
-	      supported values are provided as macros in
-	      linux/stmmac.h header file.
+ o mixed_burst: program the DMA to use the mixed burst mode
+ o aal: Address-Aligned Beats
 
 ---
 
@@ -275,11 +284,11 @@ Please see the following document:
 	Documentation/devicetree/bindings/net/stmmac.txt
 
 4.11) This is a summary of the content of some relevant files:
- o stmmac_main.c: to implement the main network device driver;
- o stmmac_mdio.c: to provide mdio functions;
- o stmmac_pci: this the PCI driver;
- o stmmac_platform.c: this the platform driver (OF supported)
- o stmmac_ethtool.c: to implement the ethtool support;
+ o stmmac_main.c: implements the main network device driver;
+ o stmmac_mdio.c: provides MDIO functions;
+ o stmmac_pci: this is the PCI driver;
+ o stmmac_platform.c: this the platform driver (OF supported);
+ o stmmac_ethtool.c: implements the ethtool support;
  o stmmac.h: private driver structure;
  o common.h: common definitions and VFTs;
  o mmc_core.c/mmc.h: Management MAC Counters;
@@ -381,12 +390,12 @@ In addition to the basic timestamp featu
 Timestamps, new GMAC cores support the advanced timestamp features.
 IEEE 1588-2008 that can be enabled when configure the Kernel.
 
-8) SGMII/RGMII supports
+8) SGMII/RGMII support
 New GMAC devices provide own way to manage RGMII/SGMII.
 This information is available at run-time by looking at the
 HW capability register. This means that the stmmac can manage
-auto-negotiation and link status w/o using the PHYLIB stuff
+auto-negotiation and link status w/o using the PHYLIB stuff.
 In fact, the HW provides a subset of extended registers to
 restart the ANE, verify Full/Half duplex mode and Speed.
-Also thanks to these registers it is possible to look at the
+Thanks to these registers, it is possible to look at the
 Auto-negotiated Link Parter Ability.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/timestamping.txt linux-libre-4.10-rc8-gnu/Documentation/networking/timestamping.txt
--- linux-libre-4.9-gnu/Documentation/networking/timestamping.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/timestamping.txt	2017-02-12 16:03:20.000000000 -0500
@@ -182,6 +182,16 @@ SOF_TIMESTAMPING_OPT_TSONLY:
   the timestamp even if sysctl net.core.tstamp_allow_data is 0.
   This option disables SOF_TIMESTAMPING_OPT_CMSG.
 
+SOF_TIMESTAMPING_OPT_STATS:
+
+  Optional stats that are obtained along with the transmit timestamps.
+  It must be used together with SOF_TIMESTAMPING_OPT_TSONLY. When the
+  transmit timestamp is available, the stats are available in a
+  separate control message of type SCM_TIMESTAMPING_OPT_STATS, as a
+  list of TLVs (struct nlattr) of types. These stats allow the
+  application to associate various transport layer stats with
+  the transmit timestamps, such as how long a certain block of
+  data was limited by peer's receiver window.
 
 New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to
 disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/networking/vortex.txt linux-libre-4.10-rc8-gnu/Documentation/networking/vortex.txt
--- linux-libre-4.9-gnu/Documentation/networking/vortex.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/networking/vortex.txt	2017-02-12 16:03:20.000000000 -0500
@@ -364,7 +364,7 @@ steps you should take:
 
 - The contents of your report will vary a lot depending upon the
   problem.  If it's a kernel crash then you should refer to the
-  REPORTING-BUGS file.
+  admin-guide/reporting-bugs.rst file.
 
   But for most problems it is useful to provide the following:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/oops-tracing.txt linux-libre-4.10-rc8-gnu/Documentation/oops-tracing.txt
--- linux-libre-4.9-gnu/Documentation/oops-tracing.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/oops-tracing.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,279 +0,0 @@
-NOTE: ksymoops is useless on 2.6.  Please use the Oops in its original format
-(from dmesg, etc).  Ignore any references in this or other docs to "decoding
-the Oops" or "running it through ksymoops".  If you post an Oops from 2.6 that
-has been run through ksymoops, people will just tell you to repost it.
-
-Quick Summary
--------------
-
-Find the Oops and send it to the maintainer of the kernel area that seems to be
-involved with the problem.  Don't worry too much about getting the wrong person.
-If you are unsure send it to the person responsible for the code relevant to
-what you were doing.  If it occurs repeatably try and describe how to recreate
-it.  That's worth even more than the oops.
-
-If you are totally stumped as to whom to send the report, send it to 
-linux-kernel@vger.kernel.org. Thanks for your help in making Linux as
-stable as humanly possible.
-
-Where is the Oops?
-----------------------
-
-Normally the Oops text is read from the kernel buffers by klogd and
-handed to syslogd which writes it to a syslog file, typically
-/var/log/messages (depends on /etc/syslog.conf).  Sometimes klogd dies,
-in which case you can run dmesg > file to read the data from the kernel
-buffers and save it.  Or you can cat /proc/kmsg > file, however you
-have to break in to stop the transfer, kmsg is a "never ending file".
-If the machine has crashed so badly that you cannot enter commands or
-the disk is not available then you have three options :-
-
-(1) Hand copy the text from the screen and type it in after the machine
-    has restarted.  Messy but it is the only option if you have not
-    planned for a crash. Alternatively, you can take a picture of
-    the screen with a digital camera - not nice, but better than
-    nothing.  If the messages scroll off the top of the console, you
-    may find that booting with a higher resolution (eg, vga=791)
-    will allow you to read more of the text. (Caveat: This needs vesafb,
-    so won't help for 'early' oopses)
-
-(2) Boot with a serial console (see Documentation/serial-console.txt),
-    run a null modem to a second machine and capture the output there
-    using your favourite communication program.  Minicom works well.
-
-(3) Use Kdump (see Documentation/kdump/kdump.txt),
-    extract the kernel ring buffer from old memory with using dmesg
-    gdbmacro in Documentation/kdump/gdbmacros.txt.
-
-
-Full Information
-----------------
-
-NOTE: the message from Linus below applies to 2.4 kernel.  I have preserved it
-for historical reasons, and because some of the information in it still
-applies.  Especially, please ignore any references to ksymoops. 
-
-From: Linus Torvalds <torvalds@osdl.org>
-
-How to track down an Oops.. [originally a mail to linux-kernel]
-
-The main trick is having 5 years of experience with those pesky oops 
-messages ;-)
-
-Actually, there are things you can do that make this easier. I have two 
-separate approaches:
-
-	gdb /usr/src/linux/vmlinux
-	gdb> disassemble <offending_function>
-
-That's the easy way to find the problem, at least if the bug-report is 
-well made (like this one was - run through ksymoops to get the 
-information of which function and the offset in the function that it 
-happened in).
-
-Oh, it helps if the report happens on a kernel that is compiled with the 
-same compiler and similar setups.
-
-The other thing to do is disassemble the "Code:" part of the bug report: 
-ksymoops will do this too with the correct tools, but if you don't have
-the tools you can just do a silly program:
-
-	char str[] = "\xXX\xXX\xXX...";
-	main(){}
-
-and compile it with gcc -g and then do "disassemble str" (where the "XX" 
-stuff are the values reported by the Oops - you can just cut-and-paste 
-and do a replace of spaces to "\x" - that's what I do, as I'm too lazy 
-to write a program to automate this all).
-
-Alternatively, you can use the shell script in scripts/decodecode.
-Its usage is:  decodecode < oops.txt
-
-The hex bytes that follow "Code:" may (in some architectures) have a series
-of bytes that precede the current instruction pointer as well as bytes at and
-following the current instruction pointer.  In some cases, one instruction
-byte or word is surrounded by <> or (), as in "<86>" or "(f00d)".  These
-<> or () markings indicate the current instruction pointer.  Example from
-i386, split into multiple lines for readability:
-
-Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
-64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
-7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
-
-Finally, if you want to see where the code comes from, you can do
-
-	cd /usr/src/linux
-	make fs/buffer.s 	# or whatever file the bug happened in
-
-and then you get a better idea of what happens than with the gdb 
-disassembly.
-
-Now, the trick is just then to combine all the data you have: the C 
-sources (and general knowledge of what it _should_ do), the assembly 
-listing and the code disassembly (and additionally the register dump you 
-also get from the "oops" message - that can be useful to see _what_ the 
-corrupted pointers were, and when you have the assembler listing you can 
-also match the other registers to whatever C expressions they were used 
-for).
-
-Essentially, you just look at what doesn't match (in this case it was the 
-"Code" disassembly that didn't match with what the compiler generated). 
-Then you need to find out _why_ they don't match. Often it's simple - you 
-see that the code uses a NULL pointer and then you look at the code and 
-wonder how the NULL pointer got there, and if it's a valid thing to do 
-you just check against it..
-
-Now, if somebody gets the idea that this is time-consuming and requires 
-some small amount of concentration, you're right. Which is why I will 
-mostly just ignore any panic reports that don't have the symbol table 
-info etc looked up: it simply gets too hard to look it up (I have some 
-programs to search for specific patterns in the kernel code segment, and 
-sometimes I have been able to look up those kinds of panics too, but 
-that really requires pretty good knowledge of the kernel just to be able 
-to pick out the right sequences etc..)
-
-_Sometimes_ it happens that I just see the disassembled code sequence 
-from the panic, and I know immediately where it's coming from. That's when 
-I get worried that I've been doing this for too long ;-)
-
-		Linus
-
-
----------------------------------------------------------------------------
-Notes on Oops tracing with klogd:
-
-In order to help Linus and the other kernel developers there has been
-substantial support incorporated into klogd for processing protection
-faults.  In order to have full support for address resolution at least
-version 1.3-pl3 of the sysklogd package should be used.
-
-When a protection fault occurs the klogd daemon automatically
-translates important addresses in the kernel log messages to their
-symbolic equivalents.  This translated kernel message is then
-forwarded through whatever reporting mechanism klogd is using.  The
-protection fault message can be simply cut out of the message files
-and forwarded to the kernel developers.
-
-Two types of address resolution are performed by klogd.  The first is
-static translation and the second is dynamic translation.  Static
-translation uses the System.map file in much the same manner that
-ksymoops does.  In order to do static translation the klogd daemon
-must be able to find a system map file at daemon initialization time.
-See the klogd man page for information on how klogd searches for map
-files.
-
-Dynamic address translation is important when kernel loadable modules
-are being used.  Since memory for kernel modules is allocated from the
-kernel's dynamic memory pools there are no fixed locations for either
-the start of the module or for functions and symbols in the module.
-
-The kernel supports system calls which allow a program to determine
-which modules are loaded and their location in memory.  Using these
-system calls the klogd daemon builds a symbol table which can be used
-to debug a protection fault which occurs in a loadable kernel module.
-
-At the very minimum klogd will provide the name of the module which
-generated the protection fault.  There may be additional symbolic
-information available if the developer of the loadable module chose to
-export symbol information from the module.
-
-Since the kernel module environment can be dynamic there must be a
-mechanism for notifying the klogd daemon when a change in module
-environment occurs.  There are command line options available which
-allow klogd to signal the currently executing daemon that symbol
-information should be refreshed.  See the klogd manual page for more
-information.
-
-A patch is included with the sysklogd distribution which modifies the
-modules-2.0.0 package to automatically signal klogd whenever a module
-is loaded or unloaded.  Applying this patch provides essentially
-seamless support for debugging protection faults which occur with
-kernel loadable modules.
-
-The following is an example of a protection fault in a loadable module
-processed by klogd:
----------------------------------------------------------------------------
-Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
-Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
-Aug 29 09:51:01 blizard kernel: *pde = 00000000
-Aug 29 09:51:01 blizard kernel: Oops: 0002
-Aug 29 09:51:01 blizard kernel: CPU:    0
-Aug 29 09:51:01 blizard kernel: EIP:    0010:[oops:_oops+16/3868]
-Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
-Aug 29 09:51:01 blizard kernel: eax: 315e97cc   ebx: 003a6f80   ecx: 001be77b   edx: 00237c0c
-Aug 29 09:51:01 blizard kernel: esi: 00000000   edi: bffffdb3   ebp: 00589f90   esp: 00589f8c
-Aug 29 09:51:01 blizard kernel: ds: 0018   es: 0018   fs: 002b   gs: 002b   ss: 0018
-Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
-Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001 
-Aug 29 09:51:01 blizard kernel:        00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00 
-Aug 29 09:51:01 blizard kernel:        bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036 
-Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128] 
-Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3 
----------------------------------------------------------------------------
-
-Dr. G.W. Wettstein           Oncology Research Div. Computing Facility
-Roger Maris Cancer Center    INTERNET: greg@wind.rmcc.com
-820 4th St. N.
-Fargo, ND  58122
-Phone: 701-234-7556
-
-
----------------------------------------------------------------------------
-Tainted kernels:
-
-Some oops reports contain the string 'Tainted: ' after the program
-counter. This indicates that the kernel has been tainted by some
-mechanism.  The string is followed by a series of position-sensitive
-characters, each representing a particular tainted value.
-
-  1: 'G' if all modules loaded have a GPL or compatible license, 'P' if
-     any proprietary module has been loaded.  Modules without a
-     MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by
-     insmod as GPL compatible are assumed to be proprietary.
-
-  2: 'F' if any module was force loaded by "insmod -f", ' ' if all
-     modules were loaded normally.
-
-  3: 'S' if the oops occurred on an SMP kernel running on hardware that
-     hasn't been certified as safe to run multiprocessor.
-     Currently this occurs only on various Athlons that are not
-     SMP capable.
-
-  4: 'R' if a module was force unloaded by "rmmod -f", ' ' if all
-     modules were unloaded normally.
-
-  5: 'M' if any processor has reported a Machine Check Exception,
-     ' ' if no Machine Check Exceptions have occurred.
-
-  6: 'B' if a page-release function has found a bad page reference or
-     some unexpected page flags.
-
-  7: 'U' if a user or user application specifically requested that the
-     Tainted flag be set, ' ' otherwise.
-
-  8: 'D' if the kernel has died recently, i.e. there was an OOPS or BUG.
-
-  9: 'A' if the ACPI table has been overridden.
-
- 10: 'W' if a warning has previously been issued by the kernel.
-     (Though some warnings may set more specific taint flags.)
-
- 11: 'C' if a staging driver has been loaded.
-
- 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.
-
- 14: 'E' if an unsigned module has been loaded in a kernel supporting
-     module signature.
-
- 15: 'L' if a soft lockup has previously occurred on the system.
-
- 16: 'K' if the kernel has been live patched.
-
-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
-unloaded, the tainted value remains to indicate that the kernel is not
-trustworthy.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/parport.txt linux-libre-4.10-rc8-gnu/Documentation/parport.txt
--- linux-libre-4.9-gnu/Documentation/parport.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/parport.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,267 +0,0 @@
-The `parport' code provides parallel-port support under Linux.  This
-includes the ability to share one port between multiple device
-drivers.
-
-You can pass parameters to the parport code to override its automatic
-detection of your hardware.  This is particularly useful if you want
-to use IRQs, since in general these can't be autoprobed successfully.
-By default IRQs are not used even if they _can_ be probed.  This is
-because there are a lot of people using the same IRQ for their
-parallel port and a sound card or network card.
-
-The parport code is split into two parts: generic (which deals with
-port-sharing) and architecture-dependent (which deals with actually
-using the port).
-
-
-Parport as modules
-==================
-
-If you load the parport code as a module, say
-
-	# insmod parport
-
-to load the generic parport code.  You then must load the
-architecture-dependent code with (for example):
-
-	# insmod parport_pc io=0x3bc,0x378,0x278 irq=none,7,auto
-
-to tell the parport code that you want three PC-style ports, one at
-0x3bc with no IRQ, one at 0x378 using IRQ 7, and one at 0x278 with an
-auto-detected IRQ.  Currently, PC-style (parport_pc), Sun `bpp',
-Amiga, Atari, and MFC3 hardware is supported.
-
-PCI parallel I/O card support comes from parport_pc.  Base I/O
-addresses should not be specified for supported PCI cards since they
-are automatically detected.
-
-
-modprobe
---------
-
-If you use modprobe , you will find it useful to add lines as below to a
-configuration file in /etc/modprobe.d/ directory:.
-
-	alias parport_lowlevel parport_pc
-	options parport_pc io=0x378,0x278 irq=7,auto
-
-modprobe will load parport_pc (with the options "io=0x378,0x278 irq=7,auto")
-whenever a parallel port device driver (such as lp) is loaded.
-
-Note that these are example lines only!  You shouldn't in general need
-to specify any options to parport_pc in order to be able to use a
-parallel port.
-
-
-Parport probe [optional]
--------------
-
-In 2.2 kernels there was a module called parport_probe, which was used
-for collecting IEEE 1284 device ID information.  This has now been
-enhanced and now lives with the IEEE 1284 support.  When a parallel
-port is detected, the devices that are connected to it are analysed,
-and information is logged like this:
-
-	parport0: Printer, BJC-210 (Canon)
-
-The probe information is available from files in /proc/sys/dev/parport/.
-
-
-Parport linked into the kernel statically
-=========================================
-
-If you compile the parport code into the kernel, then you can use
-kernel boot parameters to get the same effect.  Add something like the
-following to your LILO command line:
-
-	parport=0x3bc parport=0x378,7 parport=0x278,auto,nofifo
-
-You can have many `parport=...' statements, one for each port you want
-to add.  Adding `parport=0' to the kernel command-line will disable
-parport support entirely.  Adding `parport=auto' to the kernel
-command-line will make parport use any IRQ lines or DMA channels that
-it auto-detects.
-
-
-Files in /proc
-==============
-
-If you have configured the /proc filesystem into your kernel, you will
-see a new directory entry: /proc/sys/dev/parport.  In there will be a
-directory entry for each parallel port for which parport is
-configured.  In each of those directories are a collection of files
-describing that parallel port.
-
-The /proc/sys/dev/parport directory tree looks like:
-
-parport
-|-- default
-|   |-- spintime
-|   `-- timeslice
-|-- parport0
-|   |-- autoprobe
-|   |-- autoprobe0
-|   |-- autoprobe1
-|   |-- autoprobe2
-|   |-- autoprobe3
-|   |-- devices
-|   |   |-- active
-|   |   `-- lp
-|   |       `-- timeslice
-|   |-- base-addr
-|   |-- irq
-|   |-- dma
-|   |-- modes
-|   `-- spintime
-`-- parport1
-    |-- autoprobe
-    |-- autoprobe0
-    |-- autoprobe1
-    |-- autoprobe2
-    |-- autoprobe3
-    |-- devices
-    |   |-- active
-    |   `-- ppa
-    |       `-- timeslice
-    |-- base-addr
-    |-- irq
-    |-- dma
-    |-- modes
-    `-- spintime
-
-
-File:		Contents:
-
-devices/active	A list of the device drivers using that port.  A "+"
-		will appear by the name of the device currently using
-		the port (it might not appear against any).  The
-		string "none" means that there are no device drivers
-		using that port.
-
-base-addr	Parallel port's base address, or addresses if the port
-		has more than one in which case they are separated
-		with tabs.  These values might not have any sensible
-		meaning for some ports.
-
-irq		Parallel port's IRQ, or -1 if none is being used.
-
-dma		Parallel port's DMA channel, or -1 if none is being
-		used.
-
-modes		Parallel port's hardware modes, comma-separated,
-		meaning:
-
-		PCSPP		PC-style SPP registers are available.
-		TRISTATE	Port is bidirectional.
-		COMPAT		Hardware acceleration for printers is
-				available and will be used.
-		EPP		Hardware acceleration for EPP protocol
-				is available and will be used.
-		ECP		Hardware acceleration for ECP protocol
-				is available and will be used.
-		DMA		DMA is available and will be used.
-
-		Note that the current implementation will only take
-		advantage of COMPAT and ECP modes if it has an IRQ
-		line to use.
-
-autoprobe	Any IEEE-1284 device ID information that has been
-		acquired from the (non-IEEE 1284.3) device.
-
-autoprobe[0-3]	IEEE 1284 device ID information retrieved from
-		daisy-chain devices that conform to IEEE 1284.3.
-
-spintime	The number of microseconds to busy-loop while waiting
-		for the peripheral to respond.  You might find that
-		adjusting this improves performance, depending on your
-		peripherals.  This is a port-wide setting, i.e. it
-		applies to all devices on a particular port.
-
-timeslice	The number of milliseconds that a device driver is
-		allowed to keep a port claimed for.  This is advisory,
-		and driver can ignore it if it must.
-
-default/*	The defaults for spintime and timeslice. When a new
-		port is	registered, it picks up the default spintime.
-		When a new device is registered, it picks up the
-		default timeslice.
-
-Device drivers
-==============
-
-Once the parport code is initialised, you can attach device drivers to
-specific ports.  Normally this happens automatically; if the lp driver
-is loaded it will create one lp device for each port found.  You can
-override this, though, by using parameters either when you load the lp
-driver:
-
-	# insmod lp parport=0,2
-
-or on the LILO command line:
-
-	lp=parport0 lp=parport2
-
-Both the above examples would inform lp that you want /dev/lp0 to be
-the first parallel port, and /dev/lp1 to be the _third_ parallel port,
-with no lp device associated with the second port (parport1).  Note
-that this is different to the way older kernels worked; there used to
-be a static association between the I/O port address and the device
-name, so /dev/lp0 was always the port at 0x3bc.  This is no longer the
-case - if you only have one port, it will default to being /dev/lp0,
-regardless of base address.
-
-Also:
-
- * If you selected the IEEE 1284 support at compile time, you can say
-   `lp=auto' on the kernel command line, and lp will create devices
-   only for those ports that seem to have printers attached.
-
- * If you give PLIP the `timid' parameter, either with `plip=timid' on
-   the command line, or with `insmod plip timid=1' when using modules,
-   it will avoid any ports that seem to be in use by other devices.
-
- * IRQ autoprobing works only for a few port types at the moment.
-
-Reporting printer problems with parport
-=======================================
-
-If you are having problems printing, please go through these steps to
-try to narrow down where the problem area is.
-
-When reporting problems with parport, really you need to give all of
-the messages that parport_pc spits out when it initialises.  There are
-several code paths:
-
-o polling
-o interrupt-driven, protocol in software
-o interrupt-driven, protocol in hardware using PIO
-o interrupt-driven, protocol in hardware using DMA
-
-The kernel messages that parport_pc logs give an indication of which
-code path is being used. (They could be a lot better actually..)
-
-For normal printer protocol, having IEEE 1284 modes enabled or not
-should not make a difference.
-
-To turn off the 'protocol in hardware' code paths, disable
-CONFIG_PARPORT_PC_FIFO.  Note that when they are enabled they are not
-necessarily _used_; it depends on whether the hardware is available,
-enabled by the BIOS, and detected by the driver.
-
-So, to start with, disable CONFIG_PARPORT_PC_FIFO, and load parport_pc
-with 'irq=none'. See if printing works then.  It really should,
-because this is the simplest code path.
-
-If that works fine, try with 'io=0x378 irq=7' (adjust for your
-hardware), to make it use interrupt-driven in-software protocol.
-
-If _that_ works fine, then one of the hardware modes isn't working
-right.  Enable CONFIG_PARPORT_PC_FIFO (no, it isn't a module option,
-and yes, it should be), set the port to ECP mode in the BIOS and note
-the DMA channel, and try with:
-
-    io=0x378 irq=7 dma=none (for PIO)
-    io=0x378 irq=7 dma=3 (for DMA)
---
-philb@gnu.org
-tim@cyberelk.net
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/power/00-INDEX linux-libre-4.10-rc8-gnu/Documentation/power/00-INDEX
--- linux-libre-4.9-gnu/Documentation/power/00-INDEX	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/power/00-INDEX	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@ basic-pm-debugging.txt
 	- Debugging suspend and resume
 charger-manager.txt
 	- Battery charger management.
-devices.txt
+admin-guide/devices.rst
 	- How drivers interact with system-wide power management
 drivers-testing.txt
 	- Testing suspend and resume support in device drivers
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/power/devices.txt linux-libre-4.10-rc8-gnu/Documentation/power/devices.txt
--- linux-libre-4.9-gnu/Documentation/power/devices.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/power/devices.txt	2017-02-12 16:03:20.000000000 -0500
@@ -607,7 +607,9 @@ individually.  Instead, a set of devices
 into a low-power state together at the same time by turning off the shared
 power resource.  Of course, they also need to be put into the full-power state
 together, by turning the shared power resource on.  A set of devices with this
-property is often referred to as a power domain.
+property is often referred to as a power domain. A power domain may also be
+nested inside another power domain. The nested domain is referred to as the
+sub-domain of the parent domain.
 
 Support for power domains is provided through the pm_domain field of struct
 device.  This field is a pointer to an object of type struct dev_pm_domain,
@@ -629,6 +631,16 @@ support for power domains into subsystem
 modifying the platform bus type.  Other platforms need not implement it or take
 it into account in any way.
 
+Devices may be defined as IRQ-safe which indicates to the PM core that their
+runtime PM callbacks may be invoked with disabled interrupts (see
+Documentation/power/runtime_pm.txt for more information).  If an IRQ-safe
+device belongs to a PM domain, the runtime PM of the domain will be
+disallowed, unless the domain itself is defined as IRQ-safe. However, it
+makes sense to define a PM domain as IRQ-safe only if all the devices in it
+are IRQ-safe. Moreover, if an IRQ-safe domain has a parent domain, the runtime
+PM of the parent is only allowed if the parent itself is IRQ-safe too with the
+additional restriction that all child domains of an IRQ-safe parent must also
+be IRQ-safe.
 
 Device Low Power (suspend) States
 ---------------------------------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/power/pci.txt linux-libre-4.10-rc8-gnu/Documentation/power/pci.txt
--- linux-libre-4.9-gnu/Documentation/power/pci.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/power/pci.txt	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@ management.  Based on previous work by P
 
 This document only covers the aspects of power management specific to PCI
 devices.  For general description of the kernel's interfaces related to device
-power management refer to Documentation/power/devices.txt and
+power management refer to Documentation/power/admin-guide/devices.rst and
 Documentation/power/runtime_pm.txt.
 
 ---------------------------------------------------------------------------
@@ -417,7 +417,7 @@ pm->runtime_idle() callback.
 2.4. System-Wide Power Transitions
 ----------------------------------
 There are a few different types of system-wide power transitions, described in
-Documentation/power/devices.txt.  Each of them requires devices to be handled
+Documentation/power/admin-guide/devices.rst.  Each of them requires devices to be handled
 in a specific way and the PM core executes subsystem-level power management
 callbacks for this purpose.  They are executed in phases such that each phase
 involves executing the same subsystem-level callback for every device belonging
@@ -623,7 +623,7 @@ System restore requires a hibernation im
 pre-hibernation memory contents to be restored before the pre-hibernation system
 activity can be resumed.
 
-As described in Documentation/power/devices.txt, the hibernation image is loaded
+As described in Documentation/power/admin-guide/devices.rst, the hibernation image is loaded
 into memory by a fresh instance of the kernel, called the boot kernel, which in
 turn is loaded and run by a boot loader in the usual way.  After the boot kernel
 has loaded the image, it needs to replace its own code and data with the code
@@ -677,7 +677,7 @@ controlling the runtime power management
 
 At the time of this writing there are two ways to define power management
 callbacks for a PCI device driver, the recommended one, based on using a
-dev_pm_ops structure described in Documentation/power/devices.txt, and the
+dev_pm_ops structure described in Documentation/power/admin-guide/devices.rst, and the
 "legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and
 .resume() callbacks from struct pci_driver are used.  The legacy approach,
 however, doesn't allow one to define runtime power management callbacks and is
@@ -1046,5 +1046,5 @@ PCI Local Bus Specification, Rev. 3.0
 PCI Bus Power Management Interface Specification, Rev. 1.2
 Advanced Configuration and Power Interface (ACPI) Specification, Rev. 3.0b
 PCI Express Base Specification, Rev. 2.0
-Documentation/power/devices.txt
+Documentation/power/admin-guide/devices.rst
 Documentation/power/runtime_pm.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/power/runtime_pm.txt linux-libre-4.10-rc8-gnu/Documentation/power/runtime_pm.txt
--- linux-libre-4.9-gnu/Documentation/power/runtime_pm.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/power/runtime_pm.txt	2017-02-12 16:03:20.000000000 -0500
@@ -674,7 +674,7 @@ left in runtime suspend.  If that happen
 system suspend and resume callbacks for all of those devices, except for the
 complete callback, which is then entirely responsible for handling the device
 as appropriate.  This only applies to system suspend transitions that are not
-related to hibernation (see Documentation/power/devices.txt for more
+related to hibernation (see Documentation/power/admin-guide/devices.rst for more
 information).
 
 The PM core does its best to reduce the probability of race conditions between
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/power/states.txt linux-libre-4.10-rc8-gnu/Documentation/power/states.txt
--- linux-libre-4.9-gnu/Documentation/power/states.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/power/states.txt	2017-02-12 16:03:20.000000000 -0500
@@ -8,25 +8,41 @@ for each state.
 
 The states are represented by strings that can be read or written to the
 /sys/power/state file.  Those strings may be "mem", "standby", "freeze" and
-"disk", where the last one always represents hibernation (Suspend-To-Disk) and
-the meaning of the remaining ones depends on the relative_sleep_states command
-line argument.
+"disk", where the last three always represent Power-On Suspend (if supported),
+Suspend-To-Idle and hibernation (Suspend-To-Disk), respectively.
 
-For relative_sleep_states=1, the strings "mem", "standby" and "freeze" label the
-available non-hibernation sleep states from the deepest to the shallowest,
-respectively.  In that case, "mem" is always present in /sys/power/state,
-because there is at least one non-hibernation sleep state in every system.  If
-the given system supports two non-hibernation sleep states, "standby" is present
-in /sys/power/state in addition to "mem".  If the system supports three
-non-hibernation sleep states, "freeze" will be present in /sys/power/state in
-addition to "mem" and "standby".
+The meaning of the "mem" string is controlled by the /sys/power/mem_sleep file.
+It contains strings representing the available modes of system suspend that may
+be triggered by writing "mem" to /sys/power/state.  These modes are "s2idle"
+(Suspend-To-Idle), "shallow" (Power-On Suspend) and "deep" (Suspend-To-RAM).
+The "s2idle" mode is always available, while the other ones are only available
+if supported by the platform (if not supported, the strings representing them
+are not present in /sys/power/mem_sleep).  The string representing the suspend
+mode to be used subsequently is enclosed in square brackets.  Writing one of
+the other strings present in /sys/power/mem_sleep to it causes the suspend mode
+to be used subsequently to change to the one represented by that string.
 
-For relative_sleep_states=0, which is the default, the following descriptions
-apply.
+Consequently, there are two ways to cause the system to go into the
+Suspend-To-Idle sleep state.  The first one is to write "freeze" directly to
+/sys/power/state.  The second one is to write "s2idle" to /sys/power/mem_sleep
+and then to wrtie "mem" to /sys/power/state.  Similarly, there are two ways
+to cause the system to go into the Power-On Suspend sleep state (the strings to
+write to the control files in that case are "standby" or "shallow" and "mem",
+respectively) if that state is supported by the platform.  In turn, there is
+only one way to cause the system to go into the Suspend-To-RAM state (write
+"deep" into /sys/power/mem_sleep and "mem" into /sys/power/state).
 
-state:		Suspend-To-Idle
+The default suspend mode (ie. the one to be used without writing anything into
+/sys/power/mem_sleep) is either "deep" (if Suspend-To-RAM is supported) or
+"s2idle", but it can be overridden by the value of the "mem_sleep_default"
+parameter in the kernel command line.
+
+The properties of all of the sleep states are described below.
+
+
+State:		Suspend-To-Idle
 ACPI state:	S0
-Label:		"freeze"
+Label:		"s2idle" ("freeze")
 
 This state is a generic, pure software, light-weight, system sleep state.
 It allows more energy to be saved relative to runtime idle by freezing user
@@ -35,13 +51,13 @@ lower-power than available at run time),
 spend more time in their idle states.
 
 This state can be used for platforms without Power-On Suspend/Suspend-to-RAM
-support, or it can be used in addition to Suspend-to-RAM (memory sleep)
-to provide reduced resume latency.  It is always supported.
+support, or it can be used in addition to Suspend-to-RAM to provide reduced
+resume latency.  It is always supported.
 
 
 State:		Standby / Power-On Suspend
 ACPI State:	S1
-Label:		"standby"
+Label:		"shallow" ("standby")
 
 This state, if supported, offers moderate, though real, power savings, while
 providing a relatively low-latency transition back to a working system.  No
@@ -58,7 +74,7 @@ state.
 
 State:		Suspend-to-RAM
 ACPI State:	S3
-Label:		"mem"
+Label:		"deep"
 
 This state, if supported, offers significant power savings as everything in the
 system is put into a low-power state, except for memory, which should be placed
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/power/swsusp-dmcrypt.txt linux-libre-4.10-rc8-gnu/Documentation/power/swsusp-dmcrypt.txt
--- linux-libre-4.9-gnu/Documentation/power/swsusp-dmcrypt.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/power/swsusp-dmcrypt.txt	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@ Some prerequisites:
 You know how dm-crypt works. If not, visit the following web page:
 http://www.saout.de/misc/dm-crypt/
 You have read Documentation/power/swsusp.txt and understand it.
-You did read Documentation/initrd.txt and know how an initrd works.
+You did read Documentation/admin-guide/initrd.rst and know how an initrd works.
 You know how to create or how to modify an initrd.
 
 Now your system is properly set up, your disk is encrypted except for
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/1.Intro.rst linux-libre-4.10-rc8-gnu/Documentation/process/1.Intro.rst
--- linux-libre-4.9-gnu/Documentation/process/1.Intro.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/1.Intro.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,266 @@
+Introduction
+============
+
+Executive summary
+-----------------
+
+The rest of this section covers the scope of the kernel development process
+and the kinds of frustrations that developers and their employers can
+encounter there.  There are a great many reasons why kernel code should be
+merged into the official ("mainline") kernel, including automatic
+availability to users, community support in many forms, and the ability to
+influence the direction of kernel development.  Code contributed to the
+Linux kernel must be made available under a GPL-compatible license.
+
+:ref:`development_process` introduces the development process, the kernel
+release cycle, and the mechanics of the merge window.  The various phases in
+the patch development, review, and merging cycle are covered.  There is some
+discussion of tools and mailing lists.  Developers wanting to get started
+with kernel development are encouraged to track down and fix bugs as an
+initial exercise.
+
+:ref:`development_early_stage` covers early-stage project planning, with an
+emphasis on involving the development community as soon as possible.
+
+:ref:`development_coding` is about the coding process; several pitfalls which
+have been encountered by other developers are discussed.  Some requirements for
+patches are covered, and there is an introduction to some of the tools
+which can help to ensure that kernel patches are correct.
+
+:ref:`development_posting` talks about the process of posting patches for
+review. To be taken seriously by the development community, patches must be
+properly formatted and described, and they must be sent to the right place.
+Following the advice in this section should help to ensure the best
+possible reception for your work.
+
+:ref:`development_followthrough` covers what happens after posting patches; the
+job is far from done at that point.  Working with reviewers is a crucial part
+of the development process; this section offers a number of tips on how to
+avoid problems at this important stage.  Developers are cautioned against
+assuming that the job is done when a patch is merged into the mainline.
+
+:ref:`development_advancedtopics` introduces a couple of "advanced" topics:
+managing patches with git and reviewing patches posted by others.
+
+:ref:`development_conclusion` concludes the document with pointers to sources
+for more information on kernel development.
+
+What this document is about
+---------------------------
+
+The Linux kernel, at over 8 million lines of code and well over 1000
+contributors to each release, is one of the largest and most active free
+software projects in existence.  Since its humble beginning in 1991, this
+kernel has evolved into a best-of-breed operating system component which
+runs on pocket-sized digital music players, desktop PCs, the largest
+supercomputers in existence, and all types of systems in between.  It is a
+robust, efficient, and scalable solution for almost any situation.
+
+With the growth of Linux has come an increase in the number of developers
+(and companies) wishing to participate in its development.  Hardware
+vendors want to ensure that Linux supports their products well, making
+those products attractive to Linux users.  Embedded systems vendors, who
+use Linux as a component in an integrated product, want Linux to be as
+capable and well-suited to the task at hand as possible.  Distributors and
+other software vendors who base their products on Linux have a clear
+interest in the capabilities, performance, and reliability of the Linux
+kernel.  And end users, too, will often wish to change Linux to make it
+better suit their needs.
+
+One of the most compelling features of Linux is that it is accessible to
+these developers; anybody with the requisite skills can improve Linux and
+influence the direction of its development.  Proprietary products cannot
+offer this kind of openness, which is a characteristic of the free software
+process.  But, if anything, the kernel is even more open than most other
+free software projects.  A typical three-month kernel development cycle can
+involve over 1000 developers working for more than 100 different companies
+(or for no company at all).
+
+Working with the kernel development community is not especially hard.  But,
+that notwithstanding, many potential contributors have experienced
+difficulties when trying to do kernel work.  The kernel community has
+evolved its own distinct ways of operating which allow it to function
+smoothly (and produce a high-quality product) in an environment where
+thousands of lines of code are being changed every day.  So it is not
+surprising that Linux kernel development process differs greatly from
+proprietary development methods.
+
+The kernel's development process may come across as strange and
+intimidating to new developers, but there are good reasons and solid
+experience behind it.  A developer who does not understand the kernel
+community's ways (or, worse, who tries to flout or circumvent them) will
+have a frustrating experience in store.  The development community, while
+being helpful to those who are trying to learn, has little time for those
+who will not listen or who do not care about the development process.
+
+It is hoped that those who read this document will be able to avoid that
+frustrating experience.  There is a lot of material here, but the effort
+involved in reading it will be repaid in short order.  The development
+community is always in need of developers who will help to make the kernel
+better; the following text should help you - or those who work for you -
+join our community.
+
+Credits
+-------
+
+This document was written by Jonathan Corbet, corbet@lwn.net.  It has been
+improved by comments from Johannes Berg, James Berry, Alex Chiang, Roland
+Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh,
+Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata, and
+Jochen Voß.
+
+This work was supported by the Linux Foundation; thanks especially to
+Amanda McPherson, who saw the value of this effort and made it all happen.
+
+The importance of getting code into the mainline
+------------------------------------------------
+
+Some companies and developers occasionally wonder why they should bother
+learning how to work with the kernel community and get their code into the
+mainline kernel (the "mainline" being the kernel maintained by Linus
+Torvalds and used as a base by Linux distributors).  In the short term,
+contributing code can look like an avoidable expense; it seems easier to
+just keep the code separate and support users directly.  The truth of the
+matter is that keeping code separate ("out of tree") is a false economy.
+
+As a way of illustrating the costs of out-of-tree code, here are a few
+relevant aspects of the kernel development process; most of these will be
+discussed in greater detail later in this document.  Consider:
+
+- Code which has been merged into the mainline kernel is available to all
+  Linux users.  It will automatically be present on all distributions which
+  enable it.  There is no need for driver disks, downloads, or the hassles
+  of supporting multiple versions of multiple distributions; it all just
+  works, for the developer and for the user.  Incorporation into the
+  mainline solves a large number of distribution and support problems.
+
+- While kernel developers strive to maintain a stable interface to user
+  space, the internal kernel API is in constant flux.  The lack of a stable
+  internal interface is a deliberate design decision; it allows fundamental
+  improvements to be made at any time and results in higher-quality code.
+  But one result of that policy is that any out-of-tree code requires
+  constant upkeep if it is to work with new kernels.  Maintaining
+  out-of-tree code requires significant amounts of work just to keep that
+  code working.
+
+  Code which is in the mainline, instead, does not require this work as the
+  result of a simple rule requiring any developer who makes an API change
+  to also fix any code that breaks as the result of that change.  So code
+  which has been merged into the mainline has significantly lower
+  maintenance costs.
+
+- Beyond that, code which is in the kernel will often be improved by other
+  developers.  Surprising results can come from empowering your user
+  community and customers to improve your product.
+
+- Kernel code is subjected to review, both before and after merging into
+  the mainline.  No matter how strong the original developer's skills are,
+  this review process invariably finds ways in which the code can be
+  improved.  Often review finds severe bugs and security problems.  This is
+  especially true for code which has been developed in a closed
+  environment; such code benefits strongly from review by outside
+  developers.  Out-of-tree code is lower-quality code.
+
+- Participation in the development process is your way to influence the
+  direction of kernel development.  Users who complain from the sidelines
+  are heard, but active developers have a stronger voice - and the ability
+  to implement changes which make the kernel work better for their needs.
+
+- When code is maintained separately, the possibility that a third party
+  will contribute a different implementation of a similar feature always
+  exists.  Should that happen, getting your code merged will become much
+  harder - to the point of impossibility.  Then you will be faced with the
+  unpleasant alternatives of either (1) maintaining a nonstandard feature
+  out of tree indefinitely, or (2) abandoning your code and migrating your
+  users over to the in-tree version.
+
+- Contribution of code is the fundamental action which makes the whole
+  process work.  By contributing your code you can add new functionality to
+  the kernel and provide capabilities and examples which are of use to
+  other kernel developers.  If you have developed code for Linux (or are
+  thinking about doing so), you clearly have an interest in the continued
+  success of this platform; contributing code is one of the best ways to
+  help ensure that success.
+
+All of the reasoning above applies to any out-of-tree kernel code,
+including code which is distributed in proprietary, binary-only form.
+There are, however, additional factors which should be taken into account
+before considering any sort of binary-only kernel code distribution.  These
+include:
+
+- The legal issues around the distribution of proprietary kernel modules
+  are cloudy at best; quite a few kernel copyright holders believe that
+  most binary-only modules are derived products of the kernel and that, as
+  a result, their distribution is a violation of the GNU General Public
+  license (about which more will be said below).  Your author is not a
+  lawyer, and nothing in this document can possibly be considered to be
+  legal advice.  The true legal status of closed-source modules can only be
+  determined by the courts.  But the uncertainty which haunts those modules
+  is there regardless.
+
+- Binary modules greatly increase the difficulty of debugging kernel
+  problems, to the point that most kernel developers will not even try.  So
+  the distribution of binary-only modules will make it harder for your
+  users to get support from the community.
+
+- Support is also harder for distributors of binary-only modules, who must
+  provide a version of the module for every distribution and every kernel
+  version they wish to support.  Dozens of builds of a single module can
+  be required to provide reasonably comprehensive coverage, and your users
+  will have to upgrade your module separately every time they upgrade their
+  kernel.
+
+- Everything that was said above about code review applies doubly to
+  closed-source code.  Since this code is not available at all, it cannot
+  have been reviewed by the community and will, beyond doubt, have serious
+  problems.
+
+Makers of embedded systems, in particular, may be tempted to disregard much
+of what has been said in this section in the belief that they are shipping
+a self-contained product which uses a frozen kernel version and requires no
+more development after its release.  This argument misses the value of
+widespread code review and the value of allowing your users to add
+capabilities to your product.  But these products, too, have a limited
+commercial life, after which a new version must be released.  At that
+point, vendors whose code is in the mainline and well maintained will be
+much better positioned to get the new product ready for market quickly.
+
+Licensing
+---------
+
+Code is contributed to the Linux kernel under a number of licenses, but all
+code must be compatible with version 2 of the GNU General Public License
+(GPLv2), which is the license covering the kernel distribution as a whole.
+In practice, that means that all code contributions are covered either by
+GPLv2 (with, optionally, language allowing distribution under later
+versions of the GPL) or the three-clause BSD license.  Any contributions
+which are not covered by a compatible license will not be accepted into the
+kernel.
+
+Copyright assignments are not required (or requested) for code contributed
+to the kernel.  All code merged into the mainline kernel retains its
+original ownership; as a result, the kernel now has thousands of owners.
+
+One implication of this ownership structure is that any attempt to change
+the licensing of the kernel is doomed to almost certain failure.  There are
+few practical scenarios where the agreement of all copyright holders could
+be obtained (or their code removed from the kernel).  So, in particular,
+there is no prospect of a migration to version 3 of the GPL in the
+foreseeable future.
+
+It is imperative that all code contributed to the kernel be legitimately
+free software.  For that reason, code from anonymous (or pseudonymous)
+contributors will not be accepted.  All contributors are required to "sign
+off" on their code, stating that the code can be distributed with the
+kernel under the GPL.  Code which has not been licensed as free software by
+its owner, or which risks creating copyright-related problems for the
+kernel (such as code which derives from reverse-engineering efforts lacking
+proper safeguards) cannot be contributed.
+
+Questions about copyright-related issues are common on Linux development
+mailing lists.  Such questions will normally receive no shortage of
+answers, but one should bear in mind that the people answering those
+questions are not lawyers and cannot provide legal advice.  If you have
+legal questions relating to Linux source code, there is no substitute for
+talking with a lawyer who understands this field.  Relying on answers
+obtained on technical mailing lists is a risky affair.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/2.Process.rst linux-libre-4.10-rc8-gnu/Documentation/process/2.Process.rst
--- linux-libre-4.9-gnu/Documentation/process/2.Process.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/2.Process.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,497 @@
+.. _development_process:
+
+How the development process works
+=================================
+
+Linux kernel development in the early 1990's was a pretty loose affair,
+with relatively small numbers of users and developers involved.  With a
+user base in the millions and with some 2,000 developers involved over the
+course of one year, the kernel has since had to evolve a number of
+processes to keep development happening smoothly.  A solid understanding of
+how the process works is required in order to be an effective part of it.
+
+The big picture
+---------------
+
+The kernel developers use a loosely time-based release process, with a new
+major kernel release happening every two or three months.  The recent
+release history looks like this:
+
+	======  =================
+	2.6.38	March 14, 2011
+	2.6.37	January 4, 2011
+	2.6.36	October 20, 2010
+	2.6.35	August 1, 2010
+	2.6.34	May 15, 2010
+	2.6.33	February 24, 2010
+	======  =================
+
+Every 2.6.x release is a major kernel release with new features, internal
+API changes, and more.  A typical 2.6 release can contain nearly 10,000
+changesets with changes to several hundred thousand lines of code.  2.6 is
+thus the leading edge of Linux kernel development; the kernel uses a
+rolling development model which is continually integrating major changes.
+
+A relatively straightforward discipline is followed with regard to the
+merging of patches for each release.  At the beginning of each development
+cycle, the "merge window" is said to be open.  At that time, code which is
+deemed to be sufficiently stable (and which is accepted by the development
+community) is merged into the mainline kernel.  The bulk of changes for a
+new development cycle (and all of the major changes) will be merged during
+this time, at a rate approaching 1,000 changes ("patches," or "changesets")
+per day.
+
+(As an aside, it is worth noting that the changes integrated during the
+merge window do not come out of thin air; they have been collected, tested,
+and staged ahead of time.  How that process works will be described in
+detail later on).
+
+The merge window lasts for approximately two weeks.  At the end of this
+time, Linus Torvalds will declare that the window is closed and release the
+first of the "rc" kernels.  For the kernel which is destined to be 2.6.40,
+for example, the release which happens at the end of the merge window will
+be called 2.6.40-rc1.  The -rc1 release is the signal that the time to
+merge new features has passed, and that the time to stabilize the next
+kernel has begun.
+
+Over the next six to ten weeks, only patches which fix problems should be
+submitted to the mainline.  On occasion a more significant change will be
+allowed, but such occasions are rare; developers who try to merge new
+features outside of the merge window tend to get an unfriendly reception.
+As a general rule, if you miss the merge window for a given feature, the
+best thing to do is to wait for the next development cycle.  (An occasional
+exception is made for drivers for previously-unsupported hardware; if they
+touch no in-tree code, they cannot cause regressions and should be safe to
+add at any time).
+
+As fixes make their way into the mainline, the patch rate will slow over
+time.  Linus releases new -rc kernels about once a week; a normal series
+will get up to somewhere between -rc6 and -rc9 before the kernel is
+considered to be sufficiently stable and the final 2.6.x release is made.
+At that point the whole process starts over again.
+
+As an example, here is how the 2.6.38 development cycle went (all dates in
+2011):
+
+	==============  ===============================
+	January 4	2.6.37 stable release
+	January 18	2.6.38-rc1, merge window closes
+	January 21	2.6.38-rc2
+	February 1	2.6.38-rc3
+	February 7	2.6.38-rc4
+	February 15	2.6.38-rc5
+	February 21	2.6.38-rc6
+	March 1		2.6.38-rc7
+	March 7		2.6.38-rc8
+	March 14	2.6.38 stable release
+	==============  ===============================
+
+How do the developers decide when to close the development cycle and create
+the stable release?  The most significant metric used is the list of
+regressions from previous releases.  No bugs are welcome, but those which
+break systems which worked in the past are considered to be especially
+serious.  For this reason, patches which cause regressions are looked upon
+unfavorably and are quite likely to be reverted during the stabilization
+period.
+
+The developers' goal is to fix all known regressions before the stable
+release is made.  In the real world, this kind of perfection is hard to
+achieve; there are just too many variables in a project of this size.
+There comes a point where delaying the final release just makes the problem
+worse; the pile of changes waiting for the next merge window will grow
+larger, creating even more regressions the next time around.  So most 2.6.x
+kernels go out with a handful of known regressions though, hopefully, none
+of them are serious.
+
+Once a stable release is made, its ongoing maintenance is passed off to the
+"stable team," currently consisting of Greg Kroah-Hartman.  The stable team
+will release occasional updates to the stable release using the 2.6.x.y
+numbering scheme.  To be considered for an update release, a patch must (1)
+fix a significant bug, and (2) already be merged into the mainline for the
+next development kernel.  Kernels will typically receive stable updates for
+a little more than one development cycle past their initial release.  So,
+for example, the 2.6.36 kernel's history looked like:
+
+	==============  ===============================
+	October 10	2.6.36 stable release
+	November 22	2.6.36.1
+	December 9	2.6.36.2
+	January 7	2.6.36.3
+	February 17	2.6.36.4
+	==============  ===============================
+
+2.6.36.4 was the final stable update for the 2.6.36 release.
+
+Some kernels are designated "long term" kernels; they will receive support
+for a longer period.  As of this writing, the current long term kernels
+and their maintainers are:
+
+	======  ======================  ===========================
+	2.6.27	Willy Tarreau		(Deep-frozen stable kernel)
+	2.6.32	Greg Kroah-Hartman
+	2.6.35	Andi Kleen		(Embedded flag kernel)
+	======  ======================  ===========================
+
+The selection of a kernel for long-term support is purely a matter of a
+maintainer having the need and the time to maintain that release.  There
+are no known plans for long-term support for any specific upcoming
+release.
+
+
+The lifecycle of a patch
+------------------------
+
+Patches do not go directly from the developer's keyboard into the mainline
+kernel.  There is, instead, a somewhat involved (if somewhat informal)
+process designed to ensure that each patch is reviewed for quality and that
+each patch implements a change which is desirable to have in the mainline.
+This process can happen quickly for minor fixes, or, in the case of large
+and controversial changes, go on for years.  Much developer frustration
+comes from a lack of understanding of this process or from attempts to
+circumvent it.
+
+In the hopes of reducing that frustration, this document will describe how
+a patch gets into the kernel.  What follows below is an introduction which
+describes the process in a somewhat idealized way.  A much more detailed
+treatment will come in later sections.
+
+The stages that a patch goes through are, generally:
+
+ - Design.  This is where the real requirements for the patch - and the way
+   those requirements will be met - are laid out.  Design work is often
+   done without involving the community, but it is better to do this work
+   in the open if at all possible; it can save a lot of time redesigning
+   things later.
+
+ - Early review.  Patches are posted to the relevant mailing list, and
+   developers on that list reply with any comments they may have.  This
+   process should turn up any major problems with a patch if all goes
+   well.
+
+ - Wider review.  When the patch is getting close to ready for mainline
+   inclusion, it should be accepted by a relevant subsystem maintainer -
+   though this acceptance is not a guarantee that the patch will make it
+   all the way to the mainline.  The patch will show up in the maintainer's
+   subsystem tree and into the -next trees (described below).  When the
+   process works, this step leads to more extensive review of the patch and
+   the discovery of any problems resulting from the integration of this
+   patch with work being done by others.
+
+-  Please note that most maintainers also have day jobs, so merging
+   your patch may not be their highest priority.  If your patch is
+   getting feedback about changes that are needed, you should either
+   make those changes or justify why they should not be made.  If your
+   patch has no review complaints but is not being merged by its
+   appropriate subsystem or driver maintainer, you should be persistent
+   in updating the patch to the current kernel so that it applies cleanly
+   and keep sending it for review and merging.
+
+ - Merging into the mainline.  Eventually, a successful patch will be
+   merged into the mainline repository managed by Linus Torvalds.  More
+   comments and/or problems may surface at this time; it is important that
+   the developer be responsive to these and fix any issues which arise.
+
+ - Stable release.  The number of users potentially affected by the patch
+   is now large, so, once again, new problems may arise.
+
+ - Long-term maintenance.  While it is certainly possible for a developer
+   to forget about code after merging it, that sort of behavior tends to
+   leave a poor impression in the development community.  Merging code
+   eliminates some of the maintenance burden, in that others will fix
+   problems caused by API changes.  But the original developer should
+   continue to take responsibility for the code if it is to remain useful
+   in the longer term.
+
+One of the largest mistakes made by kernel developers (or their employers)
+is to try to cut the process down to a single "merging into the mainline"
+step.  This approach invariably leads to frustration for everybody
+involved.
+
+How patches get into the Kernel
+-------------------------------
+
+There is exactly one person who can merge patches into the mainline kernel
+repository: Linus Torvalds.  But, of the over 9,500 patches which went
+into the 2.6.38 kernel, only 112 (around 1.3%) were directly chosen by Linus
+himself.  The kernel project has long since grown to a size where no single
+developer could possibly inspect and select every patch unassisted.  The
+way the kernel developers have addressed this growth is through the use of
+a lieutenant system built around a chain of trust.
+
+The kernel code base is logically broken down into a set of subsystems:
+networking, specific architecture support, memory management, video
+devices, etc.  Most subsystems have a designated maintainer, a developer
+who has overall responsibility for the code within that subsystem.  These
+subsystem maintainers are the gatekeepers (in a loose way) for the portion
+of the kernel they manage; they are the ones who will (usually) accept a
+patch for inclusion into the mainline kernel.
+
+Subsystem maintainers each manage their own version of the kernel source
+tree, usually (but certainly not always) using the git source management
+tool.  Tools like git (and related tools like quilt or mercurial) allow
+maintainers to track a list of patches, including authorship information
+and other metadata.  At any given time, the maintainer can identify which
+patches in his or her repository are not found in the mainline.
+
+When the merge window opens, top-level maintainers will ask Linus to "pull"
+the patches they have selected for merging from their repositories.  If
+Linus agrees, the stream of patches will flow up into his repository,
+becoming part of the mainline kernel.  The amount of attention that Linus
+pays to specific patches received in a pull operation varies.  It is clear
+that, sometimes, he looks quite closely.  But, as a general rule, Linus
+trusts the subsystem maintainers to not send bad patches upstream.
+
+Subsystem maintainers, in turn, can pull patches from other maintainers.
+For example, the networking tree is built from patches which accumulated
+first in trees dedicated to network device drivers, wireless networking,
+etc.  This chain of repositories can be arbitrarily long, though it rarely
+exceeds two or three links.  Since each maintainer in the chain trusts
+those managing lower-level trees, this process is known as the "chain of
+trust."
+
+Clearly, in a system like this, getting patches into the kernel depends on
+finding the right maintainer.  Sending patches directly to Linus is not
+normally the right way to go.
+
+
+Next trees
+----------
+
+The chain of subsystem trees guides the flow of patches into the kernel,
+but it also raises an interesting question: what if somebody wants to look
+at all of the patches which are being prepared for the next merge window?
+Developers will be interested in what other changes are pending to see
+whether there are any conflicts to worry about; a patch which changes a
+core kernel function prototype, for example, will conflict with any other
+patches which use the older form of that function.  Reviewers and testers
+want access to the changes in their integrated form before all of those
+changes land in the mainline kernel.  One could pull changes from all of
+the interesting subsystem trees, but that would be a big and error-prone
+job.
+
+The answer comes in the form of -next trees, where subsystem trees are
+collected for testing and review.  The older of these trees, maintained by
+Andrew Morton, is called "-mm" (for memory management, which is how it got
+started).  The -mm tree integrates patches from a long list of subsystem
+trees; it also has some patches aimed at helping with debugging.
+
+Beyond that, -mm contains a significant collection of patches which have
+been selected by Andrew directly.  These patches may have been posted on a
+mailing list, or they may apply to a part of the kernel for which there is
+no designated subsystem tree.  As a result, -mm operates as a sort of
+subsystem tree of last resort; if there is no other obvious path for a
+patch into the mainline, it is likely to end up in -mm.  Miscellaneous
+patches which accumulate in -mm will eventually either be forwarded on to
+an appropriate subsystem tree or be sent directly to Linus.  In a typical
+development cycle, approximately 5-10% of the patches going into the
+mainline get there via -mm.
+
+The current -mm patch is available in the "mmotm" (-mm of the moment)
+directory at:
+
+	http://www.ozlabs.org/~akpm/mmotm/
+
+Use of the MMOTM tree is likely to be a frustrating experience, though;
+there is a definite chance that it will not even compile.
+
+The primary tree for next-cycle patch merging is linux-next, maintained by
+Stephen Rothwell.  The linux-next tree is, by design, a snapshot of what
+the mainline is expected to look like after the next merge window closes.
+Linux-next trees are announced on the linux-kernel and linux-next mailing
+lists when they are assembled; they can be downloaded from:
+
+	http://www.kernel.org/pub/linux/kernel/next/
+
+Linux-next has become an integral part of the kernel development process;
+all patches merged during a given merge window should really have found
+their way into linux-next some time before the merge window opens.
+
+
+Staging trees
+-------------
+
+The kernel source tree contains the drivers/staging/ directory, where
+many sub-directories for drivers or filesystems that are on their way to
+being added to the kernel tree live.  They remain in drivers/staging while
+they still need more work; once complete, they can be moved into the
+kernel proper.  This is a way to keep track of drivers that aren't
+up to Linux kernel coding or quality standards, but people may want to use
+them and track development.
+
+Greg Kroah-Hartman currently maintains the staging tree.  Drivers that
+still need work are sent to him, with each driver having its own
+subdirectory in drivers/staging/.  Along with the driver source files, a
+TODO file should be present in the directory as well.  The TODO file lists
+the pending work that the driver needs for acceptance into the kernel
+proper, as well as a list of people that should be Cc'd for any patches to
+the driver.  Current rules require that drivers contributed to staging
+must, at a minimum, compile properly.
+
+Staging can be a relatively easy way to get new drivers into the mainline
+where, with luck, they will come to the attention of other developers and
+improve quickly.  Entry into staging is not the end of the story, though;
+code in staging which is not seeing regular progress will eventually be
+removed.  Distributors also tend to be relatively reluctant to enable
+staging drivers.  So staging is, at best, a stop on the way toward becoming
+a proper mainline driver.
+
+
+Tools
+-----
+
+As can be seen from the above text, the kernel development process depends
+heavily on the ability to herd collections of patches in various
+directions.  The whole thing would not work anywhere near as well as it
+does without suitably powerful tools.  Tutorials on how to use these tools
+are well beyond the scope of this document, but there is space for a few
+pointers.
+
+By far the dominant source code management system used by the kernel
+community is git.  Git is one of a number of distributed version control
+systems being developed in the free software community.  It is well tuned
+for kernel development, in that it performs quite well when dealing with
+large repositories and large numbers of patches.  It also has a reputation
+for being difficult to learn and use, though it has gotten better over
+time.  Some sort of familiarity with git is almost a requirement for kernel
+developers; even if they do not use it for their own work, they'll need git
+to keep up with what other developers (and the mainline) are doing.
+
+Git is now packaged by almost all Linux distributions.  There is a home
+page at:
+
+	http://git-scm.com/
+
+That page has pointers to documentation and tutorials.
+
+Among the kernel developers who do not use git, the most popular choice is
+almost certainly Mercurial:
+
+	http://www.selenic.com/mercurial/
+
+Mercurial shares many features with git, but it provides an interface which
+many find easier to use.
+
+The other tool worth knowing about is Quilt:
+
+	http://savannah.nongnu.org/projects/quilt/
+
+Quilt is a patch management system, rather than a source code management
+system.  It does not track history over time; it is, instead, oriented
+toward tracking a specific set of changes against an evolving code base.
+Some major subsystem maintainers use quilt to manage patches intended to go
+upstream.  For the management of certain kinds of trees (-mm, for example),
+quilt is the best tool for the job.
+
+
+Mailing lists
+-------------
+
+A great deal of Linux kernel development work is done by way of mailing
+lists.  It is hard to be a fully-functioning member of the community
+without joining at least one list somewhere.  But Linux mailing lists also
+represent a potential hazard to developers, who risk getting buried under a
+load of electronic mail, running afoul of the conventions used on the Linux
+lists, or both.
+
+Most kernel mailing lists are run on vger.kernel.org; the master list can
+be found at:
+
+	http://vger.kernel.org/vger-lists.html
+
+There are lists hosted elsewhere, though; a number of them are at
+lists.redhat.com.
+
+The core mailing list for kernel development is, of course, linux-kernel.
+This list is an intimidating place to be; volume can reach 500 messages per
+day, the amount of noise is high, the conversation can be severely
+technical, and participants are not always concerned with showing a high
+degree of politeness.  But there is no other place where the kernel
+development community comes together as a whole; developers who avoid this
+list will miss important information.
+
+There are a few hints which can help with linux-kernel survival:
+
+- Have the list delivered to a separate folder, rather than your main
+  mailbox.  One must be able to ignore the stream for sustained periods of
+  time.
+
+- Do not try to follow every conversation - nobody else does.  It is
+  important to filter on both the topic of interest (though note that
+  long-running conversations can drift away from the original subject
+  without changing the email subject line) and the people who are
+  participating.
+
+- Do not feed the trolls.  If somebody is trying to stir up an angry
+  response, ignore them.
+
+- When responding to linux-kernel email (or that on other lists) preserve
+  the Cc: header for all involved.  In the absence of a strong reason (such
+  as an explicit request), you should never remove recipients.  Always make
+  sure that the person you are responding to is in the Cc: list.  This
+  convention also makes it unnecessary to explicitly ask to be copied on
+  replies to your postings.
+
+- Search the list archives (and the net as a whole) before asking
+  questions.  Some developers can get impatient with people who clearly
+  have not done their homework.
+
+- Avoid top-posting (the practice of putting your answer above the quoted
+  text you are responding to).  It makes your response harder to read and
+  makes a poor impression.
+
+- Ask on the correct mailing list.  Linux-kernel may be the general meeting
+  point, but it is not the best place to find developers from all
+  subsystems.
+
+The last point - finding the correct mailing list - is a common place for
+beginning developers to go wrong.  Somebody who asks a networking-related
+question on linux-kernel will almost certainly receive a polite suggestion
+to ask on the netdev list instead, as that is the list frequented by most
+networking developers.  Other lists exist for the SCSI, video4linux, IDE,
+filesystem, etc. subsystems.  The best place to look for mailing lists is
+in the MAINTAINERS file packaged with the kernel source.
+
+
+Getting started with Kernel development
+---------------------------------------
+
+Questions about how to get started with the kernel development process are
+common - from both individuals and companies.  Equally common are missteps
+which make the beginning of the relationship harder than it has to be.
+
+Companies often look to hire well-known developers to get a development
+group started.  This can, in fact, be an effective technique.  But it also
+tends to be expensive and does not do much to grow the pool of experienced
+kernel developers.  It is possible to bring in-house developers up to speed
+on Linux kernel development, given the investment of a bit of time.  Taking
+this time can endow an employer with a group of developers who understand
+the kernel and the company both, and who can help to train others as well.
+Over the medium term, this is often the more profitable approach.
+
+Individual developers are often, understandably, at a loss for a place to
+start.  Beginning with a large project can be intimidating; one often wants
+to test the waters with something smaller first.  This is the point where
+some developers jump into the creation of patches fixing spelling errors or
+minor coding style issues.  Unfortunately, such patches create a level of
+noise which is distracting for the development community as a whole, so,
+increasingly, they are looked down upon.  New developers wishing to
+introduce themselves to the community will not get the sort of reception
+they wish for by these means.
+
+Andrew Morton gives this advice for aspiring kernel developers
+
+::
+
+	The #1 project for all kernel beginners should surely be "make sure
+	that the kernel runs perfectly at all times on all machines which
+	you can lay your hands on".  Usually the way to do this is to work
+	with others on getting things fixed up (this can require
+	persistence!) but that's fine - it's a part of kernel development.
+
+(http://lwn.net/Articles/283982/).
+
+In the absence of obvious problems to fix, developers are advised to look
+at the current lists of regressions and open bugs in general.  There is
+never any shortage of issues in need of fixing; by addressing these issues,
+developers will gain experience with the process while, at the same time,
+building respect with the rest of the development community.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/3.Early-stage.rst linux-libre-4.10-rc8-gnu/Documentation/process/3.Early-stage.rst
--- linux-libre-4.9-gnu/Documentation/process/3.Early-stage.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/3.Early-stage.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,222 @@
+.. _development_early_stage:
+
+Early-stage planning
+====================
+
+When contemplating a Linux kernel development project, it can be tempting
+to jump right in and start coding.  As with any significant project,
+though, much of the groundwork for success is best laid before the first
+line of code is written.  Some time spent in early planning and
+communication can save far more time later on.
+
+
+Specifying the problem
+----------------------
+
+Like any engineering project, a successful kernel enhancement starts with a
+clear description of the problem to be solved.  In some cases, this step is
+easy: when a driver is needed for a specific piece of hardware, for
+example.  In others, though, it is tempting to confuse the real problem
+with the proposed solution, and that can lead to difficulties.
+
+Consider an example: some years ago, developers working with Linux audio
+sought a way to run applications without dropouts or other artifacts caused
+by excessive latency in the system.  The solution they arrived at was a
+kernel module intended to hook into the Linux Security Module (LSM)
+framework; this module could be configured to give specific applications
+access to the realtime scheduler.  This module was implemented and sent to
+the linux-kernel mailing list, where it immediately ran into problems.
+
+To the audio developers, this security module was sufficient to solve their
+immediate problem.  To the wider kernel community, though, it was seen as a
+misuse of the LSM framework (which is not intended to confer privileges
+onto processes which they would not otherwise have) and a risk to system
+stability.  Their preferred solutions involved realtime scheduling access
+via the rlimit mechanism for the short term, and ongoing latency reduction
+work in the long term.
+
+The audio community, however, could not see past the particular solution
+they had implemented; they were unwilling to accept alternatives.  The
+resulting disagreement left those developers feeling disillusioned with the
+entire kernel development process; one of them went back to an audio list
+and posted this:
+
+	There are a number of very good Linux kernel developers, but they
+	tend to get outshouted by a large crowd of arrogant fools. Trying
+	to communicate user requirements to these people is a waste of
+	time. They are much too "intelligent" to listen to lesser mortals.
+
+(http://lwn.net/Articles/131776/).
+
+The reality of the situation was different; the kernel developers were far
+more concerned about system stability, long-term maintenance, and finding
+the right solution to the problem than they were with a specific module.
+The moral of the story is to focus on the problem - not a specific solution
+- and to discuss it with the development community before investing in the
+creation of a body of code.
+
+So, when contemplating a kernel development project, one should obtain
+answers to a short set of questions:
+
+ - What, exactly, is the problem which needs to be solved?
+
+ - Who are the users affected by this problem?  Which use cases should the
+   solution address?
+
+ - How does the kernel fall short in addressing that problem now?
+
+Only then does it make sense to start considering possible solutions.
+
+
+Early discussion
+----------------
+
+When planning a kernel development project, it makes great sense to hold
+discussions with the community before launching into implementation.  Early
+communication can save time and trouble in a number of ways:
+
+ - It may well be that the problem is addressed by the kernel in ways which
+   you have not understood.  The Linux kernel is large and has a number of
+   features and capabilities which are not immediately obvious.  Not all
+   kernel capabilities are documented as well as one might like, and it is
+   easy to miss things.  Your author has seen the posting of a complete
+   driver which duplicated an existing driver that the new author had been
+   unaware of.  Code which reinvents existing wheels is not only wasteful;
+   it will also not be accepted into the mainline kernel.
+
+ - There may be elements of the proposed solution which will not be
+   acceptable for mainline merging.  It is better to find out about
+   problems like this before writing the code.
+
+ - It's entirely possible that other developers have thought about the
+   problem; they may have ideas for a better solution, and may be willing
+   to help in the creation of that solution.
+
+Years of experience with the kernel development community have taught a
+clear lesson: kernel code which is designed and developed behind closed
+doors invariably has problems which are only revealed when the code is
+released into the community.  Sometimes these problems are severe,
+requiring months or years of effort before the code can be brought up to
+the kernel community's standards.  Some examples include:
+
+ - The Devicescape network stack was designed and implemented for
+   single-processor systems.  It could not be merged into the mainline
+   until it was made suitable for multiprocessor systems.  Retrofitting
+   locking and such into code is a difficult task; as a result, the merging
+   of this code (now called mac80211) was delayed for over a year.
+
+ - The Reiser4 filesystem included a number of capabilities which, in the
+   core kernel developers' opinion, should have been implemented in the
+   virtual filesystem layer instead.  It also included features which could
+   not easily be implemented without exposing the system to user-caused
+   deadlocks.  The late revelation of these problems - and refusal to
+   address some of them - has caused Reiser4 to stay out of the mainline
+   kernel.
+
+ - The AppArmor security module made use of internal virtual filesystem
+   data structures in ways which were considered to be unsafe and
+   unreliable.  This concern (among others) kept AppArmor out of the
+   mainline for years.
+
+In each of these cases, a great deal of pain and extra work could have been
+avoided with some early discussion with the kernel developers.
+
+
+Who do you talk to?
+-------------------
+
+When developers decide to take their plans public, the next question will
+be: where do we start?  The answer is to find the right mailing list(s) and
+the right maintainer.  For mailing lists, the best approach is to look in
+the MAINTAINERS file for a relevant place to post.  If there is a suitable
+subsystem list, posting there is often preferable to posting on
+linux-kernel; you are more likely to reach developers with expertise in the
+relevant subsystem and the environment may be more supportive.
+
+Finding maintainers can be a bit harder.  Again, the MAINTAINERS file is
+the place to start.  That file tends to not always be up to date, though,
+and not all subsystems are represented there.  The person listed in the
+MAINTAINERS file may, in fact, not be the person who is actually acting in
+that role currently.  So, when there is doubt about who to contact, a
+useful trick is to use git (and "git log" in particular) to see who is
+currently active within the subsystem of interest.  Look at who is writing
+patches, and who, if anybody, is attaching Signed-off-by lines to those
+patches.  Those are the people who will be best placed to help with a new
+development project.
+
+The task of finding the right maintainer is sometimes challenging enough
+that the kernel developers have added a script to ease the process:
+
+::
+
+	.../scripts/get_maintainer.pl
+
+This script will return the current maintainer(s) for a given file or
+directory when given the "-f" option.  If passed a patch on the
+command line, it will list the maintainers who should probably receive
+copies of the patch.  There are a number of options regulating how hard
+get_maintainer.pl will search for maintainers; please be careful about
+using the more aggressive options as you may end up including developers
+who have no real interest in the code you are modifying.
+
+If all else fails, talking to Andrew Morton can be an effective way to
+track down a maintainer for a specific piece of code.
+
+
+When to post?
+-------------
+
+If possible, posting your plans during the early stages can only be
+helpful.  Describe the problem being solved and any plans that have been
+made on how the implementation will be done.  Any information you can
+provide can help the development community provide useful input on the
+project.
+
+One discouraging thing which can happen at this stage is not a hostile
+reaction, but, instead, little or no reaction at all.  The sad truth of the
+matter is (1) kernel developers tend to be busy, (2) there is no shortage
+of people with grand plans and little code (or even prospect of code) to
+back them up, and (3) nobody is obligated to review or comment on ideas
+posted by others.  Beyond that, high-level designs often hide problems
+which are only reviewed when somebody actually tries to implement those
+designs; for that reason, kernel developers would rather see the code.
+
+If a request-for-comments posting yields little in the way of comments, do
+not assume that it means there is no interest in the project.
+Unfortunately, you also cannot assume that there are no problems with your
+idea.  The best thing to do in this situation is to proceed, keeping the
+community informed as you go.
+
+
+Getting official buy-in
+-----------------------
+
+If your work is being done in a corporate environment - as most Linux
+kernel work is - you must, obviously, have permission from suitably
+empowered managers before you can post your company's plans or code to a
+public mailing list.  The posting of code which has not been cleared for
+release under a GPL-compatible license can be especially problematic; the
+sooner that a company's management and legal staff can agree on the posting
+of a kernel development project, the better off everybody involved will be.
+
+Some readers may be thinking at this point that their kernel work is
+intended to support a product which does not yet have an officially
+acknowledged existence.  Revealing their employer's plans on a public
+mailing list may not be a viable option.  In cases like this, it is worth
+considering whether the secrecy is really necessary; there is often no real
+need to keep development plans behind closed doors.
+
+That said, there are also cases where a company legitimately cannot
+disclose its plans early in the development process.  Companies with
+experienced kernel developers may choose to proceed in an open-loop manner
+on the assumption that they will be able to avoid serious integration
+problems later.  For companies without that sort of in-house expertise, the
+best option is often to hire an outside developer to review the plans under
+a non-disclosure agreement.  The Linux Foundation operates an NDA program
+designed to help with this sort of situation; more information can be found
+at:
+
+    http://www.linuxfoundation.org/en/NDA_program
+
+This kind of review is often enough to avoid serious problems later on
+without requiring public disclosure of the project.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/4.Coding.rst linux-libre-4.10-rc8-gnu/Documentation/process/4.Coding.rst
--- linux-libre-4.9-gnu/Documentation/process/4.Coding.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/4.Coding.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,413 @@
+.. _development_coding:
+
+Getting the code right
+======================
+
+While there is much to be said for a solid and community-oriented design
+process, the proof of any kernel development project is in the resulting
+code.  It is the code which will be examined by other developers and merged
+(or not) into the mainline tree.  So it is the quality of this code which
+will determine the ultimate success of the project.
+
+This section will examine the coding process.  We'll start with a look at a
+number of ways in which kernel developers can go wrong.  Then the focus
+will shift toward doing things right and the tools which can help in that
+quest.
+
+
+Pitfalls
+---------
+
+Coding style
+************
+
+The kernel has long had a standard coding style, described in
+Documentation/process/coding-style.rst.  For much of that time, the policies described
+in that file were taken as being, at most, advisory.  As a result, there is
+a substantial amount of code in the kernel which does not meet the coding
+style guidelines.  The presence of that code leads to two independent
+hazards for kernel developers.
+
+The first of these is to believe that the kernel coding standards do not
+matter and are not enforced.  The truth of the matter is that adding new
+code to the kernel is very difficult if that code is not coded according to
+the standard; many developers will request that the code be reformatted
+before they will even review it.  A code base as large as the kernel
+requires some uniformity of code to make it possible for developers to
+quickly understand any part of it.  So there is no longer room for
+strangely-formatted code.
+
+Occasionally, the kernel's coding style will run into conflict with an
+employer's mandated style.  In such cases, the kernel's style will have to
+win before the code can be merged.  Putting code into the kernel means
+giving up a degree of control in a number of ways - including control over
+how the code is formatted.
+
+The other trap is to assume that code which is already in the kernel is
+urgently in need of coding style fixes.  Developers may start to generate
+reformatting patches as a way of gaining familiarity with the process, or
+as a way of getting their name into the kernel changelogs - or both.  But
+pure coding style fixes are seen as noise by the development community;
+they tend to get a chilly reception.  So this type of patch is best
+avoided.  It is natural to fix the style of a piece of code while working
+on it for other reasons, but coding style changes should not be made for
+their own sake.
+
+The coding style document also should not be read as an absolute law which
+can never be transgressed.  If there is a good reason to go against the
+style (a line which becomes far less readable if split to fit within the
+80-column limit, for example), just do it.
+
+
+Abstraction layers
+******************
+
+Computer Science professors teach students to make extensive use of
+abstraction layers in the name of flexibility and information hiding.
+Certainly the kernel makes extensive use of abstraction; no project
+involving several million lines of code could do otherwise and survive.
+But experience has shown that excessive or premature abstraction can be
+just as harmful as premature optimization.  Abstraction should be used to
+the level required and no further.
+
+At a simple level, consider a function which has an argument which is
+always passed as zero by all callers.  One could retain that argument just
+in case somebody eventually needs to use the extra flexibility that it
+provides.  By that time, though, chances are good that the code which
+implements this extra argument has been broken in some subtle way which was
+never noticed - because it has never been used.  Or, when the need for
+extra flexibility arises, it does not do so in a way which matches the
+programmer's early expectation.  Kernel developers will routinely submit
+patches to remove unused arguments; they should, in general, not be added
+in the first place.
+
+Abstraction layers which hide access to hardware - often to allow the bulk
+of a driver to be used with multiple operating systems - are especially
+frowned upon.  Such layers obscure the code and may impose a performance
+penalty; they do not belong in the Linux kernel.
+
+On the other hand, if you find yourself copying significant amounts of code
+from another kernel subsystem, it is time to ask whether it would, in fact,
+make sense to pull out some of that code into a separate library or to
+implement that functionality at a higher level.  There is no value in
+replicating the same code throughout the kernel.
+
+
+#ifdef and preprocessor use in general
+**************************************
+
+The C preprocessor seems to present a powerful temptation to some C
+programmers, who see it as a way to efficiently encode a great deal of
+flexibility into a source file.  But the preprocessor is not C, and heavy
+use of it results in code which is much harder for others to read and
+harder for the compiler to check for correctness.  Heavy preprocessor use
+is almost always a sign of code which needs some cleanup work.
+
+Conditional compilation with #ifdef is, indeed, a powerful feature, and it
+is used within the kernel.  But there is little desire to see code which is
+sprinkled liberally with #ifdef blocks.  As a general rule, #ifdef use
+should be confined to header files whenever possible.
+Conditionally-compiled code can be confined to functions which, if the code
+is not to be present, simply become empty.  The compiler will then quietly
+optimize out the call to the empty function.  The result is far cleaner
+code which is easier to follow.
+
+C preprocessor macros present a number of hazards, including possible
+multiple evaluation of expressions with side effects and no type safety.
+If you are tempted to define a macro, consider creating an inline function
+instead.  The code which results will be the same, but inline functions are
+easier to read, do not evaluate their arguments multiple times, and allow
+the compiler to perform type checking on the arguments and return value.
+
+
+Inline functions
+****************
+
+Inline functions present a hazard of their own, though.  Programmers can
+become enamored of the perceived efficiency inherent in avoiding a function
+call and fill a source file with inline functions.  Those functions,
+however, can actually reduce performance.  Since their code is replicated
+at each call site, they end up bloating the size of the compiled kernel.
+That, in turn, creates pressure on the processor's memory caches, which can
+slow execution dramatically.  Inline functions, as a rule, should be quite
+small and relatively rare.  The cost of a function call, after all, is not
+that high; the creation of large numbers of inline functions is a classic
+example of premature optimization.
+
+In general, kernel programmers ignore cache effects at their peril.  The
+classic time/space tradeoff taught in beginning data structures classes
+often does not apply to contemporary hardware.  Space *is* time, in that a
+larger program will run slower than one which is more compact.
+
+More recent compilers take an increasingly active role in deciding whether
+a given function should actually be inlined or not.  So the liberal
+placement of "inline" keywords may not just be excessive; it could also be
+irrelevant.
+
+
+Locking
+*******
+
+In May, 2006, the "Devicescape" networking stack was, with great
+fanfare, released under the GPL and made available for inclusion in the
+mainline kernel.  This donation was welcome news; support for wireless
+networking in Linux was considered substandard at best, and the Devicescape
+stack offered the promise of fixing that situation.  Yet, this code did not
+actually make it into the mainline until June, 2007 (2.6.22).  What
+happened?
+
+This code showed a number of signs of having been developed behind
+corporate doors.  But one large problem in particular was that it was not
+designed to work on multiprocessor systems.  Before this networking stack
+(now called mac80211) could be merged, a locking scheme needed to be
+retrofitted onto it.
+
+Once upon a time, Linux kernel code could be developed without thinking
+about the concurrency issues presented by multiprocessor systems.  Now,
+however, this document is being written on a dual-core laptop.  Even on
+single-processor systems, work being done to improve responsiveness will
+raise the level of concurrency within the kernel.  The days when kernel
+code could be written without thinking about locking are long past.
+
+Any resource (data structures, hardware registers, etc.) which could be
+accessed concurrently by more than one thread must be protected by a lock.
+New code should be written with this requirement in mind; retrofitting
+locking after the fact is a rather more difficult task.  Kernel developers
+should take the time to understand the available locking primitives well
+enough to pick the right tool for the job.  Code which shows a lack of
+attention to concurrency will have a difficult path into the mainline.
+
+
+Regressions
+***********
+
+One final hazard worth mentioning is this: it can be tempting to make a
+change (which may bring big improvements) which causes something to break
+for existing users.  This kind of change is called a "regression," and
+regressions have become most unwelcome in the mainline kernel.  With few
+exceptions, changes which cause regressions will be backed out if the
+regression cannot be fixed in a timely manner.  Far better to avoid the
+regression in the first place.
+
+It is often argued that a regression can be justified if it causes things
+to work for more people than it creates problems for.  Why not make a
+change if it brings new functionality to ten systems for each one it
+breaks?  The best answer to this question was expressed by Linus in July,
+2007:
+
+::
+
+	So we don't fix bugs by introducing new problems.  That way lies
+	madness, and nobody ever knows if you actually make any real
+	progress at all. Is it two steps forwards, one step back, or one
+	step forward and two steps back?
+
+(http://lwn.net/Articles/243460/).
+
+An especially unwelcome type of regression is any sort of change to the
+user-space ABI.  Once an interface has been exported to user space, it must
+be supported indefinitely.  This fact makes the creation of user-space
+interfaces particularly challenging: since they cannot be changed in
+incompatible ways, they must be done right the first time.  For this
+reason, a great deal of thought, clear documentation, and wide review for
+user-space interfaces is always required.
+
+
+Code checking tools
+-------------------
+
+For now, at least, the writing of error-free code remains an ideal that few
+of us can reach.  What we can hope to do, though, is to catch and fix as
+many of those errors as possible before our code goes into the mainline
+kernel.  To that end, the kernel developers have put together an impressive
+array of tools which can catch a wide variety of obscure problems in an
+automated way.  Any problem caught by the computer is a problem which will
+not afflict a user later on, so it stands to reason that the automated
+tools should be used whenever possible.
+
+The first step is simply to heed the warnings produced by the compiler.
+Contemporary versions of gcc can detect (and warn about) a large number of
+potential errors.  Quite often, these warnings point to real problems.
+Code submitted for review should, as a rule, not produce any compiler
+warnings.  When silencing warnings, take care to understand the real cause
+and try to avoid "fixes" which make the warning go away without addressing
+its cause.
+
+Note that not all compiler warnings are enabled by default.  Build the
+kernel with "make EXTRA_CFLAGS=-W" to get the full set.
+
+The kernel provides several configuration options which turn on debugging
+features; most of these are found in the "kernel hacking" submenu.  Several
+of these options should be turned on for any kernel used for development or
+testing purposes.  In particular, you should turn on:
+
+ - ENABLE_WARN_DEPRECATED, ENABLE_MUST_CHECK, and FRAME_WARN to get an
+   extra set of warnings for problems like the use of deprecated interfaces
+   or ignoring an important return value from a function.  The output
+   generated by these warnings can be verbose, but one need not worry about
+   warnings from other parts of the kernel.
+
+ - DEBUG_OBJECTS will add code to track the lifetime of various objects
+   created by the kernel and warn when things are done out of order.  If
+   you are adding a subsystem which creates (and exports) complex objects
+   of its own, consider adding support for the object debugging
+   infrastructure.
+
+ - DEBUG_SLAB can find a variety of memory allocation and use errors; it
+   should be used on most development kernels.
+
+ - DEBUG_SPINLOCK, DEBUG_ATOMIC_SLEEP, and DEBUG_MUTEXES will find a
+   number of common locking errors.
+
+There are quite a few other debugging options, some of which will be
+discussed below.  Some of them have a significant performance impact and
+should not be used all of the time.  But some time spent learning the
+available options will likely be paid back many times over in short order.
+
+One of the heavier debugging tools is the locking checker, or "lockdep."
+This tool will track the acquisition and release of every lock (spinlock or
+mutex) in the system, the order in which locks are acquired relative to
+each other, the current interrupt environment, and more.  It can then
+ensure that locks are always acquired in the same order, that the same
+interrupt assumptions apply in all situations, and so on.  In other words,
+lockdep can find a number of scenarios in which the system could, on rare
+occasion, deadlock.  This kind of problem can be painful (for both
+developers and users) in a deployed system; lockdep allows them to be found
+in an automated manner ahead of time.  Code with any sort of non-trivial
+locking should be run with lockdep enabled before being submitted for
+inclusion.
+
+As a diligent kernel programmer, you will, beyond doubt, check the return
+status of any operation (such as a memory allocation) which can fail.  The
+fact of the matter, though, is that the resulting failure recovery paths
+are, probably, completely untested.  Untested code tends to be broken code;
+you could be much more confident of your code if all those error-handling
+paths had been exercised a few times.
+
+The kernel provides a fault injection framework which can do exactly that,
+especially where memory allocations are involved.  With fault injection
+enabled, a configurable percentage of memory allocations will be made to
+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.txt for more information on
+how to use this facility.
+
+Other kinds of errors can be found with the "sparse" static analysis tool.
+With sparse, the programmer can be warned about confusion between
+user-space and kernel-space addresses, mixture of big-endian and
+small-endian quantities, the passing of integer values where a set of bit
+flags is expected, and so on.  Sparse must be installed separately (it can
+be found at https://sparse.wiki.kernel.org/index.php/Main_Page if your
+distributor does not package it); it can then be run on the code by adding
+"C=1" to your make command.
+
+The "Coccinelle" tool (http://coccinelle.lip6.fr/) is able to find a wide
+variety of potential coding problems; it can also propose fixes for those
+problems.  Quite a few "semantic patches" for the kernel have been packaged
+under the scripts/coccinelle directory; running "make coccicheck" will run
+through those semantic patches and report on any problems found.  See
+Documentation/coccinelle.txt for more information.
+
+Other kinds of portability errors are best found by compiling your code for
+other architectures.  If you do not happen to have an S/390 system or a
+Blackfin development board handy, you can still perform the compilation
+step.  A large set of cross compilers for x86 systems can be found at
+
+	http://www.kernel.org/pub/tools/crosstool/
+
+Some time spent installing and using these compilers will help avoid
+embarrassment later.
+
+
+Documentation
+-------------
+
+Documentation has often been more the exception than the rule with kernel
+development.  Even so, adequate documentation will help to ease the merging
+of new code into the kernel, make life easier for other developers, and
+will be helpful for your users.  In many cases, the addition of
+documentation has become essentially mandatory.
+
+The first piece of documentation for any patch is its associated
+changelog.  Log entries should describe the problem being solved, the form
+of the solution, the people who worked on the patch, any relevant
+effects on performance, and anything else that might be needed to
+understand the patch.  Be sure that the changelog says *why* the patch is
+worth applying; a surprising number of developers fail to provide that
+information.
+
+Any code which adds a new user-space interface - including new sysfs or
+/proc files - should include documentation of that interface which enables
+user-space developers to know what they are working with.  See
+Documentation/ABI/README for a description of how this documentation should
+be formatted and what information needs to be provided.
+
+The file Documentation/admin-guide/kernel-parameters.rst describes all of the kernel's
+boot-time parameters.  Any patch which adds new parameters should add the
+appropriate entries to this file.
+
+Any new configuration options must be accompanied by help text which
+clearly explains the options and when the user might want to select them.
+
+Internal API information for many subsystems is documented by way of
+specially-formatted comments; these comments can be extracted and formatted
+in a number of ways by the "kernel-doc" script.  If you are working within
+a subsystem which has kerneldoc comments, you should maintain them and add
+them, as appropriate, for externally-available functions.  Even in areas
+which have not been so documented, there is no harm in adding kerneldoc
+comments for the future; indeed, this can be a useful activity for
+beginning kernel developers.  The format of these comments, along with some
+information on how to create kerneldoc templates can be found at
+:ref:`Documentation/doc-guide/ <doc_guide>`.
+
+Anybody who reads through a significant amount of existing kernel code will
+note that, often, comments are most notable by their absence.  Once again,
+the expectations for new code are higher than they were in the past;
+merging uncommented code will be harder.  That said, there is little desire
+for verbosely-commented code.  The code should, itself, be readable, with
+comments explaining the more subtle aspects.
+
+Certain things should always be commented.  Uses of memory barriers should
+be accompanied by a line explaining why the barrier is necessary.  The
+locking rules for data structures generally need to be explained somewhere.
+Major data structures need comprehensive documentation in general.
+Non-obvious dependencies between separate bits of code should be pointed
+out.  Anything which might tempt a code janitor to make an incorrect
+"cleanup" needs a comment saying why it is done the way it is.  And so on.
+
+
+Internal API changes
+--------------------
+
+The binary interface provided by the kernel to user space cannot be broken
+except under the most severe circumstances.  The kernel's internal
+programming interfaces, instead, are highly fluid and can be changed when
+the need arises.  If you find yourself having to work around a kernel API,
+or simply not using a specific functionality because it does not meet your
+needs, that may be a sign that the API needs to change.  As a kernel
+developer, you are empowered to make such changes.
+
+There are, of course, some catches.  API changes can be made, but they need
+to be well justified.  So any patch making an internal API change should be
+accompanied by a description of what the change is and why it is
+necessary.  This kind of change should also be broken out into a separate
+patch, rather than buried within a larger patch.
+
+The other catch is that a developer who changes an internal API is
+generally charged with the task of fixing any code within the kernel tree
+which is broken by the change.  For a widely-used function, this duty can
+lead to literally hundreds or thousands of changes - many of which are
+likely to conflict with work being done by other developers.  Needless to
+say, this can be a large job, so it is best to be sure that the
+justification is solid.  Note that the Coccinelle tool can help with
+wide-ranging API changes.
+
+When making an incompatible API change, one should, whenever possible,
+ensure that code which has not been updated is caught by the compiler.
+This will help you to be sure that you have found all in-tree uses of that
+interface.  It will also alert developers of out-of-tree code that there is
+a change that they need to respond to.  Supporting out-of-tree code is not
+something that kernel developers need to be worried about, but we also do
+not have to make life harder for out-of-tree developers than it needs to
+be.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/5.Posting.rst linux-libre-4.10-rc8-gnu/Documentation/process/5.Posting.rst
--- linux-libre-4.9-gnu/Documentation/process/5.Posting.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/5.Posting.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,321 @@
+.. _development_posting:
+
+Posting patches
+===============
+
+Sooner or later, the time comes when your work is ready to be presented to
+the community for review and, eventually, inclusion into the mainline
+kernel.  Unsurprisingly, the kernel development community has evolved a set
+of conventions and procedures which are used in the posting of patches;
+following them will make life much easier for everybody involved.  This
+document will attempt to cover these expectations in reasonable detail;
+more information can also be found in the files process/submitting-patches.rst,
+process/submitting-drivers.rst, and process/submit-checklist.rst in the kernel documentation
+directory.
+
+
+When to post
+------------
+
+There is a constant temptation to avoid posting patches before they are
+completely "ready."  For simple patches, that is not a problem.  If the
+work being done is complex, though, there is a lot to be gained by getting
+feedback from the community before the work is complete.  So you should
+consider posting in-progress work, or even making a git tree available so
+that interested developers can catch up with your work at any time.
+
+When posting code which is not yet considered ready for inclusion, it is a
+good idea to say so in the posting itself.  Also mention any major work
+which remains to be done and any known problems.  Fewer people will look at
+patches which are known to be half-baked, but those who do will come in
+with the idea that they can help you drive the work in the right direction.
+
+
+Before creating patches
+-----------------------
+
+There are a number of things which should be done before you consider
+sending patches to the development community.  These include:
+
+ - Test the code to the extent that you can.  Make use of the kernel's
+   debugging tools, ensure that the kernel will build with all reasonable
+   combinations of configuration options, use cross-compilers to build for
+   different architectures, etc.
+
+ - Make sure your code is compliant with the kernel coding style
+   guidelines.
+
+ - Does your change have performance implications?  If so, you should run
+   benchmarks showing what the impact (or benefit) of your change is; a
+   summary of the results should be included with the patch.
+
+ - Be sure that you have the right to post the code.  If this work was done
+   for an employer, the employer likely has a right to the work and must be
+   agreeable with its release under the GPL.
+
+As a general rule, putting in some extra thought before posting code almost
+always pays back the effort in short order.
+
+
+Patch preparation
+-----------------
+
+The preparation of patches for posting can be a surprising amount of work,
+but, once again, attempting to save time here is not generally advisable
+even in the short term.
+
+Patches must be prepared against a specific version of the kernel.  As a
+general rule, a patch should be based on the current mainline as found in
+Linus's git tree.  When basing on mainline, start with a well-known release
+point - a stable or -rc release - rather than branching off the mainline at
+an arbitrary spot.
+
+It may become necessary to make versions against -mm, linux-next, or a
+subsystem tree, though, to facilitate wider testing and review.  Depending
+on the area of your patch and what is going on elsewhere, basing a patch
+against these other trees can require a significant amount of work
+resolving conflicts and dealing with API changes.
+
+Only the most simple changes should be formatted as a single patch;
+everything else should be made as a logical series of changes.  Splitting
+up patches is a bit of an art; some developers spend a long time figuring
+out how to do it in the way that the community expects.  There are a few
+rules of thumb, however, which can help considerably:
+
+ - The patch series you post will almost certainly not be the series of
+   changes found in your working revision control system.  Instead, the
+   changes you have made need to be considered in their final form, then
+   split apart in ways which make sense.  The developers are interested in
+   discrete, self-contained changes, not the path you took to get to those
+   changes.
+
+ - Each logically independent change should be formatted as a separate
+   patch.  These changes can be small ("add a field to this structure") or
+   large (adding a significant new driver, for example), but they should be
+   conceptually small and amenable to a one-line description.  Each patch
+   should make a specific change which can be reviewed on its own and
+   verified to do what it says it does.
+
+ - As a way of restating the guideline above: do not mix different types of
+   changes in the same patch.  If a single patch fixes a critical security
+   bug, rearranges a few structures, and reformats the code, there is a
+   good chance that it will be passed over and the important fix will be
+   lost.
+
+ - Each patch should yield a kernel which builds and runs properly; if your
+   patch series is interrupted in the middle, the result should still be a
+   working kernel.  Partial application of a patch series is a common
+   scenario when the "git bisect" tool is used to find regressions; if the
+   result is a broken kernel, you will make life harder for developers and
+   users who are engaging in the noble work of tracking down problems.
+
+ - Do not overdo it, though.  One developer once posted a set of edits
+   to a single file as 500 separate patches - an act which did not make him
+   the most popular person on the kernel mailing list.  A single patch can
+   be reasonably large as long as it still contains a single *logical*
+   change.
+
+ - It can be tempting to add a whole new infrastructure with a series of
+   patches, but to leave that infrastructure unused until the final patch
+   in the series enables the whole thing.  This temptation should be
+   avoided if possible; if that series adds regressions, bisection will
+   finger the last patch as the one which caused the problem, even though
+   the real bug is elsewhere.  Whenever possible, a patch which adds new
+   code should make that code active immediately.
+
+Working to create the perfect patch series can be a frustrating process
+which takes quite a bit of time and thought after the "real work" has been
+done.  When done properly, though, it is time well spent.
+
+
+Patch formatting and changelogs
+-------------------------------
+
+So now you have a perfect series of patches for posting, but the work is
+not done quite yet.  Each patch needs to be formatted into a message which
+quickly and clearly communicates its purpose to the rest of the world.  To
+that end, each patch will be composed of the following:
+
+ - An optional "From" line naming the author of the patch.  This line is
+   only necessary if you are passing on somebody else's patch via email,
+   but it never hurts to add it when in doubt.
+
+ - A one-line description of what the patch does.  This message should be
+   enough for a reader who sees it with no other context to figure out the
+   scope of the patch; it is the line that will show up in the "short form"
+   changelogs.  This message is usually formatted with the relevant
+   subsystem name first, followed by the purpose of the patch.  For
+   example:
+
+   ::
+
+	gpio: fix build on CONFIG_GPIO_SYSFS=n
+
+ - A blank line followed by a detailed description of the contents of the
+   patch.  This description can be as long as is required; it should say
+   what the patch does and why it should be applied to the kernel.
+
+ - One or more tag lines, with, at a minimum, one Signed-off-by: line from
+   the author of the patch.  Tags will be described in more detail below.
+
+The items above, together, form the changelog for the patch.  Writing good
+changelogs is a crucial but often-neglected art; it's worth spending
+another moment discussing this issue.  When writing a changelog, you should
+bear in mind that a number of different people will be reading your words.
+These include subsystem maintainers and reviewers who need to decide
+whether the patch should be included, distributors and other maintainers
+trying to decide whether a patch should be backported to other kernels, bug
+hunters wondering whether the patch is responsible for a problem they are
+chasing, users who want to know how the kernel has changed, and more.  A
+good changelog conveys the needed information to all of these people in the
+most direct and concise way possible.
+
+To that end, the summary line should describe the effects of and motivation
+for the change as well as possible given the one-line constraint.  The
+detailed description can then amplify on those topics and provide any
+needed additional information.  If the patch fixes a bug, cite the commit
+which introduced the bug if possible (and please provide both the commit ID
+and the title when citing commits).  If a problem is associated with
+specific log or compiler output, include that output to help others
+searching for a solution to the same problem.  If the change is meant to
+support other changes coming in later patch, say so.  If internal APIs are
+changed, detail those changes and how other developers should respond.  In
+general, the more you can put yourself into the shoes of everybody who will
+be reading your changelog, the better that changelog (and the kernel as a
+whole) will be.
+
+Needless to say, the changelog should be the text used when committing the
+change to a revision control system.  It will be followed by:
+
+ - The patch itself, in the unified ("-u") patch format.  Using the "-p"
+   option to diff will associate function names with changes, making the
+   resulting patch easier for others to read.
+
+You should avoid including changes to irrelevant files (those generated by
+the build process, for example, or editor backup files) in the patch.  The
+file "dontdiff" in the Documentation directory can help in this regard;
+pass it to diff with the "-X" option.
+
+The tags mentioned above are used to describe how various developers have
+been associated with the development of this patch.  They are described in
+detail in the process/submitting-patches.rst document; what follows here is a brief
+summary.  Each of these lines has the format:
+
+::
+
+	tag: Full Name <email address>  optional-other-stuff
+
+The tags in common use are:
+
+ - Signed-off-by: this is a developer's certification that he or she has
+   the right to submit the patch for inclusion into the kernel.  It is an
+   agreement to the Developer's Certificate of Origin, the full text of
+   which can be found in Documentation/process/submitting-patches.rst.  Code without a
+   proper signoff cannot be merged into the mainline.
+
+ - Acked-by: indicates an agreement by another developer (often a
+   maintainer of the relevant code) that the patch is appropriate for
+   inclusion into the kernel.
+
+ - Tested-by: states that the named person has tested the patch and found
+   it to work.
+
+ - Reviewed-by: the named developer has reviewed the patch for correctness;
+   see the reviewer's statement in Documentation/process/submitting-patches.rst for more
+   detail.
+
+ - Reported-by: names a user who reported a problem which is fixed by this
+   patch; this tag is used to give credit to the (often underappreciated)
+   people who test our code and let us know when things do not work
+   correctly.
+
+ - Cc: the named person received a copy of the patch and had the
+   opportunity to comment on it.
+
+Be careful in the addition of tags to your patches: only Cc: is appropriate
+for addition without the explicit permission of the person named.
+
+
+Sending the patch
+-----------------
+
+Before you mail your patches, there are a couple of other things you should
+take care of:
+
+ - Are you sure that your mailer will not corrupt the patches?  Patches
+   which have had gratuitous white-space changes or line wrapping performed
+   by the mail client will not apply at the other end, and often will not
+   be examined in any detail.  If there is any doubt at all, mail the patch
+   to yourself and convince yourself that it shows up intact.
+
+   Documentation/process/email-clients.rst has some helpful hints on making
+   specific mail clients work for sending patches.
+
+ - Are you sure your patch is free of silly mistakes?  You should always
+   run patches through scripts/checkpatch.pl and address the complaints it
+   comes up with.  Please bear in mind that checkpatch.pl, while being the
+   embodiment of a fair amount of thought about what kernel patches should
+   look like, is not smarter than you.  If fixing a checkpatch.pl complaint
+   would make the code worse, don't do it.
+
+Patches should always be sent as plain text.  Please do not send them as
+attachments; that makes it much harder for reviewers to quote sections of
+the patch in their replies.  Instead, just put the patch directly into your
+message.
+
+When mailing patches, it is important to send copies to anybody who might
+be interested in it.  Unlike some other projects, the kernel encourages
+people to err on the side of sending too many copies; don't assume that the
+relevant people will see your posting on the mailing lists.  In particular,
+copies should go to:
+
+ - The maintainer(s) of the affected subsystem(s).  As described earlier,
+   the MAINTAINERS file is the first place to look for these people.
+
+ - Other developers who have been working in the same area - especially
+   those who might be working there now.  Using git to see who else has
+   modified the files you are working on can be helpful.
+
+ - If you are responding to a bug report or a feature request, copy the
+   original poster as well.
+
+ - Send a copy to the relevant mailing list, or, if nothing else applies,
+   the linux-kernel list.
+
+ - If you are fixing a bug, think about whether the fix should go into the
+   next stable update.  If so, stable@vger.kernel.org should get a copy of
+   the patch.  Also add a "Cc: stable@vger.kernel.org" to the tags within
+   the patch itself; that will cause the stable team to get a notification
+   when your fix goes into the mainline.
+
+When selecting recipients for a patch, it is good to have an idea of who
+you think will eventually accept the patch and get it merged.  While it
+is possible to send patches directly to Linus Torvalds and have him merge
+them, things are not normally done that way.  Linus is busy, and there are
+subsystem maintainers who watch over specific parts of the kernel.  Usually
+you will be wanting that maintainer to merge your patches.  If there is no
+obvious maintainer, Andrew Morton is often the patch target of last resort.
+
+Patches need good subject lines.  The canonical format for a patch line is
+something like:
+
+::
+
+	[PATCH nn/mm] subsys: one-line description of the patch
+
+where "nn" is the ordinal number of the patch, "mm" is the total number of
+patches in the series, and "subsys" is the name of the affected subsystem.
+Clearly, nn/mm can be omitted for a single, standalone patch.
+
+If you have a significant series of patches, it is customary to send an
+introductory description as part zero.  This convention is not universally
+followed though; if you use it, remember that information in the
+introduction does not make it into the kernel changelogs.  So please ensure
+that the patches, themselves, have complete changelog information.
+
+In general, the second and following parts of a multi-part patch should be
+sent as a reply to the first part so that they all thread together at the
+receiving end.  Tools like git and quilt have commands to mail out a set of
+patches with the proper threading.  If you have a long series, though, and
+are using git, please stay away from the --chain-reply-to option to avoid
+creating exceptionally deep nesting.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/6.Followthrough.rst linux-libre-4.10-rc8-gnu/Documentation/process/6.Followthrough.rst
--- linux-libre-4.9-gnu/Documentation/process/6.Followthrough.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/6.Followthrough.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,212 @@
+.. _development_followthrough:
+
+Followthrough
+=============
+
+At this point, you have followed the guidelines given so far and, with the
+addition of your own engineering skills, have posted a perfect series of
+patches.  One of the biggest mistakes that even experienced kernel
+developers can make is to conclude that their work is now done.  In truth,
+posting patches indicates a transition into the next stage of the process,
+with, possibly, quite a bit of work yet to be done.
+
+It is a rare patch which is so good at its first posting that there is no
+room for improvement.  The kernel development process recognizes this fact,
+and, as a result, is heavily oriented toward the improvement of posted
+code.  You, as the author of that code, will be expected to work with the
+kernel community to ensure that your code is up to the kernel's quality
+standards.  A failure to participate in this process is quite likely to
+prevent the inclusion of your patches into the mainline.
+
+
+Working with reviewers
+----------------------
+
+A patch of any significance will result in a number of comments from other
+developers as they review the code.  Working with reviewers can be, for
+many developers, the most intimidating part of the kernel development
+process.  Life can be made much easier, though, if you keep a few things in
+mind:
+
+ - If you have explained your patch well, reviewers will understand its
+   value and why you went to the trouble of writing it.  But that value
+   will not keep them from asking a fundamental question: what will it be
+   like to maintain a kernel with this code in it five or ten years later?
+   Many of the changes you may be asked to make - from coding style tweaks
+   to substantial rewrites - come from the understanding that Linux will
+   still be around and under development a decade from now.
+
+ - Code review is hard work, and it is a relatively thankless occupation;
+   people remember who wrote kernel code, but there is little lasting fame
+   for those who reviewed it.  So reviewers can get grumpy, especially when
+   they see the same mistakes being made over and over again.  If you get a
+   review which seems angry, insulting, or outright offensive, resist the
+   impulse to respond in kind.  Code review is about the code, not about
+   the people, and code reviewers are not attacking you personally.
+
+ - Similarly, code reviewers are not trying to promote their employers'
+   agendas at the expense of your own.  Kernel developers often expect to
+   be working on the kernel years from now, but they understand that their
+   employer could change.  They truly are, almost without exception,
+   working toward the creation of the best kernel they can; they are not
+   trying to create discomfort for their employers' competitors.
+
+What all of this comes down to is that, when reviewers send you comments,
+you need to pay attention to the technical observations that they are
+making.  Do not let their form of expression or your own pride keep that
+from happening.  When you get review comments on a patch, take the time to
+understand what the reviewer is trying to say.  If possible, fix the things
+that the reviewer is asking you to fix.  And respond back to the reviewer:
+thank them, and describe how you will answer their questions.
+
+Note that you do not have to agree with every change suggested by
+reviewers.  If you believe that the reviewer has misunderstood your code,
+explain what is really going on.  If you have a technical objection to a
+suggested change, describe it and justify your solution to the problem.  If
+your explanations make sense, the reviewer will accept them.  Should your
+explanation not prove persuasive, though, especially if others start to
+agree with the reviewer, take some time to think things over again.  It can
+be easy to become blinded by your own solution to a problem to the point
+that you don't realize that something is fundamentally wrong or, perhaps,
+you're not even solving the right problem.
+
+Andrew Morton has suggested that every review comment which does not result
+in a code change should result in an additional code comment instead; that
+can help future reviewers avoid the questions which came up the first time
+around.
+
+One fatal mistake is to ignore review comments in the hope that they will
+go away.  They will not go away.  If you repost code without having
+responded to the comments you got the time before, you're likely to find
+that your patches go nowhere.
+
+Speaking of reposting code: please bear in mind that reviewers are not
+going to remember all the details of the code you posted the last time
+around.  So it is always a good idea to remind reviewers of previously
+raised issues and how you dealt with them; the patch changelog is a good
+place for this kind of information.  Reviewers should not have to search
+through list archives to familiarize themselves with what was said last
+time; if you help them get a running start, they will be in a better mood
+when they revisit your code.
+
+What if you've tried to do everything right and things still aren't going
+anywhere?  Most technical disagreements can be resolved through discussion,
+but there are times when somebody simply has to make a decision.  If you
+honestly believe that this decision is going against you wrongly, you can
+always try appealing to a higher power.  As of this writing, that higher
+power tends to be Andrew Morton.  Andrew has a great deal of respect in the
+kernel development community; he can often unjam a situation which seems to
+be hopelessly blocked.  Appealing to Andrew should not be done lightly,
+though, and not before all other alternatives have been explored.  And bear
+in mind, of course, that he may not agree with you either.
+
+
+What happens next
+-----------------
+
+If a patch is considered to be a good thing to add to the kernel, and once
+most of the review issues have been resolved, the next step is usually
+entry into a subsystem maintainer's tree.  How that works varies from one
+subsystem to the next; each maintainer has his or her own way of doing
+things.  In particular, there may be more than one tree - one, perhaps,
+dedicated to patches planned for the next merge window, and another for
+longer-term work.
+
+For patches applying to areas for which there is no obvious subsystem tree
+(memory management patches, for example), the default tree often ends up
+being -mm.  Patches which affect multiple subsystems can also end up going
+through the -mm tree.
+
+Inclusion into a subsystem tree can bring a higher level of visibility to a
+patch.  Now other developers working with that tree will get the patch by
+default.  Subsystem trees typically feed linux-next as well, making their
+contents visible to the development community as a whole.  At this point,
+there's a good chance that you will get more comments from a new set of
+reviewers; these comments need to be answered as in the previous round.
+
+What may also happen at this point, depending on the nature of your patch,
+is that conflicts with work being done by others turn up.  In the worst
+case, heavy patch conflicts can result in some work being put on the back
+burner so that the remaining patches can be worked into shape and merged.
+Other times, conflict resolution will involve working with the other
+developers and, possibly, moving some patches between trees to ensure that
+everything applies cleanly.  This work can be a pain, but count your
+blessings: before the advent of the linux-next tree, these conflicts often
+only turned up during the merge window and had to be addressed in a hurry.
+Now they can be resolved at leisure, before the merge window opens.
+
+Some day, if all goes well, you'll log on and see that your patch has been
+merged into the mainline kernel.  Congratulations!  Once the celebration is
+complete (and you have added yourself to the MAINTAINERS file), though, it
+is worth remembering an important little fact: the job still is not done.
+Merging into the mainline brings its own challenges.
+
+To begin with, the visibility of your patch has increased yet again.  There
+may be a new round of comments from developers who had not been aware of
+the patch before.  It may be tempting to ignore them, since there is no
+longer any question of your code being merged.  Resist that temptation,
+though; you still need to be responsive to developers who have questions or
+suggestions.
+
+More importantly, though: inclusion into the mainline puts your code into
+the hands of a much larger group of testers.  Even if you have contributed
+a driver for hardware which is not yet available, you will be surprised by
+how many people will build your code into their kernels.  And, of course,
+where there are testers, there will be bug reports.
+
+The worst sort of bug reports are regressions.  If your patch causes a
+regression, you'll find an uncomfortable number of eyes upon you;
+regressions need to be fixed as soon as possible.  If you are unwilling or
+unable to fix the regression (and nobody else does it for you), your patch
+will almost certainly be removed during the stabilization period.  Beyond
+negating all of the work you have done to get your patch into the mainline,
+having a patch pulled as the result of a failure to fix a regression could
+well make it harder for you to get work merged in the future.
+
+After any regressions have been dealt with, there may be other, ordinary
+bugs to deal with.  The stabilization period is your best opportunity to
+fix these bugs and ensure that your code's debut in a mainline kernel
+release is as solid as possible.  So, please, answer bug reports, and fix
+the problems if at all possible.  That's what the stabilization period is
+for; you can start creating cool new patches once any problems with the old
+ones have been taken care of.
+
+And don't forget that there are other milestones which may also create bug
+reports: the next mainline stable release, when prominent distributors pick
+up a version of the kernel containing your patch, etc.  Continuing to
+respond to these reports is a matter of basic pride in your work.  If that
+is insufficient motivation, though, it's also worth considering that the
+development community remembers developers who lose interest in their code
+after it's merged.  The next time you post a patch, they will be evaluating
+it with the assumption that you will not be around to maintain it
+afterward.
+
+
+Other things that can happen
+-----------------------------
+
+One day, you may open your mail client and see that somebody has mailed you
+a patch to your code.  That is one of the advantages of having your code
+out there in the open, after all.  If you agree with the patch, you can
+either forward it on to the subsystem maintainer (be sure to include a
+proper From: line so that the attribution is correct, and add a signoff of
+your own), or send an Acked-by: response back and let the original poster
+send it upward.
+
+If you disagree with the patch, send a polite response explaining why.  If
+possible, tell the author what changes need to be made to make the patch
+acceptable to you.  There is a certain resistance to merging patches which
+are opposed by the author and maintainer of the code, but it only goes so
+far.  If you are seen as needlessly blocking good work, those patches will
+eventually flow around you and get into the mainline anyway.  In the Linux
+kernel, nobody has absolute veto power over any code.  Except maybe Linus.
+
+On very rare occasion, you may see something completely different: another
+developer posts a different solution to your problem.  At that point,
+chances are that one of the two patches will not be merged, and "mine was
+here first" is not considered to be a compelling technical argument.  If
+somebody else's patch displaces yours and gets into the mainline, there is
+really only one way to respond: be pleased that your problem got solved and
+get on with your work.  Having one's work shoved aside in this manner can
+be hurtful and discouraging, but the community will remember your reaction
+long after they have forgotten whose patch actually got merged.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/7.AdvancedTopics.rst linux-libre-4.10-rc8-gnu/Documentation/process/7.AdvancedTopics.rst
--- linux-libre-4.9-gnu/Documentation/process/7.AdvancedTopics.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/7.AdvancedTopics.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,178 @@
+.. _development_advancedtopics:
+
+Advanced topics
+===============
+
+At this point, hopefully, you have a handle on how the development process
+works.  There is still more to learn, however!  This section will cover a
+number of topics which can be helpful for developers wanting to become a
+regular part of the Linux kernel development process.
+
+Managing patches with git
+-------------------------
+
+The use of distributed version control for the kernel began in early 2002,
+when Linus first started playing with the proprietary BitKeeper
+application.  While BitKeeper was controversial, the approach to software
+version management it embodied most certainly was not.  Distributed version
+control enabled an immediate acceleration of the kernel development
+project.  In current times, there are several free alternatives to
+BitKeeper.  For better or for worse, the kernel project has settled on git
+as its tool of choice.
+
+Managing patches with git can make life much easier for the developer,
+especially as the volume of those patches grows.  Git also has its rough
+edges and poses certain hazards; it is a young and powerful tool which is
+still being civilized by its developers.  This document will not attempt to
+teach the reader how to use git; that would be sufficient material for a
+long document in its own right.  Instead, the focus here will be on how git
+fits into the kernel development process in particular.  Developers who
+wish to come up to speed with git will find more information at:
+
+	http://git-scm.com/
+
+	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+and on various tutorials found on the web.
+
+The first order of business is to read the above sites and get a solid
+understanding of how git works before trying to use it to make patches
+available to others.  A git-using developer should be able to obtain a copy
+of the mainline repository, explore the revision history, commit changes to
+the tree, use branches, etc.  An understanding of git's tools for the
+rewriting of history (such as rebase) is also useful.  Git comes with its
+own terminology and concepts; a new user of git should know about refs,
+remote branches, the index, fast-forward merges, pushes and pulls, detached
+heads, etc.  It can all be a little intimidating at the outset, but the
+concepts are not that hard to grasp with a bit of study.
+
+Using git to generate patches for submission by email can be a good
+exercise while coming up to speed.
+
+When you are ready to start putting up git trees for others to look at, you
+will, of course, need a server that can be pulled from.  Setting up such a
+server with git-daemon is relatively straightforward if you have a system
+which is accessible to the Internet.  Otherwise, free, public hosting sites
+(Github, for example) are starting to appear on the net.  Established
+developers can get an account on kernel.org, but those are not easy to come
+by; see http://kernel.org/faq/ for more information.
+
+The normal git workflow involves the use of a lot of branches.  Each line
+of development can be separated into a separate "topic branch" and
+maintained independently.  Branches in git are cheap, there is no reason to
+not make free use of them.  And, in any case, you should not do your
+development in any branch which you intend to ask others to pull from.
+Publicly-available branches should be created with care; merge in patches
+from development branches when they are in complete form and ready to go -
+not before.
+
+Git provides some powerful tools which can allow you to rewrite your
+development history.  An inconvenient patch (one which breaks bisection,
+say, or which has some other sort of obvious bug) can be fixed in place or
+made to disappear from the history entirely.  A patch series can be
+rewritten as if it had been written on top of today's mainline, even though
+you have been working on it for months.  Changes can be transparently
+shifted from one branch to another.  And so on.  Judicious use of git's
+ability to revise history can help in the creation of clean patch sets with
+fewer problems.
+
+Excessive use of this capability can lead to other problems, though, beyond
+a simple obsession for the creation of the perfect project history.
+Rewriting history will rewrite the changes contained in that history,
+turning a tested (hopefully) kernel tree into an untested one.  But, beyond
+that, developers cannot easily collaborate if they do not have a shared
+view of the project history; if you rewrite history which other developers
+have pulled into their repositories, you will make life much more difficult
+for those developers.  So a simple rule of thumb applies here: history
+which has been exported to others should generally be seen as immutable
+thereafter.
+
+So, once you push a set of changes to your publicly-available server, those
+changes should not be rewritten.  Git will attempt to enforce this rule if
+you try to push changes which do not result in a fast-forward merge
+(i.e. changes which do not share the same history).  It is possible to
+override this check, and there may be times when it is necessary to rewrite
+an exported tree.  Moving changesets between trees to avoid conflicts in
+linux-next is one example.  But such actions should be rare.  This is one
+of the reasons why development should be done in private branches (which
+can be rewritten if necessary) and only moved into public branches when
+it's in a reasonably advanced state.
+
+As the mainline (or other tree upon which a set of changes is based)
+advances, it is tempting to merge with that tree to stay on the leading
+edge.  For a private branch, rebasing can be an easy way to keep up with
+another tree, but rebasing is not an option once a tree is exported to the
+world.  Once that happens, a full merge must be done.  Merging occasionally
+makes good sense, but overly frequent merges can clutter the history
+needlessly.  Suggested technique in this case is to merge infrequently, and
+generally only at specific release points (such as a mainline -rc
+release).  If you are nervous about specific changes, you can always
+perform test merges in a private branch.  The git "rerere" tool can be
+useful in such situations; it remembers how merge conflicts were resolved
+so that you don't have to do the same work twice.
+
+One of the biggest recurring complaints about tools like git is this: the
+mass movement of patches from one repository to another makes it easy to
+slip in ill-advised changes which go into the mainline below the review
+radar.  Kernel developers tend to get unhappy when they see that kind of
+thing happening; putting up a git tree with unreviewed or off-topic patches
+can affect your ability to get trees pulled in the future.  Quoting Linus:
+
+::
+
+	You can send me patches, but for me to pull a git patch from you, I
+	need to know that you know what you're doing, and I need to be able
+	to trust things *without* then having to go and check every
+	individual change by hand.
+
+(http://lwn.net/Articles/224135/).
+
+To avoid this kind of situation, ensure that all patches within a given
+branch stick closely to the associated topic; a "driver fixes" branch
+should not be making changes to the core memory management code.  And, most
+importantly, do not use a git tree to bypass the review process.  Post an
+occasional summary of the tree to the relevant list, and, when the time is
+right, request that the tree be included in linux-next.
+
+If and when others start to send patches for inclusion into your tree,
+don't forget to review them.  Also ensure that you maintain the correct
+authorship information; the git "am" tool does its best in this regard, but
+you may have to add a "From:" line to the patch if it has been relayed to
+you via a third party.
+
+When requesting a pull, be sure to give all the relevant information: where
+your tree is, what branch to pull, and what changes will result from the
+pull.  The git request-pull command can be helpful in this regard; it will
+format the request as other developers expect, and will also check to be
+sure that you have remembered to push those changes to the public server.
+
+
+Reviewing patches
+-----------------
+
+Some readers will certainly object to putting this section with "advanced
+topics" on the grounds that even beginning kernel developers should be
+reviewing patches.  It is certainly true that there is no better way to
+learn how to program in the kernel environment than by looking at code
+posted by others.  In addition, reviewers are forever in short supply; by
+looking at code you can make a significant contribution to the process as a
+whole.
+
+Reviewing code can be an intimidating prospect, especially for a new kernel
+developer who may well feel nervous about questioning code - in public -
+which has been posted by those with more experience.  Even code written by
+the most experienced developers can be improved, though.  Perhaps the best
+piece of advice for reviewers (all reviewers) is this: phrase review
+comments as questions rather than criticisms.  Asking "how does the lock
+get released in this path?" will always work better than stating "the
+locking here is wrong."
+
+Different developers will review code from different points of view.  Some
+are mostly concerned with coding style and whether code lines have trailing
+white space.  Others will focus primarily on whether the change implemented
+by the patch as a whole is a good thing for the kernel or not.  Yet others
+will check for problematic locking, excessive stack usage, possible
+security issues, duplication of code found elsewhere, adequate
+documentation, adverse effects on performance, user-space ABI changes, etc.
+All types of review, if they lead to better code going into the kernel, are
+welcome and worthwhile.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/8.Conclusion.rst linux-libre-4.10-rc8-gnu/Documentation/process/8.Conclusion.rst
--- linux-libre-4.9-gnu/Documentation/process/8.Conclusion.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/8.Conclusion.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,74 @@
+.. _development_conclusion:
+
+For more information
+====================
+
+There are numerous sources of information on Linux kernel development and
+related topics.  First among those will always be the Documentation
+directory found in the kernel source distribution.  The top-level process/howto.rst
+file is an important starting point; process/submitting-patches.rst and
+process/submitting-drivers.rst are also something which all kernel developers should
+read.  Many internal kernel APIs are documented using the kerneldoc
+mechanism; "make htmldocs" or "make pdfdocs" can be used to generate those
+documents in HTML or PDF format (though the version of TeX shipped by some
+distributions runs into internal limits and fails to process the documents
+properly).
+
+Various web sites discuss kernel development at all levels of detail.  Your
+author would like to humbly suggest http://lwn.net/ as a source;
+information on many specific kernel topics can be found via the LWN kernel
+index at:
+
+	http://lwn.net/Kernel/Index/
+
+Beyond that, a valuable resource for kernel developers is:
+
+	http://kernelnewbies.org/
+
+And, of course, one should not forget http://kernel.org/, the definitive
+location for kernel release information.
+
+There are a number of books on kernel development:
+
+	Linux Device Drivers, 3rd Edition (Jonathan Corbet, Alessandro
+	Rubini, and Greg Kroah-Hartman).  Online at
+	http://lwn.net/Kernel/LDD3/.
+
+	Linux Kernel Development (Robert Love).
+
+	Understanding the Linux Kernel (Daniel Bovet and Marco Cesati).
+
+All of these books suffer from a common fault, though: they tend to be
+somewhat obsolete by the time they hit the shelves, and they have been on
+the shelves for a while now.  Still, there is quite a bit of good
+information to be found there.
+
+Documentation for git can be found at:
+
+	http://www.kernel.org/pub/software/scm/git/docs/
+
+	http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
+
+
+Conclusion
+==========
+
+Congratulations to anybody who has made it through this long-winded
+document.  Hopefully it has provided a helpful understanding of how the
+Linux kernel is developed and how you can participate in that process.
+
+In the end, it's the participation that matters.  Any open source software
+project is no more than the sum of what its contributors put into it.  The
+Linux kernel has progressed as quickly and as well as it has because it has
+been helped by an impressively large group of developers, all of whom are
+working to make it better.  The kernel is a premier example of what can be
+done when thousands of people work together toward a common goal.
+
+The kernel can always benefit from a larger developer base, though.  There
+is always more work to do.  But, just as importantly, most other
+participants in the Linux ecosystem can benefit through contributing to the
+kernel.  Getting code into the mainline is the key to higher code quality,
+lower maintenance and distribution costs, a higher level of influence over
+the direction of kernel development, and more.  It is a situation where
+everybody involved wins.  Fire up your editor and come join us; you will be
+more than welcome.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/adding-syscalls.rst linux-libre-4.10-rc8-gnu/Documentation/process/adding-syscalls.rst
--- linux-libre-4.9-gnu/Documentation/process/adding-syscalls.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/adding-syscalls.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,542 @@
+Adding a New System Call
+========================
+
+This document describes what's involved in adding a new system call to the
+Linux kernel, over and above the normal submission advice in
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
+
+
+System Call Alternatives
+------------------------
+
+The first thing to consider when adding a new system call is whether one of
+the alternatives might be suitable instead.  Although system calls are the
+most traditional and most obvious interaction points between userspace and the
+kernel, there are other possibilities -- choose what fits best for your
+interface.
+
+ - If the operations involved can be made to look like a filesystem-like
+   object, it may make more sense to create a new filesystem or device.  This
+   also makes it easier to encapsulate the new functionality in a kernel module
+   rather than requiring it to be built into the main kernel.
+
+     - If the new functionality involves operations where the kernel notifies
+       userspace that something has happened, then returning a new file
+       descriptor for the relevant object allows userspace to use
+       ``poll``/``select``/``epoll`` to receive that notification.
+     - However, operations that don't map to
+       :manpage:`read(2)`/:manpage:`write(2)`-like operations
+       have to be implemented as :manpage:`ioctl(2)` requests, which can lead
+       to a somewhat opaque API.
+
+ - If you're just exposing runtime system information, a new node in sysfs
+   (see ``Documentation/filesystems/sysfs.txt``) or the ``/proc`` filesystem may
+   be more appropriate.  However, access to these mechanisms requires that the
+   relevant filesystem is mounted, which might not always be the case (e.g.
+   in a namespaced/sandboxed/chrooted environment).  Avoid adding any API to
+   debugfs, as this is not considered a 'production' interface to userspace.
+ - If the operation is specific to a particular file or file descriptor, then
+   an additional :manpage:`fcntl(2)` command option may be more appropriate.  However,
+   :manpage:`fcntl(2)` is a multiplexing system call that hides a lot of complexity, so
+   this option is best for when the new function is closely analogous to
+   existing :manpage:`fcntl(2)` functionality, or the new functionality is very simple
+   (for example, getting/setting a simple flag related to a file descriptor).
+ - If the operation is specific to a particular task or process, then an
+   additional :manpage:`prctl(2)` command option may be more appropriate.  As
+   with :manpage:`fcntl(2)`, this system call is a complicated multiplexor so
+   is best reserved for near-analogs of existing ``prctl()`` commands or
+   getting/setting a simple flag related to a process.
+
+
+Designing the API: Planning for Extension
+-----------------------------------------
+
+A new system call forms part of the API of the kernel, and has to be supported
+indefinitely.  As such, it's a very good idea to explicitly discuss the
+interface on the kernel mailing list, and it's important to plan for future
+extensions of the interface.
+
+(The syscall table is littered with historical examples where this wasn't done,
+together with the corresponding follow-up system calls --
+``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``,
+``pipe``/``pipe2``, ``renameat``/``renameat2`` -- so
+learn from the history of the kernel and plan for extensions from the start.)
+
+For simpler system calls that only take a couple of arguments, the preferred
+way to allow for future extensibility is to include a flags argument to the
+system call.  To make sure that userspace programs can safely use flags
+between kernel versions, check whether the flags value holds any unknown
+flags, and reject the system call (with ``EINVAL``) if it does::
+
+    if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
+        return -EINVAL;
+
+(If no flags values are used yet, check that the flags argument is zero.)
+
+For more sophisticated system calls that involve a larger number of arguments,
+it's preferred to encapsulate the majority of the arguments into a structure
+that is passed in by pointer.  Such a structure can cope with future extension
+by including a size argument in the structure::
+
+    struct xyzzy_params {
+        u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */
+        u32 param_1;
+        u64 param_2;
+        u64 param_3;
+    };
+
+As long as any subsequently added field, say ``param_4``, is designed so that a
+zero value gives the previous behaviour, then this allows both directions of
+version mismatch:
+
+ - To cope with a later userspace program calling an older kernel, the kernel
+   code should check that any memory beyond the size of the structure that it
+   expects is zero (effectively checking that ``param_4 == 0``).
+ - To cope with an older userspace program calling a newer kernel, the kernel
+   code can zero-extend a smaller instance of the structure (effectively
+   setting ``param_4 = 0``).
+
+See :manpage:`perf_event_open(2)` and the ``perf_copy_attr()`` function (in
+``kernel/events/core.c``) for an example of this approach.
+
+
+Designing the API: Other Considerations
+---------------------------------------
+
+If your new system call allows userspace to refer to a kernel object, it
+should use a file descriptor as the handle for that object -- don't invent a
+new type of userspace object handle when the kernel already has mechanisms and
+well-defined semantics for using file descriptors.
+
+If your new :manpage:`xyzzy(2)` system call does return a new file descriptor,
+then the flags argument should include a value that is equivalent to setting
+``O_CLOEXEC`` on the new FD.  This makes it possible for userspace to close
+the timing window between ``xyzzy()`` and calling
+``fcntl(fd, F_SETFD, FD_CLOEXEC)``, where an unexpected ``fork()`` and
+``execve()`` in another thread could leak a descriptor to
+the exec'ed program. (However, resist the temptation to re-use the actual value
+of the ``O_CLOEXEC`` constant, as it is architecture-specific and is part of a
+numbering space of ``O_*`` flags that is fairly full.)
+
+If your system call returns a new file descriptor, you should also consider
+what it means to use the :manpage:`poll(2)` family of system calls on that file
+descriptor. Making a file descriptor ready for reading or writing is the
+normal way for the kernel to indicate to userspace that an event has
+occurred on the corresponding kernel object.
+
+If your new :manpage:`xyzzy(2)` system call involves a filename argument::
+
+    int sys_xyzzy(const char __user *path, ..., unsigned int flags);
+
+you should also consider whether an :manpage:`xyzzyat(2)` version is more appropriate::
+
+    int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);
+
+This allows more flexibility for how userspace specifies the file in question;
+in particular it allows userspace to request the functionality for an
+already-opened file descriptor using the ``AT_EMPTY_PATH`` flag, effectively
+giving an :manpage:`fxyzzy(3)` operation for free::
+
+ - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...)
+ - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...)
+
+(For more details on the rationale of the \*at() calls, see the
+:manpage:`openat(2)` man page; for an example of AT_EMPTY_PATH, see the
+:manpage:`fstatat(2)` man page.)
+
+If your new :manpage:`xyzzy(2)` system call involves a parameter describing an
+offset within a file, make its type ``loff_t`` so that 64-bit offsets can be
+supported even on 32-bit architectures.
+
+If your new :manpage:`xyzzy(2)` system call involves privileged functionality,
+it needs to be governed by the appropriate Linux capability bit (checked with
+a call to ``capable()``), as described in the :manpage:`capabilities(7)` man
+page.  Choose an existing capability bit that governs related functionality,
+but try to avoid combining lots of only vaguely related functions together
+under the same bit, as this goes against capabilities' purpose of splitting
+the power of root.  In particular, avoid adding new uses of the already
+overly-general ``CAP_SYS_ADMIN`` capability.
+
+If your new :manpage:`xyzzy(2)` system call manipulates a process other than
+the calling process, it should be restricted (using a call to
+``ptrace_may_access()``) so that only a calling process with the same
+permissions as the target process, or with the necessary capabilities, can
+manipulate the target process.
+
+Finally, be aware that some non-x86 architectures have an easier time if
+system call parameters that are explicitly 64-bit fall on odd-numbered
+arguments (i.e. parameter 1, 3, 5), to allow use of contiguous pairs of 32-bit
+registers.  (This concern does not apply if the arguments are part of a
+structure that's passed in by pointer.)
+
+
+Proposing the API
+-----------------
+
+To make new system calls easy to review, it's best to divide up the patchset
+into separate chunks.  These should include at least the following items as
+distinct commits (each of which is described further below):
+
+ - The core implementation of the system call, together with prototypes,
+   generic numbering, Kconfig changes and fallback stub implementation.
+ - Wiring up of the new system call for one particular architecture, usually
+   x86 (including all of x86_64, x86_32 and x32).
+ - A demonstration of the use of the new system call in userspace via a
+   selftest in ``tools/testing/selftests/``.
+ - A draft man-page for the new system call, either as plain text in the
+   cover letter, or as a patch to the (separate) man-pages repository.
+
+New system call proposals, like any change to the kernel's API, should always
+be cc'ed to linux-api@vger.kernel.org.
+
+
+Generic System Call Implementation
+----------------------------------
+
+The main entry point for your new :manpage:`xyzzy(2)` system call will be called
+``sys_xyzzy()``, but you add this entry point with the appropriate
+``SYSCALL_DEFINEn()`` macro rather than explicitly.  The 'n' indicates the
+number of arguments to the system call, and the macro takes the system call name
+followed by the (type, name) pairs for the parameters as arguments.  Using
+this macro allows metadata about the new system call to be made available for
+other tools.
+
+The new entry point also needs a corresponding function prototype, in
+``include/linux/syscalls.h``, marked as asmlinkage to match the way that system
+calls are invoked::
+
+    asmlinkage long sys_xyzzy(...);
+
+Some architectures (e.g. x86) have their own architecture-specific syscall
+tables, but several other architectures share a generic syscall table. Add your
+new system call to the generic list by adding an entry to the list in
+``include/uapi/asm-generic/unistd.h``::
+
+    #define __NR_xyzzy 292
+    __SYSCALL(__NR_xyzzy, sys_xyzzy)
+
+Also update the __NR_syscalls count to reflect the additional system call, and
+note that if multiple new system calls are added in the same merge window,
+your new syscall number may get adjusted to resolve conflicts.
+
+The file ``kernel/sys_ni.c`` provides a fallback stub implementation of each
+system call, returning ``-ENOSYS``.  Add your new system call here too::
+
+    cond_syscall(sys_xyzzy);
+
+Your new kernel functionality, and the system call that controls it, should
+normally be optional, so add a ``CONFIG`` option (typically to
+``init/Kconfig``) for it. As usual for new ``CONFIG`` options:
+
+ - Include a description of the new functionality and system call controlled
+   by the option.
+ - Make the option depend on EXPERT if it should be hidden from normal users.
+ - Make any new source files implementing the function dependent on the CONFIG
+   option in the Makefile (e.g. ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.c``).
+ - Double check that the kernel still builds with the new CONFIG option turned
+   off.
+
+To summarize, you need a commit that includes:
+
+ - ``CONFIG`` option for the new function, normally in ``init/Kconfig``
+ - ``SYSCALL_DEFINEn(xyzzy, ...)`` for the entry point
+ - corresponding prototype in ``include/linux/syscalls.h``
+ - generic table entry in ``include/uapi/asm-generic/unistd.h``
+ - fallback stub in ``kernel/sys_ni.c``
+
+
+x86 System Call Implementation
+------------------------------
+
+To wire up your new system call for x86 platforms, you need to update the
+master syscall tables.  Assuming your new system call isn't special in some
+way (see below), this involves a "common" entry (for x86_64 and x32) in
+arch/x86/entry/syscalls/syscall_64.tbl::
+
+    333   common   xyzzy     sys_xyzzy
+
+and an "i386" entry in ``arch/x86/entry/syscalls/syscall_32.tbl``::
+
+    380   i386     xyzzy     sys_xyzzy
+
+Again, these numbers are liable to be changed if there are conflicts in the
+relevant merge window.
+
+
+Compatibility System Calls (Generic)
+------------------------------------
+
+For most system calls the same 64-bit implementation can be invoked even when
+the userspace program is itself 32-bit; even if the system call's parameters
+include an explicit pointer, this is handled transparently.
+
+However, there are a couple of situations where a compatibility layer is
+needed to cope with size differences between 32-bit and 64-bit.
+
+The first is if the 64-bit kernel also supports 32-bit userspace programs, and
+so needs to parse areas of (``__user``) memory that could hold either 32-bit or
+64-bit values.  In particular, this is needed whenever a system call argument
+is:
+
+ - a pointer to a pointer
+ - a pointer to a struct containing a pointer (e.g. ``struct iovec __user *``)
+ - a pointer to a varying sized integral type (``time_t``, ``off_t``,
+   ``long``, ...)
+ - a pointer to a struct containing a varying sized integral type.
+
+The second situation that requires a compatibility layer is if one of the
+system call's arguments has a type that is explicitly 64-bit even on a 32-bit
+architecture, for example ``loff_t`` or ``__u64``.  In this case, a value that
+arrives at a 64-bit kernel from a 32-bit application will be split into two
+32-bit values, which then need to be re-assembled in the compatibility layer.
+
+(Note that a system call argument that's a pointer to an explicit 64-bit type
+does **not** need a compatibility layer; for example, :manpage:`splice(2)`'s arguments of
+type ``loff_t __user *`` do not trigger the need for a ``compat_`` system call.)
+
+The compatibility version of the system call is called ``compat_sys_xyzzy()``,
+and is added with the ``COMPAT_SYSCALL_DEFINEn()`` macro, analogously to
+SYSCALL_DEFINEn.  This version of the implementation runs as part of a 64-bit
+kernel, but expects to receive 32-bit parameter values and does whatever is
+needed to deal with them.  (Typically, the ``compat_sys_`` version converts the
+values to 64-bit versions and either calls on to the ``sys_`` version, or both of
+them call a common inner implementation function.)
+
+The compat entry point also needs a corresponding function prototype, in
+``include/linux/compat.h``, marked as asmlinkage to match the way that system
+calls are invoked::
+
+    asmlinkage long compat_sys_xyzzy(...);
+
+If the system call involves a structure that is laid out differently on 32-bit
+and 64-bit systems, say ``struct xyzzy_args``, then the include/linux/compat.h
+header file should also include a compat version of the structure (``struct
+compat_xyzzy_args``) where each variable-size field has the appropriate
+``compat_`` type that corresponds to the type in ``struct xyzzy_args``.  The
+``compat_sys_xyzzy()`` routine can then use this ``compat_`` structure to
+parse the arguments from a 32-bit invocation.
+
+For example, if there are fields::
+
+    struct xyzzy_args {
+        const char __user *ptr;
+        __kernel_long_t varying_val;
+        u64 fixed_val;
+        /* ... */
+    };
+
+in struct xyzzy_args, then struct compat_xyzzy_args would have::
+
+    struct compat_xyzzy_args {
+        compat_uptr_t ptr;
+        compat_long_t varying_val;
+        u64 fixed_val;
+        /* ... */
+    };
+
+The generic system call list also needs adjusting to allow for the compat
+version; the entry in ``include/uapi/asm-generic/unistd.h`` should use
+``__SC_COMP`` rather than ``__SYSCALL``::
+
+    #define __NR_xyzzy 292
+    __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)
+
+To summarize, you need:
+
+ - a ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` for the compat entry point
+ - corresponding prototype in ``include/linux/compat.h``
+ - (if needed) 32-bit mapping struct in ``include/linux/compat.h``
+ - instance of ``__SC_COMP`` not ``__SYSCALL`` in
+   ``include/uapi/asm-generic/unistd.h``
+
+
+Compatibility System Calls (x86)
+--------------------------------
+
+To wire up the x86 architecture of a system call with a compatibility version,
+the entries in the syscall tables need to be adjusted.
+
+First, the entry in ``arch/x86/entry/syscalls/syscall_32.tbl`` gets an extra
+column to indicate that a 32-bit userspace program running on a 64-bit kernel
+should hit the compat entry point::
+
+    380   i386     xyzzy     sys_xyzzy    compat_sys_xyzzy
+
+Second, you need to figure out what should happen for the x32 ABI version of
+the new system call.  There's a choice here: the layout of the arguments
+should either match the 64-bit version or the 32-bit version.
+
+If there's a pointer-to-a-pointer involved, the decision is easy: x32 is
+ILP32, so the layout should match the 32-bit version, and the entry in
+``arch/x86/entry/syscalls/syscall_64.tbl`` is split so that x32 programs hit
+the compatibility wrapper::
+
+    333   64       xyzzy     sys_xyzzy
+    ...
+    555   x32      xyzzy     compat_sys_xyzzy
+
+If no pointers are involved, then it is preferable to re-use the 64-bit system
+call for the x32 ABI (and consequently the entry in
+arch/x86/entry/syscalls/syscall_64.tbl is unchanged).
+
+In either case, you should check that the types involved in your argument
+layout do indeed map exactly from x32 (-mx32) to either the 32-bit (-m32) or
+64-bit (-m64) equivalents.
+
+
+System Calls Returning Elsewhere
+--------------------------------
+
+For most system calls, once the system call is complete the user program
+continues exactly where it left off -- at the next instruction, with the
+stack the same and most of the registers the same as before the system call,
+and with the same virtual memory space.
+
+However, a few system calls do things differently.  They might return to a
+different location (``rt_sigreturn``) or change the memory space
+(``fork``/``vfork``/``clone``) or even architecture (``execve``/``execveat``)
+of the program.
+
+To allow for this, the kernel implementation of the system call may need to
+save and restore additional registers to the kernel stack, allowing complete
+control of where and how execution continues after the system call.
+
+This is arch-specific, but typically involves defining assembly entry points
+that save/restore additional registers and invoke the real system call entry
+point.
+
+For x86_64, this is implemented as a ``stub_xyzzy`` entry point in
+``arch/x86/entry/entry_64.S``, and the entry in the syscall table
+(``arch/x86/entry/syscalls/syscall_64.tbl``) is adjusted to match::
+
+    333   common   xyzzy     stub_xyzzy
+
+The equivalent for 32-bit programs running on a 64-bit kernel is normally
+called ``stub32_xyzzy`` and implemented in ``arch/x86/entry/entry_64_compat.S``,
+with the corresponding syscall table adjustment in
+``arch/x86/entry/syscalls/syscall_32.tbl``::
+
+    380   i386     xyzzy     sys_xyzzy    stub32_xyzzy
+
+If the system call needs a compatibility layer (as in the previous section)
+then the ``stub32_`` version needs to call on to the ``compat_sys_`` version
+of the system call rather than the native 64-bit version.  Also, if the x32 ABI
+implementation is not common with the x86_64 version, then its syscall
+table will also need to invoke a stub that calls on to the ``compat_sys_``
+version.
+
+For completeness, it's also nice to set up a mapping so that user-mode Linux
+still works -- its syscall table will reference stub_xyzzy, but the UML build
+doesn't include ``arch/x86/entry/entry_64.S`` implementation (because UML
+simulates registers etc).  Fixing this is as simple as adding a #define to
+``arch/x86/um/sys_call_table_64.c``::
+
+    #define stub_xyzzy sys_xyzzy
+
+
+Other Details
+-------------
+
+Most of the kernel treats system calls in a generic way, but there is the
+occasional exception that may need updating for your particular system call.
+
+The audit subsystem is one such special case; it includes (arch-specific)
+functions that classify some special types of system call -- specifically
+file open (``open``/``openat``), program execution (``execve``/``exeveat``) or
+socket multiplexor (``socketcall``) operations. If your new system call is
+analogous to one of these, then the audit system should be updated.
+
+More generally, if there is an existing system call that is analogous to your
+new system call, it's worth doing a kernel-wide grep for the existing system
+call to check there are no other special cases.
+
+
+Testing
+-------
+
+A new system call should obviously be tested; it is also useful to provide
+reviewers with a demonstration of how user space programs will use the system
+call.  A good way to combine these aims is to include a simple self-test
+program in a new directory under ``tools/testing/selftests/``.
+
+For a new system call, there will obviously be no libc wrapper function and so
+the test will need to invoke it using ``syscall()``; also, if the system call
+involves a new userspace-visible structure, the corresponding header will need
+to be installed to compile the test.
+
+Make sure the selftest runs successfully on all supported architectures.  For
+example, check that it works when compiled as an x86_64 (-m64), x86_32 (-m32)
+and x32 (-mx32) ABI program.
+
+For more extensive and thorough testing of new functionality, you should also
+consider adding tests to the Linux Test Project, or to the xfstests project
+for filesystem-related changes.
+
+ - https://linux-test-project.github.io/
+ - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git
+
+
+Man Page
+--------
+
+All new system calls should come with a complete man page, ideally using groff
+markup, but plain text will do.  If groff is used, it's helpful to include a
+pre-rendered ASCII version of the man page in the cover email for the
+patchset, for the convenience of reviewers.
+
+The man page should be cc'ed to linux-man@vger.kernel.org
+For more details, see https://www.kernel.org/doc/man-pages/patches.html
+
+References and Sources
+----------------------
+
+ - LWN article from Michael Kerrisk on use of flags argument in system calls:
+   https://lwn.net/Articles/585415/
+ - LWN article from Michael Kerrisk on how to handle unknown flags in a system
+   call: https://lwn.net/Articles/588444/
+ - LWN article from Jake Edge describing constraints on 64-bit system call
+   arguments: https://lwn.net/Articles/311630/
+ - Pair of LWN articles from David Drysdale that describe the system call
+   implementation paths in detail for v3.14:
+
+    - https://lwn.net/Articles/604287/
+    - https://lwn.net/Articles/604515/
+
+ - Architecture-specific requirements for system calls are discussed in the
+   :manpage:`syscall(2)` man-page:
+   http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
+ - Collated emails from Linus Torvalds discussing the problems with ``ioctl()``:
+   http://yarchive.net/comp/linux/ioctl.html
+ - "How to not invent kernel interfaces", Arnd Bergmann,
+   http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
+ - LWN article from Michael Kerrisk on avoiding new uses of CAP_SYS_ADMIN:
+   https://lwn.net/Articles/486306/
+ - Recommendation from Andrew Morton that all related information for a new
+   system call should come in the same email thread:
+   https://lkml.org/lkml/2014/7/24/641
+ - Recommendation from Michael Kerrisk that a new system call should come with
+   a man page: https://lkml.org/lkml/2014/6/13/309
+ - Suggestion from Thomas Gleixner that x86 wire-up should be in a separate
+   commit: https://lkml.org/lkml/2014/11/19/254
+ - Suggestion from Greg Kroah-Hartman that it's good for new system calls to
+   come with a man-page & selftest: https://lkml.org/lkml/2014/3/19/710
+ - Discussion from Michael Kerrisk of new system call vs. :manpage:`prctl(2)` extension:
+   https://lkml.org/lkml/2014/6/3/411
+ - Suggestion from Ingo Molnar that system calls that involve multiple
+   arguments should encapsulate those arguments in a struct, which includes a
+   size field for future extensibility: https://lkml.org/lkml/2015/7/30/117
+ - Numbering oddities arising from (re-)use of O_* numbering space flags:
+
+    - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
+      check")
+    - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
+      conflict")
+    - commit bb458c644a59 ("Safer ABI for O_TMPFILE")
+
+ - Discussion from Matthew Wilcox about restrictions on 64-bit arguments:
+   https://lkml.org/lkml/2008/12/12/187
+ - Recommendation from Greg Kroah-Hartman that unknown flags should be
+   policed: https://lkml.org/lkml/2014/7/17/577
+ - Recommendation from Linus Torvalds that x32 system calls should prefer
+   compatibility with 64-bit versions rather than 32-bit versions:
+   https://lkml.org/lkml/2011/8/31/244
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/applying-patches.rst linux-libre-4.10-rc8-gnu/Documentation/process/applying-patches.rst
--- linux-libre-4.9-gnu/Documentation/process/applying-patches.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/applying-patches.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,468 @@
+.. _applying_patches:
+
+Applying Patches To The Linux Kernel
+++++++++++++++++++++++++++++++++++++
+
+Original by:
+	Jesper Juhl, August 2005
+
+Last update:
+	2016-09-14
+
+.. note::
+
+   This document is obsolete.  In most cases, rather than using ``patch``
+   manually, you'll almost certainly want to look at using Git instead.
+
+A frequently asked question on the Linux Kernel Mailing List is how to apply
+a patch to the kernel or, more specifically, what base kernel a patch for
+one of the many trees/branches should be applied to. Hopefully this document
+will explain this to you.
+
+In addition to explaining how to apply and revert patches, a brief
+description of the different kernel trees (and examples of how to apply
+their specific patches) is also provided.
+
+
+What is a patch?
+================
+
+A patch is a small text document containing a delta of changes between two
+different versions of a source tree. Patches are created with the ``diff``
+program.
+
+To correctly apply a patch you need to know what base it was generated from
+and what new version the patch will change the source tree into. These
+should both be present in the patch file metadata or be possible to deduce
+from the filename.
+
+
+How do I apply or revert a patch?
+=================================
+
+You apply a patch with the ``patch`` program. The patch program reads a diff
+(or patch) file and makes the changes to the source tree described in it.
+
+Patches for the Linux kernel are generated relative to the parent directory
+holding the kernel source dir.
+
+This means that paths to files inside the patch file contain the name of the
+kernel source directories it was generated against (or some other directory
+names like "a/" and "b/").
+
+Since this is unlikely to match the name of the kernel source dir on your
+local machine (but is often useful info to see what version an otherwise
+unlabeled patch was generated against) you should change into your kernel
+source directory and then strip the first element of the path from filenames
+in the patch file when applying it (the ``-p1`` argument to ``patch`` does
+this).
+
+To revert a previously applied patch, use the -R argument to patch.
+So, if you applied a patch like this::
+
+	patch -p1 < ../patch-x.y.z
+
+You can revert (undo) it like this::
+
+	patch -R -p1 < ../patch-x.y.z
+
+
+How do I feed a patch/diff file to ``patch``?
+=============================================
+
+This (as usual with Linux and other UNIX like operating systems) can be
+done in several different ways.
+
+In all the examples below I feed the file (in uncompressed form) to patch
+via stdin using the following syntax::
+
+	patch -p1 < path/to/patch-x.y.z
+
+If you just want to be able to follow the examples below and don't want to
+know of more than one way to use patch, then you can stop reading this
+section here.
+
+Patch can also get the name of the file to use via the -i argument, like
+this::
+
+	patch -p1 -i path/to/patch-x.y.z
+
+If your patch file is compressed with gzip or xz and you don't want to
+uncompress it before applying it, then you can feed it to patch like this
+instead::
+
+	xzcat path/to/patch-x.y.z.xz | patch -p1
+	bzcat path/to/patch-x.y.z.gz | patch -p1
+
+If you wish to uncompress the patch file by hand first before applying it
+(what I assume you've done in the examples below), then you simply run
+gunzip or xz on the file -- like this::
+
+	gunzip patch-x.y.z.gz
+	xz -d patch-x.y.z.xz
+
+Which will leave you with a plain text patch-x.y.z file that you can feed to
+patch via stdin or the ``-i`` argument, as you prefer.
+
+A few other nice arguments for patch are ``-s`` which causes patch to be silent
+except for errors which is nice to prevent errors from scrolling out of the
+screen too fast, and ``--dry-run`` which causes patch to just print a listing of
+what would happen, but doesn't actually make any changes. Finally ``--verbose``
+tells patch to print more information about the work being done.
+
+
+Common errors when patching
+===========================
+
+When patch applies a patch file it attempts to verify the sanity of the
+file in different ways.
+
+Checking that the file looks like a valid patch file and checking the code
+around the bits being modified matches the context provided in the patch are
+just two of the basic sanity checks patch does.
+
+If patch encounters something that doesn't look quite right it has two
+options. It can either refuse to apply the changes and abort or it can try
+to find a way to make the patch apply with a few minor changes.
+
+One example of something that's not 'quite right' that patch will attempt to
+fix up is if all the context matches, the lines being changed match, but the
+line numbers are different. This can happen, for example, if the patch makes
+a change in the middle of the file but for some reasons a few lines have
+been added or removed near the beginning of the file. In that case
+everything looks good it has just moved up or down a bit, and patch will
+usually adjust the line numbers and apply the patch.
+
+Whenever patch applies a patch that it had to modify a bit to make it fit
+it'll tell you about it by saying the patch applied with **fuzz**.
+You should be wary of such changes since even though patch probably got it
+right it doesn't /always/ get it right, and the result will sometimes be
+wrong.
+
+When patch encounters a change that it can't fix up with fuzz it rejects it
+outright and leaves a file with a ``.rej`` extension (a reject file). You can
+read this file to see exactly what change couldn't be applied, so you can
+go fix it up by hand if you wish.
+
+If you don't have any third-party patches applied to your kernel source, but
+only patches from kernel.org and you apply the patches in the correct order,
+and have made no modifications yourself to the source files, then you should
+never see a fuzz or reject message from patch. If you do see such messages
+anyway, then there's a high risk that either your local source tree or the
+patch file is corrupted in some way. In that case you should probably try
+re-downloading the patch and if things are still not OK then you'd be advised
+to start with a fresh tree downloaded in full from kernel.org.
+
+Let's look a bit more at some of the messages patch can produce.
+
+If patch stops and presents a ``File to patch:`` prompt, then patch could not
+find a file to be patched. Most likely you forgot to specify -p1 or you are
+in the wrong directory. Less often, you'll find patches that need to be
+applied with ``-p0`` instead of ``-p1`` (reading the patch file should reveal if
+this is the case -- if so, then this is an error by the person who created
+the patch but is not fatal).
+
+If you get ``Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines).`` or a
+message similar to that, then it means that patch had to adjust the location
+of the change (in this example it needed to move 7 lines from where it
+expected to make the change to make it fit).
+
+The resulting file may or may not be OK, depending on the reason the file
+was different than expected.
+
+This often happens if you try to apply a patch that was generated against a
+different kernel version than the one you are trying to patch.
+
+If you get a message like ``Hunk #3 FAILED at 2387.``, then it means that the
+patch could not be applied correctly and the patch program was unable to
+fuzz its way through. This will generate a ``.rej`` file with the change that
+caused the patch to fail and also a ``.orig`` file showing you the original
+content that couldn't be changed.
+
+If you get ``Reversed (or previously applied) patch detected!  Assume -R? [n]``
+then patch detected that the change contained in the patch seems to have
+already been made.
+
+If you actually did apply this patch previously and you just re-applied it
+in error, then just say [n]o and abort this patch. If you applied this patch
+previously and actually intended to revert it, but forgot to specify -R,
+then you can say [**y**]es here to make patch revert it for you.
+
+This can also happen if the creator of the patch reversed the source and
+destination directories when creating the patch, and in that case reverting
+the patch will in fact apply it.
+
+A message similar to ``patch: **** unexpected end of file in patch`` or
+``patch unexpectedly ends in middle of line`` means that patch could make no
+sense of the file you fed to it. Either your download is broken, you tried to
+feed patch a compressed patch file without uncompressing it first, or the patch
+file that you are using has been mangled by a mail client or mail transfer
+agent along the way somewhere, e.g., by splitting a long line into two lines.
+Often these warnings can easily be fixed by joining (concatenating) the
+two lines that had been split.
+
+As I already mentioned above, these errors should never happen if you apply
+a patch from kernel.org to the correct version of an unmodified source tree.
+So if you get these errors with kernel.org patches then you should probably
+assume that either your patch file or your tree is broken and I'd advise you
+to start over with a fresh download of a full kernel tree and the patch you
+wish to apply.
+
+
+Are there any alternatives to ``patch``?
+========================================
+
+
+Yes there are alternatives.
+
+You can use the ``interdiff`` program (http://cyberelk.net/tim/patchutils/) to
+generate a patch representing the differences between two patches and then
+apply the result.
+
+This will let you move from something like 4.7.2 to 4.7.3 in a single
+step. The -z flag to interdiff will even let you feed it patches in gzip or
+bzip2 compressed form directly without the use of zcat or bzcat or manual
+decompression.
+
+Here's how you'd go from 4.7.2 to 4.7.3 in a single step::
+
+	interdiff -z ../patch-4.7.2.gz ../patch-4.7.3.gz | patch -p1
+
+Although interdiff may save you a step or two you are generally advised to
+do the additional steps since interdiff can get things wrong in some cases.
+
+Another alternative is ``ketchup``, which is a python script for automatic
+downloading and applying of patches (http://www.selenic.com/ketchup/).
+
+Other nice tools are diffstat, which shows a summary of changes made by a
+patch; lsdiff, which displays a short listing of affected files in a patch
+file, along with (optionally) the line numbers of the start of each patch;
+and grepdiff, which displays a list of the files modified by a patch where
+the patch contains a given regular expression.
+
+
+Where can I download the patches?
+=================================
+
+The patches are available at http://kernel.org/
+Most recent patches are linked from the front page, but they also have
+specific homes.
+
+The 4.x.y (-stable) and 4.x patches live at
+
+	ftp://ftp.kernel.org/pub/linux/kernel/v4.x/
+
+The -rc patches live at
+
+	ftp://ftp.kernel.org/pub/linux/kernel/v4.x/testing/
+
+In place of ``ftp.kernel.org`` you can use ``ftp.cc.kernel.org``, where cc is a
+country code. This way you'll be downloading from a mirror site that's most
+likely geographically closer to you, resulting in faster downloads for you,
+less bandwidth used globally and less load on the main kernel.org servers --
+these are good things, so do use mirrors when possible.
+
+
+The 4.x kernels
+===============
+
+These are the base stable releases released by Linus. The highest numbered
+release is the most recent.
+
+If regressions or other serious flaws are found, then a -stable fix patch
+will be released (see below) on top of this base. Once a new 4.x base
+kernel is released, a patch is made available that is a delta between the
+previous 4.x kernel and the new one.
+
+To apply a patch moving from 4.6 to 4.7, you'd do the following (note
+that such patches do **NOT** apply on top of 4.x.y kernels but on top of the
+base 4.x kernel -- if you need to move from 4.x.y to 4.x+1 you need to
+first revert the 4.x.y patch).
+
+Here are some examples::
+
+	# moving from 4.6 to 4.7
+
+	$ cd ~/linux-4.6		# change to kernel source dir
+	$ patch -p1 < ../patch-4.7	# apply the 4.7 patch
+	$ cd ..
+	$ mv linux-4.6 linux-4.7	# rename source dir
+
+	# moving from 4.6.1 to 4.7
+
+	$ cd ~/linux-4.6.1		# change to kernel source dir
+	$ patch -p1 -R < ../patch-4.6.1	# revert the 4.6.1 patch
+					# source dir is now 4.6
+	$ patch -p1 < ../patch-4.7	# apply new 4.7 patch
+	$ cd ..
+	$ mv linux-4.6.1 linux-4.7	# rename source dir
+
+
+The 4.x.y kernels
+=================
+
+Kernels with 3-digit versions are -stable kernels. They contain small(ish)
+critical fixes for security problems or significant regressions discovered
+in a given 4.x kernel.
+
+This is the recommended branch for users who want the most recent stable
+kernel and are not interested in helping test development/experimental
+versions.
+
+If no 4.x.y kernel is available, then the highest numbered 4.x kernel is
+the current stable kernel.
+
+.. note::
+
+ The -stable team usually do make incremental patches available as well
+ as patches against the latest mainline release, but I only cover the
+ non-incremental ones below. The incremental ones can be found at
+ ftp://ftp.kernel.org/pub/linux/kernel/v4.x/incr/
+
+These patches are not incremental, meaning that for example the 4.7.3
+patch does not apply on top of the 4.7.2 kernel source, but rather on top
+of the base 4.7 kernel source.
+
+So, in order to apply the 4.7.3 patch to your existing 4.7.2 kernel
+source you have to first back out the 4.7.2 patch (so you are left with a
+base 4.7 kernel source) and then apply the new 4.7.3 patch.
+
+Here's a small example::
+
+	$ cd ~/linux-4.7.2		# change to the kernel source dir
+	$ patch -p1 -R < ../patch-4.7.2	# revert the 4.7.2 patch
+	$ patch -p1 < ../patch-4.7.3	# apply the new 4.7.3 patch
+	$ cd ..
+	$ mv linux-4.7.2 linux-4.7.3	# rename the kernel source dir
+
+The -rc kernels
+===============
+
+These are release-candidate kernels. These are development kernels released
+by Linus whenever he deems the current git (the kernel's source management
+tool) tree to be in a reasonably sane state adequate for testing.
+
+These kernels are not stable and you should expect occasional breakage if
+you intend to run them. This is however the most stable of the main
+development branches and is also what will eventually turn into the next
+stable kernel, so it is important that it be tested by as many people as
+possible.
+
+This is a good branch to run for people who want to help out testing
+development kernels but do not want to run some of the really experimental
+stuff (such people should see the sections about -git and -mm kernels below).
+
+The -rc patches are not incremental, they apply to a base 4.x kernel, just
+like the 4.x.y patches described above. The kernel version before the -rcN
+suffix denotes the version of the kernel that this -rc kernel will eventually
+turn into.
+
+So, 4.8-rc5 means that this is the fifth release candidate for the 4.8
+kernel and the patch should be applied on top of the 4.7 kernel source.
+
+Here are 3 examples of how to apply these patches::
+
+	# first an example of moving from 4.7 to 4.8-rc3
+
+	$ cd ~/linux-4.7			# change to the 4.7 source dir
+	$ patch -p1 < ../patch-4.8-rc3		# apply the 4.8-rc3 patch
+	$ cd ..
+	$ mv linux-4.7 linux-4.8-rc3		# rename the source dir
+
+	# now let's move from 4.8-rc3 to 4.8-rc5
+
+	$ cd ~/linux-4.8-rc3			# change to the 4.8-rc3 dir
+	$ patch -p1 -R < ../patch-4.8-rc3	# revert the 4.8-rc3 patch
+	$ patch -p1 < ../patch-4.8-rc5		# apply the new 4.8-rc5 patch
+	$ cd ..
+	$ mv linux-4.8-rc3 linux-4.8-rc5	# rename the source dir
+
+	# finally let's try and move from 4.7.3 to 4.8-rc5
+
+	$ cd ~/linux-4.7.3			# change to the kernel source dir
+	$ patch -p1 -R < ../patch-4.7.3		# revert the 4.7.3 patch
+	$ patch -p1 < ../patch-4.8-rc5		# apply new 4.8-rc5 patch
+	$ cd ..
+	$ mv linux-4.7.3 linux-4.8-rc5		# rename the kernel source dir
+
+
+The -git kernels
+================
+
+These are daily snapshots of Linus' kernel tree (managed in a git
+repository, hence the name).
+
+These patches are usually released daily and represent the current state of
+Linus's tree. They are more experimental than -rc kernels since they are
+generated automatically without even a cursory glance to see if they are
+sane.
+
+-git patches are not incremental and apply either to a base 4.x kernel or
+a base 4.x-rc kernel -- you can see which from their name.
+A patch named 4.7-git1 applies to the 4.7 kernel source and a patch
+named 4.8-rc3-git2 applies to the source of the 4.8-rc3 kernel.
+
+Here are some examples of how to apply these patches::
+
+	# moving from 4.7 to 4.7-git1
+
+	$ cd ~/linux-4.7			# change to the kernel source dir
+	$ patch -p1 < ../patch-4.7-git1		# apply the 4.7-git1 patch
+	$ cd ..
+	$ mv linux-4.7 linux-4.7-git1		# rename the kernel source dir
+
+	# moving from 4.7-git1 to 4.8-rc2-git3
+
+	$ cd ~/linux-4.7-git1			# change to the kernel source dir
+	$ patch -p1 -R < ../patch-4.7-git1	# revert the 4.7-git1 patch
+						# we now have a 4.7 kernel
+	$ patch -p1 < ../patch-4.8-rc2		# apply the 4.8-rc2 patch
+						# the kernel is now 4.8-rc2
+	$ patch -p1 < ../patch-4.8-rc2-git3	# apply the 4.8-rc2-git3 patch
+						# the kernel is now 4.8-rc2-git3
+	$ cd ..
+	$ mv linux-4.7-git1 linux-4.8-rc2-git3	# rename source dir
+
+
+The -mm patches and the linux-next tree
+=======================================
+
+The -mm patches are experimental patches released by Andrew Morton.
+
+In the past, -mm tree were used to also test subsystem patches, but this
+function is now done via the
+`linux-next <https://www.kernel.org/doc/man-pages/linux-next.html>`
+tree. The Subsystem maintainers push their patches first to linux-next,
+and, during the merge window, sends them directly to Linus.
+
+The -mm patches serve as a sort of proving ground for new features and other
+experimental patches that aren't merged via a subsystem tree.
+Once such patches has proved its worth in -mm for a while Andrew pushes
+it on to Linus for inclusion in mainline.
+
+The linux-next tree is daily updated, and includes the -mm patches.
+Both are in constant flux and contains many experimental features, a
+lot of debugging patches not appropriate for mainline etc., and is the most
+experimental of the branches described in this document.
+
+These patches are not appropriate for use on systems that are supposed to be
+stable and they are more risky to run than any of the other branches (make
+sure you have up-to-date backups -- that goes for any experimental kernel but
+even more so for -mm patches or using a Kernel from the linux-next tree).
+
+Testing of -mm patches and linux-next is greatly appreciated since the whole
+point of those are to weed out regressions, crashes, data corruption bugs,
+build breakage (and any other bug in general) before changes are merged into
+the more stable mainline Linus tree.
+
+But testers of -mm and linux-next should be aware that breakages are
+more common than in any other tree.
+
+
+This concludes this list of explanations of the various kernel trees.
+I hope you are now clear on how to apply the various patches and help testing
+the kernel.
+
+Thank you's to Randy Dunlap, Rolf Eike Beer, Linus Torvalds, Bodo Eggert,
+Johannes Stezenbach, Grant Coady, Pavel Machek and others that I may have
+forgotten for their reviews and contributions to this document.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/changes.rst linux-libre-4.10-rc8-gnu/Documentation/process/changes.rst
--- linux-libre-4.9-gnu/Documentation/process/changes.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/changes.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,485 @@
+.. _changes:
+
+Minimal requirements to compile the Kernel
+++++++++++++++++++++++++++++++++++++++++++
+
+Intro
+=====
+
+This document is designed to provide a list of the minimum levels of
+software necessary to run the 4.x kernels.
+
+This document is originally based on my "Changes" file for 2.0.x kernels
+and therefore owes credit to the same people as that file (Jared Mauch,
+Axel Boldt, Alessandro Sigala, and countless other users all over the
+'net).
+
+Current Minimal Requirements
+****************************
+
+Upgrade to at **least** these software revisions before thinking you've
+encountered a bug!  If you're unsure what version you're currently
+running, the suggested command should tell you.
+
+Again, keep in mind that this list assumes you are already functionally
+running a Linux kernel.  Also, not all tools are necessary on all
+systems; obviously, if you don't have any ISDN hardware, for example,
+you probably needn't concern yourself with isdn4k-utils.
+
+====================== ===============  ========================================
+        Program        Minimal version       Command to check the version
+====================== ===============  ========================================
+GNU C                  3.2              gcc --version
+GNU make               3.80             make --version
+binutils               2.12             ld -v
+util-linux             2.10o            fdformat --version
+module-init-tools      0.9.10           depmod -V
+e2fsprogs              1.41.4           e2fsck -V
+jfsutils               1.1.3            fsck.jfs -V
+reiserfsprogs          3.6.3            reiserfsck -V
+xfsprogs               2.6.0            xfs_db -V
+squashfs-tools         4.0              mksquashfs -version
+btrfs-progs            0.18             btrfsck
+pcmciautils            004              pccardctl -V
+quota-tools            3.09             quota -V
+PPP                    2.4.0            pppd --version
+isdn4k-utils           3.1pre1          isdnctrl 2>&1|grep version
+nfs-utils              1.0.5            showmount --version
+procps                 3.2.0            ps --version
+oprofile               0.9              oprofiled --version
+udev                   081              udevd --version
+grub                   0.93             grub --version || grub-install --version
+mcelog                 0.6              mcelog --version
+iptables               1.4.2            iptables -V
+openssl & libcrypto    1.0.0            openssl version
+bc                     1.06.95          bc --version
+Sphinx\ [#f1]_	       1.2		sphinx-build --version
+====================== ===============  ========================================
+
+.. [#f1] Sphinx is needed only to build the Kernel documentation
+
+Kernel compilation
+******************
+
+GCC
+---
+
+The gcc version requirements may vary depending on the type of CPU in your
+computer.
+
+Make
+----
+
+You will need GNU make 3.80 or later to build the kernel.
+
+Binutils
+--------
+
+Linux on IA-32 has recently switched from using ``as86`` to using ``gas`` for
+assembling the 16-bit boot code, removing the need for ``as86`` to compile
+your kernel.  This change does, however, mean that you need a recent
+release of binutils.
+
+Perl
+----
+
+You will need perl 5 and the following modules: ``Getopt::Long``,
+``Getopt::Std``, ``File::Basename``, and ``File::Find`` to build the kernel.
+
+BC
+--
+
+You will need bc to build kernels 3.10 and higher
+
+
+OpenSSL
+-------
+
+Module signing and external certificate handling use the OpenSSL program and
+crypto library to do key creation and signature generation.
+
+You will need openssl to build kernels 3.7 and higher if module signing is
+enabled.  You will also need openssl development packages to build kernels 4.3
+and higher.
+
+
+System utilities
+****************
+
+Architectural changes
+---------------------
+
+DevFS has been obsoleted in favour of udev
+(http://www.kernel.org/pub/linux/utils/kernel/hotplug/)
+
+32-bit UID support is now in place.  Have fun!
+
+Linux documentation for functions is transitioning to inline
+documentation via specially-formatted comments near their
+definitions in the source.  These comments can be combined with the
+SGML templates in the Documentation/DocBook directory to make DocBook
+files, which can then be converted by DocBook stylesheets to PostScript,
+HTML, PDF files, and several other formats.  In order to convert from
+DocBook format to a format of your choice, you'll need to install Jade as
+well as the desired DocBook stylesheets.
+
+Util-linux
+----------
+
+New versions of util-linux provide ``fdisk`` support for larger disks,
+support new options to mount, recognize more supported partition
+types, have a fdformat which works with 2.4 kernels, and similar goodies.
+You'll probably want to upgrade.
+
+Ksymoops
+--------
+
+If the unthinkable happens and your kernel oopses, you may need the
+ksymoops tool to decode it, but in most cases you don't.
+It is generally preferred to build the kernel with ``CONFIG_KALLSYMS`` so
+that it produces readable dumps that can be used as-is (this also
+produces better output than ksymoops).  If for some reason your kernel
+is not build with ``CONFIG_KALLSYMS`` and you have no way to rebuild and
+reproduce the Oops with that option, then you can still decode that Oops
+with ksymoops.
+
+Module-Init-Tools
+-----------------
+
+A new module loader is now in the kernel that requires ``module-init-tools``
+to use.  It is backward compatible with the 2.4.x series kernels.
+
+Mkinitrd
+--------
+
+These changes to the ``/lib/modules`` file tree layout also require that
+mkinitrd be upgraded.
+
+E2fsprogs
+---------
+
+The latest version of ``e2fsprogs`` fixes several bugs in fsck and
+debugfs.  Obviously, it's a good idea to upgrade.
+
+JFSutils
+--------
+
+The ``jfsutils`` package contains the utilities for the file system.
+The following utilities are available:
+
+- ``fsck.jfs`` - initiate replay of the transaction log, and check
+  and repair a JFS formatted partition.
+
+- ``mkfs.jfs`` - create a JFS formatted partition.
+
+- other file system utilities are also available in this package.
+
+Reiserfsprogs
+-------------
+
+The reiserfsprogs package should be used for reiserfs-3.6.x
+(Linux kernels 2.4.x). It is a combined package and contains working
+versions of ``mkreiserfs``, ``resize_reiserfs``, ``debugreiserfs`` and
+``reiserfsck``. These utils work on both i386 and alpha platforms.
+
+Xfsprogs
+--------
+
+The latest version of ``xfsprogs`` contains ``mkfs.xfs``, ``xfs_db``, and the
+``xfs_repair`` utilities, among others, for the XFS filesystem.  It is
+architecture independent and any version from 2.0.0 onward should
+work correctly with this version of the XFS kernel code (2.6.0 or
+later is recommended, due to some significant improvements).
+
+PCMCIAutils
+-----------
+
+PCMCIAutils replaces ``pcmcia-cs``. It properly sets up
+PCMCIA sockets at system startup and loads the appropriate modules
+for 16-bit PCMCIA devices if the kernel is modularized and the hotplug
+subsystem is used.
+
+Quota-tools
+-----------
+
+Support for 32 bit uid's and gid's is required if you want to use
+the newer version 2 quota format.  Quota-tools version 3.07 and
+newer has this support.  Use the recommended version or newer
+from the table above.
+
+Intel IA32 microcode
+--------------------
+
+A driver has been added to allow updating of Intel IA32 microcode,
+accessible as a normal (misc) character device.  If you are not using
+udev you may need to::
+
+  mkdir /dev/cpu
+  mknod /dev/cpu/microcode c 10 184
+  chmod 0644 /dev/cpu/microcode
+
+as root before you can use this.  You'll probably also want to
+get the user-space microcode_ctl utility to use with this.
+
+udev
+----
+
+``udev`` is a userspace application for populating ``/dev`` dynamically with
+only entries for devices actually present. ``udev`` replaces the basic
+functionality of devfs, while allowing persistent device naming for
+devices.
+
+FUSE
+----
+
+Needs libfuse 2.4.0 or later.  Absolute minimum is 2.3.0 but mount
+options ``direct_io`` and ``kernel_cache`` won't work.
+
+Networking
+**********
+
+General changes
+---------------
+
+If you have advanced network configuration needs, you should probably
+consider using the network tools from ip-route2.
+
+Packet Filter / NAT
+-------------------
+The packet filtering and NAT code uses the same tools like the previous 2.4.x
+kernel series (iptables).  It still includes backwards-compatibility modules
+for 2.2.x-style ipchains and 2.0.x-style ipfwadm.
+
+PPP
+---
+
+The PPP driver has been restructured to support multilink and to
+enable it to operate over diverse media layers.  If you use PPP,
+upgrade pppd to at least 2.4.0.
+
+If you are not using udev, you must have the device file /dev/ppp
+which can be made by::
+
+  mknod /dev/ppp c 108 0
+
+as root.
+
+Isdn4k-utils
+------------
+
+Due to changes in the length of the phone number field, isdn4k-utils
+needs to be recompiled or (preferably) upgraded.
+
+NFS-utils
+---------
+
+In ancient (2.4 and earlier) kernels, the nfs server needed to know
+about any client that expected to be able to access files via NFS.  This
+information would be given to the kernel by ``mountd`` when the client
+mounted the filesystem, or by ``exportfs`` at system startup.  exportfs
+would take information about active clients from ``/var/lib/nfs/rmtab``.
+
+This approach is quite fragile as it depends on rmtab being correct
+which is not always easy, particularly when trying to implement
+fail-over.  Even when the system is working well, ``rmtab`` suffers from
+getting lots of old entries that never get removed.
+
+With modern kernels we have the option of having the kernel tell mountd
+when it gets a request from an unknown host, and mountd can give
+appropriate export information to the kernel.  This removes the
+dependency on ``rmtab`` and means that the kernel only needs to know about
+currently active clients.
+
+To enable this new functionality, you need to::
+
+  mount -t nfsd nfsd /proc/fs/nfsd
+
+before running exportfs or mountd.  It is recommended that all NFS
+services be protected from the internet-at-large by a firewall where
+that is possible.
+
+mcelog
+------
+
+On x86 kernels the mcelog utility is needed to process and log machine check
+events when ``CONFIG_X86_MCE`` is enabled. Machine check events are errors
+reported by the CPU. Processing them is strongly encouraged.
+
+Kernel documentation
+********************
+
+Sphinx
+------
+
+The ReST markups currently used by the Documentation/ files are meant to be
+built with ``Sphinx`` version 1.2 or upper. If you're desiring to build
+PDF outputs, it is recommended to use version 1.4.6.
+
+.. note::
+
+  Please notice that, for PDF and LaTeX output, you'll also need ``XeLaTeX``
+  version 3.14159265. Depending on the distribution, you may also need
+  to install a series of ``texlive`` packages that provide the minimal
+  set of functionalities required for ``XeLaTex`` to work.
+
+Other tools
+-----------
+
+In order to produce documentation from DocBook, you'll also need ``xmlto``.
+Please notice, however, that we're currently migrating all documents to use
+``Sphinx``.
+
+Getting updated software
+========================
+
+Kernel compilation
+******************
+
+gcc
+---
+
+- <ftp://ftp.gnu.org/gnu/gcc/>
+
+Make
+----
+
+- <ftp://ftp.gnu.org/gnu/make/>
+
+Binutils
+--------
+
+- <ftp://ftp.kernel.org/pub/linux/devel/binutils/>
+
+OpenSSL
+-------
+
+- <https://www.openssl.org/>
+
+System utilities
+****************
+
+Util-linux
+----------
+
+- <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>
+
+Ksymoops
+--------
+
+- <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
+
+Module-Init-Tools
+-----------------
+
+- <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
+
+Mkinitrd
+--------
+
+- <https://code.launchpad.net/initrd-tools/main>
+
+E2fsprogs
+---------
+
+- <http://prdownloads.sourceforge.net/e2fsprogs/e2fsprogs-1.29.tar.gz>
+
+JFSutils
+--------
+
+- <http://jfs.sourceforge.net/>
+
+Reiserfsprogs
+-------------
+
+- <http://www.kernel.org/pub/linux/utils/fs/reiserfs/>
+
+Xfsprogs
+--------
+
+- <ftp://oss.sgi.com/projects/xfs/>
+
+Pcmciautils
+-----------
+
+- <ftp://ftp.kernel.org/pub/linux/utils/kernel/pcmcia/>
+
+Quota-tools
+-----------
+
+- <http://sourceforge.net/projects/linuxquota/>
+
+DocBook Stylesheets
+-------------------
+
+- <http://sourceforge.net/projects/docbook/files/docbook-dsssl/>
+
+XMLTO XSLT Frontend
+-------------------
+
+- <http://cyberelk.net/tim/xmlto/>
+
+Intel P6 microcode
+------------------
+
+- <https://downloadcenter.intel.com/>
+
+udev
+----
+
+- <http://www.freedesktop.org/software/systemd/man/udev.html>
+
+FUSE
+----
+
+- <http://sourceforge.net/projects/fuse>
+
+mcelog
+------
+
+- <http://www.mcelog.org/>
+
+Networking
+**********
+
+PPP
+---
+
+- <ftp://ftp.samba.org/pub/ppp/>
+
+Isdn4k-utils
+------------
+
+- <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/>
+
+NFS-utils
+---------
+
+- <http://sourceforge.net/project/showfiles.php?group_id=14>
+
+Iptables
+--------
+
+- <http://www.iptables.org/downloads.html>
+
+Ip-route2
+---------
+
+- <https://www.kernel.org/pub/linux/utils/net/iproute2/>
+
+OProfile
+--------
+
+- <http://oprofile.sf.net/download/>
+
+NFS-Utils
+---------
+
+- <http://nfs.sourceforge.net/>
+
+Kernel documentation
+********************
+
+Sphinx
+------
+
+- <http://www.sphinx-doc.org/>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/code-of-conflict.rst linux-libre-4.10-rc8-gnu/Documentation/process/code-of-conflict.rst
--- linux-libre-4.9-gnu/Documentation/process/code-of-conflict.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/code-of-conflict.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,28 @@
+Code of Conflict
+----------------
+
+The Linux kernel development effort is a very personal process compared
+to "traditional" ways of developing software.  Your code and ideas
+behind it will be carefully reviewed, often resulting in critique and
+criticism.  The review will almost always require improvements to the
+code before it can be included in the kernel.  Know that this happens
+because everyone involved wants to see the best possible solution for
+the overall success of Linux.  This development process has been proven
+to create the most robust operating system kernel ever, and we do not
+want to do anything to cause the quality of submission and eventual
+result to ever decrease.
+
+If however, anyone feels personally abused, threatened, or otherwise
+uncomfortable due to this process, that is not acceptable.  If so,
+please contact the Linux Foundation's Technical Advisory Board at
+<tab@lists.linux-foundation.org>, or the individual members, and they
+will work to resolve the issue to the best of their ability.  For more
+information on who is on the Technical Advisory Board and what their
+role is, please see:
+
+	- http://www.linuxfoundation.org/projects/linux/tab
+
+As a reviewer of code, please strive to keep things civil and focused on
+the technical issues involved.  We are all humans, and frustrations can
+be high on both sides of the process.  Try to keep in mind the immortal
+words of Bill and Ted, "Be excellent to each other."
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/coding-style.rst linux-libre-4.10-rc8-gnu/Documentation/process/coding-style.rst
--- linux-libre-4.9-gnu/Documentation/process/coding-style.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/coding-style.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1062 @@
+.. _codingstyle:
+
+Linux kernel coding style
+=========================
+
+This is a short document describing the preferred coding style for the
+linux kernel.  Coding style is very personal, and I won't **force** my
+views on anybody, but this is what goes for anything that I have to be
+able to maintain, and I'd prefer it for most other things too.  Please
+at least consider the points made here.
+
+First off, I'd suggest printing out a copy of the GNU coding standards,
+and NOT read it.  Burn them, it's a great symbolic gesture.
+
+Anyway, here goes:
+
+
+1) Indentation
+--------------
+
+Tabs are 8 characters, and thus indentations are also 8 characters.
+There are heretic movements that try to make indentations 4 (or even 2!)
+characters deep, and that is akin to trying to define the value of PI to
+be 3.
+
+Rationale: The whole idea behind indentation is to clearly define where
+a block of control starts and ends.  Especially when you've been looking
+at your screen for 20 straight hours, you'll find it a lot easier to see
+how the indentation works if you have large indentations.
+
+Now, some people will claim that having 8-character indentations makes
+the code move too far to the right, and makes it hard to read on a
+80-character terminal screen.  The answer to that is that if you need
+more than 3 levels of indentation, you're screwed anyway, and should fix
+your program.
+
+In short, 8-char indents make things easier to read, and have the added
+benefit of warning you when you're nesting your functions too deep.
+Heed that warning.
+
+The preferred way to ease multiple indentation levels in a switch statement is
+to align the ``switch`` and its subordinate ``case`` labels in the same column
+instead of ``double-indenting`` the ``case`` labels.  E.g.:
+
+.. code-block:: c
+
+	switch (suffix) {
+	case 'G':
+	case 'g':
+		mem <<= 30;
+		break;
+	case 'M':
+	case 'm':
+		mem <<= 20;
+		break;
+	case 'K':
+	case 'k':
+		mem <<= 10;
+		/* fall through */
+	default:
+		break;
+	}
+
+Don't put multiple statements on a single line unless you have
+something to hide:
+
+.. code-block:: c
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+Don't put multiple assignments on a single line either.  Kernel coding style
+is super simple.  Avoid tricky expressions.
+
+Outside of comments, documentation and except in Kconfig, spaces are never
+used for indentation, and the above example is deliberately broken.
+
+Get a decent editor and don't leave whitespace at the end of lines.
+
+
+2) Breaking long lines and strings
+----------------------------------
+
+Coding style is all about readability and maintainability using commonly
+available tools.
+
+The limit on the length of lines is 80 columns and this is a strongly
+preferred limit.
+
+Statements longer than 80 columns will be broken into sensible chunks, unless
+exceeding 80 columns significantly increases readability and does not hide
+information. Descendants are always substantially shorter than the parent and
+are placed substantially to the right. The same applies to function headers
+with a long argument list. However, never break user-visible strings such as
+printk messages, because that breaks the ability to grep for them.
+
+
+3) Placing Braces and Spaces
+----------------------------
+
+The other issue that always comes up in C styling is the placement of
+braces.  Unlike the indent size, there are few technical reasons to
+choose one placement strategy over the other, but the preferred way, as
+shown to us by the prophets Kernighan and Ritchie, is to put the opening
+brace last on the line, and put the closing brace first, thusly:
+
+.. code-block:: c
+
+	if (x is true) {
+		we do y
+	}
+
+This applies to all non-function statement blocks (if, switch, for,
+while, do).  E.g.:
+
+.. code-block:: c
+
+	switch (action) {
+	case KOBJ_ADD:
+		return "add";
+	case KOBJ_REMOVE:
+		return "remove";
+	case KOBJ_CHANGE:
+		return "change";
+	default:
+		return NULL;
+	}
+
+However, there is one special case, namely functions: they have the
+opening brace at the beginning of the next line, thus:
+
+.. code-block:: c
+
+	int function(int x)
+	{
+		body of function
+	}
+
+Heretic people all over the world have claimed that this inconsistency
+is ...  well ...  inconsistent, but all right-thinking people know that
+(a) K&R are **right** and (b) K&R are right.  Besides, functions are
+special anyway (you can't nest them in C).
+
+Note that the closing brace is empty on a line of its own, **except** in
+the cases where it is followed by a continuation of the same statement,
+ie a ``while`` in a do-statement or an ``else`` in an if-statement, like
+this:
+
+.. code-block:: c
+
+	do {
+		body of do-loop
+	} while (condition);
+
+and
+
+.. code-block:: c
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+Rationale: K&R.
+
+Also, note that this brace-placement also minimizes the number of empty
+(or almost empty) lines, without any loss of readability.  Thus, as the
+supply of new-lines on your screen is not a renewable resource (think
+25-line terminal screens here), you have more empty lines to put
+comments on.
+
+Do not unnecessarily use braces where a single statement will do.
+
+.. code-block:: c
+
+	if (condition)
+		action();
+
+and
+
+.. code-block:: none
+
+	if (condition)
+		do_this();
+	else
+		do_that();
+
+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:
+
+.. code-block:: c
+
+	if (condition) {
+		do_this();
+		do_that();
+	} else {
+		otherwise();
+	}
+
+3.1) Spaces
+***********
+
+Linux kernel style for use of spaces depends (mostly) on
+function-versus-keyword usage.  Use a space after (most) keywords.  The
+notable exceptions are sizeof, typeof, alignof, and __attribute__, which look
+somewhat like functions (and are usually used with parentheses in Linux,
+although they are not required in the language, as in: ``sizeof info`` after
+``struct fileinfo info;`` is declared).
+
+So use a space after these keywords::
+
+	if, switch, case, for, do, while
+
+but not with sizeof, typeof, alignof, or __attribute__.  E.g.,
+
+.. code-block:: c
+
+
+	s = sizeof(struct file);
+
+Do not add spaces around (inside) parenthesized expressions.  This example is
+**bad**:
+
+.. code-block:: c
+
+
+	s = sizeof( struct file );
+
+When declaring pointer data or a function that returns a pointer type, the
+preferred use of ``*`` is adjacent to the data name or function name and not
+adjacent to the type name.  Examples:
+
+.. code-block:: c
+
+
+	char *linux_banner;
+	unsigned long long memparse(char *ptr, char **retptr);
+	char *match_strdup(substring_t *s);
+
+Use one space around (on each side of) most binary and ternary operators,
+such as any of these::
+
+	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+but no space after unary operators::
+
+	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+no space before the postfix increment & decrement unary operators::
+
+	++  --
+
+no space after the prefix increment & decrement unary operators::
+
+	++  --
+
+and no space around the ``.`` and ``->`` structure member operators.
+
+Do not leave trailing whitespace at the ends of lines.  Some editors with
+``smart`` indentation will insert whitespace at the beginning of new lines as
+appropriate, so you can start typing the next line of code right away.
+However, some such editors do not remove the whitespace if you end up not
+putting a line of code there, such as if you leave a blank line.  As a result,
+you end up with lines containing trailing whitespace.
+
+Git will warn you about patches that introduce trailing whitespace, and can
+optionally strip the trailing whitespace for you; however, if applying a series
+of patches, this may make later patches in the series fail by changing their
+context lines.
+
+
+4) Naming
+---------
+
+C is a Spartan language, and so should your naming be.  Unlike Modula-2
+and Pascal programmers, C programmers do not use cute names like
+ThisVariableIsATemporaryCounter.  A C programmer would call that
+variable ``tmp``, which is much easier to write, and not the least more
+difficult to understand.
+
+HOWEVER, while mixed-case names are frowned upon, descriptive names for
+global variables are a must.  To call a global function ``foo`` is a
+shooting offense.
+
+GLOBAL variables (to be used only if you **really** need them) need to
+have descriptive names, as do global functions.  If you have a function
+that counts the number of active users, you should call that
+``count_active_users()`` or similar, you should **not** call it ``cntusr()``.
+
+Encoding the type of a function into the name (so-called Hungarian
+notation) is brain damaged - the compiler knows the types anyway and can
+check those, and it only confuses the programmer.  No wonder MicroSoft
+makes buggy programs.
+
+LOCAL variable names should be short, and to the point.  If you have
+some random integer loop counter, it should probably be called ``i``.
+Calling it ``loop_counter`` is non-productive, if there is no chance of it
+being mis-understood.  Similarly, ``tmp`` can be just about any type of
+variable that is used to hold a temporary value.
+
+If you are afraid to mix up your local variable names, you have another
+problem, which is called the function-growth-hormone-imbalance syndrome.
+See chapter 6 (Functions).
+
+
+5) Typedefs
+-----------
+
+Please don't use things like ``vps_t``.
+It's a **mistake** to use typedef for structures and pointers. When you see a
+
+.. code-block:: c
+
+
+	vps_t a;
+
+in the source, what does it mean?
+In contrast, if it says
+
+.. code-block:: c
+
+	struct virtual_container *a;
+
+you can actually tell what ``a`` is.
+
+Lots of people think that typedefs ``help readability``. Not so. They are
+useful only for:
+
+ (a) totally opaque objects (where the typedef is actively used to **hide**
+     what the object is).
+
+     Example: ``pte_t`` etc. opaque objects that you can only access using
+     the proper accessor functions.
+
+     .. note::
+
+       Opaqueness and ``accessor functions`` are not good in themselves.
+       The reason we have them for things like pte_t etc. is that there
+       really is absolutely **zero** portably accessible information there.
+
+ (b) Clear integer types, where the abstraction **helps** avoid confusion
+     whether it is ``int`` or ``long``.
+
+     u8/u16/u32 are perfectly fine typedefs, although they fit into
+     category (d) better than here.
+
+     .. note::
+
+       Again - there needs to be a **reason** for this. If something is
+       ``unsigned long``, then there's no reason to do
+
+	typedef unsigned long myflags_t;
+
+     but if there is a clear reason for why it under certain circumstances
+     might be an ``unsigned int`` and under other configurations might be
+     ``unsigned long``, then by all means go ahead and use a typedef.
+
+ (c) when you use sparse to literally create a **new** type for
+     type-checking.
+
+ (d) New types which are identical to standard C99 types, in certain
+     exceptional circumstances.
+
+     Although it would only take a short amount of time for the eyes and
+     brain to become accustomed to the standard types like ``uint32_t``,
+     some people object to their use anyway.
+
+     Therefore, the Linux-specific ``u8/u16/u32/u64`` types and their
+     signed equivalents which are identical to standard types are
+     permitted -- although they are not mandatory in new code of your
+     own.
+
+     When editing existing code which already uses one or the other set
+     of types, you should conform to the existing choices in that code.
+
+ (e) Types safe for use in userspace.
+
+     In certain structures which are visible to userspace, we cannot
+     require C99 types and cannot use the ``u32`` form above. Thus, we
+     use __u32 and similar types in all structures which are shared
+     with userspace.
+
+Maybe there are other cases too, but the rule should basically be to NEVER
+EVER use a typedef unless you can clearly match one of those rules.
+
+In general, a pointer, or a struct that has elements that can reasonably
+be directly accessed should **never** be a typedef.
+
+
+6) Functions
+------------
+
+Functions should be short and sweet, and do just one thing.  They should
+fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
+as we all know), and do one thing and do that well.
+
+The maximum length of a function is inversely proportional to the
+complexity and indentation level of that function.  So, if you have a
+conceptually simple function that is just one long (but simple)
+case-statement, where you have to do lots of small things for a lot of
+different cases, it's OK to have a longer function.
+
+However, if you have a complex function, and you suspect that a
+less-than-gifted first-year high-school student might not even
+understand what the function is all about, you should adhere to the
+maximum limits all the more closely.  Use helper functions with
+descriptive names (you can ask the compiler to in-line them if you think
+it's performance-critical, and it will probably do a better job of it
+than you would have done).
+
+Another measure of the function is the number of local variables.  They
+shouldn't exceed 5-10, or you're doing something wrong.  Re-think the
+function, and split it into smaller pieces.  A human brain can
+generally easily keep track of about 7 different things, anything more
+and it gets confused.  You know you're brilliant, but maybe you'd like
+to understand what you did 2 weeks from now.
+
+In source files, separate functions with one blank line.  If the function is
+exported, the **EXPORT** macro for it should follow immediately after the
+closing function brace line.  E.g.:
+
+.. code-block:: c
+
+	int system_is_up(void)
+	{
+		return system_state == SYSTEM_RUNNING;
+	}
+	EXPORT_SYMBOL(system_is_up);
+
+In function prototypes, include parameter names with their data types.
+Although this is not required by the C language, it is preferred in Linux
+because it is a simple way to add valuable information for the reader.
+
+
+7) Centralized exiting of functions
+-----------------------------------
+
+Albeit deprecated by some people, the equivalent of the goto statement is
+used frequently by compilers in form of the unconditional jump instruction.
+
+The goto statement comes in handy when a function exits from multiple
+locations and some common work such as cleanup has to be done.  If there is no
+cleanup needed then just return directly.
+
+Choose label names which say what the goto does or why the goto exists.  An
+example of a good name could be ``out_free_buffer:`` if the goto frees ``buffer``.
+Avoid using GW-BASIC names like ``err1:`` and ``err2:``, as you would have to
+renumber them if you ever add or remove exit paths, and they make correctness
+difficult to verify anyway.
+
+The rationale for using gotos is:
+
+- unconditional statements are easier to understand and follow
+- nesting is reduced
+- errors by not updating individual exit points when making
+  modifications are prevented
+- saves the compiler work to optimize redundant code away ;)
+
+.. code-block:: c
+
+	int fun(int a)
+	{
+		int result = 0;
+		char *buffer;
+
+		buffer = kmalloc(SIZE, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+
+		if (condition1) {
+			while (loop1) {
+				...
+			}
+			result = 1;
+			goto out_free_buffer;
+		}
+		...
+	out_free_buffer:
+		kfree(buffer);
+		return result;
+	}
+
+A common type of bug to be aware of is ``one err bugs`` which look like this:
+
+.. code-block:: c
+
+	err:
+		kfree(foo->bar);
+		kfree(foo);
+		return ret;
+
+The bug in this code is that on some exit paths ``foo`` is NULL.  Normally the
+fix for this is to split it up into two error labels ``err_free_bar:`` and
+``err_free_foo:``:
+
+.. code-block:: c
+
+	 err_free_bar:
+		kfree(foo->bar);
+	 err_free_foo:
+		kfree(foo);
+		return ret;
+
+Ideally you should simulate errors to test all exit paths.
+
+
+8) Commenting
+-------------
+
+Comments are good, but there is also a danger of over-commenting.  NEVER
+try to explain HOW your code works in a comment: it's much better to
+write the code so that the **working** is obvious, and it's a waste of
+time to explain badly written code.
+
+Generally, you want your comments to tell WHAT your code does, not HOW.
+Also, try to avoid putting comments inside a function body: if the
+function is so complex that you need to separately comment parts of it,
+you should probably go back to chapter 6 for a while.  You can make
+small comments to note or warn about something particularly clever (or
+ugly), but try to avoid excess.  Instead, put the comments at the head
+of the function, telling people what it does, and possibly WHY it does
+it.
+
+When commenting the kernel API functions, please use the kernel-doc format.
+See the files at :ref:`Documentation/doc-guide/ <doc_guide>` and
+``scripts/kernel-doc`` for details.
+
+The preferred style for long (multi-line) comments is:
+
+.. code-block:: c
+
+	/*
+	 * This is the preferred style for multi-line
+	 * comments in the Linux kernel source code.
+	 * Please use it consistently.
+	 *
+	 * Description:  A column of asterisks on the left side,
+	 * with beginning and ending almost-blank lines.
+	 */
+
+For files in net/ and drivers/net/ the preferred style for long (multi-line)
+comments is a little different.
+
+.. code-block:: c
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
+It's also important to comment data, whether they are basic types or derived
+types.  To this end, use just one data declaration per line (no commas for
+multiple data declarations).  This leaves you room for a small comment on each
+item, explaining its use.
+
+
+9) You've made a mess of it
+---------------------------
+
+That's OK, we all do.  You've probably been told by your long-time Unix
+user helper that ``GNU emacs`` automatically formats the C sources for
+you, and you've noticed that yes, it does do that, but the defaults it
+uses are less than desirable (in fact, they are worse than random
+typing - an infinite number of monkeys typing into GNU emacs would never
+make a good program).
+
+So, you can either get rid of GNU emacs, or change it to use saner
+values.  To do the latter, you can stick the following in your .emacs file:
+
+.. code-block:: none
+
+  (defun c-lineup-arglist-tabs-only (ignored)
+    "Line up argument lists by tabs, not spaces"
+    (let* ((anchor (c-langelem-pos c-syntactic-element))
+           (column (c-langelem-2nd-pos c-syntactic-element))
+           (offset (- (1+ column) anchor))
+           (steps (floor offset c-basic-offset)))
+      (* (max steps 1)
+         c-basic-offset)))
+
+  (add-hook 'c-mode-common-hook
+            (lambda ()
+              ;; Add kernel style
+              (c-add-style
+               "linux-tabs-only"
+               '("linux" (c-offsets-alist
+                          (arglist-cont-nonempty
+                           c-lineup-gcc-asm-reg
+                           c-lineup-arglist-tabs-only))))))
+
+  (add-hook 'c-mode-hook
+            (lambda ()
+              (let ((filename (buffer-file-name)))
+                ;; Enable kernel mode for the appropriate files
+                (when (and filename
+                           (string-match (expand-file-name "~/src/linux-trees")
+                                         filename))
+                  (setq indent-tabs-mode t)
+                  (setq show-trailing-whitespace t)
+                  (c-set-style "linux-tabs-only")))))
+
+This will make emacs go better with the kernel coding style for C
+files below ``~/src/linux-trees``.
+
+But even if you fail in getting emacs to do sane formatting, not
+everything is lost: use ``indent``.
+
+Now, again, GNU indent has the same brain-dead settings that GNU emacs
+has, which is why you need to give it a few command line options.
+However, that's not too bad, because even the makers of GNU indent
+recognize the authority of K&R (the GNU people aren't evil, they are
+just severely misguided in this matter), so you just give indent the
+options ``-kr -i8`` (stands for ``K&R, 8 character indents``), or use
+``scripts/Lindent``, which indents in the latest style.
+
+``indent`` has a lot of options, and especially when it comes to comment
+re-formatting you may want to take a look at the man page.  But
+remember: ``indent`` is not a fix for bad programming.
+
+
+10) Kconfig configuration files
+-------------------------------
+
+For all of the Kconfig* configuration files throughout the source tree,
+the indentation is somewhat different.  Lines under a ``config`` definition
+are indented with one tab, while help text is indented an additional two
+spaces.  Example::
+
+  config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+Seriously dangerous features (such as write support for certain
+filesystems) should advertise this prominently in their prompt string::
+
+  config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+For full documentation on the configuration files, see the file
+Documentation/kbuild/kconfig-language.txt.
+
+
+11) Data structures
+-------------------
+
+Data structures that have visibility outside the single-threaded
+environment they are created and destroyed in should always have
+reference counts.  In the kernel, garbage collection doesn't exist (and
+outside the kernel garbage collection is slow and inefficient), which
+means that you absolutely **have** to reference count all your uses.
+
+Reference counting means that you can avoid locking, and allows multiple
+users to have access to the data structure in parallel - and not having
+to worry about the structure suddenly going away from under them just
+because they slept or did something else for a while.
+
+Note that locking is **not** a replacement for reference counting.
+Locking is used to keep data structures coherent, while reference
+counting is a memory management technique.  Usually both are needed, and
+they are not to be confused with each other.
+
+Many data structures can indeed have two levels of reference counting,
+when there are users of different ``classes``.  The subclass count counts
+the number of subclass users, and decrements the global count just once
+when the subclass count goes to zero.
+
+Examples of this kind of ``multi-level-reference-counting`` can be found in
+memory management (``struct mm_struct``: mm_users and mm_count), and in
+filesystem code (``struct super_block``: s_count and s_active).
+
+Remember: if another thread can find your data structure, and you don't
+have a reference count on it, you almost certainly have a bug.
+
+
+12) Macros, Enums and RTL
+-------------------------
+
+Names of macros defining constants and labels in enums are capitalized.
+
+.. code-block:: c
+
+	#define CONSTANT 0x12345
+
+Enums are preferred when defining several related constants.
+
+CAPITALIZED macro names are appreciated but macros resembling functions
+may be named in lower case.
+
+Generally, inline functions are preferable to macros resembling functions.
+
+Macros with multiple statements should be enclosed in a do - while block:
+
+.. code-block:: c
+
+	#define macrofun(a, b, c)			\
+		do {					\
+			if (a == 5)			\
+				do_this(b, c);		\
+		} while (0)
+
+Things to avoid when using macros:
+
+1) macros that affect control flow:
+
+.. code-block:: c
+
+	#define FOO(x)					\
+		do {					\
+			if (blah(x) < 0)		\
+				return -EBUGGERED;	\
+		} while (0)
+
+is a **very** bad idea.  It looks like a function call but exits the ``calling``
+function; don't break the internal parsers of those who will read the code.
+
+2) macros that depend on having a local variable with a magic name:
+
+.. code-block:: c
+
+	#define FOO(val) bar(index, val)
+
+might look like a good thing, but it's confusing as hell when one reads the
+code and it's prone to breakage from seemingly innocent changes.
+
+3) macros with arguments that are used as l-values: FOO(x) = y; will
+bite you if somebody e.g. turns FOO into an inline function.
+
+4) forgetting about precedence: macros defining constants using expressions
+must enclose the expression in parentheses. Beware of similar issues with
+macros using parameters.
+
+.. code-block:: c
+
+	#define CONSTANT 0x4000
+	#define CONSTEXP (CONSTANT | 3)
+
+5) namespace collisions when defining local variables in macros resembling
+functions:
+
+.. code-block:: c
+
+	#define FOO(x)				\
+	({					\
+		typeof(x) ret;			\
+		ret = calc_ret(x);		\
+		(ret);				\
+	})
+
+ret is a common name for a local variable - __foo_ret is less likely
+to collide with an existing variable.
+
+The cpp manual deals with macros exhaustively. The gcc internals manual also
+covers RTL which is used frequently with assembly language in the kernel.
+
+
+13) Printing kernel messages
+----------------------------
+
+Kernel developers like to be seen as literate. Do mind the spelling
+of kernel messages to make a good impression. Do not use crippled
+words like ``dont``; use ``do not`` or ``don't`` instead.  Make the messages
+concise, clear, and unambiguous.
+
+Kernel messages do not have to be terminated with a period.
+
+Printing numbers in parentheses (%d) adds no value and should be avoided.
+
+There are a number of driver model diagnostic macros in <linux/device.h>
+which you should use to make sure messages are matched to the right device
+and driver, and are tagged with the right level:  dev_err(), dev_warn(),
+dev_info(), and so forth.  For messages that aren't associated with a
+particular device, <linux/printk.h> defines pr_notice(), pr_info(),
+pr_warn(), pr_err(), etc.
+
+Coming up with good debugging messages can be quite a challenge; and once
+you have them, they can be a huge help for remote troubleshooting.  However
+debug message printing is handled differently than printing other non-debug
+messages.  While the other pr_XXX() functions print unconditionally,
+pr_debug() does not; it is compiled out by default, unless either DEBUG is
+defined or CONFIG_DYNAMIC_DEBUG is set.  That is true for dev_dbg() also,
+and a related convention uses VERBOSE_DEBUG to add dev_vdbg() messages to
+the ones already enabled by DEBUG.
+
+Many subsystems have Kconfig debug options to turn on -DDEBUG in the
+corresponding Makefile; in other cases specific files #define DEBUG.  And
+when a debug message should be unconditionally printed, such as if it is
+already inside a debug-related #ifdef section, printk(KERN_DEBUG ...) can be
+used.
+
+
+14) Allocating memory
+---------------------
+
+The kernel provides the following general purpose memory allocators:
+kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc(), and
+vzalloc().  Please refer to the API documentation for further information
+about them.
+
+The preferred form for passing a size of a struct is the following:
+
+.. code-block:: c
+
+	p = kmalloc(sizeof(*p), ...);
+
+The alternative form where struct name is spelled out hurts readability and
+introduces an opportunity for a bug when the pointer variable type is changed
+but the corresponding sizeof that is passed to a memory allocator is not.
+
+Casting the return value which is a void pointer is redundant. The conversion
+from void pointer to any other pointer type is guaranteed by the C programming
+language.
+
+The preferred form for allocating an array is the following:
+
+.. code-block:: c
+
+	p = kmalloc_array(n, sizeof(...), ...);
+
+The preferred form for allocating a zeroed array is the following:
+
+.. code-block:: c
+
+	p = kcalloc(n, sizeof(...), ...);
+
+Both forms check for overflow on the allocation size n * sizeof(...),
+and return NULL if that occurred.
+
+
+15) The inline disease
+----------------------
+
+There appears to be a common misperception that gcc has a magic "make me
+faster" speedup option called ``inline``. While the use of inlines can be
+appropriate (for example as a means of replacing macros, see Chapter 12), it
+very often is not. Abundant use of the inline keyword leads to a much bigger
+kernel, which in turn slows the system as a whole down, due to a bigger
+icache footprint for the CPU and simply because there is less memory
+available for the pagecache. Just think about it; a pagecache miss causes a
+disk seek, which easily takes 5 milliseconds. There are a LOT of cpu cycles
+that can go into these 5 milliseconds.
+
+A reasonable rule of thumb is to not put inline at functions that have more
+than 3 lines of code in them. An exception to this rule are the cases where
+a parameter is known to be a compiletime constant, and as a result of this
+constantness you *know* the compiler will be able to optimize most of your
+function away at compile time. For a good example of this later case, see
+the kmalloc() inline function.
+
+Often people argue that adding inline to functions that are static and used
+only once is always a win since there is no space tradeoff. While this is
+technically correct, gcc is capable of inlining these automatically without
+help, and the maintenance issue of removing the inline when a second user
+appears outweighs the potential value of the hint that tells gcc to do
+something it would have done anyway.
+
+
+16) Function return values and names
+------------------------------------
+
+Functions can return values of many different kinds, and one of the
+most common is a value indicating whether the function succeeded or
+failed.  Such a value can be represented as an error-code integer
+(-Exxx = failure, 0 = success) or a ``succeeded`` boolean (0 = failure,
+non-zero = success).
+
+Mixing up these two sorts of representations is a fertile source of
+difficult-to-find bugs.  If the C language included a strong distinction
+between integers and booleans then the compiler would find these mistakes
+for us... but it doesn't.  To help prevent such bugs, always follow this
+convention::
+
+	If the name of a function is an action or an imperative command,
+	the function should return an error-code integer.  If the name
+	is a predicate, the function should return a "succeeded" boolean.
+
+For example, ``add work`` is a command, and the add_work() function returns 0
+for success or -EBUSY for failure.  In the same way, ``PCI device present`` is
+a predicate, and the pci_dev_present() function returns 1 if it succeeds in
+finding a matching device or 0 if it doesn't.
+
+All EXPORTed functions must respect this convention, and so should all
+public functions.  Private (static) functions need not, but it is
+recommended that they do.
+
+Functions whose return value is the actual result of a computation, rather
+than an indication of whether the computation succeeded, are not subject to
+this rule.  Generally they indicate failure by returning some out-of-range
+result.  Typical examples would be functions that return pointers; they use
+NULL or the ERR_PTR mechanism to report failure.
+
+
+17) Don't re-invent the kernel macros
+-------------------------------------
+
+The header file include/linux/kernel.h contains a number of macros that
+you should use, rather than explicitly coding some variant of them yourself.
+For example, if you need to calculate the length of an array, take advantage
+of the macro
+
+.. code-block:: c
+
+	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+Similarly, if you need to calculate the size of some structure member, use
+
+.. code-block:: c
+
+	#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+
+There are also min() and max() macros that do strict type checking if you
+need them.  Feel free to peruse that header file to see what else is already
+defined that you shouldn't reproduce in your code.
+
+
+18) Editor modelines and other cruft
+------------------------------------
+
+Some editors can interpret configuration information embedded in source files,
+indicated with special markers.  For example, emacs interprets lines marked
+like this:
+
+.. code-block:: c
+
+	-*- mode: c -*-
+
+Or like this:
+
+.. code-block:: c
+
+	/*
+	Local Variables:
+	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+	End:
+	*/
+
+Vim interprets markers that look like this:
+
+.. code-block:: c
+
+	/* vim:set sw=8 noet */
+
+Do not include any of these in source files.  People have their own personal
+editor configurations, and your source files should not override them.  This
+includes markers for indentation and mode configuration.  People may use their
+own custom mode, or may have some other magic method for making indentation
+work correctly.
+
+
+19) Inline assembly
+-------------------
+
+In architecture-specific code, you may need to use inline assembly to interface
+with CPU or platform functionality.  Don't hesitate to do so when necessary.
+However, don't use inline assembly gratuitously when C can do the job.  You can
+and should poke hardware from C when possible.
+
+Consider writing simple helper functions that wrap common bits of inline
+assembly, rather than repeatedly writing them with slight variations.  Remember
+that inline assembly can use C parameters.
+
+Large, non-trivial assembly functions should go in .S files, with corresponding
+C prototypes defined in C header files.  The C prototypes for assembly
+functions should use ``asmlinkage``.
+
+You may need to mark your asm statement as volatile, to prevent GCC from
+removing it if GCC doesn't notice any side effects.  You don't always need to
+do so, though, and doing so unnecessarily can limit optimization.
+
+When writing a single inline assembly statement containing multiple
+instructions, put each instruction on a separate line in a separate quoted
+string, and end each string except the last with \n\t to properly indent the
+next instruction in the assembly output:
+
+.. code-block:: c
+
+	asm ("magic %reg1, #42\n\t"
+	     "more_magic %reg2, %reg3"
+	     : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+20) Conditional Compilation
+---------------------------
+
+Wherever possible, don't use preprocessor conditionals (#if, #ifdef) in .c
+files; doing so makes code harder to read and logic harder to follow.  Instead,
+use such conditionals in a header file defining functions for use in those .c
+files, providing no-op stub versions in the #else case, and then call those
+functions unconditionally from .c files.  The compiler will avoid generating
+any code for the stub calls, producing identical results, but the logic will
+remain easy to follow.
+
+Prefer to compile out entire functions, rather than portions of functions or
+portions of expressions.  Rather than putting an ifdef in an expression, factor
+out part or all of the expression into a separate helper function and apply the
+conditional to that function.
+
+If you have a function or variable which may potentially go unused in a
+particular configuration, and the compiler would warn about its definition
+going unused, mark the definition as __maybe_unused rather than wrapping it in
+a preprocessor conditional.  (However, if a function or variable *always* goes
+unused, delete it.)
+
+Within code, where possible, use the IS_ENABLED macro to convert a Kconfig
+symbol into a C boolean expression, and use it in a normal C conditional:
+
+.. code-block:: c
+
+	if (IS_ENABLED(CONFIG_SOMETHING)) {
+		...
+	}
+
+The compiler will constant-fold the conditional away, and include or exclude
+the block of code just as with an #ifdef, so this will not add any runtime
+overhead.  However, this approach still allows the C compiler to see the code
+inside the block, and check it for correctness (syntax, types, symbol
+references, etc).  Thus, you still have to use an #ifdef if the code inside the
+block references symbols that will not exist if the condition is not met.
+
+At the end of any non-trivial #if or #ifdef block (more than a few lines),
+place a comment after the #endif on the same line, noting the conditional
+expression used.  For instance:
+
+.. code-block:: c
+
+	#ifdef CONFIG_SOMETHING
+	...
+	#endif /* CONFIG_SOMETHING */
+
+
+Appendix I) References
+----------------------
+
+The C Programming Language, Second Edition
+by Brian W. Kernighan and Dennis M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
+
+The Practice of Programming
+by Brian W. Kernighan and Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU manuals - where in compliance with K&R and this text - for cpp, gcc,
+gcc internals and indent, all available from http://www.gnu.org/manual/
+
+WG14 is the international standardization working group for the programming
+language C, URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst, by greg@kroah.com at OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/conf.py linux-libre-4.10-rc8-gnu/Documentation/process/conf.py
--- linux-libre-4.9-gnu/Documentation/process/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel Development Documentation'
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'process.tex', 'Linux Kernel Development Documentation',
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/development-process.rst linux-libre-4.10-rc8-gnu/Documentation/process/development-process.rst
--- linux-libre-4.9-gnu/Documentation/process/development-process.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/development-process.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,28 @@
+.. _development_process_main:
+
+A guide to the Kernel Development Process
+=========================================
+
+Contents:
+
+.. toctree::
+   :numbered:
+   :maxdepth: 2
+
+   1.Intro
+   2.Process
+   3.Early-stage
+   4.Coding
+   5.Posting
+   6.Followthrough
+   7.AdvancedTopics
+   8.Conclusion
+
+The purpose of this document is to help developers (and their managers)
+work with the development community with a minimum of frustration.  It is
+an attempt to document how this community works in a way which is
+accessible to those who are not intimately familiar with Linux kernel
+development (or, indeed, free software development in general).  While
+there is some technical material here, this is very much a process-oriented
+discussion which does not require a deep knowledge of kernel programming to
+understand.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/email-clients.rst linux-libre-4.10-rc8-gnu/Documentation/process/email-clients.rst
--- linux-libre-4.9-gnu/Documentation/process/email-clients.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/email-clients.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,319 @@
+.. _email_clients:
+
+Email clients info for Linux
+============================
+
+Git
+---
+
+These days most developers use ``git send-email`` instead of regular
+email clients.  The man page for this is quite good.  On the receiving
+end, maintainers use ``git am`` to apply the patches.
+
+If you are new to ``git`` then send your first patch to yourself.  Save it
+as raw text including all the headers.  Run ``git am raw_email.txt`` and
+then review the changelog with ``git log``.  When that works then send
+the patch to the appropriate mailing list(s).
+
+General Preferences
+-------------------
+
+Patches for the Linux kernel are submitted via email, preferably as
+inline text in the body of the email.  Some maintainers accept
+attachments, but then the attachments should have content-type
+``text/plain``.  However, attachments are generally frowned upon because
+it makes quoting portions of the patch more difficult in the patch
+review process.
+
+Email clients that are used for Linux kernel patches should send the
+patch text untouched.  For example, they should not modify or delete tabs
+or spaces, even at the beginning or end of lines.
+
+Don't send patches with ``format=flowed``.  This can cause unexpected
+and unwanted line breaks.
+
+Don't let your email client do automatic word wrapping for you.
+This can also corrupt your patch.
+
+Email clients should not modify the character set encoding of the text.
+Emailed patches should be in ASCII or UTF-8 encoding only.
+If you configure your email client to send emails with UTF-8 encoding,
+you avoid some possible charset problems.
+
+Email clients should generate and maintain References: or In-Reply-To:
+headers so that mail threading is not broken.
+
+Copy-and-paste (or cut-and-paste) usually does not work for patches
+because tabs are converted to spaces.  Using xclipboard, xclip, and/or
+xcutsel may work, but it's best to test this for yourself or just avoid
+copy-and-paste.
+
+Don't use PGP/GPG signatures in mail that contains patches.
+This breaks many scripts that read and apply the patches.
+(This should be fixable.)
+
+It's a good idea to send a patch to yourself, save the received message,
+and successfully apply it with 'patch' before sending patches to Linux
+mailing lists.
+
+
+Some email client (MUA) hints
+-----------------------------
+
+Here are some specific MUA configuration hints for editing and sending
+patches for the Linux kernel.  These are not meant to be complete
+software package configuration summaries.
+
+
+Legend:
+
+- TUI = text-based user interface
+- GUI = graphical user interface
+
+Alpine (TUI)
+************
+
+Config options:
+
+In the :menuselection:`Sending Preferences` section:
+
+- :menuselection:`Do Not Send Flowed Text` must be ``enabled``
+- :menuselection:`Strip Whitespace Before Sending` must be ``disabled``
+
+When composing the message, the cursor should be placed where the patch
+should appear, and then pressing :kbd:`CTRL-R` let you specify the patch file
+to insert into the message.
+
+Claws Mail (GUI)
+****************
+
+Works. Some people use this successfully for patches.
+
+To insert a patch use :menuselection:`Message-->Insert` File (:kbd:`CTRL-I`)
+or an external editor.
+
+If the inserted patch has to be edited in the Claws composition window
+"Auto wrapping" in
+:menuselection:`Configuration-->Preferences-->Compose-->Wrapping` should be
+disabled.
+
+Evolution (GUI)
+***************
+
+Some people use this successfully for patches.
+
+When composing mail select: Preformat
+  from :menuselection:`Format-->Paragraph Style-->Preformatted` (:kbd:`CTRL-7`)
+  or the toolbar
+
+Then use:
+:menuselection:`Insert-->Text File...` (:kbd:`ALT-N x`)
+to insert the patch.
+
+You can also ``diff -Nru old.c new.c | xclip``, select
+:menuselection:`Preformat`, then paste with the middle button.
+
+Kmail (GUI)
+***********
+
+Some people use Kmail successfully for patches.
+
+The default setting of not composing in HTML is appropriate; do not
+enable it.
+
+When composing an email, under options, uncheck "word wrap". The only
+disadvantage is any text you type in the email will not be word-wrapped
+so you will have to manually word wrap text before the patch. The easiest
+way around this is to compose your email with word wrap enabled, then save
+it as a draft. Once you pull it up again from your drafts it is now hard
+word-wrapped and you can uncheck "word wrap" without losing the existing
+wrapping.
+
+At the bottom of your email, put the commonly-used patch delimiter before
+inserting your patch:  three hyphens (``---``).
+
+Then from the :menuselection:`Message` menu item, select insert file and
+choose your patch.
+As an added bonus you can customise the message creation toolbar menu
+and put the :menuselection:`insert file` icon there.
+
+Make the composer window wide enough so that no lines wrap. As of
+KMail 1.13.5 (KDE 4.5.4), KMail will apply word wrapping when sending
+the email if the lines wrap in the composer window. Having word wrapping
+disabled in the Options menu isn't enough. Thus, if your patch has very
+long lines, you must make the composer window very wide before sending
+the email. See: https://bugs.kde.org/show_bug.cgi?id=174034
+
+You can safely GPG sign attachments, but inlined text is preferred for
+patches so do not GPG sign them.  Signing patches that have been inserted
+as inlined text will make them tricky to extract from their 7-bit encoding.
+
+If you absolutely must send patches as attachments instead of inlining
+them as text, right click on the attachment and select properties, and
+highlight :menuselection:`Suggest automatic display` to make the attachment
+inlined to make it more viewable.
+
+When saving patches that are sent as inlined text, select the email that
+contains the patch from the message list pane, right click and select
+:menuselection:`save as`.  You can use the whole email unmodified as a patch
+if it was properly composed.  There is no option currently to save the email
+when you are actually viewing it in its own window -- there has been a request
+filed at kmail's bugzilla and hopefully this will be addressed.  Emails are
+saved as read-write for user only so you will have to chmod them to make them
+group and world readable if you copy them elsewhere.
+
+Lotus Notes (GUI)
+*****************
+
+Run away from it.
+
+Mutt (TUI)
+**********
+
+Plenty of Linux developers use ``mutt``, so it must work pretty well.
+
+Mutt doesn't come with an editor, so whatever editor you use should be
+used in a way that there are no automatic linebreaks.  Most editors have
+an :menuselection:`insert file` option that inserts the contents of a file
+unaltered.
+
+To use ``vim`` with mutt::
+
+  set editor="vi"
+
+If using xclip, type the command::
+
+  :set paste
+
+before middle button or shift-insert or use::
+
+  :r filename
+
+if you want to include the patch inline.
+(a)ttach works fine without ``set paste``.
+
+You can also generate patches with ``git format-patch`` and then use Mutt
+to send them::
+
+    $ mutt -H 0001-some-bug-fix.patch
+
+Config options:
+
+It should work with default settings.
+However, it's a good idea to set the ``send_charset`` to::
+
+  set send_charset="us-ascii:utf-8"
+
+Mutt is highly customizable. Here is a minimum configuration to start
+using Mutt to send patches through Gmail::
+
+  # .muttrc
+  # ================  IMAP ====================
+  set imap_user = 'yourusername@gmail.com'
+  set imap_pass = 'yourpassword'
+  set spoolfile = imaps://imap.gmail.com/INBOX
+  set folder = imaps://imap.gmail.com/
+  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+  # ================  SMTP  ====================
+  set smtp_url = "smtp://username@smtp.gmail.com:587/"
+  set smtp_pass = $imap_pass
+  set ssl_force_tls = yes # Require encrypted connection
+
+  # ================  Composition  ====================
+  set editor = `echo \$EDITOR`
+  set edit_headers = yes  # See the headers when editing
+  set charset = UTF-8     # value of $LANG; also fallback for send_charset
+  # Sender, email address, and sign-off line must match
+  unset use_domain        # because joe@localhost is just embarrassing
+  set realname = "YOUR NAME"
+  set from = "username@gmail.com"
+  set use_from = yes
+
+The Mutt docs have lots more information:
+
+    http://dev.mutt.org/trac/wiki/UseCases/Gmail
+
+    http://dev.mutt.org/doc/manual.html
+
+Pine (TUI)
+**********
+
+Pine has had some whitespace truncation issues in the past, but these
+should all be fixed now.
+
+Use alpine (pine's successor) if you can.
+
+Config options:
+
+- ``quell-flowed-text`` is needed for recent versions
+- the ``no-strip-whitespace-before-send`` option is needed
+
+
+Sylpheed (GUI)
+**************
+
+- Works well for inlining text (or using attachments).
+- Allows use of an external editor.
+- Is slow on large folders.
+- Won't do TLS SMTP auth over a non-SSL connection.
+- Has a helpful ruler bar in the compose window.
+- Adding addresses to address book doesn't understand the display name
+  properly.
+
+Thunderbird (GUI)
+*****************
+
+Thunderbird is an Outlook clone that likes to mangle text, but there are ways
+to coerce it into behaving.
+
+- Allow use of an external editor:
+  The easiest thing to do with Thunderbird and patches is to use an
+  "external editor" extension and then just use your favorite ``$EDITOR``
+  for reading/merging patches into the body text.  To do this, download
+  and install the extension, then add a button for it using
+  :menuselection:`View-->Toolbars-->Customize...` and finally just click on it
+  when in the :menuselection:`Compose` dialog.
+
+  Please note that "external editor" requires that your editor must not
+  fork, or in other words, the editor must not return before closing.
+  You may have to pass additional flags or change the settings of your
+  editor. Most notably if you are using gvim then you must pass the -f
+  option to gvim by putting ``/usr/bin/gvim -f`` (if the binary is in
+  ``/usr/bin``) to the text editor field in :menuselection:`external editor`
+  settings. If you are using some other editor then please read its manual
+  to find out how to do this.
+
+To beat some sense out of the internal editor, do this:
+
+- Edit your Thunderbird config settings so that it won't use ``format=flowed``.
+  Go to :menuselection:`edit-->preferences-->advanced-->config editor` to bring up
+  the thunderbird's registry editor.
+
+- Set ``mailnews.send_plaintext_flowed`` to ``false``
+
+- Set ``mailnews.wraplength`` from ``72`` to ``0``
+
+- :menuselection:`View-->Message Body As-->Plain Text`
+
+- :menuselection:`View-->Character Encoding-->Unicode (UTF-8)`
+
+TkRat (GUI)
+***********
+
+Works.  Use "Insert file..." or external editor.
+
+Gmail (Web GUI)
+***************
+
+Does not work for sending patches.
+
+Gmail web client converts tabs to spaces automatically.
+
+At the same time it wraps lines every 78 chars with CRLF style line breaks
+although tab2space problem can be solved with external editor.
+
+Another problem is that Gmail will base64-encode any message that has a
+non-ASCII character. That includes things like European names.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/howto.rst linux-libre-4.10-rc8-gnu/Documentation/process/howto.rst
--- linux-libre-4.9-gnu/Documentation/process/howto.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/howto.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,658 @@
+HOWTO do Linux kernel development
+=================================
+
+This is the be-all, end-all document on this topic.  It contains
+instructions on how to become a Linux kernel developer and how to learn
+to work with the Linux kernel development community.  It tries to not
+contain anything related to the technical aspects of kernel programming,
+but will help point you in the right direction for that.
+
+If anything in this document becomes out of date, please send in patches
+to the maintainer of this file, who is listed at the bottom of the
+document.
+
+
+Introduction
+------------
+
+So, you want to learn how to become a Linux kernel developer?  Or you
+have been told by your manager, "Go write a Linux driver for this
+device."  This document's goal is to teach you everything you need to
+know to achieve this by describing the process you need to go through,
+and hints on how to work with the community.  It will also try to
+explain some of the reasons why the community works like it does.
+
+The kernel is written mostly in C, with some architecture-dependent
+parts written in assembly. A good understanding of C is required for
+kernel development.  Assembly (any architecture) is not required unless
+you plan to do low-level development for that architecture.  Though they
+are not a good substitute for a solid C education and/or years of
+experience, the following books are good for, if anything, reference:
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+
+The kernel is written using GNU C and the GNU toolchain.  While it
+adheres to the ISO C89 standard, it uses a number of extensions that are
+not featured in the standard.  The kernel is a freestanding C
+environment, with no reliance on the standard C library, so some
+portions of the C standard are not supported.  Arbitrary long long
+divisions and floating point are not allowed.  It can sometimes be
+difficult to understand the assumptions the kernel has on the toolchain
+and the extensions that it uses, and unfortunately there is no
+definitive reference for them.  Please check the gcc info pages (`info
+gcc`) for some information on them.
+
+Please remember that you are trying to learn how to work with the
+existing development community.  It is a diverse group of people, with
+high standards for coding, style and procedure.  These standards have
+been created over time based on what they have found to work best for
+such a large and geographically dispersed team.  Try to learn as much as
+possible about these standards ahead of time, as they are well
+documented; do not expect people to adapt to you or your company's way
+of doing things.
+
+
+Legal Issues
+------------
+
+The Linux kernel source code is released under the GPL.  Please see the
+file, COPYING, in the main directory of the source tree, for details on
+the license.  If you have further questions about the license, please
+contact a lawyer, and do not ask on the Linux kernel mailing list.  The
+people on the mailing lists are not lawyers, and you should not rely on
+their statements on legal matters.
+
+For common questions and answers about the GPL, please see:
+
+	https://www.gnu.org/licenses/gpl-faq.html
+
+
+Documentation
+-------------
+
+The Linux kernel source tree has a large range of documents that are
+invaluable for learning how to interact with the kernel community.  When
+new features are added to the kernel, it is recommended that new
+documentation files are also added which explain how to use the feature.
+When a kernel change causes the interface that the kernel exposes to
+userspace to change, it is recommended that you send the information or
+a patch to the manual pages explaining the change to the manual pages
+maintainer at mtk.manpages@gmail.com, and CC the list
+linux-api@vger.kernel.org.
+
+Here is a list of files that are in the kernel source tree that are
+required reading:
+
+  README
+    This file gives a short background on the Linux kernel and describes
+    what is necessary to do to configure and build the kernel.  People
+    who are new to the kernel should start here.
+
+  :ref:`Documentation/process/changes.rst <changes>`
+    This file gives a list of the minimum levels of various software
+    packages that are necessary to build and run the kernel
+    successfully.
+
+  :ref:`Documentation/process/coding-style.rst <codingstyle>`
+    This describes the Linux kernel coding style, and some of the
+    rationale behind it. All new code is expected to follow the
+    guidelines in this document. Most maintainers will only accept
+    patches if these rules are followed, and many people will only
+    review code if it is in the proper style.
+
+  :ref:`Documentation/process/submitting-patches.rst <submittingpatches>` and :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+    These files describe in explicit detail how to successfully create
+    and send a patch, including (but not limited to):
+
+       - Email contents
+       - Email format
+       - Who to send it to
+
+    Following these rules will not guarantee success (as all patches are
+    subject to scrutiny for content and style), but not following them
+    will almost always prevent it.
+
+    Other excellent descriptions of how to create patches properly are:
+
+	"The Perfect Patch"
+		https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+	"Linux kernel patch submission format"
+		http://linux.yyz.us/patch-format.html
+
+  :ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
+    This file describes the rationale behind the conscious decision to
+    not have a stable API within the kernel, including things like:
+
+      - Subsystem shim-layers (for compatibility?)
+      - Driver portability between Operating Systems.
+      - Mitigating rapid change within the kernel source tree (or
+	preventing rapid change)
+
+    This document is crucial for understanding the Linux development
+    philosophy and is very important for people moving to Linux from
+    development on other Operating Systems.
+
+  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+    If you feel you have found a security problem in the Linux kernel,
+    please follow the steps in this document to help notify the kernel
+    developers, and help solve the issue.
+
+  :ref:`Documentation/process/management-style.rst <managementstyle>`
+    This document describes how Linux kernel maintainers operate and the
+    shared ethos behind their methodologies.  This is important reading
+    for anyone new to kernel development (or anyone simply curious about
+    it), as it resolves a lot of common misconceptions and confusion
+    about the unique behavior of kernel maintainers.
+
+  :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+    This file describes the rules on how the stable kernel releases
+    happen, and what to do if you want to get a change into one of these
+    releases.
+
+  :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+    A list of external documentation that pertains to kernel
+    development.  Please consult this list if you do not find what you
+    are looking for within the in-kernel documentation.
+
+  :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+    A good introduction describing exactly what a patch is and how to
+    apply it to the different development branches of the kernel.
+
+The kernel also has a large number of documents that can be
+automatically generated from the source code itself or from
+ReStructuredText markups (ReST), like this one. This includes a
+full description of the in-kernel API, and rules on how to handle
+locking properly.
+
+All such documents can be generated as PDF or HTML by running::
+
+	make pdfdocs
+	make htmldocs
+
+respectively from the main kernel source directory.
+
+The documents that uses ReST markup will be generated at Documentation/output.
+They can also be generated on LaTeX and ePub formats with::
+
+	make latexdocs
+	make epubdocs
+
+Currently, there are some documents written on DocBook that are in
+the process of conversion to ReST. Such documents will be created in the
+Documentation/DocBook/ directory and can be generated also as
+Postscript or man pages by running::
+
+	make psdocs
+	make mandocs
+
+Becoming A Kernel Developer
+---------------------------
+
+If you do not know anything about Linux kernel development, you should
+look at the Linux KernelNewbies project:
+
+	https://kernelnewbies.org
+
+It consists of a helpful mailing list where you can ask almost any type
+of basic kernel development question (make sure to search the archives
+first, before asking something that has already been answered in the
+past.)  It also has an IRC channel that you can use to ask questions in
+real-time, and a lot of helpful documentation that is useful for
+learning about Linux kernel development.
+
+The website has basic information about code organization, subsystems,
+and current projects (both in-tree and out-of-tree). It also describes
+some basic logistical information, like how to compile a kernel and
+apply a patch.
+
+If you do not know where you want to start, but you want to look for
+some task to start doing to join into the kernel development community,
+go to the Linux Kernel Janitor's project:
+
+	https://kernelnewbies.org/KernelJanitors
+
+It is a great place to start.  It describes a list of relatively simple
+problems that need to be cleaned up and fixed within the Linux kernel
+source tree.  Working with the developers in charge of this project, you
+will learn the basics of getting your patch into the Linux kernel tree,
+and possibly be pointed in the direction of what to go work on next, if
+you do not already have an idea.
+
+If you already have a chunk of code that you want to put into the kernel
+tree, but need some help getting it in the proper form, the
+kernel-mentors project was created to help you out with this.  It is a
+mailing list, and can be found at:
+
+	https://selenic.com/mailman/listinfo/kernel-mentors
+
+Before making any actual modifications to the Linux kernel code, it is
+imperative to understand how the code in question works.  For this
+purpose, nothing is better than reading through it directly (most tricky
+bits are commented well), perhaps even with the help of specialized
+tools.  One such tool that is particularly recommended is the Linux
+Cross-Reference project, which is able to present source code in a
+self-referential, indexed webpage format. An excellent up-to-date
+repository of the kernel code may be found at:
+
+	http://lxr.free-electrons.com/
+
+
+The development process
+-----------------------
+
+Linux kernel development process currently consists of a few different
+main kernel "branches" and lots of different subsystem-specific kernel
+branches.  These different branches are:
+
+  - main 4.x kernel tree
+  - 4.x.y -stable kernel tree
+  - 4.x -git kernel patches
+  - subsystem specific kernel trees and patches
+  - the 4.x -next kernel tree for integration tests
+
+4.x kernel tree
+~~~~~~~~~~~~~~~
+
+4.x kernels are maintained by Linus Torvalds, and can be found on
+https://kernel.org in the pub/linux/kernel/v4.x/ directory.  Its development
+process is as follows:
+
+  - As soon as a new kernel is released a two weeks window is open,
+    during this period of time maintainers can submit big diffs to
+    Linus, usually the patches that have already been included in the
+    -next kernel for a few weeks.  The preferred way to submit big changes
+    is using git (the kernel's source management tool, more information
+    can be found at https://git-scm.com/) but plain patches are also just
+    fine.
+  - After two weeks a -rc1 kernel is released and the focus is on making the
+    new kernel as rock solid as possible.  Most of the patches at this point
+    should fix a regression.  Bugs that have always existed are not
+    regressions, so only push these kinds of fixes if they are important.
+    Please note that a whole new driver (or filesystem) might be accepted
+    after -rc1 because there is no risk of causing regressions with such a
+    change as long as the change is self-contained and does not affect areas
+    outside of the code that is being added.  git can be used to send
+    patches to Linus after -rc1 is released, but the patches need to also be
+    sent to a public mailing list for review.
+  - A new -rc is released whenever Linus deems the current git tree to
+    be in a reasonably sane state adequate for testing.  The goal is to
+    release a new -rc kernel every week.
+  - Process continues until the kernel is considered "ready", the
+    process should last around 6 weeks.
+
+It is worth mentioning what Andrew Morton wrote on the linux-kernel
+mailing list about kernel releases:
+
+	*"Nobody knows when a kernel will be released, because it's
+	released according to perceived bug status, not according to a
+	preconceived timeline."*
+
+4.x.y -stable kernel tree
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Kernels with 3-part versions are -stable kernels. They contain
+relatively small and critical fixes for security problems or significant
+regressions discovered in a given 4.x kernel.
+
+This is the recommended branch for users who want the most recent stable
+kernel and are not interested in helping test development/experimental
+versions.
+
+If no 4.x.y kernel is available, then the highest numbered 4.x
+kernel is the current stable kernel.
+
+4.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
+are released as needs dictate.  The normal release period is approximately
+two weeks, but it can be longer if there are no pressing problems.  A
+security-related problem, instead, can cause a release to happen almost
+instantly.
+
+The file Documentation/process/stable-kernel-rules.rst in the kernel tree
+documents what kinds of changes are acceptable for the -stable tree, and
+how the release process works.
+
+4.x -git patches
+~~~~~~~~~~~~~~~~
+
+These are daily snapshots of Linus' kernel tree which are managed in a
+git repository (hence the name.) These patches are usually released
+daily and represent the current state of Linus' tree.  They are more
+experimental than -rc kernels since they are generated automatically
+without even a cursory glance to see if they are sane.
+
+Subsystem Specific kernel trees and patches
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The maintainers of the various kernel subsystems --- and also many
+kernel subsystem developers --- expose their current state of
+development in source repositories.  That way, others can see what is
+happening in the different areas of the kernel.  In areas where
+development is rapid, a developer may be asked to base his submissions
+onto such a subsystem kernel tree so that conflicts between the
+submission and other already ongoing work are avoided.
+
+Most of these repositories are git trees, but there are also other SCMs
+in use, or patch queues being published as quilt series.  Addresses of
+these subsystem repositories are listed in the MAINTAINERS file.  Many
+of them can be browsed at https://git.kernel.org/.
+
+Before a proposed patch is committed to such a subsystem tree, it is
+subject to review which primarily happens on mailing lists (see the
+respective section below).  For several kernel subsystems, this review
+process is tracked with the tool patchwork.  Patchwork offers a web
+interface which shows patch postings, any comments on a patch or
+revisions to it, and maintainers can mark patches as under review,
+accepted, or rejected.  Most of these patchwork sites are listed at
+https://patchwork.kernel.org/.
+
+4.x -next kernel tree for integration tests
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Before updates from subsystem trees are merged into the mainline 4.x
+tree, they need to be integration-tested.  For this purpose, a special
+testing repository exists into which virtually all subsystem trees are
+pulled on an almost daily basis:
+
+	https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+This way, the -next kernel gives a summary outlook onto what will be
+expected to go into the mainline kernel at the next merge period.
+Adventurous testers are very welcome to runtime-test the -next kernel.
+
+
+Bug Reporting
+-------------
+
+https://bugzilla.kernel.org is where the Linux kernel developers track kernel
+bugs.  Users are encouraged to report all bugs that they find in this
+tool.  For details on how to use the kernel bugzilla, please see:
+
+	https://bugzilla.kernel.org/page.cgi?id=faq.html
+
+The file admin-guide/reporting-bugs.rst in the main kernel source directory has a good
+template for how to report a possible kernel bug, and details what kind
+of information is needed by the kernel developers to help track down the
+problem.
+
+
+Managing bug reports
+--------------------
+
+One of the best ways to put into practice your hacking skills is by fixing
+bugs reported by other people. Not only you will help to make the kernel
+more stable, you'll learn to fix real world problems and you will improve
+your skills, and other developers will be aware of your presence. Fixing
+bugs is one of the best ways to get merits among other developers, because
+not many people like wasting time fixing other people's bugs.
+
+To work in the already reported bug reports, go to https://bugzilla.kernel.org.
+If you want to be advised of the future bug reports, you can subscribe to the
+bugme-new mailing list (only new bug reports are mailed here) or to the
+bugme-janitor mailing list (every change in the bugzilla is mailed here)
+
+	https://lists.linux-foundation.org/mailman/listinfo/bugme-new
+
+	https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
+
+
+
+Mailing lists
+-------------
+
+As some of the above documents describe, the majority of the core kernel
+developers participate on the Linux Kernel Mailing list.  Details on how
+to subscribe and unsubscribe from the list can be found at:
+
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+
+There are archives of the mailing list on the web in many different
+places.  Use a search engine to find these archives.  For example:
+
+	http://dir.gmane.org/gmane.linux.kernel
+
+It is highly recommended that you search the archives about the topic
+you want to bring up, before you post it to the list. A lot of things
+already discussed in detail are only recorded at the mailing list
+archives.
+
+Most of the individual kernel subsystems also have their own separate
+mailing list where they do their development efforts.  See the
+MAINTAINERS file for a list of what these lists are for the different
+groups.
+
+Many of the lists are hosted on kernel.org. Information on them can be
+found at:
+
+	http://vger.kernel.org/vger-lists.html
+
+Please remember to follow good behavioral habits when using the lists.
+Though a bit cheesy, the following URL has some simple guidelines for
+interacting with the list (or any list):
+
+	http://www.albion.com/netiquette/
+
+If multiple people respond to your mail, the CC: list of recipients may
+get pretty large. Don't remove anybody from the CC: list without a good
+reason, or don't reply only to the list address. Get used to receiving the
+mail twice, one from the sender and the one from the list, and don't try
+to tune that by adding fancy mail-headers, people will not like it.
+
+Remember to keep the context and the attribution of your replies intact,
+keep the "John Kernelhacker wrote ...:" lines at the top of your reply, and
+add your statements between the individual quoted sections instead of
+writing at the top of the mail.
+
+If you add patches to your mail, make sure they are plain readable text
+as stated in Documentation/process/submitting-patches.rst.
+Kernel developers don't want to deal with
+attachments or compressed patches; they may want to comment on
+individual lines of your patch, which works only that way. Make sure you
+use a mail program that does not mangle spaces and tab characters. A
+good first test is to send the mail to yourself and try to apply your
+own patch by yourself. If that doesn't work, get your mail program fixed
+or change it until it works.
+
+Above all, please remember to show respect to other subscribers.
+
+
+Working with the community
+--------------------------
+
+The goal of the kernel community is to provide the best possible kernel
+there is.  When you submit a patch for acceptance, it will be reviewed
+on its technical merits and those alone.  So, what should you be
+expecting?
+
+  - criticism
+  - comments
+  - requests for change
+  - requests for justification
+  - silence
+
+Remember, this is part of getting your patch into the kernel.  You have
+to be able to take criticism and comments about your patches, evaluate
+them at a technical level and either rework your patches or provide
+clear and concise reasoning as to why those changes should not be made.
+If there are no responses to your posting, wait a few days and try
+again, sometimes things get lost in the huge volume.
+
+What should you not do?
+
+  - expect your patch to be accepted without question
+  - become defensive
+  - ignore comments
+  - resubmit the patch without making any of the requested changes
+
+In a community that is looking for the best technical solution possible,
+there will always be differing opinions on how beneficial a patch is.
+You have to be cooperative, and willing to adapt your idea to fit within
+the kernel.  Or at least be willing to prove your idea is worth it.
+Remember, being wrong is acceptable as long as you are willing to work
+toward a solution that is right.
+
+It is normal that the answers to your first patch might simply be a list
+of a dozen things you should correct.  This does **not** imply that your
+patch will not be accepted, and it is **not** meant against you
+personally.  Simply correct all issues raised against your patch and
+resend it.
+
+
+Differences between the kernel community and corporate structures
+-----------------------------------------------------------------
+
+The kernel community works differently than most traditional corporate
+development environments.  Here are a list of things that you can try to
+do to avoid problems:
+
+  Good things to say regarding your proposed changes:
+
+    - "This solves multiple problems."
+    - "This deletes 2000 lines of code."
+    - "Here is a patch that explains what I am trying to describe."
+    - "I tested it on 5 different architectures..."
+    - "Here is a series of small patches that..."
+    - "This increases performance on typical machines..."
+
+  Bad things you should avoid saying:
+
+    - "We did it this way in AIX/ptx/Solaris, so therefore it must be
+      good..."
+    - "I've being doing this for 20 years, so..."
+    - "This is required for my company to make money"
+    - "This is for our Enterprise product line."
+    - "Here is my 1000 page design document that describes my idea"
+    - "I've been working on this for 6 months..."
+    - "Here's a 5000 line patch that..."
+    - "I rewrote all of the current mess, and here it is..."
+    - "I have a deadline, and this patch needs to be applied now."
+
+Another way the kernel community is different than most traditional
+software engineering work environments is the faceless nature of
+interaction.  One benefit of using email and irc as the primary forms of
+communication is the lack of discrimination based on gender or race.
+The Linux kernel work environment is accepting of women and minorities
+because all you are is an email address.  The international aspect also
+helps to level the playing field because you can't guess gender based on
+a person's name. A man may be named Andrea and a woman may be named Pat.
+Most women who have worked in the Linux kernel and have expressed an
+opinion have had positive experiences.
+
+The language barrier can cause problems for some people who are not
+comfortable with English.  A good grasp of the language can be needed in
+order to get ideas across properly on mailing lists, so it is
+recommended that you check your emails to make sure they make sense in
+English before sending them.
+
+
+Break up your changes
+---------------------
+
+The Linux kernel community does not gladly accept large chunks of code
+dropped on it all at once.  The changes need to be properly introduced,
+discussed, and broken up into tiny, individual portions.  This is almost
+the exact opposite of what companies are used to doing.  Your proposal
+should also be introduced very early in the development process, so that
+you can receive feedback on what you are doing.  It also lets the
+community feel that you are working with them, and not simply using them
+as a dumping ground for your feature.  However, don't send 50 emails at
+one time to a mailing list, your patch series should be smaller than
+that almost all of the time.
+
+The reasons for breaking things up are the following:
+
+1) Small patches increase the likelihood that your patches will be
+   applied, since they don't take much time or effort to verify for
+   correctness.  A 5 line patch can be applied by a maintainer with
+   barely a second glance. However, a 500 line patch may take hours to
+   review for correctness (the time it takes is exponentially
+   proportional to the size of the patch, or something).
+
+   Small patches also make it very easy to debug when something goes
+   wrong.  It's much easier to back out patches one by one than it is
+   to dissect a very large patch after it's been applied (and broken
+   something).
+
+2) It's important not only to send small patches, but also to rewrite
+   and simplify (or simply re-order) patches before submitting them.
+
+Here is an analogy from kernel developer Al Viro:
+
+	*"Think of a teacher grading homework from a math student.  The
+	teacher does not want to see the student's trials and errors
+	before they came up with the solution. They want to see the
+	cleanest, most elegant answer.  A good student knows this, and
+	would never submit her intermediate work before the final
+	solution.*
+
+	*The same is true of kernel development. The maintainers and
+	reviewers do not want to see the thought process behind the
+	solution to the problem one is solving. They want to see a
+	simple and elegant solution."*
+
+It may be challenging to keep the balance between presenting an elegant
+solution and working together with the community and discussing your
+unfinished work. Therefore it is good to get early in the process to
+get feedback to improve your work, but also keep your changes in small
+chunks that they may get already accepted, even when your whole task is
+not ready for inclusion now.
+
+Also realize that it is not acceptable to send patches for inclusion
+that are unfinished and will be "fixed up later."
+
+
+Justify your change
+-------------------
+
+Along with breaking up your patches, it is very important for you to let
+the Linux community know why they should add this change.  New features
+must be justified as being needed and useful.
+
+
+Document your change
+--------------------
+
+When sending in your patches, pay special attention to what you say in
+the text in your email.  This information will become the ChangeLog
+information for the patch, and will be preserved for everyone to see for
+all time.  It should describe the patch completely, containing:
+
+  - why the change is necessary
+  - the overall design approach in the patch
+  - implementation details
+  - testing results
+
+For more details on what this should all look like, please see the
+ChangeLog section of the document:
+
+  "The Perfect Patch"
+      http://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+All of these things are sometimes very hard to do. It can take years to
+perfect these practices (if at all). It's a continuous process of
+improvement that requires a lot of patience and determination. But
+don't give up, it's possible. Many have done it before, and each had to
+start exactly where you are now.
+
+
+
+
+----------
+
+Thanks to Paolo Ciarrocchi who allowed the "Development Process"
+(https://lwn.net/Articles/94386/) section
+to be based on text he had written, and to Randy Dunlap and Gerrit
+Huizenga for some of the list of things you should and should not say.
+Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
+Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi
+Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
+David A. Wheeler, Junio Hamano, Michael Kerrisk, and Alex Shepard for
+their review, comments, and contributions.  Without their help, this
+document would not have been possible.
+
+
+
+Maintainer: Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/index.rst linux-libre-4.10-rc8-gnu/Documentation/process/index.rst
--- linux-libre-4.9-gnu/Documentation/process/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,57 @@
+.. raw:: latex
+
+	\renewcommand\thesection*
+	\renewcommand\thesubsection*
+
+
+Working with the kernel development community
+=============================================
+
+So you want to be a Linux kernel developer?  Welcome!  While there is a lot
+to be learned about the kernel in a technical sense, it is also important
+to learn about how our community works.  Reading these documents will make
+it much easier for you to get your changes merged with a minimum of
+trouble.
+
+Below are the essential guides that every developer should read.
+
+.. toctree::
+   :maxdepth: 1
+
+   howto
+   code-of-conflict
+   development-process
+   submitting-patches
+   coding-style
+   email-clients
+
+Other guides to the community that are of interest to most developers are: 
+
+.. toctree::
+   :maxdepth: 1
+
+   changes
+   submitting-drivers
+   stable-api-nonsense
+   management-style
+   stable-kernel-rules
+   submit-checklist
+   kernel-docs
+
+These are some overall technical guides that have been put here for now for
+lack of a better place.
+
+.. toctree::
+   :maxdepth: 1
+
+   applying-patches
+   adding-syscalls
+   magic-number
+   volatile-considered-harmful
+
+.. only::  subproject and html
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/kernel-docs.rst linux-libre-4.10-rc8-gnu/Documentation/process/kernel-docs.rst
--- linux-libre-4.9-gnu/Documentation/process/kernel-docs.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/kernel-docs.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,652 @@
+.. _kernel_docs:
+
+Index of Documentation for People Interested in Writing and/or Understanding the Linux Kernel
+=============================================================================================
+
+          Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
+
+The need for a document like this one became apparent in the
+linux-kernel mailing list as the same questions, asking for pointers
+to information, appeared again and again.
+
+Fortunately, as more and more people get to GNU/Linux, more and more
+get interested in the Kernel. But reading the sources is not always
+enough. It is easy to understand the code, but miss the concepts, the
+philosophy and design decisions behind this code.
+
+Unfortunately, not many documents are available for beginners to
+start. And, even if they exist, there was no "well-known" place which
+kept track of them. These lines try to cover this lack. All documents
+available on line known by the author are listed, while some reference
+books are also mentioned.
+
+PLEASE, if you know any paper not listed here or write a new document,
+send me an e-mail, and I'll include a reference to it here. Any
+corrections, ideas or comments are also welcomed.
+
+The papers that follow are listed in no particular order. All are
+cataloged with the following fields: the document's "Title", the
+"Author"/s, the "URL" where they can be found, some "Keywords" helpful
+when searching for specific topics, and a brief "Description" of the
+Document.
+
+Enjoy!
+
+.. note::
+
+   The documents on each section of this document are ordered by its
+   published date, from the newest to the oldest.
+
+Docs at the Linux Kernel tree
+-----------------------------
+
+The DocBook books should be built with ``make {htmldocs | psdocs | pdfdocs}``.
+The Sphinx books should be built with ``make {htmldocs | pdfdocs | epubdocs}``.
+
+    * Name: **linux/Documentation**
+
+      :Author: Many.
+      :Location: Documentation/
+      :Keywords: text files, Sphinx, DocBook.
+      :Description: Documentation that comes with the kernel sources,
+        inside the Documentation directory. Some pages from this document
+        (including this document itself) have been moved there, and might
+        be more up to date than the web version.
+
+    * Title: **The Kernel Hacking HOWTO**
+
+      :Author: Various Talented People, and Rusty.
+      :Location: Documentation/DocBook/kernel-hacking.tmpl
+      :Keywords: HOWTO, kernel contexts, deadlock, locking, modules,
+        symbols, return conventions.
+      :Description: From the Introduction: "Please understand that I
+        never wanted to write this document, being grossly underqualified,
+        but I always wanted to read it, and this was the only way. I
+        simply explain some best practices, and give reading entry-points
+        into the kernel sources. I avoid implementation details: that's
+        what the code is for, and I ignore whole tracts of useful
+        routines. This document assumes familiarity with C, and an
+        understanding of what the kernel is, and how it is used. It was
+        originally written for the 2.3 kernels, but nearly all of it
+        applies to 2.2 too; 2.0 is slightly different".
+
+    * Title: **Linux Kernel Locking HOWTO**
+
+      :Author: Various Talented People, and Rusty.
+      :Location: Documentation/DocBook/kernel-locking.tmpl
+      :Keywords: locks, locking, spinlock, semaphore, atomic, race
+        condition, bottom halves, tasklets, softirqs.
+      :Description: The title says it all: document describing the
+        locking system in the Linux Kernel either in uniprocessor or SMP
+        systems.
+      :Notes: "It was originally written for the later (>2.3.47) 2.3
+        kernels, but most of it applies to 2.2 too; 2.0 is slightly
+        different". Freely redistributable under the conditions of the GNU
+        General Public License.
+
+On-line docs
+------------
+
+    * Title: **Linux Kernel Mailing List Glossary**
+
+      :Author: various
+      :URL: http://kernelnewbies.org/glossary/
+      :Date: rolling version
+      :Keywords: glossary, terms, linux-kernel.
+      :Description: From the introduction: "This glossary is intended as
+        a brief description of some of the acronyms and terms you may hear
+        during discussion of the Linux kernel".
+
+    * Title: **Tracing the Way of Data in a TCP Connection through the Linux Kernel**
+
+      :Author: Richard Sailer
+      :URL: https://archive.org/details/linux_kernel_data_flow_short_paper
+      :Date: 2016
+      :Keywords: Linux Kernel Networking, TCP, tracing, ftrace
+      :Description: A seminar paper explaining ftrace and how to use it for
+        understanding linux kernel internals,
+        illustrated at tracing the way of a TCP packet through the kernel.
+      :Abstract: *This short paper outlines the usage of ftrace a tracing framework
+        as a tool to understand a running Linux system.
+        Having obtained a trace-log a kernel hacker can read and understand
+        source code more determined and with context.
+        In a detailed example this approach is demonstrated in tracing
+        and the way of data in a TCP Connection through the kernel.
+        Finally this trace-log is used as base for more a exact conceptual
+        exploration and description of the Linux TCP/IP implementation.*
+
+    * Title: **On submitting kernel Patches**
+
+      :Author: Andi Kleen
+      :URL: http://halobates.de/on-submitting-kernel-patches.pdf
+      :Date: 2008
+      :Keywords: patches, review process, types of submissions, basic rules, case studies
+      :Description: This paper gives several experience values on what types of patches
+        there are and how likley they get merged.
+      :Abstract:
+        [...]. This paper examines some common problems for
+        submitting larger changes and some strategies to avoid problems.
+
+    * Title: **Overview of the Virtual File System**
+
+      :Author: Richard Gooch.
+      :URL: http://www.mjmwired.net/kernel/Documentation/filesystems/vfs.txt
+      :Date: 2007
+      :Keywords: VFS, File System, mounting filesystems, opening files,
+        dentries, dcache.
+      :Description: Brief introduction to the Linux Virtual File System.
+        What is it, how it works, operations taken when opening a file or
+        mounting a file system and description of important data
+        structures explaining the purpose of each of their entries.
+
+    * Title: **Linux Device Drivers, Third Edition**
+
+      :Author: Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
+      :URL: http://lwn.net/Kernel/LDD3/
+      :Date: 2005
+      :Description: A 600-page book covering the (2.6.10) driver
+        programming API and kernel hacking in general.  Available under the
+        Creative Commons Attribution-ShareAlike 2.0 license.
+      :note: You can also :ref:`purchase a copy from O'Reilly or elsewhere  <ldd3_published>`.
+
+    * Title: **Writing an ALSA Driver**
+
+      :Author: Takashi Iwai <tiwai@suse.de>
+      :URL: http://www.alsa-project.org/~iwai/writing-an-alsa-driver/index.html
+      :Date: 2005
+      :Keywords: ALSA, sound, soundcard, driver, lowlevel, hardware.
+      :Description: Advanced Linux Sound Architecture for developers,
+        both at kernel and user-level sides. ALSA is the Linux kernel
+        sound architecture in the 2.6 kernel version.
+
+    * Title: **Linux PCMCIA Programmer's Guide**
+
+      :Author: David Hinds.
+      :URL: http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html
+      :Date: 2003
+      :Keywords: PCMCIA.
+      :Description: "This document describes how to write kernel device
+        drivers for the Linux PCMCIA Card Services interface. It also
+        describes how to write user-mode utilities for communicating with
+        Card Services.
+
+    * Title: **Linux Kernel Module Programming Guide**
+
+      :Author: Ori Pomerantz.
+      :URL: http://tldp.org/LDP/lkmpg/2.6/html/index.html
+      :Date: 2001
+      :Keywords: modules, GPL book, /proc, ioctls, system calls,
+        interrupt handlers .
+      :Description: Very nice 92 pages GPL book on the topic of modules
+        programming. Lots of examples.
+
+    * Title: **Global spinlock list and usage**
+
+      :Author: Rick Lindsley.
+      :URL: http://lse.sourceforge.net/lockhier/global-spin-lock
+      :Date: 2001
+      :Keywords: spinlock.
+      :Description: This is an attempt to document both the existence and
+        usage of the spinlocks in the Linux 2.4.5 kernel. Comprehensive
+        list of spinlocks showing when they are used, which functions
+        access them, how each lock is acquired, under what conditions it
+        is held, whether interrupts can occur or not while it is held...
+
+    * Title: **A Linux vm README**
+
+      :Author: Kanoj Sarcar.
+      :URL: http://kos.enix.org/pub/linux-vmm.html
+      :Date: 2001
+      :Keywords: virtual memory, mm, pgd, vma, page, page flags, page
+        cache, swap cache, kswapd.
+      :Description: Telegraphic, short descriptions and definitions
+        relating the Linux virtual memory implementation.
+
+    * Title: **Video4linux Drivers, Part 1: Video-Capture Device**
+
+      :Author: Alan Cox.
+      :URL: http://www.linux-mag.com/id/406
+      :Date: 2000
+      :Keywords: video4linux, driver, video capture, capture devices,
+        camera driver.
+      :Description: The title says it all.
+
+    * Title: **Video4linux Drivers, Part 2: Video-capture Devices**
+
+      :Author: Alan Cox.
+      :URL: http://www.linux-mag.com/id/429
+      :Date: 2000
+      :Keywords: video4linux, driver, video capture, capture devices,
+        camera driver, control, query capabilities, capability, facility.
+      :Description: The title says it all.
+
+    * Title: **Linux IP Networking. A Guide to the Implementation and Modification of the Linux Protocol Stack.**
+
+      :Author: Glenn Herrin.
+      :URL: http://www.cs.unh.edu/cnrg/gherrin
+      :Date: 2000
+      :Keywords: network, networking, protocol, IP, UDP, TCP, connection,
+        socket, receiving, transmitting, forwarding, routing, packets,
+        modules, /proc, sk_buff, FIB, tags.
+      :Description: Excellent paper devoted to the Linux IP Networking,
+        explaining anything from the kernel's to the user space
+        configuration tools' code. Very good to get a general overview of
+        the kernel networking implementation and understand all steps
+        packets follow from the time they are received at the network
+        device till they are delivered to applications. The studied kernel
+        code is from 2.2.14 version. Provides code for a working packet
+        dropper example.
+
+    * Title: **How To Make Sure Your Driver Will Work On The Power Macintosh**
+
+      :Author: Paul Mackerras.
+      :URL: http://www.linux-mag.com/id/261
+      :Date: 1999
+      :Keywords: Mac, Power Macintosh, porting, drivers, compatibility.
+      :Description: The title says it all.
+
+    * Title: **An Introduction to SCSI Drivers**
+
+      :Author: Alan Cox.
+      :URL: http://www.linux-mag.com/id/284
+      :Date: 1999
+      :Keywords: SCSI, device, driver.
+      :Description: The title says it all.
+
+    * Title: **Advanced SCSI Drivers And Other Tales**
+
+      :Author: Alan Cox.
+      :URL: http://www.linux-mag.com/id/307
+      :Date: 1999
+      :Keywords: SCSI, device, driver, advanced.
+      :Description: The title says it all.
+
+    * Title: **Writing Linux Mouse Drivers**
+
+      :Author: Alan Cox.
+      :URL: http://www.linux-mag.com/id/330
+      :Date: 1999
+      :Keywords: mouse, driver, gpm.
+      :Description: The title says it all.
+
+    * Title: **More on Mouse Drivers**
+
+      :Author: Alan Cox.
+      :URL: http://www.linux-mag.com/id/356
+      :Date: 1999
+      :Keywords: mouse, driver, gpm, races, asynchronous I/O.
+      :Description: The title still says it all.
+
+    * Title: **Writing Video4linux Radio Driver**
+
+      :Author: Alan Cox.
+      :URL: http://www.linux-mag.com/id/381
+      :Date: 1999
+      :Keywords: video4linux, driver, radio, radio devices.
+      :Description: The title says it all.
+
+    * Title: **I/O Event Handling Under Linux**
+
+      :Author: Richard Gooch.
+      :URL: http://web.mit.edu/~yandros/doc/io-events.html
+      :Date: 1999
+      :Keywords: IO, I/O, select(2), poll(2), FDs, aio_read(2), readiness
+        event queues.
+      :Description: From the Introduction: "I/O Event handling is about
+        how your Operating System allows you to manage a large number of
+        open files (file descriptors in UNIX/POSIX, or FDs) in your
+        application. You want the OS to notify you when FDs become active
+        (have data ready to be read or are ready for writing). Ideally you
+        want a mechanism that is scalable. This means a large number of
+        inactive FDs cost very little in memory and CPU time to manage".
+
+    * Title: **(nearly) Complete Linux Loadable Kernel Modules. The definitive guide for hackers, virus coders and system administrators.**
+
+      :Author: pragmatic/THC.
+      :URL: http://packetstormsecurity.org/docs/hack/LKM_HACKING.html
+      :Date: 1999
+      :Keywords: syscalls, intercept, hide, abuse, symbol table.
+      :Description: Interesting paper on how to abuse the Linux kernel in
+        order to intercept and modify syscalls, make
+        files/directories/processes invisible, become root, hijack ttys,
+        write kernel modules based virus... and solutions for admins to
+        avoid all those abuses.
+      :Notes: For 2.0.x kernels. Gives guidances to port it to 2.2.x
+        kernels.
+
+    * Name: **Linux Virtual File System**
+
+      :Author: Peter J. Braam.
+      :URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/
+      :Date: 1998
+      :Keywords: slides, VFS, inode, superblock, dentry, dcache.
+      :Description: Set of slides, presumably from a presentation on the
+        Linux VFS layer. Covers version 2.1.x, with dentries and the
+        dcache.
+
+    * Title: **The Venus kernel interface**
+
+      :Author: Peter J. Braam.
+      :URL: http://www.coda.cs.cmu.edu/doc/html/kernel-venus-protocol.html
+      :Date: 1998
+      :Keywords: coda, filesystem, venus, cache manager.
+      :Description: "This document describes the communication between
+        Venus and kernel level file system code needed for the operation
+        of the Coda filesystem. This version document is meant to describe
+        the current interface (version 1.0) as well as improvements we
+        envisage".
+
+    * Title: **Design and Implementation of the Second Extended Filesystem**
+
+      :Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
+      :URL: http://web.mit.edu/tytso/www/linux/ext2intro.html
+      :Date: 1998
+      :Keywords: ext2, linux fs history, inode, directory, link, devices,
+        VFS, physical structure, performance, benchmarks, ext2fs library,
+        ext2fs tools, e2fsck.
+      :Description: Paper written by three of the top ext2 hackers.
+        Covers Linux filesystems history, ext2 motivation, ext2 features,
+        design, physical structure on disk, performance, benchmarks,
+        e2fsck's passes description... A must read!
+      :Notes: This paper was first published in the Proceedings of the
+        First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
+
+    * Title: **The Linux RAID-1, 4, 5 Code**
+
+      :Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
+      :URL: http://www.linuxjournal.com/article.php?sid=2391
+      :Date: 1997
+      :Keywords: RAID, MD driver.
+      :Description: Linux Journal Kernel Korner article. Here is its
+      :Abstract: *A description of the implementation of the RAID-1,
+        RAID-4 and RAID-5 personalities of the MD device driver in the
+        Linux kernel, providing users with high performance and reliable,
+        secondary-storage capability using software*.
+
+    * Title: **Linux Kernel Hackers' Guide**
+
+      :Author: Michael K. Johnson.
+      :URL: http://www.tldp.org/LDP/khg/HyperNews/get/khg.html
+      :Date: 1997
+      :Keywords: device drivers, files, VFS, kernel interface, character vs
+        block devices, hardware interrupts, scsi, DMA, access to user memory,
+        memory allocation, timers.
+      :Description: A guide designed to help you get up to speed on the
+        concepts that are not intuitevly obvious, and to document the internal
+        structures of Linux.
+
+    * Title: **Dynamic Kernels: Modularized Device Drivers**
+
+      :Author: Alessandro Rubini.
+      :URL: http://www.linuxjournal.com/article.php?sid=1219
+      :Date: 1996
+      :Keywords: device driver, module, loading/unloading modules,
+        allocating resources.
+      :Description: Linux Journal Kernel Korner article. Here is its
+      :Abstract: *This is the first of a series of four articles
+        co-authored by Alessandro Rubini and Georg Zezchwitz which present
+        a practical approach to writing Linux device drivers as kernel
+        loadable modules. This installment presents an introduction to the
+        topic, preparing the reader to understand next month's
+        installment*.
+
+    * Title: **Dynamic Kernels: Discovery**
+
+      :Author: Alessandro Rubini.
+      :URL: http://www.linuxjournal.com/article.php?sid=1220
+      :Date: 1996
+      :Keywords: character driver, init_module, clean_up module,
+        autodetection, mayor number, minor number, file operations,
+        open(), close().
+      :Description: Linux Journal Kernel Korner article. Here is its
+      :Abstract: *This article, the second of four, introduces part of
+        the actual code to create custom module implementing a character
+        device driver. It describes the code for module initialization and
+        cleanup, as well as the open() and close() system calls*.
+
+    * Title: **The Devil's in the Details**
+
+      :Author: Georg v. Zezschwitz and Alessandro Rubini.
+      :URL: http://www.linuxjournal.com/article.php?sid=1221
+      :Date: 1996
+      :Keywords: read(), write(), select(), ioctl(), blocking/non
+        blocking mode, interrupt handler.
+      :Description: Linux Journal Kernel Korner article. Here is its
+      :Abstract: *This article, the third of four on writing character
+        device drivers, introduces concepts of reading, writing, and using
+        ioctl-calls*.
+
+    * Title: **Dissecting Interrupts and Browsing DMA**
+
+      :Author: Alessandro Rubini and Georg v. Zezschwitz.
+      :URL: http://www.linuxjournal.com/article.php?sid=1222
+      :Date: 1996
+      :Keywords: interrupts, irqs, DMA, bottom halves, task queues.
+      :Description: Linux Journal Kernel Korner article. Here is its
+      :Abstract: *This is the fourth in a series of articles about
+        writing character device drivers as loadable kernel modules. This
+        month, we further investigate the field of interrupt handling.
+        Though it is conceptually simple, practical limitations and
+        constraints make this an ''interesting'' part of device driver
+        writing, and several different facilities have been provided for
+        different situations. We also investigate the complex topic of
+        DMA*.
+
+    * Title: **Device Drivers Concluded**
+
+      :Author: Georg v. Zezschwitz.
+      :URL: http://www.linuxjournal.com/article.php?sid=1287
+      :Date: 1996
+      :Keywords: address spaces, pages, pagination, page management,
+        demand loading, swapping, memory protection, memory mapping, mmap,
+        virtual memory areas (VMAs), vremap, PCI.
+      :Description: Finally, the above turned out into a five articles
+        series. This latest one's introduction reads: "This is the last of
+        five articles about character device drivers. In this final
+        section, Georg deals with memory mapping devices, beginning with
+        an overall description of the Linux memory management concepts".
+
+    * Title: **Network Buffers And Memory Management**
+
+      :Author: Alan Cox.
+      :URL: http://www.linuxjournal.com/article.php?sid=1312
+      :Date: 1996
+      :Keywords: sk_buffs, network devices, protocol/link layer
+        variables, network devices flags, transmit, receive,
+        configuration, multicast.
+      :Description: Linux Journal Kernel Korner.
+      :Abstract: *Writing a network device driver for Linux is fundamentally
+        simple---most of the complexity (other than talking to the
+        hardware) involves managing network packets in memory*.
+
+    * Title: **Analysis of the Ext2fs structure**
+
+      :Author: Louis-Dominique Dubeau.
+      :URL: http://teaching.csse.uwa.edu.au/units/CITS2002/fs-ext2/
+      :Date: 1994
+      :Keywords: ext2, filesystem, ext2fs.
+      :Description: Description of ext2's blocks, directories, inodes,
+        bitmaps, invariants...
+
+Published books
+---------------
+
+    * Title: **Linux Treiber entwickeln**
+
+      :Author: Jürgen Quade, Eva-Katharina Kunst
+      :Publisher: dpunkt.verlag
+      :Date: Oct 2015 (4th edition)
+      :Pages: 688
+      :ISBN: 978-3-86490-288-8
+      :Note: German. The third edition from 2011 is
+         much cheaper and still quite up-to-date.
+
+    * Title: **Linux Kernel Networking: Implementation and Theory**
+
+      :Author: Rami Rosen
+      :Publisher: Apress
+      :Date: December 22, 2013
+      :Pages: 648
+      :ISBN: 978-1430261964
+
+    * Title: **Embedded Linux Primer: A practical Real-World Approach, 2nd Edition**
+
+      :Author: Christopher Hallinan
+      :Publisher: Pearson
+      :Date: November, 2010
+      :Pages: 656
+      :ISBN: 978-0137017836
+
+    * Title: **Linux Kernel Development, 3rd Edition**
+
+      :Author: Robert Love
+      :Publisher: Addison-Wesley
+      :Date: July, 2010
+      :Pages: 440
+      :ISBN: 978-0672329463
+
+    * Title: **Essential Linux Device Drivers**
+
+      :Author: Sreekrishnan Venkateswaran
+      :Published: Prentice Hall
+      :Date: April, 2008
+      :Pages: 744
+      :ISBN: 978-0132396554
+
+.. _ldd3_published:
+
+    * Title: **Linux Device Drivers, 3rd Edition**
+
+      :Authors: Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
+      :Publisher: O'Reilly & Associates
+      :Date: 2005
+      :Pages: 636
+      :ISBN: 0-596-00590-3
+      :Notes: Further information in
+        http://www.oreilly.com/catalog/linuxdrive3/
+        PDF format, URL: http://lwn.net/Kernel/LDD3/
+
+    * Title: **Linux Kernel Internals**
+
+      :Author: Michael Beck
+      :Publisher: Addison-Wesley
+      :Date: 1997
+      :ISBN: 0-201-33143-8 (second edition)
+
+    * Title: **Programmation Linux 2.0 API systeme et fonctionnement du noyau**
+
+      :Author: Remy Card, Eric Dumas, Franck Mevel
+      :Publisher: Eyrolles
+      :Date: 1997
+      :Pages: 520
+      :ISBN: 2-212-08932-5
+      :Notes: French
+
+    * Title: **The Design and Implementation of the 4.4 BSD UNIX Operating System**
+
+      :Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
+        John S. Quarterman
+      :Publisher: Addison-Wesley
+      :Date: 1996
+      :ISBN: 0-201-54979-4
+
+    * Title: **Unix internals -- the new frontiers**
+
+      :Author: Uresh Vahalia
+      :Publisher: Prentice Hall
+      :Date: 1996
+      :Pages: 600
+      :ISBN: 0-13-101908-2
+
+    * Title: **Programming for the real world - POSIX.4**
+
+      :Author: Bill O. Gallmeister
+      :Publisher: O'Reilly & Associates, Inc
+      :Date: 1995
+      :Pages: 552
+      :ISBN: I-56592-074-0
+      :Notes: Though not being directly about Linux, Linux aims to be
+        POSIX. Good reference.
+
+    * Title:  **UNIX  Systems  for  Modern Architectures: Symmetric Multiprocessing and Caching for Kernel Programmers**
+
+      :Author: Curt Schimmel
+      :Publisher: Addison Wesley
+      :Date: June, 1994
+      :Pages: 432
+      :ISBN: 0-201-63338-8
+
+    * Title: **The Design and Implementation of the 4.3 BSD UNIX Operating System**
+
+      :Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J
+        Karels, John S. Quarterman
+      :Publisher: Addison-Wesley
+      :Date: 1989 (reprinted with corrections on October, 1990)
+      :ISBN: 0-201-06196-1
+
+    * Title: **The Design of the UNIX Operating System**
+
+      :Author: Maurice J. Bach
+      :Publisher: Prentice Hall
+      :Date: 1986
+      :Pages: 471
+      :ISBN: 0-13-201757-1
+
+Miscellaneous
+-------------
+
+    * Name: **Cross-Referencing Linux**
+
+      :URL: http://lxr.free-electrons.com/
+      :Keywords: Browsing source code.
+      :Description: Another web-based Linux kernel source code browser.
+        Lots of cross references to variables and functions. You can see
+        where they are defined and where they are used.
+
+    * Name: **Linux Weekly News**
+
+      :URL: http://lwn.net
+      :Keywords: latest kernel news.
+      :Description: The title says it all. There's a fixed kernel section
+        summarizing developers' work, bug fixes, new features and versions
+        produced during the week. Published every Thursday.
+
+    * Name: **The home page of Linux-MM**
+
+      :Author: The Linux-MM team.
+      :URL: http://linux-mm.org/
+      :Keywords: memory management, Linux-MM, mm patches, TODO, docs,
+        mailing list.
+      :Description: Site devoted to Linux Memory Management development.
+        Memory related patches, HOWTOs, links, mm developers... Don't miss
+        it if you are interested in memory management development!
+
+    * Name: **Kernel Newbies IRC Channel and Website**
+
+      :URL: http://www.kernelnewbies.org
+      :Keywords: IRC, newbies, channel, asking doubts.
+      :Description: #kernelnewbies on irc.oftc.net.
+        #kernelnewbies is an IRC network dedicated to the 'newbie'
+        kernel hacker. The audience mostly consists of people who are
+        learning about the kernel, working on kernel projects or
+        professional kernel hackers that want to help less seasoned kernel
+        people.
+        #kernelnewbies is on the OFTC IRC Network.
+        Try irc.oftc.net as your server and then /join #kernelnewbies.
+        The kernelnewbies website also hosts articles, documents, FAQs...
+
+    * Name: **linux-kernel mailing list archives and search engines**
+
+      :URL: http://vger.kernel.org/vger-lists.html
+      :URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html
+      :URL: http://groups.google.com/group/mlist.linux.kernel
+      :Keywords: linux-kernel, archives, search.
+      :Description: Some of the linux-kernel mailing list archivers. If
+        you have a better/another one, please let me know.
+
+-------
+
+Document last updated on Tue 2016-Sep-20
+
+This document is based on:
+ http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/magic-number.rst linux-libre-4.10-rc8-gnu/Documentation/process/magic-number.rst
--- linux-libre-4.9-gnu/Documentation/process/magic-number.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/magic-number.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,164 @@
+Linux magic numbers
+===================
+
+This file is a registry of magic numbers which are in use.  When you
+add a magic number to a structure, you should also add it to this
+file, since it is best if the magic numbers used by various structures
+are unique.
+
+It is a **very** good idea to protect kernel data structures with magic
+numbers.  This allows you to check at run time whether (a) a structure
+has been clobbered, or (b) you've passed the wrong structure to a
+routine.  This last is especially useful --- particularly when you are
+passing pointers to structures via a void * pointer.  The tty code,
+for example, does this frequently to pass driver-specific and line
+discipline-specific structures back and forth.
+
+The way to use magic numbers is to declare then at the beginning of
+the structure, like so::
+
+	struct tty_ldisc {
+		int	magic;
+		...
+	};
+
+Please follow this discipline when you are adding future enhancements
+to the kernel!  It has saved me countless hours of debugging,
+especially in the screwy cases where an array has been overrun and
+structures following the array have been overwritten.  Using this
+discipline, these cases get detected quickly and safely.
+
+Changelog::
+
+					Theodore Ts'o
+					31 Mar 94
+
+  The magic table is current to Linux 2.1.55.
+
+					Michael Chastain
+					<mailto:mec@shout.net>
+					22 Sep 1997
+
+  Now it should be up to date with Linux 2.1.112. Because
+  we are in feature freeze time it is very unlikely that
+  something will change before 2.2.x. The entries are
+  sorted by number field.
+
+					Krzysztof G. Baranowski
+					<mailto: kgb@knm.org.pl>
+					29 Jul 1998
+
+  Updated the magic table to Linux 2.5.45. Right over the feature freeze,
+  but it is possible that some new magic numbers will sneak into the
+  kernel before 2.6.x yet.
+
+					Petr Baudis
+					<pasky@ucw.cz>
+					03 Nov 2002
+
+  Updated the magic table to Linux 2.5.74.
+
+					Fabian Frederick
+					<ffrederick@users.sourceforge.net>
+					09 Jul 2003
+
+
+===================== ================ ======================== ==========================================
+Magic Name            Number           Structure                File
+===================== ================ ======================== ==========================================
+PG_MAGIC              'P'              pg_{read,write}_hdr      ``include/linux/pg.h``
+CMAGIC                0x0111           user                     ``include/linux/a.out.h``
+MKISS_DRIVER_MAGIC    0x04bf           mkiss_channel            ``drivers/net/mkiss.h``
+HDLC_MAGIC            0x239e           n_hdlc                   ``drivers/char/n_hdlc.c``
+APM_BIOS_MAGIC        0x4101           apm_user                 ``arch/x86/kernel/apm_32.c``
+CYCLADES_MAGIC        0x4359           cyclades_port            ``include/linux/cyclades.h``
+DB_MAGIC              0x4442           fc_info                  ``drivers/net/iph5526_novram.c``
+DL_MAGIC              0x444d           fc_info                  ``drivers/net/iph5526_novram.c``
+FASYNC_MAGIC          0x4601           fasync_struct            ``include/linux/fs.h``
+FF_MAGIC              0x4646           fc_info                  ``drivers/net/iph5526_novram.c``
+ISICOM_MAGIC          0x4d54           isi_port                 ``include/linux/isicom.h``
+PTY_MAGIC             0x5001                                    ``drivers/char/pty.c``
+PPP_MAGIC             0x5002           ppp                      ``include/linux/if_pppvar.h``
+SERIAL_MAGIC          0x5301           async_struct             ``include/linux/serial.h``
+SSTATE_MAGIC          0x5302           serial_state             ``include/linux/serial.h``
+SLIP_MAGIC            0x5302           slip                     ``drivers/net/slip.h``
+STRIP_MAGIC           0x5303           strip                    ``drivers/net/strip.c``
+X25_ASY_MAGIC         0x5303           x25_asy                  ``drivers/net/x25_asy.h``
+SIXPACK_MAGIC         0x5304           sixpack                  ``drivers/net/hamradio/6pack.h``
+AX25_MAGIC            0x5316           ax_disp                  ``drivers/net/mkiss.h``
+TTY_MAGIC             0x5401           tty_struct               ``include/linux/tty.h``
+MGSL_MAGIC            0x5401           mgsl_info                ``drivers/char/synclink.c``
+TTY_DRIVER_MAGIC      0x5402           tty_driver               ``include/linux/tty_driver.h``
+MGSLPC_MAGIC          0x5402           mgslpc_info              ``drivers/char/pcmcia/synclink_cs.c``
+TTY_LDISC_MAGIC       0x5403           tty_ldisc                ``include/linux/tty_ldisc.h``
+USB_SERIAL_MAGIC      0x6702           usb_serial               ``drivers/usb/serial/usb-serial.h``
+FULL_DUPLEX_MAGIC     0x6969                                    ``drivers/net/ethernet/dec/tulip/de2104x.c``
+USB_BLUETOOTH_MAGIC   0x6d02           usb_bluetooth            ``drivers/usb/class/bluetty.c``
+RFCOMM_TTY_MAGIC      0x6d02                                    ``net/bluetooth/rfcomm/tty.c``
+USB_SERIAL_PORT_MAGIC 0x7301           usb_serial_port          ``drivers/usb/serial/usb-serial.h``
+CG_MAGIC              0x00090255       ufs_cylinder_group       ``include/linux/ufs_fs.h``
+RPORT_MAGIC           0x00525001       r_port                   ``drivers/char/rocket_int.h``
+LSEMAGIC              0x05091998       lse                      ``drivers/fc4/fc.c``
+GDTIOCTL_MAGIC        0x06030f07       gdth_iowr_str            ``drivers/scsi/gdth_ioctl.h``
+RIEBL_MAGIC           0x09051990                                ``drivers/net/atarilance.c``
+NBD_REQUEST_MAGIC     0x12560953       nbd_request              ``include/linux/nbd.h``
+RED_MAGIC2            0x170fc2a5       (any)                    ``mm/slab.c``
+BAYCOM_MAGIC          0x19730510       baycom_state             ``drivers/net/baycom_epp.c``
+ISDN_X25IFACE_MAGIC   0x1e75a2b9       isdn_x25iface_proto_data ``drivers/isdn/isdn_x25iface.h``
+ECP_MAGIC             0x21504345       cdkecpsig                ``include/linux/cdk.h``
+LSOMAGIC              0x27091997       lso                      ``drivers/fc4/fc.c``
+LSMAGIC               0x2a3b4d2a       ls                       ``drivers/fc4/fc.c``
+WANPIPE_MAGIC         0x414C4453       sdla_{dump,exec}         ``include/linux/wanpipe.h``
+CS_CARD_MAGIC         0x43525553       cs_card                  ``sound/oss/cs46xx.c``
+LABELCL_MAGIC         0x4857434c       labelcl_info_s           ``include/asm/ia64/sn/labelcl.h``
+ISDN_ASYNC_MAGIC      0x49344C01       modem_info               ``include/linux/isdn.h``
+CTC_ASYNC_MAGIC       0x49344C01       ctc_tty_info             ``drivers/s390/net/ctctty.c``
+ISDN_NET_MAGIC        0x49344C02       isdn_net_local_s         ``drivers/isdn/i4l/isdn_net_lib.h``
+SAVEKMSG_MAGIC2       0x4B4D5347       savekmsg                 ``arch/*/amiga/config.c``
+CS_STATE_MAGIC        0x4c4f4749       cs_state                 ``sound/oss/cs46xx.c``
+SLAB_C_MAGIC          0x4f17a36d       kmem_cache               ``mm/slab.c``
+COW_MAGIC             0x4f4f4f4d       cow_header_v1            ``arch/um/drivers/ubd_user.c``
+I810_CARD_MAGIC       0x5072696E       i810_card                ``sound/oss/i810_audio.c``
+TRIDENT_CARD_MAGIC    0x5072696E       trident_card             ``sound/oss/trident.c``
+ROUTER_MAGIC          0x524d4157       wan_device               [in ``wanrouter.h`` pre 3.9]
+SAVEKMSG_MAGIC1       0x53415645       savekmsg                 ``arch/*/amiga/config.c``
+GDA_MAGIC             0x58464552       gda                      ``arch/mips/include/asm/sn/gda.h``
+RED_MAGIC1            0x5a2cf071       (any)                    ``mm/slab.c``
+EEPROM_MAGIC_VALUE    0x5ab478d2       lanai_dev                ``drivers/atm/lanai.c``
+HDLCDRV_MAGIC         0x5ac6e778       hdlcdrv_state            ``include/linux/hdlcdrv.h``
+PCXX_MAGIC            0x5c6df104       channel                  ``drivers/char/pcxx.h``
+KV_MAGIC              0x5f4b565f       kernel_vars_s            ``arch/mips/include/asm/sn/klkernvars.h``
+I810_STATE_MAGIC      0x63657373       i810_state               ``sound/oss/i810_audio.c``
+TRIDENT_STATE_MAGIC   0x63657373       trient_state             ``sound/oss/trident.c``
+M3_CARD_MAGIC         0x646e6f50       m3_card                  ``sound/oss/maestro3.c``
+FW_HEADER_MAGIC       0x65726F66       fw_header                ``drivers/atm/fore200e.h``
+SLOT_MAGIC            0x67267321       slot                     ``drivers/hotplug/cpqphp.h``
+SLOT_MAGIC            0x67267322       slot                     ``drivers/hotplug/acpiphp.h``
+LO_MAGIC              0x68797548       nbd_device               ``include/linux/nbd.h``
+OPROFILE_MAGIC        0x6f70726f       super_block              ``drivers/oprofile/oprofilefs.h``
+M3_STATE_MAGIC        0x734d724d       m3_state                 ``sound/oss/maestro3.c``
+VMALLOC_MAGIC         0x87654320       snd_alloc_track          ``sound/core/memory.c``
+KMALLOC_MAGIC         0x87654321       snd_alloc_track          ``sound/core/memory.c``
+PWC_MAGIC             0x89DC10AB       pwc_device               ``drivers/usb/media/pwc.h``
+NBD_REPLY_MAGIC       0x96744668       nbd_reply                ``include/linux/nbd.h``
+ENI155_MAGIC          0xa54b872d       midway_eprom	        ``drivers/atm/eni.h``
+CODA_MAGIC            0xC0DAC0DA       coda_file_info           ``fs/coda/coda_fs_i.h``
+DPMEM_MAGIC           0xc0ffee11       gdt_pci_sram             ``drivers/scsi/gdth.h``
+YAM_MAGIC             0xF10A7654       yam_port                 ``drivers/net/hamradio/yam.c``
+CCB_MAGIC             0xf2691ad2       ccb                      ``drivers/scsi/ncr53c8xx.c``
+QUEUE_MAGIC_FREE      0xf7e1c9a3       queue_entry              ``drivers/scsi/arm/queue.c``
+QUEUE_MAGIC_USED      0xf7e1cc33       queue_entry              ``drivers/scsi/arm/queue.c``
+HTB_CMAGIC            0xFEFAFEF1       htb_class                ``net/sched/sch_htb.c``
+NMI_MAGIC             0x48414d4d455201 nmi_s                    ``arch/mips/include/asm/sn/nmi.h``
+===================== ================ ======================== ==========================================
+
+Note that there are also defined special per-driver magic numbers in sound
+memory management. See ``include/sound/sndmagic.h`` for complete list of them. Many
+OSS sound drivers have their magic numbers constructed from the soundcard PCI
+ID - these are not listed here as well.
+
+IrDA subsystem also uses large number of own magic numbers, see
+``include/net/irda/irda.h`` for a complete list of them.
+
+HFS is another larger user of magic numbers - you can find them in
+``fs/hfs/hfs.h``.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/management-style.rst linux-libre-4.10-rc8-gnu/Documentation/process/management-style.rst
--- linux-libre-4.9-gnu/Documentation/process/management-style.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/management-style.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,288 @@
+.. _managementstyle:
+
+Linux kernel management style
+=============================
+
+This is a short document describing the preferred (or made up, depending
+on who you ask) management style for the linux kernel.  It's meant to
+mirror the process/coding-style.rst document to some degree, and mainly written to
+avoid answering [#f1]_  the same (or similar) questions over and over again.
+
+Management style is very personal and much harder to quantify than
+simple coding style rules, so this document may or may not have anything
+to do with reality.  It started as a lark, but that doesn't mean that it
+might not actually be true. You'll have to decide for yourself.
+
+Btw, when talking about "kernel manager", it's all about the technical
+lead persons, not the people who do traditional management inside
+companies.  If you sign purchase orders or you have any clue about the
+budget of your group, you're almost certainly not a kernel manager.
+These suggestions may or may not apply to you.
+
+First off, I'd suggest buying "Seven Habits of Highly Effective
+People", and NOT read it.  Burn it, it's a great symbolic gesture.
+
+.. [#f1] This document does so not so much by answering the question, but by
+  making it painfully obvious to the questioner that we don't have a clue
+  to what the answer is.
+
+Anyway, here goes:
+
+.. _decisions:
+
+1) Decisions
+------------
+
+Everybody thinks managers make decisions, and that decision-making is
+important.  The bigger and more painful the decision, the bigger the
+manager must be to make it.  That's very deep and obvious, but it's not
+actually true.
+
+The name of the game is to **avoid** having to make a decision.  In
+particular, if somebody tells you "choose (a) or (b), we really need you
+to decide on this", you're in trouble as a manager.  The people you
+manage had better know the details better than you, so if they come to
+you for a technical decision, you're screwed.  You're clearly not
+competent to make that decision for them.
+
+(Corollary:if the people you manage don't know the details better than
+you, you're also screwed, although for a totally different reason.
+Namely that you are in the wrong job, and that **they** should be managing
+your brilliance instead).
+
+So the name of the game is to **avoid** decisions, at least the big and
+painful ones.  Making small and non-consequential decisions is fine, and
+makes you look like you know what you're doing, so what a kernel manager
+needs to do is to turn the big and painful ones into small things where
+nobody really cares.
+
+It helps to realize that the key difference between a big decision and a
+small one is whether you can fix your decision afterwards.  Any decision
+can be made small by just always making sure that if you were wrong (and
+you **will** be wrong), you can always undo the damage later by
+backtracking.  Suddenly, you get to be doubly managerial for making
+**two** inconsequential decisions - the wrong one **and** the right one.
+
+And people will even see that as true leadership (*cough* bullshit
+*cough*).
+
+Thus the key to avoiding big decisions becomes to just avoiding to do
+things that can't be undone.  Don't get ushered into a corner from which
+you cannot escape.  A cornered rat may be dangerous - a cornered manager
+is just pitiful.
+
+It turns out that since nobody would be stupid enough to ever really let
+a kernel manager have huge fiscal responsibility **anyway**, it's usually
+fairly easy to backtrack.  Since you're not going to be able to waste
+huge amounts of money that you might not be able to repay, the only
+thing you can backtrack on is a technical decision, and there
+back-tracking is very easy: just tell everybody that you were an
+incompetent nincompoop, say you're sorry, and undo all the worthless
+work you had people work on for the last year.  Suddenly the decision
+you made a year ago wasn't a big decision after all, since it could be
+easily undone.
+
+It turns out that some people have trouble with this approach, for two
+reasons:
+
+ - admitting you were an idiot is harder than it looks.  We all like to
+   maintain appearances, and coming out in public to say that you were
+   wrong is sometimes very hard indeed.
+ - having somebody tell you that what you worked on for the last year
+   wasn't worthwhile after all can be hard on the poor lowly engineers
+   too, and while the actual **work** was easy enough to undo by just
+   deleting it, you may have irrevocably lost the trust of that
+   engineer.  And remember: "irrevocable" was what we tried to avoid in
+   the first place, and your decision ended up being a big one after
+   all.
+
+Happily, both of these reasons can be mitigated effectively by just
+admitting up-front that you don't have a friggin' clue, and telling
+people ahead of the fact that your decision is purely preliminary, and
+might be the wrong thing.  You should always reserve the right to change
+your mind, and make people very **aware** of that.  And it's much easier
+to admit that you are stupid when you haven't **yet** done the really
+stupid thing.
+
+Then, when it really does turn out to be stupid, people just roll their
+eyes and say "Oops, he did it again".
+
+This preemptive admission of incompetence might also make the people who
+actually do the work also think twice about whether it's worth doing or
+not.  After all, if **they** aren't certain whether it's a good idea, you
+sure as hell shouldn't encourage them by promising them that what they
+work on will be included.  Make them at least think twice before they
+embark on a big endeavor.
+
+Remember: they'd better know more about the details than you do, and
+they usually already think they have the answer to everything.  The best
+thing you can do as a manager is not to instill confidence, but rather a
+healthy dose of critical thinking on what they do.
+
+Btw, another way to avoid a decision is to plaintively just whine "can't
+we just do both?" and look pitiful.  Trust me, it works.  If it's not
+clear which approach is better, they'll eventually figure it out.  The
+answer may end up being that both teams get so frustrated by the
+situation that they just give up.
+
+That may sound like a failure, but it's usually a sign that there was
+something wrong with both projects, and the reason the people involved
+couldn't decide was that they were both wrong.  You end up coming up
+smelling like roses, and you avoided yet another decision that you could
+have screwed up on.
+
+
+2) People
+---------
+
+Most people are idiots, and being a manager means you'll have to deal
+with it, and perhaps more importantly, that **they** have to deal with
+**you**.
+
+It turns out that while it's easy to undo technical mistakes, it's not
+as easy to undo personality disorders.  You just have to live with
+theirs - and yours.
+
+However, in order to prepare yourself as a kernel manager, it's best to
+remember not to burn any bridges, bomb any innocent villagers, or
+alienate too many kernel developers. It turns out that alienating people
+is fairly easy, and un-alienating them is hard. Thus "alienating"
+immediately falls under the heading of "not reversible", and becomes a
+no-no according to :ref:`decisions`.
+
+There's just a few simple rules here:
+
+ (1) don't call people d*ckheads (at least not in public)
+ (2) learn how to apologize when you forgot rule (1)
+
+The problem with #1 is that it's very easy to do, since you can say
+"you're a d*ckhead" in millions of different ways [#f2]_, sometimes without
+even realizing it, and almost always with a white-hot conviction that
+you are right.
+
+And the more convinced you are that you are right (and let's face it,
+you can call just about **anybody** a d*ckhead, and you often **will** be
+right), the harder it ends up being to apologize afterwards.
+
+To solve this problem, you really only have two options:
+
+ - get really good at apologies
+ - spread the "love" out so evenly that nobody really ends up feeling
+   like they get unfairly targeted.  Make it inventive enough, and they
+   might even be amused.
+
+The option of being unfailingly polite really doesn't exist. Nobody will
+trust somebody who is so clearly hiding his true character.
+
+.. [#f2] Paul Simon sang "Fifty Ways to Leave Your Lover", because quite
+  frankly, "A Million Ways to Tell a Developer He Is a D*ckhead" doesn't
+  scan nearly as well.  But I'm sure he thought about it.
+
+
+3) People II - the Good Kind
+----------------------------
+
+While it turns out that most people are idiots, the corollary to that is
+sadly that you are one too, and that while we can all bask in the secure
+knowledge that we're better than the average person (let's face it,
+nobody ever believes that they're average or below-average), we should
+also admit that we're not the sharpest knife around, and there will be
+other people that are less of an idiot than you are.
+
+Some people react badly to smart people.  Others take advantage of them.
+
+Make sure that you, as a kernel maintainer, are in the second group.
+Suck up to them, because they are the people who will make your job
+easier. In particular, they'll be able to make your decisions for you,
+which is what the game is all about.
+
+So when you find somebody smarter than you are, just coast along.  Your
+management responsibilities largely become ones of saying "Sounds like a
+good idea - go wild", or "That sounds good, but what about xxx?".  The
+second version in particular is a great way to either learn something
+new about "xxx" or seem **extra** managerial by pointing out something the
+smarter person hadn't thought about.  In either case, you win.
+
+One thing to look out for is to realize that greatness in one area does
+not necessarily translate to other areas.  So you might prod people in
+specific directions, but let's face it, they might be good at what they
+do, and suck at everything else.  The good news is that people tend to
+naturally gravitate back to what they are good at, so it's not like you
+are doing something irreversible when you **do** prod them in some
+direction, just don't push too hard.
+
+
+4) Placing blame
+----------------
+
+Things will go wrong, and people want somebody to blame. Tag, you're it.
+
+It's not actually that hard to accept the blame, especially if people
+kind of realize that it wasn't **all** your fault.  Which brings us to the
+best way of taking the blame: do it for another guy. You'll feel good
+for taking the fall, he'll feel good about not getting blamed, and the
+guy who lost his whole 36GB porn-collection because of your incompetence
+will grudgingly admit that you at least didn't try to weasel out of it.
+
+Then make the developer who really screwed up (if you can find him) know
+**in_private** that he screwed up.  Not just so he can avoid it in the
+future, but so that he knows he owes you one.  And, perhaps even more
+importantly, he's also likely the person who can fix it.  Because, let's
+face it, it sure ain't you.
+
+Taking the blame is also why you get to be manager in the first place.
+It's part of what makes people trust you, and allow you the potential
+glory, because you're the one who gets to say "I screwed up".  And if
+you've followed the previous rules, you'll be pretty good at saying that
+by now.
+
+
+5) Things to avoid
+------------------
+
+There's one thing people hate even more than being called "d*ckhead",
+and that is being called a "d*ckhead" in a sanctimonious voice.  The
+first you can apologize for, the second one you won't really get the
+chance.  They likely will no longer be listening even if you otherwise
+do a good job.
+
+We all think we're better than anybody else, which means that when
+somebody else puts on airs, it **really** rubs us the wrong way.  You may
+be morally and intellectually superior to everybody around you, but
+don't try to make it too obvious unless you really **intend** to irritate
+somebody [#f3]_.
+
+Similarly, don't be too polite or subtle about things. Politeness easily
+ends up going overboard and hiding the problem, and as they say, "On the
+internet, nobody can hear you being subtle". Use a big blunt object to
+hammer the point in, because you can't really depend on people getting
+your point otherwise.
+
+Some humor can help pad both the bluntness and the moralizing.  Going
+overboard to the point of being ridiculous can drive a point home
+without making it painful to the recipient, who just thinks you're being
+silly.  It can thus help get through the personal mental block we all
+have about criticism.
+
+.. [#f3] Hint: internet newsgroups that are not directly related to your work
+  are great ways to take out your frustrations at other people. Write
+  insulting posts with a sneer just to get into a good flame every once in
+  a while, and you'll feel cleansed. Just don't crap too close to home.
+
+
+6) Why me?
+----------
+
+Since your main responsibility seems to be to take the blame for other
+peoples mistakes, and make it painfully obvious to everybody else that
+you're incompetent, the obvious question becomes one of why do it in the
+first place?
+
+First off, while you may or may not get screaming teenage girls (or
+boys, let's not be judgmental or sexist here) knocking on your dressing
+room door, you **will** get an immense feeling of personal accomplishment
+for being "in charge".  Never mind the fact that you're really leading
+by trying to keep up with everybody else and running after them as fast
+as you can.  Everybody will still think you're the person in charge.
+
+It's a great job if you can hack it.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/stable-api-nonsense.rst linux-libre-4.10-rc8-gnu/Documentation/process/stable-api-nonsense.rst
--- linux-libre-4.9-gnu/Documentation/process/stable-api-nonsense.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/stable-api-nonsense.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,205 @@
+.. _stable_api_nonsense:
+
+The Linux Kernel Driver Interface
+==================================
+
+(all of your questions answered and then some)
+
+Greg Kroah-Hartman <greg@kroah.com>
+
+This is being written to try to explain why Linux **does not have a binary
+kernel interface, nor does it have a stable kernel interface**.
+
+.. note::
+
+  Please realize that this article describes the **in kernel** interfaces, not
+  the kernel to userspace interfaces.
+
+  The kernel to userspace interface is the one that application programs use,
+  the syscall interface.  That interface is **very** stable over time, and
+  will not break.  I have old programs that were built on a pre 0.9something
+  kernel that still work just fine on the latest 2.6 kernel release.
+  That interface is the one that users and application programmers can count
+  on being stable.
+
+
+Executive Summary
+-----------------
+You think you want a stable kernel interface, but you really do not, and
+you don't even know it.  What you want is a stable running driver, and
+you get that only if your driver is in the main kernel tree.  You also
+get lots of other good benefits if your driver is in the main kernel
+tree, all of which has made Linux into such a strong, stable, and mature
+operating system which is the reason you are using it in the first
+place.
+
+
+Intro
+-----
+
+It's only the odd person who wants to write a kernel driver that needs
+to worry about the in-kernel interfaces changing.  For the majority of
+the world, they neither see this interface, nor do they care about it at
+all.
+
+First off, I'm not going to address **any** legal issues about closed
+source, hidden source, binary blobs, source wrappers, or any other term
+that describes kernel drivers that do not have their source code
+released under the GPL.  Please consult a lawyer if you have any legal
+questions, I'm a programmer and hence, I'm just going to be describing
+the technical issues here (not to make light of the legal issues, they
+are real, and you do need to be aware of them at all times.)
+
+So, there are two main topics here, binary kernel interfaces and stable
+kernel source interfaces.  They both depend on each other, but we will
+discuss the binary stuff first to get it out of the way.
+
+
+Binary Kernel Interface
+-----------------------
+Assuming that we had a stable kernel source interface for the kernel, a
+binary interface would naturally happen too, right?  Wrong.  Please
+consider the following facts about the Linux kernel:
+
+  - Depending on the version of the C compiler you use, different kernel
+    data structures will contain different alignment of structures, and
+    possibly include different functions in different ways (putting
+    functions inline or not.)  The individual function organization
+    isn't that important, but the different data structure padding is
+    very important.
+
+  - Depending on what kernel build options you select, a wide range of
+    different things can be assumed by the kernel:
+
+      - different structures can contain different fields
+      - Some functions may not be implemented at all, (i.e. some locks
+	compile away to nothing for non-SMP builds.)
+      - Memory within the kernel can be aligned in different ways,
+	depending on the build options.
+
+  - Linux runs on a wide range of different processor architectures.
+    There is no way that binary drivers from one architecture will run
+    on another architecture properly.
+
+Now a number of these issues can be addressed by simply compiling your
+module for the exact specific kernel configuration, using the same exact
+C compiler that the kernel was built with.  This is sufficient if you
+want to provide a module for a specific release version of a specific
+Linux distribution.  But multiply that single build by the number of
+different Linux distributions and the number of different supported
+releases of the Linux distribution and you quickly have a nightmare of
+different build options on different releases.  Also realize that each
+Linux distribution release contains a number of different kernels, all
+tuned to different hardware types (different processor types and
+different options), so for even a single release you will need to create
+multiple versions of your module.
+
+Trust me, you will go insane over time if you try to support this kind
+of release, I learned this the hard way a long time ago...
+
+
+Stable Kernel Source Interfaces
+-------------------------------
+
+This is a much more "volatile" topic if you talk to people who try to
+keep a Linux kernel driver that is not in the main kernel tree up to
+date over time.
+
+Linux kernel development is continuous and at a rapid pace, never
+stopping to slow down.  As such, the kernel developers find bugs in
+current interfaces, or figure out a better way to do things.  If they do
+that, they then fix the current interfaces to work better.  When they do
+so, function names may change, structures may grow or shrink, and
+function parameters may be reworked.  If this happens, all of the
+instances of where this interface is used within the kernel are fixed up
+at the same time, ensuring that everything continues to work properly.
+
+As a specific examples of this, the in-kernel USB interfaces have
+undergone at least three different reworks over the lifetime of this
+subsystem.  These reworks were done to address a number of different
+issues:
+
+  - A change from a synchronous model of data streams to an asynchronous
+    one.  This reduced the complexity of a number of drivers and
+    increased the throughput of all USB drivers such that we are now
+    running almost all USB devices at their maximum speed possible.
+  - A change was made in the way data packets were allocated from the
+    USB core by USB drivers so that all drivers now needed to provide
+    more information to the USB core to fix a number of documented
+    deadlocks.
+
+This is in stark contrast to a number of closed source operating systems
+which have had to maintain their older USB interfaces over time.  This
+provides the ability for new developers to accidentally use the old
+interfaces and do things in improper ways, causing the stability of the
+operating system to suffer.
+
+In both of these instances, all developers agreed that these were
+important changes that needed to be made, and they were made, with
+relatively little pain.  If Linux had to ensure that it will preserve a
+stable source interface, a new interface would have been created, and
+the older, broken one would have had to be maintained over time, leading
+to extra work for the USB developers.  Since all Linux USB developers do
+their work on their own time, asking programmers to do extra work for no
+gain, for free, is not a possibility.
+
+Security issues are also very important for Linux.  When a
+security issue is found, it is fixed in a very short amount of time.  A
+number of times this has caused internal kernel interfaces to be
+reworked to prevent the security problem from occurring.  When this
+happens, all drivers that use the interfaces were also fixed at the
+same time, ensuring that the security problem was fixed and could not
+come back at some future time accidentally.  If the internal interfaces
+were not allowed to change, fixing this kind of security problem and
+insuring that it could not happen again would not be possible.
+
+Kernel interfaces are cleaned up over time.  If there is no one using a
+current interface, it is deleted.  This ensures that the kernel remains
+as small as possible, and that all potential interfaces are tested as
+well as they can be (unused interfaces are pretty much impossible to
+test for validity.)
+
+
+What to do
+----------
+
+So, if you have a Linux kernel driver that is not in the main kernel
+tree, what are you, a developer, supposed to do?  Releasing a binary
+driver for every different kernel version for every distribution is a
+nightmare, and trying to keep up with an ever changing kernel interface
+is also a rough job.
+
+Simple, get your kernel driver into the main kernel tree (remember we
+are talking about GPL released drivers here, if your code doesn't fall
+under this category, good luck, you are on your own here, you leech
+<insert link to leech comment from Andrew and Linus here>.)  If your
+driver is in the tree, and a kernel interface changes, it will be fixed
+up by the person who did the kernel change in the first place.  This
+ensures that your driver is always buildable, and works over time, with
+very little effort on your part.
+
+The very good side effects of having your driver in the main kernel tree
+are:
+
+  - The quality of the driver will rise as the maintenance costs (to the
+    original developer) will decrease.
+  - Other developers will add features to your driver.
+  - Other people will find and fix bugs in your driver.
+  - Other people will find tuning opportunities in your driver.
+  - Other people will update the driver for you when external interface
+    changes require it.
+  - The driver automatically gets shipped in all Linux distributions
+    without having to ask the distros to add it.
+
+As Linux supports a larger number of different devices "out of the box"
+than any other operating system, and it supports these devices on more
+different processor architectures than any other operating system, this
+proven type of development model must be doing something right :)
+
+
+
+------
+
+Thanks to Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan for their review and comments on
+early drafts of this paper.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/stable-kernel-rules.rst linux-libre-4.10-rc8-gnu/Documentation/process/stable-kernel-rules.rst
--- linux-libre-4.9-gnu/Documentation/process/stable-kernel-rules.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/stable-kernel-rules.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,181 @@
+.. _stable_kernel_rules:
+
+Everything you ever wanted to know about Linux -stable releases
+===============================================================
+
+Rules on what kind of patches are accepted, and which ones are not, into the
+"-stable" tree:
+
+ - It must be obviously correct and tested.
+ - It cannot be bigger than 100 lines, with context.
+ - It must fix only one thing.
+ - It must fix a real bug that bothers people (not a, "This could be a
+   problem..." type thing).
+ - It must fix a problem that causes a build error (but not for things
+   marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
+   security issue, or some "oh, that's not good" issue.  In short, something
+   critical.
+ - Serious issues as reported by a user of a distribution kernel may also
+   be considered if they fix a notable performance or interactivity issue.
+   As these fixes are not as obvious and have a higher risk of a subtle
+   regression they should only be submitted by a distribution kernel
+   maintainer and include an addendum linking to a bugzilla entry if it
+   exists and additional information on the user-visible impact.
+ - New device IDs and quirks are also accepted.
+ - No "theoretical race condition" issues, unless an explanation of how the
+   race can be exploited is also provided.
+ - It cannot contain any "trivial" fixes in it (spelling changes,
+   whitespace cleanups, etc).
+ - It must follow the
+   :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+   rules.
+ - It or an equivalent fix must already exist in Linus' tree (upstream).
+
+
+Procedure for submitting patches to the -stable tree
+----------------------------------------------------
+
+ - If the patch covers files in net/ or drivers/net please follow netdev stable
+   submission guidelines as described in
+   Documentation/networking/netdev-FAQ.txt
+ - Security patches should not be handled (solely) by the -stable review
+   process but should follow the procedures in
+   :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`.
+
+For all other submissions, choose one of the following procedures
+-----------------------------------------------------------------
+
+.. _option_1:
+
+Option 1
+********
+
+To have the patch automatically included in the stable tree, add the tag
+
+.. code-block:: none
+
+     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.
+
+.. _option_2:
+
+Option 2
+********
+
+After the patch has been merged to Linus' tree, send an email to
+stable@vger.kernel.org containing the subject of the patch, the commit ID,
+why you think it should be applied, and what kernel version you wish it to
+be applied to.
+
+.. _option_3:
+
+Option 3
+********
+
+Send the patch, after verifying that it follows the above rules, to
+stable@vger.kernel.org.  You must note the upstream commit ID in the
+changelog of your submission, as well as the kernel version you wish
+it to be applied to.
+
+:ref:`option_1` is **strongly** preferred, is the easiest and most common.
+:ref:`option_2` and :ref:`option_3` are more useful if the patch isn't deemed
+worthy at the time it is applied to a public git tree (for instance, because
+it deserves more regression testing first).  :ref:`option_3` is especially
+useful if the patch needs some special handling to apply to an older kernel
+(e.g., if API's have changed in the meantime).
+
+Note that for :ref:`option_3`, if the patch deviates from the original
+upstream patch (for example because it had to be backported) this must be very
+clearly documented and justified in the patch description.
+
+The upstream commit ID must be specified with a separate line above the commit
+text, like this:
+
+.. code-block:: none
+
+    commit <sha1> upstream.
+
+Additionally, some patches submitted via Option 1 may have additional patch
+prerequisites which can be cherry-picked. This can be specified in the following
+format in the sign-off area:
+
+.. code-block:: none
+
+     Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle
+     Cc: <stable@vger.kernel.org> # 3.3.x: 1b9508f: sched: Rate-limit newidle
+     Cc: <stable@vger.kernel.org> # 3.3.x: fd21073: sched: Fix affinity logic
+     Cc: <stable@vger.kernel.org> # 3.3.x
+     Signed-off-by: Ingo Molnar <mingo@elte.hu>
+
+The tag sequence has the meaning of:
+
+.. code-block:: none
+
+     git cherry-pick a1f84a3
+     git cherry-pick 1b9508f
+     git cherry-pick fd21073
+     git cherry-pick <this commit>
+
+Also, some patches may have kernel version prerequisites.  This can be
+specified in the following format in the sign-off area:
+
+.. code-block:: none
+
+     Cc: <stable@vger.kernel.org> # 3.3.x-
+
+The tag has the meaning of:
+
+.. code-block:: none
+
+     git cherry-pick <this commit>
+
+For each "-stable" tree starting with the specified version.
+
+Following the submission:
+
+ - The sender will receive an ACK when the patch has been accepted into the
+   queue, or a NAK if the patch is rejected.  This response might take a few
+   days, according to the developer's schedules.
+ - If accepted, the patch will be added to the -stable queue, for review by
+   other developers and by the relevant subsystem maintainer.
+
+
+Review cycle
+------------
+
+ - When the -stable maintainers decide for a review cycle, the patches will be
+   sent to the review committee, and the maintainer of the affected area of
+   the patch (unless the submitter is the maintainer of the area) and CC: to
+   the linux-kernel mailing list.
+ - The review committee has 48 hours in which to ACK or NAK the patch.
+ - If the patch is rejected by a member of the committee, or linux-kernel
+   members object to the patch, bringing up issues that the maintainers and
+   members did not realize, the patch will be dropped from the queue.
+ - At the end of the review cycle, the ACKed patches will be added to the
+   latest -stable release, and a new -stable release will happen.
+ - Security patches will be accepted into the -stable tree directly from the
+   security kernel team, and not go through the normal review cycle.
+   Contact the kernel security team for more details on this procedure.
+
+Trees
+-----
+
+ - The queues of patches, for both completed versions and in progress
+   versions can be found at:
+
+	http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git
+
+ - The finalized and tagged releases of all stable kernels can be found
+   in separate branches per version at:
+
+	http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git
+
+
+Review committee
+----------------
+
+ - This is made up of a number of kernel developers who have volunteered for
+   this task, and a few that haven't.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/submit-checklist.rst linux-libre-4.10-rc8-gnu/Documentation/process/submit-checklist.rst
--- linux-libre-4.9-gnu/Documentation/process/submit-checklist.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/submit-checklist.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,120 @@
+.. _submitchecklist:
+
+Linux Kernel patch submission checklist
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here are some basic things that developers should do if they want to see their
+kernel patch submissions accepted more quickly.
+
+These are all above and beyond the documentation that is provided in
+:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+and elsewhere regarding submitting Linux kernel patches.
+
+
+1) If you use a facility then #include the file that defines/declares
+   that facility.  Don't depend on other header files pulling in ones
+   that you use.
+
+2) Builds cleanly:
+
+  a) with applicable or modified ``CONFIG`` options ``=y``, ``=m``, and
+     ``=n``.  No ``gcc`` warnings/errors, no linker warnings/errors.
+
+  b) Passes ``allnoconfig``, ``allmodconfig``
+
+  c) Builds successfully when using ``O=builddir``
+
+3) Builds on multiple CPU architectures by using local cross-compile tools
+   or some other build farm.
+
+4) ppc64 is a good architecture for cross-compilation checking because it
+   tends to use ``unsigned long`` for 64-bit quantities.
+
+5) Check your patch for general style as detailed in
+   :ref:`Documentation/process/coding-style.rst <codingstyle>`.
+   Check for trivial violations with the patch style checker prior to
+   submission (``scripts/checkpatch.pl``).
+   You should be able to justify all violations that remain in
+   your patch.
+
+6) Any new or modified ``CONFIG`` options don't muck up the config menu.
+
+7) All new ``Kconfig`` options have help text.
+
+8) Has been carefully reviewed with respect to relevant ``Kconfig``
+   combinations.  This is very hard to get right with testing -- brainpower
+   pays off here.
+
+9) Check cleanly with sparse.
+
+10) Use ``make checkstack`` and ``make namespacecheck`` and fix any problems
+    that they find.
+
+    .. note::
+
+       ``checkstack`` does not point out problems explicitly,
+       but any one function that uses more than 512 bytes on the stack is a
+       candidate for change.
+
+11) Include :ref:`kernel-doc <kernel_doc>` to document global  kernel APIs.
+    (Not required for static functions, but OK there also.) Use
+    ``make htmldocs`` or ``make pdfdocs`` to check the
+    :ref:`kernel-doc <kernel_doc>` and fix any issues.
+
+12) Has been tested with ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
+    ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
+    ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
+    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` all
+    simultaneously enabled.
+
+13) Has been build- and runtime tested with and without ``CONFIG_SMP`` and
+    ``CONFIG_PREEMPT.``
+
+14) If the patch affects IO/Disk, etc: has been tested with and without
+    ``CONFIG_LBDAF.``
+
+15) All codepaths have been exercised with all lockdep features enabled.
+
+16) All new ``/proc`` entries are documented under ``Documentation/``
+
+17) All new kernel boot parameters are documented in
+    ``Documentation/admin-guide/kernel-parameters.rst``.
+
+18) All new module parameters are documented with ``MODULE_PARM_DESC()``
+
+19) All new userspace interfaces are documented in ``Documentation/ABI/``.
+    See ``Documentation/ABI/README`` for more information.
+    Patches that change userspace interfaces should be CCed to
+    linux-api@vger.kernel.org.
+
+20) Check that it all passes ``make headers_check``.
+
+21) Has been checked with injection of at least slab and page-allocation
+    failures.  See ``Documentation/fault-injection/``.
+
+    If the new code is substantial, addition of subsystem-specific fault
+    injection might be appropriate.
+
+22) Newly-added code has been compiled with ``gcc -W`` (use
+    ``make EXTRA_CFLAGS=-W``).  This will generate lots of noise, but is good
+    for finding bugs like "warning: comparison between signed and unsigned".
+
+23) Tested after it has been merged into the -mm patchset to make sure
+    that it still works with all of the other queued patches and various
+    changes in the VM, VFS, and other subsystems.
+
+24) All memory barriers {e.g., ``barrier()``, ``rmb()``, ``wmb()``} need a
+    comment in the source code that explains the logic of what they are doing
+    and why.
+
+25) If any ioctl's are added by the patch, then also update
+    ``Documentation/ioctl/ioctl-number.txt``.
+
+26) If your modified source code depends on or uses any of the kernel
+    APIs or features that are related to the following ``Kconfig`` symbols,
+    then test multiple builds with the related ``Kconfig`` symbols disabled
+    and/or ``=m`` (if that option is available) [not all of these at the
+    same time, just various/random combinations of them]:
+
+    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
+    ``CONFIG_NET``, ``CONFIG_INET=n`` (but latter with ``CONFIG_NET=y``).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/submitting-drivers.rst linux-libre-4.10-rc8-gnu/Documentation/process/submitting-drivers.rst
--- linux-libre-4.9-gnu/Documentation/process/submitting-drivers.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/submitting-drivers.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,191 @@
+.. _submittingdrivers:
+
+Submitting Drivers For The Linux Kernel
+=======================================
+
+This document is intended to explain how to submit device drivers to the
+various kernel trees. Note that if you are interested in video card drivers
+you should probably talk to XFree86 (http://www.xfree86.org/) and/or X.Org
+(http://x.org/) instead.
+
+.. note::
+
+   This document is old and has seen little maintenance in recent years; it
+   should probably be updated or, perhaps better, just deleted.  Most of
+   what is here can be found in the other development documents anyway.
+
+   Oh, and we don't really recommend submitting changes to XFree86 :)
+
+Also read the Documentation/process/submitting-patches.rst document.
+
+
+Allocating Device Numbers
+-------------------------
+
+Major and minor numbers for block and character devices are allocated
+by the Linux assigned name and number authority (currently this is
+Torben Mathiasen). The site is http://www.lanana.org/. This
+also deals with allocating numbers for devices that are not going to
+be submitted to the mainstream kernel.
+See Documentation/admin-guide/devices.rst for more information on this.
+
+If you don't use assigned numbers then when your device is submitted it will
+be given an assigned number even if that is different from values you may
+have shipped to customers before.
+
+Who To Submit Drivers To
+------------------------
+
+Linux 2.0:
+	No new drivers are accepted for this kernel tree.
+
+Linux 2.2:
+	No new drivers are accepted for this kernel tree.
+
+Linux 2.4:
+	If the code area has a general maintainer then please submit it to
+	the maintainer listed in MAINTAINERS in the kernel file. If the
+	maintainer does not respond or you cannot find the appropriate
+	maintainer then please contact Willy Tarreau <w@1wt.eu>.
+
+Linux 2.6 and upper:
+	The same rules apply as 2.4 except that you should follow linux-kernel
+	to track changes in API's. The final contact point for Linux 2.6+
+	submissions is Andrew Morton.
+
+What Criteria Determine Acceptance
+----------------------------------
+
+Licensing:
+		The code must be released to us under the
+		GNU General Public License. We don't insist on any kind
+		of exclusive GPL licensing, and if you wish the driver
+		to be useful to other communities such as BSD you may well
+		wish to release under multiple licenses.
+		See accepted licenses at include/linux/module.h
+
+Copyright:
+		The copyright owner must agree to use of GPL.
+		It's best if the submitter and copyright owner
+		are the same person/entity. If not, the name of
+		the person/entity authorizing use of GPL should be
+		listed in case it's necessary to verify the will of
+		the copyright owner.
+
+Interfaces:
+		If your driver uses existing interfaces and behaves like
+		other drivers in the same class it will be much more likely
+		to be accepted than if it invents gratuitous new ones.
+		If you need to implement a common API over Linux and NT
+		drivers do it in userspace.
+
+Code:
+		Please use the Linux style of code formatting as documented
+		in :ref:`Documentation/process/coding-style.rst <codingStyle>`.
+		If you have sections of code
+		that need to be in other formats, for example because they
+		are shared with a windows driver kit and you want to
+		maintain them just once separate them out nicely and note
+		this fact.
+
+Portability:
+		Pointers are not always 32bits, not all computers are little
+		endian, people do not all have floating point and you
+		shouldn't use inline x86 assembler in your driver without
+		careful thought. Pure x86 drivers generally are not popular.
+		If you only have x86 hardware it is hard to test portability
+		but it is easy to make sure the code can easily be made
+		portable.
+
+Clarity:
+		It helps if anyone can see how to fix the driver. It helps
+		you because you get patches not bug reports. If you submit a
+		driver that intentionally obfuscates how the hardware works
+		it will go in the bitbucket.
+
+PM support:
+		Since Linux is used on many portable and desktop systems, your
+		driver is likely to be used on such a system and therefore it
+		should support basic power management by implementing, if
+		necessary, the .suspend and .resume methods used during the
+		system-wide suspend and resume transitions.  You should verify
+		that your driver correctly handles the suspend and resume, but
+		if you are unable to ensure that, please at least define the
+		.suspend method returning the -ENOSYS ("Function not
+		implemented") error.  You should also try to make sure that your
+		driver uses as little power as possible when it's not doing
+		anything.  For the driver testing instructions see
+		Documentation/power/drivers-testing.txt and for a relatively
+		complete overview of the power management issues related to
+		drivers see Documentation/power/admin-guide/devices.rst .
+
+Control:
+		In general if there is active maintenance of a driver by
+		the author then patches will be redirected to them unless
+		they are totally obvious and without need of checking.
+		If you want to be the contact and update point for the
+		driver it is a good idea to state this in the comments,
+		and include an entry in MAINTAINERS for your driver.
+
+What Criteria Do Not Determine Acceptance
+-----------------------------------------
+
+Vendor:
+		Being the hardware vendor and maintaining the driver is
+		often a good thing. If there is a stable working driver from
+		other people already in the tree don't expect 'we are the
+		vendor' to get your driver chosen. Ideally work with the
+		existing driver author to build a single perfect driver.
+
+Author:
+		It doesn't matter if a large Linux company wrote the driver,
+		or you did. Nobody has any special access to the kernel
+		tree. Anyone who tells you otherwise isn't telling the
+		whole story.
+
+
+Resources
+---------
+
+Linux kernel master tree:
+	ftp.\ *country_code*\ .kernel.org:/pub/linux/kernel/...
+
+	where *country_code* == your country code, such as
+	**us**, **uk**, **fr**, etc.
+
+	http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git
+
+Linux kernel mailing list:
+	linux-kernel@vger.kernel.org
+	[mail majordomo@vger.kernel.org to subscribe]
+
+Linux Device Drivers, Third Edition (covers 2.6.10):
+	http://lwn.net/Kernel/LDD3/  (free version)
+
+LWN.net:
+	Weekly summary of kernel development activity - http://lwn.net/
+
+	2.6 API changes:
+
+		http://lwn.net/Articles/2.6-kernel-api/
+
+	Porting drivers from prior kernels to 2.6:
+
+		http://lwn.net/Articles/driver-porting/
+
+KernelNewbies:
+	Documentation and assistance for new kernel programmers
+
+		http://kernelnewbies.org/
+
+Linux USB project:
+	http://www.linux-usb.org/
+
+How to NOT write kernel driver by Arjan van de Ven:
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+Kernel Janitor:
+	http://kernelnewbies.org/KernelJanitors
+
+GIT, Fast Version Control System:
+	http://git-scm.com/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/submitting-patches.rst linux-libre-4.10-rc8-gnu/Documentation/process/submitting-patches.rst
--- linux-libre-4.9-gnu/Documentation/process/submitting-patches.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/submitting-patches.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,836 @@
+.. _submittingpatches:
+
+Submitting patches: the essential guide to getting your code into the kernel
+============================================================================
+
+For a person or company who wishes to submit a change to the Linux
+kernel, the process can sometimes be daunting if you're not familiar
+with "the system."  This text is a collection of suggestions which
+can greatly increase the chances of your change being accepted.
+
+This document contains a large number of suggestions in a relatively terse
+format.  For detailed information on how the kernel development process
+works, see :ref:`Documentation/process <development_process_main>`.
+Also, read :ref:`Documentation/process/submit-checklist.rst <submitchecklist>`
+for a list of items to check before
+submitting code.  If you are submitting a driver, also read
+:ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`;
+for device tree binding patches, read
+Documentation/devicetree/bindings/submitting-patches.txt.
+
+Many of these steps describe the default behavior of the ``git`` version
+control system; if you use ``git`` to prepare your patches, you'll find much
+of the mechanical work done for you, though you'll still need to prepare
+and document a sensible set of patches.  In general, use of ``git`` will make
+your life as a kernel developer easier.
+
+0) Obtain a current source tree
+-------------------------------
+
+If you do not have a repository with the current kernel source handy, use
+``git`` to obtain one.  You'll want to start with the mainline repository,
+which can be grabbed with::
+
+  git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+Note, however, that you may not want to develop against the mainline tree
+directly.  Most subsystem maintainers run their own trees and want to see
+patches prepared against those trees.  See the **T:** entry for the subsystem
+in the MAINTAINERS file to find that tree, or simply ask the maintainer if
+the tree is not listed there.
+
+It is still possible to download kernel releases via tarballs (as described
+in the next section), but that is the hard way to do kernel development.
+
+1) ``diff -up``
+---------------
+
+If you must generate your patches by hand, use ``diff -up`` or ``diff -uprN``
+to create patches.  Git generates patches in this form by default; if
+you're using ``git``, you can skip this section entirely.
+
+All changes to the Linux kernel occur in the form of patches, as
+generated by :manpage:`diff(1)`.  When creating your patch, make sure to
+create it in "unified diff" format, as supplied by the ``-u`` argument
+to :manpage:`diff(1)`.
+Also, please use the ``-p`` argument which shows which C function each
+change is in - that makes the resultant ``diff`` a lot easier to read.
+Patches should be based in the root kernel source directory,
+not in any lower subdirectory.
+
+To create a patch for a single file, it is often sufficient to do::
+
+	SRCTREE= linux
+	MYFILE=  drivers/net/mydriver.c
+
+	cd $SRCTREE
+	cp $MYFILE $MYFILE.orig
+	vi $MYFILE	# make your change
+	cd ..
+	diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+To create a patch for multiple files, you should unpack a "vanilla",
+or unmodified kernel source tree, and generate a ``diff`` against your
+own source tree.  For example::
+
+	MYSRC= /devel/linux
+
+	tar xvfz linux-3.19.tar.gz
+	mv linux-3.19 linux-3.19-vanilla
+	diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
+		linux-3.19-vanilla $MYSRC > /tmp/patch
+
+``dontdiff`` is a list of files which are generated by the kernel during
+the build process, and should be ignored in any :manpage:`diff(1)`-generated
+patch.
+
+Make sure your patch does not include any extra files which do not
+belong in a patch submission.  Make sure to review your patch -after-
+generating it with :manpage:`diff(1)`, to ensure accuracy.
+
+If your changes produce a lot of deltas, you need to split them into
+individual patches which modify things in logical stages; see
+:ref:`split_changes`.  This will facilitate review by other kernel developers,
+very important if you want your patch accepted.
+
+If you're using ``git``, ``git rebase -i`` can help you with this process.  If
+you're not using ``git``, ``quilt`` <http://savannah.nongnu.org/projects/quilt>
+is another popular alternative.
+
+.. _describe_changes:
+
+2) Describe your changes
+------------------------
+
+Describe your problem.  Whether your patch is a one-line bug fix or
+5000 lines of a new feature, there must be an underlying problem that
+motivated you to do this work.  Convince the reviewer that there is a
+problem worth fixing and that it makes sense for them to read past the
+first paragraph.
+
+Describe user-visible impact.  Straight up crashes and lockups are
+pretty convincing, but not all bugs are that blatant.  Even if the
+problem was spotted during code review, describe the impact you think
+it can have on users.  Keep in mind that the majority of Linux
+installations run kernels from secondary stable trees or
+vendor/product-specific trees that cherry-pick only specific patches
+from upstream, so include anything that could help route your change
+downstream: provoking circumstances, excerpts from dmesg, crash
+descriptions, performance regressions, latency spikes, lockups, etc.
+
+Quantify optimizations and trade-offs.  If you claim improvements in
+performance, memory consumption, stack footprint, or binary size,
+include numbers that back them up.  But also describe non-obvious
+costs.  Optimizations usually aren't free but trade-offs between CPU,
+memory, and readability; or, when it comes to heuristics, between
+different workloads.  Describe the expected downsides of your
+optimization so that the reviewer can weigh costs against benefits.
+
+Once the problem is established, describe what you are actually doing
+about it in technical detail.  It's important to describe the change
+in plain English for the reviewer to verify that the code is behaving
+as you intend it to.
+
+The maintainer will thank you if you write your patch description in a
+form which can be easily pulled into Linux's source code management
+system, ``git``, as a "commit log".  See :ref:`explicit_in_reply_to`.
+
+Solve only one problem per patch.  If your description starts to get
+long, that's a sign that you probably need to split up your patch.
+See :ref:`split_changes`.
+
+When you submit or resubmit a patch or patch series, include the
+complete patch description and justification for it.  Don't just
+say that this is version N of the patch (series).  Don't expect the
+subsystem maintainer to refer back to earlier patch versions or referenced
+URLs to find the patch description and put that into the patch.
+I.e., the patch (series) and its description should be self-contained.
+This benefits both the maintainers and reviewers.  Some reviewers
+probably didn't even receive earlier versions of the patch.
+
+Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
+instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
+to do frotz", as if you are giving orders to the codebase to change
+its behaviour.
+
+If the patch fixes a logged bug entry, refer to that bug entry by
+number and URL.  If the patch follows from a mailing list discussion,
+give a URL to the mailing list archive; use the https://lkml.kernel.org/
+redirector with a ``Message-Id``, to ensure that the links cannot become
+stale.
+
+However, try to make your explanation understandable without external
+resources.  In addition to giving a URL to a mailing list archive or
+bug, summarize the relevant points of the discussion that led to the
+patch as submitted.
+
+If you want to refer to a specific commit, don't just refer to the
+SHA-1 ID of the commit. Please also include the oneline summary of
+the commit, to make it easier for reviewers to know what it is about.
+Example::
+
+	Commit e21d2170f36602ae2708 ("video: remove unnecessary
+	platform_set_drvdata()") removed the unnecessary
+	platform_set_drvdata(), but left the variable "dev" unused,
+	delete it.
+
+You should also be sure to use at least the first twelve characters of the
+SHA-1 ID.  The kernel repository holds a *lot* of objects, making
+collisions with shorter IDs a real possibility.  Bear in mind that, even if
+there is no collision with your six-character ID now, that condition may
+change five years from now.
+
+If your patch fixes a bug in a specific commit, e.g. you found an issue using
+``git bisect``, please use the 'Fixes:' tag with the first 12 characters of
+the SHA-1 ID, and the one line summary.  For example::
+
+	Fixes: e21d2170f366 ("video: remove unnecessary platform_set_drvdata()")
+
+The following ``git config`` settings can be used to add a pretty format for
+outputting the above style in the ``git log`` or ``git show`` commands::
+
+	[core]
+		abbrev = 12
+	[pretty]
+		fixes = Fixes: %h (\"%s\")
+
+.. _split_changes:
+
+3) Separate your changes
+------------------------
+
+Separate each **logical change** into a separate patch.
+
+For example, if your changes include both bug fixes and performance
+enhancements for a single driver, separate those changes into two
+or more patches.  If your changes include an API update, and a new
+driver which uses that new API, separate those into two patches.
+
+On the other hand, if you make a single change to numerous files,
+group those changes into a single patch.  Thus a single logical change
+is contained within a single patch.
+
+The point to remember is that each patch should make an easily understood
+change that can be verified by reviewers.  Each patch should be justifiable
+on its own merits.
+
+If one patch depends on another patch in order for a change to be
+complete, that is OK.  Simply note **"this patch depends on patch X"**
+in your patch description.
+
+When dividing your change into a series of patches, take special care to
+ensure that the kernel builds and runs properly after each patch in the
+series.  Developers using ``git bisect`` to track down a problem can end up
+splitting your patch series at any point; they will not thank you if you
+introduce bugs in the middle.
+
+If you cannot condense your patch set into a smaller set of patches,
+then only post say 15 or so at a time and wait for review and integration.
+
+
+
+4) Style-check your changes
+---------------------------
+
+Check your patch for basic style violations, details of which can be
+found in
+:ref:`Documentation/process/coding-style.rst <codingstyle>`.
+Failure to do so simply wastes
+the reviewers time and will get your patch rejected, probably
+without even being read.
+
+One significant exception is when moving code from one file to
+another -- in this case you should not modify the moved code at all in
+the same patch which moves it.  This clearly delineates the act of
+moving the code and your changes.  This greatly aids review of the
+actual differences and allows tools to better track the history of
+the code itself.
+
+Check your patches with the patch style checker prior to submission
+(scripts/checkpatch.pl).  Note, though, that the style checker should be
+viewed as a guide, not as a replacement for human judgment.  If your code
+looks better with a violation then its probably best left alone.
+
+The checker reports at three levels:
+ - ERROR: things that are very likely to be wrong
+ - WARNING: things requiring careful review
+ - CHECK: things requiring thought
+
+You should be able to justify all violations that remain in your
+patch.
+
+
+5) Select the recipients for your patch
+---------------------------------------
+
+You should always copy the appropriate subsystem maintainer(s) on any patch
+to code that they maintain; look through the MAINTAINERS file and the
+source code revision history to see who those maintainers are.  The
+script scripts/get_maintainer.pl can be very useful at this step.  If you
+cannot find a maintainer for the subsystem you are working on, Andrew
+Morton (akpm@linux-foundation.org) serves as a maintainer of last resort.
+
+You should also normally choose at least one mailing list to receive a copy
+of your patch set.  linux-kernel@vger.kernel.org functions as a list of
+last resort, but the volume on that list has caused a number of developers
+to tune it out.  Look in the MAINTAINERS file for a subsystem-specific
+list; your patch will probably get more attention there.  Please do not
+spam unrelated lists, though.
+
+Many kernel-related lists are hosted on vger.kernel.org; you can find a
+list of them at http://vger.kernel.org/vger-lists.html.  There are
+kernel-related lists hosted elsewhere as well, though.
+
+Do not send more than 15 patches at once to the vger mailing lists!!!
+
+Linus Torvalds is the final arbiter of all changes accepted into the
+Linux kernel.  His e-mail address is <torvalds@linux-foundation.org>.
+He gets a lot of e-mail, and, at this point, very few patches go through
+Linus directly, so typically you should do your best to -avoid-
+sending him e-mail.
+
+If you have a patch that fixes an exploitable security bug, send that patch
+to security@kernel.org.  For severe bugs, a short embargo may be considered
+to allow distributors to get the patch out to users; in such cases,
+obviously, the patch should not be sent to any public lists.
+
+Patches that fix a severe bug in a released kernel should be directed
+toward the stable maintainers by putting a line like this::
+
+  Cc: stable@vger.kernel.org
+
+into the sign-off area of your patch (note, NOT an email recipient).  You
+should also read
+:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+in addition to this file.
+
+Note, however, that some subsystem maintainers want to come to their own
+conclusions on which patches should go to the stable trees.  The networking
+maintainer, in particular, would rather not see individual developers
+adding lines like the above to their patches.
+
+If changes affect userland-kernel interfaces, please send the MAN-PAGES
+maintainer (as listed in the MAINTAINERS file) a man-pages patch, or at
+least a notification of the change, so that some information makes its way
+into the manual pages.  User-space API changes should also be copied to
+linux-api@vger.kernel.org.
+
+For small patches you may want to CC the Trivial Patch Monkey
+trivial@kernel.org which collects "trivial" patches. Have a look
+into the MAINTAINERS file for its current manager.
+
+Trivial patches must qualify for one of the following rules:
+
+- Spelling fixes in documentation
+- Spelling fixes for errors which could break :manpage:`grep(1)`
+- Warning fixes (cluttering with useless warnings is bad)
+- Compilation fixes (only if they are actually correct)
+- Runtime fixes (only if they actually fix things)
+- Removing use of deprecated functions/macros
+- Contact detail and documentation fixes
+- Non-portable code replaced by portable code (even in arch-specific,
+  since people copy, as long as it's trivial)
+- Any fix by the author/maintainer of the file (ie. patch monkey
+  in re-transmission mode)
+
+
+
+6) No MIME, no links, no compression, no attachments.  Just plain text
+----------------------------------------------------------------------
+
+Linus and other kernel developers need to be able to read and comment
+on the changes you are submitting.  It is important for a kernel
+developer to be able to "quote" your changes, using standard e-mail
+tools, so that they may comment on specific portions of your code.
+
+For this reason, all patches should be submitted by e-mail "inline".
+
+.. warning::
+
+  Be wary of your editor's word-wrap corrupting your patch,
+  if you choose to cut-n-paste your patch.
+
+Do not attach the patch as a MIME attachment, compressed or not.
+Many popular e-mail applications will not always transmit a MIME
+attachment as plain text, making it impossible to comment on your
+code.  A MIME attachment also takes Linus a bit more time to process,
+decreasing the likelihood of your MIME-attached change being accepted.
+
+Exception:  If your mailer is mangling patches then someone may ask
+you to re-send them using MIME.
+
+See :ref:`Documentation/process/email-clients.rst <email_clients>`
+for hints about configuring your e-mail client so that it sends your patches
+untouched.
+
+7) E-mail size
+--------------
+
+Large changes are not appropriate for mailing lists, and some
+maintainers.  If your patch, uncompressed, exceeds 300 kB in size,
+it is preferred that you store your patch on an Internet-accessible
+server, and provide instead a URL (link) pointing to your patch.  But note
+that if your patch exceeds 300 kB, it almost certainly needs to be broken up
+anyway.
+
+8) Respond to review comments
+-----------------------------
+
+Your patch will almost certainly get comments from reviewers on ways in
+which the patch can be improved.  You must respond to those comments;
+ignoring reviewers is a good way to get ignored in return.  Review comments
+or questions that do not lead to a code change should almost certainly
+bring about a comment or changelog entry so that the next reviewer better
+understands what is going on.
+
+Be sure to tell the reviewers what changes you are making and to thank them
+for their time.  Code review is a tiring and time-consuming process, and
+reviewers sometimes get grumpy.  Even in that case, though, respond
+politely and address the problems they have pointed out.
+
+
+9) Don't get discouraged - or impatient
+---------------------------------------
+
+After you have submitted your change, be patient and wait.  Reviewers are
+busy people and may not get to your patch right away.
+
+Once upon a time, patches used to disappear into the void without comment,
+but the development process works more smoothly than that now.  You should
+receive comments within a week or so; if that does not happen, make sure
+that you have sent your patches to the right place.  Wait for a minimum of
+one week before resubmitting or pinging reviewers - possibly longer during
+busy times like merge windows.
+
+
+10) Include PATCH in the subject
+--------------------------------
+
+Due to high e-mail traffic to Linus, and to linux-kernel, it is common
+convention to prefix your subject line with [PATCH].  This lets Linus
+and other kernel developers more easily distinguish patches from other
+e-mail discussions.
+
+
+
+11) Sign your work — the Developer's Certificate of Origin
+----------------------------------------------------------
+
+To improve tracking of who did what, especially with patches that can
+percolate to their final resting place in the kernel through several
+layers of maintainers, we've introduced a "sign-off" procedure on
+patches that are being emailed around.
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right to
+pass it on as an open-source patch.  The rules are pretty simple: if you
+can certify the below:
+
+Developer's Certificate of Origin 1.1
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By making a contribution to this project, I certify that:
+
+        (a) The contribution was created in whole or in part by me and I
+            have the right to submit it under the open source license
+            indicated in the file; or
+
+        (b) The contribution is based upon previous work that, to the best
+            of my knowledge, is covered under an appropriate open source
+            license and I have the right under that license to submit that
+            work with modifications, whether created in whole or in part
+            by me, under the same open source license (unless I am
+            permitted to submit under a different license), as indicated
+            in the file; or
+
+        (c) The contribution was provided directly to me by some other
+            person who certified (a), (b) or (c) and I have not modified
+            it.
+
+        (d) I understand and agree that this project and the contribution
+            are public and that a record of the contribution (including all
+            personal information I submit with it, including my sign-off) is
+            maintained indefinitely and may be redistributed consistent with
+            this project or the open source license(s) involved.
+
+then you just add a line saying::
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+
+using your real name (sorry, no pseudonyms or anonymous contributions.)
+
+Some people also put extra tags at the end.  They'll just be ignored for
+now, but you can do this to mark internal company procedures or just
+point out some special detail about the sign-off.
+
+If you are a subsystem or branch maintainer, sometimes you need to slightly
+modify patches you receive in order to merge them, because the code is not
+exactly the same in your tree and the submitters'. If you stick strictly to
+rule (c), you should ask the submitter to rediff, but this is a totally
+counter-productive waste of time and energy. Rule (b) allows you to adjust
+the code, but then it is very impolite to change one submitter's code and
+make him endorse your bugs. To solve this problem, it is recommended that
+you add a line between the last Signed-off-by header and yours, indicating
+the nature of your changes. While there is nothing mandatory about this, it
+seems like prepending the description with your mail and/or name, all
+enclosed in square brackets, is noticeable enough to make it obvious that
+you are responsible for last-minute changes. Example::
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+This practice is particularly helpful if you maintain a stable branch and
+want at the same time to credit the author, track changes, merge the fix,
+and protect the submitter from complaints. Note that under no circumstances
+can you change the author's identity (the From header), as it is the one
+which appears in the changelog.
+
+Special note to back-porters: It seems to be a common and useful practice
+to insert an indication of the origin of a patch at the top of the commit
+message (just after the subject line) to facilitate tracking. For instance,
+here's what we see in a 3.x-stable release::
+
+  Date:   Tue Oct 7 07:26:38 2014 -0400
+
+    libata: Un-break ATA blacklist
+
+    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
+
+And here's what might appear in an older kernel once a patch is backported::
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+Whatever the format, this information provides a valuable help to people
+tracking your trees, and to people trying to troubleshoot bugs in your
+tree.
+
+
+12) When to use Acked-by: and Cc:
+---------------------------------
+
+The Signed-off-by: tag indicates that the signer was involved in the
+development of the patch, or that he/she was in the patch's delivery path.
+
+If a person was not directly involved in the preparation or handling of a
+patch but wishes to signify and record their approval of it then they can
+ask to have an Acked-by: line added to the patch's changelog.
+
+Acked-by: is often used by the maintainer of the affected code when that
+maintainer neither contributed to nor forwarded the patch.
+
+Acked-by: is not as formal as Signed-off-by:.  It is a record that the acker
+has at least reviewed the patch and has indicated acceptance.  Hence patch
+mergers will sometimes manually convert an acker's "yep, looks good to me"
+into an Acked-by: (but note that it is usually better to ask for an
+explicit ack).
+
+Acked-by: does not necessarily indicate acknowledgement of the entire patch.
+For example, if a patch affects multiple subsystems and has an Acked-by: from
+one subsystem maintainer then this usually indicates acknowledgement of just
+the part which affects that maintainer's code.  Judgement should be used here.
+When in doubt people should refer to the original discussion in the mailing
+list archives.
+
+If a person has had the opportunity to comment on a patch, but has not
+provided such comments, you may optionally add a ``Cc:`` tag to the patch.
+This is the only tag which might be added without an explicit action by the
+person it names - but it should indicate that this person was copied on the
+patch.  This tag documents that potentially interested parties
+have been included in the discussion.
+
+
+13) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes:
+--------------------------------------------------------------------------
+
+The Reported-by tag gives credit to people who find bugs and report them and it
+hopefully inspires them to help us again in the future.  Please note that if
+the bug was reported in private, then ask for permission first before using the
+Reported-by tag.
+
+A Tested-by: tag indicates that the patch has been successfully tested (in
+some environment) by the person named.  This tag informs maintainers that
+some testing has been performed, provides a means to locate testers for
+future patches, and ensures credit for the testers.
+
+Reviewed-by:, instead, indicates that the patch has been reviewed and found
+acceptable according to the Reviewer's Statement:
+
+Reviewer's statement of oversight
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+By offering my Reviewed-by: tag, I state that:
+
+	 (a) I have carried out a technical review of this patch to
+	     evaluate its appropriateness and readiness for inclusion into
+	     the mainline kernel.
+
+	 (b) Any problems, concerns, or questions relating to the patch
+	     have been communicated back to the submitter.  I am satisfied
+	     with the submitter's response to my comments.
+
+	 (c) While there may be things that could be improved with this
+	     submission, I believe that it is, at this time, (1) a
+	     worthwhile modification to the kernel, and (2) free of known
+	     issues which would argue against its inclusion.
+
+	 (d) While I have reviewed the patch and believe it to be sound, I
+	     do not (unless explicitly stated elsewhere) make any
+	     warranties or guarantees that it will achieve its stated
+	     purpose or function properly in any given situation.
+
+A Reviewed-by tag is a statement of opinion that the patch is an
+appropriate modification of the kernel without any remaining serious
+technical issues.  Any interested reviewer (who has done the work) can
+offer a Reviewed-by tag for a patch.  This tag serves to give credit to
+reviewers and to inform maintainers of the degree of review which has been
+done on the patch.  Reviewed-by: tags, when supplied by reviewers known to
+understand the subject area and to perform thorough reviews, will normally
+increase the likelihood of your patch getting into the kernel.
+
+A Suggested-by: tag indicates that the patch idea is suggested by the person
+named and ensures credit to the person for the idea. Please note that this
+tag should not be added without the reporter's permission, especially if the
+idea was not posted in a public forum. That said, if we diligently credit our
+idea reporters, they will, hopefully, be inspired to help us again in the
+future.
+
+A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
+is used to make it easy to determine where a bug originated, which can help
+review a bug fix. This tag also assists the stable kernel team in determining
+which stable kernel versions should receive your fix. This is the preferred
+method for indicating a bug fixed by the patch. See :ref:`describe_changes`
+for more details.
+
+
+14) The canonical patch format
+------------------------------
+
+This section describes how the patch itself should be formatted.  Note
+that, if you have your patches stored in a ``git`` repository, proper patch
+formatting can be had with ``git format-patch``.  The tools cannot create
+the necessary text, though, so read the instructions below anyway.
+
+The canonical patch subject line is::
+
+    Subject: [PATCH 001/123] subsystem: summary phrase
+
+The canonical patch message body contains the following:
+
+  - A ``from`` line specifying the patch author (only needed if the person
+    sending the patch is not the author).
+
+  - An empty line.
+
+  - The body of the explanation, line wrapped at 75 columns, which will
+    be copied to the permanent changelog to describe this patch.
+
+  - The ``Signed-off-by:`` lines, described above, which will
+    also go in the changelog.
+
+  - A marker line containing simply ``---``.
+
+  - Any additional comments not suitable for the changelog.
+
+  - The actual patch (``diff`` output).
+
+The Subject line format makes it very easy to sort the emails
+alphabetically by subject line - pretty much any email reader will
+support that - since because the sequence number is zero-padded,
+the numerical and alphabetic sort is the same.
+
+The ``subsystem`` in the email's Subject should identify which
+area or subsystem of the kernel is being patched.
+
+The ``summary phrase`` in the email's Subject should concisely
+describe the patch which that email contains.  The ``summary
+phrase`` should not be a filename.  Do not use the same ``summary
+phrase`` for every patch in a whole patch series (where a ``patch
+series`` is an ordered sequence of multiple, related patches).
+
+Bear in mind that the ``summary phrase`` of your email becomes a
+globally-unique identifier for that patch.  It propagates all the way
+into the ``git`` changelog.  The ``summary phrase`` may later be used in
+developer discussions which refer to the patch.  People will want to
+google for the ``summary phrase`` to read discussion regarding that
+patch.  It will also be the only thing that people may quickly see
+when, two or three months later, they are going through perhaps
+thousands of patches using tools such as ``gitk`` or ``git log
+--oneline``.
+
+For these reasons, the ``summary`` must be no more than 70-75
+characters, and it must describe both what the patch changes, as well
+as why the patch might be necessary.  It is challenging to be both
+succinct and descriptive, but that is what a well-written summary
+should do.
+
+The ``summary phrase`` may be prefixed by tags enclosed in square
+brackets: "Subject: [PATCH <tag>...] <summary phrase>".  The tags are
+not considered part of the summary phrase, but describe how the patch
+should be treated.  Common tags might include a version descriptor if
+the multiple versions of the patch have been sent out in response to
+comments (i.e., "v1, v2, v3"), or "RFC" to indicate a request for
+comments.  If there are four patches in a patch series the individual
+patches may be numbered like this: 1/4, 2/4, 3/4, 4/4.  This assures
+that developers understand the order in which the patches should be
+applied and that they have reviewed or applied all of the patches in
+the patch series.
+
+A couple of example Subjects::
+
+    Subject: [PATCH 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCH v2 01/27] x86: fix eflags tracking
+
+The ``from`` line must be the very first line in the message body,
+and has the form:
+
+        From: Original Author <author@example.com>
+
+The ``from`` line specifies who will be credited as the author of the
+patch in the permanent changelog.  If the ``from`` line is missing,
+then the ``From:`` line from the email header will be used to determine
+the patch author in the changelog.
+
+The explanation body will be committed to the permanent source
+changelog, so should make sense to a competent reader who has long
+since forgotten the immediate details of the discussion that might
+have led to this patch.  Including symptoms of the failure which the
+patch addresses (kernel log messages, oops messages, etc.) is
+especially useful for people who might be searching the commit logs
+looking for the applicable patch.  If a patch fixes a compile failure,
+it may not be necessary to include _all_ of the compile failures; just
+enough that it is likely that someone searching for the patch can find
+it.  As in the ``summary phrase``, it is important to be both succinct as
+well as descriptive.
+
+The ``---`` marker line serves the essential purpose of marking for patch
+handling tools where the changelog message ends.
+
+One good use for the additional comments after the ``---`` marker is for
+a ``diffstat``, to show what files have changed, and the number of
+inserted and deleted lines per file.  A ``diffstat`` is especially useful
+on bigger patches.  Other comments relevant only to the moment or the
+maintainer, not suitable for the permanent changelog, should also go
+here.  A good example of such comments might be ``patch changelogs``
+which describe what has changed between the v1 and v2 version of the
+patch.
+
+If you are going to include a ``diffstat`` after the ``---`` marker, please
+use ``diffstat`` options ``-p 1 -w 70`` so that filenames are listed from
+the top of the kernel source tree and don't use too much horizontal
+space (easily fit in 80 columns, maybe with some indentation).  (``git``
+generates appropriate diffstats by default.)
+
+See more details on the proper patch format in the following
+references.
+
+.. _explicit_in_reply_to:
+
+15) Explicit In-Reply-To headers
+--------------------------------
+
+It can be helpful to manually add In-Reply-To: headers to a patch
+(e.g., when using ``git send-email``) to associate the patch with
+previous relevant discussion, e.g. to link a bug fix to the email with
+the bug report.  However, for a multi-patch series, it is generally
+best to avoid using In-Reply-To: to link to older versions of the
+series.  This way multiple versions of the patch don't become an
+unmanageable forest of references in email clients.  If a link is
+helpful, you can use the https://lkml.kernel.org/ redirector (e.g., in
+the cover email text) to link to an earlier version of the patch series.
+
+
+16) Sending ``git pull`` requests
+---------------------------------
+
+If you have a series of patches, it may be most convenient to have the
+maintainer pull them directly into the subsystem repository with a
+``git pull`` operation.  Note, however, that pulling patches from a developer
+requires a higher degree of trust than taking patches from a mailing list.
+As a result, many subsystem maintainers are reluctant to take pull
+requests, especially from new, unknown developers.  If in doubt you can use
+the pull request as the cover letter for a normal posting of the patch
+series, giving the maintainer the option of using either.
+
+A pull request should have [GIT] or [PULL] in the subject line.  The
+request itself should include the repository name and the branch of
+interest on a single line; it should look something like::
+
+  Please pull from
+
+      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+  to get these changes:
+
+A pull request should also include an overall message saying what will be
+included in the request, a ``git shortlog`` listing of the patches
+themselves, and a ``diffstat`` showing the overall effect of the patch series.
+The easiest way to get all this information together is, of course, to let
+``git`` do it for you with the ``git request-pull`` command.
+
+Some maintainers (including Linus) want to see pull requests from signed
+commits; that increases their confidence that the request actually came
+from you.  Linus, in particular, will not pull from public hosting sites
+like GitHub in the absence of a signed tag.
+
+The first step toward creating such tags is to make a GNUPG key and get it
+signed by one or more core kernel developers.  This step can be hard for
+new developers, but there is no way around it.  Attending conferences can
+be a good way to find developers who can sign your key.
+
+Once you have prepared a patch series in ``git`` that you wish to have somebody
+pull, create a signed tag with ``git tag -s``.  This will create a new tag
+identifying the last commit in the series and containing a signature
+created with your private key.  You will also have the opportunity to add a
+changelog-style message to the tag; this is an ideal place to describe the
+effects of the pull request as a whole.
+
+If the tree the maintainer will be pulling from is not the repository you
+are working from, don't forget to push the signed tag explicitly to the
+public tree.
+
+When generating your pull request, use the signed tag as the target.  A
+command like this will do the trick::
+
+  git request-pull master git://my.public.tree/linux.git my-signed-tag
+
+
+References
+----------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/linux/maintainer.html>
+
+  <http://www.kroah.com/log/linux/maintainer-02.html>
+
+  <http://www.kroah.com/log/linux/maintainer-03.html>
+
+  <http://www.kroah.com/log/linux/maintainer-04.html>
+
+  <http://www.kroah.com/log/linux/maintainer-05.html>
+
+  <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lkml.org/lkml/2005/7/11/336>
+
+Kernel Documentation/process/coding-style.rst:
+  :ref:`Documentation/process/coding-style.rst <codingstyle>`
+
+Linus Torvalds's mail on the canonical patch format:
+  <http://lkml.org/lkml/2005/4/7/183>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+
+  http://halobates.de/on-submitting-patches.pdf
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/process/volatile-considered-harmful.rst linux-libre-4.10-rc8-gnu/Documentation/process/volatile-considered-harmful.rst
--- linux-libre-4.9-gnu/Documentation/process/volatile-considered-harmful.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/process/volatile-considered-harmful.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,125 @@
+
+.. _volatile_considered_harmful:
+
+Why the "volatile" type class should not be used
+------------------------------------------------
+
+C programmers have often taken volatile to mean that the variable could be
+changed outside of the current thread of execution; as a result, they are
+sometimes tempted to use it in kernel code when shared data structures are
+being used.  In other words, they have been known to treat volatile types
+as a sort of easy atomic variable, which they are not.  The use of volatile in
+kernel code is almost never correct; this document describes why.
+
+The key point to understand with regard to volatile is that its purpose is
+to suppress optimization, which is almost never what one really wants to
+do.  In the kernel, one must protect shared data structures against
+unwanted concurrent access, which is very much a different task.  The
+process of protecting against unwanted concurrency will also avoid almost
+all optimization-related problems in a more efficient way.
+
+Like volatile, the kernel primitives which make concurrent access to data
+safe (spinlocks, mutexes, memory barriers, etc.) are designed to prevent
+unwanted optimization.  If they are being used properly, there will be no
+need to use volatile as well.  If volatile is still necessary, there is
+almost certainly a bug in the code somewhere.  In properly-written kernel
+code, volatile can only serve to slow things down.
+
+Consider a typical block of kernel code::
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+If all the code follows the locking rules, the value of shared_data cannot
+change unexpectedly while the_lock is held.  Any other code which might
+want to play with that data will be waiting on the lock.  The spinlock
+primitives act as memory barriers - they are explicitly written to do so -
+meaning that data accesses will not be optimized across them.  So the
+compiler might think it knows what will be in shared_data, but the
+spin_lock() call, since it acts as a memory barrier, will force it to
+forget anything it knows.  There will be no optimization problems with
+accesses to that data.
+
+If shared_data were declared volatile, the locking would still be
+necessary.  But the compiler would also be prevented from optimizing access
+to shared_data _within_ the critical section, when we know that nobody else
+can be working with it.  While the lock is held, shared_data is not
+volatile.  When dealing with shared data, proper locking makes volatile
+unnecessary - and potentially harmful.
+
+The volatile storage class was originally meant for memory-mapped I/O
+registers.  Within the kernel, register accesses, too, should be protected
+by locks, but one also does not want the compiler "optimizing" register
+accesses within a critical section.  But, within the kernel, I/O memory
+accesses are always done through accessor functions; accessing I/O memory
+directly through pointers is frowned upon and does not work on all
+architectures.  Those accessors are written to prevent unwanted
+optimization, so, once again, volatile is unnecessary.
+
+Another situation where one might be tempted to use volatile is
+when the processor is busy-waiting on the value of a variable.  The right
+way to perform a busy wait is::
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+The cpu_relax() call can lower CPU power consumption or yield to a
+hyperthreaded twin processor; it also happens to serve as a compiler
+barrier, so, once again, volatile is unnecessary.  Of course, busy-
+waiting is generally an anti-social act to begin with.
+
+There are still a few rare situations where volatile makes sense in the
+kernel:
+
+  - The above-mentioned accessor functions might use volatile on
+    architectures where direct I/O memory access does work.  Essentially,
+    each accessor call becomes a little critical section on its own and
+    ensures that the access happens as expected by the programmer.
+
+  - Inline assembly code which changes memory, but which has no other
+    visible side effects, risks being deleted by GCC.  Adding the volatile
+    keyword to asm statements will prevent this removal.
+
+  - The jiffies variable is special in that it can have a different value
+    every time it is referenced, but it can be read without any special
+    locking.  So jiffies can be volatile, but the addition of other
+    variables of this type is strongly frowned upon.  Jiffies is considered
+    to be a "stupid legacy" issue (Linus's words) in this regard; fixing it
+    would be more trouble than it is worth.
+
+  - Pointers to data structures in coherent memory which might be modified
+    by I/O devices can, sometimes, legitimately be volatile.  A ring buffer
+    used by a network adapter, where that adapter changes pointers to
+    indicate which descriptors have been processed, is an example of this
+    type of situation.
+
+For most code, none of the above justifications for volatile apply.  As a
+result, the use of volatile is likely to be seen as a bug and will bring
+additional scrutiny to the code.  Developers who are tempted to use
+volatile should take a step back and think about what they are truly trying
+to accomplish.
+
+Patches to remove volatile variables are generally welcome - as long as
+they come with a justification which shows that the concurrency issues have
+been properly thought through.
+
+
+References
+==========
+
+[1] http://lwn.net/Articles/233481/
+
+[2] http://lwn.net/Articles/233482/
+
+Credits
+=======
+
+Original impetus and research by Randy Dunlap
+
+Written by Jonathan Corbet
+
+Improvements via comments from Satyam Sharma, Johannes Stezenbach, Jesper
+Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
+Richter.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/ramoops.txt linux-libre-4.10-rc8-gnu/Documentation/ramoops.txt
--- linux-libre-4.9-gnu/Documentation/ramoops.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/ramoops.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,146 +0,0 @@
-Ramoops oops/panic logger
-=========================
-
-Sergiu Iordache <sergiu@chromium.org>
-
-Updated: 17 November 2011
-
-0. Introduction
-
-Ramoops is an oops/panic logger that writes its logs to RAM before the system
-crashes. It works by logging oopses and panics in a circular buffer. Ramoops
-needs a system with persistent RAM so that the content of that area can
-survive after a restart.
-
-1. Ramoops concepts
-
-Ramoops uses a predefined memory area to store the dump. The start and size
-and type of the memory area are set using three variables:
-  * "mem_address" for the start
-  * "mem_size" for the size. The memory size will be rounded down to a
-  power of two.
-  * "mem_type" to specifiy if the memory type (default is pgprot_writecombine).
-
-Typically the default value of mem_type=0 should be used as that sets the pstore
-mapping to pgprot_writecombine. Setting mem_type=1 attempts to use
-pgprot_noncached, which only works on some platforms. This is because pstore
-depends on atomic operations. At least on ARM, pgprot_noncached causes the
-memory to be mapped strongly ordered, and atomic operations on strongly ordered
-memory are implementation defined, and won't work on many ARMs such as omaps.
-
-The memory area is divided into "record_size" chunks (also rounded down to
-power of two) and each oops/panic writes a "record_size" chunk of
-information.
-
-Dumping both oopses and panics can be done by setting 1 in the "dump_oops"
-variable while setting 0 in that variable dumps only the panics.
-
-The module uses a counter to record multiple dumps but the counter gets reset
-on restart (i.e. new dumps after the restart will overwrite old ones).
-
-Ramoops also supports software ECC protection of persistent memory regions.
-This might be useful when a hardware reset was used to bring the machine back
-to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat
-corrupt, but usually it is restorable.
-
-2. Setting the parameters
-
-Setting the ramoops parameters can be done in several different manners:
-
- A. Use the module parameters (which have the names of the variables described
- as before). For quick debugging, you can also reserve parts of memory during
- boot and then use the reserved memory for ramoops. For example, assuming a
- machine with > 128 MB of memory, the following kernel command line will tell
- the kernel to use only the first 128 MB of memory, and place ECC-protected
- ramoops region at 128 MB boundary:
- "mem=128M ramoops.mem_address=0x8000000 ramoops.ecc=1"
-
- B. Use Device Tree bindings, as described in
- Documentation/device-tree/bindings/reserved-memory/ramoops.txt.
- For example:
-
-	reserved-memory {
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
-
-		ramoops@8f000000 {
-			compatible = "ramoops";
-			reg = <0 0x8f000000 0 0x100000>;
-			record-size = <0x4000>;
-			console-size = <0x4000>;
-		};
-	};
-
- C. Use a platform device and set the platform data. The parameters can then
- be set through that platform data. An example of doing that is:
-
-#include <linux/pstore_ram.h>
-[...]
-
-static struct ramoops_platform_data ramoops_data = {
-        .mem_size               = <...>,
-        .mem_address            = <...>,
-        .mem_type               = <...>,
-        .record_size            = <...>,
-        .dump_oops              = <...>,
-        .ecc                    = <...>,
-};
-
-static struct platform_device ramoops_dev = {
-        .name = "ramoops",
-        .dev = {
-                .platform_data = &ramoops_data,
-        },
-};
-
-[... inside a function ...]
-int ret;
-
-ret = platform_device_register(&ramoops_dev);
-if (ret) {
-	printk(KERN_ERR "unable to register platform device\n");
-	return ret;
-}
-
-You can specify either RAM memory or peripheral devices' memory. However, when
-specifying RAM, be sure to reserve the memory by issuing memblock_reserve()
-very early in the architecture code, e.g.:
-
-#include <linux/memblock.h>
-
-memblock_reserve(ramoops_data.mem_address, ramoops_data.mem_size);
-
-3. Dump format
-
-The data dump begins with a header, currently defined as "====" followed by a
-timestamp and a new line. The dump then continues with the actual data.
-
-4. Reading the data
-
-The dump data can be read from the pstore filesystem. The format for these
-files is "dmesg-ramoops-N", where N is the record number in memory. To delete
-a stored record from RAM, simply unlink the respective pstore file.
-
-5. Persistent function tracing
-
-Persistent function tracing might be useful for debugging software or hardware
-related hangs. The functions call chain log is stored in a "ftrace-ramoops"
-file. Here is an example of usage:
-
- # mount -t debugfs debugfs /sys/kernel/debug/
- # echo 1 > /sys/kernel/debug/pstore/record_ftrace
- # reboot -f
- [...]
- # mount -t pstore pstore /mnt/
- # tail /mnt/ftrace-ramoops
- 0 ffffffff8101ea64  ffffffff8101bcda  native_apic_mem_read <- disconnect_bsp_APIC+0x6a/0xc0
- 0 ffffffff8101ea44  ffffffff8101bcf6  native_apic_mem_write <- disconnect_bsp_APIC+0x86/0xc0
- 0 ffffffff81020084  ffffffff8101a4b5  hpet_disable <- native_machine_shutdown+0x75/0x90
- 0 ffffffff81005f94  ffffffff8101a4bb  iommu_shutdown_noop <- native_machine_shutdown+0x7b/0x90
- 0 ffffffff8101a6a1  ffffffff8101a437  native_machine_emergency_restart <- native_machine_restart+0x37/0x40
- 0 ffffffff811f9876  ffffffff8101a73a  acpi_reboot <- native_machine_emergency_restart+0xaa/0x1e0
- 0 ffffffff8101a514  ffffffff8101a772  mach_reboot_fixups <- native_machine_emergency_restart+0xe2/0x1e0
- 0 ffffffff811d9c54  ffffffff8101a7a0  __const_udelay <- native_machine_emergency_restart+0x110/0x1e0
- 0 ffffffff811d9c34  ffffffff811d9c80  __delay <- __const_udelay+0x30/0x40
- 0 ffffffff811d9d14  ffffffff811d9c3f  delay_tsc <- __delay+0xf/0x20
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/RCU/Design/Requirements/Requirements.html linux-libre-4.10-rc8-gnu/Documentation/RCU/Design/Requirements/Requirements.html
--- linux-libre-4.9-gnu/Documentation/RCU/Design/Requirements/Requirements.html	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/RCU/Design/Requirements/Requirements.html	2017-02-12 16:03:20.000000000 -0500
@@ -547,7 +547,7 @@ The <tt>rcu_access_pointer()</tt> on lin
 	It could reuse a value formerly fetched from this same pointer.
 	It could also fetch the pointer from <tt>gp</tt> in a byte-at-a-time
 	manner, resulting in <i>load tearing</i>, in turn resulting a bytewise
-	mash-up of two distince pointer values.
+	mash-up of two distinct pointer values.
 	It might even use value-speculation optimizations, where it makes
 	a wrong guess, but by the time it gets around to checking the
 	value, an update has changed the pointer to match the wrong guess.
@@ -659,6 +659,29 @@ systems with more than one CPU:
 	In other words, a given instance of <tt>synchronize_rcu()</tt>
 	can avoid waiting on a given RCU read-side critical section only
 	if it can prove that <tt>synchronize_rcu()</tt> started first.
+
+	<p>
+	A related question is &ldquo;When <tt>rcu_read_lock()</tt>
+	doesn't generate any code, why does it matter how it relates
+	to a grace period?&rdquo;
+	The answer is that it is not the relationship of
+	<tt>rcu_read_lock()</tt> itself that is important, but rather
+	the relationship of the code within the enclosed RCU read-side
+	critical section to the code preceding and following the
+	grace period.
+	If we take this viewpoint, then a given RCU read-side critical
+	section begins before a given grace period when some access
+	preceding the grace period observes the effect of some access
+	within the critical section, in which case none of the accesses
+	within the critical section may observe the effects of any
+	access following the grace period.
+
+	<p>
+	As of late 2016, mathematical models of RCU take this
+	viewpoint, for example, see slides&nbsp;62 and&nbsp;63
+	of the
+	<a href="http://www2.rdrop.com/users/paulmck/scalability/paper/LinuxMM.2016.10.04c.LCE.pdf">2016 LinuxCon EU</a>
+	presentation.
 </font></td></tr>
 <tr><td>&nbsp;</td></tr>
 </table>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/RCU/whatisRCU.txt linux-libre-4.10-rc8-gnu/Documentation/RCU/whatisRCU.txt
--- linux-libre-4.9-gnu/Documentation/RCU/whatisRCU.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/RCU/whatisRCU.txt	2017-02-12 16:03:20.000000000 -0500
@@ -237,7 +237,7 @@ rcu_dereference()
 
 	The reader uses rcu_dereference() to fetch an RCU-protected
 	pointer, which returns a value that may then be safely
-	dereferenced.  Note that rcu_deference() does not actually
+	dereferenced.  Note that rcu_dereference() does not actually
 	dereference the pointer, instead, it protects the pointer for
 	later dereferencing.  It also executes any needed memory-barrier
 	instructions for a given CPU architecture.  Currently, only Alpha
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/rfkill.txt linux-libre-4.10-rc8-gnu/Documentation/rfkill.txt
--- linux-libre-4.9-gnu/Documentation/rfkill.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/rfkill.txt	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@ whether they can be changed or not:
                the system software.
 
 The rfkill subsystem has two parameters, rfkill.default_state and
-rfkill.master_switch_mode, which are documented in kernel-parameters.txt.
+rfkill.master_switch_mode, which are documented in admin-guide/kernel-parameters.rst.
 
 
 2. Implementation details
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/scheduler/completion.txt linux-libre-4.10-rc8-gnu/Documentation/scheduler/completion.txt
--- linux-libre-4.9-gnu/Documentation/scheduler/completion.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/scheduler/completion.txt	2017-02-12 16:03:20.000000000 -0500
@@ -25,8 +25,7 @@ struct completion that tells the waiting
 can continue safely.
 
 As completions are scheduling related, the code is found in
-kernel/sched/completion.c - for details on completion design and
-implementation see completions-design.txt
+kernel/sched/completion.c.
 
 
 Usage:
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/scsi/g_NCR5380.txt linux-libre-4.10-rc8-gnu/Documentation/scsi/g_NCR5380.txt
--- linux-libre-4.9-gnu/Documentation/scsi/g_NCR5380.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/scsi/g_NCR5380.txt	2017-02-12 16:03:20.000000000 -0500
@@ -6,17 +6,15 @@ NCR53c400 extensions (c) 1994,1995,1996
 This file documents the NCR53c400 extensions by Kevin Lentin and some
 enhancements to the NCR5380 core.
 
-This driver supports both NCR5380 and NCR53c400 cards in port or memory
-mapped modes. Currently this driver can only support one of those mapping
-modes at a time but it does support both of these chips at the same time.
-The next release of this driver will support port & memory mapped cards at
-the same time. It should be able to handle multiple different cards in the
-same machine.
+This driver supports NCR5380 and NCR53c400 and compatible cards in port or
+memory mapped modes.
 
-The drivers/scsi/Makefile has an override in it for the most common
-NCR53c400 card, the Trantor T130B in its default configuration:
-	Port: 0x350
-	IRQ : 5
+Use of an interrupt is recommended, if supported by the board, as this will
+allow targets to disconnect and thereby improve SCSI bus utilization.
+
+If the irq parameter is 254 or is omitted entirely, the driver will probe
+for the correct IRQ line automatically. If the irq parameter is 0 or 255
+then no IRQ will be used.
 
 The NCR53c400 does not support DMA but it does have Pseudo-DMA which is
 supported by the driver.
@@ -47,22 +45,24 @@ These old-style parameters can support o
   dtc_3181e=1  to set up for a Domex Technology Corp 3181E board
   hp_c2502=1   to set up for a Hewlett Packard C2502 board
 
-e.g.
-OLD: modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_5380=1
-NEW: modprobe g_NCR5380 irq=5 base=0x350 card=0
-  for a port mapped NCR5380 board or
-
-OLD: modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
-NEW: modprobe g_NCR5380 irq=255 base=0xc8000 card=1
-  for a memory mapped NCR53C400 board with interrupts disabled or
+E.g. Trantor T130B in its default configuration:
+modprobe g_NCR5380 irq=5 base=0x350 card=1
+or alternatively, using the old syntax,
+modprobe g_NCR5380 ncr_irq=5 ncr_addr=0x350 ncr_53c400=1
 
-NEW: modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4
-  for two cards: DTC3181 (in non-PnP mode) at 0x240 with no IRQ
-             and HP C2502 at 0x300 with IRQ 7
+E.g. a port mapped NCR5380 board, driver to probe for IRQ:
+modprobe g_NCR5380 base=0x350 card=0
+or alternatively,
+modprobe g_NCR5380 ncr_addr=0x350 ncr_5380=1
 
-(255 should be specified for no or DMA interrupt, 254 to autoprobe for an 
-     IRQ line if overridden on the command line.)
+E.g. a memory mapped NCR53C400 board with no IRQ:
+modprobe g_NCR5380 irq=255 base=0xc8000 card=1
+or alternatively,
+modprobe g_NCR5380 ncr_irq=255 ncr_addr=0xc8000 ncr_53c400=1
 
+E.g. two cards, DTC3181 (in non-PnP mode) at 0x240 with no IRQ
+and HP C2502 at 0x300 with IRQ 7:
+modprobe g_NCR5380 irq=0,7 base=0x240,0x300 card=3,4
 
 Kevin Lentin
 K.Lentin@cs.monash.edu.au
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/scsi/scsi_mid_low_api.txt linux-libre-4.10-rc8-gnu/Documentation/scsi/scsi_mid_low_api.txt
--- linux-libre-4.9-gnu/Documentation/scsi/scsi_mid_low_api.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/scsi/scsi_mid_low_api.txt	2017-02-12 16:03:20.000000000 -0500
@@ -336,7 +336,7 @@ in parallel by these functions.
 Conventions
 ===========
 First, Linus Torvalds's thoughts on C coding style can be found in the
-Documentation/CodingStyle file. 
+Documentation/process/coding-style.rst file.
 
 Next, there is a movement to "outlaw" typedefs introducing synonyms for 
 struct tags. Both can be still found in the SCSI subsystem, but
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/scsi/scsi-parameters.txt linux-libre-4.10-rc8-gnu/Documentation/scsi/scsi-parameters.txt
--- linux-libre-4.9-gnu/Documentation/scsi/scsi-parameters.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/scsi/scsi-parameters.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
                           SCSI Kernel Parameters
                           ~~~~~~~~~~~~~~~~~~~~~~
 
-See Documentation/kernel-parameters.txt for general information on
+See Documentation/admin-guide/kernel-parameters.rst for general information on
 specifying module parameters.
 
 This document may not be entirely up to date and comprehensive. The command
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/scsi/sym53c8xx_2.txt linux-libre-4.10-rc8-gnu/Documentation/scsi/sym53c8xx_2.txt
--- linux-libre-4.9-gnu/Documentation/scsi/sym53c8xx_2.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/scsi/sym53c8xx_2.txt	2017-02-12 16:03:20.000000000 -0500
@@ -427,7 +427,7 @@ Synchronous transfers frequency       (d
 10.1 Syntax
 
 Setup commands can be passed to the driver either at boot time or as
-parameters to modprobe, as described in Documentation/kernel-parameters.txt
+parameters to modprobe, as described in Documentation/admin-guide/kernel-parameters.rst
 
 Example of boot setup command under lilo prompt:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/security/conf.py linux-libre-4.10-rc8-gnu/Documentation/security/conf.py
--- linux-libre-4.9-gnu/Documentation/security/conf.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/security/conf.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+project = "The kernel security subsystem manual"
+
+tags.add("subproject")
+
+latex_documents = [
+    ('index', 'security.tex', project,
+     'The kernel development community', 'manual'),
+]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/security/index.rst linux-libre-4.10-rc8-gnu/Documentation/security/index.rst
--- linux-libre-4.9-gnu/Documentation/security/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/security/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+======================
+Security documentation
+======================
+
+.. toctree::
+
+   tpm/index
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/security/keys-trusted-encrypted.txt linux-libre-4.10-rc8-gnu/Documentation/security/keys-trusted-encrypted.txt
--- linux-libre-4.9-gnu/Documentation/security/keys-trusted-encrypted.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/security/keys-trusted-encrypted.txt	2017-02-12 16:03:20.000000000 -0500
@@ -32,8 +32,6 @@ Usage:
                      (40 ascii zeros)
        blobauth=     ascii hex auth for sealed data default 0x00...
                      (40 ascii zeros)
-       blobauth=     ascii hex auth for sealed data default 0x00...
-                     (40 ascii zeros)
        pcrinfo=	     ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
        pcrlock=	     pcr number to be extended to "lock" blob
        migratable=   0|1 indicating permission to reseal to new PCR values,
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/security/tpm/index.rst linux-libre-4.10-rc8-gnu/Documentation/security/tpm/index.rst
--- linux-libre-4.9-gnu/Documentation/security/tpm/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/security/tpm/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+=====================================
+Trusted Platform Module documentation
+=====================================
+
+.. toctree::
+
+   tpm_vtpm_proxy
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/security/tpm/tpm_vtpm_proxy.rst linux-libre-4.10-rc8-gnu/Documentation/security/tpm/tpm_vtpm_proxy.rst
--- linux-libre-4.9-gnu/Documentation/security/tpm/tpm_vtpm_proxy.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/security/tpm/tpm_vtpm_proxy.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,50 @@
+=============================================
+Virtual TPM Proxy Driver for Linux Containers
+=============================================
+
+| Authors:
+| Stefan Berger <stefanb@linux.vnet.ibm.com>
+
+This document describes the virtual Trusted Platform Module (vTPM)
+proxy device driver for Linux containers.
+
+Introduction
+============
+
+The goal of this work is to provide TPM functionality to each Linux
+container. This allows programs to interact with a TPM in a container
+the same way they interact with a TPM on the physical system. Each
+container gets its own unique, emulated, software TPM.
+
+Design
+======
+
+To make an emulated software TPM available to each container, the container
+management stack needs to create a device pair consisting of a client TPM
+character device ``/dev/tpmX`` (with X=0,1,2...) and a 'server side' file
+descriptor. The former is moved into the container by creating a character
+device with the appropriate major and minor numbers while the file descriptor
+is passed to the TPM emulator. Software inside the container can then send
+TPM commands using the character device and the emulator will receive the
+commands via the file descriptor and use it for sending back responses.
+
+To support this, the virtual TPM proxy driver provides a device ``/dev/vtpmx``
+that is used to create device pairs using an ioctl. The ioctl takes as
+an input flags for configuring the device. The flags  for example indicate
+whether TPM 1.2 or TPM 2 functionality is supported by the TPM emulator.
+The result of the ioctl are the file descriptor for the 'server side'
+as well as the major and minor numbers of the character device that was created.
+Besides that the number of the TPM character device is returned. If for
+example ``/dev/tpm10`` was created, the number (``dev_num``) 10 is returned.
+
+Once the device has been created, the driver will immediately try to talk
+to the TPM. All commands from the driver can be read from the file descriptor
+returned by the ioctl. The commands should be responded to immediately.
+
+UAPI
+====
+
+.. kernel-doc:: include/uapi/linux/vtpm_proxy.h
+
+.. kernel-doc:: drivers/char/tpm/tpm_vtpm_proxy.c
+   :functions: vtpmx_ioc_new_dev
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/security/tpm/xen-tpmfront.txt linux-libre-4.10-rc8-gnu/Documentation/security/tpm/xen-tpmfront.txt
--- linux-libre-4.9-gnu/Documentation/security/tpm/xen-tpmfront.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/security/tpm/xen-tpmfront.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,113 @@
+Virtual TPM interface for Xen
+
+Authors: Matthew Fioravante (JHUAPL), Daniel De Graaf (NSA)
+
+This document describes the virtual Trusted Platform Module (vTPM) subsystem for
+Xen. The reader is assumed to have familiarity with building and installing Xen,
+Linux, and a basic understanding of the TPM and vTPM concepts.
+
+INTRODUCTION
+
+The goal of this work is to provide a TPM functionality to a virtual guest
+operating system (in Xen terms, a DomU).  This allows programs to interact with
+a TPM in a virtual system the same way they interact with a TPM on the physical
+system.  Each guest gets its own unique, emulated, software TPM.  However, each
+of the vTPM's secrets (Keys, NVRAM, etc) are managed by a vTPM Manager domain,
+which seals the secrets to the Physical TPM.  If the process of creating each of
+these domains (manager, vTPM, and guest) is trusted, the vTPM subsystem extends
+the chain of trust rooted in the hardware TPM to virtual machines in Xen. Each
+major component of vTPM is implemented as a separate domain, providing secure
+separation guaranteed by the hypervisor. The vTPM domains are implemented in
+mini-os to reduce memory and processor overhead.
+
+This mini-os vTPM subsystem was built on top of the previous vTPM work done by
+IBM and Intel corporation.
+
+
+DESIGN OVERVIEW
+---------------
+
+The architecture of vTPM is described below:
+
++------------------+
+|    Linux DomU    | ...
+|       |  ^       |
+|       v  |       |
+|   xen-tpmfront   |
++------------------+
+        |  ^
+        v  |
++------------------+
+| mini-os/tpmback  |
+|       |  ^       |
+|       v  |       |
+|  vtpm-stubdom    | ...
+|       |  ^       |
+|       v  |       |
+| mini-os/tpmfront |
++------------------+
+        |  ^
+        v  |
++------------------+
+| mini-os/tpmback  |
+|       |  ^       |
+|       v  |       |
+| vtpmmgr-stubdom  |
+|       |  ^       |
+|       v  |       |
+| mini-os/tpm_tis  |
++------------------+
+        |  ^
+        v  |
++------------------+
+|   Hardware TPM   |
++------------------+
+
+ * Linux DomU: The Linux based guest that wants to use a vTPM. There may be
+	       more than one of these.
+
+ * xen-tpmfront.ko: Linux kernel virtual TPM frontend driver. This driver
+                    provides vTPM access to a Linux-based DomU.
+
+ * mini-os/tpmback: Mini-os TPM backend driver. The Linux frontend driver
+		    connects to this backend driver to facilitate communications
+		    between the Linux DomU and its vTPM. This driver is also
+		    used by vtpmmgr-stubdom to communicate with vtpm-stubdom.
+
+ * vtpm-stubdom: A mini-os stub domain that implements a vTPM. There is a
+		 one to one mapping between running vtpm-stubdom instances and
+                 logical vtpms on the system. The vTPM Platform Configuration
+                 Registers (PCRs) are normally all initialized to zero.
+
+ * mini-os/tpmfront: Mini-os TPM frontend driver. The vTPM mini-os domain
+		     vtpm-stubdom uses this driver to communicate with
+		     vtpmmgr-stubdom. This driver is also used in mini-os
+		     domains such as pv-grub that talk to the vTPM domain.
+
+ * vtpmmgr-stubdom: A mini-os domain that implements the vTPM manager. There is
+		    only one vTPM manager and it should be running during the
+		    entire lifetime of the machine.  This domain regulates
+		    access to the physical TPM on the system and secures the
+		    persistent state of each vTPM.
+
+ * mini-os/tpm_tis: Mini-os TPM version 1.2 TPM Interface Specification (TIS)
+                    driver. This driver used by vtpmmgr-stubdom to talk directly to
+                    the hardware TPM. Communication is facilitated by mapping
+                    hardware memory pages into vtpmmgr-stubdom.
+
+ * Hardware TPM: The physical TPM that is soldered onto the motherboard.
+
+
+INTEGRATION WITH XEN
+--------------------
+
+Support for the vTPM driver was added in Xen using the libxl toolstack in Xen
+4.3.  See the Xen documentation (docs/misc/vtpm.txt) for details on setting up
+the vTPM and vTPM Manager stub domains.  Once the stub domains are running, a
+vTPM device is set up in the same manner as a disk or network device in the
+domain's configuration file.
+
+In order to use features such as IMA that require a TPM to be loaded prior to
+the initrd, the xen-tpmfront driver must be compiled in to the kernel.  If not
+using such features, the driver can be compiled as a module and will be loaded
+as usual.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/SecurityBugs linux-libre-4.10-rc8-gnu/Documentation/SecurityBugs
--- linux-libre-4.9-gnu/Documentation/SecurityBugs	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/SecurityBugs	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-.. _securitybugs:
-
-Security bugs
-=============
-
-Linux kernel developers take security very seriously.  As such, we'd
-like to know when a security bug is found so that it can be fixed and
-disclosed as quickly as possible.  Please report security bugs to the
-Linux kernel security team.
-
-1) Contact
-----------
-
-The Linux kernel security team can be contacted by email at
-<security@kernel.org>.  This is a private list of security officers
-who will help verify the bug report and develop and release a fix.
-It is possible that the security team will bring in extra help from
-area maintainers to understand and fix the security vulnerability.
-
-As it is with any bug, the more information provided the easier it
-will be to diagnose and fix.  Please review the procedure outlined in
-REPORTING-BUGS if you are unclear about what information is helpful.
-Any exploit code is very helpful and will not be released without
-consent from the reporter unless it has already been made public.
-
-2) Disclosure
--------------
-
-The goal of the Linux kernel security team is to work with the
-bug submitter to bug resolution as well as disclosure.  We prefer
-to fully disclose the bug as soon as possible.  It is reasonable to
-delay disclosure when the bug or the fix is not yet fully understood,
-the solution is not well-tested or for vendor coordination.  However, we
-expect these delays to be short, measurable in days, not weeks or months.
-A disclosure date is negotiated by the security team working with the
-bug submitter as well as vendors.  However, the kernel security team
-holds the final say when setting a disclosure date.  The timeframe for
-disclosure is from immediate (esp. if it's already publicly known)
-to a few weeks.  As a basic default policy, we expect report date to
-disclosure date to be on the order of 7 days.
-
-3) Non-disclosure agreements
-----------------------------
-
-The Linux kernel security team is not a formal body and therefore unable
-to enter any non-disclosure agreements.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/serial-console.txt linux-libre-4.10-rc8-gnu/Documentation/serial-console.txt
--- linux-libre-4.9-gnu/Documentation/serial-console.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/serial-console.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,109 +0,0 @@
-                       Linux Serial Console
-
-To use a serial port as console you need to compile the support into your
-kernel - by default it is not compiled in. For PC style serial ports
-it's the config option next to "Standard/generic (dumb) serial support".
-You must compile serial support into the kernel and not as a module.
-
-It is possible to specify multiple devices for console output. You can
-define a new kernel command line option to select which device(s) to
-use for console output.
-
-The format of this option is:
-
-	console=device,options
-
-	device:		tty0 for the foreground virtual console
-			ttyX for any other virtual console
-			ttySx for a serial port
-			lp0 for the first parallel port
-			ttyUSB0 for the first USB serial device
-
-	options:	depend on the driver. For the serial port this
-			defines the baudrate/parity/bits/flow control of
-			the port, in the format BBBBPNF, where BBBB is the
-			speed, P is parity (n/o/e), N is number of bits,
-			and F is flow control ('r' for RTS). Default is
-			9600n8. The maximum baudrate is 115200.
-
-You can specify multiple console= options on the kernel command line.
-Output will appear on all of them. The last device will be used when
-you open /dev/console. So, for example:
-
-	console=ttyS1,9600 console=tty0
-
-defines that opening /dev/console will get you the current foreground
-virtual console, and kernel messages will appear on both the VGA
-console and the 2nd serial port (ttyS1 or COM2) at 9600 baud.
-
-Note that you can only define one console per device type (serial, video).
-
-If no console device is specified, the first device found capable of
-acting as a system console will be used. At this time, the system
-first looks for a VGA card and then for a serial port. So if you don't
-have a VGA card in your system the first serial port will automatically
-become the console.
-
-You will need to create a new device to use /dev/console. The official
-/dev/console is now character device 5,1.
-
-(You can also use a network device as a console.  See
-Documentation/networking/netconsole.txt for information on that.)
-
-Here's an example that will use /dev/ttyS1 (COM2) as the console.
-Replace the sample values as needed.
-
-1. Create /dev/console (real console) and /dev/tty0 (master virtual
-   console):
-
-   cd /dev
-   rm -f console tty0
-   mknod -m 622 console c 5 1
-   mknod -m 622 tty0 c 4 0
-
-2. LILO can also take input from a serial device. This is a very
-   useful option. To tell LILO to use the serial port:
-   In lilo.conf (global section): 
-
-   serial  = 1,9600n8 (ttyS1, 9600 bd, no parity, 8 bits)
-
-3. Adjust to kernel flags for the new kernel,
-   again in lilo.conf (kernel section)
-
-   append = "console=ttyS1,9600" 
-
-4. Make sure a getty runs on the serial port so that you can login to
-   it once the system is done booting. This is done by adding a line
-   like this to /etc/inittab (exact syntax depends on your getty):
-
-   S1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
-
-5. Init and /etc/ioctl.save
-
-   Sysvinit remembers its stty settings in a file in /etc, called
-   `/etc/ioctl.save'. REMOVE THIS FILE before using the serial
-   console for the first time, because otherwise init will probably
-   set the baudrate to 38400 (baudrate of the virtual console).
-
-6. /dev/console and X
-   Programs that want to do something with the virtual console usually
-   open /dev/console. If you have created the new /dev/console device,
-   and your console is NOT the virtual console some programs will fail.
-   Those are programs that want to access the VT interface, and use
-   /dev/console instead of /dev/tty0. Some of those programs are:
-
-   Xfree86, svgalib, gpm, SVGATextMode
-
-   It should be fixed in modern versions of these programs though.
-
-   Note that if you boot without a console= option (or with
-   console=/dev/tty0), /dev/console is the same as /dev/tty0. In that
-   case everything will still work.
-
-7. Thanks
-
-   Thanks to Geert Uytterhoeven <geert@linux-m68k.org>
-   for porting the patches from 2.1.4x to 2.1.6x for taking care of
-   the integration of these patches into m68k, ppc and alpha.
-
-Miquel van Smoorenburg <miquels@cistron.nl>, 11-Jun-2000
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/ALSA-Configuration.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/ALSA-Configuration.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2016-12-11 18:04:50.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,2321 +0,0 @@
-
-		Advanced Linux Sound Architecture - Driver
-		==========================================
-			    Configuration guide
-
-
-Kernel Configuration
-====================
-
-To enable ALSA support you need at least to build the kernel with
-primary sound card support (CONFIG_SOUND).  Since ALSA can emulate OSS,
-you don't have to choose any of the OSS modules.
-
-Enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and
-PCM supports if you want to run OSS applications with ALSA.
-
-If you want to support the WaveTable functionality on cards such as
-SB Live! then you need to enable "Sequencer support"
-(CONFIG_SND_SEQUENCER).
-
-To make ALSA debug messages more verbose, enable the "Verbose printk"
-and "Debug" options.  To check for memory leaks, turn on "Debug memory"
-too.  "Debug detection" will add checks for the detection of cards.
-
-Please note that all the ALSA ISA drivers support the Linux isapnp API
-(if the card supports ISA PnP).  You don't need to configure the cards
-using isapnptools.
-
-
-Creating ALSA devices
-=====================
-
-This depends on your distribution, but normally you use the /dev/MAKEDEV
-script to create the necessary device nodes.  On some systems you use a
-script named 'snddevices'.
-
-
-Module parameters
-=================
-
-The user can load modules with options. If the module supports more than
-one card and you have more than one card of the same type then you can
-specify multiple values for the option separated by commas.
-
-Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
-
-  Module snd
-  ----------
-
-    The core ALSA module.  It is used by all ALSA card drivers.
-    It takes the following options which have global effects.
-
-    major	- major number for sound driver
-		- Default: 116
-    cards_limit
-		- limiting card index for auto-loading (1-8)
-		- Default: 1
-		- For auto-loading more than one card, specify this
-		  option together with snd-card-X aliases.
-    slots	- Reserve the slot index for the given driver.
-		  This option takes multiple strings.		
-		  See "Module Autoloading Support" section for details.
-    debug	- Specifies the debug message level
-		  (0 = disable debug prints, 1 = normal debug messages,
-		   2 = verbose debug messages)
-		  This option appears only when CONFIG_SND_DEBUG=y.
-		  This option can be dynamically changed via sysfs
-		  /sys/modules/snd/parameters/debug file.
-  
-  Module snd-pcm-oss
-  ------------------
-
-    The PCM OSS emulation module.
-    This module takes options which change the mapping of devices.
-
-    dsp_map	- PCM device number maps assigned to the 1st OSS device.
-		- Default: 0
-    adsp_map	- PCM device number maps assigned to the 2st OSS device.
-		- Default: 1
-    nonblock_open
-		- Don't block opening busy PCM devices.  Default: 1
-
-    For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of
-    the card #0.  Similarly, when adsp_map=0, /dev/adsp will be mapped
-    to PCM #0 of the card #0.
-    For changing the second or later card, specify the option with
-    commas, such like "dsp_map=0,1".
-
-    nonblock_open option is used to change the behavior of the PCM
-    regarding opening the device.  When this option is non-zero,
-    opening a busy OSS PCM device won't be blocked but return
-    immediately with EAGAIN (just like O_NONBLOCK flag).
-    
-  Module snd-rawmidi
-  ------------------
-
-    This module takes options which change the mapping of devices.
-    similar to those of the snd-pcm-oss module.
-
-    midi_map	- MIDI device number maps assigned to the 1st OSS device.
-		- Default: 0
-    amidi_map	- MIDI device number maps assigned to the 2st OSS device.
-		- Default: 1
-
-  Common parameters for top sound card modules
-  --------------------------------------------
-
-    Each of top level sound card module takes the following options.
-
-    index	- index (slot #) of sound card
-		- Values: 0 through 31 or negative
-		- If nonnegative, assign that index number
-                - if negative, interpret as a bitmask of permissible
-		  indices; the first free permitted index is assigned
-		- Default: -1
-    id		- card ID (identifier or name)
-		- Can be up to 15 characters long
-		- Default: the card type
-		- A directory by this name is created under /proc/asound/
-		  containing information about the card
-		- This ID can be used instead of the index number in
-		  identifying the card
-    enable  	- enable card
-		- Default: enabled, for PCI and ISA PnP cards
-
-  Module snd-adlib
-  ----------------
-
-    Module for AdLib FM cards.
-
-    port	- port # for OPL chip
-
-    This module supports multiple cards. It does not support autoprobe, so
-    the port must be specified. For actual AdLib FM cards it will be 0x388.
-    Note that this card does not have PCM support and no mixer; only FM
-    synthesis.
-
-    Make sure you have "sbiload" from the alsa-tools package available and,
-    after loading the module, find out the assigned ALSA sequencer port
-    number through "sbiload -l". Example output:
-
-      Port     Client name                       Port name
-      64:0     OPL2 FM synth                     OPL2 FM Port
-
-    Load the std.sb and drums.sb patches also supplied by sbiload:
-
-      sbiload -p 64:0 std.sb drums.sb
-
-    If you use this driver to drive an OPL3, you can use std.o3 and drums.o3
-    instead. To have the card produce sound, use aplaymidi from alsa-utils:
-
-      aplaymidi -p 64:0 foo.mid
-
-  Module snd-ad1816a
-  ------------------
-
-    Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips.
-
-    clockfreq   - Clock frequency for AD1816A chip (default = 0, 33000Hz)
-    
-    This module supports multiple cards, autoprobe and PnP.
-    
-  Module snd-ad1848
-  -----------------
-
-    Module for sound cards based on AD1848/AD1847/CS4248 ISA chips.
-
-    port	- port # for AD1848 chip
-    irq		- IRQ # for AD1848  chip
-    dma1	- DMA # for AD1848 chip (0,1,3)
-    
-    This module supports multiple cards.  It does not support autoprobe
-    thus main port must be specified!!! Other ports are optional.
-    
-    The power-management is supported.
-
-  Module snd-ad1889
-  -----------------
-
-    Module for Analog Devices AD1889 chips.
-
-    ac97_quirk  - AC'97 workaround for strange hardware
-                  See the description of intel8x0 module for details.
-
-    This module supports multiple cards.
-
-  Module snd-ali5451
-  ------------------
-
-    Module for ALi M5451 PCI chip.
-
-    pcm_channels    - Number of hardware channels assigned for PCM
-    spdif           - Support SPDIF I/O
-    		    - Default: disabled
-
-    This module supports one chip and autoprobe.
-
-    The power-management is supported.
-
-  Module snd-als100
-  -----------------
-
-    Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips.
-
-    This module supports multiple cards, autoprobe and PnP.
-
-    The power-management is supported.
-
-  Module snd-als300
-  -----------------
-
-    Module for  Avance Logic ALS300 and ALS300+
-
-    This module supports multiple cards.
-
-    The power-management is supported.
-
-  Module snd-als4000
-  ------------------
-
-    Module for sound cards based on Avance Logic ALS4000 PCI chip.
-
-    joystick_port - port # for legacy joystick support.
-                    0 = disabled (default), 1 = auto-detect
-    
-    This module supports multiple cards, autoprobe and PnP.
-
-    The power-management is supported.
-
-  Module snd-asihpi
-  -----------------
-
-    Module for AudioScience ASI soundcards
-
-    enable_hpi_hwdep	- enable HPI hwdep for AudioScience soundcard
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-atiixp
-  -----------------
-
-    Module for ATI IXP 150/200/250/400 AC97 controllers.
-
-    ac97_clock		- AC'97 clock (default = 48000)
-    ac97_quirk		- AC'97 workaround for strange hardware
-			  See "AC97 Quirk Option" section below.
-    ac97_codec		- Workaround to specify which AC'97 codec 
-			  instead of probing.  If this works for you
-			  file a bug with your `lspci -vn` output.
-			  -2  -- Force probing.
-			  -1  -- Default behavior.
-			  0-2 -- Use the specified codec.
-    spdif_aclink	- S/PDIF transfer over AC-link (default = 1)
-
-    This module supports one card and autoprobe.
-
-    ATI IXP has two different methods to control SPDIF output.  One is
-    over AC-link and another is over the "direct" SPDIF output.  The
-    implementation depends on the motherboard, and you'll need to
-    choose the correct one via spdif_aclink module option.
-
-    The power-management is supported.
-
-  Module snd-atiixp-modem
-  -----------------------
-
-    Module for ATI IXP 150/200/250 AC97 modem controllers.
-
-    This module supports one card and autoprobe.
-
-    Note: The default index value of this module is -2, i.e. the first
-          slot is excluded.
-
-    The power-management is supported.
-
-  Module snd-au8810, snd-au8820, snd-au8830
-  -----------------------------------------
-
-    Module for Aureal Vortex, Vortex2 and Advantage device.
-
-    pcifix	- Control PCI workarounds
-		  0 = Disable all workarounds
-		  1 = Force the PCI latency of the Aureal card to 0xff
-		  2 = Force the Extend PCI#2 Internal Master for Efficient
-		      Handling of Dummy Requests on the VIA KT133 AGP Bridge
-		  3 = Force both settings
-		  255 = Autodetect what is required (default)
-
-    This module supports all ADB PCM channels, ac97 mixer, SPDIF, hardware
-    EQ, mpu401, gameport. A3D and wavetable support are still in development.
-    Development and reverse engineering work is being coordinated at
-    http://savannah.nongnu.org/projects/openvortex/
-    SPDIF output has a copy of the AC97 codec output, unless you use the
-    "spdif" pcm device, which allows raw data passthru.
-    The hardware EQ hardware and SPDIF is only present in the Vortex2 and 
-    Advantage.
-
-    Note: Some ALSA mixer applications don't handle the SPDIF sample rate 
-           control correctly. If you have problems regarding this, try
-           another ALSA compliant mixer (alsamixer works).
-
-  Module snd-azt1605
-  ------------------
-
-    Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
-    chipset.
-
-    port	- port # for BASE (0x220,0x240,0x260,0x280)
-    wss_port	- port # for WSS (0x530,0x604,0xe80,0xf40)
-    irq		- IRQ # for WSS (7,9,10,11)
-    dma1	- DMA # for WSS playback (0,1,3)
-    dma2	- DMA # for WSS capture (0,1), -1 = disabled (default)
-    mpu_port	- port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
-    mpu_irq	- IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
-    fm_port	- port # for OPL3 (0x388), -1 = disabled (default)
-
-    This module supports multiple cards. It does not support autoprobe: port,
-    wss_port, irq and dma1 have to be specified. The other values are
-    optional.
-
-    "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
-    or the value stored in the card's EEPROM for cards that have an EEPROM and
-    their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
-    be chosen freely from the options enumerated above.
-
-    If dma2 is specified and different from dma1, the card will operate in
-    full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
-    enable capture since only channels 0 and 1 are available for capture.
-
-    Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
-    mpu_port=0x330 mpu_irq=9 fm_port=0x388".
-
-    Whatever IRQ and DMA channels you pick, be sure to reserve them for
-    legacy ISA in your BIOS.
-
-  Module snd-azt2316
-  ------------------
-
-    Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
-    chipset.
-
-    port	- port # for BASE (0x220,0x240,0x260,0x280)
-    wss_port	- port # for WSS (0x530,0x604,0xe80,0xf40)
-    irq		- IRQ # for WSS (7,9,10,11)
-    dma1	- DMA # for WSS playback (0,1,3)
-    dma2	- DMA # for WSS capture (0,1), -1 = disabled (default)
-    mpu_port	- port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
-    mpu_irq	- IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
-    fm_port	- port # for OPL3 (0x388), -1 = disabled (default)
-
-    This module supports multiple cards. It does not support autoprobe: port,
-    wss_port, irq and dma1 have to be specified. The other values are
-    optional.
-
-    "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
-    or the value stored in the card's EEPROM for cards that have an EEPROM and
-    their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
-    be chosen freely from the options enumerated above.
-
-    If dma2 is specified and different from dma1, the card will operate in
-    full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
-    enable capture since only channels 0 and 1 are available for capture.
-
-    Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
-    mpu_port=0x330 mpu_irq=9 fm_port=0x388".
-
-    Whatever IRQ and DMA channels you pick, be sure to reserve them for
-    legacy ISA in your BIOS.
-
-  Module snd-aw2
-  --------------
-
-    Module for Audiowerk2 sound card
-
-    This module supports multiple cards.
-
-  Module snd-azt2320
-  ------------------
-
-    Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only).
-
-    This module supports multiple cards, PnP and autoprobe.
-    
-    The power-management is supported.
-
-  Module snd-azt3328
-  ------------------
-
-    Module for sound cards based on Aztech AZF3328 PCI chip.
-
-    joystick	- Enable joystick (default off)
-
-    This module supports multiple cards.
-
-  Module snd-bt87x
-  ----------------
-
-    Module for video cards based on Bt87x chips.
-
-    digital_rate - Override the default digital rate (Hz)
-    load_all	- Load the driver even if the card model isn't known
-
-    This module supports multiple cards.
-
-    Note: The default index value of this module is -2, i.e. the first
-          slot is excluded.
-
-  Module snd-ca0106
-  -----------------
-
-    Module for Creative Audigy LS and SB Live 24bit
-
-    This module supports multiple cards.
-
-
-  Module snd-cmi8330
-  ------------------
-
-    Module for sound cards based on C-Media CMI8330 ISA chips.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    wssport	- port # for CMI8330 chip (WSS)
-    wssirq	- IRQ # for CMI8330 chip (WSS)
-    wssdma	- first DMA # for CMI8330 chip (WSS)
-    sbport	- port # for CMI8330 chip (SB16)
-    sbirq	- IRQ # for CMI8330 chip (SB16)
-    sbdma8	- 8bit DMA # for CMI8330 chip (SB16)
-    sbdma16	- 16bit DMA # for CMI8330 chip (SB16)
-    fmport	- (optional) OPL3 I/O port
-    mpuport	- (optional) MPU401 I/O port
-    mpuirq	- (optional) MPU401 irq #
-
-    This module supports multiple cards and autoprobe.
-
-    The power-management is supported.
-
-  Module snd-cmipci
-  -----------------
-
-    Module for C-Media CMI8338/8738/8768/8770 PCI sound cards.
-
-    mpu_port    - port address of MIDI interface (8338 only):
-		  0x300,0x310,0x320,0x330 = legacy port,
-		  0 = disable (default)
-    fm_port     - port address of OPL-3 FM synthesizer (8x38 only):
-		  0x388 = legacy port,
-		  1 = integrated PCI port (default on 8738),
-		  0 = disable
-    soft_ac3    - Software-conversion of raw SPDIF packets (model 033 only)
-                  (default = 1)
-    joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
-
-    This module supports autoprobe and multiple cards.
-    
-    The power-management is supported.
-
-  Module snd-cs4231
-  -----------------
-
-    Module for sound cards based on CS4231 ISA chips.
-
-    port	- port # for CS4231 chip
-    mpu_port	- port # for MPU-401 UART (optional), -1 = disable
-    irq		- IRQ # for CS4231 chip
-    mpu_irq	- IRQ # for MPU-401 UART
-    dma1	- first DMA # for CS4231 chip
-    dma2	- second DMA # for CS4231 chip
-    
-    This module supports multiple cards. This module does not support autoprobe
-    thus main port must be specified!!! Other ports are optional.
-
-    The power-management is supported.
-    
-  Module snd-cs4236
-  -----------------
-
-    Module for sound cards based on CS4232/CS4232A,
-    	       	     	   	   CS4235/CS4236/CS4236B/CS4237B/
-                                   CS4238B/CS4239 ISA chips.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for CS4236 chip (PnP setup - 0x534)
-    cport	- control port # for CS4236 chip (PnP setup - 0x120,0x210,0xf00)
-    mpu_port	- port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
-    fm_port	- FM port # for CS4236 chip (PnP setup - 0x388), -1 = disable
-    irq		- IRQ # for CS4236 chip (5,7,9,11,12,15)
-    mpu_irq	- IRQ # for MPU-401 UART (9,11,12,15)
-    dma1	- first DMA # for CS4236 chip (0,1,3)
-    dma2	- second DMA # for CS4236 chip (0,1,3), -1 = disable
-    
-    This module supports multiple cards. This module does not support autoprobe
-    (if ISA PnP is not used) thus main port and control port must be
-    specified!!! Other ports are optional.
-
-    The power-management is supported.
-
-    This module is aliased as snd-cs4232 since it provides the old
-    snd-cs4232 functionality, too.
-
-  Module snd-cs4281
-  -----------------
-
-    Module for Cirrus Logic CS4281 soundchip.
-
-    dual_codec	- Secondary codec ID (0 = disable, default)
-
-    This module supports multiple cards.
-
-    The power-management is supported.
-
-  Module snd-cs46xx
-  -----------------
-
-    Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
-				       CS4624/CS4630/CS4280 PCI chips.
-
-    external_amp     - Force to enable external amplifier.
-    thinkpad         - Force to enable Thinkpad's CLKRUN control.
-    mmap_valid       - Support OSS mmap mode (default = 0).
-
-    This module supports multiple cards and autoprobe.
-    Usually external amp and CLKRUN controls are detected automatically
-    from PCI sub vendor/device ids.  If they don't work, give the options
-    above explicitly.
-
-    The power-management is supported.
-
-  Module snd-cs5530
-  _________________
-
-    Module for Cyrix/NatSemi Geode 5530 chip. 
-  
-  Module snd-cs5535audio
-  ----------------------
-
-    Module for multifunction CS5535 companion PCI device
-
-    The power-management is supported.
-
-  Module snd-ctxfi
-  ----------------
-
-    Module for Creative Sound Blaster X-Fi boards (20k1 / 20k2 chips)
-	* Creative Sound Blaster X-Fi Titanium Fatal1ty Champion Series
-	* Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series
-	* Creative Sound Blaster X-Fi Titanium Professional Audio
-	* Creative Sound Blaster X-Fi Titanium
-	* Creative Sound Blaster X-Fi Elite Pro
-	* Creative Sound Blaster X-Fi Platinum
-	* Creative Sound Blaster X-Fi Fatal1ty
-	* Creative Sound Blaster X-Fi XtremeGamer
-	* Creative Sound Blaster X-Fi XtremeMusic
-
-    reference_rate	- reference sample rate, 44100 or 48000 (default)
-    multiple		- multiple to ref. sample rate, 1 or 2 (default)
-    subsystem		- override the PCI SSID for probing; the value
-			  consists of SSVID << 16 | SSDID.  The default is
-			  zero, which means no override.
-
-    This module supports multiple cards.
-
-  Module snd-darla20
-  ------------------
-
-    Module for Echoaudio Darla20
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-darla24
-  ------------------
-
-    Module for Echoaudio Darla24
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-dt019x
-  -----------------
-
-    Module for Diamond Technologies DT-019X / Avance Logic ALS-007 (PnP
-    only)
-
-    This module supports multiple cards.  This module is enabled only with
-    ISA PnP support.
-
-    The power-management is supported.
-
-  Module snd-dummy
-  ----------------
-
-    Module for the dummy sound card. This "card" doesn't do any output
-    or input, but you may use this module for any application which
-    requires a sound card (like RealPlayer).
-
-    pcm_devs       - Number of PCM devices assigned to each card
-                     (default = 1, up to 4)
-    pcm_substreams - Number of PCM substreams assigned to each PCM
-                     (default = 8, up to 128)
-    hrtimer        - Use hrtimer (=1, default) or system timer (=0)
-    fake_buffer    - Fake buffer allocations (default = 1)
-
-    When multiple PCM devices are created, snd-dummy gives different
-    behavior to each PCM device:
-      0 = interleaved with mmap support
-      1 = non-interleaved with mmap support
-      2 = interleaved without mmap 
-      3 = non-interleaved without mmap
-
-    As default, snd-dummy drivers doesn't allocate the real buffers
-    but either ignores read/write or mmap a single dummy page to all
-    buffer pages, in order to save the resources.  If your apps need
-    the read/ written buffer data to be consistent, pass fake_buffer=0
-    option.
-
-    The power-management is supported.
-
-  Module snd-echo3g
-  -----------------
-
-    Module for Echoaudio 3G cards (Gina3G/Layla3G)
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-emu10k1
-  ------------------
-
-    Module for EMU10K1/EMU10k2 based PCI sound cards.
-			* Sound Blaster Live!
-			* Sound Blaster PCI 512
-			* Emu APS (partially supported)
-			* Sound Blaster Audigy
-
-    extin   - bitmap of available external inputs for FX8010 (see bellow)
-    extout  - bitmap of available external outputs for FX8010 (see bellow)
-    seq_ports - allocated sequencer ports (4 by default)
-    max_synth_voices - limit of voices used for wavetable (64 by default)
-    max_buffer_size  - specifies the maximum size of wavetable/pcm buffers
-                       given in MB unit.  Default value is 128.
-    enable_ir - enable IR
-
-    This module supports multiple cards and autoprobe.
-
-    Input & Output configurations 			[extin/extout]
-	* Creative Card wo/Digital out			[0x0003/0x1f03]
-	* Creative Card w/Digital out			[0x0003/0x1f0f]
-	* Creative Card w/Digital CD in			[0x000f/0x1f0f]
-	* Creative Card wo/Digital out + LiveDrive	[0x3fc3/0x1fc3]
-	* Creative Card w/Digital out + LiveDrive	[0x3fc3/0x1fcf]
-	* Creative Card w/Digital CD in + LiveDrive	[0x3fcf/0x1fcf]
-	* Creative Card wo/Digital out + Digital I/O 2  [0x0fc3/0x1f0f]
-	* Creative Card w/Digital out + Digital I/O 2	[0x0fc3/0x1f0f]
-	* Creative Card w/Digital CD in + Digital I/O 2	[0x0fcf/0x1f0f]
-        * Creative Card 5.1/w Digital out + LiveDrive	[0x3fc3/0x1fff]
-	* Creative Card 5.1 (c) 2003			[0x3fc3/0x7cff]
-        * Creative Card all ins and outs		[0x3fff/0x7fff]
-    
-    The power-management is supported.
-
-  Module snd-emu10k1x
-  -------------------
-
-    Module for Creative Emu10k1X (SB Live Dell OEM version)
-
-    This module supports multiple cards.
-
-  Module snd-ens1370
-  ------------------
-
-    Module for Ensoniq AudioPCI ES1370 PCI sound cards.
-			* SoundBlaster PCI 64
-			* SoundBlaster PCI 128
-
-    joystick		- Enable joystick (default off)
-
-    This module supports multiple cards and autoprobe.
-    
-    The power-management is supported.
-
-  Module snd-ens1371
-  ------------------
-
-    Module for Ensoniq AudioPCI ES1371 PCI sound cards.
-			* SoundBlaster PCI 64
-			* SoundBlaster PCI 128
-			* SoundBlaster Vibra PCI
-
-    joystick_port	- port # for joystick (0x200,0x208,0x210,0x218),
-			  0 = disable (default), 1 = auto-detect
-
-    This module supports multiple cards and autoprobe.
-    
-    The power-management is supported.
-
-  Module snd-es1688
-  -----------------
-
-    Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-    mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
-    mpu_irq	- IRQ # for MPU-401 port (5,7,9,10)
-    fm_port	- port # for OPL3 (option; share the same port as default)
-
-    with isapnp=0, the following additional options are available:
-    port	- port # for ES-1688 chip (0x220,0x240,0x260)
-    irq		- IRQ # for ES-1688 chip (5,7,9,10)
-    dma8	- DMA # for ES-1688 chip (0,1,3)
-
-    This module supports multiple cards and autoprobe (without MPU-401 port)
-    and PnP with the ES968 chip.
-
-  Module snd-es18xx
-  -----------------
-
-    Module for ESS AudioDrive ES-18xx sound cards.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for ES-18xx chip (0x220,0x240,0x260)
-    mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
-    fm_port	- port # for FM (optional, not used)
-    irq		- IRQ # for ES-18xx chip (5,7,9,10)
-    dma1	- first DMA # for ES-18xx chip (0,1,3)
-    dma2	- first DMA # for ES-18xx chip (0,1,3)
-
-    This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
-    port if native ISA PnP routines are not used).
-    When dma2 is equal with dma1, the driver works as half-duplex.
-
-    The power-management is supported.
-
-  Module snd-es1938
-  -----------------
-
-    Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
-
-    This module supports multiple cards and autoprobe.
-
-    The power-management is supported.
-
-  Module snd-es1968
-  -----------------
-
-    Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
-
-    total_bufsize	- total buffer size in kB (1-4096kB)
-    pcm_substreams_p	- playback channels (1-8, default=2)
-    pcm_substreams_c	- capture channels (1-8, default=0)
-    clock		- clock (0 = auto-detection)
-    use_pm		- support the power-management (0 = off, 1 = on,
-			  2 = auto (default))
-    enable_mpu		- enable MPU401 (0 = off, 1 = on, 2 = auto (default))
-    joystick		- enable joystick (default off)       
-
-    This module supports multiple cards and autoprobe.
-
-    The power-management is supported.
-
-  Module snd-fm801
-  ----------------
-
-    Module for ForteMedia FM801 based PCI sound cards.
-
-    tea575x_tuner       - Enable TEA575x tuner
-                          - 1 = MediaForte 256-PCS
-                          - 2 = MediaForte 256-PCPR
-                          - 3 = MediaForte 64-PCR  
-                          - High 16-bits are video (radio) device number + 1
-                          - example: 0x10002 (MediaForte 256-PCPR, device 1)
-
-    This module supports multiple cards and autoprobe.
-    
-    The power-management is supported.
-
-  Module snd-gina20
-  -----------------
-
-    Module for Echoaudio Gina20
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-gina24
-  -----------------
-
-    Module for Echoaudio Gina24
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-gusclassic
-  ---------------------
-
-    Module for Gravis UltraSound Classic sound card.
-
-    port	- port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
-    irq		- IRQ # for GF1 chip (3,5,9,11,12,15)
-    dma1	- DMA # for GF1 chip (1,3,5,6,7)
-    dma2	- DMA # for GF1 chip (1,3,5,6,7,-1=disable)
-    joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
-    voices	- GF1 voices limit (14-32)
-    pcm_voices	- reserved PCM voices
-
-    This module supports multiple cards and autoprobe.
-
-  Module snd-gusextreme
-  ---------------------
-
-    Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card.
-
-    port	- port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260)
-    gf1_port	- port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270)
-    mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable
-    irq		- IRQ # for ES-1688 chip (5,7,9,10)
-    gf1_irq	- IRQ # for GF1 chip (3,5,9,11,12,15)
-    mpu_irq	- IRQ # for MPU-401 port (5,7,9,10)
-    dma8	- DMA # for ES-1688 chip (0,1,3)
-    dma1	- DMA # for GF1 chip (1,3,5,6,7)
-    joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
-    voices	- GF1 voices limit (14-32)
-    pcm_voices	- reserved PCM voices
-
-    This module supports multiple cards and autoprobe (without MPU-401 port).
-
-  Module snd-gusmax
-  -----------------
-
-    Module for Gravis UltraSound MAX sound card.
-
-    port	- port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
-    irq		- IRQ # for GF1 chip (3,5,9,11,12,15)
-    dma1	- DMA # for GF1 chip (1,3,5,6,7)
-    dma2	- DMA # for GF1 chip (1,3,5,6,7,-1=disable)
-    joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
-    voices	- GF1 voices limit (14-32)
-    pcm_voices	- reserved PCM voices
-
-    This module supports multiple cards and autoprobe.
-    
-  Module snd-hda-intel
-  --------------------
-
-    Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8, ICH9, ICH10,
-			PCH, SCH),
-		ATI SB450, SB600, R600, RS600, RS690, RS780, RV610, RV620,
-			RV630, RV635, RV670, RV770,
-		VIA VT8251/VT8237A,
-		SIS966, ULI M5461
-
-    [Multiple options for each card instance]
-    model	- force the model name
-    position_fix - Fix DMA pointer
-		  -1 = system default: choose appropriate one per controller
-			hardware
-		  0 = auto: falls back to LPIB when POSBUF doesn't work
-		  1 = use LPIB
-		  2 = POSBUF: use position buffer
-		  3 = VIACOMBO: VIA-specific workaround for capture
-		  4 = COMBO: use LPIB for playback, auto for capture stream
-    probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
-    		  When the bit 8 (0x100) is set, the lower 8 bits are used
-		  as the "fixed" codec slots; i.e. the driver probes the
-		  slots regardless what hardware reports back
-    probe_only	- Only probing and no codec initialization (default=off);
-		  Useful to check the initial codec status for debugging
-    bdl_pos_adj	- Specifies the DMA IRQ timing delay in samples.
-		Passing -1 will make the driver to choose the appropriate
-		value based on the controller chip.
-    patch	- Specifies the early "patch" files to modify the HD-audio
-    		setup before initializing the codecs.  This option is
-		available only when CONFIG_SND_HDA_PATCH_LOADER=y is set.
-		See HD-Audio.txt for details.
-    beep_mode	- Selects the beep registration mode (0=off, 1=on); default
-		value is set via CONFIG_SND_HDA_INPUT_BEEP_MODE kconfig.
-    
-    [Single (global) options]
-    single_cmd  - Use single immediate commands to communicate with
-		codecs (for debugging only)
-    enable_msi	- Enable Message Signaled Interrupt (MSI) (default = off)
-    power_save	- Automatic power-saving timeout (in second, 0 =
-		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.
-    
-    See Documentation/sound/alsa/HD-Audio.txt for more details about
-    HD-audio driver.
-
-    Each codec may have a model table for different configurations.
-    If your machine isn't listed there, the default (usually minimal)
-    configuration is set up.  You can pass "model=<name>" option to
-    specify a certain model in such a case.  There are different
-    models depending on the codec chip.  The list of available models
-    is found in HD-Audio-Models.txt
-
-    The model name "generic" is treated as a special case.  When this
-    model is given, the driver uses the generic codec parser without
-    "codec-patch".  It's sometimes good for testing and debugging.
-
-    If the default configuration doesn't work and one of the above
-    matches with your device, report it together with alsa-info.sh
-    output (with --no-upload option) to kernel bugzilla or alsa-devel
-    ML (see the section "Links and Addresses").
-
-    power_save and power_save_controller options are for power-saving
-    mode.  See powersave.txt for details.
-
-    Note 2: If you get click noises on output, try the module option
-	    position_fix=1 or 2.  position_fix=1 will use the SD_LPIB
-	    register value without FIFO size correction as the current
-	    DMA pointer.  position_fix=2 will make the driver to use
-	    the position buffer instead of reading SD_LPIB register.
-	    (Usually SD_LPIB register is more accurate than the
-	    position buffer.)
-
-	    position_fix=3 is specific to VIA devices.  The position
-	    of the capture stream is checked from both LPIB and POSBUF
-	    values.  position_fix=4 is a combination mode, using LPIB
-	    for playback and POSBUF for capture.
-
-    NB: If you get many "azx_get_response timeout" messages at
-    loading, it's likely a problem of interrupts (e.g. ACPI irq
-    routing).  Try to boot with options like "pci=noacpi".  Also, you
-    can try "single_cmd=1" module option.  This will switch the
-    communication method between HDA controller and codecs to the
-    single immediate commands instead of CORB/RIRB.  Basically, the
-    single command mode is provided only for BIOS, and you won't get
-    unsolicited events, too.  But, at least, this works independently
-    from the irq.  Remember this is a last resort, and should be
-    avoided as much as possible...
-    
-    MORE NOTES ON "azx_get_response timeout" PROBLEMS:
-    On some hardware, you may need to add a proper probe_mask option
-    to avoid the "azx_get_response timeout" problem above, instead.
-    This occurs when the access to non-existing or non-working codec slot
-    (likely a modem one) causes a stall of the communication via HD-audio
-    bus.  You can see which codec slots are probed by enabling
-    CONFIG_SND_DEBUG_VERBOSE, or simply from the file name of the codec
-    proc files.  Then limit the slots to probe by probe_mask option.
-    For example, probe_mask=1 means to probe only the first slot, and
-    probe_mask=4 means only the third slot.
-
-    The power-management is supported.
-
-  Module snd-hdsp
-  ---------------
-
-    Module for RME Hammerfall DSP audio interface(s)
-
-    This module supports multiple cards.
-
-    Note: The firmware data can be automatically loaded via hotplug
-          when CONFIG_FW_LOADER is set.  Otherwise, you need to load
-          the firmware via hdsploader utility included in alsa-tools
-          package.
-          The firmware data is found in alsa-firmware package.
-
-    Note: snd-page-alloc module does the job which snd-hammerfall-mem
-          module did formerly.  It will allocate the buffers in advance
-          when any HDSP cards are found.  To make the buffer
-          allocation sure, load snd-page-alloc module in the early
-          stage of boot sequence.  See "Early Buffer Allocation"
-	  section.
-
-  Module snd-hdspm
-  ----------------
-
-    Module for RME HDSP MADI board.
-
-    precise_ptr		- Enable precise pointer, or disable.
-    line_outs_monitor	- Send playback streams to analog outs by default.
-    enable_monitor	- Enable Analog Out on Channel 63/64 by default.
-
-    See hdspm.txt for details.
-
-  Module snd-ice1712
-  ------------------
-
-    Module for Envy24 (ICE1712) based PCI sound cards.
-			* MidiMan M Audio Delta 1010
-			* MidiMan M Audio Delta 1010LT
-			* MidiMan M Audio Delta DiO 2496
-			* MidiMan M Audio Delta 66
-			* MidiMan M Audio Delta 44
-			* MidiMan M Audio Delta 410
-			* MidiMan M Audio Audiophile 2496
-                        * TerraTec EWS 88MT
-                        * TerraTec EWS 88D
-                        * TerraTec EWX 24/96
-                        * TerraTec DMX 6Fire
-			* TerraTec Phase 88
-                        * Hoontech SoundTrack DSP 24
-                        * Hoontech SoundTrack DSP 24 Value
-                        * Hoontech SoundTrack DSP 24 Media 7.1
-			* Event Electronics, EZ8
-                        * Digigram VX442
-			* Lionstracs, Mediastaton
-			* Terrasoniq TS 88
-
-    model       - Use the given board model, one of the following:
-		  delta1010, dio2496, delta66, delta44, audiophile, delta410,
-		  delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
-		  dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
-		  phase88, mediastation
-    omni	- Omni I/O support for MidiMan M-Audio Delta44/66
-    cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transceiver)
-                     in msec resolution, default value is 500 (0.5 sec)
-
-    This module supports multiple cards and autoprobe. Note: The consumer part
-    is not used with all Envy24 based cards (for example in the MidiMan Delta
-    serie).
-
-    Note: The supported board is detected by reading EEPROM or PCI
-	  SSID (if EEPROM isn't available).  You can override the
-	  model by passing "model" module option in case that the
-	  driver isn't configured properly or you want to try another
-	  type for testing.
-
-  Module snd-ice1724
-  ------------------
-
-    Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
-			* MidiMan M Audio Revolution 5.1
-			* MidiMan M Audio Revolution 7.1
-			* MidiMan M Audio Audiophile 192
-			* AMP Ltd AUDIO2000
-			* TerraTec Aureon 5.1 Sky
-			* TerraTec Aureon 7.1 Space
-			* TerraTec Aureon 7.1 Universe
-			* TerraTec Phase 22
-			* TerraTec Phase 28
-			* AudioTrak Prodigy 7.1
-			* AudioTrak Prodigy 7.1 LT
-			* AudioTrak Prodigy 7.1 XT
-			* AudioTrak Prodigy 7.1 HIFI
-			* AudioTrak Prodigy 7.1 HD2
-			* AudioTrak Prodigy 192
-			* Pontis MS300
-			* Albatron K8X800 Pro II 
-			* Chaintech ZNF3-150
-			* Chaintech ZNF3-250
-			* Chaintech 9CJS
-			* Chaintech AV-710
-			* Shuttle SN25P
-			* Onkyo SE-90PCI
-			* Onkyo SE-200PCI
-			* ESI Juli@
-			* ESI Maya44
-			* Hercules Fortissimo IV
-			* EGO-SYS WaveTerminal 192M
-
-    model       - Use the given board model, one of the following:
-		  revo51, revo71, amp2000, prodigy71, prodigy71lt,
-		  prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192,
-		  juli, aureon51, aureon71, universe, ap192, k8x800,
-		  phase22, phase28, ms300, av710, se200pci, se90pci,
-		  fortissimo4, sn25p, WT192M, maya44
-
-    This module supports multiple cards and autoprobe.
-
-    Note: The supported board is detected by reading EEPROM or PCI
-	  SSID (if EEPROM isn't available).  You can override the
-	  model by passing "model" module option in case that the
-	  driver isn't configured properly or you want to try another
-	  type for testing.
-
-  Module snd-indigo
-  -----------------
-
-    Module for Echoaudio Indigo
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-indigodj
-  -------------------
-
-    Module for Echoaudio Indigo DJ
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-indigoio
-  -------------------
-
-    Module for Echoaudio Indigo IO
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-intel8x0
-  -------------------
-
-    Module for AC'97 motherboards from Intel and compatibles.
-			* Intel i810/810E, i815, i820, i830, i84x, MX440
-				ICH5, ICH6, ICH7, 6300ESB, ESB2
-			* SiS 7012 (SiS 735)
-			* NVidia NForce, NForce2, NForce3, MCP04, CK804
-				 CK8, CK8S, MCP501
-			* AMD AMD768, AMD8111
-			* ALi m5455
-
-    ac97_clock	  - AC'97 codec clock base (0 = auto-detect)
-    ac97_quirk    - AC'97 workaround for strange hardware
-		    See "AC97 Quirk Option" section below.
-    buggy_irq     - Enable workaround for buggy interrupts on some
-                    motherboards (default yes on nForce chips,
-		    otherwise off)
-    buggy_semaphore - Enable workaround for hardware with buggy
-		    semaphores (e.g. on some ASUS laptops)
-		    (default off)
-    spdif_aclink  - Use S/PDIF over AC-link instead of direct connection
-		    from the controller chip
-		    (0 = off, 1 = on, -1 = default)
-
-    This module supports one chip and autoprobe.
-
-    Note: the latest driver supports auto-detection of chip clock.
-    if you still encounter too fast playback, specify the clock
-    explicitly via the module option "ac97_clock=41194".
-
-    Joystick/MIDI ports are not supported by this driver.  If your
-    motherboard has these devices, use the ns558 or snd-mpu401
-    modules, respectively.
-
-    The power-management is supported.
-    
-  Module snd-intel8x0m
-  --------------------
-
-    Module for Intel ICH (i8x0) chipset MC97 modems.
-			* Intel i810/810E, i815, i820, i830, i84x, MX440
-				ICH5, ICH6, ICH7
-			* SiS 7013 (SiS 735)
-			* NVidia NForce, NForce2, NForce2s, NForce3
-			* AMD AMD8111
-			* ALi m5455
-
-    ac97_clock	  - AC'97 codec clock base (0 = auto-detect)
-
-    This module supports one card and autoprobe.
-
-    Note: The default index value of this module is -2, i.e. the first
-          slot is excluded.
-
-    The power-management is supported.
-
-  Module snd-interwave
-  --------------------
-
-    Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32
-    and other sound cards based on AMD InterWave (tm) chip.
-  
-    joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
-    midi	- 1 = MIDI UART enable, 0 = MIDI UART disable (default)
-    pcm_voices	- reserved PCM voices for the synthesizer (default 2)
-    effect	- 1 = InterWave effects enable (default 0);
-                  requires 8 voices
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
-    irq		- IRQ # for InterWave chip (3,5,9,11,12,15)
-    dma1	- DMA # for InterWave chip (0,1,3,5,6,7)
-    dma2	- DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
-
-    This module supports multiple cards, autoprobe and ISA PnP.
-
-  Module snd-interwave-stb
-  ------------------------
-
-    Module for UltraSound 32-Pro (sound card from STB used by Compaq)
-    and other sound cards based on AMD InterWave (tm) chip with TEA6330T
-    circuit for extended control of bass, treble and master volume.
-  
-    joystick_dac - 0 to 31, (0.59V-4.52V or 0.389V-2.98V)
-    midi	- 1 = MIDI UART enable, 0 = MIDI UART disable (default)
-    pcm_voices	- reserved PCM voices for the synthesizer (default 2)
-    effect	- 1 = InterWave effects enable (default 0);
-                  requires 8 voices
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
-    port_tc	- tone control (i2c bus) port # for TEA6330T chip (0x350,0x360,0x370,0x380)
-    irq		- IRQ # for InterWave chip (3,5,9,11,12,15)
-    dma1	- DMA # for InterWave chip (0,1,3,5,6,7)
-    dma2	- DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
-
-    This module supports multiple cards, autoprobe and ISA PnP.
-
-  Module snd-jazz16
-  -------------------
-
-    Module for Media Vision Jazz16 chipset. The chipset consists of 3 chips:
-    MVD1216 + MVA416 + MVA514.
-
-    port	- port # for SB DSP chip (0x210,0x220,0x230,0x240,0x250,0x260)
-    irq		- IRQ # for SB DSP chip (3,5,7,9,10,15)
-    dma8	- DMA # for SB DSP chip (1,3)
-    dma16	- DMA # for SB DSP chip (5,7)
-    mpu_port	- MPU-401 port # (0x300,0x310,0x320,0x330)
-    mpu_irq	- MPU-401 irq # (2,3,5,7)
-
-    This module supports multiple cards.
-
-  Module snd-korg1212
-  -------------------
-
-    Module for Korg 1212 IO PCI card
-
-    This module supports multiple cards.
-
-  Module snd-layla20
-  ------------------
-
-    Module for Echoaudio Layla20
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-layla24
-  ------------------
-
-    Module for Echoaudio Layla24
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-lola
-  ---------------
-
-    Module for Digigram Lola PCI-e boards
-
-    This module supports multiple cards.
-
-  Module snd-lx6464es
-  -------------------
-
-    Module for Digigram LX6464ES boards
-
-    This module supports multiple cards.
-
-  Module snd-maestro3
-  -------------------
-
-    Module for Allegro/Maestro3 chips
-
-    external_amp     - enable external amp (enabled by default)
-    amp_gpio         - GPIO pin number for external amp (0-15) or
-                       -1 for default pin (8 for allegro, 1 for
-                       others) 
-
-    This module supports autoprobe and multiple chips.
-
-    Note: the binding of amplifier is dependent on hardware.
-    If there is no sound even though all channels are unmuted, try to
-    specify other gpio connection via amp_gpio option. 
-    For example, a Panasonic notebook might need "amp_gpio=0x0d"
-    option.
-
-    The power-management is supported.
-
-  Module snd-mia
-  ---------------
-
-    Module for Echoaudio Mia
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-miro
-  ---------------
-
-    Module for Miro soundcards: miroSOUND PCM 1 pro, 
-				miroSOUND PCM 12,
-				miroSOUND PCM 20 Radio.
-
-    port	- Port # (0x530,0x604,0xe80,0xf40)
-    irq		- IRQ # (5,7,9,10,11)
-    dma1	- 1st dma # (0,1,3)
-    dma2	- 2nd dma # (0,1)
-    mpu_port	- MPU-401 port # (0x300,0x310,0x320,0x330)
-    mpu_irq	- MPU-401 irq # (5,7,9,10)
-    fm_port	- FM Port # (0x388)
-    wss		- enable WSS mode
-    ide		- enable onboard ide support
-
-  Module snd-mixart
-  -----------------
-
-    Module for Digigram miXart8 sound cards.
-
-    This module supports multiple cards.
-    Note: One miXart8 board will be represented as 4 alsa cards.
-          See MIXART.txt for details.
-
-    When the driver is compiled as a module and the hotplug firmware
-    is supported, the firmware data is loaded via hotplug automatically.
-    Install the necessary firmware files in alsa-firmware package.
-    When no hotplug fw loader is available, you need to load the
-    firmware via mixartloader utility in alsa-tools package.
-
-  Module snd-mona
-  ---------------
-
-    Module for Echoaudio Mona
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-mpu401
-  -----------------
-
-    Module for MPU-401 UART devices.
-
-    port	- port number or -1 (disable)
-    irq		- IRQ number or -1 (disable)
-    pnp		- PnP detection - 0 = disable, 1 = enable (default)
-
-    This module supports multiple devices and PnP.
-    
-  Module snd-msnd-classic
-  -----------------------
-
-    Module for Turtle Beach MultiSound Classic, Tahiti or Monterey
-    soundcards.
-
-    io		- Port # for msnd-classic card
-    irq		- IRQ # for msnd-classic card
-    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
-		  0xe0000 or 0xe8000)
-    write_ndelay - enable write ndelay (default = 1)
-    calibrate_signal - calibrate signal (default = 0)
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-    digital	- Digital daughterboard present (default = 0)
-    cfg		- Config port (0x250, 0x260 or 0x270) default = PnP
-    reset	- Reset all devices
-    mpu_io	- MPU401 I/O port
-    mpu_irq	- MPU401 irq#
-    ide_io0	- IDE port #0
-    ide_io1	- IDE port #1
-    ide_irq	- IDE irq#
-    joystick_io	- Joystick I/O port
-
-    The driver requires firmware files "/*(DEBLOBBED)*/" and
-    "/*(DEBLOBBED)*/" in the proper firmware directory.
-
-    See Documentation/sound/oss/MultiSound for important information
-    about this driver.  Note that it has been discontinued, but the 
-    Voyetra Turtle Beach knowledge base entry for it is still available
-    at
-	http://www.turtlebeach.com
-
-  Module snd-msnd-pinnacle
-  ------------------------
-
-    Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards.
-
-    io		- Port # for pinnacle/fiji card
-    irq		- IRQ # for pinnalce/fiji card
-    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
-		  0xe0000 or 0xe8000)
-    write_ndelay - enable write ndelay (default = 1)
-    calibrate_signal - calibrate signal (default = 0)
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    The driver requires firmware files "/*(DEBLOBBED)*/" and
-    "/*(DEBLOBBED)*/" in the proper firmware directory.
-
-  Module snd-mtpav
-  ----------------
-
-    Module for MOTU MidiTimePiece AV multiport MIDI (on the parallel
-    port).
-
-    port	- I/O port # for MTPAV (0x378,0x278, default=0x378)
-    irq		- IRQ # for MTPAV (7,5, default=7)
-    hwports	- number of supported hardware ports, default=8.
-    
-    Module supports only 1 card.  This module has no enable option.
-
-  Module snd-mts64
-  ----------------
-
-    Module for Ego Systems (ESI) Miditerminal 4140
-
-    This module supports multiple devices.
-    Requires parport (CONFIG_PARPORT).
-
-  Module snd-nm256
-  ----------------
-
-    Module for NeoMagic NM256AV/ZX chips
-
-    playback_bufsize - max playback frame size in kB (4-128kB)
-    capture_bufsize  - max capture frame size in kB (4-128kB)
-    force_ac97       - 0 or 1 (disabled by default)
-    buffer_top       - specify buffer top address
-    use_cache        - 0 or 1 (disabled by default)
-    vaio_hack        - alias buffer_top=0x25a800
-    reset_workaround - enable AC97 RESET workaround for some laptops
-    reset_workaround2 - enable extended AC97 RESET workaround for some
-		      other laptops
-
-    This module supports one chip and autoprobe.
-
-    The power-management is supported.
-
-    Note: on some notebooks the buffer address cannot be detected
-    automatically, or causes hang-up during initialization.
-    In such a case, specify the buffer top address explicitly via
-    the buffer_top option.
-    For example,
-      Sony F250: buffer_top=0x25a800
-      Sony F270: buffer_top=0x272800
-    The driver supports only ac97 codec.  It's possible to force
-    to initialize/use ac97 although it's not detected.  In such a
-    case, use force_ac97=1 option - but *NO* guarantee whether it
-    works!
-
-    Note: The NM256 chip can be linked internally with non-AC97
-    codecs.  This driver supports only the AC97 codec, and won't work
-    with machines with other (most likely CS423x or OPL3SAx) chips,
-    even though the device is detected in lspci.  In such a case, try
-    other drivers, e.g. snd-cs4232 or snd-opl3sa2.  Some has ISA-PnP
-    but some doesn't have ISA PnP.  You'll need to specify isapnp=0
-    and proper hardware parameters in the case without ISA PnP.
-
-    Note: some laptops need a workaround for AC97 RESET.  For the
-    known hardware like Dell Latitude LS and Sony PCG-F305, this
-    workaround is enabled automatically.  For other laptops with a
-    hard freeze, you can try reset_workaround=1 option.
-
-    Note: Dell Latitude CSx laptops have another problem regarding
-    AC97 RESET.  On these laptops, reset_workaround2 option is
-    turned on as default.  This option is worth to try if the
-    previous reset_workaround option doesn't help.
-
-    Note: This driver is really crappy.  It's a porting from the
-    OSS driver, which is a result of black-magic reverse engineering.
-    The detection of codec will fail if the driver is loaded *after*
-    X-server as described above.  You might be able to force to load
-    the module, but it may result in hang-up.   Hence, make sure that
-    you load this module *before* X if you encounter this kind of
-    problem.
-
-  Module snd-opl3sa2
-  ------------------
-
-    Module for Yamaha OPL3-SA2/SA3 sound cards.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- control port # for OPL3-SA chip (0x370)
-    sb_port	- SB port # for OPL3-SA chip (0x220,0x240)
-    wss_port	- WSS port # for OPL3-SA chip (0x530,0xe80,0xf40,0x604)
-    midi_port	- port # for MPU-401 UART (0x300,0x330), -1 = disable
-    fm_port	- FM port # for OPL3-SA chip (0x388), -1 = disable
-    irq		- IRQ # for OPL3-SA chip (5,7,9,10)
-    dma1	- first DMA # for Yamaha OPL3-SA chip (0,1,3)
-    dma2	- second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
-    
-    This module supports multiple cards and ISA PnP.  It does not support
-    autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
-    
-    The power-management is supported.
-
-  Module snd-opti92x-ad1848
-  -------------------------
-
-    Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips.
-    Module works with OAK Mozart cards as well.
-    
-    isapnp    - ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port      - port # for WSS chip (0x530,0xe80,0xf40,0x604)
-    mpu_port  - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
-    fm_port   - port # for OPL3 device (0x388)
-    irq       - IRQ # for WSS chip (5,7,9,10,11)
-    mpu_irq   - IRQ # for MPU-401 UART (5,7,9,10)
-    dma1      - first DMA # for WSS chip (0,1,3)
-
-    This module supports only one card, autoprobe and PnP.
-
-  Module snd-opti92x-cs4231
-  -------------------------
-
-    Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips.
-    
-    isapnp    - ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port      - port # for WSS chip (0x530,0xe80,0xf40,0x604)
-    mpu_port  - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
-    fm_port   - port # for OPL3 device (0x388)
-    irq       - IRQ # for WSS chip (5,7,9,10,11)
-    mpu_irq   - IRQ # for MPU-401 UART (5,7,9,10)
-    dma1      - first DMA # for WSS chip (0,1,3)
-    dma2      - second DMA # for WSS chip (0,1,3)
-
-    This module supports only one card, autoprobe and PnP.
-
-  Module snd-opti93x
-  ------------------
-
-    Module for sound cards based on OPTi 82c93x chips.
-    
-    isapnp    - ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port      - port # for WSS chip (0x530,0xe80,0xf40,0x604)
-    mpu_port  - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
-    fm_port   - port # for OPL3 device (0x388)
-    irq       - IRQ # for WSS chip (5,7,9,10,11)
-    mpu_irq   - IRQ # for MPU-401 UART (5,7,9,10)
-    dma1      - first DMA # for WSS chip (0,1,3)
-    dma2      - second DMA # for WSS chip (0,1,3)
-
-    This module supports only one card, autoprobe and PnP.
-
-  Module snd-oxygen
-  -----------------
-
-    Module for sound cards based on the C-Media CMI8786/8787/8788 chip:
-    * Asound A-8788
-    * Asus Xonar DG/DGX
-    * AuzenTech X-Meridian
-    * AuzenTech X-Meridian 2G
-    * Bgears b-Enspirer
-    * Club3D Theatron DTS
-    * HT-Omega Claro (plus)
-    * HT-Omega Claro halo (XT)
-    * Kuroutoshikou CMI8787-HG2PCI
-    * Razer Barracuda AC-1
-    * Sondigo Inferno
-    * TempoTec HiFier Fantasia
-    * TempoTec HiFier Serenade
-
-    This module supports autoprobe and multiple cards.
-
-  Module snd-pcsp
-  -----------------
-
-    Module for internal PC-Speaker.
-
-    nopcm	- Disable PC-Speaker PCM sound. Only beeps remain.
-    nforce_wa	- enable NForce chipset workaround. Expect bad sound.
-
-    This module supports system beeps, some kind of PCM playback and
-    even a few mixer controls.
-
-  Module snd-pcxhr
-  ----------------
-
-    Module for Digigram PCXHR boards
-
-    This module supports multiple cards.
-
-  Module snd-portman2x4
-  ---------------------
-
-    Module for Midiman Portman 2x4 parallel port MIDI interface
-
-    This module supports multiple cards.
-
-  Module snd-powermac (on ppc only)
-  ---------------------------------
-
-    Module for PowerMac, iMac and iBook on-board soundchips
-
-    enable_beep     - enable beep using PCM (enabled as default)
-
-    Module supports autoprobe a chip.
-
-    Note: the driver may have problems regarding endianness.
-
-    The power-management is supported.
-
-  Module snd-pxa2xx-ac97 (on arm only)
-  ------------------------------------
-
-    Module for AC97 driver for the Intel PXA2xx chip
-
-    For ARM architecture only.
-
-    The power-management is supported.
-
-  Module snd-riptide
-  ------------------
-
-    Module for Conexant Riptide chip
-
-      joystick_port	- Joystick port # (default: 0x200)
-      mpu_port		- MPU401 port # (default: 0x330)
-      opl3_port		- OPL3 port # (default: 0x388)
-
-    This module supports multiple cards.
-    The driver requires the firmware loader support on kernel.
-    You need to install the firmware file "/*(DEBLOBBED)*/" to the standard
-    firmware path (e.g. /lib/firmware).
-
-  Module snd-rme32
-  ----------------
-
-    Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32, 
-    Prodif96 and Prodif Gold) sound cards.
-
-    This module supports multiple cards.
-
-  Module snd-rme96
-  ----------------
-
-    Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
-
-    This module supports multiple cards.
-
-  Module snd-rme9652
-  ------------------
-
-    Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards.
-
-    precise_ptr	- Enable precise pointer (doesn't work reliably).
-		  (default = 0)
-
-    This module supports multiple cards.
-
-    Note: snd-page-alloc module does the job which snd-hammerfall-mem
-          module did formerly.  It will allocate the buffers in advance
-          when any RME9652 cards are found.  To make the buffer
-          allocation sure, load snd-page-alloc module in the early
-          stage of boot sequence.  See "Early Buffer Allocation"
-	  section.
-
-  Module snd-sa11xx-uda1341 (on arm only)
-  ---------------------------------------
-
-    Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card.
-
-    Module supports only one card.
-    Module has no enable and index options.
-
-    The power-management is supported.
-
-  Module snd-sb8
-  --------------
-
-    Module for 8-bit SoundBlaster cards: SoundBlaster 1.0,
-					 SoundBlaster 2.0,
-					 SoundBlaster Pro
-
-    port	- port # for SB DSP chip (0x220,0x240,0x260)
-    irq		- IRQ # for SB DSP chip (5,7,9,10)
-    dma8	- DMA # for SB DSP chip (1,3)
-
-    This module supports multiple cards and autoprobe.
-    
-    The power-management is supported.
-
-  Module snd-sb16 and snd-sbawe
-  -----------------------------
-
-    Module for 16-bit SoundBlaster cards: SoundBlaster 16 (PnP),
-					  SoundBlaster AWE 32 (PnP),
-					  SoundBlaster AWE 64 PnP
-
-    mic_agc	- Mic Auto-Gain-Control - 0 = disable, 1 = enable (default)
-    csp		- ASP/CSP chip support - 0 = disable (default), 1 = enable
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for SB DSP 4.x chip (0x220,0x240,0x260)
-    mpu_port	- port # for MPU-401 UART (0x300,0x330), -1 = disable
-    awe_port	- base port # for EMU8000 synthesizer (0x620,0x640,0x660)
-                   (snd-sbawe module only)
-    irq		- IRQ # for SB DSP 4.x chip (5,7,9,10)
-    dma8	- 8-bit DMA # for SB DSP 4.x chip (0,1,3)
-    dma16	- 16-bit DMA # for SB DSP 4.x chip (5,6,7)
-    
-    This module supports multiple cards, autoprobe and ISA PnP.
-
-    Note: To use Vibra16X cards in 16-bit half duplex mode, you must
-          disable 16bit DMA with dma16 = -1 module parameter.
-          Also, all Sound Blaster 16 type cards can operate in 16-bit
-          half duplex mode through 8-bit DMA channel by disabling their
-          16-bit DMA channel.
-    
-    The power-management is supported.
-
-  Module snd-sc6000
-  -----------------
-
-    Module for Gallant SC-6000 soundcard and later models: SC-6600
-    and SC-7000.
-
-    port	- Port # (0x220 or 0x240)
-    mss_port	- MSS Port # (0x530 or 0xe80)
-    irq		- IRQ # (5,7,9,10,11)
-    mpu_irq	- MPU-401 IRQ # (5,7,9,10) ,0 - no MPU-401 irq
-    dma		- DMA # (1,3,0)
-    joystick	- Enable gameport - 0 = disable (default), 1 = enable
-
-    This module supports multiple cards.
-
-    This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
-
-  Module snd-sscape
-  -----------------
-
-    Module for ENSONIQ SoundScape cards.
-
-    port	- Port # (PnP setup)
-    wss_port	- WSS Port # (PnP setup)
-    irq		- IRQ # (PnP setup)
-    mpu_irq	- MPU-401 IRQ # (PnP setup)
-    dma		- DMA # (PnP setup)
-    dma2	- 2nd DMA # (PnP setup, -1 to disable)
-    joystick	- Enable gameport - 0 = disable (default), 1 = enable
-
-    This module supports multiple cards.
-
-    The driver requires the firmware loader support on kernel.
-
-  Module snd-sun-amd7930 (on sparc only)
-  --------------------------------------
-
-    Module for AMD7930 sound chips found on Sparcs.
-
-    This module supports multiple cards.
-
-  Module snd-sun-cs4231 (on sparc only)
-  -------------------------------------
-
-    Module for CS4231 sound chips found on Sparcs.
-
-    This module supports multiple cards.
-
-  Module snd-sun-dbri (on sparc only)
-  -----------------------------------
-
-    Module for DBRI sound chips found on Sparcs.
-
-    This module supports multiple cards.
-
-  Module snd-wavefront
-  --------------------
-
-    Module for Turtle Beach Maui, Tropez and Tropez+ sound cards.
-
-    use_cs4232_midi - Use CS4232 MPU-401 interface
-                      (inaccessibly located inside your computer)
-    isapnp          - ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    cs4232_pcm_port - Port # for CS4232 PCM interface.
-    cs4232_pcm_irq  - IRQ # for CS4232 PCM interface (5,7,9,11,12,15).
-    cs4232_mpu_port - Port # for CS4232 MPU-401 interface.
-    cs4232_mpu_irq  - IRQ # for CS4232 MPU-401 interface (9,11,12,15).
-    ics2115_port    - Port # for ICS2115
-    ics2115_irq     - IRQ # for ICS2115
-    fm_port         - FM OPL-3 Port #
-    dma1            - DMA1 # for CS4232 PCM interface.
-    dma2            - DMA2 # for CS4232 PCM interface.
-
-    The below are options for wavefront_synth features:
-    wf_raw	    - Assume that we need to boot the OS (default:no)
-	If yes, then during driver loading, the state of the board is
-	ignored, and we reset the board and load the firmware anyway.
-    fx_raw	    - Assume that the FX process needs help (default:yes)
-	If false, we'll leave the FX processor in whatever state it is
-	when the driver is loaded.  The default is to download the
-	microprogram and associated coefficients to set it up for
-	"default" operation, whatever that means.
-    debug_default   - Debug parameters for card initialization
-    wait_usecs	    - How long to wait without sleeping, usecs
-		      (default:150)
-	This magic number seems to give pretty optimal throughput
-	based on my limited experimentation. 
-	If you want to play around with it and find a better value, be
-	my guest. Remember, the idea is to get a number that causes us
-	to just busy wait for as many WaveFront commands as possible,
-	without coming up with a number so large that we hog the whole
-	CPU. 
-	Specifically, with this number, out of about 134,000 status
-	waits, only about 250 result in a sleep. 
-    sleep_interval  - How long to sleep when waiting for reply
-		      (default: 100)
-    sleep_tries	    - How many times to try sleeping during a wait
-		      (default: 50)
-    /*(DEBLOBBED)*/
-    reset_time	    - How long to wait for a reset to take effect
-		      (default:2)
-    ramcheck_time   - How many seconds to wait for the RAM test
-		      (default:20)
-    osrun_time	    - How many seconds to wait for the ICS2115 OS
-		      (default:10)
-
-    This module supports multiple cards and ISA PnP.
-
-    /*(DEBLOBBED)*/.
-
-  Module snd-sonicvibes
-  ---------------------
-
-    Module for S3 SonicVibes PCI sound cards.
-			* PINE Schubert 32 PCI
-
-    reverb    - Reverb Enable - 1 = enable, 0 = disable (default)
-                  - SoundCard must have onboard SRAM for this.
-    mge       - Mic Gain Enable - 1 = enable, 0 = disable (default)
-    
-    This module supports multiple cards and autoprobe.
-
-  Module snd-serial-u16550
-  ------------------------
-
-    Module for UART16550A serial MIDI ports.
-
-    port	- port # for UART16550A chip
-    irq		- IRQ # for UART16550A chip, -1 = poll mode
-    speed	- speed in bauds (9600,19200,38400,57600,115200)
-		  38400 = default
-    base	- base for divisor in bauds (57600,115200,230400,460800)
-		  115200 = default
-    outs	- number of MIDI ports in a serial port (1-4)
-		  1 = default
-    adaptor	- Type of adaptor.
-                  0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
-		  3 = MS-124W M/B, 4 = Generic
-    
-    This module supports multiple cards. This module does not support autoprobe
-    thus the main port must be specified!!! Other options are optional.
-
-  Module snd-trident
-  ------------------
-
-    Module for Trident 4DWave DX/NX sound cards.
-			* Best Union  Miss Melody 4DWave PCI
-			* HIS  4DWave PCI
-			* Warpspeed  ONSpeed 4DWave PCI
-			* AzTech  PCI 64-Q3D
-			* Addonics  SV 750
-			* CHIC  True Sound 4Dwave
-			* Shark  Predator4D-PCI
-			* Jaton  SonicWave 4D
-			* SiS SI7018 PCI Audio
-			* Hoontech SoundTrack Digital 4DWave NX
-
-    pcm_channels   - max channels (voices) reserved for PCM
-    wavetable_size - max wavetable size in kB (4-?kb)
-
-    This module supports multiple cards and autoprobe.
-
-    The power-management is supported.
-
-  Module snd-ua101
-  ----------------
-
-    Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.
-
-    This module supports multiple devices, autoprobe and hotplugging.
-
-  Module snd-usb-audio
-  --------------------
-
-    Module for USB audio and USB MIDI devices.
-
-    vid             - Vendor ID for the device (optional)
-    pid             - Product ID for the device (optional)
-    nrpacks	    - Max. number of packets per URB (default: 8)
-    device_setup    - Device specific magic number (optional)
-                    - Influence depends on the device
-                    - Default: 0x0000 
-    ignore_ctl_error - Ignore any USB-controller regarding mixer
-    		       interface (default: no)
-    autoclock	    - Enable auto-clock selection for UAC2 devices
-		      (default: yes)
-    quirk_alias	    - Quirk alias list, pass strings like
-		      "0123abcd:5678beef", which applies the existing
-		      quirk for the device 5678:beef to a new device
-		      0123:abcd.
-
-    This module supports multiple devices, autoprobe and hotplugging.
-
-    NB: nrpacks parameter can be modified dynamically via sysfs.
-        Don't put the value over 20.  Changing via sysfs has no sanity
-	check.
-    NB: ignore_ctl_error=1 may help when you get an error at accessing
-        the mixer element such as URB error -22.  This happens on some
-        buggy USB device or the controller.
-    NB: quirk_alias option is provided only for testing / development.
-        If you want to have a proper support, contact to upstream for
-	adding the matching quirk in the driver code statically.
-
-  Module snd-usb-caiaq
-  --------------------
-
-    Module for caiaq UB audio interfaces,
-	    * Native Instruments RigKontrol2
-	    * Native Instruments Kore Controller
-	    * Native Instruments Audio Kontrol 1
-	    * Native Instruments Audio 8 DJ
-
-    This module supports multiple devices, autoprobe and hotplugging.
-
-  Module snd-usb-usx2y
-  --------------------
-
-    Module for Tascam USB US-122, US-224 and US-428 devices.
-
-    This module supports multiple devices, autoprobe and hotplugging.
-
-    Note: you need to load the firmware via usx2yloader utility included
-          in alsa-tools and alsa-firmware packages.
-
-  Module snd-via82xx
-  ------------------
-
-    Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
-    8233A, 8233C, 8235, 8237 (south) bridge.
-
-    mpu_port	- 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
-		  [VIA686A/686B only]
-    joystick	- Enable joystick (default off) [VIA686A/686B only]
-    ac97_clock	- AC'97 codec clock base (default 48000Hz)
-    dxs_support	- support DXS channels,
-		  0 = auto (default), 1 = enable, 2 = disable,
-		  3 = 48k only, 4 = no VRA, 5 = enable any sample
-		  rate and different sample rates on different
-		  channels
-		  [VIA8233/C, 8235, 8237 only]
-    ac97_quirk  - AC'97 workaround for strange hardware
-		  See "AC97 Quirk Option" section below.
-
-    This module supports one chip and autoprobe.
-
-    Note: on some SMP motherboards like MSI 694D the interrupts might
-          not be generated properly.  In such a case, please try to
-          set the SMP (or MPS) version on BIOS to 1.1 instead of
-          default value 1.4.  Then the interrupt number will be
-          assigned under 15. You might also upgrade your BIOS.
-    
-    Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
-	  channels as the first PCM.  On these channels, up to 4
-	  streams can be played at the same time, and the controller
-	  can perform sample rate conversion with separate rates for
-	  each channel.
-	  As default (dxs_support = 0), 48k fixed rate is chosen
-	  except for the known devices since the output is often
-	  noisy except for 48k on some mother boards due to the
-	  bug of BIOS.
-	  Please try once dxs_support=5 and if it works on other
-	  sample rates (e.g. 44.1kHz of mp3 playback), please let us
-	  know the PCI subsystem vendor/device id's (output of
-	  "lspci -nv").
-	  If dxs_support=5 does not work, try dxs_support=4; if it
-	  doesn't work too, try dxs_support=1.  (dxs_support=1 is
-	  usually for old motherboards.  The correct implemented
-	  board should work with 4 or 5.)  If it still doesn't
-	  work and the default setting is ok, dxs_support=3 is the
-	  right choice.  If the default setting doesn't work at all,
-	  try dxs_support=2 to disable the DXS channels.
-	  In any cases, please let us know the result and the
-	  subsystem vendor/device ids.  See "Links and Addresses"
-	  below.
-
-    Note: for the MPU401 on VIA823x, use snd-mpu401 driver
-	  additionally.  The mpu_port option is for VIA686 chips only.
-
-    The power-management is supported.
-
-  Module snd-via82xx-modem
-  ------------------------
-
-    Module for VIA82xx AC97 modem
-
-    ac97_clock	- AC'97 codec clock base (default 48000Hz)
-
-    This module supports one card and autoprobe.
-
-    Note: The default index value of this module is -2, i.e. the first
-          slot is excluded.
-
-    The power-management is supported.
-
-  Module snd-virmidi
-  ------------------
-
-    Module for virtual rawmidi devices.
-    This module creates virtual rawmidi devices which communicate
-    to the corresponding ALSA sequencer ports.
-
-    midi_devs	- MIDI devices # (1-4, default=4)
-    
-    This module supports multiple cards.
-
-  Module snd-virtuoso
-  -------------------
-
-    Module for sound cards based on the Asus AV66/AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
-    Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
-
-    This module supports autoprobe and multiple cards.
-
-  Module snd-vx222
-  ----------------
-
-    Module for Digigram VX-Pocket VX222, V222 v2 and Mic cards.
-
-    mic		- Enable Microphone on V222 Mic (NYI)
-    ibl		- Capture IBL size. (default = 0, minimum size)
-
-    This module supports multiple cards.
-
-    When the driver is compiled as a module and the hotplug firmware
-    is supported, the firmware data is loaded via hotplug automatically.
-    Install the necessary firmware files in alsa-firmware package.
-    When no hotplug fw loader is available, you need to load the
-    firmware via vxloader utility in alsa-tools package.  To invoke
-    vxloader automatically, add the following to /etc/modprobe.d/alsa.conf
-
-	install snd-vx222 /sbin/modprobe --first-time -i snd-vx222 && /usr/bin/vxloader
-
-    (for 2.2/2.4 kernels, add "post-install /usr/bin/vxloader" to
-     /etc/modules.conf, instead.)
-    IBL size defines the interrupts period for PCM.  The smaller size
-    gives smaller latency but leads to more CPU consumption, too.
-    The size is usually aligned to 126.  As default (=0), the smallest
-    size is chosen.  The possible IBL values can be found in
-    /proc/asound/cardX/vx-status proc file.
-
-    The power-management is supported.
-
-  Module snd-vxpocket
-  -------------------
-
-    Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
-
-    ibl      - Capture IBL size. (default = 0, minimum size)
-
-    This module supports multiple cards.  The module is compiled only when
-    PCMCIA is supported on kernel.
-
-    With the older 2.6.x kernel, to activate the driver via the card
-    manager, you'll need to set up /etc/pcmcia/vxpocket.conf.  See the
-    sound/pcmcia/vx/vxpocket.c.  2.6.13 or later kernel requires no
-    longer require a config file.
-
-    When the driver is compiled as a module and the hotplug firmware
-    is supported, the firmware data is loaded via hotplug automatically.
-    Install the necessary firmware files in alsa-firmware package.
-    When no hotplug fw loader is available, you need to load the
-    firmware via vxloader utility in alsa-tools package.
-
-    About capture IBL, see the description of snd-vx222 module.
-
-    Note: snd-vxp440 driver is merged to snd-vxpocket driver since
-           ALSA 1.0.10.
-
-    The power-management is supported.
-
-  Module snd-ymfpci
-  -----------------
-
-    Module for Yamaha PCI chips (YMF72x, YMF74x & YMF75x).
-
-    mpu_port      - 0x300,0x330,0x332,0x334, 0 (disable) by default,
-                    1 (auto-detect for YMF744/754 only)
-    fm_port       - 0x388,0x398,0x3a0,0x3a8, 0 (disable) by default
-                    1 (auto-detect for YMF744/754 only)
-    joystick_port - 0x201,0x202,0x204,0x205, 0 (disable) by default,
-                    1 (auto-detect)
-    rear_switch   - enable shared rear/line-in switch (bool)
-
-    This module supports autoprobe and multiple chips.
-
-    The power-management is supported.
-
-  Module snd-pdaudiocf
-  --------------------
-
-    Module for Sound Core PDAudioCF sound card.
-
-    The power-management is supported.
-
-
-AC97 Quirk Option
-=================
-
-The ac97_quirk option is used to enable/override the workaround for
-specific devices on drivers for on-board AC'97 controllers like
-snd-intel8x0.  Some hardware have swapped output pins between Master
-and Headphone, or Surround (thanks to confusion of AC'97
-specifications from version to version :-)
-
-The driver provides the auto-detection of known problematic devices,
-but some might be unknown or wrongly detected.  In such a case, pass
-the proper value with this option.
-
-The following strings are accepted:
-    - default	Don't override the default setting
-    - none	Disable the quirk
-    - hp_only	Bind Master and Headphone controls as a single control
-    - swap_hp	Swap headphone and master controls
-    - swap_surround  Swap master and surround controls
-    - ad_sharing  For AD1985, turn on OMS bit and use headphone
-    - alc_jack	For ALC65x, turn on the jack sense mode
-    - inv_eapd	Inverted EAPD implementation
-    - mute_led	Bind EAPD bit for turning on/off mute LED
-
-For backward compatibility, the corresponding integer value -1, 0,
-... are  accepted, too.
-
-For example, if "Master" volume control has no effect on your device
-but only "Headphone" does, pass ac97_quirk=hp_only module option.
-
-
-Configuring Non-ISAPNP Cards
-============================
-
-When the kernel is configured with ISA-PnP support, the modules
-supporting the isapnp cards will have module options "isapnp".
-If this option is set, *only* the ISA-PnP devices will be probed.
-For probing the non ISA-PnP cards, you have to pass "isapnp=0" option
-together with the proper i/o and irq configuration.
-
-When the kernel is configured without ISA-PnP support, isapnp option
-will be not built in.
-
-
-Module Autoloading Support
-==========================
-
-The ALSA drivers can be loaded automatically on demand by defining
-module aliases.  The string 'snd-card-%1' is requested for ALSA native
-devices where %i is sound card number from zero to seven.
-
-To auto-load an ALSA driver for OSS services, define the string
-'sound-slot-%i' where %i means the slot number for OSS, which
-corresponds to the card index of ALSA.  Usually, define this
-as the same card module.
-
-An example configuration for a single emu10k1 card is like below:
------ /etc/modprobe.d/alsa.conf
-alias snd-card-0 snd-emu10k1
-alias sound-slot-0 snd-emu10k1
------ /etc/modprobe.d/alsa.conf
-
-The available number of auto-loaded sound cards depends on the module
-option "cards_limit" of snd module.  As default it's set to 1.
-To enable the auto-loading of multiple cards, specify the number of
-sound cards in that option.
-
-When multiple cards are available, it'd better to specify the index
-number for each card via module option, too, so that the order of
-cards is kept consistent.
-
-An example configuration for two sound cards is like below:
-
------ /etc/modprobe.d/alsa.conf
-# ALSA portion
-options snd cards_limit=2
-alias snd-card-0 snd-interwave
-alias snd-card-1 snd-ens1371
-options snd-interwave index=0
-options snd-ens1371 index=1
-# OSS/Free portion
-alias sound-slot-0 snd-interwave
-alias sound-slot-1 snd-ens1371
------ /etc/modprobe.d/alsa.conf
-
-In this example, the interwave card is always loaded as the first card
-(index 0) and ens1371 as the second (index 1).
-
-Alternative (and new) way to fixate the slot assignment is to use
-"slots" option of snd module.  In the case above, specify like the
-following: 
-
-options snd slots=snd-interwave,snd-ens1371
-
-Then, the first slot (#0) is reserved for snd-interwave driver, and
-the second (#1) for snd-ens1371.  You can omit index option in each
-driver if slots option is used (although you can still have them at
-the same time as long as they don't conflict).
-
-The slots option is especially useful for avoiding the possible
-hot-plugging and the resultant slot conflict.  For example, in the
-case above again, the first two slots are already reserved.  If any
-other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
-snd-ens1371, it will be assigned to the third or later slot.
-
-When a module name is given with '!', the slot will be given for any
-modules but that name.  For example, "slots=!snd-pcsp" will reserve
-the first slot for any modules but snd-pcsp. 
-
-
-ALSA PCM devices to OSS devices mapping
-=======================================
-
-/dev/snd/pcmC0D0[c|p]  -> /dev/audio0 (/dev/audio) -> minor 4
-/dev/snd/pcmC0D0[c|p]  -> /dev/dsp0 (/dev/dsp)     -> minor 3
-/dev/snd/pcmC0D1[c|p]  -> /dev/adsp0 (/dev/adsp)   -> minor 12
-/dev/snd/pcmC1D0[c|p]  -> /dev/audio1              -> minor 4+16 = 20
-/dev/snd/pcmC1D0[c|p]  -> /dev/dsp1                -> minor 3+16 = 19
-/dev/snd/pcmC1D1[c|p]  -> /dev/adsp1               -> minor 12+16 = 28
-/dev/snd/pcmC2D0[c|p]  -> /dev/audio2              -> minor 4+32 = 36
-/dev/snd/pcmC2D0[c|p]  -> /dev/dsp2                -> minor 3+32 = 39
-/dev/snd/pcmC2D1[c|p]  -> /dev/adsp2               -> minor 12+32 = 44
-
-The first number from /dev/snd/pcmC{X}D{Y}[c|p] expression means
-sound card number and second means device number.  The ALSA devices
-have either 'c' or 'p' suffix indicating the direction, capture and
-playback, respectively.
-
-Please note that the device mapping above may be varied via the module
-options of snd-pcm-oss module.
-
-
-Proc interfaces (/proc/asound)
-==============================
-
-/proc/asound/card#/pcm#[cp]/oss
--------------------------------
-  String "erase" - erase all additional information about OSS applications
-  String "<app_name> <fragments> <fragment_size> [<options>]"
-
-   <app_name> - name of application with (higher priority) or without path
-   <fragments> - number of fragments or zero if auto
-   <fragment_size> - size of fragment in bytes or zero if auto
-   <options> - optional parameters
-	  - disable   the application tries to open a pcm device for
-		      this channel but does not want to use it.
-		      (Cause a bug or mmap needs)
-		      It's good for Quake etc...
-	  - direct    don't use plugins
-	  - block     force block mode (rvplayer)
-	  - non-block force non-block mode
-	  - whole-frag  write only whole fragments (optimization affecting
-			playback only)
-	  - no-silence  do not fill silence ahead to avoid clicks
-	  - buggy-ptr	Returns the whitespace blocks in GETOPTR ioctl
-			instead of filled blocks
-
-  Example: echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
-           echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
-	   echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
-
-
-Early Buffer Allocation
-=======================
-
-Some drivers (e.g. hdsp) require the large contiguous buffers, and
-sometimes it's too late to find such spaces when the driver module is
-actually loaded due to memory fragmentation.  You can pre-allocate the
-PCM buffers by loading snd-page-alloc module and write commands to its
-proc file in prior, for example, in the early boot stage like
-/etc/init.d/*.local scripts.
-
-Reading the proc file /proc/drivers/snd-page-alloc shows the current
-usage of page allocation.  In writing, you can send the following
-commands to the snd-page-alloc driver:
-
-  - add VENDOR DEVICE MASK SIZE BUFFERS
-
-    VENDOR and DEVICE are PCI vendor and device IDs.  They take
-    integer numbers (0x prefix is needed for the hex).
-    MASK is the PCI DMA mask.  Pass 0 if not restricted.
-    SIZE is the size of each buffer to allocate.  You can pass
-    k and m suffix for KB and MB.  The max number is 16MB.
-    BUFFERS is the number of buffers to allocate.  It must be greater
-    than 0.  The max number is 4.
-
-  - erase
-
-    This will erase the all pre-allocated buffers which are not in
-    use.
-
-
-Links and Addresses
-===================
-
-  ALSA project homepage
-       http://www.alsa-project.org
-
-  Kernel Bugzilla
-       http://bugzilla.kernel.org/
-
-  ALSA Developers ML
-       mailto:alsa-devel@alsa-project.org
-
-  alsa-info.sh script
-       http://www.alsa-project.org/alsa-info.sh
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/alsa-parameters.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/alsa-parameters.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/alsa-parameters.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/alsa-parameters.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,135 +0,0 @@
-                          ALSA Kernel Parameters
-                          ~~~~~~~~~~~~~~~~~~~~~~
-
-See Documentation/kernel-parameters.txt for general information on
-specifying module parameters.
-
-This document may not be entirely up to date and comprehensive. The command
-"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
-module. Loadable modules, after being loaded into the running kernel, also
-reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
-parameters may be changed at runtime by the command
-"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
-
-
-	snd-ad1816a=	[HW,ALSA]
-
-	snd-ad1848=	[HW,ALSA]
-
-	snd-ali5451=	[HW,ALSA]
-
-	snd-als100=	[HW,ALSA]
-
-	snd-als4000=	[HW,ALSA]
-
-	snd-azt2320=	[HW,ALSA]
-
-	snd-cmi8330=	[HW,ALSA]
-
-	snd-cmipci=	[HW,ALSA]
-
-	snd-cs4231=	[HW,ALSA]
-
-	snd-cs4232=	[HW,ALSA]
-
-	snd-cs4236=	[HW,ALSA]
-
-	snd-cs4281=	[HW,ALSA]
-
-	snd-cs46xx=	[HW,ALSA]
-
-	snd-dt019x=	[HW,ALSA]
-
-	snd-dummy=	[HW,ALSA]
-
-	snd-emu10k1=	[HW,ALSA]
-
-	snd-ens1370=	[HW,ALSA]
-
-	snd-ens1371=	[HW,ALSA]
-
-	snd-es968=	[HW,ALSA]
-
-	snd-es1688=	[HW,ALSA]
-
-	snd-es18xx=	[HW,ALSA]
-
-	snd-es1938=	[HW,ALSA]
-
-	snd-es1968=	[HW,ALSA]
-
-	snd-fm801=	[HW,ALSA]
-
-	snd-gusclassic=	[HW,ALSA]
-
-	snd-gusextreme=	[HW,ALSA]
-
-	snd-gusmax=	[HW,ALSA]
-
-	snd-hdsp=	[HW,ALSA]
-
-	snd-ice1712=	[HW,ALSA]
-
-	snd-intel8x0=	[HW,ALSA]
-
-	snd-interwave=	[HW,ALSA]
-
-	snd-interwave-stb=
-			[HW,ALSA]
-
-	snd-korg1212=	[HW,ALSA]
-
-	snd-maestro3=	[HW,ALSA]
-
-	snd-mpu401=	[HW,ALSA]
-
-	snd-mtpav=	[HW,ALSA]
-
-	snd-nm256=	[HW,ALSA]
-
-	snd-opl3sa2=	[HW,ALSA]
-
-	snd-opti92x-ad1848=
-			[HW,ALSA]
-
-	snd-opti92x-cs4231=
-			[HW,ALSA]
-
-	snd-opti93x=	[HW,ALSA]
-
-	snd-pmac=	[HW,ALSA]
-
-	snd-rme32=	[HW,ALSA]
-
-	snd-rme96=	[HW,ALSA]
-
-	snd-rme9652=	[HW,ALSA]
-
-	snd-sb8=	[HW,ALSA]
-
-	snd-sb16=	[HW,ALSA]
-
-	snd-sbawe=	[HW,ALSA]
-
-	snd-serial=	[HW,ALSA]
-
-	snd-sgalaxy=	[HW,ALSA]
-
-	snd-sonicvibes=	[HW,ALSA]
-
-	snd-sun-amd7930=
-			[HW,ALSA]
-
-	snd-sun-cs4231=	[HW,ALSA]
-
-	snd-trident=	[HW,ALSA]
-
-	snd-usb-audio=	[HW,ALSA,USB]
-
-	snd-via82xx=	[HW,ALSA]
-
-	snd-virmidi=	[HW,ALSA]
-
-	snd-wavefront=	[HW,ALSA]
-
-	snd-ymfpci=	[HW,ALSA]
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/Audigy-mixer.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Audigy-mixer.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/Audigy-mixer.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Audigy-mixer.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,345 +0,0 @@
-
-		Sound Blaster Audigy mixer / default DSP code
-		===========================================
-
-This is based on SB-Live-mixer.txt.
-
-The EMU10K2 chips have a DSP part which can be programmed to support 
-various ways of sample processing, which is described here.
-(This article does not deal with the overall functionality of the 
-EMU10K2 chips. See the manuals section for further details.)
-
-The ALSA driver programs this portion of chip by default code
-(can be altered later) which offers the following functionality:
-
-
-1) Digital mixer controls
--------------------------
-
-These controls are built using the DSP instructions. They offer extended
-functionality. Only the default build-in code in the ALSA driver is described
-here. Note that the controls work as attenuators: the maximum value is the 
-neutral position leaving the signal unchanged. Note that if the  same destination 
-is mentioned in multiple controls, the signal is accumulated and can be wrapped 
-(set to maximal or minimal value without checking of overflow).
-
-
-Explanation of used abbreviations:
-
-DAC    - digital to analog converter
-ADC    - analog to digital converter
-I2S    - one-way three wire serial bus for digital sound by Philips Semiconductors
-         (this standard is used for connecting standalone DAC and ADC converters)
-LFE    - low frequency effects (subwoofer signal)
-AC97   - a chip containing an analog mixer, DAC and ADC converters
-IEC958 - S/PDIF
-FX-bus - the EMU10K2 chip has an effect bus containing 64 accumulators.
-         Each of the synthesizer voices can feed its output to these accumulators
-         and the DSP microcontroller can operate with the resulting sum.
-
-name='PCM Front Playback Volume',index=0
-
-This control is used to attenuate samples for left and right front PCM FX-bus
-accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM 
-samples for 5.1 playback. The result samples are forwarded to the front DAC PCM 
-slots of the Philips DAC.
-
-name='PCM Surround Playback Volume',index=0
-
-This control is used to attenuate samples for left and right surround PCM FX-bus
-accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM 
-samples for 5.1 playback. The result samples are forwarded to the surround DAC PCM 
-slots of the Philips DAC.
-
-name='PCM Center Playback Volume',index=0
-
-This control is used to attenuate samples for center PCM FX-bus accumulator.
-ALSA uses accumulator 6 for center PCM sample for 5.1 playback. The result sample
-is forwarded to the center DAC PCM slot of the Philips DAC.
-
-name='PCM LFE Playback Volume',index=0
-
-This control is used to attenuate sample for LFE PCM FX-bus accumulator. 
-ALSA uses accumulator 7 for LFE PCM sample for 5.1 playback. The result sample 
-is forwarded to the LFE DAC PCM slot of the Philips DAC.
-
-name='PCM Playback Volume',index=0
-
-This control is used to attenuate samples for left and right PCM FX-bus
-accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for
-stereo playback. The result samples are forwarded to the front DAC PCM slots 
-of the Philips DAC.
-
-name='PCM Capture Volume',index=0
-
-This control is used to attenuate samples for left and right PCM FX-bus
-accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
-The result is forwarded to the ADC capture FIFO (thus to the standard capture
-PCM device).
-
-name='Music Playback Volume',index=0
-
-This control is used to attenuate samples for left and right MIDI FX-bus
-accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
-The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
-
-name='Music Capture Volume',index=0
-
-These controls are used to attenuate samples for left and right MIDI FX-bus
-accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
-The result is forwarded to the ADC capture FIFO (thus to the standard capture
-PCM device).
-
-name='Mic Playback Volume',index=0
-
-This control is used to attenuate samples for left and right Mic input.
-For Mic input is used AC97 codec. The result samples are forwarded to 
-the front DAC PCM slots of the Philips DAC. Samples are forwarded to Mic
-capture FIFO (device 1 - 16bit/8KHz mono) too without volume control.
-
-name='Mic Capture Volume',index=0
-
-This control is used to attenuate samples for left and right Mic input.
-The result is forwarded to the ADC capture FIFO (thus to the standard capture
-PCM device).
-
-name='Audigy CD Playback Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 TTL
-digital inputs (usually used by a CDROM drive). The result samples are
-forwarded to the front DAC PCM slots of the Philips DAC.
-
-name='Audigy CD Capture Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 TTL
-digital inputs (usually used by a CDROM drive). The result samples are
-forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
-
-name='IEC958 Optical Playback Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 optical
-digital input. The result samples are forwarded to the front DAC PCM slots
-of the Philips DAC.
-
-name='IEC958 Optical Capture Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 optical
-digital inputs. The result samples are forwarded to the ADC capture FIFO
-(thus to the standard capture PCM device).
-
-name='Line2 Playback Volume',index=0
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs (on the AudigyDrive). The result samples are forwarded to the front
-DAC PCM slots of the Philips DAC.
-
-name='Line2 Capture Volume',index=1
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs (on the AudigyDrive). The result samples are forwarded to the ADC
-capture FIFO (thus to the standard capture PCM device).
-
-name='Analog Mix Playback Volume',index=0
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs from Philips ADC. The result samples are forwarded to the front
-DAC PCM slots of the Philips DAC. This contains mix from analog sources
-like CD, Line In, Aux, ....
-
-name='Analog Mix Capture Volume',index=1
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs Philips ADC. The result samples are forwarded to the ADC
-capture FIFO (thus to the standard capture PCM device).
-
-name='Aux2 Playback Volume',index=0
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs (on the AudigyDrive). The result samples are forwarded to the front
-DAC PCM slots of the Philips DAC.
-
-name='Aux2 Capture Volume',index=1
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs (on the AudigyDrive). The result samples are forwarded to the ADC
-capture FIFO (thus to the standard capture PCM device).
-
-name='Front Playback Volume',index=0
-
-All stereo signals are mixed together and mirrored to surround, center and LFE.
-This control is used to attenuate samples for left and right front speakers of
-this mix.
-
-name='Surround Playback Volume',index=0
-
-All stereo signals are mixed together and mirrored to surround, center and LFE.
-This control is used to attenuate samples for left and right surround speakers of
-this mix.
-
-name='Center Playback Volume',index=0
-
-All stereo signals are mixed together and mirrored to surround, center and LFE.
-This control is used to attenuate sample for center speaker of this mix.
-
-name='LFE Playback Volume',index=0
-
-All stereo signals are mixed together and mirrored to surround, center and LFE.
-This control is used to attenuate sample for LFE speaker of this mix.
-
-name='Tone Control - Switch',index=0
-
-This control turns the tone control on or off. The samples for front, rear
-and center / LFE outputs are affected.
-
-name='Tone Control - Bass',index=0
-
-This control sets the bass intensity. There is no neutral value!!
-When the tone control code is activated, the samples are always modified.
-The closest value to pure signal is 20.
-
-name='Tone Control - Treble',index=0
-
-This control sets the treble intensity. There is no neutral value!!
-When the tone control code is activated, the samples are always modified.
-The closest value to pure signal is 20.
-
-name='Master Playback Volume',index=0
-
-This control is used to attenuate samples for front, surround, center and 
-LFE outputs.
-
-name='IEC958 Optical Raw Playback Switch',index=0
-
-If this switch is on, then the samples for the IEC958 (S/PDIF) digital
-output are taken only from the raw FX8010 PCM, otherwise standard front
-PCM samples are taken.
-
-
-2) PCM stream related controls
-------------------------------
-
-name='EMU10K1 PCM Volume',index 0-31
-
-Channel volume attenuation in range 0-0xffff. The maximum value (no
-attenuation) is default. The channel mapping for three values is
-as follows:
-
-	0 - mono, default 0xffff (no attenuation)
-	1 - left, default 0xffff (no attenuation)
-	2 - right, default 0xffff (no attenuation)
-
-name='EMU10K1 PCM Send Routing',index 0-31
-
-This control specifies the destination - FX-bus accumulators. There 24
-values with this mapping:
-
-	 0 -  mono, A destination (FX-bus 0-63), default 0
-	 1 -  mono, B destination (FX-bus 0-63), default 1
-	 2 -  mono, C destination (FX-bus 0-63), default 2
-	 3 -  mono, D destination (FX-bus 0-63), default 3
-	 4 -  mono, E destination (FX-bus 0-63), default 0
-	 5 -  mono, F destination (FX-bus 0-63), default 0
-	 6 -  mono, G destination (FX-bus 0-63), default 0
-	 7 -  mono, H destination (FX-bus 0-63), default 0
-	 8 -  left, A destination (FX-bus 0-63), default 0
-	 9 -  left, B destination (FX-bus 0-63), default 1
-	10 -  left, C destination (FX-bus 0-63), default 2
-	11 -  left, D destination (FX-bus 0-63), default 3
-	12 -  left, E destination (FX-bus 0-63), default 0
-	13 -  left, F destination (FX-bus 0-63), default 0
-	14 -  left, G destination (FX-bus 0-63), default 0
-	15 -  left, H destination (FX-bus 0-63), default 0
-	16 - right, A destination (FX-bus 0-63), default 0
-	17 - right, B destination (FX-bus 0-63), default 1
-	18 - right, C destination (FX-bus 0-63), default 2
-	19 - right, D destination (FX-bus 0-63), default 3
-	20 - right, E destination (FX-bus 0-63), default 0
-	21 - right, F destination (FX-bus 0-63), default 0
-	22 - right, G destination (FX-bus 0-63), default 0
-	23 - right, H destination (FX-bus 0-63), default 0
-
-Don't forget that it's illegal to assign a channel to the same FX-bus accumulator 
-more than once (it means 0=0 && 1=0 is an invalid combination).
- 
-name='EMU10K1 PCM Send Volume',index 0-31
-
-It specifies the attenuation (amount) for given destination in range 0-255.
-The channel mapping is following:
-
-	 0 -  mono, A destination attn, default 255 (no attenuation)
-	 1 -  mono, B destination attn, default 255 (no attenuation)
-	 2 -  mono, C destination attn, default 0 (mute)
-	 3 -  mono, D destination attn, default 0 (mute)
-	 4 -  mono, E destination attn, default 0 (mute)
-	 5 -  mono, F destination attn, default 0 (mute)
-	 6 -  mono, G destination attn, default 0 (mute)
-	 7 -  mono, H destination attn, default 0 (mute)
-	 8 -  left, A destination attn, default 255 (no attenuation)
-	 9 -  left, B destination attn, default 0 (mute)
-	10 -  left, C destination attn, default 0 (mute)
-	11 -  left, D destination attn, default 0 (mute)
-	12 -  left, E destination attn, default 0 (mute)
-	13 -  left, F destination attn, default 0 (mute)
-	14 -  left, G destination attn, default 0 (mute)
-	15 -  left, H destination attn, default 0 (mute)
-	16 - right, A destination attn, default 0 (mute)
-	17 - right, B destination attn, default 255 (no attenuation)
-	18 - right, C destination attn, default 0 (mute)
-	19 - right, D destination attn, default 0 (mute)
-	20 - right, E destination attn, default 0 (mute)
-	21 - right, F destination attn, default 0 (mute)
-	22 - right, G destination attn, default 0 (mute)
-	23 - right, H destination attn, default 0 (mute)
-
-
-
-4) MANUALS/PATENTS:
--------------------
-
-ftp://opensource.creative.com/pub/doc
--------------------------------------
-
-        Files:
-        LM4545.pdf      AC97 Codec
-
-        m2049.pdf       The EMU10K1 Digital Audio Processor
-
-        hog63.ps        FX8010 - A DSP Chip Architecture for Audio Effects
-
-
-WIPO Patents
-------------
-        Patent numbers:
-        WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999)
-                        streams
-
-        WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
-
-        WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction
-                        Execution and Audio Data Sequencing (Jan. 14, 1999)
-
-
-US Patents (http://www.uspto.gov/)
-----------------------------------
-
-        US 5925841      Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
-
-        US 5928342      Audio Effects Processor integrated on a single chip (Jul. 27, 1999)
-                        with a multiport memory onto which multiple asynchronous
-                        digital sound samples can be concurrently loaded
-
-        US 5930158      Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
-
-        US 6032235      Memory initialization circuit (Tram) (Feb. 29, 2000)
-
-        US 6138207      Interpolation looping of audio samples in cache connected to    (Oct. 24, 2000)
-                        system bus with prioritization and modification of bus transfers
-                        in accordance with loop ends and minimum block sizes
-
-        US 6151670      Method for conserving memory storage using a (Nov. 21, 2000)
-                        pool of  short term memory registers
-
-        US 6195715      Interrupt control for multiple programs communicating with      (Feb. 27, 2001)
-                        a common interrupt by associating programs to GP registers,
-                        defining interrupt register, polling GP registers, and invoking
-                        callback routine associated with defined interrupt register
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/Audiophile-Usb.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Audiophile-Usb.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/Audiophile-Usb.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Audiophile-Usb.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,442 +0,0 @@
-	Guide to using M-Audio Audiophile USB with ALSA and Jack	v1.5
-	========================================================
-
-	    Thibault Le Meur <Thibault.LeMeur@supelec.fr>
-
-This document is a guide to using the M-Audio Audiophile USB (tm) device with 
-ALSA and JACK.
-
-History
-=======
-* v1.4 - Thibault Le Meur (2007-07-11)
- - Added Low Endianness nature of 16bits-modes
-   found by Hakan Lennestal <Hakan.Lennestal@brfsodrahamn.se>
- - Modifying document structure
-* v1.5 - Thibault Le Meur (2007-07-12)
- - Added AC3/DTS passthru info
-
-
-1 - Audiophile USB Specs and correct usage
-==========================================
-
-This part is a reminder of important facts about the functions and limitations 
-of the device.
-
-The device has 4 audio interfaces, and 2 MIDI ports:
- * Analog Stereo Input (Ai)
-   - This port supports 2 pairs of line-level audio inputs (1/4" TS and RCA) 
-   - When the 1/4" TS (jack) connectors are connected, the RCA connectors
-     are disabled
- * Analog Stereo Output (Ao)
- * Digital Stereo Input (Di)
- * Digital Stereo Output (Do)
- * Midi In (Mi)
- * Midi Out (Mo)
-
-The internal DAC/ADC has the following characteristics:
-* sample depth of 16 or 24 bits
-* sample rate from 8kHz to 96kHz
-* Two interfaces can't use different sample depths at the same time.
-Moreover, the Audiophile USB documentation gives the following Warning:
-"Please exit any audio application running before switching between bit depths"
-
-Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be 
-activated at the same time depending on the audio mode selected:
- * 16-bit/48kHz ==> 4 channels in + 4 channels out
-   - Ai+Ao+Di+Do
- * 24-bit/48kHz ==> 4 channels in + 2 channels out, 
-                    or 2 channels in + 4 channels out
-   - Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do
- * 24-bit/96kHz ==> 2 channels in _or_ 2 channels out (half duplex only)
-   - Ai or Ao or Di or Do
-
-Important facts about the Digital interface:
---------------------------------------------
- * The Do port additionally supports surround-encoded AC-3 and DTS passthrough, 
-though I haven't tested it under Linux
-   - Note that in this setup only the Do interface can be enabled
- * Apart from recording an audio digital stream, enabling the Di port is a way 
-to synchronize the device to an external sample clock
-   - As a consequence, the Di port must be enable only if an active Digital 
-source is connected
-   - Enabling Di when no digital source is connected can result in a 
-synchronization error (for instance sound played at an odd sample rate)
-
-
-2 - Audiophile USB MIDI support in ALSA
-=======================================
-
-The Audiophile USB MIDI ports will be automatically supported once the
-following modules have been loaded:
- * snd-usb-audio
- * snd-seq-midi
-
-No additional setting is required.
-
-
-3 - Audiophile USB Audio support in ALSA
-========================================
-
-Audio functions of the Audiophile USB device are handled by the snd-usb-audio 
-module. This module can work in a default mode (without any device-specific 
-parameter), or in an "advanced" mode with the device-specific parameter called 
-"device_setup".
-
-3.1 - Default Alsa driver mode
-------------------------------
-
-The default behavior of the snd-usb-audio driver is to list the device 
-capabilities at startup and activate the required mode when required 
-by the applications: for instance if the user is recording in a 
-24bit-depth-mode and immediately after wants to switch to a 16bit-depth mode,
-the snd-usb-audio module will reconfigure the device on the fly.
-
-This approach has the advantage to let the driver automatically switch from sample 
-rates/depths automatically according to the user's needs. However, those who 
-are using the device under windows know that this is not how the device is meant to
-work: under windows applications must be closed before using the m-audio control
-panel to switch the device working mode. Thus as we'll see in next section, this 
-Default Alsa driver mode can lead to device misconfigurations.
-
-Let's get back to the Default Alsa driver mode for now.  In this case the 
-Audiophile interfaces are mapped to alsa pcm devices in the following 
-way (I suppose the device's index is 1):
- * hw:1,0 is Ao in playback and Di in capture
- * hw:1,1 is Do in playback and Ai in capture
- * hw:1,2 is Do in AC3/DTS passthrough mode
-
-In this mode, the device uses Big Endian byte-encoding so that 
-supported audio format are S16_BE for 16-bit depth modes and S24_3BE for 
-24-bits depth mode.
-
-One exception is the hw:1,2 port which was reported to be Little Endian 
-compliant (supposedly supporting S16_LE) but processes in fact only S16_BE streams.
-This has been fixed in kernel 2.6.23 and above and now the hw:1,2 interface 
-is reported to be big endian in this default driver mode.
-
-Examples:
- * playing a S24_3BE encoded raw file to the Ao port
-   % aplay -D hw:1,0 -c2 -t raw -r48000 -fS24_3BE test.raw
- * recording a  S24_3BE encoded raw file from the Ai port
-   % arecord -D hw:1,1 -c2  -t raw -r48000 -fS24_3BE test.raw
- * playing a S16_BE encoded raw file to the Do port
-   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw
- * playing an ac3 sample file to the Do port
-   % aplay -D hw:1,2 --channels=6 ac3_S16_BE_encoded_file.raw
-
-If you're happy with the default Alsa driver mode and don't experience any 
-issue with this mode, then you can skip the following chapter.
-
-3.2 - Advanced module setup
----------------------------
-
-Due to the hardware constraints described above, the device initialization made 
-by the Alsa driver in default mode may result in a corrupted state of the 
-device. For instance, a particularly annoying issue is that the sound captured 
-from the Ai interface sounds distorted (as if boosted with an excessive high
-volume gain).
-
-For people having this problem, the snd-usb-audio module has a new module 
-parameter called "device_setup" (this parameter was introduced in kernel
-release 2.6.17)
-
-3.2.1 - Initializing the working mode of the Audiophile USB
-
-As far as the Audiophile USB device is concerned, this value let the user 
-specify:
- * the sample depth
- * the sample rate
- * whether the Di port is used or not 
-
-When initialized with "device_setup=0x00", the snd-usb-audio module has
-the same behaviour as when the parameter is omitted (see paragraph "Default 
-Alsa driver mode" above)
-
-Others modes are described in the following subsections.
-
-3.2.1.1 - 16-bit modes
-
-The two supported modes are:
-
- * device_setup=0x01
-   - 16bits 48kHz mode with Di disabled
-   - Ai,Ao,Do can be used at the same time
-   - hw:1,0 is not available in capture mode
-   - hw:1,2 is not available
-
- * device_setup=0x11
-   - 16bits 48kHz mode with Di enabled
-   - Ai,Ao,Di,Do can be used at the same time
-   - hw:1,0 is available in capture mode
-   - hw:1,2 is not available
-
-In this modes the device operates only at 16bits-modes. Before kernel 2.6.23,
-the devices where reported to be Big-Endian when in fact they were Little-Endian
-so that playing a file was a matter of using:
-   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test_S16_LE.raw
-where "test_S16_LE.raw" was in fact a little-endian sample file.
-
-Thanks to Hakan Lennestal (who discovered the Little-Endiannes of the device in
-these modes) a fix has been committed (expected in kernel 2.6.23) and
-Alsa now reports Little-Endian interfaces. Thus playing a file now is as simple as
-using:
-   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_LE test_S16_LE.raw
-
-3.2.1.2 - 24-bit modes
-
-The three supported modes are:
-
- * device_setup=0x09
-   - 24bits 48kHz mode with Di disabled
-   - Ai,Ao,Do can be used at the same time
-   - hw:1,0 is not available in capture mode
-   - hw:1,2 is not available
-
- * device_setup=0x19
-   - 24bits 48kHz mode with Di enabled
-   - 3 ports from {Ai,Ao,Di,Do} can be used at the same time
-   - hw:1,0 is available in capture mode and an active digital source must be 
-     connected to Di
-   - hw:1,2 is not available
-
- * device_setup=0x0D or 0x10
-   - 24bits 96kHz mode
-   - Di is enabled by default for this mode but does not need to be connected 
-     to an active source
-   - Only 1 port from {Ai,Ao,Di,Do} can be used at the same time
-   - hw:1,0 is available in captured mode
-   - hw:1,2 is not available
-
-In these modes the device is only Big-Endian compliant (see "Default Alsa driver 
-mode" above for an aplay command example)
-
-3.2.1.3 - AC3 w/ DTS passthru mode
-
-Thanks to Hakan Lennestal, I now have a report saying that this mode works.
-
- * device_setup=0x03
-   - 16bits 48kHz mode with only the Do port enabled 
-   - AC3 with DTS passthru
-   - Caution with this setup the Do port is mapped to the pcm device hw:1,0
-
-The command line used to playback the AC3/DTS encoded .wav-files in this mode:
-   % aplay -D hw:1,0 --channels=6 ac3_S16_LE_encoded_file.raw
-
-3.2.2 - How to use the device_setup parameter
-----------------------------------------------
-
-The parameter can be given:
-
- * By manually probing the device (as root):
-   # modprobe -r snd-usb-audio
-   # modprobe snd-usb-audio index=1 device_setup=0x09
-
- * Or while configuring the modules options in your modules configuration file
-   (typically a .conf file in /etc/modprobe.d/ directory:
-       alias snd-card-1 snd-usb-audio
-       options snd-usb-audio index=1 device_setup=0x09
-
-CAUTION when initializing the device
--------------------------------------
-
- * Correct initialization on the device requires that device_setup is given to
-   the module BEFORE the device is turned on. So, if you use the "manual probing"
-   method described above, take care to power-on the device AFTER this initialization.
-
- * Failing to respect this will lead to a misconfiguration of the device. In this case
-   turn off the device, unprobe the snd-usb-audio module, then probe it again with
-   correct device_setup parameter and then (and only then) turn on the device again.
-
- * If you've correctly initialized the device in a valid mode and then want to switch
-   to  another mode (possibly with another sample-depth), please use also the following 
-   procedure:
-   - first turn off the device
-   - de-register the snd-usb-audio module (modprobe -r)
-   - change the device_setup parameter by changing the device_setup
-     option in /etc/modprobe.d/*.conf
-   - turn on the device
- * A workaround for this last issue has been applied to kernel 2.6.23, but it may not
-   be enough to ensure the 'stability' of the device initialization.
-
-3.2.3 - Technical details for hackers
--------------------------------------
-This section is for hackers, wanting to understand details about the device
-internals and how Alsa supports it.
-
-3.2.3.1 - Audiophile USB's device_setup structure
-
-If you want to understand the device_setup magic numbers for the Audiophile 
-USB, you need some very basic understanding of binary computation. However, 
-this is not required to use the parameter and you may skip this section.
-
-The device_setup is one byte long and its structure is the following:
-
-       +---+---+---+---+---+---+---+---+
-       | b7| b6| b5| b4| b3| b2| b1| b0|
-       +---+---+---+---+---+---+---+---+
-       | 0 | 0 | 0 | Di|24B|96K|DTS|SET|
-       +---+---+---+---+---+---+---+---+
-
-Where:
- * b0 is the "SET" bit
-   - it MUST be set if device_setup is initialized 
- * b1 is the "DTS" bit
-   - it is set only for Digital output with DTS/AC3
-   - this setup is not tested
- * b2 is the Rate selection flag
-   - When set to "1" the rate range is 48.1-96kHz
-   - Otherwise the sample rate range is 8-48kHz
- * b3 is the bit depth selection flag
-   - When set to "1" samples are 24bits long
-   - Otherwise they are 16bits long
-   - Note that b2 implies b3 as the 96kHz mode is only supported for 24 bits 
-     samples
- * b4 is the Digital input flag
-   - When set to "1" the device assumes that an active digital source is 
-     connected 
-   - You shouldn't enable Di if no source is seen on the port (this leads to 
-     synchronization issues)
-   - b4 is implied by b2 (since only one port is enabled at a time no synch 
-     error can occur) 
- * b5 to b7 are reserved for future uses, and must be set to "0"
-   - might become Ao, Do, Ai, for b7, b6, b4 respectively
-
-Caution:
- * there is no check on the value you will give to device_setup
-   - for instance choosing 0x05 (16bits 96kHz) will fail back to 0x09 since 
-     b2 implies b3. But _there_will_be_no_warning_ in /var/log/messages
- * Hardware constraints due to the USB bus limitation aren't checked
-   - choosing b2 will prepare all interfaces for 24bits/96kHz but you'll
-     only be able to use one at the same time
-
-3.2.3.2 -  USB implementation details for this device
-
-You may safely skip this section if you're not interested in driver 
-hacking.
-
-This section describes some internal aspects of the device and summarizes the 
-data I got by usb-snooping the windows and Linux drivers.
-
-The M-Audio Audiophile USB has 7 USB Interfaces:
-a "USB interface":
- * USB Interface nb.0
- * USB Interface nb.1
-   - Audio Control function
- * USB Interface nb.2
-   - Analog Output
- * USB Interface nb.3
-   - Digital Output
- * USB Interface nb.4
-   - Analog Input
- * USB Interface nb.5
-   - Digital Input
- * USB Interface nb.6
-   - MIDI interface compliant with the MIDIMAN quirk 
-
-Each interface has 5 altsettings (AltSet 1,2,3,4,5) except:
- * Interface 3 (Digital Out) has an extra Alset nb.6 
- * Interface 5 (Digital In) does not have Alset nb.3 and 5 
-
-Here is a short description of the AltSettings capabilities:
- * AltSettings 1 corresponds to
-  - 24-bit depth, 48.1-96kHz sample mode
-  - Adaptive playback (Ao and Do), Synch capture (Ai), or Asynch capture (Di)
- * AltSettings 2 corresponds to
-  - 24-bit depth, 8-48kHz sample mode
-  - Asynch capture and playback  (Ao,Ai,Do,Di)
- * AltSettings 3 corresponds to
-  - 24-bit depth, 8-48kHz sample mode
-  - Synch capture (Ai) and Adaptive playback (Ao,Do)
- * AltSettings 4 corresponds to
-  - 16-bit depth, 8-48kHz sample mode
-  - Asynch capture and playback  (Ao,Ai,Do,Di)
- * AltSettings 5 corresponds to
-  - 16-bit depth, 8-48kHz sample mode
-  - Synch capture (Ai) and Adaptive playback (Ao,Do)
- * AltSettings 6 corresponds to
-  - 16-bit depth, 8-48kHz sample mode
-  - Synch playback (Do), audio format type III IEC1937_AC-3
-
-In order to ensure a correct initialization of the device, the driver 
-_must_know_ how the device will be used:
- * if DTS is chosen, only Interface 2 with AltSet nb.6 must be
-   registered
- * if 96KHz only AltSets nb.1 of each interface must be selected
- * if samples are using 24bits/48KHz then AltSet 2 must me used if
-   Digital input is connected, and only AltSet nb.3 if Digital input
-   is not connected
- * if samples are using 16bits/48KHz then AltSet 4 must me used if
-   Digital input is connected, and only AltSet nb.5 if Digital input
-   is not connected
-
-When device_setup is given as a parameter to the snd-usb-audio module, the 
-parse_audio_endpoints function uses a quirk called 
-"audiophile_skip_setting_quirk" in order to prevent AltSettings not 
-corresponding to device_setup from being registered in the driver.
-
-4 - Audiophile USB and Jack support
-===================================
-
-This section deals with support of the Audiophile USB device in Jack.
-
-There are 2 main potential issues when using Jackd with the device:
-* support for Big-Endian devices in 24-bit modes
-* support for 4-in / 4-out channels
-
-4.1 - Direct support in Jackd
------------------------------
-
-Jack supports big endian devices only in recent versions (thanks to
-Andreas Steinmetz for his first big-endian patch). I can't remember 
-exactly when this support was released into jackd, let's just say that
-with jackd version 0.103.0 it's almost ok (just a small bug is affecting 
-16bits Big-Endian devices, but since you've read carefully the above
-paragraphs, you're now using kernel >= 2.6.23 and your 16bits devices 
-are now Little Endians ;-) ).
-
-You can run jackd with the following command for playback with Ao and
-record with Ai:
-  % jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
-
-4.2 - Using Alsa plughw
------------------------
-If you don't have a recent Jackd installed, you can downgrade to using
-the Alsa "plug" converter.
-
-For instance here is one way to run Jack with 2 playback channels on Ao and 2 
-capture channels from Ai:
-  % jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1
-
-However you may see the following warning message:
-"You appear to be using the ALSA software "plug" layer, probably a result of 
-using the "default" ALSA device. This is less efficient than it could be. 
-Consider using a hardware device instead rather than using the plug layer."
-
-4.3 - Getting 2 input and/or output interfaces in Jack
-------------------------------------------------------
-
-As you can see, starting the Jack server this way will only enable 1 stereo
-input (Di or Ai) and 1 stereo output (Ao or Do).
-
-This is due to the following restrictions:
-* Jack can only open one capture device and one playback device at a time
-* The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1
-  (and optionally hw:1,2)
-
-If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to
-combine the Alsa devices into one logical "complex" device.
-
-If you want to give it a try, I recommend reading the information from
-this page: http://www.sound-man.co.uk/linuxaudio/ice1712multi.html
-It is related to another device (ice1712) but can be adapted to suit
-the Audiophile USB.
-
-Enabling multiple Audiophile USB interfaces for Jackd will certainly require:
-* Making sure your Jackd version has the MMAP_COMPLEX patch (see the ice1712 page)
-* (maybe) patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
-* define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc
-  file 
-* start jackd with this device
-
-I had no success in testing this for now, if you have any success with this kind 
-of setup, please drop me an email.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/Bt87x.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Bt87x.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/Bt87x.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Bt87x.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-Intro
-=====
-
-You might have noticed that the bt878 grabber cards have actually
-_two_ PCI functions:
-
-$ lspci
-[ ... ]
-00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02)
-00:0a.1 Multimedia controller: Brooktree Corporation Bt878 (rev 02)
-[ ... ]
-
-The first does video, it is backward compatible to the bt848.  The second
-does audio.  snd-bt87x is a driver for the second function.  It's a sound
-driver which can be used for recording sound (and _only_ recording, no
-playback).  As most TV cards come with a short cable which can be plugged
-into your sound card's line-in you probably don't need this driver if all
-you want to do is just watching TV...
-
-Some cards do not bother to connect anything to the audio input pins of
-the chip, and some other cards use the audio function to transport MPEG
-video data, so it's quite possible that audio recording may not work
-with your card.
-
-
-Driver Status
-=============
-
-The driver is now stable.  However, it doesn't know about many TV cards,
-and it refuses to load for cards it doesn't know.
-
-If the driver complains ("Unknown TV card found, the audio driver will
-not load"), you can specify the load_all=1 option to force the driver to
-try to use the audio capture function of your card.  If the frequency of
-recorded data is not right, try to specify the digital_rate option with
-other values than the default 32000 (often it's 44100 or 64000).
-
-If you have an unknown card, please mail the ID and board name to
-<alsa-devel@alsa-project.org>, regardless of whether audio capture works
-or not, so that future versions of this driver know about your card.
-
-
-Audio modes
-===========
-
-The chip knows two different modes (digital/analog).  snd-bt87x
-registers two PCM devices, one for each mode.  They cannot be used at
-the same time.
-
-
-Digital audio mode
-==================
-
-The first device (hw:X,0) gives you 16 bit stereo sound.  The sample
-rate depends on the external source which feeds the Bt87x with digital
-sound via I2S interface.
-
-
-Analog audio mode (A/D)
-=======================
-
-The second device (hw:X,1) gives you 8 or 16 bit mono sound.  Supported
-sample rates are between 119466 and 448000 Hz (yes, these numbers are
-that high).  If you've set the CONFIG_SND_BT87X_OVERCLOCK option, the
-maximum sample rate is 1792000 Hz, but audio data becomes unusable
-beyond 896000 Hz on my card.
-
-The chip has three analog inputs.  Consequently you'll get a mixer
-device to control these.
-
-
-Have fun,
-
-  Clemens
-
-
-Written by Clemens Ladisch <clemens@ladisch.de>
-big parts copied from btaudio.txt by Gerd Knorr <kraxel@bytesex.org>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/Channel-Mapping-API.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Channel-Mapping-API.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/Channel-Mapping-API.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Channel-Mapping-API.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-ALSA PCM channel-mapping API
-============================
-					Takashi Iwai <tiwai@suse.de>
-
-GENERAL
--------
-
-The channel mapping API allows user to query the possible channel maps
-and the current channel map, also optionally to modify the channel map
-of the current stream.
-
-A channel map is an array of position for each PCM channel.
-Typically, a stereo PCM stream has a channel map of
-  { front_left, front_right }
-while a 4.0 surround PCM stream has a channel map of
-  { front left, front right, rear left, rear right }.
-
-The problem, so far, was that we had no standard channel map
-explicitly, and applications had no way to know which channel
-corresponds to which (speaker) position.  Thus, applications applied
-wrong channels for 5.1 outputs, and you hear suddenly strange sound
-from rear.  Or, some devices secretly assume that center/LFE is the
-third/fourth channels while others that C/LFE as 5th/6th channels.
-
-Also, some devices such as HDMI are configurable for different speaker
-positions even with the same number of total channels.  However, there
-was no way to specify this because of lack of channel map
-specification.  These are the main motivations for the new channel
-mapping API.
-
-
-DESIGN
-------
-
-Actually, "the channel mapping API" doesn't introduce anything new in
-the kernel/user-space ABI perspective.  It uses only the existing
-control element features.
-
-As a ground design, each PCM substream may contain a control element
-providing the channel mapping information and configuration.  This
-element is specified by:
-	iface = SNDRV_CTL_ELEM_IFACE_PCM
-	name = "Playback Channel Map" or "Capture Channel Map"
-	device = the same device number for the assigned PCM substream
-	index = the same index number for the assigned PCM substream
-
-Note the name is different depending on the PCM substream direction.
-
-Each control element provides at least the TLV read operation and the
-read operation.  Optionally, the write operation can be provided to
-allow user to change the channel map dynamically.
-
-* TLV
-
-The TLV operation gives the list of available channel
-maps.  A list item of a channel map is usually a TLV of
-	type data-bytes ch0 ch1 ch2...
-where type is the TLV type value, the second argument is the total
-bytes (not the numbers) of channel values, and the rest are the
-position value for each channel.
-
-As a TLV type, either SNDRV_CTL_TLVT_CHMAP_FIXED,
-SNDRV_CTL_TLV_CHMAP_VAR or SNDRV_CTL_TLVT_CHMAP_PAIRED can be used.
-The _FIXED type is for a channel map with the fixed channel position
-while the latter two are for flexible channel positions.  _VAR type is
-for a channel map where all channels are freely swappable and _PAIRED
-type is where pair-wise channels are swappable.  For example, when you
-have {FL/FR/RL/RR} channel map, _PAIRED type would allow you to swap
-only {RL/RR/FL/FR} while _VAR type would allow even swapping FL and
-RR.
-
-These new TLV types are defined in sound/tlv.h.
-
-The available channel position values are defined in sound/asound.h,
-here is a cut:
-
-/* channel positions */
-enum {
-	SNDRV_CHMAP_UNKNOWN = 0,
-	SNDRV_CHMAP_NA,		/* N/A, silent */
-	SNDRV_CHMAP_MONO,	/* mono stream */
-	/* this follows the alsa-lib mixer channel value + 3 */
-	SNDRV_CHMAP_FL,		/* front left */
-	SNDRV_CHMAP_FR,		/* front right */
-	SNDRV_CHMAP_RL,		/* rear left */
-	SNDRV_CHMAP_RR,		/* rear right */
-	SNDRV_CHMAP_FC,		/* front center */
-	SNDRV_CHMAP_LFE,	/* LFE */
-	SNDRV_CHMAP_SL,		/* side left */
-	SNDRV_CHMAP_SR,		/* side right */
-	SNDRV_CHMAP_RC,		/* rear center */
-	/* new definitions */
-	SNDRV_CHMAP_FLC,	/* front left center */
-	SNDRV_CHMAP_FRC,	/* front right center */
-	SNDRV_CHMAP_RLC,	/* rear left center */
-	SNDRV_CHMAP_RRC,	/* rear right center */
-	SNDRV_CHMAP_FLW,	/* front left wide */
-	SNDRV_CHMAP_FRW,	/* front right wide */
-	SNDRV_CHMAP_FLH,	/* front left high */
-	SNDRV_CHMAP_FCH,	/* front center high */
-	SNDRV_CHMAP_FRH,	/* front right high */
-	SNDRV_CHMAP_TC,		/* top center */
-	SNDRV_CHMAP_TFL,	/* top front left */
-	SNDRV_CHMAP_TFR,	/* top front right */
-	SNDRV_CHMAP_TFC,	/* top front center */
-	SNDRV_CHMAP_TRL,	/* top rear left */
-	SNDRV_CHMAP_TRR,	/* top rear right */
-	SNDRV_CHMAP_TRC,	/* top rear center */
-	SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
-};
-
-When a PCM stream can provide more than one channel map, you can
-provide multiple channel maps in a TLV container type.  The TLV data
-to be returned will contain such as:
-	SNDRV_CTL_TLVT_CONTAINER 96
-	    SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC
-	    SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR
-	    SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \
-		SNDRV_CHMAP_RL SNDRV_CHMAP_RR
-
-The channel position is provided in LSB 16bits.  The upper bits are
-used for bit flags.
-
-#define SNDRV_CHMAP_POSITION_MASK	0xffff
-#define SNDRV_CHMAP_PHASE_INVERSE	(0x01 << 16)
-#define SNDRV_CHMAP_DRIVER_SPEC		(0x02 << 16)
-
-SNDRV_CHMAP_PHASE_INVERSE indicates the channel is phase inverted,
-(thus summing left and right channels would result in almost silence).
-Some digital mic devices have this.
-
-When SNDRV_CHMAP_DRIVER_SPEC is set, all the channel position values
-don't follow the standard definition above but driver-specific.
-
-* READ OPERATION
-
-The control read operation is for providing the current channel map of
-the given stream.  The control element returns an integer array
-containing the position of each channel.
-
-When this is performed before the number of the channel is specified
-(i.e. hw_params is set), it should return all channels set to
-UNKNOWN.
-
-* WRITE OPERATION
-
-The control write operation is optional, and only for devices that can
-change the channel configuration on the fly, such as HDMI.  User needs
-to pass an integer value containing the valid channel positions for
-all channels of the assigned PCM substream.
-
-This operation is allowed only at PCM PREPARED state.  When called in
-other states, it shall return an error.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/CMIPCI.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/CMIPCI.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/CMIPCI.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/CMIPCI.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,254 +0,0 @@
-         Brief Notes on C-Media 8338/8738/8768/8770 Driver
-         =================================================
-
-                   Takashi Iwai <tiwai@suse.de>
-
-
-Front/Rear Multi-channel Playback
----------------------------------
-
-CM8x38 chip can use ADC as the second DAC so that two different stereo
-channels can be used for front/rear playbacks.  Since there are two
-DACs, both streams are handled independently unlike the 4/6ch multi-
-channel playbacks in the section below.
-
-As default, ALSA driver assigns the first PCM device (i.e. hw:0,0 for
-card#0) for front and 4/6ch playbacks, while the second PCM device
-(hw:0,1) is assigned to the second DAC for rear playback.
-
-There are slight differences between the two DACs:
-
-- The first DAC supports U8 and S16LE formats, while the second DAC
-  supports only S16LE.
-- The second DAC supports only two channel stereo.
-
-Please note that the CM8x38 DAC doesn't support continuous playback
-rate but only fixed rates: 5512, 8000, 11025, 16000, 22050, 32000,
-44100 and 48000 Hz.
-
-The rear output can be heard only when "Four Channel Mode" switch is
-disabled.  Otherwise no signal will be routed to the rear speakers.
-As default it's turned on.
-
-*** WARNING ***
-When "Four Channel Mode" switch is off, the output from rear speakers
-will be FULL VOLUME regardless of Master and PCM volumes.
-This might damage your audio equipment.  Please disconnect speakers
-before your turn off this switch.
-*** WARNING ***
-
-[ Well.. I once got the output with correct volume (i.e. same with the
-  front one) and was so excited.  It was even with "Four Channel" bit
-  on and "double DAC" mode.  Actually I could hear separate 4 channels
-  from front and rear speakers!  But.. after reboot, all was gone.
-  It's a very pity that I didn't save the register dump at that
-  time..  Maybe there is an unknown register to achieve this... ]
-
-If your card has an extra output jack for the rear output, the rear
-playback should be routed there as default.  If not, there is a
-control switch in the driver "Line-In As Rear", which you can change
-via alsamixer or somewhat else.  When this switch is on, line-in jack
-is used as rear output.
-
-There are two more controls regarding to the rear output.
-The "Exchange DAC" switch is used to exchange front and rear playback
-routes, i.e. the 2nd DAC is output from front output.
-
-
-4/6 Multi-Channel Playback
---------------------------
-
-The recent CM8738 chips support for the 4/6 multi-channel playback
-function.  This is useful especially for AC3 decoding.
-
-When the multi-channel is supported, the driver name has a suffix
-"-MC" such like "CMI8738-MC6".  You can check this name from
-/proc/asound/cards.
-
-When the 4/6-ch output is enabled, the second DAC accepts up to 6 (or
-4) channels.  While the dual DAC supports two different rates or
-formats, the 4/6-ch playback supports only the same condition for all
-channels.  Since the multi-channel playback mode uses both DACs, you
-cannot operate with full-duplex.
-
-The 4.0 and 5.1 modes are defined as the pcm "surround40" and "surround51"
-in alsa-lib.  For example, you can play a WAV file with 6 channels like
-
-	% aplay -Dsurround51 sixchannels.wav
-
-For programming the 4/6 channel playback, you need to specify the PCM
-channels as you like and set the format S16LE.  For example, for playback
-with 4 channels,
-
-	snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
-	    // or mmap if you like
-	snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_S16_LE);
-	snd_pcm_hw_params_set_channels(pcm, hw, 4);
-
-and use the interleaved 4 channel data.
-
-There are some control switches affecting to the speaker connections:
-
-"Line-In Mode"	- an enum control to change the behavior of line-in
-	jack.  Either "Line-In", "Rear Output" or "Bass Output" can
-	be selected.  The last item is available only with model 039
-	or newer. 
-	When "Rear Output" is chosen, the surround channels 3 and 4
-	are output to line-in jack.
-"Mic-In Mode"	- an enum control to change the behavior of mic-in
-	jack.  Either "Mic-In" or "Center/LFE Output" can be
-	selected. 
-	When "Center/LFE Output" is chosen, the center and bass
-	channels (channels 5 and 6) are output to mic-in jack. 
-
-Digital I/O
------------
-
-The CM8x38 provides the excellent SPDIF capability with very cheap
-price (yes, that's the reason I bought the card :)
-
-The SPDIF playback and capture are done via the third PCM device
-(hw:0,2).  Usually this is assigned to the PCM device "spdif".
-The available rates are 44100 and 48000 Hz.
-For playback with aplay, you can run like below:
-
-	% aplay -Dhw:0,2 foo.wav
-
-or
-
-	% aplay -Dspdif foo.wav
-
-24bit format is also supported experimentally.
-
-The playback and capture over SPDIF use normal DAC and ADC,
-respectively, so you cannot playback both analog and digital streams
-simultaneously.
-
-To enable SPDIF output, you need to turn on "IEC958 Output Switch"
-control via mixer or alsactl ("IEC958" is the official name of
-so-called S/PDIF).  Then you'll see the red light on from the card so
-you know that's working obviously :)
-The SPDIF input is always enabled, so you can hear SPDIF input data
-from line-out with "IEC958 In Monitor" switch at any time (see
-below).
-
-You can play via SPDIF even with the first device (hw:0,0),
-but SPDIF is enabled only when the proper format (S16LE), sample rate
-(441100 or 48000) and channels (2) are used.  Otherwise it's turned
-off.  (Also don't forget to turn on "IEC958 Output Switch", too.)
-
-
-Additionally there are relevant control switches:
-
-"IEC958 Mix Analog" - Mix analog PCM playback and FM-OPL/3 streams and
-	output through SPDIF.  This switch appears only on old chip
-	models (CM8738 033 and 037).
-	Note: without this control you can output PCM to SPDIF.
-	This is "mixing" of streams, so e.g. it's not for AC3 output
-	(see the next section).
-
-"IEC958 In Select"  - Select SPDIF input, the internal CD-in (false)
-	and the external input (true).
-
-"IEC958 Loop"       - SPDIF input data is loop back into SPDIF
-	output (aka bypass)
-
-"IEC958 Copyright"  - Set the copyright bit.
-
-"IEC958 5V"         - Select 0.5V (coax) or 5V (optical) interface.
-	On some cards this doesn't work and you need to change the
-	configuration with hardware dip-switch.
-
-"IEC958 In Monitor" - SPDIF input is routed to DAC.
-
-"IEC958 In Phase Inverse" - Set SPDIF input format as inverse.
-	[FIXME: this doesn't work on all chips..]
-
-"IEC958 In Valid"   - Set input validity flag detection.
-
-Note: When "PCM Playback Switch" is on, you'll hear the digital output
-stream through analog line-out.
-
-
-The AC3 (RAW DIGITAL) OUTPUT
-----------------------------
-
-The driver supports raw digital (typically AC3) i/o over SPDIF.  This
-can be toggled via IEC958 playback control, but usually you need to
-access it via alsa-lib.  See alsa-lib documents for more details.
-
-On the raw digital mode, the "PCM Playback Switch" is automatically
-turned off so that non-audio data is heard from the analog line-out.
-Similarly the following switches are off: "IEC958 Mix Analog" and
-"IEC958 Loop".  The switches are resumed after closing the SPDIF PCM
-device automatically to the previous state.
-
-On the model 033, AC3 is implemented by the software conversion in
-the alsa-lib.  If you need to bypass the software conversion of IEC958
-subframes, pass the "soft_ac3=0" module option.  This doesn't matter
-on the newer models.
-
-
-ANALOG MIXER INTERFACE
-----------------------
-
-The mixer interface on CM8x38 is similar to SB16.
-There are Master, PCM, Synth, CD, Line, Mic and PC Speaker playback
-volumes.  Synth, CD, Line and Mic have playback and capture switches,
-too, as well as SB16.
-
-In addition to the standard SB mixer, CM8x38 provides more functions.
-- PCM playback switch
-- PCM capture switch (to capture the data sent to DAC)
-- Mic Boost switch
-- Mic capture volume
-- Aux playback volume/switch and capture switch
-- 3D control switch
-
-
-MIDI CONTROLLER
----------------
-
-With CMI8338 chips, the MPU401-UART interface is disabled as default.
-You need to set the module option "mpu_port" to a valid I/O port address
-to enable MIDI support.  Valid I/O ports are 0x300, 0x310, 0x320 and
-0x330.  Choose a value that doesn't conflict with other cards.
-
-With CMI8738 and newer chips, the MIDI interface is enabled by default
-and the driver automatically chooses a port address.
-
-There is _no_ hardware wavetable function on this chip (except for
-OPL3 synth below).
-What's said as MIDI synth on Windows is a software synthesizer
-emulation.  On Linux use TiMidity or other softsynth program for
-playing MIDI music.
-
-
-FM OPL/3 Synth
---------------
-
-The FM OPL/3 is also enabled as default only for the first card.
-Set "fm_port" module option for more cards.
-
-The output quality of FM OPL/3 is, however, very weird.
-I don't know why..
-
-CMI8768 and newer chips do not have the FM synth.
-
-
-Joystick and Modem
-------------------
-
-The legacy joystick is supported.  To enable the joystick support, pass
-joystick_port=1 module option.  The value 1 means the auto-detection.
-If the auto-detection fails, try to pass the exact I/O address.
-
-The modem is enabled dynamically via a card control switch "Modem".
-
-
-Debugging Information
----------------------
-
-The registers are shown in /proc/asound/cardX/cmipci.  If you have any
-problem (especially unexpected behavior of mixer), please attach the
-output of this proc file together with the bug report.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/compress_offload.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/compress_offload.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/compress_offload.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/compress_offload.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,234 +0,0 @@
-		compress_offload.txt
-		=====================
-	Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
-		Vinod Koul <vinod.koul@linux.intel.com>
-
-Overview
-
-Since its early days, the ALSA API was defined with PCM support or
-constant bitrates payloads such as IEC61937 in mind. Arguments and
-returned values in frames are the norm, making it a challenge to
-extend the existing API to compressed data streams.
-
-In recent years, audio digital signal processors (DSP) were integrated
-in system-on-chip designs, and DSPs are also integrated in audio
-codecs. Processing compressed data on such DSPs results in a dramatic
-reduction of power consumption compared to host-based
-processing. Support for such hardware has not been very good in Linux,
-mostly because of a lack of a generic API available in the mainline
-kernel.
-
-Rather than requiring a compatibility break with an API change of the
-ALSA PCM interface, a new 'Compressed Data' API is introduced to
-provide a control and data-streaming interface for audio DSPs.
-
-The design of this API was inspired by the 2-year experience with the
-Intel Moorestown SOC, with many corrections required to upstream the
-API in the mainline kernel instead of the staging tree and make it
-usable by others.
-
-Requirements
-
-The main requirements are:
-
-- separation between byte counts and time. Compressed formats may have
-  a header per file, per frame, or no header at all. The payload size
-  may vary from frame-to-frame. As a result, it is not possible to
-  estimate reliably the duration of audio buffers when handling
-  compressed data. Dedicated mechanisms are required to allow for
-  reliable audio-video synchronization, which requires precise
-  reporting of the number of samples rendered at any given time.
-
-- Handling of multiple formats. PCM data only requires a specification
-  of the sampling rate, number of channels and bits per sample. In
-  contrast, compressed data comes in a variety of formats. Audio DSPs
-  may also provide support for a limited number of audio encoders and
-  decoders embedded in firmware, or may support more choices through
-  dynamic download of libraries.
-
-- Focus on main formats. This API provides support for the most
-  popular formats used for audio and video capture and playback. It is
-  likely that as audio compression technology advances, new formats
-  will be added.
-
-- Handling of multiple configurations. Even for a given format like
-  AAC, some implementations may support AAC multichannel but HE-AAC
-  stereo. Likewise WMA10 level M3 may require too much memory and cpu
-  cycles. The new API needs to provide a generic way of listing these
-  formats.
-
-- Rendering/Grabbing only. This API does not provide any means of
-  hardware acceleration, where PCM samples are provided back to
-  user-space for additional processing. This API focuses instead on
-  streaming compressed data to a DSP, with the assumption that the
-  decoded samples are routed to a physical output or logical back-end.
-
- - Complexity hiding. Existing user-space multimedia frameworks all
-  have existing enums/structures for each compressed format. This new
-  API assumes the existence of a platform-specific compatibility layer
-  to expose, translate and make use of the capabilities of the audio
-  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
-  applications are not supposed to make use of this API.
-
-
-Design
-
-The new API shares a number of concepts with the PCM API for flow
-control. Start, pause, resume, drain and stop commands have the same
-semantics no matter what the content is.
-
-The concept of memory ring buffer divided in a set of fragments is
-borrowed from the ALSA PCM API. However, only sizes in bytes can be
-specified.
-
-Seeks/trick modes are assumed to be handled by the host.
-
-The notion of rewinds/forwards is not supported. Data committed to the
-ring buffer cannot be invalidated, except when dropping all buffers.
-
-The Compressed Data API does not make any assumptions on how the data
-is transmitted to the audio DSP. DMA transfers from main memory to an
-embedded audio cluster or to a SPI interface for external DSPs are
-possible. As in the ALSA PCM case, a core set of routines is exposed;
-each driver implementer will have to write support for a set of
-mandatory routines and possibly make use of optional ones.
-
-The main additions are
-
-- get_caps
-This routine returns the list of audio formats supported. Querying the
-codecs on a capture stream will return encoders, decoders will be
-listed for playback streams.
-
-- get_codec_caps For each codec, this routine returns a list of
-capabilities. The intent is to make sure all the capabilities
-correspond to valid settings, and to minimize the risks of
-configuration failures. For example, for a complex codec such as AAC,
-the number of channels supported may depend on a specific profile. If
-the capabilities were exposed with a single descriptor, it may happen
-that a specific combination of profiles/channels/formats may not be
-supported. Likewise, embedded DSPs have limited memory and cpu cycles,
-it is likely that some implementations make the list of capabilities
-dynamic and dependent on existing workloads. In addition to codec
-settings, this routine returns the minimum buffer size handled by the
-implementation. This information can be a function of the DMA buffer
-sizes, the number of bytes required to synchronize, etc, and can be
-used by userspace to define how much needs to be written in the ring
-buffer before playback can start.
-
-- set_params
-This routine sets the configuration chosen for a specific codec. The
-most important field in the parameters is the codec type; in most
-cases decoders will ignore other fields, while encoders will strictly
-comply to the settings
-
-- get_params
-This routines returns the actual settings used by the DSP. Changes to
-the settings should remain the exception.
-
-- get_timestamp
-The timestamp becomes a multiple field structure. It lists the number
-of bytes transferred, the number of samples processed and the number
-of samples rendered/grabbed. All these values can be used to determine
-the average bitrate, figure out if the ring buffer needs to be
-refilled or the delay due to decoding/encoding/io on the DSP.
-
-Note that the list of codecs/profiles/modes was derived from the
-OpenMAX AL specification instead of reinventing the wheel.
-Modifications include:
-- Addition of FLAC and IEC formats
-- Merge of encoder/decoder capabilities
-- Profiles/modes listed as bitmasks to make descriptors more compact
-- Addition of set_params for decoders (missing in OpenMAX AL)
-- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
-- Addition of format information for WMA
-- Addition of encoding options when required (derived from OpenMAX IL)
-- Addition of rateControlSupported (missing in OpenMAX AL)
-
-Gapless Playback
-================
-When playing thru an album, the decoders have the ability to skip the encoder
-delay and padding and directly move from one track content to another. The end
-user can perceive this as gapless playback as we don't have silence while
-switching from one track to another
-
-Also, there might be low-intensity noises due to encoding. Perfect gapless is
-difficult to reach with all types of compressed data, but works fine with most
-music content. The decoder needs to know the encoder delay and encoder padding.
-So we need to pass this to DSP. This metadata is extracted from ID3/MP4 headers
-and are not present by default in the bitstream, hence the need for a new
-interface to pass this information to the DSP. Also DSP and userspace needs to
-switch from one track to another and start using data for second track.
-
-The main additions are:
-
-- set_metadata
-This routine sets the encoder delay and encoder padding. This can be used by
-decoder to strip the silence. This needs to be set before the data in the track
-is written.
-
-- set_next_track
-This routine tells DSP that metadata and write operation sent after this would
-correspond to subsequent track
-
-- partial drain
-This is called when end of file is reached. The userspace can inform DSP that
-EOF is reached and now DSP can start skipping padding delay. Also next write
-data would belong to next track
-
-Sequence flow for gapless would be:
-- Open
-- Get caps / codec caps
-- Set params
-- Set metadata of the first track
-- Fill data of the first track
-- Trigger start
-- User-space finished sending all,
-- Indicate next track data by sending set_next_track
-- Set metadata of the next track
-- then call partial_drain to flush most of buffer in DSP
-- Fill data of the next track
-- DSP switches to second track
-(note: order for partial_drain and write for next track can be reversed as well)
-
-Not supported:
-
-- Support for VoIP/circuit-switched calls is not the target of this
-  API. Support for dynamic bit-rate changes would require a tight
-  coupling between the DSP and the host stack, limiting power savings.
-
-- Packet-loss concealment is not supported. This would require an
-  additional interface to let the decoder synthesize data when frames
-  are lost during transmission. This may be added in the future.
-
-- Volume control/routing is not handled by this API. Devices exposing a
-  compressed data interface will be considered as regular ALSA devices;
-  volume changes and routing information will be provided with regular
-  ALSA kcontrols.
-
-- Embedded audio effects. Such effects should be enabled in the same
-  manner, no matter if the input was PCM or compressed.
-
-- multichannel IEC encoding. Unclear if this is required.
-
-- Encoding/decoding acceleration is not supported as mentioned
-  above. It is possible to route the output of a decoder to a capture
-  stream, or even implement transcoding capabilities. This routing
-  would be enabled with ALSA kcontrols.
-
-- Audio policy/resource management. This API does not provide any
-  hooks to query the utilization of the audio DSP, nor any preemption
-  mechanisms.
-
-- No notion of underrun/overrun. Since the bytes written are compressed
-  in nature and data written/read doesn't translate directly to
-  rendered output in time, this does not deal with underrun/overrun and
-  maybe dealt in user-library
-
-Credits:
-- Mark Brown and Liam Girdwood for discussions on the need for this API
-- Harsha Priya for her work on intel_sst compressed API
-- Rakesh Ughreja for valuable feedback
-- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
-  demonstrating and quantifying the benefits of audio offload on a
-  real platform.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/ControlNames.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/ControlNames.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/ControlNames.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/ControlNames.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-This document describes standard names of mixer controls.
-
-Syntax: [LOCATION] SOURCE [CHANNEL] [DIRECTION] FUNCTION
-
-DIRECTION:
-  <nothing>	(both directions)
-  Playback
-  Capture
-  Bypass Playback
-  Bypass Capture
-
-FUNCTION:
-  Switch	(on/off switch)
-  Volume
-  Route		(route control, hardware specific)
-
-CHANNEL:
-  <nothing>     (channel independent, or applies to all channels)
-  Front
-  Surround      (rear left/right in 4.0/5.1 surround)
-  CLFE
-  Center
-  LFE
-  Side          (side left/right for 7.1 surround)
-
-LOCATION:       (physical location of source)
-  Front
-  Rear
-  Dock          (docking station)
-  Internal
-
-SOURCE:
-  Master
-  Master Mono
-  Hardware Master
-  Speaker	(internal speaker)
-  Bass Speaker	(internal LFE speaker)
-  Headphone
-  Line Out
-  Beep		(beep generator)
-  Phone
-  Phone Input
-  Phone Output
-  Synth
-  FM
-  Mic
-  Headset Mic	(mic part of combined headset jack - 4-pin headphone + mic)
-  Headphone Mic	(mic part of either/or - 3-pin headphone or mic)
-  Line		(input only, use "Line Out" for output)
-  CD
-  Video
-  Zoom Video
-  Aux
-  PCM
-  PCM Pan
-  Loopback
-  Analog Loopback	(D/A -> A/D loopback)
-  Digital Loopback	(playback -> capture loopback - without analog path)
-  Mono
-  Mono Output
-  Multi
-  ADC
-  Wave
-  Music
-  I2S
-  IEC958
-  HDMI
-  SPDIF		(output only)
-  SPDIF In
-  Digital In
-  HDMI/DP	(either HDMI or DisplayPort)
-
-Exceptions (deprecated):
-  [Analogue|Digital] Capture Source
-  [Analogue|Digital] Capture Switch	(aka input gain switch)
-  [Analogue|Digital] Capture Volume	(aka input gain volume)
-  [Analogue|Digital] Playback Switch	(aka output gain switch)
-  [Analogue|Digital] Playback Volume	(aka output gain volume)
-  Tone Control - Switch
-  Tone Control - Bass
-  Tone Control - Treble
-  3D Control - Switch
-  3D Control - Center
-  3D Control - Depth
-  3D Control - Wide
-  3D Control - Space
-  3D Control - Level
-  Mic Boost [(?dB)]
-
-PCM interface:
-
-  Sample Clock Source	{ "Word", "Internal", "AutoSync" }
-  Clock Sync Status	{ "Lock", "Sync", "No Lock" }
-  External Rate		/* external capture rate */
-  Capture Rate		/* capture rate taken from external source */
-
-IEC958 (S/PDIF) interface:
-
-  IEC958 [...] [Playback|Capture] Switch	/* turn on/off the IEC958 interface */
-  IEC958 [...] [Playback|Capture] Volume	/* digital volume control */
-  IEC958 [...] [Playback|Capture] Default	/* default or global value - read/write */
-  IEC958 [...] [Playback|Capture] Mask		/* consumer and professional mask */
-  IEC958 [...] [Playback|Capture] Con Mask	/* consumer mask */
-  IEC958 [...] [Playback|Capture] Pro Mask	/* professional mask */
-  IEC958 [...] [Playback|Capture] PCM Stream	/* the settings assigned to a PCM stream */
-  IEC958 Q-subcode [Playback|Capture] Default	/* Q-subcode bits */
-  IEC958 Preamble [Playback|Capture] Default	/* burst preamble words (4*16bits) */
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/emu10k1-jack.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/emu10k1-jack.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/emu10k1-jack.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/emu10k1-jack.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-This document is a guide to using the emu10k1 based devices with JACK for low
-latency, multichannel recording functionality.  All of my recent work to allow
-Linux users to use the full capabilities of their hardware has been inspired 
-by the kX Project.  Without their work I never would have discovered the true
-power of this hardware.
-
-	http://www.kxproject.com
-						- Lee Revell, 2005.03.30
-
-Low latency, multichannel audio with JACK and the emu10k1/emu10k2
------------------------------------------------------------------
-
-Until recently, emu10k1 users on Linux did not have access to the same low
-latency, multichannel features offered by the "kX ASIO" feature of their
-Windows driver.  As of ALSA 1.0.9 this is no more!
-
-For those unfamiliar with kX ASIO, this consists of 16 capture and 16 playback
-channels.  With a post 2.6.9 Linux kernel, latencies down to 64 (1.33 ms) or
-even 32 (0.66ms) frames should work well.
-
-The configuration is slightly more involved than on Windows, as you have to
-select the correct device for JACK to use.  Actually, for qjackctl users it's
-fairly self explanatory - select Duplex, then for capture and playback select
-the multichannel devices, set the in and out channels to 16, and the sample
-rate to 48000Hz.  The command line looks like this:
-
-/usr/local/bin/jackd -R -dalsa -r48000 -p64 -n2 -D -Chw:0,2 -Phw:0,3 -S
-
-This will give you 16 input ports and 16 output ports.
-
-The 16 output ports map onto the 16 FX buses (or the first 16 of 64, for the
-Audigy).  The mapping from FX bus to physical output is described in
-SB-Live-mixer.txt (or Audigy-mixer.txt).
-
-The 16 input ports are connected to the 16 physical inputs.  Contrary to
-popular belief, all emu10k1 cards are multichannel cards.  Which of these
-input channels have physical inputs connected to them depends on the card
-model.  Trial and error is highly recommended; the pinout diagrams
-for the card have been reverse engineered by some enterprising kX users and are 
-available on the internet.  Meterbridge is helpful here, and the kX forums are
-packed with useful information.
-
-Each input port will either correspond to a digital (SPDIF) input, an analog
-input, or nothing.  The one exception is the SBLive! 5.1.  On these devices,
-the second and third input ports are wired to the center/LFE output.  You will
-still see 16 capture channels, but only 14 are available for recording inputs.
-
-This chart, borrowed from kxfxlib/da_asio51.cpp, describes the mapping of JACK
-ports to FXBUS2 (multitrack recording input) and EXTOUT (physical output)
-channels.
-
-/*JACK (& ASIO) mappings on 10k1 5.1 SBLive cards:
---------------------------------------------
-JACK		Epilog		FXBUS2(nr)
---------------------------------------------
-capture_1	asio14		FXBUS2(0xe)
-capture_2	asio15		FXBUS2(0xf)
-capture_3	asio0		FXBUS2(0x0)	
-~capture_4	Center		EXTOUT(0x11)	// mapped to by Center
-~capture_5	LFE		EXTOUT(0x12)	// mapped to by LFE
-capture_6	asio3		FXBUS2(0x3)
-capture_7	asio4		FXBUS2(0x4)
-capture_8	asio5		FXBUS2(0x5)
-capture_9	asio6		FXBUS2(0x6)
-capture_10	asio7		FXBUS2(0x7)
-capture_11	asio8		FXBUS2(0x8)
-capture_12	asio9		FXBUS2(0x9)
-capture_13	asio10		FXBUS2(0xa)
-capture_14	asio11		FXBUS2(0xb)
-capture_15	asio12		FXBUS2(0xc)
-capture_16	asio13		FXBUS2(0xd)
-*/
-
-TODO: describe use of ld10k1/qlo10k1 in conjunction with JACK
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio-Controls.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,116 +0,0 @@
-This file explains the codec-specific mixer controls.
-
-Realtek 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", "6ch",
-  and "8ch".  According to the configuration, this also controls the
-  jack-retasking of multi-I/O jacks.
-
-* Auto-Mute Mode
-  This is an enum control to change the auto-mute behavior of the
-  headphone and line-out jacks.  If built-in speakers and headphone
-  and/or line-out jacks are available on a machine, this controls
-  appears.
-  When there are only either headphones or line-out jacks, it gives
-  "Disabled" and "Enabled" state.  When enabled, the speaker is muted
-  automatically when a jack is plugged.
-
-  When both headphone and line-out jacks are present, it gives
-  "Disabled", "Speaker Only" and "Line-Out+Speaker".  When
-  speaker-only is chosen, plugging into a headphone or a line-out jack
-  mutes the speakers, but not line-outs.  When line-out+speaker is
-  selected, plugging to a headphone jack mutes both speakers and
-  line-outs.
-
-
-IDT/Sigmatel codecs
--------------------
-
-* Analog Loopback
-  This control enables/disables the analog-loopback circuit.  This
-  appears only when "loopback" is set to true in a codec hint
-  (see HD-Audio.txt).  Note that on some codecs the analog-loopback
-  and the normal PCM playback are exclusive, i.e. when this is on, you
-  won't hear any PCM stream.
-
-* Swap Center/LFE
-  Swaps the center and LFE channel order.  Normally, the left
-  corresponds to the center and the right to the LFE.  When this is
-  ON, the left to the LFE and the right to the center.
-
-* Headphone as Line Out
-  When this control is ON, treat the headphone jacks as line-out
-  jacks.  That is, the headphone won't auto-mute the other line-outs,
-  and no HP-amp is set to the pins.
-
-* Mic Jack Mode, Line Jack Mode, etc
-  These enum controls the direction and the bias of the input jack
-  pins.  Depending on the jack type, it can set as "Mic In" and "Line 
-  In", for determining the input bias, or it can be set to "Line Out"
-  when the pin is a multi-I/O jack for surround channels.
-
-
-VIA codecs
-----------
-
-* Smart 5.1
-  An enum control to re-task the multi-I/O jacks for surround outputs.
-  When it's ON, the corresponding input jacks (usually a line-in and a
-  mic-in) are switched as the surround and the CLFE output 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.  In the case the headphone DAC is shared with a
-  side or a CLFE-channel DAC, the DAC is switched to the headphone
-  automatically.
-
-* Loopback Mixing
-  An enum control to determine whether the analog-loopback route is
-  enabled or not.  When it's enabled, the analog-loopback is mixed to
-  the front-channel.  Also, the same route is used for the headphone
-  and speaker outputs.  As a side-effect, when this mode is set, the
-  individual volume controls will be no longer available for
-  headphones and speakers because there is only one DAC connected to a
-  mixer widget.
-
-* Dynamic Power-Control
-  This control determines whether the dynamic power-control per jack
-  detection is enabled or not.  When enabled, the widgets power state
-  (D0/D3) are changed dynamically depending on the jack plugging
-  state for saving power consumptions.  However, if your system
-  doesn't provide a proper jack-detection, this won't work; in such a
-  case, turn this control OFF.
-
-* Jack Detect
-  This control is provided only for VT1708 codec which gives no proper
-  unsolicited event per jack plug.  When this is on, the driver polls
-  the jack detection so that the headphone auto-mute can work, while 
-  turning this off would reduce the power consumption.
-
-
-Conexant codecs
----------------
-
-* 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 -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio-DP-MST-audio.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-To support DP MST audio, HD Audio hdmi codec driver introduces virtual pin
-and dynamic pcm assignment.
-
-Virtual pin is an extension of per_pin. The most difference of DP MST
-from legacy is that DP MST introduces device entry. Each pin can contain
-several device entries. Each device entry behaves as a pin.
-
-As each pin may contain several device entries and each codec may contain
-several pins, if we use one pcm per per_pin, there will be many PCMs.
-The new solution is to create a few PCMs and to dynamically bind pcm to
-per_pin. Driver uses spec->dyn_pcm_assign flag to indicate whether to use
-the new solution.
-
-PCM
-===
-To be added
-
-
-Jack
-====
-
-Presume:
- - MST must be dyn_pcm_assign, and it is acomp (for Intel scenario);
- - NON-MST may or may not be dyn_pcm_assign, it can be acomp or !acomp;
-
-So there are the following scenarios:
- a. MST (&& dyn_pcm_assign && acomp)
- b. NON-MST && dyn_pcm_assign && acomp
- c. NON-MST && !dyn_pcm_assign && !acomp
-
-Below discussion will ignore MST and NON-MST difference as it doesn't
-impact on jack handling too much.
-
-Driver uses struct hdmi_pcm pcm[] array in hdmi_spec and snd_jack is
-a member of hdmi_pcm. Each pin has one struct hdmi_pcm * pcm pointer.
-
-For !dyn_pcm_assign, per_pin->pcm will assigned to spec->pcm[n] statically.
-
-For dyn_pcm_assign, per_pin->pcm will assigned to spec->pcm[n]
-when monitor is hotplugged.
-
-
-Build Jack
-----------
-
-- dyn_pcm_assign
-Will not use hda_jack but use snd_jack in spec->pcm_rec[pcm_idx].jack directly.
-
-- !dyn_pcm_assign
-Use hda_jack and assign spec->pcm_rec[pcm_idx].jack = jack->jack statically.
-
-
-Unsolicited Event Enabling
---------------------------
-Enable unsolicited event if !acomp.
-
-
-Monitor Hotplug Event Handling
-------------------------------
-- acomp
-pin_eld_notify() -> check_presence_and_report() -> hdmi_present_sense() ->
-sync_eld_via_acomp().
-Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for
-both dyn_pcm_assign and !dyn_pcm_assign
-
-- !acomp
-Hdmi_unsol_event() -> hdmi_intrinsic_event() -> check_presence_and_report() ->
-hdmi_present_sense() -> hdmi_prepsent_sense_via_verbs()
-Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for dyn_pcm_assign.
-Use hda_jack mechanism to handle jack events.
-
-
-Others to be added later
-========================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio-Models.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio-Models.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio-Models.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,324 +0,0 @@
-  Model name	Description
-  ----------    -----------
-ALC880
-======
-  3stack	3-jack in back and a headphone out
-  3stack-digout	3-jack in back, a HP out and a SPDIF out
-  5stack	5-jack in back, 2-jack in front
-  5stack-digout	5-jack in back, 2-jack in front, a SPDIF out
-  6stack	6-jack in back, 2-jack in front
-  6stack-digout	6-jack with a SPDIF out
-
-ALC260
-======
-  gpio1		Enable GPIO1
-  coef		Enable EAPD via COEF table
-  fujitsu	Quirk for FSC S7020
-  fujitsu-jwse	Quirk for FSC S7020 with jack modes and HP mic support
-
-ALC262
-======
-  inv-dmic	Inverted internal mic workaround
-
-ALC267/268
-==========
-  inv-dmic	Inverted internal mic workaround
-  hp-eapd	Disable HP EAPD on NID 0x15
-
-ALC22x/23x/25x/269/27x/28x/29x (and vendor-specific ALC3xxx models)
-======
-  laptop-amic		Laptops with analog-mic input
-  laptop-dmic		Laptops with digital-mic input
-  alc269-dmic		Enable ALC269(VA) digital mic workaround
-  alc271-dmic		Enable ALC271X digital mic workaround
-  inv-dmic		Inverted internal mic workaround
-  headset-mic		Indicates a combined headset (headphone+mic) jack
-  headset-mode		More comprehensive headset support for ALC269 & co
-  headset-mode-no-hp-mic Headset mode support without headphone mic
-  lenovo-dock   	Enables docking station I/O for some Lenovos
-  hp-gpio-led		GPIO LED support on HP laptops
-  dell-headset-multi	Headset jack, which can also be used as mic-in
-  dell-headset-dock	Headset jack (without mic-in), and also dock I/O
-  alc283-dac-wcaps	Fixups for Chromebook with ALC283
-  alc283-sense-combo	Combo jack sensing on ALC283
-  tpt440-dock		Pin configs for Lenovo Thinkpad Dock support
-
-ALC66x/67x/892
-==============
-  mario			Chromebook mario model fixup
-  asus-mode1		ASUS
-  asus-mode2		ASUS
-  asus-mode3		ASUS
-  asus-mode4		ASUS
-  asus-mode5		ASUS
-  asus-mode6		ASUS
-  asus-mode7		ASUS
-  asus-mode8		ASUS
-  inv-dmic		Inverted internal mic workaround
-  dell-headset-multi	Headset jack, which can also be used as mic-in
-
-ALC680
-======
-  N/A
-
-ALC88x/898/1150
-======================
-  acer-aspire-4930g	Acer Aspire 4930G/5930G/6530G/6930G/7730G
-  acer-aspire-8930g	Acer Aspire 8330G/6935G
-  acer-aspire		Acer Aspire others
-  inv-dmic		Inverted internal mic workaround
-  no-primary-hp		VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC)
-
-ALC861/660
-==========
-  N/A
-
-ALC861VD/660VD
-==============
-  N/A
-
-CMI9880
-=======
-  minimal	3-jack in back
-  min_fp	3-jack in back, 2-jack in front
-  full		6-jack in back, 2-jack in front
-  full_dig	6-jack in back, 2-jack in front, SPDIF I/O
-  allout	5-jack in back, 2-jack in front, SPDIF out
-  auto		auto-config reading BIOS (default)
-
-AD1882 / AD1882A
-================
-  3stack	3-stack mode
-  3stack-automute 3-stack with automute front HP (default)
-  6stack	6-stack mode
-
-AD1884A / AD1883 / AD1984A / AD1984B
-====================================
-  desktop	3-stack desktop (default)
-  laptop	laptop with HP jack sensing
-  mobile	mobile devices with HP jack sensing
-  thinkpad	Lenovo Thinkpad X300
-  touchsmart	HP Touchsmart
-
-AD1884
-======
-  N/A
-
-AD1981
-======
-  basic		3-jack (default)
-  hp		HP nx6320
-  thinkpad	Lenovo Thinkpad T60/X60/Z60
-  toshiba	Toshiba U205
-
-AD1983
-======
-  N/A
-
-AD1984
-======
-  basic		default configuration
-  thinkpad	Lenovo Thinkpad T61/X61
-  dell_desktop	Dell T3400
-
-AD1986A
-=======
-  3stack	3-stack, shared surrounds
-  laptop	2-channel only (FSC V2060, Samsung M50)
-  laptop-imic	2-channel with built-in mic
-  eapd		Turn on EAPD constantly
-
-AD1988/AD1988B/AD1989A/AD1989B
-==============================
-  6stack	6-jack
-  6stack-dig	ditto with SPDIF
-  3stack	3-jack
-  3stack-dig	ditto with SPDIF
-  laptop	3-jack with hp-jack automute
-  laptop-dig	ditto with SPDIF
-  auto		auto-config reading BIOS (default)
-
-Conexant 5045
-=============
-  laptop-hpsense    Laptop with HP sense (old model laptop)
-  laptop-micsense   Laptop with Mic sense (old model fujitsu)
-  laptop-hpmicsense Laptop with HP and Mic senses
-  benq		Benq R55E
-  laptop-hp530	HP 530 laptop
-  test		for testing/debugging purpose, almost all controls
-		can be adjusted.  Appearing only when compiled with
-		$CONFIG_SND_DEBUG=y
-
-Conexant 5047
-=============
-  laptop	Basic Laptop config 
-  laptop-hp	Laptop config for some HP models (subdevice 30A5)
-  laptop-eapd	Laptop config with EAPD support
-  test		for testing/debugging purpose, almost all controls
-		can be adjusted.  Appearing only when compiled with
-		$CONFIG_SND_DEBUG=y
-
-Conexant 5051
-=============
-  laptop	Basic Laptop config (default)
-  hp		HP Spartan laptop
-  hp-dv6736	HP dv6736
-  hp-f700	HP Compaq Presario F700
-  ideapad	Lenovo IdeaPad laptop
-  toshiba	Toshiba Satellite M300
-
-Conexant 5066
-=============
-  laptop	Basic Laptop config (default)
-  hp-laptop	HP laptops, e g G60
-  asus		Asus K52JU, Lenovo G560
-  dell-laptop	Dell laptops
-  dell-vostro	Dell Vostro
-  olpc-xo-1_5	OLPC XO 1.5
-  ideapad       Lenovo IdeaPad U150
-  thinkpad	Lenovo Thinkpad
-
-STAC9200
-========
-  ref		Reference board
-  oqo		OQO Model 2
-  dell-d21	Dell (unknown)
-  dell-d22	Dell (unknown)
-  dell-d23	Dell (unknown)
-  dell-m21	Dell Inspiron 630m, Dell Inspiron 640m
-  dell-m22	Dell Latitude D620, Dell Latitude D820
-  dell-m23	Dell XPS M1710, Dell Precision M90
-  dell-m24	Dell Latitude 120L
-  dell-m25	Dell Inspiron E1505n
-  dell-m26	Dell Inspiron 1501
-  dell-m27	Dell Inspiron E1705/9400
-  gateway-m4	Gateway laptops with EAPD control
-  gateway-m4-2	Gateway laptops with EAPD control
-  panasonic	Panasonic CF-74
-  auto		BIOS setup (default)
-
-STAC9205/9254
-=============
-  ref		Reference board
-  dell-m42	Dell (unknown)
-  dell-m43	Dell Precision
-  dell-m44	Dell Inspiron
-  eapd		Keep EAPD on (e.g. Gateway T1616)
-  auto		BIOS setup (default)
-
-STAC9220/9221
-=============
-  ref		Reference board
-  3stack	D945 3stack
-  5stack	D945 5stack + SPDIF
-  intel-mac-v1	Intel Mac Type 1
-  intel-mac-v2	Intel Mac Type 2
-  intel-mac-v3	Intel Mac Type 3
-  intel-mac-v4	Intel Mac Type 4
-  intel-mac-v5	Intel Mac Type 5
-  intel-mac-auto Intel Mac (detect type according to subsystem id)
-  macmini	Intel Mac Mini (equivalent with type 3)
-  macbook	Intel Mac Book (eq. type 5)
-  macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3)
-  macbook-pro	Intel Mac Book Pro 2nd generation (eq. type 3)
-  imac-intel	Intel iMac (eq. type 2)
-  imac-intel-20	Intel iMac (newer version) (eq. type 3)
-  ecs202	ECS/PC chips
-  dell-d81	Dell (unknown)
-  dell-d82	Dell (unknown)
-  dell-m81	Dell (unknown)
-  dell-m82	Dell XPS M1210
-  auto		BIOS setup (default)
-
-STAC9202/9250/9251
-==================
-  ref		Reference board, base config
-  m1		Some Gateway MX series laptops (NX560XL)
-  m1-2		Some Gateway MX series laptops (MX6453)
-  m2		Some Gateway MX series laptops (M255)
-  m2-2		Some Gateway MX series laptops
-  m3		Some Gateway MX series laptops
-  m5		Some Gateway MX series laptops (MP6954)
-  m6		Some Gateway NX series laptops
-  auto		BIOS setup (default)
-
-STAC9227/9228/9229/927x
-=======================
-  ref		Reference board
-  ref-no-jd	Reference board without HP/Mic jack detection
-  3stack	D965 3stack
-  5stack	D965 5stack + SPDIF
-  5stack-no-fp	D965 5stack without front panel
-  dell-3stack	Dell Dimension E520
-  dell-bios	Fixes with Dell BIOS setup
-  dell-bios-amic Fixes with Dell BIOS setup including analog mic
-  volknob	Fixes with volume-knob widget 0x24
-  auto		BIOS setup (default)
-
-STAC92HD71B*
-============
-  ref		Reference board
-  dell-m4-1	Dell desktops
-  dell-m4-2	Dell desktops
-  dell-m4-3	Dell desktops
-  hp-m4		HP mini 1000
-  hp-dv5	HP dv series
-  hp-hdx	HP HDX series
-  hp-dv4-1222nr	HP dv4-1222nr (with LED support)
-  auto		BIOS setup (default)
-
-STAC92HD73*
-===========
-  ref		Reference board
-  no-jd		BIOS setup but without jack-detection
-  intel		Intel DG45* mobos
-  dell-m6-amic	Dell desktops/laptops with analog mics
-  dell-m6-dmic	Dell desktops/laptops with digital mics
-  dell-m6	Dell desktops/laptops with both type of mics
-  dell-eq	Dell desktops/laptops
-  alienware	Alienware M17x
-  auto		BIOS setup (default)
-
-STAC92HD83*
-===========
-  ref		Reference board
-  mic-ref	Reference board with power management for ports
-  dell-s14	Dell laptop
-  dell-vostro-3500	Dell Vostro 3500 laptop
-  hp-dv7-4000	HP dv-7 4000
-  hp_cNB11_intquad HP CNB models with 4 speakers
-  hp-zephyr	HP Zephyr
-  hp-led	HP with broken BIOS for mute LED
-  hp-inv-led	HP with broken BIOS for inverted mute LED
-  hp-mic-led	HP with mic-mute LED
-  headset-jack	Dell Latitude with a 4-pin headset jack
-  hp-envy-bass	Pin fixup for HP Envy bass speaker (NID 0x0f)
-  hp-envy-ts-bass Pin fixup for HP Envy TS bass speaker (NID 0x10)
-  hp-bnb13-eq	Hardware equalizer setup for HP laptops
-  auto		BIOS setup (default)
-
-STAC92HD95
-==========
-  hp-led	LED support for HP laptops
-  hp-bass	Bass HPF setup for HP Spectre 13
-
-STAC9872
-========
-  vaio		VAIO laptop without SPDIF
-  auto		BIOS setup (default)
-
-Cirrus Logic CS4206/4207
-========================
-  mbp55		MacBook Pro 5,5
-  imac27	IMac 27 Inch
-  auto		BIOS setup (default)
-
-Cirrus Logic CS4208
-===================
-  mba6		MacBook Air 6,1 and 6,2
-  gpio0		Enable GPIO 0 amp
-  auto		BIOS setup (default)
-
-VIA VT17xx/VT18xx/VT20xx
-========================
-  auto		BIOS setup (default)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/HD-Audio.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/HD-Audio.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,853 +0,0 @@
-MORE NOTES ON HD-AUDIO DRIVER
-=============================
-					Takashi Iwai <tiwai@suse.de>
-
-
-GENERAL
--------
-
-HD-audio is the new standard on-board audio component on modern PCs
-after AC97.  Although Linux has been supporting HD-audio since long
-time ago, there are often problems with new machines.  A part of the
-problem is broken BIOS, and the rest is the driver implementation.
-This document explains the brief trouble-shooting and debugging
-methods for the	HD-audio hardware.
-
-The HD-audio component consists of two parts: the controller chip and 
-the codec chips on the HD-audio bus.  Linux provides a single driver
-for all controllers, snd-hda-intel.  Although the driver name contains
-a word of a well-known hardware vendor, it's not specific to it but for
-all controller chips by other companies.  Since the HD-audio
-controllers are supposed to be compatible, the single snd-hda-driver
-should work in most cases.  But, not surprisingly, there are known
-bugs and issues specific to each controller type.  The snd-hda-intel
-driver has a bunch of workarounds for these as described below.
-
-A controller may have multiple codecs.  Usually you have one audio
-codec and optionally one modem codec.  In theory, there might be
-multiple audio codecs, e.g. for analog and digital outputs, and the
-driver might not work properly because of conflict of mixer elements.
-This should be fixed in future if such hardware really exists.
-
-The snd-hda-intel driver has several different codec parsers depending
-on the codec.  It has a generic parser as a fallback, but this
-functionality is fairly limited until now.  Instead of the generic
-parser, usually the codec-specific parser (coded in patch_*.c) is used
-for the codec-specific implementations.  The details about the
-codec-specific problems are explained in the later sections.
-
-If you are interested in the deep debugging of HD-audio, read the
-HD-audio specification at first.  The specification is found on
-Intel's web page, for example:
-
-- http://www.intel.com/standards/hdaudio/
-
-
-HD-AUDIO CONTROLLER
--------------------
-
-DMA-Position Problem
-~~~~~~~~~~~~~~~~~~~~
-The most common problem of the controller is the inaccurate DMA
-pointer reporting.  The DMA pointer for playback and capture can be
-read in two ways, either via a LPIB register or via a position-buffer
-map.  As default the driver tries to read from the io-mapped
-position-buffer, and falls back to LPIB if the position-buffer appears
-dead.  However, this detection isn't perfect on some devices.  In such
-a case, you can change the default method via `position_fix` option.
-
-`position_fix=1` means to use LPIB method explicitly.
-`position_fix=2` means to use the position-buffer.
-`position_fix=3` means to use a combination of both methods, needed
-for some VIA controllers.  The capture stream position is corrected
-by comparing both LPIB and position-buffer values.
-`position_fix=4` is another combination available for all controllers,
-and uses LPIB for the playback and the position-buffer for the capture
-streams.
-0 is the default value for all other
-controllers, the automatic check and fallback to LPIB as described in
-the above.  If you get a problem of repeated sounds, this option might
-help.
-
-In addition to that, every controller is known to be broken regarding
-the wake-up timing.  It wakes up a few samples before actually
-processing the data on the buffer.  This caused a lot of problems, for
-example, with ALSA dmix or JACK.  Since 2.6.27 kernel, the driver puts
-an artificial delay to the wake up timing.  This delay is controlled
-via `bdl_pos_adj` option. 
-
-When `bdl_pos_adj` is a negative value (as default), it's assigned to
-an appropriate value depending on the controller chip.  For Intel
-chips, it'd be 1 while it'd be 32 for others.  Usually this works.
-Only in case it doesn't work and you get warning messages, you should
-change this parameter to other values.
-
-
-Codec-Probing Problem
-~~~~~~~~~~~~~~~~~~~~~
-A less often but a more severe problem is the codec probing.  When
-BIOS reports the available codec slots wrongly, the driver gets
-confused and tries to access the non-existing codec slot.  This often
-results in the total screw-up, and destructs the further communication
-with the codec chips.  The symptom appears usually as error messages
-like:
-------------------------------------------------------------------------
-  hda_intel: azx_get_response timeout, switching to polling mode:
-        last cmd=0x12345678
-  hda_intel: azx_get_response timeout, switching to single_cmd mode:
-        last cmd=0x12345678
-------------------------------------------------------------------------
-
-The first line is a warning, and this is usually relatively harmless.
-It means that the codec response isn't notified via an IRQ.  The
-driver uses explicit polling method to read the response.  It gives
-very slight CPU overhead, but you'd unlikely notice it.
-
-The second line is, however, a fatal error.  If this happens, usually
-it means that something is really wrong.  Most likely you are
-accessing a non-existing codec slot.
-
-Thus, if the second error message appears, try to narrow the probed
-codec slots via `probe_mask` option.  It's a bitmask, and each bit
-corresponds to the codec slot.  For example, to probe only the first
-slot, pass `probe_mask=1`.  For the first and the third slots, pass
-`probe_mask=5` (where 5 = 1 | 4), and so on.
-
-Since 2.6.29 kernel, the driver has a more robust probing method, so
-this error might happen rarely, though.
-
-On a machine with a broken BIOS, sometimes you need to force the
-driver to probe the codec slots the hardware doesn't report for use.
-In such a case, turn the bit 8 (0x100) of `probe_mask` option on.
-Then the rest 8 bits are passed as the codec slots to probe
-unconditionally.  For example, `probe_mask=0x103` will force to probe
-the codec slots 0 and 1 no matter what the hardware reports.
-
-
-Interrupt Handling
-~~~~~~~~~~~~~~~~~~
-HD-audio driver uses MSI as default (if available) since 2.6.33
-kernel as MSI works better on some machines, and in general, it's
-better for performance.  However, Nvidia controllers showed bad
-regressions with MSI (especially in a combination with AMD chipset),
-thus we disabled MSI for them.
-
-There seem also still other devices that don't work with MSI.  If you
-see a regression wrt the sound quality (stuttering, etc) or a lock-up
-in the recent kernel, try to pass `enable_msi=0` option to disable
-MSI.  If it works, you can add the known bad device to the blacklist
-defined in hda_intel.c.  In such a case, please report and give the
-patch back to the upstream developer. 
-
-
-HD-AUDIO CODEC
---------------
-
-Model Option
-~~~~~~~~~~~~
-The most common problem regarding the HD-audio driver is the
-unsupported codec features or the mismatched device configuration.
-Most of codec-specific code has several preset models, either to
-override the BIOS setup or to provide more comprehensive features.
-
-The driver checks PCI SSID and looks through the static configuration
-table until any matching entry is found.  If you have a new machine,
-you may see a message like below:
-------------------------------------------------------------------------
-    hda_codec: ALC880: BIOS auto-probing.
-------------------------------------------------------------------------
-Meanwhile, in the earlier versions, you would see a message like:
-------------------------------------------------------------------------
-    hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...
-------------------------------------------------------------------------
-Even if you see such a message, DON'T PANIC.  Take a deep breath and
-keep your towel.  First of all, it's an informational message, no
-warning, no error.  This means that the PCI SSID of your device isn't
-listed in the known preset model (white-)list.  But, this doesn't mean
-that the driver is broken.  Many codec-drivers provide the automatic
-configuration mechanism based on the BIOS setup.
-
-The HD-audio codec has usually "pin" widgets, and BIOS sets the default
-configuration of each pin, which indicates the location, the
-connection type, the jack color, etc.  The HD-audio driver can guess
-the right connection judging from these default configuration values.
-However -- some codec-support codes, such as patch_analog.c, don't
-support the automatic probing (yet as of 2.6.28).  And, BIOS is often,
-yes, pretty often broken.  It sets up wrong values and screws up the
-driver.
-
-The preset model (or recently called as "fix-up") is provided
-basically to overcome such a situation.  When the matching preset
-model is found in the white-list, the driver assumes the static
-configuration of that preset with the correct pin setup, etc.
-Thus, if you have a newer machine with a slightly different PCI SSID
-(or codec SSID) from the existing one, you may have a good chance to
-re-use the same model.  You can pass the `model` option to specify the
-preset model instead of PCI (and codec-) SSID look-up.
-
-What `model` option values are available depends on the codec chip.
-Check your codec chip from the codec proc file (see "Codec Proc-File"
-section below).  It will show the vendor/product name of your codec
-chip.  Then, see Documentation/sound/alsa/HD-Audio-Models.txt file,
-the section of HD-audio driver.  You can find a list of codecs
-and `model` options belonging to each codec.  For example, for Realtek
-ALC262 codec chip, pass `model=ultra` for devices that are compatible
-with Samsung Q1 Ultra.
-
-Thus, the first thing you can do for any brand-new, unsupported and
-non-working HD-audio hardware is to check HD-audio codec and several
-different `model` option values.  If you have any luck, some of them
-might suit with your device well.
-
-There are a few special model option values:
-- when 'nofixup' is passed, the device-specific fixups in the codec
-  parser are skipped.
-- when `generic` is passed, the codec-specific parser is skipped and
-  only the generic parser is used.
-
-
-Speaker and Headphone Output
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-One of the most frequent (and obvious) bugs with HD-audio is the
-silent output from either or both of a built-in speaker and a
-headphone jack.  In general, you should try a headphone output at
-first.  A speaker output often requires more additional controls like
-the external amplifier bits.  Thus a headphone output has a slightly
-better chance.
-
-Before making a bug report, double-check whether the mixer is set up
-correctly.  The recent version of snd-hda-intel driver provides mostly
-"Master" volume control as well as "Front" volume (where Front
-indicates the front-channels).  In addition, there can be individual
-"Headphone" and "Speaker" controls.
-
-Ditto for the speaker output.  There can be "External Amplifier"
-switch on some codecs.  Turn on this if present.
-
-Another related problem is the automatic mute of speaker output by
-headphone plugging.  This feature is implemented in most cases, but
-not on every preset model or codec-support code.
-
-In anyway, try a different model option if you have such a problem.
-Some other models may match better and give you more matching
-functionality.  If none of the available models works, send a bug
-report.  See the bug report section for details.
-
-If you are masochistic enough to debug the driver problem, note the
-following:
-
-- The speaker (and the headphone, too) output often requires the
-  external amplifier.  This can be set usually via EAPD verb or a
-  certain GPIO.  If the codec pin supports EAPD, you have a better
-  chance via SET_EAPD_BTL verb (0x70c).  On others, GPIO pin (mostly
-  it's either GPIO0 or GPIO1) may turn on/off EAPD.
-- Some Realtek codecs require special vendor-specific coefficients to
-  turn on the amplifier.  See patch_realtek.c.
-- IDT codecs may have extra power-enable/disable controls on each
-  analog pin.  See patch_sigmatel.c.
-- Very rare but some devices don't accept the pin-detection verb until
-  triggered.  Issuing GET_PIN_SENSE verb (0xf09) may result in the
-  codec-communication stall.  Some examples are found in
-  patch_realtek.c.
-
-
-Capture Problems
-~~~~~~~~~~~~~~~~
-The capture problems are often because of missing setups of mixers.
-Thus, before submitting a bug report, make sure that you set up the
-mixer correctly.  For example, both "Capture Volume" and "Capture
-Switch" have to be set properly in addition to the right "Capture
-Source" or "Input Source" selection.  Some devices have "Mic Boost"
-volume or switch.
-
-When the PCM device is opened via "default" PCM (without pulse-audio
-plugin), you'll likely have "Digital Capture Volume" control as well.
-This is provided for the extra gain/attenuation of the signal in
-software, especially for the inputs without the hardware volume
-control such as digital microphones.  Unless really needed, this
-should be set to exactly 50%, corresponding to 0dB -- neither extra
-gain nor attenuation.  When you use "hw" PCM, i.e., a raw access PCM,
-this control will have no influence, though.
-
-It's known that some codecs / devices have fairly bad analog circuits,
-and the recorded sound contains a certain DC-offset.  This is no bug
-of the driver.
-
-Most of modern laptops have no analog CD-input connection.  Thus, the
-recording from CD input won't work in many cases although the driver
-provides it as the capture source.  Use CDDA instead.
-
-The automatic switching of the built-in and external mic per plugging
-is implemented on some codec models but not on every model.  Partly
-because of my laziness but mostly lack of testers.  Feel free to
-submit the improvement patch to the author.
-
-
-Direct Debugging
-~~~~~~~~~~~~~~~~
-If no model option gives you a better result, and you are a tough guy
-to fight against evil, try debugging via hitting the raw HD-audio
-codec verbs to the device.  Some tools are available: hda-emu and
-hda-analyzer.  The detailed description is found in the sections
-below.  You'd need to enable hwdep for using these tools.  See "Kernel
-Configuration" section.
-
-
-OTHER ISSUES
-------------
-
-Kernel Configuration
-~~~~~~~~~~~~~~~~~~~~
-In general, I recommend you to enable the sound debug option,
-`CONFIG_SND_DEBUG=y`, no matter whether you are debugging or not.
-This enables snd_printd() macro and others, and you'll get additional
-kernel messages at probing.
-
-In addition, you can enable `CONFIG_SND_DEBUG_VERBOSE=y`.  But this
-will give you far more messages.  Thus turn this on only when you are
-sure to want it.
-
-Don't forget to turn on the appropriate `CONFIG_SND_HDA_CODEC_*`
-options.  Note that each of them corresponds to the codec chip, not
-the controller chip.  Thus, even if lspci shows the Nvidia controller,
-you may need to choose the option for other vendors.  If you are
-unsure, just select all yes.
-
-`CONFIG_SND_HDA_HWDEP` is a useful option for debugging the driver.
-When this is enabled, the driver creates hardware-dependent devices
-(one per each codec), and you have a raw access to the device via
-these device files.  For example, `hwC0D2` will be created for the
-codec slot #2 of the first card (#0).  For debug-tools such as
-hda-verb and hda-analyzer, the hwdep device has to be enabled.
-Thus, it'd be better to turn this on always.
-
-`CONFIG_SND_HDA_RECONFIG` is a new option, and this depends on the
-hwdep option above.  When enabled, you'll have some sysfs files under
-the corresponding hwdep directory.  See "HD-audio reconfiguration"
-section below.
-
-`CONFIG_SND_HDA_POWER_SAVE` option enables the power-saving feature.
-See "Power-saving" section below.
-
-
-Codec Proc-File
-~~~~~~~~~~~~~~~
-The codec proc-file is a treasure-chest for debugging HD-audio.
-It shows most of useful information of each codec widget.
-
-The proc file is located in /proc/asound/card*/codec#*, one file per
-each codec slot.  You can know the codec vendor, product id and
-names, the type of each widget, capabilities and so on.
-This file, however, doesn't show the jack sensing state, so far.  This
-is because the jack-sensing might be depending on the trigger state.
-
-This file will be picked up by the debug tools, and also it can be fed
-to the emulator as the primary codec information.  See the debug tools
-section below.
-
-This proc file can be also used to check whether the generic parser is
-used.  When the generic parser is used, the vendor/product ID name
-will appear as "Realtek ID 0262", instead of "Realtek ALC262".
-
-
-HD-Audio Reconfiguration
-~~~~~~~~~~~~~~~~~~~~~~~~
-This is an experimental feature to allow you re-configure the HD-audio
-codec dynamically without reloading the driver.  The following sysfs
-files are available under each codec-hwdep device directory (e.g. 
-/sys/class/sound/hwC0D0):
-
-vendor_id::
-  Shows the 32bit codec vendor-id hex number.  You can change the
-  vendor-id value by writing to this file.
-subsystem_id::
-  Shows the 32bit codec subsystem-id hex number.  You can change the
-  subsystem-id value by writing to this file.
-revision_id::
-  Shows the 32bit codec revision-id hex number.  You can change the
-  revision-id value by writing to this file.
-afg::
-  Shows the AFG ID.  This is read-only.
-mfg::
-  Shows the MFG ID.  This is read-only.
-name::
-  Shows the codec name string.  Can be changed by writing to this
-  file.
-modelname::
-  Shows the currently set `model` option.  Can be changed by writing
-  to this file.
-init_verbs::
-  The extra verbs to execute at initialization.  You can add a verb by
-  writing to this file.  Pass three numbers: nid, verb and parameter
-  (separated with a space).
-hints::
-  Shows / stores hint strings for codec parsers for any use.
-  Its format is `key = value`.  For example, passing `jack_detect = no`
-  will disable the jack detection of the machine completely.
-init_pin_configs::
-  Shows the initial pin default config values set by BIOS.
-driver_pin_configs::
-  Shows the pin default values set by the codec parser explicitly.
-  This doesn't show all pin values but only the changed values by
-  the parser.  That is, if the parser doesn't change the pin default
-  config values by itself, this will contain nothing.
-user_pin_configs::
-  Shows the pin default config values to override the BIOS setup.
-  Writing this (with two numbers, NID and value) appends the new
-  value.  The given will be used instead of the initial BIOS value at
-  the next reconfiguration time.  Note that this config will override
-  even the driver pin configs, too.
-reconfig::
-  Triggers the codec re-configuration.  When any value is written to
-  this file, the driver re-initialize and parses the codec tree
-  again.  All the changes done by the sysfs entries above are taken
-  into account.
-clear::
-  Resets the codec, removes the mixer elements and PCM stuff of the
-  specified codec, and clear all init verbs and hints.
-
-For example, when you want to change the pin default configuration
-value of the pin widget 0x14 to 0x9993013f, and let the driver
-re-configure based on that state, run like below:
-------------------------------------------------------------------------
-  # echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
-  # echo 1 > /sys/class/sound/hwC0D0/reconfig  
-------------------------------------------------------------------------
-
-
-Hint Strings
-~~~~~~~~~~~~
-The codec parser have several switches and adjustment knobs for
-matching better with the actual codec or device behavior.  Many of
-them can be adjusted dynamically via "hints" strings as mentioned in
-the section above.  For example, by passing `jack_detect = no` string
-via sysfs or a patch file, you can disable the jack detection, thus
-the codec parser will skip the features like auto-mute or mic
-auto-switch.  As a boolean value, either `yes`, `no`, `true`, `false`,
-`1` or `0` can be passed.
-
-The generic parser supports the following hints:
-
-- jack_detect (bool): specify whether the jack detection is available
-  at all on this machine; default true
-- inv_jack_detect (bool): indicates that the jack detection logic is
-  inverted
-- trigger_sense (bool): indicates that the jack detection needs the
-  explicit call of AC_VERB_SET_PIN_SENSE verb
-- inv_eapd (bool): indicates that the EAPD is implemented in the
-  inverted logic
-- pcm_format_first (bool): sets the PCM format before the stream tag
-  and channel ID
-- sticky_stream (bool): keep the PCM format, stream tag and ID as long
-  as possible; default true
-- spdif_status_reset (bool): reset the SPDIF status bits at each time
-  the SPDIF stream is set up
--  pin_amp_workaround (bool): the output pin may have multiple amp
-  values
-- single_adc_amp (bool): ADCs can have only single input amps
-- auto_mute (bool): enable/disable the headphone auto-mute feature;
-  default true
-- auto_mic (bool): enable/disable the mic auto-switch feature; default
-  true
-- line_in_auto_switch (bool): enable/disable the line-in auto-switch
-  feature; default false
-- need_dac_fix (bool): limits the DACs depending on the channel count
-- primary_hp (bool): probe headphone jacks as the primary outputs;
-  default true
-- multi_io (bool): try probing multi-I/O config (e.g. shared
-  line-in/surround, mic/clfe jacks)
-- multi_cap_vol (bool): provide multiple capture volumes
-- inv_dmic_split (bool): provide split internal mic volume/switch for
-  phase-inverted digital mics
-- indep_hp (bool): provide the independent headphone PCM stream and
-  the corresponding mixer control, if available
-- add_stereo_mix_input (bool): add the stereo mix (analog-loopback
-  mix) to the input mux if available
-- add_jack_modes (bool): add "xxx Jack Mode" enum controls to each
-  I/O jack for allowing to change the headphone amp and mic bias VREF
-  capabilities
-- power_save_node (bool): advanced power management for each widget,
-  controlling the power sate (D0/D3) of each widget node depending on
-  the actual pin and stream states
-- power_down_unused (bool): power down the unused widgets, a subset of
-  power_save_node, and will be dropped in future
-- add_hp_mic (bool): add the headphone to capture source if possible
-- hp_mic_detect (bool): enable/disable the hp/mic shared input for a
-  single built-in mic case; default true
-- mixer_nid (int): specifies the widget NID of the analog-loopback
-  mixer
-
-
-Early Patching
-~~~~~~~~~~~~~~
-When CONFIG_SND_HDA_PATCH_LOADER=y is set, you can pass a "patch" as a
-firmware file for modifying the HD-audio setup before initializing the
-codec.  This can work basically like the reconfiguration via sysfs in
-the above, but it does it before the first codec configuration.
-
-A patch file is a plain text file which looks like below:
-
-------------------------------------------------------------------------
-  [codec]
-  0x12345678 0xabcd1234 2
-
-  [model]
-  auto
-
-  [pincfg]
-  0x12 0x411111f0
-
-  [verb]
-  0x20 0x500 0x03
-  0x20 0x400 0xff
-
-  [hint]
-  jack_detect = no
-------------------------------------------------------------------------
-
-The file needs to have a line `[codec]`.  The next line should contain
-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.  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.
-Note that this overrides the module option.
-
-After the `[pincfg]` line, the contents are parsed as the initial
-default pin-configurations just like `user_pin_configs` sysfs above.
-The values can be shown in user_pin_configs sysfs file, too.
-
-Similarly, the lines after `[verb]` are parsed as `init_verbs`
-sysfs entries, and the lines after `[hint]` are parsed as `hints`
-sysfs entries, respectively.
-
-Another example to override the codec vendor id from 0x12345678 to
-0xdeadbeef is like below:
-------------------------------------------------------------------------
-  [codec]
-  0x12345678 0xabcd1234 2
-
-  [vendor_id]
-  0xdeadbeef
-------------------------------------------------------------------------
-
-In the similar way, you can override the codec subsystem_id via
-`[subsystem_id]`, the revision id via `[revision_id]` line.
-Also, the codec chip name can be rewritten via `[chip_name]` line.
-------------------------------------------------------------------------
-  [codec]
-  0x12345678 0xabcd1234 2
-
-  [subsystem_id]
-  0xffff1111
-
-  [revision_id]
-  0x10
-
-  [chip_name]
-  My-own NEWS-0002
-------------------------------------------------------------------------
-
-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
-present.
-
-The patch module option is specific to each card instance, and you
-need to give one file name for each instance, separated by commas.
-For example, if you have two cards, one for an on-board analog and one 
-for an HDMI video board, you may pass patch option like below:
-------------------------------------------------------------------------
-    options snd-hda-intel patch=on-board-patch,hdmi-patch
-------------------------------------------------------------------------
-
-
-Power-Saving
-~~~~~~~~~~~~
-The power-saving is a kind of auto-suspend of the device.  When the
-device is inactive for a certain time, the device is automatically
-turned off to save the power.  The time to go down is specified via
-`power_save` module option, and this option can be changed dynamically
-via sysfs.
-
-The power-saving won't work when the analog loopback is enabled on
-some codecs.  Make sure that you mute all unneeded signal routes when
-you want the power-saving.
-
-The power-saving feature might cause audible click noises at each
-power-down/up depending on the device.  Some of them might be
-solvable, but some are hard, I'm afraid.  Some distros such as
-openSUSE enables the power-saving feature automatically when the power
-cable is unplugged.  Thus, if you hear noises, suspect first the
-power-saving.  See /sys/module/snd_hda_intel/parameters/power_save to
-check the current value.  If it's non-zero, the feature is turned on.
-
-The recent kernel supports the runtime PM for the HD-audio controller
-chip, too.  It means that the HD-audio controller is also powered up /
-down dynamically.  The feature is enabled only for certain controller
-chips like Intel LynxPoint.  You can enable/disable this feature
-forcibly by setting `power_save_controller` option, which is also
-available at /sys/module/snd_hda_intel/parameters directory.
-
-
-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.git
-
-The master branch or for-next branches can be used as the main
-development branches in general while the development for the current
-and next kernels are found in for-linus and for-next branches,
-respectively.
-
-
-Sending a Bug Report
-~~~~~~~~~~~~~~~~~~~~
-If any model or module options don't work for your device, it's time
-to send a bug report to the developers.  Give the following in your
-bug report:
-
-- Hardware vendor, product and model names
-- Kernel version (and ALSA-driver version if you built externally)
-- `alsa-info.sh` output; run with `--no-upload` option.  See the
-  section below about alsa-info
-
-If it's a regression, at best, send alsa-info outputs of both working
-and non-working kernels.  This is really helpful because we can
-compare the codec registers directly.
-
-Send a bug report either the followings:
-
-kernel-bugzilla::
-  https://bugzilla.kernel.org/
-alsa-devel ML::
-  alsa-devel@alsa-project.org
-
-
-DEBUG TOOLS
------------
-
-This section describes some tools available for debugging HD-audio
-problems.
-
-alsa-info
-~~~~~~~~~
-The script `alsa-info.sh` is a very useful tool to gather the audio
-device information.  It's included in alsa-utils package.  The latest
-version can be found on git repository:
-
-- git://git.alsa-project.org/alsa-utils.git
-
-The script can be fetched directly from the following URL, too:
-
-- http://www.alsa-project.org/alsa-info.sh
-
-Run this script as root, and it will gather the important information
-such as the module lists, module parameters, proc file contents
-including the codec proc files, mixer outputs and the control
-elements.  As default, it will store the information onto a web server
-on alsa-project.org.  But, if you send a bug report, it'd be better to
-run with `--no-upload` option, and attach the generated file.
-
-There are some other useful options.  See `--help` option output for
-details.
-
-When a probe error occurs or when the driver obviously assigns a
-mismatched model, it'd be helpful to load the driver with
-`probe_only=1` option (at best after the cold reboot) and run
-alsa-info at this state.  With this option, the driver won't configure
-the mixer and PCM but just tries to probe the codec slot.  After
-probing, the proc file is available, so you can get the raw codec
-information before modified by the driver.  Of course, the driver
-isn't usable with `probe_only=1`.  But you can continue the
-configuration via hwdep sysfs file if hda-reconfig option is enabled.
-Using `probe_only` mask 2 skips the reset of HDA codecs (use
-`probe_only=3` as module option). The hwdep interface can be used
-to determine the BIOS codec initialization.
-
-
-hda-verb
-~~~~~~~~
-hda-verb is a tiny program that allows you to access the HD-audio
-codec directly.  You can execute a raw HD-audio codec verb with this.
-This program accesses the hwdep device, thus you need to enable the
-kernel config `CONFIG_SND_HDA_HWDEP=y` beforehand.
-
-The hda-verb program takes four arguments: the hwdep device file, the
-widget NID, the verb and the parameter.  When you access to the codec
-on the slot 2 of the card 0, pass /dev/snd/hwC0D2 to the first
-argument, typically.  (However, the real path name depends on the
-system.)
-
-The second parameter is the widget number-id to access.  The third
-parameter can be either a hex/digit number or a string corresponding
-to a verb.  Similarly, the last parameter is the value to write, or
-can be a string for the parameter type.
-
-------------------------------------------------------------------------
-  % hda-verb /dev/snd/hwC0D0 0x12 0x701 2
-  nid = 0x12, verb = 0x701, param = 0x2
-  value = 0x0
-
-  % hda-verb /dev/snd/hwC0D0 0x0 PARAMETERS VENDOR_ID
-  nid = 0x0, verb = 0xf00, param = 0x0
-  value = 0x10ec0262
-
-  % hda-verb /dev/snd/hwC0D0 2 set_a 0xb080
-  nid = 0x2, verb = 0x300, param = 0xb080
-  value = 0x0
-------------------------------------------------------------------------
-
-Although you can issue any verbs with this program, the driver state
-won't be always updated.  For example, the volume values are usually
-cached in the driver, and thus changing the widget amp value directly
-via hda-verb won't change the mixer value.
-
-The hda-verb program is included now in alsa-tools:
-
-- git://git.alsa-project.org/alsa-tools.git
-
-Also, the old stand-alone package is found in the ftp directory:
-
-- ftp://ftp.suse.com/pub/people/tiwai/misc/
-
-Also a git repository is available:
-
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-verb.git
-
-See README file in the tarball for more details about hda-verb
-program.
-
-
-hda-analyzer
-~~~~~~~~~~~~
-hda-analyzer provides a graphical interface to access the raw HD-audio
-control, based on pyGTK2 binding.  It's a more powerful version of
-hda-verb.  The program gives you an easy-to-use GUI stuff for showing
-the widget information and adjusting the amp values, as well as the
-proc-compatible output.
-
-The hda-analyzer:
-
-- http://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer
-
-is a part of alsa.git repository in alsa-project.org:
-
-- git://git.alsa-project.org/alsa.git
-
-Codecgraph
-~~~~~~~~~~
-Codecgraph is a utility program to generate a graph and visualizes the
-codec-node connection of a codec chip.  It's especially useful when
-you analyze or debug a codec without a proper datasheet.  The program
-parses the given codec proc file and converts to SVG via graphiz
-program.
-
-The tarball and GIT trees are found in the web page at:
-
-- http://helllabs.org/codecgraph/
-
-
-hda-emu
-~~~~~~~
-hda-emu is an HD-audio emulator.  The main purpose of this program is
-to debug an HD-audio codec without the real hardware.  Thus, it
-doesn't emulate the behavior with the real audio I/O, but it just
-dumps the codec register changes and the ALSA-driver internal changes
-at probing and operating the HD-audio driver.
-
-The program requires a codec proc-file to simulate.  Get a proc file
-for the target codec beforehand, or pick up an example codec from the
-codec proc collections in the tarball.  Then, run the program with the
-proc file, and the hda-emu program will start parsing the codec file
-and simulates the HD-audio driver:
-
-------------------------------------------------------------------------
-  % hda-emu codecs/stac9200-dell-d820-laptop
-  # Parsing..
-  hda_codec: Unknown model for STAC9200, using BIOS defaults
-  hda_codec: pin nid 08 bios pin config 40c003fa
-  ....
-------------------------------------------------------------------------
-
-The program gives you only a very dumb command-line interface.  You
-can get a proc-file dump at the current state, get a list of control
-(mixer) elements, set/get the control element value, simulate the PCM
-operation, the jack plugging simulation, etc.
-
-The program is found in the git repository below:
-
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
-
-See README file in the repository for more details about hda-emu
-program.
-
-
-hda-jack-retask
-~~~~~~~~~~~~~~~
-hda-jack-retask is a user-friendly GUI program to manipulate the
-HD-audio pin control for jack retasking.  If you have a problem about
-the jack assignment, try this program and check whether you can get
-useful results.  Once when you figure out the proper pin assignment,
-it can be fixed either in the driver code statically or via passing a
-firmware patch file (see "Early Patching" section).
-
-The program is included in alsa-tools now:
-
-- git://git.alsa-project.org/alsa-tools.git
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/hdspm.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/hdspm.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/hdspm.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/hdspm.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,362 +0,0 @@
-Software Interface ALSA-DSP MADI Driver 
-
-(translated from German, so no good English ;-), 
-2004 - winfried ritsch
-
-
-
- Full functionality has been added to the driver. Since some of
- the Controls and startup-options  are ALSA-Standard and only the
- special Controls are described and discussed below.
-
-
- hardware functionality:
-
-   
-   Audio transmission:
-
-     number of channels --  depends on transmission mode
-
-		The number of channels chosen is from 1..Nmax. The reason to
-		use for a lower number of channels is only resource allocation,
-		since unused DMA channels are disabled and less memory is
-		allocated. So also the throughput of the PCI system can be
-		scaled. (Only important for low performance boards).
-
-       Single Speed -- 1..64 channels 
-
-		 (Note: Choosing the 56channel mode for transmission or as
-		 receiver, only 56 are transmitted/received over the MADI, but
-		 all 64 channels are available for the mixer, so channel count
-		 for the driver)
-
-       Double Speed -- 1..32 channels
-
-		 Note: Choosing the 56-channel mode for
-		 transmission/receive-mode , only 28 are transmitted/received
-		 over the MADI, but all 32 channels are available for the mixer,
-		 so channel count for the driver
-
-
-       Quad Speed -- 1..16 channels 
-
-		 Note: Choosing the 56-channel mode for
-		 transmission/receive-mode , only 14 are transmitted/received
-		 over the MADI, but all 16 channels are available for the mixer,
-		 so channel count for the driver
-
-     Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
-
-     Sample Rates --
-
-       Single Speed -- 32000, 44100, 48000
-
-       Double Speed -- 64000, 88200, 96000 (untested)
-
-       Quad Speed -- 128000, 176400, 192000 (untested)
-
-     access-mode -- MMAP (memory mapped), Not interleaved
-     (PCM_NON-INTERLEAVED)
-
-     buffer-sizes -- 64,128,256,512,1024,2048,8192 Samples
-
-     fragments -- 2
-
-     Hardware-pointer -- 2 Modi
-
-
-		 The Card supports the readout of the actual Buffer-pointer,
-		 where DMA reads/writes. Since of the bulk mode of PCI it is only
-		 64 Byte accurate. SO it is not really usable for the
-		 ALSA-mid-level functions (here the buffer-ID gives a better
-		 result), but if MMAP is used by the application. Therefore it
-		 can be configured at load-time with the parameter
-		 precise-pointer.
-
-
-		 (Hint: Experimenting I found that the pointer is maximum 64 to
-		 large never to small. So if you subtract 64 you always have a
-		 safe pointer for writing, which is used on this mode inside
-		 ALSA. In theory now you can get now a latency as low as 16
-		 Samples, which is a quarter of the interrupt possibilities.)
-
-       Precise Pointer -- off
-					interrupt used for pointer-calculation
-
-       Precise Pointer -- on
-					hardware pointer used.
-
-   Controller:
-
-
-	  Since DSP-MADI-Mixer has 8152 Fader, it does not make sense to
-	  use the standard mixer-controls, since this would break most of
-	  (especially graphic) ALSA-Mixer GUIs. So Mixer control has be
-	  provided by a 2-dimensional controller using the
-	  hwdep-interface. 
-
-     Also all 128+256 Peak and RMS-Meter can be accessed via the
-     hwdep-interface. Since it could be a performance problem always
-     copying and converting Peak and RMS-Levels even if you just need
-     one, I decided to export the hardware structure, so that of
-     needed some driver-guru can implement a memory-mapping of mixer
-     or peak-meters over ioctl, or also to do only copying and no
-     conversion. A test-application shows the usage of the controller.
-
-    Latency Controls --- not implemented !!!
-
-
-	   Note: Within the windows-driver the latency is accessible of a
-	   control-panel, but buffer-sizes are controlled with ALSA from
-	   hwparams-calls and should not be changed in run-state, I did not
-	   implement it here.
-
-
-    System Clock -- suspended !!!!
-
-        Name -- "System Clock Mode"
-
-        Access -- Read Write
-
-        Values -- "Master" "Slave"
-
-
-		  !!!! This is a hardware-function but is in conflict with the
-		  Clock-source controller, which is a kind of ALSA-standard. I
-		  makes sense to set the card to a special mode (master at some
-		  frequency or slave), since even not using an Audio-application
-		  a studio should have working synchronisations setup. So use
-		  Clock-source-controller instead !!!!
-
-    Clock Source  
-
-       Name -- "Sample Clock Source"
-
-       Access -- Read Write
-
-       Values -- "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
-       "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
-       "Internal 96.0 kHz"
-
-		 Choose between Master at a specific Frequency and so also the
-		 Speed-mode or Slave (Autosync). Also see  "Preferred Sync Ref"
-
-
-       !!!! This is no pure hardware function but was implemented by
-       ALSA by some ALSA-drivers before, so I use it also. !!!
-
-
-    Preferred Sync Ref
-
-       Name -- "Preferred Sync Reference"
-
-       Access -- Read Write
-
-       Values -- "Word" "MADI"
-
-
-		 Within the Auto-sync-Mode the preferred Sync Source can be
-		 chosen. If it is not available another is used if possible.
-
-		 Note: Since MADI has a much higher bit-rate than word-clock, the
-		 card should synchronise better in MADI Mode. But since the
-		 RME-PLL is very good, there are almost no problems with
-		 word-clock too. I never found a difference.
-
-
-    TX 64 channel --- 
-
-       Name -- "TX 64 channels mode"
-
-       Access -- Read Write
-
-       Values -- 0 1
-
-		 Using 64-channel-modus (1) or 56-channel-modus for
-		 MADI-transmission (0).
-
-
-		 Note: This control is for output only. Input-mode is detected
-		 automatically from hardware sending MADI.
-
-
-    Clear TMS ---
-
-       Name -- "Clear Track Marker"
-
-       Access -- Read Write
-
-       Values -- 0 1
-
-
-		 Don't use to lower 5 Audio-bits on AES as additional Bits.
-        
-
-    Safe Mode oder Auto Input --- 
-
-       Name -- "Safe Mode"
-
-       Access -- Read Write
-
-       Values -- 0 1
-
-       (default on)
-
-		 If on (1), then if either the optical or coaxial connection
-		 has a failure, there is a takeover to the working one, with no
-		 sample failure. Its only useful if you use the second as a
-		 backup connection.
-
-    Input --- 
-
-       Name -- "Input Select"
-
-       Access -- Read Write
-
-       Values -- optical coaxial
-
-
-		 Choosing the Input, optical or coaxial. If Safe-mode is active,
-		 this is the preferred Input.
-
--------------- Mixer ----------------------
-
-    Mixer
-
-       Name -- "Mixer"
-
-       Access -- Read Write
-
-       Values - <channel-number 0-127> <Value 0-65535>
-
-
-		 Here as a first value the channel-index is taken to get/set the
-		 corresponding mixer channel, where 0-63 are the input to output
-		 fader and 64-127 the playback to outputs fader. Value 0
-		 is channel muted 0 and 32768 an amplification of  1.
-
-    Chn 1-64
-
-       fast mixer for the ALSA-mixer utils. The diagonal of the
-       mixer-matrix is implemented from playback to output.
-       
-
-    Line Out
-
-       Name  -- "Line Out"
-
-       Access -- Read Write
-
-       Values -- 0 1
-
-		 Switching on and off the analog out, which has nothing to do
-		 with mixing or routing. the analog outs reflects channel 63,64.
-
-
---- information (only read access):
- 
-    Sample Rate
-
-       Name -- "System Sample Rate"
-
-       Access -- Read-only
-
-		 getting the sample rate.
-
-
-    External Rate measured
-
-       Name -- "External Rate"
-
-       Access -- Read only
-
-
-		 Should be "Autosync Rate", but Name used is
-		 ALSA-Scheme. External Sample frequency liked used on Autosync is
-		 reported.
-
-
-    MADI Sync Status
-
-       Name -- "MADI Sync Lock Status"
-
-       Access -- Read
-
-       Values -- 0,1,2
-
-       MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced.
-
-
-    Word Clock Sync Status
-
-       Name -- "Word Clock Lock Status"
-
-       Access -- Read
-
-       Values -- 0,1,2
-
-       Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced.
-
-    AutoSync
-
-       Name -- "AutoSync Reference"
-
-       Access -- Read
-
-       Values -- "WordClock", "MADI", "None"
-
-		 Sync-Reference is either "WordClock", "MADI" or none.
-
-   RX 64ch --- noch nicht implementiert
-
-       MADI-Receiver is in 64 channel mode oder 56 channel mode.
-
-
-   AB_inp   --- not tested 
-
-		 Used input for Auto-Input.
-
-
-   actual Buffer Position --- not implemented
-
-	   !!! this is a ALSA internal function, so no control is used !!!
-
-
-
-Calling Parameter:
-
-   index int array (min = 1, max = 8), 
-     "Index value for RME HDSPM interface." card-index within ALSA
-
-     note: ALSA-standard
-
-   id string array (min = 1, max = 8), 
-     "ID string for RME HDSPM interface."
-
-     note: ALSA-standard
-
-   enable int array (min = 1, max = 8), 
-     "Enable/disable specific HDSPM sound-cards."
-
-     note: ALSA-standard
-
-   precise_ptr int array (min = 1, max = 8), 
-     "Enable precise pointer, or disable."
-
-     note: Use only when the application supports this (which is a special case).
-
-   line_outs_monitor int array (min = 1, max = 8), 
-     "Send playback streams to analog outs by default."
-
-
-	  note: each playback channel is mixed to the same numbered output
-	  channel (routed). This is against the ALSA-convention, where all
-	  channels have to be muted on after loading the driver, but was
-	  used before on other cards, so i historically use it again)
-
-
-
-   enable_monitor int array (min = 1, max = 8), 
-     "Enable Analog Out on Channel 63/64 by default."
-
-      note: here the analog output is enabled (but not routed).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/img,spdif-in.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/img,spdif-in.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/img,spdif-in.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/img,spdif-in.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-The Imagination Technologies SPDIF Input controller contains the following
-controls:
-
-name='IEC958 Capture Mask',index=0
-
-This control returns a mask that shows which of the IEC958 status bits
-can be read using the 'IEC958 Capture Default' control.
-
-name='IEC958 Capture Default',index=0
-
-This control returns the status bits contained within the SPDIF stream that
-is being received. The 'IEC958 Capture Mask' shows which bits can be read
-from this control.
-
-name='SPDIF In Multi Frequency Acquire',index=0
-name='SPDIF In Multi Frequency Acquire',index=1
-name='SPDIF In Multi Frequency Acquire',index=2
-name='SPDIF In Multi Frequency Acquire',index=3
-
-This control is used to attempt acquisition of up to four different sample
-rates. The active rate can be obtained by reading the 'SPDIF In Lock Frequency'
-control.
-
-When the value of this control is set to {0,0,0,0}, the rate given to hw_params
-will determine the single rate the block will capture. Else, the rate given to
-hw_params will be ignored, and the block will attempt capture for each of the
-four sample rates set here.
-
-If less than four rates are required, the same rate can be specified more than
-once
-
-name='SPDIF In Lock Frequency',index=0
-
-This control returns the active capture rate, or 0 if a lock has not been
-acquired
-
-name='SPDIF In Lock TRK',index=0
-
-This control is used to modify the locking/jitter rejection characteristics
-of the block. Larger values increase the locking range, but reduce jitter
-rejection.
-
-name='SPDIF In Lock Acquire Threshold',index=0
-
-This control is used to change the threshold at which a lock is acquired.
-
-name='SPDIF In Lock Release Threshold',index=0
-
-This control is used to change the threshold at which a lock is released.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/Jack-Controls.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Jack-Controls.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/Jack-Controls.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Jack-Controls.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-Why we need Jack kcontrols
-==========================
-
-ALSA uses kcontrols to export audio controls(switch, volume, Mux, ...)
-to user space. This means userspace applications like pulseaudio can
-switch off headphones and switch on speakers when no headphones are
-pluged in.
-
-The old ALSA jack code only created input devices for each registered
-jack. These jack input devices are not readable by userspace devices
-that run as non root.
-
-The new jack code creates embedded jack kcontrols for each jack that
-can be read by any process.
-
-This can be combined with UCM to allow userspace to route audio more
-intelligently based on jack insertion or removal events.
-
-Jack Kcontrol Internals
-=======================
-
-Each jack will have a kcontrol list, so that we can create a kcontrol
-and attach it to the jack, at jack creation stage. We can also add a
-kcontrol to an existing jack, at anytime when required.
-
-Those kcontrols will be freed automatically when the Jack is freed.
-
-How to use jack kcontrols
-=========================
-
-In order to keep compatibility, snd_jack_new() has been modified by
-adding two params :-
-
- - @initial_kctl: if true, create a kcontrol and add it to the jack
-	list.
- - @phantom_jack: Don't create a input device for phantom jacks.
-
-HDA jacks can set phantom_jack to true in order to create a phantom
-jack and set initial_kctl to true to create an initial kcontrol with
-the correct id.
-
-ASoC jacks should set initial_kctl as false. The pin name will be
-assigned as the jack kcontrol name.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/Joystick.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Joystick.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/Joystick.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Joystick.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-Analog Joystick Support on ALSA Drivers
-=======================================
-                          Oct. 14, 2003
-           Takashi Iwai <tiwai@suse.de>
-
-General
--------
-
-First of all, you need to enable GAMEPORT support on Linux kernel for
-using a joystick with the ALSA driver.  For the details of gameport
-support, refer to Documentation/input/joystick.txt.
-
-The joystick support of ALSA drivers is different between ISA and PCI
-cards.  In the case of ISA (PnP) cards, it's usually handled by the
-independent module (ns558).  Meanwhile, the ALSA PCI drivers have the
-built-in gameport support.  Hence, when the ALSA PCI driver is built
-in the kernel, CONFIG_GAMEPORT must be 'y', too.  Otherwise, the
-gameport support on that card will be (silently) disabled.
-
-Some adapter modules probe the physical connection of the device at
-the load time.  It'd be safer to plug in the joystick device before
-loading the module.
-
-
-PCI Cards
----------
-
-For PCI cards, the joystick is enabled when the appropriate module
-option is specified.  Some drivers don't need options, and the
-joystick support is always enabled.  In the former ALSA version, there
-was a dynamic control API for the joystick activation.  It was
-changed, however, to the static module options because of the system
-stability and the resource management.
-
-The following PCI drivers support the joystick natively.
-
-    Driver	Module Option	Available Values
-    ---------------------------------------------------------------------------
-    als4000	joystick_port	0 = disable (default), 1 = auto-detect,
-                                manual: any address (e.g. 0x200)
-    au88x0	N/A		N/A
-    azf3328	joystick	0 = disable, 1 = enable, -1 = auto (default)
-    ens1370	joystick	0 = disable (default), 1 = enable
-    ens1371	joystick_port	0 = disable (default), 1 = auto-detect,
-                                manual: 0x200, 0x208, 0x210, 0x218
-    cmipci	joystick_port	0 = disable (default), 1 = auto-detect,
-                                manual: any address (e.g. 0x200)
-    cs4281	N/A		N/A
-    cs46xx	N/A		N/A
-    es1938	N/A		N/A
-    es1968	joystick	0 = disable (default), 1 = enable
-    sonicvibes	N/A		N/A
-    trident	N/A		N/A
-    via82xx(*1)	joystick	0 = disable (default), 1 = enable
-    ymfpci	joystick_port	0 = disable (default), 1 = auto-detect,
-                                manual: 0x201, 0x202, 0x204, 0x205(*2)
-    ---------------------------------------------------------------------------
-
-    *1)  VIA686A/B only
-    *2)  With YMF744/754 chips, the port address can be chosen arbitrarily
-
-The following drivers don't support gameport natively, but there are
-additional modules.  Load the corresponding module to add the gameport
-support.
-
-    Driver	Additional Module
-    -----------------------------
-    emu10k1	emu10k1-gp
-    fm801	fm801-gp
-    -----------------------------
-
-Note: the "pcigame" and "cs461x" modules are for the OSS drivers only.
-      These ALSA drivers (cs46xx, trident and au88x0) have the
-      built-in gameport support.
-
-As mentioned above, ALSA PCI drivers have the built-in gameport
-support, so you don't have to load ns558 module.  Just load "joydev"
-and the appropriate adapter module (e.g. "analog").
-
-
-ISA Cards
----------
-
-ALSA ISA drivers don't have the built-in gameport support.
-Instead, you need to load "ns558" module in addition to "joydev" and
-the adapter module (e.g. "analog").
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/MIXART.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/MIXART.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/MIXART.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/MIXART.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-    Alsa driver for Digigram miXart8 and miXart8AES/EBU soundcards
-	    Digigram <alsa@digigram.com>
-
-
-GENERAL
-=======
-
-The miXart8 is a multichannel audio processing and mixing soundcard
-that has 4 stereo audio inputs and 4 stereo audio outputs.
-The miXart8AES/EBU is the same with a add-on card that offers further
-4 digital stereo audio inputs and outputs.
-Furthermore the add-on card offers external clock synchronisation
-(AES/EBU, Word Clock, Time Code and Video Synchro)
-
-The mainboard has a PowerPC that offers onboard mpeg encoding and
-decoding, samplerate conversions and various effects.
-
-The driver don't work properly at all until the certain firmwares
-are loaded, i.e. no PCM nor mixer devices will appear.
-Use the mixartloader that can be found in the alsa-tools package.
-
-
-VERSION 0.1.0
-=============
-
-One miXart8 board will be represented as 4 alsa cards, each with 1
-stereo analog capture 'pcm0c' and 1 stereo analog playback 'pcm0p' device.
-With a miXart8AES/EBU there is in addition 1 stereo digital input
-'pcm1c' and 1 stereo digital output 'pcm1p' per card.
-
-Formats
--------
-U8, S16_LE, S16_BE, S24_3LE, S24_3BE, FLOAT_LE, FLOAT_BE
-Sample rates : 8000 - 48000 Hz continuously
-
-Playback
---------
-For instance the playback devices are configured to have max. 4
-substreams performing hardware mixing. This could be changed to a
-maximum of 24 substreams if wished.
-Mono files will be played on the left and right channel. Each channel
-can be muted for each stream to use 8 analog/digital outputs separately.
-
-Capture
--------
-There is one substream per capture device. For instance only stereo
-formats are supported.
-
-Mixer
------
-<Master> and <Master Capture> : analog volume control of playback and capture PCM.
-<PCM 0-3> and <PCM Capture> : digital volume control of each analog substream.
-<AES 0-3> and <AES Capture> : digital volume control of each AES/EBU substream.
-<Monitoring> : Loopback from 'pcm0c' to 'pcm0p' with digital volume
-and mute control.
-
-Rem : for best audio quality try to keep a 0 attenuation on the PCM
-and AES volume controls which is set by 219 in the range from 0 to 255
-(about 86% with alsamixer)
-
-
-NOT YET IMPLEMENTED
-===================
-
-- external clock support (AES/EBU, Word Clock, Time Code, Video Sync)
-- MPEG audio formats
-- mono record
-- on-board effects and samplerate conversions
-- linked streams
-
-
-FIRMWARE
-========
-
-[As of 2.6.11, the firmware can be loaded automatically with hotplug
- when CONFIG_FW_LOADER is set.  The mixartloader is necessary only
- for older versions or when you build the driver into kernel.]
- 
-For loading the firmware automatically after the module is loaded, use a
-install command.  For example, add the following entry to
-/etc/modprobe.d/mixart.conf for miXart driver:
-
-	install snd-mixart /sbin/modprobe --first-time -i snd-mixart && \
-			   /usr/bin/mixartloader
-(for 2.2/2.4 kernels, add "post-install snd-mixart /usr/bin/vxloader" to
- /etc/modules.conf, instead.)
-
-The firmware binaries are installed on /usr/share/alsa/firmware
-(or /usr/local/share/alsa/firmware, depending to the prefix option of
-configure).  There will be a miXart.conf file, which define the dsp image
-files.
-
-The firmware files are copyright by Digigram SA
-
-
-COPYRIGHT
-=========
-
-Copyright (c) 2003 Digigram SA <alsa@digigram.com>
-Distributable under GPL.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/OSS-Emulation.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/OSS-Emulation.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/OSS-Emulation.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/OSS-Emulation.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,305 +0,0 @@
-		NOTES ON KERNEL OSS-EMULATION
-		=============================
-
-		Jan. 22, 2004  Takashi Iwai <tiwai@suse.de>
-
-
-Modules
-=======
-
-ALSA provides a powerful OSS emulation on the kernel.
-The OSS emulation for PCM, mixer and sequencer devices is implemented
-as add-on kernel modules, snd-pcm-oss, snd-mixer-oss and snd-seq-oss.
-When you need to access the OSS PCM, mixer or sequencer devices, the
-corresponding module has to be loaded.
-
-These modules are loaded automatically when the corresponding service
-is called.  The alias is defined sound-service-x-y, where x and y are
-the card number and the minor unit number.  Usually you don't have to
-define these aliases by yourself.
-
-Only necessary step for auto-loading of OSS modules is to define the
-card alias in /etc/modprobe.d/alsa.conf, such as
-
-	alias sound-slot-0 snd-emu10k1
-
-As the second card, define sound-slot-1 as well.
-Note that you can't use the aliased name as the target name (i.e.
-"alias sound-slot-0 snd-card-0" doesn't work any more like the old
-modutils).
-
-The currently available OSS configuration is shown in
-/proc/asound/oss/sndstat.  This shows in the same syntax of
-/dev/sndstat, which is available on the commercial OSS driver.
-On ALSA, you can symlink /dev/sndstat to this proc file.
-
-Please note that the devices listed in this proc file appear only
-after the corresponding OSS-emulation module is loaded.  Don't worry
-even if "NOT ENABLED IN CONFIG" is shown in it.
-
-
-Device Mapping
-==============
-
-ALSA supports the following OSS device files:
-
-	PCM:
-		/dev/dspX
-		/dev/adspX
-
-	Mixer:
-		/dev/mixerX
-
-	MIDI:
-		/dev/midi0X
-		/dev/amidi0X
-
-	Sequencer:
-		/dev/sequencer
-		/dev/sequencer2 (aka /dev/music)
-
-where X is the card number from 0 to 7.
-
-(NOTE: Some distributions have the device files like /dev/midi0 and
-       /dev/midi1.  They are NOT for OSS but for tclmidi, which is
-       a totally different thing.)
-
-Unlike the real OSS, ALSA cannot use the device files more than the
-assigned ones.  For example, the first card cannot use /dev/dsp1 or
-/dev/dsp2, but only /dev/dsp0 and /dev/adsp0.
-
-As seen above, PCM and MIDI may have two devices.  Usually, the first
-PCM device (hw:0,0 in ALSA) is mapped to /dev/dsp and the secondary
-device (hw:0,1) to /dev/adsp (if available).  For MIDI, /dev/midi and
-/dev/amidi, respectively.
-
-You can change this device mapping via the module options of
-snd-pcm-oss and snd-rawmidi.  In the case of PCM, the following
-options are available for snd-pcm-oss:
-
-	dsp_map		PCM device number assigned to /dev/dspX
-			(default = 0)
-	adsp_map	PCM device number assigned to /dev/adspX
-			(default = 1)
-
-For example, to map the third PCM device (hw:0,2) to /dev/adsp0,
-define like this:
-
-	options snd-pcm-oss adsp_map=2
-
-The options take arrays.  For configuring the second card, specify
-two entries separated by comma.  For example, to map the third PCM
-device on the second card to /dev/adsp1, define like below:
-
-	options snd-pcm-oss adsp_map=0,2
-
-To change the mapping of MIDI devices, the following options are
-available for snd-rawmidi:
-
-	midi_map	MIDI device number assigned to /dev/midi0X
-			(default = 0)
-	amidi_map	MIDI device number assigned to /dev/amidi0X
-			(default = 1)
-
-For example, to assign the third MIDI device on the first card to
-/dev/midi00, define as follows:
-
-	options snd-rawmidi midi_map=2
-
-
-PCM Mode
-========
-
-As default, ALSA emulates the OSS PCM with so-called plugin layer,
-i.e. tries to convert the sample format, rate or channels
-automatically when the card doesn't support it natively.
-This will lead to some problems for some applications like quake or
-wine, especially if they use the card only in the MMAP mode.
-
-In such a case, you can change the behavior of PCM per application by
-writing a command to the proc file.  There is a proc file for each PCM
-stream, /proc/asound/cardX/pcmY[cp]/oss, where X is the card number
-(zero-based), Y the PCM device number (zero-based), and 'p' is for
-playback and 'c' for capture, respectively.  Note that this proc file
-exists only after snd-pcm-oss module is loaded.
-
-The command sequence has the following syntax:
-
-	app_name fragments fragment_size [options]
-
-app_name is the name of application with (higher priority) or without
-path.
-fragments specifies the number of fragments or zero if no specific
-number is given.
-fragment_size is the size of fragment in bytes or zero if not given.
-options is the optional parameters.  The following options are
-available:
-
-	disable		the application tries to open a pcm device for
-			this channel but does not want to use it.
-	direct		don't use plugins
-	block		force block open mode
-	non-block	force non-block open mode
-	partial-frag	write also partial fragments (affects playback only)
-	no-silence	do not fill silence ahead to avoid clicks
-
-The disable option is useful when one stream direction (playback or
-capture) is not handled correctly by the application although the
-hardware itself does support both directions.
-The direct option is used, as mentioned above, to bypass the automatic
-conversion and useful for MMAP-applications.
-For example, to playback the first PCM device without plugins for
-quake, send a command via echo like the following:
-
-	% echo "quake 0 0 direct" > /proc/asound/card0/pcm0p/oss
-
-While quake wants only playback, you may append the second command
-to notify driver that only this direction is about to be allocated:
-
-	% echo "quake 0 0 disable" > /proc/asound/card0/pcm0c/oss
-
-The permission of proc files depend on the module options of snd.
-As default it's set as root, so you'll likely need to be superuser for
-sending the command above.
-
-The block and non-block options are used to change the behavior of
-opening the device file.
-
-As default, ALSA behaves as original OSS drivers, i.e. does not block
-the file when it's busy. The -EBUSY error is returned in this case.
-
-This blocking behavior can be changed globally via nonblock_open
-module option of snd-pcm-oss.  For using the blocking mode as default
-for OSS devices, define like the following:
-
-	options snd-pcm-oss nonblock_open=0
-
-The partial-frag and no-silence commands have been added recently.
-Both commands are for optimization use only.  The former command
-specifies to invoke the write transfer only when the whole fragment is
-filled.  The latter stops writing the silence data ahead
-automatically.  Both are disabled as default.
-
-You can check the currently defined configuration by reading the proc
-file.  The read image can be sent to the proc file again, hence you
-can save the current configuration
-
-	% cat /proc/asound/card0/pcm0p/oss > /somewhere/oss-cfg
-
-and restore it like
-
-	% cat /somewhere/oss-cfg > /proc/asound/card0/pcm0p/oss
-
-Also, for clearing all the current configuration, send "erase" command
-as below:
-
-	% echo "erase" > /proc/asound/card0/pcm0p/oss
-
-
-Mixer Elements
-==============
-
-Since ALSA has completely different mixer interface, the emulation of
-OSS mixer is relatively complicated.  ALSA builds up a mixer element
-from several different ALSA (mixer) controls based on the name
-string.  For example, the volume element SOUND_MIXER_PCM is composed
-from "PCM Playback Volume" and "PCM Playback Switch" controls for the
-playback direction and from "PCM Capture Volume" and "PCM Capture
-Switch" for the capture directory (if exists).  When the PCM volume of
-OSS is changed, all the volume and switch controls above are adjusted
-automatically.
-
-As default, ALSA uses the following control for OSS volumes:
-
-	OSS volume		ALSA control		Index
-	-----------------------------------------------------
-	SOUND_MIXER_VOLUME 	Master			0
-	SOUND_MIXER_BASS	Tone Control - Bass	0
-	SOUND_MIXER_TREBLE	Tone Control - Treble	0
-	SOUND_MIXER_SYNTH	Synth			0
-	SOUND_MIXER_PCM		PCM			0
-	SOUND_MIXER_SPEAKER	PC Speaker 		0
-	SOUND_MIXER_LINE	Line			0
-	SOUND_MIXER_MIC		Mic 			0
-	SOUND_MIXER_CD		CD 			0
-	SOUND_MIXER_IMIX	Monitor Mix 		0
-	SOUND_MIXER_ALTPCM	PCM			1
-	SOUND_MIXER_RECLEV	(not assigned)
-	SOUND_MIXER_IGAIN	Capture			0
-	SOUND_MIXER_OGAIN	Playback		0
-	SOUND_MIXER_LINE1	Aux			0
-	SOUND_MIXER_LINE2	Aux			1
-	SOUND_MIXER_LINE3	Aux			2
-	SOUND_MIXER_DIGITAL1	Digital			0
-	SOUND_MIXER_DIGITAL2	Digital			1
-	SOUND_MIXER_DIGITAL3	Digital			2
-	SOUND_MIXER_PHONEIN	Phone			0
-	SOUND_MIXER_PHONEOUT	Phone			1
-	SOUND_MIXER_VIDEO	Video			0
-	SOUND_MIXER_RADIO	Radio			0
-	SOUND_MIXER_MONITOR	Monitor			0
-
-The second column is the base-string of the corresponding ALSA
-control.  In fact, the controls with "XXX [Playback|Capture]
-[Volume|Switch]" will be checked in addition.
-
-The current assignment of these mixer elements is listed in the proc
-file, /proc/asound/cardX/oss_mixer, which will be like the following
-
-	VOLUME "Master" 0
-	BASS "" 0
-	TREBLE "" 0
-	SYNTH "" 0
-	PCM "PCM" 0
-	...
-
-where the first column is the OSS volume element, the second column
-the base-string of the corresponding ALSA control, and the third the
-control index.  When the string is empty, it means that the
-corresponding OSS control is not available.
-
-For changing the assignment, you can write the configuration to this
-proc file.  For example, to map "Wave Playback" to the PCM volume,
-send the command like the following:
-
-	% echo 'VOLUME "Wave Playback" 0' > /proc/asound/card0/oss_mixer
-
-The command is exactly as same as listed in the proc file.  You can
-change one or more elements, one volume per line.  In the last
-example, both "Wave Playback Volume" and "Wave Playback Switch" will
-be affected when PCM volume is changed.
-
-Like the case of PCM proc file, the permission of proc files depend on
-the module options of snd.  you'll likely need to be superuser for
-sending the command above.
-
-As well as in the case of PCM proc file, you can save and restore the
-current mixer configuration by reading and writing the whole file
-image.
-
-
-Duplex Streams
-==============
-
-Note that when attempting to use a single device file for playback and
-capture, the OSS API provides no way to set the format, sample rate or
-number of channels different in each direction.  Thus
-	io_handle = open("device", O_RDWR)
-will only function correctly if the values are the same in each direction.
-
-To use different values in the two directions, use both
-	input_handle = open("device", O_RDONLY)
-	output_handle = open("device", O_WRONLY)
-and set the values for the corresponding handle.
-
-
-Unsupported Features
-====================
-
-MMAP on ICE1712 driver
-----------------------
-ICE1712 supports only the unconventional format, interleaved
-10-channels 24bit (packed in 32bit) format.  Therefore you cannot mmap
-the buffer as the conventional (mono or 2-channels, 8 or 16bit) format
-on OSS.
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/powersave.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/powersave.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/powersave.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/powersave.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-Notes on Power-Saving Mode
-==========================
-
-AC97 and HD-audio drivers have the automatic power-saving mode.
-This feature is enabled via Kconfig CONFIG_SND_AC97_POWER_SAVE
-and CONFIG_SND_HDA_POWER_SAVE options, respectively.
-
-With the automatic power-saving, the driver turns off the codec power
-appropriately when no operation is required.  When no applications use
-the device and/or no analog loopback is set, the power disablement is
-done fully or partially.  It'll save a certain power consumption, thus
-good for laptops (even for desktops).
-
-The time-out for automatic power-off can be specified via power_save
-module option of snd-ac97-codec and snd-hda-intel modules.  Specify
-the time-out value in seconds.  0 means to disable the automatic
-power-saving.  The default value of timeout is given via
-CONFIG_SND_AC97_POWER_SAVE_DEFAULT and
-CONFIG_SND_HDA_POWER_SAVE_DEFAULT Kconfig options.  Setting this to 1
-(the minimum value) isn't recommended because many applications try to
-reopen the device frequently.  10 would be a good choice for normal
-operations.
-
-The power_save option is exported as writable.  This means you can
-adjust the value via sysfs on the fly.  For example, to turn on the
-automatic power-save mode with 10 seconds, write to
-/sys/modules/snd_ac97_codec/parameters/power_save (usually as root):
-
-	# echo 10 > /sys/modules/snd_ac97_codec/parameters/power_save
-
-
-Note that you might hear click noise/pop when changing the power
-state.  Also, it often takes certain time to wake up from the
-power-down to the active state.  These are often hardly to fix, so
-don't report extra bug reports unless you have a fix patch ;-)
-
-For HD-audio interface, there is another module option,
-power_save_controller.  This enables/disables the power-save mode of
-the controller side.  Setting this on may reduce a bit more power
-consumption, but might result in longer wake-up time and click noise.
-Try to turn it off when you experience such a thing too often.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/Procfile.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Procfile.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/Procfile.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/Procfile.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,234 +0,0 @@
-		Proc Files of ALSA Drivers
-		==========================
-		Takashi Iwai <tiwai@suse.de>
-
-General
--------
-
-ALSA has its own proc tree, /proc/asound.  Many useful information are
-found in this tree.  When you encounter a problem and need debugging,
-check the files listed in the following sections.
-
-Each card has its subtree cardX, where X is from 0 to 7. The
-card-specific files are stored in the card* subdirectories.
-
-
-Global Information
-------------------
-
-cards
-	Shows the list of currently configured ALSA drivers,
-	index, the id string, short and long descriptions.
-
-version
-	Shows the version string and compile date.
-
-modules
-	Lists the module of each card
-
-devices
-	Lists the ALSA native device mappings.
-
-meminfo
-	Shows the status of allocated pages via ALSA drivers.
-	Appears only when CONFIG_SND_DEBUG=y.
-
-hwdep
-	Lists the currently available hwdep devices in format of
-	<card>-<device>: <name>
-
-pcm
-	Lists the currently available PCM devices in format of
-	<card>-<device>: <id>: <name> : <sub-streams>
-
-timer
-	Lists the currently available timer devices
-
-
-oss/devices
-	Lists the OSS device mappings.
-
-oss/sndstat
-	Provides the output compatible with /dev/sndstat.
-	You can symlink this to /dev/sndstat.
-
-
-Card Specific Files
--------------------
-
-The card-specific files are found in /proc/asound/card* directories.
-Some drivers (e.g. cmipci) have their own proc entries for the
-register dump, etc (e.g. /proc/asound/card*/cmipci shows the register
-dump).  These files would be really helpful for debugging.
-
-When PCM devices are available on this card, you can see directories
-like pcm0p or pcm1c.  They hold the PCM information for each PCM
-stream.  The number after 'pcm' is the PCM device number from 0, and
-the last 'p' or 'c' means playback or capture direction.  The files in
-this subtree is described later.
-
-The status of MIDI I/O is found in midi* files.  It shows the device
-name and the received/transmitted bytes through the MIDI device.
-
-When the card is equipped with AC97 codecs, there are codec97#*
-subdirectories (described later).
-
-When the OSS mixer emulation is enabled (and the module is loaded),
-oss_mixer file appears here, too.  This shows the current mapping of
-OSS mixer elements to the ALSA control elements.  You can change the
-mapping by writing to this device.  Read OSS-Emulation.txt for
-details.
-
-
-PCM Proc Files
---------------
-
-card*/pcm*/info
-	The general information of this PCM device: card #, device #,
-	substreams, etc.
-
-card*/pcm*/xrun_debug
-	This file appears when CONFIG_SND_DEBUG=y and
-	CONFIG_PCM_XRUN_DEBUG=y.
-	This shows the status of xrun (= buffer overrun/xrun) and
-	invalid PCM position debug/check of ALSA PCM middle layer.
-	It takes an integer value, can be changed by writing to this
-	file, such as
-
-		 # echo 5 > /proc/asound/card0/pcm0p/xrun_debug
-
-	The value consists of the following bit flags:
-	  bit 0 = Enable XRUN/jiffies debug messages
-	  bit 1 = Show stack trace at XRUN / jiffies check
-	  bit 2 = Enable additional jiffies check
-
-	When the bit 0 is set, the driver will show the messages to
-	kernel log when an xrun is detected.  The debug message is
-	shown also when the invalid H/W pointer is detected at the
-	update of periods (usually called from the interrupt
-	handler).
-
-	When the bit 1 is set, the driver will show the stack trace
-	additionally.  This may help the debugging.
-
-	Since 2.6.30, this option can enable the hwptr check using
-	jiffies.  This detects spontaneous invalid pointer callback
-	values, but can be lead to too much corrections for a (mostly
-	buggy) hardware that doesn't give smooth pointer updates.
-	This feature is enabled via the bit 2.
-
-card*/pcm*/sub*/info
-	The general information of this PCM sub-stream.
-
-card*/pcm*/sub*/status
-	The current status of this PCM sub-stream, elapsed time,
-	H/W position, etc.
-
-card*/pcm*/sub*/hw_params
-	The hardware parameters set for this sub-stream.
-
-card*/pcm*/sub*/sw_params
-	The soft parameters set for this sub-stream.
-
-card*/pcm*/sub*/prealloc
-	The buffer pre-allocation information.
-
-card*/pcm*/sub*/xrun_injection
-	Triggers an XRUN to the running stream when any value is
-	written to this proc file.  Used for fault injection.
-	This entry is write-only.
-
-AC97 Codec Information
-----------------------
-
-card*/codec97#*/ac97#?-?
-	Shows the general information of this AC97 codec chip, such as
-	name, capabilities, set up.
-
-card*/codec97#0/ac97#?-?+regs
-	Shows the AC97 register dump.  Useful for debugging.
-
-	When CONFIG_SND_DEBUG is enabled, you can write to this file for
-	changing an AC97 register directly.  Pass two hex numbers.
-	For example,
-
-	# echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs
-
-
-USB Audio Streams
------------------
-
-card*/stream*
-	Shows the assignment and the current status of each audio stream
-	of the given card.  This information is very useful for debugging.
-
-
-HD-Audio Codecs
----------------
-
-card*/codec#*
-	Shows the general codec information and the attribute of each
-	widget node.
-
-card*/eld#*
-	Available for HDMI or DisplayPort interfaces.
-	Shows ELD(EDID Like Data) info retrieved from the attached HDMI sink,
-	and describes its audio capabilities and configurations.
-
-	Some ELD fields may be modified by doing `echo name hex_value > eld#*`.
-	Only do this if you are sure the HDMI sink provided value is wrong.
-	And if that makes your HDMI audio work, please report to us so that we
-	can fix it in future kernel releases.
-
-
-Sequencer Information
----------------------
-
-seq/drivers
-	Lists the currently available ALSA sequencer drivers.
-
-seq/clients
-	Shows the list of currently available sequencer clients and
-	ports.  The connection status and the running status are shown
-	in this file, too.
-
-seq/queues
-	Lists the currently allocated/running sequencer queues.
-
-seq/timer
-	Lists the currently allocated/running sequencer timers.
-
-seq/oss
-	Lists the OSS-compatible sequencer stuffs.
-
-
-Help For Debugging?
--------------------
-
-When the problem is related with PCM, first try to turn on xrun_debug
-mode.  This will give you the kernel messages when and where xrun
-happened.
-
-If it's really a bug, report it with the following information:
-
-  - the name of the driver/card, show in /proc/asound/cards
-  - the register dump, if available (e.g. card*/cmipci)
-
-when it's a PCM problem,
-
-  - set-up of PCM, shown in hw_parms, sw_params, and status in the PCM
-    sub-stream directory
-
-when it's a mixer problem,
-
-  - AC97 proc files, codec97#*/* files
-
-for USB audio/midi,
-
-  - output of lsusb -v
-  - stream* files in card directory
-
-
-The ALSA bug-tracking system is found at:
-
-    https://bugtrack.alsa-project.org/alsa-bug/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/README.maya44 linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/README.maya44
--- linux-libre-4.9-gnu/Documentation/sound/alsa/README.maya44	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/README.maya44	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-NOTE: The following is the original document of Rainer's patch that the
-current maya44 code based on.  Some contents might be obsoleted, but I
-keep here as reference -- tiwai
-
-----------------------------------------------------------------
- 
-STATE OF DEVELOPMENT:
-
-This driver is being developed on the initiative of Piotr Makowski (oponek@gmail.com) and financed by Lars Bergmann.
-Development is carried out by Rainer Zimmermann (mail@lightshed.de).
-
-ESI provided a sample Maya44 card for the development work.
-
-However, unfortunately it has turned out difficult to get detailed programming information, so I (Rainer Zimmermann) had to find out some card-specific information by experiment and conjecture. Some information (in particular, several GPIO bits) is still missing.
-
-This is the first testing version of the Maya44 driver released to the alsa-devel mailing list (Feb 5, 2008).
-
-
-The following functions work, as tested by Rainer Zimmermann and Piotr Makowski:
-
-- playback and capture at all sampling rates
-- input/output level
-- crossmixing
-- line/mic switch
-- phantom power switch
-- analogue monitor a.k.a bypass
-
-
-The following functions *should* work, but are not fully tested:
-
-- Channel 3+4 analogue - S/PDIF input switching
-- S/PDIF output
-- all inputs/outputs on the M/IO/DIO extension card
-- internal/external clock selection
-
-
-*In particular, we would appreciate testing of these functions by anyone who has access to an M/IO/DIO extension card.*
-
-
-Things that do not seem to work:
-
-- The level meters ("multi track") in 'alsamixer' do not seem to react to signals in (if this is a bug, it would probably be in the existing ICE1724 code).
-
-- Ardour 2.1 seems to work only via JACK, not using ALSA directly or via OSS. This still needs to be tracked down.
-
-
-DRIVER DETAILS:
-
-the following files were added:
-
-pci/ice1724/maya44.c        - Maya44 specific code
-pci/ice1724/maya44.h
-pci/ice1724/ice1724.patch
-pci/ice1724/ice1724.h.patch - PROPOSED patch to ice1724.h (see SAMPLING RATES)
-i2c/other/wm8776.c  - low-level access routines for Wolfson WM8776 codecs 
-include/wm8776.h
-
-
-Note that the wm8776.c code is meant to be card-independent and does not actually register the codec with the ALSA infrastructure.
-This is done in maya44.c, mainly because some of the WM8776 controls are used in Maya44-specific ways, and should be named appropriately.
-
-
-the following files were created in pci/ice1724, simply #including the corresponding file from the alsa-kernel tree:
-
-wtm.h
-vt1720_mobo.h
-revo.h
-prodigy192.h
-pontis.h
-phase.h
-maya44.h
-juli.h
-aureon.h
-amp.h
-envy24ht.h
-se.h
-prodigy_hifi.h
-
-
-*I hope this is the correct way to do things.*
-
-
-SAMPLING RATES:
-
-The Maya44 card (or more exactly, the Wolfson WM8776 codecs) allow a maximum sampling rate of 192 kHz for playback and 92 kHz for capture.
-
-As the ICE1724 chip only allows one global sampling rate, this is handled as follows:
-
-* setting the sampling rate on any open PCM device on the maya44 card will always set the *global* sampling rate for all playback and capture channels.
-
-* In the current state of the driver, setting rates of up to 192 kHz is permitted even for capture devices.
-
-*AVOID CAPTURING AT RATES ABOVE 96kHz*, even though it may appear to work. The codec cannot actually capture at such rates, meaning poor quality.
-
-
-I propose some additional code for limiting the sampling rate when setting on a capture pcm device. However because of the global sampling rate, this logic would be somewhat problematic.
-
-The proposed code (currently deactivated) is in ice1712.h.patch, ice1724.c and maya44.c (in pci/ice1712).
-
-
-SOUND DEVICES:
-
-PCM devices correspond to inputs/outputs as follows (assuming Maya44 is card #0):
-
-hw:0,0 input - stereo, analog input 1+2
-hw:0,0 output - stereo, analog output 1+2
-hw:0,1 input - stereo, analog input 3+4 OR S/PDIF input
-hw:0,1 output - stereo, analog output 3+4 (and SPDIF out)
-
-
-NAMING OF MIXER CONTROLS:
-
-(for more information about the signal flow, please refer to the block diagram on p.24 of the ESI Maya44 manual, or in the ESI windows software).
-
-
-PCM: (digital) output level for channel 1+2
-PCM 1: same for channel 3+4
-
-Mic Phantom+48V: switch for +48V phantom power for electrostatic microphones on input 1/2.
-    Make sure this is not turned on while any other source is connected to input 1/2.
-    It might damage the source and/or the maya44 card.
-
-Mic/Line input: if switch is on, input jack 1/2 is microphone input (mono), otherwise line input (stereo).
-
-Bypass: analogue bypass from ADC input to output for channel 1+2. Same as "Monitor" in the windows driver.
-Bypass 1: same for channel 3+4.
-
-Crossmix: cross-mixer from channels 1+2 to channels 3+4
-Crossmix 1: cross-mixer from channels 3+4 to channels 1+2
-
-IEC958 Output: switch for S/PDIF output.
-    This is not supported by the ESI windows driver.
-    S/PDIF should output the same signal as channel 3+4. [untested!]
-
-
-Digitial output selectors:
-
-    These switches allow a direct digital routing from the ADCs to the DACs.
-    Each switch determines where the digital input data to one of the DACs comes from.
-    They are not supported by the ESI windows driver.
-    For normal operation, they should all be set to "PCM out".
-
-H/W: Output source channel 1
-H/W 1: Output source channel 2
-H/W 2: Output source channel 3
-H/W 3: Output source channel 4
-
-H/W 4 ... H/W 9: unknown function, left in to enable testing.
-    Possibly some of these control S/PDIF output(s).
-    If these turn out to be unused, they will go away in later driver versions.
-
-Selectable values for each of the digital output selectors are:
-   "PCM out" -> DAC output of the corresponding channel (default setting)
-   "Input 1"...
-   "Input 4" -> direct routing from ADC output of the selected input channel
-
-
---------
-
-Feb 14, 2008
-Rainer Zimmermann
-mail@lightshed.de
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/SB-Live-mixer.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/SB-Live-mixer.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/SB-Live-mixer.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/SB-Live-mixer.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,356 +0,0 @@
-
-		Sound Blaster Live mixer / default DSP code
-		===========================================
-
-
-The EMU10K1 chips have a DSP part which can be programmed to support
-various ways of sample processing, which is described here.
-(This article does not deal with the overall functionality of the 
-EMU10K1 chips. See the manuals section for further details.)
-
-The ALSA driver programs this portion of chip by default code
-(can be altered later) which offers the following functionality:
-
-
-1) IEC958 (S/PDIF) raw PCM
---------------------------
-
-This PCM device (it's the 4th PCM device (index 3!) and first subdevice
-(index 0) for a given card) allows to forward 48kHz, stereo, 16-bit
-little endian streams without any modifications to the digital output
-(coaxial or optical). The universal interface allows the creation of up
-to 8 raw PCM devices operating at 48kHz, 16-bit little endian. It would
-be easy to add support for multichannel devices to the current code,
-but the conversion routines exist only for stereo (2-channel streams)
-at the time. 
-
-Look to tram_poke routines in lowlevel/emu10k1/emufx.c for more details.
-
-
-2) Digital mixer controls
--------------------------
-
-These controls are built using the DSP instructions. They offer extended
-functionality. Only the default build-in code in the ALSA driver is described
-here. Note that the controls work as attenuators: the maximum value is the 
-neutral position leaving the signal unchanged. Note that if the  same destination 
-is mentioned in multiple controls, the signal is accumulated and can be wrapped 
-(set to maximal or minimal value without checking of overflow).
-
-
-Explanation of used abbreviations:
-
-DAC    - digital to analog converter
-ADC    - analog to digital converter
-I2S    - one-way three wire serial bus for digital sound by Philips Semiconductors
-         (this standard is used for connecting standalone DAC and ADC converters)
-LFE    - low frequency effects (subwoofer signal)
-AC97   - a chip containing an analog mixer, DAC and ADC converters
-IEC958 - S/PDIF
-FX-bus - the EMU10K1 chip has an effect bus containing 16 accumulators.
-         Each of the synthesizer voices can feed its output to these accumulators
-         and the DSP microcontroller can operate with the resulting sum.
-
-
-name='Wave Playback Volume',index=0
-
-This control is used to attenuate samples for left and right PCM FX-bus
-accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
-The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
-
-name='Wave Surround Playback Volume',index=0
-
-This control is used to attenuate samples for left and right PCM FX-bus
-accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
-The result samples are forwarded to the rear I2S DACs. These DACs operates
-separately (they are not inside the AC97 codec).
-
-name='Wave Center Playback Volume',index=0
-
-This control is used to attenuate samples for left and right PCM FX-bus
-accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
-The result is mixed to mono signal (single channel) and forwarded to
-the ??rear?? right DAC PCM slot of the AC97 codec.
-
-name='Wave LFE Playback Volume',index=0
-
-This control is used to attenuate samples for left and right PCM FX-bus
-accumulators. ALSA uses accumulators 0 and 1 for left and right PCM.
-The result is mixed to mono signal (single channel) and forwarded to
-the ??rear?? left DAC PCM slot of the AC97 codec.
-
-name='Wave Capture Volume',index=0
-name='Wave Capture Switch',index=0
-
-These controls are used to attenuate samples for left and right PCM FX-bus
-accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
-The result is forwarded to the ADC capture FIFO (thus to the standard capture
-PCM device).
-
-name='Synth Playback Volume',index=0
-
-This control is used to attenuate samples for left and right MIDI FX-bus
-accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
-The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
-
-name='Synth Capture Volume',index=0
-name='Synth Capture Switch',index=0
-
-These controls are used to attenuate samples for left and right MIDI FX-bus
-accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
-The result is forwarded to the ADC capture FIFO (thus to the standard capture
-PCM device).
-
-name='Surround Playback Volume',index=0
-
-This control is used to attenuate samples for left and right rear PCM FX-bus
-accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
-The result samples are forwarded to the rear I2S DACs. These DACs operate
-separately (they are not inside the AC97 codec).
-
-name='Surround Capture Volume',index=0
-name='Surround Capture Switch',index=0
-
-These controls are used to attenuate samples for left and right rear PCM FX-bus
-accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
-The result is forwarded to the ADC capture FIFO (thus to the standard capture
-PCM device).
-
-name='Center Playback Volume',index=0
-
-This control is used to attenuate sample for center PCM FX-bus accumulator.
-ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
-to the ??rear?? right DAC PCM slot of the AC97 codec.
-
-name='LFE Playback Volume',index=0
-
-This control is used to attenuate sample for center PCM FX-bus accumulator.
-ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
-to the ??rear?? left DAC PCM slot of the AC97 codec.
-
-name='AC97 Playback Volume',index=0
-
-This control is used to attenuate samples for left and right front ADC PCM slots
-of the AC97 codec. The result samples are forwarded to the front DAC PCM
-slots of the AC97 codec.
-********************************************************************************
-*** Note: This control should be zero for the standard operations, otherwise ***
-*** a digital loopback is activated.                                         ***
-********************************************************************************
-
-name='AC97 Capture Volume',index=0
-
-This control is used to attenuate samples for left and right front ADC PCM slots
-of the AC97 codec. The result is forwarded to the ADC capture FIFO (thus to
-the standard capture PCM device).
-********************************************************************************
-*** Note: This control should be 100 (maximal value), otherwise no analog    ***
-*** inputs of the AC97 codec can be captured (recorded).                     ***
-********************************************************************************
-
-name='IEC958 TTL Playback Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 TTL
-digital inputs (usually used by a CDROM drive). The result samples are
-forwarded to the front DAC PCM slots of the AC97 codec.
-
-name='IEC958 TTL Capture Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 TTL
-digital inputs (usually used by a CDROM drive). The result samples are
-forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
-
-name='Zoom Video Playback Volume',index=0
-
-This control is used to attenuate samples from left and right zoom video
-digital inputs (usually used by a CDROM drive). The result samples are
-forwarded to the front DAC PCM slots of the AC97 codec.
-
-name='Zoom Video Capture Volume',index=0
-
-This control is used to attenuate samples from left and right zoom video
-digital inputs (usually used by a CDROM drive). The result samples are
-forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
-
-name='IEC958 LiveDrive Playback Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 optical
-digital input. The result samples are forwarded to the front DAC PCM slots
-of the AC97 codec.
-
-name='IEC958 LiveDrive Capture Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 optical
-digital inputs. The result samples are forwarded to the ADC capture FIFO
-(thus to the standard capture PCM device).
-
-name='IEC958 Coaxial Playback Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 coaxial
-digital inputs. The result samples are forwarded to the front DAC PCM slots
-of the AC97 codec.
-
-name='IEC958 Coaxial Capture Volume',index=0
-
-This control is used to attenuate samples from left and right IEC958 coaxial
-digital inputs. The result samples are forwarded to the ADC capture FIFO
-(thus to the standard capture PCM device).
-
-name='Line LiveDrive Playback Volume',index=0
-name='Line LiveDrive Playback Volume',index=1
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs (on the LiveDrive). The result samples are forwarded to the front
-DAC PCM slots of the AC97 codec.
-
-name='Line LiveDrive Capture Volume',index=1
-name='Line LiveDrive Capture Volume',index=1
-
-This control is used to attenuate samples from left and right I2S ADC
-inputs (on the LiveDrive). The result samples are forwarded to the ADC
-capture FIFO (thus to the standard capture PCM device).
-
-name='Tone Control - Switch',index=0
-
-This control turns the tone control on or off. The samples for front, rear
-and center / LFE outputs are affected.
-
-name='Tone Control - Bass',index=0
-
-This control sets the bass intensity. There is no neutral value!!
-When the tone control code is activated, the samples are always modified.
-The closest value to pure signal is 20.
-
-name='Tone Control - Treble',index=0
-
-This control sets the treble intensity. There is no neutral value!!
-When the tone control code is activated, the samples are always modified.
-The closest value to pure signal is 20.
-
-name='IEC958 Optical Raw Playback Switch',index=0
-
-If this switch is on, then the samples for the IEC958 (S/PDIF) digital
-output are taken only from the raw FX8010 PCM, otherwise standard front
-PCM samples are taken.
-
-name='Headphone Playback Volume',index=1
-
-This control attenuates the samples for the headphone output.
-
-name='Headphone Center Playback Switch',index=1
-
-If this switch is on, then the sample for the center PCM is put to the
-left headphone output (useful for SB Live cards without separate center/LFE
-output).
-
-name='Headphone LFE Playback Switch',index=1
-
-If this switch is on, then the sample for the center PCM is put to the
-right headphone output (useful for SB Live cards without separate center/LFE
-output).
-
-
-3) PCM stream related controls
-------------------------------
-
-name='EMU10K1 PCM Volume',index 0-31
-
-Channel volume attenuation in range 0-0xffff. The maximum value (no
-attenuation) is default. The channel mapping for three values is
-as follows:
-
-	0 - mono, default 0xffff (no attenuation)
-	1 - left, default 0xffff (no attenuation)
-	2 - right, default 0xffff (no attenuation)
-
-name='EMU10K1 PCM Send Routing',index 0-31
-
-This control specifies the destination - FX-bus accumulators. There are
-twelve values with this mapping:
-
-	 0 -  mono, A destination (FX-bus 0-15), default 0
-	 1 -  mono, B destination (FX-bus 0-15), default 1
-	 2 -  mono, C destination (FX-bus 0-15), default 2
-	 3 -  mono, D destination (FX-bus 0-15), default 3
-	 4 -  left, A destination (FX-bus 0-15), default 0
-	 5 -  left, B destination (FX-bus 0-15), default 1
-	 6 -  left, C destination (FX-bus 0-15), default 2
-	 7 -  left, D destination (FX-bus 0-15), default 3
-	 8 - right, A destination (FX-bus 0-15), default 0
-	 9 - right, B destination (FX-bus 0-15), default 1
-	10 - right, C destination (FX-bus 0-15), default 2
-	11 - right, D destination (FX-bus 0-15), default 3
-
-Don't forget that it's illegal to assign a channel to the same FX-bus accumulator 
-more than once (it means 0=0 && 1=0 is an invalid combination).
- 
-name='EMU10K1 PCM Send Volume',index 0-31
-
-It specifies the attenuation (amount) for given destination in range 0-255.
-The channel mapping is following:
-
-	 0 -  mono, A destination attn, default 255 (no attenuation)
-	 1 -  mono, B destination attn, default 255 (no attenuation)
-	 2 -  mono, C destination attn, default 0 (mute)
-	 3 -  mono, D destination attn, default 0 (mute)
-	 4 -  left, A destination attn, default 255 (no attenuation)
-	 5 -  left, B destination attn, default 0 (mute)
-	 6 -  left, C destination attn, default 0 (mute)
-	 7 -  left, D destination attn, default 0 (mute)
-	 8 - right, A destination attn, default 0 (mute)
-	 9 - right, B destination attn, default 255 (no attenuation)
-	10 - right, C destination attn, default 0 (mute)
-	11 - right, D destination attn, default 0 (mute)
-
-
-
-4) MANUALS/PATENTS:
--------------------
-
-ftp://opensource.creative.com/pub/doc
--------------------------------------
-
-        Files:
-        LM4545.pdf      AC97 Codec
-
-        m2049.pdf       The EMU10K1 Digital Audio Processor
-
-        hog63.ps        FX8010 - A DSP Chip Architecture for Audio Effects
-
-
-WIPO Patents
-------------
-        Patent numbers:
-        WO 9901813 (A1) Audio Effects Processor with multiple asynchronous (Jan. 14, 1999)
-                        streams
-
-        WO 9901814 (A1) Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
-
-        WO 9901953 (A1) Audio Effects Processor having Decoupled Instruction
-                        Execution and Audio Data Sequencing (Jan. 14, 1999)
-
-
-US Patents (http://www.uspto.gov/)
-----------------------------------
-
-        US 5925841      Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
-
-        US 5928342      Audio Effects Processor integrated on a single chip (Jul. 27, 1999)
-                        with a multiport memory onto which multiple asynchronous
-                        digital sound samples can be concurrently loaded
-
-        US 5930158      Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
-
-        US 6032235      Memory initialization circuit (Tram) (Feb. 29, 2000)
-
-        US 6138207      Interpolation looping of audio samples in cache connected to    (Oct. 24, 2000)
-                        system bus with prioritization and modification of bus transfers
-                        in accordance with loop ends and minimum block sizes
-
-        US 6151670      Method for conserving memory storage using a (Nov. 21, 2000)
-                        pool of  short term memory registers
-
-        US 6195715      Interrupt control for multiple programs communicating with      (Feb. 27, 2001)
-                        a common interrupt by associating programs to GP registers,
-                        defining interrupt register, polling GP registers, and invoking
-                        callback routine associated with defined interrupt register
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/seq_oss.html linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/seq_oss.html
--- linux-libre-4.9-gnu/Documentation/sound/alsa/seq_oss.html	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/seq_oss.html	1969-12-31 19:00:00.000000000 -0500
@@ -1,409 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<HTML>
-<HEAD>
-   <TITLE>OSS Sequencer Emulation on ALSA</TITLE>
-</HEAD>
-<BODY>
-
-<CENTER>
-<H1>
-
-<HR WIDTH="100%"></H1></CENTER>
-
-<CENTER>
-<H1>
-OSS Sequencer Emulation on ALSA</H1></CENTER>
-
-<HR WIDTH="100%">
-<P>Copyright (c) 1998,1999 by Takashi Iwai
-<TT><A HREF="mailto:iwai@ww.uni-erlangen.de">&lt;iwai@ww.uni-erlangen.de></A></TT>
-<P>ver.0.1.8; Nov. 16, 1999
-<H2>
-
-<HR WIDTH="100%"></H2>
-
-<H2>
-1. Description</H2>
-This directory contains the OSS sequencer emulation driver on ALSA. Note
-that this program is still in the development state.
-<P>What this does - it provides the emulation of the OSS sequencer, access
-via
-<TT>/dev/sequencer</TT> and <TT>/dev/music</TT> devices.
-The most of applications using OSS can run if the appropriate ALSA
-sequencer is prepared.
-<P>The following features are emulated by this driver:
-<UL>
-<LI>
-Normal sequencer and MIDI events:</LI>
-
-<BR>They are converted to the ALSA sequencer events, and sent to the corresponding
-port.
-<LI>
-Timer events:</LI>
-
-<BR>The timer is not selectable by ioctl. The control rate is fixed to
-100 regardless of HZ. That is, even on Alpha system, a tick is always
-1/100 second. The base rate and tempo can be changed in <TT>/dev/music</TT>.
-
-<LI>
-Patch loading:</LI>
-
-<BR>It purely depends on the synth drivers whether it's supported since
-the patch loading is realized by callback to the synth driver.
-<LI>
-I/O controls:</LI>
-
-<BR>Most of controls are accepted. Some controls
-are dependent on the synth driver, as well as even on original OSS.</UL>
-Furthermore, you can find the following advanced features:
-<UL>
-<LI>
-Better queue mechanism:</LI>
-
-<BR>The events are queued before processing them.
-<LI>
-Multiple applications:</LI>
-
-<BR>You can run two or more applications simultaneously (even for OSS sequencer)!
-However, each MIDI device is exclusive - that is, if a MIDI device is opened
-once by some application, other applications can't use it. No such a restriction
-in synth devices.
-<LI>
-Real-time event processing:</LI>
-
-<BR>The events can be processed in real time without using out of bound
-ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
-events will be processed in real-time without queued. To switch off the
-real-time mode, send RELTIME 0 event.
-<LI>
-<TT>/proc</TT> interface:</LI>
-
-<BR>The status of applications and devices can be shown via <TT>/proc/asound/seq/oss</TT>
-at any time. In the later version, configuration will be changed via <TT>/proc</TT>
-interface, too.</UL>
-
-<H2>
-2. Installation</H2>
-Run configure script with both sequencer support (<TT>--with-sequencer=yes</TT>)
-and OSS emulation (<TT>--with-oss=yes</TT>) options. A module <TT>snd-seq-oss.o</TT>
-will be created. If the synth module of your sound card supports for OSS
-emulation (so far, only Emu8000 driver), this module will be loaded automatically.
-Otherwise, you need to load this module manually.
-<P>At beginning, this module probes all the MIDI ports which have been
-already connected to the sequencer. Once after that, the creation and deletion
-of ports are watched by announcement mechanism of ALSA sequencer.
-<P>The available synth and MIDI devices can be found in proc interface.
-Run "<TT>cat /proc/asound/seq/oss</TT>", and check the devices. For example,
-if you use an AWE64 card, you'll see like the following:
-<PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OSS sequencer emulation version 0.1.8
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALSA client number 63
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALSA receiver port 0
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of applications: 0
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of synth devices: 1
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synth 0: [EMU8000]
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type 0x1 : subtype 0x20 : voices 32
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capabilties : ioctl enabled / load_patch enabled
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Number of MIDI devices: 3
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 0: [Emu8000 Port-0] ALSA port 65:0
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability write / opened none
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 1: [Emu8000 Port-1] ALSA port 65:1
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability write / opened none
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; midi 2: [0: MPU-401 (UART)] ALSA port 64:0
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; capability read/write / opened none</PRE>
-Note that the device number may be different from the information of
-<TT>/proc/asound/oss-devices</TT>
-or ones of the original OSS driver. Use the device number listed in <TT>/proc/asound/seq/oss</TT>
-to play via OSS sequencer emulation.
-<H2>
-3. Using Synthesizer Devices</H2>
-Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
-and xmp-1.1.5. You can load samples via <TT>/dev/sequencer</TT> like sfxload,
-too.
-<P>If the lowlevel driver supports multiple access to synth devices (like
-Emu8000 driver), two or more applications are allowed to run at the same
-time.
-<H2>
-4. Using MIDI Devices</H2>
-So far, only MIDI output was tested. MIDI input was not checked at all,
-but hopefully it will work. Use the device number listed in <TT>/proc/asound/seq/oss</TT>.
-Be aware that these numbers are mostly different from the list in
-<TT>/proc/asound/oss-devices</TT>.
-<H2>
-5. Module Options</H2>
-The following module options are available:
-<UL>
-<LI>
-<TT>maxqlen</TT></LI>
-
-<BR>specifies the maximum read/write queue length. This queue is private
-for OSS sequencer, so that it is independent from the queue length of ALSA
-sequencer. Default value is 1024.
-<LI>
-<TT>seq_oss_debug</TT></LI>
-
-<BR>specifies the debug level and accepts zero (= no debug message) or
-positive integer. Default value is 0.</UL>
-
-<H2>
-6. Queue Mechanism</H2>
-OSS sequencer emulation uses an ALSA priority queue. The
-events from <TT>/dev/sequencer</TT> are processed and put onto the queue
-specified by module option.
-<P>All the events from <TT>/dev/sequencer</TT> are parsed at beginning.
-The timing events are also parsed at this moment, so that the events may
-be processed in real-time. Sending an event ABSTIME 0 switches the operation
-mode to real-time mode, and sending an event RELTIME 0 switches it off.
-In the real-time mode, all events are dispatched immediately.
-<P>The queued events are dispatched to the corresponding ALSA sequencer
-ports after scheduled time by ALSA sequencer dispatcher.
-<P>If the write-queue is full, the application sleeps until a certain amount
-(as default one half) becomes empty in blocking mode. The synchronization
-to write timing was implemented, too.
-<P>The input from MIDI devices or echo-back events are stored on read FIFO
-queue. If application reads <TT>/dev/sequencer</TT> in blocking mode, the
-process will be awaked.
-
-<H2>
-7. Interface to Synthesizer Device</H2>
-
-<H3>
-7.1. Registration</H3>
-To register an OSS synthesizer device, use <TT>snd_seq_oss_synth_register</TT>
-function.
-<PRE>int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snd_seq_oss_callback_t *oper, void *private_data)</PRE>
-The arguments <TT>name</TT>, <TT>type</TT>, <TT>subtype</TT> and
-<TT>nvoices</TT>
-are used for making the appropriate synth_info structure for ioctl. The
-return value is an index number of this device. This index must be remembered
-for unregister. If registration is failed, -errno will be returned.
-<P>To release this device, call <TT>snd_seq_oss_synth_unregister function</TT>:
-<PRE>int snd_seq_oss_synth_unregister(int index),</PRE>
-where the <TT>index</TT> is the index number returned by register function.
-<H3>
-7.2. Callbacks</H3>
-OSS synthesizer devices have capability for sample downloading and ioctls
-like sample reset. In OSS emulation, these special features are realized
-by using callbacks. The registration argument oper is used to specify these
-callbacks. The following callback functions must be defined:
-<PRE>snd_seq_oss_callback_t:
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*open)(snd_seq_oss_arg_t *p, void *closure);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*close)(snd_seq_oss_arg_t *p);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int (*reset)(snd_seq_oss_arg_t *p);
-Except for <TT>open</TT> and <TT>close</TT> callbacks, they are allowed
-to be NULL.
-<P>Each callback function takes the argument type snd_seq_oss_arg_t as the
-first argument.
-<PRE>struct snd_seq_oss_arg_t {
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int app_index;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int file_mode;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int seq_mode;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snd_seq_addr_t addr;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *private_data;
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int event_passing;
-};</PRE>
-The first three fields, <TT>app_index</TT>, <TT>file_mode</TT> and
-<TT>seq_mode</TT>
-are initialized by OSS sequencer. The <TT>app_index</TT> is the application
-index which is unique to each application opening OSS sequencer. The
-<TT>file_mode</TT>
-is bit-flags indicating the file operation mode. See
-<TT>seq_oss.h</TT>
-for its meaning. The <TT>seq_mode</TT> is sequencer operation mode. In
-the current version, only <TT>SND_OSSSEQ_MODE_SYNTH</TT> is used.
-<P>The next two fields, <TT>addr</TT> and <TT>private_data</TT>, must be
-filled by the synth driver at open callback. The <TT>addr</TT> contains
-the address of ALSA sequencer port which is assigned to this device. If
-the driver allocates memory for <TT>private_data</TT>, it must be released
-in close callback by itself.
-<P>The last field, <TT>event_passing</TT>, indicates how to translate note-on
-/ off events. In <TT>PROCESS_EVENTS</TT> mode, the note 255 is regarded
-as velocity change, and key pressure event is passed to the port. In <TT>PASS_EVENTS</TT>
-mode, all note on/off events are passed to the port without modified. <TT>PROCESS_KEYPRESS</TT>
-mode checks the note above 128 and regards it as key pressure event (mainly
-for Emu8000 driver).
-<H4>
-7.2.1. Open Callback</H4>
-The <TT>open</TT> is called at each time this device is opened by an application
-using OSS sequencer. This must not be NULL. Typically, the open callback
-does the following procedure:
-<OL>
-<LI>
-Allocate private data record.</LI>
-
-<LI>
-Create an ALSA sequencer port.</LI>
-
-<LI>
-Set the new port address on arg->addr.</LI>
-
-<LI>
-Set the private data record pointer on arg->private_data.</LI>
-</OL>
-Note that the type bit-flags in port_info of this synth port must NOT contain
-<TT>TYPE_MIDI_GENERIC</TT>
-bit. Instead, <TT>TYPE_SPECIFIC</TT> should be used. Also, <TT>CAP_SUBSCRIPTION</TT>
-bit should NOT be included, too. This is necessary to tell it from other
-normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
-return -errno.
-<H4>
-7.2.2 Ioctl Callback</H4>
-The <TT>ioctl</TT> callback is called when the sequencer receives device-specific
-ioctls. The following two ioctls should be processed by this callback:
-<UL>
-<LI>
-<TT>IOCTL_SEQ_RESET_SAMPLES</TT></LI>
-
-<BR>reset all samples on memory -- return 0
-<LI>
-<TT>IOCTL_SYNTH_MEMAVL</TT></LI>
-
-<BR>return the available memory size
-<LI>
-<TT>FM_4OP_ENABLE</TT></LI>
-
-<BR>can be ignored usually</UL>
-The other ioctls are processed inside the sequencer without passing to
-the lowlevel driver.
-<H4>
-7.2.3 Load_Patch Callback</H4>
-The <TT>load_patch</TT> callback is used for sample-downloading. This callback
-must read the data on user-space and transfer to each device. Return 0
-if succeeded, and -errno if failed. The format argument is the patch key
-in patch_info record. The buf is user-space pointer where patch_info record
-is stored. The offs can be ignored. The count is total data size of this
-sample data.
-<H4>
-7.2.4 Close Callback</H4>
-The <TT>close</TT> callback is called when this device is closed by the
-application. If any private data was allocated in open callback, it must
-be released in the close callback. The deletion of ALSA port should be
-done here, too. This callback must not be NULL.
-<H4>
-7.2.5 Reset Callback</H4>
-The <TT>reset</TT> callback is called when sequencer device is reset or
-closed by applications. The callback should turn off the sounds on the
-relevant port immediately, and initialize the status of the port. If this
-callback is undefined, OSS seq sends a <TT>HEARTBEAT</TT> event to the
-port.
-<H3>
-7.3 Events</H3>
-Most of the events are processed by sequencer and translated to the adequate
-ALSA sequencer events, so that each synth device can receive by input_event
-callback of ALSA sequencer port. The following ALSA events should be implemented
-by the driver:
-<BR>&nbsp;
-<TABLE BORDER WIDTH="75%" NOSAVE >
-<TR NOSAVE>
-<TD NOSAVE><B>ALSA event</B></TD>
-
-<TD><B>Original OSS events</B></TD>
-</TR>
-
-<TR>
-<TD>NOTEON</TD>
-
-<TD>SEQ_NOTEON
-<BR>MIDI_NOTEON</TD>
-</TR>
-
-<TR>
-<TD>NOTE</TD>
-
-<TD>SEQ_NOTEOFF
-<BR>MIDI_NOTEOFF</TD>
-</TR>
-
-<TR NOSAVE>
-<TD NOSAVE>KEYPRESS</TD>
-
-<TD>MIDI_KEY_PRESSURE</TD>
-</TR>
-
-<TR NOSAVE>
-<TD>CHANPRESS</TD>
-
-<TD NOSAVE>SEQ_AFTERTOUCH
-<BR>MIDI_CHN_PRESSURE</TD>
-</TR>
-
-<TR NOSAVE>
-<TD NOSAVE>PGMCHANGE</TD>
-
-<TD NOSAVE>SEQ_PGMCHANGE
-<BR>MIDI_PGM_CHANGE</TD>
-</TR>
-
-<TR>
-<TD>PITCHBEND</TD>
-
-<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER)
-<BR>MIDI_PITCH_BEND</TD>
-</TR>
-
-<TR>
-<TD>CONTROLLER</TD>
-
-<TD>MIDI_CTL_CHANGE
-<BR>SEQ_BALANCE (with CTL_PAN)</TD>
-</TR>
-
-<TR>
-<TD>CONTROL14</TD>
-
-<TD>SEQ_CONTROLLER</TD>
-</TR>
-
-<TR>
-<TD>REGPARAM</TD>
-
-<TD>SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)</TD>
-</TR>
-
-<TR>
-<TD>SYSEX</TD>
-
-<TD>SEQ_SYSEX</TD>
-</TR>
-</TABLE>
-
-<P>The most of these behavior can be realized by MIDI emulation driver
-included in the Emu8000 lowlevel driver. In the future release, this module
-will be independent.
-<P>Some OSS events (<TT>SEQ_PRIVATE</TT> and <TT>SEQ_VOLUME</TT> events) are passed as event
-type SND_SEQ_OSS_PRIVATE.  The OSS sequencer passes these event 8 byte
-packets without any modification. The lowlevel driver should process these
-events appropriately.
-<H2>
-8. Interface to MIDI Device</H2>
-Since the OSS emulation probes the creation and deletion of ALSA MIDI sequencer
-ports automatically by receiving announcement from ALSA sequencer, the
-MIDI devices don't need to be registered explicitly like synth devices.
-However, the MIDI port_info registered to ALSA sequencer must include a group
-name <TT>SND_SEQ_GROUP_DEVICE</TT> and a capability-bit <TT>CAP_READ</TT> or
-<TT>CAP_WRITE</TT>. Also, subscription capabilities, <TT>CAP_SUBS_READ</TT> or <TT>CAP_SUBS_WRITE</TT>,
-must be defined, too. If these conditions are not satisfied, the port is not
-registered as OSS sequencer MIDI device.
-<P>The events via MIDI devices are parsed in OSS sequencer and converted
-to the corresponding ALSA sequencer events. The input from MIDI sequencer
-is also converted to MIDI byte events by OSS sequencer. This works just
-a reverse way of seq_midi module.
-<H2>
-9. Known Problems / TODO's</H2>
-
-<UL>
-<LI>
-Patch loading via ALSA instrument layer is not implemented yet.</LI>
-</UL>
-
-</BODY>
-</HTML>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/serial-u16550.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/serial-u16550.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/serial-u16550.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/serial-u16550.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,88 +0,0 @@
-
-			Serial UART 16450/16550 MIDI driver
-			===================================
-
-The adaptor module parameter allows you to select either:
-
-  0 - Roland Soundcanvas support (default)
-  1 - Midiator MS-124T support (1)
-  2 - Midiator MS-124W S/A mode (2)
-  3 - MS-124W M/B mode support (3)
-  4 - Generic device with multiple input support (4)
-
-For the Midiator MS-124W, you must set the physical M-S and A-B
-switches on the Midiator to match the driver mode you select.
-
-In Roland Soundcanvas mode, multiple ALSA raw MIDI substreams are supported
-(midiCnD0-midiCnD15).  Whenever you write to a different substream, the driver
-sends the nonstandard MIDI command sequence F5 NN, where NN is the substream
-number plus 1.  Roland modules use this command to switch between different
-"parts", so this feature lets you treat each part as a distinct raw MIDI
-substream. The driver provides no way to send F5 00 (no selection) or to not
-send the F5 NN command sequence at all; perhaps it ought to.
-
-Usage example for simple serial converter:
-
-	/sbin/setserial /dev/ttyS0 uart none
-	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
-
-Usage example for Roland SoundCanvas with 4 MIDI ports:
-
-	/sbin/setserial /dev/ttyS0 uart none
-	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
-
-In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
-module parameter is automatically set to 1. The driver sends the same data to
-all four MIDI Out connectors.  Set the A-B switch and the speed module
-parameter to match (A=19200, B=9600).
-
-Usage example for MS-124T, with A-B switch in A position:
-
-	/sbin/setserial /dev/ttyS0 uart none
-	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
-			speed=19200
-
-In MS-124W S/A mode, one raw MIDI substream is supported (midiCnD0);
-the outs module parameter is automatically set to 1. The driver sends
-the same data to all four MIDI Out connectors at full MIDI speed.
-
-Usage example for S/A mode:
-
-	/sbin/setserial /dev/ttyS0 uart none
-	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
-
-In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
-the outs module parameter is automatically set to 16.  The substream
-number gives a bitmask of which MIDI Out connectors the data should be
-sent to, with midiCnD1 sending to Out 1, midiCnD2 to Out 2, midiCnD4 to
-Out 3, and midiCnD8 to Out 4.  Thus midiCnD15 sends the data to all 4 ports.
-As a special case, midiCnD0 also sends to all ports, since it is not useful
-to send the data to no ports.  M/B mode has extra overhead to select the MIDI
-Out for each byte, so the aggregate data rate across all four MIDI Outs is
-at most one byte every 520 us, as compared with the full MIDI data rate of
-one byte every 320 us per port.
-
-Usage example for M/B mode:
-
-	/sbin/setserial /dev/ttyS0 uart none
-	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
-
-The MS-124W hardware's M/A mode is currently not supported. This mode allows
-the MIDI Outs to act independently at double the aggregate throughput of M/B,
-but does not allow sending the same byte simultaneously to multiple MIDI Outs. 
-The M/A protocol requires the driver to twiddle the modem control lines under
-timing constraints, so it would be a bit more complicated to implement than
-the other modes.
-
-Midiator models other than MS-124W and MS-124T are currently not supported. 
-Note that the suffix letter is significant; the MS-124 and MS-124B are not
-compatible, nor are the other known models MS-101, MS-101B, MS-103, and MS-114.
-I do have documentation (tim.mann@compaq.com) that partially covers these models,
-but no units to experiment with.  The MS-124W support is tested with a real unit.
-The MS-124T support is untested, but should work.
-
-The Generic driver supports multiple input and output substreams over a single
-serial port.  Similar to Roland Soundcanvas mode, F5 NN is used to select the
-appropriate input or output stream (depending on the data direction).
-Additionally, the CTS signal is used to regulate the data flow.  The number of
-inputs is specified by the ins parameter.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/clocking.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/clocking.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/clocking.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/clocking.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-Audio Clocking
-==============
-
-This text describes the audio clocking terms in ASoC and digital audio in
-general. Note: Audio clocking can be complex!
-
-
-Master Clock
-------------
-
-Every audio subsystem is driven by a master clock (sometimes referred to as MCLK
-or SYSCLK). This audio master clock can be derived from a number of sources
-(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
-audio playback and capture sample rates.
-
-Some master clocks (e.g. PLLs and CPU based clocks) are configurable in that
-their speed can be altered by software (depending on the system use and to save
-power). Other master clocks are fixed at a set frequency (i.e. crystals).
-
-
-DAI Clocks
-----------
-The Digital Audio Interface is usually driven by a Bit Clock (often referred to
-as BCLK). This clock is used to drive the digital audio data across the link
-between the codec and CPU.
-
-The DAI also has a frame clock to signal the start of each audio frame. This
-clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
-runs at exactly the sample rate (LRC = Rate).
-
-Bit Clock can be generated as follows:-
-
-BCLK = MCLK / x
-
- or
-
-BCLK = LRC * x
-
- or
-
-BCLK = LRC * Channels * Word Size
-
-This relationship depends on the codec or SoC CPU in particular. In general
-it is best to configure BCLK to the lowest possible speed (depending on your
-rate, number of channels and word size) to save on power.
-
-It is also desirable to use the codec (if possible) to drive (or master) the
-audio clocks as it usually gives more accurate sample rates than the CPU.
-
-
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/codec.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/codec.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/codec.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/codec.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-ASoC Codec Class Driver
-=======================
-
-The codec class driver is generic and hardware independent code that configures
-the codec, FM, MODEM, BT or external DSP to provide audio capture and playback.
-It should contain no code that is specific to the target platform or machine.
-All platform and machine specific code should be added to the platform and
-machine drivers respectively.
-
-Each codec class driver *must* provide the following features:-
-
- 1) Codec DAI and PCM configuration
- 2) Codec control IO - using RegMap API
- 3) Mixers and audio controls
- 4) Codec audio operations
- 5) DAPM description.
- 6) DAPM event handler.
-
-Optionally, codec drivers can also provide:-
-
- 7) DAC Digital mute control.
-
-Its probably best to use this guide in conjunction with the existing codec
-driver code in sound/soc/codecs/
-
-ASoC Codec driver breakdown
-===========================
-
-1 - Codec DAI and PCM configuration
------------------------------------
-Each codec driver must have a struct snd_soc_dai_driver to define its DAI and
-PCM capabilities and operations. This struct is exported so that it can be
-registered with the core by your machine driver.
-
-e.g.
-
-static struct snd_soc_dai_ops wm8731_dai_ops = {
-	.prepare	= wm8731_pcm_prepare,
-	.hw_params	= wm8731_hw_params,
-	.shutdown	= wm8731_shutdown,
-	.digital_mute	= wm8731_mute,
-	.set_sysclk	= wm8731_set_dai_sysclk,
-	.set_fmt	= wm8731_set_dai_fmt,
-};
-
-struct snd_soc_dai_driver wm8731_dai = {
-	.name = "wm8731-hifi",
-	.playback = {
-		.stream_name = "Playback",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = WM8731_RATES,
-		.formats = WM8731_FORMATS,},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = WM8731_RATES,
-		.formats = WM8731_FORMATS,},
-	.ops = &wm8731_dai_ops,
-	.symmetric_rates = 1,
-};
-
-
-2 - Codec control IO
---------------------
-The codec can usually be controlled via an I2C or SPI style interface
-(AC97 combines control with data in the DAI). The codec driver should use the
-Regmap API for all codec IO. Please see include/linux/regmap.h and existing
-codec drivers for example regmap usage.
-
-
-3 - Mixers and audio controls
------------------------------
-All the codec mixers and audio controls can be defined using the convenience
-macros defined in soc.h.
-
-    #define SOC_SINGLE(xname, reg, shift, mask, invert)
-
-Defines a single control as follows:-
-
-  xname = Control name e.g. "Playback Volume"
-  reg = codec register
-  shift = control bit(s) offset in register
-  mask = control bit size(s) e.g. mask of 7 = 3 bits
-  invert = the control is inverted
-
-Other macros include:-
-
-    #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
-
-A stereo control
-
-    #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
-
-A stereo control spanning 2 registers
-
-    #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
-
-Defines an single enumerated control as follows:-
-
-   xreg = register
-   xshift = control bit(s) offset in register
-   xmask = control bit(s) size
-   xtexts = pointer to array of strings that describe each setting
-
-   #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
-
-Defines a stereo enumerated control
-
-
-4 - Codec Audio Operations
---------------------------
-The codec driver also supports the following ALSA PCM operations:-
-
-/* SoC audio ops */
-struct snd_soc_ops {
-	int (*startup)(struct snd_pcm_substream *);
-	void (*shutdown)(struct snd_pcm_substream *);
-	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
-	int (*hw_free)(struct snd_pcm_substream *);
-	int (*prepare)(struct snd_pcm_substream *);
-};
-
-Please refer to the ALSA driver PCM documentation for details.
-http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
-
-
-5 - DAPM description.
----------------------
-The Dynamic Audio Power Management description describes the codec power
-components and their relationships and registers to the ASoC core.
-Please read dapm.txt for details of building the description.
-
-Please also see the examples in other codec drivers.
-
-
-6 - DAPM event handler
-----------------------
-This function is a callback that handles codec domain PM calls and system
-domain PM calls (e.g. suspend and resume). It is used to put the codec
-to sleep when not in use.
-
-Power states:-
-
-	SNDRV_CTL_POWER_D0: /* full On */
-	/* vref/mid, clk and osc on, active */
-
-	SNDRV_CTL_POWER_D1: /* partial On */
-	SNDRV_CTL_POWER_D2: /* partial On */
-
-	SNDRV_CTL_POWER_D3hot: /* Off, with power */
-	/* everything off except vref/vmid, inactive */
-
-	SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
-
-
-7 - Codec DAC digital mute control
-----------------------------------
-Most codecs have a digital mute before the DACs that can be used to
-minimise any system noise.  The mute stops any digital data from
-entering the DAC.
-
-A callback can be created that is called by the core for each codec DAI
-when the mute is applied or freed.
-
-i.e.
-
-static int wm8974_mute(struct snd_soc_dai *dai, int mute)
-{
-	struct snd_soc_codec *codec = dai->codec;
-	u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
-
-	if (mute)
-		snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
-	else
-		snd_soc_write(codec, WM8974_DAC, mute_reg);
-	return 0;
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/DAI.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/DAI.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/DAI.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/DAI.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
-SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.
-
-
-AC97
-====
-
-  AC97 is a five wire interface commonly found on many PC sound cards. It is
-now also popular in many portable devices. This DAI has a reset line and time
-multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
-The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
-frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
-frame is 21uS long and is divided into 13 time slots.
-
-The AC97 specification can be found at :-
-http://www.intel.com/p/en_US/business/design
-
-
-I2S
-===
-
- I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
-Rx lines are used for audio transmission, whilst the bit clock (BCLK) and
-left/right clock (LRC) synchronise the link. I2S is flexible in that either the
-controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
-usually varies depending on the sample rate and the master system clock
-(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
-ADC and DAC LRCLKs, this allows for simultaneous capture and playback at
-different sample rates.
-
-I2S has several different operating modes:-
-
- o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
-         transition.
-
- o Left Justified - MSB is transmitted on transition of LRC.
-
- o Right Justified - MSB is transmitted sample size BCLKs before LRC
-                     transition.
-
-PCM
-===
-
-PCM is another 4 wire interface, very similar to I2S, which can support a more
-flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
-to synchronise the link whilst the Tx and Rx lines are used to transmit and
-receive the audio data. Bit clock usually varies depending on sample rate
-whilst sync runs at the sample rate. PCM also supports Time Division
-Multiplexing (TDM) in that several devices can use the bus simultaneously (this
-is sometimes referred to as network mode).
-
-Common PCM operating modes:-
-
- o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
-
- o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/dapm.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/dapm.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/dapm.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/dapm.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,305 +0,0 @@
-Dynamic Audio Power Management for Portable Devices
-===================================================
-
-1. Description
-==============
-
-Dynamic Audio Power Management (DAPM) is designed to allow portable
-Linux devices to use the minimum amount of power within the audio
-subsystem at all times. It is independent of other kernel PM and as
-such, can easily co-exist with the other PM systems.
-
-DAPM is also completely transparent to all user space applications as
-all power switching is done within the ASoC core. No code changes or
-recompiling are required for user space applications. DAPM makes power
-switching decisions based upon any audio stream (capture/playback)
-activity and audio mixer settings within the device.
-
-DAPM spans the whole machine. It covers power control within the entire
-audio subsystem, this includes internal codec power blocks and machine
-level power systems.
-
-There are 4 power domains within DAPM
-
-   1. Codec bias domain - VREF, VMID (core codec and audio power)
-      Usually controlled at codec probe/remove and suspend/resume, although
-      can be set at stream time if power is not needed for sidetone, etc.
-
-   2. Platform/Machine domain - physically connected inputs and outputs
-      Is platform/machine and user action specific, is configured by the
-      machine driver and responds to asynchronous events e.g when HP
-      are inserted
-
-   3. Path domain - audio subsystem signal paths
-      Automatically set when mixer and mux settings are changed by the user.
-      e.g. alsamixer, amixer.
-
-   4. Stream domain - DACs and ADCs.
-      Enabled and disabled when stream playback/capture is started and
-      stopped respectively. e.g. aplay, arecord.
-
-All DAPM power switching decisions are made automatically by consulting an audio
-routing map of the whole machine. This map is specific to each machine and
-consists of the interconnections between every audio component (including
-internal codec components). All audio components that effect power are called
-widgets hereafter.
-
-
-2. DAPM Widgets
-===============
-
-Audio DAPM widgets fall into a number of types:-
-
- o Mixer      - Mixes several analog signals into a single analog signal.
- o Mux        - An analog switch that outputs only one of many inputs.
- o PGA        - A programmable gain amplifier or attenuation widget.
- o ADC        - Analog to Digital Converter
- o DAC        - Digital to Analog Converter
- o Switch     - An analog switch
- o Input      - A codec input pin
- o Output     - A codec output pin
- o Headphone  - Headphone (and optional Jack)
- o Mic        - Mic (and optional Jack)
- o Line       - Line Input/Output (and optional Jack)
- o Speaker    - Speaker
- o Supply     - Power or clock supply widget used by other widgets.
- o Regulator  - External regulator that supplies power to audio components.
- o Clock      -	External clock that supplies clock to audio components.
- o AIF IN     - Audio Interface Input (with TDM slot mask).
- o AIF OUT    - Audio Interface Output (with TDM slot mask).
- o Siggen     - Signal Generator.
- o DAI IN     - Digital Audio Interface Input.
- o DAI OUT    - Digital Audio Interface Output.
- o DAI Link   - DAI Link between two DAI structures */
- o Pre        - Special PRE widget (exec before all others)
- o Post       - Special POST widget (exec after all others)
-
-(Widgets are defined in include/sound/soc-dapm.h)
-
-Widgets can be added to the sound card by any of the component driver types.
-There are convenience macros defined in soc-dapm.h that can be used to quickly
-build a list of widgets of the codecs and machines DAPM widgets.
-
-Most widgets have a name, register, shift and invert. Some widgets have extra
-parameters for stream name and kcontrols.
-
-
-2.1 Stream Domain Widgets
--------------------------
-
-Stream Widgets relate to the stream power domain and only consist of ADCs
-(analog to digital converters), DACs (digital to analog converters),
-AIF IN and AIF OUT.
-
-Stream widgets have the following format:-
-
-SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
-SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)
-
-NOTE: the stream name must match the corresponding stream name in your codec
-snd_soc_codec_dai.
-
-e.g. stream widgets for HiFi playback and capture
-
-SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
-SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
-
-e.g. stream widgets for AIF
-
-SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-
-
-2.2 Path Domain Widgets
------------------------
-
-Path domain widgets have a ability to control or affect the audio signal or
-audio paths within the audio subsystem. They have the following form:-
-
-SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
-
-Any widget kcontrols can be set using the controls and num_controls members.
-
-e.g. Mixer widget (the kcontrols are declared first)
-
-/* Output Mixer */
-static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
-SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
-SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
-SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
-};
-
-SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
-	ARRAY_SIZE(wm8731_output_mixer_controls)),
-
-If you don't want the mixer elements prefixed with the name of the mixer widget,
-you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
-as for SND_SOC_DAPM_MIXER.
-
-
-2.3 Machine domain Widgets
---------------------------
-
-Machine widgets are different from codec widgets in that they don't have a
-codec register bit associated with them. A machine widget is assigned to each
-machine audio component (non codec or DSP) that can be independently
-powered. e.g.
-
- o Speaker Amp
- o Microphone Bias
- o Jack connectors
-
-A machine widget can have an optional call back.
-
-e.g. Jack connector widget for an external Mic that enables Mic Bias
-when the Mic is inserted:-
-
-static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
-{
-	gpio_set_value(SPITZ_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
-	return 0;
-}
-
-SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
-
-
-2.4 Codec (BIAS) Domain
------------------------
-
-The codec bias power domain has no widgets and is handled by the codecs DAPM
-event handler. This handler is called when the codec powerstate is changed wrt
-to any stream event or by kernel PM events.
-
-
-2.5 Virtual Widgets
--------------------
-
-Sometimes widgets exist in the codec or machine audio map that don't have any
-corresponding soft power control. In this case it is necessary to create
-a virtual widget - a widget with no control bits e.g.
-
-SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
-
-This can be used to merge to signal paths together in software.
-
-After all the widgets have been defined, they can then be added to the DAPM
-subsystem individually with a call to snd_soc_dapm_new_control().
-
-
-3. Codec/DSP Widget Interconnections
-====================================
-
-Widgets are connected to each other within the codec, platform and machine by
-audio paths (called interconnections). Each interconnection must be defined in
-order to create a map of all audio paths between widgets.
-
-This is easiest with a diagram of the codec or DSP (and schematic of the machine
-audio system), as it requires joining widgets together via their audio signal
-paths.
-
-e.g., from the WM8731 output mixer (wm8731.c)
-
-The WM8731 output mixer has 3 inputs (sources)
-
- 1. Line Bypass Input
- 2. DAC (HiFi playback)
- 3. Mic Sidetone Input
-
-Each input in this example has a kcontrol associated with it (defined in example
-above) and is connected to the output mixer via its kcontrol name. We can now
-connect the destination widget (wrt audio signal) with its source widgets.
-
-	/* output mixer */
-	{"Output Mixer", "Line Bypass Switch", "Line Input"},
-	{"Output Mixer", "HiFi Playback Switch", "DAC"},
-	{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
-
-So we have :-
-
-	Destination Widget  <=== Path Name <=== Source Widget
-
-Or:-
-
-	Sink, Path, Source
-
-Or :-
-
-	"Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
-
-When there is no path name connecting widgets (e.g. a direct connection) we
-pass NULL for the path name.
-
-Interconnections are created with a call to:-
-
-snd_soc_dapm_connect_input(codec, sink, path, source);
-
-Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
-interconnections have been registered with the core. This causes the core to
-scan the codec and machine so that the internal DAPM state matches the
-physical state of the machine.
-
-
-3.1 Machine Widget Interconnections
------------------------------------
-Machine widget interconnections are created in the same way as codec ones and
-directly connect the codec pins to machine level widgets.
-
-e.g. connects the speaker out codec pins to the internal speaker.
-
-	/* ext speaker connected to codec pins LOUT2, ROUT2  */
-	{"Ext Spk", NULL , "ROUT2"},
-	{"Ext Spk", NULL , "LOUT2"},
-
-This allows the DAPM to power on and off pins that are connected (and in use)
-and pins that are NC respectively.
-
-
-4 Endpoint Widgets
-===================
-An endpoint is a start or end point (widget) of an audio signal within the
-machine and includes the codec. e.g.
-
- o Headphone Jack
- o Internal Speaker
- o Internal Mic
- o Mic Jack
- o Codec Pins
-
-Endpoints are added to the DAPM graph so that their usage can be determined in
-order to save power. e.g. NC codecs pins will be switched OFF, unconnected
-jacks can also be switched OFF.
-
-
-5 DAPM Widget Events
-====================
-
-Some widgets can register their interest with the DAPM core in PM events.
-e.g. A Speaker with an amplifier registers a widget so the amplifier can be
-powered only when the spk is in use.
-
-/* turn speaker amplifier on/off depending on use */
-static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
-{
-	gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
-	return 0;
-}
-
-/* corgi machine dapm widgets */
-static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
-	SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
-
-Please see soc-dapm.h for all other widgets that support events.
-
-
-5.1 Event types
----------------
-
-The following event types are supported by event widgets.
-
-/* dapm event types */
-#define SND_SOC_DAPM_PRE_PMU	0x1 	/* before widget power up */
-#define SND_SOC_DAPM_POST_PMU	0x2		/* after widget power up */
-#define SND_SOC_DAPM_PRE_PMD	0x4 	/* before widget power down */
-#define SND_SOC_DAPM_POST_PMD	0x8		/* after widget power down */
-#define SND_SOC_DAPM_PRE_REG	0x10	/* before audio path setup */
-#define SND_SOC_DAPM_POST_REG	0x20	/* after audio path setup */
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/DPCM.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/DPCM.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/DPCM.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/DPCM.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,380 +0,0 @@
-Dynamic PCM
-===========
-
-1. Description
-==============
-
-Dynamic PCM allows an ALSA PCM device to digitally route its PCM audio to
-various digital endpoints during the PCM stream runtime. e.g. PCM0 can route
-digital audio to I2S DAI0, I2S DAI1 or PDM DAI2. This is useful for on SoC DSP
-drivers that expose several ALSA PCMs and can route to multiple DAIs.
-
-The DPCM runtime routing is determined by the ALSA mixer settings in the same
-way as the analog signal is routed in an ASoC codec driver. DPCM uses a DAPM
-graph representing the DSP internal audio paths and uses the mixer settings to
-determine the patch used by each ALSA PCM.
-
-DPCM re-uses all the existing component codec, platform and DAI drivers without
-any modifications.
-
-
-Phone Audio System with SoC based DSP
--------------------------------------
-
-Consider the following phone audio subsystem. This will be used in this
-document for all examples :-
-
-| Front End PCMs    |  SoC DSP  | Back End DAIs | Audio devices |
-
-                    *************
-PCM0 <------------> *           * <----DAI0-----> Codec Headset
-                    *           *
-PCM1 <------------> *           * <----DAI1-----> Codec Speakers
-                    *   DSP     *
-PCM2 <------------> *           * <----DAI2-----> MODEM
-                    *           *
-PCM3 <------------> *           * <----DAI3-----> BT
-                    *           *
-                    *           * <----DAI4-----> DMIC
-                    *           *
-                    *           * <----DAI5-----> FM
-                    *************
-
-This diagram shows a simple smart phone audio subsystem. It supports Bluetooth,
-FM digital radio, Speakers, Headset Jack, digital microphones and cellular
-modem. This sound card exposes 4 DSP front end (FE) ALSA PCM devices and
-supports 6 back end (BE) DAIs. Each FE PCM can digitally route audio data to any
-of the BE DAIs. The FE PCM devices can also route audio to more than 1 BE DAI.
-
-
-
-Example - DPCM Switching playback from DAI0 to DAI1
----------------------------------------------------
-
-Audio is being played to the Headset. After a while the user removes the headset
-and audio continues playing on the speakers.
-
-Playback on PCM0 to Headset would look like :-
-
-                    *************
-PCM0 <============> *           * <====DAI0=====> Codec Headset
-                    *           *
-PCM1 <------------> *           * <----DAI1-----> Codec Speakers
-                    *   DSP     *
-PCM2 <------------> *           * <----DAI2-----> MODEM
-                    *           *
-PCM3 <------------> *           * <----DAI3-----> BT
-                    *           *
-                    *           * <----DAI4-----> DMIC
-                    *           *
-                    *           * <----DAI5-----> FM
-                    *************
-
-The headset is removed from the jack by user so the speakers must now be used :-
-
-                    *************
-PCM0 <============> *           * <----DAI0-----> Codec Headset
-                    *           *
-PCM1 <------------> *           * <====DAI1=====> Codec Speakers
-                    *   DSP     *
-PCM2 <------------> *           * <----DAI2-----> MODEM
-                    *           *
-PCM3 <------------> *           * <----DAI3-----> BT
-                    *           *
-                    *           * <----DAI4-----> DMIC
-                    *           *
-                    *           * <----DAI5-----> FM
-                    *************
-
-The audio driver processes this as follows :-
-
- 1) Machine driver receives Jack removal event.
-
- 2) Machine driver OR audio HAL disables the Headset path.
-
- 3) DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
-    for headset since the path is now disabled.
-
- 4) Machine driver or audio HAL enables the speaker path.
-
- 5) DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
-    trigger(start) for DAI1 Speakers since the path is enabled.
-
-In this example, the machine driver or userspace audio HAL can alter the routing
-and then DPCM will take care of managing the DAI PCM operations to either bring
-the link up or down. Audio playback does not stop during this transition.
-
-
-
-DPCM machine driver
-===================
-
-The DPCM enabled ASoC machine driver is similar to normal machine drivers
-except that we also have to :-
-
- 1) Define the FE and BE DAI links.
-
- 2) Define any FE/BE PCM operations.
-
- 3) Define widget graph connections.
-
-
-1 FE and BE DAI links
----------------------
-
-| Front End PCMs    |  SoC DSP  | Back End DAIs | Audio devices |
-
-                    *************
-PCM0 <------------> *           * <----DAI0-----> Codec Headset
-                    *           *
-PCM1 <------------> *           * <----DAI1-----> Codec Speakers
-                    *   DSP     *
-PCM2 <------------> *           * <----DAI2-----> MODEM
-                    *           *
-PCM3 <------------> *           * <----DAI3-----> BT
-                    *           *
-                    *           * <----DAI4-----> DMIC
-                    *           *
-                    *           * <----DAI5-----> FM
-                    *************
-
-For the example above we have to define 4 FE DAI links and 6 BE DAI links. The
-FE DAI links are defined as follows :-
-
-static struct snd_soc_dai_link machine_dais[] = {
-	{
-		.name = "PCM0 System",
-		.stream_name = "System Playback",
-		.cpu_dai_name = "System Pin",
-		.platform_name = "dsp-audio",
-		.codec_name = "snd-soc-dummy",
-		.codec_dai_name = "snd-soc-dummy-dai",
-		.dynamic = 1,
-		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
-		.dpcm_playback = 1,
-	},
-	.....< other FE and BE DAI links here >
-};
-
-This FE DAI link is pretty similar to a regular DAI link except that we also
-set the DAI link to a DPCM FE with the "dynamic = 1". The supported FE stream
-directions should also be set with the "dpcm_playback" and "dpcm_capture"
-flags. There is also an option to specify the ordering of the trigger call for
-each FE. This allows the ASoC core to trigger the DSP before or after the other
-components (as some DSPs have strong requirements for the ordering DAI/DSP
-start and stop sequences).
-
-The FE DAI above sets the codec and code DAIs to dummy devices since the BE is
-dynamic and will change depending on runtime config.
-
-The BE DAIs are configured as follows :-
-
-static struct snd_soc_dai_link machine_dais[] = {
-	.....< FE DAI links here >
-	{
-		.name = "Codec Headset",
-		.cpu_dai_name = "ssp-dai.0",
-		.platform_name = "snd-soc-dummy",
-		.no_pcm = 1,
-		.codec_name = "rt5640.0-001c",
-		.codec_dai_name = "rt5640-aif1",
-		.ignore_suspend = 1,
-		.ignore_pmdown_time = 1,
-		.be_hw_params_fixup = hswult_ssp0_fixup,
-		.ops = &haswell_ops,
-		.dpcm_playback = 1,
-		.dpcm_capture = 1,
-	},
-	.....< other BE DAI links here >
-};
-
-This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets
-the "no_pcm" flag to mark it has a BE and sets flags for supported stream
-directions using "dpcm_playback" and "dpcm_capture" above.
-
-The BE has also flags set for ignoring suspend and PM down time. This allows
-the BE to work in a hostless mode where the host CPU is not transferring data
-like a BT phone call :-
-
-                    *************
-PCM0 <------------> *           * <----DAI0-----> Codec Headset
-                    *           *
-PCM1 <------------> *           * <----DAI1-----> Codec Speakers
-                    *   DSP     *
-PCM2 <------------> *           * <====DAI2=====> MODEM
-                    *           *
-PCM3 <------------> *           * <====DAI3=====> BT
-                    *           *
-                    *           * <----DAI4-----> DMIC
-                    *           *
-                    *           * <----DAI5-----> FM
-                    *************
-
-This allows the host CPU to sleep whilst the DSP, MODEM DAI and the BT DAI are
-still in operation.
-
-A BE DAI link can also set the codec to a dummy device if the code is a device
-that is managed externally.
-
-Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the
-DSP firmware.
-
-
-2 FE/BE PCM operations
-----------------------
-
-The BE above also exports some PCM operations and a "fixup" callback. The fixup
-callback is used by the machine driver to (re)configure the DAI based upon the
-FE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE.
-
-e.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo for
-DAI0. This means all FE hw_params have to be fixed in the machine driver for
-DAI0 so that the DAI is running at desired configuration regardless of the FE
-configuration.
-
-static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
-			struct snd_pcm_hw_params *params)
-{
-	struct snd_interval *rate = hw_param_interval(params,
-			SNDRV_PCM_HW_PARAM_RATE);
-	struct snd_interval *channels = hw_param_interval(params,
-						SNDRV_PCM_HW_PARAM_CHANNELS);
-
-	/* The DSP will covert the FE rate to 48k, stereo */
-	rate->min = rate->max = 48000;
-	channels->min = channels->max = 2;
-
-	/* set DAI0 to 16 bit */
-	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
-				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
-				    SNDRV_PCM_FORMAT_S16_LE);
-	return 0;
-}
-
-The other PCM operation are the same as for regular DAI links. Use as necessary.
-
-
-3 Widget graph connections
---------------------------
-
-The BE DAI links will normally be connected to the graph at initialisation time
-by the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this
-has to be set explicitly in the driver :-
-
-/* BE for codec Headset -  DAI0 is dummy and managed by DSP FW */
-{"DAI0 CODEC IN", NULL, "AIF1 Capture"},
-{"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
-
-
-Writing a DPCM DSP driver
-=========================
-
-The DPCM DSP driver looks much like a standard platform class ASoC driver
-combined with elements from a codec class driver. A DSP platform driver must
-implement :-
-
- 1) Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
-
- 2) DAPM graph showing DSP audio routing from FE DAIs to BEs.
-
- 3) DAPM widgets from DSP graph.
-
- 4) Mixers for gains, routing, etc.
-
- 5) DMA configuration.
-
- 6) BE AIF widgets.
-
-Items 6 is important for routing the audio outside of the DSP. AIF need to be
-defined for each BE and each stream direction. e.g for BE DAI0 above we would
-have :-
-
-SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
-
-The BE AIF are used to connect the DSP graph to the graphs for the other
-component drivers (e.g. codec graph).
-
-
-Hostless PCM streams
-====================
-
-A hostless PCM stream is a stream that is not routed through the host CPU. An
-example of this would be a phone call from handset to modem.
-
-
-                    *************
-PCM0 <------------> *           * <----DAI0-----> Codec Headset
-                    *           *
-PCM1 <------------> *           * <====DAI1=====> Codec Speakers/Mic
-                    *   DSP     *
-PCM2 <------------> *           * <====DAI2=====> MODEM
-                    *           *
-PCM3 <------------> *           * <----DAI3-----> BT
-                    *           *
-                    *           * <----DAI4-----> DMIC
-                    *           *
-                    *           * <----DAI5-----> FM
-                    *************
-
-In this case the PCM data is routed via the DSP. The host CPU in this use case
-is only used for control and can sleep during the runtime of the stream.
-
-The host can control the hostless link either by :-
-
- 1) Configuring the link as a CODEC <-> CODEC style link. In this case the link
-    is enabled or disabled by the state of the DAPM graph. This usually means
-    there is a mixer control that can be used to connect or disconnect the path
-    between both DAIs.
-
- 2) Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
-    graph. Control is then carried out by the FE as regular PCM operations.
-    This method gives more control over the DAI links, but requires much more
-    userspace code to control the link. Its recommended to use CODEC<->CODEC
-    unless your HW needs more fine grained sequencing of the PCM ops.
-
-
-CODEC <-> CODEC link
---------------------
-
-This DAI link is enabled when DAPM detects a valid path within the DAPM graph.
-The machine driver sets some additional parameters to the DAI link i.e.
-
-static const struct snd_soc_pcm_stream dai_params = {
-	.formats = SNDRV_PCM_FMTBIT_S32_LE,
-	.rate_min = 8000,
-	.rate_max = 8000,
-	.channels_min = 2,
-	.channels_max = 2,
-};
-
-static struct snd_soc_dai_link dais[] = {
-	< ... more DAI links above ... >
-	{
-		.name = "MODEM",
-		.stream_name = "MODEM",
-		.cpu_dai_name = "dai2",
-		.codec_dai_name = "modem-aif1",
-		.codec_name = "modem",
-		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-				| SND_SOC_DAIFMT_CBM_CFM,
-		.params = &dai_params,
-	}
-	< ... more DAI links here ... >
-
-These parameters are used to configure the DAI hw_params() when DAPM detects a
-valid path and then calls the PCM operations to start the link. DAPM will also
-call the appropriate PCM operations to disable the DAI when the path is no
-longer valid.
-
-
-Hostless FE
------------
-
-The DAI link(s) are enabled by a FE that does not read or write any PCM data.
-This means creating a new FE that is connected with a virtual path to both
-DAI links. The DAI links will be started when the FE PCM is started and stopped
-when the FE PCM is stopped. Note that the FE PCM cannot read or write data in
-this configuration.
-
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/jack.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/jack.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/jack.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/jack.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-ASoC jack detection
-===================
-
-ALSA has a standard API for representing physical jacks to user space,
-the kernel side of which can be seen in include/sound/jack.h.  ASoC
-provides a version of this API adding two additional features:
-
- - It allows more than one jack detection method to work together on one
-   user visible jack.  In embedded systems it is common for multiple
-   to be present on a single jack but handled by separate bits of
-   hardware.
-
- - Integration with DAPM, allowing DAPM endpoints to be updated
-   automatically based on the detected jack status (eg, turning off the
-   headphone outputs if no headphones are present).
-
-This is done by splitting the jacks up into three things working
-together: the jack itself represented by a struct snd_soc_jack, sets of
-snd_soc_jack_pins representing DAPM endpoints to update and blocks of
-code providing jack reporting mechanisms.
-
-For example, a system may have a stereo headset jack with two reporting
-mechanisms, one for the headphone and one for the microphone.  Some
-systems won't be able to use their speaker output while a headphone is
-connected and so will want to make sure to update both speaker and
-headphone when the headphone jack status changes.
-
-The jack - struct snd_soc_jack
-==============================
-
-This represents a physical jack on the system and is what is visible to
-user space.  The jack itself is completely passive, it is set up by the
-machine driver and updated by jack detection methods.
-
-Jacks are created by the machine driver calling snd_soc_jack_new().
-
-snd_soc_jack_pin
-================
-
-These represent a DAPM pin to update depending on some of the status
-bits supported by the jack.  Each snd_soc_jack has zero or more of these
-which are updated automatically.  They are created by the machine driver
-and associated with the jack using snd_soc_jack_add_pins().  The status
-of the endpoint may configured to be the opposite of the jack status if
-required (eg, enabling a built in microphone if a microphone is not
-connected via a jack).
-
-Jack detection methods
-======================
-
-Actual jack detection is done by code which is able to monitor some
-input to the system and update a jack by calling snd_soc_jack_report(),
-specifying a subset of bits to update.  The jack detection code should
-be set up by the machine driver, taking configuration for the jack to
-update and the set of things to report when the jack is connected.
-
-Often this is done based on the status of a GPIO - a handler for this is
-provided by the snd_soc_jack_add_gpio() function.  Other methods are
-also available, for example integrated into CODECs.  One example of
-CODEC integrated jack detection can be see in the WM8350 driver.
-
-Each jack may have multiple reporting mechanisms, though it will need at
-least one to be useful.
-
-Machine drivers
-===============
-
-These are all hooked together by the machine driver depending on the
-system hardware.  The machine driver will set up the snd_soc_jack and
-the list of pins to update then set up one or more jack detection
-mechanisms to update that jack based on their current status.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/machine.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/machine.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/machine.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/machine.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-ASoC Machine Driver
-===================
-
-The ASoC machine (or board) driver is the code that glues together all the
-component drivers (e.g. codecs, platforms and DAIs). It also describes the
-relationships between each component which include audio paths, GPIOs,
-interrupts, clocking, jacks and voltage regulators.
-
-The machine driver can contain codec and platform specific code. It registers
-the audio subsystem with the kernel as a platform device and is represented by
-the following struct:-
-
-/* SoC machine */
-struct snd_soc_card {
-	char *name;
-
-	...
-
-	int (*probe)(struct platform_device *pdev);
-	int (*remove)(struct platform_device *pdev);
-
-	/* the pre and post PM functions are used to do any PM work before and
-	 * after the codec and DAIs do any PM work. */
-	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
-	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
-	int (*resume_pre)(struct platform_device *pdev);
-	int (*resume_post)(struct platform_device *pdev);
-
-	...
-
-	/* CPU <--> Codec DAI links  */
-	struct snd_soc_dai_link *dai_link;
-	int num_links;
-
-	...
-};
-
-probe()/remove()
-----------------
-probe/remove are optional. Do any machine specific probe here.
-
-
-suspend()/resume()
-------------------
-The machine driver has pre and post versions of suspend and resume to take care
-of any machine audio tasks that have to be done before or after the codec, DAIs
-and DMA is suspended and resumed. Optional.
-
-
-Machine DAI Configuration
--------------------------
-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.
-
-struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
-
-/* corgi digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link corgi_dai = {
-	.name = "WM8731",
-	.stream_name = "WM8731",
-	.cpu_dai_name = "pxa-is2-dai",
-	.codec_dai_name = "wm8731-hifi",
-	.platform_name = "pxa-pcm-audio",
-	.codec_name = "wm8713-codec.0-001a",
-	.init = corgi_wm8731_init,
-	.ops = &corgi_ops,
-};
-
-struct snd_soc_card then sets up the machine with its DAIs. e.g.
-
-/* corgi audio machine driver */
-static struct snd_soc_card snd_soc_corgi = {
-	.name = "Corgi",
-	.dai_link = &corgi_dai,
-	.num_links = 1,
-};
-
-
-Machine Power Map
------------------
-
-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.
-
-
-Machine Controls
-----------------
-
-Machine specific audio mixer controls can be added in the DAI init function.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/overview.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/overview.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/overview.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/overview.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,95 +0,0 @@
-ALSA SoC Layer
-==============
-
-The overall project goal of the ALSA System on Chip (ASoC) layer is to
-provide better ALSA support for embedded system-on-chip processors (e.g.
-pxa2xx, au1x00, iMX, etc) and portable audio codecs.  Prior to the ASoC
-subsystem there was some support in the kernel for SoC audio, however it
-had some limitations:-
-
-  * Codec drivers were often tightly coupled to the underlying SoC
-    CPU. This is not ideal and leads to code duplication - for example,
-    Linux had different wm8731 drivers for 4 different SoC platforms.
-
-  * There was no standard method to signal user initiated audio events (e.g.
-    Headphone/Mic insertion, Headphone/Mic detection after an insertion
-    event). These are quite common events on portable devices and often require
-    machine specific code to re-route audio, enable amps, etc., after such an
-    event.
-
-  * Drivers tended to power up the entire codec when playing (or
-    recording) audio. This is fine for a PC, but tends to waste a lot of
-    power on portable devices. There was also no support for saving
-    power via changing codec oversampling rates, bias currents, etc.
-
-
-ASoC Design
-===========
-
-The ASoC layer is designed to address these issues and provide the following
-features :-
-
-  * Codec independence. Allows reuse of codec drivers on other platforms
-    and machines.
-
-  * Easy I2S/PCM audio interface setup between codec and SoC. Each SoC
-    interface and codec registers its audio interface capabilities with the
-    core and are subsequently matched and configured when the application
-    hardware parameters are known.
-
-  * Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
-    its minimum power state at all times. This includes powering up/down
-    internal power blocks depending on the internal codec audio routing and any
-    active streams.
-
-  * Pop and click reduction. Pops and clicks can be reduced by powering the
-    codec up/down in the correct sequence (including using digital mute). ASoC
-    signals the codec when to change power states.
-
-  * Machine specific controls: Allow machines to add controls to the sound card
-    (e.g. volume control for speaker amplifier).
-
-To achieve all this, ASoC basically splits an embedded audio system into
-multiple re-usable component drivers :-
-
-  * Codec class drivers: The codec class driver is platform independent and
-    contains audio controls, audio interface capabilities, codec DAPM
-    definition and codec IO functions. This class extends to BT, FM and MODEM
-    ICs if required. Codec class drivers should be generic code that can run
-    on any architecture and machine.
-
-  * Platform class drivers: The platform class driver includes the audio DMA
-    engine driver, digital audio interface (DAI) drivers (e.g. I2S, AC97, PCM)
-    and any audio DSP drivers for that platform.
-
-  * Machine class driver: The machine driver class acts as the glue that
-    describes and binds the other component drivers together to form an ALSA
-    "sound card device". It handles any machine specific controls and
-    machine level audio events (e.g. turning on an amp at start of playback).
-
-
-Documentation
-=============
-
-The documentation is spilt into the following sections:-
-
-overview.txt: This file.
-
-codec.txt: Codec driver internals.
-
-DAI.txt: Description of Digital Audio Interface standards and how to configure
-a DAI within your codec and CPU DAI drivers.
-
-dapm.txt: Dynamic Audio Power Management
-
-platform.txt: Platform audio DMA and DAI.
-
-machine.txt: Machine driver internals.
-
-pop_clicks.txt: How to minimise audio artifacts.
-
-clocking.txt: ASoC clocking for best power performance.
-
-jack.txt: ASoC jack detection.
-
-DPCM.txt: Dynamic PCM - Describes DPCM with DSP examples.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/platform.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/platform.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/platform.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/platform.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-ASoC Platform Driver
-====================
-
-An ASoC platform driver class can be divided into audio DMA drivers, SoC DAI
-drivers and DSP drivers. The platform drivers only target the SoC CPU and must
-have no board specific code.
-
-Audio DMA
-=========
-
-The platform DMA driver optionally supports the following ALSA operations:-
-
-/* SoC audio ops */
-struct snd_soc_ops {
-	int (*startup)(struct snd_pcm_substream *);
-	void (*shutdown)(struct snd_pcm_substream *);
-	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
-	int (*hw_free)(struct snd_pcm_substream *);
-	int (*prepare)(struct snd_pcm_substream *);
-	int (*trigger)(struct snd_pcm_substream *, int);
-};
-
-The platform driver exports its DMA functionality via struct
-snd_soc_platform_driver:-
-
-struct snd_soc_platform_driver {
-	char *name;
-
-	int (*probe)(struct platform_device *pdev);
-	int (*remove)(struct platform_device *pdev);
-	int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
-	int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
-
-	/* pcm creation and destruction */
-	int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
-	void (*pcm_free)(struct snd_pcm *);
-
-	/*
-	 * For platform caused delay reporting.
-	 * Optional.
-	 */
-	snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
-		struct snd_soc_dai *);
-
-	/* platform stream ops */
-	struct snd_pcm_ops *pcm_ops;
-};
-
-Please refer to the ALSA driver documentation for details of audio DMA.
-http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
-
-An example DMA driver is soc/pxa/pxa2xx-pcm.c
-
-
-SoC DAI Drivers
-===============
-
-Each SoC DAI driver must provide the following features:-
-
- 1) Digital audio interface (DAI) description
- 2) Digital audio interface configuration
- 3) PCM's description
- 4) SYSCLK configuration
- 5) Suspend and resume (optional)
-
-Please see codec.txt for a description of items 1 - 4.
-
-
-SoC DSP Drivers
-===============
-
-Each SoC DSP driver usually supplies the following features :-
-
- 1) DAPM graph
- 2) Mixer controls
- 3) DMA IO to/from DSP buffers (if applicable)
- 4) Definition of DSP front end (FE) PCM devices.
-
-Please see DPCM.txt for a description of item 4.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/soc/pops_clicks.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/pops_clicks.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/soc/pops_clicks.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/soc/pops_clicks.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-Audio Pops and Clicks
-=====================
-
-Pops and clicks are unwanted audio artifacts caused by the powering up and down
-of components within the audio subsystem. This is noticeable on PCs when an
-audio module is either loaded or unloaded (at module load time the sound card is
-powered up and causes a popping noise on the speakers).
-
-Pops and clicks can be more frequent on portable systems with DAPM. This is
-because the components within the subsystem are being dynamically powered
-depending on the audio usage and this can subsequently cause a small pop or
-click every time a component power state is changed.
-
-
-Minimising Playback Pops and Clicks
-===================================
-
-Playback pops in portable audio subsystems cannot be completely eliminated
-currently, however future audio codec hardware will have better pop and click
-suppression.  Pops can be reduced within playback by powering the audio
-components in a specific order. This order is different for startup and
-shutdown and follows some basic rules:-
-
- Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
-
- Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
-
-This assumes that the codec PCM output path from the DAC is via a mixer and then
-a PGA (programmable gain amplifier) before being output to the speakers.
-
-
-Minimising Capture Pops and Clicks
-==================================
-
-Capture artifacts are somewhat easier to get rid as we can delay activating the
-ADC until all the pops have occurred. This follows similar power rules to
-playback in that components are powered in a sequence depending upon stream
-startup or shutdown.
-
- Startup Order - Input PGA --> Mixers --> ADC
-
- Shutdown Order - ADC --> Mixers --> Input PGA
-
-
-Zipper Noise
-============
-An unwanted zipper noise can occur within the audio playback or capture stream
-when a volume control is changed near its maximum gain value. The zipper noise
-is heard when the gain increase or decrease changes the mean audio signal
-amplitude too quickly. It can be minimised by enabling the zero cross setting
-for each volume control. The ZC forces the gain change to occur when the signal
-crosses the zero amplitude line.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/timestamping.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/timestamping.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/timestamping.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/timestamping.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,200 +0,0 @@
-The ALSA API can provide two different system timestamps:
-
-- Trigger_tstamp is the system time snapshot taken when the .trigger
-callback is invoked. This snapshot is taken by the ALSA core in the
-general case, but specific hardware may have synchronization
-capabilities or conversely may only be able to provide a correct
-estimate with a delay. In the latter two cases, the low-level driver
-is responsible for updating the trigger_tstamp at the most appropriate
-and precise moment. Applications should not rely solely on the first
-trigger_tstamp but update their internal calculations if the driver
-provides a refined estimate with a delay.
-
-- tstamp is the current system timestamp updated during the last
-event or application query.
-The difference (tstamp - trigger_tstamp) defines the elapsed time.
-
-The ALSA API provides two basic pieces of information, avail
-and delay, which combined with the trigger and current system
-timestamps allow for applications to keep track of the 'fullness' of
-the ring buffer and the amount of queued samples.
-
-The use of these different pointers and time information depends on
-the application needs:
-
-- 'avail' reports how much can be written in the ring buffer
-- 'delay' reports the time it will take to hear a new sample after all
-queued samples have been played out.
-
-When timestamps are enabled, the avail/delay information is reported
-along with a snapshot of system time. Applications can select from
-CLOCK_REALTIME (NTP corrections including going backwards),
-CLOCK_MONOTONIC (NTP corrections but never going backwards),
-CLOCK_MONOTIC_RAW (without NTP corrections) and change the mode
-dynamically with sw_params
-
-
-The ALSA API also provide an audio_tstamp which reflects the passage
-of time as measured by different components of audio hardware.  In
-ascii-art, this could be represented as follows (for the playback
-case):
-
-
---------------------------------------------------------------> time
-  ^               ^              ^                ^           ^
-  |               |              |                |           |
- analog         link            dma              app       FullBuffer
- time           time           time              time        time
-  |               |              |                |           |
-  |< codec delay >|<--hw delay-->|<queued samples>|<---avail->|
-  |<----------------- delay---------------------->|           |
-			         |<----ring buffer length---->|
-
-The analog time is taken at the last stage of the playback, as close
-as possible to the actual transducer
-
-The link time is taken at the output of the SoC/chipset as the samples
-are pushed on a link. The link time can be directly measured if
-supported in hardware by sample counters or wallclocks (e.g. with
-HDAudio 24MHz or PTP clock for networked solutions) or indirectly
-estimated (e.g. with the frame counter in USB).
-
-The DMA time is measured using counters - typically the least reliable
-of all measurements due to the bursty nature of DMA transfers.
-
-The app time corresponds to the time tracked by an application after
-writing in the ring buffer.
-
-The application can query the hardware capabilities, define which
-audio time it wants reported by selecting the relevant settings in
-audio_tstamp_config fields, thus get an estimate of the timestamp
-accuracy. It can also request the delay-to-analog be included in the
-measurement. Direct access to the link time is very interesting on
-platforms that provide an embedded DSP; measuring directly the link
-time with dedicated hardware, possibly synchronized with system time,
-removes the need to keep track of internal DSP processing times and
-latency.
-
-In case the application requests an audio tstamp that is not supported
-in hardware/low-level driver, the type is overridden as DEFAULT and the
-timestamp will report the DMA time based on the hw_pointer value.
-
-For backwards compatibility with previous implementations that did not
-provide timestamp selection, with a zero-valued COMPAT timestamp type
-the results will default to the HDAudio wall clock for playback
-streams and to the DMA time (hw_ptr) in all other cases.
-
-The audio timestamp accuracy can be returned to user-space, so that
-appropriate decisions are made:
-
-- for dma time (default), the granularity of the transfers can be
-  inferred from the steps between updates and in turn provide
-  information on how much the application pointer can be rewound
-  safely.
-
-- the link time can be used to track long-term drifts between audio
-  and system time using the (tstamp-trigger_tstamp)/audio_tstamp
-  ratio, the precision helps define how much smoothing/low-pass
-  filtering is required. The link time can be either reset on startup
-  or reported as is (the latter being useful to compare progress of
-  different streams - but may require the wallclock to be always
-  running and not wrap-around during idle periods). If supported in
-  hardware, the absolute link time could also be used to define a
-  precise start time (patches WIP)
-
-- including the delay in the audio timestamp may
-  counter-intuitively not increase the precision of timestamps, e.g. if a
-  codec includes variable-latency DSP processing or a chain of
-  hardware components the delay is typically not known with precision.
-
-The accuracy is reported in nanosecond units (using an unsigned 32-bit
-word), which gives a max precision of 4.29s, more than enough for
-audio applications...
-
-Due to the varied nature of timestamping needs, even for a single
-application, the audio_tstamp_config can be changed dynamically. In
-the STATUS ioctl, the parameters are read-only and do not allow for
-any application selection. To work around this limitation without
-impacting legacy applications, a new STATUS_EXT ioctl is introduced
-with read/write parameters. ALSA-lib will be modified to make use of
-STATUS_EXT and effectively deprecate STATUS.
-
-The ALSA API only allows for a single audio timestamp to be reported
-at a time. This is a conscious design decision, reading the audio
-timestamps from hardware registers or from IPC takes time, the more
-timestamps are read the more imprecise the combined measurements
-are. To avoid any interpretation issues, a single (system, audio)
-timestamp is reported. Applications that need different timestamps
-will be required to issue multiple queries and perform an
-interpolation of the results
-
-In some hardware-specific configuration, the system timestamp is
-latched by a low-level audio subsystem, and the information provided
-back to the driver. Due to potential delays in the communication with
-the hardware, there is a risk of misalignment with the avail and delay
-information. To make sure applications are not confused, a
-driver_timestamp field is added in the snd_pcm_status structure; this
-timestamp shows when the information is put together by the driver
-before returning from the STATUS and STATUS_EXT ioctl. in most cases
-this driver_timestamp will be identical to the regular system tstamp.
-
-Examples of typestamping with HDaudio:
-
-1. DMA timestamp, no compensation for DMA+analog delay
-$ ./audio_time  -p --ts_type=1
-playback: systime: 341121338 nsec, audio time 342000000 nsec, 	systime delta -878662
-playback: systime: 426236663 nsec, audio time 427187500 nsec, 	systime delta -950837
-playback: systime: 597080580 nsec, audio time 598000000 nsec, 	systime delta -919420
-playback: systime: 682059782 nsec, audio time 683020833 nsec, 	systime delta -961051
-playback: systime: 852896415 nsec, audio time 853854166 nsec, 	systime delta -957751
-playback: systime: 937903344 nsec, audio time 938854166 nsec, 	systime delta -950822
-
-2. DMA timestamp, compensation for DMA+analog delay
-$ ./audio_time  -p --ts_type=1 -d
-playback: systime: 341053347 nsec, audio time 341062500 nsec, 	systime delta -9153
-playback: systime: 426072447 nsec, audio time 426062500 nsec, 	systime delta 9947
-playback: systime: 596899518 nsec, audio time 596895833 nsec, 	systime delta 3685
-playback: systime: 681915317 nsec, audio time 681916666 nsec, 	systime delta -1349
-playback: systime: 852741306 nsec, audio time 852750000 nsec, 	systime delta -8694
-
-3. link timestamp, compensation for DMA+analog delay
-$ ./audio_time  -p --ts_type=2 -d
-playback: systime: 341060004 nsec, audio time 341062791 nsec, 	systime delta -2787
-playback: systime: 426242074 nsec, audio time 426244875 nsec, 	systime delta -2801
-playback: systime: 597080992 nsec, audio time 597084583 nsec, 	systime delta -3591
-playback: systime: 682084512 nsec, audio time 682088291 nsec, 	systime delta -3779
-playback: systime: 852936229 nsec, audio time 852940916 nsec, 	systime delta -4687
-playback: systime: 938107562 nsec, audio time 938112708 nsec, 	systime delta -5146
-
-Example 1 shows that the timestamp at the DMA level is close to 1ms
-ahead of the actual playback time (as a side time this sort of
-measurement can help define rewind safeguards). Compensating for the
-DMA-link delay in example 2 helps remove the hardware buffering but
-the information is still very jittery, with up to one sample of
-error. In example 3 where the timestamps are measured with the link
-wallclock, the timestamps show a monotonic behavior and a lower
-dispersion.
-
-Example 3 and 4 are with USB audio class. Example 3 shows a high
-offset between audio time and system time due to buffering. Example 4
-shows how compensating for the delay exposes a 1ms accuracy (due to
-the use of the frame counter by the driver)
-
-Example 3: DMA timestamp, no compensation for delay, delta of ~5ms
-$ ./audio_time -p -Dhw:1 -t1
-playback: systime: 120174019 nsec, audio time 125000000 nsec, 	systime delta -4825981
-playback: systime: 245041136 nsec, audio time 250000000 nsec, 	systime delta -4958864
-playback: systime: 370106088 nsec, audio time 375000000 nsec, 	systime delta -4893912
-playback: systime: 495040065 nsec, audio time 500000000 nsec, 	systime delta -4959935
-playback: systime: 620038179 nsec, audio time 625000000 nsec, 	systime delta -4961821
-playback: systime: 745087741 nsec, audio time 750000000 nsec, 	systime delta -4912259
-playback: systime: 870037336 nsec, audio time 875000000 nsec, 	systime delta -4962664
-
-Example 4: DMA timestamp, compensation for delay, delay of ~1ms
-$ ./audio_time -p -Dhw:1 -t1 -d
-playback: systime: 120190520 nsec, audio time 120000000 nsec, 	systime delta 190520
-playback: systime: 245036740 nsec, audio time 244000000 nsec, 	systime delta 1036740
-playback: systime: 370034081 nsec, audio time 369000000 nsec, 	systime delta 1034081
-playback: systime: 495159907 nsec, audio time 494000000 nsec, 	systime delta 1159907
-playback: systime: 620098824 nsec, audio time 619000000 nsec, 	systime delta 1098824
-playback: systime: 745031847 nsec, audio time 744000000 nsec, 	systime delta 1031847
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa/VIA82xx-mixer.txt linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/VIA82xx-mixer.txt
--- linux-libre-4.9-gnu/Documentation/sound/alsa/VIA82xx-mixer.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa/VIA82xx-mixer.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-
-				VIA82xx mixer
-				=============
-
-On many VIA82xx boards, the 'Input Source Select' mixer control does not work.
-Setting it to 'Input2' on such boards will cause recording to hang, or fail
-with EIO (input/output error) via OSS emulation.  This control should be left
-at 'Input1' for such cards.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/alsa-configuration.rst linux-libre-4.10-rc8-gnu/Documentation/sound/alsa-configuration.rst
--- linux-libre-4.9-gnu/Documentation/sound/alsa-configuration.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/alsa-configuration.rst	2017-02-12 17:57:52.000000000 -0500
@@ -0,0 +1,2683 @@
+==============================================================
+Advanced Linux Sound Architecture - Driver Configuration guide
+==============================================================
+
+
+Kernel Configuration
+====================
+
+To enable ALSA support you need at least to build the kernel with
+primary sound card support (``CONFIG_SOUND``).  Since ALSA can emulate
+OSS, you don't have to choose any of the OSS modules.
+
+Enable "OSS API emulation" (``CONFIG_SND_OSSEMUL``) and both OSS mixer
+and PCM supports if you want to run OSS applications with ALSA.
+
+If you want to support the WaveTable functionality on cards such as
+SB Live! then you need to enable "Sequencer support"
+(``CONFIG_SND_SEQUENCER``).
+
+To make ALSA debug messages more verbose, enable the "Verbose printk"
+and "Debug" options.  To check for memory leaks, turn on "Debug memory"
+too.  "Debug detection" will add checks for the detection of cards.
+
+Please note that all the ALSA ISA drivers support the Linux isapnp API
+(if the card supports ISA PnP).  You don't need to configure the cards
+using isapnptools.
+
+
+Module parameters
+=================
+
+The user can load modules with options. If the module supports more than
+one card and you have more than one card of the same type then you can
+specify multiple values for the option separated by commas.
+
+
+Module snd
+----------
+
+The core ALSA module.  It is used by all ALSA card drivers.
+It takes the following options which have global effects.
+
+major
+    major number for sound driver;
+    Default: 116
+cards_limit
+    limiting card index for auto-loading (1-8);
+    Default: 1;
+    For auto-loading more than one card, specify this option
+    together with snd-card-X aliases.
+slots
+    Reserve the slot index for the given driver;
+    This option takes multiple strings.
+    See `Module Autoloading Support`_ section for details.
+debug
+    Specifies the debug message level;
+    (0 = disable debug prints, 1 = normal debug messages,
+    2 = verbose debug messages);
+    This option appears only when ``CONFIG_SND_DEBUG=y``.
+    This option can be dynamically changed via sysfs
+    /sys/modules/snd/parameters/debug file.
+  
+Module snd-pcm-oss
+------------------
+
+The PCM OSS emulation module.
+This module takes options which change the mapping of devices.
+
+dsp_map
+    PCM device number maps assigned to the 1st OSS device;
+    Default: 0
+adsp_map
+    PCM device number maps assigned to the 2st OSS device;
+    Default: 1
+nonblock_open
+    Don't block opening busy PCM devices;
+    Default: 1
+
+For example, when ``dsp_map=2``, /dev/dsp will be mapped to PCM #2 of
+the card #0.  Similarly, when ``adsp_map=0``, /dev/adsp will be mapped
+to PCM #0 of the card #0.
+For changing the second or later card, specify the option with
+commas, such like ``dsp_map=0,1``.
+
+``nonblock_open`` option is used to change the behavior of the PCM
+regarding opening the device.  When this option is non-zero,
+opening a busy OSS PCM device won't be blocked but return
+immediately with EAGAIN (just like O_NONBLOCK flag).
+    
+Module snd-rawmidi
+------------------
+
+This module takes options which change the mapping of devices.
+similar to those of the snd-pcm-oss module.
+
+midi_map
+    MIDI device number maps assigned to the 1st OSS device;
+    Default: 0
+amidi_map
+    MIDI device number maps assigned to the 2st OSS device;
+    Default: 1
+
+Common parameters for top sound card modules
+--------------------------------------------
+
+Each of top level sound card module takes the following options.
+
+index
+    index (slot #) of sound card;
+    Values: 0 through 31 or negative;
+    If nonnegative, assign that index number;
+    if negative, interpret as a bitmask of permissible indices;
+    the first free permitted index is assigned;
+    Default: -1
+id
+    card ID (identifier or name);
+    Can be up to 15 characters long;
+    Default: the card type;
+    A directory by this name is created under /proc/asound/
+    containing information about the card;
+    This ID can be used instead of the index number in
+    identifying the card
+enable
+    enable card;
+    Default: enabled, for PCI and ISA PnP cards
+
+Module snd-adlib
+----------------
+
+Module for AdLib FM cards.
+
+port
+    port # for OPL chip
+
+This module supports multiple cards. It does not support autoprobe, so
+the port must be specified. For actual AdLib FM cards it will be 0x388.
+Note that this card does not have PCM support and no mixer; only FM
+synthesis.
+
+Make sure you have ``sbiload`` from the alsa-tools package available and,
+after loading the module, find out the assigned ALSA sequencer port
+number through ``sbiload -l``.
+
+Example output:
+::
+
+      Port     Client name                       Port name
+      64:0     OPL2 FM synth                     OPL2 FM Port
+
+Load the ``std.sb`` and ``drums.sb`` patches also supplied by ``sbiload``:
+::
+
+      sbiload -p 64:0 std.sb drums.sb
+
+If you use this driver to drive an OPL3, you can use ``std.o3`` and ``drums.o3``
+instead. To have the card produce sound, use ``aplaymidi`` from alsa-utils:
+::
+
+      aplaymidi -p 64:0 foo.mid
+
+Module snd-ad1816a
+------------------
+
+Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips.
+
+clockfreq
+    Clock frequency for AD1816A chip (default = 0, 33000Hz)
+    
+This module supports multiple cards, autoprobe and PnP.
+    
+Module snd-ad1848
+-----------------
+
+Module for sound cards based on AD1848/AD1847/CS4248 ISA chips.
+
+port
+    port # for AD1848 chip
+irq
+    IRQ # for AD1848  chip
+dma1
+    DMA # for AD1848 chip (0,1,3)
+    
+This module supports multiple cards.  It does not support autoprobe
+thus main port must be specified!!! Other ports are optional.
+    
+The power-management is supported.
+
+Module snd-ad1889
+-----------------
+
+Module for Analog Devices AD1889 chips.
+
+ac97_quirk
+    AC'97 workaround for strange hardware;
+    See the description of intel8x0 module for details.
+
+This module supports multiple cards.
+
+Module snd-ali5451
+------------------
+
+Module for ALi M5451 PCI chip.
+
+pcm_channels
+    Number of hardware channels assigned for PCM
+spdif
+    Support SPDIF I/O;
+    Default: disabled
+
+This module supports one chip and autoprobe.
+
+The power-management is supported.
+
+Module snd-als100
+-----------------
+
+Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips.
+
+This module supports multiple cards, autoprobe and PnP.
+
+The power-management is supported.
+
+Module snd-als300
+-----------------
+
+Module for Avance Logic ALS300 and ALS300+
+
+This module supports multiple cards.
+
+The power-management is supported.
+
+Module snd-als4000
+------------------
+
+Module for sound cards based on Avance Logic ALS4000 PCI chip.
+
+joystick_port
+    port # for legacy joystick support;
+    0 = disabled (default), 1 = auto-detect
+    
+This module supports multiple cards, autoprobe and PnP.
+
+The power-management is supported.
+
+Module snd-asihpi
+-----------------
+
+Module for AudioScience ASI soundcards
+
+enable_hpi_hwdep
+    enable HPI hwdep for AudioScience soundcard
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-atiixp
+-----------------
+
+Module for ATI IXP 150/200/250/400 AC97 controllers.
+
+ac97_clock
+    AC'97 clock (default = 48000)
+ac97_quirk
+    AC'97 workaround for strange hardware;
+    See `AC97 Quirk Option`_ section below.
+ac97_codec
+    Workaround to specify which AC'97 codec instead of probing.
+    If this works for you file a bug with your `lspci -vn` output.
+    (-2 = Force probing, -1 = Default behavior, 0-2 = Use the
+    specified codec.)
+spdif_aclink
+    S/PDIF transfer over AC-link (default = 1)
+
+This module supports one card and autoprobe.
+
+ATI IXP has two different methods to control SPDIF output.  One is
+over AC-link and another is over the "direct" SPDIF output.  The
+implementation depends on the motherboard, and you'll need to
+choose the correct one via spdif_aclink module option.
+
+The power-management is supported.
+
+Module snd-atiixp-modem
+-----------------------
+
+Module for ATI IXP 150/200/250 AC97 modem controllers.
+
+This module supports one card and autoprobe.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+The power-management is supported.
+
+Module snd-au8810, snd-au8820, snd-au8830
+-----------------------------------------
+
+Module for Aureal Vortex, Vortex2 and Advantage device.
+
+pcifix
+    Control PCI workarounds;
+    0 = Disable all workarounds,
+    1 = Force the PCI latency of the Aureal card to 0xff,
+    2 = Force the Extend PCI#2 Internal Master for Efficient
+    Handling of Dummy Requests on the VIA KT133 AGP Bridge,
+    3 = Force both settings,
+    255 = Autodetect what is required (default)
+
+This module supports all ADB PCM channels, ac97 mixer, SPDIF, hardware
+EQ, mpu401, gameport. A3D and wavetable support are still in development.
+Development and reverse engineering work is being coordinated at
+http://savannah.nongnu.org/projects/openvortex/
+SPDIF output has a copy of the AC97 codec output, unless you use the
+``spdif`` pcm device, which allows raw data passthru.
+The hardware EQ hardware and SPDIF is only present in the Vortex2 and 
+Advantage.
+
+Note: Some ALSA mixer applications don't handle the SPDIF sample rate 
+control correctly. If you have problems regarding this, try
+another ALSA compliant mixer (alsamixer works).
+
+Module snd-azt1605
+------------------
+
+Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
+chipset.
+
+port
+    port # for BASE (0x220,0x240,0x260,0x280)
+wss_port
+    port # for WSS (0x530,0x604,0xe80,0xf40)
+irq
+    IRQ # for WSS (7,9,10,11)
+dma1
+    DMA # for WSS playback (0,1,3)
+dma2
+    DMA # for WSS capture (0,1), -1 = disabled (default)
+mpu_port
+    port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
+mpu_irq
+    IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
+fm_port
+    port # for OPL3 (0x388), -1 = disabled (default)
+
+This module supports multiple cards. It does not support autoprobe:
+``port``, ``wss_port``, ``irq`` and ``dma1`` have to be specified.
+The other values are optional.
+
+``port`` needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
+or the value stored in the card's EEPROM for cards that have an EEPROM and
+their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
+be chosen freely from the options enumerated above.
+
+If ``dma2`` is specified and different from ``dma1``, the card will operate in
+full-duplex mode. When ``dma1=3``, only ``dma2=0`` is valid and the only way to
+enable capture since only channels 0 and 1 are available for capture.
+
+Generic settings are ``port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
+mpu_port=0x330 mpu_irq=9 fm_port=0x388``.
+
+Whatever IRQ and DMA channels you pick, be sure to reserve them for
+legacy ISA in your BIOS.
+
+Module snd-azt2316
+------------------
+
+Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
+chipset.
+
+port
+    port # for BASE (0x220,0x240,0x260,0x280)
+wss_port
+    port # for WSS (0x530,0x604,0xe80,0xf40)
+irq
+    IRQ # for WSS (7,9,10,11)
+dma1
+    DMA # for WSS playback (0,1,3)
+dma2
+    DMA # for WSS capture (0,1), -1 = disabled (default)
+mpu_port
+    port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
+mpu_irq
+    IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
+fm_port
+    port # for OPL3 (0x388), -1 = disabled (default)
+
+This module supports multiple cards. It does not support autoprobe:
+``port``, ``wss_port``, ``irq`` and ``dma1`` have to be specified.
+The other values are optional.
+
+``port`` needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
+or the value stored in the card's EEPROM for cards that have an EEPROM and
+their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
+be chosen freely from the options enumerated above.
+
+If ``dma2`` is specified and different from ``dma1``, the card will operate in
+full-duplex mode. When ``dma1=3``, only ``dma2=0`` is valid and the only way to
+enable capture since only channels 0 and 1 are available for capture.
+
+Generic settings are ``port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
+mpu_port=0x330 mpu_irq=9 fm_port=0x388``.
+
+Whatever IRQ and DMA channels you pick, be sure to reserve them for
+legacy ISA in your BIOS.
+
+Module snd-aw2
+--------------
+
+Module for Audiowerk2 sound card
+
+This module supports multiple cards.
+
+Module snd-azt2320
+------------------
+
+Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only).
+
+This module supports multiple cards, PnP and autoprobe.
+
+The power-management is supported.
+
+Module snd-azt3328
+------------------
+
+Module for sound cards based on Aztech AZF3328 PCI chip.
+
+joystick
+    Enable joystick (default off)
+
+This module supports multiple cards.
+
+Module snd-bt87x
+----------------
+
+Module for video cards based on Bt87x chips.
+
+digital_rate
+    Override the default digital rate (Hz)
+load_all
+    Load the driver even if the card model isn't known
+
+This module supports multiple cards.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+Module snd-ca0106
+-----------------
+
+Module for Creative Audigy LS and SB Live 24bit
+
+This module supports multiple cards.
+
+
+Module snd-cmi8330
+------------------
+
+Module for sound cards based on C-Media CMI8330 ISA chips.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+wssport
+    port # for CMI8330 chip (WSS)
+wssirq
+    IRQ # for CMI8330 chip (WSS)
+wssdma
+    first DMA # for CMI8330 chip (WSS)
+sbport
+    port # for CMI8330 chip (SB16)
+sbirq
+    IRQ # for CMI8330 chip (SB16)
+sbdma8
+    8bit DMA # for CMI8330 chip (SB16)
+sbdma16
+    16bit DMA # for CMI8330 chip (SB16)
+fmport
+    (optional) OPL3 I/O port
+mpuport
+    (optional) MPU401 I/O port
+mpuirq
+    (optional) MPU401 irq #
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-cmipci
+-----------------
+
+Module for C-Media CMI8338/8738/8768/8770 PCI sound cards.
+
+mpu_port
+    port address of MIDI interface (8338 only):
+    0x300,0x310,0x320,0x330 = legacy port,
+    0 = disable (default)
+fm_port
+    port address of OPL-3 FM synthesizer (8x38 only):
+    0x388 = legacy port,
+    1 = integrated PCI port (default on 8738),
+    0 = disable
+soft_ac3
+    Software-conversion of raw SPDIF packets (model 033 only) (default = 1)
+joystick_port
+    Joystick port address (0 = disable, 1 = auto-detect)
+
+This module supports autoprobe and multiple cards.
+
+The power-management is supported.
+
+Module snd-cs4231
+-----------------
+
+Module for sound cards based on CS4231 ISA chips.
+
+port
+    port # for CS4231 chip
+mpu_port
+    port # for MPU-401 UART (optional), -1 = disable
+irq
+    IRQ # for CS4231 chip
+mpu_irq
+    IRQ # for MPU-401 UART
+dma1
+    first DMA # for CS4231 chip
+dma2
+    second DMA # for CS4231 chip
+
+This module supports multiple cards. This module does not support autoprobe
+thus main port must be specified!!! Other ports are optional.
+
+The power-management is supported.
+
+Module snd-cs4236
+-----------------
+
+Module for sound cards based on CS4232/CS4232A,
+CS4235/CS4236/CS4236B/CS4237B/CS4238B/CS4239 ISA chips.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    port # for CS4236 chip (PnP setup - 0x534)
+cport
+    control port # for CS4236 chip (PnP setup - 0x120,0x210,0xf00)
+mpu_port
+    port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
+fm_port
+    FM port # for CS4236 chip (PnP setup - 0x388), -1 = disable
+irq
+    IRQ # for CS4236 chip (5,7,9,11,12,15)
+mpu_irq
+    IRQ # for MPU-401 UART (9,11,12,15)
+dma1
+    first DMA # for CS4236 chip (0,1,3)
+dma2
+    second DMA # for CS4236 chip (0,1,3), -1 = disable
+
+This module supports multiple cards. This module does not support autoprobe
+(if ISA PnP is not used) thus main port and control port must be
+specified!!! Other ports are optional.
+
+The power-management is supported.
+
+This module is aliased as snd-cs4232 since it provides the old
+snd-cs4232 functionality, too.
+
+Module snd-cs4281
+-----------------
+
+Module for Cirrus Logic CS4281 soundchip.
+
+dual_codec
+    Secondary codec ID (0 = disable, default)
+
+This module supports multiple cards.
+
+The power-management is supported.
+
+Module snd-cs46xx
+-----------------
+
+Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
+CS4624/CS4630/CS4280 PCI chips.
+
+external_amp
+    Force to enable external amplifier.
+thinkpad
+    Force to enable Thinkpad's CLKRUN control.
+mmap_valid
+    Support OSS mmap mode (default = 0).
+
+This module supports multiple cards and autoprobe.
+Usually external amp and CLKRUN controls are detected automatically
+from PCI sub vendor/device ids.  If they don't work, give the options
+above explicitly.
+
+The power-management is supported.
+
+Module snd-cs5530
+-----------------
+
+Module for Cyrix/NatSemi Geode 5530 chip. 
+
+Module snd-cs5535audio
+----------------------
+
+Module for multifunction CS5535 companion PCI device
+
+The power-management is supported.
+
+Module snd-ctxfi
+----------------
+
+Module for Creative Sound Blaster X-Fi boards (20k1 / 20k2 chips)
+
+* Creative Sound Blaster X-Fi Titanium Fatal1ty Champion Series
+* Creative Sound Blaster X-Fi Titanium Fatal1ty Professional Series
+* Creative Sound Blaster X-Fi Titanium Professional Audio
+* Creative Sound Blaster X-Fi Titanium
+* Creative Sound Blaster X-Fi Elite Pro
+* Creative Sound Blaster X-Fi Platinum
+* Creative Sound Blaster X-Fi Fatal1ty
+* Creative Sound Blaster X-Fi XtremeGamer
+* Creative Sound Blaster X-Fi XtremeMusic
+	
+reference_rate
+    reference sample rate, 44100 or 48000 (default)
+multiple
+    multiple to ref. sample rate, 1 or 2 (default)
+subsystem
+    override the PCI SSID for probing;
+    the value consists of SSVID << 16 | SSDID.
+    The default is zero, which means no override.
+
+This module supports multiple cards.
+
+Module snd-darla20
+------------------
+
+Module for Echoaudio Darla20
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-darla24
+------------------
+
+Module for Echoaudio Darla24
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-dt019x
+-----------------
+
+Module for Diamond Technologies DT-019X / Avance Logic ALS-007 (PnP
+only)
+
+This module supports multiple cards.  This module is enabled only with
+ISA PnP support.
+
+The power-management is supported.
+
+Module snd-dummy
+----------------
+
+Module for the dummy sound card. This "card" doesn't do any output
+or input, but you may use this module for any application which
+requires a sound card (like RealPlayer).
+
+pcm_devs
+    Number of PCM devices assigned to each card (default = 1, up to 4)
+pcm_substreams
+    Number of PCM substreams assigned to each PCM (default = 8, up to 128)
+hrtimer
+    Use hrtimer (=1, default) or system timer (=0)
+fake_buffer
+    Fake buffer allocations (default = 1)
+
+When multiple PCM devices are created, snd-dummy gives different
+behavior to each PCM device:
+* 0 = interleaved with mmap support
+* 1 = non-interleaved with mmap support
+* 2 = interleaved without mmap 
+* 3 = non-interleaved without mmap
+
+As default, snd-dummy drivers doesn't allocate the real buffers
+but either ignores read/write or mmap a single dummy page to all
+buffer pages, in order to save the resources.  If your apps need
+the read/ written buffer data to be consistent, pass fake_buffer=0
+option.
+
+The power-management is supported.
+
+Module snd-echo3g
+-----------------
+
+Module for Echoaudio 3G cards (Gina3G/Layla3G)
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-emu10k1
+------------------
+
+Module for EMU10K1/EMU10k2 based PCI sound cards.
+
+* Sound Blaster Live!
+* Sound Blaster PCI 512
+* Emu APS (partially supported)
+* Sound Blaster Audigy
+	
+extin
+    bitmap of available external inputs for FX8010 (see bellow)
+extout
+    bitmap of available external outputs for FX8010 (see bellow)
+seq_ports
+    allocated sequencer ports (4 by default)
+max_synth_voices
+    limit of voices used for wavetable (64 by default)
+max_buffer_size
+    specifies the maximum size of wavetable/pcm buffers given in MB
+    unit.  Default value is 128.
+enable_ir
+    enable IR
+
+This module supports multiple cards and autoprobe.
+
+Input & Output configurations 			[extin/extout]
+* Creative Card wo/Digital out			[0x0003/0x1f03]
+* Creative Card w/Digital out			[0x0003/0x1f0f]
+* Creative Card w/Digital CD in			[0x000f/0x1f0f]
+* Creative Card wo/Digital out + LiveDrive	[0x3fc3/0x1fc3]
+* Creative Card w/Digital out + LiveDrive	[0x3fc3/0x1fcf]
+* Creative Card w/Digital CD in + LiveDrive	[0x3fcf/0x1fcf]
+* Creative Card wo/Digital out + Digital I/O 2  [0x0fc3/0x1f0f]
+* Creative Card w/Digital out + Digital I/O 2	[0x0fc3/0x1f0f]
+* Creative Card w/Digital CD in + Digital I/O 2	[0x0fcf/0x1f0f]
+* Creative Card 5.1/w Digital out + LiveDrive	[0x3fc3/0x1fff]
+* Creative Card 5.1 (c) 2003			[0x3fc3/0x7cff]
+* Creative Card all ins and outs		[0x3fff/0x7fff]
+  
+The power-management is supported.
+  
+Module snd-emu10k1x
+-------------------
+
+Module for Creative Emu10k1X (SB Live Dell OEM version)
+
+This module supports multiple cards.
+
+Module snd-ens1370
+------------------
+
+Module for Ensoniq AudioPCI ES1370 PCI sound cards.
+
+* SoundBlaster PCI 64
+* SoundBlaster PCI 128
+    
+joystick
+    Enable joystick (default off)
+  
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-ens1371
+------------------
+
+Module for Ensoniq AudioPCI ES1371 PCI sound cards.
+
+* SoundBlaster PCI 64
+* SoundBlaster PCI 128
+* SoundBlaster Vibra PCI
+      
+joystick_port
+    port # for joystick (0x200,0x208,0x210,0x218), 0 = disable
+    (default), 1 = auto-detect
+  
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-es1688
+-----------------
+
+Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+mpu_port
+    port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
+mpu_irq
+    IRQ # for MPU-401 port (5,7,9,10)
+fm_port
+    port # for OPL3 (option; share the same port as default)
+
+with ``isapnp=0``, the following additional options are available:
+
+port
+    port # for ES-1688 chip (0x220,0x240,0x260)
+irq
+    IRQ # for ES-1688 chip (5,7,9,10)
+dma8
+    DMA # for ES-1688 chip (0,1,3)
+
+This module supports multiple cards and autoprobe (without MPU-401 port)
+and PnP with the ES968 chip.
+
+Module snd-es18xx
+-----------------
+
+Module for ESS AudioDrive ES-18xx sound cards.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    port # for ES-18xx chip (0x220,0x240,0x260)
+mpu_port
+    port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
+fm_port
+    port # for FM (optional, not used)
+irq
+    IRQ # for ES-18xx chip (5,7,9,10)
+dma1
+    first DMA # for ES-18xx chip (0,1,3)
+dma2
+    first DMA # for ES-18xx chip (0,1,3)
+
+This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
+port if native ISA PnP routines are not used).
+When ``dma2`` is equal with ``dma1``, the driver works as half-duplex.
+
+The power-management is supported.
+
+Module snd-es1938
+-----------------
+
+Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-es1968
+-----------------
+
+Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
+
+total_bufsize
+    total buffer size in kB (1-4096kB)
+pcm_substreams_p
+    playback channels (1-8, default=2)
+pcm_substreams_c
+    capture channels (1-8, default=0)
+clock
+    clock (0 = auto-detection)
+use_pm
+    support the power-management (0 = off, 1 = on, 2 = auto (default))
+enable_mpu
+    enable MPU401 (0 = off, 1 = on, 2 = auto (default))
+joystick
+    enable joystick (default off)       
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-fm801
+----------------
+
+Module for ForteMedia FM801 based PCI sound cards.
+
+tea575x_tuner
+    Enable TEA575x tuner;
+    1 = MediaForte 256-PCS,
+    2 = MediaForte 256-PCPR,
+    3 = MediaForte 64-PCR
+    High 16-bits are video (radio) device number + 1;
+    example: 0x10002 (MediaForte 256-PCPR, device 1)
+	  
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-gina20
+-----------------
+
+Module for Echoaudio Gina20
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-gina24
+-----------------
+
+Module for Echoaudio Gina24
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-gusclassic
+---------------------
+
+Module for Gravis UltraSound Classic sound card.
+
+port
+    port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
+irq
+    IRQ # for GF1 chip (3,5,9,11,12,15)
+dma1
+    DMA # for GF1 chip (1,3,5,6,7)
+dma2
+    DMA # for GF1 chip (1,3,5,6,7,-1=disable)
+joystick_dac
+    0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+voices
+    GF1 voices limit (14-32)
+pcm_voices
+    reserved PCM voices
+
+This module supports multiple cards and autoprobe.
+
+Module snd-gusextreme
+---------------------
+
+Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card.
+
+port
+    port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260)
+gf1_port
+    port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270)
+mpu_port
+    port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable
+irq
+    IRQ # for ES-1688 chip (5,7,9,10)
+gf1_irq
+    IRQ # for GF1 chip (3,5,9,11,12,15)
+mpu_irq
+    IRQ # for MPU-401 port (5,7,9,10)
+dma8
+    DMA # for ES-1688 chip (0,1,3)
+dma1
+    DMA # for GF1 chip (1,3,5,6,7)
+joystick_dac
+    0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+voices
+    GF1 voices limit (14-32)
+pcm_voices
+    reserved PCM voices
+
+This module supports multiple cards and autoprobe (without MPU-401 port).
+
+Module snd-gusmax
+-----------------
+
+Module for Gravis UltraSound MAX sound card.
+
+port
+    port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
+irq
+    IRQ # for GF1 chip (3,5,9,11,12,15)
+dma1
+    DMA # for GF1 chip (1,3,5,6,7)
+dma2
+    DMA # for GF1 chip (1,3,5,6,7,-1=disable)
+joystick_dac
+    0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+voices
+    GF1 voices limit (14-32)
+pcm_voices
+    reserved PCM voices
+
+This module supports multiple cards and autoprobe.
+
+Module snd-hda-intel
+--------------------
+
+Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8, ICH9, ICH10,
+PCH, SCH), ATI SB450, SB600, R600, RS600, RS690, RS780, RV610, RV620,
+RV630, RV635, RV670, RV770, VIA VT8251/VT8237A, SIS966, ULI M5461
+
+[Multiple options for each card instance]
+
+model
+    force the model name
+position_fix
+    Fix DMA pointer;
+    -1 = system default: choose appropriate one per controller hardware,
+    0 = auto: falls back to LPIB when POSBUF doesn't work,
+    1 = use LPIB,
+    2 = POSBUF: use position buffer,
+    3 = VIACOMBO: VIA-specific workaround for capture,
+    4 = COMBO: use LPIB for playback, auto for capture stream
+probe_mask
+    Bitmask to probe codecs (default = -1, meaning all slots);
+    When the bit 8 (0x100) is set, the lower 8 bits are used
+    as the "fixed" codec slots; i.e. the driver probes the
+    slots regardless what hardware reports back
+probe_only
+    Only probing and no codec initialization (default=off);
+    Useful to check the initial codec status for debugging
+bdl_pos_adj
+    Specifies the DMA IRQ timing delay in samples.
+    Passing -1 will make the driver to choose the appropriate
+    value based on the controller chip.
+patch
+    Specifies the early "patch" files to modify the HD-audio setup
+    before initializing the codecs.
+    This option is available only when ``CONFIG_SND_HDA_PATCH_LOADER=y``
+    is set.  See hd-audio/notes.rst for details.
+beep_mode
+    Selects the beep registration mode (0=off, 1=on);
+    default value is set via ``CONFIG_SND_HDA_INPUT_BEEP_MODE`` kconfig.
+
+[Single (global) options]
+
+single_cmd
+    Use single immediate commands to communicate with codecs
+    (for debugging only)
+enable_msi
+    Enable Message Signaled Interrupt (MSI) (default = off)
+power_save
+    Automatic power-saving timeout (in second, 0 = 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.
+
+See hd-audio/notes.rst for more details about HD-audio driver.
+
+Each codec may have a model table for different configurations.
+If your machine isn't listed there, the default (usually minimal)
+configuration is set up.  You can pass ``model=<name>`` option to
+specify a certain model in such a case.  There are different
+models depending on the codec chip.  The list of available models
+is found in hd-audio/models.rst.
+
+The model name ``generic`` is treated as a special case.  When this
+model is given, the driver uses the generic codec parser without
+"codec-patch".  It's sometimes good for testing and debugging.
+
+If the default configuration doesn't work and one of the above
+matches with your device, report it together with alsa-info.sh
+output (with ``--no-upload`` option) to kernel bugzilla or alsa-devel
+ML (see the section `Links and Addresses`_).
+
+``power_save`` and ``power_save_controller`` options are for power-saving
+mode.  See powersave.txt for details.
+
+Note 2: If you get click noises on output, try the module option
+``position_fix=1`` or ``2``.  ``position_fix=1`` will use the SD_LPIB
+register value without FIFO size correction as the current
+DMA pointer.  ``position_fix=2`` will make the driver to use
+the position buffer instead of reading SD_LPIB register.
+(Usually SD_LPIB register is more accurate than the
+position buffer.)
+
+``position_fix=3`` is specific to VIA devices.  The position
+of the capture stream is checked from both LPIB and POSBUF
+values.  ``position_fix=4`` is a combination mode, using LPIB
+for playback and POSBUF for capture.
+
+NB: If you get many ``azx_get_response timeout`` messages at
+loading, it's likely a problem of interrupts (e.g. ACPI irq
+routing).  Try to boot with options like ``pci=noacpi``.  Also, you
+can try ``single_cmd=1`` module option.  This will switch the
+communication method between HDA controller and codecs to the
+single immediate commands instead of CORB/RIRB.  Basically, the
+single command mode is provided only for BIOS, and you won't get
+unsolicited events, too.  But, at least, this works independently
+from the irq.  Remember this is a last resort, and should be
+avoided as much as possible...
+
+MORE NOTES ON ``azx_get_response timeout`` PROBLEMS:
+On some hardware, you may need to add a proper probe_mask option
+to avoid the ``azx_get_response timeout`` problem above, instead.
+This occurs when the access to non-existing or non-working codec slot
+(likely a modem one) causes a stall of the communication via HD-audio
+bus.  You can see which codec slots are probed by enabling
+``CONFIG_SND_DEBUG_VERBOSE``, or simply from the file name of the codec
+proc files.  Then limit the slots to probe by probe_mask option.
+For example, ``probe_mask=1`` means to probe only the first slot, and
+``probe_mask=4`` means only the third slot.
+
+The power-management is supported.
+
+Module snd-hdsp
+---------------
+
+Module for RME Hammerfall DSP audio interface(s)
+
+This module supports multiple cards.
+
+Note: The firmware data can be automatically loaded via hotplug
+when ``CONFIG_FW_LOADER`` is set.  Otherwise, you need to load
+the firmware via hdsploader utility included in alsa-tools
+package.
+The firmware data is found in alsa-firmware package.
+
+Note: snd-page-alloc module does the job which snd-hammerfall-mem
+module did formerly.  It will allocate the buffers in advance
+when any HDSP cards are found.  To make the buffer
+allocation sure, load snd-page-alloc module in the early
+stage of boot sequence.  See `Early Buffer Allocation`_
+section.
+
+Module snd-hdspm
+----------------
+
+Module for RME HDSP MADI board.
+
+precise_ptr
+    Enable precise pointer, or disable.
+line_outs_monitor
+    Send playback streams to analog outs by default.
+enable_monitor
+    Enable Analog Out on Channel 63/64 by default.
+
+See hdspm.txt for details.
+
+Module snd-ice1712
+------------------
+
+Module for Envy24 (ICE1712) based PCI sound cards.
+
+* MidiMan M Audio Delta 1010
+* MidiMan M Audio Delta 1010LT
+* MidiMan M Audio Delta DiO 2496
+* MidiMan M Audio Delta 66
+* MidiMan M Audio Delta 44
+* MidiMan M Audio Delta 410
+* MidiMan M Audio Audiophile 2496
+* TerraTec EWS 88MT
+* TerraTec EWS 88D
+* TerraTec EWX 24/96
+* TerraTec DMX 6Fire
+* TerraTec Phase 88
+* Hoontech SoundTrack DSP 24
+* Hoontech SoundTrack DSP 24 Value
+* Hoontech SoundTrack DSP 24 Media 7.1
+* Event Electronics, EZ8
+* Digigram VX442
+* Lionstracs, Mediastaton
+* Terrasoniq TS 88
+			
+model
+    Use the given board model, one of the following:
+    delta1010, dio2496, delta66, delta44, audiophile, delta410,
+    delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
+    dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
+    phase88, mediastation
+omni
+    Omni I/O support for MidiMan M-Audio Delta44/66
+cs8427_timeout
+    reset timeout for the CS8427 chip (S/PDIF transceiver) in msec
+    resolution, default value is 500 (0.5 sec)
+
+This module supports multiple cards and autoprobe.
+Note: The consumer part is not used with all Envy24 based cards (for
+example in the MidiMan Delta siree).
+
+Note: The supported board is detected by reading EEPROM or PCI
+SSID (if EEPROM isn't available).  You can override the
+model by passing ``model`` module option in case that the
+driver isn't configured properly or you want to try another
+type for testing.
+
+Module snd-ice1724
+------------------
+
+Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
+
+* MidiMan M Audio Revolution 5.1
+* MidiMan M Audio Revolution 7.1
+* MidiMan M Audio Audiophile 192
+* AMP Ltd AUDIO2000
+* TerraTec Aureon 5.1 Sky
+* TerraTec Aureon 7.1 Space
+* TerraTec Aureon 7.1 Universe
+* TerraTec Phase 22
+* TerraTec Phase 28
+* AudioTrak Prodigy 7.1
+* AudioTrak Prodigy 7.1 LT
+* AudioTrak Prodigy 7.1 XT
+* AudioTrak Prodigy 7.1 HIFI
+* AudioTrak Prodigy 7.1 HD2
+* AudioTrak Prodigy 192
+* Pontis MS300
+* Albatron K8X800 Pro II 
+* Chaintech ZNF3-150
+* Chaintech ZNF3-250
+* Chaintech 9CJS
+* Chaintech AV-710
+* Shuttle SN25P
+* Onkyo SE-90PCI
+* Onkyo SE-200PCI
+* ESI Juli@
+* ESI Maya44
+* Hercules Fortissimo IV
+* EGO-SYS WaveTerminal 192M
+			
+model
+    Use the given board model, one of the following:
+    revo51, revo71, amp2000, prodigy71, prodigy71lt,
+    prodigy71xt, prodigy71hifi, prodigyhd2, prodigy192,
+    juli, aureon51, aureon71, universe, ap192, k8x800,
+    phase22, phase28, ms300, av710, se200pci, se90pci,
+    fortissimo4, sn25p, WT192M, maya44
+  
+This module supports multiple cards and autoprobe.
+
+Note: The supported board is detected by reading EEPROM or PCI
+SSID (if EEPROM isn't available).  You can override the
+model by passing ``model`` module option in case that the
+driver isn't configured properly or you want to try another
+type for testing.
+
+Module snd-indigo
+-----------------
+
+Module for Echoaudio Indigo
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-indigodj
+-------------------
+
+Module for Echoaudio Indigo DJ
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-indigoio
+-------------------
+
+Module for Echoaudio Indigo IO
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-intel8x0
+-------------------
+
+Module for AC'97 motherboards from Intel and compatibles.
+
+* Intel i810/810E, i815, i820, i830, i84x, MX440 ICH5, ICH6, ICH7,
+  6300ESB, ESB2 
+* SiS 7012 (SiS 735)
+* NVidia NForce, NForce2, NForce3, MCP04, CK804 CK8, CK8S, MCP501
+* AMD AMD768, AMD8111
+* ALi m5455
+	  
+ac97_clock
+    AC'97 codec clock base (0 = auto-detect)
+ac97_quirk
+    AC'97 workaround for strange hardware;
+    See `AC97 Quirk Option`_ section below.
+buggy_irq
+    Enable workaround for buggy interrupts on some motherboards
+    (default yes on nForce chips, otherwise off)
+buggy_semaphore
+    Enable workaround for hardware with buggy semaphores (e.g. on some
+    ASUS laptops) (default off)
+spdif_aclink
+    Use S/PDIF over AC-link instead of direct connection from the
+    controller chip (0 = off, 1 = on, -1 = default)
+
+This module supports one chip and autoprobe.
+
+Note: the latest driver supports auto-detection of chip clock.
+if you still encounter too fast playback, specify the clock
+explicitly via the module option ``ac97_clock=41194``.
+
+Joystick/MIDI ports are not supported by this driver.  If your
+motherboard has these devices, use the ns558 or snd-mpu401
+modules, respectively.
+
+The power-management is supported.
+
+Module snd-intel8x0m
+--------------------
+
+Module for Intel ICH (i8x0) chipset MC97 modems.
+
+* Intel i810/810E, i815, i820, i830, i84x, MX440 ICH5, ICH6, ICH7
+* SiS 7013 (SiS 735)
+* NVidia NForce, NForce2, NForce2s, NForce3
+* AMD AMD8111
+* ALi m5455
+	  
+ac97_clock
+    AC'97 codec clock base (0 = auto-detect)
+  
+This module supports one card and autoprobe.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+The power-management is supported.
+
+Module snd-interwave
+--------------------
+
+Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32
+and other sound cards based on AMD InterWave (tm) chip.
+
+joystick_dac
+    0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+midi
+    1 = MIDI UART enable, 0 = MIDI UART disable (default)
+pcm_voices
+    reserved PCM voices for the synthesizer (default 2)
+effect
+    1 = InterWave effects enable (default 0); requires 8 voices
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
+irq
+    IRQ # for InterWave chip (3,5,9,11,12,15)
+dma1
+    DMA # for InterWave chip (0,1,3,5,6,7)
+dma2
+    DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
+
+This module supports multiple cards, autoprobe and ISA PnP.
+
+Module snd-interwave-stb
+------------------------
+
+Module for UltraSound 32-Pro (sound card from STB used by Compaq)
+and other sound cards based on AMD InterWave (tm) chip with TEA6330T
+circuit for extended control of bass, treble and master volume.
+
+joystick_dac
+    0 to 31, (0.59V-4.52V or 0.389V-2.98V)
+midi
+    1 = MIDI UART enable, 0 = MIDI UART disable (default)
+pcm_voices
+    reserved PCM voices for the synthesizer (default 2)
+effect
+    1 = InterWave effects enable (default 0); requires 8 voices
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
+port_tc
+    tone control (i2c bus) port # for TEA6330T chip (0x350,0x360,0x370,0x380)
+irq
+    IRQ # for InterWave chip (3,5,9,11,12,15)
+dma1
+    DMA # for InterWave chip (0,1,3,5,6,7)
+dma2
+    DMA # for InterWave chip (0,1,3,5,6,7,-1=disable)
+
+This module supports multiple cards, autoprobe and ISA PnP.
+
+Module snd-jazz16
+-------------------
+
+Module for Media Vision Jazz16 chipset. The chipset consists of 3 chips:
+MVD1216 + MVA416 + MVA514.
+
+port
+    port # for SB DSP chip (0x210,0x220,0x230,0x240,0x250,0x260)
+irq
+    IRQ # for SB DSP chip (3,5,7,9,10,15)
+dma8
+    DMA # for SB DSP chip (1,3)
+dma16
+    DMA # for SB DSP chip (5,7)
+mpu_port
+    MPU-401 port # (0x300,0x310,0x320,0x330)
+mpu_irq
+    MPU-401 irq # (2,3,5,7)
+
+This module supports multiple cards.
+
+Module snd-korg1212
+-------------------
+
+Module for Korg 1212 IO PCI card
+
+This module supports multiple cards.
+
+Module snd-layla20
+------------------
+
+Module for Echoaudio Layla20
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-layla24
+------------------
+
+Module for Echoaudio Layla24
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-lola
+---------------
+
+Module for Digigram Lola PCI-e boards
+
+This module supports multiple cards.
+
+Module snd-lx6464es
+-------------------
+
+Module for Digigram LX6464ES boards
+
+This module supports multiple cards.
+
+Module snd-maestro3
+-------------------
+
+Module for Allegro/Maestro3 chips
+
+external_amp
+    enable external amp (enabled by default)
+amp_gpio
+    GPIO pin number for external amp (0-15) or -1 for default pin (8
+    for allegro, 1 for others) 
+
+This module supports autoprobe and multiple chips.
+
+Note: the binding of amplifier is dependent on hardware.
+If there is no sound even though all channels are unmuted, try to
+specify other gpio connection via amp_gpio option. 
+For example, a Panasonic notebook might need ``amp_gpio=0x0d``
+option.
+
+The power-management is supported.
+
+Module snd-mia
+---------------
+
+Module for Echoaudio Mia
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-miro
+---------------
+
+Module for Miro soundcards: miroSOUND PCM 1 pro, miroSOUND PCM 12,
+miroSOUND PCM 20 Radio.
+
+port
+    Port # (0x530,0x604,0xe80,0xf40)
+irq
+    IRQ # (5,7,9,10,11)
+dma1
+    1st dma # (0,1,3)
+dma2
+    2nd dma # (0,1)
+mpu_port
+    MPU-401 port # (0x300,0x310,0x320,0x330)
+mpu_irq
+    MPU-401 irq # (5,7,9,10)
+fm_port
+    FM Port # (0x388)
+wss
+    enable WSS mode
+ide
+    enable onboard ide support
+
+Module snd-mixart
+-----------------
+
+Module for Digigram miXart8 sound cards.
+
+This module supports multiple cards.
+Note: One miXart8 board will be represented as 4 alsa cards.
+See MIXART.txt for details.
+
+When the driver is compiled as a module and the hotplug firmware
+is supported, the firmware data is loaded via hotplug automatically.
+Install the necessary firmware files in alsa-firmware package.
+When no hotplug fw loader is available, you need to load the
+firmware via mixartloader utility in alsa-tools package.
+
+Module snd-mona
+---------------
+
+Module for Echoaudio Mona
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+
+Module snd-mpu401
+-----------------
+
+Module for MPU-401 UART devices.
+
+port
+    port number or -1 (disable)
+irq
+    IRQ number or -1 (disable)
+pnp
+    PnP detection - 0 = disable, 1 = enable (default)
+
+This module supports multiple devices and PnP.
+
+Module snd-msnd-classic
+-----------------------
+
+Module for Turtle Beach MultiSound Classic, Tahiti or Monterey
+soundcards.
+
+io
+    Port # for msnd-classic card
+irq
+    IRQ # for msnd-classic card
+mem
+    Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000)
+write_ndelay
+    enable write ndelay (default = 1)
+calibrate_signal
+    calibrate signal (default = 0)
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+digital
+    Digital daughterboard present (default = 0)
+cfg
+    Config port (0x250, 0x260 or 0x270) default = PnP
+reset
+    Reset all devices
+mpu_io
+    MPU401 I/O port
+mpu_irq
+    MPU401 irq#
+ide_io0
+    IDE port #0
+ide_io1
+    IDE port #1
+ide_irq
+    IDE irq#
+joystick_io
+    Joystick I/O port
+
+The driver requires firmware files ``/*(DEBLOBBED)*/`` and
+``/*(DEBLOBBED)*/`` in the proper firmware directory.
+
+See Documentation/sound/oss/MultiSound for important information
+about this driver.  Note that it has been discontinued, but the 
+Voyetra Turtle Beach knowledge base entry for it is still available
+at
+http://www.turtlebeach.com
+
+Module snd-msnd-pinnacle
+------------------------
+
+Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards.
+
+io
+    Port # for pinnacle/fiji card
+irq
+    IRQ # for pinnalce/fiji card
+mem
+    Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or 0xe8000)
+write_ndelay
+    enable write ndelay (default = 1)
+calibrate_signal
+    calibrate signal (default = 0)
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+The driver requires firmware files ``/*(DEBLOBBED)*/`` and
+``/*(DEBLOBBED)*/`` in the proper firmware directory.
+
+Module snd-mtpav
+----------------
+
+Module for MOTU MidiTimePiece AV multiport MIDI (on the parallel
+port).
+
+port
+    I/O port # for MTPAV (0x378,0x278, default=0x378)
+irq
+    IRQ # for MTPAV (7,5, default=7)
+hwports
+    number of supported hardware ports, default=8.
+
+Module supports only 1 card.  This module has no enable option.
+
+Module snd-mts64
+----------------
+
+Module for Ego Systems (ESI) Miditerminal 4140
+
+This module supports multiple devices.
+Requires parport (``CONFIG_PARPORT``).
+
+Module snd-nm256
+----------------
+
+Module for NeoMagic NM256AV/ZX chips
+
+playback_bufsize
+    max playback frame size in kB (4-128kB)
+capture_bufsize
+    max capture frame size in kB (4-128kB)
+force_ac97
+    0 or 1 (disabled by default)
+buffer_top
+    specify buffer top address
+use_cache
+    0 or 1 (disabled by default)
+vaio_hack
+    alias buffer_top=0x25a800
+reset_workaround
+    enable AC97 RESET workaround for some laptops
+reset_workaround2
+    enable extended AC97 RESET workaround for some other laptops
+
+This module supports one chip and autoprobe.
+
+The power-management is supported.
+
+Note: on some notebooks the buffer address cannot be detected
+automatically, or causes hang-up during initialization.
+In such a case, specify the buffer top address explicitly via
+the buffer_top option.
+For example,
+Sony F250: buffer_top=0x25a800
+Sony F270: buffer_top=0x272800
+The driver supports only ac97 codec.  It's possible to force
+to initialize/use ac97 although it's not detected.  In such a
+case, use ``force_ac97=1`` option - but *NO* guarantee whether it
+works!
+
+Note: The NM256 chip can be linked internally with non-AC97
+codecs.  This driver supports only the AC97 codec, and won't work
+with machines with other (most likely CS423x or OPL3SAx) chips,
+even though the device is detected in lspci.  In such a case, try
+other drivers, e.g. snd-cs4232 or snd-opl3sa2.  Some has ISA-PnP
+but some doesn't have ISA PnP.  You'll need to specify ``isapnp=0``
+and proper hardware parameters in the case without ISA PnP.
+
+Note: some laptops need a workaround for AC97 RESET.  For the
+known hardware like Dell Latitude LS and Sony PCG-F305, this
+workaround is enabled automatically.  For other laptops with a
+hard freeze, you can try ``reset_workaround=1`` option.
+
+Note: Dell Latitude CSx laptops have another problem regarding
+AC97 RESET.  On these laptops, reset_workaround2 option is
+turned on as default.  This option is worth to try if the
+previous reset_workaround option doesn't help.
+
+Note: This driver is really crappy.  It's a porting from the
+OSS driver, which is a result of black-magic reverse engineering.
+The detection of codec will fail if the driver is loaded *after*
+X-server as described above.  You might be able to force to load
+the module, but it may result in hang-up.   Hence, make sure that
+you load this module *before* X if you encounter this kind of
+problem.
+
+Module snd-opl3sa2
+------------------
+
+Module for Yamaha OPL3-SA2/SA3 sound cards.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    control port # for OPL3-SA chip (0x370)
+sb_port
+    SB port # for OPL3-SA chip (0x220,0x240)
+wss_port
+    WSS port # for OPL3-SA chip (0x530,0xe80,0xf40,0x604)
+midi_port
+    port # for MPU-401 UART (0x300,0x330), -1 = disable
+fm_port
+    FM port # for OPL3-SA chip (0x388), -1 = disable
+irq
+    IRQ # for OPL3-SA chip (5,7,9,10)
+dma1
+    first DMA # for Yamaha OPL3-SA chip (0,1,3)
+dma2
+    second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
+
+This module supports multiple cards and ISA PnP.  It does not support
+autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
+
+The power-management is supported.
+
+Module snd-opti92x-ad1848
+-------------------------
+
+Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips.
+Module works with OAK Mozart cards as well.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    port # for WSS chip (0x530,0xe80,0xf40,0x604)
+mpu_port
+    port # for MPU-401 UART (0x300,0x310,0x320,0x330)
+fm_port
+    port # for OPL3 device (0x388)
+irq
+    IRQ # for WSS chip (5,7,9,10,11)
+mpu_irq
+    IRQ # for MPU-401 UART (5,7,9,10)
+dma1
+    first DMA # for WSS chip (0,1,3)
+
+This module supports only one card, autoprobe and PnP.
+
+Module snd-opti92x-cs4231
+-------------------------
+
+Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    port # for WSS chip (0x530,0xe80,0xf40,0x604)
+mpu_port
+    port # for MPU-401 UART (0x300,0x310,0x320,0x330)
+fm_port
+    port # for OPL3 device (0x388)
+irq
+    IRQ # for WSS chip (5,7,9,10,11)
+mpu_irq
+    IRQ # for MPU-401 UART (5,7,9,10)
+dma1
+    first DMA # for WSS chip (0,1,3)
+dma2
+    second DMA # for WSS chip (0,1,3)
+
+This module supports only one card, autoprobe and PnP.
+
+Module snd-opti93x
+------------------
+
+Module for sound cards based on OPTi 82c93x chips.
+
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with ``isapnp=0``, the following options are available:
+
+port
+    port # for WSS chip (0x530,0xe80,0xf40,0x604)
+mpu_port
+    port # for MPU-401 UART (0x300,0x310,0x320,0x330)
+fm_port
+    port # for OPL3 device (0x388)
+irq
+    IRQ # for WSS chip (5,7,9,10,11)
+mpu_irq
+    IRQ # for MPU-401 UART (5,7,9,10)
+dma1
+    first DMA # for WSS chip (0,1,3)
+dma2
+    second DMA # for WSS chip (0,1,3)
+
+This module supports only one card, autoprobe and PnP.
+
+Module snd-oxygen
+-----------------
+
+Module for sound cards based on the C-Media CMI8786/8787/8788 chip:
+
+* Asound A-8788
+* Asus Xonar DG/DGX
+* AuzenTech X-Meridian
+* AuzenTech X-Meridian 2G
+* Bgears b-Enspirer
+* Club3D Theatron DTS
+* HT-Omega Claro (plus)
+* HT-Omega Claro halo (XT)
+* Kuroutoshikou CMI8787-HG2PCI
+* Razer Barracuda AC-1
+* Sondigo Inferno
+* TempoTec HiFier Fantasia
+* TempoTec HiFier Serenade
+    
+This module supports autoprobe and multiple cards.
+  
+Module snd-pcsp
+---------------
+
+Module for internal PC-Speaker.
+
+nopcm
+    Disable PC-Speaker PCM sound. Only beeps remain.
+nforce_wa
+    enable NForce chipset workaround. Expect bad sound.
+
+This module supports system beeps, some kind of PCM playback and
+even a few mixer controls.
+
+Module snd-pcxhr
+----------------
+
+Module for Digigram PCXHR boards
+
+This module supports multiple cards.
+
+Module snd-portman2x4
+---------------------
+
+Module for Midiman Portman 2x4 parallel port MIDI interface
+
+This module supports multiple cards.
+
+Module snd-powermac (on ppc only)
+---------------------------------
+
+Module for PowerMac, iMac and iBook on-board soundchips
+
+enable_beep
+    enable beep using PCM (enabled as default)
+
+Module supports autoprobe a chip.
+
+Note: the driver may have problems regarding endianness.
+
+The power-management is supported.
+
+Module snd-pxa2xx-ac97 (on arm only)
+------------------------------------
+
+Module for AC97 driver for the Intel PXA2xx chip
+
+For ARM architecture only.
+
+The power-management is supported.
+
+Module snd-riptide
+------------------
+
+Module for Conexant Riptide chip
+
+joystick_port
+    Joystick port # (default: 0x200)
+mpu_port
+    MPU401 port # (default: 0x330)
+opl3_port
+    OPL3 port # (default: 0x388)
+
+This module supports multiple cards.
+The driver requires the firmware loader support on kernel.
+You need to install the firmware file ``/*(DEBLOBBED)*/`` to the standard
+firmware path (e.g. /lib/firmware).
+
+Module snd-rme32
+----------------
+
+Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32, 
+Prodif96 and Prodif Gold) sound cards.
+
+This module supports multiple cards.
+
+Module snd-rme96
+----------------
+
+Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
+
+This module supports multiple cards.
+
+Module snd-rme9652
+------------------
+
+Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards.
+
+precise_ptr
+    Enable precise pointer (doesn't work reliably). (default = 0)
+
+This module supports multiple cards.
+
+Note: snd-page-alloc module does the job which snd-hammerfall-mem
+module did formerly.  It will allocate the buffers in advance
+when any RME9652 cards are found.  To make the buffer
+allocation sure, load snd-page-alloc module in the early
+stage of boot sequence.  See `Early Buffer Allocation`_
+section.
+
+Module snd-sa11xx-uda1341 (on arm only)
+---------------------------------------
+
+Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card.
+
+Module supports only one card.
+Module has no enable and index options.
+
+The power-management is supported.
+
+Module snd-sb8
+--------------
+
+Module for 8-bit SoundBlaster cards: SoundBlaster 1.0, SoundBlaster 2.0,
+SoundBlaster Pro
+
+port
+    port # for SB DSP chip (0x220,0x240,0x260)
+irq
+    IRQ # for SB DSP chip (5,7,9,10)
+dma8
+    DMA # for SB DSP chip (1,3)
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-sb16 and snd-sbawe
+-----------------------------
+
+Module for 16-bit SoundBlaster cards: SoundBlaster 16 (PnP),
+SoundBlaster AWE 32 (PnP), SoundBlaster AWE 64 PnP
+
+mic_agc
+    Mic Auto-Gain-Control - 0 = disable, 1 = enable (default)
+csp
+    ASP/CSP chip support - 0 = disable (default), 1 = enable
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with isapnp=0, the following options are available:
+
+port
+    port # for SB DSP 4.x chip (0x220,0x240,0x260)
+mpu_port
+    port # for MPU-401 UART (0x300,0x330), -1 = disable
+awe_port
+    base port # for EMU8000 synthesizer (0x620,0x640,0x660) (snd-sbawe
+    module only)
+irq
+    IRQ # for SB DSP 4.x chip (5,7,9,10)
+dma8
+    8-bit DMA # for SB DSP 4.x chip (0,1,3)
+dma16
+    16-bit DMA # for SB DSP 4.x chip (5,6,7)
+
+This module supports multiple cards, autoprobe and ISA PnP.
+
+Note: To use Vibra16X cards in 16-bit half duplex mode, you must
+disable 16bit DMA with dma16 = -1 module parameter.
+Also, all Sound Blaster 16 type cards can operate in 16-bit
+half duplex mode through 8-bit DMA channel by disabling their
+16-bit DMA channel.
+
+The power-management is supported.
+
+Module snd-sc6000
+-----------------
+
+Module for Gallant SC-6000 soundcard and later models: SC-6600 and
+SC-7000.
+
+port
+    Port # (0x220 or 0x240)
+mss_port
+    MSS Port # (0x530 or 0xe80)
+irq
+    IRQ # (5,7,9,10,11)
+mpu_irq
+    MPU-401 IRQ # (5,7,9,10) ,0 - no MPU-401 irq
+dma
+    DMA # (1,3,0)
+joystick
+    Enable gameport - 0 = disable (default), 1 = enable
+
+This module supports multiple cards.
+
+This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
+
+Module snd-sscape
+-----------------
+
+Module for ENSONIQ SoundScape cards.
+
+port
+    Port # (PnP setup)
+wss_port
+    WSS Port # (PnP setup)
+irq
+    IRQ # (PnP setup)
+mpu_irq
+    MPU-401 IRQ # (PnP setup)
+dma
+    DMA # (PnP setup)
+dma2
+    2nd DMA # (PnP setup, -1 to disable)
+joystick
+    Enable gameport - 0 = disable (default), 1 = enable
+
+This module supports multiple cards.
+
+The driver requires the firmware loader support on kernel.
+
+Module snd-sun-amd7930 (on sparc only)
+--------------------------------------
+
+Module for AMD7930 sound chips found on Sparcs.
+
+This module supports multiple cards.
+
+Module snd-sun-cs4231 (on sparc only)
+-------------------------------------
+
+Module for CS4231 sound chips found on Sparcs.
+
+This module supports multiple cards.
+
+Module snd-sun-dbri (on sparc only)
+-----------------------------------
+
+Module for DBRI sound chips found on Sparcs.
+
+This module supports multiple cards.
+
+Module snd-wavefront
+--------------------
+
+Module for Turtle Beach Maui, Tropez and Tropez+ sound cards.
+
+use_cs4232_midi
+    Use CS4232 MPU-401 interface
+    (inaccessibly located inside your computer)
+isapnp
+    ISA PnP detection - 0 = disable, 1 = enable (default)
+
+with isapnp=0, the following options are available:
+
+cs4232_pcm_port
+    Port # for CS4232 PCM interface.
+cs4232_pcm_irq
+    IRQ # for CS4232 PCM interface (5,7,9,11,12,15).
+cs4232_mpu_port
+    Port # for CS4232 MPU-401 interface.
+cs4232_mpu_irq
+    IRQ # for CS4232 MPU-401 interface (9,11,12,15).
+ics2115_port
+    Port # for ICS2115
+ics2115_irq
+    IRQ # for ICS2115
+fm_port
+    FM OPL-3 Port #
+dma1
+    DMA1 # for CS4232 PCM interface.
+dma2
+    DMA2 # for CS4232 PCM interface.
+
+The below are options for wavefront_synth features:
+
+wf_raw
+    Assume that we need to boot the OS (default:no);
+    If yes, then during driver loading, the state of the board is
+    ignored, and we reset the board and load the firmware anyway.
+fx_raw
+    Assume that the FX process needs help (default:yes);
+    If false, we'll leave the FX processor in whatever state it is
+    when the driver is loaded.  The default is to download the
+    microprogram and associated coefficients to set it up for
+    "default" operation, whatever that means.
+debug_default
+    Debug parameters for card initialization
+wait_usecs
+    How long to wait without sleeping, usecs (default:150);
+    This magic number seems to give pretty optimal throughput
+    based on my limited experimentation. 
+    If you want to play around with it and find a better value, be
+    my guest. Remember, the idea is to get a number that causes us
+    to just busy wait for as many WaveFront commands as possible,
+    without coming up with a number so large that we hog the whole
+    CPU. 
+    Specifically, with this number, out of about 134,000 status
+    waits, only about 250 result in a sleep. 
+sleep_interval
+    How long to sleep when waiting for reply (default: 100)
+sleep_tries
+    How many times to try sleeping during a wait (default: 50)
+ospath
+    Pathname to processed ICS2115 OS firmware (default:/*(DEBLOBBED)*/);
+    The path name of the ISC2115 OS firmware.  In the recent
+    version, it's handled via firmware loader framework, so it
+    must be installed in the proper path, typically,
+    /lib/firmware.
+reset_time
+    How long to wait for a reset to take effect (default:2)
+ramcheck_time
+    How many seconds to wait for the RAM test (default:20)
+osrun_time
+    How many seconds to wait for the ICS2115 OS (default:10)
+
+This module supports multiple cards and ISA PnP.
+
+Note: the firmware file ``/*(DEBLOBBED)*/`` was located in the earlier
+version in /etc.  Now it's loaded via firmware loader, and
+must be in the proper firmware path, such as /lib/firmware.
+Copy (or symlink) the file appropriately if you get an error
+regarding firmware downloading after upgrading the kernel.
+
+Module snd-sonicvibes
+---------------------
+
+Module for S3 SonicVibes PCI sound cards.
+* PINE Schubert 32 PCI
+  
+reverb
+    Reverb Enable - 1 = enable, 0 = disable (default);
+    SoundCard must have onboard SRAM for this.
+mge
+    Mic Gain Enable - 1 = enable, 0 = disable (default)
+
+This module supports multiple cards and autoprobe.
+
+Module snd-serial-u16550
+------------------------
+
+Module for UART16550A serial MIDI ports.
+
+port
+    port # for UART16550A chip
+irq
+    IRQ # for UART16550A chip, -1 = poll mode
+speed
+    speed in bauds (9600,19200,38400,57600,115200)
+    38400 = default
+base
+    base for divisor in bauds (57600,115200,230400,460800)
+    115200 = default
+outs
+    number of MIDI ports in a serial port (1-4)
+    1 = default
+adaptor
+    Type of adaptor.
+	0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
+	3 = MS-124W M/B, 4 = Generic
+
+This module supports multiple cards. This module does not support autoprobe
+thus the main port must be specified!!! Other options are optional.
+
+Module snd-trident
+------------------
+
+Module for Trident 4DWave DX/NX sound cards.
+* Best Union  Miss Melody 4DWave PCI
+* HIS  4DWave PCI
+* Warpspeed  ONSpeed 4DWave PCI
+* AzTech  PCI 64-Q3D
+* Addonics  SV 750
+* CHIC  True Sound 4Dwave
+* Shark  Predator4D-PCI
+* Jaton  SonicWave 4D
+* SiS SI7018 PCI Audio
+* Hoontech SoundTrack Digital 4DWave NX
+		    
+pcm_channels
+    max channels (voices) reserved for PCM
+wavetable_size
+    max wavetable size in kB (4-?kb)
+
+This module supports multiple cards and autoprobe.
+
+The power-management is supported.
+
+Module snd-ua101
+----------------
+
+Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.
+
+This module supports multiple devices, autoprobe and hotplugging.
+
+Module snd-usb-audio
+--------------------
+
+Module for USB audio and USB MIDI devices.
+
+vid
+    Vendor ID for the device (optional)
+pid
+    Product ID for the device (optional)
+nrpacks
+    Max. number of packets per URB (default: 8)
+device_setup
+    Device specific magic number (optional);
+    Influence depends on the device
+    Default: 0x0000 
+ignore_ctl_error
+    Ignore any USB-controller regarding mixer interface (default: no)
+autoclock
+    Enable auto-clock selection for UAC2 devices (default: yes)
+quirk_alias
+    Quirk alias list, pass strings like ``0123abcd:5678beef``, which
+    applies the existing quirk for the device 5678:beef to a new
+    device 0123:abcd.
+
+This module supports multiple devices, autoprobe and hotplugging.
+
+NB: ``nrpacks`` parameter can be modified dynamically via sysfs.
+Don't put the value over 20.  Changing via sysfs has no sanity
+check.
+
+NB: ``ignore_ctl_error=1`` may help when you get an error at accessing
+the mixer element such as URB error -22.  This happens on some
+buggy USB device or the controller.
+
+NB: quirk_alias option is provided only for testing / development.
+If you want to have a proper support, contact to upstream for
+adding the matching quirk in the driver code statically.
+
+Module snd-usb-caiaq
+--------------------
+
+Module for caiaq UB audio interfaces,
+
+* Native Instruments RigKontrol2
+* Native Instruments Kore Controller
+* Native Instruments Audio Kontrol 1
+* Native Instruments Audio 8 DJ
+	
+This module supports multiple devices, autoprobe and hotplugging.
+  
+Module snd-usb-usx2y
+--------------------
+
+Module for Tascam USB US-122, US-224 and US-428 devices.
+
+This module supports multiple devices, autoprobe and hotplugging.
+
+Note: you need to load the firmware via ``usx2yloader`` utility included
+in alsa-tools and alsa-firmware packages.
+
+Module snd-via82xx
+------------------
+
+Module for AC'97 motherboards based on VIA 82C686A/686B, 8233, 8233A,
+8233C, 8235, 8237 (south) bridge.
+
+mpu_port
+    0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
+    [VIA686A/686B only]
+joystick
+    Enable joystick (default off) [VIA686A/686B only]
+ac97_clock
+    AC'97 codec clock base (default 48000Hz)
+dxs_support
+    support DXS channels, 0 = auto (default), 1 = enable, 2 = disable,
+    3 = 48k only, 4 = no VRA, 5 = enable any sample rate and different
+    sample rates on different channels [VIA8233/C, 8235, 8237 only]
+ac97_quirk
+    AC'97 workaround for strange hardware;
+    See `AC97 Quirk Option`_ section below.
+
+This module supports one chip and autoprobe.
+
+Note: on some SMP motherboards like MSI 694D the interrupts might
+not be generated properly.  In such a case, please try to
+set the SMP (or MPS) version on BIOS to 1.1 instead of
+default value 1.4.  Then the interrupt number will be
+assigned under 15. You might also upgrade your BIOS.
+
+Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
+channels as the first PCM.  On these channels, up to 4
+streams can be played at the same time, and the controller
+can perform sample rate conversion with separate rates for
+each channel.
+As default (``dxs_support = 0``), 48k fixed rate is chosen
+except for the known devices since the output is often
+noisy except for 48k on some mother boards due to the
+bug of BIOS.
+Please try once ``dxs_support=5`` and if it works on other
+sample rates (e.g. 44.1kHz of mp3 playback), please let us
+know the PCI subsystem vendor/device id's (output of
+``lspci -nv``).
+If ``dxs_support=5`` does not work, try ``dxs_support=4``; if it
+doesn't work too, try dxs_support=1.  (dxs_support=1 is
+usually for old motherboards.  The correct implemented
+board should work with 4 or 5.)  If it still doesn't
+work and the default setting is ok, ``dxs_support=3`` is the
+right choice.  If the default setting doesn't work at all,
+try ``dxs_support=2`` to disable the DXS channels.
+In any cases, please let us know the result and the
+subsystem vendor/device ids.  See `Links and Addresses`_
+below.
+
+Note: for the MPU401 on VIA823x, use snd-mpu401 driver
+additionally.  The mpu_port option is for VIA686 chips only.
+
+The power-management is supported.
+
+Module snd-via82xx-modem
+------------------------
+
+Module for VIA82xx AC97 modem
+
+ac97_clock
+    AC'97 codec clock base (default 48000Hz)
+
+This module supports one card and autoprobe.
+
+Note: The default index value of this module is -2, i.e. the first
+slot is excluded.
+
+The power-management is supported.
+
+Module snd-virmidi
+------------------
+
+Module for virtual rawmidi devices.
+This module creates virtual rawmidi devices which communicate
+to the corresponding ALSA sequencer ports.
+
+midi_devs
+    MIDI devices # (1-4, default=4)
+
+This module supports multiple cards.
+
+Module snd-virtuoso
+-------------------
+
+Module for sound cards based on the Asus AV66/AV100/AV200 chips,
+i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
+Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
+
+This module supports autoprobe and multiple cards.
+
+Module snd-vx222
+----------------
+
+Module for Digigram VX-Pocket VX222, V222 v2 and Mic cards.
+
+mic
+    Enable Microphone on V222 Mic (NYI)
+ibl
+    Capture IBL size. (default = 0, minimum size)
+
+This module supports multiple cards.
+
+When the driver is compiled as a module and the hotplug firmware
+is supported, the firmware data is loaded via hotplug automatically.
+Install the necessary firmware files in alsa-firmware package.
+When no hotplug fw loader is available, you need to load the
+firmware via vxloader utility in alsa-tools package.  To invoke
+vxloader automatically, add the following to /etc/modprobe.d/alsa.conf
+
+::
+
+  install snd-vx222 /sbin/modprobe --first-time -i snd-vx222\
+    && /usr/bin/vxloader
+
+(for 2.2/2.4 kernels, add ``post-install /usr/bin/vxloader`` to
+/etc/modules.conf, instead.)
+IBL size defines the interrupts period for PCM.  The smaller size
+gives smaller latency but leads to more CPU consumption, too.
+The size is usually aligned to 126.  As default (=0), the smallest
+size is chosen.  The possible IBL values can be found in
+/proc/asound/cardX/vx-status proc file.
+
+The power-management is supported.
+
+Module snd-vxpocket
+-------------------
+
+Module for Digigram VX-Pocket VX2 and 440 PCMCIA cards.
+
+ibl
+    Capture IBL size. (default = 0, minimum size)
+
+This module supports multiple cards.  The module is compiled only when
+PCMCIA is supported on kernel.
+
+With the older 2.6.x kernel, to activate the driver via the card
+manager, you'll need to set up /etc/pcmcia/vxpocket.conf.  See the
+sound/pcmcia/vx/vxpocket.c.  2.6.13 or later kernel requires no
+longer require a config file.
+
+When the driver is compiled as a module and the hotplug firmware
+is supported, the firmware data is loaded via hotplug automatically.
+Install the necessary firmware files in alsa-firmware package.
+When no hotplug fw loader is available, you need to load the
+firmware via vxloader utility in alsa-tools package.
+
+About capture IBL, see the description of snd-vx222 module.
+
+Note: snd-vxp440 driver is merged to snd-vxpocket driver since
+ALSA 1.0.10.
+
+The power-management is supported.
+
+Module snd-ymfpci
+-----------------
+
+Module for Yamaha PCI chips (YMF72x, YMF74x & YMF75x).
+
+mpu_port
+    0x300,0x330,0x332,0x334, 0 (disable) by default,
+    1 (auto-detect for YMF744/754 only)
+fm_port
+    0x388,0x398,0x3a0,0x3a8, 0 (disable) by default
+    1 (auto-detect for YMF744/754 only)
+joystick_port
+    0x201,0x202,0x204,0x205, 0 (disable) by default,
+    1 (auto-detect)
+rear_switch
+    enable shared rear/line-in switch (bool)
+
+This module supports autoprobe and multiple chips.
+
+The power-management is supported.
+
+Module snd-pdaudiocf
+--------------------
+
+Module for Sound Core PDAudioCF sound card.
+
+The power-management is supported.
+
+
+AC97 Quirk Option
+=================
+
+The ac97_quirk option is used to enable/override the workaround for
+specific devices on drivers for on-board AC'97 controllers like
+snd-intel8x0.  Some hardware have swapped output pins between Master
+and Headphone, or Surround (thanks to confusion of AC'97
+specifications from version to version :-)
+
+The driver provides the auto-detection of known problematic devices,
+but some might be unknown or wrongly detected.  In such a case, pass
+the proper value with this option.
+
+The following strings are accepted:
+
+default
+    Don't override the default setting
+none
+    Disable the quirk
+hp_only
+    Bind Master and Headphone controls as a single control
+swap_hp
+    Swap headphone and master controls
+swap_surround
+    Swap master and surround controls
+ad_sharing
+    For AD1985, turn on OMS bit and use headphone
+alc_jack
+    For ALC65x, turn on the jack sense mode
+inv_eapd
+    Inverted EAPD implementation
+mute_led
+    Bind EAPD bit for turning on/off mute LED
+
+For backward compatibility, the corresponding integer value -1, 0, ...
+are  accepted, too.
+
+For example, if ``Master`` volume control has no effect on your device
+but only ``Headphone`` does, pass ac97_quirk=hp_only module option.
+
+
+Configuring Non-ISAPNP Cards
+============================
+
+When the kernel is configured with ISA-PnP support, the modules
+supporting the isapnp cards will have module options ``isapnp``.
+If this option is set, *only* the ISA-PnP devices will be probed.
+For probing the non ISA-PnP cards, you have to pass ``isapnp=0`` option
+together with the proper i/o and irq configuration.
+
+When the kernel is configured without ISA-PnP support, isapnp option
+will be not built in.
+
+
+Module Autoloading Support
+==========================
+
+The ALSA drivers can be loaded automatically on demand by defining
+module aliases.  The string ``snd-card-%1`` is requested for ALSA native
+devices where ``%i`` is sound card number from zero to seven.
+
+To auto-load an ALSA driver for OSS services, define the string
+``sound-slot-%i`` where ``%i`` means the slot number for OSS, which
+corresponds to the card index of ALSA.  Usually, define this
+as the same card module.
+
+An example configuration for a single emu10k1 card is like below:
+::
+
+    ----- /etc/modprobe.d/alsa.conf
+    alias snd-card-0 snd-emu10k1
+    alias sound-slot-0 snd-emu10k1
+    ----- /etc/modprobe.d/alsa.conf
+
+The available number of auto-loaded sound cards depends on the module
+option ``cards_limit`` of snd module.  As default it's set to 1.
+To enable the auto-loading of multiple cards, specify the number of
+sound cards in that option.
+
+When multiple cards are available, it'd better to specify the index
+number for each card via module option, too, so that the order of
+cards is kept consistent.
+
+An example configuration for two sound cards is like below:
+::
+
+    ----- /etc/modprobe.d/alsa.conf
+    # ALSA portion
+    options snd cards_limit=2
+    alias snd-card-0 snd-interwave
+    alias snd-card-1 snd-ens1371
+    options snd-interwave index=0
+    options snd-ens1371 index=1
+    # OSS/Free portion
+    alias sound-slot-0 snd-interwave
+    alias sound-slot-1 snd-ens1371
+    ----- /etc/modprobe.d/alsa.conf
+
+In this example, the interwave card is always loaded as the first card
+(index 0) and ens1371 as the second (index 1).
+
+Alternative (and new) way to fixate the slot assignment is to use
+``slots`` option of snd module.  In the case above, specify like the
+following: 
+::
+
+    options snd slots=snd-interwave,snd-ens1371
+
+Then, the first slot (#0) is reserved for snd-interwave driver, and
+the second (#1) for snd-ens1371.  You can omit index option in each
+driver if slots option is used (although you can still have them at
+the same time as long as they don't conflict).
+
+The slots option is especially useful for avoiding the possible
+hot-plugging and the resultant slot conflict.  For example, in the
+case above again, the first two slots are already reserved.  If any
+other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
+snd-ens1371, it will be assigned to the third or later slot.
+
+When a module name is given with '!', the slot will be given for any
+modules but that name.  For example, ``slots=!snd-pcsp`` will reserve
+the first slot for any modules but snd-pcsp. 
+
+
+ALSA PCM devices to OSS devices mapping
+=======================================
+::
+
+    /dev/snd/pcmC0D0[c|p]  -> /dev/audio0 (/dev/audio) -> minor 4
+    /dev/snd/pcmC0D0[c|p]  -> /dev/dsp0 (/dev/dsp)     -> minor 3
+    /dev/snd/pcmC0D1[c|p]  -> /dev/adsp0 (/dev/adsp)   -> minor 12
+    /dev/snd/pcmC1D0[c|p]  -> /dev/audio1              -> minor 4+16 = 20
+    /dev/snd/pcmC1D0[c|p]  -> /dev/dsp1                -> minor 3+16 = 19
+    /dev/snd/pcmC1D1[c|p]  -> /dev/adsp1               -> minor 12+16 = 28
+    /dev/snd/pcmC2D0[c|p]  -> /dev/audio2              -> minor 4+32 = 36
+    /dev/snd/pcmC2D0[c|p]  -> /dev/dsp2                -> minor 3+32 = 39
+    /dev/snd/pcmC2D1[c|p]  -> /dev/adsp2               -> minor 12+32 = 44
+
+The first number from ``/dev/snd/pcmC{X}D{Y}[c|p]`` expression means
+sound card number and second means device number.  The ALSA devices
+have either ``c`` or ``p`` suffix indicating the direction, capture and
+playback, respectively.
+
+Please note that the device mapping above may be varied via the module
+options of snd-pcm-oss module.
+
+
+Proc interfaces (/proc/asound)
+==============================
+
+/proc/asound/card#/pcm#[cp]/oss
+-------------------------------
+erase
+    erase all additional information about OSS applications
+
+<app_name> <fragments> <fragment_size> [<options>]
+    <app_name>
+	name of application with (higher priority) or without path
+    <fragments>
+	 number of fragments or zero if auto
+    <fragment_size>
+	 size of fragment in bytes or zero if auto
+    <options>
+	optional parameters
+
+	disable
+	    the application tries to open a pcm device for
+	    this channel but does not want to use it.
+	    (Cause a bug or mmap needs)
+	    It's good for Quake etc...
+	direct
+	    don't use plugins
+	block
+	     force block mode (rvplayer)
+	non-block
+	    force non-block mode
+	whole-frag
+	    write only whole fragments (optimization affecting
+	    playback only)
+	no-silence
+	    do not fill silence ahead to avoid clicks
+	buggy-ptr
+	    Returns the whitespace blocks in GETOPTR ioctl
+	    instead of filled blocks
+
+Example:
+::
+
+    echo "x11amp 128 16384" > /proc/asound/card0/pcm0p/oss
+    echo "squake 0 0 disable" > /proc/asound/card0/pcm0c/oss
+    echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
+
+
+Early Buffer Allocation
+=======================
+
+Some drivers (e.g. hdsp) require the large contiguous buffers, and
+sometimes it's too late to find such spaces when the driver module is
+actually loaded due to memory fragmentation.  You can pre-allocate the
+PCM buffers by loading snd-page-alloc module and write commands to its
+proc file in prior, for example, in the early boot stage like
+``/etc/init.d/*.local`` scripts.
+
+Reading the proc file /proc/drivers/snd-page-alloc shows the current
+usage of page allocation.  In writing, you can send the following
+commands to the snd-page-alloc driver:
+
+* add VENDOR DEVICE MASK SIZE BUFFERS
+
+VENDOR and DEVICE are PCI vendor and device IDs.  They take
+integer numbers (0x prefix is needed for the hex).
+MASK is the PCI DMA mask.  Pass 0 if not restricted.
+SIZE is the size of each buffer to allocate.  You can pass
+k and m suffix for KB and MB.  The max number is 16MB.
+BUFFERS is the number of buffers to allocate.  It must be greater
+than 0.  The max number is 4.
+
+* erase
+
+This will erase the all pre-allocated buffers which are not in
+use.
+
+
+Links and Addresses
+===================
+
+ALSA project homepage
+    http://www.alsa-project.org
+Kernel Bugzilla
+    http://bugzilla.kernel.org/
+ALSA Developers ML
+    mailto:alsa-devel@alsa-project.org
+alsa-info.sh script
+    http://www.alsa-project.org/alsa-info.sh
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/audigy-mixer.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/audigy-mixer.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/audigy-mixer.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/audigy-mixer.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,368 @@
+=============================================
+Sound Blaster Audigy mixer / default DSP code
+=============================================
+
+This is based on sb-live-mixer.rst.
+
+The EMU10K2 chips have a DSP part which can be programmed to support 
+various ways of sample processing, which is described here.
+(This article does not deal with the overall functionality of the 
+EMU10K2 chips. See the manuals section for further details.)
+
+The ALSA driver programs this portion of chip by default code
+(can be altered later) which offers the following functionality:
+
+
+Digital mixer controls
+======================
+
+These controls are built using the DSP instructions. They offer extended
+functionality. Only the default build-in code in the ALSA driver is described
+here. Note that the controls work as attenuators: the maximum value is the 
+neutral position leaving the signal unchanged. Note that if the  same destination 
+is mentioned in multiple controls, the signal is accumulated and can be wrapped 
+(set to maximal or minimal value without checking of overflow).
+
+
+Explanation of used abbreviations:
+
+DAC
+	digital to analog converter
+ADC
+	analog to digital converter
+I2S
+	one-way three wire serial bus for digital sound by Philips Semiconductors
+        (this standard is used for connecting standalone DAC and ADC converters)
+LFE
+	low frequency effects (subwoofer signal)
+AC97
+	a chip containing an analog mixer, DAC and ADC converters
+IEC958
+	S/PDIF
+FX-bus
+	the EMU10K2 chip has an effect bus containing 64 accumulators.
+        Each of the synthesizer voices can feed its output to these accumulators
+        and the DSP microcontroller can operate with the resulting sum.
+
+name='PCM Front Playback Volume',index=0
+----------------------------------------
+This control is used to attenuate samples for left and right front PCM FX-bus
+accumulators. ALSA uses accumulators 8 and 9 for left and right front PCM 
+samples for 5.1 playback. The result samples are forwarded to the front DAC PCM 
+slots of the Philips DAC.
+
+name='PCM Surround Playback Volume',index=0
+-------------------------------------------
+This control is used to attenuate samples for left and right surround PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right surround PCM 
+samples for 5.1 playback. The result samples are forwarded to the surround DAC PCM 
+slots of the Philips DAC.
+
+name='PCM Center Playback Volume',index=0
+-----------------------------------------
+This control is used to attenuate samples for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample for 5.1 playback. The result sample
+is forwarded to the center DAC PCM slot of the Philips DAC.
+
+name='PCM LFE Playback Volume',index=0
+--------------------------------------
+This control is used to attenuate sample for LFE PCM FX-bus accumulator. 
+ALSA uses accumulator 7 for LFE PCM sample for 5.1 playback. The result sample 
+is forwarded to the LFE DAC PCM slot of the Philips DAC.
+
+name='PCM Playback Volume',index=0
+----------------------------------
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples for
+stereo playback. The result samples are forwarded to the front DAC PCM slots 
+of the Philips DAC.
+
+name='PCM Capture Volume',index=0
+---------------------------------
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Music Playback Volume',index=0
+------------------------------------
+This control is used to attenuate samples for left and right MIDI FX-bus
+accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+name='Music Capture Volume',index=0
+-----------------------------------
+These controls are used to attenuate samples for left and right MIDI FX-bus
+accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Mic Playback Volume',index=0
+----------------------------------
+This control is used to attenuate samples for left and right Mic input.
+For Mic input is used AC97 codec. The result samples are forwarded to 
+the front DAC PCM slots of the Philips DAC. Samples are forwarded to Mic
+capture FIFO (device 1 - 16bit/8KHz mono) too without volume control.
+
+name='Mic Capture Volume',index=0
+---------------------------------
+This control is used to attenuate samples for left and right Mic input.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+name='Audigy CD Playback Volume',index=0
+----------------------------------------
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the Philips DAC.
+
+name='Audigy CD Capture Volume',index=0
+---------------------------------------
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+name='IEC958 Optical Playback Volume',index=0
+---------------------------------------------
+This control is used to attenuate samples from left and right IEC958 optical
+digital input. The result samples are forwarded to the front DAC PCM slots
+of the Philips DAC.
+
+name='IEC958 Optical Capture Volume',index=0
+--------------------------------------------
+This control is used to attenuate samples from left and right IEC958 optical
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+name='Line2 Playback Volume',index=0
+------------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the front
+DAC PCM slots of the Philips DAC.
+
+name='Line2 Capture Volume',index=1
+-----------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Analog Mix Playback Volume',index=0
+-----------------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs from Philips ADC. The result samples are forwarded to the front
+DAC PCM slots of the Philips DAC. This contains mix from analog sources
+like CD, Line In, Aux, ....
+
+name='Analog Mix Capture Volume',index=1
+----------------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs Philips ADC. The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Aux2 Playback Volume',index=0
+-----------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the front
+DAC PCM slots of the Philips DAC.
+
+name='Aux2 Capture Volume',index=1
+----------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the AudigyDrive). The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+name='Front Playback Volume',index=0
+------------------------------------
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate samples for left and right front speakers of
+this mix.
+
+name='Surround Playback Volume',index=0
+---------------------------------------
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate samples for left and right surround speakers of
+this mix.
+
+name='Center Playback Volume',index=0
+-------------------------------------
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate sample for center speaker of this mix.
+
+name='LFE Playback Volume',index=0
+----------------------------------
+All stereo signals are mixed together and mirrored to surround, center and LFE.
+This control is used to attenuate sample for LFE speaker of this mix.
+
+name='Tone Control - Switch',index=0
+------------------------------------
+This control turns the tone control on or off. The samples for front, rear
+and center / LFE outputs are affected.
+
+name='Tone Control - Bass',index=0
+----------------------------------
+This control sets the bass intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='Tone Control - Treble',index=0
+------------------------------------
+This control sets the treble intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+name='Master Playback Volume',index=0
+-------------------------------------
+This control is used to attenuate samples for front, surround, center and 
+LFE outputs.
+
+name='IEC958 Optical Raw Playback Switch',index=0
+-------------------------------------------------
+If this switch is on, then the samples for the IEC958 (S/PDIF) digital
+output are taken only from the raw FX8010 PCM, otherwise standard front
+PCM samples are taken.
+
+
+PCM stream related controls
+===========================
+
+name='EMU10K1 PCM Volume',index 0-31
+------------------------------------
+Channel volume attenuation in range 0-0xffff. The maximum value (no
+attenuation) is default. The channel mapping for three values is
+as follows:
+
+* 0 - mono, default 0xffff (no attenuation)
+* 1 - left, default 0xffff (no attenuation)
+* 2 - right, default 0xffff (no attenuation)
+
+name='EMU10K1 PCM Send Routing',index 0-31
+------------------------------------------
+This control specifies the destination - FX-bus accumulators. There 24
+values with this mapping:
+
+* 0 -  mono, A destination (FX-bus 0-63), default 0
+* 1 -  mono, B destination (FX-bus 0-63), default 1
+* 2 -  mono, C destination (FX-bus 0-63), default 2
+* 3 -  mono, D destination (FX-bus 0-63), default 3
+* 4 -  mono, E destination (FX-bus 0-63), default 0
+* 5 -  mono, F destination (FX-bus 0-63), default 0
+* 6 -  mono, G destination (FX-bus 0-63), default 0
+* 7 -  mono, H destination (FX-bus 0-63), default 0
+* 8 -  left, A destination (FX-bus 0-63), default 0
+* 9 -  left, B destination (FX-bus 0-63), default 1
+* 10 -  left, C destination (FX-bus 0-63), default 2
+* 11 -  left, D destination (FX-bus 0-63), default 3
+* 12 -  left, E destination (FX-bus 0-63), default 0
+* 13 -  left, F destination (FX-bus 0-63), default 0
+* 14 -  left, G destination (FX-bus 0-63), default 0
+* 15 -  left, H destination (FX-bus 0-63), default 0
+* 16 - right, A destination (FX-bus 0-63), default 0
+* 17 - right, B destination (FX-bus 0-63), default 1
+* 18 - right, C destination (FX-bus 0-63), default 2
+* 19 - right, D destination (FX-bus 0-63), default 3
+* 20 - right, E destination (FX-bus 0-63), default 0
+* 21 - right, F destination (FX-bus 0-63), default 0
+* 22 - right, G destination (FX-bus 0-63), default 0
+* 23 - right, H destination (FX-bus 0-63), default 0
+
+Don't forget that it's illegal to assign a channel to the same FX-bus accumulator 
+more than once (it means 0=0 && 1=0 is an invalid combination).
+ 
+name='EMU10K1 PCM Send Volume',index 0-31
+-----------------------------------------
+It specifies the attenuation (amount) for given destination in range 0-255.
+The channel mapping is following:
+
+*  0 -  mono, A destination attn, default 255 (no attenuation)
+*  1 -  mono, B destination attn, default 255 (no attenuation)
+*  2 -  mono, C destination attn, default 0 (mute)
+*  3 -  mono, D destination attn, default 0 (mute)
+*  4 -  mono, E destination attn, default 0 (mute)
+*  5 -  mono, F destination attn, default 0 (mute)
+*  6 -  mono, G destination attn, default 0 (mute)
+*  7 -  mono, H destination attn, default 0 (mute)
+*  8 -  left, A destination attn, default 255 (no attenuation)
+*  9 -  left, B destination attn, default 0 (mute)
+* 10 -  left, C destination attn, default 0 (mute)
+* 11 -  left, D destination attn, default 0 (mute)
+* 12 -  left, E destination attn, default 0 (mute)
+* 13 -  left, F destination attn, default 0 (mute)
+* 14 -  left, G destination attn, default 0 (mute)
+* 15 -  left, H destination attn, default 0 (mute)
+* 16 - right, A destination attn, default 0 (mute)
+* 17 - right, B destination attn, default 255 (no attenuation)
+* 18 - right, C destination attn, default 0 (mute)
+* 19 - right, D destination attn, default 0 (mute)
+* 20 - right, E destination attn, default 0 (mute)
+* 21 - right, F destination attn, default 0 (mute)
+* 22 - right, G destination attn, default 0 (mute)
+* 23 - right, H destination attn, default 0 (mute)
+
+
+
+MANUALS/PATENTS
+===============
+
+ftp://opensource.creative.com/pub/doc
+-------------------------------------
+
+LM4545.pdf
+	AC97 Codec
+
+m2049.pdf
+	The EMU10K1 Digital Audio Processor
+
+hog63.ps
+	FX8010 - A DSP Chip Architecture for Audio Effects
+
+
+WIPO Patents
+------------
+
+WO 9901813 (A1)
+	Audio Effects Processor with multiple asynchronous streams
+	(Jan. 14, 1999)
+
+WO 9901814 (A1)
+	Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
+
+WO 9901953 (A1)
+	Audio Effects Processor having Decoupled Instruction
+        Execution and Audio Data Sequencing (Jan. 14, 1999)
+
+
+US Patents (http://www.uspto.gov/)
+----------------------------------
+
+US 5925841
+	Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
+
+US 5928342
+	Audio Effects Processor integrated on a single chip
+        with a multiport memory onto which multiple asynchronous
+        digital sound samples can be concurrently loaded
+	(Jul. 27, 1999)
+
+US 5930158
+	Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
+
+US 6032235
+	Memory initialization circuit (Tram) (Feb. 29, 2000)
+
+US 6138207
+	Interpolation looping of audio samples in cache connected to
+        system bus with prioritization and modification of bus transfers
+        in accordance with loop ends and minimum block sizes
+	(Oct. 24, 2000)
+
+US 6151670
+	Method for conserving memory storage using a
+        pool of  short term memory registers
+	(Nov. 21, 2000)
+
+US 6195715
+	Interrupt control for multiple programs communicating with
+        a common interrupt by associating programs to GP registers,
+        defining interrupt register, polling GP registers, and invoking
+        callback routine associated with defined interrupt register
+	(Feb. 27, 2001)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/audiophile-usb.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/audiophile-usb.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/audiophile-usb.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/audiophile-usb.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,550 @@
+========================================================
+Guide to using M-Audio Audiophile USB with ALSA and Jack
+========================================================
+
+v1.5
+
+Thibault Le Meur <Thibault.LeMeur@supelec.fr>
+
+This document is a guide to using the M-Audio Audiophile USB (tm) device with 
+ALSA and JACK.
+
+History
+=======
+
+* v1.4 - Thibault Le Meur (2007-07-11)
+
+  - Added Low Endianness nature of 16bits-modes
+    found by Hakan Lennestal <Hakan.Lennestal@brfsodrahamn.se>
+  - Modifying document structure
+
+* v1.5 - Thibault Le Meur (2007-07-12)
+  - Added AC3/DTS passthru info
+
+
+Audiophile USB Specs and correct usage
+======================================
+
+This part is a reminder of important facts about the functions and limitations 
+of the device.
+
+The device has 4 audio interfaces, and 2 MIDI ports:
+
+ * Analog Stereo Input (Ai)
+
+   - This port supports 2 pairs of line-level audio inputs (1/4" TS and RCA) 
+   - When the 1/4" TS (jack) connectors are connected, the RCA connectors
+     are disabled
+
+ * Analog Stereo Output (Ao)
+ * Digital Stereo Input (Di)
+ * Digital Stereo Output (Do)
+ * Midi In (Mi)
+ * Midi Out (Mo)
+
+The internal DAC/ADC has the following characteristics:
+
+* sample depth of 16 or 24 bits
+* sample rate from 8kHz to 96kHz
+* Two interfaces can't use different sample depths at the same time.
+
+Moreover, the Audiophile USB documentation gives the following Warning:
+  Please exit any audio application running before switching between bit depths
+
+Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be 
+activated at the same time depending on the audio mode selected:
+
+ * 16-bit/48kHz ==> 4 channels in + 4 channels out
+
+   - Ai+Ao+Di+Do
+
+ * 24-bit/48kHz ==> 4 channels in + 2 channels out, 
+   or 2 channels in + 4 channels out
+
+   - Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do
+
+ * 24-bit/96kHz ==> 2 channels in _or_ 2 channels out (half duplex only)
+
+   - Ai or Ao or Di or Do
+
+Important facts about the Digital interface:
+--------------------------------------------
+
+ * The Do port additionally supports surround-encoded AC-3 and DTS passthrough, 
+   though I haven't tested it under Linux
+
+   - Note that in this setup only the Do interface can be enabled
+
+ * Apart from recording an audio digital stream, enabling the Di port is a way 
+   to synchronize the device to an external sample clock
+
+   - As a consequence, the Di port must be enable only if an active Digital 
+     source is connected
+   - Enabling Di when no digital source is connected can result in a 
+     synchronization error (for instance sound played at an odd sample rate)
+
+
+Audiophile USB MIDI support in ALSA
+===================================
+
+The Audiophile USB MIDI ports will be automatically supported once the
+following modules have been loaded:
+
+ * snd-usb-audio
+ * snd-seq-midi
+
+No additional setting is required.
+
+
+Audiophile USB Audio support in ALSA
+====================================
+
+Audio functions of the Audiophile USB device are handled by the snd-usb-audio 
+module. This module can work in a default mode (without any device-specific 
+parameter), or in an "advanced" mode with the device-specific parameter called 
+``device_setup``.
+
+Default Alsa driver mode
+------------------------
+
+The default behavior of the snd-usb-audio driver is to list the device 
+capabilities at startup and activate the required mode when required 
+by the applications: for instance if the user is recording in a 
+24bit-depth-mode and immediately after wants to switch to a 16bit-depth mode,
+the snd-usb-audio module will reconfigure the device on the fly.
+
+This approach has the advantage to let the driver automatically switch from sample 
+rates/depths automatically according to the user's needs. However, those who 
+are using the device under windows know that this is not how the device is meant to
+work: under windows applications must be closed before using the m-audio control
+panel to switch the device working mode. Thus as we'll see in next section, this 
+Default Alsa driver mode can lead to device misconfigurations.
+
+Let's get back to the Default Alsa driver mode for now.  In this case the 
+Audiophile interfaces are mapped to alsa pcm devices in the following 
+way (I suppose the device's index is 1):
+
+ * hw:1,0 is Ao in playback and Di in capture
+ * hw:1,1 is Do in playback and Ai in capture
+ * hw:1,2 is Do in AC3/DTS passthrough mode
+
+In this mode, the device uses Big Endian byte-encoding so that 
+supported audio format are S16_BE for 16-bit depth modes and S24_3BE for 
+24-bits depth mode.
+
+One exception is the hw:1,2 port which was reported to be Little Endian 
+compliant (supposedly supporting S16_LE) but processes in fact only S16_BE streams.
+This has been fixed in kernel 2.6.23 and above and now the hw:1,2 interface 
+is reported to be big endian in this default driver mode.
+
+Examples:
+
+ * playing a S24_3BE encoded raw file to the Ao port::
+
+   % aplay -D hw:1,0 -c2 -t raw -r48000 -fS24_3BE test.raw
+
+ * recording a  S24_3BE encoded raw file from the Ai port::
+
+   % arecord -D hw:1,1 -c2  -t raw -r48000 -fS24_3BE test.raw
+
+ * playing a S16_BE encoded raw file to the Do port::
+
+   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw
+
+ * playing an ac3 sample file to the Do port::
+
+   % aplay -D hw:1,2 --channels=6 ac3_S16_BE_encoded_file.raw
+
+If you're happy with the default Alsa driver mode and don't experience any 
+issue with this mode, then you can skip the following chapter.
+
+Advanced module setup
+---------------------
+
+Due to the hardware constraints described above, the device initialization made 
+by the Alsa driver in default mode may result in a corrupted state of the 
+device. For instance, a particularly annoying issue is that the sound captured 
+from the Ai interface sounds distorted (as if boosted with an excessive high
+volume gain).
+
+For people having this problem, the snd-usb-audio module has a new module 
+parameter called ``device_setup`` (this parameter was introduced in kernel
+release 2.6.17)
+
+Initializing the working mode of the Audiophile USB
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As far as the Audiophile USB device is concerned, this value let the user 
+specify:
+
+ * the sample depth
+ * the sample rate
+ * whether the Di port is used or not 
+
+When initialized with ``device_setup=0x00``, the snd-usb-audio module has
+the same behaviour as when the parameter is omitted (see paragraph "Default 
+Alsa driver mode" above)
+
+Others modes are described in the following subsections.
+
+16-bit modes
+~~~~~~~~~~~~
+
+The two supported modes are:
+
+ * ``device_setup=0x01``
+
+   - 16bits 48kHz mode with Di disabled
+   - Ai,Ao,Do can be used at the same time
+   - hw:1,0 is not available in capture mode
+   - hw:1,2 is not available
+
+ * ``device_setup=0x11``
+
+   - 16bits 48kHz mode with Di enabled
+   - Ai,Ao,Di,Do can be used at the same time
+   - hw:1,0 is available in capture mode
+   - hw:1,2 is not available
+
+In this modes the device operates only at 16bits-modes. Before kernel 2.6.23,
+the devices where reported to be Big-Endian when in fact they were Little-Endian
+so that playing a file was a matter of using:
+::
+
+   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test_S16_LE.raw
+
+where "test_S16_LE.raw" was in fact a little-endian sample file.
+
+Thanks to Hakan Lennestal (who discovered the Little-Endiannes of the device in
+these modes) a fix has been committed (expected in kernel 2.6.23) and
+Alsa now reports Little-Endian interfaces. Thus playing a file now is as simple as
+using:
+::
+
+   % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_LE test_S16_LE.raw
+
+
+24-bit modes
+~~~~~~~~~~~~
+
+The three supported modes are:
+
+ * ``device_setup=0x09``
+
+   - 24bits 48kHz mode with Di disabled
+   - Ai,Ao,Do can be used at the same time
+   - hw:1,0 is not available in capture mode
+   - hw:1,2 is not available
+
+ * ``device_setup=0x19``
+
+   - 24bits 48kHz mode with Di enabled
+   - 3 ports from {Ai,Ao,Di,Do} can be used at the same time
+   - hw:1,0 is available in capture mode and an active digital source must be 
+     connected to Di
+   - hw:1,2 is not available
+
+ * ``device_setup=0x0D`` or ``0x10``
+
+   - 24bits 96kHz mode
+   - Di is enabled by default for this mode but does not need to be connected 
+     to an active source
+   - Only 1 port from {Ai,Ao,Di,Do} can be used at the same time
+   - hw:1,0 is available in captured mode
+   - hw:1,2 is not available
+
+In these modes the device is only Big-Endian compliant (see "Default Alsa driver 
+mode" above for an aplay command example)
+
+AC3 w/ DTS passthru mode
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Thanks to Hakan Lennestal, I now have a report saying that this mode works.
+
+ * ``device_setup=0x03``
+
+   - 16bits 48kHz mode with only the Do port enabled 
+   - AC3 with DTS passthru
+   - Caution with this setup the Do port is mapped to the pcm device hw:1,0
+
+The command line used to playback the AC3/DTS encoded .wav-files in this mode:
+::
+
+   % aplay -D hw:1,0 --channels=6 ac3_S16_LE_encoded_file.raw
+
+How to use the ``device_setup`` parameter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The parameter can be given:
+
+ * By manually probing the device (as root):::
+
+   # modprobe -r snd-usb-audio
+   # modprobe snd-usb-audio index=1 device_setup=0x09
+
+ * Or while configuring the modules options in your modules configuration file
+   (typically a .conf file in /etc/modprobe.d/ directory:::
+
+       alias snd-card-1 snd-usb-audio
+       options snd-usb-audio index=1 device_setup=0x09
+
+CAUTION when initializing the device
+-------------------------------------
+
+ * Correct initialization on the device requires that device_setup is given to
+   the module BEFORE the device is turned on. So, if you use the "manual probing"
+   method described above, take care to power-on the device AFTER this initialization.
+
+ * Failing to respect this will lead to a misconfiguration of the device. In this case
+   turn off the device, unprobe the snd-usb-audio module, then probe it again with
+   correct device_setup parameter and then (and only then) turn on the device again.
+
+ * If you've correctly initialized the device in a valid mode and then want to switch
+   to  another mode (possibly with another sample-depth), please use also the following 
+   procedure:
+
+   - first turn off the device
+   - de-register the snd-usb-audio module (modprobe -r)
+   - change the device_setup parameter by changing the device_setup
+     option in ``/etc/modprobe.d/*.conf``
+   - turn on the device
+
+ * A workaround for this last issue has been applied to kernel 2.6.23, but it may not
+   be enough to ensure the 'stability' of the device initialization.
+
+Technical details for hackers
+-----------------------------
+
+This section is for hackers, wanting to understand details about the device
+internals and how Alsa supports it.
+
+Audiophile USB's ``device_setup`` structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you want to understand the device_setup magic numbers for the Audiophile 
+USB, you need some very basic understanding of binary computation. However, 
+this is not required to use the parameter and you may skip this section.
+
+The device_setup is one byte long and its structure is the following:
+::
+
+       +---+---+---+---+---+---+---+---+
+       | b7| b6| b5| b4| b3| b2| b1| b0|
+       +---+---+---+---+---+---+---+---+
+       | 0 | 0 | 0 | Di|24B|96K|DTS|SET|
+       +---+---+---+---+---+---+---+---+
+
+Where:
+
+ * b0 is the ``SET`` bit
+
+   - it MUST be set if device_setup is initialized 
+
+ * b1 is the ``DTS`` bit
+
+   - it is set only for Digital output with DTS/AC3
+   - this setup is not tested
+
+ * b2 is the Rate selection flag
+
+   - When set to ``1`` the rate range is 48.1-96kHz
+   - Otherwise the sample rate range is 8-48kHz
+
+ * b3 is the bit depth selection flag
+
+   - When set to ``1`` samples are 24bits long
+   - Otherwise they are 16bits long
+   - Note that b2 implies b3 as the 96kHz mode is only supported for 24 bits 
+     samples
+
+ * b4 is the Digital input flag
+
+   - When set to ``1`` the device assumes that an active digital source is 
+     connected 
+   - You shouldn't enable Di if no source is seen on the port (this leads to 
+     synchronization issues)
+   - b4 is implied by b2 (since only one port is enabled at a time no synch 
+     error can occur) 
+
+ * b5 to b7 are reserved for future uses, and must be set to ``0``
+
+   - might become Ao, Do, Ai, for b7, b6, b4 respectively
+
+Caution:
+
+ * there is no check on the value you will give to device_setup
+
+   - for instance choosing 0x05 (16bits 96kHz) will fail back to 0x09 since 
+     b2 implies b3. But _there_will_be_no_warning_ in /var/log/messages
+
+ * Hardware constraints due to the USB bus limitation aren't checked
+
+   - choosing b2 will prepare all interfaces for 24bits/96kHz but you'll
+     only be able to use one at the same time
+
+USB implementation details for this device
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You may safely skip this section if you're not interested in driver 
+hacking.
+
+This section describes some internal aspects of the device and summarizes the 
+data I got by usb-snooping the windows and Linux drivers.
+
+The M-Audio Audiophile USB has 7 USB Interfaces:
+a "USB interface":
+
+ * USB Interface nb.0
+ * USB Interface nb.1
+
+   - Audio Control function
+
+ * USB Interface nb.2
+
+   - Analog Output
+
+ * USB Interface nb.3
+
+   - Digital Output
+
+ * USB Interface nb.4
+
+   - Analog Input
+
+ * USB Interface nb.5
+
+   - Digital Input
+
+ * USB Interface nb.6
+
+   - MIDI interface compliant with the MIDIMAN quirk 
+
+Each interface has 5 altsettings (AltSet 1,2,3,4,5) except:
+
+ * Interface 3 (Digital Out) has an extra Alset nb.6 
+ * Interface 5 (Digital In) does not have Alset nb.3 and 5 
+
+Here is a short description of the AltSettings capabilities:
+
+* AltSettings 1 corresponds to
+
+  - 24-bit depth, 48.1-96kHz sample mode
+  - Adaptive playback (Ao and Do), Synch capture (Ai), or Asynch capture (Di)
+
+* AltSettings 2 corresponds to
+
+  - 24-bit depth, 8-48kHz sample mode
+  - Asynch capture and playback  (Ao,Ai,Do,Di)
+
+* AltSettings 3 corresponds to
+
+  - 24-bit depth, 8-48kHz sample mode
+  - Synch capture (Ai) and Adaptive playback (Ao,Do)
+
+* AltSettings 4 corresponds to
+
+  - 16-bit depth, 8-48kHz sample mode
+  - Asynch capture and playback  (Ao,Ai,Do,Di)
+
+* AltSettings 5 corresponds to
+
+  - 16-bit depth, 8-48kHz sample mode
+  - Synch capture (Ai) and Adaptive playback (Ao,Do)
+
+* AltSettings 6 corresponds to
+
+  - 16-bit depth, 8-48kHz sample mode
+  - Synch playback (Do), audio format type III IEC1937_AC-3
+
+In order to ensure a correct initialization of the device, the driver 
+*must* *know* how the device will be used:
+
+ * if DTS is chosen, only Interface 2 with AltSet nb.6 must be
+   registered
+ * if 96KHz only AltSets nb.1 of each interface must be selected
+ * if samples are using 24bits/48KHz then AltSet 2 must me used if
+   Digital input is connected, and only AltSet nb.3 if Digital input
+   is not connected
+ * if samples are using 16bits/48KHz then AltSet 4 must me used if
+   Digital input is connected, and only AltSet nb.5 if Digital input
+   is not connected
+
+When device_setup is given as a parameter to the snd-usb-audio module, the 
+parse_audio_endpoints function uses a quirk called 
+``audiophile_skip_setting_quirk`` in order to prevent AltSettings not 
+corresponding to device_setup from being registered in the driver.
+
+Audiophile USB and Jack support
+===============================
+
+This section deals with support of the Audiophile USB device in Jack.
+
+There are 2 main potential issues when using Jackd with the device:
+
+* support for Big-Endian devices in 24-bit modes
+* support for 4-in / 4-out channels
+
+Direct support in Jackd
+-----------------------
+
+Jack supports big endian devices only in recent versions (thanks to
+Andreas Steinmetz for his first big-endian patch). I can't remember 
+exactly when this support was released into jackd, let's just say that
+with jackd version 0.103.0 it's almost ok (just a small bug is affecting 
+16bits Big-Endian devices, but since you've read carefully the above
+paragraphs, you're now using kernel >= 2.6.23 and your 16bits devices 
+are now Little Endians ;-) ).
+
+You can run jackd with the following command for playback with Ao and
+record with Ai:
+::
+
+  % jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1
+
+Using Alsa plughw
+-----------------
+
+If you don't have a recent Jackd installed, you can downgrade to using
+the Alsa ``plug`` converter.
+
+For instance here is one way to run Jack with 2 playback channels on Ao and 2 
+capture channels from Ai:
+::
+
+  % jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1
+
+However you may see the following warning message:
+  You appear to be using the ALSA software "plug" layer, probably a result of 
+  using the "default" ALSA device. This is less efficient than it could be. 
+  Consider using a hardware device instead rather than using the plug layer.
+
+Getting 2 input and/or output interfaces in Jack
+------------------------------------------------
+
+As you can see, starting the Jack server this way will only enable 1 stereo
+input (Di or Ai) and 1 stereo output (Ao or Do).
+
+This is due to the following restrictions:
+
+* Jack can only open one capture device and one playback device at a time
+* The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1
+  (and optionally hw:1,2)
+
+If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to
+combine the Alsa devices into one logical "complex" device.
+
+If you want to give it a try, I recommend reading the information from
+this page: http://www.sound-man.co.uk/linuxaudio/ice1712multi.html
+It is related to another device (ice1712) but can be adapted to suit
+the Audiophile USB.
+
+Enabling multiple Audiophile USB interfaces for Jackd will certainly require:
+
+* Making sure your Jackd version has the MMAP_COMPLEX patch (see the ice1712 page)
+* (maybe) patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page)
+* define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc
+  file 
+* start jackd with this device
+
+I had no success in testing this for now, if you have any success with this kind 
+of setup, please drop me an email.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/bt87x.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/bt87x.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/bt87x.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/bt87x.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,83 @@
+=================
+ALSA BT87x Driver
+=================
+
+Intro
+=====
+
+You might have noticed that the bt878 grabber cards have actually
+*two* PCI functions:
+::
+
+  $ lspci
+  [ ... ]
+  00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02)
+  00:0a.1 Multimedia controller: Brooktree Corporation Bt878 (rev 02)
+  [ ... ]
+
+The first does video, it is backward compatible to the bt848.  The second
+does audio.  snd-bt87x is a driver for the second function.  It's a sound
+driver which can be used for recording sound (and *only* recording, no
+playback).  As most TV cards come with a short cable which can be plugged
+into your sound card's line-in you probably don't need this driver if all
+you want to do is just watching TV...
+
+Some cards do not bother to connect anything to the audio input pins of
+the chip, and some other cards use the audio function to transport MPEG
+video data, so it's quite possible that audio recording may not work
+with your card.
+
+
+Driver Status
+=============
+
+The driver is now stable.  However, it doesn't know about many TV cards,
+and it refuses to load for cards it doesn't know.
+
+If the driver complains ("Unknown TV card found, the audio driver will
+not load"), you can specify the ``load_all=1`` option to force the driver to
+try to use the audio capture function of your card.  If the frequency of
+recorded data is not right, try to specify the ``digital_rate`` option with
+other values than the default 32000 (often it's 44100 or 64000).
+
+If you have an unknown card, please mail the ID and board name to
+<alsa-devel@alsa-project.org>, regardless of whether audio capture works
+or not, so that future versions of this driver know about your card.
+
+
+Audio modes
+===========
+
+The chip knows two different modes (digital/analog).  snd-bt87x
+registers two PCM devices, one for each mode.  They cannot be used at
+the same time.
+
+
+Digital audio mode
+==================
+
+The first device (hw:X,0) gives you 16 bit stereo sound.  The sample
+rate depends on the external source which feeds the Bt87x with digital
+sound via I2S interface.
+
+
+Analog audio mode (A/D)
+=======================
+
+The second device (hw:X,1) gives you 8 or 16 bit mono sound.  Supported
+sample rates are between 119466 and 448000 Hz (yes, these numbers are
+that high).  If you've set the CONFIG_SND_BT87X_OVERCLOCK option, the
+maximum sample rate is 1792000 Hz, but audio data becomes unusable
+beyond 896000 Hz on my card.
+
+The chip has three analog inputs.  Consequently you'll get a mixer
+device to control these.
+
+
+Have fun,
+
+  Clemens
+
+
+Written by Clemens Ladisch <clemens@ladisch.de>
+big parts copied from btaudio.txt by Gerd Knorr <kraxel@bytesex.org>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/cmipci.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/cmipci.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/cmipci.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/cmipci.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,272 @@
+=================================================
+Brief Notes on C-Media 8338/8738/8768/8770 Driver
+=================================================
+
+Takashi Iwai <tiwai@suse.de>
+
+
+Front/Rear Multi-channel Playback
+---------------------------------
+
+CM8x38 chip can use ADC as the second DAC so that two different stereo
+channels can be used for front/rear playbacks.  Since there are two
+DACs, both streams are handled independently unlike the 4/6ch multi-
+channel playbacks in the section below.
+
+As default, ALSA driver assigns the first PCM device (i.e. hw:0,0 for
+card#0) for front and 4/6ch playbacks, while the second PCM device
+(hw:0,1) is assigned to the second DAC for rear playback.
+
+There are slight differences between the two DACs:
+
+- The first DAC supports U8 and S16LE formats, while the second DAC
+  supports only S16LE.
+- The second DAC supports only two channel stereo.
+
+Please note that the CM8x38 DAC doesn't support continuous playback
+rate but only fixed rates: 5512, 8000, 11025, 16000, 22050, 32000,
+44100 and 48000 Hz.
+
+The rear output can be heard only when "Four Channel Mode" switch is
+disabled.  Otherwise no signal will be routed to the rear speakers.
+As default it's turned on.
+
+.. WARNING::
+  When "Four Channel Mode" switch is off, the output from rear speakers
+  will be FULL VOLUME regardless of Master and PCM volumes [#]_.
+  This might damage your audio equipment.  Please disconnect speakers
+  before your turn off this switch.
+
+
+.. [#]
+  Well.. I once got the output with correct volume (i.e. same with the
+  front one) and was so excited.  It was even with "Four Channel" bit
+  on and "double DAC" mode.  Actually I could hear separate 4 channels
+  from front and rear speakers!  But.. after reboot, all was gone.
+  It's a very pity that I didn't save the register dump at that
+  time..  Maybe there is an unknown register to achieve this...
+
+If your card has an extra output jack for the rear output, the rear
+playback should be routed there as default.  If not, there is a
+control switch in the driver "Line-In As Rear", which you can change
+via alsamixer or somewhat else.  When this switch is on, line-in jack
+is used as rear output.
+
+There are two more controls regarding to the rear output.
+The "Exchange DAC" switch is used to exchange front and rear playback
+routes, i.e. the 2nd DAC is output from front output.
+
+
+4/6 Multi-Channel Playback
+--------------------------
+
+The recent CM8738 chips support for the 4/6 multi-channel playback
+function.  This is useful especially for AC3 decoding.
+
+When the multi-channel is supported, the driver name has a suffix
+"-MC" such like "CMI8738-MC6".  You can check this name from
+/proc/asound/cards.
+
+When the 4/6-ch output is enabled, the second DAC accepts up to 6 (or
+4) channels.  While the dual DAC supports two different rates or
+formats, the 4/6-ch playback supports only the same condition for all
+channels.  Since the multi-channel playback mode uses both DACs, you
+cannot operate with full-duplex.
+
+The 4.0 and 5.1 modes are defined as the pcm "surround40" and "surround51"
+in alsa-lib.  For example, you can play a WAV file with 6 channels like
+::
+
+	% aplay -Dsurround51 sixchannels.wav
+
+For programming the 4/6 channel playback, you need to specify the PCM
+channels as you like and set the format S16LE.  For example, for playback
+with 4 channels,
+::
+
+	snd_pcm_hw_params_set_access(pcm, hw, SND_PCM_ACCESS_RW_INTERLEAVED);
+	    // or mmap if you like
+	snd_pcm_hw_params_set_format(pcm, hw, SND_PCM_FORMAT_S16_LE);
+	snd_pcm_hw_params_set_channels(pcm, hw, 4);
+
+and use the interleaved 4 channel data.
+
+There are some control switches affecting to the speaker connections:
+
+Line-In Mode
+	an enum control to change the behavior of line-in
+	jack.  Either "Line-In", "Rear Output" or "Bass Output" can
+	be selected.  The last item is available only with model 039
+	or newer. 
+	When "Rear Output" is chosen, the surround channels 3 and 4
+	are output to line-in jack.
+Mic-In Mode
+	an enum control to change the behavior of mic-in
+	jack.  Either "Mic-In" or "Center/LFE Output" can be
+	selected. 
+	When "Center/LFE Output" is chosen, the center and bass
+	channels (channels 5 and 6) are output to mic-in jack. 
+
+Digital I/O
+-----------
+
+The CM8x38 provides the excellent SPDIF capability with very cheap
+price (yes, that's the reason I bought the card :)
+
+The SPDIF playback and capture are done via the third PCM device
+(hw:0,2).  Usually this is assigned to the PCM device "spdif".
+The available rates are 44100 and 48000 Hz.
+For playback with aplay, you can run like below:
+::
+
+	% aplay -Dhw:0,2 foo.wav
+
+or
+
+::
+
+	% aplay -Dspdif foo.wav
+
+24bit format is also supported experimentally.
+
+The playback and capture over SPDIF use normal DAC and ADC,
+respectively, so you cannot playback both analog and digital streams
+simultaneously.
+
+To enable SPDIF output, you need to turn on "IEC958 Output Switch"
+control via mixer or alsactl ("IEC958" is the official name of
+so-called S/PDIF).  Then you'll see the red light on from the card so
+you know that's working obviously :)
+The SPDIF input is always enabled, so you can hear SPDIF input data
+from line-out with "IEC958 In Monitor" switch at any time (see
+below).
+
+You can play via SPDIF even with the first device (hw:0,0),
+but SPDIF is enabled only when the proper format (S16LE), sample rate
+(441100 or 48000) and channels (2) are used.  Otherwise it's turned
+off.  (Also don't forget to turn on "IEC958 Output Switch", too.)
+
+
+Additionally there are relevant control switches:
+
+IEC958 Mix Analog
+	Mix analog PCM playback and FM-OPL/3 streams and
+	output through SPDIF.  This switch appears only on old chip
+	models (CM8738 033 and 037).
+
+	Note: without this control you can output PCM to SPDIF.
+	This is "mixing" of streams, so e.g. it's not for AC3 output
+	(see the next section).
+
+IEC958 In Select
+	Select SPDIF input, the internal CD-in (false)
+	and the external input (true).
+
+IEC958 Loop
+	SPDIF input data is loop back into SPDIF
+	output (aka bypass)
+
+IEC958 Copyright
+	Set the copyright bit.
+
+IEC958 5V
+	Select 0.5V (coax) or 5V (optical) interface.
+	On some cards this doesn't work and you need to change the
+	configuration with hardware dip-switch.
+
+IEC958 In Monitor
+	SPDIF input is routed to DAC.
+
+IEC958 In Phase Inverse
+	Set SPDIF input format as inverse.
+	[FIXME: this doesn't work on all chips..]
+
+IEC958 In Valid
+	Set input validity flag detection.
+
+Note: When "PCM Playback Switch" is on, you'll hear the digital output
+stream through analog line-out.
+
+
+The AC3 (RAW DIGITAL) OUTPUT
+----------------------------
+
+The driver supports raw digital (typically AC3) i/o over SPDIF.  This
+can be toggled via IEC958 playback control, but usually you need to
+access it via alsa-lib.  See alsa-lib documents for more details.
+
+On the raw digital mode, the "PCM Playback Switch" is automatically
+turned off so that non-audio data is heard from the analog line-out.
+Similarly the following switches are off: "IEC958 Mix Analog" and
+"IEC958 Loop".  The switches are resumed after closing the SPDIF PCM
+device automatically to the previous state.
+
+On the model 033, AC3 is implemented by the software conversion in
+the alsa-lib.  If you need to bypass the software conversion of IEC958
+subframes, pass the "soft_ac3=0" module option.  This doesn't matter
+on the newer models.
+
+
+ANALOG MIXER INTERFACE
+----------------------
+
+The mixer interface on CM8x38 is similar to SB16.
+There are Master, PCM, Synth, CD, Line, Mic and PC Speaker playback
+volumes.  Synth, CD, Line and Mic have playback and capture switches,
+too, as well as SB16.
+
+In addition to the standard SB mixer, CM8x38 provides more functions.
+- PCM playback switch
+- PCM capture switch (to capture the data sent to DAC)
+- Mic Boost switch
+- Mic capture volume
+- Aux playback volume/switch and capture switch
+- 3D control switch
+
+
+MIDI CONTROLLER
+---------------
+
+With CMI8338 chips, the MPU401-UART interface is disabled as default.
+You need to set the module option "mpu_port" to a valid I/O port address
+to enable MIDI support.  Valid I/O ports are 0x300, 0x310, 0x320 and
+0x330.  Choose a value that doesn't conflict with other cards.
+
+With CMI8738 and newer chips, the MIDI interface is enabled by default
+and the driver automatically chooses a port address.
+
+There is *no* hardware wavetable function on this chip (except for
+OPL3 synth below).
+What's said as MIDI synth on Windows is a software synthesizer
+emulation.  On Linux use TiMidity or other softsynth program for
+playing MIDI music.
+
+
+FM OPL/3 Synth
+--------------
+
+The FM OPL/3 is also enabled as default only for the first card.
+Set "fm_port" module option for more cards.
+
+The output quality of FM OPL/3 is, however, very weird.
+I don't know why..
+
+CMI8768 and newer chips do not have the FM synth.
+
+
+Joystick and Modem
+------------------
+
+The legacy joystick is supported.  To enable the joystick support, pass
+joystick_port=1 module option.  The value 1 means the auto-detection.
+If the auto-detection fails, try to pass the exact I/O address.
+
+The modem is enabled dynamically via a card control switch "Modem".
+
+
+Debugging Information
+---------------------
+
+The registers are shown in /proc/asound/cardX/cmipci.  If you have any
+problem (especially unexpected behavior of mixer), please attach the
+output of this proc file together with the bug report.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/emu10k1-jack.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/emu10k1-jack.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/emu10k1-jack.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/emu10k1-jack.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,78 @@
+=================================================================
+Low latency, multichannel audio with JACK and the emu10k1/emu10k2
+=================================================================
+
+This document is a guide to using the emu10k1 based devices with JACK for low
+latency, multichannel recording functionality.  All of my recent work to allow
+Linux users to use the full capabilities of their hardware has been inspired 
+by the kX Project.  Without their work I never would have discovered the true
+power of this hardware.
+
+	http://www.kxproject.com
+						- Lee Revell, 2005.03.30
+
+
+Until recently, emu10k1 users on Linux did not have access to the same low
+latency, multichannel features offered by the "kX ASIO" feature of their
+Windows driver.  As of ALSA 1.0.9 this is no more!
+
+For those unfamiliar with kX ASIO, this consists of 16 capture and 16 playback
+channels.  With a post 2.6.9 Linux kernel, latencies down to 64 (1.33 ms) or
+even 32 (0.66ms) frames should work well.
+
+The configuration is slightly more involved than on Windows, as you have to
+select the correct device for JACK to use.  Actually, for qjackctl users it's
+fairly self explanatory - select Duplex, then for capture and playback select
+the multichannel devices, set the in and out channels to 16, and the sample
+rate to 48000Hz.  The command line looks like this:
+::
+
+  /usr/local/bin/jackd -R -dalsa -r48000 -p64 -n2 -D -Chw:0,2 -Phw:0,3 -S
+
+This will give you 16 input ports and 16 output ports.
+
+The 16 output ports map onto the 16 FX buses (or the first 16 of 64, for the
+Audigy).  The mapping from FX bus to physical output is described in
+sb-live-mixer.rst (or audigy-mixer.rst).
+
+The 16 input ports are connected to the 16 physical inputs.  Contrary to
+popular belief, all emu10k1 cards are multichannel cards.  Which of these
+input channels have physical inputs connected to them depends on the card
+model.  Trial and error is highly recommended; the pinout diagrams
+for the card have been reverse engineered by some enterprising kX users and are 
+available on the internet.  Meterbridge is helpful here, and the kX forums are
+packed with useful information.
+
+Each input port will either correspond to a digital (SPDIF) input, an analog
+input, or nothing.  The one exception is the SBLive! 5.1.  On these devices,
+the second and third input ports are wired to the center/LFE output.  You will
+still see 16 capture channels, but only 14 are available for recording inputs.
+
+This chart, borrowed from kxfxlib/da_asio51.cpp, describes the mapping of JACK
+ports to FXBUS2 (multitrack recording input) and EXTOUT (physical output)
+channels.
+
+JACK (& ASIO) mappings on 10k1 5.1 SBLive cards:
+
+==============  ========        ============
+JACK		Epilog		FXBUS2(nr)
+==============  ========        ============
+capture_1	asio14		FXBUS2(0xe)
+capture_2	asio15		FXBUS2(0xf)
+capture_3	asio0		FXBUS2(0x0)	
+~capture_4	Center		EXTOUT(0x11)	// mapped to by Center
+~capture_5	LFE		EXTOUT(0x12)	// mapped to by LFE
+capture_6	asio3		FXBUS2(0x3)
+capture_7	asio4		FXBUS2(0x4)
+capture_8	asio5		FXBUS2(0x5)
+capture_9	asio6		FXBUS2(0x6)
+capture_10	asio7		FXBUS2(0x7)
+capture_11	asio8		FXBUS2(0x8)
+capture_12	asio9		FXBUS2(0x9)
+capture_13	asio10		FXBUS2(0xa)
+capture_14	asio11		FXBUS2(0xb)
+capture_15	asio12		FXBUS2(0xc)
+capture_16	asio13		FXBUS2(0xd)
+==============  ========        ============
+
+TODO: describe use of ld10k1/qlo10k1 in conjunction with JACK
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/hdspm.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/hdspm.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/hdspm.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/hdspm.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,379 @@
+=======================================
+Software Interface ALSA-DSP MADI Driver 
+=======================================
+
+(translated from German, so no good English ;-), 
+
+2004 - winfried ritsch
+
+
+Full functionality has been added to the driver. Since some of
+the Controls and startup-options  are ALSA-Standard and only the
+special Controls are described and discussed below.
+
+
+Hardware functionality
+======================
+   
+Audio transmission
+------------------
+
+* number of channels --  depends on transmission mode
+
+		The number of channels chosen is from 1..Nmax. The reason to
+		use for a lower number of channels is only resource allocation,
+		since unused DMA channels are disabled and less memory is
+		allocated. So also the throughput of the PCI system can be
+		scaled. (Only important for low performance boards).
+
+* Single Speed -- 1..64 channels 
+
+.. note::
+		 (Note: Choosing the 56channel mode for transmission or as
+		 receiver, only 56 are transmitted/received over the MADI, but
+		 all 64 channels are available for the mixer, so channel count
+		 for the driver)
+
+* Double Speed -- 1..32 channels
+
+.. note::
+		 Note: Choosing the 56-channel mode for
+		 transmission/receive-mode , only 28 are transmitted/received
+		 over the MADI, but all 32 channels are available for the mixer,
+		 so channel count for the driver
+
+
+* Quad Speed -- 1..16 channels 
+
+.. note::
+		 Choosing the 56-channel mode for
+		 transmission/receive-mode , only 14 are transmitted/received
+		 over the MADI, but all 16 channels are available for the mixer,
+		 so channel count for the driver
+
+* Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
+
+* Sample Rates --
+
+       Single Speed -- 32000, 44100, 48000
+
+       Double Speed -- 64000, 88200, 96000 (untested)
+
+       Quad Speed -- 128000, 176400, 192000 (untested)
+
+* access-mode -- MMAP (memory mapped), Not interleaved (PCM_NON-INTERLEAVED)
+
+* buffer-sizes -- 64,128,256,512,1024,2048,8192 Samples
+
+* fragments -- 2
+
+* Hardware-pointer -- 2 Modi
+
+
+		 The Card supports the readout of the actual Buffer-pointer,
+		 where DMA reads/writes. Since of the bulk mode of PCI it is only
+		 64 Byte accurate. SO it is not really usable for the
+		 ALSA-mid-level functions (here the buffer-ID gives a better
+		 result), but if MMAP is used by the application. Therefore it
+		 can be configured at load-time with the parameter
+		 precise-pointer.
+
+
+.. hint::
+		 (Hint: Experimenting I found that the pointer is maximum 64 to
+		 large never to small. So if you subtract 64 you always have a
+		 safe pointer for writing, which is used on this mode inside
+		 ALSA. In theory now you can get now a latency as low as 16
+		 Samples, which is a quarter of the interrupt possibilities.)
+
+   * Precise Pointer -- off
+					interrupt used for pointer-calculation
+				
+   * Precise Pointer -- on
+					hardware pointer used.
+
+Controller
+----------
+
+Since DSP-MADI-Mixer has 8152 Fader, it does not make sense to
+use the standard mixer-controls, since this would break most of
+(especially graphic) ALSA-Mixer GUIs. So Mixer control has be
+provided by a 2-dimensional controller using the
+hwdep-interface. 
+
+Also all 128+256 Peak and RMS-Meter can be accessed via the
+hwdep-interface. Since it could be a performance problem always
+copying and converting Peak and RMS-Levels even if you just need
+one, I decided to export the hardware structure, so that of
+needed some driver-guru can implement a memory-mapping of mixer
+or peak-meters over ioctl, or also to do only copying and no
+conversion. A test-application shows the usage of the controller.
+
+* Latency Controls --- not implemented !!!
+
+.. note::
+	   Note: Within the windows-driver the latency is accessible of a
+	   control-panel, but buffer-sizes are controlled with ALSA from
+	   hwparams-calls and should not be changed in run-state, I did not
+	   implement it here.
+
+
+* System Clock -- suspended !!!!
+
+  * Name -- "System Clock Mode"
+
+  * Access -- Read Write
+    
+  * Values -- "Master" "Slave"
+
+.. note::
+		  !!!! This is a hardware-function but is in conflict with the
+		  Clock-source controller, which is a kind of ALSA-standard. I
+		  makes sense to set the card to a special mode (master at some
+		  frequency or slave), since even not using an Audio-application
+		  a studio should have working synchronisations setup. So use
+		  Clock-source-controller instead !!!!
+
+* Clock Source  
+
+  * Name -- "Sample Clock Source"
+
+  * Access -- Read Write
+
+  * Values -- "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
+    "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
+    "Internal 96.0 kHz"
+
+		 Choose between Master at a specific Frequency and so also the
+		 Speed-mode or Slave (Autosync). Also see  "Preferred Sync Ref"
+
+.. warning::
+       !!!! This is no pure hardware function but was implemented by
+       ALSA by some ALSA-drivers before, so I use it also. !!!
+
+
+* Preferred Sync Ref
+
+  * Name -- "Preferred Sync Reference"
+
+  * Access -- Read Write
+
+  * Values -- "Word" "MADI"
+
+
+		 Within the Auto-sync-Mode the preferred Sync Source can be
+		 chosen. If it is not available another is used if possible.
+
+.. note::
+		 Note: Since MADI has a much higher bit-rate than word-clock, the
+		 card should synchronise better in MADI Mode. But since the
+		 RME-PLL is very good, there are almost no problems with
+		 word-clock too. I never found a difference.
+
+
+* TX 64 channel
+
+  * Name -- "TX 64 channels mode"
+
+  * Access -- Read Write
+
+  * Values -- 0 1
+
+		 Using 64-channel-modus (1) or 56-channel-modus for
+		 MADI-transmission (0).
+
+
+.. note::
+		 Note: This control is for output only. Input-mode is detected
+		 automatically from hardware sending MADI.
+
+
+* Clear TMS
+
+  * Name -- "Clear Track Marker"
+
+  * Access -- Read Write
+
+  * Values -- 0 1
+
+
+		 Don't use to lower 5 Audio-bits on AES as additional Bits.
+        
+
+* Safe Mode oder Auto Input
+
+  * Name -- "Safe Mode"
+
+  * Access -- Read Write
+
+  * Values -- 0 1 (default on)
+
+		 If on (1), then if either the optical or coaxial connection
+		 has a failure, there is a takeover to the working one, with no
+		 sample failure. Its only useful if you use the second as a
+		 backup connection.
+
+* Input
+
+  * Name -- "Input Select"
+
+  * Access -- Read Write
+
+  * Values -- optical coaxial
+
+
+		 Choosing the Input, optical or coaxial. If Safe-mode is active,
+		 this is the preferred Input.
+
+Mixer
+-----
+
+* Mixer
+
+  * Name -- "Mixer"
+
+  * Access -- Read Write
+
+  * Values - <channel-number 0-127> <Value 0-65535>
+
+
+		 Here as a first value the channel-index is taken to get/set the
+		 corresponding mixer channel, where 0-63 are the input to output
+		 fader and 64-127 the playback to outputs fader. Value 0
+		 is channel muted 0 and 32768 an amplification of  1.
+
+* Chn 1-64
+
+       fast mixer for the ALSA-mixer utils. The diagonal of the
+       mixer-matrix is implemented from playback to output.
+       
+
+* Line Out
+
+  * Name  -- "Line Out"
+
+  * Access -- Read Write
+
+  * Values -- 0 1
+
+		 Switching on and off the analog out, which has nothing to do
+		 with mixing or routing. the analog outs reflects channel 63,64.
+
+
+Information (only read access)
+------------------------------
+ 
+* Sample Rate
+
+  * Name -- "System Sample Rate"
+
+  * Access -- Read-only
+
+		 getting the sample rate.
+
+
+* External Rate measured
+
+  * Name -- "External Rate"
+
+  * Access -- Read only
+
+
+		 Should be "Autosync Rate", but Name used is
+		 ALSA-Scheme. External Sample frequency liked used on Autosync is
+		 reported.
+
+
+* MADI Sync Status
+
+  * Name -- "MADI Sync Lock Status"
+
+  * Access -- Read
+
+  * Values -- 0,1,2
+
+       MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+
+* Word Clock Sync Status
+
+  * Name -- "Word Clock Lock Status"
+
+  * Access -- Read
+
+  * Values -- 0,1,2
+
+       Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+* AutoSync
+
+  * Name -- "AutoSync Reference"
+
+  * Access -- Read
+
+  * Values -- "WordClock", "MADI", "None"
+
+		 Sync-Reference is either "WordClock", "MADI" or none.
+
+* RX 64ch --- noch nicht implementiert
+
+       MADI-Receiver is in 64 channel mode oder 56 channel mode.
+
+
+* AB_inp   --- not tested 
+
+		 Used input for Auto-Input.
+
+
+* actual Buffer Position --- not implemented
+
+	   !!! this is a ALSA internal function, so no control is used !!!
+
+
+
+Calling Parameter
+=================
+
+* index int array (min = 1, max = 8) 
+
+     Index value for RME HDSPM interface. card-index within ALSA
+
+     note: ALSA-standard
+
+* id string array (min = 1, max = 8) 
+
+     ID string for RME HDSPM interface.
+
+     note: ALSA-standard
+
+* enable int array (min = 1, max = 8)
+
+     Enable/disable specific HDSPM sound-cards.
+
+     note: ALSA-standard
+
+* precise_ptr int array (min = 1, max = 8)
+
+     Enable precise pointer, or disable.
+
+.. note::
+     note: Use only when the application supports this (which is a special case).
+
+* line_outs_monitor int array (min = 1, max = 8)
+
+     Send playback streams to analog outs by default.
+
+.. note::
+	  note: each playback channel is mixed to the same numbered output
+	  channel (routed). This is against the ALSA-convention, where all
+	  channels have to be muted on after loading the driver, but was
+	  used before on other cards, so i historically use it again)
+
+
+
+* enable_monitor int array (min = 1, max = 8)
+
+     Enable Analog Out on Channel 63/64 by default.
+
+.. note ::
+      note: here the analog output is enabled (but not routed).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/img-spdif-in.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/img-spdif-in.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/img-spdif-in.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/img-spdif-in.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,53 @@
+================================================
+Imagination Technologies SPDIF Input Controllers
+================================================
+
+The Imagination Technologies SPDIF Input controller contains the following
+controls:
+
+* name='IEC958 Capture Mask',index=0
+
+This control returns a mask that shows which of the IEC958 status bits
+can be read using the 'IEC958 Capture Default' control.
+
+* name='IEC958 Capture Default',index=0
+
+This control returns the status bits contained within the SPDIF stream that
+is being received. The 'IEC958 Capture Mask' shows which bits can be read
+from this control.
+
+* name='SPDIF In Multi Frequency Acquire',index=0
+* name='SPDIF In Multi Frequency Acquire',index=1
+* name='SPDIF In Multi Frequency Acquire',index=2
+* name='SPDIF In Multi Frequency Acquire',index=3
+
+This control is used to attempt acquisition of up to four different sample
+rates. The active rate can be obtained by reading the 'SPDIF In Lock Frequency'
+control.
+
+When the value of this control is set to {0,0,0,0}, the rate given to hw_params
+will determine the single rate the block will capture. Else, the rate given to
+hw_params will be ignored, and the block will attempt capture for each of the
+four sample rates set here.
+
+If less than four rates are required, the same rate can be specified more than
+once
+
+* name='SPDIF In Lock Frequency',index=0
+
+This control returns the active capture rate, or 0 if a lock has not been
+acquired
+
+* name='SPDIF In Lock TRK',index=0
+
+This control is used to modify the locking/jitter rejection characteristics
+of the block. Larger values increase the locking range, but reduce jitter
+rejection.
+
+* name='SPDIF In Lock Acquire Threshold',index=0
+
+This control is used to change the threshold at which a lock is acquired.
+
+* name='SPDIF In Lock Release Threshold',index=0
+
+This control is used to change the threshold at which a lock is released.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/index.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/index.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,19 @@
+Card-Specific Information
+=========================
+
+.. toctree::
+   :maxdepth: 2
+
+   joystick
+   cmipci
+   sb-live-mixer
+   audigy-mixer
+   emu10k1-jack
+   via82xx-mixer
+   audiophile-usb
+   mixart
+   bt87x
+   maya44
+   hdspm
+   serial-u16550
+   img-spdif-in
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/joystick.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/joystick.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/joystick.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/joystick.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,91 @@
+=======================================
+Analog Joystick Support on ALSA Drivers
+=======================================
+
+Oct. 14, 2003
+
+Takashi Iwai <tiwai@suse.de>
+
+General
+-------
+
+First of all, you need to enable GAMEPORT support on Linux kernel for
+using a joystick with the ALSA driver.  For the details of gameport
+support, refer to Documentation/input/joystick.txt.
+
+The joystick support of ALSA drivers is different between ISA and PCI
+cards.  In the case of ISA (PnP) cards, it's usually handled by the
+independent module (ns558).  Meanwhile, the ALSA PCI drivers have the
+built-in gameport support.  Hence, when the ALSA PCI driver is built
+in the kernel, CONFIG_GAMEPORT must be 'y', too.  Otherwise, the
+gameport support on that card will be (silently) disabled.
+
+Some adapter modules probe the physical connection of the device at
+the load time.  It'd be safer to plug in the joystick device before
+loading the module.
+
+
+PCI Cards
+---------
+
+For PCI cards, the joystick is enabled when the appropriate module
+option is specified.  Some drivers don't need options, and the
+joystick support is always enabled.  In the former ALSA version, there
+was a dynamic control API for the joystick activation.  It was
+changed, however, to the static module options because of the system
+stability and the resource management.
+
+The following PCI drivers support the joystick natively.
+
+==============	=============	============================================
+Driver		Module Option	Available Values
+==============	=============	============================================
+als4000		joystick_port	0 = disable (default), 1 = auto-detect,
+	                        manual: any address (e.g. 0x200)
+au88x0		N/A		N/A
+azf3328		joystick	0 = disable, 1 = enable, -1 = auto (default)
+ens1370		joystick	0 = disable (default), 1 = enable
+ens1371		joystick_port	0 = disable (default), 1 = auto-detect,
+	                        manual: 0x200, 0x208, 0x210, 0x218
+cmipci		joystick_port	0 = disable (default), 1 = auto-detect,
+	                        manual: any address (e.g. 0x200)
+cs4281		N/A		N/A
+cs46xx		N/A		N/A
+es1938		N/A		N/A
+es1968		joystick	0 = disable (default), 1 = enable
+sonicvibes	N/A		N/A
+trident		N/A		N/A
+via82xx [#f1]_	joystick	0 = disable (default), 1 = enable
+ymfpci		joystick_port	0 = disable (default), 1 = auto-detect,
+	                        manual: 0x201, 0x202, 0x204, 0x205 [#f2]_
+==============	=============	============================================
+
+.. [#f1] VIA686A/B only
+.. [#f2] With YMF744/754 chips, the port address can be chosen arbitrarily
+
+The following drivers don't support gameport natively, but there are
+additional modules.  Load the corresponding module to add the gameport
+support.
+
+=======	=================
+Driver	Additional Module
+=======	=================
+emu10k1	emu10k1-gp
+fm801	fm801-gp
+=======	=================
+
+Note: the "pcigame" and "cs461x" modules are for the OSS drivers only.
+These ALSA drivers (cs46xx, trident and au88x0) have the
+built-in gameport support.
+
+As mentioned above, ALSA PCI drivers have the built-in gameport
+support, so you don't have to load ns558 module.  Just load "joydev"
+and the appropriate adapter module (e.g. "analog").
+
+
+ISA Cards
+---------
+
+ALSA ISA drivers don't have the built-in gameport support.
+Instead, you need to load "ns558" module in addition to "joydev" and
+the adapter module (e.g. "analog").
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/maya44.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/maya44.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/maya44.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/maya44.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,186 @@
+=================================
+Notes on Maya44 USB Audio Support
+=================================
+
+.. note::
+   The following is the original document of Rainer's patch that the
+   current maya44 code based on.  Some contents might be obsoleted, but I
+   keep here as reference -- tiwai
+
+Feb 14, 2008
+
+Rainer Zimmermann <mail@lightshed.de>
+ 
+STATE OF DEVELOPMENT
+====================
+
+This driver is being developed on the initiative of Piotr Makowski (oponek@gmail.com) and financed by Lars Bergmann.
+Development is carried out by Rainer Zimmermann (mail@lightshed.de).
+
+ESI provided a sample Maya44 card for the development work.
+
+However, unfortunately it has turned out difficult to get detailed programming information, so I (Rainer Zimmermann) had to find out some card-specific information by experiment and conjecture. Some information (in particular, several GPIO bits) is still missing.
+
+This is the first testing version of the Maya44 driver released to the alsa-devel mailing list (Feb 5, 2008).
+
+
+The following functions work, as tested by Rainer Zimmermann and Piotr Makowski:
+
+- playback and capture at all sampling rates
+- input/output level
+- crossmixing
+- line/mic switch
+- phantom power switch
+- analogue monitor a.k.a bypass
+
+
+The following functions *should* work, but are not fully tested:
+
+- Channel 3+4 analogue - S/PDIF input switching
+- S/PDIF output
+- all inputs/outputs on the M/IO/DIO extension card
+- internal/external clock selection
+
+
+*In particular, we would appreciate testing of these functions by anyone who has access to an M/IO/DIO extension card.*
+
+
+Things that do not seem to work:
+
+- The level meters ("multi track") in 'alsamixer' do not seem to react to signals in (if this is a bug, it would probably be in the existing ICE1724 code).
+
+- Ardour 2.1 seems to work only via JACK, not using ALSA directly or via OSS. This still needs to be tracked down.
+
+
+DRIVER DETAILS
+==============
+
+the following files were added:
+
+* pci/ice1724/maya44.c - Maya44 specific code
+* pci/ice1724/maya44.h
+* pci/ice1724/ice1724.patch
+* pci/ice1724/ice1724.h.patch - PROPOSED patch to ice1724.h (see SAMPLING RATES)
+* i2c/other/wm8776.c - low-level access routines for Wolfson WM8776 codecs 
+* include/wm8776.h
+
+
+Note that the wm8776.c code is meant to be card-independent and does not actually register the codec with the ALSA infrastructure.
+This is done in maya44.c, mainly because some of the WM8776 controls are used in Maya44-specific ways, and should be named appropriately.
+
+
+the following files were created in pci/ice1724, simply #including the corresponding file from the alsa-kernel tree:
+
+* wtm.h
+* vt1720_mobo.h
+* revo.h
+* prodigy192.h
+* pontis.h
+* phase.h
+* maya44.h
+* juli.h
+* aureon.h
+* amp.h
+* envy24ht.h
+* se.h
+* prodigy_hifi.h
+
+
+*I hope this is the correct way to do things.*
+
+
+SAMPLING RATES
+==============
+
+The Maya44 card (or more exactly, the Wolfson WM8776 codecs) allow a maximum sampling rate of 192 kHz for playback and 92 kHz for capture.
+
+As the ICE1724 chip only allows one global sampling rate, this is handled as follows:
+
+* setting the sampling rate on any open PCM device on the maya44 card will always set the *global* sampling rate for all playback and capture channels.
+
+* In the current state of the driver, setting rates of up to 192 kHz is permitted even for capture devices.
+
+*AVOID CAPTURING AT RATES ABOVE 96kHz*, even though it may appear to work. The codec cannot actually capture at such rates, meaning poor quality.
+
+
+I propose some additional code for limiting the sampling rate when setting on a capture pcm device. However because of the global sampling rate, this logic would be somewhat problematic.
+
+The proposed code (currently deactivated) is in ice1712.h.patch, ice1724.c and maya44.c (in pci/ice1712).
+
+
+SOUND DEVICES
+=============
+
+PCM devices correspond to inputs/outputs as follows (assuming Maya44 is card #0):
+
+* hw:0,0 input - stereo, analog input 1+2
+* hw:0,0 output - stereo, analog output 1+2
+* hw:0,1 input - stereo, analog input 3+4 OR S/PDIF input
+* hw:0,1 output - stereo, analog output 3+4 (and SPDIF out)
+
+
+NAMING OF MIXER CONTROLS
+========================
+
+(for more information about the signal flow, please refer to the block diagram on p.24 of the ESI Maya44 manual, or in the ESI windows software).
+
+
+PCM
+    (digital) output level for channel 1+2
+PCM 1
+    same for channel 3+4
+
+Mic Phantom+48V
+    switch for +48V phantom power for electrostatic microphones on input 1/2.
+
+    Make sure this is not turned on while any other source is connected to input 1/2.
+    It might damage the source and/or the maya44 card.
+
+Mic/Line input
+    if switch is on, input jack 1/2 is microphone input (mono), otherwise line input (stereo).
+
+Bypass
+    analogue bypass from ADC input to output for channel 1+2. Same as "Monitor" in the windows driver.
+Bypass 1
+    same for channel 3+4.
+
+Crossmix
+    cross-mixer from channels 1+2 to channels 3+4
+Crossmix 1
+    cross-mixer from channels 3+4 to channels 1+2
+
+IEC958 Output
+    switch for S/PDIF output.
+
+    This is not supported by the ESI windows driver.
+    S/PDIF should output the same signal as channel 3+4. [untested!]
+
+
+Digitial output selectors
+    These switches allow a direct digital routing from the ADCs to the DACs.
+    Each switch determines where the digital input data to one of the DACs comes from.
+    They are not supported by the ESI windows driver.
+    For normal operation, they should all be set to "PCM out".
+
+H/W
+    Output source channel 1
+H/W 1
+    Output source channel 2
+H/W 2
+    Output source channel 3
+H/W 3
+    Output source channel 4
+
+H/W 4 ... H/W 9
+    unknown function, left in to enable testing.
+
+    Possibly some of these control S/PDIF output(s).
+    If these turn out to be unused, they will go away in later driver versions.
+
+Selectable values for each of the digital output selectors are:
+
+PCM out
+	DAC output of the corresponding channel (default setting)
+Input 1 ... Input 4
+	direct routing from ADC output of the selected input channel
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/mixart.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/mixart.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/mixart.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/mixart.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,110 @@
+==============================================================
+Alsa driver for Digigram miXart8 and miXart8AES/EBU soundcards
+==============================================================
+
+Digigram <alsa@digigram.com>
+
+
+GENERAL
+=======
+
+The miXart8 is a multichannel audio processing and mixing soundcard
+that has 4 stereo audio inputs and 4 stereo audio outputs.
+The miXart8AES/EBU is the same with a add-on card that offers further
+4 digital stereo audio inputs and outputs.
+Furthermore the add-on card offers external clock synchronisation
+(AES/EBU, Word Clock, Time Code and Video Synchro)
+
+The mainboard has a PowerPC that offers onboard mpeg encoding and
+decoding, samplerate conversions and various effects.
+
+The driver don't work properly at all until the certain firmwares
+are loaded, i.e. no PCM nor mixer devices will appear.
+Use the mixartloader that can be found in the alsa-tools package.
+
+
+VERSION 0.1.0
+=============
+
+One miXart8 board will be represented as 4 alsa cards, each with 1
+stereo analog capture 'pcm0c' and 1 stereo analog playback 'pcm0p' device.
+With a miXart8AES/EBU there is in addition 1 stereo digital input
+'pcm1c' and 1 stereo digital output 'pcm1p' per card.
+
+Formats
+-------
+U8, S16_LE, S16_BE, S24_3LE, S24_3BE, FLOAT_LE, FLOAT_BE
+Sample rates : 8000 - 48000 Hz continuously
+
+Playback
+--------
+For instance the playback devices are configured to have max. 4
+substreams performing hardware mixing. This could be changed to a
+maximum of 24 substreams if wished.
+Mono files will be played on the left and right channel. Each channel
+can be muted for each stream to use 8 analog/digital outputs separately.
+
+Capture
+-------
+There is one substream per capture device. For instance only stereo
+formats are supported.
+
+Mixer
+-----
+<Master> and <Master Capture>
+	analog volume control of playback and capture PCM.
+<PCM 0-3> and <PCM Capture>
+	digital volume control of each analog substream.
+<AES 0-3> and <AES Capture>
+	digital volume control of each AES/EBU substream.
+<Monitoring>
+	Loopback from 'pcm0c' to 'pcm0p' with digital volume
+	and mute control.
+
+Rem : for best audio quality try to keep a 0 attenuation on the PCM
+and AES volume controls which is set by 219 in the range from 0 to 255
+(about 86% with alsamixer)
+
+
+NOT YET IMPLEMENTED
+===================
+
+- external clock support (AES/EBU, Word Clock, Time Code, Video Sync)
+- MPEG audio formats
+- mono record
+- on-board effects and samplerate conversions
+- linked streams
+
+
+FIRMWARE
+========
+
+[As of 2.6.11, the firmware can be loaded automatically with hotplug
+ when CONFIG_FW_LOADER is set.  The mixartloader is necessary only
+ for older versions or when you build the driver into kernel.]
+ 
+For loading the firmware automatically after the module is loaded, use a
+install command.  For example, add the following entry to
+/etc/modprobe.d/mixart.conf for miXart driver:
+::
+
+	install snd-mixart /sbin/modprobe --first-time -i snd-mixart && \
+			   /usr/bin/mixartloader
+
+
+(for 2.2/2.4 kernels, add "post-install snd-mixart /usr/bin/vxloader" to
+/etc/modules.conf, instead.)
+
+The firmware binaries are installed on /usr/share/alsa/firmware
+(or /usr/local/share/alsa/firmware, depending to the prefix option of
+configure).  There will be a miXart.conf file, which define the dsp image
+files.
+
+The firmware files are copyright by Digigram SA
+
+
+COPYRIGHT
+=========
+
+Copyright (c) 2003 Digigram SA <alsa@digigram.com>
+Distributable under GPL.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/sb-live-mixer.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/sb-live-mixer.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/sb-live-mixer.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/sb-live-mixer.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,373 @@
+===========================================
+Sound Blaster Live mixer / default DSP code
+===========================================
+
+
+The EMU10K1 chips have a DSP part which can be programmed to support
+various ways of sample processing, which is described here.
+(This article does not deal with the overall functionality of the 
+EMU10K1 chips. See the manuals section for further details.)
+
+The ALSA driver programs this portion of chip by default code
+(can be altered later) which offers the following functionality:
+
+
+IEC958 (S/PDIF) raw PCM
+=======================
+
+This PCM device (it's the 4th PCM device (index 3!) and first subdevice
+(index 0) for a given card) allows to forward 48kHz, stereo, 16-bit
+little endian streams without any modifications to the digital output
+(coaxial or optical). The universal interface allows the creation of up
+to 8 raw PCM devices operating at 48kHz, 16-bit little endian. It would
+be easy to add support for multichannel devices to the current code,
+but the conversion routines exist only for stereo (2-channel streams)
+at the time. 
+
+Look to tram_poke routines in lowlevel/emu10k1/emufx.c for more details.
+
+
+Digital mixer controls
+======================
+
+These controls are built using the DSP instructions. They offer extended
+functionality. Only the default build-in code in the ALSA driver is described
+here. Note that the controls work as attenuators: the maximum value is the 
+neutral position leaving the signal unchanged. Note that if the  same destination 
+is mentioned in multiple controls, the signal is accumulated and can be wrapped 
+(set to maximal or minimal value without checking of overflow).
+
+
+Explanation of used abbreviations:
+
+DAC
+	digital to analog converter
+ADC
+	analog to digital converter
+I2S
+	one-way three wire serial bus for digital sound by Philips Semiconductors
+        (this standard is used for connecting standalone DAC and ADC converters)
+LFE
+	low frequency effects (subwoofer signal)
+AC97
+	a chip containing an analog mixer, DAC and ADC converters
+IEC958
+	S/PDIF
+FX-bus
+	the EMU10K1 chip has an effect bus containing 16 accumulators.
+	Each of the synthesizer voices can feed its output to these accumulators
+	and the DSP microcontroller can operate with the resulting sum.
+
+
+``name='Wave Playback Volume',index=0``
+---------------------------------------
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+``name='Wave Surround Playback Volume',index=0``
+------------------------------------------------
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result samples are forwarded to the rear I2S DACs. These DACs operates
+separately (they are not inside the AC97 codec).
+
+``name='Wave Center Playback Volume',index=0``
+----------------------------------------------
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM samples.
+The result is mixed to mono signal (single channel) and forwarded to
+the ??rear?? right DAC PCM slot of the AC97 codec.
+
+``name='Wave LFE Playback Volume',index=0``
+-------------------------------------------
+This control is used to attenuate samples for left and right PCM FX-bus
+accumulators. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is mixed to mono signal (single channel) and forwarded to
+the ??rear?? left DAC PCM slot of the AC97 codec.
+
+``name='Wave Capture Volume',index=0``, ``name='Wave Capture Switch',index=0``
+------------------------------------------------------------------------------
+These controls are used to attenuate samples for left and right PCM FX-bus
+accumulator. ALSA uses accumulators 0 and 1 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+``name='Synth Playback Volume',index=0``
+----------------------------------------
+This control is used to attenuate samples for left and right MIDI FX-bus
+accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
+The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
+
+``name='Synth Capture Volume',index=0``, ``name='Synth Capture Switch',index=0``
+--------------------------------------------------------------------------------
+These controls are used to attenuate samples for left and right MIDI FX-bus
+accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+``name='Surround Playback Volume',index=0``
+-------------------------------------------
+This control is used to attenuate samples for left and right rear PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
+The result samples are forwarded to the rear I2S DACs. These DACs operate
+separately (they are not inside the AC97 codec).
+
+``name='Surround Capture Volume',index=0``, ``name='Surround Capture Switch',index=0``
+--------------------------------------------------------------------------------------
+These controls are used to attenuate samples for left and right rear PCM FX-bus
+accumulators. ALSA uses accumulators 2 and 3 for left and right rear PCM samples.
+The result is forwarded to the ADC capture FIFO (thus to the standard capture
+PCM device).
+
+``name='Center Playback Volume',index=0``
+-----------------------------------------
+This control is used to attenuate sample for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
+to the ??rear?? right DAC PCM slot of the AC97 codec.
+
+``name='LFE Playback Volume',index=0``
+--------------------------------------
+This control is used to attenuate sample for center PCM FX-bus accumulator.
+ALSA uses accumulator 6 for center PCM sample. The result sample is forwarded
+to the ??rear?? left DAC PCM slot of the AC97 codec.
+
+``name='AC97 Playback Volume',index=0``
+---------------------------------------
+This control is used to attenuate samples for left and right front ADC PCM slots
+of the AC97 codec. The result samples are forwarded to the front DAC PCM
+slots of the AC97 codec.
+
+.. note::
+  This control should be zero for the standard operations, otherwise
+  a digital loopback is activated.
+
+
+``name='AC97 Capture Volume',index=0``
+--------------------------------------
+This control is used to attenuate samples for left and right front ADC PCM slots
+of the AC97 codec. The result is forwarded to the ADC capture FIFO (thus to
+the standard capture PCM device).
+
+.. note::
+   This control should be 100 (maximal value), otherwise no analog
+   inputs of the AC97 codec can be captured (recorded).
+
+``name='IEC958 TTL Playback Volume',index=0``
+---------------------------------------------
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the AC97 codec.
+
+``name='IEC958 TTL Capture Volume',index=0``
+--------------------------------------------
+This control is used to attenuate samples from left and right IEC958 TTL
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+``name='Zoom Video Playback Volume',index=0``
+---------------------------------------------
+This control is used to attenuate samples from left and right zoom video
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the front DAC PCM slots of the AC97 codec.
+
+``name='Zoom Video Capture Volume',index=0``
+--------------------------------------------
+This control is used to attenuate samples from left and right zoom video
+digital inputs (usually used by a CDROM drive). The result samples are
+forwarded to the ADC capture FIFO (thus to the standard capture PCM device).
+
+``name='IEC958 LiveDrive Playback Volume',index=0``
+---------------------------------------------------
+This control is used to attenuate samples from left and right IEC958 optical
+digital input. The result samples are forwarded to the front DAC PCM slots
+of the AC97 codec.
+
+``name='IEC958 LiveDrive Capture Volume',index=0``
+--------------------------------------------------
+This control is used to attenuate samples from left and right IEC958 optical
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+``name='IEC958 Coaxial Playback Volume',index=0``
+-------------------------------------------------
+This control is used to attenuate samples from left and right IEC958 coaxial
+digital inputs. The result samples are forwarded to the front DAC PCM slots
+of the AC97 codec.
+
+``name='IEC958 Coaxial Capture Volume',index=0``
+------------------------------------------------
+This control is used to attenuate samples from left and right IEC958 coaxial
+digital inputs. The result samples are forwarded to the ADC capture FIFO
+(thus to the standard capture PCM device).
+
+``name='Line LiveDrive Playback Volume',index=0``, ``name='Line LiveDrive Playback Volume',index=1``
+----------------------------------------------------------------------------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the LiveDrive). The result samples are forwarded to the front
+DAC PCM slots of the AC97 codec.
+
+``name='Line LiveDrive Capture Volume',index=1``, ``name='Line LiveDrive Capture Volume',index=1``
+--------------------------------------------------------------------------------------------------
+This control is used to attenuate samples from left and right I2S ADC
+inputs (on the LiveDrive). The result samples are forwarded to the ADC
+capture FIFO (thus to the standard capture PCM device).
+
+``name='Tone Control - Switch',index=0``
+----------------------------------------
+This control turns the tone control on or off. The samples for front, rear
+and center / LFE outputs are affected.
+
+``name='Tone Control - Bass',index=0``
+--------------------------------------
+This control sets the bass intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+``name='Tone Control - Treble',index=0``
+----------------------------------------
+This control sets the treble intensity. There is no neutral value!!
+When the tone control code is activated, the samples are always modified.
+The closest value to pure signal is 20.
+
+``name='IEC958 Optical Raw Playback Switch',index=0``
+-----------------------------------------------------
+If this switch is on, then the samples for the IEC958 (S/PDIF) digital
+output are taken only from the raw FX8010 PCM, otherwise standard front
+PCM samples are taken.
+
+``name='Headphone Playback Volume',index=1``
+--------------------------------------------
+This control attenuates the samples for the headphone output.
+
+``name='Headphone Center Playback Switch',index=1``
+---------------------------------------------------
+If this switch is on, then the sample for the center PCM is put to the
+left headphone output (useful for SB Live cards without separate center/LFE
+output).
+
+``name='Headphone LFE Playback Switch',index=1``
+------------------------------------------------
+If this switch is on, then the sample for the center PCM is put to the
+right headphone output (useful for SB Live cards without separate center/LFE
+output).
+
+
+PCM stream related controls
+===========================
+
+``name='EMU10K1 PCM Volume',index 0-31``
+----------------------------------------
+Channel volume attenuation in range 0-0xffff. The maximum value (no
+attenuation) is default. The channel mapping for three values is
+as follows:
+
+* 0 - mono, default 0xffff (no attenuation)
+* 1 - left, default 0xffff (no attenuation)
+* 2 - right, default 0xffff (no attenuation)
+
+``name='EMU10K1 PCM Send Routing',index 0-31``
+----------------------------------------------
+This control specifies the destination - FX-bus accumulators. There are
+twelve values with this mapping:
+
+*  0 -  mono, A destination (FX-bus 0-15), default 0
+*  1 -  mono, B destination (FX-bus 0-15), default 1
+*  2 -  mono, C destination (FX-bus 0-15), default 2
+*  3 -  mono, D destination (FX-bus 0-15), default 3
+*  4 -  left, A destination (FX-bus 0-15), default 0
+*  5 -  left, B destination (FX-bus 0-15), default 1
+*  6 -  left, C destination (FX-bus 0-15), default 2
+*  7 -  left, D destination (FX-bus 0-15), default 3
+*  8 - right, A destination (FX-bus 0-15), default 0
+*  9 - right, B destination (FX-bus 0-15), default 1
+* 10 - right, C destination (FX-bus 0-15), default 2
+* 11 - right, D destination (FX-bus 0-15), default 3
+
+Don't forget that it's illegal to assign a channel to the same FX-bus accumulator 
+more than once (it means 0=0 && 1=0 is an invalid combination).
+ 
+``name='EMU10K1 PCM Send Volume',index 0-31``
+---------------------------------------------
+It specifies the attenuation (amount) for given destination in range 0-255.
+The channel mapping is following:
+
+*  0 -  mono, A destination attn, default 255 (no attenuation)
+*  1 -  mono, B destination attn, default 255 (no attenuation)
+*  2 -  mono, C destination attn, default 0 (mute)
+*  3 -  mono, D destination attn, default 0 (mute)
+*  4 -  left, A destination attn, default 255 (no attenuation)
+*  5 -  left, B destination attn, default 0 (mute)
+*  6 -  left, C destination attn, default 0 (mute)
+*  7 -  left, D destination attn, default 0 (mute)
+*  8 - right, A destination attn, default 0 (mute)
+*  9 - right, B destination attn, default 255 (no attenuation)
+* 10 - right, C destination attn, default 0 (mute)
+* 11 - right, D destination attn, default 0 (mute)
+
+
+
+MANUALS/PATENTS
+===============
+
+ftp://opensource.creative.com/pub/doc
+-------------------------------------
+
+LM4545.pdf
+	AC97 Codec
+m2049.pdf
+	The EMU10K1 Digital Audio Processor
+hog63.ps
+	FX8010 - A DSP Chip Architecture for Audio Effects
+
+
+WIPO Patents
+------------
+
+WO 9901813 (A1)
+	Audio Effects Processor with multiple asynchronous streams
+	(Jan. 14, 1999)
+
+WO 9901814 (A1)
+	Processor with Instruction Set for Audio Effects (Jan. 14, 1999)
+
+WO 9901953 (A1)
+	Audio Effects Processor having Decoupled Instruction
+        Execution and Audio Data Sequencing (Jan. 14, 1999)
+
+
+US Patents (http://www.uspto.gov/)
+----------------------------------
+
+US 5925841
+	Digital Sampling Instrument employing cache memory (Jul. 20, 1999)
+
+US 5928342
+	Audio Effects Processor integrated on a single chip
+        with a multiport memory onto which multiple asynchronous
+        digital sound samples can be concurrently loaded
+	(Jul. 27, 1999)
+
+US 5930158
+	Processor with Instruction Set for Audio Effects (Jul. 27, 1999)
+
+US 6032235
+	Memory initialization circuit (Tram) (Feb. 29, 2000)
+
+US 6138207
+	Interpolation looping of audio samples in cache connected to
+        system bus with prioritization and modification of bus transfers
+        in accordance with loop ends and minimum block sizes
+	(Oct. 24, 2000)
+
+US 6151670
+	Method for conserving memory storage using a
+        pool of  short term memory registers
+	(Nov. 21, 2000)
+
+US 6195715
+	Interrupt control for multiple programs communicating with
+        a common interrupt by associating programs to GP registers,
+        defining interrupt register, polling GP registers, and invoking
+        callback routine associated with defined interrupt register
+	(Feb. 27, 2001)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/serial-u16550.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/serial-u16550.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/serial-u16550.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/serial-u16550.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,93 @@
+===================================
+Serial UART 16450/16550 MIDI driver
+===================================
+
+The adaptor module parameter allows you to select either:
+
+* 0 - Roland Soundcanvas support (default)
+* 1 - Midiator MS-124T support (1)
+* 2 - Midiator MS-124W S/A mode (2)
+* 3 - MS-124W M/B mode support (3)
+* 4 - Generic device with multiple input support (4)
+
+For the Midiator MS-124W, you must set the physical M-S and A-B
+switches on the Midiator to match the driver mode you select.
+
+In Roland Soundcanvas mode, multiple ALSA raw MIDI substreams are supported
+(midiCnD0-midiCnD15).  Whenever you write to a different substream, the driver
+sends the nonstandard MIDI command sequence F5 NN, where NN is the substream
+number plus 1.  Roland modules use this command to switch between different
+"parts", so this feature lets you treat each part as a distinct raw MIDI
+substream. The driver provides no way to send F5 00 (no selection) or to not
+send the F5 NN command sequence at all; perhaps it ought to.
+
+Usage example for simple serial converter:
+::
+
+	/sbin/setserial /dev/ttyS0 uart none
+	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
+
+Usage example for Roland SoundCanvas with 4 MIDI ports:
+::
+
+	/sbin/setserial /dev/ttyS0 uart none
+	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
+
+In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
+module parameter is automatically set to 1. The driver sends the same data to
+all four MIDI Out connectors.  Set the A-B switch and the speed module
+parameter to match (A=19200, B=9600).
+
+Usage example for MS-124T, with A-B switch in A position:
+::
+
+	/sbin/setserial /dev/ttyS0 uart none
+	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
+			speed=19200
+
+In MS-124W S/A mode, one raw MIDI substream is supported (midiCnD0);
+the outs module parameter is automatically set to 1. The driver sends
+the same data to all four MIDI Out connectors at full MIDI speed.
+
+Usage example for S/A mode:
+::
+
+	/sbin/setserial /dev/ttyS0 uart none
+	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
+
+In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
+the outs module parameter is automatically set to 16.  The substream
+number gives a bitmask of which MIDI Out connectors the data should be
+sent to, with midiCnD1 sending to Out 1, midiCnD2 to Out 2, midiCnD4 to
+Out 3, and midiCnD8 to Out 4.  Thus midiCnD15 sends the data to all 4 ports.
+As a special case, midiCnD0 also sends to all ports, since it is not useful
+to send the data to no ports.  M/B mode has extra overhead to select the MIDI
+Out for each byte, so the aggregate data rate across all four MIDI Outs is
+at most one byte every 520 us, as compared with the full MIDI data rate of
+one byte every 320 us per port.
+
+Usage example for M/B mode:
+::
+
+	/sbin/setserial /dev/ttyS0 uart none
+	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
+
+The MS-124W hardware's M/A mode is currently not supported. This mode allows
+the MIDI Outs to act independently at double the aggregate throughput of M/B,
+but does not allow sending the same byte simultaneously to multiple MIDI Outs. 
+The M/A protocol requires the driver to twiddle the modem control lines under
+timing constraints, so it would be a bit more complicated to implement than
+the other modes.
+
+Midiator models other than MS-124W and MS-124T are currently not supported. 
+Note that the suffix letter is significant; the MS-124 and MS-124B are not
+compatible, nor are the other known models MS-101, MS-101B, MS-103, and MS-114.
+I do have documentation (tim.mann@compaq.com) that partially covers these models,
+but no units to experiment with.  The MS-124W support is tested with a real unit.
+The MS-124T support is untested, but should work.
+
+The Generic driver supports multiple input and output substreams over a single
+serial port.  Similar to Roland Soundcanvas mode, F5 NN is used to select the
+appropriate input or output stream (depending on the data direction).
+Additionally, the CTS signal is used to regulate the data flow.  The number of
+inputs is specified by the ins parameter.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/cards/via82xx-mixer.rst linux-libre-4.10-rc8-gnu/Documentation/sound/cards/via82xx-mixer.rst
--- linux-libre-4.9-gnu/Documentation/sound/cards/via82xx-mixer.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/cards/via82xx-mixer.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+=============
+VIA82xx mixer
+=============
+
+On many VIA82xx boards, the ``Input Source Select`` mixer control does not work.
+Setting it to ``Input2`` on such boards will cause recording to hang, or fail
+with EIO (input/output error) via OSS emulation.  This control should be left
+at ``Input1`` for such cards.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/channel-mapping-api.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/channel-mapping-api.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/channel-mapping-api.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/channel-mapping-api.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,164 @@
+============================
+ALSA PCM channel-mapping API
+============================
+
+Takashi Iwai <tiwai@suse.de>
+
+General
+=======
+
+The channel mapping API allows user to query the possible channel maps
+and the current channel map, also optionally to modify the channel map
+of the current stream.
+
+A channel map is an array of position for each PCM channel.
+Typically, a stereo PCM stream has a channel map of
+``{ front_left, front_right }``
+while a 4.0 surround PCM stream has a channel map of
+``{ front left, front right, rear left, rear right }.``
+
+The problem, so far, was that we had no standard channel map
+explicitly, and applications had no way to know which channel
+corresponds to which (speaker) position.  Thus, applications applied
+wrong channels for 5.1 outputs, and you hear suddenly strange sound
+from rear.  Or, some devices secretly assume that center/LFE is the
+third/fourth channels while others that C/LFE as 5th/6th channels.
+
+Also, some devices such as HDMI are configurable for different speaker
+positions even with the same number of total channels.  However, there
+was no way to specify this because of lack of channel map
+specification.  These are the main motivations for the new channel
+mapping API.
+
+
+Design
+======
+
+Actually, "the channel mapping API" doesn't introduce anything new in
+the kernel/user-space ABI perspective.  It uses only the existing
+control element features.
+
+As a ground design, each PCM substream may contain a control element
+providing the channel mapping information and configuration.  This
+element is specified by:
+
+* iface = SNDRV_CTL_ELEM_IFACE_PCM
+* name = "Playback Channel Map" or "Capture Channel Map"
+* device = the same device number for the assigned PCM substream
+* index = the same index number for the assigned PCM substream
+
+Note the name is different depending on the PCM substream direction.
+
+Each control element provides at least the TLV read operation and the
+read operation.  Optionally, the write operation can be provided to
+allow user to change the channel map dynamically.
+
+TLV
+---
+
+The TLV operation gives the list of available channel
+maps.  A list item of a channel map is usually a TLV of
+``type data-bytes ch0 ch1 ch2...``
+where type is the TLV type value, the second argument is the total
+bytes (not the numbers) of channel values, and the rest are the
+position value for each channel.
+
+As a TLV type, either ``SNDRV_CTL_TLVT_CHMAP_FIXED``,
+``SNDRV_CTL_TLV_CHMAP_VAR`` or ``SNDRV_CTL_TLVT_CHMAP_PAIRED`` can be used.
+The ``_FIXED`` type is for a channel map with the fixed channel position
+while the latter two are for flexible channel positions. ``_VAR`` type is
+for a channel map where all channels are freely swappable and ``_PAIRED``
+type is where pair-wise channels are swappable.  For example, when you
+have {FL/FR/RL/RR} channel map, ``_PAIRED`` type would allow you to swap
+only {RL/RR/FL/FR} while ``_VAR`` type would allow even swapping FL and
+RR.
+
+These new TLV types are defined in ``sound/tlv.h``.
+
+The available channel position values are defined in ``sound/asound.h``,
+here is a cut:
+
+::
+
+  /* channel positions */
+  enum {
+	SNDRV_CHMAP_UNKNOWN = 0,
+	SNDRV_CHMAP_NA,		/* N/A, silent */
+	SNDRV_CHMAP_MONO,	/* mono stream */
+	/* this follows the alsa-lib mixer channel value + 3 */
+	SNDRV_CHMAP_FL,		/* front left */
+	SNDRV_CHMAP_FR,		/* front right */
+	SNDRV_CHMAP_RL,		/* rear left */
+	SNDRV_CHMAP_RR,		/* rear right */
+	SNDRV_CHMAP_FC,		/* front center */
+	SNDRV_CHMAP_LFE,	/* LFE */
+	SNDRV_CHMAP_SL,		/* side left */
+	SNDRV_CHMAP_SR,		/* side right */
+	SNDRV_CHMAP_RC,		/* rear center */
+	/* new definitions */
+	SNDRV_CHMAP_FLC,	/* front left center */
+	SNDRV_CHMAP_FRC,	/* front right center */
+	SNDRV_CHMAP_RLC,	/* rear left center */
+	SNDRV_CHMAP_RRC,	/* rear right center */
+	SNDRV_CHMAP_FLW,	/* front left wide */
+	SNDRV_CHMAP_FRW,	/* front right wide */
+	SNDRV_CHMAP_FLH,	/* front left high */
+	SNDRV_CHMAP_FCH,	/* front center high */
+	SNDRV_CHMAP_FRH,	/* front right high */
+	SNDRV_CHMAP_TC,		/* top center */
+	SNDRV_CHMAP_TFL,	/* top front left */
+	SNDRV_CHMAP_TFR,	/* top front right */
+	SNDRV_CHMAP_TFC,	/* top front center */
+	SNDRV_CHMAP_TRL,	/* top rear left */
+	SNDRV_CHMAP_TRR,	/* top rear right */
+	SNDRV_CHMAP_TRC,	/* top rear center */
+	SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC,
+  };
+
+When a PCM stream can provide more than one channel map, you can
+provide multiple channel maps in a TLV container type.  The TLV data
+to be returned will contain such as:
+::
+
+	SNDRV_CTL_TLVT_CONTAINER 96
+	    SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC
+	    SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR
+	    SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \
+		SNDRV_CHMAP_RL SNDRV_CHMAP_RR
+
+The channel position is provided in LSB 16bits.  The upper bits are
+used for bit flags.
+::
+
+	#define SNDRV_CHMAP_POSITION_MASK	0xffff
+	#define SNDRV_CHMAP_PHASE_INVERSE	(0x01 << 16)
+	#define SNDRV_CHMAP_DRIVER_SPEC		(0x02 << 16)
+
+``SNDRV_CHMAP_PHASE_INVERSE`` indicates the channel is phase inverted,
+(thus summing left and right channels would result in almost silence).
+Some digital mic devices have this.
+
+When ``SNDRV_CHMAP_DRIVER_SPEC`` is set, all the channel position values
+don't follow the standard definition above but driver-specific.
+
+Read Operation
+--------------
+
+The control read operation is for providing the current channel map of
+the given stream.  The control element returns an integer array
+containing the position of each channel.
+
+When this is performed before the number of the channel is specified
+(i.e. hw_params is set), it should return all channels set to
+``UNKNOWN``.
+
+Write Operation
+---------------
+
+The control write operation is optional, and only for devices that can
+change the channel configuration on the fly, such as HDMI.  User needs
+to pass an integer value containing the valid channel positions for
+all channels of the assigned PCM substream.
+
+This operation is allowed only at PCM PREPARED state.  When called in
+other states, it shall return an error.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/compress-offload.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/compress-offload.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/compress-offload.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/compress-offload.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,245 @@
+=========================
+ALSA Compress-Offload API
+=========================
+
+Pierre-Louis.Bossart <pierre-louis.bossart@linux.intel.com>
+
+Vinod Koul <vinod.koul@linux.intel.com>
+
+
+Overview
+========
+Since its early days, the ALSA API was defined with PCM support or
+constant bitrates payloads such as IEC61937 in mind. Arguments and
+returned values in frames are the norm, making it a challenge to
+extend the existing API to compressed data streams.
+
+In recent years, audio digital signal processors (DSP) were integrated
+in system-on-chip designs, and DSPs are also integrated in audio
+codecs. Processing compressed data on such DSPs results in a dramatic
+reduction of power consumption compared to host-based
+processing. Support for such hardware has not been very good in Linux,
+mostly because of a lack of a generic API available in the mainline
+kernel.
+
+Rather than requiring a compatibility break with an API change of the
+ALSA PCM interface, a new 'Compressed Data' API is introduced to
+provide a control and data-streaming interface for audio DSPs.
+
+The design of this API was inspired by the 2-year experience with the
+Intel Moorestown SOC, with many corrections required to upstream the
+API in the mainline kernel instead of the staging tree and make it
+usable by others.
+
+
+Requirements
+============
+The main requirements are:
+
+- separation between byte counts and time. Compressed formats may have
+  a header per file, per frame, or no header at all. The payload size
+  may vary from frame-to-frame. As a result, it is not possible to
+  estimate reliably the duration of audio buffers when handling
+  compressed data. Dedicated mechanisms are required to allow for
+  reliable audio-video synchronization, which requires precise
+  reporting of the number of samples rendered at any given time.
+
+- Handling of multiple formats. PCM data only requires a specification
+  of the sampling rate, number of channels and bits per sample. In
+  contrast, compressed data comes in a variety of formats. Audio DSPs
+  may also provide support for a limited number of audio encoders and
+  decoders embedded in firmware, or may support more choices through
+  dynamic download of libraries.
+
+- Focus on main formats. This API provides support for the most
+  popular formats used for audio and video capture and playback. It is
+  likely that as audio compression technology advances, new formats
+  will be added.
+
+- Handling of multiple configurations. Even for a given format like
+  AAC, some implementations may support AAC multichannel but HE-AAC
+  stereo. Likewise WMA10 level M3 may require too much memory and cpu
+  cycles. The new API needs to provide a generic way of listing these
+  formats.
+
+- Rendering/Grabbing only. This API does not provide any means of
+  hardware acceleration, where PCM samples are provided back to
+  user-space for additional processing. This API focuses instead on
+  streaming compressed data to a DSP, with the assumption that the
+  decoded samples are routed to a physical output or logical back-end.
+
+- Complexity hiding. Existing user-space multimedia frameworks all
+  have existing enums/structures for each compressed format. This new
+  API assumes the existence of a platform-specific compatibility layer
+  to expose, translate and make use of the capabilities of the audio
+  DSP, eg. Android HAL or PulseAudio sinks. By construction, regular
+  applications are not supposed to make use of this API.
+
+
+Design
+======
+The new API shares a number of concepts with the PCM API for flow
+control. Start, pause, resume, drain and stop commands have the same
+semantics no matter what the content is.
+
+The concept of memory ring buffer divided in a set of fragments is
+borrowed from the ALSA PCM API. However, only sizes in bytes can be
+specified.
+
+Seeks/trick modes are assumed to be handled by the host.
+
+The notion of rewinds/forwards is not supported. Data committed to the
+ring buffer cannot be invalidated, except when dropping all buffers.
+
+The Compressed Data API does not make any assumptions on how the data
+is transmitted to the audio DSP. DMA transfers from main memory to an
+embedded audio cluster or to a SPI interface for external DSPs are
+possible. As in the ALSA PCM case, a core set of routines is exposed;
+each driver implementer will have to write support for a set of
+mandatory routines and possibly make use of optional ones.
+
+The main additions are
+
+get_caps
+  This routine returns the list of audio formats supported. Querying the
+  codecs on a capture stream will return encoders, decoders will be
+  listed for playback streams.
+
+get_codec_caps
+  For each codec, this routine returns a list of
+  capabilities. The intent is to make sure all the capabilities
+  correspond to valid settings, and to minimize the risks of
+  configuration failures. For example, for a complex codec such as AAC,
+  the number of channels supported may depend on a specific profile. If
+  the capabilities were exposed with a single descriptor, it may happen
+  that a specific combination of profiles/channels/formats may not be
+  supported. Likewise, embedded DSPs have limited memory and cpu cycles,
+  it is likely that some implementations make the list of capabilities
+  dynamic and dependent on existing workloads. In addition to codec
+  settings, this routine returns the minimum buffer size handled by the
+  implementation. This information can be a function of the DMA buffer
+  sizes, the number of bytes required to synchronize, etc, and can be
+  used by userspace to define how much needs to be written in the ring
+  buffer before playback can start.
+
+set_params
+  This routine sets the configuration chosen for a specific codec. The
+  most important field in the parameters is the codec type; in most
+  cases decoders will ignore other fields, while encoders will strictly
+  comply to the settings
+
+get_params
+  This routines returns the actual settings used by the DSP. Changes to
+  the settings should remain the exception.
+
+get_timestamp
+  The timestamp becomes a multiple field structure. It lists the number
+  of bytes transferred, the number of samples processed and the number
+  of samples rendered/grabbed. All these values can be used to determine
+  the average bitrate, figure out if the ring buffer needs to be
+  refilled or the delay due to decoding/encoding/io on the DSP.
+
+Note that the list of codecs/profiles/modes was derived from the
+OpenMAX AL specification instead of reinventing the wheel.
+Modifications include:
+- Addition of FLAC and IEC formats
+- Merge of encoder/decoder capabilities
+- Profiles/modes listed as bitmasks to make descriptors more compact
+- Addition of set_params for decoders (missing in OpenMAX AL)
+- Addition of AMR/AMR-WB encoding modes (missing in OpenMAX AL)
+- Addition of format information for WMA
+- Addition of encoding options when required (derived from OpenMAX IL)
+- Addition of rateControlSupported (missing in OpenMAX AL)
+
+
+Gapless Playback
+================
+When playing thru an album, the decoders have the ability to skip the encoder
+delay and padding and directly move from one track content to another. The end
+user can perceive this as gapless playback as we don't have silence while
+switching from one track to another
+
+Also, there might be low-intensity noises due to encoding. Perfect gapless is
+difficult to reach with all types of compressed data, but works fine with most
+music content. The decoder needs to know the encoder delay and encoder padding.
+So we need to pass this to DSP. This metadata is extracted from ID3/MP4 headers
+and are not present by default in the bitstream, hence the need for a new
+interface to pass this information to the DSP. Also DSP and userspace needs to
+switch from one track to another and start using data for second track.
+
+The main additions are:
+
+set_metadata
+  This routine sets the encoder delay and encoder padding. This can be used by
+  decoder to strip the silence. This needs to be set before the data in the track
+  is written.
+
+set_next_track
+  This routine tells DSP that metadata and write operation sent after this would
+  correspond to subsequent track
+
+partial drain
+  This is called when end of file is reached. The userspace can inform DSP that
+  EOF is reached and now DSP can start skipping padding delay. Also next write
+  data would belong to next track
+
+Sequence flow for gapless would be:
+- Open
+- Get caps / codec caps
+- Set params
+- Set metadata of the first track
+- Fill data of the first track
+- Trigger start
+- User-space finished sending all,
+- Indicate next track data by sending set_next_track
+- Set metadata of the next track
+- then call partial_drain to flush most of buffer in DSP
+- Fill data of the next track
+- DSP switches to second track
+
+(note: order for partial_drain and write for next track can be reversed as well)
+
+
+Not supported
+=============
+- Support for VoIP/circuit-switched calls is not the target of this
+  API. Support for dynamic bit-rate changes would require a tight
+  coupling between the DSP and the host stack, limiting power savings.
+
+- Packet-loss concealment is not supported. This would require an
+  additional interface to let the decoder synthesize data when frames
+  are lost during transmission. This may be added in the future.
+
+- Volume control/routing is not handled by this API. Devices exposing a
+  compressed data interface will be considered as regular ALSA devices;
+  volume changes and routing information will be provided with regular
+  ALSA kcontrols.
+
+- Embedded audio effects. Such effects should be enabled in the same
+  manner, no matter if the input was PCM or compressed.
+
+- multichannel IEC encoding. Unclear if this is required.
+
+- Encoding/decoding acceleration is not supported as mentioned
+  above. It is possible to route the output of a decoder to a capture
+  stream, or even implement transcoding capabilities. This routing
+  would be enabled with ALSA kcontrols.
+
+- Audio policy/resource management. This API does not provide any
+  hooks to query the utilization of the audio DSP, nor any preemption
+  mechanisms.
+
+- No notion of underrun/overrun. Since the bytes written are compressed
+  in nature and data written/read doesn't translate directly to
+  rendered output in time, this does not deal with underrun/overrun and
+  maybe dealt in user-library
+
+
+Credits
+=======
+- Mark Brown and Liam Girdwood for discussions on the need for this API
+- Harsha Priya for her work on intel_sst compressed API
+- Rakesh Ughreja for valuable feedback
+- Sing Nallasellan, Sikkandar Madar and Prasanna Samaga for
+  demonstrating and quantifying the benefits of audio offload on a
+  real platform.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/control-names.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/control-names.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/control-names.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/control-names.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,142 @@
+===========================
+Standard ALSA Control Names
+===========================
+
+This document describes standard names of mixer controls.
+
+Standard Syntax
+---------------
+Syntax: [LOCATION] SOURCE [CHANNEL] [DIRECTION] FUNCTION
+
+
+DIRECTION
+~~~~~~~~~
+================	===============
+<nothing>		both directions
+Playback		one direction
+Capture			one direction
+Bypass Playback		one direction
+Bypass Capture		one direction
+================	===============
+
+FUNCTION
+~~~~~~~~
+========	=================================
+Switch		on/off switch
+Volume		amplifier
+Route		route control, hardware specific
+========	=================================
+
+CHANNEL
+~~~~~~~
+============	==================================================
+<nothing>	channel independent, or applies to all channels
+Front		front left/right channels
+Surround	rear left/right in 4.0/5.1 surround
+CLFE		C/LFE channels
+Center		center cannel
+LFE		LFE channel
+Side		side left/right for 7.1 surround
+============	==================================================
+
+LOCATION (Physical location of source)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+============	=====================
+Front		front position
+Rear		rear position
+Dock		on docking station
+Internal	internal
+============	=====================
+
+SOURCE
+~~~~~~
+===================	=================================================
+Master
+Master Mono
+Hardware Master
+Speaker			internal speaker
+Bass Speaker		internal LFE speaker
+Headphone
+Line Out
+Beep			beep generator
+Phone
+Phone Input
+Phone Output
+Synth
+FM
+Mic
+Headset Mic		mic part of combined headset jack - 4-pin
+			headphone + mic
+Headphone Mic		mic part of either/or - 3-pin headphone or mic
+Line			input only, use "Line Out" for output
+CD
+Video
+Zoom Video
+Aux
+PCM
+PCM Pan
+Loopback
+Analog Loopback		D/A -> A/D loopback
+Digital Loopback	playback -> capture loopback -
+			without analog path
+Mono
+Mono Output
+Multi
+ADC
+Wave
+Music
+I2S
+IEC958
+HDMI
+SPDIF			output only
+SPDIF In
+Digital In
+HDMI/DP			either HDMI or DisplayPort
+===================	=================================================
+
+Exceptions (deprecated)
+-----------------------
+
+=====================================	=======================
+[Analogue|Digital] Capture Source
+[Analogue|Digital] Capture Switch	aka input gain switch
+[Analogue|Digital] Capture Volume	aka input gain volume
+[Analogue|Digital] Playback Switch	aka output gain switch
+[Analogue|Digital] Playback Volume	aka output gain volume
+Tone Control - Switch
+Tone Control - Bass
+Tone Control - Treble
+3D Control - Switch
+3D Control - Center
+3D Control - Depth
+3D Control - Wide
+3D Control - Space
+3D Control - Level
+Mic Boost [(?dB)]
+=====================================	=======================
+
+PCM interface
+-------------
+
+===================	========================================
+Sample Clock Source	{ "Word", "Internal", "AutoSync" }
+Clock Sync Status	{ "Lock", "Sync", "No Lock" }
+External Rate		external capture rate
+Capture Rate		capture rate taken from external source
+===================	========================================
+
+IEC958 (S/PDIF) interface
+-------------------------
+
+============================================	======================================
+IEC958 [...] [Playback|Capture] Switch		turn on/off the IEC958 interface
+IEC958 [...] [Playback|Capture] Volume		digital volume control
+IEC958 [...] [Playback|Capture] Default		default or global value - read/write
+IEC958 [...] [Playback|Capture] Mask		consumer and professional mask
+IEC958 [...] [Playback|Capture] Con Mask	consumer mask
+IEC958 [...] [Playback|Capture] Pro Mask	professional mask
+IEC958 [...] [Playback|Capture] PCM Stream	the settings assigned to a PCM stream
+IEC958 Q-subcode [Playback|Capture] Default	Q-subcode bits
+
+IEC958 Preamble [Playback|Capture] Default	burst preamble words (4*16bits)
+============================================	======================================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/index.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/index.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,15 @@
+Designs and Implementations
+===========================
+
+.. toctree::
+   :maxdepth: 2
+
+   control-names
+   channel-mapping-api
+   compress-offload
+   timestamping
+   jack-controls
+   procfile
+   powersave
+   oss-emulation
+   seq-oss
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/jack-controls.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/jack-controls.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/jack-controls.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/jack-controls.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,48 @@
+==================
+ALSA Jack Controls
+==================
+
+Why we need Jack kcontrols
+==========================
+
+ALSA uses kcontrols to export audio controls(switch, volume, Mux, ...)
+to user space. This means userspace applications like pulseaudio can
+switch off headphones and switch on speakers when no headphones are
+pluged in.
+
+The old ALSA jack code only created input devices for each registered
+jack. These jack input devices are not readable by userspace devices
+that run as non root.
+
+The new jack code creates embedded jack kcontrols for each jack that
+can be read by any process.
+
+This can be combined with UCM to allow userspace to route audio more
+intelligently based on jack insertion or removal events.
+
+Jack Kcontrol Internals
+=======================
+
+Each jack will have a kcontrol list, so that we can create a kcontrol
+and attach it to the jack, at jack creation stage. We can also add a
+kcontrol to an existing jack, at anytime when required.
+
+Those kcontrols will be freed automatically when the Jack is freed.
+
+How to use jack kcontrols
+=========================
+
+In order to keep compatibility, snd_jack_new() has been modified by
+adding two params:
+
+initial_kctl
+  if true, create a kcontrol and add it to the jack list.
+phantom_jack
+  Don't create a input device for phantom jacks.
+
+HDA jacks can set phantom_jack to true in order to create a phantom
+jack and set initial_kctl to true to create an initial kcontrol with
+the correct id.
+
+ASoC jacks should set initial_kctl as false. The pin name will be
+assigned as the jack kcontrol name.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/oss-emulation.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/oss-emulation.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/oss-emulation.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/oss-emulation.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,336 @@
+=============================
+Notes on Kernel OSS-Emulation
+=============================
+
+Jan. 22, 2004  Takashi Iwai <tiwai@suse.de>
+
+
+Modules
+=======
+
+ALSA provides a powerful OSS emulation on the kernel.
+The OSS emulation for PCM, mixer and sequencer devices is implemented
+as add-on kernel modules, snd-pcm-oss, snd-mixer-oss and snd-seq-oss.
+When you need to access the OSS PCM, mixer or sequencer devices, the
+corresponding module has to be loaded.
+
+These modules are loaded automatically when the corresponding service
+is called.  The alias is defined ``sound-service-x-y``, where x and y are
+the card number and the minor unit number.  Usually you don't have to
+define these aliases by yourself.
+
+Only necessary step for auto-loading of OSS modules is to define the
+card alias in ``/etc/modprobe.d/alsa.conf``, such as::
+
+	alias sound-slot-0 snd-emu10k1
+
+As the second card, define ``sound-slot-1`` as well.
+Note that you can't use the aliased name as the target name (i.e.
+``alias sound-slot-0 snd-card-0`` doesn't work any more like the old
+modutils).
+
+The currently available OSS configuration is shown in
+/proc/asound/oss/sndstat.  This shows in the same syntax of
+/dev/sndstat, which is available on the commercial OSS driver.
+On ALSA, you can symlink /dev/sndstat to this proc file.
+
+Please note that the devices listed in this proc file appear only
+after the corresponding OSS-emulation module is loaded.  Don't worry
+even if "NOT ENABLED IN CONFIG" is shown in it.
+
+
+Device Mapping
+==============
+
+ALSA supports the following OSS device files:
+::
+
+	PCM:
+		/dev/dspX
+		/dev/adspX
+
+	Mixer:
+		/dev/mixerX
+
+	MIDI:
+		/dev/midi0X
+		/dev/amidi0X
+
+	Sequencer:
+		/dev/sequencer
+		/dev/sequencer2 (aka /dev/music)
+
+where X is the card number from 0 to 7.
+
+(NOTE: Some distributions have the device files like /dev/midi0 and
+/dev/midi1.  They are NOT for OSS but for tclmidi, which is
+a totally different thing.)
+
+Unlike the real OSS, ALSA cannot use the device files more than the
+assigned ones.  For example, the first card cannot use /dev/dsp1 or
+/dev/dsp2, but only /dev/dsp0 and /dev/adsp0.
+
+As seen above, PCM and MIDI may have two devices.  Usually, the first
+PCM device (``hw:0,0`` in ALSA) is mapped to /dev/dsp and the secondary
+device (``hw:0,1``) to /dev/adsp (if available).  For MIDI, /dev/midi and
+/dev/amidi, respectively.
+
+You can change this device mapping via the module options of
+snd-pcm-oss and snd-rawmidi.  In the case of PCM, the following
+options are available for snd-pcm-oss:
+
+dsp_map
+	PCM device number assigned to /dev/dspX
+	(default = 0)
+adsp_map
+	PCM device number assigned to /dev/adspX
+	(default = 1)
+
+For example, to map the third PCM device (``hw:0,2``) to /dev/adsp0,
+define like this:
+::
+
+	options snd-pcm-oss adsp_map=2
+
+The options take arrays.  For configuring the second card, specify
+two entries separated by comma.  For example, to map the third PCM
+device on the second card to /dev/adsp1, define like below:
+::
+
+	options snd-pcm-oss adsp_map=0,2
+
+To change the mapping of MIDI devices, the following options are
+available for snd-rawmidi:
+
+midi_map
+	MIDI device number assigned to /dev/midi0X
+	(default = 0)
+amidi_map
+	MIDI device number assigned to /dev/amidi0X
+	(default = 1)
+
+For example, to assign the third MIDI device on the first card to
+/dev/midi00, define as follows:
+::
+
+	options snd-rawmidi midi_map=2
+
+
+PCM Mode
+========
+
+As default, ALSA emulates the OSS PCM with so-called plugin layer,
+i.e. tries to convert the sample format, rate or channels
+automatically when the card doesn't support it natively.
+This will lead to some problems for some applications like quake or
+wine, especially if they use the card only in the MMAP mode.
+
+In such a case, you can change the behavior of PCM per application by
+writing a command to the proc file.  There is a proc file for each PCM
+stream, ``/proc/asound/cardX/pcmY[cp]/oss``, where X is the card number
+(zero-based), Y the PCM device number (zero-based), and ``p`` is for
+playback and ``c`` for capture, respectively.  Note that this proc file
+exists only after snd-pcm-oss module is loaded.
+
+The command sequence has the following syntax:
+::
+
+	app_name fragments fragment_size [options]
+
+``app_name`` is the name of application with (higher priority) or without
+path.
+``fragments`` specifies the number of fragments or zero if no specific
+number is given.
+``fragment_size`` is the size of fragment in bytes or zero if not given.
+``options`` is the optional parameters.  The following options are
+available:
+
+disable
+	the application tries to open a pcm device for
+	this channel but does not want to use it.
+direct
+	don't use plugins
+block
+	force block open mode
+non-block
+	force non-block open mode
+partial-frag
+	write also partial fragments (affects playback only)
+no-silence
+	do not fill silence ahead to avoid clicks
+
+The ``disable`` option is useful when one stream direction (playback or
+capture) is not handled correctly by the application although the
+hardware itself does support both directions.
+The ``direct`` option is used, as mentioned above, to bypass the automatic
+conversion and useful for MMAP-applications.
+For example, to playback the first PCM device without plugins for
+quake, send a command via echo like the following:
+::
+
+	% echo "quake 0 0 direct" > /proc/asound/card0/pcm0p/oss
+
+While quake wants only playback, you may append the second command
+to notify driver that only this direction is about to be allocated:
+::
+
+	% echo "quake 0 0 disable" > /proc/asound/card0/pcm0c/oss
+
+The permission of proc files depend on the module options of snd.
+As default it's set as root, so you'll likely need to be superuser for
+sending the command above.
+
+The block and non-block options are used to change the behavior of
+opening the device file.
+
+As default, ALSA behaves as original OSS drivers, i.e. does not block
+the file when it's busy. The -EBUSY error is returned in this case.
+
+This blocking behavior can be changed globally via nonblock_open
+module option of snd-pcm-oss.  For using the blocking mode as default
+for OSS devices, define like the following:
+::
+
+	options snd-pcm-oss nonblock_open=0
+
+The ``partial-frag`` and ``no-silence`` commands have been added recently.
+Both commands are for optimization use only.  The former command
+specifies to invoke the write transfer only when the whole fragment is
+filled.  The latter stops writing the silence data ahead
+automatically.  Both are disabled as default.
+
+You can check the currently defined configuration by reading the proc
+file.  The read image can be sent to the proc file again, hence you
+can save the current configuration
+::
+
+	% cat /proc/asound/card0/pcm0p/oss > /somewhere/oss-cfg
+
+and restore it like
+::
+
+	% cat /somewhere/oss-cfg > /proc/asound/card0/pcm0p/oss
+
+Also, for clearing all the current configuration, send ``erase`` command
+as below:
+::
+
+	% echo "erase" > /proc/asound/card0/pcm0p/oss
+
+
+Mixer Elements
+==============
+
+Since ALSA has completely different mixer interface, the emulation of
+OSS mixer is relatively complicated.  ALSA builds up a mixer element
+from several different ALSA (mixer) controls based on the name
+string.  For example, the volume element SOUND_MIXER_PCM is composed
+from "PCM Playback Volume" and "PCM Playback Switch" controls for the
+playback direction and from "PCM Capture Volume" and "PCM Capture
+Switch" for the capture directory (if exists).  When the PCM volume of
+OSS is changed, all the volume and switch controls above are adjusted
+automatically.
+
+As default, ALSA uses the following control for OSS volumes:
+
+====================	=====================	=====
+OSS volume		ALSA control		Index
+====================	=====================	=====
+SOUND_MIXER_VOLUME 	Master			0
+SOUND_MIXER_BASS	Tone Control - Bass	0
+SOUND_MIXER_TREBLE	Tone Control - Treble	0
+SOUND_MIXER_SYNTH	Synth			0
+SOUND_MIXER_PCM		PCM			0
+SOUND_MIXER_SPEAKER	PC Speaker 		0
+SOUND_MIXER_LINE	Line			0
+SOUND_MIXER_MIC		Mic 			0
+SOUND_MIXER_CD		CD 			0
+SOUND_MIXER_IMIX	Monitor Mix 		0
+SOUND_MIXER_ALTPCM	PCM			1
+SOUND_MIXER_RECLEV	(not assigned)
+SOUND_MIXER_IGAIN	Capture			0
+SOUND_MIXER_OGAIN	Playback		0
+SOUND_MIXER_LINE1	Aux			0
+SOUND_MIXER_LINE2	Aux			1
+SOUND_MIXER_LINE3	Aux			2
+SOUND_MIXER_DIGITAL1	Digital			0
+SOUND_MIXER_DIGITAL2	Digital			1
+SOUND_MIXER_DIGITAL3	Digital			2
+SOUND_MIXER_PHONEIN	Phone			0
+SOUND_MIXER_PHONEOUT	Phone			1
+SOUND_MIXER_VIDEO	Video			0
+SOUND_MIXER_RADIO	Radio			0
+SOUND_MIXER_MONITOR	Monitor			0
+====================	=====================	=====
+
+The second column is the base-string of the corresponding ALSA
+control.  In fact, the controls with ``XXX [Playback|Capture]
+[Volume|Switch]`` will be checked in addition.
+
+The current assignment of these mixer elements is listed in the proc
+file, /proc/asound/cardX/oss_mixer, which will be like the following
+::
+
+	VOLUME "Master" 0
+	BASS "" 0
+	TREBLE "" 0
+	SYNTH "" 0
+	PCM "PCM" 0
+	...
+
+where the first column is the OSS volume element, the second column
+the base-string of the corresponding ALSA control, and the third the
+control index.  When the string is empty, it means that the
+corresponding OSS control is not available.
+
+For changing the assignment, you can write the configuration to this
+proc file.  For example, to map "Wave Playback" to the PCM volume,
+send the command like the following:
+::
+
+	% echo 'VOLUME "Wave Playback" 0' > /proc/asound/card0/oss_mixer
+
+The command is exactly as same as listed in the proc file.  You can
+change one or more elements, one volume per line.  In the last
+example, both "Wave Playback Volume" and "Wave Playback Switch" will
+be affected when PCM volume is changed.
+
+Like the case of PCM proc file, the permission of proc files depend on
+the module options of snd.  you'll likely need to be superuser for
+sending the command above.
+
+As well as in the case of PCM proc file, you can save and restore the
+current mixer configuration by reading and writing the whole file
+image.
+
+
+Duplex Streams
+==============
+
+Note that when attempting to use a single device file for playback and
+capture, the OSS API provides no way to set the format, sample rate or
+number of channels different in each direction.  Thus
+::
+
+	io_handle = open("device", O_RDWR)
+
+will only function correctly if the values are the same in each direction.
+
+To use different values in the two directions, use both
+::
+
+	input_handle = open("device", O_RDONLY)
+	output_handle = open("device", O_WRONLY)
+
+and set the values for the corresponding handle.
+
+
+Unsupported Features
+====================
+
+MMAP on ICE1712 driver
+----------------------
+ICE1712 supports only the unconventional format, interleaved
+10-channels 24bit (packed in 32bit) format.  Therefore you cannot mmap
+the buffer as the conventional (mono or 2-channels, 8 or 16bit) format
+on OSS.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/powersave.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/powersave.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/powersave.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/powersave.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,43 @@
+==========================
+Notes on Power-Saving Mode
+==========================
+
+AC97 and HD-audio drivers have the automatic power-saving mode.
+This feature is enabled via Kconfig ``CONFIG_SND_AC97_POWER_SAVE``
+and ``CONFIG_SND_HDA_POWER_SAVE`` options, respectively.
+
+With the automatic power-saving, the driver turns off the codec power
+appropriately when no operation is required.  When no applications use
+the device and/or no analog loopback is set, the power disablement is
+done fully or partially.  It'll save a certain power consumption, thus
+good for laptops (even for desktops).
+
+The time-out for automatic power-off can be specified via ``power_save``
+module option of snd-ac97-codec and snd-hda-intel modules.  Specify
+the time-out value in seconds.  0 means to disable the automatic
+power-saving.  The default value of timeout is given via
+``CONFIG_SND_AC97_POWER_SAVE_DEFAULT`` and
+``CONFIG_SND_HDA_POWER_SAVE_DEFAULT`` Kconfig options.  Setting this to 1
+(the minimum value) isn't recommended because many applications try to
+reopen the device frequently.  10 would be a good choice for normal
+operations.
+
+The ``power_save`` option is exported as writable.  This means you can
+adjust the value via sysfs on the fly.  For example, to turn on the
+automatic power-save mode with 10 seconds, write to
+``/sys/modules/snd_ac97_codec/parameters/power_save`` (usually as root):
+::
+
+	# echo 10 > /sys/modules/snd_ac97_codec/parameters/power_save
+
+
+Note that you might hear click noise/pop when changing the power
+state.  Also, it often takes certain time to wake up from the
+power-down to the active state.  These are often hardly to fix, so
+don't report extra bug reports unless you have a fix patch ;-)
+
+For HD-audio interface, there is another module option,
+power_save_controller.  This enables/disables the power-save mode of
+the controller side.  Setting this on may reduce a bit more power
+consumption, but might result in longer wake-up time and click noise.
+Try to turn it off when you experience such a thing too often.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/procfile.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/procfile.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/procfile.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/procfile.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,238 @@
+==========================
+Proc Files of ALSA Drivers
+==========================
+
+Takashi Iwai <tiwai@suse.de>
+
+General
+=======
+
+ALSA has its own proc tree, /proc/asound.  Many useful information are
+found in this tree.  When you encounter a problem and need debugging,
+check the files listed in the following sections.
+
+Each card has its subtree cardX, where X is from 0 to 7. The
+card-specific files are stored in the ``card*`` subdirectories.
+
+
+Global Information
+==================
+
+cards
+	Shows the list of currently configured ALSA drivers,
+	index, the id string, short and long descriptions.
+
+version
+	Shows the version string and compile date.
+
+modules
+	Lists the module of each card
+
+devices
+	Lists the ALSA native device mappings.
+
+meminfo
+	Shows the status of allocated pages via ALSA drivers.
+	Appears only when ``CONFIG_SND_DEBUG=y``.
+
+hwdep
+	Lists the currently available hwdep devices in format of
+	``<card>-<device>: <name>``
+
+pcm
+	Lists the currently available PCM devices in format of
+	``<card>-<device>: <id>: <name> : <sub-streams>``
+
+timer
+	Lists the currently available timer devices
+
+
+oss/devices
+	Lists the OSS device mappings.
+
+oss/sndstat
+	Provides the output compatible with /dev/sndstat.
+	You can symlink this to /dev/sndstat.
+
+
+Card Specific Files
+===================
+
+The card-specific files are found in ``/proc/asound/card*`` directories.
+Some drivers (e.g. cmipci) have their own proc entries for the
+register dump, etc (e.g. ``/proc/asound/card*/cmipci`` shows the register
+dump).  These files would be really helpful for debugging.
+
+When PCM devices are available on this card, you can see directories
+like pcm0p or pcm1c.  They hold the PCM information for each PCM
+stream.  The number after ``pcm`` is the PCM device number from 0, and
+the last ``p`` or ``c`` means playback or capture direction.  The files in
+this subtree is described later.
+
+The status of MIDI I/O is found in ``midi*`` files.  It shows the device
+name and the received/transmitted bytes through the MIDI device.
+
+When the card is equipped with AC97 codecs, there are ``codec97#*``
+subdirectories (described later).
+
+When the OSS mixer emulation is enabled (and the module is loaded),
+oss_mixer file appears here, too.  This shows the current mapping of
+OSS mixer elements to the ALSA control elements.  You can change the
+mapping by writing to this device.  Read OSS-Emulation.txt for
+details.
+
+
+PCM Proc Files
+==============
+
+``card*/pcm*/info``
+	The general information of this PCM device: card #, device #,
+	substreams, etc.
+
+``card*/pcm*/xrun_debug``
+	This file appears when ``CONFIG_SND_DEBUG=y`` and
+	``CONFIG_PCM_XRUN_DEBUG=y``.
+	This shows the status of xrun (= buffer overrun/xrun) and
+	invalid PCM position debug/check of ALSA PCM middle layer.
+	It takes an integer value, can be changed by writing to this
+	file, such as::
+
+		 # echo 5 > /proc/asound/card0/pcm0p/xrun_debug
+
+	The value consists of the following bit flags:
+
+	* bit 0 = Enable XRUN/jiffies debug messages
+	* bit 1 = Show stack trace at XRUN / jiffies check
+	* bit 2 = Enable additional jiffies check
+
+	When the bit 0 is set, the driver will show the messages to
+	kernel log when an xrun is detected.  The debug message is
+	shown also when the invalid H/W pointer is detected at the
+	update of periods (usually called from the interrupt
+	handler).
+
+	When the bit 1 is set, the driver will show the stack trace
+	additionally.  This may help the debugging.
+
+	Since 2.6.30, this option can enable the hwptr check using
+	jiffies.  This detects spontaneous invalid pointer callback
+	values, but can be lead to too much corrections for a (mostly
+	buggy) hardware that doesn't give smooth pointer updates.
+	This feature is enabled via the bit 2.
+
+``card*/pcm*/sub*/info``
+	The general information of this PCM sub-stream.
+
+``card*/pcm*/sub*/status``
+	The current status of this PCM sub-stream, elapsed time,
+	H/W position, etc.
+
+``card*/pcm*/sub*/hw_params``
+	The hardware parameters set for this sub-stream.
+
+``card*/pcm*/sub*/sw_params``
+	The soft parameters set for this sub-stream.
+
+``card*/pcm*/sub*/prealloc``
+	The buffer pre-allocation information.
+
+``card*/pcm*/sub*/xrun_injection``
+	Triggers an XRUN to the running stream when any value is
+	written to this proc file.  Used for fault injection.
+	This entry is write-only.
+
+AC97 Codec Information
+======================
+
+``card*/codec97#*/ac97#?-?``
+	Shows the general information of this AC97 codec chip, such as
+	name, capabilities, set up.
+
+``card*/codec97#0/ac97#?-?+regs``
+	Shows the AC97 register dump.  Useful for debugging.
+
+	When CONFIG_SND_DEBUG is enabled, you can write to this file for
+	changing an AC97 register directly.  Pass two hex numbers.
+	For example,
+
+::
+
+	# echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs
+
+
+USB Audio Streams
+=================
+
+``card*/stream*``
+	Shows the assignment and the current status of each audio stream
+	of the given card.  This information is very useful for debugging.
+
+
+HD-Audio Codecs
+===============
+
+``card*/codec#*``
+	Shows the general codec information and the attribute of each
+	widget node.
+
+``card*/eld#*``
+	Available for HDMI or DisplayPort interfaces.
+	Shows ELD(EDID Like Data) info retrieved from the attached HDMI sink,
+	and describes its audio capabilities and configurations.
+
+	Some ELD fields may be modified by doing ``echo name hex_value > eld#*``.
+	Only do this if you are sure the HDMI sink provided value is wrong.
+	And if that makes your HDMI audio work, please report to us so that we
+	can fix it in future kernel releases.
+
+
+Sequencer Information
+=====================
+
+seq/drivers
+	Lists the currently available ALSA sequencer drivers.
+
+seq/clients
+	Shows the list of currently available sequencer clients and
+	ports.  The connection status and the running status are shown
+	in this file, too.
+
+seq/queues
+	Lists the currently allocated/running sequencer queues.
+
+seq/timer
+	Lists the currently allocated/running sequencer timers.
+
+seq/oss
+	Lists the OSS-compatible sequencer stuffs.
+
+
+Help For Debugging?
+===================
+
+When the problem is related with PCM, first try to turn on xrun_debug
+mode.  This will give you the kernel messages when and where xrun
+happened.
+
+If it's really a bug, report it with the following information:
+
+- the name of the driver/card, show in ``/proc/asound/cards``
+- the register dump, if available (e.g. ``card*/cmipci``)
+
+when it's a PCM problem,
+
+- set-up of PCM, shown in hw_parms, sw_params, and status in the PCM
+  sub-stream directory
+
+when it's a mixer problem,
+
+- AC97 proc files, ``codec97#*/*`` files
+
+for USB audio/midi,
+
+- output of ``lsusb -v``
+- ``stream*`` files in card directory
+
+
+The ALSA bug-tracking system is found at:
+https://bugtrack.alsa-project.org/alsa-bug/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/seq-oss.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/seq-oss.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/seq-oss.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/seq-oss.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,371 @@
+===============================
+OSS Sequencer Emulation on ALSA
+===============================
+
+Copyright (c) 1998,1999 by Takashi Iwai
+
+ver.0.1.8; Nov. 16, 1999
+
+Description
+===========
+
+This directory contains the OSS sequencer emulation driver on ALSA. Note
+that this program is still in the development state.
+
+What this does - it provides the emulation of the OSS sequencer, access
+via ``/dev/sequencer`` and ``/dev/music`` devices.
+The most of applications using OSS can run if the appropriate ALSA
+sequencer is prepared.
+
+The following features are emulated by this driver:
+
+* Normal sequencer and MIDI events:
+
+    They are converted to the ALSA sequencer events, and sent to the
+    corresponding port.
+
+* Timer events:
+
+    The timer is not selectable by ioctl. The control rate is fixed to
+    100 regardless of HZ. That is, even on Alpha system, a tick is always
+    1/100 second. The base rate and tempo can be changed in ``/dev/music``.
+
+* Patch loading:
+
+    It purely depends on the synth drivers whether it's supported since
+    the patch loading is realized by callback to the synth driver.
+
+* I/O controls:
+
+    Most of controls are accepted. Some controls
+    are dependent on the synth driver, as well as even on original OSS.
+
+Furthermore, you can find the following advanced features:
+
+* Better queue mechanism:
+
+    The events are queued before processing them.
+
+* Multiple applications:
+
+    You can run two or more applications simultaneously (even for OSS
+    sequencer)!
+    However, each MIDI device is exclusive - that is, if a MIDI device
+    is opened once by some application, other applications can't use
+    it. No such a restriction in synth devices.
+
+* Real-time event processing:
+
+    The events can be processed in real time without using out of bound
+    ioctl. To switch to real-time mode, send ABSTIME 0 event. The followed
+    events will be processed in real-time without queued. To switch off the
+    real-time mode, send RELTIME 0 event.
+
+* ``/proc`` interface:
+
+    The status of applications and devices can be shown via
+    ``/proc/asound/seq/oss`` at any time. In the later version,
+    configuration will be changed via ``/proc`` interface, too.
+
+
+Installation
+============
+
+Run configure script with both sequencer support (``--with-sequencer=yes``)
+and OSS emulation (``--with-oss=yes``) options. A module ``snd-seq-oss.o``
+will be created. If the synth module of your sound card supports for OSS
+emulation (so far, only Emu8000 driver), this module will be loaded
+automatically.
+Otherwise, you need to load this module manually.
+
+At beginning, this module probes all the MIDI ports which have been
+already connected to the sequencer. Once after that, the creation and deletion
+of ports are watched by announcement mechanism of ALSA sequencer.
+
+The available synth and MIDI devices can be found in proc interface.
+Run ``cat /proc/asound/seq/oss``, and check the devices. For example,
+if you use an AWE64 card, you'll see like the following:
+::
+
+    OSS sequencer emulation version 0.1.8
+    ALSA client number 63
+    ALSA receiver port 0
+
+    Number of applications: 0
+
+    Number of synth devices: 1
+    synth 0: [EMU8000]
+      type 0x1 : subtype 0x20 : voices 32
+      capabilties : ioctl enabled / load_patch enabled
+
+    Number of MIDI devices: 3
+    midi 0: [Emu8000 Port-0] ALSA port 65:0
+      capability write / opened none
+
+    midi 1: [Emu8000 Port-1] ALSA port 65:1
+      capability write / opened none
+
+    midi 2: [0: MPU-401 (UART)] ALSA port 64:0
+      capability read/write / opened none
+
+Note that the device number may be different from the information of
+``/proc/asound/oss-devices`` or ones of the original OSS driver.
+Use the device number listed in ``/proc/asound/seq/oss``
+to play via OSS sequencer emulation.
+
+Using Synthesizer Devices
+=========================
+
+Run your favorite program. I've tested playmidi-2.4, awemidi-0.4.3, gmod-3.1
+and xmp-1.1.5. You can load samples via ``/dev/sequencer`` like sfxload,
+too.
+
+If the lowlevel driver supports multiple access to synth devices (like
+Emu8000 driver), two or more applications are allowed to run at the same
+time.
+
+Using MIDI Devices
+==================
+
+So far, only MIDI output was tested. MIDI input was not checked at all,
+but hopefully it will work. Use the device number listed in
+``/proc/asound/seq/oss``.
+Be aware that these numbers are mostly different from the list in
+``/proc/asound/oss-devices``.
+
+Module Options
+==============
+
+The following module options are available:
+
+maxqlen
+  specifies the maximum read/write queue length. This queue is private
+  for OSS sequencer, so that it is independent from the queue length of ALSA
+  sequencer. Default value is 1024.
+
+seq_oss_debug
+  specifies the debug level and accepts zero (= no debug message) or
+  positive integer. Default value is 0.
+
+Queue Mechanism
+===============
+
+OSS sequencer emulation uses an ALSA priority queue. The
+events from ``/dev/sequencer`` are processed and put onto the queue
+specified by module option.
+
+All the events from ``/dev/sequencer`` are parsed at beginning.
+The timing events are also parsed at this moment, so that the events may
+be processed in real-time. Sending an event ABSTIME 0 switches the operation
+mode to real-time mode, and sending an event RELTIME 0 switches it off.
+In the real-time mode, all events are dispatched immediately.
+
+The queued events are dispatched to the corresponding ALSA sequencer
+ports after scheduled time by ALSA sequencer dispatcher.
+
+If the write-queue is full, the application sleeps until a certain amount
+(as default one half) becomes empty in blocking mode. The synchronization
+to write timing was implemented, too.
+
+The input from MIDI devices or echo-back events are stored on read FIFO
+queue. If application reads ``/dev/sequencer`` in blocking mode, the
+process will be awaked.
+
+Interface to Synthesizer Device
+===============================
+
+Registration
+------------
+
+To register an OSS synthesizer device, use snd_seq_oss_synth_register()
+function:
+::
+
+  int snd_seq_oss_synth_register(char *name, int type, int subtype, int nvoices,
+          snd_seq_oss_callback_t *oper, void *private_data)
+
+The arguments ``name``, ``type``, ``subtype`` and ``nvoices``
+are used for making the appropriate synth_info structure for ioctl. The
+return value is an index number of this device. This index must be remembered
+for unregister. If registration is failed, -errno will be returned.
+
+To release this device, call snd_seq_oss_synth_unregister() function:
+::
+
+  int snd_seq_oss_synth_unregister(int index)
+
+where the ``index`` is the index number returned by register function.
+
+Callbacks
+---------
+
+OSS synthesizer devices have capability for sample downloading and ioctls
+like sample reset. In OSS emulation, these special features are realized
+by using callbacks. The registration argument oper is used to specify these
+callbacks. The following callback functions must be defined:
+::
+
+  snd_seq_oss_callback_t:
+   int (*open)(snd_seq_oss_arg_t *p, void *closure);
+   int (*close)(snd_seq_oss_arg_t *p);
+   int (*ioctl)(snd_seq_oss_arg_t *p, unsigned int cmd, unsigned long arg);
+   int (*load_patch)(snd_seq_oss_arg_t *p, int format, const char *buf, int offs, int count);
+   int (*reset)(snd_seq_oss_arg_t *p);
+
+Except for ``open`` and ``close`` callbacks, they are allowed to be NULL.
+
+Each callback function takes the argument type ``snd_seq_oss_arg_t`` as the
+first argument.
+::
+
+  struct snd_seq_oss_arg_t {
+      int app_index;
+      int file_mode;
+      int seq_mode;
+      snd_seq_addr_t addr;
+      void *private_data;
+      int event_passing;
+  };
+
+The first three fields, ``app_index``, ``file_mode`` and ``seq_mode``
+are initialized by OSS sequencer. The ``app_index`` is the application
+index which is unique to each application opening OSS sequencer. The
+``file_mode`` is bit-flags indicating the file operation mode. See
+``seq_oss.h`` for its meaning. The ``seq_mode`` is sequencer operation
+mode. In the current version, only ``SND_OSSSEQ_MODE_SYNTH`` is used.
+
+The next two fields, ``addr`` and ``private_data``, must be
+filled by the synth driver at open callback. The ``addr`` contains
+the address of ALSA sequencer port which is assigned to this device. If
+the driver allocates memory for ``private_data``, it must be released
+in close callback by itself.
+
+The last field, ``event_passing``, indicates how to translate note-on
+/ off events. In ``PROCESS_EVENTS`` mode, the note 255 is regarded
+as velocity change, and key pressure event is passed to the port. In
+``PASS_EVENTS`` mode, all note on/off events are passed to the port
+without modified. ``PROCESS_KEYPRESS`` mode checks the note above 128
+and regards it as key pressure event (mainly for Emu8000 driver).
+
+Open Callback
+-------------
+
+The ``open`` is called at each time this device is opened by an application
+using OSS sequencer. This must not be NULL. Typically, the open callback
+does the following procedure:
+
+#. Allocate private data record.
+#. Create an ALSA sequencer port.
+#. Set the new port address on ``arg->addr``.
+#. Set the private data record pointer on ``arg->private_data``.
+
+Note that the type bit-flags in port_info of this synth port must NOT contain
+``TYPE_MIDI_GENERIC``
+bit. Instead, ``TYPE_SPECIFIC`` should be used. Also, ``CAP_SUBSCRIPTION``
+bit should NOT be included, too. This is necessary to tell it from other
+normal MIDI devices. If the open procedure succeeded, return zero. Otherwise,
+return -errno.
+
+Ioctl Callback
+--------------
+
+The ``ioctl`` callback is called when the sequencer receives device-specific
+ioctls. The following two ioctls should be processed by this callback:
+
+IOCTL_SEQ_RESET_SAMPLES
+    reset all samples on memory -- return 0
+
+IOCTL_SYNTH_MEMAVL
+    return the available memory size
+
+FM_4OP_ENABLE
+    can be ignored usually
+
+The other ioctls are processed inside the sequencer without passing to
+the lowlevel driver.
+
+Load_Patch Callback
+-------------------
+
+The ``load_patch`` callback is used for sample-downloading. This callback
+must read the data on user-space and transfer to each device. Return 0
+if succeeded, and -errno if failed. The format argument is the patch key
+in patch_info record. The buf is user-space pointer where patch_info record
+is stored. The offs can be ignored. The count is total data size of this
+sample data.
+
+Close Callback
+--------------
+
+The ``close`` callback is called when this device is closed by the
+application. If any private data was allocated in open callback, it must
+be released in the close callback. The deletion of ALSA port should be
+done here, too. This callback must not be NULL.
+
+Reset Callback
+--------------
+
+The ``reset`` callback is called when sequencer device is reset or
+closed by applications. The callback should turn off the sounds on the
+relevant port immediately, and initialize the status of the port. If this
+callback is undefined, OSS seq sends a ``HEARTBEAT`` event to the
+port.
+
+Events
+======
+
+Most of the events are processed by sequencer and translated to the adequate
+ALSA sequencer events, so that each synth device can receive by input_event
+callback of ALSA sequencer port. The following ALSA events should be
+implemented by the driver:
+
+=============	===================
+ALSA event	Original OSS events
+=============	===================
+NOTEON		SEQ_NOTEON, MIDI_NOTEON
+NOTE		SEQ_NOTEOFF, MIDI_NOTEOFF
+KEYPRESS	MIDI_KEY_PRESSURE
+CHANPRESS	SEQ_AFTERTOUCH, MIDI_CHN_PRESSURE
+PGMCHANGE	SEQ_PGMCHANGE, MIDI_PGM_CHANGE
+PITCHBEND	SEQ_CONTROLLER(CTRL_PITCH_BENDER),
+		MIDI_PITCH_BEND
+CONTROLLER	MIDI_CTL_CHANGE,
+		SEQ_BALANCE (with CTL_PAN)
+CONTROL14	SEQ_CONTROLLER
+REGPARAM	SEQ_CONTROLLER(CTRL_PITCH_BENDER_RANGE)
+SYSEX		SEQ_SYSEX
+=============	===================
+
+The most of these behavior can be realized by MIDI emulation driver
+included in the Emu8000 lowlevel driver. In the future release, this module
+will be independent.
+
+Some OSS events (``SEQ_PRIVATE`` and ``SEQ_VOLUME`` events) are passed as event
+type SND_SEQ_OSS_PRIVATE.  The OSS sequencer passes these event 8 byte
+packets without any modification. The lowlevel driver should process these
+events appropriately.
+
+Interface to MIDI Device
+========================
+
+Since the OSS emulation probes the creation and deletion of ALSA MIDI
+sequencer ports automatically by receiving announcement from ALSA
+sequencer, the MIDI devices don't need to be registered explicitly
+like synth devices.
+However, the MIDI port_info registered to ALSA sequencer must include
+a group name ``SND_SEQ_GROUP_DEVICE`` and a capability-bit
+``CAP_READ`` or ``CAP_WRITE``. Also, subscription capabilities,
+``CAP_SUBS_READ`` or ``CAP_SUBS_WRITE``, must be defined, too. If
+these conditions are not satisfied, the port is not registered as OSS
+sequencer MIDI device.
+
+The events via MIDI devices are parsed in OSS sequencer and converted
+to the corresponding ALSA sequencer events. The input from MIDI sequencer
+is also converted to MIDI byte events by OSS sequencer. This works just
+a reverse way of seq_midi module.
+
+Known Problems / TODO's
+=======================
+
+* Patch loading via ALSA instrument layer is not implemented yet.
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/designs/timestamping.rst linux-libre-4.10-rc8-gnu/Documentation/sound/designs/timestamping.rst
--- linux-libre-4.9-gnu/Documentation/sound/designs/timestamping.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/designs/timestamping.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,215 @@
+=====================
+ALSA PCM Timestamping
+=====================
+
+The ALSA API can provide two different system timestamps:
+
+- Trigger_tstamp is the system time snapshot taken when the .trigger
+  callback is invoked. This snapshot is taken by the ALSA core in the
+  general case, but specific hardware may have synchronization
+  capabilities or conversely may only be able to provide a correct
+  estimate with a delay. In the latter two cases, the low-level driver
+  is responsible for updating the trigger_tstamp at the most appropriate
+  and precise moment. Applications should not rely solely on the first
+  trigger_tstamp but update their internal calculations if the driver
+  provides a refined estimate with a delay.
+
+- tstamp is the current system timestamp updated during the last
+  event or application query.
+  The difference (tstamp - trigger_tstamp) defines the elapsed time.
+
+The ALSA API provides two basic pieces of information, avail
+and delay, which combined with the trigger and current system
+timestamps allow for applications to keep track of the 'fullness' of
+the ring buffer and the amount of queued samples.
+
+The use of these different pointers and time information depends on
+the application needs:
+
+- ``avail`` reports how much can be written in the ring buffer
+- ``delay`` reports the time it will take to hear a new sample after all
+  queued samples have been played out.
+
+When timestamps are enabled, the avail/delay information is reported
+along with a snapshot of system time. Applications can select from
+``CLOCK_REALTIME`` (NTP corrections including going backwards),
+``CLOCK_MONOTONIC`` (NTP corrections but never going backwards),
+``CLOCK_MONOTIC_RAW`` (without NTP corrections) and change the mode
+dynamically with sw_params
+
+
+The ALSA API also provide an audio_tstamp which reflects the passage
+of time as measured by different components of audio hardware.  In
+ascii-art, this could be represented as follows (for the playback
+case):
+::
+
+  --------------------------------------------------------------> time
+    ^               ^              ^                ^           ^
+    |               |              |                |           |
+   analog         link            dma              app       FullBuffer
+   time           time           time              time        time
+    |               |              |                |           |
+    |< codec delay >|<--hw delay-->|<queued samples>|<---avail->|
+    |<----------------- delay---------------------->|           |
+                                   |<----ring buffer length---->|
+
+
+The analog time is taken at the last stage of the playback, as close
+as possible to the actual transducer
+
+The link time is taken at the output of the SoC/chipset as the samples
+are pushed on a link. The link time can be directly measured if
+supported in hardware by sample counters or wallclocks (e.g. with
+HDAudio 24MHz or PTP clock for networked solutions) or indirectly
+estimated (e.g. with the frame counter in USB).
+
+The DMA time is measured using counters - typically the least reliable
+of all measurements due to the bursty nature of DMA transfers.
+
+The app time corresponds to the time tracked by an application after
+writing in the ring buffer.
+
+The application can query the hardware capabilities, define which
+audio time it wants reported by selecting the relevant settings in
+audio_tstamp_config fields, thus get an estimate of the timestamp
+accuracy. It can also request the delay-to-analog be included in the
+measurement. Direct access to the link time is very interesting on
+platforms that provide an embedded DSP; measuring directly the link
+time with dedicated hardware, possibly synchronized with system time,
+removes the need to keep track of internal DSP processing times and
+latency.
+
+In case the application requests an audio tstamp that is not supported
+in hardware/low-level driver, the type is overridden as DEFAULT and the
+timestamp will report the DMA time based on the hw_pointer value.
+
+For backwards compatibility with previous implementations that did not
+provide timestamp selection, with a zero-valued COMPAT timestamp type
+the results will default to the HDAudio wall clock for playback
+streams and to the DMA time (hw_ptr) in all other cases.
+
+The audio timestamp accuracy can be returned to user-space, so that
+appropriate decisions are made:
+
+- for dma time (default), the granularity of the transfers can be
+  inferred from the steps between updates and in turn provide
+  information on how much the application pointer can be rewound
+  safely.
+
+- the link time can be used to track long-term drifts between audio
+  and system time using the (tstamp-trigger_tstamp)/audio_tstamp
+  ratio, the precision helps define how much smoothing/low-pass
+  filtering is required. The link time can be either reset on startup
+  or reported as is (the latter being useful to compare progress of
+  different streams - but may require the wallclock to be always
+  running and not wrap-around during idle periods). If supported in
+  hardware, the absolute link time could also be used to define a
+  precise start time (patches WIP)
+
+- including the delay in the audio timestamp may
+  counter-intuitively not increase the precision of timestamps, e.g. if a
+  codec includes variable-latency DSP processing or a chain of
+  hardware components the delay is typically not known with precision.
+
+The accuracy is reported in nanosecond units (using an unsigned 32-bit
+word), which gives a max precision of 4.29s, more than enough for
+audio applications...
+
+Due to the varied nature of timestamping needs, even for a single
+application, the audio_tstamp_config can be changed dynamically. In
+the ``STATUS`` ioctl, the parameters are read-only and do not allow for
+any application selection. To work around this limitation without
+impacting legacy applications, a new ``STATUS_EXT`` ioctl is introduced
+with read/write parameters. ALSA-lib will be modified to make use of
+``STATUS_EXT`` and effectively deprecate ``STATUS``.
+
+The ALSA API only allows for a single audio timestamp to be reported
+at a time. This is a conscious design decision, reading the audio
+timestamps from hardware registers or from IPC takes time, the more
+timestamps are read the more imprecise the combined measurements
+are. To avoid any interpretation issues, a single (system, audio)
+timestamp is reported. Applications that need different timestamps
+will be required to issue multiple queries and perform an
+interpolation of the results
+
+In some hardware-specific configuration, the system timestamp is
+latched by a low-level audio subsystem, and the information provided
+back to the driver. Due to potential delays in the communication with
+the hardware, there is a risk of misalignment with the avail and delay
+information. To make sure applications are not confused, a
+driver_timestamp field is added in the snd_pcm_status structure; this
+timestamp shows when the information is put together by the driver
+before returning from the ``STATUS`` and ``STATUS_EXT`` ioctl. in most cases
+this driver_timestamp will be identical to the regular system tstamp.
+
+Examples of typestamping with HDaudio:
+
+1. DMA timestamp, no compensation for DMA+analog delay
+::
+
+  $ ./audio_time  -p --ts_type=1
+  playback: systime: 341121338 nsec, audio time 342000000 nsec, 	systime delta -878662
+  playback: systime: 426236663 nsec, audio time 427187500 nsec, 	systime delta -950837
+  playback: systime: 597080580 nsec, audio time 598000000 nsec, 	systime delta -919420
+  playback: systime: 682059782 nsec, audio time 683020833 nsec, 	systime delta -961051
+  playback: systime: 852896415 nsec, audio time 853854166 nsec, 	systime delta -957751
+  playback: systime: 937903344 nsec, audio time 938854166 nsec, 	systime delta -950822
+
+2. DMA timestamp, compensation for DMA+analog delay
+::
+
+  $ ./audio_time  -p --ts_type=1 -d
+  playback: systime: 341053347 nsec, audio time 341062500 nsec, 	systime delta -9153
+  playback: systime: 426072447 nsec, audio time 426062500 nsec, 	systime delta 9947
+  playback: systime: 596899518 nsec, audio time 596895833 nsec, 	systime delta 3685
+  playback: systime: 681915317 nsec, audio time 681916666 nsec, 	systime delta -1349
+  playback: systime: 852741306 nsec, audio time 852750000 nsec, 	systime delta -8694
+
+3. link timestamp, compensation for DMA+analog delay
+::
+
+  $ ./audio_time  -p --ts_type=2 -d
+  playback: systime: 341060004 nsec, audio time 341062791 nsec, 	systime delta -2787
+  playback: systime: 426242074 nsec, audio time 426244875 nsec, 	systime delta -2801
+  playback: systime: 597080992 nsec, audio time 597084583 nsec, 	systime delta -3591
+  playback: systime: 682084512 nsec, audio time 682088291 nsec, 	systime delta -3779
+  playback: systime: 852936229 nsec, audio time 852940916 nsec, 	systime delta -4687
+  playback: systime: 938107562 nsec, audio time 938112708 nsec, 	systime delta -5146
+
+Example 1 shows that the timestamp at the DMA level is close to 1ms
+ahead of the actual playback time (as a side time this sort of
+measurement can help define rewind safeguards). Compensating for the
+DMA-link delay in example 2 helps remove the hardware buffering but
+the information is still very jittery, with up to one sample of
+error. In example 3 where the timestamps are measured with the link
+wallclock, the timestamps show a monotonic behavior and a lower
+dispersion.
+
+Example 3 and 4 are with USB audio class. Example 3 shows a high
+offset between audio time and system time due to buffering. Example 4
+shows how compensating for the delay exposes a 1ms accuracy (due to
+the use of the frame counter by the driver)
+
+Example 3: DMA timestamp, no compensation for delay, delta of ~5ms
+::
+
+  $ ./audio_time -p -Dhw:1 -t1
+  playback: systime: 120174019 nsec, audio time 125000000 nsec, 	systime delta -4825981
+  playback: systime: 245041136 nsec, audio time 250000000 nsec, 	systime delta -4958864
+  playback: systime: 370106088 nsec, audio time 375000000 nsec, 	systime delta -4893912
+  playback: systime: 495040065 nsec, audio time 500000000 nsec, 	systime delta -4959935
+  playback: systime: 620038179 nsec, audio time 625000000 nsec, 	systime delta -4961821
+  playback: systime: 745087741 nsec, audio time 750000000 nsec, 	systime delta -4912259
+  playback: systime: 870037336 nsec, audio time 875000000 nsec, 	systime delta -4962664
+
+Example 4: DMA timestamp, compensation for delay, delay of ~1ms
+::
+
+  $ ./audio_time -p -Dhw:1 -t1 -d
+  playback: systime: 120190520 nsec, audio time 120000000 nsec, 	systime delta 190520
+  playback: systime: 245036740 nsec, audio time 244000000 nsec, 	systime delta 1036740
+  playback: systime: 370034081 nsec, audio time 369000000 nsec, 	systime delta 1034081
+  playback: systime: 495159907 nsec, audio time 494000000 nsec, 	systime delta 1159907
+  playback: systime: 620098824 nsec, audio time 619000000 nsec, 	systime delta 1098824
+  playback: systime: 745031847 nsec, audio time 744000000 nsec, 	systime delta 1031847
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/hd-audio/controls.rst linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/controls.rst
--- linux-libre-4.9-gnu/Documentation/sound/hd-audio/controls.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/controls.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,121 @@
+======================================
+HD-Audio Codec-Specific Mixer Controls
+======================================
+
+
+This file explains the codec-specific mixer controls.
+
+Realtek 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", "6ch",
+  and "8ch".  According to the configuration, this also controls the
+  jack-retasking of multi-I/O jacks.
+
+Auto-Mute Mode
+  This is an enum control to change the auto-mute behavior of the
+  headphone and line-out jacks.  If built-in speakers and headphone
+  and/or line-out jacks are available on a machine, this controls
+  appears.
+  When there are only either headphones or line-out jacks, it gives
+  "Disabled" and "Enabled" state.  When enabled, the speaker is muted
+  automatically when a jack is plugged.
+
+  When both headphone and line-out jacks are present, it gives
+  "Disabled", "Speaker Only" and "Line-Out+Speaker".  When
+  speaker-only is chosen, plugging into a headphone or a line-out jack
+  mutes the speakers, but not line-outs.  When line-out+speaker is
+  selected, plugging to a headphone jack mutes both speakers and
+  line-outs.
+
+
+IDT/Sigmatel codecs
+-------------------
+
+Analog Loopback
+  This control enables/disables the analog-loopback circuit.  This
+  appears only when "loopback" is set to true in a codec hint
+  (see HD-Audio.txt).  Note that on some codecs the analog-loopback
+  and the normal PCM playback are exclusive, i.e. when this is on, you
+  won't hear any PCM stream.
+
+Swap Center/LFE
+  Swaps the center and LFE channel order.  Normally, the left
+  corresponds to the center and the right to the LFE.  When this is
+  ON, the left to the LFE and the right to the center.
+
+Headphone as Line Out
+  When this control is ON, treat the headphone jacks as line-out
+  jacks.  That is, the headphone won't auto-mute the other line-outs,
+  and no HP-amp is set to the pins.
+
+Mic Jack Mode, Line Jack Mode, etc
+  These enum controls the direction and the bias of the input jack
+  pins.  Depending on the jack type, it can set as "Mic In" and "Line 
+  In", for determining the input bias, or it can be set to "Line Out"
+  when the pin is a multi-I/O jack for surround channels.
+
+
+VIA codecs
+----------
+
+Smart 5.1
+  An enum control to re-task the multi-I/O jacks for surround outputs.
+  When it's ON, the corresponding input jacks (usually a line-in and a
+  mic-in) are switched as the surround and the CLFE output 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.  In the case the headphone DAC is shared with a
+  side or a CLFE-channel DAC, the DAC is switched to the headphone
+  automatically.
+
+Loopback Mixing
+  An enum control to determine whether the analog-loopback route is
+  enabled or not.  When it's enabled, the analog-loopback is mixed to
+  the front-channel.  Also, the same route is used for the headphone
+  and speaker outputs.  As a side-effect, when this mode is set, the
+  individual volume controls will be no longer available for
+  headphones and speakers because there is only one DAC connected to a
+  mixer widget.
+
+Dynamic Power-Control
+  This control determines whether the dynamic power-control per jack
+  detection is enabled or not.  When enabled, the widgets power state
+  (D0/D3) are changed dynamically depending on the jack plugging
+  state for saving power consumptions.  However, if your system
+  doesn't provide a proper jack-detection, this won't work; in such a
+  case, turn this control OFF.
+
+Jack Detect
+  This control is provided only for VT1708 codec which gives no proper
+  unsolicited event per jack plug.  When this is on, the driver polls
+  the jack detection so that the headphone auto-mute can work, while 
+  turning this off would reduce the power consumption.
+
+
+Conexant codecs
+---------------
+
+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 -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/hd-audio/dp-mst.rst linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/dp-mst.rst
--- linux-libre-4.9-gnu/Documentation/sound/hd-audio/dp-mst.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/dp-mst.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,84 @@
+=======================
+HD-Audio DP-MST Support
+=======================
+
+To support DP MST audio, HD Audio hdmi codec driver introduces virtual pin
+and dynamic pcm assignment.
+
+Virtual pin is an extension of per_pin. The most difference of DP MST
+from legacy is that DP MST introduces device entry. Each pin can contain
+several device entries. Each device entry behaves as a pin.
+
+As each pin may contain several device entries and each codec may contain
+several pins, if we use one pcm per per_pin, there will be many PCMs.
+The new solution is to create a few PCMs and to dynamically bind pcm to
+per_pin. Driver uses spec->dyn_pcm_assign flag to indicate whether to use
+the new solution.
+
+PCM
+===
+To be added
+
+
+Jack
+====
+
+Presume:
+ - MST must be dyn_pcm_assign, and it is acomp (for Intel scenario);
+ - NON-MST may or may not be dyn_pcm_assign, it can be acomp or !acomp;
+
+So there are the following scenarios:
+ a. MST (&& dyn_pcm_assign && acomp)
+ b. NON-MST && dyn_pcm_assign && acomp
+ c. NON-MST && !dyn_pcm_assign && !acomp
+
+Below discussion will ignore MST and NON-MST difference as it doesn't
+impact on jack handling too much.
+
+Driver uses struct hdmi_pcm pcm[] array in hdmi_spec and snd_jack is
+a member of hdmi_pcm. Each pin has one struct hdmi_pcm * pcm pointer.
+
+For !dyn_pcm_assign, per_pin->pcm will assigned to spec->pcm[n] statically.
+
+For dyn_pcm_assign, per_pin->pcm will assigned to spec->pcm[n]
+when monitor is hotplugged.
+
+
+Build Jack
+----------
+
+- dyn_pcm_assign
+
+  Will not use hda_jack but use snd_jack in spec->pcm_rec[pcm_idx].jack directly.
+
+- !dyn_pcm_assign
+
+  Use hda_jack and assign spec->pcm_rec[pcm_idx].jack = jack->jack statically.
+
+
+Unsolicited Event Enabling
+--------------------------
+Enable unsolicited event if !acomp.
+
+
+Monitor Hotplug Event Handling
+------------------------------
+- acomp
+
+  pin_eld_notify() -> check_presence_and_report() -> hdmi_present_sense() ->
+  sync_eld_via_acomp().
+
+  Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for
+  both dyn_pcm_assign and !dyn_pcm_assign
+
+- !acomp
+
+  hdmi_unsol_event() -> hdmi_intrinsic_event() -> check_presence_and_report() ->
+  hdmi_present_sense() -> hdmi_prepsent_sense_via_verbs()
+
+  Use directly snd_jack_report() on spec->pcm_rec[pcm_idx].jack for dyn_pcm_assign.
+  Use hda_jack mechanism to handle jack events.
+
+
+Others to be added later
+========================
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/hd-audio/index.rst linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/index.rst
--- linux-libre-4.9-gnu/Documentation/sound/hd-audio/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+HD-Audio
+========
+
+.. toctree::
+   :maxdepth: 2
+
+   notes
+   models
+   controls
+   dp-mst
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/hd-audio/models.rst linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/models.rst
--- linux-libre-4.9-gnu/Documentation/sound/hd-audio/models.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/models.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,518 @@
+==============================
+HD-Audio Codec-Specific Models
+==============================
+
+ALC880
+======
+3stack
+    3-jack in back and a headphone out
+3stack-digout
+    3-jack in back, a HP out and a SPDIF out
+5stack
+    5-jack in back, 2-jack in front
+5stack-digout
+    5-jack in back, 2-jack in front, a SPDIF out
+6stack
+    6-jack in back, 2-jack in front
+6stack-digout
+    6-jack with a SPDIF out
+
+ALC260
+======
+gpio1
+    Enable GPIO1
+coef
+    Enable EAPD via COEF table
+fujitsu
+    Quirk for FSC S7020
+fujitsu-jwse
+    Quirk for FSC S7020 with jack modes and HP mic support
+
+ALC262
+======
+inv-dmic
+    Inverted internal mic workaround
+
+ALC267/268
+==========
+inv-dmic
+    Inverted internal mic workaround
+hp-eapd
+    Disable HP EAPD on NID 0x15
+
+ALC22x/23x/25x/269/27x/28x/29x (and vendor-specific ALC3xxx models)
+===================================================================
+laptop-amic
+    Laptops with analog-mic input
+laptop-dmic
+    Laptops with digital-mic input
+alc269-dmic
+    Enable ALC269(VA) digital mic workaround
+alc271-dmic
+    Enable ALC271X digital mic workaround
+inv-dmic
+    Inverted internal mic workaround
+headset-mic
+    Indicates a combined headset (headphone+mic) jack
+headset-mode
+    More comprehensive headset support for ALC269 & co
+headset-mode-no-hp-mic
+    Headset mode support without headphone mic
+lenovo-dock
+    Enables docking station I/O for some Lenovos
+hp-gpio-led
+    GPIO LED support on HP laptops
+dell-headset-multi
+    Headset jack, which can also be used as mic-in
+dell-headset-dock
+    Headset jack (without mic-in), and also dock I/O
+alc283-dac-wcaps
+    Fixups for Chromebook with ALC283
+alc283-sense-combo
+    Combo jack sensing on ALC283
+tpt440-dock
+    Pin configs for Lenovo Thinkpad Dock support
+
+ALC66x/67x/892
+==============
+mario
+    Chromebook mario model fixup
+asus-mode1
+    ASUS
+asus-mode2
+    ASUS
+asus-mode3
+    ASUS
+asus-mode4
+    ASUS
+asus-mode5
+    ASUS
+asus-mode6
+    ASUS
+asus-mode7
+    ASUS
+asus-mode8
+    ASUS
+inv-dmic
+    Inverted internal mic workaround
+dell-headset-multi
+    Headset jack, which can also be used as mic-in
+
+ALC680
+======
+N/A
+
+ALC88x/898/1150
+======================
+acer-aspire-4930g
+    Acer Aspire 4930G/5930G/6530G/6930G/7730G
+acer-aspire-8930g
+    Acer Aspire 8330G/6935G
+acer-aspire
+    Acer Aspire others
+inv-dmic
+    Inverted internal mic workaround
+no-primary-hp
+    VAIO Z/VGC-LN51JGB workaround (for fixed speaker DAC)
+
+ALC861/660
+==========
+N/A
+
+ALC861VD/660VD
+==============
+N/A
+
+CMI9880
+=======
+minimal
+    3-jack in back
+min_fp
+    3-jack in back, 2-jack in front
+full
+    6-jack in back, 2-jack in front
+full_dig
+    6-jack in back, 2-jack in front, SPDIF I/O
+allout
+    5-jack in back, 2-jack in front, SPDIF out
+auto
+    auto-config reading BIOS (default)
+
+AD1882 / AD1882A
+================
+3stack
+    3-stack mode
+3stack-automute
+    3-stack with automute front HP (default)
+6stack
+    6-stack mode
+
+AD1884A / AD1883 / AD1984A / AD1984B
+====================================
+desktop	3-stack desktop (default)
+laptop	laptop with HP jack sensing
+mobile	mobile devices with HP jack sensing
+thinkpad	Lenovo Thinkpad X300
+touchsmart	HP Touchsmart
+
+AD1884
+======
+N/A
+
+AD1981
+======
+basic		3-jack (default)
+hp		HP nx6320
+thinkpad	Lenovo Thinkpad T60/X60/Z60
+toshiba	Toshiba U205
+
+AD1983
+======
+N/A
+
+AD1984
+======
+basic		default configuration
+thinkpad	Lenovo Thinkpad T61/X61
+dell_desktop	Dell T3400
+
+AD1986A
+=======
+3stack
+    3-stack, shared surrounds
+laptop
+    2-channel only (FSC V2060, Samsung M50)
+laptop-imic
+    2-channel with built-in mic
+eapd
+    Turn on EAPD constantly
+
+AD1988/AD1988B/AD1989A/AD1989B
+==============================
+6stack
+    6-jack
+6stack-dig
+    ditto with SPDIF
+3stack
+    3-jack
+3stack-dig
+    ditto with SPDIF
+laptop
+    3-jack with hp-jack automute
+laptop-dig
+    ditto with SPDIF
+auto
+    auto-config reading BIOS (default)
+
+Conexant 5045
+=============
+laptop-hpsense
+    Laptop with HP sense (old model laptop)
+laptop-micsense
+    Laptop with Mic sense (old model fujitsu)
+laptop-hpmicsense
+    Laptop with HP and Mic senses
+benq
+    Benq R55E
+laptop-hp530
+    HP 530 laptop
+test
+    for testing/debugging purpose, almost all controls can be
+    adjusted.  Appearing only when compiled with $CONFIG_SND_DEBUG=y
+
+Conexant 5047
+=============
+laptop
+    Basic Laptop config 
+laptop-hp
+    Laptop config for some HP models (subdevice 30A5)
+laptop-eapd
+    Laptop config with EAPD support
+test
+    for testing/debugging purpose, almost all controls can be
+    adjusted.  Appearing only when compiled with $CONFIG_SND_DEBUG=y
+
+Conexant 5051
+=============
+laptop
+    Basic Laptop config (default)
+hp
+    HP Spartan laptop
+hp-dv6736
+    HP dv6736
+hp-f700
+    HP Compaq Presario F700
+ideapad
+    Lenovo IdeaPad laptop
+toshiba
+    Toshiba Satellite M300
+
+Conexant 5066
+=============
+laptop
+    Basic Laptop config (default)
+hp-laptop
+    HP laptops, e g G60
+asus
+    Asus K52JU, Lenovo G560
+dell-laptop
+    Dell laptops
+dell-vostro
+    Dell Vostro
+olpc-xo-1_5
+    OLPC XO 1.5
+ideapad
+    Lenovo IdeaPad U150
+thinkpad
+    Lenovo Thinkpad
+
+STAC9200
+========
+ref
+    Reference board
+oqo
+    OQO Model 2
+dell-d21
+    Dell (unknown)
+dell-d22
+    Dell (unknown)
+dell-d23
+    Dell (unknown)
+dell-m21
+    Dell Inspiron 630m, Dell Inspiron 640m
+dell-m22
+    Dell Latitude D620, Dell Latitude D820
+dell-m23
+    Dell XPS M1710, Dell Precision M90
+dell-m24
+    Dell Latitude 120L
+dell-m25
+    Dell Inspiron E1505n
+dell-m26
+    Dell Inspiron 1501
+dell-m27
+    Dell Inspiron E1705/9400
+gateway-m4
+    Gateway laptops with EAPD control
+gateway-m4-2
+    Gateway laptops with EAPD control
+panasonic
+    Panasonic CF-74
+auto
+    BIOS setup (default)
+
+STAC9205/9254
+=============
+ref
+    Reference board
+dell-m42
+    Dell (unknown)
+dell-m43
+    Dell Precision
+dell-m44
+    Dell Inspiron
+eapd
+    Keep EAPD on (e.g. Gateway T1616)
+auto
+    BIOS setup (default)
+
+STAC9220/9221
+=============
+ref
+    Reference board
+3stack
+    D945 3stack
+5stack
+    D945 5stack + SPDIF
+intel-mac-v1
+    Intel Mac Type 1
+intel-mac-v2
+    Intel Mac Type 2
+intel-mac-v3
+    Intel Mac Type 3
+intel-mac-v4
+    Intel Mac Type 4
+intel-mac-v5
+    Intel Mac Type 5
+intel-mac-auto
+    Intel Mac (detect type according to subsystem id)
+macmini
+    Intel Mac Mini (equivalent with type 3)
+macbook
+    Intel Mac Book (eq. type 5)
+macbook-pro-v1
+    Intel Mac Book Pro 1st generation (eq. type 3)
+macbook-pro
+    Intel Mac Book Pro 2nd generation (eq. type 3)
+imac-intel
+    Intel iMac (eq. type 2)
+imac-intel-20
+    Intel iMac (newer version) (eq. type 3)
+ecs202
+    ECS/PC chips
+dell-d81
+    Dell (unknown)
+dell-d82
+    Dell (unknown)
+dell-m81
+    Dell (unknown)
+dell-m82
+    Dell XPS M1210
+auto
+    BIOS setup (default)
+
+STAC9202/9250/9251
+==================
+ref
+    Reference board, base config
+m1
+    Some Gateway MX series laptops (NX560XL)
+m1-2
+    Some Gateway MX series laptops (MX6453)
+m2
+    Some Gateway MX series laptops (M255)
+m2-2
+    Some Gateway MX series laptops
+m3
+    Some Gateway MX series laptops
+m5
+    Some Gateway MX series laptops (MP6954)
+m6
+    Some Gateway NX series laptops
+auto
+    BIOS setup (default)
+
+STAC9227/9228/9229/927x
+=======================
+ref
+    Reference board
+ref-no-jd
+    Reference board without HP/Mic jack detection
+3stack
+    D965 3stack
+5stack
+    D965 5stack + SPDIF
+5stack-no-fp
+    D965 5stack without front panel
+dell-3stack
+    Dell Dimension E520
+dell-bios
+    Fixes with Dell BIOS setup
+dell-bios-amic
+    Fixes with Dell BIOS setup including analog mic
+volknob
+    Fixes with volume-knob widget 0x24
+auto
+    BIOS setup (default)
+
+STAC92HD71B*
+============
+ref
+    Reference board
+dell-m4-1
+    Dell desktops
+dell-m4-2
+    Dell desktops
+dell-m4-3
+    Dell desktops
+hp-m4
+    HP mini 1000
+hp-dv5
+    HP dv series
+hp-hdx
+    HP HDX series
+hp-dv4-1222nr
+    HP dv4-1222nr (with LED support)
+auto
+    BIOS setup (default)
+
+STAC92HD73*
+===========
+ref
+    Reference board
+no-jd
+    BIOS setup but without jack-detection
+intel
+    Intel DG45* mobos
+dell-m6-amic
+    Dell desktops/laptops with analog mics
+dell-m6-dmic
+    Dell desktops/laptops with digital mics
+dell-m6
+    Dell desktops/laptops with both type of mics
+dell-eq
+    Dell desktops/laptops
+alienware
+    Alienware M17x
+auto
+    BIOS setup (default)
+
+STAC92HD83*
+===========
+ref
+    Reference board
+mic-ref
+    Reference board with power management for ports
+dell-s14
+    Dell laptop
+dell-vostro-3500
+    Dell Vostro 3500 laptop
+hp-dv7-4000
+    HP dv-7 4000
+hp_cNB11_intquad
+    HP CNB models with 4 speakers
+hp-zephyr
+    HP Zephyr
+hp-led
+    HP with broken BIOS for mute LED
+hp-inv-led
+    HP with broken BIOS for inverted mute LED
+hp-mic-led
+    HP with mic-mute LED
+headset-jack
+    Dell Latitude with a 4-pin headset jack
+hp-envy-bass
+    Pin fixup for HP Envy bass speaker (NID 0x0f)
+hp-envy-ts-bass
+    Pin fixup for HP Envy TS bass speaker (NID 0x10)
+hp-bnb13-eq
+    Hardware equalizer setup for HP laptops
+auto
+    BIOS setup (default)
+
+STAC92HD95
+==========
+hp-led
+    LED support for HP laptops
+hp-bass
+    Bass HPF setup for HP Spectre 13
+
+STAC9872
+========
+vaio
+    VAIO laptop without SPDIF
+auto
+    BIOS setup (default)
+
+Cirrus Logic CS4206/4207
+========================
+mbp55
+    MacBook Pro 5,5
+imac27
+    IMac 27 Inch
+auto
+    BIOS setup (default)
+
+Cirrus Logic CS4208
+===================
+mba6
+    MacBook Air 6,1 and 6,2
+gpio0
+    Enable GPIO 0 amp
+auto
+    BIOS setup (default)
+
+VIA VT17xx/VT18xx/VT20xx
+========================
+auto
+    BIOS setup (default)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/hd-audio/notes.rst linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/notes.rst
--- linux-libre-4.9-gnu/Documentation/sound/hd-audio/notes.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/hd-audio/notes.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,880 @@
+=============================
+More Notes on HD-Audio Driver
+=============================
+
+Takashi Iwai <tiwai@suse.de>
+
+
+General
+=======
+
+HD-audio is the new standard on-board audio component on modern PCs
+after AC97.  Although Linux has been supporting HD-audio since long
+time ago, there are often problems with new machines.  A part of the
+problem is broken BIOS, and the rest is the driver implementation.
+This document explains the brief trouble-shooting and debugging
+methods for the	HD-audio hardware.
+
+The HD-audio component consists of two parts: the controller chip and 
+the codec chips on the HD-audio bus.  Linux provides a single driver
+for all controllers, snd-hda-intel.  Although the driver name contains
+a word of a well-known hardware vendor, it's not specific to it but for
+all controller chips by other companies.  Since the HD-audio
+controllers are supposed to be compatible, the single snd-hda-driver
+should work in most cases.  But, not surprisingly, there are known
+bugs and issues specific to each controller type.  The snd-hda-intel
+driver has a bunch of workarounds for these as described below.
+
+A controller may have multiple codecs.  Usually you have one audio
+codec and optionally one modem codec.  In theory, there might be
+multiple audio codecs, e.g. for analog and digital outputs, and the
+driver might not work properly because of conflict of mixer elements.
+This should be fixed in future if such hardware really exists.
+
+The snd-hda-intel driver has several different codec parsers depending
+on the codec.  It has a generic parser as a fallback, but this
+functionality is fairly limited until now.  Instead of the generic
+parser, usually the codec-specific parser (coded in patch_*.c) is used
+for the codec-specific implementations.  The details about the
+codec-specific problems are explained in the later sections.
+
+If you are interested in the deep debugging of HD-audio, read the
+HD-audio specification at first.  The specification is found on
+Intel's web page, for example:
+
+* http://www.intel.com/standards/hdaudio/
+
+
+HD-Audio Controller
+===================
+
+DMA-Position Problem
+--------------------
+The most common problem of the controller is the inaccurate DMA
+pointer reporting.  The DMA pointer for playback and capture can be
+read in two ways, either via a LPIB register or via a position-buffer
+map.  As default the driver tries to read from the io-mapped
+position-buffer, and falls back to LPIB if the position-buffer appears
+dead.  However, this detection isn't perfect on some devices.  In such
+a case, you can change the default method via ``position_fix`` option.
+
+``position_fix=1`` means to use LPIB method explicitly.
+``position_fix=2`` means to use the position-buffer.
+``position_fix=3`` means to use a combination of both methods, needed
+for some VIA controllers.  The capture stream position is corrected
+by comparing both LPIB and position-buffer values.
+``position_fix=4`` is another combination available for all controllers,
+and uses LPIB for the playback and the position-buffer for the capture
+streams.
+0 is the default value for all other
+controllers, the automatic check and fallback to LPIB as described in
+the above.  If you get a problem of repeated sounds, this option might
+help.
+
+In addition to that, every controller is known to be broken regarding
+the wake-up timing.  It wakes up a few samples before actually
+processing the data on the buffer.  This caused a lot of problems, for
+example, with ALSA dmix or JACK.  Since 2.6.27 kernel, the driver puts
+an artificial delay to the wake up timing.  This delay is controlled
+via ``bdl_pos_adj`` option. 
+
+When ``bdl_pos_adj`` is a negative value (as default), it's assigned to
+an appropriate value depending on the controller chip.  For Intel
+chips, it'd be 1 while it'd be 32 for others.  Usually this works.
+Only in case it doesn't work and you get warning messages, you should
+change this parameter to other values.
+
+
+Codec-Probing Problem
+---------------------
+A less often but a more severe problem is the codec probing.  When
+BIOS reports the available codec slots wrongly, the driver gets
+confused and tries to access the non-existing codec slot.  This often
+results in the total screw-up, and destructs the further communication
+with the codec chips.  The symptom appears usually as error messages
+like:
+::
+
+    hda_intel: azx_get_response timeout, switching to polling mode:
+          last cmd=0x12345678
+    hda_intel: azx_get_response timeout, switching to single_cmd mode:
+          last cmd=0x12345678
+
+The first line is a warning, and this is usually relatively harmless.
+It means that the codec response isn't notified via an IRQ.  The
+driver uses explicit polling method to read the response.  It gives
+very slight CPU overhead, but you'd unlikely notice it.
+
+The second line is, however, a fatal error.  If this happens, usually
+it means that something is really wrong.  Most likely you are
+accessing a non-existing codec slot.
+
+Thus, if the second error message appears, try to narrow the probed
+codec slots via ``probe_mask`` option.  It's a bitmask, and each bit
+corresponds to the codec slot.  For example, to probe only the first
+slot, pass ``probe_mask=1``.  For the first and the third slots, pass
+``probe_mask=5`` (where 5 = 1 | 4), and so on.
+
+Since 2.6.29 kernel, the driver has a more robust probing method, so
+this error might happen rarely, though.
+
+On a machine with a broken BIOS, sometimes you need to force the
+driver to probe the codec slots the hardware doesn't report for use.
+In such a case, turn the bit 8 (0x100) of ``probe_mask`` option on.
+Then the rest 8 bits are passed as the codec slots to probe
+unconditionally.  For example, ``probe_mask=0x103`` will force to probe
+the codec slots 0 and 1 no matter what the hardware reports.
+
+
+Interrupt Handling
+------------------
+HD-audio driver uses MSI as default (if available) since 2.6.33
+kernel as MSI works better on some machines, and in general, it's
+better for performance.  However, Nvidia controllers showed bad
+regressions with MSI (especially in a combination with AMD chipset),
+thus we disabled MSI for them.
+
+There seem also still other devices that don't work with MSI.  If you
+see a regression wrt the sound quality (stuttering, etc) or a lock-up
+in the recent kernel, try to pass ``enable_msi=0`` option to disable
+MSI.  If it works, you can add the known bad device to the blacklist
+defined in hda_intel.c.  In such a case, please report and give the
+patch back to the upstream developer. 
+
+
+HD-Audio Codec
+==============
+
+Model Option
+------------
+The most common problem regarding the HD-audio driver is the
+unsupported codec features or the mismatched device configuration.
+Most of codec-specific code has several preset models, either to
+override the BIOS setup or to provide more comprehensive features.
+
+The driver checks PCI SSID and looks through the static configuration
+table until any matching entry is found.  If you have a new machine,
+you may see a message like below:
+::
+
+    hda_codec: ALC880: BIOS auto-probing.
+
+Meanwhile, in the earlier versions, you would see a message like:
+::
+
+    hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...
+
+Even if you see such a message, DON'T PANIC.  Take a deep breath and
+keep your towel.  First of all, it's an informational message, no
+warning, no error.  This means that the PCI SSID of your device isn't
+listed in the known preset model (white-)list.  But, this doesn't mean
+that the driver is broken.  Many codec-drivers provide the automatic
+configuration mechanism based on the BIOS setup.
+
+The HD-audio codec has usually "pin" widgets, and BIOS sets the default
+configuration of each pin, which indicates the location, the
+connection type, the jack color, etc.  The HD-audio driver can guess
+the right connection judging from these default configuration values.
+However -- some codec-support codes, such as patch_analog.c, don't
+support the automatic probing (yet as of 2.6.28).  And, BIOS is often,
+yes, pretty often broken.  It sets up wrong values and screws up the
+driver.
+
+The preset model (or recently called as "fix-up") is provided
+basically to overcome such a situation.  When the matching preset
+model is found in the white-list, the driver assumes the static
+configuration of that preset with the correct pin setup, etc.
+Thus, if you have a newer machine with a slightly different PCI SSID
+(or codec SSID) from the existing one, you may have a good chance to
+re-use the same model.  You can pass the ``model`` option to specify the
+preset model instead of PCI (and codec-) SSID look-up.
+
+What ``model`` option values are available depends on the codec chip.
+Check your codec chip from the codec proc file (see "Codec Proc-File"
+section below).  It will show the vendor/product name of your codec
+chip.  Then, see Documentation/sound/HD-Audio-Models.rst file,
+the section of HD-audio driver.  You can find a list of codecs
+and ``model`` options belonging to each codec.  For example, for Realtek
+ALC262 codec chip, pass ``model=ultra`` for devices that are compatible
+with Samsung Q1 Ultra.
+
+Thus, the first thing you can do for any brand-new, unsupported and
+non-working HD-audio hardware is to check HD-audio codec and several
+different ``model`` option values.  If you have any luck, some of them
+might suit with your device well.
+
+There are a few special model option values:
+
+* when 'nofixup' is passed, the device-specific fixups in the codec
+  parser are skipped.
+* when ``generic`` is passed, the codec-specific parser is skipped and
+  only the generic parser is used.
+
+
+Speaker and Headphone Output
+----------------------------
+One of the most frequent (and obvious) bugs with HD-audio is the
+silent output from either or both of a built-in speaker and a
+headphone jack.  In general, you should try a headphone output at
+first.  A speaker output often requires more additional controls like
+the external amplifier bits.  Thus a headphone output has a slightly
+better chance.
+
+Before making a bug report, double-check whether the mixer is set up
+correctly.  The recent version of snd-hda-intel driver provides mostly
+"Master" volume control as well as "Front" volume (where Front
+indicates the front-channels).  In addition, there can be individual
+"Headphone" and "Speaker" controls.
+
+Ditto for the speaker output.  There can be "External Amplifier"
+switch on some codecs.  Turn on this if present.
+
+Another related problem is the automatic mute of speaker output by
+headphone plugging.  This feature is implemented in most cases, but
+not on every preset model or codec-support code.
+
+In anyway, try a different model option if you have such a problem.
+Some other models may match better and give you more matching
+functionality.  If none of the available models works, send a bug
+report.  See the bug report section for details.
+
+If you are masochistic enough to debug the driver problem, note the
+following:
+
+* The speaker (and the headphone, too) output often requires the
+  external amplifier.  This can be set usually via EAPD verb or a
+  certain GPIO.  If the codec pin supports EAPD, you have a better
+  chance via SET_EAPD_BTL verb (0x70c).  On others, GPIO pin (mostly
+  it's either GPIO0 or GPIO1) may turn on/off EAPD.
+* Some Realtek codecs require special vendor-specific coefficients to
+  turn on the amplifier.  See patch_realtek.c.
+* IDT codecs may have extra power-enable/disable controls on each
+  analog pin.  See patch_sigmatel.c.
+* Very rare but some devices don't accept the pin-detection verb until
+  triggered.  Issuing GET_PIN_SENSE verb (0xf09) may result in the
+  codec-communication stall.  Some examples are found in
+  patch_realtek.c.
+
+
+Capture Problems
+----------------
+The capture problems are often because of missing setups of mixers.
+Thus, before submitting a bug report, make sure that you set up the
+mixer correctly.  For example, both "Capture Volume" and "Capture
+Switch" have to be set properly in addition to the right "Capture
+Source" or "Input Source" selection.  Some devices have "Mic Boost"
+volume or switch.
+
+When the PCM device is opened via "default" PCM (without pulse-audio
+plugin), you'll likely have "Digital Capture Volume" control as well.
+This is provided for the extra gain/attenuation of the signal in
+software, especially for the inputs without the hardware volume
+control such as digital microphones.  Unless really needed, this
+should be set to exactly 50%, corresponding to 0dB -- neither extra
+gain nor attenuation.  When you use "hw" PCM, i.e., a raw access PCM,
+this control will have no influence, though.
+
+It's known that some codecs / devices have fairly bad analog circuits,
+and the recorded sound contains a certain DC-offset.  This is no bug
+of the driver.
+
+Most of modern laptops have no analog CD-input connection.  Thus, the
+recording from CD input won't work in many cases although the driver
+provides it as the capture source.  Use CDDA instead.
+
+The automatic switching of the built-in and external mic per plugging
+is implemented on some codec models but not on every model.  Partly
+because of my laziness but mostly lack of testers.  Feel free to
+submit the improvement patch to the author.
+
+
+Direct Debugging
+----------------
+If no model option gives you a better result, and you are a tough guy
+to fight against evil, try debugging via hitting the raw HD-audio
+codec verbs to the device.  Some tools are available: hda-emu and
+hda-analyzer.  The detailed description is found in the sections
+below.  You'd need to enable hwdep for using these tools.  See "Kernel
+Configuration" section.
+
+
+Other Issues
+============
+
+Kernel Configuration
+--------------------
+In general, I recommend you to enable the sound debug option,
+``CONFIG_SND_DEBUG=y``, no matter whether you are debugging or not.
+This enables snd_printd() macro and others, and you'll get additional
+kernel messages at probing.
+
+In addition, you can enable ``CONFIG_SND_DEBUG_VERBOSE=y``.  But this
+will give you far more messages.  Thus turn this on only when you are
+sure to want it.
+
+Don't forget to turn on the appropriate ``CONFIG_SND_HDA_CODEC_*``
+options.  Note that each of them corresponds to the codec chip, not
+the controller chip.  Thus, even if lspci shows the Nvidia controller,
+you may need to choose the option for other vendors.  If you are
+unsure, just select all yes.
+
+``CONFIG_SND_HDA_HWDEP`` is a useful option for debugging the driver.
+When this is enabled, the driver creates hardware-dependent devices
+(one per each codec), and you have a raw access to the device via
+these device files.  For example, ``hwC0D2`` will be created for the
+codec slot #2 of the first card (#0).  For debug-tools such as
+hda-verb and hda-analyzer, the hwdep device has to be enabled.
+Thus, it'd be better to turn this on always.
+
+``CONFIG_SND_HDA_RECONFIG`` is a new option, and this depends on the
+hwdep option above.  When enabled, you'll have some sysfs files under
+the corresponding hwdep directory.  See "HD-audio reconfiguration"
+section below.
+
+``CONFIG_SND_HDA_POWER_SAVE`` option enables the power-saving feature.
+See "Power-saving" section below.
+
+
+Codec Proc-File
+---------------
+The codec proc-file is a treasure-chest for debugging HD-audio.
+It shows most of useful information of each codec widget.
+
+The proc file is located in /proc/asound/card*/codec#*, one file per
+each codec slot.  You can know the codec vendor, product id and
+names, the type of each widget, capabilities and so on.
+This file, however, doesn't show the jack sensing state, so far.  This
+is because the jack-sensing might be depending on the trigger state.
+
+This file will be picked up by the debug tools, and also it can be fed
+to the emulator as the primary codec information.  See the debug tools
+section below.
+
+This proc file can be also used to check whether the generic parser is
+used.  When the generic parser is used, the vendor/product ID name
+will appear as "Realtek ID 0262", instead of "Realtek ALC262".
+
+
+HD-Audio Reconfiguration
+------------------------
+This is an experimental feature to allow you re-configure the HD-audio
+codec dynamically without reloading the driver.  The following sysfs
+files are available under each codec-hwdep device directory (e.g. 
+/sys/class/sound/hwC0D0):
+
+vendor_id
+    Shows the 32bit codec vendor-id hex number.  You can change the
+    vendor-id value by writing to this file.
+subsystem_id
+    Shows the 32bit codec subsystem-id hex number.  You can change the
+    subsystem-id value by writing to this file.
+revision_id
+    Shows the 32bit codec revision-id hex number.  You can change the
+    revision-id value by writing to this file.
+afg
+    Shows the AFG ID.  This is read-only.
+mfg
+    Shows the MFG ID.  This is read-only.
+name
+    Shows the codec name string.  Can be changed by writing to this
+    file.
+modelname
+    Shows the currently set ``model`` option.  Can be changed by writing
+    to this file.
+init_verbs
+    The extra verbs to execute at initialization.  You can add a verb by
+    writing to this file.  Pass three numbers: nid, verb and parameter
+    (separated with a space).
+hints
+    Shows / stores hint strings for codec parsers for any use.
+    Its format is ``key = value``.  For example, passing ``jack_detect = no``
+    will disable the jack detection of the machine completely.
+init_pin_configs
+    Shows the initial pin default config values set by BIOS.
+driver_pin_configs
+    Shows the pin default values set by the codec parser explicitly.
+    This doesn't show all pin values but only the changed values by
+    the parser.  That is, if the parser doesn't change the pin default
+    config values by itself, this will contain nothing.
+user_pin_configs
+    Shows the pin default config values to override the BIOS setup.
+    Writing this (with two numbers, NID and value) appends the new
+    value.  The given will be used instead of the initial BIOS value at
+    the next reconfiguration time.  Note that this config will override
+    even the driver pin configs, too.
+reconfig
+    Triggers the codec re-configuration.  When any value is written to
+    this file, the driver re-initialize and parses the codec tree
+    again.  All the changes done by the sysfs entries above are taken
+    into account.
+clear
+    Resets the codec, removes the mixer elements and PCM stuff of the
+    specified codec, and clear all init verbs and hints.
+
+For example, when you want to change the pin default configuration
+value of the pin widget 0x14 to 0x9993013f, and let the driver
+re-configure based on that state, run like below:
+::
+
+    # echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
+    # echo 1 > /sys/class/sound/hwC0D0/reconfig  
+
+
+Hint Strings
+------------
+The codec parser have several switches and adjustment knobs for
+matching better with the actual codec or device behavior.  Many of
+them can be adjusted dynamically via "hints" strings as mentioned in
+the section above.  For example, by passing ``jack_detect = no`` string
+via sysfs or a patch file, you can disable the jack detection, thus
+the codec parser will skip the features like auto-mute or mic
+auto-switch.  As a boolean value, either ``yes``, ``no``, ``true``, ``false``,
+``1`` or ``0`` can be passed.
+
+The generic parser supports the following hints:
+
+jack_detect (bool)
+    specify whether the jack detection is available at all on this
+    machine; default true
+inv_jack_detect (bool)
+    indicates that the jack detection logic is inverted
+trigger_sense (bool)
+    indicates that the jack detection needs the explicit call of
+    AC_VERB_SET_PIN_SENSE verb
+inv_eapd (bool)
+    indicates that the EAPD is implemented in the inverted logic
+pcm_format_first (bool)
+    sets the PCM format before the stream tag and channel ID
+sticky_stream (bool)
+    keep the PCM format, stream tag and ID as long as possible;
+    default true
+spdif_status_reset (bool)
+    reset the SPDIF status bits at each time the SPDIF stream is set
+    up
+pin_amp_workaround (bool)
+    the output pin may have multiple amp values
+single_adc_amp (bool)
+    ADCs can have only single input amps
+auto_mute (bool)
+    enable/disable the headphone auto-mute feature; default true
+auto_mic (bool)
+    enable/disable the mic auto-switch feature; default true
+line_in_auto_switch (bool)
+    enable/disable the line-in auto-switch feature; default false
+need_dac_fix (bool)
+    limits the DACs depending on the channel count
+primary_hp (bool)
+    probe headphone jacks as the primary outputs; default true
+multi_io (bool)
+    try probing multi-I/O config (e.g. shared line-in/surround,
+    mic/clfe jacks)
+multi_cap_vol (bool)
+    provide multiple capture volumes
+inv_dmic_split (bool)
+    provide split internal mic volume/switch for phase-inverted
+    digital mics
+indep_hp (bool)
+    provide the independent headphone PCM stream and the corresponding
+    mixer control, if available
+add_stereo_mix_input (bool)
+    add the stereo mix (analog-loopback mix) to the input mux if
+    available 
+add_jack_modes (bool)
+    add "xxx Jack Mode" enum controls to each I/O jack for allowing to
+    change the headphone amp and mic bias VREF capabilities
+power_save_node (bool)
+    advanced power management for each widget, controlling the power
+    sate (D0/D3) of each widget node depending on the actual pin and
+    stream states
+power_down_unused (bool)
+    power down the unused widgets, a subset of power_save_node, and
+    will be dropped in future 
+add_hp_mic (bool)
+    add the headphone to capture source if possible
+hp_mic_detect (bool)
+    enable/disable the hp/mic shared input for a single built-in mic
+    case; default true
+mixer_nid (int)
+    specifies the widget NID of the analog-loopback mixer
+
+
+Early Patching
+--------------
+When ``CONFIG_SND_HDA_PATCH_LOADER=y`` is set, you can pass a "patch"
+as a firmware file for modifying the HD-audio setup before
+initializing the codec.  This can work basically like the
+reconfiguration via sysfs in the above, but it does it before the
+first codec configuration.
+
+A patch file is a plain text file which looks like below:
+
+::
+
+    [codec]
+    0x12345678 0xabcd1234 2
+
+    [model]
+    auto
+
+    [pincfg]
+    0x12 0x411111f0
+
+    [verb]
+    0x20 0x500 0x03
+    0x20 0x400 0xff
+
+    [hint]
+    jack_detect = no
+
+
+The file needs to have a line ``[codec]``.  The next line should contain
+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.  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.
+Note that this overrides the module option.
+
+After the ``[pincfg]`` line, the contents are parsed as the initial
+default pin-configurations just like ``user_pin_configs`` sysfs above.
+The values can be shown in user_pin_configs sysfs file, too.
+
+Similarly, the lines after ``[verb]`` are parsed as ``init_verbs``
+sysfs entries, and the lines after ``[hint]`` are parsed as ``hints``
+sysfs entries, respectively.
+
+Another example to override the codec vendor id from 0x12345678 to
+0xdeadbeef is like below:
+::
+
+    [codec]
+    0x12345678 0xabcd1234 2
+
+    [vendor_id]
+    0xdeadbeef
+
+
+In the similar way, you can override the codec subsystem_id via
+``[subsystem_id]``, the revision id via ``[revision_id]`` line.
+Also, the codec chip name can be rewritten via ``[chip_name]`` line.
+::
+
+    [codec]
+    0x12345678 0xabcd1234 2
+
+    [subsystem_id]
+    0xffff1111
+
+    [revision_id]
+    0x10
+
+    [chip_name]
+    My-own NEWS-0002
+
+
+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
+present.
+
+The patch module option is specific to each card instance, and you
+need to give one file name for each instance, separated by commas.
+For example, if you have two cards, one for an on-board analog and one 
+for an HDMI video board, you may pass patch option like below:
+::
+
+    options snd-hda-intel patch=on-board-patch,hdmi-patch
+
+
+Power-Saving
+------------
+The power-saving is a kind of auto-suspend of the device.  When the
+device is inactive for a certain time, the device is automatically
+turned off to save the power.  The time to go down is specified via
+``power_save`` module option, and this option can be changed dynamically
+via sysfs.
+
+The power-saving won't work when the analog loopback is enabled on
+some codecs.  Make sure that you mute all unneeded signal routes when
+you want the power-saving.
+
+The power-saving feature might cause audible click noises at each
+power-down/up depending on the device.  Some of them might be
+solvable, but some are hard, I'm afraid.  Some distros such as
+openSUSE enables the power-saving feature automatically when the power
+cable is unplugged.  Thus, if you hear noises, suspect first the
+power-saving.  See /sys/module/snd_hda_intel/parameters/power_save to
+check the current value.  If it's non-zero, the feature is turned on.
+
+The recent kernel supports the runtime PM for the HD-audio controller
+chip, too.  It means that the HD-audio controller is also powered up /
+down dynamically.  The feature is enabled only for certain controller
+chips like Intel LynxPoint.  You can enable/disable this feature
+forcibly by setting ``power_save_controller`` option, which is also
+available at /sys/module/snd_hda_intel/parameters directory.
+
+
+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.git
+
+The master branch or for-next branches can be used as the main
+development branches in general while the development for the current
+and next kernels are found in for-linus and for-next branches,
+respectively.
+
+
+Sending a Bug Report
+--------------------
+If any model or module options don't work for your device, it's time
+to send a bug report to the developers.  Give the following in your
+bug report:
+
+* Hardware vendor, product and model names
+* Kernel version (and ALSA-driver version if you built externally)
+* ``alsa-info.sh`` output; run with ``--no-upload`` option.  See the
+  section below about alsa-info
+
+If it's a regression, at best, send alsa-info outputs of both working
+and non-working kernels.  This is really helpful because we can
+compare the codec registers directly.
+
+Send a bug report either the followings:
+
+kernel-bugzilla
+    https://bugzilla.kernel.org/
+alsa-devel ML
+    alsa-devel@alsa-project.org
+
+
+Debug Tools
+===========
+
+This section describes some tools available for debugging HD-audio
+problems.
+
+alsa-info
+---------
+The script ``alsa-info.sh`` is a very useful tool to gather the audio
+device information.  It's included in alsa-utils package.  The latest
+version can be found on git repository:
+
+* git://git.alsa-project.org/alsa-utils.git
+
+The script can be fetched directly from the following URL, too:
+
+* http://www.alsa-project.org/alsa-info.sh
+
+Run this script as root, and it will gather the important information
+such as the module lists, module parameters, proc file contents
+including the codec proc files, mixer outputs and the control
+elements.  As default, it will store the information onto a web server
+on alsa-project.org.  But, if you send a bug report, it'd be better to
+run with ``--no-upload`` option, and attach the generated file.
+
+There are some other useful options.  See ``--help`` option output for
+details.
+
+When a probe error occurs or when the driver obviously assigns a
+mismatched model, it'd be helpful to load the driver with
+``probe_only=1`` option (at best after the cold reboot) and run
+alsa-info at this state.  With this option, the driver won't configure
+the mixer and PCM but just tries to probe the codec slot.  After
+probing, the proc file is available, so you can get the raw codec
+information before modified by the driver.  Of course, the driver
+isn't usable with ``probe_only=1``.  But you can continue the
+configuration via hwdep sysfs file if hda-reconfig option is enabled.
+Using ``probe_only`` mask 2 skips the reset of HDA codecs (use
+``probe_only=3`` as module option). The hwdep interface can be used
+to determine the BIOS codec initialization.
+
+
+hda-verb
+--------
+hda-verb is a tiny program that allows you to access the HD-audio
+codec directly.  You can execute a raw HD-audio codec verb with this.
+This program accesses the hwdep device, thus you need to enable the
+kernel config ``CONFIG_SND_HDA_HWDEP=y`` beforehand.
+
+The hda-verb program takes four arguments: the hwdep device file, the
+widget NID, the verb and the parameter.  When you access to the codec
+on the slot 2 of the card 0, pass /dev/snd/hwC0D2 to the first
+argument, typically.  (However, the real path name depends on the
+system.)
+
+The second parameter is the widget number-id to access.  The third
+parameter can be either a hex/digit number or a string corresponding
+to a verb.  Similarly, the last parameter is the value to write, or
+can be a string for the parameter type.
+
+::
+
+    % hda-verb /dev/snd/hwC0D0 0x12 0x701 2
+    nid = 0x12, verb = 0x701, param = 0x2
+    value = 0x0
+
+    % hda-verb /dev/snd/hwC0D0 0x0 PARAMETERS VENDOR_ID
+    nid = 0x0, verb = 0xf00, param = 0x0
+    value = 0x10ec0262
+
+    % hda-verb /dev/snd/hwC0D0 2 set_a 0xb080
+    nid = 0x2, verb = 0x300, param = 0xb080
+    value = 0x0
+
+
+Although you can issue any verbs with this program, the driver state
+won't be always updated.  For example, the volume values are usually
+cached in the driver, and thus changing the widget amp value directly
+via hda-verb won't change the mixer value.
+
+The hda-verb program is included now in alsa-tools:
+
+* git://git.alsa-project.org/alsa-tools.git
+
+Also, the old stand-alone package is found in the ftp directory:
+
+* ftp://ftp.suse.com/pub/people/tiwai/misc/
+
+Also a git repository is available:
+
+* git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-verb.git
+
+See README file in the tarball for more details about hda-verb
+program.
+
+
+hda-analyzer
+------------
+hda-analyzer provides a graphical interface to access the raw HD-audio
+control, based on pyGTK2 binding.  It's a more powerful version of
+hda-verb.  The program gives you an easy-to-use GUI stuff for showing
+the widget information and adjusting the amp values, as well as the
+proc-compatible output.
+
+The hda-analyzer:
+
+* http://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer
+
+is a part of alsa.git repository in alsa-project.org:
+
+* git://git.alsa-project.org/alsa.git
+
+Codecgraph
+----------
+Codecgraph is a utility program to generate a graph and visualizes the
+codec-node connection of a codec chip.  It's especially useful when
+you analyze or debug a codec without a proper datasheet.  The program
+parses the given codec proc file and converts to SVG via graphiz
+program.
+
+The tarball and GIT trees are found in the web page at:
+
+* http://helllabs.org/codecgraph/
+
+
+hda-emu
+-------
+hda-emu is an HD-audio emulator.  The main purpose of this program is
+to debug an HD-audio codec without the real hardware.  Thus, it
+doesn't emulate the behavior with the real audio I/O, but it just
+dumps the codec register changes and the ALSA-driver internal changes
+at probing and operating the HD-audio driver.
+
+The program requires a codec proc-file to simulate.  Get a proc file
+for the target codec beforehand, or pick up an example codec from the
+codec proc collections in the tarball.  Then, run the program with the
+proc file, and the hda-emu program will start parsing the codec file
+and simulates the HD-audio driver:
+
+::
+
+    % hda-emu codecs/stac9200-dell-d820-laptop
+    # Parsing..
+    hda_codec: Unknown model for STAC9200, using BIOS defaults
+    hda_codec: pin nid 08 bios pin config 40c003fa
+    ....
+
+
+The program gives you only a very dumb command-line interface.  You
+can get a proc-file dump at the current state, get a list of control
+(mixer) elements, set/get the control element value, simulate the PCM
+operation, the jack plugging simulation, etc.
+
+The program is found in the git repository below:
+
+* git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
+
+See README file in the repository for more details about hda-emu
+program.
+
+
+hda-jack-retask
+---------------
+hda-jack-retask is a user-friendly GUI program to manipulate the
+HD-audio pin control for jack retasking.  If you have a problem about
+the jack assignment, try this program and check whether you can get
+useful results.  Once when you figure out the proper pin assignment,
+it can be fixed either in the driver code statically or via passing a
+firmware patch file (see "Early Patching" section).
+
+The program is included in alsa-tools now:
+
+* git://git.alsa-project.org/alsa-tools.git
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/index.rst linux-libre-4.10-rc8-gnu/Documentation/sound/index.rst
--- linux-libre-4.9-gnu/Documentation/sound/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+===================================
+Linux Sound Subsystem Documentation
+===================================
+
+.. toctree::
+   :maxdepth: 2
+
+   kernel-api/index
+   designs/index
+   soc/index
+   alsa-configuration
+   hd-audio/index
+   cards/index
+
+.. only::  subproject
+
+   Indices
+   =======
+
+   * :ref:`genindex`
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/kernel-api/alsa-driver-api.rst linux-libre-4.10-rc8-gnu/Documentation/sound/kernel-api/alsa-driver-api.rst
--- linux-libre-4.9-gnu/Documentation/sound/kernel-api/alsa-driver-api.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/kernel-api/alsa-driver-api.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,134 @@
+===================
+The ALSA Driver API
+===================
+
+Management of Cards and Devices
+===============================
+
+Card Management
+---------------
+.. kernel-doc:: sound/core/init.c
+
+Device Components
+-----------------
+.. kernel-doc:: sound/core/device.c
+
+Module requests and Device File Entries
+---------------------------------------
+.. kernel-doc:: sound/core/sound.c
+
+Memory Management Helpers
+-------------------------
+.. kernel-doc:: sound/core/memory.c
+.. kernel-doc:: sound/core/memalloc.c
+
+
+PCM API
+=======
+
+PCM Core
+--------
+.. kernel-doc:: sound/core/pcm.c
+.. kernel-doc:: sound/core/pcm_lib.c
+.. kernel-doc:: sound/core/pcm_native.c
+.. kernel-doc:: include/sound/pcm.h
+
+PCM Format Helpers
+------------------
+.. kernel-doc:: sound/core/pcm_misc.c
+
+PCM Memory Management
+---------------------
+.. kernel-doc:: sound/core/pcm_memory.c
+
+PCM DMA Engine API
+------------------
+.. kernel-doc:: sound/core/pcm_dmaengine.c
+.. kernel-doc:: include/sound/dmaengine_pcm.h
+
+Control/Mixer API
+=================
+
+General Control Interface
+-------------------------
+.. kernel-doc:: sound/core/control.c
+
+AC97 Codec API
+--------------
+.. kernel-doc:: sound/pci/ac97/ac97_codec.c
+.. kernel-doc:: sound/pci/ac97/ac97_pcm.c
+
+Virtual Master Control API
+--------------------------
+.. kernel-doc:: sound/core/vmaster.c
+.. kernel-doc:: include/sound/control.h
+
+MIDI API
+========
+
+Raw MIDI API
+------------
+.. kernel-doc:: sound/core/rawmidi.c
+
+MPU401-UART API
+---------------
+.. kernel-doc:: sound/drivers/mpu401/mpu401_uart.c
+
+Proc Info API
+=============
+
+Proc Info Interface
+-------------------
+.. kernel-doc:: sound/core/info.c
+
+Compress Offload
+================
+
+Compress Offload API
+--------------------
+.. kernel-doc:: sound/core/compress_offload.c
+.. kernel-doc:: include/uapi/sound/compress_offload.h
+.. kernel-doc:: include/uapi/sound/compress_params.h
+.. kernel-doc:: include/sound/compress_driver.h
+
+ASoC
+====
+
+ASoC Core API
+-------------
+.. kernel-doc:: include/sound/soc.h
+.. kernel-doc:: sound/soc/soc-core.c
+.. kernel-doc:: sound/soc/soc-devres.c
+.. kernel-doc:: sound/soc/soc-io.c
+.. kernel-doc:: sound/soc/soc-pcm.c
+.. kernel-doc:: sound/soc/soc-ops.c
+.. kernel-doc:: sound/soc/soc-compress.c
+
+ASoC DAPM API
+-------------
+.. kernel-doc:: sound/soc/soc-dapm.c
+
+ASoC DMA Engine API
+-------------------
+.. kernel-doc:: sound/soc/soc-generic-dmaengine-pcm.c
+
+Miscellaneous Functions
+=======================
+
+Hardware-Dependent Devices API
+------------------------------
+.. kernel-doc:: sound/core/hwdep.c
+
+Jack Abstraction Layer API
+--------------------------
+.. kernel-doc:: include/sound/jack.h
+.. kernel-doc:: sound/core/jack.c
+.. kernel-doc:: sound/soc/soc-jack.c
+
+ISA DMA Helpers
+---------------
+.. kernel-doc:: sound/core/isadma.c
+
+Other Helper Macros
+-------------------
+.. kernel-doc:: include/sound/core.h
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/kernel-api/index.rst linux-libre-4.10-rc8-gnu/Documentation/sound/kernel-api/index.rst
--- linux-libre-4.9-gnu/Documentation/sound/kernel-api/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/kernel-api/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+ALSA Kernel API Documentation
+=============================
+
+.. toctree::
+   :maxdepth: 2
+
+   alsa-driver-api
+   writing-an-alsa-driver
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/kernel-api/writing-an-alsa-driver.rst linux-libre-4.10-rc8-gnu/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
--- linux-libre-4.9-gnu/Documentation/sound/kernel-api/writing-an-alsa-driver.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/kernel-api/writing-an-alsa-driver.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,4219 @@
+======================
+Writing an ALSA Driver
+======================
+
+:Author: Takashi Iwai <tiwai@suse.de>
+:Date:   Oct 15, 2007
+:Edition: 0.3.7
+
+Preface
+=======
+
+This document describes how to write an `ALSA (Advanced Linux Sound
+Architecture) <http://www.alsa-project.org/>`__ driver. The document
+focuses mainly on PCI soundcards. In the case of other device types, the
+API might be different, too. However, at least the ALSA kernel API is
+consistent, and therefore it would be still a bit help for writing them.
+
+This document targets people who already have enough C language skills
+and have basic linux kernel programming knowledge. This document doesn't
+explain the general topic of linux kernel coding and doesn't cover
+low-level driver implementation details. It only describes the standard
+way to write a PCI sound driver on ALSA.
+
+If you are already familiar with the older ALSA ver.0.5.x API, you can
+check the drivers such as ``sound/pci/es1938.c`` or
+``sound/pci/maestro3.c`` which have also almost the same code-base in
+the ALSA 0.5.x tree, so you can compare the differences.
+
+This document is still a draft version. Any feedback and corrections,
+please!!
+
+File Tree Structure
+===================
+
+General
+-------
+
+The ALSA drivers are provided in two ways.
+
+One is the trees provided as a tarball or via cvs from the ALSA's ftp
+site, and another is the 2.6 (or later) Linux kernel tree. To
+synchronize both, the ALSA driver tree is split into two different
+trees: alsa-kernel and alsa-driver. The former contains purely the
+source code for the Linux 2.6 (or later) tree. This tree is designed
+only for compilation on 2.6 or later environment. The latter,
+alsa-driver, contains many subtle files for compiling ALSA drivers
+outside of the Linux kernel tree, wrapper functions for older 2.2 and
+2.4 kernels, to adapt the latest kernel API, and additional drivers
+which are still in development or in tests. The drivers in alsa-driver
+tree will be moved to alsa-kernel (and eventually to the 2.6 kernel
+tree) when they are finished and confirmed to work fine.
+
+The file tree structure of ALSA driver is depicted below. Both
+alsa-kernel and alsa-driver have almost the same file structure, except
+for “core” directory. It's named as “acore” in alsa-driver tree.
+
+::
+
+            sound
+                    /core
+                            /oss
+                            /seq
+                                    /oss
+                                    /instr
+                    /ioctl32
+                    /include
+                    /drivers
+                            /mpu401
+                            /opl3
+                    /i2c
+                            /l3
+                    /synth
+                            /emux
+                    /pci
+                            /(cards)
+                    /isa
+                            /(cards)
+                    /arm
+                    /ppc
+                    /sparc
+                    /usb
+                    /pcmcia /(cards)
+                    /oss
+
+
+core directory
+--------------
+
+This directory contains the middle layer which is the heart of ALSA
+drivers. In this directory, the native ALSA modules are stored. The
+sub-directories contain different modules and are dependent upon the
+kernel config.
+
+core/oss
+~~~~~~~~
+
+The codes for PCM and mixer OSS emulation modules are stored in this
+directory. The rawmidi OSS emulation is included in the ALSA rawmidi
+code since it's quite small. The sequencer code is stored in
+``core/seq/oss`` directory (see `below <#core-seq-oss>`__).
+
+core/ioctl32
+~~~~~~~~~~~~
+
+This directory contains the 32bit-ioctl wrappers for 64bit architectures
+such like x86-64, ppc64 and sparc64. For 32bit and alpha architectures,
+these are not compiled.
+
+core/seq
+~~~~~~~~
+
+This directory and its sub-directories are for the ALSA sequencer. This
+directory contains the sequencer core and primary sequencer modules such
+like snd-seq-midi, snd-seq-virmidi, etc. They are compiled only when
+``CONFIG_SND_SEQUENCER`` is set in the kernel config.
+
+core/seq/oss
+~~~~~~~~~~~~
+
+This contains the OSS sequencer emulation codes.
+
+core/seq/instr
+~~~~~~~~~~~~~~
+
+This directory contains the modules for the sequencer instrument layer.
+
+include directory
+-----------------
+
+This is the place for the public header files of ALSA drivers, which are
+to be exported to user-space, or included by several files at different
+directories. Basically, the private header files should not be placed in
+this directory, but you may still find files there, due to historical
+reasons :)
+
+drivers directory
+-----------------
+
+This directory contains code shared among different drivers on different
+architectures. They are hence supposed not to be architecture-specific.
+For example, the dummy pcm driver and the serial MIDI driver are found
+in this directory. In the sub-directories, there is code for components
+which are independent from bus and cpu architectures.
+
+drivers/mpu401
+~~~~~~~~~~~~~~
+
+The MPU401 and MPU401-UART modules are stored here.
+
+drivers/opl3 and opl4
+~~~~~~~~~~~~~~~~~~~~~
+
+The OPL3 and OPL4 FM-synth stuff is found here.
+
+i2c directory
+-------------
+
+This contains the ALSA i2c components.
+
+Although there is a standard i2c layer on Linux, ALSA has its own i2c
+code for some cards, because the soundcard needs only a simple operation
+and the standard i2c API is too complicated for such a purpose.
+
+i2c/l3
+~~~~~~
+
+This is a sub-directory for ARM L3 i2c.
+
+synth directory
+---------------
+
+This contains the synth middle-level modules.
+
+So far, there is only Emu8000/Emu10k1 synth driver under the
+``synth/emux`` sub-directory.
+
+pci directory
+-------------
+
+This directory and its sub-directories hold the top-level card modules
+for PCI soundcards and the code specific to the PCI BUS.
+
+The drivers compiled from a single file are stored directly in the pci
+directory, while the drivers with several source files are stored on
+their own sub-directory (e.g. emu10k1, ice1712).
+
+isa directory
+-------------
+
+This directory and its sub-directories hold the top-level card modules
+for ISA soundcards.
+
+arm, ppc, and sparc directories
+-------------------------------
+
+They are used for top-level card modules which are specific to one of
+these architectures.
+
+usb directory
+-------------
+
+This directory contains the USB-audio driver. In the latest version, the
+USB MIDI driver is integrated in the usb-audio driver.
+
+pcmcia directory
+----------------
+
+The PCMCIA, especially PCCard drivers will go here. CardBus drivers will
+be in the pci directory, because their API is identical to that of
+standard PCI cards.
+
+oss directory
+-------------
+
+The OSS/Lite source files are stored here in Linux 2.6 (or later) tree.
+In the ALSA driver tarball, this directory is empty, of course :)
+
+Basic Flow for PCI Drivers
+==========================
+
+Outline
+-------
+
+The minimum flow for PCI soundcards is as follows:
+
+-  define the PCI ID table (see the section `PCI Entries`_).
+
+-  create ``probe`` callback.
+
+-  create ``remove`` callback.
+
+-  create a :c:type:`struct pci_driver <pci_driver>` structure
+   containing the three pointers above.
+
+-  create an ``init`` function just calling the
+   :c:func:`pci_register_driver()` to register the pci_driver
+   table defined above.
+
+-  create an ``exit`` function to call the
+   :c:func:`pci_unregister_driver()` function.
+
+Full Code Example
+-----------------
+
+The code example is shown below. Some parts are kept unimplemented at
+this moment but will be filled in the next sections. The numbers in the
+comment lines of the :c:func:`snd_mychip_probe()` function refer
+to details explained in the following section.
+
+::
+
+      #include <linux/init.h>
+      #include <linux/pci.h>
+      #include <linux/slab.h>
+      #include <sound/core.h>
+      #include <sound/initval.h>
+
+      /* module parameters (see "Module Parameters") */
+      /* SNDRV_CARDS: maximum number of cards supported by this module */
+      static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+      static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+      static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+      /* definition of the chip-specific record */
+      struct mychip {
+              struct snd_card *card;
+              /* the rest of the implementation will be in section
+               * "PCI Resource Management"
+               */
+      };
+
+      /* chip-specific destructor
+       * (see "PCI Resource Management")
+       */
+      static int snd_mychip_free(struct mychip *chip)
+      {
+              .... /* will be implemented later... */
+      }
+
+      /* component-destructor
+       * (see "Management of Cards and Components")
+       */
+      static int snd_mychip_dev_free(struct snd_device *device)
+      {
+              return snd_mychip_free(device->device_data);
+      }
+
+      /* chip-specific constructor
+       * (see "Management of Cards and Components")
+       */
+      static int snd_mychip_create(struct snd_card *card,
+                                   struct pci_dev *pci,
+                                   struct mychip **rchip)
+      {
+              struct mychip *chip;
+              int err;
+              static struct snd_device_ops ops = {
+                     .dev_free = snd_mychip_dev_free,
+              };
+
+              *rchip = NULL;
+
+              /* check PCI availability here
+               * (see "PCI Resource Management")
+               */
+              ....
+
+              /* allocate a chip-specific data with zero filled */
+              chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+              if (chip == NULL)
+                      return -ENOMEM;
+
+              chip->card = card;
+
+              /* rest of initialization here; will be implemented
+               * later, see "PCI Resource Management"
+               */
+              ....
+
+              err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+              if (err < 0) {
+                      snd_mychip_free(chip);
+                      return err;
+              }
+
+              *rchip = chip;
+              return 0;
+      }
+
+      /* constructor -- see "Driver Constructor" sub-section */
+      static int snd_mychip_probe(struct pci_dev *pci,
+                                  const struct pci_device_id *pci_id)
+      {
+              static int dev;
+              struct snd_card *card;
+              struct mychip *chip;
+              int err;
+
+              /* (1) */
+              if (dev >= SNDRV_CARDS)
+                      return -ENODEV;
+              if (!enable[dev]) {
+                      dev++;
+                      return -ENOENT;
+              }
+
+              /* (2) */
+              err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                                 0, &card);
+              if (err < 0)
+                      return err;
+
+              /* (3) */
+              err = snd_mychip_create(card, pci, &chip);
+              if (err < 0) {
+                      snd_card_free(card);
+                      return err;
+              }
+
+              /* (4) */
+              strcpy(card->driver, "My Chip");
+              strcpy(card->shortname, "My Own Chip 123");
+              sprintf(card->longname, "%s at 0x%lx irq %i",
+                      card->shortname, chip->ioport, chip->irq);
+
+              /* (5) */
+              .... /* implemented later */
+
+              /* (6) */
+              err = snd_card_register(card);
+              if (err < 0) {
+                      snd_card_free(card);
+                      return err;
+              }
+
+              /* (7) */
+              pci_set_drvdata(pci, card);
+              dev++;
+              return 0;
+      }
+
+      /* destructor -- see the "Destructor" sub-section */
+      static void snd_mychip_remove(struct pci_dev *pci)
+      {
+              snd_card_free(pci_get_drvdata(pci));
+              pci_set_drvdata(pci, NULL);
+      }
+
+
+
+Driver Constructor
+------------------
+
+The real constructor of PCI drivers is the ``probe`` callback. The
+``probe`` callback and other component-constructors which are called
+from the ``probe`` callback cannot be used with the ``__init`` prefix
+because any PCI device could be a hotplug device.
+
+In the ``probe`` callback, the following scheme is often used.
+
+1) Check and increment the device index.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  static int dev;
+  ....
+  if (dev >= SNDRV_CARDS)
+          return -ENODEV;
+  if (!enable[dev]) {
+          dev++;
+          return -ENOENT;
+  }
+
+
+where ``enable[dev]`` is the module option.
+
+Each time the ``probe`` callback is called, check the availability of
+the device. If not available, simply increment the device index and
+returns. dev will be incremented also later (`step 7
+<#set-the-pci-driver-data-and-return-zero>`__).
+
+2) Create a card instance
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  struct snd_card *card;
+  int err;
+  ....
+  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                     0, &card);
+
+
+The details will be explained in the section `Management of Cards and
+Components`_.
+
+3) Create a main component
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In this part, the PCI resources are allocated.
+
+::
+
+  struct mychip *chip;
+  ....
+  err = snd_mychip_create(card, pci, &chip);
+  if (err < 0) {
+          snd_card_free(card);
+          return err;
+  }
+
+The details will be explained in the section `PCI Resource
+Management`_.
+
+4) Set the driver ID and name strings.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  strcpy(card->driver, "My Chip");
+  strcpy(card->shortname, "My Own Chip 123");
+  sprintf(card->longname, "%s at 0x%lx irq %i",
+          card->shortname, chip->ioport, chip->irq);
+
+The driver field holds the minimal ID string of the chip. This is used
+by alsa-lib's configurator, so keep it simple but unique. Even the
+same driver can have different driver IDs to distinguish the
+functionality of each chip type.
+
+The shortname field is a string shown as more verbose name. The longname
+field contains the information shown in ``/proc/asound/cards``.
+
+5) Create other components, such as mixer, MIDI, etc.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here you define the basic components such as `PCM <#PCM-Interface>`__,
+mixer (e.g. `AC97 <#API-for-AC97-Codec>`__), MIDI (e.g.
+`MPU-401 <#MIDI-MPU401-UART-Interface>`__), and other interfaces.
+Also, if you want a `proc file <#Proc-Interface>`__, define it here,
+too.
+
+6) Register the card instance.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  err = snd_card_register(card);
+  if (err < 0) {
+          snd_card_free(card);
+          return err;
+  }
+
+Will be explained in the section `Management of Cards and
+Components`_, too.
+
+7) Set the PCI driver data and return zero.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  pci_set_drvdata(pci, card);
+  dev++;
+  return 0;
+
+In the above, the card record is stored. This pointer is used in the
+remove callback and power-management callbacks, too.
+
+Destructor
+----------
+
+The destructor, remove callback, simply releases the card instance. Then
+the ALSA middle layer will release all the attached components
+automatically.
+
+It would be typically like the following:
+
+::
+
+  static void snd_mychip_remove(struct pci_dev *pci)
+  {
+          snd_card_free(pci_get_drvdata(pci));
+          pci_set_drvdata(pci, NULL);
+  }
+
+
+The above code assumes that the card pointer is set to the PCI driver
+data.
+
+Header Files
+------------
+
+For the above example, at least the following include files are
+necessary.
+
+::
+
+  #include <linux/init.h>
+  #include <linux/pci.h>
+  #include <linux/slab.h>
+  #include <sound/core.h>
+  #include <sound/initval.h>
+
+where the last one is necessary only when module options are defined
+in the source file. If the code is split into several files, the files
+without module options don't need them.
+
+In addition to these headers, you'll need ``<linux/interrupt.h>`` for
+interrupt handling, and ``<asm/io.h>`` for I/O access. If you use the
+:c:func:`mdelay()` or :c:func:`udelay()` functions, you'll need
+to include ``<linux/delay.h>`` too.
+
+The ALSA interfaces like the PCM and control APIs are defined in other
+``<sound/xxx.h>`` header files. They have to be included after
+``<sound/core.h>``.
+
+Management of Cards and Components
+==================================
+
+Card Instance
+-------------
+
+For each soundcard, a “card” record must be allocated.
+
+A card record is the headquarters of the soundcard. It manages the whole
+list of devices (components) on the soundcard, such as PCM, mixers,
+MIDI, synthesizer, and so on. Also, the card record holds the ID and the
+name strings of the card, manages the root of proc files, and controls
+the power-management states and hotplug disconnections. The component
+list on the card record is used to manage the correct release of
+resources at destruction.
+
+As mentioned above, to create a card instance, call
+:c:func:`snd_card_new()`.
+
+::
+
+  struct snd_card *card;
+  int err;
+  err = snd_card_new(&pci->dev, index, id, module, extra_size, &card);
+
+
+The function takes six arguments: the parent device pointer, the
+card-index number, the id string, the module pointer (usually
+``THIS_MODULE``), the size of extra-data space, and the pointer to
+return the card instance. The extra_size argument is used to allocate
+card->private_data for the chip-specific data. Note that these data are
+allocated by :c:func:`snd_card_new()`.
+
+The first argument, the pointer of struct :c:type:`struct device
+<device>`, specifies the parent device. For PCI devices, typically
+``&pci->`` is passed there.
+
+Components
+----------
+
+After the card is created, you can attach the components (devices) to
+the card instance. In an ALSA driver, a component is represented as a
+:c:type:`struct snd_device <snd_device>` object. A component
+can be a PCM instance, a control interface, a raw MIDI interface, etc.
+Each such instance has one component entry.
+
+A component can be created via :c:func:`snd_device_new()`
+function.
+
+::
+
+  snd_device_new(card, SNDRV_DEV_XXX, chip, &ops);
+
+This takes the card pointer, the device-level (``SNDRV_DEV_XXX``), the
+data pointer, and the callback pointers (``&ops``). The device-level
+defines the type of components and the order of registration and
+de-registration. For most components, the device-level is already
+defined. For a user-defined component, you can use
+``SNDRV_DEV_LOWLEVEL``.
+
+This function itself doesn't allocate the data space. The data must be
+allocated manually beforehand, and its pointer is passed as the
+argument. This pointer (``chip`` in the above example) is used as the
+identifier for the instance.
+
+Each pre-defined ALSA component such as ac97 and pcm calls
+:c:func:`snd_device_new()` inside its constructor. The destructor
+for each component is defined in the callback pointers. Hence, you don't
+need to take care of calling a destructor for such a component.
+
+If you wish to create your own component, you need to set the destructor
+function to the dev_free callback in the ``ops``, so that it can be
+released automatically via :c:func:`snd_card_free()`. The next
+example will show an implementation of chip-specific data.
+
+Chip-Specific Data
+------------------
+
+Chip-specific information, e.g. the I/O port address, its resource
+pointer, or the irq number, is stored in the chip-specific record.
+
+::
+
+  struct mychip {
+          ....
+  };
+
+
+In general, there are two ways of allocating the chip record.
+
+1. Allocating via :c:func:`snd_card_new()`.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As mentioned above, you can pass the extra-data-length to the 5th
+argument of :c:func:`snd_card_new()`, i.e.
+
+::
+
+  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                     sizeof(struct mychip), &card);
+
+:c:type:`struct mychip <mychip>` is the type of the chip record.
+
+In return, the allocated record can be accessed as
+
+::
+
+  struct mychip *chip = card->private_data;
+
+With this method, you don't have to allocate twice. The record is
+released together with the card instance.
+
+2. Allocating an extra device.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+After allocating a card instance via :c:func:`snd_card_new()`
+(with ``0`` on the 4th arg), call :c:func:`kzalloc()`.
+
+::
+
+  struct snd_card *card;
+  struct mychip *chip;
+  err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                     0, &card);
+  .....
+  chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+
+The chip record should have the field to hold the card pointer at least,
+
+::
+
+  struct mychip {
+          struct snd_card *card;
+          ....
+  };
+
+
+Then, set the card pointer in the returned chip instance.
+
+::
+
+  chip->card = card;
+
+Next, initialize the fields, and register this chip record as a
+low-level device with a specified ``ops``,
+
+::
+
+  static struct snd_device_ops ops = {
+          .dev_free =        snd_mychip_dev_free,
+  };
+  ....
+  snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+
+:c:func:`snd_mychip_dev_free()` is the device-destructor
+function, which will call the real destructor.
+
+::
+
+  static int snd_mychip_dev_free(struct snd_device *device)
+  {
+          return snd_mychip_free(device->device_data);
+  }
+
+where :c:func:`snd_mychip_free()` is the real destructor.
+
+Registration and Release
+------------------------
+
+After all components are assigned, register the card instance by calling
+:c:func:`snd_card_register()`. Access to the device files is
+enabled at this point. That is, before
+:c:func:`snd_card_register()` is called, the components are safely
+inaccessible from external side. If this call fails, exit the probe
+function after releasing the card via :c:func:`snd_card_free()`.
+
+For releasing the card instance, you can call simply
+:c:func:`snd_card_free()`. As mentioned earlier, all components
+are released automatically by this call.
+
+For a device which allows hotplugging, you can use
+:c:func:`snd_card_free_when_closed()`. This one will postpone
+the destruction until all devices are closed.
+
+PCI Resource Management
+=======================
+
+Full Code Example
+-----------------
+
+In this section, we'll complete the chip-specific constructor,
+destructor and PCI entries. Example code is shown first, below.
+
+::
+
+      struct mychip {
+              struct snd_card *card;
+              struct pci_dev *pci;
+
+              unsigned long port;
+              int irq;
+      };
+
+      static int snd_mychip_free(struct mychip *chip)
+      {
+              /* disable hardware here if any */
+              .... /* (not implemented in this document) */
+
+              /* release the irq */
+              if (chip->irq >= 0)
+                      free_irq(chip->irq, chip);
+              /* release the I/O ports & memory */
+              pci_release_regions(chip->pci);
+              /* disable the PCI entry */
+              pci_disable_device(chip->pci);
+              /* release the data */
+              kfree(chip);
+              return 0;
+      }
+
+      /* chip-specific constructor */
+      static int snd_mychip_create(struct snd_card *card,
+                                   struct pci_dev *pci,
+                                   struct mychip **rchip)
+      {
+              struct mychip *chip;
+              int err;
+              static struct snd_device_ops ops = {
+                     .dev_free = snd_mychip_dev_free,
+              };
+
+              *rchip = NULL;
+
+              /* initialize the PCI entry */
+              err = pci_enable_device(pci);
+              if (err < 0)
+                      return err;
+              /* check PCI availability (28bit DMA) */
+              if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
+                  pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
+                      printk(KERN_ERR "error to set 28bit mask DMA\n");
+                      pci_disable_device(pci);
+                      return -ENXIO;
+              }
+
+              chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+              if (chip == NULL) {
+                      pci_disable_device(pci);
+                      return -ENOMEM;
+              }
+
+              /* initialize the stuff */
+              chip->card = card;
+              chip->pci = pci;
+              chip->irq = -1;
+
+              /* (1) PCI resource allocation */
+              err = pci_request_regions(pci, "My Chip");
+              if (err < 0) {
+                      kfree(chip);
+                      pci_disable_device(pci);
+                      return err;
+              }
+              chip->port = pci_resource_start(pci, 0);
+              if (request_irq(pci->irq, snd_mychip_interrupt,
+                              IRQF_SHARED, KBUILD_MODNAME, chip)) {
+                      printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+                      snd_mychip_free(chip);
+                      return -EBUSY;
+              }
+              chip->irq = pci->irq;
+
+              /* (2) initialization of the chip hardware */
+              .... /*   (not implemented in this document) */
+
+              err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
+              if (err < 0) {
+                      snd_mychip_free(chip);
+                      return err;
+              }
+
+              *rchip = chip;
+              return 0;
+      }
+
+      /* PCI IDs */
+      static struct pci_device_id snd_mychip_ids[] = {
+              { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
+                PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+              ....
+              { 0, }
+      };
+      MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
+
+      /* pci_driver definition */
+      static struct pci_driver driver = {
+              .name = KBUILD_MODNAME,
+              .id_table = snd_mychip_ids,
+              .probe = snd_mychip_probe,
+              .remove = snd_mychip_remove,
+      };
+
+      /* module initialization */
+      static int __init alsa_card_mychip_init(void)
+      {
+              return pci_register_driver(&driver);
+      }
+
+      /* module clean up */
+      static void __exit alsa_card_mychip_exit(void)
+      {
+              pci_unregister_driver(&driver);
+      }
+
+      module_init(alsa_card_mychip_init)
+      module_exit(alsa_card_mychip_exit)
+
+      EXPORT_NO_SYMBOLS; /* for old kernels only */
+
+Some Hafta's
+------------
+
+The allocation of PCI resources is done in the ``probe`` function, and
+usually an extra :c:func:`xxx_create()` function is written for this
+purpose.
+
+In the case of PCI devices, you first have to call the
+:c:func:`pci_enable_device()` function before allocating
+resources. Also, you need to set the proper PCI DMA mask to limit the
+accessed I/O range. In some cases, you might need to call
+:c:func:`pci_set_master()` function, too.
+
+Suppose the 28bit mask, and the code to be added would be like:
+
+::
+
+  err = pci_enable_device(pci);
+  if (err < 0)
+          return err;
+  if (pci_set_dma_mask(pci, DMA_BIT_MASK(28)) < 0 ||
+      pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(28)) < 0) {
+          printk(KERN_ERR "error to set 28bit mask DMA\n");
+          pci_disable_device(pci);
+          return -ENXIO;
+  }
+  
+
+Resource Allocation
+-------------------
+
+The allocation of I/O ports and irqs is done via standard kernel
+functions. Unlike ALSA ver.0.5.x., there are no helpers for that. And
+these resources must be released in the destructor function (see below).
+Also, on ALSA 0.9.x, you don't need to allocate (pseudo-)DMA for PCI
+like in ALSA 0.5.x.
+
+Now assume that the PCI device has an I/O port with 8 bytes and an
+interrupt. Then :c:type:`struct mychip <mychip>` will have the
+following fields:
+
+::
+
+  struct mychip {
+          struct snd_card *card;
+
+          unsigned long port;
+          int irq;
+  };
+
+
+For an I/O port (and also a memory region), you need to have the
+resource pointer for the standard resource management. For an irq, you
+have to keep only the irq number (integer). But you need to initialize
+this number as -1 before actual allocation, since irq 0 is valid. The
+port address and its resource pointer can be initialized as null by
+:c:func:`kzalloc()` automatically, so you don't have to take care of
+resetting them.
+
+The allocation of an I/O port is done like this:
+
+::
+
+  err = pci_request_regions(pci, "My Chip");
+  if (err < 0) { 
+          kfree(chip);
+          pci_disable_device(pci);
+          return err;
+  }
+  chip->port = pci_resource_start(pci, 0);
+
+It will reserve the I/O port region of 8 bytes of the given PCI device.
+The returned value, ``chip->res_port``, is allocated via
+:c:func:`kmalloc()` by :c:func:`request_region()`. The pointer
+must be released via :c:func:`kfree()`, but there is a problem with
+this. This issue will be explained later.
+
+The allocation of an interrupt source is done like this:
+
+::
+
+  if (request_irq(pci->irq, snd_mychip_interrupt,
+                  IRQF_SHARED, KBUILD_MODNAME, chip)) {
+          printk(KERN_ERR "cannot grab irq %d\n", pci->irq);
+          snd_mychip_free(chip);
+          return -EBUSY;
+  }
+  chip->irq = pci->irq;
+
+where :c:func:`snd_mychip_interrupt()` is the interrupt handler
+defined `later <#pcm-interface-interrupt-handler>`__. Note that
+``chip->irq`` should be defined only when :c:func:`request_irq()`
+succeeded.
+
+On the PCI bus, interrupts can be shared. Thus, ``IRQF_SHARED`` is used
+as the interrupt flag of :c:func:`request_irq()`.
+
+The last argument of :c:func:`request_irq()` is the data pointer
+passed to the interrupt handler. Usually, the chip-specific record is
+used for that, but you can use what you like, too.
+
+I won't give details about the interrupt handler at this point, but at
+least its appearance can be explained now. The interrupt handler looks
+usually like the following:
+
+::
+
+  static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+  {
+          struct mychip *chip = dev_id;
+          ....
+          return IRQ_HANDLED;
+  }
+
+
+Now let's write the corresponding destructor for the resources above.
+The role of destructor is simple: disable the hardware (if already
+activated) and release the resources. So far, we have no hardware part,
+so the disabling code is not written here.
+
+To release the resources, the “check-and-release” method is a safer way.
+For the interrupt, do like this:
+
+::
+
+  if (chip->irq >= 0)
+          free_irq(chip->irq, chip);
+
+Since the irq number can start from 0, you should initialize
+``chip->irq`` with a negative value (e.g. -1), so that you can check
+the validity of the irq number as above.
+
+When you requested I/O ports or memory regions via
+:c:func:`pci_request_region()` or
+:c:func:`pci_request_regions()` like in this example, release the
+resource(s) using the corresponding function,
+:c:func:`pci_release_region()` or
+:c:func:`pci_release_regions()`.
+
+::
+
+  pci_release_regions(chip->pci);
+
+When you requested manually via :c:func:`request_region()` or
+:c:func:`request_mem_region()`, you can release it via
+:c:func:`release_resource()`. Suppose that you keep the resource
+pointer returned from :c:func:`request_region()` in
+chip->res_port, the release procedure looks like:
+
+::
+
+  release_and_free_resource(chip->res_port);
+
+Don't forget to call :c:func:`pci_disable_device()` before the
+end.
+
+And finally, release the chip-specific record.
+
+::
+
+  kfree(chip);
+
+We didn't implement the hardware disabling part in the above. If you
+need to do this, please note that the destructor may be called even
+before the initialization of the chip is completed. It would be better
+to have a flag to skip hardware disabling if the hardware was not
+initialized yet.
+
+When the chip-data is assigned to the card using
+:c:func:`snd_device_new()` with ``SNDRV_DEV_LOWLELVEL`` , its
+destructor is called at the last. That is, it is assured that all other
+components like PCMs and controls have already been released. You don't
+have to stop PCMs, etc. explicitly, but just call low-level hardware
+stopping.
+
+The management of a memory-mapped region is almost as same as the
+management of an I/O port. You'll need three fields like the
+following:
+
+::
+
+  struct mychip {
+          ....
+          unsigned long iobase_phys;
+          void __iomem *iobase_virt;
+  };
+
+and the allocation would be like below:
+
+::
+
+  if ((err = pci_request_regions(pci, "My Chip")) < 0) {
+          kfree(chip);
+          return err;
+  }
+  chip->iobase_phys = pci_resource_start(pci, 0);
+  chip->iobase_virt = ioremap_nocache(chip->iobase_phys,
+                                      pci_resource_len(pci, 0));
+
+and the corresponding destructor would be:
+
+::
+
+  static int snd_mychip_free(struct mychip *chip)
+  {
+          ....
+          if (chip->iobase_virt)
+                  iounmap(chip->iobase_virt);
+          ....
+          pci_release_regions(chip->pci);
+          ....
+  }
+
+PCI Entries
+-----------
+
+So far, so good. Let's finish the missing PCI stuff. At first, we need a
+:c:type:`struct pci_device_id <pci_device_id>` table for
+this chipset. It's a table of PCI vendor/device ID number, and some
+masks.
+
+For example,
+
+::
+
+  static struct pci_device_id snd_mychip_ids[] = {
+          { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR,
+            PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+          ....
+          { 0, }
+  };
+  MODULE_DEVICE_TABLE(pci, snd_mychip_ids);
+
+The first and second fields of the :c:type:`struct pci_device_id
+<pci_device_id>` structure are the vendor and device IDs. If you
+have no reason to filter the matching devices, you can leave the
+remaining fields as above. The last field of the :c:type:`struct
+pci_device_id <pci_device_id>` struct contains private data
+for this entry. You can specify any value here, for example, to define
+specific operations for supported device IDs. Such an example is found
+in the intel8x0 driver.
+
+The last entry of this list is the terminator. You must specify this
+all-zero entry.
+
+Then, prepare the :c:type:`struct pci_driver <pci_driver>`
+record:
+
+::
+
+  static struct pci_driver driver = {
+          .name = KBUILD_MODNAME,
+          .id_table = snd_mychip_ids,
+          .probe = snd_mychip_probe,
+          .remove = snd_mychip_remove,
+  };
+
+The ``probe`` and ``remove`` functions have already been defined in
+the previous sections. The ``name`` field is the name string of this
+device. Note that you must not use a slash “/” in this string.
+
+And at last, the module entries:
+
+::
+
+  static int __init alsa_card_mychip_init(void)
+  {
+          return pci_register_driver(&driver);
+  }
+
+  static void __exit alsa_card_mychip_exit(void)
+  {
+          pci_unregister_driver(&driver);
+  }
+
+  module_init(alsa_card_mychip_init)
+  module_exit(alsa_card_mychip_exit)
+
+Note that these module entries are tagged with ``__init`` and ``__exit``
+prefixes.
+
+Oh, one thing was forgotten. If you have no exported symbols, you need
+to declare it in 2.2 or 2.4 kernels (it's not necessary in 2.6 kernels).
+
+::
+
+  EXPORT_NO_SYMBOLS;
+
+That's all!
+
+PCM Interface
+=============
+
+General
+-------
+
+The PCM middle layer of ALSA is quite powerful and it is only necessary
+for each driver to implement the low-level functions to access its
+hardware.
+
+For accessing to the PCM layer, you need to include ``<sound/pcm.h>``
+first. In addition, ``<sound/pcm_params.h>`` might be needed if you
+access to some functions related with hw_param.
+
+Each card device can have up to four pcm instances. A pcm instance
+corresponds to a pcm device file. The limitation of number of instances
+comes only from the available bit size of the Linux's device numbers.
+Once when 64bit device number is used, we'll have more pcm instances
+available.
+
+A pcm instance consists of pcm playback and capture streams, and each
+pcm stream consists of one or more pcm substreams. Some soundcards
+support multiple playback functions. For example, emu10k1 has a PCM
+playback of 32 stereo substreams. In this case, at each open, a free
+substream is (usually) automatically chosen and opened. Meanwhile, when
+only one substream exists and it was already opened, the successful open
+will either block or error with ``EAGAIN`` according to the file open
+mode. But you don't have to care about such details in your driver. The
+PCM middle layer will take care of such work.
+
+Full Code Example
+-----------------
+
+The example code below does not include any hardware access routines but
+shows only the skeleton, how to build up the PCM interfaces.
+
+::
+
+      #include <sound/pcm.h>
+      ....
+
+      /* hardware definition */
+      static struct snd_pcm_hardware snd_mychip_playback_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_8000_48000,
+              .rate_min =         8000,
+              .rate_max =         48000,
+              .channels_min =     2,
+              .channels_max =     2,
+              .buffer_bytes_max = 32768,
+              .period_bytes_min = 4096,
+              .period_bytes_max = 32768,
+              .periods_min =      1,
+              .periods_max =      1024,
+      };
+
+      /* hardware definition */
+      static struct snd_pcm_hardware snd_mychip_capture_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_8000_48000,
+              .rate_min =         8000,
+              .rate_max =         48000,
+              .channels_min =     2,
+              .channels_max =     2,
+              .buffer_bytes_max = 32768,
+              .period_bytes_min = 4096,
+              .period_bytes_max = 32768,
+              .periods_min =      1,
+              .periods_max =      1024,
+      };
+
+      /* open callback */
+      static int snd_mychip_playback_open(struct snd_pcm_substream *substream)
+      {
+              struct mychip *chip = snd_pcm_substream_chip(substream);
+              struct snd_pcm_runtime *runtime = substream->runtime;
+
+              runtime->hw = snd_mychip_playback_hw;
+              /* more hardware-initialization will be done here */
+              ....
+              return 0;
+      }
+
+      /* close callback */
+      static int snd_mychip_playback_close(struct snd_pcm_substream *substream)
+      {
+              struct mychip *chip = snd_pcm_substream_chip(substream);
+              /* the hardware-specific codes will be here */
+              ....
+              return 0;
+
+      }
+
+      /* open callback */
+      static int snd_mychip_capture_open(struct snd_pcm_substream *substream)
+      {
+              struct mychip *chip = snd_pcm_substream_chip(substream);
+              struct snd_pcm_runtime *runtime = substream->runtime;
+
+              runtime->hw = snd_mychip_capture_hw;
+              /* more hardware-initialization will be done here */
+              ....
+              return 0;
+      }
+
+      /* close callback */
+      static int snd_mychip_capture_close(struct snd_pcm_substream *substream)
+      {
+              struct mychip *chip = snd_pcm_substream_chip(substream);
+              /* the hardware-specific codes will be here */
+              ....
+              return 0;
+
+      }
+
+      /* hw_params callback */
+      static int snd_mychip_pcm_hw_params(struct snd_pcm_substream *substream,
+                                   struct snd_pcm_hw_params *hw_params)
+      {
+              return snd_pcm_lib_malloc_pages(substream,
+                                         params_buffer_bytes(hw_params));
+      }
+
+      /* hw_free callback */
+      static int snd_mychip_pcm_hw_free(struct snd_pcm_substream *substream)
+      {
+              return snd_pcm_lib_free_pages(substream);
+      }
+
+      /* prepare callback */
+      static int snd_mychip_pcm_prepare(struct snd_pcm_substream *substream)
+      {
+              struct mychip *chip = snd_pcm_substream_chip(substream);
+              struct snd_pcm_runtime *runtime = substream->runtime;
+
+              /* set up the hardware with the current configuration
+               * for example...
+               */
+              mychip_set_sample_format(chip, runtime->format);
+              mychip_set_sample_rate(chip, runtime->rate);
+              mychip_set_channels(chip, runtime->channels);
+              mychip_set_dma_setup(chip, runtime->dma_addr,
+                                   chip->buffer_size,
+                                   chip->period_size);
+              return 0;
+      }
+
+      /* trigger callback */
+      static int snd_mychip_pcm_trigger(struct snd_pcm_substream *substream,
+                                        int cmd)
+      {
+              switch (cmd) {
+              case SNDRV_PCM_TRIGGER_START:
+                      /* do something to start the PCM engine */
+                      ....
+                      break;
+              case SNDRV_PCM_TRIGGER_STOP:
+                      /* do something to stop the PCM engine */
+                      ....
+                      break;
+              default:
+                      return -EINVAL;
+              }
+      }
+
+      /* pointer callback */
+      static snd_pcm_uframes_t
+      snd_mychip_pcm_pointer(struct snd_pcm_substream *substream)
+      {
+              struct mychip *chip = snd_pcm_substream_chip(substream);
+              unsigned int current_ptr;
+
+              /* get the current hardware pointer */
+              current_ptr = mychip_get_hw_pointer(chip);
+              return current_ptr;
+      }
+
+      /* operators */
+      static struct snd_pcm_ops snd_mychip_playback_ops = {
+              .open =        snd_mychip_playback_open,
+              .close =       snd_mychip_playback_close,
+              .ioctl =       snd_pcm_lib_ioctl,
+              .hw_params =   snd_mychip_pcm_hw_params,
+              .hw_free =     snd_mychip_pcm_hw_free,
+              .prepare =     snd_mychip_pcm_prepare,
+              .trigger =     snd_mychip_pcm_trigger,
+              .pointer =     snd_mychip_pcm_pointer,
+      };
+
+      /* operators */
+      static struct snd_pcm_ops snd_mychip_capture_ops = {
+              .open =        snd_mychip_capture_open,
+              .close =       snd_mychip_capture_close,
+              .ioctl =       snd_pcm_lib_ioctl,
+              .hw_params =   snd_mychip_pcm_hw_params,
+              .hw_free =     snd_mychip_pcm_hw_free,
+              .prepare =     snd_mychip_pcm_prepare,
+              .trigger =     snd_mychip_pcm_trigger,
+              .pointer =     snd_mychip_pcm_pointer,
+      };
+
+      /*
+       *  definitions of capture are omitted here...
+       */
+
+      /* create a pcm device */
+      static int snd_mychip_new_pcm(struct mychip *chip)
+      {
+              struct snd_pcm *pcm;
+              int err;
+
+              err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+              if (err < 0)
+                      return err;
+              pcm->private_data = chip;
+              strcpy(pcm->name, "My Chip");
+              chip->pcm = pcm;
+              /* set operators */
+              snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                              &snd_mychip_playback_ops);
+              snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                              &snd_mychip_capture_ops);
+              /* pre-allocation of buffers */
+              /* NOTE: this may fail */
+              snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                                    snd_dma_pci_data(chip->pci),
+                                                    64*1024, 64*1024);
+              return 0;
+      }
+
+
+PCM Constructor
+---------------
+
+A pcm instance is allocated by the :c:func:`snd_pcm_new()`
+function. It would be better to create a constructor for pcm, namely,
+
+::
+
+  static int snd_mychip_new_pcm(struct mychip *chip)
+  {
+          struct snd_pcm *pcm;
+          int err;
+
+          err = snd_pcm_new(chip->card, "My Chip", 0, 1, 1, &pcm);
+          if (err < 0) 
+                  return err;
+          pcm->private_data = chip;
+          strcpy(pcm->name, "My Chip");
+          chip->pcm = pcm;
+	  ....
+          return 0;
+  }
+
+The :c:func:`snd_pcm_new()` function takes four arguments. The
+first argument is the card pointer to which this pcm is assigned, and
+the second is the ID string.
+
+The third argument (``index``, 0 in the above) is the index of this new
+pcm. It begins from zero. If you create more than one pcm instances,
+specify the different numbers in this argument. For example, ``index =
+1`` for the second PCM device.
+
+The fourth and fifth arguments are the number of substreams for playback
+and capture, respectively. Here 1 is used for both arguments. When no
+playback or capture substreams are available, pass 0 to the
+corresponding argument.
+
+If a chip supports multiple playbacks or captures, you can specify more
+numbers, but they must be handled properly in open/close, etc.
+callbacks. When you need to know which substream you are referring to,
+then it can be obtained from :c:type:`struct snd_pcm_substream
+<snd_pcm_substream>` data passed to each callback as follows:
+
+::
+
+  struct snd_pcm_substream *substream;
+  int index = substream->number;
+
+
+After the pcm is created, you need to set operators for each pcm stream.
+
+::
+
+  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+                  &snd_mychip_playback_ops);
+  snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                  &snd_mychip_capture_ops);
+
+The operators are defined typically like this:
+
+::
+
+  static struct snd_pcm_ops snd_mychip_playback_ops = {
+          .open =        snd_mychip_pcm_open,
+          .close =       snd_mychip_pcm_close,
+          .ioctl =       snd_pcm_lib_ioctl,
+          .hw_params =   snd_mychip_pcm_hw_params,
+          .hw_free =     snd_mychip_pcm_hw_free,
+          .prepare =     snd_mychip_pcm_prepare,
+          .trigger =     snd_mychip_pcm_trigger,
+          .pointer =     snd_mychip_pcm_pointer,
+  };
+
+All the callbacks are described in the Operators_ subsection.
+
+After setting the operators, you probably will want to pre-allocate the
+buffer. For the pre-allocation, simply call the following:
+
+::
+
+  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                        snd_dma_pci_data(chip->pci),
+                                        64*1024, 64*1024);
+
+It will allocate a buffer up to 64kB as default. Buffer management
+details will be described in the later section `Buffer and Memory
+Management`_.
+
+Additionally, you can set some extra information for this pcm in
+``pcm->info_flags``. The available values are defined as
+``SNDRV_PCM_INFO_XXX`` in ``<sound/asound.h>``, which is used for the
+hardware definition (described later). When your soundchip supports only
+half-duplex, specify like this:
+
+::
+
+  pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
+
+
+... And the Destructor?
+-----------------------
+
+The destructor for a pcm instance is not always necessary. Since the pcm
+device will be released by the middle layer code automatically, you
+don't have to call the destructor explicitly.
+
+The destructor would be necessary if you created special records
+internally and needed to release them. In such a case, set the
+destructor function to ``pcm->private_free``:
+
+::
+
+      static void mychip_pcm_free(struct snd_pcm *pcm)
+      {
+              struct mychip *chip = snd_pcm_chip(pcm);
+              /* free your own data */
+              kfree(chip->my_private_pcm_data);
+              /* do what you like else */
+              ....
+      }
+
+      static int snd_mychip_new_pcm(struct mychip *chip)
+      {
+              struct snd_pcm *pcm;
+              ....
+              /* allocate your own data */
+              chip->my_private_pcm_data = kmalloc(...);
+              /* set the destructor */
+              pcm->private_data = chip;
+              pcm->private_free = mychip_pcm_free;
+              ....
+      }
+
+
+
+Runtime Pointer - The Chest of PCM Information
+----------------------------------------------
+
+When the PCM substream is opened, a PCM runtime instance is allocated
+and assigned to the substream. This pointer is accessible via
+``substream->runtime``. This runtime pointer holds most information you
+need to control the PCM: the copy of hw_params and sw_params
+configurations, the buffer pointers, mmap records, spinlocks, etc.
+
+The definition of runtime instance is found in ``<sound/pcm.h>``. Here
+are the contents of this file:
+
+::
+
+  struct _snd_pcm_runtime {
+          /* -- Status -- */
+          struct snd_pcm_substream *trigger_master;
+          snd_timestamp_t trigger_tstamp;	/* trigger timestamp */
+          int overrange;
+          snd_pcm_uframes_t avail_max;
+          snd_pcm_uframes_t hw_ptr_base;	/* Position at buffer restart */
+          snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time*/
+  
+          /* -- HW params -- */
+          snd_pcm_access_t access;	/* access mode */
+          snd_pcm_format_t format;	/* SNDRV_PCM_FORMAT_* */
+          snd_pcm_subformat_t subformat;	/* subformat */
+          unsigned int rate;		/* rate in Hz */
+          unsigned int channels;		/* channels */
+          snd_pcm_uframes_t period_size;	/* period size */
+          unsigned int periods;		/* periods */
+          snd_pcm_uframes_t buffer_size;	/* buffer size */
+          unsigned int tick_time;		/* tick time */
+          snd_pcm_uframes_t min_align;	/* Min alignment for the format */
+          size_t byte_align;
+          unsigned int frame_bits;
+          unsigned int sample_bits;
+          unsigned int info;
+          unsigned int rate_num;
+          unsigned int rate_den;
+  
+          /* -- SW params -- */
+          struct timespec tstamp_mode;	/* mmap timestamp is updated */
+          unsigned int period_step;
+          unsigned int sleep_min;		/* min ticks to sleep */
+          snd_pcm_uframes_t start_threshold;
+          snd_pcm_uframes_t stop_threshold;
+          snd_pcm_uframes_t silence_threshold; /* Silence filling happens when
+                                                  noise is nearest than this */
+          snd_pcm_uframes_t silence_size;	/* Silence filling size */
+          snd_pcm_uframes_t boundary;	/* pointers wrap point */
+  
+          snd_pcm_uframes_t silenced_start;
+          snd_pcm_uframes_t silenced_size;
+  
+          snd_pcm_sync_id_t sync;		/* hardware synchronization ID */
+  
+          /* -- mmap -- */
+          volatile struct snd_pcm_mmap_status *status;
+          volatile struct snd_pcm_mmap_control *control;
+          atomic_t mmap_count;
+  
+          /* -- locking / scheduling -- */
+          spinlock_t lock;
+          wait_queue_head_t sleep;
+          struct timer_list tick_timer;
+          struct fasync_struct *fasync;
+
+          /* -- private section -- */
+          void *private_data;
+          void (*private_free)(struct snd_pcm_runtime *runtime);
+  
+          /* -- hardware description -- */
+          struct snd_pcm_hardware hw;
+          struct snd_pcm_hw_constraints hw_constraints;
+  
+          /* -- timer -- */
+          unsigned int timer_resolution;	/* timer resolution */
+  
+          /* -- DMA -- */           
+          unsigned char *dma_area;	/* DMA area */
+          dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
+          size_t dma_bytes;		/* size of DMA area */
+  
+          struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
+  
+  #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
+          /* -- OSS things -- */
+          struct snd_pcm_oss_runtime oss;
+  #endif
+  };
+
+
+For the operators (callbacks) of each sound driver, most of these
+records are supposed to be read-only. Only the PCM middle-layer changes
+/ updates them. The exceptions are the hardware description (hw) DMA
+buffer information and the private data. Besides, if you use the
+standard buffer allocation method via
+:c:func:`snd_pcm_lib_malloc_pages()`, you don't need to set the
+DMA buffer information by yourself.
+
+In the sections below, important records are explained.
+
+Hardware Description
+~~~~~~~~~~~~~~~~~~~~
+
+The hardware descriptor (:c:type:`struct snd_pcm_hardware
+<snd_pcm_hardware>`) contains the definitions of the fundamental
+hardware configuration. Above all, you'll need to define this in the
+`PCM open callback`_. Note that the runtime instance holds the copy of
+the descriptor, not the pointer to the existing descriptor. That is,
+in the open callback, you can modify the copied descriptor
+(``runtime->hw``) as you need. For example, if the maximum number of
+channels is 1 only on some chip models, you can still use the same
+hardware descriptor and change the channels_max later:
+
+::
+
+          struct snd_pcm_runtime *runtime = substream->runtime;
+          ...
+          runtime->hw = snd_mychip_playback_hw; /* common definition */
+          if (chip->model == VERY_OLD_ONE)
+                  runtime->hw.channels_max = 1;
+
+Typically, you'll have a hardware descriptor as below:
+
+::
+
+  static struct snd_pcm_hardware snd_mychip_playback_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_8000_48000,
+          .rate_min =         8000,
+          .rate_max =         48000,
+          .channels_min =     2,
+          .channels_max =     2,
+          .buffer_bytes_max = 32768,
+          .period_bytes_min = 4096,
+          .period_bytes_max = 32768,
+          .periods_min =      1,
+          .periods_max =      1024,
+  };
+
+-  The ``info`` field contains the type and capabilities of this
+   pcm. The bit flags are defined in ``<sound/asound.h>`` as
+   ``SNDRV_PCM_INFO_XXX``. Here, at least, you have to specify whether
+   the mmap is supported and which interleaved format is
+   supported. When the hardware supports mmap, add the
+   ``SNDRV_PCM_INFO_MMAP`` flag here. When the hardware supports the
+   interleaved or the non-interleaved formats,
+   ``SNDRV_PCM_INFO_INTERLEAVED`` or ``SNDRV_PCM_INFO_NONINTERLEAVED``
+   flag must be set, respectively. If both are supported, you can set
+   both, too.
+
+   In the above example, ``MMAP_VALID`` and ``BLOCK_TRANSFER`` are
+   specified for the OSS mmap mode. Usually both are set. Of course,
+   ``MMAP_VALID`` is set only if the mmap is really supported.
+
+   The other possible flags are ``SNDRV_PCM_INFO_PAUSE`` and
+   ``SNDRV_PCM_INFO_RESUME``. The ``PAUSE`` bit means that the pcm
+   supports the “pause” operation, while the ``RESUME`` bit means that
+   the pcm supports the full “suspend/resume” operation. If the
+   ``PAUSE`` flag is set, the ``trigger`` callback below must handle
+   the corresponding (pause push/release) commands. The suspend/resume
+   trigger commands can be defined even without the ``RESUME``
+   flag. See `Power Management`_ section for details.
+
+   When the PCM substreams can be synchronized (typically,
+   synchronized start/stop of a playback and a capture streams), you
+   can give ``SNDRV_PCM_INFO_SYNC_START``, too. In this case, you'll
+   need to check the linked-list of PCM substreams in the trigger
+   callback. This will be described in the later section.
+
+-  ``formats`` field contains the bit-flags of supported formats
+   (``SNDRV_PCM_FMTBIT_XXX``). If the hardware supports more than one
+   format, give all or'ed bits. In the example above, the signed 16bit
+   little-endian format is specified.
+
+-  ``rates`` field contains the bit-flags of supported rates
+   (``SNDRV_PCM_RATE_XXX``). When the chip supports continuous rates,
+   pass ``CONTINUOUS`` bit additionally. The pre-defined rate bits are
+   provided only for typical rates. If your chip supports
+   unconventional rates, you need to add the ``KNOT`` bit and set up
+   the hardware constraint manually (explained later).
+
+-  ``rate_min`` and ``rate_max`` define the minimum and maximum sample
+   rate. This should correspond somehow to ``rates`` bits.
+
+-  ``channel_min`` and ``channel_max`` define, as you might already
+   expected, the minimum and maximum number of channels.
+
+-  ``buffer_bytes_max`` defines the maximum buffer size in
+   bytes. There is no ``buffer_bytes_min`` field, since it can be
+   calculated from the minimum period size and the minimum number of
+   periods. Meanwhile, ``period_bytes_min`` and define the minimum and
+   maximum size of the period in bytes. ``periods_max`` and
+   ``periods_min`` define the maximum and minimum number of periods in
+   the buffer.
+
+   The “period” is a term that corresponds to a fragment in the OSS
+   world. The period defines the size at which a PCM interrupt is
+   generated. This size strongly depends on the hardware. Generally,
+   the smaller period size will give you more interrupts, that is,
+   more controls. In the case of capture, this size defines the input
+   latency. On the other hand, the whole buffer size defines the
+   output latency for the playback direction.
+
+-  There is also a field ``fifo_size``. This specifies the size of the
+   hardware FIFO, but currently it is neither used in the driver nor
+   in the alsa-lib. So, you can ignore this field.
+
+PCM Configurations
+~~~~~~~~~~~~~~~~~~
+
+Ok, let's go back again to the PCM runtime records. The most
+frequently referred records in the runtime instance are the PCM
+configurations. The PCM configurations are stored in the runtime
+instance after the application sends ``hw_params`` data via
+alsa-lib. There are many fields copied from hw_params and sw_params
+structs. For example, ``format`` holds the format type chosen by the
+application. This field contains the enum value
+``SNDRV_PCM_FORMAT_XXX``.
+
+One thing to be noted is that the configured buffer and period sizes
+are stored in “frames” in the runtime. In the ALSA world, ``1 frame =
+channels \* samples-size``. For conversion between frames and bytes,
+you can use the :c:func:`frames_to_bytes()` and
+:c:func:`bytes_to_frames()` helper functions.
+
+::
+
+  period_bytes = frames_to_bytes(runtime, runtime->period_size);
+
+Also, many software parameters (sw_params) are stored in frames, too.
+Please check the type of the field. ``snd_pcm_uframes_t`` is for the
+frames as unsigned integer while ``snd_pcm_sframes_t`` is for the
+frames as signed integer.
+
+DMA Buffer Information
+~~~~~~~~~~~~~~~~~~~~~~
+
+The DMA buffer is defined by the following four fields, ``dma_area``,
+``dma_addr``, ``dma_bytes`` and ``dma_private``. The ``dma_area``
+holds the buffer pointer (the logical address). You can call
+:c:func:`memcpy()` from/to this pointer. Meanwhile, ``dma_addr`` holds
+the physical address of the buffer. This field is specified only when
+the buffer is a linear buffer. ``dma_bytes`` holds the size of buffer
+in bytes. ``dma_private`` is used for the ALSA DMA allocator.
+
+If you use a standard ALSA function,
+:c:func:`snd_pcm_lib_malloc_pages()`, for allocating the buffer,
+these fields are set by the ALSA middle layer, and you should *not*
+change them by yourself. You can read them but not write them. On the
+other hand, if you want to allocate the buffer by yourself, you'll
+need to manage it in hw_params callback. At least, ``dma_bytes`` is
+mandatory. ``dma_area`` is necessary when the buffer is mmapped. If
+your driver doesn't support mmap, this field is not
+necessary. ``dma_addr`` is also optional. You can use dma_private as
+you like, too.
+
+Running Status
+~~~~~~~~~~~~~~
+
+The running status can be referred via ``runtime->status``. This is
+the pointer to the :c:type:`struct snd_pcm_mmap_status
+<snd_pcm_mmap_status>` record. For example, you can get the current
+DMA hardware pointer via ``runtime->status->hw_ptr``.
+
+The DMA application pointer can be referred via ``runtime->control``,
+which points to the :c:type:`struct snd_pcm_mmap_control
+<snd_pcm_mmap_control>` record. However, accessing directly to
+this value is not recommended.
+
+Private Data
+~~~~~~~~~~~~
+
+You can allocate a record for the substream and store it in
+``runtime->private_data``. Usually, this is done in the `PCM open
+callback`_. Don't mix this with ``pcm->private_data``. The
+``pcm->private_data`` usually points to the chip instance assigned
+statically at the creation of PCM, while the ``runtime->private_data``
+points to a dynamic data structure created at the PCM open
+callback.
+
+::
+
+  static int snd_xxx_open(struct snd_pcm_substream *substream)
+  {
+          struct my_pcm_data *data;
+          ....
+          data = kmalloc(sizeof(*data), GFP_KERNEL);
+          substream->runtime->private_data = data;
+          ....
+  }
+
+
+The allocated object must be released in the `close callback`_.
+
+Operators
+---------
+
+OK, now let me give details about each pcm callback (``ops``). In
+general, every callback must return 0 if successful, or a negative
+error number such as ``-EINVAL``. To choose an appropriate error
+number, it is advised to check what value other parts of the kernel
+return when the same kind of request fails.
+
+The callback function takes at least the argument with :c:type:`struct
+snd_pcm_substream <snd_pcm_substream>` pointer. To retrieve the chip
+record from the given substream instance, you can use the following
+macro.
+
+::
+
+  int xxx() {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          ....
+  }
+
+The macro reads ``substream->private_data``, which is a copy of
+``pcm->private_data``. You can override the former if you need to
+assign different data records per PCM substream. For example, the
+cmi8330 driver assigns different ``private_data`` for playback and
+capture directions, because it uses two different codecs (SB- and
+AD-compatible) for different directions.
+
+PCM open callback
+~~~~~~~~~~~~~~~~~
+
+::
+
+  static int snd_xxx_open(struct snd_pcm_substream *substream);
+
+This is called when a pcm substream is opened.
+
+At least, here you have to initialize the ``runtime->hw``
+record. Typically, this is done by like this:
+
+::
+
+  static int snd_xxx_open(struct snd_pcm_substream *substream)
+  {
+          struct mychip *chip = snd_pcm_substream_chip(substream);
+          struct snd_pcm_runtime *runtime = substream->runtime;
+
+          runtime->hw = snd_mychip_playback_hw;
+          return 0;
+  }
+
+where ``snd_mychip_playback_hw`` is the pre-defined hardware
+description.
+
+You can allocate a private data in this callback, as described in
+`Private Data`_ section.
+
+If the hardware configuration needs more constraints, set the hardware
+constraints here, too. See Constraints_ for more details.
+
+close callback
+~~~~~~~~~~~~~~
+
+::
+
+  static int snd_xxx_close(struct snd_pcm_substream *substream);
+
+
+Obviously, this is called when a pcm substream is closed.
+
+Any private instance for a pcm substream allocated in the ``open``
+callback will be released here.
+
+::
+
+  static int snd_xxx_close(struct snd_pcm_substream *substream)
+  {
+          ....
+          kfree(substream->runtime->private_data);
+          ....
+  }
+
+ioctl callback
+~~~~~~~~~~~~~~
+
+This is used for any special call to pcm ioctls. But usually you can
+pass a generic ioctl callback, :c:func:`snd_pcm_lib_ioctl()`.
+
+hw_params callback
+~~~~~~~~~~~~~~~~~~~
+
+::
+
+  static int snd_xxx_hw_params(struct snd_pcm_substream *substream,
+                               struct snd_pcm_hw_params *hw_params);
+
+This is called when the hardware parameter (``hw_params``) is set up
+by the application, that is, once when the buffer size, the period
+size, the format, etc. are defined for the pcm substream.
+
+Many hardware setups should be done in this callback, including the
+allocation of buffers.
+
+Parameters to be initialized are retrieved by
+:c:func:`params_xxx()` macros. To allocate buffer, you can call a
+helper function,
+
+::
+
+  snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+
+:c:func:`snd_pcm_lib_malloc_pages()` is available only when the
+DMA buffers have been pre-allocated. See the section `Buffer Types`_
+for more details.
+
+Note that this and ``prepare`` callbacks may be called multiple times
+per initialization. For example, the OSS emulation may call these
+callbacks at each change via its ioctl.
+
+Thus, you need to be careful not to allocate the same buffers many
+times, which will lead to memory leaks! Calling the helper function
+above many times is OK. It will release the previous buffer
+automatically when it was already allocated.
+
+Another note is that this callback is non-atomic (schedulable) as
+default, i.e. when no ``nonatomic`` flag set. This is important,
+because the ``trigger`` callback is atomic (non-schedulable). That is,
+mutexes or any schedule-related functions are not available in
+``trigger`` callback. Please see the subsection Atomicity_ for
+details.
+
+hw_free callback
+~~~~~~~~~~~~~~~~~
+
+::
+
+  static int snd_xxx_hw_free(struct snd_pcm_substream *substream);
+
+This is called to release the resources allocated via
+``hw_params``. For example, releasing the buffer via
+:c:func:`snd_pcm_lib_malloc_pages()` is done by calling the
+following:
+
+::
+
+  snd_pcm_lib_free_pages(substream);
+
+This function is always called before the close callback is called.
+Also, the callback may be called multiple times, too. Keep track
+whether the resource was already released.
+
+prepare callback
+~~~~~~~~~~~~~~~~
+
+::
+
+  static int snd_xxx_prepare(struct snd_pcm_substream *substream);
+
+This callback is called when the pcm is “prepared”. You can set the
+format type, sample rate, etc. here. The difference from ``hw_params``
+is that the ``prepare`` callback will be called each time
+:c:func:`snd_pcm_prepare()` is called, i.e. when recovering after
+underruns, etc.
+
+Note that this callback is now non-atomic. You can use
+schedule-related functions safely in this callback.
+
+In this and the following callbacks, you can refer to the values via
+the runtime record, ``substream->runtime``. For example, to get the
+current rate, format or channels, access to ``runtime->rate``,
+``runtime->format`` or ``runtime->channels``, respectively. The
+physical address of the allocated buffer is set to
+``runtime->dma_area``. The buffer and period sizes are in
+``runtime->buffer_size`` and ``runtime->period_size``, respectively.
+
+Be careful that this callback will be called many times at each setup,
+too.
+
+trigger callback
+~~~~~~~~~~~~~~~~
+
+::
+
+  static int snd_xxx_trigger(struct snd_pcm_substream *substream, int cmd);
+
+This is called when the pcm is started, stopped or paused.
+
+Which action is specified in the second argument,
+``SNDRV_PCM_TRIGGER_XXX`` in ``<sound/pcm.h>``. At least, the ``START``
+and ``STOP`` commands must be defined in this callback.
+
+::
+
+  switch (cmd) {
+  case SNDRV_PCM_TRIGGER_START:
+          /* do something to start the PCM engine */
+          break;
+  case SNDRV_PCM_TRIGGER_STOP:
+          /* do something to stop the PCM engine */
+          break;
+  default:
+          return -EINVAL;
+  }
+
+When the pcm supports the pause operation (given in the info field of
+the hardware table), the ``PAUSE_PUSH`` and ``PAUSE_RELEASE`` commands
+must be handled here, too. The former is the command to pause the pcm,
+and the latter to restart the pcm again.
+
+When the pcm supports the suspend/resume operation, regardless of full
+or partial suspend/resume support, the ``SUSPEND`` and ``RESUME``
+commands must be handled, too. These commands are issued when the
+power-management status is changed. Obviously, the ``SUSPEND`` and
+``RESUME`` commands suspend and resume the pcm substream, and usually,
+they are identical to the ``STOP`` and ``START`` commands, respectively.
+See the `Power Management`_ section for details.
+
+As mentioned, this callback is atomic as default unless ``nonatomic``
+flag set, and you cannot call functions which may sleep. The
+``trigger`` callback should be as minimal as possible, just really
+triggering the DMA. The other stuff should be initialized
+``hw_params`` and ``prepare`` callbacks properly beforehand.
+
+pointer callback
+~~~~~~~~~~~~~~~~
+
+::
+
+  static snd_pcm_uframes_t snd_xxx_pointer(struct snd_pcm_substream *substream)
+
+This callback is called when the PCM middle layer inquires the current
+hardware position on the buffer. The position must be returned in
+frames, ranging from 0 to ``buffer_size - 1``. 
+
+This is called usually from the buffer-update routine in the pcm
+middle layer, which is invoked when :c:func:`snd_pcm_period_elapsed()`
+is called in the interrupt routine. Then the pcm middle layer updates
+the position and calculates the available space, and wakes up the
+sleeping poll threads, etc.
+
+This callback is also atomic as default.
+
+copy and silence callbacks
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+These callbacks are not mandatory, and can be omitted in most cases.
+These callbacks are used when the hardware buffer cannot be in the
+normal memory space. Some chips have their own buffer on the hardware
+which is not mappable. In such a case, you have to transfer the data
+manually from the memory buffer to the hardware buffer. Or, if the
+buffer is non-contiguous on both physical and virtual memory spaces,
+these callbacks must be defined, too.
+
+If these two callbacks are defined, copy and set-silence operations
+are done by them. The detailed will be described in the later section
+`Buffer and Memory Management`_.
+
+ack callback
+~~~~~~~~~~~~
+
+This callback is also not mandatory. This callback is called when the
+``appl_ptr`` is updated in read or write operations. Some drivers like
+emu10k1-fx and cs46xx need to track the current ``appl_ptr`` for the
+internal buffer, and this callback is useful only for such a purpose.
+
+This callback is atomic as default.
+
+page callback
+~~~~~~~~~~~~~
+
+This callback is optional too. This callback is used mainly for
+non-contiguous buffers. The mmap calls this callback to get the page
+address. Some examples will be explained in the later section `Buffer
+and Memory Management`_, too.
+
+PCM Interrupt Handler
+---------------------
+
+The rest of pcm stuff is the PCM interrupt handler. The role of PCM
+interrupt handler in the sound driver is to update the buffer position
+and to tell the PCM middle layer when the buffer position goes across
+the prescribed period size. To inform this, call the
+:c:func:`snd_pcm_period_elapsed()` function.
+
+There are several types of sound chips to generate the interrupts.
+
+Interrupts at the period (fragment) boundary
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the most frequently found type: the hardware generates an
+interrupt at each period boundary. In this case, you can call
+:c:func:`snd_pcm_period_elapsed()` at each interrupt.
+
+:c:func:`snd_pcm_period_elapsed()` takes the substream pointer as
+its argument. Thus, you need to keep the substream pointer accessible
+from the chip instance. For example, define ``substream`` field in the
+chip record to hold the current running substream pointer, and set the
+pointer value at ``open`` callback (and reset at ``close`` callback).
+
+If you acquire a spinlock in the interrupt handler, and the lock is used
+in other pcm callbacks, too, then you have to release the lock before
+calling :c:func:`snd_pcm_period_elapsed()`, because
+:c:func:`snd_pcm_period_elapsed()` calls other pcm callbacks
+inside.
+
+Typical code would be like:
+
+::
+
+
+      static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+      {
+              struct mychip *chip = dev_id;
+              spin_lock(&chip->lock);
+              ....
+              if (pcm_irq_invoked(chip)) {
+                      /* call updater, unlock before it */
+                      spin_unlock(&chip->lock);
+                      snd_pcm_period_elapsed(chip->substream);
+                      spin_lock(&chip->lock);
+                      /* acknowledge the interrupt if necessary */
+              }
+              ....
+              spin_unlock(&chip->lock);
+              return IRQ_HANDLED;
+      }
+
+
+
+High frequency timer interrupts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This happens when the hardware doesn't generate interrupts at the period
+boundary but issues timer interrupts at a fixed timer rate (e.g. es1968
+or ymfpci drivers). In this case, you need to check the current hardware
+position and accumulate the processed sample length at each interrupt.
+When the accumulated size exceeds the period size, call
+:c:func:`snd_pcm_period_elapsed()` and reset the accumulator.
+
+Typical code would be like the following.
+
+::
+
+
+      static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
+      {
+              struct mychip *chip = dev_id;
+              spin_lock(&chip->lock);
+              ....
+              if (pcm_irq_invoked(chip)) {
+                      unsigned int last_ptr, size;
+                      /* get the current hardware pointer (in frames) */
+                      last_ptr = get_hw_ptr(chip);
+                      /* calculate the processed frames since the
+                       * last update
+                       */
+                      if (last_ptr < chip->last_ptr)
+                              size = runtime->buffer_size + last_ptr
+                                       - chip->last_ptr;
+                      else
+                              size = last_ptr - chip->last_ptr;
+                      /* remember the last updated point */
+                      chip->last_ptr = last_ptr;
+                      /* accumulate the size */
+                      chip->size += size;
+                      /* over the period boundary? */
+                      if (chip->size >= runtime->period_size) {
+                              /* reset the accumulator */
+                              chip->size %= runtime->period_size;
+                              /* call updater */
+                              spin_unlock(&chip->lock);
+                              snd_pcm_period_elapsed(substream);
+                              spin_lock(&chip->lock);
+                      }
+                      /* acknowledge the interrupt if necessary */
+              }
+              ....
+              spin_unlock(&chip->lock);
+              return IRQ_HANDLED;
+      }
+
+
+
+On calling :c:func:`snd_pcm_period_elapsed()`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In both cases, even if more than one period are elapsed, you don't have
+to call :c:func:`snd_pcm_period_elapsed()` many times. Call only
+once. And the pcm layer will check the current hardware pointer and
+update to the latest status.
+
+Atomicity
+---------
+
+One of the most important (and thus difficult to debug) problems in
+kernel programming are race conditions. In the Linux kernel, they are
+usually avoided via spin-locks, mutexes or semaphores. In general, if a
+race condition can happen in an interrupt handler, it has to be managed
+atomically, and you have to use a spinlock to protect the critical
+session. If the critical section is not in interrupt handler code and if
+taking a relatively long time to execute is acceptable, you should use
+mutexes or semaphores instead.
+
+As already seen, some pcm callbacks are atomic and some are not. For
+example, the ``hw_params`` callback is non-atomic, while ``trigger``
+callback is atomic. This means, the latter is called already in a
+spinlock held by the PCM middle layer. Please take this atomicity into
+account when you choose a locking scheme in the callbacks.
+
+In the atomic callbacks, you cannot use functions which may call
+:c:func:`schedule()` or go to :c:func:`sleep()`. Semaphores and
+mutexes can sleep, and hence they cannot be used inside the atomic
+callbacks (e.g. ``trigger`` callback). To implement some delay in such a
+callback, please use :c:func:`udelay()` or :c:func:`mdelay()`.
+
+All three atomic callbacks (trigger, pointer, and ack) are called with
+local interrupts disabled.
+
+The recent changes in PCM core code, however, allow all PCM operations
+to be non-atomic. This assumes that the all caller sides are in
+non-atomic contexts. For example, the function
+:c:func:`snd_pcm_period_elapsed()` is called typically from the
+interrupt handler. But, if you set up the driver to use a threaded
+interrupt handler, this call can be in non-atomic context, too. In such
+a case, you can set ``nonatomic`` filed of :c:type:`struct snd_pcm
+<snd_pcm>` object after creating it. When this flag is set, mutex
+and rwsem are used internally in the PCM core instead of spin and
+rwlocks, so that you can call all PCM functions safely in a non-atomic
+context.
+
+Constraints
+-----------
+
+If your chip supports unconventional sample rates, or only the limited
+samples, you need to set a constraint for the condition.
+
+For example, in order to restrict the sample rates in the some supported
+values, use :c:func:`snd_pcm_hw_constraint_list()`. You need to
+call this function in the open callback.
+
+::
+
+      static unsigned int rates[] =
+              {4000, 10000, 22050, 44100};
+      static struct snd_pcm_hw_constraint_list constraints_rates = {
+              .count = ARRAY_SIZE(rates),
+              .list = rates,
+              .mask = 0,
+      };
+
+      static int snd_mychip_pcm_open(struct snd_pcm_substream *substream)
+      {
+              int err;
+              ....
+              err = snd_pcm_hw_constraint_list(substream->runtime, 0,
+                                               SNDRV_PCM_HW_PARAM_RATE,
+                                               &constraints_rates);
+              if (err < 0)
+                      return err;
+              ....
+      }
+
+
+
+There are many different constraints. Look at ``sound/pcm.h`` for a
+complete list. You can even define your own constraint rules. For
+example, let's suppose my_chip can manage a substream of 1 channel if
+and only if the format is ``S16_LE``, otherwise it supports any format
+specified in the :c:type:`struct snd_pcm_hardware
+<snd_pcm_hardware>` structure (or in any other
+constraint_list). You can build a rule like this:
+
+::
+
+      static int hw_rule_channels_by_format(struct snd_pcm_hw_params *params,
+                                            struct snd_pcm_hw_rule *rule)
+      {
+              struct snd_interval *c = hw_param_interval(params,
+                            SNDRV_PCM_HW_PARAM_CHANNELS);
+              struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+              struct snd_interval ch;
+
+              snd_interval_any(&ch);
+              if (f->bits[0] == SNDRV_PCM_FMTBIT_S16_LE) {
+                      ch.min = ch.max = 1;
+                      ch.integer = 1;
+                      return snd_interval_refine(c, &ch);
+              }
+              return 0;
+      }
+
+
+Then you need to call this function to add your rule:
+
+::
+
+  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+                      hw_rule_channels_by_format, NULL,
+                      SNDRV_PCM_HW_PARAM_FORMAT, -1);
+
+The rule function is called when an application sets the PCM format, and
+it refines the number of channels accordingly. But an application may
+set the number of channels before setting the format. Thus you also need
+to define the inverse rule:
+
+::
+
+      static int hw_rule_format_by_channels(struct snd_pcm_hw_params *params,
+                                            struct snd_pcm_hw_rule *rule)
+      {
+              struct snd_interval *c = hw_param_interval(params,
+                    SNDRV_PCM_HW_PARAM_CHANNELS);
+              struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+              struct snd_mask fmt;
+
+              snd_mask_any(&fmt);    /* Init the struct */
+              if (c->min < 2) {
+                      fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_LE;
+                      return snd_mask_refine(f, &fmt);
+              }
+              return 0;
+      }
+
+
+... and in the open callback:
+
+::
+
+  snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
+                      hw_rule_format_by_channels, NULL,
+                      SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+I won't give more details here, rather I would like to say, “Luke, use
+the source.”
+
+Control Interface
+=================
+
+General
+-------
+
+The control interface is used widely for many switches, sliders, etc.
+which are accessed from user-space. Its most important use is the mixer
+interface. In other words, since ALSA 0.9.x, all the mixer stuff is
+implemented on the control kernel API.
+
+ALSA has a well-defined AC97 control module. If your chip supports only
+the AC97 and nothing else, you can skip this section.
+
+The control API is defined in ``<sound/control.h>``. Include this file
+if you want to add your own controls.
+
+Definition of Controls
+----------------------
+
+To create a new control, you need to define the following three
+callbacks: ``info``, ``get`` and ``put``. Then, define a
+:c:type:`struct snd_kcontrol_new <snd_kcontrol_new>` record, such as:
+
+::
+
+
+      static struct snd_kcontrol_new my_control = {
+              .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+              .name = "PCM Playback Switch",
+              .index = 0,
+              .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+              .private_value = 0xffff,
+              .info = my_control_info,
+              .get = my_control_get,
+              .put = my_control_put
+      };
+
+
+The ``iface`` field specifies the control type,
+``SNDRV_CTL_ELEM_IFACE_XXX``, which is usually ``MIXER``. Use ``CARD``
+for global controls that are not logically part of the mixer. If the
+control is closely associated with some specific device on the sound
+card, use ``HWDEP``, ``PCM``, ``RAWMIDI``, ``TIMER``, or ``SEQUENCER``,
+and specify the device number with the ``device`` and ``subdevice``
+fields.
+
+The ``name`` is the name identifier string. Since ALSA 0.9.x, the
+control name is very important, because its role is classified from
+its name. There are pre-defined standard control names. The details
+are described in the `Control Names`_ subsection.
+
+The ``index`` field holds the index number of this control. If there
+are several different controls with the same name, they can be
+distinguished by the index number. This is the case when several
+codecs exist on the card. If the index is zero, you can omit the
+definition above. 
+
+The ``access`` field contains the access type of this control. Give
+the combination of bit masks, ``SNDRV_CTL_ELEM_ACCESS_XXX``,
+there. The details will be explained in the `Access Flags`_
+subsection.
+
+The ``private_value`` field contains an arbitrary long integer value
+for this record. When using the generic ``info``, ``get`` and ``put``
+callbacks, you can pass a value through this field. If several small
+numbers are necessary, you can combine them in bitwise. Or, it's
+possible to give a pointer (casted to unsigned long) of some record to
+this field, too. 
+
+The ``tlv`` field can be used to provide metadata about the control;
+see the `Metadata`_ subsection.
+
+The other three are `Control Callbacks`_.
+
+Control Names
+-------------
+
+There are some standards to define the control names. A control is
+usually defined from the three parts as “SOURCE DIRECTION FUNCTION”.
+
+The first, ``SOURCE``, specifies the source of the control, and is a
+string such as “Master”, “PCM”, “CD” and “Line”. There are many
+pre-defined sources.
+
+The second, ``DIRECTION``, is one of the following strings according to
+the direction of the control: “Playback”, “Capture”, “Bypass Playback”
+and “Bypass Capture”. Or, it can be omitted, meaning both playback and
+capture directions.
+
+The third, ``FUNCTION``, is one of the following strings according to
+the function of the control: “Switch”, “Volume” and “Route”.
+
+The example of control names are, thus, “Master Capture Switch” or “PCM
+Playback Volume”.
+
+There are some exceptions:
+
+Global capture and playback
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+“Capture Source”, “Capture Switch” and “Capture Volume” are used for the
+global capture (input) source, switch and volume. Similarly, “Playback
+Switch” and “Playback Volume” are used for the global output gain switch
+and volume.
+
+Tone-controls
+~~~~~~~~~~~~~
+
+tone-control switch and volumes are specified like “Tone Control - XXX”,
+e.g. “Tone Control - Switch”, “Tone Control - Bass”, “Tone Control -
+Center”.
+
+3D controls
+~~~~~~~~~~~
+
+3D-control switches and volumes are specified like “3D Control - XXX”,
+e.g. “3D Control - Switch”, “3D Control - Center”, “3D Control - Space”.
+
+Mic boost
+~~~~~~~~~
+
+Mic-boost switch is set as “Mic Boost” or “Mic Boost (6dB)”.
+
+More precise information can be found in
+``Documentation/sound/alsa/ControlNames.txt``.
+
+Access Flags
+------------
+
+The access flag is the bitmask which specifies the access type of the
+given control. The default access type is
+``SNDRV_CTL_ELEM_ACCESS_READWRITE``, which means both read and write are
+allowed to this control. When the access flag is omitted (i.e. = 0), it
+is considered as ``READWRITE`` access as default.
+
+When the control is read-only, pass ``SNDRV_CTL_ELEM_ACCESS_READ``
+instead. In this case, you don't have to define the ``put`` callback.
+Similarly, when the control is write-only (although it's a rare case),
+you can use the ``WRITE`` flag instead, and you don't need the ``get``
+callback.
+
+If the control value changes frequently (e.g. the VU meter),
+``VOLATILE`` flag should be given. This means that the control may be
+changed without `Change notification`_. Applications should poll such
+a control constantly.
+
+When the control is inactive, set the ``INACTIVE`` flag, too. There are
+``LOCK`` and ``OWNER`` flags to change the write permissions.
+
+Control Callbacks
+-----------------
+
+info callback
+~~~~~~~~~~~~~
+
+The ``info`` callback is used to get detailed information on this
+control. This must store the values of the given :c:type:`struct
+snd_ctl_elem_info <snd_ctl_elem_info>` object. For example,
+for a boolean control with a single element:
+
+::
+
+
+      static int snd_myctl_mono_info(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_info *uinfo)
+      {
+              uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+              uinfo->count = 1;
+              uinfo->value.integer.min = 0;
+              uinfo->value.integer.max = 1;
+              return 0;
+      }
+
+
+
+The ``type`` field specifies the type of the control. There are
+``BOOLEAN``, ``INTEGER``, ``ENUMERATED``, ``BYTES``, ``IEC958`` and
+``INTEGER64``. The ``count`` field specifies the number of elements in
+this control. For example, a stereo volume would have count = 2. The
+``value`` field is a union, and the values stored are depending on the
+type. The boolean and integer types are identical.
+
+The enumerated type is a bit different from others. You'll need to set
+the string for the currently given item index.
+
+::
+
+  static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_info *uinfo)
+  {
+          static char *texts[4] = {
+                  "First", "Second", "Third", "Fourth"
+          };
+          uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+          uinfo->count = 1;
+          uinfo->value.enumerated.items = 4;
+          if (uinfo->value.enumerated.item > 3)
+                  uinfo->value.enumerated.item = 3;
+          strcpy(uinfo->value.enumerated.name,
+                 texts[uinfo->value.enumerated.item]);
+          return 0;
+  }
+
+The above callback can be simplified with a helper function,
+:c:func:`snd_ctl_enum_info()`. The final code looks like below.
+(You can pass ``ARRAY_SIZE(texts)`` instead of 4 in the third argument;
+it's a matter of taste.)
+
+::
+
+  static int snd_myctl_enum_info(struct snd_kcontrol *kcontrol,
+                          struct snd_ctl_elem_info *uinfo)
+  {
+          static char *texts[4] = {
+                  "First", "Second", "Third", "Fourth"
+          };
+          return snd_ctl_enum_info(uinfo, 1, 4, texts);
+  }
+
+
+Some common info callbacks are available for your convenience:
+:c:func:`snd_ctl_boolean_mono_info()` and
+:c:func:`snd_ctl_boolean_stereo_info()`. Obviously, the former
+is an info callback for a mono channel boolean item, just like
+:c:func:`snd_myctl_mono_info()` above, and the latter is for a
+stereo channel boolean item.
+
+get callback
+~~~~~~~~~~~~
+
+This callback is used to read the current value of the control and to
+return to user-space.
+
+For example,
+
+::
+
+
+      static int snd_myctl_get(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+      {
+              struct mychip *chip = snd_kcontrol_chip(kcontrol);
+              ucontrol->value.integer.value[0] = get_some_value(chip);
+              return 0;
+      }
+
+
+
+The ``value`` field depends on the type of control as well as on the
+info callback. For example, the sb driver uses this field to store the
+register offset, the bit-shift and the bit-mask. The ``private_value``
+field is set as follows:
+
+::
+
+  .private_value = reg | (shift << 16) | (mask << 24)
+
+and is retrieved in callbacks like
+
+::
+
+  static int snd_sbmixer_get_single(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+  {
+          int reg = kcontrol->private_value & 0xff;
+          int shift = (kcontrol->private_value >> 16) & 0xff;
+          int mask = (kcontrol->private_value >> 24) & 0xff;
+          ....
+  }
+
+In the ``get`` callback, you have to fill all the elements if the
+control has more than one elements, i.e. ``count > 1``. In the example
+above, we filled only one element (``value.integer.value[0]``) since
+it's assumed as ``count = 1``.
+
+put callback
+~~~~~~~~~~~~
+
+This callback is used to write a value from user-space.
+
+For example,
+
+::
+
+
+      static int snd_myctl_put(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_value *ucontrol)
+      {
+              struct mychip *chip = snd_kcontrol_chip(kcontrol);
+              int changed = 0;
+              if (chip->current_value !=
+                   ucontrol->value.integer.value[0]) {
+                      change_current_value(chip,
+                                  ucontrol->value.integer.value[0]);
+                      changed = 1;
+              }
+              return changed;
+      }
+
+
+
+As seen above, you have to return 1 if the value is changed. If the
+value is not changed, return 0 instead. If any fatal error happens,
+return a negative error code as usual.
+
+As in the ``get`` callback, when the control has more than one
+elements, all elements must be evaluated in this callback, too.
+
+Callbacks are not atomic
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+All these three callbacks are basically not atomic.
+
+Control Constructor
+-------------------
+
+When everything is ready, finally we can create a new control. To create
+a control, there are two functions to be called,
+:c:func:`snd_ctl_new1()` and :c:func:`snd_ctl_add()`.
+
+In the simplest way, you can do like this:
+
+::
+
+  err = snd_ctl_add(card, snd_ctl_new1(&my_control, chip));
+  if (err < 0)
+          return err;
+
+where ``my_control`` is the :c:type:`struct snd_kcontrol_new
+<snd_kcontrol_new>` object defined above, and chip is the object
+pointer to be passed to kcontrol->private_data which can be referred
+to in callbacks.
+
+:c:func:`snd_ctl_new1()` allocates a new :c:type:`struct
+snd_kcontrol <snd_kcontrol>` instance, and
+:c:func:`snd_ctl_add()` assigns the given control component to the
+card.
+
+Change Notification
+-------------------
+
+If you need to change and update a control in the interrupt routine, you
+can call :c:func:`snd_ctl_notify()`. For example,
+
+::
+
+  snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, id_pointer);
+
+This function takes the card pointer, the event-mask, and the control id
+pointer for the notification. The event-mask specifies the types of
+notification, for example, in the above example, the change of control
+values is notified. The id pointer is the pointer of :c:type:`struct
+snd_ctl_elem_id <snd_ctl_elem_id>` to be notified. You can
+find some examples in ``es1938.c`` or ``es1968.c`` for hardware volume
+interrupts.
+
+Metadata
+--------
+
+To provide information about the dB values of a mixer control, use on of
+the ``DECLARE_TLV_xxx`` macros from ``<sound/tlv.h>`` to define a
+variable containing this information, set the ``tlv.p`` field to point to
+this variable, and include the ``SNDRV_CTL_ELEM_ACCESS_TLV_READ`` flag
+in the ``access`` field; like this:
+
+::
+
+  static DECLARE_TLV_DB_SCALE(db_scale_my_control, -4050, 150, 0);
+
+  static struct snd_kcontrol_new my_control = {
+          ...
+          .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                    SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+          ...
+          .tlv.p = db_scale_my_control,
+  };
+
+
+The :c:func:`DECLARE_TLV_DB_SCALE()` macro defines information
+about a mixer control where each step in the control's value changes the
+dB value by a constant dB amount. The first parameter is the name of the
+variable to be defined. The second parameter is the minimum value, in
+units of 0.01 dB. The third parameter is the step size, in units of 0.01
+dB. Set the fourth parameter to 1 if the minimum value actually mutes
+the control.
+
+The :c:func:`DECLARE_TLV_DB_LINEAR()` macro defines information
+about a mixer control where the control's value affects the output
+linearly. The first parameter is the name of the variable to be defined.
+The second parameter is the minimum value, in units of 0.01 dB. The
+third parameter is the maximum value, in units of 0.01 dB. If the
+minimum value mutes the control, set the second parameter to
+``TLV_DB_GAIN_MUTE``.
+
+API for AC97 Codec
+==================
+
+General
+-------
+
+The ALSA AC97 codec layer is a well-defined one, and you don't have to
+write much code to control it. Only low-level control routines are
+necessary. The AC97 codec API is defined in ``<sound/ac97_codec.h>``.
+
+Full Code Example
+-----------------
+
+::
+
+      struct mychip {
+              ....
+              struct snd_ac97 *ac97;
+              ....
+      };
+
+      static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
+                                                 unsigned short reg)
+      {
+              struct mychip *chip = ac97->private_data;
+              ....
+              /* read a register value here from the codec */
+              return the_register_value;
+      }
+
+      static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
+                                       unsigned short reg, unsigned short val)
+      {
+              struct mychip *chip = ac97->private_data;
+              ....
+              /* write the given register value to the codec */
+      }
+
+      static int snd_mychip_ac97(struct mychip *chip)
+      {
+              struct snd_ac97_bus *bus;
+              struct snd_ac97_template ac97;
+              int err;
+              static struct snd_ac97_bus_ops ops = {
+                      .write = snd_mychip_ac97_write,
+                      .read = snd_mychip_ac97_read,
+              };
+
+              err = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
+              if (err < 0)
+                      return err;
+              memset(&ac97, 0, sizeof(ac97));
+              ac97.private_data = chip;
+              return snd_ac97_mixer(bus, &ac97, &chip->ac97);
+      }
+
+
+AC97 Constructor
+----------------
+
+To create an ac97 instance, first call :c:func:`snd_ac97_bus()`
+with an ``ac97_bus_ops_t`` record with callback functions.
+
+::
+
+  struct snd_ac97_bus *bus;
+  static struct snd_ac97_bus_ops ops = {
+        .write = snd_mychip_ac97_write,
+        .read = snd_mychip_ac97_read,
+  };
+
+  snd_ac97_bus(card, 0, &ops, NULL, &pbus);
+
+The bus record is shared among all belonging ac97 instances.
+
+And then call :c:func:`snd_ac97_mixer()` with an :c:type:`struct
+snd_ac97_template <snd_ac97_template>` record together with
+the bus pointer created above.
+
+::
+
+  struct snd_ac97_template ac97;
+  int err;
+
+  memset(&ac97, 0, sizeof(ac97));
+  ac97.private_data = chip;
+  snd_ac97_mixer(bus, &ac97, &chip->ac97);
+
+where chip->ac97 is a pointer to a newly created ``ac97_t``
+instance. In this case, the chip pointer is set as the private data,
+so that the read/write callback functions can refer to this chip
+instance. This instance is not necessarily stored in the chip
+record. If you need to change the register values from the driver, or
+need the suspend/resume of ac97 codecs, keep this pointer to pass to
+the corresponding functions.
+
+AC97 Callbacks
+--------------
+
+The standard callbacks are ``read`` and ``write``. Obviously they
+correspond to the functions for read and write accesses to the
+hardware low-level codes.
+
+The ``read`` callback returns the register value specified in the
+argument.
+
+::
+
+  static unsigned short snd_mychip_ac97_read(struct snd_ac97 *ac97,
+                                             unsigned short reg)
+  {
+          struct mychip *chip = ac97->private_data;
+          ....
+          return the_register_value;
+  }
+
+Here, the chip can be cast from ``ac97->private_data``.
+
+Meanwhile, the ``write`` callback is used to set the register
+value
+
+::
+
+  static void snd_mychip_ac97_write(struct snd_ac97 *ac97,
+                       unsigned short reg, unsigned short val)
+
+
+These callbacks are non-atomic like the control API callbacks.
+
+There are also other callbacks: ``reset``, ``wait`` and ``init``.
+
+The ``reset`` callback is used to reset the codec. If the chip
+requires a special kind of reset, you can define this callback.
+
+The ``wait`` callback is used to add some waiting time in the standard
+initialization of the codec. If the chip requires the extra waiting
+time, define this callback.
+
+The ``init`` callback is used for additional initialization of the
+codec.
+
+Updating Registers in The Driver
+--------------------------------
+
+If you need to access to the codec from the driver, you can call the
+following functions: :c:func:`snd_ac97_write()`,
+:c:func:`snd_ac97_read()`, :c:func:`snd_ac97_update()` and
+:c:func:`snd_ac97_update_bits()`.
+
+Both :c:func:`snd_ac97_write()` and
+:c:func:`snd_ac97_update()` functions are used to set a value to
+the given register (``AC97_XXX``). The difference between them is that
+:c:func:`snd_ac97_update()` doesn't write a value if the given
+value has been already set, while :c:func:`snd_ac97_write()`
+always rewrites the value.
+
+::
+
+  snd_ac97_write(ac97, AC97_MASTER, 0x8080);
+  snd_ac97_update(ac97, AC97_MASTER, 0x8080);
+
+:c:func:`snd_ac97_read()` is used to read the value of the given
+register. For example,
+
+::
+
+  value = snd_ac97_read(ac97, AC97_MASTER);
+
+:c:func:`snd_ac97_update_bits()` is used to update some bits in
+the given register.
+
+::
+
+  snd_ac97_update_bits(ac97, reg, mask, value);
+
+Also, there is a function to change the sample rate (of a given register
+such as ``AC97_PCM_FRONT_DAC_RATE``) when VRA or DRA is supported by the
+codec: :c:func:`snd_ac97_set_rate()`.
+
+::
+
+  snd_ac97_set_rate(ac97, AC97_PCM_FRONT_DAC_RATE, 44100);
+
+
+The following registers are available to set the rate:
+``AC97_PCM_MIC_ADC_RATE``, ``AC97_PCM_FRONT_DAC_RATE``,
+``AC97_PCM_LR_ADC_RATE``, ``AC97_SPDIF``. When ``AC97_SPDIF`` is
+specified, the register is not really changed but the corresponding
+IEC958 status bits will be updated.
+
+Clock Adjustment
+----------------
+
+In some chips, the clock of the codec isn't 48000 but using a PCI clock
+(to save a quartz!). In this case, change the field ``bus->clock`` to
+the corresponding value. For example, intel8x0 and es1968 drivers have
+their own function to read from the clock.
+
+Proc Files
+----------
+
+The ALSA AC97 interface will create a proc file such as
+``/proc/asound/card0/codec97#0/ac97#0-0`` and ``ac97#0-0+regs``. You
+can refer to these files to see the current status and registers of
+the codec.
+
+Multiple Codecs
+---------------
+
+When there are several codecs on the same card, you need to call
+:c:func:`snd_ac97_mixer()` multiple times with ``ac97.num=1`` or
+greater. The ``num`` field specifies the codec number.
+
+If you set up multiple codecs, you either need to write different
+callbacks for each codec or check ``ac97->num`` in the callback
+routines.
+
+MIDI (MPU401-UART) Interface
+============================
+
+General
+-------
+
+Many soundcards have built-in MIDI (MPU401-UART) interfaces. When the
+soundcard supports the standard MPU401-UART interface, most likely you
+can use the ALSA MPU401-UART API. The MPU401-UART API is defined in
+``<sound/mpu401.h>``.
+
+Some soundchips have a similar but slightly different implementation of
+mpu401 stuff. For example, emu10k1 has its own mpu401 routines.
+
+MIDI Constructor
+----------------
+
+To create a rawmidi object, call :c:func:`snd_mpu401_uart_new()`.
+
+::
+
+  struct snd_rawmidi *rmidi;
+  snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
+                      irq, &rmidi);
+
+
+The first argument is the card pointer, and the second is the index of
+this component. You can create up to 8 rawmidi devices.
+
+The third argument is the type of the hardware, ``MPU401_HW_XXX``. If
+it's not a special one, you can use ``MPU401_HW_MPU401``.
+
+The 4th argument is the I/O port address. Many backward-compatible
+MPU401 have an I/O port such as 0x330. Or, it might be a part of its own
+PCI I/O region. It depends on the chip design.
+
+The 5th argument is a bitflag for additional information. When the I/O
+port address above is part of the PCI I/O region, the MPU401 I/O port
+might have been already allocated (reserved) by the driver itself. In
+such a case, pass a bit flag ``MPU401_INFO_INTEGRATED``, and the
+mpu401-uart layer will allocate the I/O ports by itself.
+
+When the controller supports only the input or output MIDI stream, pass
+the ``MPU401_INFO_INPUT`` or ``MPU401_INFO_OUTPUT`` bitflag,
+respectively. Then the rawmidi instance is created as a single stream.
+
+``MPU401_INFO_MMIO`` bitflag is used to change the access method to MMIO
+(via readb and writeb) instead of iob and outb. In this case, you have
+to pass the iomapped address to :c:func:`snd_mpu401_uart_new()`.
+
+When ``MPU401_INFO_TX_IRQ`` is set, the output stream isn't checked in
+the default interrupt handler. The driver needs to call
+:c:func:`snd_mpu401_uart_interrupt_tx()` by itself to start
+processing the output stream in the irq handler.
+
+If the MPU-401 interface shares its interrupt with the other logical
+devices on the card, set ``MPU401_INFO_IRQ_HOOK`` (see
+`below <#MIDI-Interrupt-Handler>`__).
+
+Usually, the port address corresponds to the command port and port + 1
+corresponds to the data port. If not, you may change the ``cport``
+field of :c:type:`struct snd_mpu401 <snd_mpu401>` manually afterward.
+However, :c:type:`struct snd_mpu401 <snd_mpu401>` pointer is
+not returned explicitly by :c:func:`snd_mpu401_uart_new()`. You
+need to cast ``rmidi->private_data`` to :c:type:`struct snd_mpu401
+<snd_mpu401>` explicitly,
+
+::
+
+  struct snd_mpu401 *mpu;
+  mpu = rmidi->private_data;
+
+and reset the ``cport`` as you like:
+
+::
+
+  mpu->cport = my_own_control_port;
+
+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.
+
+MIDI Interrupt Handler
+----------------------
+
+When the interrupt is allocated in
+:c:func:`snd_mpu401_uart_new()`, 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
+``MPU401_INFO_IRQ_HOOK``, and call
+:c:func:`snd_mpu401_uart_interrupt()` explicitly from your own
+interrupt handler when it has determined that a UART interrupt has
+occurred.
+
+In this case, you need to pass the private_data of the returned rawmidi
+object from :c:func:`snd_mpu401_uart_new()` as the second
+argument of :c:func:`snd_mpu401_uart_interrupt()`.
+
+::
+
+  snd_mpu401_uart_interrupt(irq, rmidi->private_data, regs);
+
+
+RawMIDI Interface
+=================
+
+Overview
+--------
+
+The raw MIDI interface is used for hardware MIDI ports that can be
+accessed as a byte stream. It is not used for synthesizer chips that do
+not directly understand MIDI.
+
+ALSA handles file and buffer management. All you have to do is to write
+some code to move data between the buffer and the hardware.
+
+The rawmidi API is defined in ``<sound/rawmidi.h>``.
+
+RawMIDI Constructor
+-------------------
+
+To create a rawmidi device, call the :c:func:`snd_rawmidi_new()`
+function:
+
+::
+
+  struct snd_rawmidi *rmidi;
+  err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
+  if (err < 0)
+          return err;
+  rmidi->private_data = chip;
+  strcpy(rmidi->name, "My MIDI");
+  rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+                      SNDRV_RAWMIDI_INFO_INPUT |
+                      SNDRV_RAWMIDI_INFO_DUPLEX;
+
+The first argument is the card pointer, the second argument is the ID
+string.
+
+The third argument is the index of this component. You can create up to
+8 rawmidi devices.
+
+The fourth and fifth arguments are the number of output and input
+substreams, respectively, of this device (a substream is the equivalent
+of a MIDI port).
+
+Set the ``info_flags`` field to specify the capabilities of the
+device. Set ``SNDRV_RAWMIDI_INFO_OUTPUT`` if there is at least one
+output port, ``SNDRV_RAWMIDI_INFO_INPUT`` if there is at least one
+input port, and ``SNDRV_RAWMIDI_INFO_DUPLEX`` if the device can handle
+output and input at the same time.
+
+After the rawmidi device is created, you need to set the operators
+(callbacks) for each substream. There are helper functions to set the
+operators for all the substreams of a device:
+
+::
+
+  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
+  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
+
+The operators are usually defined like this:
+
+::
+
+  static struct snd_rawmidi_ops snd_mymidi_output_ops = {
+          .open =    snd_mymidi_output_open,
+          .close =   snd_mymidi_output_close,
+          .trigger = snd_mymidi_output_trigger,
+  };
+
+These callbacks are explained in the `RawMIDI Callbacks`_ section.
+
+If there are more than one substream, you should give a unique name to
+each of them:
+
+::
+
+  struct snd_rawmidi_substream *substream;
+  list_for_each_entry(substream,
+                      &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
+                      list {
+          sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
+  }
+  /* same for SNDRV_RAWMIDI_STREAM_INPUT */
+
+RawMIDI Callbacks
+-----------------
+
+In all the callbacks, the private data that you've set for the rawmidi
+device can be accessed as ``substream->rmidi->private_data``.
+
+If there is more than one port, your callbacks can determine the port
+index from the struct snd_rawmidi_substream data passed to each
+callback:
+
+::
+
+  struct snd_rawmidi_substream *substream;
+  int index = substream->number;
+
+RawMIDI open callback
+~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+      static int snd_xxx_open(struct snd_rawmidi_substream *substream);
+
+
+This is called when a substream is opened. You can initialize the
+hardware here, but you shouldn't start transmitting/receiving data yet.
+
+RawMIDI close callback
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+      static int snd_xxx_close(struct snd_rawmidi_substream *substream);
+
+Guess what.
+
+The ``open`` and ``close`` callbacks of a rawmidi device are
+serialized with a mutex, and can sleep.
+
+Rawmidi trigger callback for output substreams
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+      static void snd_xxx_output_trigger(struct snd_rawmidi_substream *substream, int up);
+
+
+This is called with a nonzero ``up`` parameter when there is some data
+in the substream buffer that must be transmitted.
+
+To read data from the buffer, call
+:c:func:`snd_rawmidi_transmit_peek()`. It will return the number
+of bytes that have been read; this will be less than the number of bytes
+requested when there are no more data in the buffer. After the data have
+been transmitted successfully, call
+:c:func:`snd_rawmidi_transmit_ack()` to remove the data from the
+substream buffer:
+
+::
+
+  unsigned char data;
+  while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
+          if (snd_mychip_try_to_transmit(data))
+                  snd_rawmidi_transmit_ack(substream, 1);
+          else
+                  break; /* hardware FIFO full */
+  }
+
+If you know beforehand that the hardware will accept data, you can use
+the :c:func:`snd_rawmidi_transmit()` function which reads some
+data and removes them from the buffer at once:
+
+::
+
+  while (snd_mychip_transmit_possible()) {
+          unsigned char data;
+          if (snd_rawmidi_transmit(substream, &data, 1) != 1)
+                  break; /* no more data */
+          snd_mychip_transmit(data);
+  }
+
+If you know beforehand how many bytes you can accept, you can use a
+buffer size greater than one with the
+:c:func:`snd_rawmidi_transmit\*()` functions.
+
+The ``trigger`` callback must not sleep. If the hardware FIFO is full
+before the substream buffer has been emptied, you have to continue
+transmitting data later, either in an interrupt handler, or with a
+timer if the hardware doesn't have a MIDI transmit interrupt.
+
+The ``trigger`` callback is called with a zero ``up`` parameter when
+the transmission of data should be aborted.
+
+RawMIDI trigger callback for input substreams
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+      static void snd_xxx_input_trigger(struct snd_rawmidi_substream *substream, int up);
+
+
+This is called with a nonzero ``up`` parameter to enable receiving data,
+or with a zero ``up`` parameter do disable receiving data.
+
+The ``trigger`` callback must not sleep; the actual reading of data
+from the device is usually done in an interrupt handler.
+
+When data reception is enabled, your interrupt handler should call
+:c:func:`snd_rawmidi_receive()` for all received data:
+
+::
+
+  void snd_mychip_midi_interrupt(...)
+  {
+          while (mychip_midi_available()) {
+                  unsigned char data;
+                  data = mychip_midi_read();
+                  snd_rawmidi_receive(substream, &data, 1);
+          }
+  }
+
+
+drain callback
+~~~~~~~~~~~~~~
+
+::
+
+      static void snd_xxx_drain(struct snd_rawmidi_substream *substream);
+
+
+This is only used with output substreams. This function should wait
+until all data read from the substream buffer have been transmitted.
+This ensures that the device can be closed and the driver unloaded
+without losing data.
+
+This callback is optional. If you do not set ``drain`` in the struct
+snd_rawmidi_ops structure, ALSA will simply wait for 50 milliseconds
+instead.
+
+Miscellaneous Devices
+=====================
+
+FM OPL3
+-------
+
+The FM OPL3 is still used in many chips (mainly for backward
+compatibility). ALSA has a nice OPL3 FM control layer, too. The OPL3 API
+is defined in ``<sound/opl3.h>``.
+
+FM registers can be directly accessed through the direct-FM API, defined
+in ``<sound/asound_fm.h>``. In ALSA native mode, FM registers are
+accessed through the Hardware-Dependent Device direct-FM extension API,
+whereas in OSS compatible mode, FM registers can be accessed with the
+OSS direct-FM compatible API in ``/dev/dmfmX`` device.
+
+To create the OPL3 component, you have two functions to call. The first
+one is a constructor for the ``opl3_t`` instance.
+
+::
+
+  struct snd_opl3 *opl3;
+  snd_opl3_create(card, lport, rport, OPL3_HW_OPL3_XXX,
+                  integrated, &opl3);
+
+The first argument is the card pointer, the second one is the left port
+address, and the third is the right port address. In most cases, the
+right port is placed at the left port + 2.
+
+The fourth argument is the hardware type.
+
+When the left and right ports have been already allocated by the card
+driver, pass non-zero to the fifth argument (``integrated``). Otherwise,
+the opl3 module will allocate the specified ports by itself.
+
+When the accessing the hardware requires special method instead of the
+standard I/O access, you can create opl3 instance separately with
+:c:func:`snd_opl3_new()`.
+
+::
+
+  struct snd_opl3 *opl3;
+  snd_opl3_new(card, OPL3_HW_OPL3_XXX, &opl3);
+
+Then set ``command``, ``private_data`` and ``private_free`` for the
+private access function, the private data and the destructor. The
+``l_port`` and ``r_port`` are not necessarily set. Only the command
+must be set properly. You can retrieve the data from the
+``opl3->private_data`` field. 
+
+After creating the opl3 instance via :c:func:`snd_opl3_new()`,
+call :c:func:`snd_opl3_init()` to initialize the chip to the
+proper state. Note that :c:func:`snd_opl3_create()` always calls
+it internally.
+
+If the opl3 instance is created successfully, then create a hwdep device
+for this opl3.
+
+::
+
+  struct snd_hwdep *opl3hwdep;
+  snd_opl3_hwdep_new(opl3, 0, 1, &opl3hwdep);
+
+The first argument is the ``opl3_t`` instance you created, and the
+second is the index number, usually 0.
+
+The third argument is the index-offset for the sequencer client assigned
+to the OPL3 port. When there is an MPU401-UART, give 1 for here (UART
+always takes 0).
+
+Hardware-Dependent Devices
+--------------------------
+
+Some chips need user-space access for special controls or for loading
+the micro code. In such a case, you can create a hwdep
+(hardware-dependent) device. The hwdep API is defined in
+``<sound/hwdep.h>``. You can find examples in opl3 driver or
+``isa/sb/sb16_csp.c``.
+
+The creation of the ``hwdep`` instance is done via
+:c:func:`snd_hwdep_new()`.
+
+::
+
+  struct snd_hwdep *hw;
+  snd_hwdep_new(card, "My HWDEP", 0, &hw);
+
+where the third argument is the index number.
+
+You can then pass any pointer value to the ``private_data``. If you
+assign a private data, you should define the destructor, too. The
+destructor function is set in the ``private_free`` field.
+
+::
+
+  struct mydata *p = kmalloc(sizeof(*p), GFP_KERNEL);
+  hw->private_data = p;
+  hw->private_free = mydata_free;
+
+and the implementation of the destructor would be:
+
+::
+
+  static void mydata_free(struct snd_hwdep *hw)
+  {
+          struct mydata *p = hw->private_data;
+          kfree(p);
+  }
+
+The arbitrary file operations can be defined for this instance. The file
+operators are defined in the ``ops`` table. For example, assume that
+this chip needs an ioctl.
+
+::
+
+  hw->ops.open = mydata_open;
+  hw->ops.ioctl = mydata_ioctl;
+  hw->ops.release = mydata_release;
+
+And implement the callback functions as you like.
+
+IEC958 (S/PDIF)
+---------------
+
+Usually the controls for IEC958 devices are implemented via the control
+interface. There is a macro to compose a name string for IEC958
+controls, :c:func:`SNDRV_CTL_NAME_IEC958()` defined in
+``<include/asound.h>``.
+
+There are some standard controls for IEC958 status bits. These controls
+use the type ``SNDRV_CTL_ELEM_TYPE_IEC958``, and the size of element is
+fixed as 4 bytes array (value.iec958.status[x]). For the ``info``
+callback, you don't specify the value field for this type (the count
+field must be set, though).
+
+“IEC958 Playback Con Mask” is used to return the bit-mask for the IEC958
+status bits of consumer mode. Similarly, “IEC958 Playback Pro Mask”
+returns the bitmask for professional mode. They are read-only controls,
+and are defined as MIXER controls (iface =
+``SNDRV_CTL_ELEM_IFACE_MIXER``).
+
+Meanwhile, “IEC958 Playback Default” control is defined for getting and
+setting the current default IEC958 bits. Note that this one is usually
+defined as a PCM control (iface = ``SNDRV_CTL_ELEM_IFACE_PCM``),
+although in some places it's defined as a MIXER control.
+
+In addition, you can define the control switches to enable/disable or to
+set the raw bit mode. The implementation will depend on the chip, but
+the control should be named as “IEC958 xxx”, preferably using the
+:c:func:`SNDRV_CTL_NAME_IEC958()` macro.
+
+You can find several cases, for example, ``pci/emu10k1``,
+``pci/ice1712``, or ``pci/cmipci.c``.
+
+Buffer and Memory Management
+============================
+
+Buffer Types
+------------
+
+ALSA provides several different buffer allocation functions depending on
+the bus and the architecture. All these have a consistent API. The
+allocation of physically-contiguous pages is done via
+:c:func:`snd_malloc_xxx_pages()` function, where xxx is the bus
+type.
+
+The allocation of pages with fallback is
+:c:func:`snd_malloc_xxx_pages_fallback()`. This function tries
+to allocate the specified pages but if the pages are not available, it
+tries to reduce the page sizes until enough space is found.
+
+The release the pages, call :c:func:`snd_free_xxx_pages()`
+function.
+
+Usually, ALSA drivers try to allocate and reserve a large contiguous
+physical space at the time the module is loaded for the later use. This
+is called “pre-allocation”. As already written, you can call the
+following function at pcm instance construction time (in the case of PCI
+bus).
+
+::
+
+  snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                        snd_dma_pci_data(pci), size, max);
+
+where ``size`` is the byte size to be pre-allocated and the ``max`` is
+the maximum size to be changed via the ``prealloc`` proc file. The
+allocator will try to get an area as large as possible within the
+given size.
+
+The second argument (type) and the third argument (device pointer) are
+dependent on the bus. In the case of the ISA bus, pass
+:c:func:`snd_dma_isa_data()` as the third argument with
+``SNDRV_DMA_TYPE_DEV`` type. For the continuous buffer unrelated to the
+bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type and the
+``snd_dma_continuous_data(GFP_KERNEL)`` device pointer, where
+``GFP_KERNEL`` is the kernel allocation flag to use. For the PCI
+scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with
+``snd_dma_pci_data(pci)`` (see the `Non-Contiguous Buffers`_
+section).
+
+Once the buffer is pre-allocated, you can use the allocator in the
+``hw_params`` callback:
+
+::
+
+  snd_pcm_lib_malloc_pages(substream, size);
+
+Note that you have to pre-allocate to use this function.
+
+External Hardware Buffers
+-------------------------
+
+Some chips have their own hardware buffers and the DMA transfer from the
+host memory is not available. In such a case, you need to either 1)
+copy/set the audio data directly to the external hardware buffer, or 2)
+make an intermediate buffer and copy/set the data from it to the
+external hardware buffer in interrupts (or in tasklets, preferably).
+
+The first case works fine if the external hardware buffer is large
+enough. This method doesn't need any extra buffers and thus is more
+effective. You need to define the ``copy`` and ``silence`` callbacks
+for the data transfer. However, there is a drawback: it cannot be
+mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM.
+
+The second case allows for mmap on the buffer, although you have to
+handle an interrupt or a tasklet to transfer the data from the
+intermediate buffer to the hardware buffer. You can find an example in
+the vxpocket driver.
+
+Another case is when the chip uses a PCI memory-map region for the
+buffer instead of the host memory. In this case, mmap is available only
+on certain architectures like the Intel one. In non-mmap mode, the data
+cannot be transferred as in the normal way. Thus you need to define the
+``copy`` and ``silence`` callbacks as well, as in the cases above. The
+examples are found in ``rme32.c`` and ``rme96.c``.
+
+The implementation of the ``copy`` and ``silence`` callbacks depends
+upon whether the hardware supports interleaved or non-interleaved
+samples. The ``copy`` callback is defined like below, a bit
+differently depending whether the direction is playback or capture:
+
+::
+
+  static int playback_copy(struct snd_pcm_substream *substream, int channel,
+               snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
+  static int capture_copy(struct snd_pcm_substream *substream, int channel,
+               snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
+
+In the case of interleaved samples, the second argument (``channel``) is
+not used. The third argument (``pos``) points the current position
+offset in frames.
+
+The meaning of the fourth argument is different between playback and
+capture. For playback, it holds the source data pointer, and for
+capture, it's the destination data pointer.
+
+The last argument is the number of frames to be copied.
+
+What you have to do in this callback is again different between playback
+and capture directions. In the playback case, you copy the given amount
+of data (``count``) at the specified pointer (``src``) to the specified
+offset (``pos``) on the hardware buffer. When coded like memcpy-like
+way, the copy would be like:
+
+::
+
+  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
+            frames_to_bytes(runtime, count));
+
+For the capture direction, you copy the given amount of data (``count``)
+at the specified offset (``pos``) on the hardware buffer to the
+specified pointer (``dst``).
+
+::
+
+  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
+            frames_to_bytes(runtime, count));
+
+Note that both the position and the amount of data are given in frames.
+
+In the case of non-interleaved samples, the implementation will be a bit
+more complicated.
+
+You need to check the channel argument, and if it's -1, copy the whole
+channels. Otherwise, you have to copy only the specified channel. Please
+check ``isa/gus/gus_pcm.c`` as an example.
+
+The ``silence`` callback is also implemented in a similar way
+
+::
+
+  static int silence(struct snd_pcm_substream *substream, int channel,
+                     snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
+
+The meanings of arguments are the same as in the ``copy`` callback,
+although there is no ``src/dst`` argument. In the case of interleaved
+samples, the channel argument has no meaning, as well as on ``copy``
+callback.
+
+The role of ``silence`` callback is to set the given amount
+(``count``) of silence data at the specified offset (``pos``) on the
+hardware buffer. Suppose that the data format is signed (that is, the
+silent-data is 0), and the implementation using a memset-like function
+would be like: 
+
+::
+
+  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), 0,
+            frames_to_bytes(runtime, count));
+
+In the case of non-interleaved samples, again, the implementation
+becomes a bit more complicated. See, for example, ``isa/gus/gus_pcm.c``.
+
+Non-Contiguous Buffers
+----------------------
+
+If your hardware supports the page table as in emu10k1 or the buffer
+descriptors as in via82xx, you can use the scatter-gather (SG) DMA. ALSA
+provides an interface for handling SG-buffers. The API is provided in
+``<sound/pcm.h>``.
+
+For creating the SG-buffer handler, call
+:c:func:`snd_pcm_lib_preallocate_pages()` or
+:c:func:`snd_pcm_lib_preallocate_pages_for_all()` with
+``SNDRV_DMA_TYPE_DEV_SG`` in the PCM constructor like other PCI
+pre-allocator. You need to pass ``snd_dma_pci_data(pci)``, where pci is
+the :c:type:`struct pci_dev <pci_dev>` pointer of the chip as
+well. The ``struct snd_sg_buf`` instance is created as
+``substream->dma_private``. You can cast the pointer like:
+
+::
+
+  struct snd_sg_buf *sgbuf = (struct snd_sg_buf *)substream->dma_private;
+
+Then call :c:func:`snd_pcm_lib_malloc_pages()` in the ``hw_params``
+callback as well as in the case of normal PCI buffer. The SG-buffer
+handler will allocate the non-contiguous kernel pages of the given size
+and map them onto the virtually contiguous memory. The virtual pointer
+is addressed in runtime->dma_area. The physical address
+(``runtime->dma_addr``) is set to zero, because the buffer is
+physically non-contiguous. The physical address table is set up in
+``sgbuf->table``. You can get the physical address at a certain offset
+via :c:func:`snd_pcm_sgbuf_get_addr()`.
+
+When a SG-handler is used, you need to set
+:c:func:`snd_pcm_sgbuf_ops_page()` as the ``page`` callback. (See
+`page callback`_ section.)
+
+To release the data, call :c:func:`snd_pcm_lib_free_pages()` in
+the ``hw_free`` callback as usual.
+
+Vmalloc'ed Buffers
+------------------
+
+It's possible to use a buffer allocated via :c:func:`vmalloc()`, for
+example, for an intermediate buffer. Since the allocated pages are not
+contiguous, you need to set the ``page`` callback to obtain the physical
+address at every offset.
+
+The implementation of ``page`` callback would be like this:
+
+::
+
+  #include <linux/vmalloc.h>
+
+  /* get the physical page pointer on the given offset */
+  static struct page *mychip_page(struct snd_pcm_substream *substream,
+                                  unsigned long offset)
+  {
+          void *pageptr = substream->runtime->dma_area + offset;
+          return vmalloc_to_page(pageptr);
+  }
+
+Proc Interface
+==============
+
+ALSA provides an easy interface for procfs. The proc files are very
+useful for debugging. I recommend you set up proc files if you write a
+driver and want to get a running status or register dumps. The API is
+found in ``<sound/info.h>``.
+
+To create a proc file, call :c:func:`snd_card_proc_new()`.
+
+::
+
+  struct snd_info_entry *entry;
+  int err = snd_card_proc_new(card, "my-file", &entry);
+
+where the second argument specifies the name of the proc file to be
+created. The above example will create a file ``my-file`` under the
+card directory, e.g. ``/proc/asound/card0/my-file``.
+
+Like other components, the proc entry created via
+:c:func:`snd_card_proc_new()` will be registered and released
+automatically in the card registration and release functions.
+
+When the creation is successful, the function stores a new instance in
+the pointer given in the third argument. It is initialized as a text
+proc file for read only. To use this proc file as a read-only text file
+as it is, set the read callback with a private data via
+:c:func:`snd_info_set_text_ops()`.
+
+::
+
+  snd_info_set_text_ops(entry, chip, my_proc_read);
+
+where the second argument (``chip``) is the private data to be used in
+the callbacks. The third parameter specifies the read buffer size and
+the fourth (``my_proc_read``) is the callback function, which is
+defined like
+
+::
+
+  static void my_proc_read(struct snd_info_entry *entry,
+                           struct snd_info_buffer *buffer);
+
+In the read callback, use :c:func:`snd_iprintf()` for output
+strings, which works just like normal :c:func:`printf()`. For
+example,
+
+::
+
+  static void my_proc_read(struct snd_info_entry *entry,
+                           struct snd_info_buffer *buffer)
+  {
+          struct my_chip *chip = entry->private_data;
+
+          snd_iprintf(buffer, "This is my chip!\n");
+          snd_iprintf(buffer, "Port = %ld\n", chip->port);
+  }
+
+The file permissions can be changed afterwards. As default, it's set as
+read only for all users. If you want to add write permission for the
+user (root as default), do as follows:
+
+::
+
+ entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
+
+and set the write buffer size and the callback
+
+::
+
+  entry->c.text.write = my_proc_write;
+
+For the write callback, you can use :c:func:`snd_info_get_line()`
+to get a text line, and :c:func:`snd_info_get_str()` to retrieve
+a string from the line. Some examples are found in
+``core/oss/mixer_oss.c``, core/oss/and ``pcm_oss.c``.
+
+For a raw-data proc-file, set the attributes as follows:
+
+::
+
+  static struct snd_info_entry_ops my_file_io_ops = {
+          .read = my_file_io_read,
+  };
+
+  entry->content = SNDRV_INFO_CONTENT_DATA;
+  entry->private_data = chip;
+  entry->c.ops = &my_file_io_ops;
+  entry->size = 4096;
+  entry->mode = S_IFREG | S_IRUGO;
+
+For the raw data, ``size`` field must be set properly. This specifies
+the maximum size of the proc file access.
+
+The read/write callbacks of raw mode are more direct than the text mode.
+You need to use a low-level I/O functions such as
+:c:func:`copy_from/to_user()` to transfer the data.
+
+::
+
+  static ssize_t my_file_io_read(struct snd_info_entry *entry,
+                              void *file_private_data,
+                              struct file *file,
+                              char *buf,
+                              size_t count,
+                              loff_t pos)
+  {
+          if (copy_to_user(buf, local_data + pos, count))
+                  return -EFAULT;
+          return count;
+  }
+
+If the size of the info entry has been set up properly, ``count`` and
+``pos`` are guaranteed to fit within 0 and the given size. You don't
+have to check the range in the callbacks unless any other condition is
+required.
+
+Power Management
+================
+
+If the chip is supposed to work with suspend/resume functions, you need
+to add power-management code to the driver. The additional code for
+power-management should be ifdef-ed with ``CONFIG_PM``.
+
+If the driver *fully* supports suspend/resume that is, the device can be
+properly resumed to its state when suspend was called, you can set the
+``SNDRV_PCM_INFO_RESUME`` flag in the pcm info field. Usually, this is
+possible when the registers of the chip can be safely saved and restored
+to RAM. If this is set, the trigger callback is called with
+``SNDRV_PCM_TRIGGER_RESUME`` after the resume callback completes.
+
+Even if the driver doesn't support PM fully but partial suspend/resume
+is still possible, it's still worthy to implement suspend/resume
+callbacks. In such a case, applications would reset the status by
+calling :c:func:`snd_pcm_prepare()` and restart the stream
+appropriately. Hence, you can define suspend/resume callbacks below but
+don't set ``SNDRV_PCM_INFO_RESUME`` info flag to the PCM.
+
+Note that the trigger with SUSPEND can always be called when
+:c:func:`snd_pcm_suspend_all()` is called, regardless of the
+``SNDRV_PCM_INFO_RESUME`` flag. The ``RESUME`` flag affects only the
+behavior of :c:func:`snd_pcm_resume()`. (Thus, in theory,
+``SNDRV_PCM_TRIGGER_RESUME`` isn't needed to be handled in the trigger
+callback when no ``SNDRV_PCM_INFO_RESUME`` flag is set. But, it's better
+to keep it for compatibility reasons.)
+
+In the earlier version of ALSA drivers, a common power-management layer
+was provided, but it has been removed. The driver needs to define the
+suspend/resume hooks according to the bus the device is connected to. In
+the case of PCI drivers, the callbacks look like below:
+
+::
+
+  #ifdef CONFIG_PM
+  static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
+  {
+          .... /* do things for suspend */
+          return 0;
+  }
+  static int snd_my_resume(struct pci_dev *pci)
+  {
+          .... /* do things for suspend */
+          return 0;
+  }
+  #endif
+
+The scheme of the real suspend job is as follows.
+
+1. Retrieve the card and the chip data.
+
+2. Call :c:func:`snd_power_change_state()` with
+   ``SNDRV_CTL_POWER_D3hot`` to change the power status.
+
+3. Call :c:func:`snd_pcm_suspend_all()` to suspend the running
+   PCM streams.
+
+4. If AC97 codecs are used, call :c:func:`snd_ac97_suspend()` for
+   each codec.
+
+5. Save the register values if necessary.
+
+6. Stop the hardware if necessary.
+
+7. Disable the PCI device by calling
+   :c:func:`pci_disable_device()`. Then, call
+   :c:func:`pci_save_state()` at last.
+
+A typical code would be like:
+
+::
+
+  static int mychip_suspend(struct pci_dev *pci, pm_message_t state)
+  {
+          /* (1) */
+          struct snd_card *card = pci_get_drvdata(pci);
+          struct mychip *chip = card->private_data;
+          /* (2) */
+          snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+          /* (3) */
+          snd_pcm_suspend_all(chip->pcm);
+          /* (4) */
+          snd_ac97_suspend(chip->ac97);
+          /* (5) */
+          snd_mychip_save_registers(chip);
+          /* (6) */
+          snd_mychip_stop_hardware(chip);
+          /* (7) */
+          pci_disable_device(pci);
+          pci_save_state(pci);
+          return 0;
+  }
+
+
+The scheme of the real resume job is as follows.
+
+1. Retrieve the card and the chip data.
+
+2. Set up PCI. First, call :c:func:`pci_restore_state()`. Then
+   enable the pci device again by calling
+   :c:func:`pci_enable_device()`. Call
+   :c:func:`pci_set_master()` if necessary, too.
+
+3. Re-initialize the chip.
+
+4. Restore the saved registers if necessary.
+
+5. Resume the mixer, e.g. calling :c:func:`snd_ac97_resume()`.
+
+6. Restart the hardware (if any).
+
+7. Call :c:func:`snd_power_change_state()` with
+   ``SNDRV_CTL_POWER_D0`` to notify the processes.
+
+A typical code would be like:
+
+::
+
+  static int mychip_resume(struct pci_dev *pci)
+  {
+          /* (1) */
+          struct snd_card *card = pci_get_drvdata(pci);
+          struct mychip *chip = card->private_data;
+          /* (2) */
+          pci_restore_state(pci);
+          pci_enable_device(pci);
+          pci_set_master(pci);
+          /* (3) */
+          snd_mychip_reinit_chip(chip);
+          /* (4) */
+          snd_mychip_restore_registers(chip);
+          /* (5) */
+          snd_ac97_resume(chip->ac97);
+          /* (6) */
+          snd_mychip_restart_chip(chip);
+          /* (7) */
+          snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+          return 0;
+  }
+
+As shown in the above, it's better to save registers after suspending
+the PCM operations via :c:func:`snd_pcm_suspend_all()` or
+:c:func:`snd_pcm_suspend()`. It means that the PCM streams are
+already stopped when the register snapshot is taken. But, remember that
+you don't have to restart the PCM stream in the resume callback. It'll
+be restarted via trigger call with ``SNDRV_PCM_TRIGGER_RESUME`` when
+necessary.
+
+OK, we have all callbacks now. Let's set them up. In the initialization
+of the card, make sure that you can get the chip data from the card
+instance, typically via ``private_data`` field, in case you created the
+chip data individually.
+
+::
+
+  static int snd_mychip_probe(struct pci_dev *pci,
+                              const struct pci_device_id *pci_id)
+  {
+          ....
+          struct snd_card *card;
+          struct mychip *chip;
+          int err;
+          ....
+          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                             0, &card);
+          ....
+          chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+          ....
+          card->private_data = chip;
+          ....
+  }
+
+When you created the chip data with :c:func:`snd_card_new()`, it's
+anyway accessible via ``private_data`` field.
+
+::
+
+  static int snd_mychip_probe(struct pci_dev *pci,
+                              const struct pci_device_id *pci_id)
+  {
+          ....
+          struct snd_card *card;
+          struct mychip *chip;
+          int err;
+          ....
+          err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
+                             sizeof(struct mychip), &card);
+          ....
+          chip = card->private_data;
+          ....
+  }
+
+If you need a space to save the registers, allocate the buffer for it
+here, too, since it would be fatal if you cannot allocate a memory in
+the suspend phase. The allocated buffer should be released in the
+corresponding destructor.
+
+And next, set suspend/resume callbacks to the pci_driver.
+
+::
+
+  static struct pci_driver driver = {
+          .name = KBUILD_MODNAME,
+          .id_table = snd_my_ids,
+          .probe = snd_my_probe,
+          .remove = snd_my_remove,
+  #ifdef CONFIG_PM
+          .suspend = snd_my_suspend,
+          .resume = snd_my_resume,
+  #endif
+  };
+
+Module Parameters
+=================
+
+There are standard module options for ALSA. At least, each module should
+have the ``index``, ``id`` and ``enable`` options.
+
+If the module supports multiple cards (usually up to 8 = ``SNDRV_CARDS``
+cards), they should be arrays. The default initial values are defined
+already as constants for easier programming:
+
+::
+
+  static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+  static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+  static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+If the module supports only a single card, they could be single
+variables, instead. ``enable`` option is not always necessary in this
+case, but it would be better to have a dummy option for compatibility.
+
+The module parameters must be declared with the standard
+``module_param()()``, ``module_param_array()()`` and
+:c:func:`MODULE_PARM_DESC()` macros.
+
+The typical coding would be like below:
+
+::
+
+  #define CARD_NAME "My Chip"
+
+  module_param_array(index, int, NULL, 0444);
+  MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
+  module_param_array(id, charp, NULL, 0444);
+  MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
+  module_param_array(enable, bool, NULL, 0444);
+  MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
+
+Also, don't forget to define the module description, classes, license
+and devices. Especially, the recent modprobe requires to define the
+module license as GPL, etc., otherwise the system is shown as “tainted”.
+
+::
+
+  MODULE_DESCRIPTION("My Chip");
+  MODULE_LICENSE("GPL");
+  MODULE_SUPPORTED_DEVICE("{{Vendor,My Chip Name}}");
+
+
+How To Put Your Driver Into ALSA Tree
+=====================================
+
+General
+-------
+
+So far, you've learned how to write the driver codes. And you might have
+a question now: how to put my own driver into the ALSA driver tree? Here
+(finally :) the standard procedure is described briefly.
+
+Suppose that you create a new PCI driver for the card “xyz”. The card
+module name would be snd-xyz. The new driver is usually put into the
+alsa-driver tree, ``alsa-driver/pci`` directory in the case of PCI
+cards. Then the driver is evaluated, audited and tested by developers
+and users. After a certain time, the driver will go to the alsa-kernel
+tree (to the corresponding directory, such as ``alsa-kernel/pci``) and
+eventually will be integrated into the Linux 2.6 tree (the directory
+would be ``linux/sound/pci``).
+
+In the following sections, the driver code is supposed to be put into
+alsa-driver tree. The two cases are covered: a driver consisting of a
+single source file and one consisting of several source files.
+
+Driver with A Single Source File
+--------------------------------
+
+1. Modify alsa-driver/pci/Makefile
+
+   Suppose you have a file xyz.c. Add the following two lines
+
+::
+
+  snd-xyz-objs := xyz.o
+  obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+
+2. Create the Kconfig entry
+
+   Add the new entry of Kconfig for your xyz driver. config SND_XYZ
+   tristate "Foobar XYZ" depends on SND select SND_PCM help Say Y here
+   to include support for Foobar XYZ soundcard. To compile this driver
+   as a module, choose M here: the module will be called snd-xyz. the
+   line, select SND_PCM, specifies that the driver xyz supports PCM. In
+   addition to SND_PCM, the following components are supported for
+   select command: SND_RAWMIDI, SND_TIMER, SND_HWDEP,
+   SND_MPU401_UART, SND_OPL3_LIB, SND_OPL4_LIB, SND_VX_LIB,
+   SND_AC97_CODEC. Add the select command for each supported
+   component.
+
+   Note that some selections imply the lowlevel selections. For example,
+   PCM includes TIMER, MPU401_UART includes RAWMIDI, AC97_CODEC
+   includes PCM, and OPL3_LIB includes HWDEP. You don't need to give
+   the lowlevel selections again.
+
+   For the details of Kconfig script, refer to the kbuild documentation.
+
+3. Run cvscompile script to re-generate the configure script and build
+   the whole stuff again.
+
+Drivers with Several Source Files
+---------------------------------
+
+Suppose that the driver snd-xyz have several source files. They are
+located in the new subdirectory, pci/xyz.
+
+1. Add a new directory (``xyz``) in ``alsa-driver/pci/Makefile`` as
+   below
+
+::
+
+  obj-$(CONFIG_SND) += xyz/
+
+
+2. Under the directory ``xyz``, create a Makefile
+
+::
+
+         ifndef SND_TOPDIR
+         SND_TOPDIR=../..
+         endif
+
+         include $(SND_TOPDIR)/toplevel.config
+         include $(SND_TOPDIR)/Makefile.conf
+
+         snd-xyz-objs := xyz.o abc.o def.o
+
+         obj-$(CONFIG_SND_XYZ) += snd-xyz.o
+
+         include $(SND_TOPDIR)/Rules.make
+
+3. Create the Kconfig entry
+
+   This procedure is as same as in the last section.
+
+4. Run cvscompile script to re-generate the configure script and build
+   the whole stuff again.
+
+Useful Functions
+================
+
+:c:func:`snd_printk()` and friends
+---------------------------------------
+
+ALSA provides a verbose version of the :c:func:`printk()` function.
+If a kernel config ``CONFIG_SND_VERBOSE_PRINTK`` is set, this function
+prints the given message together with the file name and the line of the
+caller. The ``KERN_XXX`` prefix is processed as well as the original
+:c:func:`printk()` does, so it's recommended to add this prefix,
+e.g. snd_printk(KERN_ERR "Oh my, sorry, it's extremely bad!\\n");
+
+There are also :c:func:`printk()`'s for debugging.
+:c:func:`snd_printd()` can be used for general debugging purposes.
+If ``CONFIG_SND_DEBUG`` is set, this function is compiled, and works
+just like :c:func:`snd_printk()`. If the ALSA is compiled without
+the debugging flag, it's ignored.
+
+:c:func:`snd_printdd()` is compiled in only when
+``CONFIG_SND_DEBUG_VERBOSE`` is set. Please note that
+``CONFIG_SND_DEBUG_VERBOSE`` is not set as default even if you configure
+the alsa-driver with ``--with-debug=full`` option. You need to give
+explicitly ``--with-debug=detect`` option instead.
+
+:c:func:`snd_BUG()`
+------------------------
+
+It shows the ``BUG?`` message and stack trace as well as
+:c:func:`snd_BUG_ON()` at the point. It's useful to show that a
+fatal error happens there.
+
+When no debug flag is set, this macro is ignored.
+
+:c:func:`snd_BUG_ON()`
+----------------------------
+
+:c:func:`snd_BUG_ON()` macro is similar with
+:c:func:`WARN_ON()` macro. For example, snd_BUG_ON(!pointer); or
+it can be used as the condition, if (snd_BUG_ON(non_zero_is_bug))
+return -EINVAL;
+
+The macro takes an conditional expression to evaluate. When
+``CONFIG_SND_DEBUG``, is set, if the expression is non-zero, it shows
+the warning message such as ``BUG? (xxx)`` normally followed by stack
+trace. In both cases it returns the evaluated value.
+
+Acknowledgments
+===============
+
+I would like to thank Phil Kerr for his help for improvement and
+corrections of this document.
+
+Kevin Conder reformatted the original plain-text to the DocBook format.
+
+Giuliano Pochini corrected typos and contributed the example codes in
+the hardware constraints section.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/oss/oss-parameters.txt linux-libre-4.10-rc8-gnu/Documentation/sound/oss/oss-parameters.txt
--- linux-libre-4.9-gnu/Documentation/sound/oss/oss-parameters.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/oss/oss-parameters.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
                           OSS Kernel Parameters
                           ~~~~~~~~~~~~~~~~~~~~~
 
-See Documentation/kernel-parameters.txt for general information on
+See Documentation/admin-guide/kernel-parameters.rst for general information on
 specifying module parameters.
 
 This document may not be entirely up to date and comprehensive. The command
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/clocking.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/clocking.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/clocking.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/clocking.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,46 @@
+==============
+Audio Clocking
+==============
+
+This text describes the audio clocking terms in ASoC and digital audio in
+general. Note: Audio clocking can be complex!
+
+
+Master Clock
+------------
+
+Every audio subsystem is driven by a master clock (sometimes referred to as MCLK
+or SYSCLK). This audio master clock can be derived from a number of sources
+(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
+audio playback and capture sample rates.
+
+Some master clocks (e.g. PLLs and CPU based clocks) are configurable in that
+their speed can be altered by software (depending on the system use and to save
+power). Other master clocks are fixed at a set frequency (i.e. crystals).
+
+
+DAI Clocks
+----------
+The Digital Audio Interface is usually driven by a Bit Clock (often referred to
+as BCLK). This clock is used to drive the digital audio data across the link
+between the codec and CPU.
+
+The DAI also has a frame clock to signal the start of each audio frame. This
+clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
+runs at exactly the sample rate (LRC = Rate).
+
+Bit Clock can be generated as follows:-
+
+- BCLK = MCLK / x, or
+- BCLK = LRC * x, or
+- BCLK = LRC * Channels * Word Size
+
+This relationship depends on the codec or SoC CPU in particular. In general
+it is best to configure BCLK to the lowest possible speed (depending on your
+rate, number of channels and word size) to save on power.
+
+It is also desirable to use the codec (if possible) to drive (or master) the
+audio clocks as it usually gives more accurate sample rates than the CPU.
+
+
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/codec.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/codec.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/codec.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/codec.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,190 @@
+=======================
+ASoC Codec Class Driver
+=======================
+
+The codec class driver is generic and hardware independent code that configures
+the codec, FM, MODEM, BT or external DSP to provide audio capture and playback.
+It should contain no code that is specific to the target platform or machine.
+All platform and machine specific code should be added to the platform and
+machine drivers respectively.
+
+Each codec class driver *must* provide the following features:-
+
+1. Codec DAI and PCM configuration
+2. Codec control IO - using RegMap API
+3. Mixers and audio controls
+4. Codec audio operations
+5. DAPM description.
+6. DAPM event handler.
+
+Optionally, codec drivers can also provide:-
+
+7. DAC Digital mute control.
+
+Its probably best to use this guide in conjunction with the existing codec
+driver code in sound/soc/codecs/
+
+ASoC Codec driver breakdown
+===========================
+
+Codec DAI and PCM configuration
+-------------------------------
+Each codec driver must have a struct snd_soc_dai_driver to define its DAI and
+PCM capabilities and operations. This struct is exported so that it can be
+registered with the core by your machine driver.
+
+e.g.
+::
+
+  static struct snd_soc_dai_ops wm8731_dai_ops = {
+	.prepare	= wm8731_pcm_prepare,
+	.hw_params	= wm8731_hw_params,
+	.shutdown	= wm8731_shutdown,
+	.digital_mute	= wm8731_mute,
+	.set_sysclk	= wm8731_set_dai_sysclk,
+	.set_fmt	= wm8731_set_dai_fmt,
+  };
+  
+  struct snd_soc_dai_driver wm8731_dai = {
+	.name = "wm8731-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8731_RATES,
+		.formats = WM8731_FORMATS,},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = WM8731_RATES,
+		.formats = WM8731_FORMATS,},
+	.ops = &wm8731_dai_ops,
+	.symmetric_rates = 1,
+  };
+
+
+Codec control IO
+----------------
+The codec can usually be controlled via an I2C or SPI style interface
+(AC97 combines control with data in the DAI). The codec driver should use the
+Regmap API for all codec IO. Please see include/linux/regmap.h and existing
+codec drivers for example regmap usage.
+
+
+Mixers and audio controls
+-------------------------
+All the codec mixers and audio controls can be defined using the convenience
+macros defined in soc.h.
+::
+
+    #define SOC_SINGLE(xname, reg, shift, mask, invert)
+
+Defines a single control as follows:-
+::
+
+  xname = Control name e.g. "Playback Volume"
+  reg = codec register
+  shift = control bit(s) offset in register
+  mask = control bit size(s) e.g. mask of 7 = 3 bits
+  invert = the control is inverted
+
+Other macros include:-
+::
+
+    #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
+
+A stereo control
+::
+
+    #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
+
+A stereo control spanning 2 registers
+::
+
+    #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
+
+Defines an single enumerated control as follows:-
+::
+
+   xreg = register
+   xshift = control bit(s) offset in register
+   xmask = control bit(s) size
+   xtexts = pointer to array of strings that describe each setting
+
+   #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
+
+Defines a stereo enumerated control
+
+
+Codec Audio Operations
+----------------------
+The codec driver also supports the following ALSA PCM operations:-
+::
+
+  /* SoC audio ops */
+  struct snd_soc_ops {
+	int (*startup)(struct snd_pcm_substream *);
+	void (*shutdown)(struct snd_pcm_substream *);
+	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
+	int (*hw_free)(struct snd_pcm_substream *);
+	int (*prepare)(struct snd_pcm_substream *);
+  };
+
+Please refer to the ALSA driver PCM documentation for details.
+http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
+
+
+DAPM description
+----------------
+The Dynamic Audio Power Management description describes the codec power
+components and their relationships and registers to the ASoC core.
+Please read dapm.txt for details of building the description.
+
+Please also see the examples in other codec drivers.
+
+
+DAPM event handler
+------------------
+This function is a callback that handles codec domain PM calls and system
+domain PM calls (e.g. suspend and resume). It is used to put the codec
+to sleep when not in use.
+
+Power states:-
+::
+
+	SNDRV_CTL_POWER_D0: /* full On */
+	/* vref/mid, clk and osc on, active */
+
+	SNDRV_CTL_POWER_D1: /* partial On */
+	SNDRV_CTL_POWER_D2: /* partial On */
+
+	SNDRV_CTL_POWER_D3hot: /* Off, with power */
+	/* everything off except vref/vmid, inactive */
+
+	SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
+
+
+Codec DAC digital mute control
+------------------------------
+Most codecs have a digital mute before the DACs that can be used to
+minimise any system noise.  The mute stops any digital data from
+entering the DAC.
+
+A callback can be created that is called by the core for each codec DAI
+when the mute is applied or freed.
+
+i.e.
+::
+
+  static int wm8974_mute(struct snd_soc_dai *dai, int mute)
+  {
+	struct snd_soc_codec *codec = dai->codec;
+	u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf;
+
+	if (mute)
+		snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40);
+	else
+		snd_soc_write(codec, WM8974_DAC, mute_reg);
+	return 0;
+  }
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/codec-to-codec.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/codec-to-codec.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/codec-to-codec.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/codec-to-codec.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,108 @@
+==============================================
+Creating codec to codec dai link for ALSA dapm
+==============================================
+
+Mostly the flow of audio is always from CPU to codec so your system
+will look as below:
+::
+
+   ---------          ---------
+  |         |  dai   |         |
+      CPU    ------->    codec
+  |         |        |         |
+   ---------          ---------
+
+In case your system looks as below:
+::
+
+                       ---------
+                      |         |
+                        codec-2
+                      |         |
+                      ---------
+                           |
+                         dai-2
+                           |
+   ----------          ---------
+  |          |  dai-1 |         |
+      CPU     ------->  codec-1
+  |          |        |         |
+   ----------          ---------
+                           |
+                         dai-3
+                           |
+                       ---------
+                      |         |
+                        codec-3
+                      |         |
+                       ---------
+
+Suppose codec-2 is a bluetooth chip and codec-3 is connected to
+a speaker and you have a below scenario:
+codec-2 will receive the audio data and the user wants to play that
+audio through codec-3 without involving the CPU.This
+aforementioned case is the ideal case when codec to codec
+connection should be used.
+
+Your dai_link should appear as below in your machine
+file:
+::
+
+ /*
+  * this pcm stream only supports 24 bit, 2 channel and
+  * 48k sampling rate.
+  */
+ static const struct snd_soc_pcm_stream dsp_codec_params = {
+        .formats = SNDRV_PCM_FMTBIT_S24_LE,
+        .rate_min = 48000,
+        .rate_max = 48000,
+        .channels_min = 2,
+        .channels_max = 2,
+ };
+
+ {
+    .name = "CPU-DSP",
+    .stream_name = "CPU-DSP",
+    .cpu_dai_name = "samsung-i2s.0",
+    .codec_name = "codec-2,
+    .codec_dai_name = "codec-2-dai_name",
+    .platform_name = "samsung-i2s.0",
+    .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+            | SND_SOC_DAIFMT_CBM_CFM,
+    .ignore_suspend = 1,
+    .params = &dsp_codec_params,
+ },
+ {
+    .name = "DSP-CODEC",
+    .stream_name = "DSP-CODEC",
+    .cpu_dai_name = "wm0010-sdi2",
+    .codec_name = "codec-3,
+    .codec_dai_name = "codec-3-dai_name",
+    .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+            | SND_SOC_DAIFMT_CBM_CFM,
+    .ignore_suspend = 1,
+    .params = &dsp_codec_params,
+ },
+
+Above code snippet is motivated from sound/soc/samsung/speyside.c.
+
+Note the "params" callback which lets the dapm know that this
+dai_link is a codec to codec connection.
+
+In dapm core a route is created between cpu_dai playback widget
+and codec_dai capture widget for playback path and vice-versa is
+true for capture path. In order for this aforementioned route to get
+triggered, DAPM needs to find a valid endpoint which could be either
+a sink or source widget corresponding to playback and capture path
+respectively.
+
+In order to trigger this dai_link widget, a thin codec driver for
+the speaker amp can be created as demonstrated in wm8727.c file, it
+sets appropriate constraints for the device even if it needs no control.
+
+Make sure to name your corresponding cpu and codec playback and capture
+dai names ending with "Playback" and "Capture" respectively as dapm core
+will link and power those dais based on the name.
+
+Note that in current device tree there is no way to mark a dai_link
+as codec to codec. However, it may change in future.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/dai.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/dai.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/dai.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/dai.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+==================================
+ASoC Digital Audio Interface (DAI)
+==================================
+
+ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
+SoC controllers and portable audio CODECs today, namely AC97, I2S and PCM.
+
+
+AC97
+====
+
+AC97 is a five wire interface commonly found on many PC sound cards. It is
+now also popular in many portable devices. This DAI has a reset line and time
+multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
+The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
+frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
+frame is 21uS long and is divided into 13 time slots.
+
+The AC97 specification can be found at :
+http://www.intel.com/p/en_US/business/design
+
+
+I2S
+===
+
+I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
+Rx lines are used for audio transmission, whilst the bit clock (BCLK) and
+left/right clock (LRC) synchronise the link. I2S is flexible in that either the
+controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
+usually varies depending on the sample rate and the master system clock
+(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
+ADC and DAC LRCLKs, this allows for simultaneous capture and playback at
+different sample rates.
+
+I2S has several different operating modes:-
+
+I2S
+  MSB is transmitted on the falling edge of the first BCLK after LRC
+  transition.
+
+Left Justified
+  MSB is transmitted on transition of LRC.
+
+Right Justified
+  MSB is transmitted sample size BCLKs before LRC transition.
+
+PCM
+===
+
+PCM is another 4 wire interface, very similar to I2S, which can support a more
+flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
+to synchronise the link whilst the Tx and Rx lines are used to transmit and
+receive the audio data. Bit clock usually varies depending on sample rate
+whilst sync runs at the sample rate. PCM also supports Time Division
+Multiplexing (TDM) in that several devices can use the bus simultaneously (this
+is sometimes referred to as network mode).
+
+Common PCM operating modes:-
+
+Mode A
+  MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
+
+Mode B
+  MSB is transmitted on rising edge of FRAME/SYNC.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/dapm.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/dapm.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/dapm.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/dapm.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,342 @@
+===================================================
+Dynamic Audio Power Management for Portable Devices
+===================================================
+
+Description
+===========
+
+Dynamic Audio Power Management (DAPM) is designed to allow portable
+Linux devices to use the minimum amount of power within the audio
+subsystem at all times. It is independent of other kernel PM and as
+such, can easily co-exist with the other PM systems.
+
+DAPM is also completely transparent to all user space applications as
+all power switching is done within the ASoC core. No code changes or
+recompiling are required for user space applications. DAPM makes power
+switching decisions based upon any audio stream (capture/playback)
+activity and audio mixer settings within the device.
+
+DAPM spans the whole machine. It covers power control within the entire
+audio subsystem, this includes internal codec power blocks and machine
+level power systems.
+
+There are 4 power domains within DAPM
+
+Codec bias domain
+      VREF, VMID (core codec and audio power)
+
+      Usually controlled at codec probe/remove and suspend/resume, although
+      can be set at stream time if power is not needed for sidetone, etc.
+
+Platform/Machine domain
+      physically connected inputs and outputs
+
+      Is platform/machine and user action specific, is configured by the
+      machine driver and responds to asynchronous events e.g when HP
+      are inserted
+
+Path domain
+      audio subsystem signal paths
+
+      Automatically set when mixer and mux settings are changed by the user.
+      e.g. alsamixer, amixer.
+
+Stream domain
+      DACs and ADCs.
+
+      Enabled and disabled when stream playback/capture is started and
+      stopped respectively. e.g. aplay, arecord.
+
+All DAPM power switching decisions are made automatically by consulting an audio
+routing map of the whole machine. This map is specific to each machine and
+consists of the interconnections between every audio component (including
+internal codec components). All audio components that effect power are called
+widgets hereafter.
+
+
+DAPM Widgets
+============
+
+Audio DAPM widgets fall into a number of types:-
+
+Mixer
+	Mixes several analog signals into a single analog signal.
+Mux
+	An analog switch that outputs only one of many inputs.
+PGA
+	A programmable gain amplifier or attenuation widget.
+ADC
+	Analog to Digital Converter
+DAC
+	Digital to Analog Converter
+Switch
+	An analog switch
+Input
+	A codec input pin
+Output
+	A codec output pin
+Headphone
+	Headphone (and optional Jack)
+Mic
+	Mic (and optional Jack)
+Line
+	Line Input/Output (and optional Jack)
+Speaker
+	Speaker
+Supply
+	Power or clock supply widget used by other widgets.
+Regulator
+	External regulator that supplies power to audio components.
+Clock
+	External clock that supplies clock to audio components.
+AIF IN
+	Audio Interface Input (with TDM slot mask).
+AIF OUT
+	Audio Interface Output (with TDM slot mask).
+Siggen
+	Signal Generator.
+DAI IN
+	Digital Audio Interface Input.
+DAI OUT
+	Digital Audio Interface Output.
+DAI Link
+	DAI Link between two DAI structures
+Pre
+	Special PRE widget (exec before all others)
+Post
+	Special POST widget (exec after all others)
+
+(Widgets are defined in include/sound/soc-dapm.h)
+
+Widgets can be added to the sound card by any of the component driver types.
+There are convenience macros defined in soc-dapm.h that can be used to quickly
+build a list of widgets of the codecs and machines DAPM widgets.
+
+Most widgets have a name, register, shift and invert. Some widgets have extra
+parameters for stream name and kcontrols.
+
+
+Stream Domain Widgets
+---------------------
+
+Stream Widgets relate to the stream power domain and only consist of ADCs
+(analog to digital converters), DACs (digital to analog converters),
+AIF IN and AIF OUT.
+
+Stream widgets have the following format:-
+::
+
+  SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
+  SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert)
+
+NOTE: the stream name must match the corresponding stream name in your codec
+snd_soc_codec_dai.
+
+e.g. stream widgets for HiFi playback and capture
+::
+
+  SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
+  SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
+
+e.g. stream widgets for AIF
+::
+
+  SND_SOC_DAPM_AIF_IN("AIF1RX", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+  SND_SOC_DAPM_AIF_OUT("AIF1TX", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+
+Path Domain Widgets
+-------------------
+
+Path domain widgets have a ability to control or affect the audio signal or
+audio paths within the audio subsystem. They have the following form:-
+::
+
+  SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
+
+Any widget kcontrols can be set using the controls and num_controls members.
+
+e.g. Mixer widget (the kcontrols are declared first)
+::
+
+  /* Output Mixer */
+  static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
+  SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
+  SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
+  SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
+  };
+
+  SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
+	ARRAY_SIZE(wm8731_output_mixer_controls)),
+
+If you don't want the mixer elements prefixed with the name of the mixer widget,
+you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
+as for SND_SOC_DAPM_MIXER.
+
+
+Machine domain Widgets
+----------------------
+
+Machine widgets are different from codec widgets in that they don't have a
+codec register bit associated with them. A machine widget is assigned to each
+machine audio component (non codec or DSP) that can be independently
+powered. e.g.
+
+* Speaker Amp
+* Microphone Bias
+* Jack connectors
+
+A machine widget can have an optional call back.
+
+e.g. Jack connector widget for an external Mic that enables Mic Bias
+when the Mic is inserted:-::
+
+  static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
+  {
+	gpio_set_value(SPITZ_GPIO_MIC_BIAS, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+  }
+
+  SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
+
+
+Codec (BIAS) Domain
+-------------------
+
+The codec bias power domain has no widgets and is handled by the codecs DAPM
+event handler. This handler is called when the codec powerstate is changed wrt
+to any stream event or by kernel PM events.
+
+
+Virtual Widgets
+---------------
+
+Sometimes widgets exist in the codec or machine audio map that don't have any
+corresponding soft power control. In this case it is necessary to create
+a virtual widget - a widget with no control bits e.g.
+::
+
+  SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
+
+This can be used to merge to signal paths together in software.
+
+After all the widgets have been defined, they can then be added to the DAPM
+subsystem individually with a call to snd_soc_dapm_new_control().
+
+
+Codec/DSP Widget Interconnections
+=================================
+
+Widgets are connected to each other within the codec, platform and machine by
+audio paths (called interconnections). Each interconnection must be defined in
+order to create a map of all audio paths between widgets.
+
+This is easiest with a diagram of the codec or DSP (and schematic of the machine
+audio system), as it requires joining widgets together via their audio signal
+paths.
+
+e.g., from the WM8731 output mixer (wm8731.c)
+
+The WM8731 output mixer has 3 inputs (sources)
+
+1. Line Bypass Input
+2. DAC (HiFi playback)
+3. Mic Sidetone Input
+
+Each input in this example has a kcontrol associated with it (defined in example
+above) and is connected to the output mixer via its kcontrol name. We can now
+connect the destination widget (wrt audio signal) with its source widgets.
+::
+
+	/* output mixer */
+	{"Output Mixer", "Line Bypass Switch", "Line Input"},
+	{"Output Mixer", "HiFi Playback Switch", "DAC"},
+	{"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
+
+So we have :-
+
+* Destination Widget  <=== Path Name <=== Source Widget, or
+* Sink, Path, Source, or
+* ``Output Mixer`` is connected to the ``DAC`` via the ``HiFi Playback Switch``.
+
+When there is no path name connecting widgets (e.g. a direct connection) we
+pass NULL for the path name.
+
+Interconnections are created with a call to:-
+::
+
+  snd_soc_dapm_connect_input(codec, sink, path, source);
+
+Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
+interconnections have been registered with the core. This causes the core to
+scan the codec and machine so that the internal DAPM state matches the
+physical state of the machine.
+
+
+Machine Widget Interconnections
+-------------------------------
+Machine widget interconnections are created in the same way as codec ones and
+directly connect the codec pins to machine level widgets.
+
+e.g. connects the speaker out codec pins to the internal speaker.
+::
+
+	/* ext speaker connected to codec pins LOUT2, ROUT2  */
+	{"Ext Spk", NULL , "ROUT2"},
+	{"Ext Spk", NULL , "LOUT2"},
+
+This allows the DAPM to power on and off pins that are connected (and in use)
+and pins that are NC respectively.
+
+
+Endpoint Widgets
+================
+An endpoint is a start or end point (widget) of an audio signal within the
+machine and includes the codec. e.g.
+
+* Headphone Jack
+* Internal Speaker
+* Internal Mic
+* Mic Jack
+* Codec Pins
+
+Endpoints are added to the DAPM graph so that their usage can be determined in
+order to save power. e.g. NC codecs pins will be switched OFF, unconnected
+jacks can also be switched OFF.
+
+
+DAPM Widget Events
+==================
+
+Some widgets can register their interest with the DAPM core in PM events.
+e.g. A Speaker with an amplifier registers a widget so the amplifier can be
+powered only when the spk is in use.
+::
+
+  /* turn speaker amplifier on/off depending on use */
+  static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
+  {
+	gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event));
+	return 0;
+  }
+
+  /* corgi machine dapm widgets */
+  static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
+	SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
+
+Please see soc-dapm.h for all other widgets that support events.
+
+
+Event types
+-----------
+
+The following event types are supported by event widgets.
+::
+
+  /* dapm event types */
+  #define SND_SOC_DAPM_PRE_PMU	0x1 	/* before widget power up */
+  #define SND_SOC_DAPM_POST_PMU	0x2		/* after widget power up */
+  #define SND_SOC_DAPM_PRE_PMD	0x4 	/* before widget power down */
+  #define SND_SOC_DAPM_POST_PMD	0x8		/* after widget power down */
+  #define SND_SOC_DAPM_PRE_REG	0x10	/* before audio path setup */
+  #define SND_SOC_DAPM_POST_REG	0x20	/* after audio path setup */
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/dpcm.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/dpcm.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/dpcm.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/dpcm.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,392 @@
+===========
+Dynamic PCM
+===========
+
+Description
+===========
+
+Dynamic PCM allows an ALSA PCM device to digitally route its PCM audio to
+various digital endpoints during the PCM stream runtime. e.g. PCM0 can route
+digital audio to I2S DAI0, I2S DAI1 or PDM DAI2. This is useful for on SoC DSP
+drivers that expose several ALSA PCMs and can route to multiple DAIs.
+
+The DPCM runtime routing is determined by the ALSA mixer settings in the same
+way as the analog signal is routed in an ASoC codec driver. DPCM uses a DAPM
+graph representing the DSP internal audio paths and uses the mixer settings to
+determine the patch used by each ALSA PCM.
+
+DPCM re-uses all the existing component codec, platform and DAI drivers without
+any modifications.
+
+
+Phone Audio System with SoC based DSP
+-------------------------------------
+
+Consider the following phone audio subsystem. This will be used in this
+document for all examples :-
+::
+
+  | Front End PCMs    |  SoC DSP  | Back End DAIs | Audio devices |
+  
+                      *************
+  PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                      *           *
+  PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                      *   DSP     *
+  PCM2 <------------> *           * <----DAI2-----> MODEM
+                      *           *
+  PCM3 <------------> *           * <----DAI3-----> BT
+                      *           *
+                      *           * <----DAI4-----> DMIC
+                      *           *
+                      *           * <----DAI5-----> FM
+                      *************
+
+This diagram shows a simple smart phone audio subsystem. It supports Bluetooth,
+FM digital radio, Speakers, Headset Jack, digital microphones and cellular
+modem. This sound card exposes 4 DSP front end (FE) ALSA PCM devices and
+supports 6 back end (BE) DAIs. Each FE PCM can digitally route audio data to any
+of the BE DAIs. The FE PCM devices can also route audio to more than 1 BE DAI.
+
+
+
+Example - DPCM Switching playback from DAI0 to DAI1
+---------------------------------------------------
+
+Audio is being played to the Headset. After a while the user removes the headset
+and audio continues playing on the speakers.
+
+Playback on PCM0 to Headset would look like :-
+::
+
+                      *************
+  PCM0 <============> *           * <====DAI0=====> Codec Headset
+                      *           *
+  PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                      *   DSP     *
+  PCM2 <------------> *           * <----DAI2-----> MODEM
+                      *           *
+  PCM3 <------------> *           * <----DAI3-----> BT
+                      *           *
+                      *           * <----DAI4-----> DMIC
+                      *           *
+                      *           * <----DAI5-----> FM
+                      *************
+
+The headset is removed from the jack by user so the speakers must now be used :-
+::
+
+                      *************
+  PCM0 <============> *           * <----DAI0-----> Codec Headset
+                      *           *
+  PCM1 <------------> *           * <====DAI1=====> Codec Speakers
+                      *   DSP     *
+  PCM2 <------------> *           * <----DAI2-----> MODEM
+                      *           *
+  PCM3 <------------> *           * <----DAI3-----> BT
+                      *           *
+                      *           * <----DAI4-----> DMIC
+                      *           *
+                      *           * <----DAI5-----> FM
+                      *************
+
+The audio driver processes this as follows :-
+
+1. Machine driver receives Jack removal event.
+
+2. Machine driver OR audio HAL disables the Headset path.
+
+3. DPCM runs the PCM trigger(stop), hw_free(), shutdown() operations on DAI0
+   for headset since the path is now disabled.
+
+4. Machine driver or audio HAL enables the speaker path.
+
+5. DPCM runs the PCM ops for startup(), hw_params(), prepapre() and
+   trigger(start) for DAI1 Speakers since the path is enabled.
+
+In this example, the machine driver or userspace audio HAL can alter the routing
+and then DPCM will take care of managing the DAI PCM operations to either bring
+the link up or down. Audio playback does not stop during this transition.
+
+
+
+DPCM machine driver
+===================
+
+The DPCM enabled ASoC machine driver is similar to normal machine drivers
+except that we also have to :-
+
+1. Define the FE and BE DAI links.
+
+2. Define any FE/BE PCM operations.
+
+3. Define widget graph connections.
+
+
+FE and BE DAI links
+-------------------
+::
+
+  | Front End PCMs    |  SoC DSP  | Back End DAIs | Audio devices |
+  
+                      *************
+  PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                      *           *
+  PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                      *   DSP     *
+  PCM2 <------------> *           * <----DAI2-----> MODEM
+                      *           *
+  PCM3 <------------> *           * <----DAI3-----> BT
+                      *           *
+                      *           * <----DAI4-----> DMIC
+                      *           *
+                      *           * <----DAI5-----> FM
+                      *************
+
+For the example above we have to define 4 FE DAI links and 6 BE DAI links. The
+FE DAI links are defined as follows :-
+::
+
+  static struct snd_soc_dai_link machine_dais[] = {
+	{
+		.name = "PCM0 System",
+		.stream_name = "System Playback",
+		.cpu_dai_name = "System Pin",
+		.platform_name = "dsp-audio",
+		.codec_name = "snd-soc-dummy",
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
+		.dpcm_playback = 1,
+	},
+	.....< other FE and BE DAI links here >
+  };
+
+This FE DAI link is pretty similar to a regular DAI link except that we also
+set the DAI link to a DPCM FE with the ``dynamic = 1``. The supported FE stream
+directions should also be set with the ``dpcm_playback`` and ``dpcm_capture``
+flags. There is also an option to specify the ordering of the trigger call for
+each FE. This allows the ASoC core to trigger the DSP before or after the other
+components (as some DSPs have strong requirements for the ordering DAI/DSP
+start and stop sequences).
+
+The FE DAI above sets the codec and code DAIs to dummy devices since the BE is
+dynamic and will change depending on runtime config.
+
+The BE DAIs are configured as follows :-
+::
+
+  static struct snd_soc_dai_link machine_dais[] = {
+	.....< FE DAI links here >
+	{
+		.name = "Codec Headset",
+		.cpu_dai_name = "ssp-dai.0",
+		.platform_name = "snd-soc-dummy",
+		.no_pcm = 1,
+		.codec_name = "rt5640.0-001c",
+		.codec_dai_name = "rt5640-aif1",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.be_hw_params_fixup = hswult_ssp0_fixup,
+		.ops = &haswell_ops,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+	},
+	.....< other BE DAI links here >
+  };
+
+This BE DAI link connects DAI0 to the codec (in this case RT5460 AIF1). It sets
+the ``no_pcm`` flag to mark it has a BE and sets flags for supported stream
+directions using ``dpcm_playback`` and ``dpcm_capture`` above.
+
+The BE has also flags set for ignoring suspend and PM down time. This allows
+the BE to work in a hostless mode where the host CPU is not transferring data
+like a BT phone call :-
+::
+
+                      *************
+  PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                      *           *
+  PCM1 <------------> *           * <----DAI1-----> Codec Speakers
+                      *   DSP     *
+  PCM2 <------------> *           * <====DAI2=====> MODEM
+                      *           *
+  PCM3 <------------> *           * <====DAI3=====> BT
+                      *           *
+                      *           * <----DAI4-----> DMIC
+                      *           *
+                      *           * <----DAI5-----> FM
+                      *************
+
+This allows the host CPU to sleep whilst the DSP, MODEM DAI and the BT DAI are
+still in operation.
+
+A BE DAI link can also set the codec to a dummy device if the code is a device
+that is managed externally.
+
+Likewise a BE DAI can also set a dummy cpu DAI if the CPU DAI is managed by the
+DSP firmware.
+
+
+FE/BE PCM operations
+--------------------
+
+The BE above also exports some PCM operations and a ``fixup`` callback. The fixup
+callback is used by the machine driver to (re)configure the DAI based upon the
+FE hw params. i.e. the DSP may perform SRC or ASRC from the FE to BE.
+
+e.g. DSP converts all FE hw params to run at fixed rate of 48k, 16bit, stereo for
+DAI0. This means all FE hw_params have to be fixed in the machine driver for
+DAI0 so that the DAI is running at desired configuration regardless of the FE
+configuration.
+::
+
+  static int dai0_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+  {
+	struct snd_interval *rate = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+						SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	/* The DSP will covert the FE rate to 48k, stereo */
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = 2;
+
+	/* set DAI0 to 16 bit */
+	snd_mask_set(&params->masks[SNDRV_PCM_HW_PARAM_FORMAT -
+				    SNDRV_PCM_HW_PARAM_FIRST_MASK],
+				    SNDRV_PCM_FORMAT_S16_LE);
+	return 0;
+  }
+
+The other PCM operation are the same as for regular DAI links. Use as necessary.
+
+
+Widget graph connections
+------------------------
+
+The BE DAI links will normally be connected to the graph at initialisation time
+by the ASoC DAPM core. However, if the BE codec or BE DAI is a dummy then this
+has to be set explicitly in the driver :-
+::
+
+  /* BE for codec Headset -  DAI0 is dummy and managed by DSP FW */
+  {"DAI0 CODEC IN", NULL, "AIF1 Capture"},
+  {"AIF1 Playback", NULL, "DAI0 CODEC OUT"},
+
+
+Writing a DPCM DSP driver
+=========================
+
+The DPCM DSP driver looks much like a standard platform class ASoC driver
+combined with elements from a codec class driver. A DSP platform driver must
+implement :-
+
+1. Front End PCM DAIs - i.e. struct snd_soc_dai_driver.
+
+2. DAPM graph showing DSP audio routing from FE DAIs to BEs.
+
+3. DAPM widgets from DSP graph.
+
+4. Mixers for gains, routing, etc.
+
+5. DMA configuration.
+
+6. BE AIF widgets.
+
+Items 6 is important for routing the audio outside of the DSP. AIF need to be
+defined for each BE and each stream direction. e.g for BE DAI0 above we would
+have :-
+::
+
+  SND_SOC_DAPM_AIF_IN("DAI0 RX", NULL, 0, SND_SOC_NOPM, 0, 0),
+  SND_SOC_DAPM_AIF_OUT("DAI0 TX", NULL, 0, SND_SOC_NOPM, 0, 0),
+
+The BE AIF are used to connect the DSP graph to the graphs for the other
+component drivers (e.g. codec graph).
+
+
+Hostless PCM streams
+====================
+
+A hostless PCM stream is a stream that is not routed through the host CPU. An
+example of this would be a phone call from handset to modem.
+::
+
+                      *************
+  PCM0 <------------> *           * <----DAI0-----> Codec Headset
+                      *           *
+  PCM1 <------------> *           * <====DAI1=====> Codec Speakers/Mic
+                      *   DSP     *
+  PCM2 <------------> *           * <====DAI2=====> MODEM
+                      *           *
+  PCM3 <------------> *           * <----DAI3-----> BT
+                      *           *
+                      *           * <----DAI4-----> DMIC
+                      *           *
+                      *           * <----DAI5-----> FM
+                      *************
+
+In this case the PCM data is routed via the DSP. The host CPU in this use case
+is only used for control and can sleep during the runtime of the stream.
+
+The host can control the hostless link either by :-
+
+ 1. Configuring the link as a CODEC <-> CODEC style link. In this case the link
+    is enabled or disabled by the state of the DAPM graph. This usually means
+    there is a mixer control that can be used to connect or disconnect the path
+    between both DAIs.
+
+ 2. Hostless FE. This FE has a virtual connection to the BE DAI links on the DAPM
+    graph. Control is then carried out by the FE as regular PCM operations.
+    This method gives more control over the DAI links, but requires much more
+    userspace code to control the link. Its recommended to use CODEC<->CODEC
+    unless your HW needs more fine grained sequencing of the PCM ops.
+
+
+CODEC <-> CODEC link
+--------------------
+
+This DAI link is enabled when DAPM detects a valid path within the DAPM graph.
+The machine driver sets some additional parameters to the DAI link i.e.
+::
+
+  static const struct snd_soc_pcm_stream dai_params = {
+	.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	.rate_min = 8000,
+	.rate_max = 8000,
+	.channels_min = 2,
+	.channels_max = 2,
+  };
+
+  static struct snd_soc_dai_link dais[] = {
+	< ... more DAI links above ... >
+	{
+		.name = "MODEM",
+		.stream_name = "MODEM",
+		.cpu_dai_name = "dai2",
+		.codec_dai_name = "modem-aif1",
+		.codec_name = "modem",
+		.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+				| SND_SOC_DAIFMT_CBM_CFM,
+		.params = &dai_params,
+	}
+	< ... more DAI links here ... >
+
+These parameters are used to configure the DAI hw_params() when DAPM detects a
+valid path and then calls the PCM operations to start the link. DAPM will also
+call the appropriate PCM operations to disable the DAI when the path is no
+longer valid.
+
+
+Hostless FE
+-----------
+
+The DAI link(s) are enabled by a FE that does not read or write any PCM data.
+This means creating a new FE that is connected with a virtual path to both
+DAI links. The DAI links will be started when the FE PCM is started and stopped
+when the FE PCM is stopped. Note that the FE PCM cannot read or write data in
+this configuration.
+
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/index.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/index.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,20 @@
+==============
+ALSA SoC Layer
+==============
+
+The documentation is spilt into the following sections:-
+
+.. toctree::
+   :maxdepth: 2
+
+   overview
+   codec
+   dai
+   dapm
+   platform
+   machine
+   pops-clicks
+   clocking
+   jack
+   dpcm
+   codec-to-codec
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/jack.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/jack.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/jack.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/jack.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,72 @@
+===================
+ASoC jack detection
+===================
+
+ALSA has a standard API for representing physical jacks to user space,
+the kernel side of which can be seen in include/sound/jack.h.  ASoC
+provides a version of this API adding two additional features:
+
+ - It allows more than one jack detection method to work together on one
+   user visible jack.  In embedded systems it is common for multiple
+   to be present on a single jack but handled by separate bits of
+   hardware.
+
+ - Integration with DAPM, allowing DAPM endpoints to be updated
+   automatically based on the detected jack status (eg, turning off the
+   headphone outputs if no headphones are present).
+
+This is done by splitting the jacks up into three things working
+together: the jack itself represented by a struct snd_soc_jack, sets of
+snd_soc_jack_pins representing DAPM endpoints to update and blocks of
+code providing jack reporting mechanisms.
+
+For example, a system may have a stereo headset jack with two reporting
+mechanisms, one for the headphone and one for the microphone.  Some
+systems won't be able to use their speaker output while a headphone is
+connected and so will want to make sure to update both speaker and
+headphone when the headphone jack status changes.
+
+The jack - struct snd_soc_jack
+==============================
+
+This represents a physical jack on the system and is what is visible to
+user space.  The jack itself is completely passive, it is set up by the
+machine driver and updated by jack detection methods.
+
+Jacks are created by the machine driver calling snd_soc_jack_new().
+
+snd_soc_jack_pin
+================
+
+These represent a DAPM pin to update depending on some of the status
+bits supported by the jack.  Each snd_soc_jack has zero or more of these
+which are updated automatically.  They are created by the machine driver
+and associated with the jack using snd_soc_jack_add_pins().  The status
+of the endpoint may configured to be the opposite of the jack status if
+required (eg, enabling a built in microphone if a microphone is not
+connected via a jack).
+
+Jack detection methods
+======================
+
+Actual jack detection is done by code which is able to monitor some
+input to the system and update a jack by calling snd_soc_jack_report(),
+specifying a subset of bits to update.  The jack detection code should
+be set up by the machine driver, taking configuration for the jack to
+update and the set of things to report when the jack is connected.
+
+Often this is done based on the status of a GPIO - a handler for this is
+provided by the snd_soc_jack_add_gpio() function.  Other methods are
+also available, for example integrated into CODECs.  One example of
+CODEC integrated jack detection can be see in the WM8350 driver.
+
+Each jack may have multiple reporting mechanisms, though it will need at
+least one to be useful.
+
+Machine drivers
+===============
+
+These are all hooked together by the machine driver depending on the
+system hardware.  The machine driver will set up the snd_soc_jack and
+the list of pins to update then set up one or more jack detection
+mechanisms to update that jack based on their current status.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/machine.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/machine.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/machine.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/machine.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,97 @@
+===================
+ASoC Machine Driver
+===================
+
+The ASoC machine (or board) driver is the code that glues together all the
+component drivers (e.g. codecs, platforms and DAIs). It also describes the
+relationships between each component which include audio paths, GPIOs,
+interrupts, clocking, jacks and voltage regulators.
+
+The machine driver can contain codec and platform specific code. It registers
+the audio subsystem with the kernel as a platform device and is represented by
+the following struct:-
+::
+
+  /* SoC machine */
+  struct snd_soc_card {
+	char *name;
+
+	...
+
+	int (*probe)(struct platform_device *pdev);
+	int (*remove)(struct platform_device *pdev);
+
+	/* the pre and post PM functions are used to do any PM work before and
+	 * after the codec and DAIs do any PM work. */
+	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
+	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
+	int (*resume_pre)(struct platform_device *pdev);
+	int (*resume_post)(struct platform_device *pdev);
+
+	...
+
+	/* CPU <--> Codec DAI links  */
+	struct snd_soc_dai_link *dai_link;
+	int num_links;
+
+	...
+  };
+
+probe()/remove()
+----------------
+probe/remove are optional. Do any machine specific probe here.
+
+
+suspend()/resume()
+------------------
+The machine driver has pre and post versions of suspend and resume to take care
+of any machine audio tasks that have to be done before or after the codec, DAIs
+and DMA is suspended and resumed. Optional.
+
+
+Machine DAI Configuration
+-------------------------
+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.
+
+struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
+::
+
+  /* corgi digital audio interface glue - connects codec <--> CPU */
+  static struct snd_soc_dai_link corgi_dai = {
+	.name = "WM8731",
+	.stream_name = "WM8731",
+	.cpu_dai_name = "pxa-is2-dai",
+	.codec_dai_name = "wm8731-hifi",
+	.platform_name = "pxa-pcm-audio",
+	.codec_name = "wm8713-codec.0-001a",
+	.init = corgi_wm8731_init,
+	.ops = &corgi_ops,
+  };
+
+struct snd_soc_card then sets up the machine with its DAIs. e.g.
+::
+
+  /* corgi audio machine driver */
+  static struct snd_soc_card snd_soc_corgi = {
+	.name = "Corgi",
+	.dai_link = &corgi_dai,
+	.num_links = 1,
+  };
+
+
+Machine Power Map
+-----------------
+
+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.
+
+
+Machine Controls
+----------------
+
+Machine specific audio mixer controls can be added in the DAI init function.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/overview.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/overview.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/overview.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/overview.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,69 @@
+=======================
+ALSA SoC Layer Overview
+=======================
+
+The overall project goal of the ALSA System on Chip (ASoC) layer is to
+provide better ALSA support for embedded system-on-chip processors (e.g.
+pxa2xx, au1x00, iMX, etc) and portable audio codecs.  Prior to the ASoC
+subsystem there was some support in the kernel for SoC audio, however it
+had some limitations:-
+
+  * Codec drivers were often tightly coupled to the underlying SoC
+    CPU. This is not ideal and leads to code duplication - for example,
+    Linux had different wm8731 drivers for 4 different SoC platforms.
+
+  * There was no standard method to signal user initiated audio events (e.g.
+    Headphone/Mic insertion, Headphone/Mic detection after an insertion
+    event). These are quite common events on portable devices and often require
+    machine specific code to re-route audio, enable amps, etc., after such an
+    event.
+
+  * Drivers tended to power up the entire codec when playing (or
+    recording) audio. This is fine for a PC, but tends to waste a lot of
+    power on portable devices. There was also no support for saving
+    power via changing codec oversampling rates, bias currents, etc.
+
+
+ASoC Design
+===========
+
+The ASoC layer is designed to address these issues and provide the following
+features :-
+
+  * Codec independence. Allows reuse of codec drivers on other platforms
+    and machines.
+
+  * Easy I2S/PCM audio interface setup between codec and SoC. Each SoC
+    interface and codec registers its audio interface capabilities with the
+    core and are subsequently matched and configured when the application
+    hardware parameters are known.
+
+  * Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
+    its minimum power state at all times. This includes powering up/down
+    internal power blocks depending on the internal codec audio routing and any
+    active streams.
+
+  * Pop and click reduction. Pops and clicks can be reduced by powering the
+    codec up/down in the correct sequence (including using digital mute). ASoC
+    signals the codec when to change power states.
+
+  * Machine specific controls: Allow machines to add controls to the sound card
+    (e.g. volume control for speaker amplifier).
+
+To achieve all this, ASoC basically splits an embedded audio system into
+multiple re-usable component drivers :-
+
+  * Codec class drivers: The codec class driver is platform independent and
+    contains audio controls, audio interface capabilities, codec DAPM
+    definition and codec IO functions. This class extends to BT, FM and MODEM
+    ICs if required. Codec class drivers should be generic code that can run
+    on any architecture and machine.
+
+  * Platform class drivers: The platform class driver includes the audio DMA
+    engine driver, digital audio interface (DAI) drivers (e.g. I2S, AC97, PCM)
+    and any audio DSP drivers for that platform.
+
+  * Machine class driver: The machine driver class acts as the glue that
+    describes and binds the other component drivers together to form an ALSA
+    "sound card device". It handles any machine specific controls and
+    machine level audio events (e.g. turning on an amp at start of playback).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/platform.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/platform.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/platform.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/platform.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,82 @@
+====================
+ASoC Platform Driver
+====================
+
+An ASoC platform driver class can be divided into audio DMA drivers, SoC DAI
+drivers and DSP drivers. The platform drivers only target the SoC CPU and must
+have no board specific code.
+
+Audio DMA
+=========
+
+The platform DMA driver optionally supports the following ALSA operations:-
+::
+
+  /* SoC audio ops */
+  struct snd_soc_ops {
+	int (*startup)(struct snd_pcm_substream *);
+	void (*shutdown)(struct snd_pcm_substream *);
+	int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
+	int (*hw_free)(struct snd_pcm_substream *);
+	int (*prepare)(struct snd_pcm_substream *);
+	int (*trigger)(struct snd_pcm_substream *, int);
+  };
+
+The platform driver exports its DMA functionality via struct
+snd_soc_platform_driver:-
+::
+
+  struct snd_soc_platform_driver {
+	char *name;
+
+	int (*probe)(struct platform_device *pdev);
+	int (*remove)(struct platform_device *pdev);
+	int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
+	int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
+
+	/* pcm creation and destruction */
+	int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
+	void (*pcm_free)(struct snd_pcm *);
+
+	/*
+	 * For platform caused delay reporting.
+	 * Optional.
+	 */
+	snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *,
+		struct snd_soc_dai *);
+
+	/* platform stream ops */
+	struct snd_pcm_ops *pcm_ops;
+  };
+
+Please refer to the ALSA driver documentation for details of audio DMA.
+http://www.alsa-project.org/~iwai/writing-an-alsa-driver/
+
+An example DMA driver is soc/pxa/pxa2xx-pcm.c
+
+
+SoC DAI Drivers
+===============
+
+Each SoC DAI driver must provide the following features:-
+
+1. Digital audio interface (DAI) description
+2. Digital audio interface configuration
+3. PCM's description
+4. SYSCLK configuration
+5. Suspend and resume (optional)
+
+Please see codec.txt for a description of items 1 - 4.
+
+
+SoC DSP Drivers
+===============
+
+Each SoC DSP driver usually supplies the following features :-
+
+1. DAPM graph
+2. Mixer controls
+3. DMA IO to/from DSP buffers (if applicable)
+4. Definition of DSP front end (FE) PCM devices.
+
+Please see DPCM.txt for a description of item 4.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sound/soc/pops-clicks.rst linux-libre-4.10-rc8-gnu/Documentation/sound/soc/pops-clicks.rst
--- linux-libre-4.9-gnu/Documentation/sound/soc/pops-clicks.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sound/soc/pops-clicks.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,55 @@
+=====================
+Audio Pops and Clicks
+=====================
+
+Pops and clicks are unwanted audio artifacts caused by the powering up and down
+of components within the audio subsystem. This is noticeable on PCs when an
+audio module is either loaded or unloaded (at module load time the sound card is
+powered up and causes a popping noise on the speakers).
+
+Pops and clicks can be more frequent on portable systems with DAPM. This is
+because the components within the subsystem are being dynamically powered
+depending on the audio usage and this can subsequently cause a small pop or
+click every time a component power state is changed.
+
+
+Minimising Playback Pops and Clicks
+===================================
+
+Playback pops in portable audio subsystems cannot be completely eliminated
+currently, however future audio codec hardware will have better pop and click
+suppression.  Pops can be reduced within playback by powering the audio
+components in a specific order. This order is different for startup and
+shutdown and follows some basic rules:-
+::
+
+   Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
+  
+   Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
+
+This assumes that the codec PCM output path from the DAC is via a mixer and then
+a PGA (programmable gain amplifier) before being output to the speakers.
+
+
+Minimising Capture Pops and Clicks
+==================================
+
+Capture artifacts are somewhat easier to get rid as we can delay activating the
+ADC until all the pops have occurred. This follows similar power rules to
+playback in that components are powered in a sequence depending upon stream
+startup or shutdown.
+::
+
+   Startup Order - Input PGA --> Mixers --> ADC
+  
+   Shutdown Order - ADC --> Mixers --> Input PGA
+
+
+Zipper Noise
+============
+An unwanted zipper noise can occur within the audio playback or capture stream
+when a volume control is changed near its maximum gain value. The zipper noise
+is heard when the gain increase or decrease changes the mean audio signal
+amplitude too quickly. It can be minimised by enabling the zero cross setting
+for each volume control. The ZC forces the gain change to occur when the signal
+crosses the zero amplitude line.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sphinx/kernel-doc.py linux-libre-4.10-rc8-gnu/Documentation/sphinx/kernel-doc.py
--- linux-libre-4.9-gnu/Documentation/sphinx/kernel-doc.py	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sphinx/kernel-doc.py	1969-12-31 19:00:00.000000000 -0500
@@ -1,149 +0,0 @@
-# coding=utf-8
-#
-# Copyright © 2016 Intel Corporation
-#
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice (including the next
-# paragraph) shall be included in all copies or substantial portions of the
-# Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-#
-# Authors:
-#    Jani Nikula <jani.nikula@intel.com>
-#
-# Please make sure this works on both python2 and python3.
-#
-
-import os
-import subprocess
-import sys
-import re
-import glob
-
-from docutils import nodes, statemachine
-from docutils.statemachine import ViewList
-from docutils.parsers.rst import directives
-from sphinx.util.compat import Directive
-from sphinx.ext.autodoc import AutodocReporter
-
-__version__  = '1.0'
-
-class KernelDocDirective(Directive):
-    """Extract kernel-doc comments from the specified file"""
-    required_argument = 1
-    optional_arguments = 4
-    option_spec = {
-        'doc': directives.unchanged_required,
-        'functions': directives.unchanged_required,
-        'export': directives.unchanged,
-        'internal': directives.unchanged,
-    }
-    has_content = False
-
-    def run(self):
-        env = self.state.document.settings.env
-        cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
-
-        filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
-        export_file_patterns = []
-
-        # Tell sphinx of the dependency
-        env.note_dependency(os.path.abspath(filename))
-
-        tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
-
-        # FIXME: make this nicer and more robust against errors
-        if 'export' in self.options:
-            cmd += ['-export']
-            export_file_patterns = str(self.options.get('export')).split()
-        elif 'internal' in self.options:
-            cmd += ['-internal']
-            export_file_patterns = str(self.options.get('internal')).split()
-        elif 'doc' in self.options:
-            cmd += ['-function', str(self.options.get('doc'))]
-        elif 'functions' in self.options:
-            for f in str(self.options.get('functions')).split():
-                cmd += ['-function', f]
-
-        for pattern in export_file_patterns:
-            for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
-                env.note_dependency(os.path.abspath(f))
-                cmd += ['-export-file', f]
-
-        cmd += [filename]
-
-        try:
-            env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd)))
-
-            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
-            out, err = p.communicate()
-
-            # python2 needs conversion to unicode.
-            # python3 with universal_newlines=True returns strings.
-            if sys.version_info.major < 3:
-                out, err = unicode(out, 'utf-8'), unicode(err, 'utf-8')
-
-            if p.returncode != 0:
-                sys.stderr.write(err)
-
-                env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
-                return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
-            elif env.config.kerneldoc_verbosity > 0:
-                sys.stderr.write(err)
-
-            lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
-            result = ViewList()
-
-            lineoffset = 0;
-            line_regex = re.compile("^#define LINENO ([0-9]+)$")
-            for line in lines:
-                match = line_regex.search(line)
-                if match:
-                    # sphinx counts lines from 0
-                    lineoffset = int(match.group(1)) - 1
-                    # we must eat our comments since the upset the markup
-                else:
-                    result.append(line, filename, lineoffset)
-                    lineoffset += 1
-
-            node = nodes.section()
-            buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
-            self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
-            self.state.memo.title_styles, self.state.memo.section_level = [], 0
-            try:
-                self.state.nested_parse(result, 0, node, match_titles=1)
-            finally:
-                self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
-
-            return node.children
-
-        except Exception as e:  # pylint: disable=W0703
-            env.app.warn('kernel-doc \'%s\' processing failed with: %s' %
-                         (" ".join(cmd), str(e)))
-            return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
-
-def setup(app):
-    app.add_config_value('kerneldoc_bin', None, 'env')
-    app.add_config_value('kerneldoc_srctree', None, 'env')
-    app.add_config_value('kerneldoc_verbosity', 1, 'env')
-
-    app.add_directive('kernel-doc', KernelDocDirective)
-
-    return dict(
-        version = __version__,
-        parallel_read_safe = True,
-        parallel_write_safe = True
-    )
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sphinx/kerneldoc.py linux-libre-4.10-rc8-gnu/Documentation/sphinx/kerneldoc.py
--- linux-libre-4.9-gnu/Documentation/sphinx/kerneldoc.py	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sphinx/kerneldoc.py	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,149 @@
+# coding=utf-8
+#
+# Copyright © 2016 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+# Authors:
+#    Jani Nikula <jani.nikula@intel.com>
+#
+# Please make sure this works on both python2 and python3.
+#
+
+import os
+import subprocess
+import sys
+import re
+import glob
+
+from docutils import nodes, statemachine
+from docutils.statemachine import ViewList
+from docutils.parsers.rst import directives
+from sphinx.util.compat import Directive
+from sphinx.ext.autodoc import AutodocReporter
+
+__version__  = '1.0'
+
+class KernelDocDirective(Directive):
+    """Extract kernel-doc comments from the specified file"""
+    required_argument = 1
+    optional_arguments = 4
+    option_spec = {
+        'doc': directives.unchanged_required,
+        'functions': directives.unchanged_required,
+        'export': directives.unchanged,
+        'internal': directives.unchanged,
+    }
+    has_content = False
+
+    def run(self):
+        env = self.state.document.settings.env
+        cmd = [env.config.kerneldoc_bin, '-rst', '-enable-lineno']
+
+        filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
+        export_file_patterns = []
+
+        # Tell sphinx of the dependency
+        env.note_dependency(os.path.abspath(filename))
+
+        tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
+
+        # FIXME: make this nicer and more robust against errors
+        if 'export' in self.options:
+            cmd += ['-export']
+            export_file_patterns = str(self.options.get('export')).split()
+        elif 'internal' in self.options:
+            cmd += ['-internal']
+            export_file_patterns = str(self.options.get('internal')).split()
+        elif 'doc' in self.options:
+            cmd += ['-function', str(self.options.get('doc'))]
+        elif 'functions' in self.options:
+            for f in str(self.options.get('functions')).split():
+                cmd += ['-function', f]
+
+        for pattern in export_file_patterns:
+            for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
+                env.note_dependency(os.path.abspath(f))
+                cmd += ['-export-file', f]
+
+        cmd += [filename]
+
+        try:
+            env.app.verbose('calling kernel-doc \'%s\'' % (" ".join(cmd)))
+
+            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+            out, err = p.communicate()
+
+            # python2 needs conversion to unicode.
+            # python3 with universal_newlines=True returns strings.
+            if sys.version_info.major < 3:
+                out, err = unicode(out, 'utf-8'), unicode(err, 'utf-8')
+
+            if p.returncode != 0:
+                sys.stderr.write(err)
+
+                env.app.warn('kernel-doc \'%s\' failed with return code %d' % (" ".join(cmd), p.returncode))
+                return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
+            elif env.config.kerneldoc_verbosity > 0:
+                sys.stderr.write(err)
+
+            lines = statemachine.string2lines(out, tab_width, convert_whitespace=True)
+            result = ViewList()
+
+            lineoffset = 0;
+            line_regex = re.compile("^#define LINENO ([0-9]+)$")
+            for line in lines:
+                match = line_regex.search(line)
+                if match:
+                    # sphinx counts lines from 0
+                    lineoffset = int(match.group(1)) - 1
+                    # we must eat our comments since the upset the markup
+                else:
+                    result.append(line, filename, lineoffset)
+                    lineoffset += 1
+
+            node = nodes.section()
+            buf = self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter
+            self.state.memo.reporter = AutodocReporter(result, self.state.memo.reporter)
+            self.state.memo.title_styles, self.state.memo.section_level = [], 0
+            try:
+                self.state.nested_parse(result, 0, node, match_titles=1)
+            finally:
+                self.state.memo.title_styles, self.state.memo.section_level, self.state.memo.reporter = buf
+
+            return node.children
+
+        except Exception as e:  # pylint: disable=W0703
+            env.app.warn('kernel-doc \'%s\' processing failed with: %s' %
+                         (" ".join(cmd), str(e)))
+            return [nodes.error(None, nodes.paragraph(text = "kernel-doc missing"))]
+
+def setup(app):
+    app.add_config_value('kerneldoc_bin', None, 'env')
+    app.add_config_value('kerneldoc_srctree', None, 'env')
+    app.add_config_value('kerneldoc_verbosity', 1, 'env')
+
+    app.add_directive('kernel-doc', KernelDocDirective)
+
+    return dict(
+        version = __version__,
+        parallel_read_safe = True,
+        parallel_write_safe = True
+    )
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sphinx/parse-headers.pl linux-libre-4.10-rc8-gnu/Documentation/sphinx/parse-headers.pl
--- linux-libre-4.9-gnu/Documentation/sphinx/parse-headers.pl	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sphinx/parse-headers.pl	2017-02-12 16:03:20.000000000 -0500
@@ -1,22 +1,22 @@
 #!/usr/bin/perl
 use strict;
 use Text::Tabs;
+use Getopt::Long;
+use Pod::Usage;
 
-my $debug = 0;
+my $debug;
+my $help;
+my $man;
 
-while ($ARGV[0] =~ m/^-(.*)/) {
-	my $cmd = shift @ARGV;
-	if ($cmd eq "--debug") {
-		require Data::Dumper;
-		$debug = 1;
-		next;
-	}
-	die "argument $cmd unknown";
-}
+GetOptions(
+	"debug" => \$debug,
+	'usage|?' => \$help,
+	'help' => \$man
+) or pod2usage(2);
 
-if (scalar @ARGV < 2 || scalar @ARGV > 3) {
-	die "Usage:\n\t$0 <file in> <file out> [<exceptions file>]\n";
-}
+pod2usage(1) if $help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $man;
+pod2usage(2) if (scalar @ARGV < 2 || scalar @ARGV > 3);
 
 my ($file_in, $file_out, $file_exceptions) = @ARGV;
 
@@ -28,6 +28,8 @@ my %enums;
 my %enum_symbols;
 my %structs;
 
+require Data::Dumper if ($debug);
+
 #
 # read the file and get identifiers
 #
@@ -330,3 +332,70 @@ print OUT "=" x length($title);
 print OUT "\n\n.. parsed-literal::\n\n";
 print OUT $data;
 close OUT;
+
+__END__
+
+=head1 NAME
+
+parse_headers.pl - parse a C file, in order to identify functions, structs,
+enums and defines and create cross-references to a Sphinx book.
+
+=head1 SYNOPSIS
+
+B<parse_headers.pl> [<options>] <C_FILE> <OUT_FILE> [<EXCEPTIONS_FILE>]
+
+Where <options> can be: --debug, --help or --man.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--debug>
+
+Put the script in verbose mode, useful for debugging.
+
+=item B<--usage>
+
+Prints a brief help message and exits.
+
+=item B<--help>
+
+Prints a more detailed help message and exits.
+
+=back
+
+=head1 DESCRIPTION
+
+Convert a C header or source file (C_FILE), into a ReStructured Text
+included via ..parsed-literal block with cross-references for the
+documentation files that describe the API. It accepts an optional
+EXCEPTIONS_FILE with describes what elements will be either ignored or
+be pointed to a non-default reference.
+
+The output is written at the (OUT_FILE).
+
+It is capable of identifying defines, functions, structs, typedefs,
+enums and enum symbols and create cross-references for all of them.
+It is also capable of distinguish #define used for specifying a Linux
+ioctl.
+
+The EXCEPTIONS_FILE contain two rules to allow ignoring a symbol or
+to replace the default references by a custom one.
+
+Please read Documentation/doc-guide/parse-headers.rst at the Kernel's
+tree for more details.
+
+=head1 BUGS
+
+Report bugs to Mauro Carvalho Chehab <mchehab@s-opensource.com>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2016 by Mauro Carvalho Chehab <mchehab@s-opensource.com>.
+
+License GPLv2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>.
+
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+
+=cut
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sphinx/rstFlatTable.py linux-libre-4.10-rc8-gnu/Documentation/sphinx/rstFlatTable.py
--- linux-libre-4.9-gnu/Documentation/sphinx/rstFlatTable.py	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sphinx/rstFlatTable.py	2017-02-12 16:03:20.000000000 -0500
@@ -157,6 +157,11 @@ class ListTableBuilder(object):
     def buildTableNode(self):
 
         colwidths    = self.directive.get_column_widths(self.max_cols)
+        if isinstance(colwidths, tuple):
+            # Since docutils 0.13, get_column_widths returns a (widths,
+            # colwidths) tuple, where widths is a string (i.e. 'auto').
+            # See https://sourceforge.net/p/docutils/patches/120/.
+            colwidths = colwidths[1]
         stub_columns = self.directive.options.get('stub-columns', 0)
         header_rows  = self.directive.options.get('header-rows', 0)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/stable_api_nonsense.txt linux-libre-4.10-rc8-gnu/Documentation/stable_api_nonsense.txt
--- linux-libre-4.9-gnu/Documentation/stable_api_nonsense.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/stable_api_nonsense.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,205 +0,0 @@
-.. _stable_api_nonsense:
-
-The Linux Kernel Driver Interface
-==================================
-
-(all of your questions answered and then some)
-
-Greg Kroah-Hartman <greg@kroah.com>
-
-This is being written to try to explain why Linux **does not have a binary
-kernel interface, nor does it have a stable kernel interface**.
-
-.. note::
-
-  Please realize that this article describes the **in kernel** interfaces, not
-  the kernel to userspace interfaces.
-
-  The kernel to userspace interface is the one that application programs use,
-  the syscall interface.  That interface is **very** stable over time, and
-  will not break.  I have old programs that were built on a pre 0.9something
-  kernel that still work just fine on the latest 2.6 kernel release.
-  That interface is the one that users and application programmers can count
-  on being stable.
-
-
-Executive Summary
------------------
-You think you want a stable kernel interface, but you really do not, and
-you don't even know it.  What you want is a stable running driver, and
-you get that only if your driver is in the main kernel tree.  You also
-get lots of other good benefits if your driver is in the main kernel
-tree, all of which has made Linux into such a strong, stable, and mature
-operating system which is the reason you are using it in the first
-place.
-
-
-Intro
------
-
-It's only the odd person who wants to write a kernel driver that needs
-to worry about the in-kernel interfaces changing.  For the majority of
-the world, they neither see this interface, nor do they care about it at
-all.
-
-First off, I'm not going to address **any** legal issues about closed
-source, hidden source, binary blobs, source wrappers, or any other term
-that describes kernel drivers that do not have their source code
-released under the GPL.  Please consult a lawyer if you have any legal
-questions, I'm a programmer and hence, I'm just going to be describing
-the technical issues here (not to make light of the legal issues, they
-are real, and you do need to be aware of them at all times.)
-
-So, there are two main topics here, binary kernel interfaces and stable
-kernel source interfaces.  They both depend on each other, but we will
-discuss the binary stuff first to get it out of the way.
-
-
-Binary Kernel Interface
------------------------
-Assuming that we had a stable kernel source interface for the kernel, a
-binary interface would naturally happen too, right?  Wrong.  Please
-consider the following facts about the Linux kernel:
-
-  - Depending on the version of the C compiler you use, different kernel
-    data structures will contain different alignment of structures, and
-    possibly include different functions in different ways (putting
-    functions inline or not.)  The individual function organization
-    isn't that important, but the different data structure padding is
-    very important.
-
-  - Depending on what kernel build options you select, a wide range of
-    different things can be assumed by the kernel:
-
-      - different structures can contain different fields
-      - Some functions may not be implemented at all, (i.e. some locks
-	compile away to nothing for non-SMP builds.)
-      - Memory within the kernel can be aligned in different ways,
-	depending on the build options.
-
-  - Linux runs on a wide range of different processor architectures.
-    There is no way that binary drivers from one architecture will run
-    on another architecture properly.
-
-Now a number of these issues can be addressed by simply compiling your
-module for the exact specific kernel configuration, using the same exact
-C compiler that the kernel was built with.  This is sufficient if you
-want to provide a module for a specific release version of a specific
-Linux distribution.  But multiply that single build by the number of
-different Linux distributions and the number of different supported
-releases of the Linux distribution and you quickly have a nightmare of
-different build options on different releases.  Also realize that each
-Linux distribution release contains a number of different kernels, all
-tuned to different hardware types (different processor types and
-different options), so for even a single release you will need to create
-multiple versions of your module.
-
-Trust me, you will go insane over time if you try to support this kind
-of release, I learned this the hard way a long time ago...
-
-
-Stable Kernel Source Interfaces
--------------------------------
-
-This is a much more "volatile" topic if you talk to people who try to
-keep a Linux kernel driver that is not in the main kernel tree up to
-date over time.
-
-Linux kernel development is continuous and at a rapid pace, never
-stopping to slow down.  As such, the kernel developers find bugs in
-current interfaces, or figure out a better way to do things.  If they do
-that, they then fix the current interfaces to work better.  When they do
-so, function names may change, structures may grow or shrink, and
-function parameters may be reworked.  If this happens, all of the
-instances of where this interface is used within the kernel are fixed up
-at the same time, ensuring that everything continues to work properly.
-
-As a specific examples of this, the in-kernel USB interfaces have
-undergone at least three different reworks over the lifetime of this
-subsystem.  These reworks were done to address a number of different
-issues:
-
-  - A change from a synchronous model of data streams to an asynchronous
-    one.  This reduced the complexity of a number of drivers and
-    increased the throughput of all USB drivers such that we are now
-    running almost all USB devices at their maximum speed possible.
-  - A change was made in the way data packets were allocated from the
-    USB core by USB drivers so that all drivers now needed to provide
-    more information to the USB core to fix a number of documented
-    deadlocks.
-
-This is in stark contrast to a number of closed source operating systems
-which have had to maintain their older USB interfaces over time.  This
-provides the ability for new developers to accidentally use the old
-interfaces and do things in improper ways, causing the stability of the
-operating system to suffer.
-
-In both of these instances, all developers agreed that these were
-important changes that needed to be made, and they were made, with
-relatively little pain.  If Linux had to ensure that it will preserve a
-stable source interface, a new interface would have been created, and
-the older, broken one would have had to be maintained over time, leading
-to extra work for the USB developers.  Since all Linux USB developers do
-their work on their own time, asking programmers to do extra work for no
-gain, for free, is not a possibility.
-
-Security issues are also very important for Linux.  When a
-security issue is found, it is fixed in a very short amount of time.  A
-number of times this has caused internal kernel interfaces to be
-reworked to prevent the security problem from occurring.  When this
-happens, all drivers that use the interfaces were also fixed at the
-same time, ensuring that the security problem was fixed and could not
-come back at some future time accidentally.  If the internal interfaces
-were not allowed to change, fixing this kind of security problem and
-insuring that it could not happen again would not be possible.
-
-Kernel interfaces are cleaned up over time.  If there is no one using a
-current interface, it is deleted.  This ensures that the kernel remains
-as small as possible, and that all potential interfaces are tested as
-well as they can be (unused interfaces are pretty much impossible to
-test for validity.)
-
-
-What to do
-----------
-
-So, if you have a Linux kernel driver that is not in the main kernel
-tree, what are you, a developer, supposed to do?  Releasing a binary
-driver for every different kernel version for every distribution is a
-nightmare, and trying to keep up with an ever changing kernel interface
-is also a rough job.
-
-Simple, get your kernel driver into the main kernel tree (remember we
-are talking about GPL released drivers here, if your code doesn't fall
-under this category, good luck, you are on your own here, you leech
-<insert link to leech comment from Andrew and Linus here>.)  If your
-driver is in the tree, and a kernel interface changes, it will be fixed
-up by the person who did the kernel change in the first place.  This
-ensures that your driver is always buildable, and works over time, with
-very little effort on your part.
-
-The very good side effects of having your driver in the main kernel tree
-are:
-
-  - The quality of the driver will rise as the maintenance costs (to the
-    original developer) will decrease.
-  - Other developers will add features to your driver.
-  - Other people will find and fix bugs in your driver.
-  - Other people will find tuning opportunities in your driver.
-  - Other people will update the driver for you when external interface
-    changes require it.
-  - The driver automatically gets shipped in all Linux distributions
-    without having to ask the distros to add it.
-
-As Linux supports a larger number of different devices "out of the box"
-than any other operating system, and it supports these devices on more
-different processor architectures than any other operating system, this
-proven type of development model must be doing something right :)
-
-
-
-------
-
-Thanks to Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
-Robert Love, and Nishanth Aravamudan for their review and comments on
-early drafts of this paper.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/stable_kernel_rules.txt linux-libre-4.10-rc8-gnu/Documentation/stable_kernel_rules.txt
--- linux-libre-4.9-gnu/Documentation/stable_kernel_rules.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/stable_kernel_rules.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,181 +0,0 @@
-.. _stable_kernel_rules:
-
-Everything you ever wanted to know about Linux -stable releases
-===============================================================
-
-Rules on what kind of patches are accepted, and which ones are not, into the
-"-stable" tree:
-
- - It must be obviously correct and tested.
- - It cannot be bigger than 100 lines, with context.
- - It must fix only one thing.
- - It must fix a real bug that bothers people (not a, "This could be a
-   problem..." type thing).
- - It must fix a problem that causes a build error (but not for things
-   marked CONFIG_BROKEN), an oops, a hang, data corruption, a real
-   security issue, or some "oh, that's not good" issue.  In short, something
-   critical.
- - Serious issues as reported by a user of a distribution kernel may also
-   be considered if they fix a notable performance or interactivity issue.
-   As these fixes are not as obvious and have a higher risk of a subtle
-   regression they should only be submitted by a distribution kernel
-   maintainer and include an addendum linking to a bugzilla entry if it
-   exists and additional information on the user-visible impact.
- - New device IDs and quirks are also accepted.
- - No "theoretical race condition" issues, unless an explanation of how the
-   race can be exploited is also provided.
- - It cannot contain any "trivial" fixes in it (spelling changes,
-   whitespace cleanups, etc).
- - It must follow the
-   :ref:`Documentation/SubmittingPatches <submittingpatches>`
-   rules.
- - It or an equivalent fix must already exist in Linus' tree (upstream).
-
-
-Procedure for submitting patches to the -stable tree
-----------------------------------------------------
-
- - If the patch covers files in net/ or drivers/net please follow netdev stable
-   submission guidelines as described in
-   Documentation/networking/netdev-FAQ.txt
- - Security patches should not be handled (solely) by the -stable review
-   process but should follow the procedures in
-   :ref:`Documentation/SecurityBugs <securitybugs>`.
-
-For all other submissions, choose one of the following procedures
------------------------------------------------------------------
-
-.. _option_1:
-
-Option 1
-********
-
-To have the patch automatically included in the stable tree, add the tag
-
-.. code-block:: none
-
-     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.
-
-.. _option_2:
-
-Option 2
-********
-
-After the patch has been merged to Linus' tree, send an email to
-stable@vger.kernel.org containing the subject of the patch, the commit ID,
-why you think it should be applied, and what kernel version you wish it to
-be applied to.
-
-.. _option_3:
-
-Option 3
-********
-
-Send the patch, after verifying that it follows the above rules, to
-stable@vger.kernel.org.  You must note the upstream commit ID in the
-changelog of your submission, as well as the kernel version you wish
-it to be applied to.
-
-:ref:`option_1` is **strongly** preferred, is the easiest and most common.
-:ref:`option_2` and :ref:`option_3` are more useful if the patch isn't deemed
-worthy at the time it is applied to a public git tree (for instance, because
-it deserves more regression testing first).  :ref:`option_3` is especially
-useful if the patch needs some special handling to apply to an older kernel
-(e.g., if API's have changed in the meantime).
-
-Note that for :ref:`option_3`, if the patch deviates from the original
-upstream patch (for example because it had to be backported) this must be very
-clearly documented and justified in the patch description.
-
-The upstream commit ID must be specified with a separate line above the commit
-text, like this:
-
-.. code-block:: none
-
-    commit <sha1> upstream.
-
-Additionally, some patches submitted via Option 1 may have additional patch
-prerequisites which can be cherry-picked. This can be specified in the following
-format in the sign-off area:
-
-.. code-block:: none
-
-     Cc: <stable@vger.kernel.org> # 3.3.x: a1f84a3: sched: Check for idle
-     Cc: <stable@vger.kernel.org> # 3.3.x: 1b9508f: sched: Rate-limit newidle
-     Cc: <stable@vger.kernel.org> # 3.3.x: fd21073: sched: Fix affinity logic
-     Cc: <stable@vger.kernel.org> # 3.3.x
-     Signed-off-by: Ingo Molnar <mingo@elte.hu>
-
-The tag sequence has the meaning of:
-
-.. code-block:: none
-
-     git cherry-pick a1f84a3
-     git cherry-pick 1b9508f
-     git cherry-pick fd21073
-     git cherry-pick <this commit>
-
-Also, some patches may have kernel version prerequisites.  This can be
-specified in the following format in the sign-off area:
-
-.. code-block:: none
-
-     Cc: <stable@vger.kernel.org> # 3.3.x-
-
-The tag has the meaning of:
-
-.. code-block:: none
-
-     git cherry-pick <this commit>
-
-For each "-stable" tree starting with the specified version.
-
-Following the submission:
-
- - The sender will receive an ACK when the patch has been accepted into the
-   queue, or a NAK if the patch is rejected.  This response might take a few
-   days, according to the developer's schedules.
- - If accepted, the patch will be added to the -stable queue, for review by
-   other developers and by the relevant subsystem maintainer.
-
-
-Review cycle
-------------
-
- - When the -stable maintainers decide for a review cycle, the patches will be
-   sent to the review committee, and the maintainer of the affected area of
-   the patch (unless the submitter is the maintainer of the area) and CC: to
-   the linux-kernel mailing list.
- - The review committee has 48 hours in which to ACK or NAK the patch.
- - If the patch is rejected by a member of the committee, or linux-kernel
-   members object to the patch, bringing up issues that the maintainers and
-   members did not realize, the patch will be dropped from the queue.
- - At the end of the review cycle, the ACKed patches will be added to the
-   latest -stable release, and a new -stable release will happen.
- - Security patches will be accepted into the -stable tree directly from the
-   security kernel team, and not go through the normal review cycle.
-   Contact the kernel security team for more details on this procedure.
-
-Trees
------
-
- - The queues of patches, for both completed versions and in progress
-   versions can be found at:
-
-	http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git
-
- - The finalized and tagged releases of all stable kernels can be found
-   in separate branches per version at:
-
-	http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git
-
-
-Review committee
-----------------
-
- - This is made up of a number of kernel developers who have volunteered for
-   this task, and a few that haven't.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/SubmitChecklist linux-libre-4.10-rc8-gnu/Documentation/SubmitChecklist
--- linux-libre-4.9-gnu/Documentation/SubmitChecklist	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/SubmitChecklist	1969-12-31 19:00:00.000000000 -0500
@@ -1,120 +0,0 @@
-.. _submitchecklist:
-
-Linux Kernel patch submission checklist
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Here are some basic things that developers should do if they want to see their
-kernel patch submissions accepted more quickly.
-
-These are all above and beyond the documentation that is provided in
-:ref:`Documentation/SubmittingPatches <submittingpatches>`
-and elsewhere regarding submitting Linux kernel patches.
-
-
-1) If you use a facility then #include the file that defines/declares
-   that facility.  Don't depend on other header files pulling in ones
-   that you use.
-
-2) Builds cleanly:
-
-  a) with applicable or modified ``CONFIG`` options ``=y``, ``=m``, and
-     ``=n``.  No ``gcc`` warnings/errors, no linker warnings/errors.
-
-  b) Passes ``allnoconfig``, ``allmodconfig``
-
-  c) Builds successfully when using ``O=builddir``
-
-3) Builds on multiple CPU architectures by using local cross-compile tools
-   or some other build farm.
-
-4) ppc64 is a good architecture for cross-compilation checking because it
-   tends to use ``unsigned long`` for 64-bit quantities.
-
-5) Check your patch for general style as detailed in
-   :ref:`Documentation/CodingStyle <codingstyle>`.
-   Check for trivial violations with the patch style checker prior to
-   submission (``scripts/checkpatch.pl``).
-   You should be able to justify all violations that remain in
-   your patch.
-
-6) Any new or modified ``CONFIG`` options don't muck up the config menu.
-
-7) All new ``Kconfig`` options have help text.
-
-8) Has been carefully reviewed with respect to relevant ``Kconfig``
-   combinations.  This is very hard to get right with testing -- brainpower
-   pays off here.
-
-9) Check cleanly with sparse.
-
-10) Use ``make checkstack`` and ``make namespacecheck`` and fix any problems
-    that they find.
-
-    .. note::
-
-       ``checkstack`` does not point out problems explicitly,
-       but any one function that uses more than 512 bytes on the stack is a
-       candidate for change.
-
-11) Include :ref:`kernel-doc <kernel_doc>` to document global  kernel APIs.
-    (Not required for static functions, but OK there also.) Use
-    ``make htmldocs`` or ``make pdfdocs`` to check the
-    :ref:`kernel-doc <kernel_doc>` and fix any issues.
-
-12) Has been tested with ``CONFIG_PREEMPT``, ``CONFIG_DEBUG_PREEMPT``,
-    ``CONFIG_DEBUG_SLAB``, ``CONFIG_DEBUG_PAGEALLOC``, ``CONFIG_DEBUG_MUTEXES``,
-    ``CONFIG_DEBUG_SPINLOCK``, ``CONFIG_DEBUG_ATOMIC_SLEEP``,
-    ``CONFIG_PROVE_RCU`` and ``CONFIG_DEBUG_OBJECTS_RCU_HEAD`` all
-    simultaneously enabled.
-
-13) Has been build- and runtime tested with and without ``CONFIG_SMP`` and
-    ``CONFIG_PREEMPT.``
-
-14) If the patch affects IO/Disk, etc: has been tested with and without
-    ``CONFIG_LBDAF.``
-
-15) All codepaths have been exercised with all lockdep features enabled.
-
-16) All new ``/proc`` entries are documented under ``Documentation/``
-
-17) All new kernel boot parameters are documented in
-    ``Documentation/kernel-parameters.txt``.
-
-18) All new module parameters are documented with ``MODULE_PARM_DESC()``
-
-19) All new userspace interfaces are documented in ``Documentation/ABI/``.
-    See ``Documentation/ABI/README`` for more information.
-    Patches that change userspace interfaces should be CCed to
-    linux-api@vger.kernel.org.
-
-20) Check that it all passes ``make headers_check``.
-
-21) Has been checked with injection of at least slab and page-allocation
-    failures.  See ``Documentation/fault-injection/``.
-
-    If the new code is substantial, addition of subsystem-specific fault
-    injection might be appropriate.
-
-22) Newly-added code has been compiled with ``gcc -W`` (use
-    ``make EXTRA_CFLAGS=-W``).  This will generate lots of noise, but is good
-    for finding bugs like "warning: comparison between signed and unsigned".
-
-23) Tested after it has been merged into the -mm patchset to make sure
-    that it still works with all of the other queued patches and various
-    changes in the VM, VFS, and other subsystems.
-
-24) All memory barriers {e.g., ``barrier()``, ``rmb()``, ``wmb()``} need a
-    comment in the source code that explains the logic of what they are doing
-    and why.
-
-25) If any ioctl's are added by the patch, then also update
-    ``Documentation/ioctl/ioctl-number.txt``.
-
-26) If your modified source code depends on or uses any of the kernel
-    APIs or features that are related to the following ``Kconfig`` symbols,
-    then test multiple builds with the related ``Kconfig`` symbols disabled
-    and/or ``=m`` (if that option is available) [not all of these at the
-    same time, just various/random combinations of them]:
-
-    ``CONFIG_SMP``, ``CONFIG_SYSFS``, ``CONFIG_PROC_FS``, ``CONFIG_INPUT``, ``CONFIG_PCI``, ``CONFIG_BLOCK``, ``CONFIG_PM``, ``CONFIG_MAGIC_SYSRQ``,
-    ``CONFIG_NET``, ``CONFIG_INET=n`` (but latter with ``CONFIG_NET=y``).
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/SubmittingDrivers linux-libre-4.10-rc8-gnu/Documentation/SubmittingDrivers
--- linux-libre-4.9-gnu/Documentation/SubmittingDrivers	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/SubmittingDrivers	1969-12-31 19:00:00.000000000 -0500
@@ -1,183 +0,0 @@
-.. _submittingdrivers:
-
-Submitting Drivers For The Linux Kernel
-=======================================
-
-This document is intended to explain how to submit device drivers to the
-various kernel trees. Note that if you are interested in video card drivers
-you should probably talk to XFree86 (http://www.xfree86.org/) and/or X.Org
-(http://x.org/) instead.
-
-Also read the Documentation/SubmittingPatches document.
-
-
-Allocating Device Numbers
--------------------------
-
-Major and minor numbers for block and character devices are allocated
-by the Linux assigned name and number authority (currently this is
-Torben Mathiasen). The site is http://www.lanana.org/. This
-also deals with allocating numbers for devices that are not going to
-be submitted to the mainstream kernel.
-See Documentation/devices.txt for more information on this.
-
-If you don't use assigned numbers then when your device is submitted it will
-be given an assigned number even if that is different from values you may
-have shipped to customers before.
-
-Who To Submit Drivers To
-------------------------
-
-Linux 2.0:
-	No new drivers are accepted for this kernel tree.
-
-Linux 2.2:
-	No new drivers are accepted for this kernel tree.
-
-Linux 2.4:
-	If the code area has a general maintainer then please submit it to
-	the maintainer listed in MAINTAINERS in the kernel file. If the
-	maintainer does not respond or you cannot find the appropriate
-	maintainer then please contact Willy Tarreau <w@1wt.eu>.
-
-Linux 2.6 and upper:
-	The same rules apply as 2.4 except that you should follow linux-kernel
-	to track changes in API's. The final contact point for Linux 2.6+
-	submissions is Andrew Morton.
-
-What Criteria Determine Acceptance
-----------------------------------
-
-Licensing:
-		The code must be released to us under the
-		GNU General Public License. We don't insist on any kind
-		of exclusive GPL licensing, and if you wish the driver
-		to be useful to other communities such as BSD you may well
-		wish to release under multiple licenses.
-		See accepted licenses at include/linux/module.h
-
-Copyright:
-		The copyright owner must agree to use of GPL.
-		It's best if the submitter and copyright owner
-		are the same person/entity. If not, the name of
-		the person/entity authorizing use of GPL should be
-		listed in case it's necessary to verify the will of
-		the copyright owner.
-
-Interfaces:
-		If your driver uses existing interfaces and behaves like
-		other drivers in the same class it will be much more likely
-		to be accepted than if it invents gratuitous new ones.
-		If you need to implement a common API over Linux and NT
-		drivers do it in userspace.
-
-Code:
-		Please use the Linux style of code formatting as documented
-		in :ref:`Documentation/CodingStyle <codingStyle>`.
-		If you have sections of code
-		that need to be in other formats, for example because they
-		are shared with a windows driver kit and you want to
-		maintain them just once separate them out nicely and note
-		this fact.
-
-Portability:
-		Pointers are not always 32bits, not all computers are little
-		endian, people do not all have floating point and you
-		shouldn't use inline x86 assembler in your driver without
-		careful thought. Pure x86 drivers generally are not popular.
-		If you only have x86 hardware it is hard to test portability
-		but it is easy to make sure the code can easily be made
-		portable.
-
-Clarity:
-		It helps if anyone can see how to fix the driver. It helps
-		you because you get patches not bug reports. If you submit a
-		driver that intentionally obfuscates how the hardware works
-		it will go in the bitbucket.
-
-PM support:
-		Since Linux is used on many portable and desktop systems, your
-		driver is likely to be used on such a system and therefore it
-		should support basic power management by implementing, if
-		necessary, the .suspend and .resume methods used during the
-		system-wide suspend and resume transitions.  You should verify
-		that your driver correctly handles the suspend and resume, but
-		if you are unable to ensure that, please at least define the
-		.suspend method returning the -ENOSYS ("Function not
-		implemented") error.  You should also try to make sure that your
-		driver uses as little power as possible when it's not doing
-		anything.  For the driver testing instructions see
-		Documentation/power/drivers-testing.txt and for a relatively
-		complete overview of the power management issues related to
-		drivers see Documentation/power/devices.txt .
-
-Control:
-		In general if there is active maintenance of a driver by
-		the author then patches will be redirected to them unless
-		they are totally obvious and without need of checking.
-		If you want to be the contact and update point for the
-		driver it is a good idea to state this in the comments,
-		and include an entry in MAINTAINERS for your driver.
-
-What Criteria Do Not Determine Acceptance
------------------------------------------
-
-Vendor:
-		Being the hardware vendor and maintaining the driver is
-		often a good thing. If there is a stable working driver from
-		other people already in the tree don't expect 'we are the
-		vendor' to get your driver chosen. Ideally work with the
-		existing driver author to build a single perfect driver.
-
-Author:
-		It doesn't matter if a large Linux company wrote the driver,
-		or you did. Nobody has any special access to the kernel
-		tree. Anyone who tells you otherwise isn't telling the
-		whole story.
-
-
-Resources
----------
-
-Linux kernel master tree:
-	ftp.\ *country_code*\ .kernel.org:/pub/linux/kernel/...
-
-	where *country_code* == your country code, such as
-	**us**, **uk**, **fr**, etc.
-
-	http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git
-
-Linux kernel mailing list:
-	linux-kernel@vger.kernel.org
-	[mail majordomo@vger.kernel.org to subscribe]
-
-Linux Device Drivers, Third Edition (covers 2.6.10):
-	http://lwn.net/Kernel/LDD3/  (free version)
-
-LWN.net:
-	Weekly summary of kernel development activity - http://lwn.net/
-
-	2.6 API changes:
-
-		http://lwn.net/Articles/2.6-kernel-api/
-
-	Porting drivers from prior kernels to 2.6:
-
-		http://lwn.net/Articles/driver-porting/
-
-KernelNewbies:
-	Documentation and assistance for new kernel programmers
-
-		http://kernelnewbies.org/
-
-Linux USB project:
-	http://www.linux-usb.org/
-
-How to NOT write kernel driver by Arjan van de Ven:
-	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
-
-Kernel Janitor:
-	http://kernelnewbies.org/KernelJanitors
-
-GIT, Fast Version Control System:
-	http://git-scm.com/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/SubmittingPatches linux-libre-4.10-rc8-gnu/Documentation/SubmittingPatches
--- linux-libre-4.9-gnu/Documentation/SubmittingPatches	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/SubmittingPatches	2017-02-12 16:03:20.000000000 -0500
@@ -1,841 +1 @@
-.. _submittingpatches:
-
-How to Get Your Change Into the Linux Kernel or Care And Operation Of Your Linus Torvalds
-=========================================================================================
-
-For a person or company who wishes to submit a change to the Linux
-kernel, the process can sometimes be daunting if you're not familiar
-with "the system."  This text is a collection of suggestions which
-can greatly increase the chances of your change being accepted.
-
-This document contains a large number of suggestions in a relatively terse
-format.  For detailed information on how the kernel development process
-works, see :ref:`Documentation/development-process <development_process_main>`.
-Also, read :ref:`Documentation/SubmitChecklist <submitchecklist>`
-for a list of items to check before
-submitting code.  If you are submitting a driver, also read
-:ref:`Documentation/SubmittingDrivers <submittingdrivers>`;
-for device tree binding patches, read
-Documentation/devicetree/bindings/submitting-patches.txt.
-
-Many of these steps describe the default behavior of the ``git`` version
-control system; if you use ``git`` to prepare your patches, you'll find much
-of the mechanical work done for you, though you'll still need to prepare
-and document a sensible set of patches.  In general, use of ``git`` will make
-your life as a kernel developer easier.
-
-Creating and Sending your Change
-********************************
-
-
-0) Obtain a current source tree
--------------------------------
-
-If you do not have a repository with the current kernel source handy, use
-``git`` to obtain one.  You'll want to start with the mainline repository,
-which can be grabbed with::
-
-  git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
-
-Note, however, that you may not want to develop against the mainline tree
-directly.  Most subsystem maintainers run their own trees and want to see
-patches prepared against those trees.  See the **T:** entry for the subsystem
-in the MAINTAINERS file to find that tree, or simply ask the maintainer if
-the tree is not listed there.
-
-It is still possible to download kernel releases via tarballs (as described
-in the next section), but that is the hard way to do kernel development.
-
-1) ``diff -up``
----------------
-
-If you must generate your patches by hand, use ``diff -up`` or ``diff -uprN``
-to create patches.  Git generates patches in this form by default; if
-you're using ``git``, you can skip this section entirely.
-
-All changes to the Linux kernel occur in the form of patches, as
-generated by :manpage:`diff(1)`.  When creating your patch, make sure to
-create it in "unified diff" format, as supplied by the ``-u`` argument
-to :manpage:`diff(1)`.
-Also, please use the ``-p`` argument which shows which C function each
-change is in - that makes the resultant ``diff`` a lot easier to read.
-Patches should be based in the root kernel source directory,
-not in any lower subdirectory.
-
-To create a patch for a single file, it is often sufficient to do::
-
-	SRCTREE= linux
-	MYFILE=  drivers/net/mydriver.c
-
-	cd $SRCTREE
-	cp $MYFILE $MYFILE.orig
-	vi $MYFILE	# make your change
-	cd ..
-	diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
-
-To create a patch for multiple files, you should unpack a "vanilla",
-or unmodified kernel source tree, and generate a ``diff`` against your
-own source tree.  For example::
-
-	MYSRC= /devel/linux
-
-	tar xvfz linux-3.19.tar.gz
-	mv linux-3.19 linux-3.19-vanilla
-	diff -uprN -X linux-3.19-vanilla/Documentation/dontdiff \
-		linux-3.19-vanilla $MYSRC > /tmp/patch
-
-``dontdiff`` is a list of files which are generated by the kernel during
-the build process, and should be ignored in any :manpage:`diff(1)`-generated
-patch.
-
-Make sure your patch does not include any extra files which do not
-belong in a patch submission.  Make sure to review your patch -after-
-generating it with :manpage:`diff(1)`, to ensure accuracy.
-
-If your changes produce a lot of deltas, you need to split them into
-individual patches which modify things in logical stages; see
-:ref:`split_changes`.  This will facilitate review by other kernel developers,
-very important if you want your patch accepted.
-
-If you're using ``git``, ``git rebase -i`` can help you with this process.  If
-you're not using ``git``, ``quilt`` <http://savannah.nongnu.org/projects/quilt>
-is another popular alternative.
-
-.. _describe_changes:
-
-2) Describe your changes
-------------------------
-
-Describe your problem.  Whether your patch is a one-line bug fix or
-5000 lines of a new feature, there must be an underlying problem that
-motivated you to do this work.  Convince the reviewer that there is a
-problem worth fixing and that it makes sense for them to read past the
-first paragraph.
-
-Describe user-visible impact.  Straight up crashes and lockups are
-pretty convincing, but not all bugs are that blatant.  Even if the
-problem was spotted during code review, describe the impact you think
-it can have on users.  Keep in mind that the majority of Linux
-installations run kernels from secondary stable trees or
-vendor/product-specific trees that cherry-pick only specific patches
-from upstream, so include anything that could help route your change
-downstream: provoking circumstances, excerpts from dmesg, crash
-descriptions, performance regressions, latency spikes, lockups, etc.
-
-Quantify optimizations and trade-offs.  If you claim improvements in
-performance, memory consumption, stack footprint, or binary size,
-include numbers that back them up.  But also describe non-obvious
-costs.  Optimizations usually aren't free but trade-offs between CPU,
-memory, and readability; or, when it comes to heuristics, between
-different workloads.  Describe the expected downsides of your
-optimization so that the reviewer can weigh costs against benefits.
-
-Once the problem is established, describe what you are actually doing
-about it in technical detail.  It's important to describe the change
-in plain English for the reviewer to verify that the code is behaving
-as you intend it to.
-
-The maintainer will thank you if you write your patch description in a
-form which can be easily pulled into Linux's source code management
-system, ``git``, as a "commit log".  See :ref:`explicit_in_reply_to`.
-
-Solve only one problem per patch.  If your description starts to get
-long, that's a sign that you probably need to split up your patch.
-See :ref:`split_changes`.
-
-When you submit or resubmit a patch or patch series, include the
-complete patch description and justification for it.  Don't just
-say that this is version N of the patch (series).  Don't expect the
-subsystem maintainer to refer back to earlier patch versions or referenced
-URLs to find the patch description and put that into the patch.
-I.e., the patch (series) and its description should be self-contained.
-This benefits both the maintainers and reviewers.  Some reviewers
-probably didn't even receive earlier versions of the patch.
-
-Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
-instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
-to do frotz", as if you are giving orders to the codebase to change
-its behaviour.
-
-If the patch fixes a logged bug entry, refer to that bug entry by
-number and URL.  If the patch follows from a mailing list discussion,
-give a URL to the mailing list archive; use the https://lkml.kernel.org/
-redirector with a ``Message-Id``, to ensure that the links cannot become
-stale.
-
-However, try to make your explanation understandable without external
-resources.  In addition to giving a URL to a mailing list archive or
-bug, summarize the relevant points of the discussion that led to the
-patch as submitted.
-
-If you want to refer to a specific commit, don't just refer to the
-SHA-1 ID of the commit. Please also include the oneline summary of
-the commit, to make it easier for reviewers to know what it is about.
-Example::
-
-	Commit e21d2170f36602ae2708 ("video: remove unnecessary
-	platform_set_drvdata()") removed the unnecessary
-	platform_set_drvdata(), but left the variable "dev" unused,
-	delete it.
-
-You should also be sure to use at least the first twelve characters of the
-SHA-1 ID.  The kernel repository holds a *lot* of objects, making
-collisions with shorter IDs a real possibility.  Bear in mind that, even if
-there is no collision with your six-character ID now, that condition may
-change five years from now.
-
-If your patch fixes a bug in a specific commit, e.g. you found an issue using
-``git bisect``, please use the 'Fixes:' tag with the first 12 characters of
-the SHA-1 ID, and the one line summary.  For example::
-
-	Fixes: e21d2170f366 ("video: remove unnecessary platform_set_drvdata()")
-
-The following ``git config`` settings can be used to add a pretty format for
-outputting the above style in the ``git log`` or ``git show`` commands::
-
-	[core]
-		abbrev = 12
-	[pretty]
-		fixes = Fixes: %h (\"%s\")
-
-.. _split_changes:
-
-3) Separate your changes
-------------------------
-
-Separate each **logical change** into a separate patch.
-
-For example, if your changes include both bug fixes and performance
-enhancements for a single driver, separate those changes into two
-or more patches.  If your changes include an API update, and a new
-driver which uses that new API, separate those into two patches.
-
-On the other hand, if you make a single change to numerous files,
-group those changes into a single patch.  Thus a single logical change
-is contained within a single patch.
-
-The point to remember is that each patch should make an easily understood
-change that can be verified by reviewers.  Each patch should be justifiable
-on its own merits.
-
-If one patch depends on another patch in order for a change to be
-complete, that is OK.  Simply note **"this patch depends on patch X"**
-in your patch description.
-
-When dividing your change into a series of patches, take special care to
-ensure that the kernel builds and runs properly after each patch in the
-series.  Developers using ``git bisect`` to track down a problem can end up
-splitting your patch series at any point; they will not thank you if you
-introduce bugs in the middle.
-
-If you cannot condense your patch set into a smaller set of patches,
-then only post say 15 or so at a time and wait for review and integration.
-
-
-
-4) Style-check your changes
----------------------------
-
-Check your patch for basic style violations, details of which can be
-found in
-:ref:`Documentation/CodingStyle <codingstyle>`.
-Failure to do so simply wastes
-the reviewers time and will get your patch rejected, probably
-without even being read.
-
-One significant exception is when moving code from one file to
-another -- in this case you should not modify the moved code at all in
-the same patch which moves it.  This clearly delineates the act of
-moving the code and your changes.  This greatly aids review of the
-actual differences and allows tools to better track the history of
-the code itself.
-
-Check your patches with the patch style checker prior to submission
-(scripts/checkpatch.pl).  Note, though, that the style checker should be
-viewed as a guide, not as a replacement for human judgment.  If your code
-looks better with a violation then its probably best left alone.
-
-The checker reports at three levels:
- - ERROR: things that are very likely to be wrong
- - WARNING: things requiring careful review
- - CHECK: things requiring thought
-
-You should be able to justify all violations that remain in your
-patch.
-
-
-5) Select the recipients for your patch
----------------------------------------
-
-You should always copy the appropriate subsystem maintainer(s) on any patch
-to code that they maintain; look through the MAINTAINERS file and the
-source code revision history to see who those maintainers are.  The
-script scripts/get_maintainer.pl can be very useful at this step.  If you
-cannot find a maintainer for the subsystem you are working on, Andrew
-Morton (akpm@linux-foundation.org) serves as a maintainer of last resort.
-
-You should also normally choose at least one mailing list to receive a copy
-of your patch set.  linux-kernel@vger.kernel.org functions as a list of
-last resort, but the volume on that list has caused a number of developers
-to tune it out.  Look in the MAINTAINERS file for a subsystem-specific
-list; your patch will probably get more attention there.  Please do not
-spam unrelated lists, though.
-
-Many kernel-related lists are hosted on vger.kernel.org; you can find a
-list of them at http://vger.kernel.org/vger-lists.html.  There are
-kernel-related lists hosted elsewhere as well, though.
-
-Do not send more than 15 patches at once to the vger mailing lists!!!
-
-Linus Torvalds is the final arbiter of all changes accepted into the
-Linux kernel.  His e-mail address is <torvalds@linux-foundation.org>.
-He gets a lot of e-mail, and, at this point, very few patches go through
-Linus directly, so typically you should do your best to -avoid-
-sending him e-mail.
-
-If you have a patch that fixes an exploitable security bug, send that patch
-to security@kernel.org.  For severe bugs, a short embargo may be considered
-to allow distributors to get the patch out to users; in such cases,
-obviously, the patch should not be sent to any public lists.
-
-Patches that fix a severe bug in a released kernel should be directed
-toward the stable maintainers by putting a line like this::
-
-  Cc: stable@vger.kernel.org
-
-into the sign-off area of your patch (note, NOT an email recipient).  You
-should also read
-:ref:`Documentation/stable_kernel_rules.txt <stable_kernel_rules>`
-in addition to this file.
-
-Note, however, that some subsystem maintainers want to come to their own
-conclusions on which patches should go to the stable trees.  The networking
-maintainer, in particular, would rather not see individual developers
-adding lines like the above to their patches.
-
-If changes affect userland-kernel interfaces, please send the MAN-PAGES
-maintainer (as listed in the MAINTAINERS file) a man-pages patch, or at
-least a notification of the change, so that some information makes its way
-into the manual pages.  User-space API changes should also be copied to
-linux-api@vger.kernel.org.
-
-For small patches you may want to CC the Trivial Patch Monkey
-trivial@kernel.org which collects "trivial" patches. Have a look
-into the MAINTAINERS file for its current manager.
-
-Trivial patches must qualify for one of the following rules:
-
-- Spelling fixes in documentation
-- Spelling fixes for errors which could break :manpage:`grep(1)`
-- Warning fixes (cluttering with useless warnings is bad)
-- Compilation fixes (only if they are actually correct)
-- Runtime fixes (only if they actually fix things)
-- Removing use of deprecated functions/macros
-- Contact detail and documentation fixes
-- Non-portable code replaced by portable code (even in arch-specific,
-  since people copy, as long as it's trivial)
-- Any fix by the author/maintainer of the file (ie. patch monkey
-  in re-transmission mode)
-
-
-
-6) No MIME, no links, no compression, no attachments.  Just plain text
-----------------------------------------------------------------------
-
-Linus and other kernel developers need to be able to read and comment
-on the changes you are submitting.  It is important for a kernel
-developer to be able to "quote" your changes, using standard e-mail
-tools, so that they may comment on specific portions of your code.
-
-For this reason, all patches should be submitted by e-mail "inline".
-
-.. warning::
-
-  Be wary of your editor's word-wrap corrupting your patch,
-  if you choose to cut-n-paste your patch.
-
-Do not attach the patch as a MIME attachment, compressed or not.
-Many popular e-mail applications will not always transmit a MIME
-attachment as plain text, making it impossible to comment on your
-code.  A MIME attachment also takes Linus a bit more time to process,
-decreasing the likelihood of your MIME-attached change being accepted.
-
-Exception:  If your mailer is mangling patches then someone may ask
-you to re-send them using MIME.
-
-See :ref:`Documentation/email-clients.txt <email_clients>`
-for hints about configuring your e-mail client so that it sends your patches
-untouched.
-
-7) E-mail size
---------------
-
-Large changes are not appropriate for mailing lists, and some
-maintainers.  If your patch, uncompressed, exceeds 300 kB in size,
-it is preferred that you store your patch on an Internet-accessible
-server, and provide instead a URL (link) pointing to your patch.  But note
-that if your patch exceeds 300 kB, it almost certainly needs to be broken up
-anyway.
-
-8) Respond to review comments
------------------------------
-
-Your patch will almost certainly get comments from reviewers on ways in
-which the patch can be improved.  You must respond to those comments;
-ignoring reviewers is a good way to get ignored in return.  Review comments
-or questions that do not lead to a code change should almost certainly
-bring about a comment or changelog entry so that the next reviewer better
-understands what is going on.
-
-Be sure to tell the reviewers what changes you are making and to thank them
-for their time.  Code review is a tiring and time-consuming process, and
-reviewers sometimes get grumpy.  Even in that case, though, respond
-politely and address the problems they have pointed out.
-
-
-9) Don't get discouraged - or impatient
----------------------------------------
-
-After you have submitted your change, be patient and wait.  Reviewers are
-busy people and may not get to your patch right away.
-
-Once upon a time, patches used to disappear into the void without comment,
-but the development process works more smoothly than that now.  You should
-receive comments within a week or so; if that does not happen, make sure
-that you have sent your patches to the right place.  Wait for a minimum of
-one week before resubmitting or pinging reviewers - possibly longer during
-busy times like merge windows.
-
-
-10) Include PATCH in the subject
---------------------------------
-
-Due to high e-mail traffic to Linus, and to linux-kernel, it is common
-convention to prefix your subject line with [PATCH].  This lets Linus
-and other kernel developers more easily distinguish patches from other
-e-mail discussions.
-
-
-
-11) Sign your work
-------------------
-
-To improve tracking of who did what, especially with patches that can
-percolate to their final resting place in the kernel through several
-layers of maintainers, we've introduced a "sign-off" procedure on
-patches that are being emailed around.
-
-The sign-off is a simple line at the end of the explanation for the
-patch, which certifies that you wrote it or otherwise have the right to
-pass it on as an open-source patch.  The rules are pretty simple: if you
-can certify the below:
-
-Developer's Certificate of Origin 1.1
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-By making a contribution to this project, I certify that:
-
-        (a) The contribution was created in whole or in part by me and I
-            have the right to submit it under the open source license
-            indicated in the file; or
-
-        (b) The contribution is based upon previous work that, to the best
-            of my knowledge, is covered under an appropriate open source
-            license and I have the right under that license to submit that
-            work with modifications, whether created in whole or in part
-            by me, under the same open source license (unless I am
-            permitted to submit under a different license), as indicated
-            in the file; or
-
-        (c) The contribution was provided directly to me by some other
-            person who certified (a), (b) or (c) and I have not modified
-            it.
-
-        (d) I understand and agree that this project and the contribution
-            are public and that a record of the contribution (including all
-            personal information I submit with it, including my sign-off) is
-            maintained indefinitely and may be redistributed consistent with
-            this project or the open source license(s) involved.
-
-then you just add a line saying::
-
-	Signed-off-by: Random J Developer <random@developer.example.org>
-
-using your real name (sorry, no pseudonyms or anonymous contributions.)
-
-Some people also put extra tags at the end.  They'll just be ignored for
-now, but you can do this to mark internal company procedures or just
-point out some special detail about the sign-off.
-
-If you are a subsystem or branch maintainer, sometimes you need to slightly
-modify patches you receive in order to merge them, because the code is not
-exactly the same in your tree and the submitters'. If you stick strictly to
-rule (c), you should ask the submitter to rediff, but this is a totally
-counter-productive waste of time and energy. Rule (b) allows you to adjust
-the code, but then it is very impolite to change one submitter's code and
-make him endorse your bugs. To solve this problem, it is recommended that
-you add a line between the last Signed-off-by header and yours, indicating
-the nature of your changes. While there is nothing mandatory about this, it
-seems like prepending the description with your mail and/or name, all
-enclosed in square brackets, is noticeable enough to make it obvious that
-you are responsible for last-minute changes. Example::
-
-	Signed-off-by: Random J Developer <random@developer.example.org>
-	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
-	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
-
-This practice is particularly helpful if you maintain a stable branch and
-want at the same time to credit the author, track changes, merge the fix,
-and protect the submitter from complaints. Note that under no circumstances
-can you change the author's identity (the From header), as it is the one
-which appears in the changelog.
-
-Special note to back-porters: It seems to be a common and useful practice
-to insert an indication of the origin of a patch at the top of the commit
-message (just after the subject line) to facilitate tracking. For instance,
-here's what we see in a 3.x-stable release::
-
-  Date:   Tue Oct 7 07:26:38 2014 -0400
-
-    libata: Un-break ATA blacklist
-
-    commit 1c40279960bcd7d52dbdf1d466b20d24b99176c8 upstream.
-
-And here's what might appear in an older kernel once a patch is backported::
-
-    Date:   Tue May 13 22:12:27 2008 +0200
-
-        wireless, airo: waitbusy() won't delay
-
-        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
-
-Whatever the format, this information provides a valuable help to people
-tracking your trees, and to people trying to troubleshoot bugs in your
-tree.
-
-
-12) When to use Acked-by: and Cc:
----------------------------------
-
-The Signed-off-by: tag indicates that the signer was involved in the
-development of the patch, or that he/she was in the patch's delivery path.
-
-If a person was not directly involved in the preparation or handling of a
-patch but wishes to signify and record their approval of it then they can
-ask to have an Acked-by: line added to the patch's changelog.
-
-Acked-by: is often used by the maintainer of the affected code when that
-maintainer neither contributed to nor forwarded the patch.
-
-Acked-by: is not as formal as Signed-off-by:.  It is a record that the acker
-has at least reviewed the patch and has indicated acceptance.  Hence patch
-mergers will sometimes manually convert an acker's "yep, looks good to me"
-into an Acked-by: (but note that it is usually better to ask for an
-explicit ack).
-
-Acked-by: does not necessarily indicate acknowledgement of the entire patch.
-For example, if a patch affects multiple subsystems and has an Acked-by: from
-one subsystem maintainer then this usually indicates acknowledgement of just
-the part which affects that maintainer's code.  Judgement should be used here.
-When in doubt people should refer to the original discussion in the mailing
-list archives.
-
-If a person has had the opportunity to comment on a patch, but has not
-provided such comments, you may optionally add a ``Cc:`` tag to the patch.
-This is the only tag which might be added without an explicit action by the
-person it names - but it should indicate that this person was copied on the
-patch.  This tag documents that potentially interested parties
-have been included in the discussion.
-
-
-13) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes:
---------------------------------------------------------------------------
-
-The Reported-by tag gives credit to people who find bugs and report them and it
-hopefully inspires them to help us again in the future.  Please note that if
-the bug was reported in private, then ask for permission first before using the
-Reported-by tag.
-
-A Tested-by: tag indicates that the patch has been successfully tested (in
-some environment) by the person named.  This tag informs maintainers that
-some testing has been performed, provides a means to locate testers for
-future patches, and ensures credit for the testers.
-
-Reviewed-by:, instead, indicates that the patch has been reviewed and found
-acceptable according to the Reviewer's Statement:
-
-Reviewer's statement of oversight
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-By offering my Reviewed-by: tag, I state that:
-
-	 (a) I have carried out a technical review of this patch to
-	     evaluate its appropriateness and readiness for inclusion into
-	     the mainline kernel.
-
-	 (b) Any problems, concerns, or questions relating to the patch
-	     have been communicated back to the submitter.  I am satisfied
-	     with the submitter's response to my comments.
-
-	 (c) While there may be things that could be improved with this
-	     submission, I believe that it is, at this time, (1) a
-	     worthwhile modification to the kernel, and (2) free of known
-	     issues which would argue against its inclusion.
-
-	 (d) While I have reviewed the patch and believe it to be sound, I
-	     do not (unless explicitly stated elsewhere) make any
-	     warranties or guarantees that it will achieve its stated
-	     purpose or function properly in any given situation.
-
-A Reviewed-by tag is a statement of opinion that the patch is an
-appropriate modification of the kernel without any remaining serious
-technical issues.  Any interested reviewer (who has done the work) can
-offer a Reviewed-by tag for a patch.  This tag serves to give credit to
-reviewers and to inform maintainers of the degree of review which has been
-done on the patch.  Reviewed-by: tags, when supplied by reviewers known to
-understand the subject area and to perform thorough reviews, will normally
-increase the likelihood of your patch getting into the kernel.
-
-A Suggested-by: tag indicates that the patch idea is suggested by the person
-named and ensures credit to the person for the idea. Please note that this
-tag should not be added without the reporter's permission, especially if the
-idea was not posted in a public forum. That said, if we diligently credit our
-idea reporters, they will, hopefully, be inspired to help us again in the
-future.
-
-A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
-is used to make it easy to determine where a bug originated, which can help
-review a bug fix. This tag also assists the stable kernel team in determining
-which stable kernel versions should receive your fix. This is the preferred
-method for indicating a bug fixed by the patch. See :ref:`describe_changes`
-for more details.
-
-
-14) The canonical patch format
-------------------------------
-
-This section describes how the patch itself should be formatted.  Note
-that, if you have your patches stored in a ``git`` repository, proper patch
-formatting can be had with ``git format-patch``.  The tools cannot create
-the necessary text, though, so read the instructions below anyway.
-
-The canonical patch subject line is::
-
-    Subject: [PATCH 001/123] subsystem: summary phrase
-
-The canonical patch message body contains the following:
-
-  - A ``from`` line specifying the patch author (only needed if the person
-    sending the patch is not the author).
-
-  - An empty line.
-
-  - The body of the explanation, line wrapped at 75 columns, which will
-    be copied to the permanent changelog to describe this patch.
-
-  - The ``Signed-off-by:`` lines, described above, which will
-    also go in the changelog.
-
-  - A marker line containing simply ``---``.
-
-  - Any additional comments not suitable for the changelog.
-
-  - The actual patch (``diff`` output).
-
-The Subject line format makes it very easy to sort the emails
-alphabetically by subject line - pretty much any email reader will
-support that - since because the sequence number is zero-padded,
-the numerical and alphabetic sort is the same.
-
-The ``subsystem`` in the email's Subject should identify which
-area or subsystem of the kernel is being patched.
-
-The ``summary phrase`` in the email's Subject should concisely
-describe the patch which that email contains.  The ``summary
-phrase`` should not be a filename.  Do not use the same ``summary
-phrase`` for every patch in a whole patch series (where a ``patch
-series`` is an ordered sequence of multiple, related patches).
-
-Bear in mind that the ``summary phrase`` of your email becomes a
-globally-unique identifier for that patch.  It propagates all the way
-into the ``git`` changelog.  The ``summary phrase`` may later be used in
-developer discussions which refer to the patch.  People will want to
-google for the ``summary phrase`` to read discussion regarding that
-patch.  It will also be the only thing that people may quickly see
-when, two or three months later, they are going through perhaps
-thousands of patches using tools such as ``gitk`` or ``git log
---oneline``.
-
-For these reasons, the ``summary`` must be no more than 70-75
-characters, and it must describe both what the patch changes, as well
-as why the patch might be necessary.  It is challenging to be both
-succinct and descriptive, but that is what a well-written summary
-should do.
-
-The ``summary phrase`` may be prefixed by tags enclosed in square
-brackets: "Subject: [PATCH <tag>...] <summary phrase>".  The tags are
-not considered part of the summary phrase, but describe how the patch
-should be treated.  Common tags might include a version descriptor if
-the multiple versions of the patch have been sent out in response to
-comments (i.e., "v1, v2, v3"), or "RFC" to indicate a request for
-comments.  If there are four patches in a patch series the individual
-patches may be numbered like this: 1/4, 2/4, 3/4, 4/4.  This assures
-that developers understand the order in which the patches should be
-applied and that they have reviewed or applied all of the patches in
-the patch series.
-
-A couple of example Subjects::
-
-    Subject: [PATCH 2/5] ext2: improve scalability of bitmap searching
-    Subject: [PATCH v2 01/27] x86: fix eflags tracking
-
-The ``from`` line must be the very first line in the message body,
-and has the form:
-
-        From: Original Author <author@example.com>
-
-The ``from`` line specifies who will be credited as the author of the
-patch in the permanent changelog.  If the ``from`` line is missing,
-then the ``From:`` line from the email header will be used to determine
-the patch author in the changelog.
-
-The explanation body will be committed to the permanent source
-changelog, so should make sense to a competent reader who has long
-since forgotten the immediate details of the discussion that might
-have led to this patch.  Including symptoms of the failure which the
-patch addresses (kernel log messages, oops messages, etc.) is
-especially useful for people who might be searching the commit logs
-looking for the applicable patch.  If a patch fixes a compile failure,
-it may not be necessary to include _all_ of the compile failures; just
-enough that it is likely that someone searching for the patch can find
-it.  As in the ``summary phrase``, it is important to be both succinct as
-well as descriptive.
-
-The ``---`` marker line serves the essential purpose of marking for patch
-handling tools where the changelog message ends.
-
-One good use for the additional comments after the ``---`` marker is for
-a ``diffstat``, to show what files have changed, and the number of
-inserted and deleted lines per file.  A ``diffstat`` is especially useful
-on bigger patches.  Other comments relevant only to the moment or the
-maintainer, not suitable for the permanent changelog, should also go
-here.  A good example of such comments might be ``patch changelogs``
-which describe what has changed between the v1 and v2 version of the
-patch.
-
-If you are going to include a ``diffstat`` after the ``---`` marker, please
-use ``diffstat`` options ``-p 1 -w 70`` so that filenames are listed from
-the top of the kernel source tree and don't use too much horizontal
-space (easily fit in 80 columns, maybe with some indentation).  (``git``
-generates appropriate diffstats by default.)
-
-See more details on the proper patch format in the following
-references.
-
-.. _explicit_in_reply_to:
-
-15) Explicit In-Reply-To headers
---------------------------------
-
-It can be helpful to manually add In-Reply-To: headers to a patch
-(e.g., when using ``git send-email``) to associate the patch with
-previous relevant discussion, e.g. to link a bug fix to the email with
-the bug report.  However, for a multi-patch series, it is generally
-best to avoid using In-Reply-To: to link to older versions of the
-series.  This way multiple versions of the patch don't become an
-unmanageable forest of references in email clients.  If a link is
-helpful, you can use the https://lkml.kernel.org/ redirector (e.g., in
-the cover email text) to link to an earlier version of the patch series.
-
-
-16) Sending ``git pull`` requests
----------------------------------
-
-If you have a series of patches, it may be most convenient to have the
-maintainer pull them directly into the subsystem repository with a
-``git pull`` operation.  Note, however, that pulling patches from a developer
-requires a higher degree of trust than taking patches from a mailing list.
-As a result, many subsystem maintainers are reluctant to take pull
-requests, especially from new, unknown developers.  If in doubt you can use
-the pull request as the cover letter for a normal posting of the patch
-series, giving the maintainer the option of using either.
-
-A pull request should have [GIT] or [PULL] in the subject line.  The
-request itself should include the repository name and the branch of
-interest on a single line; it should look something like::
-
-  Please pull from
-
-      git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
-
-  to get these changes:
-
-A pull request should also include an overall message saying what will be
-included in the request, a ``git shortlog`` listing of the patches
-themselves, and a ``diffstat`` showing the overall effect of the patch series.
-The easiest way to get all this information together is, of course, to let
-``git`` do it for you with the ``git request-pull`` command.
-
-Some maintainers (including Linus) want to see pull requests from signed
-commits; that increases their confidence that the request actually came
-from you.  Linus, in particular, will not pull from public hosting sites
-like GitHub in the absence of a signed tag.
-
-The first step toward creating such tags is to make a GNUPG key and get it
-signed by one or more core kernel developers.  This step can be hard for
-new developers, but there is no way around it.  Attending conferences can
-be a good way to find developers who can sign your key.
-
-Once you have prepared a patch series in ``git`` that you wish to have somebody
-pull, create a signed tag with ``git tag -s``.  This will create a new tag
-identifying the last commit in the series and containing a signature
-created with your private key.  You will also have the opportunity to add a
-changelog-style message to the tag; this is an ideal place to describe the
-effects of the pull request as a whole.
-
-If the tree the maintainer will be pulling from is not the repository you
-are working from, don't forget to push the signed tag explicitly to the
-public tree.
-
-When generating your pull request, use the signed tag as the target.  A
-command like this will do the trick::
-
-  git request-pull master git://my.public.tree/linux.git my-signed-tag
-
-
-REFERENCES
-**********
-
-Andrew Morton, "The perfect patch" (tpp).
-  <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
-
-Jeff Garzik, "Linux kernel patch submission format".
-  <http://linux.yyz.us/patch-format.html>
-
-Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
-  <http://www.kroah.com/log/linux/maintainer.html>
-
-  <http://www.kroah.com/log/linux/maintainer-02.html>
-
-  <http://www.kroah.com/log/linux/maintainer-03.html>
-
-  <http://www.kroah.com/log/linux/maintainer-04.html>
-
-  <http://www.kroah.com/log/linux/maintainer-05.html>
-
-  <http://www.kroah.com/log/linux/maintainer-06.html>
-
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
-  <https://lkml.org/lkml/2005/7/11/336>
-
-Kernel Documentation/CodingStyle:
-  :ref:`Documentation/CodingStyle <codingstyle>`
-
-Linus Torvalds's mail on the canonical patch format:
-  <http://lkml.org/lkml/2005/4/7/183>
-
-Andi Kleen, "On submitting kernel patches"
-  Some strategies to get difficult or controversial changes in.
-
-  http://halobates.de/on-submitting-patches.pdf
-
+This file has moved to process/submitting-patches.rst
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sync_file.txt linux-libre-4.10-rc8-gnu/Documentation/sync_file.txt
--- linux-libre-4.9-gnu/Documentation/sync_file.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sync_file.txt	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
 
 This document serves as a guide for device drivers writers on what the
 sync_file API is, and how drivers can support it. Sync file is the carrier of
-the fences(struct fence) that are needed to synchronize between drivers or
+the fences(struct dma_fence) that are needed to synchronize between drivers or
 across process boundaries.
 
 The sync_file API is meant to be used to send and receive fence information
@@ -32,9 +32,9 @@ in-fences and out-fences
 Sync files can go either to or from userspace. When a sync_file is sent from
 the driver to userspace we call the fences it contains 'out-fences'. They are
 related to a buffer that the driver is processing or is going to process, so
-the driver creates an out-fence to be able to notify, through fence_signal(),
-when it has finished using (or processing) that buffer. Out-fences are fences
-that the driver creates.
+the driver creates an out-fence to be able to notify, through
+dma_fence_signal(), when it has finished using (or processing) that buffer.
+Out-fences are fences that the driver creates.
 
 On the other hand if the driver receives fence(s) through a sync_file from
 userspace we call these fence(s) 'in-fences'. Receiveing in-fences means that
@@ -47,7 +47,7 @@ Creating Sync Files
 When a driver needs to send an out-fence userspace it creates a sync_file.
 
 Interface:
-	struct sync_file *sync_file_create(struct fence *fence);
+	struct sync_file *sync_file_create(struct dma_fence *fence);
 
 The caller pass the out-fence and gets back the sync_file. That is just the
 first step, next it needs to install an fd on sync_file->file. So it gets an
@@ -72,11 +72,11 @@ of the Sync File to the kernel. The kern
 from it.
 
 Interface:
-	struct fence *sync_file_get_fence(int fd);
+	struct dma_fence *sync_file_get_fence(int fd);
 
 
 The returned reference is owned by the caller and must be disposed of
-afterwards using fence_put(). In case of error, a NULL is returned instead.
+afterwards using dma_fence_put(). In case of error, a NULL is returned instead.
 
 References:
 [1] struct sync_file in include/linux/sync_file.h
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sysctl/kernel.txt linux-libre-4.10-rc8-gnu/Documentation/sysctl/kernel.txt
--- linux-libre-4.9-gnu/Documentation/sysctl/kernel.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sysctl/kernel.txt	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,6 @@ show up in /proc/sys/kernel:
 - hung_task_warnings
 - kexec_load_disabled
 - kptr_restrict
-- kstack_depth_to_print       [ X86 only ]
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/debugging-modules.txt
 - modules_disabled
@@ -71,7 +70,7 @@ show up in /proc/sys/kernel:
 - printk_ratelimit_burst
 - pty                         ==> Documentation/filesystems/devpts.txt
 - randomize_va_space
-- real-root-dev               ==> Documentation/initrd.txt
+- real-root-dev               ==> Documentation/admin-guide/initrd.rst
 - reboot-cmd                  [ SPARC only ]
 - rtsig-max
 - rtsig-nr
@@ -395,13 +394,6 @@ When kptr_restrict is set to (2), kernel
 
 ==============================================================
 
-kstack_depth_to_print: (X86 only)
-
-Controls the number of words to print when dumping the raw
-kernel stack.
-
-==============================================================
-
 l2cr: (PPC only)
 
 This flag controls the L2 cache of G3 processor boards. If
@@ -453,7 +445,7 @@ in a KVM virtual machine. This default c
 
    nmi_watchdog=1
 
-to the guest kernel command line (see Documentation/kernel-parameters.txt).
+to the guest kernel command line (see Documentation/admin-guide/kernel-parameters.rst).
 
 ==============================================================
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sysfs-rules.txt linux-libre-4.10-rc8-gnu/Documentation/sysfs-rules.txt
--- linux-libre-4.9-gnu/Documentation/sysfs-rules.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sysfs-rules.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,184 +0,0 @@
-Rules on how to access information in the Linux kernel sysfs
-
-The kernel-exported sysfs exports internal kernel implementation details
-and depends on internal kernel structures and layout. It is agreed upon
-by the kernel developers that the Linux kernel does not provide a stable
-internal API. Therefore, there are aspects of the sysfs interface that
-may not be stable across kernel releases.
-
-To minimize the risk of breaking users of sysfs, which are in most cases
-low-level userspace applications, with a new kernel release, the users
-of sysfs must follow some rules to use an as-abstract-as-possible way to
-access this filesystem. The current udev and HAL programs already
-implement this and users are encouraged to plug, if possible, into the
-abstractions these programs provide instead of accessing sysfs directly.
-
-But if you really do want or need to access sysfs directly, please follow
-the following rules and then your programs should work with future
-versions of the sysfs interface.
-
-- Do not use libsysfs
-  It makes assumptions about sysfs which are not true. Its API does not
-  offer any abstraction, it exposes all the kernel driver-core
-  implementation details in its own API. Therefore it is not better than
-  reading directories and opening the files yourself.
-  Also, it is not actively maintained, in the sense of reflecting the
-  current kernel development. The goal of providing a stable interface
-  to sysfs has failed; it causes more problems than it solves. It
-  violates many of the rules in this document.
-
-- sysfs is always at /sys
-  Parsing /proc/mounts is a waste of time. Other mount points are a
-  system configuration bug you should not try to solve. For test cases,
-  possibly support a SYSFS_PATH environment variable to overwrite the
-  application's behavior, but never try to search for sysfs. Never try
-  to mount it, if you are not an early boot script.
-
-- devices are only "devices"
-  There is no such thing like class-, bus-, physical devices,
-  interfaces, and such that you can rely on in userspace. Everything is
-  just simply a "device". Class-, bus-, physical, ... types are just
-  kernel implementation details which should not be expected by
-  applications that look for devices in sysfs.
-
-  The properties of a device are:
-    o devpath (/devices/pci0000:00/0000:00:1d.1/usb2/2-2/2-2:1.0)
-      - identical to the DEVPATH value in the event sent from the kernel
-        at device creation and removal
-      - the unique key to the device at that point in time
-      - the kernel's path to the device directory without the leading
-        /sys, and always starting with a slash
-      - all elements of a devpath must be real directories. Symlinks
-        pointing to /sys/devices must always be resolved to their real
-        target and the target path must be used to access the device.
-        That way the devpath to the device matches the devpath of the
-        kernel used at event time.
-      - using or exposing symlink values as elements in a devpath string
-        is a bug in the application
-
-    o kernel name (sda, tty, 0000:00:1f.2, ...)
-      - a directory name, identical to the last element of the devpath
-      - applications need to handle spaces and characters like '!' in
-        the name
-
-    o subsystem (block, tty, pci, ...)
-      - simple string, never a path or a link
-      - retrieved by reading the "subsystem"-link and using only the
-        last element of the target path
-
-    o driver (tg3, ata_piix, uhci_hcd)
-      - a simple string, which may contain spaces, never a path or a
-        link
-      - it is retrieved by reading the "driver"-link and using only the
-        last element of the target path
-      - devices which do not have "driver"-link just do not have a
-        driver; copying the driver value in a child device context is a
-        bug in the application
-
-    o attributes
-      - the files in the device directory or files below subdirectories
-        of the same device directory
-      - accessing attributes reached by a symlink pointing to another device,
-        like the "device"-link, is a bug in the application
-
-  Everything else is just a kernel driver-core implementation detail
-  that should not be assumed to be stable across kernel releases.
-
-- Properties of parent devices never belong into a child device.
-  Always look at the parent devices themselves for determining device
-  context properties. If the device 'eth0' or 'sda' does not have a
-  "driver"-link, then this device does not have a driver. Its value is empty.
-  Never copy any property of the parent-device into a child-device. Parent
-  device properties may change dynamically without any notice to the
-  child device.
-
-- Hierarchy in a single device tree
-  There is only one valid place in sysfs where hierarchy can be examined
-  and this is below: /sys/devices.
-  It is planned that all device directories will end up in the tree
-  below this directory.
-
-- Classification by subsystem
-  There are currently three places for classification of devices:
-  /sys/block, /sys/class and /sys/bus. It is planned that these will
-  not contain any device directories themselves, but only flat lists of
-  symlinks pointing to the unified /sys/devices tree.
-  All three places have completely different rules on how to access
-  device information. It is planned to merge all three
-  classification directories into one place at /sys/subsystem,
-  following the layout of the bus directories. All buses and
-  classes, including the converted block subsystem, will show up
-  there.
-  The devices belonging to a subsystem will create a symlink in the
-  "devices" directory at /sys/subsystem/<name>/devices.
-
-  If /sys/subsystem exists, /sys/bus, /sys/class and /sys/block can be
-  ignored. If it does not exist, you always have to scan all three
-  places, as the kernel is free to move a subsystem from one place to
-  the other, as long as the devices are still reachable by the same
-  subsystem name.
-
-  Assuming /sys/class/<subsystem> and /sys/bus/<subsystem>, or
-  /sys/block and /sys/class/block are not interchangeable is a bug in
-  the application.
-
-- Block
-  The converted block subsystem at /sys/class/block or
-  /sys/subsystem/block will contain the links for disks and partitions
-  at the same level, never in a hierarchy. Assuming the block subsystem to
-  contain only disks and not partition devices in the same flat list is
-  a bug in the application.
-
-- "device"-link and <subsystem>:<kernel name>-links
-  Never depend on the "device"-link. The "device"-link is a workaround
-  for the old layout, where class devices are not created in
-  /sys/devices/ like the bus devices. If the link-resolving of a
-  device directory does not end in /sys/devices/, you can use the
-  "device"-link to find the parent devices in /sys/devices/. That is the
-  single valid use of the "device"-link; it must never appear in any
-  path as an element. Assuming the existence of the "device"-link for
-  a device in /sys/devices/ is a bug in the application.
-  Accessing /sys/class/net/eth0/device is a bug in the application.
-
-  Never depend on the class-specific links back to the /sys/class
-  directory.  These links are also a workaround for the design mistake
-  that class devices are not created in /sys/devices. If a device
-  directory does not contain directories for child devices, these links
-  may be used to find the child devices in /sys/class. That is the single
-  valid use of these links; they must never appear in any path as an
-  element. Assuming the existence of these links for devices which are
-  real child device directories in the /sys/devices tree is a bug in
-  the application.
-
-  It is planned to remove all these links when all class device
-  directories live in /sys/devices.
-
-- Position of devices along device chain can change.
-  Never depend on a specific parent device position in the devpath,
-  or the chain of parent devices. The kernel is free to insert devices into
-  the chain. You must always request the parent device you are looking for
-  by its subsystem value. You need to walk up the chain until you find
-  the device that matches the expected subsystem. Depending on a specific
-  position of a parent device or exposing relative paths using "../" to
-  access the chain of parents is a bug in the application.
-
-- When reading and writing sysfs device attribute files, avoid dependency
-  on specific error codes wherever possible. This minimizes coupling to
-  the error handling implementation within the kernel.
-
-  In general, failures to read or write sysfs device attributes shall
-  propagate errors wherever possible. Common errors include, but are not
-  limited to:
-
-  -EIO: The read or store operation is not supported, typically returned by
-        the sysfs system itself if the read or store pointer is NULL.
-
-  -ENXIO: The read or store operation failed
-
-  Error codes will not be changed without good reason, and should a change
-  to error codes result in user-space breakage, it will be fixed, or the
-  the offending change will be reverted.
-
-  Userspace applications can, however, expect the format and contents of
-  the attribute files to remain consistent in the absence of a version
-  attribute change in the context of a given attribute.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/sysrq.txt linux-libre-4.10-rc8-gnu/Documentation/sysrq.txt
--- linux-libre-4.9-gnu/Documentation/sysrq.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/sysrq.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,257 +0,0 @@
-Linux Magic System Request Key Hacks
-Documentation for sysrq.c
-
-*  What is the magic SysRq key?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-It is a 'magical' key combo you can hit which the kernel will respond to
-regardless of whatever else it is doing, unless it is completely locked up.
-
-*  How do I enable the magic SysRq key?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
-configuring the kernel. When running a kernel with SysRq compiled in,
-/proc/sys/kernel/sysrq controls the functions allowed to be invoked via
-the SysRq key. The default value in this file is set by the
-CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults
-to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
-   0 - disable sysrq completely
-   1 - enable all functions of sysrq
-  >1 - bitmask of allowed sysrq functions (see below for detailed function
-       description):
-          2 =   0x2 - enable control of console logging level
-          4 =   0x4 - enable control of keyboard (SAK, unraw)
-          8 =   0x8 - enable debugging dumps of processes etc.
-         16 =  0x10 - enable sync command
-         32 =  0x20 - enable remount read-only
-         64 =  0x40 - enable signalling of processes (term, kill, oom-kill)
-        128 =  0x80 - allow reboot/poweroff
-        256 = 0x100 - allow nicing of all RT tasks
-
-You can set the value in the file by the following command:
-    echo "number" >/proc/sys/kernel/sysrq
-
-The number may be written here either as decimal or as hexadecimal
-with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be
-written in hexadecimal.
-
-Note that the value of /proc/sys/kernel/sysrq influences only the invocation
-via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
-allowed (by a user with admin privileges).
-
-*  How do I use the magic SysRq key?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-On x86   - You press the key combo 'ALT-SysRq-<command key>'. Note - Some
-           keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
-           also known as the 'Print Screen' key. Also some keyboards cannot
-	   handle so many keys being pressed at the same time, so you might
-	   have better luck with "press Alt", "press SysRq", "release SysRq",
-	   "press <command key>", release everything.
-
-On SPARC - You press 'ALT-STOP-<command key>', I believe.
-
-On the serial console (PC style standard serial ports only) -
-           You send a BREAK, then within 5 seconds a command key. Sending
-           BREAK twice is interpreted as a normal BREAK.
-
-On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,  
-             Print Screen (or F13) - <command key> may suffice.
-
-On other - If you know of the key combos for other architectures, please
-           let me know so I can add them to this section.
-
-On all -  write a character to /proc/sysrq-trigger.  e.g.:
-
-		echo t > /proc/sysrq-trigger
-
-*  What are the 'command' keys?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-'b'     - Will immediately reboot the system without syncing or unmounting
-          your disks.
-
-'c'	- Will perform a system crash by a NULL pointer dereference.
-          A crashdump will be taken if configured.
-
-'d'	- Shows all locks that are held.
-
-'e'     - Send a SIGTERM to all processes, except for init.
-
-'f'	- Will call the oom killer to kill a memory hog process, but do not
-	  panic if nothing can be killed.
-
-'g'	- Used by kgdb (kernel debugger)
-
-'h'     - Will display help (actually any other key than those listed
-          here will display help. but 'h' is easy to remember :-)
-
-'i'     - Send a SIGKILL to all processes, except for init.
-
-'j'     - Forcibly "Just thaw it" - filesystems frozen by the FIFREEZE ioctl.
-
-'k'     - Secure Access Key (SAK) Kills all programs on the current virtual
-          console. NOTE: See important comments below in SAK section.
-
-'l'     - Shows a stack backtrace for all active CPUs.
-
-'m'     - Will dump current memory info to your console.
-
-'n'	- Used to make RT tasks nice-able
-
-'o'     - Will shut your system off (if configured and supported).
-
-'p'     - Will dump the current registers and flags to your console.
-
-'q'     - Will dump per CPU lists of all armed hrtimers (but NOT regular
-          timer_list timers) and detailed information about all
-          clockevent devices.
-
-'r'     - Turns off keyboard raw mode and sets it to XLATE.
-
-'s'     - Will attempt to sync all mounted filesystems.
-
-'t'     - Will dump a list of current tasks and their information to your
-          console.
-
-'u'     - Will attempt to remount all mounted filesystems read-only.
-
-'v'	- Forcefully restores framebuffer console
-'v'	- Causes ETM buffer dump [ARM-specific]
-
-'w'	- Dumps tasks that are in uninterruptable (blocked) state.
-
-'x'	- Used by xmon interface on ppc/powerpc platforms.
-          Show global PMU Registers on sparc64.
-          Dump all TLB entries on MIPS.
-
-'y'	- Show global CPU Registers [SPARC-64 specific]
-
-'z'	- Dump the ftrace buffer
-
-'0'-'9' - Sets the console log level, controlling which kernel messages
-          will be printed to your console. ('0', for example would make
-          it so that only emergency messages like PANICs or OOPSes would
-          make it to your console.)
-
-*  Okay, so what can I use them for?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Well, unraw(r) is very handy when your X server or a svgalib program crashes.
-
-sak(k) (Secure Access Key) is useful when you want to be sure there is no
-trojan program running at console which could grab your password
-when you would try to login. It will kill all programs on given console,
-thus letting you make sure that the login prompt you see is actually
-the one from init, not some trojan program.
-IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
-IMPORTANT: c2 compliant system, and it should not be mistaken as   :IMPORTANT
-IMPORTANT: such.                                                   :IMPORTANT
-       It seems others find it useful as (System Attention Key) which is
-useful when you want to exit a program that will not let you switch consoles.
-(For example, X or a svgalib program.)
-
-reboot(b) is good when you're unable to shut down. But you should also
-sync(s) and umount(u) first.
-
-crash(c) can be used to manually trigger a crashdump when the system is hung.
-Note that this just triggers a crash if there is no dump mechanism available.
-
-sync(s) is great when your system is locked up, it allows you to sync your
-disks and will certainly lessen the chance of data loss and fscking. Note
-that the sync hasn't taken place until you see the "OK" and "Done" appear
-on the screen. (If the kernel is really in strife, you may not ever get the
-OK or Done message...)
-
-umount(u) is basically useful in the same ways as sync(s). I generally sync(s),
-umount(u), then reboot(b) when my system locks. It's saved me many a fsck.
-Again, the unmount (remount read-only) hasn't taken place until you see the
-"OK" and "Done" message appear on the screen.
-
-The loglevels '0'-'9' are useful when your console is being flooded with
-kernel messages you do not want to see. Selecting '0' will prevent all but
-the most urgent kernel messages from reaching your console. (They will
-still be logged if syslogd/klogd are alive, though.)
-
-term(e) and kill(i) are useful if you have some sort of runaway process you
-are unable to kill any other way, especially if it's spawning other
-processes.
-
-"just thaw it(j)" is useful if your system becomes unresponsive due to a frozen
-(probably root) filesystem via the FIFREEZE ioctl.
-
-*  Sometimes SysRq seems to get 'stuck' after using it, what can I do?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-That happens to me, also. I've found that tapping shift, alt, and control
-on both sides of the keyboard, and hitting an invalid sysrq sequence again
-will fix the problem. (i.e., something like alt-sysrq-z). Switching to another
-virtual console (ALT+Fn) and then back again should also help.
-
-*  I hit SysRq, but nothing seems to happen, what's wrong?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There are some keyboards that produce a different keycode for SysRq than the
-pre-defined value of 99 (see KEY_SYSRQ in include/linux/input.h), or which
-don't have a SysRq key at all. In these cases, run 'showkey -s' to find an
-appropriate scancode sequence, and use 'setkeycodes <sequence> 99' to map
-this sequence to the usual SysRq code (e.g., 'setkeycodes e05b 99'). It's
-probably best to put this command in a boot script. Oh, and by the way, you
-exit 'showkey' by not typing anything for ten seconds.
-
-*  I want to add SysRQ key events to a module, how does it work?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In order to register a basic function with the table, you must first include
-the header 'include/linux/sysrq.h', this will define everything else you need.
-Next, you must create a sysrq_key_op struct, and populate it with A) the key
-handler function you will use, B) a help_msg string, that will print when SysRQ
-prints help, and C) an action_msg string, that will print right before your
-handler is called. Your handler must conform to the prototype in 'sysrq.h'.
-
-After the sysrq_key_op is created, you can call the kernel function
-register_sysrq_key(int key, struct sysrq_key_op *op_p); this will
-register the operation pointed to by 'op_p' at table key 'key',
-if that slot in the table is blank. At module unload time, you must call
-the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
-will remove the key op pointed to by 'op_p' from the key 'key', if and only if
-it is currently registered in that slot. This is in case the slot has been
-overwritten since you registered it.
-
-The Magic SysRQ system works by registering key operations against a key op
-lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
-a number of operations registered into it at compile time, but is mutable,
-and 2 functions are exported for interface to it:
-	register_sysrq_key and unregister_sysrq_key.
-Of course, never ever leave an invalid pointer in the table. I.e., when
-your module that called register_sysrq_key() exits, it must call
-unregister_sysrq_key() to clean up the sysrq key table entry that it used.
-Null pointers in the table are always safe. :)
-
-If for some reason you feel the need to call the handle_sysrq function from
-within a function called by handle_sysrq, you must be aware that you are in
-a lock (you are also in an interrupt handler, which means don't sleep!), so
-you must call __handle_sysrq_nolock instead.
-
-*  When I hit a SysRq key combination only the header appears on the console?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Sysrq output is subject to the same console loglevel control as all
-other console output.  This means that if the kernel was booted 'quiet'
-as is common on distro kernels the output may not appear on the actual
-console, even though it will appear in the dmesg buffer, and be accessible
-via the dmesg command and to the consumers of /proc/kmsg.  As a specific
-exception the header line from the sysrq command is passed to all console
-consumers as if the current loglevel was maximum.  If only the header
-is emitted it is almost certain that the kernel loglevel is too low.
-Should you require the output on the console channel then you will need
-to temporarily up the console loglevel using alt-sysrq-8 or:
-
-    echo 8 > /proc/sysrq-trigger
-
-Remember to return the loglevel to normal after triggering the sysrq
-command you are interested in.
-
-*  I have more questions, who can I ask?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Just ask them on the linux-kernel mailing list:
-	linux-kernel@vger.kernel.org
-
-*  Credits
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Written by Mydraal <vulpyne@vulpyne.net>
-Updated by Adam Sulmicki <adam@cfar.umd.edu>
-Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
-Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/tpm/tpm_vtpm_proxy.txt linux-libre-4.10-rc8-gnu/Documentation/tpm/tpm_vtpm_proxy.txt
--- linux-libre-4.9-gnu/Documentation/tpm/tpm_vtpm_proxy.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/tpm/tpm_vtpm_proxy.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-Virtual TPM Proxy Driver for Linux Containers
-
-Authors: Stefan Berger (IBM)
-
-This document describes the virtual Trusted Platform Module (vTPM)
-proxy device driver for Linux containers.
-
-INTRODUCTION
-------------
-
-The goal of this work is to provide TPM functionality to each Linux
-container. This allows programs to interact with a TPM in a container
-the same way they interact with a TPM on the physical system. Each
-container gets its own unique, emulated, software TPM.
-
-
-DESIGN
-------
-
-To make an emulated software TPM available to each container, the container
-management stack needs to create a device pair consisting of a client TPM
-character device /dev/tpmX (with X=0,1,2...) and a 'server side' file
-descriptor. The former is moved into the container by creating a character
-device with the appropriate major and minor numbers while the file descriptor
-is passed to the TPM emulator. Software inside the container can then send
-TPM commands using the character device and the emulator will receive the
-commands via the file descriptor and use it for sending back responses.
-
-To support this, the virtual TPM proxy driver provides a device /dev/vtpmx
-that is used to create device pairs using an ioctl. The ioctl takes as
-an input flags for configuring the device. The flags  for example indicate
-whether TPM 1.2 or TPM 2 functionality is supported by the TPM emulator.
-The result of the ioctl are the file descriptor for the 'server side'
-as well as the major and minor numbers of the character device that was created.
-Besides that the number of the TPM character device is return. If for
-example /dev/tpm10 was created, the number (dev_num) 10 is returned.
-
-The following is the data structure of the TPM_PROXY_IOC_NEW_DEV ioctl:
-
-struct vtpm_proxy_new_dev {
-	__u32 flags;         /* input */
-	__u32 tpm_num;       /* output */
-	__u32 fd;            /* output */
-	__u32 major;         /* output */
-	__u32 minor;         /* output */
-};
-
-Note that if unsupported flags are passed to the device driver, the ioctl will
-fail and errno will be set to EOPNOTSUPP. Similarly, if an unsupported ioctl is
-called on the device driver, the ioctl will fail and errno will be set to
-ENOTTY.
-
-See /usr/include/linux/vtpm_proxy.h for definitions related to the public interface
-of this vTPM device driver.
-
-Once the device has been created, the driver will immediately try to talk
-to the TPM. All commands from the driver can be read from the file descriptor
-returned by the ioctl. The commands should be responded to immediately.
-
-Depending on the version of TPM the following commands will be sent by the
-driver:
-
-- TPM 1.2:
-  - the driver will send a TPM_Startup command to the TPM emulator
-  - the driver will send commands to read the command durations and
-    interface timeouts from the TPM emulator
-- TPM 2:
-  - the driver will send a TPM2_Startup command to the TPM emulator
-
-The TPM device /dev/tpmX will only appear if all of the relevant commands
-were responded to properly.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/tpm/xen-tpmfront.txt linux-libre-4.10-rc8-gnu/Documentation/tpm/xen-tpmfront.txt
--- linux-libre-4.9-gnu/Documentation/tpm/xen-tpmfront.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/tpm/xen-tpmfront.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,113 +0,0 @@
-Virtual TPM interface for Xen
-
-Authors: Matthew Fioravante (JHUAPL), Daniel De Graaf (NSA)
-
-This document describes the virtual Trusted Platform Module (vTPM) subsystem for
-Xen. The reader is assumed to have familiarity with building and installing Xen,
-Linux, and a basic understanding of the TPM and vTPM concepts.
-
-INTRODUCTION
-
-The goal of this work is to provide a TPM functionality to a virtual guest
-operating system (in Xen terms, a DomU).  This allows programs to interact with
-a TPM in a virtual system the same way they interact with a TPM on the physical
-system.  Each guest gets its own unique, emulated, software TPM.  However, each
-of the vTPM's secrets (Keys, NVRAM, etc) are managed by a vTPM Manager domain,
-which seals the secrets to the Physical TPM.  If the process of creating each of
-these domains (manager, vTPM, and guest) is trusted, the vTPM subsystem extends
-the chain of trust rooted in the hardware TPM to virtual machines in Xen. Each
-major component of vTPM is implemented as a separate domain, providing secure
-separation guaranteed by the hypervisor. The vTPM domains are implemented in
-mini-os to reduce memory and processor overhead.
-
-This mini-os vTPM subsystem was built on top of the previous vTPM work done by
-IBM and Intel corporation.
-
-
-DESIGN OVERVIEW
----------------
-
-The architecture of vTPM is described below:
-
-+------------------+
-|    Linux DomU    | ...
-|       |  ^       |
-|       v  |       |
-|   xen-tpmfront   |
-+------------------+
-        |  ^
-        v  |
-+------------------+
-| mini-os/tpmback  |
-|       |  ^       |
-|       v  |       |
-|  vtpm-stubdom    | ...
-|       |  ^       |
-|       v  |       |
-| mini-os/tpmfront |
-+------------------+
-        |  ^
-        v  |
-+------------------+
-| mini-os/tpmback  |
-|       |  ^       |
-|       v  |       |
-| vtpmmgr-stubdom  |
-|       |  ^       |
-|       v  |       |
-| mini-os/tpm_tis  |
-+------------------+
-        |  ^
-        v  |
-+------------------+
-|   Hardware TPM   |
-+------------------+
-
- * Linux DomU: The Linux based guest that wants to use a vTPM. There may be
-	       more than one of these.
-
- * xen-tpmfront.ko: Linux kernel virtual TPM frontend driver. This driver
-                    provides vTPM access to a Linux-based DomU.
-
- * mini-os/tpmback: Mini-os TPM backend driver. The Linux frontend driver
-		    connects to this backend driver to facilitate communications
-		    between the Linux DomU and its vTPM. This driver is also
-		    used by vtpmmgr-stubdom to communicate with vtpm-stubdom.
-
- * vtpm-stubdom: A mini-os stub domain that implements a vTPM. There is a
-		 one to one mapping between running vtpm-stubdom instances and
-                 logical vtpms on the system. The vTPM Platform Configuration
-                 Registers (PCRs) are normally all initialized to zero.
-
- * mini-os/tpmfront: Mini-os TPM frontend driver. The vTPM mini-os domain
-		     vtpm-stubdom uses this driver to communicate with
-		     vtpmmgr-stubdom. This driver is also used in mini-os
-		     domains such as pv-grub that talk to the vTPM domain.
-
- * vtpmmgr-stubdom: A mini-os domain that implements the vTPM manager. There is
-		    only one vTPM manager and it should be running during the
-		    entire lifetime of the machine.  This domain regulates
-		    access to the physical TPM on the system and secures the
-		    persistent state of each vTPM.
-
- * mini-os/tpm_tis: Mini-os TPM version 1.2 TPM Interface Specification (TIS)
-                    driver. This driver used by vtpmmgr-stubdom to talk directly to
-                    the hardware TPM. Communication is facilitated by mapping
-                    hardware memory pages into vtpmmgr-stubdom.
-
- * Hardware TPM: The physical TPM that is soldered onto the motherboard.
-
-
-INTEGRATION WITH XEN
---------------------
-
-Support for the vTPM driver was added in Xen using the libxl toolstack in Xen
-4.3.  See the Xen documentation (docs/misc/vtpm.txt) for details on setting up
-the vTPM and vTPM Manager stub domains.  Once the stub domains are running, a
-vTPM device is set up in the same manner as a disk or network device in the
-domain's configuration file.
-
-In order to use features such as IMA that require a TPM to be loaded prior to
-the initrd, the xen-tpmfront driver must be compiled in to the kernel.  If not
-using such features, the driver can be compiled as a module and will be loaded
-as usual.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/trace/events.txt linux-libre-4.10-rc8-gnu/Documentation/trace/events.txt
--- linux-libre-4.9-gnu/Documentation/trace/events.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/trace/events.txt	2017-02-12 16:03:20.000000000 -0500
@@ -189,16 +189,13 @@ And for string fields they are:
 
 ==, !=, ~
 
-The glob (~) only accepts a wild card character (*) at the start and or
-end of the string. For example:
+The glob (~) accepts a wild card character (*,?) and character classes
+([). For example:
 
   prev_comm ~ "*sh"
   prev_comm ~ "sh*"
   prev_comm ~ "*sh*"
-
-But does not allow for it to be within the string:
-
-  prev_comm ~ "ba*sh"   <-- is invalid
+  prev_comm ~ "ba*sh"
 
 5.2 Setting filters
 -------------------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/trace/ftrace.txt linux-libre-4.10-rc8-gnu/Documentation/trace/ftrace.txt
--- linux-libre-4.9-gnu/Documentation/trace/ftrace.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/trace/ftrace.txt	2017-02-12 16:03:20.000000000 -0500
@@ -362,6 +362,26 @@ of ftrace. Here is a list of some of the
 		  to correlate events across hypervisor/guest if
 		  tb_offset is known.
 
+	  mono: This uses the fast monotonic clock (CLOCK_MONOTONIC)
+		which is monotonic and is subject to NTP rate adjustments.
+
+	  mono_raw:
+		This is the raw monotonic clock (CLOCK_MONOTONIC_RAW)
+		which is montonic but is not subject to any rate adjustments
+		and ticks at the same rate as the hardware clocksource.
+
+	  boot: This is the boot clock (CLOCK_BOOTTIME) and is based on the
+		fast monotonic clock, but also accounts for time spent in
+		suspend. Since the clock access is designed for use in
+		tracing in the suspend path, some side effects are possible
+		if clock is accessed after the suspend time is accounted before
+		the fast mono clock is updated. In this case, the clock update
+		appears to happen slightly sooner than it normally would have.
+		Also on 32-bit systems, it's possible that the 64-bit boot offset
+		sees a partial update. These effects are rare and post
+		processing should be able to handle them. See comments in the
+		ktime_get_boot_fast_ns() function for more information.
+
 	To set a clock, simply echo the clock name into this file.
 
 	  echo global > trace_clock
@@ -396,6 +416,12 @@ of ftrace. Here is a list of some of the
 
 		trace_fd = open("trace_marker", WR_ONLY);
 
+  trace_marker_raw:
+
+	This is similar to trace_marker above, but is meant for for binary data
+	to be written to it, where a tool can be used to parse the data
+	from trace_pipe_raw.
+
   uprobe_events:
  
 	Add dynamic tracepoints in programs.
@@ -2218,16 +2244,13 @@ hrtimer_interrupt
 sys_nanosleep
 
 
-Perhaps this is not enough. The filters also allow simple wild
-cards. Only the following are currently available
+Perhaps this is not enough. The filters also allow glob(7) matching.
 
   <match>*  - will match functions that begin with <match>
   *<match>  - will match functions that end with <match>
   *<match>* - will match functions that have <match> in it
-
-These are the only wild cards which are supported.
-
-  <match>*<match> will not work.
+  <match1>*<match2> - will match functions that begin with
+                      <match1> and end with <match2>
 
 Note: It is better to use quotes to enclose the wild cards,
       otherwise the shell may expand the parameters into names
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/trace/intel_th.txt linux-libre-4.10-rc8-gnu/Documentation/trace/intel_th.txt
--- linux-libre-4.9-gnu/Documentation/trace/intel_th.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/trace/intel_th.txt	2017-02-12 16:03:20.000000000 -0500
@@ -97,3 +97,25 @@ $ echo 0 > /sys/bus/intel_th/devices/0-m
 # and now you can collect the trace from the device node:
 
 $ cat /dev/intel_th0/msc0 > my_stp_trace
+
+Host Debugger Mode
+==================
+
+It is possible to configure the Trace Hub and control its trace
+capture from a remote debug host, which should be connected via one of
+the hardware debugging interfaces, which will then be used to both
+control Intel Trace Hub and transfer its trace data to the debug host.
+
+The driver needs to be told that such an arrangement is taking place
+so that it does not touch any capture/port configuration and avoids
+conflicting with the debug host's configuration accesses. The only
+activity that the driver will perform in this mode is collecting
+software traces to the Software Trace Hub (an stm class device). The
+user is still responsible for setting up adequate master/channel
+mappings that the decoder on the receiving end would recognize.
+
+In order to enable the host mode, set the 'host_mode' parameter of the
+'intel_th' kernel module to 'y'. None of the virtual output devices
+will show up on the intel_th bus. Also, trace configuration and
+capture controlling attribute groups of the 'gth' device will not be
+exposed. The 'sth' device will operate as usual.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/trace/stm.txt linux-libre-4.10-rc8-gnu/Documentation/trace/stm.txt
--- linux-libre-4.9-gnu/Documentation/trace/stm.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/trace/stm.txt	2017-02-12 16:03:20.000000000 -0500
@@ -69,12 +69,43 @@ stm device's channel mmio region is 64 b
 width==64, you should be able to mmap() one page on this file
 descriptor and obtain direct access to an mmio region for 64 channels.
 
+Examples of STM devices are Intel(R) Trace Hub [1] and Coresight STM
+[2].
+
+stm_source
+==========
+
 For kernel-based trace sources, there is "stm_source" device
 class. Devices of this class can be connected and disconnected to/from
-stm devices at runtime via a sysfs attribute.
+stm devices at runtime via a sysfs attribute called "stm_source_link"
+by writing the name of the desired stm device there, for example:
 
-Examples of STM devices are Intel(R) Trace Hub [1] and Coresight STM
-[2].
+$ echo dummy_stm.0 > /sys/class/stm_source/console/stm_source_link
+
+For examples on how to use stm_source interface in the kernel, refer
+to stm_console or stm_heartbeat drivers.
+
+Each stm_source device will need to assume a master and a range of
+channels, depending on how many channels it requires. These are
+allocated for the device according to the policy configuration. If
+there's a node in the root of the policy directory that matches the
+stm_source device's name (for example, "console"), this node will be
+used to allocate master and channel numbers. If there's no such policy
+node, the stm core will pick the first contiguous chunk of channels
+within the first available master. Note that the node must exist
+before the stm_source device is connected to its stm device.
+
+stm_console
+===========
+
+One implementation of this interface also used in the example above is
+the "stm_console" driver, which basically provides a one-way console
+for kernel messages over an stm device.
+
+To configure the master/channel pair that will be assigned to this
+console in the STP stream, create a "console" policy entry (see the
+beginning of this text on how to do that). When initialized, it will
+consume one channel.
 
 [1] https://software.intel.com/sites/default/files/managed/d3/3c/intel-th-developer-manual.pdf
 [2] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0444b/index.html
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/trace/uprobetracer.txt linux-libre-4.10-rc8-gnu/Documentation/trace/uprobetracer.txt
--- linux-libre-4.9-gnu/Documentation/trace/uprobetracer.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/trace/uprobetracer.txt	2017-02-12 16:03:20.000000000 -0500
@@ -76,15 +76,15 @@ Usage examples
  * Add a probe as a new uprobe event, write a new definition to uprobe_events
 as below: (sets a uprobe at an offset of 0x4245c0 in the executable /bin/bash)
 
-    echo 'p: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
+    echo 'p /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
 
  * Add a probe as a new uretprobe event:
 
-    echo 'r: /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
+    echo 'r /bin/bash:0x4245c0' > /sys/kernel/debug/tracing/uprobe_events
 
  * Unset registered event:
 
-    echo '-:bash_0x4245c0' >> /sys/kernel/debug/tracing/uprobe_events
+    echo '-:p_bash_0x4245c0' >> /sys/kernel/debug/tracing/uprobe_events
 
  * Print out the events that are registered:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ja_JP/HOWTO linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/HOWTO
--- linux-libre-4.9-gnu/Documentation/translations/ja_JP/HOWTO	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/HOWTO	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,637 @@
+NOTE:
+This is a version of Documentation/HOWTO translated into Japanese.
+This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
+and the JF Project team <www.linux.or.jp/JF>.
+If you find any difference between this document and the original file
+or a problem with the translation,
+please contact the maintainer of this file or JF project.
+
+Please also note that the purpose of this file is to be easier to read
+for non English (read: Japanese) speakers and is not intended as a
+fork. So if you have any comments or updates for this file, please try
+to update the original English file first.
+
+Last Updated: 2013/07/19
+==================================
+これは、
+linux-3.10/Documentation/HOWTO
+の和訳です。
+
+翻訳団体： JF プロジェクト < http://linuxjf.sourceforge.jp/ >
+翻訳日： 2013/7/19
+翻訳者： Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
+校正者： 松倉さん <nbh--mats at nifty dot com>
+         小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
+         武井伸光さん、<takei at webmasters dot gr dot jp>
+         かねこさん (Seiji Kaneko) <skaneko at a2 dot mbn dot or dot jp>
+         野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
+         河内さん (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com>
+         岩本さん (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp>
+         内田さん (Satoshi Uchida) <s-uchida at ap dot jp dot nec dot com>
+==================================
+
+Linux カーネル開発のやり方
+-------------------------------
+
+これは上のトピック( Linux カーネル開発のやり方)の重要な事柄を網羅した
+ドキュメントです。ここには Linux カーネル開発者になるための方法と
+Linux カーネル開発コミュニティと共に活動するやり方を学ぶ方法が含まれて
+います。カーネルプログラミングに関する技術的な項目に関することは何も含
+めないようにしていますが、カーネル開発者となるための正しい方向に向かう
+手助けになります。
+
+もし、このドキュメントのどこかが古くなっていた場合には、このドキュメン
+トの最後にリストしたメンテナにパッチを送ってください。
+
+はじめに
+---------
+
+あなたは　Linux カーネルの開発者になる方法を学びたいのでしょうか？　そ
+れともあなたは上司から「このデバイスの Linux ドライバを書くように」と
+言われているのでしょうか？　
+この文書の目的は、あなたが踏むべき手順と、コミュニティと一緒にうまく働
+くヒントを書き下すことで、あなたが知るべき全てのことを教えることです。
+また、このコミュニティがなぜ今うまくまわっているのかという理由の一部も
+説明しようと試みています。
+
+
+カーネルは 少量のアーキテクチャ依存部分がアセンブリ言語で書かれている
+以外は大部分は C 言語で書かれています。C言語をよく理解していることはカー
+ネル開発者には必要です。アーキテクチャ向けの低レベル部分の開発をするの
+でなければ、(どんなアーキテクチャでも)アセンブリ(訳注: 言語)は必要あり
+ません。以下の本は、C 言語の十分な知識や何年もの経験に取って代わるもの
+ではありませんが、少なくともリファレンスとしては良い本です。
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+ -『プログラミング言語Ｃ第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+ - 『C実践プログラミング第3版』(Steve Oualline著 望月康司監訳 谷口功訳) [オライリージャパン]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+ - 『新・詳説 C 言語 H&S リファレンス』
+       (サミュエル P ハービソン/ガイ L スティール共著 斉藤 信男監訳)[ソフトバンク]
+
+カーネルは GNU C と GNU ツールチェインを使って書かれています。カーネル
+は ISO C89 仕様に準拠して書く一方で、標準には無い言語拡張を多く使って
+います。カーネルは標準 C ライブラリとは関係がないといった、C 言語フリー
+スタンディング環境です。そのため、C の標準で使えないものもあります。任
+意の long long の除算や浮動小数点は使えません。
+ときどき、カーネルがツールチェインや C 言語拡張に置いている前提がどう
+なっているのかわかりにくいことがあり、また、残念なことに決定的なリファ
+レンスは存在しません。情報を得るには、gcc の info ページ( info gcc )を
+見てください。
+
+あなたは既存の開発コミュニティと一緒に作業する方法を学ぼうとしているこ
+とに留意してください。そのコミュニティは、コーディング、スタイル、
+開発手順について高度な標準を持つ、多様な人の集まりです。
+地理的に分散した大規模なチームに対してもっともうまくいくとわかったこと
+をベースにしながら、これらの標準は長い時間をかけて築かれてきました。
+これらはきちんと文書化されていますから、事前にこれらの標準についてでき
+るだけたくさん学んでください。また皆があなたやあなたの会社のやり方に合わ
+せてくれると思わないでください。
+
+法的問題
+------------
+
+Linux カーネルのソースコードは GPL ライセンスの下でリリースされていま
+す。ライセンスの詳細については、ソースツリーのメインディレクトリに存在
+する、COPYING のファイルを見てください。もしライセンスについてさらに質
+問があれば、Linux Kernel メーリングリストに質問するのではなく、どうぞ
+法律家に相談してください。メーリングリストの人達は法律家ではなく、法的
+問題については彼らの声明はあてにするべきではありません。
+
+GPL に関する共通の質問や回答については、以下を参照してください。
+	http://www.gnu.org/licenses/gpl-faq.html
+
+ドキュメント
+------------
+
+Linux カーネルソースツリーは幅広い範囲のドキュメントを含んでおり、それ
+らはカーネルコミュニティと会話する方法を学ぶのに非常に貴重なものです。
+新しい機能がカーネルに追加される場合、その機能の使い方について説明した
+新しいドキュメントファイルも追加することを勧めます。
+カーネルの変更が、カーネルがユーザ空間に公開しているインターフェイスの
+変更を引き起こす場合、その変更を説明するマニュアルページのパッチや情報
+をマニュアルページのメンテナ mtk.manpages@gmail.com に送り、CC を
+linux-api@ver.kernel.org に送ることを勧めます。
+
+以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で
+す-
+
+  README
+    このファイルは Linuxカーネルの簡単な背景とカーネルを設定(訳注
+    configure )し、生成(訳注 build )するために必要なことは何かが書かれ
+    ています。カーネルに関して初めての人はここからスタートすると良いで
+    しょう。
+
+  Documentation/Changes
+     このファイルはカーネルをうまく生成(訳注 build )し、走らせるのに最
+     小限のレベルで必要な数々のソフトウェアパッケージの一覧を示してい
+     ます。
+
+  Documentation/process/coding-style.rst
+    これは Linux カーネルのコーディングスタイルと背景にある理由を記述
+    しています。全ての新しいコードはこのドキュメントにあるガイドライン
+    に従っていることを期待されています。大部分のメンテナはこれらのルー
+    ルに従っているものだけを受け付け、多くの人は正しいスタイルのコード
+    だけをレビューします。
+
+  Documentation/process/submitting-patches.rst
+  Documentation/process/submitting-drivers.rst
+     これらのファイルには、どうやってうまくパッチを作って投稿するかに
+     ついて非常に詳しく書かれており、以下を含みます(これだけに限らない
+     けれども)
+        - Email に含むこと
+        - Email の形式
+        - だれに送るか
+     これらのルールに従えばうまくいくことを保証することではありません
+     が (すべてのパッチは内容とスタイルについて精査を受けるので)、
+     ルールに従わなければ間違いなくうまくいかないでしょう。
+
+     この他にパッチを作る方法についてのよくできた記述は-
+
+	"The Perfect Patch"
+		http://www.ozlabs.org/~akpm/stuff/tpp.txt
+	"Linux kernel patch submission format"
+		http://linux.yyz.us/patch-format.html
+
+  Documentation/process/stable-api-nonsense.rst
+     このファイルはカーネルの中に不変のAPIを持たないことにした意識的な
+     決断の背景にある理由について書かれています。以下のようなことを含
+     んでいます-
+       - サブシステムとの間に層を作ること(コンパチビリティのため?)
+       - オペレーティングシステム間のドライバの移植性
+       - カーネルソースツリーの素早い変更を遅らせる(もしくは素早い変更
+         を妨げる)
+     このドキュメントは Linux 開発の思想を理解するのに非常に重要です。
+     そして、他のOSでの開発者が Linux に移る時にとても重要です。
+
+  Documentation/admin-guide/security-bugs.rst
+    もし Linux カーネルでセキュリティ問題を発見したように思ったら、こ
+    のドキュメントのステップに従ってカーネル開発者に連絡し、問題解決を
+    支援してください。
+
+  Documentation/process/management-style.rst
+    このドキュメントは Linux カーネルのメンテナ達がどう行動するか、
+    彼らの手法の背景にある共有されている精神について記述しています。こ
+    れはカーネル開発の初心者なら（もしくは、単に興味があるだけの人でも）
+    重要です。なぜならこのドキュメントは、カーネルメンテナ達の独特な
+    行動についての多くの誤解や混乱を解消するからです。
+
+  Documentation/process/stable-kernel-rules.rst
+    このファイルはどのように stable カーネルのリリースが行われるかのルー
+    ルが記述されています。そしてこれらのリリースの中のどこかで変更を取
+    り入れてもらいたい場合に何をすれば良いかが示されています。
+
+  Documentation/process/kernel-docs.rst
+　　カーネル開発に付随する外部ドキュメントのリストです。もしあなたが
+    探しているものがカーネル内のドキュメントでみつからなかった場合、
+    このリストをあたってみてください。
+
+  Documentation/process/applying-patches.rst
+    パッチとはなにか、パッチをどうやって様々なカーネルの開発ブランチに
+    適用するのかについて正確に記述した良い入門書です。
+
+カーネルはソースコードから自動的に生成可能な多数のドキュメントを自分自
+身でもっています。これにはカーネル内 API のすべての記述や、どう正しく
+ロックをかけるかの規則が含まれます。このドキュメントは
+Documentation/DocBook/ ディレクトリに作られ、以下のように
+	make pdfdocs
+	make psdocs
+	make htmldocs
+	make mandocs
+コマンドを実行するとメインカーネルのソースディレクトリから
+それぞれ、PDF, Postscript, HTML, man page の形式で生成されます。
+
+カーネル開発者になるには
+---------------------------
+
+もしあなたが、Linux カーネル開発について何も知らないならば、
+KernelNewbies プロジェクトを見るべきです
+	http://kernelnewbies.org
+
+このサイトには役に立つメーリングリストがあり、基本的なカーネル開発に関
+するほとんどどんな種類の質問もできます (既に回答されているようなことを
+聞く前にまずはアーカイブを調べてください)。
+またここには、リアルタイムで質問を聞くことができる IRC チャネルや、Linux
+カーネルの開発に関して学ぶのに便利なたくさんの役に立つドキュメントがあ
+ります。
+
+web サイトには、コードの構成、サブシステム、現在存在するプロジェクト(ツ
+リーにあるもの無いものの両方)の基本的な管理情報があります。
+ここには、また、カーネルのコンパイルのやり方やパッチの当て方などの間接
+的な基本情報も記述されています。
+
+あなたがどこからスタートして良いかわからないが、Linux カーネル開発コミュ
+ニティに参加して何かすることをさがしている場合には、Linux kernel
+Janitor's プロジェクトにいけば良いでしょう -
+	http://kernelnewbies.org/KernelJanitors
+ここはそのようなスタートをするのにうってつけの場所です。ここには、
+Linux カーネルソースツリーの中に含まれる、きれいにし、修正しなければな
+らない、単純な問題のリストが記述されています。このプロジェクトに関わる
+開発者と一緒に作業することで、あなたのパッチを Linuxカーネルツリーに入
+れるための基礎を学ぶことができ、そしてもしあなたがまだアイディアを持っ
+ていない場合には、次にやる仕事の方向性が見えてくるかもしれません。
+
+もしあなたが、すでにひとまとまりコードを書いていて、カーネルツリーに入
+れたいと思っていたり、それに関する適切な支援を求めたい場合、カーネル
+メンターズプロジェクトはそのような皆さんを助けるためにできました。
+ここにはメーリングリストがあり、以下から参照できます
+	http://selenic.com/mailman/listinfo/kernel-mentors
+
+実際に Linux カーネルのコードについて修正を加える前に、どうやってその
+コードが動作するのかを理解することが必要です。そのためには、特別なツー
+ルの助けを借りてでも、それを直接よく読むことが最良の方法です(ほとんど
+のトリッキーな部分は十分にコメントしてありますから)。そういうツールで
+特におすすめなのは、Linux クロスリファレンスプロジェクトです。これは、
+自己参照方式で、索引がついた web 形式で、ソースコードを参照することが
+できます。この最新の素晴しいカーネルコードのリポジトリは以下で見つかり
+ます-
+	http://lxr.free-electrons.com/
+
+開発プロセス
+-----------------------
+
+Linux カーネルの開発プロセスは現在幾つかの異なるメインカーネル「ブラン
+チ」と多数のサブシステム毎のカーネルブランチから構成されます。
+これらのブランチとは-
+  - メインの 3.x カーネルツリー
+  - 3.x.y -stable カーネルツリー
+  - 3.x -git カーネルパッチ
+  - サブシステム毎のカーネルツリーとパッチ
+  - 統合テストのための 3.x -next カーネルツリー
+
+3.x カーネルツリー
+-----------------
+
+3.x カーネルは Linus Torvalds によってメンテナンスされ、kernel.org
+の pub/linux/kernel/v3.x/ ディレクトリに存在します。この開発プロセスは
+以下のとおり-
+
+  - 新しいカーネルがリリースされた直後に、2週間の特別期間が設けられ、
+    この期間中に、メンテナ達は Linus に大きな差分を送ることができます。
+    このような差分は通常 -next カーネルに数週間含まれてきたパッチです。
+    大きな変更は git(カーネルのソース管理ツール、詳細は
+    http://git-scm.com/ 参照) を使って送るのが好ましいやり方ですが、パッ
+    チファイルの形式のまま送るのでも十分です。
+
+  - 2週間後、-rc1 カーネルがリリースされ、この後にはカーネル全体の安定
+    性に影響をあたえるような新機能は含まない類のパッチしか取り込むこと
+    はできません。新しいドライバ(もしくはファイルシステム)のパッチは
+    -rc1 の後で受け付けられることもあることを覚えておいてください。な
+    ぜなら、変更が独立していて、追加されたコードの外の領域に影響を与え
+    ない限り、退行のリスクは無いからです。-rc1 がリリースされた後、
+    Linus へパッチを送付するのに git を使うこともできますが、パッチは
+    レビューのために、パブリックなメーリングリストへも同時に送る必要が
+    あります。
+
+  - 新しい -rc は Linus が、最新の git ツリーがテスト目的であれば十分
+    に安定した状態にあると判断したときにリリースされます。目標は毎週新
+    しい -rc カーネルをリリースすることです。
+
+  - このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
+    す。このプロセスはだいたい 6週間継続します。
+
+Andrew Morton が Linux-kernel メーリングリストにカーネルリリースについ
+て書いたことをここで言っておくことは価値があります-
+  「カーネルがいつリリースされるかは誰も知りません。なぜなら、これは現
+  実に認識されたバグの状況によりリリースされるのであり、前もって決めら
+  れた計画によってリリースされるものではないからです。」
+
+3.x.y -stable カーネルツリー
+---------------------------
+
+バージョン番号が3つの数字に分かれているカーネルは -stable カーネルです。
+これには、3.x カーネルで見つかったセキュリティ問題や重大な後戻りに対
+する比較的小さい重要な修正が含まれます。
+
+これは、開発/実験的バージョンのテストに協力することに興味が無く、
+最新の安定したカーネルを使いたいユーザに推奨するブランチです。
+
+もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が
+最新の安定版カーネルです。
+
+3.x.y は "stable" チーム <stable@vger.kernel.org> でメンテされており、必
+要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
+た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
+の場合はこれに対してだいたいの場合、すぐにリリースがされます。
+
+カーネルツリーに入っている、Documentation/process/stable-kernel-rules.rst ファ
+イルにはどのような種類の変更が -stable ツリーに受け入れ可能か、またリ
+リースプロセスがどう動くかが記述されています。
+
+3.x -git パッチ
+------------------
+
+git リポジトリで管理されているLinus のカーネルツリーの毎日のスナップ
+ショットがあります。(だから -git という名前がついています)。これらのパッ
+チはおおむね毎日リリースされており、Linus のツリーの現状を表します。こ
+れは -rc カーネルと比べて、パッチが大丈夫かどうかも確認しないで自動的
+に生成されるので、より実験的です。
+
+サブシステム毎のカーネルツリーとパッチ
+-------------------------------------------
+
+それぞれのカーネルサブシステムのメンテナ達は --- そして多くのカーネル
+サブシステムの開発者達も --- 各自の最新の開発状況をソースリポジトリに
+公開しています。そのため、自分とは異なる領域のカーネルで何が起きている
+かを他の人が見られるようになっています。開発が早く進んでいる領域では、
+開発者は自身の投稿がどのサブシステムカーネルツリーを元にしているか質問
+されるので、その投稿とすでに進行中の他の作業との衝突が避けられます。
+
+大部分のこれらのリポジトリは git ツリーです。しかしその他の SCM や
+quilt シリーズとして公開されているパッチキューも使われています。これら
+のサブシステムリポジトリのアドレスは MAINTAINERS ファイルにリストされ
+ています。これらの多くは http://git.kernel.org/ で参照することができま
+す。
+
+提案されたパッチがこのようなサブシステムツリーにコミットされる前に、メー
+リングリストで事前にレビューにかけられます（以下の対応するセクションを
+参照）。いくつかのカーネルサブシステムでは、このレビューは patchwork
+というツールによって追跡されます。Patchwork は web インターフェイスに
+よってパッチ投稿の表示、パッチへのコメント付けや改訂などができ、そして
+メンテナはパッチに対して、レビュー中、受付済み、拒否というようなマーク
+をつけることができます。大部分のこれらの patchwork のサイトは
+http://patchwork.kernel.org/ でリストされています。
+
+統合テストのための 3.x -next カーネルツリー
+---------------------------------------------
+
+サブシステムツリーの更新内容がメインラインの 3.x ツリーにマージされ
+る前に、それらは統合テストされる必要があります。この目的のため、実質的
+に全サブシステムツリーからほぼ毎日プルされてできる特別なテスト用のリ
+ポジトリが存在します-
+       http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+このやり方によって、-next カーネルは次のマージ機会でどんなものがメイン
+ラインカーネルにマージされるか、おおまかなの展望を提供します。-next 
+カーネルの実行テストを行う冒険好きなテスターは大いに歓迎されます
+
+バグレポート
+-------------
+
+bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを追跡する
+場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。
+どう kernel bugzilla を使うかの詳細は、以下を参照してください-
+	http://bugzilla.kernel.org/page.cgi?id=faq.html
+メインカーネルソースディレクトリにあるファイル admin-guide/reporting-bugs.rst はカーネ
+ルバグらしいものについてどうレポートするかの良いテンプレートであり、問
+題の追跡を助けるためにカーネル開発者にとってどんな情報が必要なのかの詳
+細が書かれています。
+
+バグレポートの管理
+-------------------
+
+あなたのハッキングのスキルを訓練する最高の方法のひとつに、他人がレポー
+トしたバグを修正することがあります。あなたがカーネルをより安定化させる
+こに寄与するということだけでなく、あなたは 現実の問題を修正することを
+学び、自分のスキルも強化でき、また他の開発者があなたの存在に気がつき
+ます。バグを修正することは、多くの開発者の中から自分が功績をあげる最善
+の道です、なぜなら多くの人は他人のバグの修正に時間を浪費することを好ま
+ないからです。
+
+すでにレポートされたバグのために仕事をするためには、
+http://bugzilla.kernel.org に行ってください。もし今後のバグレポートに
+ついてアドバイスを受けたいのであれば、bugme-new メーリングリスト(新し
+いバグレポートだけがここにメールされる) または bugme-janitor メーリン
+グリスト(bugzilla の変更毎にここにメールされる)を購読できます。
+
+	http://lists.linux-foundation.org/mailman/listinfo/bugme-new
+	http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
+
+メーリングリスト
+-------------
+
+上のいくつかのドキュメントで述べていますが、コアカーネル開発者の大部分
+は Linux kernel メーリングリストに参加しています。このリストの登録/脱
+退の方法については以下を参照してください-
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+
+このメーリングリストのアーカイブは web 上の多数の場所に存在します。こ
+れらのアーカイブを探すにはサーチエンジンを使いましょう。例えば-
+	http://dir.gmane.org/gmane.linux.kernel
+
+リストに投稿する前にすでにその話題がアーカイブに存在するかどうかを検索
+することを是非やってください。多数の事がすでに詳細に渡って議論されて
+おり、アーカイブにのみ記録されています。
+
+大部分のカーネルサブシステムも自分の個別の開発を実施するメーリングリス
+トを持っています。個々のグループがどんなリストを持っているかは、
+MAINTAINERS ファイルにリストがありますので参照してください。
+
+多くのリストは kernel.org でホストされています。これらの情報は以下にあ
+ります-
+	http://vger.kernel.org/vger-lists.html
+
+メーリングリストを使う場合、良い行動習慣に従うようにしましょう。
+少し安っぽいが、以下の URL は上のリスト(や他のリスト)で会話する場合の
+シンプルなガイドラインを示しています-
+	http://www.albion.com/netiquette/
+
+もし複数の人があなたのメールに返事をした場合、CC: で受ける人のリストは
+だいぶ多くなるでしょう。良い理由がない場合、CC: リストから誰かを削除を
+しないように、また、メーリングリストのアドレスだけにリプライすることの
+ないようにしましょう。1つは送信者から、もう1つはリストからのように、メー
+ルを2回受けることになってもそれに慣れ、しゃれたメールヘッダーを追加し
+てこの状態を変えようとしないように。人々はそのようなことは好みません。
+
+今までのメールでのやりとりとその間のあなたの発言はそのまま残し、
+"John Kernelhacker wrote ...:" の行をあなたのリプライの先頭行にして、
+メールの先頭でなく、各引用行の間にあなたの言いたいことを追加するべきで
+す。
+
+もしパッチをメールに付ける場合は、Documentation/process/submitting-patches.rst に提
+示されているように、それは プレーンな可読テキストにすることを忘れない
+ようにしましょう。カーネル開発者は 添付や圧縮したパッチを扱いたがりま
+せん-
+彼らはあなたのパッチの行毎にコメントを入れたいので、そのためにはそうす
+るしかありません。あなたのメールプログラムが空白やタブを圧縮しないよう
+に確認した方が良いです。最初の良いテストとしては、自分にメールを送って
+みて、そのパッチを自分で当ててみることです。もしそれがうまく行かないな
+ら、あなたのメールプログラムを直してもらうか、正しく動くように変えるべ
+きです。
+
+とりわけ、他の登録者に対する尊敬を表すようにすることを覚えておいてくだ
+さい。
+
+コミュニティと共に働くこと
+--------------------------
+
+カーネルコミュニティのゴールは可能なかぎり最高のカーネルを提供すること
+です。あなたがパッチを受け入れてもらうために投稿した場合、それは、技術
+的メリットだけがレビューされます。その際、あなたは何を予想すべきでしょ
+うか?
+  - 批判
+  - コメント
+  - 変更の要求
+  - パッチの正当性の証明要求
+  - 沈黙
+
+思い出してください、ここはあなたのパッチをカーネルに入れる話です。あ
+なたは、あなたのパッチに対する批判とコメントを受け入れるべきで、それら
+を技術的レベルで評価して、パッチを再作成するか、なぜそれらの変更をすべ
+きでないかを明確で簡潔な理由の説明を提供してください。
+もし、あなたのパッチに何も反応がない場合、たまにはメールの山に埋もれて
+見逃され、あなたの投稿が忘れられてしまうこともあるので、数日待って再度
+投稿してください。
+
+あなたがやるべきでないものは?
+  - 質問なしにあなたのパッチが受け入れられると想像すること
+  - 守りに入ること
+  - コメントを無視すること
+  - 要求された変更を何もしないでパッチを出し直すこと
+
+可能な限り最高の技術的解決を求めているコミュニティでは、パッチがどのく
+らい有益なのかについては常に異なる意見があります。あなたは協調的である
+べきですし、また、あなたのアイディアをカーネルに対してうまく合わせるよ
+うにすることが望まれています。もしくは、最低限あなたのアイディアがそれ
+だけの価値があるとすすんで証明するようにしなければなりません。
+正しい解決に向かって進もうという意志がある限り、間違うことがあっても許
+容されることを忘れないでください。
+
+あなたの最初のパッチに単に 1ダースもの修正を求めるリストの返答になるこ
+とも普通のことです。これはあなたのパッチが受け入れられないということで
+は *ありません*、そしてあなた自身に反対することを意味するのでも *ありま
+せん*。単に自分のパッチに対して指摘された問題を全て修正して再送すれば
+良いのです。
+
+
+カーネルコミュニティと企業組織のちがい
+-----------------------------------------------------------------
+
+カーネルコミュニティは大部分の伝統的な会社の開発環境とは異ったやり方で
+動いています。以下は問題を避けるためにできると良いことのリストです-
+
+  あなたの提案する変更について言うときのうまい言い方：
+
+    - "これは複数の問題を解決します"
+    - "これは2000行のコードを削除します"
+    - "以下のパッチは、私が言おうとしていることを説明するものです"
+    - "私はこれを5つの異なるアーキテクチャでテストしたのですが..."
+    - "以下は一連の小さなパッチ群ですが..."
+    - "これは典型的なマシンでの性能を向上させます.."
+
+  やめた方が良い悪い言い方：
+
+    - このやり方で AIX/ptx/Solaris ではできたので、できるはずだ
+    - 私はこれを20年もの間やってきた、だから
+    - これは、私の会社が金儲けをするために必要だ
+    - これは我々のエンタープライズ向け商品ラインのためである
+    - これは 私が自分のアイディアを記述した、1000ページの設計資料である
+    - 私はこれについて、6ケ月作業している。
+    - 以下は ... に関する5000行のパッチです
+    - 私は現在のぐちゃぐちゃを全部書き直した、それが以下です...
+    - 私は〆切がある、そのためこのパッチは今すぐ適用される必要がある
+
+カーネルコミュニティが大部分の伝統的なソフトウェアエンジニアリングの労
+働環境と異なるもう一つの点は、やりとりに顔を合わせないということです。
+email と irc を第一のコミュニケーションの形とする一つの利点は、性別や
+民族の差別がないことです。Linux カーネルの職場環境は女性や少数民族を受
+容します。なぜなら、email アドレスによってのみあなたが認識されるからで
+す。
+国際的な側面からも活動領域を均等にするようにします。なぜならば、あなた
+は人の名前で性別を想像できないからです。ある男性が アンドレアという名
+前で、女性の名前は パット かもしれません (訳注 Andrea は米国では女性、
+それ以外(欧州など)では男性名として使われることが多い。同様に、Pat は
+Patricia (主に女性名)や Patrick (主に男性名)の略称)。
+Linux カーネルの活動をして、意見を表明したことがある大部分の女性は、前
+向きな経験をもっています。
+
+言葉の壁は英語が得意でない一部の人には問題になります。
+メーリングリストの中できちんとアイディアを交換するには、相当うまく英語
+を操れる必要があることもあります。そのため、あなたは自分のメール
+を送る前に英語で意味が通じているかをチェックすることをお薦めします。
+
+変更を分割する
+---------------------
+
+Linux カーネルコミュニティは、一度に大量のコードの塊を喜んで受容するこ
+とはありません。変更は正確に説明される必要があり、議論され、小さい、個
+別の部分に分割する必要があります。これはこれまで多くの会社がやり慣れて
+きたことと全く正反対のことです。あなたのプロポーザルは、開発プロセスのと
+ても早い段階から紹介されるべきです。そうすれば あなたは自分のやってい
+ることにフィードバックを得られます。これは、コミュニティからみれば、あ
+なたが彼らと一緒にやっているように感じられ、単にあなたの提案する機能の
+ゴミ捨て場として使っているのではない、と感じられるでしょう。
+しかし、一度に 50 もの email をメーリングリストに送りつけるようなことは
+やってはいけません、あなたのパッチ群はいつもどんな時でもそれよりは小さ
+くなければなりません。
+
+パッチを分割する理由は以下です-
+
+1) 小さいパッチはあなたのパッチが適用される見込みを大きくします、カー
+   ネルの人達はパッチが正しいかどうかを確認する時間や労力をかけないか
+   らです。5行のパッチはメンテナがたった1秒見るだけで適用できます。
+   しかし、500行のパッチは、正しいことをレビューするのに数時間かかるか
+   もしれません(時間はパッチのサイズなどにより指数関数に比例してかかり
+   ます)
+
+   小さいパッチは何かあったときにデバッグもとても簡単になります。パッ
+   チを1個1個取り除くのは、とても大きなパッチを当てた後に(かつ、何かお
+   かしくなった後で)解剖するのに比べればとても簡単です。
+
+2) 小さいパッチを送るだけでなく、送るまえに、書き直して、シンプルにす
+   る(もしくは、単に順番を変えるだけでも)ことも、とても重要です。
+
+以下はカーネル開発者の Al Viro のたとえ話です：
+
+        "生徒の数学の宿題を採点する先生のことを考えてみてください、先
+        生は生徒が解に到達するまでの試行錯誤を見たいとは思わないでしょ
+        う。先生は簡潔な最高の解を見たいのです。良い生徒はこれを知って
+        おり、そして最終解の前の中間作業を提出することは決してないので
+        す"
+
+        カーネル開発でもこれは同じです。メンテナ達とレビューア達は、
+        問題を解決する解の背後になる思考プロセスを見たいとは思いません。
+        彼らは単純であざやかな解決方法を見たいのです。
+
+あざやかな解を説明するのと、コミュニティと共に仕事をし、未解決の仕事を
+議論することのバランスをキープするのは難しいかもしれません。
+ですから、開発プロセスの早期段階で改善のためのフィードバックをもらうよ
+うにするのも良いですが、変更点を小さい部分に分割して全体ではまだ完成し
+ていない仕事を(部分的に)取り込んでもらえるようにすることも良いことです。
+
+また、でき上がっていないものや、"将来直す" ようなパッチを、本流に含め
+てもらうように送っても、それは受け付けられないことを理解してください。
+
+あなたの変更を正当化する
+-------------------
+
+あなたのパッチを分割するのと同時に、なぜその変更を追加しなければならな
+いかを Linux コミュニティに知らせることはとても重要です。新機能は必要
+性と有用性で正当化されなければなりません。
+
+あなたの変更の説明
+--------------------
+
+あなたのパッチを送付する場合には、メールの中のテキストで何を言うかにつ
+いて、特別に注意を払ってください。この情報はパッチの ChangeLog に使わ
+れ、いつも皆がみられるように保管されます。これは次のような項目を含め、
+パッチを完全に記述するべきです-
+
+  - なぜ変更が必要か
+  - パッチ全体の設計アプローチ
+  - 実装の詳細
+  - テスト結果
+
+これについて全てがどのようにあるべきかについての詳細は、以下のドキュメ
+ントの ChangeLog セクションを見てください-
+  "The Perfect Patch"
+      http://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+これらのどれもが、時にはとても困難です。これらの慣例を完璧に実施するに
+は数年かかるかもしれません。これは継続的な改善のプロセスであり、そのた
+めには多数の忍耐と決意を必要とするものです。でも、諦めないで、これは可
+能なことです。多数の人がすでにできていますし、彼らも皆最初はあなたと同
+じところからスタートしたのですから。
+
+Paolo Ciarrocchi に感謝、彼は彼の書いた "Development Process"
+(http://lwn.net/Articles/94386/) セクションをこのテキストの原型にする
+ことを許可してくれました。Rundy Dunlap と Gerrit Huizenga はメーリング
+リストでやるべきこととやってはいけないことのリストを提供してくれました。
+以下の人々のレビュー、コメント、貢献に感謝。
+Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
+Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi
+Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
+David A. Wheeler, Junio Hamano, Michael Kerrisk, と Alex Shepard
+彼らの支援なしでは、このドキュメントはできなかったでしょう。
+
+Maintainer: Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ja_JP/stable_api_nonsense.txt linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/stable_api_nonsense.txt
--- linux-libre-4.9-gnu/Documentation/translations/ja_JP/stable_api_nonsense.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/stable_api_nonsense.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,263 @@
+NOTE:
+This is a version of Documentation/process/stable-api-nonsense.rst into Japanese.
+This document is maintained by IKEDA, Munehiro <m-ikeda@ds.jp.nec.com>
+and the JF Project team <http://www.linux.or.jp/JF/>.
+If you find any difference between this document and the original file
+or a problem with the translation,
+please contact the maintainer of this file or JF project.
+
+Please also note that the purpose of this file is to be easier to read
+for non English (read: Japanese) speakers and is not intended as a
+fork. So if you have any comments or updates of this file, please try
+to update the original English file first.
+
+Last Updated: 2007/07/18
+==================================
+これは、
+linux-2.6.22-rc4/Documentation/process/stable-api-nonsense.rst の和訳
+です。
+翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
+翻訳日 ： 2007/06/11
+原著作者: Greg Kroah-Hartman < greg at kroah dot com >
+翻訳者 ： 池田 宗広 < m-ikeda at ds dot jp dot nec dot com >
+校正者 ： Masanori Kobayashi さん < zap03216 at nifty dot ne dot jp >
+          Seiji Kaneko さん < skaneko at a2 dot mbn dot or dot jp >
+==================================
+
+
+
+Linux カーネルのドライバインターフェース
+（あなたの質問すべてに対する回答とその他諸々）
+
+Greg Kroah-Hartman <greg at kroah dot com>
+
+
+この文書は、なぜ Linux ではバイナリカーネルインターフェースが定義
+されていないのか、またはなぜ不変のカーネルインターフェースを持たな
+いのか、ということを説明するために書かれた。ここでの話題は「カーネ
+ル内部の」インターフェースについてであり、ユーザー空間とのインター
+フェースではないことを理解してほしい。カーネルとユーザー空間とのイ
+ンターフェースとはアプリケーションプログラムが使用するものであり、
+つまりシステムコールのインターフェースがこれに当たる。これは今まで
+長きに渡り、かつ今後も「まさしく」不変である。私は確か 0.9 か何か
+より前のカーネルを使ってビルドした古いプログラムを持っているが、そ
+れは最新の 2.6 カーネルでもきちんと動作する。ユーザー空間とのイン
+ターフェースは、ユーザーとアプリケーションプログラマが不変性を信頼
+してよいものの一つである。
+
+
+要旨
+----
+
+あなたは不変のカーネルインターフェースが必要だと考えているかもしれ
+ないが、実際のところはそうではない。あなたは必要としているものが分
+かっていない。あなたが必要としているものは安定して動作するドライバ
+であり、それはドライバがメインのカーネルツリーに含まれる場合のみ得
+ることができる。ドライバがメインのカーネルツリーに含まれていると、
+他にも多くの良いことがある。それは、Linux をより強固で、安定な、成
+熟したオペレーティングシステムにすることができるということだ。これ
+こそ、そもそもあなたが Linux を使う理由のはずだ。
+
+
+はじめに
+--------
+
+カーネル内部のインターフェース変更を心配しなければならないドライバ
+を書きたいなどというのは、変わり者だけだ。この世界のほとんどの人は、
+そのようなドライバがどんなインターフェースを使っているかなど知らな
+いし、そんなドライバのことなど全く気にもかけていない。
+
+
+まず初めに、クローズソースとか、ソースコードの隠蔽とか、バイナリの
+みが配布される使い物にならない代物[訳注(1)]とか、実体はバイナリ
+コードでそれを読み込むためのラッパー部分のみソースコードが公開され
+ているとか、その他用語は何であれ GPL の下にソースコードがリリース
+されていないカーネルドライバに関する法的な問題について、私は「いか
+なる議論も」行うつもりがない。法的な疑問があるのならば、プログラマ
+である私ではなく、弁護士に相談して欲しい。ここでは単に、技術的な問
+題について述べることにする。（法的な問題を軽視しているわけではない。
+それらは実際に存在するし、あなたはそれをいつも気にかけておく必要が
+ある）
+
+訳注(1)
+「使い物にならない代物」の原文は "blob"
+
+
+さてここでは、バイナリカーネルインターフェースについてと、ソースレ
+ベルでのインターフェースの不変性について、という二つの話題を取り上
+げる。この二つは互いに依存する関係にあるが、まずはバイナリインター
+フェースについて議論を行いやっつけてしまおう。
+
+
+バイナリカーネルインターフェース
+--------------------------------
+
+もしソースレベルでのインターフェースが不変ならば、バイナリインター
+フェースも当然のように不変である、というのは正しいだろうか？正しく
+ない。Linux カーネルに関する以下の事実を考えてみてほしい。
+  - あなたが使用するＣコンパイラのバージョンによって、カーネル内部
+    の構造体の配置構造は異なったものになる。また、関数は異なった方
+    法でカーネルに含まれることになるかもしれない（例えばインライン
+    関数として扱われたり、扱われなかったりする）。個々の関数がどの
+    ようにコンパイルされるかはそれほど重要ではないが、構造体のパデ
+    ィングが異なるというのは非常に重要である。
+  - あなたがカーネルのビルドオプションをどのように設定するかによっ
+    て、カーネルには広い範囲で異なった事態が起こり得る。
+      - データ構造は異なるデータフィールドを持つかもしれない
+      - いくつかの関数は全く実装されていない状態になり得る
+        （例：SMP向けではないビルドでは、いくつかのロックは中身が
+          カラにコンパイルされる）
+      - カーネル内のメモリは、異なった方法で配置され得る。これはビ
+        ルドオプションに依存している。
+  - Linux は様々な異なるプロセッサアーキテクチャ上で動作する。
+    あるアーキテクチャ用のバイナリドライバを、他のアーキテクチャで
+    正常に動作させる方法はない。
+
+
+ある特定のカーネル設定を使用し、カーネルをビルドしたのと正確に同じ
+Ｃコンパイラを使用して単にカーネルモジュールをコンパイルするだけで
+も、あなたはこれらいくつもの問題に直面することになる。ある特定の
+Linux ディストリビューションの、ある特定のリリースバージョン用にモ
+ジュールを提供しようと思っただけでも、これらの問題を引き起こすには
+十分である。にも関わらず Linux ディストリビューションの数と、サ
+ポートするディストリビューションのリリース数を掛け算し、それら一つ
+一つについてビルドを行ったとしたら、今度はリリースごとのビルドオプ
+ションの違いという悪夢にすぐさま悩まされることになる。また、ディス
+トリビューションの各リリースバージョンには、異なるハードウェア（プ
+ロセッサタイプや種々のオプション）に対応するため、何種類かのカーネ
+ルが含まれているということも理解して欲しい。従って、ある一つのリ
+リースバージョンだけのためにモジュールを作成する場合でも、あなたは
+何バージョンものモジュールを用意しなければならない。
+
+
+信じて欲しい。このような方法でサポートを続けようとするなら、あなた
+はいずれ正気を失うだろう。遠い昔、私はそれがいかに困難なことか、身
+をもって学んだのだ・・・
+
+
+不変のカーネルソースレベルインターフェース
+------------------------------------------
+
+メインカーネルツリーに含まれていない Linux カーネルドライバを継続
+してサポートしていこうとしている人たちとの議論においては、これは極
+めて「引火性の高い」話題である。[訳注(2)]
+
+訳注(2)
+「引火性の高い」の原文は "volatile"。
+volatile には「揮発性の」「爆発しやすい」という意味の他、「変わり
+やすい」「移り気な」という意味がある。
+「（この話題は）爆発的に激しい論争を巻き起こしかねない」ということ
+を、「（カーネルのソースレベルインターフェースは）移ろい行くもので
+ある」ということを連想させる "volatile" という単語で表現している。
+
+
+Linux カーネルの開発は継続的に速いペースで行われ、決して歩みを緩め
+ることがない。その中でカーネル開発者達は、現状のインターフェースに
+あるバグを見つけ、より良い方法を考え出す。彼らはやがて、現状のイン
+ターフェースがより正しく動作するように修正を行う。その過程で関数の
+名前は変更されるかもしれず、構造体は大きく、または小さくなるかもし
+れず、関数の引数は検討しなおされるかもしれない。そのような場合、引
+き続き全てが正常に動作するよう、カーネル内でこれらのインターフェー
+スを使用している個所も全て同時に修正される。
+
+
+具体的な例として、カーネル内の USB インターフェースを挙げる。USB
+サブシステムはこれまでに少なくとも３回の書き直しが行われ、その結果
+インターフェースが変更された。これらの書き直しはいくつかの異なった
+問題を修正するために行われた。
+  - 同期的データストリームが非同期に変更された。これにより多数のド
+    ライバを単純化でき、全てのドライバのスループットが向上した。今
+    やほとんど全ての USB デバイスは、考えられる最高の速度で動作し
+    ている。
+  - USB ドライバが USB サブシステムのコアから行う、データパケット
+    用のメモリ確保方法が変更された。これに伴い、いくつもの文書化さ
+    れたデッドロック条件を回避するため、全ての USB ドライバはより
+    多くの情報を USB コアに提供しなければならないようになっている。
+
+
+このできごとは、数多く存在するクローズソースのオペレーティングシス
+テムとは全く対照的だ。それらは長期に渡り古い USB インターフェース
+をメンテナンスしなければならない。古いインターフェースが残ることで、
+新たな開発者が偶然古いインターフェースを使い、正しくない方法で開発
+を行ってしまう可能性が生じる。これによりシステムの安定性は危険にさ
+らされることになる。
+
+
+上に挙げたどちらの例においても、開発者達はその変更が重要かつ必要で
+あることに合意し、比較的楽にそれを実行した。もし Linux がソースレ
+ベルでインターフェースの不変性を保証しなければならないとしたら、新
+しいインターフェースを作ると同時に、古い、問題のある方を今後ともメ
+ンテナンスするという余計な仕事を USB の開発者にさせなければならな
+い。Linux の USB 開発者は、自分の時間を使って仕事をしている。よっ
+て、価値のない余計な仕事を報酬もなしに実行しろと言うことはできない。
+
+
+セキュリティ問題も、Linux にとっては非常に重要である。ひとたびセキ
+ュリティに関する問題が発見されれば、それは極めて短期間のうちに修正
+される。セキュリティ問題の発生を防ぐための修正は、カーネルの内部イ
+ンターフェースの変更を何度も引き起こしてきた。その際同時に、変更さ
+れたインターフェースを使用する全てのドライバもまた変更された。これ
+により問題が解消し、将来偶然に問題が再発してしまわないことが保証さ
+れる。もし内部インターフェースの変更が許されないとしたら、このよう
+にセキュリティ問題を修正し、将来再発しないことを保証することなど不
+可能なのだ。
+
+
+カーネルのインターフェースは時が経つにつれクリーンナップを受ける。
+誰も使っていないインターフェースは削除される。これにより、可能な限
+りカーネルが小さく保たれ、現役の全てのインターフェースが可能な限り
+テストされることを保証しているのだ。（使われていないインターフェー
+スの妥当性をテストすることは不可能と言っていいだろう）
+
+
+
+これから何をすべきか
+-----------------------
+
+では、もしメインのカーネルツリーに含まれない Linux カーネルドライ
+バがあったとして、あなたは、つまり開発者は何をするべきだろうか？全
+てのディストリビューションの全てのカーネルバージョン向けにバイナリ
+のドライバを供給することは悪夢であり、カーネルインターフェースの変
+更を追いかけ続けることもまた過酷な仕事だ。
+
+
+答えは簡単。そのドライバをメインのカーネルツリーに入れてしまえばよ
+い。（ここで言及しているのは、GPL に従って公開されるドライバのこと
+だということに注意してほしい。あなたのコードがそれに該当しないなら
+ば、さよなら。幸運を祈ります。ご自分で何とかしてください。Andrew
+と Linus からのコメント＜Andrew と Linus のコメントへのリンクをこ
+こに置く＞をどうぞ）ドライバがメインツリーに入れば、カーネルのイン
+ターフェースが変更された場合、変更を行った開発者によってドライバも
+修正されることになるだろう。あなたはほとんど労力を払うことなしに、
+常にビルド可能できちんと動作するドライバを手に入れることができる。
+
+
+ドライバをメインのカーネルツリーに入れると、非常に好ましい以下の効
+果がある。
+  - ドライバの品質が向上する一方で、（元の開発者にとっての）メンテ
+    ナンスコストは下がる。
+  - あなたのドライバに他の開発者が機能を追加してくれる。
+  - 誰かがあなたのドライバにあるバグを見つけ、修正してくれる。
+  - 誰かがあなたのドライバにある改善点を見つけてくれる。
+  - 外部インターフェースが変更されドライバの更新が必要になった場合、
+    誰かがあなたの代わりに更新してくれる。
+  - ドライバを入れてくれとディストロに頼まなくても、そのドライバは
+    全ての Linux ディストリビューションに自動的に含まれてリリース
+    される。
+
+
+Linux では、他のどのオペレーティングシステムよりも数多くのデバイス
+が「そのまま」使用できるようになった。また Linux は、どのオペレー
+ティングシステムよりも数多くのプロセッサアーキテクチャ上でそれらの
+デバイスを使用することができるようにもなった。このように、Linux の
+開発モデルは実証されており、今後も間違いなく正しい方向へと進んでい
+くだろう。:)
+
+
+
+------
+
+この文書の初期の草稿に対し、Randy Dunlap, Andrew Morton, David
+Brownell, Hanna Linder, Robert Love, Nishanth Aravamudan から査読
+と助言を頂きました。感謝申し上げます。
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ja_JP/stable_kernel_rules.txt linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/stable_kernel_rules.txt
--- linux-libre-4.9-gnu/Documentation/translations/ja_JP/stable_kernel_rules.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/stable_kernel_rules.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,84 @@
+NOTE:
+This is Japanese translated version of "Documentation/process/stable-kernel-rules.rst".
+This one is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
+and JF Project team <www.linux.or.jp/JF>.
+If you find difference with original file or problem in translation,
+please contact maintainer of this file or JF project.
+
+Please also note that purpose of this file is easier to read for non
+English natives and do no intended to fork. So, if you have any
+comment or update of this file, please try to update Original(English)
+file at first.
+
+==================================
+これは、
+linux-2.6.29/Documentation/process/stable-kernel-rules.rst
+の和訳です。
+
+翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
+翻訳日： 2009/1/14
+翻訳者： Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
+校正者： 武井伸光さん、<takei at webmasters dot gr dot jp>
+         かねこさん (Seiji Kaneko) <skaneko at a2 dot mbn dot or dot jp>
+         小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
+         野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
+         神宮信太郎さん <jin at libjingu dot jp>
+==================================
+
+ずっと知りたかった Linux 2.6 -stable リリースの全て
+
+"-stable" ツリーにどのような種類のパッチが受け入れられるか、どのような
+ものが受け入れられないか、についての規則-
+
+ - 明らかに正しく、テストされているものでなければならない。
+ - 文脈(変更行の前後)を含めて 100 行より大きくてはいけない。
+ - ただ一個のことだけを修正しているべき。
+ - 皆を悩ませている本物のバグを修正しなければならない。("これはバグで
+   あるかもしれないが..." のようなものではない)
+ - ビルドエラー(CONFIG_BROKENになっているものを除く), oops, ハング、デー
+   タ破壊、現実のセキュリティ問題、その他 "ああ、これはダメだね"という
+   ようなものを修正しなければならない。短く言えば、重大な問題。
+ - 新しい device ID とクオークも受け入れられる。
+ - どのように競合状態が発生するかの説明も一緒に書かれていない限り、
+   "理論的には競合状態になる"ようなものは不可。
+ - いかなる些細な修正も含めることはできない。(スペルの修正、空白のクリー
+   ンアップなど)
+ - Documentation/process/submitting-patches.rst の規則に従ったものでなければならない。
+ - パッチ自体か同等の修正が Linus のツリーに既に存在しなければならない。
+　 Linus のツリーでのコミットID を -stable へのパッチ投稿の際に引用す
+   ること。
+
+-stable ツリーにパッチを送付する手続き-
+
+ - 上記の規則に従っているかを確認した後に、stable@vger.kernel.org にパッチ
+   を送る。
+ - 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合
+   には NAK を受け取る。この反応は開発者たちのスケジュールによって、数
+   日かかる場合がある。
+ - もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの
+   メンテナーによるレビューのために -stable キューに追加される。
+ - パッチに stable@vger.kernel.org のアドレスが付加されているときには、それ
+   が Linus のツリーに入る時に自動的に stable チームに email される。
+ - セキュリティパッチはこのエイリアス (stable@vger.kernel.org) に送られるべ
+   きではなく、代わりに security@kernel.org のアドレスに送られる。
+
+レビューサイクル-
+
+ - -stable メンテナがレビューサイクルを決めるとき、パッチはレビュー委
+   員会とパッチが影響する領域のメンテナ(提供者がその領域のメンテナで無
+   い限り)に送られ、linux-kernel メーリングリストにCCされる。
+ - レビュー委員会は 48時間の間に ACK か NAK を出す。
+ - もしパッチが委員会のメンバから却下されるか、メンテナ達やメンバが気付
+   かなかった問題が持ちあがり、linux-kernel メンバがパッチに異議を唱え
+   た場合には、パッチはキューから削除される。
+ - レビューサイクルの最後に、ACK を受けたパッチは最新の -stable リリー
+   スに追加され、その後に新しい -stable リリースが行われる。
+ - セキュリティパッチは、通常のレビューサイクルを通らず、セキュリティ
+   カーネルチームから直接 -stable ツリーに受け付けられる。
+   この手続きの詳細については kernel security チームに問い合わせること。
+
+レビュー委員会-
+
+ - この委員会は、このタスクについて活動する多くのボランティアと、少数の
+   非ボランティアのカーネル開発者達で構成されている。
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ja_JP/SubmitChecklist linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/SubmitChecklist
--- linux-libre-4.9-gnu/Documentation/translations/ja_JP/SubmitChecklist	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/SubmitChecklist	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,111 @@
+NOTE:
+This is a version of Documentation/process/submit-checklist.rst into Japanese.
+This document is maintained by Takenori Nagano <t-nagano@ah.jp.nec.com>
+and the JF Project team <http://www.linux.or.jp/JF/>.
+If you find any difference between this document and the original file
+or a problem with the translation,
+please contact the maintainer of this file or JF project.
+
+Please also note that the purpose of this file is to be easier to read
+for non English (read: Japanese) speakers and is not intended as a
+fork. So if you have any comments or updates of this file, please try
+to update the original English file first.
+
+Last Updated: 2008/07/14
+==================================
+これは、
+linux-2.6.26/Documentation/process/submit-checklist.rst の和訳です。
+
+翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
+翻訳日： 2008/07/14
+翻訳者： Takenori Nagano <t-nagano at ah dot jp dot nec dot com>
+校正者： Masanori Kobayashi さん <zap03216 at nifty dot ne dot jp>
+==================================
+
+
+Linux カーネルパッチ投稿者向けチェックリスト
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+本書では、パッチをより素早く取り込んでもらいたい開発者が実践すべき基本的な事柄
+をいくつか紹介します。ここにある全ての事柄は、Documentation/process/submitting-patches.rst
+などのLinuxカーネルパッチ投稿に際しての心得を補足するものです。
+
+ 1: 妥当なCONFIGオプションや変更されたCONFIGオプション、つまり =y, =m, =n
+    全てで正しくビルドできることを確認してください。その際、gcc及びリンカが
+    warningやerrorを出していないことも確認してください。
+
+ 2: allnoconfig, allmodconfig オプションを用いて正しくビルドできることを
+    確認してください。
+
+ 3: 手許のクロスコンパイルツールやOSDLのPLMのようなものを用いて、複数の
+    アーキテクチャにおいても正しくビルドできることを確認してください。
+
+ 4: 64bit長の'unsigned long'を使用しているppc64は、クロスコンパイルでの
+    チェックに適当なアーキテクチャです。
+
+ 5: カーネルコーディングスタイルに準拠しているかどうか確認してください(!)
+
+ 6: CONFIGオプションの追加・変更をした場合には、CONFIGメニューが壊れていない
+    ことを確認してください。
+
+ 7: 新しくKconfigのオプションを追加する際には、必ずそのhelpも記述してください。
+
+ 8: 適切なKconfigの依存関係を考えながら慎重にチェックしてください。
+    ただし、この作業はマシンを使ったテストできちんと行うのがとても困難です。
+    うまくやるには、自分の頭で考えることです。
+
+ 9: sparseを利用してちゃんとしたコードチェックをしてください。
+
+10: 'make checkstack' と 'make namespacecheck' を利用し、問題が発見されたら
+    修正してください。'make checkstack' は明示的に問題を示しませんが、どれか
+    １つの関数が512バイトより大きいスタックを使っていれば、修正すべき候補と
+    なります。
+
+11: グローバルなkernel API を説明する kernel-doc をソースの中に含めてください。
+    ( staticな関数においては必須ではありませんが、含めてもらっても結構です )
+    そして、'make htmldocs' もしくは 'make mandocs' を利用して追記した
+    ドキュメントのチェックを行い、問題が見つかった場合には修正を行ってください。
+
+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: もしパッチがディスクのI/O性能などに影響を与えるようであれば、
+    'CONFIG_LBDAF'オプションを有効にした場合と無効にした場合の両方で
+    テストを実施してみてください。
+
+15: lockdepの機能を全て有効にした上で、全てのコードパスを評価してください。
+
+16: /proc に新しいエントリを追加した場合には、Documentation/ 配下に
+    必ずドキュメントを追加してください。
+
+17: 新しいブートパラメータを追加した場合には、
+    必ずDocumentation/admin-guide/kernel-parameters.rst に説明を追加してください。
+
+18: 新しくmoduleにパラメータを追加した場合には、MODULE_PARM_DESC()を
+    利用して必ずその説明を記述してください。
+
+19: 新しいuserspaceインタフェースを作成した場合には、Documentation/ABI/ に
+    Documentation/ABI/README を参考にして必ずドキュメントを追加してください。
+
+20: 'make headers_check'を実行して全く問題がないことを確認してください。
+
+21: 少なくともslabアロケーションとpageアロケーションに失敗した場合の
+    挙動について、fault-injectionを利用して確認してください。
+    Documentation/fault-injection/ を参照してください。
+
+    追加したコードがかなりの量であったならば、サブシステム特有の
+    fault-injectionを追加したほうが良いかもしれません。
+
+22: 新たに追加したコードは、`gcc -W'でコンパイルしてください。
+    このオプションは大量の不要なメッセージを出力しますが、
+    "warning: comparison between signed and unsigned" のようなメッセージは、
+    バグを見つけるのに役に立ちます。
+
+23: 投稿したパッチが -mm パッチセットにマージされた後、全ての既存のパッチや
+    VM, VFS およびその他のサブシステムに関する様々な変更と、現時点でも共存
+    できることを確認するテストを行ってください。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ja_JP/SubmittingPatches linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/SubmittingPatches
--- linux-libre-4.9-gnu/Documentation/translations/ja_JP/SubmittingPatches	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ja_JP/SubmittingPatches	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,719 @@
+NOTE:
+This is a version of Documentation/process/submitting-patches.rst into Japanese.
+This document is maintained by Keiichi KII <k-keiichi@bx.jp.nec.com>
+and the JF Project team <http://www.linux.or.jp/JF/>.
+If you find any difference between this document and the original file
+or a problem with the translation,
+please contact the maintainer of this file or JF project.
+
+Please also note that the purpose of this file is to be easier to read
+for non English (read: Japanese) speakers and is not intended as a
+fork. So if you have any comments or updates of this file, please try
+to update the original English file first.
+
+Last Updated: 2011/06/09
+
+==================================
+これは、
+linux-2.6.39/Documentation/process/submitting-patches.rst の和訳
+です。
+翻訳団体： JF プロジェクト < http://www.linux.or.jp/JF/ >
+翻訳日： 2011/06/09
+翻訳者： Keiichi Kii <k-keiichi at bx dot jp dot nec dot com>
+校正者： Masanari Kobayashi さん <zap03216 at nifty dot ne dot jp>
+         Matsukura さん <nbh--mats at nifty dot com>
+         Takeshi Hamasaki さん <hmatrjp at users dot sourceforge dot jp>
+==================================
+
+        Linux カーネルに変更を加えるための Howto
+        又は
+        かの Linus Torvalds の取り扱い説明書
+
+Linux カーネルに変更を加えたいと思っている個人又は会社にとって、パッ
+チの投稿に関連した仕組みに慣れていなければ、その過程は時々みなさんを
+おじけづかせることもあります。この文章はあなたの変更を大いに受け入れ
+てもらえやすくする提案を集めたものです。
+
+コードを投稿する前に、Documentation/process/submit-checklist.rst の項目リストに目
+を通してチェックしてください。もしあなたがドライバーを投稿しようとし
+ているなら、Documentation/process/submitting-drivers.rst にも目を通してください。
+
+--------------------------------------------
+セクション1 パッチの作り方と送り方
+--------------------------------------------
+
+1) 「 diff -up 」
+------------
+
+パッチの作成には「 diff -up 」又は「 diff -uprN 」を使ってください。
+
+Linux カーネルに対する全ての変更は diff(1) コマンドによるパッチの形式で
+生成してください。パッチを作成するときには、diff(1) コマンドに「 -u 」引
+数を指定して、unified 形式のパッチを作成することを確認してください。また、
+変更がどの C 関数で行われたのかを表示する「 -p 」引数を使ってください。
+この引数は生成した差分をずっと読みやすくしてくれます。パッチは Linux
+カーネルソースの中のサブディレクトリではなく Linux カーネルソースのルート
+ディレクトリを基準にしないといけません。
+
+1個のファイルについてのパッチを作成するためには、ほとんどの場合、
+以下の作業を行えば十分です。
+
+	SRCTREE= linux-2.6
+	MYFILE=  drivers/net/mydriver.c
+
+	cd $SRCTREE
+	cp $MYFILE $MYFILE.orig
+	vi $MYFILE	# make your change
+	cd ..
+	diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+複数のファイルについてのパッチを作成するためには、素の( vanilla )、す
+なわち変更を加えてない Linux カーネルを展開し、自分の Linux カーネル
+ソースとの差分を生成しないといけません。例えば、
+
+	MYSRC= /devel/linux-2.6
+
+	tar xvfz linux-2.6.12.tar.gz
+	mv linux-2.6.12 linux-2.6.12-vanilla
+	diff -uprN -X linux-2.6.12-vanilla/Documentation/dontdiff \
+		linux-2.6.12-vanilla $MYSRC > /tmp/patch
+
+dontdiff ファイルには Linux カーネルのビルドプロセスの過程で生成された
+ファイルの一覧がのっています。そして、それらはパッチを生成する diff(1)
+コマンドで無視されるべきです。dontdiff ファイルは 2.6.12 以後のバージョ
+ンの Linux カーネルソースツリーに含まれています。それより前のバージョン
+の Linux カーネルソースツリーに対する dontdiff ファイルは、
+<http://www.xenotime.net/linux/doc/dontdiff>から取得することができます。
+
+投稿するパッチの中に関係のない余分なファイルが含まれていないことを確
+認してください。diff(1) コマンドで生成したパッチがあなたの意図したとお
+りのものであることを確認してください。
+
+もしあなたのパッチが多くの差分を生み出すのであれば、あなたはパッチ
+を意味のあるひとまとまりごとに分けたいと思うかもしれません。
+これは他のカーネル開発者にとってレビューしやすくなるので、あなたの
+パッチを受け入れてもらうためにはとても重要なことです。これを補助でき
+る多くのスクリプトがあります。
+
+Quilt:
+http://savannah.nongnu.org/projects/quilt
+
+2) パッチに対する説明
+
+パッチの中の変更点に対する技術的な詳細について説明してください。
+
+説明はできる限り具体的に。もっとも悪い説明は「ドライバー X を更新」、
+「ドライバー X に対するバグフィックス」あるいは「このパッチはサブシス
+テム X に対する更新を含んでいます。どうか取り入れてください。」などです。
+
+パッチの説明を Linux カーネルのソースコードマネジメントシステム「 git 」の
+コミットログとして簡単に引用できる形で書けば、メンテナから感謝されるでしょう。
+以下の #15 を見てください。
+
+説明が長くなりだしたのであれば、おそらくそれはパッチを分ける必要がある
+という兆候です。次の #3 を見てください。
+
+パッチ(シリーズ)を(再)投稿する時、十分なパッチの説明とそのパッチが必要な理由を
+パッチに含めてください。ただ「これはパッチ(シリーズ)のバージョン N」とだけ
+書かないでください。そして、パッチをマージする人にパッチの説明を探させそれを
+パッチに追記させるため、過去のバージョンのパッチやそのパッチの URL を参照する
+手間をかけさせないでください。
+つまり、パッチシリーズとその説明は一緒にあるべきです。これはパッチをマージする
+人、レビューする人、どちらのためにもなります。レビューする人の中には、おそらく
+過去のバージョンのパッチを受け取ってもいない人がいます。
+
+登録済みのバグエントリを修正するパッチであれば、そのバグエントリを示すバグ ID
+や URL を明記してください。
+
+3) パッチの分割
+
+意味のあるひとまとまりごとに変更を個々のパッチファイルに分けてください。
+
+例えば、もし1つのドライバーに対するバグフィックスとパフォーマンス強
+化の両方の変更を含んでいるのであれば、その変更を2つ以上のパッチに分
+けてください。もし変更箇所に API の更新と、その新しい API を使う新たな
+ドライバーが含まれているなら、2つのパッチに分けてください。
+
+一方で、もしあなたが多数のファイルに対して意味的に同じ1つの変更を加え
+るのであれば、その変更を1つのパッチにまとめてください。言いかえると、
+意味的に同じ1つの変更は1つのパッチの中に含まれます。
+
+あるパッチが変更を完結させるために他のパッチに依存していたとしても、
+それは問題ありません。パッチの説明の中で「このパッチはパッチ X に依存
+している」と簡単に注意書きをつけてください。
+
+もしパッチをより小さなパッチの集合に凝縮することができないなら、まずは
+15かそこらのパッチを送り、そのレビューと統合を待って下さい。
+
+4) パッチのスタイルチェック
+
+あなたのパッチが基本的な( Linux カーネルの)コーディングスタイルに違反し
+ていないかをチェックして下さい。その詳細を Documentation/process/coding-style.rst で
+見つけることができます。コーディングスタイルの違反はレビューする人の
+時間を無駄にするだけなので、恐らくあなたのパッチは読まれることすらなく
+拒否されるでしょう。
+
+あなたはパッチを投稿する前に最低限パッチスタイルチェッカー
+( scripts/checkpatch.pl )を利用してパッチをチェックすべきです。
+もしパッチに違反がのこっているならば、それらの全てについてあなたは正当な
+理由を示せるようにしておく必要があります。
+
+5) 電子メールの宛先の選び方
+
+MAINTAINERS ファイルとソースコードに目を通してください。そして、その変
+更がメンテナのいる特定のサブシステムに加えられるものであることが分か
+れば、その人に電子メールを送ってください。
+
+もし、メンテナが載っていなかったり、メンテナからの応答がないなら、
+LKML ( linux-kernel@vger.kernel.org )へパッチを送ってください。ほとんど
+のカーネル開発者はこのメーリングリストに目を通しており、変更に対して
+コメントを得ることができます。
+
+15個より多くのパッチを同時に vger.kernel.org のメーリングリストへ送らな
+いでください!!!
+
+Linus Torvalds は Linux カーネルに入る全ての変更に対する最終的な意思決定者
+です。電子メールアドレスは torvalds@linux-foundation.org になります。彼は
+多くの電子メールを受け取っているため、できる限り彼に電子メールを送るのは
+避けるべきです。
+
+バグフィックスであったり、自明な変更であったり、話し合いをほとんど
+必要としないパッチは Linus へ電子メールを送るか CC しなければなりません。
+話し合いを必要としたり、明確なアドバンテージがないパッチは、通常まず
+は LKML へ送られるべきです。パッチが議論された後にだけ、そのパッチを
+Linus へ送るべきです。
+
+6) CC (カーボンコピー)先の選び方
+
+特に理由がないなら、LKML にも CC してください。
+
+Linus 以外のカーネル開発者は変更に気づく必要があり、その結果、彼らはそ
+の変更に対してコメントをくれたり、コードに対してレビューや提案をくれ
+るかもしれません。LKML とは Linux カーネル開発者にとって一番中心的なメー
+リングリストです。USB やフレームバッファデバイスや VFS や SCSI サブシステ
+ムなどの特定のサブシステムに関するメーリングリストもあります。あなた
+の変更に、はっきりと関連のあるメーリングリストについて知りたければ
+MAINTAINERS ファイルを参照してください。
+
+VGER.KERNEL.ORG でホスティングされているメーリングリストの一覧が下記の
+サイトに載っています。
+<http://vger.kernel.org/vger-lists.html>
+
+もし、変更がユーザランドのカーネルインタフェースに影響を与え
+るのであれば、MAN-PAGES のメンテナ( MAINTAINERS ファイルに一覧
+があります)に man ページのパッチを送ってください。少なくとも
+情報がマニュアルページの中に入ってくるように、変更が起きたという
+通知を送ってください。
+
+たとえ、メンテナが #5 で反応がなかったとしても、メンテナのコードに変更を
+加えたときには、いつもメンテナに CC するのを忘れないようにしてください。
+
+小さなパッチであれば、Trivial Patch Monkey(ちょっとしたパッチを集めている)
+<trivial@kernel.org>に CC してもいいです。その現管理者については MAINTAINERS
+ファイルを見てください。ちょっとしたパッチとは以下のルールのどれか1つを満たして
+いなければなりません。
+ ・ドキュメントのスペルミスの修正
+ ・grep(1) コマンドによる検索を困難にしているスペルの修正
+ ・コンパイル時の警告の修正(無駄な警告が散乱することは好ましくないた
+   めです)
+ ・コンパイル問題の修正(それらの修正が本当に正しい場合に限る)
+ ・実行時の問題の修正(それらの修正が本当に問題を修正している場合に限る)
+ ・廃止予定の関数やマクロを使用しているコードの除去(例 check_region )
+ ・問い合わせ先やドキュメントの修正
+ ・移植性のないコードから移植性のあるコードへの置き換え(小さい範囲で
+   あればアーキテクチャ特有のことでも他の人がコピーできます)
+ ・作者やメンテナによる修正(すなわち patch monkey の再転送モード)
+
+7) MIME やリンクや圧縮ファイルや添付ファイルではなくプレインテキストのみ
+
+Linus や他のカーネル開発者はあなたが投稿した変更を読んで、コメントでき
+る必要があります。カーネル開発者にとって、あなたが書いたコードの特定の
+部分にコメントをするために、標準的な電子メールクライアントで変更が引用
+できることは重要です。
+
+上記の理由で、すべてのパッチは文中に含める形式の電子メールで投稿さ
+れるべきです。警告：あなたがパッチをコピー&ペーストする際には、パッ
+チを改悪するエディターの折り返し機能に注意してください。
+
+パッチを圧縮の有無に関わらず MIME 形式で添付しないでください。多くのポ
+ピュラーな電子メールクライアントは MIME 形式の添付ファイルをプレーンテ
+キストとして送信するとは限らないでしょう。そうなると、電子メールクラ
+イアントがコードに対するコメントを付けることをできなくします。また、
+MIME 形式の添付ファイルは Linus に手間を取らせることになり、その変更を
+受け入れてもらう可能性が低くなってしまいます。
+
+例外：お使いの電子メールクライアントがパッチをめちゃくちゃにするので
+あれば、誰かが MIME 形式のパッチを再送するよう求めるかもしれません。
+
+余計な変更を加えずにあなたのパッチを送信するための電子メールクライアントの設定
+のヒントについては Documentation/process/email-clients.rst を参照してください。
+
+8) 電子メールのサイズ
+
+パッチを Linus へ送るときは常に #7 の手順に従ってください。
+
+大きなパッチはメーリングリストやメンテナにとって不親切です。パッチが
+未圧縮で 300KB を超えるようであるなら、インターネット上のアクセス可能な
+サーバに保存し、保存場所を示す URL を伝えるほうが適切です。
+
+9) カーネルバージョンの明記
+
+パッチが対象とするカーネルのバージョンをパッチの概要か電子メールの
+サブジェクトに付けることが重要です。
+
+パッチが最新バージョンのカーネルに正しく適用できなければ、Linus は
+そのパッチを採用しないでしょう。
+
+10) がっかりせず再投稿
+
+パッチを投稿した後は、辛抱強く待っていてください。Linus があなたのパッ
+チを気に入って採用すれば、Linus がリリースする次のバージョンのカーネル
+の中で姿を見せるでしょう。
+
+しかし、パッチが次のバージョンのカーネルに入っていないなら、いくつもの
+理由があるのでしょう。その原因を絞り込み、間違っているものを正し、更新
+したパッチを投稿するのはあなたの仕事です。
+
+Linus があなたのパッチに対して何のコメントもなく不採用にすることは極め
+て普通のことです。それは自然な姿です。もし、Linus があなたのパッチを受
+け取っていないのであれば、以下の理由が考えられます。
+* パッチが最新バージョンの Linux カーネルにきちんと適用できなかった
+* パッチが LKML で十分に議論されていなかった
+* スタイルの問題(セクション2を参照)
+* 電子メールフォーマットの問題(このセクションを参照)
+* パッチに対する技術的な問題
+* Linus はたくさんの電子メールを受け取っているので、どさくさに紛れて見
+  失った
+* 不愉快にさせている
+
+判断できない場合は、LKML にコメントを頼んでください。
+
+11) サブジェクトに「 PATCH 」
+
+Linus や LKML への大量の電子メールのために、サブジェクトのプレフィックスに
+「 [PATCH] 」を付けることが慣習となっています。これによって Linus や他の
+カーネル開発者がパッチであるのか、又は、他の議論に関する電子メールであるの
+かをより簡単に識別できます。
+
+12) パッチへの署名
+
+誰が何をしたのかを追いかけやすくするために (特に、パッチが何人かの
+メンテナを経て最終的に Linux カーネルに取り込まれる場合のために)、電子
+メールでやり取りされるパッチに対して「 sign-off 」という手続きを導入し
+ました。
+
+「 sign-off 」とは、パッチがあなたの書いたものであるか、あるいは、
+あなたがそのパッチをオープンソースとして提供する権利を保持している、
+という証明をパッチの説明の末尾に一行記載するというものです。
+ルールはとても単純です。以下の項目を確認して下さい。
+
+        原作者の証明書( DCO ) 1.1
+
+        このプロジェクトに寄与するものとして、以下のことを証明する。
+
+        (a) 本寄与は私が全体又は一部作成したものであり、私がそのファイ
+            ル中に明示されたオープンソースライセンスの下で公開する権利
+            を持っている。もしくは、
+
+        (b) 本寄与は、私が知る限り、適切なオープンソースライセンスでカバ
+            ーされている既存の作品を元にしている。同時に、私はそのライセ
+            ンスの下で、私が全体又は一部作成した修正物を、ファイル中で示
+            される同一のオープンソースライセンスで(異なるライセンスの下で
+            投稿することが許可されている場合を除いて)投稿する権利を持って
+            いる。もしくは、
+
+        (c) 本寄与は(a)、(b)、(c)を証明する第3者から私へ直接提供された
+            ものであり、私はそれに変更を加えていない。
+
+        (d) 私はこのプロジェクトと本寄与が公のものであることに理解及び同意す
+            る。同時に、関与した記録(投稿の際の全ての個人情報と sign-off を
+            含む)が無期限に保全されることと、当該プロジェクト又は関連する
+            オープンソースライセンスに沿った形で再配布されることに理解及び
+            同意する。
+
+もしこれに同意できるなら、以下のような1行を追加してください。
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+
+実名を使ってください。(残念ですが、偽名や匿名による寄与はできません。)
+
+人によっては sign-off の近くに追加のタグを付加しています。それらは今のところ
+無視されますが、あなたはそのタグを社内の手続きに利用したり、sign-off に特別
+な情報を示したりすることができます。
+
+あなたがサブシステムまたはブランチのメンテナであれば、受け取ったパッチを自身の
+ツリーにマージするために、わずかに変更が必要となる場合があります。なぜなら
+あなたのツリーの中のコードと投稿者のツリーの中のコードは同一ではないためです。
+もし、あなたが厳密に上記ルール(c)にこだわるのであれば、投稿者に再度差分を
+とるよう依頼すべきです。しかし、これは時間とエネルギーを非生産的に浪費する
+ことになります。ルール(b)はあなたにコードを修正する権利を与えてくれます。
+しかし、投稿者のコードを修正し、その修正によるバグを投稿者に押し付けてしまう
+ことはとても失礼なことです。この問題を解決するために、末尾の投稿者の
+Signed-off-by とあなたがその末尾に追加する Signed-off-by の間に、修正を
+加えたことを示す1行を追加することが推奨されています。
+(その1行の書き方に)決まりはありませんが、大括弧の中に電子メールアドレスや氏名
+と修正内容を記載するやり方は目につきやすく、最終段階での変更の責任があなたに
+あることを明確にするのに十分な方法のようです。例えば、
+
+	Signed-off-by: Random J Developer <random@developer.example.org>
+	[lucky@maintainer.example.org: struct foo moved from foo.c to foo.h]
+	Signed-off-by: Lucky K Maintainer <lucky@maintainer.example.org>
+
+あなたが安定版のブランチを管理しており、作成者のクレジット、変更の追跡、
+修正のマージ、と同時に苦情からの投稿者の保護を行いたい場合、この慣習は特に
+有用となります。いかなる事情があってもチェンジログに出てくる作成者の
+アイデンティティ情報(From ヘッダ)は変更できないことに注意してください。
+
+バックポートする人のための特別な注意事項。追跡を容易に行うために、コミット
+メッセージのトップ(サブジェクト行のすぐ後)にパッチの起源を示す情報を記述する
+ことは一般的で有用な慣習です。例えば、これは 2.6-stable ツリーでの一例です。    
+
+    Date:   Tue May 13 19:10:30 2008 +0000
+
+        SCSI: libiscsi regression in 2.6.25: fix nop timer handling
+
+        commit 4cf1043593db6a337f10e006c23c69e5fc93e722 upstream
+
+そして、これは 2.4 ツリーでの一例です。
+
+    Date:   Tue May 13 22:12:27 2008 +0200
+
+        wireless, airo: waitbusy() won't delay
+
+        [backport of 2.6 commit b7acbdfbd1f277c1eb23f344f899cfa4cd0bf36a]
+
+どんな形式であれ、この情報はあなたのツリーを追跡する人やあなたのツリーのバグを
+解決しようとしている人にとって価値のある支援となります。
+
+13) いつ Acked-by: と Cc: を使うのか
+
+「 Signed-off-by: 」タグはその署名者がパッチの開発に関わっていたことやパッチ
+の伝播パスにいたことを示しています。
+
+ある人が直接パッチの準備や作成に関わっていないけれど、その人のパッチに対す
+る承認を記録し、示したいとします。その場合、その人を示すのに Acked-by: が使
+えます。Acked-by: はパッチのチェンジログにも追加されます。
+
+パッチの影響を受けるコードのメンテナがパッチに関わっていなかったり、パッチ
+の伝播パスにいなかった時にも、メンテナは Acked-by: をしばしば利用します。
+
+Acked-by: は Signed-off-by: のように公式なタグではありません。それはメンテナが
+少なくともパッチをレビューし、同意を示しているという記録です。そのような
+ことからパッチをマージする人がメンテナの「うん、良いと思うよ」という発言を
+Acked-by: へ置き換えることがあります。
+
+Acked-by: が必ずしもパッチ全体の承認を示しているわけではありません。例えば、
+あるパッチが複数のサブシステムへ影響を与えており、その中の1つのサブシステム
+のメンテナからの Acked-by: を持っているとします。その場合、Acked-by: は通常
+そのメンテナのコードに影響を与える一部分だけに対する承認を示しています。
+この点は、ご自分で判断してください。(その Acked-by: が)疑わしい場合は、
+メーリングリストアーカイブの中の大元の議論を参照すべきです。
+
+パッチにコメントする機会を持っていたが、その時にコメントしなかった人がいれば、
+その人を指す「Cc:」タグを任意で追加してもかまいません。これは指定された人からの
+明確なアクションなしに付与できる唯一のタグです。
+このタグはパッチに関心があると思われる人達がそのパッチの議論に含まれていたこと
+を明文化します。
+
+14) Reported-by と Tested-by: と Reviewed-by: の利用
+
+他の誰かによって報告された問題を修正するパッチであれば、問題報告者という寄与を
+クレジットするために、Reported-by: タグを追加することを検討してください。
+こまめにバグ報告者をクレジットしていくことで、うまくいけばその人たちが将来再び
+コミュニティの力となってくれるでしょう。
+ただし、報告者の許可無くこのタグを追加しないように注意してください。特に、
+問題が公の場で報告されていなかったのであれば。
+
+Tested-by: タグはタグで指定された人によって(ある環境下で)パッチのテストに成功
+していることを示します。このタグはメンテナにテストが実施済みであることを
+知らせ、将来の関連パッチのテスト協力者を見つける方法を提供し、テスト実施者に
+対するクレジットを保証します。
+
+Reviewed-by: タグは、それとは異なり、下記のレビューア宣言の下にレビューされ、
+受け入れ可能とみなされたパッチであることを示します。
+
+        レビューアによる監督宣言
+
+        私は Reviewed-by: タグを提示することによって、以下のことを明言する。
+
+        (a) 私はメインラインカーネルへの統合に向け、その妥当性及び「即応性
+            (訳注)」を検証し、技術的側面からパッチをレビュー済みである。
+
+        訳注:
+        「即応性」の原文は "readiness"。
+        パッチが十分な品質を持っており、メインラインカーネルへの統合を即座に
+        行うことができる状態であるかどうかを "readiness" という単語で表現
+        している。
+
+        (b) パッチに関するあらゆる問題、懸念、あるいは、疑問は投稿者へ伝達済み
+            である。私はそれらのコメントに対する投稿者の返答に満足している。
+
+        (c) 投稿に伴い改良されるコードがある一方で、現時点で、私は(1)それが
+            カーネルにとって価値のある変更であること、そして、(2)統合に際して
+            議論になり得るような問題はないものと確信している。
+
+        (d) 私はパッチをレビューし適切であると確信している一方で、あらゆる
+            状況においてその宣言した目的や機能が正しく実現することに関して、
+            いかなる保証もしない(特にどこかで明示しない限り)。
+
+Reviewd-by タグはそのパッチがカーネルに対して適切な修正であって、深刻な技術的
+問題を残していないという意見の宣言です。興味のあるレビューアは誰でも(レビュー
+作業を終えたら)パッチに対して Reviewed-by タグを提示できます。このタグは
+レビューアの寄与をクレジットする働き、レビューの進捗の度合いをメンテナに
+知らせる働きを持ちます。そのパッチの領域に詳しく、そして、しっかりとした
+レビューを実施したレビューアによって提供される時、Reviewed-by: タグがあなたの
+パッチをカーネルにマージする可能性を高めるでしょう。
+
+15) 標準的なパッチのフォーマット
+
+標準的なパッチのサブジェクトは以下のとおりです。
+
+    Subject: [PATCH 001/123] subsystem: summary phrase
+
+標準的なパッチの、電子メールのボディは以下の項目を含んでいます。
+
+  - パッチの作成者を明記する「 from 」行
+
+  - 空行
+
+  - 説明本体。これはこのパッチを説明するために無期限のチェンジログ
+    (変更履歴)にコピーされます。
+
+  - 上述した「 Signed-off-by: 」行。これも説明本体と同じくチェン
+    ジログ内にコピーされます。
+
+  - マーカー行は単純に「 --- 」です。
+
+  - 余計なコメントは、チェンジログには不適切です。
+
+  - 実際のパッチ(差分出力)
+
+サブジェクト行のフォーマットは、アルファベット順で電子メールをとても
+ソートしやすいものになっています。(ほとんどの電子メールクライアント
+はソートをサポートしています)パッチのサブジェクトの連番は0詰めであ
+るため、数字でのソートとアルファベットでのソートは同じ結果になります。
+
+電子メールのサブジェクト内のサブシステム表記は、パッチが適用される
+分野またはサブシステムを識別できるようにすべきです。
+
+電子メールのサブジェクトの「summary phrase」はそのパッチの概要を正確
+に表現しなければなりません。「summary phrase」をファイル名にしてはい
+けません。パッチシリーズ中でそれぞれのパッチは同じ「summary phrase」を
+使ってはいけません(「パッチシリーズ」とは順序付けられた関連のある複数の
+パッチ群です)。
+
+あなたの電子メールの「summary phrase」がそのパッチにとって世界で唯一の識別子に
+なるように心がけてください。「summary phrase」は git のチェンジログの中へ
+ずっと伝播していきます。「summary phrase」は、開発者が後でパッチを参照する
+ために議論の中で利用するかもしれません。
+人々はそのパッチに関連した議論を読むために「summary phrase」を使って google で
+検索したがるでしょう。それはまた2、3ヶ月あとで、人々が「gitk」や
+「git log --oneline」のようなツールを使用して何千ものパッチに目を通す時、
+唯一目にとまる情報となるでしょう。
+
+これらの理由のため、「summary phrase」はなぜパッチが必要であるか、パッチが何を
+変更するかの2つの情報をせいぜい70〜75文字で表現していなければなりません。
+「summary phrase」は簡潔であり説明的である表現を目指しつつ、うまく
+まとめられている概要となるべきです。
+
+「summary phrase」は「Subject: [PATCH tag] <summary phrase>」のように、
+大括弧で閉じられたタグを接頭辞として付加してもかまいません。このタグは
+「summary phrase」の一部とは考えませんが、パッチをどのように取り扱うべきかを
+表現します。
+一般的には「v1, v2, v3」のようなバージョン情報を表すタグ(過去のパッチに対する
+コメントを反映するために複数のバージョンのパッチが投稿されているのであれば)、
+「RFC」のようなコメントを要求するタグが挙げられます。パッチシリーズとして4つの
+パッチがあれば、個々のパッチに「1/4, 2/4, 3/4, 4/4」のように番号を付けても
+かまいません。これは開発者がパッチを適用する順番を確実に把握するためです。
+そして、開発者がパッチシリーズの中のすべてのパッチをもらさずレビュー或いは
+適用するのを保証するためです。
+
+サブジェクトの例を二つ
+
+    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+「 from 」行は電子メールのボディの一番最初の行でなければなりません。
+その形式は以下のとおりです。
+
+        From: Original Author <author@example.com>
+
+「 from 」行はチェンジログの中で、そのパッチの作成者としてクレジットされ
+ている人を特定するものです。「 from 」行がかけていると、電子メールのヘッ
+ダーの「 From: 」が、チェンジログの中でパッチの作成者を決定するために使わ
+れるでしょう。
+
+説明本体は無期限のソースのチェンジログにコミットされます。なので、説明
+本体はそのパッチに至った議論の詳細を忘れているある程度の技量を持っている人
+がその詳細を思い出すことができるものでなければなりません。パッチが対処する
+障害の症状(カーネルログメッセージや oops メッセージ等)を記載することは問題に
+対処可能なパッチを求めてコミットログを検索する人々にとって特に有用です。
+パッチがコンパイル問題を解決するのであれば、そのパッチを探している人が見つける
+ことができる情報だけで十分であり、コンパイル時の全てのエラーを含める必要は
+ありません。「summary phrase」と同様に、簡潔であり説明的であることが重要です。
+
+「 --- 」マーカー行はパッチ処理ツールに対して、チェンジログメッセージの終端
+部分を認識させるという重要な役目を果たします。
+
+「 --- 」マーカー行の後の追加コメントの良い使用方法の1つに diffstat コマンド
+があります。diffstat コマンドとは何のファイルが変更され、1ファイル当たり何行
+追加され何行消されたかを示すものです。diffstat コマンドは特に大きなパッチに
+おいて役立ちます。その時点でだけ又はメンテナにとってのみ関係のあるコメント
+は無期限に保存されるチェンジログにとって適切ではありません。そのため、この
+ようなコメントもマーカー行の後に書かれるべきです。
+このようなコメントの良い例として、v1 と v2 のバージョン間で何が変更されたかを
+表す「パッチの変更履歴」が挙げられます。
+
+「 --- 」マーカー行の後に diffstat コマンドの結果を含めるのであれば、ファイル
+名はカーネルソースツリーのトップディレクトリからの表記で列記されるため、横方向
+のスペースをとり過ぎないように、diffstat コマンドにオプション「 -p 1 -w 70 」
+を指定してください(インデントを含めてちょうど80列に合うでしょう)。
+
+適切なパッチのフォーマットの詳細についてはセクション3の参考文献を参照して
+ください。
+
+16) 「git pull」要求の送り方(Linus の電子メールから)
+
+間違ったブランチから引っ張るのを防ぐために、git リポジトリのアドレスと
+ブランチ名を同じ行に1行で記載してください。そうすることで、3回の連続クリック
+で全て選択できます。
+
+正しい形式は下記の通りです。
+
+	"Please pull from
+
+		git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
+
+	 to get these changes:"
+
+その結果、アドレスを自分自身でタイピングして間違えることはなくなります(実際に、
+何度か間違ったブランチから引っ張ってきてしまい、その時に diffstat の結果を
+検証して間違っていることに気づいたことがあります。どこから何を引っ張るべきかを
+「探したり」、正しいブランチ名かどうかを重ねてチェックしたりする必要が
+なくなればより快適になるでしょう)。
+
+diffstat の結果を生成するために「 git diff -M --stat --summary 」を使って
+ください。-M オプションはファイル名の変更を検知でき、--summary オプションは
+新規ファイル、削除されたファイル、名前が変更されたファイルの概要を生成します。
+
+-M オプション(ファイル名の変更検知)を指定すると、diffstat の結果はかなり
+異なってきます。git は大規模な変更(追加と削除のペア)をファイル名の変更と
+判断するためです。
+
+------------------------------------
+セクション2 - ヒントとTIPSと小技
+------------------------------------
+
+このセクションは Linux カーネルに変更を適用することに関係のある一般的な
+「お約束」の多くを載せています。物事には例外というものがあります。しか
+し例外を適用するには、本当に妥当な理由が不可欠です。あなたは恐らくこの
+セクションを Linus のコンピュータ・サイエンス101と呼ぶでしょう。
+
+1) Documentation/process/coding-style.rstを参照
+
+言うまでもなく、あなたのコードがこのコーディングスタイルからあまりに
+も逸脱していると、レビューやコメントなしに受け取ってもらえないかもし
+れません。
+
+特筆すべき例外は、コードをあるファイルから別のファイルに移動
+するときです。この場合、コードを移動するパッチでは、移動されるコード
+に関して移動以外の変更を一切加えるべきではありません。これにより、
+コードの移動とあなたが行ったコードの修正を明確に区別できるようにな
+ります。これは実際に何が変更されたかをレビューする際の大きな助けに
+なるとともに、ツールにコードの履歴を追跡させることも容易になります。
+
+投稿するより前にパッチのスタイルチェッカー( scripts/checkpatch.pl )で
+あなたのパッチをチェックしてください。このスタイルチェッカーは最終結
+論としてではなく、指標としてみるべきです。もし、あなたのコードが違反
+はしているが修正するより良く見えるのであれば、おそらくそのままにする
+のがベストです。
+
+スタイルチェッカーによる3段階のレポート:
+ - エラー: 間違っている可能性が高い
+ - 警告：注意してレビューする必要がある
+ - チェック：考慮する必要がある
+
+あなたはパッチに残っている全ての違反について、それがなぜ必要なのか正当な
+理由を示せるようにしておく必要があります。
+
+2) #ifdefは見苦しい
+
+ifdef が散乱したコードは、読むのもメンテナンスするのも面倒です。コードの中
+で ifdef を使わないでください。代わりに、ヘッダファイルの中に ifdef を入れて、
+条件付きで、コードの中で使われる関数を「 static inline 」関数かマクロで定義し
+てください。後はコンパイラが、何もしない箇所を最適化して取り去ってくれるで
+しょう。
+
+まずいコードの簡単な例
+
+	dev = alloc_etherdev (sizeof(struct funky_private));
+	if (!dev)
+		return -ENODEV;
+	#ifdef CONFIG_NET_FUNKINESS
+	init_funky_net(dev);
+	#endif
+
+クリーンアップしたコードの例
+
+(in header)
+	#ifndef CONFIG_NET_FUNKINESS
+	static inline void init_funky_net (struct net_device *d) {}
+	#endif
+
+(in the code itself)
+	dev = alloc_etherdev (sizeof(struct funky_private));
+	if (!dev)
+		return -ENODEV;
+	init_funky_net(dev);
+
+3) マクロより「 static inline 」を推奨
+
+「 static inline 」関数はマクロよりもずっと推奨されています。それらは、
+型安全性があり、長さにも制限が無く、フォーマットの制限もありません。
+gcc においては、マクロと同じくらい軽いです。
+
+マクロは「 static inline 」が明らかに不適切であると分かる場所(高速化パスの
+いくつかの特定のケース)や「 static inline 」関数を使うことができないような
+場所(マクロの引数の文字列連結のような)にだけ使われるべきです。
+
+「 static inline 」は「 static __inline__ 」や「 extern inline 」や
+「 extern __inline__ 」よりも適切です。
+
+4) 設計に凝りすぎるな
+
+それが有用になるかどうか分からないような不明瞭な将来を見越した設計
+をしないでください。「できる限り簡単に、そして、それ以上簡単になら
+ないような設計をしてください。」
+
+----------------------
+セクション3 参考文献
+----------------------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/2005/03/31/>
+  <http://www.kroah.com/log/2005/07/08/>
+  <http://www.kroah.com/log/2005/10/19/>
+  <http://www.kroah.com/log/2006/01/11/>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lkml.org/lkml/2005/7/11/336>
+
+Kernel Documentation/process/coding-style.rst:
+  <http://users.sosdg.org/~qiyong/lxr/source/Documentation/process/coding-style.rst>
+
+Linus Torvalds's mail on the canonical patch format:
+  <http://lkml.org/lkml/2005/4/7/183>
+
+Andi Kleen, "On submitting kernel patches"
+  Some strategies to get difficult or controversial changes in.
+  http://halobates.de/on-submitting-patches.pdf
+
+--
+
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ko_KR/howto.rst linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/howto.rst
--- linux-libre-4.9-gnu/Documentation/translations/ko_KR/howto.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/howto.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,637 @@
+NOTE:
+This is a version of Documentation/process/howto.rst translated into korean
+This document is maintained by Minchan Kim <minchan@kernel.org>
+If you find any difference between this document and the original file or
+a problem with the translation, please contact the maintainer of this file.
+
+Please also note that the purpose of this file is to be easier to
+read for non English (read: korean) speakers and is not intended as
+a fork. So if you have any comments or updates for this file please
+try to update the original English file first.
+
+----------------------------------
+
+이 문서는
+Documentation/process/howto.rst
+의 한글 번역입니다.
+
+역자： 김민찬 <minchan@kernel.org>
+감수： 이제이미 <jamee.lee@samsung.com>
+
+----------------------------------
+
+
+어떻게 리눅스 커널 개발을 하는가
+================================
+
+이 문서는 커널 개발에 있어 가장 중요한 문서이다. 이 문서는
+리눅스 커널 개발자가 되는 법과 리눅스 커널 개발 커뮤니티와 일하는
+법을 담고있다. 커널 프로그래밍의 기술적인 측면과 관련된 내용들은
+포함하지 않으려고 하였지만 올바른 길로 여러분을 안내하는 데는 도움이
+될 것이다.
+
+이 문서에서 오래된 것을 발견하면 문서의 아래쪽에 나열된 메인테이너에게
+패치를 보내달라.
+
+
+소개
+----
+
+자, 여러분은 리눅스 커널 개발자가 되는 법을 배우고 싶은가? 아니면
+상사로부터"이 장치를 위한 리눅스 드라이버를 작성하시오"라는 말을
+들었는가? 이 문서의 목적은 여러분이 겪게 될 과정과 커뮤니티와 협력하는
+법을 조언하여 여러분의 목적을 달성하기 위해 필요한 것 모두를 알려주기
+위함이다.
+
+커널은 대부분은 C로 작성되어 있고 몇몇 아키텍쳐의 의존적인 부분은
+어셈블리로 작성되어 있다. 커널 개발을 위해 C를 잘 이해하고 있어야 한다.
+여러분이 특정 아키텍쳐의 low-level 개발을 할 것이 아니라면
+어셈블리(특정 아키텍쳐)는 잘 알아야 할 필요는 없다.
+다음의 참고서적들은 기본에 충실한 C 교육이나 수년간의 경험에 견주지는
+못하지만 적어도 참고 용도로는 좋을 것이다
+
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+
+커널은 GNU C와 GNU 툴체인을 사용하여 작성되었다. 이 툴들은 ISO C89 표준을
+따르는 반면 표준에 있지 않은 많은 확장기능도 가지고 있다. 커널은 표준 C
+라이브러리와는 관계없이 freestanding C 환경이어서 C 표준의 일부는
+지원되지 않는다. 임의의 long long 나누기나 floating point는 지원되지 않는다.
+때론 이런 이유로 커널이 그런 확장 기능을 가진 툴체인을 가지고 만들어졌다는
+것이 이해하기 어려울 수도 있고 게다가 불행하게도 그런 것을 정확하게 설명하는
+어떤 참고문서도 있지 않다. 정보를 얻기 위해서는 gcc info (`info gcc`)페이지를
+살펴보라.
+
+여러분은 기존의 개발 커뮤니티와 협력하는 법을 배우려고 하고 있다는 것을
+기억하라. 코딩, 스타일, 함수에 관한 훌륭한 표준을 가진 사람들이 모인
+다양한 그룹이 있다. 이 표준들은 오랜동안 크고 지역적으로 분산된 팀들에
+의해 가장 좋은 방법으로 일하기 위하여 찾은 것을 기초로 만들어져 왔다.
+그 표준들은 문서화가 잘 되어있기 때문에 가능한한 미리 많은 표준들에
+관하여 배우려고 시도하라. 다른 사람들은 여러분이나 여러분의 회사가
+일하는 방식에 적응하는 것을 원하지는 않는다.
+
+
+법적 문제
+---------
+
+리눅스 커널 소스 코드는 GPL로 배포(release)되었다. 소스트리의 메인
+디렉토리에 있는 라이센스에 관하여 상세하게 쓰여 있는 COPYING이라는
+파일을 봐라. 여러분이 라이센스에 관한 더 깊은 문제를 가지고 있다면
+리눅스 커널 메일링 리스트에 묻지말고 변호사와 연락하라. 메일링
+리스트들에 있는 사람들은 변호사가 아니기 때문에 법적 문제에 관하여
+그들의 말에 의지해서는 안된다.
+
+GPL에 관한 잦은 질문들과 답변들은 다음을 참조하라.
+
+    https://www.gnu.org/licenses/gpl-faq.html
+
+
+문서
+----
+
+리눅스 커널 소스 트리는 커널 커뮤니티와 협력하는 법을 배우기위해 훌륭한
+다양한 문서들을 가지고 있다. 새로운 기능들이 커널에 들어가게 될 때,
+그 기능을 어떻게 사용하는지에 관한 설명을 위하여 새로운 문서 파일을
+추가하는 것을 권장한다. 커널이 유저스페이스로 노출하는 인터페이스를
+변경하게 되면 변경을 설명하는 메뉴얼 페이지들에 대한 패치나 정보를
+mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다.
+
+다음은 커널 소스 트리에 있는 읽어야 할 파일들의 리스트이다.
+
+  README
+    이 파일은 리눅스 커널에 관하여 간단한 배경 설명과 커널을 설정하고
+    빌드하기 위해 필요한 것을 설명한다. 커널에 입문하는 사람들은 여기서
+    시작해야 한다.
+
+  :ref:`Documentation/process/changes.rst <changes>`
+    이 파일은 커널을 성공적으로 빌드하고 실행시키기 위해 필요한 다양한
+    소프트웨어 패키지들의 최소 버젼을 나열한다.
+
+  :ref:`Documentation/process/coding-style.rst <codingstyle>`
+    이 문서는 리눅스 커널 코딩 스타일과 그렇게 한 몇몇 이유를 설명한다.
+    모든 새로운 코드는 이 문서에 가이드라인들을 따라야 한다. 대부분의
+    메인테이너들은 이 규칙을 따르는 패치들만을 받아들일 것이고 많은 사람들이
+    그 패치가 올바른 스타일일 경우만 코드를 검토할 것이다.
+
+  :ref:`Documentation/process/submitting-patches.rst <submittingpatches>` 와 :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
+    이 파일들은 성공적으로 패치를 만들고 보내는 법을 다음의 내용들로
+    굉장히 상세히 설명하고 있다(그러나 다음으로 한정되진 않는다).
+
+       - Email 내용들
+       - Email 양식
+       - 그것을 누구에게 보낼지
+
+    이러한 규칙들을 따르는 것이 성공(역자주: 패치가 받아들여 지는 것)을
+    보장하진 않는다(왜냐하면 모든 패치들은 내용과 스타일에 관하여
+    면밀히 검토되기 때문이다). 그러나 규칙을 따르지 않는다면 거의
+    성공하지도 못할 것이다.
+
+    올바른 패치들을 만드는 법에 관한 훌륭한 다른 문서들이 있다.
+
+    "The Perfect Patch"
+        https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+    "Linux kernel patch submission format"
+        http://linux.yyz.us/patch-format.html
+
+   :ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
+    이 문서는 의도적으로 커널이 불변하는 API를 갖지 않도록 결정한
+    이유를 설명하며 다음과 같은 것들을 포함한다.
+
+       - 서브시스템 shim-layer(호환성을 위해?)
+       - 운영체제들간의 드라이버 이식성
+       - 커널 소스 트리내에 빠른 변화를 늦추는 것(또는 빠른 변화를 막는 것)
+
+    이 문서는 리눅스 개발 철학을 이해하는데 필수적이며 다른 운영체제에서
+    리눅스로 전향하는 사람들에게는 매우 중요하다.
+
+
+  :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+    여러분들이 리눅스 커널의 보안 문제를 발견했다고 생각한다면 이 문서에
+    나온 단계에 따라서 커널 개발자들에게 알리고 그 문제를 해결할 수 있도록
+    도와 달라.
+
+  :ref:`Documentation/process/management-style.rst <managementstyle>`
+    이 문서는 리눅스 커널 메인테이너들이 그들의 방법론에 녹아 있는
+    정신을 어떻게 공유하고 운영하는지를 설명한다. 이것은 커널 개발에 입문하는
+    모든 사람들(또는 커널 개발에 작은 호기심이라도 있는 사람들)이
+    읽어야 할 중요한 문서이다. 왜냐하면 이 문서는 커널 메인테이너들의
+    독특한 행동에 관하여 흔히 있는 오해들과 혼란들을 해소하고 있기
+    때문이다.
+
+  :ref:`Documentation/process/stable_kernel_rules.rst <stable_kernel_rules>`
+    이 문서는 안정적인 커널 배포가 이루어지는 규칙을 설명하고 있으며
+    여러분들이 이러한 배포들 중 하나에 변경을 하길 원한다면
+    무엇을 해야 하는지를 설명한다.
+
+  :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+    커널 개발에 관계된 외부 문서의 리스트이다. 커널 내의 포함된 문서들
+    중에 여러분이 찾고 싶은 문서를 발견하지 못할 경우 이 리스트를
+    살펴보라.
+
+  :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+    패치가 무엇이며 그것을 커널의 다른 개발 브랜치들에 어떻게
+    적용하는지에 관하여 자세히 설명하고 있는 좋은 입문서이다.
+
+커널은 소스 코드 그 자체에서 또는 이것과 같은 ReStructuredText 마크업 (ReST) 을
+통해 자동적으로 만들어질 수 있는 많은 문서들을 가지고 있다. 이것은 커널 내의
+API에 대한 모든 설명, 그리고 락킹을 올바르게 처리하는 법에 관한 규칙을 포함하고
+있다.
+
+모든 그런 문서들은 커널 소스 디렉토리에서 다음 커맨드를 실행하는 것을 통해 PDF
+나 HTML 의 형태로 만들어질 수 있다::
+
+         make pdfdocs
+         make htmldocs
+
+ReST 마크업을 사용하는 문서들은 Documentation/output 에 생성된다.  해당
+문서들은 다음의 커맨드를 사용하면 LaTeX 이나 ePub 로도 만들어질 수 있다::
+
+         make latexdocs
+         make epubdocs
+
+현재, ReST 로의 변환이 진행중인, DocBook 으로 쓰인 문서들이 존재한다. 그런
+문서들은 Documentation/DocBook/ 디렉토리 안에 생성될 것이고 다음 커맨드를 통해
+Postscript 나 man page 로도 만들어질 수 있다::
+
+         make psdocs
+         make mandocs
+
+커널 개발자가 되는 것
+---------------------
+
+여러분이 리눅스 커널 개발에 관하여 아무것도 모른다면 Linux KernelNewbies
+프로젝트를 봐야 한다.
+
+    https://kernelnewbies.org
+
+그곳은 거의 모든 종류의 기본적인 커널 개발 질문들(질문하기 전에 먼저
+아카이브를 찾아봐라. 과거에 이미 답변되었을 수도 있다)을 할 수 있는 도움이
+될만한 메일링 리스트가 있다. 또한 실시간으로 질문 할 수 있는 IRC 채널도
+가지고 있으며 리눅스 커널 개발을 배우는 데 유용한 문서들을 보유하고 있다.
+
+웹사이트는 코드구성, 서브시스템들, 그리고 현재 프로젝트들
+(트리 내, 외부에 존재하는)에 관한 기본적인 정보들을 가지고 있다. 또한
+그곳은 커널 컴파일이나 패치를 하는 법과 같은 기본적인 것들을  설명한다.
+
+여러분이 어디서 시작해야 할진 모르지만 커널 개발 커뮤니티에 참여할 수
+있는 일들을 찾길 원한다면 리눅스 커널 Janitor 프로젝트를 살펴봐라.
+
+	https://kernelnewbies.org/KernelJanitors
+
+그곳은 시작하기에 훌륭한 장소이다. 그곳은 리눅스 커널 소스 트리내에
+간단히 정리되고 수정될 수 있는 문제들에 관하여 설명한다. 여러분은 이
+프로젝트를 대표하는 개발자들과 일하면서 자신의 패치를 리눅스 커널 트리에
+반영하기 위한 기본적인 것들을 배우게 될것이며 여러분이 아직 아이디어를
+가지고 있지 않다면 다음에 무엇을 해야할지에 관한 방향을 배울 수 있을
+것이다.
+
+여러분들이 이미 커널 트리에 반영하길 원하는 코드 묶음을 가지고 있지만
+올바른 포맷으로 포장하는데 도움이 필요하다면 그러한 문제를 돕기 위해
+만들어진 kernel-mentors 프로젝트가 있다. 그곳은 메일링 리스트이며
+다음에서 참조할 수 있다.
+
+         https://selenic.com/mailman/listinfo/kernel-mentors
+
+리눅스 커널 코드에 실제 변경을 하기 전에 반드시 그 코드가 어떻게
+동작하는지 이해하고 있어야 한다. 코드를 분석하기 위하여 특정한 툴의
+도움을 빌려서라도 코드를 직접 읽는 것보다 좋은 것은 없다(대부분의
+자잘한 부분들은 잘 코멘트되어 있다). 그런 툴들 중에 특히 추천할만한
+것은 Linux Cross-Reference project이며 그것은 자기 참조 방식이며
+소스코드를 인덱스된 웹 페이지들의 형태로 보여준다. 최신의 멋진 커널
+코드 저장소는 다음을 통하여 참조할 수 있다.
+
+      http://lxr.free-electrons.com/
+
+
+개발 프로세스
+-------------
+
+리눅스 커널 개발 프로세스는 현재 몇몇 다른 메인 커널 "브랜치들"과
+서브시스템에 특화된 커널 브랜치들로 구성된다. 몇몇 다른 메인
+브랜치들은 다음과 같다.
+
+  - main 4.x 커널 트리
+  - 4.x.y - 안정된 커널 트리
+  - 4.x -git 커널 패치들
+  - 서브시스템을 위한 커널 트리들과 패치들
+  - 4.x - 통합 테스트를 위한 next 커널 트리
+
+4.x 커널 트리
+~~~~~~~~~~~~~
+
+4.x 커널들은 Linus Torvalds가 관리하며 https://kernel.org 의
+pub/linux/kernel/v4.x/ 디렉토리에서 참조될 수 있다.개발 프로세스는 다음과 같다.
+
+  - 새로운 커널이 배포되자마자 2주의 시간이 주어진다. 이 기간동은
+    메인테이너들은 큰 diff들을 Linus에게 제출할 수 있다. 대개 이 패치들은
+    몇 주 동안 -next 커널내에 이미 있었던 것들이다. 큰 변경들을 제출하는 데
+    선호되는 방법은  git(커널의 소스 관리 툴, 더 많은 정보들은
+    https://git-scm.com/ 에서 참조할 수 있다)를 사용하는 것이지만 순수한
+    패치파일의 형식으로 보내는 것도 무관하다.
+  - 2주 후에 -rc1 커널이 배포되며 지금부터는 전체 커널의 안정성에 영향을
+    미칠수 있는 새로운 기능들을 포함하지 않는 패치들만이 추가될 수 있다.
+    완전히 새로운 드라이버(혹은 파일시스템)는 -rc1 이후에만 받아들여진다는
+    것을 기억해라. 왜냐하면 변경이 자체내에서만 발생하고 추가된 코드가
+    드라이버 외부의 다른 부분에는 영향을 주지 않으므로 그런 변경은
+    회귀(역자주: 이전에는 존재하지 않았지만 새로운 기능추가나 변경으로 인해
+    생겨난 버그)를 일으킬 만한 위험을 가지고 있지 않기 때문이다. -rc1이
+    배포된 이후에 git를 사용하여 패치들을 Linus에게 보낼수 있지만 패치들은
+    공식적인 메일링 리스트로 보내서 검토를 받을 필요가 있다.
+  - 새로운 -rc는 Linus가 현재 git tree가 테스트 하기에 충분히 안정된 상태에
+    있다고 판단될 때마다 배포된다. 목표는 새로운 -rc 커널을 매주 배포하는
+    것이다.
+  - 이러한 프로세스는 커널이 "준비(ready)"되었다고 여겨질때까지 계속된다.
+    프로세스는 대체로 6주간 지속된다.
+
+커널 배포에 있어서 언급할만한 가치가 있는 리눅스 커널 메일링 리스트의
+Andrew Morton의 글이 있다.
+
+        *"커널이 언제 배포될지는 아무도 모른다. 왜냐하면 배포는 알려진
+         버그의 상황에 따라 배포되는 것이지 미리정해 놓은 시간에 따라
+         배포되는 것은 아니기 때문이다."*
+
+4.x.y - 안정 커널 트리
+~~~~~~~~~~~~~~~~~~~~~~
+
+3 자리 숫자로 이루어진 버젼의 커널들은 -stable 커널들이다. 그것들은 4.x
+커널에서 발견된 큰 회귀들이나 보안 문제들 중 비교적 작고 중요한 수정들을
+포함한다.
+
+이것은 가장 최근의 안정적인 커널을 원하는 사용자에게 추천되는 브랜치이며,
+개발/실험적 버젼을 테스트하는 것을 돕고자 하는 사용자들과는 별로 관련이 없다.
+
+어떤 4.x.y 커널도 사용할 수 없다면 그때는 가장 높은 숫자의 4.x
+커널이 현재의 안정 커널이다.
+
+4.x.y는 "stable" 팀<stable@vger.kernel.org>에 의해 관리되며 거의 매번 격주로
+배포된다.
+
+커널 트리 문서들 내에 Documentation/process/stable-kernel-rules.rst 파일은 어떤
+종류의 변경들이 -stable 트리로 들어왔는지와 배포 프로세스가 어떻게
+진행되는지를 설명한다.
+
+4.x -git 패치들
+~~~~~~~~~~~~~~~
+
+git 저장소(그러므로 -git이라는 이름이 붙음)에는 날마다 관리되는 Linus의
+커널 트리의 snapshot 들이 있다. 이 패치들은 일반적으로 날마다 배포되며
+Linus의 트리의 현재 상태를 나타낸다. 이 패치들은 정상적인지 조금도
+살펴보지 않고 자동적으로 생성된 것이므로 -rc 커널들 보다도 더 실험적이다.
+
+서브시스템 커널 트리들과 패치들
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+다양한 커널 서브시스템의 메인테이너들 --- 그리고 많은 커널 서브시스템 개발자들
+--- 은 그들의 현재 개발 상태를 소스 저장소로 노출한다. 이를 통해 다른 사람들도
+커널의 다른 영역에 어떤 변화가 이루어지고 있는지 알 수 있다. 급속히 개발이
+진행되는 영역이 있고 그렇지 않은 영역이 있으므로, 개발자는 다른 개발자가 제출한
+수정 사항과 자신의 수정사항의 충돌이나 동일한 일을 동시에 두사람이 따로
+진행하는 사태를 방지하기 위해 급속히 개발이 진행되고 있는 영역에 작업의
+베이스를 맞춰줄 것이 요구된다.
+
+대부분의 이러한 저장소는 git 트리지만, git이 아닌 SCM으로 관리되거나, quilt
+시리즈로 제공되는 패치들도 존재한다. 이러한 서브시스템 저장소들은 MAINTAINERS
+파일에 나열되어 있다. 대부분은 https://git.kernel.org 에서 볼 수 있다.
+
+제안된 패치는 서브시스템 트리에 커밋되기 전에 메일링 리스트를 통해
+리뷰된다(아래의 관련 섹션을 참고하기 바란다). 일부 커널 서브시스템의 경우, 이
+리뷰 프로세스는 patchwork라는 도구를 통해 추적된다. patchwork은 등록된 패치와
+패치에 대한 코멘트, 패치의 버전을 볼 수 있는 웹 인터페이스를 제공하고,
+메인테이너는 패치를 리뷰 중, 리뷰 통과, 또는 반려됨으로 표시할 수 있다.
+대부분의 이러한 patchwork 사이트는 https://patchwork.kernel.org/ 또는
+http://patchwork.ozlabs.org/ 에 나열되어 있다.
+
+4.x - 통합 테스트를 위한 next 커널 트리
+---------------------------------------
+서브시스템 트리들의 변경사항들은 mainline 4.x 트리로 들어오기 전에 통합
+테스트를 거쳐야 한다. 이런 목적으로, 모든 서브시스템 트리의 변경사항을 거의
+매일 받아가는 특수한 테스트 저장소가 존재한다:
+
+       https://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+
+이런 식으로, -next 커널을 통해 다음 머지 기간에 메인라인 커널에 어떤 변경이
+가해질 것인지 간략히 알 수 있다. 모험심 강한 테스터라면 -next 커널에서 테스트를
+수행하는 것도 좋을 것이다.
+
+
+버그 보고
+---------
+
+https://bugzilla.kernel.org는 리눅스 커널 개발자들이 커널의 버그를 추적하는
+곳이다. 사용자들은 발견한 모든 버그들을 보고하기 위하여 이 툴을 사용할 것을
+권장한다.  kernel bugzilla를 사용하는 자세한 방법은 다음을 참조하라.
+
+    https://bugzilla.kernel.org/page.cgi?id=faq.html
+
+메인 커널 소스 디렉토리에 있는 admin-guide/reporting-bugs.rst 파일은 커널 버그라고 생각되는
+것을 보고하는 방법에 관한 좋은 템플릿이며 문제를 추적하기 위해서 커널
+개발자들이 필요로 하는 정보가 무엇들인지를 상세히 설명하고 있다.
+
+
+버그 리포트들의 관리
+--------------------
+
+여러분의 해킹 기술을 연습하는 가장 좋은 방법 중의 하는 다른 사람들이
+보고한 버그들을 수정하는 것이다. 여러분은 커널을 더욱 안정화시키는데
+도움을 줄 뿐만이 아니라 실제있는 문제들을 수정하는 법을 배우게 되고
+그와 함께 여러분들의 기술은 향상될 것이며 다른 개발자들이 여러분의
+존재에 대해 알게 될 것이다. 버그를 수정하는 것은 개발자들  사이에서
+점수를 얻을 수 있는 가장 좋은 방법중의 하나이다. 왜냐하면 많은 사람들은
+다른 사람들의 버그들을 수정하기 위하여 시간을 낭비하지 않기 때문이다.
+
+이미 보고된 버그 리포트들을 가지고 작업하기 위해서 https://bugzilla.kernel.org
+를 참조하라. 여러분이 앞으로 생겨날 버그 리포트들의 조언자가 되길 원한다면
+bugme-new 메일링 리스트나(새로운 버그 리포트들만이 이곳에서 메일로 전해진다)
+bugme-janitor 메일링 리스트(bugzilla에 모든 변화들이 여기서 메일로 전해진다)
+에 등록하면 된다.
+
+      https://lists.linux-foundation.org/mailman/listinfo/bugme-new
+
+      https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
+
+
+
+메일링 리스트들
+---------------
+
+위의 몇몇 문서들이 설명하였지만 핵심 커널 개발자들의 대다수는
+리눅스 커널 메일링 리스트에 참여하고 있다. 리스트에 등록하고 해지하는
+방법에 관한 자세한 사항은 다음에서 참조할 수 있다.
+
+    http://vger.kernel.org/vger-lists.html#linux-kernel
+
+웹상의 많은 다른 곳에도 메일링 리스트의 아카이브들이 있다.
+이러한 아카이브들을 찾으려면 검색 엔진을 사용하라. 예를 들어:
+
+      http://dir.gmane.org/gmane.linux.kernel
+
+여러분이 새로운 문제에 관해 리스트에 올리기 전에 말하고 싶은 주제에 관한
+것을 아카이브에서 먼저 찾아보기를 강력히 권장한다. 이미 상세하게 토론된 많은
+것들이 메일링 리스트의 아카이브에 기록되어 있다.
+
+각각의 커널 서브시스템들의 대부분은 자신들의 개발에 관한 노력들로 이루어진
+분리된 메일링 리스트를 따로 가지고 있다. 다른 그룹들이 무슨 리스트를 가지고
+있는지는 MAINTAINERS 파일을 참조하라.
+
+많은 리스트들은 kernel.org에서 호스트되고 있다. 그 정보들은 다음에서 참조될 수 있다.
+
+         http://vger.kernel.org/vger-lists.html
+
+리스트들을 사용할 때는 올바른 예절을 따를 것을 유념해라.
+대단하진 않지만 다음 URL은 리스트(혹은 모든 리스트)와 대화하는 몇몇 간단한
+가이드라인을 가지고 있다.
+
+         http://www.albion.com/netiquette/
+
+여러 사람들이 여러분의 메일에 응답한다면 CC: 즉 수신 리스트는 꽤 커지게
+될 것이다. 아무 이유없이 CC에서 어떤 사람도 제거하거나 리스트 주소로만
+회신하지 마라. 메일을 보낸 사람으로서 하나를 받고 리스트로부터 또
+하나를 받아 두번 받는 것에 익숙하여 있으니 mail-header를 조작하려고 하지
+말아라. 사람들은 그런 것을 좋아하지 않을 것이다.
+
+여러분의 회신의 문맥을 원래대로 유지해야 한다. 여러분들의 회신의 윗부분에
+"John 커널해커는 작성했다...."를 유지하며 여러분들의 의견을 그 메일의 윗부분에
+작성하지 말고 각 인용한 단락들 사이에 넣어라.
+
+여러분들이 패치들을 메일에 넣는다면 그것들은 Documentation/process/submitting-patches.rst에
+나와있는데로 명백히(plain) 읽을 수 있는 텍스트여야 한다. 커널 개발자들은
+첨부파일이나 압축된 패치들을 원하지 않는다. 그들은 여러분들의 패치의
+각 라인 단위로 코멘트를 하길 원하며 압축하거나 첨부하지 않고 보내는 것이
+그렇게 할 수 있는 유일한 방법이다. 여러분들이 사용하는 메일 프로그램이
+스페이스나 탭 문자들을 조작하지 않는지 확인하라. 가장 좋은 첫 테스트는
+메일을 자신에게 보내보고 스스로 그 패치를 적용해보라. 그것이 동작하지
+않는다면 여러분의 메일 프로그램을 고치던가 제대로 동작하는 프로그램으로
+바꾸어라.
+
+무엇보다도 메일링 리스트의 다른 구독자들에게 보여주려 한다는 것을 기억하라.
+
+
+커뮤니티와 협력하는 법
+----------------------
+
+커널 커뮤니티의 목적은 가능한한 가장 좋은 커널을 제공하는 것이다. 여러분이
+받아들여질 패치를 제출하게 되면 그 패치의 기술적인 이점으로 검토될 것이다.
+그럼 여러분들은 무엇을 기대하고 있어야 하는가?
+
+ - 비판
+ - 의견
+ - 변경을 위한 요구
+ - 당위성을 위한 요구
+ - 침묵
+
+기억하라. 이것들은 여러분의 패치가 커널로 들어가기 위한 과정이다. 여러분의
+패치들은 비판과 다른 의견을 받을 수 있고 그것들을 기술적인 레벨로 평가하고
+재작업하거나 또는 왜 수정하면 안되는지에 관하여 명료하고 간결한 이유를
+말할 수 있어야 한다. 여러분이 제출한 것에 어떤 응답도 있지 않다면 몇 일을
+기다려보고 다시 시도해라. 때론 너무 많은 메일들 속에 묻혀버리기도 한다.
+
+여러분은 무엇을 해서는 안되는가?
+
+ - 여러분의 패치가 아무 질문 없이 받아들여지기를 기대하는 것
+ - 방어적이 되는 것
+ - 의견을 무시하는 것
+ - 요청된 변경을 하지 않고 패치를 다시 제출하는 것
+
+가능한한 가장 좋은 기술적인 해답을 찾고 있는 커뮤니티에서는 항상
+어떤 패치가 얼마나 좋은지에 관하여 다른 의견들이 있을 수 있다. 여러분은
+협조적이어야 하고 기꺼이 여러분의 생각을 커널 내에 맞추어야 한다. 아니면
+적어도 여러분의 것이 가치있다는 것을 증명하여야 한다. 잘못된 것도 여러분이
+올바른 방향의 해결책으로 이끌어갈 의지가 있다면 받아들여질 것이라는 점을
+기억하라.
+
+여러분의 첫 패치에 여러분이 수정해야하는 십여개 정도의 회신이 오는
+경우도 흔하다. 이것은 여러분의 패치가 받아들여지지 않을 것이라는 것을
+의미하는 것이 아니고 개인적으로 여러분에게 감정이 있어서 그러는 것도
+아니다. 간단히 여러분의 패치에 제기된 문제들을 수정하고 그것을 다시
+보내라.
+
+
+커널 커뮤니티와 기업 조직간의 차이점
+------------------------------------
+커널 커뮤니티는 가장 전통적인 회사의 개발 환경과는 다르다. 여기에 여러분들의
+문제를 피하기 위한 목록이 있다.
+
+  여러분들이 제안한 변경들에 관하여 말할 때 좋은 것들 :
+
+    - "이것은 여러 문제들을 해결합니다."
+    - "이것은 2000 라인의 코드를 줄입니다."
+    - "이것은 내가 말하려는 것에 관해 설명하는 패치입니다."
+    - "나는 5개의 다른 아키텍쳐에서 그것을 테스트 했으므로..."
+    - "여기에 일련의 작은 패치들이 있으므로..."
+    - "이것은 일반적인 머신에서 성능을 향상함으로..."
+
+  여러분들이 말할 때 피해야 할 좋지 않은 것들 :
+
+    - "우리는 그것을 AIX/ptx/Solaris에서 이러한 방법으로 했다. 그러므로 그것은 좋은 것임에 틀림없다..."
+    - "나는 20년동안 이것을 해왔다. 그러므로..."
+    - "이것은 돈을 벌기위해 나의 회사가 필요로 하는 것이다."
+    - "이것은 우리의 엔터프라이즈 상품 라인을 위한 것이다."
+    - "여기에 나의 생각을 말하고 있는 1000 페이지 설계 문서가 있다."
+    - "나는 6달동안 이것을 했으니..."
+    - "여기에 5000 라인 짜리 패치가 있으니..."
+    - "나는 현재 뒤죽박죽인 것을 재작성했다. 그리고 여기에..."
+    - "나는 마감시한을 가지고 있으므로 이 패치는 지금 적용될 필요가 있다."
+
+커널 커뮤니티가 전통적인 소프트웨어 엔지니어링 개발 환경들과
+또 다른 점은 얼굴을 보지 않고 일한다는 점이다. 이메일과 irc를 대화의
+주요수단으로 사용하는 것의 한가지 장점은 성별이나 인종의 차별이
+없다는 것이다. 리눅스 커널의 작업 환경에서는 단지 이메일 주소만
+알수 있기 때문에 여성과 소수 민족들도 모두 받아들여진다. 국제적으로
+일하게 되는 측면은 사람의 이름에 근거하여 성별을 추측할 수 없게
+하기때문에 차별을 없애는 데 도움을 준다. Andrea라는 이름을 가진 남자와
+Pat이라는 이름을 가진 여자가 있을 수도 있는 것이다. 리눅스 커널에서
+작업하며 생각을 표현해왔던 대부분의 여성들은 긍정적인 경험을 가지고
+있다.
+
+언어 장벽은 영어에 익숙하지 않은 몇몇 사람들에게 문제가 될 수도 있다.
+언어의 훌륭한 구사는 메일링 리스트에서 올바르게 자신의 생각을
+표현하기 위하여 필요하다. 그래서 여러분은 이메일을 보내기 전에
+영어를 올바르게 사용하고 있는지를 체크하는 것이 바람직하다.
+
+
+여러분의 변경을 나누어라
+------------------------
+
+리눅스 커널 커뮤니티는 한꺼번에 굉장히 큰 코드의 묶음(chunk)을 쉽게
+받아들이지 않는다. 변경은 적절하게 소개되고, 검토되고, 각각의
+부분으로 작게 나누어져야 한다. 이것은 회사에서 하는 것과는 정확히
+반대되는 것이다. 여러분들의 제안은 개발 초기에 일찍이 소개되야 한다.
+그래서 여러분들은 자신이 하고 있는 것에 관하여 피드백을 받을 수 있게
+된다. 커뮤니티가 여러분들이 커뮤니티와 함께 일하고 있다는 것을
+느끼도록 만들고 커뮤니티가 여러분의 기능을 위한 쓰레기 장으로써
+사용되지 않고 있다는 것을 느끼게 하자. 그러나 메일링 리스트에 한번에
+50개의 이메일을 보내지는 말아라. 여러분들의 일련의 패치들은 항상
+더 작아야 한다.
+
+패치를 나누는 이유는 다음과 같다.
+
+1) 작은 패치들은 여러분의 패치들이 적용될 수 있는 확률을 높여준다.
+   왜냐하면 다른 사람들은 정확성을 검증하기 위하여 많은 시간과 노력을
+   들이기를 원하지 않는다. 5줄의 패치는 메인테이너가 거의 몇 초간 힐끗
+   보면 적용될 수 있다. 그러나 500 줄의 패치는 정확성을 검토하기 위하여
+   몇시간이 걸릴 수도 있다(걸리는 시간은 패치의 크기 혹은 다른 것에
+   비례하여 기하급수적으로 늘어난다).
+
+   패치를 작게 만드는 것은 무엇인가 잘못되었을 때 디버그하는 것을
+   쉽게 만든다. 즉, 그렇게 만드는 것은 매우 큰 패치를 적용한 후에
+   조사하는 것 보다 작은 패치를 적용한 후에 (그리고 몇몇의 것이
+   깨졌을 때) 하나씩 패치들을 제거해가며 디버그 하기 쉽도록 만들어 준다.
+
+2) 작은 패치들을 보내는 것뿐만 아니라 패치들을 제출하기전에 재작성하고
+   간단하게(혹은 간단한게 재배치하여) 하는 것도 중요하다.
+
+여기에 커널 개발자 Al Viro의 이야기가 있다.
+
+    *"학생의 수학 숙제를 채점하는 선생님을 생각해보라. 선생님은 학생들이
+    답을 얻을때까지 겪은 시행착오를 보길 원하지 않는다. 선생님들은
+    간결하고 가장 뛰어난 답을 보길 원한다. 훌륭한 학생은 이것을 알고
+    마지막으로 답을 얻기 전 중간 과정들을 제출하진 않는다.*
+
+    *커널 개발도 마찬가지이다. 메인테이너들과 검토하는 사람들은 문제를
+    풀어나가는 과정속에 숨겨진 과정을 보길 원하진 않는다. 그들은
+    간결하고 멋진 답을 보길 원한다."*
+
+커뮤니티와 협력하며 뛰어난 답을 찾는 것과 여러분들의 끝마치지 못한 작업들
+사이에 균형을 유지해야 하는 것은 어려울지도 모른다. 그러므로 프로세스의
+초반에 여러분의 작업을 향상시키기위한 피드백을 얻는 것 뿐만 아니라
+여러분들의 변경들을 작은 묶음으로 유지해서 심지어는 여러분의 작업의
+모든 부분이 지금은 포함될 준비가 되어있지 않지만 작은 부분은 벌써
+받아들여질 수 있도록 유지하는 것이 바람직하다.
+
+또한 완성되지 않았고 "나중에 수정될 것이다." 와 같은 것들을 포함하는
+패치들은 받아들여지지 않을 것이라는 점을 유념하라.
+
+
+변경을 정당화해라
+-----------------
+
+여러분들의 나누어진 패치들을 리눅스 커뮤니티가 왜 반영해야 하는지를
+알도록 하는 것은 매우 중요하다. 새로운 기능들이 필요하고 유용하다는
+것은 반드시 그에 합당한 이유가 있어야 한다.
+
+
+변경을 문서화해라
+-----------------
+
+여러분이 패치를 보내려 할때는 여러분이 무엇을 말하려고 하는지를 충분히
+생각하여 이메일을 작성해야 한다. 이 정보는 패치를 위한 ChangeLog가 될
+것이다. 그리고 항상 그 내용을 보길 원하는 모든 사람들을 위해 보존될
+것이다. 패치는 완벽하게 다음과 같은 내용들을 포함하여 설명해야 한다.
+
+  - 변경이 왜 필요한지
+  - 패치에 관한 전체 설계 접근(approach)
+  - 구현 상세들
+  - 테스트 결과들
+
+이것이 무엇인지 더 자세한 것을 알고 싶다면 다음 문서의 ChageLog 항을 봐라.
+
+   "The Perfect Patch"
+
+    http://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+이 모든 것을 하는 것은 매우 어려운 일이다. 완벽히 소화하는 데는 적어도 몇년이
+걸릴 수도 있다. 많은 인내와 결심이 필요한 계속되는 개선의 과정이다. 그러나
+가능한한 포기하지 말라. 많은 사람들은 이전부터 해왔던 것이고 그 사람들도
+정확하게 여러분들이 지금 서 있는 그 곳부터  시작했었다.
+
+
+
+
+----------
+
+"개발 프로세스"(https://lwn.net/Articles/94386/) 섹션을
+작성하는데 있어 참고할 문서를 사용하도록 허락해준 Paolo Ciarrocchi에게
+감사한다. 여러분들이 말해야 할 것과 말해서는 안되는 것의 목록 중 일부를 제공해준
+Randy Dunlap과 Gerrit Huizenga에게 감사한다. 또한 검토와 의견 그리고
+공헌을 아끼지 않은 Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
+Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi Kleen,
+Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
+David A. Wheeler, Junio Hamano, Michael Kerrisk, and Alex Shepard에게도 감사를 전한다.
+그들의 도움이 없었다면 이 문서는 존재하지 않았을 것이다.
+
+
+
+메인테이너: Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ko_KR/index.rst linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/index.rst
--- linux-libre-4.9-gnu/Documentation/translations/ko_KR/index.rst	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/index.rst	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,12 @@
+.. raw:: latex
+
+        \renewcommand\thesection*
+        \renewcommand\thesubsection*
+
+Korean translations
+===================
+
+.. toctree::
+   :maxdepth: 1
+
+   howto
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ko_KR/memory-barriers.txt linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/memory-barriers.txt
--- linux-libre-4.9-gnu/Documentation/translations/ko_KR/memory-barriers.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/memory-barriers.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3171 @@
+NOTE:
+This is a version of Documentation/memory-barriers.txt translated into Korean.
+This document is maintained by SeongJae Park <sj38.park@gmail.com>.
+If you find any difference between this document and the original file or
+a problem with the translation, please contact the maintainer of this file.
+
+Please also note that the purpose of this file is to be easier to
+read for non English (read: Korean) speakers and is not intended as
+a fork.  So if you have any comments or updates for this file please
+update the original English file first.  The English version is
+definitive, and readers should look there if they have any doubt.
+
+===================================
+이 문서는
+Documentation/memory-barriers.txt
+의 한글 번역입니다.
+
+역자： 박성재 <sj38.park@gmail.com>
+===================================
+
+
+			 =========================
+			 리눅스 커널 메모리 배리어
+			 =========================
+
+저자: David Howells <dhowells@redhat.com>
+      Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+      Will Deacon <will.deacon@arm.com>
+      Peter Zijlstra <peterz@infradead.org>
+
+========
+면책조항
+========
+
+이 문서는 명세서가 아닙니다; 이 문서는 완벽하지 않은데, 간결성을 위해 의도된
+부분도 있고, 의도하진 않았지만 사람에 의해 쓰였다보니 불완전한 부분도 있습니다.
+이 문서는 리눅스에서 제공하는 다양한 메모리 배리어들을 사용하기 위한
+안내서입니다만, 뭔가 이상하다 싶으면 (그런게 많을 겁니다) 질문을 부탁드립니다.
+
+다시 말하지만, 이 문서는 리눅스가 하드웨어에 기대하는 사항에 대한 명세서가
+아닙니다.
+
+이 문서의 목적은 두가지입니다:
+
+ (1) 어떤 특정 배리어에 대해 기대할 수 있는 최소한의 기능을 명세하기 위해서,
+     그리고
+
+ (2) 사용 가능한 배리어들에 대해 어떻게 사용해야 하는지에 대한 안내를 제공하기
+     위해서.
+
+어떤 아키텍쳐는 특정한 배리어들에 대해서는 여기서 이야기하는 최소한의
+요구사항들보다 많은 기능을 제공할 수도 있습니다만, 여기서 이야기하는
+요구사항들을 충족하지 않는 아키텍쳐가 있다면 그 아키텍쳐가 잘못된 것이란 점을
+알아두시기 바랍니다.
+
+또한, 특정 아키텍쳐에서 일부 배리어는 해당 아키텍쳐의 특수한 동작 방식으로 인해
+해당 배리어의 명시적 사용이 불필요해서 no-op 이 될수도 있음을 알아두시기
+바랍니다.
+
+역자: 본 번역 역시 완벽하지 않은데, 이 역시 부분적으로는 의도된 것이기도
+합니다.  여타 기술 문서들이 그렇듯 완벽한 이해를 위해서는 번역문과 원문을 함께
+읽으시되 번역문을 하나의 가이드로 활용하시길 추천드리며, 발견되는 오역 등에
+대해서는 언제든 의견을 부탁드립니다.  과한 번역으로 인한 오해를 최소화하기 위해
+애매한 부분이 있을 경우에는 어색함이 있더라도 원래의 용어를 차용합니다.
+
+
+=====
+목차:
+=====
+
+ (*) 추상 메모리 액세스 모델.
+
+     - 디바이스 오퍼레이션.
+     - 보장사항.
+
+ (*) 메모리 배리어란 무엇인가?
+
+     - 메모리 배리어의 종류.
+     - 메모리 배리어에 대해 가정해선 안될 것.
+     - 데이터 의존성 배리어.
+     - 컨트롤 의존성.
+     - SMP 배리어 짝맞추기.
+     - 메모리 배리어 시퀀스의 예.
+     - 읽기 메모리 배리어 vs 로드 예측.
+     - 이행성
+
+ (*) 명시적 커널 배리어.
+
+     - 컴파일러 배리어.
+     - CPU 메모리 배리어.
+     - MMIO 쓰기 배리어.
+
+ (*) 암묵적 커널 메모리 배리어.
+
+     - 락 Acquisition 함수.
+     - 인터럽트 비활성화 함수.
+     - 슬립과 웨이크업 함수.
+     - 그외의 함수들.
+
+ (*) CPU 간 ACQUIRING 배리어의 효과.
+
+     - Acquire vs 메모리 액세스.
+     - Acquire vs I/O 액세스.
+
+ (*) 메모리 배리어가 필요한 곳
+
+     - 프로세서간 상호 작용.
+     - 어토믹 오퍼레이션.
+     - 디바이스 액세스.
+     - 인터럽트.
+
+ (*) 커널 I/O 배리어의 효과.
+
+ (*) 가정되는 가장 완화된 실행 순서 모델.
+
+ (*) CPU 캐시의 영향.
+
+     - 캐시 일관성.
+     - 캐시 일관성 vs DMA.
+     - 캐시 일관성 vs MMIO.
+
+ (*) CPU 들이 저지르는 일들.
+
+     - 그리고, Alpha 가 있다.
+     - 가상 머신 게스트.
+
+ (*) 사용 예.
+
+     - 순환식 버퍼.
+
+ (*) 참고 문헌.
+
+
+=======================
+추상 메모리 액세스 모델
+=======================
+
+다음과 같이 추상화된 시스템 모델을 생각해 봅시다:
+
+		            :                :
+		            :                :
+		            :                :
+		+-------+   :   +--------+   :   +-------+
+		|       |   :   |        |   :   |       |
+		|       |   :   |        |   :   |       |
+		| CPU 1 |<----->| Memory |<----->| CPU 2 |
+		|       |   :   |        |   :   |       |
+		|       |   :   |        |   :   |       |
+		+-------+   :   +--------+   :   +-------+
+		    ^       :       ^        :       ^
+		    |       :       |        :       |
+		    |       :       |        :       |
+		    |       :       v        :       |
+		    |       :   +--------+   :       |
+		    |       :   |        |   :       |
+		    |       :   |        |   :       |
+		    +---------->| Device |<----------+
+		            :   |        |   :
+		            :   |        |   :
+		            :   +--------+   :
+		            :                :
+
+프로그램은 여러 메모리 액세스 오퍼레이션을 발생시키고, 각각의 CPU 는 그런
+프로그램들을 실행합니다.  추상화된 CPU 모델에서 메모리 오퍼레이션들의 순서는
+매우 완화되어 있고, CPU 는 프로그램이 인과관계를 어기지 않는 상태로 관리된다고
+보일 수만 있다면 메모리 오퍼레이션을 자신이 원하는 어떤 순서대로든 재배치해
+동작시킬 수 있습니다.  비슷하게, 컴파일러 또한 프로그램의 정상적 동작을 해치지
+않는 한도 내에서는 어떤 순서로든 자신이 원하는 대로 인스트럭션을 재배치 할 수
+있습니다.
+
+따라서 위의 다이어그램에서 한 CPU가 동작시키는 메모리 오퍼레이션이 만들어내는
+변화는 해당 오퍼레이션이 CPU 와 시스템의 다른 부분들 사이의 인터페이스(점선)를
+지나가면서 시스템의 나머지 부분들에 인지됩니다.
+
+
+예를 들어, 다음의 일련의 이벤트들을 생각해 봅시다:
+
+	CPU 1		CPU 2
+	===============	===============
+	{ A == 1; B == 2 }
+	A = 3;		x = B;
+	B = 4;		y = A;
+
+다이어그램의 가운데에 위치한 메모리 시스템에 보여지게 되는 액세스들은 다음의 총
+24개의 조합으로 재구성될 수 있습니다:
+
+	STORE A=3,	STORE B=4,	y=LOAD A->3,	x=LOAD B->4
+	STORE A=3,	STORE B=4,	x=LOAD B->4,	y=LOAD A->3
+	STORE A=3,	y=LOAD A->3,	STORE B=4,	x=LOAD B->4
+	STORE A=3,	y=LOAD A->3,	x=LOAD B->2,	STORE B=4
+	STORE A=3,	x=LOAD B->2,	STORE B=4,	y=LOAD A->3
+	STORE A=3,	x=LOAD B->2,	y=LOAD A->3,	STORE B=4
+	STORE B=4,	STORE A=3,	y=LOAD A->3,	x=LOAD B->4
+	STORE B=4, ...
+	...
+
+따라서 다음의 네가지 조합의 값들이 나올 수 있습니다:
+
+	x == 2, y == 1
+	x == 2, y == 3
+	x == 4, y == 1
+	x == 4, y == 3
+
+
+한발 더 나아가서, 한 CPU 가 메모리 시스템에 반영한 스토어 오퍼레이션들의 결과는
+다른 CPU 에서의 로드 오퍼레이션을 통해 인지되는데, 이 때 스토어가 반영된 순서와
+다른 순서로 인지될 수도 있습니다.
+
+
+예로, 아래의 일련의 이벤트들을 생각해 봅시다:
+
+	CPU 1		CPU 2
+	===============	===============
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
+	B = 4;		Q = P;
+	P = &B		D = *Q;
+
+D 로 읽혀지는 값은 CPU 2 에서 P 로부터 읽혀진 주소값에 의존적이기 때문에 여기엔
+분명한 데이터 의존성이 있습니다.  하지만 이 이벤트들의 실행 결과로는 아래의
+결과들이 모두 나타날 수 있습니다:
+
+	(Q == &A) and (D == 1)
+	(Q == &B) and (D == 2)
+	(Q == &B) and (D == 4)
+
+CPU 2 는 *Q 의 로드를 요청하기 전에 P 를 Q 에 넣기 때문에 D 에 C 를 집어넣는
+일은 없음을 알아두세요.
+
+
+디바이스 오퍼레이션
+-------------------
+
+일부 디바이스는 자신의 컨트롤 인터페이스를 메모리의 특정 영역으로 매핑해서
+제공하는데(Memory mapped I/O), 해당 컨트롤 레지스터에 접근하는 순서는 매우
+중요합니다.  예를 들어, 어드레스 포트 레지스터 (A) 와 데이터 포트 레지스터 (D)
+를 통해 접근되는 내부 레지스터 집합을 갖는 이더넷 카드를 생각해 봅시다.  내부의
+5번 레지스터를 읽기 위해 다음의 코드가 사용될 수 있습니다:
+
+	*A = 5;
+	x = *D;
+
+하지만, 이건 다음의 두 조합 중 하나로 만들어질 수 있습니다:
+
+	STORE *A = 5, x = LOAD *D
+	x = LOAD *D, STORE *A = 5
+
+두번째 조합은 데이터를 읽어온 _후에_ 주소를 설정하므로, 오동작을 일으킬 겁니다.
+
+
+보장사항
+--------
+
+CPU 에게 기대할 수 있는 최소한의 보장사항 몇가지가 있습니다:
+
+ (*) 어떤 CPU 든, 의존성이 존재하는 메모리 액세스들은 해당 CPU 자신에게
+     있어서는 순서대로 메모리 시스템에 수행 요청됩니다. 즉, 다음에 대해서:
+
+	Q = READ_ONCE(P); smp_read_barrier_depends(); D = READ_ONCE(*Q);
+
+     CPU 는 다음과 같은 메모리 오퍼레이션 시퀀스를 수행 요청합니다:
+
+	Q = LOAD P, D = LOAD *Q
+
+     그리고 그 시퀀스 내에서의 순서는 항상 지켜집니다.  대부분의 시스템에서
+     smp_read_barrier_depends() 는 아무일도 안하지만 DEC Alpha 에서는
+     명시적으로 사용되어야 합니다.  보통의 경우에는 smp_read_barrier_depends()
+     를 직접 사용하는 대신 rcu_dereference() 같은 것들을 사용해야 함을
+     알아두세요.
+
+ (*) 특정 CPU 내에서 겹치는 영역의 메모리에 행해지는 로드와 스토어 들은 해당
+     CPU 안에서는 순서가 바뀌지 않은 것으로 보여집니다.  즉, 다음에 대해서:
+
+	a = READ_ONCE(*X); WRITE_ONCE(*X, b);
+
+     CPU 는 다음의 메모리 오퍼레이션 시퀀스만을 메모리에 요청할 겁니다:
+
+	a = LOAD *X, STORE *X = b
+
+     그리고 다음에 대해서는:
+
+	WRITE_ONCE(*X, c); d = READ_ONCE(*X);
+
+     CPU 는 다음의 수행 요청만을 만들어 냅니다:
+
+	STORE *X = c, d = LOAD *X
+
+     (로드 오퍼레이션과 스토어 오퍼레이션이 겹치는 메모리 영역에 대해
+     수행된다면 해당 오퍼레이션들은 겹친다고 표현됩니다).
+
+그리고 _반드시_ 또는 _절대로_ 가정하거나 가정하지 말아야 하는 것들이 있습니다:
+
+ (*) 컴파일러가 READ_ONCE() 나 WRITE_ONCE() 로 보호되지 않은 메모리 액세스를
+     당신이 원하는 대로 할 것이라는 가정은 _절대로_ 해선 안됩니다.  그것들이
+     없다면, 컴파일러는 컴파일러 배리어 섹션에서 다루게 될, 모든 "창의적인"
+     변경들을 만들어낼 권한을 갖게 됩니다.
+
+ (*) 개별적인 로드와 스토어들이 주어진 순서대로 요청될 것이라는 가정은 _절대로_
+     하지 말아야 합니다.  이 말은 곧:
+
+	X = *A; Y = *B; *D = Z;
+
+     는 다음의 것들 중 어느 것으로든 만들어질 수 있다는 의미입니다:
+
+	X = LOAD *A,  Y = LOAD *B,  STORE *D = Z
+	X = LOAD *A,  STORE *D = Z, Y = LOAD *B
+	Y = LOAD *B,  X = LOAD *A,  STORE *D = Z
+	Y = LOAD *B,  STORE *D = Z, X = LOAD *A
+	STORE *D = Z, X = LOAD *A,  Y = LOAD *B
+	STORE *D = Z, Y = LOAD *B,  X = LOAD *A
+
+ (*) 겹치는 메모리 액세스들은 합쳐지거나 버려질 수 있음을 _반드시_ 가정해야
+     합니다.  다음의 코드는:
+
+	X = *A; Y = *(A + 4);
+
+     다음의 것들 중 뭐든 될 수 있습니다:
+
+	X = LOAD *A; Y = LOAD *(A + 4);
+	Y = LOAD *(A + 4); X = LOAD *A;
+	{X, Y} = LOAD {*A, *(A + 4) };
+
+     그리고:
+
+	*A = X; *(A + 4) = Y;
+
+     는 다음 중 뭐든 될 수 있습니다:
+
+	STORE *A = X; STORE *(A + 4) = Y;
+	STORE *(A + 4) = Y; STORE *A = X;
+	STORE {*A, *(A + 4) } = {X, Y};
+
+그리고 보장사항에 반대되는 것들(anti-guarantees)이 있습니다:
+
+ (*) 이 보장사항들은 bitfield 에는 적용되지 않는데, 컴파일러들은 bitfield 를
+     수정하는 코드를 생성할 때 원자성 없는(non-atomic) 읽고-수정하고-쓰는
+     인스트럭션들의 조합을 만드는 경우가 많기 때문입니다.  병렬 알고리즘의
+     동기화에 bitfield 를 사용하려 하지 마십시오.
+
+ (*) bitfield 들이 여러 락으로 보호되는 경우라 하더라도, 하나의 bitfield 의
+     모든 필드들은 하나의 락으로 보호되어야 합니다.  만약 한 bitfield 의 두
+     필드가 서로 다른 락으로 보호된다면, 컴파일러의 원자성 없는
+     읽고-수정하고-쓰는 인스트럭션 조합은 한 필드에의 업데이트가 근처의
+     필드에도 영향을 끼치게 할 수 있습니다.
+
+ (*) 이 보장사항들은 적절하게 정렬되고 크기가 잡힌 스칼라 변수들에 대해서만
+     적용됩니다.  "적절하게 크기가 잡힌" 이라함은 현재로써는 "char", "short",
+     "int" 그리고 "long" 과 같은 크기의 변수들을 의미합니다.  "적절하게 정렬된"
+     은 자연스런 정렬을 의미하는데, 따라서 "char" 에 대해서는 아무 제약이 없고,
+     "short" 에 대해서는 2바이트 정렬을, "int" 에는 4바이트 정렬을, 그리고
+     "long" 에 대해서는 32-bit 시스템인지 64-bit 시스템인지에 따라 4바이트 또는
+     8바이트 정렬을 의미합니다.  이 보장사항들은 C11 표준에서 소개되었으므로,
+     C11 전의 오래된 컴파일러(예를 들어, gcc 4.6) 를 사용할 때엔 주의하시기
+     바랍니다.  표준에 이 보장사항들은 "memory location" 을 정의하는 3.14
+     섹션에 다음과 같이 설명되어 있습니다:
+     (역자: 인용문이므로 번역하지 않습니다)
+
+	memory location
+		either an object of scalar type, or a maximal sequence
+		of adjacent bit-fields all having nonzero width
+
+		NOTE 1: Two threads of execution can update and access
+		separate memory locations without interfering with
+		each other.
+
+		NOTE 2: A bit-field and an adjacent non-bit-field member
+		are in separate memory locations. The same applies
+		to two bit-fields, if one is declared inside a nested
+		structure declaration and the other is not, or if the two
+		are separated by a zero-length bit-field declaration,
+		or if they are separated by a non-bit-field member
+		declaration. It is not safe to concurrently update two
+		bit-fields in the same structure if all members declared
+		between them are also bit-fields, no matter what the
+		sizes of those intervening bit-fields happen to be.
+
+
+=========================
+메모리 배리어란 무엇인가?
+=========================
+
+앞에서 봤듯이, 상호간 의존성이 없는 메모리 오퍼레이션들은 실제로는 무작위적
+순서로 수행될 수 있으며, 이는 CPU 와 CPU 간의 상호작용이나 I/O 에 문제가 될 수
+있습니다.  따라서 컴파일러와 CPU 가 순서를 바꾸는데 제약을 걸 수 있도록 개입할
+수 있는 어떤 방법이 필요합니다.
+
+메모리 배리어는 그런 개입 수단입니다.  메모리 배리어는 배리어를 사이에 둔 앞과
+뒤 양측의 메모리 오퍼레이션들 간에 부분적 순서가 존재하도록 하는 효과를 줍니다.
+
+시스템의 CPU 들과 여러 디바이스들은 성능을 올리기 위해 명령어 재배치, 실행
+유예, 메모리 오퍼레이션들의 조합, 예측적 로드(speculative load), 브랜치
+예측(speculative branch prediction), 다양한 종류의 캐싱(caching) 등의 다양한
+트릭을 사용할 수 있기 때문에 이런 강제력은 중요합니다.  메모리 배리어들은 이런
+트릭들을 무효로 하거나 억제하는 목적으로 사용되어져서 코드가 여러 CPU 와
+디바이스들 간의 상호작용을 정상적으로 제어할 수 있게 해줍니다.
+
+
+메모리 배리어의 종류
+--------------------
+
+메모리 배리어는 네개의 기본 타입으로 분류됩니다:
+
+ (1) 쓰기 (또는 스토어) 메모리 배리어.
+
+     쓰기 메모리 배리어는 시스템의 다른 컴포넌트들에 해당 배리어보다 앞서
+     명시된 모든 STORE 오퍼레이션들이 해당 배리어 뒤에 명시된 모든 STORE
+     오퍼레이션들보다 먼저 수행된 것으로 보일 것을 보장합니다.
+
+     쓰기 배리어는 스토어 오퍼레이션들에 대한 부분적 순서 세우기입니다; 로드
+     오퍼레이션들에 대해서는 어떤 영향도 끼치지 않습니다.
+
+     CPU 는 시간의 흐름에 따라 메모리 시스템에 일련의 스토어 오퍼레이션들을
+     하나씩 요청해 집어넣습니다.  쓰기 배리어 앞의 모든 스토어 오퍼레이션들은
+     쓰기 배리어 뒤의 모든 스토어 오퍼레이션들보다 _앞서_ 수행될 겁니다.
+
+     [!] 쓰기 배리어들은 읽기 또는 데이터 의존성 배리어와 함께 짝을 맞춰
+     사용되어야만 함을 알아두세요; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요.
+
+
+ (2) 데이터 의존성 배리어.
+
+     데이터 의존성 배리어는 읽기 배리어의 보다 완화된 형태입니다.  두개의 로드
+     오퍼레이션이 있고 두번째 것이 첫번째 것의 결과에 의존하고 있을 때(예:
+     두번째 로드가 참조할 주소를 첫번째 로드가 읽는 경우), 두번째 로드가 읽어올
+     데이터는 첫번째 로드에 의해 그 주소가 얻어지기 전에 업데이트 되어 있음을
+     보장하기 위해서 데이터 의존성 배리어가 필요할 수 있습니다.
+
+     데이터 의존성 배리어는 상호 의존적인 로드 오퍼레이션들 사이의 부분적 순서
+     세우기입니다; 스토어 오퍼레이션들이나 독립적인 로드들, 또는 중복되는
+     로드들에 대해서는 어떤 영향도 끼치지 않습니다.
+
+     (1) 에서 언급했듯이, 시스템의 CPU 들은 메모리 시스템에 일련의 스토어
+     오퍼레이션들을 던져 넣고 있으며, 거기에 관심이 있는 다른 CPU 는 그
+     오퍼레이션들을 메모리 시스템이 실행한 결과를 인지할 수 있습니다.  이처럼
+     다른 CPU 의 스토어 오퍼레이션의 결과에 관심을 두고 있는 CPU 가 수행 요청한
+     데이터 의존성 배리어는, 배리어 앞의 어떤 로드 오퍼레이션이 다른 CPU 에서
+     던져 넣은 스토어 오퍼레이션과 같은 영역을 향했다면, 그런 스토어
+     오퍼레이션들이 만들어내는 결과가 데이터 의존성 배리어 뒤의 로드
+     오퍼레이션들에게는 보일 것을 보장합니다.
+
+     이 순서 세우기 제약에 대한 그림을 보기 위해선 "메모리 배리어 시퀀스의 예"
+     서브섹션을 참고하시기 바랍니다.
+
+     [!] 첫번째 로드는 반드시 _데이터_ 의존성을 가져야지 컨트롤 의존성을 가져야
+     하는게 아님을 알아두십시오.  만약 두번째 로드를 위한 주소가 첫번째 로드에
+     의존적이지만 그 의존성은 조건적이지 그 주소 자체를 가져오는게 아니라면,
+     그것은 _컨트롤_ 의존성이고, 이 경우에는 읽기 배리어나 그보다 강력한
+     무언가가 필요합니다.  더 자세한 내용을 위해서는 "컨트롤 의존성" 서브섹션을
+     참고하시기 바랍니다.
+
+     [!] 데이터 의존성 배리어는 보통 쓰기 배리어들과 함께 짝을 맞춰 사용되어야
+     합니다; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요.
+
+
+ (3) 읽기 (또는 로드) 메모리 배리어.
+
+     읽기 배리어는 데이터 의존성 배리어 기능의 보장사항에 더해서 배리어보다
+     앞서 명시된 모든 LOAD 오퍼레이션들이 배리어 뒤에 명시되는 모든 LOAD
+     오퍼레이션들보다 먼저 행해진 것으로 시스템의 다른 컴포넌트들에 보여질 것을
+     보장합니다.
+
+     읽기 배리어는 로드 오퍼레이션에 행해지는 부분적 순서 세우기입니다; 스토어
+     오퍼레이션에 대해서는 어떤 영향도 끼치지 않습니다.
+
+     읽기 메모리 배리어는 데이터 의존성 배리어를 내장하므로 데이터 의존성
+     배리어를 대신할 수 있습니다.
+
+     [!] 읽기 배리어는 일반적으로 쓰기 배리어들과 함께 짝을 맞춰 사용되어야
+     합니다; "SMP 배리어 짝맞추기" 서브섹션을 참고하세요.
+
+
+ (4) 범용 메모리 배리어.
+
+     범용(general) 메모리 배리어는 배리어보다 앞서 명시된 모든 LOAD 와 STORE
+     오퍼레이션들이 배리어 뒤에 명시된 모든 LOAD 와 STORE 오퍼레이션들보다
+     먼저 수행된 것으로 시스템의 나머지 컴포넌트들에 보이게 됨을 보장합니다.
+
+     범용 메모리 배리어는 로드와 스토어 모두에 대한 부분적 순서 세우기입니다.
+
+     범용 메모리 배리어는 읽기 메모리 배리어, 쓰기 메모리 배리어 모두를
+     내장하므로, 두 배리어를 모두 대신할 수 있습니다.
+
+
+그리고 두개의 명시적이지 않은 타입이 있습니다:
+
+ (5) ACQUIRE 오퍼레이션.
+
+     이 타입의 오퍼레이션은 단방향의 투과성 배리어처럼 동작합니다.  ACQUIRE
+     오퍼레이션 뒤의 모든 메모리 오퍼레이션들이 ACQUIRE 오퍼레이션 후에
+     일어난 것으로 시스템의 나머지 컴포넌트들에 보이게 될 것이 보장됩니다.
+     LOCK 오퍼레이션과 smp_load_acquire(), smp_cond_acquire() 오퍼레이션도
+     ACQUIRE 오퍼레이션에 포함됩니다.  smp_cond_acquire() 오퍼레이션은 컨트롤
+     의존성과 smp_rmb() 를 사용해서 ACQUIRE 의 의미적 요구사항(semantic)을
+     충족시킵니다.
+
+     ACQUIRE 오퍼레이션 앞의 메모리 오퍼레이션들은 ACQUIRE 오퍼레이션 완료 후에
+     수행된 것처럼 보일 수 있습니다.
+
+     ACQUIRE 오퍼레이션은 거의 항상 RELEASE 오퍼레이션과 짝을 지어 사용되어야
+     합니다.
+
+
+ (6) RELEASE 오퍼레이션.
+
+     이 타입의 오퍼레이션들도 단방향 투과성 배리어처럼 동작합니다.  RELEASE
+     오퍼레이션 앞의 모든 메모리 오퍼레이션들은 RELEASE 오퍼레이션 전에 완료된
+     것으로 시스템의 다른 컴포넌트들에 보여질 것이 보장됩니다.  UNLOCK 류의
+     오퍼레이션들과 smp_store_release() 오퍼레이션도 RELEASE 오퍼레이션의
+     일종입니다.
+
+     RELEASE 오퍼레이션 뒤의 메모리 오퍼레이션들은 RELEASE 오퍼레이션이
+     완료되기 전에 행해진 것처럼 보일 수 있습니다.
+
+     ACQUIRE 와 RELEASE 오퍼레이션의 사용은 일반적으로 다른 메모리 배리어의
+     필요성을 없앱니다 (하지만 "MMIO 쓰기 배리어" 서브섹션에서 설명되는 예외를
+     알아두세요).  또한, RELEASE+ACQUIRE 조합은 범용 메모리 배리어처럼 동작할
+     것을 보장하지 -않습니다-.  하지만, 어떤 변수에 대한 RELEASE 오퍼레이션을
+     앞서는 메모리 액세스들의 수행 결과는 이 RELEASE 오퍼레이션을 뒤이어 같은
+     변수에 대해 수행된 ACQUIRE 오퍼레이션을 뒤따르는 메모리 액세스에는 보여질
+     것이 보장됩니다.  다르게 말하자면, 주어진 변수의 크리티컬 섹션에서는, 해당
+     변수에 대한 앞의 크리티컬 섹션에서의 모든 액세스들이 완료되었을 것을
+     보장합니다.
+
+     즉, ACQUIRE 는 최소한의 "취득" 동작처럼, 그리고 RELEASE 는 최소한의 "공개"
+     처럼 동작한다는 의미입니다.
+
+atomic_ops.txt 에서 설명되는 어토믹 오퍼레이션들 중에는 완전히 순서잡힌 것들과
+(배리어를 사용하지 않는) 완화된 순서의 것들 외에 ACQUIRE 와 RELEASE 부류의
+것들도 존재합니다.  로드와 스토어를 모두 수행하는 조합된 어토믹 오퍼레이션에서,
+ACQUIRE 는 해당 오퍼레이션의 로드 부분에만 적용되고 RELEASE 는 해당
+오퍼레이션의 스토어 부분에만 적용됩니다.
+
+메모리 배리어들은 두 CPU 간, 또는 CPU 와 디바이스 간에 상호작용의 가능성이 있을
+때에만 필요합니다.  만약 어떤 코드에 그런 상호작용이 없을 것이 보장된다면, 해당
+코드에서는 메모리 배리어를 사용할 필요가 없습니다.
+
+
+이것들은 _최소한의_ 보장사항들임을 알아두세요.  다른 아키텍쳐에서는 더 강력한
+보장사항을 제공할 수도 있습니다만, 그런 보장사항은 아키텍쳐 종속적 코드 이외의
+부분에서는 신뢰되지 _않을_ 겁니다.
+
+
+메모리 배리어에 대해 가정해선 안될 것
+-------------------------------------
+
+리눅스 커널 메모리 배리어들이 보장하지 않는 것들이 있습니다:
+
+ (*) 메모리 배리어 앞에서 명시된 어떤 메모리 액세스도 메모리 배리어 명령의 수행
+     완료 시점까지 _완료_ 될 것이란 보장은 없습니다; 배리어가 하는 일은 CPU 의
+     액세스 큐에 특정 타입의 액세스들은 넘을 수 없는 선을 긋는 것으로 생각될 수
+     있습니다.
+
+ (*) 한 CPU 에서 메모리 배리어를 수행하는게 시스템의 다른 CPU 나 하드웨어에
+     어떤 직접적인 영향을 끼친다는 보장은 존재하지 않습니다.  배리어 수행이
+     만드는 간접적 영향은 두번째 CPU 가 첫번째 CPU 의 액세스들의 결과를
+     바라보는 순서가 됩니다만, 다음 항목을 보세요:
+
+ (*) 첫번째 CPU 가 두번째 CPU 의 메모리 액세스들의 결과를 바라볼 때, _설령_
+     두번째 CPU 가 메모리 배리어를 사용한다 해도, 첫번째 CPU _또한_ 그에 맞는
+     메모리 배리어를 사용하지 않는다면 ("SMP 배리어 짝맞추기" 서브섹션을
+     참고하세요) 그 결과가 올바른 순서로 보여진다는 보장은 없습니다.
+
+ (*) CPU 바깥의 하드웨어[*] 가 메모리 액세스들의 순서를 바꾸지 않는다는 보장은
+     존재하지 않습니다.  CPU 캐시 일관성 메커니즘은 메모리 배리어의 간접적
+     영향을 CPU 사이에 전파하긴 하지만, 순서대로 전파하지는 않을 수 있습니다.
+
+	[*] 버스 마스터링 DMA 와 일관성에 대해서는 다음을 참고하시기 바랍니다:
+
+	    Documentation/PCI/pci.txt
+	    Documentation/DMA-API-HOWTO.txt
+	    Documentation/DMA-API.txt
+
+
+데이터 의존성 배리어
+--------------------
+
+데이터 의존성 배리어의 사용에 있어 지켜야 하는 사항들은 약간 미묘하고, 데이터
+의존성 배리어가 사용되어야 하는 상황도 항상 명백하지는 않습니다.  설명을 위해
+다음의 이벤트 시퀀스를 생각해 봅시다:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
+	B = 4;
+	<쓰기 배리어>
+	WRITE_ONCE(P, &B)
+			      Q = READ_ONCE(P);
+			      D = *Q;
+
+여기엔 분명한 데이터 의존성이 존재하므로, 이 시퀀스가 끝났을 때 Q 는 &A 또는 &B
+일 것이고, 따라서:
+
+	(Q == &A) 는 (D == 1) 를,
+	(Q == &B) 는 (D == 4) 를 의미합니다.
+
+하지만!  CPU 2 는 B 의 업데이트를 인식하기 전에 P 의 업데이트를 인식할 수 있고,
+따라서 다음의 결과가 가능합니다:
+
+	(Q == &B) and (D == 2) ????
+
+이런 결과는 일관성이나 인과 관계 유지가 실패한 것처럼 보일 수도 있겠지만,
+그렇지 않습니다, 그리고 이 현상은 (DEC Alpha 와 같은) 여러 CPU 에서 실제로
+발견될 수 있습니다.
+
+이 문제 상황을 제대로 해결하기 위해, 데이터 의존성 배리어나 그보다 강화된
+무언가가 주소를 읽어올 때와 데이터를 읽어올 때 사이에 추가되어야만 합니다:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	{ A == 1, B == 2, C == 3, P == &A, Q == &C }
+	B = 4;
+	<쓰기 배리어>
+	WRITE_ONCE(P, &B);
+			      Q = READ_ONCE(P);
+			      <데이터 의존성 배리어>
+			      D = *Q;
+
+이 변경은 앞의 처음 두가지 결과 중 하나만이 발생할 수 있고, 세번째의 결과는
+발생할 수 없도록 합니다.
+
+데이터 의존성 배리어는 의존적 쓰기에 대해서도 순서를 잡아줍니다:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	{ A == 1, B == 2, C = 3, P == &A, Q == &C }
+	B = 4;
+	<쓰기 배리어>
+	WRITE_ONCE(P, &B);
+			      Q = READ_ONCE(P);
+			      <데이터 의존성 배리어>
+			      *Q = 5;
+
+이 데이터 의존성 배리어는 Q 로의 읽기가 *Q 로의 스토어와 순서를 맞추게
+해줍니다.  이는 다음과 같은 결과를 막습니다:
+
+	(Q == &B) && (B == 4)
+
+이런 패턴은 드물게 사용되어야 함을 알아 두시기 바랍니다.  무엇보다도, 의존성
+순서 규칙의 의도는 쓰기 작업을 -예방- 해서 그로 인해 발생하는 비싼 캐시 미스도
+없애려는 것입니다.  이 패턴은 드물게 발생하는 에러 조건 같은것들을 기록하는데
+사용될 수 있고, 이렇게 배리어를 사용해 순서를 지키게 함으로써 그런 기록이
+사라지는 것을 막습니다.
+
+
+[!] 상당히 비직관적인 이 상황은 분리된 캐시를 가진 기계, 예를 들어 한 캐시
+뱅크가 짝수번 캐시 라인을 처리하고 다른 뱅크는 홀수번 캐시 라인을 처리하는 기계
+등에서 가장 잘 발생합니다.  포인터 P 는 홀수 번호의 캐시 라인에 있고, 변수 B 는
+짝수 번호 캐시 라인에 있다고 생각해 봅시다.  그런 상태에서 읽기 작업을 하는 CPU
+의 짝수번 뱅크는 할 일이 쌓여 매우 바쁘지만 홀수번 뱅크는 할 일이 없어 아무
+일도 하지 않고  있었다면, 포인터 P 는 새 값 (&B) 을, 그리고 변수 B 는 옛날 값
+(2) 을 가지고 있는 상태가 보여질 수도 있습니다.
+
+
+데이터 의존성 배리어는 매우 중요한데, 예를 들어 RCU 시스템에서 그렇습니다.
+include/linux/rcupdate.h 의 rcu_assign_pointer() 와 rcu_dereference() 를
+참고하세요.  여기서 데이터 의존성 배리어는 RCU 로 관리되는 포인터의 타겟을 현재
+타겟에서 수정된 새로운 타겟으로 바꾸는 작업에서 새로 수정된 타겟이 초기화가
+완료되지 않은 채로 보여지는 일이 일어나지 않게 해줍니다.
+
+더 많은 예를 위해선 "캐시 일관성" 서브섹션을 참고하세요.
+
+
+컨트롤 의존성
+-------------
+
+로드-로드 컨트롤 의존성은 데이터 의존성 배리어만으로는 정확히 동작할 수가
+없어서 읽기 메모리 배리어를 필요로 합니다.  아래의 코드를 봅시다:
+
+	q = READ_ONCE(a);
+	if (q) {
+		<데이터 의존성 배리어>  /* BUG: No data dependency!!! */
+		p = READ_ONCE(b);
+	}
+
+이 코드는 원하는 대로의 효과를 내지 못할 수 있는데, 이 코드에는 데이터 의존성이
+아니라 컨트롤 의존성이 존재하기 때문으로, 이런 상황에서 CPU 는 실행 속도를 더
+빠르게 하기 위해 분기 조건의 결과를 예측하고 코드를 재배치 할 수 있어서 다른
+CPU 는 b 로부터의 로드 오퍼레이션이 a 로부터의 로드 오퍼레이션보다 먼저 발생한
+걸로 인식할 수 있습니다.  여기에 정말로 필요했던 건 다음과 같습니다:
+
+	q = READ_ONCE(a);
+	if (q) {
+		<읽기 배리어>
+		p = READ_ONCE(b);
+	}
+
+하지만, 스토어 오퍼레이션은 예측적으로 수행되지 않습니다.  즉, 다음 예에서와
+같이 로드-스토어 컨트롤 의존성이 존재하는 경우에는 순서가 -지켜진다-는
+의미입니다.
+
+	q = READ_ONCE(a);
+	if (q) {
+		WRITE_ONCE(b, p);
+	}
+
+컨트롤 의존성은 보통 다른 타입의 배리어들과 짝을 맞춰 사용됩니다.  그렇다곤
+하나, READ_ONCE() 는 반드시 사용해야 함을 부디 명심하세요!  READ_ONCE() 가
+없다면, 컴파일러가 'a' 로부터의 로드를 'a' 로부터의 또다른 로드와, 'b' 로의
+스토어를 'b' 로의 또다른 스토어와 조합해 버려 매우 비직관적인 결과를 초래할 수
+있습니다.
+
+이걸로 끝이 아닌게, 컴파일러가 변수 'a' 의 값이 항상 0이 아니라고 증명할 수
+있다면, 앞의 예에서 "if" 문을 없애서 다음과 같이 최적화 할 수도 있습니다:
+
+	q = a;
+	b = p;  /* BUG: Compiler and CPU can both reorder!!! */
+
+그러니 READ_ONCE() 를 반드시 사용하세요.
+
+다음과 같이 "if" 문의 양갈래 브랜치에 모두 존재하는 동일한 스토어에 대해 순서를
+강제하고 싶은 경우가 있을 수 있습니다:
+
+	q = READ_ONCE(a);
+	if (q) {
+		barrier();
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		barrier();
+		WRITE_ONCE(b, p);
+		do_something_else();
+	}
+
+안타깝게도, 현재의 컴파일러들은 높은 최적화 레벨에서는 이걸 다음과 같이
+바꿔버립니다:
+
+	q = READ_ONCE(a);
+	barrier();
+	WRITE_ONCE(b, p);  /* BUG: No ordering vs. load from a!!! */
+	if (q) {
+		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
+		do_something();
+	} else {
+		/* WRITE_ONCE(b, p); -- moved up, BUG!!! */
+		do_something_else();
+	}
+
+이제 'a' 에서의 로드와 'b' 로의 스토어 사이에는 조건적 관계가 없기 때문에 CPU
+는 이들의 순서를 바꿀 수 있게 됩니다: 이런 경우에 조건적 관계는 반드시
+필요한데, 모든 컴파일러 최적화가 이루어지고 난 후의 어셈블리 코드에서도
+마찬가지입니다.  따라서, 이 예에서 순서를 지키기 위해서는 smp_store_release()
+와 같은 명시적 메모리 배리어가 필요합니다:
+
+	q = READ_ONCE(a);
+	if (q) {
+		smp_store_release(&b, p);
+		do_something();
+	} else {
+		smp_store_release(&b, p);
+		do_something_else();
+	}
+
+반면에 명시적 메모리 배리어가 없다면, 이런 경우의 순서는 스토어 오퍼레이션들이
+서로 다를 때에만 보장되는데, 예를 들면 다음과 같은 경우입니다:
+
+	q = READ_ONCE(a);
+	if (q) {
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		WRITE_ONCE(b, r);
+		do_something_else();
+	}
+
+처음의 READ_ONCE() 는 컴파일러가 'a' 의 값을 증명해내는 것을 막기 위해 여전히
+필요합니다.
+
+또한, 로컬 변수 'q' 를 가지고 하는 일에 대해 주의해야 하는데, 그러지 않으면
+컴파일러는 그 값을 추측하고 또다시 필요한 조건관계를 없애버릴 수 있습니다.
+예를 들면:
+
+	q = READ_ONCE(a);
+	if (q % MAX) {
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		WRITE_ONCE(b, r);
+		do_something_else();
+	}
+
+만약 MAX 가 1 로 정의된 상수라면, 컴파일러는 (q % MAX) 는 0이란 것을 알아채고,
+위의 코드를 아래와 같이 바꿔버릴 수 있습니다:
+
+	q = READ_ONCE(a);
+	WRITE_ONCE(b, p);
+	do_something_else();
+
+이렇게 되면, CPU 는 변수 'a' 로부터의 로드와 변수 'b' 로의 스토어 사이의 순서를
+지켜줄 필요가 없어집니다.  barrier() 를 추가해 해결해 보고 싶겠지만, 그건
+도움이 안됩니다.  조건 관계는 사라졌고, barrier() 는 이를 되돌리지 못합니다.
+따라서, 이 순서를 지켜야 한다면, MAX 가 1 보다 크다는 것을, 다음과 같은 방법을
+사용해 분명히 해야 합니다:
+
+	q = READ_ONCE(a);
+	BUILD_BUG_ON(MAX <= 1); /* Order load from a with store to b. */
+	if (q % MAX) {
+		WRITE_ONCE(b, p);
+		do_something();
+	} else {
+		WRITE_ONCE(b, r);
+		do_something_else();
+	}
+
+'b' 로의 스토어들은 여전히 서로 다름을 알아두세요.  만약 그것들이 동일하면,
+앞에서 이야기했듯, 컴파일러가 그 스토어 오퍼레이션들을 'if' 문 바깥으로
+끄집어낼 수 있습니다.
+
+또한 이진 조건문 평가에 너무 의존하지 않도록 조심해야 합니다.  다음의 예를
+봅시다:
+
+	q = READ_ONCE(a);
+	if (q || 1 > 0)
+		WRITE_ONCE(b, 1);
+
+첫번째 조건만으로는 브랜치 조건 전체를 거짓으로 만들 수 없고 두번째 조건은 항상
+참이기 때문에, 컴파일러는 이 예를 다음과 같이 바꿔서 컨트롤 의존성을 없애버릴
+수 있습니다:
+
+	q = READ_ONCE(a);
+	WRITE_ONCE(b, 1);
+
+이 예는 컴파일러가 코드를 추측으로 수정할 수 없도록 분명히 해야 한다는 점을
+강조합니다.  조금 더 일반적으로 말해서, READ_ONCE() 는 컴파일러에게 주어진 로드
+오퍼레이션을 위한 코드를 정말로 만들도록 하지만, 컴파일러가 그렇게 만들어진
+코드의 수행 결과를 사용하도록 강제하지는 않습니다.
+
+또한, 컨트롤 의존성은 if 문의 then 절과 else 절에 대해서만 적용됩니다.  상세히
+말해서, 컨트롤 의존성은 if 문을 뒤따르는 코드에는 적용되지 않습니다:
+
+	q = READ_ONCE(a);
+	if (q) {
+		WRITE_ONCE(b, p);
+	} else {
+		WRITE_ONCE(b, r);
+	}
+	WRITE_ONCE(c, 1);  /* BUG: No ordering against the read from "a". */
+
+컴파일러는 volatile 타입에 대한 액세스를 재배치 할 수 없고 이 조건 하의 "b"
+로의 쓰기를 재배치 할 수 없기 때문에 여기에 순서 규칙이 존재한다고 주장하고
+싶을 겁니다.  불행히도 이 경우에, 컴파일러는 다음의 가상의 pseudo-assembly 언어
+코드처럼 "b" 로의 두개의 쓰기 오퍼레이션을 conditional-move 인스트럭션으로
+번역할 수 있습니다:
+
+	ld r1,a
+	ld r2,p
+	ld r3,r
+	cmp r1,$0
+	cmov,ne r4,r2
+	cmov,eq r4,r3
+	st r4,b
+	st $1,c
+
+완화된 순서 규칙의 CPU 는 "a" 로부터의 로드와 "c" 로의 스토어 사이에 어떤
+종류의 의존성도 갖지 않을 겁니다.  이 컨트롤 의존성은 두개의 cmov 인스트럭션과
+거기에 의존하는 스토어 에게만 적용될 겁니다.  짧게 말하자면, 컨트롤 의존성은
+주어진 if 문의 then 절과 else 절에게만 (그리고 이 두 절 내에서 호출되는
+함수들에게까지) 적용되지, 이 if 문을 뒤따르는 코드에는 적용되지 않습니다.
+
+마지막으로, 컨트롤 의존성은 이행성 (transitivity) 을 제공하지 -않습니다-.  이건
+x 와 y 가 둘 다 0 이라는 초기값을 가졌다는 가정 하의 두개의 예제로
+보이겠습니다:
+
+	CPU 0                     CPU 1
+	=======================   =======================
+	r1 = READ_ONCE(x);        r2 = READ_ONCE(y);
+	if (r1 > 0)               if (r2 > 0)
+	  WRITE_ONCE(y, 1);         WRITE_ONCE(x, 1);
+
+	assert(!(r1 == 1 && r2 == 1));
+
+이 두 CPU 예제에서 assert() 의 조건은 항상 참일 것입니다.  그리고, 만약 컨트롤
+의존성이 이행성을 (실제로는 그러지 않지만) 보장한다면, 다음의 CPU 가 추가되어도
+아래의 assert() 조건은 참이 될것입니다:
+
+	CPU 2
+	=====================
+	WRITE_ONCE(x, 2);
+
+	assert(!(r1 == 2 && r2 == 1 && x == 2)); /* FAILS!!! */
+
+하지만 컨트롤 의존성은 이행성을 제공하지 -않기- 때문에, 세개의 CPU 예제가 실행
+완료된 후에 위의 assert() 의 조건은 거짓으로 평가될 수 있습니다.  세개의 CPU
+예제가 순서를 지키길 원한다면, CPU 0 와 CPU 1 코드의 로드와 스토어 사이, "if"
+문 바로 다음에 smp_mb()를 넣어야 합니다.  더 나아가서, 최초의 두 CPU 예제는
+매우 위험하므로 사용되지 않아야 합니다.
+
+이 두개의 예제는 다음 논문:
+http://www.cl.cam.ac.uk/users/pes20/ppc-supplemental/test6.pdf 와
+이 사이트: https://www.cl.cam.ac.uk/~pes20/ppcmem/index.html 에 나온 LB 와 WWC
+리트머스 테스트입니다.
+
+요약하자면:
+
+  (*) 컨트롤 의존성은 앞의 로드들을 뒤의 스토어들에 대해 순서를 맞춰줍니다.
+      하지만, 그 외의 어떤 순서도 보장하지 -않습니다-: 앞의 로드와 뒤의 로드들
+      사이에도, 앞의 스토어와 뒤의 스토어들 사이에도요.  이런 다른 형태의
+      순서가 필요하다면 smp_rmb() 나 smp_wmb()를, 또는, 앞의 스토어들과 뒤의
+      로드들 사이의 순서를 위해서는 smp_mb() 를 사용하세요.
+
+  (*) "if" 문의 양갈래 브랜치가 같은 변수에의 동일한 스토어로 시작한다면, 그
+      스토어들은 각 스토어 앞에 smp_mb() 를 넣거나 smp_store_release() 를
+      사용해서 스토어를 하는 식으로 순서를 맞춰줘야 합니다.  이 문제를 해결하기
+      위해 "if" 문의 양갈래 브랜치의 시작 지점에 barrier() 를 넣는 것만으로는
+      충분한 해결이 되지 않는데, 이는 앞의 예에서 본것과 같이, 컴파일러의
+      최적화는 barrier() 가 의미하는 바를 지키면서도 컨트롤 의존성을 손상시킬
+      수 있기 때문이라는 점을 부디 알아두시기 바랍니다.
+
+  (*) 컨트롤 의존성은 앞의 로드와 뒤의 스토어 사이에 최소 하나의, 실행
+      시점에서의 조건관계를 필요로 하며, 이 조건관계는 앞의 로드와 관계되어야
+      합니다.  만약 컴파일러가 조건 관계를 최적화로 없앨수 있다면, 순서도
+      최적화로 없애버렸을 겁니다.  READ_ONCE() 와 WRITE_ONCE() 의 주의 깊은
+      사용은 주어진 조건 관계를 유지하는데 도움이 될 수 있습니다.
+
+  (*) 컨트롤 의존성을 위해선 컴파일러가 조건관계를 없애버리는 것을 막아야
+      합니다.  주의 깊은 READ_ONCE() 나 atomic{,64}_read() 의 사용이 컨트롤
+      의존성이 사라지지 않게 하는데 도움을 줄 수 있습니다.  더 많은 정보를
+      위해선 "컴파일러 배리어" 섹션을 참고하시기 바랍니다.
+
+  (*) 컨트롤 의존성은 컨트롤 의존성을 갖는 if 문의 then 절과 else 절과 이 두 절
+      내에서 호출되는 함수들에만 적용됩니다.  컨트롤 의존성은 컨트롤 의존성을
+      갖는 if 문을 뒤따르는 코드에는 적용되지 -않습니다-.
+
+  (*) 컨트롤 의존성은 보통 다른 타입의 배리어들과 짝을 맞춰 사용됩니다.
+
+  (*) 컨트롤 의존성은 이행성을 제공하지 -않습니다-.  이행성이 필요하다면,
+      smp_mb() 를 사용하세요.
+
+
+SMP 배리어 짝맞추기
+--------------------
+
+CPU 간 상호작용을 다룰 때에 일부 타입의 메모리 배리어는 항상 짝을 맞춰
+사용되어야 합니다.  적절하게 짝을 맞추지 않은 코드는 사실상 에러에 가깝습니다.
+
+범용 배리어들은 범용 배리어끼리도 짝을 맞추지만 이행성이 없는 대부분의 다른
+타입의 배리어들과도 짝을 맞춥니다.  ACQUIRE 배리어는 RELEASE 배리어와 짝을
+맞춥니다만, 둘 다 범용 배리어를 포함해 다른 배리어들과도 짝을 맞출 수 있습니다.
+쓰기 배리어는 데이터 의존성 배리어나 컨트롤 의존성, ACQUIRE 배리어, RELEASE
+배리어, 읽기 배리어, 또는 범용 배리어와 짝을 맞춥니다.  비슷하게 읽기 배리어나
+컨트롤 의존성, 또는 데이터 의존성 배리어는 쓰기 배리어나 ACQUIRE 배리어,
+RELEASE 배리어, 또는 범용 배리어와 짝을 맞추는데, 다음과 같습니다:
+
+	CPU 1		      CPU 2
+	===============	      ===============
+	WRITE_ONCE(a, 1);
+	<쓰기 배리어>
+	WRITE_ONCE(b, 2);     x = READ_ONCE(b);
+			      <읽기 배리어>
+			      y = READ_ONCE(a);
+
+또는:
+
+	CPU 1		      CPU 2
+	===============	      ===============================
+	a = 1;
+	<쓰기 배리어>
+	WRITE_ONCE(b, &a);    x = READ_ONCE(b);
+			      <데이터 의존성 배리어>
+			      y = *x;
+
+또는:
+
+	CPU 1		      CPU 2
+	===============	      ===============================
+	r1 = READ_ONCE(y);
+	<범용 배리어>
+	WRITE_ONCE(y, 1);     if (r2 = READ_ONCE(x)) {
+			         <묵시적 컨트롤 의존성>
+			         WRITE_ONCE(y, 1);
+			      }
+
+	assert(r1 == 0 || r2 == 0);
+
+기본적으로, 여기서의 읽기 배리어는 "더 완화된" 타입일 순 있어도 항상 존재해야
+합니다.
+
+[!] 쓰기 배리어 앞의 스토어 오퍼레이션은 일반적으로 읽기 배리어나 데이터
+의존성 배리어 뒤의 로드 오퍼레이션과 매치될 것이고, 반대도 마찬가지입니다:
+
+	CPU 1                               CPU 2
+	===================                 ===================
+	WRITE_ONCE(a, 1);    }----   --->{  v = READ_ONCE(c);
+	WRITE_ONCE(b, 2);    }    \ /    {  w = READ_ONCE(d);
+	<쓰기 배리어>              \        <읽기 배리어>
+	WRITE_ONCE(c, 3);    }    / \    {  x = READ_ONCE(a);
+	WRITE_ONCE(d, 4);    }----   --->{  y = READ_ONCE(b);
+
+
+메모리 배리어 시퀀스의 예
+-------------------------
+
+첫째, 쓰기 배리어는 스토어 오퍼레이션들의 부분적 순서 세우기로 동작합니다.
+아래의 이벤트 시퀀스를 보세요:
+
+	CPU 1
+	=======================
+	STORE A = 1
+	STORE B = 2
+	STORE C = 3
+	<쓰기 배리어>
+	STORE D = 4
+	STORE E = 5
+
+이 이벤트 시퀀스는 메모리 일관성 시스템에 원소끼리의 순서가 존재하지 않는 집합
+{ STORE A, STORE B, STORE C } 가 역시 원소끼리의 순서가 존재하지 않는 집합
+{ STORE D, STORE E } 보다 먼저 일어난 것으로 시스템의 나머지 요소들에 보이도록
+전달됩니다:
+
+	+-------+       :      :
+	|       |       +------+
+	|       |------>| C=3  |     }     /\
+	|       |  :    +------+     }-----  \  -----> 시스템의 나머지 요소에
+	|       |  :    | A=1  |     }        \/       보여질 수 있는 이벤트들
+	|       |  :    +------+     }
+	| CPU 1 |  :    | B=2  |     }
+	|       |       +------+     }
+	|       |   wwwwwwwwwwwwwwww }   <--- 여기서 쓰기 배리어는 배리어 앞의
+	|       |       +------+     }        모든 스토어가 배리어 뒤의 스토어
+	|       |  :    | E=5  |     }        전에 메모리 시스템에 전달되도록
+	|       |  :    +------+     }        합니다
+	|       |------>| D=4  |     }
+	|       |       +------+
+	+-------+       :      :
+	                   |
+	                   | CPU 1 에 의해 메모리 시스템에 전달되는
+	                   | 일련의 스토어 오퍼레이션들
+	                   V
+
+
+둘째, 데이터 의존성 배리어는 데이터 의존적 로드 오퍼레이션들의 부분적 순서
+세우기로 동작합니다.  다음 일련의 이벤트들을 보세요:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ B = 7; X = 9; Y = 8; C = &Y }
+	STORE A = 1
+	STORE B = 2
+	<쓰기 배리어>
+	STORE C = &B		LOAD X
+	STORE D = 4		LOAD C (gets &B)
+				LOAD *C (reads B)
+
+여기에 별다른 개입이 없다면, CPU 1 의 쓰기 배리어에도 불구하고 CPU 2 는 CPU 1
+의 이벤트들을 완전히 무작위적 순서로 인지하게 됩니다:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+  | CPU 2 에 인지되는
+	|       |------>| B=2  |-----       --->| Y->8  |  | 업데이트 이벤트
+	|       |  :    +------+     \          +-------+  | 시퀀스
+	| CPU 1 |  :    | A=1  |      \     --->| C->&Y |  V
+	|       |       +------+       |        +-------+
+	|       |   wwwwwwwwwwwwwwww   |        :       :
+	|       |       +------+       |        :       :
+	|       |  :    | C=&B |---    |        :       :       +-------+
+	|       |  :    +------+   \   |        +-------+       |       |
+	|       |------>| D=4  |    ----------->| C->&B |------>|       |
+	|       |       +------+       |        +-------+       |       |
+	+-------+       :      :       |        :       :       |       |
+	                               |        :       :       |       |
+	                               |        :       :       | CPU 2 |
+	                               |        +-------+       |       |
+	    분명히 잘못된        --->  |        | B->7  |------>|       |
+	    B 의 값 인지 (!)           |        +-------+       |       |
+	                               |        :       :       |       |
+	                               |        +-------+       |       |
+	    X 의 로드가 B 의    --->    \       | X->9  |------>|       |
+	    일관성 유지를                \      +-------+       |       |
+	    지연시킴                      ----->| B->2  |       +-------+
+	                                        +-------+
+	                                        :       :
+
+
+앞의 예에서, CPU 2 는 (B 의 값이 될) *C 의 값 읽기가 C 의 LOAD 뒤에 이어짐에도
+B 가 7 이라는 결과를 얻습니다.
+
+하지만, 만약 데이터 의존성 배리어가 C 의 로드와 *C (즉, B) 의 로드 사이에
+있었다면:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ B = 7; X = 9; Y = 8; C = &Y }
+	STORE A = 1
+	STORE B = 2
+	<쓰기 배리어>
+	STORE C = &B		LOAD X
+	STORE D = 4		LOAD C (gets &B)
+				<데이터 의존성 배리어>
+				LOAD *C (reads B)
+
+다음과 같이 됩니다:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| B=2  |-----       --->| Y->8  |
+	|       |  :    +------+     \          +-------+
+	| CPU 1 |  :    | A=1  |      \     --->| C->&Y |
+	|       |       +------+       |        +-------+
+	|       |   wwwwwwwwwwwwwwww   |        :       :
+	|       |       +------+       |        :       :
+	|       |  :    | C=&B |---    |        :       :       +-------+
+	|       |  :    +------+   \   |        +-------+       |       |
+	|       |------>| D=4  |    ----------->| C->&B |------>|       |
+	|       |       +------+       |        +-------+       |       |
+	+-------+       :      :       |        :       :       |       |
+	                               |        :       :       |       |
+	                               |        :       :       | CPU 2 |
+	                               |        +-------+       |       |
+	                               |        | X->9  |------>|       |
+	                               |        +-------+       |       |
+	  C 로의 스토어 앞의     --->   \   ddddddddddddddddd   |       |
+	  모든 이벤트 결과가             \      +-------+       |       |
+	  뒤의 로드에게                   ----->| B->2  |------>|       |
+	  보이게 강제한다                       +-------+       |       |
+	                                        :       :       +-------+
+
+
+셋째, 읽기 배리어는 로드 오퍼레이션들에의 부분적 순서 세우기로 동작합니다.
+아래의 일련의 이벤트를 봅시다:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ A = 0, B = 9 }
+	STORE A=1
+	<쓰기 배리어>
+	STORE B=2
+				LOAD B
+				LOAD A
+
+CPU 1 은 쓰기 배리어를 쳤지만, 별다른 개입이 없다면 CPU 2 는 CPU 1 에서 행해진
+이벤트의 결과를 무작위적 순서로 인지하게 됩니다.
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       | A->0  |------>|       |
+	                                |       +-------+       |       |
+	                                |       :       :       +-------+
+	                                 \      :       :
+	                                  \     +-------+
+	                                   ---->| A->1  |
+	                                        +-------+
+	                                        :       :
+
+
+하지만, 만약 읽기 배리어가 B 의 로드와 A 의 로드 사이에 존재한다면:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ A = 0, B = 9 }
+	STORE A=1
+	<쓰기 배리어>
+	STORE B=2
+				LOAD B
+				<읽기 배리어>
+				LOAD A
+
+CPU 1 에 의해 만들어진 부분적 순서가 CPU 2 에도 그대로 인지됩니다:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       :       :       |       |
+	                                |       :       :       |       |
+	  여기서 읽기 배리어는   ---->   \  rrrrrrrrrrrrrrrrr   |       |
+	  B 로의 스토어 전의              \     +-------+       |       |
+	  모든 결과를 CPU 2 에             ---->| A->1  |------>|       |
+	  보이도록 한다                         +-------+       |       |
+	                                        :       :       +-------+
+
+
+더 완벽한 설명을 위해, A 의 로드가 읽기 배리어 앞과 뒤에 있으면 어떻게 될지
+생각해 봅시다:
+
+	CPU 1			CPU 2
+	=======================	=======================
+		{ A = 0, B = 9 }
+	STORE A=1
+	<쓰기 배리어>
+	STORE B=2
+				LOAD B
+				LOAD A [first load of A]
+				<읽기 배리어>
+				LOAD A [second load of A]
+
+A 의 로드 두개가 모두 B 의 로드 뒤에 있지만, 서로 다른 값을 얻어올 수
+있습니다:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       :       :       |       |
+	                                |       :       :       |       |
+	                                |       +-------+       |       |
+	                                |       | A->0  |------>| 1st   |
+	                                |       +-------+       |       |
+	  여기서 읽기 배리어는   ---->   \  rrrrrrrrrrrrrrrrr   |       |
+	  B 로의 스토어 전의              \     +-------+       |       |
+	  모든 결과를 CPU 2 에             ---->| A->1  |------>| 2nd   |
+	  보이도록 한다                         +-------+       |       |
+	                                        :       :       +-------+
+
+
+하지만 CPU 1 에서의 A 업데이트는 읽기 배리어가 완료되기 전에도 보일 수도
+있긴 합니다:
+
+	+-------+       :      :                :       :
+	|       |       +------+                +-------+
+	|       |------>| A=1  |------      --->| A->0  |
+	|       |       +------+      \         +-------+
+	| CPU 1 |   wwwwwwwwwwwwwwww   \    --->| B->9  |
+	|       |       +------+        |       +-------+
+	|       |------>| B=2  |---     |       :       :
+	|       |       +------+   \    |       :       :       +-------+
+	+-------+       :      :    \   |       +-------+       |       |
+	                             ---------->| B->2  |------>|       |
+	                                |       +-------+       | CPU 2 |
+	                                |       :       :       |       |
+	                                 \      :       :       |       |
+	                                  \     +-------+       |       |
+	                                   ---->| A->1  |------>| 1st   |
+	                                        +-------+       |       |
+	                                    rrrrrrrrrrrrrrrrr   |       |
+	                                        +-------+       |       |
+	                                        | A->1  |------>| 2nd   |
+	                                        +-------+       |       |
+	                                        :       :       +-------+
+
+
+여기서 보장되는 건, 만약 B 의 로드가 B == 2 라는 결과를 봤다면, A 에의 두번째
+로드는 항상 A == 1 을 보게 될 것이라는 겁니다.  A 에의 첫번째 로드에는 그런
+보장이 없습니다; A == 0 이거나 A == 1 이거나 둘 중 하나의 결과를 보게 될겁니다.
+
+
+읽기 메모리 배리어 VS 로드 예측
+-------------------------------
+
+많은 CPU들이 로드를 예측적으로 (speculatively) 합니다: 어떤 데이터를 메모리에서
+로드해야 하게 될지 예측을 했다면, 해당 데이터를 로드하는 인스트럭션을 실제로는
+아직 만나지 않았더라도 다른 로드 작업이 없어 버스 (bus) 가 아무 일도 하고 있지
+않다면, 그 데이터를 로드합니다.  이후에 실제 로드 인스트럭션이 실행되면 CPU 가
+이미 그 값을 가지고 있기 때문에 그 로드 인스트럭션은 즉시 완료됩니다.
+
+해당 CPU 는 실제로는 그 값이 필요치 않았다는 사실이 나중에 드러날 수도 있는데 -
+해당 로드 인스트럭션이 브랜치로 우회되거나 했을 수 있겠죠 - , 그렇게 되면 앞서
+읽어둔 값을 버리거나 나중의 사용을 위해 캐시에 넣어둘 수 있습니다.
+
+다음을 생각해 봅시다:
+
+	CPU 1			CPU 2
+	=======================	=======================
+				LOAD B
+				DIVIDE		} 나누기 명령은 일반적으로
+				DIVIDE		} 긴 시간을 필요로 합니다
+				LOAD A
+
+는 이렇게 될 수 있습니다:
+
+	                                        :       :       +-------+
+	                                        +-------+       |       |
+	                                    --->| B->2  |------>|       |
+	                                        +-------+       | CPU 2 |
+	                                        :       :DIVIDE |       |
+	                                        +-------+       |       |
+	나누기 하느라 바쁜       --->       --->| A->0  |~~~~   |       |
+	CPU 는 A 의 LOAD 를                     +-------+   ~   |       |
+	예측해서 수행한다                       :       :   ~   |       |
+	                                        :       :DIVIDE |       |
+	                                        :       :   ~   |       |
+	나누기가 끝나면       --->     --->     :       :   ~-->|       |
+	CPU 는 해당 LOAD 를                     :       :       |       |
+	즉각 완료한다                           :       :       +-------+
+
+
+읽기 배리어나 데이터 의존성 배리어를 두번째 로드 직전에 놓는다면:
+
+	CPU 1			CPU 2
+	=======================	=======================
+				LOAD B
+				DIVIDE
+				DIVIDE
+				<읽기 배리어>
+				LOAD A
+
+예측으로 얻어진 값은 사용된 배리어의 타입에 따라서 해당 값이 옳은지 검토되게
+됩니다.  만약 해당 메모리 영역에 변화가 없었다면, 예측으로 얻어두었던 값이
+사용됩니다:
+
+	                                        :       :       +-------+
+	                                        +-------+       |       |
+	                                    --->| B->2  |------>|       |
+	                                        +-------+       | CPU 2 |
+	                                        :       :DIVIDE |       |
+	                                        +-------+       |       |
+	나누기 하느라 바쁜       --->       --->| A->0  |~~~~   |       |
+	CPU 는 A 의 LOAD 를                     +-------+   ~   |       |
+	예측한다                                :       :   ~   |       |
+	                                        :       :DIVIDE |       |
+	                                        :       :   ~   |       |
+	                                        :       :   ~   |       |
+	                                    rrrrrrrrrrrrrrrr~   |       |
+	                                        :       :   ~   |       |
+	                                        :       :   ~-->|       |
+	                                        :       :       |       |
+	                                        :       :       +-------+
+
+
+하지만 다른 CPU 에서 업데이트나 무효화가 있었다면, 그 예측은 무효화되고 그 값은
+다시 읽혀집니다:
+
+	                                        :       :       +-------+
+	                                        +-------+       |       |
+	                                    --->| B->2  |------>|       |
+	                                        +-------+       | CPU 2 |
+	                                        :       :DIVIDE |       |
+	                                        +-------+       |       |
+	나누기 하느라 바쁜       --->       --->| A->0  |~~~~   |       |
+	CPU 는 A 의 LOAD 를                     +-------+   ~   |       |
+	예측한다                                :       :   ~   |       |
+	                                        :       :DIVIDE |       |
+	                                        :       :   ~   |       |
+	                                        :       :   ~   |       |
+	                                    rrrrrrrrrrrrrrrrr   |       |
+	                                        +-------+       |       |
+	예측성 동작은 무효화 되고    --->   --->| A->1  |------>|       |
+	업데이트된 값이 다시 읽혀진다           +-------+       |       |
+	                                        :       :       +-------+
+
+
+이행성
+------
+
+이행성(transitivity)은 실제의 컴퓨터 시스템에서 항상 제공되지는 않는, 순서
+맞추기에 대한 상당히 직관적인 개념입니다.  다음의 예가 이행성을 보여줍니다:
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<범용 배리어>		<범용 배리어>
+				LOAD Y			LOAD X
+
+CPU 2 의 X 로드가 1을 리턴했고 Y 로드가 0을 리턴했다고 해봅시다.  이는 CPU 2 의
+X 로드가 CPU 1 의 X 스토어 뒤에 이루어졌고 CPU 2 의 Y 로드는 CPU 3 의 Y 스토어
+전에 이루어졌음을 의미합니다.  그럼 "CPU 3 의 X 로드는 0을 리턴할 수 있나요?"
+
+CPU 2 의 X 로드는 CPU 1 의 스토어 후에 이루어졌으니, CPU 3 의 X 로드는 1을
+리턴하는게 자연스럽습니다.  이런 생각이 이행성의 한 예입니다: CPU A 에서 실행된
+로드가 CPU B 에서의 같은 변수에 대한 로드를 뒤따른다면, CPU A 의 로드는 CPU B
+의 로드가 내놓은 값과 같거나 그 후의 값을 내놓아야 합니다.
+
+리눅스 커널에서 범용 배리어의 사용은 이행성을 보장합니다.  따라서, 앞의 예에서
+CPU 2 의 X 로드가 1을, Y 로드는 0을 리턴했다면, CPU 3 의 X 로드는 반드시 1을
+리턴합니다.
+
+하지만, 읽기나 쓰기 배리어에 대해서는 이행성이 보장되지 -않습니다-.  예를 들어,
+앞의 예에서 CPU 2 의 범용 배리어가 아래처럼 읽기 배리어로 바뀐 경우를 생각해
+봅시다:
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<읽기 배리어>		<범용 배리어>
+				LOAD Y			LOAD X
+
+이 코드는 이행성을 갖지 않습니다: 이 예에서는, CPU 2 의 X 로드가 1을
+리턴하고, Y 로드는 0을 리턴하지만 CPU 3 의 X 로드가 0을 리턴하는 것도 완전히
+합법적입니다.
+
+CPU 2 의 읽기 배리어가 자신의 읽기는 순서를 맞춰줘도, CPU 1 의 스토어와의
+순서를 맞춰준다고는 보장할 수 없다는게 핵심입니다.  따라서, CPU 1 과 CPU 2 가
+버퍼나 캐시를 공유하는 시스템에서 이 예제 코드가 실행된다면, CPU 2 는 CPU 1 이
+쓴 값에 좀 빨리 접근할 수 있을 것입니다.  따라서 CPU 1 과 CPU 2 의 접근으로
+조합된 순서를 모든 CPU 가 동의할 수 있도록 하기 위해 범용 배리어가 필요합니다.
+
+범용 배리어는 "글로벌 이행성"을 제공해서, 모든 CPU 들이 오퍼레이션들의 순서에
+동의하게 할 것입니다.  반면, release-acquire 조합은 "로컬 이행성" 만을
+제공해서, 해당 조합이 사용된 CPU 들만이 해당 액세스들의 조합된 순서에 동의함이
+보장됩니다.  예를 들어, 존경스런 Herman Hollerith 의 C 코드로 보면:
+
+	int u, v, x, y, z;
+
+	void cpu0(void)
+	{
+		r0 = smp_load_acquire(&x);
+		WRITE_ONCE(u, 1);
+		smp_store_release(&y, 1);
+	}
+
+	void cpu1(void)
+	{
+		r1 = smp_load_acquire(&y);
+		r4 = READ_ONCE(v);
+		r5 = READ_ONCE(u);
+		smp_store_release(&z, 1);
+	}
+
+	void cpu2(void)
+	{
+		r2 = smp_load_acquire(&z);
+		smp_store_release(&x, 1);
+	}
+
+	void cpu3(void)
+	{
+		WRITE_ONCE(v, 1);
+		smp_mb();
+		r3 = READ_ONCE(u);
+	}
+
+cpu0(), cpu1(), 그리고 cpu2() 는 smp_store_release()/smp_load_acquire() 쌍의
+연결을 통한 로컬 이행성에 동참하고 있으므로, 다음과 같은 결과는 나오지 않을
+겁니다:
+
+	r0 == 1 && r1 == 1 && r2 == 1
+
+더 나아가서, cpu0() 와 cpu1() 사이의 release-acquire 관계로 인해, cpu1() 은
+cpu0() 의 쓰기를 봐야만 하므로, 다음과 같은 결과도 없을 겁니다:
+
+	r1 == 1 && r5 == 0
+
+하지만, release-acquire 타동성은 동참한 CPU 들에만 적용되므로 cpu3() 에는
+적용되지 않습니다.  따라서, 다음과 같은 결과가 가능합니다:
+
+	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
+
+비슷하게, 다음과 같은 결과도 가능합니다:
+
+	r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 && r5 == 1
+
+cpu0(), cpu1(), 그리고 cpu2() 는 그들의 읽기와 쓰기를 순서대로 보게 되지만,
+release-acquire 체인에 관여되지 않은 CPU 들은 그 순서에 이견을 가질 수
+있습니다.  이런 이견은 smp_load_acquire() 와 smp_store_release() 의 구현에
+사용되는 완화된 메모리 배리어 인스트럭션들은 항상 배리어 앞의 스토어들을 뒤의
+로드들에 앞세울 필요는 없다는 사실에서 기인합니다.  이 말은 cpu3() 는 cpu0() 의
+u 로의 스토어를 cpu1() 의 v 로부터의 로드 뒤에 일어난 것으로 볼 수 있다는
+뜻입니다, cpu0() 와 cpu1() 은 이 두 오퍼레이션이 의도된 순서대로 일어났음에
+모두 동의하는데도 말입니다.
+
+하지만, smp_load_acquire() 는 마술이 아님을 명심하시기 바랍니다.  구체적으로,
+이 함수는 단순히 순서 규칙을 지키며 인자로부터의 읽기를 수행합니다.  이것은
+어떤 특정한 값이 읽힐 것인지는 보장하지 -않습니다-.  따라서, 다음과 같은 결과도
+가능합니다:
+
+	r0 == 0 && r1 == 0 && r2 == 0 && r5 == 0
+
+이런 결과는 어떤 것도 재배치 되지 않는, 순차적 일관성을 가진 가상의
+시스템에서도 일어날 수 있음을 기억해 두시기 바랍니다.
+
+다시 말하지만, 당신의 코드가 글로벌 이행성을 필요로 한다면, 범용 배리어를
+사용하십시오.
+
+
+==================
+명시적 커널 배리어
+==================
+
+리눅스 커널은 서로 다른 단계에서 동작하는 다양한 배리어들을 가지고 있습니다:
+
+  (*) 컴파일러 배리어.
+
+  (*) CPU 메모리 배리어.
+
+  (*) MMIO 쓰기 배리어.
+
+
+컴파일러 배리어
+---------------
+
+리눅스 커널은 컴파일러가 메모리 액세스를 재배치 하는 것을 막아주는 명시적인
+컴파일러 배리어를 가지고 있습니다:
+
+	barrier();
+
+이건 범용 배리어입니다 -- barrier() 의 읽기-읽기 나 쓰기-쓰기 변종은 없습니다.
+하지만, READ_ONCE() 와 WRITE_ONCE() 는 특정 액세스들에 대해서만 동작하는
+barrier() 의 완화된 형태로 볼 수 있습니다.
+
+barrier() 함수는 다음과 같은 효과를 갖습니다:
+
+ (*) 컴파일러가 barrier() 뒤의 액세스들이 barrier() 앞의 액세스보다 앞으로
+     재배치되지 못하게 합니다.  예를 들어, 인터럽트 핸들러 코드와 인터럽트 당한
+     코드 사이의 통신을 신중히 하기 위해 사용될 수 있습니다.
+
+ (*) 루프에서, 컴파일러가 루프 조건에 사용된 변수를 매 이터레이션마다
+     메모리에서 로드하지 않아도 되도록 최적화 하는걸 방지합니다.
+
+READ_ONCE() 와 WRITE_ONCE() 함수는 싱글 쓰레드 코드에서는 문제 없지만 동시성이
+있는 코드에서는 문제가 될 수 있는 모든 최적화를 막습니다.  이런 류의 최적화에
+대한 예를 몇가지 들어보면 다음과 같습니다:
+
+ (*) 컴파일러는 같은 변수에 대한 로드와 스토어를 재배치 할 수 있고, 어떤
+     경우에는 CPU가 같은 변수로부터의 로드들을 재배치할 수도 있습니다.  이는
+     다음의 코드가:
+
+	a[0] = x;
+	a[1] = x;
+
+     x 의 예전 값이 a[1] 에, 새 값이 a[0] 에 있게 할 수 있다는 뜻입니다.
+     컴파일러와 CPU가 이런 일을 못하게 하려면 다음과 같이 해야 합니다:
+
+	a[0] = READ_ONCE(x);
+	a[1] = READ_ONCE(x);
+
+     즉, READ_ONCE() 와 WRITE_ONCE() 는 여러 CPU 에서 하나의 변수에 가해지는
+     액세스들에 캐시 일관성을 제공합니다.
+
+ (*) 컴파일러는 같은 변수에 대한 연속적인 로드들을 병합할 수 있습니다.  그런
+     병합 작업으로 컴파일러는 다음의 코드를:
+
+	while (tmp = a)
+		do_something_with(tmp);
+
+     다음과 같이, 싱글 쓰레드 코드에서는 말이 되지만 개발자의 의도와 전혀 맞지
+     않는 방향으로 "최적화" 할 수 있습니다:
+
+	if (tmp = a)
+		for (;;)
+			do_something_with(tmp);
+
+     컴파일러가 이런 짓을 하지 못하게 하려면 READ_ONCE() 를 사용하세요:
+
+	while (tmp = READ_ONCE(a))
+		do_something_with(tmp);
+
+ (*) 예컨대 레지스터 사용량이 많아 컴파일러가 모든 데이터를 레지스터에 담을 수
+     없는 경우, 컴파일러는 변수를 다시 로드할 수 있습니다.  따라서 컴파일러는
+     앞의 예에서 변수 'tmp' 사용을 최적화로 없애버릴 수 있습니다:
+
+	while (tmp = a)
+		do_something_with(tmp);
+
+     이 코드는 다음과 같이 싱글 쓰레드에서는 완벽하지만 동시성이 존재하는
+     경우엔 치명적인 코드로 바뀔 수 있습니다:
+
+	while (a)
+		do_something_with(a);
+
+     예를 들어, 최적화된 이 코드는 변수 a 가 다른 CPU 에 의해 "while" 문과
+     do_something_with() 호출 사이에 바뀌어 do_something_with() 에 0을 넘길
+     수도 있습니다.
+
+     이번에도, 컴파일러가 그런 짓을 하는걸 막기 위해 READ_ONCE() 를 사용하세요:
+
+	while (tmp = READ_ONCE(a))
+		do_something_with(tmp);
+
+     레지스터가 부족한 상황을 겪는 경우, 컴파일러는 tmp 를 스택에 저장해둘 수도
+     있습니다.  컴파일러가 변수를 다시 읽어들이는건 이렇게 저장해두고 후에 다시
+     읽어들이는데 드는 오버헤드 때문입니다.  그렇게 하는게 싱글 쓰레드
+     코드에서는 안전하므로, 안전하지 않은 경우에는 컴파일러에게 직접 알려줘야
+     합니다.
+
+ (*) 컴파일러는 그 값이 무엇일지 알고 있다면 로드를 아예 안할 수도 있습니다.
+     예를 들어, 다음의 코드는 변수 'a' 의 값이 항상 0임을 증명할 수 있다면:
+
+	while (tmp = a)
+		do_something_with(tmp);
+
+     이렇게 최적화 되어버릴 수 있습니다:
+
+	do { } while (0);
+
+     이 변환은 싱글 쓰레드 코드에서는 도움이 되는데 로드와 브랜치를 제거했기
+     때문입니다.  문제는 컴파일러가 'a' 의 값을 업데이트 하는건 현재의 CPU 하나
+     뿐이라는 가정 위에서 증명을 했다는데 있습니다.  만약 변수 'a' 가 공유되어
+     있다면, 컴파일러의 증명은 틀린 것이 될겁니다.  컴파일러는 그 자신이
+     생각하는 것만큼 많은 것을 알고 있지 못함을 컴파일러에게 알리기 위해
+     READ_ONCE() 를 사용하세요:
+
+	while (tmp = READ_ONCE(a))
+		do_something_with(tmp);
+
+     하지만 컴파일러는 READ_ONCE() 뒤에 나오는 값에 대해서도 눈길을 두고 있음을
+     기억하세요.  예를 들어, 다음의 코드에서 MAX 는 전처리기 매크로로, 1의 값을
+     갖는다고 해봅시다:
+
+	while ((tmp = READ_ONCE(a)) % MAX)
+		do_something_with(tmp);
+
+     이렇게 되면 컴파일러는 MAX 를 가지고 수행되는 "%" 오퍼레이터의 결과가 항상
+     0이라는 것을 알게 되고, 컴파일러가 코드를 실질적으로는 존재하지 않는
+     것처럼 최적화 하는 것이 허용되어 버립니다.  ('a' 변수의 로드는 여전히
+     행해질 겁니다.)
+
+ (*) 비슷하게, 컴파일러는 변수가 저장하려 하는 값을 이미 가지고 있다는 것을
+     알면 스토어 자체를 제거할 수 있습니다.  이번에도, 컴파일러는 현재의 CPU
+     만이 그 변수에 값을 쓰는 오로지 하나의 존재라고 생각하여 공유된 변수에
+     대해서는 잘못된 일을 하게 됩니다.  예를 들어, 다음과 같은 경우가 있을 수
+     있습니다:
+
+	a = 0;
+	... 변수 a 에 스토어를 하지 않는 코드 ...
+	a = 0;
+
+     컴파일러는 변수 'a' 의 값은 이미 0이라는 것을 알고, 따라서 두번째 스토어를
+     삭제할 겁니다.  만약 다른 CPU 가 그 사이 변수 'a' 에 다른 값을 썼다면
+     황당한 결과가 나올 겁니다.
+
+     컴파일러가 그런 잘못된 추측을 하지 않도록 WRITE_ONCE() 를 사용하세요:
+
+	WRITE_ONCE(a, 0);
+	... 변수 a 에 스토어를 하지 않는 코드 ...
+	WRITE_ONCE(a, 0);
+
+ (*) 컴파일러는 하지 말라고 하지 않으면 메모리 액세스들을 재배치 할 수
+     있습니다.  예를 들어, 다음의 프로세스 레벨 코드와 인터럽트 핸들러 사이의
+     상호작용을 생각해 봅시다:
+
+	void process_level(void)
+	{
+		msg = get_message();
+		flag = true;
+	}
+
+	void interrupt_handler(void)
+	{
+		if (flag)
+			process_message(msg);
+	}
+
+     이 코드에는 컴파일러가 process_level() 을 다음과 같이 변환하는 것을 막을
+     수단이 없고, 이런 변환은 싱글쓰레드에서라면 실제로 훌륭한 선택일 수
+     있습니다:
+
+	void process_level(void)
+	{
+		flag = true;
+		msg = get_message();
+	}
+
+     이 두개의 문장 사이에 인터럽트가 발생한다면, interrupt_handler() 는 의미를
+     알 수 없는 메세지를 받을 수도 있습니다.  이걸 막기 위해 다음과 같이
+     WRITE_ONCE() 를 사용하세요:
+
+	void process_level(void)
+	{
+		WRITE_ONCE(msg, get_message());
+		WRITE_ONCE(flag, true);
+	}
+
+	void interrupt_handler(void)
+	{
+		if (READ_ONCE(flag))
+			process_message(READ_ONCE(msg));
+	}
+
+     interrupt_handler() 안에서도 중첩된 인터럽트나 NMI 와 같이 인터럽트 핸들러
+     역시 'flag' 와 'msg' 에 접근하는 또다른 무언가에 인터럽트 될 수 있다면
+     READ_ONCE() 와 WRITE_ONCE() 를 사용해야 함을 기억해 두세요.  만약 그런
+     가능성이 없다면, interrupt_handler() 안에서는 문서화 목적이 아니라면
+     READ_ONCE() 와 WRITE_ONCE() 는 필요치 않습니다.  (근래의 리눅스 커널에서
+     중첩된 인터럽트는 보통 잘 일어나지 않음도 기억해 두세요, 실제로, 어떤
+     인터럽트 핸들러가 인터럽트가 활성화된 채로 리턴하면 WARN_ONCE() 가
+     실행됩니다.)
+
+     컴파일러는 READ_ONCE() 와 WRITE_ONCE() 뒤의 READ_ONCE() 나 WRITE_ONCE(),
+     barrier(), 또는 비슷한 것들을 담고 있지 않은 코드를 움직일 수 있을 것으로
+     가정되어야 합니다.
+
+     이 효과는 barrier() 를 통해서도 만들 수 있지만, READ_ONCE() 와
+     WRITE_ONCE() 가 좀 더 안목 높은 선택입니다: READ_ONCE() 와 WRITE_ONCE()는
+     컴파일러에 주어진 메모리 영역에 대해서만 최적화 가능성을 포기하도록
+     하지만, barrier() 는 컴파일러가 지금까지 기계의 레지스터에 캐시해 놓은
+     모든 메모리 영역의 값을 버려야 하게 하기 때문입니다.  물론, 컴파일러는
+     READ_ONCE() 와 WRITE_ONCE() 가 일어난 순서도 지켜줍니다, CPU 는 당연히
+     그 순서를 지킬 의무가 없지만요.
+
+ (*) 컴파일러는 다음의 예에서와 같이 변수에의 스토어를 날조해낼 수도 있습니다:
+
+	if (a)
+		b = a;
+	else
+		b = 42;
+
+     컴파일러는 아래와 같은 최적화로 브랜치를 줄일 겁니다:
+
+	b = 42;
+	if (a)
+		b = a;
+
+     싱글 쓰레드 코드에서 이 최적화는 안전할 뿐 아니라 브랜치 갯수를
+     줄여줍니다.  하지만 안타깝게도, 동시성이 있는 코드에서는 이 최적화는 다른
+     CPU 가 'b' 를 로드할 때, -- 'a' 가 0이 아닌데도 -- 가짜인 값, 42를 보게
+     되는 경우를 가능하게 합니다.  이걸 방지하기 위해 WRITE_ONCE() 를
+     사용하세요:
+
+	if (a)
+		WRITE_ONCE(b, a);
+	else
+		WRITE_ONCE(b, 42);
+
+     컴파일러는 로드를 만들어낼 수도 있습니다.  일반적으로는 문제를 일으키지
+     않지만, 캐시 라인 바운싱을 일으켜 성능과 확장성을 떨어뜨릴 수 있습니다.
+     날조된 로드를 막기 위해선 READ_ONCE() 를 사용하세요.
+
+ (*) 정렬된 메모리 주소에 위치한, 한번의 메모리 참조 인스트럭션으로 액세스
+     가능한 크기의 데이터는 하나의 큰 액세스가 여러개의 작은 액세스들로
+     대체되는 "로드 티어링(load tearing)" 과 "스토어 티어링(store tearing)" 을
+     방지합니다.  예를 들어, 주어진 아키텍쳐가 7-bit imeediate field 를 갖는
+     16-bit 스토어 인스트럭션을 제공한다면, 컴파일러는 다음의 32-bit 스토어를
+     구현하는데에 두개의 16-bit store-immediate 명령을 사용하려 할겁니다:
+
+	p = 0x00010002;
+
+     스토어 할 상수를 만들고 그 값을 스토어 하기 위해 두개가 넘는 인스트럭션을
+     사용하게 되는, 이런 종류의 최적화를 GCC 는 실제로 함을 부디 알아 두십시오.
+     이 최적화는 싱글 쓰레드 코드에서는 성공적인 최적화 입니다.  실제로, 근래에
+     발생한 (그리고 고쳐진) 버그는 GCC 가 volatile 스토어에 비정상적으로 이
+     최적화를 사용하게 했습니다.  그런 버그가 없다면, 다음의 예에서
+     WRITE_ONCE() 의 사용은 스토어 티어링을 방지합니다:
+
+	WRITE_ONCE(p, 0x00010002);
+
+     Packed 구조체의 사용 역시 다음의 예처럼  로드 / 스토어 티어링을 유발할 수
+     있습니다:
+
+	struct __attribute__((__packed__)) foo {
+		short a;
+		int b;
+		short c;
+	};
+	struct foo foo1, foo2;
+	...
+
+	foo2.a = foo1.a;
+	foo2.b = foo1.b;
+	foo2.c = foo1.c;
+
+     READ_ONCE() 나 WRITE_ONCE() 도 없고 volatile 마킹도 없기 때문에,
+     컴파일러는 이 세개의 대입문을 두개의 32-bit 로드와 두개의 32-bit 스토어로
+     변환할 수 있습니다.  이는 'foo1.b' 의 값의 로드 티어링과 'foo2.b' 의
+     스토어 티어링을 초래할 겁니다.  이 예에서도 READ_ONCE() 와 WRITE_ONCE()
+     가 티어링을 막을 수 있습니다:
+
+	foo2.a = foo1.a;
+	WRITE_ONCE(foo2.b, READ_ONCE(foo1.b));
+	foo2.c = foo1.c;
+
+그렇지만, volatile 로 마크된 변수에 대해서는 READ_ONCE() 와 WRITE_ONCE() 가
+필요치 않습니다.  예를 들어, 'jiffies' 는 volatile 로 마크되어 있기 때문에,
+READ_ONCE(jiffies) 라고 할 필요가 없습니다.  READ_ONCE() 와 WRITE_ONCE() 가
+실은 volatile 캐스팅으로 구현되어 있어서 인자가 이미 volatile 로 마크되어
+있다면 또다른 효과를 내지는 않기 때문입니다.
+
+이 컴파일러 배리어들은 CPU 에는 직접적 효과를 전혀 만들지 않기 때문에, 결국은
+재배치가 일어날 수도 있음을 부디 기억해 두십시오.
+
+
+CPU 메모리 배리어
+-----------------
+
+리눅스 커널은 다음의 여덟개 기본 CPU 메모리 배리어를 가지고 있습니다:
+
+	TYPE		MANDATORY		SMP CONDITIONAL
+	===============	=======================	===========================
+	범용		mb()			smp_mb()
+	쓰기		wmb()			smp_wmb()
+	읽기		rmb()			smp_rmb()
+	데이터 의존성	read_barrier_depends()	smp_read_barrier_depends()
+
+
+데이터 의존성 배리어를 제외한 모든 메모리 배리어는 컴파일러 배리어를
+포함합니다.  데이터 의존성은 컴파일러에의 추가적인 순서 보장을 포함하지
+않습니다.
+
+방백: 데이터 의존성이 있는 경우, 컴파일러는 해당 로드를 올바른 순서로 일으킬
+것으로 (예: `a[b]` 는 a[b] 를 로드 하기 전에 b 의 값을 먼저 로드한다)
+기대되지만, C 언어 사양에는 컴파일러가 b 의 값을 추측 (예: 1 과 같음) 해서
+b  로드 전에 a 로드를 하는 코드 (예: tmp = a[1]; if (b != 1) tmp = a[b]; ) 를
+만들지 않아야 한다는 내용 같은 건 없습니다.  또한 컴파일러는 a[b] 를 로드한
+후에 b 를 또다시 로드할 수도 있어서, a[b] 보다 최신 버전의 b 값을 가질 수도
+있습니다.  이런 문제들의 해결책에 대한 의견 일치는 아직 없습니다만, 일단
+READ_ONCE() 매크로부터 보기 시작하는게 좋은 시작이 될겁니다.
+
+SMP 메모리 배리어들은 유니프로세서로 컴파일된 시스템에서는 컴파일러 배리어로
+바뀌는데, 하나의 CPU 는 스스로 일관성을 유지하고, 겹치는 액세스들 역시 올바른
+순서로 행해질 것으로 생각되기 때문입니다.  하지만, 아래의 "Virtual Machine
+Guests" 서브섹션을 참고하십시오.
+
+[!] SMP 시스템에서 공유메모리로의 접근들을 순서 세워야 할 때, SMP 메모리
+배리어는 _반드시_ 사용되어야 함을 기억하세요, 그대신 락을 사용하는 것으로도
+충분하긴 하지만 말이죠.
+
+Mandatory 배리어들은 SMP 시스템에서도 UP 시스템에서도 SMP 효과만 통제하기에는
+불필요한 오버헤드를 갖기 때문에 SMP 효과만 통제하면 되는 곳에는 사용되지 않아야
+합니다.  하지만, 느슨한 순서 규칙의 메모리 I/O 윈도우를 통한 MMIO 의 효과를
+통제할 때에는 mandatory 배리어들이 사용될 수 있습니다.  이 배리어들은
+컴파일러와 CPU 모두 재배치를 못하도록 함으로써 메모리 오퍼레이션들이 디바이스에
+보여지는 순서에도 영향을 주기 때문에, SMP 가 아닌 시스템이라 할지라도 필요할 수
+있습니다.
+
+
+일부 고급 배리어 함수들도 있습니다:
+
+ (*) smp_store_mb(var, value)
+
+     이 함수는 특정 변수에 특정 값을 대입하고 범용 메모리 배리어를 칩니다.
+     UP 컴파일에서는 컴파일러 배리어보다 더한 것을 친다고는 보장되지 않습니다.
+
+
+ (*) smp_mb__before_atomic();
+ (*) smp_mb__after_atomic();
+
+     이것들은 값을 리턴하지 않는 (더하기, 빼기, 증가, 감소와 같은) 어토믹
+     함수들을 위한, 특히 그것들이 레퍼런스 카운팅에 사용될 때를 위한
+     함수들입니다.  이 함수들은 메모리 배리어를 내포하고 있지는 않습니다.
+
+     이것들은 값을 리턴하지 않으며 어토믹한 (set_bit 과 clear_bit 같은) 비트
+     연산에도 사용될 수 있습니다.
+
+     한 예로, 객체 하나를 무효한 것으로 표시하고 그 객체의 레퍼런스 카운트를
+     감소시키는 다음 코드를 보세요:
+
+	obj->dead = 1;
+	smp_mb__before_atomic();
+	atomic_dec(&obj->ref_count);
+
+     이 코드는 객체의 업데이트된 death 마크가 레퍼런스 카운터 감소 동작
+     *전에* 보일 것을 보장합니다.
+
+     더 많은 정보를 위해선 Documentation/atomic_ops.txt 문서를 참고하세요.
+     어디서 이것들을 사용해야 할지 궁금하다면 "어토믹 오퍼레이션" 서브섹션을
+     참고하세요.
+
+
+ (*) lockless_dereference();
+
+     이 함수는 smp_read_barrier_depends() 데이터 의존성 배리어를 사용하는
+     포인터 읽어오기 래퍼(wrapper) 함수로 생각될 수 있습니다.
+
+     객체의 라이프타임이 RCU 외의 메커니즘으로 관리된다는 점을 제외하면
+     rcu_dereference() 와도 유사한데, 예를 들면 객체가 시스템이 꺼질 때에만
+     제거되는 경우 등입니다.  또한, lockless_dereference() 은 RCU 와 함께
+     사용될수도, RCU 없이 사용될 수도 있는 일부 데이터 구조에 사용되고
+     있습니다.
+
+
+ (*) dma_wmb();
+ (*) dma_rmb();
+
+     이것들은 CPU 와 DMA 가능한 디바이스에서 모두 액세스 가능한 공유 메모리의
+     읽기, 쓰기 작업들의 순서를 보장하기 위해 consistent memory 에서 사용하기
+     위한 것들입니다.
+
+     예를 들어, 디바이스와 메모리를 공유하며, 디스크립터 상태 값을 사용해
+     디스크립터가 디바이스에 속해 있는지 아니면 CPU 에 속해 있는지 표시하고,
+     공지용 초인종(doorbell) 을 사용해 업데이트된 디스크립터가 디바이스에 사용
+     가능해졌음을 공지하는 디바이스 드라이버를 생각해 봅시다:
+
+	if (desc->status != DEVICE_OWN) {
+		/* 디스크립터를 소유하기 전에는 데이터를 읽지 않음 */
+		dma_rmb();
+
+		/* 데이터를 읽고 씀 */
+		read_data = desc->data;
+		desc->data = write_data;
+
+		/* 상태 업데이트 전 수정사항을 반영 */
+		dma_wmb();
+
+		/* 소유권을 수정 */
+		desc->status = DEVICE_OWN;
+
+		/* MMIO 를 통해 디바이스에 공지를 하기 전에 메모리를 동기화 */
+		wmb();
+
+		/* 업데이트된 디스크립터의 디바이스에 공지 */
+		writel(DESC_NOTIFY, doorbell);
+	}
+
+     dma_rmb() 는 디스크립터로부터 데이터를 읽어오기 전에 디바이스가 소유권을
+     내놓았음을 보장하게 하고, dma_wmb() 는 디바이스가 자신이 소유권을 다시
+     가졌음을 보기 전에 디스크립터에 데이터가 쓰였음을 보장합니다.  wmb() 는
+     캐시 일관성이 없는 (cache incoherent) MMIO 영역에 쓰기를 시도하기 전에
+     캐시 일관성이 있는 메모리 (cache coherent memory) 쓰기가 완료되었음을
+     보장해주기 위해 필요합니다.
+
+     consistent memory 에 대한 자세한 내용을 위해선 Documentation/DMA-API.txt
+     문서를 참고하세요.
+
+
+MMIO 쓰기 배리어
+----------------
+
+리눅스 커널은 또한 memory-mapped I/O 쓰기를 위한 특별한 배리어도 가지고
+있습니다:
+
+	mmiowb();
+
+이것은 mandatory 쓰기 배리어의 변종으로, 완화된 순서 규칙의 I/O 영역에으로의
+쓰기가 부분적으로 순서를 맞추도록 해줍니다.  이 함수는 CPU->하드웨어 사이를
+넘어서 실제 하드웨어에까지 일부 수준의 영향을 끼칩니다.
+
+더 많은 정보를 위해선 "Acquire vs I/O 액세스" 서브섹션을 참고하세요.
+
+
+=========================
+암묵적 커널 메모리 배리어
+=========================
+
+리눅스 커널의 일부 함수들은 메모리 배리어를 내장하고 있는데, 락(lock)과
+스케쥴링 관련 함수들이 대부분입니다.
+
+여기선 _최소한의_ 보장을 설명합니다; 특정 아키텍쳐에서는 이 설명보다 더 많은
+보장을 제공할 수도 있습니다만 해당 아키텍쳐에 종속적인 코드 외의 부분에서는
+그런 보장을 기대해선 안될겁니다.
+
+
+락 ACQUISITION 함수
+-------------------
+
+리눅스 커널은 다양한 락 구성체를 가지고 있습니다:
+
+ (*) 스핀 락
+ (*) R/W 스핀 락
+ (*) 뮤텍스
+ (*) 세마포어
+ (*) R/W 세마포어
+
+각 구성체마다 모든 경우에 "ACQUIRE" 오퍼레이션과 "RELEASE" 오퍼레이션의 변종이
+존재합니다.  이 오퍼레이션들은 모두 적절한 배리어를 내포하고 있습니다:
+
+ (1) ACQUIRE 오퍼레이션의 영향:
+
+     ACQUIRE 뒤에서 요청된 메모리 오퍼레이션은 ACQUIRE 오퍼레이션이 완료된
+     뒤에 완료됩니다.
+
+     ACQUIRE 앞에서 요청된 메모리 오퍼레이션은 ACQUIRE 오퍼레이션이 완료된 후에
+     완료될 수 있습니다.  smp_mb__before_spinlock() 뒤에 ACQUIRE 가 실행되는
+     코드 블록은 블록 앞의 스토어를 블록 뒤의 로드와 스토어에 대해 순서
+     맞춥니다.  이건 smp_mb() 보다 완화된 것임을 기억하세요!  많은 아키텍쳐에서
+     smp_mb__before_spinlock() 은 사실 아무일도 하지 않습니다.
+
+ (2) RELEASE 오퍼레이션의 영향:
+
+     RELEASE 앞에서 요청된 메모리 오퍼레이션은 RELEASE 오퍼레이션이 완료되기
+     전에 완료됩니다.
+
+     RELEASE 뒤에서 요청된 메모리 오퍼레이션은 RELEASE 오퍼레이션 완료 전에
+     완료될 수 있습니다.
+
+ (3) ACQUIRE vs ACQUIRE 영향:
+
+     어떤 ACQUIRE 오퍼레이션보다 앞에서 요청된 모든 ACQUIRE 오퍼레이션은 그
+     ACQUIRE 오퍼레이션 전에 완료됩니다.
+
+ (4) ACQUIRE vs RELEASE implication:
+
+     어떤 RELEASE 오퍼레이션보다 앞서 요청된 ACQUIRE 오퍼레이션은 그 RELEASE
+     오퍼레이션보다 먼저 완료됩니다.
+
+ (5) 실패한 조건적 ACQUIRE 영향:
+
+     ACQUIRE 오퍼레이션의 일부 락(lock) 변종은 락이 곧바로 획득하기에는
+     불가능한 상태이거나 락이 획득 가능해지도록 기다리는 도중 시그널을 받거나
+     해서 실패할 수 있습니다.  실패한 락은 어떤 배리어도 내포하지 않습니다.
+
+[!] 참고: 락 ACQUIRE 와 RELEASE 가 단방향 배리어여서 나타나는 현상 중 하나는
+크리티컬 섹션 바깥의 인스트럭션의 영향이 크리티컬 섹션 내부로도 들어올 수
+있다는 것입니다.
+
+RELEASE 후에 요청되는 ACQUIRE 는 전체 메모리 배리어라 여겨지면 안되는데,
+ACQUIRE 앞의 액세스가 ACQUIRE 후에 수행될 수 있고, RELEASE 후의 액세스가
+RELEASE 전에 수행될 수도 있으며, 그 두개의 액세스가 서로를 지나칠 수도 있기
+때문입니다:
+
+	*A = a;
+	ACQUIRE M
+	RELEASE M
+	*B = b;
+
+는 다음과 같이 될 수도 있습니다:
+
+	ACQUIRE M, STORE *B, STORE *A, RELEASE M
+
+ACQUIRE 와 RELEASE 가 락 획득과 해제라면, 그리고 락의 ACQUIRE 와 RELEASE 가
+같은 락 변수에 대한 것이라면, 해당 락을 쥐고 있지 않은 다른 CPU 의 시야에는
+이와 같은 재배치가 일어나는 것으로 보일 수 있습니다.  요약하자면, ACQUIRE 에
+이어 RELEASE 오퍼레이션을 순차적으로 실행하는 행위가 전체 메모리 배리어로
+생각되어선 -안됩니다-.
+
+비슷하게, 앞의 반대 케이스인 RELEASE 와 ACQUIRE 두개 오퍼레이션의 순차적 실행
+역시 전체 메모리 배리어를 내포하지 않습니다.  따라서, RELEASE, ACQUIRE 로
+규정되는 크리티컬 섹션의 CPU 수행은 RELEASE 와 ACQUIRE 를 가로지를 수 있으므로,
+다음과 같은 코드는:
+
+	*A = a;
+	RELEASE M
+	ACQUIRE N
+	*B = b;
+
+다음과 같이 수행될 수 있습니다:
+
+	ACQUIRE N, STORE *B, STORE *A, RELEASE M
+
+이런 재배치는 데드락을 일으킬 수도 있을 것처럼 보일 수 있습니다.  하지만, 그런
+데드락의 조짐이 있다면 RELEASE 는 단순히 완료될 것이므로 데드락은 존재할 수
+없습니다.
+
+	이게 어떻게 올바른 동작을 할 수 있을까요?
+
+	우리가 이야기 하고 있는건 재배치를 하는 CPU 에 대한 이야기이지,
+	컴파일러에 대한 것이 아니란 점이 핵심입니다.  컴파일러 (또는, 개발자)
+	가 오퍼레이션들을 이렇게 재배치하면, 데드락이 일어날 수 -있습-니다.
+
+	하지만 CPU 가 오퍼레이션들을 재배치 했다는걸 생각해 보세요.  이 예에서,
+	어셈블리 코드 상으로는 언락이 락을 앞서게 되어 있습니다.  CPU 가 이를
+	재배치해서 뒤의 락 오퍼레이션을 먼저 실행하게 됩니다.  만약 데드락이
+	존재한다면, 이 락 오퍼레이션은 그저 스핀을 하며 계속해서 락을
+	시도합니다 (또는, 한참 후에겠지만, 잠듭니다).  CPU 는 언젠가는
+	(어셈블리 코드에서는 락을 앞서는) 언락 오퍼레이션을 실행하는데, 이 언락
+	오퍼레이션이 잠재적 데드락을 해결하고, 락 오퍼레이션도 뒤이어 성공하게
+	됩니다.
+
+	하지만 만약 락이 잠을 자는 타입이었다면요?  그런 경우에 코드는
+	스케쥴러로 들어가려 할 거고, 여기서 결국은 메모리 배리어를 만나게
+	되는데, 이 메모리 배리어는 앞의 언락 오퍼레이션이 완료되도록 만들고,
+	데드락은 이번에도 해결됩니다.  잠을 자는 행위와 언락 사이의 경주 상황
+	(race) 도 있을 수 있겠습니다만, 락 관련 기능들은 그런 경주 상황을 모든
+	경우에 제대로 해결할 수 있어야 합니다.
+
+락과 세마포어는 UP 컴파일된 시스템에서의 순서에 대해 보장을 하지 않기 때문에,
+그런 상황에서 인터럽트 비활성화 오퍼레이션과 함께가 아니라면 어떤 일에도 - 특히
+I/O 액세스와 관련해서는 - 제대로 사용될 수 없을 겁니다.
+
+"CPU 간 ACQUIRING 배리어 효과" 섹션도 참고하시기 바랍니다.
+
+
+예를 들어, 다음과 같은 코드를 생각해 봅시다:
+
+	*A = a;
+	*B = b;
+	ACQUIRE
+	*C = c;
+	*D = d;
+	RELEASE
+	*E = e;
+	*F = f;
+
+여기선 다음의 이벤트 시퀀스가 생길 수 있습니다:
+
+	ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
+
+	[+] {*F,*A} 는 조합된 액세스를 의미합니다.
+
+하지만 다음과 같은 건 불가능하죠:
+
+	{*F,*A}, *B,	ACQUIRE, *C, *D,	RELEASE, *E
+	*A, *B, *C,	ACQUIRE, *D,		RELEASE, *E, *F
+	*A, *B,		ACQUIRE, *C,		RELEASE, *D, *E, *F
+	*B,		ACQUIRE, *C, *D,	RELEASE, {*F,*A}, *E
+
+
+
+인터럽트 비활성화 함수
+----------------------
+
+인터럽트를 비활성화 하는 함수 (ACQUIRE 와 동일) 와 인터럽트를 활성화 하는 함수
+(RELEASE 와 동일) 는 컴파일러 배리어처럼만 동작합니다.  따라서, 별도의 메모리
+배리어나 I/O 배리어가 필요한 상황이라면 그 배리어들은 인터럽트 비활성화 함수
+외의 방법으로 제공되어야만 합니다.
+
+
+슬립과 웨이크업 함수
+--------------------
+
+글로벌 데이터에 표시된 이벤트에 의해 프로세스를 잠에 빠트리는 것과 깨우는 것은
+해당 이벤트를 기다리는 태스크의 태스크 상태와 그 이벤트를 알리기 위해 사용되는
+글로벌 데이터, 두 데이터간의 상호작용으로 볼 수 있습니다.  이것이 옳은 순서대로
+일어남을 분명히 하기 위해, 프로세스를 잠에 들게 하는 기능과 깨우는 기능은
+몇가지 배리어를 내포합니다.
+
+먼저, 잠을 재우는 쪽은 일반적으로 다음과 같은 이벤트 시퀀스를 따릅니다:
+
+	for (;;) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		if (event_indicated)
+			break;
+		schedule();
+	}
+
+set_current_state() 에 의해, 태스크 상태가 바뀐 후 범용 메모리 배리어가
+자동으로 삽입됩니다:
+
+	CPU 1
+	===============================
+	set_current_state();
+	  smp_store_mb();
+	    STORE current->state
+	    <범용 배리어>
+	LOAD event_indicated
+
+set_current_state() 는 다음의 것들로 감싸질 수도 있습니다:
+
+	prepare_to_wait();
+	prepare_to_wait_exclusive();
+
+이것들 역시 상태를 설정한 후 범용 메모리 배리어를 삽입합니다.
+앞의 전체 시퀀스는 다음과 같은 함수들로 한번에 수행 가능한데, 이것들은 모두
+올바른 장소에 메모리 배리어를 삽입합니다:
+
+	wait_event();
+	wait_event_interruptible();
+	wait_event_interruptible_exclusive();
+	wait_event_interruptible_timeout();
+	wait_event_killable();
+	wait_event_timeout();
+	wait_on_bit();
+	wait_on_bit_lock();
+
+
+두번째로, 깨우기를 수행하는 코드는 일반적으로 다음과 같을 겁니다:
+
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+또는:
+
+	event_indicated = 1;
+	wake_up_process(event_daemon);
+
+wake_up() 류에 의해 쓰기 메모리 배리어가 내포됩니다.  만약 그것들이 뭔가를
+깨운다면요.  이 배리어는 태스크 상태가 지워지기 전에 수행되므로, 이벤트를
+알리기 위한 STORE 와 태스크 상태를 TASK_RUNNING 으로 설정하는 STORE 사이에
+위치하게 됩니다.
+
+	CPU 1				CPU 2
+	===============================	===============================
+	set_current_state();		STORE event_indicated
+	  smp_store_mb();		wake_up();
+	    STORE current->state	  <쓰기 배리어>
+	    <범용 배리어>		  STORE current->state
+	LOAD event_indicated
+
+한번더 말합니다만, 이 쓰기 메모리 배리어는 이 코드가 정말로 뭔가를 깨울 때에만
+실행됩니다.  이걸 설명하기 위해, X 와 Y 는 모두 0 으로 초기화 되어 있다는 가정
+하에 아래의 이벤트 시퀀스를 생각해 봅시다:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	X = 1;				STORE event_indicated
+	smp_mb();			wake_up();
+	Y = 1;				wait_event(wq, Y == 1);
+	wake_up();			  load from Y sees 1, no memory barrier
+					load from X might see 0
+
+위 예제에서의 경우와 달리 깨우기가 정말로 행해졌다면, CPU 2 의 X 로드는 1 을
+본다고 보장될 수 있을 겁니다.
+
+사용 가능한 깨우기류 함수들로 다음과 같은 것들이 있습니다:
+
+	complete();
+	wake_up();
+	wake_up_all();
+	wake_up_bit();
+	wake_up_interruptible();
+	wake_up_interruptible_all();
+	wake_up_interruptible_nr();
+	wake_up_interruptible_poll();
+	wake_up_interruptible_sync();
+	wake_up_interruptible_sync_poll();
+	wake_up_locked();
+	wake_up_locked_poll();
+	wake_up_nr();
+	wake_up_poll();
+	wake_up_process();
+
+
+[!] 잠재우는 코드와 깨우는 코드에 내포되는 메모리 배리어들은 깨우기 전에
+이루어진 스토어를 잠재우는 코드가 set_current_state() 를 호출한 후에 행하는
+로드에 대해 순서를 맞추지 _않는다는_ 점을 기억하세요.  예를 들어, 잠재우는
+코드가 다음과 같고:
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (event_indicated)
+		break;
+	__set_current_state(TASK_RUNNING);
+	do_something(my_data);
+
+깨우는 코드는 다음과 같다면:
+
+	my_data = value;
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+event_indecated 에의 변경이 잠재우는 코드에게 my_data 에의 변경 후에 이루어진
+것으로 인지될 것이라는 보장이 없습니다.  이런 경우에는 양쪽 코드 모두 각각의
+데이터 액세스 사이에 메모리 배리어를 직접 쳐야 합니다.  따라서 앞의 재우는
+코드는 다음과 같이:
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (event_indicated) {
+		smp_rmb();
+		do_something(my_data);
+	}
+
+그리고 깨우는 코드는 다음과 같이 되어야 합니다:
+
+	my_data = value;
+	smp_wmb();
+	event_indicated = 1;
+	wake_up(&event_wait_queue);
+
+
+그외의 함수들
+-------------
+
+그외의 배리어를 내포하는 함수들은 다음과 같습니다:
+
+ (*) schedule() 과 그 유사한 것들이 완전한 메모리 배리어를 내포합니다.
+
+
+==============================
+CPU 간 ACQUIRING 배리어의 효과
+==============================
+
+SMP 시스템에서의 락 기능들은 더욱 강력한 형태의 배리어를 제공합니다: 이
+배리어는 동일한 락을 사용하는 다른 CPU 들의 메모리 액세스 순서에도 영향을
+끼칩니다.
+
+
+ACQUIRE VS 메모리 액세스
+------------------------
+
+다음의 예를 생각해 봅시다: 시스템은 두개의 스핀락 (M) 과 (Q), 그리고 세개의 CPU
+를 가지고 있습니다; 여기에 다음의 이벤트 시퀀스가 발생합니다:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	WRITE_ONCE(*A, a);		WRITE_ONCE(*E, e);
+	ACQUIRE M			ACQUIRE Q
+	WRITE_ONCE(*B, b);		WRITE_ONCE(*F, f);
+	WRITE_ONCE(*C, c);		WRITE_ONCE(*G, g);
+	RELEASE M			RELEASE Q
+	WRITE_ONCE(*D, d);		WRITE_ONCE(*H, h);
+
+*A 로의 액세스부터 *H 로의 액세스까지가 어떤 순서로 CPU 3 에게 보여질지에
+대해서는 각 CPU 에서의 락 사용에 의해 내포되어 있는 제약을 제외하고는 어떤
+보장도 존재하지 않습니다.  예를 들어, CPU 3 에게 다음과 같은 순서로 보여지는
+것이 가능합니다:
+
+	*E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
+
+하지만 다음과 같이 보이지는 않을 겁니다:
+
+	*B, *C or *D preceding ACQUIRE M
+	*A, *B or *C following RELEASE M
+	*F, *G or *H preceding ACQUIRE Q
+	*E, *F or *G following RELEASE Q
+
+
+
+ACQUIRE VS I/O 액세스
+----------------------
+
+특정한 (특히 NUMA 가 관련된) 환경 하에서 두개의 CPU 에서 동일한 스핀락으로
+보호되는 두개의 크리티컬 섹션 안의 I/O 액세스는 PCI 브릿지에 겹쳐진 I/O
+액세스로 보일 수 있는데, PCI 브릿지는 캐시 일관성 프로토콜과 합을 맞춰야 할
+의무가 없으므로, 필요한 읽기 메모리 배리어가 요청되지 않기 때문입니다.
+
+예를 들어서:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	spin_lock(Q)
+	writel(0, ADDR)
+	writel(1, DATA);
+	spin_unlock(Q);
+					spin_lock(Q);
+					writel(4, ADDR);
+					writel(5, DATA);
+					spin_unlock(Q);
+
+는 PCI 브릿지에 다음과 같이 보일 수 있습니다:
+
+	STORE *ADDR = 0, STORE *ADDR = 4, STORE *DATA = 1, STORE *DATA = 5
+
+이렇게 되면 하드웨어의 오동작을 일으킬 수 있습니다.
+
+
+이런 경우엔 잡아둔 스핀락을 내려놓기 전에 mmiowb() 를 수행해야 하는데, 예를
+들면 다음과 같습니다:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	spin_lock(Q)
+	writel(0, ADDR)
+	writel(1, DATA);
+	mmiowb();
+	spin_unlock(Q);
+					spin_lock(Q);
+					writel(4, ADDR);
+					writel(5, DATA);
+					mmiowb();
+					spin_unlock(Q);
+
+이 코드는 CPU 1 에서 요청된 두개의 스토어가 PCI 브릿지에 CPU 2 에서 요청된
+스토어들보다 먼저 보여짐을 보장합니다.
+
+
+또한, 같은 디바이스에서 스토어를 이어 로드가 수행되면 이 로드는 로드가 수행되기
+전에 스토어가 완료되기를 강제하므로 mmiowb() 의 필요가 없어집니다:
+
+	CPU 1				CPU 2
+	===============================	===============================
+	spin_lock(Q)
+	writel(0, ADDR)
+	a = readl(DATA);
+	spin_unlock(Q);
+					spin_lock(Q);
+					writel(4, ADDR);
+					b = readl(DATA);
+					spin_unlock(Q);
+
+
+더 많은 정보를 위해선 Documenataion/DocBook/deviceiobook.tmpl 을 참고하세요.
+
+
+=========================
+메모리 배리어가 필요한 곳
+=========================
+
+설령 SMP 커널을 사용하더라도 싱글 쓰레드로 동작하는 코드는 올바르게 동작하는
+것으로 보여질 것이기 때문에, 평범한 시스템 운영중에 메모리 오퍼레이션 재배치는
+일반적으로 문제가 되지 않습니다.  하지만, 재배치가 문제가 _될 수 있는_ 네가지
+환경이 있습니다:
+
+ (*) 프로세서간 상호 작용.
+
+ (*) 어토믹 오퍼레이션.
+
+ (*) 디바이스 액세스.
+
+ (*) 인터럽트.
+
+
+프로세서간 상호 작용
+--------------------
+
+두개 이상의 프로세서를 가진 시스템이 있다면, 시스템의 두개 이상의 CPU 는 동시에
+같은 데이터에 대한 작업을 할 수 있습니다.  이는 동기화 문제를 일으킬 수 있고,
+이 문제를 해결하는 일반적 방법은 락을 사용하는 것입니다.  하지만, 락은 상당히
+비용이 비싸서 가능하면 락을 사용하지 않고 일을 처리하는 것이 낫습니다.  이런
+경우, 두 CPU 모두에 영향을 끼치는 오퍼레이션들은 오동작을 막기 위해 신중하게
+순서가 맞춰져야 합니다.
+
+예를 들어, R/W 세마포어의 느린 수행경로 (slow path) 를 생각해 봅시다.
+세마포어를 위해 대기를 하는 하나의 프로세스가 자신의 스택 중 일부를 이
+세마포어의 대기 프로세스 리스트에 링크한 채로 있습니다:
+
+	struct rw_semaphore {
+		...
+		spinlock_t lock;
+		struct list_head waiters;
+	};
+
+	struct rwsem_waiter {
+		struct list_head list;
+		struct task_struct *task;
+	};
+
+특정 대기 상태 프로세스를 깨우기 위해, up_read() 나 up_write() 함수는 다음과
+같은 일을 합니다:
+
+ (1) 다음 대기 상태 프로세스 레코드는 어디있는지 알기 위해 이 대기 상태
+     프로세스 레코드의 next 포인터를 읽습니다;
+
+ (2) 이 대기 상태 프로세스의 task 구조체로의 포인터를 읽습니다;
+
+ (3) 이 대기 상태 프로세스가 세마포어를 획득했음을 알리기 위해 task
+     포인터를 초기화 합니다;
+
+ (4) 해당 태스크에 대해 wake_up_process() 를 호출합니다; 그리고
+
+ (5) 해당 대기 상태 프로세스의 task 구조체를 잡고 있던 레퍼런스를 해제합니다.
+
+달리 말하자면, 다음 이벤트 시퀀스를 수행해야 합니다:
+
+	LOAD waiter->list.next;
+	LOAD waiter->task;
+	STORE waiter->task;
+	CALL wakeup
+	RELEASE task
+
+그리고 이 이벤트들이 다른 순서로 수행된다면, 오동작이 일어날 수 있습니다.
+
+한번 세마포어의 대기줄에 들어갔고 세마포어 락을 놓았다면, 해당 대기 프로세스는
+락을 다시는 잡지 않습니다; 대신 자신의 task 포인터가 초기화 되길 기다립니다.
+그 레코드는 대기 프로세스의 스택에 있기 때문에, 리스트의 next 포인터가 읽혀지기
+_전에_ task 포인터가 지워진다면, 다른 CPU 는 해당 대기 프로세스를 시작해 버리고
+up*() 함수가 next 포인터를 읽기 전에 대기 프로세스의 스택을 마구 건드릴 수
+있습니다.
+
+그렇게 되면 위의 이벤트 시퀀스에 어떤 일이 일어나는지 생각해 보죠:
+
+	CPU 1				CPU 2
+	===============================	===============================
+					down_xxx()
+					Queue waiter
+					Sleep
+	up_yyy()
+	LOAD waiter->task;
+	STORE waiter->task;
+					Woken up by other event
+	<preempt>
+					Resume processing
+					down_xxx() returns
+					call foo()
+					foo() clobbers *waiter
+	</preempt>
+	LOAD waiter->list.next;
+	--- OOPS ---
+
+이 문제는 세마포어 락의 사용으로 해결될 수도 있겠지만, 그렇게 되면 깨어난 후에
+down_xxx() 함수가 불필요하게 스핀락을 또다시 얻어야만 합니다.
+
+이 문제를 해결하는 방법은 범용 SMP 메모리 배리어를 추가하는 겁니다:
+
+	LOAD waiter->list.next;
+	LOAD waiter->task;
+	smp_mb();
+	STORE waiter->task;
+	CALL wakeup
+	RELEASE task
+
+이 경우에, 배리어는 시스템의 나머지 CPU 들에게 모든 배리어 앞의 메모리 액세스가
+배리어 뒤의 메모리 액세스보다 앞서 일어난 것으로 보이게 만듭니다.  배리어 앞의
+메모리 액세스들이 배리어 명령 자체가 완료되는 시점까지 완료된다고는 보장하지
+_않습니다_.
+
+(이게 문제가 되지 않을) 단일 프로세서 시스템에서 smp_mb() 는 실제로는 그저
+컴파일러가 CPU 안에서의 순서를 바꾸거나 하지 않고 주어진 순서대로 명령을
+내리도록 하는 컴파일러 배리어일 뿐입니다.  오직 하나의 CPU 만 있으니, CPU 의
+의존성 순서 로직이 그 외의 모든것을 알아서 처리할 겁니다.
+
+
+어토믹 오퍼레이션
+-----------------
+
+어토믹 오퍼레이션은 기술적으로 프로세서간 상호작용으로 분류되며 그 중 일부는
+전체 메모리 배리어를 내포하고 또 일부는 내포하지 않지만, 커널에서 상당히
+의존적으로 사용하는 기능 중 하나입니다.
+
+메모리의 어떤 상태를 수정하고 해당 상태에 대한 (예전의 또는 최신의) 정보를
+리턴하는 어토믹 오퍼레이션은 모두 SMP-조건적 범용 메모리 배리어(smp_mb())를
+실제 오퍼레이션의 앞과 뒤에 내포합니다.  이런 오퍼레이션은 다음의 것들을
+포함합니다:
+
+	xchg();
+	atomic_xchg();			atomic_long_xchg();
+	atomic_inc_return();		atomic_long_inc_return();
+	atomic_dec_return();		atomic_long_dec_return();
+	atomic_add_return();		atomic_long_add_return();
+	atomic_sub_return();		atomic_long_sub_return();
+	atomic_inc_and_test();		atomic_long_inc_and_test();
+	atomic_dec_and_test();		atomic_long_dec_and_test();
+	atomic_sub_and_test();		atomic_long_sub_and_test();
+	atomic_add_negative();		atomic_long_add_negative();
+	test_and_set_bit();
+	test_and_clear_bit();
+	test_and_change_bit();
+
+	/* exchange 조건이 성공할 때 */
+	cmpxchg();
+	atomic_cmpxchg();		atomic_long_cmpxchg();
+	atomic_add_unless();		atomic_long_add_unless();
+
+이것들은 메모리 배리어 효과가 필요한 ACQUIRE 부류와 RELEASE 부류 오퍼레이션들을
+구현할 때, 그리고 객체 해제를 위해 레퍼런스 카운터를 조정할 때, 암묵적 메모리
+배리어 효과가 필요한 곳 등에 사용됩니다.
+
+
+다음의 오퍼레이션들은 메모리 배리어를 내포하지 _않기_ 때문에 문제가 될 수
+있지만, RELEASE 부류의 오퍼레이션들과 같은 것들을 구현할 때 사용될 수도
+있습니다:
+
+	atomic_set();
+	set_bit();
+	clear_bit();
+	change_bit();
+
+이것들을 사용할 때에는 필요하다면 적절한 (예를 들면 smp_mb__before_atomic()
+같은) 메모리 배리어가 명시적으로 함께 사용되어야 합니다.
+
+
+아래의 것들도 메모리 배리어를 내포하지 _않기_ 때문에, 일부 환경에서는 (예를
+들면 smp_mb__before_atomic() 과 같은) 명시적인 메모리 배리어 사용이 필요합니다.
+
+	atomic_add();
+	atomic_sub();
+	atomic_inc();
+	atomic_dec();
+
+이것들이 통계 생성을 위해 사용된다면, 그리고 통계 데이터 사이에 관계가 존재하지
+않는다면 메모리 배리어는 필요치 않을 겁니다.
+
+객체의 수명을 관리하기 위해 레퍼런스 카운팅 목적으로 사용된다면, 레퍼런스
+카운터는 락으로 보호되는 섹션에서만 조정되거나 호출하는 쪽이 이미 충분한
+레퍼런스를 잡고 있을 것이기 때문에 메모리 배리어는 아마 필요 없을 겁니다.
+
+만약 어떤 락을 구성하기 위해 사용된다면, 락 관련 동작은 일반적으로 작업을 특정
+순서대로 진행해야 하므로 메모리 배리어가 필요할 수 있습니다.
+
+기본적으로, 각 사용처에서는 메모리 배리어가 필요한지 아닌지 충분히 고려해야
+합니다.
+
+아래의 오퍼레이션들은 특별한 락 관련 동작들입니다:
+
+	test_and_set_bit_lock();
+	clear_bit_unlock();
+	__clear_bit_unlock();
+
+이것들은 ACQUIRE 류와 RELEASE 류의 오퍼레이션들을 구현합니다.  락 관련 도구를
+구현할 때에는 이것들을 좀 더 선호하는 편이 나은데, 이것들의 구현은 많은
+아키텍쳐에서 최적화 될 수 있기 때문입니다.
+
+[!] 이런 상황에 사용할 수 있는 특수한 메모리 배리어 도구들이 있습니다만, 일부
+CPU 에서는 사용되는 어토믹 인스트럭션 자체에 메모리 배리어가 내포되어 있어서
+어토믹 오퍼레이션과 메모리 배리어를 함께 사용하는 게 불필요한 일이 될 수
+있는데, 그런 경우에 이 특수 메모리 배리어 도구들은 no-op 이 되어 실질적으로
+아무일도 하지 않습니다.
+
+더 많은 내용을 위해선 Documentation/atomic_ops.txt 를 참고하세요.
+
+
+디바이스 액세스
+---------------
+
+많은 디바이스가 메모리 매핑 기법으로 제어될 수 있는데, 그렇게 제어되는
+디바이스는 CPU 에는 단지 특정 메모리 영역의 집합처럼 보이게 됩니다.  드라이버는
+그런 디바이스를 제어하기 위해 정확히 올바른 순서로 올바른 메모리 액세스를
+만들어야 합니다.
+
+하지만, 액세스들을 재배치 하거나 조합하거나 병합하는게 더 효율적이라 판단하는
+영리한 CPU 나 컴파일러들을 사용하면 드라이버 코드의 조심스럽게 순서 맞춰진
+액세스들이 디바이스에는 요청된 순서대로 도착하지 못하게 할 수 있는 - 디바이스가
+오동작을 하게 할 - 잠재적 문제가 생길 수 있습니다.
+
+리눅스 커널 내부에서, I/O 는 어떻게 액세스들을 적절히 순차적이게 만들 수 있는지
+알고 있는, - inb() 나 writel() 과 같은 - 적절한 액세스 루틴을 통해 이루어져야만
+합니다.  이것들은 대부분의 경우에는 명시적 메모리 배리어 와 함께 사용될 필요가
+없습니다만, 다음의 두가지 상황에서는 명시적 메모리 배리어가 필요할 수 있습니다:
+
+ (1) 일부 시스템에서 I/O 스토어는 모든 CPU 에 일관되게 순서 맞춰지지 않는데,
+     따라서 _모든_ 일반적인 드라이버들에 락이 사용되어야만 하고 이 크리티컬
+     섹션을 빠져나오기 전에 mmiowb() 가 꼭 호출되어야 합니다.
+
+ (2) 만약 액세스 함수들이 완화된 메모리 액세스 속성을 갖는 I/O 메모리 윈도우를
+     사용한다면, 순서를 강제하기 위해선 _mandatory_ 메모리 배리어가 필요합니다.
+
+더 많은 정보를 위해선 Documentation/DocBook/deviceiobook.tmpl 을 참고하십시오.
+
+
+인터럽트
+--------
+
+드라이버는 자신의 인터럽트 서비스 루틴에 의해 인터럽트 당할 수 있기 때문에
+드라이버의 이 두 부분은 서로의 디바이스 제어 또는 액세스 부분과 상호 간섭할 수
+있습니다.
+
+스스로에게 인터럽트 당하는 걸 불가능하게 하고, 드라이버의 크리티컬한
+오퍼레이션들을 모두 인터럽트가 불가능하게 된 영역에 집어넣거나 하는 방법 (락의
+한 형태) 으로 이런 상호 간섭을 - 최소한 부분적으로라도 - 줄일 수 있습니다.
+드라이버의 인터럽트 루틴이 실행 중인 동안, 해당 드라이버의 코어는 같은 CPU 에서
+수행되지 않을 것이며, 현재의 인터럽트가 처리되는 중에는 또다시 인터럽트가
+일어나지 못하도록 되어 있으니 인터럽트 핸들러는 그에 대해서는 락을 잡지 않아도
+됩니다.
+
+하지만, 어드레스 레지스터와 데이터 레지스터를 갖는 이더넷 카드를 다루는
+드라이버를 생각해 봅시다.  만약 이 드라이버의 코어가 인터럽트를 비활성화시킨
+채로 이더넷 카드와 대화하고 드라이버의 인터럽트 핸들러가 호출되었다면:
+
+	LOCAL IRQ DISABLE
+	writew(ADDR, 3);
+	writew(DATA, y);
+	LOCAL IRQ ENABLE
+	<interrupt>
+	writew(ADDR, 4);
+	q = readw(DATA);
+	</interrupt>
+
+만약 순서 규칙이 충분히 완화되어 있다면 데이터 레지스터에의 스토어는 어드레스
+레지스터에 두번째로 행해지는 스토어 뒤에 일어날 수도 있습니다:
+
+	STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA
+
+
+만약 순서 규칙이 충분히 완화되어 있고 묵시적으로든 명시적으로든 배리어가
+사용되지 않았다면 인터럽트 비활성화 섹션에서 일어난 액세스가 바깥으로 새어서
+인터럽트 내에서 일어난 액세스와 섞일 수 있다고 - 그리고 그 반대도 - 가정해야만
+합니다.
+
+그런 영역 안에서 일어나는 I/O 액세스들은 엄격한 순서 규칙의 I/O 레지스터에
+묵시적 I/O 배리어를 형성하는 동기적 (synchronous) 로드 오퍼레이션을 포함하기
+때문에 일반적으로는 이런게 문제가 되지 않습니다.  만약 이걸로는 충분치 않다면
+mmiowb() 가 명시적으로 사용될 필요가 있습니다.
+
+
+하나의 인터럽트 루틴과 별도의 CPU 에서 수행중이며 서로 통신을 하는 두 루틴
+사이에도 비슷한 상황이 일어날 수 있습니다.  만약 그런 경우가 발생할 가능성이
+있다면, 순서를 보장하기 위해 인터럽트 비활성화 락이 사용되어져야만 합니다.
+
+
+======================
+커널 I/O 배리어의 효과
+======================
+
+I/O 메모리에 액세스할 때, 드라이버는 적절한 액세스 함수를 사용해야 합니다:
+
+ (*) inX(), outX():
+
+     이것들은 메모리 공간보다는 I/O 공간에 이야기를 하려는 의도로
+     만들어졌습니다만, 그건 기본적으로 CPU 마다 다른 컨셉입니다.  i386 과
+     x86_64 프로세서들은 특별한 I/O 공간 액세스 사이클과 명령어를 실제로 가지고
+     있지만, 다른 많은 CPU 들에는 그런 컨셉이 존재하지 않습니다.
+
+     다른 것들 중에서도 PCI 버스가 I/O 공간 컨셉을 정의하는데, 이는 - i386 과
+     x86_64 같은 CPU 에서 - CPU 의 I/O 공간 컨셉으로 쉽게 매치됩니다.  하지만,
+     대체할 I/O 공간이 없는 CPU 에서는 CPU 의 메모리 맵의 가상 I/O 공간으로
+     매핑될 수도 있습니다.
+
+     이 공간으로의 액세스는 (i386 등에서는) 완전하게 동기화 됩니다만, 중간의
+     (PCI 호스트 브리지와 같은) 브리지들은 이를 완전히 보장하진 않을수도
+     있습니다.
+
+     이것들의 상호간의 순서는 완전하게 보장됩니다.
+
+     다른 타입의 메모리 오퍼레이션, I/O 오퍼레이션에 대한 순서는 완전하게
+     보장되지는 않습니다.
+
+ (*) readX(), writeX():
+
+     이것들이 수행 요청되는 CPU 에서 서로에게 완전히 순서가 맞춰지고 독립적으로
+     수행되는지에 대한 보장 여부는 이들이 액세스 하는 메모리 윈도우에 정의된
+     특성에 의해 결정됩니다.  예를 들어, 최신의 i386 아키텍쳐 머신에서는 MTRR
+     레지스터로 이 특성이 조정됩니다.
+
+     일반적으로는, 프리페치 (prefetch) 가능한 디바이스를 액세스 하는게
+     아니라면, 이것들은 완전히 순서가 맞춰지고 결합되지 않게 보장될 겁니다.
+
+     하지만, (PCI 브리지와 같은) 중간의 하드웨어는 자신이 원한다면 집행을
+     연기시킬 수 있습니다; 스토어 명령을 실제로 하드웨어로 내려보내기(flush)
+     위해서는 같은 위치로부터 로드를 하는 방법이 있습니다만[*], PCI 의 경우는
+     같은 디바이스나 환경 구성 영역에서의 로드만으로도 충분할 겁니다.
+
+     [*] 주의! 쓰여진 것과 같은 위치로부터의 로드를 시도하는 것은 오동작을
+	 일으킬 수도 있습니다 - 예로 16650 Rx/Tx 시리얼 레지스터를 생각해
+	 보세요.
+
+     프리페치 가능한 I/O 메모리가 사용되면, 스토어 명령들이 순서를 지키도록
+     하기 위해 mmiowb() 배리어가 필요할 수 있습니다.
+
+     PCI 트랜잭션 사이의 상호작용에 대해 더 많은 정보를 위해선 PCI 명세서를
+     참고하시기 바랍니다.
+
+ (*) readX_relaxed(), writeX_relaxed()
+
+     이것들은 readX() 와 writeX() 랑 비슷하지만, 더 완화된 메모리 순서 보장을
+     제공합니다.  구체적으로, 이것들은 일반적 메모리 액세스 (예: DMA 버퍼) 에도
+     LOCK 이나 UNLOCK 오퍼레이션들에도 순서를 보장하지 않습니다.  LOCK 이나
+     UNLOCK 오퍼레이션들에 맞춰지는 순서가 필요하다면, mmiowb() 배리어가 사용될
+     수 있습니다.  같은 주변 장치에의 완화된 액세스끼리는 순서가 지켜짐을 알아
+     두시기 바랍니다.
+
+ (*) ioreadX(), iowriteX()
+
+     이것들은 inX()/outX() 나 readX()/writeX() 처럼 실제로 수행하는 액세스의
+     종류에 따라 적절하게 수행될 것입니다.
+
+
+===================================
+가정되는 가장 완화된 실행 순서 모델
+===================================
+
+컨셉적으로 CPU 는 주어진 프로그램에 대해 프로그램 그 자체에는 인과성 (program
+causality) 을 지키는 것처럼 보이게 하지만 일반적으로는 순서를 거의 지켜주지
+않는다고 가정되어야만 합니다.  (i386 이나 x86_64 같은) 일부 CPU 들은 코드
+재배치에 (powerpc 나 frv 와 같은) 다른 것들에 비해 강한 제약을 갖지만, 아키텍쳐
+종속적 코드 이외의 코드에서는 순서에 대한 제약이 가장 완화된 경우 (DEC Alpha)
+를 가정해야 합니다.
+
+이 말은, CPU 에게 주어지는 인스트럭션 스트림 내의 한 인스트럭션이 앞의
+인스트럭션에 종속적이라면 앞의 인스트럭션은 뒤의 종속적 인스트럭션이 실행되기
+전에 완료[*]될 수 있어야 한다는 제약 (달리 말해서, 인과성이 지켜지는 것으로
+보이게 함) 외에는 자신이 원하는 순서대로 - 심지어 병렬적으로도 - 그 스트림을
+실행할 수 있음을 의미합니다
+
+ [*] 일부 인스트럭션은 하나 이상의 영향 - 조건 코드를 바꾼다던지, 레지스터나
+     메모리를 바꾼다던지 - 을 만들어내며, 다른 인스트럭션은 다른 효과에
+     종속적일 수 있습니다.
+
+CPU 는 최종적으로 아무 효과도 만들지 않는 인스트럭션 시퀀스는 없애버릴 수도
+있습니다.  예를 들어, 만약 두개의 연속되는 인스트럭션이 둘 다 같은 레지스터에
+직접적인 값 (immediate value) 을 집어넣는다면, 첫번째 인스트럭션은 버려질 수도
+있습니다.
+
+
+비슷하게, 컴파일러 역시 프로그램의 인과성만 지켜준다면 인스트럭션 스트림을
+자신이 보기에 올바르다 생각되는대로 재배치 할 수 있습니다.
+
+
+===============
+CPU 캐시의 영향
+===============
+
+캐시된 메모리 오퍼레이션들이 시스템 전체에 어떻게 인지되는지는 CPU 와 메모리
+사이에 존재하는 캐시들, 그리고 시스템 상태의 일관성을 관리하는 메모리 일관성
+시스템에 상당 부분 영향을 받습니다.
+
+한 CPU 가 시스템의 다른 부분들과 캐시를 통해 상호작용한다면, 메모리 시스템은
+CPU 의 캐시들을 포함해야 하며, CPU 와 CPU 자신의 캐시 사이에서의 동작을 위한
+메모리 배리어를 가져야 합니다. (메모리 배리어는 논리적으로는 다음 그림의
+점선에서 동작합니다):
+
+	    <--- CPU --->         :       <----------- Memory ----------->
+	                          :
+	+--------+    +--------+  :   +--------+    +-----------+
+	|        |    |        |  :   |        |    |           |    +--------+
+	|  CPU   |    | Memory |  :   | CPU    |    |           |    |        |
+	|  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+	|        |    | Queue  |  :   |        |    |           |--->| Memory |
+	|        |    |        |  :   |        |    |           |    |        |
+	+--------+    +--------+  :   +--------+    |           |    |        |
+	                          :                 | Cache     |    +--------+
+	                          :                 | Coherency |
+	                          :                 | Mechanism |    +--------+
+	+--------+    +--------+  :   +--------+    |           |    |	      |
+	|        |    |        |  :   |        |    |           |    |        |
+	|  CPU   |    | Memory |  :   | CPU    |    |           |--->| Device |
+	|  Core  |--->| Access |----->| Cache  |<-->|           |    |        |
+	|        |    | Queue  |  :   |        |    |           |    |        |
+	|        |    |        |  :   |        |    |           |    +--------+
+	+--------+    +--------+  :   +--------+    +-----------+
+	                          :
+	                          :
+
+특정 로드나 스토어는 해당 오퍼레이션을 요청한 CPU 의 캐시 내에서 동작을 완료할
+수도 있기 때문에 해당 CPU 의 바깥에는 보이지 않을 수 있지만, 다른 CPU 가 관심을
+갖는다면 캐시 일관성 메커니즘이 해당 캐시라인을 해당 CPU 에게 전달하고, 해당
+메모리 영역에 대한 오퍼레이션이 발생할 때마다 그 영향을 전파시키기 때문에, 해당
+오퍼레이션은 메모리에 실제로 액세스를 한것처럼 나타날 것입니다.
+
+CPU 코어는 프로그램의 인과성이 유지된다고만 여겨진다면 인스트럭션들을 어떤
+순서로든 재배치해서 수행할 수 있습니다.  일부 인스트럭션들은 로드나 스토어
+오퍼레이션을 만드는데 이 오퍼레이션들은 이후 수행될 메모리 액세스 큐에 들어가게
+됩니다.  코어는 이 오퍼레이션들을 해당 큐에 어떤 순서로든 원하는대로 넣을 수
+있고, 다른 인스트럭션의 완료를 기다리도록 강제되기 전까지는 수행을 계속합니다.
+
+메모리 배리어가 하는 일은 CPU 쪽에서 메모리 쪽으로 넘어가는 액세스들의 순서,
+그리고 그 액세스의 결과가 시스템의 다른 관찰자들에게 인지되는 순서를 제어하는
+것입니다.
+
+[!] CPU 들은 항상 그들 자신의 로드와 스토어는 프로그램 순서대로 일어난 것으로
+보기 때문에, 주어진 CPU 내에서는 메모리 배리어를 사용할 필요가 _없습니다_.
+
+[!] MMIO 나 다른 디바이스 액세스들은 캐시 시스템을 우회할 수도 있습니다.  우회
+여부는 디바이스가 액세스 되는 메모리 윈도우의 특성에 의해 결정될 수도 있고, CPU
+가 가지고 있을 수 있는 특수한 디바이스 통신 인스트럭션의 사용에 의해서 결정될
+수도 있습니다.
+
+
+캐시 일관성
+-----------
+
+하지만 삶은 앞에서 이야기한 것처럼 단순하지 않습니다: 캐시들은 일관적일 것으로
+기대되지만, 그 일관성이 순서에도 적용될 거라는 보장은 없습니다.  한 CPU 에서
+만들어진 변경 사항은 최종적으로는 시스템의 모든 CPU 에게 보여지게 되지만, 다른
+CPU 들에게도 같은 순서로 보이게 될 거라는 보장은 없다는 뜻입니다.
+
+
+두개의 CPU (1 & 2) 가 달려 있고, 각 CPU 에 두개의 데이터 캐시(CPU 1 은 A/B 를,
+CPU 2 는 C/D 를 갖습니다)가 병렬로 연결되어 있는 시스템을 다룬다고 생각해
+봅시다:
+
+	            :
+	            :                          +--------+
+	            :      +---------+         |        |
+	+--------+  : +--->| Cache A |<------->|        |
+	|        |  : |    +---------+         |        |
+	|  CPU 1 |<---+                        |        |
+	|        |  : |    +---------+         |        |
+	+--------+  : +--->| Cache B |<------->|        |
+	            :      +---------+         |        |
+	            :                          | Memory |
+	            :      +---------+         | System |
+	+--------+  : +--->| Cache C |<------->|        |
+	|        |  : |    +---------+         |        |
+	|  CPU 2 |<---+                        |        |
+	|        |  : |    +---------+         |        |
+	+--------+  : +--->| Cache D |<------->|        |
+	            :      +---------+         |        |
+	            :                          +--------+
+	            :
+
+이 시스템이 다음과 같은 특성을 갖는다 생각해 봅시다:
+
+ (*) 홀수번 캐시라인은 캐시 A, 캐시 C 또는 메모리에 위치할 수 있음;
+
+ (*) 짝수번 캐시라인은 캐시 B, 캐시 D 또는 메모리에 위치할 수 있음;
+
+ (*) CPU 코어가 한개의 캐시에 접근하는 동안, 다른 캐시는 - 더티 캐시라인을
+     메모리에 내리거나 추측성 로드를 하거나 하기 위해 - 시스템의 다른 부분에
+     액세스 하기 위해 버스를 사용할 수 있음;
+
+ (*) 각 캐시는 시스템의 나머지 부분들과 일관성을 맞추기 위해 해당 캐시에
+     적용되어야 할 오퍼레이션들의 큐를 가짐;
+
+ (*) 이 일관성 큐는 캐시에 이미 존재하는 라인에 가해지는 평범한 로드에 의해서는
+     비워지지 않는데, 큐의 오퍼레이션들이 이 로드의 결과에 영향을 끼칠 수 있다
+     할지라도 그러함.
+
+이제, 첫번째 CPU 에서 두개의 쓰기 오퍼레이션을 만드는데, 해당 CPU 의 캐시에
+요청된 순서로 오퍼레이션이 도달됨을 보장하기 위해 두 오퍼레이션 사이에 쓰기
+배리어를 사용하는 상황을 상상해 봅시다:
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+					u == 0, v == 1 and p == &u, q == &u
+	v = 2;
+	smp_wmb();			v 의 변경이 p 의 변경 전에 보일 것을
+					 분명히 함
+	<A:modify v=2>			v 는 이제 캐시 A 에 독점적으로 존재함
+	p = &v;
+	<B:modify p=&v>			p 는 이제 캐시 B 에 독점적으로 존재함
+
+여기서의 쓰기 메모리 배리어는 CPU 1 의 캐시가 올바른 순서로 업데이트 된 것으로
+시스템의 다른 CPU 들이 인지하게 만듭니다.  하지만, 이제 두번째 CPU 가 그 값들을
+읽으려 하는 상황을 생각해 봅시다:
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+	...
+			q = p;
+			x = *q;
+
+위의 두개의 읽기 오퍼레이션은 예상된 순서로 일어나지 못할 수 있는데, 두번째 CPU
+의 한 캐시에 다른 캐시 이벤트가 발생해 v 를 담고 있는 캐시라인의 해당 캐시에의
+업데이트가 지연되는 사이, p 를 담고 있는 캐시라인은 두번째 CPU 의 다른 캐시에
+업데이트 되어버렸을 수 있기 때문입니다.
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+					u == 0, v == 1 and p == &u, q == &u
+	v = 2;
+	smp_wmb();
+	<A:modify v=2>	<C:busy>
+			<C:queue v=2>
+	p = &v;		q = p;
+			<D:request p>
+	<B:modify p=&v>	<D:commit p=&v>
+			<D:read p>
+			x = *q;
+			<C:read *q>	캐시에 업데이트 되기 전의 v 를 읽음
+			<C:unbusy>
+			<C:commit v=2>
+
+기본적으로, 두개의 캐시라인 모두 CPU 2 에 최종적으로는 업데이트 될 것이지만,
+별도의 개입 없이는, 업데이트의 순서가 CPU 1 에서 만들어진 순서와 동일할
+것이라는 보장이 없습니다.
+
+
+여기에 개입하기 위해선, 데이터 의존성 배리어나 읽기 배리어를 로드 오퍼레이션들
+사이에 넣어야 합니다.  이렇게 함으로써 캐시가 다음 요청을 처리하기 전에 일관성
+큐를 처리하도록 강제하게 됩니다.
+
+	CPU 1		CPU 2		COMMENT
+	===============	===============	=======================================
+					u == 0, v == 1 and p == &u, q == &u
+	v = 2;
+	smp_wmb();
+	<A:modify v=2>	<C:busy>
+			<C:queue v=2>
+	p = &v;		q = p;
+			<D:request p>
+	<B:modify p=&v>	<D:commit p=&v>
+			<D:read p>
+			smp_read_barrier_depends()
+			<C:unbusy>
+			<C:commit v=2>
+			x = *q;
+			<C:read *q>	캐시에 업데이트 된 v 를 읽음
+
+
+이런 부류의 문제는 DEC Alpha 계열 프로세서들에서 발견될 수 있는데, 이들은
+데이터 버스를 좀 더 잘 사용해 성능을 개선할 수 있는, 분할된 캐시를 가지고 있기
+때문입니다.  대부분의 CPU 는 하나의 읽기 오퍼레이션의 메모리 액세스가 다른 읽기
+오퍼레이션에 의존적이라면 데이터 의존성 배리어를 내포시킵니다만, 모두가 그런건
+아니기 때문에 이점에 의존해선 안됩니다.
+
+다른 CPU 들도 분할된 캐시를 가지고 있을 수 있지만, 그런 CPU 들은 평범한 메모리
+액세스를 위해서도 이 분할된 캐시들 사이의 조정을 해야만 합니다.  Alpha 는 가장
+약한 메모리 순서 시맨틱 (semantic) 을 선택함으로써 메모리 배리어가 명시적으로
+사용되지 않았을 때에는 그런 조정이 필요하지 않게 했습니다.
+
+
+캐시 일관성 VS DMA
+------------------
+
+모든 시스템이 DMA 를 하는 디바이스에 대해서까지 캐시 일관성을 유지하지는
+않습니다.  그런 경우, DMA 를 시도하는 디바이스는 RAM 으로부터 잘못된 데이터를
+읽을 수 있는데, 더티 캐시 라인이 CPU 의 캐시에 머무르고 있고, 바뀐 값이 아직
+RAM 에 써지지 않았을 수 있기 때문입니다.  이 문제를 해결하기 위해선, 커널의
+적절한 부분에서 각 CPU 캐시의 문제되는 비트들을 플러시 (flush) 시켜야만 합니다
+(그리고 그것들을 무효화 - invalidation - 시킬 수도 있겠죠).
+
+또한, 디바이스에 의해 RAM 에 DMA 로 쓰여진 값은 디바이스가 쓰기를 완료한 후에
+CPU 의 캐시에서 RAM 으로 쓰여지는 더티 캐시 라인에 의해 덮어써질 수도 있고, CPU
+의 캐시에 존재하는 캐시 라인이 해당 캐시에서 삭제되고 다시 값을 읽어들이기
+전까지는 RAM 이 업데이트 되었다는 사실 자체가 숨겨져 버릴 수도 있습니다.  이
+문제를 해결하기 위해선, 커널의 적절한 부분에서 각 CPU 의 캐시 안의 문제가 되는
+비트들을 무효화 시켜야 합니다.
+
+캐시 관리에 대한 더 많은 정보를 위해선 Documentation/cachetlb.txt 를
+참고하세요.
+
+
+캐시 일관성 VS MMIO
+-------------------
+
+Memory mapped I/O 는 일반적으로 CPU 의 메모리 공간 내의 한 윈도우의 특정 부분
+내의 메모리 지역에 이루어지는데, 이 윈도우는 일반적인, RAM 으로 향하는
+윈도우와는 다른 특성을 갖습니다.
+
+그런 특성 가운데 하나는, 일반적으로 그런 액세스는 캐시를 완전히 우회하고
+디바이스 버스로 곧바로 향한다는 것입니다.  이 말은 MMIO 액세스는 먼저
+시작되어서 캐시에서 완료된 메모리 액세스를 추월할 수 있다는 뜻입니다.  이런
+경우엔 메모리 배리어만으로는 충분치 않고, 만약 캐시된 메모리 쓰기 오퍼레이션과
+MMIO 액세스가 어떤 방식으로든 의존적이라면 해당 캐시는 두 오퍼레이션 사이에
+비워져(flush)야만 합니다.
+
+
+======================
+CPU 들이 저지르는 일들
+======================
+
+프로그래머는 CPU 가 메모리 오퍼레이션들을 정확히 요청한대로 수행해 줄 것이라고
+생각하는데, 예를 들어 다음과 같은 코드를 CPU 에게 넘긴다면:
+
+	a = READ_ONCE(*A);
+	WRITE_ONCE(*B, b);
+	c = READ_ONCE(*C);
+	d = READ_ONCE(*D);
+	WRITE_ONCE(*E, e);
+
+CPU 는 다음 인스트럭션을 처리하기 전에 현재의 인스트럭션을 위한 메모리
+오퍼레이션을 완료할 것이라 생각하고, 따라서 시스템 외부에서 관찰하기에도 정해진
+순서대로 오퍼레이션이 수행될 것으로 예상합니다:
+
+	LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E.
+
+
+당연하지만, 실제로는 훨씬 엉망입니다.  많은 CPU 와 컴파일러에서 앞의 가정은
+성립하지 못하는데 그 이유는 다음과 같습니다:
+
+ (*) 로드 오퍼레이션들은 실행을 계속 해나가기 위해 곧바로 완료될 필요가 있는
+     경우가 많은 반면, 스토어 오퍼레이션들은 종종 별다른 문제 없이 유예될 수
+     있습니다;
+
+ (*) 로드 오퍼레이션들은 예측적으로 수행될 수 있으며, 필요없는 로드였다고
+     증명된 예측적 로드의 결과는 버려집니다;
+
+ (*) 로드 오퍼레이션들은 예측적으로 수행될 수 있으므로, 예상된 이벤트의
+     시퀀스와 다른 시간에 로드가 이뤄질 수 있습니다;
+
+ (*) 메모리 액세스 순서는 CPU 버스와 캐시를 좀 더 잘 사용할 수 있도록 재배치
+     될 수 있습니다;
+
+ (*) 로드와 스토어는 인접한 위치에의 액세스들을 일괄적으로 처리할 수 있는
+     메모리나 I/O 하드웨어 (메모리와 PCI 디바이스 둘 다 이게 가능할 수
+     있습니다) 에 대해 요청되는 경우, 개별 오퍼레이션을 위한 트랜잭션 설정
+     비용을 아끼기 위해 조합되어 실행될 수 있습니다; 그리고
+
+ (*) 해당 CPU 의 데이터 캐시가 순서에 영향을 끼칠 수도 있고, 캐시 일관성
+     메커니즘이 - 스토어가 실제로 캐시에 도달한다면 - 이 문제를 완화시킬 수는
+     있지만 이 일관성 관리가 다른 CPU 들에도 같은 순서로 전달된다는 보장은
+     없습니다.
+
+따라서, 앞의 코드에 대해 다른 CPU 가 보는 결과는 다음과 같을 수 있습니다:
+
+	LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B
+
+	("LOAD {*C,*D}" 는 조합된 로드입니다)
+
+
+하지만, CPU 는 스스로는 일관적일 것을 보장합니다: CPU _자신_ 의 액세스들은
+자신에게는 메모리 배리어가 없음에도 불구하고 정확히 순서 세워진 것으로 보여질
+것입니다.  예를 들어 다음의 코드가 주어졌다면:
+
+	U = READ_ONCE(*A);
+	WRITE_ONCE(*A, V);
+	WRITE_ONCE(*A, W);
+	X = READ_ONCE(*A);
+	WRITE_ONCE(*A, Y);
+	Z = READ_ONCE(*A);
+
+그리고 외부의 영향에 의한 간섭이 없다고 가정하면, 최종 결과는 다음과 같이
+나타날 것이라고 예상될 수 있습니다:
+
+	U == *A 의 최초 값
+	X == W
+	Z == Y
+	*A == Y
+
+앞의 코드는 CPU 가 다음의 메모리 액세스 시퀀스를 만들도록 할겁니다:
+
+	U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A
+
+하지만, 별다른 개입이 없고 프로그램의 시야에 이 세상이 여전히 일관적이라고
+보인다는 보장만 지켜진다면 이 시퀀스는 어떤 조합으로든 재구성될 수 있으며, 각
+액세스들은 합쳐지거나 버려질 수 있습니다.  일부 아키텍쳐에서 CPU 는 같은 위치에
+대한 연속적인 로드 오퍼레이션들을 재배치 할 수 있기 때문에 앞의 예에서의
+READ_ONCE() 와 WRITE_ONCE() 는 반드시 존재해야 함을 알아두세요.  그런 종류의
+아키텍쳐에서 READ_ONCE() 와 WRITE_ONCE() 는 이 문제를 막기 위해 필요한 일을
+뭐가 됐든지 하게 되는데, 예를 들어 Itanium 에서는 READ_ONCE() 와 WRITE_ONCE()
+가 사용하는 volatile 캐스팅은 GCC 가 그런 재배치를 방지하는 특수 인스트럭션인
+ld.acq 와 stl.rel 인스트럭션을 각각 만들어 내도록 합니다.
+
+컴파일러 역시 이 시퀀스의 액세스들을 CPU 가 보기도 전에 합치거나 버리거나 뒤로
+미뤄버릴 수 있습니다.
+
+예를 들어:
+
+	*A = V;
+	*A = W;
+
+는 다음과 같이 변형될 수 있습니다:
+
+	*A = W;
+
+따라서, 쓰기 배리어나 WRITE_ONCE() 가 없다면 *A 로의 V 값의 저장의 효과는
+사라진다고 가정될 수 있습니다.  비슷하게:
+
+	*A = Y;
+	Z = *A;
+
+는, 메모리 배리어나 READ_ONCE() 와 WRITE_ONCE() 없이는 다음과 같이 변형될 수
+있습니다:
+
+	*A = Y;
+	Z = Y;
+
+그리고 이 LOAD 오퍼레이션은 CPU 바깥에는 아예 보이지 않습니다.
+
+
+그리고, ALPHA 가 있다
+---------------------
+
+DEC Alpha CPU 는 가장 완화된 메모리 순서의 CPU 중 하나입니다.  뿐만 아니라,
+Alpha CPU 의 일부 버전은 분할된 데이터 캐시를 가지고 있어서, 의미적으로
+관계되어 있는 두개의 캐시 라인이 서로 다른 시간에 업데이트 되는게 가능합니다.
+이게 데이터 의존성 배리어가 정말 필요해지는 부분인데, 데이터 의존성 배리어는
+메모리 일관성 시스템과 함께 두개의 캐시를 동기화 시켜서, 포인터 변경과 새로운
+데이터의 발견을 올바른 순서로 일어나게 하기 때문입니다.
+
+리눅스 커널의 메모리 배리어 모델은 Alpha 에 기초해서 정의되었습니다.
+
+위의 "캐시 일관성" 서브섹션을 참고하세요.
+
+
+가상 머신 게스트
+----------------
+
+가상 머신에서 동작하는 게스트들은 게스트 자체는 SMP 지원 없이 컴파일 되었다
+해도 SMP 영향을 받을 수 있습니다.  이건 UP 커널을 사용하면서 SMP 호스트와
+결부되어 발생하는 부작용입니다.  이 경우에는 mandatory 배리어를 사용해서 문제를
+해결할 수 있겠지만 그런 해결은 대부분의 경우 최적의 해결책이 아닙니다.
+
+이 문제를 완벽하게 해결하기 위해, 로우 레벨의 virt_mb() 등의 매크로를 사용할 수
+있습니다. 이것들은 SMP 가 활성화 되어 있다면 smp_mb() 등과 동일한 효과를
+갖습니다만, SMP 와 SMP 아닌 시스템 모두에 대해 동일한 코드를 만들어냅니다.
+예를 들어, 가상 머신 게스트들은 (SMP 일 수 있는) 호스트와 동기화를 할 때에는
+smp_mb() 가 아니라 virt_mb() 를 사용해야 합니다.
+
+이것들은 smp_mb() 류의 것들과 모든 부분에서 동일하며, 특히, MMIO 의 영향에
+대해서는 간여하지 않습니다: MMIO 의 영향을 제어하려면, mandatory 배리어를
+사용하시기 바랍니다.
+
+
+=======
+사용 예
+=======
+
+순환식 버퍼
+-----------
+
+메모리 배리어는 순환식 버퍼를 생성자(producer)와 소비자(consumer) 사이의
+동기화에 락을 사용하지 않고 구현하는데에 사용될 수 있습니다.  더 자세한 내용을
+위해선 다음을 참고하세요:
+
+	Documentation/circular-buffers.txt
+
+
+=========
+참고 문헌
+=========
+
+Alpha AXP Architecture Reference Manual, Second Edition (Sites & Witek,
+Digital Press)
+	Chapter 5.2: Physical Address Space Characteristics
+	Chapter 5.4: Caches and Write Buffers
+	Chapter 5.5: Data Sharing
+	Chapter 5.6: Read/Write Ordering
+
+AMD64 Architecture Programmer's Manual Volume 2: System Programming
+	Chapter 7.1: Memory-Access Ordering
+	Chapter 7.4: Buffering and Combining Memory Writes
+
+IA-32 Intel Architecture Software Developer's Manual, Volume 3:
+System Programming Guide
+	Chapter 7.1: Locked Atomic Operations
+	Chapter 7.2: Memory Ordering
+	Chapter 7.4: Serializing Instructions
+
+The SPARC Architecture Manual, Version 9
+	Chapter 8: Memory Models
+	Appendix D: Formal Specification of the Memory Models
+	Appendix J: Programming with the Memory Models
+
+UltraSPARC Programmer Reference Manual
+	Chapter 5: Memory Accesses and Cacheability
+	Chapter 15: Sparc-V9 Memory Models
+
+UltraSPARC III Cu User's Manual
+	Chapter 9: Memory Models
+
+UltraSPARC IIIi Processor User's Manual
+	Chapter 8: Memory Models
+
+UltraSPARC Architecture 2005
+	Chapter 9: Memory
+	Appendix D: Formal Specifications of the Memory Models
+
+UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
+	Chapter 8: Memory Models
+	Appendix F: Caches and Cache Coherency
+
+Solaris Internals, Core Kernel Architecture, p63-68:
+	Chapter 3.3: Hardware Considerations for Locks and
+			Synchronization
+
+Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching
+for Kernel Programmers:
+	Chapter 13: Other Memory Models
+
+Intel Itanium Architecture Software Developer's Manual: Volume 1:
+	Section 2.6: Speculation
+	Section 4.4: Memory Access
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/ko_KR/stable_api_nonsense.txt linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/stable_api_nonsense.txt
--- linux-libre-4.9-gnu/Documentation/translations/ko_KR/stable_api_nonsense.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/ko_KR/stable_api_nonsense.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,195 @@
+NOTE:
+This is a version of Documentation/process/stable-api-nonsense.rst translated
+into korean
+This document is maintained by Minchan Kim <minchan@kernel.org>
+If you find any difference between this document and the original file or
+a problem with the translation, please contact the maintainer of this file.
+
+Please also note that the purpose of this file is to be easier to
+read for non English (read: korean) speakers and is not intended as
+a fork. So if you have any comments or updates for this file please
+try to update the original English file first.
+
+==================================
+이 문서는
+Documentation/process/stable-api-nonsense.rst
+의 한글 번역입니다.
+
+역자： 김민찬 <minchan@kernel.org>
+감수： 이제이미 <jamee.lee@samsung.com>
+==================================
+
+리눅스 커널 드라이버 인터페이스
+(여러분들의 모든 질문에 대한 답 그리고 다른 몇가지)
+
+Greg Kroah-Hartman <greg@kroah.com>
+
+이 문서는 리눅스가 왜 바이너리 커널 인터페이스를 갖지 않는지, 왜 변하지
+않는(stable) 커널 인터페이스를 갖지 않는지를 설명하기 위해 쓰여졌다.
+이 문서는 커널과 유저공간 사이의 인터페이스가 아니라 커널 내부의
+인터페이스들을 설명하고 있다는 것을 유념하라. 커널과 유저공간 사이의
+인터페이스는 응용프로그램이 사용하는 syscall 인터페이스이다. 그 인터페이스는
+오랫동안 거의 변하지 않았고 앞으로도 변하지 않을 것이다. 나는 pre 0.9에서
+만들어졌지만 최신의 2.6 커널 배포에서도 잘 동작하는 프로그램을 가지고
+있다. 이 인터페이스는 사용자와 응용프로그램 개발자들이 변하지 않을 것이라고
+여길수 있는 것이다.
+
+
+초록
+----
+여러분은 변하지 않는 커널 인터페이스를 원한다고 생각하지만 실제로는
+그렇지 않으며 심지어는 그것을 알아채지 못한다. 여러분이 원하는 것은
+안정되게 실행되는 드라이버이며 드라이버가 메인 커널 트리에 있을 때
+그런 안정적인 드라이버를 얻을 수 있게 된다. 또한 여러분의 드라이버가
+메인 커널 트리에 있다면 다른 많은 좋은 이점들을 얻게 된다. 그러한 것들이
+리눅스를 강건하고, 안정적이며, 성숙한 운영체제로 만들어 놓음으로써
+여러분들로 하여금 바로 리눅스를 사용하게 만드는 이유이다.
+
+
+소개
+----
+
+커널 내부의 인터페이스가 바뀌는 것을 걱정하며 커널 드라이버를 작성하고
+싶어하는 사람은 정말 이상한 사람이다. 세상의 대다수의 사람들은 이 인터페이스를
+보지못할 것이며 전혀 걱정하지도 않는다.
+
+먼저, 나는 closed 소스, hidden 소스, binary blobs, 소스 wrappers, 또는 GPL로
+배포되었지만 소스 코드를 갖고 있지 않은 커널 드라이버들을 설명하는 어떤 다른
+용어들에 관한 어떤 법적인 문제에 관해서는 언급하지 않을 것이다. 어떤 법적인
+질문들을 가지고 있다면 변호사와 연락하라. 나는 프로그래머이므로 여기서 기술적인
+문제들만을 설명하려고 한다. (법적인 문제를 경시하는 것은 아니다. 그런 문제들은
+엄연히 현실에 있고 여러분들은 항상 그 문제들을 인식하고 있을 필요는 있다.)
+
+자, 두가지의 주요 주제가 있다. 바이너리 커널 인터페이스들과 변하지 않는
+커널 소스 인터페이들. 그것들은 서로 의존성을 가지고 있지만 바이너리
+문제를 먼저 풀고 넘어갈 것이다.
+
+
+
+바이너리 커널 인터페이스
+------------------------
+우리가 변하지 않는 커널 소스 인터페이스를 가지고 있다고 가정하자. 그러면
+바이너리 인터페이스 또한 자연적으로 변하지 않을까? 틀렸다. 리눅스 커널에
+관한 다음 사실들을 생각해보라.
+   - 여러분들이 사용하는 C 컴파일러의 버젼에 따라 다른 커널 자료 구조들은
+     다른 alignmnet들을 갖게 될것이고 다른 방법으로(함수들을 inline으로
+     했느냐, 아니냐) 다른 함수들을 포함하는 것도 가능한다. 중요한 것은
+     개별적인 함수 구성이 아니라 자료 구조 패딩이 달라진다는 점이다.
+   - 여러분이 선택한 커널 빌드 옵션에 따라서 커널은 다양한 것들을 가정할
+     수 있다.
+      - 다른 구조체들은 다른 필드들을 포함할 수 있다.
+      - 몇몇 함수들은 전혀 구현되지 않을 수도 있다(즉, 몇몇 lock들은
+        non-SMP 빌드에서는 사라져 버릴수도 있다).
+      - 커널내에 메모리는 build optoin들에 따라 다른 방법으로 align될수
+        있다.
+      - 리눅스는 많은 다양한 프로세서 아키텍쳐에서 실행된다. 한 아키텍쳐의
+        바이너리 드라이버를 다른 아키텍쳐에서 정상적으로 실행시킬 방법은
+        없다.
+
+커널을 빌드했던 C 컴파일러와 정확하게 같은 것을 사용하고 정확하게 같은
+커널 구성(configuration)을 사용하여 여러분들의 모듈을 빌드하면 간단히
+많은 문제들을 해결할 수 있다. 이렇게 하는 것은 여러분들이 하나의 리눅스
+배포판의 하나의 배포 버젼을 위한 모듈만을 제공한다면 별일 아닐 것이다.
+그러나 각기 다른 리눅스 배포판마다 한번씩 빌드하는 수를 각 리눅스 배포판마다
+제공하는 다른 릴리즈의 수와 곱하게 되면 이번에는 각 릴리즈들의 다른 빌드
+옵션의 악몽과 마주하게  것이다. 또한 각 리눅스 배포판들은 다른 하드웨어
+종류에(다른 프로세서 타입과 다른 옵션들) 맞춰져 있는 많은 다른 커널들을
+배포한다. 그러므로 한번의 배포에서조차 여러분들의 모듈은 여러 버젼을
+만들 필요가 있다.
+
+나를 믿어라. 여러분들은 이러한 종류의 배포를 지원하려고 시도한다면 시간이
+지나면 미칠지경이 될 것이다. 난 이러한 것을 오래전에 아주 어렵게 배웠다...
+
+
+
+변하지않는 커널 소스 인터페이스들
+---------------------------------
+
+리눅스 커널 드라이버를 계속해서 메인 커널 트리에 반영하지 않고
+유지보수하려고 하는 사람들과 이 문제를 논의하게 되면 훨씬 더
+"논란의 여지가 많은" 주제가 될 것이다.
+
+리눅스 커널 개발은 끊임없이 빠른 속도로 이루어지고 있으며 결코
+느슨해진 적이 없다. 커널 개발자들이 현재 인터페이스들에서 버그를
+발견하거나 무엇인가 할 수 있는 더 좋은 방법을 찾게 되었다고 하자.
+그들이 발견한 것을 실행한다면 아마도 더 잘 동작하도록 현재 인터페이스들을
+수정하게 될 것이다. 그들이 그런 일을 하게되면 함수 이름들은 변하게 되고,
+구조체들은 늘어나거나 줄어들게 되고, 함수 파라미터들은 재작업될 것이다.
+이러한 일이 발생되면 커널 내에 이 인터페이스를 사용했던 인스턴스들이 동시에
+수정될 것이며 이러한 과정은 모든 것이 계속해서 올바르게 동작할 것이라는
+것을 보장한다.
+
+이러한 것의 한 예로써, 커널 내부의 USB 인터페이스들은 이 서브시스템이
+생긴 이후로 적어도 3번의 다른 재작업을 겪었다. 이 재작업들은 많은 다른
+문제들을 풀었다.
+   - 데이터 스트림들의 동기적인 모델에서 비동기적인 모델로의 변화. 이것은
+     많은 드라이버들의 복잡성을 줄이고 처리량을 향상시켜 현재는 거의 모든
+     USB 장치들의 거의 최대 속도로 실행되고 있다.
+   - USB 드라이버가 USB 코어로부터 데이터 패킷들을 할당받로록 한 변경으로
+     인해서 지금의 모든 드라이버들은 많은 문서화된 데드락을 수정하기 위하여
+     USB 코어에게 더 많은 정보를 제공해야만 한다.
+
+이것은 오랫동안 자신의 오래된 USB 인터페이스들을 유지해야 하는 closed 운영체제들과는
+완전히 반대되는 것이다. closed된 운영체제들은 새로운 개발자들에게 우연히 낡은
+인터페이스를 사용하게 할 기회를 주게되며, 적절하지 못한 방법으로 처리하게 되어
+운영체제의 안정성을 해치는 문제를 야기하게 된다.
+
+이 두가지의 예들 모두, 모든 개발자들은 꼭 이루어져야 하는 중요한 변화들이라고
+동의를 하였고 비교적 적은 고통으로 변경되어졌다. 리눅스가 변하지 않는 소스
+인터페이스를 고집한다면, 새로운 인터페이스가 만들어지게 되며 반면 기존의 오래된
+것들, 그리고 깨진 것들은 계속해서 유지되어야 하며 이러한 일들은 USB 개발자들에게
+또 다른 일거리를 주게 된다. 모든 리눅스 USB 개발자들에게 자신의 그들의 업무를
+마친 후 시간을 투자하여 아무 득도 없는 무료 봉사를 해달라고 하는 것은 가능성이
+희박한 일이다.
+
+보안 문제 역시 리눅스에게는 매우 중요하다. 보안 문제가 발견되면 그것은
+매우 짧은 시간 안에 수정된다. 보안 문제는 그 문제를 해결하기 위하여
+여러번 내부 커널 인터페이스들을 재작업하게 만들었다. 이러한 문제가
+발생하였을 때 그 인터페이스들을 사용하는 모든 드라이버들도 동시에
+수정되어 보안 문제가 앞으로 갑작스럽게 생기지는 않을 것이라는 것을
+보장한다. 내부 인터페이스들의 변경이 허락되지 않으면 이러한 종류의 보안
+문제를 수정하고 그것이 다시 발생하지 않을 것이라고 보장하는 것은 가능하지
+않을 것이다.
+
+커널 인터페이스들은 계속해서 정리되고 있다. 현재 인터페이스를 사용하는
+사람이 한명도 없다면 그것은 삭제된다. 이것은 커널이 가능한한 가장 작게
+유지되며 존재하는 모든 가능성이 있는 인터페이스들이 테스트된다는 것을
+보장한다(사용되지 않는 인터페이스들은 유효성 검증을 하기가 거의 불가능하다).
+
+
+무엇을 해야 하나
+---------------
+자, 여러분이 메인 커널 트리에 있지 않은 리눅스 커널 드라이버를 가지고
+있다면 여러분은 즉, 개발자는 무엇을 해야 하나? 모든 배포판마다 다른
+커널 버젼을 위한 바이너리 드라이버를 배포하는 것은 악몽이며 계속해서
+변하고 있는 커널 인터페이스들의 맞처 유지보수하려고 시도하는 것은 힘든
+일이다.
+
+간단하다. 여러분의 커널 드라이버를 메인 커널 트리에 반영하라(우리는 여기서
+GPL을 따르는 배포 드라이버에 관해 얘기하고 있다는 것을 상기하라. 여러분의
+코드가 이러한 분류에 해당되지 않는다면 행운을 빈다. 여러분 스스로 어떻게든
+해야만 한다). 여러분의 드라이버가 트리에 있게되면 커널 인터페이스가
+변경되더라도 가장 먼저 커널에 변경을 가했던 사람에 의해서 수정될 것이다.
+이것은 여러분의 드라이버가 여러분의 별다른 노력없이 항상 빌드가 가능하며
+동작하는 것을 보장한다.
+
+메인 커널 트리에 여러분의 드라이버를 반영하면 얻게 되는 장점들은 다음과 같다.
+   - 관리에 드는 비용(원래 개발자의)은 줄어줄면서 드라이버의 질은 향상될 것이다.
+   - 다른 개발자들이 여러분의 드라이버에 기능들을 추가 할 것이다.
+   - 다른 사람들은 여러분의 드라이버에 버그를 발견하고 수정할 것이다.
+   - 다른 사람들은 여러분의 드라이버의 개선점을 찾을 줄 것이다.
+   - 외부 인터페이스 변경으로 인해 여러분의 드라이버의 수정이 필요하다면 다른
+     사람들이 드라이버를 업데이트할 것이다.
+   - 여러분의 드라이버는 별다른 노력 없이 모든 리눅스 배포판에  자동적으로
+     추가될 것이다.
+
+리눅스는 다른 운영 체제보다 "쉽게 쓸수 있는(out of the box)" 많은 다른 장치들을
+지원하고 어떤 다른 운영 체제보다 다양한 아키텍쳐위에서 이러한 장치들을 지원하기 때문에
+이러한 증명된 개발 모델은 틀림없이 바로 가고 있는 것이다.
+
+
+
+------
+
+이 문서의 초안을 검토해주고 코멘트 해준 Randy Dunlap, Andrew Morton, David Brownell,
+Hanna Linder, Robert Love, 그리고 Nishanth Aravamudan에게 감사한다.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm/Booting linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm/Booting
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm/Booting	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm/Booting	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,175 @@
+Chinese translated version of Documentation/arm/Booting
+
+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.
+
+Maintainer: Russell King <linux@arm.linux.org.uk>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm/Booting 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Russell King <linux@arm.linux.org.uk>
+中文版维护者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+			启动 ARM Linux
+			==============
+
+作者：Russell King
+日期：2002年5月18日
+
+以下文档适用于 2.4.18-rmk6 及以上版本。
+
+为了启动 ARM Linux，你需要一个引导装载程序（boot loader），
+它是一个在主内核启动前运行的一个小程序。引导装载程序需要初始化各种
+设备，并最终调用 Linux 内核，将信息传递给内核。
+
+从本质上讲，引导装载程序应提供（至少）以下功能：
+
+1、设置和初始化 RAM。
+2、初始化一个串口。
+3、检测机器的类型（machine type）。
+4、设置内核标签列表（tagged list）。
+5、调用内核映像。
+
+
+1、设置和初始化 RAM
+-------------------
+
+现有的引导加载程序:		强制
+新开发的引导加载程序:		强制
+
+引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
+这个操作的执行是设备依赖的。（它可能使用内部算法来自动定位和计算所有
+RAM，或可能使用对这个设备已知的 RAM 信息，还可能使用任何引导装载程序
+设计者想到的匹配方法。）
+
+
+2、初始化一个串口
+-----------------------------
+
+现有的引导加载程序:		可选、建议
+新开发的引导加载程序:		可选、建议
+
+引导加载程序应该初始化并使能一个目标板上的串口。这允许内核串口驱动
+自动检测哪个串口用于内核控制台。(一般用于调试或与目标板通信。)
+
+作为替代方案，引导加载程序也可以通过标签列表传递相关的'console='
+选项给内核以指定某个串口，而串口数据格式的选项在以下文档中描述：
+
+       Documentation/admin-guide/kernel-parameters.rst。
+
+
+3、检测机器类型
+--------------------------
+
+现有的引导加载程序:		可选
+新开发的引导加载程序:		强制
+
+引导加载程序应该通过某些方式检测自身所处的机器类型。这是一个硬件
+代码或通过查看所连接的硬件用某些算法得到，这些超出了本文档的范围。
+引导加载程序最终必须能提供一个 MACH_TYPE_xxx 值给内核。
+(详见 linux/arch/arm/tools/mach-types )。
+
+4、设置启动数据
+------------------
+
+现有的引导加载程序:		可选、强烈建议
+新开发的引导加载程序:		强制
+
+引导加载程序必须提供标签列表或者 dtb 映像以传递配置数据给内核。启动
+数据的物理地址通过寄存器 r2 传递给内核。
+
+4a、设置内核标签列表
+--------------------------------
+
+bootloader 必须创建和初始化内核标签列表。一个有效的标签列表以
+ATAG_CORE 标签开始，并以 ATAG_NONE 标签结束。ATAG_CORE 标签可以是
+空的，也可以是非空。一个空 ATAG_CORE 标签其 size 域设置为
+‘2’(0x00000002)。ATAG_NONE 标签的 size 域必须设置为零。
+
+在列表中可以保存任意数量的标签。对于一个重复的标签是追加到之前标签
+所携带的信息之后，还是会覆盖原来的信息，是未定义的。某些标签的行为
+是前者，其他是后者。
+
+bootloader 必须传递一个系统内存的位置和最小值，以及根文件系统位置。
+因此，最小的标签列表如下所示：
+
+		+-----------+
+基地址 ->	| ATAG_CORE |  |
+		+-----------+  |
+		| ATAG_MEM  |  | 地址增长方向
+		+-----------+  |
+		| ATAG_NONE |  |
+		+-----------+  v
+
+标签列表应该保存在系统的 RAM 中。
+
+标签列表必须置于内核自解压和 initrd'bootp' 程序都不会覆盖的内存区。
+建议放在 RAM 的头 16KiB 中。
+
+4b、设置设备树
+-------------------------
+
+bootloader 必须以 64bit 地址对齐的形式加载一个设备树映像(dtb)到系统
+RAM 中，并用启动数据初始化它。dtb 格式在文档
+Documentation/devicetree/booting-without-of.txt 中。内核将会在
+dtb 物理地址处查找 dtb 魔数值（0xd00dfeed），以确定 dtb 是否已经代替
+标签列表被传递进来。
+
+bootloader 必须传递一个系统内存的位置和最小值，以及根文件系统位置。
+dtb 必须置于内核自解压不会覆盖的内存区。建议将其放置于 RAM 的头 16KiB
+中。但是不可将其放置于“0”物理地址处，因为内核认为：r2 中为 0，意味着
+没有标签列表和 dtb 传递过来。
+
+5、调用内核映像
+---------------------------
+
+现有的引导加载程序:		强制
+新开发的引导加载程序:		强制
+
+调用内核映像 zImage 有两个选择。如果 zImge 保存在 flash 中，且是为了
+在 flash 中直接运行而被正确链接的。这样引导加载程序就可以在 flash 中
+直接调用 zImage。
+
+zImage 也可以被放在系统 RAM（任意位置）中被调用。注意：内核使用映像
+基地址的前 16KB RAM 空间来保存页表。建议将映像置于 RAM 的 32KB 处。
+
+对于以上任意一种情况，都必须符合以下启动状态：
+
+- 停止所有 DMA 设备，这样内存数据就不会因为虚假网络包或磁盘数据而被破坏。
+  这可能可以节省你许多的调试时间。
+
+- CPU 寄存器配置
+  r0 = 0，
+  r1 = （在上面 3 中获取的）机器类型码。
+  r2 = 标签列表在系统 RAM 中的物理地址，或
+       设备树块(dtb)在系统 RAM 中的物理地址
+
+- CPU 模式
+  所有形式的中断必须被禁止 (IRQs 和 FIQs)
+  CPU 必须处于 SVC 模式。(对于 Angel 调试有特例存在)
+
+- 缓存，MMUs
+  MMU 必须关闭。
+  指令缓存开启或关闭都可以。
+  数据缓存必须关闭。
+
+- 引导加载程序应该通过直接跳转到内核映像的第一条指令来调用内核映像。
+
+  对于支持 ARM 指令集的 CPU，跳入内核入口时必须处在 ARM 状态，即使
+  对于 Thumb-2 内核也是如此。
+
+  对于仅支持 Thumb 指令集的 CPU，比如 Cortex-M 系列的 CPU，跳入
+  内核入口时必须处于 Thumb 状态。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm/kernel_user_helpers.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,284 @@
+Chinese translated version of Documentation/arm/kernel_user_helpers.txt
+
+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.
+
+Maintainer: Nicolas Pitre <nicolas.pitre@linaro.org>
+		Dave Martin <dave.martin@linaro.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm/kernel_user_helpers.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Nicolas Pitre <nicolas.pitre@linaro.org>
+		Dave Martin <dave.martin@linaro.org>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
+		傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+内核提供的用户空间辅助代码
+=========================
+
+在内核内存空间的固定地址处，有一个由内核提供并可从用户空间访问的代码
+段。它用于向用户空间提供因在许多 ARM CPU 中未实现的特性和/或指令而需
+内核提供帮助的某些操作。这些代码直接在用户模式下执行的想法是为了获得
+最佳效率，但那些与内核计数器联系过于紧密的部分，则被留给了用户库实现。
+事实上，此代码甚至可能因不同的 CPU 而异，这取决于其可用的指令集或它
+是否为 SMP 系统。换句话说，内核保留在不作出警告的情况下根据需要更改
+这些代码的权利。只有本文档描述的入口及其结果是保证稳定的。
+
+这与完全成熟的 VDSO 实现不同（但两者并不冲突），尽管如此，VDSO 可阻止
+某些通过常量高效跳转到那些代码段的汇编技巧。且由于那些代码段在返回用户
+代码前仅使用少量的代码周期，则一个 VDSO 间接远程调用将会在这些简单的
+操作上增加一个可测量的开销。
+
+在对那些拥有原生支持的新型处理器进行代码优化时，仅在已为其他操作使用
+了类似的新增指令，而导致二进制结果已与早期 ARM 处理器不兼容的情况下，
+用户空间才应绕过这些辅助代码，并在内联函数中实现这些操作（无论是通过
+编译器在代码中直接放置，还是作为库函数调用实现的一部分）。也就是说，
+如果你编译的代码不会为了其他目的使用新指令，则不要仅为了避免使用这些
+内核辅助代码，导致二进制程序无法在早期处理器上运行。
+
+新的辅助代码可能随着时间的推移而增加，所以新内核中的某些辅助代码在旧
+内核中可能不存在。因此，程序必须在对任何辅助代码调用假设是安全之前，
+检测 __kuser_helper_version 的值（见下文）。理想情况下，这种检测应该
+只在进程启动时执行一次；如果内核版本不支持所需辅助代码，则该进程可尽早
+中止执行。
+
+kuser_helper_version
+--------------------
+
+位置:	0xffff0ffc
+
+参考声明:
+
+  extern int32_t __kuser_helper_version;
+
+定义:
+
+  这个区域包含了当前运行内核实现的辅助代码版本号。用户空间可以通过读
+  取此版本号以确定特定的辅助代码是否存在。
+
+使用范例:
+
+#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
+
+void check_kuser_version(void)
+{
+	if (__kuser_helper_version < 2) {
+		fprintf(stderr, "can't do atomic operations, kernel too old\n");
+		abort();
+	}
+}
+
+注意:
+
+  用户空间可以假设这个域的值不会在任何单个进程的生存期内改变。也就
+  是说，这个域可以仅在库的初始化阶段或进程启动阶段读取一次。
+
+kuser_get_tls
+-------------
+
+位置:	0xffff0fe0
+
+参考原型:
+
+  void * __kuser_get_tls(void);
+
+输入:
+
+  lr = 返回地址
+
+输出:
+
+  r0 = TLS 值
+
+被篡改的寄存器:
+
+  无
+
+定义:
+
+  获取之前通过 __ARM_NR_set_tls 系统调用设置的 TLS 值。
+
+使用范例:
+
+typedef void * (__kuser_get_tls_t)(void);
+#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
+
+void foo()
+{
+	void *tls = __kuser_get_tls();
+	printf("TLS = %p\n", tls);
+}
+
+注意:
+
+  - 仅在 __kuser_helper_version >= 1 时，此辅助代码存在
+    （从内核版本 2.6.12 开始）。
+
+kuser_cmpxchg
+-------------
+
+位置:	0xffff0fc0
+
+参考原型:
+
+  int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
+
+输入:
+
+  r0 = oldval
+  r1 = newval
+  r2 = ptr
+  lr = 返回地址
+
+输出:
+
+  r0 = 成功代码 (零或非零)
+  C flag = 如果 r0 == 0 则置 1，如果 r0 != 0 则清零。
+
+被篡改的寄存器:
+
+  r3, ip, flags
+
+定义:
+
+  仅在 *ptr 为 oldval 时原子保存 newval 于 *ptr 中。
+  如果 *ptr 被改变，则返回值为零，否则为非零值。
+  如果 *ptr 被改变，则 C flag 也会被置 1，以实现调用代码中的汇编
+  优化。
+
+使用范例:
+
+typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
+#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
+
+int atomic_add(volatile int *ptr, int val)
+{
+	int old, new;
+
+	do {
+		old = *ptr;
+		new = old + val;
+	} while(__kuser_cmpxchg(old, new, ptr));
+
+	return new;
+}
+
+注意:
+
+  - 这个例程已根据需要包含了内存屏障。
+
+  - 仅在 __kuser_helper_version >= 2 时，此辅助代码存在
+    （从内核版本 2.6.12 开始）。
+
+kuser_memory_barrier
+--------------------
+
+位置:	0xffff0fa0
+
+参考原型:
+
+  void __kuser_memory_barrier(void);
+
+输入:
+
+  lr = 返回地址
+
+输出:
+
+  无
+
+被篡改的寄存器:
+
+  无
+
+定义:
+
+  应用于任何需要内存屏障以防止手动数据修改带来的一致性问题，以及
+  __kuser_cmpxchg 中。
+
+使用范例:
+
+typedef void (__kuser_dmb_t)(void);
+#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
+
+注意:
+
+  - 仅在 __kuser_helper_version >= 3 时，此辅助代码存在
+    （从内核版本 2.6.15 开始）。
+
+kuser_cmpxchg64
+---------------
+
+位置:	0xffff0f60
+
+参考原型:
+
+  int __kuser_cmpxchg64(const int64_t *oldval,
+                        const int64_t *newval,
+                        volatile int64_t *ptr);
+
+输入:
+
+  r0 = 指向 oldval
+  r1 = 指向 newval
+  r2 = 指向目标值
+  lr = 返回地址
+
+输出:
+
+  r0 = 成功代码 (零或非零)
+  C flag = 如果 r0 == 0 则置 1，如果 r0 != 0 则清零。
+
+被篡改的寄存器:
+
+  r3, lr, flags
+
+定义:
+
+  仅在 *ptr 等于 *oldval 指向的 64 位值时，原子保存 *newval
+  指向的 64 位值于 *ptr 中。如果 *ptr 被改变，则返回值为零，
+  否则为非零值。
+
+  如果 *ptr 被改变，则 C flag 也会被置 1，以实现调用代码中的汇编
+  优化。
+
+使用范例:
+
+typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
+                                  const int64_t *newval,
+                                  volatile int64_t *ptr);
+#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
+
+int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
+{
+	int64_t old, new;
+
+	do {
+		old = *ptr;
+		new = old + val;
+	} while(__kuser_cmpxchg64(&old, &new, ptr));
+
+	return new;
+}
+
+注意:
+
+  - 这个例程已根据需要包含了内存屏障。
+
+  - 由于这个过程的代码长度（此辅助代码跨越 2 个常规的 kuser “槽”），
+    因此 0xffff0f80 不被作为有效的入口点。
+
+  - 仅在 __kuser_helper_version >= 5 时，此辅助代码存在
+    （从内核版本 3.1 开始）。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/booting.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/booting.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/booting.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/booting.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,246 @@
+Chinese translated version of Documentation/arm64/booting.txt
+
+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.
+
+M:	Will Deacon <will.deacon@arm.com>
+zh_CN:	Fu Wei <wefu@redhat.com>
+C:	55f058e7574c3615dea4615573a19bdb258696c6
+---------------------------------------------------------------------
+Documentation/arm64/booting.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Will Deacon <will.deacon@arm.com>
+中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
+本文翻译提交时的 Git 检出点为： 55f058e7574c3615dea4615573a19bdb258696c6
+
+以下为正文
+---------------------------------------------------------------------
+			启动 AArch64 Linux
+			==================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2012 年 09 月 07 日
+
+本文档基于 Russell King 的 ARM 启动文档，且适用于所有公开发布的
+AArch64 Linux 内核代码。
+
+AArch64 异常模型由多个异常级（EL0 - EL3）组成，对于 EL0 和 EL1 异常级
+有对应的安全和非安全模式。EL2 是系统管理级，且仅存在于非安全模式下。
+EL3 是最高特权级，且仅存在于安全模式下。
+
+基于本文档的目的，我们将简单地使用‘引导装载程序’（‘boot loader’）
+这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。
+这可能包含安全监控和系统管理代码，或者它可能只是一些用于准备最小启动
+环境的指令。
+
+基本上，引导装载程序（至少）应实现以下操作：
+
+1、设置和初始化 RAM
+2、设置设备树数据
+3、解压内核映像
+4、调用内核映像
+
+
+1、设置和初始化 RAM
+-----------------
+
+必要性: 强制
+
+引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
+这个操作的执行方式因设备而异。（它可能使用内部算法来自动定位和计算所有
+RAM，或可能使用对这个设备已知的 RAM 信息，还可能是引导装载程序设计者
+想到的任何合适的方法。）
+
+
+2、设置设备树数据
+---------------
+
+必要性: 强制
+
+设备树数据块（dtb）必须 8 字节对齐，且大小不能超过 2MB。由于设备树
+数据块将在使能缓存的情况下以 2MB 粒度被映射，故其不能被置于带任意
+特定属性被映射的 2MB 区域内。
+
+注： v4.2 之前的版本同时要求设备树数据块被置于从内核映像以下
+text_offset 字节处算起第一个 512MB 内。
+
+3、解压内核映像
+-------------
+
+必要性: 可选
+
+AArch64 内核当前没有提供自解压代码，因此如果使用了压缩内核映像文件
+（比如 Image.gz），则需要通过引导装载程序（使用 gzip 等）来进行解压。
+若引导装载程序没有实现这个功能，就要使用非压缩内核映像文件。
+
+
+4、调用内核映像
+-------------
+
+必要性: 强制
+
+已解压的内核映像包含一个 64 字节的头，内容如下：
+
+  u32 code0;			/* 可执行代码 */
+  u32 code1;			/* 可执行代码 */
+  u64 text_offset;		/* 映像装载偏移，小端模式 */
+  u64 image_size;		/* 映像实际大小, 小端模式 */
+  u64 flags;			/* 内核旗标, 小端模式 *
+  u64 res2	= 0;		/* 保留 */
+  u64 res3	= 0;		/* 保留 */
+  u64 res4	= 0;		/* 保留 */
+  u32 magic	= 0x644d5241;	/* 魔数, 小端, "ARM\x64" */
+  u32 res5;			/* 保留 （用于 PE COFF 偏移） */
+
+
+映像头注释：
+
+- 自 v3.17 起，除非另有说明，所有域都是小端模式。
+
+- code0/code1 负责跳转到 stext.
+
+- 当通过 EFI 启动时， 最初 code0/code1 被跳过。
+  res5 是到 PE 文件头的偏移，而 PE 文件头含有 EFI 的启动入口点
+  （efi_stub_entry）。当 stub 代码完成了它的使命，它会跳转到 code0
+  继续正常的启动流程。
+
+- v3.17 之前，未明确指定 text_offset 的字节序。此时，image_size 为零，
+  且 text_offset 依照内核字节序为 0x80000。
+  当 image_size 非零，text_offset 为小端模式且是有效值，应被引导加载
+  程序使用。当 image_size 为零，text_offset 可假定为 0x80000。
+
+- flags 域 (v3.17 引入) 为 64 位小端模式，其编码如下：
+  位 0: 	内核字节序。 1 表示大端模式，0 表示小端模式。
+  位 1-2:	内核页大小。
+			0 - 未指定。
+			1 - 4K
+			2 - 16K
+			3 - 64K
+  位 3:		内核物理位置
+			0 - 2MB 对齐基址应尽量靠近内存起始处，因为
+			    其基址以下的内存无法通过线性映射访问
+			1 - 2MB 对齐基址可以在物理内存的任意位置
+  位 4-63:	保留。
+
+- 当 image_size 为零时，引导装载程序应试图在内核映像末尾之后尽可能
+  多地保留空闲内存供内核直接使用。对内存空间的需求量因所选定的内核
+  特性而异, 并无实际限制。
+
+内核映像必须被放置在任意一个可用系统内存 2MB 对齐基址的 text_offset
+字节处，并从该处被调用。2MB 对齐基址和内核映像起始地址之间的区域对于
+内核来说没有特殊意义，且可能被用于其他目的。
+从映像起始地址算起，最少必须准备 image_size 字节的空闲内存供内核使用。
+注： v4.6 之前的版本无法使用内核映像物理偏移以下的内存，所以当时建议
+将映像尽量放置在靠近系统内存起始的地方。
+
+任何提供给内核的内存（甚至在映像起始地址之前），若未从内核中标记为保留
+(如在设备树（dtb）的 memreserve 区域），都将被认为对内核是可用。
+
+在跳转入内核前，必须符合以下状态：
+
+- 停止所有 DMA 设备，这样内存数据就不会因为虚假网络包或磁盘数据而
+  被破坏。这可能可以节省你许多的调试时间。
+
+- 主 CPU 通用寄存器设置
+  x0 = 系统 RAM 中设备树数据块（dtb）的物理地址。
+  x1 = 0 (保留，将来可能使用)
+  x2 = 0 (保留，将来可能使用)
+  x3 = 0 (保留，将来可能使用)
+
+- CPU 模式
+  所有形式的中断必须在 PSTATE.DAIF 中被屏蔽（Debug、SError、IRQ
+  和 FIQ）。
+  CPU 必须处于 EL2（推荐，可访问虚拟化扩展）或非安全 EL1 模式下。
+
+- 高速缓存、MMU
+  MMU 必须关闭。
+  指令缓存开启或关闭皆可。
+  已载入的内核映像的相应内存区必须被清理，以达到缓存一致性点（PoC）。
+  当存在系统缓存或其他使能缓存的一致性主控器时，通常需使用虚拟地址
+  维护其缓存，而非 set/way 操作。
+  遵从通过虚拟地址操作维护构架缓存的系统缓存必须被配置，并可以被使能。
+  而不通过虚拟地址操作维护构架缓存的系统缓存（不推荐），必须被配置且
+  禁用。
+
+  *译者注：对于 PoC 以及缓存相关内容，请参考 ARMv8 构架参考手册
+   ARM DDI 0487A
+
+- 架构计时器
+  CNTFRQ 必须设定为计时器的频率，且 CNTVOFF 必须设定为对所有 CPU
+  都一致的值。如果在 EL1 模式下进入内核，则 CNTHCTL_EL2 中的
+  EL1PCTEN (bit 0) 必须置位。
+
+- 一致性
+  通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。
+  这可能要根据具体实现来定义初始化过程，以使能每个CPU上对维护操作的
+  接收。
+
+- 系统寄存器
+  在进入内核映像的异常级中，所有构架中可写的系统寄存器必须通过软件
+  在一个更高的异常级别下初始化，以防止在 未知 状态下运行。
+
+  对于拥有 GICv3 中断控制器并以 v3 模式运行的系统：
+  - 如果 EL3 存在：
+    ICC_SRE_EL3.Enable (位 3) 必须初始化为 0b1。
+    ICC_SRE_EL3.SRE (位 0) 必须初始化为 0b1。
+  - 若内核运行在 EL1：
+    ICC_SRE_EL2.Enable (位 3) 必须初始化为 0b1。
+    ICC_SRE_EL2.SRE (位 0) 必须初始化为 0b1。
+  - 设备树（DT）或 ACPI 表必须描述一个 GICv3 中断控制器。
+
+  对于拥有 GICv3 中断控制器并以兼容（v2）模式运行的系统：
+  - 如果 EL3 存在：
+    ICC_SRE_EL3.SRE (位 0) 必须初始化为 0b0。
+  - 若内核运行在 EL1：
+    ICC_SRE_EL2.SRE (位 0) 必须初始化为 0b0。
+  - 设备树（DT）或 ACPI 表必须描述一个 GICv2 中断控制器。
+
+以上对于 CPU 模式、高速缓存、MMU、架构计时器、一致性、系统寄存器的
+必要条件描述适用于所有 CPU。所有 CPU 必须在同一异常级别跳入内核。
+
+引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口：
+
+- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树
+  数据块必须在每个 CPU 节点中包含一个 ‘enable-method’ 属性，所
+  支持的 enable-method 请见下文。
+
+  引导装载程序必须生成这些设备树属性，并在跳入内核入口之前将其插入
+  数据块。
+
+- enable-method 为 “spin-table” 的 CPU 必须在它们的 CPU
+  节点中包含一个 ‘cpu-release-addr’ 属性。这个属性标识了一个
+  64 位自然对齐且初始化为零的内存位置。
+
+  这些 CPU 必须在内存保留区（通过设备树中的 /memreserve/ 域传递
+  给内核）中自旋于内核之外，轮询它们的 cpu-release-addr 位置（必须
+  包含在保留区中）。可通过插入 wfe 指令来降低忙循环开销，而主 CPU 将
+  发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值
+  时，CPU 必须跳入此值所指向的地址。此值为一个单独的 64 位小端值，
+  因此 CPU 须在跳转前将所读取的值转换为其本身的端模式。
+
+- enable-method 为 “psci” 的 CPU 保持在内核外（比如，在
+  memory 节点中描述为内核空间的内存区外，或在通过设备树 /memreserve/
+  域中描述为内核保留区的空间中）。内核将会发起在 ARM 文档（编号
+  ARM DEN 0022A：用于 ARM 上的电源状态协调接口系统软件）中描述的
+  CPU_ON 调用来将 CPU 带入内核。
+
+  *译者注: ARM DEN 0022A 已更新到 ARM DEN 0022C。
+
+  设备树必须包含一个 ‘psci’ 节点，请参考以下文档：
+  Documentation/devicetree/bindings/arm/psci.txt
+
+
+- 辅助 CPU 通用寄存器设置
+  x0 = 0 (保留，将来可能使用)
+  x1 = 0 (保留，将来可能使用)
+  x2 = 0 (保留，将来可能使用)
+  x3 = 0 (保留，将来可能使用)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/legacy_instructions.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/legacy_instructions.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/legacy_instructions.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/legacy_instructions.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,72 @@
+Chinese translated version of Documentation/arm64/legacy_instructions.txt
+
+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.
+
+Maintainer: Punit Agrawal <punit.agrawal@arm.com>
+            Suzuki K. Poulose <suzuki.poulose@arm.com>
+Chinese maintainer: Fu Wei <wefu@redhat.com>
+---------------------------------------------------------------------
+Documentation/arm64/legacy_instructions.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+本文翻译提交时的 Git 检出点为： bc465aa9d045feb0e13b4a8f32cc33c1943f62d6
+
+英文版维护者： Punit Agrawal <punit.agrawal@arm.com>
+            Suzuki K. Poulose <suzuki.poulose@arm.com>
+中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
+
+以下为正文
+---------------------------------------------------------------------
+Linux 内核在 arm64 上的移植提供了一个基础框架，以支持构架中正在被淘汰或已废弃指令的模拟执行。
+这个基础框架的代码使用未定义指令钩子（hooks）来支持模拟。如果指令存在，它也允许在硬件中启用该指令。
+
+模拟模式可通过写 sysctl 节点（/proc/sys/abi）来控制。
+不同的执行方式及 sysctl 节点的相应值，解释如下：
+
+* Undef（未定义）
+  值： 0
+  产生未定义指令终止异常。它是那些构架中已废弃的指令，如 SWP，的默认处理方式。
+
+* Emulate（模拟）
+  值： 1
+  使用软件模拟方式。为解决软件迁移问题，这种模拟指令模式的使用是被跟踪的，并会发出速率限制警告。
+  它是那些构架中正在被淘汰的指令，如 CP15 barriers（隔离指令），的默认处理方式。
+
+* Hardware Execution（硬件执行）
+  值： 2
+  虽然标记为正在被淘汰，但一些实现可能提供硬件执行这些指令的使能/禁用操作。
+  使用硬件执行一般会有更好的性能，但将无法收集运行时对正被淘汰指令的使用统计数据。
+
+默认执行模式依赖于指令在构架中状态。正在被淘汰的指令应该以模拟（Emulate）作为默认模式，
+而已废弃的指令必须默认使用未定义（Undef）模式
+
+注意：指令模拟可能无法应对所有情况。更多详情请参考单独的指令注释。
+
+受支持的遗留指令
+-------------
+* SWP{B}
+节点: /proc/sys/abi/swp
+状态: 已废弃
+默认执行方式: Undef (0)
+
+* CP15 Barriers
+节点: /proc/sys/abi/cp15_barrier
+状态: 正被淘汰，不推荐使用
+默认执行方式: Emulate (1)
+
+* SETEND
+节点: /proc/sys/abi/setend
+状态: 正被淘汰，不推荐使用
+默认执行方式: Emulate (1)*
+注：为了使能这个特性，系统中的所有 CPU 必须在 EL0 支持混合字节序。
+如果一个新的 CPU （不支持混合字节序） 在使能这个特性后被热插入系统，
+在应用中可能会出现不可预期的结果。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/memory.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/memory.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/memory.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/memory.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,114 @@
+Chinese translated version of Documentation/arm64/memory.txt
+
+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.
+
+Maintainer: Catalin Marinas <catalin.marinas@arm.com>
+Chinese maintainer: Fu Wei <wefu@redhat.com>
+---------------------------------------------------------------------
+Documentation/arm64/memory.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+本文翻译提交时的 Git 检出点为： bc465aa9d045feb0e13b4a8f32cc33c1943f62d6
+
+英文版维护者： Catalin Marinas <catalin.marinas@arm.com>
+中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
+
+以下为正文
+---------------------------------------------------------------------
+		     Linux 在 AArch64 中的内存布局
+		     ===========================
+
+作者: Catalin Marinas <catalin.marinas@arm.com>
+
+本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现
+页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。
+
+AArch64 Linux 使用 3 级或 4 级转换表，其页大小配置为 4KB，对于用户和内核
+分别都有 39-bit (512GB) 或 48-bit (256TB) 的虚拟地址空间。
+对于页大小为 64KB的配置，仅使用 2 级转换表，有 42-bit (4TB) 的虚拟地址空间，但内存布局相同。
+
+用户地址空间的 63:48 位为 0，而内核地址空间的相应位为 1。TTBRx 的
+选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核（全局）映射，
+而用户 pgd 仅包含用户（非全局）映射。swapper_pg_dir 地址被写入
+TTBR1 中，且从不写入 TTBR0。
+
+
+AArch64 Linux 在页大小为 4KB，并使用 3 级转换表时的内存布局：
+
+起始地址			结束地址			大小		用途
+-----------------------------------------------------------------------
+0000000000000000	0000007fffffffff	 512GB		用户空间
+ffffff8000000000	ffffffffffffffff	 512GB		内核空间
+
+
+AArch64 Linux 在页大小为 4KB，并使用 4 级转换表时的内存布局：
+
+起始地址			结束地址			大小		用途
+-----------------------------------------------------------------------
+0000000000000000	0000ffffffffffff	 256TB		用户空间
+ffff000000000000	ffffffffffffffff	 256TB		内核空间
+
+
+AArch64 Linux 在页大小为 64KB，并使用 2 级转换表时的内存布局：
+
+起始地址			结束地址			大小		用途
+-----------------------------------------------------------------------
+0000000000000000	000003ffffffffff	   4TB		用户空间
+fffffc0000000000	ffffffffffffffff	   4TB		内核空间
+
+
+AArch64 Linux 在页大小为 64KB，并使用 3 级转换表时的内存布局：
+
+起始地址			结束地址			大小		用途
+-----------------------------------------------------------------------
+0000000000000000	0000ffffffffffff	 256TB		用户空间
+ffff000000000000	ffffffffffffffff	 256TB		内核空间
+
+
+更详细的内核虚拟内存布局，请参阅内核启动信息。
+
+
+4KB 页大小的转换表查找：
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |         |         |         |         |
+ |                 |         |         |         |         v
+ |                 |         |         |         |   [11:0]  页内偏移
+ |                 |         |         |         +-> [20:12] L3 索引
+ |                 |         |         +-----------> [29:21] L2 索引
+ |                 |         +---------------------> [38:30] L1 索引
+ |                 +-------------------------------> [47:39] L0 索引
+ +-------------------------------------------------> [63] TTBR0/1
+
+
+64KB 页大小的转换表查找：
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |    |               |              |
+ |                 |    |               |              v
+ |                 |    |               |            [15:0]  页内偏移
+ |                 |    |               +----------> [28:16] L3 索引
+ |                 |    +--------------------------> [41:29] L2 索引
+ |                 +-------------------------------> [47:42] L1 索引
+ +-------------------------------------------------> [63] TTBR0/1
+
+
+当使用 KVM 时, 管理程序（hypervisor）在 EL2 中通过相对内核虚拟地址的
+一个固定偏移来映射内核页（内核虚拟地址的高 24 位设为零）:
+
+起始地址			结束地址			大小		用途
+-----------------------------------------------------------------------
+0000004000000000	0000007fffffffff	 256GB		在 HYP 中映射的内核对象
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/silicon-errata.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/silicon-errata.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/silicon-errata.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/silicon-errata.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,74 @@
+Chinese translated version of Documentation/arm64/silicon-errata.txt
+
+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.
+
+M:	Will Deacon <will.deacon@arm.com>
+zh_CN:	Fu Wei <wefu@redhat.com>
+C:	1926e54f115725a9248d0c4c65c22acaf94de4c4
+---------------------------------------------------------------------
+Documentation/arm64/silicon-errata.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Will Deacon <will.deacon@arm.com>
+中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
+本文翻译提交时的 Git 检出点为： 1926e54f115725a9248d0c4c65c22acaf94de4c4
+
+以下为正文
+---------------------------------------------------------------------
+                芯片勘误和软件补救措施
+                ==================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2015年11月27日
+
+一个不幸的现实：硬件经常带有一些所谓的“瑕疵（errata）”，导致其在
+某些特定情况下会违背构架定义的行为。就基于 ARM 的硬件而言，这些瑕疵
+大体可分为以下几类：
+
+  A 类：无可行补救措施的严重缺陷。
+  B 类：有可接受的补救措施的重大或严重缺陷。
+  C 类：在正常操作中不会显现的小瑕疵。
+
+更多资讯，请在 infocenter.arm.com （需注册）中查阅“软件开发者勘误
+笔记”（“Software Developers Errata Notice”）文档。
+
+对于 Linux 而言，B 类缺陷可能需要操作系统的某些特别处理。例如，避免
+一个特殊的代码序列，或是以一种特定的方式配置处理器。在某种不太常见的
+情况下，为将 A 类缺陷当作 C 类处理，可能需要用类似的手段。这些手段被
+统称为“软件补救措施”，且仅在少数情况需要（例如，那些需要一个运行在
+非安全异常级的补救措施 *并且* 能被 Linux 触发的情况）。
+
+对于尚在讨论中的可能对未受瑕疵影响的系统产生干扰的软件补救措施，有一个
+相应的内核配置（Kconfig）选项被加在 “内核特性（Kernel Features）”->
+“基于可选方法框架的 ARM 瑕疵补救措施（ARM errata workarounds via
+the alternatives framework）"。这些选项被默认开启，若探测到受影响的CPU，
+补丁将在运行时被使用。至于对系统运行影响较小的补救措施，内核配置选项
+并不存在，且代码以某种规避瑕疵的方式被构造（带注释为宜）。
+
+这种做法对于在任意内核源代码树中准确地判断出哪个瑕疵已被软件方法所补救
+稍微有点麻烦，所以在 Linux 内核中此文件作为软件补救措施的注册表，
+并将在新的软件补救措施被提交和向后移植（backported）到稳定内核时被更新。
+
+| 实现者         | 受影响的组件    | 勘误编号        | 内核配置                |
++----------------+-----------------+-----------------+-------------------------+
+| ARM            | Cortex-A53      | #826319         | ARM64_ERRATUM_826319    |
+| ARM            | Cortex-A53      | #827319         | ARM64_ERRATUM_827319    |
+| ARM            | Cortex-A53      | #824069         | ARM64_ERRATUM_824069    |
+| ARM            | Cortex-A53      | #819472         | ARM64_ERRATUM_819472    |
+| ARM            | Cortex-A53      | #845719         | ARM64_ERRATUM_845719    |
+| ARM            | Cortex-A53      | #843419         | ARM64_ERRATUM_843419    |
+| ARM            | Cortex-A57      | #832075         | ARM64_ERRATUM_832075    |
+| ARM            | Cortex-A57      | #852523         | N/A                     |
+| ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220    |
+|                |                 |                 |                         |
+| Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375    |
+| Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154    |
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/tagged-pointers.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/tagged-pointers.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/arm64/tagged-pointers.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/arm64/tagged-pointers.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,52 @@
+Chinese translated version of Documentation/arm64/tagged-pointers.txt
+
+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.
+
+Maintainer: Will Deacon <will.deacon@arm.com>
+Chinese maintainer: Fu Wei <wefu@redhat.com>
+---------------------------------------------------------------------
+Documentation/arm64/tagged-pointers.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Will Deacon <will.deacon@arm.com>
+中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
+中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
+
+以下为正文
+---------------------------------------------------------------------
+		Linux 在 AArch64 中带标记的虚拟地址
+		=================================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2013 年 06 月 12 日
+
+本文档简述了在 AArch64 地址转换系统中提供的带标记的虚拟地址及其在
+AArch64 Linux 中的潜在用途。
+
+内核提供的地址转换表配置使通过 TTBR0 完成的虚拟地址转换（即用户空间
+映射），其虚拟地址的最高 8 位（63:56）会被转换硬件所忽略。这种机制
+让这些位可供应用程序自由使用，其注意事项如下：
+
+	(1) 内核要求所有传递到 EL1 的用户空间地址带有 0x00 标记。
+	    这意味着任何携带用户空间虚拟地址的系统调用（syscall）
+	    参数 *必须* 在陷入内核前使它们的最高字节被清零。
+
+	(2) 非零标记在传递信号时不被保存。这意味着在应用程序中利用了
+	    标记的信号处理函数无法依赖 siginfo_t 的用户空间虚拟
+	    地址所携带的包含其内部域信息的标记。此规则的一个例外是
+	    当信号是在调试观察点的异常处理程序中产生的，此时标记的
+	    信息将被保存。
+
+	(3) 当使用带标记的指针时需特别留心，因为仅对两个虚拟地址
+	    的高字节，C 编译器很可能无法判断它们是不同的。
+
+此构架会阻止对带标记的 PC 指针的利用，因此在异常返回时，其高字节
+将被设置成一个为 “55” 的扩展符。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/basic_profiling.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/basic_profiling.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/basic_profiling.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/basic_profiling.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,71 @@
+Chinese translated version of Documentation/basic_profiling
+
+If you have any comment or update to the content, please post to LKML directly.
+However, if you have problem communicating in English you can also ask the
+Chinese maintainer for help.  Contact the Chinese maintainer, if this
+translation is outdated or there is problem with translation.
+
+Chinese maintainer: Liang Xie <xieliang@xiaomi.com>
+---------------------------------------------------------------------
+Documentation/basic_profiling的中文翻译
+
+如果想评论或更新本文的内容，请直接发信到LKML。如果你使用英文交流有困难的话，也可
+以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题，请联系中文版维护者。
+
+中文版维护者： 谢良 Liang Xie <xieliang007@gmail.com>
+中文版翻译者： 谢良 Liang Xie <xieliang007@gmail.com>
+中文版校译者：
+以下为正文
+---------------------------------------------------------------------
+
+下面这些说明指令都是非常基础的，如果你想进一步了解请阅读相关专业文档：）
+请不要再在本文档增加新的内容，但可以修复文档中的错误：）(mbligh@aracnet.com)
+感谢John Levon，Dave Hansen等在撰写时的帮助
+
+<test> 用于表示要测量的目标
+请先确保您已经有正确的System.map / vmlinux配置！
+
+对于linux系统来说，配置vmlinuz最容易的方法可能就是使用“make install”，然后修改
+/sbin/installkernel将vmlinux拷贝到/boot目录，而System.map通常是默认安装好的
+
+Readprofile
+-----------
+2.6系列内核需要版本相对较新的readprofile，比如util-linux 2.12a中包含的，可以从:
+
+http://www.kernel.org/pub/linux/utils/util-linux/ 下载
+
+大部分linux发行版已经包含了.
+
+启用readprofile需要在kernel启动命令行增加”profile=2“
+
+clear		readprofile -r
+		<test>
+dump output	readprofile -m /boot/System.map > captured_profile
+
+Oprofile
+--------
+
+从http://oprofile.sourceforge.net/获取源代码（请参考Changes以获取匹配的版本）
+在kernel启动命令行增加“idle=poll”
+
+配置CONFIG_PROFILING=y和CONFIG_OPROFILE=y然后重启进入新kernel
+
+./configure --with-kernel-support
+make install
+
+想得到好的测量结果，请确保启用了本地APIC特性。如果opreport显示有0Hz CPU，
+说明APIC特性没有开启。另外注意idle=poll选项可能有损性能。
+
+One time setup:
+		opcontrol --setup --vmlinux=/boot/vmlinux
+
+clear		opcontrol --reset
+start		opcontrol --start
+		<test>
+stop		opcontrol --stop
+dump output	opreport >  output_file
+
+如果只看kernel相关的报告结果，请运行命令 opreport -l /boot/vmlinux > output_file
+
+通过reset选项可以清理过期统计数据，相当于重启的效果。
+
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/CodingStyle linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/CodingStyle
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/CodingStyle	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/CodingStyle	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,813 @@
+Chinese translated version of Documentation/process/coding-style.rst
+
+If you have any comment or update to the content, please post to LKML directly.
+However, if you have problem communicating in English you can also ask the
+Chinese maintainer for help.  Contact the Chinese maintainer, if this
+translation is outdated or there is problem with translation.
+
+Chinese maintainer: Zhang Le <r0bertz@gentoo.org>
+---------------------------------------------------------------------
+Documentation/process/coding-style.rst的中文翻译
+
+如果想评论或更新本文的内容，请直接发信到LKML。如果你使用英文交流有困难的话，也可
+以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题，请联系中文版维护者。
+
+中文版维护者： 张乐 Zhang Le <r0bertz@gentoo.org>
+中文版翻译者： 张乐 Zhang Le <r0bertz@gentoo.org>
+中文版校译者： 王聪 Wang Cong <xiyou.wangcong@gmail.com>
+               wheelz <kernel.zeng@gmail.com>
+               管旭东 Xudong Guan <xudong.guan@gmail.com>
+               Li Zefan <lizf@cn.fujitsu.com>
+               Wang Chen <wangchen@cn.fujitsu.com>
+以下为正文
+---------------------------------------------------------------------
+
+		Linux内核代码风格
+
+这是一个简短的文档，描述了 linux 内核的首选代码风格。代码风格是因人而异的，而且我
+不愿意把自己的观点强加给任何人，但这就像我去做任何事情都必须遵循的原则那样，我也
+希望在绝大多数事上保持这种的态度。请（在写代码时）至少考虑一下这里的代码风格。
+
+首先，我建议你打印一份 GNU 代码规范，然后不要读。烧了它，这是一个具有重大象征性意义
+的动作。
+
+不管怎样，现在我们开始：
+
+
+		第一章：缩进
+
+制表符是 8 个字符，所以缩进也是 8 个字符。有些异端运动试图将缩进变为 4（甚至 2！）
+个字符深，这几乎相当于尝试将圆周率的值定义为 3。
+
+理由：缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的屏幕
+连续看了 20 小时之后，你将会发现大一点的缩进会使你更容易分辨缩进。
+
+现在，有些人会抱怨 8 个字符的缩进会使代码向右边移动的太远，在 80 个字符的终端屏幕上
+就很难读这样的代码。这个问题的答案是，如果你需要 3 级以上的缩进，不管用何种方式你
+的代码已经有问题了，应该修正你的程序。
+
+简而言之，8 个字符的缩进可以让代码更容易阅读，还有一个好处是当你的函数嵌套太深的
+时候可以给你警告。留心这个警告。
+
+在 switch 语句中消除多级缩进的首选的方式是让 “switch” 和从属于它的 “case” 标签
+对齐于同一列，而不要 “两次缩进” “case” 标签。比如：
+
+	switch (suffix) {
+	case 'G':
+	case 'g':
+		mem <<= 30;
+		break;
+	case 'M':
+	case 'm':
+		mem <<= 20;
+		break;
+	case 'K':
+	case 'k':
+		mem <<= 10;
+		/* fall through */
+	default:
+		break;
+	}
+
+不要把多个语句放在一行里，除非你有什么东西要隐藏：
+
+	if (condition) do_this;
+	  do_something_everytime;
+
+也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读的表
+达式。
+
+除了注释、文档和 Kconfig 之外，不要使用空格来缩进，前面的例子是例外，是有意为之。
+
+选用一个好的编辑器，不要在行尾留空格。
+
+
+		第二章：把长的行和字符串打散
+
+代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。
+
+每一行的长度的限制是 80 列，我们强烈建议您遵守这个惯例。
+
+长于 80 列的语句要打散成有意义的片段。除非超过 80 列能显著增加可读性，并且不会隐藏
+信息。子片段要明显短于母片段，并明显靠右。这同样适用于有着很长参数列表的函数头。
+然而，绝对不要打散对用户可见的字符串，例如 printk 信息，因为这将导致无法 grep 这些
+信息。
+
+		第三章：大括号和空格的放置
+
+C语言风格中另外一个常见问题是大括号的放置。和缩进大小不同，选择或弃用某种放置策
+略并没有多少技术上的原因，不过首选的方式，就像 Kernighan 和 Ritchie 展示给我们的，
+是把起始大括号放在行尾，而把结束大括号放在行首，所以：
+
+	if (x is true) {
+		we do y
+	}
+
+这适用于所有的非函数语句块（if、switch、for、while、do）。比如：
+
+	switch (action) {
+	case KOBJ_ADD:
+		return "add";
+	case KOBJ_REMOVE:
+		return "remove";
+	case KOBJ_CHANGE:
+		return "change";
+	default:
+		return NULL;
+	}
+
+不过，有一个例外，那就是函数：函数的起始大括号放置于下一行的开头，所以：
+
+	int function(int x)
+	{
+		body of function
+	}
+
+全世界的异端可能会抱怨这个不一致性是……呃……不一致的，不过所有思维健全的人都知道
+(a) K&R 是 _正确的_，并且 (b) K&R 是正确的。此外，不管怎样函数都是特殊的（C
+函数是不能嵌套的）。
+
+注意结束大括号独自占据一行，除非它后面跟着同一个语句的剩余部分，也就是 do 语句中的
+“while” 或者 if 语句中的 “else”，像这样：
+
+	do {
+		body of do-loop
+	} while (condition);
+
+和
+
+	if (x == y) {
+		..
+	} else if (x > y) {
+		...
+	} else {
+		....
+	}
+
+理由：K&R。
+
+也请注意这种大括号的放置方式也能使空（或者差不多空的）行的数量最小化，同时不失可
+读性。因此，由于你的屏幕上的新行是不可再生资源（想想 25 行的终端屏幕），你将会有更
+多的空行来放置注释。
+
+当只有一个单独的语句的时候，不用加不必要的大括号。
+
+	if (condition)
+		action();
+
+和
+
+	if (condition)
+		do_this();
+	else
+		do_that();
+
+这并不适用于只有一个条件分支是单语句的情况；这时所有分支都要使用大括号：
+
+	if (condition) {
+		do_this();
+		do_that();
+	} else {
+		otherwise();
+	}
+
+		3.1：空格
+
+Linux 内核的空格使用方式（主要）取决于它是用于函数还是关键字。（大多数）关键字后
+要加一个空格。值得注意的例外是 sizeof、typeof、alignof 和 __attribute__，这些
+关键字某些程度上看起来更像函数（它们在 Linux 里也常常伴随小括号而使用，尽管在 C 里
+这样的小括号不是必需的，就像 “struct fileinfo info” 声明过后的 “sizeof info”）。
+
+所以在这些关键字之后放一个空格：
+
+	if, switch, case, for, do, while
+
+但是不要在 sizeof、typeof、alignof 或者 __attribute__ 这些关键字之后放空格。例如，
+
+	s = sizeof(struct file);
+
+不要在小括号里的表达式两侧加空格。这是一个反例：
+
+	s = sizeof( struct file );
+
+当声明指针类型或者返回指针类型的函数时，“*” 的首选使用方式是使之靠近变量名或者函
+数名，而不是靠近类型名。例子：
+
+	char *linux_banner;
+	unsigned long long memparse(char *ptr, char **retptr);
+	char *match_strdup(substring_t *s);
+
+在大多数二元和三元操作符两侧使用一个空格，例如下面所有这些操作符：
+
+	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
+
+但是一元操作符后不要加空格：
+
+	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
+
+后缀自加和自减一元操作符前不加空格：
+
+	++  --
+
+前缀自加和自减一元操作符后不加空格：
+
+	++  --
+
+‘.’ 和 “->” 结构体成员操作符前后不加空格。
+
+不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白，然后你
+就可以直接在那一行输入代码。不过假如你最后没有在那一行输入代码，有些编辑器就不
+会移除已经加入的空白，就像你故意留下一个只有空白的行。包含行尾空白的行就这样产
+生了。
+
+当git发现补丁包含了行尾空白的时候会警告你，并且可以应你的要求去掉行尾空白；不过
+如果你是正在打一系列补丁，这样做会导致后面的补丁失败，因为你改变了补丁的上下文。
+
+
+		第四章：命名
+
+C是一个简朴的语言，你的命名也应该这样。和 Modula-2 和 Pascal 程序员不同，C 程序员
+不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字。C 程序员会称那个变量
+为 “tmp”，这样写起来会更容易，而且至少不会令其难于理解。
+
+不过，虽然混用大小写的名字是不提倡使用的，但是全局变量还是需要一个具描述性的名字
+。称一个全局函数为 “foo” 是一个难以饶恕的错误。
+
+全局变量（只有当你真正需要它们的时候再用它）需要有一个具描述性的名字，就像全局函
+数。如果你有一个可以计算活动用户数量的函数，你应该叫它 “count_active_users()”
+或者类似的名字，你不应该叫它 “cntuser()”。
+
+在函数名中包含函数类型（所谓的匈牙利命名法）是脑子出了问题——编译器知道那些类型而
+且能够检查那些类型，这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题的程序。
+
+本地变量名应该简短，而且能够表达相关的含义。如果你有一些随机的整数型的循环计数器
+，它应该被称为 “i”。叫它 “loop_counter” 并无益处，如果它没有被误解的可能的话。
+类似的，“tmp” 可以用来称呼任意类型的临时变量。
+
+如果你怕混淆了你的本地变量名，你就遇到另一个问题了，叫做函数增长荷尔蒙失衡综合症
+。请看第六章（函数）。
+
+
+		第五章：Typedef
+
+不要使用类似 “vps_t” 之类的东西。
+
+对结构体和指针使用 typedef 是一个错误。当你在代码里看到：
+
+	vps_t a;
+
+这代表什么意思呢？
+
+相反，如果是这样
+
+	struct virtual_container *a;
+
+你就知道 “a” 是什么了。
+
+很多人认为 typedef “能提高可读性”。实际不是这样的。它们只在下列情况下有用：
+
+ (a) 完全不透明的对象（这种情况下要主动使用 typedef 来隐藏这个对象实际上是什么）。
+
+     例如：“pte_t” 等不透明对象，你只能用合适的访问函数来访问它们。
+
+     注意！不透明性和“访问函数”本身是不好的。我们使用 pte_t 等类型的原因在于真的是
+     完全没有任何共用的可访问信息。
+
+ (b) 清楚的整数类型，如此，这层抽象就可以帮助消除到底是 “int” 还是 “long” 的混淆。
+
+     u8/u16/u32 是完全没有问题的 typedef，不过它们更符合类别 (d) 而不是这里。
+
+     再次注意！要这样做，必须事出有因。如果某个变量是 “unsigned long“，那么没有必要
+
+	typedef unsigned long myflags_t;
+
+     不过如果有一个明确的原因，比如它在某种情况下可能会是一个 “unsigned int” 而在
+     其他情况下可能为 “unsigned long”，那么就不要犹豫，请务必使用 typedef。
+
+ (c) 当你使用sparse按字面的创建一个新类型来做类型检查的时候。
+
+ (d) 和标准C99类型相同的类型，在某些例外的情况下。
+
+     虽然让眼睛和脑筋来适应新的标准类型比如 “uint32_t” 不需要花很多时间，可是有些
+     人仍然拒绝使用它们。
+
+     因此，Linux 特有的等同于标准类型的 “u8/u16/u32/u64” 类型和它们的有符号类型是被
+     允许的——尽管在你自己的新代码中，它们不是强制要求要使用的。
+
+     当编辑已经使用了某个类型集的已有代码时，你应该遵循那些代码中已经做出的选择。
+
+ (e) 可以在用户空间安全使用的类型。
+
+     在某些用户空间可见的结构体里，我们不能要求C99类型而且不能用上面提到的 “u32”
+     类型。因此，我们在与用户空间共享的所有结构体中使用 __u32 和类似的类型。
+
+可能还有其他的情况，不过基本的规则是永远不要使用 typedef，除非你可以明确的应用上
+述某个规则中的一个。
+
+总的来说，如果一个指针或者一个结构体里的元素可以合理的被直接访问到，那么它们就不
+应该是一个 typedef。
+
+
+		第六章：函数
+
+函数应该简短而漂亮，并且只完成一件事情。函数应该可以一屏或者两屏显示完（我们都知
+道 ISO/ANSI 屏幕大小是 80x24），只做一件事情，而且把它做好。
+
+一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。所以，如果你有一个理论上
+很简单的只有一个很长（但是简单）的 case 语句的函数，而且你需要在每个 case 里做
+很多很小的事情，这样的函数尽管很长，但也是可以的。
+
+不过，如果你有一个复杂的函数，而且你怀疑一个天分不是很高的高中一年级学生可能甚至
+搞不清楚这个函数的目的，你应该严格的遵守前面提到的长度限制。使用辅助函数，并为之
+取个具描述性的名字（如果你觉得它们的性能很重要的话，可以让编译器内联它们，这样的
+效果往往会比你写一个复杂函数的效果要好。）
+
+函数的另外一个衡量标准是本地变量的数量。此数量不应超过 5－10 个，否则你的函数就有
+问题了。重新考虑一下你的函数，把它分拆成更小的函数。人的大脑一般可以轻松的同时跟
+踪 7 个不同的事物，如果再增多的话，就会糊涂了。即便你聪颖过人，你也可能会记不清你
+2 个星期前做过的事情。
+
+在源文件里，使用空行隔开不同的函数。如果该函数需要被导出，它的 EXPORT* 宏应该紧贴
+在它的结束大括号之下。比如：
+
+	int system_is_up(void)
+	{
+		return system_state == SYSTEM_RUNNING;
+	}
+	EXPORT_SYMBOL(system_is_up);
+
+在函数原型中，包含函数名和它们的数据类型。虽然C语言里没有这样的要求，在 Linux 里这
+是提倡的做法，因为这样可以很简单的给读者提供更多的有价值的信息。
+
+
+		第七章：集中的函数退出途径
+
+虽然被某些人声称已经过时，但是 goto 语句的等价物还是经常被编译器所使用，具体形式是
+无条件跳转指令。
+
+当一个函数从多个位置退出，并且需要做一些类似清理的常见操作时，goto 语句就很方便了。
+如果并不需要清理操作，那么直接 return 即可。
+
+理由是：
+
+- 无条件语句容易理解和跟踪
+- 嵌套程度减小
+- 可以避免由于修改时忘记更新某个单独的退出点而导致的错误
+- 减轻了编译器的工作，无需删除冗余代码;)
+
+	int fun(int a)
+	{
+		int result = 0;
+		char *buffer;
+
+		buffer = kmalloc(SIZE, GFP_KERNEL);
+		if (!buffer)
+			return -ENOMEM;
+
+		if (condition1) {
+			while (loop1) {
+				...
+			}
+			result = 1;
+			goto out_buffer;
+		}
+		...
+	out_buffer:
+		kfree(buffer);
+		return result;
+	}
+
+一个需要注意的常见错误是“一个 err 错误”，就像这样：
+
+	err:
+		kfree(foo->bar);
+		kfree(foo);
+		return ret;
+
+这段代码的错误是，在某些退出路径上 “foo” 是 NULL。通常情况下，通过把它分离成两个
+错误标签 “err_bar:” 和 “err_foo:” 来修复这个错误。
+
+		第八章：注释
+
+注释是好的，不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的：更好
+的做法是让别人一看你的代码就可以明白，解释写的很差的代码是浪费时间。
+
+一般的，你想要你的注释告诉别人你的代码做了什么，而不是怎么做的。也请你不要把注释
+放在一个函数体内部：如果函数复杂到你需要独立的注释其中的一部分，你很可能需要回到
+第六章看一看。你可以做一些小注释来注明或警告某些很聪明（或者槽糕）的做法，但不要
+加太多。你应该做的，是把注释放在函数的头部，告诉人们它做了什么，也可以加上它做这
+些事情的原因。
+
+当注释内核API函数时，请使用 kernel-doc 格式。请看
+Documentation/doc-guide/和scripts/kernel-doc 以获得详细信息。
+
+Linux的注释风格是 C89 “/* ... */” 风格。不要使用 C99 风格 “// ...” 注释。
+
+长（多行）的首选注释风格是：
+
+	/*
+	 * This is the preferred style for multi-line
+	 * comments in the Linux kernel source code.
+	 * Please use it consistently.
+	 *
+	 * Description:  A column of asterisks on the left side,
+	 * with beginning and ending almost-blank lines.
+	 */
+
+对于在 net/ 和 drivers/net/ 的文件，首选的长（多行）注释风格有些不同。
+
+	/* The preferred comment style for files in net/ and drivers/net
+	 * looks like this.
+	 *
+	 * It is nearly the same as the generally preferred comment style,
+	 * but there is no initial almost-blank line.
+	 */
+
+注释数据也是很重要的，不管是基本类型还是衍生类型。为了方便实现这一点，每一行应只
+声明一个数据（不要使用逗号来一次声明多个数据）。这样你就有空间来为每个数据写一段
+小注释来解释它们的用途了。
+
+
+		第九章：你已经把事情弄糟了
+
+这没什么，我们都是这样。可能你的使用了很长时间 Unix 的朋友已经告诉你 “GNU emacs” 能
+自动帮你格式化 C 源代码，而且你也注意到了，确实是这样，不过它所使用的默认值和我们
+想要的相去甚远（实际上，甚至比随机打的还要差——无数个猴子在 GNU emacs 里打字永远不
+会创造出一个好程序）（译注：请参考 Infinite Monkey Theorem）
+
+所以你要么放弃 GNU emacs，要么改变它让它使用更合理的设定。要采用后一个方案，你可
+以把下面这段粘贴到你的 .emacs 文件里。
+
+(defun c-lineup-arglist-tabs-only (ignored)
+  "Line up argument lists by tabs, not spaces"
+  (let* ((anchor (c-langelem-pos c-syntactic-element))
+         (column (c-langelem-2nd-pos c-syntactic-element))
+         (offset (- (1+ column) anchor))
+         (steps (floor offset c-basic-offset)))
+    (* (max steps 1)
+       c-basic-offset)))
+
+(add-hook 'c-mode-common-hook
+          (lambda ()
+            ;; Add kernel style
+            (c-add-style
+             "linux-tabs-only"
+             '("linux" (c-offsets-alist
+                        (arglist-cont-nonempty
+                         c-lineup-gcc-asm-reg
+                         c-lineup-arglist-tabs-only))))))
+
+(add-hook 'c-mode-hook
+          (lambda ()
+            (let ((filename (buffer-file-name)))
+              ;; Enable kernel mode for the appropriate files
+              (when (and filename
+                         (string-match (expand-file-name "~/src/linux-trees")
+                                       filename))
+                (setq indent-tabs-mode t)
+                (setq show-trailing-whitespace t)
+                (c-set-style "linux-tabs-only")))))
+
+这会让 emacs 在 ~/src/linux-trees 目录下的 C 源文件获得更好的内核代码风格。
+
+不过就算你尝试让 emacs 正确的格式化代码失败了，也并不意味着你失去了一切：还可以用
+“indent”。
+
+不过，GNU indent 也有和 GNU emacs 一样有问题的设定，所以你需要给它一些命令选项。不
+过，这还不算太糟糕，因为就算是 GNU indent 的作者也认同 K&R 的权威性（GNU 的人并不是
+坏人，他们只是在这个问题上被严重的误导了），所以你只要给 indent 指定选项 “-kr -i8”
+（代表 “K&R，8 个字符缩进”），或者使用 “scripts/Lindent”，这样就可以以最时髦的方式
+缩进源代码。
+
+“indent” 有很多选项，特别是重新格式化注释的时候，你可能需要看一下它的手册页。不过
+记住：“indent” 不能修正坏的编程习惯。
+
+
+		第十章：Kconfig 配置文件
+
+对于遍布源码树的所有 Kconfig* 配置文件来说，它们缩进方式与 C 代码相比有所不同。紧挨
+在 “config” 定义下面的行缩进一个制表符，帮助信息则再多缩进 2 个空格。比如：
+
+config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+而那些危险的功能（比如某些文件系统的写支持）应该在它们的提示字符串里显著的声明这
+一点：
+
+config ADFS_FS_RW
+	bool "ADFS write support (DANGEROUS)"
+	depends on ADFS_FS
+	...
+
+要查看配置文件的完整文档，请看 Documentation/kbuild/kconfig-language.txt。
+
+
+		第十一章：数据结构
+
+如果一个数据结构，在创建和销毁它的单线执行环境之外可见，那么它必须要有一个引用计
+数器。内核里没有垃圾收集（并且内核之外的垃圾收集慢且效率低下），这意味着你绝对需
+要记录你对这种数据结构的使用情况。
+
+引用计数意味着你能够避免上锁，并且允许多个用户并行访问这个数据结构——而不需要担心
+这个数据结构仅仅因为暂时不被使用就消失了，那些用户可能不过是沉睡了一阵或者做了一
+些其他事情而已。
+
+注意上锁不能取代引用计数。上锁是为了保持数据结构的一致性，而引用计数是一个内存管
+理技巧。通常二者都需要，不要把两个搞混了。
+
+很多数据结构实际上有2级引用计数，它们通常有不同“类”的用户。子类计数器统计子类用
+户的数量，每当子类计数器减至零时，全局计数器减一。
+
+这种“多级引用计数”的例子可以在内存管理（“struct mm_struct”：mm_users 和 mm_count）
+和文件系统（“struct super_block”：s_count和s_active）中找到。
+
+记住：如果另一个执行线索可以找到你的数据结构，但是这个数据结构没有引用计数器，这
+里几乎肯定是一个 bug。
+
+
+		第十二章：宏，枚举和RTL
+
+用于定义常量的宏的名字及枚举里的标签需要大写。
+
+#define CONSTANT 0x12345
+
+在定义几个相关的常量时，最好用枚举。
+
+宏的名字请用大写字母，不过形如函数的宏的名字可以用小写字母。
+
+一般的，如果能写成内联函数就不要写成像函数的宏。
+
+含有多个语句的宏应该被包含在一个 do-while 代码块里：
+
+	#define macrofun(a, b, c)			\
+		do {					\
+			if (a == 5)			\
+				do_this(b, c);		\
+		} while (0)
+
+使用宏的时候应避免的事情：
+
+1) 影响控制流程的宏：
+
+	#define FOO(x)					\
+		do {					\
+			if (blah(x) < 0)		\
+				return -EBUGGERED;	\
+		} while (0)
+
+非常不好。它看起来像一个函数，不过却能导致“调用”它的函数退出；不要打乱读者大脑里
+的语法分析器。
+
+2) 依赖于一个固定名字的本地变量的宏：
+
+	#define FOO(val) bar(index, val)
+
+可能看起来像是个不错的东西，不过它非常容易把读代码的人搞糊涂，而且容易导致看起来
+不相关的改动带来错误。
+
+3) 作为左值的带参数的宏： FOO(x) = y；如果有人把 FOO 变成一个内联函数的话，这种用
+法就会出错了。
+
+4) 忘记了优先级：使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数的
+宏也要注意此类问题。
+
+	#define CONSTANT 0x4000
+	#define CONSTEXP (CONSTANT | 3)
+
+5) 在宏里定义类似函数的本地变量时命名冲突：
+
+	#define FOO(x)				\
+	({					\
+		typeof(x) ret;			\
+		ret = calc_ret(x);		\
+		(ret);				\
+	})
+
+ret 是本地变量的通用名字 - __foo_ret 更不容易与一个已存在的变量冲突。
+
+cpp 手册对宏的讲解很详细。gcc internals 手册也详细讲解了 RTL（译注：register
+transfer language），内核里的汇编语言经常用到它。
+
+
+		第十三章：打印内核消息
+
+内核开发者应该是受过良好教育的。请一定注意内核信息的拼写，以给人以好的印象。不要
+用不规范的单词比如 “dont”，而要用 “do not”或者 “don't”。保证这些信息简单、明了、
+无歧义。
+
+内核信息不必以句号（译注：英文句号，即点）结束。
+
+在小括号里打印数字 (%d) 没有任何价值，应该避免这样做。
+
+<linux/device.h> 里有一些驱动模型诊断宏，你应该使用它们，以确保信息对应于正确的
+设备和驱动，并且被标记了正确的消息级别。这些宏有：dev_err()，dev_warn()，
+dev_info() 等等。对于那些不和某个特定设备相关连的信息，<linux/printk.h> 定义了
+pr_notice()，pr_info()，pr_warn()，pr_err() 和其他。
+
+写出好的调试信息可以是一个很大的挑战；一旦你写出后，这些信息在远程除错时能提供极大
+的帮助。然而打印调试信息的处理方式同打印非调试信息不同。其他 pr_XXX() 函数能无条件地
+打印，pr_debug() 却不；默认情况下它不会被编译，除非定义了 DEBUG 或设定了
+CONFIG_DYNAMIC_DEBUG。实际这同样是为了 dev_dbg()，一个相关约定是在一个已经开启了
+DEBUG 时，使用 VERBOSE_DEBUG 来添加 dev_vdbg()。
+
+许多子系统拥有 Kconfig 调试选项来开启 -DDEBUG 在对应的 Makefile 里面；在其他
+情况下，特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时，例如，如果
+已经包含一个调试相关的 #ifdef 条件，printk(KERN_DEBUG ...) 就可被使用。
+
+
+		第十四章：分配内存
+
+内核提供了下面的一般用途的内存分配函数：
+kmalloc()，kzalloc()，kmalloc_array()，kcalloc()，vmalloc() 和 vzalloc()。
+请参考 API 文档以获取有关它们的详细信息。
+
+传递结构体大小的首选形式是这样的：
+
+	p = kmalloc(sizeof(*p), ...);
+
+另外一种传递方式中，sizeof 的操作数是结构体的名字，这样会降低可读性，并且可能会引
+入 bug。有可能指针变量类型被改变时，而对应的传递给内存分配函数的 sizeof 的结果不变。
+
+强制转换一个 void 指针返回值是多余的。C 语言本身保证了从 void 指针到其他任何指针类型
+的转换是没有问题的。
+
+分配一个数组的首选形式是这样的：
+
+	p = kmalloc_array(n, sizeof(...), ...);
+
+分配一个零长数组的首选形式是这样的：
+
+	p = kcalloc(n, sizeof(...), ...);
+
+两种形式检查分配大小 n * sizeof(...) 的溢出，如果溢出返回 NULL。
+
+
+		第十五章：内联弊病
+
+有一个常见的误解是内联函数是 gcc 提供的可以让代码运行更快的一个选项。虽然使用内联
+函数有时候是恰当的（比如作为一种替代宏的方式，请看第十二章），不过很多情况下不是
+这样。inline 关键字的过度使用会使内核变大，从而使整个系统运行速度变慢。因为大内核
+会占用更多的指令高速缓存（译注：一级缓存通常是指令缓存和数据缓存分开的）而且会导
+致 pagecache 的可用内存减少。想象一下，一次pagecache未命中就会导致一次磁盘寻址，
+将耗时 5 毫秒。5 毫秒的时间内 CPU 能执行很多很多指令。
+
+一个基本的原则是如果一个函数有 3 行以上，就不要把它变成内联函数。这个原则的一个例
+外是，如果你知道某个参数是一个编译时常量，而且因为这个常量你确定编译器在编译时能
+优化掉你的函数的大部分代码，那仍然可以给它加上 inline 关键字。kmalloc() 内联函数就
+是一个很好的例子。
+
+人们经常主张给 static 的而且只用了一次的函数加上 inline，如此不会有任何损失，因为没
+有什么好权衡的。虽然从技术上说这是正确的，但是实际上这种情况下即使不加 inline gcc
+也可以自动使其内联。而且其他用户可能会要求移除 inline，由此而来的争论会抵消 inline
+自身的潜在价值，得不偿失。
+
+
+		第十六章：函数返回值及命名
+
+函数可以返回很多种不同类型的值，最常见的一种是表明函数执行成功或者失败的值。这样
+的一个值可以表示为一个错误代码整数（-Exxx＝失败，0＝成功）或者一个“成功”布尔值（
+0＝失败，非0＝成功）。
+
+混合使用这两种表达方式是难于发现的 bug 的来源。如果 C 语言本身严格区分整形和布尔型变
+量，那么编译器就能够帮我们发现这些错误……不过 C 语言不区分。为了避免产生这种 bug，请
+遵循下面的惯例：
+
+	如果函数的名字是一个动作或者强制性的命令，那么这个函数应该返回错误代码整
+	数。如果是一个判断，那么函数应该返回一个“成功”布尔值。
+
+比如，“add work” 是一个命令，所以 add_work() 函数在成功时返回 0，在失败时返回 -EBUSY。
+类似的，因为 “PCI device present” 是一个判断，所以 pci_dev_present() 函数在成功找到
+一个匹配的设备时应该返回 1，如果找不到时应该返回 0。
+
+所有导出（译注：EXPORT）的函数都必须遵守这个惯例，所有的公共函数也都应该如此。私
+有（static）函数不需要如此，但是我们也推荐这样做。
+
+返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的，他们
+通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数，他们使用
+NULL 或者 ERR_PTR 机制来报告错误。
+
+
+		第十七章：不要重新发明内核宏
+
+头文件 include/linux/kernel.h 包含了一些宏，你应该使用它们，而不要自己写一些它们的
+变种。比如，如果你需要计算一个数组的长度，使用这个宏
+
+	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+类似的，如果你要计算某结构体成员的大小，使用
+
+	#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+
+还有可以做严格的类型检查的 min() 和 max() 宏，如果你需要可以使用它们。你可以自己看看
+那个头文件里还定义了什么你可以拿来用的东西，如果有定义的话，你就不应在你的代码里
+自己重新定义。
+
+
+		第十八章：编辑器模式行和其他需要罗嗦的事情
+
+有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如，emacs
+能够解释被标记成这样的行：
+
+	-*- mode: c -*-
+
+或者这样的：
+
+	/*
+	Local Variables:
+	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+	End:
+	*/
+
+Vim 能够解释这样的标记：
+
+	/* vim:set sw=8 noet */
+
+不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置，你的源文件不应
+该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制的模
+式，或者使用其他可以产生正确的缩进的巧妙方法。
+
+
+		第十九章：内联汇编
+
+在特定架构的代码中，你也许需要内联汇编来使用 CPU 接口和平台相关功能。在需要
+这么做时，不要犹豫。然而，当 C 可以完成工作时，不要无端地使用内联汇编。如果
+可能，你可以并且应该用 C 和硬件交互。
+
+考虑去写通用一点的内联汇编作为简明的辅助函数，而不是重复写下它们的细节。记住
+内联汇编可以使用 C 参数。
+
+大而特殊的汇编函数应该放在 .S 文件中，对应 C 的原型定义在 C 头文件中。汇编
+函数的 C 原型应该使用 “asmlinkage”。
+
+你可能需要将你的汇编语句标记为 volatile，来阻止 GCC 在没发现任何副作用后就
+移除了它。你不必总是这样做，虽然，这样可以限制不必要的优化。
+
+在写一个包含多条指令的单个内联汇编语句时，把每条指令用引号字符串分离，并写在
+单独一行，在每个字符串结尾，除了 \n\t 结尾之外，在汇编输出中适当地缩进下
+一条指令：
+
+	asm ("magic %reg1, #42\n\t"
+	     "more_magic %reg2, %reg3"
+	     : /* outputs */ : /* inputs */ : /* clobbers */);
+
+
+		第二十章：条件编译
+
+只要可能，就不要在 .c 文件里面使用预处理条件；这样做让代码更难阅读并且逻辑难以
+跟踪。替代方案是，在头文件定义函数在这些 .c 文件中使用这类的条件表达式，提供空
+操作的桩版本（译注：桩程序，是指用来替换一部分功能的程序段）在 #else 情况下，
+再从 .c 文件中无条件地调用这些函数。编译器会避免生成任何桩调用的代码，产生一致
+的结果，但逻辑将更加清晰。
+
+宁可编译整个函数，而不是部分函数或部分表达式。而不是在一个表达式添加 ifdef，
+解析部分或全部表达式到一个单独的辅助函数，并应用条件到该函数内。
+
+如果你有一个在特定配置中可能是未使用的函数或变量，编译器将警告它定义了但未使用，
+标记这个定义为 __maybe_unused 而不是将它包含在一个预处理条件中。（然而，如果
+一个函数或变量总是未使用的，就直接删除它。）
+
+在代码中，可能的情况下，使用 IS_ENABLED 宏来转化某个 Kconfig 标记为 C 的布尔
+表达式，并在正常的 C 条件中使用它：
+
+	if (IS_ENABLED(CONFIG_SOMETHING)) {
+		...
+	}
+
+编译器会无条件地做常数合并，就像使用 #ifdef 那样，包含或排除代码块，所以这不会
+带来任何运行时开销。然而，这种方法依旧允许 C 编译器查看块内的代码，并检查它的正确
+性（语法，类型，符号引用，等等）。因此，如果条件不满足，代码块内的引用符号将不存在，
+你必须继续使用 #ifdef。
+
+在任何有意义的 #if 或 #ifdef 块的末尾（超过几行），在 #endif 同一行的后面写下
+注释，指出该条件表达式被使用。例如：
+
+	#ifdef CONFIG_SOMETHING
+	...
+	#endif /* CONFIG_SOMETHING */
+
+
+		附录 I：参考
+
+The C Programming Language, 第二版
+作者：Brian W. Kernighan 和 Denni M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮).
+
+The Practice of Programming
+作者：Brian W. Kernighan 和 Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent,
+都可以从 http://www.gnu.org/manual/ 找到
+
+WG14是C语言的国际标准化工作组，URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+Kernel process/coding-style.rst，作者 greg@kroah.com 发表于OLS 2002：
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/email-clients.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/email-clients.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/email-clients.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/email-clients.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,210 @@
+﻿Chinese translated version of Documentation/process/email-clients.rst
+
+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/process/email-clients.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 贾威威  Harry Wei <harryxiyou@gmail.com>
+中文版翻译者： 贾威威  Harry Wei <harryxiyou@gmail.com>
+中文版校译者： Yinglin Luan <synmyth@gmail.com>
+		Xiaochen Wang <wangxiaochen0@gmail.com>
+		yaxinsn <yaxinsn@163.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+Linux邮件客户端配置信息
+======================================================================
+
+普通配置
+----------------------------------------------------------------------
+Linux内核补丁是通过邮件被提交的，最好把补丁作为邮件体的内嵌文本。有些维护者
+接收附件，但是附件的内容格式应该是"text/plain"。然而，附件一般是不赞成的，
+因为这会使补丁的引用部分在评论过程中变的很困难。
+
+用来发送Linux内核补丁的邮件客户端在发送补丁时应该处于文本的原始状态。例如，
+他们不能改变或者删除制表符或者空格，甚至是在每一行的开头或者结尾。
+
+不要通过"format=flowed"模式发送补丁。这样会引起不可预期以及有害的断行。
+
+不要让你的邮件客户端进行自动换行。这样也会破坏你的补丁。
+
+邮件客户端不能改变文本的字符集编码方式。要发送的补丁只能是ASCII或者UTF-8编码方式，
+如果你使用UTF-8编码方式发送邮件，那么你将会避免一些可能发生的字符集问题。
+
+邮件客户端应该形成并且保持 References: 或者 In-Reply-To: 标题，那么
+邮件话题就不会中断。
+
+复制粘帖(或者剪贴粘帖)通常不能用于补丁，因为制表符会转换为空格。使用xclipboard, xclip
+或者xcutsel也许可以，但是最好测试一下或者避免使用复制粘帖。
+
+不要在使用PGP/GPG署名的邮件中包含补丁。这样会使得很多脚本不能读取和适用于你的补丁。
+（这个问题应该是可以修复的）
+
+在给内核邮件列表发送补丁之前，给自己发送一个补丁是个不错的主意，保存接收到的
+邮件，将补丁用'patch'命令打上，如果成功了，再给内核邮件列表发送。
+
+
+一些邮件客户端提示
+----------------------------------------------------------------------
+这里给出一些详细的MUA配置提示，可以用于给Linux内核发送补丁。这些并不意味是
+所有的软件包配置总结。
+
+说明：
+TUI = 以文本为基础的用户接口
+GUI = 图形界面用户接口
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Alpine (TUI)
+
+配置选项：
+在"Sending Preferences"部分：
+
+- "Do Not Send Flowed Text"必须开启
+- "Strip Whitespace Before Sending"必须关闭
+
+当写邮件时，光标应该放在补丁会出现的地方，然后按下CTRL-R组合键，使指定的
+补丁文件嵌入到邮件中。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Evolution (GUI)
+
+一些开发者成功的使用它发送补丁
+
+当选择邮件选项：Preformat
+  从Format->Heading->Preformatted (Ctrl-7)或者工具栏
+
+然后使用：
+  Insert->Text File... (Alt-n x)插入补丁文件。
+
+你还可以"diff -Nru old.c new.c | xclip"，选择Preformat，然后使用中间键进行粘帖。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Kmail (GUI)
+
+一些开发者成功的使用它发送补丁。
+
+默认设置不为HTML格式是合适的；不要启用它。
+
+当书写一封邮件的时候，在选项下面不要选择自动换行。唯一的缺点就是你在邮件中输入的任何文本
+都不会被自动换行，因此你必须在发送补丁之前手动换行。最简单的方法就是启用自动换行来书写邮件，
+然后把它保存为草稿。一旦你在草稿中再次打开它，它已经全部自动换行了，那么你的邮件虽然没有
+选择自动换行，但是还不会失去已有的自动换行。
+
+在邮件的底部，插入补丁之前，放上常用的补丁定界符：三个连字号(---)。
+
+然后在"Message"菜单条目，选择插入文件，接着选取你的补丁文件。还有一个额外的选项，你可以
+通过它配置你的邮件建立工具栏菜单，还可以带上"insert file"图标。
+
+你可以安全地通过GPG标记附件，但是内嵌补丁最好不要使用GPG标记它们。作为内嵌文本的签发补丁，
+当从GPG中提取7位编码时会使他们变的更加复杂。
+
+如果你非要以附件的形式发送补丁，那么就右键点击附件，然后选中属性，突出"Suggest automatic
+display"，这样内嵌附件更容易让读者看到。
+
+当你要保存将要发送的内嵌文本补丁，你可以从消息列表窗格选择包含补丁的邮件，然后右击选择
+"save as"。你可以使用一个没有更改的包含补丁的邮件，如果它是以正确的形式组成。当你正真在它
+自己的窗口之下察看，那时没有选项可以保存邮件--已经有一个这样的bug被汇报到了kmail的bugzilla
+并且希望这将会被处理。邮件是以只针对某个用户可读写的权限被保存的，所以如果你想把邮件复制到其他地方，
+你不得不把他们的权限改为组或者整体可读。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Lotus Notes (GUI)
+
+不要使用它。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Mutt (TUI)
+
+很多Linux开发人员使用mutt客户端，所以证明它肯定工作的非常漂亮。
+
+Mutt不自带编辑器，所以不管你使用什么编辑器都不应该带有自动断行。大多数编辑器都带有
+一个"insert file"选项，它可以通过不改变文件内容的方式插入文件。
+
+'vim'作为mutt的编辑器：
+  set editor="vi"
+
+  如果使用xclip，敲入以下命令
+  :set paste
+  按中键之前或者shift-insert或者使用
+  :r filename
+
+如果想要把补丁作为内嵌文本。
+(a)ttach工作的很好，不带有"set paste"。
+
+配置选项：
+它应该以默认设置的形式工作。
+然而，把"send_charset"设置为"us-ascii::utf-8"也是一个不错的主意。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Pine (TUI)
+
+Pine过去有一些空格删减问题，但是这些现在应该都被修复了。
+
+如果可以，请使用alpine(pine的继承者)
+
+配置选项：
+- 最近的版本需要消除流程文本
+- "no-strip-whitespace-before-send"选项也是需要的。
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Sylpheed (GUI)
+
+- 内嵌文本可以很好的工作（或者使用附件）。
+- 允许使用外部的编辑器。
+- 对于目录较多时非常慢。
+- 如果通过non-SSL连接，无法使用TLS SMTP授权。
+- 在组成窗口中有一个很有用的ruler bar。
+- 给地址本中添加地址就不会正确的了解显示名。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Thunderbird (GUI)
+
+默认情况下，thunderbird很容易损坏文本，但是还有一些方法可以强制它变得更好。
+
+- 在用户帐号设置里，组成和寻址，不要选择"Compose messages in HTML format"。
+
+- 编辑你的Thunderbird配置设置来使它不要拆行使用：user_pref("mailnews.wraplength", 0);
+
+- 编辑你的Thunderbird配置设置，使它不要使用"format=flowed"格式：user_pref("mailnews.
+  send_plaintext_flowed", false);
+
+- 你需要使Thunderbird变为预先格式方式：
+  如果默认情况下你书写的是HTML格式，那不是很难。仅仅从标题栏的下拉框中选择"Preformat"格式。
+  如果默认情况下你书写的是文本格式，你不得把它改为HTML格式（仅仅作为一次性的）来书写新的消息，
+  然后强制使它回到文本格式，否则它就会拆行。要实现它，在写信的图标上使用shift键来使它变为HTML
+  格式，然后标题栏的下拉框中选择"Preformat"格式。
+
+- 允许使用外部的编辑器：
+  针对Thunderbird打补丁最简单的方法就是使用一个"external editor"扩展，然后使用你最喜欢的
+  $EDITOR来读取或者合并补丁到文本中。要实现它，可以下载并且安装这个扩展，然后添加一个使用它的
+  按键View->Toolbars->Customize...最后当你书写信息的时候仅仅点击它就可以了。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+TkRat (GUI)
+
+可以使用它。使用"Insert file..."或者外部的编辑器。
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Gmail (Web GUI)
+
+不要使用它发送补丁。
+
+Gmail网页客户端自动地把制表符转换为空格。
+
+虽然制表符转换为空格问题可以被外部编辑器解决，同时它还会使用回车换行把每行拆分为78个字符。
+
+另一个问题是Gmail还会把任何不是ASCII的字符的信息改为base64编码。它把东西变的像欧洲人的名字。
+
+                                ###
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/filesystems/sysfs.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/filesystems/sysfs.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/filesystems/sysfs.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/filesystems/sysfs.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,372 @@
+Chinese translated version of Documentation/filesystems/sysfs.txt
+
+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.
+
+Maintainer: Patrick Mochel	<mochel@osdl.org>
+		Mike Murphy <mamurph@cs.clemson.edu>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/filesystems/sysfs.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Patrick Mochel	<mochel@osdl.org>
+		Mike Murphy <mamurph@cs.clemson.edu>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+sysfs - 用于导出内核对象(kobject)的文件系统
+
+Patrick Mochel	<mochel@osdl.org>
+Mike Murphy <mamurph@cs.clemson.edu>
+
+修订:    16 August 2011
+原始版本:   10 January 2003
+
+
+sysfs 简介:
+~~~~~~~~~~
+
+sysfs 是一个最初基于 ramfs 且位于内存的文件系统。它提供导出内核
+数据结构及其属性，以及它们之间的关联到用户空间的方法。
+
+sysfs 始终与 kobject 的底层结构紧密相关。请阅读
+Documentation/kobject.txt 文档以获得更多关于 kobject 接口的
+信息。
+
+
+使用 sysfs
+~~~~~~~~~~~
+
+只要内核配置中定义了 CONFIG_SYSFS ，sysfs 总是被编译进内核。你可
+通过以下命令挂载它:
+
+    mount -t sysfs sysfs /sys
+
+
+创建目录
+~~~~~~~~
+
+任何 kobject 在系统中注册，就会有一个目录在 sysfs 中被创建。这个
+目录是作为该 kobject 的父对象所在目录的子目录创建的，以准确地传递
+内核的对象层次到用户空间。sysfs 中的顶层目录代表着内核对象层次的
+共同祖先；例如：某些对象属于某个子系统。
+
+Sysfs 在与其目录关联的 kernfs_node 对象中内部保存一个指向实现
+目录的 kobject 的指针。以前，这个 kobject 指针被 sysfs 直接用于
+kobject 文件打开和关闭的引用计数。而现在的 sysfs 实现中，kobject
+引用计数只能通过 sysfs_schedule_callback() 函数直接修改。
+
+
+属性
+~~~~
+
+kobject 的属性可在文件系统中以普通文件的形式导出。Sysfs 为属性定义
+了面向文件 I/O 操作的方法，以提供对内核属性的读写。
+
+
+属性应为 ASCII 码文本文件。以一个文件只存储一个属性值为宜。但一个
+文件只包含一个属性值可能影响效率，所以一个包含相同数据类型的属性值
+数组也被广泛地接受。
+
+混合类型、表达多行数据以及一些怪异的数据格式会遭到强烈反对。这样做是
+很丢脸的,而且其代码会在未通知作者的情况下被重写。
+
+
+一个简单的属性结构定义如下:
+
+struct attribute {
+        char                    * name;
+        struct module		*owner;
+        umode_t                 mode;
+};
+
+
+int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
+void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
+
+
+一个单独的属性结构并不包含读写其属性值的方法。子系统最好为增删特定
+对象类型的属性定义自己的属性结构体和封装函数。
+
+例如:驱动程序模型定义的 device_attribute 结构体如下:
+
+struct device_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count);
+};
+
+int device_create_file(struct device *, const struct device_attribute *);
+void device_remove_file(struct device *, const struct device_attribute *);
+
+为了定义设备属性，同时定义了一下辅助宏:
+
+#define DEVICE_ATTR(_name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+
+例如:声明
+
+static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
+
+等同于如下代码：
+
+static struct device_attribute dev_attr_foo = {
+       .attr	= {
+		.name = "foo",
+		.mode = S_IWUSR | S_IRUGO,
+		.show = show_foo,
+		.store = store_foo,
+	},
+};
+
+
+子系统特有的回调函数
+~~~~~~~~~~~~~~~~~~~
+
+当一个子系统定义一个新的属性类型时，必须实现一系列的 sysfs 操作，
+以帮助读写调用实现属性所有者的显示和储存方法。
+
+struct sysfs_ops {
+        ssize_t (*show)(struct kobject *, struct attribute *, char *);
+        ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
+};
+
+[子系统应已经定义了一个 struct kobj_type 结构体作为这个类型的
+描述符，并在此保存 sysfs_ops 的指针。更多的信息参见 kobject 的
+文档]
+
+sysfs 会为这个类型调用适当的方法。当一个文件被读写时，这个方法会
+将一般的kobject 和 attribute 结构体指针转换为适当的指针类型后
+调用相关联的函数。
+
+
+示例:
+
+#define to_dev(obj) container_of(obj, struct device, kobj)
+#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
+
+static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
+                             char *buf)
+{
+        struct device_attribute *dev_attr = to_dev_attr(attr);
+        struct device *dev = to_dev(kobj);
+        ssize_t ret = -EIO;
+
+        if (dev_attr->show)
+                ret = dev_attr->show(dev, dev_attr, buf);
+        if (ret >= (ssize_t)PAGE_SIZE) {
+                print_symbol("dev_attr_show: %s returned bad count\n",
+                                (unsigned long)dev_attr->show);
+        }
+        return ret;
+}
+
+
+
+读写属性数据
+~~~~~~~~~~~~
+
+在声明属性时，必须指定 show() 或 store() 方法，以实现属性的
+读或写。这些方法的类型应该和以下的设备属性定义一样简单。
+
+ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
+ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+                 const char *buf, size_t count);
+
+也就是说,他们应只以一个处理对象、一个属性和一个缓冲指针作为参数。
+
+sysfs 会分配一个大小为 (PAGE_SIZE) 的缓冲区并传递给这个方法。
+Sysfs 将会为每次读写操作调用一次这个方法。这使得这些方法在执行时
+会出现以下的行为:
+
+- 在读方面（read(2)），show() 方法应该填充整个缓冲区。回想属性
+  应只导出了一个属性值或是一个同类型属性值的数组，所以这个代价将
+  不会不太高。
+
+  这使得用户空间可以局部地读和任意的向前搜索整个文件。如果用户空间
+  向后搜索到零或使用‘0’偏移执行一个pread(2)操作，show()方法将
+  再次被调用，以重新填充缓存。
+
+- 在写方面（write(2)），sysfs 希望在第一次写操作时得到整个缓冲区。
+  之后 Sysfs 传递整个缓冲区给 store() 方法。
+
+  当要写 sysfs 文件时，用户空间进程应首先读取整个文件，修该想要
+  改变的值，然后回写整个缓冲区。
+
+  在读写属性值时，属性方法的执行应操作相同的缓冲区。
+
+注记:
+
+- 写操作导致的 show() 方法重载，会忽略当前文件位置。
+
+- 缓冲区应总是 PAGE_SIZE 大小。对于i386，这个值为4096。
+
+- show() 方法应该返回写入缓冲区的字节数，也就是 snprintf()的
+  返回值。
+
+- show() 应始终使用 snprintf()。
+
+- store() 应返回缓冲区的已用字节数。如果整个缓存都已填满，只需返回
+  count 参数。
+
+- show() 或 store() 可以返回错误值。当得到一个非法值，必须返回一个
+  错误值。
+
+- 一个传递给方法的对象将会通过 sysfs 调用对象内嵌的引用计数固定在
+  内存中。尽管如此，对象代表的物理实体(如设备)可能已不存在。如有必要，
+  应该实现一个检测机制。
+
+一个简单的(未经实验证实的)设备属性实现如下：
+
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name);
+}
+
+static ssize_t store_name(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+        snprintf(dev->name, sizeof(dev->name), "%.*s",
+                 (int)min(count, sizeof(dev->name) - 1), buf);
+	return count;
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
+
+
+（注意：真正的实现不允许用户空间设置设备名。）
+
+顶层目录布局
+~~~~~~~~~~~~
+
+sysfs 目录的安排显示了内核数据结构之间的关系。
+
+顶层 sysfs 目录如下:
+
+block/
+bus/
+class/
+dev/
+devices/
+firmware/
+net/
+fs/
+
+devices/ 包含了一个设备树的文件系统表示。他直接映射了内部的内核
+设备树，反映了设备的层次结构。
+
+bus/ 包含了内核中各种总线类型的平面目录布局。每个总线目录包含两个
+子目录:
+
+	devices/
+	drivers/
+
+devices/ 包含了系统中出现的每个设备的符号链接，他们指向 root/ 下的
+设备目录。
+
+drivers/ 包含了每个已为特定总线上的设备而挂载的驱动程序的目录(这里
+假定驱动没有跨越多个总线类型)。
+
+fs/ 包含了一个为文件系统设立的目录。现在每个想要导出属性的文件系统必须
+在 fs/ 下创建自己的层次结构(参见Documentation/filesystems/fuse.txt)。
+
+dev/ 包含两个子目录： char/ 和 block/。在这两个子目录中，有以
+<major>:<minor> 格式命名的符号链接。这些符号链接指向 sysfs 目录
+中相应的设备。/sys/dev 提供一个通过一个 stat(2) 操作结果，查找
+设备 sysfs 接口快捷的方法。
+
+更多有关 driver-model 的特性信息可以在 Documentation/driver-model/
+中找到。
+
+
+TODO: 完成这一节。
+
+
+当前接口
+~~~~~~~~
+
+以下的接口层普遍存在于当前的sysfs中:
+
+- 设备 (include/linux/device.h)
+----------------------------------
+结构体:
+
+struct device_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count);
+};
+
+声明:
+
+DEVICE_ATTR(_name, _mode, _show, _store);
+
+增/删属性:
+
+int device_create_file(struct device *dev, const struct device_attribute * attr);
+void device_remove_file(struct device *dev, const struct device_attribute * attr);
+
+
+- 总线驱动程序 (include/linux/device.h)
+--------------------------------------
+结构体:
+
+struct bus_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct bus_type *, char * buf);
+        ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
+};
+
+声明:
+
+BUS_ATTR(_name, _mode, _show, _store)
+
+增/删属性:
+
+int bus_create_file(struct bus_type *, struct bus_attribute *);
+void bus_remove_file(struct bus_type *, struct bus_attribute *);
+
+
+- 设备驱动程序 (include/linux/device.h)
+-----------------------------------------
+
+结构体:
+
+struct driver_attribute {
+        struct attribute        attr;
+        ssize_t (*show)(struct device_driver *, char * buf);
+        ssize_t (*store)(struct device_driver *, const char * buf,
+                         size_t count);
+};
+
+声明:
+
+DRIVER_ATTR(_name, _mode, _show, _store)
+
+增/删属性：
+
+int driver_create_file(struct device_driver *, const struct driver_attribute *);
+void driver_remove_file(struct device_driver *, const struct driver_attribute *);
+
+
+文档
+~~~~
+
+sysfs 目录结构以及其中包含的属性定义了一个内核与用户空间之间的 ABI。
+对于任何 ABI，其自身的稳定和适当的文档是非常重要的。所有新的 sysfs
+属性必须在 Documentation/ABI 中有文档。详见 Documentation/ABI/README。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/gpio.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/gpio.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/gpio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/gpio.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,650 @@
+Chinese translated version of Documentation/gpio.txt
+
+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.
+
+Maintainer: Grant Likely <grant.likely@secretlab.ca>
+		Linus Walleij <linus.walleij@linaro.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/gpio.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Grant Likely <grant.likely@secretlab.ca>
+		Linus Walleij <linus.walleij@linaro.org>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+GPIO 接口
+
+本文档提供了一个在Linux下访问GPIO的公约概述。
+
+这些函数以 gpio_* 作为前缀。其他的函数不允许使用这样的前缀或相关的
+__gpio_* 前缀。
+
+
+什么是GPIO?
+==========
+"通用输入/输出口"(GPIO)是一个灵活的由软件控制的数字信号。他们可
+由多种芯片提供,且对于从事嵌入式和定制硬件的 Linux 开发者来说是
+比较熟悉。每个GPIO 都代表一个连接到特定引脚或球栅阵列(BGA)封装中
+“球珠”的一个位。电路板原理图显示了 GPIO 与外部硬件的连接关系。
+驱动可以编写成通用代码，以使板级启动代码可传递引脚配置数据给驱动。
+
+片上系统 (SOC) 处理器对 GPIO 有很大的依赖。在某些情况下,每个
+非专用引脚都可配置为 GPIO,且大多数芯片都最少有一些 GPIO。
+可编程逻辑器件(类似 FPGA) 可以方便地提供 GPIO。像电源管理和
+音频编解码器这样的多功能芯片经常留有一些这样的引脚来帮助那些引脚
+匮乏的 SOC。同时还有通过 I2C 或 SPI 串行总线连接的“GPIO扩展器”
+芯片。大多数 PC 的南桥有一些拥有 GPIO 能力的引脚 (只有BIOS
+固件才知道如何使用他们)。
+
+GPIO 的实际功能因系统而异。通常用法有:
+
+  - 输出值可写 (高电平=1，低电平=0)。一些芯片也有如何驱动这些值的选项,
+    例如只允许输出一个值、支持“线与”及其他取值类似的模式(值得注意的是
+    “开漏”信号)
+
+  - 输入值可读(1、0)。一些芯片支持引脚在配置为“输出”时回读，这对于类似
+    “线与”的情况(以支持双向信号)是非常有用的。GPIO 控制器可能有输入
+    去毛刺/消抖逻辑,这有时需要软件控制。
+
+  - 输入通常可作为 IRQ 信号,一般是沿触发,但有时是电平触发。这样的 IRQ
+    可能配置为系统唤醒事件,以将系统从低功耗状态下唤醒。
+
+  - 通常一个 GPIO 根据不同产品电路板的需求,可以配置为输入或输出,也有仅
+    支持单向的。
+
+  - 大部分 GPIO 可以在持有自旋锁时访问,但是通常由串行总线扩展的 GPIO
+    不允许持有自旋锁。但某些系统也支持这种类型。
+
+对于给定的电路板,每个 GPIO 都用于某个特定的目的,如监控 MMC/SD 卡的
+插入/移除、检测卡的写保护状态、驱动 LED、配置收发器、模拟串行总线、
+复位硬件看门狗、感知开关状态等等。
+
+
+GPIO 公约
+=========
+注意,这个叫做“公约”，因为这不是强制性的，不遵循这个公约是无伤大雅的，
+因为此时可移植性并不重要。GPIO 常用于板级特定的电路逻辑,甚至可能
+随着电路板的版本而改变，且不可能在不同走线的电路板上使用。仅有在少数
+功能上才具有可移植性，其他功能是平台特定。这也是由于“胶合”的逻辑造成的。
+
+此外，这不需要任何的执行框架，只是一个接口。某个平台可能通过一个简单地
+访问芯片寄存器的内联函数来实现它，其他平台可能通过委托一系列不同的GPIO
+控制器的抽象函数来实现它。(有一些可选的代码能支持这种策略的实现,本文档
+后面会介绍，但作为 GPIO 接口的客户端驱动程序必须与它的实现无关。)
+
+也就是说,如果在他们的平台上支持这个公约，驱动应尽可能的使用它。同时，平台
+必须在 Kconfig 中选择 ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB
+选项。那些调用标准 GPIO 函数的驱动应该在 Kconfig 入口中声明依赖GENERIC_GPIO。
+当驱动包含文件:
+
+	#include <linux/gpio.h>
+
+则 GPIO 函数是可用,无论是“真实代码”还是经优化过的语句。如果你遵守
+这个公约，当你的代码完成后，对其他的开发者来说会更容易看懂和维护。
+
+注意，这些操作包含所用平台的 I/O 屏障代码，驱动无须显式地调用他们。
+
+
+标识 GPIO
+---------
+GPIO 是通过无符号整型来标识的,范围是 0 到 MAX_INT。保留“负”数
+用于其他目的,例如标识信号“在这个板子上不可用”或指示错误。未接触底层
+硬件的代码会忽略这些整数。
+
+平台会定义这些整数的用法,且通常使用 #define 来定义 GPIO，这样
+板级特定的启动代码可以直接关联相应的原理图。相对来说，驱动应该仅使用
+启动代码传递过来的 GPIO 编号，使用 platform_data 保存板级特定
+引脚配置数据 (同时还有其他须要的板级特定数据)，避免可能出现的问题。
+
+例如一个平台使用编号 32-159 来标识 GPIO,而在另一个平台使用编号0-63
+标识一组 GPIO 控制器,64-79标识另一类 GPIO 控制器,且在一个含有
+FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中，也可以
+使用编号2000-2063来标识一个 I2C 接口的 GPIO 扩展器中的 GPIO。
+
+如果你要初始化一个带有无效 GPIO 编号的结构体,可以使用一些负编码
+(如"-EINVAL")，那将使其永远不会是有效。来测试这样一个结构体中的编号
+是否关联一个 GPIO，你可使用以下断言:
+
+	int gpio_is_valid(int number);
+
+如果编号不存在，则请求和释放 GPIO 的函数将拒绝执行相关操作(见下文)。
+其他编号也可能被拒绝,比如一个编号可能存在，但暂时在给定的电路上不可用。
+
+一个平台是否支持多个 GPIO 控制器为平台特定的实现问题，就像是否可以
+在 GPIO 编号空间中有“空洞”和是否可以在运行时添加新的控制器一样。
+这些问题会影响其他事情，包括相邻的 GPIO 编号是否存在等。
+
+使用 GPIO
+---------
+对于一个 GPIO，系统应该做的第一件事情就是通过 gpio_request()
+函数分配它，见下文。
+
+接下来是设置I/O方向，这通常是在板级启动代码中为所使用的 GPIO 设置
+platform_device 时完成。
+
+	/* 设置为输入或输出, 返回 0 或负的错误代码 */
+	int gpio_direction_input(unsigned gpio);
+	int gpio_direction_output(unsigned gpio, int value);
+
+返回值为零代表成功，否则返回一个负的错误代码。这个返回值需要检查，因为
+get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误。通常，
+你应该在进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO，在板子
+启动的早期、进程启动前使用他们也是可以的。
+
+对于作为输出的 GPIO，为其提供初始输出值，对于避免在系统启动期间出现
+信号毛刺是很有帮助的。
+
+为了与传统的 GPIO 接口兼容, 在设置一个 GPIO 方向时，如果它还未被申请，
+则隐含了申请那个 GPIO 的操作(见下文)。这种兼容性正在从可选的 gpiolib
+框架中移除。
+
+如果这个 GPIO 编码不存在，或者特定的 GPIO 不能用于那种模式，则方向
+设置可能失败。依赖启动固件来正确地设置方向通常是一个坏主意，因为它可能
+除了启动Linux，并没有做更多的验证工作。(同理, 板子的启动代码可能需要
+将这个复用的引脚设置为 GPIO，并正确地配置上拉/下拉电阻。)
+
+
+访问自旋锁安全的 GPIO
+-------------------
+大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以
+安全地在硬(非线程)中断例程和类似的上下文中完成。
+
+对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文)，使用
+以下的函数访问:
+
+	/* GPIO 输入:返回零或非零 */
+	int gpio_get_value(unsigned gpio);
+
+	/* GPIO 输出 */
+	void gpio_set_value(unsigned gpio, int value);
+
+GPIO值是布尔值，零表示低电平，非零表示高电平。当读取一个输出引脚的值时，
+返回值应该是引脚上的值。这个值不总是和输出值相符，因为存在开漏输出信号和
+输出延迟问题。
+
+以上的 get/set 函数无错误返回值，因为之前 gpio_direction_*()应已检查过
+其是否为“无效GPIO”。此外，还需要注意的是并不是所有平台都可以从输出引脚
+中读取数据，对于不能读取的引脚应总返回零。另外，对那些在原子上下文中无法
+安全访问的 GPIO (译者注：因为访问可能导致休眠)使用这些函数是不合适的
+(见下文)。
+
+在 GPIO 编号(还有输出、值)为常数的情况下,鼓励通过平台特定的实现来优化
+这两个函数来访问 GPIO 值。这种情况(读写一个硬件寄存器)下只需要几条指令
+是很正常的,且无须自旋锁。这种优化函数比起那些在子程序上花费许多指令的
+函数可以使得模拟接口(译者注:例如 GPIO 模拟 I2C、1-wire 或 SPI)的
+应用(在空间和时间上都)更具效率。
+
+
+访问可能休眠的 GPIO
+-----------------
+某些 GPIO 控制器必须通过基于总线(如 I2C 或 SPI)的消息访问。读或写这些
+GPIO 值的命令需要等待其信息排到队首才发送命令，再获得其反馈。期间需要
+休眠，这不能在 IRQ 例程(中断上下文)中执行。
+
+支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要
+一个之前通过 gpio_request 分配到的有效 GPIO 编号):
+
+	int gpio_cansleep(unsigned gpio);
+
+为了访问这种 GPIO,内核定义了一套不同的函数:
+
+	/* GPIO 输入:返回零或非零 ,可能会休眠 */
+	int gpio_get_value_cansleep(unsigned gpio);
+
+	/* GPIO 输出,可能会休眠 */
+	void gpio_set_value_cansleep(unsigned gpio, int value);
+
+
+访问这样的 GPIO 需要一个允许休眠的上下文，例如线程 IRQ 处理例程，并用以上的
+访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。
+
+除了这些访问函数可能休眠，且它们操作的 GPIO 不能在硬件 IRQ 处理例程中访问的
+事实，这些处理例程实际上和自旋锁安全的函数是一样的。
+
+** 除此之外 ** 调用设置和配置此类 GPIO 的函数也必须在允许休眠的上下文中，
+因为它们可能也需要访问 GPIO 控制器芯片: (这些设置函数通常在板级启动代码或者
+驱动探测/断开代码中，所以这是一个容易满足的约束条件。)
+
+	gpio_direction_input()
+	gpio_direction_output()
+	gpio_request()
+
+## 	gpio_request_one()
+##	gpio_request_array()
+## 	gpio_free_array()
+
+	gpio_free()
+	gpio_set_debounce()
+
+
+
+声明和释放 GPIO
+----------------------------
+为了有助于捕获系统配置错误,定义了两个函数。
+
+	/* 申请 GPIO, 返回 0 或负的错误代码.
+	 * 非空标签可能有助于诊断.
+	 */
+	int gpio_request(unsigned gpio, const char *label);
+
+	/* 释放之前声明的 GPIO */
+	void gpio_free(unsigned gpio);
+
+将无效的 GPIO 编码传递给 gpio_request()会导致失败，申请一个已使用这个
+函数声明过的 GPIO 也会失败。gpio_request()的返回值必须检查。你应该在
+进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子启动的早期、
+进入进程之前是可以申请的。
+
+这个函数完成两个基本的目标。一是标识那些实际上已作为 GPIO 使用的信号线，
+这样便于更好地诊断;系统可能需要服务几百个可用的 GPIO，但是对于任何一个
+给定的电路板通常只有一些被使用。另一个目的是捕获冲突，查明错误:如两个或
+更多驱动错误地认为他们已经独占了某个信号线,或是错误地认为移除一个管理着
+某个已激活信号的驱动是安全的。也就是说，申请 GPIO 的作用类似一种锁机制。
+
+某些平台可能也使用 GPIO 作为电源管理激活信号(例如通过关闭未使用芯片区和
+简单地关闭未使用时钟)。
+
+对于 GPIO 使用 pinctrl 子系统已知的引脚，子系统应该被告知其使用情况；
+一个 gpiolib 驱动的 .request()操作应调用 pinctrl_request_gpio()，
+而 gpiolib 驱动的 .free()操作应调用 pinctrl_free_gpio()。pinctrl
+子系统允许 pinctrl_request_gpio()在某个引脚或引脚组以复用形式“属于”
+一个设备时都成功返回。
+
+任何须将 GPIO 信号导向适当引脚的引脚复用硬件的编程应该发生在 GPIO
+驱动的 .direction_input()或 .direction_output()函数中，以及
+任何输出 GPIO 值的设置之后。这样可使从引脚特殊功能到 GPIO 的转换
+不会在引脚产生毛刺波形。有时当用一个 GPIO 实现其信号驱动一个非 GPIO
+硬件模块的解决方案时，就需要这种机制。
+
+某些平台允许部分或所有 GPIO 信号使用不同的引脚。类似的，GPIO 或引脚的
+其他方面也需要配置，如上拉/下拉。平台软件应该在对这些 GPIO 调用
+gpio_request()前将这类细节配置好，例如使用 pinctrl 子系统的映射表，
+使得 GPIO 的用户无须关注这些细节。
+
+还有一个值得注意的是在释放 GPIO 前，你必须停止使用它。
+
+
+注意:申请一个 GPIO 并没有以任何方式配置它，只不过标识那个 GPIO 处于使用
+状态。必须有另外的代码来处理引脚配置(如控制 GPIO 使用的引脚、上拉/下拉)。
+考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数:
+
+	/* 申请一个 GPIO 信号, 同时通过特定的'flags'初始化配置,
+	 * 其他和 gpio_request()的参数和返回值相同
+	 *
+	 */
+	int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+
+	/* 在单个函数中申请多个 GPIO
+	 */
+	int gpio_request_array(struct gpio *array, size_t num);
+
+	/* 在单个函数中释放多个 GPIO
+	 */
+	void gpio_free_array(struct gpio *array, size_t num);
+
+这里 'flags' 当前定义可指定以下属性:
+
+	* GPIOF_DIR_IN		- 配置方向为输入
+	* GPIOF_DIR_OUT		- 配置方向为输出
+
+	* GPIOF_INIT_LOW	- 在作为输出时,初始值为低电平
+	* GPIOF_INIT_HIGH	- 在作为输出时,初始值为高电平
+	* GPIOF_OPEN_DRAIN	- gpio引脚为开漏信号
+	* GPIOF_OPEN_SOURCE	- gpio引脚为源极开路信号
+
+	* GPIOF_EXPORT_DIR_FIXED	- 将 gpio 导出到 sysfs，并保持方向
+	* GPIOF_EXPORT_DIR_CHANGEABLE	- 同样是导出, 但允许改变方向
+
+因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为:
+
+	* GPIOF_IN		- 配置为输入
+	* GPIOF_OUT_INIT_LOW	- 配置为输出,并初始化为低电平
+	* GPIOF_OUT_INIT_HIGH	- 配置为输出,并初始化为高电平
+
+当设置 flag 为 GPIOF_OPEN_DRAIN 时，则假设引脚是开漏信号。这样的引脚
+将不会在输出模式下置1。这样的引脚需要连接上拉电阻。通过使能这个标志，gpio库
+将会在被要求输出模式下置1时将引脚变为输入状态来使引脚置高。引脚在输出模式下
+通过置0使其输出低电平。
+
+当设置 flag 为 GPIOF_OPEN_SOURCE 时，则假设引脚为源极开路信号。这样的引脚
+将不会在输出模式下置0。这样的引脚需要连接下拉电阻。通过使能这个标志，gpio库
+将会在被要求输出模式下置0时将引脚变为输入状态来使引脚置低。引脚在输出模式下
+通过置1使其输出高电平。
+
+将来这些标志可能扩展到支持更多的属性。
+
+更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有
+这三个领域:
+
+	struct gpio {
+		unsigned	gpio;
+		unsigned long	flags;
+		const char	*label;
+	};
+
+一个典型的用例:
+
+	static struct gpio leds_gpios[] = {
+		{ 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默认开启 */
+		{ 33, GPIOF_OUT_INIT_LOW,  "Green LED" }, /* 默认关闭 */
+		{ 34, GPIOF_OUT_INIT_LOW,  "Red LED"   }, /* 默认关闭 */
+		{ 35, GPIOF_OUT_INIT_LOW,  "Blue LED"  }, /* 默认关闭 */
+		{ ... },
+	};
+
+	err = gpio_request_one(31, GPIOF_IN, "Reset Button");
+	if (err)
+		...
+
+	err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+	if (err)
+		...
+
+	gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+
+
+GPIO 映射到 IRQ
+--------------------
+GPIO 编号是无符号整数;IRQ 编号也是。这些构成了两个逻辑上不同的命名空间
+(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射:
+
+	/* 映射 GPIO 编号到 IRQ 编号 */
+	int gpio_to_irq(unsigned gpio);
+
+	/* 映射 IRQ 编号到 GPIO 编号 (尽量避免使用) */
+	int irq_to_gpio(unsigned irq);
+
+它们的返回值为对应命名空间的相关编号，或是负的错误代码(如果无法映射)。
+(例如,某些 GPIO 无法做为 IRQ 使用。)以下的编号错误是未经检测的:使用一个
+未通过 gpio_direction_input()配置为输入的 GPIO 编号，或者使用一个
+并非来源于gpio_to_irq()的 IRQ 编号。
+
+这两个映射函数可能会在信号编号的加减计算过程上花些时间。它们不可休眠。
+
+gpio_to_irq()返回的非错误值可以传递给 request_irq()或者 free_irq()。
+它们通常通过板级特定的初始化代码存放到平台设备的 IRQ 资源中。注意:IRQ
+触发选项是 IRQ 接口的一部分，如 IRQF_TRIGGER_FALLING，系统唤醒能力
+也是如此。
+
+irq_to_gpio()返回的非错误值大多数通常可以被 gpio_get_value()所使用，
+比如在 IRQ 是沿触发时初始化或更新驱动状态。注意某些平台不支持反映射,所以
+你应该尽量避免使用它。
+
+
+模拟开漏信号
+----------------------------
+有时在只有低电平信号作为实际驱动结果(译者注:多个输出连接于一点，逻辑电平
+结果为所有输出的逻辑与)的时候,共享的信号线需要使用“开漏”信号。(该术语
+适用于 CMOS 管；而 TTL 用“集电极开路”。)一个上拉电阻使信号为高电平。这
+有时被称为“线与”。实际上，从负逻辑(低电平为真)的角度来看，这是一个“线或”。
+
+一个开漏信号的常见例子是共享的低电平使能 IRQ 信号线。此外,有时双向数据总线
+信号也使用漏极开路信号。
+
+某些 GPIO 控制器直接支持开漏输出，还有许多不支持。当你需要开漏信号，但
+硬件又不直接支持的时候，一个常用的方法是用任何即可作输入也可作输出的 GPIO
+引脚来模拟:
+
+ LOW:	gpio_direction_output(gpio, 0) ... 这代码驱动信号并覆盖
+	上拉配置。
+
+ HIGH:	gpio_direction_input(gpio) ... 这代码关闭输出,所以上拉电阻
+	(或其他的一些器件)控制了信号。
+
+如果你将信号线“驱动”为高电平，但是 gpio_get_value(gpio)报告了一个
+低电平(在适当的上升时间后)，你就可以知道是其他的一些组件将共享信号线拉低了。
+这不一定是错误的。一个常见的例子就是 I2C 时钟的延长：一个需要较慢时钟的
+从设备延迟 SCK 的上升沿，而 I2C 主设备相应地调整其信号传输速率。
+
+
+这些公约忽略了什么?
+================
+这些公约忽略的最大一件事就是引脚复用，因为这属于高度芯片特定的属性且
+没有可移植性。某个平台可能不需要明确的复用信息；有的对于任意给定的引脚
+可能只有两个功能选项；有的可能每个引脚有八个功能选项；有的可能可以将
+几个引脚中的任何一个作为给定的 GPIO。(是的，这些例子都来自于当前运行
+Linux 的系统。)
+
+在某些系统中,与引脚复用相关的是配置和使能集成的上、下拉模式。并不是所有
+平台都支持这种模式,或者不会以相同的方式来支持这种模式；且任何给定的电路板
+可能使用外置的上拉(或下拉)电阻,这时芯片上的就不应该使用。(当一个电路需要
+5kOhm 的拉动电阻,芯片上的 100 kOhm 电阻就不能做到。)同样的，驱动能力
+(2 mA vs 20 mA)和电压(1.8V vs 3.3V)是平台特定问题,就像模型一样在
+可配置引脚和 GPIO 之间(没)有一一对应的关系。
+
+还有其他一些系统特定的机制没有在这里指出，例如上述的输入去毛刺和线与输出
+选项。硬件可能支持批量读或写 GPIO，但是那一般是配置相关的：对于处于同一
+块区(bank)的GPIO。(GPIO 通常以 16 或 32 个组成一个区块，一个给定的
+片上系统一般有几个这样的区块。)某些系统可以通过输出 GPIO 触发 IRQ，
+或者从并非以 GPIO 管理的引脚取值。这些机制的相关代码没有必要具有可移植性。
+
+当前，动态定义 GPIO 并不是标准的，例如作为配置一个带有某些 GPIO 扩展器的
+附加电路板的副作用。
+
+GPIO 实现者的框架 (可选)
+=====================
+前面提到了，有一个可选的实现框架，让平台使用相同的编程接口，更加简单地支持
+不同种类的 GPIO 控制器。这个框架称为"gpiolib"。
+
+作为一个辅助调试功能，如果 debugfs 可用，就会有一个 /sys/kernel/debug/gpio
+文件。通过这个框架，它可以列出所有注册的控制器,以及当前正在使用中的 GPIO
+的状态。
+
+
+控制器驱动: gpio_chip
+-------------------
+在框架中每个 GPIO 控制器都包装为一个 "struct gpio_chip"，他包含了
+该类型的每个控制器的常用信息:
+
+ - 设置 GPIO 方向的方法
+ - 用于访问 GPIO 值的方法
+ - 告知调用其方法是否可能休眠的标志
+ - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态)
+ - 诊断标签
+
+也包含了来自 device.platform_data 的每个实例的数据：它第一个 GPIO 的
+编号和它可用的 GPIO 的数量。
+
+实现 gpio_chip 的代码应支持多控制器实例，这可能使用驱动模型。那些代码要
+配置每个 gpio_chip，并发起gpiochip_add()。卸载一个 GPIO 控制器很少见，
+但在必要的时候可以使用 gpiochip_remove()。
+
+大部分 gpio_chip 是一个实例特定结构体的一部分，而并不将 GPIO 接口单独
+暴露出来,比如编址、电源管理等。类似编解码器这样的芯片会有复杂的非 GPIO
+状态。
+
+任何一个 debugfs 信息导出方法通常应该忽略还未申请作为 GPIO 的信号线。
+他们可以使用 gpiochip_is_requested()测试，当这个 GPIO 已经申请过了
+就返回相关的标签，否则返回 NULL。
+
+
+平台支持
+-------
+为了支持这个框架，一个平台的 Kconfig 文件将会 "select"(选择)
+ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB，并让它的
+<asm/gpio.h> 包含 <asm-generic/gpio.h>，同时定义三个方法:
+gpio_get_value()、gpio_set_value()和 gpio_cansleep()。
+
+它也应提供一个 ARCH_NR_GPIOS 的定义值，这样可以更好地反映该平台 GPIO
+的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和
+GPIO 扩展器中的数据。)
+
+ARCH_REQUIRE_GPIOLIB 意味着 gpiolib 核心在这个构架中将总是编译进内核。
+
+ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以
+使能它,并将其编译进内核(可选)。
+
+如果这些选项都没被选择,该平台就不通过 GPIO-lib 支持 GPIO,且代码不可以
+被用户使能。
+
+以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度:
+
+  #define gpio_get_value	__gpio_get_value
+  #define gpio_set_value	__gpio_set_value
+  #define gpio_cansleep		__gpio_cansleep
+
+这些定义可以用更理想的实现方法替代，那就是使用经过逻辑优化的内联函数来访问
+基于特定片上系统的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量“12”，
+读取或设置它可能只需少则两或三个指令，且不会休眠。当这样的优化无法实现时，
+那些函数必须使用框架提供的代码，那就至少要几十条指令才可以实现。对于用 GPIO
+模拟的 I/O 接口, 如此精简指令是很有意义的。
+
+对于片上系统，平台特定代码为片上 GPIO 每个区(bank)定义并注册 gpio_chip
+实例。那些 GPIO 应该根据芯片厂商的文档进行编码/标签,并直接和电路板原理图
+对应。他们应该开始于零并终止于平台特定的限制。这些 GPIO(代码)通常从
+arch_initcall()或者更早的地方集成进平台初始化代码，使这些 GPIO 总是可用，
+且他们通常可以作为 IRQ 使用。
+
+板级支持
+-------
+对于外部 GPIO 控制器(例如 I2C 或 SPI 扩展器、专用芯片、多功能器件、FPGA
+或 CPLD)，大多数常用板级特定代码都可以注册控制器设备，并保证他们的驱动知道
+gpiochip_add()所使用的 GPIO 编号。他们的起始编号通常跟在平台特定的 GPIO
+编号之后。
+
+例如板级启动代码应该创建结构体指明芯片公开的 GPIO 范围，并使用 platform_data
+将其传递给每个 GPIO 扩展器芯片。然后芯片驱动中的 probe()例程可以将这个
+数据传递给 gpiochip_add()。
+
+初始化顺序很重要。例如，如果一个设备依赖基于 I2C 的(扩展)GPIO，那么它的
+probe()例程就应该在那个 GPIO 有效以后才可以被调用。这意味着设备应该在
+GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是让这种 gpio_chip
+控制器向板级特定代码提供 setup()和 teardown()回调函数。一旦所有必须的
+资源可用之后，这些板级特定的回调函数将会注册设备，并可以在这些 GPIO 控制器
+设备变成无效时移除它们。
+
+
+用户空间的 Sysfs 接口(可选)
+========================
+使用“gpiolib”实现框架的平台可以选择配置一个 GPIO 的 sysfs 用户接口。
+这不同于 debugfs 接口，因为它提供的是对 GPIO方向和值的控制，而不只显示
+一个GPIO 的状态摘要。此外,它可以出现在没有调试支持的产品级系统中。
+
+例如，通过适当的系统硬件文档，用户空间可以知道 GIOP #23 控制 Flash
+存储器的写保护(用于保护其中 Bootloader 分区)。产品的系统升级可能需要
+临时解除这个保护：首先导入一个 GPIO，改变其输出状态，然后在重新使能写保护
+前升级代码。通常情况下,GPIO #23 是不会被触及的，并且内核也不需要知道他。
+
+根据适当的硬件文档，某些系统的用户空间 GPIO 可以用于确定系统配置数据，
+这些数据是标准内核不知道的。在某些任务中，简单的用户空间 GPIO 驱动可能是
+系统真正需要的。
+
+注意：标准内核驱动中已经存在通用的“LED 和按键”GPIO 任务，分别是:
+"leds-gpio" 和 "gpio_keys"。请使用这些来替代直接访问 GPIO，因为集成在
+内核框架中的这类驱动比你在用户空间的代码更好。
+
+
+Sysfs 中的路径
+--------------
+在/sys/class/gpio 中有 3 类入口:
+
+   -	用于在用户空间控制 GPIO 的控制接口;
+
+   -	GPIOs 本身;以及
+
+   -	GPIO 控制器 ("gpio_chip" 实例)。
+
+除了这些标准的文件,还包含“device”符号链接。
+
+控制接口是只写的:
+
+    /sys/class/gpio/
+
+    	"export" ... 用户空间可以通过写其编号到这个文件，要求内核导出
+		一个 GPIO 的控制到用户空间。
+
+		例如: 如果内核代码没有申请 GPIO #19,"echo 19 > export"
+		将会为 GPIO #19 创建一个 "gpio19" 节点。
+
+    	"unexport" ... 导出到用户空间的逆操作。
+
+		例如: "echo 19 > unexport" 将会移除使用"export"文件导出的
+		"gpio19" 节点。
+
+GPIO 信号的路径类似 /sys/class/gpio/gpio42/ (对于 GPIO #42 来说)，
+并有如下的读/写属性:
+
+    /sys/class/gpio/gpioN/
+
+	"direction" ... 读取得到 "in" 或 "out"。这个值通常运行写入。
+		写入"out" 时,其引脚的默认输出为低电平。为了确保无故障运行，
+		"low" 或 "high" 的电平值应该写入 GPIO 的配置，作为初始输出值。
+
+		注意:如果内核不支持改变 GPIO 的方向，或者在导出时内核代码没有
+		明确允许用户空间可以重新配置 GPIO 方向，那么这个属性将不存在。
+
+	"value" ... 读取得到 0 (低电平) 或 1 (高电平)。如果 GPIO 配置为
+		输出,这个值允许写操作。任何非零值都以高电平看待。
+
+		如果引脚可以配置为中断信号，且如果已经配置了产生中断的模式
+		（见"edge"的描述），你可以对这个文件使用轮询操作(poll(2))，
+		且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2))，
+		请在 events 中设置 POLLPRI 和 POLLERR。如果你使用轮询操作
+		(select(2))，请在 exceptfds 设置你期望的文件描述符。在
+		轮询操作(poll(2))返回之后，既可以通过 lseek(2)操作读取
+		sysfs 文件的开始部分，也可以关闭这个文件并重新打开它来读取数据。
+
+	"edge" ... 读取得到“none”、“rising”、“falling”或者“both”。
+		将这些字符串写入这个文件可以选择沿触发模式，会使得轮询操作
+		(select(2))在"value"文件中返回。
+
+		这个文件仅有在这个引脚可以配置为可产生中断输入引脚时，才存在。
+
+	"active_low" ... 读取得到 0 (假) 或 1 (真)。写入任何非零值可以
+		翻转这个属性的(读写)值。已存在或之后通过"edge"属性设置了"rising"
+		和 "falling" 沿触发模式的轮询操作(poll(2))将会遵循这个设置。
+
+GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
+开始实现控制的控制器),并有着以下只读属性:
+
+    /sys/class/gpio/gpiochipN/
+
+    	"base" ... 与以上的 N 相同,代表此芯片管理的第一个 GPIO 的编号
+
+    	"label" ... 用于诊断 (并不总是只有唯一值)
+
+    	"ngpio" ... 此控制器所管理的 GPIO 数量(而 GPIO 编号从 N 到
+    		N + ngpio - 1)
+
+大多数情况下,电路板的文档应当标明每个 GPIO 的使用目的。但是那些编号并不总是
+固定的,例如在扩展卡上的 GPIO会根据所使用的主板或所在堆叠架构中其他的板子而
+有所不同。在这种情况下,你可能需要使用 gpiochip 节点(尽可能地结合电路图)来
+确定给定信号所用的 GPIO 编号。
+
+
+从内核代码中导出
+-------------
+内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出:
+
+	/* 导出 GPIO 到用户空间 */
+	int gpio_export(unsigned gpio, bool direction_may_change);
+
+	/* gpio_export()的逆操作 */
+	void gpio_unexport();
+
+	/* 创建一个 sysfs 连接到已导出的 GPIO 节点 */
+	int gpio_export_link(struct device *dev, const char *name,
+		unsigned gpio)
+
+在一个内核驱动申请一个 GPIO 之后，它可以通过 gpio_export()使其在 sysfs
+接口中可见。该驱动可以控制信号方向是否可修改。这有助于防止用户空间代码无意间
+破坏重要的系统状态。
+
+这个明确的导出有助于(通过使某些实验更容易来)调试，也可以提供一个始终存在的接口，
+与文档配合作为板级支持包的一部分。
+
+在 GPIO 被导出之后，gpio_export_link()允许在 sysfs 文件系统的任何地方
+创建一个到这个 GPIO sysfs 节点的符号链接。这样驱动就可以通过一个描述性的
+名字，在 sysfs 中他们所拥有的设备下提供一个(到这个 GPIO sysfs 节点的)接口。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/HOWTO linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/HOWTO
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/HOWTO	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/HOWTO	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,536 @@
+﻿Chinese translated version of Documentation/process/howto.rst
+
+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.
+
+Maintainer: Greg Kroah-Hartman <greg@kroah.com>
+Chinese maintainer: Li Yang <leoli@freescale.com>
+---------------------------------------------------------------------
+Documentation/process/howto.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
+中文版维护者： 李阳  Li Yang <leoli@freescale.com>
+中文版翻译者： 李阳  Li Yang <leoli@freescale.com>
+中文版校译者： 钟宇  TripleX Chung <xxx.phy@gmail.com>
+               陈琦  Maggie Chen <chenqi@beyondsoft.com>
+               王聪  Wang Cong <xiyou.wangcong@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+如何参与Linux内核开发
+---------------------
+
+这是一篇将如何参与Linux内核开发的相关问题一网打尽的终极秘笈。它将指导你
+成为一名Linux内核开发者，并且学会如何同Linux内核开发社区合作。它尽可能不
+包括任何关于内核编程的技术细节，但会给你指引一条获得这些知识的正确途径。
+
+如果这篇文章中的任何内容不再适用，请给文末列出的文件维护者发送补丁。
+
+
+入门
+----
+
+你想了解如何成为一名Linux内核开发者？或者老板吩咐你“给这个设备写个Linux
+驱动程序”？这篇文章的目的就是教会你达成这些目标的全部诀窍，它将描述你需
+要经过的流程以及给出如何同内核社区合作的一些提示。它还将试图解释内核社区
+为何这样运作。
+
+Linux内核大部分是由C语言写成的，一些体系结构相关的代码用到了汇编语言。要
+参与内核开发，你必须精通C语言。除非你想为某个架构开发底层代码，否则你并
+不需要了解（任何体系结构的）汇编语言。下面列举的书籍虽然不能替代扎实的C
+语言教育和多年的开发经验，但如果需要的话，做为参考还是不错的：
+ - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
+   《C程序设计语言（第2版·新版）》（徐宝文 李志 译）[机械工业出版社]
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+   《实用C语言编程（第三版）》（郭大海 译）[中国电力出版社]
+ - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
+   《C语言参考手册（原书第5版）》（邱仲潘 等译）[机械工业出版社]
+
+Linux内核使用GNU C和GNU工具链开发。虽然它遵循ISO C89标准，但也用到了一些
+标准中没有定义的扩展。内核是自给自足的C环境，不依赖于标准C库的支持，所以
+并不支持C标准中的部分定义。比如long long类型的大数除法和浮点运算就不允许
+使用。有时候确实很难弄清楚内核对工具链的要求和它所使用的扩展，不幸的是目
+前还没有明确的参考资料可以解释它们。请查阅gcc信息页（使用“info gcc”命令
+显示）获得一些这方面信息。
+
+请记住你是在学习怎么和已经存在的开发社区打交道。它由一群形形色色的人组成，
+他们对代码、风格和过程有着很高的标准。这些标准是在长期实践中总结出来的，
+适应于地理上分散的大型开发团队。它们已经被很好得整理成档，建议你在开发
+之前尽可能多的学习这些标准，而不要期望别人来适应你或者你公司的行为方式。
+
+
+法律问题
+--------
+
+Linux内核源代码都是在GPL（通用公共许可证）的保护下发布的。要了解这种许可
+的细节请查看源代码主目录下的COPYING文件。如果你对它还有更深入问题请联系
+律师，而不要在Linux内核邮件组上提问。因为邮件组里的人并不是律师，不要期
+望他们的话有法律效力。
+
+对于GPL的常见问题和解答，请访问以下链接：
+	http://www.gnu.org/licenses/gpl-faq.html
+
+
+文档
+----
+
+Linux内核代码中包含有大量的文档。这些文档对于学习如何与内核社区互动有着
+不可估量的价值。当一个新的功能被加入内核，最好把解释如何使用这个功能的文
+档也放进内核。当内核的改动导致面向用户空间的接口发生变化时，最好将相关信
+息或手册页(manpages)的补丁发到mtk.manpages@gmail.com，以向手册页(manpages)
+的维护者解释这些变化。
+
+以下是内核代码中需要阅读的文档：
+  README
+    文件简要介绍了Linux内核的背景，并且描述了如何配置和编译内核。内核的
+    新用户应该从这里开始。
+
+  Documentation/process/changes.rst
+    文件给出了用来编译和使用内核所需要的最小软件包列表。
+
+  Documentation/process/coding-style.rst
+    描述Linux内核的代码风格和理由。所有新代码需要遵守这篇文档中定义的规
+    范。大多数维护者只会接收符合规定的补丁，很多人也只会帮忙检查符合风格
+    的代码。
+
+  Documentation/process/submitting-patches.rst
+  Documentation/process/submitting-drivers.rst
+    这两份文档明确描述如何创建和发送补丁，其中包括（但不仅限于)：
+       - 邮件内容
+       - 邮件格式
+       - 选择收件人
+    遵守这些规定并不能保证提交成功（因为所有补丁需要通过严格的内容和风格
+    审查），但是忽视他们几乎就意味着失败。
+
+    其他关于如何正确地生成补丁的优秀文档包括：
+    "The Perfect Patch"
+        http://www.ozlabs.org/~akpm/stuff/tpp.txt
+    "Linux kernel patch submission format"
+        http://linux.yyz.us/patch-format.html
+
+  Documentation/process/stable-api-nonsense.rst
+    论证内核为什么特意不包括稳定的内核内部API，也就是说不包括像这样的特
+    性：
+       - 子系统中间层（为了兼容性？）
+       - 在不同操作系统间易于移植的驱动程序
+       - 减缓（甚至阻止）内核代码的快速变化
+    这篇文档对于理解Linux的开发哲学至关重要。对于将开发平台从其他操作系
+    统转移到Linux的人来说也很重要。
+
+  Documentation/admin-guide/security-bugs.rst
+    如果你认为自己发现了Linux内核的安全性问题，请根据这篇文档中的步骤来
+    提醒其他内核开发者并帮助解决这个问题。
+
+  Documentation/process/management-style.rst
+    描述内核维护者的工作方法及其共有特点。这对于刚刚接触内核开发（或者对
+    它感到好奇）的人来说很重要，因为它解释了很多对于内核维护者独特行为的
+    普遍误解与迷惑。
+
+  Documentation/process/stable-kernel-rules.rst
+    解释了稳定版内核发布的规则，以及如何将改动放入这些版本的步骤。
+
+  Documentation/process/kernel-docs.rst
+    有助于内核开发的外部文档列表。如果你在内核自带的文档中没有找到你想找
+    的内容，可以查看这些文档。
+
+  Documentation/process/applying-patches.rst
+    关于补丁是什么以及如何将它打在不同内核开发分支上的好介绍
+
+内核还拥有大量从代码自动生成的文档。它包含内核内部API的全面介绍以及如何
+妥善处理加锁的规则。生成的文档会放在 Documentation/DocBook/目录下。在内
+核源码的主目录中使用以下不同命令将会分别生成PDF、Postscript、HTML和手册
+页等不同格式的文档：
+    make pdfdocs
+    make psdocs
+    make htmldocs
+    make mandocs
+
+
+如何成为内核开发者
+------------------
+如果你对Linux内核开发一无所知，你应该访问“Linux内核新手”计划：
+	http://kernelnewbies.org
+它拥有一个可以问各种最基本的内核开发问题的邮件列表（在提问之前一定要记得
+查找已往的邮件，确认是否有人已经回答过相同的问题）。它还拥有一个可以获得
+实时反馈的IRC聊天频道，以及大量对于学习Linux内核开发相当有帮助的文档。
+
+网站简要介绍了源代码组织结构、子系统划分以及目前正在进行的项目（包括内核
+中的和单独维护的）。它还提供了一些基本的帮助信息，比如如何编译内核和打补
+丁。
+
+如果你想加入内核开发社区并协助完成一些任务，却找不到从哪里开始，可以访问
+“Linux内核房管员”计划：
+	http://kernelnewbies.org/KernelJanitors
+这是极佳的起点。它提供一个相对简单的任务列表，列出内核代码中需要被重新
+整理或者改正的地方。通过和负责这个计划的开发者们一同工作，你会学到将补丁
+集成进内核的基本原理。如果还没有决定下一步要做什么的话，你还可能会得到方
+向性的指点。
+
+如果你已经有一些现成的代码想要放到内核中，但是需要一些帮助来使它们拥有正
+确的格式。请访问“内核导师”计划。这个计划就是用来帮助你完成这个目标的。它
+是一个邮件列表，地址如下：
+	http://selenic.com/mailman/listinfo/kernel-mentors
+
+在真正动手修改内核代码之前，理解要修改的代码如何运作是必需的。要达到这个
+目的，没什么办法比直接读代码更有效了（大多数花招都会有相应的注释），而且
+一些特制的工具还可以提供帮助。例如，“Linux代码交叉引用”项目就是一个值得
+特别推荐的帮助工具，它将源代码显示在有编目和索引的网页上。其中一个更新及
+时的内核源码库，可以通过以下地址访问：
+	http://sosdg.org/~coywolf/lxr/
+
+
+开发流程
+--------
+
+目前Linux内核开发流程包括几个“主内核分支”和很多子系统相关的内核分支。这
+些分支包括：
+  - 2.6.x主内核源码树
+  - 2.6.x.y -stable内核源码树
+  - 2.6.x -git内核补丁集
+  - 2.6.x -mm内核补丁集
+  - 子系统相关的内核源码树和补丁集
+
+
+2.6.x内核主源码树
+-----------------
+2.6.x内核是由Linus Torvalds（Linux的创造者）亲自维护的。你可以在
+kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循以下步
+骤：
+  - 每当一个新版本的内核被发布，为期两周的集成窗口将被打开。在这段时间里
+    维护者可以向Linus提交大段的修改，通常这些修改已经被放到-mm内核中几个
+    星期了。提交大量修改的首选方式是使用git工具（内核的代码版本管理工具
+    ，更多的信息可以在http://git-scm.com/获取），不过使用普通补丁也是可以
+    的。
+  - 两个星期以后-rc1版本内核发布。之后只有不包含可能影响整个内核稳定性的
+    新功能的补丁才可能被接受。请注意一个全新的驱动程序（或者文件系统）有
+    可能在-rc1后被接受是因为这样的修改完全独立，不会影响其他的代码，所以
+    没有造成内核退步的风险。在-rc1以后也可以用git向Linus提交补丁，不过所
+    有的补丁需要同时被发送到相应的公众邮件列表以征询意见。
+  - 当Linus认为当前的git源码树已经达到一个合理健全的状态足以发布供人测试
+    时，一个新的-rc版本就会被发布。计划是每周都发布新的-rc版本。
+  - 这个过程一直持续下去直到内核被认为达到足够稳定的状态，持续时间大概是
+    6个星期。
+
+关于内核发布，值得一提的是Andrew Morton在linux-kernel邮件列表中如是说：
+	“没有人知道新内核何时会被发布，因为发布是根据已知bug的情况来决定
+	的，而不是根据一个事先制定好的时间表。”
+
+
+2.6.x.y -stable（稳定版）内核源码树
+-----------------------------------
+由4个数字组成的内核版本号说明此内核是-stable版本。它们包含基于2.6.x版本
+内核的相对较小且至关重要的修补，这些修补针对安全性问题或者严重的内核退步。
+
+这种版本的内核适用于那些期望获得最新的稳定版内核并且不想参与测试开发版或
+者实验版的用户。
+
+如果没有2.6.x.y版本内核存在，那么最新的2.6.x版本内核就相当于是当前的稳定
+版内核。
+
+2.6.x.y版本由“稳定版”小组（邮件地址<stable@vger.kernel.org>）维护，一般隔周发
+布新版本。
+
+内核源码中的Documentation/process/stable-kernel-rules.rst文件具体描述了可被稳定
+版内核接受的修改类型以及发布的流程。
+
+
+2.6.x -git补丁集
+----------------
+Linus的内核源码树的每日快照，这个源码树是由git工具管理的（由此得名）。这
+些补丁通常每天更新以反映Linus的源码树的最新状态。它们比-rc版本的内核源码
+树更具试验性质，因为这个补丁集是全自动生成的，没有任何人来确认其是否真正
+健全。
+
+
+2.6.x -mm补丁集
+---------------
+这是由Andrew Morton维护的试验性内核补丁集。Andrew将所有子系统的内核源码
+和补丁拼凑到一起，并且加入了大量从linux-kernel邮件列表中采集的补丁。这个
+源码树是新功能和补丁的试炼场。当补丁在-mm补丁集里证明了其价值以后Andrew
+或者相应子系统的维护者会将补丁发给Linus以便集成进主内核源码树。
+
+在将所有新补丁发给Linus以集成到主内核源码树之前，我们非常鼓励先把这些补
+丁放在-mm版内核源码树中进行测试。
+
+这些内核版本不适合在需要稳定运行的系统上运行，因为运行它们比运行任何其他
+内核分支都更具有风险。
+
+如果你想为内核开发进程提供帮助，请尝试并使用这些内核版本，并在
+linux-kernel邮件列表中提供反馈，告诉大家你遇到了问题还是一切正常。
+
+通常-mm版补丁集不光包括这些额外的试验性补丁，还包括发布时-git版主源码树
+中的改动。
+
+-mm版内核没有固定的发布周期，但是通常在每两个-rc版内核发布之间都会有若干
+个-mm版内核发布（一般是1至3个）。
+
+
+子系统相关内核源码树和补丁集
+----------------------------
+相当一部分内核子系统开发者会公开他们自己的开发源码树，以便其他人能了解内
+核的不同领域正在发生的事情。如上所述，这些源码树会被集成到-mm版本内核中。
+
+下面是目前可用的一些内核源码树的列表：
+  通过git管理的源码树：
+    - Kbuild开发源码树， Sam Ravnborg <sam@ravnborg.org>
+	git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
+
+    - ACPI开发源码树, Len Brown <len.brown@intel.com>
+	git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
+
+    - 块设备开发源码树, Jens Axboe <axboe@suse.de>
+	git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
+
+    - DRM开发源码树, Dave Airlie <airlied@linux.ie>
+	git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
+
+    - ia64开发源码树, Tony Luck <tony.luck@intel.com>
+	git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
+
+    - ieee1394开发源码树, Jody McIntyre <scjody@modernduck.com>
+	git.kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
+
+    - infiniband开发源码树, Roland Dreier <rolandd@cisco.com>
+	git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
+
+    - libata开发源码树, Jeff Garzik <jgarzik@pobox.com>
+	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
+
+    - 网络驱动程序开发源码树, Jeff Garzik <jgarzik@pobox.com>
+	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
+
+    - pcmcia开发源码树, Dominik Brodowski <linux@dominikbrodowski.net>
+	git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
+
+    - SCSI开发源码树, James Bottomley <James.Bottomley@SteelEye.com>
+	git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
+
+  使用quilt管理的补丁集：
+    - USB, PCI, 驱动程序核心和I2C, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+	kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+    - x86-64, 部分i386, Andi Kleen <ak@suse.de>
+	ftp.firstfloor.org:/pub/ak/x86_64/quilt/
+
+  其他内核源码树可以在http://git.kernel.org的列表中和MAINTAINERS文件里
+  找到。
+
+报告bug
+-------
+
+bugzilla.kernel.org是Linux内核开发者们用来跟踪内核Bug的网站。我们鼓励用
+户在这个工具中报告找到的所有bug。如何使用内核bugzilla的细节请访问：
+	http://test.kernel.org/bugzilla/faq.html
+
+内核源码主目录中的admin-guide/reporting-bugs.rst文件里有一个很好的模板。它指导用户如何报
+告可能的内核bug以及需要提供哪些信息来帮助内核开发者们找到问题的根源。
+
+
+利用bug报告
+-----------
+
+练习内核开发技能的最好办法就是修改其他人报告的bug。你不光可以帮助内核变
+得更加稳定，还可以学会如何解决实际问题从而提高自己的技能，并且让其他开发
+者感受到你的存在。修改bug是赢得其他开发者赞誉的最好办法，因为并不是很多
+人都喜欢浪费时间去修改别人报告的bug。
+
+要尝试修改已知的bug，请访问http://bugzilla.kernel.org网址。如果你想获得
+最新bug的通知，可以订阅bugme-new邮件列表（只有新的bug报告会被寄到这里）
+或者订阅bugme-janitor邮件列表（所有bugzilla的变动都会被寄到这里）。
+
+	https://lists.linux-foundation.org/mailman/listinfo/bugme-new
+	https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
+
+
+邮件列表
+--------
+
+正如上面的文档所描述，大多数的骨干内核开发者都加入了Linux Kernel邮件列
+表。如何订阅和退订列表的细节可以在这里找到：
+	http://vger.kernel.org/vger-lists.html#linux-kernel
+网上很多地方都有这个邮件列表的存档(archive)。可以使用搜索引擎来找到这些
+存档。比如：
+	http://dir.gmane.org/gmane.linux.kernel
+在发信之前，我们强烈建议你先在存档中搜索你想要讨论的问题。很多已经被详细
+讨论过的问题只在邮件列表的存档中可以找到。
+
+大多数内核子系统也有自己独立的邮件列表来协调各自的开发工作。从
+MAINTAINERS文件中可以找到不同话题对应的邮件列表。
+
+很多邮件列表架设在kernel.org服务器上。这些列表的信息可以在这里找到：
+	http://vger.kernel.org/vger-lists.html
+
+在使用这些邮件列表时，请记住保持良好的行为习惯。下面的链接提供了与这些列
+表（或任何其它邮件列表）交流的一些简单规则，虽然内容有点滥竽充数。
+	http://www.albion.com/netiquette/
+
+当有很多人回复你的邮件时，邮件的抄送列表会变得很长。请不要将任何人从抄送
+列表中删除，除非你有足够的理由这么做。也不要只回复到邮件列表。请习惯于同
+一封邮件接收两次（一封来自发送者一封来自邮件列表），而不要试图通过添加一
+些奇特的邮件头来解决这个问题，人们不会喜欢的。
+
+记住保留你所回复内容的上下文和源头。在你回复邮件的顶部保留“某某某说到……”
+这几行。将你的评论加在被引用的段落之间而不要放在邮件的顶部。
+
+如果你在邮件中附带补丁，请确认它们是可以直接阅读的纯文本（如
+Documentation/process/submitting-patches.rst文档中所述）。内核开发者们不希望遇到附件
+或者被压缩了的补丁。只有这样才能保证他们可以直接评论你的每行代码。请确保
+你使用的邮件发送程序不会修改空格和制表符。一个防范性的测试方法是先将邮件
+发送给自己，然后自己尝试是否可以顺利地打上收到的补丁。如果测试不成功，请
+调整或者更换你的邮件发送程序直到它正确工作为止。
+
+总而言之，请尊重其他的邮件列表订阅者。
+
+
+同内核社区合作
+----------------
+
+内核社区的目标就是提供尽善尽美的内核。所以当你提交补丁期望被接受进内核的
+时候，它的技术价值以及其他方面都将被评审。那么你可能会得到什么呢？
+  - 批评
+  - 评论
+  - 要求修改
+  - 要求证明修改的必要性
+  - 沉默
+
+要记住，这些是把补丁放进内核的正常情况。你必须学会听取对补丁的批评和评论，
+从技术层面评估它们，然后要么重写你的补丁要么简明扼要地论证修改是不必要
+的。如果你发的邮件没有得到任何回应，请过几天后再试一次，因为有时信件会湮
+没在茫茫信海中。
+
+你不应该做的事情：
+  - 期望自己的补丁不受任何质疑就直接被接受
+  - 翻脸
+  - 忽略别人的评论
+  - 没有按照别人的要求做任何修改就重新提交
+
+在一个努力追寻最好技术方案的社区里，对于一个补丁有多少好处总会有不同的见
+解。你必须要抱着合作的态度，愿意改变自己的观点来适应内核的风格。或者至少
+愿意去证明你的想法是有价值的。记住，犯错误是允许的，只要你愿意朝着正确的
+方案去努力。
+
+如果你的第一个补丁换来的是一堆修改建议，这是很正常的。这并不代表你的补丁
+不会被接受，也不意味着有人和你作对。你只需要改正所有提出的问题然后重新发
+送你的补丁。
+
+内核社区和公司文化的差异
+------------------------
+
+内核社区的工作模式同大多数传统公司开发队伍的工作模式并不相同。下面这些例
+子，可以帮助你避免某些可能发生问题：
+  用这些话介绍你的修改提案会有好处：
+    - 它同时解决了多个问题
+    - 它删除了2000行代码
+    - 这是补丁，它已经解释了我想要说明的
+    - 我在5种不同的体系结构上测试过它……
+    - 这是一系列小补丁用来……
+    - 这个修改提高了普通机器的性能……
+
+  应该避免如下的说法：
+    - 我们在AIX/ptx/Solaris就是这么做的，所以这么做肯定是好的……
+    - 我做这行已经20年了，所以……
+    - 为了我们公司赚钱考虑必须这么做
+    - 这是我们的企业产品线所需要的
+    - 这里是描述我观点的1000页设计文档
+    - 这是一个5000行的补丁用来……
+    - 我重写了现在乱七八糟的代码，这就是……
+    - 我被规定了最后期限，所以这个补丁需要立刻被接受
+
+另外一个内核社区与大部分传统公司的软件开发队伍不同的地方是无法面对面地交
+流。使用电子邮件和IRC聊天工具做为主要沟通工具的一个好处是性别和种族歧视
+将会更少。Linux内核的工作环境更能接受妇女和少数族群，因为每个人在别人眼
+里只是一个邮件地址。国际化也帮助了公平的实现，因为你无法通过姓名来判断人
+的性别。男人有可能叫李丽，女人也有可能叫王刚。大多数在Linux内核上工作过
+并表达过看法的女性对在linux上工作的经历都给出了正面的评价。
+
+对于一些不习惯使用英语的人来说，语言可能是一个引起问题的障碍。在邮件列表
+中要正确地表达想法必需良好地掌握语言，所以建议你在发送邮件之前最好检查一
+下英文写得是否正确。
+
+
+拆分修改
+--------
+
+Linux内核社区并不喜欢一下接收大段的代码。修改需要被恰当地介绍、讨论并且
+拆分成独立的小段。这几乎完全和公司中的习惯背道而驰。你的想法应该在开发最
+开始的阶段就让大家知道，这样你就可以及时获得对你正在进行的开发的反馈。这
+样也会让社区觉得你是在和他们协作，而不是仅仅把他们当作倾销新功能的对象。
+无论如何，你不要一次性地向邮件列表发送50封信，你的补丁序列应该永远用不到
+这么多。
+
+将补丁拆开的原因如下：
+
+1) 小的补丁更有可能被接受，因为它们不需要太多的时间和精力去验证其正确性。
+   一个5行的补丁，可能在维护者看了一眼以后就会被接受。而500行的补丁则
+   需要数个小时来审查其正确性（所需时间随补丁大小增加大约呈指数级增长）。
+
+   当出了问题的时候，小的补丁也会让调试变得非常容易。一个一个补丁地回溯
+   将会比仔细剖析一个被打上的大补丁（这个补丁破坏了其他东西）容易得多。
+
+2）不光发送小的补丁很重要，在提交之前重新编排、化简（或者仅仅重新排列）
+   补丁也是很重要的。
+
+这里有内核开发者Al Viro打的一个比方：
+	“想象一个老师正在给学生批改数学作业。老师并不希望看到学生为了得
+	到正确解法所进行的尝试和产生的错误。他希望看到的是最干净最优雅的
+	解答。好学生了解这点，绝不会把最终解决之前的中间方案提交上去。”
+
+	内核开发也是这样。维护者和评审者不希望看到一个人在解决问题时的思
+	考过程。他们只希望看到简单和优雅的解决方案。
+
+直接给出一流的解决方案，和社区一起协作讨论尚未完成的工作，这两者之间似乎
+很难找到一个平衡点。所以最好尽早开始收集有利于你进行改进的反馈；同时也要
+保证修改分成很多小块，这样在整个项目都准备好被包含进内核之前，其中的一部
+分可能会先被接收。
+
+必须了解这样做是不可接受的：试图将未完成的工作提交进内核，然后再找时间修
+复。
+
+
+证明修改的必要性
+----------------
+除了将补丁拆成小块，很重要的一点是让Linux社区了解他们为什么需要这样修改。
+你必须证明新功能是有人需要的并且是有用的。
+
+
+记录修改
+--------
+
+当你发送补丁的时候，需要特别留意邮件正文的内容。因为这里的信息将会做为补
+丁的修改记录(ChangeLog)，会被一直保留以备大家查阅。它需要完全地描述补丁，
+包括：
+  - 为什么需要这个修改
+  - 补丁的总体设计
+  - 实现细节
+  - 测试结果
+
+想了解它具体应该看起来像什么，请查阅以下文档中的“ChangeLog”章节：
+  “The Perfect Patch”
+  	 http://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+
+这些事情有时候做起来很难。要在任何方面都做到完美可能需要好几年时间。这是
+一个持续提高的过程，它需要大量的耐心和决心。只要不放弃，你一定可以做到。
+很多人已经做到了，而他们都曾经和现在的你站在同样的起点上。
+
+
+---------------
+感谢Paolo Ciarrocchi允许“开发流程”部分基于他所写的文章
+(http://www.kerneltravel.net/newbie/2.6-development_process)，感谢Randy
+Dunlap和Gerrit Huizenga完善了应该说和不该说的列表。感谢Pat Mochel, Hanna
+Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
+Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
+Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
+Kerrisk和Alex Shepard的评审、建议和贡献。没有他们的帮助，这篇文档是不可
+能完成的。
+
+
+
+英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/io_ordering.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/io_ordering.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/io_ordering.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/io_ordering.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,67 @@
+Chinese translated version of Documentation/io_orderings.txt
+
+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: Lin Yongting <linyongting@gmail.com>
+---------------------------------------------------------------------
+Documentation/io_ordering.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 林永听 Lin Yongting <linyongting@gmail.com>
+中文版翻译者： 林永听 Lin Yongting <linyongting@gmail.com>
+中文版校译者： 林永听 Lin Yongting <linyongting@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+
+在某些平台上，所谓的内存映射I/O是弱顺序。在这些平台上，驱动开发者有责任
+保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
+设备寄存器或桥寄存器，触发IO芯片清刷未处理的写操作到达设备后才处理读操作，
+而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
+这也可以保证后面的写操作只在前面的写操作之后到达设备（这非常类似于内存
+屏障操作，mb()，不过仅适用于I/O）。
+
+假设一个设备驱动程的具体例子：
+
+        ...
+CPU A:  spin_lock_irqsave(&dev_lock, flags)
+CPU A:  val = readl(my_status);
+CPU A:  ...
+CPU A:  writel(newval, ring_ptr);
+CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
+        ...
+CPU B:  spin_lock_irqsave(&dev_lock, flags)
+CPU B:  val = readl(my_status);
+CPU B:  ...
+CPU B:  writel(newval2, ring_ptr);
+CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
+        ...
+
+上述例子中，设备可能会先接收到newval2的值，然后接收到newval的值，问题就
+发生了。不过很容易通过下面方法来修复：
+
+        ...
+CPU A:  spin_lock_irqsave(&dev_lock, flags)
+CPU A:  val = readl(my_status);
+CPU A:  ...
+CPU A:  writel(newval, ring_ptr);
+CPU A:  (void)readl(safe_register); /* 配置寄存器？*/
+CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
+        ...
+CPU B:  spin_lock_irqsave(&dev_lock, flags)
+CPU B:  val = readl(my_status);
+CPU B:  ...
+CPU B:  writel(newval2, ring_ptr);
+CPU B:  (void)readl(safe_register); /* 配置寄存器？*/
+CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
+
+在解决方案中，读取safe_register寄存器，触发IO芯片清刷未处理的写操作，
+再处理后面的读操作，防止引发数据不一致问题。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/IRQ.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/IRQ.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/IRQ.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/IRQ.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,39 @@
+Chinese translated version of Documentation/IRQ.txt
+
+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.
+
+Maintainer: Eric W. Biederman <ebiederman@xmission.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/IRQ.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Eric W. Biederman <ebiederman@xmission.com>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+何为 IRQ?
+
+一个 IRQ 是来自某个设备的一个中断请求。目前，它们可以来自一个硬件引脚，
+或来自一个数据包。多个设备可能连接到同个硬件引脚，从而共享一个 IRQ。
+
+一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下，这是一个
+全局 irq_desc 数组的索引，但是除了在 linux/interrupt.h 中的实现，
+具体的细节是体系结构特定的。
+
+一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下，枚举的编号是
+该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况，
+枚举的是在两个 i8259 中断控制器中 16 个输入引脚。
+
+架构可以对 IRQ 编号指定额外的含义，在硬件涉及任何手工配置的情况下，
+是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/magic-number.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/magic-number.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/magic-number.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/magic-number.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,153 @@
+Chinese translated version of Documentation/magic-number.txt
+
+If you have any comment or update to the content, please post to LKML directly.
+However, if you have problem communicating in English you can also ask the
+Chinese maintainer for help.  Contact the Chinese maintainer, if this
+translation is outdated or there is problem with translation.
+
+Chinese maintainer: Jia Wei Wei <harryxiyou@gmail.com>
+---------------------------------------------------------------------
+Documentation/magic-number.txt的中文翻译
+
+如果想评论或更新本文的内容，请直接发信到LKML。如果你使用英文交流有困难的话，也可
+以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题，请联系中文版维护者。
+
+中文版维护者： 贾威威 Jia Wei Wei <harryxiyou@gmail.com>
+中文版翻译者： 贾威威 Jia Wei Wei <harryxiyou@gmail.com>
+中文版校译者： 贾威威 Jia Wei Wei <harryxiyou@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+这个文件是有关当前使用的魔术值注册表。当你给一个结构添加了一个魔术值，你也应该把这个魔术值添加到这个文件，因为我们最好把用于各种结构的魔术值统一起来。
+
+使用魔术值来保护内核数据结构是一个非常好的主意。这就允许你在运行期检查(a)一个结构是否已经被攻击，或者(b)你已经给一个例行程序通过了一个错误的结构。后一种情况特别地有用---特别是当你通过一个空指针指向结构体的时候。tty源码，例如，经常通过特定驱动使用这种方法并且反复地排列特定方面的结构。
+
+使用魔术值的方法是在结构的开始处声明的，如下：
+
+struct tty_ldisc {
+	int	magic;
+	...
+};
+
+当你以后给内核添加增强功能的时候，请遵守这条规则！这样就会节省数不清的调试时间，特别是一些古怪的情况，例如，数组超出范围并且重新写了超出部分。遵守这个规则，‪这些情况可以被快速地，安全地避免。
+
+		Theodore Ts'o
+		  31 Mar 94
+
+给当前的Linux 2.1.55添加魔术表。
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+现在应该最新的Linux 2.1.112.因为在特性冻结期间，不能在2.2.x前改变任何东西。这些条目被数域所排序。
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+更新魔术表到Linux 2.5.45。刚好越过特性冻结，但是有可能还会有一些新的魔术值在2.6.x之前融入到内核中。
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+更新魔术表到Linux 2.5.74。
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+魔术名                 地址         结构               所在文件
+===========================================================================
+PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
+CMAGIC                0x0111      user              include/linux/a.out.h
+MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
+HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
+APM_BIOS_MAGIC        0x4101      apm_user          arch/x86/kernel/apm_32.c
+CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
+DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
+DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
+FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
+FF_MAGIC              0x4646      fc_info           drivers/net/iph5526_novram.c
+ISICOM_MAGIC          0x4d54      isi_port          include/linux/isicom.h
+PTY_MAGIC             0x5001                        drivers/char/pty.c
+PPP_MAGIC             0x5002      ppp               include/linux/if_pppvar.h
+SERIAL_MAGIC          0x5301      async_struct      include/linux/serial.h
+SSTATE_MAGIC          0x5302      serial_state      include/linux/serial.h
+SLIP_MAGIC            0x5302      slip              drivers/net/slip.h
+STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
+X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
+SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
+AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
+TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
+MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
+TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
+MGSLPC_MAGIC          0x5402      mgslpc_info       drivers/char/pcmcia/synclink_cs.c
+TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
+USB_SERIAL_MAGIC      0x6702      usb_serial        drivers/usb/serial/usb-serial.h
+FULL_DUPLEX_MAGIC     0x6969                        drivers/net/ethernet/dec/tulip/de2104x.c
+USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
+RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
+USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
+CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
+RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
+LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
+GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
+RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
+NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
+RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
+BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
+ISDN_X25IFACE_MAGIC   0x1e75a2b9  isdn_x25iface_proto_data
+                                                    drivers/isdn/isdn_x25iface.h
+ECP_MAGIC             0x21504345  cdkecpsig         include/linux/cdk.h
+LSOMAGIC              0x27091997  lso               drivers/fc4/fc.c
+LSMAGIC               0x2a3b4d2a  ls                drivers/fc4/fc.c
+WANPIPE_MAGIC         0x414C4453  sdla_{dump,exec}  include/linux/wanpipe.h
+CS_CARD_MAGIC         0x43525553  cs_card           sound/oss/cs46xx.c
+LABELCL_MAGIC         0x4857434c  labelcl_info_s    include/asm/ia64/sn/labelcl.h
+ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
+CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
+ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
+SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
+CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
+SLAB_C_MAGIC          0x4f17a36d  kmem_cache        mm/slab.c
+COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
+I810_CARD_MAGIC       0x5072696E  i810_card         sound/oss/i810_audio.c
+TRIDENT_CARD_MAGIC    0x5072696E  trident_card      sound/oss/trident.c
+ROUTER_MAGIC          0x524d4157  wan_device        [in wanrouter.h pre 3.9]
+SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
+GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
+RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
+EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
+HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
+PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
+KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
+I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
+TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
+M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
+FW_HEADER_MAGIC       0x65726F66  fw_header         drivers/atm/fore200e.h
+SLOT_MAGIC            0x67267321  slot              drivers/hotplug/cpqphp.h
+SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
+LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
+OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
+M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
+VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
+KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
+PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
+NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
+ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
+CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
+DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
+YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
+CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
+QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
+QUEUE_MAGIC_USED      0xf7e1cc33  queue_entry       drivers/scsi/arm/queue.c
+HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
+NMI_MAGIC             0x48414d4d455201 nmi_s        arch/mips/include/asm/sn/nmi.h
+
+请注意，在声音记忆管理中仍然有一些特殊的为每个驱动定义的魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。
+
+IrDA子系统也使用了大量的自己的魔术值，查看include/net/irda/irda.h来获取他们完整的信息。
+
+HFS是另外一个比较大的使用魔术值的文件系统-你可以在fs/hfs/hfs.h中找到他们。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/oops-tracing.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/oops-tracing.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/oops-tracing.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/oops-tracing.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,212 @@
+Chinese translated version of Documentation/admin-guide/oops-tracing.rst
+
+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: Dave Young <hidave.darkstar@gmail.com>
+---------------------------------------------------------------------
+Documentation/admin-guide/oops-tracing.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 杨瑞 Dave Young <hidave.darkstar@gmail.com>
+中文版翻译者： 杨瑞 Dave Young <hidave.darkstar@gmail.com>
+中文版校译者： 李阳 Li Yang <leo@zh-kernel.org>
+               王聪 Wang Cong <xiyou.wangcong@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+注意： ksymoops 在2.6中是没有用的。 请以原有格式使用Oops(来自dmesg，等等)。
+忽略任何这样那样关于“解码Oops”或者“通过ksymoops运行”的文档。 如果你贴出运行过
+ksymoops的来自2.6的Oops，人们只会让你重贴一次。
+
+快速总结
+-------------
+
+发现Oops并发送给看似相关的内核领域的维护者。别太担心对不上号。如果你不确定就发给
+和你所做的事情相关的代码的负责人。 如果可重现试着描述怎样重构。 那甚至比oops更有
+价值。
+
+如果你对于发送给谁一无所知， 发给linux-kernel@vger.kernel.org。感谢你帮助Linux
+尽可能地稳定。
+
+Oops在哪里?
+----------------------
+
+通常Oops文本由klogd从内核缓冲区里读取并传给syslogd，由syslogd写到syslog文件中，
+典型地是/var/log/messages(依赖于/etc/syslog.conf)。有时klogd崩溃了,这种情况下你
+能够运行dmesg > file来从内核缓冲区中读取数据并保存下来。 否则你可以
+cat /proc/kmsg > file， 然而你必须介入中止传输， kmsg是一个“永不结束的文件”。如
+果机器崩溃坏到你不能输入命令或者磁盘不可用那么你有三种选择:-
+
+（1） 手抄屏幕上的文本待机器重启后再输入计算机。 麻烦但如果没有针对崩溃的准备，
+这是仅有的选择。 另外，你可以用数码相机把屏幕拍下来-不太好，但比没有强。 如果信
+息滚动到了终端的上面，你会发现以高分辩率启动（比如，vga=791）会让你读到更多的文
+本。（注意：这需要vesafb，所以对‘早期’的oops没有帮助）
+
+（2）用串口终端启动（请参看Documentation/admin-guide/serial-console.rst），运行一个null
+modem到另一台机器并用你喜欢的通讯工具获取输出。Minicom工作地很好。
+
+（3）使用Kdump（请参看Documentation/kdump/kdump.txt），
+使用在Documentation/kdump/gdbmacros.txt中定义的dmesg gdb宏，从旧的内存中提取内核
+环形缓冲区。
+
+完整信息
+----------------
+
+注意：以下来自于Linus的邮件适用于2.4内核。 我因为历史原因保留了它，并且因为其中
+一些信息仍然适用。 特别注意的是，请忽略任何ksymoops的引用。
+
+From: Linus Torvalds <torvalds@osdl.org>
+
+怎样跟踪Oops.. [原发到linux-kernel的一封邮件]
+
+主要的窍门是有五年和这些烦人的oops消息打交道的经验;-)
+
+实际上，你有办法使它更简单。我有两个不同的方法：
+
+	gdb /usr/src/linux/vmlinux
+	gdb> disassemble <offending_function>
+
+那是发现问题的简单办法，至少如果bug报告做的好的情况下（象这个一样-运行ksymoops
+得到oops发生的函数及函数内的偏移）。
+
+哦，如果报告发生的内核以相同的编译器和相似的配置编译它会有帮助的。
+
+另一件要做的事是反汇编bug报告的“Code”部分：ksymoops也会用正确的工具来做这件事，
+但如果没有那些工具你可以写一个傻程序：
+
+	char str[] = "\xXX\xXX\xXX...";
+	main(){}
+
+并用gcc -g编译它然后执行“disassemble str”（XX部分是由Oops报告的值-你可以仅剪切
+粘贴并用“\x”替换空格-我就是这么做的，因为我懒得写程序自动做这一切）。
+
+另外，你可以用scripts/decodecode这个shell脚本。它的使用方法是：
+decodecode < oops.txt
+
+“Code”之后的十六进制字节可能（在某些架构上）有一些当前指令之前的指令字节以及
+当前和之后的指令字节
+
+Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
+64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
+7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
+
+最后，如果你想知道代码来自哪里，你可以：
+
+	cd /usr/src/linux
+	make fs/buffer.s 	# 或任何产生BUG的文件
+
+然后你会比gdb反汇编更清楚的知道发生了什么。
+
+现在，问题是把你所拥有的所有数据结合起来：C源码（关于它应该怎样的一般知识），
+汇编代码及其反汇编得到的代码（另外还有从“oops”消息得到的寄存器状态-对了解毁坏的
+指针有用，而且当你有了汇编代码你也能拿其它的寄存器和任何它们对应的C表达式做匹配
+）。
+
+实际上，你仅需看看哪里不匹配（这个例子是“Code”反汇编和编译器生成的代码不匹配）。
+然后你须要找出为什么不匹配。通常很简单-你看到代码使用了空指针然后你看代码想知道
+空指针是怎么出现的，还有检查它是否合法..
+
+现在，如果明白这是一项耗时的工作而且需要一丁点儿的专心，没错。这就是我为什么大多
+只是忽略那些没有符号表信息的崩溃报告的原因：简单的说太难查找了（我有一些
+程序用于在内核代码段中搜索特定的模式，而且有时我也已经能找出那些崩溃的地方，但是
+仅仅是找出正确的序列也确实需要相当扎实的内核知识）
+
+_有时_会发生这种情况，我仅看到崩溃中的反汇编代码序列， 然后我马上就明白问题出在
+哪里。这时我才意识到自己干这个工作已经太长时间了;-)
+
+		Linus
+
+
+---------------------------------------------------------------------------
+关于Oops跟踪的注解：
+
+为了帮助Linus和其它内核开发者，klogd纳入了大量的支持来处理保护错误。为了拥有对
+地址解析的完整支持至少应该使用1.3-pl3的sysklogd包。
+
+当保护错误发生时，klogd守护进程自动把内核日志信息中的重要地址翻译成它们相应的符
+号。
+
+klogd执行两种类型的地址解析。首先是静态翻译其次是动态翻译。静态翻译和ksymoops
+一样使用System.map文件。为了做静态翻译klogd守护进程必须在初始化时能找到system
+map文件。关于klogd怎样搜索map文件请参看klogd手册页。
+
+动态地址翻译在使用内核可装载模块时很重要。 因为内核模块的内存是从内核动态内存池
+里分配的，所以不管是模块开始位置还是模块中函数和符号的位置都不是固定的。
+
+内核支持允许程序决定装载哪些模块和它们在内存中位置的系统调用。使用这些系统调用
+klogd守护进程生成一张符号表用于调试发生在可装载模块中的保护错误。
+
+至少klogd会提供产生保护错误的模块名。还可有额外的符号信息供可装载模块开发者选择
+以从模块中输出符号信息。
+
+因为内核模块环境可能是动态的，所以必须有一种机制当模块环境发生改变时来通知klogd
+守护进程。 有一些可用的命令行选项允许klogd向当前执行中的守护进程发送信号，告知符
+号信息应该被刷新了。 更多信息请参看klogd手册页。
+
+sysklogd发布时包含一个补丁修改了modules-2.0.0包，无论何时一个模块装载或者卸载都
+会自动向klogd发送信号。打上这个补丁提供了必要的对调试发生于内核可装载模块的保护
+错误的无缝支持。
+
+以下是被klogd处理过的发生在可装载模块中的一个保护错误例子：
+---------------------------------------------------------------------------
+Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
+Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
+Aug 29 09:51:01 blizard kernel: *pde = 00000000
+Aug 29 09:51:01 blizard kernel: Oops: 0002
+Aug 29 09:51:01 blizard kernel: CPU:    0
+Aug 29 09:51:01 blizard kernel: EIP:    0010:[oops:_oops+16/3868]
+Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
+Aug 29 09:51:01 blizard kernel: eax: 315e97cc   ebx: 003a6f80   ecx: 001be77b   edx: 00237c0c
+Aug 29 09:51:01 blizard kernel: esi: 00000000   edi: bffffdb3   ebp: 00589f90   esp: 00589f8c
+Aug 29 09:51:01 blizard kernel: ds: 0018   es: 0018   fs: 002b   gs: 002b   ss: 0018
+Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
+Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
+Aug 29 09:51:01 blizard kernel:        00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
+Aug 29 09:51:01 blizard kernel:        bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
+Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
+Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
+---------------------------------------------------------------------------
+
+Dr. G.W. Wettstein           Oncology Research Div. Computing Facility
+Roger Maris Cancer Center    INTERNET: greg@wind.rmcc.com
+820 4th St. N.
+Fargo, ND  58122
+Phone: 701-234-7556
+
+
+---------------------------------------------------------------------------
+受污染的内核
+
+一些oops报告在程序记数器之后包含字符串'Tainted: '。这表明内核已经被一些东西给污
+染了。 该字符串之后紧跟着一系列的位置敏感的字符，每个代表一个特定的污染值。
+
+  1：'G'如果所有装载的模块都有GPL或相容的许可证，'P'如果装载了任何的专有模块。
+没有模块MODULE_LICENSE或者带有insmod认为是与GPL不相容的的MODULE_LICENSE的模块被
+认定是专有的。
+
+  2：'F'如果有任何通过“insmod -f”被强制装载的模块，' '如果所有模块都被正常装载。
+
+  3：'S'如果oops发生在SMP内核中，运行于没有证明安全运行多处理器的硬件。 当前这种
+情况仅限于几种不支持SMP的速龙处理器。
+
+  4：'R'如果模块通过“insmod -f”被强制装载，' '如果所有模块都被正常装载。
+
+  5：'M'如果任何处理器报告了机器检查异常，' '如果没有发生机器检查异常。
+
+  6：'B'如果页释放函数发现了一个错误的页引用或者一些非预期的页标志。
+
+  7：'U'如果用户或者用户应用程序特别请求设置污染标志，否则' '。
+
+  8：'D'如果内核刚刚死掉，比如有OOPS或者BUG。
+
+使用'Tainted: '字符串的主要原因是要告诉内核调试者，这是否是一个干净的内核亦或发
+生了任何的不正常的事。污染是永久的：即使出错的模块已经被卸载了，污染值仍然存在，
+以表明内核不再值得信任。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/SecurityBugs linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/SecurityBugs
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/SecurityBugs	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/SecurityBugs	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,50 @@
+Chinese translated version of Documentation/admin-guide/security-bugs.rst
+
+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/admin-guide/security-bugs.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 贾威威 Harry Wei <harryxiyou@gmail.com>
+中文版翻译者： 贾威威 Harry Wei <harryxiyou@gmail.com>
+中文版校译者： 贾威威 Harry Wei <harryxiyou@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+Linux内核开发者认为安全非常重要。因此，我们想要知道当一个有关于
+安全的漏洞被发现的时候，并且它可能会被尽快的修复或者公开。请把这个安全
+漏洞报告给Linux内核安全团队。
+
+1) 联系
+
+linux内核安全团队可以通过email<security@kernel.org>来联系。这是
+一组独立的安全工作人员，可以帮助改善漏洞报告并且公布和取消一个修复。安
+全团队有可能会从部分的维护者那里引进额外的帮助来了解并且修复安全漏洞。
+当遇到任何漏洞，所能提供的信息越多就越能诊断和修复。如果你不清楚什么
+是有帮助的信息，那就请重温一下admin-guide/reporting-bugs.rst文件中的概述过程。任
+何攻击性的代码都是非常有用的，未经报告者的同意不会被取消，除非它已经
+被公布于众。
+
+2) 公开
+
+Linux内核安全团队的宗旨就是和漏洞提交者一起处理漏洞的解决方案直
+到公开。我们喜欢尽快地完全公开漏洞。当一个漏洞或者修复还没有被完全地理
+解，解决方案没有通过测试或者供应商协调，可以合理地延迟公开。然而，我们
+期望这些延迟尽可能的短些，是可数的几天，而不是几个星期或者几个月。公开
+日期是通过安全团队和漏洞提供者以及供应商洽谈后的结果。公开时间表是从很
+短（特殊的，它已经被公众所知道）到几个星期。作为一个基本的默认政策，我
+们所期望通知公众的日期是7天的安排。
+
+3) 保密协议
+
+Linux内核安全团队不是一个正式的团体，因此不能加入任何的保密协议。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/sparse.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/sparse.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/sparse.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/sparse.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,95 @@
+﻿Chinese translated version of Documentation/sparse.txt
+
+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: Li Yang <leo@zh-kernel.org>
+---------------------------------------------------------------------
+Documentation/sparse.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 李阳  Li Yang <leo@zh-kernel.org>
+中文版翻译者： 李阳  Li Yang <leo@zh-kernel.org>
+
+
+以下为正文
+---------------------------------------------------------------------
+
+Copyright 2004 Linus Torvalds
+Copyright 2004 Pavel Machek <pavel@ucw.cz>
+Copyright 2006 Bob Copeland <me@bobcopeland.com>
+
+使用 sparse 工具做类型检查
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+"__bitwise" 是一种类型属性，所以你应该这样使用它：
+
+        typedef int __bitwise pm_request_t;
+
+        enum pm_request {
+                PM_SUSPEND = (__force pm_request_t) 1,
+                PM_RESUME = (__force pm_request_t) 2
+        };
+
+这样会使 PM_SUSPEND 和 PM_RESUME 成为位方式(bitwise)整数（使用"__force"
+是因为 sparse 会抱怨改变位方式的类型转换，但是这里我们确实需要强制进行转
+换）。而且因为所有枚举值都使用了相同的类型，这里的"enum pm_request"也将
+会使用那个类型做为底层实现。
+
+而且使用 gcc 编译的时候，所有的 __bitwise/__force 都会消失，最后在 gcc
+看来它们只不过是普通的整数。
+
+坦白来说，你并不需要使用枚举类型。上面那些实际都可以浓缩成一个特殊的"int
+__bitwise"类型。
+
+所以更简单的办法只要这样做：
+
+	typedef int __bitwise pm_request_t;
+
+	#define PM_SUSPEND ((__force pm_request_t) 1)
+	#define PM_RESUME ((__force pm_request_t) 2)
+
+现在你就有了严格的类型检查所需要的所有基础架构。
+
+一个小提醒：常数整数"0"是特殊的。你可以直接把常数零当作位方式整数使用而
+不用担心 sparse 会抱怨。这是因为"bitwise"（恰如其名）是用来确保不同位方
+式类型不会被弄混（小尾模式，大尾模式，cpu尾模式，或者其他），对他们来说
+常数"0"确实是特殊的。
+
+获取 sparse 工具
+~~~~~~~~~~~~~~~~
+
+你可以从 Sparse 的主页获取最新的发布版本：
+
+	http://www.kernel.org/pub/linux/kernel/people/josh/sparse/
+
+或者，你也可以使用 git 克隆最新的 sparse 开发版本：
+
+	git://git.kernel.org/pub/scm/linux/kernel/git/josh/sparse.git
+
+DaveJ 把每小时自动生成的 git 源码树 tar 包放在以下地址：
+
+	http://www.codemonkey.org.uk/projects/git-snapshots/sparse/
+
+一旦你下载了源码，只要以普通用户身份运行：
+
+	make
+	make install
+
+它将会被自动安装到你的 ~/bin 目录下。
+
+使用 sparse 工具
+~~~~~~~~~~~~~~~~
+
+用"make C=1"命令来编译内核，会对所有重新编译的 C 文件使用 sparse 工具。
+或者使用"make C=2"命令，无论文件是否被重新编译都会对其使用 sparse 工具。
+如果你已经编译了内核，用后一种方式可以很快地检查整个源码树。
+
+make 的可选变量 CHECKFLAGS 可以用来向 sparse 工具传递参数。编译系统会自
+动向 sparse 工具传递 -Wbitwise 参数。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/stable_api_nonsense.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/stable_api_nonsense.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/stable_api_nonsense.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/stable_api_nonsense.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,157 @@
+Chinese translated version of Documentation/process/stable-api-nonsense.rst
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have problem
+communicating in English you can also ask the Chinese maintainer for help.
+Contact the Chinese maintainer, if this translation is outdated or there
+is problem with translation.
+
+Maintainer: Greg Kroah-Hartman <greg@kroah.com>
+Chinese maintainer: TripleX Chung <zhongyu@18mail.cn>
+---------------------------------------------------------------------
+Documentation/process/stable-api-nonsense.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
+中文版维护者： 钟宇  TripleX Chung <zhongyu@18mail.cn>
+中文版翻译者： 钟宇  TripleX Chung <zhongyu@18mail.cn>
+中文版校译者： 李阳  Li Yang <leoli@freescale.com>
+以下为正文
+---------------------------------------------------------------------
+
+写作本文档的目的，是为了解释为什么Linux既没有二进制内核接口，也没有稳定
+的内核接口。这里所说的内核接口，是指内核里的接口，而不是内核和用户空间
+的接口。内核到用户空间的接口，是提供给应用程序使用的系统调用，系统调用
+在历史上几乎没有过变化，将来也不会有变化。我有一些老应用程序是在0.9版本
+或者更早版本的内核上编译的，在使用2.6版本内核的Linux发布上依然用得很好
+。用户和应用程序作者可以将这个接口看成是稳定的。
+
+
+执行纲要
+--------
+
+你也许以为自己想要稳定的内核接口，但是你不清楚你要的实际上不是它。你需
+要的其实是稳定的驱动程序，而你只有将驱动程序放到公版内核的源代码树里，
+才有可能达到这个目的。而且这样做还有很多其它好处，正是因为这些好处使得
+Linux能成为强壮，稳定，成熟的操作系统，这也是你最开始选择Linux的原因。
+
+
+入门
+-----
+
+只有那些写驱动程序的“怪人”才会担心内核接口的改变，对广大用户来说，既
+看不到内核接口，也不需要去关心它。
+
+首先，我不打算讨论关于任何非GPL许可的内核驱动的法律问题，这些非GPL许可
+的驱动程序包括不公开源代码，隐藏源代码，二进制或者是用源代码包装，或者
+是其它任何形式的不能以GPL许可公开源代码的驱动程序。如果有法律问题，请咨
+询律师，我只是一个程序员，所以我只打算探讨技术问题（不是小看法律问题，
+法律问题很实际，并且需要一直关注）。
+
+既然只谈技术问题，我们就有了下面两个主题：二进制内核接口和稳定的内核源
+代码接口。这两个问题是互相关联的，让我们先解决掉二进制接口的问题。
+
+
+二进制内核接口
+--------------
+假如我们有一个稳定的内核源代码接口，那么自然而然的，我们就拥有了稳定的
+二进制接口，是这样的吗？错。让我们看看关于Linux内核的几点事实：
+    - 取决于所用的C编译器的版本，不同的内核数据结构里的结构体的对齐方
+式会有差别，代码中不同函数的表现形式也不一样（函数是不是被inline编译取
+决于编译器行为）。不同的函数的表现形式并不重要，但是数据结构内部的对齐
+方式很关键。
+    - 取决于内核的配置选项，不同的选项会让内核的很多东西发生改变：
+      - 同一个结构体可能包含不同的成员变量
+      - 有的函数可能根本不会被实现（比如编译的时候没有选择SMP支持
+，一些锁函数就会被定义成空函数）。
+      - 内核使用的内存会以不同的方式对齐，这取决于不同的内核配置选
+项。
+    - Linux可以在很多的不同体系结构的处理器上运行。在某个体系结构上编
+译好的二进制驱动程序，不可能在另外一个体系结构上正确的运行。
+
+对于一个特定的内核，满足这些条件并不难，使用同一个C编译器和同样的内核配
+置选项来编译驱动程序模块就可以了。这对于给一个特定Linux发布的特定版本提
+供驱动程序，是完全可以满足需求的。但是如果你要给不同发布的不同版本都发
+布一个驱动程序，就需要在每个发布上用不同的内核设置参数都编译一次内核，
+这简直跟噩梦一样。而且还要注意到，每个Linux发布还提供不同的Linux内核，
+这些内核都针对不同的硬件类型进行了优化（有很多种不同的处理器，还有不同
+的内核设置选项）。所以每发布一次驱动程序，都需要提供很多不同版本的内核
+模块。
+
+相信我，如果你真的要采取这种发布方式，一定会慢慢疯掉，我很久以前就有过
+深刻的教训...
+
+
+稳定的内核源代码接口
+--------------------
+
+如果有人不将他的内核驱动程序，放入公版内核的源代码树，而又想让驱动程序
+一直保持在最新的内核中可用，那么这个话题将会变得没完没了。
+ 内核开发是持续而且快节奏的，从来都不会慢下来。内核开发人员在当前接口中
+找到bug，或者找到更好的实现方式。一旦发现这些，他们就很快会去修改当前的
+接口。修改接口意味着，函数名可能会改变，结构体可能被扩充或者删减，函数
+的参数也可能发生改变。一旦接口被修改，内核中使用这些接口的地方需要同时
+修正，这样才能保证所有的东西继续工作。
+
+举一个例子，内核的USB驱动程序接口在USB子系统的整个生命周期中，至少经历
+了三次重写。这些重写解决以下问题：
+    - 把数据流从同步模式改成非同步模式，这个改动减少了一些驱动程序的
+复杂度，提高了所有USB驱动程序的吞吐率，这样几乎所有的USB设备都能以最大
+速率工作了。
+    - 修改了USB核心代码中为USB驱动分配数据包内存的方式，所有的驱动都
+需要提供更多的参数给USB核心，以修正了很多已经被记录在案的死锁。
+
+这和一些封闭源代码的操作系统形成鲜明的对比，在那些操作系统上，不得不额
+外的维护旧的USB接口。这导致了一个可能性，新的开发者依然会不小心使用旧的
+接口，以不恰当的方式编写代码，进而影响到操作系统的稳定性。
+ 在上面的例子中，所有的开发者都同意这些重要的改动，在这样的情况下修改代
+价很低。如果Linux保持一个稳定的内核源代码接口，那么就得创建一个新的接口
+；旧的，有问题的接口必须一直维护，给Linux USB开发者带来额外的工作。既然
+所有的Linux USB驱动的作者都是利用自己的时间工作，那么要求他们去做毫无意
+义的免费额外工作，是不可能的。
+ 安全问题对Linux来说十分重要。一个安全问题被发现，就会在短时间内得到修
+正。在很多情况下，这将导致Linux内核中的一些接口被重写，以从根本上避免安
+全问题。一旦接口被重写，所有使用这些接口的驱动程序，必须同时得到修正，
+以确定安全问题已经得到修复并且不可能在未来还有同样的安全问题。如果内核
+内部接口不允许改变，那么就不可能修复这样的安全问题，也不可能确认这样的
+安全问题以后不会发生。
+开发者一直在清理内核接口。如果一个接口没有人在使用了，它就会被删除。这
+样可以确保内核尽可能的小，而且所有潜在的接口都会得到尽可能完整的测试
+（没有人使用的接口是不可能得到良好的测试的）。
+
+
+要做什么
+-------
+
+如果你写了一个Linux内核驱动，但是它还不在Linux源代码树里，作为一个开发
+者，你应该怎么做？为每个发布的每个版本提供一个二进制驱动，那简直是一个
+噩梦，要跟上永远处于变化之中的内核接口，也是一件辛苦活。
+很简单，让你的驱动进入内核源代码树（要记得我们在谈论的是以GPL许可发行
+的驱动，如果你的代码不符合GPL，那么祝你好运，你只能自己解决这个问题了，
+你这个吸血鬼<把Andrew和Linus对吸血鬼的定义链接到这里>）。当你的代码加入
+公版内核源代码树之后，如果一个内核接口改变，你的驱动会直接被修改接口的
+那个人修改。保证你的驱动永远都可以编译通过，并且一直工作，你几乎不需要
+做什么事情。
+
+把驱动放到内核源代码树里会有很多的好处：
+    - 驱动的质量会提升，而维护成本（对原始作者来说）会下降。
+    - 其他人会给驱动添加新特性。
+    - 其他人会找到驱动中的bug并修复。
+    - 其他人会在驱动中找到性能优化的机会。
+    - 当外部的接口的改变需要修改驱动程序的时候，其他人会修改驱动程序
+。
+    - 不需要联系任何发行商，这个驱动会自动的随着所有的Linux发布一起发
+布。
+
+和别的操作系统相比，Linux为更多不同的设备提供现成的驱动，而且能在更多不
+同体系结构的处理器上支持这些设备。这个经过考验的开发模式，必然是错不了
+的 :)
+
+-------------
+感谢 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
+Robert Love, and Nishanth Aravamudan 对于本文档早期版本的评审和建议。
+
+英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/stable_kernel_rules.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/stable_kernel_rules.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/stable_kernel_rules.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/stable_kernel_rules.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,66 @@
+Chinese translated version of Documentation/process/stable-kernel-rules.rst
+
+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: TripleX Chung <triplex@zh-kernel.org>
+---------------------------------------------------------------------
+Documentation/process/stable-kernel-rules.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+
+中文版维护者： 钟宇  TripleX Chung <triplex@zh-kernel.org>
+中文版翻译者： 钟宇  TripleX Chung <triplex@zh-kernel.org>
+中文版校译者： 李阳  Li Yang <leo@zh-kernel.org>
+               Kangkai Yin <e12051@motorola.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+关于Linux 2.6稳定版发布，所有你想知道的事情。
+
+关于哪些类型的补丁可以被接收进入稳定版代码树，哪些不可以的规则：
+
+  - 必须是显而易见的正确，并且经过测试的。
+  - 连同上下文，不能大于100行。
+  - 必须只修正一件事情。
+  - 必须修正了一个给大家带来麻烦的真正的bug（不是“这也许是一个问题...”
+    那样的东西）。
+  - 必须修正带来如下后果的问题：编译错误（对被标记为CONFIG_BROKEN的例外），
+    内核崩溃，挂起，数据损坏，真正的安全问题，或者一些类似“哦，这不
+    好”的问题。简短的说，就是一些致命的问题。
+  - 没有“理论上的竞争条件”，除非能给出竞争条件如何被利用的解释。
+  - 不能存在任何的“琐碎的”修正（拼写修正，去掉多余空格之类的）。
+  - 必须被相关子系统的维护者接受。
+  - 必须遵循Documentation/process/submitting-patches.rst里的规则。
+
+向稳定版代码树提交补丁的过程：
+
+  - 在确认了补丁符合以上的规则后，将补丁发送到stable@vger.kernel.org。
+  - 如果补丁被接受到队列里，发送者会收到一个ACK回复，如果没有被接受，收
+    到的是NAK回复。回复需要几天的时间，这取决于开发者的时间安排。
+  - 被接受的补丁会被加到稳定版本队列里，等待其他开发者的审查。
+  - 安全方面的补丁不要发到这个列表，应该发送到security@kernel.org。
+
+审查周期：
+
+  - 当稳定版的维护者决定开始一个审查周期，补丁将被发送到审查委员会，以
+    及被补丁影响的领域的维护者（除非提交者就是该领域的维护者）并且抄送
+    到linux-kernel邮件列表。
+  - 审查委员会有48小时的时间，用来决定给该补丁回复ACK还是NAK。
+  - 如果委员会中有成员拒绝这个补丁，或者linux-kernel列表上有人反对这个
+    补丁，并提出维护者和审查委员会之前没有意识到的问题，补丁会从队列中
+    丢弃。
+  - 在审查周期结束的时候，那些得到ACK回应的补丁将会被加入到最新的稳定版
+    发布中，一个新的稳定版发布就此产生。
+  - 安全性补丁将从内核安全小组那里直接接收到稳定版代码树中，而不是通过
+    通常的审查周期。请联系内核安全小组以获得关于这个过程的更多细节。
+
+审查委员会：
+  - 由一些自愿承担这项任务的内核开发者，和几个非志愿的组成。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/SubmittingDrivers linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/SubmittingDrivers
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/SubmittingDrivers	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/SubmittingDrivers	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,164 @@
+﻿Chinese translated version of Documentation/process/submitting-drivers.rst
+
+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: Li Yang <leo@zh-kernel.org>
+---------------------------------------------------------------------
+Documentation/process/submitting-drivers.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 李阳  Li Yang <leo@zh-kernel.org>
+中文版翻译者： 李阳  Li Yang <leo@zh-kernel.org>
+中文版校译者： 陈琦 Maggie Chen <chenqi@beyondsoft.com>
+               王聪 Wang Cong <xiyou.wangcong@gmail.com>
+               张巍 Zhang Wei <Wei.Zhang@freescale.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+如何向 Linux 内核提交驱动程序
+-----------------------------
+
+这篇文档将会解释如何向不同的内核源码树提交设备驱动程序。请注意，如果你感
+兴趣的是显卡驱动程序，你也许应该访问 XFree86 项目(http://www.xfree86.org/)
+和／或 X.org 项目 (http://x.org)。
+
+另请参阅 Documentation/process/submitting-patches.rst 文档。
+
+
+分配设备号
+----------
+
+块设备和字符设备的主设备号与从设备号是由 Linux 命名编号分配权威 LANANA（
+现在是 Torben Mathiasen）负责分配。申请的网址是 http://www.lanana.org/。
+即使不准备提交到主流内核的设备驱动也需要在这里分配设备号。有关详细信息，
+请参阅 Documentation/admin-guide/devices.rst。
+
+如果你使用的不是已经分配的设备号，那么当你提交设备驱动的时候，它将会被强
+制分配一个新的设备号，即便这个设备号和你之前发给客户的截然不同。
+
+设备驱动的提交对象
+------------------
+
+Linux 2.0:
+	此内核源码树不接受新的驱动程序。
+
+Linux 2.2:
+	此内核源码树不接受新的驱动程序。
+
+Linux 2.4:
+	如果所属的代码领域在内核的 MAINTAINERS 文件中列有一个总维护者，
+	那么请将驱动程序提交给他。如果此维护者没有回应或者你找不到恰当的
+	维护者，那么请联系 Willy Tarreau <w@1wt.eu>。
+
+Linux 2.6:
+	除了遵循和 2.4 版内核同样的规则外，你还需要在 linux-kernel 邮件
+	列表上跟踪最新的 API 变化。向 Linux 2.6 内核提交驱动的顶级联系人
+	是 Andrew Morton <akpm@linux-foundation.org>。
+
+决定设备驱动能否被接受的条件
+----------------------------
+
+许可：		代码必须使用 GNU 通用公开许可证 (GPL) 提交给 Linux，但是
+		我们并不要求 GPL 是唯一的许可。你或许会希望同时使用多种
+		许可证发布，如果希望驱动程序可以被其他开源社区（比如BSD）
+		使用。请参考 include/linux/module.h 文件中所列出的可被
+		接受共存的许可。
+
+版权：		版权所有者必须同意使用 GPL 许可。最好提交者和版权所有者
+		是相同个人或实体。否则，必需列出授权使用 GPL 的版权所有
+		人或实体，以备验证之需。
+
+接口：		如果你的驱动程序使用现成的接口并且和其他同类的驱动程序行
+		为相似，而不是去发明无谓的新接口，那么它将会更容易被接受。
+		如果你需要一个 Linux 和 NT 的通用驱动接口，那么请在用
+		户空间实现它。
+
+代码：		请使用 Documentation/process/coding-style.rst 中所描述的 Linux 代码风
+		格。如果你的某些代码段（例如那些与 Windows 驱动程序包共
+		享的代码段）需要使用其他格式，而你却只希望维护一份代码，
+		那么请将它们很好地区分出来，并且注明原因。
+
+可移植性：	请注意，指针并不永远是 32 位的，不是所有的计算机都使用小
+		尾模式 (little endian) 存储数据，不是所有的人都拥有浮点
+		单元，不要随便在你的驱动程序里嵌入 x86 汇编指令。只能在
+		x86 上运行的驱动程序一般是不受欢迎的。虽然你可能只有 x86
+		硬件，很难测试驱动程序在其他平台上是否可用，但是确保代码
+		可以被轻松地移植却是很简单的。
+
+清晰度：	做到所有人都能修补这个驱动程序将会很有好处，因为这样你将
+		会直接收到修复的补丁而不是 bug 报告。如果你提交一个试图
+		隐藏硬件工作机理的驱动程序，那么它将会被扔进废纸篓。
+
+电源管理：	因为 Linux 正在被很多移动设备和桌面系统使用，所以你的驱
+		动程序也很有可能被使用在这些设备上。它应该支持最基本的电
+		源管理，即在需要的情况下实现系统级休眠和唤醒要用到的
+		.suspend 和 .resume 函数。你应该检查你的驱动程序是否能正
+		确地处理休眠与唤醒，如果实在无法确认，请至少把 .suspend
+		函数定义成返回 -ENOSYS（功能未实现）错误。你还应该尝试确
+		保你的驱动在什么都不干的情况下将耗电降到最低。要获得驱动
+		程序测试的指导，请参阅
+		Documentation/power/drivers-testing.txt。有关驱动程序电
+		源管理问题相对全面的概述，请参阅
+		Documentation/power/admin-guide/devices.rst。
+
+管理：		如果一个驱动程序的作者还在进行有效的维护，那么通常除了那
+		些明显正确且不需要任何检查的补丁以外，其他所有的补丁都会
+		被转发给作者。如果你希望成为驱动程序的联系人和更新者，最
+		好在代码注释中写明并且在 MAINTAINERS 文件中加入这个驱动
+		程序的条目。
+
+不影响设备驱动能否被接受的条件
+------------------------------
+
+供应商：	由硬件供应商来维护驱动程序通常是一件好事。不过，如果源码
+		树里已经有其他人提供了可稳定工作的驱动程序，那么请不要期
+		望“我是供应商”会成为内核改用你的驱动程序的理由。理想的情
+		况是：供应商与现有驱动程序的作者合作，构建一个统一完美的
+		驱动程序。
+
+作者：		驱动程序是由大的 Linux 公司研发还是由你个人编写，并不影
+		响其是否能被内核接受。没有人对内核源码树享有特权。只要你
+		充分了解内核社区，你就会发现这一点。
+
+
+资源列表
+--------
+
+Linux 内核主源码树：
+	ftp.??.kernel.org:/pub/linux/kernel/...
+	?? == 你的国家代码，例如 "cn"、"us"、"uk"、"fr" 等等
+
+Linux 内核邮件列表：
+	linux-kernel@vger.kernel.org
+	[可通过向majordomo@vger.kernel.org发邮件来订阅]
+
+Linux 设备驱动程序，第三版（探讨 2.6.10 版内核）：
+	http://lwn.net/Kernel/LDD3/ （免费版）
+
+LWN.net:
+	每周内核开发活动摘要 - http://lwn.net/
+	2.6 版中 API 的变更：
+		http://lwn.net/Articles/2.6-kernel-api/
+	将旧版内核的驱动程序移植到 2.6 版：
+		http://lwn.net/Articles/driver-porting/
+
+内核新手(KernelNewbies):
+	为新的内核开发者提供文档和帮助
+	http://kernelnewbies.org/
+
+Linux USB项目：
+	http://www.linux-usb.org/
+
+写内核驱动的“不要”（Arjan van de Ven著）:
+	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
+
+内核清洁工 (Kernel Janitor):
+	http://kernelnewbies.org/KernelJanitors
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/SubmittingPatches linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/SubmittingPatches
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/SubmittingPatches	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/SubmittingPatches	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,412 @@
+Chinese translated version of Documentation/process/submitting-patches.rst
+
+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: TripleX Chung <triplex@zh-kernel.org>
+---------------------------------------------------------------------
+Documentation/process/submitting-patches.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+中文版维护者： 钟宇 TripleX Chung <triplex@zh-kernel.org>
+中文版翻译者： 钟宇 TripleX Chung <triplex@zh-kernel.org>
+中文版校译者： 李阳 Li Yang <leo@zh-kernel.org>
+               王聪 Wang Cong <xiyou.wangcong@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+
+   如何让你的改动进入内核
+     或者
+  获得亲爱的 Linus Torvalds 的关注和处理
+----------------------------------
+
+对于想要将改动提交到 Linux 内核的个人或者公司来说，如果不熟悉“规矩”，
+提交的流程会让人畏惧。本文档收集了一系列建议，这些建议可以大大的提高你
+的改动被接受的机会。
+阅读 Documentation/process/submit-checklist.rst 来获得在提交代码前需要检查的项目的列
+表。如果你在提交一个驱动程序，那么同时阅读一下
+Documentation/process/submitting-drivers.rst 。
+
+
+--------------------------
+第一节 - 创建并发送你的改动
+--------------------------
+
+1) "diff -up"
+-----------
+
+使用 "diff -up" 或者 "diff -uprN" 来创建补丁。
+
+所有内核的改动，都是以补丁的形式呈现的，补丁由 diff(1) 生成。创建补丁的
+时候，要确认它是以 "unified diff" 格式创建的，这种格式由 diff(1) 的 '-u'
+参数生成。而且，请使用 '-p' 参数，那样会显示每个改动所在的C函数，使得
+产生的补丁容易读得多。补丁应该基于内核源代码树的根目录，而不是里边的任
+何子目录。
+为一个单独的文件创建补丁，一般来说这样做就够了：
+
+        SRCTREE= linux-2.6
+        MYFILE=  drivers/net/mydriver.c
+
+        cd $SRCTREE
+        cp $MYFILE $MYFILE.orig
+        vi $MYFILE      # make your change
+        cd ..
+        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
+
+为多个文件创建补丁，你可以解开一个没有修改过的内核源代码树，然后和你自
+己的代码树之间做 diff 。例如：
+
+        MYSRC= /devel/linux-2.6
+
+        tar xvfz linux-2.6.12.tar.gz
+        mv linux-2.6.12 linux-2.6.12-vanilla
+        diff -uprN -X linux-2.6.12-vanilla/Documentation/dontdiff \
+                linux-2.6.12-vanilla $MYSRC > /tmp/patch
+
+"dontdiff" 是内核在编译的时候产生的文件的列表，列表中的文件在 diff(1)
+产生的补丁里会被跳过。"dontdiff" 文件被包含在2.6.12和之后版本的内核源代
+码树中。对于更早的内核版本，你可以从
+<http://www.xenotime.net/linux/doc/dontdiff> 获取它。
+确定你的补丁里没有包含任何不属于这次补丁提交的额外文件。记得在用diff(1)
+生成补丁之后，审阅一次补丁，以确保准确。
+如果你的改动很散乱，你应该研究一下如何将补丁分割成独立的部分，将改动分
+割成一系列合乎逻辑的步骤。这样更容易让其他内核开发者审核，如果你想你的
+补丁被接受，这是很重要的。下面这些脚本能够帮助你做这件事情：
+Quilt:
+http://savannah.nongnu.org/projects/quilt
+
+2)描述你的改动。
+描述你的改动包含的技术细节。
+
+要多具体就写多具体。最糟糕的描述可能是像下面这些语句：“更新了某驱动程
+序”，“修正了某驱动程序的bug”，或者“这个补丁包含了某子系统的修改，请
+使用。”
+
+如果你的描述开始变长，这表示你也许需要拆分你的补丁了，请看第3小节，
+继续。
+
+3)拆分你的改动
+
+将改动拆分，逻辑类似的放到同一个补丁文件里。
+
+例如，如果你的改动里同时有bug修正和性能优化，那么把这些改动拆分到两个或
+者更多的补丁文件中。如果你的改动包含对API的修改，并且修改了驱动程序来适
+应这些新的API，那么把这些修改分成两个补丁。
+
+另一方面，如果你将一个单独的改动做成多个补丁文件，那么将它们合并成一个
+单独的补丁文件。这样一个逻辑上单独的改动只被包含在一个补丁文件里。
+
+如果有一个补丁依赖另外一个补丁来完成它的改动，那没问题。简单的在你的补
+丁描述里指出“这个补丁依赖某补丁”就好了。
+
+如果你不能将补丁浓缩成更少的文件，那么每次大约发送出15个，然后等待审查
+和整合。
+
+4)选择 e-mail 的收件人
+
+看一遍 MAINTAINERS 文件和源代码，看看你所的改动所在的内核子系统有没有指
+定的维护者。如果有，给他们发e-mail。
+
+如果没有找到维护者，或者维护者没有反馈，将你的补丁发送到内核开发者主邮
+件列表 linux-kernel@vger.kernel.org。大部分的内核开发者都跟踪这个邮件列
+表，可以评价你的改动。
+
+每次不要发送超过15个补丁到 vger 邮件列表！！！
+
+Linus Torvalds 是决定改动能否进入 Linux 内核的最终裁决者。他的 e-mail
+地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多，所以一般
+的说，最好别给他发 e-mail。
+
+那些修正bug，“显而易见”的修改或者是类似的只需要很少讨论的补丁可以直接
+发送或者CC给Linus。那些需要讨论或者没有很清楚的好处的补丁，一般先发送到
+linux-kernel邮件列表。只有当补丁被讨论得差不多了，才提交给Linus。
+
+5)选择CC( e-mail 抄送)列表
+
+除非你有理由不这样做，否则CC linux-kernel@vger.kernel.org。
+
+除了 Linus 之外，其他内核开发者也需要注意到你的改动，这样他们才能评论你
+的改动并提供代码审查和建议。linux-kernel 是 Linux 内核开发者主邮件列表
+。其它的邮件列表为特定的子系统提供服务，比如 USB，framebuffer 设备，虚
+拟文件系统，SCSI 子系统，等等。查看 MAINTAINERS 文件来获得和你的改动有
+关的邮件列表。
+
+Majordomo lists of VGER.KERNEL.ORG at:
+        <http://vger.kernel.org/vger-lists.html>
+
+如果改动影响了用户空间和内核之间的接口，请给 MAN-PAGES 的维护者（列在
+MAINTAINERS 文件里的）发送一个手册页（man-pages）补丁，或者至少通知一下改
+变，让一些信息有途径进入手册页。
+
+即使在第四步的时候，维护者没有作出回应，也要确认在修改他们的代码的时候
+，一直将维护者拷贝到CC列表中。
+
+对于小的补丁，你也许会CC到 Adrian Bunk 管理的搜集琐碎补丁的邮件列表
+(Trivial Patch Monkey)trivial@kernel.org，那里专门收集琐碎的补丁。下面这样
+的补丁会被看作“琐碎的”补丁：
+  文档的拼写修正。
+  修正会影响到 grep(1) 的拼写。
+  警告信息修正(频繁的打印无用的警告是不好的。)
+  编译错误修正（代码逻辑的确是对的，只是编译有问题。）
+  运行时修正（只要真的修正了错误。）
+  移除使用了被废弃的函数/宏的代码(例如 check_region。)
+  联系方式和文档修正。
+  用可移植的代码替换不可移植的代码（即使在体系结构相关的代码中，既然有
+  人拷贝，只要它是琐碎的）
+  任何文件的作者/维护者对该文件的改动（例如 patch monkey 在重传模式下）
+
+EMAIL: trivial@kernel.org
+
+(译注，关于“琐碎补丁”的一些说明：因为原文的这一部分写得比较简单，所以不得不
+违例写一下译注。"trivial"这个英文单词的本意是“琐碎的，不重要的。”但是在这里
+有稍微有一些变化，例如对一些明显的NULL指针的修正，属于运行时修正，会被归类
+到琐碎补丁里。虽然NULL指针的修正很重要，但是这样的修正往往很小而且很容易得到
+检验，所以也被归入琐碎补丁。琐碎补丁更精确的归类应该是
+“simple, localized & easy to verify”，也就是说简单的，局部的和易于检验的。
+trivial@kernel.org邮件列表的目的是针对这样的补丁，为提交者提供一个中心，来
+降低提交的门槛。)
+
+6)没有 MIME 编码，没有链接，没有压缩，没有附件，只有纯文本。
+
+Linus 和其他的内核开发者需要阅读和评论你提交的改动。对于内核开发者来说
+，可以“引用”你的改动很重要，使用一般的 e-mail 工具，他们就可以在你的
+代码的任何位置添加评论。
+
+因为这个原因，所有的提交的补丁都是 e-mail 中“内嵌”的。
+警告：如果你使用剪切-粘贴你的补丁，小心你的编辑器的自动换行功能破坏你的
+补丁。
+
+不要将补丁作为 MIME 编码的附件，不管是否压缩。很多流行的 e-mail 软件不
+是任何时候都将 MIME 编码的附件当作纯文本发送的，这会使得别人无法在你的
+代码中加评论。另外，MIME 编码的附件会让 Linus 多花一点时间来处理，这就
+降低了你的改动被接受的可能性。
+
+警告：一些邮件软件，比如 Mozilla 会将你的信息以如下格式发送：
+---- 邮件头 ----
+Content-Type: text/plain; charset=us-ascii; format=flowed
+---- 邮件头 ----
+问题在于 “format=flowed” 会让接收端的某些邮件软件将邮件中的制表符替换
+成空格以及做一些类似的替换。这样，你发送的时候看起来没问题的补丁就被破
+坏了。
+
+要修正这个问题，只需要将你的 mozilla 的 defaults/pref/mailnews.js 文件
+里的
+pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
+修改成
+pref("mailnews.display.disable_format_flowed_support", true);
+就可以了。
+
+7) e-mail 的大小
+
+给 Linus 发送补丁的时候，永远按照第6小节说的做。
+
+大的改动对邮件列表不合适，对某些维护者也不合适。如果你的补丁，在不压缩
+的情况下，超过了40kB，那么你最好将补丁放在一个能通过 internet 访问的服
+务器上，然后用指向你的补丁的 URL 替代。
+
+8) 指出你的内核版本
+
+在标题和在补丁的描述中，指出补丁对应的内核的版本，是很重要的。
+
+如果补丁不能干净的在最新版本的内核上打上，Linus 是不会接受它的。
+
+9) 不要气馁，继续提交。
+
+当你提交了改动以后，耐心地等待。如果 Linus 喜欢你的改动并且同意它，那么
+它将在下一个内核发布版本中出现。
+
+然而，如果你的改动没有出现在下一个版本的内核中，可能有若干原因。减少那
+些原因，修正错误，重新提交更新后的改动，是你自己的工作。
+
+Linus不给出任何评论就“丢弃”你的补丁是常见的事情。在系统中这样的事情很
+平常。如果他没有接受你的补丁，也许是由于以下原因：
+* 你的补丁不能在最新版本的内核上干净的打上。
+* 你的补丁在 linux-kernel 邮件列表中没有得到充分的讨论。
+* 风格问题（参照第2小节）
+* 邮件格式问题（重读本节）
+* 你的改动有技术问题。
+* 他收到了成吨的 e-mail，而你的在混乱中丢失了。
+* 你让人为难。
+
+有疑问的时候，在 linux-kernel 邮件列表上请求评论。
+
+10) 在标题上加上 PATCH 的字样
+
+Linus 和 linux-kernel 邮件列表的 e-mail 流量都很高，一个通常的约定是标
+题行以 [PATCH] 开头。这样可以让 Linus 和其他内核开发人员可以从 e-mail
+的讨论中很轻易的将补丁分辨出来。
+
+11）为你的工作签名
+
+为了加强对谁做了何事的追踪，尤其是对那些透过好几层的维护者的补丁，我们
+建议在发送出去的补丁上加一个 “sign-off” 的过程。
+
+"sign-off" 是在补丁的注释的最后的简单的一行文字，认证你编写了它或者其他
+人有权力将它作为开放源代码的补丁传递。规则很简单：如果你能认证如下信息
+：
+      开发者来源证书 1.1
+      对于本项目的贡献，我认证如下信息：
+      （a）这些贡献是完全或者部分的由我创建，我有权利以文件中指出
+       的开放源代码许可证提交它；或者
+      （b）这些贡献基于以前的工作，据我所知，这些以前的工作受恰当的开放
+       源代码许可证保护，而且，根据许可证，我有权提交修改后的贡献，
+       无论是完全还是部分由我创造，这些贡献都使用同一个开放源代码许可证
+       （除非我被允许用其它的许可证），正如文件中指出的；或者
+      （c）这些贡献由认证（a），（b）或者（c）的人直接提供给我，而
+       且我没有修改它。
+      （d）我理解并同意这个项目和贡献是公开的，贡献的记录（包括我
+       一起提交的个人记录，包括 sign-off ）被永久维护并且可以和这个项目
+       或者开放源代码的许可证同步地再发行。
+       那么加入这样一行：
+       Signed-off-by: Random J Developer <random@developer.example.org>
+
+使用你的真名（抱歉，不能使用假名或者匿名。）
+
+有人在最后加上标签。现在这些东西会被忽略，但是你可以这样做，来标记公司
+内部的过程，或者只是指出关于 sign-off 的一些特殊细节。
+
+12）标准补丁格式
+
+标准的补丁，标题行是：
+    Subject: [PATCH 001/123] 子系统:一句话概述
+
+标准补丁的信体存在如下部分：
+
+  - 一个 "from" 行指出补丁作者。
+
+  - 一个空行
+
+  - 说明的主体，这些说明文字会被拷贝到描述该补丁的永久改动记录里。
+
+  - 一个由"---"构成的标记行
+
+  - 不合适放到改动记录里的额外的注解。
+
+  - 补丁本身（diff 输出）
+
+标题行的格式，使得对标题行按字母序排序非常的容易 - 很多 e-mail 客户端都
+可以支持 - 因为序列号是用零填充的，所以按数字排序和按字母排序是一样的。
+
+e-mail 标题中的“子系统”标识哪个内核子系统将被打补丁。
+
+e-mail 标题中的“一句话概述”扼要的描述 e-mail 中的补丁。“一句话概述”
+不应该是一个文件名。对于一个补丁系列（“补丁系列”指一系列的多个相关补
+丁），不要对每个补丁都使用同样的“一句话概述”。
+
+记住 e-mail 的“一句话概述”会成为该补丁的全局唯一标识。它会蔓延到 git
+的改动记录里。然后“一句话概述”会被用在开发者的讨论里，用来指代这个补
+丁。用户将希望通过 google 来搜索"一句话概述"来找到那些讨论这个补丁的文
+章。
+
+一些标题的例子：
+
+    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
+    Subject: [PATCHv2 001/207] x86: fix eflags tracking
+
+"from" 行是信体里的最上面一行，具有如下格式：
+        From: Original Author <author@example.com>
+
+"from" 行指明在永久改动日志里，谁会被确认为作者。如果没有 "from" 行，那
+么邮件头里的 "From: " 行会被用来决定改动日志中的作者。
+
+说明的主题将会被提交到永久的源代码改动日志里，因此对那些早已经不记得和
+这个补丁相关的讨论细节的有能力的读者来说，是有意义的。
+
+"---" 标记行对于补丁处理工具要找到哪里是改动日志信息的结束，是不可缺少
+的。
+
+对于 "---" 标记之后的额外注解，一个好的用途就是用来写 diffstat，用来显
+示修改了什么文件和每个文件都增加和删除了多少行。diffstat 对于比较大的补
+丁特别有用。其余那些只是和时刻或者开发者相关的注解，不合适放到永久的改
+动日志里的，也应该放这里。
+使用 diffstat的选项 "-p 1 -w 70" 这样文件名就会从内核源代码树的目录开始
+，不会占用太宽的空间（很容易适合80列的宽度，也许会有一些缩进。）
+
+在后面的参考资料中能看到适当的补丁格式的更多细节。
+
+-------------------------------
+第二节 提示，建议和诀窍
+-------------------------------
+
+本节包含很多和提交到内核的代码有关的通常的"规则"。事情永远有例外...但是
+你必须真的有好的理由这样做。你可以把本节叫做Linus的计算机科学入门课。
+
+1) 读 Document/process/coding-style.rst
+
+Nuff 说过，如果你的代码和这个偏离太多，那么它有可能会被拒绝，没有更多的
+审查，没有更多的评价。
+
+2) #ifdef 是丑陋的
+混杂了 ifdef 的代码难以阅读和维护。别这样做。作为替代，将你的 ifdef 放
+在头文件里，有条件地定义 "static inline" 函数，或者宏，在代码里用这些东
+西。让编译器把那些"空操作"优化掉。
+
+一个简单的例子，不好的代码：
+
+    dev = alloc_etherdev (sizeof(struct funky_private));
+    if (!dev)
+        return -ENODEV;
+    #ifdef CONFIG_NET_FUNKINESS
+    init_funky_net(dev);
+    #endif
+
+清理后的例子:
+
+(头文件里)
+    #ifndef CONFIG_NET_FUNKINESS
+    static inline void init_funky_net (struct net_device *d) {}
+    #endif
+
+(代码文件里)
+    dev = alloc_etherdev (sizeof(struct funky_private));
+    if (!dev)
+        return -ENODEV;
+    init_funky_net(dev);
+
+3) 'static inline' 比宏好
+
+Static inline 函数相比宏来说，是好得多的选择。Static inline 函数提供了
+类型安全，没有长度限制，没有格式限制，在 gcc 下开销和宏一样小。
+
+宏只在 static inline 函数不是最优的时候[在 fast paths 里有很少的独立的
+案例]，或者不可能用 static inline 函数的时候[例如字符串分配]。
+应该用 'static inline' 而不是 'static __inline__', 'extern inline' 和
+'extern __inline__' 。
+
+4) 不要过度设计
+
+不要试图预计模糊的未来事情，这些事情也许有用也许没有用："让事情尽可能的
+简单，而不是更简单"。
+
+----------------
+第三节 参考文献
+----------------
+
+Andrew Morton, "The perfect patch" (tpp).
+  <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+Jeff Garzik, "Linux kernel patch submission format".
+  <http://linux.yyz.us/patch-format.html>
+
+Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
+  <http://www.kroah.com/log/2005/03/31/>
+  <http://www.kroah.com/log/2005/07/08/>
+  <http://www.kroah.com/log/2005/10/19/>
+  <http://www.kroah.com/log/2006/01/11/>
+
+NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
+  <https://lkml.org/lkml/2005/7/11/336>
+
+Kernel Documentation/process/coding-style.rst:
+  <http://sosdg.org/~coywolf/lxr/source/Documentation/process/coding-style.rst>
+
+Linus Torvalds's mail on the canonical patch format:
+  <http://lkml.org/lkml/2005/4/7/183>
+--
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/video4linux/omap3isp.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/video4linux/omap3isp.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/video4linux/omap3isp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/video4linux/omap3isp.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,277 @@
+Chinese translated version of Documentation/video4linux/omap3isp.txt
+
+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.
+
+Maintainer: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+	  Sakari Ailus <sakari.ailus@iki.fi>
+	  David Cohen <dacohen@gmail.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/video4linux/omap3isp.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+	  Sakari Ailus <sakari.ailus@iki.fi>
+	  David Cohen <dacohen@gmail.com>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+OMAP 3 图像信号处理器 (ISP) 驱动
+
+Copyright (C) 2010 Nokia Corporation
+Copyright (C) 2009 Texas Instruments, Inc.
+
+联系人: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+	  Sakari Ailus <sakari.ailus@iki.fi>
+	  David Cohen <dacohen@gmail.com>
+
+
+介绍
+===
+
+本文档介绍了由 drivers/media/video/omap3isp 加载的德州仪器
+（TI）OMAP 3 图像信号处理器 (ISP) 驱动。原始驱动由德州仪器（TI）
+编写，但此后由诺基亚重写了两次。
+
+驱动已在以下 OMAP 3 系列的芯片中成功使用：
+
+	3430
+	3530
+	3630
+
+驱动实现了 V4L2、媒体控制器和 v4l2_subdev 接口。支持内核中使用
+v4l2_subdev 接口的传感器、镜头和闪光灯驱动。
+
+
+拆分为子设备
+==========
+
+OMAP 3 ISP 被拆分为 V4L2 子设备，ISP中的每个模块都由一个子设备
+来表示。每个子设备向用户空间提供一个 V4L2 子设备接口。
+
+	OMAP3 ISP CCP2
+	OMAP3 ISP CSI2a
+	OMAP3 ISP CCDC
+	OMAP3 ISP preview
+	OMAP3 ISP resizer
+	OMAP3 ISP AEWB
+	OMAP3 ISP AF
+	OMAP3 ISP histogram
+
+ISP 中每个可能的连接都通过一个链接嵌入到媒体控制器接口中。详见例程 [2]。
+
+
+控制 OMAP 3 ISP
+==============
+
+通常，对 OMAP 3 ISP 的配置会在下一帧起始时生效。在传感器垂直消隐期间，
+模块变为空闲时完成配置。在内存到内存的操作中，视频管道一次处理一帧。
+应用配置应在帧间完成。
+
+ISP 中的所有模块，除 CSI-2 和 （可能存在的）CCP2 接收器外，都必须
+接收完整的帧数据。因此，传感器必须保证从不发送部分帧数据给ISP。
+
+Autoidle（自动空闲）功能至少在 3430 的 ISP 模块中确实存在一些问题。
+当 omap3isp 模块参数 autoidle 非零时，autoidle（自动空闲）功能
+仅在 3630 中启用了。
+
+
+事件机制
+======
+
+OMAP 3 ISP 驱动在 CCDC 和统计（AEWB、AF 和 直方图）子设备中支持
+V4L2 事件机制接口。
+
+CCDC 子设备通过 HS_VS 中断，处理 V4L2_EVENT_FRAME_SYNC 类型
+事件，用于告知帧起始。早期版本的驱动则使用 V4L2_EVENT_OMAP3ISP_HS_VS。
+当在 CCDC 模块中接收到起始帧的第一行时，会准确地触发事件。这个事件
+可以在 CCDC 子设备中“订阅”。
+
+（当使用并行接口时，必须注意正确地配置 VS 信号极性。而当使用串行接收时
+这个会自动校正。）
+
+每个统计子设备都可以产生事件。每当一个统计缓冲区可由用户空间应用程序
+通过 VIDIOC_OMAP3ISP_STAT_REQ IOCTL 操作获取时，就会产生一个
+事件。当前存在以下事件：
+
+	V4L2_EVENT_OMAP3ISP_AEWB
+	V4L2_EVENT_OMAP3ISP_AF
+	V4L2_EVENT_OMAP3ISP_HIST
+
+这些 ioctl 的事件数据类型为 struct omap3isp_stat_event_status
+结构体。如果出现计算错误的统计，也同样会产生一个事件，但没有相关的统计
+数据缓冲区。这种情况下 omap3isp_stat_event_status.buf_err 会被
+设置为非零值。
+
+
+私有 IOCTL
+==========
+
+OMAP 3 ISP 驱动支持标准的 V4L2 IOCTL 以及可能存在且实用的控制。但
+ISP 提供的许多功能都不在标准 IOCTL 之列，例如 gamma（伽马）表和统计
+数据采集配置等。
+
+通常，会有一个私有 ioctl 用于配置每个包含硬件依赖功能的模块。
+
+支持以下私有 IOCTL：
+
+	VIDIOC_OMAP3ISP_CCDC_CFG
+	VIDIOC_OMAP3ISP_PRV_CFG
+	VIDIOC_OMAP3ISP_AEWB_CFG
+	VIDIOC_OMAP3ISP_HIST_CFG
+	VIDIOC_OMAP3ISP_AF_CFG
+	VIDIOC_OMAP3ISP_STAT_REQ
+	VIDIOC_OMAP3ISP_STAT_EN
+
+在 include/linux/omap3isp.h 中描述了这些 ioctl 使用的参数结构体。
+与特定 ISP 模块相关的 ISP 自身的详细功能在技术参考手册 (TRMs)中有
+描述，详见文档结尾。
+
+虽然在不使用任何私有 IOCTL 的情况下使用 ISP 驱动是可能的，但这样无法
+获得最佳的图像质量。AEWB、AF 和 直方图（译者注：一般用于自动曝光和增益
+控制，以及图像均衡等）模块无法在未使用适当的私有 IOCTL 配置的情况下使用。
+
+
+CCDC 和 preview（预览）模块 IOCTL
+===============================
+
+VIDIOC_OMAP3ISP_CCDC_CFG 和 VIDIOC_OMAP3ISP_PRV_CFG IOCTL
+被分别用于配置、启用和禁用 CCDC 和 preview（预览）模块的功能。在它们
+所控制的模块中，两个 IOCTL 控制多种功能。VIDIOC_OMAP3ISP_CCDC_CFG IOCTL
+接受一个指向 omap3isp_ccdc_update_config 结构体的指针作为它的参数。
+同样的，VIDIOC_OMAP3ISP_PRV_CFG 接受一个指向 omap3isp_prev_update_config
+结构体的指针。以上两个结构体定义位于 [1]。
+
+这些结构体中的 update 域标识是否针对指定的功能更新配置，而 flag 域
+则标识是启用还是禁用此功能。
+
+update 和 flag 位接受以下掩码值。CCDC 和 preview（预览）模块的
+每个单独功能都与一个 flag 关联（禁用或启用；在结构体中 flag 域的
+一部分）和一个指向功能配置数据的指针。
+
+对于 VIDIOC_OMAP3ISP_CCDC_CFG，下面列出了 update 和 flag 域
+中的有效值。 这些值可能会在同一个 IOCTL 调用中配置多个功能。
+
+        OMAP3ISP_CCDC_ALAW
+        OMAP3ISP_CCDC_LPF
+        OMAP3ISP_CCDC_BLCLAMP
+        OMAP3ISP_CCDC_BCOMP
+        OMAP3ISP_CCDC_FPC
+        OMAP3ISP_CCDC_CULL
+        OMAP3ISP_CCDC_CONFIG_LSC
+        OMAP3ISP_CCDC_TBL_LSC
+
+针对 VIDIOC_OMAP3ISP_PRV_CFG 的相应值如下：
+
+        OMAP3ISP_PREV_LUMAENH
+        OMAP3ISP_PREV_INVALAW
+        OMAP3ISP_PREV_HRZ_MED
+        OMAP3ISP_PREV_CFA
+        OMAP3ISP_PREV_CHROMA_SUPP
+        OMAP3ISP_PREV_WB
+        OMAP3ISP_PREV_BLKADJ
+        OMAP3ISP_PREV_RGB2RGB
+        OMAP3ISP_PREV_COLOR_CONV
+        OMAP3ISP_PREV_YC_LIMIT
+        OMAP3ISP_PREV_DEFECT_COR
+        OMAP3ISP_PREV_GAMMABYPASS
+        OMAP3ISP_PREV_DRK_FRM_CAPTURE
+        OMAP3ISP_PREV_DRK_FRM_SUBTRACT
+        OMAP3ISP_PREV_LENS_SHADING
+        OMAP3ISP_PREV_NF
+        OMAP3ISP_PREV_GAMMA
+
+在启用某个功能的时候，相关的配置数据指针不可为 NULL。在禁用某个功能时，
+配置数据指针会被忽略。
+
+
+统计模块 IOCTL
+=============
+
+统计子设备相较于其他子设备提供了更多动态配置选项。在图像处理流水线处于
+工作状态时，它们可以被启用、禁用和重配。
+
+统计模块总是从 CCDC 中获取输入的图像数据（由于直方图内存读取未实现）。
+统计数据可由用户通过统计子设备节点使用私有 IOCTL 获取。
+
+AEWB、AF 和 直方图子设备提供的私有 IOCTL 极大程度上反应了 ISP 硬件
+提供的寄存器级接口。有些方面纯粹和驱动程序的实现相关，这些将在下面讨论。
+
+VIDIOC_OMAP3ISP_STAT_EN
+-----------------------
+
+这个私有 IOCTL 启用/禁用 一个统计模块。如果这个申请在视频流启动前完成，
+它将在视频流水线开始工作时生效。如果视频流水线已经处于工作状态了，它将在
+CCDC 变为空闲时生效。
+
+VIDIOC_OMAP3ISP_AEWB_CFG, VIDIOC_OMAP3ISP_HIST_CFG and VIDIOC_OMAP3ISP_AF_CFG
+-----------------------------------------------------------------------------
+
+这些 IOCTL 用于配置模块。它们要求用户应用程序对硬件有深入的认识。对
+大多数域的解释可以在 OMAP 的 TRM 中找到。以下两个域对于以上所有的
+私有 IOCTL 配置都很常见，由于他们没有在 TRM 中提及，故需要对其有
+更好的认识。
+
+omap3isp_[h3a_af/h3a_aewb/hist]_config.buf_size:
+
+模块在内部处理自身缓冲。对模块数据输出所必需的缓存大小依赖于已申请的配置。
+虽然驱动支持在视频流工作时重新配置，但对于所需缓存量大于模块启用时内部
+所分配数量的情况，则不支持重新配置。在这种情况下将返回 -EBUSY。为了避免
+此类状况，无论是禁用/重配/启用模块，还是第一次配置时申请必须的缓存大小，
+都应在模块禁用的情况下进行。
+
+内部缓冲分配的大小需综合考虑所申请配置的最小缓存量以及 buf_size 域中
+所设的值。如果 buf_size 域在[minimum（最小值）, maximum（最大值）]
+缓冲大小范围之外，则应该将其调整到其范围中。驱动则会选择最大值。正确的
+buf_size 值将回写到用户应用程序中。
+
+omap3isp_[h3a_af/h3a_aewb/hist]_config.config_counter:
+
+由于配置并未在申请之后同步生效，驱动必须提供一个跟踪这类信息的方法，
+以提供更准确的数据。在一个配置被申请之后，返回到用户空间应用程序的
+config_counter 是一个与其配置相关的唯一值。当用户应用程序接收到
+一个缓冲可用或一个新的缓冲申请事件时，这个 config_counter 用于
+一个缓冲数据和一个配置的匹配。
+
+VIDIOC_OMAP3ISP_STAT_REQ
+------------------------
+
+将内部缓冲队列中最早的数据发送到用户空间，然后丢弃此缓冲区。
+omap3isp_stat_data.frame_number 域与视频缓冲的 field_count
+域相匹配。
+
+
+技术参考手册 (TRMs) 和其他文档
+==========================
+
+OMAP 3430 TRM:
+<URL:http://focus.ti.com/pdfs/wtbu/OMAP34xx_ES3.1.x_PUBLIC_TRM_vZM.zip>
+参考于 2011-03-05.
+
+OMAP 35xx TRM:
+<URL:http://www.ti.com/litv/pdf/spruf98o> 参考于 2011-03-05.
+
+OMAP 3630 TRM:
+<URL:http://focus.ti.com/pdfs/wtbu/OMAP36xx_ES1.x_PUBLIC_TRM_vQ.zip>
+参考于 2011-03-05.
+
+DM 3730 TRM:
+<URL:http://www.ti.com/litv/pdf/sprugn4h> 参考于 2011-03-06.
+
+
+参考资料
+=======
+
+[1] include/linux/omap3isp.h
+
+[2] http://git.ideasonboard.org/?p=media-ctl.git;a=summary
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,976 @@
+Chinese translated version of Documentation/video4linux/v4l2-framework.txt
+
+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.
+
+Maintainer: Mauro Carvalho Chehab <mchehab@infradead.org>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/video4linux/v4l2-framework.txt 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+英文版维护者： Mauro Carvalho Chehab <mchehab@infradead.org>
+中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+V4L2 驱动框架概览
+==============
+
+本文档描述 V4L2 框架所提供的各种结构和它们之间的关系。
+
+
+介绍
+----
+
+大部分现代 V4L2 设备由多个 IC 组成，在 /dev 下导出多个设备节点，
+并同时创建非 V4L2 设备（如 DVB、ALSA、FB、I2C 和红外输入设备）。
+由于这种硬件的复杂性，V4L2 驱动也变得非常复杂。
+
+尤其是 V4L2 必须支持 IC 实现音视频的多路复用和编解码，这就更增加了其
+复杂性。通常这些 IC 通过一个或多个 I2C 总线连接到主桥驱动器，但也可
+使用其他总线。这些设备称为“子设备”。
+
+长期以来，这个框架仅限于通过 video_device 结构体创建 V4L 设备节点，
+并使用 video_buf 处理视频缓冲（注：本文不讨论 video_buf 框架）。
+
+这意味着所有驱动必须自己设置设备实例并连接到子设备。其中一部分要正确地
+完成是比较复杂的，使得许多驱动都没有正确地实现。
+
+由于框架的缺失，有很多通用代码都不可重复利用。
+
+因此，这个框架构建所有驱动都需要的基本结构块，而统一的框架将使通用代码
+创建成实用函数并在所有驱动中共享变得更加容易。
+
+
+驱动结构
+-------
+
+所有 V4L2 驱动都有如下结构：
+
+1) 每个设备实例的结构体--包含其设备状态。
+
+2) 初始化和控制子设备的方法（如果有）。
+
+3) 创建 V4L2 设备节点 (/dev/videoX、/dev/vbiX 和 /dev/radioX)
+   并跟踪设备节点的特定数据。
+
+4) 特定文件句柄结构体--包含每个文件句柄的数据。
+
+5) 视频缓冲处理。
+
+以下是它们的初略关系图：
+
+    device instances（设备实例）
+      |
+      +-sub-device instances（子设备实例）
+      |
+      \-V4L2 device nodes（V4L2 设备节点）
+	  |
+	  \-filehandle instances（文件句柄实例）
+
+
+框架结构
+-------
+
+该框架非常类似驱动结构：它有一个 v4l2_device 结构用于保存设备
+实例的数据；一个 v4l2_subdev 结构体代表子设备实例；video_device
+结构体保存 V4L2 设备节点的数据；将来 v4l2_fh 结构体将跟踪文件句柄
+实例（暂未尚未实现）。
+
+V4L2 框架也可与媒体框架整合（可选的）。如果驱动设置了 v4l2_device
+结构体的 mdev 域，子设备和视频节点的入口将自动出现在媒体框架中。
+
+
+v4l2_device 结构体
+----------------
+
+每个设备实例都通过 v4l2_device (v4l2-device.h)结构体来表示。
+简单设备可以仅分配这个结构体，但在大多数情况下，都会将这个结构体
+嵌入到一个更大的结构体中。
+
+你必须注册这个设备实例：
+
+	v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
+
+注册操作将会初始化 v4l2_device 结构体。如果 dev->driver_data 域
+为 NULL，就将其指向 v4l2_dev。
+
+需要与媒体框架整合的驱动必须手动设置 dev->driver_data，指向包含
+v4l2_device 结构体实例的驱动特定设备结构体。这可以在注册 V4L2 设备
+实例前通过 dev_set_drvdata() 函数完成。同时必须设置 v4l2_device
+结构体的 mdev 域，指向适当的初始化并注册过的 media_device 实例。
+
+如果 v4l2_dev->name 为空，则它将被设置为从 dev 中衍生出的值（为了
+更加精确，形式为驱动名后跟 bus_id）。如果你在调用 v4l2_device_register
+前已经设置好了，则不会被修改。如果 dev 为 NULL，则你*必须*在调用
+v4l2_device_register 前设置 v4l2_dev->name。
+
+你可以基于驱动名和驱动的全局 atomic_t 类型的实例编号，通过
+v4l2_device_set_name() 设置 name。这样会生成类似 ivtv0、ivtv1 等
+名字。若驱动名以数字结尾，则会在编号和驱动名间插入一个破折号，如：
+cx18-0、cx18-1 等。此函数返回实例编号。
+
+第一个 “dev” 参数通常是一个指向 pci_dev、usb_interface 或
+platform_device 的指针。很少使其为 NULL，除非是一个ISA设备或者
+当一个设备创建了多个 PCI 设备，使得 v4l2_dev 无法与一个特定的父设备
+关联。
+
+你也可以提供一个 notify() 回调，使子设备可以调用它实现事件通知。
+但这个设置与子设备相关。子设备支持的任何通知必须在
+include/media/<subdevice>.h 中定义一个消息头。
+
+注销 v4l2_device 使用如下函数：
+
+	v4l2_device_unregister(struct v4l2_device *v4l2_dev);
+
+如果 dev->driver_data 域指向 v4l2_dev，将会被重置为 NULL。注销同时
+会自动从设备中注销所有子设备。
+
+如果你有一个热插拔设备（如USB设备），则当断开发生时，父设备将无效。
+由于 v4l2_device 有一个指向父设备的指针必须被清除，同时标志父设备
+已消失，所以必须调用以下函数：
+
+	v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
+
+这个函数并*不*注销子设备，因此你依然要调用 v4l2_device_unregister()
+函数。如果你的驱动器并非热插拔的，就没有必要调用 v4l2_device_disconnect()。
+
+有时你需要遍历所有被特定驱动注册的设备。这通常发生在多个设备驱动使用
+同一个硬件的情况下。如：ivtvfb 驱动是一个使用 ivtv 硬件的帧缓冲驱动，
+同时 alsa 驱动也使用此硬件。
+
+你可以使用如下例程遍历所有注册的设备：
+
+static int callback(struct device *dev, void *p)
+{
+	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+
+	/* 测试这个设备是否已经初始化 */
+	if (v4l2_dev == NULL)
+		return 0;
+	...
+	return 0;
+}
+
+int iterate(void *p)
+{
+	struct device_driver *drv;
+	int err;
+
+	/* 在PCI 总线上查找ivtv驱动。
+	   pci_bus_type是全局的. 对于USB总线使用usb_bus_type。 */
+	drv = driver_find("ivtv", &pci_bus_type);
+	/* 遍历所有的ivtv设备实例 */
+	err = driver_for_each_device(drv, NULL, p, callback);
+	put_driver(drv);
+	return err;
+}
+
+有时你需要一个设备实例的运行计数。这个通常用于映射一个设备实例到一个
+模块选择数组的索引。
+
+推荐方法如下：
+
+static atomic_t drv_instance = ATOMIC_INIT(0);
+
+static int drv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	...
+	state->instance = atomic_inc_return(&drv_instance) - 1;
+}
+
+如果你有多个设备节点，对于热插拔设备，知道何时注销 v4l2_device 结构体
+就比较困难。为此 v4l2_device 有引用计数支持。当调用 video_register_device
+时增加引用计数，而设备节点释放时减小引用计数。当引用计数为零，则
+v4l2_device 的release() 回调将被执行。你就可以在此时做最后的清理工作。
+
+如果创建了其他设备节点（比如 ALSA），则你可以通过以下函数手动增减
+引用计数：
+
+void v4l2_device_get(struct v4l2_device *v4l2_dev);
+
+或:
+
+int v4l2_device_put(struct v4l2_device *v4l2_dev);
+
+由于引用技术初始化为 1 ，你也需要在 disconnect() 回调（对于 USB 设备）中
+调用 v4l2_device_put，或者 remove() 回调（例如对于 PCI 设备），否则
+引用计数将永远不会为 0 。
+
+v4l2_subdev结构体
+------------------
+
+许多驱动需要与子设备通信。这些设备可以完成各种任务，但通常他们负责
+音视频复用和编解码。如网络摄像头的子设备通常是传感器和摄像头控制器。
+
+这些一般为 I2C 接口设备，但并不一定都是。为了给驱动提供调用子设备的
+统一接口，v4l2_subdev 结构体（v4l2-subdev.h）产生了。
+
+每个子设备驱动都必须有一个 v4l2_subdev 结构体。这个结构体可以单独
+代表一个简单的子设备，也可以嵌入到一个更大的结构体中，与更多设备状态
+信息保存在一起。通常有一个下级设备结构体（比如：i2c_client）包含了
+内核创建的设备数据。建议使用 v4l2_set_subdevdata() 将这个结构体的
+指针保存在 v4l2_subdev 的私有数据域(dev_priv)中。这使得通过 v4l2_subdev
+找到实际的低层总线特定设备数据变得容易。
+
+你同时需要一个从低层结构体获取 v4l2_subdev 指针的方法。对于常用的
+i2c_client 结构体，i2c_set_clientdata() 函数可用于保存一个 v4l2_subdev
+指针；对于其他总线你可能需要使用其他相关函数。
+
+桥驱动中也应保存每个子设备的私有数据，比如一个指向特定桥的各设备私有
+数据的指针。为此 v4l2_subdev 结构体提供主机私有数据域(host_priv)，
+并可通过 v4l2_get_subdev_hostdata() 和 v4l2_set_subdev_hostdata()
+访问。
+
+从总线桥驱动的视角，驱动加载子设备模块并以某种方式获得 v4l2_subdev
+结构体指针。对于 i2c 总线设备相对简单：调用 i2c_get_clientdata()。
+对于其他总线也需要做类似的操作。针对 I2C 总线上的子设备辅助函数帮你
+完成了大部分复杂的工作。
+
+每个 v4l2_subdev 都包含子设备驱动需要实现的函数指针（如果对此设备
+不适用，可为NULL）。由于子设备可完成许多不同的工作，而在一个庞大的
+函数指针结构体中通常仅有少数有用的函数实现其功能肯定不合适。所以，
+函数指针根据其实现的功能被分类，每一类都有自己的函数指针结构体。
+
+顶层函数指针结构体包含了指向各类函数指针结构体的指针，如果子设备驱动
+不支持该类函数中的任何一个功能，则指向该类结构体的指针为NULL。
+
+这些结构体定义如下：
+
+struct v4l2_subdev_core_ops {
+	int (*log_status)(struct v4l2_subdev *sd);
+	int (*init)(struct v4l2_subdev *sd, u32 val);
+	...
+};
+
+struct v4l2_subdev_tuner_ops {
+	...
+};
+
+struct v4l2_subdev_audio_ops {
+	...
+};
+
+struct v4l2_subdev_video_ops {
+	...
+};
+
+struct v4l2_subdev_pad_ops {
+	...
+};
+
+struct v4l2_subdev_ops {
+	const struct v4l2_subdev_core_ops  *core;
+	const struct v4l2_subdev_tuner_ops *tuner;
+	const struct v4l2_subdev_audio_ops *audio;
+	const struct v4l2_subdev_video_ops *video;
+	const struct v4l2_subdev_pad_ops *video;
+};
+
+其中 core（核心）函数集通常可用于所有子设备，其他类别的实现依赖于
+子设备。如视频设备可能不支持音频操作函数，反之亦然。
+
+这样的设置在限制了函数指针数量的同时，还使增加新的操作函数和分类
+变得较为容易。
+
+子设备驱动可使用如下函数初始化 v4l2_subdev 结构体：
+
+	v4l2_subdev_init(sd, &ops);
+
+然后，你必须用一个唯一的名字初始化 subdev->name，并初始化模块的
+owner 域。若使用 i2c 辅助函数，这些都会帮你处理好。
+
+若需同媒体框架整合，你必须调用 media_entity_pads_init() 初始化 v4l2_subdev
+结构体中的 media_entity 结构体（entity 域）：
+
+	struct media_pad *pads = &my_sd->pads;
+	int err;
+
+	err = media_entity_pads_init(&sd->entity, npads, pads);
+
+pads 数组必须预先初始化。无须手动设置 media_entity 的 type 和
+name 域，但如有必要，revision 域必须初始化。
+
+当（任何）子设备节点被打开/关闭，对 entity 的引用将被自动获取/释放。
+
+在子设备被注销之后，不要忘记清理 media_entity 结构体：
+
+	media_entity_cleanup(&sd->entity);
+
+如果子设备驱动趋向于处理视频并整合进了媒体框架，必须使用 v4l2_subdev_pad_ops
+替代 v4l2_subdev_video_ops 实现格式相关的功能。
+
+这种情况下，子设备驱动应该设置 link_validate 域，以提供它自身的链接
+验证函数。链接验证函数应对管道（两端链接的都是 V4L2 子设备）中的每个
+链接调用。驱动还要负责验证子设备和视频节点间格式配置的正确性。
+
+如果 link_validate 操作没有设置，默认的 v4l2_subdev_link_validate_default()
+函数将会被调用。这个函数保证宽、高和媒体总线像素格式在链接的收发两端
+都一致。子设备驱动除了它们自己的检测外，也可以自由使用这个函数以执行
+上面提到的检查。
+
+设备（桥）驱动程序必须向 v4l2_device 注册 v4l2_subdev：
+
+	int err = v4l2_device_register_subdev(v4l2_dev, sd);
+
+如果子设备模块在它注册前消失，这个操作可能失败。在这个函数成功返回后，
+subdev->dev 域就指向了 v4l2_device。
+
+如果 v4l2_device 父设备的 mdev 域为非 NULL 值，则子设备实体将被自动
+注册为媒体设备。
+
+注销子设备则可用如下函数：
+
+	v4l2_device_unregister_subdev(sd);
+
+此后，子设备模块就可卸载，且 sd->dev == NULL。
+
+注册之设备后，可通过以下方式直接调用其操作函数：
+
+	err = sd->ops->core->g_std(sd, &norm);
+
+但使用如下宏会比较容易且合适：
+
+	err = v4l2_subdev_call(sd, core, g_std, &norm);
+
+这个宏将会做 NULL 指针检查，如果 subdev 为 NULL，则返回-ENODEV；如果
+subdev->core 或 subdev->core->g_std 为 NULL，则返回 -ENOIOCTLCMD；
+否则将返回 subdev->ops->core->g_std ops 调用的实际结果。
+
+有时也可能同时调用所有或一系列子设备的某个操作函数：
+
+	v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm);
+
+任何不支持此操作的子设备都会被跳过，并忽略错误返回值。但如果你需要
+检查出错码，则可使用如下函数：
+
+	err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm);
+
+除 -ENOIOCTLCMD 外的任何错误都会跳出循环并返回错误值。如果（除 -ENOIOCTLCMD
+外）没有错误发生，则返回 0。
+
+对于以上两个函数的第二个参数为组 ID。如果为 0，则所有子设备都会执行
+这个操作。如果为非 0 值，则只有那些组 ID 匹配的子设备才会执行此操作。
+在桥驱动注册一个子设备前，可以设置 sd->grp_id 为任何期望值（默认值为
+0）。这个值属于桥驱动，且子设备驱动将不会修改和使用它。
+
+组 ID 赋予了桥驱动更多对于如何调用回调的控制。例如，电路板上有多个
+音频芯片，每个都有改变音量的能力。但当用户想要改变音量的时候，通常
+只有一个会被实际使用。你可以对这样的子设备设置组 ID 为（例如 AUDIO_CONTROLLER）
+并在调用 v4l2_device_call_all() 时指定它为组 ID 值。这就保证了只有
+需要的子设备才会执行这个回调。
+
+如果子设备需要通知它的 v4l2_device 父设备一个事件，可以调用
+v4l2_subdev_notify(sd, notification, arg)。这个宏检查是否有一个
+notify() 回调被注册，如果没有，返回 -ENODEV。否则返回 notify() 调用
+结果。
+
+使用 v4l2_subdev 的好处在于它是一个通用结构体，且不包含任何底层硬件
+信息。所有驱动可以包含多个 I2C 总线的子设备，但也有子设备是通过 GPIO
+控制。这个区别仅在配置设备时有关系，一旦子设备注册完成，对于 v4l2
+子系统来说就完全透明了。
+
+
+V4L2 子设备用户空间API
+--------------------
+
+除了通过 v4l2_subdev_ops 结构导出的内核 API，V4L2 子设备也可以直接
+通过用户空间应用程序来控制。
+
+可以在 /dev 中创建名为 v4l-subdevX 设备节点，以通过其直接访问子设备。
+如果子设备支持用户空间直接配置，必须在注册前设置 V4L2_SUBDEV_FL_HAS_DEVNODE
+标志。
+
+注册子设备之后， v4l2_device 驱动会通过调用 v4l2_device_register_subdev_nodes()
+函数为所有已注册并设置了 V4L2_SUBDEV_FL_HAS_DEVNODE 的子设备创建
+设备节点。这些设备节点会在子设备注销时自动删除。
+
+这些设备节点处理 V4L2 API 的一个子集。
+
+VIDIOC_QUERYCTRL
+VIDIOC_QUERYMENU
+VIDIOC_G_CTRL
+VIDIOC_S_CTRL
+VIDIOC_G_EXT_CTRLS
+VIDIOC_S_EXT_CTRLS
+VIDIOC_TRY_EXT_CTRLS
+
+	这些 ioctls 控制与 V4L2 中定义的一致。他们行为相同，唯一的
+	不同是他们只处理子设备的控制实现。根据驱动程序，这些控制也
+	可以通过一个（或多个） V4L2 设备节点访问。
+
+VIDIOC_DQEVENT
+VIDIOC_SUBSCRIBE_EVENT
+VIDIOC_UNSUBSCRIBE_EVENT
+
+	这些  ioctls 事件与 V4L2 中定义的一致。他们行为相同，唯一的
+	不同是他们只处理子设备产生的事件。根据驱动程序，这些事件也
+	可以通过一个（或多个） V4L2 设备节点上报。
+
+	要使用事件通知的子设备驱动，在注册子设备前必须在 v4l2_subdev::flags
+	中设置 V4L2_SUBDEV_USES_EVENTS 并在 v4l2_subdev::nevents
+	中初始化事件队列深度。注册完成后，事件会在 v4l2_subdev::devnode
+	设备节点中像通常一样被排队。
+
+	为正确支持事件机制，poll() 文件操作也应被实现。
+
+私有 ioctls
+
+	不在以上列表中的所有 ioctls 会通过 core::ioctl 操作直接传递
+	给子设备驱动。
+
+
+I2C 子设备驱动
+-------------
+
+由于这些驱动很常见，所以内特提供了特定的辅助函数(v4l2-common.h)让这些
+设备的使用更加容易。
+
+添加 v4l2_subdev 支持的推荐方法是让 I2C 驱动将 v4l2_subdev 结构体
+嵌入到为每个 I2C 设备实例创建的状态结构体中。而最简单的设备没有状态
+结构体，此时可以直接创建一个 v4l2_subdev 结构体。
+
+一个典型的状态结构体如下所示（‘chipname’用芯片名代替）：
+
+struct chipname_state {
+	struct v4l2_subdev sd;
+	...  /* 附加的状态域*/
+};
+
+初始化 v4l2_subdev 结构体的方法如下：
+
+	v4l2_i2c_subdev_init(&state->sd, client, subdev_ops);
+
+这个函数将填充 v4l2_subdev 结构体中的所有域，并保证 v4l2_subdev 和
+i2c_client 都指向彼此。
+
+同时，你也应该为从 v4l2_subdev 指针找到 chipname_state 结构体指针
+添加一个辅助内联函数。
+
+static inline struct chipname_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct chipname_state, sd);
+}
+
+使用以下函数可以通过 v4l2_subdev 结构体指针获得 i2c_client 结构体
+指针：
+
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+而以下函数则相反，通过 i2c_client 结构体指针获得 v4l2_subdev 结构体
+指针：
+
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+当 remove()函数被调用前，必须保证先调用 v4l2_device_unregister_subdev(sd)。
+此操作将会从桥驱动中注销子设备。即使子设备没有注册，调用此函数也是
+安全的。
+
+必须这样做的原因是：当桥驱动注销 i2c 适配器时，remove()回调函数
+会被那个适配器上的 i2c 设备调用。此后，相应的 v4l2_subdev 结构体
+就不存在了，所有它们必须先被注销。在 remove()回调函数中调用
+v4l2_device_unregister_subdev(sd)，可以保证执行总是正确的。
+
+
+桥驱动也有一些辅组函数可用：
+
+struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter,
+	       "module_foo", "chipid", 0x36, NULL);
+
+这个函数会加载给定的模块（如果没有模块需要加载，可以为 NULL），
+并用给定的 i2c 适配器结构体指针（i2c_adapter）和 器件地址（chip/address）
+作为参数调用 i2c_new_device()。如果一切顺利，则就在 v4l2_device
+中注册了子设备。
+
+你也可以利用 v4l2_i2c_new_subdev()的最后一个参数，传递一个可能的
+I2C 地址数组，让函数自动探测。这些探测地址只有在前一个参数为 0 的
+情况下使用。非零参数意味着你知道准确的 i2c 地址，所以此时无须进行
+探测。
+
+如果出错，两个函数都返回 NULL。
+
+注意：传递给 v4l2_i2c_new_subdev()的 chipid 通常与模块名一致。
+它允许你指定一个芯片的变体，比如“saa7114”或“saa7115”。一般通过
+i2c 驱动自动探测。chipid 的使用是在今后需要深入了解的事情。这个与
+i2c 驱动不同，较容易混淆。要知道支持哪些芯片变体，你可以查阅 i2c
+驱动代码的 i2c_device_id 表，上面列出了所有可能支持的芯片。
+
+还有两个辅助函数：
+
+v4l2_i2c_new_subdev_cfg：这个函数添加新的 irq 和 platform_data
+参数，并有‘addr’和‘probed_addrs’参数：如果 addr 非零，则被使用
+（不探测变体），否则 probed_addrs 中的地址将用于自动探测。
+
+例如：以下代码将会探测地址（0x10）：
+
+struct v4l2_subdev *sd = v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter,
+	       "module_foo", "chipid", 0, NULL, 0, I2C_ADDRS(0x10));
+
+v4l2_i2c_new_subdev_board 使用一个 i2c_board_info 结构体，将其
+替代 irq、platform_data 和 add r参数传递给 i2c 驱动。
+
+如果子设备支持 s_config 核心操作，这个操作会在子设备配置好之后以 irq 和
+platform_data 为参数调用。早期的 v4l2_i2c_new_(probed_)subdev 函数
+同样也会调用 s_config，但仅在 irq 为 0 且 platform_data 为 NULL 时。
+
+video_device结构体
+-----------------
+
+在 /dev 目录下的实际设备节点根据 video_device 结构体(v4l2-dev.h)
+创建。此结构体既可以动态分配也可以嵌入到一个更大的结构体中。
+
+动态分配方法如下：
+
+	struct video_device *vdev = video_device_alloc();
+
+	if (vdev == NULL)
+		return -ENOMEM;
+
+	vdev->release = video_device_release;
+
+如果将其嵌入到一个大结构体中，则必须自己实现 release()回调。
+
+	struct video_device *vdev = &my_vdev->vdev;
+
+	vdev->release = my_vdev_release;
+
+release()回调必须被设置，且在最后一个 video_device 用户退出之后
+被调用。
+
+默认的 video_device_release()回调只是调用 kfree 来释放之前分配的
+内存。
+
+你应该设置这些域：
+
+- v4l2_dev: 设置为 v4l2_device 父设备。
+
+- name: 设置为唯一的描述性设备名。
+
+- fops: 设置为已有的 v4l2_file_operations 结构体。
+
+- ioctl_ops: 如果你使用v4l2_ioctl_ops 来简化 ioctl 的维护
+  (强烈建议使用，且将来可能变为强制性的!)，然后设置你自己的
+  v4l2_ioctl_ops 结构体.
+
+- lock: 如果你要在驱动中实现所有的锁操作，则设为 NULL 。否则
+  就要设置一个指向 struct mutex_lock 结构体的指针，这个锁将
+  在 unlocked_ioctl 文件操作被调用前由内核获得，并在调用返回后
+  释放。详见下一节。
+
+- prio: 保持对优先级的跟踪。用于实现 VIDIOC_G/S_PRIORITY。如果
+  设置为 NULL，则会使用 v4l2_device 中的 v4l2_prio_state 结构体。
+  如果要对每个设备节点（组）实现独立的优先级，可以将其指向自己
+  实现的 v4l2_prio_state 结构体。
+
+- parent: 仅在使用 NULL 作为父设备结构体参数注册 v4l2_device 时
+  设置此参数。只有在一个硬件设备包含多一个 PCI 设备，共享同一个
+  v4l2_device 核心时才会发生。
+
+  cx88 驱动就是一个例子：一个 v4l2_device 结构体核心，被一个裸的
+  视频 PCI 设备(cx8800)和一个 MPEG PCI 设备(cx8802)共用。由于
+  v4l2_device 无法与特定的 PCI 设备关联，所有没有设置父设备。但当
+  video_device 配置后，就知道使用哪个父 PCI 设备了。
+
+如果你使用 v4l2_ioctl_ops，则应该在 v4l2_file_operations 结构体中
+设置 .unlocked_ioctl 指向 video_ioctl2。
+
+请勿使用 .ioctl！它已被废弃，今后将消失。
+
+某些情况下你要告诉核心：你在 v4l2_ioctl_ops 指定的某个函数应被忽略。
+你可以在 video_device_register 被调用前通过以下函数标记这个 ioctls。
+
+void v4l2_disable_ioctl(struct video_device *vdev, unsigned int cmd);
+
+基于外部因素（例如某个板卡已被使用），在不创建新结构体的情况下，你想
+要关闭 v4l2_ioctl_ops 中某个特性往往需要这个机制。
+
+v4l2_file_operations 结构体是 file_operations 的一个子集。其主要
+区别在于：因 inode 参数从未被使用，它将被忽略。
+
+如果需要与媒体框架整合，你必须通过调用 media_entity_pads_init() 初始化
+嵌入在 video_device 结构体中的 media_entity（entity 域）结构体：
+
+	struct media_pad *pad = &my_vdev->pad;
+	int err;
+
+	err = media_entity_pads_init(&vdev->entity, 1, pad);
+
+pads 数组必须预先初始化。没有必要手动设置 media_entity 的 type 和
+name 域。
+
+当（任何）子设备节点被打开/关闭，对 entity 的引用将被自动获取/释放。
+
+v4l2_file_operations 与锁
+--------------------------
+
+你可以在 video_device 结构体中设置一个指向 mutex_lock 的指针。通常
+这既可是一个顶层互斥锁也可为设备节点自身的互斥锁。默认情况下，此锁
+用于 unlocked_ioctl，但为了使用 ioctls 你通过以下函数可禁用锁定：
+
+	void v4l2_disable_ioctl_locking(struct video_device *vdev, unsigned int cmd);
+
+例如: v4l2_disable_ioctl_locking(vdev, VIDIOC_DQBUF);
+
+你必须在注册 video_device 前调用这个函数。
+
+特别是对于 USB 驱动程序，某些命令（如设置控制）需要很长的时间，可能
+需要自行为缓冲区队列的 ioctls 实现锁定。
+
+如果你需要更细粒度的锁，你必须设置 mutex_lock 为 NULL，并完全自己实现
+锁机制。
+
+这完全由驱动开发者决定使用何种方法。然而，如果你的驱动存在长延时操作
+（例如，改变 USB 摄像头的曝光时间可能需要较长时间），而你又想让用户
+在等待长延时操作完成期间做其他的事，则你最好自己实现锁机制。
+
+如果指定一个锁，则所有 ioctl 操作将在这个锁的作用下串行执行。如果你
+使用 videobuf，则必须将同一个锁传递给 videobuf 队列初始化函数；如
+videobuf 必须等待一帧的到达，则可临时解锁并在这之后重新上锁。如果驱动
+也在代码执行期间等待，则可做同样的工作（临时解锁，再上锁）让其他进程
+可以在第一个进程阻塞时访问设备节点。
+
+在使用 videobuf2 的情况下，必须实现 wait_prepare 和 wait_finish 回调
+在适当的时候解锁/加锁。进一步来说，如果你在 video_device 结构体中使用
+锁，则必须在 wait_prepare 和 wait_finish 中对这个互斥锁进行解锁/加锁。
+
+热插拔的断开实现也必须在调用 v4l2_device_disconnect 前获得锁。
+
+video_device注册
+---------------
+
+接下来你需要注册视频设备：这会为你创建一个字符设备。
+
+	err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	if (err) {
+		video_device_release(vdev); /* or kfree(my_vdev); */
+		return err;
+	}
+
+如果 v4l2_device 父设备的 mdev 域为非 NULL 值，视频设备实体将自动
+注册为媒体设备。
+
+注册哪种设备是根据类型（type）参数。存在以下类型：
+
+VFL_TYPE_GRABBER: 用于视频输入/输出设备的 videoX
+VFL_TYPE_VBI: 用于垂直消隐数据的 vbiX (例如，隐藏式字幕，图文电视)
+VFL_TYPE_RADIO: 用于广播调谐器的 radioX
+
+最后一个参数让你确定一个所控制设备的设备节点号数量(例如 videoX 中的 X)。
+通常你可以传入-1，让 v4l2 框架自己选择第一个空闲的编号。但是有时用户
+需要选择一个特定的节点号。驱动允许用户通过驱动模块参数选择一个特定的
+设备节点号是很普遍的。这个编号将会传递给这个函数，且 video_register_device
+将会试图选择这个设备节点号。如果这个编号被占用，下一个空闲的设备节点
+编号将被选中，并向内核日志中发送一个警告信息。
+
+另一个使用场景是当驱动创建多个设备时。这种情况下，对不同的视频设备在
+编号上使用不同的范围是很有用的。例如，视频捕获设备从 0 开始，视频
+输出设备从 16 开始。所以你可以使用最后一个参数来指定设备节点号最小值，
+而 v4l2 框架会试图选择第一个的空闲编号（等于或大于你提供的编号）。
+如果失败，则它会就选择第一个空闲的编号。
+
+由于这种情况下，你会忽略无法选择特定设备节点号的警告，则可调用
+video_register_device_no_warn() 函数避免警告信息的产生。
+
+只要设备节点被创建，一些属性也会同时创建。在 /sys/class/video4linux
+目录中你会找到这些设备。例如进入其中的 video0 目录，你会看到‘name’和
+‘index’属性。‘name’属性值就是 video_device 结构体中的‘name’域。
+
+‘index’属性值就是设备节点的索引值：每次调用 video_register_device()，
+索引值都递增 1 。第一个视频设备节点总是从索引值 0 开始。
+
+用户可以设置 udev 规则，利用索引属性生成花哨的设备名（例如：用‘mpegX’
+代表 MPEG 视频捕获设备节点）。
+
+在设备成功注册后，就可以使用这些域：
+
+- vfl_type: 传递给 video_register_device 的设备类型。
+- minor: 已指派的次设备号。
+- num: 设备节点编号 (例如 videoX 中的 X)。
+- index: 设备索引号。
+
+如果注册失败，你必须调用 video_device_release() 来释放已分配的
+video_device 结构体；如果 video_device 是嵌入在自己创建的结构体中，
+你也必须释放它。vdev->release() 回调不会在注册失败之后被调用，
+你也不应试图在注册失败后注销设备。
+
+
+video_device 注销
+----------------
+
+当视频设备节点已被移除，不论是卸载驱动还是USB设备断开，你都应注销
+它们：
+
+	video_unregister_device(vdev);
+
+这个操作将从 sysfs 中移除设备节点（导致 udev 将其从 /dev 中移除）。
+
+video_unregister_device() 返回之后，就无法完成打开操作。尽管如此，
+USB 设备的情况则不同，某些应用程序可能依然打开着其中一个已注销设备
+节点。所以在注销之后，所有文件操作（当然除了 release ）也应返回错误值。
+
+当最后一个视频设备节点的用户退出，则 vdev->release() 回调会被调用，
+并且你可以做最后的清理操作。
+
+不要忘记清理与视频设备相关的媒体入口（如果被初始化过）：
+
+	media_entity_cleanup(&vdev->entity);
+
+这可以在 release 回调中完成。
+
+
+video_device 辅助函数
+---------------------
+
+一些有用的辅助函数如下：
+
+- file/video_device 私有数据
+
+你可以用以下函数在 video_device 结构体中设置/获取驱动私有数据：
+
+void *video_get_drvdata(struct video_device *vdev);
+void video_set_drvdata(struct video_device *vdev, void *data);
+
+注意：在调用 video_register_device() 前执行 video_set_drvdata()
+是安全的。
+
+而以下函数：
+
+struct video_device *video_devdata(struct file *file);
+
+返回 file 结构体中拥有的的 video_device 指针。
+
+video_drvdata 辅助函数结合了 video_get_drvdata 和 video_devdata
+的功能：
+
+void *video_drvdata(struct file *file);
+
+你可以使用如下代码从 video_device 结构体中获取 v4l2_device 结构体
+指针：
+
+struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
+
+- 设备节点名
+
+video_device 设备节点在内核中的名称可以通过以下函数获得
+
+const char *video_device_node_name(struct video_device *vdev);
+
+这个名字被用户空间工具（例如 udev）作为提示信息使用。应尽可能使用
+此功能，而非访问 video_device::num 和 video_device::minor 域。
+
+
+视频缓冲辅助函数
+---------------
+
+v4l2 核心 API 提供了一个处理视频缓冲的标准方法(称为“videobuf”)。
+这些方法使驱动可以通过统一的方式实现 read()、mmap() 和 overlay()。
+目前在设备上支持视频缓冲的方法有分散/聚集 DMA(videobuf-dma-sg)、
+线性 DMA(videobuf-dma-contig)以及大多用于 USB 设备的用 vmalloc
+分配的缓冲(videobuf-vmalloc)。
+
+请参阅 Documentation/video4linux/videobuf，以获得更多关于 videobuf
+层的使用信息。
+
+v4l2_fh 结构体
+-------------
+
+v4l2_fh 结构体提供一个保存用于 V4L2 框架的文件句柄特定数据的简单方法。
+如果 video_device 标志，新驱动
+必须使用 v4l2_fh 结构体，因为它也用于实现优先级处理（VIDIOC_G/S_PRIORITY）。
+
+v4l2_fh 的用户（位于 V4l2 框架中，并非驱动）可通过测试
+video_device->flags 中的 V4L2_FL_USES_V4L2_FH 位得知驱动是否使用
+v4l2_fh 作为他的 file->private_data 指针。这个位会在调用 v4l2_fh_init()
+时被设置。
+
+v4l2_fh 结构体作为驱动自身文件句柄结构体的一部分被分配，且驱动在
+其打开函数中将 file->private_data 指向它。
+
+在许多情况下，v4l2_fh 结构体会嵌入到一个更大的结构体中。这钟情况下，
+应该在 open() 中调用 v4l2_fh_init+v4l2_fh_add，并在 release() 中
+调用 v4l2_fh_del+v4l2_fh_exit。
+
+驱动可以通过使用 container_of 宏提取他们自己的文件句柄结构体。例如：
+
+struct my_fh {
+	int blah;
+	struct v4l2_fh fh;
+};
+
+...
+
+int my_open(struct file *file)
+{
+	struct my_fh *my_fh;
+	struct video_device *vfd;
+	int ret;
+
+	...
+
+	my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL);
+
+	...
+
+	v4l2_fh_init(&my_fh->fh, vfd);
+
+	...
+
+	file->private_data = &my_fh->fh;
+	v4l2_fh_add(&my_fh->fh);
+	return 0;
+}
+
+int my_release(struct file *file)
+{
+	struct v4l2_fh *fh = file->private_data;
+	struct my_fh *my_fh = container_of(fh, struct my_fh, fh);
+
+	...
+	v4l2_fh_del(&my_fh->fh);
+	v4l2_fh_exit(&my_fh->fh);
+	kfree(my_fh);
+	return 0;
+}
+
+以下是 v4l2_fh 函数使用的简介：
+
+void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
+
+  初始化文件句柄。这*必须*在驱动的 v4l2_file_operations->open()
+  函数中执行。
+
+void v4l2_fh_add(struct v4l2_fh *fh)
+
+  添加一个 v4l2_fh 到 video_device 文件句柄列表。一旦文件句柄
+  初始化完成就必须调用。
+
+void v4l2_fh_del(struct v4l2_fh *fh)
+
+  从 video_device() 中解除文件句柄的关联。文件句柄的退出函数也
+  将被调用。
+
+void v4l2_fh_exit(struct v4l2_fh *fh)
+
+  清理文件句柄。在清理完 v4l2_fh 后，相关内存会被释放。
+
+
+如果 v4l2_fh 不是嵌入在其他结构体中的，则可以用这些辅助函数：
+
+int v4l2_fh_open(struct file *filp)
+
+  分配一个 v4l2_fh 结构体空间，初始化并将其添加到 file 结构体相关的
+  video_device 结构体中。
+
+int v4l2_fh_release(struct file *filp)
+
+  从 file 结构体相关的 video_device 结构体中删除 v4l2_fh ，清理
+  v4l2_fh 并释放空间。
+
+这两个函数可以插入到 v4l2_file_operation 的 open() 和 release()
+操作中。
+
+
+某些驱动需要在第一个文件句柄打开和最后一个文件句柄关闭的时候做些
+工作。所以加入了两个辅助函数以检查 v4l2_fh 结构体是否是相关设备
+节点打开的唯一文件句柄。
+
+int v4l2_fh_is_singular(struct v4l2_fh *fh)
+
+  如果此文件句柄是唯一打开的文件句柄，则返回 1 ，否则返回 0 。
+
+int v4l2_fh_is_singular_file(struct file *filp)
+
+  功能相同，但通过 filp->private_data 调用 v4l2_fh_is_singular。
+
+
+V4L2 事件机制
+-----------
+
+V4L2 事件机制提供了一个通用的方法将事件传递到用户空间。驱动必须使用
+v4l2_fh 才能支持 V4L2 事件机制。
+
+
+事件通过一个类型和选择 ID 来定义。ID 对应一个 V4L2 对象，例如
+一个控制 ID。如果未使用，则 ID 为 0。
+
+当用户订阅一个事件，驱动会为此分配一些 kevent 结构体。所以每个
+事件组（类型、ID）都会有自己的一套 kevent 结构体。这保证了如果
+一个驱动短时间内产生了许多同类事件，不会覆盖其他类型的事件。
+
+但如果你收到的事件数量大于同类事件 kevent 的保存数量，则最早的
+事件将被丢弃，并加入新事件。
+
+此外，v4l2_subscribed_event 结构体内部有可供驱动设置的 merge() 和
+replace() 回调，这些回调会在新事件产生且没有多余空间的时候被调用。
+replace() 回调让你可以将早期事件的净荷替换为新事件的净荷，将早期
+净荷的相关数据合并到替换进来的新净荷中。当该类型的事件仅分配了一个
+kevent 结构体时，它将被调用。merge() 回调让你可以合并最早的事件净荷
+到在它之后的那个事件净荷中。当该类型的事件分配了两个或更多 kevent
+结构体时，它将被调用。
+
+这种方法不会有状态信息丢失，只会导致中间步骤信息丢失。
+
+
+关于 replace/merge 回调的一个不错的例子在 v4l2-event.c 中：用于
+控制事件的 ctrls_replace() 和 ctrls_merge() 回调。
+
+注意：这些回调可以在中断上下文中调用，所以它们必须尽快完成并退出。
+
+有用的函数：
+
+void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
+
+  将事件加入视频设备的队列。驱动仅负责填充 type 和 data 域。
+  其他域由 V4L2 填充。
+
+int v4l2_event_subscribe(struct v4l2_fh *fh,
+			 struct v4l2_event_subscription *sub, unsigned elems,
+			 const struct v4l2_subscribed_event_ops *ops)
+
+  video_device->ioctl_ops->vidioc_subscribe_event 必须检测驱动能
+  产生特定 id 的事件。然后调用 v4l2_event_subscribe() 来订阅该事件。
+
+  elems 参数是该事件的队列大小。若为 0，V4L2 框架将会（根据事件类型）
+  填充默认值。
+
+  ops 参数允许驱动指定一系列回调：
+  * add:     当添加一个新监听者时调用（重复订阅同一个事件，此回调
+             仅被执行一次）。
+  * del:     当一个监听者停止监听时调用。
+  * replace: 用‘新’事件替换‘早期‘事件。
+  * merge:   将‘早期‘事件合并到‘新’事件中。
+  这四个调用都是可选的，如果不想指定任何回调，则 ops 可为 NULL。
+
+int v4l2_event_unsubscribe(struct v4l2_fh *fh,
+			   struct v4l2_event_subscription *sub)
+
+  v4l2_ioctl_ops 结构体中的 vidioc_unsubscribe_event 回调函数。
+  驱动程序可以直接使用 v4l2_event_unsubscribe() 实现退订事件过程。
+
+  特殊的 V4L2_EVENT_ALL 类型，可用于退订所有事件。驱动可能在特殊
+  情况下需要做此操作。
+
+int v4l2_event_pending(struct v4l2_fh *fh)
+
+  返回未决事件的数量。有助于实现轮询（poll）操作。
+
+事件通过 poll 系统调用传递到用户空间。驱动可用
+v4l2_fh->wait (wait_queue_head_t 类型)作为参数调用 poll_wait()。
+
+事件分为标准事件和私有事件。新的标准事件必须使用可用的最小事件类型
+编号。驱动必须从他们本类型的编号起始处分配事件。类型的编号起始为
+V4L2_EVENT_PRIVATE_START + n * 1000 ，其中 n 为可用最小编号。每个
+类型中的第一个事件类型编号是为以后的使用保留的，所以第一个可用事件
+类型编号是‘class base + 1’。
+
+V4L2 事件机制的使用实例可以在 OMAP3 ISP 的驱动
+(drivers/media/video/omap3isp)中找到。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/translations/zh_CN/volatile-considered-harmful.txt linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/volatile-considered-harmful.txt
--- linux-libre-4.9-gnu/Documentation/translations/zh_CN/volatile-considered-harmful.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/translations/zh_CN/volatile-considered-harmful.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,113 @@
+Chinese translated version of Documentation/process/volatile-considered-harmful.rst
+
+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.
+
+Maintainer: Jonathan Corbet <corbet@lwn.net>
+Chinese maintainer: Bryan Wu <bryan.wu@analog.com>
+---------------------------------------------------------------------
+Documentation/process/volatile-considered-harmful.rst 的中文翻译
+
+如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
+交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题，请联系中文版维护者。
+
+英文版维护者： Jonathan Corbet <corbet@lwn.net>
+中文版维护者： 伍鹏  Bryan Wu <bryan.wu@analog.com>
+中文版翻译者： 伍鹏  Bryan Wu <bryan.wu@analog.com>
+中文版校译者： 张汉辉  Eugene Teo <eugeneteo@kernel.sg>
+               杨瑞  Dave Young <hidave.darkstar@gmail.com>
+以下为正文
+---------------------------------------------------------------------
+
+为什么不应该使用“volatile”类型
+------------------------------
+
+C程序员通常认为volatile表示某个变量可以在当前执行的线程之外被改变；因此，在内核
+中用到共享数据结构时，常常会有C程序员喜欢使用volatile这类变量。换句话说，他们经
+常会把volatile类型看成某种简易的原子变量，当然它们不是。在内核中使用volatile几
+乎总是错误的；本文档将解释为什么这样。
+
+理解volatile的关键是知道它的目的是用来消除优化，实际上很少有人真正需要这样的应
+用。在内核中，程序员必须防止意外的并发访问破坏共享的数据结构，这其实是一个完全
+不同的任务。用来防止意外并发访问的保护措施，可以更加高效的避免大多数优化相关的
+问题。
+
+像volatile一样，内核提供了很多原语来保证并发访问时的数据安全（自旋锁, 互斥量,内
+存屏障等等），同样可以防止意外的优化。如果可以正确使用这些内核原语，那么就没有
+必要再使用volatile。如果仍然必须使用volatile，那么几乎可以肯定在代码的某处有一
+个bug。在正确设计的内核代码中，volatile能带来的仅仅是使事情变慢。
+
+思考一下这段典型的内核代码：
+
+    spin_lock(&the_lock);
+    do_something_on(&shared_data);
+    do_something_else_with(&shared_data);
+    spin_unlock(&the_lock);
+
+如果所有的代码都遵循加锁规则，当持有the_lock的时候，不可能意外的改变shared_data的
+值。任何可能访问该数据的其他代码都会在这个锁上等待。自旋锁原语跟内存屏障一样—— 它
+们显式的用来书写成这样 —— 意味着数据访问不会跨越它们而被优化。所以本来编译器认为
+它知道在shared_data里面将有什么，但是因为spin_lock()调用跟内存屏障一样，会强制编
+译器忘记它所知道的一切。那么在访问这些数据时不会有优化的问题。
+
+如果shared_data被声名为volatile，锁操作将仍然是必须的。就算我们知道没有其他人正在
+使用它，编译器也将被阻止优化对临界区内shared_data的访问。在锁有效的同时，
+shared_data不是volatile的。在处理共享数据的时候，适当的锁操作可以不再需要
+volatile —— 并且是有潜在危害的。
+
+volatile的存储类型最初是为那些内存映射的I/O寄存器而定义。在内核里，寄存器访问也应
+该被锁保护，但是人们也不希望编译器“优化”临界区内的寄存器访问。内核里I/O的内存访问
+是通过访问函数完成的；不赞成通过指针对I/O内存的直接访问，并且不是在所有体系架构上
+都能工作。那些访问函数正是为了防止意外优化而写的，因此，再说一次，volatile类型不
+是必需的。
+
+另一种引起用户可能使用volatile的情况是当处理器正忙着等待一个变量的值。正确执行一
+个忙等待的方法是：
+
+    while (my_variable != what_i_want)
+        cpu_relax();
+
+cpu_relax()调用会降低CPU的能量消耗或者让位于超线程双处理器；它也作为内存屏障一样出
+现，所以，再一次，volatile不是必需的。当然，忙等待一开始就是一种反常规的做法。
+
+在内核中，一些稀少的情况下volatile仍然是有意义的：
+
+  - 在一些体系架构的系统上，允许直接的I/0内存访问，那么前面提到的访问函数可以使用
+    volatile。基本上，每一个访问函数调用它自己都是一个小的临界区域并且保证了按照
+    程序员期望的那样发生访问操作。
+
+  - 某些会改变内存的内联汇编代码虽然没有什么其他明显的附作用，但是有被GCC删除的可
+    能性。在汇编声明中加上volatile关键字可以防止这种删除操作。
+
+  - Jiffies变量是一种特殊情况，虽然每次引用它的时候都可以有不同的值，但读jiffies
+    变量时不需要任何特殊的加锁保护。所以jiffies变量可以使用volatile，但是不赞成
+    其他跟jiffies相同类型变量使用volatile。Jiffies被认为是一种“愚蠢的遗留物"
+    （Linus的话）因为解决这个问题比保持现状要麻烦的多。
+
+  - 由于某些I/0设备可能会修改连续一致的内存,所以有时,指向连续一致内存的数据结构
+    的指针需要正确的使用volatile。网络适配器使用的环状缓存区正是这类情形的一个例
+    子，其中适配器用改变指针来表示哪些描述符已经处理过了。
+
+对于大多代码，上述几种可以使用volatile的情况都不适用。所以，使用volatile是一种
+bug并且需要对这样的代码额外仔细检查。那些试图使用volatile的开发人员需要退一步想想
+他们真正想实现的是什么。
+
+非常欢迎删除volatile变量的补丁 － 只要证明这些补丁完整的考虑了并发问题。
+
+注释
+----
+
+[1] http://lwn.net/Articles/233481/
+[2] http://lwn.net/Articles/233482/
+
+致谢
+----
+
+最初由Randy Dunlap推动并作初步研究
+由Jonathan Corbet撰写
+参考Satyam Sharma，Johannes Stezenbach，Jesper Juhl，Heikki Orsila，
+H. Peter Anvin，Philipp Hahn和Stefan Richter的意见改善了本档。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/unaligned-memory-access.txt linux-libre-4.10-rc8-gnu/Documentation/unaligned-memory-access.txt
--- linux-libre-4.9-gnu/Documentation/unaligned-memory-access.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/unaligned-memory-access.txt	2017-02-12 16:03:20.000000000 -0500
@@ -151,7 +151,7 @@ bool ether_addr_equal(const u8 *addr1, c
 #else
 	const u16 *a = (const u16 *)addr1;
 	const u16 *b = (const u16 *)addr2;
-	return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0;
+	return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) == 0;
 #endif
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/unicode.txt linux-libre-4.10-rc8-gnu/Documentation/unicode.txt
--- linux-libre-4.9-gnu/Documentation/unicode.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/unicode.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-		 Last update: 2005-01-17, version 1.4
-
-This file is maintained by H. Peter Anvin <unicode@lanana.org> as part
-of the Linux Assigned Names And Numbers Authority (LANANA) project.
-The current version can be found at:
-
-	    http://www.lanana.org/docs/unicode/unicode.txt
-
-		       ------------------------
-
-The Linux kernel code has been rewritten to use Unicode to map
-characters to fonts.  By downloading a single Unicode-to-font table,
-both the eight-bit character sets and UTF-8 mode are changed to use
-the font as indicated.
-
-This changes the semantics of the eight-bit character tables subtly.
-The four character tables are now:
-
-Map symbol	Map name			Escape code (G0)
-
-LAT1_MAP	Latin-1 (ISO 8859-1)		ESC ( B
-GRAF_MAP	DEC VT100 pseudographics	ESC ( 0
-IBMPC_MAP	IBM code page 437		ESC ( U
-USER_MAP	User defined			ESC ( K
-
-In particular, ESC ( U is no longer "straight to font", since the font
-might be completely different than the IBM character set.  This
-permits for example the use of block graphics even with a Latin-1 font
-loaded.
-
-Note that although these codes are similar to ISO 2022, neither the
-codes nor their uses match ISO 2022; Linux has two 8-bit codes (G0 and
-G1), whereas ISO 2022 has four 7-bit codes (G0-G3).
-
-In accordance with the Unicode standard/ISO 10646 the range U+F000 to
-U+F8FF has been reserved for OS-wide allocation (the Unicode Standard
-refers to this as a "Corporate Zone", since this is inaccurate for
-Linux we call it the "Linux Zone").  U+F000 was picked as the starting
-point since it lets the direct-mapping area start on a large power of
-two (in case 1024- or 2048-character fonts ever become necessary).
-This leaves U+E000 to U+EFFF as End User Zone.
-
-[v1.2]: The Unicodes range from U+F000 and up to U+F7FF have been
-hard-coded to map directly to the loaded font, bypassing the
-translation table.  The user-defined map now defaults to U+F000 to
-U+F0FF, emulating the previous behaviour.  In practice, this range
-might be shorter; for example, vgacon can only handle 256-character
-(U+F000..U+F0FF) or 512-character (U+F000..U+F1FF) fonts.
-
-
-Actual characters assigned in the Linux Zone
---------------------------------------------
-
-In addition, the following characters not present in Unicode 1.1.4
-have been defined; these are used by the DEC VT graphics map.  [v1.2]
-THIS USE IS OBSOLETE AND SHOULD NO LONGER BE USED; PLEASE SEE BELOW.
-
-U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
-U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
-U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
-U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
-
-The DEC VT220 uses a 6x10 character matrix, and these characters form
-a smooth progression in the DEC VT graphics character set.  I have
-omitted the scan 5 line, since it is also used as a block-graphics
-character, and hence has been coded as U+2500 FORMS LIGHT HORIZONTAL.
-
-[v1.3]: These characters have been officially added to Unicode 3.2.0;
-they are added at U+23BA, U+23BB, U+23BC, U+23BD.  Linux now uses the
-new values.
-
-[v1.2]: The following characters have been added to represent common
-keyboard symbols that are unlikely to ever be added to Unicode proper
-since they are horribly vendor-specific.  This, of course, is an
-excellent example of horrible design.
-
-U+F810 KEYBOARD SYMBOL FLYING FLAG
-U+F811 KEYBOARD SYMBOL PULLDOWN MENU
-U+F812 KEYBOARD SYMBOL OPEN APPLE
-U+F813 KEYBOARD SYMBOL SOLID APPLE
-
-Klingon language support
-------------------------
-
-In 1996, Linux was the first operating system in the world to add
-support for the artificial language Klingon, created by Marc Okrand
-for the "Star Trek" television series.	This encoding was later
-adopted by the ConScript Unicode Registry and proposed (but ultimately
-rejected) for inclusion in Unicode Plane 1.  Thus, it remains as a
-Linux/CSUR private assignment in the Linux Zone.
-
-This encoding has been endorsed by the Klingon Language Institute.
-For more information, contact them at:
-
-	http://www.kli.org/
-
-Since the characters in the beginning of the Linux CZ have been more
-of the dingbats/symbols/forms type and this is a language, I have
-located it at the end, on a 16-cell boundary in keeping with standard
-Unicode practice.
-
-NOTE: This range is now officially managed by the ConScript Unicode
-Registry.  The normative reference is at:
-
-	http://www.evertype.com/standards/csur/klingon.html
-
-Klingon has an alphabet of 26 characters, a positional numeric writing
-system with 10 digits, and is written left-to-right, top-to-bottom.
-
-Several glyph forms for the Klingon alphabet have been proposed.
-However, since the set of symbols appear to be consistent throughout,
-with only the actual shapes being different, in keeping with standard
-Unicode practice these differences are considered font variants.
-
-U+F8D0	KLINGON LETTER A
-U+F8D1	KLINGON LETTER B
-U+F8D2	KLINGON LETTER CH
-U+F8D3	KLINGON LETTER D
-U+F8D4	KLINGON LETTER E
-U+F8D5	KLINGON LETTER GH
-U+F8D6	KLINGON LETTER H
-U+F8D7	KLINGON LETTER I
-U+F8D8	KLINGON LETTER J
-U+F8D9	KLINGON LETTER L
-U+F8DA	KLINGON LETTER M
-U+F8DB	KLINGON LETTER N
-U+F8DC	KLINGON LETTER NG
-U+F8DD	KLINGON LETTER O
-U+F8DE	KLINGON LETTER P
-U+F8DF	KLINGON LETTER Q
-	- Written <q> in standard Okrand Latin transliteration
-U+F8E0	KLINGON LETTER QH
-	- Written <Q> in standard Okrand Latin transliteration
-U+F8E1	KLINGON LETTER R
-U+F8E2	KLINGON LETTER S
-U+F8E3	KLINGON LETTER T
-U+F8E4	KLINGON LETTER TLH
-U+F8E5	KLINGON LETTER U
-U+F8E6	KLINGON LETTER V
-U+F8E7	KLINGON LETTER W
-U+F8E8	KLINGON LETTER Y
-U+F8E9	KLINGON LETTER GLOTTAL STOP
-
-U+F8F0	KLINGON DIGIT ZERO
-U+F8F1	KLINGON DIGIT ONE
-U+F8F2	KLINGON DIGIT TWO
-U+F8F3	KLINGON DIGIT THREE
-U+F8F4	KLINGON DIGIT FOUR
-U+F8F5	KLINGON DIGIT FIVE
-U+F8F6	KLINGON DIGIT SIX
-U+F8F7	KLINGON DIGIT SEVEN
-U+F8F8	KLINGON DIGIT EIGHT
-U+F8F9	KLINGON DIGIT NINE
-
-U+F8FD	KLINGON COMMA
-U+F8FE	KLINGON FULL STOP
-U+F8FF	KLINGON SYMBOL FOR EMPIRE
-
-Other Fictional and Artificial Scripts
---------------------------------------
-
-Since the assignment of the Klingon Linux Unicode block, a registry of
-fictional and artificial scripts has been established by John Cowan
-<jcowan@reutershealth.com> and Michael Everson <everson@evertype.com>.
-The ConScript Unicode Registry is accessible at:
-
-	  http://www.evertype.com/standards/csur/
-
-The ranges used fall at the low end of the End User Zone and can hence
-not be normatively assigned, but it is recommended that people who
-wish to encode fictional scripts use these codes, in the interest of
-interoperability.  For Klingon, CSUR has adopted the Linux encoding.
-The CSUR people are driving adding Tengwar and Cirth into Unicode
-Plane 1; the addition of Klingon to Unicode Plane 1 has been rejected
-and so the above encoding remains official.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/vfio-mediated-device.txt linux-libre-4.10-rc8-gnu/Documentation/vfio-mediated-device.txt
--- linux-libre-4.9-gnu/Documentation/vfio-mediated-device.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/vfio-mediated-device.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,401 @@
+/*
+ * VFIO Mediated devices
+ *
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ *     Author: Neo Jia <cjia@nvidia.com>
+ *             Kirti Wankhede <kwankhede@nvidia.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.
+ */
+
+Virtual Function I/O (VFIO) Mediated devices[1]
+===============================================
+
+The number of use cases for virtualizing DMA devices that do not have built-in
+SR_IOV capability is increasing. Previously, to virtualize such devices,
+developers had to create their own management interfaces and APIs, and then
+integrate them with user space software. To simplify integration with user space
+software, we have identified common requirements and a unified management
+interface for such devices.
+
+The VFIO driver framework provides unified APIs for direct device access. It is
+an IOMMU/device-agnostic framework for exposing direct device access to user
+space in a secure, IOMMU-protected environment. This framework is used for
+multiple devices, such as GPUs, network adapters, and compute accelerators. With
+direct device access, virtual machines or user space applications have direct
+access to the physical device. This framework is reused for mediated devices.
+
+The mediated core driver provides a common interface for mediated device
+management that can be used by drivers of different devices. This module
+provides a generic interface to perform these operations:
+
+* Create and destroy a mediated device
+* Add a mediated device to and remove it from a mediated bus driver
+* Add a mediated device to and remove it from an IOMMU group
+
+The mediated core driver also provides an interface to register a bus driver.
+For example, the mediated VFIO mdev driver is designed for mediated devices and
+supports VFIO APIs. The mediated bus driver adds a mediated device to and
+removes it from a VFIO group.
+
+The following high-level block diagram shows the main components and interfaces
+in the VFIO mediated driver framework. The diagram shows NVIDIA, Intel, and IBM
+devices as examples, as these devices are the first devices to use this module.
+
+     +---------------+
+     |               |
+     | +-----------+ |  mdev_register_driver() +--------------+
+     | |           | +<------------------------+              |
+     | |  mdev     | |                         |              |
+     | |  bus      | +------------------------>+ vfio_mdev.ko |<-> VFIO user
+     | |  driver   | |     probe()/remove()    |              |    APIs
+     | |           | |                         +--------------+
+     | +-----------+ |
+     |               |
+     |  MDEV CORE    |
+     |   MODULE      |
+     |   mdev.ko     |
+     | +-----------+ |  mdev_register_device() +--------------+
+     | |           | +<------------------------+              |
+     | |           | |                         |  nvidia.ko   |<-> physical
+     | |           | +------------------------>+              |    device
+     | |           | |        callbacks        +--------------+
+     | | Physical  | |
+     | |  device   | |  mdev_register_device() +--------------+
+     | | interface | |<------------------------+              |
+     | |           | |                         |  i915.ko     |<-> physical
+     | |           | +------------------------>+              |    device
+     | |           | |        callbacks        +--------------+
+     | |           | |
+     | |           | |  mdev_register_device() +--------------+
+     | |           | +<------------------------+              |
+     | |           | |                         | ccw_device.ko|<-> physical
+     | |           | +------------------------>+              |    device
+     | |           | |        callbacks        +--------------+
+     | +-----------+ |
+     +---------------+
+
+
+Registration Interfaces
+=======================
+
+The mediated core driver provides the following types of registration
+interfaces:
+
+* Registration interface for a mediated bus driver
+* Physical device driver interface
+
+Registration Interface for a Mediated Bus Driver
+------------------------------------------------
+
+The registration interface for a mediated bus driver provides the following
+structure to represent a mediated device's driver:
+
+     /*
+      * struct mdev_driver [2] - Mediated device's driver
+      * @name: driver name
+      * @probe: called when new device created
+      * @remove: called when device removed
+      * @driver: device driver structure
+      */
+     struct mdev_driver {
+	     const char *name;
+	     int  (*probe)  (struct device *dev);
+	     void (*remove) (struct device *dev);
+	     struct device_driver    driver;
+     };
+
+A mediated bus driver for mdev should use this structure in the function calls
+to register and unregister itself with the core driver:
+
+* Register:
+
+  extern int  mdev_register_driver(struct mdev_driver *drv,
+				   struct module *owner);
+
+* Unregister:
+
+  extern void mdev_unregister_driver(struct mdev_driver *drv);
+
+The mediated bus driver is responsible for adding mediated devices to the VFIO
+group when devices are bound to the driver and removing mediated devices from
+the VFIO when devices are unbound from the driver.
+
+
+Physical Device Driver Interface
+--------------------------------
+
+The physical device driver interface provides the mdev_parent_ops[3] structure
+to define the APIs to manage work in the mediated core driver that is related
+to the physical device.
+
+The structures in the mdev_parent_ops structure are as follows:
+
+* dev_attr_groups: attributes of the parent device
+* mdev_attr_groups: attributes of the mediated device
+* supported_config: attributes to define supported configurations
+
+The functions in the mdev_parent_ops structure are as follows:
+
+* create: allocate basic resources in a driver for a mediated device
+* remove: free resources in a driver when a mediated device is destroyed
+
+The callbacks in the mdev_parent_ops structure are as follows:
+
+* open: open callback of mediated device
+* close: close callback of mediated device
+* ioctl: ioctl callback of mediated device
+* read : read emulation callback
+* write: write emulation callback
+* mmap: mmap emulation callback
+
+A driver should use the mdev_parent_ops structure in the function call to
+register itself with the mdev core driver:
+
+extern int  mdev_register_device(struct device *dev,
+                                 const struct mdev_parent_ops *ops);
+
+However, the mdev_parent_ops structure is not required in the function call
+that a driver should use to unregister itself with the mdev core driver:
+
+extern void mdev_unregister_device(struct device *dev);
+
+
+Mediated Device Management Interface Through sysfs
+==================================================
+
+The management interface through sysfs enables user space software, such as
+libvirt, to query and configure mediated devices in a hardware-agnostic fashion.
+This management interface provides flexibility to the underlying physical
+device's driver to support features such as:
+
+* Mediated device hot plug
+* Multiple mediated devices in a single virtual machine
+* Multiple mediated devices from different physical devices
+
+Links in the mdev_bus Class Directory
+-------------------------------------
+The /sys/class/mdev_bus/ directory contains links to devices that are registered
+with the mdev core driver.
+
+Directories and files under the sysfs for Each Physical Device
+--------------------------------------------------------------
+
+|- [parent physical device]
+|--- Vendor-specific-attributes [optional]
+|--- [mdev_supported_types]
+|     |--- [<type-id>]
+|     |   |--- create
+|     |   |--- name
+|     |   |--- available_instances
+|     |   |--- device_api
+|     |   |--- description
+|     |   |--- [devices]
+|     |--- [<type-id>]
+|     |   |--- create
+|     |   |--- name
+|     |   |--- available_instances
+|     |   |--- device_api
+|     |   |--- description
+|     |   |--- [devices]
+|     |--- [<type-id>]
+|          |--- create
+|          |--- name
+|          |--- available_instances
+|          |--- device_api
+|          |--- description
+|          |--- [devices]
+
+* [mdev_supported_types]
+
+  The list of currently supported mediated device types and their details.
+
+  [<type-id>], device_api, and available_instances are mandatory attributes
+  that should be provided by vendor driver.
+
+* [<type-id>]
+
+  The [<type-id>] name is created by adding the the device driver string as a
+  prefix to the string provided by the vendor driver. This format of this name
+  is as follows:
+
+	sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
+
+  (or using mdev_parent_dev(mdev) to arrive at the parent device outside
+   of the core mdev code)
+
+* device_api
+
+  This attribute should show which device API is being created, for example,
+  "vfio-pci" for a PCI device.
+
+* available_instances
+
+  This attribute should show the number of devices of type <type-id> that can be
+  created.
+
+* [device]
+
+  This directory contains links to the devices of type <type-id> that have been
+created.
+
+* name
+
+  This attribute should show human readable name. This is optional attribute.
+
+* description
+
+  This attribute should show brief features/description of the type. This is
+  optional attribute.
+
+Directories and Files Under the sysfs for Each mdev Device
+----------------------------------------------------------
+
+|- [parent phy device]
+|--- [$MDEV_UUID]
+         |--- remove
+         |--- mdev_type {link to its type}
+         |--- vendor-specific-attributes [optional]
+
+* remove (write only)
+Writing '1' to the 'remove' file destroys the mdev device. The vendor driver can
+fail the remove() callback if that device is active and the vendor driver
+doesn't support hot unplug.
+
+Example:
+	# echo 1 > /sys/bus/mdev/devices/$mdev_UUID/remove
+
+Mediated device Hot plug:
+------------------------
+
+Mediated devices can be created and assigned at runtime. The procedure to hot
+plug a mediated device is the same as the procedure to hot plug a PCI device.
+
+Translation APIs for Mediated Devices
+=====================================
+
+The following APIs are provided for translating user pfn to host pfn in a VFIO
+driver:
+
+extern int vfio_pin_pages(struct device *dev, unsigned long *user_pfn,
+                          int npage, int prot, unsigned long *phys_pfn);
+
+extern int vfio_unpin_pages(struct device *dev, unsigned long *user_pfn,
+                            int npage);
+
+These functions call back into the back-end IOMMU module by using the pin_pages
+and unpin_pages callbacks of the struct vfio_iommu_driver_ops[4]. Currently
+these callbacks are supported in the TYPE1 IOMMU module. To enable them for
+other IOMMU backend modules, such as PPC64 sPAPR module, they need to provide
+these two callback functions.
+
+Using the Sample Code
+=====================
+
+mtty.c in samples/vfio-mdev/ directory is a sample driver program to
+demonstrate how to use the mediated device framework.
+
+The sample driver creates an mdev device that simulates a serial port over a PCI
+card.
+
+1. Build and load the mtty.ko module.
+
+   This step creates a dummy device, /sys/devices/virtual/mtty/mtty/
+
+   Files in this device directory in sysfs are similar to the following:
+
+   # tree /sys/devices/virtual/mtty/mtty/
+      /sys/devices/virtual/mtty/mtty/
+      |-- mdev_supported_types
+      |   |-- mtty-1
+      |   |   |-- available_instances
+      |   |   |-- create
+      |   |   |-- device_api
+      |   |   |-- devices
+      |   |   `-- name
+      |   `-- mtty-2
+      |       |-- available_instances
+      |       |-- create
+      |       |-- device_api
+      |       |-- devices
+      |       `-- name
+      |-- mtty_dev
+      |   `-- sample_mtty_dev
+      |-- power
+      |   |-- autosuspend_delay_ms
+      |   |-- control
+      |   |-- runtime_active_time
+      |   |-- runtime_status
+      |   `-- runtime_suspended_time
+      |-- subsystem -> ../../../../class/mtty
+      `-- uevent
+
+2. Create a mediated device by using the dummy device that you created in the
+   previous step.
+
+   # echo "83b8f4f2-509f-382f-3c1e-e6bfe0fa1001" >	\
+              /sys/devices/virtual/mtty/mtty/mdev_supported_types/mtty-2/create
+
+3. Add parameters to qemu-kvm.
+
+   -device vfio-pci,\
+    sysfsdev=/sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1001
+
+4. Boot the VM.
+
+   In the Linux guest VM, with no hardware on the host, the device appears
+   as  follows:
+
+   # lspci -s 00:05.0 -xxvv
+   00:05.0 Serial controller: Device 4348:3253 (rev 10) (prog-if 02 [16550])
+           Subsystem: Device 4348:3253
+           Physical Slot: 5
+           Control: I/O+ Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr-
+   Stepping- SERR- FastB2B- DisINTx-
+           Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort-
+   <TAbort- <MAbort- >SERR- <PERR- INTx-
+           Interrupt: pin A routed to IRQ 10
+           Region 0: I/O ports at c150 [size=8]
+           Region 1: I/O ports at c158 [size=8]
+           Kernel driver in use: serial
+   00: 48 43 53 32 01 00 00 02 10 02 00 07 00 00 00 00
+   10: 51 c1 00 00 59 c1 00 00 00 00 00 00 00 00 00 00
+   20: 00 00 00 00 00 00 00 00 00 00 00 00 48 43 53 32
+   30: 00 00 00 00 00 00 00 00 00 00 00 00 0a 01 00 00
+
+   In the Linux guest VM, dmesg output for the device is as follows:
+
+   serial 0000:00:05.0: PCI INT A -> Link[LNKA] -> GSI 10 (level, high) -> IRQ
+10
+   0000:00:05.0: ttyS1 at I/O 0xc150 (irq = 10) is a 16550A
+   0000:00:05.0: ttyS2 at I/O 0xc158 (irq = 10) is a 16550A
+
+
+5. In the Linux guest VM, check the serial ports.
+
+   # setserial -g /dev/ttyS*
+   /dev/ttyS0, UART: 16550A, Port: 0x03f8, IRQ: 4
+   /dev/ttyS1, UART: 16550A, Port: 0xc150, IRQ: 10
+   /dev/ttyS2, UART: 16550A, Port: 0xc158, IRQ: 10
+
+6. Using a minicom or any terminal enulation program, open port /dev/ttyS1 or
+   /dev/ttyS2 with hardware flow control disabled.
+
+7. Type data on the minicom terminal or send data to the terminal emulation
+   program and read the data.
+
+   Data is loop backed from hosts mtty driver.
+
+8. Destroy the mediated device that you created.
+
+   # echo 1 > /sys/bus/mdev/devices/83b8f4f2-509f-382f-3c1e-e6bfe0fa1001/remove
+
+References
+==========
+
+[1] See Documentation/vfio.txt for more information on VFIO.
+[2] struct mdev_driver in include/linux/mdev.h
+[3] struct mdev_parent_ops in include/linux/mdev.h
+[4] struct vfio_iommu_driver_ops in include/linux/vfio.h
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/VGA-softcursor.txt linux-libre-4.10-rc8-gnu/Documentation/VGA-softcursor.txt
--- linux-libre-4.9-gnu/Documentation/VGA-softcursor.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/VGA-softcursor.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-Software cursor for VGA    by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
-=======================    and Martin Mares <mj@atrey.karlin.mff.cuni.cz>
-
-   Linux now has some ability to manipulate cursor appearance. Normally, you
-can set the size of hardware cursor (and also work around some ugly bugs in
-those miserable Trident cards--see #define TRIDENT_GLITCH in drivers/video/
-vgacon.c). You can now play a few new tricks:  you can make your cursor look
-like a non-blinking red block, make it inverse background of the character it's
-over or to highlight that character and still choose whether the original
-hardware cursor should remain visible or not.  There may be other things I have
-never thought of.
-
-   The cursor appearance is controlled by a "<ESC>[?1;2;3c" escape sequence
-where 1, 2 and 3 are parameters described below. If you omit any of them,
-they will default to zeroes.
-
-   Parameter 1 specifies cursor size (0=default, 1=invisible, 2=underline, ...,
-8=full block) + 16 if you want the software cursor to be applied + 32 if you
-want to always change the background color + 64 if you dislike having the
-background the same as the foreground.  Highlights are ignored for the last two
-flags.
-
-   The second parameter selects character attribute bits you want to change
-(by simply XORing them with the value of this parameter). On standard VGA,
-the high four bits specify background and the low four the foreground. In both
-groups, low three bits set color (as in normal color codes used by the console)
-and the most significant one turns on highlight (or sometimes blinking--it
-depends on the configuration of your VGA).
-
-   The third parameter consists of character attribute bits you want to set.
-Bit setting takes place before bit toggling, so you can simply clear a bit by 
-including it in both the set mask and the toggle mask.
-
-Examples:
-=========
-
-To get normal blinking underline, use: echo -e '\033[?2c'
-To get blinking block, use:            echo -e '\033[?6c'
-To get red non-blinking block, use:    echo -e '\033[?17;0;64c'
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/virtual/kvm/00-INDEX linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/00-INDEX
--- linux-libre-4.9-gnu/Documentation/virtual/kvm/00-INDEX	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/00-INDEX	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,8 @@ cpuid.txt
 	- KVM-specific cpuid leaves (x86).
 devices/
 	- KVM_CAP_DEVICE_CTRL userspace API.
+halt-polling.txt
+	- notes on halt-polling
 hypercalls.txt
 	- KVM hypercalls.
 locking.txt
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/virtual/kvm/api.txt linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/api.txt
--- linux-libre-4.9-gnu/Documentation/virtual/kvm/api.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/api.txt	2017-02-12 16:03:20.000000000 -0500
@@ -2034,6 +2034,8 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_WORT              | 64
   PPC	| KVM_REG_PPC_SPRG9             | 64
   PPC	| KVM_REG_PPC_DBSR              | 32
+  PPC   | KVM_REG_PPC_TIDR              | 64
+  PPC   | KVM_REG_PPC_PSSCR             | 64
   PPC   | KVM_REG_PPC_TM_GPR0           | 64
           ...
   PPC   | KVM_REG_PPC_TM_GPR31          | 64
@@ -2050,6 +2052,7 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_TM_VSCR           | 32
   PPC   | KVM_REG_PPC_TM_DSCR           | 64
   PPC   | KVM_REG_PPC_TM_TAR            | 64
+  PPC   | KVM_REG_PPC_TM_XER            | 64
         |                               |
   MIPS  | KVM_REG_MIPS_R0               | 64
           ...
@@ -2209,7 +2212,7 @@ after pausing the vcpu, but before it is
 4.71 KVM_SIGNAL_MSI
 
 Capability: KVM_CAP_SIGNAL_MSI
-Architectures: x86 arm64
+Architectures: x86 arm arm64
 Type: vm ioctl
 Parameters: struct kvm_msi (in)
 Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/virtual/kvm/halt-polling.txt linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/halt-polling.txt
--- linux-libre-4.9-gnu/Documentation/virtual/kvm/halt-polling.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/halt-polling.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,127 @@
+The KVM halt polling system
+===========================
+
+The KVM halt polling system provides a feature within KVM whereby the latency
+of a guest can, under some circumstances, be reduced by polling in the host
+for some time period after the guest has elected to no longer run by cedeing.
+That is, when a guest vcpu has ceded, or in the case of powerpc when all of the
+vcpus of a single vcore have ceded, the host kernel polls for wakeup conditions
+before giving up the cpu to the scheduler in order to let something else run.
+
+Polling provides a latency advantage in cases where the guest can be run again
+very quickly by at least saving us a trip through the scheduler, normally on
+the order of a few micro-seconds, although performance benefits are workload
+dependant. In the event that no wakeup source arrives during the polling
+interval or some other task on the runqueue is runnable the scheduler is
+invoked. Thus halt polling is especially useful on workloads with very short
+wakeup periods where the time spent halt polling is minimised and the time
+savings of not invoking the scheduler are distinguishable.
+
+The generic halt polling code is implemented in:
+
+	virt/kvm/kvm_main.c: kvm_vcpu_block()
+
+The powerpc kvm-hv specific case is implemented in:
+
+	arch/powerpc/kvm/book3s_hv.c: kvmppc_vcore_blocked()
+
+Halt Polling Interval
+=====================
+
+The maximum time for which to poll before invoking the scheduler, referred to
+as the halt polling interval, is increased and decreased based on the perceived
+effectiveness of the polling in an attempt to limit pointless polling.
+This value is stored in either the vcpu struct:
+
+	kvm_vcpu->halt_poll_ns
+
+or in the case of powerpc kvm-hv, in the vcore struct:
+
+	kvmppc_vcore->halt_poll_ns
+
+Thus this is a per vcpu (or vcore) value.
+
+During polling if a wakeup source is received within the halt polling interval,
+the interval is left unchanged. In the event that a wakeup source isn't
+received during the polling interval (and thus schedule is invoked) there are
+two options, either the polling interval and total block time[0] were less than
+the global max polling interval (see module params below), or the total block
+time was greater than the global max polling interval.
+
+In the event that both the polling interval and total block time were less than
+the global max polling interval then the polling interval can be increased in
+the hope that next time during the longer polling interval the wake up source
+will be received while the host is polling and the latency benefits will be
+received. The polling interval is grown in the function grow_halt_poll_ns() and
+is multiplied by the module parameter halt_poll_ns_grow.
+
+In the event that the total block time was greater than the global max polling
+interval then the host will never poll for long enough (limited by the global
+max) to wakeup during the polling interval so it may as well be shrunk in order
+to avoid pointless polling. The polling interval is shrunk in the function
+shrink_halt_poll_ns() and is divided by the module parameter
+halt_poll_ns_shrink, or set to 0 iff halt_poll_ns_shrink == 0.
+
+It is worth noting that this adjustment process attempts to hone in on some
+steady state polling interval but will only really do a good job for wakeups
+which come at an approximately constant rate, otherwise there will be constant
+adjustment of the polling interval.
+
+[0] total block time: the time between when the halt polling function is
+		      invoked and a wakeup source received (irrespective of
+		      whether the scheduler is invoked within that function).
+
+Module Parameters
+=================
+
+The kvm module has 3 tuneable module parameters to adjust the global max
+polling interval as well as the rate at which the polling interval is grown and
+shrunk. These variables are defined in include/linux/kvm_host.h and as module
+parameters in virt/kvm/kvm_main.c, or arch/powerpc/kvm/book3s_hv.c in the
+powerpc kvm-hv case.
+
+Module Parameter    |	     Description	      |	     Default Value
+--------------------------------------------------------------------------------
+halt_poll_ns	    | The global max polling interval | KVM_HALT_POLL_NS_DEFAULT
+		    | which defines the ceiling value |
+		    | of the polling interval for     | (per arch value)
+		    | each vcpu. 		      |
+--------------------------------------------------------------------------------
+halt_poll_ns_grow   | The value by which the halt     |	2
+		    | polling interval is multiplied  |
+		    | in the grow_halt_poll_ns()      |
+		    | function.			      |
+--------------------------------------------------------------------------------
+halt_poll_ns_shrink | The value by which the halt     |	0
+		    | polling interval is divided in  |
+		    | the shrink_halt_poll_ns()	      |
+		    | function.			      |
+--------------------------------------------------------------------------------
+
+These module parameters can be set from the debugfs files in:
+
+	/sys/module/kvm/parameters/
+
+Note: that these module parameters are system wide values and are not able to
+      be tuned on a per vm basis.
+
+Further Notes
+=============
+
+- Care should be taken when setting the halt_poll_ns module parameter as a
+large value has the potential to drive the cpu usage to 100% on a machine which
+would be almost entirely idle otherwise. This is because even if a guest has
+wakeups during which very little work is done and which are quite far apart, if
+the period is shorter than the global max polling interval (halt_poll_ns) then
+the host will always poll for the entire block time and thus cpu utilisation
+will go to 100%.
+
+- Halt polling essentially presents a trade off between power usage and latency
+and the module parameters should be used to tune the affinity for this. Idle
+cpu time is essentially converted to host kernel time with the aim of decreasing
+latency when entering the guest.
+
+- Halt polling will only be conducted by the host when no other tasks are
+runnable on that cpu, otherwise the polling will cease immediately and
+schedule will be invoked to allow that other task to run. Thus this doesn't
+allow a guest to denial of service the cpu.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/virtual/kvm/locking.txt linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/locking.txt
--- linux-libre-4.9-gnu/Documentation/virtual/kvm/locking.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/locking.txt	2017-02-12 16:03:20.000000000 -0500
@@ -13,8 +13,12 @@ The acquisition orders for mutexes are a
 - kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
   them together is quite rare.
 
-For spinlocks, kvm_lock is taken outside kvm->mmu_lock.  Everything
-else is a leaf: no other lock is taken inside the critical sections.
+On x86, vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock.
+
+For spinlocks, kvm_lock is taken outside kvm->mmu_lock.
+
+Everything else is a leaf: no other lock is taken inside the critical
+sections.
 
 2: Exception
 ------------
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/virtual/kvm/msr.txt linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/msr.txt
--- linux-libre-4.9-gnu/Documentation/virtual/kvm/msr.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/msr.txt	2017-02-12 16:03:20.000000000 -0500
@@ -208,7 +208,9 @@ MSR_KVM_STEAL_TIME: 0x4b564d03
 		__u64 steal;
 		__u32 version;
 		__u32 flags;
-		__u32 pad[12];
+		__u8  preempted;
+		__u8  u8_pad[3];
+		__u32 pad[11];
 	}
 
 	whose data will be filled in by the hypervisor periodically. Only one
@@ -232,6 +234,11 @@ MSR_KVM_STEAL_TIME: 0x4b564d03
 		nanoseconds. Time during which the vcpu is idle, will not be
 		reported as steal time.
 
+		preempted: indicate the vCPU who owns this struct is running or
+		not. Non-zero values mean the vCPU has been preempted. Zero
+		means the vCPU is not preempted. NOTE, it is always zero if the
+		the hypervisor doesn't support this field.
+
 MSR_KVM_EOI_EN: 0x4b564d04
 	data: Bit 0 is 1 when PV end of interrupt is enabled on the vcpu; 0
 	when disabled.  Bit 1 is reserved and must be zero.  When PV end of
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/virtual/kvm/review-checklist.txt linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/review-checklist.txt
--- linux-libre-4.9-gnu/Documentation/virtual/kvm/review-checklist.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/virtual/kvm/review-checklist.txt	2017-02-12 16:03:20.000000000 -0500
@@ -1,8 +1,8 @@
 Review checklist for kvm patches
 ================================
 
-1.  The patch must follow Documentation/CodingStyle and
-    Documentation/SubmittingPatches.
+1.  The patch must follow Documentation/process/coding-style.rst and
+    Documentation/process/submitting-patches.rst.
 
 2.  Patches should be against kvm.git master branch.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/vm/numa linux-libre-4.10-rc8-gnu/Documentation/vm/numa
--- linux-libre-4.9-gnu/Documentation/vm/numa	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/vm/numa	2017-02-12 16:03:20.000000000 -0500
@@ -82,7 +82,7 @@ such as DMA or DMA32, represent relative
 a default zonelist order based on the sizes of the various zone types relative
 to the total memory of the node and the total memory of the system.  The
 default zonelist order may be overridden using the numa_zonelist_order kernel
-boot parameter or sysctl.  [see Documentation/kernel-parameters.txt and
+boot parameter or sysctl.  [see Documentation/admin-guide/kernel-parameters.rst and
 Documentation/sysctl/vm.txt]
 
 By default, Linux will attempt to satisfy memory allocation requests from the
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/vm/page_frags linux-libre-4.10-rc8-gnu/Documentation/vm/page_frags
--- linux-libre-4.9-gnu/Documentation/vm/page_frags	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/vm/page_frags	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,42 @@
+Page fragments
+--------------
+
+A page fragment is an arbitrary-length arbitrary-offset area of memory
+which resides within a 0 or higher order compound page.  Multiple
+fragments within that page are individually refcounted, in the page's
+reference counter.
+
+The page_frag functions, page_frag_alloc and page_frag_free, provide a
+simple allocation framework for page fragments.  This is used by the
+network stack and network device drivers to provide a backing region of
+memory for use as either an sk_buff->head, or to be used in the "frags"
+portion of skb_shared_info.
+
+In order to make use of the page fragment APIs a backing page fragment
+cache is needed.  This provides a central point for the fragment allocation
+and tracks allows multiple calls to make use of a cached page.  The
+advantage to doing this is that multiple calls to get_page can be avoided
+which can be expensive at allocation time.  However due to the nature of
+this caching it is required that any calls to the cache be protected by
+either a per-cpu limitation, or a per-cpu limitation and forcing interrupts
+to be disabled when executing the fragment allocation.
+
+The network stack uses two separate caches per CPU to handle fragment
+allocation.  The netdev_alloc_cache is used by callers making use of the
+__netdev_alloc_frag and __netdev_alloc_skb calls.  The napi_alloc_cache is
+used by callers of the __napi_alloc_frag and __napi_alloc_skb calls.  The
+main difference between these two calls is the context in which they may be
+called.  The "netdev" prefixed functions are usable in any context as these
+functions will disable interrupts, while the "napi" prefixed functions are
+only usable within the softirq context.
+
+Many network device drivers use a similar methodology for allocating page
+fragments, but the page fragments are cached at the ring or descriptor
+level.  In order to enable these cases it is necessary to provide a generic
+way of tearing down a page cache.  For this reason __page_frag_cache_drain
+was implemented.  It allows for freeing multiple references from a single
+page via a single call.  The advantage to doing this is that it allows for
+cleaning up the multiple references that were added to a page in order to
+avoid calling get_page per allocation.
+
+Alexander Duyck, Nov 29, 2016.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/vm/transhuge.txt linux-libre-4.10-rc8-gnu/Documentation/vm/transhuge.txt
--- linux-libre-4.9-gnu/Documentation/vm/transhuge.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/vm/transhuge.txt	2017-02-12 16:03:20.000000000 -0500
@@ -136,6 +136,11 @@ or enable it back by writing 1:
 echo 0 >/sys/kernel/mm/transparent_hugepage/use_zero_page
 echo 1 >/sys/kernel/mm/transparent_hugepage/use_zero_page
 
+Some userspace (such as a test program, or an optimized memory allocation
+library) may want to know the size (in bytes) of a transparent hugepage:
+
+cat /sys/kernel/mm/transparent_hugepage/hpage_pmd_size
+
 khugepaged will be automatically started when
 transparent_hugepage/enabled is set to "always" or "madvise, and it'll
 be automatically shutdown if it's set to "never".
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/vme_api.txt linux-libre-4.10-rc8-gnu/Documentation/vme_api.txt
--- linux-libre-4.9-gnu/Documentation/vme_api.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/vme_api.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,413 +0,0 @@
-			VME Device Driver API
-			=====================
-
-Driver registration
-===================
-
-As with other subsystems within the Linux kernel, VME device drivers register
-with the VME subsystem, typically called from the devices init routine.  This is
-achieved via a call to the following function:
-
-	int vme_register_driver (struct vme_driver *driver, unsigned int ndevs);
-
-If driver registration is successful this function returns zero, if an error
-occurred a negative error code will be returned.
-
-A pointer to a structure of type 'vme_driver' must be provided to the
-registration function. Along with ndevs, which is the number of devices your
-driver is able to support. The structure is as follows:
-
-	struct vme_driver {
-		struct list_head node;
-		const char *name;
-		int (*match)(struct vme_dev *);
-		int (*probe)(struct vme_dev *);
-		int (*remove)(struct vme_dev *);
-		void (*shutdown)(void);
-		struct device_driver driver;
-		struct list_head devices;
-		unsigned int ndev;
-	};
-
-At the minimum, the '.name', '.match' and '.probe' elements of this structure
-should be correctly set. The '.name' element is a pointer to a string holding
-the device driver's name.
-
-The '.match' function allows control over which VME devices should be registered
-with the driver. The match function should return 1 if a device should be
-probed and 0 otherwise. This example match function (from vme_user.c) limits
-the number of devices probed to one:
-
-	#define USER_BUS_MAX	1
-	...
-	static int vme_user_match(struct vme_dev *vdev)
-	{
-		if (vdev->id.num >= USER_BUS_MAX)
-			return 0;
-		return 1;
-	}
-
-The '.probe' element should contain a pointer to the probe routine. The
-probe routine is passed a 'struct vme_dev' pointer as an argument. The
-'struct vme_dev' structure looks like the following:
-
-	struct vme_dev {
-		int num;
-		struct vme_bridge *bridge;
-		struct device dev;
-		struct list_head drv_list;
-		struct list_head bridge_list;
-	};
-
-Here, the 'num' field refers to the sequential device ID for this specific
-driver. The bridge number (or bus number) can be accessed using
-dev->bridge->num.
-
-A function is also provided to unregister the driver from the VME core and is
-usually called from the device driver's exit routine:
-
-	void vme_unregister_driver (struct vme_driver *driver);
-
-
-Resource management
-===================
-
-Once a driver has registered with the VME core the provided match routine will
-be called the number of times specified during the registration. If a match
-succeeds, a non-zero value should be returned. A zero return value indicates
-failure. For all successful matches, the probe routine of the corresponding
-driver is called. The probe routine is passed a pointer to the devices
-device structure. This pointer should be saved, it will be required for
-requesting VME resources.
-
-The driver can request ownership of one or more master windows, slave windows
-and/or dma channels. Rather than allowing the device driver to request a
-specific window or DMA channel (which may be used by a different driver) this
-driver allows a resource to be assigned based on the required attributes of the
-driver in question:
-
-	struct vme_resource * vme_master_request(struct vme_dev *dev,
-		u32 aspace, u32 cycle, u32 width);
-
-	struct vme_resource * vme_slave_request(struct vme_dev *dev, u32 aspace,
-		u32 cycle);
-
-	struct vme_resource *vme_dma_request(struct vme_dev *dev, u32 route);
-
-For slave windows these attributes are split into the VME address spaces that
-need to be accessed in 'aspace' and VME bus cycle types required in 'cycle'.
-Master windows add a further set of attributes in 'width' specifying the
-required data transfer widths. These attributes are defined as bitmasks and as
-such any combination of the attributes can be requested for a single window,
-the core will assign a window that meets the requirements, returning a pointer
-of type vme_resource that should be used to identify the allocated resource
-when it is used. For DMA controllers, the request function requires the
-potential direction of any transfers to be provided in the route attributes.
-This is typically VME-to-MEM and/or MEM-to-VME, though some hardware can
-support VME-to-VME and MEM-to-MEM transfers as well as test pattern generation.
-If an unallocated window fitting the requirements can not be found a NULL
-pointer will be returned.
-
-Functions are also provided to free window allocations once they are no longer
-required. These functions should be passed the pointer to the resource provided
-during resource allocation:
-
-	void vme_master_free(struct vme_resource *res);
-
-	void vme_slave_free(struct vme_resource *res);
-
-	void vme_dma_free(struct vme_resource *res);
-
-
-Master windows
-==============
-
-Master windows provide access from the local processor[s] out onto the VME bus.
-The number of windows available and the available access modes is dependent on
-the underlying chipset. A window must be configured before it can be used.
-
-
-Master window configuration
----------------------------
-
-Once a master window has been assigned the following functions can be used to
-configure it and retrieve the current settings:
-
-	int vme_master_set (struct vme_resource *res, int enabled,
-		unsigned long long base, unsigned long long size, u32 aspace,
-		u32 cycle, u32 width);
-
-	int vme_master_get (struct vme_resource *res, int *enabled,
-		unsigned long long *base, unsigned long long *size, u32 *aspace,
-		u32 *cycle, u32 *width);
-
-The address spaces, transfer widths and cycle types are the same as described
-under resource management, however some of the options are mutually exclusive.
-For example, only one address space may be specified.
-
-These functions return 0 on success or an error code should the call fail.
-
-
-Master window access
---------------------
-
-The following functions can be used to read from and write to configured master
-windows. These functions return the number of bytes copied:
-
-	ssize_t vme_master_read(struct vme_resource *res, void *buf,
-		size_t count, loff_t offset);
-
-	ssize_t vme_master_write(struct vme_resource *res, void *buf,
-		size_t count, loff_t offset);
-
-In addition to simple reads and writes, a function is provided to do a
-read-modify-write transaction. This function returns the original value of the
-VME bus location :
-
-	unsigned int vme_master_rmw (struct vme_resource *res,
-		unsigned int mask, unsigned int compare, unsigned int swap,
-		loff_t offset);
-
-This functions by reading the offset, applying the mask. If the bits selected in
-the mask match with the values of the corresponding bits in the compare field,
-the value of swap is written the specified offset.
-
-Parts of a VME window can be mapped into user space memory using the following
-function:
-
-	int vme_master_mmap(struct vme_resource *resource,
-		struct vm_area_struct *vma)
-
-
-Slave windows
-=============
-
-Slave windows provide devices on the VME bus access into mapped portions of the
-local memory. The number of windows available and the access modes that can be
-used is dependent on the underlying chipset. A window must be configured before
-it can be used.
-
-
-Slave window configuration
---------------------------
-
-Once a slave window has been assigned the following functions can be used to
-configure it and retrieve the current settings:
-
-	int vme_slave_set (struct vme_resource *res, int enabled,
-		unsigned long long base, unsigned long long size,
-		dma_addr_t mem, u32 aspace, u32 cycle);
-
-	int vme_slave_get (struct vme_resource *res, int *enabled,
-		unsigned long long *base, unsigned long long *size,
-		dma_addr_t *mem, u32 *aspace, u32 *cycle);
-
-The address spaces, transfer widths and cycle types are the same as described
-under resource management, however some of the options are mutually exclusive.
-For example, only one address space may be specified.
-
-These functions return 0 on success or an error code should the call fail.
-
-
-Slave window buffer allocation
-------------------------------
-
-Functions are provided to allow the user to allocate and free a contiguous
-buffers which will be accessible by the VME bridge. These functions do not have
-to be used, other methods can be used to allocate a buffer, though care must be
-taken to ensure that they are contiguous and accessible by the VME bridge:
-
-	void * vme_alloc_consistent(struct vme_resource *res, size_t size,
-		dma_addr_t *mem);
-
-	void vme_free_consistent(struct vme_resource *res, size_t size,
-		void *virt,	dma_addr_t mem);
-
-
-Slave window access
--------------------
-
-Slave windows map local memory onto the VME bus, the standard methods for
-accessing memory should be used.
-
-
-DMA channels
-============
-
-The VME DMA transfer provides the ability to run link-list DMA transfers. The
-API introduces the concept of DMA lists. Each DMA list is a link-list which can
-be passed to a DMA controller. Multiple lists can be created, extended,
-executed, reused and destroyed.
-
-
-List Management
----------------
-
-The following functions are provided to create and destroy DMA lists. Execution
-of a list will not automatically destroy the list, thus enabling a list to be
-reused for repetitive tasks:
-
-	struct vme_dma_list *vme_new_dma_list(struct vme_resource *res);
-
-	int vme_dma_list_free(struct vme_dma_list *list);
-
-
-List Population
----------------
-
-An item can be added to a list using the following function ( the source and
-destination attributes need to be created before calling this function, this is
-covered under "Transfer Attributes"):
-
-	int vme_dma_list_add(struct vme_dma_list *list,
-		struct vme_dma_attr *src, struct vme_dma_attr *dest,
-		size_t count);
-
-NOTE:	The detailed attributes of the transfers source and destination
-	are not checked until an entry is added to a DMA list, the request
-	for a DMA channel purely checks the directions in which the
-	controller is expected to transfer data. As a result it is
-	possible for this call to return an error, for example if the
-	source or destination is in an unsupported VME address space.
-
-Transfer Attributes
--------------------
-
-The attributes for the source and destination are handled separately from adding
-an item to a list. This is due to the diverse attributes required for each type
-of source and destination. There are functions to create attributes for PCI, VME
-and pattern sources and destinations (where appropriate):
-
-Pattern source:
-
-	struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern, u32 type);
-
-PCI source or destination:
-
-	struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t mem);
-
-VME source or destination:
-
-	struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long base,
-		u32 aspace, u32 cycle, u32 width);
-
-The following function should be used to free an attribute:
-
-	void vme_dma_free_attribute(struct vme_dma_attr *attr);
-
-
-List Execution
---------------
-
-The following function queues a list for execution. The function will return
-once the list has been executed:
-
-	int vme_dma_list_exec(struct vme_dma_list *list);
-
-
-Interrupts
-==========
-
-The VME API provides functions to attach and detach callbacks to specific VME
-level and status ID combinations and for the generation of VME interrupts with
-specific VME level and status IDs.
-
-
-Attaching Interrupt Handlers
-----------------------------
-
-The following functions can be used to attach and free a specific VME level and
-status ID combination. Any given combination can only be assigned a single
-callback function. A void pointer parameter is provided, the value of which is
-passed to the callback function, the use of this pointer is user undefined:
-
-	int vme_irq_request(struct vme_dev *dev, int level, int statid,
-		void (*callback)(int, int, void *), void *priv);
-
-	void vme_irq_free(struct vme_dev *dev, int level, int statid);
-
-The callback parameters are as follows. Care must be taken in writing a callback
-function, callback functions run in interrupt context:
-
-	void callback(int level, int statid, void *priv);
-
-
-Interrupt Generation
---------------------
-
-The following function can be used to generate a VME interrupt at a given VME
-level and VME status ID:
-
-	int vme_irq_generate(struct vme_dev *dev, int level, int statid);
-
-
-Location monitors
-=================
-
-The VME API provides the following functionality to configure the location
-monitor.
-
-
-Location Monitor Management
----------------------------
-
-The following functions are provided to request the use of a block of location
-monitors and to free them after they are no longer required:
-
-	struct vme_resource * vme_lm_request(struct vme_dev *dev);
-
-	void vme_lm_free(struct vme_resource * res);
-
-Each block may provide a number of location monitors, monitoring adjacent
-locations. The following function can be used to determine how many locations
-are provided:
-
-	int vme_lm_count(struct vme_resource * res);
-
-
-Location Monitor Configuration
-------------------------------
-
-Once a bank of location monitors has been allocated, the following functions
-are provided to configure the location and mode of the location monitor:
-
-	int vme_lm_set(struct vme_resource *res, unsigned long long base,
-		u32 aspace, u32 cycle);
-
-	int vme_lm_get(struct vme_resource *res, unsigned long long *base,
-		u32 *aspace, u32 *cycle);
-
-
-Location Monitor Use
---------------------
-
-The following functions allow a callback to be attached and detached from each
-location monitor location. Each location monitor can monitor a number of
-adjacent locations:
-
-	int vme_lm_attach(struct vme_resource *res, int num,
-		void (*callback)(void *));
-
-	int vme_lm_detach(struct vme_resource *res, int num);
-
-The callback function is declared as follows.
-
-	void callback(void *data);
-
-
-Slot Detection
-==============
-
-This function returns the slot ID of the provided bridge.
-
-	int vme_slot_num(struct vme_dev *dev);
-
-
-Bus Detection
-=============
-
-This function returns the bus ID of the provided bridge.
-
-	int vme_bus_num(struct vme_dev *dev);
-
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/volatile-considered-harmful.txt linux-libre-4.10-rc8-gnu/Documentation/volatile-considered-harmful.txt
--- linux-libre-4.9-gnu/Documentation/volatile-considered-harmful.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/volatile-considered-harmful.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,119 +0,0 @@
-Why the "volatile" type class should not be used
-------------------------------------------------
-
-C programmers have often taken volatile to mean that the variable could be
-changed outside of the current thread of execution; as a result, they are
-sometimes tempted to use it in kernel code when shared data structures are
-being used.  In other words, they have been known to treat volatile types
-as a sort of easy atomic variable, which they are not.  The use of volatile in
-kernel code is almost never correct; this document describes why.
-
-The key point to understand with regard to volatile is that its purpose is
-to suppress optimization, which is almost never what one really wants to
-do.  In the kernel, one must protect shared data structures against
-unwanted concurrent access, which is very much a different task.  The
-process of protecting against unwanted concurrency will also avoid almost
-all optimization-related problems in a more efficient way.
-
-Like volatile, the kernel primitives which make concurrent access to data
-safe (spinlocks, mutexes, memory barriers, etc.) are designed to prevent
-unwanted optimization.  If they are being used properly, there will be no
-need to use volatile as well.  If volatile is still necessary, there is
-almost certainly a bug in the code somewhere.  In properly-written kernel
-code, volatile can only serve to slow things down.
-
-Consider a typical block of kernel code:
-
-    spin_lock(&the_lock);
-    do_something_on(&shared_data);
-    do_something_else_with(&shared_data);
-    spin_unlock(&the_lock);
-
-If all the code follows the locking rules, the value of shared_data cannot
-change unexpectedly while the_lock is held.  Any other code which might
-want to play with that data will be waiting on the lock.  The spinlock
-primitives act as memory barriers - they are explicitly written to do so -
-meaning that data accesses will not be optimized across them.  So the
-compiler might think it knows what will be in shared_data, but the
-spin_lock() call, since it acts as a memory barrier, will force it to
-forget anything it knows.  There will be no optimization problems with
-accesses to that data.
-
-If shared_data were declared volatile, the locking would still be
-necessary.  But the compiler would also be prevented from optimizing access
-to shared_data _within_ the critical section, when we know that nobody else
-can be working with it.  While the lock is held, shared_data is not
-volatile.  When dealing with shared data, proper locking makes volatile
-unnecessary - and potentially harmful.
-
-The volatile storage class was originally meant for memory-mapped I/O
-registers.  Within the kernel, register accesses, too, should be protected
-by locks, but one also does not want the compiler "optimizing" register
-accesses within a critical section.  But, within the kernel, I/O memory
-accesses are always done through accessor functions; accessing I/O memory
-directly through pointers is frowned upon and does not work on all
-architectures.  Those accessors are written to prevent unwanted
-optimization, so, once again, volatile is unnecessary.
-
-Another situation where one might be tempted to use volatile is
-when the processor is busy-waiting on the value of a variable.  The right
-way to perform a busy wait is:
-
-    while (my_variable != what_i_want)
-        cpu_relax();
-
-The cpu_relax() call can lower CPU power consumption or yield to a
-hyperthreaded twin processor; it also happens to serve as a compiler
-barrier, so, once again, volatile is unnecessary.  Of course, busy-
-waiting is generally an anti-social act to begin with.
-
-There are still a few rare situations where volatile makes sense in the
-kernel:
-
-  - The above-mentioned accessor functions might use volatile on
-    architectures where direct I/O memory access does work.  Essentially,
-    each accessor call becomes a little critical section on its own and
-    ensures that the access happens as expected by the programmer.
-
-  - Inline assembly code which changes memory, but which has no other
-    visible side effects, risks being deleted by GCC.  Adding the volatile
-    keyword to asm statements will prevent this removal.
-
-  - The jiffies variable is special in that it can have a different value
-    every time it is referenced, but it can be read without any special
-    locking.  So jiffies can be volatile, but the addition of other
-    variables of this type is strongly frowned upon.  Jiffies is considered
-    to be a "stupid legacy" issue (Linus's words) in this regard; fixing it
-    would be more trouble than it is worth.
-
-  - Pointers to data structures in coherent memory which might be modified
-    by I/O devices can, sometimes, legitimately be volatile.  A ring buffer
-    used by a network adapter, where that adapter changes pointers to
-    indicate which descriptors have been processed, is an example of this
-    type of situation.
-
-For most code, none of the above justifications for volatile apply.  As a
-result, the use of volatile is likely to be seen as a bug and will bring
-additional scrutiny to the code.  Developers who are tempted to use
-volatile should take a step back and think about what they are truly trying
-to accomplish.
-
-Patches to remove volatile variables are generally welcome - as long as
-they come with a justification which shows that the concurrency issues have
-been properly thought through.
-
-
-NOTES
------
-
-[1] http://lwn.net/Articles/233481/
-[2] http://lwn.net/Articles/233482/
-
-CREDITS
--------
-
-Original impetus and research by Randy Dunlap
-Written by Jonathan Corbet
-Improvements via comments from Satyam Sharma, Johannes Stezenbach, Jesper
-	Juhl, Heikki Orsila, H. Peter Anvin, Philipp Hahn, and Stefan
-	Richter.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt linux-libre-4.10-rc8-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt
--- linux-libre-4.9-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/watchdog/convert_drivers_to_kernel_api.txt	2017-02-12 16:03:20.000000000 -0500
@@ -213,6 +213,6 @@ The entry for the driver now needs to se
 Create a patch and send it to upstream
 --------------------------------------
 
-Make sure you understood Documentation/SubmittingPatches and send your patch to
+Make sure you understood Documentation/process/submitting-patches.rst and send your patch to
 linux-watchdog@vger.kernel.org. We are looking forward to it :)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/watchdog/watchdog-parameters.txt linux-libre-4.10-rc8-gnu/Documentation/watchdog/watchdog-parameters.txt
--- linux-libre-4.9-gnu/Documentation/watchdog/watchdog-parameters.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/watchdog/watchdog-parameters.txt	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@ be listed here unless the driver has its
 file.
 
 
-See Documentation/kernel-parameters.txt for information on
+See Documentation/admin-guide/kernel-parameters.rst for information on
 providing kernel parameters for builtin drivers versus loadable
 modules.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/workqueue.txt linux-libre-4.10-rc8-gnu/Documentation/workqueue.txt
--- linux-libre-4.9-gnu/Documentation/workqueue.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/workqueue.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,388 +0,0 @@
-
-Concurrency Managed Workqueue (cmwq)
-
-September, 2010		Tejun Heo <tj@kernel.org>
-			Florian Mickler <florian@mickler.org>
-
-CONTENTS
-
-1. Introduction
-2. Why cmwq?
-3. The Design
-4. Application Programming Interface (API)
-5. Example Execution Scenarios
-6. Guidelines
-7. Debugging
-
-
-1. Introduction
-
-There are many cases where an asynchronous process execution context
-is needed and the workqueue (wq) API is the most commonly used
-mechanism for such cases.
-
-When such an asynchronous execution context is needed, a work item
-describing which function to execute is put on a queue.  An
-independent thread serves as the asynchronous execution context.  The
-queue is called workqueue and the thread is called worker.
-
-While there are work items on the workqueue the worker executes the
-functions associated with the work items one after the other.  When
-there is no work item left on the workqueue the worker becomes idle.
-When a new work item gets queued, the worker begins executing again.
-
-
-2. Why cmwq?
-
-In the original wq implementation, a multi threaded (MT) wq had one
-worker thread per CPU and a single threaded (ST) wq had one worker
-thread system-wide.  A single MT wq needed to keep around the same
-number of workers as the number of CPUs.  The kernel grew a lot of MT
-wq users over the years and with the number of CPU cores continuously
-rising, some systems saturated the default 32k PID space just booting
-up.
-
-Although MT wq wasted a lot of resource, the level of concurrency
-provided was unsatisfactory.  The limitation was common to both ST and
-MT wq albeit less severe on MT.  Each wq maintained its own separate
-worker pool.  A MT wq could provide only one execution context per CPU
-while a ST wq one for the whole system.  Work items had to compete for
-those very limited execution contexts leading to various problems
-including proneness to deadlocks around the single execution context.
-
-The tension between the provided level of concurrency and resource
-usage also forced its users to make unnecessary tradeoffs like libata
-choosing to use ST wq for polling PIOs and accepting an unnecessary
-limitation that no two polling PIOs can progress at the same time.  As
-MT wq don't provide much better concurrency, users which require
-higher level of concurrency, like async or fscache, had to implement
-their own thread pool.
-
-Concurrency Managed Workqueue (cmwq) is a reimplementation of wq with
-focus on the following goals.
-
-* Maintain compatibility with the original workqueue API.
-
-* Use per-CPU unified worker pools shared by all wq to provide
-  flexible level of concurrency on demand without wasting a lot of
-  resource.
-
-* Automatically regulate worker pool and level of concurrency so that
-  the API users don't need to worry about such details.
-
-
-3. The Design
-
-In order to ease the asynchronous execution of functions a new
-abstraction, the work item, is introduced.
-
-A work item is a simple struct that holds a pointer to the function
-that is to be executed asynchronously.  Whenever a driver or subsystem
-wants a function to be executed asynchronously it has to set up a work
-item pointing to that function and queue that work item on a
-workqueue.
-
-Special purpose threads, called worker threads, execute the functions
-off of the queue, one after the other.  If no work is queued, the
-worker threads become idle.  These worker threads are managed in so
-called worker-pools.
-
-The cmwq design differentiates between the user-facing workqueues that
-subsystems and drivers queue work items on and the backend mechanism
-which manages worker-pools and processes the queued work items.
-
-There are two worker-pools, one for normal work items and the other
-for high priority ones, for each possible CPU and some extra
-worker-pools to serve work items queued on unbound workqueues - the
-number of these backing pools is dynamic.
-
-Subsystems and drivers can create and queue work items through special
-workqueue API functions as they see fit. They can influence some
-aspects of the way the work items are executed by setting flags on the
-workqueue they are putting the work item on. These flags include
-things like CPU locality, concurrency limits, priority and more.  To
-get a detailed overview refer to the API description of
-alloc_workqueue() below.
-
-When a work item is queued to a workqueue, the target worker-pool is
-determined according to the queue parameters and workqueue attributes
-and appended on the shared worklist of the worker-pool.  For example,
-unless specifically overridden, a work item of a bound workqueue will
-be queued on the worklist of either normal or highpri worker-pool that
-is associated to the CPU the issuer is running on.
-
-For any worker pool implementation, managing the concurrency level
-(how many execution contexts are active) is an important issue.  cmwq
-tries to keep the concurrency at a minimal but sufficient level.
-Minimal to save resources and sufficient in that the system is used at
-its full capacity.
-
-Each worker-pool bound to an actual CPU implements concurrency
-management by hooking into the scheduler.  The worker-pool is notified
-whenever an active worker wakes up or sleeps and keeps track of the
-number of the currently runnable workers.  Generally, work items are
-not expected to hog a CPU and consume many cycles.  That means
-maintaining just enough concurrency to prevent work processing from
-stalling should be optimal.  As long as there are one or more runnable
-workers on the CPU, the worker-pool doesn't start execution of a new
-work, but, when the last running worker goes to sleep, it immediately
-schedules a new worker so that the CPU doesn't sit idle while there
-are pending work items.  This allows using a minimal number of workers
-without losing execution bandwidth.
-
-Keeping idle workers around doesn't cost other than the memory space
-for kthreads, so cmwq holds onto idle ones for a while before killing
-them.
-
-For unbound workqueues, the number of backing pools is dynamic.
-Unbound workqueue can be assigned custom attributes using
-apply_workqueue_attrs() and workqueue will automatically create
-backing worker pools matching the attributes.  The responsibility of
-regulating concurrency level is on the users.  There is also a flag to
-mark a bound wq to ignore the concurrency management.  Please refer to
-the API section for details.
-
-Forward progress guarantee relies on that workers can be created when
-more execution contexts are necessary, which in turn is guaranteed
-through the use of rescue workers.  All work items which might be used
-on code paths that handle memory reclaim are required to be queued on
-wq's that have a rescue-worker reserved for execution under memory
-pressure.  Else it is possible that the worker-pool deadlocks waiting
-for execution contexts to free up.
-
-
-4. Application Programming Interface (API)
-
-alloc_workqueue() allocates a wq.  The original create_*workqueue()
-functions are deprecated and scheduled for removal.  alloc_workqueue()
-takes three arguments - @name, @flags and @max_active.  @name is the
-name of the wq and also used as the name of the rescuer thread if
-there is one.
-
-A wq no longer manages execution resources but serves as a domain for
-forward progress guarantee, flush and work item attributes.  @flags
-and @max_active control how work items are assigned execution
-resources, scheduled and executed.
-
-@flags:
-
-  WQ_UNBOUND
-
-	Work items queued to an unbound wq are served by the special
-	worker-pools which host workers which are not bound to any
-	specific CPU.  This makes the wq behave as a simple execution
-	context provider without concurrency management.  The unbound
-	worker-pools try to start execution of work items as soon as
-	possible.  Unbound wq sacrifices locality but is useful for
-	the following cases.
-
-	* Wide fluctuation in the concurrency level requirement is
-	  expected and using bound wq may end up creating large number
-	  of mostly unused workers across different CPUs as the issuer
-	  hops through different CPUs.
-
-	* Long running CPU intensive workloads which can be better
-	  managed by the system scheduler.
-
-  WQ_FREEZABLE
-
-	A freezable wq participates in the freeze phase of the system
-	suspend operations.  Work items on the wq are drained and no
-	new work item starts execution until thawed.
-
-  WQ_MEM_RECLAIM
-
-	All wq which might be used in the memory reclaim paths _MUST_
-	have this flag set.  The wq is guaranteed to have at least one
-	execution context regardless of memory pressure.
-
-  WQ_HIGHPRI
-
-	Work items of a highpri wq are queued to the highpri
-	worker-pool of the target cpu.  Highpri worker-pools are
-	served by worker threads with elevated nice level.
-
-	Note that normal and highpri worker-pools don't interact with
-	each other.  Each maintain its separate pool of workers and
-	implements concurrency management among its workers.
-
-  WQ_CPU_INTENSIVE
-
-	Work items of a CPU intensive wq do not contribute to the
-	concurrency level.  In other words, runnable CPU intensive
-	work items will not prevent other work items in the same
-	worker-pool from starting execution.  This is useful for bound
-	work items which are expected to hog CPU cycles so that their
-	execution is regulated by the system scheduler.
-
-	Although CPU intensive work items don't contribute to the
-	concurrency level, start of their executions is still
-	regulated by the concurrency management and runnable
-	non-CPU-intensive work items can delay execution of CPU
-	intensive work items.
-
-	This flag is meaningless for unbound wq.
-
-Note that the flag WQ_NON_REENTRANT no longer exists as all workqueues
-are now non-reentrant - any work item is guaranteed to be executed by
-at most one worker system-wide at any given time.
-
-@max_active:
-
-@max_active determines the maximum number of execution contexts per
-CPU which can be assigned to the work items of a wq.  For example,
-with @max_active of 16, at most 16 work items of the wq can be
-executing at the same time per CPU.
-
-Currently, for a bound wq, the maximum limit for @max_active is 512
-and the default value used when 0 is specified is 256.  For an unbound
-wq, the limit is higher of 512 and 4 * num_possible_cpus().  These
-values are chosen sufficiently high such that they are not the
-limiting factor while providing protection in runaway cases.
-
-The number of active work items of a wq is usually regulated by the
-users of the wq, more specifically, by how many work items the users
-may queue at the same time.  Unless there is a specific need for
-throttling the number of active work items, specifying '0' is
-recommended.
-
-Some users depend on the strict execution ordering of ST wq.  The
-combination of @max_active of 1 and WQ_UNBOUND is used to achieve this
-behavior.  Work items on such wq are always queued to the unbound
-worker-pools and only one work item can be active at any given time thus
-achieving the same ordering property as ST wq.
-
-
-5. Example Execution Scenarios
-
-The following example execution scenarios try to illustrate how cmwq
-behave under different configurations.
-
- Work items w0, w1, w2 are queued to a bound wq q0 on the same CPU.
- w0 burns CPU for 5ms then sleeps for 10ms then burns CPU for 5ms
- again before finishing.  w1 and w2 burn CPU for 5ms then sleep for
- 10ms.
-
-Ignoring all other tasks, works and processing overhead, and assuming
-simple FIFO scheduling, the following is one highly simplified version
-of possible sequences of events with the original wq.
-
- TIME IN MSECS	EVENT
- 0		w0 starts and burns CPU
- 5		w0 sleeps
- 15		w0 wakes up and burns CPU
- 20		w0 finishes
- 20		w1 starts and burns CPU
- 25		w1 sleeps
- 35		w1 wakes up and finishes
- 35		w2 starts and burns CPU
- 40		w2 sleeps
- 50		w2 wakes up and finishes
-
-And with cmwq with @max_active >= 3,
-
- TIME IN MSECS	EVENT
- 0		w0 starts and burns CPU
- 5		w0 sleeps
- 5		w1 starts and burns CPU
- 10		w1 sleeps
- 10		w2 starts and burns CPU
- 15		w2 sleeps
- 15		w0 wakes up and burns CPU
- 20		w0 finishes
- 20		w1 wakes up and finishes
- 25		w2 wakes up and finishes
-
-If @max_active == 2,
-
- TIME IN MSECS	EVENT
- 0		w0 starts and burns CPU
- 5		w0 sleeps
- 5		w1 starts and burns CPU
- 10		w1 sleeps
- 15		w0 wakes up and burns CPU
- 20		w0 finishes
- 20		w1 wakes up and finishes
- 20		w2 starts and burns CPU
- 25		w2 sleeps
- 35		w2 wakes up and finishes
-
-Now, let's assume w1 and w2 are queued to a different wq q1 which has
-WQ_CPU_INTENSIVE set,
-
- TIME IN MSECS	EVENT
- 0		w0 starts and burns CPU
- 5		w0 sleeps
- 5		w1 and w2 start and burn CPU
- 10		w1 sleeps
- 15		w2 sleeps
- 15		w0 wakes up and burns CPU
- 20		w0 finishes
- 20		w1 wakes up and finishes
- 25		w2 wakes up and finishes
-
-
-6. Guidelines
-
-* Do not forget to use WQ_MEM_RECLAIM if a wq may process work items
-  which are used during memory reclaim.  Each wq with WQ_MEM_RECLAIM
-  set has an execution context reserved for it.  If there is
-  dependency among multiple work items used during memory reclaim,
-  they should be queued to separate wq each with WQ_MEM_RECLAIM.
-
-* Unless strict ordering is required, there is no need to use ST wq.
-
-* Unless there is a specific need, using 0 for @max_active is
-  recommended.  In most use cases, concurrency level usually stays
-  well under the default limit.
-
-* A wq serves as a domain for forward progress guarantee
-  (WQ_MEM_RECLAIM, flush and work item attributes.  Work items which
-  are not involved in memory reclaim and don't need to be flushed as a
-  part of a group of work items, and don't require any special
-  attribute, can use one of the system wq.  There is no difference in
-  execution characteristics between using a dedicated wq and a system
-  wq.
-
-* Unless work items are expected to consume a huge amount of CPU
-  cycles, using a bound wq is usually beneficial due to the increased
-  level of locality in wq operations and work item execution.
-
-
-7. Debugging
-
-Because the work functions are executed by generic worker threads
-there are a few tricks needed to shed some light on misbehaving
-workqueue users.
-
-Worker threads show up in the process list as:
-
-root      5671  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/0:1]
-root      5672  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/1:2]
-root      5673  0.0  0.0      0     0 ?        S    12:12   0:00 [kworker/0:0]
-root      5674  0.0  0.0      0     0 ?        S    12:13   0:00 [kworker/1:0]
-
-If kworkers are going crazy (using too much cpu), there are two types
-of possible problems:
-
-	1. Something being scheduled in rapid succession
-	2. A single work item that consumes lots of cpu cycles
-
-The first one can be tracked using tracing:
-
-	$ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event
-	$ cat /sys/kernel/debug/tracing/trace_pipe > out.txt
-	(wait a few secs)
-	^C
-
-If something is busy looping on work queueing, it would be dominating
-the output and the offender can be determined with the work item
-function.
-
-For the second type of problems it should be possible to just check
-the stack trace of the offending worker thread.
-
-	$ cat /proc/THE_OFFENDING_KWORKER/stack
-
-The work item's function should be trivially visible in the stack
-trace.
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/x86/boot.txt linux-libre-4.10-rc8-gnu/Documentation/x86/boot.txt
--- linux-libre-4.9-gnu/Documentation/x86/boot.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/x86/boot.txt	2017-02-12 16:03:20.000000000 -0500
@@ -921,7 +921,7 @@ They should normally not be deleted from
 though not all of them are actually meaningful to the kernel.  Boot
 loader authors who need additional command line options for the boot
 loader itself should get them registered in
-Documentation/kernel-parameters.txt to make sure they will not
+Documentation/admin-guide/kernel-parameters.rst to make sure they will not
 conflict with actual kernel options now or in the future.
 
   vga=<mode>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/x86/intel_rdt_ui.txt linux-libre-4.10-rc8-gnu/Documentation/x86/intel_rdt_ui.txt
--- linux-libre-4.9-gnu/Documentation/x86/intel_rdt_ui.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/x86/intel_rdt_ui.txt	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,214 @@
+User Interface for Resource Allocation in Intel Resource Director Technology
+
+Copyright (C) 2016 Intel Corporation
+
+Fenghua Yu <fenghua.yu@intel.com>
+Tony Luck <tony.luck@intel.com>
+
+This feature is enabled by the CONFIG_INTEL_RDT_A Kconfig and the
+X86 /proc/cpuinfo flag bits "rdt", "cat_l3" and "cdp_l3".
+
+To use the feature mount the file system:
+
+ # mount -t resctrl resctrl [-o cdp] /sys/fs/resctrl
+
+mount options are:
+
+"cdp": Enable code/data prioritization in L3 cache allocations.
+
+
+Info directory
+--------------
+
+The 'info' directory contains information about the enabled
+resources. Each resource has its own subdirectory. The subdirectory
+names reflect the resource names. Each subdirectory contains the
+following files:
+
+"num_closids":  The number of CLOSIDs which are valid for this
+	        resource. The kernel uses the smallest number of
+		CLOSIDs of all enabled resources as limit.
+
+"cbm_mask":     The bitmask which is valid for this resource. This
+		mask is equivalent to 100%.
+
+"min_cbm_bits": The minimum number of consecutive bits which must be
+		set when writing a mask.
+
+
+Resource groups
+---------------
+Resource groups are represented as directories in the resctrl file
+system. The default group is the root directory. Other groups may be
+created as desired by the system administrator using the "mkdir(1)"
+command, and removed using "rmdir(1)".
+
+There are three files associated with each group:
+
+"tasks": A list of tasks that belongs to this group. Tasks can be
+	added to a group by writing the task ID to the "tasks" file
+	(which will automatically remove them from the previous
+	group to which they belonged). New tasks created by fork(2)
+	and clone(2) are added to the same group as their parent.
+	If a pid is not in any sub partition, it is in root partition
+	(i.e. default partition).
+
+"cpus": A bitmask of logical CPUs assigned to this group. Writing
+	a new mask can add/remove CPUs from this group. Added CPUs
+	are removed from their previous group. Removed ones are
+	given to the default (root) group. You cannot remove CPUs
+	from the default group.
+
+"schemata": A list of all the resources available to this group.
+	Each resource has its own line and format - see below for
+	details.
+
+When a task is running the following rules define which resources
+are available to it:
+
+1) If the task is a member of a non-default group, then the schemata
+for that group is used.
+
+2) Else if the task belongs to the default group, but is running on a
+CPU that is assigned to some specific group, then the schemata for
+the CPU's group is used.
+
+3) Otherwise the schemata for the default group is used.
+
+
+Schemata files - general concepts
+---------------------------------
+Each line in the file describes one resource. The line starts with
+the name of the resource, followed by specific values to be applied
+in each of the instances of that resource on the system.
+
+Cache IDs
+---------
+On current generation systems there is one L3 cache per socket and L2
+caches are generally just shared by the hyperthreads on a core, but this
+isn't an architectural requirement. We could have multiple separate L3
+caches on a socket, multiple cores could share an L2 cache. So instead
+of using "socket" or "core" to define the set of logical cpus sharing
+a resource we use a "Cache ID". At a given cache level this will be a
+unique number across the whole system (but it isn't guaranteed to be a
+contiguous sequence, there may be gaps).  To find the ID for each logical
+CPU look in /sys/devices/system/cpu/cpu*/cache/index*/id
+
+Cache Bit Masks (CBM)
+---------------------
+For cache resources we describe the portion of the cache that is available
+for allocation using a bitmask. The maximum value of the mask is defined
+by each cpu model (and may be different for different cache levels). It
+is found using CPUID, but is also provided in the "info" directory of
+the resctrl file system in "info/{resource}/cbm_mask". X86 hardware
+requires that these masks have all the '1' bits in a contiguous block. So
+0x3, 0x6 and 0xC are legal 4-bit masks with two bits set, but 0x5, 0x9
+and 0xA are not.  On a system with a 20-bit mask each bit represents 5%
+of the capacity of the cache. You could partition the cache into four
+equal parts with masks: 0x1f, 0x3e0, 0x7c00, 0xf8000.
+
+
+L3 details (code and data prioritization disabled)
+--------------------------------------------------
+With CDP disabled the L3 schemata format is:
+
+	L3:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+L3 details (CDP enabled via mount option to resctrl)
+----------------------------------------------------
+When CDP is enabled L3 control is split into two separate resources
+so you can specify independent masks for code and data like this:
+
+	L3data:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+	L3code:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+L2 details
+----------
+L2 cache does not support code and data prioritization, so the
+schemata format is always:
+
+	L2:<cache_id0>=<cbm>;<cache_id1>=<cbm>;...
+
+Example 1
+---------
+On a two socket machine (one L3 cache per socket) with just four bits
+for cache bit masks
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+# mkdir p0 p1
+# echo "L3:0=3;1=c" > /sys/fs/resctrl/p0/schemata
+# echo "L3:0=3;1=3" > /sys/fs/resctrl/p1/schemata
+
+The default resource group is unmodified, so we have access to all parts
+of all caches (its schemata file reads "L3:0=f;1=f").
+
+Tasks that are under the control of group "p0" may only allocate from the
+"lower" 50% on cache ID 0, and the "upper" 50% of cache ID 1.
+Tasks in group "p1" use the "lower" 50% of cache on both sockets.
+
+Example 2
+---------
+Again two sockets, but this time with a more realistic 20-bit mask.
+
+Two real time tasks pid=1234 running on processor 0 and pid=5678 running on
+processor 1 on socket 0 on a 2-socket and dual core machine. To avoid noisy
+neighbors, each of the two real-time tasks exclusively occupies one quarter
+of L3 cache on socket 0.
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+
+First we reset the schemata for the default group so that the "upper"
+50% of the L3 cache on socket 0 cannot be used by ordinary tasks:
+
+# echo "L3:0=3ff;1=fffff" > schemata
+
+Next we make a resource group for our first real time task and give
+it access to the "top" 25% of the cache on socket 0.
+
+# mkdir p0
+# echo "L3:0=f8000;1=fffff" > p0/schemata
+
+Finally we move our first real time task into this resource group. We
+also use taskset(1) to ensure the task always runs on a dedicated CPU
+on socket 0. Most uses of resource groups will also constrain which
+processors tasks run on.
+
+# echo 1234 > p0/tasks
+# taskset -cp 1 1234
+
+Ditto for the second real time task (with the remaining 25% of cache):
+
+# mkdir p1
+# echo "L3:0=7c00;1=fffff" > p1/schemata
+# echo 5678 > p1/tasks
+# taskset -cp 2 5678
+
+Example 3
+---------
+
+A single socket system which has real-time tasks running on core 4-7 and
+non real-time workload assigned to core 0-3. The real-time tasks share text
+and data, so a per task association is not required and due to interaction
+with the kernel it's desired that the kernel on these cores shares L3 with
+the tasks.
+
+# mount -t resctrl resctrl /sys/fs/resctrl
+# cd /sys/fs/resctrl
+
+First we reset the schemata for the default group so that the "upper"
+50% of the L3 cache on socket 0 cannot be used by ordinary tasks:
+
+# echo "L3:0=3ff" > schemata
+
+Next we make a resource group for our real time cores and give
+it access to the "top" 50% of the cache on socket 0.
+
+# mkdir p0
+# echo "L3:0=ffc00;" > p0/schemata
+
+Finally we move core 4-7 over to the new group and make sure that the
+kernel and the tasks running there get 50% of the cache.
+
+# echo C0 > p0/cpus
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/x86/topology.txt linux-libre-4.10-rc8-gnu/Documentation/x86/topology.txt
--- linux-libre-4.9-gnu/Documentation/x86/topology.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/x86/topology.txt	2017-02-12 16:03:20.000000000 -0500
@@ -63,6 +63,15 @@ The topology of a system is described in
     The maximum possible number of packages in the system. Helpful for per
     package facilities to preallocate per package information.
 
+  - cpu_llc_id:
+
+    A per-CPU variable containing:
+    - On Intel, the first APIC ID of the list of CPUs sharing the Last Level
+    Cache
+
+    - On AMD, the Node ID or Core Complex ID containing the Last Level
+    Cache. In general, it is a number identifying an LLC uniquely on the
+    system.
 
 * Cores:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/x86/x86_64/boot-options.txt linux-libre-4.10-rc8-gnu/Documentation/x86/x86_64/boot-options.txt
--- linux-libre-4.9-gnu/Documentation/x86/x86_64/boot-options.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/x86/x86_64/boot-options.txt	2017-02-12 16:03:20.000000000 -0500
@@ -277,10 +277,6 @@ IOMMU (input/output memory management un
     space might stop working. Use this option if you have devices that
     are accessed from userspace directly on some PCI host bridge.
 
-Debugging
-
-  kstack=N	Print N words from the kernel stack in oops dumps.
-
 Miscellaneous
 
 	nogbpages
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/arm/Booting linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm/Booting
--- linux-libre-4.9-gnu/Documentation/zh_CN/arm/Booting	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm/Booting	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-Chinese translated version of Documentation/arm/Booting
-
-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.
-
-Maintainer: Russell King <linux@arm.linux.org.uk>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/arm/Booting 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-英文版维护者： Russell King <linux@arm.linux.org.uk>
-中文版维护者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
-中文版校译者： 傅炜  Fu Wei <tekkamanninja@gmail.com>
-
-以下为正文
----------------------------------------------------------------------
-
-			启动 ARM Linux
-			==============
-
-作者：Russell King
-日期：2002年5月18日
-
-以下文档适用于 2.4.18-rmk6 及以上版本。
-
-为了启动 ARM Linux，你需要一个引导装载程序（boot loader），
-它是一个在主内核启动前运行的一个小程序。引导装载程序需要初始化各种
-设备，并最终调用 Linux 内核，将信息传递给内核。
-
-从本质上讲，引导装载程序应提供（至少）以下功能：
-
-1、设置和初始化 RAM。
-2、初始化一个串口。
-3、检测机器的类型（machine type）。
-4、设置内核标签列表（tagged list）。
-5、调用内核映像。
-
-
-1、设置和初始化 RAM
--------------------
-
-现有的引导加载程序:		强制
-新开发的引导加载程序:		强制
-
-引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
-这个操作的执行是设备依赖的。（它可能使用内部算法来自动定位和计算所有
-RAM，或可能使用对这个设备已知的 RAM 信息，还可能使用任何引导装载程序
-设计者想到的匹配方法。）
-
-
-2、初始化一个串口
------------------------------
-
-现有的引导加载程序:		可选、建议
-新开发的引导加载程序:		可选、建议
-
-引导加载程序应该初始化并使能一个目标板上的串口。这允许内核串口驱动
-自动检测哪个串口用于内核控制台。(一般用于调试或与目标板通信。)
-
-作为替代方案，引导加载程序也可以通过标签列表传递相关的'console='
-选项给内核以指定某个串口，而串口数据格式的选项在以下文档中描述：
-
-       Documentation/kernel-parameters.txt。
-
-
-3、检测机器类型
---------------------------
-
-现有的引导加载程序:		可选
-新开发的引导加载程序:		强制
-
-引导加载程序应该通过某些方式检测自身所处的机器类型。这是一个硬件
-代码或通过查看所连接的硬件用某些算法得到，这些超出了本文档的范围。
-引导加载程序最终必须能提供一个 MACH_TYPE_xxx 值给内核。
-(详见 linux/arch/arm/tools/mach-types )。
-
-4、设置启动数据
-------------------
-
-现有的引导加载程序:		可选、强烈建议
-新开发的引导加载程序:		强制
-
-引导加载程序必须提供标签列表或者 dtb 映像以传递配置数据给内核。启动
-数据的物理地址通过寄存器 r2 传递给内核。
-
-4a、设置内核标签列表
---------------------------------
-
-bootloader 必须创建和初始化内核标签列表。一个有效的标签列表以
-ATAG_CORE 标签开始，并以 ATAG_NONE 标签结束。ATAG_CORE 标签可以是
-空的，也可以是非空。一个空 ATAG_CORE 标签其 size 域设置为
-‘2’(0x00000002)。ATAG_NONE 标签的 size 域必须设置为零。
-
-在列表中可以保存任意数量的标签。对于一个重复的标签是追加到之前标签
-所携带的信息之后，还是会覆盖原来的信息，是未定义的。某些标签的行为
-是前者，其他是后者。
-
-bootloader 必须传递一个系统内存的位置和最小值，以及根文件系统位置。
-因此，最小的标签列表如下所示：
-
-		+-----------+
-基地址 ->	| ATAG_CORE |  |
-		+-----------+  |
-		| ATAG_MEM  |  | 地址增长方向
-		+-----------+  |
-		| ATAG_NONE |  |
-		+-----------+  v
-
-标签列表应该保存在系统的 RAM 中。
-
-标签列表必须置于内核自解压和 initrd'bootp' 程序都不会覆盖的内存区。
-建议放在 RAM 的头 16KiB 中。
-
-4b、设置设备树
--------------------------
-
-bootloader 必须以 64bit 地址对齐的形式加载一个设备树映像(dtb)到系统
-RAM 中，并用启动数据初始化它。dtb 格式在文档
-Documentation/devicetree/booting-without-of.txt 中。内核将会在
-dtb 物理地址处查找 dtb 魔数值（0xd00dfeed），以确定 dtb 是否已经代替
-标签列表被传递进来。
-
-bootloader 必须传递一个系统内存的位置和最小值，以及根文件系统位置。
-dtb 必须置于内核自解压不会覆盖的内存区。建议将其放置于 RAM 的头 16KiB
-中。但是不可将其放置于“0”物理地址处，因为内核认为：r2 中为 0，意味着
-没有标签列表和 dtb 传递过来。
-
-5、调用内核映像
----------------------------
-
-现有的引导加载程序:		强制
-新开发的引导加载程序:		强制
-
-调用内核映像 zImage 有两个选择。如果 zImge 保存在 flash 中，且是为了
-在 flash 中直接运行而被正确链接的。这样引导加载程序就可以在 flash 中
-直接调用 zImage。
-
-zImage 也可以被放在系统 RAM（任意位置）中被调用。注意：内核使用映像
-基地址的前 16KB RAM 空间来保存页表。建议将映像置于 RAM 的 32KB 处。
-
-对于以上任意一种情况，都必须符合以下启动状态：
-
-- 停止所有 DMA 设备，这样内存数据就不会因为虚假网络包或磁盘数据而被破坏。
-  这可能可以节省你许多的调试时间。
-
-- CPU 寄存器配置
-  r0 = 0，
-  r1 = （在上面 3 中获取的）机器类型码。
-  r2 = 标签列表在系统 RAM 中的物理地址，或
-       设备树块(dtb)在系统 RAM 中的物理地址
-
-- CPU 模式
-  所有形式的中断必须被禁止 (IRQs 和 FIQs)
-  CPU 必须处于 SVC 模式。(对于 Angel 调试有特例存在)
-
-- 缓存，MMUs
-  MMU 必须关闭。
-  指令缓存开启或关闭都可以。
-  数据缓存必须关闭。
-
-- 引导加载程序应该通过直接跳转到内核映像的第一条指令来调用内核映像。
-
-  对于支持 ARM 指令集的 CPU，跳入内核入口时必须处在 ARM 状态，即使
-  对于 Thumb-2 内核也是如此。
-
-  对于仅支持 Thumb 指令集的 CPU，比如 Cortex-M 系列的 CPU，跳入
-  内核入口时必须处于 Thumb 状态。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/arm/kernel_user_helpers.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm/kernel_user_helpers.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/arm/kernel_user_helpers.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm/kernel_user_helpers.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,284 +0,0 @@
-Chinese translated version of Documentation/arm/kernel_user_helpers.txt
-
-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.
-
-Maintainer: Nicolas Pitre <nicolas.pitre@linaro.org>
-		Dave Martin <dave.martin@linaro.org>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/arm/kernel_user_helpers.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-英文版维护者： Nicolas Pitre <nicolas.pitre@linaro.org>
-		Dave Martin <dave.martin@linaro.org>
-中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者： 宋冬生 Dongsheng Song <dongshneg.song@gmail.com>
-		傅炜 Fu Wei <tekkamanninja@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-内核提供的用户空间辅助代码
-=========================
-
-在内核内存空间的固定地址处，有一个由内核提供并可从用户空间访问的代码
-段。它用于向用户空间提供因在许多 ARM CPU 中未实现的特性和/或指令而需
-内核提供帮助的某些操作。这些代码直接在用户模式下执行的想法是为了获得
-最佳效率，但那些与内核计数器联系过于紧密的部分，则被留给了用户库实现。
-事实上，此代码甚至可能因不同的 CPU 而异，这取决于其可用的指令集或它
-是否为 SMP 系统。换句话说，内核保留在不作出警告的情况下根据需要更改
-这些代码的权利。只有本文档描述的入口及其结果是保证稳定的。
-
-这与完全成熟的 VDSO 实现不同（但两者并不冲突），尽管如此，VDSO 可阻止
-某些通过常量高效跳转到那些代码段的汇编技巧。且由于那些代码段在返回用户
-代码前仅使用少量的代码周期，则一个 VDSO 间接远程调用将会在这些简单的
-操作上增加一个可测量的开销。
-
-在对那些拥有原生支持的新型处理器进行代码优化时，仅在已为其他操作使用
-了类似的新增指令，而导致二进制结果已与早期 ARM 处理器不兼容的情况下，
-用户空间才应绕过这些辅助代码，并在内联函数中实现这些操作（无论是通过
-编译器在代码中直接放置，还是作为库函数调用实现的一部分）。也就是说，
-如果你编译的代码不会为了其他目的使用新指令，则不要仅为了避免使用这些
-内核辅助代码，导致二进制程序无法在早期处理器上运行。
-
-新的辅助代码可能随着时间的推移而增加，所以新内核中的某些辅助代码在旧
-内核中可能不存在。因此，程序必须在对任何辅助代码调用假设是安全之前，
-检测 __kuser_helper_version 的值（见下文）。理想情况下，这种检测应该
-只在进程启动时执行一次；如果内核版本不支持所需辅助代码，则该进程可尽早
-中止执行。
-
-kuser_helper_version
---------------------
-
-位置:	0xffff0ffc
-
-参考声明:
-
-  extern int32_t __kuser_helper_version;
-
-定义:
-
-  这个区域包含了当前运行内核实现的辅助代码版本号。用户空间可以通过读
-  取此版本号以确定特定的辅助代码是否存在。
-
-使用范例:
-
-#define __kuser_helper_version (*(int32_t *)0xffff0ffc)
-
-void check_kuser_version(void)
-{
-	if (__kuser_helper_version < 2) {
-		fprintf(stderr, "can't do atomic operations, kernel too old\n");
-		abort();
-	}
-}
-
-注意:
-
-  用户空间可以假设这个域的值不会在任何单个进程的生存期内改变。也就
-  是说，这个域可以仅在库的初始化阶段或进程启动阶段读取一次。
-
-kuser_get_tls
--------------
-
-位置:	0xffff0fe0
-
-参考原型:
-
-  void * __kuser_get_tls(void);
-
-输入:
-
-  lr = 返回地址
-
-输出:
-
-  r0 = TLS 值
-
-被篡改的寄存器:
-
-  无
-
-定义:
-
-  获取之前通过 __ARM_NR_set_tls 系统调用设置的 TLS 值。
-
-使用范例:
-
-typedef void * (__kuser_get_tls_t)(void);
-#define __kuser_get_tls (*(__kuser_get_tls_t *)0xffff0fe0)
-
-void foo()
-{
-	void *tls = __kuser_get_tls();
-	printf("TLS = %p\n", tls);
-}
-
-注意:
-
-  - 仅在 __kuser_helper_version >= 1 时，此辅助代码存在
-    （从内核版本 2.6.12 开始）。
-
-kuser_cmpxchg
--------------
-
-位置:	0xffff0fc0
-
-参考原型:
-
-  int __kuser_cmpxchg(int32_t oldval, int32_t newval, volatile int32_t *ptr);
-
-输入:
-
-  r0 = oldval
-  r1 = newval
-  r2 = ptr
-  lr = 返回地址
-
-输出:
-
-  r0 = 成功代码 (零或非零)
-  C flag = 如果 r0 == 0 则置 1，如果 r0 != 0 则清零。
-
-被篡改的寄存器:
-
-  r3, ip, flags
-
-定义:
-
-  仅在 *ptr 为 oldval 时原子保存 newval 于 *ptr 中。
-  如果 *ptr 被改变，则返回值为零，否则为非零值。
-  如果 *ptr 被改变，则 C flag 也会被置 1，以实现调用代码中的汇编
-  优化。
-
-使用范例:
-
-typedef int (__kuser_cmpxchg_t)(int oldval, int newval, volatile int *ptr);
-#define __kuser_cmpxchg (*(__kuser_cmpxchg_t *)0xffff0fc0)
-
-int atomic_add(volatile int *ptr, int val)
-{
-	int old, new;
-
-	do {
-		old = *ptr;
-		new = old + val;
-	} while(__kuser_cmpxchg(old, new, ptr));
-
-	return new;
-}
-
-注意:
-
-  - 这个例程已根据需要包含了内存屏障。
-
-  - 仅在 __kuser_helper_version >= 2 时，此辅助代码存在
-    （从内核版本 2.6.12 开始）。
-
-kuser_memory_barrier
---------------------
-
-位置:	0xffff0fa0
-
-参考原型:
-
-  void __kuser_memory_barrier(void);
-
-输入:
-
-  lr = 返回地址
-
-输出:
-
-  无
-
-被篡改的寄存器:
-
-  无
-
-定义:
-
-  应用于任何需要内存屏障以防止手动数据修改带来的一致性问题，以及
-  __kuser_cmpxchg 中。
-
-使用范例:
-
-typedef void (__kuser_dmb_t)(void);
-#define __kuser_dmb (*(__kuser_dmb_t *)0xffff0fa0)
-
-注意:
-
-  - 仅在 __kuser_helper_version >= 3 时，此辅助代码存在
-    （从内核版本 2.6.15 开始）。
-
-kuser_cmpxchg64
----------------
-
-位置:	0xffff0f60
-
-参考原型:
-
-  int __kuser_cmpxchg64(const int64_t *oldval,
-                        const int64_t *newval,
-                        volatile int64_t *ptr);
-
-输入:
-
-  r0 = 指向 oldval
-  r1 = 指向 newval
-  r2 = 指向目标值
-  lr = 返回地址
-
-输出:
-
-  r0 = 成功代码 (零或非零)
-  C flag = 如果 r0 == 0 则置 1，如果 r0 != 0 则清零。
-
-被篡改的寄存器:
-
-  r3, lr, flags
-
-定义:
-
-  仅在 *ptr 等于 *oldval 指向的 64 位值时，原子保存 *newval
-  指向的 64 位值于 *ptr 中。如果 *ptr 被改变，则返回值为零，
-  否则为非零值。
-
-  如果 *ptr 被改变，则 C flag 也会被置 1，以实现调用代码中的汇编
-  优化。
-
-使用范例:
-
-typedef int (__kuser_cmpxchg64_t)(const int64_t *oldval,
-                                  const int64_t *newval,
-                                  volatile int64_t *ptr);
-#define __kuser_cmpxchg64 (*(__kuser_cmpxchg64_t *)0xffff0f60)
-
-int64_t atomic_add64(volatile int64_t *ptr, int64_t val)
-{
-	int64_t old, new;
-
-	do {
-		old = *ptr;
-		new = old + val;
-	} while(__kuser_cmpxchg64(&old, &new, ptr));
-
-	return new;
-}
-
-注意:
-
-  - 这个例程已根据需要包含了内存屏障。
-
-  - 由于这个过程的代码长度（此辅助代码跨越 2 个常规的 kuser “槽”），
-    因此 0xffff0f80 不被作为有效的入口点。
-
-  - 仅在 __kuser_helper_version >= 5 时，此辅助代码存在
-    （从内核版本 3.1 开始）。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/arm64/booting.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/booting.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/arm64/booting.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/booting.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-Chinese translated version of Documentation/arm64/booting.txt
-
-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.
-
-M:	Will Deacon <will.deacon@arm.com>
-zh_CN:	Fu Wei <wefu@redhat.com>
-C:	55f058e7574c3615dea4615573a19bdb258696c6
----------------------------------------------------------------------
-Documentation/arm64/booting.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-英文版维护者： Will Deacon <will.deacon@arm.com>
-中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
-本文翻译提交时的 Git 检出点为： 55f058e7574c3615dea4615573a19bdb258696c6
-
-以下为正文
----------------------------------------------------------------------
-			启动 AArch64 Linux
-			==================
-
-作者: Will Deacon <will.deacon@arm.com>
-日期: 2012 年 09 月 07 日
-
-本文档基于 Russell King 的 ARM 启动文档，且适用于所有公开发布的
-AArch64 Linux 内核代码。
-
-AArch64 异常模型由多个异常级（EL0 - EL3）组成，对于 EL0 和 EL1 异常级
-有对应的安全和非安全模式。EL2 是系统管理级，且仅存在于非安全模式下。
-EL3 是最高特权级，且仅存在于安全模式下。
-
-基于本文档的目的，我们将简单地使用‘引导装载程序’（‘boot loader’）
-这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。
-这可能包含安全监控和系统管理代码，或者它可能只是一些用于准备最小启动
-环境的指令。
-
-基本上，引导装载程序（至少）应实现以下操作：
-
-1、设置和初始化 RAM
-2、设置设备树数据
-3、解压内核映像
-4、调用内核映像
-
-
-1、设置和初始化 RAM
------------------
-
-必要性: 强制
-
-引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
-这个操作的执行方式因设备而异。（它可能使用内部算法来自动定位和计算所有
-RAM，或可能使用对这个设备已知的 RAM 信息，还可能是引导装载程序设计者
-想到的任何合适的方法。）
-
-
-2、设置设备树数据
----------------
-
-必要性: 强制
-
-设备树数据块（dtb）必须 8 字节对齐，且大小不能超过 2MB。由于设备树
-数据块将在使能缓存的情况下以 2MB 粒度被映射，故其不能被置于带任意
-特定属性被映射的 2MB 区域内。
-
-注： v4.2 之前的版本同时要求设备树数据块被置于从内核映像以下
-text_offset 字节处算起第一个 512MB 内。
-
-3、解压内核映像
--------------
-
-必要性: 可选
-
-AArch64 内核当前没有提供自解压代码，因此如果使用了压缩内核映像文件
-（比如 Image.gz），则需要通过引导装载程序（使用 gzip 等）来进行解压。
-若引导装载程序没有实现这个功能，就要使用非压缩内核映像文件。
-
-
-4、调用内核映像
--------------
-
-必要性: 强制
-
-已解压的内核映像包含一个 64 字节的头，内容如下：
-
-  u32 code0;			/* 可执行代码 */
-  u32 code1;			/* 可执行代码 */
-  u64 text_offset;		/* 映像装载偏移，小端模式 */
-  u64 image_size;		/* 映像实际大小, 小端模式 */
-  u64 flags;			/* 内核旗标, 小端模式 *
-  u64 res2	= 0;		/* 保留 */
-  u64 res3	= 0;		/* 保留 */
-  u64 res4	= 0;		/* 保留 */
-  u32 magic	= 0x644d5241;	/* 魔数, 小端, "ARM\x64" */
-  u32 res5;			/* 保留 （用于 PE COFF 偏移） */
-
-
-映像头注释：
-
-- 自 v3.17 起，除非另有说明，所有域都是小端模式。
-
-- code0/code1 负责跳转到 stext.
-
-- 当通过 EFI 启动时， 最初 code0/code1 被跳过。
-  res5 是到 PE 文件头的偏移，而 PE 文件头含有 EFI 的启动入口点
-  （efi_stub_entry）。当 stub 代码完成了它的使命，它会跳转到 code0
-  继续正常的启动流程。
-
-- v3.17 之前，未明确指定 text_offset 的字节序。此时，image_size 为零，
-  且 text_offset 依照内核字节序为 0x80000。
-  当 image_size 非零，text_offset 为小端模式且是有效值，应被引导加载
-  程序使用。当 image_size 为零，text_offset 可假定为 0x80000。
-
-- flags 域 (v3.17 引入) 为 64 位小端模式，其编码如下：
-  位 0: 	内核字节序。 1 表示大端模式，0 表示小端模式。
-  位 1-2:	内核页大小。
-			0 - 未指定。
-			1 - 4K
-			2 - 16K
-			3 - 64K
-  位 3:		内核物理位置
-			0 - 2MB 对齐基址应尽量靠近内存起始处，因为
-			    其基址以下的内存无法通过线性映射访问
-			1 - 2MB 对齐基址可以在物理内存的任意位置
-  位 4-63:	保留。
-
-- 当 image_size 为零时，引导装载程序应试图在内核映像末尾之后尽可能
-  多地保留空闲内存供内核直接使用。对内存空间的需求量因所选定的内核
-  特性而异, 并无实际限制。
-
-内核映像必须被放置在任意一个可用系统内存 2MB 对齐基址的 text_offset
-字节处，并从该处被调用。2MB 对齐基址和内核映像起始地址之间的区域对于
-内核来说没有特殊意义，且可能被用于其他目的。
-从映像起始地址算起，最少必须准备 image_size 字节的空闲内存供内核使用。
-注： v4.6 之前的版本无法使用内核映像物理偏移以下的内存，所以当时建议
-将映像尽量放置在靠近系统内存起始的地方。
-
-任何提供给内核的内存（甚至在映像起始地址之前），若未从内核中标记为保留
-(如在设备树（dtb）的 memreserve 区域），都将被认为对内核是可用。
-
-在跳转入内核前，必须符合以下状态：
-
-- 停止所有 DMA 设备，这样内存数据就不会因为虚假网络包或磁盘数据而
-  被破坏。这可能可以节省你许多的调试时间。
-
-- 主 CPU 通用寄存器设置
-  x0 = 系统 RAM 中设备树数据块（dtb）的物理地址。
-  x1 = 0 (保留，将来可能使用)
-  x2 = 0 (保留，将来可能使用)
-  x3 = 0 (保留，将来可能使用)
-
-- CPU 模式
-  所有形式的中断必须在 PSTATE.DAIF 中被屏蔽（Debug、SError、IRQ
-  和 FIQ）。
-  CPU 必须处于 EL2（推荐，可访问虚拟化扩展）或非安全 EL1 模式下。
-
-- 高速缓存、MMU
-  MMU 必须关闭。
-  指令缓存开启或关闭皆可。
-  已载入的内核映像的相应内存区必须被清理，以达到缓存一致性点（PoC）。
-  当存在系统缓存或其他使能缓存的一致性主控器时，通常需使用虚拟地址
-  维护其缓存，而非 set/way 操作。
-  遵从通过虚拟地址操作维护构架缓存的系统缓存必须被配置，并可以被使能。
-  而不通过虚拟地址操作维护构架缓存的系统缓存（不推荐），必须被配置且
-  禁用。
-
-  *译者注：对于 PoC 以及缓存相关内容，请参考 ARMv8 构架参考手册
-   ARM DDI 0487A
-
-- 架构计时器
-  CNTFRQ 必须设定为计时器的频率，且 CNTVOFF 必须设定为对所有 CPU
-  都一致的值。如果在 EL1 模式下进入内核，则 CNTHCTL_EL2 中的
-  EL1PCTEN (bit 0) 必须置位。
-
-- 一致性
-  通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。
-  这可能要根据具体实现来定义初始化过程，以使能每个CPU上对维护操作的
-  接收。
-
-- 系统寄存器
-  在进入内核映像的异常级中，所有构架中可写的系统寄存器必须通过软件
-  在一个更高的异常级别下初始化，以防止在 未知 状态下运行。
-
-  对于拥有 GICv3 中断控制器并以 v3 模式运行的系统：
-  - 如果 EL3 存在：
-    ICC_SRE_EL3.Enable (位 3) 必须初始化为 0b1。
-    ICC_SRE_EL3.SRE (位 0) 必须初始化为 0b1。
-  - 若内核运行在 EL1：
-    ICC_SRE_EL2.Enable (位 3) 必须初始化为 0b1。
-    ICC_SRE_EL2.SRE (位 0) 必须初始化为 0b1。
-  - 设备树（DT）或 ACPI 表必须描述一个 GICv3 中断控制器。
-
-  对于拥有 GICv3 中断控制器并以兼容（v2）模式运行的系统：
-  - 如果 EL3 存在：
-    ICC_SRE_EL3.SRE (位 0) 必须初始化为 0b0。
-  - 若内核运行在 EL1：
-    ICC_SRE_EL2.SRE (位 0) 必须初始化为 0b0。
-  - 设备树（DT）或 ACPI 表必须描述一个 GICv2 中断控制器。
-
-以上对于 CPU 模式、高速缓存、MMU、架构计时器、一致性、系统寄存器的
-必要条件描述适用于所有 CPU。所有 CPU 必须在同一异常级别跳入内核。
-
-引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口：
-
-- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树
-  数据块必须在每个 CPU 节点中包含一个 ‘enable-method’ 属性，所
-  支持的 enable-method 请见下文。
-
-  引导装载程序必须生成这些设备树属性，并在跳入内核入口之前将其插入
-  数据块。
-
-- enable-method 为 “spin-table” 的 CPU 必须在它们的 CPU
-  节点中包含一个 ‘cpu-release-addr’ 属性。这个属性标识了一个
-  64 位自然对齐且初始化为零的内存位置。
-
-  这些 CPU 必须在内存保留区（通过设备树中的 /memreserve/ 域传递
-  给内核）中自旋于内核之外，轮询它们的 cpu-release-addr 位置（必须
-  包含在保留区中）。可通过插入 wfe 指令来降低忙循环开销，而主 CPU 将
-  发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值
-  时，CPU 必须跳入此值所指向的地址。此值为一个单独的 64 位小端值，
-  因此 CPU 须在跳转前将所读取的值转换为其本身的端模式。
-
-- enable-method 为 “psci” 的 CPU 保持在内核外（比如，在
-  memory 节点中描述为内核空间的内存区外，或在通过设备树 /memreserve/
-  域中描述为内核保留区的空间中）。内核将会发起在 ARM 文档（编号
-  ARM DEN 0022A：用于 ARM 上的电源状态协调接口系统软件）中描述的
-  CPU_ON 调用来将 CPU 带入内核。
-
-  *译者注: ARM DEN 0022A 已更新到 ARM DEN 0022C。
-
-  设备树必须包含一个 ‘psci’ 节点，请参考以下文档：
-  Documentation/devicetree/bindings/arm/psci.txt
-
-
-- 辅助 CPU 通用寄存器设置
-  x0 = 0 (保留，将来可能使用)
-  x1 = 0 (保留，将来可能使用)
-  x2 = 0 (保留，将来可能使用)
-  x3 = 0 (保留，将来可能使用)
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/arm64/legacy_instructions.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/legacy_instructions.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/arm64/legacy_instructions.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/legacy_instructions.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-Chinese translated version of Documentation/arm64/legacy_instructions.txt
-
-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.
-
-Maintainer: Punit Agrawal <punit.agrawal@arm.com>
-            Suzuki K. Poulose <suzuki.poulose@arm.com>
-Chinese maintainer: Fu Wei <wefu@redhat.com>
----------------------------------------------------------------------
-Documentation/arm64/legacy_instructions.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-本文翻译提交时的 Git 检出点为： bc465aa9d045feb0e13b4a8f32cc33c1943f62d6
-
-英文版维护者： Punit Agrawal <punit.agrawal@arm.com>
-            Suzuki K. Poulose <suzuki.poulose@arm.com>
-中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
-
-以下为正文
----------------------------------------------------------------------
-Linux 内核在 arm64 上的移植提供了一个基础框架，以支持构架中正在被淘汰或已废弃指令的模拟执行。
-这个基础框架的代码使用未定义指令钩子（hooks）来支持模拟。如果指令存在，它也允许在硬件中启用该指令。
-
-模拟模式可通过写 sysctl 节点（/proc/sys/abi）来控制。
-不同的执行方式及 sysctl 节点的相应值，解释如下：
-
-* Undef（未定义）
-  值： 0
-  产生未定义指令终止异常。它是那些构架中已废弃的指令，如 SWP，的默认处理方式。
-
-* Emulate（模拟）
-  值： 1
-  使用软件模拟方式。为解决软件迁移问题，这种模拟指令模式的使用是被跟踪的，并会发出速率限制警告。
-  它是那些构架中正在被淘汰的指令，如 CP15 barriers（隔离指令），的默认处理方式。
-
-* Hardware Execution（硬件执行）
-  值： 2
-  虽然标记为正在被淘汰，但一些实现可能提供硬件执行这些指令的使能/禁用操作。
-  使用硬件执行一般会有更好的性能，但将无法收集运行时对正被淘汰指令的使用统计数据。
-
-默认执行模式依赖于指令在构架中状态。正在被淘汰的指令应该以模拟（Emulate）作为默认模式，
-而已废弃的指令必须默认使用未定义（Undef）模式
-
-注意：指令模拟可能无法应对所有情况。更多详情请参考单独的指令注释。
-
-受支持的遗留指令
--------------
-* SWP{B}
-节点: /proc/sys/abi/swp
-状态: 已废弃
-默认执行方式: Undef (0)
-
-* CP15 Barriers
-节点: /proc/sys/abi/cp15_barrier
-状态: 正被淘汰，不推荐使用
-默认执行方式: Emulate (1)
-
-* SETEND
-节点: /proc/sys/abi/setend
-状态: 正被淘汰，不推荐使用
-默认执行方式: Emulate (1)*
-注：为了使能这个特性，系统中的所有 CPU 必须在 EL0 支持混合字节序。
-如果一个新的 CPU （不支持混合字节序） 在使能这个特性后被热插入系统，
-在应用中可能会出现不可预期的结果。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/arm64/memory.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/memory.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/arm64/memory.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/memory.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,114 +0,0 @@
-Chinese translated version of Documentation/arm64/memory.txt
-
-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.
-
-Maintainer: Catalin Marinas <catalin.marinas@arm.com>
-Chinese maintainer: Fu Wei <wefu@redhat.com>
----------------------------------------------------------------------
-Documentation/arm64/memory.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-本文翻译提交时的 Git 检出点为： bc465aa9d045feb0e13b4a8f32cc33c1943f62d6
-
-英文版维护者： Catalin Marinas <catalin.marinas@arm.com>
-中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
-
-以下为正文
----------------------------------------------------------------------
-		     Linux 在 AArch64 中的内存布局
-		     ===========================
-
-作者: Catalin Marinas <catalin.marinas@arm.com>
-
-本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现
-页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。
-
-AArch64 Linux 使用 3 级或 4 级转换表，其页大小配置为 4KB，对于用户和内核
-分别都有 39-bit (512GB) 或 48-bit (256TB) 的虚拟地址空间。
-对于页大小为 64KB的配置，仅使用 2 级转换表，有 42-bit (4TB) 的虚拟地址空间，但内存布局相同。
-
-用户地址空间的 63:48 位为 0，而内核地址空间的相应位为 1。TTBRx 的
-选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核（全局）映射，
-而用户 pgd 仅包含用户（非全局）映射。swapper_pg_dir 地址被写入
-TTBR1 中，且从不写入 TTBR0。
-
-
-AArch64 Linux 在页大小为 4KB，并使用 3 级转换表时的内存布局：
-
-起始地址			结束地址			大小		用途
------------------------------------------------------------------------
-0000000000000000	0000007fffffffff	 512GB		用户空间
-ffffff8000000000	ffffffffffffffff	 512GB		内核空间
-
-
-AArch64 Linux 在页大小为 4KB，并使用 4 级转换表时的内存布局：
-
-起始地址			结束地址			大小		用途
------------------------------------------------------------------------
-0000000000000000	0000ffffffffffff	 256TB		用户空间
-ffff000000000000	ffffffffffffffff	 256TB		内核空间
-
-
-AArch64 Linux 在页大小为 64KB，并使用 2 级转换表时的内存布局：
-
-起始地址			结束地址			大小		用途
------------------------------------------------------------------------
-0000000000000000	000003ffffffffff	   4TB		用户空间
-fffffc0000000000	ffffffffffffffff	   4TB		内核空间
-
-
-AArch64 Linux 在页大小为 64KB，并使用 3 级转换表时的内存布局：
-
-起始地址			结束地址			大小		用途
------------------------------------------------------------------------
-0000000000000000	0000ffffffffffff	 256TB		用户空间
-ffff000000000000	ffffffffffffffff	 256TB		内核空间
-
-
-更详细的内核虚拟内存布局，请参阅内核启动信息。
-
-
-4KB 页大小的转换表查找：
-
-+--------+--------+--------+--------+--------+--------+--------+--------+
-|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
-+--------+--------+--------+--------+--------+--------+--------+--------+
- |                 |         |         |         |         |
- |                 |         |         |         |         v
- |                 |         |         |         |   [11:0]  页内偏移
- |                 |         |         |         +-> [20:12] L3 索引
- |                 |         |         +-----------> [29:21] L2 索引
- |                 |         +---------------------> [38:30] L1 索引
- |                 +-------------------------------> [47:39] L0 索引
- +-------------------------------------------------> [63] TTBR0/1
-
-
-64KB 页大小的转换表查找：
-
-+--------+--------+--------+--------+--------+--------+--------+--------+
-|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
-+--------+--------+--------+--------+--------+--------+--------+--------+
- |                 |    |               |              |
- |                 |    |               |              v
- |                 |    |               |            [15:0]  页内偏移
- |                 |    |               +----------> [28:16] L3 索引
- |                 |    +--------------------------> [41:29] L2 索引
- |                 +-------------------------------> [47:42] L1 索引
- +-------------------------------------------------> [63] TTBR0/1
-
-
-当使用 KVM 时, 管理程序（hypervisor）在 EL2 中通过相对内核虚拟地址的
-一个固定偏移来映射内核页（内核虚拟地址的高 24 位设为零）:
-
-起始地址			结束地址			大小		用途
------------------------------------------------------------------------
-0000004000000000	0000007fffffffff	 256GB		在 HYP 中映射的内核对象
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/arm64/silicon-errata.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/silicon-errata.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/arm64/silicon-errata.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/silicon-errata.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-Chinese translated version of Documentation/arm64/silicon-errata.txt
-
-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.
-
-M:	Will Deacon <will.deacon@arm.com>
-zh_CN:	Fu Wei <wefu@redhat.com>
-C:	1926e54f115725a9248d0c4c65c22acaf94de4c4
----------------------------------------------------------------------
-Documentation/arm64/silicon-errata.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-英文版维护者： Will Deacon <will.deacon@arm.com>
-中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
-本文翻译提交时的 Git 检出点为： 1926e54f115725a9248d0c4c65c22acaf94de4c4
-
-以下为正文
----------------------------------------------------------------------
-                芯片勘误和软件补救措施
-                ==================
-
-作者: Will Deacon <will.deacon@arm.com>
-日期: 2015年11月27日
-
-一个不幸的现实：硬件经常带有一些所谓的“瑕疵（errata）”，导致其在
-某些特定情况下会违背构架定义的行为。就基于 ARM 的硬件而言，这些瑕疵
-大体可分为以下几类：
-
-  A 类：无可行补救措施的严重缺陷。
-  B 类：有可接受的补救措施的重大或严重缺陷。
-  C 类：在正常操作中不会显现的小瑕疵。
-
-更多资讯，请在 infocenter.arm.com （需注册）中查阅“软件开发者勘误
-笔记”（“Software Developers Errata Notice”）文档。
-
-对于 Linux 而言，B 类缺陷可能需要操作系统的某些特别处理。例如，避免
-一个特殊的代码序列，或是以一种特定的方式配置处理器。在某种不太常见的
-情况下，为将 A 类缺陷当作 C 类处理，可能需要用类似的手段。这些手段被
-统称为“软件补救措施”，且仅在少数情况需要（例如，那些需要一个运行在
-非安全异常级的补救措施 *并且* 能被 Linux 触发的情况）。
-
-对于尚在讨论中的可能对未受瑕疵影响的系统产生干扰的软件补救措施，有一个
-相应的内核配置（Kconfig）选项被加在 “内核特性（Kernel Features）”->
-“基于可选方法框架的 ARM 瑕疵补救措施（ARM errata workarounds via
-the alternatives framework）"。这些选项被默认开启，若探测到受影响的CPU，
-补丁将在运行时被使用。至于对系统运行影响较小的补救措施，内核配置选项
-并不存在，且代码以某种规避瑕疵的方式被构造（带注释为宜）。
-
-这种做法对于在任意内核源代码树中准确地判断出哪个瑕疵已被软件方法所补救
-稍微有点麻烦，所以在 Linux 内核中此文件作为软件补救措施的注册表，
-并将在新的软件补救措施被提交和向后移植（backported）到稳定内核时被更新。
-
-| 实现者         | 受影响的组件    | 勘误编号        | 内核配置                |
-+----------------+-----------------+-----------------+-------------------------+
-| ARM            | Cortex-A53      | #826319         | ARM64_ERRATUM_826319    |
-| ARM            | Cortex-A53      | #827319         | ARM64_ERRATUM_827319    |
-| ARM            | Cortex-A53      | #824069         | ARM64_ERRATUM_824069    |
-| ARM            | Cortex-A53      | #819472         | ARM64_ERRATUM_819472    |
-| ARM            | Cortex-A53      | #845719         | ARM64_ERRATUM_845719    |
-| ARM            | Cortex-A53      | #843419         | ARM64_ERRATUM_843419    |
-| ARM            | Cortex-A57      | #832075         | ARM64_ERRATUM_832075    |
-| ARM            | Cortex-A57      | #852523         | N/A                     |
-| ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220    |
-|                |                 |                 |                         |
-| Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375    |
-| Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154    |
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/arm64/tagged-pointers.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/tagged-pointers.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/arm64/tagged-pointers.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/arm64/tagged-pointers.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-Chinese translated version of Documentation/arm64/tagged-pointers.txt
-
-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.
-
-Maintainer: Will Deacon <will.deacon@arm.com>
-Chinese maintainer: Fu Wei <wefu@redhat.com>
----------------------------------------------------------------------
-Documentation/arm64/tagged-pointers.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-英文版维护者： Will Deacon <will.deacon@arm.com>
-中文版维护者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版翻译者： 傅炜  Fu Wei <wefu@redhat.com>
-中文版校译者： 傅炜  Fu Wei <wefu@redhat.com>
-
-以下为正文
----------------------------------------------------------------------
-		Linux 在 AArch64 中带标记的虚拟地址
-		=================================
-
-作者: Will Deacon <will.deacon@arm.com>
-日期: 2013 年 06 月 12 日
-
-本文档简述了在 AArch64 地址转换系统中提供的带标记的虚拟地址及其在
-AArch64 Linux 中的潜在用途。
-
-内核提供的地址转换表配置使通过 TTBR0 完成的虚拟地址转换（即用户空间
-映射），其虚拟地址的最高 8 位（63:56）会被转换硬件所忽略。这种机制
-让这些位可供应用程序自由使用，其注意事项如下：
-
-	(1) 内核要求所有传递到 EL1 的用户空间地址带有 0x00 标记。
-	    这意味着任何携带用户空间虚拟地址的系统调用（syscall）
-	    参数 *必须* 在陷入内核前使它们的最高字节被清零。
-
-	(2) 非零标记在传递信号时不被保存。这意味着在应用程序中利用了
-	    标记的信号处理函数无法依赖 siginfo_t 的用户空间虚拟
-	    地址所携带的包含其内部域信息的标记。此规则的一个例外是
-	    当信号是在调试观察点的异常处理程序中产生的，此时标记的
-	    信息将被保存。
-
-	(3) 当使用带标记的指针时需特别留心，因为仅对两个虚拟地址
-	    的高字节，C 编译器很可能无法判断它们是不同的。
-
-此构架会阻止对带标记的 PC 指针的利用，因此在异常返回时，其高字节
-将被设置成一个为 “55” 的扩展符。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/basic_profiling.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/basic_profiling.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/basic_profiling.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/basic_profiling.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-Chinese translated version of Documentation/basic_profiling
-
-If you have any comment or update to the content, please post to LKML directly.
-However, if you have problem communicating in English you can also ask the
-Chinese maintainer for help.  Contact the Chinese maintainer, if this
-translation is outdated or there is problem with translation.
-
-Chinese maintainer: Liang Xie <xieliang@xiaomi.com>
----------------------------------------------------------------------
-Documentation/basic_profiling的中文翻译
-
-如果想评论或更新本文的内容，请直接发信到LKML。如果你使用英文交流有困难的话，也可
-以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题，请联系中文版维护者。
-
-中文版维护者： 谢良 Liang Xie <xieliang007@gmail.com>
-中文版翻译者： 谢良 Liang Xie <xieliang007@gmail.com>
-中文版校译者：
-以下为正文
----------------------------------------------------------------------
-
-下面这些说明指令都是非常基础的，如果你想进一步了解请阅读相关专业文档：）
-请不要再在本文档增加新的内容，但可以修复文档中的错误：）(mbligh@aracnet.com)
-感谢John Levon，Dave Hansen等在撰写时的帮助
-
-<test> 用于表示要测量的目标
-请先确保您已经有正确的System.map / vmlinux配置！
-
-对于linux系统来说，配置vmlinuz最容易的方法可能就是使用“make install”，然后修改
-/sbin/installkernel将vmlinux拷贝到/boot目录，而System.map通常是默认安装好的
-
-Readprofile
------------
-2.6系列内核需要版本相对较新的readprofile，比如util-linux 2.12a中包含的，可以从:
-
-http://www.kernel.org/pub/linux/utils/util-linux/ 下载
-
-大部分linux发行版已经包含了.
-
-启用readprofile需要在kernel启动命令行增加”profile=2“
-
-clear		readprofile -r
-		<test>
-dump output	readprofile -m /boot/System.map > captured_profile
-
-Oprofile
---------
-
-从http://oprofile.sourceforge.net/获取源代码（请参考Changes以获取匹配的版本）
-在kernel启动命令行增加“idle=poll”
-
-配置CONFIG_PROFILING=y和CONFIG_OPROFILE=y然后重启进入新kernel
-
-./configure --with-kernel-support
-make install
-
-想得到好的测量结果，请确保启用了本地APIC特性。如果opreport显示有0Hz CPU，
-说明APIC特性没有开启。另外注意idle=poll选项可能有损性能。
-
-One time setup:
-		opcontrol --setup --vmlinux=/boot/vmlinux
-
-clear		opcontrol --reset
-start		opcontrol --start
-		<test>
-stop		opcontrol --stop
-dump output	opreport >  output_file
-
-如果只看kernel相关的报告结果，请运行命令 opreport -l /boot/vmlinux > output_file
-
-通过reset选项可以清理过期统计数据，相当于重启的效果。
-
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/CodingStyle linux-libre-4.10-rc8-gnu/Documentation/zh_CN/CodingStyle
--- linux-libre-4.9-gnu/Documentation/zh_CN/CodingStyle	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/CodingStyle	1969-12-31 19:00:00.000000000 -0500
@@ -1,813 +0,0 @@
-Chinese translated version of Documentation/CodingStyle
-
-If you have any comment or update to the content, please post to LKML directly.
-However, if you have problem communicating in English you can also ask the
-Chinese maintainer for help.  Contact the Chinese maintainer, if this
-translation is outdated or there is problem with translation.
-
-Chinese maintainer: Zhang Le <r0bertz@gentoo.org>
----------------------------------------------------------------------
-Documentation/CodingStyle的中文翻译
-
-如果想评论或更新本文的内容，请直接发信到LKML。如果你使用英文交流有困难的话，也可
-以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题，请联系中文版维护者。
-
-中文版维护者： 张乐 Zhang Le <r0bertz@gentoo.org>
-中文版翻译者： 张乐 Zhang Le <r0bertz@gentoo.org>
-中文版校译者： 王聪 Wang Cong <xiyou.wangcong@gmail.com>
-               wheelz <kernel.zeng@gmail.com>
-               管旭东 Xudong Guan <xudong.guan@gmail.com>
-               Li Zefan <lizf@cn.fujitsu.com>
-               Wang Chen <wangchen@cn.fujitsu.com>
-以下为正文
----------------------------------------------------------------------
-
-		Linux内核代码风格
-
-这是一个简短的文档，描述了 linux 内核的首选代码风格。代码风格是因人而异的，而且我
-不愿意把自己的观点强加给任何人，但这就像我去做任何事情都必须遵循的原则那样，我也
-希望在绝大多数事上保持这种的态度。请（在写代码时）至少考虑一下这里的代码风格。
-
-首先，我建议你打印一份 GNU 代码规范，然后不要读。烧了它，这是一个具有重大象征性意义
-的动作。
-
-不管怎样，现在我们开始：
-
-
-		第一章：缩进
-
-制表符是 8 个字符，所以缩进也是 8 个字符。有些异端运动试图将缩进变为 4（甚至 2！）
-个字符深，这几乎相当于尝试将圆周率的值定义为 3。
-
-理由：缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的屏幕
-连续看了 20 小时之后，你将会发现大一点的缩进会使你更容易分辨缩进。
-
-现在，有些人会抱怨 8 个字符的缩进会使代码向右边移动的太远，在 80 个字符的终端屏幕上
-就很难读这样的代码。这个问题的答案是，如果你需要 3 级以上的缩进，不管用何种方式你
-的代码已经有问题了，应该修正你的程序。
-
-简而言之，8 个字符的缩进可以让代码更容易阅读，还有一个好处是当你的函数嵌套太深的
-时候可以给你警告。留心这个警告。
-
-在 switch 语句中消除多级缩进的首选的方式是让 “switch” 和从属于它的 “case” 标签
-对齐于同一列，而不要 “两次缩进” “case” 标签。比如：
-
-	switch (suffix) {
-	case 'G':
-	case 'g':
-		mem <<= 30;
-		break;
-	case 'M':
-	case 'm':
-		mem <<= 20;
-		break;
-	case 'K':
-	case 'k':
-		mem <<= 10;
-		/* fall through */
-	default:
-		break;
-	}
-
-不要把多个语句放在一行里，除非你有什么东西要隐藏：
-
-	if (condition) do_this;
-	  do_something_everytime;
-
-也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读的表
-达式。
-
-除了注释、文档和 Kconfig 之外，不要使用空格来缩进，前面的例子是例外，是有意为之。
-
-选用一个好的编辑器，不要在行尾留空格。
-
-
-		第二章：把长的行和字符串打散
-
-代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。
-
-每一行的长度的限制是 80 列，我们强烈建议您遵守这个惯例。
-
-长于 80 列的语句要打散成有意义的片段。除非超过 80 列能显著增加可读性，并且不会隐藏
-信息。子片段要明显短于母片段，并明显靠右。这同样适用于有着很长参数列表的函数头。
-然而，绝对不要打散对用户可见的字符串，例如 printk 信息，因为这将导致无法 grep 这些
-信息。
-
-		第三章：大括号和空格的放置
-
-C语言风格中另外一个常见问题是大括号的放置。和缩进大小不同，选择或弃用某种放置策
-略并没有多少技术上的原因，不过首选的方式，就像 Kernighan 和 Ritchie 展示给我们的，
-是把起始大括号放在行尾，而把结束大括号放在行首，所以：
-
-	if (x is true) {
-		we do y
-	}
-
-这适用于所有的非函数语句块（if、switch、for、while、do）。比如：
-
-	switch (action) {
-	case KOBJ_ADD:
-		return "add";
-	case KOBJ_REMOVE:
-		return "remove";
-	case KOBJ_CHANGE:
-		return "change";
-	default:
-		return NULL;
-	}
-
-不过，有一个例外，那就是函数：函数的起始大括号放置于下一行的开头，所以：
-
-	int function(int x)
-	{
-		body of function
-	}
-
-全世界的异端可能会抱怨这个不一致性是……呃……不一致的，不过所有思维健全的人都知道
-(a) K&R 是 _正确的_，并且 (b) K&R 是正确的。此外，不管怎样函数都是特殊的（C
-函数是不能嵌套的）。
-
-注意结束大括号独自占据一行，除非它后面跟着同一个语句的剩余部分，也就是 do 语句中的
-“while” 或者 if 语句中的 “else”，像这样：
-
-	do {
-		body of do-loop
-	} while (condition);
-
-和
-
-	if (x == y) {
-		..
-	} else if (x > y) {
-		...
-	} else {
-		....
-	}
-
-理由：K&R。
-
-也请注意这种大括号的放置方式也能使空（或者差不多空的）行的数量最小化，同时不失可
-读性。因此，由于你的屏幕上的新行是不可再生资源（想想 25 行的终端屏幕），你将会有更
-多的空行来放置注释。
-
-当只有一个单独的语句的时候，不用加不必要的大括号。
-
-	if (condition)
-		action();
-
-和
-
-	if (condition)
-		do_this();
-	else
-		do_that();
-
-这并不适用于只有一个条件分支是单语句的情况；这时所有分支都要使用大括号：
-
-	if (condition) {
-		do_this();
-		do_that();
-	} else {
-		otherwise();
-	}
-
-		3.1：空格
-
-Linux 内核的空格使用方式（主要）取决于它是用于函数还是关键字。（大多数）关键字后
-要加一个空格。值得注意的例外是 sizeof、typeof、alignof 和 __attribute__，这些
-关键字某些程度上看起来更像函数（它们在 Linux 里也常常伴随小括号而使用，尽管在 C 里
-这样的小括号不是必需的，就像 “struct fileinfo info” 声明过后的 “sizeof info”）。
-
-所以在这些关键字之后放一个空格：
-
-	if, switch, case, for, do, while
-
-但是不要在 sizeof、typeof、alignof 或者 __attribute__ 这些关键字之后放空格。例如，
-
-	s = sizeof(struct file);
-
-不要在小括号里的表达式两侧加空格。这是一个反例：
-
-	s = sizeof( struct file );
-
-当声明指针类型或者返回指针类型的函数时，“*” 的首选使用方式是使之靠近变量名或者函
-数名，而不是靠近类型名。例子：
-
-	char *linux_banner;
-	unsigned long long memparse(char *ptr, char **retptr);
-	char *match_strdup(substring_t *s);
-
-在大多数二元和三元操作符两侧使用一个空格，例如下面所有这些操作符：
-
-	=  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :
-
-但是一元操作符后不要加空格：
-
-	&  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined
-
-后缀自加和自减一元操作符前不加空格：
-
-	++  --
-
-前缀自加和自减一元操作符后不加空格：
-
-	++  --
-
-‘.’ 和 “->” 结构体成员操作符前后不加空格。
-
-不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白，然后你
-就可以直接在那一行输入代码。不过假如你最后没有在那一行输入代码，有些编辑器就不
-会移除已经加入的空白，就像你故意留下一个只有空白的行。包含行尾空白的行就这样产
-生了。
-
-当git发现补丁包含了行尾空白的时候会警告你，并且可以应你的要求去掉行尾空白；不过
-如果你是正在打一系列补丁，这样做会导致后面的补丁失败，因为你改变了补丁的上下文。
-
-
-		第四章：命名
-
-C是一个简朴的语言，你的命名也应该这样。和 Modula-2 和 Pascal 程序员不同，C 程序员
-不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字。C 程序员会称那个变量
-为 “tmp”，这样写起来会更容易，而且至少不会令其难于理解。
-
-不过，虽然混用大小写的名字是不提倡使用的，但是全局变量还是需要一个具描述性的名字
-。称一个全局函数为 “foo” 是一个难以饶恕的错误。
-
-全局变量（只有当你真正需要它们的时候再用它）需要有一个具描述性的名字，就像全局函
-数。如果你有一个可以计算活动用户数量的函数，你应该叫它 “count_active_users()”
-或者类似的名字，你不应该叫它 “cntuser()”。
-
-在函数名中包含函数类型（所谓的匈牙利命名法）是脑子出了问题——编译器知道那些类型而
-且能够检查那些类型，这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题的程序。
-
-本地变量名应该简短，而且能够表达相关的含义。如果你有一些随机的整数型的循环计数器
-，它应该被称为 “i”。叫它 “loop_counter” 并无益处，如果它没有被误解的可能的话。
-类似的，“tmp” 可以用来称呼任意类型的临时变量。
-
-如果你怕混淆了你的本地变量名，你就遇到另一个问题了，叫做函数增长荷尔蒙失衡综合症
-。请看第六章（函数）。
-
-
-		第五章：Typedef
-
-不要使用类似 “vps_t” 之类的东西。
-
-对结构体和指针使用 typedef 是一个错误。当你在代码里看到：
-
-	vps_t a;
-
-这代表什么意思呢？
-
-相反，如果是这样
-
-	struct virtual_container *a;
-
-你就知道 “a” 是什么了。
-
-很多人认为 typedef “能提高可读性”。实际不是这样的。它们只在下列情况下有用：
-
- (a) 完全不透明的对象（这种情况下要主动使用 typedef 来隐藏这个对象实际上是什么）。
-
-     例如：“pte_t” 等不透明对象，你只能用合适的访问函数来访问它们。
-
-     注意！不透明性和“访问函数”本身是不好的。我们使用 pte_t 等类型的原因在于真的是
-     完全没有任何共用的可访问信息。
-
- (b) 清楚的整数类型，如此，这层抽象就可以帮助消除到底是 “int” 还是 “long” 的混淆。
-
-     u8/u16/u32 是完全没有问题的 typedef，不过它们更符合类别 (d) 而不是这里。
-
-     再次注意！要这样做，必须事出有因。如果某个变量是 “unsigned long“，那么没有必要
-
-	typedef unsigned long myflags_t;
-
-     不过如果有一个明确的原因，比如它在某种情况下可能会是一个 “unsigned int” 而在
-     其他情况下可能为 “unsigned long”，那么就不要犹豫，请务必使用 typedef。
-
- (c) 当你使用sparse按字面的创建一个新类型来做类型检查的时候。
-
- (d) 和标准C99类型相同的类型，在某些例外的情况下。
-
-     虽然让眼睛和脑筋来适应新的标准类型比如 “uint32_t” 不需要花很多时间，可是有些
-     人仍然拒绝使用它们。
-
-     因此，Linux 特有的等同于标准类型的 “u8/u16/u32/u64” 类型和它们的有符号类型是被
-     允许的——尽管在你自己的新代码中，它们不是强制要求要使用的。
-
-     当编辑已经使用了某个类型集的已有代码时，你应该遵循那些代码中已经做出的选择。
-
- (e) 可以在用户空间安全使用的类型。
-
-     在某些用户空间可见的结构体里，我们不能要求C99类型而且不能用上面提到的 “u32”
-     类型。因此，我们在与用户空间共享的所有结构体中使用 __u32 和类似的类型。
-
-可能还有其他的情况，不过基本的规则是永远不要使用 typedef，除非你可以明确的应用上
-述某个规则中的一个。
-
-总的来说，如果一个指针或者一个结构体里的元素可以合理的被直接访问到，那么它们就不
-应该是一个 typedef。
-
-
-		第六章：函数
-
-函数应该简短而漂亮，并且只完成一件事情。函数应该可以一屏或者两屏显示完（我们都知
-道 ISO/ANSI 屏幕大小是 80x24），只做一件事情，而且把它做好。
-
-一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。所以，如果你有一个理论上
-很简单的只有一个很长（但是简单）的 case 语句的函数，而且你需要在每个 case 里做
-很多很小的事情，这样的函数尽管很长，但也是可以的。
-
-不过，如果你有一个复杂的函数，而且你怀疑一个天分不是很高的高中一年级学生可能甚至
-搞不清楚这个函数的目的，你应该严格的遵守前面提到的长度限制。使用辅助函数，并为之
-取个具描述性的名字（如果你觉得它们的性能很重要的话，可以让编译器内联它们，这样的
-效果往往会比你写一个复杂函数的效果要好。）
-
-函数的另外一个衡量标准是本地变量的数量。此数量不应超过 5－10 个，否则你的函数就有
-问题了。重新考虑一下你的函数，把它分拆成更小的函数。人的大脑一般可以轻松的同时跟
-踪 7 个不同的事物，如果再增多的话，就会糊涂了。即便你聪颖过人，你也可能会记不清你
-2 个星期前做过的事情。
-
-在源文件里，使用空行隔开不同的函数。如果该函数需要被导出，它的 EXPORT* 宏应该紧贴
-在它的结束大括号之下。比如：
-
-	int system_is_up(void)
-	{
-		return system_state == SYSTEM_RUNNING;
-	}
-	EXPORT_SYMBOL(system_is_up);
-
-在函数原型中，包含函数名和它们的数据类型。虽然C语言里没有这样的要求，在 Linux 里这
-是提倡的做法，因为这样可以很简单的给读者提供更多的有价值的信息。
-
-
-		第七章：集中的函数退出途径
-
-虽然被某些人声称已经过时，但是 goto 语句的等价物还是经常被编译器所使用，具体形式是
-无条件跳转指令。
-
-当一个函数从多个位置退出，并且需要做一些类似清理的常见操作时，goto 语句就很方便了。
-如果并不需要清理操作，那么直接 return 即可。
-
-理由是：
-
-- 无条件语句容易理解和跟踪
-- 嵌套程度减小
-- 可以避免由于修改时忘记更新某个单独的退出点而导致的错误
-- 减轻了编译器的工作，无需删除冗余代码;)
-
-	int fun(int a)
-	{
-		int result = 0;
-		char *buffer;
-
-		buffer = kmalloc(SIZE, GFP_KERNEL);
-		if (!buffer)
-			return -ENOMEM;
-
-		if (condition1) {
-			while (loop1) {
-				...
-			}
-			result = 1;
-			goto out_buffer;
-		}
-		...
-	out_buffer:
-		kfree(buffer);
-		return result;
-	}
-
-一个需要注意的常见错误是“一个 err 错误”，就像这样：
-
-	err:
-		kfree(foo->bar);
-		kfree(foo);
-		return ret;
-
-这段代码的错误是，在某些退出路径上 “foo” 是 NULL。通常情况下，通过把它分离成两个
-错误标签 “err_bar:” 和 “err_foo:” 来修复这个错误。
-
-		第八章：注释
-
-注释是好的，不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的：更好
-的做法是让别人一看你的代码就可以明白，解释写的很差的代码是浪费时间。
-
-一般的，你想要你的注释告诉别人你的代码做了什么，而不是怎么做的。也请你不要把注释
-放在一个函数体内部：如果函数复杂到你需要独立的注释其中的一部分，你很可能需要回到
-第六章看一看。你可以做一些小注释来注明或警告某些很聪明（或者槽糕）的做法，但不要
-加太多。你应该做的，是把注释放在函数的头部，告诉人们它做了什么，也可以加上它做这
-些事情的原因。
-
-当注释内核API函数时，请使用 kernel-doc 格式。请看
-Documentation/kernel-documentation.rst和scripts/kernel-doc 以获得详细信息。
-
-Linux的注释风格是 C89 “/* ... */” 风格。不要使用 C99 风格 “// ...” 注释。
-
-长（多行）的首选注释风格是：
-
-	/*
-	 * This is the preferred style for multi-line
-	 * comments in the Linux kernel source code.
-	 * Please use it consistently.
-	 *
-	 * Description:  A column of asterisks on the left side,
-	 * with beginning and ending almost-blank lines.
-	 */
-
-对于在 net/ 和 drivers/net/ 的文件，首选的长（多行）注释风格有些不同。
-
-	/* The preferred comment style for files in net/ and drivers/net
-	 * looks like this.
-	 *
-	 * It is nearly the same as the generally preferred comment style,
-	 * but there is no initial almost-blank line.
-	 */
-
-注释数据也是很重要的，不管是基本类型还是衍生类型。为了方便实现这一点，每一行应只
-声明一个数据（不要使用逗号来一次声明多个数据）。这样你就有空间来为每个数据写一段
-小注释来解释它们的用途了。
-
-
-		第九章：你已经把事情弄糟了
-
-这没什么，我们都是这样。可能你的使用了很长时间 Unix 的朋友已经告诉你 “GNU emacs” 能
-自动帮你格式化 C 源代码，而且你也注意到了，确实是这样，不过它所使用的默认值和我们
-想要的相去甚远（实际上，甚至比随机打的还要差——无数个猴子在 GNU emacs 里打字永远不
-会创造出一个好程序）（译注：请参考 Infinite Monkey Theorem）
-
-所以你要么放弃 GNU emacs，要么改变它让它使用更合理的设定。要采用后一个方案，你可
-以把下面这段粘贴到你的 .emacs 文件里。
-
-(defun c-lineup-arglist-tabs-only (ignored)
-  "Line up argument lists by tabs, not spaces"
-  (let* ((anchor (c-langelem-pos c-syntactic-element))
-         (column (c-langelem-2nd-pos c-syntactic-element))
-         (offset (- (1+ column) anchor))
-         (steps (floor offset c-basic-offset)))
-    (* (max steps 1)
-       c-basic-offset)))
-
-(add-hook 'c-mode-common-hook
-          (lambda ()
-            ;; Add kernel style
-            (c-add-style
-             "linux-tabs-only"
-             '("linux" (c-offsets-alist
-                        (arglist-cont-nonempty
-                         c-lineup-gcc-asm-reg
-                         c-lineup-arglist-tabs-only))))))
-
-(add-hook 'c-mode-hook
-          (lambda ()
-            (let ((filename (buffer-file-name)))
-              ;; Enable kernel mode for the appropriate files
-              (when (and filename
-                         (string-match (expand-file-name "~/src/linux-trees")
-                                       filename))
-                (setq indent-tabs-mode t)
-                (setq show-trailing-whitespace t)
-                (c-set-style "linux-tabs-only")))))
-
-这会让 emacs 在 ~/src/linux-trees 目录下的 C 源文件获得更好的内核代码风格。
-
-不过就算你尝试让 emacs 正确的格式化代码失败了，也并不意味着你失去了一切：还可以用
-“indent”。
-
-不过，GNU indent 也有和 GNU emacs 一样有问题的设定，所以你需要给它一些命令选项。不
-过，这还不算太糟糕，因为就算是 GNU indent 的作者也认同 K&R 的权威性（GNU 的人并不是
-坏人，他们只是在这个问题上被严重的误导了），所以你只要给 indent 指定选项 “-kr -i8”
-（代表 “K&R，8 个字符缩进”），或者使用 “scripts/Lindent”，这样就可以以最时髦的方式
-缩进源代码。
-
-“indent” 有很多选项，特别是重新格式化注释的时候，你可能需要看一下它的手册页。不过
-记住：“indent” 不能修正坏的编程习惯。
-
-
-		第十章：Kconfig 配置文件
-
-对于遍布源码树的所有 Kconfig* 配置文件来说，它们缩进方式与 C 代码相比有所不同。紧挨
-在 “config” 定义下面的行缩进一个制表符，帮助信息则再多缩进 2 个空格。比如：
-
-config AUDIT
-	bool "Auditing support"
-	depends on NET
-	help
-	  Enable auditing infrastructure that can be used with another
-	  kernel subsystem, such as SELinux (which requires this for
-	  logging of avc messages output).  Does not do system-call
-	  auditing without CONFIG_AUDITSYSCALL.
-
-而那些危险的功能（比如某些文件系统的写支持）应该在它们的提示字符串里显著的声明这
-一点：
-
-config ADFS_FS_RW
-	bool "ADFS write support (DANGEROUS)"
-	depends on ADFS_FS
-	...
-
-要查看配置文件的完整文档，请看 Documentation/kbuild/kconfig-language.txt。
-
-
-		第十一章：数据结构
-
-如果一个数据结构，在创建和销毁它的单线执行环境之外可见，那么它必须要有一个引用计
-数器。内核里没有垃圾收集（并且内核之外的垃圾收集慢且效率低下），这意味着你绝对需
-要记录你对这种数据结构的使用情况。
-
-引用计数意味着你能够避免上锁，并且允许多个用户并行访问这个数据结构——而不需要担心
-这个数据结构仅仅因为暂时不被使用就消失了，那些用户可能不过是沉睡了一阵或者做了一
-些其他事情而已。
-
-注意上锁不能取代引用计数。上锁是为了保持数据结构的一致性，而引用计数是一个内存管
-理技巧。通常二者都需要，不要把两个搞混了。
-
-很多数据结构实际上有2级引用计数，它们通常有不同“类”的用户。子类计数器统计子类用
-户的数量，每当子类计数器减至零时，全局计数器减一。
-
-这种“多级引用计数”的例子可以在内存管理（“struct mm_struct”：mm_users 和 mm_count）
-和文件系统（“struct super_block”：s_count和s_active）中找到。
-
-记住：如果另一个执行线索可以找到你的数据结构，但是这个数据结构没有引用计数器，这
-里几乎肯定是一个 bug。
-
-
-		第十二章：宏，枚举和RTL
-
-用于定义常量的宏的名字及枚举里的标签需要大写。
-
-#define CONSTANT 0x12345
-
-在定义几个相关的常量时，最好用枚举。
-
-宏的名字请用大写字母，不过形如函数的宏的名字可以用小写字母。
-
-一般的，如果能写成内联函数就不要写成像函数的宏。
-
-含有多个语句的宏应该被包含在一个 do-while 代码块里：
-
-	#define macrofun(a, b, c)			\
-		do {					\
-			if (a == 5)			\
-				do_this(b, c);		\
-		} while (0)
-
-使用宏的时候应避免的事情：
-
-1) 影响控制流程的宏：
-
-	#define FOO(x)					\
-		do {					\
-			if (blah(x) < 0)		\
-				return -EBUGGERED;	\
-		} while (0)
-
-非常不好。它看起来像一个函数，不过却能导致“调用”它的函数退出；不要打乱读者大脑里
-的语法分析器。
-
-2) 依赖于一个固定名字的本地变量的宏：
-
-	#define FOO(val) bar(index, val)
-
-可能看起来像是个不错的东西，不过它非常容易把读代码的人搞糊涂，而且容易导致看起来
-不相关的改动带来错误。
-
-3) 作为左值的带参数的宏： FOO(x) = y；如果有人把 FOO 变成一个内联函数的话，这种用
-法就会出错了。
-
-4) 忘记了优先级：使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数的
-宏也要注意此类问题。
-
-	#define CONSTANT 0x4000
-	#define CONSTEXP (CONSTANT | 3)
-
-5) 在宏里定义类似函数的本地变量时命名冲突：
-
-	#define FOO(x)				\
-	({					\
-		typeof(x) ret;			\
-		ret = calc_ret(x);		\
-		(ret);				\
-	})
-
-ret 是本地变量的通用名字 - __foo_ret 更不容易与一个已存在的变量冲突。
-
-cpp 手册对宏的讲解很详细。gcc internals 手册也详细讲解了 RTL（译注：register
-transfer language），内核里的汇编语言经常用到它。
-
-
-		第十三章：打印内核消息
-
-内核开发者应该是受过良好教育的。请一定注意内核信息的拼写，以给人以好的印象。不要
-用不规范的单词比如 “dont”，而要用 “do not”或者 “don't”。保证这些信息简单、明了、
-无歧义。
-
-内核信息不必以句号（译注：英文句号，即点）结束。
-
-在小括号里打印数字 (%d) 没有任何价值，应该避免这样做。
-
-<linux/device.h> 里有一些驱动模型诊断宏，你应该使用它们，以确保信息对应于正确的
-设备和驱动，并且被标记了正确的消息级别。这些宏有：dev_err()，dev_warn()，
-dev_info() 等等。对于那些不和某个特定设备相关连的信息，<linux/printk.h> 定义了
-pr_notice()，pr_info()，pr_warn()，pr_err() 和其他。
-
-写出好的调试信息可以是一个很大的挑战；一旦你写出后，这些信息在远程除错时能提供极大
-的帮助。然而打印调试信息的处理方式同打印非调试信息不同。其他 pr_XXX() 函数能无条件地
-打印，pr_debug() 却不；默认情况下它不会被编译，除非定义了 DEBUG 或设定了
-CONFIG_DYNAMIC_DEBUG。实际这同样是为了 dev_dbg()，一个相关约定是在一个已经开启了
-DEBUG 时，使用 VERBOSE_DEBUG 来添加 dev_vdbg()。
-
-许多子系统拥有 Kconfig 调试选项来开启 -DDEBUG 在对应的 Makefile 里面；在其他
-情况下，特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时，例如，如果
-已经包含一个调试相关的 #ifdef 条件，printk(KERN_DEBUG ...) 就可被使用。
-
-
-		第十四章：分配内存
-
-内核提供了下面的一般用途的内存分配函数：
-kmalloc()，kzalloc()，kmalloc_array()，kcalloc()，vmalloc() 和 vzalloc()。
-请参考 API 文档以获取有关它们的详细信息。
-
-传递结构体大小的首选形式是这样的：
-
-	p = kmalloc(sizeof(*p), ...);
-
-另外一种传递方式中，sizeof 的操作数是结构体的名字，这样会降低可读性，并且可能会引
-入 bug。有可能指针变量类型被改变时，而对应的传递给内存分配函数的 sizeof 的结果不变。
-
-强制转换一个 void 指针返回值是多余的。C 语言本身保证了从 void 指针到其他任何指针类型
-的转换是没有问题的。
-
-分配一个数组的首选形式是这样的：
-
-	p = kmalloc_array(n, sizeof(...), ...);
-
-分配一个零长数组的首选形式是这样的：
-
-	p = kcalloc(n, sizeof(...), ...);
-
-两种形式检查分配大小 n * sizeof(...) 的溢出，如果溢出返回 NULL。
-
-
-		第十五章：内联弊病
-
-有一个常见的误解是内联函数是 gcc 提供的可以让代码运行更快的一个选项。虽然使用内联
-函数有时候是恰当的（比如作为一种替代宏的方式，请看第十二章），不过很多情况下不是
-这样。inline 关键字的过度使用会使内核变大，从而使整个系统运行速度变慢。因为大内核
-会占用更多的指令高速缓存（译注：一级缓存通常是指令缓存和数据缓存分开的）而且会导
-致 pagecache 的可用内存减少。想象一下，一次pagecache未命中就会导致一次磁盘寻址，
-将耗时 5 毫秒。5 毫秒的时间内 CPU 能执行很多很多指令。
-
-一个基本的原则是如果一个函数有 3 行以上，就不要把它变成内联函数。这个原则的一个例
-外是，如果你知道某个参数是一个编译时常量，而且因为这个常量你确定编译器在编译时能
-优化掉你的函数的大部分代码，那仍然可以给它加上 inline 关键字。kmalloc() 内联函数就
-是一个很好的例子。
-
-人们经常主张给 static 的而且只用了一次的函数加上 inline，如此不会有任何损失，因为没
-有什么好权衡的。虽然从技术上说这是正确的，但是实际上这种情况下即使不加 inline gcc
-也可以自动使其内联。而且其他用户可能会要求移除 inline，由此而来的争论会抵消 inline
-自身的潜在价值，得不偿失。
-
-
-		第十六章：函数返回值及命名
-
-函数可以返回很多种不同类型的值，最常见的一种是表明函数执行成功或者失败的值。这样
-的一个值可以表示为一个错误代码整数（-Exxx＝失败，0＝成功）或者一个“成功”布尔值（
-0＝失败，非0＝成功）。
-
-混合使用这两种表达方式是难于发现的 bug 的来源。如果 C 语言本身严格区分整形和布尔型变
-量，那么编译器就能够帮我们发现这些错误……不过 C 语言不区分。为了避免产生这种 bug，请
-遵循下面的惯例：
-
-	如果函数的名字是一个动作或者强制性的命令，那么这个函数应该返回错误代码整
-	数。如果是一个判断，那么函数应该返回一个“成功”布尔值。
-
-比如，“add work” 是一个命令，所以 add_work() 函数在成功时返回 0，在失败时返回 -EBUSY。
-类似的，因为 “PCI device present” 是一个判断，所以 pci_dev_present() 函数在成功找到
-一个匹配的设备时应该返回 1，如果找不到时应该返回 0。
-
-所有导出（译注：EXPORT）的函数都必须遵守这个惯例，所有的公共函数也都应该如此。私
-有（static）函数不需要如此，但是我们也推荐这样做。
-
-返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的，他们
-通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数，他们使用
-NULL 或者 ERR_PTR 机制来报告错误。
-
-
-		第十七章：不要重新发明内核宏
-
-头文件 include/linux/kernel.h 包含了一些宏，你应该使用它们，而不要自己写一些它们的
-变种。比如，如果你需要计算一个数组的长度，使用这个宏
-
-	#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-类似的，如果你要计算某结构体成员的大小，使用
-
-	#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
-
-还有可以做严格的类型检查的 min() 和 max() 宏，如果你需要可以使用它们。你可以自己看看
-那个头文件里还定义了什么你可以拿来用的东西，如果有定义的话，你就不应在你的代码里
-自己重新定义。
-
-
-		第十八章：编辑器模式行和其他需要罗嗦的事情
-
-有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如，emacs
-能够解释被标记成这样的行：
-
-	-*- mode: c -*-
-
-或者这样的：
-
-	/*
-	Local Variables:
-	compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
-	End:
-	*/
-
-Vim 能够解释这样的标记：
-
-	/* vim:set sw=8 noet */
-
-不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置，你的源文件不应
-该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制的模
-式，或者使用其他可以产生正确的缩进的巧妙方法。
-
-
-		第十九章：内联汇编
-
-在特定架构的代码中，你也许需要内联汇编来使用 CPU 接口和平台相关功能。在需要
-这么做时，不要犹豫。然而，当 C 可以完成工作时，不要无端地使用内联汇编。如果
-可能，你可以并且应该用 C 和硬件交互。
-
-考虑去写通用一点的内联汇编作为简明的辅助函数，而不是重复写下它们的细节。记住
-内联汇编可以使用 C 参数。
-
-大而特殊的汇编函数应该放在 .S 文件中，对应 C 的原型定义在 C 头文件中。汇编
-函数的 C 原型应该使用 “asmlinkage”。
-
-你可能需要将你的汇编语句标记为 volatile，来阻止 GCC 在没发现任何副作用后就
-移除了它。你不必总是这样做，虽然，这样可以限制不必要的优化。
-
-在写一个包含多条指令的单个内联汇编语句时，把每条指令用引号字符串分离，并写在
-单独一行，在每个字符串结尾，除了 \n\t 结尾之外，在汇编输出中适当地缩进下
-一条指令：
-
-	asm ("magic %reg1, #42\n\t"
-	     "more_magic %reg2, %reg3"
-	     : /* outputs */ : /* inputs */ : /* clobbers */);
-
-
-		第二十章：条件编译
-
-只要可能，就不要在 .c 文件里面使用预处理条件；这样做让代码更难阅读并且逻辑难以
-跟踪。替代方案是，在头文件定义函数在这些 .c 文件中使用这类的条件表达式，提供空
-操作的桩版本（译注：桩程序，是指用来替换一部分功能的程序段）在 #else 情况下，
-再从 .c 文件中无条件地调用这些函数。编译器会避免生成任何桩调用的代码，产生一致
-的结果，但逻辑将更加清晰。
-
-宁可编译整个函数，而不是部分函数或部分表达式。而不是在一个表达式添加 ifdef，
-解析部分或全部表达式到一个单独的辅助函数，并应用条件到该函数内。
-
-如果你有一个在特定配置中可能是未使用的函数或变量，编译器将警告它定义了但未使用，
-标记这个定义为 __maybe_unused 而不是将它包含在一个预处理条件中。（然而，如果
-一个函数或变量总是未使用的，就直接删除它。）
-
-在代码中，可能的情况下，使用 IS_ENABLED 宏来转化某个 Kconfig 标记为 C 的布尔
-表达式，并在正常的 C 条件中使用它：
-
-	if (IS_ENABLED(CONFIG_SOMETHING)) {
-		...
-	}
-
-编译器会无条件地做常数合并，就像使用 #ifdef 那样，包含或排除代码块，所以这不会
-带来任何运行时开销。然而，这种方法依旧允许 C 编译器查看块内的代码，并检查它的正确
-性（语法，类型，符号引用，等等）。因此，如果条件不满足，代码块内的引用符号将不存在，
-你必须继续使用 #ifdef。
-
-在任何有意义的 #if 或 #ifdef 块的末尾（超过几行），在 #endif 同一行的后面写下
-注释，指出该条件表达式被使用。例如：
-
-	#ifdef CONFIG_SOMETHING
-	...
-	#endif /* CONFIG_SOMETHING */
-
-
-		附录 I：参考
-
-The C Programming Language, 第二版
-作者：Brian W. Kernighan 和 Denni M. Ritchie.
-Prentice Hall, Inc., 1988.
-ISBN 0-13-110362-8 (软皮), 0-13-110370-9 (硬皮).
-
-The Practice of Programming
-作者：Brian W. Kernighan 和 Rob Pike.
-Addison-Wesley, Inc., 1999.
-ISBN 0-201-61586-X.
-
-GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent,
-都可以从 http://www.gnu.org/manual/ 找到
-
-WG14是C语言的国际标准化工作组，URL: http://www.open-std.org/JTC1/SC22/WG14/
-
-Kernel CodingStyle，作者 greg@kroah.com 发表于OLS 2002：
-http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/email-clients.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/email-clients.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/email-clients.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/email-clients.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,210 +0,0 @@
-﻿Chinese translated version of Documentation/email-clients.txt
-
-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/email-clients.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-中文版维护者： 贾威威  Harry Wei <harryxiyou@gmail.com>
-中文版翻译者： 贾威威  Harry Wei <harryxiyou@gmail.com>
-中文版校译者： Yinglin Luan <synmyth@gmail.com>
-		Xiaochen Wang <wangxiaochen0@gmail.com>
-		yaxinsn <yaxinsn@163.com>
-
-以下为正文
----------------------------------------------------------------------
-
-Linux邮件客户端配置信息
-======================================================================
-
-普通配置
-----------------------------------------------------------------------
-Linux内核补丁是通过邮件被提交的，最好把补丁作为邮件体的内嵌文本。有些维护者
-接收附件，但是附件的内容格式应该是"text/plain"。然而，附件一般是不赞成的，
-因为这会使补丁的引用部分在评论过程中变的很困难。
-
-用来发送Linux内核补丁的邮件客户端在发送补丁时应该处于文本的原始状态。例如，
-他们不能改变或者删除制表符或者空格，甚至是在每一行的开头或者结尾。
-
-不要通过"format=flowed"模式发送补丁。这样会引起不可预期以及有害的断行。
-
-不要让你的邮件客户端进行自动换行。这样也会破坏你的补丁。
-
-邮件客户端不能改变文本的字符集编码方式。要发送的补丁只能是ASCII或者UTF-8编码方式，
-如果你使用UTF-8编码方式发送邮件，那么你将会避免一些可能发生的字符集问题。
-
-邮件客户端应该形成并且保持 References: 或者 In-Reply-To: 标题，那么
-邮件话题就不会中断。
-
-复制粘帖(或者剪贴粘帖)通常不能用于补丁，因为制表符会转换为空格。使用xclipboard, xclip
-或者xcutsel也许可以，但是最好测试一下或者避免使用复制粘帖。
-
-不要在使用PGP/GPG署名的邮件中包含补丁。这样会使得很多脚本不能读取和适用于你的补丁。
-（这个问题应该是可以修复的）
-
-在给内核邮件列表发送补丁之前，给自己发送一个补丁是个不错的主意，保存接收到的
-邮件，将补丁用'patch'命令打上，如果成功了，再给内核邮件列表发送。
-
-
-一些邮件客户端提示
-----------------------------------------------------------------------
-这里给出一些详细的MUA配置提示，可以用于给Linux内核发送补丁。这些并不意味是
-所有的软件包配置总结。
-
-说明：
-TUI = 以文本为基础的用户接口
-GUI = 图形界面用户接口
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Alpine (TUI)
-
-配置选项：
-在"Sending Preferences"部分：
-
-- "Do Not Send Flowed Text"必须开启
-- "Strip Whitespace Before Sending"必须关闭
-
-当写邮件时，光标应该放在补丁会出现的地方，然后按下CTRL-R组合键，使指定的
-补丁文件嵌入到邮件中。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Evolution (GUI)
-
-一些开发者成功的使用它发送补丁
-
-当选择邮件选项：Preformat
-  从Format->Heading->Preformatted (Ctrl-7)或者工具栏
-
-然后使用：
-  Insert->Text File... (Alt-n x)插入补丁文件。
-
-你还可以"diff -Nru old.c new.c | xclip"，选择Preformat，然后使用中间键进行粘帖。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Kmail (GUI)
-
-一些开发者成功的使用它发送补丁。
-
-默认设置不为HTML格式是合适的；不要启用它。
-
-当书写一封邮件的时候，在选项下面不要选择自动换行。唯一的缺点就是你在邮件中输入的任何文本
-都不会被自动换行，因此你必须在发送补丁之前手动换行。最简单的方法就是启用自动换行来书写邮件，
-然后把它保存为草稿。一旦你在草稿中再次打开它，它已经全部自动换行了，那么你的邮件虽然没有
-选择自动换行，但是还不会失去已有的自动换行。
-
-在邮件的底部，插入补丁之前，放上常用的补丁定界符：三个连字号(---)。
-
-然后在"Message"菜单条目，选择插入文件，接着选取你的补丁文件。还有一个额外的选项，你可以
-通过它配置你的邮件建立工具栏菜单，还可以带上"insert file"图标。
-
-你可以安全地通过GPG标记附件，但是内嵌补丁最好不要使用GPG标记它们。作为内嵌文本的签发补丁，
-当从GPG中提取7位编码时会使他们变的更加复杂。
-
-如果你非要以附件的形式发送补丁，那么就右键点击附件，然后选中属性，突出"Suggest automatic
-display"，这样内嵌附件更容易让读者看到。
-
-当你要保存将要发送的内嵌文本补丁，你可以从消息列表窗格选择包含补丁的邮件，然后右击选择
-"save as"。你可以使用一个没有更改的包含补丁的邮件，如果它是以正确的形式组成。当你正真在它
-自己的窗口之下察看，那时没有选项可以保存邮件--已经有一个这样的bug被汇报到了kmail的bugzilla
-并且希望这将会被处理。邮件是以只针对某个用户可读写的权限被保存的，所以如果你想把邮件复制到其他地方，
-你不得不把他们的权限改为组或者整体可读。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Lotus Notes (GUI)
-
-不要使用它。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Mutt (TUI)
-
-很多Linux开发人员使用mutt客户端，所以证明它肯定工作的非常漂亮。
-
-Mutt不自带编辑器，所以不管你使用什么编辑器都不应该带有自动断行。大多数编辑器都带有
-一个"insert file"选项，它可以通过不改变文件内容的方式插入文件。
-
-'vim'作为mutt的编辑器：
-  set editor="vi"
-
-  如果使用xclip，敲入以下命令
-  :set paste
-  按中键之前或者shift-insert或者使用
-  :r filename
-
-如果想要把补丁作为内嵌文本。
-(a)ttach工作的很好，不带有"set paste"。
-
-配置选项：
-它应该以默认设置的形式工作。
-然而，把"send_charset"设置为"us-ascii::utf-8"也是一个不错的主意。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Pine (TUI)
-
-Pine过去有一些空格删减问题，但是这些现在应该都被修复了。
-
-如果可以，请使用alpine(pine的继承者)
-
-配置选项：
-- 最近的版本需要消除流程文本
-- "no-strip-whitespace-before-send"选项也是需要的。
-
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Sylpheed (GUI)
-
-- 内嵌文本可以很好的工作（或者使用附件）。
-- 允许使用外部的编辑器。
-- 对于目录较多时非常慢。
-- 如果通过non-SSL连接，无法使用TLS SMTP授权。
-- 在组成窗口中有一个很有用的ruler bar。
-- 给地址本中添加地址就不会正确的了解显示名。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Thunderbird (GUI)
-
-默认情况下，thunderbird很容易损坏文本，但是还有一些方法可以强制它变得更好。
-
-- 在用户帐号设置里，组成和寻址，不要选择"Compose messages in HTML format"。
-
-- 编辑你的Thunderbird配置设置来使它不要拆行使用：user_pref("mailnews.wraplength", 0);
-
-- 编辑你的Thunderbird配置设置，使它不要使用"format=flowed"格式：user_pref("mailnews.
-  send_plaintext_flowed", false);
-
-- 你需要使Thunderbird变为预先格式方式：
-  如果默认情况下你书写的是HTML格式，那不是很难。仅仅从标题栏的下拉框中选择"Preformat"格式。
-  如果默认情况下你书写的是文本格式，你不得把它改为HTML格式（仅仅作为一次性的）来书写新的消息，
-  然后强制使它回到文本格式，否则它就会拆行。要实现它，在写信的图标上使用shift键来使它变为HTML
-  格式，然后标题栏的下拉框中选择"Preformat"格式。
-
-- 允许使用外部的编辑器：
-  针对Thunderbird打补丁最简单的方法就是使用一个"external editor"扩展，然后使用你最喜欢的
-  $EDITOR来读取或者合并补丁到文本中。要实现它，可以下载并且安装这个扩展，然后添加一个使用它的
-  按键View->Toolbars->Customize...最后当你书写信息的时候仅仅点击它就可以了。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-TkRat (GUI)
-
-可以使用它。使用"Insert file..."或者外部的编辑器。
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Gmail (Web GUI)
-
-不要使用它发送补丁。
-
-Gmail网页客户端自动地把制表符转换为空格。
-
-虽然制表符转换为空格问题可以被外部编辑器解决，同时它还会使用回车换行把每行拆分为78个字符。
-
-另一个问题是Gmail还会把任何不是ASCII的字符的信息改为base64编码。它把东西变的像欧洲人的名字。
-
-                                ###
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/filesystems/sysfs.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/filesystems/sysfs.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/filesystems/sysfs.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/filesystems/sysfs.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,372 +0,0 @@
-Chinese translated version of Documentation/filesystems/sysfs.txt
-
-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.
-
-Maintainer: Patrick Mochel	<mochel@osdl.org>
-		Mike Murphy <mamurph@cs.clemson.edu>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/filesystems/sysfs.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-英文版维护者： Patrick Mochel	<mochel@osdl.org>
-		Mike Murphy <mamurph@cs.clemson.edu>
-中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-sysfs - 用于导出内核对象(kobject)的文件系统
-
-Patrick Mochel	<mochel@osdl.org>
-Mike Murphy <mamurph@cs.clemson.edu>
-
-修订:    16 August 2011
-原始版本:   10 January 2003
-
-
-sysfs 简介:
-~~~~~~~~~~
-
-sysfs 是一个最初基于 ramfs 且位于内存的文件系统。它提供导出内核
-数据结构及其属性，以及它们之间的关联到用户空间的方法。
-
-sysfs 始终与 kobject 的底层结构紧密相关。请阅读
-Documentation/kobject.txt 文档以获得更多关于 kobject 接口的
-信息。
-
-
-使用 sysfs
-~~~~~~~~~~~
-
-只要内核配置中定义了 CONFIG_SYSFS ，sysfs 总是被编译进内核。你可
-通过以下命令挂载它:
-
-    mount -t sysfs sysfs /sys
-
-
-创建目录
-~~~~~~~~
-
-任何 kobject 在系统中注册，就会有一个目录在 sysfs 中被创建。这个
-目录是作为该 kobject 的父对象所在目录的子目录创建的，以准确地传递
-内核的对象层次到用户空间。sysfs 中的顶层目录代表着内核对象层次的
-共同祖先；例如：某些对象属于某个子系统。
-
-Sysfs 在与其目录关联的 kernfs_node 对象中内部保存一个指向实现
-目录的 kobject 的指针。以前，这个 kobject 指针被 sysfs 直接用于
-kobject 文件打开和关闭的引用计数。而现在的 sysfs 实现中，kobject
-引用计数只能通过 sysfs_schedule_callback() 函数直接修改。
-
-
-属性
-~~~~
-
-kobject 的属性可在文件系统中以普通文件的形式导出。Sysfs 为属性定义
-了面向文件 I/O 操作的方法，以提供对内核属性的读写。
-
-
-属性应为 ASCII 码文本文件。以一个文件只存储一个属性值为宜。但一个
-文件只包含一个属性值可能影响效率，所以一个包含相同数据类型的属性值
-数组也被广泛地接受。
-
-混合类型、表达多行数据以及一些怪异的数据格式会遭到强烈反对。这样做是
-很丢脸的,而且其代码会在未通知作者的情况下被重写。
-
-
-一个简单的属性结构定义如下:
-
-struct attribute {
-        char                    * name;
-        struct module		*owner;
-        umode_t                 mode;
-};
-
-
-int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
-void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
-
-
-一个单独的属性结构并不包含读写其属性值的方法。子系统最好为增删特定
-对象类型的属性定义自己的属性结构体和封装函数。
-
-例如:驱动程序模型定义的 device_attribute 结构体如下:
-
-struct device_attribute {
-	struct attribute	attr;
-	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t count);
-};
-
-int device_create_file(struct device *, const struct device_attribute *);
-void device_remove_file(struct device *, const struct device_attribute *);
-
-为了定义设备属性，同时定义了一下辅助宏:
-
-#define DEVICE_ATTR(_name, _mode, _show, _store) \
-struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
-
-例如:声明
-
-static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
-
-等同于如下代码：
-
-static struct device_attribute dev_attr_foo = {
-       .attr	= {
-		.name = "foo",
-		.mode = S_IWUSR | S_IRUGO,
-		.show = show_foo,
-		.store = store_foo,
-	},
-};
-
-
-子系统特有的回调函数
-~~~~~~~~~~~~~~~~~~~
-
-当一个子系统定义一个新的属性类型时，必须实现一系列的 sysfs 操作，
-以帮助读写调用实现属性所有者的显示和储存方法。
-
-struct sysfs_ops {
-        ssize_t (*show)(struct kobject *, struct attribute *, char *);
-        ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
-};
-
-[子系统应已经定义了一个 struct kobj_type 结构体作为这个类型的
-描述符，并在此保存 sysfs_ops 的指针。更多的信息参见 kobject 的
-文档]
-
-sysfs 会为这个类型调用适当的方法。当一个文件被读写时，这个方法会
-将一般的kobject 和 attribute 结构体指针转换为适当的指针类型后
-调用相关联的函数。
-
-
-示例:
-
-#define to_dev(obj) container_of(obj, struct device, kobj)
-#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
-
-static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
-                             char *buf)
-{
-        struct device_attribute *dev_attr = to_dev_attr(attr);
-        struct device *dev = to_dev(kobj);
-        ssize_t ret = -EIO;
-
-        if (dev_attr->show)
-                ret = dev_attr->show(dev, dev_attr, buf);
-        if (ret >= (ssize_t)PAGE_SIZE) {
-                print_symbol("dev_attr_show: %s returned bad count\n",
-                                (unsigned long)dev_attr->show);
-        }
-        return ret;
-}
-
-
-
-读写属性数据
-~~~~~~~~~~~~
-
-在声明属性时，必须指定 show() 或 store() 方法，以实现属性的
-读或写。这些方法的类型应该和以下的设备属性定义一样简单。
-
-ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf);
-ssize_t (*store)(struct device *dev, struct device_attribute *attr,
-                 const char *buf, size_t count);
-
-也就是说,他们应只以一个处理对象、一个属性和一个缓冲指针作为参数。
-
-sysfs 会分配一个大小为 (PAGE_SIZE) 的缓冲区并传递给这个方法。
-Sysfs 将会为每次读写操作调用一次这个方法。这使得这些方法在执行时
-会出现以下的行为:
-
-- 在读方面（read(2)），show() 方法应该填充整个缓冲区。回想属性
-  应只导出了一个属性值或是一个同类型属性值的数组，所以这个代价将
-  不会不太高。
-
-  这使得用户空间可以局部地读和任意的向前搜索整个文件。如果用户空间
-  向后搜索到零或使用‘0’偏移执行一个pread(2)操作，show()方法将
-  再次被调用，以重新填充缓存。
-
-- 在写方面（write(2)），sysfs 希望在第一次写操作时得到整个缓冲区。
-  之后 Sysfs 传递整个缓冲区给 store() 方法。
-
-  当要写 sysfs 文件时，用户空间进程应首先读取整个文件，修该想要
-  改变的值，然后回写整个缓冲区。
-
-  在读写属性值时，属性方法的执行应操作相同的缓冲区。
-
-注记:
-
-- 写操作导致的 show() 方法重载，会忽略当前文件位置。
-
-- 缓冲区应总是 PAGE_SIZE 大小。对于i386，这个值为4096。
-
-- show() 方法应该返回写入缓冲区的字节数，也就是 snprintf()的
-  返回值。
-
-- show() 应始终使用 snprintf()。
-
-- store() 应返回缓冲区的已用字节数。如果整个缓存都已填满，只需返回
-  count 参数。
-
-- show() 或 store() 可以返回错误值。当得到一个非法值，必须返回一个
-  错误值。
-
-- 一个传递给方法的对象将会通过 sysfs 调用对象内嵌的引用计数固定在
-  内存中。尽管如此，对象代表的物理实体(如设备)可能已不存在。如有必要，
-  应该实现一个检测机制。
-
-一个简单的(未经实验证实的)设备属性实现如下：
-
-static ssize_t show_name(struct device *dev, struct device_attribute *attr,
-                         char *buf)
-{
-	return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name);
-}
-
-static ssize_t store_name(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
-{
-        snprintf(dev->name, sizeof(dev->name), "%.*s",
-                 (int)min(count, sizeof(dev->name) - 1), buf);
-	return count;
-}
-
-static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
-
-
-（注意：真正的实现不允许用户空间设置设备名。）
-
-顶层目录布局
-~~~~~~~~~~~~
-
-sysfs 目录的安排显示了内核数据结构之间的关系。
-
-顶层 sysfs 目录如下:
-
-block/
-bus/
-class/
-dev/
-devices/
-firmware/
-net/
-fs/
-
-devices/ 包含了一个设备树的文件系统表示。他直接映射了内部的内核
-设备树，反映了设备的层次结构。
-
-bus/ 包含了内核中各种总线类型的平面目录布局。每个总线目录包含两个
-子目录:
-
-	devices/
-	drivers/
-
-devices/ 包含了系统中出现的每个设备的符号链接，他们指向 root/ 下的
-设备目录。
-
-drivers/ 包含了每个已为特定总线上的设备而挂载的驱动程序的目录(这里
-假定驱动没有跨越多个总线类型)。
-
-fs/ 包含了一个为文件系统设立的目录。现在每个想要导出属性的文件系统必须
-在 fs/ 下创建自己的层次结构(参见Documentation/filesystems/fuse.txt)。
-
-dev/ 包含两个子目录： char/ 和 block/。在这两个子目录中，有以
-<major>:<minor> 格式命名的符号链接。这些符号链接指向 sysfs 目录
-中相应的设备。/sys/dev 提供一个通过一个 stat(2) 操作结果，查找
-设备 sysfs 接口快捷的方法。
-
-更多有关 driver-model 的特性信息可以在 Documentation/driver-model/
-中找到。
-
-
-TODO: 完成这一节。
-
-
-当前接口
-~~~~~~~~
-
-以下的接口层普遍存在于当前的sysfs中:
-
-- 设备 (include/linux/device.h)
-----------------------------------
-结构体:
-
-struct device_attribute {
-	struct attribute	attr;
-	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
-			char *buf);
-	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
-			 const char *buf, size_t count);
-};
-
-声明:
-
-DEVICE_ATTR(_name, _mode, _show, _store);
-
-增/删属性:
-
-int device_create_file(struct device *dev, const struct device_attribute * attr);
-void device_remove_file(struct device *dev, const struct device_attribute * attr);
-
-
-- 总线驱动程序 (include/linux/device.h)
---------------------------------------
-结构体:
-
-struct bus_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct bus_type *, char * buf);
-        ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
-};
-
-声明:
-
-BUS_ATTR(_name, _mode, _show, _store)
-
-增/删属性:
-
-int bus_create_file(struct bus_type *, struct bus_attribute *);
-void bus_remove_file(struct bus_type *, struct bus_attribute *);
-
-
-- 设备驱动程序 (include/linux/device.h)
------------------------------------------
-
-结构体:
-
-struct driver_attribute {
-        struct attribute        attr;
-        ssize_t (*show)(struct device_driver *, char * buf);
-        ssize_t (*store)(struct device_driver *, const char * buf,
-                         size_t count);
-};
-
-声明:
-
-DRIVER_ATTR(_name, _mode, _show, _store)
-
-增/删属性：
-
-int driver_create_file(struct device_driver *, const struct driver_attribute *);
-void driver_remove_file(struct device_driver *, const struct driver_attribute *);
-
-
-文档
-~~~~
-
-sysfs 目录结构以及其中包含的属性定义了一个内核与用户空间之间的 ABI。
-对于任何 ABI，其自身的稳定和适当的文档是非常重要的。所有新的 sysfs
-属性必须在 Documentation/ABI 中有文档。详见 Documentation/ABI/README。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/gpio.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/gpio.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/gpio.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/gpio.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,650 +0,0 @@
-Chinese translated version of Documentation/gpio.txt
-
-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.
-
-Maintainer: Grant Likely <grant.likely@secretlab.ca>
-		Linus Walleij <linus.walleij@linaro.org>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/gpio.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-英文版维护者： Grant Likely <grant.likely@secretlab.ca>
-		Linus Walleij <linus.walleij@linaro.org>
-中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-GPIO 接口
-
-本文档提供了一个在Linux下访问GPIO的公约概述。
-
-这些函数以 gpio_* 作为前缀。其他的函数不允许使用这样的前缀或相关的
-__gpio_* 前缀。
-
-
-什么是GPIO?
-==========
-"通用输入/输出口"(GPIO)是一个灵活的由软件控制的数字信号。他们可
-由多种芯片提供,且对于从事嵌入式和定制硬件的 Linux 开发者来说是
-比较熟悉。每个GPIO 都代表一个连接到特定引脚或球栅阵列(BGA)封装中
-“球珠”的一个位。电路板原理图显示了 GPIO 与外部硬件的连接关系。
-驱动可以编写成通用代码，以使板级启动代码可传递引脚配置数据给驱动。
-
-片上系统 (SOC) 处理器对 GPIO 有很大的依赖。在某些情况下,每个
-非专用引脚都可配置为 GPIO,且大多数芯片都最少有一些 GPIO。
-可编程逻辑器件(类似 FPGA) 可以方便地提供 GPIO。像电源管理和
-音频编解码器这样的多功能芯片经常留有一些这样的引脚来帮助那些引脚
-匮乏的 SOC。同时还有通过 I2C 或 SPI 串行总线连接的“GPIO扩展器”
-芯片。大多数 PC 的南桥有一些拥有 GPIO 能力的引脚 (只有BIOS
-固件才知道如何使用他们)。
-
-GPIO 的实际功能因系统而异。通常用法有:
-
-  - 输出值可写 (高电平=1，低电平=0)。一些芯片也有如何驱动这些值的选项,
-    例如只允许输出一个值、支持“线与”及其他取值类似的模式(值得注意的是
-    “开漏”信号)
-
-  - 输入值可读(1、0)。一些芯片支持引脚在配置为“输出”时回读，这对于类似
-    “线与”的情况(以支持双向信号)是非常有用的。GPIO 控制器可能有输入
-    去毛刺/消抖逻辑,这有时需要软件控制。
-
-  - 输入通常可作为 IRQ 信号,一般是沿触发,但有时是电平触发。这样的 IRQ
-    可能配置为系统唤醒事件,以将系统从低功耗状态下唤醒。
-
-  - 通常一个 GPIO 根据不同产品电路板的需求,可以配置为输入或输出,也有仅
-    支持单向的。
-
-  - 大部分 GPIO 可以在持有自旋锁时访问,但是通常由串行总线扩展的 GPIO
-    不允许持有自旋锁。但某些系统也支持这种类型。
-
-对于给定的电路板,每个 GPIO 都用于某个特定的目的,如监控 MMC/SD 卡的
-插入/移除、检测卡的写保护状态、驱动 LED、配置收发器、模拟串行总线、
-复位硬件看门狗、感知开关状态等等。
-
-
-GPIO 公约
-=========
-注意,这个叫做“公约”，因为这不是强制性的，不遵循这个公约是无伤大雅的，
-因为此时可移植性并不重要。GPIO 常用于板级特定的电路逻辑,甚至可能
-随着电路板的版本而改变，且不可能在不同走线的电路板上使用。仅有在少数
-功能上才具有可移植性，其他功能是平台特定。这也是由于“胶合”的逻辑造成的。
-
-此外，这不需要任何的执行框架，只是一个接口。某个平台可能通过一个简单地
-访问芯片寄存器的内联函数来实现它，其他平台可能通过委托一系列不同的GPIO
-控制器的抽象函数来实现它。(有一些可选的代码能支持这种策略的实现,本文档
-后面会介绍，但作为 GPIO 接口的客户端驱动程序必须与它的实现无关。)
-
-也就是说,如果在他们的平台上支持这个公约，驱动应尽可能的使用它。同时，平台
-必须在 Kconfig 中选择 ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB
-选项。那些调用标准 GPIO 函数的驱动应该在 Kconfig 入口中声明依赖GENERIC_GPIO。
-当驱动包含文件:
-
-	#include <linux/gpio.h>
-
-则 GPIO 函数是可用,无论是“真实代码”还是经优化过的语句。如果你遵守
-这个公约，当你的代码完成后，对其他的开发者来说会更容易看懂和维护。
-
-注意，这些操作包含所用平台的 I/O 屏障代码，驱动无须显式地调用他们。
-
-
-标识 GPIO
----------
-GPIO 是通过无符号整型来标识的,范围是 0 到 MAX_INT。保留“负”数
-用于其他目的,例如标识信号“在这个板子上不可用”或指示错误。未接触底层
-硬件的代码会忽略这些整数。
-
-平台会定义这些整数的用法,且通常使用 #define 来定义 GPIO，这样
-板级特定的启动代码可以直接关联相应的原理图。相对来说，驱动应该仅使用
-启动代码传递过来的 GPIO 编号，使用 platform_data 保存板级特定
-引脚配置数据 (同时还有其他须要的板级特定数据)，避免可能出现的问题。
-
-例如一个平台使用编号 32-159 来标识 GPIO,而在另一个平台使用编号0-63
-标识一组 GPIO 控制器,64-79标识另一类 GPIO 控制器,且在一个含有
-FPGA 的特定板子上使用 80-95。编号不一定要连续,那些平台中，也可以
-使用编号2000-2063来标识一个 I2C 接口的 GPIO 扩展器中的 GPIO。
-
-如果你要初始化一个带有无效 GPIO 编号的结构体,可以使用一些负编码
-(如"-EINVAL")，那将使其永远不会是有效。来测试这样一个结构体中的编号
-是否关联一个 GPIO，你可使用以下断言:
-
-	int gpio_is_valid(int number);
-
-如果编号不存在，则请求和释放 GPIO 的函数将拒绝执行相关操作(见下文)。
-其他编号也可能被拒绝,比如一个编号可能存在，但暂时在给定的电路上不可用。
-
-一个平台是否支持多个 GPIO 控制器为平台特定的实现问题，就像是否可以
-在 GPIO 编号空间中有“空洞”和是否可以在运行时添加新的控制器一样。
-这些问题会影响其他事情，包括相邻的 GPIO 编号是否存在等。
-
-使用 GPIO
----------
-对于一个 GPIO，系统应该做的第一件事情就是通过 gpio_request()
-函数分配它，见下文。
-
-接下来是设置I/O方向，这通常是在板级启动代码中为所使用的 GPIO 设置
-platform_device 时完成。
-
-	/* 设置为输入或输出, 返回 0 或负的错误代码 */
-	int gpio_direction_input(unsigned gpio);
-	int gpio_direction_output(unsigned gpio, int value);
-
-返回值为零代表成功，否则返回一个负的错误代码。这个返回值需要检查，因为
-get/set(获取/设置)函数调用没法返回错误,且有可能是配置错误。通常，
-你应该在进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO，在板子
-启动的早期、进程启动前使用他们也是可以的。
-
-对于作为输出的 GPIO，为其提供初始输出值，对于避免在系统启动期间出现
-信号毛刺是很有帮助的。
-
-为了与传统的 GPIO 接口兼容, 在设置一个 GPIO 方向时，如果它还未被申请，
-则隐含了申请那个 GPIO 的操作(见下文)。这种兼容性正在从可选的 gpiolib
-框架中移除。
-
-如果这个 GPIO 编码不存在，或者特定的 GPIO 不能用于那种模式，则方向
-设置可能失败。依赖启动固件来正确地设置方向通常是一个坏主意，因为它可能
-除了启动Linux，并没有做更多的验证工作。(同理, 板子的启动代码可能需要
-将这个复用的引脚设置为 GPIO，并正确地配置上拉/下拉电阻。)
-
-
-访问自旋锁安全的 GPIO
--------------------
-大多数 GPIO 控制器可以通过内存读/写指令来访问。这些指令不会休眠,可以
-安全地在硬(非线程)中断例程和类似的上下文中完成。
-
-对于那些用 gpio_cansleep()测试总是返回失败的 GPIO(见下文)，使用
-以下的函数访问:
-
-	/* GPIO 输入:返回零或非零 */
-	int gpio_get_value(unsigned gpio);
-
-	/* GPIO 输出 */
-	void gpio_set_value(unsigned gpio, int value);
-
-GPIO值是布尔值，零表示低电平，非零表示高电平。当读取一个输出引脚的值时，
-返回值应该是引脚上的值。这个值不总是和输出值相符，因为存在开漏输出信号和
-输出延迟问题。
-
-以上的 get/set 函数无错误返回值，因为之前 gpio_direction_*()应已检查过
-其是否为“无效GPIO”。此外，还需要注意的是并不是所有平台都可以从输出引脚
-中读取数据，对于不能读取的引脚应总返回零。另外，对那些在原子上下文中无法
-安全访问的 GPIO (译者注：因为访问可能导致休眠)使用这些函数是不合适的
-(见下文)。
-
-在 GPIO 编号(还有输出、值)为常数的情况下,鼓励通过平台特定的实现来优化
-这两个函数来访问 GPIO 值。这种情况(读写一个硬件寄存器)下只需要几条指令
-是很正常的,且无须自旋锁。这种优化函数比起那些在子程序上花费许多指令的
-函数可以使得模拟接口(译者注:例如 GPIO 模拟 I2C、1-wire 或 SPI)的
-应用(在空间和时间上都)更具效率。
-
-
-访问可能休眠的 GPIO
------------------
-某些 GPIO 控制器必须通过基于总线(如 I2C 或 SPI)的消息访问。读或写这些
-GPIO 值的命令需要等待其信息排到队首才发送命令，再获得其反馈。期间需要
-休眠，这不能在 IRQ 例程(中断上下文)中执行。
-
-支持此类 GPIO 的平台通过以下函数返回非零值来区分出这种 GPIO。(此函数需要
-一个之前通过 gpio_request 分配到的有效 GPIO 编号):
-
-	int gpio_cansleep(unsigned gpio);
-
-为了访问这种 GPIO,内核定义了一套不同的函数:
-
-	/* GPIO 输入:返回零或非零 ,可能会休眠 */
-	int gpio_get_value_cansleep(unsigned gpio);
-
-	/* GPIO 输出,可能会休眠 */
-	void gpio_set_value_cansleep(unsigned gpio, int value);
-
-
-访问这样的 GPIO 需要一个允许休眠的上下文，例如线程 IRQ 处理例程，并用以上的
-访问函数替换那些没有 cansleep()后缀的自旋锁安全访问函数。
-
-除了这些访问函数可能休眠，且它们操作的 GPIO 不能在硬件 IRQ 处理例程中访问的
-事实，这些处理例程实际上和自旋锁安全的函数是一样的。
-
-** 除此之外 ** 调用设置和配置此类 GPIO 的函数也必须在允许休眠的上下文中，
-因为它们可能也需要访问 GPIO 控制器芯片: (这些设置函数通常在板级启动代码或者
-驱动探测/断开代码中，所以这是一个容易满足的约束条件。)
-
-	gpio_direction_input()
-	gpio_direction_output()
-	gpio_request()
-
-## 	gpio_request_one()
-##	gpio_request_array()
-## 	gpio_free_array()
-
-	gpio_free()
-	gpio_set_debounce()
-
-
-
-声明和释放 GPIO
-----------------------------
-为了有助于捕获系统配置错误,定义了两个函数。
-
-	/* 申请 GPIO, 返回 0 或负的错误代码.
-	 * 非空标签可能有助于诊断.
-	 */
-	int gpio_request(unsigned gpio, const char *label);
-
-	/* 释放之前声明的 GPIO */
-	void gpio_free(unsigned gpio);
-
-将无效的 GPIO 编码传递给 gpio_request()会导致失败，申请一个已使用这个
-函数声明过的 GPIO 也会失败。gpio_request()的返回值必须检查。你应该在
-进程上下文中调用这些函数。然而,对于自旋锁安全的 GPIO,在板子启动的早期、
-进入进程之前是可以申请的。
-
-这个函数完成两个基本的目标。一是标识那些实际上已作为 GPIO 使用的信号线，
-这样便于更好地诊断;系统可能需要服务几百个可用的 GPIO，但是对于任何一个
-给定的电路板通常只有一些被使用。另一个目的是捕获冲突，查明错误:如两个或
-更多驱动错误地认为他们已经独占了某个信号线,或是错误地认为移除一个管理着
-某个已激活信号的驱动是安全的。也就是说，申请 GPIO 的作用类似一种锁机制。
-
-某些平台可能也使用 GPIO 作为电源管理激活信号(例如通过关闭未使用芯片区和
-简单地关闭未使用时钟)。
-
-对于 GPIO 使用 pinctrl 子系统已知的引脚，子系统应该被告知其使用情况；
-一个 gpiolib 驱动的 .request()操作应调用 pinctrl_request_gpio()，
-而 gpiolib 驱动的 .free()操作应调用 pinctrl_free_gpio()。pinctrl
-子系统允许 pinctrl_request_gpio()在某个引脚或引脚组以复用形式“属于”
-一个设备时都成功返回。
-
-任何须将 GPIO 信号导向适当引脚的引脚复用硬件的编程应该发生在 GPIO
-驱动的 .direction_input()或 .direction_output()函数中，以及
-任何输出 GPIO 值的设置之后。这样可使从引脚特殊功能到 GPIO 的转换
-不会在引脚产生毛刺波形。有时当用一个 GPIO 实现其信号驱动一个非 GPIO
-硬件模块的解决方案时，就需要这种机制。
-
-某些平台允许部分或所有 GPIO 信号使用不同的引脚。类似的，GPIO 或引脚的
-其他方面也需要配置，如上拉/下拉。平台软件应该在对这些 GPIO 调用
-gpio_request()前将这类细节配置好，例如使用 pinctrl 子系统的映射表，
-使得 GPIO 的用户无须关注这些细节。
-
-还有一个值得注意的是在释放 GPIO 前，你必须停止使用它。
-
-
-注意:申请一个 GPIO 并没有以任何方式配置它，只不过标识那个 GPIO 处于使用
-状态。必须有另外的代码来处理引脚配置(如控制 GPIO 使用的引脚、上拉/下拉)。
-考虑到大多数情况下声明 GPIO 之后就会立即配置它们,所以定义了以下三个辅助函数:
-
-	/* 申请一个 GPIO 信号, 同时通过特定的'flags'初始化配置,
-	 * 其他和 gpio_request()的参数和返回值相同
-	 *
-	 */
-	int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
-
-	/* 在单个函数中申请多个 GPIO
-	 */
-	int gpio_request_array(struct gpio *array, size_t num);
-
-	/* 在单个函数中释放多个 GPIO
-	 */
-	void gpio_free_array(struct gpio *array, size_t num);
-
-这里 'flags' 当前定义可指定以下属性:
-
-	* GPIOF_DIR_IN		- 配置方向为输入
-	* GPIOF_DIR_OUT		- 配置方向为输出
-
-	* GPIOF_INIT_LOW	- 在作为输出时,初始值为低电平
-	* GPIOF_INIT_HIGH	- 在作为输出时,初始值为高电平
-	* GPIOF_OPEN_DRAIN	- gpio引脚为开漏信号
-	* GPIOF_OPEN_SOURCE	- gpio引脚为源极开路信号
-
-	* GPIOF_EXPORT_DIR_FIXED	- 将 gpio 导出到 sysfs，并保持方向
-	* GPIOF_EXPORT_DIR_CHANGEABLE	- 同样是导出, 但允许改变方向
-
-因为 GPIOF_INIT_* 仅有在配置为输出的时候才存在,所以有效的组合为:
-
-	* GPIOF_IN		- 配置为输入
-	* GPIOF_OUT_INIT_LOW	- 配置为输出,并初始化为低电平
-	* GPIOF_OUT_INIT_HIGH	- 配置为输出,并初始化为高电平
-
-当设置 flag 为 GPIOF_OPEN_DRAIN 时，则假设引脚是开漏信号。这样的引脚
-将不会在输出模式下置1。这样的引脚需要连接上拉电阻。通过使能这个标志，gpio库
-将会在被要求输出模式下置1时将引脚变为输入状态来使引脚置高。引脚在输出模式下
-通过置0使其输出低电平。
-
-当设置 flag 为 GPIOF_OPEN_SOURCE 时，则假设引脚为源极开路信号。这样的引脚
-将不会在输出模式下置0。这样的引脚需要连接下拉电阻。通过使能这个标志，gpio库
-将会在被要求输出模式下置0时将引脚变为输入状态来使引脚置低。引脚在输出模式下
-通过置1使其输出高电平。
-
-将来这些标志可能扩展到支持更多的属性。
-
-更进一步,为了更简单地声明/释放多个 GPIO,'struct gpio'被引进来封装所有
-这三个领域:
-
-	struct gpio {
-		unsigned	gpio;
-		unsigned long	flags;
-		const char	*label;
-	};
-
-一个典型的用例:
-
-	static struct gpio leds_gpios[] = {
-		{ 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* 默认开启 */
-		{ 33, GPIOF_OUT_INIT_LOW,  "Green LED" }, /* 默认关闭 */
-		{ 34, GPIOF_OUT_INIT_LOW,  "Red LED"   }, /* 默认关闭 */
-		{ 35, GPIOF_OUT_INIT_LOW,  "Blue LED"  }, /* 默认关闭 */
-		{ ... },
-	};
-
-	err = gpio_request_one(31, GPIOF_IN, "Reset Button");
-	if (err)
-		...
-
-	err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
-	if (err)
-		...
-
-	gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
-
-
-GPIO 映射到 IRQ
---------------------
-GPIO 编号是无符号整数;IRQ 编号也是。这些构成了两个逻辑上不同的命名空间
-(GPIO 0 不一定使用 IRQ 0)。你可以通过以下函数在它们之间实现映射:
-
-	/* 映射 GPIO 编号到 IRQ 编号 */
-	int gpio_to_irq(unsigned gpio);
-
-	/* 映射 IRQ 编号到 GPIO 编号 (尽量避免使用) */
-	int irq_to_gpio(unsigned irq);
-
-它们的返回值为对应命名空间的相关编号，或是负的错误代码(如果无法映射)。
-(例如,某些 GPIO 无法做为 IRQ 使用。)以下的编号错误是未经检测的:使用一个
-未通过 gpio_direction_input()配置为输入的 GPIO 编号，或者使用一个
-并非来源于gpio_to_irq()的 IRQ 编号。
-
-这两个映射函数可能会在信号编号的加减计算过程上花些时间。它们不可休眠。
-
-gpio_to_irq()返回的非错误值可以传递给 request_irq()或者 free_irq()。
-它们通常通过板级特定的初始化代码存放到平台设备的 IRQ 资源中。注意:IRQ
-触发选项是 IRQ 接口的一部分，如 IRQF_TRIGGER_FALLING，系统唤醒能力
-也是如此。
-
-irq_to_gpio()返回的非错误值大多数通常可以被 gpio_get_value()所使用，
-比如在 IRQ 是沿触发时初始化或更新驱动状态。注意某些平台不支持反映射,所以
-你应该尽量避免使用它。
-
-
-模拟开漏信号
-----------------------------
-有时在只有低电平信号作为实际驱动结果(译者注:多个输出连接于一点，逻辑电平
-结果为所有输出的逻辑与)的时候,共享的信号线需要使用“开漏”信号。(该术语
-适用于 CMOS 管；而 TTL 用“集电极开路”。)一个上拉电阻使信号为高电平。这
-有时被称为“线与”。实际上，从负逻辑(低电平为真)的角度来看，这是一个“线或”。
-
-一个开漏信号的常见例子是共享的低电平使能 IRQ 信号线。此外,有时双向数据总线
-信号也使用漏极开路信号。
-
-某些 GPIO 控制器直接支持开漏输出，还有许多不支持。当你需要开漏信号，但
-硬件又不直接支持的时候，一个常用的方法是用任何即可作输入也可作输出的 GPIO
-引脚来模拟:
-
- LOW:	gpio_direction_output(gpio, 0) ... 这代码驱动信号并覆盖
-	上拉配置。
-
- HIGH:	gpio_direction_input(gpio) ... 这代码关闭输出,所以上拉电阻
-	(或其他的一些器件)控制了信号。
-
-如果你将信号线“驱动”为高电平，但是 gpio_get_value(gpio)报告了一个
-低电平(在适当的上升时间后)，你就可以知道是其他的一些组件将共享信号线拉低了。
-这不一定是错误的。一个常见的例子就是 I2C 时钟的延长：一个需要较慢时钟的
-从设备延迟 SCK 的上升沿，而 I2C 主设备相应地调整其信号传输速率。
-
-
-这些公约忽略了什么?
-================
-这些公约忽略的最大一件事就是引脚复用，因为这属于高度芯片特定的属性且
-没有可移植性。某个平台可能不需要明确的复用信息；有的对于任意给定的引脚
-可能只有两个功能选项；有的可能每个引脚有八个功能选项；有的可能可以将
-几个引脚中的任何一个作为给定的 GPIO。(是的，这些例子都来自于当前运行
-Linux 的系统。)
-
-在某些系统中,与引脚复用相关的是配置和使能集成的上、下拉模式。并不是所有
-平台都支持这种模式,或者不会以相同的方式来支持这种模式；且任何给定的电路板
-可能使用外置的上拉(或下拉)电阻,这时芯片上的就不应该使用。(当一个电路需要
-5kOhm 的拉动电阻,芯片上的 100 kOhm 电阻就不能做到。)同样的，驱动能力
-(2 mA vs 20 mA)和电压(1.8V vs 3.3V)是平台特定问题,就像模型一样在
-可配置引脚和 GPIO 之间(没)有一一对应的关系。
-
-还有其他一些系统特定的机制没有在这里指出，例如上述的输入去毛刺和线与输出
-选项。硬件可能支持批量读或写 GPIO，但是那一般是配置相关的：对于处于同一
-块区(bank)的GPIO。(GPIO 通常以 16 或 32 个组成一个区块，一个给定的
-片上系统一般有几个这样的区块。)某些系统可以通过输出 GPIO 触发 IRQ，
-或者从并非以 GPIO 管理的引脚取值。这些机制的相关代码没有必要具有可移植性。
-
-当前，动态定义 GPIO 并不是标准的，例如作为配置一个带有某些 GPIO 扩展器的
-附加电路板的副作用。
-
-GPIO 实现者的框架 (可选)
-=====================
-前面提到了，有一个可选的实现框架，让平台使用相同的编程接口，更加简单地支持
-不同种类的 GPIO 控制器。这个框架称为"gpiolib"。
-
-作为一个辅助调试功能，如果 debugfs 可用，就会有一个 /sys/kernel/debug/gpio
-文件。通过这个框架，它可以列出所有注册的控制器,以及当前正在使用中的 GPIO
-的状态。
-
-
-控制器驱动: gpio_chip
--------------------
-在框架中每个 GPIO 控制器都包装为一个 "struct gpio_chip"，他包含了
-该类型的每个控制器的常用信息:
-
- - 设置 GPIO 方向的方法
- - 用于访问 GPIO 值的方法
- - 告知调用其方法是否可能休眠的标志
- - 可选的 debugfs 信息导出方法 (显示类似上拉配置一样的额外状态)
- - 诊断标签
-
-也包含了来自 device.platform_data 的每个实例的数据：它第一个 GPIO 的
-编号和它可用的 GPIO 的数量。
-
-实现 gpio_chip 的代码应支持多控制器实例，这可能使用驱动模型。那些代码要
-配置每个 gpio_chip，并发起gpiochip_add()。卸载一个 GPIO 控制器很少见，
-但在必要的时候可以使用 gpiochip_remove()。
-
-大部分 gpio_chip 是一个实例特定结构体的一部分，而并不将 GPIO 接口单独
-暴露出来,比如编址、电源管理等。类似编解码器这样的芯片会有复杂的非 GPIO
-状态。
-
-任何一个 debugfs 信息导出方法通常应该忽略还未申请作为 GPIO 的信号线。
-他们可以使用 gpiochip_is_requested()测试，当这个 GPIO 已经申请过了
-就返回相关的标签，否则返回 NULL。
-
-
-平台支持
--------
-为了支持这个框架，一个平台的 Kconfig 文件将会 "select"(选择)
-ARCH_REQUIRE_GPIOLIB 或 ARCH_WANT_OPTIONAL_GPIOLIB，并让它的
-<asm/gpio.h> 包含 <asm-generic/gpio.h>，同时定义三个方法:
-gpio_get_value()、gpio_set_value()和 gpio_cansleep()。
-
-它也应提供一个 ARCH_NR_GPIOS 的定义值，这样可以更好地反映该平台 GPIO
-的实际数量,节省静态表的空间。(这个定义值应该包含片上系统内建 GPIO 和
-GPIO 扩展器中的数据。)
-
-ARCH_REQUIRE_GPIOLIB 意味着 gpiolib 核心在这个构架中将总是编译进内核。
-
-ARCH_WANT_OPTIONAL_GPIOLIB 意味着 gpiolib 核心默认关闭,且用户可以
-使能它,并将其编译进内核(可选)。
-
-如果这些选项都没被选择,该平台就不通过 GPIO-lib 支持 GPIO,且代码不可以
-被用户使能。
-
-以下这些方法的实现可以直接使用框架代码,并总是通过 gpio_chip 调度:
-
-  #define gpio_get_value	__gpio_get_value
-  #define gpio_set_value	__gpio_set_value
-  #define gpio_cansleep		__gpio_cansleep
-
-这些定义可以用更理想的实现方法替代，那就是使用经过逻辑优化的内联函数来访问
-基于特定片上系统的 GPIO。例如,若引用的 GPIO (寄存器位偏移)是常量“12”，
-读取或设置它可能只需少则两或三个指令，且不会休眠。当这样的优化无法实现时，
-那些函数必须使用框架提供的代码，那就至少要几十条指令才可以实现。对于用 GPIO
-模拟的 I/O 接口, 如此精简指令是很有意义的。
-
-对于片上系统，平台特定代码为片上 GPIO 每个区(bank)定义并注册 gpio_chip
-实例。那些 GPIO 应该根据芯片厂商的文档进行编码/标签,并直接和电路板原理图
-对应。他们应该开始于零并终止于平台特定的限制。这些 GPIO(代码)通常从
-arch_initcall()或者更早的地方集成进平台初始化代码，使这些 GPIO 总是可用，
-且他们通常可以作为 IRQ 使用。
-
-板级支持
--------
-对于外部 GPIO 控制器(例如 I2C 或 SPI 扩展器、专用芯片、多功能器件、FPGA
-或 CPLD)，大多数常用板级特定代码都可以注册控制器设备，并保证他们的驱动知道
-gpiochip_add()所使用的 GPIO 编号。他们的起始编号通常跟在平台特定的 GPIO
-编号之后。
-
-例如板级启动代码应该创建结构体指明芯片公开的 GPIO 范围，并使用 platform_data
-将其传递给每个 GPIO 扩展器芯片。然后芯片驱动中的 probe()例程可以将这个
-数据传递给 gpiochip_add()。
-
-初始化顺序很重要。例如，如果一个设备依赖基于 I2C 的(扩展)GPIO，那么它的
-probe()例程就应该在那个 GPIO 有效以后才可以被调用。这意味着设备应该在
-GPIO 可以工作之后才可被注册。解决这类依赖的的一种方法是让这种 gpio_chip
-控制器向板级特定代码提供 setup()和 teardown()回调函数。一旦所有必须的
-资源可用之后，这些板级特定的回调函数将会注册设备，并可以在这些 GPIO 控制器
-设备变成无效时移除它们。
-
-
-用户空间的 Sysfs 接口(可选)
-========================
-使用“gpiolib”实现框架的平台可以选择配置一个 GPIO 的 sysfs 用户接口。
-这不同于 debugfs 接口，因为它提供的是对 GPIO方向和值的控制，而不只显示
-一个GPIO 的状态摘要。此外,它可以出现在没有调试支持的产品级系统中。
-
-例如，通过适当的系统硬件文档，用户空间可以知道 GIOP #23 控制 Flash
-存储器的写保护(用于保护其中 Bootloader 分区)。产品的系统升级可能需要
-临时解除这个保护：首先导入一个 GPIO，改变其输出状态，然后在重新使能写保护
-前升级代码。通常情况下,GPIO #23 是不会被触及的，并且内核也不需要知道他。
-
-根据适当的硬件文档，某些系统的用户空间 GPIO 可以用于确定系统配置数据，
-这些数据是标准内核不知道的。在某些任务中，简单的用户空间 GPIO 驱动可能是
-系统真正需要的。
-
-注意：标准内核驱动中已经存在通用的“LED 和按键”GPIO 任务，分别是:
-"leds-gpio" 和 "gpio_keys"。请使用这些来替代直接访问 GPIO，因为集成在
-内核框架中的这类驱动比你在用户空间的代码更好。
-
-
-Sysfs 中的路径
---------------
-在/sys/class/gpio 中有 3 类入口:
-
-   -	用于在用户空间控制 GPIO 的控制接口;
-
-   -	GPIOs 本身;以及
-
-   -	GPIO 控制器 ("gpio_chip" 实例)。
-
-除了这些标准的文件,还包含“device”符号链接。
-
-控制接口是只写的:
-
-    /sys/class/gpio/
-
-    	"export" ... 用户空间可以通过写其编号到这个文件，要求内核导出
-		一个 GPIO 的控制到用户空间。
-
-		例如: 如果内核代码没有申请 GPIO #19,"echo 19 > export"
-		将会为 GPIO #19 创建一个 "gpio19" 节点。
-
-    	"unexport" ... 导出到用户空间的逆操作。
-
-		例如: "echo 19 > unexport" 将会移除使用"export"文件导出的
-		"gpio19" 节点。
-
-GPIO 信号的路径类似 /sys/class/gpio/gpio42/ (对于 GPIO #42 来说)，
-并有如下的读/写属性:
-
-    /sys/class/gpio/gpioN/
-
-	"direction" ... 读取得到 "in" 或 "out"。这个值通常运行写入。
-		写入"out" 时,其引脚的默认输出为低电平。为了确保无故障运行，
-		"low" 或 "high" 的电平值应该写入 GPIO 的配置，作为初始输出值。
-
-		注意:如果内核不支持改变 GPIO 的方向，或者在导出时内核代码没有
-		明确允许用户空间可以重新配置 GPIO 方向，那么这个属性将不存在。
-
-	"value" ... 读取得到 0 (低电平) 或 1 (高电平)。如果 GPIO 配置为
-		输出,这个值允许写操作。任何非零值都以高电平看待。
-
-		如果引脚可以配置为中断信号，且如果已经配置了产生中断的模式
-		（见"edge"的描述），你可以对这个文件使用轮询操作(poll(2))，
-		且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2))，
-		请在 events 中设置 POLLPRI 和 POLLERR。如果你使用轮询操作
-		(select(2))，请在 exceptfds 设置你期望的文件描述符。在
-		轮询操作(poll(2))返回之后，既可以通过 lseek(2)操作读取
-		sysfs 文件的开始部分，也可以关闭这个文件并重新打开它来读取数据。
-
-	"edge" ... 读取得到“none”、“rising”、“falling”或者“both”。
-		将这些字符串写入这个文件可以选择沿触发模式，会使得轮询操作
-		(select(2))在"value"文件中返回。
-
-		这个文件仅有在这个引脚可以配置为可产生中断输入引脚时，才存在。
-
-	"active_low" ... 读取得到 0 (假) 或 1 (真)。写入任何非零值可以
-		翻转这个属性的(读写)值。已存在或之后通过"edge"属性设置了"rising"
-		和 "falling" 沿触发模式的轮询操作(poll(2))将会遵循这个设置。
-
-GPIO 控制器的路径类似 /sys/class/gpio/gpiochip42/ (对于从#42 GPIO
-开始实现控制的控制器),并有着以下只读属性:
-
-    /sys/class/gpio/gpiochipN/
-
-    	"base" ... 与以上的 N 相同,代表此芯片管理的第一个 GPIO 的编号
-
-    	"label" ... 用于诊断 (并不总是只有唯一值)
-
-    	"ngpio" ... 此控制器所管理的 GPIO 数量(而 GPIO 编号从 N 到
-    		N + ngpio - 1)
-
-大多数情况下,电路板的文档应当标明每个 GPIO 的使用目的。但是那些编号并不总是
-固定的,例如在扩展卡上的 GPIO会根据所使用的主板或所在堆叠架构中其他的板子而
-有所不同。在这种情况下,你可能需要使用 gpiochip 节点(尽可能地结合电路图)来
-确定给定信号所用的 GPIO 编号。
-
-
-从内核代码中导出
--------------
-内核代码可以明确地管理那些已通过 gpio_request()申请的 GPIO 的导出:
-
-	/* 导出 GPIO 到用户空间 */
-	int gpio_export(unsigned gpio, bool direction_may_change);
-
-	/* gpio_export()的逆操作 */
-	void gpio_unexport();
-
-	/* 创建一个 sysfs 连接到已导出的 GPIO 节点 */
-	int gpio_export_link(struct device *dev, const char *name,
-		unsigned gpio)
-
-在一个内核驱动申请一个 GPIO 之后，它可以通过 gpio_export()使其在 sysfs
-接口中可见。该驱动可以控制信号方向是否可修改。这有助于防止用户空间代码无意间
-破坏重要的系统状态。
-
-这个明确的导出有助于(通过使某些实验更容易来)调试，也可以提供一个始终存在的接口，
-与文档配合作为板级支持包的一部分。
-
-在 GPIO 被导出之后，gpio_export_link()允许在 sysfs 文件系统的任何地方
-创建一个到这个 GPIO sysfs 节点的符号链接。这样驱动就可以通过一个描述性的
-名字，在 sysfs 中他们所拥有的设备下提供一个(到这个 GPIO sysfs 节点的)接口。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/HOWTO linux-libre-4.10-rc8-gnu/Documentation/zh_CN/HOWTO
--- linux-libre-4.9-gnu/Documentation/zh_CN/HOWTO	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/HOWTO	1969-12-31 19:00:00.000000000 -0500
@@ -1,536 +0,0 @@
-﻿Chinese translated version of Documentation/HOWTO
-
-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.
-
-Maintainer: Greg Kroah-Hartman <greg@kroah.com>
-Chinese maintainer: Li Yang <leoli@freescale.com>
----------------------------------------------------------------------
-Documentation/HOWTO 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
-中文版维护者： 李阳  Li Yang <leoli@freescale.com>
-中文版翻译者： 李阳  Li Yang <leoli@freescale.com>
-中文版校译者： 钟宇  TripleX Chung <xxx.phy@gmail.com>
-               陈琦  Maggie Chen <chenqi@beyondsoft.com>
-               王聪  Wang Cong <xiyou.wangcong@gmail.com>
-
-以下为正文
----------------------------------------------------------------------
-
-如何参与Linux内核开发
----------------------
-
-这是一篇将如何参与Linux内核开发的相关问题一网打尽的终极秘笈。它将指导你
-成为一名Linux内核开发者，并且学会如何同Linux内核开发社区合作。它尽可能不
-包括任何关于内核编程的技术细节，但会给你指引一条获得这些知识的正确途径。
-
-如果这篇文章中的任何内容不再适用，请给文末列出的文件维护者发送补丁。
-
-
-入门
-----
-
-你想了解如何成为一名Linux内核开发者？或者老板吩咐你“给这个设备写个Linux
-驱动程序”？这篇文章的目的就是教会你达成这些目标的全部诀窍，它将描述你需
-要经过的流程以及给出如何同内核社区合作的一些提示。它还将试图解释内核社区
-为何这样运作。
-
-Linux内核大部分是由C语言写成的，一些体系结构相关的代码用到了汇编语言。要
-参与内核开发，你必须精通C语言。除非你想为某个架构开发底层代码，否则你并
-不需要了解（任何体系结构的）汇编语言。下面列举的书籍虽然不能替代扎实的C
-语言教育和多年的开发经验，但如果需要的话，做为参考还是不错的：
- - "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
-   《C程序设计语言（第2版·新版）》（徐宝文 李志 译）[机械工业出版社]
- - "Practical C Programming" by Steve Oualline [O'Reilly]
-   《实用C语言编程（第三版）》（郭大海 译）[中国电力出版社]
- - "C:  A Reference Manual" by Harbison and Steele [Prentice Hall]
-   《C语言参考手册（原书第5版）》（邱仲潘 等译）[机械工业出版社]
-
-Linux内核使用GNU C和GNU工具链开发。虽然它遵循ISO C89标准，但也用到了一些
-标准中没有定义的扩展。内核是自给自足的C环境，不依赖于标准C库的支持，所以
-并不支持C标准中的部分定义。比如long long类型的大数除法和浮点运算就不允许
-使用。有时候确实很难弄清楚内核对工具链的要求和它所使用的扩展，不幸的是目
-前还没有明确的参考资料可以解释它们。请查阅gcc信息页（使用“info gcc”命令
-显示）获得一些这方面信息。
-
-请记住你是在学习怎么和已经存在的开发社区打交道。它由一群形形色色的人组成，
-他们对代码、风格和过程有着很高的标准。这些标准是在长期实践中总结出来的，
-适应于地理上分散的大型开发团队。它们已经被很好得整理成档，建议你在开发
-之前尽可能多的学习这些标准，而不要期望别人来适应你或者你公司的行为方式。
-
-
-法律问题
---------
-
-Linux内核源代码都是在GPL（通用公共许可证）的保护下发布的。要了解这种许可
-的细节请查看源代码主目录下的COPYING文件。如果你对它还有更深入问题请联系
-律师，而不要在Linux内核邮件组上提问。因为邮件组里的人并不是律师，不要期
-望他们的话有法律效力。
-
-对于GPL的常见问题和解答，请访问以下链接：
-	http://www.gnu.org/licenses/gpl-faq.html
-
-
-文档
-----
-
-Linux内核代码中包含有大量的文档。这些文档对于学习如何与内核社区互动有着
-不可估量的价值。当一个新的功能被加入内核，最好把解释如何使用这个功能的文
-档也放进内核。当内核的改动导致面向用户空间的接口发生变化时，最好将相关信
-息或手册页(manpages)的补丁发到mtk.manpages@gmail.com，以向手册页(manpages)
-的维护者解释这些变化。
-
-以下是内核代码中需要阅读的文档：
-  README
-    文件简要介绍了Linux内核的背景，并且描述了如何配置和编译内核。内核的
-    新用户应该从这里开始。
-
-  Documentation/Changes
-    文件给出了用来编译和使用内核所需要的最小软件包列表。
-
-  Documentation/CodingStyle
-    描述Linux内核的代码风格和理由。所有新代码需要遵守这篇文档中定义的规
-    范。大多数维护者只会接收符合规定的补丁，很多人也只会帮忙检查符合风格
-    的代码。
-
-  Documentation/SubmittingPatches
-  Documentation/SubmittingDrivers
-    这两份文档明确描述如何创建和发送补丁，其中包括（但不仅限于)：
-       - 邮件内容
-       - 邮件格式
-       - 选择收件人
-    遵守这些规定并不能保证提交成功（因为所有补丁需要通过严格的内容和风格
-    审查），但是忽视他们几乎就意味着失败。
-
-    其他关于如何正确地生成补丁的优秀文档包括：
-    "The Perfect Patch"
-        http://www.ozlabs.org/~akpm/stuff/tpp.txt
-    "Linux kernel patch submission format"
-        http://linux.yyz.us/patch-format.html
-
-  Documentation/stable_api_nonsense.txt
-    论证内核为什么特意不包括稳定的内核内部API，也就是说不包括像这样的特
-    性：
-       - 子系统中间层（为了兼容性？）
-       - 在不同操作系统间易于移植的驱动程序
-       - 减缓（甚至阻止）内核代码的快速变化
-    这篇文档对于理解Linux的开发哲学至关重要。对于将开发平台从其他操作系
-    统转移到Linux的人来说也很重要。
-
-  Documentation/SecurityBugs
-    如果你认为自己发现了Linux内核的安全性问题，请根据这篇文档中的步骤来
-    提醒其他内核开发者并帮助解决这个问题。
-
-  Documentation/ManagementStyle
-    描述内核维护者的工作方法及其共有特点。这对于刚刚接触内核开发（或者对
-    它感到好奇）的人来说很重要，因为它解释了很多对于内核维护者独特行为的
-    普遍误解与迷惑。
-
-  Documentation/stable_kernel_rules.txt
-    解释了稳定版内核发布的规则，以及如何将改动放入这些版本的步骤。
-
-  Documentation/kernel-docs.txt
-    有助于内核开发的外部文档列表。如果你在内核自带的文档中没有找到你想找
-    的内容，可以查看这些文档。
-
-  Documentation/applying-patches.txt
-    关于补丁是什么以及如何将它打在不同内核开发分支上的好介绍
-
-内核还拥有大量从代码自动生成的文档。它包含内核内部API的全面介绍以及如何
-妥善处理加锁的规则。生成的文档会放在 Documentation/DocBook/目录下。在内
-核源码的主目录中使用以下不同命令将会分别生成PDF、Postscript、HTML和手册
-页等不同格式的文档：
-    make pdfdocs
-    make psdocs
-    make htmldocs
-    make mandocs
-
-
-如何成为内核开发者
-------------------
-如果你对Linux内核开发一无所知，你应该访问“Linux内核新手”计划：
-	http://kernelnewbies.org
-它拥有一个可以问各种最基本的内核开发问题的邮件列表（在提问之前一定要记得
-查找已往的邮件，确认是否有人已经回答过相同的问题）。它还拥有一个可以获得
-实时反馈的IRC聊天频道，以及大量对于学习Linux内核开发相当有帮助的文档。
-
-网站简要介绍了源代码组织结构、子系统划分以及目前正在进行的项目（包括内核
-中的和单独维护的）。它还提供了一些基本的帮助信息，比如如何编译内核和打补
-丁。
-
-如果你想加入内核开发社区并协助完成一些任务，却找不到从哪里开始，可以访问
-“Linux内核房管员”计划：
-	http://kernelnewbies.org/KernelJanitors
-这是极佳的起点。它提供一个相对简单的任务列表，列出内核代码中需要被重新
-整理或者改正的地方。通过和负责这个计划的开发者们一同工作，你会学到将补丁
-集成进内核的基本原理。如果还没有决定下一步要做什么的话，你还可能会得到方
-向性的指点。
-
-如果你已经有一些现成的代码想要放到内核中，但是需要一些帮助来使它们拥有正
-确的格式。请访问“内核导师”计划。这个计划就是用来帮助你完成这个目标的。它
-是一个邮件列表，地址如下：
-	http://selenic.com/mailman/listinfo/kernel-mentors
-
-在真正动手修改内核代码之前，理解要修改的代码如何运作是必需的。要达到这个
-目的，没什么办法比直接读代码更有效了（大多数花招都会有相应的注释），而且
-一些特制的工具还可以提供帮助。例如，“Linux代码交叉引用”项目就是一个值得
-特别推荐的帮助工具，它将源代码显示在有编目和索引的网页上。其中一个更新及
-时的内核源码库，可以通过以下地址访问：
-	http://sosdg.org/~coywolf/lxr/
-
-
-开发流程
---------
-
-目前Linux内核开发流程包括几个“主内核分支”和很多子系统相关的内核分支。这
-些分支包括：
-  - 2.6.x主内核源码树
-  - 2.6.x.y -stable内核源码树
-  - 2.6.x -git内核补丁集
-  - 2.6.x -mm内核补丁集
-  - 子系统相关的内核源码树和补丁集
-
-
-2.6.x内核主源码树
------------------
-2.6.x内核是由Linus Torvalds（Linux的创造者）亲自维护的。你可以在
-kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循以下步
-骤：
-  - 每当一个新版本的内核被发布，为期两周的集成窗口将被打开。在这段时间里
-    维护者可以向Linus提交大段的修改，通常这些修改已经被放到-mm内核中几个
-    星期了。提交大量修改的首选方式是使用git工具（内核的代码版本管理工具
-    ，更多的信息可以在http://git-scm.com/获取），不过使用普通补丁也是可以
-    的。
-  - 两个星期以后-rc1版本内核发布。之后只有不包含可能影响整个内核稳定性的
-    新功能的补丁才可能被接受。请注意一个全新的驱动程序（或者文件系统）有
-    可能在-rc1后被接受是因为这样的修改完全独立，不会影响其他的代码，所以
-    没有造成内核退步的风险。在-rc1以后也可以用git向Linus提交补丁，不过所
-    有的补丁需要同时被发送到相应的公众邮件列表以征询意见。
-  - 当Linus认为当前的git源码树已经达到一个合理健全的状态足以发布供人测试
-    时，一个新的-rc版本就会被发布。计划是每周都发布新的-rc版本。
-  - 这个过程一直持续下去直到内核被认为达到足够稳定的状态，持续时间大概是
-    6个星期。
-
-关于内核发布，值得一提的是Andrew Morton在linux-kernel邮件列表中如是说：
-	“没有人知道新内核何时会被发布，因为发布是根据已知bug的情况来决定
-	的，而不是根据一个事先制定好的时间表。”
-
-
-2.6.x.y -stable（稳定版）内核源码树
------------------------------------
-由4个数字组成的内核版本号说明此内核是-stable版本。它们包含基于2.6.x版本
-内核的相对较小且至关重要的修补，这些修补针对安全性问题或者严重的内核退步。
-
-这种版本的内核适用于那些期望获得最新的稳定版内核并且不想参与测试开发版或
-者实验版的用户。
-
-如果没有2.6.x.y版本内核存在，那么最新的2.6.x版本内核就相当于是当前的稳定
-版内核。
-
-2.6.x.y版本由“稳定版”小组（邮件地址<stable@vger.kernel.org>）维护，一般隔周发
-布新版本。
-
-内核源码中的Documentation/stable_kernel_rules.txt文件具体描述了可被稳定
-版内核接受的修改类型以及发布的流程。
-
-
-2.6.x -git补丁集
-----------------
-Linus的内核源码树的每日快照，这个源码树是由git工具管理的（由此得名）。这
-些补丁通常每天更新以反映Linus的源码树的最新状态。它们比-rc版本的内核源码
-树更具试验性质，因为这个补丁集是全自动生成的，没有任何人来确认其是否真正
-健全。
-
-
-2.6.x -mm补丁集
----------------
-这是由Andrew Morton维护的试验性内核补丁集。Andrew将所有子系统的内核源码
-和补丁拼凑到一起，并且加入了大量从linux-kernel邮件列表中采集的补丁。这个
-源码树是新功能和补丁的试炼场。当补丁在-mm补丁集里证明了其价值以后Andrew
-或者相应子系统的维护者会将补丁发给Linus以便集成进主内核源码树。
-
-在将所有新补丁发给Linus以集成到主内核源码树之前，我们非常鼓励先把这些补
-丁放在-mm版内核源码树中进行测试。
-
-这些内核版本不适合在需要稳定运行的系统上运行，因为运行它们比运行任何其他
-内核分支都更具有风险。
-
-如果你想为内核开发进程提供帮助，请尝试并使用这些内核版本，并在
-linux-kernel邮件列表中提供反馈，告诉大家你遇到了问题还是一切正常。
-
-通常-mm版补丁集不光包括这些额外的试验性补丁，还包括发布时-git版主源码树
-中的改动。
-
--mm版内核没有固定的发布周期，但是通常在每两个-rc版内核发布之间都会有若干
-个-mm版内核发布（一般是1至3个）。
-
-
-子系统相关内核源码树和补丁集
-----------------------------
-相当一部分内核子系统开发者会公开他们自己的开发源码树，以便其他人能了解内
-核的不同领域正在发生的事情。如上所述，这些源码树会被集成到-mm版本内核中。
-
-下面是目前可用的一些内核源码树的列表：
-  通过git管理的源码树：
-    - Kbuild开发源码树， Sam Ravnborg <sam@ravnborg.org>
-	git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
-
-    - ACPI开发源码树, Len Brown <len.brown@intel.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
-
-    - 块设备开发源码树, Jens Axboe <axboe@suse.de>
-	git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
-
-    - DRM开发源码树, Dave Airlie <airlied@linux.ie>
-	git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
-
-    - ia64开发源码树, Tony Luck <tony.luck@intel.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
-
-    - ieee1394开发源码树, Jody McIntyre <scjody@modernduck.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
-
-    - infiniband开发源码树, Roland Dreier <rolandd@cisco.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
-
-    - libata开发源码树, Jeff Garzik <jgarzik@pobox.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
-
-    - 网络驱动程序开发源码树, Jeff Garzik <jgarzik@pobox.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
-
-    - pcmcia开发源码树, Dominik Brodowski <linux@dominikbrodowski.net>
-	git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
-
-    - SCSI开发源码树, James Bottomley <James.Bottomley@SteelEye.com>
-	git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
-
-  使用quilt管理的补丁集：
-    - USB, PCI, 驱动程序核心和I2C, Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-	kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
-    - x86-64, 部分i386, Andi Kleen <ak@suse.de>
-	ftp.firstfloor.org:/pub/ak/x86_64/quilt/
-
-  其他内核源码树可以在http://git.kernel.org的列表中和MAINTAINERS文件里
-  找到。
-
-报告bug
--------
-
-bugzilla.kernel.org是Linux内核开发者们用来跟踪内核Bug的网站。我们鼓励用
-户在这个工具中报告找到的所有bug。如何使用内核bugzilla的细节请访问：
-	http://test.kernel.org/bugzilla/faq.html
-
-内核源码主目录中的REPORTING-BUGS文件里有一个很好的模板。它指导用户如何报
-告可能的内核bug以及需要提供哪些信息来帮助内核开发者们找到问题的根源。
-
-
-利用bug报告
------------
-
-练习内核开发技能的最好办法就是修改其他人报告的bug。你不光可以帮助内核变
-得更加稳定，还可以学会如何解决实际问题从而提高自己的技能，并且让其他开发
-者感受到你的存在。修改bug是赢得其他开发者赞誉的最好办法，因为并不是很多
-人都喜欢浪费时间去修改别人报告的bug。
-
-要尝试修改已知的bug，请访问http://bugzilla.kernel.org网址。如果你想获得
-最新bug的通知，可以订阅bugme-new邮件列表（只有新的bug报告会被寄到这里）
-或者订阅bugme-janitor邮件列表（所有bugzilla的变动都会被寄到这里）。
-
-	https://lists.linux-foundation.org/mailman/listinfo/bugme-new
-	https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
-
-
-邮件列表
---------
-
-正如上面的文档所描述，大多数的骨干内核开发者都加入了Linux Kernel邮件列
-表。如何订阅和退订列表的细节可以在这里找到：
-	http://vger.kernel.org/vger-lists.html#linux-kernel
-网上很多地方都有这个邮件列表的存档(archive)。可以使用搜索引擎来找到这些
-存档。比如：
-	http://dir.gmane.org/gmane.linux.kernel
-在发信之前，我们强烈建议你先在存档中搜索你想要讨论的问题。很多已经被详细
-讨论过的问题只在邮件列表的存档中可以找到。
-
-大多数内核子系统也有自己独立的邮件列表来协调各自的开发工作。从
-MAINTAINERS文件中可以找到不同话题对应的邮件列表。
-
-很多邮件列表架设在kernel.org服务器上。这些列表的信息可以在这里找到：
-	http://vger.kernel.org/vger-lists.html
-
-在使用这些邮件列表时，请记住保持良好的行为习惯。下面的链接提供了与这些列
-表（或任何其它邮件列表）交流的一些简单规则，虽然内容有点滥竽充数。
-	http://www.albion.com/netiquette/
-
-当有很多人回复你的邮件时，邮件的抄送列表会变得很长。请不要将任何人从抄送
-列表中删除，除非你有足够的理由这么做。也不要只回复到邮件列表。请习惯于同
-一封邮件接收两次（一封来自发送者一封来自邮件列表），而不要试图通过添加一
-些奇特的邮件头来解决这个问题，人们不会喜欢的。
-
-记住保留你所回复内容的上下文和源头。在你回复邮件的顶部保留“某某某说到……”
-这几行。将你的评论加在被引用的段落之间而不要放在邮件的顶部。
-
-如果你在邮件中附带补丁，请确认它们是可以直接阅读的纯文本（如
-Documentation/SubmittingPatches文档中所述）。内核开发者们不希望遇到附件
-或者被压缩了的补丁。只有这样才能保证他们可以直接评论你的每行代码。请确保
-你使用的邮件发送程序不会修改空格和制表符。一个防范性的测试方法是先将邮件
-发送给自己，然后自己尝试是否可以顺利地打上收到的补丁。如果测试不成功，请
-调整或者更换你的邮件发送程序直到它正确工作为止。
-
-总而言之，请尊重其他的邮件列表订阅者。
-
-
-同内核社区合作
-----------------
-
-内核社区的目标就是提供尽善尽美的内核。所以当你提交补丁期望被接受进内核的
-时候，它的技术价值以及其他方面都将被评审。那么你可能会得到什么呢？
-  - 批评
-  - 评论
-  - 要求修改
-  - 要求证明修改的必要性
-  - 沉默
-
-要记住，这些是把补丁放进内核的正常情况。你必须学会听取对补丁的批评和评论，
-从技术层面评估它们，然后要么重写你的补丁要么简明扼要地论证修改是不必要
-的。如果你发的邮件没有得到任何回应，请过几天后再试一次，因为有时信件会湮
-没在茫茫信海中。
-
-你不应该做的事情：
-  - 期望自己的补丁不受任何质疑就直接被接受
-  - 翻脸
-  - 忽略别人的评论
-  - 没有按照别人的要求做任何修改就重新提交
-
-在一个努力追寻最好技术方案的社区里，对于一个补丁有多少好处总会有不同的见
-解。你必须要抱着合作的态度，愿意改变自己的观点来适应内核的风格。或者至少
-愿意去证明你的想法是有价值的。记住，犯错误是允许的，只要你愿意朝着正确的
-方案去努力。
-
-如果你的第一个补丁换来的是一堆修改建议，这是很正常的。这并不代表你的补丁
-不会被接受，也不意味着有人和你作对。你只需要改正所有提出的问题然后重新发
-送你的补丁。
-
-内核社区和公司文化的差异
-------------------------
-
-内核社区的工作模式同大多数传统公司开发队伍的工作模式并不相同。下面这些例
-子，可以帮助你避免某些可能发生问题：
-  用这些话介绍你的修改提案会有好处：
-    - 它同时解决了多个问题
-    - 它删除了2000行代码
-    - 这是补丁，它已经解释了我想要说明的
-    - 我在5种不同的体系结构上测试过它……
-    - 这是一系列小补丁用来……
-    - 这个修改提高了普通机器的性能……
-
-  应该避免如下的说法：
-    - 我们在AIX/ptx/Solaris就是这么做的，所以这么做肯定是好的……
-    - 我做这行已经20年了，所以……
-    - 为了我们公司赚钱考虑必须这么做
-    - 这是我们的企业产品线所需要的
-    - 这里是描述我观点的1000页设计文档
-    - 这是一个5000行的补丁用来……
-    - 我重写了现在乱七八糟的代码，这就是……
-    - 我被规定了最后期限，所以这个补丁需要立刻被接受
-
-另外一个内核社区与大部分传统公司的软件开发队伍不同的地方是无法面对面地交
-流。使用电子邮件和IRC聊天工具做为主要沟通工具的一个好处是性别和种族歧视
-将会更少。Linux内核的工作环境更能接受妇女和少数族群，因为每个人在别人眼
-里只是一个邮件地址。国际化也帮助了公平的实现，因为你无法通过姓名来判断人
-的性别。男人有可能叫李丽，女人也有可能叫王刚。大多数在Linux内核上工作过
-并表达过看法的女性对在linux上工作的经历都给出了正面的评价。
-
-对于一些不习惯使用英语的人来说，语言可能是一个引起问题的障碍。在邮件列表
-中要正确地表达想法必需良好地掌握语言，所以建议你在发送邮件之前最好检查一
-下英文写得是否正确。
-
-
-拆分修改
---------
-
-Linux内核社区并不喜欢一下接收大段的代码。修改需要被恰当地介绍、讨论并且
-拆分成独立的小段。这几乎完全和公司中的习惯背道而驰。你的想法应该在开发最
-开始的阶段就让大家知道，这样你就可以及时获得对你正在进行的开发的反馈。这
-样也会让社区觉得你是在和他们协作，而不是仅仅把他们当作倾销新功能的对象。
-无论如何，你不要一次性地向邮件列表发送50封信，你的补丁序列应该永远用不到
-这么多。
-
-将补丁拆开的原因如下：
-
-1) 小的补丁更有可能被接受，因为它们不需要太多的时间和精力去验证其正确性。
-   一个5行的补丁，可能在维护者看了一眼以后就会被接受。而500行的补丁则
-   需要数个小时来审查其正确性（所需时间随补丁大小增加大约呈指数级增长）。
-
-   当出了问题的时候，小的补丁也会让调试变得非常容易。一个一个补丁地回溯
-   将会比仔细剖析一个被打上的大补丁（这个补丁破坏了其他东西）容易得多。
-
-2）不光发送小的补丁很重要，在提交之前重新编排、化简（或者仅仅重新排列）
-   补丁也是很重要的。
-
-这里有内核开发者Al Viro打的一个比方：
-	“想象一个老师正在给学生批改数学作业。老师并不希望看到学生为了得
-	到正确解法所进行的尝试和产生的错误。他希望看到的是最干净最优雅的
-	解答。好学生了解这点，绝不会把最终解决之前的中间方案提交上去。”
-
-	内核开发也是这样。维护者和评审者不希望看到一个人在解决问题时的思
-	考过程。他们只希望看到简单和优雅的解决方案。
-
-直接给出一流的解决方案，和社区一起协作讨论尚未完成的工作，这两者之间似乎
-很难找到一个平衡点。所以最好尽早开始收集有利于你进行改进的反馈；同时也要
-保证修改分成很多小块，这样在整个项目都准备好被包含进内核之前，其中的一部
-分可能会先被接收。
-
-必须了解这样做是不可接受的：试图将未完成的工作提交进内核，然后再找时间修
-复。
-
-
-证明修改的必要性
-----------------
-除了将补丁拆成小块，很重要的一点是让Linux社区了解他们为什么需要这样修改。
-你必须证明新功能是有人需要的并且是有用的。
-
-
-记录修改
---------
-
-当你发送补丁的时候，需要特别留意邮件正文的内容。因为这里的信息将会做为补
-丁的修改记录(ChangeLog)，会被一直保留以备大家查阅。它需要完全地描述补丁，
-包括：
-  - 为什么需要这个修改
-  - 补丁的总体设计
-  - 实现细节
-  - 测试结果
-
-想了解它具体应该看起来像什么，请查阅以下文档中的“ChangeLog”章节：
-  “The Perfect Patch”
-  	 http://www.ozlabs.org/~akpm/stuff/tpp.txt
-
-
-这些事情有时候做起来很难。要在任何方面都做到完美可能需要好几年时间。这是
-一个持续提高的过程，它需要大量的耐心和决心。只要不放弃，你一定可以做到。
-很多人已经做到了，而他们都曾经和现在的你站在同样的起点上。
-
-
----------------
-感谢Paolo Ciarrocchi允许“开发流程”部分基于他所写的文章
-(http://www.kerneltravel.net/newbie/2.6-development_process)，感谢Randy
-Dunlap和Gerrit Huizenga完善了应该说和不该说的列表。感谢Pat Mochel, Hanna
-Linder, Randy Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer,
-Kees Cook, Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian
-Bunk, Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael
-Kerrisk和Alex Shepard的评审、建议和贡献。没有他们的帮助，这篇文档是不可
-能完成的。
-
-
-
-英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/io_ordering.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/io_ordering.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/io_ordering.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/io_ordering.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-Chinese translated version of Documentation/io_orderings.txt
-
-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: Lin Yongting <linyongting@gmail.com>
----------------------------------------------------------------------
-Documentation/io_ordering.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-中文版维护者： 林永听 Lin Yongting <linyongting@gmail.com>
-中文版翻译者： 林永听 Lin Yongting <linyongting@gmail.com>
-中文版校译者： 林永听 Lin Yongting <linyongting@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-
-在某些平台上，所谓的内存映射I/O是弱顺序。在这些平台上，驱动开发者有责任
-保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
-设备寄存器或桥寄存器，触发IO芯片清刷未处理的写操作到达设备后才处理读操作，
-而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
-这也可以保证后面的写操作只在前面的写操作之后到达设备（这非常类似于内存
-屏障操作，mb()，不过仅适用于I/O）。
-
-假设一个设备驱动程的具体例子：
-
-        ...
-CPU A:  spin_lock_irqsave(&dev_lock, flags)
-CPU A:  val = readl(my_status);
-CPU A:  ...
-CPU A:  writel(newval, ring_ptr);
-CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
-        ...
-CPU B:  spin_lock_irqsave(&dev_lock, flags)
-CPU B:  val = readl(my_status);
-CPU B:  ...
-CPU B:  writel(newval2, ring_ptr);
-CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
-        ...
-
-上述例子中，设备可能会先接收到newval2的值，然后接收到newval的值，问题就
-发生了。不过很容易通过下面方法来修复：
-
-        ...
-CPU A:  spin_lock_irqsave(&dev_lock, flags)
-CPU A:  val = readl(my_status);
-CPU A:  ...
-CPU A:  writel(newval, ring_ptr);
-CPU A:  (void)readl(safe_register); /* 配置寄存器？*/
-CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
-        ...
-CPU B:  spin_lock_irqsave(&dev_lock, flags)
-CPU B:  val = readl(my_status);
-CPU B:  ...
-CPU B:  writel(newval2, ring_ptr);
-CPU B:  (void)readl(safe_register); /* 配置寄存器？*/
-CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
-
-在解决方案中，读取safe_register寄存器，触发IO芯片清刷未处理的写操作，
-再处理后面的读操作，防止引发数据不一致问题。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/IRQ.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/IRQ.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/IRQ.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/IRQ.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-Chinese translated version of Documentation/IRQ.txt
-
-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.
-
-Maintainer: Eric W. Biederman <ebiederman@xmission.com>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/IRQ.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-英文版维护者： Eric W. Biederman <ebiederman@xmission.com>
-中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-何为 IRQ?
-
-一个 IRQ 是来自某个设备的一个中断请求。目前，它们可以来自一个硬件引脚，
-或来自一个数据包。多个设备可能连接到同个硬件引脚，从而共享一个 IRQ。
-
-一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下，这是一个
-全局 irq_desc 数组的索引，但是除了在 linux/interrupt.h 中的实现，
-具体的细节是体系结构特定的。
-
-一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下，枚举的编号是
-该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况，
-枚举的是在两个 i8259 中断控制器中 16 个输入引脚。
-
-架构可以对 IRQ 编号指定额外的含义，在硬件涉及任何手工配置的情况下，
-是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/magic-number.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/magic-number.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/magic-number.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/magic-number.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-Chinese translated version of Documentation/magic-number.txt
-
-If you have any comment or update to the content, please post to LKML directly.
-However, if you have problem communicating in English you can also ask the
-Chinese maintainer for help.  Contact the Chinese maintainer, if this
-translation is outdated or there is problem with translation.
-
-Chinese maintainer: Jia Wei Wei <harryxiyou@gmail.com>
----------------------------------------------------------------------
-Documentation/magic-number.txt的中文翻译
-
-如果想评论或更新本文的内容，请直接发信到LKML。如果你使用英文交流有困难的话，也可
-以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题，请联系中文版维护者。
-
-中文版维护者： 贾威威 Jia Wei Wei <harryxiyou@gmail.com>
-中文版翻译者： 贾威威 Jia Wei Wei <harryxiyou@gmail.com>
-中文版校译者： 贾威威 Jia Wei Wei <harryxiyou@gmail.com>
-
-以下为正文
----------------------------------------------------------------------
-这个文件是有关当前使用的魔术值注册表。当你给一个结构添加了一个魔术值，你也应该把这个魔术值添加到这个文件，因为我们最好把用于各种结构的魔术值统一起来。
-
-使用魔术值来保护内核数据结构是一个非常好的主意。这就允许你在运行期检查(a)一个结构是否已经被攻击，或者(b)你已经给一个例行程序通过了一个错误的结构。后一种情况特别地有用---特别是当你通过一个空指针指向结构体的时候。tty源码，例如，经常通过特定驱动使用这种方法并且反复地排列特定方面的结构。
-
-使用魔术值的方法是在结构的开始处声明的，如下：
-
-struct tty_ldisc {
-	int	magic;
-	...
-};
-
-当你以后给内核添加增强功能的时候，请遵守这条规则！这样就会节省数不清的调试时间，特别是一些古怪的情况，例如，数组超出范围并且重新写了超出部分。遵守这个规则，‪这些情况可以被快速地，安全地避免。
-
-		Theodore Ts'o
-		  31 Mar 94
-
-给当前的Linux 2.1.55添加魔术表。
-
-		Michael Chastain
-		<mailto:mec@shout.net>
-		22 Sep 1997
-
-现在应该最新的Linux 2.1.112.因为在特性冻结期间，不能在2.2.x前改变任何东西。这些条目被数域所排序。
-
-		Krzysztof G.Baranowski
-	        <mailto: kgb@knm.org.pl>
-		29 Jul 1998
-
-更新魔术表到Linux 2.5.45。刚好越过特性冻结，但是有可能还会有一些新的魔术值在2.6.x之前融入到内核中。
-
-		Petr Baudis
-		<pasky@ucw.cz>
-		03 Nov 2002
-
-更新魔术表到Linux 2.5.74。
-
-		Fabian Frederick
-                <ffrederick@users.sourceforge.net>
-		09 Jul 2003
-
-魔术名                 地址         结构               所在文件
-===========================================================================
-PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
-CMAGIC                0x0111      user              include/linux/a.out.h
-MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
-HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
-APM_BIOS_MAGIC        0x4101      apm_user          arch/x86/kernel/apm_32.c
-CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
-DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
-DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
-FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
-FF_MAGIC              0x4646      fc_info           drivers/net/iph5526_novram.c
-ISICOM_MAGIC          0x4d54      isi_port          include/linux/isicom.h
-PTY_MAGIC             0x5001                        drivers/char/pty.c
-PPP_MAGIC             0x5002      ppp               include/linux/if_pppvar.h
-SERIAL_MAGIC          0x5301      async_struct      include/linux/serial.h
-SSTATE_MAGIC          0x5302      serial_state      include/linux/serial.h
-SLIP_MAGIC            0x5302      slip              drivers/net/slip.h
-STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
-X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
-SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
-AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
-TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
-MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
-TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
-MGSLPC_MAGIC          0x5402      mgslpc_info       drivers/char/pcmcia/synclink_cs.c
-TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
-USB_SERIAL_MAGIC      0x6702      usb_serial        drivers/usb/serial/usb-serial.h
-FULL_DUPLEX_MAGIC     0x6969                        drivers/net/ethernet/dec/tulip/de2104x.c
-USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
-RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
-USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
-CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
-RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
-LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
-GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
-RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
-NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
-RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
-BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
-ISDN_X25IFACE_MAGIC   0x1e75a2b9  isdn_x25iface_proto_data
-                                                    drivers/isdn/isdn_x25iface.h
-ECP_MAGIC             0x21504345  cdkecpsig         include/linux/cdk.h
-LSOMAGIC              0x27091997  lso               drivers/fc4/fc.c
-LSMAGIC               0x2a3b4d2a  ls                drivers/fc4/fc.c
-WANPIPE_MAGIC         0x414C4453  sdla_{dump,exec}  include/linux/wanpipe.h
-CS_CARD_MAGIC         0x43525553  cs_card           sound/oss/cs46xx.c
-LABELCL_MAGIC         0x4857434c  labelcl_info_s    include/asm/ia64/sn/labelcl.h
-ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
-CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
-ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
-SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
-CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
-SLAB_C_MAGIC          0x4f17a36d  kmem_cache        mm/slab.c
-COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
-I810_CARD_MAGIC       0x5072696E  i810_card         sound/oss/i810_audio.c
-TRIDENT_CARD_MAGIC    0x5072696E  trident_card      sound/oss/trident.c
-ROUTER_MAGIC          0x524d4157  wan_device        [in wanrouter.h pre 3.9]
-SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
-GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
-RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
-EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
-HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
-PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
-KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
-I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
-TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
-M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
-FW_HEADER_MAGIC       0x65726F66  fw_header         drivers/atm/fore200e.h
-SLOT_MAGIC            0x67267321  slot              drivers/hotplug/cpqphp.h
-SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
-LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
-OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
-M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
-VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
-KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
-PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
-NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
-ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
-CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
-DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
-YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
-CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
-QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
-QUEUE_MAGIC_USED      0xf7e1cc33  queue_entry       drivers/scsi/arm/queue.c
-HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
-NMI_MAGIC             0x48414d4d455201 nmi_s        arch/mips/include/asm/sn/nmi.h
-
-请注意，在声音记忆管理中仍然有一些特殊的为每个驱动定义的魔术值。查看include/sound/sndmagic.h来获取他们完整的列表信息。很多OSS声音驱动拥有自己从声卡PCI ID构建的魔术值-他们也没有被列在这里。
-
-IrDA子系统也使用了大量的自己的魔术值，查看include/net/irda/irda.h来获取他们完整的信息。
-
-HFS是另外一个比较大的使用魔术值的文件系统-你可以在fs/hfs/hfs.h中找到他们。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/oops-tracing.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/oops-tracing.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/oops-tracing.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/oops-tracing.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,212 +0,0 @@
-Chinese translated version of Documentation/oops-tracing.txt
-
-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: Dave Young <hidave.darkstar@gmail.com>
----------------------------------------------------------------------
-Documentation/oops-tracing.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-中文版维护者： 杨瑞 Dave Young <hidave.darkstar@gmail.com>
-中文版翻译者： 杨瑞 Dave Young <hidave.darkstar@gmail.com>
-中文版校译者： 李阳 Li Yang <leo@zh-kernel.org>
-               王聪 Wang Cong <xiyou.wangcong@gmail.com>
-
-以下为正文
----------------------------------------------------------------------
-
-注意： ksymoops 在2.6中是没有用的。 请以原有格式使用Oops(来自dmesg，等等)。
-忽略任何这样那样关于“解码Oops”或者“通过ksymoops运行”的文档。 如果你贴出运行过
-ksymoops的来自2.6的Oops，人们只会让你重贴一次。
-
-快速总结
--------------
-
-发现Oops并发送给看似相关的内核领域的维护者。别太担心对不上号。如果你不确定就发给
-和你所做的事情相关的代码的负责人。 如果可重现试着描述怎样重构。 那甚至比oops更有
-价值。
-
-如果你对于发送给谁一无所知， 发给linux-kernel@vger.kernel.org。感谢你帮助Linux
-尽可能地稳定。
-
-Oops在哪里?
-----------------------
-
-通常Oops文本由klogd从内核缓冲区里读取并传给syslogd，由syslogd写到syslog文件中，
-典型地是/var/log/messages(依赖于/etc/syslog.conf)。有时klogd崩溃了,这种情况下你
-能够运行dmesg > file来从内核缓冲区中读取数据并保存下来。 否则你可以
-cat /proc/kmsg > file， 然而你必须介入中止传输， kmsg是一个“永不结束的文件”。如
-果机器崩溃坏到你不能输入命令或者磁盘不可用那么你有三种选择:-
-
-（1） 手抄屏幕上的文本待机器重启后再输入计算机。 麻烦但如果没有针对崩溃的准备，
-这是仅有的选择。 另外，你可以用数码相机把屏幕拍下来-不太好，但比没有强。 如果信
-息滚动到了终端的上面，你会发现以高分辩率启动（比如，vga=791）会让你读到更多的文
-本。（注意：这需要vesafb，所以对‘早期’的oops没有帮助）
-
-（2）用串口终端启动（请参看Documentation/serial-console.txt），运行一个null
-modem到另一台机器并用你喜欢的通讯工具获取输出。Minicom工作地很好。
-
-（3）使用Kdump（请参看Documentation/kdump/kdump.txt），
-使用在Documentation/kdump/gdbmacros.txt中定义的dmesg gdb宏，从旧的内存中提取内核
-环形缓冲区。
-
-完整信息
-----------------
-
-注意：以下来自于Linus的邮件适用于2.4内核。 我因为历史原因保留了它，并且因为其中
-一些信息仍然适用。 特别注意的是，请忽略任何ksymoops的引用。
-
-From: Linus Torvalds <torvalds@osdl.org>
-
-怎样跟踪Oops.. [原发到linux-kernel的一封邮件]
-
-主要的窍门是有五年和这些烦人的oops消息打交道的经验;-)
-
-实际上，你有办法使它更简单。我有两个不同的方法：
-
-	gdb /usr/src/linux/vmlinux
-	gdb> disassemble <offending_function>
-
-那是发现问题的简单办法，至少如果bug报告做的好的情况下（象这个一样-运行ksymoops
-得到oops发生的函数及函数内的偏移）。
-
-哦，如果报告发生的内核以相同的编译器和相似的配置编译它会有帮助的。
-
-另一件要做的事是反汇编bug报告的“Code”部分：ksymoops也会用正确的工具来做这件事，
-但如果没有那些工具你可以写一个傻程序：
-
-	char str[] = "\xXX\xXX\xXX...";
-	main(){}
-
-并用gcc -g编译它然后执行“disassemble str”（XX部分是由Oops报告的值-你可以仅剪切
-粘贴并用“\x”替换空格-我就是这么做的，因为我懒得写程序自动做这一切）。
-
-另外，你可以用scripts/decodecode这个shell脚本。它的使用方法是：
-decodecode < oops.txt
-
-“Code”之后的十六进制字节可能（在某些架构上）有一些当前指令之前的指令字节以及
-当前和之后的指令字节
-
-Code: f9 0f 8d f9 00 00 00 8d 42 0c e8 dd 26 11 c7 a1 60 ea 2b f9 8b 50 08 a1
-64 ea 2b f9 8d 34 82 8b 1e 85 db 74 6d 8b 15 60 ea 2b f9 <8b> 43 04 39 42 54
-7e 04 40 89 42 54 8b 43 04 3b 05 00 f6 52 c0
-
-最后，如果你想知道代码来自哪里，你可以：
-
-	cd /usr/src/linux
-	make fs/buffer.s 	# 或任何产生BUG的文件
-
-然后你会比gdb反汇编更清楚的知道发生了什么。
-
-现在，问题是把你所拥有的所有数据结合起来：C源码（关于它应该怎样的一般知识），
-汇编代码及其反汇编得到的代码（另外还有从“oops”消息得到的寄存器状态-对了解毁坏的
-指针有用，而且当你有了汇编代码你也能拿其它的寄存器和任何它们对应的C表达式做匹配
-）。
-
-实际上，你仅需看看哪里不匹配（这个例子是“Code”反汇编和编译器生成的代码不匹配）。
-然后你须要找出为什么不匹配。通常很简单-你看到代码使用了空指针然后你看代码想知道
-空指针是怎么出现的，还有检查它是否合法..
-
-现在，如果明白这是一项耗时的工作而且需要一丁点儿的专心，没错。这就是我为什么大多
-只是忽略那些没有符号表信息的崩溃报告的原因：简单的说太难查找了（我有一些
-程序用于在内核代码段中搜索特定的模式，而且有时我也已经能找出那些崩溃的地方，但是
-仅仅是找出正确的序列也确实需要相当扎实的内核知识）
-
-_有时_会发生这种情况，我仅看到崩溃中的反汇编代码序列， 然后我马上就明白问题出在
-哪里。这时我才意识到自己干这个工作已经太长时间了;-)
-
-		Linus
-
-
----------------------------------------------------------------------------
-关于Oops跟踪的注解：
-
-为了帮助Linus和其它内核开发者，klogd纳入了大量的支持来处理保护错误。为了拥有对
-地址解析的完整支持至少应该使用1.3-pl3的sysklogd包。
-
-当保护错误发生时，klogd守护进程自动把内核日志信息中的重要地址翻译成它们相应的符
-号。
-
-klogd执行两种类型的地址解析。首先是静态翻译其次是动态翻译。静态翻译和ksymoops
-一样使用System.map文件。为了做静态翻译klogd守护进程必须在初始化时能找到system
-map文件。关于klogd怎样搜索map文件请参看klogd手册页。
-
-动态地址翻译在使用内核可装载模块时很重要。 因为内核模块的内存是从内核动态内存池
-里分配的，所以不管是模块开始位置还是模块中函数和符号的位置都不是固定的。
-
-内核支持允许程序决定装载哪些模块和它们在内存中位置的系统调用。使用这些系统调用
-klogd守护进程生成一张符号表用于调试发生在可装载模块中的保护错误。
-
-至少klogd会提供产生保护错误的模块名。还可有额外的符号信息供可装载模块开发者选择
-以从模块中输出符号信息。
-
-因为内核模块环境可能是动态的，所以必须有一种机制当模块环境发生改变时来通知klogd
-守护进程。 有一些可用的命令行选项允许klogd向当前执行中的守护进程发送信号，告知符
-号信息应该被刷新了。 更多信息请参看klogd手册页。
-
-sysklogd发布时包含一个补丁修改了modules-2.0.0包，无论何时一个模块装载或者卸载都
-会自动向klogd发送信号。打上这个补丁提供了必要的对调试发生于内核可装载模块的保护
-错误的无缝支持。
-
-以下是被klogd处理过的发生在可装载模块中的一个保护错误例子：
----------------------------------------------------------------------------
-Aug 29 09:51:01 blizard kernel: Unable to handle kernel paging request at virtual address f15e97cc
-Aug 29 09:51:01 blizard kernel: current->tss.cr3 = 0062d000, %cr3 = 0062d000
-Aug 29 09:51:01 blizard kernel: *pde = 00000000
-Aug 29 09:51:01 blizard kernel: Oops: 0002
-Aug 29 09:51:01 blizard kernel: CPU:    0
-Aug 29 09:51:01 blizard kernel: EIP:    0010:[oops:_oops+16/3868]
-Aug 29 09:51:01 blizard kernel: EFLAGS: 00010212
-Aug 29 09:51:01 blizard kernel: eax: 315e97cc   ebx: 003a6f80   ecx: 001be77b   edx: 00237c0c
-Aug 29 09:51:01 blizard kernel: esi: 00000000   edi: bffffdb3   ebp: 00589f90   esp: 00589f8c
-Aug 29 09:51:01 blizard kernel: ds: 0018   es: 0018   fs: 002b   gs: 002b   ss: 0018
-Aug 29 09:51:01 blizard kernel: Process oops_test (pid: 3374, process nr: 21, stackpage=00589000)
-Aug 29 09:51:01 blizard kernel: Stack: 315e97cc 00589f98 0100b0b4 bffffed4 0012e38e 00240c64 003a6f80 00000001
-Aug 29 09:51:01 blizard kernel:        00000000 00237810 bfffff00 0010a7fa 00000003 00000001 00000000 bfffff00
-Aug 29 09:51:01 blizard kernel:        bffffdb3 bffffed4 ffffffda 0000002b 0007002b 0000002b 0000002b 00000036
-Aug 29 09:51:01 blizard kernel: Call Trace: [oops:_oops_ioctl+48/80] [_sys_ioctl+254/272] [_system_call+82/128]
-Aug 29 09:51:01 blizard kernel: Code: c7 00 05 00 00 00 eb 08 90 90 90 90 90 90 90 90 89 ec 5d c3
----------------------------------------------------------------------------
-
-Dr. G.W. Wettstein           Oncology Research Div. Computing Facility
-Roger Maris Cancer Center    INTERNET: greg@wind.rmcc.com
-820 4th St. N.
-Fargo, ND  58122
-Phone: 701-234-7556
-
-
----------------------------------------------------------------------------
-受污染的内核
-
-一些oops报告在程序记数器之后包含字符串'Tainted: '。这表明内核已经被一些东西给污
-染了。 该字符串之后紧跟着一系列的位置敏感的字符，每个代表一个特定的污染值。
-
-  1：'G'如果所有装载的模块都有GPL或相容的许可证，'P'如果装载了任何的专有模块。
-没有模块MODULE_LICENSE或者带有insmod认为是与GPL不相容的的MODULE_LICENSE的模块被
-认定是专有的。
-
-  2：'F'如果有任何通过“insmod -f”被强制装载的模块，' '如果所有模块都被正常装载。
-
-  3：'S'如果oops发生在SMP内核中，运行于没有证明安全运行多处理器的硬件。 当前这种
-情况仅限于几种不支持SMP的速龙处理器。
-
-  4：'R'如果模块通过“insmod -f”被强制装载，' '如果所有模块都被正常装载。
-
-  5：'M'如果任何处理器报告了机器检查异常，' '如果没有发生机器检查异常。
-
-  6：'B'如果页释放函数发现了一个错误的页引用或者一些非预期的页标志。
-
-  7：'U'如果用户或者用户应用程序特别请求设置污染标志，否则' '。
-
-  8：'D'如果内核刚刚死掉，比如有OOPS或者BUG。
-
-使用'Tainted: '字符串的主要原因是要告诉内核调试者，这是否是一个干净的内核亦或发
-生了任何的不正常的事。污染是永久的：即使出错的模块已经被卸载了，污染值仍然存在，
-以表明内核不再值得信任。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/SecurityBugs linux-libre-4.10-rc8-gnu/Documentation/zh_CN/SecurityBugs
--- linux-libre-4.9-gnu/Documentation/zh_CN/SecurityBugs	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/SecurityBugs	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-Chinese translated version of Documentation/SecurityBugs
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have a problem
-communicating in English you can also ask the Chinese maintainer for
-help.  Contact the Chinese maintainer if this translation is outdated
-or if there is a problem with the translation.
-
-Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
----------------------------------------------------------------------
-Documentation/SecurityBugs 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-中文版维护者： 贾威威 Harry Wei <harryxiyou@gmail.com>
-中文版翻译者： 贾威威 Harry Wei <harryxiyou@gmail.com>
-中文版校译者： 贾威威 Harry Wei <harryxiyou@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-Linux内核开发者认为安全非常重要。因此，我们想要知道当一个有关于
-安全的漏洞被发现的时候，并且它可能会被尽快的修复或者公开。请把这个安全
-漏洞报告给Linux内核安全团队。
-
-1) 联系
-
-linux内核安全团队可以通过email<security@kernel.org>来联系。这是
-一组独立的安全工作人员，可以帮助改善漏洞报告并且公布和取消一个修复。安
-全团队有可能会从部分的维护者那里引进额外的帮助来了解并且修复安全漏洞。
-当遇到任何漏洞，所能提供的信息越多就越能诊断和修复。如果你不清楚什么
-是有帮助的信息，那就请重温一下REPORTING-BUGS文件中的概述过程。任
-何攻击性的代码都是非常有用的，未经报告者的同意不会被取消，除非它已经
-被公布于众。
-
-2) 公开
-
-Linux内核安全团队的宗旨就是和漏洞提交者一起处理漏洞的解决方案直
-到公开。我们喜欢尽快地完全公开漏洞。当一个漏洞或者修复还没有被完全地理
-解，解决方案没有通过测试或者供应商协调，可以合理地延迟公开。然而，我们
-期望这些延迟尽可能的短些，是可数的几天，而不是几个星期或者几个月。公开
-日期是通过安全团队和漏洞提供者以及供应商洽谈后的结果。公开时间表是从很
-短（特殊的，它已经被公众所知道）到几个星期。作为一个基本的默认政策，我
-们所期望通知公众的日期是7天的安排。
-
-3) 保密协议
-
-Linux内核安全团队不是一个正式的团体，因此不能加入任何的保密协议。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/sparse.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/sparse.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/sparse.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/sparse.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-﻿Chinese translated version of Documentation/sparse.txt
-
-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: Li Yang <leo@zh-kernel.org>
----------------------------------------------------------------------
-Documentation/sparse.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-中文版维护者： 李阳  Li Yang <leo@zh-kernel.org>
-中文版翻译者： 李阳  Li Yang <leo@zh-kernel.org>
-
-
-以下为正文
----------------------------------------------------------------------
-
-Copyright 2004 Linus Torvalds
-Copyright 2004 Pavel Machek <pavel@ucw.cz>
-Copyright 2006 Bob Copeland <me@bobcopeland.com>
-
-使用 sparse 工具做类型检查
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-"__bitwise" 是一种类型属性，所以你应该这样使用它：
-
-        typedef int __bitwise pm_request_t;
-
-        enum pm_request {
-                PM_SUSPEND = (__force pm_request_t) 1,
-                PM_RESUME = (__force pm_request_t) 2
-        };
-
-这样会使 PM_SUSPEND 和 PM_RESUME 成为位方式(bitwise)整数（使用"__force"
-是因为 sparse 会抱怨改变位方式的类型转换，但是这里我们确实需要强制进行转
-换）。而且因为所有枚举值都使用了相同的类型，这里的"enum pm_request"也将
-会使用那个类型做为底层实现。
-
-而且使用 gcc 编译的时候，所有的 __bitwise/__force 都会消失，最后在 gcc
-看来它们只不过是普通的整数。
-
-坦白来说，你并不需要使用枚举类型。上面那些实际都可以浓缩成一个特殊的"int
-__bitwise"类型。
-
-所以更简单的办法只要这样做：
-
-	typedef int __bitwise pm_request_t;
-
-	#define PM_SUSPEND ((__force pm_request_t) 1)
-	#define PM_RESUME ((__force pm_request_t) 2)
-
-现在你就有了严格的类型检查所需要的所有基础架构。
-
-一个小提醒：常数整数"0"是特殊的。你可以直接把常数零当作位方式整数使用而
-不用担心 sparse 会抱怨。这是因为"bitwise"（恰如其名）是用来确保不同位方
-式类型不会被弄混（小尾模式，大尾模式，cpu尾模式，或者其他），对他们来说
-常数"0"确实是特殊的。
-
-获取 sparse 工具
-~~~~~~~~~~~~~~~~
-
-你可以从 Sparse 的主页获取最新的发布版本：
-
-	http://www.kernel.org/pub/linux/kernel/people/josh/sparse/
-
-或者，你也可以使用 git 克隆最新的 sparse 开发版本：
-
-	git://git.kernel.org/pub/scm/linux/kernel/git/josh/sparse.git
-
-DaveJ 把每小时自动生成的 git 源码树 tar 包放在以下地址：
-
-	http://www.codemonkey.org.uk/projects/git-snapshots/sparse/
-
-一旦你下载了源码，只要以普通用户身份运行：
-
-	make
-	make install
-
-它将会被自动安装到你的 ~/bin 目录下。
-
-使用 sparse 工具
-~~~~~~~~~~~~~~~~
-
-用"make C=1"命令来编译内核，会对所有重新编译的 C 文件使用 sparse 工具。
-或者使用"make C=2"命令，无论文件是否被重新编译都会对其使用 sparse 工具。
-如果你已经编译了内核，用后一种方式可以很快地检查整个源码树。
-
-make 的可选变量 CHECKFLAGS 可以用来向 sparse 工具传递参数。编译系统会自
-动向 sparse 工具传递 -Wbitwise 参数。你可以定义 __CHECK_ENDIAN__ 来进行
-大小尾检查。
-
-	make C=2 CHECKFLAGS="-D__CHECK_ENDIAN__"
-
-这些检查默认都是被关闭的，因为他们通常会产生大量的警告。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/stable_api_nonsense.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/stable_api_nonsense.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/stable_api_nonsense.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/stable_api_nonsense.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,157 +0,0 @@
-Chinese translated version of Documentation/stable_api_nonsense.txt
-
-If you have any comment or update to the content, please contact the
-original document maintainer directly.  However, if you have problem
-communicating in English you can also ask the Chinese maintainer for help.
-Contact the Chinese maintainer, if this translation is outdated or there
-is problem with translation.
-
-Maintainer: Greg Kroah-Hartman <greg@kroah.com>
-Chinese maintainer: TripleX Chung <zhongyu@18mail.cn>
----------------------------------------------------------------------
-Documentation/stable_api_nonsense.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
-中文版维护者： 钟宇  TripleX Chung <zhongyu@18mail.cn>
-中文版翻译者： 钟宇  TripleX Chung <zhongyu@18mail.cn>
-中文版校译者： 李阳  Li Yang <leoli@freescale.com>
-以下为正文
----------------------------------------------------------------------
-
-写作本文档的目的，是为了解释为什么Linux既没有二进制内核接口，也没有稳定
-的内核接口。这里所说的内核接口，是指内核里的接口，而不是内核和用户空间
-的接口。内核到用户空间的接口，是提供给应用程序使用的系统调用，系统调用
-在历史上几乎没有过变化，将来也不会有变化。我有一些老应用程序是在0.9版本
-或者更早版本的内核上编译的，在使用2.6版本内核的Linux发布上依然用得很好
-。用户和应用程序作者可以将这个接口看成是稳定的。
-
-
-执行纲要
---------
-
-你也许以为自己想要稳定的内核接口，但是你不清楚你要的实际上不是它。你需
-要的其实是稳定的驱动程序，而你只有将驱动程序放到公版内核的源代码树里，
-才有可能达到这个目的。而且这样做还有很多其它好处，正是因为这些好处使得
-Linux能成为强壮，稳定，成熟的操作系统，这也是你最开始选择Linux的原因。
-
-
-入门
------
-
-只有那些写驱动程序的“怪人”才会担心内核接口的改变，对广大用户来说，既
-看不到内核接口，也不需要去关心它。
-
-首先，我不打算讨论关于任何非GPL许可的内核驱动的法律问题，这些非GPL许可
-的驱动程序包括不公开源代码，隐藏源代码，二进制或者是用源代码包装，或者
-是其它任何形式的不能以GPL许可公开源代码的驱动程序。如果有法律问题，请咨
-询律师，我只是一个程序员，所以我只打算探讨技术问题（不是小看法律问题，
-法律问题很实际，并且需要一直关注）。
-
-既然只谈技术问题，我们就有了下面两个主题：二进制内核接口和稳定的内核源
-代码接口。这两个问题是互相关联的，让我们先解决掉二进制接口的问题。
-
-
-二进制内核接口
---------------
-假如我们有一个稳定的内核源代码接口，那么自然而然的，我们就拥有了稳定的
-二进制接口，是这样的吗？错。让我们看看关于Linux内核的几点事实：
-    - 取决于所用的C编译器的版本，不同的内核数据结构里的结构体的对齐方
-式会有差别，代码中不同函数的表现形式也不一样（函数是不是被inline编译取
-决于编译器行为）。不同的函数的表现形式并不重要，但是数据结构内部的对齐
-方式很关键。
-    - 取决于内核的配置选项，不同的选项会让内核的很多东西发生改变：
-      - 同一个结构体可能包含不同的成员变量
-      - 有的函数可能根本不会被实现（比如编译的时候没有选择SMP支持
-，一些锁函数就会被定义成空函数）。
-      - 内核使用的内存会以不同的方式对齐，这取决于不同的内核配置选
-项。
-    - Linux可以在很多的不同体系结构的处理器上运行。在某个体系结构上编
-译好的二进制驱动程序，不可能在另外一个体系结构上正确的运行。
-
-对于一个特定的内核，满足这些条件并不难，使用同一个C编译器和同样的内核配
-置选项来编译驱动程序模块就可以了。这对于给一个特定Linux发布的特定版本提
-供驱动程序，是完全可以满足需求的。但是如果你要给不同发布的不同版本都发
-布一个驱动程序，就需要在每个发布上用不同的内核设置参数都编译一次内核，
-这简直跟噩梦一样。而且还要注意到，每个Linux发布还提供不同的Linux内核，
-这些内核都针对不同的硬件类型进行了优化（有很多种不同的处理器，还有不同
-的内核设置选项）。所以每发布一次驱动程序，都需要提供很多不同版本的内核
-模块。
-
-相信我，如果你真的要采取这种发布方式，一定会慢慢疯掉，我很久以前就有过
-深刻的教训...
-
-
-稳定的内核源代码接口
---------------------
-
-如果有人不将他的内核驱动程序，放入公版内核的源代码树，而又想让驱动程序
-一直保持在最新的内核中可用，那么这个话题将会变得没完没了。
- 内核开发是持续而且快节奏的，从来都不会慢下来。内核开发人员在当前接口中
-找到bug，或者找到更好的实现方式。一旦发现这些，他们就很快会去修改当前的
-接口。修改接口意味着，函数名可能会改变，结构体可能被扩充或者删减，函数
-的参数也可能发生改变。一旦接口被修改，内核中使用这些接口的地方需要同时
-修正，这样才能保证所有的东西继续工作。
-
-举一个例子，内核的USB驱动程序接口在USB子系统的整个生命周期中，至少经历
-了三次重写。这些重写解决以下问题：
-    - 把数据流从同步模式改成非同步模式，这个改动减少了一些驱动程序的
-复杂度，提高了所有USB驱动程序的吞吐率，这样几乎所有的USB设备都能以最大
-速率工作了。
-    - 修改了USB核心代码中为USB驱动分配数据包内存的方式，所有的驱动都
-需要提供更多的参数给USB核心，以修正了很多已经被记录在案的死锁。
-
-这和一些封闭源代码的操作系统形成鲜明的对比，在那些操作系统上，不得不额
-外的维护旧的USB接口。这导致了一个可能性，新的开发者依然会不小心使用旧的
-接口，以不恰当的方式编写代码，进而影响到操作系统的稳定性。
- 在上面的例子中，所有的开发者都同意这些重要的改动，在这样的情况下修改代
-价很低。如果Linux保持一个稳定的内核源代码接口，那么就得创建一个新的接口
-；旧的，有问题的接口必须一直维护，给Linux USB开发者带来额外的工作。既然
-所有的Linux USB驱动的作者都是利用自己的时间工作，那么要求他们去做毫无意
-义的免费额外工作，是不可能的。
- 安全问题对Linux来说十分重要。一个安全问题被发现，就会在短时间内得到修
-正。在很多情况下，这将导致Linux内核中的一些接口被重写，以从根本上避免安
-全问题。一旦接口被重写，所有使用这些接口的驱动程序，必须同时得到修正，
-以确定安全问题已经得到修复并且不可能在未来还有同样的安全问题。如果内核
-内部接口不允许改变，那么就不可能修复这样的安全问题，也不可能确认这样的
-安全问题以后不会发生。
-开发者一直在清理内核接口。如果一个接口没有人在使用了，它就会被删除。这
-样可以确保内核尽可能的小，而且所有潜在的接口都会得到尽可能完整的测试
-（没有人使用的接口是不可能得到良好的测试的）。
-
-
-要做什么
--------
-
-如果你写了一个Linux内核驱动，但是它还不在Linux源代码树里，作为一个开发
-者，你应该怎么做？为每个发布的每个版本提供一个二进制驱动，那简直是一个
-噩梦，要跟上永远处于变化之中的内核接口，也是一件辛苦活。
-很简单，让你的驱动进入内核源代码树（要记得我们在谈论的是以GPL许可发行
-的驱动，如果你的代码不符合GPL，那么祝你好运，你只能自己解决这个问题了，
-你这个吸血鬼<把Andrew和Linus对吸血鬼的定义链接到这里>）。当你的代码加入
-公版内核源代码树之后，如果一个内核接口改变，你的驱动会直接被修改接口的
-那个人修改。保证你的驱动永远都可以编译通过，并且一直工作，你几乎不需要
-做什么事情。
-
-把驱动放到内核源代码树里会有很多的好处：
-    - 驱动的质量会提升，而维护成本（对原始作者来说）会下降。
-    - 其他人会给驱动添加新特性。
-    - 其他人会找到驱动中的bug并修复。
-    - 其他人会在驱动中找到性能优化的机会。
-    - 当外部的接口的改变需要修改驱动程序的时候，其他人会修改驱动程序
-。
-    - 不需要联系任何发行商，这个驱动会自动的随着所有的Linux发布一起发
-布。
-
-和别的操作系统相比，Linux为更多不同的设备提供现成的驱动，而且能在更多不
-同体系结构的处理器上支持这些设备。这个经过考验的开发模式，必然是错不了
-的 :)
-
--------------
-感谢 Randy Dunlap, Andrew Morton, David Brownell, Hanna Linder,
-Robert Love, and Nishanth Aravamudan 对于本文档早期版本的评审和建议。
-
-英文版维护者： Greg Kroah-Hartman <greg@kroah.com>
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/stable_kernel_rules.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/stable_kernel_rules.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/stable_kernel_rules.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/stable_kernel_rules.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-Chinese translated version of Documentation/stable_kernel_rules.txt
-
-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: TripleX Chung <triplex@zh-kernel.org>
----------------------------------------------------------------------
-Documentation/stable_kernel_rules.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-
-中文版维护者： 钟宇  TripleX Chung <triplex@zh-kernel.org>
-中文版翻译者： 钟宇  TripleX Chung <triplex@zh-kernel.org>
-中文版校译者： 李阳  Li Yang <leo@zh-kernel.org>
-               Kangkai Yin <e12051@motorola.com>
-
-以下为正文
----------------------------------------------------------------------
-
-关于Linux 2.6稳定版发布，所有你想知道的事情。
-
-关于哪些类型的补丁可以被接收进入稳定版代码树，哪些不可以的规则：
-
-  - 必须是显而易见的正确，并且经过测试的。
-  - 连同上下文，不能大于100行。
-  - 必须只修正一件事情。
-  - 必须修正了一个给大家带来麻烦的真正的bug（不是“这也许是一个问题...”
-    那样的东西）。
-  - 必须修正带来如下后果的问题：编译错误（对被标记为CONFIG_BROKEN的例外），
-    内核崩溃，挂起，数据损坏，真正的安全问题，或者一些类似“哦，这不
-    好”的问题。简短的说，就是一些致命的问题。
-  - 没有“理论上的竞争条件”，除非能给出竞争条件如何被利用的解释。
-  - 不能存在任何的“琐碎的”修正（拼写修正，去掉多余空格之类的）。
-  - 必须被相关子系统的维护者接受。
-  - 必须遵循Documentation/SubmittingPatches里的规则。
-
-向稳定版代码树提交补丁的过程：
-
-  - 在确认了补丁符合以上的规则后，将补丁发送到stable@vger.kernel.org。
-  - 如果补丁被接受到队列里，发送者会收到一个ACK回复，如果没有被接受，收
-    到的是NAK回复。回复需要几天的时间，这取决于开发者的时间安排。
-  - 被接受的补丁会被加到稳定版本队列里，等待其他开发者的审查。
-  - 安全方面的补丁不要发到这个列表，应该发送到security@kernel.org。
-
-审查周期：
-
-  - 当稳定版的维护者决定开始一个审查周期，补丁将被发送到审查委员会，以
-    及被补丁影响的领域的维护者（除非提交者就是该领域的维护者）并且抄送
-    到linux-kernel邮件列表。
-  - 审查委员会有48小时的时间，用来决定给该补丁回复ACK还是NAK。
-  - 如果委员会中有成员拒绝这个补丁，或者linux-kernel列表上有人反对这个
-    补丁，并提出维护者和审查委员会之前没有意识到的问题，补丁会从队列中
-    丢弃。
-  - 在审查周期结束的时候，那些得到ACK回应的补丁将会被加入到最新的稳定版
-    发布中，一个新的稳定版发布就此产生。
-  - 安全性补丁将从内核安全小组那里直接接收到稳定版代码树中，而不是通过
-    通常的审查周期。请联系内核安全小组以获得关于这个过程的更多细节。
-
-审查委员会：
-  - 由一些自愿承担这项任务的内核开发者，和几个非志愿的组成。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/SubmittingDrivers linux-libre-4.10-rc8-gnu/Documentation/zh_CN/SubmittingDrivers
--- linux-libre-4.9-gnu/Documentation/zh_CN/SubmittingDrivers	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/SubmittingDrivers	1969-12-31 19:00:00.000000000 -0500
@@ -1,164 +0,0 @@
-﻿Chinese translated version of Documentation/SubmittingDrivers
-
-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: Li Yang <leo@zh-kernel.org>
----------------------------------------------------------------------
-Documentation/SubmittingDrivers 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-中文版维护者： 李阳  Li Yang <leo@zh-kernel.org>
-中文版翻译者： 李阳  Li Yang <leo@zh-kernel.org>
-中文版校译者： 陈琦 Maggie Chen <chenqi@beyondsoft.com>
-               王聪 Wang Cong <xiyou.wangcong@gmail.com>
-               张巍 Zhang Wei <Wei.Zhang@freescale.com>
-
-以下为正文
----------------------------------------------------------------------
-
-如何向 Linux 内核提交驱动程序
------------------------------
-
-这篇文档将会解释如何向不同的内核源码树提交设备驱动程序。请注意，如果你感
-兴趣的是显卡驱动程序，你也许应该访问 XFree86 项目(http://www.xfree86.org/)
-和／或 X.org 项目 (http://x.org)。
-
-另请参阅 Documentation/SubmittingPatches 文档。
-
-
-分配设备号
-----------
-
-块设备和字符设备的主设备号与从设备号是由 Linux 命名编号分配权威 LANANA（
-现在是 Torben Mathiasen）负责分配。申请的网址是 http://www.lanana.org/。
-即使不准备提交到主流内核的设备驱动也需要在这里分配设备号。有关详细信息，
-请参阅 Documentation/devices.txt。
-
-如果你使用的不是已经分配的设备号，那么当你提交设备驱动的时候，它将会被强
-制分配一个新的设备号，即便这个设备号和你之前发给客户的截然不同。
-
-设备驱动的提交对象
-------------------
-
-Linux 2.0:
-	此内核源码树不接受新的驱动程序。
-
-Linux 2.2:
-	此内核源码树不接受新的驱动程序。
-
-Linux 2.4:
-	如果所属的代码领域在内核的 MAINTAINERS 文件中列有一个总维护者，
-	那么请将驱动程序提交给他。如果此维护者没有回应或者你找不到恰当的
-	维护者，那么请联系 Willy Tarreau <w@1wt.eu>。
-
-Linux 2.6:
-	除了遵循和 2.4 版内核同样的规则外，你还需要在 linux-kernel 邮件
-	列表上跟踪最新的 API 变化。向 Linux 2.6 内核提交驱动的顶级联系人
-	是 Andrew Morton <akpm@linux-foundation.org>。
-
-决定设备驱动能否被接受的条件
-----------------------------
-
-许可：		代码必须使用 GNU 通用公开许可证 (GPL) 提交给 Linux，但是
-		我们并不要求 GPL 是唯一的许可。你或许会希望同时使用多种
-		许可证发布，如果希望驱动程序可以被其他开源社区（比如BSD）
-		使用。请参考 include/linux/module.h 文件中所列出的可被
-		接受共存的许可。
-
-版权：		版权所有者必须同意使用 GPL 许可。最好提交者和版权所有者
-		是相同个人或实体。否则，必需列出授权使用 GPL 的版权所有
-		人或实体，以备验证之需。
-
-接口：		如果你的驱动程序使用现成的接口并且和其他同类的驱动程序行
-		为相似，而不是去发明无谓的新接口，那么它将会更容易被接受。
-		如果你需要一个 Linux 和 NT 的通用驱动接口，那么请在用
-		户空间实现它。
-
-代码：		请使用 Documentation/CodingStyle 中所描述的 Linux 代码风
-		格。如果你的某些代码段（例如那些与 Windows 驱动程序包共
-		享的代码段）需要使用其他格式，而你却只希望维护一份代码，
-		那么请将它们很好地区分出来，并且注明原因。
-
-可移植性：	请注意，指针并不永远是 32 位的，不是所有的计算机都使用小
-		尾模式 (little endian) 存储数据，不是所有的人都拥有浮点
-		单元，不要随便在你的驱动程序里嵌入 x86 汇编指令。只能在
-		x86 上运行的驱动程序一般是不受欢迎的。虽然你可能只有 x86
-		硬件，很难测试驱动程序在其他平台上是否可用，但是确保代码
-		可以被轻松地移植却是很简单的。
-
-清晰度：	做到所有人都能修补这个驱动程序将会很有好处，因为这样你将
-		会直接收到修复的补丁而不是 bug 报告。如果你提交一个试图
-		隐藏硬件工作机理的驱动程序，那么它将会被扔进废纸篓。
-
-电源管理：	因为 Linux 正在被很多移动设备和桌面系统使用，所以你的驱
-		动程序也很有可能被使用在这些设备上。它应该支持最基本的电
-		源管理，即在需要的情况下实现系统级休眠和唤醒要用到的
-		.suspend 和 .resume 函数。你应该检查你的驱动程序是否能正
-		确地处理休眠与唤醒，如果实在无法确认，请至少把 .suspend
-		函数定义成返回 -ENOSYS（功能未实现）错误。你还应该尝试确
-		保你的驱动在什么都不干的情况下将耗电降到最低。要获得驱动
-		程序测试的指导，请参阅
-		Documentation/power/drivers-testing.txt。有关驱动程序电
-		源管理问题相对全面的概述，请参阅
-		Documentation/power/devices.txt。
-
-管理：		如果一个驱动程序的作者还在进行有效的维护，那么通常除了那
-		些明显正确且不需要任何检查的补丁以外，其他所有的补丁都会
-		被转发给作者。如果你希望成为驱动程序的联系人和更新者，最
-		好在代码注释中写明并且在 MAINTAINERS 文件中加入这个驱动
-		程序的条目。
-
-不影响设备驱动能否被接受的条件
-------------------------------
-
-供应商：	由硬件供应商来维护驱动程序通常是一件好事。不过，如果源码
-		树里已经有其他人提供了可稳定工作的驱动程序，那么请不要期
-		望“我是供应商”会成为内核改用你的驱动程序的理由。理想的情
-		况是：供应商与现有驱动程序的作者合作，构建一个统一完美的
-		驱动程序。
-
-作者：		驱动程序是由大的 Linux 公司研发还是由你个人编写，并不影
-		响其是否能被内核接受。没有人对内核源码树享有特权。只要你
-		充分了解内核社区，你就会发现这一点。
-
-
-资源列表
---------
-
-Linux 内核主源码树：
-	ftp.??.kernel.org:/pub/linux/kernel/...
-	?? == 你的国家代码，例如 "cn"、"us"、"uk"、"fr" 等等
-
-Linux 内核邮件列表：
-	linux-kernel@vger.kernel.org
-	[可通过向majordomo@vger.kernel.org发邮件来订阅]
-
-Linux 设备驱动程序，第三版（探讨 2.6.10 版内核）：
-	http://lwn.net/Kernel/LDD3/ （免费版）
-
-LWN.net:
-	每周内核开发活动摘要 - http://lwn.net/
-	2.6 版中 API 的变更：
-		http://lwn.net/Articles/2.6-kernel-api/
-	将旧版内核的驱动程序移植到 2.6 版：
-		http://lwn.net/Articles/driver-porting/
-
-内核新手(KernelNewbies):
-	为新的内核开发者提供文档和帮助
-	http://kernelnewbies.org/
-
-Linux USB项目：
-	http://www.linux-usb.org/
-
-写内核驱动的“不要”（Arjan van de Ven著）:
-	http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
-
-内核清洁工 (Kernel Janitor):
-	http://kernelnewbies.org/KernelJanitors
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/SubmittingPatches linux-libre-4.10-rc8-gnu/Documentation/zh_CN/SubmittingPatches
--- linux-libre-4.9-gnu/Documentation/zh_CN/SubmittingPatches	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/SubmittingPatches	1969-12-31 19:00:00.000000000 -0500
@@ -1,412 +0,0 @@
-Chinese translated version of Documentation/SubmittingPatches
-
-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: TripleX Chung <triplex@zh-kernel.org>
----------------------------------------------------------------------
-Documentation/SubmittingPatches 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-中文版维护者： 钟宇 TripleX Chung <triplex@zh-kernel.org>
-中文版翻译者： 钟宇 TripleX Chung <triplex@zh-kernel.org>
-中文版校译者： 李阳 Li Yang <leo@zh-kernel.org>
-               王聪 Wang Cong <xiyou.wangcong@gmail.com>
-
-以下为正文
----------------------------------------------------------------------
-
-   如何让你的改动进入内核
-     或者
-  获得亲爱的 Linus Torvalds 的关注和处理
-----------------------------------
-
-对于想要将改动提交到 Linux 内核的个人或者公司来说，如果不熟悉“规矩”，
-提交的流程会让人畏惧。本文档收集了一系列建议，这些建议可以大大的提高你
-的改动被接受的机会。
-阅读 Documentation/SubmitChecklist 来获得在提交代码前需要检查的项目的列
-表。如果你在提交一个驱动程序，那么同时阅读一下
-Documentation/SubmittingDrivers 。
-
-
---------------------------
-第一节 - 创建并发送你的改动
---------------------------
-
-1) "diff -up"
------------
-
-使用 "diff -up" 或者 "diff -uprN" 来创建补丁。
-
-所有内核的改动，都是以补丁的形式呈现的，补丁由 diff(1) 生成。创建补丁的
-时候，要确认它是以 "unified diff" 格式创建的，这种格式由 diff(1) 的 '-u'
-参数生成。而且，请使用 '-p' 参数，那样会显示每个改动所在的C函数，使得
-产生的补丁容易读得多。补丁应该基于内核源代码树的根目录，而不是里边的任
-何子目录。
-为一个单独的文件创建补丁，一般来说这样做就够了：
-
-        SRCTREE= linux-2.6
-        MYFILE=  drivers/net/mydriver.c
-
-        cd $SRCTREE
-        cp $MYFILE $MYFILE.orig
-        vi $MYFILE      # make your change
-        cd ..
-        diff -up $SRCTREE/$MYFILE{.orig,} > /tmp/patch
-
-为多个文件创建补丁，你可以解开一个没有修改过的内核源代码树，然后和你自
-己的代码树之间做 diff 。例如：
-
-        MYSRC= /devel/linux-2.6
-
-        tar xvfz linux-2.6.12.tar.gz
-        mv linux-2.6.12 linux-2.6.12-vanilla
-        diff -uprN -X linux-2.6.12-vanilla/Documentation/dontdiff \
-                linux-2.6.12-vanilla $MYSRC > /tmp/patch
-
-"dontdiff" 是内核在编译的时候产生的文件的列表，列表中的文件在 diff(1)
-产生的补丁里会被跳过。"dontdiff" 文件被包含在2.6.12和之后版本的内核源代
-码树中。对于更早的内核版本，你可以从
-<http://www.xenotime.net/linux/doc/dontdiff> 获取它。
-确定你的补丁里没有包含任何不属于这次补丁提交的额外文件。记得在用diff(1)
-生成补丁之后，审阅一次补丁，以确保准确。
-如果你的改动很散乱，你应该研究一下如何将补丁分割成独立的部分，将改动分
-割成一系列合乎逻辑的步骤。这样更容易让其他内核开发者审核，如果你想你的
-补丁被接受，这是很重要的。下面这些脚本能够帮助你做这件事情：
-Quilt:
-http://savannah.nongnu.org/projects/quilt
-
-2)描述你的改动。
-描述你的改动包含的技术细节。
-
-要多具体就写多具体。最糟糕的描述可能是像下面这些语句：“更新了某驱动程
-序”，“修正了某驱动程序的bug”，或者“这个补丁包含了某子系统的修改，请
-使用。”
-
-如果你的描述开始变长，这表示你也许需要拆分你的补丁了，请看第3小节，
-继续。
-
-3)拆分你的改动
-
-将改动拆分，逻辑类似的放到同一个补丁文件里。
-
-例如，如果你的改动里同时有bug修正和性能优化，那么把这些改动拆分到两个或
-者更多的补丁文件中。如果你的改动包含对API的修改，并且修改了驱动程序来适
-应这些新的API，那么把这些修改分成两个补丁。
-
-另一方面，如果你将一个单独的改动做成多个补丁文件，那么将它们合并成一个
-单独的补丁文件。这样一个逻辑上单独的改动只被包含在一个补丁文件里。
-
-如果有一个补丁依赖另外一个补丁来完成它的改动，那没问题。简单的在你的补
-丁描述里指出“这个补丁依赖某补丁”就好了。
-
-如果你不能将补丁浓缩成更少的文件，那么每次大约发送出15个，然后等待审查
-和整合。
-
-4)选择 e-mail 的收件人
-
-看一遍 MAINTAINERS 文件和源代码，看看你所的改动所在的内核子系统有没有指
-定的维护者。如果有，给他们发e-mail。
-
-如果没有找到维护者，或者维护者没有反馈，将你的补丁发送到内核开发者主邮
-件列表 linux-kernel@vger.kernel.org。大部分的内核开发者都跟踪这个邮件列
-表，可以评价你的改动。
-
-每次不要发送超过15个补丁到 vger 邮件列表！！！
-
-Linus Torvalds 是决定改动能否进入 Linux 内核的最终裁决者。他的 e-mail
-地址是 <torvalds@linux-foundation.org> 。他收到的 e-mail 很多，所以一般
-的说，最好别给他发 e-mail。
-
-那些修正bug，“显而易见”的修改或者是类似的只需要很少讨论的补丁可以直接
-发送或者CC给Linus。那些需要讨论或者没有很清楚的好处的补丁，一般先发送到
-linux-kernel邮件列表。只有当补丁被讨论得差不多了，才提交给Linus。
-
-5)选择CC( e-mail 抄送)列表
-
-除非你有理由不这样做，否则CC linux-kernel@vger.kernel.org。
-
-除了 Linus 之外，其他内核开发者也需要注意到你的改动，这样他们才能评论你
-的改动并提供代码审查和建议。linux-kernel 是 Linux 内核开发者主邮件列表
-。其它的邮件列表为特定的子系统提供服务，比如 USB，framebuffer 设备，虚
-拟文件系统，SCSI 子系统，等等。查看 MAINTAINERS 文件来获得和你的改动有
-关的邮件列表。
-
-Majordomo lists of VGER.KERNEL.ORG at:
-        <http://vger.kernel.org/vger-lists.html>
-
-如果改动影响了用户空间和内核之间的接口，请给 MAN-PAGES 的维护者（列在
-MAINTAINERS 文件里的）发送一个手册页（man-pages）补丁，或者至少通知一下改
-变，让一些信息有途径进入手册页。
-
-即使在第四步的时候，维护者没有作出回应，也要确认在修改他们的代码的时候
-，一直将维护者拷贝到CC列表中。
-
-对于小的补丁，你也许会CC到 Adrian Bunk 管理的搜集琐碎补丁的邮件列表
-(Trivial Patch Monkey)trivial@kernel.org，那里专门收集琐碎的补丁。下面这样
-的补丁会被看作“琐碎的”补丁：
-  文档的拼写修正。
-  修正会影响到 grep(1) 的拼写。
-  警告信息修正(频繁的打印无用的警告是不好的。)
-  编译错误修正（代码逻辑的确是对的，只是编译有问题。）
-  运行时修正（只要真的修正了错误。）
-  移除使用了被废弃的函数/宏的代码(例如 check_region。)
-  联系方式和文档修正。
-  用可移植的代码替换不可移植的代码（即使在体系结构相关的代码中，既然有
-  人拷贝，只要它是琐碎的）
-  任何文件的作者/维护者对该文件的改动（例如 patch monkey 在重传模式下）
-
-EMAIL: trivial@kernel.org
-
-(译注，关于“琐碎补丁”的一些说明：因为原文的这一部分写得比较简单，所以不得不
-违例写一下译注。"trivial"这个英文单词的本意是“琐碎的，不重要的。”但是在这里
-有稍微有一些变化，例如对一些明显的NULL指针的修正，属于运行时修正，会被归类
-到琐碎补丁里。虽然NULL指针的修正很重要，但是这样的修正往往很小而且很容易得到
-检验，所以也被归入琐碎补丁。琐碎补丁更精确的归类应该是
-“simple, localized & easy to verify”，也就是说简单的，局部的和易于检验的。
-trivial@kernel.org邮件列表的目的是针对这样的补丁，为提交者提供一个中心，来
-降低提交的门槛。)
-
-6)没有 MIME 编码，没有链接，没有压缩，没有附件，只有纯文本。
-
-Linus 和其他的内核开发者需要阅读和评论你提交的改动。对于内核开发者来说
-，可以“引用”你的改动很重要，使用一般的 e-mail 工具，他们就可以在你的
-代码的任何位置添加评论。
-
-因为这个原因，所有的提交的补丁都是 e-mail 中“内嵌”的。
-警告：如果你使用剪切-粘贴你的补丁，小心你的编辑器的自动换行功能破坏你的
-补丁。
-
-不要将补丁作为 MIME 编码的附件，不管是否压缩。很多流行的 e-mail 软件不
-是任何时候都将 MIME 编码的附件当作纯文本发送的，这会使得别人无法在你的
-代码中加评论。另外，MIME 编码的附件会让 Linus 多花一点时间来处理，这就
-降低了你的改动被接受的可能性。
-
-警告：一些邮件软件，比如 Mozilla 会将你的信息以如下格式发送：
----- 邮件头 ----
-Content-Type: text/plain; charset=us-ascii; format=flowed
----- 邮件头 ----
-问题在于 “format=flowed” 会让接收端的某些邮件软件将邮件中的制表符替换
-成空格以及做一些类似的替换。这样，你发送的时候看起来没问题的补丁就被破
-坏了。
-
-要修正这个问题，只需要将你的 mozilla 的 defaults/pref/mailnews.js 文件
-里的
-pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
-修改成
-pref("mailnews.display.disable_format_flowed_support", true);
-就可以了。
-
-7) e-mail 的大小
-
-给 Linus 发送补丁的时候，永远按照第6小节说的做。
-
-大的改动对邮件列表不合适，对某些维护者也不合适。如果你的补丁，在不压缩
-的情况下，超过了40kB，那么你最好将补丁放在一个能通过 internet 访问的服
-务器上，然后用指向你的补丁的 URL 替代。
-
-8) 指出你的内核版本
-
-在标题和在补丁的描述中，指出补丁对应的内核的版本，是很重要的。
-
-如果补丁不能干净的在最新版本的内核上打上，Linus 是不会接受它的。
-
-9) 不要气馁，继续提交。
-
-当你提交了改动以后，耐心地等待。如果 Linus 喜欢你的改动并且同意它，那么
-它将在下一个内核发布版本中出现。
-
-然而，如果你的改动没有出现在下一个版本的内核中，可能有若干原因。减少那
-些原因，修正错误，重新提交更新后的改动，是你自己的工作。
-
-Linus不给出任何评论就“丢弃”你的补丁是常见的事情。在系统中这样的事情很
-平常。如果他没有接受你的补丁，也许是由于以下原因：
-* 你的补丁不能在最新版本的内核上干净的打上。
-* 你的补丁在 linux-kernel 邮件列表中没有得到充分的讨论。
-* 风格问题（参照第2小节）
-* 邮件格式问题（重读本节）
-* 你的改动有技术问题。
-* 他收到了成吨的 e-mail，而你的在混乱中丢失了。
-* 你让人为难。
-
-有疑问的时候，在 linux-kernel 邮件列表上请求评论。
-
-10) 在标题上加上 PATCH 的字样
-
-Linus 和 linux-kernel 邮件列表的 e-mail 流量都很高，一个通常的约定是标
-题行以 [PATCH] 开头。这样可以让 Linus 和其他内核开发人员可以从 e-mail
-的讨论中很轻易的将补丁分辨出来。
-
-11）为你的工作签名
-
-为了加强对谁做了何事的追踪，尤其是对那些透过好几层的维护者的补丁，我们
-建议在发送出去的补丁上加一个 “sign-off” 的过程。
-
-"sign-off" 是在补丁的注释的最后的简单的一行文字，认证你编写了它或者其他
-人有权力将它作为开放源代码的补丁传递。规则很简单：如果你能认证如下信息
-：
-      开发者来源证书 1.1
-      对于本项目的贡献，我认证如下信息：
-      （a）这些贡献是完全或者部分的由我创建，我有权利以文件中指出
-       的开放源代码许可证提交它；或者
-      （b）这些贡献基于以前的工作，据我所知，这些以前的工作受恰当的开放
-       源代码许可证保护，而且，根据许可证，我有权提交修改后的贡献，
-       无论是完全还是部分由我创造，这些贡献都使用同一个开放源代码许可证
-       （除非我被允许用其它的许可证），正如文件中指出的；或者
-      （c）这些贡献由认证（a），（b）或者（c）的人直接提供给我，而
-       且我没有修改它。
-      （d）我理解并同意这个项目和贡献是公开的，贡献的记录（包括我
-       一起提交的个人记录，包括 sign-off ）被永久维护并且可以和这个项目
-       或者开放源代码的许可证同步地再发行。
-       那么加入这样一行：
-       Signed-off-by: Random J Developer <random@developer.example.org>
-
-使用你的真名（抱歉，不能使用假名或者匿名。）
-
-有人在最后加上标签。现在这些东西会被忽略，但是你可以这样做，来标记公司
-内部的过程，或者只是指出关于 sign-off 的一些特殊细节。
-
-12）标准补丁格式
-
-标准的补丁，标题行是：
-    Subject: [PATCH 001/123] 子系统:一句话概述
-
-标准补丁的信体存在如下部分：
-
-  - 一个 "from" 行指出补丁作者。
-
-  - 一个空行
-
-  - 说明的主体，这些说明文字会被拷贝到描述该补丁的永久改动记录里。
-
-  - 一个由"---"构成的标记行
-
-  - 不合适放到改动记录里的额外的注解。
-
-  - 补丁本身（diff 输出）
-
-标题行的格式，使得对标题行按字母序排序非常的容易 - 很多 e-mail 客户端都
-可以支持 - 因为序列号是用零填充的，所以按数字排序和按字母排序是一样的。
-
-e-mail 标题中的“子系统”标识哪个内核子系统将被打补丁。
-
-e-mail 标题中的“一句话概述”扼要的描述 e-mail 中的补丁。“一句话概述”
-不应该是一个文件名。对于一个补丁系列（“补丁系列”指一系列的多个相关补
-丁），不要对每个补丁都使用同样的“一句话概述”。
-
-记住 e-mail 的“一句话概述”会成为该补丁的全局唯一标识。它会蔓延到 git
-的改动记录里。然后“一句话概述”会被用在开发者的讨论里，用来指代这个补
-丁。用户将希望通过 google 来搜索"一句话概述"来找到那些讨论这个补丁的文
-章。
-
-一些标题的例子：
-
-    Subject: [patch 2/5] ext2: improve scalability of bitmap searching
-    Subject: [PATCHv2 001/207] x86: fix eflags tracking
-
-"from" 行是信体里的最上面一行，具有如下格式：
-        From: Original Author <author@example.com>
-
-"from" 行指明在永久改动日志里，谁会被确认为作者。如果没有 "from" 行，那
-么邮件头里的 "From: " 行会被用来决定改动日志中的作者。
-
-说明的主题将会被提交到永久的源代码改动日志里，因此对那些早已经不记得和
-这个补丁相关的讨论细节的有能力的读者来说，是有意义的。
-
-"---" 标记行对于补丁处理工具要找到哪里是改动日志信息的结束，是不可缺少
-的。
-
-对于 "---" 标记之后的额外注解，一个好的用途就是用来写 diffstat，用来显
-示修改了什么文件和每个文件都增加和删除了多少行。diffstat 对于比较大的补
-丁特别有用。其余那些只是和时刻或者开发者相关的注解，不合适放到永久的改
-动日志里的，也应该放这里。
-使用 diffstat的选项 "-p 1 -w 70" 这样文件名就会从内核源代码树的目录开始
-，不会占用太宽的空间（很容易适合80列的宽度，也许会有一些缩进。）
-
-在后面的参考资料中能看到适当的补丁格式的更多细节。
-
--------------------------------
-第二节 提示，建议和诀窍
--------------------------------
-
-本节包含很多和提交到内核的代码有关的通常的"规则"。事情永远有例外...但是
-你必须真的有好的理由这样做。你可以把本节叫做Linus的计算机科学入门课。
-
-1) 读 Document/CodingStyle
-
-Nuff 说过，如果你的代码和这个偏离太多，那么它有可能会被拒绝，没有更多的
-审查，没有更多的评价。
-
-2) #ifdef 是丑陋的
-混杂了 ifdef 的代码难以阅读和维护。别这样做。作为替代，将你的 ifdef 放
-在头文件里，有条件地定义 "static inline" 函数，或者宏，在代码里用这些东
-西。让编译器把那些"空操作"优化掉。
-
-一个简单的例子，不好的代码：
-
-    dev = alloc_etherdev (sizeof(struct funky_private));
-    if (!dev)
-        return -ENODEV;
-    #ifdef CONFIG_NET_FUNKINESS
-    init_funky_net(dev);
-    #endif
-
-清理后的例子:
-
-(头文件里)
-    #ifndef CONFIG_NET_FUNKINESS
-    static inline void init_funky_net (struct net_device *d) {}
-    #endif
-
-(代码文件里)
-    dev = alloc_etherdev (sizeof(struct funky_private));
-    if (!dev)
-        return -ENODEV;
-    init_funky_net(dev);
-
-3) 'static inline' 比宏好
-
-Static inline 函数相比宏来说，是好得多的选择。Static inline 函数提供了
-类型安全，没有长度限制，没有格式限制，在 gcc 下开销和宏一样小。
-
-宏只在 static inline 函数不是最优的时候[在 fast paths 里有很少的独立的
-案例]，或者不可能用 static inline 函数的时候[例如字符串分配]。
-应该用 'static inline' 而不是 'static __inline__', 'extern inline' 和
-'extern __inline__' 。
-
-4) 不要过度设计
-
-不要试图预计模糊的未来事情，这些事情也许有用也许没有用："让事情尽可能的
-简单，而不是更简单"。
-
-----------------
-第三节 参考文献
-----------------
-
-Andrew Morton, "The perfect patch" (tpp).
-  <http://www.ozlabs.org/~akpm/stuff/tpp.txt>
-
-Jeff Garzik, "Linux kernel patch submission format".
-  <http://linux.yyz.us/patch-format.html>
-
-Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
-  <http://www.kroah.com/log/2005/03/31/>
-  <http://www.kroah.com/log/2005/07/08/>
-  <http://www.kroah.com/log/2005/10/19/>
-  <http://www.kroah.com/log/2006/01/11/>
-
-NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
-  <https://lkml.org/lkml/2005/7/11/336>
-
-Kernel Documentation/CodingStyle:
-  <http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
-
-Linus Torvalds's mail on the canonical patch format:
-  <http://lkml.org/lkml/2005/4/7/183>
---
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/video4linux/omap3isp.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/video4linux/omap3isp.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/video4linux/omap3isp.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/video4linux/omap3isp.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,277 +0,0 @@
-Chinese translated version of Documentation/video4linux/omap3isp.txt
-
-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.
-
-Maintainer: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-	  Sakari Ailus <sakari.ailus@iki.fi>
-	  David Cohen <dacohen@gmail.com>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/video4linux/omap3isp.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-英文版维护者： Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-	  Sakari Ailus <sakari.ailus@iki.fi>
-	  David Cohen <dacohen@gmail.com>
-中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-OMAP 3 图像信号处理器 (ISP) 驱动
-
-Copyright (C) 2010 Nokia Corporation
-Copyright (C) 2009 Texas Instruments, Inc.
-
-联系人: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-	  Sakari Ailus <sakari.ailus@iki.fi>
-	  David Cohen <dacohen@gmail.com>
-
-
-介绍
-===
-
-本文档介绍了由 drivers/media/video/omap3isp 加载的德州仪器
-（TI）OMAP 3 图像信号处理器 (ISP) 驱动。原始驱动由德州仪器（TI）
-编写，但此后由诺基亚重写了两次。
-
-驱动已在以下 OMAP 3 系列的芯片中成功使用：
-
-	3430
-	3530
-	3630
-
-驱动实现了 V4L2、媒体控制器和 v4l2_subdev 接口。支持内核中使用
-v4l2_subdev 接口的传感器、镜头和闪光灯驱动。
-
-
-拆分为子设备
-==========
-
-OMAP 3 ISP 被拆分为 V4L2 子设备，ISP中的每个模块都由一个子设备
-来表示。每个子设备向用户空间提供一个 V4L2 子设备接口。
-
-	OMAP3 ISP CCP2
-	OMAP3 ISP CSI2a
-	OMAP3 ISP CCDC
-	OMAP3 ISP preview
-	OMAP3 ISP resizer
-	OMAP3 ISP AEWB
-	OMAP3 ISP AF
-	OMAP3 ISP histogram
-
-ISP 中每个可能的连接都通过一个链接嵌入到媒体控制器接口中。详见例程 [2]。
-
-
-控制 OMAP 3 ISP
-==============
-
-通常，对 OMAP 3 ISP 的配置会在下一帧起始时生效。在传感器垂直消隐期间，
-模块变为空闲时完成配置。在内存到内存的操作中，视频管道一次处理一帧。
-应用配置应在帧间完成。
-
-ISP 中的所有模块，除 CSI-2 和 （可能存在的）CCP2 接收器外，都必须
-接收完整的帧数据。因此，传感器必须保证从不发送部分帧数据给ISP。
-
-Autoidle（自动空闲）功能至少在 3430 的 ISP 模块中确实存在一些问题。
-当 omap3isp 模块参数 autoidle 非零时，autoidle（自动空闲）功能
-仅在 3630 中启用了。
-
-
-事件机制
-======
-
-OMAP 3 ISP 驱动在 CCDC 和统计（AEWB、AF 和 直方图）子设备中支持
-V4L2 事件机制接口。
-
-CCDC 子设备通过 HS_VS 中断，处理 V4L2_EVENT_FRAME_SYNC 类型
-事件，用于告知帧起始。早期版本的驱动则使用 V4L2_EVENT_OMAP3ISP_HS_VS。
-当在 CCDC 模块中接收到起始帧的第一行时，会准确地触发事件。这个事件
-可以在 CCDC 子设备中“订阅”。
-
-（当使用并行接口时，必须注意正确地配置 VS 信号极性。而当使用串行接收时
-这个会自动校正。）
-
-每个统计子设备都可以产生事件。每当一个统计缓冲区可由用户空间应用程序
-通过 VIDIOC_OMAP3ISP_STAT_REQ IOCTL 操作获取时，就会产生一个
-事件。当前存在以下事件：
-
-	V4L2_EVENT_OMAP3ISP_AEWB
-	V4L2_EVENT_OMAP3ISP_AF
-	V4L2_EVENT_OMAP3ISP_HIST
-
-这些 ioctl 的事件数据类型为 struct omap3isp_stat_event_status
-结构体。如果出现计算错误的统计，也同样会产生一个事件，但没有相关的统计
-数据缓冲区。这种情况下 omap3isp_stat_event_status.buf_err 会被
-设置为非零值。
-
-
-私有 IOCTL
-==========
-
-OMAP 3 ISP 驱动支持标准的 V4L2 IOCTL 以及可能存在且实用的控制。但
-ISP 提供的许多功能都不在标准 IOCTL 之列，例如 gamma（伽马）表和统计
-数据采集配置等。
-
-通常，会有一个私有 ioctl 用于配置每个包含硬件依赖功能的模块。
-
-支持以下私有 IOCTL：
-
-	VIDIOC_OMAP3ISP_CCDC_CFG
-	VIDIOC_OMAP3ISP_PRV_CFG
-	VIDIOC_OMAP3ISP_AEWB_CFG
-	VIDIOC_OMAP3ISP_HIST_CFG
-	VIDIOC_OMAP3ISP_AF_CFG
-	VIDIOC_OMAP3ISP_STAT_REQ
-	VIDIOC_OMAP3ISP_STAT_EN
-
-在 include/linux/omap3isp.h 中描述了这些 ioctl 使用的参数结构体。
-与特定 ISP 模块相关的 ISP 自身的详细功能在技术参考手册 (TRMs)中有
-描述，详见文档结尾。
-
-虽然在不使用任何私有 IOCTL 的情况下使用 ISP 驱动是可能的，但这样无法
-获得最佳的图像质量。AEWB、AF 和 直方图（译者注：一般用于自动曝光和增益
-控制，以及图像均衡等）模块无法在未使用适当的私有 IOCTL 配置的情况下使用。
-
-
-CCDC 和 preview（预览）模块 IOCTL
-===============================
-
-VIDIOC_OMAP3ISP_CCDC_CFG 和 VIDIOC_OMAP3ISP_PRV_CFG IOCTL
-被分别用于配置、启用和禁用 CCDC 和 preview（预览）模块的功能。在它们
-所控制的模块中，两个 IOCTL 控制多种功能。VIDIOC_OMAP3ISP_CCDC_CFG IOCTL
-接受一个指向 omap3isp_ccdc_update_config 结构体的指针作为它的参数。
-同样的，VIDIOC_OMAP3ISP_PRV_CFG 接受一个指向 omap3isp_prev_update_config
-结构体的指针。以上两个结构体定义位于 [1]。
-
-这些结构体中的 update 域标识是否针对指定的功能更新配置，而 flag 域
-则标识是启用还是禁用此功能。
-
-update 和 flag 位接受以下掩码值。CCDC 和 preview（预览）模块的
-每个单独功能都与一个 flag 关联（禁用或启用；在结构体中 flag 域的
-一部分）和一个指向功能配置数据的指针。
-
-对于 VIDIOC_OMAP3ISP_CCDC_CFG，下面列出了 update 和 flag 域
-中的有效值。 这些值可能会在同一个 IOCTL 调用中配置多个功能。
-
-        OMAP3ISP_CCDC_ALAW
-        OMAP3ISP_CCDC_LPF
-        OMAP3ISP_CCDC_BLCLAMP
-        OMAP3ISP_CCDC_BCOMP
-        OMAP3ISP_CCDC_FPC
-        OMAP3ISP_CCDC_CULL
-        OMAP3ISP_CCDC_CONFIG_LSC
-        OMAP3ISP_CCDC_TBL_LSC
-
-针对 VIDIOC_OMAP3ISP_PRV_CFG 的相应值如下：
-
-        OMAP3ISP_PREV_LUMAENH
-        OMAP3ISP_PREV_INVALAW
-        OMAP3ISP_PREV_HRZ_MED
-        OMAP3ISP_PREV_CFA
-        OMAP3ISP_PREV_CHROMA_SUPP
-        OMAP3ISP_PREV_WB
-        OMAP3ISP_PREV_BLKADJ
-        OMAP3ISP_PREV_RGB2RGB
-        OMAP3ISP_PREV_COLOR_CONV
-        OMAP3ISP_PREV_YC_LIMIT
-        OMAP3ISP_PREV_DEFECT_COR
-        OMAP3ISP_PREV_GAMMABYPASS
-        OMAP3ISP_PREV_DRK_FRM_CAPTURE
-        OMAP3ISP_PREV_DRK_FRM_SUBTRACT
-        OMAP3ISP_PREV_LENS_SHADING
-        OMAP3ISP_PREV_NF
-        OMAP3ISP_PREV_GAMMA
-
-在启用某个功能的时候，相关的配置数据指针不可为 NULL。在禁用某个功能时，
-配置数据指针会被忽略。
-
-
-统计模块 IOCTL
-=============
-
-统计子设备相较于其他子设备提供了更多动态配置选项。在图像处理流水线处于
-工作状态时，它们可以被启用、禁用和重配。
-
-统计模块总是从 CCDC 中获取输入的图像数据（由于直方图内存读取未实现）。
-统计数据可由用户通过统计子设备节点使用私有 IOCTL 获取。
-
-AEWB、AF 和 直方图子设备提供的私有 IOCTL 极大程度上反应了 ISP 硬件
-提供的寄存器级接口。有些方面纯粹和驱动程序的实现相关，这些将在下面讨论。
-
-VIDIOC_OMAP3ISP_STAT_EN
------------------------
-
-这个私有 IOCTL 启用/禁用 一个统计模块。如果这个申请在视频流启动前完成，
-它将在视频流水线开始工作时生效。如果视频流水线已经处于工作状态了，它将在
-CCDC 变为空闲时生效。
-
-VIDIOC_OMAP3ISP_AEWB_CFG, VIDIOC_OMAP3ISP_HIST_CFG and VIDIOC_OMAP3ISP_AF_CFG
------------------------------------------------------------------------------
-
-这些 IOCTL 用于配置模块。它们要求用户应用程序对硬件有深入的认识。对
-大多数域的解释可以在 OMAP 的 TRM 中找到。以下两个域对于以上所有的
-私有 IOCTL 配置都很常见，由于他们没有在 TRM 中提及，故需要对其有
-更好的认识。
-
-omap3isp_[h3a_af/h3a_aewb/hist]_config.buf_size:
-
-模块在内部处理自身缓冲。对模块数据输出所必需的缓存大小依赖于已申请的配置。
-虽然驱动支持在视频流工作时重新配置，但对于所需缓存量大于模块启用时内部
-所分配数量的情况，则不支持重新配置。在这种情况下将返回 -EBUSY。为了避免
-此类状况，无论是禁用/重配/启用模块，还是第一次配置时申请必须的缓存大小，
-都应在模块禁用的情况下进行。
-
-内部缓冲分配的大小需综合考虑所申请配置的最小缓存量以及 buf_size 域中
-所设的值。如果 buf_size 域在[minimum（最小值）, maximum（最大值）]
-缓冲大小范围之外，则应该将其调整到其范围中。驱动则会选择最大值。正确的
-buf_size 值将回写到用户应用程序中。
-
-omap3isp_[h3a_af/h3a_aewb/hist]_config.config_counter:
-
-由于配置并未在申请之后同步生效，驱动必须提供一个跟踪这类信息的方法，
-以提供更准确的数据。在一个配置被申请之后，返回到用户空间应用程序的
-config_counter 是一个与其配置相关的唯一值。当用户应用程序接收到
-一个缓冲可用或一个新的缓冲申请事件时，这个 config_counter 用于
-一个缓冲数据和一个配置的匹配。
-
-VIDIOC_OMAP3ISP_STAT_REQ
-------------------------
-
-将内部缓冲队列中最早的数据发送到用户空间，然后丢弃此缓冲区。
-omap3isp_stat_data.frame_number 域与视频缓冲的 field_count
-域相匹配。
-
-
-技术参考手册 (TRMs) 和其他文档
-==========================
-
-OMAP 3430 TRM:
-<URL:http://focus.ti.com/pdfs/wtbu/OMAP34xx_ES3.1.x_PUBLIC_TRM_vZM.zip>
-参考于 2011-03-05.
-
-OMAP 35xx TRM:
-<URL:http://www.ti.com/litv/pdf/spruf98o> 参考于 2011-03-05.
-
-OMAP 3630 TRM:
-<URL:http://focus.ti.com/pdfs/wtbu/OMAP36xx_ES1.x_PUBLIC_TRM_vQ.zip>
-参考于 2011-03-05.
-
-DM 3730 TRM:
-<URL:http://www.ti.com/litv/pdf/sprugn4h> 参考于 2011-03-06.
-
-
-参考资料
-=======
-
-[1] include/linux/omap3isp.h
-
-[2] http://git.ideasonboard.org/?p=media-ctl.git;a=summary
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/video4linux/v4l2-framework.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,976 +0,0 @@
-Chinese translated version of Documentation/video4linux/v4l2-framework.txt
-
-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.
-
-Maintainer: Mauro Carvalho Chehab <mchehab@infradead.org>
-Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
----------------------------------------------------------------------
-Documentation/video4linux/v4l2-framework.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-英文版维护者： Mauro Carvalho Chehab <mchehab@infradead.org>
-中文版维护者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版翻译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-中文版校译者： 傅炜 Fu Wei <tekkamanninja@gmail.com>
-
-
-以下为正文
----------------------------------------------------------------------
-V4L2 驱动框架概览
-==============
-
-本文档描述 V4L2 框架所提供的各种结构和它们之间的关系。
-
-
-介绍
-----
-
-大部分现代 V4L2 设备由多个 IC 组成，在 /dev 下导出多个设备节点，
-并同时创建非 V4L2 设备（如 DVB、ALSA、FB、I2C 和红外输入设备）。
-由于这种硬件的复杂性，V4L2 驱动也变得非常复杂。
-
-尤其是 V4L2 必须支持 IC 实现音视频的多路复用和编解码，这就更增加了其
-复杂性。通常这些 IC 通过一个或多个 I2C 总线连接到主桥驱动器，但也可
-使用其他总线。这些设备称为“子设备”。
-
-长期以来，这个框架仅限于通过 video_device 结构体创建 V4L 设备节点，
-并使用 video_buf 处理视频缓冲（注：本文不讨论 video_buf 框架）。
-
-这意味着所有驱动必须自己设置设备实例并连接到子设备。其中一部分要正确地
-完成是比较复杂的，使得许多驱动都没有正确地实现。
-
-由于框架的缺失，有很多通用代码都不可重复利用。
-
-因此，这个框架构建所有驱动都需要的基本结构块，而统一的框架将使通用代码
-创建成实用函数并在所有驱动中共享变得更加容易。
-
-
-驱动结构
--------
-
-所有 V4L2 驱动都有如下结构：
-
-1) 每个设备实例的结构体--包含其设备状态。
-
-2) 初始化和控制子设备的方法（如果有）。
-
-3) 创建 V4L2 设备节点 (/dev/videoX、/dev/vbiX 和 /dev/radioX)
-   并跟踪设备节点的特定数据。
-
-4) 特定文件句柄结构体--包含每个文件句柄的数据。
-
-5) 视频缓冲处理。
-
-以下是它们的初略关系图：
-
-    device instances（设备实例）
-      |
-      +-sub-device instances（子设备实例）
-      |
-      \-V4L2 device nodes（V4L2 设备节点）
-	  |
-	  \-filehandle instances（文件句柄实例）
-
-
-框架结构
--------
-
-该框架非常类似驱动结构：它有一个 v4l2_device 结构用于保存设备
-实例的数据；一个 v4l2_subdev 结构体代表子设备实例；video_device
-结构体保存 V4L2 设备节点的数据；将来 v4l2_fh 结构体将跟踪文件句柄
-实例（暂未尚未实现）。
-
-V4L2 框架也可与媒体框架整合（可选的）。如果驱动设置了 v4l2_device
-结构体的 mdev 域，子设备和视频节点的入口将自动出现在媒体框架中。
-
-
-v4l2_device 结构体
-----------------
-
-每个设备实例都通过 v4l2_device (v4l2-device.h)结构体来表示。
-简单设备可以仅分配这个结构体，但在大多数情况下，都会将这个结构体
-嵌入到一个更大的结构体中。
-
-你必须注册这个设备实例：
-
-	v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
-
-注册操作将会初始化 v4l2_device 结构体。如果 dev->driver_data 域
-为 NULL，就将其指向 v4l2_dev。
-
-需要与媒体框架整合的驱动必须手动设置 dev->driver_data，指向包含
-v4l2_device 结构体实例的驱动特定设备结构体。这可以在注册 V4L2 设备
-实例前通过 dev_set_drvdata() 函数完成。同时必须设置 v4l2_device
-结构体的 mdev 域，指向适当的初始化并注册过的 media_device 实例。
-
-如果 v4l2_dev->name 为空，则它将被设置为从 dev 中衍生出的值（为了
-更加精确，形式为驱动名后跟 bus_id）。如果你在调用 v4l2_device_register
-前已经设置好了，则不会被修改。如果 dev 为 NULL，则你*必须*在调用
-v4l2_device_register 前设置 v4l2_dev->name。
-
-你可以基于驱动名和驱动的全局 atomic_t 类型的实例编号，通过
-v4l2_device_set_name() 设置 name。这样会生成类似 ivtv0、ivtv1 等
-名字。若驱动名以数字结尾，则会在编号和驱动名间插入一个破折号，如：
-cx18-0、cx18-1 等。此函数返回实例编号。
-
-第一个 “dev” 参数通常是一个指向 pci_dev、usb_interface 或
-platform_device 的指针。很少使其为 NULL，除非是一个ISA设备或者
-当一个设备创建了多个 PCI 设备，使得 v4l2_dev 无法与一个特定的父设备
-关联。
-
-你也可以提供一个 notify() 回调，使子设备可以调用它实现事件通知。
-但这个设置与子设备相关。子设备支持的任何通知必须在
-include/media/<subdevice>.h 中定义一个消息头。
-
-注销 v4l2_device 使用如下函数：
-
-	v4l2_device_unregister(struct v4l2_device *v4l2_dev);
-
-如果 dev->driver_data 域指向 v4l2_dev，将会被重置为 NULL。注销同时
-会自动从设备中注销所有子设备。
-
-如果你有一个热插拔设备（如USB设备），则当断开发生时，父设备将无效。
-由于 v4l2_device 有一个指向父设备的指针必须被清除，同时标志父设备
-已消失，所以必须调用以下函数：
-
-	v4l2_device_disconnect(struct v4l2_device *v4l2_dev);
-
-这个函数并*不*注销子设备，因此你依然要调用 v4l2_device_unregister()
-函数。如果你的驱动器并非热插拔的，就没有必要调用 v4l2_device_disconnect()。
-
-有时你需要遍历所有被特定驱动注册的设备。这通常发生在多个设备驱动使用
-同一个硬件的情况下。如：ivtvfb 驱动是一个使用 ivtv 硬件的帧缓冲驱动，
-同时 alsa 驱动也使用此硬件。
-
-你可以使用如下例程遍历所有注册的设备：
-
-static int callback(struct device *dev, void *p)
-{
-	struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
-
-	/* 测试这个设备是否已经初始化 */
-	if (v4l2_dev == NULL)
-		return 0;
-	...
-	return 0;
-}
-
-int iterate(void *p)
-{
-	struct device_driver *drv;
-	int err;
-
-	/* 在PCI 总线上查找ivtv驱动。
-	   pci_bus_type是全局的. 对于USB总线使用usb_bus_type。 */
-	drv = driver_find("ivtv", &pci_bus_type);
-	/* 遍历所有的ivtv设备实例 */
-	err = driver_for_each_device(drv, NULL, p, callback);
-	put_driver(drv);
-	return err;
-}
-
-有时你需要一个设备实例的运行计数。这个通常用于映射一个设备实例到一个
-模块选择数组的索引。
-
-推荐方法如下：
-
-static atomic_t drv_instance = ATOMIC_INIT(0);
-
-static int drv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
-{
-	...
-	state->instance = atomic_inc_return(&drv_instance) - 1;
-}
-
-如果你有多个设备节点，对于热插拔设备，知道何时注销 v4l2_device 结构体
-就比较困难。为此 v4l2_device 有引用计数支持。当调用 video_register_device
-时增加引用计数，而设备节点释放时减小引用计数。当引用计数为零，则
-v4l2_device 的release() 回调将被执行。你就可以在此时做最后的清理工作。
-
-如果创建了其他设备节点（比如 ALSA），则你可以通过以下函数手动增减
-引用计数：
-
-void v4l2_device_get(struct v4l2_device *v4l2_dev);
-
-或:
-
-int v4l2_device_put(struct v4l2_device *v4l2_dev);
-
-由于引用技术初始化为 1 ，你也需要在 disconnect() 回调（对于 USB 设备）中
-调用 v4l2_device_put，或者 remove() 回调（例如对于 PCI 设备），否则
-引用计数将永远不会为 0 。
-
-v4l2_subdev结构体
-------------------
-
-许多驱动需要与子设备通信。这些设备可以完成各种任务，但通常他们负责
-音视频复用和编解码。如网络摄像头的子设备通常是传感器和摄像头控制器。
-
-这些一般为 I2C 接口设备，但并不一定都是。为了给驱动提供调用子设备的
-统一接口，v4l2_subdev 结构体（v4l2-subdev.h）产生了。
-
-每个子设备驱动都必须有一个 v4l2_subdev 结构体。这个结构体可以单独
-代表一个简单的子设备，也可以嵌入到一个更大的结构体中，与更多设备状态
-信息保存在一起。通常有一个下级设备结构体（比如：i2c_client）包含了
-内核创建的设备数据。建议使用 v4l2_set_subdevdata() 将这个结构体的
-指针保存在 v4l2_subdev 的私有数据域(dev_priv)中。这使得通过 v4l2_subdev
-找到实际的低层总线特定设备数据变得容易。
-
-你同时需要一个从低层结构体获取 v4l2_subdev 指针的方法。对于常用的
-i2c_client 结构体，i2c_set_clientdata() 函数可用于保存一个 v4l2_subdev
-指针；对于其他总线你可能需要使用其他相关函数。
-
-桥驱动中也应保存每个子设备的私有数据，比如一个指向特定桥的各设备私有
-数据的指针。为此 v4l2_subdev 结构体提供主机私有数据域(host_priv)，
-并可通过 v4l2_get_subdev_hostdata() 和 v4l2_set_subdev_hostdata()
-访问。
-
-从总线桥驱动的视角，驱动加载子设备模块并以某种方式获得 v4l2_subdev
-结构体指针。对于 i2c 总线设备相对简单：调用 i2c_get_clientdata()。
-对于其他总线也需要做类似的操作。针对 I2C 总线上的子设备辅助函数帮你
-完成了大部分复杂的工作。
-
-每个 v4l2_subdev 都包含子设备驱动需要实现的函数指针（如果对此设备
-不适用，可为NULL）。由于子设备可完成许多不同的工作，而在一个庞大的
-函数指针结构体中通常仅有少数有用的函数实现其功能肯定不合适。所以，
-函数指针根据其实现的功能被分类，每一类都有自己的函数指针结构体。
-
-顶层函数指针结构体包含了指向各类函数指针结构体的指针，如果子设备驱动
-不支持该类函数中的任何一个功能，则指向该类结构体的指针为NULL。
-
-这些结构体定义如下：
-
-struct v4l2_subdev_core_ops {
-	int (*log_status)(struct v4l2_subdev *sd);
-	int (*init)(struct v4l2_subdev *sd, u32 val);
-	...
-};
-
-struct v4l2_subdev_tuner_ops {
-	...
-};
-
-struct v4l2_subdev_audio_ops {
-	...
-};
-
-struct v4l2_subdev_video_ops {
-	...
-};
-
-struct v4l2_subdev_pad_ops {
-	...
-};
-
-struct v4l2_subdev_ops {
-	const struct v4l2_subdev_core_ops  *core;
-	const struct v4l2_subdev_tuner_ops *tuner;
-	const struct v4l2_subdev_audio_ops *audio;
-	const struct v4l2_subdev_video_ops *video;
-	const struct v4l2_subdev_pad_ops *video;
-};
-
-其中 core（核心）函数集通常可用于所有子设备，其他类别的实现依赖于
-子设备。如视频设备可能不支持音频操作函数，反之亦然。
-
-这样的设置在限制了函数指针数量的同时，还使增加新的操作函数和分类
-变得较为容易。
-
-子设备驱动可使用如下函数初始化 v4l2_subdev 结构体：
-
-	v4l2_subdev_init(sd, &ops);
-
-然后，你必须用一个唯一的名字初始化 subdev->name，并初始化模块的
-owner 域。若使用 i2c 辅助函数，这些都会帮你处理好。
-
-若需同媒体框架整合，你必须调用 media_entity_pads_init() 初始化 v4l2_subdev
-结构体中的 media_entity 结构体（entity 域）：
-
-	struct media_pad *pads = &my_sd->pads;
-	int err;
-
-	err = media_entity_pads_init(&sd->entity, npads, pads);
-
-pads 数组必须预先初始化。无须手动设置 media_entity 的 type 和
-name 域，但如有必要，revision 域必须初始化。
-
-当（任何）子设备节点被打开/关闭，对 entity 的引用将被自动获取/释放。
-
-在子设备被注销之后，不要忘记清理 media_entity 结构体：
-
-	media_entity_cleanup(&sd->entity);
-
-如果子设备驱动趋向于处理视频并整合进了媒体框架，必须使用 v4l2_subdev_pad_ops
-替代 v4l2_subdev_video_ops 实现格式相关的功能。
-
-这种情况下，子设备驱动应该设置 link_validate 域，以提供它自身的链接
-验证函数。链接验证函数应对管道（两端链接的都是 V4L2 子设备）中的每个
-链接调用。驱动还要负责验证子设备和视频节点间格式配置的正确性。
-
-如果 link_validate 操作没有设置，默认的 v4l2_subdev_link_validate_default()
-函数将会被调用。这个函数保证宽、高和媒体总线像素格式在链接的收发两端
-都一致。子设备驱动除了它们自己的检测外，也可以自由使用这个函数以执行
-上面提到的检查。
-
-设备（桥）驱动程序必须向 v4l2_device 注册 v4l2_subdev：
-
-	int err = v4l2_device_register_subdev(v4l2_dev, sd);
-
-如果子设备模块在它注册前消失，这个操作可能失败。在这个函数成功返回后，
-subdev->dev 域就指向了 v4l2_device。
-
-如果 v4l2_device 父设备的 mdev 域为非 NULL 值，则子设备实体将被自动
-注册为媒体设备。
-
-注销子设备则可用如下函数：
-
-	v4l2_device_unregister_subdev(sd);
-
-此后，子设备模块就可卸载，且 sd->dev == NULL。
-
-注册之设备后，可通过以下方式直接调用其操作函数：
-
-	err = sd->ops->core->g_std(sd, &norm);
-
-但使用如下宏会比较容易且合适：
-
-	err = v4l2_subdev_call(sd, core, g_std, &norm);
-
-这个宏将会做 NULL 指针检查，如果 subdev 为 NULL，则返回-ENODEV；如果
-subdev->core 或 subdev->core->g_std 为 NULL，则返回 -ENOIOCTLCMD；
-否则将返回 subdev->ops->core->g_std ops 调用的实际结果。
-
-有时也可能同时调用所有或一系列子设备的某个操作函数：
-
-	v4l2_device_call_all(v4l2_dev, 0, core, g_std, &norm);
-
-任何不支持此操作的子设备都会被跳过，并忽略错误返回值。但如果你需要
-检查出错码，则可使用如下函数：
-
-	err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_std, &norm);
-
-除 -ENOIOCTLCMD 外的任何错误都会跳出循环并返回错误值。如果（除 -ENOIOCTLCMD
-外）没有错误发生，则返回 0。
-
-对于以上两个函数的第二个参数为组 ID。如果为 0，则所有子设备都会执行
-这个操作。如果为非 0 值，则只有那些组 ID 匹配的子设备才会执行此操作。
-在桥驱动注册一个子设备前，可以设置 sd->grp_id 为任何期望值（默认值为
-0）。这个值属于桥驱动，且子设备驱动将不会修改和使用它。
-
-组 ID 赋予了桥驱动更多对于如何调用回调的控制。例如，电路板上有多个
-音频芯片，每个都有改变音量的能力。但当用户想要改变音量的时候，通常
-只有一个会被实际使用。你可以对这样的子设备设置组 ID 为（例如 AUDIO_CONTROLLER）
-并在调用 v4l2_device_call_all() 时指定它为组 ID 值。这就保证了只有
-需要的子设备才会执行这个回调。
-
-如果子设备需要通知它的 v4l2_device 父设备一个事件，可以调用
-v4l2_subdev_notify(sd, notification, arg)。这个宏检查是否有一个
-notify() 回调被注册，如果没有，返回 -ENODEV。否则返回 notify() 调用
-结果。
-
-使用 v4l2_subdev 的好处在于它是一个通用结构体，且不包含任何底层硬件
-信息。所有驱动可以包含多个 I2C 总线的子设备，但也有子设备是通过 GPIO
-控制。这个区别仅在配置设备时有关系，一旦子设备注册完成，对于 v4l2
-子系统来说就完全透明了。
-
-
-V4L2 子设备用户空间API
---------------------
-
-除了通过 v4l2_subdev_ops 结构导出的内核 API，V4L2 子设备也可以直接
-通过用户空间应用程序来控制。
-
-可以在 /dev 中创建名为 v4l-subdevX 设备节点，以通过其直接访问子设备。
-如果子设备支持用户空间直接配置，必须在注册前设置 V4L2_SUBDEV_FL_HAS_DEVNODE
-标志。
-
-注册子设备之后， v4l2_device 驱动会通过调用 v4l2_device_register_subdev_nodes()
-函数为所有已注册并设置了 V4L2_SUBDEV_FL_HAS_DEVNODE 的子设备创建
-设备节点。这些设备节点会在子设备注销时自动删除。
-
-这些设备节点处理 V4L2 API 的一个子集。
-
-VIDIOC_QUERYCTRL
-VIDIOC_QUERYMENU
-VIDIOC_G_CTRL
-VIDIOC_S_CTRL
-VIDIOC_G_EXT_CTRLS
-VIDIOC_S_EXT_CTRLS
-VIDIOC_TRY_EXT_CTRLS
-
-	这些 ioctls 控制与 V4L2 中定义的一致。他们行为相同，唯一的
-	不同是他们只处理子设备的控制实现。根据驱动程序，这些控制也
-	可以通过一个（或多个） V4L2 设备节点访问。
-
-VIDIOC_DQEVENT
-VIDIOC_SUBSCRIBE_EVENT
-VIDIOC_UNSUBSCRIBE_EVENT
-
-	这些  ioctls 事件与 V4L2 中定义的一致。他们行为相同，唯一的
-	不同是他们只处理子设备产生的事件。根据驱动程序，这些事件也
-	可以通过一个（或多个） V4L2 设备节点上报。
-
-	要使用事件通知的子设备驱动，在注册子设备前必须在 v4l2_subdev::flags
-	中设置 V4L2_SUBDEV_USES_EVENTS 并在 v4l2_subdev::nevents
-	中初始化事件队列深度。注册完成后，事件会在 v4l2_subdev::devnode
-	设备节点中像通常一样被排队。
-
-	为正确支持事件机制，poll() 文件操作也应被实现。
-
-私有 ioctls
-
-	不在以上列表中的所有 ioctls 会通过 core::ioctl 操作直接传递
-	给子设备驱动。
-
-
-I2C 子设备驱动
--------------
-
-由于这些驱动很常见，所以内特提供了特定的辅助函数(v4l2-common.h)让这些
-设备的使用更加容易。
-
-添加 v4l2_subdev 支持的推荐方法是让 I2C 驱动将 v4l2_subdev 结构体
-嵌入到为每个 I2C 设备实例创建的状态结构体中。而最简单的设备没有状态
-结构体，此时可以直接创建一个 v4l2_subdev 结构体。
-
-一个典型的状态结构体如下所示（‘chipname’用芯片名代替）：
-
-struct chipname_state {
-	struct v4l2_subdev sd;
-	...  /* 附加的状态域*/
-};
-
-初始化 v4l2_subdev 结构体的方法如下：
-
-	v4l2_i2c_subdev_init(&state->sd, client, subdev_ops);
-
-这个函数将填充 v4l2_subdev 结构体中的所有域，并保证 v4l2_subdev 和
-i2c_client 都指向彼此。
-
-同时，你也应该为从 v4l2_subdev 指针找到 chipname_state 结构体指针
-添加一个辅助内联函数。
-
-static inline struct chipname_state *to_state(struct v4l2_subdev *sd)
-{
-	return container_of(sd, struct chipname_state, sd);
-}
-
-使用以下函数可以通过 v4l2_subdev 结构体指针获得 i2c_client 结构体
-指针：
-
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-而以下函数则相反，通过 i2c_client 结构体指针获得 v4l2_subdev 结构体
-指针：
-
-	struct v4l2_subdev *sd = i2c_get_clientdata(client);
-
-当 remove()函数被调用前，必须保证先调用 v4l2_device_unregister_subdev(sd)。
-此操作将会从桥驱动中注销子设备。即使子设备没有注册，调用此函数也是
-安全的。
-
-必须这样做的原因是：当桥驱动注销 i2c 适配器时，remove()回调函数
-会被那个适配器上的 i2c 设备调用。此后，相应的 v4l2_subdev 结构体
-就不存在了，所有它们必须先被注销。在 remove()回调函数中调用
-v4l2_device_unregister_subdev(sd)，可以保证执行总是正确的。
-
-
-桥驱动也有一些辅组函数可用：
-
-struct v4l2_subdev *sd = v4l2_i2c_new_subdev(v4l2_dev, adapter,
-	       "module_foo", "chipid", 0x36, NULL);
-
-这个函数会加载给定的模块（如果没有模块需要加载，可以为 NULL），
-并用给定的 i2c 适配器结构体指针（i2c_adapter）和 器件地址（chip/address）
-作为参数调用 i2c_new_device()。如果一切顺利，则就在 v4l2_device
-中注册了子设备。
-
-你也可以利用 v4l2_i2c_new_subdev()的最后一个参数，传递一个可能的
-I2C 地址数组，让函数自动探测。这些探测地址只有在前一个参数为 0 的
-情况下使用。非零参数意味着你知道准确的 i2c 地址，所以此时无须进行
-探测。
-
-如果出错，两个函数都返回 NULL。
-
-注意：传递给 v4l2_i2c_new_subdev()的 chipid 通常与模块名一致。
-它允许你指定一个芯片的变体，比如“saa7114”或“saa7115”。一般通过
-i2c 驱动自动探测。chipid 的使用是在今后需要深入了解的事情。这个与
-i2c 驱动不同，较容易混淆。要知道支持哪些芯片变体，你可以查阅 i2c
-驱动代码的 i2c_device_id 表，上面列出了所有可能支持的芯片。
-
-还有两个辅助函数：
-
-v4l2_i2c_new_subdev_cfg：这个函数添加新的 irq 和 platform_data
-参数，并有‘addr’和‘probed_addrs’参数：如果 addr 非零，则被使用
-（不探测变体），否则 probed_addrs 中的地址将用于自动探测。
-
-例如：以下代码将会探测地址（0x10）：
-
-struct v4l2_subdev *sd = v4l2_i2c_new_subdev_cfg(v4l2_dev, adapter,
-	       "module_foo", "chipid", 0, NULL, 0, I2C_ADDRS(0x10));
-
-v4l2_i2c_new_subdev_board 使用一个 i2c_board_info 结构体，将其
-替代 irq、platform_data 和 add r参数传递给 i2c 驱动。
-
-如果子设备支持 s_config 核心操作，这个操作会在子设备配置好之后以 irq 和
-platform_data 为参数调用。早期的 v4l2_i2c_new_(probed_)subdev 函数
-同样也会调用 s_config，但仅在 irq 为 0 且 platform_data 为 NULL 时。
-
-video_device结构体
------------------
-
-在 /dev 目录下的实际设备节点根据 video_device 结构体(v4l2-dev.h)
-创建。此结构体既可以动态分配也可以嵌入到一个更大的结构体中。
-
-动态分配方法如下：
-
-	struct video_device *vdev = video_device_alloc();
-
-	if (vdev == NULL)
-		return -ENOMEM;
-
-	vdev->release = video_device_release;
-
-如果将其嵌入到一个大结构体中，则必须自己实现 release()回调。
-
-	struct video_device *vdev = &my_vdev->vdev;
-
-	vdev->release = my_vdev_release;
-
-release()回调必须被设置，且在最后一个 video_device 用户退出之后
-被调用。
-
-默认的 video_device_release()回调只是调用 kfree 来释放之前分配的
-内存。
-
-你应该设置这些域：
-
-- v4l2_dev: 设置为 v4l2_device 父设备。
-
-- name: 设置为唯一的描述性设备名。
-
-- fops: 设置为已有的 v4l2_file_operations 结构体。
-
-- ioctl_ops: 如果你使用v4l2_ioctl_ops 来简化 ioctl 的维护
-  (强烈建议使用，且将来可能变为强制性的!)，然后设置你自己的
-  v4l2_ioctl_ops 结构体.
-
-- lock: 如果你要在驱动中实现所有的锁操作，则设为 NULL 。否则
-  就要设置一个指向 struct mutex_lock 结构体的指针，这个锁将
-  在 unlocked_ioctl 文件操作被调用前由内核获得，并在调用返回后
-  释放。详见下一节。
-
-- prio: 保持对优先级的跟踪。用于实现 VIDIOC_G/S_PRIORITY。如果
-  设置为 NULL，则会使用 v4l2_device 中的 v4l2_prio_state 结构体。
-  如果要对每个设备节点（组）实现独立的优先级，可以将其指向自己
-  实现的 v4l2_prio_state 结构体。
-
-- parent: 仅在使用 NULL 作为父设备结构体参数注册 v4l2_device 时
-  设置此参数。只有在一个硬件设备包含多一个 PCI 设备，共享同一个
-  v4l2_device 核心时才会发生。
-
-  cx88 驱动就是一个例子：一个 v4l2_device 结构体核心，被一个裸的
-  视频 PCI 设备(cx8800)和一个 MPEG PCI 设备(cx8802)共用。由于
-  v4l2_device 无法与特定的 PCI 设备关联，所有没有设置父设备。但当
-  video_device 配置后，就知道使用哪个父 PCI 设备了。
-
-如果你使用 v4l2_ioctl_ops，则应该在 v4l2_file_operations 结构体中
-设置 .unlocked_ioctl 指向 video_ioctl2。
-
-请勿使用 .ioctl！它已被废弃，今后将消失。
-
-某些情况下你要告诉核心：你在 v4l2_ioctl_ops 指定的某个函数应被忽略。
-你可以在 video_device_register 被调用前通过以下函数标记这个 ioctls。
-
-void v4l2_disable_ioctl(struct video_device *vdev, unsigned int cmd);
-
-基于外部因素（例如某个板卡已被使用），在不创建新结构体的情况下，你想
-要关闭 v4l2_ioctl_ops 中某个特性往往需要这个机制。
-
-v4l2_file_operations 结构体是 file_operations 的一个子集。其主要
-区别在于：因 inode 参数从未被使用，它将被忽略。
-
-如果需要与媒体框架整合，你必须通过调用 media_entity_pads_init() 初始化
-嵌入在 video_device 结构体中的 media_entity（entity 域）结构体：
-
-	struct media_pad *pad = &my_vdev->pad;
-	int err;
-
-	err = media_entity_pads_init(&vdev->entity, 1, pad);
-
-pads 数组必须预先初始化。没有必要手动设置 media_entity 的 type 和
-name 域。
-
-当（任何）子设备节点被打开/关闭，对 entity 的引用将被自动获取/释放。
-
-v4l2_file_operations 与锁
---------------------------
-
-你可以在 video_device 结构体中设置一个指向 mutex_lock 的指针。通常
-这既可是一个顶层互斥锁也可为设备节点自身的互斥锁。默认情况下，此锁
-用于 unlocked_ioctl，但为了使用 ioctls 你通过以下函数可禁用锁定：
-
-	void v4l2_disable_ioctl_locking(struct video_device *vdev, unsigned int cmd);
-
-例如: v4l2_disable_ioctl_locking(vdev, VIDIOC_DQBUF);
-
-你必须在注册 video_device 前调用这个函数。
-
-特别是对于 USB 驱动程序，某些命令（如设置控制）需要很长的时间，可能
-需要自行为缓冲区队列的 ioctls 实现锁定。
-
-如果你需要更细粒度的锁，你必须设置 mutex_lock 为 NULL，并完全自己实现
-锁机制。
-
-这完全由驱动开发者决定使用何种方法。然而，如果你的驱动存在长延时操作
-（例如，改变 USB 摄像头的曝光时间可能需要较长时间），而你又想让用户
-在等待长延时操作完成期间做其他的事，则你最好自己实现锁机制。
-
-如果指定一个锁，则所有 ioctl 操作将在这个锁的作用下串行执行。如果你
-使用 videobuf，则必须将同一个锁传递给 videobuf 队列初始化函数；如
-videobuf 必须等待一帧的到达，则可临时解锁并在这之后重新上锁。如果驱动
-也在代码执行期间等待，则可做同样的工作（临时解锁，再上锁）让其他进程
-可以在第一个进程阻塞时访问设备节点。
-
-在使用 videobuf2 的情况下，必须实现 wait_prepare 和 wait_finish 回调
-在适当的时候解锁/加锁。进一步来说，如果你在 video_device 结构体中使用
-锁，则必须在 wait_prepare 和 wait_finish 中对这个互斥锁进行解锁/加锁。
-
-热插拔的断开实现也必须在调用 v4l2_device_disconnect 前获得锁。
-
-video_device注册
----------------
-
-接下来你需要注册视频设备：这会为你创建一个字符设备。
-
-	err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
-	if (err) {
-		video_device_release(vdev); /* or kfree(my_vdev); */
-		return err;
-	}
-
-如果 v4l2_device 父设备的 mdev 域为非 NULL 值，视频设备实体将自动
-注册为媒体设备。
-
-注册哪种设备是根据类型（type）参数。存在以下类型：
-
-VFL_TYPE_GRABBER: 用于视频输入/输出设备的 videoX
-VFL_TYPE_VBI: 用于垂直消隐数据的 vbiX (例如，隐藏式字幕，图文电视)
-VFL_TYPE_RADIO: 用于广播调谐器的 radioX
-
-最后一个参数让你确定一个所控制设备的设备节点号数量(例如 videoX 中的 X)。
-通常你可以传入-1，让 v4l2 框架自己选择第一个空闲的编号。但是有时用户
-需要选择一个特定的节点号。驱动允许用户通过驱动模块参数选择一个特定的
-设备节点号是很普遍的。这个编号将会传递给这个函数，且 video_register_device
-将会试图选择这个设备节点号。如果这个编号被占用，下一个空闲的设备节点
-编号将被选中，并向内核日志中发送一个警告信息。
-
-另一个使用场景是当驱动创建多个设备时。这种情况下，对不同的视频设备在
-编号上使用不同的范围是很有用的。例如，视频捕获设备从 0 开始，视频
-输出设备从 16 开始。所以你可以使用最后一个参数来指定设备节点号最小值，
-而 v4l2 框架会试图选择第一个的空闲编号（等于或大于你提供的编号）。
-如果失败，则它会就选择第一个空闲的编号。
-
-由于这种情况下，你会忽略无法选择特定设备节点号的警告，则可调用
-video_register_device_no_warn() 函数避免警告信息的产生。
-
-只要设备节点被创建，一些属性也会同时创建。在 /sys/class/video4linux
-目录中你会找到这些设备。例如进入其中的 video0 目录，你会看到‘name’和
-‘index’属性。‘name’属性值就是 video_device 结构体中的‘name’域。
-
-‘index’属性值就是设备节点的索引值：每次调用 video_register_device()，
-索引值都递增 1 。第一个视频设备节点总是从索引值 0 开始。
-
-用户可以设置 udev 规则，利用索引属性生成花哨的设备名（例如：用‘mpegX’
-代表 MPEG 视频捕获设备节点）。
-
-在设备成功注册后，就可以使用这些域：
-
-- vfl_type: 传递给 video_register_device 的设备类型。
-- minor: 已指派的次设备号。
-- num: 设备节点编号 (例如 videoX 中的 X)。
-- index: 设备索引号。
-
-如果注册失败，你必须调用 video_device_release() 来释放已分配的
-video_device 结构体；如果 video_device 是嵌入在自己创建的结构体中，
-你也必须释放它。vdev->release() 回调不会在注册失败之后被调用，
-你也不应试图在注册失败后注销设备。
-
-
-video_device 注销
-----------------
-
-当视频设备节点已被移除，不论是卸载驱动还是USB设备断开，你都应注销
-它们：
-
-	video_unregister_device(vdev);
-
-这个操作将从 sysfs 中移除设备节点（导致 udev 将其从 /dev 中移除）。
-
-video_unregister_device() 返回之后，就无法完成打开操作。尽管如此，
-USB 设备的情况则不同，某些应用程序可能依然打开着其中一个已注销设备
-节点。所以在注销之后，所有文件操作（当然除了 release ）也应返回错误值。
-
-当最后一个视频设备节点的用户退出，则 vdev->release() 回调会被调用，
-并且你可以做最后的清理操作。
-
-不要忘记清理与视频设备相关的媒体入口（如果被初始化过）：
-
-	media_entity_cleanup(&vdev->entity);
-
-这可以在 release 回调中完成。
-
-
-video_device 辅助函数
----------------------
-
-一些有用的辅助函数如下：
-
-- file/video_device 私有数据
-
-你可以用以下函数在 video_device 结构体中设置/获取驱动私有数据：
-
-void *video_get_drvdata(struct video_device *vdev);
-void video_set_drvdata(struct video_device *vdev, void *data);
-
-注意：在调用 video_register_device() 前执行 video_set_drvdata()
-是安全的。
-
-而以下函数：
-
-struct video_device *video_devdata(struct file *file);
-
-返回 file 结构体中拥有的的 video_device 指针。
-
-video_drvdata 辅助函数结合了 video_get_drvdata 和 video_devdata
-的功能：
-
-void *video_drvdata(struct file *file);
-
-你可以使用如下代码从 video_device 结构体中获取 v4l2_device 结构体
-指针：
-
-struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
-
-- 设备节点名
-
-video_device 设备节点在内核中的名称可以通过以下函数获得
-
-const char *video_device_node_name(struct video_device *vdev);
-
-这个名字被用户空间工具（例如 udev）作为提示信息使用。应尽可能使用
-此功能，而非访问 video_device::num 和 video_device::minor 域。
-
-
-视频缓冲辅助函数
----------------
-
-v4l2 核心 API 提供了一个处理视频缓冲的标准方法(称为“videobuf”)。
-这些方法使驱动可以通过统一的方式实现 read()、mmap() 和 overlay()。
-目前在设备上支持视频缓冲的方法有分散/聚集 DMA(videobuf-dma-sg)、
-线性 DMA(videobuf-dma-contig)以及大多用于 USB 设备的用 vmalloc
-分配的缓冲(videobuf-vmalloc)。
-
-请参阅 Documentation/video4linux/videobuf，以获得更多关于 videobuf
-层的使用信息。
-
-v4l2_fh 结构体
--------------
-
-v4l2_fh 结构体提供一个保存用于 V4L2 框架的文件句柄特定数据的简单方法。
-如果 video_device 标志，新驱动
-必须使用 v4l2_fh 结构体，因为它也用于实现优先级处理（VIDIOC_G/S_PRIORITY）。
-
-v4l2_fh 的用户（位于 V4l2 框架中，并非驱动）可通过测试
-video_device->flags 中的 V4L2_FL_USES_V4L2_FH 位得知驱动是否使用
-v4l2_fh 作为他的 file->private_data 指针。这个位会在调用 v4l2_fh_init()
-时被设置。
-
-v4l2_fh 结构体作为驱动自身文件句柄结构体的一部分被分配，且驱动在
-其打开函数中将 file->private_data 指向它。
-
-在许多情况下，v4l2_fh 结构体会嵌入到一个更大的结构体中。这钟情况下，
-应该在 open() 中调用 v4l2_fh_init+v4l2_fh_add，并在 release() 中
-调用 v4l2_fh_del+v4l2_fh_exit。
-
-驱动可以通过使用 container_of 宏提取他们自己的文件句柄结构体。例如：
-
-struct my_fh {
-	int blah;
-	struct v4l2_fh fh;
-};
-
-...
-
-int my_open(struct file *file)
-{
-	struct my_fh *my_fh;
-	struct video_device *vfd;
-	int ret;
-
-	...
-
-	my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL);
-
-	...
-
-	v4l2_fh_init(&my_fh->fh, vfd);
-
-	...
-
-	file->private_data = &my_fh->fh;
-	v4l2_fh_add(&my_fh->fh);
-	return 0;
-}
-
-int my_release(struct file *file)
-{
-	struct v4l2_fh *fh = file->private_data;
-	struct my_fh *my_fh = container_of(fh, struct my_fh, fh);
-
-	...
-	v4l2_fh_del(&my_fh->fh);
-	v4l2_fh_exit(&my_fh->fh);
-	kfree(my_fh);
-	return 0;
-}
-
-以下是 v4l2_fh 函数使用的简介：
-
-void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
-
-  初始化文件句柄。这*必须*在驱动的 v4l2_file_operations->open()
-  函数中执行。
-
-void v4l2_fh_add(struct v4l2_fh *fh)
-
-  添加一个 v4l2_fh 到 video_device 文件句柄列表。一旦文件句柄
-  初始化完成就必须调用。
-
-void v4l2_fh_del(struct v4l2_fh *fh)
-
-  从 video_device() 中解除文件句柄的关联。文件句柄的退出函数也
-  将被调用。
-
-void v4l2_fh_exit(struct v4l2_fh *fh)
-
-  清理文件句柄。在清理完 v4l2_fh 后，相关内存会被释放。
-
-
-如果 v4l2_fh 不是嵌入在其他结构体中的，则可以用这些辅助函数：
-
-int v4l2_fh_open(struct file *filp)
-
-  分配一个 v4l2_fh 结构体空间，初始化并将其添加到 file 结构体相关的
-  video_device 结构体中。
-
-int v4l2_fh_release(struct file *filp)
-
-  从 file 结构体相关的 video_device 结构体中删除 v4l2_fh ，清理
-  v4l2_fh 并释放空间。
-
-这两个函数可以插入到 v4l2_file_operation 的 open() 和 release()
-操作中。
-
-
-某些驱动需要在第一个文件句柄打开和最后一个文件句柄关闭的时候做些
-工作。所以加入了两个辅助函数以检查 v4l2_fh 结构体是否是相关设备
-节点打开的唯一文件句柄。
-
-int v4l2_fh_is_singular(struct v4l2_fh *fh)
-
-  如果此文件句柄是唯一打开的文件句柄，则返回 1 ，否则返回 0 。
-
-int v4l2_fh_is_singular_file(struct file *filp)
-
-  功能相同，但通过 filp->private_data 调用 v4l2_fh_is_singular。
-
-
-V4L2 事件机制
------------
-
-V4L2 事件机制提供了一个通用的方法将事件传递到用户空间。驱动必须使用
-v4l2_fh 才能支持 V4L2 事件机制。
-
-
-事件通过一个类型和选择 ID 来定义。ID 对应一个 V4L2 对象，例如
-一个控制 ID。如果未使用，则 ID 为 0。
-
-当用户订阅一个事件，驱动会为此分配一些 kevent 结构体。所以每个
-事件组（类型、ID）都会有自己的一套 kevent 结构体。这保证了如果
-一个驱动短时间内产生了许多同类事件，不会覆盖其他类型的事件。
-
-但如果你收到的事件数量大于同类事件 kevent 的保存数量，则最早的
-事件将被丢弃，并加入新事件。
-
-此外，v4l2_subscribed_event 结构体内部有可供驱动设置的 merge() 和
-replace() 回调，这些回调会在新事件产生且没有多余空间的时候被调用。
-replace() 回调让你可以将早期事件的净荷替换为新事件的净荷，将早期
-净荷的相关数据合并到替换进来的新净荷中。当该类型的事件仅分配了一个
-kevent 结构体时，它将被调用。merge() 回调让你可以合并最早的事件净荷
-到在它之后的那个事件净荷中。当该类型的事件分配了两个或更多 kevent
-结构体时，它将被调用。
-
-这种方法不会有状态信息丢失，只会导致中间步骤信息丢失。
-
-
-关于 replace/merge 回调的一个不错的例子在 v4l2-event.c 中：用于
-控制事件的 ctrls_replace() 和 ctrls_merge() 回调。
-
-注意：这些回调可以在中断上下文中调用，所以它们必须尽快完成并退出。
-
-有用的函数：
-
-void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev)
-
-  将事件加入视频设备的队列。驱动仅负责填充 type 和 data 域。
-  其他域由 V4L2 填充。
-
-int v4l2_event_subscribe(struct v4l2_fh *fh,
-			 struct v4l2_event_subscription *sub, unsigned elems,
-			 const struct v4l2_subscribed_event_ops *ops)
-
-  video_device->ioctl_ops->vidioc_subscribe_event 必须检测驱动能
-  产生特定 id 的事件。然后调用 v4l2_event_subscribe() 来订阅该事件。
-
-  elems 参数是该事件的队列大小。若为 0，V4L2 框架将会（根据事件类型）
-  填充默认值。
-
-  ops 参数允许驱动指定一系列回调：
-  * add:     当添加一个新监听者时调用（重复订阅同一个事件，此回调
-             仅被执行一次）。
-  * del:     当一个监听者停止监听时调用。
-  * replace: 用‘新’事件替换‘早期‘事件。
-  * merge:   将‘早期‘事件合并到‘新’事件中。
-  这四个调用都是可选的，如果不想指定任何回调，则 ops 可为 NULL。
-
-int v4l2_event_unsubscribe(struct v4l2_fh *fh,
-			   struct v4l2_event_subscription *sub)
-
-  v4l2_ioctl_ops 结构体中的 vidioc_unsubscribe_event 回调函数。
-  驱动程序可以直接使用 v4l2_event_unsubscribe() 实现退订事件过程。
-
-  特殊的 V4L2_EVENT_ALL 类型，可用于退订所有事件。驱动可能在特殊
-  情况下需要做此操作。
-
-int v4l2_event_pending(struct v4l2_fh *fh)
-
-  返回未决事件的数量。有助于实现轮询（poll）操作。
-
-事件通过 poll 系统调用传递到用户空间。驱动可用
-v4l2_fh->wait (wait_queue_head_t 类型)作为参数调用 poll_wait()。
-
-事件分为标准事件和私有事件。新的标准事件必须使用可用的最小事件类型
-编号。驱动必须从他们本类型的编号起始处分配事件。类型的编号起始为
-V4L2_EVENT_PRIVATE_START + n * 1000 ，其中 n 为可用最小编号。每个
-类型中的第一个事件类型编号是为以后的使用保留的，所以第一个可用事件
-类型编号是‘class base + 1’。
-
-V4L2 事件机制的使用实例可以在 OMAP3 ISP 的驱动
-(drivers/media/video/omap3isp)中找到。
diff -druNp --no-dereference linux-libre-4.9-gnu/Documentation/zh_CN/volatile-considered-harmful.txt linux-libre-4.10-rc8-gnu/Documentation/zh_CN/volatile-considered-harmful.txt
--- linux-libre-4.9-gnu/Documentation/zh_CN/volatile-considered-harmful.txt	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/Documentation/zh_CN/volatile-considered-harmful.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,113 +0,0 @@
-Chinese translated version of Documentation/volatile-considered-harmful.txt
-
-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.
-
-Maintainer: Jonathan Corbet <corbet@lwn.net>
-Chinese maintainer: Bryan Wu <bryan.wu@analog.com>
----------------------------------------------------------------------
-Documentation/volatile-considered-harmful.txt 的中文翻译
-
-如果想评论或更新本文的内容，请直接联系原文档的维护者。如果你使用英文
-交流有困难的话，也可以向中文版维护者求助。如果本翻译更新不及时或者翻
-译存在问题，请联系中文版维护者。
-
-英文版维护者： Jonathan Corbet <corbet@lwn.net>
-中文版维护者： 伍鹏  Bryan Wu <bryan.wu@analog.com>
-中文版翻译者： 伍鹏  Bryan Wu <bryan.wu@analog.com>
-中文版校译者： 张汉辉  Eugene Teo <eugeneteo@kernel.sg>
-               杨瑞  Dave Young <hidave.darkstar@gmail.com>
-以下为正文
----------------------------------------------------------------------
-
-为什么不应该使用“volatile”类型
-------------------------------
-
-C程序员通常认为volatile表示某个变量可以在当前执行的线程之外被改变；因此，在内核
-中用到共享数据结构时，常常会有C程序员喜欢使用volatile这类变量。换句话说，他们经
-常会把volatile类型看成某种简易的原子变量，当然它们不是。在内核中使用volatile几
-乎总是错误的；本文档将解释为什么这样。
-
-理解volatile的关键是知道它的目的是用来消除优化，实际上很少有人真正需要这样的应
-用。在内核中，程序员必须防止意外的并发访问破坏共享的数据结构，这其实是一个完全
-不同的任务。用来防止意外并发访问的保护措施，可以更加高效的避免大多数优化相关的
-问题。
-
-像volatile一样，内核提供了很多原语来保证并发访问时的数据安全（自旋锁, 互斥量,内
-存屏障等等），同样可以防止意外的优化。如果可以正确使用这些内核原语，那么就没有
-必要再使用volatile。如果仍然必须使用volatile，那么几乎可以肯定在代码的某处有一
-个bug。在正确设计的内核代码中，volatile能带来的仅仅是使事情变慢。
-
-思考一下这段典型的内核代码：
-
-    spin_lock(&the_lock);
-    do_something_on(&shared_data);
-    do_something_else_with(&shared_data);
-    spin_unlock(&the_lock);
-
-如果所有的代码都遵循加锁规则，当持有the_lock的时候，不可能意外的改变shared_data的
-值。任何可能访问该数据的其他代码都会在这个锁上等待。自旋锁原语跟内存屏障一样—— 它
-们显式的用来书写成这样 —— 意味着数据访问不会跨越它们而被优化。所以本来编译器认为
-它知道在shared_data里面将有什么，但是因为spin_lock()调用跟内存屏障一样，会强制编
-译器忘记它所知道的一切。那么在访问这些数据时不会有优化的问题。
-
-如果shared_data被声名为volatile，锁操作将仍然是必须的。就算我们知道没有其他人正在
-使用它，编译器也将被阻止优化对临界区内shared_data的访问。在锁有效的同时，
-shared_data不是volatile的。在处理共享数据的时候，适当的锁操作可以不再需要
-volatile —— 并且是有潜在危害的。
-
-volatile的存储类型最初是为那些内存映射的I/O寄存器而定义。在内核里，寄存器访问也应
-该被锁保护，但是人们也不希望编译器“优化”临界区内的寄存器访问。内核里I/O的内存访问
-是通过访问函数完成的；不赞成通过指针对I/O内存的直接访问，并且不是在所有体系架构上
-都能工作。那些访问函数正是为了防止意外优化而写的，因此，再说一次，volatile类型不
-是必需的。
-
-另一种引起用户可能使用volatile的情况是当处理器正忙着等待一个变量的值。正确执行一
-个忙等待的方法是：
-
-    while (my_variable != what_i_want)
-        cpu_relax();
-
-cpu_relax()调用会降低CPU的能量消耗或者让位于超线程双处理器；它也作为内存屏障一样出
-现，所以，再一次，volatile不是必需的。当然，忙等待一开始就是一种反常规的做法。
-
-在内核中，一些稀少的情况下volatile仍然是有意义的：
-
-  - 在一些体系架构的系统上，允许直接的I/0内存访问，那么前面提到的访问函数可以使用
-    volatile。基本上，每一个访问函数调用它自己都是一个小的临界区域并且保证了按照
-    程序员期望的那样发生访问操作。
-
-  - 某些会改变内存的内联汇编代码虽然没有什么其他明显的附作用，但是有被GCC删除的可
-    能性。在汇编声明中加上volatile关键字可以防止这种删除操作。
-
-  - Jiffies变量是一种特殊情况，虽然每次引用它的时候都可以有不同的值，但读jiffies
-    变量时不需要任何特殊的加锁保护。所以jiffies变量可以使用volatile，但是不赞成
-    其他跟jiffies相同类型变量使用volatile。Jiffies被认为是一种“愚蠢的遗留物"
-    （Linus的话）因为解决这个问题比保持现状要麻烦的多。
-
-  - 由于某些I/0设备可能会修改连续一致的内存,所以有时,指向连续一致内存的数据结构
-    的指针需要正确的使用volatile。网络适配器使用的环状缓存区正是这类情形的一个例
-    子，其中适配器用改变指针来表示哪些描述符已经处理过了。
-
-对于大多代码，上述几种可以使用volatile的情况都不适用。所以，使用volatile是一种
-bug并且需要对这样的代码额外仔细检查。那些试图使用volatile的开发人员需要退一步想想
-他们真正想实现的是什么。
-
-非常欢迎删除volatile变量的补丁 － 只要证明这些补丁完整的考虑了并发问题。
-
-注释
-----
-
-[1] http://lwn.net/Articles/233481/
-[2] http://lwn.net/Articles/233482/
-
-致谢
-----
-
-最初由Randy Dunlap推动并作初步研究
-由Jonathan Corbet撰写
-参考Satyam Sharma，Johannes Stezenbach，Jesper Juhl，Heikki Orsila，
-H. Peter Anvin，Philipp Hahn和Stefan Richter的意见改善了本档。
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpi_apd.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_apd.c
--- linux-libre-4.9-gnu/drivers/acpi/acpi_apd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_apd.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,6 +77,11 @@ static const struct apd_device_desc cz_i
 	.fixed_clk_rate = 133000000,
 };
 
+static const struct apd_device_desc wt_i2c_desc = {
+	.setup = acpi_apd_setup,
+	.fixed_clk_rate = 150000000,
+};
+
 static struct property_entry uart_properties[] = {
 	PROPERTY_ENTRY_U32("reg-io-width", 4),
 	PROPERTY_ENTRY_U32("reg-shift", 2),
@@ -156,7 +161,7 @@ static const struct acpi_device_id acpi_
 	/* Generic apd devices */
 #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
 	{ "AMD0010", APD_ADDR(cz_i2c_desc) },
-	{ "AMDI0010", APD_ADDR(cz_i2c_desc) },
+	{ "AMDI0010", APD_ADDR(wt_i2c_desc) },
 	{ "AMD0020", APD_ADDR(cz_uart_desc) },
 	{ "AMDI0020", APD_ADDR(cz_uart_desc) },
 	{ "AMD0030", },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/acevents.h linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acevents.h
--- linux-libre-4.9-gnu/drivers/acpi/acpica/acevents.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acevents.h	2017-02-12 16:03:20.000000000 -0500
@@ -243,9 +243,7 @@ acpi_ev_default_region_setup(acpi_handle
 			     u32 function,
 			     void *handler_context, void **region_context);
 
-acpi_status
-acpi_ev_initialize_region(union acpi_operand_object *region_obj,
-			  u8 acpi_ns_locked);
+acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj);
 
 /*
  * evsci - SCI (System Control Interrupt) handling/dispatch
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/acglobal.h linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acglobal.h
--- linux-libre-4.9-gnu/drivers/acpi/acpica/acglobal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acglobal.h	2017-02-12 16:03:20.000000000 -0500
@@ -240,10 +240,6 @@ ACPI_INIT_GLOBAL(u32, acpi_gbl_nesting_l
 
 ACPI_GLOBAL(struct acpi_thread_state *, acpi_gbl_current_walk_list);
 
-/* Maximum number of While() loop iterations before forced abort */
-
-ACPI_GLOBAL(u16, acpi_gbl_max_loop_iterations);
-
 /* Control method single step flag */
 
 ACPI_GLOBAL(u8, acpi_gbl_cm_single_step);
@@ -318,6 +314,7 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_cstyle_dis
 ACPI_INIT_GLOBAL(u8, acpi_gbl_force_aml_disassembly, FALSE);
 ACPI_INIT_GLOBAL(u8, acpi_gbl_dm_opt_verbose, TRUE);
 ACPI_INIT_GLOBAL(u8, acpi_gbl_dm_emit_external_opcodes, FALSE);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_do_disassembler_optimizations, TRUE);
 
 ACPI_GLOBAL(u8, acpi_gbl_dm_opt_disasm);
 ACPI_GLOBAL(u8, acpi_gbl_dm_opt_listing);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/aclocal.h linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/aclocal.h
--- linux-libre-4.9-gnu/drivers/acpi/acpica/aclocal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/aclocal.h	2017-02-12 16:03:20.000000000 -0500
@@ -765,7 +765,7 @@ union acpi_parse_value {
 	union acpi_parse_value          value;          /* Value or args associated with the opcode */\
 	u8                              arg_list_length; /* Number of elements in the arg list */\
 	ACPI_DISASM_ONLY_MEMBERS (\
-	u8                              disasm_flags;   /* Used during AML disassembly */\
+	u16                             disasm_flags;   /* Used during AML disassembly */\
 	u8                              disasm_opcode;  /* Subtype used for disassembly */\
 	char                            *operator_symbol;/* Used for C-style operator name strings */\
 	char                            aml_op_name[16])	/* Op name (debug only) */
@@ -868,14 +868,15 @@ struct acpi_parse_state {
 
 /* Parse object disasm_flags */
 
-#define ACPI_PARSEOP_IGNORE                 0x01
-#define ACPI_PARSEOP_PARAMETER_LIST         0x02
-#define ACPI_PARSEOP_EMPTY_TERMLIST         0x04
-#define ACPI_PARSEOP_PREDEFINED_CHECKED     0x08
-#define ACPI_PARSEOP_CLOSING_PAREN          0x10
-#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT    0x20
-#define ACPI_PARSEOP_ASSIGNMENT             0x40
-#define ACPI_PARSEOP_ELSEIF                 0x80
+#define ACPI_PARSEOP_IGNORE                 0x0001
+#define ACPI_PARSEOP_PARAMETER_LIST         0x0002
+#define ACPI_PARSEOP_EMPTY_TERMLIST         0x0004
+#define ACPI_PARSEOP_PREDEFINED_CHECKED     0x0008
+#define ACPI_PARSEOP_CLOSING_PAREN          0x0010
+#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT    0x0020
+#define ACPI_PARSEOP_ASSIGNMENT             0x0040
+#define ACPI_PARSEOP_ELSEIF                 0x0080
+#define ACPI_PARSEOP_LEGACY_ASL_ONLY        0x0100
 
 /*****************************************************************************
  *
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/acnamesp.h linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acnamesp.h
--- linux-libre-4.9-gnu/drivers/acpi/acpica/acnamesp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acnamesp.h	2017-02-12 16:03:20.000000000 -0500
@@ -292,6 +292,9 @@ char *acpi_ns_get_normalized_pathname(st
 char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state);
 
 acpi_status
+acpi_ns_handle_to_name(acpi_handle target_handle, struct acpi_buffer *buffer);
+
+acpi_status
 acpi_ns_handle_to_pathname(acpi_handle target_handle,
 			   struct acpi_buffer *buffer, u8 no_trailing);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/actables.h linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/actables.h
--- linux-libre-4.9-gnu/drivers/acpi/acpica/actables.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/actables.h	2017-02-12 16:03:20.000000000 -0500
@@ -127,10 +127,11 @@ acpi_status
 acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node);
 
 acpi_status
-acpi_tb_install_and_load_table(struct acpi_table_header *table,
-			       acpi_physical_address address,
+acpi_tb_install_and_load_table(acpi_physical_address address,
 			       u8 flags, u8 override, u32 *table_index);
 
+acpi_status acpi_tb_unload_table(u32 table_index);
+
 void acpi_tb_terminate(void);
 
 acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index);
@@ -165,6 +166,12 @@ acpi_tb_install_table_with_override(stru
 
 acpi_status acpi_tb_parse_root_table(acpi_physical_address rsdp_address);
 
+acpi_status
+acpi_tb_get_table(struct acpi_table_desc *table_desc,
+		  struct acpi_table_header **out_table);
+
+void acpi_tb_put_table(struct acpi_table_desc *table_desc);
+
 /*
  * tbxfload
  */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/acutils.h linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acutils.h
--- linux-libre-4.9-gnu/drivers/acpi/acpica/acutils.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/acutils.h	2017-02-12 16:03:20.000000000 -0500
@@ -232,6 +232,8 @@ const char *acpi_ut_get_region_name(u8 s
 
 const char *acpi_ut_get_event_name(u32 event_id);
 
+const char *acpi_ut_get_argument_type_name(u32 arg_type);
+
 char acpi_ut_hex_to_ascii_char(u64 integer, u32 position);
 
 acpi_status acpi_ut_ascii_to_hex_byte(char *two_ascii_chars, u8 *return_byte);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/amlcode.h linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/amlcode.h
--- linux-libre-4.9-gnu/drivers/acpi/acpica/amlcode.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/amlcode.h	2017-02-12 16:03:20.000000000 -0500
@@ -240,6 +240,7 @@
 #define ARGP_QWORDDATA              0x11
 #define ARGP_SIMPLENAME             0x12	/* name_string | local_term | arg_term */
 #define ARGP_NAME_OR_REF            0x13	/* For object_type only */
+#define ARGP_MAX                    0x13
 
 /*
  * Resolved argument types for the AML Interpreter
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/dsinit.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/dsinit.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/dsinit.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/dsinit.c	2017-02-12 16:03:20.000000000 -0500
@@ -221,8 +221,8 @@ acpi_ds_initialize_objects(u32 table_ind
 	 */
 	status =
 	    acpi_ns_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
-				   0, acpi_ds_init_one_object, NULL, &info,
-				   NULL);
+				   ACPI_NS_WALK_NO_UNLOCK,
+				   acpi_ds_init_one_object, NULL, &info, NULL);
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/dsopcode.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/dsopcode.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/dsopcode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/dsopcode.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,7 @@ acpi_status acpi_ds_initialize_region(ac
 
 	/* Namespace is NOT locked */
 
-	status = acpi_ev_initialize_region(obj_desc, FALSE);
+	status = acpi_ev_initialize_region(obj_desc);
 	return (status);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/dswload2.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/dswload2.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/dswload2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/dswload2.c	2017-02-12 16:03:20.000000000 -0500
@@ -609,18 +609,7 @@ acpi_status acpi_ds_load2_end_op(struct
 
 			status =
 			    acpi_ev_initialize_region
-			    (acpi_ns_get_attached_object(node), FALSE);
-
-			if (ACPI_FAILURE(status)) {
-				/*
-				 *  If AE_NOT_EXIST is returned, it is not fatal
-				 *  because many regions get created before a handler
-				 *  is installed for said region.
-				 */
-				if (AE_NOT_EXIST == status) {
-					status = AE_OK;
-				}
-			}
+			    (acpi_ns_get_attached_object(node));
 			break;
 
 		case AML_NAME_OP:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/evrgnini.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/evrgnini.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/evrgnini.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/evrgnini.c	2017-02-12 16:03:20.000000000 -0500
@@ -479,7 +479,6 @@ acpi_ev_default_region_setup(acpi_handle
  * FUNCTION:    acpi_ev_initialize_region
  *
  * PARAMETERS:  region_obj      - Region we are initializing
- *              acpi_ns_locked  - Is namespace locked?
  *
  * RETURN:      Status
  *
@@ -497,19 +496,28 @@ acpi_ev_default_region_setup(acpi_handle
  * MUTEX:       Interpreter should be unlocked, because we may run the _REG
  *              method for this region.
  *
+ * NOTE:        Possible incompliance:
+ *              There is a behavior conflict in automatic _REG execution:
+ *              1. When the interpreter is evaluating a method, we can only
+ *                 automatically run _REG for the following case:
+ *                   operation_region (OPR1, 0x80, 0x1000010, 0x4)
+ *              2. When the interpreter is loading a table, we can also
+ *                 automatically run _REG for the following case:
+ *                   operation_region (OPR1, 0x80, 0x1000010, 0x4)
+ *              Though this may not be compliant to the de-facto standard, the
+ *              logic is kept in order not to trigger regressions. And keeping
+ *              this logic should be taken care by the caller of this function.
+ *
  ******************************************************************************/
 
-acpi_status
-acpi_ev_initialize_region(union acpi_operand_object *region_obj,
-			  u8 acpi_ns_locked)
+acpi_status acpi_ev_initialize_region(union acpi_operand_object *region_obj)
 {
 	union acpi_operand_object *handler_obj;
 	union acpi_operand_object *obj_desc;
 	acpi_adr_space_type space_id;
 	struct acpi_namespace_node *node;
-	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);
+	ACPI_FUNCTION_TRACE(ev_initialize_region);
 
 	if (!region_obj) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -580,39 +588,17 @@ acpi_ev_initialize_region(union acpi_ope
 						  handler_obj, region_obj,
 						  obj_desc));
 
-				status =
-				    acpi_ev_attach_region(handler_obj,
-							  region_obj,
-							  acpi_ns_locked);
+				(void)acpi_ev_attach_region(handler_obj,
+							    region_obj, FALSE);
 
 				/*
 				 * Tell all users that this region is usable by
 				 * running the _REG method
 				 */
-				if (acpi_ns_locked) {
-					status =
-					    acpi_ut_release_mutex
-					    (ACPI_MTX_NAMESPACE);
-					if (ACPI_FAILURE(status)) {
-						return_ACPI_STATUS(status);
-					}
-				}
-
 				acpi_ex_exit_interpreter();
-				status =
-				    acpi_ev_execute_reg_method(region_obj,
-							       ACPI_REG_CONNECT);
+				(void)acpi_ev_execute_reg_method(region_obj,
+								 ACPI_REG_CONNECT);
 				acpi_ex_enter_interpreter();
-
-				if (acpi_ns_locked) {
-					status =
-					    acpi_ut_acquire_mutex
-					    (ACPI_MTX_NAMESPACE);
-					if (ACPI_FAILURE(status)) {
-						return_ACPI_STATUS(status);
-					}
-				}
-
 				return_ACPI_STATUS(AE_OK);
 			}
 		}
@@ -622,12 +608,15 @@ acpi_ev_initialize_region(union acpi_ope
 		node = node->parent;
 	}
 
-	/* If we get here, there is no handler for this region */
-
+	/*
+	 * If we get here, there is no handler for this region. This is not
+	 * fatal because many regions get created before a handler is installed
+	 * for said region.
+	 */
 	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 			  "No handler for RegionType %s(%X) (RegionObj %p)\n",
 			  acpi_ut_get_region_name(space_id), space_id,
 			  region_obj));
 
-	return_ACPI_STATUS(AE_NOT_EXIST);
+	return_ACPI_STATUS(AE_OK);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/exconfig.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/exconfig.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/exconfig.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/exconfig.c	2017-02-12 16:03:20.000000000 -0500
@@ -437,10 +437,9 @@ acpi_ex_load_op(union acpi_operand_objec
 
 	ACPI_INFO(("Dynamic OEM Table Load:"));
 	acpi_ex_exit_interpreter();
-	status =
-	    acpi_tb_install_and_load_table(table, ACPI_PTR_TO_PHYSADDR(table),
-					   ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
-					   TRUE, &table_index);
+	status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
+						ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
+						TRUE, &table_index);
 	acpi_ex_enter_interpreter();
 	if (ACPI_FAILURE(status)) {
 
@@ -500,7 +499,6 @@ acpi_status acpi_ex_unload_table(union a
 	acpi_status status = AE_OK;
 	union acpi_operand_object *table_desc = ddb_handle;
 	u32 table_index;
-	struct acpi_table_header *table;
 
 	ACPI_FUNCTION_TRACE(ex_unload_table);
 
@@ -537,39 +535,7 @@ acpi_status acpi_ex_unload_table(union a
 	 * strict order requirement against it.
 	 */
 	acpi_ex_exit_interpreter();
-
-	/* Ensure the table is still loaded */
-
-	if (!acpi_tb_is_table_loaded(table_index)) {
-		status = AE_NOT_EXIST;
-		goto lock_and_exit;
-	}
-
-	/* Invoke table handler if present */
-
-	if (acpi_gbl_table_handler) {
-		status = acpi_get_table_by_index(table_index, &table);
-		if (ACPI_SUCCESS(status)) {
-			(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
-						     table,
-						     acpi_gbl_table_handler_context);
-		}
-	}
-
-	/* Delete the portion of the namespace owned by this table */
-
-	status = acpi_tb_delete_namespace_by_owner(table_index);
-	if (ACPI_FAILURE(status)) {
-		goto lock_and_exit;
-	}
-
-	(void)acpi_tb_release_owner_id(table_index);
-	acpi_tb_set_table_loaded_flag(table_index, FALSE);
-
-lock_and_exit:
-
-	/* Re-acquire the interpreter lock */
-
+	status = acpi_tb_unload_table(table_index);
 	acpi_ex_enter_interpreter();
 
 	/*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/nsnames.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/nsnames.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/nsnames.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/nsnames.c	2017-02-12 16:03:20.000000000 -0500
@@ -97,6 +97,51 @@ acpi_size acpi_ns_get_pathname_length(st
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ns_handle_to_name
+ *
+ * PARAMETERS:  target_handle           - Handle of named object whose name is
+ *                                        to be found
+ *              buffer                  - Where the name is returned
+ *
+ * RETURN:      Status, Buffer is filled with name if status is AE_OK
+ *
+ * DESCRIPTION: Build and return a full namespace name
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_handle_to_name(acpi_handle target_handle, struct acpi_buffer *buffer)
+{
+	acpi_status status;
+	struct acpi_namespace_node *node;
+	const char *node_name;
+
+	ACPI_FUNCTION_TRACE_PTR(ns_handle_to_name, target_handle);
+
+	node = acpi_ns_validate_handle(target_handle);
+	if (!node) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	/* Validate/Allocate/Clear caller buffer */
+
+	status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Just copy the ACPI name from the Node and zero terminate it */
+
+	node_name = acpi_ut_get_node_name(node);
+	ACPI_MOVE_NAME(buffer->pointer, node_name);
+	((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%4.4s\n", (char *)buffer->pointer));
+	return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ns_handle_to_pathname
  *
  * PARAMETERS:  target_handle           - Handle of named object whose name is
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/nsxfname.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/nsxfname.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/nsxfname.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/nsxfname.c	2017-02-12 16:03:20.000000000 -0500
@@ -158,8 +158,6 @@ acpi_status
 acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer *buffer)
 {
 	acpi_status status;
-	struct acpi_namespace_node *node;
-	const char *node_name;
 
 	/* Parameter validation */
 
@@ -172,18 +170,6 @@ acpi_get_name(acpi_handle handle, u32 na
 		return (status);
 	}
 
-	if (name_type == ACPI_FULL_PATHNAME ||
-	    name_type == ACPI_FULL_PATHNAME_NO_TRAILING) {
-
-		/* Get the full pathname (From the namespace root) */
-
-		status = acpi_ns_handle_to_pathname(handle, buffer,
-						    name_type ==
-						    ACPI_FULL_PATHNAME ? FALSE :
-						    TRUE);
-		return (status);
-	}
-
 	/*
 	 * Wants the single segment ACPI name.
 	 * Validate handle and convert to a namespace Node
@@ -193,27 +179,20 @@ acpi_get_name(acpi_handle handle, u32 na
 		return (status);
 	}
 
-	node = acpi_ns_validate_handle(handle);
-	if (!node) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
-	}
-
-	/* Validate/Allocate/Clear caller buffer */
-
-	status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
-	if (ACPI_FAILURE(status)) {
-		goto unlock_and_exit;
-	}
+	if (name_type == ACPI_FULL_PATHNAME ||
+	    name_type == ACPI_FULL_PATHNAME_NO_TRAILING) {
 
-	/* Just copy the ACPI name from the Node and zero terminate it */
+		/* Get the full pathname (From the namespace root) */
 
-	node_name = acpi_ut_get_node_name(node);
-	ACPI_MOVE_NAME(buffer->pointer, node_name);
-	((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
-	status = AE_OK;
+		status = acpi_ns_handle_to_pathname(handle, buffer,
+						    name_type ==
+						    ACPI_FULL_PATHNAME ? FALSE :
+						    TRUE);
+	} else {
+		/* Get the single name */
 
-unlock_and_exit:
+		status = acpi_ns_handle_to_name(handle, buffer);
+	}
 
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return (status);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/tbdata.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbdata.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/tbdata.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbdata.c	2017-02-12 16:03:20.000000000 -0500
@@ -832,9 +832,9 @@ acpi_tb_load_table(u32 table_index, stru
  *
  * FUNCTION:    acpi_tb_install_and_load_table
  *
- * PARAMETERS:  table                   - Pointer to the table
- *              address                 - Physical address of the table
+ * PARAMETERS:  address                 - Physical address of the table
  *              flags                   - Allocation flags of the table
+ *              override                - Whether override should be performed
  *              table_index             - Where table index is returned
  *
  * RETURN:      Status
@@ -844,65 +844,73 @@ acpi_tb_load_table(u32 table_index, stru
  ******************************************************************************/
 
 acpi_status
-acpi_tb_install_and_load_table(struct acpi_table_header *table,
-			       acpi_physical_address address,
+acpi_tb_install_and_load_table(acpi_physical_address address,
 			       u8 flags, u8 override, u32 *table_index)
 {
 	acpi_status status;
 	u32 i;
-	acpi_owner_id owner_id;
 
-	ACPI_FUNCTION_TRACE(acpi_load_table);
-
-	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+	ACPI_FUNCTION_TRACE(tb_install_and_load_table);
 
 	/* Install the table and load it into the namespace */
 
 	status = acpi_tb_install_standard_table(address, flags, TRUE,
 						override, &i);
 	if (ACPI_FAILURE(status)) {
-		goto unlock_and_exit;
+		goto exit;
 	}
 
-	/*
-	 * Note: Now table is "INSTALLED", it must be validated before
-	 * using.
-	 */
-	status = acpi_tb_validate_table(&acpi_gbl_root_table_list.tables[i]);
-	if (ACPI_FAILURE(status)) {
-		goto unlock_and_exit;
-	}
+	status = acpi_tb_load_table(i, acpi_gbl_root_node);
 
-	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-	status = acpi_ns_load_table(i, acpi_gbl_root_node);
+exit:
+	*table_index = i;
+	return_ACPI_STATUS(status);
+}
 
-	/* Execute any module-level code that was found in the table */
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_unload_table
+ *
+ * PARAMETERS:  table_index             - Table index
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Unload an ACPI table
+ *
+ ******************************************************************************/
 
-	if (!acpi_gbl_parse_table_as_term_list
-	    && acpi_gbl_group_module_level_code) {
-		acpi_ns_exec_module_code_list();
-	}
+acpi_status acpi_tb_unload_table(u32 table_index)
+{
+	acpi_status status = AE_OK;
+	struct acpi_table_header *table;
 
-	/*
-	 * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
-	 * responsible for discovering any new wake GPEs by running _PRW methods
-	 * that may have been loaded by this table.
-	 */
-	status = acpi_tb_get_owner_id(i, &owner_id);
-	if (ACPI_SUCCESS(status)) {
-		acpi_ev_update_gpes(owner_id);
+	ACPI_FUNCTION_TRACE(tb_unload_table);
+
+	/* Ensure the table is still loaded */
+
+	if (!acpi_tb_is_table_loaded(table_index)) {
+		return_ACPI_STATUS(AE_NOT_EXIST);
 	}
 
 	/* Invoke table handler if present */
 
 	if (acpi_gbl_table_handler) {
-		(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
-					     acpi_gbl_table_handler_context);
+		status = acpi_get_table_by_index(table_index, &table);
+		if (ACPI_SUCCESS(status)) {
+			(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
+						     table,
+						     acpi_gbl_table_handler_context);
+		}
 	}
-	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
-unlock_and_exit:
-	*table_index = i;
-	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+	/* Delete the portion of the namespace owned by this table */
+
+	status = acpi_tb_delete_namespace_by_owner(table_index);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	(void)acpi_tb_release_owner_id(table_index);
+	acpi_tb_set_table_loaded_flag(table_index, FALSE);
 	return_ACPI_STATUS(status);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/tbfadt.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbfadt.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/tbfadt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbfadt.c	2017-02-12 16:03:20.000000000 -0500
@@ -311,6 +311,8 @@ void acpi_tb_parse_fadt(void)
 {
 	u32 length;
 	struct acpi_table_header *table;
+	struct acpi_table_desc *fadt_desc;
+	acpi_status status;
 
 	/*
 	 * The FADT has multiple versions with different lengths,
@@ -319,14 +321,12 @@ void acpi_tb_parse_fadt(void)
 	 * Get a local copy of the FADT and convert it to a common format
 	 * Map entire FADT, assumed to be smaller than one page.
 	 */
-	length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
-
-	table =
-	    acpi_os_map_memory(acpi_gbl_root_table_list.
-			       tables[acpi_gbl_fadt_index].address, length);
-	if (!table) {
+	fadt_desc = &acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index];
+	status = acpi_tb_get_table(fadt_desc, &table);
+	if (ACPI_FAILURE(status)) {
 		return;
 	}
+	length = fadt_desc->length;
 
 	/*
 	 * Validate the FADT checksum before we copy the table. Ignore
@@ -340,7 +340,7 @@ void acpi_tb_parse_fadt(void)
 
 	/* All done with the real FADT, unmap it */
 
-	acpi_os_unmap_memory(table, length);
+	acpi_tb_put_table(fadt_desc);
 
 	/* Obtain the DSDT and FACS tables via their addresses within the FADT */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/tbinstal.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbinstal.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/tbinstal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbinstal.c	2017-02-12 16:03:20.000000000 -0500
@@ -217,6 +217,10 @@ acpi_tb_install_standard_table(acpi_phys
 		goto release_and_exit;
 	}
 
+	/* Acquire the table lock */
+
+	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
 	if (reload) {
 		/*
 		 * Validate the incoming table signature.
@@ -244,7 +248,7 @@ acpi_tb_install_standard_table(acpi_phys
 					 new_table_desc.signature.integer));
 
 			status = AE_BAD_SIGNATURE;
-			goto release_and_exit;
+			goto unlock_and_exit;
 		}
 
 		/* Check if table is already registered */
@@ -279,7 +283,7 @@ acpi_tb_install_standard_table(acpi_phys
 				/* Table is still loaded, this is an error */
 
 				status = AE_ALREADY_EXISTS;
-				goto release_and_exit;
+				goto unlock_and_exit;
 			} else {
 				/*
 				 * Table was unloaded, allow it to be reloaded.
@@ -290,6 +294,7 @@ acpi_tb_install_standard_table(acpi_phys
 				 * indicate the re-installation.
 				 */
 				acpi_tb_uninstall_table(&new_table_desc);
+				(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 				*table_index = i;
 				return_ACPI_STATUS(AE_OK);
 			}
@@ -303,11 +308,19 @@ acpi_tb_install_standard_table(acpi_phys
 
 	/* Invoke table handler if present */
 
+	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 	if (acpi_gbl_table_handler) {
 		(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_INSTALL,
 					     new_table_desc.pointer,
 					     acpi_gbl_table_handler_context);
 	}
+	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
+unlock_and_exit:
+
+	/* Release the table lock */
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 
 release_and_exit:
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/tbutils.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbutils.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/tbutils.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbutils.c	2017-02-12 16:03:20.000000000 -0500
@@ -381,3 +381,88 @@ next_table:
 	acpi_os_unmap_memory(table, length);
 	return_ACPI_STATUS(AE_OK);
 }
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_get_table
+ *
+ * PARAMETERS:  table_desc          - Table descriptor
+ *              out_table           - Where the pointer to the table is returned
+ *
+ * RETURN:      Status and pointer to the requested table
+ *
+ * DESCRIPTION: Increase a reference to a table descriptor and return the
+ *              validated table pointer.
+ *              If the table descriptor is an entry of the root table list,
+ *              this API must be invoked with ACPI_MTX_TABLES acquired.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_tb_get_table(struct acpi_table_desc *table_desc,
+		  struct acpi_table_header **out_table)
+{
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_tb_get_table);
+
+	if (table_desc->validation_count == 0) {
+
+		/* Table need to be "VALIDATED" */
+
+		status = acpi_tb_validate_table(table_desc);
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+	}
+
+	table_desc->validation_count++;
+	if (table_desc->validation_count == 0) {
+		ACPI_ERROR((AE_INFO,
+			    "Table %p, Validation count is zero after increment\n",
+			    table_desc));
+		table_desc->validation_count--;
+		return_ACPI_STATUS(AE_LIMIT);
+	}
+
+	*out_table = table_desc->pointer;
+	return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_put_table
+ *
+ * PARAMETERS:  table_desc          - Table descriptor
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Decrease a reference to a table descriptor and release the
+ *              validated table pointer if no references.
+ *              If the table descriptor is an entry of the root table list,
+ *              this API must be invoked with ACPI_MTX_TABLES acquired.
+ *
+ ******************************************************************************/
+
+void acpi_tb_put_table(struct acpi_table_desc *table_desc)
+{
+
+	ACPI_FUNCTION_TRACE(acpi_tb_put_table);
+
+	if (table_desc->validation_count == 0) {
+		ACPI_WARNING((AE_INFO,
+			      "Table %p, Validation count is zero before decrement\n",
+			      table_desc));
+		return_VOID;
+	}
+	table_desc->validation_count--;
+
+	if (table_desc->validation_count == 0) {
+
+		/* Table need to be "INVALIDATED" */
+
+		acpi_tb_invalidate_table(table_desc);
+	}
+
+	return_VOID;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/tbxface.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbxface.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/tbxface.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbxface.c	2017-02-12 16:03:20.000000000 -0500
@@ -167,6 +167,7 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_
 acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
 {
 	acpi_status status;
+	u32 i;
 
 	ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
 
@@ -178,6 +179,21 @@ acpi_status ACPI_INIT_FUNCTION acpi_real
 		return_ACPI_STATUS(AE_SUPPORT);
 	}
 
+	/*
+	 * Ensure OS early boot logic, which is required by some hosts. If the
+	 * table state is reported to be wrong, developers should fix the
+	 * issue by invoking acpi_put_table() for the reported table during the
+	 * early stage.
+	 */
+	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
+		if (acpi_gbl_root_table_list.tables[i].pointer) {
+			ACPI_ERROR((AE_INFO,
+				    "Table [%4.4s] is not invalidated during early boot stage",
+				    acpi_gbl_root_table_list.tables[i].
+				    signature.ascii));
+		}
+	}
+
 	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
 
 	status = acpi_tb_resize_root_table_list();
@@ -266,7 +282,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_header
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_get_table_with_size
+ * FUNCTION:    acpi_get_table
  *
  * PARAMETERS:  signature           - ACPI signature of needed table
  *              instance            - Which instance (for SSDTs)
@@ -276,16 +292,21 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_header
  *
  * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
  *              RSDT/XSDT.
+ *              Note that an early stage acpi_get_table() call must be paired
+ *              with an early stage acpi_put_table() call. otherwise the table
+ *              pointer mapped by the early stage mapping implementation may be
+ *              erroneously unmapped by the late stage unmapping implementation
+ *              in an acpi_put_table() invoked during the late stage.
  *
  ******************************************************************************/
 acpi_status
-acpi_get_table_with_size(char *signature,
-	       u32 instance, struct acpi_table_header **out_table,
-	       acpi_size *tbl_size)
+acpi_get_table(char *signature,
+	       u32 instance, struct acpi_table_header ** out_table)
 {
 	u32 i;
 	u32 j;
-	acpi_status status;
+	acpi_status status = AE_NOT_FOUND;
+	struct acpi_table_desc *table_desc;
 
 	/* Parameter validation */
 
@@ -293,13 +314,22 @@ acpi_get_table_with_size(char *signature
 		return (AE_BAD_PARAMETER);
 	}
 
+	/*
+	 * Note that the following line is required by some OSPMs, they only
+	 * check if the returned table is NULL instead of the returned status
+	 * to determined if this function is succeeded.
+	 */
+	*out_table = NULL;
+
+	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
 	/* Walk the root table list */
 
 	for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
 	     i++) {
-		if (!ACPI_COMPARE_NAME
-		    (&(acpi_gbl_root_table_list.tables[i].signature),
-		     signature)) {
+		table_desc = &acpi_gbl_root_table_list.tables[i];
+
+		if (!ACPI_COMPARE_NAME(&table_desc->signature, signature)) {
 			continue;
 		}
 
@@ -307,43 +337,65 @@ acpi_get_table_with_size(char *signature
 			continue;
 		}
 
-		status =
-		    acpi_tb_validate_table(&acpi_gbl_root_table_list.tables[i]);
-		if (ACPI_SUCCESS(status)) {
-			*out_table = acpi_gbl_root_table_list.tables[i].pointer;
-			*tbl_size = acpi_gbl_root_table_list.tables[i].length;
-		}
-
-		if (!acpi_gbl_permanent_mmap) {
-			acpi_gbl_root_table_list.tables[i].pointer = NULL;
-		}
-
-		return (status);
+		status = acpi_tb_get_table(table_desc, out_table);
+		break;
 	}
 
-	return (AE_NOT_FOUND);
+	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+	return (status);
 }
 
-ACPI_EXPORT_SYMBOL(acpi_get_table_with_size)
+ACPI_EXPORT_SYMBOL(acpi_get_table)
 
-acpi_status
-acpi_get_table(char *signature,
-	       u32 instance, struct acpi_table_header **out_table)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_put_table
+ *
+ * PARAMETERS:  table               - The pointer to the table
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Release a table returned by acpi_get_table() and its clones.
+ *              Note that it is not safe if this function was invoked after an
+ *              uninstallation happened to the original table descriptor.
+ *              Currently there is no OSPMs' requirement to handle such
+ *              situations.
+ *
+ ******************************************************************************/
+void acpi_put_table(struct acpi_table_header *table)
 {
-	acpi_size tbl_size;
+	u32 i;
+	struct acpi_table_desc *table_desc;
 
-	return acpi_get_table_with_size(signature,
-		       instance, out_table, &tbl_size);
+	ACPI_FUNCTION_TRACE(acpi_put_table);
+
+	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+
+	/* Walk the root table list */
+
+	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
+		table_desc = &acpi_gbl_root_table_list.tables[i];
+
+		if (table_desc->pointer != table) {
+			continue;
+		}
+
+		acpi_tb_put_table(table_desc);
+		break;
+	}
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+	return_VOID;
 }
 
-ACPI_EXPORT_SYMBOL(acpi_get_table)
+ACPI_EXPORT_SYMBOL(acpi_put_table)
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_table_by_index
  *
  * PARAMETERS:  table_index         - Table index
- *              table               - Where the pointer to the table is returned
+ *              out_table           - Where the pointer to the table is returned
  *
  * RETURN:      Status and pointer to the requested table
  *
@@ -352,7 +404,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table)
  *
  ******************************************************************************/
 acpi_status
-acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table)
 {
 	acpi_status status;
 
@@ -360,35 +412,33 @@ acpi_get_table_by_index(u32 table_index,
 
 	/* Parameter validation */
 
-	if (!table) {
+	if (!out_table) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
+	/*
+	 * Note that the following line is required by some OSPMs, they only
+	 * check if the returned table is NULL instead of the returned status
+	 * to determined if this function is succeeded.
+	 */
+	*out_table = NULL;
+
 	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 
 	/* Validate index */
 
 	if (table_index >= acpi_gbl_root_table_list.current_table_count) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
+		status = AE_BAD_PARAMETER;
+		goto unlock_and_exit;
 	}
 
-	if (!acpi_gbl_root_table_list.tables[table_index].pointer) {
-
-		/* Table is not mapped, map it */
-
-		status =
-		    acpi_tb_validate_table(&acpi_gbl_root_table_list.
-					   tables[table_index]);
-		if (ACPI_FAILURE(status)) {
-			(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-			return_ACPI_STATUS(status);
-		}
-	}
+	status =
+	    acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index],
+			      out_table);
 
-	*table = acpi_gbl_root_table_list.tables[table_index].pointer;
+unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-	return_ACPI_STATUS(AE_OK);
+	return_ACPI_STATUS(status);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/tbxfload.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbxfload.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/tbxfload.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/tbxfload.c	2017-02-12 16:03:20.000000000 -0500
@@ -239,7 +239,7 @@ acpi_status acpi_tb_load_namespace(void)
 	}
 
 	if (!tables_failed) {
-		ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded\n", tables_loaded));
+		ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded", tables_loaded));
 	} else {
 		ACPI_ERROR((AE_INFO,
 			    "%u table load failures, %u successful",
@@ -250,6 +250,10 @@ acpi_status acpi_tb_load_namespace(void)
 		status = AE_CTRL_TERMINATE;
 	}
 
+#ifdef ACPI_APPLICATION
+	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "\n"));
+#endif
+
 unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 	return_ACPI_STATUS(status);
@@ -326,10 +330,9 @@ acpi_status acpi_load_table(struct acpi_
 	/* Install the table and load it into the namespace */
 
 	ACPI_INFO(("Host-directed Dynamic ACPI Table Load:"));
-	status =
-	    acpi_tb_install_and_load_table(table, ACPI_PTR_TO_PHYSADDR(table),
-					   ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
-					   FALSE, &table_index);
+	status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
+						ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
+						FALSE, &table_index);
 	return_ACPI_STATUS(status);
 }
 
@@ -405,37 +408,8 @@ acpi_status acpi_unload_parent_table(acp
 			break;
 		}
 
-		/* Ensure the table is actually loaded */
-
 		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
-		if (!acpi_tb_is_table_loaded(i)) {
-			status = AE_NOT_EXIST;
-			(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
-			break;
-		}
-
-		/* Invoke table handler if present */
-
-		if (acpi_gbl_table_handler) {
-			(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
-						     acpi_gbl_root_table_list.
-						     tables[i].pointer,
-						     acpi_gbl_table_handler_context);
-		}
-
-		/*
-		 * Delete all namespace objects owned by this table. Note that
-		 * these objects can appear anywhere in the namespace by virtue
-		 * of the AML "Scope" operator. Thus, we need to track ownership
-		 * by an ID, not simply a position within the hierarchy.
-		 */
-		status = acpi_tb_delete_namespace_by_owner(i);
-		if (ACPI_FAILURE(status)) {
-			break;
-		}
-
-		status = acpi_tb_release_owner_id(i);
-		acpi_tb_set_table_loaded_flag(i, FALSE);
+		status = acpi_tb_unload_table(i);
 		(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 		break;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpica/utdecode.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/utdecode.c
--- linux-libre-4.9-gnu/drivers/acpi/acpica/utdecode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpica/utdecode.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,7 @@
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
+#include "amlcode.h"
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utdecode")
@@ -532,6 +533,54 @@ const char *acpi_ut_get_notify_name(u32
 
 	return ("Hardware-Specific");
 }
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_argument_type_name
+ *
+ * PARAMETERS:  arg_type            - an ARGP_* parser argument type
+ *
+ * RETURN:      Decoded ARGP_* type
+ *
+ * DESCRIPTION: Decode an ARGP_* parser type, as defined in the amlcode.h file,
+ *              and used in the acopcode.h file. For example, ARGP_TERMARG.
+ *              Used for debug only.
+ *
+ ******************************************************************************/
+
+static const char *acpi_gbl_argument_type[20] = {
+	/* 00 */ "Unknown ARGP",
+	/* 01 */ "ByteData",
+	/* 02 */ "ByteList",
+	/* 03 */ "CharList",
+	/* 04 */ "DataObject",
+	/* 05 */ "DataObjectList",
+	/* 06 */ "DWordData",
+	/* 07 */ "FieldList",
+	/* 08 */ "Name",
+	/* 09 */ "NameString",
+	/* 0A */ "ObjectList",
+	/* 0B */ "PackageLength",
+	/* 0C */ "SuperName",
+	/* 0D */ "Target",
+	/* 0E */ "TermArg",
+	/* 0F */ "TermList",
+	/* 10 */ "WordData",
+	/* 11 */ "QWordData",
+	/* 12 */ "SimpleName",
+	/* 13 */ "NameOrRef"
+};
+
+const char *acpi_ut_get_argument_type_name(u32 arg_type)
+{
+
+	if (arg_type > ARGP_MAX) {
+		return ("Unknown ARGP");
+	}
+
+	return (acpi_gbl_argument_type[arg_type]);
+}
+
 #endif
 
 /*******************************************************************************
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpi_lpss.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_lpss.c
--- linux-libre-4.9-gnu/drivers/acpi/acpi_lpss.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_lpss.c	2017-02-12 16:03:20.000000000 -0500
@@ -718,13 +718,14 @@ static int acpi_lpss_resume_early(struct
 #define LPSS_GPIODEF0_DMA1_D3		BIT(2)
 #define LPSS_GPIODEF0_DMA2_D3		BIT(3)
 #define LPSS_GPIODEF0_DMA_D3_MASK	GENMASK(3, 2)
+#define LPSS_GPIODEF0_DMA_LLP		BIT(13)
 
 static DEFINE_MUTEX(lpss_iosf_mutex);
 
 static void lpss_iosf_enter_d3_state(void)
 {
 	u32 value1 = 0;
-	u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+	u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP;
 	u32 value2 = LPSS_PMCSR_D3hot;
 	u32 mask2 = LPSS_PMCSR_Dx_MASK;
 	/*
@@ -768,8 +769,9 @@ exit:
 
 static void lpss_iosf_exit_d3_state(void)
 {
-	u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3;
-	u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+	u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3 |
+		     LPSS_GPIODEF0_DMA_LLP;
+	u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK | LPSS_GPIODEF0_DMA_LLP;
 	u32 value2 = LPSS_PMCSR_D0;
 	u32 mask2 = LPSS_PMCSR_Dx_MASK;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpi_video.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_video.c
--- linux-libre-4.9-gnu/drivers/acpi/acpi_video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_video.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,23 +37,12 @@
 #include <linux/suspend.h>
 #include <linux/acpi.h>
 #include <acpi/video.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define PREFIX "ACPI: "
 
 #define ACPI_VIDEO_BUS_NAME		"Video Bus"
 #define ACPI_VIDEO_DEVICE_NAME		"Video Device"
-#define ACPI_VIDEO_NOTIFY_SWITCH	0x80
-#define ACPI_VIDEO_NOTIFY_PROBE		0x81
-#define ACPI_VIDEO_NOTIFY_CYCLE		0x82
-#define ACPI_VIDEO_NOTIFY_NEXT_OUTPUT	0x83
-#define ACPI_VIDEO_NOTIFY_PREV_OUTPUT	0x84
-
-#define ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS	0x85
-#define	ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS	0x86
-#define ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS	0x87
-#define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS	0x88
-#define ACPI_VIDEO_NOTIFY_DISPLAY_OFF		0x89
 
 #define MAX_NAME_LEN	20
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/acpi_watchdog.c linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_watchdog.c
--- linux-libre-4.9-gnu/drivers/acpi/acpi_watchdog.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/acpi_watchdog.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,7 +114,7 @@ void __init acpi_watchdog_init(void)
 	pdev = platform_device_register_simple("wdat_wdt", PLATFORM_DEVID_NONE,
 					       resources, nresources);
 	if (IS_ERR(pdev))
-		pr_err("Failed to create platform device\n");
+		pr_err("Device creation failed: %ld\n", PTR_ERR(pdev));
 
 	kfree(resources);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/apei/ghes.c linux-libre-4.10-rc8-gnu/drivers/acpi/apei/ghes.c
--- linux-libre-4.9-gnu/drivers/acpi/apei/ghes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/apei/ghes.c	2017-02-12 16:03:20.000000000 -0500
@@ -852,6 +852,8 @@ static int ghes_notify_nmi(unsigned int
 		if (ghes_read_estatus(ghes, 1)) {
 			ghes_clear_estatus(ghes);
 			continue;
+		} else {
+			ret = NMI_HANDLED;
 		}
 
 		sev = ghes_severity(ghes->estatus->error_severity);
@@ -863,12 +865,11 @@ static int ghes_notify_nmi(unsigned int
 
 		__process_error(ghes);
 		ghes_clear_estatus(ghes);
-
-		ret = NMI_HANDLED;
 	}
 
 #ifdef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG
-	irq_work_queue(&ghes_proc_irq_work);
+	if (ret == NMI_HANDLED)
+		irq_work_queue(&ghes_proc_irq_work);
 #endif
 	atomic_dec(&ghes_in_nmi);
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/apei/hest.c linux-libre-4.10-rc8-gnu/drivers/acpi/apei/hest.c
--- linux-libre-4.9-gnu/drivers/acpi/apei/hest.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/apei/hest.c	2017-02-12 16:03:20.000000000 -0500
@@ -123,7 +123,13 @@ EXPORT_SYMBOL_GPL(apei_hest_parse);
  */
 static int __init hest_parse_cmc(struct acpi_hest_header *hest_hdr, void *data)
 {
-	return arch_apei_enable_cmcff(hest_hdr, data);
+	if (hest_hdr->type != ACPI_HEST_TYPE_IA32_CORRECTED_CHECK)
+		return 0;
+
+	if (!acpi_disable_cmcff)
+		return !arch_apei_enable_cmcff(hest_hdr, data);
+
+	return 0;
 }
 
 struct ghes_arr {
@@ -232,8 +238,9 @@ void __init acpi_hest_init(void)
 		goto err;
 	}
 
-	if (!acpi_disable_cmcff)
-		apei_hest_parse(hest_parse_cmc, NULL);
+	rc = apei_hest_parse(hest_parse_cmc, NULL);
+	if (rc)
+		goto err;
 
 	if (!ghes_disable) {
 		rc = apei_hest_parse(hest_parse_ghes_count, &ghes_count);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/arm64/iort.c linux-libre-4.10-rc8-gnu/drivers/acpi/arm64/iort.c
--- linux-libre-4.9-gnu/drivers/acpi/arm64/iort.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/arm64/iort.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,8 +19,17 @@
 #define pr_fmt(fmt)	"ACPI: IORT: " fmt
 
 #include <linux/acpi_iort.h>
+#include <linux/iommu.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
 #include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define IORT_TYPE_MASK(type)	(1 << (type))
+#define IORT_MSI_TYPE		(1 << ACPI_IORT_NODE_ITS_GROUP)
+#define IORT_IOMMU_TYPE		((1 << ACPI_IORT_NODE_SMMU) |	\
+				(1 << ACPI_IORT_NODE_SMMU_V3))
 
 struct iort_its_msi_chip {
 	struct list_head	list;
@@ -28,6 +37,90 @@ struct iort_its_msi_chip {
 	u32			translation_id;
 };
 
+struct iort_fwnode {
+	struct list_head list;
+	struct acpi_iort_node *iort_node;
+	struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ *		       iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ *          <0 on failure
+ */
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+				  struct fwnode_handle *fwnode)
+{
+	struct iort_fwnode *np;
+
+	np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);
+
+	if (WARN_ON(!np))
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&np->list);
+	np->iort_node = iort_node;
+	np->fwnode = fwnode;
+
+	spin_lock(&iort_fwnode_lock);
+	list_add_tail(&np->list, &iort_fwnode_list);
+	spin_unlock(&iort_fwnode_lock);
+
+	return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success, NULL on failure
+ */
+static inline
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
+{
+	struct iort_fwnode *curr;
+	struct fwnode_handle *fwnode = NULL;
+
+	spin_lock(&iort_fwnode_lock);
+	list_for_each_entry(curr, &iort_fwnode_list, list) {
+		if (curr->iort_node == node) {
+			fwnode = curr->fwnode;
+			break;
+		}
+	}
+	spin_unlock(&iort_fwnode_lock);
+
+	return fwnode;
+}
+
+/**
+ * iort_delete_fwnode() - Delete fwnode associated with an IORT node
+ *
+ * @node: IORT table node associated with fwnode to delete
+ */
+static inline void iort_delete_fwnode(struct acpi_iort_node *node)
+{
+	struct iort_fwnode *curr, *tmp;
+
+	spin_lock(&iort_fwnode_lock);
+	list_for_each_entry_safe(curr, tmp, &iort_fwnode_list, list) {
+		if (curr->iort_node == node) {
+			list_del(&curr->list);
+			kfree(curr);
+			break;
+		}
+	}
+	spin_unlock(&iort_fwnode_lock);
+}
+
 typedef acpi_status (*iort_find_node_callback)
 	(struct acpi_iort_node *node, void *context);
 
@@ -141,6 +234,21 @@ static struct acpi_iort_node *iort_scan_
 	return NULL;
 }
 
+static acpi_status
+iort_match_type_callback(struct acpi_iort_node *node, void *context)
+{
+	return AE_OK;
+}
+
+bool iort_node_match(u8 type)
+{
+	struct acpi_iort_node *node;
+
+	node = iort_scan_node(type, iort_match_type_callback, NULL);
+
+	return node != NULL;
+}
+
 static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
 					    void *context)
 {
@@ -212,9 +320,48 @@ static int iort_id_map(struct acpi_iort_
 	return 0;
 }
 
+static
+struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
+					u32 *id_out, u8 type_mask,
+					int index)
+{
+	struct acpi_iort_node *parent;
+	struct acpi_iort_id_mapping *map;
+
+	if (!node->mapping_offset || !node->mapping_count ||
+				     index >= node->mapping_count)
+		return NULL;
+
+	map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, node,
+			   node->mapping_offset);
+
+	/* Firmware bug! */
+	if (!map->output_reference) {
+		pr_err(FW_BUG "[node %p type %d] ID map has NULL parent reference\n",
+		       node, node->type);
+		return NULL;
+	}
+
+	parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
+			       map->output_reference);
+
+	if (!(IORT_TYPE_MASK(parent->type) & type_mask))
+		return NULL;
+
+	if (map[index].flags & ACPI_IORT_ID_SINGLE_MAPPING) {
+		if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
+		    node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
+			*id_out = map[index].output_base;
+			return parent;
+		}
+	}
+
+	return NULL;
+}
+
 static struct acpi_iort_node *iort_node_map_rid(struct acpi_iort_node *node,
 						u32 rid_in, u32 *rid_out,
-						u8 type)
+						u8 type_mask)
 {
 	u32 rid = rid_in;
 
@@ -223,7 +370,7 @@ static struct acpi_iort_node *iort_node_
 		struct acpi_iort_id_mapping *map;
 		int i;
 
-		if (node->type == type) {
+		if (IORT_TYPE_MASK(node->type) & type_mask) {
 			if (rid_out)
 				*rid_out = rid;
 			return node;
@@ -296,7 +443,7 @@ u32 iort_msi_map_rid(struct device *dev,
 	if (!node)
 		return req_id;
 
-	iort_node_map_rid(node, req_id, &dev_id, ACPI_IORT_NODE_ITS_GROUP);
+	iort_node_map_rid(node, req_id, &dev_id, IORT_MSI_TYPE);
 	return dev_id;
 }
 
@@ -318,7 +465,7 @@ static int iort_dev_find_its_id(struct d
 	if (!node)
 		return -ENXIO;
 
-	node = iort_node_map_rid(node, req_id, NULL, ACPI_IORT_NODE_ITS_GROUP);
+	node = iort_node_map_rid(node, req_id, NULL, IORT_MSI_TYPE);
 	if (!node)
 		return -ENXIO;
 
@@ -356,13 +503,459 @@ struct irq_domain *iort_get_device_domai
 	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
 }
 
+static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
+{
+	u32 *rid = data;
+
+	*rid = alias;
+	return 0;
+}
+
+static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
+			       struct fwnode_handle *fwnode,
+			       const struct iommu_ops *ops)
+{
+	int ret = iommu_fwspec_init(dev, fwnode, ops);
+
+	if (!ret)
+		ret = iommu_fwspec_add_ids(dev, &streamid, 1);
+
+	return ret;
+}
+
+static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
+					struct acpi_iort_node *node,
+					u32 streamid)
+{
+	const struct iommu_ops *ops = NULL;
+	int ret = -ENODEV;
+	struct fwnode_handle *iort_fwnode;
+
+	if (node) {
+		iort_fwnode = iort_get_fwnode(node);
+		if (!iort_fwnode)
+			return NULL;
+
+		ops = iommu_get_instance(iort_fwnode);
+		if (!ops)
+			return NULL;
+
+		ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
+	}
+
+	return ret ? NULL : ops;
+}
+
+/**
+ * iort_set_dma_mask - Set-up dma mask for a device.
+ *
+ * @dev: device to configure
+ */
+void iort_set_dma_mask(struct device *dev)
+{
+	/*
+	 * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
+	 * setup the correct supported mask.
+	 */
+	if (!dev->coherent_dma_mask)
+		dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	/*
+	 * Set it to coherent_dma_mask by default if the architecture
+	 * code has not set it.
+	 */
+	if (!dev->dma_mask)
+		dev->dma_mask = &dev->coherent_dma_mask;
+}
+
+/**
+ * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ *
+ * @dev: device to configure
+ *
+ * Returns: iommu_ops pointer on configuration success
+ *          NULL on configuration failure
+ */
+const struct iommu_ops *iort_iommu_configure(struct device *dev)
+{
+	struct acpi_iort_node *node, *parent;
+	const struct iommu_ops *ops = NULL;
+	u32 streamid = 0;
+
+	if (dev_is_pci(dev)) {
+		struct pci_bus *bus = to_pci_dev(dev)->bus;
+		u32 rid;
+
+		pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid,
+				       &rid);
+
+		node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
+				      iort_match_node_callback, &bus->dev);
+		if (!node)
+			return NULL;
+
+		parent = iort_node_map_rid(node, rid, &streamid,
+					   IORT_IOMMU_TYPE);
+
+		ops = iort_iommu_xlate(dev, parent, streamid);
+
+	} else {
+		int i = 0;
+
+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+				      iort_match_node_callback, dev);
+		if (!node)
+			return NULL;
+
+		parent = iort_node_get_id(node, &streamid,
+					  IORT_IOMMU_TYPE, i++);
+
+		while (parent) {
+			ops = iort_iommu_xlate(dev, parent, streamid);
+
+			parent = iort_node_get_id(node, &streamid,
+						  IORT_IOMMU_TYPE, i++);
+		}
+	}
+
+	return ops;
+}
+
+static void __init acpi_iort_register_irq(int hwirq, const char *name,
+					  int trigger,
+					  struct resource *res)
+{
+	int irq = acpi_register_gsi(NULL, hwirq, trigger,
+				    ACPI_ACTIVE_HIGH);
+
+	if (irq <= 0) {
+		pr_err("could not register gsi hwirq %d name [%s]\n", hwirq,
+								      name);
+		return;
+	}
+
+	res->start = irq;
+	res->end = irq;
+	res->flags = IORESOURCE_IRQ;
+	res->name = name;
+}
+
+static int __init arm_smmu_v3_count_resources(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	/* Always present mem resource */
+	int num_res = 1;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	if (smmu->event_gsiv)
+		num_res++;
+
+	if (smmu->pri_gsiv)
+		num_res++;
+
+	if (smmu->gerr_gsiv)
+		num_res++;
+
+	if (smmu->sync_gsiv)
+		num_res++;
+
+	return num_res;
+}
+
+static void __init arm_smmu_v3_init_resources(struct resource *res,
+					      struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+	int num_res = 0;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	res[num_res].start = smmu->base_address;
+	res[num_res].end = smmu->base_address + SZ_128K - 1;
+	res[num_res].flags = IORESOURCE_MEM;
+
+	num_res++;
+
+	if (smmu->event_gsiv)
+		acpi_iort_register_irq(smmu->event_gsiv, "eventq",
+				       ACPI_EDGE_SENSITIVE,
+				       &res[num_res++]);
+
+	if (smmu->pri_gsiv)
+		acpi_iort_register_irq(smmu->pri_gsiv, "priq",
+				       ACPI_EDGE_SENSITIVE,
+				       &res[num_res++]);
+
+	if (smmu->gerr_gsiv)
+		acpi_iort_register_irq(smmu->gerr_gsiv, "gerror",
+				       ACPI_EDGE_SENSITIVE,
+				       &res[num_res++]);
+
+	if (smmu->sync_gsiv)
+		acpi_iort_register_irq(smmu->sync_gsiv, "cmdq-sync",
+				       ACPI_EDGE_SENSITIVE,
+				       &res[num_res++]);
+}
+
+static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu_v3 *smmu;
+
+	/* Retrieve SMMUv3 specific data */
+	smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	return smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE;
+}
+
+static int __init arm_smmu_count_resources(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu *smmu;
+
+	/* Retrieve SMMU specific data */
+	smmu = (struct acpi_iort_smmu *)node->node_data;
+
+	/*
+	 * Only consider the global fault interrupt and ignore the
+	 * configuration access interrupt.
+	 *
+	 * MMIO address and global fault interrupt resources are always
+	 * present so add them to the context interrupt count as a static
+	 * value.
+	 */
+	return smmu->context_interrupt_count + 2;
+}
+
+static void __init arm_smmu_init_resources(struct resource *res,
+					   struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu *smmu;
+	int i, hw_irq, trigger, num_res = 0;
+	u64 *ctx_irq, *glb_irq;
+
+	/* Retrieve SMMU specific data */
+	smmu = (struct acpi_iort_smmu *)node->node_data;
+
+	res[num_res].start = smmu->base_address;
+	res[num_res].end = smmu->base_address + smmu->span - 1;
+	res[num_res].flags = IORESOURCE_MEM;
+	num_res++;
+
+	glb_irq = ACPI_ADD_PTR(u64, node, smmu->global_interrupt_offset);
+	/* Global IRQs */
+	hw_irq = IORT_IRQ_MASK(glb_irq[0]);
+	trigger = IORT_IRQ_TRIGGER_MASK(glb_irq[0]);
+
+	acpi_iort_register_irq(hw_irq, "arm-smmu-global", trigger,
+				     &res[num_res++]);
+
+	/* Context IRQs */
+	ctx_irq = ACPI_ADD_PTR(u64, node, smmu->context_interrupt_offset);
+	for (i = 0; i < smmu->context_interrupt_count; i++) {
+		hw_irq = IORT_IRQ_MASK(ctx_irq[i]);
+		trigger = IORT_IRQ_TRIGGER_MASK(ctx_irq[i]);
+
+		acpi_iort_register_irq(hw_irq, "arm-smmu-context", trigger,
+				       &res[num_res++]);
+	}
+}
+
+static bool __init arm_smmu_is_coherent(struct acpi_iort_node *node)
+{
+	struct acpi_iort_smmu *smmu;
+
+	/* Retrieve SMMU specific data */
+	smmu = (struct acpi_iort_smmu *)node->node_data;
+
+	return smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK;
+}
+
+struct iort_iommu_config {
+	const char *name;
+	int (*iommu_init)(struct acpi_iort_node *node);
+	bool (*iommu_is_coherent)(struct acpi_iort_node *node);
+	int (*iommu_count_resources)(struct acpi_iort_node *node);
+	void (*iommu_init_resources)(struct resource *res,
+				     struct acpi_iort_node *node);
+};
+
+static const struct iort_iommu_config iort_arm_smmu_v3_cfg __initconst = {
+	.name = "arm-smmu-v3",
+	.iommu_is_coherent = arm_smmu_v3_is_coherent,
+	.iommu_count_resources = arm_smmu_v3_count_resources,
+	.iommu_init_resources = arm_smmu_v3_init_resources
+};
+
+static const struct iort_iommu_config iort_arm_smmu_cfg __initconst = {
+	.name = "arm-smmu",
+	.iommu_is_coherent = arm_smmu_is_coherent,
+	.iommu_count_resources = arm_smmu_count_resources,
+	.iommu_init_resources = arm_smmu_init_resources
+};
+
+static __init
+const struct iort_iommu_config *iort_get_iommu_cfg(struct acpi_iort_node *node)
+{
+	switch (node->type) {
+	case ACPI_IORT_NODE_SMMU_V3:
+		return &iort_arm_smmu_v3_cfg;
+	case ACPI_IORT_NODE_SMMU:
+		return &iort_arm_smmu_cfg;
+	default:
+		return NULL;
+	}
+}
+
+/**
+ * iort_add_smmu_platform_device() - Allocate a platform device for SMMU
+ * @node: Pointer to SMMU ACPI IORT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+static int __init iort_add_smmu_platform_device(struct acpi_iort_node *node)
+{
+	struct fwnode_handle *fwnode;
+	struct platform_device *pdev;
+	struct resource *r;
+	enum dev_dma_attr attr;
+	int ret, count;
+	const struct iort_iommu_config *ops = iort_get_iommu_cfg(node);
+
+	if (!ops)
+		return -ENODEV;
+
+	pdev = platform_device_alloc(ops->name, PLATFORM_DEVID_AUTO);
+	if (!pdev)
+		return PTR_ERR(pdev);
+
+	count = ops->iommu_count_resources(node);
+
+	r = kcalloc(count, sizeof(*r), GFP_KERNEL);
+	if (!r) {
+		ret = -ENOMEM;
+		goto dev_put;
+	}
+
+	ops->iommu_init_resources(r, node);
+
+	ret = platform_device_add_resources(pdev, r, count);
+	/*
+	 * Resources are duplicated in platform_device_add_resources,
+	 * free their allocated memory
+	 */
+	kfree(r);
+
+	if (ret)
+		goto dev_put;
+
+	/*
+	 * Add a copy of IORT node pointer to platform_data to
+	 * be used to retrieve IORT data information.
+	 */
+	ret = platform_device_add_data(pdev, &node, sizeof(node));
+	if (ret)
+		goto dev_put;
+
+	/*
+	 * We expect the dma masks to be equivalent for
+	 * all SMMUs set-ups
+	 */
+	pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+	fwnode = iort_get_fwnode(node);
+
+	if (!fwnode) {
+		ret = -ENODEV;
+		goto dev_put;
+	}
+
+	pdev->dev.fwnode = fwnode;
+
+	attr = ops->iommu_is_coherent(node) ?
+			     DEV_DMA_COHERENT : DEV_DMA_NON_COHERENT;
+
+	/* Configure DMA for the page table walker */
+	acpi_dma_configure(&pdev->dev, attr);
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto dma_deconfigure;
+
+	return 0;
+
+dma_deconfigure:
+	acpi_dma_deconfigure(&pdev->dev);
+dev_put:
+	platform_device_put(pdev);
+
+	return ret;
+}
+
+static void __init iort_init_platform_devices(void)
+{
+	struct acpi_iort_node *iort_node, *iort_end;
+	struct acpi_table_iort *iort;
+	struct fwnode_handle *fwnode;
+	int i, ret;
+
+	/*
+	 * iort_table and iort both point to the start of IORT table, but
+	 * have different struct types
+	 */
+	iort = (struct acpi_table_iort *)iort_table;
+
+	/* Get the first IORT node */
+	iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				 iort->node_offset);
+	iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
+				iort_table->length);
+
+	for (i = 0; i < iort->node_count; i++) {
+		if (iort_node >= iort_end) {
+			pr_err("iort node pointer overflows, bad table\n");
+			return;
+		}
+
+		if ((iort_node->type == ACPI_IORT_NODE_SMMU) ||
+			(iort_node->type == ACPI_IORT_NODE_SMMU_V3)) {
+
+			fwnode = acpi_alloc_fwnode_static();
+			if (!fwnode)
+				return;
+
+			iort_set_fwnode(iort_node, fwnode);
+
+			ret = iort_add_smmu_platform_device(iort_node);
+			if (ret) {
+				iort_delete_fwnode(iort_node);
+				acpi_free_fwnode_static(fwnode);
+				return;
+			}
+		}
+
+		iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
+					 iort_node->length);
+	}
+}
+
 void __init acpi_iort_init(void)
 {
 	acpi_status status;
 
 	status = acpi_get_table(ACPI_SIG_IORT, 0, &iort_table);
-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-		const char *msg = acpi_format_exception(status);
-		pr_err("Failed to get table, %s\n", msg);
+	if (ACPI_FAILURE(status)) {
+		if (status != AE_NOT_FOUND) {
+			const char *msg = acpi_format_exception(status);
+
+			pr_err("Failed to get table, %s\n", msg);
+		}
+
+		return;
 	}
+
+	iort_init_platform_devices();
+
+	acpi_probe_device_table(iort);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/battery.c linux-libre-4.10-rc8-gnu/drivers/acpi/battery.c
--- linux-libre-4.9-gnu/drivers/acpi/battery.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/battery.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #endif
 
 #include <linux/acpi.h>
@@ -430,39 +430,24 @@ static int acpi_battery_get_status(struc
 	return 0;
 }
 
-static int acpi_battery_get_info(struct acpi_battery *battery)
+
+static int extract_battery_info(const int use_bix,
+			 struct acpi_battery *battery,
+			 const struct acpi_buffer *buffer)
 {
 	int result = -EFAULT;
-	acpi_status status = 0;
-	char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
-			"_BIX" : "_BIF";
-
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
-	if (!acpi_battery_present(battery))
-		return 0;
-	mutex_lock(&battery->lock);
-	status = acpi_evaluate_object(battery->device->handle, name,
-						NULL, &buffer);
-	mutex_unlock(&battery->lock);
 
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
-		return -ENODEV;
-	}
-
-	if (battery_bix_broken_package)
-		result = extract_package(battery, buffer.pointer,
+	if (use_bix && battery_bix_broken_package)
+		result = extract_package(battery, buffer->pointer,
 				extended_info_offsets + 1,
 				ARRAY_SIZE(extended_info_offsets) - 1);
-	else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
-		result = extract_package(battery, buffer.pointer,
+	else if (use_bix)
+		result = extract_package(battery, buffer->pointer,
 				extended_info_offsets,
 				ARRAY_SIZE(extended_info_offsets));
 	else
-		result = extract_package(battery, buffer.pointer,
+		result = extract_package(battery, buffer->pointer,
 				info_offsets, ARRAY_SIZE(info_offsets));
-	kfree(buffer.pointer);
 	if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
 		battery->full_charge_capacity = battery->design_capacity;
 	if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
@@ -483,6 +468,45 @@ static int acpi_battery_get_info(struct
 	return result;
 }
 
+static int acpi_battery_get_info(struct acpi_battery *battery)
+{
+	const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
+	int use_bix;
+	int result = -ENODEV;
+
+	if (!acpi_battery_present(battery))
+		return 0;
+
+
+	for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
+		struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+		acpi_status status = AE_ERROR;
+
+		mutex_lock(&battery->lock);
+		status = acpi_evaluate_object(battery->device->handle,
+					      use_bix ? "_BIX":"_BIF",
+					      NULL, &buffer);
+		mutex_unlock(&battery->lock);
+
+		if (ACPI_FAILURE(status)) {
+			ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
+					use_bix ? "_BIX":"_BIF"));
+		} else {
+			result = extract_battery_info(use_bix,
+						      battery,
+						      &buffer);
+
+			kfree(buffer.pointer);
+			break;
+		}
+	}
+
+	if (!result && !use_bix && xinfo)
+		pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
+
+	return result;
+}
+
 static int acpi_battery_get_state(struct acpi_battery *battery)
 {
 	int result = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/blacklist.c linux-libre-4.10-rc8-gnu/drivers/acpi/blacklist.c
--- linux-libre-4.9-gnu/drivers/acpi/blacklist.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/blacklist.c	2017-02-12 16:03:20.000000000 -0500
@@ -160,6 +160,34 @@ static struct dmi_system_id acpi_rev_dmi
 		      DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343"),
 		},
 	},
+	{
+	 .callback = dmi_enable_rev_override,
+	 .ident = "DELL Precision 5520",
+	 .matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "Precision 5520"),
+		},
+	},
+	{
+	 .callback = dmi_enable_rev_override,
+	 .ident = "DELL Precision 3520",
+	 .matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "Precision 3520"),
+		},
+	},
+	/*
+	 * Resolves a quirk with the Dell Latitude 3350 that
+	 * causes the ethernet adapter to not function.
+	 */
+	{
+	 .callback = dmi_enable_rev_override,
+	 .ident = "DELL Latitude 3350",
+	 .matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "Latitude 3350"),
+		},
+	},
 #endif
 	{}
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/bus.c linux-libre-4.10-rc8-gnu/drivers/acpi/bus.c
--- linux-libre-4.9-gnu/drivers/acpi/bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -331,6 +331,16 @@ static void acpi_bus_osc_support(void)
 	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
 	capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT;
 
+#ifdef CONFIG_X86
+	if (boot_cpu_has(X86_FEATURE_HWP)) {
+		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_SUPPORT;
+		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPCV2_SUPPORT;
+	}
+#endif
+
+	if (IS_ENABLED(CONFIG_SCHED_MC_PRIO))
+		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_CPC_DIVERSE_HIGH_SUPPORT;
+
 	if (!ghes_disable)
 		capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_APEI_SUPPORT;
 	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
@@ -964,7 +974,7 @@ void __init acpi_early_init(void)
 	if (!acpi_strict)
 		acpi_gbl_enable_interpreter_slack = TRUE;
 
-	acpi_gbl_permanent_mmap = 1;
+	acpi_permanent_mmap = true;
 
 	/*
 	 * If the machine falls into the DMI check table,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/cppc_acpi.c linux-libre-4.10-rc8-gnu/drivers/acpi/cppc_acpi.c
--- linux-libre-4.9-gnu/drivers/acpi/cppc_acpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/cppc_acpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -776,21 +776,25 @@ int acpi_cppc_processor_probe(struct acp
 		init_waitqueue_head(&pcc_data.pcc_write_wait_q);
 	}
 
-	/* Plug PSD data into this CPUs CPC descriptor. */
-	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
-
 	/* Everything looks okay */
 	pr_debug("Parsed CPC struct for CPU: %d\n", pr->id);
 
 	/* Add per logical CPU nodes for reading its feedback counters. */
 	cpu_dev = get_cpu_device(pr->id);
-	if (!cpu_dev)
+	if (!cpu_dev) {
+		ret = -EINVAL;
 		goto out_free;
+	}
+
+	/* Plug PSD data into this CPUs CPC descriptor. */
+	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
 
 	ret = kobject_init_and_add(&cpc_ptr->kobj, &cppc_ktype, &cpu_dev->kobj,
 			"acpi_cppc");
-	if (ret)
+	if (ret) {
+		per_cpu(cpc_desc_ptr, pr->id) = NULL;
 		goto out_free;
+	}
 
 	kfree(output.pointer);
 	return 0;
@@ -824,6 +828,8 @@ void acpi_cppc_processor_exit(struct acp
 	void __iomem *addr;
 
 	cpc_ptr = per_cpu(cpc_desc_ptr, pr->id);
+	if (!cpc_ptr)
+		return;
 
 	/* Free all the mapped sys mem areas for this CPU */
 	for (i = 2; i < cpc_ptr->num_entries; i++) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/device_sysfs.c linux-libre-4.10-rc8-gnu/drivers/acpi/device_sysfs.c
--- linux-libre-4.9-gnu/drivers/acpi/device_sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/device_sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@ struct acpi_data_node_attr {
 
 static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf)
 {
-	return acpi_object_path(dn->handle, buf);
+	return dn->handle ? acpi_object_path(dn->handle, buf) : 0;
 }
 
 DATA_NODE_ATTR(path);
@@ -105,10 +105,10 @@ static void acpi_expose_nondev_subnodes(
 		init_completion(&dn->kobj_done);
 		ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype,
 					   kobj, "%s", dn->name);
-		if (ret)
-			acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
-		else
+		if (!ret)
 			acpi_expose_nondev_subnodes(&dn->kobj, &dn->data);
+		else if (dn->handle)
+			acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/event.c linux-libre-4.10-rc8-gnu/drivers/acpi/event.c
--- linux-libre-4.9-gnu/drivers/acpi/event.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/event.c	2017-02-12 16:03:20.000000000 -0500
@@ -82,8 +82,8 @@ static const struct genl_multicast_group
 	{ .name = ACPI_GENL_MCAST_GROUP_NAME, },
 };
 
-static struct genl_family acpi_event_genl_family = {
-	.id = GENL_ID_GENERATE,
+static struct genl_family acpi_event_genl_family __ro_after_init = {
+	.module = THIS_MODULE,
 	.name = ACPI_GENL_FAMILY_NAME,
 	.version = ACPI_GENL_VERSION,
 	.maxattr = ACPI_GENL_ATTR_MAX,
@@ -144,7 +144,7 @@ int acpi_bus_generate_netlink_event(cons
 
 EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
 
-static int acpi_event_genetlink_init(void)
+static int __init acpi_event_genetlink_init(void)
 {
 	return genl_register_family(&acpi_event_genl_family);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/glue.c linux-libre-4.10-rc8-gnu/drivers/acpi/glue.c
--- linux-libre-4.9-gnu/drivers/acpi/glue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/glue.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,7 +98,15 @@ static int find_child_checks(struct acpi
 	if (check_children && list_empty(&adev->children))
 		return -ENODEV;
 
-	return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
+	/*
+	 * If the device has a _HID (or _CID) returning a valid ACPI/PNP
+	 * device ID, it is better to make it look less attractive here, so that
+	 * the other device with the same _ADR value (that may not have a valid
+	 * device ID) can be matched going forward.  [This means a second spec
+	 * violation in a row, so whatever we do here is best effort anyway.]
+	 */
+	return sta_present && list_empty(&adev->pnp.ids) ?
+			FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
 }
 
 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
@@ -227,8 +235,7 @@ int acpi_bind_one(struct device *dev, st
 
 	attr = acpi_get_dma_attr(acpi_dev);
 	if (attr != DEV_DMA_NOT_SUPPORTED)
-		arch_setup_dma_ops(dev, 0, 0, NULL,
-				   attr == DEV_DMA_COHERENT);
+		acpi_dma_configure(dev, attr);
 
 	acpi_physnode_link_name(physical_node_name, node_id);
 	retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/internal.h linux-libre-4.10-rc8-gnu/drivers/acpi/internal.h
--- linux-libre-4.9-gnu/drivers/acpi/internal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/internal.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@ void acpi_amba_init(void);
 static inline void acpi_amba_init(void) {}
 #endif
 int acpi_sysfs_init(void);
+void acpi_gpe_apply_masked_gpes(void);
 void acpi_container_init(void);
 void acpi_memory_hotplug_init(void);
 #ifdef	CONFIG_ACPI_HOTPLUG_IOAPIC
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/Kconfig linux-libre-4.10-rc8-gnu/drivers/acpi/Kconfig
--- linux-libre-4.9-gnu/drivers/acpi/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@ config ACPI_PROCFS_POWER
 	  Say N to delete power /proc/acpi/ directories that have moved to /sys/
 
 config ACPI_REV_OVERRIDE_POSSIBLE
-	bool "Allow supported ACPI revision to be overriden"
+	bool "Allow supported ACPI revision to be overridden"
 	depends on X86
 	default y
 	help
@@ -342,7 +342,7 @@ config ACPI_DEBUG
 
 	  Use the acpi.debug_layer and acpi.debug_level kernel command-line
 	  parameters documented in Documentation/acpi/debug.txt and
-	  Documentation/kernel-parameters.txt to control the type and
+	  Documentation/admin-guide/kernel-parameters.rst to control the type and
 	  amount of debug output.
 
 config ACPI_PCI_SLOT
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/nfit/core.c linux-libre-4.10-rc8-gnu/drivers/acpi/nfit/core.c
--- linux-libre-4.9-gnu/drivers/acpi/nfit/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/nfit/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -2704,6 +2704,7 @@ static int acpi_nfit_flush_probe(struct
 	struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
 	struct device *dev = acpi_desc->dev;
 	struct acpi_nfit_flush_work flush;
+	int rc;
 
 	/* bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
 	device_lock(dev);
@@ -2716,7 +2717,10 @@ static int acpi_nfit_flush_probe(struct
 	INIT_WORK_ONSTACK(&flush.work, flush_probe);
 	COMPLETION_INITIALIZER_ONSTACK(flush.cmp);
 	queue_work(nfit_wq, &flush.work);
-	return wait_for_completion_interruptible(&flush.cmp);
+
+	rc = wait_for_completion_interruptible(&flush.cmp);
+	cancel_work_sync(&flush.work);
+	return rc;
 }
 
 static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
@@ -2806,12 +2810,13 @@ static int acpi_nfit_add(struct acpi_dev
 	acpi_size sz;
 	int rc = 0;
 
-	status = acpi_get_table_with_size(ACPI_SIG_NFIT, 0, &tbl, &sz);
+	status = acpi_get_table(ACPI_SIG_NFIT, 0, &tbl);
 	if (ACPI_FAILURE(status)) {
 		/* This is ok, we could have an nvdimm hotplugged later */
 		dev_dbg(dev, "failed to find NFIT at startup\n");
 		return 0;
 	}
+	sz = tbl->length;
 
 	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
 	if (!acpi_desc)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/numa.c linux-libre-4.10-rc8-gnu/drivers/acpi/numa.c
--- linux-libre-4.9-gnu/drivers/acpi/numa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/numa.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,7 @@ int acpi_map_pxm_to_node(int pxm)
 {
 	int node;
 
-	if (pxm < 0 || pxm >= MAX_PXM_DOMAINS)
+	if (pxm < 0 || pxm >= MAX_PXM_DOMAINS || numa_off)
 		return NUMA_NO_NODE;
 
 	node = pxm_to_node_map[pxm];
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/osl.c linux-libre-4.10-rc8-gnu/drivers/acpi/osl.c
--- linux-libre-4.9-gnu/drivers/acpi/osl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/osl.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@
 #include <linux/semaphore.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 
 #include "internal.h"
@@ -76,6 +76,7 @@ static struct workqueue_struct *kacpi_no
 static struct workqueue_struct *kacpi_hotplug_wq;
 static bool acpi_os_initialized;
 unsigned int acpi_sci_irq = INVALID_ACPI_IRQ;
+bool acpi_permanent_mmap = false;
 
 /*
  * This list of permanent mappings is for memory that may be accessed from
@@ -181,15 +182,15 @@ void acpi_os_vprintf(const char *fmt, va
 static unsigned long acpi_rsdp;
 static int __init setup_acpi_rsdp(char *arg)
 {
-	if (kstrtoul(arg, 16, &acpi_rsdp))
-		return -EINVAL;
-	return 0;
+	return kstrtoul(arg, 16, &acpi_rsdp);
 }
 early_param("acpi_rsdp", setup_acpi_rsdp);
 #endif
 
 acpi_physical_address __init acpi_os_get_root_pointer(void)
 {
+	acpi_physical_address pa = 0;
+
 #ifdef CONFIG_KEXEC
 	if (acpi_rsdp)
 		return acpi_rsdp;
@@ -198,21 +199,14 @@ acpi_physical_address __init acpi_os_get
 	if (efi_enabled(EFI_CONFIG_TABLES)) {
 		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
 			return efi.acpi20;
-		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
+		if (efi.acpi != EFI_INVALID_TABLE_ADDR)
 			return efi.acpi;
-		else {
-			printk(KERN_ERR PREFIX
-			       "System description tables not found\n");
-			return 0;
-		}
+		pr_err(PREFIX "System description tables not found\n");
 	} else if (IS_ENABLED(CONFIG_ACPI_LEGACY_TABLES_LOOKUP)) {
-		acpi_physical_address pa = 0;
-
 		acpi_find_root_pointer(&pa);
-		return pa;
 	}
 
-	return 0;
+	return pa;
 }
 
 /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
@@ -313,7 +307,7 @@ static void acpi_unmap(acpi_physical_add
  * virtual address).  If not found, map it, add it to that list and return a
  * pointer to it.
  *
- * During early init (when acpi_gbl_permanent_mmap has not been set yet) this
+ * During early init (when acpi_permanent_mmap has not been set yet) this
  * routine simply calls __acpi_map_table() to get the job done.
  */
 void __iomem *__ref
@@ -329,7 +323,7 @@ acpi_os_map_iomem(acpi_physical_address
 		return NULL;
 	}
 
-	if (!acpi_gbl_permanent_mmap)
+	if (!acpi_permanent_mmap)
 		return __acpi_map_table((unsigned long)phys, size);
 
 	mutex_lock(&acpi_ioremap_lock);
@@ -399,7 +393,7 @@ static void acpi_os_map_cleanup(struct a
  * mappings, drop a reference to it and unmap it if there are no more active
  * references to it.
  *
- * During early init (when acpi_gbl_permanent_mmap has not been set yet) this
+ * During early init (when acpi_permanent_mmap has not been set yet) this
  * routine simply calls __acpi_unmap_table() to get the job done.  Since
  * __acpi_unmap_table() is an __init function, the __ref annotation is needed
  * here.
@@ -408,7 +402,7 @@ void __ref acpi_os_unmap_iomem(void __io
 {
 	struct acpi_ioremap *map;
 
-	if (!acpi_gbl_permanent_mmap) {
+	if (!acpi_permanent_mmap) {
 		__acpi_unmap_table(virt, size);
 		return;
 	}
@@ -433,12 +427,6 @@ void __ref acpi_os_unmap_memory(void *vi
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
-void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
-{
-	if (!acpi_gbl_permanent_mmap)
-		__acpi_unmap_table(virt, size);
-}
-
 int acpi_os_map_generic_address(struct acpi_generic_address *gas)
 {
 	u64 addr;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/pci_mcfg.c linux-libre-4.10-rc8-gnu/drivers/acpi/pci_mcfg.c
--- linux-libre-4.9-gnu/drivers/acpi/pci_mcfg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/pci_mcfg.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/pci-acpi.h>
+#include <linux/pci-ecam.h>
 
 /* Structure to hold entries from the MCFG table */
 struct mcfg_entry {
@@ -32,12 +33,166 @@ struct mcfg_entry {
 	u8			bus_end;
 };
 
+#ifdef CONFIG_PCI_QUIRKS
+struct mcfg_fixup {
+	char oem_id[ACPI_OEM_ID_SIZE + 1];
+	char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
+	u32 oem_revision;
+	u16 segment;
+	struct resource bus_range;
+	struct pci_ecam_ops *ops;
+	struct resource cfgres;
+};
+
+#define MCFG_BUS_RANGE(start, end)	DEFINE_RES_NAMED((start),	\
+						((end) - (start) + 1),	\
+						NULL, IORESOURCE_BUS)
+#define MCFG_BUS_ANY			MCFG_BUS_RANGE(0x0, 0xff)
+
+static struct mcfg_fixup mcfg_quirks[] = {
+/*	{ OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */
+
+#define QCOM_ECAM32(seg) \
+	{ "QCOM  ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }
+	QCOM_ECAM32(0),
+	QCOM_ECAM32(1),
+	QCOM_ECAM32(2),
+	QCOM_ECAM32(3),
+	QCOM_ECAM32(4),
+	QCOM_ECAM32(5),
+	QCOM_ECAM32(6),
+	QCOM_ECAM32(7),
+
+#define HISI_QUAD_DOM(table_id, seg, ops) \
+	{ "HISI  ", table_id, 0, (seg) + 0, MCFG_BUS_ANY, ops }, \
+	{ "HISI  ", table_id, 0, (seg) + 1, MCFG_BUS_ANY, ops }, \
+	{ "HISI  ", table_id, 0, (seg) + 2, MCFG_BUS_ANY, ops }, \
+	{ "HISI  ", table_id, 0, (seg) + 3, MCFG_BUS_ANY, ops }
+	HISI_QUAD_DOM("HIP05   ",  0, &hisi_pcie_ops),
+	HISI_QUAD_DOM("HIP06   ",  0, &hisi_pcie_ops),
+	HISI_QUAD_DOM("HIP07   ",  0, &hisi_pcie_ops),
+	HISI_QUAD_DOM("HIP07   ",  4, &hisi_pcie_ops),
+	HISI_QUAD_DOM("HIP07   ",  8, &hisi_pcie_ops),
+	HISI_QUAD_DOM("HIP07   ", 12, &hisi_pcie_ops),
+
+#define THUNDER_PEM_RES(addr, node) \
+	DEFINE_RES_MEM((addr) + ((u64) (node) << 44), 0x39 * SZ_16M)
+#define THUNDER_PEM_QUIRK(rev, node) \
+	{ "CAVIUM", "THUNDERX", rev, 4 + (10 * (node)), MCFG_BUS_ANY,	    \
+	  &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88001f000000UL, node) },  \
+	{ "CAVIUM", "THUNDERX", rev, 5 + (10 * (node)), MCFG_BUS_ANY,	    \
+	  &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x884057000000UL, node) },  \
+	{ "CAVIUM", "THUNDERX", rev, 6 + (10 * (node)), MCFG_BUS_ANY,	    \
+	  &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88808f000000UL, node) },  \
+	{ "CAVIUM", "THUNDERX", rev, 7 + (10 * (node)), MCFG_BUS_ANY,	    \
+	  &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89001f000000UL, node) },  \
+	{ "CAVIUM", "THUNDERX", rev, 8 + (10 * (node)), MCFG_BUS_ANY,	    \
+	  &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x894057000000UL, node) },  \
+	{ "CAVIUM", "THUNDERX", rev, 9 + (10 * (node)), MCFG_BUS_ANY,	    \
+	  &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89808f000000UL, node) }
+	/* SoC pass2.x */
+	THUNDER_PEM_QUIRK(1, 0),
+	THUNDER_PEM_QUIRK(1, 1),
+
+#define THUNDER_ECAM_QUIRK(rev, seg)					\
+	{ "CAVIUM", "THUNDERX", rev, seg, MCFG_BUS_ANY,			\
+	&pci_thunder_ecam_ops }
+	/* SoC pass1.x */
+	THUNDER_PEM_QUIRK(2, 0),	/* off-chip devices */
+	THUNDER_PEM_QUIRK(2, 1),	/* off-chip devices */
+	THUNDER_ECAM_QUIRK(2,  0),
+	THUNDER_ECAM_QUIRK(2,  1),
+	THUNDER_ECAM_QUIRK(2,  2),
+	THUNDER_ECAM_QUIRK(2,  3),
+	THUNDER_ECAM_QUIRK(2, 10),
+	THUNDER_ECAM_QUIRK(2, 11),
+	THUNDER_ECAM_QUIRK(2, 12),
+	THUNDER_ECAM_QUIRK(2, 13),
+
+#define XGENE_V1_ECAM_MCFG(rev, seg) \
+	{"APM   ", "XGENE   ", rev, seg, MCFG_BUS_ANY, \
+		&xgene_v1_pcie_ecam_ops }
+#define XGENE_V2_ECAM_MCFG(rev, seg) \
+	{"APM   ", "XGENE   ", rev, seg, MCFG_BUS_ANY, \
+		&xgene_v2_pcie_ecam_ops }
+	/* X-Gene SoC with v1 PCIe controller */
+	XGENE_V1_ECAM_MCFG(1, 0),
+	XGENE_V1_ECAM_MCFG(1, 1),
+	XGENE_V1_ECAM_MCFG(1, 2),
+	XGENE_V1_ECAM_MCFG(1, 3),
+	XGENE_V1_ECAM_MCFG(1, 4),
+	XGENE_V1_ECAM_MCFG(2, 0),
+	XGENE_V1_ECAM_MCFG(2, 1),
+	XGENE_V1_ECAM_MCFG(2, 2),
+	XGENE_V1_ECAM_MCFG(2, 3),
+	XGENE_V1_ECAM_MCFG(2, 4),
+	/* X-Gene SoC with v2.1 PCIe controller */
+	XGENE_V2_ECAM_MCFG(3, 0),
+	XGENE_V2_ECAM_MCFG(3, 1),
+	/* X-Gene SoC with v2.2 PCIe controller */
+	XGENE_V2_ECAM_MCFG(4, 0),
+	XGENE_V2_ECAM_MCFG(4, 1),
+	XGENE_V2_ECAM_MCFG(4, 2),
+};
+
+static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
+static char mcfg_oem_table_id[ACPI_OEM_TABLE_ID_SIZE];
+static u32 mcfg_oem_revision;
+
+static int pci_mcfg_quirk_matches(struct mcfg_fixup *f, u16 segment,
+				  struct resource *bus_range)
+{
+	if (!memcmp(f->oem_id, mcfg_oem_id, ACPI_OEM_ID_SIZE) &&
+	    !memcmp(f->oem_table_id, mcfg_oem_table_id,
+	            ACPI_OEM_TABLE_ID_SIZE) &&
+	    f->oem_revision == mcfg_oem_revision &&
+	    f->segment == segment &&
+	    resource_contains(&f->bus_range, bus_range))
+		return 1;
+
+	return 0;
+}
+#endif
+
+static void pci_mcfg_apply_quirks(struct acpi_pci_root *root,
+				  struct resource *cfgres,
+				  struct pci_ecam_ops **ecam_ops)
+{
+#ifdef CONFIG_PCI_QUIRKS
+	u16 segment = root->segment;
+	struct resource *bus_range = &root->secondary;
+	struct mcfg_fixup *f;
+	int i;
+
+	for (i = 0, f = mcfg_quirks; i < ARRAY_SIZE(mcfg_quirks); i++, f++) {
+		if (pci_mcfg_quirk_matches(f, segment, bus_range)) {
+			if (f->cfgres.start)
+				*cfgres = f->cfgres;
+			if (f->ops)
+				*ecam_ops =  f->ops;
+			dev_info(&root->device->dev, "MCFG quirk: ECAM at %pR for %pR with %ps\n",
+				 cfgres, bus_range, *ecam_ops);
+			return;
+		}
+	}
+#endif
+}
+
 /* List to save MCFG entries */
 static LIST_HEAD(pci_mcfg_list);
 
-phys_addr_t pci_mcfg_lookup(u16 seg, struct resource *bus_res)
+int pci_mcfg_lookup(struct acpi_pci_root *root, struct resource *cfgres,
+		    struct pci_ecam_ops **ecam_ops)
 {
+	struct pci_ecam_ops *ops = &pci_generic_ecam_ops;
+	struct resource *bus_res = &root->secondary;
+	u16 seg = root->segment;
 	struct mcfg_entry *e;
+	struct resource res;
+
+	/* Use address from _CBA if present, otherwise lookup MCFG */
+	if (root->mcfg_addr)
+		goto skip_lookup;
 
 	/*
 	 * We expect exact match, unless MCFG entry end bus covers more than
@@ -45,10 +200,32 @@ phys_addr_t pci_mcfg_lookup(u16 seg, str
 	 */
 	list_for_each_entry(e, &pci_mcfg_list, list) {
 		if (e->segment == seg && e->bus_start == bus_res->start &&
-		    e->bus_end >= bus_res->end)
-			return e->addr;
+		    e->bus_end >= bus_res->end) {
+			root->mcfg_addr = e->addr;
+		}
+
 	}
 
+skip_lookup:
+	memset(&res, 0, sizeof(res));
+	if (root->mcfg_addr) {
+		res.start = root->mcfg_addr + (bus_res->start << 20);
+		res.end = res.start + (resource_size(bus_res) << 20) - 1;
+		res.flags = IORESOURCE_MEM;
+	}
+
+	/*
+	 * Allow quirks to override default ECAM ops and CFG resource
+	 * range.  This may even fabricate a CFG resource range in case
+	 * MCFG does not have it.  Invalid CFG start address means MCFG
+	 * firmware bug or we need another quirk in array.
+	 */
+	pci_mcfg_apply_quirks(root, &res, &ops);
+	if (!res.start)
+		return -ENXIO;
+
+	*cfgres = res;
+	*ecam_ops = ops;
 	return 0;
 }
 
@@ -79,6 +256,13 @@ static __init int pci_mcfg_parse(struct
 		list_add(&e->list, &pci_mcfg_list);
 	}
 
+#ifdef CONFIG_PCI_QUIRKS
+	/* Save MCFG IDs and revision for quirks matching */
+	memcpy(mcfg_oem_id, header->oem_id, ACPI_OEM_ID_SIZE);
+	memcpy(mcfg_oem_table_id, header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
+	mcfg_oem_revision = header->oem_revision;
+#endif
+
 	pr_info("MCFG table detected, %d entries\n", n);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/proc.c linux-libre-4.10-rc8-gnu/drivers/acpi/proc.c
--- linux-libre-4.9-gnu/drivers/acpi/proc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/proc.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
 #include <linux/suspend.h>
 #include <linux/bcd.h>
 #include <linux/acpi.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "sleep.h"
 #include "internal.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/processor_core.c linux-libre-4.10-rc8-gnu/drivers/acpi/processor_core.c
--- linux-libre-4.9-gnu/drivers/acpi/processor_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/processor_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -154,18 +154,16 @@ static phys_cpuid_t map_madt_entry(struc
 phys_cpuid_t __init acpi_map_madt_entry(u32 acpi_id)
 {
 	struct acpi_table_madt *madt = NULL;
-	acpi_size tbl_size;
 	phys_cpuid_t rv;
 
-	acpi_get_table_with_size(ACPI_SIG_MADT, 0,
-				 (struct acpi_table_header **)&madt,
-				 &tbl_size);
+	acpi_get_table(ACPI_SIG_MADT, 0,
+		       (struct acpi_table_header **)&madt);
 	if (!madt)
 		return PHYS_CPUID_INVALID;
 
 	rv = map_madt_entry(madt, 1, acpi_id, true);
 
-	early_acpi_os_unmap_memory(madt, tbl_size);
+	acpi_put_table((struct acpi_table_header *)madt);
 
 	return rv;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/processor_idle.c linux-libre-4.10-rc8-gnu/drivers/acpi/processor_idle.c
--- linux-libre-4.9-gnu/drivers/acpi/processor_idle.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/processor_idle.c	2017-02-12 16:03:20.000000000 -0500
@@ -141,7 +141,7 @@ static void lapic_timer_check_state(int
 	if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT))
 		return;
 
-	if (amd_e400_c1e_detected)
+	if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E))
 		type = ACPI_STATE_C1;
 
 	/*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/processor_perflib.c linux-libre-4.10-rc8-gnu/drivers/acpi/processor_perflib.c
--- linux-libre-4.9-gnu/drivers/acpi/processor_perflib.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/processor_perflib.c	2017-02-12 16:03:20.000000000 -0500
@@ -157,7 +157,7 @@ static void acpi_processor_ppc_ost(acpi_
 				  status, NULL);
 }
 
-int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
+void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
 {
 	int ret;
 
@@ -168,7 +168,7 @@ int acpi_processor_ppc_has_changed(struc
 		 */
 		if (event_flag)
 			acpi_processor_ppc_ost(pr->handle, 1);
-		return 0;
+		return;
 	}
 
 	ret = acpi_processor_get_platform_limit(pr);
@@ -182,10 +182,8 @@ int acpi_processor_ppc_has_changed(struc
 		else
 			acpi_processor_ppc_ost(pr->handle, 0);
 	}
-	if (ret < 0)
-		return (ret);
-	else
-		return cpufreq_update_policy(pr->id);
+	if (ret >= 0)
+		cpufreq_update_policy(pr->id);
 }
 
 int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
@@ -465,11 +463,33 @@ int acpi_processor_get_performance_info(
 	return result;
 }
 EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
-int acpi_processor_notify_smm(struct module *calling_module)
+
+int acpi_processor_pstate_control(void)
 {
 	acpi_status status;
-	static int is_done = 0;
 
+	if (!acpi_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control)
+		return 0;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+			  "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
+			  acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
+
+	status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
+				    (u32)acpi_gbl_FADT.pstate_control, 8);
+	if (ACPI_SUCCESS(status))
+		return 1;
+
+	ACPI_EXCEPTION((AE_INFO, status,
+			"Failed to write pstate_control [0x%x] to smi_command [0x%x]",
+			acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
+	return -EIO;
+}
+
+int acpi_processor_notify_smm(struct module *calling_module)
+{
+	static int is_done = 0;
+	int result;
 
 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
 		return -EBUSY;
@@ -492,26 +512,15 @@ int acpi_processor_notify_smm(struct mod
 
 	is_done = -EIO;
 
-	/* Can't write pstate_control to smi_command if either value is zero */
-	if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) {
+	result = acpi_processor_pstate_control();
+	if (!result) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
 		module_put(calling_module);
 		return 0;
 	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
-			  acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
-
-	status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
-				    (u32) acpi_gbl_FADT.pstate_control, 8);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status,
-				"Failed to write pstate_control [0x%x] to "
-				"smi_command [0x%x]", acpi_gbl_FADT.pstate_control,
-				acpi_gbl_FADT.smi_command));
+	if (result < 0) {
 		module_put(calling_module);
-		return status;
+		return result;
 	}
 
 	/* Success. If there's no _PPC, we need to fear nothing, so
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/processor_thermal.c linux-libre-4.10-rc8-gnu/drivers/acpi/processor_thermal.c
--- linux-libre-4.9-gnu/drivers/acpi/processor_thermal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/processor_thermal.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/cpufreq.h>
 #include <linux/acpi.h>
 #include <acpi/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define PREFIX "ACPI: "
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/processor_throttling.c linux-libre-4.10-rc8-gnu/drivers/acpi/processor_throttling.c
--- linux-libre-4.9-gnu/drivers/acpi/processor_throttling.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/processor_throttling.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/acpi.h>
 #include <acpi/processor.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define PREFIX "ACPI: "
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/property.c linux-libre-4.10-rc8-gnu/drivers/acpi/property.c
--- linux-libre-4.9-gnu/drivers/acpi/property.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/property.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,14 +41,13 @@ static bool acpi_enumerate_nondev_subnod
 static bool acpi_extract_properties(const union acpi_object *desc,
 				    struct acpi_device_data *data);
 
-static bool acpi_nondev_subnode_ok(acpi_handle scope,
-				   const union acpi_object *link,
-				   struct list_head *list)
+static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
+					acpi_handle handle,
+					const union acpi_object *link,
+					struct list_head *list)
 {
-	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
 	struct acpi_data_node *dn;
-	acpi_handle handle;
-	acpi_status status;
+	bool result;
 
 	dn = kzalloc(sizeof(*dn), GFP_KERNEL);
 	if (!dn)
@@ -58,43 +57,75 @@ static bool acpi_nondev_subnode_ok(acpi_
 	dn->fwnode.type = FWNODE_ACPI_DATA;
 	INIT_LIST_HEAD(&dn->data.subnodes);
 
-	status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
-				 &handle);
-	if (ACPI_FAILURE(status))
-		goto fail;
+	result = acpi_extract_properties(desc, &dn->data);
 
-	status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
-					    ACPI_TYPE_PACKAGE);
-	if (ACPI_FAILURE(status))
-		goto fail;
+	if (handle) {
+		acpi_handle scope;
+		acpi_status status;
 
-	if (acpi_extract_properties(buf.pointer, &dn->data))
-		dn->handle = handle;
+		/*
+		 * The scope for the subnode object lookup is the one of the
+		 * namespace node (device) containing the object that has
+		 * returned the package.  That is, it's the scope of that
+		 * object's parent.
+		 */
+		status = acpi_get_parent(handle, &scope);
+		if (ACPI_SUCCESS(status)
+		    && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data))
+			result = true;
+	} else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data)) {
+		result = true;
+	}
 
-	/*
-	 * The scope for the subnode object lookup is the one of the namespace
-	 * node (device) containing the object that has returned the package.
-	 * That is, it's the scope of that object's parent.
-	 */
-	status = acpi_get_parent(handle, &scope);
-	if (ACPI_SUCCESS(status)
-	    && acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data))
+	if (result) {
 		dn->handle = handle;
-
-	if (dn->handle) {
-		dn->data.pointer = buf.pointer;
+		dn->data.pointer = desc;
 		list_add_tail(&dn->sibling, list);
 		return true;
 	}
 
+	kfree(dn);
 	acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
+	return false;
+}
+
+static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
+					const union acpi_object *link,
+					struct list_head *list)
+{
+	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+	acpi_status status;
+
+	status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
+					    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(status))
+		return false;
+
+	if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list))
+		return true;
 
- fail:
 	ACPI_FREE(buf.pointer);
-	kfree(dn);
 	return false;
 }
 
+static bool acpi_nondev_subnode_ok(acpi_handle scope,
+				   const union acpi_object *link,
+				   struct list_head *list)
+{
+	acpi_handle handle;
+	acpi_status status;
+
+	if (!scope)
+		return false;
+
+	status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
+				 &handle);
+	if (ACPI_FAILURE(status))
+		return false;
+
+	return acpi_nondev_subnode_data_ok(handle, link, list);
+}
+
 static int acpi_add_nondev_subnodes(acpi_handle scope,
 				    const union acpi_object *links,
 				    struct list_head *list)
@@ -103,15 +134,37 @@ static int acpi_add_nondev_subnodes(acpi
 	int i;
 
 	for (i = 0; i < links->package.count; i++) {
-		const union acpi_object *link;
+		const union acpi_object *link, *desc;
+		acpi_handle handle;
+		bool result;
 
 		link = &links->package.elements[i];
-		/* Only two elements allowed, both must be strings. */
-		if (link->package.count == 2
-		    && link->package.elements[0].type == ACPI_TYPE_STRING
-		    && link->package.elements[1].type == ACPI_TYPE_STRING
-		    && acpi_nondev_subnode_ok(scope, link, list))
-			ret = true;
+		/* Only two elements allowed. */
+		if (link->package.count != 2)
+			continue;
+
+		/* The first one must be a string. */
+		if (link->package.elements[0].type != ACPI_TYPE_STRING)
+			continue;
+
+		/* The second one may be a string, a reference or a package. */
+		switch (link->package.elements[1].type) {
+		case ACPI_TYPE_STRING:
+			result = acpi_nondev_subnode_ok(scope, link, list);
+			break;
+		case ACPI_TYPE_LOCAL_REFERENCE:
+			handle = link->package.elements[1].reference.handle;
+			result = acpi_nondev_subnode_data_ok(handle, link, list);
+			break;
+		case ACPI_TYPE_PACKAGE:
+			desc = &link->package.elements[1];
+			result = acpi_nondev_subnode_extract(desc, NULL, link, list);
+			break;
+		default:
+			result = false;
+			break;
+		}
+		ret = ret || result;
 	}
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/resource.c linux-libre-4.10-rc8-gnu/drivers/acpi/resource.c
--- linux-libre-4.9-gnu/drivers/acpi/resource.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/resource.c	2017-02-12 16:03:20.000000000 -0500
@@ -664,3 +664,60 @@ int acpi_dev_filter_resource_type(struct
 	return (type & types) ? 0 : 1;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type);
+
+static int acpi_dev_consumes_res(struct acpi_device *adev, struct resource *res)
+{
+	struct list_head resource_list;
+	struct resource_entry *rentry;
+	int ret, found = 0;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+	if (ret < 0)
+		return 0;
+
+	list_for_each_entry(rentry, &resource_list, node) {
+		if (resource_contains(rentry->res, res)) {
+			found = 1;
+			break;
+		}
+
+	}
+
+	acpi_dev_free_resource_list(&resource_list);
+	return found;
+}
+
+static acpi_status acpi_res_consumer_cb(acpi_handle handle, u32 depth,
+					 void *context, void **ret)
+{
+	struct resource *res = context;
+	struct acpi_device **consumer = (struct acpi_device **) ret;
+	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+
+	if (acpi_dev_consumes_res(adev, res)) {
+		*consumer = adev;
+		return AE_CTRL_TERMINATE;
+	}
+
+	return AE_OK;
+}
+
+/**
+ * acpi_resource_consumer - Find the ACPI device that consumes @res.
+ * @res: Resource to search for.
+ *
+ * Search the current resource settings (_CRS) of every ACPI device node
+ * for @res.  If we find an ACPI device whose _CRS includes @res, return
+ * it.  Otherwise, return NULL.
+ */
+struct acpi_device *acpi_resource_consumer(struct resource *res)
+{
+	struct acpi_device *consumer = NULL;
+
+	acpi_get_devices(NULL, acpi_res_consumer_cb, res, (void **) &consumer);
+	return consumer;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/scan.c linux-libre-4.10-rc8-gnu/drivers/acpi/scan.c
--- linux-libre-4.9-gnu/drivers/acpi/scan.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/scan.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/acpi.h>
+#include <linux/acpi_iort.h>
 #include <linux/signal.h>
 #include <linux/kthread.h>
 #include <linux/dmi.h>
@@ -1119,9 +1120,6 @@ acpi_backlight_cap_match(acpi_handle han
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found generic backlight "
 				  "support\n"));
 		*cap |= ACPI_VIDEO_BACKLIGHT;
-		if (!acpi_has_method(handle, "_BQC"))
-			printk(KERN_WARNING FW_BUG PREFIX "No _BQC method, "
-				"cannot determine initial brightness\n");
 		/* We have backlight support, no need to scan further */
 		return AE_CTRL_TERMINATE;
 	}
@@ -1370,6 +1368,38 @@ enum dev_dma_attr acpi_get_dma_attr(stru
 		return DEV_DMA_NON_COHERENT;
 }
 
+/**
+ * acpi_dma_configure - Set-up DMA configuration for the device.
+ * @dev: The pointer to the device
+ * @attr: device dma attributes
+ */
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+{
+	const struct iommu_ops *iommu;
+
+	iort_set_dma_mask(dev);
+
+	iommu = iort_iommu_configure(dev);
+
+	/*
+	 * Assume dma valid range starts at 0 and covers the whole
+	 * coherent_dma_mask.
+	 */
+	arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
+			   attr == DEV_DMA_COHERENT);
+}
+EXPORT_SYMBOL_GPL(acpi_dma_configure);
+
+/**
+ * acpi_dma_deconfigure - Tear-down DMA configuration for the device.
+ * @dev: The pointer to the device
+ */
+void acpi_dma_deconfigure(struct device *dev)
+{
+	arch_teardown_dma_ops(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_dma_deconfigure);
+
 static void acpi_init_coherency(struct acpi_device *adev)
 {
 	unsigned long long cca = 0;
@@ -2044,6 +2074,7 @@ int __init acpi_scan_init(void)
 		}
 	}
 
+	acpi_gpe_apply_masked_gpes();
 	acpi_update_all_gpes();
 	acpi_ec_ecdt_start();
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/spcr.c linux-libre-4.10-rc8-gnu/drivers/acpi/spcr.c
--- linux-libre-4.9-gnu/drivers/acpi/spcr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/spcr.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,6 @@ int __init parse_spcr(bool earlycon)
 {
 	static char opts[64];
 	struct acpi_table_spcr *table;
-	acpi_size table_size;
 	acpi_status status;
 	char *uart;
 	char *iotype;
@@ -43,9 +42,8 @@ int __init parse_spcr(bool earlycon)
 	if (acpi_disabled)
 		return -ENODEV;
 
-	status = acpi_get_table_with_size(ACPI_SIG_SPCR, 0,
-					  (struct acpi_table_header **)&table,
-					  &table_size);
+	status = acpi_get_table(ACPI_SIG_SPCR, 0,
+				(struct acpi_table_header **)&table);
 
 	if (ACPI_FAILURE(status))
 		return -ENOENT;
@@ -106,6 +104,6 @@ int __init parse_spcr(bool earlycon)
 	err = add_preferred_console(uart, 0, opts + strlen(uart) + 1);
 
 done:
-	early_acpi_os_unmap_memory((void __iomem *)table, table_size);
+	acpi_put_table((struct acpi_table_header *)table);
 	return err;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/sysfs.c linux-libre-4.10-rc8-gnu/drivers/acpi/sysfs.c
--- linux-libre-4.9-gnu/drivers/acpi/sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -708,6 +708,62 @@ end:
 	return result ? result : size;
 }
 
+/*
+ * A Quirk Mechanism for GPE Flooding Prevention:
+ *
+ * Quirks may be needed to prevent GPE flooding on a specific GPE. The
+ * flooding typically cannot be detected and automatically prevented by
+ * ACPI_GPE_DISPATCH_NONE check because there is a _Lxx/_Exx prepared in
+ * the AML tables. This normally indicates a feature gap in Linux, thus
+ * instead of providing endless quirk tables, we provide a boot parameter
+ * for those who want this quirk. For example, if the users want to prevent
+ * the GPE flooding for GPE 00, they need to specify the following boot
+ * parameter:
+ *   acpi_mask_gpe=0x00
+ * The masking status can be modified by the following runtime controlling
+ * interface:
+ *   echo unmask > /sys/firmware/acpi/interrupts/gpe00
+ */
+
+/*
+ * Currently, the GPE flooding prevention only supports to mask the GPEs
+ * numbered from 00 to 7f.
+ */
+#define ACPI_MASKABLE_GPE_MAX	0x80
+
+static u64 __initdata acpi_masked_gpes;
+
+static int __init acpi_gpe_set_masked_gpes(char *val)
+{
+	u8 gpe;
+
+	if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
+		return -EINVAL;
+	acpi_masked_gpes |= ((u64)1<<gpe);
+
+	return 1;
+}
+__setup("acpi_mask_gpe=", acpi_gpe_set_masked_gpes);
+
+void __init acpi_gpe_apply_masked_gpes(void)
+{
+	acpi_handle handle;
+	acpi_status status;
+	u8 gpe;
+
+	for (gpe = 0;
+	     gpe < min_t(u8, ACPI_MASKABLE_GPE_MAX, acpi_current_gpe_count);
+	     gpe++) {
+		if (acpi_masked_gpes & ((u64)1<<gpe)) {
+			status = acpi_get_gpe_device(gpe, &handle);
+			if (ACPI_SUCCESS(status)) {
+				pr_info("Masking GPE 0x%x.\n", gpe);
+				(void)acpi_mask_gpe(handle, gpe, TRUE);
+			}
+		}
+	}
+}
+
 void acpi_irq_stats_init(void)
 {
 	acpi_status status;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/tables.c linux-libre-4.10-rc8-gnu/drivers/acpi/tables.c
--- linux-libre-4.9-gnu/drivers/acpi/tables.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/tables.c	2017-02-12 16:03:20.000000000 -0500
@@ -333,7 +333,6 @@ acpi_table_parse_entries_array(char *id,
 			 unsigned int max_entries)
 {
 	struct acpi_table_header *table_header = NULL;
-	acpi_size tbl_size;
 	int count;
 	u32 instance = 0;
 
@@ -346,7 +345,7 @@ acpi_table_parse_entries_array(char *id,
 	if (!strncmp(id, ACPI_SIG_MADT, 4))
 		instance = acpi_apic_instance;
 
-	acpi_get_table_with_size(id, instance, &table_header, &tbl_size);
+	acpi_get_table(id, instance, &table_header);
 	if (!table_header) {
 		pr_warn("%4.4s not present\n", id);
 		return -ENODEV;
@@ -355,7 +354,7 @@ acpi_table_parse_entries_array(char *id,
 	count = acpi_parse_entries_array(id, table_size, table_header,
 			proc, proc_num, max_entries);
 
-	early_acpi_os_unmap_memory((char *)table_header, tbl_size);
+	acpi_put_table(table_header);
 	return count;
 }
 
@@ -397,7 +396,6 @@ acpi_table_parse_madt(enum acpi_madt_typ
 int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler)
 {
 	struct acpi_table_header *table = NULL;
-	acpi_size tbl_size;
 
 	if (acpi_disabled)
 		return -ENODEV;
@@ -406,13 +404,13 @@ int __init acpi_table_parse(char *id, ac
 		return -EINVAL;
 
 	if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
-		acpi_get_table_with_size(id, acpi_apic_instance, &table, &tbl_size);
+		acpi_get_table(id, acpi_apic_instance, &table);
 	else
-		acpi_get_table_with_size(id, 0, &table, &tbl_size);
+		acpi_get_table(id, 0, &table);
 
 	if (table) {
 		handler(table);
-		early_acpi_os_unmap_memory(table, tbl_size);
+		acpi_put_table(table);
 		return 0;
 	} else
 		return -ENODEV;
@@ -426,16 +424,15 @@ int __init acpi_table_parse(char *id, ac
 static void __init check_multiple_madt(void)
 {
 	struct acpi_table_header *table = NULL;
-	acpi_size tbl_size;
 
-	acpi_get_table_with_size(ACPI_SIG_MADT, 2, &table, &tbl_size);
+	acpi_get_table(ACPI_SIG_MADT, 2, &table);
 	if (table) {
 		pr_warn("BIOS bug: multiple APIC/MADT found, using %d\n",
 			acpi_apic_instance);
 		pr_warn("If \"acpi_apic_instance=%d\" works better, "
 			"notify linux-acpi@vger.kernel.org\n",
 			acpi_apic_instance ? 0 : 2);
-		early_acpi_os_unmap_memory(table, tbl_size);
+		acpi_put_table(table);
 
 	} else
 		acpi_apic_instance = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/thermal.c linux-libre-4.10-rc8-gnu/drivers/acpi/thermal.c
--- linux-libre-4.9-gnu/drivers/acpi/thermal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/thermal.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@
 #include <linux/thermal.h>
 #include <linux/acpi.h>
 #include <linux/workqueue.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define PREFIX "ACPI: "
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/acpi/video_detect.c linux-libre-4.10-rc8-gnu/drivers/acpi/video_detect.c
--- linux-libre-4.9-gnu/drivers/acpi/video_detect.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/acpi/video_detect.c	2017-02-12 16:03:20.000000000 -0500
@@ -296,6 +296,15 @@ static const struct dmi_system_id video_
 		DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
 		},
 	},
+	{
+	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */
+	 .callback = video_detect_force_native,
+	 .ident = "Dell XPS 17 L702X",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
+		},
+	},
 	{ },
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/ahci.c linux-libre-4.10-rc8-gnu/drivers/ata/ahci.c
--- linux-libre-4.9-gnu/drivers/ata/ahci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/ahci.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,6 +46,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 #include <linux/libata.h>
+#include <linux/ahci-remap.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 #include "ahci.h"
 
 #define DRV_NAME	"ahci"
@@ -1400,6 +1402,40 @@ static irqreturn_t ahci_thunderx_irq_han
 }
 #endif
 
+static void ahci_remap_check(struct pci_dev *pdev, int bar,
+		struct ahci_host_priv *hpriv)
+{
+	int i, count = 0;
+	u32 cap;
+
+	/*
+	 * Check if this device might have remapped nvme devices.
+	 */
+	if (pdev->vendor != PCI_VENDOR_ID_INTEL ||
+	    pci_resource_len(pdev, bar) < SZ_512K ||
+	    bar != AHCI_PCI_BAR_STANDARD ||
+	    !(readl(hpriv->mmio + AHCI_VSCAP) & 1))
+		return;
+
+	cap = readq(hpriv->mmio + AHCI_REMAP_CAP);
+	for (i = 0; i < AHCI_MAX_REMAP; i++) {
+		if ((cap & (1 << i)) == 0)
+			continue;
+		if (readl(hpriv->mmio + ahci_remap_dcc(i))
+				!= PCI_CLASS_STORAGE_EXPRESS)
+			continue;
+
+		/* We've found a remapped device */
+		count++;
+	}
+
+	if (!count)
+		return;
+
+	dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count);
+	dev_warn(&pdev->dev, "Switch your BIOS from RAID to AHCI mode to use them.\n");
+}
+
 static int ahci_get_irq_vector(struct ata_host *host, int port)
 {
 	return pci_irq_vector(to_pci_dev(host->dev), port);
@@ -1541,6 +1577,9 @@ static int ahci_init_one(struct pci_dev
 
 	hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar];
 
+	/* detect remapped nvme devices */
+	ahci_remap_check(pdev, ahci_pci_bar, hpriv);
+
 	/* must set flag prior to save config in order to take effect */
 	if (ahci_broken_devslp(pdev))
 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/ahci_qoriq.c linux-libre-4.10-rc8-gnu/drivers/ata/ahci_qoriq.c
--- linux-libre-4.9-gnu/drivers/ata/ahci_qoriq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/ahci_qoriq.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,11 +46,13 @@
 #define LS1021A_AXICC_ADDR	0xC0
 
 #define SATA_ECC_DISABLE	0x00020000
+#define LS1046A_SATA_ECC_DIS	0x80000000
 
 enum ahci_qoriq_type {
 	AHCI_LS1021A,
 	AHCI_LS1043A,
 	AHCI_LS2080A,
+	AHCI_LS1046A,
 };
 
 struct ahci_qoriq_priv {
@@ -63,6 +65,7 @@ static const struct of_device_id ahci_qo
 	{ .compatible = "fsl,ls1021a-ahci", .data = (void *)AHCI_LS1021A},
 	{ .compatible = "fsl,ls1043a-ahci", .data = (void *)AHCI_LS1043A},
 	{ .compatible = "fsl,ls2080a-ahci", .data = (void *)AHCI_LS2080A},
+	{ .compatible = "fsl,ls1046a-ahci", .data = (void *)AHCI_LS1046A},
 	{},
 };
 MODULE_DEVICE_TABLE(of, ahci_qoriq_of_match);
@@ -175,6 +178,13 @@ static int ahci_qoriq_phy_init(struct ah
 		writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
 		writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
 		break;
+
+	case AHCI_LS1046A:
+		writel(LS1046A_SATA_ECC_DIS, qpriv->ecc_addr);
+		writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+		writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+		writel(AHCI_PORT_AXICC_CFG, reg_base + PORT_AXICC);
+		break;
 	}
 
 	return 0;
@@ -204,9 +214,9 @@ static int ahci_qoriq_probe(struct platf
 
 	qoriq_priv->type = (enum ahci_qoriq_type)of_id->data;
 
-	if (qoriq_priv->type == AHCI_LS1021A) {
-		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-				"sata-ecc");
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+			"sata-ecc");
+	if (res) {
 		qoriq_priv->ecc_addr = devm_ioremap_resource(dev, res);
 		if (IS_ERR(qoriq_priv->ecc_addr))
 			return PTR_ERR(qoriq_priv->ecc_addr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/libahci.c linux-libre-4.10-rc8-gnu/drivers/ata/libahci.c
--- linux-libre-4.9-gnu/drivers/ata/libahci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/libahci.c	2017-02-12 16:03:20.000000000 -0500
@@ -140,6 +140,7 @@ EXPORT_SYMBOL_GPL(ahci_shost_attrs);
 struct device_attribute *ahci_sdev_attrs[] = {
 	&dev_attr_sw_activity,
 	&dev_attr_unload_heads,
+	&dev_attr_ncq_prio_enable,
 	NULL
 };
 EXPORT_SYMBOL_GPL(ahci_sdev_attrs);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/libata-core.c linux-libre-4.10-rc8-gnu/drivers/ata/libata-core.c
--- linux-libre-4.9-gnu/drivers/ata/libata-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/libata-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -129,7 +129,7 @@ static int ata_force_tbl_size;
 static char ata_force_param_buf[PAGE_SIZE] __initdata;
 /* param_buf is thrown away after initialization, disallow read */
 module_param_string(force, ata_force_param_buf, sizeof(ata_force_param_buf), 0);
-MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/kernel-parameters.txt for details)");
+MODULE_PARM_DESC(force, "Force ATA configurations including cable type, link speed and transfer mode (see Documentation/admin-guide/kernel-parameters.rst for details)");
 
 static int atapi_enabled = 1;
 module_param(atapi_enabled, int, 0444);
@@ -739,6 +739,7 @@ u64 ata_tf_read_block(const struct ata_t
  *	@n_block: Number of blocks
  *	@tf_flags: RW/FUA etc...
  *	@tag: tag
+ *	@class: IO priority class
  *
  *	LOCKING:
  *	None.
@@ -753,7 +754,7 @@ u64 ata_tf_read_block(const struct ata_t
  */
 int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
 		    u64 block, u32 n_block, unsigned int tf_flags,
-		    unsigned int tag)
+		    unsigned int tag, int class)
 {
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	tf->flags |= tf_flags;
@@ -785,6 +786,12 @@ int ata_build_rw_tf(struct ata_taskfile
 		tf->device = ATA_LBA;
 		if (tf->flags & ATA_TFLAG_FUA)
 			tf->device |= 1 << 7;
+
+		if (dev->flags & ATA_DFLAG_NCQ_PRIO) {
+			if (class == IOPRIO_CLASS_RT)
+				tf->hob_nsect |= ATA_PRIO_HIGH <<
+						 ATA_SHIFT_PRIO;
+		}
 	} else if (dev->flags & ATA_DFLAG_LBA) {
 		tf->flags |= ATA_TFLAG_LBA;
 
@@ -1695,6 +1702,8 @@ unsigned ata_exec_internal_sg(struct ata
 
 		if (qc->err_mask & ~AC_ERR_OTHER)
 			qc->err_mask &= ~AC_ERR_OTHER;
+	} else if (qc->tf.command == ATA_CMD_REQ_SENSE_DATA) {
+		qc->result_tf.command |= ATA_SENSE;
 	}
 
 	/* finish up */
@@ -2156,6 +2165,37 @@ static void ata_dev_config_ncq_non_data(
 	}
 }
 
+static void ata_dev_config_ncq_prio(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->link->ap;
+	unsigned int err_mask;
+
+	if (!(dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE)) {
+		dev->flags &= ~ATA_DFLAG_NCQ_PRIO;
+		return;
+	}
+
+	err_mask = ata_read_log_page(dev,
+				     ATA_LOG_SATA_ID_DEV_DATA,
+				     ATA_LOG_SATA_SETTINGS,
+				     ap->sector_buf,
+				     1);
+	if (err_mask) {
+		ata_dev_dbg(dev,
+			    "failed to get Identify Device data, Emask 0x%x\n",
+			    err_mask);
+		return;
+	}
+
+	if (ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET] & BIT(3)) {
+		dev->flags |= ATA_DFLAG_NCQ_PRIO;
+	} else {
+		dev->flags &= ~ATA_DFLAG_NCQ_PRIO;
+		ata_dev_dbg(dev, "SATA page does not support priority\n");
+	}
+
+}
+
 static int ata_dev_config_ncq(struct ata_device *dev,
 			       char *desc, size_t desc_sz)
 {
@@ -2205,6 +2245,8 @@ static int ata_dev_config_ncq(struct ata
 			ata_dev_config_ncq_send_recv(dev);
 		if (ata_id_has_ncq_non_data(dev->id))
 			ata_dev_config_ncq_non_data(dev);
+		if (ata_id_has_ncq_prio(dev->id))
+			ata_dev_config_ncq_prio(dev);
 	}
 
 	return 0;
@@ -4316,10 +4358,10 @@ static const struct ata_blacklist_entry
 	{ "ST380013AS",		"3.20",		ATA_HORKAGE_MAX_SEC_1024 },
 
 	/*
-	 * Device times out with higher max sects.
+	 * These devices time out with higher max sects.
 	 * https://bugzilla.kernel.org/show_bug.cgi?id=121671
 	 */
-	{ "LITEON CX1-JB256-HP", NULL,		ATA_HORKAGE_MAX_SEC_1024 },
+	{ "LITEON CX1-JB*-HP",	NULL,		ATA_HORKAGE_MAX_SEC_1024 },
 
 	/* Devices we expect to fail diagnostics */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/libata.h linux-libre-4.10-rc8-gnu/drivers/ata/libata.h
--- linux-libre-4.9-gnu/drivers/ata/libata.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/libata.h	2017-02-12 16:03:20.000000000 -0500
@@ -66,7 +66,7 @@ extern u64 ata_tf_to_lba48(const struct
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
 			   u64 block, u32 n_block, unsigned int tf_flags,
-			   unsigned int tag);
+			   unsigned int tag, int class);
 extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
 			     struct ata_device *dev);
 extern unsigned ata_exec_internal(struct ata_device *dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/libata-scsi.c linux-libre-4.10-rc8-gnu/drivers/ata/libata-scsi.c
--- linux-libre-4.9-gnu/drivers/ata/libata-scsi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/libata-scsi.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,6 +50,7 @@
 #include <linux/uaccess.h>
 #include <linux/suspend.h>
 #include <asm/unaligned.h>
+#include <linux/ioprio.h>
 
 #include "libata.h"
 #include "libata-transport.h"
@@ -270,6 +271,83 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IW
 	    ata_scsi_park_show, ata_scsi_park_store);
 EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
 
+static ssize_t ata_ncq_prio_enable_show(struct device *device,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct scsi_device *sdev = to_scsi_device(device);
+	struct ata_port *ap;
+	struct ata_device *dev;
+	bool ncq_prio_enable;
+	int rc = 0;
+
+	ap = ata_shost_to_port(sdev->host);
+
+	spin_lock_irq(ap->lock);
+	dev = ata_scsi_find_dev(ap, sdev);
+	if (!dev) {
+		rc = -ENODEV;
+		goto unlock;
+	}
+
+	ncq_prio_enable = dev->flags & ATA_DFLAG_NCQ_PRIO_ENABLE;
+
+unlock:
+	spin_unlock_irq(ap->lock);
+
+	return rc ? rc : snprintf(buf, 20, "%u\n", ncq_prio_enable);
+}
+
+static ssize_t ata_ncq_prio_enable_store(struct device *device,
+					 struct device_attribute *attr,
+					 const char *buf, size_t len)
+{
+	struct scsi_device *sdev = to_scsi_device(device);
+	struct ata_port *ap;
+	struct ata_device *dev;
+	long int input;
+	int rc;
+
+	rc = kstrtol(buf, 10, &input);
+	if (rc)
+		return rc;
+	if ((input < 0) || (input > 1))
+		return -EINVAL;
+
+	ap = ata_shost_to_port(sdev->host);
+	dev = ata_scsi_find_dev(ap, sdev);
+	if (unlikely(!dev))
+		return  -ENODEV;
+
+	spin_lock_irq(ap->lock);
+	if (input)
+		dev->flags |= ATA_DFLAG_NCQ_PRIO_ENABLE;
+	else
+		dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE;
+
+	dev->link->eh_info.action |= ATA_EH_REVALIDATE;
+	dev->link->eh_info.flags |= ATA_EHI_QUIET;
+	ata_port_schedule_eh(ap);
+	spin_unlock_irq(ap->lock);
+
+	ata_port_wait_eh(ap);
+
+	if (input) {
+		spin_lock_irq(ap->lock);
+		if (!(dev->flags & ATA_DFLAG_NCQ_PRIO)) {
+			dev->flags &= ~ATA_DFLAG_NCQ_PRIO_ENABLE;
+			rc = -EIO;
+		}
+		spin_unlock_irq(ap->lock);
+	}
+
+	return rc ? rc : len;
+}
+
+DEVICE_ATTR(ncq_prio_enable, S_IRUGO | S_IWUSR,
+	    ata_ncq_prio_enable_show, ata_ncq_prio_enable_store);
+EXPORT_SYMBOL_GPL(dev_attr_ncq_prio_enable);
+
 void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd,
 			u8 sk, u8 asc, u8 ascq)
 {
@@ -401,6 +479,7 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
 
 struct device_attribute *ata_common_sdev_attrs[] = {
 	&dev_attr_unload_heads,
+	&dev_attr_ncq_prio_enable,
 	NULL
 };
 EXPORT_SYMBOL_GPL(ata_common_sdev_attrs);
@@ -1756,6 +1835,8 @@ static unsigned int ata_scsi_rw_xlat(str
 {
 	struct scsi_cmnd *scmd = qc->scsicmd;
 	const u8 *cdb = scmd->cmnd;
+	struct request *rq = scmd->request;
+	int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
 	unsigned int tf_flags = 0;
 	u64 block;
 	u32 n_block;
@@ -1822,7 +1903,8 @@ static unsigned int ata_scsi_rw_xlat(str
 	qc->nbytes = n_block * scmd->device->sector_size;
 
 	rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags,
-			     qc->tag);
+			     qc->tag, class);
+
 	if (likely(rc == 0))
 		return 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/pata_imx.c linux-libre-4.10-rc8-gnu/drivers/ata/pata_imx.c
--- linux-libre-4.9-gnu/drivers/ata/pata_imx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/pata_imx.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,19 +11,26 @@
  *
  * TODO:
  * - dmaengine support
- * - check if timing stuff needed
  */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/blkdev.h>
-#include <scsi/scsi_host.h>
+
 #include <linux/ata.h>
+#include <linux/clk.h>
 #include <linux/libata.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/clk.h>
 
 #define DRV_NAME "pata_imx"
 
+#define PATA_IMX_ATA_TIME_OFF		0x00
+#define PATA_IMX_ATA_TIME_ON		0x01
+#define PATA_IMX_ATA_TIME_1		0x02
+#define PATA_IMX_ATA_TIME_2W		0x03
+#define PATA_IMX_ATA_TIME_2R		0x04
+#define PATA_IMX_ATA_TIME_AX		0x05
+#define PATA_IMX_ATA_TIME_PIO_RDX	0x06
+#define PATA_IMX_ATA_TIME_4		0x07
+#define PATA_IMX_ATA_TIME_9		0x08
+
 #define PATA_IMX_ATA_CONTROL		0x24
 #define PATA_IMX_ATA_CTRL_FIFO_RST_B	(1<<7)
 #define PATA_IMX_ATA_CTRL_ATA_RST_B	(1<<6)
@@ -33,6 +40,10 @@
 #define PATA_IMX_DRIVE_DATA		0xA0
 #define PATA_IMX_DRIVE_CONTROL		0xD8
 
+static u32 pio_t4[] = { 30,  20,  15,  10,  10 };
+static u32 pio_t9[] = { 20,  15,  10,  10,  10 };
+static u32 pio_tA[] = { 35,  35,  35,  35,  35 };
+
 struct pata_imx_priv {
 	struct clk *clk;
 	/* timings/interrupt/control regs */
@@ -40,28 +51,49 @@ struct pata_imx_priv {
 	u32 ata_ctl;
 };
 
-static int pata_imx_set_mode(struct ata_link *link, struct ata_device **unused)
+static void pata_imx_set_timing(struct ata_device *adev,
+				struct pata_imx_priv *priv)
+{
+	struct ata_timing timing;
+	unsigned long clkrate;
+	u32 T, mode;
+
+	clkrate = clk_get_rate(priv->clk);
+
+	if (adev->pio_mode < XFER_PIO_0 || adev->pio_mode > XFER_PIO_4 ||
+	    !clkrate)
+		return;
+
+	T = 1000000000 / clkrate;
+	ata_timing_compute(adev, adev->pio_mode, &timing, T * 1000, 0);
+
+	mode = adev->pio_mode - XFER_PIO_0;
+
+	writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_OFF);
+	writeb(3, priv->host_regs + PATA_IMX_ATA_TIME_ON);
+	writeb(timing.setup, priv->host_regs + PATA_IMX_ATA_TIME_1);
+	writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2W);
+	writeb(timing.act8b, priv->host_regs + PATA_IMX_ATA_TIME_2R);
+	writeb(1, priv->host_regs + PATA_IMX_ATA_TIME_PIO_RDX);
+
+	writeb(pio_t4[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_4);
+	writeb(pio_t9[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_9);
+	writeb(pio_tA[mode] / T + 1, priv->host_regs + PATA_IMX_ATA_TIME_AX);
+}
+
+static void pata_imx_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	struct ata_device *dev;
-	struct ata_port *ap = link->ap;
 	struct pata_imx_priv *priv = ap->host->private_data;
 	u32 val;
 
-	ata_for_each_dev(dev, link, ENABLED) {
-		dev->pio_mode = dev->xfer_mode = XFER_PIO_0;
-		dev->xfer_shift = ATA_SHIFT_PIO;
-		dev->flags |= ATA_DFLAG_PIO;
-
-		val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL);
-		if (ata_pio_need_iordy(dev))
-			val |= PATA_IMX_ATA_CTRL_IORDY_EN;
-		else
-			val &= ~PATA_IMX_ATA_CTRL_IORDY_EN;
-		__raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL);
+	pata_imx_set_timing(adev, priv);
 
-		ata_dev_info(dev, "configured for PIO\n");
-	}
-	return 0;
+	val = __raw_readl(priv->host_regs + PATA_IMX_ATA_CONTROL);
+	if (ata_pio_need_iordy(adev))
+		val |= PATA_IMX_ATA_CTRL_IORDY_EN;
+	else
+		val &= ~PATA_IMX_ATA_CTRL_IORDY_EN;
+	__raw_writel(val, priv->host_regs + PATA_IMX_ATA_CONTROL);
 }
 
 static struct scsi_host_template pata_imx_sht = {
@@ -72,7 +104,7 @@ static struct ata_port_operations pata_i
 	.inherits		= &ata_sff_port_ops,
 	.sff_data_xfer		= ata_sff_data_xfer_noirq,
 	.cable_detect		= ata_cable_unknown,
-	.set_mode		= pata_imx_set_mode,
+	.set_piomode		= pata_imx_set_piomode,
 };
 
 static void pata_imx_setup_port(struct ata_ioports *ioaddr)
@@ -128,7 +160,7 @@ static int pata_imx_probe(struct platfor
 	ap = host->ports[0];
 
 	ap->ops = &pata_imx_port_ops;
-	ap->pio_mask = ATA_PIO0;
+	ap->pio_mask = ATA_PIO4;
 	ap->flags |= ATA_FLAG_SLAVE_POSS;
 
 	io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ata/sata_mv.c linux-libre-4.10-rc8-gnu/drivers/ata/sata_mv.c
--- linux-libre-4.9-gnu/drivers/ata/sata_mv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ata/sata_mv.c	2017-02-12 16:03:20.000000000 -0500
@@ -4132,6 +4132,9 @@ static int mv_platform_probe(struct plat
 	host->iomap = NULL;
 	hpriv->base = devm_ioremap(&pdev->dev, res->start,
 				   resource_size(res));
+	if (!hpriv->base)
+		return -ENOMEM;
+
 	hpriv->base -= SATAHC0_REG_BASE;
 
 	hpriv->clk = clk_get(&pdev->dev, NULL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/adummy.c linux-libre-4.10-rc8-gnu/drivers/atm/adummy.c
--- linux-libre-4.9-gnu/drivers/atm/adummy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/adummy.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/atmdev.h>
 #include <linux/atm.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/atmtcp.c linux-libre-4.10-rc8-gnu/drivers/atm/atmtcp.c
--- linux-libre-4.9-gnu/drivers/atm/atmtcp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/atmtcp.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/bitops.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/eni.c linux-libre-4.10-rc8-gnu/drivers/atm/eni.c
--- linux-libre-4.9-gnu/drivers/atm/eni.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/eni.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/firestream.c linux-libre-4.10-rc8-gnu/drivers/atm/firestream.c
--- linux-libre-4.9-gnu/drivers/atm/firestream.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/firestream.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@
 #include <asm/string.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/wait.h>
 
 #include "firestream.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/fore200e.c linux-libre-4.10-rc8-gnu/drivers/atm/fore200e.c
--- linux-libre-4.9-gnu/drivers/atm/fore200e.c	2016-12-11 17:40:23.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/fore200e.c	2017-02-12 17:22:41.000000000 -0500
@@ -43,7 +43,7 @@
 #include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
 
 #ifdef CONFIG_SBUS
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/he.c linux-libre-4.10-rc8-gnu/drivers/atm/he.c
--- linux-libre-4.9-gnu/drivers/atm/he.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/he.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,7 @@
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/atmdev.h>
 #include <linux/atm.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/horizon.c linux-libre-4.10-rc8-gnu/drivers/atm/horizon.c
--- linux-libre-4.9-gnu/drivers/atm/horizon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/horizon.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
 
 #include <asm/io.h>
 #include <linux/atomic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/string.h>
 #include <asm/byteorder.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/idt77105.c linux-libre-4.10-rc8-gnu/drivers/atm/idt77105.c
--- linux-libre-4.9-gnu/drivers/atm/idt77105.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/idt77105.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <asm/param.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "idt77105.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/idt77252.c linux-libre-4.10-rc8-gnu/drivers/atm/idt77252.c
--- linux-libre-4.9-gnu/drivers/atm/idt77252.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/idt77252.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
 #include <asm/byteorder.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/iphase.c linux-libre-4.10-rc8-gnu/drivers/atm/iphase.c
--- linux-libre-4.9-gnu/drivers/atm/iphase.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/iphase.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,7 @@
 #include <linux/slab.h>
 #include <asm/io.h>  
 #include <linux/atomic.h>
-#include <asm/uaccess.h>  
+#include <linux/uaccess.h>  
 #include <asm/string.h>  
 #include <asm/byteorder.h>  
 #include <linux/vmalloc.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/nicstar.c linux-libre-4.10-rc8-gnu/drivers/atm/nicstar.c
--- linux-libre-4.9-gnu/drivers/atm/nicstar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/nicstar.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,7 +50,7 @@
 #include <linux/slab.h>
 #include <linux/idr.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
 #include <linux/etherdevice.h>
 #include "nicstar.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/solos-pci.c linux-libre-4.10-rc8-gnu/drivers/atm/solos-pci.c
--- linux-libre-4.9-gnu/drivers/atm/solos-pci.c	2016-12-11 17:40:33.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/solos-pci.c	2017-02-12 17:22:58.000000000 -0500
@@ -582,7 +582,7 @@ static ssize_t hardware_show(struct devi
 	return sprintf(buf, "%d\n", data32);
 }
 
-static DEVICE_ATTR(console, 0644, console_show, console_store);
+static DEVICE_ATTR_RW(console);
 
 
 #define SOLOS_ATTR_RO(x) static DEVICE_ATTR(x, 0444, solos_param_show, NULL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/suni.c linux-libre-4.10-rc8-gnu/drivers/atm/suni.c
--- linux-libre-4.9-gnu/drivers/atm/suni.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/suni.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/atm_suni.h>
 #include <linux/slab.h>
 #include <asm/param.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
 
 #include "suni.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/uPD98402.c linux-libre-4.10-rc8-gnu/drivers/atm/uPD98402.c
--- linux-libre-4.9-gnu/drivers/atm/uPD98402.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/uPD98402.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@
 #include <linux/sonet.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/atomic.h>
 
 #include "uPD98402.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/atm/zatm.c linux-libre-4.10-rc8-gnu/drivers/atm/zatm.c
--- linux-libre-4.9-gnu/drivers/atm/zatm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/atm/zatm.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <asm/string.h>
 #include <asm/io.h>
 #include <linux/atomic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "uPD98401.h"
 #include "uPD98402.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/auxdisplay/ht16k33.c linux-libre-4.10-rc8-gnu/drivers/auxdisplay/ht16k33.c
--- linux-libre-4.9-gnu/drivers/auxdisplay/ht16k33.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/auxdisplay/ht16k33.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,563 @@
+/*
+ * HT16K33 driver
+ *
+ * Author: Robin van der Gracht <robin@protonic.nl>
+ *
+ * Copyright: (C) 2016 Protonic Holland.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/fb.h>
+#include <linux/slab.h>
+#include <linux/backlight.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/workqueue.h>
+#include <linux/mm.h>
+
+/* Registers */
+#define REG_SYSTEM_SETUP		0x20
+#define REG_SYSTEM_SETUP_OSC_ON		BIT(0)
+
+#define REG_DISPLAY_SETUP		0x80
+#define REG_DISPLAY_SETUP_ON		BIT(0)
+
+#define REG_ROWINT_SET			0xA0
+#define REG_ROWINT_SET_INT_EN		BIT(0)
+#define REG_ROWINT_SET_INT_ACT_HIGH	BIT(1)
+
+#define REG_BRIGHTNESS			0xE0
+
+/* Defines */
+#define DRIVER_NAME			"ht16k33"
+
+#define MIN_BRIGHTNESS			0x1
+#define MAX_BRIGHTNESS			0x10
+
+#define HT16K33_MATRIX_LED_MAX_COLS	8
+#define HT16K33_MATRIX_LED_MAX_ROWS	16
+#define HT16K33_MATRIX_KEYPAD_MAX_COLS	3
+#define HT16K33_MATRIX_KEYPAD_MAX_ROWS	12
+
+#define BYTES_PER_ROW		(HT16K33_MATRIX_LED_MAX_ROWS / 8)
+#define HT16K33_FB_SIZE		(HT16K33_MATRIX_LED_MAX_COLS * BYTES_PER_ROW)
+
+struct ht16k33_keypad {
+	struct input_dev *dev;
+	spinlock_t lock;
+	struct delayed_work work;
+	uint32_t cols;
+	uint32_t rows;
+	uint32_t row_shift;
+	uint32_t debounce_ms;
+	uint16_t last_key_state[HT16K33_MATRIX_KEYPAD_MAX_COLS];
+};
+
+struct ht16k33_fbdev {
+	struct fb_info *info;
+	uint32_t refresh_rate;
+	uint8_t *buffer;
+	uint8_t *cache;
+	struct delayed_work work;
+};
+
+struct ht16k33_priv {
+	struct i2c_client *client;
+	struct ht16k33_keypad keypad;
+	struct ht16k33_fbdev fbdev;
+	struct workqueue_struct *workqueue;
+};
+
+static struct fb_fix_screeninfo ht16k33_fb_fix = {
+	.id		= DRIVER_NAME,
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_MONO10,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.line_length	= HT16K33_MATRIX_LED_MAX_ROWS,
+	.accel		= FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo ht16k33_fb_var = {
+	.xres = HT16K33_MATRIX_LED_MAX_ROWS,
+	.yres = HT16K33_MATRIX_LED_MAX_COLS,
+	.xres_virtual = HT16K33_MATRIX_LED_MAX_ROWS,
+	.yres_virtual = HT16K33_MATRIX_LED_MAX_COLS,
+	.bits_per_pixel = 1,
+	.red = { 0, 1, 0 },
+	.green = { 0, 1, 0 },
+	.blue = { 0, 1, 0 },
+	.left_margin = 0,
+	.right_margin = 0,
+	.upper_margin = 0,
+	.lower_margin = 0,
+	.vmode = FB_VMODE_NONINTERLACED,
+};
+
+static int ht16k33_display_on(struct ht16k33_priv *priv)
+{
+	uint8_t data = REG_DISPLAY_SETUP | REG_DISPLAY_SETUP_ON;
+
+	return i2c_smbus_write_byte(priv->client, data);
+}
+
+static int ht16k33_display_off(struct ht16k33_priv *priv)
+{
+	return i2c_smbus_write_byte(priv->client, REG_DISPLAY_SETUP);
+}
+
+static void ht16k33_fb_queue(struct ht16k33_priv *priv)
+{
+	struct ht16k33_fbdev *fbdev = &priv->fbdev;
+
+	queue_delayed_work(priv->workqueue, &fbdev->work,
+		msecs_to_jiffies(HZ / fbdev->refresh_rate));
+}
+
+static void ht16k33_keypad_queue(struct ht16k33_priv *priv)
+{
+	struct ht16k33_keypad *keypad = &priv->keypad;
+
+	queue_delayed_work(priv->workqueue, &keypad->work,
+		msecs_to_jiffies(keypad->debounce_ms));
+}
+
+/*
+ * This gets the fb data from cache and copies it to ht16k33 display RAM
+ */
+static void ht16k33_fb_update(struct work_struct *work)
+{
+	struct ht16k33_fbdev *fbdev =
+		container_of(work, struct ht16k33_fbdev, work.work);
+	struct ht16k33_priv *priv =
+		container_of(fbdev, struct ht16k33_priv, fbdev);
+
+	uint8_t *p1, *p2;
+	int len, pos = 0, first = -1;
+
+	p1 = fbdev->cache;
+	p2 = fbdev->buffer;
+
+	/* Search for the first byte with changes */
+	while (pos < HT16K33_FB_SIZE && first < 0) {
+		if (*(p1++) - *(p2++))
+			first = pos;
+		pos++;
+	}
+
+	/* No changes found */
+	if (first < 0)
+		goto requeue;
+
+	len = HT16K33_FB_SIZE - first;
+	p1 = fbdev->cache + HT16K33_FB_SIZE - 1;
+	p2 = fbdev->buffer + HT16K33_FB_SIZE - 1;
+
+	/* Determine i2c transfer length */
+	while (len > 1) {
+		if (*(p1--) - *(p2--))
+			break;
+		len--;
+	}
+
+	p1 = fbdev->cache + first;
+	p2 = fbdev->buffer + first;
+	if (!i2c_smbus_write_i2c_block_data(priv->client, first, len, p2))
+		memcpy(p1, p2, len);
+requeue:
+	ht16k33_fb_queue(priv);
+}
+
+static int ht16k33_keypad_start(struct input_dev *dev)
+{
+	struct ht16k33_priv *priv = input_get_drvdata(dev);
+	struct ht16k33_keypad *keypad = &priv->keypad;
+
+	/*
+	 * Schedule an immediate key scan to capture current key state;
+	 * columns will be activated and IRQs be enabled after the scan.
+	 */
+	queue_delayed_work(priv->workqueue, &keypad->work, 0);
+	return 0;
+}
+
+static void ht16k33_keypad_stop(struct input_dev *dev)
+{
+	struct ht16k33_priv *priv = input_get_drvdata(dev);
+	struct ht16k33_keypad *keypad = &priv->keypad;
+
+	cancel_delayed_work(&keypad->work);
+	/*
+	 * ht16k33_keypad_scan() will leave IRQs enabled;
+	 * we should disable them now.
+	 */
+	disable_irq_nosync(priv->client->irq);
+}
+
+static int ht16k33_initialize(struct ht16k33_priv *priv)
+{
+	uint8_t byte;
+	int err;
+	uint8_t data[HT16K33_MATRIX_LED_MAX_COLS * 2];
+
+	/* Clear RAM (8 * 16 bits) */
+	memset(data, 0, sizeof(data));
+	err = i2c_smbus_write_block_data(priv->client, 0, sizeof(data), data);
+	if (err)
+		return err;
+
+	/* Turn on internal oscillator */
+	byte = REG_SYSTEM_SETUP_OSC_ON | REG_SYSTEM_SETUP;
+	err = i2c_smbus_write_byte(priv->client, byte);
+	if (err)
+		return err;
+
+	/* Configure INT pin */
+	byte = REG_ROWINT_SET | REG_ROWINT_SET_INT_ACT_HIGH;
+	if (priv->client->irq > 0)
+		byte |= REG_ROWINT_SET_INT_EN;
+	return i2c_smbus_write_byte(priv->client, byte);
+}
+
+/*
+ * This gets the keys from keypad and reports it to input subsystem
+ */
+static void ht16k33_keypad_scan(struct work_struct *work)
+{
+	struct ht16k33_keypad *keypad =
+		container_of(work, struct ht16k33_keypad, work.work);
+	struct ht16k33_priv *priv =
+		container_of(keypad, struct ht16k33_priv, keypad);
+	const unsigned short *keycodes = keypad->dev->keycode;
+	uint16_t bits_changed, new_state[HT16K33_MATRIX_KEYPAD_MAX_COLS];
+	uint8_t data[HT16K33_MATRIX_KEYPAD_MAX_COLS * 2];
+	int row, col, code;
+	bool reschedule = false;
+
+	if (i2c_smbus_read_i2c_block_data(priv->client, 0x40, 6, data) != 6) {
+		dev_err(&priv->client->dev, "Failed to read key data\n");
+		goto end;
+	}
+
+	for (col = 0; col < keypad->cols; col++) {
+		new_state[col] = (data[col * 2 + 1] << 8) | data[col * 2];
+		if (new_state[col])
+			reschedule = true;
+		bits_changed = keypad->last_key_state[col] ^ new_state[col];
+
+		while (bits_changed) {
+			row = ffs(bits_changed) - 1;
+			code = MATRIX_SCAN_CODE(row, col, keypad->row_shift);
+			input_event(keypad->dev, EV_MSC, MSC_SCAN, code);
+			input_report_key(keypad->dev, keycodes[code],
+					 new_state[col] & BIT(row));
+			bits_changed &= ~BIT(row);
+		}
+	}
+	input_sync(keypad->dev);
+	memcpy(keypad->last_key_state, new_state, sizeof(new_state));
+
+end:
+	if (reschedule)
+		ht16k33_keypad_queue(priv);
+	else
+		enable_irq(priv->client->irq);
+}
+
+static irqreturn_t ht16k33_irq_thread(int irq, void *dev)
+{
+	struct ht16k33_priv *priv = dev;
+
+	disable_irq_nosync(priv->client->irq);
+	ht16k33_keypad_queue(priv);
+
+	return IRQ_HANDLED;
+}
+
+static int ht16k33_bl_update_status(struct backlight_device *bl)
+{
+	int brightness = bl->props.brightness;
+	struct ht16k33_priv *priv = bl_get_data(bl);
+
+	if (bl->props.power != FB_BLANK_UNBLANK ||
+	    bl->props.fb_blank != FB_BLANK_UNBLANK ||
+	    bl->props.state & BL_CORE_FBBLANK || brightness == 0) {
+		return ht16k33_display_off(priv);
+	}
+
+	ht16k33_display_on(priv);
+	return i2c_smbus_write_byte(priv->client,
+				    REG_BRIGHTNESS | (brightness - 1));
+}
+
+static int ht16k33_bl_check_fb(struct backlight_device *bl, struct fb_info *fi)
+{
+	struct ht16k33_priv *priv = bl_get_data(bl);
+
+	return (fi == NULL) || (fi->par == priv);
+}
+
+static const struct backlight_ops ht16k33_bl_ops = {
+	.update_status	= ht16k33_bl_update_status,
+	.check_fb	= ht16k33_bl_check_fb,
+};
+
+static int ht16k33_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct ht16k33_priv *priv = info->par;
+
+	return vm_insert_page(vma, vma->vm_start,
+			      virt_to_page(priv->fbdev.buffer));
+}
+
+static struct fb_ops ht16k33_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_read = fb_sys_read,
+	.fb_write = fb_sys_write,
+	.fb_fillrect = sys_fillrect,
+	.fb_copyarea = sys_copyarea,
+	.fb_imageblit = sys_imageblit,
+	.fb_mmap = ht16k33_mmap,
+};
+
+static int ht16k33_probe(struct i2c_client *client,
+				  const struct i2c_device_id *id)
+{
+	int err;
+	uint32_t rows, cols, dft_brightness;
+	struct backlight_device *bl;
+	struct backlight_properties bl_props;
+	struct ht16k33_priv *priv;
+	struct ht16k33_keypad *keypad;
+	struct ht16k33_fbdev *fbdev;
+	struct device_node *node = client->dev.of_node;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "i2c_check_functionality error\n");
+		return -EIO;
+	}
+
+	if (client->irq <= 0) {
+		dev_err(&client->dev, "No IRQ specified\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client = client;
+	i2c_set_clientdata(client, priv);
+	fbdev = &priv->fbdev;
+	keypad = &priv->keypad;
+
+	priv->workqueue = create_singlethread_workqueue(DRIVER_NAME "-wq");
+	if (priv->workqueue == NULL)
+		return -ENOMEM;
+
+	err = ht16k33_initialize(priv);
+	if (err)
+		goto err_destroy_wq;
+
+	/* Framebuffer (2 bytes per column) */
+	BUILD_BUG_ON(PAGE_SIZE < HT16K33_FB_SIZE);
+	fbdev->buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
+	if (!fbdev->buffer) {
+		err = -ENOMEM;
+		goto err_free_fbdev;
+	}
+
+	fbdev->cache = devm_kmalloc(&client->dev, HT16K33_FB_SIZE, GFP_KERNEL);
+	if (!fbdev->cache) {
+		err = -ENOMEM;
+		goto err_fbdev_buffer;
+	}
+
+	fbdev->info = framebuffer_alloc(0, &client->dev);
+	if (!fbdev->info) {
+		err = -ENOMEM;
+		goto err_fbdev_buffer;
+	}
+
+	err = of_property_read_u32(node, "refresh-rate-hz",
+		&fbdev->refresh_rate);
+	if (err) {
+		dev_err(&client->dev, "refresh rate not specified\n");
+		goto err_fbdev_info;
+	}
+	fb_bl_default_curve(fbdev->info, 0, MIN_BRIGHTNESS, MAX_BRIGHTNESS);
+
+	INIT_DELAYED_WORK(&fbdev->work, ht16k33_fb_update);
+	fbdev->info->fbops = &ht16k33_fb_ops;
+	fbdev->info->screen_base = (char __iomem *) fbdev->buffer;
+	fbdev->info->screen_size = HT16K33_FB_SIZE;
+	fbdev->info->fix = ht16k33_fb_fix;
+	fbdev->info->var = ht16k33_fb_var;
+	fbdev->info->pseudo_palette = NULL;
+	fbdev->info->flags = FBINFO_FLAG_DEFAULT;
+	fbdev->info->par = priv;
+
+	err = register_framebuffer(fbdev->info);
+	if (err)
+		goto err_fbdev_info;
+
+	/* Keypad */
+	keypad->dev = devm_input_allocate_device(&client->dev);
+	if (!keypad->dev) {
+		err = -ENOMEM;
+		goto err_fbdev_unregister;
+	}
+
+	keypad->dev->name = DRIVER_NAME"-keypad";
+	keypad->dev->id.bustype = BUS_I2C;
+	keypad->dev->open = ht16k33_keypad_start;
+	keypad->dev->close = ht16k33_keypad_stop;
+
+	if (!of_get_property(node, "linux,no-autorepeat", NULL))
+		__set_bit(EV_REP, keypad->dev->evbit);
+
+	err = of_property_read_u32(node, "debounce-delay-ms",
+				   &keypad->debounce_ms);
+	if (err) {
+		dev_err(&client->dev, "key debounce delay not specified\n");
+		goto err_fbdev_unregister;
+	}
+
+	err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+					ht16k33_irq_thread,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+					DRIVER_NAME, priv);
+	if (err) {
+		dev_err(&client->dev, "irq request failed %d, error %d\n",
+			client->irq, err);
+		goto err_fbdev_unregister;
+	}
+
+	disable_irq_nosync(client->irq);
+	rows = HT16K33_MATRIX_KEYPAD_MAX_ROWS;
+	cols = HT16K33_MATRIX_KEYPAD_MAX_COLS;
+	err = matrix_keypad_parse_of_params(&client->dev, &rows, &cols);
+	if (err)
+		goto err_fbdev_unregister;
+
+	err = matrix_keypad_build_keymap(NULL, NULL, rows, cols, NULL,
+					 keypad->dev);
+	if (err) {
+		dev_err(&client->dev, "failed to build keymap\n");
+		goto err_fbdev_unregister;
+	}
+
+	input_set_drvdata(keypad->dev, priv);
+	keypad->rows = rows;
+	keypad->cols = cols;
+	keypad->row_shift = get_count_order(cols);
+	INIT_DELAYED_WORK(&keypad->work, ht16k33_keypad_scan);
+
+	err = input_register_device(keypad->dev);
+	if (err)
+		goto err_fbdev_unregister;
+
+	/* Backlight */
+	memset(&bl_props, 0, sizeof(struct backlight_properties));
+	bl_props.type = BACKLIGHT_RAW;
+	bl_props.max_brightness = MAX_BRIGHTNESS;
+
+	bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl",
+					    &client->dev, priv,
+					    &ht16k33_bl_ops, &bl_props);
+	if (IS_ERR(bl)) {
+		dev_err(&client->dev, "failed to register backlight\n");
+		err = PTR_ERR(bl);
+		goto err_keypad_unregister;
+	}
+
+	err = of_property_read_u32(node, "default-brightness-level",
+				   &dft_brightness);
+	if (err) {
+		dft_brightness = MAX_BRIGHTNESS;
+	} else if (dft_brightness > MAX_BRIGHTNESS) {
+		dev_warn(&client->dev,
+			 "invalid default brightness level: %u, using %u\n",
+			 dft_brightness, MAX_BRIGHTNESS);
+		dft_brightness = MAX_BRIGHTNESS;
+	}
+
+	bl->props.brightness = dft_brightness;
+	ht16k33_bl_update_status(bl);
+
+	ht16k33_fb_queue(priv);
+	return 0;
+
+err_keypad_unregister:
+	input_unregister_device(keypad->dev);
+err_fbdev_unregister:
+	unregister_framebuffer(fbdev->info);
+err_fbdev_info:
+	framebuffer_release(fbdev->info);
+err_fbdev_buffer:
+	free_page((unsigned long) fbdev->buffer);
+err_free_fbdev:
+	kfree(fbdev);
+err_destroy_wq:
+	destroy_workqueue(priv->workqueue);
+
+	return err;
+}
+
+static int ht16k33_remove(struct i2c_client *client)
+{
+	struct ht16k33_priv *priv = i2c_get_clientdata(client);
+	struct ht16k33_keypad *keypad = &priv->keypad;
+	struct ht16k33_fbdev *fbdev = &priv->fbdev;
+
+	ht16k33_keypad_stop(keypad->dev);
+
+	cancel_delayed_work(&fbdev->work);
+	unregister_framebuffer(fbdev->info);
+	framebuffer_release(fbdev->info);
+	free_page((unsigned long) fbdev->buffer);
+
+	destroy_workqueue(priv->workqueue);
+	return 0;
+}
+
+static const struct i2c_device_id ht16k33_i2c_match[] = {
+	{ "ht16k33", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ht16k33_i2c_match);
+
+static const struct of_device_id ht16k33_of_match[] = {
+	{ .compatible = "holtek,ht16k33", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ht16k33_of_match);
+
+static struct i2c_driver ht16k33_driver = {
+	.probe		= ht16k33_probe,
+	.remove		= ht16k33_remove,
+	.driver		= {
+		.name		= DRIVER_NAME,
+		.of_match_table	= of_match_ptr(ht16k33_of_match),
+	},
+	.id_table = ht16k33_i2c_match,
+};
+module_i2c_driver(ht16k33_driver);
+
+MODULE_DESCRIPTION("Holtek HT16K33 driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robin van der Gracht <robin@protonic.nl>");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/auxdisplay/Kconfig linux-libre-4.10-rc8-gnu/drivers/auxdisplay/Kconfig
--- linux-libre-4.9-gnu/drivers/auxdisplay/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/auxdisplay/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -128,4 +128,17 @@ config IMG_ASCII_LCD
 	  development boards such as the MIPS Boston, MIPS Malta & MIPS SEAD3
 	  from Imagination Technologies.
 
+config HT16K33
+	tristate "Holtek Ht16K33 LED controller with keyscan"
+	depends on FB && OF && I2C && INPUT
+	select FB_SYS_FOPS
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select INPUT_MATRIXKMAP
+	select FB_BACKLIGHT
+	help
+	  Say yes here to add support for Holtek HT16K33, RAM mapping 16*8
+	  LED controller driver with keyscan.
+
 endif # AUXDISPLAY
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/auxdisplay/Makefile linux-libre-4.10-rc8-gnu/drivers/auxdisplay/Makefile
--- linux-libre-4.9-gnu/drivers/auxdisplay/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/auxdisplay/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -5,3 +5,4 @@
 obj-$(CONFIG_KS0108)		+= ks0108.o
 obj-$(CONFIG_CFAG12864B)	+= cfag12864b.o cfag12864bfb.o
 obj-$(CONFIG_IMG_ASCII_LCD)	+= img-ascii-lcd.o
+obj-$(CONFIG_HT16K33)		+= ht16k33.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/base.h linux-libre-4.10-rc8-gnu/drivers/base/base.h
--- linux-libre-4.9-gnu/drivers/base/base.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/base.h	2017-02-12 16:03:20.000000000 -0500
@@ -107,6 +107,9 @@ extern void bus_remove_device(struct dev
 
 extern int bus_add_driver(struct device_driver *drv);
 extern void bus_remove_driver(struct device_driver *drv);
+extern void device_release_driver_internal(struct device *dev,
+					   struct device_driver *drv,
+					   struct device *parent);
 
 extern void driver_detach(struct device_driver *drv);
 extern int driver_probe_device(struct device_driver *drv, struct device *dev);
@@ -152,3 +155,13 @@ extern int devtmpfs_init(void);
 #else
 static inline int devtmpfs_init(void) { return 0; }
 #endif
+
+/* Device links support */
+extern int device_links_read_lock(void);
+extern void device_links_read_unlock(int idx);
+extern int device_links_check_suppliers(struct device *dev);
+extern void device_links_driver_bound(struct device *dev);
+extern void device_links_driver_cleanup(struct device *dev);
+extern void device_links_no_driver(struct device *dev);
+extern bool device_links_busy(struct device *dev);
+extern void device_links_unbind_consumers(struct device *dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/cacheinfo.c linux-libre-4.10-rc8-gnu/drivers/base/cacheinfo.c
--- linux-libre-4.9-gnu/drivers/base/cacheinfo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/cacheinfo.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,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 <linux/acpi.h>
 #include <linux/bitops.h>
 #include <linux/cacheinfo.h>
 #include <linux/compiler.h>
@@ -85,7 +88,120 @@ static inline bool cache_leaves_are_shar
 {
 	return sib_leaf->of_node == this_leaf->of_node;
 }
+
+/* OF properties to query for a given cache type */
+struct cache_type_info {
+	const char *size_prop;
+	const char *line_size_props[2];
+	const char *nr_sets_prop;
+};
+
+static const struct cache_type_info cache_type_info[] = {
+	{
+		.size_prop       = "cache-size",
+		.line_size_props = { "cache-line-size",
+				     "cache-block-size", },
+		.nr_sets_prop    = "cache-sets",
+	}, {
+		.size_prop       = "i-cache-size",
+		.line_size_props = { "i-cache-line-size",
+				     "i-cache-block-size", },
+		.nr_sets_prop    = "i-cache-sets",
+	}, {
+		.size_prop       = "d-cache-size",
+		.line_size_props = { "d-cache-line-size",
+				     "d-cache-block-size", },
+		.nr_sets_prop    = "d-cache-sets",
+	},
+};
+
+static inline int get_cacheinfo_idx(enum cache_type type)
+{
+	if (type == CACHE_TYPE_UNIFIED)
+		return 0;
+	return type;
+}
+
+static void cache_size(struct cacheinfo *this_leaf)
+{
+	const char *propname;
+	const __be32 *cache_size;
+	int ct_idx;
+
+	ct_idx = get_cacheinfo_idx(this_leaf->type);
+	propname = cache_type_info[ct_idx].size_prop;
+
+	cache_size = of_get_property(this_leaf->of_node, propname, NULL);
+	if (cache_size)
+		this_leaf->size = of_read_number(cache_size, 1);
+}
+
+/* not cache_line_size() because that's a macro in include/linux/cache.h */
+static void cache_get_line_size(struct cacheinfo *this_leaf)
+{
+	const __be32 *line_size;
+	int i, lim, ct_idx;
+
+	ct_idx = get_cacheinfo_idx(this_leaf->type);
+	lim = ARRAY_SIZE(cache_type_info[ct_idx].line_size_props);
+
+	for (i = 0; i < lim; i++) {
+		const char *propname;
+
+		propname = cache_type_info[ct_idx].line_size_props[i];
+		line_size = of_get_property(this_leaf->of_node, propname, NULL);
+		if (line_size)
+			break;
+	}
+
+	if (line_size)
+		this_leaf->coherency_line_size = of_read_number(line_size, 1);
+}
+
+static void cache_nr_sets(struct cacheinfo *this_leaf)
+{
+	const char *propname;
+	const __be32 *nr_sets;
+	int ct_idx;
+
+	ct_idx = get_cacheinfo_idx(this_leaf->type);
+	propname = cache_type_info[ct_idx].nr_sets_prop;
+
+	nr_sets = of_get_property(this_leaf->of_node, propname, NULL);
+	if (nr_sets)
+		this_leaf->number_of_sets = of_read_number(nr_sets, 1);
+}
+
+static void cache_associativity(struct cacheinfo *this_leaf)
+{
+	unsigned int line_size = this_leaf->coherency_line_size;
+	unsigned int nr_sets = this_leaf->number_of_sets;
+	unsigned int size = this_leaf->size;
+
+	/*
+	 * If the cache is fully associative, there is no need to
+	 * check the other properties.
+	 */
+	if (!(nr_sets == 1) && (nr_sets > 0 && size > 0 && line_size > 0))
+		this_leaf->ways_of_associativity = (size / nr_sets) / line_size;
+}
+
+static void cache_of_override_properties(unsigned int cpu)
+{
+	int index;
+	struct cacheinfo *this_leaf;
+	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+
+	for (index = 0; index < cache_leaves(cpu); index++) {
+		this_leaf = this_cpu_ci->info_list + index;
+		cache_size(this_leaf);
+		cache_get_line_size(this_leaf);
+		cache_nr_sets(this_leaf);
+		cache_associativity(this_leaf);
+	}
+}
 #else
+static void cache_of_override_properties(unsigned int cpu) { }
 static inline int cache_setup_of_node(unsigned int cpu) { return 0; }
 static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf,
 					   struct cacheinfo *sib_leaf)
@@ -104,9 +220,16 @@ static int cache_shared_cpu_map_setup(un
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 	struct cacheinfo *this_leaf, *sib_leaf;
 	unsigned int index;
-	int ret;
+	int ret = 0;
 
-	ret = cache_setup_of_node(cpu);
+	if (this_cpu_ci->cpu_map_populated)
+		return 0;
+
+	if (of_have_populated_dt())
+		ret = cache_setup_of_node(cpu);
+	else if (!acpi_disabled)
+		/* No cache property/hierarchy support yet in ACPI */
+		ret = -ENOTSUPP;
 	if (ret)
 		return ret;
 
@@ -161,6 +284,12 @@ static void cache_shared_cpu_map_remove(
 	}
 }
 
+static void cache_override_properties(unsigned int cpu)
+{
+	if (of_have_populated_dt())
+		return cache_of_override_properties(cpu);
+}
+
 static void free_cache_attributes(unsigned int cpu)
 {
 	if (!per_cpu_cacheinfo(cpu))
@@ -203,10 +332,11 @@ static int detect_cache_attributes(unsig
 	 */
 	ret = cache_shared_cpu_map_setup(cpu);
 	if (ret) {
-		pr_warn("Unable to detect cache hierarchy from DT for CPU %d\n",
-			cpu);
+		pr_warn("Unable to detect cache hierarchy for CPU %d\n", cpu);
 		goto free_ci;
 	}
+
+	cache_override_properties(cpu);
 	return 0;
 
 free_ci:
@@ -233,6 +363,7 @@ static ssize_t file_name##_show(struct d
 	return sprintf(buf, "%u\n", this_leaf->object);		\
 }
 
+show_one(id, id);
 show_one(level, level);
 show_one(coherency_line_size, coherency_line_size);
 show_one(number_of_sets, number_of_sets);
@@ -314,6 +445,7 @@ static ssize_t write_policy_show(struct
 	return n;
 }
 
+static DEVICE_ATTR_RO(id);
 static DEVICE_ATTR_RO(level);
 static DEVICE_ATTR_RO(type);
 static DEVICE_ATTR_RO(coherency_line_size);
@@ -327,6 +459,7 @@ static DEVICE_ATTR_RO(shared_cpu_list);
 static DEVICE_ATTR_RO(physical_line_partition);
 
 static struct attribute *cache_default_attrs[] = {
+	&dev_attr_id.attr,
 	&dev_attr_type.attr,
 	&dev_attr_level.attr,
 	&dev_attr_shared_cpu_map.attr,
@@ -350,6 +483,8 @@ cache_default_attrs_is_visible(struct ko
 	const struct cpumask *mask = &this_leaf->shared_cpu_map;
 	umode_t mode = attr->mode;
 
+	if ((attr == &dev_attr_id.attr) && (this_leaf->attributes & CACHE_ID))
+		return mode;
 	if ((attr == &dev_attr_type.attr) && this_leaf->type)
 		return mode;
 	if ((attr == &dev_attr_level.attr) && this_leaf->level)
@@ -498,57 +633,30 @@ err:
 	return rc;
 }
 
-static void cache_remove_dev(unsigned int cpu)
+static int cacheinfo_cpu_online(unsigned int cpu)
 {
-	if (!cpumask_test_cpu(cpu, &cache_dev_map))
-		return;
-	cpumask_clear_cpu(cpu, &cache_dev_map);
+	int rc = detect_cache_attributes(cpu);
 
-	cpu_cache_sysfs_exit(cpu);
+	if (rc)
+		return rc;
+	rc = cache_add_dev(cpu);
+	if (rc)
+		free_cache_attributes(cpu);
+	return rc;
 }
 
-static int cacheinfo_cpu_callback(struct notifier_block *nfb,
-				  unsigned long action, void *hcpu)
+static int cacheinfo_cpu_pre_down(unsigned int cpu)
 {
-	unsigned int cpu = (unsigned long)hcpu;
-	int rc = 0;
+	if (cpumask_test_and_clear_cpu(cpu, &cache_dev_map))
+		cpu_cache_sysfs_exit(cpu);
 
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_ONLINE:
-		rc = detect_cache_attributes(cpu);
-		if (!rc)
-			rc = cache_add_dev(cpu);
-		break;
-	case CPU_DEAD:
-		cache_remove_dev(cpu);
-		free_cache_attributes(cpu);
-		break;
-	}
-	return notifier_from_errno(rc);
+	free_cache_attributes(cpu);
+	return 0;
 }
 
 static int __init cacheinfo_sysfs_init(void)
 {
-	int cpu, rc = 0;
-
-	cpu_notifier_register_begin();
-
-	for_each_online_cpu(cpu) {
-		rc = detect_cache_attributes(cpu);
-		if (rc)
-			goto out;
-		rc = cache_add_dev(cpu);
-		if (rc) {
-			free_cache_attributes(cpu);
-			pr_err("error populating cacheinfo..cpu%d\n", cpu);
-			goto out;
-		}
-	}
-	__hotcpu_notifier(cacheinfo_cpu_callback, 0);
-
-out:
-	cpu_notifier_register_done();
-	return rc;
+	return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "base/cacheinfo:online",
+				 cacheinfo_cpu_online, cacheinfo_cpu_pre_down);
 }
-
 device_initcall(cacheinfo_sysfs_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/class.c linux-libre-4.10-rc8-gnu/drivers/base/class.c
--- linux-libre-4.9-gnu/drivers/base/class.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/class.c	2017-02-12 16:03:20.000000000 -0500
@@ -163,6 +163,18 @@ static void klist_class_dev_put(struct k
 	put_device(dev);
 }
 
+static int class_add_groups(struct class *cls,
+			    const struct attribute_group **groups)
+{
+	return sysfs_create_groups(&cls->p->subsys.kobj, groups);
+}
+
+static void class_remove_groups(struct class *cls,
+				const struct attribute_group **groups)
+{
+	return sysfs_remove_groups(&cls->p->subsys.kobj, groups);
+}
+
 int __class_register(struct class *cls, struct lock_class_key *key)
 {
 	struct subsys_private *cp;
@@ -203,6 +215,8 @@ int __class_register(struct class *cls,
 		kfree(cp);
 		return error;
 	}
+	error = class_add_groups(class_get(cls), cls->class_groups);
+	class_put(cls);
 	error = add_class_attrs(class_get(cls));
 	class_put(cls);
 	return error;
@@ -213,6 +227,7 @@ void class_unregister(struct class *cls)
 {
 	pr_debug("device class '%s': unregistering\n", cls->name);
 	remove_class_attrs(cls);
+	class_remove_groups(cls, cls->class_groups);
 	kset_unregister(&cls->p->subsys);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/core.c linux-libre-4.10-rc8-gnu/drivers/base/core.c
--- linux-libre-4.9-gnu/drivers/base/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,572 @@ static int __init sysfs_deprecated_setup
 early_param("sysfs.deprecated", sysfs_deprecated_setup);
 #endif
 
+/* Device links support. */
+
+#ifdef CONFIG_SRCU
+static DEFINE_MUTEX(device_links_lock);
+DEFINE_STATIC_SRCU(device_links_srcu);
+
+static inline void device_links_write_lock(void)
+{
+	mutex_lock(&device_links_lock);
+}
+
+static inline void device_links_write_unlock(void)
+{
+	mutex_unlock(&device_links_lock);
+}
+
+int device_links_read_lock(void)
+{
+	return srcu_read_lock(&device_links_srcu);
+}
+
+void device_links_read_unlock(int idx)
+{
+	srcu_read_unlock(&device_links_srcu, idx);
+}
+#else /* !CONFIG_SRCU */
+static DECLARE_RWSEM(device_links_lock);
+
+static inline void device_links_write_lock(void)
+{
+	down_write(&device_links_lock);
+}
+
+static inline void device_links_write_unlock(void)
+{
+	up_write(&device_links_lock);
+}
+
+int device_links_read_lock(void)
+{
+	down_read(&device_links_lock);
+	return 0;
+}
+
+void device_links_read_unlock(int not_used)
+{
+	up_read(&device_links_lock);
+}
+#endif /* !CONFIG_SRCU */
+
+/**
+ * device_is_dependent - Check if one device depends on another one
+ * @dev: Device to check dependencies for.
+ * @target: Device to check against.
+ *
+ * Check if @target depends on @dev or any device dependent on it (its child or
+ * its consumer etc).  Return 1 if that is the case or 0 otherwise.
+ */
+static int device_is_dependent(struct device *dev, void *target)
+{
+	struct device_link *link;
+	int ret;
+
+	if (WARN_ON(dev == target))
+		return 1;
+
+	ret = device_for_each_child(dev, target, device_is_dependent);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(link, &dev->links.consumers, s_node) {
+		if (WARN_ON(link->consumer == target))
+			return 1;
+
+		ret = device_is_dependent(link->consumer, target);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+static int device_reorder_to_tail(struct device *dev, void *not_used)
+{
+	struct device_link *link;
+
+	/*
+	 * Devices that have not been registered yet will be put to the ends
+	 * of the lists during the registration, so skip them here.
+	 */
+	if (device_is_registered(dev))
+		devices_kset_move_last(dev);
+
+	if (device_pm_initialized(dev))
+		device_pm_move_last(dev);
+
+	device_for_each_child(dev, NULL, device_reorder_to_tail);
+	list_for_each_entry(link, &dev->links.consumers, s_node)
+		device_reorder_to_tail(link->consumer, NULL);
+
+	return 0;
+}
+
+/**
+ * device_link_add - Create a link between two devices.
+ * @consumer: Consumer end of the link.
+ * @supplier: Supplier end of the link.
+ * @flags: Link flags.
+ *
+ * The caller is responsible for the proper synchronization of the link creation
+ * with runtime PM.  First, setting the DL_FLAG_PM_RUNTIME flag will cause the
+ * runtime PM framework to take the link into account.  Second, if the
+ * DL_FLAG_RPM_ACTIVE flag is set in addition to it, the supplier devices will
+ * be forced into the active metastate and reference-counted upon the creation
+ * of the link.  If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be
+ * ignored.
+ *
+ * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically
+ * when the consumer device driver unbinds from it.  The combination of both
+ * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL
+ * to be returned.
+ *
+ * A side effect of the link creation is re-ordering of dpm_list and the
+ * devices_kset list by moving the consumer device and all devices depending
+ * on it to the ends of these lists (that does not happen to devices that have
+ * not been registered when this function is called).
+ *
+ * The supplier device is required to be registered when this function is called
+ * and NULL will be returned if that is not the case.  The consumer device need
+ * not be registered, however.
+ */
+struct device_link *device_link_add(struct device *consumer,
+				    struct device *supplier, u32 flags)
+{
+	struct device_link *link;
+
+	if (!consumer || !supplier ||
+	    ((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_AUTOREMOVE)))
+		return NULL;
+
+	device_links_write_lock();
+	device_pm_lock();
+
+	/*
+	 * If the supplier has not been fully registered yet or there is a
+	 * reverse dependency between the consumer and the supplier already in
+	 * the graph, return NULL.
+	 */
+	if (!device_pm_initialized(supplier)
+	    || device_is_dependent(consumer, supplier)) {
+		link = NULL;
+		goto out;
+	}
+
+	list_for_each_entry(link, &supplier->links.consumers, s_node)
+		if (link->consumer == consumer)
+			goto out;
+
+	link = kzalloc(sizeof(*link), GFP_KERNEL);
+	if (!link)
+		goto out;
+
+	if (flags & DL_FLAG_PM_RUNTIME) {
+		if (flags & DL_FLAG_RPM_ACTIVE) {
+			if (pm_runtime_get_sync(supplier) < 0) {
+				pm_runtime_put_noidle(supplier);
+				kfree(link);
+				link = NULL;
+				goto out;
+			}
+			link->rpm_active = true;
+		}
+		pm_runtime_new_link(consumer);
+	}
+	get_device(supplier);
+	link->supplier = supplier;
+	INIT_LIST_HEAD(&link->s_node);
+	get_device(consumer);
+	link->consumer = consumer;
+	INIT_LIST_HEAD(&link->c_node);
+	link->flags = flags;
+
+	/* Determine the initial link state. */
+	if (flags & DL_FLAG_STATELESS) {
+		link->status = DL_STATE_NONE;
+	} else {
+		switch (supplier->links.status) {
+		case DL_DEV_DRIVER_BOUND:
+			switch (consumer->links.status) {
+			case DL_DEV_PROBING:
+				/*
+				 * Balance the decrementation of the supplier's
+				 * runtime PM usage counter after consumer probe
+				 * in driver_probe_device().
+				 */
+				if (flags & DL_FLAG_PM_RUNTIME)
+					pm_runtime_get_sync(supplier);
+
+				link->status = DL_STATE_CONSUMER_PROBE;
+				break;
+			case DL_DEV_DRIVER_BOUND:
+				link->status = DL_STATE_ACTIVE;
+				break;
+			default:
+				link->status = DL_STATE_AVAILABLE;
+				break;
+			}
+			break;
+		case DL_DEV_UNBINDING:
+			link->status = DL_STATE_SUPPLIER_UNBIND;
+			break;
+		default:
+			link->status = DL_STATE_DORMANT;
+			break;
+		}
+	}
+
+	/*
+	 * Move the consumer and all of the devices depending on it to the end
+	 * of dpm_list and the devices_kset list.
+	 *
+	 * It is necessary to hold dpm_list locked throughout all that or else
+	 * we may end up suspending with a wrong ordering of it.
+	 */
+	device_reorder_to_tail(consumer, NULL);
+
+	list_add_tail_rcu(&link->s_node, &supplier->links.consumers);
+	list_add_tail_rcu(&link->c_node, &consumer->links.suppliers);
+
+	dev_info(consumer, "Linked as a consumer to %s\n", dev_name(supplier));
+
+ out:
+	device_pm_unlock();
+	device_links_write_unlock();
+	return link;
+}
+EXPORT_SYMBOL_GPL(device_link_add);
+
+static void device_link_free(struct device_link *link)
+{
+	put_device(link->consumer);
+	put_device(link->supplier);
+	kfree(link);
+}
+
+#ifdef CONFIG_SRCU
+static void __device_link_free_srcu(struct rcu_head *rhead)
+{
+	device_link_free(container_of(rhead, struct device_link, rcu_head));
+}
+
+static void __device_link_del(struct device_link *link)
+{
+	dev_info(link->consumer, "Dropping the link to %s\n",
+		 dev_name(link->supplier));
+
+	if (link->flags & DL_FLAG_PM_RUNTIME)
+		pm_runtime_drop_link(link->consumer);
+
+	list_del_rcu(&link->s_node);
+	list_del_rcu(&link->c_node);
+	call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
+}
+#else /* !CONFIG_SRCU */
+static void __device_link_del(struct device_link *link)
+{
+	dev_info(link->consumer, "Dropping the link to %s\n",
+		 dev_name(link->supplier));
+
+	list_del(&link->s_node);
+	list_del(&link->c_node);
+	device_link_free(link);
+}
+#endif /* !CONFIG_SRCU */
+
+/**
+ * device_link_del - Delete a link between two devices.
+ * @link: Device link to delete.
+ *
+ * The caller must ensure proper synchronization of this function with runtime
+ * PM.
+ */
+void device_link_del(struct device_link *link)
+{
+	device_links_write_lock();
+	device_pm_lock();
+	__device_link_del(link);
+	device_pm_unlock();
+	device_links_write_unlock();
+}
+EXPORT_SYMBOL_GPL(device_link_del);
+
+static void device_links_missing_supplier(struct device *dev)
+{
+	struct device_link *link;
+
+	list_for_each_entry(link, &dev->links.suppliers, c_node)
+		if (link->status == DL_STATE_CONSUMER_PROBE)
+			WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
+}
+
+/**
+ * device_links_check_suppliers - Check presence of supplier drivers.
+ * @dev: Consumer device.
+ *
+ * Check links from this device to any suppliers.  Walk the list of the device's
+ * links to suppliers and see if all of them are available.  If not, simply
+ * return -EPROBE_DEFER.
+ *
+ * We need to guarantee that the supplier will not go away after the check has
+ * been positive here.  It only can go away in __device_release_driver() and
+ * that function  checks the device's links to consumers.  This means we need to
+ * mark the link as "consumer probe in progress" to make the supplier removal
+ * wait for us to complete (or bad things may happen).
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ */
+int device_links_check_suppliers(struct device *dev)
+{
+	struct device_link *link;
+	int ret = 0;
+
+	device_links_write_lock();
+
+	list_for_each_entry(link, &dev->links.suppliers, c_node) {
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		if (link->status != DL_STATE_AVAILABLE) {
+			device_links_missing_supplier(dev);
+			ret = -EPROBE_DEFER;
+			break;
+		}
+		WRITE_ONCE(link->status, DL_STATE_CONSUMER_PROBE);
+	}
+	dev->links.status = DL_DEV_PROBING;
+
+	device_links_write_unlock();
+	return ret;
+}
+
+/**
+ * device_links_driver_bound - Update device links after probing its driver.
+ * @dev: Device to update the links for.
+ *
+ * The probe has been successful, so update links from this device to any
+ * consumers by changing their status to "available".
+ *
+ * Also change the status of @dev's links to suppliers to "active".
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ */
+void device_links_driver_bound(struct device *dev)
+{
+	struct device_link *link;
+
+	device_links_write_lock();
+
+	list_for_each_entry(link, &dev->links.consumers, s_node) {
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		WARN_ON(link->status != DL_STATE_DORMANT);
+		WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
+	}
+
+	list_for_each_entry(link, &dev->links.suppliers, c_node) {
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		WARN_ON(link->status != DL_STATE_CONSUMER_PROBE);
+		WRITE_ONCE(link->status, DL_STATE_ACTIVE);
+	}
+
+	dev->links.status = DL_DEV_DRIVER_BOUND;
+
+	device_links_write_unlock();
+}
+
+/**
+ * __device_links_no_driver - Update links of a device without a driver.
+ * @dev: Device without a drvier.
+ *
+ * Delete all non-persistent links from this device to any suppliers.
+ *
+ * Persistent links stay around, but their status is changed to "available",
+ * unless they already are in the "supplier unbind in progress" state in which
+ * case they need not be updated.
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ */
+static void __device_links_no_driver(struct device *dev)
+{
+	struct device_link *link, *ln;
+
+	list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		if (link->flags & DL_FLAG_AUTOREMOVE)
+			__device_link_del(link);
+		else if (link->status != DL_STATE_SUPPLIER_UNBIND)
+			WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
+	}
+
+	dev->links.status = DL_DEV_NO_DRIVER;
+}
+
+void device_links_no_driver(struct device *dev)
+{
+	device_links_write_lock();
+	__device_links_no_driver(dev);
+	device_links_write_unlock();
+}
+
+/**
+ * device_links_driver_cleanup - Update links after driver removal.
+ * @dev: Device whose driver has just gone away.
+ *
+ * Update links to consumers for @dev by changing their status to "dormant" and
+ * invoke %__device_links_no_driver() to update links to suppliers for it as
+ * appropriate.
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ */
+void device_links_driver_cleanup(struct device *dev)
+{
+	struct device_link *link;
+
+	device_links_write_lock();
+
+	list_for_each_entry(link, &dev->links.consumers, s_node) {
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		WARN_ON(link->flags & DL_FLAG_AUTOREMOVE);
+		WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND);
+		WRITE_ONCE(link->status, DL_STATE_DORMANT);
+	}
+
+	__device_links_no_driver(dev);
+
+	device_links_write_unlock();
+}
+
+/**
+ * device_links_busy - Check if there are any busy links to consumers.
+ * @dev: Device to check.
+ *
+ * Check each consumer of the device and return 'true' if its link's status
+ * is one of "consumer probe" or "active" (meaning that the given consumer is
+ * probing right now or its driver is present).  Otherwise, change the link
+ * state to "supplier unbind" to prevent the consumer from being probed
+ * successfully going forward.
+ *
+ * Return 'false' if there are no probing or active consumers.
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ */
+bool device_links_busy(struct device *dev)
+{
+	struct device_link *link;
+	bool ret = false;
+
+	device_links_write_lock();
+
+	list_for_each_entry(link, &dev->links.consumers, s_node) {
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		if (link->status == DL_STATE_CONSUMER_PROBE
+		    || link->status == DL_STATE_ACTIVE) {
+			ret = true;
+			break;
+		}
+		WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND);
+	}
+
+	dev->links.status = DL_DEV_UNBINDING;
+
+	device_links_write_unlock();
+	return ret;
+}
+
+/**
+ * device_links_unbind_consumers - Force unbind consumers of the given device.
+ * @dev: Device to unbind the consumers of.
+ *
+ * Walk the list of links to consumers for @dev and if any of them is in the
+ * "consumer probe" state, wait for all device probes in progress to complete
+ * and start over.
+ *
+ * If that's not the case, change the status of the link to "supplier unbind"
+ * and check if the link was in the "active" state.  If so, force the consumer
+ * driver to unbind and start over (the consumer will not re-probe as we have
+ * changed the state of the link already).
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ */
+void device_links_unbind_consumers(struct device *dev)
+{
+	struct device_link *link;
+
+ start:
+	device_links_write_lock();
+
+	list_for_each_entry(link, &dev->links.consumers, s_node) {
+		enum device_link_state status;
+
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		status = link->status;
+		if (status == DL_STATE_CONSUMER_PROBE) {
+			device_links_write_unlock();
+
+			wait_for_device_probe();
+			goto start;
+		}
+		WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND);
+		if (status == DL_STATE_ACTIVE) {
+			struct device *consumer = link->consumer;
+
+			get_device(consumer);
+
+			device_links_write_unlock();
+
+			device_release_driver_internal(consumer, NULL,
+						       consumer->parent);
+			put_device(consumer);
+			goto start;
+		}
+	}
+
+	device_links_write_unlock();
+}
+
+/**
+ * device_links_purge - Delete existing links to other devices.
+ * @dev: Target device.
+ */
+static void device_links_purge(struct device *dev)
+{
+	struct device_link *link, *ln;
+
+	/*
+	 * Delete all of the remaining links from this device to any other
+	 * devices (either consumers or suppliers).
+	 */
+	device_links_write_lock();
+
+	list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
+		WARN_ON(link->status == DL_STATE_ACTIVE);
+		__device_link_del(link);
+	}
+
+	list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
+		WARN_ON(link->status != DL_STATE_DORMANT &&
+			link->status != DL_STATE_NONE);
+		__device_link_del(link);
+	}
+
+	device_links_write_unlock();
+}
+
+/* Device links support end. */
+
 int (*platform_notify)(struct device *dev) = NULL;
 int (*platform_notify_remove)(struct device *dev) = NULL;
 static struct kobject *dev_kobj;
@@ -711,6 +1277,9 @@ void device_initialize(struct device *de
 #ifdef CONFIG_GENERIC_MSI_IRQ
 	INIT_LIST_HEAD(&dev->msi_list);
 #endif
+	INIT_LIST_HEAD(&dev->links.consumers);
+	INIT_LIST_HEAD(&dev->links.suppliers);
+	dev->links.status = DL_DEV_NO_DRIVER;
 }
 EXPORT_SYMBOL_GPL(device_initialize);
 
@@ -1258,6 +1827,8 @@ void device_del(struct device *dev)
 	if (dev->bus)
 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_DEL_DEVICE, dev);
+
+	device_links_purge(dev);
 	dpm_sysfs_remove(dev);
 	if (parent)
 		klist_del(&dev->p->knode_parent);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/dd.c linux-libre-4.10-rc8-gnu/drivers/base/dd.c
--- linux-libre-4.9-gnu/drivers/base/dd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/dd.c	2017-02-12 16:03:20.000000000 -0500
@@ -244,6 +244,7 @@ static void driver_bound(struct device *
 		 __func__, dev_name(dev));
 
 	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
+	device_links_driver_bound(dev);
 
 	device_pm_check_callbacks(dev);
 
@@ -338,6 +339,10 @@ static int really_probe(struct device *d
 		return ret;
 	}
 
+	ret = device_links_check_suppliers(dev);
+	if (ret)
+		return ret;
+
 	atomic_inc(&probe_count);
 	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
 		 drv->bus->name, __func__, drv->name, dev_name(dev));
@@ -416,6 +421,7 @@ probe_failed:
 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
 pinctrl_bind_failed:
+	device_links_no_driver(dev);
 	devres_release_all(dev);
 	driver_sysfs_remove(dev);
 	dev->driver = NULL;
@@ -508,6 +514,7 @@ int driver_probe_device(struct device_dr
 	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
 		 drv->bus->name, __func__, dev_name(dev), drv->name);
 
+	pm_runtime_get_suppliers(dev);
 	if (dev->parent)
 		pm_runtime_get_sync(dev->parent);
 
@@ -518,6 +525,7 @@ int driver_probe_device(struct device_dr
 	if (dev->parent)
 		pm_runtime_put(dev->parent);
 
+	pm_runtime_put_suppliers(dev);
 	return ret;
 }
 
@@ -772,7 +780,7 @@ EXPORT_SYMBOL_GPL(driver_attach);
  * __device_release_driver() must be called with @dev lock held.
  * When called for a USB interface, @dev->parent lock must be held as well.
  */
-static void __device_release_driver(struct device *dev)
+static void __device_release_driver(struct device *dev, struct device *parent)
 {
 	struct device_driver *drv;
 
@@ -781,7 +789,27 @@ static void __device_release_driver(stru
 		if (driver_allows_async_probing(drv))
 			async_synchronize_full();
 
+		while (device_links_busy(dev)) {
+			device_unlock(dev);
+			if (parent)
+				device_unlock(parent);
+
+			device_links_unbind_consumers(dev);
+			if (parent)
+				device_lock(parent);
+
+			device_lock(dev);
+			/*
+			 * A concurrent invocation of the same function might
+			 * have released the driver successfully while this one
+			 * was waiting, so check for that.
+			 */
+			if (dev->driver != drv)
+				return;
+		}
+
 		pm_runtime_get_sync(dev);
+		pm_runtime_clean_up_links(dev);
 
 		driver_sysfs_remove(dev);
 
@@ -796,6 +824,8 @@ static void __device_release_driver(stru
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
+		device_links_driver_cleanup(dev);
 		devres_release_all(dev);
 		dev->driver = NULL;
 		dev_set_drvdata(dev, NULL);
@@ -812,12 +842,32 @@ static void __device_release_driver(stru
 	}
 }
 
+void device_release_driver_internal(struct device *dev,
+				    struct device_driver *drv,
+				    struct device *parent)
+{
+	if (parent)
+		device_lock(parent);
+
+	device_lock(dev);
+	if (!drv || drv == dev->driver)
+		__device_release_driver(dev, parent);
+
+	device_unlock(dev);
+	if (parent)
+		device_unlock(parent);
+}
+
 /**
  * device_release_driver - manually detach device from driver.
  * @dev: device.
  *
  * Manually detach device from driver.
  * When called for a USB interface, @dev->parent lock must be held.
+ *
+ * If this function is to be called with @dev->parent lock held, ensure that
+ * the device's consumers are unbound in advance or that their locks can be
+ * acquired under the @dev->parent lock.
  */
 void device_release_driver(struct device *dev)
 {
@@ -826,9 +876,7 @@ void device_release_driver(struct device
 	 * within their ->remove callback for the same device, they
 	 * will deadlock right here.
 	 */
-	device_lock(dev);
-	__device_release_driver(dev);
-	device_unlock(dev);
+	device_release_driver_internal(dev, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(device_release_driver);
 
@@ -853,15 +901,7 @@ void driver_detach(struct device_driver
 		dev = dev_prv->device;
 		get_device(dev);
 		spin_unlock(&drv->p->klist_devices.k_lock);
-
-		if (dev->parent)	/* Needed for USB */
-			device_lock(dev->parent);
-		device_lock(dev);
-		if (dev->driver == drv)
-			__device_release_driver(dev);
-		device_unlock(dev);
-		if (dev->parent)
-			device_unlock(dev->parent);
+		device_release_driver_internal(dev, drv, dev->parent);
 		put_device(dev);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/devcoredump.c linux-libre-4.10-rc8-gnu/drivers/base/devcoredump.c
--- linux-libre-4.9-gnu/drivers/base/devcoredump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/devcoredump.c	2017-02-12 16:03:20.000000000 -0500
@@ -160,18 +160,20 @@ static ssize_t disabled_store(struct cla
 
 	return count;
 }
+static CLASS_ATTR_RW(disabled);
 
-static struct class_attribute devcd_class_attrs[] = {
-	__ATTR_RW(disabled),
-	__ATTR_NULL
+static struct attribute *devcd_class_attrs[] = {
+	&class_attr_disabled.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(devcd_class);
 
 static struct class devcd_class = {
 	.name		= "devcoredump",
 	.owner		= THIS_MODULE,
 	.dev_release	= devcd_dev_release,
 	.dev_groups	= devcd_dev_groups,
-	.class_attrs	= devcd_class_attrs,
+	.class_groups	= devcd_class_groups,
 };
 
 static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/devres.c linux-libre-4.10-rc8-gnu/drivers/base/devres.c
--- linux-libre-4.9-gnu/drivers/base/devres.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/devres.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/percpu.h>
 
 #include "base.h"
 
@@ -985,3 +986,68 @@ void devm_free_pages(struct device *dev,
 			       &devres));
 }
 EXPORT_SYMBOL_GPL(devm_free_pages);
+
+static void devm_percpu_release(struct device *dev, void *pdata)
+{
+	void __percpu *p;
+
+	p = *(void __percpu **)pdata;
+	free_percpu(p);
+}
+
+static int devm_percpu_match(struct device *dev, void *data, void *p)
+{
+	struct devres *devr = container_of(data, struct devres, data);
+
+	return *(void **)devr->data == p;
+}
+
+/**
+ * __devm_alloc_percpu - Resource-managed alloc_percpu
+ * @dev: Device to allocate per-cpu memory for
+ * @size: Size of per-cpu memory to allocate
+ * @align: Alignment of per-cpu memory to allocate
+ *
+ * Managed alloc_percpu. Per-cpu memory allocated with this function is
+ * automatically freed on driver detach.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
+		size_t align)
+{
+	void *p;
+	void __percpu *pcpu;
+
+	pcpu = __alloc_percpu(size, align);
+	if (!pcpu)
+		return NULL;
+
+	p = devres_alloc(devm_percpu_release, sizeof(void *), GFP_KERNEL);
+	if (!p) {
+		free_percpu(pcpu);
+		return NULL;
+	}
+
+	*(void __percpu **)p = pcpu;
+
+	devres_add(dev, p);
+
+	return pcpu;
+}
+EXPORT_SYMBOL_GPL(__devm_alloc_percpu);
+
+/**
+ * devm_free_percpu - Resource-managed free_percpu
+ * @dev: Device this memory belongs to
+ * @pdata: Per-cpu memory to free
+ *
+ * Free memory allocated with devm_alloc_percpu().
+ */
+void devm_free_percpu(struct device *dev, void __percpu *pdata)
+{
+	WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match,
+			       (void *)pdata));
+}
+EXPORT_SYMBOL_GPL(devm_free_percpu);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/dma-mapping.c linux-libre-4.10-rc8-gnu/drivers/base/dma-mapping.c
--- linux-libre-4.9-gnu/drivers/base/dma-mapping.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/dma-mapping.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,13 +108,13 @@ void dmam_free_coherent(struct device *d
 EXPORT_SYMBOL(dmam_free_coherent);
 
 /**
- * dmam_alloc_non_coherent - Managed dma_alloc_non_coherent()
+ * dmam_alloc_non_coherent - Managed dma_alloc_noncoherent()
  * @dev: Device to allocate non_coherent memory for
  * @size: Size of allocation
  * @dma_handle: Out argument for allocated DMA handle
  * @gfp: Allocation flags
  *
- * Managed dma_alloc_non_coherent().  Memory allocated using this
+ * Managed dma_alloc_noncoherent().  Memory allocated using this
  * function will be automatically released on driver detach.
  *
  * RETURNS:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/firmware_class.c linux-libre-4.10-rc8-gnu/drivers/base/firmware_class.c
--- linux-libre-4.9-gnu/drivers/base/firmware_class.c	2016-12-11 17:39:18.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/firmware_class.c	2017-02-12 17:21:10.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/swait.h>
 
 #include <generated/utsrelease.h>
 
@@ -91,10 +92,11 @@ static inline bool fw_is_builtin_firmwar
 }
 #endif
 
-enum {
+enum fw_status {
+	FW_STATUS_UNKNOWN,
 	FW_STATUS_LOADING,
 	FW_STATUS_DONE,
-	FW_STATUS_ABORT,
+	FW_STATUS_ABORTED,
 };
 
 static int loading_timeout = 60;	/* In seconds */
@@ -104,6 +106,82 @@ static inline long firmware_loading_time
 	return loading_timeout > 0 ? loading_timeout * HZ : MAX_JIFFY_OFFSET;
 }
 
+/*
+ * Concurrent request_firmware() for the same firmware need to be
+ * serialized.  struct fw_state is simple state machine which hold the
+ * state of the firmware loading.
+ */
+struct fw_state {
+	struct swait_queue_head wq;
+	enum fw_status status;
+};
+
+static void fw_state_init(struct fw_state *fw_st)
+{
+	init_swait_queue_head(&fw_st->wq);
+	fw_st->status = FW_STATUS_UNKNOWN;
+}
+
+static inline bool __fw_state_is_done(enum fw_status status)
+{
+	return status == FW_STATUS_DONE || status == FW_STATUS_ABORTED;
+}
+
+static int __fw_state_wait_common(struct fw_state *fw_st, long timeout)
+{
+	long ret;
+
+	ret = swait_event_interruptible_timeout(fw_st->wq,
+				__fw_state_is_done(READ_ONCE(fw_st->status)),
+				timeout);
+	if (ret != 0 && fw_st->status == FW_STATUS_ABORTED)
+		return -ENOENT;
+	if (!ret)
+		return -ETIMEDOUT;
+
+	return ret < 0 ? ret : 0;
+}
+
+static void __fw_state_set(struct fw_state *fw_st,
+			   enum fw_status status)
+{
+	WRITE_ONCE(fw_st->status, status);
+
+	if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED)
+		swake_up(&fw_st->wq);
+}
+
+#define fw_state_start(fw_st)					\
+	__fw_state_set(fw_st, FW_STATUS_LOADING)
+#define fw_state_done(fw_st)					\
+	__fw_state_set(fw_st, FW_STATUS_DONE)
+#define fw_state_wait(fw_st)					\
+	__fw_state_wait_common(fw_st, MAX_SCHEDULE_TIMEOUT)
+
+#ifndef CONFIG_FW_LOADER_USER_HELPER
+
+#define fw_state_is_aborted(fw_st)	false
+
+#else /* CONFIG_FW_LOADER_USER_HELPER */
+
+static int __fw_state_check(struct fw_state *fw_st, enum fw_status status)
+{
+	return fw_st->status == status;
+}
+
+#define fw_state_aborted(fw_st)					\
+	__fw_state_set(fw_st, FW_STATUS_ABORTED)
+#define fw_state_is_done(fw_st)					\
+	__fw_state_check(fw_st, FW_STATUS_DONE)
+#define fw_state_is_loading(fw_st)				\
+	__fw_state_check(fw_st, FW_STATUS_LOADING)
+#define fw_state_is_aborted(fw_st)				\
+	__fw_state_check(fw_st, FW_STATUS_ABORTED)
+#define fw_state_wait_timeout(fw_st, timeout)			\
+	__fw_state_wait_common(fw_st, timeout)
+
+#endif /* CONFIG_FW_LOADER_USER_HELPER */
+
 /* firmware behavior options */
 #define FW_OPT_UEVENT	(1U << 0)
 #define FW_OPT_NOWAIT	(1U << 1)
@@ -145,9 +223,8 @@ struct firmware_cache {
 struct firmware_buf {
 	struct kref ref;
 	struct list_head list;
-	struct completion completion;
 	struct firmware_cache *fwc;
-	unsigned long status;
+	struct fw_state fw_st;
 	void *data;
 	size_t size;
 	size_t allocated_size;
@@ -205,7 +282,7 @@ static struct firmware_buf *__allocate_f
 	buf->fwc = fwc;
 	buf->data = dbuf;
 	buf->allocated_size = size;
-	init_completion(&buf->completion);
+	fw_state_init(&buf->fw_st);
 #ifdef CONFIG_FW_LOADER_USER_HELPER
 	INIT_LIST_HEAD(&buf->pending_list);
 #endif
@@ -305,15 +382,6 @@ static const char * const fw_path[] = {
 module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
 MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
 
-static void fw_finish_direct_load(struct device *device,
-				  struct firmware_buf *buf)
-{
-	mutex_lock(&fw_lock);
-	set_bit(FW_STATUS_DONE, &buf->status);
-	complete_all(&buf->completion);
-	mutex_unlock(&fw_lock);
-}
-
 static int
 fw_get_filesystem_firmware(struct device *device, struct firmware_buf *buf)
 {
@@ -360,7 +428,7 @@ fw_get_filesystem_firmware(struct device
 		}
 		dev_dbg(device, "direct-loading %s\n", buf->fw_id);
 		buf->size = size;
-		fw_finish_direct_load(device, buf);
+		fw_state_done(&buf->fw_st);
 		break;
 	}
 	__putname(path);
@@ -478,12 +546,11 @@ static void __fw_load_abort(struct firmw
 	 * There is a small window in which user can write to 'loading'
 	 * between loading done and disappearance of 'loading'
 	 */
-	if (test_bit(FW_STATUS_DONE, &buf->status))
+	if (fw_state_is_done(&buf->fw_st))
 		return;
 
 	list_del_init(&buf->pending_list);
-	set_bit(FW_STATUS_ABORT, &buf->status);
-	complete_all(&buf->completion);
+	fw_state_aborted(&buf->fw_st);
 }
 
 static void fw_load_abort(struct firmware_priv *fw_priv)
@@ -491,14 +558,8 @@ static void fw_load_abort(struct firmwar
 	struct firmware_buf *buf = fw_priv->buf;
 
 	__fw_load_abort(buf);
-
-	/* avoid user action after loading abort */
-	fw_priv->buf = NULL;
 }
 
-#define is_fw_load_aborted(buf)	\
-	test_bit(FW_STATUS_ABORT, &(buf)->status)
-
 static LIST_HEAD(pending_fw_head);
 
 /* reboot notifier for avoid deadlock with usermode_lock */
@@ -546,11 +607,13 @@ static ssize_t timeout_store(struct clas
 
 	return count;
 }
+static CLASS_ATTR_RW(timeout);
 
-static struct class_attribute firmware_class_attrs[] = {
-	__ATTR_RW(timeout),
-	__ATTR_NULL
+static struct attribute *firmware_class_attrs[] = {
+	&class_attr_timeout.attr,
+	NULL,
 };
+ATTRIBUTE_GROUPS(firmware_class);
 
 static void fw_dev_release(struct device *dev)
 {
@@ -585,7 +648,7 @@ static int firmware_uevent(struct device
 
 static struct class firmware_class = {
 	.name		= "firmware",
-	.class_attrs	= firmware_class_attrs,
+	.class_groups	= firmware_class_groups,
 	.dev_uevent	= firmware_uevent,
 	.dev_release	= fw_dev_release,
 };
@@ -598,7 +661,7 @@ static ssize_t firmware_loading_show(str
 
 	mutex_lock(&fw_lock);
 	if (fw_priv->buf)
-		loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status);
+		loading = fw_state_is_loading(&fw_priv->buf->fw_st);
 	mutex_unlock(&fw_lock);
 
 	return sprintf(buf, "%d\n", loading);
@@ -647,29 +710,26 @@ static ssize_t firmware_loading_store(st
 
 	mutex_lock(&fw_lock);
 	fw_buf = fw_priv->buf;
-	if (!fw_buf)
+	if (fw_state_is_aborted(&fw_buf->fw_st))
 		goto out;
 
 	switch (loading) {
 	case 1:
 		/* discarding any previous partial load */
-		if (!test_bit(FW_STATUS_DONE, &fw_buf->status)) {
+		if (!fw_state_is_done(&fw_buf->fw_st)) {
 			for (i = 0; i < fw_buf->nr_pages; i++)
 				__free_page(fw_buf->pages[i]);
 			vfree(fw_buf->pages);
 			fw_buf->pages = NULL;
 			fw_buf->page_array_size = 0;
 			fw_buf->nr_pages = 0;
-			set_bit(FW_STATUS_LOADING, &fw_buf->status);
+			fw_state_start(&fw_buf->fw_st);
 		}
 		break;
 	case 0:
-		if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
+		if (fw_state_is_loading(&fw_buf->fw_st)) {
 			int rc;
 
-			set_bit(FW_STATUS_DONE, &fw_buf->status);
-			clear_bit(FW_STATUS_LOADING, &fw_buf->status);
-
 			/*
 			 * Several loading requests may be pending on
 			 * one same firmware buf, so let all requests
@@ -691,10 +751,11 @@ static ssize_t firmware_loading_store(st
 			 */
 			list_del_init(&fw_buf->pending_list);
 			if (rc) {
-				set_bit(FW_STATUS_ABORT, &fw_buf->status);
+				fw_state_aborted(&fw_buf->fw_st);
 				written = rc;
+			} else {
+				fw_state_done(&fw_buf->fw_st);
 			}
-			complete_all(&fw_buf->completion);
 			break;
 		}
 		/* fallthrough */
@@ -755,7 +816,7 @@ static ssize_t firmware_data_read(struct
 
 	mutex_lock(&fw_lock);
 	buf = fw_priv->buf;
-	if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) {
+	if (!buf || fw_state_is_done(&buf->fw_st)) {
 		ret_count = -ENODEV;
 		goto out;
 	}
@@ -842,7 +903,7 @@ static ssize_t firmware_data_write(struc
 
 	mutex_lock(&fw_lock);
 	buf = fw_priv->buf;
-	if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) {
+	if (!buf || fw_state_is_done(&buf->fw_st)) {
 		retval = -ENODEV;
 		goto out;
 	}
@@ -955,17 +1016,14 @@ static int _request_firmware_load(struct
 		timeout = MAX_JIFFY_OFFSET;
 	}
 
-	retval = wait_for_completion_interruptible_timeout(&buf->completion,
-			timeout);
-	if (retval == -ERESTARTSYS || !retval) {
+	retval = fw_state_wait_timeout(&buf->fw_st, timeout);
+	if (retval < 0) {
 		mutex_lock(&fw_lock);
 		fw_load_abort(fw_priv);
 		mutex_unlock(&fw_lock);
-	} else if (retval > 0) {
-		retval = 0;
 	}
 
-	if (is_fw_load_aborted(buf))
+	if (fw_state_is_aborted(&buf->fw_st))
 		retval = -EAGAIN;
 	else if (buf->is_paged_buf && !buf->data)
 		retval = -ENOMEM;
@@ -1015,35 +1073,12 @@ fw_load_from_user_helper(struct firmware
 	return -ENOENT;
 }
 
-/* No abort during direct loading */
-#define is_fw_load_aborted(buf) false
-
 #ifdef CONFIG_PM_SLEEP
 static inline void kill_requests_without_uevent(void) { }
 #endif
 
 #endif /* CONFIG_FW_LOADER_USER_HELPER */
 
-
-/* wait until the shared firmware_buf becomes ready (or error) */
-static int sync_cached_firmware_buf(struct firmware_buf *buf)
-{
-	int ret = 0;
-
-	mutex_lock(&fw_lock);
-	while (!test_bit(FW_STATUS_DONE, &buf->status)) {
-		if (is_fw_load_aborted(buf)) {
-			ret = -ENOENT;
-			break;
-		}
-		mutex_unlock(&fw_lock);
-		ret = wait_for_completion_interruptible(&buf->completion);
-		mutex_lock(&fw_lock);
-	}
-	mutex_unlock(&fw_lock);
-	return ret;
-}
-
 /* prepare firmware and firmware_buf structs;
  * return 0 if a firmware is already assigned, 1 if need to load one,
  * or a negative error code
@@ -1077,7 +1112,7 @@ _request_firmware_prepare(struct firmwar
 	firmware->priv = buf;
 
 	if (ret > 0) {
-		ret = sync_cached_firmware_buf(buf);
+		ret = fw_state_wait(&buf->fw_st);
 		if (!ret) {
 			fw_set_page_data(buf, firmware);
 			return 0; /* assigned */
@@ -1095,7 +1130,7 @@ static int assign_firmware_buf(struct fi
 	struct firmware_buf *buf = fw->priv;
 
 	mutex_lock(&fw_lock);
-	if (!buf->size || is_fw_load_aborted(buf)) {
+	if (!buf->size || fw_state_is_aborted(&buf->fw_st)) {
 		mutex_unlock(&fw_lock);
 		return -ENOENT;
 	}
@@ -1345,9 +1380,9 @@ static void request_firmware_work_func(s
  *
  *	Asynchronous variant of request_firmware() for user contexts:
  *		- sleep for as small periods as possible since it may
- *		increase kernel boot time of built-in device drivers
- *		requesting firmware in their ->probe() methods, if
- *		@gfp is GFP_KERNEL.
+ *		  increase kernel boot time of built-in device drivers
+ *		  requesting firmware in their ->probe() methods, if
+ *		  @gfp is GFP_KERNEL.
  *
  *		- can't sleep at all if @gfp is GFP_ATOMIC.
  **/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/Kconfig linux-libre-4.10-rc8-gnu/drivers/base/Kconfig
--- linux-libre-4.9-gnu/drivers/base/Kconfig	2016-12-11 18:05:06.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/Kconfig	2017-02-12 17:58:06.000000000 -0500
@@ -224,6 +224,8 @@ config DEBUG_TEST_DRIVER_REMOVE
 	  unusable. You should say N here unless you are explicitly looking to
 	  test this functionality.
 
+source "drivers/base/test/Kconfig"
+
 config SYS_HYPERVISOR
 	bool
 	default n
@@ -237,6 +239,7 @@ config GENERIC_CPU_AUTOPROBE
 
 config SOC_BUS
 	bool
+	select GLOB
 
 source "drivers/base/regmap/Kconfig"
 
@@ -250,11 +253,11 @@ config DMA_SHARED_BUFFER
 	  APIs extension; the file's descriptor can then be passed on to other
 	  driver.
 
-config FENCE_TRACE
-	bool "Enable verbose FENCE_TRACE messages"
+config DMA_FENCE_TRACE
+	bool "Enable verbose DMA_FENCE_TRACE messages"
 	depends on DMA_SHARED_BUFFER
 	help
-	  Enable the FENCE_TRACE printks. This will add extra
+	  Enable the DMA_FENCE_TRACE printks. This will add extra
 	  spam to the console log, but will make it easier to diagnose
 	  lockup related problems for dma-buffers shared across multiple
 	  devices.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/Makefile linux-libre-4.10-rc8-gnu/drivers/base/Makefile
--- linux-libre-4.9-gnu/drivers/base/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -24,5 +24,7 @@ obj-$(CONFIG_PINCTRL) += pinctrl.o
 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o
 obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o
 
+obj-y			+= test/
+
 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/memory.c linux-libre-4.10-rc8-gnu/drivers/base/memory.c
--- linux-libre-4.9-gnu/drivers/base/memory.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/memory.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/slab.h>
 
 #include <linux/atomic.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static DEFINE_MUTEX(mem_sysfs_mutex);
 
@@ -226,11 +226,9 @@ memory_block_action(unsigned long phys_i
 {
 	unsigned long start_pfn;
 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
-	struct page *first_page;
 	int ret;
 
 	start_pfn = section_nr_to_pfn(phys_index);
-	first_page = pfn_to_page(start_pfn);
 
 	switch (action) {
 	case MEM_ONLINE:
@@ -391,33 +389,33 @@ static ssize_t show_valid_zones(struct d
 {
 	struct memory_block *mem = to_memory_block(dev);
 	unsigned long start_pfn, end_pfn;
+	unsigned long valid_start, valid_end, valid_pages;
 	unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
-	struct page *first_page;
 	struct zone *zone;
 	int zone_shift = 0;
 
 	start_pfn = section_nr_to_pfn(mem->start_section_nr);
 	end_pfn = start_pfn + nr_pages;
-	first_page = pfn_to_page(start_pfn);
 
 	/* The block contains more than one zone can not be offlined. */
-	if (!test_pages_in_a_zone(start_pfn, end_pfn))
+	if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start, &valid_end))
 		return sprintf(buf, "none\n");
 
-	zone = page_zone(first_page);
+	zone = page_zone(pfn_to_page(valid_start));
+	valid_pages = valid_end - valid_start;
 
 	/* MMOP_ONLINE_KEEP */
 	sprintf(buf, "%s", zone->name);
 
 	/* MMOP_ONLINE_KERNEL */
-	zone_shift = zone_can_shift(start_pfn, nr_pages, ZONE_NORMAL);
+	zone_can_shift(valid_start, valid_pages, ZONE_NORMAL, &zone_shift);
 	if (zone_shift) {
 		strcat(buf, " ");
 		strcat(buf, (zone + zone_shift)->name);
 	}
 
 	/* MMOP_ONLINE_MOVABLE */
-	zone_shift = zone_can_shift(start_pfn, nr_pages, ZONE_MOVABLE);
+	zone_can_shift(valid_start, valid_pages, ZONE_MOVABLE, &zone_shift);
 	if (zone_shift) {
 		strcat(buf, " ");
 		strcat(buf, (zone + zone_shift)->name);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/domain.c linux-libre-4.10-rc8-gnu/drivers/base/power/domain.c
--- linux-libre-4.9-gnu/drivers/base/power/domain.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/domain.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,105 @@
 static LIST_HEAD(gpd_list);
 static DEFINE_MUTEX(gpd_list_lock);
 
+struct genpd_lock_ops {
+	void (*lock)(struct generic_pm_domain *genpd);
+	void (*lock_nested)(struct generic_pm_domain *genpd, int depth);
+	int (*lock_interruptible)(struct generic_pm_domain *genpd);
+	void (*unlock)(struct generic_pm_domain *genpd);
+};
+
+static void genpd_lock_mtx(struct generic_pm_domain *genpd)
+{
+	mutex_lock(&genpd->mlock);
+}
+
+static void genpd_lock_nested_mtx(struct generic_pm_domain *genpd,
+					int depth)
+{
+	mutex_lock_nested(&genpd->mlock, depth);
+}
+
+static int genpd_lock_interruptible_mtx(struct generic_pm_domain *genpd)
+{
+	return mutex_lock_interruptible(&genpd->mlock);
+}
+
+static void genpd_unlock_mtx(struct generic_pm_domain *genpd)
+{
+	return mutex_unlock(&genpd->mlock);
+}
+
+static const struct genpd_lock_ops genpd_mtx_ops = {
+	.lock = genpd_lock_mtx,
+	.lock_nested = genpd_lock_nested_mtx,
+	.lock_interruptible = genpd_lock_interruptible_mtx,
+	.unlock = genpd_unlock_mtx,
+};
+
+static void genpd_lock_spin(struct generic_pm_domain *genpd)
+	__acquires(&genpd->slock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&genpd->slock, flags);
+	genpd->lock_flags = flags;
+}
+
+static void genpd_lock_nested_spin(struct generic_pm_domain *genpd,
+					int depth)
+	__acquires(&genpd->slock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave_nested(&genpd->slock, flags, depth);
+	genpd->lock_flags = flags;
+}
+
+static int genpd_lock_interruptible_spin(struct generic_pm_domain *genpd)
+	__acquires(&genpd->slock)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&genpd->slock, flags);
+	genpd->lock_flags = flags;
+	return 0;
+}
+
+static void genpd_unlock_spin(struct generic_pm_domain *genpd)
+	__releases(&genpd->slock)
+{
+	spin_unlock_irqrestore(&genpd->slock, genpd->lock_flags);
+}
+
+static const struct genpd_lock_ops genpd_spin_ops = {
+	.lock = genpd_lock_spin,
+	.lock_nested = genpd_lock_nested_spin,
+	.lock_interruptible = genpd_lock_interruptible_spin,
+	.unlock = genpd_unlock_spin,
+};
+
+#define genpd_lock(p)			p->lock_ops->lock(p)
+#define genpd_lock_nested(p, d)		p->lock_ops->lock_nested(p, d)
+#define genpd_lock_interruptible(p)	p->lock_ops->lock_interruptible(p)
+#define genpd_unlock(p)			p->lock_ops->unlock(p)
+
+#define genpd_is_irq_safe(genpd)	(genpd->flags & GENPD_FLAG_IRQ_SAFE)
+
+static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
+		struct generic_pm_domain *genpd)
+{
+	bool ret;
+
+	ret = pm_runtime_is_irq_safe(dev) && !genpd_is_irq_safe(genpd);
+
+	/* Warn once for each IRQ safe dev in no sleep domain */
+	if (ret)
+		dev_warn_once(dev, "PM domain %s will not be powered off\n",
+				genpd->name);
+
+	return ret;
+}
+
 /*
  * Get the generic PM domain for a particular struct device.
  * This validates the struct device pointer, the PM domain pointer,
@@ -200,9 +299,9 @@ static int genpd_poweron(struct generic_
 
 		genpd_sd_counter_inc(master);
 
-		mutex_lock_nested(&master->lock, depth + 1);
+		genpd_lock_nested(master, depth + 1);
 		ret = genpd_poweron(master, depth + 1);
-		mutex_unlock(&master->lock);
+		genpd_unlock(master);
 
 		if (ret) {
 			genpd_sd_counter_dec(master);
@@ -255,9 +354,9 @@ static int genpd_dev_pm_qos_notifier(str
 		spin_unlock_irq(&dev->power.lock);
 
 		if (!IS_ERR(genpd)) {
-			mutex_lock(&genpd->lock);
+			genpd_lock(genpd);
 			genpd->max_off_time_changed = true;
-			mutex_unlock(&genpd->lock);
+			genpd_unlock(genpd);
 		}
 
 		dev = dev->parent;
@@ -303,7 +402,12 @@ static int genpd_poweroff(struct generic
 		if (stat > PM_QOS_FLAGS_NONE)
 			return -EBUSY;
 
-		if (!pm_runtime_suspended(pdd->dev) || pdd->dev->power.irq_safe)
+		/*
+		 * Do not allow PM domain to be powered off, when an IRQ safe
+		 * device is part of a non-IRQ safe domain.
+		 */
+		if (!pm_runtime_suspended(pdd->dev) ||
+			irq_safe_dev_in_no_sleep_domain(pdd->dev, genpd))
 			not_suspended++;
 	}
 
@@ -354,9 +458,9 @@ static void genpd_power_off_work_fn(stru
 
 	genpd = container_of(work, struct generic_pm_domain, power_off_work);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 	genpd_poweroff(genpd, true);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 }
 
 /**
@@ -440,6 +544,7 @@ static int genpd_runtime_suspend(struct
 		return -EBUSY;
 
 	/* Measure suspend latency. */
+	time_start = 0;
 	if (runtime_pm)
 		time_start = ktime_get();
 
@@ -466,15 +571,15 @@ static int genpd_runtime_suspend(struct
 	}
 
 	/*
-	 * If power.irq_safe is set, this routine will be run with interrupts
-	 * off, so it can't use mutexes.
+	 * If power.irq_safe is set, this routine may be run with
+	 * IRQs disabled, so suspend only if the PM domain also is irq_safe.
 	 */
-	if (dev->power.irq_safe)
+	if (irq_safe_dev_in_no_sleep_domain(dev, genpd))
 		return 0;
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 	genpd_poweroff(genpd, false);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	return 0;
 }
@@ -503,21 +608,25 @@ static int genpd_runtime_resume(struct d
 	if (IS_ERR(genpd))
 		return -EINVAL;
 
-	/* If power.irq_safe, the PM domain is never powered off. */
-	if (dev->power.irq_safe) {
+	/*
+	 * As we don't power off a non IRQ safe domain, which holds
+	 * an IRQ safe device, we don't need to restore power to it.
+	 */
+	if (irq_safe_dev_in_no_sleep_domain(dev, genpd)) {
 		timed = false;
 		goto out;
 	}
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 	ret = genpd_poweron(genpd, 0);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	if (ret)
 		return ret;
 
  out:
 	/* Measure resume latency. */
+	time_start = 0;
 	if (timed && runtime_pm)
 		time_start = ktime_get();
 
@@ -546,10 +655,11 @@ static int genpd_runtime_resume(struct d
 err_stop:
 	genpd_stop_dev(genpd, dev);
 err_poweroff:
-	if (!dev->power.irq_safe) {
-		mutex_lock(&genpd->lock);
+	if (!pm_runtime_is_irq_safe(dev) ||
+		(pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) {
+		genpd_lock(genpd);
 		genpd_poweroff(genpd, 0);
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 	}
 
 	return ret;
@@ -732,20 +842,20 @@ static int pm_genpd_prepare(struct devic
 	if (resume_needed(dev, genpd))
 		pm_runtime_resume(dev);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->prepared_count++ == 0)
 		genpd->suspended_count = 0;
 
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	ret = pm_generic_prepare(dev);
 	if (ret) {
-		mutex_lock(&genpd->lock);
+		genpd_lock(genpd);
 
 		genpd->prepared_count--;
 
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 	}
 
 	return ret;
@@ -936,13 +1046,13 @@ static void pm_genpd_complete(struct dev
 
 	pm_generic_complete(dev);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	genpd->prepared_count--;
 	if (!genpd->prepared_count)
 		genpd_queue_power_off_work(genpd);
 
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 }
 
 /**
@@ -1071,7 +1181,7 @@ static int genpd_add_device(struct gener
 	if (IS_ERR(gpd_data))
 		return PTR_ERR(gpd_data);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->prepared_count > 0) {
 		ret = -EAGAIN;
@@ -1088,7 +1198,7 @@ static int genpd_add_device(struct gener
 	list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
 
  out:
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	if (ret)
 		genpd_free_dev_data(dev, gpd_data);
@@ -1130,7 +1240,7 @@ static int genpd_remove_device(struct ge
 	gpd_data = to_gpd_data(pdd);
 	dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->prepared_count > 0) {
 		ret = -EAGAIN;
@@ -1145,14 +1255,14 @@ static int genpd_remove_device(struct ge
 
 	list_del_init(&pdd->list_node);
 
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	genpd_free_dev_data(dev, gpd_data);
 
 	return 0;
 
  out:
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 	dev_pm_qos_add_notifier(dev, &gpd_data->nb);
 
 	return ret;
@@ -1183,12 +1293,23 @@ static int genpd_add_subdomain(struct ge
 	    || genpd == subdomain)
 		return -EINVAL;
 
+	/*
+	 * If the domain can be powered on/off in an IRQ safe
+	 * context, ensure that the subdomain can also be
+	 * powered on/off in that context.
+	 */
+	if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) {
+		WARN(1, "Parent %s of subdomain %s must be IRQ safe\n",
+				genpd->name, subdomain->name);
+		return -EINVAL;
+	}
+
 	link = kzalloc(sizeof(*link), GFP_KERNEL);
 	if (!link)
 		return -ENOMEM;
 
-	mutex_lock(&subdomain->lock);
-	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+	genpd_lock(subdomain);
+	genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING);
 
 	if (genpd->status == GPD_STATE_POWER_OFF
 	    &&  subdomain->status != GPD_STATE_POWER_OFF) {
@@ -1211,8 +1332,8 @@ static int genpd_add_subdomain(struct ge
 		genpd_sd_counter_inc(genpd);
 
  out:
-	mutex_unlock(&genpd->lock);
-	mutex_unlock(&subdomain->lock);
+	genpd_unlock(genpd);
+	genpd_unlock(subdomain);
 	if (ret)
 		kfree(link);
 	return ret;
@@ -1250,8 +1371,8 @@ int pm_genpd_remove_subdomain(struct gen
 	if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
 		return -EINVAL;
 
-	mutex_lock(&subdomain->lock);
-	mutex_lock_nested(&genpd->lock, SINGLE_DEPTH_NESTING);
+	genpd_lock(subdomain);
+	genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING);
 
 	if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
 		pr_warn("%s: unable to remove subdomain %s\n", genpd->name,
@@ -1275,13 +1396,39 @@ int pm_genpd_remove_subdomain(struct gen
 	}
 
 out:
-	mutex_unlock(&genpd->lock);
-	mutex_unlock(&subdomain->lock);
+	genpd_unlock(genpd);
+	genpd_unlock(subdomain);
 
 	return ret;
 }
 EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
 
+static int genpd_set_default_power_state(struct generic_pm_domain *genpd)
+{
+	struct genpd_power_state *state;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	genpd->states = state;
+	genpd->state_count = 1;
+	genpd->free = state;
+
+	return 0;
+}
+
+static void genpd_lock_init(struct generic_pm_domain *genpd)
+{
+	if (genpd->flags & GENPD_FLAG_IRQ_SAFE) {
+		spin_lock_init(&genpd->slock);
+		genpd->lock_ops = &genpd_spin_ops;
+	} else {
+		mutex_init(&genpd->mlock);
+		genpd->lock_ops = &genpd_mtx_ops;
+	}
+}
+
 /**
  * pm_genpd_init - Initialize a generic I/O PM domain object.
  * @genpd: PM domain object to initialize.
@@ -1293,13 +1440,15 @@ EXPORT_SYMBOL_GPL(pm_genpd_remove_subdom
 int pm_genpd_init(struct generic_pm_domain *genpd,
 		  struct dev_power_governor *gov, bool is_off)
 {
+	int ret;
+
 	if (IS_ERR_OR_NULL(genpd))
 		return -EINVAL;
 
 	INIT_LIST_HEAD(&genpd->master_links);
 	INIT_LIST_HEAD(&genpd->slave_links);
 	INIT_LIST_HEAD(&genpd->dev_list);
-	mutex_init(&genpd->lock);
+	genpd_lock_init(genpd);
 	genpd->gov = gov;
 	INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
 	atomic_set(&genpd->sd_count, 0);
@@ -1325,19 +1474,12 @@ int pm_genpd_init(struct generic_pm_doma
 		genpd->dev_ops.start = pm_clk_resume;
 	}
 
-	if (genpd->state_idx >= GENPD_MAX_NUM_STATES) {
-		pr_warn("Initial state index out of bounds.\n");
-		genpd->state_idx = GENPD_MAX_NUM_STATES - 1;
-	}
-
-	if (genpd->state_count > GENPD_MAX_NUM_STATES) {
-		pr_warn("Limiting states to  %d\n", GENPD_MAX_NUM_STATES);
-		genpd->state_count = GENPD_MAX_NUM_STATES;
-	}
-
 	/* Use only one "off" state if there were no states declared */
-	if (genpd->state_count == 0)
-		genpd->state_count = 1;
+	if (genpd->state_count == 0) {
+		ret = genpd_set_default_power_state(genpd);
+		if (ret)
+			return ret;
+	}
 
 	mutex_lock(&gpd_list_lock);
 	list_add(&genpd->gpd_list_node, &gpd_list);
@@ -1354,16 +1496,16 @@ static int genpd_remove(struct generic_p
 	if (IS_ERR_OR_NULL(genpd))
 		return -EINVAL;
 
-	mutex_lock(&genpd->lock);
+	genpd_lock(genpd);
 
 	if (genpd->has_provider) {
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 		pr_err("Provider present, unable to remove %s\n", genpd->name);
 		return -EBUSY;
 	}
 
 	if (!list_empty(&genpd->master_links) || genpd->device_count) {
-		mutex_unlock(&genpd->lock);
+		genpd_unlock(genpd);
 		pr_err("%s: unable to remove %s\n", __func__, genpd->name);
 		return -EBUSY;
 	}
@@ -1375,8 +1517,9 @@ static int genpd_remove(struct generic_p
 	}
 
 	list_del(&genpd->gpd_list_node);
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 	cancel_work_sync(&genpd->power_off_work);
+	kfree(genpd->free);
 	pr_debug("%s: removed %s\n", __func__, genpd->name);
 
 	return 0;
@@ -1890,21 +2033,117 @@ int genpd_dev_pm_attach(struct device *d
 	mutex_unlock(&gpd_list_lock);
 
 	if (ret < 0) {
-		dev_err(dev, "failed to add to PM domain %s: %d",
-			pd->name, ret);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "failed to add to PM domain %s: %d",
+				pd->name, ret);
 		goto out;
 	}
 
 	dev->pm_domain->detach = genpd_dev_pm_detach;
 	dev->pm_domain->sync = genpd_dev_pm_sync;
 
-	mutex_lock(&pd->lock);
+	genpd_lock(pd);
 	ret = genpd_poweron(pd, 0);
-	mutex_unlock(&pd->lock);
+	genpd_unlock(pd);
 out:
 	return ret ? -EPROBE_DEFER : 0;
 }
 EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+
+static const struct of_device_id idle_state_match[] = {
+	{ .compatible = "domain-idle-state", },
+	{ }
+};
+
+static int genpd_parse_state(struct genpd_power_state *genpd_state,
+				    struct device_node *state_node)
+{
+	int err;
+	u32 residency;
+	u32 entry_latency, exit_latency;
+	const struct of_device_id *match_id;
+
+	match_id = of_match_node(idle_state_match, state_node);
+	if (!match_id)
+		return -EINVAL;
+
+	err = of_property_read_u32(state_node, "entry-latency-us",
+						&entry_latency);
+	if (err) {
+		pr_debug(" * %s missing entry-latency-us property\n",
+						state_node->full_name);
+		return -EINVAL;
+	}
+
+	err = of_property_read_u32(state_node, "exit-latency-us",
+						&exit_latency);
+	if (err) {
+		pr_debug(" * %s missing exit-latency-us property\n",
+						state_node->full_name);
+		return -EINVAL;
+	}
+
+	err = of_property_read_u32(state_node, "min-residency-us", &residency);
+	if (!err)
+		genpd_state->residency_ns = 1000 * residency;
+
+	genpd_state->power_on_latency_ns = 1000 * exit_latency;
+	genpd_state->power_off_latency_ns = 1000 * entry_latency;
+	genpd_state->fwnode = &state_node->fwnode;
+
+	return 0;
+}
+
+/**
+ * of_genpd_parse_idle_states: Return array of idle states for the genpd.
+ *
+ * @dn: The genpd device node
+ * @states: The pointer to which the state array will be saved.
+ * @n: The count of elements in the array returned from this function.
+ *
+ * Returns the device states parsed from the OF node. The memory for the states
+ * is allocated by this function and is the responsibility of the caller to
+ * free the memory after use.
+ */
+int of_genpd_parse_idle_states(struct device_node *dn,
+			struct genpd_power_state **states, int *n)
+{
+	struct genpd_power_state *st;
+	struct device_node *np;
+	int i = 0;
+	int err, ret;
+	int count;
+	struct of_phandle_iterator it;
+
+	count = of_count_phandle_with_args(dn, "domain-idle-states", NULL);
+	if (count <= 0)
+		return -EINVAL;
+
+	st = kcalloc(count, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	/* Loop over the phandles until all the requested entry is found */
+	of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) {
+		np = it.node;
+		ret = genpd_parse_state(&st[i++], np);
+		if (ret) {
+			pr_err
+			("Parsing idle state node %s failed with err %d\n",
+							np->full_name, ret);
+			of_node_put(np);
+			kfree(st);
+			return ret;
+		}
+	}
+
+	*n = count;
+	*states = st;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
+
 #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
 
 
@@ -1958,7 +2197,7 @@ static int pm_genpd_summary_one(struct s
 	char state[16];
 	int ret;
 
-	ret = mutex_lock_interruptible(&genpd->lock);
+	ret = genpd_lock_interruptible(genpd);
 	if (ret)
 		return -ERESTARTSYS;
 
@@ -1984,7 +2223,9 @@ static int pm_genpd_summary_one(struct s
 	}
 
 	list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
-		kobj_path = kobject_get_path(&pm_data->dev->kobj, GFP_KERNEL);
+		kobj_path = kobject_get_path(&pm_data->dev->kobj,
+				genpd_is_irq_safe(genpd) ?
+				GFP_ATOMIC : GFP_KERNEL);
 		if (kobj_path == NULL)
 			continue;
 
@@ -1995,7 +2236,7 @@ static int pm_genpd_summary_one(struct s
 
 	seq_puts(s, "\n");
 exit:
-	mutex_unlock(&genpd->lock);
+	genpd_unlock(genpd);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/main.c linux-libre-4.10-rc8-gnu/drivers/base/power/main.c
--- linux-libre-4.9-gnu/drivers/base/power/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -131,6 +131,7 @@ void device_pm_add(struct device *dev)
 		dev_warn(dev, "parent %s should not be sleeping\n",
 			dev_name(dev->parent));
 	list_add_tail(&dev->power.entry, &dpm_list);
+	dev->power.in_dpm_list = true;
 	mutex_unlock(&dpm_list_mtx);
 }
 
@@ -145,6 +146,7 @@ void device_pm_remove(struct device *dev
 	complete_all(&dev->power.completion);
 	mutex_lock(&dpm_list_mtx);
 	list_del_init(&dev->power.entry);
+	dev->power.in_dpm_list = false;
 	mutex_unlock(&dpm_list_mtx);
 	device_wakeup_disable(dev);
 	pm_runtime_remove(dev);
@@ -192,7 +194,7 @@ void device_pm_move_last(struct device *
 
 static ktime_t initcall_debug_start(struct device *dev)
 {
-	ktime_t calltime = ktime_set(0, 0);
+	ktime_t calltime = 0;
 
 	if (pm_print_times_enabled) {
 		pr_info("calling  %s+ @ %i, parent: %s\n",
@@ -244,6 +246,62 @@ static void dpm_wait_for_children(struct
        device_for_each_child(dev, &async, dpm_wait_fn);
 }
 
+static void dpm_wait_for_suppliers(struct device *dev, bool async)
+{
+	struct device_link *link;
+	int idx;
+
+	idx = device_links_read_lock();
+
+	/*
+	 * If the supplier goes away right after we've checked the link to it,
+	 * we'll wait for its completion to change the state, but that's fine,
+	 * because the only things that will block as a result are the SRCU
+	 * callbacks freeing the link objects for the links in the list we're
+	 * walking.
+	 */
+	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+		if (READ_ONCE(link->status) != DL_STATE_DORMANT)
+			dpm_wait(link->supplier, async);
+
+	device_links_read_unlock(idx);
+}
+
+static void dpm_wait_for_superior(struct device *dev, bool async)
+{
+	dpm_wait(dev->parent, async);
+	dpm_wait_for_suppliers(dev, async);
+}
+
+static void dpm_wait_for_consumers(struct device *dev, bool async)
+{
+	struct device_link *link;
+	int idx;
+
+	idx = device_links_read_lock();
+
+	/*
+	 * The status of a device link can only be changed from "dormant" by a
+	 * probe, but that cannot happen during system suspend/resume.  In
+	 * theory it can change to "dormant" at that time, but then it is
+	 * reasonable to wait for the target device anyway (eg. if it goes
+	 * away, it's better to wait for it to go away completely and then
+	 * continue instead of trying to continue in parallel with its
+	 * unregistration).
+	 */
+	list_for_each_entry_rcu(link, &dev->links.consumers, s_node)
+		if (READ_ONCE(link->status) != DL_STATE_DORMANT)
+			dpm_wait(link->consumer, async);
+
+	device_links_read_unlock(idx);
+}
+
+static void dpm_wait_for_subordinate(struct device *dev, bool async)
+{
+	dpm_wait_for_children(dev, async);
+	dpm_wait_for_consumers(dev, async);
+}
+
 /**
  * pm_op - Return the PM operation appropriate for given PM event.
  * @ops: PM operations to choose from.
@@ -488,7 +546,7 @@ static int device_resume_noirq(struct de
 	if (!dev->power.is_noirq_suspended)
 		goto Out;
 
-	dpm_wait(dev->parent, async);
+	dpm_wait_for_superior(dev, async);
 
 	if (dev->pm_domain) {
 		info = "noirq power domain ";
@@ -618,7 +676,7 @@ static int device_resume_early(struct de
 	if (!dev->power.is_late_suspended)
 		goto Out;
 
-	dpm_wait(dev->parent, async);
+	dpm_wait_for_superior(dev, async);
 
 	if (dev->pm_domain) {
 		info = "early power domain ";
@@ -750,7 +808,7 @@ static int device_resume(struct device *
 		goto Complete;
 	}
 
-	dpm_wait(dev->parent, async);
+	dpm_wait_for_superior(dev, async);
 	dpm_watchdog_set(&wd, dev);
 	device_lock(dev);
 
@@ -1027,7 +1085,7 @@ static int __device_suspend_noirq(struct
 	TRACE_DEVICE(dev);
 	TRACE_SUSPEND(0);
 
-	dpm_wait_for_children(dev, async);
+	dpm_wait_for_subordinate(dev, async);
 
 	if (async_error)
 		goto Complete;
@@ -1174,7 +1232,7 @@ static int __device_suspend_late(struct
 
 	__pm_runtime_disable(dev, false);
 
-	dpm_wait_for_children(dev, async);
+	dpm_wait_for_subordinate(dev, async);
 
 	if (async_error)
 		goto Complete;
@@ -1342,6 +1400,22 @@ static int legacy_suspend(struct device
 	return error;
 }
 
+static void dpm_clear_suppliers_direct_complete(struct device *dev)
+{
+	struct device_link *link;
+	int idx;
+
+	idx = device_links_read_lock();
+
+	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
+		spin_lock_irq(&link->supplier->power.lock);
+		link->supplier->power.direct_complete = false;
+		spin_unlock_irq(&link->supplier->power.lock);
+	}
+
+	device_links_read_unlock(idx);
+}
+
 /**
  * device_suspend - Execute "suspend" callbacks for given device.
  * @dev: Device to handle.
@@ -1358,7 +1432,7 @@ static int __device_suspend(struct devic
 	TRACE_DEVICE(dev);
 	TRACE_SUSPEND(0);
 
-	dpm_wait_for_children(dev, async);
+	dpm_wait_for_subordinate(dev, async);
 
 	if (async_error)
 		goto Complete;
@@ -1454,16 +1528,17 @@ static int __device_suspend(struct devic
 
 			spin_unlock_irq(&parent->power.lock);
 		}
+		dpm_clear_suppliers_direct_complete(dev);
 	}
 
 	device_unlock(dev);
 	dpm_watchdog_clear(&wd);
 
  Complete:
-	complete_all(&dev->power.completion);
 	if (error)
 		async_error = error;
 
+	complete_all(&dev->power.completion);
 	TRACE_SUSPEND(error);
 	return error;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/opp/core.c linux-libre-4.10-rc8-gnu/drivers/base/power/opp/core.c
--- linux-libre-4.9-gnu/drivers/base/power/opp/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/opp/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -93,6 +93,8 @@ struct opp_table *_find_opp_table(struct
  * Return: voltage in micro volt corresponding to the opp, else
  * return 0
  *
+ * This is useful only for devices with single power supply.
+ *
  * Locking: This function must be called under rcu_read_lock(). opp is a rcu
  * protected pointer. This means that opp which could have been fetched by
  * opp_find_freq_{exact,ceil,floor} functions is valid as long as we are
@@ -112,7 +114,7 @@ unsigned long dev_pm_opp_get_voltage(str
 	if (IS_ERR_OR_NULL(tmp_opp))
 		pr_err("%s: Invalid parameters\n", __func__);
 	else
-		v = tmp_opp->u_volt;
+		v = tmp_opp->supplies[0].u_volt;
 
 	return v;
 }
@@ -210,6 +212,24 @@ unsigned long dev_pm_opp_get_max_clock_l
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_get_max_clock_latency);
 
+static int _get_regulator_count(struct device *dev)
+{
+	struct opp_table *opp_table;
+	int count;
+
+	rcu_read_lock();
+
+	opp_table = _find_opp_table(dev);
+	if (!IS_ERR(opp_table))
+		count = opp_table->regulator_count;
+	else
+		count = 0;
+
+	rcu_read_unlock();
+
+	return count;
+}
+
 /**
  * dev_pm_opp_get_max_volt_latency() - Get max voltage latency in nanoseconds
  * @dev: device for which we do this operation
@@ -222,34 +242,51 @@ unsigned long dev_pm_opp_get_max_volt_la
 {
 	struct opp_table *opp_table;
 	struct dev_pm_opp *opp;
-	struct regulator *reg;
+	struct regulator *reg, **regulators;
 	unsigned long latency_ns = 0;
-	unsigned long min_uV = ~0, max_uV = 0;
-	int ret;
+	int ret, i, count;
+	struct {
+		unsigned long min;
+		unsigned long max;
+	} *uV;
+
+	count = _get_regulator_count(dev);
+
+	/* Regulator may not be required for the device */
+	if (!count)
+		return 0;
+
+	regulators = kmalloc_array(count, sizeof(*regulators), GFP_KERNEL);
+	if (!regulators)
+		return 0;
+
+	uV = kmalloc_array(count, sizeof(*uV), GFP_KERNEL);
+	if (!uV)
+		goto free_regulators;
 
 	rcu_read_lock();
 
 	opp_table = _find_opp_table(dev);
 	if (IS_ERR(opp_table)) {
 		rcu_read_unlock();
-		return 0;
+		goto free_uV;
 	}
 
-	reg = opp_table->regulator;
-	if (IS_ERR(reg)) {
-		/* Regulator may not be required for device */
-		rcu_read_unlock();
-		return 0;
-	}
+	memcpy(regulators, opp_table->regulators, count * sizeof(*regulators));
 
-	list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
-		if (!opp->available)
-			continue;
+	for (i = 0; i < count; i++) {
+		uV[i].min = ~0;
+		uV[i].max = 0;
 
-		if (opp->u_volt_min < min_uV)
-			min_uV = opp->u_volt_min;
-		if (opp->u_volt_max > max_uV)
-			max_uV = opp->u_volt_max;
+		list_for_each_entry_rcu(opp, &opp_table->opp_list, node) {
+			if (!opp->available)
+				continue;
+
+			if (opp->supplies[i].u_volt_min < uV[i].min)
+				uV[i].min = opp->supplies[i].u_volt_min;
+			if (opp->supplies[i].u_volt_max > uV[i].max)
+				uV[i].max = opp->supplies[i].u_volt_max;
+		}
 	}
 
 	rcu_read_unlock();
@@ -258,9 +295,16 @@ unsigned long dev_pm_opp_get_max_volt_la
 	 * The caller needs to ensure that opp_table (and hence the regulator)
 	 * isn't freed, while we are executing this routine.
 	 */
-	ret = regulator_set_voltage_time(reg, min_uV, max_uV);
-	if (ret > 0)
-		latency_ns = ret * 1000;
+	for (i = 0; reg = regulators[i], i < count; i++) {
+		ret = regulator_set_voltage_time(reg, uV[i].min, uV[i].max);
+		if (ret > 0)
+			latency_ns += ret * 1000;
+	}
+
+free_uV:
+	kfree(uV);
+free_regulators:
+	kfree(regulators);
 
 	return latency_ns;
 }
@@ -542,8 +586,7 @@ unlock:
 }
 
 static int _set_opp_voltage(struct device *dev, struct regulator *reg,
-			    unsigned long u_volt, unsigned long u_volt_min,
-			    unsigned long u_volt_max)
+			    struct dev_pm_opp_supply *supply)
 {
 	int ret;
 
@@ -554,14 +597,78 @@ static int _set_opp_voltage(struct devic
 		return 0;
 	}
 
-	dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__, u_volt_min,
-		u_volt, u_volt_max);
+	dev_dbg(dev, "%s: voltages (mV): %lu %lu %lu\n", __func__,
+		supply->u_volt_min, supply->u_volt, supply->u_volt_max);
 
-	ret = regulator_set_voltage_triplet(reg, u_volt_min, u_volt,
-					    u_volt_max);
+	ret = regulator_set_voltage_triplet(reg, supply->u_volt_min,
+					    supply->u_volt, supply->u_volt_max);
 	if (ret)
 		dev_err(dev, "%s: failed to set voltage (%lu %lu %lu mV): %d\n",
-			__func__, u_volt_min, u_volt, u_volt_max, ret);
+			__func__, supply->u_volt_min, supply->u_volt,
+			supply->u_volt_max, ret);
+
+	return ret;
+}
+
+static inline int
+_generic_set_opp_clk_only(struct device *dev, struct clk *clk,
+			  unsigned long old_freq, unsigned long freq)
+{
+	int ret;
+
+	ret = clk_set_rate(clk, freq);
+	if (ret) {
+		dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
+			ret);
+	}
+
+	return ret;
+}
+
+static int _generic_set_opp(struct dev_pm_set_opp_data *data)
+{
+	struct dev_pm_opp_supply *old_supply = data->old_opp.supplies;
+	struct dev_pm_opp_supply *new_supply = data->new_opp.supplies;
+	unsigned long old_freq = data->old_opp.rate, freq = data->new_opp.rate;
+	struct regulator *reg = data->regulators[0];
+	struct device *dev= data->dev;
+	int ret;
+
+	/* This function only supports single regulator per device */
+	if (WARN_ON(data->regulator_count > 1)) {
+		dev_err(dev, "multiple regulators are not supported\n");
+		return -EINVAL;
+	}
+
+	/* Scaling up? Scale voltage before frequency */
+	if (freq > old_freq) {
+		ret = _set_opp_voltage(dev, reg, new_supply);
+		if (ret)
+			goto restore_voltage;
+	}
+
+	/* Change frequency */
+	ret = _generic_set_opp_clk_only(dev, data->clk, old_freq, freq);
+	if (ret)
+		goto restore_voltage;
+
+	/* Scaling down? Scale voltage after frequency */
+	if (freq < old_freq) {
+		ret = _set_opp_voltage(dev, reg, new_supply);
+		if (ret)
+			goto restore_freq;
+	}
+
+	return 0;
+
+restore_freq:
+	if (_generic_set_opp_clk_only(dev, data->clk, freq, old_freq))
+		dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
+			__func__, old_freq);
+restore_voltage:
+	/* This shouldn't harm even if the voltages weren't updated earlier */
+	if (old_supply->u_volt)
+		_set_opp_voltage(dev, reg, old_supply);
 
 	return ret;
 }
@@ -579,12 +686,13 @@ static int _set_opp_voltage(struct devic
 int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
 {
 	struct opp_table *opp_table;
+	unsigned long freq, old_freq;
+	int (*set_opp)(struct dev_pm_set_opp_data *data);
 	struct dev_pm_opp *old_opp, *opp;
-	struct regulator *reg;
+	struct regulator **regulators;
+	struct dev_pm_set_opp_data *data;
 	struct clk *clk;
-	unsigned long freq, old_freq;
-	unsigned long u_volt, u_volt_min, u_volt_max;
-	int ret;
+	int ret, size;
 
 	if (unlikely(!target_freq)) {
 		dev_err(dev, "%s: Invalid target frequency %lu\n", __func__,
@@ -633,55 +741,41 @@ int dev_pm_opp_set_rate(struct device *d
 		return ret;
 	}
 
-	u_volt = opp->u_volt;
-	u_volt_min = opp->u_volt_min;
-	u_volt_max = opp->u_volt_max;
-
-	reg = opp_table->regulator;
+	dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n", __func__,
+		old_freq, freq);
 
-	rcu_read_unlock();
+	regulators = opp_table->regulators;
 
-	/* Scaling up? Scale voltage before frequency */
-	if (freq > old_freq) {
-		ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
-				       u_volt_max);
-		if (ret)
-			goto restore_voltage;
+	/* Only frequency scaling */
+	if (!regulators) {
+		rcu_read_unlock();
+		return _generic_set_opp_clk_only(dev, clk, old_freq, freq);
 	}
 
-	/* Change frequency */
-
-	dev_dbg(dev, "%s: switching OPP: %lu Hz --> %lu Hz\n",
-		__func__, old_freq, freq);
+	if (opp_table->set_opp)
+		set_opp = opp_table->set_opp;
+	else
+		set_opp = _generic_set_opp;
 
-	ret = clk_set_rate(clk, freq);
-	if (ret) {
-		dev_err(dev, "%s: failed to set clock rate: %d\n", __func__,
-			ret);
-		goto restore_voltage;
-	}
+	data = opp_table->set_opp_data;
+	data->regulators = regulators;
+	data->regulator_count = opp_table->regulator_count;
+	data->clk = clk;
+	data->dev = dev;
 
-	/* Scaling down? Scale voltage after frequency */
-	if (freq < old_freq) {
-		ret = _set_opp_voltage(dev, reg, u_volt, u_volt_min,
-				       u_volt_max);
-		if (ret)
-			goto restore_freq;
-	}
+	data->old_opp.rate = old_freq;
+	size = sizeof(*opp->supplies) * opp_table->regulator_count;
+	if (IS_ERR(old_opp))
+		memset(data->old_opp.supplies, 0, size);
+	else
+		memcpy(data->old_opp.supplies, old_opp->supplies, size);
 
-	return 0;
+	data->new_opp.rate = freq;
+	memcpy(data->new_opp.supplies, opp->supplies, size);
 
-restore_freq:
-	if (clk_set_rate(clk, old_freq))
-		dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n",
-			__func__, old_freq);
-restore_voltage:
-	/* This shouldn't harm even if the voltages weren't updated earlier */
-	if (!IS_ERR(old_opp))
-		_set_opp_voltage(dev, reg, old_opp->u_volt,
-				 old_opp->u_volt_min, old_opp->u_volt_max);
+	rcu_read_unlock();
 
-	return ret;
+	return set_opp(data);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_set_rate);
 
@@ -764,9 +858,6 @@ static struct opp_table *_add_opp_table(
 
 	_of_init_opp_table(opp_table, dev);
 
-	/* Set regulator to a non-NULL error value */
-	opp_table->regulator = ERR_PTR(-ENXIO);
-
 	/* Find clk for the device */
 	opp_table->clk = clk_get(dev, NULL);
 	if (IS_ERR(opp_table->clk)) {
@@ -815,7 +906,10 @@ static void _remove_opp_table(struct opp
 	if (opp_table->prop_name)
 		return;
 
-	if (!IS_ERR(opp_table->regulator))
+	if (opp_table->regulators)
+		return;
+
+	if (opp_table->set_opp)
 		return;
 
 	/* Release clk */
@@ -924,34 +1018,50 @@ struct dev_pm_opp *_allocate_opp(struct
 				 struct opp_table **opp_table)
 {
 	struct dev_pm_opp *opp;
+	int count, supply_size;
+	struct opp_table *table;
 
-	/* allocate new OPP node */
-	opp = kzalloc(sizeof(*opp), GFP_KERNEL);
-	if (!opp)
+	table = _add_opp_table(dev);
+	if (!table)
 		return NULL;
 
-	INIT_LIST_HEAD(&opp->node);
+	/* Allocate space for at least one supply */
+	count = table->regulator_count ? table->regulator_count : 1;
+	supply_size = sizeof(*opp->supplies) * count;
 
-	*opp_table = _add_opp_table(dev);
-	if (!*opp_table) {
-		kfree(opp);
+	/* allocate new OPP node and supplies structures */
+	opp = kzalloc(sizeof(*opp) + supply_size, GFP_KERNEL);
+	if (!opp) {
+		kfree(table);
 		return NULL;
 	}
 
+	/* Put the supplies at the end of the OPP structure as an empty array */
+	opp->supplies = (struct dev_pm_opp_supply *)(opp + 1);
+	INIT_LIST_HEAD(&opp->node);
+
+	*opp_table = table;
+
 	return opp;
 }
 
 static bool _opp_supported_by_regulators(struct dev_pm_opp *opp,
 					 struct opp_table *opp_table)
 {
-	struct regulator *reg = opp_table->regulator;
+	struct regulator *reg;
+	int i;
 
-	if (!IS_ERR(reg) &&
-	    !regulator_is_supported_voltage(reg, opp->u_volt_min,
-					    opp->u_volt_max)) {
-		pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
-			__func__, opp->u_volt_min, opp->u_volt_max);
-		return false;
+	for (i = 0; i < opp_table->regulator_count; i++) {
+		reg = opp_table->regulators[i];
+
+		if (!regulator_is_supported_voltage(reg,
+					opp->supplies[i].u_volt_min,
+					opp->supplies[i].u_volt_max)) {
+			pr_warn("%s: OPP minuV: %lu maxuV: %lu, not supported by regulator\n",
+				__func__, opp->supplies[i].u_volt_min,
+				opp->supplies[i].u_volt_max);
+			return false;
+		}
 	}
 
 	return true;
@@ -983,11 +1093,13 @@ int _opp_add(struct device *dev, struct
 
 		/* Duplicate OPPs */
 		dev_warn(dev, "%s: duplicate OPPs detected. Existing: freq: %lu, volt: %lu, enabled: %d. New: freq: %lu, volt: %lu, enabled: %d\n",
-			 __func__, opp->rate, opp->u_volt, opp->available,
-			 new_opp->rate, new_opp->u_volt, new_opp->available);
+			 __func__, opp->rate, opp->supplies[0].u_volt,
+			 opp->available, new_opp->rate,
+			 new_opp->supplies[0].u_volt, new_opp->available);
 
-		return opp->available && new_opp->u_volt == opp->u_volt ?
-			0 : -EEXIST;
+		/* Should we compare voltages for all regulators here ? */
+		return opp->available &&
+		       new_opp->supplies[0].u_volt == opp->supplies[0].u_volt ? 0 : -EEXIST;
 	}
 
 	new_opp->opp_table = opp_table;
@@ -1054,9 +1166,9 @@ int _opp_add_v1(struct device *dev, unsi
 	/* populate the opp table */
 	new_opp->rate = freq;
 	tol = u_volt * opp_table->voltage_tolerance_v1 / 100;
-	new_opp->u_volt = u_volt;
-	new_opp->u_volt_min = u_volt - tol;
-	new_opp->u_volt_max = u_volt + tol;
+	new_opp->supplies[0].u_volt = u_volt;
+	new_opp->supplies[0].u_volt_min = u_volt - tol;
+	new_opp->supplies[0].u_volt_max = u_volt + tol;
 	new_opp->available = true;
 	new_opp->dynamic = dynamic;
 
@@ -1300,13 +1412,47 @@ unlock:
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
 
+static int _allocate_set_opp_data(struct opp_table *opp_table)
+{
+	struct dev_pm_set_opp_data *data;
+	int len, count = opp_table->regulator_count;
+
+	if (WARN_ON(!count))
+		return -EINVAL;
+
+	/* space for set_opp_data */
+	len = sizeof(*data);
+
+	/* space for old_opp.supplies and new_opp.supplies */
+	len += 2 * sizeof(struct dev_pm_opp_supply) * count;
+
+	data = kzalloc(len, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->old_opp.supplies = (void *)(data + 1);
+	data->new_opp.supplies = data->old_opp.supplies + count;
+
+	opp_table->set_opp_data = data;
+
+	return 0;
+}
+
+static void _free_set_opp_data(struct opp_table *opp_table)
+{
+	kfree(opp_table->set_opp_data);
+	opp_table->set_opp_data = NULL;
+}
+
 /**
- * dev_pm_opp_set_regulator() - Set regulator name for the device
+ * dev_pm_opp_set_regulators() - Set regulator names for the device
  * @dev: Device for which regulator name is being set.
- * @name: Name of the regulator.
+ * @names: Array of pointers to the names of the regulator.
+ * @count: Number of regulators.
  *
  * In order to support OPP switching, OPP layer needs to know the name of the
- * device's regulator, as the core would be required to switch voltages as well.
+ * device's regulators, as the core would be required to switch voltages as
+ * well.
  *
  * This must be called before any OPPs are initialized for the device.
  *
@@ -1316,11 +1462,13 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_na
  * that this function is *NOT* called under RCU protection or in contexts where
  * mutex cannot be locked.
  */
-int dev_pm_opp_set_regulator(struct device *dev, const char *name)
+struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
+					    const char * const names[],
+					    unsigned int count)
 {
 	struct opp_table *opp_table;
 	struct regulator *reg;
-	int ret;
+	int ret, i;
 
 	mutex_lock(&opp_table_lock);
 
@@ -1336,22 +1484,146 @@ int dev_pm_opp_set_regulator(struct devi
 		goto err;
 	}
 
-	/* Already have a regulator set */
-	if (WARN_ON(!IS_ERR(opp_table->regulator))) {
+	/* Already have regulators set */
+	if (opp_table->regulators) {
 		ret = -EBUSY;
 		goto err;
 	}
-	/* Allocate the regulator */
-	reg = regulator_get_optional(dev, name);
-	if (IS_ERR(reg)) {
-		ret = PTR_ERR(reg);
-		if (ret != -EPROBE_DEFER)
-			dev_err(dev, "%s: no regulator (%s) found: %d\n",
-				__func__, name, ret);
+
+	opp_table->regulators = kmalloc_array(count,
+					      sizeof(*opp_table->regulators),
+					      GFP_KERNEL);
+	if (!opp_table->regulators) {
+		ret = -ENOMEM;
 		goto err;
 	}
 
-	opp_table->regulator = reg;
+	for (i = 0; i < count; i++) {
+		reg = regulator_get_optional(dev, names[i]);
+		if (IS_ERR(reg)) {
+			ret = PTR_ERR(reg);
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "%s: no regulator (%s) found: %d\n",
+					__func__, names[i], ret);
+			goto free_regulators;
+		}
+
+		opp_table->regulators[i] = reg;
+	}
+
+	opp_table->regulator_count = count;
+
+	/* Allocate block only once to pass to set_opp() routines */
+	ret = _allocate_set_opp_data(opp_table);
+	if (ret)
+		goto free_regulators;
+
+	mutex_unlock(&opp_table_lock);
+	return opp_table;
+
+free_regulators:
+	while (i != 0)
+		regulator_put(opp_table->regulators[--i]);
+
+	kfree(opp_table->regulators);
+	opp_table->regulators = NULL;
+	opp_table->regulator_count = 0;
+err:
+	_remove_opp_table(opp_table);
+unlock:
+	mutex_unlock(&opp_table_lock);
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulators);
+
+/**
+ * dev_pm_opp_put_regulators() - Releases resources blocked for regulator
+ * @opp_table: OPP table returned from dev_pm_opp_set_regulators().
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_put_regulators(struct opp_table *opp_table)
+{
+	int i;
+
+	mutex_lock(&opp_table_lock);
+
+	if (!opp_table->regulators) {
+		pr_err("%s: Doesn't have regulators set\n", __func__);
+		goto unlock;
+	}
+
+	/* Make sure there are no concurrent readers while updating opp_table */
+	WARN_ON(!list_empty(&opp_table->opp_list));
+
+	for (i = opp_table->regulator_count - 1; i >= 0; i--)
+		regulator_put(opp_table->regulators[i]);
+
+	_free_set_opp_data(opp_table);
+
+	kfree(opp_table->regulators);
+	opp_table->regulators = NULL;
+	opp_table->regulator_count = 0;
+
+	/* Try freeing opp_table if this was the last blocking resource */
+	_remove_opp_table(opp_table);
+
+unlock:
+	mutex_unlock(&opp_table_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulators);
+
+/**
+ * dev_pm_opp_register_set_opp_helper() - Register custom set OPP helper
+ * @dev: Device for which the helper is getting registered.
+ * @set_opp: Custom set OPP helper.
+ *
+ * This is useful to support complex platforms (like platforms with multiple
+ * regulators per device), instead of the generic OPP set rate helper.
+ *
+ * This must be called before any OPPs are initialized for the device.
+ *
+ * Locking: The internal opp_table and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_register_set_opp_helper(struct device *dev,
+			int (*set_opp)(struct dev_pm_set_opp_data *data))
+{
+	struct opp_table *opp_table;
+	int ret;
+
+	if (!set_opp)
+		return -EINVAL;
+
+	mutex_lock(&opp_table_lock);
+
+	opp_table = _add_opp_table(dev);
+	if (!opp_table) {
+		ret = -ENOMEM;
+		goto unlock;
+	}
+
+	/* This should be called before OPPs are initialized */
+	if (WARN_ON(!list_empty(&opp_table->opp_list))) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	/* Already have custom set_opp helper */
+	if (WARN_ON(opp_table->set_opp)) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	opp_table->set_opp = set_opp;
 
 	mutex_unlock(&opp_table_lock);
 	return 0;
@@ -1363,11 +1635,12 @@ unlock:
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulator);
+EXPORT_SYMBOL_GPL(dev_pm_opp_register_set_opp_helper);
 
 /**
- * dev_pm_opp_put_regulator() - Releases resources blocked for regulator
- * @dev: Device for which regulator was set.
+ * dev_pm_opp_register_put_opp_helper() - Releases resources blocked for
+ *					   set_opp helper
+ * @dev: Device for which custom set_opp helper has to be cleared.
  *
  * Locking: The internal opp_table and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
@@ -1375,7 +1648,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_set_regulat
  * that this function is *NOT* called under RCU protection or in contexts where
  * mutex cannot be locked.
  */
-void dev_pm_opp_put_regulator(struct device *dev)
+void dev_pm_opp_register_put_opp_helper(struct device *dev)
 {
 	struct opp_table *opp_table;
 
@@ -1389,16 +1662,16 @@ void dev_pm_opp_put_regulator(struct dev
 		goto unlock;
 	}
 
-	if (IS_ERR(opp_table->regulator)) {
-		dev_err(dev, "%s: Doesn't have regulator set\n", __func__);
+	if (!opp_table->set_opp) {
+		dev_err(dev, "%s: Doesn't have custom set_opp helper set\n",
+			__func__);
 		goto unlock;
 	}
 
 	/* Make sure there are no concurrent readers while updating opp_table */
 	WARN_ON(!list_empty(&opp_table->opp_list));
 
-	regulator_put(opp_table->regulator);
-	opp_table->regulator = ERR_PTR(-ENXIO);
+	opp_table->set_opp = NULL;
 
 	/* Try freeing opp_table if this was the last blocking resource */
 	_remove_opp_table(opp_table);
@@ -1406,7 +1679,7 @@ void dev_pm_opp_put_regulator(struct dev
 unlock:
 	mutex_unlock(&opp_table_lock);
 }
-EXPORT_SYMBOL_GPL(dev_pm_opp_put_regulator);
+EXPORT_SYMBOL_GPL(dev_pm_opp_register_put_opp_helper);
 
 /**
  * dev_pm_opp_add()  - Add an OPP table from a table definitions
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/opp/debugfs.c linux-libre-4.10-rc8-gnu/drivers/base/power/opp/debugfs.c
--- linux-libre-4.9-gnu/drivers/base/power/opp/debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/opp/debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/limits.h>
+#include <linux/slab.h>
 
 #include "opp.h"
 
@@ -34,6 +35,46 @@ void opp_debug_remove_one(struct dev_pm_
 	debugfs_remove_recursive(opp->dentry);
 }
 
+static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
+				      struct opp_table *opp_table,
+				      struct dentry *pdentry)
+{
+	struct dentry *d;
+	int i = 0;
+	char *name;
+
+	/* Always create at least supply-0 directory */
+	do {
+		name = kasprintf(GFP_KERNEL, "supply-%d", i);
+
+		/* Create per-opp directory */
+		d = debugfs_create_dir(name, pdentry);
+
+		kfree(name);
+
+		if (!d)
+			return false;
+
+		if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d,
+					  &opp->supplies[i].u_volt))
+			return false;
+
+		if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d,
+					  &opp->supplies[i].u_volt_min))
+			return false;
+
+		if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d,
+					  &opp->supplies[i].u_volt_max))
+			return false;
+
+		if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
+					  &opp->supplies[i].u_amp))
+			return false;
+	} while (++i < opp_table->regulator_count);
+
+	return true;
+}
+
 int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
 {
 	struct dentry *pdentry = opp_table->dentry;
@@ -63,16 +104,7 @@ int opp_debug_create_one(struct dev_pm_o
 	if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate))
 		return -ENOMEM;
 
-	if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->u_volt))
-		return -ENOMEM;
-
-	if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->u_volt_min))
-		return -ENOMEM;
-
-	if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->u_volt_max))
-		return -ENOMEM;
-
-	if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->u_amp))
+	if (!opp_debug_create_supplies(opp, opp_table, d))
 		return -ENOMEM;
 
 	if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/opp/of.c linux-libre-4.10-rc8-gnu/drivers/base/power/opp/of.c
--- linux-libre-4.9-gnu/drivers/base/power/opp/of.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/opp/of.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/device.h>
 #include <linux/of.h>
+#include <linux/slab.h>
 #include <linux/export.h>
 
 #include "opp.h"
@@ -101,16 +102,16 @@ static bool _opp_is_supported(struct dev
 	return true;
 }
 
-/* TODO: Support multiple regulators */
 static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
 			      struct opp_table *opp_table)
 {
-	u32 microvolt[3] = {0};
-	u32 val;
-	int count, ret;
+	u32 *microvolt, *microamp = NULL;
+	int supplies, vcount, icount, ret, i, j;
 	struct property *prop = NULL;
 	char name[NAME_MAX];
 
+	supplies = opp_table->regulator_count ? opp_table->regulator_count : 1;
+
 	/* Search for "opp-microvolt-<name>" */
 	if (opp_table->prop_name) {
 		snprintf(name, sizeof(name), "opp-microvolt-%s",
@@ -128,34 +129,29 @@ static int opp_parse_supplies(struct dev
 			return 0;
 	}
 
-	count = of_property_count_u32_elems(opp->np, name);
-	if (count < 0) {
+	vcount = of_property_count_u32_elems(opp->np, name);
+	if (vcount < 0) {
 		dev_err(dev, "%s: Invalid %s property (%d)\n",
-			__func__, name, count);
-		return count;
+			__func__, name, vcount);
+		return vcount;
 	}
 
-	/* There can be one or three elements here */
-	if (count != 1 && count != 3) {
-		dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",
-			__func__, name, count);
+	/* There can be one or three elements per supply */
+	if (vcount != supplies && vcount != supplies * 3) {
+		dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
+			__func__, name, vcount, supplies);
 		return -EINVAL;
 	}
 
-	ret = of_property_read_u32_array(opp->np, name, microvolt, count);
+	microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL);
+	if (!microvolt)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
 	if (ret) {
 		dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
-		return -EINVAL;
-	}
-
-	opp->u_volt = microvolt[0];
-
-	if (count == 1) {
-		opp->u_volt_min = opp->u_volt;
-		opp->u_volt_max = opp->u_volt;
-	} else {
-		opp->u_volt_min = microvolt[1];
-		opp->u_volt_max = microvolt[2];
+		ret = -EINVAL;
+		goto free_microvolt;
 	}
 
 	/* Search for "opp-microamp-<name>" */
@@ -172,10 +168,59 @@ static int opp_parse_supplies(struct dev
 		prop = of_find_property(opp->np, name, NULL);
 	}
 
-	if (prop && !of_property_read_u32(opp->np, name, &val))
-		opp->u_amp = val;
+	if (prop) {
+		icount = of_property_count_u32_elems(opp->np, name);
+		if (icount < 0) {
+			dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
+				name, icount);
+			ret = icount;
+			goto free_microvolt;
+		}
 
-	return 0;
+		if (icount != supplies) {
+			dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n",
+				__func__, name, icount, supplies);
+			ret = -EINVAL;
+			goto free_microvolt;
+		}
+
+		microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL);
+		if (!microamp) {
+			ret = -EINVAL;
+			goto free_microvolt;
+		}
+
+		ret = of_property_read_u32_array(opp->np, name, microamp,
+						 icount);
+		if (ret) {
+			dev_err(dev, "%s: error parsing %s: %d\n", __func__,
+				name, ret);
+			ret = -EINVAL;
+			goto free_microamp;
+		}
+	}
+
+	for (i = 0, j = 0; i < supplies; i++) {
+		opp->supplies[i].u_volt = microvolt[j++];
+
+		if (vcount == supplies) {
+			opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
+			opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
+		} else {
+			opp->supplies[i].u_volt_min = microvolt[j++];
+			opp->supplies[i].u_volt_max = microvolt[j++];
+		}
+
+		if (microamp)
+			opp->supplies[i].u_amp = microamp[i];
+	}
+
+free_microamp:
+	kfree(microamp);
+free_microvolt:
+	kfree(microvolt);
+
+	return ret;
 }
 
 /**
@@ -198,7 +243,7 @@ void dev_pm_opp_of_remove_table(struct d
 EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
 
 /* Returns opp descriptor node for a device, caller must do of_node_put() */
-struct device_node *_of_get_opp_desc_node(struct device *dev)
+static struct device_node *_of_get_opp_desc_node(struct device *dev)
 {
 	/*
 	 * TODO: Support for multiple OPP tables.
@@ -303,9 +348,9 @@ static int _opp_add_static_v2(struct dev
 	mutex_unlock(&opp_table_lock);
 
 	pr_debug("%s: turbo:%d rate:%lu uv:%lu uvmin:%lu uvmax:%lu latency:%lu\n",
-		 __func__, new_opp->turbo, new_opp->rate, new_opp->u_volt,
-		 new_opp->u_volt_min, new_opp->u_volt_max,
-		 new_opp->clock_latency_ns);
+		 __func__, new_opp->turbo, new_opp->rate,
+		 new_opp->supplies[0].u_volt, new_opp->supplies[0].u_volt_min,
+		 new_opp->supplies[0].u_volt_max, new_opp->clock_latency_ns);
 
 	/*
 	 * Notify the changes in the availability of the operable
@@ -562,7 +607,7 @@ int dev_pm_opp_of_get_sharing_cpus(struc
 	/* Get OPP descriptor node */
 	np = _of_get_opp_desc_node(cpu_dev);
 	if (!np) {
-		dev_dbg(cpu_dev, "%s: Couldn't find cpu_dev node.\n", __func__);
+		dev_dbg(cpu_dev, "%s: Couldn't find opp node.\n", __func__);
 		return -ENOENT;
 	}
 
@@ -587,7 +632,7 @@ int dev_pm_opp_of_get_sharing_cpus(struc
 		/* Get OPP descriptor node */
 		tmp_np = _of_get_opp_desc_node(tcpu_dev);
 		if (!tmp_np) {
-			dev_err(tcpu_dev, "%s: Couldn't find tcpu_dev node.\n",
+			dev_err(tcpu_dev, "%s: Couldn't find opp node.\n",
 				__func__);
 			ret = -ENOENT;
 			goto put_cpu_node;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/opp/opp.h linux-libre-4.10-rc8-gnu/drivers/base/power/opp/opp.h
--- linux-libre-4.9-gnu/drivers/base/power/opp/opp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/opp/opp.h	2017-02-12 16:03:20.000000000 -0500
@@ -61,10 +61,7 @@ extern struct list_head opp_tables;
  * @turbo:	true if turbo (boost) OPP
  * @suspend:	true if suspend OPP
  * @rate:	Frequency in hertz
- * @u_volt:	Target voltage in microvolts corresponding to this OPP
- * @u_volt_min:	Minimum voltage in microvolts corresponding to this OPP
- * @u_volt_max:	Maximum voltage in microvolts corresponding to this OPP
- * @u_amp:	Maximum current drawn by the device in microamperes
+ * @supplies:	Power supplies voltage/current values
  * @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
  *		frequency from any other OPP's frequency.
  * @opp_table:	points back to the opp_table struct this opp belongs to
@@ -83,10 +80,8 @@ struct dev_pm_opp {
 	bool suspend;
 	unsigned long rate;
 
-	unsigned long u_volt;
-	unsigned long u_volt_min;
-	unsigned long u_volt_max;
-	unsigned long u_amp;
+	struct dev_pm_opp_supply *supplies;
+
 	unsigned long clock_latency_ns;
 
 	struct opp_table *opp_table;
@@ -144,7 +139,10 @@ enum opp_table_access {
  * @supported_hw_count: Number of elements in supported_hw array.
  * @prop_name: A name to postfix to many DT properties, while parsing them.
  * @clk: Device's clock handle
- * @regulator: Supply regulator
+ * @regulators: Supply regulators
+ * @regulator_count: Number of power supply regulators
+ * @set_opp: Platform specific set_opp callback
+ * @set_opp_data: Data to be passed to set_opp callback
  * @dentry:	debugfs dentry pointer of the real device directory (not links).
  * @dentry_name: Name of the real dentry.
  *
@@ -179,7 +177,11 @@ struct opp_table {
 	unsigned int supported_hw_count;
 	const char *prop_name;
 	struct clk *clk;
-	struct regulator *regulator;
+	struct regulator **regulators;
+	unsigned int regulator_count;
+
+	int (*set_opp)(struct dev_pm_set_opp_data *data);
+	struct dev_pm_set_opp_data *set_opp_data;
 
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *dentry;
@@ -190,7 +192,6 @@ struct opp_table {
 /* Routines internal to opp core */
 struct opp_table *_find_opp_table(struct device *dev);
 struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
-struct device_node *_of_get_opp_desc_node(struct device *dev);
 void _dev_pm_opp_remove_table(struct device *dev, bool remove_all);
 struct dev_pm_opp *_allocate_opp(struct device *dev, struct opp_table **opp_table);
 int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, struct opp_table *opp_table);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/power.h linux-libre-4.10-rc8-gnu/drivers/base/power/power.h
--- linux-libre-4.9-gnu/drivers/base/power/power.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/power.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,14 +21,22 @@ extern void pm_runtime_init(struct devic
 extern void pm_runtime_reinit(struct device *dev);
 extern void pm_runtime_remove(struct device *dev);
 
+#define WAKE_IRQ_DEDICATED_ALLOCATED	BIT(0)
+#define WAKE_IRQ_DEDICATED_MANAGED	BIT(1)
+#define WAKE_IRQ_DEDICATED_MASK		(WAKE_IRQ_DEDICATED_ALLOCATED | \
+					 WAKE_IRQ_DEDICATED_MANAGED)
+
 struct wake_irq {
 	struct device *dev;
+	unsigned int status;
 	int irq;
-	bool dedicated_irq:1;
 };
 
 extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
 extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
+extern void dev_pm_enable_wake_irq_check(struct device *dev,
+					 bool can_change_status);
+extern void dev_pm_disable_wake_irq_check(struct device *dev);
 
 #ifdef CONFIG_PM_SLEEP
 
@@ -104,6 +112,15 @@ static inline void dev_pm_disarm_wake_ir
 {
 }
 
+static inline void dev_pm_enable_wake_irq_check(struct device *dev,
+						bool can_change_status)
+{
+}
+
+static inline void dev_pm_disable_wake_irq_check(struct device *dev)
+{
+}
+
 #endif
 
 #ifdef CONFIG_PM_SLEEP
@@ -127,6 +144,11 @@ extern void device_pm_move_after(struct
 extern void device_pm_move_last(struct device *);
 extern void device_pm_check_callbacks(struct device *dev);
 
+static inline bool device_pm_initialized(struct device *dev)
+{
+	return dev->power.in_dpm_list;
+}
+
 #else /* !CONFIG_PM_SLEEP */
 
 static inline void device_pm_sleep_init(struct device *dev) {}
@@ -146,6 +168,11 @@ static inline void device_pm_move_last(s
 
 static inline void device_pm_check_callbacks(struct device *dev) {}
 
+static inline bool device_pm_initialized(struct device *dev)
+{
+	return device_is_registered(dev);
+}
+
 #endif /* !CONFIG_PM_SLEEP */
 
 static inline void device_pm_init(struct device *dev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/qos.c linux-libre-4.10-rc8-gnu/drivers/base/power/qos.c
--- linux-libre-4.9-gnu/drivers/base/power/qos.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/qos.c	2017-02-12 16:03:20.000000000 -0500
@@ -856,7 +856,10 @@ int dev_pm_qos_update_user_latency_toler
 		struct dev_pm_qos_request *req;
 
 		if (val < 0) {
-			ret = -EINVAL;
+			if (val == PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT)
+				ret = 0;
+			else
+				ret = -EINVAL;
 			goto out;
 		}
 		req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -883,6 +886,7 @@ int dev_pm_qos_update_user_latency_toler
 	mutex_unlock(&dev_pm_qos_mtx);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dev_pm_qos_update_user_latency_tolerance);
 
 /**
  * dev_pm_qos_expose_latency_tolerance - Expose latency tolerance to userspace
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/runtime.c linux-libre-4.10-rc8-gnu/drivers/base/power/runtime.c
--- linux-libre-4.9-gnu/drivers/base/power/runtime.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/runtime.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_wakeirq.h>
 #include <trace/events/rpm.h>
+
+#include "../base.h"
 #include "power.h"
 
 typedef int (*pm_callback_t)(struct device *);
@@ -241,7 +243,8 @@ static int rpm_check_suspend_allowed(str
 		retval = -EACCES;
 	else if (atomic_read(&dev->power.usage_count) > 0)
 		retval = -EAGAIN;
-	else if (!pm_children_suspended(dev))
+	else if (!dev->power.ignore_children &&
+			atomic_read(&dev->power.child_count))
 		retval = -EBUSY;
 
 	/* Pending resume requests take precedence over suspends. */
@@ -258,6 +261,42 @@ static int rpm_check_suspend_allowed(str
 	return retval;
 }
 
+static int rpm_get_suppliers(struct device *dev)
+{
+	struct device_link *link;
+
+	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
+		int retval;
+
+		if (!(link->flags & DL_FLAG_PM_RUNTIME))
+			continue;
+
+		if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND ||
+		    link->rpm_active)
+			continue;
+
+		retval = pm_runtime_get_sync(link->supplier);
+		if (retval < 0) {
+			pm_runtime_put_noidle(link->supplier);
+			return retval;
+		}
+		link->rpm_active = true;
+	}
+	return 0;
+}
+
+static void rpm_put_suppliers(struct device *dev)
+{
+	struct device_link *link;
+
+	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+		if (link->rpm_active &&
+		    READ_ONCE(link->status) != DL_STATE_SUPPLIER_UNBIND) {
+			pm_runtime_put(link->supplier);
+			link->rpm_active = false;
+		}
+}
+
 /**
  * __rpm_callback - Run a given runtime PM callback for a given device.
  * @cb: Runtime PM callback to run.
@@ -266,19 +305,57 @@ static int rpm_check_suspend_allowed(str
 static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
 	__releases(&dev->power.lock) __acquires(&dev->power.lock)
 {
-	int retval;
+	int retval, idx;
+	bool use_links = dev->power.links_count > 0;
 
-	if (dev->power.irq_safe)
+	if (dev->power.irq_safe) {
 		spin_unlock(&dev->power.lock);
-	else
+	} else {
 		spin_unlock_irq(&dev->power.lock);
 
+		/*
+		 * Resume suppliers if necessary.
+		 *
+		 * The device's runtime PM status cannot change until this
+		 * routine returns, so it is safe to read the status outside of
+		 * the lock.
+		 */
+		if (use_links && dev->power.runtime_status == RPM_RESUMING) {
+			idx = device_links_read_lock();
+
+			retval = rpm_get_suppliers(dev);
+			if (retval)
+				goto fail;
+
+			device_links_read_unlock(idx);
+		}
+	}
+
 	retval = cb(dev);
 
-	if (dev->power.irq_safe)
+	if (dev->power.irq_safe) {
 		spin_lock(&dev->power.lock);
-	else
+	} else {
+		/*
+		 * If the device is suspending and the callback has returned
+		 * success, drop the usage counters of the suppliers that have
+		 * been reference counted on its resume.
+		 *
+		 * Do that if resume fails too.
+		 */
+		if (use_links
+		    && ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
+		    || (dev->power.runtime_status == RPM_RESUMING && retval))) {
+			idx = device_links_read_lock();
+
+ fail:
+			rpm_put_suppliers(dev);
+
+			device_links_read_unlock(idx);
+		}
+
 		spin_lock_irq(&dev->power.lock);
+	}
 
 	return retval;
 }
@@ -515,7 +592,7 @@ static int rpm_suspend(struct device *de
 
 	callback = RPM_GET_CALLBACK(dev, runtime_suspend);
 
-	dev_pm_enable_wake_irq(dev);
+	dev_pm_enable_wake_irq_check(dev, true);
 	retval = rpm_callback(callback, dev);
 	if (retval)
 		goto fail;
@@ -554,7 +631,7 @@ static int rpm_suspend(struct device *de
 	return retval;
 
  fail:
-	dev_pm_disable_wake_irq(dev);
+	dev_pm_disable_wake_irq_check(dev);
 	__update_runtime_status(dev, RPM_ACTIVE);
 	dev->power.deferred_resume = false;
 	wake_up_all(&dev->power.wait_queue);
@@ -712,8 +789,8 @@ static int rpm_resume(struct device *dev
 
 		spin_lock(&parent->power.lock);
 		/*
-		 * We can resume if the parent's runtime PM is disabled or it
-		 * is set to ignore children.
+		 * Resume the parent if it has runtime PM enabled and not been
+		 * set to ignore its children.
 		 */
 		if (!parent->power.disable_depth
 		    && !parent->power.ignore_children) {
@@ -737,12 +814,12 @@ static int rpm_resume(struct device *dev
 
 	callback = RPM_GET_CALLBACK(dev, runtime_resume);
 
-	dev_pm_disable_wake_irq(dev);
+	dev_pm_disable_wake_irq_check(dev);
 	retval = rpm_callback(callback, dev);
 	if (retval) {
 		__update_runtime_status(dev, RPM_SUSPENDED);
 		pm_runtime_cancel_pending(dev);
-		dev_pm_enable_wake_irq(dev);
+		dev_pm_enable_wake_irq_check(dev, false);
 	} else {
  no_callback:
 		__update_runtime_status(dev, RPM_ACTIVE);
@@ -889,13 +966,13 @@ int __pm_runtime_idle(struct device *dev
 	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;
 	}
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	spin_lock_irqsave(&dev->power.lock, flags);
 	retval = rpm_idle(dev, rpmflags);
 	spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -921,13 +998,13 @@ int __pm_runtime_suspend(struct device *
 	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;
 	}
 
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+
 	spin_lock_irqsave(&dev->power.lock, flags);
 	retval = rpm_suspend(dev, rpmflags);
 	spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -952,7 +1029,8 @@ int __pm_runtime_resume(struct device *d
 	unsigned long flags;
 	int retval;
 
-	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
+	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
+			dev->power.runtime_status != RPM_ACTIVE);
 
 	if (rpmflags & RPM_GET_PUT)
 		atomic_inc(&dev->power.usage_count);
@@ -1027,7 +1105,17 @@ int __pm_runtime_set_status(struct devic
 		goto out_set;
 
 	if (status == RPM_SUSPENDED) {
-		/* It always is possible to set the status to 'suspended'. */
+		/*
+		 * It is invalid to suspend a device with an active child,
+		 * unless it has been set to ignore its children.
+		 */
+		if (!dev->power.ignore_children &&
+			atomic_read(&dev->power.child_count)) {
+			dev_err(dev, "runtime PM trying to suspend device but active child\n");
+			error = -EBUSY;
+			goto out;
+		}
+
 		if (parent) {
 			atomic_add_unless(&parent->power.child_count, -1, 0);
 			notify_parent = !parent->power.ignore_children;
@@ -1447,6 +1535,94 @@ void pm_runtime_remove(struct device *de
 }
 
 /**
+ * pm_runtime_clean_up_links - Prepare links to consumers for driver removal.
+ * @dev: Device whose driver is going to be removed.
+ *
+ * Check links from this device to any consumers and if any of them have active
+ * runtime PM references to the device, drop the usage counter of the device
+ * (once per link).
+ *
+ * Links with the DL_FLAG_STATELESS flag set are ignored.
+ *
+ * Since the device is guaranteed to be runtime-active at the point this is
+ * called, nothing else needs to be done here.
+ *
+ * Moreover, this is called after device_links_busy() has returned 'false', so
+ * the status of each link is guaranteed to be DL_STATE_SUPPLIER_UNBIND and
+ * therefore rpm_active can't be manipulated concurrently.
+ */
+void pm_runtime_clean_up_links(struct device *dev)
+{
+	struct device_link *link;
+	int idx;
+
+	idx = device_links_read_lock();
+
+	list_for_each_entry_rcu(link, &dev->links.consumers, s_node) {
+		if (link->flags & DL_FLAG_STATELESS)
+			continue;
+
+		if (link->rpm_active) {
+			pm_runtime_put_noidle(dev);
+			link->rpm_active = false;
+		}
+	}
+
+	device_links_read_unlock(idx);
+}
+
+/**
+ * pm_runtime_get_suppliers - Resume and reference-count supplier devices.
+ * @dev: Consumer device.
+ */
+void pm_runtime_get_suppliers(struct device *dev)
+{
+	struct device_link *link;
+	int idx;
+
+	idx = device_links_read_lock();
+
+	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+		if (link->flags & DL_FLAG_PM_RUNTIME)
+			pm_runtime_get_sync(link->supplier);
+
+	device_links_read_unlock(idx);
+}
+
+/**
+ * pm_runtime_put_suppliers - Drop references to supplier devices.
+ * @dev: Consumer device.
+ */
+void pm_runtime_put_suppliers(struct device *dev)
+{
+	struct device_link *link;
+	int idx;
+
+	idx = device_links_read_lock();
+
+	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+		if (link->flags & DL_FLAG_PM_RUNTIME)
+			pm_runtime_put(link->supplier);
+
+	device_links_read_unlock(idx);
+}
+
+void pm_runtime_new_link(struct device *dev)
+{
+	spin_lock_irq(&dev->power.lock);
+	dev->power.links_count++;
+	spin_unlock_irq(&dev->power.lock);
+}
+
+void pm_runtime_drop_link(struct device *dev)
+{
+	spin_lock_irq(&dev->power.lock);
+	WARN_ON(dev->power.links_count == 0);
+	dev->power.links_count--;
+	spin_unlock_irq(&dev->power.lock);
+}
+
+/**
  * pm_runtime_force_suspend - Force a device into suspend state if needed.
  * @dev: Device to suspend.
  *
@@ -1478,6 +1654,16 @@ int pm_runtime_force_suspend(struct devi
 	if (ret)
 		goto err;
 
+	/*
+	 * Increase the runtime PM usage count for the device's parent, in case
+	 * when we find the device being used when system suspend was invoked.
+	 * This informs pm_runtime_force_resume() to resume the parent
+	 * immediately, which is needed to be able to resume its children,
+	 * when not deferring the resume to be managed via runtime PM.
+	 */
+	if (dev->parent && atomic_read(&dev->power.usage_count) > 1)
+		pm_runtime_get_noresume(dev->parent);
+
 	pm_runtime_set_suspended(dev);
 	return 0;
 err:
@@ -1487,16 +1673,20 @@ err:
 EXPORT_SYMBOL_GPL(pm_runtime_force_suspend);
 
 /**
- * pm_runtime_force_resume - Force a device into resume state.
+ * pm_runtime_force_resume - Force a device into resume state if needed.
  * @dev: Device to resume.
  *
  * Prior invoking this function we expect the user to have brought the device
  * into low power state by a call to pm_runtime_force_suspend(). Here we reverse
- * those actions and brings the device into full power. We update the runtime PM
- * status and re-enables runtime PM.
+ * those actions and brings the device into full power, if it is expected to be
+ * used on system resume. To distinguish that, we check whether the runtime PM
+ * usage count is greater than 1 (the PM core increases the usage count in the
+ * system PM prepare phase), as that indicates a real user (such as a subsystem,
+ * driver, userspace, etc.) is using it. If that is the case, the device is
+ * expected to be used on system resume as well, so then we resume it. In the
+ * other case, we defer the resume to be managed via runtime PM.
  *
- * Typically this function may be invoked from a system resume callback to make
- * sure the device is put into full power state.
+ * Typically this function may be invoked from a system resume callback.
  */
 int pm_runtime_force_resume(struct device *dev)
 {
@@ -1513,6 +1703,17 @@ int pm_runtime_force_resume(struct devic
 	if (!pm_runtime_status_suspended(dev))
 		goto out;
 
+	/*
+	 * Decrease the parent's runtime PM usage count, if we increased it
+	 * during system suspend in pm_runtime_force_suspend().
+	*/
+	if (atomic_read(&dev->power.usage_count) > 1) {
+		if (dev->parent)
+			pm_runtime_put_noidle(dev->parent);
+	} else {
+		goto out;
+	}
+
 	ret = pm_runtime_set_active(dev);
 	if (ret)
 		goto out;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/sysfs.c linux-libre-4.10-rc8-gnu/drivers/base/power/sysfs.c
--- linux-libre-4.9-gnu/drivers/base/power/sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -263,7 +263,11 @@ static ssize_t pm_qos_latency_tolerance_
 	s32 value;
 	int ret;
 
-	if (kstrtos32(buf, 0, &value)) {
+	if (kstrtos32(buf, 0, &value) == 0) {
+		/* Users can't write negative values directly */
+		if (value < 0)
+			return -EINVAL;
+	} else {
 		if (!strcmp(buf, "auto") || !strcmp(buf, "auto\n"))
 			value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
 		else if (!strcmp(buf, "any") || !strcmp(buf, "any\n"))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/trace.c linux-libre-4.10-rc8-gnu/drivers/base/power/trace.c
--- linux-libre-4.9-gnu/drivers/base/power/trace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/trace.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@
 #include <linux/pm-trace.h>
 #include <linux/export.h>
 #include <linux/rtc.h>
+#include <linux/suspend.h>
 
 #include <linux/mc146818rtc.h>
 
@@ -74,6 +75,9 @@
 
 #define DEVSEED (7919)
 
+bool pm_trace_rtc_abused __read_mostly;
+EXPORT_SYMBOL_GPL(pm_trace_rtc_abused);
+
 static unsigned int dev_hash_value;
 
 static int set_magic_time(unsigned int user, unsigned int file, unsigned int device)
@@ -104,6 +108,7 @@ static int set_magic_time(unsigned int u
 	time.tm_min = (n % 20) * 3;
 	n /= 20;
 	mc146818_set_time(&time);
+	pm_trace_rtc_abused = true;
 	return n ? -1 : 0;
 }
 
@@ -239,9 +244,31 @@ int show_trace_dev_match(char *buf, size
 	return ret;
 }
 
+static int
+pm_trace_notify(struct notifier_block *nb, unsigned long mode, void *_unused)
+{
+	switch (mode) {
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		if (pm_trace_rtc_abused) {
+			pm_trace_rtc_abused = false;
+			pr_warn("Possible incorrect RTC due to pm_trace, please use 'ntpdate' or 'rdate' to reset it.\n");
+		}
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static struct notifier_block pm_trace_nb = {
+	.notifier_call = pm_trace_notify,
+};
+
 static int early_resume_init(void)
 {
 	hash_value_early_read = read_magic_time();
+	register_pm_notifier(&pm_trace_nb);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/wakeirq.c linux-libre-4.10-rc8-gnu/drivers/base/power/wakeirq.c
--- linux-libre-4.9-gnu/drivers/base/power/wakeirq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/wakeirq.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,8 +110,10 @@ void dev_pm_clear_wake_irq(struct device
 	dev->power.wakeirq = NULL;
 	spin_unlock_irqrestore(&dev->power.lock, flags);
 
-	if (wirq->dedicated_irq)
+	if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED) {
 		free_irq(wirq->irq, wirq);
+		wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;
+	}
 	kfree(wirq);
 }
 EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
@@ -179,7 +181,6 @@ int dev_pm_set_dedicated_wake_irq(struct
 
 	wirq->dev = dev;
 	wirq->irq = irq;
-	wirq->dedicated_irq = true;
 	irq_set_status_flags(irq, IRQ_NOAUTOEN);
 
 	/*
@@ -195,6 +196,8 @@ int dev_pm_set_dedicated_wake_irq(struct
 	if (err)
 		goto err_free_irq;
 
+	wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED;
+
 	return err;
 
 err_free_irq:
@@ -210,9 +213,9 @@ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_w
  * dev_pm_enable_wake_irq - Enable device wake-up interrupt
  * @dev: Device
  *
- * Called from the bus code or the device driver for
- * runtime_suspend() to enable the wake-up interrupt while
- * the device is running.
+ * Optionally called from the bus code or the device driver for
+ * runtime_resume() to override the PM runtime core managed wake-up
+ * interrupt handling to enable the wake-up interrupt.
  *
  * Note that for runtime_suspend()) the wake-up interrupts
  * should be unconditionally enabled unlike for suspend()
@@ -222,7 +225,7 @@ void dev_pm_enable_wake_irq(struct devic
 {
 	struct wake_irq *wirq = dev->power.wakeirq;
 
-	if (wirq && wirq->dedicated_irq)
+	if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
 		enable_irq(wirq->irq);
 }
 EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq);
@@ -231,20 +234,73 @@ EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq
  * dev_pm_disable_wake_irq - Disable device wake-up interrupt
  * @dev: Device
  *
- * Called from the bus code or the device driver for
- * runtime_resume() to disable the wake-up interrupt while
- * the device is running.
+ * Optionally called from the bus code or the device driver for
+ * runtime_suspend() to override the PM runtime core managed wake-up
+ * interrupt handling to disable the wake-up interrupt.
  */
 void dev_pm_disable_wake_irq(struct device *dev)
 {
 	struct wake_irq *wirq = dev->power.wakeirq;
 
-	if (wirq && wirq->dedicated_irq)
+	if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
 		disable_irq_nosync(wirq->irq);
 }
 EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq);
 
 /**
+ * dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt
+ * @dev: Device
+ * @can_change_status: Can change wake-up interrupt status
+ *
+ * Enables wakeirq conditionally. We need to enable wake-up interrupt
+ * lazily on the first rpm_suspend(). This is needed as the consumer device
+ * starts in RPM_SUSPENDED state, and the the first pm_runtime_get() would
+ * otherwise try to disable already disabled wakeirq. The wake-up interrupt
+ * starts disabled with IRQ_NOAUTOEN set.
+ *
+ * Should be only called from rpm_suspend() and rpm_resume() path.
+ * Caller must hold &dev->power.lock to change wirq->status
+ */
+void dev_pm_enable_wake_irq_check(struct device *dev,
+				  bool can_change_status)
+{
+	struct wake_irq *wirq = dev->power.wakeirq;
+
+	if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
+		return;
+
+	if (likely(wirq->status & WAKE_IRQ_DEDICATED_MANAGED)) {
+		goto enable;
+	} else if (can_change_status) {
+		wirq->status |= WAKE_IRQ_DEDICATED_MANAGED;
+		goto enable;
+	}
+
+	return;
+
+enable:
+	enable_irq(wirq->irq);
+}
+
+/**
+ * dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt
+ * @dev: Device
+ *
+ * Disables wake-up interrupt conditionally based on status.
+ * Should be only called from rpm_suspend() and rpm_resume() path.
+ */
+void dev_pm_disable_wake_irq_check(struct device *dev)
+{
+	struct wake_irq *wirq = dev->power.wakeirq;
+
+	if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
+		return;
+
+	if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
+		disable_irq_nosync(wirq->irq);
+}
+
+/**
  * dev_pm_arm_wake_irq - Arm device wake-up
  * @wirq: Device wake-up interrupt
  *
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/power/wakeup.c linux-libre-4.10-rc8-gnu/drivers/base/power/wakeup.c
--- linux-libre-4.9-gnu/drivers/base/power/wakeup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/power/wakeup.c	2017-02-12 16:03:20.000000000 -0500
@@ -811,7 +811,7 @@ void pm_print_active_wakeup_sources(void
 	rcu_read_lock();
 	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
 		if (ws->active) {
-			pr_info("active wakeup source: %s\n", ws->name);
+			pr_debug("active wakeup source: %s\n", ws->name);
 			active = 1;
 		} else if (!active &&
 			   (!last_activity_ws ||
@@ -822,7 +822,7 @@ void pm_print_active_wakeup_sources(void
 	}
 
 	if (!active && last_activity_ws)
-		pr_info("last active wakeup source: %s\n",
+		pr_debug("last active wakeup source: %s\n",
 			last_activity_ws->name);
 	rcu_read_unlock();
 }
@@ -905,7 +905,7 @@ bool pm_get_wakeup_count(unsigned int *c
 			split_counters(&cnt, &inpr);
 			if (inpr == 0 || signal_pending(current))
 				break;
-
+			pm_print_active_wakeup_sources();
 			schedule();
 		}
 		finish_wait(&wakeup_count_wait_queue, &wait);
@@ -998,14 +998,14 @@ static int print_wakeup_source_stats(str
 
 		active_time = ktime_sub(now, ws->last_time);
 		total_time = ktime_add(total_time, active_time);
-		if (active_time.tv64 > max_time.tv64)
+		if (active_time > max_time)
 			max_time = active_time;
 
 		if (ws->autosleep_enabled)
 			prevent_sleep_time = ktime_add(prevent_sleep_time,
 				ktime_sub(now, ws->start_prevent_time));
 	} else {
-		active_time = ktime_set(0, 0);
+		active_time = 0;
 	}
 
 	seq_printf(m, "%-12s\t%lu\t\t%lu\t\t%lu\t\t%lu\t\t%lld\t\t%lld\t\t%lld\t\t%lld\t\t%lld\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/regmap/regcache-lzo.c linux-libre-4.10-rc8-gnu/drivers/base/regmap/regcache-lzo.c
--- linux-libre-4.9-gnu/drivers/base/regmap/regcache-lzo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/regmap/regcache-lzo.c	2017-02-12 16:03:20.000000000 -0500
@@ -236,15 +236,13 @@ static int regcache_lzo_read(struct regm
 {
 	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
 	int ret, blkindex, blkpos;
-	size_t blksize, tmp_dst_len;
+	size_t 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];
 
@@ -275,15 +273,13 @@ static int regcache_lzo_write(struct reg
 {
 	struct regcache_lzo_ctx *lzo_block, **lzo_blocks;
 	int ret, blkindex, blkpos;
-	size_t blksize, tmp_dst_len;
+	size_t 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];
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/soc.c linux-libre-4.10-rc8-gnu/drivers/base/soc.c
--- linux-libre-4.9-gnu/drivers/base/soc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/soc.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/sys_soc.h>
 #include <linux/err.h>
+#include <linux/glob.h>
 
 static DEFINE_IDA(soc_ida);
 
@@ -113,6 +114,12 @@ struct soc_device *soc_device_register(s
 	struct soc_device *soc_dev;
 	int ret;
 
+	if (!soc_bus_type.p) {
+		ret = bus_register(&soc_bus_type);
+		if (ret)
+			goto out1;
+	}
+
 	soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
 	if (!soc_dev) {
 		ret = -ENOMEM;
@@ -156,6 +163,78 @@ void soc_device_unregister(struct soc_de
 
 static int __init soc_bus_register(void)
 {
+	if (soc_bus_type.p)
+		return 0;
+
 	return bus_register(&soc_bus_type);
 }
 core_initcall(soc_bus_register);
+
+static int soc_device_match_one(struct device *dev, void *arg)
+{
+	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
+	const struct soc_device_attribute *match = arg;
+
+	if (match->machine &&
+	    (!soc_dev->attr->machine ||
+	     !glob_match(match->machine, soc_dev->attr->machine)))
+		return 0;
+
+	if (match->family &&
+	    (!soc_dev->attr->family ||
+	     !glob_match(match->family, soc_dev->attr->family)))
+		return 0;
+
+	if (match->revision &&
+	    (!soc_dev->attr->revision ||
+	     !glob_match(match->revision, soc_dev->attr->revision)))
+		return 0;
+
+	if (match->soc_id &&
+	    (!soc_dev->attr->soc_id ||
+	     !glob_match(match->soc_id, soc_dev->attr->soc_id)))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * soc_device_match - identify the SoC in the machine
+ * @matches: zero-terminated array of possible matches
+ *
+ * returns the first matching entry of the argument array, or NULL
+ * if none of them match.
+ *
+ * This function is meant as a helper in place of of_match_node()
+ * in cases where either no device tree is available or the information
+ * in a device node is insufficient to identify a particular variant
+ * by its compatible strings or other properties. For new devices,
+ * the DT binding should always provide unique compatible strings
+ * that allow the use of of_match_node() instead.
+ *
+ * The calling function can use the .data entry of the
+ * soc_device_attribute to pass a structure or function pointer for
+ * each entry.
+ */
+const struct soc_device_attribute *soc_device_match(
+	const struct soc_device_attribute *matches)
+{
+	int ret = 0;
+
+	if (!matches)
+		return NULL;
+
+	while (!ret) {
+		if (!(matches->machine || matches->family ||
+		      matches->revision || matches->soc_id))
+			break;
+		ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
+				       soc_device_match_one);
+		if (!ret)
+			matches++;
+		else
+			return matches;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(soc_device_match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/test/Kconfig linux-libre-4.10-rc8-gnu/drivers/base/test/Kconfig
--- linux-libre-4.9-gnu/drivers/base/test/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/test/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,9 @@
+config TEST_ASYNC_DRIVER_PROBE
+	tristate "Build kernel module to test asynchronous driver probing"
+	depends on m
+	help
+	  Enabling this option produces a kernel module that allows
+	  testing asynchronous driver probing by the device core.
+	  The module name will be test_async_driver_probe.ko
+
+	  If unsure say N.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/test/Makefile linux-libre-4.10-rc8-gnu/drivers/base/test/Makefile
--- linux-libre-4.9-gnu/drivers/base/test/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/test/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1 @@
+obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE)	+= test_async_driver_probe.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/test/test_async_driver_probe.c linux-libre-4.10-rc8-gnu/drivers/base/test/test_async_driver_probe.c
--- linux-libre-4.9-gnu/drivers/base/test/test_async_driver_probe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/test/test_async_driver_probe.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2014 Google, 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/hrtimer.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+
+#define TEST_PROBE_DELAY	(5 * 1000)	/* 5 sec */
+#define TEST_PROBE_THRESHOLD	(TEST_PROBE_DELAY / 2)
+
+static int test_probe(struct platform_device *pdev)
+{
+	dev_info(&pdev->dev, "sleeping for %d msecs in probe\n",
+		 TEST_PROBE_DELAY);
+	msleep(TEST_PROBE_DELAY);
+	dev_info(&pdev->dev, "done sleeping\n");
+
+	return 0;
+}
+
+static struct platform_driver async_driver = {
+	.driver = {
+		.name = "test_async_driver",
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+	.probe = test_probe,
+};
+
+static struct platform_driver sync_driver = {
+	.driver = {
+		.name = "test_sync_driver",
+		.probe_type = PROBE_FORCE_SYNCHRONOUS,
+	},
+	.probe = test_probe,
+};
+
+static struct platform_device *async_dev_1, *async_dev_2;
+static struct platform_device *sync_dev_1;
+
+static int __init test_async_probe_init(void)
+{
+	ktime_t calltime, delta;
+	unsigned long long duration;
+	int error;
+
+	pr_info("registering first asynchronous device...\n");
+
+	async_dev_1 = platform_device_register_simple("test_async_driver", 1,
+						      NULL, 0);
+	if (IS_ERR(async_dev_1)) {
+		error = PTR_ERR(async_dev_1);
+		pr_err("failed to create async_dev_1: %d", error);
+		return error;
+	}
+
+	pr_info("registering asynchronous driver...\n");
+	calltime = ktime_get();
+	error = platform_driver_register(&async_driver);
+	if (error) {
+		pr_err("Failed to register async_driver: %d\n", error);
+		goto err_unregister_async_dev_1;
+	}
+
+	delta = ktime_sub(ktime_get(), calltime);
+	duration = (unsigned long long) ktime_to_ms(delta);
+	pr_info("registration took %lld msecs\n", duration);
+	if (duration > TEST_PROBE_THRESHOLD) {
+		pr_err("test failed: probe took too long\n");
+		error = -ETIMEDOUT;
+		goto err_unregister_async_driver;
+	}
+
+	pr_info("registering second asynchronous device...\n");
+	calltime = ktime_get();
+	async_dev_2 = platform_device_register_simple("test_async_driver", 2,
+						      NULL, 0);
+	if (IS_ERR(async_dev_2)) {
+		error = PTR_ERR(async_dev_2);
+		pr_err("failed to create async_dev_2: %d", error);
+		goto err_unregister_async_driver;
+	}
+
+	delta = ktime_sub(ktime_get(), calltime);
+	duration = (unsigned long long) ktime_to_ms(delta);
+	pr_info("registration took %lld msecs\n", duration);
+	if (duration > TEST_PROBE_THRESHOLD) {
+		pr_err("test failed: probe took too long\n");
+		error = -ETIMEDOUT;
+		goto err_unregister_async_dev_2;
+	}
+
+	pr_info("registering synchronous driver...\n");
+
+	error = platform_driver_register(&sync_driver);
+	if (error) {
+		pr_err("Failed to register async_driver: %d\n", error);
+		goto err_unregister_async_dev_2;
+	}
+
+	pr_info("registering synchronous device...\n");
+	calltime = ktime_get();
+	sync_dev_1 = platform_device_register_simple("test_sync_driver", 1,
+						     NULL, 0);
+	if (IS_ERR(sync_dev_1)) {
+		error = PTR_ERR(sync_dev_1);
+		pr_err("failed to create sync_dev_1: %d", error);
+		goto err_unregister_sync_driver;
+	}
+
+	delta = ktime_sub(ktime_get(), calltime);
+	duration = (unsigned long long) ktime_to_ms(delta);
+	pr_info("registration took %lld msecs\n", duration);
+	if (duration < TEST_PROBE_THRESHOLD) {
+		pr_err("test failed: probe was too quick\n");
+		error = -ETIMEDOUT;
+		goto err_unregister_sync_dev_1;
+	}
+
+	pr_info("completed successfully");
+
+	return 0;
+
+err_unregister_sync_dev_1:
+	platform_device_unregister(sync_dev_1);
+
+err_unregister_sync_driver:
+	platform_driver_unregister(&sync_driver);
+
+err_unregister_async_dev_2:
+	platform_device_unregister(async_dev_2);
+
+err_unregister_async_driver:
+	platform_driver_unregister(&async_driver);
+
+err_unregister_async_dev_1:
+	platform_device_unregister(async_dev_1);
+
+	return error;
+}
+module_init(test_async_probe_init);
+
+static void __exit test_async_probe_exit(void)
+{
+	platform_driver_unregister(&async_driver);
+	platform_driver_unregister(&sync_driver);
+	platform_device_unregister(async_dev_1);
+	platform_device_unregister(async_dev_2);
+	platform_device_unregister(sync_dev_1);
+}
+module_exit(test_async_probe_exit);
+
+MODULE_DESCRIPTION("Test module for asynchronous driver probing");
+MODULE_AUTHOR("Dmitry Torokhov <dtor@chromium.org>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/base/topology.c linux-libre-4.10-rc8-gnu/drivers/base/topology.c
--- linux-libre-4.9-gnu/drivers/base/topology.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/base/topology.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,51 +118,19 @@ static int topology_add_dev(unsigned int
 	return sysfs_create_group(&dev->kobj, &topology_attr_group);
 }
 
-static void topology_remove_dev(unsigned int cpu)
+static int topology_remove_dev(unsigned int cpu)
 {
 	struct device *dev = get_cpu_device(cpu);
 
 	sysfs_remove_group(&dev->kobj, &topology_attr_group);
-}
-
-static int topology_cpu_callback(struct notifier_block *nfb,
-				 unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long)hcpu;
-	int rc = 0;
-
-	switch (action) {
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		rc = topology_add_dev(cpu);
-		break;
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		topology_remove_dev(cpu);
-		break;
-	}
-	return notifier_from_errno(rc);
+	return 0;
 }
 
 static int topology_sysfs_init(void)
 {
-	int cpu;
-	int rc = 0;
-
-	cpu_notifier_register_begin();
-
-	for_each_online_cpu(cpu) {
-		rc = topology_add_dev(cpu);
-		if (rc)
-			goto out;
-	}
-	__hotcpu_notifier(topology_cpu_callback, 0);
-
-out:
-	cpu_notifier_register_done();
-	return rc;
+	return cpuhp_setup_state(CPUHP_TOPOLOGY_PREPARE,
+				 "base/topology:prepare", topology_add_dev,
+				 topology_remove_dev);
 }
 
 device_initcall(topology_sysfs_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bcma/bcma_private.h linux-libre-4.10-rc8-gnu/drivers/bcma/bcma_private.h
--- linux-libre-4.9-gnu/drivers/bcma/bcma_private.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bcma/bcma_private.h	2017-02-12 16:03:20.000000000 -0500
@@ -45,6 +45,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
 void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
 void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
 void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
 
 /* driver_chipcommon_b.c */
 int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bcma/driver_chipcommon.c linux-libre-4.10-rc8-gnu/drivers/bcma/driver_chipcommon.c
--- linux-libre-4.9-gnu/drivers/bcma/driver_chipcommon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bcma/driver_chipcommon.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,8 +15,6 @@
 #include <linux/platform_device.h>
 #include <linux/bcma/bcma.h>
 
-static void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
-
 static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
 					 u32 mask, u32 value)
 {
@@ -186,9 +184,6 @@ void bcma_core_chipcommon_early_init(str
 	if (cc->capabilities & BCMA_CC_CAP_PMU)
 		bcma_pmu_early_init(cc);
 
-	if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC)
-		bcma_chipco_serial_init(cc);
-
 	if (bus->hosttype == BCMA_HOSTTYPE_SOC)
 		bcma_core_chipcommon_flash_detect(cc);
 
@@ -378,9 +373,9 @@ u32 bcma_chipco_gpio_pulldown(struct bcm
 	return res;
 }
 
-static void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
+#ifdef CONFIG_BCMA_DRIVER_MIPS
+void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
 {
-#if IS_BUILTIN(CONFIG_BCM47XX)
 	unsigned int irq;
 	u32 baud_base;
 	u32 i;
@@ -422,5 +417,5 @@ static void bcma_chipco_serial_init(stru
 		ports[i].baud_base = baud_base;
 		ports[i].reg_shift = 0;
 	}
-#endif /* CONFIG_BCM47XX */
 }
+#endif /* CONFIG_BCMA_DRIVER_MIPS */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bcma/driver_mips.c linux-libre-4.10-rc8-gnu/drivers/bcma/driver_mips.c
--- linux-libre-4.9-gnu/drivers/bcma/driver_mips.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bcma/driver_mips.c	2017-02-12 16:03:20.000000000 -0500
@@ -278,9 +278,12 @@ static void bcma_core_mips_nvram_init(st
 
 void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
 {
+	struct bcma_bus *bus = mcore->core->bus;
+
 	if (mcore->early_setup_done)
 		return;
 
+	bcma_chipco_serial_init(&bus->drv_cc);
 	bcma_core_mips_nvram_init(mcore);
 
 	mcore->early_setup_done = true;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bcma/host_pci.c linux-libre-4.10-rc8-gnu/drivers/bcma/host_pci.c
--- linux-libre-4.9-gnu/drivers/bcma/host_pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bcma/host_pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -295,6 +295,7 @@ static const struct pci_device_id bcma_p
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4360) },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0016) },
+	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_DELL, 0x0018) },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, 0x4365, PCI_VENDOR_ID_FOXCONN, 0xe092) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a0) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/amiflop.c linux-libre-4.10-rc8-gnu/drivers/block/amiflop.c
--- linux-libre-4.9-gnu/drivers/block/amiflop.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/amiflop.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/irq.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/brd.c linux-libre-4.10-rc8-gnu/drivers/block/brd.c
--- linux-libre-4.9-gnu/drivers/block/brd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/brd.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/pfn_t.h>
 #endif
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define SECTOR_SHIFT		9
 #define PAGE_SECTORS_SHIFT	(PAGE_SHIFT - SECTOR_SHIFT)
@@ -395,44 +395,9 @@ static long brd_direct_access(struct blo
 #define brd_direct_access NULL
 #endif
 
-static int brd_ioctl(struct block_device *bdev, fmode_t mode,
-			unsigned int cmd, unsigned long arg)
-{
-	int error;
-	struct brd_device *brd = bdev->bd_disk->private_data;
-
-	if (cmd != BLKFLSBUF)
-		return -ENOTTY;
-
-	/*
-	 * ram device BLKFLSBUF has special semantics, we want to actually
-	 * release and destroy the ramdisk data.
-	 */
-	mutex_lock(&brd_mutex);
-	mutex_lock(&bdev->bd_mutex);
-	error = -EBUSY;
-	if (bdev->bd_openers <= 1) {
-		/*
-		 * Kill the cache first, so it isn't written back to the
-		 * device.
-		 *
-		 * Another thread might instantiate more buffercache here,
-		 * but there is not much we can do to close that race.
-		 */
-		kill_bdev(bdev);
-		brd_free_pages(brd);
-		error = 0;
-	}
-	mutex_unlock(&bdev->bd_mutex);
-	mutex_unlock(&brd_mutex);
-
-	return error;
-}
-
 static const struct block_device_operations brd_fops = {
 	.owner =		THIS_MODULE,
 	.rw_page =		brd_rw_page,
-	.ioctl =		brd_ioctl,
 	.direct_access =	brd_direct_access,
 };
 
@@ -443,8 +408,8 @@ static int rd_nr = CONFIG_BLK_DEV_RAM_CO
 module_param(rd_nr, int, S_IRUGO);
 MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
 
-int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
-module_param(rd_size, int, S_IRUGO);
+unsigned long rd_size = CONFIG_BLK_DEV_RAM_SIZE;
+module_param(rd_size, ulong, S_IRUGO);
 MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
 
 static int max_part = 1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/cciss.c linux-libre-4.10-rc8-gnu/drivers/block/cciss.c
--- linux-libre-4.9-gnu/drivers/block/cciss.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/cciss.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
 #include <linux/mutex.h>
 #include <linux/bitmap.h>
 #include <linux/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/dma-mapping.h>
 #include <linux/blkdev.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/cciss_scsi.c linux-libre-4.10-rc8-gnu/drivers/block/cciss_scsi.c
--- linux-libre-4.9-gnu/drivers/block/cciss_scsi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/cciss_scsi.c	2017-02-12 16:03:20.000000000 -0500
@@ -260,43 +260,6 @@ scsi_cmd_stack_free(ctlr_info_t *h)
 }
 
 #if 0
-static int xmargin=8;
-static int amargin=60;
-
-static void
-print_bytes (unsigned char *c, int len, int hex, int ascii)
-{
-
-	int i;
-	unsigned char *x;
-
-	if (hex)
-	{
-		x = c;
-		for (i=0;i<len;i++)
-		{
-			if ((i % xmargin) == 0 && i>0) printk("\n");
-			if ((i % xmargin) == 0) printk("0x%04x:", i);
-			printk(" %02x", *x);
-			x++;
-		}
-		printk("\n");
-	}
-	if (ascii)
-	{
-		x = c;
-		for (i=0;i<len;i++)
-		{
-			if ((i % amargin) == 0 && i>0) printk("\n");
-			if ((i % amargin) == 0) printk("0x%04x:", i);
-			if (*x > 26 && *x < 128) printk("%c", *x);
-			else printk(".");
-			x++;
-		}
-		printk("\n");
-	}
-}
-
 static void
 print_cmd(CommandList_struct *cp)
 {
@@ -305,30 +268,13 @@ print_cmd(CommandList_struct *cp)
 	printk("sgtot:%d\n", cp->Header.SGTotal);
 	printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper, 
 			cp->Header.Tag.lower);
-	printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
-		cp->Header.LUN.LunAddrBytes[0],
-		cp->Header.LUN.LunAddrBytes[1],
-		cp->Header.LUN.LunAddrBytes[2],
-		cp->Header.LUN.LunAddrBytes[3],
-		cp->Header.LUN.LunAddrBytes[4],
-		cp->Header.LUN.LunAddrBytes[5],
-		cp->Header.LUN.LunAddrBytes[6],
-		cp->Header.LUN.LunAddrBytes[7]);
+	printk("LUN:0x%8phN\n", cp->Header.LUN.LunAddrBytes);
 	printk("CDBLen:%d\n", cp->Request.CDBLen);
 	printk("Type:%d\n",cp->Request.Type.Type);
 	printk("Attr:%d\n",cp->Request.Type.Attribute);
 	printk(" Dir:%d\n",cp->Request.Type.Direction);
 	printk("Timeout:%d\n",cp->Request.Timeout);
-	printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x"
-		" %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		cp->Request.CDB[0], cp->Request.CDB[1],
-		cp->Request.CDB[2], cp->Request.CDB[3],
-		cp->Request.CDB[4], cp->Request.CDB[5],
-		cp->Request.CDB[6], cp->Request.CDB[7],
-		cp->Request.CDB[8], cp->Request.CDB[9],
-		cp->Request.CDB[10], cp->Request.CDB[11],
-		cp->Request.CDB[12], cp->Request.CDB[13],
-		cp->Request.CDB[14], cp->Request.CDB[15]),
+	printk("CDB: %16ph\n", cp->Request.CDB);
 	printk("edesc.Addr: 0x%08x/0%08x, Len  = %d\n", 
 		cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower, 
 			cp->ErrDesc.Len);
@@ -340,9 +286,7 @@ print_cmd(CommandList_struct *cp)
 	printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size);
 	printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num);
 	printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
-			
 }
-
 #endif
 
 static int 
@@ -782,8 +726,10 @@ static void complete_scsi_command(Comman
 					"reported\n", c);
 			break;
 			case CMD_INVALID: {
-				/* print_bytes(c, sizeof(*c), 1, 0);
-				print_cmd(c); */
+				/*
+				print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, c, sizeof(*c), false);
+				print_cmd(c);
+				 */
      /* We get CMD_INVALID if you address a non-existent tape drive instead
 	of a selection timeout (no response).  You will see this if you yank 
 	out a tape drive, then try to access it. This is kind of a shame
@@ -985,8 +931,10 @@ cciss_scsi_interpret_error(ctlr_info_t *
 			dev_warn(&h->pdev->dev,
 				"%p is reported invalid (probably means "
 				"target device no longer present)\n", c);
-			/* print_bytes((unsigned char *) c, sizeof(*c), 1, 0);
-			print_cmd(c);  */
+			/*
+			print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, c, sizeof(*c), false);
+			print_cmd(c);
+			 */
 			}
 		break;
 		case CMD_PROTOCOL_ERR:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/cryptoloop.c linux-libre-4.10-rc8-gnu/drivers/block/cryptoloop.c
--- linux-libre-4.9-gnu/drivers/block/cryptoloop.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/cryptoloop.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/string.h>
 #include <linux/blkdev.h>
 #include <linux/scatterlist.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "loop.h"
 
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/DAC960.c linux-libre-4.10-rc8-gnu/drivers/block/DAC960.c
--- linux-libre-4.9-gnu/drivers/block/DAC960.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/DAC960.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
 #include <linux/random.h>
 #include <linux/scatterlist.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "DAC960.h"
 
 #define DAC960_GAM_MINOR	252
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/drbd/drbd_actlog.c linux-libre-4.10-rc8-gnu/drivers/block/drbd/drbd_actlog.c
--- linux-libre-4.9-gnu/drivers/block/drbd/drbd_actlog.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/drbd/drbd_actlog.c	2017-02-12 16:03:20.000000000 -0500
@@ -148,7 +148,7 @@ static int _drbd_md_sync_page_io(struct
 
 	if ((op == REQ_OP_WRITE) && !test_bit(MD_NO_FUA, &device->flags))
 		op_flags |= REQ_FUA | REQ_PREFLUSH;
-	op_flags |= REQ_SYNC | REQ_NOIDLE;
+	op_flags |= REQ_SYNC;
 
 	bio = bio_alloc_drbd(GFP_NOIO);
 	bio->bi_bdev = bdev->md_bdev;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/drbd/drbd_receiver.c linux-libre-4.10-rc8-gnu/drivers/block/drbd/drbd_receiver.c
--- linux-libre-4.9-gnu/drivers/block/drbd/drbd_receiver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/drbd/drbd_receiver.c	2017-02-12 16:03:20.000000000 -0500
@@ -1266,7 +1266,7 @@ static void submit_one_flush(struct drbd
 	bio->bi_bdev = device->ldev->backing_bdev;
 	bio->bi_private = octx;
 	bio->bi_end_io = one_flush_endio;
-	bio_set_op_attrs(bio, REQ_OP_FLUSH, WRITE_FLUSH);
+	bio->bi_opf = REQ_OP_FLUSH | REQ_PREFLUSH;
 
 	device->flush_jif = jiffies;
 	set_bit(FLUSH_PENDING, &device->flags);
@@ -1648,20 +1648,8 @@ next_bio:
 
 	page_chain_for_each(page) {
 		unsigned len = min_t(unsigned, data_size, PAGE_SIZE);
-		if (!bio_add_page(bio, page, len, 0)) {
-			/* A single page must always be possible!
-			 * But in case it fails anyways,
-			 * we deal with it, and complain (below). */
-			if (bio->bi_vcnt == 0) {
-				drbd_err(device,
-					"bio_add_page failed for len=%u, "
-					"bi_vcnt=0 (bi_sector=%llu)\n",
-					len, (uint64_t)bio->bi_iter.bi_sector);
-				err = -ENOSPC;
-				goto fail;
-			}
+		if (!bio_add_page(bio, page, len, 0))
 			goto next_bio;
-		}
 		data_size -= len;
 		sector += len >> 9;
 		--nr_pages;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/floppy.c linux-libre-4.10-rc8-gnu/drivers/block/floppy.c
--- linux-libre-4.9-gnu/drivers/block/floppy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/floppy.c	2017-02-12 16:03:20.000000000 -0500
@@ -3806,14 +3806,10 @@ static int __floppy_read_block_0(struct
 
 	cbdata.drive = drive;
 
-	bio_init(&bio);
-	bio.bi_io_vec = &bio_vec;
-	bio_vec.bv_page = page;
-	bio_vec.bv_len = size;
-	bio_vec.bv_offset = 0;
-	bio.bi_vcnt = 1;
-	bio.bi_iter.bi_size = size;
+	bio_init(&bio, &bio_vec, 1);
 	bio.bi_bdev = bdev;
+	bio_add_page(&bio, page, size, 0);
+
 	bio.bi_iter.bi_sector = 0;
 	bio.bi_flags |= (1 << BIO_QUIET);
 	bio.bi_private = &cbdata;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/hd.c linux-libre-4.10-rc8-gnu/drivers/block/hd.c
--- linux-libre-4.9-gnu/drivers/block/hd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/hd.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
 
 #define REALLY_SLOW_IO
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef __arm__
 #undef  HD_IRQ
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/Kconfig linux-libre-4.10-rc8-gnu/drivers/block/Kconfig
--- linux-libre-4.9-gnu/drivers/block/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -384,9 +384,12 @@ config BLK_DEV_RAM_DAX
 	  allocated from highmem (only a problem for highmem systems).
 
 config CDROM_PKTCDVD
-	tristate "Packet writing on CD/DVD media"
+	tristate "Packet writing on CD/DVD media (DEPRECATED)"
 	depends on !UML
 	help
+	  Note: This driver is deprecated and will be removed from the
+	  kernel in the near future!
+
 	  If you have a CDROM/DVD drive that supports packet writing, say
 	  Y to include support. It should work with any MMC/Mt Fuji
 	  compliant ATAPI or SCSI drive, which is just about any newer
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/loop.c linux-libre-4.10-rc8-gnu/drivers/block/loop.c
--- linux-libre-4.9-gnu/drivers/block/loop.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/loop.c	2017-02-12 16:03:20.000000000 -0500
@@ -78,7 +78,7 @@
 #include <linux/uio.h>
 #include "loop.h"
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static DEFINE_IDR(loop_index_idr);
 static DEFINE_MUTEX(loop_index_mutex);
@@ -1646,7 +1646,7 @@ static int loop_queue_rq(struct blk_mq_h
 	blk_mq_start_request(bd->rq);
 
 	if (lo->lo_state != Lo_bound)
-		return -EIO;
+		return BLK_MQ_RQ_QUEUE_ERROR;
 
 	switch (req_op(cmd->rq)) {
 	case REQ_OP_FLUSH:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/mtip32xx/mtip32xx.c linux-libre-4.10-rc8-gnu/drivers/block/mtip32xx/mtip32xx.c
--- linux-libre-4.9-gnu/drivers/block/mtip32xx/mtip32xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/mtip32xx/mtip32xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -2035,18 +2035,14 @@ static int exec_drive_taskfile(struct dr
 	taskout = req_task->out_size;
 	taskin = req_task->in_size;
 	/* 130560 = 512 * 0xFF*/
-	if (taskin > 130560 || taskout > 130560) {
-		err = -EINVAL;
-		goto abort;
-	}
+	if (taskin > 130560 || taskout > 130560)
+		return -EINVAL;
 
 	if (taskout) {
 		outbuf = memdup_user(buf + outtotal, taskout);
-		if (IS_ERR(outbuf)) {
-			err = PTR_ERR(outbuf);
-			outbuf = NULL;
-			goto abort;
-		}
+		if (IS_ERR(outbuf))
+			return PTR_ERR(outbuf);
+
 		outbuf_dma = pci_map_single(dd->pdev,
 					 outbuf,
 					 taskout,
@@ -3937,8 +3933,10 @@ static int mtip_block_initialize(struct
 
 	/* Generate the disk name, implemented same as in sd.c */
 	do {
-		if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL))
+		if (!ida_pre_get(&rssd_index_ida, GFP_KERNEL)) {
+			rv = -ENOMEM;
 			goto ida_get_error;
+		}
 
 		spin_lock(&rssd_index_lock);
 		rv = ida_get_new(&rssd_index_ida, &index);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/nbd.c linux-libre-4.10-rc8-gnu/drivers/block/nbd.c
--- linux-libre-4.9-gnu/drivers/block/nbd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/nbd.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,31 +36,39 @@
 #include <linux/debugfs.h>
 #include <linux/blk-mq.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/types.h>
 
 #include <linux/nbd.h>
 
+struct nbd_sock {
+	struct socket *sock;
+	struct mutex tx_lock;
+};
+
 #define NBD_TIMEDOUT			0
 #define NBD_DISCONNECT_REQUESTED	1
+#define NBD_DISCONNECTED		2
+#define NBD_RUNNING			3
 
 struct nbd_device {
 	u32 flags;
 	unsigned long runtime_flags;
-	struct socket * sock;	/* If == NULL, device is not ready, yet	*/
+	struct nbd_sock **socks;
 	int magic;
 
 	struct blk_mq_tag_set tag_set;
 
-	struct mutex tx_lock;
+	struct mutex config_lock;
 	struct gendisk *disk;
-	int blksize;
+	int num_connections;
+	atomic_t recv_threads;
+	wait_queue_head_t recv_wq;
+	loff_t blksize;
 	loff_t bytesize;
 
-	/* protects initialization and shutdown of the socket */
-	spinlock_t sock_lock;
 	struct task_struct *task_recv;
-	struct task_struct *task_send;
+	struct task_struct *task_setup;
 
 #if IS_ENABLED(CONFIG_DEBUG_FS)
 	struct dentry *dbg_dir;
@@ -69,7 +77,7 @@ struct nbd_device {
 
 struct nbd_cmd {
 	struct nbd_device *nbd;
-	struct list_head list;
+	struct completion send_complete;
 };
 
 #if IS_ENABLED(CONFIG_DEBUG_FS)
@@ -126,7 +134,7 @@ static void nbd_size_update(struct nbd_d
 }
 
 static int nbd_size_set(struct nbd_device *nbd, struct block_device *bdev,
-			int blocksize, int nr_blocks)
+			loff_t blocksize, loff_t nr_blocks)
 {
 	int ret;
 
@@ -135,7 +143,7 @@ static int nbd_size_set(struct nbd_devic
 		return ret;
 
 	nbd->blksize = blocksize;
-	nbd->bytesize = (loff_t)blocksize * (loff_t)nr_blocks;
+	nbd->bytesize = blocksize * nr_blocks;
 
 	nbd_size_update(nbd, bdev);
 
@@ -159,22 +167,20 @@ static void nbd_end_request(struct nbd_c
  */
 static void sock_shutdown(struct nbd_device *nbd)
 {
-	struct socket *sock;
-
-	spin_lock(&nbd->sock_lock);
+	int i;
 
-	if (!nbd->sock) {
-		spin_unlock(&nbd->sock_lock);
+	if (nbd->num_connections == 0)
+		return;
+	if (test_and_set_bit(NBD_DISCONNECTED, &nbd->runtime_flags))
 		return;
-	}
-
-	sock = nbd->sock;
-	dev_warn(disk_to_dev(nbd->disk), "shutting down socket\n");
-	nbd->sock = NULL;
-	spin_unlock(&nbd->sock_lock);
 
-	kernel_sock_shutdown(sock, SHUT_RDWR);
-	sockfd_put(sock);
+	for (i = 0; i < nbd->num_connections; i++) {
+		struct nbd_sock *nsock = nbd->socks[i];
+		mutex_lock(&nsock->tx_lock);
+		kernel_sock_shutdown(nsock->sock, SHUT_RDWR);
+		mutex_unlock(&nsock->tx_lock);
+	}
+	dev_warn(disk_to_dev(nbd->disk), "shutting down sockets\n");
 }
 
 static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req,
@@ -182,42 +188,38 @@ static enum blk_eh_timer_return nbd_xmit
 {
 	struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
 	struct nbd_device *nbd = cmd->nbd;
-	struct socket *sock = NULL;
-
-	spin_lock(&nbd->sock_lock);
 
+	dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
 	set_bit(NBD_TIMEDOUT, &nbd->runtime_flags);
-
-	if (nbd->sock) {
-		sock = nbd->sock;
-		get_file(sock->file);
-	}
-
-	spin_unlock(&nbd->sock_lock);
-	if (sock) {
-		kernel_sock_shutdown(sock, SHUT_RDWR);
-		sockfd_put(sock);
-	}
-
 	req->errors++;
-	dev_err(nbd_to_dev(nbd), "Connection timed out, shutting down connection\n");
+
+	/*
+	 * If our disconnect packet times out then we're already holding the
+	 * config_lock and could deadlock here, so just set an error and return,
+	 * we'll handle shutting everything down later.
+	 */
+	if (req->cmd_type == REQ_TYPE_DRV_PRIV)
+		return BLK_EH_HANDLED;
+	mutex_lock(&nbd->config_lock);
+	sock_shutdown(nbd);
+	mutex_unlock(&nbd->config_lock);
 	return BLK_EH_HANDLED;
 }
 
 /*
  *  Send or receive packet.
  */
-static int sock_xmit(struct nbd_device *nbd, int send, void *buf, int size,
-		int msg_flags)
+static int sock_xmit(struct nbd_device *nbd, int index, int send, void *buf,
+		     int size, int msg_flags)
 {
-	struct socket *sock = nbd->sock;
+	struct socket *sock = nbd->socks[index]->sock;
 	int result;
 	struct msghdr msg;
 	struct kvec iov;
 	unsigned long pflags = current->flags;
 
 	if (unlikely(!sock)) {
-		dev_err(disk_to_dev(nbd->disk),
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
 			"Attempted %s on closed socket in sock_xmit\n",
 			(send ? "send" : "recv"));
 		return -EINVAL;
@@ -254,29 +256,29 @@ static int sock_xmit(struct nbd_device *
 	return result;
 }
 
-static inline int sock_send_bvec(struct nbd_device *nbd, struct bio_vec *bvec,
-		int flags)
+static inline int sock_send_bvec(struct nbd_device *nbd, int index,
+				 struct bio_vec *bvec, int flags)
 {
 	int result;
 	void *kaddr = kmap(bvec->bv_page);
-	result = sock_xmit(nbd, 1, kaddr + bvec->bv_offset,
+	result = sock_xmit(nbd, index, 1, kaddr + bvec->bv_offset,
 			   bvec->bv_len, flags);
 	kunmap(bvec->bv_page);
 	return result;
 }
 
 /* always call with the tx_lock held */
-static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd)
+static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
 {
 	struct request *req = blk_mq_rq_from_pdu(cmd);
-	int result, flags;
+	int result;
 	struct nbd_request request;
 	unsigned long size = blk_rq_bytes(req);
+	struct bio *bio;
 	u32 type;
+	u32 tag = blk_mq_unique_tag(req);
 
-	if (req->cmd_type == REQ_TYPE_DRV_PRIV)
-		type = NBD_CMD_DISC;
-	else if (req_op(req) == REQ_OP_DISCARD)
+	if (req_op(req) == REQ_OP_DISCARD)
 		type = NBD_CMD_TRIM;
 	else if (req_op(req) == REQ_OP_FLUSH)
 		type = NBD_CMD_FLUSH;
@@ -288,73 +290,87 @@ static int nbd_send_cmd(struct nbd_devic
 	memset(&request, 0, sizeof(request));
 	request.magic = htonl(NBD_REQUEST_MAGIC);
 	request.type = htonl(type);
-	if (type != NBD_CMD_FLUSH && type != NBD_CMD_DISC) {
+	if (type != NBD_CMD_FLUSH) {
 		request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
 		request.len = htonl(size);
 	}
-	memcpy(request.handle, &req->tag, sizeof(req->tag));
+	memcpy(request.handle, &tag, sizeof(tag));
 
 	dev_dbg(nbd_to_dev(nbd), "request %p: sending control (%s@%llu,%uB)\n",
 		cmd, nbdcmd_to_ascii(type),
 		(unsigned long long)blk_rq_pos(req) << 9, blk_rq_bytes(req));
-	result = sock_xmit(nbd, 1, &request, sizeof(request),
+	result = sock_xmit(nbd, index, 1, &request, sizeof(request),
 			(type == NBD_CMD_WRITE) ? MSG_MORE : 0);
 	if (result <= 0) {
-		dev_err(disk_to_dev(nbd->disk),
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
 			"Send control failed (result %d)\n", result);
 		return -EIO;
 	}
 
-	if (type == NBD_CMD_WRITE) {
-		struct req_iterator iter;
+	if (type != NBD_CMD_WRITE)
+		return 0;
+
+	bio = req->bio;
+	while (bio) {
+		struct bio *next = bio->bi_next;
+		struct bvec_iter iter;
 		struct bio_vec bvec;
-		/*
-		 * we are really probing at internals to determine
-		 * whether to set MSG_MORE or not...
-		 */
-		rq_for_each_segment(bvec, req, iter) {
-			flags = 0;
-			if (!rq_iter_last(bvec, iter))
-				flags = MSG_MORE;
+
+		bio_for_each_segment(bvec, bio, iter) {
+			bool is_last = !next && bio_iter_last(bvec, iter);
+			int flags = is_last ? 0 : MSG_MORE;
+
 			dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n",
 				cmd, bvec.bv_len);
-			result = sock_send_bvec(nbd, &bvec, flags);
+			result = sock_send_bvec(nbd, index, &bvec, flags);
 			if (result <= 0) {
 				dev_err(disk_to_dev(nbd->disk),
 					"Send data failed (result %d)\n",
 					result);
 				return -EIO;
 			}
+			/*
+			 * The completion might already have come in,
+			 * so break for the last one instead of letting
+			 * the iterator do it. This prevents use-after-free
+			 * of the bio.
+			 */
+			if (is_last)
+				break;
 		}
+		bio = next;
 	}
 	return 0;
 }
 
-static inline int sock_recv_bvec(struct nbd_device *nbd, struct bio_vec *bvec)
+static inline int sock_recv_bvec(struct nbd_device *nbd, int index,
+				 struct bio_vec *bvec)
 {
 	int result;
 	void *kaddr = kmap(bvec->bv_page);
-	result = sock_xmit(nbd, 0, kaddr + bvec->bv_offset, bvec->bv_len,
-			MSG_WAITALL);
+	result = sock_xmit(nbd, index, 0, kaddr + bvec->bv_offset,
+			   bvec->bv_len, MSG_WAITALL);
 	kunmap(bvec->bv_page);
 	return result;
 }
 
 /* NULL returned = something went wrong, inform userspace */
-static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd)
+static struct nbd_cmd *nbd_read_stat(struct nbd_device *nbd, int index)
 {
 	int result;
 	struct nbd_reply reply;
 	struct nbd_cmd *cmd;
 	struct request *req = NULL;
 	u16 hwq;
-	int tag;
+	u32 tag;
 
 	reply.magic = 0;
-	result = sock_xmit(nbd, 0, &reply, sizeof(reply), MSG_WAITALL);
+	result = sock_xmit(nbd, index, 0, &reply, sizeof(reply), MSG_WAITALL);
 	if (result <= 0) {
-		dev_err(disk_to_dev(nbd->disk),
-			"Receive control failed (result %d)\n", result);
+		if (!test_bit(NBD_DISCONNECTED, &nbd->runtime_flags) &&
+		    !test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
+			dev_err(disk_to_dev(nbd->disk),
+				"Receive control failed (result %d)\n", result);
 		return ERR_PTR(result);
 	}
 
@@ -364,7 +380,7 @@ static struct nbd_cmd *nbd_read_stat(str
 		return ERR_PTR(-EPROTO);
 	}
 
-	memcpy(&tag, reply.handle, sizeof(int));
+	memcpy(&tag, reply.handle, sizeof(u32));
 
 	hwq = blk_mq_unique_tag_to_hwq(tag);
 	if (hwq < nbd->tag_set.nr_hw_queues)
@@ -376,7 +392,6 @@ static struct nbd_cmd *nbd_read_stat(str
 		return ERR_PTR(-ENOENT);
 	}
 	cmd = blk_mq_rq_to_pdu(req);
-
 	if (ntohl(reply.error)) {
 		dev_err(disk_to_dev(nbd->disk), "Other side returned error (%d)\n",
 			ntohl(reply.error));
@@ -390,7 +405,7 @@ static struct nbd_cmd *nbd_read_stat(str
 		struct bio_vec bvec;
 
 		rq_for_each_segment(bvec, req, iter) {
-			result = sock_recv_bvec(nbd, &bvec);
+			result = sock_recv_bvec(nbd, index, &bvec);
 			if (result <= 0) {
 				dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
 					result);
@@ -400,6 +415,9 @@ static struct nbd_cmd *nbd_read_stat(str
 			dev_dbg(nbd_to_dev(nbd), "request %p: got %d bytes data\n",
 				cmd, bvec.bv_len);
 		}
+	} else {
+		/* See the comment in nbd_queue_rq. */
+		wait_for_completion(&cmd->send_complete);
 	}
 	return cmd;
 }
@@ -418,25 +436,24 @@ static struct device_attribute pid_attr
 	.show = pid_show,
 };
 
-static int nbd_thread_recv(struct nbd_device *nbd, struct block_device *bdev)
+struct recv_thread_args {
+	struct work_struct work;
+	struct nbd_device *nbd;
+	int index;
+};
+
+static void recv_work(struct work_struct *work)
 {
+	struct recv_thread_args *args = container_of(work,
+						     struct recv_thread_args,
+						     work);
+	struct nbd_device *nbd = args->nbd;
 	struct nbd_cmd *cmd;
-	int ret;
+	int ret = 0;
 
 	BUG_ON(nbd->magic != NBD_MAGIC);
-
-	sk_set_memalloc(nbd->sock->sk);
-
-	ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
-	if (ret) {
-		dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
-		return ret;
-	}
-
-	nbd_size_update(nbd, bdev);
-
 	while (1) {
-		cmd = nbd_read_stat(nbd);
+		cmd = nbd_read_stat(nbd, args->index);
 		if (IS_ERR(cmd)) {
 			ret = PTR_ERR(cmd);
 			break;
@@ -445,10 +462,14 @@ static int nbd_thread_recv(struct nbd_de
 		nbd_end_request(cmd);
 	}
 
-	nbd_size_clear(nbd, bdev);
-
-	device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
-	return ret;
+	/*
+	 * We got an error, shut everybody down if this wasn't the result of a
+	 * disconnect request.
+	 */
+	if (ret && !test_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags))
+		sock_shutdown(nbd);
+	atomic_dec(&nbd->recv_threads);
+	wake_up(&nbd->recv_wq);
 }
 
 static void nbd_clear_req(struct request *req, void *data, bool reserved)
@@ -466,51 +487,60 @@ static void nbd_clear_que(struct nbd_dev
 {
 	BUG_ON(nbd->magic != NBD_MAGIC);
 
-	/*
-	 * Because we have set nbd->sock to NULL under the tx_lock, all
-	 * modifications to the list must have completed by now.
-	 */
-	BUG_ON(nbd->sock);
-
 	blk_mq_tagset_busy_iter(&nbd->tag_set, nbd_clear_req, NULL);
 	dev_dbg(disk_to_dev(nbd->disk), "queue cleared\n");
 }
 
 
-static void nbd_handle_cmd(struct nbd_cmd *cmd)
+static void nbd_handle_cmd(struct nbd_cmd *cmd, int index)
 {
 	struct request *req = blk_mq_rq_from_pdu(cmd);
 	struct nbd_device *nbd = cmd->nbd;
+	struct nbd_sock *nsock;
 
-	if (req->cmd_type != REQ_TYPE_FS)
+	if (index >= nbd->num_connections) {
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
+				    "Attempted send on invalid socket\n");
 		goto error_out;
+	}
 
-	if (rq_data_dir(req) == WRITE &&
+	if (test_bit(NBD_DISCONNECTED, &nbd->runtime_flags)) {
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
+				    "Attempted send on closed socket\n");
+		goto error_out;
+	}
+
+	if (req->cmd_type != REQ_TYPE_FS &&
+	    req->cmd_type != REQ_TYPE_DRV_PRIV)
+		goto error_out;
+
+	if (req->cmd_type == REQ_TYPE_FS &&
+	    rq_data_dir(req) == WRITE &&
 	    (nbd->flags & NBD_FLAG_READ_ONLY)) {
-		dev_err(disk_to_dev(nbd->disk),
-			"Write on read-only\n");
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
+				    "Write on read-only\n");
 		goto error_out;
 	}
 
 	req->errors = 0;
 
-	mutex_lock(&nbd->tx_lock);
-	nbd->task_send = current;
-	if (unlikely(!nbd->sock)) {
-		mutex_unlock(&nbd->tx_lock);
-		dev_err(disk_to_dev(nbd->disk),
-			"Attempted send on closed socket\n");
+	nsock = nbd->socks[index];
+	mutex_lock(&nsock->tx_lock);
+	if (unlikely(!nsock->sock)) {
+		mutex_unlock(&nsock->tx_lock);
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
+				    "Attempted send on closed socket\n");
 		goto error_out;
 	}
 
-	if (nbd_send_cmd(nbd, cmd) != 0) {
-		dev_err(disk_to_dev(nbd->disk), "Request send failed\n");
+	if (nbd_send_cmd(nbd, cmd, index) != 0) {
+		dev_err_ratelimited(disk_to_dev(nbd->disk),
+				    "Request send failed\n");
 		req->errors++;
 		nbd_end_request(cmd);
 	}
 
-	nbd->task_send = NULL;
-	mutex_unlock(&nbd->tx_lock);
+	mutex_unlock(&nsock->tx_lock);
 
 	return;
 
@@ -524,39 +554,70 @@ static int nbd_queue_rq(struct blk_mq_hw
 {
 	struct nbd_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
 
+	/*
+	 * Since we look at the bio's to send the request over the network we
+	 * need to make sure the completion work doesn't mark this request done
+	 * before we are done doing our send.  This keeps us from dereferencing
+	 * freed data if we have particularly fast completions (ie we get the
+	 * completion before we exit sock_xmit on the last bvec) or in the case
+	 * that the server is misbehaving (or there was an error) before we're
+	 * done sending everything over the wire.
+	 */
+	init_completion(&cmd->send_complete);
 	blk_mq_start_request(bd->rq);
-	nbd_handle_cmd(cmd);
+	nbd_handle_cmd(cmd, hctx->queue_num);
+	complete(&cmd->send_complete);
+
 	return BLK_MQ_RQ_QUEUE_OK;
 }
 
-static int nbd_set_socket(struct nbd_device *nbd, struct socket *sock)
+static int nbd_add_socket(struct nbd_device *nbd, struct socket *sock)
 {
-	int ret = 0;
-
-	spin_lock_irq(&nbd->sock_lock);
+	struct nbd_sock **socks;
+	struct nbd_sock *nsock;
 
-	if (nbd->sock) {
-		ret = -EBUSY;
-		goto out;
+	if (!nbd->task_setup)
+		nbd->task_setup = current;
+	if (nbd->task_setup != current) {
+		dev_err(disk_to_dev(nbd->disk),
+			"Device being setup by another task");
+		return -EINVAL;
 	}
 
-	nbd->sock = sock;
+	socks = krealloc(nbd->socks, (nbd->num_connections + 1) *
+			 sizeof(struct nbd_sock *), GFP_KERNEL);
+	if (!socks)
+		return -ENOMEM;
+	nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL);
+	if (!nsock)
+		return -ENOMEM;
 
-out:
-	spin_unlock_irq(&nbd->sock_lock);
+	nbd->socks = socks;
 
-	return ret;
+	mutex_init(&nsock->tx_lock);
+	nsock->sock = sock;
+	socks[nbd->num_connections++] = nsock;
+
+	return 0;
 }
 
 /* Reset all properties of an NBD device */
 static void nbd_reset(struct nbd_device *nbd)
 {
+	int i;
+
+	for (i = 0; i < nbd->num_connections; i++)
+		kfree(nbd->socks[i]);
+	kfree(nbd->socks);
+	nbd->socks = NULL;
 	nbd->runtime_flags = 0;
 	nbd->blksize = 1024;
 	nbd->bytesize = 0;
 	set_capacity(nbd->disk, 0);
 	nbd->flags = 0;
 	nbd->tag_set.timeout = 0;
+	nbd->num_connections = 0;
+	nbd->task_setup = NULL;
 	queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue);
 }
 
@@ -582,48 +643,68 @@ static void nbd_parse_flags(struct nbd_d
 		blk_queue_write_cache(nbd->disk->queue, false, false);
 }
 
+static void send_disconnects(struct nbd_device *nbd)
+{
+	struct nbd_request request = {};
+	int i, ret;
+
+	request.magic = htonl(NBD_REQUEST_MAGIC);
+	request.type = htonl(NBD_CMD_DISC);
+
+	for (i = 0; i < nbd->num_connections; i++) {
+		ret = sock_xmit(nbd, i, 1, &request, sizeof(request), 0);
+		if (ret <= 0)
+			dev_err(disk_to_dev(nbd->disk),
+				"Send disconnect failed %d\n", ret);
+	}
+}
+
 static int nbd_dev_dbg_init(struct nbd_device *nbd);
 static void nbd_dev_dbg_close(struct nbd_device *nbd);
 
-/* Must be called with tx_lock held */
-
+/* Must be called with config_lock held */
 static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
 		       unsigned int cmd, unsigned long arg)
 {
 	switch (cmd) {
 	case NBD_DISCONNECT: {
-		struct request *sreq;
-
 		dev_info(disk_to_dev(nbd->disk), "NBD_DISCONNECT\n");
-		if (!nbd->sock)
+		if (!nbd->socks)
 			return -EINVAL;
 
-		sreq = blk_mq_alloc_request(bdev_get_queue(bdev), WRITE, 0);
-		if (IS_ERR(sreq))
-			return -ENOMEM;
-
-		mutex_unlock(&nbd->tx_lock);
+		mutex_unlock(&nbd->config_lock);
 		fsync_bdev(bdev);
-		mutex_lock(&nbd->tx_lock);
-		sreq->cmd_type = REQ_TYPE_DRV_PRIV;
+		mutex_lock(&nbd->config_lock);
 
 		/* Check again after getting mutex back.  */
-		if (!nbd->sock) {
-			blk_mq_free_request(sreq);
+		if (!nbd->socks)
 			return -EINVAL;
-		}
-
-		set_bit(NBD_DISCONNECT_REQUESTED, &nbd->runtime_flags);
 
-		nbd_send_cmd(nbd, blk_mq_rq_to_pdu(sreq));
-		blk_mq_free_request(sreq);
+		if (!test_and_set_bit(NBD_DISCONNECT_REQUESTED,
+				      &nbd->runtime_flags))
+			send_disconnects(nbd);
 		return 0;
 	}
- 
+
 	case NBD_CLEAR_SOCK:
 		sock_shutdown(nbd);
 		nbd_clear_que(nbd);
 		kill_bdev(bdev);
+		nbd_bdev_reset(bdev);
+		/*
+		 * We want to give the run thread a chance to wait for everybody
+		 * to clean up and then do it's own cleanup.
+		 */
+		if (!test_bit(NBD_RUNNING, &nbd->runtime_flags)) {
+			int i;
+
+			for (i = 0; i < nbd->num_connections; i++)
+				kfree(nbd->socks[i]);
+			kfree(nbd->socks);
+			nbd->socks = NULL;
+			nbd->num_connections = 0;
+			nbd->task_setup = NULL;
+		}
 		return 0;
 
 	case NBD_SET_SOCK: {
@@ -633,7 +714,7 @@ static int __nbd_ioctl(struct block_devi
 		if (!sock)
 			return err;
 
-		err = nbd_set_socket(nbd, sock);
+		err = nbd_add_socket(nbd, sock);
 		if (!err && max_part)
 			bdev->bd_invalidated = 1;
 
@@ -648,7 +729,7 @@ static int __nbd_ioctl(struct block_devi
 
 	case NBD_SET_SIZE:
 		return nbd_size_set(nbd, bdev, nbd->blksize,
-				    arg / nbd->blksize);
+					div_s64(arg, nbd->blksize));
 
 	case NBD_SET_SIZE_BLOCKS:
 		return nbd_size_set(nbd, bdev, nbd->blksize, arg);
@@ -662,26 +743,61 @@ static int __nbd_ioctl(struct block_devi
 		return 0;
 
 	case NBD_DO_IT: {
-		int error;
+		struct recv_thread_args *args;
+		int num_connections = nbd->num_connections;
+		int error = 0, i;
 
 		if (nbd->task_recv)
 			return -EBUSY;
-		if (!nbd->sock)
+		if (!nbd->socks)
 			return -EINVAL;
+		if (num_connections > 1 &&
+		    !(nbd->flags & NBD_FLAG_CAN_MULTI_CONN)) {
+			dev_err(disk_to_dev(nbd->disk), "server does not support multiple connections per device.\n");
+			error = -EINVAL;
+			goto out_err;
+		}
 
-		/* We have to claim the device under the lock */
+		set_bit(NBD_RUNNING, &nbd->runtime_flags);
+		blk_mq_update_nr_hw_queues(&nbd->tag_set, nbd->num_connections);
+		args = kcalloc(num_connections, sizeof(*args), GFP_KERNEL);
+		if (!args) {
+			error = -ENOMEM;
+			goto out_err;
+		}
 		nbd->task_recv = current;
-		mutex_unlock(&nbd->tx_lock);
+		mutex_unlock(&nbd->config_lock);
 
 		nbd_parse_flags(nbd, bdev);
 
+		error = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
+		if (error) {
+			dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
+			goto out_recv;
+		}
+
+		nbd_size_update(nbd, bdev);
+
 		nbd_dev_dbg_init(nbd);
-		error = nbd_thread_recv(nbd, bdev);
+		for (i = 0; i < num_connections; i++) {
+			sk_set_memalloc(nbd->socks[i]->sock->sk);
+			atomic_inc(&nbd->recv_threads);
+			INIT_WORK(&args[i].work, recv_work);
+			args[i].nbd = nbd;
+			args[i].index = i;
+			queue_work(system_long_wq, &args[i].work);
+		}
+		wait_event_interruptible(nbd->recv_wq,
+					 atomic_read(&nbd->recv_threads) == 0);
+		for (i = 0; i < num_connections; i++)
+			flush_work(&args[i].work);
 		nbd_dev_dbg_close(nbd);
-
-		mutex_lock(&nbd->tx_lock);
+		nbd_size_clear(nbd, bdev);
+		device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
+out_recv:
+		mutex_lock(&nbd->config_lock);
 		nbd->task_recv = NULL;
-
+out_err:
 		sock_shutdown(nbd);
 		nbd_clear_que(nbd);
 		kill_bdev(bdev);
@@ -694,7 +810,6 @@ static int __nbd_ioctl(struct block_devi
 			error = -ETIMEDOUT;
 
 		nbd_reset(nbd);
-
 		return error;
 	}
 
@@ -726,9 +841,9 @@ static int nbd_ioctl(struct block_device
 
 	BUG_ON(nbd->magic != NBD_MAGIC);
 
-	mutex_lock(&nbd->tx_lock);
+	mutex_lock(&nbd->config_lock);
 	error = __nbd_ioctl(bdev, nbd, cmd, arg);
-	mutex_unlock(&nbd->tx_lock);
+	mutex_unlock(&nbd->config_lock);
 
 	return error;
 }
@@ -748,8 +863,6 @@ static int nbd_dbg_tasks_show(struct seq
 
 	if (nbd->task_recv)
 		seq_printf(s, "recv: %d\n", task_pid_nr(nbd->task_recv));
-	if (nbd->task_send)
-		seq_printf(s, "send: %d\n", task_pid_nr(nbd->task_send));
 
 	return 0;
 }
@@ -817,7 +930,7 @@ static int nbd_dev_dbg_init(struct nbd_d
 	debugfs_create_file("tasks", 0444, dir, nbd, &nbd_dbg_tasks_ops);
 	debugfs_create_u64("size_bytes", 0444, dir, &nbd->bytesize);
 	debugfs_create_u32("timeout", 0444, dir, &nbd->tag_set.timeout);
-	debugfs_create_u32("blocksize", 0444, dir, &nbd->blksize);
+	debugfs_create_u64("blocksize", 0444, dir, &nbd->blksize);
 	debugfs_create_file("flags", 0444, dir, nbd, &nbd_dbg_flags_ops);
 
 	return 0;
@@ -873,9 +986,7 @@ static int nbd_init_request(void *data,
 			    unsigned int numa_node)
 {
 	struct nbd_cmd *cmd = blk_mq_rq_to_pdu(rq);
-
 	cmd->nbd = data;
-	INIT_LIST_HEAD(&cmd->list);
 	return 0;
 }
 
@@ -929,6 +1040,7 @@ static int __init nbd_init(void)
 		return -ENOMEM;
 
 	for (i = 0; i < nbds_max; i++) {
+		struct request_queue *q;
 		struct gendisk *disk = alloc_disk(1 << part_shift);
 		if (!disk)
 			goto out;
@@ -954,12 +1066,13 @@ static int __init nbd_init(void)
 		 * every gendisk to have its very own request_queue struct.
 		 * These structs are big so we dynamically allocate them.
 		 */
-		disk->queue = blk_mq_init_queue(&nbd_dev[i].tag_set);
-		if (!disk->queue) {
+		q = blk_mq_init_queue(&nbd_dev[i].tag_set);
+		if (IS_ERR(q)) {
 			blk_mq_free_tag_set(&nbd_dev[i].tag_set);
 			put_disk(disk);
 			goto out;
 		}
+		disk->queue = q;
 
 		/*
 		 * Tell the block layer that we are not a rotational device
@@ -985,13 +1098,13 @@ static int __init nbd_init(void)
 	for (i = 0; i < nbds_max; i++) {
 		struct gendisk *disk = nbd_dev[i].disk;
 		nbd_dev[i].magic = NBD_MAGIC;
-		spin_lock_init(&nbd_dev[i].sock_lock);
-		mutex_init(&nbd_dev[i].tx_lock);
+		mutex_init(&nbd_dev[i].config_lock);
 		disk->major = NBD_MAJOR;
 		disk->first_minor = i << part_shift;
 		disk->fops = &nbd_fops;
 		disk->private_data = &nbd_dev[i];
 		sprintf(disk->disk_name, "nbd%d", i);
+		init_waitqueue_head(&nbd_dev[i].recv_wq);
 		nbd_reset(&nbd_dev[i]);
 		add_disk(disk);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/null_blk.c linux-libre-4.10-rc8-gnu/drivers/block/null_blk.c
--- linux-libre-4.9-gnu/drivers/block/null_blk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/null_blk.c	2017-02-12 16:03:20.000000000 -0500
@@ -257,7 +257,7 @@ static enum hrtimer_restart null_cmd_tim
 
 static void null_cmd_end_timer(struct nullb_cmd *cmd)
 {
-	ktime_t kt = ktime_set(0, completion_nsec);
+	ktime_t kt = completion_nsec;
 
 	hrtimer_start(&cmd->timer, kt, HRTIMER_MODE_REL);
 }
@@ -577,6 +577,7 @@ static void null_nvm_unregister(struct n
 #else
 static int null_nvm_register(struct nullb *nullb)
 {
+	pr_err("null_blk: CONFIG_NVM needs to be enabled for LightNVM\n");
 	return -EINVAL;
 }
 static void null_nvm_unregister(struct nullb *nullb) {}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/paride/pcd.c linux-libre-4.10-rc8-gnu/drivers/block/paride/pcd.c
--- linux-libre-4.9-gnu/drivers/block/paride/pcd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/paride/pcd.c	2017-02-12 16:03:20.000000000 -0500
@@ -139,7 +139,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV,
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static DEFINE_MUTEX(pcd_mutex);
 static DEFINE_SPINLOCK(pcd_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/paride/pd.c linux-libre-4.10-rc8-gnu/drivers/block/paride/pd.c
--- linux-libre-4.9-gnu/drivers/block/paride/pd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/paride/pd.c	2017-02-12 16:03:20.000000000 -0500
@@ -155,7 +155,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO,
 #include <linux/blkpg.h>
 #include <linux/kernel.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/workqueue.h>
 
 static DEFINE_MUTEX(pd_mutex);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/paride/pf.c linux-libre-4.10-rc8-gnu/drivers/block/paride/pf.c
--- linux-libre-4.9-gnu/drivers/block/paride/pf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/paride/pf.c	2017-02-12 16:03:20.000000000 -0500
@@ -155,7 +155,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV,
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static DEFINE_MUTEX(pf_mutex);
 static DEFINE_SPINLOCK(pf_spin_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/paride/pg.c linux-libre-4.10-rc8-gnu/drivers/block/paride/pg.c
--- linux-libre-4.9-gnu/drivers/block/paride/pg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/paride/pg.c	2017-02-12 16:03:20.000000000 -0500
@@ -166,7 +166,7 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV,
 #include <linux/mutex.h>
 #include <linux/jiffies.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 module_param(verbose, int, 0644);
 module_param(major, int, 0);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/paride/pt.c linux-libre-4.10-rc8-gnu/drivers/block/paride/pt.c
--- linux-libre-4.9-gnu/drivers/block/paride/pt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/paride/pt.c	2017-02-12 16:03:20.000000000 -0500
@@ -150,7 +150,7 @@ static int (*drives[4])[6] = {&drive0, &
 #include <linux/sched.h>	/* current, TASK_*, schedule_timeout() */
 #include <linux/mutex.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 module_param(verbose, int, 0);
 module_param(major, int, 0);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/pktcdvd.c linux-libre-4.10-rc8-gnu/drivers/block/pktcdvd.c
--- linux-libre-4.9-gnu/drivers/block/pktcdvd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/pktcdvd.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,7 +68,7 @@
 #include <linux/debugfs.h>
 #include <linux/device.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define DRIVER_NAME	"pktcdvd"
 
@@ -721,7 +721,7 @@ static int pkt_generic_packet(struct pkt
 
 	rq->timeout = 60*HZ;
 	if (cgc->quiet)
-		rq->cmd_flags |= REQ_QUIET;
+		rq->rq_flags |= RQF_QUIET;
 
 	blk_execute_rq(rq->q, pd->bdev->bd_disk, rq, 0);
 	if (rq->errors)
@@ -944,39 +944,6 @@ static int pkt_set_segment_merging(struc
 	}
 }
 
-/*
- * Copy all data for this packet to pkt->pages[], so that
- * a) The number of required segments for the write bio is minimized, which
- *    is necessary for some scsi controllers.
- * b) The data can be used as cache to avoid read requests if we receive a
- *    new write request for the same zone.
- */
-static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec)
-{
-	int f, p, offs;
-
-	/* Copy all data to pkt->pages[] */
-	p = 0;
-	offs = 0;
-	for (f = 0; f < pkt->frames; f++) {
-		if (bvec[f].bv_page != pkt->pages[p]) {
-			void *vfrom = kmap_atomic(bvec[f].bv_page) + bvec[f].bv_offset;
-			void *vto = page_address(pkt->pages[p]) + offs;
-			memcpy(vto, vfrom, CD_FRAMESIZE);
-			kunmap_atomic(vfrom);
-			bvec[f].bv_page = pkt->pages[p];
-			bvec[f].bv_offset = offs;
-		} else {
-			BUG_ON(bvec[f].bv_offset != offs);
-		}
-		offs += CD_FRAMESIZE;
-		if (offs >= PAGE_SIZE) {
-			offs = 0;
-			p++;
-		}
-	}
-}
-
 static void pkt_end_io_read(struct bio *bio)
 {
 	struct packet_data *pkt = bio->bi_private;
@@ -1298,7 +1265,6 @@ try_next_bio:
 static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
 {
 	int f;
-	struct bio_vec *bvec = pkt->w_bio->bi_io_vec;
 
 	bio_reset(pkt->w_bio);
 	pkt->w_bio->bi_iter.bi_sector = pkt->sector;
@@ -1308,9 +1274,10 @@ static void pkt_start_write(struct pktcd
 
 	/* XXX: locking? */
 	for (f = 0; f < pkt->frames; f++) {
-		bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
-		bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
-		if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
+		struct page *page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
+		unsigned offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
+
+		if (!bio_add_page(pkt->w_bio, page, CD_FRAMESIZE, offset))
 			BUG();
 	}
 	pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt);
@@ -1327,12 +1294,10 @@ static void pkt_start_write(struct pktcd
 	pkt_dbg(2, pd, "Writing %d frames for zone %llx\n",
 		pkt->write_size, (unsigned long long)pkt->sector);
 
-	if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
-		pkt_make_local_copy(pkt, bvec);
+	if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames))
 		pkt->cache_valid = 1;
-	} else {
+	else
 		pkt->cache_valid = 0;
-	}
 
 	/* Start the write request */
 	atomic_set(&pkt->io_wait, 1);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/rbd.c linux-libre-4.10-rc8-gnu/drivers/block/rbd.c
--- linux-libre-4.9-gnu/drivers/block/rbd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/rbd.c	2017-02-12 16:03:20.000000000 -0500
@@ -3756,7 +3756,7 @@ static void rbd_watch_cb(void *arg, u64
 	struct rbd_device *rbd_dev = arg;
 	void *p = data;
 	void *const end = p + data_len;
-	u8 struct_v;
+	u8 struct_v = 0;
 	u32 len;
 	u32 notify_op;
 	int ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/skd_main.c linux-libre-4.10-rc8-gnu/drivers/block/skd_main.c
--- linux-libre-4.9-gnu/drivers/block/skd_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/skd_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,6 @@
 #include <linux/scatterlist.h>
 #include <linux/version.h>
 #include <linux/err.h>
-#include <linux/scatterlist.h>
 #include <linux/aer.h>
 #include <linux/ctype.h>
 #include <linux/wait.h>
@@ -270,8 +269,6 @@ struct skd_device {
 	resource_size_t mem_phys[SKD_MAX_BARS];
 	u32 mem_size[SKD_MAX_BARS];
 
-	skd_irq_type_t irq_type;
-	u32 msix_count;
 	struct skd_msix_entry *msix_entries;
 
 	struct pci_dev *pdev;
@@ -2138,12 +2135,8 @@ static void skd_send_fitmsg(struct skd_d
 		u8 *bp = (u8 *)skmsg->msg_buf;
 		int i;
 		for (i = 0; i < skmsg->length; i += 8) {
-			pr_debug("%s:%s:%d msg[%2d] %02x %02x %02x %02x "
-				 "%02x %02x %02x %02x\n",
-				 skdev->name, __func__, __LINE__,
-				 i, bp[i + 0], bp[i + 1], bp[i + 2],
-				 bp[i + 3], bp[i + 4], bp[i + 5],
-				 bp[i + 6], bp[i + 7]);
+			pr_debug("%s:%s:%d msg[%2d] %8ph\n",
+				 skdev->name, __func__, __LINE__, i, &bp[i]);
 			if (i == 0)
 				i = 64 - 8;
 		}
@@ -2164,7 +2157,6 @@ static void skd_send_fitmsg(struct skd_d
 		qcmd |= FIT_QCMD_MSGSIZE_64;
 
 	SKD_WRITEQ(skdev, qcmd, FIT_Q_COMMAND);
-
 }
 
 static void skd_send_special_fitmsg(struct skd_device *skdev,
@@ -2177,11 +2169,8 @@ static void skd_send_special_fitmsg(stru
 		int i;
 
 		for (i = 0; i < SKD_N_SPECIAL_FITMSG_BYTES; i += 8) {
-			pr_debug("%s:%s:%d  spcl[%2d] %02x %02x %02x %02x  "
-				 "%02x %02x %02x %02x\n",
-				 skdev->name, __func__, __LINE__, i,
-				 bp[i + 0], bp[i + 1], bp[i + 2], bp[i + 3],
-				 bp[i + 4], bp[i + 5], bp[i + 6], bp[i + 7]);
+			pr_debug("%s:%s:%d  spcl[%2d] %8ph\n",
+				 skdev->name, __func__, __LINE__, i, &bp[i]);
 			if (i == 0)
 				i = 64 - 8;
 		}
@@ -2955,8 +2944,8 @@ static void skd_completion_worker(struct
 
 static void skd_isr_msg_from_dev(struct skd_device *skdev);
 
-irqreturn_t
-static skd_isr(int irq, void *ptr)
+static irqreturn_t
+skd_isr(int irq, void *ptr)
 {
 	struct skd_device *skdev;
 	u32 intstat;
@@ -3821,10 +3810,6 @@ static irqreturn_t skd_qfull_isr(int irq
  */
 
 struct skd_msix_entry {
-	int have_irq;
-	u32 vector;
-	u32 entry;
-	struct skd_device *rsp;
 	char isr_name[30];
 };
 
@@ -3853,193 +3838,121 @@ static struct skd_init_msix_entry msix_e
 	{ "(Queue Full 3)", skd_qfull_isr    },
 };
 
-static void skd_release_msix(struct skd_device *skdev)
-{
-	struct skd_msix_entry *qentry;
-	int i;
-
-	if (skdev->msix_entries) {
-		for (i = 0; i < skdev->msix_count; i++) {
-			qentry = &skdev->msix_entries[i];
-			skdev = qentry->rsp;
-
-			if (qentry->have_irq)
-				devm_free_irq(&skdev->pdev->dev,
-					      qentry->vector, qentry->rsp);
-		}
-
-		kfree(skdev->msix_entries);
-	}
-
-	if (skdev->msix_count)
-		pci_disable_msix(skdev->pdev);
-
-	skdev->msix_count = 0;
-	skdev->msix_entries = NULL;
-}
-
 static int skd_acquire_msix(struct skd_device *skdev)
 {
 	int i, rc;
 	struct pci_dev *pdev = skdev->pdev;
-	struct msix_entry *entries;
-	struct skd_msix_entry *qentry;
 
-	entries = kzalloc(sizeof(struct msix_entry) * SKD_MAX_MSIX_COUNT,
-			  GFP_KERNEL);
-	if (!entries)
-		return -ENOMEM;
-
-	for (i = 0; i < SKD_MAX_MSIX_COUNT; i++)
-		entries[i].entry = i;
-
-	rc = pci_enable_msix_exact(pdev, entries, SKD_MAX_MSIX_COUNT);
-	if (rc) {
+	rc = pci_alloc_irq_vectors(pdev, SKD_MAX_MSIX_COUNT, SKD_MAX_MSIX_COUNT,
+			PCI_IRQ_MSIX);
+	if (rc < 0) {
 		pr_err("(%s): failed to enable MSI-X %d\n",
 		       skd_name(skdev), rc);
-		goto msix_out;
+		goto out;
 	}
 
-	skdev->msix_count = SKD_MAX_MSIX_COUNT;
-	skdev->msix_entries = kzalloc(sizeof(struct skd_msix_entry) *
-				      skdev->msix_count, GFP_KERNEL);
+	skdev->msix_entries = kcalloc(SKD_MAX_MSIX_COUNT,
+			sizeof(struct skd_msix_entry), GFP_KERNEL);
 	if (!skdev->msix_entries) {
 		rc = -ENOMEM;
 		pr_err("(%s): msix table allocation error\n",
 		       skd_name(skdev));
-		goto msix_out;
-	}
-
-	for (i = 0; i < skdev->msix_count; i++) {
-		qentry = &skdev->msix_entries[i];
-		qentry->vector = entries[i].vector;
-		qentry->entry = entries[i].entry;
-		qentry->rsp = NULL;
-		qentry->have_irq = 0;
-		pr_debug("%s:%s:%d %s: <%s> msix (%d) vec %d, entry %x\n",
-			 skdev->name, __func__, __LINE__,
-			 pci_name(pdev), skdev->name,
-			 i, qentry->vector, qentry->entry);
+		goto out;
 	}
 
 	/* Enable MSI-X vectors for the base queue */
-	for (i = 0; i < skdev->msix_count; i++) {
-		qentry = &skdev->msix_entries[i];
+	for (i = 0; i < SKD_MAX_MSIX_COUNT; i++) {
+		struct skd_msix_entry *qentry = &skdev->msix_entries[i];
+
 		snprintf(qentry->isr_name, sizeof(qentry->isr_name),
 			 "%s%d-msix %s", DRV_NAME, skdev->devno,
 			 msix_entries[i].name);
-		rc = devm_request_irq(&skdev->pdev->dev, qentry->vector,
-				      msix_entries[i].handler, 0,
-				      qentry->isr_name, skdev);
+
+		rc = devm_request_irq(&skdev->pdev->dev,
+				pci_irq_vector(skdev->pdev, i),
+				msix_entries[i].handler, 0,
+				qentry->isr_name, skdev);
 		if (rc) {
 			pr_err("(%s): Unable to register(%d) MSI-X "
 			       "handler %d: %s\n",
 			       skd_name(skdev), rc, i, qentry->isr_name);
 			goto msix_out;
-		} else {
-			qentry->have_irq = 1;
-			qentry->rsp = skdev;
 		}
 	}
+
 	pr_debug("%s:%s:%d %s: <%s> msix %d irq(s) enabled\n",
 		 skdev->name, __func__, __LINE__,
-		 pci_name(pdev), skdev->name, skdev->msix_count);
+		 pci_name(pdev), skdev->name, SKD_MAX_MSIX_COUNT);
 	return 0;
 
 msix_out:
-	if (entries)
-		kfree(entries);
-	skd_release_msix(skdev);
+	while (--i >= 0)
+		devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i), skdev);
+out:
+	kfree(skdev->msix_entries);
+	skdev->msix_entries = NULL;
 	return rc;
 }
 
 static int skd_acquire_irq(struct skd_device *skdev)
 {
+	struct pci_dev *pdev = skdev->pdev;
+	unsigned int irq_flag = PCI_IRQ_LEGACY;
 	int rc;
-	struct pci_dev *pdev;
-
-	pdev = skdev->pdev;
-	skdev->msix_count = 0;
 
-RETRY_IRQ_TYPE:
-	switch (skdev->irq_type) {
-	case SKD_IRQ_MSIX:
+	if (skd_isr_type == SKD_IRQ_MSIX) {
 		rc = skd_acquire_msix(skdev);
 		if (!rc)
-			pr_info("(%s): MSI-X %d irqs enabled\n",
-			       skd_name(skdev), skdev->msix_count);
-		else {
-			pr_err(
-			       "(%s): failed to enable MSI-X, re-trying with MSI %d\n",
-			       skd_name(skdev), rc);
-			skdev->irq_type = SKD_IRQ_MSI;
-			goto RETRY_IRQ_TYPE;
-		}
-		break;
-	case SKD_IRQ_MSI:
-		snprintf(skdev->isr_name, sizeof(skdev->isr_name), "%s%d-msi",
-			 DRV_NAME, skdev->devno);
-		rc = pci_enable_msi_range(pdev, 1, 1);
-		if (rc > 0) {
-			rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr, 0,
-					      skdev->isr_name, skdev);
-			if (rc) {
-				pci_disable_msi(pdev);
-				pr_err(
-				       "(%s): failed to allocate the MSI interrupt %d\n",
-				       skd_name(skdev), rc);
-				goto RETRY_IRQ_LEGACY;
-			}
-			pr_info("(%s): MSI irq %d enabled\n",
-			       skd_name(skdev), pdev->irq);
-		} else {
-RETRY_IRQ_LEGACY:
-			pr_err(
-			       "(%s): failed to enable MSI, re-trying with LEGACY %d\n",
-			       skd_name(skdev), rc);
-			skdev->irq_type = SKD_IRQ_LEGACY;
-			goto RETRY_IRQ_TYPE;
-		}
-		break;
-	case SKD_IRQ_LEGACY:
-		snprintf(skdev->isr_name, sizeof(skdev->isr_name),
-			 "%s%d-legacy", DRV_NAME, skdev->devno);
-		rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr,
-				      IRQF_SHARED, skdev->isr_name, skdev);
-		if (!rc)
-			pr_info("(%s): LEGACY irq %d enabled\n",
-			       skd_name(skdev), pdev->irq);
-		else
-			pr_err("(%s): request LEGACY irq error %d\n",
-			       skd_name(skdev), rc);
-		break;
-	default:
-		pr_info("(%s): irq_type %d invalid, re-set to %d\n",
-		       skd_name(skdev), skdev->irq_type, SKD_IRQ_DEFAULT);
-		skdev->irq_type = SKD_IRQ_LEGACY;
-		goto RETRY_IRQ_TYPE;
+			return 0;
+
+		pr_err("(%s): failed to enable MSI-X, re-trying with MSI %d\n",
+		       skd_name(skdev), rc);
 	}
-	return rc;
+
+	snprintf(skdev->isr_name, sizeof(skdev->isr_name), "%s%d", DRV_NAME,
+			skdev->devno);
+
+	if (skd_isr_type != SKD_IRQ_LEGACY)
+		irq_flag |= PCI_IRQ_MSI;
+	rc = pci_alloc_irq_vectors(pdev, 1, 1, irq_flag);
+	if (rc < 0) {
+		pr_err("(%s): failed to allocate the MSI interrupt %d\n",
+			skd_name(skdev), rc);
+		return rc;
+	}
+
+	rc = devm_request_irq(&pdev->dev, pdev->irq, skd_isr,
+			pdev->msi_enabled ? 0 : IRQF_SHARED,
+			skdev->isr_name, skdev);
+	if (rc) {
+		pci_free_irq_vectors(pdev);
+		pr_err("(%s): failed to allocate interrupt %d\n",
+			skd_name(skdev), rc);
+		return rc;
+	}
+
+	return 0;
 }
 
 static void skd_release_irq(struct skd_device *skdev)
 {
-	switch (skdev->irq_type) {
-	case SKD_IRQ_MSIX:
-		skd_release_msix(skdev);
-		break;
-	case SKD_IRQ_MSI:
-		devm_free_irq(&skdev->pdev->dev, skdev->pdev->irq, skdev);
-		pci_disable_msi(skdev->pdev);
-		break;
-	case SKD_IRQ_LEGACY:
-		devm_free_irq(&skdev->pdev->dev, skdev->pdev->irq, skdev);
-		break;
-	default:
-		pr_err("(%s): wrong irq type %d!",
-		       skd_name(skdev), skdev->irq_type);
-		break;
+	struct pci_dev *pdev = skdev->pdev;
+
+	if (skdev->msix_entries) {
+		int i;
+
+		for (i = 0; i < SKD_MAX_MSIX_COUNT; i++) {
+			devm_free_irq(&pdev->dev, pci_irq_vector(pdev, i),
+					skdev);
+		}
+
+		kfree(skdev->msix_entries);
+		skdev->msix_entries = NULL;
+	} else {
+		devm_free_irq(&pdev->dev, pdev->irq, skdev);
 	}
+
+	pci_free_irq_vectors(pdev);
 }
 
 /*
@@ -4402,7 +4315,6 @@ static struct skd_device *skd_construct(
 	skdev->pdev = pdev;
 	skdev->devno = skd_next_devno++;
 	skdev->major = blk_major;
-	skdev->irq_type = skd_isr_type;
 	sprintf(skdev->name, DRV_NAME "%d", skdev->devno);
 	skdev->dev_max_queue_depth = 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/swim3.c linux-libre-4.10-rc8-gnu/drivers/block/swim3.c
--- linux-libre-4.9-gnu/drivers/block/swim3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/swim3.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <asm/io.h>
 #include <asm/dbdma.h>
 #include <asm/prom.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mediabay.h>
 #include <asm/machdep.h>
 #include <asm/pmac_feature.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/sx8.c linux-libre-4.10-rc8-gnu/drivers/block/sx8.c
--- linux-libre-4.9-gnu/drivers/block/sx8.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/sx8.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/completion.h>
 #include <linux/scatterlist.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #if 0
 #define CARM_DEBUG
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/umem.c linux-libre-4.10-rc8-gnu/drivers/block/umem.c
--- linux-libre-4.9-gnu/drivers/block/umem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/umem.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 
 #include "umem.h"
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #define MM_MAXCARDS 4
@@ -535,7 +535,7 @@ static blk_qc_t mm_make_request(struct r
 	*card->biotail = bio;
 	bio->bi_next = NULL;
 	card->biotail = &bio->bi_next;
-	if (bio->bi_opf & REQ_SYNC || !mm_check_plugged(card))
+	if (op_is_sync(bio->bi_opf) || !mm_check_plugged(card))
 		activate(card);
 	spin_unlock_irq(&card->lock);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/virtio_blk.c linux-libre-4.10-rc8-gnu/drivers/block/virtio_blk.c
--- linux-libre-4.9-gnu/drivers/block/virtio_blk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/virtio_blk.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,6 +56,7 @@ struct virtblk_req {
 	struct virtio_blk_outhdr out_hdr;
 	struct virtio_scsi_inhdr in_hdr;
 	u8 status;
+	u8 sense[SCSI_SENSE_BUFFERSIZE];
 	struct scatterlist sg[];
 };
 
@@ -102,7 +103,8 @@ static int __virtblk_add_req(struct virt
 	}
 
 	if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
-		sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
+		memcpy(vbr->sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
+		sg_init_one(&sense, vbr->sense, SCSI_SENSE_BUFFERSIZE);
 		sgs[num_out + num_in++] = &sense;
 		sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
 		sgs[num_out + num_in++] = &inhdr;
@@ -628,11 +630,12 @@ static int virtblk_probe(struct virtio_d
 	if (err)
 		goto out_put_disk;
 
-	q = vblk->disk->queue = blk_mq_init_queue(&vblk->tag_set);
+	q = blk_mq_init_queue(&vblk->tag_set);
 	if (IS_ERR(q)) {
 		err = -ENOMEM;
 		goto out_free_tags;
 	}
+	vblk->disk->queue = q;
 
 	q->queuedata = vblk;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/xen-blkback/blkback.c linux-libre-4.10-rc8-gnu/drivers/block/xen-blkback/blkback.c
--- linux-libre-4.9-gnu/drivers/block/xen-blkback/blkback.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/xen-blkback/blkback.c	2017-02-12 16:03:20.000000000 -0500
@@ -1253,14 +1253,14 @@ static int dispatch_rw_block_io(struct x
 	case BLKIF_OP_WRITE:
 		ring->st_wr_req++;
 		operation = REQ_OP_WRITE;
-		operation_flags = WRITE_ODIRECT;
+		operation_flags = REQ_SYNC | REQ_IDLE;
 		break;
 	case BLKIF_OP_WRITE_BARRIER:
 		drain = true;
 	case BLKIF_OP_FLUSH_DISKCACHE:
 		ring->st_f_req++;
 		operation = REQ_OP_WRITE;
-		operation_flags = WRITE_FLUSH;
+		operation_flags = REQ_PREFLUSH;
 		break;
 	default:
 		operation = 0; /* make gcc happy */
@@ -1272,7 +1272,7 @@ static int dispatch_rw_block_io(struct x
 	nseg = req->operation == BLKIF_OP_INDIRECT ?
 	       req->u.indirect.nr_segments : req->u.rw.nr_segments;
 
-	if (unlikely(nseg == 0 && operation_flags != WRITE_FLUSH) ||
+	if (unlikely(nseg == 0 && operation_flags != REQ_PREFLUSH) ||
 	    unlikely((req->operation != BLKIF_OP_INDIRECT) &&
 		     (nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) ||
 	    unlikely((req->operation == BLKIF_OP_INDIRECT) &&
@@ -1334,7 +1334,7 @@ static int dispatch_rw_block_io(struct x
 	}
 
 	/* Wait on all outstanding I/O's and once that has been completed
-	 * issue the WRITE_FLUSH.
+	 * issue the flush.
 	 */
 	if (drain)
 		xen_blk_drain_io(pending_req->ring);
@@ -1380,7 +1380,7 @@ static int dispatch_rw_block_io(struct x
 
 	/* This will be hit if the operation was a flush or discard. */
 	if (!bio) {
-		BUG_ON(operation_flags != WRITE_FLUSH);
+		BUG_ON(operation_flags != REQ_PREFLUSH);
 
 		bio = bio_alloc(GFP_KERNEL, 0);
 		if (unlikely(bio == NULL))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/xen-blkback/xenbus.c linux-libre-4.10-rc8-gnu/drivers/block/xen-blkback/xenbus.c
--- linux-libre-4.9-gnu/drivers/block/xen-blkback/xenbus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/xen-blkback/xenbus.c	2017-02-12 16:03:20.000000000 -0500
@@ -533,13 +533,11 @@ static void xen_blkbk_discard(struct xen
 	struct xenbus_device *dev = be->dev;
 	struct xen_blkif *blkif = be->blkif;
 	int err;
-	int state = 0, discard_enable;
+	int state = 0;
 	struct block_device *bdev = be->blkif->vbd.bdev;
 	struct request_queue *q = bdev_get_queue(bdev);
 
-	err = xenbus_scanf(XBT_NIL, dev->nodename, "discard-enable", "%d",
-			   &discard_enable);
-	if (err == 1 && !discard_enable)
+	if (!xenbus_read_unsigned(dev->nodename, "discard-enable", 1))
 		return;
 
 	if (blk_queue_discard(q)) {
@@ -1039,30 +1037,24 @@ static int connect_ring(struct backend_i
 		xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol);
 		return -ENOSYS;
 	}
-	err = xenbus_scanf(XBT_NIL, dev->otherend,
-			   "feature-persistent", "%u", &pers_grants);
-	if (err <= 0)
-		pers_grants = 0;
-
+	pers_grants = xenbus_read_unsigned(dev->otherend, "feature-persistent",
+					   0);
 	be->blkif->vbd.feature_gnt_persistent = pers_grants;
 	be->blkif->vbd.overflow_max_grants = 0;
 
 	/*
 	 * Read the number of hardware queues from frontend.
 	 */
-	err = xenbus_scanf(XBT_NIL, dev->otherend, "multi-queue-num-queues",
-			   "%u", &requested_num_queues);
-	if (err < 0) {
-		requested_num_queues = 1;
-	} else {
-		if (requested_num_queues > xenblk_max_queues
-		    || requested_num_queues == 0) {
-			/* Buggy or malicious guest. */
-			xenbus_dev_fatal(dev, err,
-					"guest requested %u queues, exceeding the maximum of %u.",
-					requested_num_queues, xenblk_max_queues);
-			return -ENOSYS;
-		}
+	requested_num_queues = xenbus_read_unsigned(dev->otherend,
+						    "multi-queue-num-queues",
+						    1);
+	if (requested_num_queues > xenblk_max_queues
+	    || requested_num_queues == 0) {
+		/* Buggy or malicious guest. */
+		xenbus_dev_fatal(dev, err,
+				"guest requested %u queues, exceeding the maximum of %u.",
+				requested_num_queues, xenblk_max_queues);
+		return -ENOSYS;
 	}
 	be->blkif->nr_rings = requested_num_queues;
 	if (xen_blkif_alloc_rings(be->blkif))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/xen-blkfront.c linux-libre-4.10-rc8-gnu/drivers/block/xen-blkfront.c
--- linux-libre-4.9-gnu/drivers/block/xen-blkfront.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/xen-blkfront.c	2017-02-12 16:03:20.000000000 -0500
@@ -197,13 +197,13 @@ struct blkfront_info
 	/* Number of pages per ring buffer. */
 	unsigned int nr_ring_pages;
 	struct request_queue *rq;
-	unsigned int feature_flush;
-	unsigned int feature_fua;
+	unsigned int feature_flush:1;
+	unsigned int feature_fua:1;
 	unsigned int feature_discard:1;
 	unsigned int feature_secdiscard:1;
+	unsigned int feature_persistent:1;
 	unsigned int discard_granularity;
 	unsigned int discard_alignment;
-	unsigned int feature_persistent:1;
 	/* Number of 4KB segments handled */
 	unsigned int max_indirect_segments;
 	int is_ready;
@@ -1758,17 +1758,13 @@ static int talk_to_blkback(struct xenbus
 	const char *message = NULL;
 	struct xenbus_transaction xbt;
 	int err;
-	unsigned int i, max_page_order = 0;
-	unsigned int ring_page_order = 0;
+	unsigned int i, max_page_order;
+	unsigned int ring_page_order;
 
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "max-ring-page-order", "%u", &max_page_order);
-	if (err != 1)
-		info->nr_ring_pages = 1;
-	else {
-		ring_page_order = min(xen_blkif_max_ring_order, max_page_order);
-		info->nr_ring_pages = 1 << ring_page_order;
-	}
+	max_page_order = xenbus_read_unsigned(info->xbdev->otherend,
+					      "max-ring-page-order", 0);
+	ring_page_order = min(xen_blkif_max_ring_order, max_page_order);
+	info->nr_ring_pages = 1 << ring_page_order;
 
 	for (i = 0; i < info->nr_rings; i++) {
 		struct blkfront_ring_info *rinfo = &info->rinfo[i];
@@ -1877,18 +1873,14 @@ again:
 
 static int negotiate_mq(struct blkfront_info *info)
 {
-	unsigned int backend_max_queues = 0;
-	int err;
+	unsigned int backend_max_queues;
 	unsigned int i;
 
 	BUG_ON(info->nr_rings);
 
 	/* Check if backend supports multiple queues. */
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "multi-queue-max-queues", "%u", &backend_max_queues);
-	if (err < 0)
-		backend_max_queues = 1;
-
+	backend_max_queues = xenbus_read_unsigned(info->xbdev->otherend,
+						  "multi-queue-max-queues", 1);
 	info->nr_rings = min(backend_max_queues, xen_blkif_max_queues);
 	/* We need at least one ring. */
 	if (!info->nr_rings)
@@ -2043,8 +2035,9 @@ static int blkif_recover(struct blkfront
 		/* Requeue pending requests (flush or discard) */
 		list_del_init(&req->queuelist);
 		BUG_ON(req->nr_phys_segments > segs);
-		blk_mq_requeue_request(req);
+		blk_mq_requeue_request(req, false);
 	}
+	blk_mq_start_stopped_hw_queues(info->rq, true);
 	blk_mq_kick_requeue_list(info->rq);
 
 	while ((bio = bio_list_pop(&info->bio_list)) != NULL) {
@@ -2195,7 +2188,6 @@ static void blkfront_setup_discard(struc
 	int err;
 	unsigned int discard_granularity;
 	unsigned int discard_alignment;
-	unsigned int discard_secure;
 
 	info->feature_discard = 1;
 	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
@@ -2206,10 +2198,9 @@ static void blkfront_setup_discard(struc
 		info->discard_granularity = discard_granularity;
 		info->discard_alignment = discard_alignment;
 	}
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "discard-secure", "%u", &discard_secure);
-	if (err > 0)
-		info->feature_secdiscard = !!discard_secure;
+	info->feature_secdiscard =
+		!!xenbus_read_unsigned(info->xbdev->otherend, "discard-secure",
+				       0);
 }
 
 static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
@@ -2232,7 +2223,7 @@ static int blkfront_setup_indirect(struc
 	}
 	else
 		grants = info->max_indirect_segments;
-	psegs = grants / GRANTS_PER_PSEG;
+	psegs = DIV_ROUND_UP(grants, GRANTS_PER_PSEG);
 
 	err = fill_grant_buffer(rinfo,
 				(grants + INDIRECT_GREFS(grants)) * BLK_RING_SIZE(info));
@@ -2301,16 +2292,11 @@ out_of_memory:
  */
 static void blkfront_gather_backend_features(struct blkfront_info *info)
 {
-	int err;
-	int barrier, flush, discard, persistent;
 	unsigned int indirect_segments;
 
 	info->feature_flush = 0;
 	info->feature_fua = 0;
 
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "feature-barrier", "%d", &barrier);
-
 	/*
 	 * If there's no "feature-barrier" defined, then it means
 	 * we're dealing with a very old backend which writes
@@ -2318,7 +2304,7 @@ static void blkfront_gather_backend_feat
 	 *
 	 * If there are barriers, then we use flush.
 	 */
-	if (err > 0 && barrier) {
+	if (xenbus_read_unsigned(info->xbdev->otherend, "feature-barrier", 0)) {
 		info->feature_flush = 1;
 		info->feature_fua = 1;
 	}
@@ -2327,35 +2313,26 @@ static void blkfront_gather_backend_feat
 	 * And if there is "feature-flush-cache" use that above
 	 * barriers.
 	 */
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "feature-flush-cache", "%d", &flush);
-
-	if (err > 0 && flush) {
+	if (xenbus_read_unsigned(info->xbdev->otherend, "feature-flush-cache",
+				 0)) {
 		info->feature_flush = 1;
 		info->feature_fua = 0;
 	}
 
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "feature-discard", "%d", &discard);
-
-	if (err > 0 && discard)
+	if (xenbus_read_unsigned(info->xbdev->otherend, "feature-discard", 0))
 		blkfront_setup_discard(info);
 
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "feature-persistent", "%d", &persistent);
-	if (err <= 0)
-		info->feature_persistent = 0;
-	else
-		info->feature_persistent = persistent;
+	info->feature_persistent =
+		!!xenbus_read_unsigned(info->xbdev->otherend,
+				       "feature-persistent", 0);
 
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "feature-max-indirect-segments", "%u",
-			   &indirect_segments);
-	if (err <= 0)
-		info->max_indirect_segments = 0;
-	else
-		info->max_indirect_segments = min(indirect_segments,
-						  xen_blkif_max_segments);
+	indirect_segments = xenbus_read_unsigned(info->xbdev->otherend,
+					"feature-max-indirect-segments", 0);
+	if (indirect_segments > xen_blkif_max_segments)
+		indirect_segments = xen_blkif_max_segments;
+	if (indirect_segments <= BLKIF_MAX_SEGMENTS_PER_REQUEST)
+		indirect_segments = 0;
+	info->max_indirect_segments = indirect_segments;
 }
 
 /*
@@ -2420,11 +2397,9 @@ static void blkfront_connect(struct blkf
 	 * provide this. Assume physical sector size to be the same as
 	 * sector_size in that case.
 	 */
-	err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-			   "physical-sector-size", "%u", &physical_sector_size);
-	if (err != 1)
-		physical_sector_size = sector_size;
-
+	physical_sector_size = xenbus_read_unsigned(info->xbdev->otherend,
+						    "physical-sector-size",
+						    sector_size);
 	blkfront_gather_backend_features(info);
 	for (i = 0; i < info->nr_rings; i++) {
 		err = blkfront_setup_indirect(&info->rinfo[i]);
@@ -2680,6 +2655,9 @@ static int __init xlblk_init(void)
 	if (!xen_domain())
 		return -ENODEV;
 
+	if (xen_blkif_max_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST)
+		xen_blkif_max_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+
 	if (xen_blkif_max_ring_order > XENBUS_MAX_RING_GRANT_ORDER) {
 		pr_info("Invalid max_ring_order (%d), will use default max: %d.\n",
 			xen_blkif_max_ring_order, XENBUS_MAX_RING_GRANT_ORDER);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/zram/zcomp.c linux-libre-4.10-rc8-gnu/drivers/block/zram/zcomp.c
--- linux-libre-4.9-gnu/drivers/block/zram/zcomp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/zram/zcomp.c	2017-02-12 16:03:20.000000000 -0500
@@ -160,82 +160,56 @@ int zcomp_decompress(struct zcomp_strm *
 			dst, &dst_len);
 }
 
-static int __zcomp_cpu_notifier(struct zcomp *comp,
-		unsigned long action, unsigned long cpu)
+int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node)
 {
+	struct zcomp *comp = hlist_entry(node, struct zcomp, node);
 	struct zcomp_strm *zstrm;
 
-	switch (action) {
-	case CPU_UP_PREPARE:
-		if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
-			break;
-		zstrm = zcomp_strm_alloc(comp);
-		if (IS_ERR_OR_NULL(zstrm)) {
-			pr_err("Can't allocate a compression stream\n");
-			return NOTIFY_BAD;
-		}
-		*per_cpu_ptr(comp->stream, cpu) = zstrm;
-		break;
-	case CPU_DEAD:
-	case CPU_UP_CANCELED:
-		zstrm = *per_cpu_ptr(comp->stream, cpu);
-		if (!IS_ERR_OR_NULL(zstrm))
-			zcomp_strm_free(zstrm);
-		*per_cpu_ptr(comp->stream, cpu) = NULL;
-		break;
-	default:
-		break;
+	if (WARN_ON(*per_cpu_ptr(comp->stream, cpu)))
+		return 0;
+
+	zstrm = zcomp_strm_alloc(comp);
+	if (IS_ERR_OR_NULL(zstrm)) {
+		pr_err("Can't allocate a compression stream\n");
+		return -ENOMEM;
 	}
-	return NOTIFY_OK;
+	*per_cpu_ptr(comp->stream, cpu) = zstrm;
+	return 0;
 }
 
-static int zcomp_cpu_notifier(struct notifier_block *nb,
-		unsigned long action, void *pcpu)
+int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node)
 {
-	unsigned long cpu = (unsigned long)pcpu;
-	struct zcomp *comp = container_of(nb, typeof(*comp), notifier);
+	struct zcomp *comp = hlist_entry(node, struct zcomp, node);
+	struct zcomp_strm *zstrm;
 
-	return __zcomp_cpu_notifier(comp, action, cpu);
+	zstrm = *per_cpu_ptr(comp->stream, cpu);
+	if (!IS_ERR_OR_NULL(zstrm))
+		zcomp_strm_free(zstrm);
+	*per_cpu_ptr(comp->stream, cpu) = NULL;
+	return 0;
 }
 
 static int zcomp_init(struct zcomp *comp)
 {
-	unsigned long cpu;
 	int ret;
 
-	comp->notifier.notifier_call = zcomp_cpu_notifier;
-
 	comp->stream = alloc_percpu(struct zcomp_strm *);
 	if (!comp->stream)
 		return -ENOMEM;
 
-	cpu_notifier_register_begin();
-	for_each_online_cpu(cpu) {
-		ret = __zcomp_cpu_notifier(comp, CPU_UP_PREPARE, cpu);
-		if (ret == NOTIFY_BAD)
-			goto cleanup;
-	}
-	__register_cpu_notifier(&comp->notifier);
-	cpu_notifier_register_done();
+	ret = cpuhp_state_add_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
+	if (ret < 0)
+		goto cleanup;
 	return 0;
 
 cleanup:
-	for_each_online_cpu(cpu)
-		__zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
-	cpu_notifier_register_done();
-	return -ENOMEM;
+	free_percpu(comp->stream);
+	return ret;
 }
 
 void zcomp_destroy(struct zcomp *comp)
 {
-	unsigned long cpu;
-
-	cpu_notifier_register_begin();
-	for_each_online_cpu(cpu)
-		__zcomp_cpu_notifier(comp, CPU_UP_CANCELED, cpu);
-	__unregister_cpu_notifier(&comp->notifier);
-	cpu_notifier_register_done();
-
+	cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node);
 	free_percpu(comp->stream);
 	kfree(comp);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/zram/zcomp.h linux-libre-4.10-rc8-gnu/drivers/block/zram/zcomp.h
--- linux-libre-4.9-gnu/drivers/block/zram/zcomp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/zram/zcomp.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,11 +19,12 @@ struct zcomp_strm {
 /* dynamic per-device compression frontend */
 struct zcomp {
 	struct zcomp_strm * __percpu *stream;
-	struct notifier_block notifier;
-
 	const char *name;
+	struct hlist_node node;
 };
 
+int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node);
+int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node);
 ssize_t zcomp_available_show(const char *comp, char *buf);
 bool zcomp_available_algorithm(const char *comp);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/block/zram/zram_drv.c linux-libre-4.10-rc8-gnu/drivers/block/zram/zram_drv.c
--- linux-libre-4.9-gnu/drivers/block/zram/zram_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/block/zram/zram_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,11 +25,13 @@
 #include <linux/genhd.h>
 #include <linux/highmem.h>
 #include <linux/slab.h>
+#include <linux/backing-dev.h>
 #include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/sysfs.h>
+#include <linux/cpuhotplug.h>
 
 #include "zram_drv.h"
 
@@ -111,6 +113,14 @@ static inline bool is_partial_io(struct
 	return bvec->bv_len != PAGE_SIZE;
 }
 
+static void zram_revalidate_disk(struct zram *zram)
+{
+	revalidate_disk(zram->disk);
+	/* revalidate_disk reset the BDI_CAP_STABLE_WRITES so set again */
+	zram->disk->queue->backing_dev_info.capabilities |=
+		BDI_CAP_STABLE_WRITES;
+}
+
 /*
  * Check if request is within bounds and aligned on zram logical blocks.
  */
@@ -1094,15 +1104,9 @@ static ssize_t disksize_store(struct dev
 	zram->comp = comp;
 	zram->disksize = disksize;
 	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
+	zram_revalidate_disk(zram);
 	up_write(&zram->init_lock);
 
-	/*
-	 * Revalidate disk out of the init_lock to avoid lockdep splat.
-	 * It's okay because disk's capacity is protected by init_lock
-	 * so that revalidate_disk always sees up-to-date capacity.
-	 */
-	revalidate_disk(zram->disk);
-
 	return len;
 
 out_destroy_comp:
@@ -1148,7 +1152,7 @@ static ssize_t reset_store(struct device
 	/* Make sure all the pending I/O are finished */
 	fsync_bdev(bdev);
 	zram_reset_device(zram);
-	revalidate_disk(zram->disk);
+	zram_revalidate_disk(zram);
 	bdput(bdev);
 
 	mutex_lock(&bdev->bd_mutex);
@@ -1443,15 +1447,22 @@ static void destroy_devices(void)
 	idr_for_each(&zram_index_idr, &zram_remove_cb, NULL);
 	idr_destroy(&zram_index_idr);
 	unregister_blkdev(zram_major, "zram");
+	cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
 }
 
 static int __init zram_init(void)
 {
 	int ret;
 
+	ret = cpuhp_setup_state_multi(CPUHP_ZCOMP_PREPARE, "block/zram:prepare",
+				      zcomp_cpu_up_prepare, zcomp_cpu_dead);
+	if (ret < 0)
+		return ret;
+
 	ret = class_register(&zram_control_class);
 	if (ret) {
 		pr_err("Unable to register zram-control class\n");
+		cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
 		return ret;
 	}
 
@@ -1459,6 +1470,7 @@ static int __init zram_init(void)
 	if (zram_major <= 0) {
 		pr_err("Unable to get major number\n");
 		class_unregister(&zram_control_class);
+		cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
 		return -EBUSY;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bluetooth/btmrvl_drv.h linux-libre-4.10-rc8-gnu/drivers/bluetooth/btmrvl_drv.h
--- linux-libre-4.9-gnu/drivers/bluetooth/btmrvl_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bluetooth/btmrvl_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,6 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-#include <linux/slab.h>
 #include <linux/of_irq.h>
 
 #define BTM_HEADER_LEN			4
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bluetooth/hci_bcsp.c linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_bcsp.c
--- linux-libre-4.9-gnu/drivers/bluetooth/hci_bcsp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_bcsp.c	2017-02-12 16:03:20.000000000 -0500
@@ -733,9 +733,7 @@ static int bcsp_open(struct hci_uart *hu
 	skb_queue_head_init(&bcsp->rel);
 	skb_queue_head_init(&bcsp->unrel);
 
-	init_timer(&bcsp->tbcsp);
-	bcsp->tbcsp.function = bcsp_timed_event;
-	bcsp->tbcsp.data     = (u_long)hu;
+	setup_timer(&bcsp->tbcsp, bcsp_timed_event, (u_long)hu);
 
 	bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bluetooth/hci_h5.c linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_h5.c
--- linux-libre-4.9-gnu/drivers/bluetooth/hci_h5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_h5.c	2017-02-12 16:03:20.000000000 -0500
@@ -204,9 +204,7 @@ static int h5_open(struct hci_uart *hu)
 
 	h5_reset_rx(h5);
 
-	init_timer(&h5->timer);
-	h5->timer.function = h5_timed_event;
-	h5->timer.data = (unsigned long)hu;
+	setup_timer(&h5->timer, h5_timed_event, (unsigned long)hu);
 
 	h5->tx_win = H5_TX_WIN_MAX;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bluetooth/hci_qca.c linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_qca.c
--- linux-libre-4.9-gnu/drivers/bluetooth/hci_qca.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_qca.c	2017-02-12 16:03:20.000000000 -0500
@@ -438,14 +438,11 @@ static int qca_open(struct hci_uart *hu)
 
 	hu->priv = qca;
 
-	init_timer(&qca->wake_retrans_timer);
-	qca->wake_retrans_timer.function = hci_ibs_wake_retrans_timeout;
-	qca->wake_retrans_timer.data = (u_long)hu;
+	setup_timer(&qca->wake_retrans_timer, hci_ibs_wake_retrans_timeout,
+		    (u_long)hu);
 	qca->wake_retrans = IBS_WAKE_RETRANS_TIMEOUT_MS;
 
-	init_timer(&qca->tx_idle_timer);
-	qca->tx_idle_timer.function = hci_ibs_tx_idle_timeout;
-	qca->tx_idle_timer.data = (u_long)hu;
+	setup_timer(&qca->tx_idle_timer, hci_ibs_tx_idle_timeout, (u_long)hu);
 	qca->tx_idle_delay = IBS_TX_IDLE_TIMEOUT_MS;
 
 	BT_DBG("HCI_UART_QCA open, tx_idle_delay=%u, wake_retrans=%u",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bluetooth/hci_vhci.c linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_vhci.c
--- linux-libre-4.9-gnu/drivers/bluetooth/hci_vhci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bluetooth/hci_vhci.c	2017-02-12 16:03:20.000000000 -0500
@@ -181,7 +181,7 @@ static inline ssize_t vhci_get_user(stru
 	if (!skb)
 		return -ENOMEM;
 
-	if (copy_from_iter(skb_put(skb, len), len, from) != len) {
+	if (!copy_from_iter_full(skb_put(skb, len), len, from)) {
 		kfree_skb(skb);
 		return -EFAULT;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bluetooth/Makefile linux-libre-4.10-rc8-gnu/drivers/bluetooth/Makefile
--- linux-libre-4.9-gnu/drivers/bluetooth/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bluetooth/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -40,5 +40,3 @@ hci_uart-$(CONFIG_BT_HCIUART_QCA)	+= hci
 hci_uart-$(CONFIG_BT_HCIUART_AG6XX)	+= hci_ag6xx.o
 hci_uart-$(CONFIG_BT_HCIUART_MRVL)	+= hci_mrvl.o
 hci_uart-objs				:= $(hci_uart-y)
-
-ccflags-y += -D__CHECK_ENDIAN__
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bus/arm-cci.c linux-libre-4.10-rc8-gnu/drivers/bus/arm-cci.c
--- linux-libre-4.9-gnu/drivers/bus/arm-cci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bus/arm-cci.c	2017-02-12 16:03:20.000000000 -0500
@@ -1796,7 +1796,7 @@ static int __init cci_platform_init(void
 	int ret;
 
 	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CCI_ONLINE,
-				      "AP_PERF_ARM_CCI_ONLINE", NULL,
+				      "perf/arm/cci:online", NULL,
 				      cci_pmu_offline_cpu);
 	if (ret)
 		return ret;
@@ -2190,6 +2190,9 @@ static int cci_probe_ports(struct device
 		if (!of_match_node(arm_cci_ctrl_if_matches, cp))
 			continue;
 
+		if (!of_device_is_available(cp))
+			continue;
+
 		i = nb_ace + nb_ace_lite;
 
 		if (i >= nb_cci_ports)
@@ -2232,6 +2235,13 @@ static int cci_probe_ports(struct device
 		ports[i].dn = cp;
 	}
 
+	/*
+	 * If there is no CCI port that is under kernel control
+	 * return early and report probe status.
+	 */
+	if (!nb_ace && !nb_ace_lite)
+		return -ENODEV;
+
 	 /* initialize a stashed array of ACE ports to speed-up look-up */
 	cci_ace_init_ports();
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bus/arm-ccn.c linux-libre-4.10-rc8-gnu/drivers/bus/arm-ccn.c
--- linux-libre-4.9-gnu/drivers/bus/arm-ccn.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bus/arm-ccn.c	2017-02-12 16:03:20.000000000 -0500
@@ -1562,7 +1562,7 @@ static int __init arm_ccn_init(void)
 	int i, ret;
 
 	ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CCN_ONLINE,
-				      "AP_PERF_ARM_CCN_ONLINE", NULL,
+				      "perf/arm/ccn:online", NULL,
 				      arm_ccn_pmu_offline_cpu);
 	if (ret)
 		return ret;
@@ -1570,7 +1570,10 @@ static int __init arm_ccn_init(void)
 	for (i = 0; i < ARRAY_SIZE(arm_ccn_pmu_events); i++)
 		arm_ccn_pmu_events_attrs[i] = &arm_ccn_pmu_events[i].attr.attr;
 
-	return platform_driver_register(&arm_ccn_driver);
+	ret = platform_driver_register(&arm_ccn_driver);
+	if (ret)
+		cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_CCN_ONLINE);
+	return ret;
 }
 
 static void __exit arm_ccn_exit(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bus/da8xx-mstpri.c linux-libre-4.10-rc8-gnu/drivers/bus/da8xx-mstpri.c
--- linux-libre-4.9-gnu/drivers/bus/da8xx-mstpri.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bus/da8xx-mstpri.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,267 @@
+/*
+ * TI da8xx master peripheral priority driver
+ *
+ * Copyright (C) 2016 BayLibre SAS
+ *
+ * Author:
+ *   Bartosz Golaszewski <bgolaszewski@baylibre.com.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/of.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/regmap.h>
+
+/*
+ * REVISIT: Linux doesn't have a good framework for the kind of performance
+ * knobs this driver controls. We can't use device tree properties as it deals
+ * with hardware configuration rather than description. We also don't want to
+ * commit to maintaining some random sysfs attributes.
+ *
+ * For now we just hardcode the register values for the boards that need
+ * some changes (as is the case for the LCD controller on da850-lcdk - the
+ * first board we support here). When linux gets an appropriate framework,
+ * we'll easily convert the driver to it.
+ */
+
+#define DA8XX_MSTPRI0_OFFSET		0
+#define DA8XX_MSTPRI1_OFFSET		4
+#define DA8XX_MSTPRI2_OFFSET		8
+
+enum {
+	DA8XX_MSTPRI_ARM_I = 0,
+	DA8XX_MSTPRI_ARM_D,
+	DA8XX_MSTPRI_UPP,
+	DA8XX_MSTPRI_SATA,
+	DA8XX_MSTPRI_PRU0,
+	DA8XX_MSTPRI_PRU1,
+	DA8XX_MSTPRI_EDMA30TC0,
+	DA8XX_MSTPRI_EDMA30TC1,
+	DA8XX_MSTPRI_EDMA31TC0,
+	DA8XX_MSTPRI_VPIF_DMA_0,
+	DA8XX_MSTPRI_VPIF_DMA_1,
+	DA8XX_MSTPRI_EMAC,
+	DA8XX_MSTPRI_USB0CFG,
+	DA8XX_MSTPRI_USB0CDMA,
+	DA8XX_MSTPRI_UHPI,
+	DA8XX_MSTPRI_USB1,
+	DA8XX_MSTPRI_LCDC,
+};
+
+struct da8xx_mstpri_descr {
+	int reg;
+	int shift;
+	int mask;
+};
+
+static const struct da8xx_mstpri_descr da8xx_mstpri_priority_list[] = {
+	[DA8XX_MSTPRI_ARM_I] = {
+		.reg = DA8XX_MSTPRI0_OFFSET,
+		.shift = 0,
+		.mask = 0x0000000f,
+	},
+	[DA8XX_MSTPRI_ARM_D] = {
+		.reg = DA8XX_MSTPRI0_OFFSET,
+		.shift = 4,
+		.mask = 0x000000f0,
+	},
+	[DA8XX_MSTPRI_UPP] = {
+		.reg = DA8XX_MSTPRI0_OFFSET,
+		.shift = 16,
+		.mask = 0x000f0000,
+	},
+	[DA8XX_MSTPRI_SATA] = {
+		.reg = DA8XX_MSTPRI0_OFFSET,
+		.shift = 20,
+		.mask = 0x00f00000,
+	},
+	[DA8XX_MSTPRI_PRU0] = {
+		.reg = DA8XX_MSTPRI1_OFFSET,
+		.shift = 0,
+		.mask = 0x0000000f,
+	},
+	[DA8XX_MSTPRI_PRU1] = {
+		.reg = DA8XX_MSTPRI1_OFFSET,
+		.shift = 4,
+		.mask = 0x000000f0,
+	},
+	[DA8XX_MSTPRI_EDMA30TC0] = {
+		.reg = DA8XX_MSTPRI1_OFFSET,
+		.shift = 8,
+		.mask = 0x00000f00,
+	},
+	[DA8XX_MSTPRI_EDMA30TC1] = {
+		.reg = DA8XX_MSTPRI1_OFFSET,
+		.shift = 12,
+		.mask = 0x0000f000,
+	},
+	[DA8XX_MSTPRI_EDMA31TC0] = {
+		.reg = DA8XX_MSTPRI1_OFFSET,
+		.shift = 16,
+		.mask = 0x000f0000,
+	},
+	[DA8XX_MSTPRI_VPIF_DMA_0] = {
+		.reg = DA8XX_MSTPRI1_OFFSET,
+		.shift = 24,
+		.mask = 0x0f000000,
+	},
+	[DA8XX_MSTPRI_VPIF_DMA_1] = {
+		.reg = DA8XX_MSTPRI1_OFFSET,
+		.shift = 28,
+		.mask = 0xf0000000,
+	},
+	[DA8XX_MSTPRI_EMAC] = {
+		.reg = DA8XX_MSTPRI2_OFFSET,
+		.shift = 0,
+		.mask = 0x0000000f,
+	},
+	[DA8XX_MSTPRI_USB0CFG] = {
+		.reg = DA8XX_MSTPRI2_OFFSET,
+		.shift = 8,
+		.mask = 0x00000f00,
+	},
+	[DA8XX_MSTPRI_USB0CDMA] = {
+		.reg = DA8XX_MSTPRI2_OFFSET,
+		.shift = 12,
+		.mask = 0x0000f000,
+	},
+	[DA8XX_MSTPRI_UHPI] = {
+		.reg = DA8XX_MSTPRI2_OFFSET,
+		.shift = 20,
+		.mask = 0x00f00000,
+	},
+	[DA8XX_MSTPRI_USB1] = {
+		.reg = DA8XX_MSTPRI2_OFFSET,
+		.shift = 24,
+		.mask = 0x0f000000,
+	},
+	[DA8XX_MSTPRI_LCDC] = {
+		.reg = DA8XX_MSTPRI2_OFFSET,
+		.shift = 28,
+		.mask = 0xf0000000,
+	},
+};
+
+struct da8xx_mstpri_priority {
+	int which;
+	u32 val;
+};
+
+struct da8xx_mstpri_board_priorities {
+	const char *board;
+	const struct da8xx_mstpri_priority *priorities;
+	size_t numprio;
+};
+
+/*
+ * Default memory settings of da850 do not meet the throughput/latency
+ * requirements of tilcdc. This results in the image displayed being
+ * incorrect and the following warning being displayed by the LCDC
+ * drm driver:
+ *
+ *   tilcdc da8xx_lcdc.0: tilcdc_crtc_irq(0x00000020): FIFO underfow
+ */
+static const struct da8xx_mstpri_priority da850_lcdk_priorities[] = {
+	{
+		.which = DA8XX_MSTPRI_LCDC,
+		.val = 0,
+	},
+	{
+		.which = DA8XX_MSTPRI_EDMA30TC1,
+		.val = 0,
+	},
+	{
+		.which = DA8XX_MSTPRI_EDMA30TC0,
+		.val = 1,
+	},
+};
+
+static const struct da8xx_mstpri_board_priorities da8xx_mstpri_board_confs[] = {
+	{
+		.board = "ti,da850-lcdk",
+		.priorities = da850_lcdk_priorities,
+		.numprio = ARRAY_SIZE(da850_lcdk_priorities),
+	},
+};
+
+static const struct da8xx_mstpri_board_priorities *
+da8xx_mstpri_get_board_prio(void)
+{
+	const struct da8xx_mstpri_board_priorities *board_prio;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(da8xx_mstpri_board_confs); i++) {
+		board_prio = &da8xx_mstpri_board_confs[i];
+
+		if (of_machine_is_compatible(board_prio->board))
+			return board_prio;
+	}
+
+	return NULL;
+}
+
+static int da8xx_mstpri_probe(struct platform_device *pdev)
+{
+	const struct da8xx_mstpri_board_priorities *prio_list;
+	const struct da8xx_mstpri_descr *prio_descr;
+	const struct da8xx_mstpri_priority *prio;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	void __iomem *mstpri;
+	u32 reg;
+	int i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mstpri = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mstpri)) {
+		dev_err(dev, "unable to map MSTPRI registers\n");
+		return PTR_ERR(mstpri);
+	}
+
+	prio_list = da8xx_mstpri_get_board_prio();
+	if (!prio_list) {
+		dev_err(dev, "no master priorities defined for this board\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < prio_list->numprio; i++) {
+		prio = &prio_list->priorities[i];
+		prio_descr = &da8xx_mstpri_priority_list[prio->which];
+
+		if (prio_descr->reg + sizeof(u32) > resource_size(res)) {
+			dev_warn(dev, "register offset out of range\n");
+			continue;
+		}
+
+		reg = readl(mstpri + prio_descr->reg);
+		reg &= ~prio_descr->mask;
+		reg |= prio->val << prio_descr->shift;
+
+		writel(reg, mstpri + prio_descr->reg);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id da8xx_mstpri_of_match[] = {
+	{ .compatible = "ti,da850-mstpri", },
+	{ },
+};
+
+static struct platform_driver da8xx_mstpri_driver = {
+	.probe = da8xx_mstpri_probe,
+	.driver = {
+		.name = "da8xx-mstpri",
+		.of_match_table = da8xx_mstpri_of_match,
+	},
+};
+module_platform_driver(da8xx_mstpri_driver);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_DESCRIPTION("TI da8xx master peripheral priority driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bus/Kconfig linux-libre-4.10-rc8-gnu/drivers/bus/Kconfig
--- linux-libre-4.9-gnu/drivers/bus/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bus/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -150,6 +150,13 @@ config TEGRA_ACONNECT
 	  Driver for the Tegra ACONNECT bus which is used to interface with
 	  the devices inside the Audio Processing Engine (APE) for Tegra210.
 
+config TEGRA_GMI
+	tristate "Tegra Generic Memory Interface bus driver"
+	depends on ARCH_TEGRA
+	help
+	  Driver for the Tegra Generic Memory Interface bus which can be used
+	  to attach devices such as NOR, UART, FPGA and more.
+
 config UNIPHIER_SYSTEM_BUS
 	tristate "UniPhier System Bus driver"
 	depends on ARCH_UNIPHIER && OF
@@ -167,4 +174,13 @@ config VEXPRESS_CONFIG
 	help
 	  Platform configuration infrastructure for the ARM Ltd.
 	  Versatile Express.
+
+config DA8XX_MSTPRI
+	bool "TI da8xx master peripheral priority driver"
+	depends on ARCH_DAVINCI_DA8XX
+	help
+	  Driver for Texas Instruments da8xx master peripheral priority
+	  configuration. Allows to adjust the priorities of all master
+	  peripherals.
+
 endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bus/Makefile linux-libre-4.10-rc8-gnu/drivers/bus/Makefile
--- linux-libre-4.9-gnu/drivers/bus/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bus/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -19,5 +19,8 @@ obj-$(CONFIG_QCOM_EBI2)		+= qcom-ebi2.o
 obj-$(CONFIG_SUNXI_RSB)		+= sunxi-rsb.o
 obj-$(CONFIG_SIMPLE_PM_BUS)	+= simple-pm-bus.o
 obj-$(CONFIG_TEGRA_ACONNECT)	+= tegra-aconnect.o
+obj-$(CONFIG_TEGRA_GMI)		+= tegra-gmi.o
 obj-$(CONFIG_UNIPHIER_SYSTEM_BUS)	+= uniphier-system-bus.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o
+
+obj-$(CONFIG_DA8XX_MSTPRI)	+= da8xx-mstpri.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bus/tegra-gmi.c linux-libre-4.10-rc8-gnu/drivers/bus/tegra-gmi.c
--- linux-libre-4.9-gnu/drivers/bus/tegra-gmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bus/tegra-gmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,284 @@
+/*
+ * Driver for NVIDIA Generic Memory Interface
+ *
+ * Copyright (C) 2016 Host Mobility AB. All rights reserved.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/reset.h>
+
+#define TEGRA_GMI_CONFIG		0x00
+#define TEGRA_GMI_CONFIG_GO		BIT(31)
+#define TEGRA_GMI_BUS_WIDTH_32BIT	BIT(30)
+#define TEGRA_GMI_MUX_MODE		BIT(28)
+#define TEGRA_GMI_RDY_BEFORE_DATA	BIT(24)
+#define TEGRA_GMI_RDY_ACTIVE_HIGH	BIT(23)
+#define TEGRA_GMI_ADV_ACTIVE_HIGH	BIT(22)
+#define TEGRA_GMI_OE_ACTIVE_HIGH	BIT(21)
+#define TEGRA_GMI_CS_ACTIVE_HIGH	BIT(20)
+#define TEGRA_GMI_CS_SELECT(x)		((x & 0x7) << 4)
+
+#define TEGRA_GMI_TIMING0		0x10
+#define TEGRA_GMI_MUXED_WIDTH(x)	((x & 0xf) << 12)
+#define TEGRA_GMI_HOLD_WIDTH(x)		((x & 0xf) << 8)
+#define TEGRA_GMI_ADV_WIDTH(x)		((x & 0xf) << 4)
+#define TEGRA_GMI_CE_WIDTH(x)		(x & 0xf)
+
+#define TEGRA_GMI_TIMING1		0x14
+#define TEGRA_GMI_WE_WIDTH(x)		((x & 0xff) << 16)
+#define TEGRA_GMI_OE_WIDTH(x)		((x & 0xff) << 8)
+#define TEGRA_GMI_WAIT_WIDTH(x)		(x & 0xff)
+
+#define TEGRA_GMI_MAX_CHIP_SELECT	8
+
+struct tegra_gmi {
+	struct device *dev;
+	void __iomem *base;
+	struct clk *clk;
+	struct reset_control *rst;
+
+	u32 snor_config;
+	u32 snor_timing0;
+	u32 snor_timing1;
+};
+
+static int tegra_gmi_enable(struct tegra_gmi *gmi)
+{
+	int err;
+
+	err = clk_prepare_enable(gmi->clk);
+	if (err < 0) {
+		dev_err(gmi->dev, "failed to enable clock: %d\n", err);
+		return err;
+	}
+
+	reset_control_assert(gmi->rst);
+	usleep_range(2000, 4000);
+	reset_control_deassert(gmi->rst);
+
+	writel(gmi->snor_timing0, gmi->base + TEGRA_GMI_TIMING0);
+	writel(gmi->snor_timing1, gmi->base + TEGRA_GMI_TIMING1);
+
+	gmi->snor_config |= TEGRA_GMI_CONFIG_GO;
+	writel(gmi->snor_config, gmi->base + TEGRA_GMI_CONFIG);
+
+	return 0;
+}
+
+static void tegra_gmi_disable(struct tegra_gmi *gmi)
+{
+	u32 config;
+
+	/* stop GMI operation */
+	config = readl(gmi->base + TEGRA_GMI_CONFIG);
+	config &= ~TEGRA_GMI_CONFIG_GO;
+	writel(config, gmi->base + TEGRA_GMI_CONFIG);
+
+	reset_control_assert(gmi->rst);
+	clk_disable_unprepare(gmi->clk);
+}
+
+static int tegra_gmi_parse_dt(struct tegra_gmi *gmi)
+{
+	struct device_node *child;
+	u32 property, ranges[4];
+	int err;
+
+	child = of_get_next_available_child(gmi->dev->of_node, NULL);
+	if (!child) {
+		dev_err(gmi->dev, "no child nodes found\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * We currently only support one child device due to lack of
+	 * chip-select address decoding. Which means that we only have one
+	 * chip-select line from the GMI controller.
+	 */
+	if (of_get_child_count(gmi->dev->of_node) > 1)
+		dev_warn(gmi->dev, "only one child device is supported.");
+
+	if (of_property_read_bool(child, "nvidia,snor-data-width-32bit"))
+		gmi->snor_config |= TEGRA_GMI_BUS_WIDTH_32BIT;
+
+	if (of_property_read_bool(child, "nvidia,snor-mux-mode"))
+		gmi->snor_config |= TEGRA_GMI_MUX_MODE;
+
+	if (of_property_read_bool(child, "nvidia,snor-rdy-active-before-data"))
+		gmi->snor_config |= TEGRA_GMI_RDY_BEFORE_DATA;
+
+	if (of_property_read_bool(child, "nvidia,snor-rdy-active-high"))
+		gmi->snor_config |= TEGRA_GMI_RDY_ACTIVE_HIGH;
+
+	if (of_property_read_bool(child, "nvidia,snor-adv-active-high"))
+		gmi->snor_config |= TEGRA_GMI_ADV_ACTIVE_HIGH;
+
+	if (of_property_read_bool(child, "nvidia,snor-oe-active-high"))
+		gmi->snor_config |= TEGRA_GMI_OE_ACTIVE_HIGH;
+
+	if (of_property_read_bool(child, "nvidia,snor-cs-active-high"))
+		gmi->snor_config |= TEGRA_GMI_CS_ACTIVE_HIGH;
+
+	/* Decode the CS# */
+	err = of_property_read_u32_array(child, "ranges", ranges, 4);
+	if (err < 0) {
+		/* Invalid binding */
+		if (err == -EOVERFLOW) {
+			dev_err(gmi->dev,
+				"failed to decode CS: invalid ranges length\n");
+			goto error_cs;
+		}
+
+		/*
+		 * If we reach here it means that the child node has an empty
+		 * ranges or it does not exist at all. Attempt to decode the
+		 * CS# from the reg property instead.
+		 */
+		err = of_property_read_u32(child, "reg", &property);
+		if (err < 0) {
+			dev_err(gmi->dev,
+				"failed to decode CS: no reg property found\n");
+			goto error_cs;
+		}
+	} else {
+		property = ranges[1];
+	}
+
+	/* Valid chip selects are CS0-CS7 */
+	if (property >= TEGRA_GMI_MAX_CHIP_SELECT) {
+		dev_err(gmi->dev, "invalid chip select: %d", property);
+		err = -EINVAL;
+		goto error_cs;
+	}
+
+	gmi->snor_config |= TEGRA_GMI_CS_SELECT(property);
+
+	/* The default values that are provided below are reset values */
+	if (!of_property_read_u32(child, "nvidia,snor-muxed-width", &property))
+		gmi->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(property);
+	else
+		gmi->snor_timing0 |= TEGRA_GMI_MUXED_WIDTH(1);
+
+	if (!of_property_read_u32(child, "nvidia,snor-hold-width", &property))
+		gmi->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(property);
+	else
+		gmi->snor_timing0 |= TEGRA_GMI_HOLD_WIDTH(1);
+
+	if (!of_property_read_u32(child, "nvidia,snor-adv-width", &property))
+		gmi->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(property);
+	else
+		gmi->snor_timing0 |= TEGRA_GMI_ADV_WIDTH(1);
+
+	if (!of_property_read_u32(child, "nvidia,snor-ce-width", &property))
+		gmi->snor_timing0 |= TEGRA_GMI_CE_WIDTH(property);
+	else
+		gmi->snor_timing0 |= TEGRA_GMI_CE_WIDTH(4);
+
+	if (!of_property_read_u32(child, "nvidia,snor-we-width", &property))
+		gmi->snor_timing1 |= TEGRA_GMI_WE_WIDTH(property);
+	else
+		gmi->snor_timing1 |= TEGRA_GMI_WE_WIDTH(1);
+
+	if (!of_property_read_u32(child, "nvidia,snor-oe-width", &property))
+		gmi->snor_timing1 |= TEGRA_GMI_OE_WIDTH(property);
+	else
+		gmi->snor_timing1 |= TEGRA_GMI_OE_WIDTH(1);
+
+	if (!of_property_read_u32(child, "nvidia,snor-wait-width", &property))
+		gmi->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(property);
+	else
+		gmi->snor_timing1 |= TEGRA_GMI_WAIT_WIDTH(3);
+
+error_cs:
+	of_node_put(child);
+	return err;
+}
+
+static int tegra_gmi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra_gmi *gmi;
+	struct resource *res;
+	int err;
+
+	gmi = devm_kzalloc(dev, sizeof(*gmi), GFP_KERNEL);
+	if (!gmi)
+		return -ENOMEM;
+
+	gmi->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	gmi->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(gmi->base))
+		return PTR_ERR(gmi->base);
+
+	gmi->clk = devm_clk_get(dev, "gmi");
+	if (IS_ERR(gmi->clk)) {
+		dev_err(dev, "can not get clock\n");
+		return PTR_ERR(gmi->clk);
+	}
+
+	gmi->rst = devm_reset_control_get(dev, "gmi");
+	if (IS_ERR(gmi->rst)) {
+		dev_err(dev, "can not get reset\n");
+		return PTR_ERR(gmi->rst);
+	}
+
+	err = tegra_gmi_parse_dt(gmi);
+	if (err)
+		return err;
+
+	err = tegra_gmi_enable(gmi);
+	if (err < 0)
+		return err;
+
+	err = of_platform_default_populate(dev->of_node, NULL, dev);
+	if (err < 0) {
+		dev_err(dev, "fail to create devices.\n");
+		tegra_gmi_disable(gmi);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, gmi);
+
+	return 0;
+}
+
+static int tegra_gmi_remove(struct platform_device *pdev)
+{
+	struct tegra_gmi *gmi = platform_get_drvdata(pdev);
+
+	of_platform_depopulate(gmi->dev);
+	tegra_gmi_disable(gmi);
+
+	return 0;
+}
+
+static const struct of_device_id tegra_gmi_id_table[] = {
+	{ .compatible = "nvidia,tegra20-gmi", },
+	{ .compatible = "nvidia,tegra30-gmi", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tegra_gmi_id_table);
+
+static struct platform_driver tegra_gmi_driver = {
+	.probe = tegra_gmi_probe,
+	.remove = tegra_gmi_remove,
+	.driver = {
+		.name		= "tegra-gmi",
+		.of_match_table	= tegra_gmi_id_table,
+	},
+};
+module_platform_driver(tegra_gmi_driver);
+
+MODULE_AUTHOR("Mirza Krak <mirza.krak@gmail.com");
+MODULE_DESCRIPTION("NVIDIA Tegra GMI Bus Driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/bus/vexpress-config.c linux-libre-4.10-rc8-gnu/drivers/bus/vexpress-config.c
--- linux-libre-4.9-gnu/drivers/bus/vexpress-config.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/bus/vexpress-config.c	2017-02-12 16:03:20.000000000 -0500
@@ -171,6 +171,7 @@ static int vexpress_config_populate(stru
 {
 	struct device_node *bridge;
 	struct device *parent;
+	int ret;
 
 	bridge = of_parse_phandle(node, "arm,vexpress,config-bridge", 0);
 	if (!bridge)
@@ -182,7 +183,11 @@ static int vexpress_config_populate(stru
 	if (WARN_ON(!parent))
 		return -ENODEV;
 
-	return of_platform_populate(node, NULL, NULL, parent);
+	ret = of_platform_populate(node, NULL, NULL, parent);
+
+	put_device(parent);
+
+	return ret;
 }
 
 static int __init vexpress_config_init(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cdrom/cdrom.c linux-libre-4.10-rc8-gnu/drivers/cdrom/cdrom.c
--- linux-libre-4.9-gnu/drivers/cdrom/cdrom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cdrom/cdrom.c	2017-02-12 16:03:20.000000000 -0500
@@ -282,7 +282,7 @@
 #include <linux/blkdev.h>
 #include <linux/times.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* used to tell the module to turn on full debugging messages */
 static bool debug;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/agp/alpha-agp.c linux-libre-4.10-rc8-gnu/drivers/char/agp/alpha-agp.c
--- linux-libre-4.9-gnu/drivers/char/agp/alpha-agp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/agp/alpha-agp.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,8 +19,7 @@ static int alpha_core_agp_vm_fault(struc
 	unsigned long pa;
 	struct page *page;
 
-	dma_addr = (unsigned long)vmf->virtual_address - vma->vm_start
-						+ agp->aperture.bus_base;
+	dma_addr = vmf->address - vma->vm_start + agp->aperture.bus_base;
 	pa = agp->ops->translate(agp, dma_addr);
 
 	if (pa == (unsigned long)-EINVAL)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/agp/compat_ioctl.c linux-libre-4.10-rc8-gnu/drivers/char/agp/compat_ioctl.c
--- linux-libre-4.9-gnu/drivers/char/agp/compat_ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/agp/compat_ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/fs.h>
 #include <linux/agpgart.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "agp.h"
 #include "compat_ioctl.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/agp/frontend.c linux-libre-4.10-rc8-gnu/drivers/char/agp/frontend.c
--- linux-libre-4.9-gnu/drivers/char/agp/frontend.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/agp/frontend.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/sched.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include "agp.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/applicom.c linux-libre-4.10-rc8-gnu/drivers/char/applicom.c
--- linux-libre-4.9-gnu/drivers/char/applicom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/applicom.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/fs.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "applicom.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/bfin-otp.c linux-libre-4.10-rc8-gnu/drivers/char/bfin-otp.c
--- linux-libre-4.9-gnu/drivers/char/bfin-otp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/bfin-otp.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 
 #include <asm/blackfin.h>
 #include <asm/bfrom.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
 #define stampit() stamp("here i am")
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/ds1620.c linux-libre-4.10-rc8-gnu/drivers/char/ds1620.c
--- linux-libre-4.9-gnu/drivers/char/ds1620.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/ds1620.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/therm.h>
 
 #ifdef CONFIG_PROC_FS
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/dtlk.c linux-libre-4.10-rc8-gnu/drivers/char/dtlk.c
--- linux-libre-4.9-gnu/drivers/char/dtlk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/dtlk.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@
 #include <linux/sched.h>
 #include <linux/mutex.h>
 #include <asm/io.h>		/* for inb_p, outb_p, inb, outb, etc. */
-#include <asm/uaccess.h>	/* for get_user, etc. */
+#include <linux/uaccess.h>	/* for get_user, etc. */
 #include <linux/wait.h>		/* for wait_queue */
 #include <linux/init.h>		/* for __init, module_{init,exit} */
 #include <linux/poll.h>		/* for POLLIN, etc. */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/generic_nvram.c linux-libre-4.10-rc8-gnu/drivers/char/generic_nvram.c
--- linux-libre-4.9-gnu/drivers/char/generic_nvram.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/generic_nvram.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/pagemap.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/nvram.h>
 #ifdef CONFIG_PPC_PMAC
 #include <asm/machdep.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hangcheck-timer.c linux-libre-4.10-rc8-gnu/drivers/char/hangcheck-timer.c
--- linux-libre-4.9-gnu/drivers/char/hangcheck-timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hangcheck-timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/sysrq.h>
 #include <linux/timer.h>
 #include <linux/hrtimer.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hpet.c linux-libre-4.10-rc8-gnu/drivers/char/hpet.c
--- linux-libre-4.9-gnu/drivers/char/hpet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hpet.c	2017-02-12 16:03:20.000000000 -0500
@@ -69,9 +69,9 @@ static u32 hpet_nhpet, hpet_max_freq = H
 #ifdef CONFIG_IA64
 static void __iomem *hpet_mctr;
 
-static cycle_t read_hpet(struct clocksource *cs)
+static u64 read_hpet(struct clocksource *cs)
 {
-	return (cycle_t)read_counter((void __iomem *)hpet_mctr);
+	return (u64)read_counter((void __iomem *)hpet_mctr);
 }
 
 static struct clocksource clocksource_hpet = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/atmel-rng.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/atmel-rng.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/atmel-rng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/atmel-rng.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,16 @@ static int atmel_trng_read(struct hwrng
 		return 0;
 }
 
+static void atmel_trng_enable(struct atmel_trng *trng)
+{
+	writel(TRNG_KEY | 1, trng->base + TRNG_CR);
+}
+
+static void atmel_trng_disable(struct atmel_trng *trng)
+{
+	writel(TRNG_KEY, trng->base + TRNG_CR);
+}
+
 static int atmel_trng_probe(struct platform_device *pdev)
 {
 	struct atmel_trng *trng;
@@ -71,7 +81,7 @@ static int atmel_trng_probe(struct platf
 	if (ret)
 		return ret;
 
-	writel(TRNG_KEY | 1, trng->base + TRNG_CR);
+	atmel_trng_enable(trng);
 	trng->rng.name = pdev->name;
 	trng->rng.read = atmel_trng_read;
 
@@ -84,7 +94,7 @@ static int atmel_trng_probe(struct platf
 	return 0;
 
 err_register:
-	clk_disable(trng->clk);
+	clk_disable_unprepare(trng->clk);
 	return ret;
 }
 
@@ -94,7 +104,7 @@ static int atmel_trng_remove(struct plat
 
 	hwrng_unregister(&trng->rng);
 
-	writel(TRNG_KEY, trng->base + TRNG_CR);
+	atmel_trng_disable(trng);
 	clk_disable_unprepare(trng->clk);
 
 	return 0;
@@ -105,6 +115,7 @@ static int atmel_trng_suspend(struct dev
 {
 	struct atmel_trng *trng = dev_get_drvdata(dev);
 
+	atmel_trng_disable(trng);
 	clk_disable_unprepare(trng->clk);
 
 	return 0;
@@ -113,8 +124,15 @@ static int atmel_trng_suspend(struct dev
 static int atmel_trng_resume(struct device *dev)
 {
 	struct atmel_trng *trng = dev_get_drvdata(dev);
+	int ret;
 
-	return clk_prepare_enable(trng->clk);
+	ret = clk_prepare_enable(trng->clk);
+	if (ret)
+		return ret;
+
+	atmel_trng_enable(trng);
+
+	return 0;
 }
 
 static const struct dev_pm_ops atmel_trng_pm_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/core.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/core.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/err.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 #define RNG_MODULE_NAME		"hw_random"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/Kconfig linux-libre-4.10-rc8-gnu/drivers/char/hw_random/Kconfig
--- linux-libre-4.9-gnu/drivers/char/hw_random/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -168,7 +168,7 @@ config HW_RANDOM_IXP4XX
 
 config HW_RANDOM_OMAP
 	tristate "OMAP Random Number Generator support"
-	depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS
+	depends on ARCH_OMAP16XX || ARCH_OMAP2PLUS || ARCH_MVEBU
 	default HW_RANDOM
  	---help---
  	  This driver provides kernel-side support for the Random Number
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/meson-rng.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/meson-rng.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/meson-rng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/meson-rng.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,6 +110,7 @@ static const struct of_device_id meson_r
 	{ .compatible = "amlogic,meson-rng", },
 	{},
 };
+MODULE_DEVICE_TABLE(of, meson_rng_of_match);
 
 static struct platform_driver meson_rng_driver = {
 	.probe	= meson_rng_probe,
@@ -121,7 +122,6 @@ static struct platform_driver meson_rng_
 
 module_platform_driver(meson_rng_driver);
 
-MODULE_ALIAS("platform:meson-rng");
 MODULE_DESCRIPTION("Meson H/W Random Number Generator driver");
 MODULE_AUTHOR("Lawrence Mok <lawrence.mok@amlogic.com>");
 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/msm-rng.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/msm-rng.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/msm-rng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/msm-rng.c	2017-02-12 16:03:20.000000000 -0500
@@ -90,10 +90,6 @@ static int msm_rng_read(struct hwrng *hw
 	/* calculate max size bytes to transfer back to caller */
 	maxsize = min_t(size_t, MAX_HW_FIFO_SIZE, max);
 
-	/* no room for word data */
-	if (maxsize < WORD_SZ)
-		return 0;
-
 	ret = clk_prepare_enable(rng->clk);
 	if (ret)
 		return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/omap-rng.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/omap-rng.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/omap-rng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/omap-rng.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/of_device.h>
 #include <linux/of_address.h>
 #include <linux/interrupt.h>
+#include <linux/clk.h>
 
 #include <asm/io.h>
 
@@ -63,10 +64,13 @@
 
 #define OMAP2_RNG_OUTPUT_SIZE			0x4
 #define OMAP4_RNG_OUTPUT_SIZE			0x8
+#define EIP76_RNG_OUTPUT_SIZE			0x10
 
 enum {
-	RNG_OUTPUT_L_REG = 0,
-	RNG_OUTPUT_H_REG,
+	RNG_OUTPUT_0_REG = 0,
+	RNG_OUTPUT_1_REG,
+	RNG_OUTPUT_2_REG,
+	RNG_OUTPUT_3_REG,
 	RNG_STATUS_REG,
 	RNG_INTMASK_REG,
 	RNG_INTACK_REG,
@@ -82,7 +86,7 @@ enum {
 };
 
 static const u16 reg_map_omap2[] = {
-	[RNG_OUTPUT_L_REG]	= 0x0,
+	[RNG_OUTPUT_0_REG]	= 0x0,
 	[RNG_STATUS_REG]	= 0x4,
 	[RNG_CONFIG_REG]	= 0x28,
 	[RNG_REV_REG]		= 0x3c,
@@ -90,8 +94,8 @@ static const u16 reg_map_omap2[] = {
 };
 
 static const u16 reg_map_omap4[] = {
-	[RNG_OUTPUT_L_REG]	= 0x0,
-	[RNG_OUTPUT_H_REG]	= 0x4,
+	[RNG_OUTPUT_0_REG]	= 0x0,
+	[RNG_OUTPUT_1_REG]	= 0x4,
 	[RNG_STATUS_REG]	= 0x8,
 	[RNG_INTMASK_REG]	= 0xc,
 	[RNG_INTACK_REG]	= 0x10,
@@ -106,6 +110,23 @@ static const u16 reg_map_omap4[] = {
 	[RNG_SYSCONFIG_REG]	= 0x1FE4,
 };
 
+static const u16 reg_map_eip76[] = {
+	[RNG_OUTPUT_0_REG]	= 0x0,
+	[RNG_OUTPUT_1_REG]	= 0x4,
+	[RNG_OUTPUT_2_REG]	= 0x8,
+	[RNG_OUTPUT_3_REG]	= 0xc,
+	[RNG_STATUS_REG]	= 0x10,
+	[RNG_INTACK_REG]	= 0x10,
+	[RNG_CONTROL_REG]	= 0x14,
+	[RNG_CONFIG_REG]	= 0x18,
+	[RNG_ALARMCNT_REG]	= 0x1c,
+	[RNG_FROENABLE_REG]	= 0x20,
+	[RNG_FRODETUNE_REG]	= 0x24,
+	[RNG_ALARMMASK_REG]	= 0x28,
+	[RNG_ALARMSTOP_REG]	= 0x2c,
+	[RNG_REV_REG]		= 0x7c,
+};
+
 struct omap_rng_dev;
 /**
  * struct omap_rng_pdata - RNG IP block-specific data
@@ -127,6 +148,8 @@ struct omap_rng_dev {
 	void __iomem			*base;
 	struct device			*dev;
 	const struct omap_rng_pdata	*pdata;
+	struct hwrng rng;
+	struct clk 			*clk;
 };
 
 static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg)
@@ -140,41 +163,35 @@ static inline void omap_rng_write(struct
 	__raw_writel(val, priv->base + priv->pdata->regs[reg]);
 }
 
-static int omap_rng_data_present(struct hwrng *rng, int wait)
+
+static int omap_rng_do_read(struct hwrng *rng, void *data, size_t max,
+			    bool wait)
 {
 	struct omap_rng_dev *priv;
-	int data, i;
+	int i, present;
 
 	priv = (struct omap_rng_dev *)rng->priv;
 
+	if (max < priv->pdata->data_size)
+		return 0;
+
 	for (i = 0; i < 20; i++) {
-		data = priv->pdata->data_present(priv);
-		if (data || !wait)
+		present = priv->pdata->data_present(priv);
+		if (present || !wait)
 			break;
-		/* RNG produces data fast enough (2+ MBit/sec, even
-		 * during "rngtest" loads, that these delays don't
-		 * seem to trigger.  We *could* use the RNG IRQ, but
-		 * that'd be higher overhead ... so why bother?
-		 */
+
 		udelay(10);
 	}
-	return data;
-}
-
-static int omap_rng_data_read(struct hwrng *rng, u32 *data)
-{
-	struct omap_rng_dev *priv;
-	u32 data_size, i;
-
-	priv = (struct omap_rng_dev *)rng->priv;
-	data_size = priv->pdata->data_size;
+	if (!present)
+		return 0;
 
-	for (i = 0; i < data_size / sizeof(u32); i++)
-		data[i] = omap_rng_read(priv, RNG_OUTPUT_L_REG + i);
+	memcpy_fromio(data, priv->base + priv->pdata->regs[RNG_OUTPUT_0_REG],
+		      priv->pdata->data_size);
 
 	if (priv->pdata->regs[RNG_INTACK_REG])
 		omap_rng_write(priv, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK);
-	return data_size;
+
+	return priv->pdata->data_size;
 }
 
 static int omap_rng_init(struct hwrng *rng)
@@ -193,13 +210,6 @@ static void omap_rng_cleanup(struct hwrn
 	priv->pdata->cleanup(priv);
 }
 
-static struct hwrng omap_rng_ops = {
-	.name		= "omap",
-	.data_present	= omap_rng_data_present,
-	.data_read	= omap_rng_data_read,
-	.init		= omap_rng_init,
-	.cleanup	= omap_rng_cleanup,
-};
 
 static inline u32 omap2_rng_data_present(struct omap_rng_dev *priv)
 {
@@ -231,6 +241,38 @@ static inline u32 omap4_rng_data_present
 	return omap_rng_read(priv, RNG_STATUS_REG) & RNG_REG_STATUS_RDY;
 }
 
+static int eip76_rng_init(struct omap_rng_dev *priv)
+{
+	u32 val;
+
+	/* Return if RNG is already running. */
+	if (omap_rng_read(priv, RNG_CONTROL_REG) & RNG_CONTROL_ENABLE_TRNG_MASK)
+		return 0;
+
+	/*  Number of 512 bit blocks of raw Noise Source output data that must
+	 *  be processed by either the Conditioning Function or the
+	 *  SP 800-90 DRBG ‘BC_DF’ functionality to yield a ‘full entropy’
+	 *  output value.
+	 */
+	val = 0x5 << RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT;
+
+	/* Number of FRO samples that are XOR-ed together into one bit to be
+	 * shifted into the main shift register
+	 */
+	val |= RNG_CONFIG_MAX_REFIL_CYCLES << RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT;
+	omap_rng_write(priv, RNG_CONFIG_REG, val);
+
+	/* Enable all available FROs */
+	omap_rng_write(priv, RNG_FRODETUNE_REG, 0x0);
+	omap_rng_write(priv, RNG_FROENABLE_REG, RNG_REG_FROENABLE_MASK);
+
+	/* Enable TRNG */
+	val = RNG_CONTROL_ENABLE_TRNG_MASK;
+	omap_rng_write(priv, RNG_CONTROL_REG, val);
+
+	return 0;
+}
+
 static int omap4_rng_init(struct omap_rng_dev *priv)
 {
 	u32 val;
@@ -300,6 +342,14 @@ static struct omap_rng_pdata omap4_rng_p
 	.cleanup	= omap4_rng_cleanup,
 };
 
+static struct omap_rng_pdata eip76_rng_pdata = {
+	.regs		= (u16 *)reg_map_eip76,
+	.data_size	= EIP76_RNG_OUTPUT_SIZE,
+	.data_present	= omap4_rng_data_present,
+	.init		= eip76_rng_init,
+	.cleanup	= omap4_rng_cleanup,
+};
+
 static const struct of_device_id omap_rng_of_match[] = {
 		{
 			.compatible	= "ti,omap2-rng",
@@ -309,6 +359,10 @@ static const struct of_device_id omap_rn
 			.compatible	= "ti,omap4-rng",
 			.data		= &omap4_rng_pdata,
 		},
+		{
+			.compatible	= "inside-secure,safexcel-eip76",
+			.data		= &eip76_rng_pdata,
+		},
 		{},
 };
 MODULE_DEVICE_TABLE(of, omap_rng_of_match);
@@ -327,7 +381,8 @@ static int of_get_omap_rng_device_detail
 	}
 	priv->pdata = match->data;
 
-	if (of_device_is_compatible(dev->of_node, "ti,omap4-rng")) {
+	if (of_device_is_compatible(dev->of_node, "ti,omap4-rng") ||
+	    of_device_is_compatible(dev->of_node, "inside-secure,safexcel-eip76")) {
 		irq = platform_get_irq(pdev, 0);
 		if (irq < 0) {
 			dev_err(dev, "%s: error getting IRQ resource - %d\n",
@@ -343,6 +398,16 @@ static int of_get_omap_rng_device_detail
 			return err;
 		}
 		omap_rng_write(priv, RNG_INTMASK_REG, RNG_SHUTDOWN_OFLO_MASK);
+
+		priv->clk = of_clk_get(pdev->dev.of_node, 0);
+		if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		if (!IS_ERR(priv->clk)) {
+			err = clk_prepare_enable(priv->clk);
+			if (err)
+				dev_err(&pdev->dev, "unable to enable the clk, "
+						    "err = %d\n", err);
+		}
 	}
 	return 0;
 }
@@ -372,7 +437,11 @@ static int omap_rng_probe(struct platfor
 	if (!priv)
 		return -ENOMEM;
 
-	omap_rng_ops.priv = (unsigned long)priv;
+	priv->rng.read = omap_rng_do_read;
+	priv->rng.init = omap_rng_init;
+	priv->rng.cleanup = omap_rng_cleanup;
+
+	priv->rng.priv = (unsigned long)priv;
 	platform_set_drvdata(pdev, priv);
 	priv->dev = dev;
 
@@ -383,6 +452,12 @@ static int omap_rng_probe(struct platfor
 		goto err_ioremap;
 	}
 
+	priv->rng.name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
+	if (!priv->rng.name) {
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
 	pm_runtime_enable(&pdev->dev);
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0) {
@@ -394,20 +469,24 @@ static int omap_rng_probe(struct platfor
 	ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
 				get_omap_rng_device_details(priv);
 	if (ret)
-		goto err_ioremap;
+		goto err_register;
 
-	ret = hwrng_register(&omap_rng_ops);
+	ret = hwrng_register(&priv->rng);
 	if (ret)
 		goto err_register;
 
-	dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
+	dev_info(&pdev->dev, "Random Number Generator ver. %02x\n",
 		 omap_rng_read(priv, RNG_REV_REG));
 
 	return 0;
 
 err_register:
 	priv->base = NULL;
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
+
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
 err_ioremap:
 	dev_err(dev, "initialization failed.\n");
 	return ret;
@@ -417,13 +496,16 @@ static int omap_rng_remove(struct platfo
 {
 	struct omap_rng_dev *priv = platform_get_drvdata(pdev);
 
-	hwrng_unregister(&omap_rng_ops);
+	hwrng_unregister(&priv->rng);
 
 	priv->pdata->cleanup(priv);
 
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/pic32-rng.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/pic32-rng.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/pic32-rng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/pic32-rng.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,9 +62,6 @@ static int pic32_rng_read(struct hwrng *
 	u32 t;
 	unsigned int timeout = RNG_TIMEOUT;
 
-	if (max < 8)
-		return 0;
-
 	do {
 		t = readl(priv->base + RNGRCNT) & RCNT_MASK;
 		if (t == 64) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/pseries-rng.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/pseries-rng.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/pseries-rng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/pseries-rng.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,6 @@
 static int pseries_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
 	u64 buffer[PLPAR_HCALL_BUFSIZE];
-	size_t size = max < 8 ? max : 8;
 	int rc;
 
 	rc = plpar_hcall(H_RANDOM, (unsigned long *)buffer);
@@ -36,10 +35,10 @@ static int pseries_rng_read(struct hwrng
 		pr_err_ratelimited("H_RANDOM call failed %d\n", rc);
 		return -EIO;
 	}
-	memcpy(data, buffer, size);
+	memcpy(data, buffer, 8);
 
 	/* The hypervisor interface returns 64 bits */
-	return size;
+	return 8;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/hw_random/via-rng.c linux-libre-4.10-rc8-gnu/drivers/char/hw_random/via-rng.c
--- linux-libre-4.9-gnu/drivers/char/hw_random/via-rng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/hw_random/via-rng.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,21 +70,17 @@ enum {
  * until we have 4 bytes, thus returning a u32 at a time,
  * instead of the current u8-at-a-time.
  *
- * Padlock instructions can generate a spurious DNA fault, so
- * we have to call them in the context of irq_ts_save/restore()
+ * Padlock instructions can generate a spurious DNA fault, but the
+ * kernel doesn't use CR0.TS, so this doesn't matter.
  */
 
 static inline u32 xstore(u32 *addr, u32 edx_in)
 {
 	u32 eax_out;
-	int ts_state;
-
-	ts_state = irq_ts_save();
 
 	asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
 		: "=m" (*addr), "=a" (eax_out), "+d" (edx_in), "+D" (addr));
 
-	irq_ts_restore(ts_state);
 	return eax_out;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_devintf.c linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_devintf.c
--- linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_devintf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_devintf.c	2017-02-12 16:03:20.000000000 -0500
@@ -989,4 +989,3 @@ module_exit(cleanup_ipmi);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Corey Minyard <minyard@mvista.com>");
 MODULE_DESCRIPTION("Linux device interface for the IPMI message handler.");
-MODULE_ALIAS("platform:ipmi_si");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_msghandler.c linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_msghandler.c
--- linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_msghandler.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_msghandler.c	2017-02-12 16:03:20.000000000 -0500
@@ -158,15 +158,16 @@ struct seq_table {
  * Store the information in a msgid (long) to allow us to find a
  * sequence table entry from the msgid.
  */
-#define STORE_SEQ_IN_MSGID(seq, seqid) (((seq&0xff)<<26) | (seqid&0x3ffffff))
+#define STORE_SEQ_IN_MSGID(seq, seqid) \
+	((((seq) & 0x3f) << 26) | ((seqid) & 0x3ffffff))
 
 #define GET_SEQ_FROM_MSGID(msgid, seq, seqid) \
 	do {								\
-		seq = ((msgid >> 26) & 0x3f);				\
-		seqid = (msgid & 0x3fffff);				\
+		seq = (((msgid) >> 26) & 0x3f);				\
+		seqid = ((msgid) & 0x3ffffff);				\
 	} while (0)
 
-#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3fffff)
+#define NEXT_SEQID(seqid) (((seqid) + 1) & 0x3ffffff)
 
 struct ipmi_channel {
 	unsigned char medium;
@@ -4645,3 +4646,4 @@ MODULE_AUTHOR("Corey Minyard <minyard@mv
 MODULE_DESCRIPTION("Incoming and outgoing message routing for an IPMI"
 		   " interface.");
 MODULE_VERSION(IPMI_DRIVER_VERSION);
+MODULE_SOFTDEP("post: ipmi_devintf");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_si_intf.c linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_si_intf.c
--- linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_si_intf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_si_intf.c	2017-02-12 16:03:20.000000000 -0500
@@ -789,7 +789,7 @@ static void handle_transaction_done(stru
 				smi_info->si_state = SI_NORMAL;
 				break;
 			}
-			start_getting_msg_queue(smi_info);
+			start_getting_events(smi_info);
 		} else {
 			smi_info->si_state = SI_NORMAL;
 		}
@@ -812,7 +812,7 @@ static void handle_transaction_done(stru
 				smi_info->si_state = SI_NORMAL;
 				break;
 			}
-			start_getting_msg_queue(smi_info);
+			start_getting_events(smi_info);
 		} else {
 			smi_info->si_state = SI_NORMAL;
 		}
@@ -1764,7 +1764,7 @@ static int parse_str(const struct hotmod
 
 	s = strchr(*curr, ',');
 	if (!s) {
-		printk(KERN_WARNING PFX "No hotmod %s given.\n", name);
+		pr_warn(PFX "No hotmod %s given.\n", name);
 		return -EINVAL;
 	}
 	*s = '\0';
@@ -1777,7 +1777,7 @@ static int parse_str(const struct hotmod
 		}
 	}
 
-	printk(KERN_WARNING PFX "Invalid hotmod %s '%s'\n", name, *curr);
+	pr_warn(PFX "Invalid hotmod %s '%s'\n", name, *curr);
 	return -EINVAL;
 }
 
@@ -1788,16 +1788,12 @@ static int check_hotmod_int_op(const cha
 
 	if (strcmp(curr, name) == 0) {
 		if (!option) {
-			printk(KERN_WARNING PFX
-			       "No option given for '%s'\n",
-			       curr);
+			pr_warn(PFX "No option given for '%s'\n", curr);
 			return -EINVAL;
 		}
 		*val = simple_strtoul(option, &n, 0);
 		if ((*n != '\0') || (*option == '\0')) {
-			printk(KERN_WARNING PFX
-			       "Bad option given for '%s'\n",
-			       curr);
+			pr_warn(PFX "Bad option given for '%s'\n", curr);
 			return -EINVAL;
 		}
 		return 1;
@@ -1877,8 +1873,7 @@ static int hotmod_handler(const char *va
 		}
 		addr = simple_strtoul(curr, &n, 0);
 		if ((*n != '\0') || (*curr == '\0')) {
-			printk(KERN_WARNING PFX "Invalid hotmod address"
-			       " '%s'\n", curr);
+			pr_warn(PFX "Invalid hotmod address '%s'\n", curr);
 			break;
 		}
 
@@ -1921,9 +1916,7 @@ static int hotmod_handler(const char *va
 				continue;
 
 			rv = -EINVAL;
-			printk(KERN_WARNING PFX
-			       "Invalid hotmod option '%s'\n",
-			       curr);
+			pr_warn(PFX "Invalid hotmod option '%s'\n", curr);
 			goto out;
 		}
 
@@ -2003,7 +1996,7 @@ static int hardcode_find_bmc(void)
 			return -ENOMEM;
 
 		info->addr_source = SI_HARDCODED;
-		printk(KERN_INFO PFX "probing via hardcoded address\n");
+		pr_info(PFX "probing via hardcoded address\n");
 
 		if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) {
 			info->si_type = SI_KCS;
@@ -2012,9 +2005,8 @@ static int hardcode_find_bmc(void)
 		} else if (strcmp(si_type[i], "bt") == 0) {
 			info->si_type = SI_BT;
 		} else {
-			printk(KERN_WARNING PFX "Interface type specified "
-			       "for interface %d, was invalid: %s\n",
-			       i, si_type[i]);
+			pr_warn(PFX "Interface type specified for interface %d, was invalid: %s\n",
+				i, si_type[i]);
 			kfree(info);
 			continue;
 		}
@@ -2030,9 +2022,8 @@ static int hardcode_find_bmc(void)
 			info->io.addr_data = addrs[i];
 			info->io.addr_type = IPMI_MEM_ADDR_SPACE;
 		} else {
-			printk(KERN_WARNING PFX "Interface type specified "
-			       "for interface %d, but port and address were "
-			       "not set or set to zero.\n", i);
+			pr_warn(PFX "Interface type specified for interface %d, but port and address were not set or set to zero.\n",
+				i);
 			kfree(info);
 			continue;
 		}
@@ -2173,18 +2164,18 @@ static int try_init_spmi(struct SPMITabl
 	int rv;
 
 	if (spmi->IPMIlegacy != 1) {
-		printk(KERN_INFO PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy);
+		pr_info(PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy);
 		return -ENODEV;
 	}
 
 	info = smi_info_alloc();
 	if (!info) {
-		printk(KERN_ERR PFX "Could not allocate SI data (3)\n");
+		pr_err(PFX "Could not allocate SI data (3)\n");
 		return -ENOMEM;
 	}
 
 	info->addr_source = SI_SPMI;
-	printk(KERN_INFO PFX "probing via SPMI\n");
+	pr_info(PFX "probing via SPMI\n");
 
 	/* Figure out the interface type. */
 	switch (spmi->InterfaceType) {
@@ -2201,8 +2192,8 @@ static int try_init_spmi(struct SPMITabl
 		kfree(info);
 		return -EIO;
 	default:
-		printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n",
-		       spmi->InterfaceType);
+		pr_info(PFX "Unknown ACPI/SPMI SI type %d\n",
+			spmi->InterfaceType);
 		kfree(info);
 		return -EIO;
 	}
@@ -2238,15 +2229,15 @@ static int try_init_spmi(struct SPMITabl
 		info->io.addr_type = IPMI_IO_ADDR_SPACE;
 	} else {
 		kfree(info);
-		printk(KERN_WARNING PFX "Unknown ACPI I/O Address type\n");
+		pr_warn(PFX "Unknown ACPI I/O Address type\n");
 		return -EIO;
 	}
 	info->io.addr_data = spmi->addr.address;
 
 	pr_info("ipmi_si: SPMI: %s %#lx regsize %d spacing %d irq %d\n",
-		 (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
-		 info->io.addr_data, info->io.regsize, info->io.regspacing,
-		 info->irq);
+		(info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
+		info->io.addr_data, info->io.regsize, info->io.regspacing,
+		info->irq);
 
 	rv = add_smi(info);
 	if (rv)
@@ -2356,12 +2347,12 @@ static void try_init_dmi(struct dmi_ipmi
 
 	info = smi_info_alloc();
 	if (!info) {
-		printk(KERN_ERR PFX "Could not allocate SI data\n");
+		pr_err(PFX "Could not allocate SI data\n");
 		return;
 	}
 
 	info->addr_source = SI_SMBIOS;
-	printk(KERN_INFO PFX "probing via SMBIOS\n");
+	pr_info(PFX "probing via SMBIOS\n");
 
 	switch (ipmi_data->type) {
 	case 0x01: /* KCS */
@@ -2391,8 +2382,8 @@ static void try_init_dmi(struct dmi_ipmi
 
 	default:
 		kfree(info);
-		printk(KERN_WARNING PFX "Unknown SMBIOS I/O Address type: %d\n",
-		       ipmi_data->addr_space);
+		pr_warn(PFX "Unknown SMBIOS I/O Address type: %d\n",
+			ipmi_data->addr_space);
 		return;
 	}
 	info->io.addr_data = ipmi_data->base_addr;
@@ -2410,9 +2401,9 @@ static void try_init_dmi(struct dmi_ipmi
 		info->irq_setup = std_irq_setup;
 
 	pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n",
-		 (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
-		 info->io.addr_data, info->io.regsize, info->io.regspacing,
-		 info->irq);
+		(info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
+		info->io.addr_data, info->io.regsize, info->io.regspacing,
+		info->irq);
 
 	if (add_smi(info))
 		kfree(info);
@@ -3141,9 +3132,7 @@ static int try_enable_event_buffer(struc
 
 	rv = wait_for_msg_done(smi_info);
 	if (rv) {
-		printk(KERN_WARNING PFX "Error getting response from get"
-		       " global enables command, the event buffer is not"
-		       " enabled.\n");
+		pr_warn(PFX "Error getting response from get global enables command, the event buffer is not enabled.\n");
 		goto out;
 	}
 
@@ -3154,8 +3143,7 @@ static int try_enable_event_buffer(struc
 			resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
 			resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD   ||
 			resp[2] != 0) {
-		printk(KERN_WARNING PFX "Invalid return from get global"
-		       " enables command, cannot enable the event buffer.\n");
+		pr_warn(PFX "Invalid return from get global enables command, cannot enable the event buffer.\n");
 		rv = -EINVAL;
 		goto out;
 	}
@@ -3173,9 +3161,7 @@ static int try_enable_event_buffer(struc
 
 	rv = wait_for_msg_done(smi_info);
 	if (rv) {
-		printk(KERN_WARNING PFX "Error getting response from set"
-		       " global, enables command, the event buffer is not"
-		       " enabled.\n");
+		pr_warn(PFX "Error getting response from set global, enables command, the event buffer is not enabled.\n");
 		goto out;
 	}
 
@@ -3185,8 +3171,7 @@ static int try_enable_event_buffer(struc
 	if (resp_len < 3 ||
 			resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
 			resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
-		printk(KERN_WARNING PFX "Invalid return from get global,"
-		       "enables command, not enable the event buffer.\n");
+		pr_warn(PFX "Invalid return from get global, enables command, not enable the event buffer.\n");
 		rv = -EINVAL;
 		goto out;
 	}
@@ -3463,8 +3448,16 @@ static int is_new_interface(struct smi_i
 	list_for_each_entry(e, &smi_infos, link) {
 		if (e->io.addr_type != info->io.addr_type)
 			continue;
-		if (e->io.addr_data == info->io.addr_data)
+		if (e->io.addr_data == info->io.addr_data) {
+			/*
+			 * This is a cheap hack, ACPI doesn't have a defined
+			 * slave address but SMBIOS does.  Pick it up from
+			 * any source that has it available.
+			 */
+			if (info->slave_addr && !e->slave_addr)
+				e->slave_addr = info->slave_addr;
 			return 0;
+		}
 	}
 
 	return 1;
@@ -3474,17 +3467,18 @@ static int add_smi(struct smi_info *new_
 {
 	int rv = 0;
 
-	printk(KERN_INFO PFX "Adding %s-specified %s state machine",
-	       ipmi_addr_src_to_str(new_smi->addr_source),
-	       si_to_str[new_smi->si_type]);
 	mutex_lock(&smi_infos_lock);
 	if (!is_new_interface(new_smi)) {
-		printk(KERN_CONT " duplicate interface\n");
+		pr_info(PFX "%s-specified %s state machine: duplicate\n",
+			ipmi_addr_src_to_str(new_smi->addr_source),
+			si_to_str[new_smi->si_type]);
 		rv = -EBUSY;
 		goto out_err;
 	}
 
-	printk(KERN_CONT "\n");
+	pr_info(PFX "Adding %s-specified %s state machine\n",
+		ipmi_addr_src_to_str(new_smi->addr_source),
+		si_to_str[new_smi->si_type]);
 
 	/* So we know not to free it unless we have allocated one. */
 	new_smi->intf = NULL;
@@ -3502,15 +3496,14 @@ static int try_smi_init(struct smi_info
 {
 	int rv = 0;
 	int i;
+	char *init_name = NULL;
 
-	printk(KERN_INFO PFX "Trying %s-specified %s state"
-	       " machine at %s address 0x%lx, slave address 0x%x,"
-	       " irq %d\n",
-	       ipmi_addr_src_to_str(new_smi->addr_source),
-	       si_to_str[new_smi->si_type],
-	       addr_space_to_str[new_smi->io.addr_type],
-	       new_smi->io.addr_data,
-	       new_smi->slave_addr, new_smi->irq);
+	pr_info(PFX "Trying %s-specified %s state machine at %s address 0x%lx, slave address 0x%x, irq %d\n",
+		ipmi_addr_src_to_str(new_smi->addr_source),
+		si_to_str[new_smi->si_type],
+		addr_space_to_str[new_smi->io.addr_type],
+		new_smi->io.addr_data,
+		new_smi->slave_addr, new_smi->irq);
 
 	switch (new_smi->si_type) {
 	case SI_KCS:
@@ -3531,11 +3524,30 @@ static int try_smi_init(struct smi_info
 		goto out_err;
 	}
 
+	/* Do this early so it's available for logs. */
+	if (!new_smi->dev) {
+		init_name = kasprintf(GFP_KERNEL, "ipmi_si.%d", 0);
+
+		/*
+		 * If we don't already have a device from something
+		 * else (like PCI), then register a new one.
+		 */
+		new_smi->pdev = platform_device_alloc("ipmi_si",
+						      new_smi->intf_num);
+		if (!new_smi->pdev) {
+			pr_err(PFX "Unable to allocate platform device\n");
+			goto out_err;
+		}
+		new_smi->dev = &new_smi->pdev->dev;
+		new_smi->dev->driver = &ipmi_driver.driver;
+		/* Nulled by device_add() */
+		new_smi->dev->init_name = init_name;
+	}
+
 	/* Allocate the state machine's data and initialize it. */
 	new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL);
 	if (!new_smi->si_sm) {
-		printk(KERN_ERR PFX
-		       "Could not allocate state machine memory\n");
+		pr_err(PFX "Could not allocate state machine memory\n");
 		rv = -ENOMEM;
 		goto out_err;
 	}
@@ -3545,14 +3557,14 @@ static int try_smi_init(struct smi_info
 	/* Now that we know the I/O size, we can set up the I/O. */
 	rv = new_smi->io_setup(new_smi);
 	if (rv) {
-		printk(KERN_ERR PFX "Could not set up I/O space\n");
+		dev_err(new_smi->dev, "Could not set up I/O space\n");
 		goto out_err;
 	}
 
 	/* Do low-level detection first. */
 	if (new_smi->handlers->detect(new_smi->si_sm)) {
 		if (new_smi->addr_source)
-			printk(KERN_INFO PFX "Interface detection failed\n");
+			dev_err(new_smi->dev, "Interface detection failed\n");
 		rv = -ENODEV;
 		goto out_err;
 	}
@@ -3564,8 +3576,7 @@ static int try_smi_init(struct smi_info
 	rv = try_get_dev_id(new_smi);
 	if (rv) {
 		if (new_smi->addr_source)
-			printk(KERN_INFO PFX "There appears to be no BMC"
-			       " at this location\n");
+			dev_err(new_smi->dev, "There appears to be no BMC at this location\n");
 		goto out_err;
 	}
 
@@ -3604,27 +3615,12 @@ static int try_smi_init(struct smi_info
 		atomic_set(&new_smi->req_events, 1);
 	}
 
-	if (!new_smi->dev) {
-		/*
-		 * If we don't already have a device from something
-		 * else (like PCI), then register a new one.
-		 */
-		new_smi->pdev = platform_device_alloc("ipmi_si",
-						      new_smi->intf_num);
-		if (!new_smi->pdev) {
-			printk(KERN_ERR PFX
-			       "Unable to allocate platform device\n");
-			goto out_err;
-		}
-		new_smi->dev = &new_smi->pdev->dev;
-		new_smi->dev->driver = &ipmi_driver.driver;
-
+	if (new_smi->pdev) {
 		rv = platform_device_add(new_smi->pdev);
 		if (rv) {
-			printk(KERN_ERR PFX
-			       "Unable to register system interface device:"
-			       " %d\n",
-			       rv);
+			dev_err(new_smi->dev,
+				"Unable to register system interface device: %d\n",
+				rv);
 			goto out_err;
 		}
 		new_smi->dev_registered = true;
@@ -3668,6 +3664,9 @@ static int try_smi_init(struct smi_info
 	dev_info(new_smi->dev, "IPMI %s interface initialized\n",
 		 si_to_str[new_smi->si_type]);
 
+	WARN_ON(new_smi->dev->init_name != NULL);
+	kfree(init_name);
+
 	return 0;
 
 out_err_stop_timer:
@@ -3712,8 +3711,14 @@ out_err:
 	if (new_smi->dev_registered) {
 		platform_device_unregister(new_smi->pdev);
 		new_smi->dev_registered = false;
+		new_smi->pdev = NULL;
+	} else if (new_smi->pdev) {
+		platform_device_put(new_smi->pdev);
+		new_smi->pdev = NULL;
 	}
 
+	kfree(init_name);
+
 	return rv;
 }
 
@@ -3732,8 +3737,7 @@ static int init_ipmi_si(void)
 	if (si_tryplatform) {
 		rv = platform_driver_register(&ipmi_driver);
 		if (rv) {
-			printk(KERN_ERR PFX "Unable to register "
-			       "driver: %d\n", rv);
+			pr_err(PFX "Unable to register driver: %d\n", rv);
 			return rv;
 		}
 	}
@@ -3753,7 +3757,7 @@ static int init_ipmi_si(void)
 		}
 	}
 
-	printk(KERN_INFO "IPMI System Interface driver.\n");
+	pr_info("IPMI System Interface driver.\n");
 
 	/* If the user gave us a device, they presumably want us to use it */
 	if (!hardcode_find_bmc())
@@ -3763,8 +3767,7 @@ static int init_ipmi_si(void)
 	if (si_trypci) {
 		rv = pci_register_driver(&ipmi_pci_driver);
 		if (rv)
-			printk(KERN_ERR PFX "Unable to register "
-			       "PCI driver: %d\n", rv);
+			pr_err(PFX "Unable to register PCI driver: %d\n", rv);
 		else
 			pci_registered = true;
 	}
@@ -3826,8 +3829,7 @@ static int init_ipmi_si(void)
 	if (unload_when_empty && list_empty(&smi_infos)) {
 		mutex_unlock(&smi_infos_lock);
 		cleanup_ipmi_si();
-		printk(KERN_WARNING PFX
-		       "Unable to find any System Interface(s)\n");
+		pr_warn(PFX "Unable to find any System Interface(s)\n");
 		return -ENODEV;
 	} else {
 		mutex_unlock(&smi_infos_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_ssif.c linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_ssif.c
--- linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_ssif.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_ssif.c	2017-02-12 16:03:20.000000000 -0500
@@ -174,7 +174,6 @@ enum ssif_stat_indexes {
 };
 
 struct ssif_addr_info {
-	unsigned short addr;
 	struct i2c_board_info binfo;
 	char *adapter_name;
 	int debug;
@@ -1154,10 +1153,6 @@ static bool ssif_dbg_probe;
 module_param_named(dbg_probe, ssif_dbg_probe, bool, 0);
 MODULE_PARM_DESC(dbg_probe, "Enable debugging of probing of adapters.");
 
-static int use_thread;
-module_param(use_thread, int, 0);
-MODULE_PARM_DESC(use_thread, "Use the thread interface.");
-
 static bool ssif_tryacpi = true;
 module_param_named(tryacpi, ssif_tryacpi, bool, 0);
 MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the default scan of the interfaces identified via ACPI");
@@ -1405,6 +1400,34 @@ static bool check_acpi(struct ssif_info
 	return false;
 }
 
+static int find_slave_address(struct i2c_client *client, int slave_addr)
+{
+	struct ssif_addr_info *info;
+
+	if (slave_addr)
+		return slave_addr;
+
+	/*
+	 * Came in without a slave address, search around to see if
+	 * the other sources have a slave address.  This lets us pick
+	 * up an SMBIOS slave address when using ACPI.
+	 */
+	list_for_each_entry(info, &ssif_infos, link) {
+		if (info->binfo.addr != client->addr)
+			continue;
+		if (info->adapter_name && client->adapter->name &&
+		    strcmp_nospace(info->adapter_name,
+				   client->adapter->name))
+			continue;
+		if (info->slave_addr) {
+			slave_addr = info->slave_addr;
+			break;
+		}
+	}
+
+	return slave_addr;
+}
+
 /*
  * Global enables we care about.
  */
@@ -1447,6 +1470,8 @@ static int ssif_probe(struct i2c_client
 		}
 	}
 
+	slave_addr = find_slave_address(client, slave_addr);
+
 	pr_info(PFX "Trying %s-specified SSIF interface at i2c address 0x%x, adapter %s, slave address 0x%x\n",
 	       ipmi_addr_src_to_str(ssif_info->addr_source),
 	       client->addr, client->adapter->name, slave_addr);
@@ -1935,7 +1960,7 @@ static int decode_dmi(const struct dmi_d
 		slave_addr = data[6];
 	}
 
-	return new_ssif_client(myaddr, NULL, 0, 0, SI_SMBIOS);
+	return new_ssif_client(myaddr, NULL, 0, slave_addr, SI_SMBIOS);
 }
 
 static void dmi_iterator(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_watchdog.c linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_watchdog.c
--- linux-libre-4.9-gnu/drivers/char/ipmi/ipmi_watchdog.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/ipmi/ipmi_watchdog.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@
 #include <linux/kdebug.h>
 #include <linux/rwsem.h>
 #include <linux/errno.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/notifier.h>
 #include <linux/nmi.h>
 #include <linux/reboot.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/Kconfig linux-libre-4.10-rc8-gnu/drivers/char/Kconfig
--- linux-libre-4.9-gnu/drivers/char/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,6 @@ config DEVMEM
 
 config DEVKMEM
 	bool "/dev/kmem virtual device support"
-	default y
 	help
 	  Say Y here if you want to support the /dev/kmem device. The
 	  /dev/kmem device is rarely used, but can be used for certain
@@ -542,6 +541,7 @@ config HANGCHECK_TIMER
 config MMTIMER
 	tristate "MMTIMER Memory mapped RTC for SGI Altix"
 	depends on IA64_GENERIC || IA64_SGI_SN2
+	depends on POSIX_TIMERS
 	default y
 	help
 	  The mmtimer device allows direct userspace access to the
@@ -578,7 +578,7 @@ config DEVPORT
 source "drivers/s390/char/Kconfig"
 
 config TILE_SROM
-	bool "Character-device access via hypervisor to the Tilera SPI ROM"
+	tristate "Character-device access via hypervisor to the Tilera SPI ROM"
 	depends on TILE
 	default y
 	---help---
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/lp.c linux-libre-4.10-rc8-gnu/drivers/char/lp.c
--- linux-libre-4.9-gnu/drivers/char/lp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/lp.c	2017-02-12 16:03:20.000000000 -0500
@@ -134,7 +134,7 @@
 #include <linux/lp.h>
 
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* if you have more than 8 printers, remember to increase LP_NO */
 #define LP_NO 8
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/mbcs.c linux-libre-4.10-rc8-gnu/drivers/char/mbcs.c
--- linux-libre-4.9-gnu/drivers/char/mbcs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/mbcs.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/intr.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/mem.c linux-libre-4.10-rc8-gnu/drivers/char/mem.c
--- linux-libre-4.9-gnu/drivers/char/mem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/mem.c	2017-02-12 16:03:20.000000000 -0500
@@ -381,9 +381,6 @@ static ssize_t read_kmem(struct file *fi
 	char *kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
 	int err = 0;
 
-	if (!pfn_valid(PFN_DOWN(p)))
-		return -EIO;
-
 	read = 0;
 	if (p < (unsigned long) high_memory) {
 		low_count = count;
@@ -412,6 +409,8 @@ static ssize_t read_kmem(struct file *fi
 			 * by the kernel or data corruption may occur
 			 */
 			kbuf = xlate_dev_kmem_ptr((void *)p);
+			if (!virt_addr_valid(kbuf))
+				return -ENXIO;
 
 			if (copy_to_user(buf, kbuf, sz))
 				return -EFAULT;
@@ -482,6 +481,8 @@ static ssize_t do_write_kmem(unsigned lo
 		 * corruption may occur.
 		 */
 		ptr = xlate_dev_kmem_ptr((void *)p);
+		if (!virt_addr_valid(ptr))
+			return -ENXIO;
 
 		copied = copy_from_user(ptr, buf, sz);
 		if (copied) {
@@ -512,9 +513,6 @@ static ssize_t write_kmem(struct file *f
 	char *kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
 	int err = 0;
 
-	if (!pfn_valid(PFN_DOWN(p)))
-		return -EIO;
-
 	if (p < (unsigned long) high_memory) {
 		unsigned long to_write = min_t(unsigned long, count,
 					       (unsigned long)high_memory - p);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/mmtimer.c linux-libre-4.10-rc8-gnu/drivers/char/mmtimer.c
--- linux-libre-4.9-gnu/drivers/char/mmtimer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/mmtimer.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/shub_mmr.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/mspec.c linux-libre-4.10-rc8-gnu/drivers/char/mspec.c
--- linux-libre-4.9-gnu/drivers/char/mspec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/mspec.c	2017-02-12 16:03:20.000000000 -0500
@@ -227,7 +227,7 @@ mspec_fault(struct vm_area_struct *vma,
 	 * be because another thread has installed the pte first, so it
 	 * is no problem.
 	 */
-	vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+	vm_insert_pfn(vma, vmf->address, pfn);
 
 	return VM_FAULT_NOPAGE;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/mwave/3780i.c linux-libre-4.10-rc8-gnu/drivers/char/mwave/3780i.c
--- linux-libre-4.9-gnu/drivers/char/mwave/3780i.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/mwave/3780i.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 #include <linux/sched.h>	/* cond_resched() */
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 #include "smapi.h"
 #include "mwavedd.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/mwave/mwavedd.h linux-libre-4.10-rc8-gnu/drivers/char/mwave/mwavedd.h
--- linux-libre-4.9-gnu/drivers/char/mwave/mwavedd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/mwave/mwavedd.h	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@
 #include "smapi.h"
 #include "mwavepub.h"
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/wait.h>
 
 extern int mwave_debug;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/nsc_gpio.c linux-libre-4.10-rc8-gnu/drivers/char/nsc_gpio.c
--- linux-libre-4.9-gnu/drivers/char/nsc_gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/nsc_gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/nsc_gpio.h>
 #include <linux/platform_device.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #define NAME "nsc_gpio"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/nwbutton.c linux-libre-4.10-rc8-gnu/drivers/char/nwbutton.c
--- linux-libre-4.9-gnu/drivers/char/nwbutton.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/nwbutton.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/nwflash.c linux-libre-4.10-rc8-gnu/drivers/char/nwflash.c
--- linux-libre-4.9-gnu/drivers/char/nwflash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/nwflash.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <asm/hardware/dec21285.h>
 #include <asm/io.h>
 #include <asm/mach-types.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /*****************************************************************************/
 #include <asm/nwflash.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/pc8736x_gpio.c linux-libre-4.10-rc8-gnu/drivers/char/pc8736x_gpio.c
--- linux-libre-4.9-gnu/drivers/char/pc8736x_gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/pc8736x_gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/mutex.h>
 #include <linux/nsc_gpio.h>
 #include <linux/platform_device.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define DEVNAME "pc8736x_gpio"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/pcmcia/cm4000_cs.c linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/cm4000_cs.c
--- linux-libre-4.9-gnu/drivers/char/pcmcia/cm4000_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/cm4000_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
   * (C) 2000,2001,2002,2003,2004 Omnikey AG
   *
   * (C) 2005-2006 Harald Welte <laforge@gnumonks.org>
-  * 	- Adhere to Kernel CodingStyle
+  * 	- Adhere to Kernel process/coding-style.rst
   * 	- Port to 2.6.13 "new" style PCMCIA
   * 	- Check for copy_{from,to}_user return values
   * 	- Use nonseekable_open()
@@ -151,7 +151,7 @@ static struct pcmcia_device *dev_table[C
 static struct class *cmm_class;
 
 /* This table doesn't use spaces after the comma between fields and thus
- * violates CodingStyle.  However, I don't really think wrapping it around will
+ * violates process/coding-style.rst.  However, I don't really think wrapping it around will
  * make it any clearer to read -HW */
 static unsigned char fi_di_table[10][14] = {
 /*FI     00   01   02   03   04   05   06   07   08   09   10   11   12   13 */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/pcmcia/cm4040_cs.c linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/cm4040_cs.c
--- linux-libre-4.9-gnu/drivers/char/pcmcia/cm4040_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/cm4040_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/poll.h>
 #include <linux/mutex.h>
 #include <linux/wait.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #include <pcmcia/cistpl.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/pcmcia/Kconfig linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/Kconfig
--- linux-libre-4.9-gnu/drivers/char/pcmcia/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,17 @@ config CARDMAN_4040
 	  (http://www.omnikey.com/), or a current development version of OpenCT
 	  (http://www.opensc-project.org/opensc).
 
+config SCR24X
+	tristate "SCR24x Chip Card Interface support"
+	depends on PCMCIA
+	help
+	  Enable support for the SCR24x PCMCIA Chip Card Interface.
+
+	  To compile this driver as a module, choose M here.
+	  The module will be called scr24x_cs..
+
+	  If unsure say N.
+
 config IPWIRELESS
 	tristate "IPWireless 3G UMTS PCMCIA card support"
 	depends on PCMCIA && NETDEVICES && TTY
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/pcmcia/Makefile linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/Makefile
--- linux-libre-4.9-gnu/drivers/char/pcmcia/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -7,3 +7,4 @@
 obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o
 obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o
 obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o
+obj-$(CONFIG_SCR24X) += scr24x_cs.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/pcmcia/scr24x_cs.c linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/scr24x_cs.c
--- linux-libre-4.9-gnu/drivers/char/pcmcia/scr24x_cs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/scr24x_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,373 @@
+/*
+ * SCR24x PCMCIA Smart Card Reader Driver
+ *
+ * Copyright (C) 2005-2006 TL Sudheendran
+ * Copyright (C) 2016 Lubomir Rintel
+ *
+ * Derived from "scr24x_v4.2.6_Release.tar.gz" driver by TL Sudheendran.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#define CCID_HEADER_SIZE	10
+#define CCID_LENGTH_OFFSET	1
+#define CCID_MAX_LEN		271
+
+#define SCR24X_DATA(n)		(1 + n)
+#define SCR24X_CMD_STATUS	7
+#define CMD_START		0x40
+#define CMD_WRITE_BYTE		0x41
+#define CMD_READ_BYTE		0x42
+#define STATUS_BUSY		0x80
+
+struct scr24x_dev {
+	struct device *dev;
+	struct cdev c_dev;
+	unsigned char buf[CCID_MAX_LEN];
+	int devno;
+	struct mutex lock;
+	struct kref refcnt;
+	u8 __iomem *regs;
+};
+
+#define SCR24X_DEVS 8
+static DECLARE_BITMAP(scr24x_minors, SCR24X_DEVS);
+
+static struct class *scr24x_class;
+static dev_t scr24x_devt;
+
+static void scr24x_delete(struct kref *kref)
+{
+	struct scr24x_dev *dev = container_of(kref, struct scr24x_dev,
+								refcnt);
+
+	kfree(dev);
+}
+
+static int scr24x_wait_ready(struct scr24x_dev *dev)
+{
+	u_char status;
+	int timeout = 100;
+
+	do {
+		status = ioread8(dev->regs + SCR24X_CMD_STATUS);
+		if (!(status & STATUS_BUSY))
+			return 0;
+
+		msleep(20);
+	} while (--timeout);
+
+	return -EIO;
+}
+
+static int scr24x_open(struct inode *inode, struct file *filp)
+{
+	struct scr24x_dev *dev = container_of(inode->i_cdev,
+				struct scr24x_dev, c_dev);
+
+	kref_get(&dev->refcnt);
+	filp->private_data = dev;
+
+	return nonseekable_open(inode, filp);
+}
+
+static int scr24x_release(struct inode *inode, struct file *filp)
+{
+	struct scr24x_dev *dev = filp->private_data;
+
+	/* We must not take the dev->lock here as scr24x_delete()
+	 * might be called to remove the dev structure altogether.
+	 * We don't need the lock anyway, since after the reference
+	 * acquired in probe() is released in remove() the chrdev
+	 * is already unregistered and noone can possibly acquire
+	 * a reference via open() anymore. */
+	kref_put(&dev->refcnt, scr24x_delete);
+	return 0;
+}
+
+static int read_chunk(struct scr24x_dev *dev, size_t offset, size_t limit)
+{
+	size_t i, y;
+	int ret;
+
+	for (i = offset; i < limit; i += 5) {
+		iowrite8(CMD_READ_BYTE, dev->regs + SCR24X_CMD_STATUS);
+		ret = scr24x_wait_ready(dev);
+		if (ret < 0)
+			return ret;
+
+		for (y = 0; y < 5 && i + y < limit; y++)
+			dev->buf[i + y] = ioread8(dev->regs + SCR24X_DATA(y));
+	}
+
+	return 0;
+}
+
+static ssize_t scr24x_read(struct file *filp, char __user *buf, size_t count,
+								loff_t *ppos)
+{
+	struct scr24x_dev *dev = filp->private_data;
+	int ret;
+	int len;
+
+	if (count < CCID_HEADER_SIZE)
+		return -EINVAL;
+
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+
+	if (!dev->dev) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = scr24x_wait_ready(dev);
+	if (ret < 0)
+		goto out;
+	len = CCID_HEADER_SIZE;
+	ret = read_chunk(dev, 0, len);
+	if (ret < 0)
+		goto out;
+
+	len += le32_to_cpu(*(__le32 *)(&dev->buf[CCID_LENGTH_OFFSET]));
+	if (len > sizeof(dev->buf)) {
+		ret = -EIO;
+		goto out;
+	}
+	ret = read_chunk(dev, CCID_HEADER_SIZE, len);
+	if (ret < 0)
+		goto out;
+
+	if (len < count)
+		count = len;
+
+	if (copy_to_user(buf, dev->buf, count)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	ret = count;
+out:
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+static ssize_t scr24x_write(struct file *filp, const char __user *buf,
+					size_t count, loff_t *ppos)
+{
+	struct scr24x_dev *dev = filp->private_data;
+	size_t i, y;
+	int ret;
+
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+
+	if (!dev->dev) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (count > sizeof(dev->buf)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (copy_from_user(dev->buf, buf, count)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	ret = scr24x_wait_ready(dev);
+	if (ret < 0)
+		goto out;
+
+	iowrite8(CMD_START, dev->regs + SCR24X_CMD_STATUS);
+	ret = scr24x_wait_ready(dev);
+	if (ret < 0)
+		goto out;
+
+	for (i = 0; i < count; i += 5) {
+		for (y = 0; y < 5 && i + y < count; y++)
+			iowrite8(dev->buf[i + y], dev->regs + SCR24X_DATA(y));
+
+		iowrite8(CMD_WRITE_BYTE, dev->regs + SCR24X_CMD_STATUS);
+		ret = scr24x_wait_ready(dev);
+		if (ret < 0)
+			goto out;
+	}
+
+	ret = count;
+out:
+	mutex_unlock(&dev->lock);
+	return ret;
+}
+
+static const struct file_operations scr24x_fops = {
+	.owner		= THIS_MODULE,
+	.read		= scr24x_read,
+	.write		= scr24x_write,
+	.open		= scr24x_open,
+	.release	= scr24x_release,
+	.llseek		= no_llseek,
+};
+
+static int scr24x_config_check(struct pcmcia_device *link, void *priv_data)
+{
+	if (resource_size(link->resource[PCMCIA_IOPORT_0]) != 0x11)
+		return -ENODEV;
+	return pcmcia_request_io(link);
+}
+
+static int scr24x_probe(struct pcmcia_device *link)
+{
+	struct scr24x_dev *dev;
+	int ret;
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->devno = find_first_zero_bit(scr24x_minors, SCR24X_DEVS);
+	if (dev->devno >= SCR24X_DEVS) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	mutex_init(&dev->lock);
+	kref_init(&dev->refcnt);
+
+	link->priv = dev;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+	ret = pcmcia_loop_config(link, scr24x_config_check, NULL);
+	if (ret < 0)
+		goto err;
+
+	dev->dev = &link->dev;
+	dev->regs = devm_ioport_map(&link->dev,
+				link->resource[PCMCIA_IOPORT_0]->start,
+				resource_size(link->resource[PCMCIA_IOPORT_0]));
+	if (!dev->regs) {
+		ret = -EIO;
+		goto err;
+	}
+
+	cdev_init(&dev->c_dev, &scr24x_fops);
+	dev->c_dev.owner = THIS_MODULE;
+	dev->c_dev.ops = &scr24x_fops;
+	ret = cdev_add(&dev->c_dev, MKDEV(MAJOR(scr24x_devt), dev->devno), 1);
+	if (ret < 0)
+		goto err;
+
+	ret = pcmcia_enable_device(link);
+	if (ret < 0) {
+		pcmcia_disable_device(link);
+		goto err;
+	}
+
+	device_create(scr24x_class, NULL, MKDEV(MAJOR(scr24x_devt), dev->devno),
+		      NULL, "scr24x%d", dev->devno);
+
+	dev_info(&link->dev, "SCR24x Chip Card Interface\n");
+	return 0;
+
+err:
+	if (dev->devno < SCR24X_DEVS)
+		clear_bit(dev->devno, scr24x_minors);
+	kfree (dev);
+	return ret;
+}
+
+static void scr24x_remove(struct pcmcia_device *link)
+{
+	struct scr24x_dev *dev = (struct scr24x_dev *)link->priv;
+
+	device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno));
+	mutex_lock(&dev->lock);
+	pcmcia_disable_device(link);
+	cdev_del(&dev->c_dev);
+	clear_bit(dev->devno, scr24x_minors);
+	dev->dev = NULL;
+	mutex_unlock(&dev->lock);
+
+	kref_put(&dev->refcnt, scr24x_delete);
+}
+
+static const struct pcmcia_device_id scr24x_ids[] = {
+	PCMCIA_DEVICE_PROD_ID12("HP", "PC Card Smart Card Reader",
+					0x53cb94f9, 0xbfdf89a5),
+	PCMCIA_DEVICE_PROD_ID1("SCR241 PCMCIA", 0x6271efa3),
+	PCMCIA_DEVICE_PROD_ID1("SCR243 PCMCIA", 0x2054e8de),
+	PCMCIA_DEVICE_PROD_ID1("SCR24x PCMCIA", 0x54a33665),
+	PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, scr24x_ids);
+
+static struct pcmcia_driver scr24x_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "scr24x_cs",
+	.probe		= scr24x_probe,
+	.remove		= scr24x_remove,
+	.id_table	= scr24x_ids,
+};
+
+static int __init scr24x_init(void)
+{
+	int ret;
+
+	scr24x_class = class_create(THIS_MODULE, "scr24x");
+	if (IS_ERR(scr24x_class))
+		return PTR_ERR(scr24x_class);
+
+	ret = alloc_chrdev_region(&scr24x_devt, 0, SCR24X_DEVS, "scr24x");
+	if (ret < 0)  {
+		class_destroy(scr24x_class);
+		return ret;
+	}
+
+	ret = pcmcia_register_driver(&scr24x_driver);
+	if (ret < 0) {
+		unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
+		class_destroy(scr24x_class);
+	}
+
+	return ret;
+}
+
+static void __exit scr24x_exit(void)
+{
+	pcmcia_unregister_driver(&scr24x_driver);
+	unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
+	class_destroy(scr24x_class);
+}
+
+module_init(scr24x_init);
+module_exit(scr24x_exit);
+
+MODULE_AUTHOR("Lubomir Rintel");
+MODULE_DESCRIPTION("SCR24x PCMCIA Smart Card Reader Driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/pcmcia/synclink_cs.c linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/synclink_cs.c
--- linux-libre-4.9-gnu/drivers/char/pcmcia/synclink_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/pcmcia/synclink_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,7 @@
 #define PUT_USER(error,value,addr) error = put_user(value,addr)
 #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static MGSL_PARAMS default_params = {
 	MGSL_MODE_HDLC,			/* unsigned long mode */
@@ -4248,7 +4248,6 @@ static void hdlcdev_rx(MGSLPC_INFO *info
 static const struct net_device_ops hdlcdev_ops = {
 	.ndo_open       = hdlcdev_open,
 	.ndo_stop       = hdlcdev_close,
-	.ndo_change_mtu = hdlc_change_mtu,
 	.ndo_start_xmit = hdlc_start_xmit,
 	.ndo_do_ioctl   = hdlcdev_ioctl,
 	.ndo_tx_timeout = hdlcdev_tx_timeout,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/ppdev.c linux-libre-4.10-rc8-gnu/drivers/char/ppdev.c
--- linux-libre-4.9-gnu/drivers/char/ppdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/ppdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -86,6 +86,9 @@ struct pp_struct {
 	long default_inactivity;
 };
 
+/* should we use PARDEVICE_MAX here? */
+static struct device *devices[PARPORT_MAX];
+
 /* pp_struct.flags bitfields */
 #define PP_CLAIMED    (1<<0)
 #define PP_EXCL       (1<<1)
@@ -287,6 +290,7 @@ static int register_device(int minor, st
 	struct pardevice *pdev = NULL;
 	char *name;
 	struct pardev_cb ppdev_cb;
+	int rc = 0;
 
 	name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor);
 	if (name == NULL)
@@ -294,9 +298,9 @@ static int register_device(int minor, st
 
 	port = parport_find_number(minor);
 	if (!port) {
-		printk(KERN_WARNING "%s: no associated port!\n", name);
-		kfree(name);
-		return -ENXIO;
+		pr_warn("%s: no associated port!\n", name);
+		rc = -ENXIO;
+		goto err;
 	}
 
 	memset(&ppdev_cb, 0, sizeof(ppdev_cb));
@@ -307,14 +311,16 @@ static int register_device(int minor, st
 	parport_put_port(port);
 
 	if (!pdev) {
-		printk(KERN_WARNING "%s: failed to register device!\n", name);
-		kfree(name);
-		return -ENXIO;
+		pr_warn("%s: failed to register device!\n", name);
+		rc = -ENXIO;
+		goto err;
 	}
 
 	pp->pdev = pdev;
 	dev_dbg(&pdev->dev, "registered pardevice\n");
-	return 0;
+err:
+	kfree(name);
+	return rc;
 }
 
 static enum ieee1284_phase init_phase(int mode)
@@ -789,13 +795,29 @@ static const struct file_operations pp_f
 
 static void pp_attach(struct parport *port)
 {
-	device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number),
-		      NULL, "parport%d", port->number);
+	struct device *ret;
+
+	if (devices[port->number])
+		return;
+
+	ret = device_create(ppdev_class, port->dev,
+			    MKDEV(PP_MAJOR, port->number), NULL,
+			    "parport%d", port->number);
+	if (IS_ERR(ret)) {
+		pr_err("Failed to create device parport%d\n",
+		       port->number);
+		return;
+	}
+	devices[port->number] = ret;
 }
 
 static void pp_detach(struct parport *port)
 {
+	if (!devices[port->number])
+		return;
+
 	device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
+	devices[port->number] = NULL;
 }
 
 static int pp_probe(struct pardevice *par_dev)
@@ -822,8 +844,7 @@ static int __init ppdev_init(void)
 	int err = 0;
 
 	if (register_chrdev(PP_MAJOR, CHRDEV, &pp_fops)) {
-		printk(KERN_WARNING CHRDEV ": unable to get major %d\n",
-		       PP_MAJOR);
+		pr_warn(CHRDEV ": unable to get major %d\n", PP_MAJOR);
 		return -EIO;
 	}
 	ppdev_class = class_create(THIS_MODULE, CHRDEV);
@@ -833,11 +854,11 @@ static int __init ppdev_init(void)
 	}
 	err = parport_register_driver(&pp_driver);
 	if (err < 0) {
-		printk(KERN_WARNING CHRDEV ": unable to register with parport\n");
+		pr_warn(CHRDEV ": unable to register with parport\n");
 		goto out_class;
 	}
 
-	printk(KERN_INFO PP_VERSION "\n");
+	pr_info(PP_VERSION "\n");
 	goto out;
 
 out_class:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/random.c linux-libre-4.10-rc8-gnu/drivers/char/random.c
--- linux-libre-4.9-gnu/drivers/char/random.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/random.c	2017-02-12 16:03:20.000000000 -0500
@@ -265,7 +265,7 @@
 #include <crypto/chacha20.h>
 
 #include <asm/processor.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/io.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/raw.c linux-libre-4.10-rc8-gnu/drivers/char/raw.c
--- linux-libre-4.9-gnu/drivers/char/raw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/raw.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/compat.h>
 #include <linux/vmalloc.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 struct raw_device_data {
 	struct block_device *binding;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/scx200_gpio.c linux-libre-4.10-rc8-gnu/drivers/char/scx200_gpio.c
--- linux-libre-4.9-gnu/drivers/char/scx200_gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/scx200_gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/types.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/snsc.c linux-libre-4.10-rc8-gnu/drivers/char/snsc.c
--- linux-libre-4.9-gnu/drivers/char/snsc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/snsc.c	2017-02-12 16:03:20.000000000 -0500
@@ -285,7 +285,7 @@ scdrv_write(struct file *file, const cha
 		DECLARE_WAITQUEUE(wait, current);
 
 		if (file->f_flags & O_NONBLOCK) {
-			spin_unlock(&sd->sd_wlock);
+			spin_unlock_irqrestore(&sd->sd_wlock, flags);
 			up(&sd->sd_wbs);
 			return -EAGAIN;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/sonypi.c linux-libre-4.10-rc8-gnu/drivers/char/sonypi.c
--- linux-libre-4.9-gnu/drivers/char/sonypi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/sonypi.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@
 #include <linux/platform_device.h>
 #include <linux/gfp.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/sonypi.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tile-srom.c linux-libre-4.10-rc8-gnu/drivers/char/tile-srom.c
--- linux-libre-4.9-gnu/drivers/char/tile-srom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tile-srom.c	2017-02-12 16:03:20.000000000 -0500
@@ -312,7 +312,8 @@ ATTRIBUTE_GROUPS(srom_dev);
 
 static char *srom_devnode(struct device *dev, umode_t *mode)
 {
-	*mode = S_IRUGO | S_IWUSR;
+	if (mode)
+		*mode = 0644;
 	return kasprintf(GFP_KERNEL, "srom/%s", dev_name(dev));
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tlclk.c linux-libre-4.10-rc8-gnu/drivers/char/tlclk.c
--- linux-libre-4.9-gnu/drivers/char/tlclk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tlclk.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 #include <linux/miscdevice.h>
 #include <linux/platform_device.h>
 #include <asm/io.h>		/* inb/outb */
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 MODULE_AUTHOR("Sebastien Bouchard <sebastien.bouchard@ca.kontron.com>");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/toshiba.c linux-libre-4.10-rc8-gnu/drivers/char/toshiba.c
--- linux-libre-4.9-gnu/drivers/char/toshiba.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/toshiba.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,7 +63,7 @@
 #include <linux/miscdevice.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/init.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/Kconfig linux-libre-4.10-rc8-gnu/drivers/char/tpm/Kconfig
--- linux-libre-4.9-gnu/drivers/char/tpm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@ config TCG_TIS_CORE
 
 config TCG_TIS
 	tristate "TPM Interface Specification 1.2 Interface / TPM 2.0 FIFO Interface"
-	depends on X86
+	depends on X86 || OF
 	select TCG_TIS_CORE
 	---help---
 	  If you have a TPM security chip that is compliant with the
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/Makefile linux-libre-4.10-rc8-gnu/drivers/char/tpm/Makefile
--- linux-libre-4.9-gnu/drivers/char/tpm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,16 +2,10 @@
 # Makefile for the kernel tpm device drivers.
 #
 obj-$(CONFIG_TCG_TPM) += tpm.o
-tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o
-tpm-$(CONFIG_ACPI) += tpm_ppi.o
-
-ifdef CONFIG_ACPI
-	tpm-y += tpm_eventlog.o tpm_acpi.o
-else
-ifdef CONFIG_TCG_IBMVTPM
-	tpm-y += tpm_eventlog.o tpm_of.o
-endif
-endif
+tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
+		tpm_eventlog.o
+tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
+tpm-$(CONFIG_OF) += tpm_of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
 obj-$(CONFIG_TCG_TIS) += tpm_tis.o
 obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm2-cmd.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm2-cmd.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm2-cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm2-cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -680,7 +680,7 @@ static int tpm2_unseal_cmd(struct tpm_ch
 }
 
 /**
- * tpm_unseal_trusted() - unseal the payload of a trusted key
+ * tpm2_unseal_trusted() - unseal the payload of a trusted key
  * @chip_num: TPM chip to use
  * @payload: the key data in clear and encrypted form
  * @options: authentication values and other options
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_acpi.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_acpi.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_acpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_acpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,10 +6,11 @@
  *	Stefan Berger <stefanb@us.ibm.com>
  *	Reiner Sailer <sailer@watson.ibm.com>
  *	Kylene Hall <kjhall@us.ibm.com>
+ *	Nayna Jain <nayna@linux.vnet.ibm.com>
  *
  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
  *
- * Access to the eventlog extended by the TCG BIOS of PC platform
+ * Access to the event log extended by the TCG BIOS of PC platform
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -45,29 +46,28 @@ struct acpi_tcpa {
 };
 
 /* read binary bios log */
-int read_log(struct tpm_bios_log *log)
+int tpm_read_log_acpi(struct tpm_chip *chip)
 {
 	struct acpi_tcpa *buff;
 	acpi_status status;
 	void __iomem *virt;
 	u64 len, start;
+	struct tpm_bios_log *log;
 
-	if (log->bios_event_log != NULL) {
-		printk(KERN_ERR
-		       "%s: ERROR - Eventlog already initialized\n",
-		       __func__);
-		return -EFAULT;
-	}
+	log = &chip->log;
+
+	/* Unfortuntely ACPI does not associate the event log with a specific
+	 * TPM, like PPI. Thus all ACPI TPMs will read the same log.
+	 */
+	if (!chip->acpi_dev_handle)
+		return -ENODEV;
 
 	/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
 	status = acpi_get_table(ACPI_SIG_TCPA, 1,
 				(struct acpi_table_header **)&buff);
 
-	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n",
-		       __func__);
-		return -EIO;
-	}
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
 
 	switch(buff->platform_class) {
 	case BIOS_SERVER:
@@ -81,29 +81,29 @@ int read_log(struct tpm_bios_log *log)
 		break;
 	}
 	if (!len) {
-		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+		dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
 		return -EIO;
 	}
 
 	/* malloc EventLog space */
 	log->bios_event_log = kmalloc(len, GFP_KERNEL);
-	if (!log->bios_event_log) {
-		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
-			__func__);
+	if (!log->bios_event_log)
 		return -ENOMEM;
-	}
 
 	log->bios_event_log_end = log->bios_event_log + len;
 
 	virt = acpi_os_map_iomem(start, len);
-	if (!virt) {
-		kfree(log->bios_event_log);
-		printk("%s: ERROR - Unable to map memory\n", __func__);
-		return -EIO;
-	}
+	if (!virt)
+		goto err;
 
 	memcpy_fromio(log->bios_event_log, virt, len);
 
 	acpi_os_unmap_iomem(virt, len);
 	return 0;
+
+err:
+	kfree(log->bios_event_log);
+	log->bios_event_log = NULL;
+	return -EIO;
+
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm-chip.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm-chip.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm-chip.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm-chip.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,7 @@ EXPORT_SYMBOL_GPL(tpm_put_ops);
  *
  * The return'd chip has been tpm_try_get_ops'd and must be released via
  * tpm_put_ops
-  */
+ */
 struct tpm_chip *tpm_chip_find_get(int chip_num)
 {
 	struct tpm_chip *chip, *res = NULL;
@@ -103,7 +103,7 @@ struct tpm_chip *tpm_chip_find_get(int c
 			}
 		} while (chip_prev != chip_num);
 	} else {
-		chip = idr_find_slowpath(&dev_nums_idr, chip_num);
+		chip = idr_find(&dev_nums_idr, chip_num);
 		if (chip && !tpm_try_get_ops(chip))
 			res = chip;
 	}
@@ -127,6 +127,7 @@ static void tpm_dev_release(struct devic
 	idr_remove(&dev_nums_idr, chip->dev_num);
 	mutex_unlock(&idr_lock);
 
+	kfree(chip->log.bios_event_log);
 	kfree(chip);
 }
 
@@ -276,27 +277,6 @@ static void tpm_del_char_device(struct t
 	up_write(&chip->ops_sem);
 }
 
-static int tpm1_chip_register(struct tpm_chip *chip)
-{
-	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		return 0;
-
-	tpm_sysfs_add_device(chip);
-
-	chip->bios_dir = tpm_bios_log_setup(dev_name(&chip->dev));
-
-	return 0;
-}
-
-static void tpm1_chip_unregister(struct tpm_chip *chip)
-{
-	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		return;
-
-	if (chip->bios_dir)
-		tpm_bios_log_teardown(chip->bios_dir);
-}
-
 static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
 {
 	struct attribute **i;
@@ -363,20 +343,20 @@ int tpm_chip_register(struct tpm_chip *c
 			return rc;
 	}
 
-	rc = tpm1_chip_register(chip);
-	if (rc)
+	tpm_sysfs_add_device(chip);
+
+	rc = tpm_bios_log_setup(chip);
+	if (rc != 0 && rc != -ENODEV)
 		return rc;
 
 	tpm_add_ppi(chip);
 
 	rc = tpm_add_char_device(chip);
 	if (rc) {
-		tpm1_chip_unregister(chip);
+		tpm_bios_log_teardown(chip);
 		return rc;
 	}
 
-	chip->flags |= TPM_CHIP_FLAG_REGISTERED;
-
 	rc = tpm_add_legacy_sysfs(chip);
 	if (rc) {
 		tpm_chip_unregister(chip);
@@ -402,12 +382,8 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
  */
 void tpm_chip_unregister(struct tpm_chip *chip)
 {
-	if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
-		return;
-
 	tpm_del_legacy_sysfs(chip);
-
-	tpm1_chip_unregister(chip);
+	tpm_bios_log_teardown(chip);
 	tpm_del_char_device(chip);
 }
 EXPORT_SYMBOL_GPL(tpm_chip_unregister);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_crb.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_crb.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_crb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_crb.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/highmem.h>
 #include <linux/rculist.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include "tpm.h"
 
 #define ACPI_SIG_TPM2 "TPM2"
@@ -83,7 +84,71 @@ struct crb_priv {
 	u32 cmd_size;
 };
 
-static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
+/**
+ * crb_go_idle - request tpm crb device to go the idle state
+ *
+ * @dev:  crb device
+ * @priv: crb private data
+ *
+ * Write CRB_CTRL_REQ_GO_IDLE to TPM_CRB_CTRL_REQ
+ * The device should respond within TIMEOUT_C by clearing the bit.
+ * Anyhow, we do not wait here as a consequent CMD_READY request
+ * will be handled correctly even if idle was not completed.
+ *
+ * The function does nothing for devices with ACPI-start method.
+ *
+ * Return: 0 always
+ */
+static int __maybe_unused crb_go_idle(struct device *dev, struct crb_priv *priv)
+{
+	if (priv->flags & CRB_FL_ACPI_START)
+		return 0;
+
+	iowrite32(CRB_CTRL_REQ_GO_IDLE, &priv->cca->req);
+	/* we don't really care when this settles */
+
+	return 0;
+}
+
+/**
+ * crb_cmd_ready - request tpm crb device to enter ready state
+ *
+ * @dev:  crb device
+ * @priv: crb private data
+ *
+ * Write CRB_CTRL_REQ_CMD_READY to TPM_CRB_CTRL_REQ
+ * and poll till the device acknowledge it by clearing the bit.
+ * The device should respond within TIMEOUT_C.
+ *
+ * The function does nothing for devices with ACPI-start method
+ *
+ * Return: 0 on success -ETIME on timeout;
+ */
+static int __maybe_unused crb_cmd_ready(struct device *dev,
+					struct crb_priv *priv)
+{
+	ktime_t stop, start;
+
+	if (priv->flags & CRB_FL_ACPI_START)
+		return 0;
+
+	iowrite32(CRB_CTRL_REQ_CMD_READY, &priv->cca->req);
+
+	start = ktime_get();
+	stop = ktime_add(start, ms_to_ktime(TPM2_TIMEOUT_C));
+	do {
+		if (!(ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY))
+			return 0;
+		usleep_range(50, 100);
+	} while (ktime_before(ktime_get(), stop));
+
+	if (ioread32(&priv->cca->req) & CRB_CTRL_REQ_CMD_READY) {
+		dev_warn(dev, "cmdReady timed out\n");
+		return -ETIME;
+	}
+
+	return 0;
+}
 
 static u8 crb_status(struct tpm_chip *chip)
 {
@@ -196,21 +261,6 @@ static const struct tpm_class_ops tpm_cr
 	.req_complete_val = CRB_DRV_STS_COMPLETE,
 };
 
-static int crb_init(struct acpi_device *device, struct crb_priv *priv)
-{
-	struct tpm_chip *chip;
-
-	chip = tpmm_chip_alloc(&device->dev, &tpm_crb);
-	if (IS_ERR(chip))
-		return PTR_ERR(chip);
-
-	dev_set_drvdata(&chip->dev, priv);
-	chip->acpi_dev_handle = device->handle;
-	chip->flags = TPM_CHIP_FLAG_TPM2;
-
-	return tpm_chip_register(chip);
-}
-
 static int crb_check_resource(struct acpi_resource *ares, void *data)
 {
 	struct resource *io_res = data;
@@ -249,6 +299,7 @@ static int crb_map_io(struct acpi_device
 	struct list_head resources;
 	struct resource io_res;
 	struct device *dev = &device->dev;
+	u32 pa_high, pa_low;
 	u64 cmd_pa;
 	u32 cmd_size;
 	u64 rsp_pa;
@@ -276,12 +327,27 @@ static int crb_map_io(struct acpi_device
 	if (IS_ERR(priv->cca))
 		return PTR_ERR(priv->cca);
 
-	cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
-		  (u64) ioread32(&priv->cca->cmd_pa_low);
+	/*
+	 * PTT HW bug w/a: wake up the device to access
+	 * possibly not retained registers.
+	 */
+	ret = crb_cmd_ready(dev, priv);
+	if (ret)
+		return ret;
+
+	pa_high = ioread32(&priv->cca->cmd_pa_high);
+	pa_low  = ioread32(&priv->cca->cmd_pa_low);
+	cmd_pa = ((u64)pa_high << 32) | pa_low;
 	cmd_size = ioread32(&priv->cca->cmd_size);
+
+	dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n",
+		pa_high, pa_low, cmd_size);
+
 	priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size);
-	if (IS_ERR(priv->cmd))
-		return PTR_ERR(priv->cmd);
+	if (IS_ERR(priv->cmd)) {
+		ret = PTR_ERR(priv->cmd);
+		goto out;
+	}
 
 	memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
 	rsp_pa = le64_to_cpu(rsp_pa);
@@ -289,7 +355,8 @@ static int crb_map_io(struct acpi_device
 
 	if (cmd_pa != rsp_pa) {
 		priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
-		return PTR_ERR_OR_ZERO(priv->rsp);
+		ret = PTR_ERR_OR_ZERO(priv->rsp);
+		goto out;
 	}
 
 	/* According to the PTP specification, overlapping command and response
@@ -297,18 +364,25 @@ static int crb_map_io(struct acpi_device
 	 */
 	if (cmd_size != rsp_size) {
 		dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out;
 	}
+
 	priv->cmd_size = cmd_size;
 
 	priv->rsp = priv->cmd;
-	return 0;
+
+out:
+	crb_go_idle(dev, priv);
+
+	return ret;
 }
 
 static int crb_acpi_add(struct acpi_device *device)
 {
 	struct acpi_table_tpm2 *buf;
 	struct crb_priv *priv;
+	struct tpm_chip *chip;
 	struct device *dev = &device->dev;
 	acpi_status status;
 	u32 sm;
@@ -346,7 +420,33 @@ static int crb_acpi_add(struct acpi_devi
 	if (rc)
 		return rc;
 
-	return crb_init(device, priv);
+	chip = tpmm_chip_alloc(dev, &tpm_crb);
+	if (IS_ERR(chip))
+		return PTR_ERR(chip);
+
+	dev_set_drvdata(&chip->dev, priv);
+	chip->acpi_dev_handle = device->handle;
+	chip->flags = TPM_CHIP_FLAG_TPM2;
+
+	rc  = crb_cmd_ready(dev, priv);
+	if (rc)
+		return rc;
+
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	rc = tpm_chip_register(chip);
+	if (rc) {
+		crb_go_idle(dev, priv);
+		pm_runtime_put_noidle(dev);
+		pm_runtime_disable(dev);
+		return rc;
+	}
+
+	pm_runtime_put(dev);
+
+	return 0;
 }
 
 static int crb_acpi_remove(struct acpi_device *device)
@@ -356,9 +456,34 @@ static int crb_acpi_remove(struct acpi_d
 
 	tpm_chip_unregister(chip);
 
+	pm_runtime_disable(dev);
+
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int crb_pm_runtime_suspend(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct crb_priv *priv = dev_get_drvdata(&chip->dev);
+
+	return crb_go_idle(dev, priv);
+}
+
+static int crb_pm_runtime_resume(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct crb_priv *priv = dev_get_drvdata(&chip->dev);
+
+	return crb_cmd_ready(dev, priv);
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops crb_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(tpm_pm_suspend, tpm_pm_resume)
+	SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL)
+};
+
 static struct acpi_device_id crb_device_ids[] = {
 	{"MSFT0101", 0},
 	{"", 0},
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_eventlog.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_eventlog.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_eventlog.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_eventlog.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,10 +7,11 @@
  *	Stefan Berger <stefanb@us.ibm.com>
  *	Reiner Sailer <sailer@watson.ibm.com>
  *	Kylene Hall <kjhall@us.ibm.com>
+ *	Nayna Jain <nayna@linux.vnet.ibm.com>
  *
  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
  *
- * Access to the eventlog created by a system's firmware / BIOS
+ * Access to the event log created by a system's firmware / BIOS
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -72,7 +73,8 @@ static const char* tcpa_pc_event_id_stri
 static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
 {
 	loff_t i;
-	struct tpm_bios_log *log = m->private;
+	struct tpm_chip *chip = m->private;
+	struct tpm_bios_log *log = &chip->log;
 	void *addr = log->bios_event_log;
 	void *limit = log->bios_event_log_end;
 	struct tcpa_event *event;
@@ -119,7 +121,8 @@ static void *tpm_bios_measurements_next(
 					loff_t *pos)
 {
 	struct tcpa_event *event = v;
-	struct tpm_bios_log *log = m->private;
+	struct tpm_chip *chip = m->private;
+	struct tpm_bios_log *log = &chip->log;
 	void *limit = log->bios_event_log_end;
 	u32 converted_event_size;
 	u32 converted_event_type;
@@ -260,13 +263,10 @@ static int tpm_binary_bios_measurements_
 static int tpm_bios_measurements_release(struct inode *inode,
 					 struct file *file)
 {
-	struct seq_file *seq = file->private_data;
-	struct tpm_bios_log *log = seq->private;
+	struct seq_file *seq = (struct seq_file *)file->private_data;
+	struct tpm_chip *chip = (struct tpm_chip *)seq->private;
 
-	if (log) {
-		kfree(log->bios_event_log);
-		kfree(log);
-	}
+	put_device(&chip->dev);
 
 	return seq_release(inode, file);
 }
@@ -304,151 +304,159 @@ static int tpm_ascii_bios_measurements_s
 	return 0;
 }
 
-static const struct seq_operations tpm_ascii_b_measurments_seqops = {
+static const struct seq_operations tpm_ascii_b_measurements_seqops = {
 	.start = tpm_bios_measurements_start,
 	.next = tpm_bios_measurements_next,
 	.stop = tpm_bios_measurements_stop,
 	.show = tpm_ascii_bios_measurements_show,
 };
 
-static const struct seq_operations tpm_binary_b_measurments_seqops = {
+static const struct seq_operations tpm_binary_b_measurements_seqops = {
 	.start = tpm_bios_measurements_start,
 	.next = tpm_bios_measurements_next,
 	.stop = tpm_bios_measurements_stop,
 	.show = tpm_binary_bios_measurements_show,
 };
 
-static int tpm_ascii_bios_measurements_open(struct inode *inode,
+static int tpm_bios_measurements_open(struct inode *inode,
 					    struct file *file)
 {
 	int err;
-	struct tpm_bios_log *log;
 	struct seq_file *seq;
+	struct tpm_chip_seqops *chip_seqops;
+	const struct seq_operations *seqops;
+	struct tpm_chip *chip;
 
-	log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
-	if (!log)
-		return -ENOMEM;
-
-	if ((err = read_log(log)))
-		goto out_free;
+	inode_lock(inode);
+	if (!inode->i_private) {
+		inode_unlock(inode);
+		return -ENODEV;
+	}
+	chip_seqops = (struct tpm_chip_seqops *)inode->i_private;
+	seqops = chip_seqops->seqops;
+	chip = chip_seqops->chip;
+	get_device(&chip->dev);
+	inode_unlock(inode);
 
 	/* now register seq file */
-	err = seq_open(file, &tpm_ascii_b_measurments_seqops);
+	err = seq_open(file, seqops);
 	if (!err) {
 		seq = file->private_data;
-		seq->private = log;
-	} else {
-		goto out_free;
+		seq->private = chip;
 	}
 
-out:
 	return err;
-out_free:
-	kfree(log->bios_event_log);
-	kfree(log);
-	goto out;
 }
 
-static const struct file_operations tpm_ascii_bios_measurements_ops = {
-	.open = tpm_ascii_bios_measurements_open,
+static const struct file_operations tpm_bios_measurements_ops = {
+	.owner = THIS_MODULE,
+	.open = tpm_bios_measurements_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = tpm_bios_measurements_release,
 };
 
-static int tpm_binary_bios_measurements_open(struct inode *inode,
-					     struct file *file)
+static int tpm_read_log(struct tpm_chip *chip)
 {
-	int err;
-	struct tpm_bios_log *log;
-	struct seq_file *seq;
-
-	log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
-	if (!log)
-		return -ENOMEM;
-
-	if ((err = read_log(log)))
-		goto out_free;
+	int rc;
 
-	/* now register seq file */
-	err = seq_open(file, &tpm_binary_b_measurments_seqops);
-	if (!err) {
-		seq = file->private_data;
-		seq->private = log;
-	} else {
-		goto out_free;
+	if (chip->log.bios_event_log != NULL) {
+		dev_dbg(&chip->dev,
+			"%s: ERROR - event log already initialized\n",
+			__func__);
+		return -EFAULT;
 	}
 
-out:
-	return err;
-out_free:
-	kfree(log->bios_event_log);
-	kfree(log);
-	goto out;
-}
-
-static const struct file_operations tpm_binary_bios_measurements_ops = {
-	.open = tpm_binary_bios_measurements_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = tpm_bios_measurements_release,
-};
+	rc = tpm_read_log_acpi(chip);
+	if (rc != -ENODEV)
+		return rc;
 
-static int is_bad(void *p)
-{
-	if (!p)
-		return 1;
-	if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV))
-		return 1;
-	return 0;
+	return tpm_read_log_of(chip);
 }
 
-struct dentry **tpm_bios_log_setup(const char *name)
+/*
+ * tpm_bios_log_setup() - Read the event log from the firmware
+ * @chip: TPM chip to use.
+ *
+ * If an event log is found then the securityfs files are setup to
+ * export it to userspace, otherwise nothing is done.
+ *
+ * Returns -ENODEV if the firmware has no event log or securityfs is not
+ * supported.
+ */
+int tpm_bios_log_setup(struct tpm_chip *chip)
 {
-	struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
+	const char *name = dev_name(&chip->dev);
+	unsigned int cnt;
+	int rc = 0;
 
-	tpm_dir = securityfs_create_dir(name, NULL);
-	if (is_bad(tpm_dir))
-		goto out;
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		return 0;
 
-	bin_file =
-	    securityfs_create_file("binary_bios_measurements",
-				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
-				   &tpm_binary_bios_measurements_ops);
-	if (is_bad(bin_file))
-		goto out_tpm;
+	rc = tpm_read_log(chip);
+	if (rc)
+		return rc;
 
-	ascii_file =
-	    securityfs_create_file("ascii_bios_measurements",
-				   S_IRUSR | S_IRGRP, tpm_dir, NULL,
-				   &tpm_ascii_bios_measurements_ops);
-	if (is_bad(ascii_file))
-		goto out_bin;
+	cnt = 0;
+	chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
+	/* NOTE: securityfs_create_dir can return ENODEV if securityfs is
+	 * compiled out. The caller should ignore the ENODEV return code.
+	 */
+	if (IS_ERR(chip->bios_dir[cnt]))
+		goto err;
+	cnt++;
 
-	ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL);
-	if (!ret)
-		goto out_ascii;
+	chip->bin_log_seqops.chip = chip;
+	chip->bin_log_seqops.seqops = &tpm_binary_b_measurements_seqops;
 
-	ret[0] = ascii_file;
-	ret[1] = bin_file;
-	ret[2] = tpm_dir;
+	chip->bios_dir[cnt] =
+	    securityfs_create_file("binary_bios_measurements",
+				   0440, chip->bios_dir[0],
+				   (void *)&chip->bin_log_seqops,
+				   &tpm_bios_measurements_ops);
+	if (IS_ERR(chip->bios_dir[cnt]))
+		goto err;
+	cnt++;
 
-	return ret;
+	chip->ascii_log_seqops.chip = chip;
+	chip->ascii_log_seqops.seqops = &tpm_ascii_b_measurements_seqops;
 
-out_ascii:
-	securityfs_remove(ascii_file);
-out_bin:
-	securityfs_remove(bin_file);
-out_tpm:
-	securityfs_remove(tpm_dir);
-out:
-	return NULL;
+	chip->bios_dir[cnt] =
+	    securityfs_create_file("ascii_bios_measurements",
+				   0440, chip->bios_dir[0],
+				   (void *)&chip->ascii_log_seqops,
+				   &tpm_bios_measurements_ops);
+	if (IS_ERR(chip->bios_dir[cnt]))
+		goto err;
+	cnt++;
+
+	return 0;
+
+err:
+	rc = PTR_ERR(chip->bios_dir[cnt]);
+	chip->bios_dir[cnt] = NULL;
+	tpm_bios_log_teardown(chip);
+	return rc;
 }
 
-void tpm_bios_log_teardown(struct dentry **lst)
+void tpm_bios_log_teardown(struct tpm_chip *chip)
 {
 	int i;
+	struct inode *inode;
 
-	for (i = 0; i < 3; i++)
-		securityfs_remove(lst[i]);
+	/* securityfs_remove currently doesn't take care of handling sync
+	 * between removal and opening of pseudo files. To handle this, a
+	 * workaround is added by making i_private = NULL here during removal
+	 * and to check it during open(), both within inode_lock()/unlock().
+	 * This design ensures that open() either safely gets kref or fails.
+	 */
+	for (i = (TPM_NUM_EVENT_LOG_FILES - 1); i >= 0; i--) {
+		if (chip->bios_dir[i]) {
+			inode = d_inode(chip->bios_dir[i]);
+			inode_lock(inode);
+			inode->i_private = NULL;
+			inode_unlock(inode);
+			securityfs_remove(chip->bios_dir[i]);
+		}
+	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_eventlog.h linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_eventlog.h
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_eventlog.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_eventlog.h	2017-02-12 16:03:20.000000000 -0500
@@ -73,20 +73,24 @@ enum tcpa_pc_event_ids {
 	HOST_TABLE_OF_DEVICES,
 };
 
-int read_log(struct tpm_bios_log *log);
-
-#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
-	defined(CONFIG_ACPI)
-extern struct dentry **tpm_bios_log_setup(const char *);
-extern void tpm_bios_log_teardown(struct dentry **);
+#if defined(CONFIG_ACPI)
+int tpm_read_log_acpi(struct tpm_chip *chip);
 #else
-static inline struct dentry **tpm_bios_log_setup(const char *name)
+static inline int tpm_read_log_acpi(struct tpm_chip *chip)
 {
-	return NULL;
+	return -ENODEV;
 }
-static inline void tpm_bios_log_teardown(struct dentry **dir)
+#endif
+#if defined(CONFIG_OF)
+int tpm_read_log_of(struct tpm_chip *chip);
+#else
+static inline int tpm_read_log_of(struct tpm_chip *chip)
 {
+	return -ENODEV;
 }
 #endif
 
+int tpm_bios_log_setup(struct tpm_chip *chip);
+void tpm_bios_log_teardown(struct tpm_chip *chip);
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm.h linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm.h
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,11 +35,14 @@
 #include <linux/cdev.h>
 #include <linux/highmem.h>
 
+#include "tpm_eventlog.h"
+
 enum tpm_const {
 	TPM_MINOR = 224,	/* officially assigned */
 	TPM_BUFSIZE = 4096,
 	TPM_NUM_DEVICES = 65536,
 	TPM_RETRY = 50,		/* 5 seconds */
+	TPM_NUM_EVENT_LOG_FILES = 3,
 };
 
 enum tpm_timeout {
@@ -139,10 +142,15 @@ enum tpm2_startup_types {
 #define TPM_PPI_VERSION_LEN		3
 
 enum tpm_chip_flags {
-	TPM_CHIP_FLAG_REGISTERED	= BIT(0),
 	TPM_CHIP_FLAG_TPM2		= BIT(1),
 	TPM_CHIP_FLAG_IRQ		= BIT(2),
 	TPM_CHIP_FLAG_VIRTUAL		= BIT(3),
+	TPM_CHIP_FLAG_HAVE_TIMEOUTS	= BIT(4),
+};
+
+struct tpm_chip_seqops {
+	struct tpm_chip *chip;
+	const struct seq_operations *seqops;
 };
 
 struct tpm_chip {
@@ -156,6 +164,10 @@ struct tpm_chip {
 	struct rw_semaphore ops_sem;
 	const struct tpm_class_ops *ops;
 
+	struct tpm_bios_log log;
+	struct tpm_chip_seqops bin_log_seqops;
+	struct tpm_chip_seqops ascii_log_seqops;
+
 	unsigned int flags;
 
 	int dev_num;		/* /dev/tpm# */
@@ -171,7 +183,7 @@ struct tpm_chip {
 	unsigned long duration[3]; /* jiffies */
 	bool duration_adjusted;
 
-	struct dentry **bios_dir;
+	struct dentry *bios_dir[TPM_NUM_EVENT_LOG_FILES];
 
 	const struct attribute_group *groups[3];
 	unsigned int groups_cnt;
@@ -282,21 +294,20 @@ typedef union {
 } cap_t;
 
 enum tpm_capabilities {
-	TPM_CAP_FLAG = cpu_to_be32(4),
-	TPM_CAP_PROP = cpu_to_be32(5),
-	CAP_VERSION_1_1 = cpu_to_be32(0x06),
-	CAP_VERSION_1_2 = cpu_to_be32(0x1A)
+	TPM_CAP_FLAG = 4,
+	TPM_CAP_PROP = 5,
+	TPM_CAP_VERSION_1_1 = 0x06,
+	TPM_CAP_VERSION_1_2 = 0x1A,
 };
 
 enum tpm_sub_capabilities {
-	TPM_CAP_PROP_PCR = cpu_to_be32(0x101),
-	TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103),
-	TPM_CAP_FLAG_PERM = cpu_to_be32(0x108),
-	TPM_CAP_FLAG_VOL = cpu_to_be32(0x109),
-	TPM_CAP_PROP_OWNER = cpu_to_be32(0x111),
-	TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115),
-	TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120),
-
+	TPM_CAP_PROP_PCR = 0x101,
+	TPM_CAP_PROP_MANUFACTURER = 0x103,
+	TPM_CAP_FLAG_PERM = 0x108,
+	TPM_CAP_FLAG_VOL = 0x109,
+	TPM_CAP_PROP_OWNER = 0x111,
+	TPM_CAP_PROP_TIS_TIMEOUT = 0x115,
+	TPM_CAP_PROP_TIS_DURATION = 0x120,
 };
 
 struct	tpm_getcap_params_in {
@@ -484,7 +495,7 @@ ssize_t tpm_transmit(struct tpm_chip *ch
 		     unsigned int flags);
 ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len,
 			 unsigned int flags, const char *desc);
-ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap,
+ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
 		   const char *desc);
 int tpm_get_timeouts(struct tpm_chip *);
 int tpm1_auto_startup(struct tpm_chip *chip);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm-interface.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm-interface.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm-interface.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm-interface.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/freezer.h>
+#include <linux/pm_runtime.h>
 
 #include "tpm.h"
 #include "tpm_eventlog.h"
@@ -356,6 +357,9 @@ ssize_t tpm_transmit(struct tpm_chip *ch
 	if (!(flags & TPM_TRANSMIT_UNLOCKED))
 		mutex_lock(&chip->tpm_mutex);
 
+	if (chip->dev.parent)
+		pm_runtime_get_sync(chip->dev.parent);
+
 	rc = chip->ops->send(chip, (u8 *) buf, count);
 	if (rc < 0) {
 		dev_err(&chip->dev,
@@ -397,6 +401,9 @@ out_recv:
 		dev_err(&chip->dev,
 			"tpm_transmit: tpm_recv: error %zd\n", rc);
 out:
+	if (chip->dev.parent)
+		pm_runtime_put_sync(chip->dev.parent);
+
 	if (!(flags & TPM_TRANSMIT_UNLOCKED))
 		mutex_unlock(&chip->tpm_mutex);
 	return rc;
@@ -437,26 +444,29 @@ static const struct tpm_input_header tpm
 	.ordinal = TPM_ORD_GET_CAP
 };
 
-ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap,
+ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
 		   const char *desc)
 {
 	struct tpm_cmd_t tpm_cmd;
 	int rc;
 
 	tpm_cmd.header.in = tpm_getcap_header;
-	if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
-		tpm_cmd.params.getcap_in.cap = subcap_id;
+	if (subcap_id == TPM_CAP_VERSION_1_1 ||
+	    subcap_id == TPM_CAP_VERSION_1_2) {
+		tpm_cmd.params.getcap_in.cap = cpu_to_be32(subcap_id);
 		/*subcap field not necessary */
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0);
 		tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32));
 	} else {
 		if (subcap_id == TPM_CAP_FLAG_PERM ||
 		    subcap_id == TPM_CAP_FLAG_VOL)
-			tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG;
+			tpm_cmd.params.getcap_in.cap =
+				cpu_to_be32(TPM_CAP_FLAG);
 		else
-			tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
+			tpm_cmd.params.getcap_in.cap =
+				cpu_to_be32(TPM_CAP_PROP);
 		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
-		tpm_cmd.params.getcap_in.subcap = subcap_id;
+		tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id);
 	}
 	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
 			      desc);
@@ -488,12 +498,14 @@ static int tpm_startup(struct tpm_chip *
 
 int tpm_get_timeouts(struct tpm_chip *chip)
 {
-	struct tpm_cmd_t tpm_cmd;
+	cap_t cap;
 	unsigned long new_timeout[4];
 	unsigned long old_timeout[4];
-	struct duration_t *duration_cap;
 	ssize_t rc;
 
+	if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
+		return 0;
+
 	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
 		/* Fixed timeouts for TPM2 */
 		chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
@@ -506,46 +518,30 @@ int tpm_get_timeouts(struct tpm_chip *ch
 		    msecs_to_jiffies(TPM2_DURATION_MEDIUM);
 		chip->duration[TPM_LONG] =
 		    msecs_to_jiffies(TPM2_DURATION_LONG);
+
+		chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
 		return 0;
 	}
 
-	tpm_cmd.header.in = tpm_getcap_header;
-	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
-	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
-	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
-			      NULL);
-
+	rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
+			"attempting to determine the timeouts");
 	if (rc == TPM_ERR_INVALID_POSTINIT) {
 		/* The TPM is not started, we are the first to talk to it.
 		   Execute a startup command. */
-		dev_info(&chip->dev, "Issuing TPM_STARTUP");
+		dev_info(&chip->dev, "Issuing TPM_STARTUP\n");
 		if (tpm_startup(chip, TPM_ST_CLEAR))
 			return rc;
 
-		tpm_cmd.header.in = tpm_getcap_header;
-		tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
-		tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
-		tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT;
-		rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
-				      0, NULL);
-	}
-	if (rc) {
-		dev_err(&chip->dev,
-			"A TPM error (%zd) occurred attempting to determine the timeouts\n",
-			rc);
-		goto duration;
+		rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
+				"attempting to determine the timeouts");
 	}
+	if (rc)
+		return rc;
 
-	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
-	    be32_to_cpu(tpm_cmd.header.out.length)
-	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
-		return -EINVAL;
-
-	old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a);
-	old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b);
-	old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c);
-	old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d);
+	old_timeout[0] = be32_to_cpu(cap.timeout.a);
+	old_timeout[1] = be32_to_cpu(cap.timeout.b);
+	old_timeout[2] = be32_to_cpu(cap.timeout.c);
+	old_timeout[3] = be32_to_cpu(cap.timeout.d);
 	memcpy(new_timeout, old_timeout, sizeof(new_timeout));
 
 	/*
@@ -583,29 +579,17 @@ int tpm_get_timeouts(struct tpm_chip *ch
 	chip->timeout_c = usecs_to_jiffies(new_timeout[2]);
 	chip->timeout_d = usecs_to_jiffies(new_timeout[3]);
 
-duration:
-	tpm_cmd.header.in = tpm_getcap_header;
-	tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP;
-	tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
-	tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION;
-
-	rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
-			      "attempting to determine the durations");
+	rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap,
+			"attempting to determine the durations");
 	if (rc)
 		return rc;
 
-	if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
-	    be32_to_cpu(tpm_cmd.header.out.length)
-	    != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
-		return -EINVAL;
-
-	duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
 	chip->duration[TPM_SHORT] =
-	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
+		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short));
 	chip->duration[TPM_MEDIUM] =
-	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
+		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium));
 	chip->duration[TPM_LONG] =
-	    usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
+		usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long));
 
 	/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
 	 * value wrong and apparently reports msecs rather than usecs. So we
@@ -619,6 +603,8 @@ duration:
 		chip->duration_adjusted = true;
 		dev_info(&chip->dev, "Adjusting TPM timeout parameters.");
 	}
+
+	chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_get_timeouts);
@@ -726,6 +712,14 @@ int tpm_pcr_read(u32 chip_num, int pcr_i
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_read);
 
+#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
+#define EXTEND_PCR_RESULT_SIZE 34
+static const struct tpm_input_header pcrextend_header = {
+	.tag = TPM_TAG_RQU_COMMAND,
+	.length = cpu_to_be32(34),
+	.ordinal = TPM_ORD_PCR_EXTEND
+};
+
 /**
  * tpm_pcr_extend - extend pcr value with hash
  * @chip_num:	tpm idx # or AN&
@@ -736,14 +730,6 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read);
  * isn't, protect against the chip disappearing, by incrementing
  * the module usage count.
  */
-#define TPM_ORD_PCR_EXTEND cpu_to_be32(20)
-#define EXTEND_PCR_RESULT_SIZE 34
-static const struct tpm_input_header pcrextend_header = {
-	.tag = TPM_TAG_RQU_COMMAND,
-	.length = cpu_to_be32(34),
-	.ordinal = TPM_ORD_PCR_EXTEND
-};
-
 int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
 {
 	struct tpm_cmd_t cmd;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_of.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_of.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_of.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_of.c	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,7 @@
  * Copyright 2012 IBM Corporation
  *
  * Author: Ashley Lai <ashleydlai@gmail.com>
+ *         Nayna Jain <nayna@linux.vnet.ibm.com>
  *
  * Maintained by: <tpmdd-devel@lists.sourceforge.net>
  *
@@ -20,55 +21,38 @@
 #include "tpm.h"
 #include "tpm_eventlog.h"
 
-int read_log(struct tpm_bios_log *log)
+int tpm_read_log_of(struct tpm_chip *chip)
 {
 	struct device_node *np;
 	const u32 *sizep;
 	const u64 *basep;
+	struct tpm_bios_log *log;
 
-	if (log->bios_event_log != NULL) {
-		pr_err("%s: ERROR - Eventlog already initialized\n", __func__);
-		return -EFAULT;
-	}
-
-	np = of_find_node_by_name(NULL, "vtpm");
-	if (!np) {
-		pr_err("%s: ERROR - IBMVTPM not supported\n", __func__);
+	log = &chip->log;
+	if (chip->dev.parent && chip->dev.parent->of_node)
+		np = chip->dev.parent->of_node;
+	else
 		return -ENODEV;
-	}
 
 	sizep = of_get_property(np, "linux,sml-size", NULL);
-	if (sizep == NULL) {
-		pr_err("%s: ERROR - SML size not found\n", __func__);
-		goto cleanup_eio;
-	}
-	if (*sizep == 0) {
-		pr_err("%s: ERROR - event log area empty\n", __func__);
-		goto cleanup_eio;
-	}
-
 	basep = of_get_property(np, "linux,sml-base", NULL);
-	if (basep == NULL) {
-		pr_err("%s: ERROR - SML not found\n", __func__);
-		goto cleanup_eio;
+	if (sizep == NULL && basep == NULL)
+		return -ENODEV;
+	if (sizep == NULL || basep == NULL)
+		return -EIO;
+
+	if (*sizep == 0) {
+		dev_warn(&chip->dev, "%s: Event log area empty\n", __func__);
+		return -EIO;
 	}
 
 	log->bios_event_log = kmalloc(*sizep, GFP_KERNEL);
-	if (!log->bios_event_log) {
-		pr_err("%s: ERROR - Not enough memory for BIOS measurements\n",
-		       __func__);
-		of_node_put(np);
+	if (!log->bios_event_log)
 		return -ENOMEM;
-	}
 
 	log->bios_event_log_end = log->bios_event_log + *sizep;
 
 	memcpy(log->bios_event_log, __va(*basep), *sizep);
-	of_node_put(np);
 
 	return 0;
-
-cleanup_eio:
-	of_node_put(np);
-	return -EIO;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm-sysfs.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm-sysfs.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm-sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm-sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -193,7 +193,7 @@ static ssize_t caps_show(struct device *
 		       be32_to_cpu(cap.manufacturer_id));
 
 	/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
-	rc = tpm_getcap(chip, CAP_VERSION_1_2, &cap,
+	rc = tpm_getcap(chip, TPM_CAP_VERSION_1_2, &cap,
 			"attempting to determine the 1.2 version");
 	if (!rc) {
 		str += sprintf(str,
@@ -204,7 +204,7 @@ static ssize_t caps_show(struct device *
 			       cap.tpm_version_1_2.revMinor);
 	} else {
 		/* Otherwise just use TPM_STRUCT_VER */
-		rc = tpm_getcap(chip, CAP_VERSION_1_1, &cap,
+		rc = tpm_getcap(chip, TPM_CAP_VERSION_1_1, &cap,
 				"attempting to determine the 1.1 version");
 		if (rc)
 			return 0;
@@ -284,6 +284,9 @@ static const struct attribute_group tpm_
 
 void tpm_sysfs_add_device(struct tpm_chip *chip)
 {
+	if (chip->flags & TPM_CHIP_FLAG_TPM2)
+		return;
+
 	/* The sysfs routines rely on an implicit tpm_try_get_ops, device_del
 	 * is called before ops is null'd and the sysfs core synchronizes this
 	 * removal so that no callbacks are running or can run again
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_tis.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_tis.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_tis.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_tis.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,8 @@
 #include <linux/wait.h>
 #include <linux/acpi.h>
 #include <linux/freezer.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include "tpm.h"
 #include "tpm_tis_core.h"
 
@@ -354,12 +356,21 @@ static int tpm_tis_plat_remove(struct pl
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id tis_of_platform_match[] = {
+	{.compatible = "tcg,tpm-tis-mmio"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, tis_of_platform_match);
+#endif
+
 static struct platform_driver tis_drv = {
 	.probe = tpm_tis_plat_probe,
 	.remove = tpm_tis_plat_remove,
 	.driver = {
 		.name		= "tpm_tis",
 		.pm		= &tpm_tis_pm,
+		.of_match_table = of_match_ptr(tis_of_platform_match),
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_tis_core.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_tis_core.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_tis_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_tis_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,12 +180,19 @@ static int recv_data(struct tpm_chip *ch
 	struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
 	int size = 0, burstcnt, rc;
 
-	while (size < count &&
-	       wait_for_tpm_stat(chip,
+	while (size < count) {
+		rc = wait_for_tpm_stat(chip,
 				 TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 				 chip->timeout_c,
-				 &priv->read_queue, true) == 0) {
-		burstcnt = min_t(int, get_burstcount(chip), count - size);
+				 &priv->read_queue, true);
+		if (rc < 0)
+			return rc;
+		burstcnt = get_burstcount(chip);
+		if (burstcnt < 0) {
+			dev_err(&chip->dev, "Unable to read burstcount\n");
+			return burstcnt;
+		}
+		burstcnt = min_t(int, burstcnt, count - size);
 
 		rc = tpm_tis_read_bytes(priv, TPM_DATA_FIFO(priv->locality),
 					burstcnt, buf + size);
@@ -229,8 +236,11 @@ static int tpm_tis_recv(struct tpm_chip
 		goto out;
 	}
 
-	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
-			  &priv->int_queue, false);
+	if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
+				&priv->int_queue, false) < 0) {
+		size = -ETIME;
+		goto out;
+	}
 	status = tpm_tis_status(chip);
 	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
 		dev_err(&chip->dev, "Error left over data\n");
@@ -271,7 +281,13 @@ static int tpm_tis_send_data(struct tpm_
 	}
 
 	while (count < len - 1) {
-		burstcnt = min_t(int, get_burstcount(chip), len - count - 1);
+		burstcnt = get_burstcount(chip);
+		if (burstcnt < 0) {
+			dev_err(&chip->dev, "Unable to read burstcount\n");
+			rc = burstcnt;
+			goto out_err;
+		}
+		burstcnt = min_t(int, burstcnt, len - count - 1);
 		rc = tpm_tis_write_bytes(priv, TPM_DATA_FIFO(priv->locality),
 					 burstcnt, buf + count);
 		if (rc < 0)
@@ -279,8 +295,11 @@ static int tpm_tis_send_data(struct tpm_
 
 		count += burstcnt;
 
-		wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
-				  &priv->int_queue, false);
+		if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
+					&priv->int_queue, false) < 0) {
+			rc = -ETIME;
+			goto out_err;
+		}
 		status = tpm_tis_status(chip);
 		if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
 			rc = -EIO;
@@ -293,8 +312,11 @@ static int tpm_tis_send_data(struct tpm_
 	if (rc < 0)
 		goto out_err;
 
-	wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
-			  &priv->int_queue, false);
+	if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c,
+				&priv->int_queue, false) < 0) {
+		rc = -ETIME;
+		goto out_err;
+	}
 	status = tpm_tis_status(chip);
 	if (!itpm && (status & TPM_STS_DATA_EXPECT) != 0) {
 		rc = -EIO;
@@ -755,20 +777,20 @@ int tpm_tis_core_init(struct device *dev
 	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
 		dev_dbg(dev, "\tData Avail Int Support\n");
 
-	/* Very early on issue a command to the TPM in polling mode to make
-	 * sure it works. May as well use that command to set the proper
-	 *  timeouts for the driver.
-	 */
-	if (tpm_get_timeouts(chip)) {
-		dev_err(dev, "Could not get TPM timeouts and durations\n");
-		rc = -ENODEV;
-		goto out_err;
-	}
-
 	/* INTERRUPT Setup */
 	init_waitqueue_head(&priv->read_queue);
 	init_waitqueue_head(&priv->int_queue);
 	if (irq != -1) {
+		/* Before doing irq testing issue a command to the TPM in polling mode
+		 * to make sure it works. May as well use that command to set the
+		 * proper timeouts for the driver.
+		 */
+		if (tpm_get_timeouts(chip)) {
+			dev_err(dev, "Could not get TPM timeouts and durations\n");
+			rc = -ENODEV;
+			goto out_err;
+		}
+
 		if (irq) {
 			tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
 						 irq);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/tpm_vtpm_proxy.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_vtpm_proxy.c
--- linux-libre-4.9-gnu/drivers/char/tpm/tpm_vtpm_proxy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/tpm_vtpm_proxy.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2015, 2016 IBM Corporation
+ * Copyright (C) 2016 Intel Corporation
  *
  * Author: Stefan Berger <stefanb@us.ibm.com>
  *
@@ -41,6 +42,7 @@ struct proxy_dev {
 	long state;                  /* internal state */
 #define STATE_OPENED_FLAG        BIT(0)
 #define STATE_WAIT_RESPONSE_FLAG BIT(1)  /* waiting for emulator response */
+#define STATE_REGISTERED_FLAG	 BIT(2)
 
 	size_t req_len;              /* length of queued TPM request */
 	size_t resp_len;             /* length of queued TPM response */
@@ -369,12 +371,9 @@ static void vtpm_proxy_work(struct work_
 
 	rc = tpm_chip_register(proxy_dev->chip);
 	if (rc)
-		goto err;
-
-	return;
-
-err:
-	vtpm_proxy_fops_undo_open(proxy_dev);
+		vtpm_proxy_fops_undo_open(proxy_dev);
+	else
+		proxy_dev->state |= STATE_REGISTERED_FLAG;
 }
 
 /*
@@ -515,7 +514,8 @@ static void vtpm_proxy_delete_device(str
 	 */
 	vtpm_proxy_fops_undo_open(proxy_dev);
 
-	tpm_chip_unregister(proxy_dev->chip);
+	if (proxy_dev->state & STATE_REGISTERED_FLAG)
+		tpm_chip_unregister(proxy_dev->chip);
 
 	vtpm_proxy_delete_proxy_dev(proxy_dev);
 }
@@ -524,6 +524,50 @@ static void vtpm_proxy_delete_device(str
  * Code related to the control device /dev/vtpmx
  */
 
+/**
+ * vtpmx_ioc_new_dev - handler for the %VTPM_PROXY_IOC_NEW_DEV ioctl
+ * @file:	/dev/vtpmx
+ * @ioctl:	the ioctl number
+ * @arg:	pointer to the struct vtpmx_proxy_new_dev
+ *
+ * Creates an anonymous file that is used by the process acting as a TPM to
+ * communicate with the client processes. The function will also add a new TPM
+ * device through which data is proxied to this TPM acting process. The caller
+ * will be provided with a file descriptor to communicate with the clients and
+ * major and minor numbers for the TPM device.
+ */
+static long vtpmx_ioc_new_dev(struct file *file, unsigned int ioctl,
+			      unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	struct vtpm_proxy_new_dev __user *vtpm_new_dev_p;
+	struct vtpm_proxy_new_dev vtpm_new_dev;
+	struct file *vtpm_file;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	vtpm_new_dev_p = argp;
+
+	if (copy_from_user(&vtpm_new_dev, vtpm_new_dev_p,
+			   sizeof(vtpm_new_dev)))
+		return -EFAULT;
+
+	vtpm_file = vtpm_proxy_create_device(&vtpm_new_dev);
+	if (IS_ERR(vtpm_file))
+		return PTR_ERR(vtpm_file);
+
+	if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev,
+			 sizeof(vtpm_new_dev))) {
+		put_unused_fd(vtpm_new_dev.fd);
+		fput(vtpm_file);
+		return -EFAULT;
+	}
+
+	fd_install(vtpm_new_dev.fd, vtpm_file);
+	return 0;
+}
+
 /*
  * vtpmx_fops_ioctl: ioctl on /dev/vtpmx
  *
@@ -531,34 +575,11 @@ static void vtpm_proxy_delete_device(str
  *      Returns 0 on success, a negative error code otherwise.
  */
 static long vtpmx_fops_ioctl(struct file *f, unsigned int ioctl,
-				   unsigned long arg)
+			     unsigned long arg)
 {
-	void __user *argp = (void __user *)arg;
-	struct vtpm_proxy_new_dev __user *vtpm_new_dev_p;
-	struct vtpm_proxy_new_dev vtpm_new_dev;
-	struct file *file;
-
 	switch (ioctl) {
 	case VTPM_PROXY_IOC_NEW_DEV:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		vtpm_new_dev_p = argp;
-		if (copy_from_user(&vtpm_new_dev, vtpm_new_dev_p,
-				   sizeof(vtpm_new_dev)))
-			return -EFAULT;
-		file = vtpm_proxy_create_device(&vtpm_new_dev);
-		if (IS_ERR(file))
-			return PTR_ERR(file);
-		if (copy_to_user(vtpm_new_dev_p, &vtpm_new_dev,
-				 sizeof(vtpm_new_dev))) {
-			put_unused_fd(vtpm_new_dev.fd);
-			fput(file);
-			return -EFAULT;
-		}
-
-		fd_install(vtpm_new_dev.fd, file);
-		return 0;
-
+		return vtpmx_ioc_new_dev(f, ioctl, arg);
 	default:
 		return -ENOIOCTLCMD;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/tpm/xen-tpmfront.c linux-libre-4.10-rc8-gnu/drivers/char/tpm/xen-tpmfront.c
--- linux-libre-4.9-gnu/drivers/char/tpm/xen-tpmfront.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/tpm/xen-tpmfront.c	2017-02-12 16:03:20.000000000 -0500
@@ -307,7 +307,6 @@ static int tpmfront_probe(struct xenbus_
 	rv = setup_ring(dev, priv);
 	if (rv) {
 		chip = dev_get_drvdata(&dev->dev);
-		tpm_chip_unregister(chip);
 		ring_free(priv);
 		return rv;
 	}
@@ -337,18 +336,14 @@ static int tpmfront_resume(struct xenbus
 static void backend_changed(struct xenbus_device *dev,
 		enum xenbus_state backend_state)
 {
-	int val;
-
 	switch (backend_state) {
 	case XenbusStateInitialised:
 	case XenbusStateConnected:
 		if (dev->state == XenbusStateConnected)
 			break;
 
-		if (xenbus_scanf(XBT_NIL, dev->otherend,
-				"feature-protocol-v2", "%d", &val) < 0)
-			val = 0;
-		if (!val) {
+		if (!xenbus_read_unsigned(dev->otherend, "feature-protocol-v2",
+					  0)) {
 			xenbus_dev_fatal(dev, -EINVAL,
 					"vTPM protocol 2 required");
 			return;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/virtio_console.c linux-libre-4.10-rc8-gnu/drivers/char/virtio_console.c
--- linux-libre-4.9-gnu/drivers/char/virtio_console.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/virtio_console.c	2017-02-12 16:03:20.000000000 -0500
@@ -152,8 +152,8 @@ struct ports_device {
 	spinlock_t c_ivq_lock;
 	spinlock_t c_ovq_lock;
 
-	/* The current config space is stored here */
-	struct virtio_console_config config;
+	/* max. number of ports this device can hold */
+	u32 max_nr_ports;
 
 	/* The virtio device we're associated with */
 	struct virtio_device *vdev;
@@ -1649,11 +1649,11 @@ static void handle_control_message(struc
 			break;
 		}
 		if (virtio32_to_cpu(vdev, cpkt->id) >=
-		    portdev->config.max_nr_ports) {
+		    portdev->max_nr_ports) {
 			dev_warn(&portdev->vdev->dev,
 				"Request for adding port with "
 				"out-of-bound id %u, max. supported id: %u\n",
-				cpkt->id, portdev->config.max_nr_ports - 1);
+				cpkt->id, portdev->max_nr_ports - 1);
 			break;
 		}
 		add_port(portdev, virtio32_to_cpu(vdev, cpkt->id));
@@ -1862,7 +1862,7 @@ static void config_work_handler(struct w
 {
 	struct ports_device *portdev;
 
-	portdev = container_of(work, struct ports_device, control_work);
+	portdev = container_of(work, struct ports_device, config_work);
 	if (!use_multiport(portdev)) {
 		struct virtio_device *vdev;
 		struct port *port;
@@ -1894,7 +1894,7 @@ static int init_vqs(struct ports_device
 	u32 i, j, nr_ports, nr_queues;
 	int err;
 
-	nr_ports = portdev->config.max_nr_ports;
+	nr_ports = portdev->max_nr_ports;
 	nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2;
 
 	vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL);
@@ -2047,13 +2047,13 @@ static int virtcons_probe(struct virtio_
 	}
 
 	multiport = false;
-	portdev->config.max_nr_ports = 1;
+	portdev->max_nr_ports = 1;
 
 	/* Don't test MULTIPORT at all if we're rproc: not a valid feature! */
 	if (!is_rproc_serial(vdev) &&
 	    virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
 				 struct virtio_console_config, max_nr_ports,
-				 &portdev->config.max_nr_ports) == 0) {
+				 &portdev->max_nr_ports) == 0) {
 		multiport = true;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c linux-libre-4.10-rc8-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c
--- linux-libre-4.9-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,7 +88,7 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_OF
 /* For open firmware. */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/bcm/clk-bcm2835.c linux-libre-4.10-rc8-gnu/drivers/clk/bcm/clk-bcm2835.c
--- linux-libre-4.9-gnu/drivers/clk/bcm/clk-bcm2835.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/bcm/clk-bcm2835.c	2017-02-12 16:03:20.000000000 -0500
@@ -436,6 +436,9 @@ struct bcm2835_clock_data {
 	const char *const *parents;
 	int num_mux_parents;
 
+	/* Bitmap encoding which parents accept rate change propagation. */
+	unsigned int set_rate_parent;
+
 	u32 ctl_reg;
 	u32 div_reg;
 
@@ -751,7 +754,9 @@ static void bcm2835_pll_divider_off(stru
 	cprman_write(cprman, data->cm_reg,
 		     (cprman_read(cprman, data->cm_reg) &
 		      ~data->load_mask) | data->hold_mask);
-	cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+	cprman_write(cprman, data->a2w_reg,
+		     cprman_read(cprman, data->a2w_reg) |
+		     A2W_PLL_CHANNEL_DISABLE);
 	spin_unlock(&cprman->regs_lock);
 }
 
@@ -1015,10 +1020,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw)
 	return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
 }
 
+static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
+							int parent_idx,
+							unsigned long rate,
+							u32 *div,
+							unsigned long *prate)
+{
+	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+	struct bcm2835_cprman *cprman = clock->cprman;
+	const struct bcm2835_clock_data *data = clock->data;
+	unsigned long best_rate = 0;
+	u32 curdiv, mindiv, maxdiv;
+	struct clk_hw *parent;
+
+	parent = clk_hw_get_parent_by_index(hw, parent_idx);
+
+	if (!(BIT(parent_idx) & data->set_rate_parent)) {
+		*prate = clk_hw_get_rate(parent);
+		*div = bcm2835_clock_choose_div(hw, rate, *prate, true);
+
+		return bcm2835_clock_rate_from_divisor(clock, *prate,
+						       *div);
+	}
+
+	if (data->frac_bits)
+		dev_warn(cprman->dev,
+			"frac bits are not used when propagating rate change");
+
+	/* clamp to min divider of 2 if we're dealing with a mash clock */
+	mindiv = data->is_mash_clock ? 2 : 1;
+	maxdiv = BIT(data->int_bits) - 1;
+
+	/* TODO: Be smart, and only test a subset of the available divisors. */
+	for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
+		unsigned long tmp_rate;
+
+		tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
+		tmp_rate /= curdiv;
+		if (curdiv == mindiv ||
+		    (tmp_rate > best_rate && tmp_rate <= rate))
+			best_rate = tmp_rate;
+
+		if (best_rate == rate)
+			break;
+	}
+
+	*div = curdiv << CM_DIV_FRAC_BITS;
+	*prate = curdiv * best_rate;
+
+	return best_rate;
+}
+
 static int bcm2835_clock_determine_rate(struct clk_hw *hw,
 					struct clk_rate_request *req)
 {
-	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	struct clk_hw *parent, *best_parent = NULL;
 	bool current_parent_is_pllc;
 	unsigned long rate, best_rate = 0;
@@ -1046,9 +1101,8 @@ static int bcm2835_clock_determine_rate(
 		if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
 			continue;
 
-		prate = clk_hw_get_rate(parent);
-		div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
-		rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
+		rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
+							  &div, &prate);
 		if (rate > best_rate && rate <= req->rate) {
 			best_parent = parent;
 			best_prate = prate;
@@ -1260,6 +1314,13 @@ static struct clk_hw *bcm2835_register_c
 	init.name = data->name;
 	init.flags = data->flags | CLK_IGNORE_UNUSED;
 
+	/*
+	 * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
+	 * rate changes on at least of the parents.
+	 */
+	if (data->set_rate_parent)
+		init.flags |= CLK_SET_RATE_PARENT;
+
 	if (data->is_vpu_clock) {
 		init.ops = &bcm2835_vpu_clock_clk_ops;
 	} else {
@@ -1596,7 +1657,7 @@ static const struct bcm2835_clk_desc clk
 		.a2w_reg = A2W_PLLH_AUX,
 		.load_mask = CM_PLLH_LOADAUX,
 		.hold_mask = 0,
-		.fixed_divider = 10),
+		.fixed_divider = 1),
 	[BCM2835_PLLH_PIX]	= REGISTER_PLL_DIV(
 		.name = "pllh_pix",
 		.source_pll = "pllh",
@@ -1800,7 +1861,12 @@ static const struct bcm2835_clk_desc clk
 		.ctl_reg = CM_VECCTL,
 		.div_reg = CM_VECDIV,
 		.int_bits = 4,
-		.frac_bits = 0),
+		.frac_bits = 0,
+		/*
+		 * Allow rate change propagation only on PLLH_AUX which is
+		 * assigned index 7 in the parent array.
+		 */
+		.set_rate_parent = BIT(7)),
 
 	/* dsi clocks */
 	[BCM2835_CLOCK_DSI0E]	= REGISTER_PER_CLK(
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/bcm/Kconfig linux-libre-4.10-rc8-gnu/drivers/clk/bcm/Kconfig
--- linux-libre-4.9-gnu/drivers/clk/bcm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/bcm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,6 @@
 config CLK_BCM_63XX
 	bool "Broadcom BCM63xx clock support"
 	depends on ARCH_BCM_63XX || COMPILE_TEST
-	depends on COMMON_CLK
 	select COMMON_CLK_IPROC
 	default ARCH_BCM_63XX
 	help
@@ -11,27 +10,22 @@ config CLK_BCM_63XX
 config CLK_BCM_KONA
 	bool "Broadcom Kona CCU clock support"
 	depends on ARCH_BCM_MOBILE || COMPILE_TEST
-	depends on COMMON_CLK
-	default y
+	default ARCH_BCM_MOBILE
 	help
 	  Enable common clock framework support for Broadcom SoCs
 	  using "Kona" style clock control units, including those
 	  in the BCM281xx and BCM21664 families.
 
 config COMMON_CLK_IPROC
-	bool "Broadcom iProc clock support"
-	depends on ARCH_BCM_IPROC || ARCH_BCM_63XX || COMPILE_TEST
-	depends on COMMON_CLK
-	default ARCH_BCM_IPROC
+	bool
 	help
 	  Enable common clock framework support for Broadcom SoCs
 	  based on the iProc architecture
 
-if COMMON_CLK_IPROC
-
 config CLK_BCM_CYGNUS
 	bool "Broadcom Cygnus clock support"
 	depends on ARCH_BCM_CYGNUS || COMPILE_TEST
+	select COMMON_CLK_IPROC
 	default ARCH_BCM_CYGNUS
 	help
 	  Enable common clock framework support for the Broadcom Cygnus SoC
@@ -39,6 +33,7 @@ config CLK_BCM_CYGNUS
 config CLK_BCM_NSP
 	bool "Broadcom Northstar/Northstar Plus clock support"
 	depends on ARCH_BCM_5301X || ARCH_BCM_NSP || COMPILE_TEST
+	select COMMON_CLK_IPROC
 	default ARCH_BCM_5301X || ARCH_BCM_NSP
 	help
 	  Enable common clock framework support for the Broadcom Northstar and
@@ -47,8 +42,7 @@ config CLK_BCM_NSP
 config CLK_BCM_NS2
 	bool "Broadcom Northstar 2 clock support"
 	depends on ARCH_BCM_IPROC || COMPILE_TEST
+	select COMMON_CLK_IPROC
 	default ARCH_BCM_IPROC
 	help
 	  Enable common clock framework support for the Broadcom Northstar 2 SoC
-
-endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clk-cdce925.c linux-libre-4.10-rc8-gnu/drivers/clk/clk-cdce925.c
--- linux-libre-4.9-gnu/drivers/clk/clk-cdce925.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clk-cdce925.c	2017-02-12 16:03:20.000000000 -0500
@@ -216,7 +216,7 @@ static int cdce925_pll_prepare(struct cl
 		nn = n * BIT(p);
 		/* q = int(nn/m) */
 		q = nn / m;
-		if ((q < 16) || (1 > 64)) {
+		if ((q < 16) || (q > 63)) {
 			pr_debug("%s invalid q=%d\n", __func__, q);
 			return -EINVAL;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clkdev.c linux-libre-4.10-rc8-gnu/drivers/clk/clkdev.c
--- linux-libre-4.9-gnu/drivers/clk/clkdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clkdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -448,12 +448,20 @@ EXPORT_SYMBOL(clk_register_clkdev);
  *
  * con_id or dev_id may be NULL as a wildcard, just as in the rest of
  * clkdev.
+ *
+ * To make things easier for mass registration, we detect error clk_hws
+ * from a previous clk_hw_register_*() call, and return the error code for
+ * those.  This is to permit this function to be called immediately
+ * after clk_hw_register_*().
  */
 int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
 	const char *dev_id)
 {
 	struct clk_lookup *cl;
 
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
 	/*
 	 * Since dev_id can be NULL, and NULL is handled specially, we must
 	 * pass it as either a NULL format string, or with "%s".
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clk-devres.c linux-libre-4.10-rc8-gnu/drivers/clk/clk-devres.c
--- linux-libre-4.9-gnu/drivers/clk/clk-devres.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clk-devres.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,3 +53,24 @@ void devm_clk_put(struct device *dev, st
 	WARN_ON(ret);
 }
 EXPORT_SYMBOL(devm_clk_put);
+
+struct clk *devm_get_clk_from_child(struct device *dev,
+				    struct device_node *np, const char *con_id)
+{
+	struct clk **ptr, *clk;
+
+	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	clk = of_clk_get_by_name(np, con_id);
+	if (!IS_ERR(clk)) {
+		*ptr = clk;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return clk;
+}
+EXPORT_SYMBOL(devm_get_clk_from_child);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clk-gate.c linux-libre-4.10-rc8-gnu/drivers/clk/clk-gate.c
--- linux-libre-4.9-gnu/drivers/clk/clk-gate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clk-gate.c	2017-02-12 16:03:20.000000000 -0500
@@ -145,8 +145,8 @@ struct clk_hw *clk_hw_register_gate(stru
 	init.name = name;
 	init.ops = &clk_gate_ops;
 	init.flags = flags | CLK_IS_BASIC;
-	init.parent_names = (parent_name ? &parent_name: NULL);
-	init.num_parents = (parent_name ? 1 : 0);
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
 
 	/* struct clk_gate assignments */
 	gate->reg = reg;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clk-oxnas.c linux-libre-4.10-rc8-gnu/drivers/clk/clk-oxnas.c
--- linux-libre-4.9-gnu/drivers/clk/clk-oxnas.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clk-oxnas.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,31 +20,43 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/stringify.h>
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 
+#include <dt-bindings/clock/oxsemi,ox810se.h>
+#include <dt-bindings/clock/oxsemi,ox820.h>
+
 /* Standard regmap gate clocks */
-struct clk_oxnas {
+struct clk_oxnas_gate {
 	struct clk_hw hw;
-	signed char bit;
+	unsigned int bit;
 	struct regmap *regmap;
 };
 
+struct oxnas_stdclk_data {
+	struct clk_hw_onecell_data *onecell_data;
+	struct clk_oxnas_gate **gates;
+	unsigned int ngates;
+	struct clk_oxnas_pll **plls;
+	unsigned int nplls;
+};
+
 /* Regmap offsets */
 #define CLK_STAT_REGOFFSET	0x24
 #define CLK_SET_REGOFFSET	0x2c
 #define CLK_CLR_REGOFFSET	0x30
 
-static inline struct clk_oxnas *to_clk_oxnas(struct clk_hw *hw)
+static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw)
 {
-	return container_of(hw, struct clk_oxnas, hw);
+	return container_of(hw, struct clk_oxnas_gate, hw);
 }
 
-static int oxnas_clk_is_enabled(struct clk_hw *hw)
+static int oxnas_clk_gate_is_enabled(struct clk_hw *hw)
 {
-	struct clk_oxnas *std = to_clk_oxnas(hw);
+	struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
 	int ret;
 	unsigned int val;
 
@@ -55,29 +67,29 @@ static int oxnas_clk_is_enabled(struct c
 	return val & BIT(std->bit);
 }
 
-static int oxnas_clk_enable(struct clk_hw *hw)
+static int oxnas_clk_gate_enable(struct clk_hw *hw)
 {
-	struct clk_oxnas *std = to_clk_oxnas(hw);
+	struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
 
 	regmap_write(std->regmap, CLK_SET_REGOFFSET, BIT(std->bit));
 
 	return 0;
 }
 
-static void oxnas_clk_disable(struct clk_hw *hw)
+static void oxnas_clk_gate_disable(struct clk_hw *hw)
 {
-	struct clk_oxnas *std = to_clk_oxnas(hw);
+	struct clk_oxnas_gate *std = to_clk_oxnas_gate(hw);
 
 	regmap_write(std->regmap, CLK_CLR_REGOFFSET, BIT(std->bit));
 }
 
-static const struct clk_ops oxnas_clk_ops = {
-	.enable = oxnas_clk_enable,
-	.disable = oxnas_clk_disable,
-	.is_enabled = oxnas_clk_is_enabled,
+static const struct clk_ops oxnas_clk_gate_ops = {
+	.enable = oxnas_clk_gate_enable,
+	.disable = oxnas_clk_gate_disable,
+	.is_enabled = oxnas_clk_gate_is_enabled,
 };
 
-static const char *const oxnas_clk_parents[] = {
+static const char *const osc_parents[] = {
 	"oscillator",
 };
 
@@ -85,63 +97,138 @@ static const char *const eth_parents[] =
 	"gmacclk",
 };
 
-#define DECLARE_STD_CLKP(__clk, __parent)			\
-static const struct clk_init_data clk_##__clk##_init = {	\
-	.name = __stringify(__clk),				\
-	.ops = &oxnas_clk_ops,					\
-	.parent_names = __parent,				\
-	.num_parents = ARRAY_SIZE(__parent),			\
+#define OXNAS_GATE(_name, _bit, _parents)				\
+struct clk_oxnas_gate _name = {						\
+	.bit = (_bit),							\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = #_name,						\
+		.ops = &oxnas_clk_gate_ops,				\
+		.parent_names = _parents,				\
+		.num_parents = ARRAY_SIZE(_parents),			\
+		.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),	\
+	},								\
 }
 
-#define DECLARE_STD_CLK(__clk) DECLARE_STD_CLKP(__clk, oxnas_clk_parents)
+static OXNAS_GATE(ox810se_leon, 0, osc_parents);
+static OXNAS_GATE(ox810se_dma_sgdma, 1, osc_parents);
+static OXNAS_GATE(ox810se_cipher, 2, osc_parents);
+static OXNAS_GATE(ox810se_sata, 4, osc_parents);
+static OXNAS_GATE(ox810se_audio, 5, osc_parents);
+static OXNAS_GATE(ox810se_usbmph, 6, osc_parents);
+static OXNAS_GATE(ox810se_etha, 7, eth_parents);
+static OXNAS_GATE(ox810se_pciea, 8, osc_parents);
+static OXNAS_GATE(ox810se_nand, 9, osc_parents);
 
-/* Hardware Bit - Clock association */
-struct clk_oxnas_init_data {
-	unsigned long bit;
-	const struct clk_init_data *clk_init;
+static struct clk_oxnas_gate *ox810se_gates[] = {
+	&ox810se_leon,
+	&ox810se_dma_sgdma,
+	&ox810se_cipher,
+	&ox810se_sata,
+	&ox810se_audio,
+	&ox810se_usbmph,
+	&ox810se_etha,
+	&ox810se_pciea,
+	&ox810se_nand,
 };
 
-/* Clk init data declaration */
-DECLARE_STD_CLK(leon);
-DECLARE_STD_CLK(dma_sgdma);
-DECLARE_STD_CLK(cipher);
-DECLARE_STD_CLK(sata);
-DECLARE_STD_CLK(audio);
-DECLARE_STD_CLK(usbmph);
-DECLARE_STD_CLKP(etha, eth_parents);
-DECLARE_STD_CLK(pciea);
-DECLARE_STD_CLK(nand);
+static OXNAS_GATE(ox820_leon, 0, osc_parents);
+static OXNAS_GATE(ox820_dma_sgdma, 1, osc_parents);
+static OXNAS_GATE(ox820_cipher, 2, osc_parents);
+static OXNAS_GATE(ox820_sd, 3, osc_parents);
+static OXNAS_GATE(ox820_sata, 4, osc_parents);
+static OXNAS_GATE(ox820_audio, 5, osc_parents);
+static OXNAS_GATE(ox820_usbmph, 6, osc_parents);
+static OXNAS_GATE(ox820_etha, 7, eth_parents);
+static OXNAS_GATE(ox820_pciea, 8, osc_parents);
+static OXNAS_GATE(ox820_nand, 9, osc_parents);
+static OXNAS_GATE(ox820_ethb, 10, eth_parents);
+static OXNAS_GATE(ox820_pcieb, 11, osc_parents);
+static OXNAS_GATE(ox820_ref600, 12, osc_parents);
+static OXNAS_GATE(ox820_usbdev, 13, osc_parents);
 
-/* Table index is clock indice */
-static const struct clk_oxnas_init_data clk_oxnas_init[] = {
-	[0] = {0, &clk_leon_init},
-	[1] = {1, &clk_dma_sgdma_init},
-	[2] = {2, &clk_cipher_init},
-	/* Skip & Do not touch to DDR clock */
-	[3] = {4, &clk_sata_init},
-	[4] = {5, &clk_audio_init},
-	[5] = {6, &clk_usbmph_init},
-	[6] = {7, &clk_etha_init},
-	[7] = {8, &clk_pciea_init},
-	[8] = {9, &clk_nand_init},
+static struct clk_oxnas_gate *ox820_gates[] = {
+	&ox820_leon,
+	&ox820_dma_sgdma,
+	&ox820_cipher,
+	&ox820_sd,
+	&ox820_sata,
+	&ox820_audio,
+	&ox820_usbmph,
+	&ox820_etha,
+	&ox820_pciea,
+	&ox820_nand,
+	&ox820_etha,
+	&ox820_pciea,
+	&ox820_ref600,
+	&ox820_usbdev,
 };
 
-struct clk_oxnas_data {
-	struct clk_oxnas clk_oxnas[ARRAY_SIZE(clk_oxnas_init)];
-	struct clk_onecell_data onecell_data[ARRAY_SIZE(clk_oxnas_init)];
-	struct clk *clks[ARRAY_SIZE(clk_oxnas_init)];
+static struct clk_hw_onecell_data ox810se_hw_onecell_data = {
+	.hws = {
+		[CLK_810_LEON]	= &ox810se_leon.hw,
+		[CLK_810_DMA_SGDMA]	= &ox810se_dma_sgdma.hw,
+		[CLK_810_CIPHER]	= &ox810se_cipher.hw,
+		[CLK_810_SATA]	= &ox810se_sata.hw,
+		[CLK_810_AUDIO]	= &ox810se_audio.hw,
+		[CLK_810_USBMPH]	= &ox810se_usbmph.hw,
+		[CLK_810_ETHA]	= &ox810se_etha.hw,
+		[CLK_810_PCIEA]	= &ox810se_pciea.hw,
+		[CLK_810_NAND]	= &ox810se_nand.hw,
+	},
+	.num = ARRAY_SIZE(ox810se_gates),
+};
+
+static struct clk_hw_onecell_data ox820_hw_onecell_data = {
+	.hws = {
+		[CLK_820_LEON]	= &ox820_leon.hw,
+		[CLK_820_DMA_SGDMA]	= &ox820_dma_sgdma.hw,
+		[CLK_820_CIPHER]	= &ox820_cipher.hw,
+		[CLK_820_SD]	= &ox820_sd.hw,
+		[CLK_820_SATA]	= &ox820_sata.hw,
+		[CLK_820_AUDIO]	= &ox820_audio.hw,
+		[CLK_820_USBMPH]	= &ox820_usbmph.hw,
+		[CLK_820_ETHA]	= &ox820_etha.hw,
+		[CLK_820_PCIEA]	= &ox820_pciea.hw,
+		[CLK_820_NAND]	= &ox820_nand.hw,
+		[CLK_820_ETHB]	= &ox820_ethb.hw,
+		[CLK_820_PCIEB]	= &ox820_pcieb.hw,
+		[CLK_820_REF600]	= &ox820_ref600.hw,
+		[CLK_820_USBDEV]	= &ox820_usbdev.hw,
+	},
+	.num = ARRAY_SIZE(ox820_gates),
+};
+
+static struct oxnas_stdclk_data ox810se_stdclk_data = {
+	.onecell_data = &ox810se_hw_onecell_data,
+	.gates = ox810se_gates,
+	.ngates = ARRAY_SIZE(ox810se_gates),
+};
+
+static struct oxnas_stdclk_data ox820_stdclk_data = {
+	.onecell_data = &ox820_hw_onecell_data,
+	.gates = ox820_gates,
+	.ngates = ARRAY_SIZE(ox820_gates),
+};
+
+static const struct of_device_id oxnas_stdclk_dt_ids[] = {
+	{ .compatible = "oxsemi,ox810se-stdclk", &ox810se_stdclk_data },
+	{ .compatible = "oxsemi,ox820-stdclk", &ox820_stdclk_data },
+	{ }
 };
 
 static int oxnas_stdclk_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	struct clk_oxnas_data *clk_oxnas;
+	const struct oxnas_stdclk_data *data;
+	const struct of_device_id *id;
 	struct regmap *regmap;
+	int ret;
 	int i;
 
-	clk_oxnas = devm_kzalloc(&pdev->dev, sizeof(*clk_oxnas), GFP_KERNEL);
-	if (!clk_oxnas)
-		return -ENOMEM;
+	id = of_match_device(oxnas_stdclk_dt_ids, &pdev->dev);
+	if (!id)
+		return -ENODEV;
+	data = id->data;
 
 	regmap = syscon_node_to_regmap(of_get_parent(np));
 	if (IS_ERR(regmap)) {
@@ -149,32 +236,23 @@ static int oxnas_stdclk_probe(struct pla
 		return PTR_ERR(regmap);
 	}
 
-	for (i = 0; i < ARRAY_SIZE(clk_oxnas_init); i++) {
-		struct clk_oxnas *_clk;
+	for (i = 0 ; i < data->ngates ; ++i)
+		data->gates[i]->regmap = regmap;
 
-		_clk = &clk_oxnas->clk_oxnas[i];
-		_clk->bit = clk_oxnas_init[i].bit;
-		_clk->hw.init = clk_oxnas_init[i].clk_init;
-		_clk->regmap = regmap;
+	for (i = 0; i < data->onecell_data->num; i++) {
+		if (!data->onecell_data->hws[i])
+			continue;
 
-		clk_oxnas->clks[i] =
-			devm_clk_register(&pdev->dev, &_clk->hw);
-		if (WARN_ON(IS_ERR(clk_oxnas->clks[i])))
-			return PTR_ERR(clk_oxnas->clks[i]);
+		ret = devm_clk_hw_register(&pdev->dev,
+					   data->onecell_data->hws[i]);
+		if (ret)
+			return ret;
 	}
 
-	clk_oxnas->onecell_data->clks = clk_oxnas->clks;
-	clk_oxnas->onecell_data->clk_num = ARRAY_SIZE(clk_oxnas_init);
-
-	return of_clk_add_provider(np, of_clk_src_onecell_get,
-				   clk_oxnas->onecell_data);
+	return of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
+				      data->onecell_data);
 }
 
-static const struct of_device_id oxnas_stdclk_dt_ids[] = {
-	{ .compatible = "oxsemi,ox810se-stdclk" },
-	{ }
-};
-
 static struct platform_driver oxnas_stdclk_driver = {
 	.probe = oxnas_stdclk_probe,
 	.driver	= {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clk-qoriq.c linux-libre-4.10-rc8-gnu/drivers/clk/clk-qoriq.c
--- linux-libre-4.9-gnu/drivers/clk/clk-qoriq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clk-qoriq.c	2017-02-12 16:03:20.000000000 -0500
@@ -266,6 +266,39 @@ static const struct clockgen_muxinfo ls1
 	},
 };
 
+static const struct clockgen_muxinfo ls1046a_hwa1 = {
+	{
+		{},
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV3 },
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV4 },
+		{ CLKSEL_VALID, PLATFORM_PLL, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+	},
+};
+
+static const struct clockgen_muxinfo ls1046a_hwa2 = {
+	{
+		{},
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV1 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV2 },
+		{ CLKSEL_VALID, CGA_PLL2, PLL_DIV3 },
+		{},
+		{},
+		{ CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	},
+};
+
+static const struct clockgen_muxinfo ls1012a_cmux = {
+	{
+		[0] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV1 },
+		{},
+		[2] = { CLKSEL_VALID, CGA_PLL1, PLL_DIV2 },
+	}
+};
+
 static const struct clockgen_muxinfo t1023_hwa1 = {
 	{
 		{},
@@ -489,6 +522,31 @@ static const struct clockgen_chipinfo ch
 		.flags = CG_PLL_8BIT,
 	},
 	{
+		.compat = "fsl,ls1046a-clockgen",
+		.init_periph = t2080_init_periph,
+		.cmux_groups = {
+			&t1040_cmux
+		},
+		.hwaccel = {
+			&ls1046a_hwa1, &ls1046a_hwa2
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x07,
+		.flags = CG_PLL_8BIT,
+	},
+	{
+		.compat = "fsl,ls1012a-clockgen",
+		.cmux_groups = {
+			&ls1012a_cmux
+		},
+		.cmux_to_group = {
+			0, -1
+		},
+		.pll_mask = 0x03,
+	},
+	{
 		.compat = "fsl,ls2080a-clockgen",
 		.cmux_groups = {
 			&clockgen2_cmux_cga12, &clockgen2_cmux_cgb
@@ -1273,8 +1331,10 @@ err:
 
 CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init);
+CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init);
 CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init);
 
 /* Legacy nodes */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clk-stm32f4.c linux-libre-4.10-rc8-gnu/drivers/clk/clk-stm32f4.c
--- linux-libre-4.9-gnu/drivers/clk/clk-stm32f4.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clk-stm32f4.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,10 +19,14 @@
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
 
 #define STM32F4_RCC_PLLCFGR		0x04
 #define STM32F4_RCC_CFGR		0x08
@@ -31,6 +35,8 @@
 #define STM32F4_RCC_AHB3ENR		0x38
 #define STM32F4_RCC_APB1ENR		0x40
 #define STM32F4_RCC_APB2ENR		0x44
+#define STM32F4_RCC_BDCR		0x70
+#define STM32F4_RCC_CSR			0x74
 
 struct stm32f4_gate_data {
 	u8	offset;
@@ -40,7 +46,7 @@ struct stm32f4_gate_data {
 	unsigned long flags;
 };
 
-static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
+static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
 	{ STM32F4_RCC_AHB1ENR,  0,	"gpioa",	"ahb_div" },
 	{ STM32F4_RCC_AHB1ENR,  1,	"gpiob",	"ahb_div" },
 	{ STM32F4_RCC_AHB1ENR,  2,	"gpioc",	"ahb_div" },
@@ -120,26 +126,113 @@ static const struct stm32f4_gate_data st
 	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
 };
 
-/*
- * MAX_CLKS is the maximum value in the enumeration below plus the combined
- * hweight of stm32f42xx_gate_map (plus one).
- */
-#define MAX_CLKS 74
+static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
+	{ STM32F4_RCC_AHB1ENR,  0,	"gpioa",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  1,	"gpiob",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  2,	"gpioc",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  3,	"gpiod",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  4,	"gpioe",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  5,	"gpiof",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  6,	"gpiog",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  7,	"gpioh",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  8,	"gpioi",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR,  9,	"gpioj",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 10,	"gpiok",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 12,	"crc",		"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 18,	"bkpsra",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 20,	"ccmdatam",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 21,	"dma1",		"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 22,	"dma2",		"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 23,	"dma2d",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 25,	"ethmac",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 26,	"ethmactx",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 27,	"ethmacrx",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 28,	"ethmacptp",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 29,	"otghs",	"ahb_div" },
+	{ STM32F4_RCC_AHB1ENR, 30,	"otghsulpi",	"ahb_div" },
 
-enum { SYSTICK, FCLK };
+	{ STM32F4_RCC_AHB2ENR,  0,	"dcmi",		"ahb_div" },
+	{ STM32F4_RCC_AHB2ENR,  4,	"cryp",		"ahb_div" },
+	{ STM32F4_RCC_AHB2ENR,  5,	"hash",		"ahb_div" },
+	{ STM32F4_RCC_AHB2ENR,  6,	"rng",		"pll48" },
+	{ STM32F4_RCC_AHB2ENR,  7,	"otgfs",	"pll48" },
+
+	{ STM32F4_RCC_AHB3ENR,  0,	"fmc",		"ahb_div",
+		CLK_IGNORE_UNUSED },
+	{ STM32F4_RCC_AHB3ENR,  1,	"qspi",		"ahb_div",
+		CLK_IGNORE_UNUSED },
+
+	{ STM32F4_RCC_APB1ENR,  0,	"tim2",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  1,	"tim3",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  2,	"tim4",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  3,	"tim5",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  4,	"tim6",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  5,	"tim7",		"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  6,	"tim12",	"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  7,	"tim13",	"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR,  8,	"tim14",	"apb1_mul" },
+	{ STM32F4_RCC_APB1ENR, 11,	"wwdg",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 14,	"spi2",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 15,	"spi3",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 17,	"uart2",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 18,	"uart3",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 19,	"uart4",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 20,	"uart5",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 21,	"i2c1",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 22,	"i2c2",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 23,	"i2c3",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 25,	"can1",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 26,	"can2",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 28,	"pwr",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 29,	"dac",		"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 30,	"uart7",	"apb1_div" },
+	{ STM32F4_RCC_APB1ENR, 31,	"uart8",	"apb1_div" },
+
+	{ STM32F4_RCC_APB2ENR,  0,	"tim1",		"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR,  1,	"tim8",		"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR,  4,	"usart1",	"apb2_div" },
+	{ STM32F4_RCC_APB2ENR,  5,	"usart6",	"apb2_div" },
+	{ STM32F4_RCC_APB2ENR,  8,	"adc1",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR,  9,	"adc2",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 10,	"adc3",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 11,	"sdio",		"pll48" },
+	{ STM32F4_RCC_APB2ENR, 12,	"spi1",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 13,	"spi4",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 14,	"syscfg",	"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 16,	"tim9",		"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR, 17,	"tim10",	"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR, 18,	"tim11",	"apb2_mul" },
+	{ STM32F4_RCC_APB2ENR, 20,	"spi5",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 21,	"spi6",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 22,	"sai1",		"apb2_div" },
+	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
+};
+
+enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
 
 /*
  * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
  * have gate bits associated with them. Its combined hweight is 71.
  */
-static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull,
-					   0x0000000000000001ull,
-					   0x04777f33f6fec9ffull };
+#define MAX_GATE_MAP 3
+
+static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+						       0x0000000000000001ull,
+						       0x04777f33f6fec9ffull };
+
+static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
+						       0x0000000000000003ull,
+						       0x0c777f33f6fec9ffull };
+
+static const u64 *stm32f4_gate_map;
+
+static struct clk_hw **clks;
 
-static struct clk_hw *clks[MAX_CLKS];
 static DEFINE_SPINLOCK(stm32f4_clk_lock);
 static void __iomem *base;
 
+static struct regmap *pdrm;
+
 /*
  * "Multiplier" device for APBx clocks.
  *
@@ -256,15 +349,15 @@ static void stm32f4_rcc_register_pll(con
  */
 static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
 {
-	u64 table[ARRAY_SIZE(stm32f42xx_gate_map)];
+	u64 table[MAX_GATE_MAP];
 
 	if (primary == 1) {
-		if (WARN_ON(secondary > FCLK))
+		if (WARN_ON(secondary >= END_PRIMARY_CLK))
 			return -EINVAL;
 		return secondary;
 	}
 
-	memcpy(table, stm32f42xx_gate_map, sizeof(table));
+	memcpy(table, stm32f4_gate_map, sizeof(table));
 
 	/* only bits set in table can be used as indices */
 	if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
@@ -276,7 +369,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8
 	table[BIT_ULL_WORD(secondary)] &=
 	    GENMASK_ULL(secondary % BITS_PER_LONG_LONG, 0);
 
-	return FCLK + hweight64(table[0]) +
+	return END_PRIMARY_CLK - 1 + hweight64(table[0]) +
 	       (BIT_ULL_WORD(secondary) >= 1 ? hweight64(table[1]) : 0) +
 	       (BIT_ULL_WORD(secondary) >= 2 ? hweight64(table[2]) : 0);
 }
@@ -292,6 +385,212 @@ stm32f4_rcc_lookup_clk(struct of_phandle
 	return clks[i];
 }
 
+#define to_rgclk(_rgate) container_of(_rgate, struct stm32_rgate, gate)
+
+static inline void disable_power_domain_write_protection(void)
+{
+	if (pdrm)
+		regmap_update_bits(pdrm, 0x00, (1 << 8), (1 << 8));
+}
+
+static inline void enable_power_domain_write_protection(void)
+{
+	if (pdrm)
+		regmap_update_bits(pdrm, 0x00, (1 << 8), (0 << 8));
+}
+
+static inline void sofware_reset_backup_domain(void)
+{
+	unsigned long val;
+
+	val = readl(base + STM32F4_RCC_BDCR);
+	writel(val | BIT(16), base + STM32F4_RCC_BDCR);
+	writel(val & ~BIT(16), base + STM32F4_RCC_BDCR);
+}
+
+struct stm32_rgate {
+	struct	clk_gate gate;
+	u8	bit_rdy_idx;
+};
+
+#define RTC_TIMEOUT 1000000
+
+static int rgclk_enable(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+	struct stm32_rgate *rgate = to_rgclk(gate);
+	u32 reg;
+	int ret;
+
+	disable_power_domain_write_protection();
+
+	clk_gate_ops.enable(hw);
+
+	ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg,
+			reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT);
+
+	enable_power_domain_write_protection();
+	return ret;
+}
+
+static void rgclk_disable(struct clk_hw *hw)
+{
+	clk_gate_ops.disable(hw);
+}
+
+static int rgclk_is_enabled(struct clk_hw *hw)
+{
+	return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops rgclk_ops = {
+	.enable = rgclk_enable,
+	.disable = rgclk_disable,
+	.is_enabled = rgclk_is_enabled,
+};
+
+static struct clk_hw *clk_register_rgate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx, u8 bit_rdy_idx,
+		u8 clk_gate_flags, spinlock_t *lock)
+{
+	struct stm32_rgate *rgate;
+	struct clk_init_data init = { NULL };
+	struct clk_hw *hw;
+	int ret;
+
+	rgate = kzalloc(sizeof(*rgate), GFP_KERNEL);
+	if (!rgate)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &rgclk_ops;
+	init.flags = flags;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	rgate->bit_rdy_idx = bit_rdy_idx;
+
+	rgate->gate.lock = lock;
+	rgate->gate.reg = reg;
+	rgate->gate.bit_idx = bit_idx;
+	rgate->gate.hw.init = &init;
+
+	hw = &rgate->gate.hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
+		kfree(rgate);
+		hw = ERR_PTR(ret);
+	}
+
+	return hw;
+}
+
+static int cclk_gate_enable(struct clk_hw *hw)
+{
+	int ret;
+
+	disable_power_domain_write_protection();
+
+	ret = clk_gate_ops.enable(hw);
+
+	enable_power_domain_write_protection();
+
+	return ret;
+}
+
+static void cclk_gate_disable(struct clk_hw *hw)
+{
+	disable_power_domain_write_protection();
+
+	clk_gate_ops.disable(hw);
+
+	enable_power_domain_write_protection();
+}
+
+static int cclk_gate_is_enabled(struct clk_hw *hw)
+{
+	return clk_gate_ops.is_enabled(hw);
+}
+
+static const struct clk_ops cclk_gate_ops = {
+	.enable		= cclk_gate_enable,
+	.disable	= cclk_gate_disable,
+	.is_enabled	= cclk_gate_is_enabled,
+};
+
+static u8 cclk_mux_get_parent(struct clk_hw *hw)
+{
+	return clk_mux_ops.get_parent(hw);
+}
+
+static int cclk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	int ret;
+
+	disable_power_domain_write_protection();
+
+	sofware_reset_backup_domain();
+
+	ret = clk_mux_ops.set_parent(hw, index);
+
+	enable_power_domain_write_protection();
+
+	return ret;
+}
+
+static const struct clk_ops cclk_mux_ops = {
+	.get_parent = cclk_mux_get_parent,
+	.set_parent = cclk_mux_set_parent,
+};
+
+static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
+		const char * const *parent_names, int num_parents,
+		void __iomem *reg, u8 bit_idx, u8 shift, unsigned long flags,
+		spinlock_t *lock)
+{
+	struct clk_hw *hw;
+	struct clk_gate *gate;
+	struct clk_mux *mux;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate) {
+		hw = ERR_PTR(-EINVAL);
+		goto fail;
+	}
+
+	mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+	if (!mux) {
+		kfree(gate);
+		hw = ERR_PTR(-EINVAL);
+		goto fail;
+	}
+
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = 0;
+	gate->lock = lock;
+
+	mux->reg = reg;
+	mux->shift = shift;
+	mux->mask = 3;
+	mux->flags = 0;
+
+	hw = clk_hw_register_composite(dev, name, parent_names, num_parents,
+			&mux->hw, &cclk_mux_ops,
+			NULL, NULL,
+			&gate->hw, &cclk_gate_ops,
+			flags);
+
+	if (IS_ERR(hw)) {
+		kfree(gate);
+		kfree(mux);
+	}
+
+fail:
+	return hw;
+}
+
 static const char *sys_parents[] __initdata =   { "hsi", NULL, "pll" };
 
 static const struct clk_div_table ahb_div_table[] = {
@@ -308,10 +607,46 @@ static const struct clk_div_table apb_di
 	{ 0 },
 };
 
+static const char *rtc_parents[4] = {
+	"no-clock", "lse", "lsi", "hse-rtc"
+};
+
+struct stm32f4_clk_data {
+	const struct stm32f4_gate_data *gates_data;
+	const u64 *gates_map;
+	int gates_num;
+};
+
+static const struct stm32f4_clk_data stm32f429_clk_data = {
+	.gates_data	= stm32f429_gates,
+	.gates_map	= stm32f42xx_gate_map,
+	.gates_num	= ARRAY_SIZE(stm32f429_gates),
+};
+
+static const struct stm32f4_clk_data stm32f469_clk_data = {
+	.gates_data	= stm32f469_gates,
+	.gates_map	= stm32f46xx_gate_map,
+	.gates_num	= ARRAY_SIZE(stm32f469_gates),
+};
+
+static const struct of_device_id stm32f4_of_match[] = {
+	{
+		.compatible = "st,stm32f42xx-rcc",
+		.data = &stm32f429_clk_data
+	},
+	{
+		.compatible = "st,stm32f469-rcc",
+		.data = &stm32f469_clk_data
+	},
+	{}
+};
+
 static void __init stm32f4_rcc_init(struct device_node *np)
 {
 	const char *hse_clk;
 	int n;
+	const struct of_device_id *match;
+	const struct stm32f4_clk_data *data;
 
 	base = of_iomap(np, 0);
 	if (!base) {
@@ -319,6 +654,25 @@ static void __init stm32f4_rcc_init(stru
 		return;
 	}
 
+	pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+	if (IS_ERR(pdrm)) {
+		pdrm = NULL;
+		pr_warn("%s: Unable to get syscfg\n", __func__);
+	}
+
+	match = of_match_node(stm32f4_of_match, np);
+	if (WARN_ON(!match))
+		return;
+
+	data = match->data;
+
+	clks = kmalloc_array(data->gates_num + END_PRIMARY_CLK,
+			sizeof(*clks), GFP_KERNEL);
+	if (!clks)
+		goto fail;
+
+	stm32f4_gate_map = data->gates_map;
+
 	hse_clk = of_clk_get_parent_name(np, 0);
 
 	clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
@@ -351,11 +705,15 @@ static void __init stm32f4_rcc_init(stru
 	clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
 					       0, 1, 1);
 
-	for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) {
-		const struct stm32f4_gate_data *gd = &stm32f4_gates[n];
-		unsigned int secondary =
-		    8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx;
-		int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
+	for (n = 0; n < data->gates_num; n++) {
+		const struct stm32f4_gate_data *gd;
+		unsigned int secondary;
+		int idx;
+
+		gd = &data->gates_data[n];
+		secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) +
+			gd->bit_idx;
+		idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
 
 		if (idx < 0)
 			goto fail;
@@ -371,9 +729,44 @@ static void __init stm32f4_rcc_init(stru
 		}
 	}
 
+	clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
+			base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock);
+
+	if (IS_ERR(clks[CLK_LSI])) {
+		pr_err("Unable to register lsi clock\n");
+		goto fail;
+	}
+
+	clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
+			base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock);
+
+	if (IS_ERR(clks[CLK_LSE])) {
+		pr_err("Unable to register lse clock\n");
+		goto fail;
+	}
+
+	clks[CLK_HSE_RTC] = clk_hw_register_divider(NULL, "hse-rtc", "clk-hse",
+			0, base + STM32F4_RCC_CFGR, 16, 5, 0,
+			&stm32f4_clk_lock);
+
+	if (IS_ERR(clks[CLK_HSE_RTC])) {
+		pr_err("Unable to register hse-rtc clock\n");
+		goto fail;
+	}
+
+	clks[CLK_RTC] = stm32_register_cclk(NULL, "rtc", rtc_parents, 4,
+			base + STM32F4_RCC_BDCR, 15, 8, 0, &stm32f4_clk_lock);
+
+	if (IS_ERR(clks[CLK_RTC])) {
+		pr_err("Unable to register rtc clock\n");
+		goto fail;
+	}
+
 	of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
 	return;
 fail:
+	kfree(clks);
 	iounmap(base);
 }
-CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
+CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/clk-wm831x.c linux-libre-4.10-rc8-gnu/drivers/clk/clk-wm831x.c
--- linux-libre-4.9-gnu/drivers/clk/clk-wm831x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/clk-wm831x.c	2017-02-12 16:03:20.000000000 -0500
@@ -243,7 +243,7 @@ static int wm831x_clkout_is_prepared(str
 	if (ret < 0) {
 		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
 			ret);
-		return true;
+		return false;
 	}
 
 	return (ret & WM831X_CLKOUT_ENA) != 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/hisilicon/crg.h linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/crg.h
--- linux-libre-4.9-gnu/drivers/clk/hisilicon/crg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/crg.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * HiSilicon Clock and Reset Driver Header
+ *
+ * Copyright (c) 2016 HiSilicon 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.
+ */
+
+#ifndef __HISI_CRG_H
+#define __HISI_CRG_H
+
+struct hisi_clock_data;
+struct hisi_reset_controller;
+
+struct hisi_crg_funcs {
+	struct hisi_clock_data*	(*register_clks)(struct platform_device *pdev);
+	void (*unregister_clks)(struct platform_device *pdev);
+};
+
+struct hisi_crg_dev {
+	struct hisi_clock_data *clk_data;
+	struct hisi_reset_controller *rstc;
+	const struct hisi_crg_funcs *funcs;
+};
+
+#endif	/* __HISI_CRG_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/hisilicon/crg-hi3516cv300.c linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/crg-hi3516cv300.c
--- linux-libre-4.9-gnu/drivers/clk/hisilicon/crg-hi3516cv300.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/crg-hi3516cv300.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,330 @@
+/*
+ * Hi3516CV300 Clock and Reset Generator Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 <dt-bindings/clock/hi3516cv300-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "crg.h"
+#include "reset.h"
+
+/* hi3516CV300 core CRG */
+#define HI3516CV300_INNER_CLK_OFFSET	64
+#define HI3516CV300_FIXED_3M		65
+#define HI3516CV300_FIXED_6M		66
+#define HI3516CV300_FIXED_24M		67
+#define HI3516CV300_FIXED_49P5		68
+#define HI3516CV300_FIXED_50M		69
+#define HI3516CV300_FIXED_83P3M		70
+#define HI3516CV300_FIXED_99M		71
+#define HI3516CV300_FIXED_100M		72
+#define HI3516CV300_FIXED_148P5M	73
+#define HI3516CV300_FIXED_198M		74
+#define HI3516CV300_FIXED_297M		75
+#define HI3516CV300_UART_MUX		76
+#define HI3516CV300_FMC_MUX		77
+#define HI3516CV300_MMC0_MUX		78
+#define HI3516CV300_MMC1_MUX		79
+#define HI3516CV300_MMC2_MUX		80
+#define HI3516CV300_MMC3_MUX		81
+#define HI3516CV300_PWM_MUX		82
+#define HI3516CV300_CRG_NR_CLKS		128
+
+static const struct hisi_fixed_rate_clock hi3516cv300_fixed_rate_clks[] = {
+	{ HI3516CV300_FIXED_3M, "3m", NULL, 0, 3000000, },
+	{ HI3516CV300_FIXED_6M, "6m", NULL, 0, 6000000, },
+	{ HI3516CV300_FIXED_24M, "24m", NULL, 0, 24000000, },
+	{ HI3516CV300_FIXED_49P5, "49.5m", NULL, 0, 49500000, },
+	{ HI3516CV300_FIXED_50M, "50m", NULL, 0, 50000000, },
+	{ HI3516CV300_FIXED_83P3M, "83.3m", NULL, 0, 83300000, },
+	{ HI3516CV300_FIXED_99M, "99m", NULL, 0, 99000000, },
+	{ HI3516CV300_FIXED_100M, "100m", NULL, 0, 100000000, },
+	{ HI3516CV300_FIXED_148P5M, "148.5m", NULL, 0, 148500000, },
+	{ HI3516CV300_FIXED_198M, "198m", NULL, 0, 198000000, },
+	{ HI3516CV300_FIXED_297M, "297m", NULL, 0, 297000000, },
+	{ HI3516CV300_APB_CLK, "apb", NULL, 0, 50000000, },
+};
+
+static const char *const uart_mux_p[] = {"24m", "6m"};
+static const char *const fmc_mux_p[] = {
+	"24m", "83.3m", "148.5m", "198m", "297m"
+};
+static const char *const mmc_mux_p[] = {"49.5m"};
+static const char *const mmc2_mux_p[] = {"99m", "49.5m"};
+static const char *const pwm_mux_p[] = {"3m", "50m", "24m", "24m"};
+
+static u32 uart_mux_table[] = {0, 1};
+static u32 fmc_mux_table[] = {0, 1, 2, 3, 4};
+static u32 mmc_mux_table[] = {0};
+static u32 mmc2_mux_table[] = {0, 2};
+static u32 pwm_mux_table[] = {0, 1, 2, 3};
+
+static const struct hisi_mux_clock hi3516cv300_mux_clks[] = {
+	{ HI3516CV300_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
+		CLK_SET_RATE_PARENT, 0xe4, 19, 1, 0, uart_mux_table, },
+	{ HI3516CV300_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
+		CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, },
+	{ HI3516CV300_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+		CLK_SET_RATE_PARENT, 0xc4, 4, 2, 0, mmc_mux_table, },
+	{ HI3516CV300_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+		CLK_SET_RATE_PARENT, 0xc4, 12, 2, 0, mmc_mux_table, },
+	{ HI3516CV300_MMC2_MUX, "mmc2_mux", mmc2_mux_p, ARRAY_SIZE(mmc2_mux_p),
+		CLK_SET_RATE_PARENT, 0xc4, 20, 2, 0, mmc2_mux_table, },
+	{ HI3516CV300_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+		CLK_SET_RATE_PARENT, 0xc8, 4, 2, 0, mmc_mux_table, },
+	{ HI3516CV300_PWM_MUX, "pwm_mux", pwm_mux_p, ARRAY_SIZE(pwm_mux_p),
+		CLK_SET_RATE_PARENT, 0x38, 2, 2, 0, pwm_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3516cv300_gate_clks[] = {
+
+	{ HI3516CV300_UART0_CLK, "clk_uart0", "uart_mux", CLK_SET_RATE_PARENT,
+		0xe4, 15, 0, },
+	{ HI3516CV300_UART1_CLK, "clk_uart1", "uart_mux", CLK_SET_RATE_PARENT,
+		0xe4, 16, 0, },
+	{ HI3516CV300_UART2_CLK, "clk_uart2", "uart_mux", CLK_SET_RATE_PARENT,
+		0xe4, 17, 0, },
+
+	{ HI3516CV300_SPI0_CLK, "clk_spi0", "100m", CLK_SET_RATE_PARENT,
+		0xe4, 13, 0, },
+	{ HI3516CV300_SPI1_CLK, "clk_spi1", "100m", CLK_SET_RATE_PARENT,
+		0xe4, 14, 0, },
+
+	{ HI3516CV300_FMC_CLK, "clk_fmc", "fmc_mux", CLK_SET_RATE_PARENT,
+		0xc0, 1, 0, },
+	{ HI3516CV300_MMC0_CLK, "clk_mmc0", "mmc0_mux", CLK_SET_RATE_PARENT,
+		0xc4, 1, 0, },
+	{ HI3516CV300_MMC1_CLK, "clk_mmc1", "mmc1_mux", CLK_SET_RATE_PARENT,
+		0xc4, 9, 0, },
+	{ HI3516CV300_MMC2_CLK, "clk_mmc2", "mmc2_mux", CLK_SET_RATE_PARENT,
+		0xc4, 17, 0, },
+	{ HI3516CV300_MMC3_CLK, "clk_mmc3", "mmc3_mux", CLK_SET_RATE_PARENT,
+		0xc8, 1, 0, },
+
+	{ HI3516CV300_ETH_CLK, "clk_eth", NULL, 0, 0xec, 1, 0, },
+
+	{ HI3516CV300_DMAC_CLK, "clk_dmac", NULL, 0, 0xd8, 5, 0, },
+	{ HI3516CV300_PWM_CLK, "clk_pwm", "pwm_mux", CLK_SET_RATE_PARENT,
+		0x38, 1, 0, },
+
+	{ HI3516CV300_USB2_BUS_CLK, "clk_usb2_bus", NULL, 0, 0xb8, 0, 0, },
+	{ HI3516CV300_USB2_OHCI48M_CLK, "clk_usb2_ohci48m", NULL, 0,
+		0xb8, 1, 0, },
+	{ HI3516CV300_USB2_OHCI12M_CLK, "clk_usb2_ohci12m", NULL, 0,
+		0xb8, 2, 0, },
+	{ HI3516CV300_USB2_OTG_UTMI_CLK, "clk_usb2_otg_utmi", NULL, 0,
+		0xb8, 3, 0, },
+	{ HI3516CV300_USB2_HST_PHY_CLK, "clk_usb2_hst_phy", NULL, 0,
+		0xb8, 4, 0, },
+	{ HI3516CV300_USB2_UTMI0_CLK, "clk_usb2_utmi0", NULL, 0, 0xb8, 5, 0, },
+	{ HI3516CV300_USB2_PHY_CLK, "clk_usb2_phy", NULL, 0, 0xb8, 7, 0, },
+};
+
+static struct hisi_clock_data *hi3516cv300_clk_register(
+		struct platform_device *pdev)
+{
+	struct hisi_clock_data *clk_data;
+	int ret;
+
+	clk_data = hisi_clk_alloc(pdev, HI3516CV300_CRG_NR_CLKS);
+	if (!clk_data)
+		return ERR_PTR(-ENOMEM);
+
+	ret = hisi_clk_register_fixed_rate(hi3516cv300_fixed_rate_clks,
+			ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = hisi_clk_register_mux(hi3516cv300_mux_clks,
+			ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
+	if (ret)
+		goto unregister_fixed_rate;
+
+	ret = hisi_clk_register_gate(hi3516cv300_gate_clks,
+			ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
+	if (ret)
+		goto unregister_mux;
+
+	ret = of_clk_add_provider(pdev->dev.of_node,
+			of_clk_src_onecell_get, &clk_data->clk_data);
+	if (ret)
+		goto unregister_gate;
+
+	return clk_data;
+
+unregister_gate:
+	hisi_clk_unregister_gate(hi3516cv300_gate_clks,
+				ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
+unregister_mux:
+	hisi_clk_unregister_mux(hi3516cv300_mux_clks,
+			ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
+unregister_fixed_rate:
+	hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
+			ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
+	return ERR_PTR(ret);
+}
+
+static void hi3516cv300_clk_unregister(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	hisi_clk_unregister_gate(hi3516cv300_gate_clks,
+			ARRAY_SIZE(hi3516cv300_gate_clks), crg->clk_data);
+	hisi_clk_unregister_mux(hi3516cv300_mux_clks,
+			ARRAY_SIZE(hi3516cv300_mux_clks), crg->clk_data);
+	hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
+			ARRAY_SIZE(hi3516cv300_fixed_rate_clks), crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
+	.register_clks = hi3516cv300_clk_register,
+	.unregister_clks = hi3516cv300_clk_unregister,
+};
+
+/* hi3516CV300 sysctrl CRG */
+#define HI3516CV300_SYSCTRL_NR_CLKS 16
+
+static const char *wdt_mux_p[] __initconst = { "3m", "apb" };
+static u32 wdt_mux_table[] = {0, 1};
+
+static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
+	{ HI3516CV300_WDT_CLK, "wdt", wdt_mux_p, ARRAY_SIZE(wdt_mux_p),
+		CLK_SET_RATE_PARENT, 0x0, 23, 1, 0, wdt_mux_table, },
+};
+
+static struct hisi_clock_data *hi3516cv300_sysctrl_clk_register(
+		struct platform_device *pdev)
+{
+	struct hisi_clock_data *clk_data;
+	int ret;
+
+	clk_data = hisi_clk_alloc(pdev, HI3516CV300_SYSCTRL_NR_CLKS);
+	if (!clk_data)
+		return ERR_PTR(-ENOMEM);
+
+	ret = hisi_clk_register_mux(hi3516cv300_sysctrl_mux_clks,
+			ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
+	if (ret)
+		return ERR_PTR(ret);
+
+
+	ret = of_clk_add_provider(pdev->dev.of_node,
+			of_clk_src_onecell_get, &clk_data->clk_data);
+	if (ret)
+		goto unregister_mux;
+
+	return clk_data;
+
+unregister_mux:
+	hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
+			ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
+	return ERR_PTR(ret);
+}
+
+static void hi3516cv300_sysctrl_clk_unregister(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
+			ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
+			crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3516cv300_sysctrl_funcs = {
+	.register_clks = hi3516cv300_sysctrl_clk_register,
+	.unregister_clks = hi3516cv300_sysctrl_clk_unregister,
+};
+
+static const struct of_device_id hi3516cv300_crg_match_table[] = {
+	{
+		.compatible = "hisilicon,hi3516cv300-crg",
+		.data = &hi3516cv300_crg_funcs
+	},
+	{
+		.compatible = "hisilicon,hi3516cv300-sysctrl",
+		.data = &hi3516cv300_sysctrl_funcs
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hi3516cv300_crg_match_table);
+
+static int hi3516cv300_crg_probe(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg;
+
+	crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
+	if (!crg)
+		return -ENOMEM;
+
+	crg->funcs = of_device_get_match_data(&pdev->dev);
+	if (!crg->funcs)
+		return -ENOENT;
+
+	crg->rstc = hisi_reset_init(pdev);
+	if (!crg->rstc)
+		return -ENOMEM;
+
+	crg->clk_data = crg->funcs->register_clks(pdev);
+	if (IS_ERR(crg->clk_data)) {
+		hisi_reset_exit(crg->rstc);
+		return PTR_ERR(crg->clk_data);
+	}
+
+	platform_set_drvdata(pdev, crg);
+	return 0;
+}
+
+static int hi3516cv300_crg_remove(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+	hisi_reset_exit(crg->rstc);
+	crg->funcs->unregister_clks(pdev);
+	return 0;
+}
+
+static struct platform_driver hi3516cv300_crg_driver = {
+	.probe          = hi3516cv300_crg_probe,
+	.remove		= hi3516cv300_crg_remove,
+	.driver         = {
+		.name   = "hi3516cv300-crg",
+		.of_match_table = hi3516cv300_crg_match_table,
+	},
+};
+
+static int __init hi3516cv300_crg_init(void)
+{
+	return platform_driver_register(&hi3516cv300_crg_driver);
+}
+core_initcall(hi3516cv300_crg_init);
+
+static void __exit hi3516cv300_crg_exit(void)
+{
+	platform_driver_unregister(&hi3516cv300_crg_driver);
+}
+module_exit(hi3516cv300_crg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3516CV300 CRG Driver");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/hisilicon/crg-hi3798cv200.c linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/crg-hi3798cv200.c
--- linux-libre-4.9-gnu/drivers/clk/hisilicon/crg-hi3798cv200.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/crg-hi3798cv200.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,337 @@
+/*
+ * Hi3798CV200 Clock and Reset Generator Driver
+ *
+ * Copyright (c) 2016 HiSilicon Technologies 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 <dt-bindings/clock/histb-clock.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include "clk.h"
+#include "crg.h"
+#include "reset.h"
+
+/* hi3798CV200 core CRG */
+#define HI3798CV200_INNER_CLK_OFFSET	64
+#define HI3798CV200_FIXED_24M	65
+#define HI3798CV200_FIXED_25M	66
+#define HI3798CV200_FIXED_50M	67
+#define HI3798CV200_FIXED_75M	68
+#define HI3798CV200_FIXED_100M	69
+#define HI3798CV200_FIXED_150M	70
+#define HI3798CV200_FIXED_200M	71
+#define HI3798CV200_FIXED_250M	72
+#define HI3798CV200_FIXED_300M	73
+#define HI3798CV200_FIXED_400M	74
+#define HI3798CV200_MMC_MUX	75
+#define HI3798CV200_ETH_PUB_CLK	76
+#define HI3798CV200_ETH_BUS_CLK	77
+#define HI3798CV200_ETH_BUS0_CLK	78
+#define HI3798CV200_ETH_BUS1_CLK	79
+#define HI3798CV200_COMBPHY1_MUX	80
+
+#define HI3798CV200_CRG_NR_CLKS		128
+
+static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
+	{ HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
+	{ HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
+	{ HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },
+	{ HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },
+	{ HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },
+	{ HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },
+	{ HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
+	{ HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
+	{ HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
+	{ HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
+	{ HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
+};
+
+static const char *const mmc_mux_p[] = {
+		"100m", "50m", "25m", "200m", "150m" };
+static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};
+
+static const char *const comphy1_mux_p[] = {
+		"100m", "25m"};
+static u32 comphy1_mux_table[] = {2, 3};
+
+static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
+	{ HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
+		CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
+	{ HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
+		comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p),
+		CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, },
+};
+
+static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
+	/* UART */
+	{ HISTB_UART2_CLK, "clk_uart2", "75m",
+		CLK_SET_RATE_PARENT, 0x68, 4, 0, },
+	/* I2C */
+	{ HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",
+		CLK_SET_RATE_PARENT, 0x6C, 4, 0, },
+	{ HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",
+		CLK_SET_RATE_PARENT, 0x6C, 8, 0, },
+	{ HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",
+		CLK_SET_RATE_PARENT, 0x6C, 12, 0, },
+	{ HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",
+		CLK_SET_RATE_PARENT, 0x6C, 16, 0, },
+	{ HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",
+		CLK_SET_RATE_PARENT, 0x6C, 20, 0, },
+	/* SPI */
+	{ HISTB_SPI0_CLK, "clk_spi0", "clk_apb",
+		CLK_SET_RATE_PARENT, 0x70, 0, 0, },
+	/* SDIO */
+	{ HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
+			CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
+	{ HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "mmc_mux",
+		CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
+	/* EMMC */
+	{ HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",
+		CLK_SET_RATE_PARENT, 0xa0, 0, 0, },
+	{ HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",
+		CLK_SET_RATE_PARENT, 0xa0, 1, 0, },
+	/* PCIE*/
+	{ HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",
+		CLK_SET_RATE_PARENT, 0x18c, 0, 0, },
+	{ HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",
+		CLK_SET_RATE_PARENT, 0x18c, 1, 0, },
+	{ HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",
+		CLK_SET_RATE_PARENT, 0x18c, 2, 0, },
+	{ HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",
+		CLK_SET_RATE_PARENT, 0x18c, 3, 0, },
+	/* Ethernet */
+	{ HI3798CV200_ETH_PUB_CLK, "clk_pub", NULL,
+		CLK_SET_RATE_PARENT, 0xcc, 5, 0, },
+	{ HI3798CV200_ETH_BUS_CLK, "clk_bus", "clk_pub",
+		CLK_SET_RATE_PARENT, 0xcc, 0, 0, },
+	{ HI3798CV200_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",
+		CLK_SET_RATE_PARENT, 0xcc, 1, 0, },
+	{ HI3798CV200_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",
+		CLK_SET_RATE_PARENT, 0xcc, 2, 0, },
+	{ HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",
+		CLK_SET_RATE_PARENT, 0xcc, 3, 0, },
+	{ HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",
+		CLK_SET_RATE_PARENT, 0xcc, 24, 0, },
+	{ HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",
+		CLK_SET_RATE_PARENT, 0xcc, 4, 0, },
+	{ HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",
+		CLK_SET_RATE_PARENT, 0xcc, 25, 0, },
+	/* COMBPHY1 */
+	{ HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",
+		CLK_SET_RATE_PARENT, 0x188, 8, 0, },
+};
+
+static struct hisi_clock_data *hi3798cv200_clk_register(
+				struct platform_device *pdev)
+{
+	struct hisi_clock_data *clk_data;
+	int ret;
+
+	clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);
+	if (!clk_data)
+		return ERR_PTR(-ENOMEM);
+
+	ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
+				     ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+				     clk_data);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = hisi_clk_register_mux(hi3798cv200_mux_clks,
+				ARRAY_SIZE(hi3798cv200_mux_clks),
+				clk_data);
+	if (ret)
+		goto unregister_fixed_rate;
+
+	ret = hisi_clk_register_gate(hi3798cv200_gate_clks,
+				ARRAY_SIZE(hi3798cv200_gate_clks),
+				clk_data);
+	if (ret)
+		goto unregister_mux;
+
+	ret = of_clk_add_provider(pdev->dev.of_node,
+			of_clk_src_onecell_get, &clk_data->clk_data);
+	if (ret)
+		goto unregister_gate;
+
+	return clk_data;
+
+unregister_fixed_rate:
+	hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
+				ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+				clk_data);
+
+unregister_mux:
+	hisi_clk_unregister_mux(hi3798cv200_mux_clks,
+				ARRAY_SIZE(hi3798cv200_mux_clks),
+				clk_data);
+unregister_gate:
+	hisi_clk_unregister_gate(hi3798cv200_gate_clks,
+				ARRAY_SIZE(hi3798cv200_gate_clks),
+				clk_data);
+	return ERR_PTR(ret);
+}
+
+static void hi3798cv200_clk_unregister(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	hisi_clk_unregister_gate(hi3798cv200_gate_clks,
+				ARRAY_SIZE(hi3798cv200_gate_clks),
+				crg->clk_data);
+	hisi_clk_unregister_mux(hi3798cv200_mux_clks,
+				ARRAY_SIZE(hi3798cv200_mux_clks),
+				crg->clk_data);
+	hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
+				ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+				crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
+	.register_clks = hi3798cv200_clk_register,
+	.unregister_clks = hi3798cv200_clk_unregister,
+};
+
+/* hi3798CV200 sysctrl CRG */
+
+#define HI3798CV200_SYSCTRL_NR_CLKS 16
+
+static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
+	{ HISTB_IR_CLK, "clk_ir", "100m",
+		CLK_SET_RATE_PARENT, 0x48, 4, 0, },
+	{ HISTB_TIMER01_CLK, "clk_timer01", "24m",
+		CLK_SET_RATE_PARENT, 0x48, 6, 0, },
+	{ HISTB_UART0_CLK, "clk_uart0", "75m",
+		CLK_SET_RATE_PARENT, 0x48, 10, 0, },
+};
+
+static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(
+					struct platform_device *pdev)
+{
+	struct hisi_clock_data *clk_data;
+	int ret;
+
+	clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);
+	if (!clk_data)
+		return ERR_PTR(-ENOMEM);
+
+	ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,
+				ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+				clk_data);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = of_clk_add_provider(pdev->dev.of_node,
+			of_clk_src_onecell_get, &clk_data->clk_data);
+	if (ret)
+		goto unregister_gate;
+
+	return clk_data;
+
+unregister_gate:
+	hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
+				ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+				clk_data);
+	return ERR_PTR(ret);
+}
+
+static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
+				ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
+				crg->clk_data);
+}
+
+static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {
+	.register_clks = hi3798cv200_sysctrl_clk_register,
+	.unregister_clks = hi3798cv200_sysctrl_clk_unregister,
+};
+
+static const struct of_device_id hi3798cv200_crg_match_table[] = {
+	{ .compatible = "hisilicon,hi3798cv200-crg",
+		.data = &hi3798cv200_crg_funcs },
+	{ .compatible = "hisilicon,hi3798cv200-sysctrl",
+		.data = &hi3798cv200_sysctrl_funcs },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);
+
+static int hi3798cv200_crg_probe(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg;
+
+	crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
+	if (!crg)
+		return -ENOMEM;
+
+	crg->funcs = of_device_get_match_data(&pdev->dev);
+	if (!crg->funcs)
+		return -ENOENT;
+
+	crg->rstc = hisi_reset_init(pdev);
+	if (!crg->rstc)
+		return -ENOMEM;
+
+	crg->clk_data = crg->funcs->register_clks(pdev);
+	if (IS_ERR(crg->clk_data)) {
+		hisi_reset_exit(crg->rstc);
+		return PTR_ERR(crg->clk_data);
+	}
+
+	platform_set_drvdata(pdev, crg);
+	return 0;
+}
+
+static int hi3798cv200_crg_remove(struct platform_device *pdev)
+{
+	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+	hisi_reset_exit(crg->rstc);
+	crg->funcs->unregister_clks(pdev);
+	return 0;
+}
+
+static struct platform_driver hi3798cv200_crg_driver = {
+	.probe          = hi3798cv200_crg_probe,
+	.remove		= hi3798cv200_crg_remove,
+	.driver         = {
+		.name   = "hi3798cv200-crg",
+		.of_match_table = hi3798cv200_crg_match_table,
+	},
+};
+
+static int __init hi3798cv200_crg_init(void)
+{
+	return platform_driver_register(&hi3798cv200_crg_driver);
+}
+core_initcall(hi3798cv200_crg_init);
+
+static void __exit hi3798cv200_crg_exit(void)
+{
+	platform_driver_unregister(&hi3798cv200_crg_driver);
+}
+module_exit(hi3798cv200_crg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/hisilicon/Kconfig linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/Kconfig
--- linux-libre-4.9-gnu/drivers/clk/hisilicon/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,11 @@
+config COMMON_CLK_HI3516CV300
+	tristate "HI3516CV300 Clock Driver"
+	depends on ARCH_HISI || COMPILE_TEST
+	select RESET_HISI
+	default ARCH_HISI
+	help
+	  Build the clock driver for hi3516cv300.
+
 config COMMON_CLK_HI3519
 	tristate "Hi3519 Clock Driver"
 	depends on ARCH_HISI || COMPILE_TEST
@@ -6,6 +14,14 @@ config COMMON_CLK_HI3519
 	help
 	  Build the clock driver for hi3519.
 
+config COMMON_CLK_HI3798CV200
+	tristate "Hi3798CV200 Clock Driver"
+	depends on ARCH_HISI || COMPILE_TEST
+	select RESET_HISI
+	default ARCH_HISI
+	help
+	  Build the clock driver for hi3798cv200.
+
 config COMMON_CLK_HI6220
 	bool "Hi6220 Clock Driver"
 	depends on ARCH_HISI || COMPILE_TEST
@@ -23,5 +39,6 @@ config RESET_HISI
 config STUB_CLK_HI6220
 	bool "Hi6220 Stub Clock Driver"
 	depends on COMMON_CLK_HI6220 && MAILBOX
+	default ARCH_HISI
 	help
 	  Build the Hisilicon Hi6220 stub clock driver.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/hisilicon/Makefile linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/Makefile
--- linux-libre-4.9-gnu/drivers/clk/hisilicon/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/hisilicon/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,9 @@ obj-y	+= clk.o clkgate-separated.o clkdi
 obj-$(CONFIG_ARCH_HI3xxx)	+= clk-hi3620.o
 obj-$(CONFIG_ARCH_HIP04)	+= clk-hip04.o
 obj-$(CONFIG_ARCH_HIX5HD2)	+= clk-hix5hd2.o
+obj-$(CONFIG_COMMON_CLK_HI3516CV300)	+= crg-hi3516cv300.o
 obj-$(CONFIG_COMMON_CLK_HI3519)	+= clk-hi3519.o
+obj-$(CONFIG_COMMON_CLK_HI3798CV200)	+= crg-hi3798cv200.o
 obj-$(CONFIG_COMMON_CLK_HI6220)	+= clk-hi6220.o
 obj-$(CONFIG_RESET_HISI)	+= reset.o
 obj-$(CONFIG_STUB_CLK_HI6220)	+= clk-hi6220-stub.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/imx/clk.h linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk.h
--- linux-libre-4.9-gnu/drivers/clk/imx/clk.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk.h	2017-02-12 16:03:20.000000000 -0500
@@ -75,6 +75,14 @@ static inline struct clk *imx_clk_fixed(
 	return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
 }
 
+static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg,
+		u8 shift, u8 width, const char **parents, int num_parents)
+{
+	return clk_register_mux(NULL, name, parents, num_parents,
+			CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, reg,
+			shift, width, CLK_MUX_READ_ONLY, &imx_ccm_lock);
+}
+
 static inline struct clk *imx_clk_fixed_factor(const char *name,
 		const char *parent, unsigned int mult, unsigned int div)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/imx/clk-imx31.c linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-imx31.c
--- linux-libre-4.9-gnu/drivers/clk/imx/clk-imx31.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-imx31.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <soc/imx/revision.h>
 #include <soc/imx/timer.h>
 #include <asm/irq.h>
@@ -72,14 +73,8 @@ static struct clk ** const uart_clks[] _
 	NULL
 };
 
-static void __init _mx31_clocks_init(unsigned long fref)
+static void __init _mx31_clocks_init(void __iomem *base, unsigned long fref)
 {
-	void __iomem *base;
-	struct device_node *np;
-
-	base = ioremap(MX31_CCM_BASE_ADDR, SZ_4K);
-	BUG_ON(!base);
-
 	clk[dummy] = imx_clk_fixed("dummy", 0);
 	clk[ckih] = imx_clk_fixed("ckih", fref);
 	clk[ckil] = imx_clk_fixed("ckil", 32768);
@@ -147,21 +142,17 @@ static void __init _mx31_clocks_init(uns
 	clk_prepare_enable(clk[iim_gate]);
 	mx31_revision();
 	clk_disable_unprepare(clk[iim_gate]);
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
-
-	if (np) {
-		clk_data.clks = clk;
-		clk_data.clk_num = ARRAY_SIZE(clk);
-		of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
-	}
 }
 
-int __init mx31_clocks_init(void)
+int __init mx31_clocks_init(unsigned long fref)
 {
-	u32 fref = 26000000; /* default */
+	void __iomem *base;
 
-	_mx31_clocks_init(fref);
+	base = ioremap(MX31_CCM_BASE_ADDR, SZ_4K);
+	if (!base)
+		panic("%s: failed to map registers\n", __func__);
+
+	_mx31_clocks_init(base, fref);
 
 	clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
 	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
@@ -224,22 +215,31 @@ int __init mx31_clocks_init(void)
 	return 0;
 }
 
-int __init mx31_clocks_init_dt(void)
+static void __init mx31_clocks_init_dt(struct device_node *np)
 {
-	struct device_node *np;
+	struct device_node *osc_np;
 	u32 fref = 26000000; /* default */
+	void __iomem *ccm;
 
-	for_each_compatible_node(np, NULL, "fixed-clock") {
-		if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
+	for_each_compatible_node(osc_np, NULL, "fixed-clock") {
+		if (!of_device_is_compatible(osc_np, "fsl,imx-osc26m"))
 			continue;
 
-		if (!of_property_read_u32(np, "clock-frequency", &fref)) {
-			of_node_put(np);
+		if (!of_property_read_u32(osc_np, "clock-frequency", &fref)) {
+			of_node_put(osc_np);
 			break;
 		}
 	}
 
-	_mx31_clocks_init(fref);
+	ccm = of_iomap(np, 0);
+	if (!ccm)
+		panic("%s: failed to map registers\n", __func__);
 
-	return 0;
+	_mx31_clocks_init(ccm, fref);
+
+	clk_data.clks = clk;
+	clk_data.clk_num = ARRAY_SIZE(clk);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 }
+
+CLK_OF_DECLARE(imx31_ccm, "fsl,imx31-ccm", mx31_clocks_init_dt);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/imx/clk-imx6q.c linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-imx6q.c
--- linux-libre-4.9-gnu/drivers/clk/imx/clk-imx6q.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-imx6q.c	2017-02-12 16:03:20.000000000 -0500
@@ -156,10 +156,267 @@ static struct clk ** const uart_clks[] _
 	NULL
 };
 
+static int ldb_di_sel_by_clock_id(int clock_id)
+{
+	switch (clock_id) {
+	case IMX6QDL_CLK_PLL5_VIDEO_DIV:
+		if (clk_on_imx6q() &&
+		    imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
+			return -ENOENT;
+		return 0;
+	case IMX6QDL_CLK_PLL2_PFD0_352M:
+		return 1;
+	case IMX6QDL_CLK_PLL2_PFD2_396M:
+		return 2;
+	case IMX6QDL_CLK_MMDC_CH1_AXI:
+		return 3;
+	case IMX6QDL_CLK_PLL3_USB_OTG:
+		return 4;
+	default:
+		return -ENOENT;
+	}
+}
+
+static void of_assigned_ldb_sels(struct device_node *node,
+				 unsigned int *ldb_di0_sel,
+				 unsigned int *ldb_di1_sel)
+{
+	struct of_phandle_args clkspec;
+	int index, rc, num_parents;
+	int parent, child, sel;
+
+	num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+						 "#clock-cells");
+	for (index = 0; index < num_parents; index++) {
+		rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+					"#clock-cells", index, &clkspec);
+		if (rc < 0) {
+			/* skip empty (null) phandles */
+			if (rc == -ENOENT)
+				continue;
+			else
+				return;
+		}
+		if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+			pr_err("ccm: parent clock %d not in ccm\n", index);
+			return;
+		}
+		parent = clkspec.args[0];
+
+		rc = of_parse_phandle_with_args(node, "assigned-clocks",
+				"#clock-cells", index, &clkspec);
+		if (rc < 0)
+			return;
+		if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+			pr_err("ccm: child clock %d not in ccm\n", index);
+			return;
+		}
+		child = clkspec.args[0];
+
+		if (child != IMX6QDL_CLK_LDB_DI0_SEL &&
+		    child != IMX6QDL_CLK_LDB_DI1_SEL)
+			continue;
+
+		sel = ldb_di_sel_by_clock_id(parent);
+		if (sel < 0) {
+			pr_err("ccm: invalid ldb_di%d parent clock: %d\n",
+			       child == IMX6QDL_CLK_LDB_DI1_SEL, parent);
+			continue;
+		}
+
+		if (child == IMX6QDL_CLK_LDB_DI0_SEL)
+			*ldb_di0_sel = sel;
+		if (child == IMX6QDL_CLK_LDB_DI1_SEL)
+			*ldb_di1_sel = sel;
+	}
+}
+
+#define CCM_CCDR		0x04
+#define CCM_CCSR		0x0c
+#define CCM_CS2CDR		0x2c
+
+#define CCDR_MMDC_CH1_MASK		BIT(16)
+#define CCSR_PLL3_SW_CLK_SEL		BIT(0)
+
+#define CS2CDR_LDB_DI0_CLK_SEL_SHIFT	9
+#define CS2CDR_LDB_DI1_CLK_SEL_SHIFT	12
+
+static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
+{
+	unsigned int reg;
+
+	reg = readl_relaxed(ccm_base + CCM_CCDR);
+	reg |= CCDR_MMDC_CH1_MASK;
+	writel_relaxed(reg, ccm_base + CCM_CCDR);
+}
+
+/*
+ * The only way to disable the MMDC_CH1 clock is to move it to pll3_sw_clk
+ * via periph2_clk2_sel and then to disable pll3_sw_clk by selecting the
+ * bypass clock source, since there is no CG bit for mmdc_ch1.
+ */
+static void mmdc_ch1_disable(void __iomem *ccm_base)
+{
+	unsigned int reg;
+
+	clk_set_parent(clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL],
+		       clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+
+	/*
+	 * Handshake with mmdc_ch1 module must be masked when changing
+	 * periph2_clk_sel.
+	 */
+	clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_CLK2]);
+
+	/* Disable pll3_sw_clk by selecting the bypass clock source */
+	reg = readl_relaxed(ccm_base + CCM_CCSR);
+	reg |= CCSR_PLL3_SW_CLK_SEL;
+	writel_relaxed(reg, ccm_base + CCM_CCSR);
+}
+
+static void mmdc_ch1_reenable(void __iomem *ccm_base)
+{
+	unsigned int reg;
+
+	/* Enable pll3_sw_clk by disabling the bypass */
+	reg = readl_relaxed(ccm_base + CCM_CCSR);
+	reg &= ~CCSR_PLL3_SW_CLK_SEL;
+	writel_relaxed(reg, ccm_base + CCM_CCSR);
+
+	clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_PRE]);
+}
+
+/*
+ * We have to follow a strict procedure when changing the LDB clock source,
+ * otherwise we risk introducing a glitch that can lock up the LDB divider.
+ * Things to keep in mind:
+ *
+ * 1. The current and new parent clock inputs to the mux must be disabled.
+ * 2. The default clock input for ldb_di0/1_clk_sel is mmdc_ch1_axi, which
+ *    has no CG bit.
+ * 3. pll2_pfd2_396m can not be gated if it is used as memory clock.
+ * 4. In the RTL implementation of the LDB_DI_CLK_SEL muxes the top four
+ *    options are in one mux and the PLL3 option along with three unused
+ *    inputs is in a second mux. There is a third mux with two inputs used
+ *    to decide between the first and second 4-port mux:
+ *
+ *    pll5_video_div 0 --|\
+ *    pll2_pfd0_352m 1 --| |_
+ *    pll2_pfd2_396m 2 --| | `-|\
+ *    mmdc_ch1_axi   3 --|/    | |
+ *                             | |--
+ *    pll3_usb_otg   4 --|\    | |
+ *                   5 --| |_,-|/
+ *                   6 --| |
+ *                   7 --|/
+ *
+ * The ldb_di0/1_clk_sel[1:0] bits control both 4-port muxes at the same time.
+ * The ldb_di0/1_clk_sel[2] bit controls the 2-port mux. The code below
+ * switches the parent to the bottom mux first and then manipulates the top
+ * mux to ensure that no glitch will enter the divider.
+ */
+static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base)
+{
+	unsigned int reg;
+	unsigned int sel[2][4];
+	int i;
+
+	reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+	sel[0][0] = (reg >> CS2CDR_LDB_DI0_CLK_SEL_SHIFT) & 7;
+	sel[1][0] = (reg >> CS2CDR_LDB_DI1_CLK_SEL_SHIFT) & 7;
+
+	sel[0][3] = sel[0][2] = sel[0][1] = sel[0][0];
+	sel[1][3] = sel[1][2] = sel[1][1] = sel[1][0];
+
+	of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]);
+
+	for (i = 0; i < 2; i++) {
+		/* Warn if a glitch might have been introduced already */
+		if (sel[i][0] != 3) {
+			pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n",
+				i, sel[i][0]);
+		}
+
+		if (sel[i][0] == sel[i][3])
+			continue;
+
+		/* Only switch to or from pll2_pfd2_396m if it is disabled */
+		if ((sel[i][0] == 2 || sel[i][3] == 2) &&
+		    (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+		     clk[IMX6QDL_CLK_PLL2_PFD2_396M])) {
+			pr_err("ccm: ldb_di%d_sel: couldn't disable pll2_pfd2_396m\n",
+			       i);
+			sel[i][3] = sel[i][2] = sel[i][1] = sel[i][0];
+			continue;
+		}
+
+		/* First switch to the bottom mux */
+		sel[i][1] = sel[i][0] | 4;
+
+		/* Then configure the top mux before switching back to it */
+		sel[i][2] = sel[i][3] | 4;
+
+		pr_debug("ccm: switching ldb_di%d_sel: %d->%d->%d->%d\n", i,
+			 sel[i][0], sel[i][1], sel[i][2], sel[i][3]);
+	}
+
+	if (sel[0][0] == sel[0][3] && sel[1][0] == sel[1][3])
+		return;
+
+	mmdc_ch1_disable(ccm_base);
+
+	for (i = 1; i < 4; i++) {
+		reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+		reg &= ~((7 << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+			 (7 << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+		reg |= ((sel[0][i] << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+			(sel[1][i] << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+		writel_relaxed(reg, ccm_base + CCM_CS2CDR);
+	}
+
+	mmdc_ch1_reenable(ccm_base);
+}
+
+#define CCM_ANALOG_PLL_VIDEO	0xa0
+#define CCM_ANALOG_PFD_480	0xf0
+#define CCM_ANALOG_PFD_528	0x100
+
+#define PLL_ENABLE		BIT(13)
+
+#define PFD0_CLKGATE		BIT(7)
+#define PFD1_CLKGATE		BIT(15)
+#define PFD2_CLKGATE		BIT(23)
+#define PFD3_CLKGATE		BIT(31)
+
+static void disable_anatop_clocks(void __iomem *anatop_base)
+{
+	unsigned int reg;
+
+	/* Make sure PLL2 PFDs 0-2 are gated */
+	reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_528);
+	/* Cannot gate PFD2 if pll2_pfd2_396m is the parent of MMDC clock */
+	if (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+	    clk[IMX6QDL_CLK_PLL2_PFD2_396M])
+		reg |= PFD0_CLKGATE | PFD1_CLKGATE;
+	else
+		reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE;
+	writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_528);
+
+	/* Make sure PLL3 PFDs 0-3 are gated */
+	reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_480);
+	reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE | PFD3_CLKGATE;
+	writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_480);
+
+	/* Make sure PLL5 is disabled */
+	reg = readl_relaxed(anatop_base + CCM_ANALOG_PLL_VIDEO);
+	reg &= ~PLL_ENABLE;
+	writel_relaxed(reg, anatop_base + CCM_ANALOG_PLL_VIDEO);
+}
+
 static void __init imx6q_clocks_init(struct device_node *ccm_node)
 {
 	struct device_node *np;
-	void __iomem *base;
+	void __iomem *anatop_base, *base;
 	int i;
 	int ret;
 
@@ -172,7 +429,7 @@ static void __init imx6q_clocks_init(str
 	clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
-	base = of_iomap(np, 0);
+	anatop_base = base = of_iomap(np, 0);
 	WARN_ON(!base);
 
 	/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
@@ -330,8 +587,20 @@ static void __init imx6q_clocks_init(str
 		clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8,  2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
 	clk[IMX6QDL_CLK_IPU1_SEL]         = imx_clk_mux("ipu1_sel",         base + 0x3c, 9,  2, ipu_sels,          ARRAY_SIZE(ipu_sels));
 	clk[IMX6QDL_CLK_IPU2_SEL]         = imx_clk_mux("ipu2_sel",         base + 0x3c, 14, 2, ipu_sels,          ARRAY_SIZE(ipu_sels));
-	clk[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
-	clk[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+
+	disable_anatop_clocks(anatop_base);
+
+	imx6q_mmdc_ch1_mask_handshake(base);
+
+	/*
+	 * The LDB_DI0/1_SEL muxes are registered read-only due to a hardware
+	 * bug. Set the muxes to the requested values before registering the
+	 * ldb_di_sel clocks.
+	 */
+	init_ldb_clks(np, base);
+
+	clk[IMX6QDL_CLK_LDB_DI0_SEL]      = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9,  3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
+	clk[IMX6QDL_CLK_LDB_DI1_SEL]      = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels,      ARRAY_SIZE(ldb_di_sels));
 	clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
 	clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
 	clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6,  3, ipu_di_pre_sels,   ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
@@ -582,12 +851,6 @@ static void __init imx6q_clocks_init(str
 
 	clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
 
-	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
-	    clk_on_imx6dl()) {
-		clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-		clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
-	}
-
 	clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000);
 	if (clk_on_imx6dl())
 		clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/imx/clk-imx6ul.c linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-imx6ul.c
--- linux-libre-4.9-gnu/drivers/clk/imx/clk-imx6ul.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-imx6ul.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,10 @@ static const char *perclk_sels[] = { "ip
 static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
 static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
 static const char *sim_sels[] = { "sim_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+/* epdc_pre_sels, epdc_sels, esai_sels only exists on i.MX6ULL */
+static const char *epdc_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *esai_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *epdc_sels[] = { "epdc_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
 
 static struct clk *clks[IMX6UL_CLK_END];
 static struct clk_onecell_data clk_data;
@@ -102,6 +106,17 @@ static u32 share_count_audio;
 static u32 share_count_sai1;
 static u32 share_count_sai2;
 static u32 share_count_sai3;
+static u32 share_count_esai;
+
+static inline int clk_on_imx6ul(void)
+{
+	return of_machine_is_compatible("fsl,imx6ul");
+}
+
+static inline int clk_on_imx6ull(void)
+{
+	return of_machine_is_compatible("fsl,imx6ull");
+}
 
 static void __init imx6ul_clocks_init(struct device_node *ccm_node)
 {
@@ -238,12 +253,19 @@ static void __init imx6ul_clocks_init(st
 	clks[IMX6UL_CLK_QSPI1_SEL]	  = imx_clk_mux("qspi1_sel",    base + 0x1c, 7,  3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
 	clks[IMX6UL_CLK_PERCLK_SEL]	  = imx_clk_mux("perclk_sel",	base + 0x1c, 6,  1, perclk_sels, ARRAY_SIZE(perclk_sels));
 	clks[IMX6UL_CLK_CAN_SEL]	  = imx_clk_mux("can_sel",	base + 0x20, 8,  2, can_sels, ARRAY_SIZE(can_sels));
+	if (clk_on_imx6ull())
+		clks[IMX6ULL_CLK_ESAI_SEL]	  = imx_clk_mux("esai_sel",	base + 0x20, 19, 2, esai_sels, ARRAY_SIZE(esai_sels));
 	clks[IMX6UL_CLK_UART_SEL]	  = imx_clk_mux("uart_sel",	base + 0x24, 6,  1, uart_sels, ARRAY_SIZE(uart_sels));
 	clks[IMX6UL_CLK_ENFC_SEL]	  = imx_clk_mux("enfc_sel",	base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
 	clks[IMX6UL_CLK_LDB_DI0_SEL]	  = imx_clk_mux("ldb_di0_sel",	base + 0x2c, 9,  3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
 	clks[IMX6UL_CLK_SPDIF_SEL]	  = imx_clk_mux("spdif_sel",	base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
-	clks[IMX6UL_CLK_SIM_PRE_SEL]	  = imx_clk_mux("sim_pre_sel",	base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
-	clks[IMX6UL_CLK_SIM_SEL]	  = imx_clk_mux("sim_sel",	base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+	if (clk_on_imx6ul()) {
+		clks[IMX6UL_CLK_SIM_PRE_SEL] 	  = imx_clk_mux("sim_pre_sel",	base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
+		clks[IMX6UL_CLK_SIM_SEL]	  = imx_clk_mux("sim_sel", 	base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+	} else if (clk_on_imx6ull()) {
+		clks[IMX6ULL_CLK_EPDC_PRE_SEL]	  = imx_clk_mux("epdc_pre_sel",	base + 0x34, 15, 3, epdc_pre_sels, ARRAY_SIZE(epdc_pre_sels));
+		clks[IMX6ULL_CLK_EPDC_SEL]	  = imx_clk_mux("epdc_sel",	base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
+	}
 	clks[IMX6UL_CLK_ECSPI_SEL]	  = imx_clk_mux("ecspi_sel",	base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
 	clks[IMX6UL_CLK_LCDIF_PRE_SEL]	  = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
 	clks[IMX6UL_CLK_LCDIF_SEL]	  = imx_clk_mux("lcdif_sel",	base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
@@ -276,6 +298,10 @@ static void __init imx6ul_clocks_init(st
 	clks[IMX6UL_CLK_SAI3_PODF]	= imx_clk_divider("sai3_podf",	   "sai3_pred",		base + 0x28, 16, 6);
 	clks[IMX6UL_CLK_SAI1_PRED]	= imx_clk_divider("sai1_pred",	   "sai1_sel",		base + 0x28, 6,	 3);
 	clks[IMX6UL_CLK_SAI1_PODF]	= imx_clk_divider("sai1_podf",	   "sai1_pred",		base + 0x28, 0,	 6);
+	if (clk_on_imx6ull()) {
+		clks[IMX6ULL_CLK_ESAI_PRED]	= imx_clk_divider("esai_pred",     "esai_sel",		base + 0x28, 9,  3);
+		clks[IMX6ULL_CLK_ESAI_PODF]	= imx_clk_divider("esai_podf",     "esai_pred",		base + 0x28, 25, 3);
+	}
 	clks[IMX6UL_CLK_ENFC_PRED]	= imx_clk_divider("enfc_pred",	   "enfc_sel",		base + 0x2c, 18, 3);
 	clks[IMX6UL_CLK_ENFC_PODF]	= imx_clk_divider("enfc_podf",	   "enfc_pred",		base + 0x2c, 21, 6);
 	clks[IMX6UL_CLK_SAI2_PRED]	= imx_clk_divider("sai2_pred",	   "sai2_sel",		base + 0x2c, 6,	 3);
@@ -298,9 +324,15 @@ static void __init imx6ul_clocks_init(st
 	clks[IMX6UL_CLK_APBHDMA]	= imx_clk_gate2("apbh_dma",	"bch_podf",	base + 0x68,	4);
 	clks[IMX6UL_CLK_ASRC_IPG]	= imx_clk_gate2_shared("asrc_ipg",	"ahb",	base + 0x68,	6, &share_count_asrc);
 	clks[IMX6UL_CLK_ASRC_MEM]	= imx_clk_gate2_shared("asrc_mem",	"ahb",	base + 0x68,	6, &share_count_asrc);
-	clks[IMX6UL_CLK_CAAM_MEM]	= imx_clk_gate2("caam_mem",	"ahb",		base + 0x68,	8);
-	clks[IMX6UL_CLK_CAAM_ACLK]	= imx_clk_gate2("caam_aclk",	"ahb",		base + 0x68,	10);
-	clks[IMX6UL_CLK_CAAM_IPG]	= imx_clk_gate2("caam_ipg",	"ipg",		base + 0x68,	12);
+	if (clk_on_imx6ul()) {
+		clks[IMX6UL_CLK_CAAM_MEM]	= imx_clk_gate2("caam_mem",	"ahb",		base + 0x68,	8);
+		clks[IMX6UL_CLK_CAAM_ACLK]	= imx_clk_gate2("caam_aclk",	"ahb",		base + 0x68,	10);
+		clks[IMX6UL_CLK_CAAM_IPG]	= imx_clk_gate2("caam_ipg",	"ipg",		base + 0x68,	12);
+	} else if (clk_on_imx6ull()) {
+		clks[IMX6ULL_CLK_DCP_CLK]	= imx_clk_gate2("dcp",		"ahb",		base + 0x68,	10);
+		clks[IMX6UL_CLK_ENET]		= imx_clk_gate2("enet",		"ipg",		base + 0x68,	12);
+		clks[IMX6UL_CLK_ENET_AHB]	= imx_clk_gate2("enet_ahb",	"ahb",		base + 0x68,	12);
+	}
 	clks[IMX6UL_CLK_CAN1_IPG]	= imx_clk_gate2("can1_ipg",	"ipg",		base + 0x68,	14);
 	clks[IMX6UL_CLK_CAN1_SERIAL]	= imx_clk_gate2("can1_serial",	"can_podf",	base + 0x68,	16);
 	clks[IMX6UL_CLK_CAN2_IPG]	= imx_clk_gate2("can2_ipg",	"ipg",		base + 0x68,	18);
@@ -309,7 +341,10 @@ static void __init imx6ul_clocks_init(st
 	clks[IMX6UL_CLK_GPT2_SERIAL]	= imx_clk_gate2("gpt2_serial",	"perclk",	base + 0x68,	26);
 	clks[IMX6UL_CLK_UART2_IPG]	= imx_clk_gate2("uart2_ipg",	"ipg",		base + 0x68,	28);
 	clks[IMX6UL_CLK_UART2_SERIAL]	= imx_clk_gate2("uart2_serial",	"uart_podf",	base + 0x68,	28);
-	clks[IMX6UL_CLK_AIPSTZ3]	= imx_clk_gate2("aips_tz3",	"ahb",		base + 0x68,	30);
+	if (clk_on_imx6ul())
+		clks[IMX6UL_CLK_AIPSTZ3]	= imx_clk_gate2("aips_tz3",	"ahb",		base + 0x68,	30);
+	else if (clk_on_imx6ull())
+		clks[IMX6UL_CLK_AIPSTZ3]	= imx_clk_gate2("aips_tz3",	"ahb",		 base + 0x80,	18);
 
 	/* CCGR1 */
 	clks[IMX6UL_CLK_ECSPI1]		= imx_clk_gate2("ecspi1",	"ecspi_podf",	base + 0x6c,	0);
@@ -328,6 +363,11 @@ static void __init imx6ul_clocks_init(st
 	clks[IMX6UL_CLK_UART4_SERIAL]	= imx_clk_gate2("uart4_serail",	"uart_podf",	base + 0x6c,	24);
 
 	/* CCGR2 */
+	if (clk_on_imx6ull()) {
+		clks[IMX6ULL_CLK_ESAI_EXTAL]	= imx_clk_gate2_shared("esai_extal",	"esai_podf",	base + 0x70,	0, &share_count_esai);
+		clks[IMX6ULL_CLK_ESAI_IPG]	= imx_clk_gate2_shared("esai_ipg",	"ahb",		base + 0x70,	0, &share_count_esai);
+		clks[IMX6ULL_CLK_ESAI_MEM]	= imx_clk_gate2_shared("esai_mem",	"ahb",		base + 0x70,	0, &share_count_esai);
+	}
 	clks[IMX6UL_CLK_CSI]		= imx_clk_gate2("csi",		"csi_podf",		base + 0x70,	2);
 	clks[IMX6UL_CLK_I2C1]		= imx_clk_gate2("i2c1",		"perclk",	base + 0x70,	6);
 	clks[IMX6UL_CLK_I2C2]		= imx_clk_gate2("i2c2",		"perclk",	base + 0x70,	8);
@@ -340,8 +380,13 @@ static void __init imx6ul_clocks_init(st
 	/* CCGR3 */
 	clks[IMX6UL_CLK_UART5_IPG]	= imx_clk_gate2("uart5_ipg",	"ipg",		base + 0x74,	2);
 	clks[IMX6UL_CLK_UART5_SERIAL]	= imx_clk_gate2("uart5_serial",	"uart_podf",	base + 0x74,	2);
-	clks[IMX6UL_CLK_ENET]		= imx_clk_gate2("enet",		"ipg",		base + 0x74,	4);
-	clks[IMX6UL_CLK_ENET_AHB]	= imx_clk_gate2("enet_ahb",	"ahb",		base + 0x74,	4);
+	if (clk_on_imx6ul()) {
+		clks[IMX6UL_CLK_ENET]		= imx_clk_gate2("enet",		"ipg",		base + 0x74,	4);
+		clks[IMX6UL_CLK_ENET_AHB]	= imx_clk_gate2("enet_ahb",	"ahb",		base + 0x74,	4);
+	} else if (clk_on_imx6ull()) {
+		clks[IMX6ULL_CLK_EPDC_ACLK]	= imx_clk_gate2("epdc_aclk",	"axi",		base + 0x74,	4);
+		clks[IMX6ULL_CLK_EPDC_PIX]	= imx_clk_gate2("epdc_pix",	"epdc_podf",	base + 0x74,	4);
+	}
 	clks[IMX6UL_CLK_UART6_IPG]	= imx_clk_gate2("uart6_ipg",	"ipg",		base + 0x74,	6);
 	clks[IMX6UL_CLK_UART6_SERIAL]	= imx_clk_gate2("uart6_serial",	"uart_podf",	base + 0x74,	6);
 	clks[IMX6UL_CLK_LCDIF_PIX]	= imx_clk_gate2("lcdif_pix",	"lcdif_podf",	base + 0x74,	10);
@@ -385,8 +430,10 @@ static void __init imx6ul_clocks_init(st
 	clks[IMX6UL_CLK_USBOH3]		= imx_clk_gate2("usboh3",	"ipg",		 base + 0x80,	0);
 	clks[IMX6UL_CLK_USDHC1]		= imx_clk_gate2("usdhc1",	"usdhc1_podf",	 base + 0x80,	2);
 	clks[IMX6UL_CLK_USDHC2]		= imx_clk_gate2("usdhc2",	"usdhc2_podf",	 base + 0x80,	4);
-	clks[IMX6UL_CLK_SIM1]		= imx_clk_gate2("sim1",		"sim_sel",	 base + 0x80,	6);
-	clks[IMX6UL_CLK_SIM2]		= imx_clk_gate2("sim2",		"sim_sel",	 base + 0x80,	8);
+	if (clk_on_imx6ul()) {
+		clks[IMX6UL_CLK_SIM1]		= imx_clk_gate2("sim1",		"sim_sel",	 base + 0x80,	6);
+		clks[IMX6UL_CLK_SIM2]		= imx_clk_gate2("sim2",		"sim_sel",	 base + 0x80,	8);
+	}
 	clks[IMX6UL_CLK_EIM]		= imx_clk_gate2("eim",		"eim_slow_podf", base + 0x80,	10);
 	clks[IMX6UL_CLK_PWM8]		= imx_clk_gate2("pwm8",		"perclk",	 base + 0x80,	16);
 	clks[IMX6UL_CLK_UART8_IPG]	= imx_clk_gate2("uart8_ipg",	"ipg",		 base + 0x80,	14);
@@ -441,7 +488,10 @@ static void __init imx6ul_clocks_init(st
 	}
 
 	clk_set_parent(clks[IMX6UL_CLK_CAN_SEL], clks[IMX6UL_CLK_PLL3_60M]);
-	clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+	if (clk_on_imx6ul())
+		clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+	else if (clk_on_imx6ull())
+		clk_set_parent(clks[IMX6ULL_CLK_EPDC_PRE_SEL], clks[IMX6UL_CLK_PLL3_PFD2]);
 
 	clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/imx/clk-pllv3.c linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-pllv3.c
--- linux-libre-4.9-gnu/drivers/clk/imx/clk-pllv3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/imx/clk-pllv3.c	2017-02-12 16:03:20.000000000 -0500
@@ -234,6 +234,7 @@ static long clk_pllv3_av_round_rate(stru
 	unsigned long max_rate = parent_rate * 54;
 	u32 div;
 	u32 mfn, mfd = 1000000;
+	u32 max_mfd = 0x3FFFFFFF;
 	u64 temp64;
 
 	if (rate > max_rate)
@@ -241,6 +242,9 @@ static long clk_pllv3_av_round_rate(stru
 	else if (rate < min_rate)
 		rate = min_rate;
 
+	if (parent_rate <= max_mfd)
+		mfd = parent_rate;
+
 	div = rate / parent_rate;
 	temp64 = (u64) (rate - div * parent_rate);
 	temp64 *= mfd;
@@ -262,11 +266,15 @@ static int clk_pllv3_av_set_rate(struct
 	unsigned long max_rate = parent_rate * 54;
 	u32 val, div;
 	u32 mfn, mfd = 1000000;
+	u32 max_mfd = 0x3FFFFFFF;
 	u64 temp64;
 
 	if (rate < min_rate || rate > max_rate)
 		return -EINVAL;
 
+	if (parent_rate <= max_mfd)
+		mfd = parent_rate;
+
 	div = rate / parent_rate;
 	temp64 = (u64) (rate - div * parent_rate);
 	temp64 *= mfd;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/Kconfig linux-libre-4.10-rc8-gnu/drivers/clk/Kconfig
--- linux-libre-4.9-gnu/drivers/clk/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@ source "drivers/clk/versatile/Kconfig"
 
 config COMMON_CLK_MAX77686
 	tristate "Clock driver for Maxim 77620/77686/77802 MFD"
-	depends on MFD_MAX77686 || MFD_MAX77620
+	depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST
 	---help---
 	  This driver supports Maxim 77620/77686/77802 crystal oscillator
 	  clock.
@@ -119,7 +119,7 @@ config COMMON_CLK_CS2000_CP
 
 config COMMON_CLK_S2MPS11
 	tristate "Clock driver for S2MPS1X/S5M8767 MFD"
-	depends on MFD_SEC_CORE
+	depends on MFD_SEC_CORE || COMPILE_TEST
 	---help---
 	  This driver supports S2MPS11/S2MPS14/S5M8767 crystal oscillator
 	  clock. These multi-function devices have two (S2MPS14) or three
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/keystone/pll.c linux-libre-4.10-rc8-gnu/drivers/clk/keystone/pll.c
--- linux-libre-4.9-gnu/drivers/clk/keystone/pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/keystone/pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -154,7 +154,7 @@ out:
 }
 
 /**
- * _of_clk_init - PLL initialisation via DT
+ * _of_pll_clk_init - PLL initialisation via DT
  * @node: device tree node for this clock
  * @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
  *		pll controller, else it is in the control register0(bit 11-6)
@@ -235,7 +235,7 @@ CLK_OF_DECLARE(keystone_pll_clock, "ti,k
 					of_keystone_pll_clk_init);
 
 /**
- * of_keystone_pll_main_clk_init - Main PLL initialisation DT wrapper
+ * of_keystone_main_pll_clk_init - Main PLL initialisation DT wrapper
  * @node: device tree node for this clock
  */
 static void __init of_keystone_main_pll_clk_init(struct device_node *node)
@@ -267,25 +267,30 @@ static void __init of_pll_div_clk_init(s
 	parent_name = of_clk_get_parent_name(node, 0);
 	if (!parent_name) {
 		pr_err("%s: missing parent clock\n", __func__);
+		iounmap(reg);
 		return;
 	}
 
 	if (of_property_read_u32(node, "bit-shift", &shift)) {
 		pr_err("%s: missing 'shift' property\n", __func__);
+		iounmap(reg);
 		return;
 	}
 
 	if (of_property_read_u32(node, "bit-mask", &mask)) {
 		pr_err("%s: missing 'bit-mask' property\n", __func__);
+		iounmap(reg);
 		return;
 	}
 
 	clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
 				 mask, 0, NULL);
-	if (clk)
+	if (clk) {
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
-	else
+	} else {
 		pr_err("%s: error registering divider %s\n", __func__, clk_name);
+		iounmap(reg);
+	}
 }
 CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-gate.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-gate.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-gate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-gate.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,6 +61,22 @@ static void mtk_cg_clr_bit(struct clk_hw
 	regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit));
 }
 
+static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 cgbit = BIT(cg->bit);
+
+	regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, cgbit);
+}
+
+static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw)
+{
+	struct mtk_clk_gate *cg = to_mtk_clk_gate(hw);
+	u32 cgbit = BIT(cg->bit);
+
+	regmap_update_bits(cg->regmap, cg->sta_ofs, cgbit, 0);
+}
+
 static int mtk_cg_enable(struct clk_hw *hw)
 {
 	mtk_cg_clr_bit(hw);
@@ -85,6 +101,30 @@ static void mtk_cg_disable_inv(struct cl
 	mtk_cg_clr_bit(hw);
 }
 
+static int mtk_cg_enable_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit_no_setclr(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_set_bit_no_setclr(hw);
+}
+
+static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_set_bit_no_setclr(hw);
+
+	return 0;
+}
+
+static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw)
+{
+	mtk_cg_clr_bit_no_setclr(hw);
+}
+
 const struct clk_ops mtk_clk_gate_ops_setclr = {
 	.is_enabled	= mtk_cg_bit_is_cleared,
 	.enable		= mtk_cg_enable,
@@ -97,6 +137,18 @@ const struct clk_ops mtk_clk_gate_ops_se
 	.disable	= mtk_cg_disable_inv,
 };
 
+const struct clk_ops mtk_clk_gate_ops_no_setclr = {
+	.is_enabled	= mtk_cg_bit_is_cleared,
+	.enable		= mtk_cg_enable_no_setclr,
+	.disable	= mtk_cg_disable_no_setclr,
+};
+
+const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = {
+	.is_enabled	= mtk_cg_bit_is_set,
+	.enable		= mtk_cg_enable_inv_no_setclr,
+	.disable	= mtk_cg_disable_inv_no_setclr,
+};
+
 struct clk *mtk_clk_register_gate(
 		const char *name,
 		const char *parent_name,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-gate.h linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-gate.h
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-gate.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-gate.h	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,8 @@ static inline struct mtk_clk_gate *to_mt
 
 extern const struct clk_ops mtk_clk_gate_ops_setclr;
 extern const struct clk_ops mtk_clk_gate_ops_setclr_inv;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr;
+extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv;
 
 struct clk *mtk_clk_register_gate(
 		const char *name,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-bdp.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-bdp.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-bdp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-bdp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs bdp0_cg_regs = {
+	.set_ofs = 0x0104,
+	.clr_ofs = 0x0108,
+	.sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs bdp1_cg_regs = {
+	.set_ofs = 0x0114,
+	.clr_ofs = 0x0118,
+	.sta_ofs = 0x0110,
+};
+
+#define GATE_BDP0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &bdp0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_BDP1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &bdp1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate bdp_clks[] = {
+	GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0),
+	GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1),
+	GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2),
+	GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3),
+	GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4),
+	GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5),
+	GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6),
+	GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7),
+	GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8),
+	GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9),
+	GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10),
+	GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11),
+	GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12),
+	GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13),
+	GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14),
+	GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15),
+	GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16),
+	GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17),
+	GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18),
+	GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19),
+	GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20),
+	GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21),
+	GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22),
+	GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23),
+	GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24),
+	GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25),
+	GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26),
+	GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27),
+	GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28),
+	GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29),
+	GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30),
+	GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31),
+	GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0),
+	GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1),
+	GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2),
+	GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3),
+	GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4),
+	GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5),
+	GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6),
+	GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7),
+	GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8),
+	GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9),
+	GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10),
+	GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11),
+	GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12),
+	GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13),
+	GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14),
+	GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15),
+	GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16),
+};
+
+static const struct of_device_id of_match_clk_mt2701_bdp[] = {
+	{ .compatible = "mediatek,mt2701-bdpsys", },
+	{}
+};
+
+static int clk_mt2701_bdp_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
+
+	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_bdp_drv = {
+	.probe = clk_mt2701_bdp_probe,
+	.driver = {
+		.name = "clk-mt2701-bdp",
+		.of_match_table = of_match_clk_mt2701_bdp,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_bdp_drv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1035 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.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/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+#define DUMMY_RATE		0
+
+static DEFINE_SPINLOCK(mt2701_clk_lock);
+
+static const struct mtk_fixed_clk top_fixed_clks[] = {
+	FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m",
+		108 * MHZ),
+	FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m",
+		400 * MHZ),
+	FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m",
+		295750000),
+	FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m",
+		340 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_dig_cts", "clk26m",
+		300 * MHZ),
+	FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m",
+		27 * MHZ),
+	FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m",
+		416 * MHZ),
+	FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, "dsi0_lntc_dsi", "clk26m",
+		143 * MHZ),
+	FIXED_CLK(CLK_TOP_HDMI_SCL_RX, "hdmi_scl_rx", "clk26m",
+		27 * MHZ),
+	FIXED_CLK(CLK_TOP_AUD_EXT1, "aud_ext1", "clk26m",
+		DUMMY_RATE),
+	FIXED_CLK(CLK_TOP_AUD_EXT2, "aud_ext2", "clk26m",
+		DUMMY_RATE),
+	FIXED_CLK(CLK_TOP_NFI1X_PAD, "nfi1x_pad", "clk26m",
+		DUMMY_RATE),
+};
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+	FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1),
+	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+	FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+
+	FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+	FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+	FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52),
+	FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108),
+	FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26),
+	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+	FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1),
+	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8),
+	FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16),
+	FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32),
+	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+	FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+
+	FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1),
+	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+	FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
+
+	FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1),
+	FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2),
+
+	FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2),
+	FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4),
+	FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1),
+
+	FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1),
+	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
+	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+
+	FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1),
+	FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1),
+	FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2),
+
+	FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1),
+	FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2),
+	FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4),
+
+	FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1),
+	FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2),
+	FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3),
+
+	FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1),
+
+	FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1),
+	FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4),
+	FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8),
+	FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16),
+	FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24),
+
+	FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3),
+	FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3),
+	FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3),
+	FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1),
+	FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1),
+	FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8),
+	FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793),
+	FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1),
+};
+
+static const char * const axi_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"mmpll_d2",
+	"dmpll_d2"
+};
+
+static const char * const mem_parents[] = {
+	"clk26m",
+	"dmpll_ck"
+};
+
+static const char * const ddrphycfg_parents[] = {
+	"clk26m",
+	"syspll1_d8"
+};
+
+static const char * const mm_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"syspll1_d2",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_ck"
+};
+
+static const char * const pwm_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll3_d2",
+	"univpll1_d4",
+};
+
+static const char * const vdec_parents[] = {
+	"clk26m",
+	"vdecpll_ck",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll2_d2",
+	"vencpll_ck",
+	"msdcpll_d2",
+	"mmpll_d2"
+};
+
+static const char * const mfg_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"dmpll_x2_ck",
+	"msdcpll_ck",
+	"clk26m",
+	"syspll_d3",
+	"univpll_d3",
+	"univpll1_d2"
+};
+
+static const char * const camtg_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll2_d2",
+	"syspll3_d2",
+	"syspll3_d4",
+	"msdcpll_d2",
+	"mmpll_d2"
+};
+
+static const char * const uart_parents[] = {
+	"clk26m",
+	"univpll2_d8"
+};
+
+static const char * const spi_parents[] = {
+	"clk26m",
+	"syspll3_d2",
+	"syspll4_d2",
+	"univpll2_d4",
+	"univpll1_d8"
+};
+
+static const char * const usb20_parents[] = {
+	"clk26m",
+	"univpll1_d8",
+	"univpll3_d4"
+};
+
+static const char * const msdc30_parents[] = {
+	"clk26m",
+	"msdcpll_d2",
+	"syspll2_d2",
+	"syspll1_d4",
+	"univpll1_d4",
+	"univpll2_d4"
+};
+
+static const char * const audio_parents[] = {
+	"clk26m",
+	"syspll1_d16"
+};
+
+static const char * const aud_intbus_parents[] = {
+	"clk26m",
+	"syspll1_d4",
+	"syspll3_d2",
+	"syspll4_d2",
+	"univpll3_d2",
+	"univpll2_d4"
+};
+
+static const char * const pmicspi_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"syspll2_d4",
+	"syspll4_d2",
+	"syspll3_d4",
+	"syspll2_d8",
+	"syspll1_d16",
+	"univpll3_d4",
+	"univpll_d26",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const scp_parents[] = {
+	"clk26m",
+	"syspll1_d8",
+	"dmpll_d2",
+	"dmpll_d4"
+};
+
+static const char * const dpi0_parents[] = {
+	"clk26m",
+	"mipipll",
+	"mipipll_d2",
+	"mipipll_d4",
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const dpi1_parents[] = {
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const tve_parents[] = {
+	"clk26m",
+	"mipipll",
+	"mipipll_d2",
+	"mipipll_d4",
+	"clk26m",
+	"tvdpll_ck",
+	"tvdpll_d2",
+	"tvdpll_d4"
+};
+
+static const char * const hdmi_parents[] = {
+	"clk26m",
+	"hdmipll_ck",
+	"hdmipll_d2",
+	"hdmipll_d3"
+};
+
+static const char * const apll_parents[] = {
+	"clk26m",
+	"audpll",
+	"audpll_d4",
+	"audpll_d8",
+	"audpll_d16",
+	"audpll_d24",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const rtc_parents[] = {
+	"32k_internal",
+	"32k_external",
+	"clk26m",
+	"univpll3_d8"
+};
+
+static const char * const nfi2x_parents[] = {
+	"clk26m",
+	"syspll2_d2",
+	"syspll_d7",
+	"univpll3_d2",
+	"syspll2_d4",
+	"univpll3_d4",
+	"syspll4_d4",
+	"clk26m"
+};
+
+static const char * const emmc_hclk_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll1_d4",
+	"syspll2_d2"
+};
+
+static const char * const flash_parents[] = {
+	"clk26m_d8",
+	"clk26m",
+	"syspll2_d8",
+	"syspll3_d4",
+	"univpll3_d4",
+	"syspll4_d2",
+	"syspll2_d4",
+	"univpll2_d4"
+};
+
+static const char * const di_parents[] = {
+	"clk26m",
+	"tvd2pll_ck",
+	"tvd2pll_d2",
+	"clk26m"
+};
+
+static const char * const nr_osd_parents[] = {
+	"clk26m",
+	"vencpll_ck",
+	"syspll1_d2",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"univpll2_d2",
+	"dmpll_ck"
+};
+
+static const char * const hdmirx_bist_parents[] = {
+	"clk26m",
+	"syspll_d3",
+	"clk26m",
+	"syspll1_d16",
+	"syspll4_d2",
+	"syspll1_d4",
+	"vencpll_ck",
+	"clk26m"
+};
+
+static const char * const intdir_parents[] = {
+	"clk26m",
+	"mmpll_ck",
+	"syspll_d2",
+	"univpll_d2"
+};
+
+static const char * const asm_parents[] = {
+	"clk26m",
+	"univpll2_d4",
+	"univpll2_d2",
+	"syspll_d5"
+};
+
+static const char * const ms_card_parents[] = {
+	"clk26m",
+	"univpll3_d8",
+	"syspll4_d4"
+};
+
+static const char * const ethif_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"syspll_d5",
+	"syspll1_d4",
+	"univpll_d5",
+	"univpll1_d2",
+	"dmpll_ck",
+	"dmpll_d2"
+};
+
+static const char * const hdmirx_parents[] = {
+	"clk26m",
+	"univpll_d52"
+};
+
+static const char * const cmsys_parents[] = {
+	"clk26m",
+	"syspll1_d2",
+	"univpll1_d2",
+	"univpll_d5",
+	"syspll_d5",
+	"syspll2_d2",
+	"syspll1_d4",
+	"syspll3_d2",
+	"syspll2_d4",
+	"syspll1_d8",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const clk_8bdac_parents[] = {
+	"32k_internal",
+	"8bdac_ck",
+	"clk26m",
+	"clk26m"
+};
+
+static const char * const aud2dvd_parents[] = {
+	"a1sys_hp_ck",
+	"a2sys_hp_ck"
+};
+
+static const char * const padmclk_parents[] = {
+	"clk26m",
+	"univpll_d26",
+	"univpll_d52",
+	"univpll_d108",
+	"univpll2_d8",
+	"univpll2_d16",
+	"univpll2_d32"
+};
+
+static const char * const aud_mux_parents[] = {
+	"clk26m",
+	"aud1pll_98m_ck",
+	"aud2pll_90m_ck",
+	"hadds2pll_98m",
+	"audio_ext1_ck",
+	"audio_ext2_ck"
+};
+
+static const char * const aud_src_parents[] = {
+	"aud_mux1_sel",
+	"aud_mux2_sel"
+};
+
+static const char * const cpu_parents[] = {
+	"clk26m",
+	"armpll",
+	"mainpll",
+	"mmpll"
+};
+
+static const struct mtk_composite top_muxes[] = {
+	MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
+		0x0040, 0, 3, 7, CLK_IS_CRITICAL),
+	MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
+		0x0040, 8, 1, 15, CLK_IS_CRITICAL),
+	MUX_GATE_FLAGS(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel",
+		ddrphycfg_parents, 0x0040, 16, 1, 23, CLK_IS_CRITICAL),
+	MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents,
+		0x0040, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
+		0x0050, 0, 2, 7),
+	MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents,
+		0x0050, 8, 4, 15),
+	MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents,
+		0x0050, 16, 3, 23),
+	MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents,
+		0x0050, 24, 3, 31),
+	MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
+		0x0060, 0, 1, 7),
+
+	MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents,
+		0x0060, 8, 3, 15),
+	MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents,
+		0x0060, 16, 2, 23),
+	MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents,
+		0x0060, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents,
+		0x0070, 0, 3, 7),
+	MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents,
+		0x0070, 8, 3, 15),
+	MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents,
+		0x0070, 16, 1, 23),
+	MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
+		0x0070, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
+		0x0080, 0, 4, 7),
+	MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents,
+		0x0080, 8, 2, 15),
+	MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents,
+		0x0080, 16, 3, 23),
+	MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents,
+		0x0080, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents,
+		0x0090, 0, 3, 7),
+	MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents,
+		0x0090, 8, 2, 15),
+	MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents,
+		0x0090, 16, 3, 23),
+
+	MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents,
+		0x00A0, 0, 2, 7, CLK_IS_CRITICAL),
+	MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents,
+		0x00A0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents,
+		0x00A0, 24, 2, 31),
+
+	MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
+		0x00B0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents,
+		0x00B0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents,
+		0x00B0, 16, 3, 23),
+	MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents,
+		0x00B0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel",
+		hdmirx_bist_parents, 0x00C0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
+		0x00C0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents,
+		0x00C0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents,
+		0x00C0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents,
+		0x00D0, 0, 2, 7),
+	MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents,
+		0x00D0, 16, 2, 23),
+	MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents,
+		0x00D0, 24, 3, 31),
+
+	MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents,
+		0x00E0, 0, 1, 7),
+	MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents,
+		0x00E0, 8, 3, 15),
+	MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents,
+		0x00E0, 16, 4, 23),
+
+	MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents,
+		0x00E0, 24, 3, 31),
+	MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents,
+		0x00F0, 0, 3, 7),
+	MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents,
+		0x00F0, 8, 2, 15),
+	MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents,
+		0x00F0, 16, 1, 23),
+
+	MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents,
+		0x0100, 0, 3),
+
+	MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents,
+		0x012c, 0, 3),
+	MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents,
+		0x012c, 3, 3),
+	MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents,
+		0x012c, 6, 3),
+	MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents,
+		0x012c, 15, 1, 23),
+	MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents,
+		0x012c, 16, 1, 24),
+	MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents,
+		0x012c, 17, 1, 25),
+	MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents,
+		0x012c, 18, 1, 26),
+	MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents,
+		0x012c, 19, 1, 27),
+	MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents,
+		0x012c, 20, 1, 28),
+};
+
+static const struct mtk_clk_divider top_adj_divs[] = {
+	DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext1",
+		0x0120, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext2",
+		0x0120, 8, 8),
+	DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel",
+		0x0120, 16, 8),
+	DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel",
+		0x0120, 24, 8),
+	DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel",
+		0x0124, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel",
+		0x0124, 8, 8),
+	DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel",
+		0x0124, 16, 8),
+	DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel",
+		0x0124, 24, 8),
+	DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel",
+		0x0128, 0, 8),
+	DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel",
+		0x0128, 8, 8),
+};
+
+static const struct mtk_gate_regs top_aud_cg_regs = {
+	.sta_ofs = 0x012C,
+};
+
+#define GATE_TOP_AUD(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &top_aud_cg_regs,		\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr,	\
+	}
+
+static const struct mtk_gate top_clks[] = {
+	GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div",
+		21),
+	GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div",
+		22),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div",
+		23),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div",
+		24),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div",
+		25),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div",
+		26),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div",
+		27),
+	GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div",
+		28),
+};
+
+static int mtk_topckgen_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	struct device_node *node = pdev->dev.of_node;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+
+	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
+								clk_data);
+
+	mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+								clk_data);
+
+	mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
+				base, &mt2701_clk_lock, clk_data);
+
+	mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
+				base, &mt2701_clk_lock, clk_data);
+
+	mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
+						clk_data);
+
+	return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct mtk_gate_regs infra_cg_regs = {
+	.set_ofs = 0x0040,
+	.clr_ofs = 0x0044,
+	.sta_ofs = 0x0048,
+};
+
+#define GATE_ICG(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &infra_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate infra_clks[] = {
+	GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0),
+	GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1),
+	GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2),
+	GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2pll_294m", 4),
+	GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk26m", 5),
+	GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6),
+	GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7),
+	GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8),
+	GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12),
+	GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13),
+	GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14),
+	GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15),
+	GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16),
+	GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18),
+	GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19),
+	GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22),
+	GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23),
+	GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24),
+};
+
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+	FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static struct clk_onecell_data *infra_clk_data;
+
+static void mtk_infrasys_init_early(struct device_node *node)
+{
+	int r, i;
+
+	if (!infra_clk_data) {
+		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+
+		for (i = 0; i < CLK_INFRA_NR; i++)
+			infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+	}
+
+	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+						infra_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+	if (r)
+		pr_err("%s(): could not register clock provider: %d\n",
+			__func__, r);
+}
+CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt2701-infracfg",
+			mtk_infrasys_init_early);
+
+static int mtk_infrasys_init(struct platform_device *pdev)
+{
+	int r, i;
+	struct device_node *node = pdev->dev.of_node;
+
+	if (!infra_clk_data) {
+		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+	} else {
+		for (i = 0; i < CLK_INFRA_NR; i++) {
+			if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+				infra_clk_data->clks[i] = ERR_PTR(-ENOENT);
+		}
+	}
+
+	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+						infra_clk_data);
+	mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+						infra_clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+	if (r)
+		return r;
+
+	mtk_register_reset_controller(node, 2, 0x30);
+
+	return 0;
+}
+
+static const struct mtk_gate_regs peri0_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x0010,
+	.sta_ofs = 0x0018,
+};
+
+static const struct mtk_gate_regs peri1_cg_regs = {
+	.set_ofs = 0x000c,
+	.clr_ofs = 0x0014,
+	.sta_ofs = 0x001c,
+};
+
+#define GATE_PERI0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_PERI1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &peri1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate peri_clks[] = {
+	GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31),
+	GATE_PERI0(CLK_PERI_ETH, "eth_ck", "clk26m", 30),
+	GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29),
+	GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28),
+	GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27),
+	GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26),
+	GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25),
+	GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24),
+	GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23),
+	GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22),
+	GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21),
+	GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20),
+	GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19),
+	GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18),
+	GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17),
+	GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16),
+	GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15),
+	GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14),
+	GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13),
+	GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12),
+	GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11),
+	GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10),
+	GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9),
+	GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8),
+	GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7),
+	GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6),
+	GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5),
+	GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4),
+	GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3),
+	GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2),
+	GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1),
+	GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0),
+
+	GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card_sel", 11),
+	GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10),
+	GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9),
+	GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8),
+	GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7),
+	GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6),
+	GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5),
+	GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi1x_pad", 4),
+	GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi1x_pad", 3),
+	GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2),
+	GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1),
+	GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0),
+};
+
+static const char * const uart_ck_sel_parents[] = {
+	"clk26m",
+	"uart_sel",
+};
+
+static const struct mtk_composite peri_muxs[] = {
+	MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents,
+		0x40c, 0, 1),
+	MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents,
+		0x40c, 1, 1),
+	MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents,
+		0x40c, 2, 1),
+	MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents,
+		0x40c, 3, 1),
+};
+
+static int mtk_pericfg_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	void __iomem *base;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+
+	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
+						clk_data);
+
+	mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base,
+			&mt2701_clk_lock, clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		return r;
+
+	mtk_register_reset_controller(node, 2, 0x0);
+
+	return 0;
+}
+
+#define MT8590_PLL_FMAX		(2000 * MHZ)
+#define CON0_MT8590_RST_BAR	BIT(27)
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \
+			_pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) {	\
+		.id = _id,						\
+		.name = _name,						\
+		.reg = _reg,						\
+		.pwr_reg = _pwr_reg,					\
+		.en_mask = _en_mask,					\
+		.flags = _flags,					\
+		.rst_bar_mask = CON0_MT8590_RST_BAR,			\
+		.fmax = MT8590_PLL_FMAX,				\
+		.pcwbits = _pcwbits,					\
+		.pd_reg = _pd_reg,					\
+		.pd_shift = _pd_shift,					\
+		.tuner_reg = _tuner_reg,				\
+		.pcw_reg = _pcw_reg,					\
+		.pcw_shift = _pcw_shift,				\
+	}
+
+static const struct mtk_pll_data apmixed_plls[] = {
+	PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000001,
+			PLL_AO, 21, 0x204, 24, 0x0, 0x204, 0),
+	PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000001,
+		  HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0),
+	PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000001,
+		  HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14),
+	PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0x00000001, 0,
+				21, 0x230, 4, 0x0, 0x234, 0),
+	PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0,
+				21, 0x240, 4, 0x0, 0x244, 0),
+	PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0,
+				21, 0x250, 4, 0x0, 0x254, 0),
+	PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0,
+				31, 0x270, 4, 0x0, 0x274, 0),
+	PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0,
+				31, 0x280, 4, 0x0, 0x284, 0),
+	PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0,
+				31, 0x290, 4, 0x0, 0x294, 0),
+	PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0,
+				31, 0x2a0, 4, 0x0, 0x2a4, 0),
+	PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0,
+				31, 0x2b0, 4, 0x0, 0x2b4, 0),
+	PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0,
+				31, 0x2c0, 4, 0x0, 0x2c4, 0),
+	PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0,
+				21, 0x2d0, 4, 0x0, 0x2d4, 0),
+};
+
+static int mtk_apmixedsys_init(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+	if (!clk_data)
+		return -ENOMEM;
+
+	mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls),
+								clk_data);
+
+	return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt2701[] = {
+	{
+		.compatible = "mediatek,mt2701-topckgen",
+		.data = mtk_topckgen_init,
+	}, {
+		.compatible = "mediatek,mt2701-infracfg",
+		.data = mtk_infrasys_init,
+	}, {
+		.compatible = "mediatek,mt2701-pericfg",
+		.data = mtk_pericfg_init,
+	}, {
+		.compatible = "mediatek,mt2701-apmixedsys",
+		.data = mtk_apmixedsys_init,
+	}, {
+		/* sentinel */
+	}
+};
+
+static int clk_mt2701_probe(struct platform_device *pdev)
+{
+	int (*clk_init)(struct platform_device *);
+	int r;
+
+	clk_init = of_device_get_match_data(&pdev->dev);
+	if (!clk_init)
+		return -EINVAL;
+
+	r = clk_init(pdev);
+	if (r)
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_drv = {
+	.probe = clk_mt2701_probe,
+	.driver = {
+		.name = "clk-mt2701",
+		.of_match_table = of_match_clk_mt2701,
+	},
+};
+
+static int __init clk_mt2701_init(void)
+{
+	return platform_driver_register(&clk_mt2701_drv);
+}
+
+arch_initcall(clk_mt2701_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-eth.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-eth.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-eth.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-eth.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs eth_cg_regs = {
+	.sta_ofs = 0x0030,
+};
+
+#define GATE_ETH(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &eth_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+static const struct mtk_gate eth_clks[] = {
+	GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5),
+	GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6),
+	GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7),
+	GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8),
+	GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11),
+	GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14),
+	GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17),
+	GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29),
+};
+
+static const struct of_device_id of_match_clk_mt2701_eth[] = {
+	{ .compatible = "mediatek,mt2701-ethsys", },
+	{}
+};
+
+static int clk_mt2701_eth_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
+
+	mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_eth_drv = {
+	.probe = clk_mt2701_eth_probe,
+	.driver = {
+		.name = "clk-mt2701-eth",
+		.of_match_table = of_match_clk_mt2701_eth,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_eth_drv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-hif.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-hif.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-hif.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-hif.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs hif_cg_regs = {
+	.sta_ofs = 0x0030,
+};
+
+#define GATE_HIF(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &hif_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_no_setclr_inv,	\
+	}
+
+static const struct mtk_gate hif_clks[] = {
+	GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21),
+	GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22),
+	GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24),
+	GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25),
+	GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26),
+};
+
+static const struct of_device_id of_match_clk_mt2701_hif[] = {
+	{ .compatible = "mediatek,mt2701-hifsys", },
+	{}
+};
+
+static int clk_mt2701_hif_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
+
+	mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r) {
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+		return r;
+	}
+
+	mtk_register_reset_controller(node, 1, 0x34);
+
+	return 0;
+}
+
+static struct platform_driver clk_mt2701_hif_drv = {
+	.probe = clk_mt2701_hif_probe,
+	.driver = {
+		.name = "clk-mt2701-hif",
+		.of_match_table = of_match_clk_mt2701_hif,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_hif_drv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-img.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-img.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-img.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-img.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs img_cg_regs = {
+	.set_ofs = 0x0004,
+	.clr_ofs = 0x0008,
+	.sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) {		\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &img_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate img_clks[] = {
+	GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0),
+	GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1),
+	GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5),
+	GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6),
+	GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8),
+	GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9),
+};
+
+static const struct of_device_id of_match_clk_mt2701_img[] = {
+	{ .compatible = "mediatek,mt2701-imgsys", },
+	{}
+};
+
+static int clk_mt2701_img_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+
+	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_img_drv = {
+	.probe = clk_mt2701_img_probe,
+	.driver = {
+		.name = "clk-mt2701-img",
+		.of_match_table = of_match_clk_mt2701_img,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_img_drv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-mm.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-mm.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-mm.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs disp0_cg_regs = {
+	.set_ofs = 0x0104,
+	.clr_ofs = 0x0108,
+	.sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs disp1_cg_regs = {
+	.set_ofs = 0x0114,
+	.clr_ofs = 0x0118,
+	.sta_ofs = 0x0110,
+};
+
+#define GATE_DISP0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &disp0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+#define GATE_DISP1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &disp1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr,	\
+	}
+
+static const struct mtk_gate mm_clks[] = {
+	GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0),
+	GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+	GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2),
+	GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3),
+	GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4),
+	GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5),
+	GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6),
+	GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7),
+	GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8),
+	GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+	GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10),
+	GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+	GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12),
+	GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13),
+	GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14),
+	GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15),
+	GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16),
+	GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17),
+	GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18),
+	GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+	GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20),
+	GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0),
+	GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1),
+	GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2),
+	GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3),
+	GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4),
+	GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5),
+	GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6),
+	GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7),
+	GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8),
+	GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9),
+	GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10),
+	GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11),
+	GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14),
+};
+
+static const struct of_device_id of_match_clk_mt2701_mm[] = {
+	{ .compatible = "mediatek,mt2701-mmsys", },
+	{}
+};
+
+static int clk_mt2701_mm_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+
+	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_mm_drv = {
+	.probe = clk_mt2701_mm_probe,
+	.driver = {
+		.name = "clk-mt2701-mm",
+		.of_match_table = of_match_clk_mt2701_mm,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_mm_drv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-vdec.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-vdec.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mt2701-vdec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mt2701-vdec.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2014 MediaTek Inc.
+ * Author: Shunli Wang <shunli.wang@mediatek.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/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt2701-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+	.set_ofs = 0x0000,
+	.clr_ofs = 0x0004,
+	.sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+	.set_ofs = 0x0008,
+	.clr_ofs = 0x000c,
+	.sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec0_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) {	\
+		.id = _id,				\
+		.name = _name,				\
+		.parent_name = _parent,			\
+		.regs = &vdec1_cg_regs,			\
+		.shift = _shift,			\
+		.ops = &mtk_clk_gate_ops_setclr_inv,	\
+	}
+
+static const struct mtk_gate vdec_clks[] = {
+	GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0),
+	GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0),
+};
+
+static const struct of_device_id of_match_clk_mt2701_vdec[] = {
+	{ .compatible = "mediatek,mt2701-vdecsys", },
+	{}
+};
+
+static int clk_mt2701_vdec_probe(struct platform_device *pdev)
+{
+	struct clk_onecell_data *clk_data;
+	int r;
+	struct device_node *node = pdev->dev.of_node;
+
+	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+
+	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+						clk_data);
+
+	r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+	if (r)
+		dev_err(&pdev->dev,
+			"could not register clock provider: %s: %d\n",
+			pdev->name, r);
+
+	return r;
+}
+
+static struct platform_driver clk_mt2701_vdec_drv = {
+	.probe = clk_mt2701_vdec_probe,
+	.driver = {
+		.name = "clk-mt2701-vdec",
+		.of_match_table = of_match_clk_mt2701_vdec,
+	},
+};
+
+builtin_platform_driver(clk_mt2701_vdec_drv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mtk.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mtk.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mtk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mtk.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,6 +58,9 @@ void mtk_clk_register_fixed_clks(const s
 	for (i = 0; i < num; i++) {
 		const struct mtk_fixed_clk *rc = &clks[i];
 
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id]))
+			continue;
+
 		clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0,
 					      rc->rate);
 
@@ -81,6 +84,9 @@ void mtk_clk_register_factors(const stru
 	for (i = 0; i < num; i++) {
 		const struct mtk_fixed_factor *ff = &clks[i];
 
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id]))
+			continue;
+
 		clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
 				CLK_SET_RATE_PARENT, ff->mult, ff->div);
 
@@ -116,6 +122,9 @@ int mtk_clk_register_gates(struct device
 	for (i = 0; i < num; i++) {
 		const struct mtk_gate *gate = &clks[i];
 
+		if (!IS_ERR_OR_NULL(clk_data->clks[gate->id]))
+			continue;
+
 		clk = mtk_clk_register_gate(gate->name, gate->parent_name,
 				regmap,
 				gate->regs->set_ofs,
@@ -232,6 +241,9 @@ void mtk_clk_register_composites(const s
 	for (i = 0; i < num; i++) {
 		const struct mtk_composite *mc = &mcs[i];
 
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id]))
+			continue;
+
 		clk = mtk_clk_register_composite(mc, base, lock);
 
 		if (IS_ERR(clk)) {
@@ -244,3 +256,31 @@ void mtk_clk_register_composites(const s
 			clk_data->clks[mc->id] = clk;
 	}
 }
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+			int num, void __iomem *base, spinlock_t *lock,
+				struct clk_onecell_data *clk_data)
+{
+	struct clk *clk;
+	int i;
+
+	for (i = 0; i <  num; i++) {
+		const struct mtk_clk_divider *mcd = &mcds[i];
+
+		if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id]))
+			continue;
+
+		clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
+			mcd->flags, base +  mcd->div_reg, mcd->div_shift,
+			mcd->div_width, mcd->clk_divider_flags, lock);
+
+		if (IS_ERR(clk)) {
+			pr_err("Failed to register clk %s: %ld\n",
+				mcd->name, PTR_ERR(clk));
+			continue;
+		}
+
+		if (clk_data)
+			clk_data->clks[mcd->id] = clk;
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mtk.h linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mtk.h
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-mtk.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-mtk.h	2017-02-12 16:03:20.000000000 -0500
@@ -87,7 +87,8 @@ struct mtk_composite {
  * In case the rate change propagation to parent clocks is undesirable,
  * this macro allows to specify the clock flags manually.
  */
-#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) {	\
+#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
+			_gate, _flags) {				\
 		.id = _id,						\
 		.name = _name,						\
 		.mux_reg = _reg,					\
@@ -106,7 +107,8 @@ struct mtk_composite {
  * parent clock by default.
  */
 #define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)	\
-	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, CLK_SET_RATE_PARENT)
+	MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,	\
+		_gate, CLK_SET_RATE_PARENT)
 
 #define MUX(_id, _name, _parents, _reg, _shift, _width) {		\
 		.id = _id,						\
@@ -121,7 +123,8 @@ struct mtk_composite {
 		.flags = CLK_SET_RATE_PARENT,				\
 	}
 
-#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, _div_width, _div_shift) {	\
+#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg,	\
+					_div_width, _div_shift) {	\
 		.id = _id,						\
 		.parent = _parent,					\
 		.name = _name,						\
@@ -156,12 +159,40 @@ struct mtk_gate {
 	const struct clk_ops *ops;
 };
 
-int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
-		int num, struct clk_onecell_data *clk_data);
+int mtk_clk_register_gates(struct device_node *node,
+			const struct mtk_gate *clks, int num,
+			struct clk_onecell_data *clk_data);
+
+struct mtk_clk_divider {
+	int id;
+	const char *name;
+	const char *parent_name;
+	unsigned long flags;
+
+	u32 div_reg;
+	unsigned char div_shift;
+	unsigned char div_width;
+	unsigned char clk_divider_flags;
+	const struct clk_div_table *clk_div_table;
+};
+
+#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) {	\
+		.id = _id,					\
+		.name = _name,					\
+		.parent_name = _parent,				\
+		.div_reg = _reg,				\
+		.div_shift = _shift,				\
+		.div_width = _width,				\
+}
+
+void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
+			int num, void __iomem *base, spinlock_t *lock,
+				struct clk_onecell_data *clk_data);
 
 struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
 
 #define HAVE_RST_BAR	BIT(0)
+#define PLL_AO		BIT(1)
 
 struct mtk_pll_div_table {
 	u32 div;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/clk-pll.c linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-pll.c
--- linux-libre-4.9-gnu/drivers/clk/mediatek/clk-pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/clk-pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -301,6 +301,7 @@ static struct clk *mtk_clk_register_pll(
 	pll->data = data;
 
 	init.name = data->name;
+	init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
 	init.ops = &mtk_pll_ops;
 	init.parent_names = &parent_name;
 	init.num_parents = 1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/Kconfig linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/Kconfig
--- linux-libre-4.9-gnu/drivers/clk/mediatek/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,49 @@ config COMMON_CLK_MEDIATEK
 	---help---
 	  Mediatek SoCs' clock support.
 
+config COMMON_CLK_MT2701
+	bool "Clock driver for Mediatek MT2701"
+	select COMMON_CLK_MEDIATEK
+	default ARCH_MEDIATEK
+	---help---
+	  This driver supports Mediatek MT2701 basic clocks.
+
+config COMMON_CLK_MT2701_MMSYS
+	bool "Clock driver for Mediatek MT2701 mmsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 mmsys clocks.
+
+config COMMON_CLK_MT2701_IMGSYS
+	bool "Clock driver for Mediatek MT2701 imgsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 imgsys clocks.
+
+config COMMON_CLK_MT2701_VDECSYS
+	bool "Clock driver for Mediatek MT2701 vdecsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 vdecsys clocks.
+
+config COMMON_CLK_MT2701_HIFSYS
+	bool "Clock driver for Mediatek MT2701 hifsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 hifsys clocks.
+
+config COMMON_CLK_MT2701_ETHSYS
+	bool "Clock driver for Mediatek MT2701 ethsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 ethsys clocks.
+
+config COMMON_CLK_MT2701_BDPSYS
+	bool "Clock driver for Mediatek MT2701 bdpsys"
+	select COMMON_CLK_MT2701
+	---help---
+	  This driver supports Mediatek MT2701 bdpsys clocks.
+
 config COMMON_CLK_MT8135
 	bool "Clock driver for Mediatek MT8135"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mediatek/Makefile linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/Makefile
--- linux-libre-4.9-gnu/drivers/clk/mediatek/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mediatek/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,11 @@
 obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
+obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
+obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
+obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
+obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
+obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
+obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
 obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
 obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mmp/clk-of-mmp2.c linux-libre-4.10-rc8-gnu/drivers/clk/mmp/clk-of-mmp2.c
--- linux-libre-4.9-gnu/drivers/clk/mmp/clk-of-mmp2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mmp/clk-of-mmp2.c	2017-02-12 16:03:20.000000000 -0500
@@ -309,19 +309,19 @@ static void __init mmp2_clk_init(struct
 	pxa_unit->mpmu_base = of_iomap(np, 0);
 	if (!pxa_unit->mpmu_base) {
 		pr_err("failed to map mpmu registers\n");
-		return;
+		goto free_memory;
 	}
 
 	pxa_unit->apmu_base = of_iomap(np, 1);
 	if (!pxa_unit->apmu_base) {
 		pr_err("failed to map apmu registers\n");
-		return;
+		goto unmap_mpmu_region;
 	}
 
 	pxa_unit->apbc_base = of_iomap(np, 2);
 	if (!pxa_unit->apbc_base) {
 		pr_err("failed to map apbc registers\n");
-		return;
+		goto unmap_apmu_region;
 	}
 
 	mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS);
@@ -333,6 +333,15 @@ static void __init mmp2_clk_init(struct
 	mmp2_axi_periph_clk_init(pxa_unit);
 
 	mmp2_clk_reset_init(np, pxa_unit);
+
+	return;
+
+unmap_apmu_region:
+	iounmap(pxa_unit->apmu_base);
+unmap_mpmu_region:
+	iounmap(pxa_unit->mpmu_base);
+free_memory:
+	kfree(pxa_unit);
 }
 
 CLK_OF_DECLARE(mmp2_clk, "marvell,mmp2-clock", mmp2_clk_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mmp/clk-of-pxa1928.c linux-libre-4.10-rc8-gnu/drivers/clk/mmp/clk-of-pxa1928.c
--- linux-libre-4.9-gnu/drivers/clk/mmp/clk-of-pxa1928.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mmp/clk-of-pxa1928.c	2017-02-12 16:03:20.000000000 -0500
@@ -216,6 +216,7 @@ static void __init pxa1928_mpmu_clk_init
 	pxa_unit->mpmu_base = of_iomap(np, 0);
 	if (!pxa_unit->mpmu_base) {
 		pr_err("failed to map mpmu registers\n");
+		kfree(pxa_unit);
 		return;
 	}
 
@@ -234,6 +235,7 @@ static void __init pxa1928_apmu_clk_init
 	pxa_unit->apmu_base = of_iomap(np, 0);
 	if (!pxa_unit->apmu_base) {
 		pr_err("failed to map apmu registers\n");
+		kfree(pxa_unit);
 		return;
 	}
 
@@ -254,6 +256,7 @@ static void __init pxa1928_apbc_clk_init
 	pxa_unit->apbc_base = of_iomap(np, 0);
 	if (!pxa_unit->apbc_base) {
 		pr_err("failed to map apbc registers\n");
+		kfree(pxa_unit);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mmp/clk-of-pxa910.c linux-libre-4.10-rc8-gnu/drivers/clk/mmp/clk-of-pxa910.c
--- linux-libre-4.9-gnu/drivers/clk/mmp/clk-of-pxa910.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mmp/clk-of-pxa910.c	2017-02-12 16:03:20.000000000 -0500
@@ -278,25 +278,25 @@ static void __init pxa910_clk_init(struc
 	pxa_unit->mpmu_base = of_iomap(np, 0);
 	if (!pxa_unit->mpmu_base) {
 		pr_err("failed to map mpmu registers\n");
-		return;
+		goto free_memory;
 	}
 
 	pxa_unit->apmu_base = of_iomap(np, 1);
 	if (!pxa_unit->apmu_base) {
 		pr_err("failed to map apmu registers\n");
-		return;
+		goto unmap_mpmu_region;
 	}
 
 	pxa_unit->apbc_base = of_iomap(np, 2);
 	if (!pxa_unit->apbc_base) {
 		pr_err("failed to map apbc registers\n");
-		return;
+		goto unmap_apmu_region;
 	}
 
 	pxa_unit->apbcp_base = of_iomap(np, 3);
 	if (!pxa_unit->apbcp_base) {
 		pr_err("failed to map apbcp registers\n");
-		return;
+		goto unmap_apbc_region;
 	}
 
 	mmp_clk_init(np, &pxa_unit->unit, PXA910_NR_CLKS);
@@ -308,6 +308,17 @@ static void __init pxa910_clk_init(struc
 	pxa910_axi_periph_clk_init(pxa_unit);
 
 	pxa910_clk_reset_init(np, pxa_unit);
+
+	return;
+
+unmap_apbc_region:
+	iounmap(pxa_unit->apbc_base);
+unmap_apmu_region:
+	iounmap(pxa_unit->apmu_base);
+unmap_mpmu_region:
+	iounmap(pxa_unit->mpmu_base);
+free_memory:
+	kfree(pxa_unit);
 }
 
 CLK_OF_DECLARE(pxa910_clk, "marvell,pxa910-clock", pxa910_clk_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mvebu/ap806-system-controller.c linux-libre-4.10-rc8-gnu/drivers/clk/mvebu/ap806-system-controller.c
--- linux-libre-4.9-gnu/drivers/clk/mvebu/ap806-system-controller.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mvebu/ap806-system-controller.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/mfd/syscon.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -135,34 +135,17 @@ fail0:
 	return ret;
 }
 
-static int ap806_syscon_clk_remove(struct platform_device *pdev)
-{
-	of_clk_del_provider(pdev->dev.of_node);
-	clk_unregister_fixed_factor(ap806_clks[3]);
-	clk_unregister_fixed_rate(ap806_clks[2]);
-	clk_unregister_fixed_rate(ap806_clks[1]);
-	clk_unregister_fixed_rate(ap806_clks[0]);
-
-	return 0;
-}
-
 static const struct of_device_id ap806_syscon_of_match[] = {
 	{ .compatible = "marvell,ap806-system-controller", },
 	{ }
 };
-MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
 
 static struct platform_driver ap806_syscon_driver = {
 	.probe = ap806_syscon_clk_probe,
-	.remove = ap806_syscon_clk_remove,
 	.driver		= {
 		.name	= "marvell-ap806-system-controller",
 		.of_match_table = ap806_syscon_of_match,
+		.suppress_bind_attrs = true,
 	},
 };
-
-module_platform_driver(ap806_syscon_driver);
-
-MODULE_DESCRIPTION("Marvell AP806 System Controller driver");
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(ap806_syscon_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/mvebu/cp110-system-controller.c linux-libre-4.10-rc8-gnu/drivers/clk/mvebu/cp110-system-controller.c
--- linux-libre-4.9-gnu/drivers/clk/mvebu/cp110-system-controller.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/mvebu/cp110-system-controller.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/mfd/syscon.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -87,7 +87,7 @@ struct cp110_gate_clk {
 	u8 bit_idx;
 };
 
-#define to_cp110_gate_clk(clk) container_of(clk, struct cp110_gate_clk, hw)
+#define to_cp110_gate_clk(hw) container_of(hw, struct cp110_gate_clk, hw)
 
 static int cp110_gate_enable(struct clk_hw *hw)
 {
@@ -123,13 +123,14 @@ static const struct clk_ops cp110_gate_o
 	.is_enabled = cp110_gate_is_enabled,
 };
 
-static struct clk *cp110_register_gate(const char *name,
-				       const char *parent_name,
-				       struct regmap *regmap, u8 bit_idx)
+static struct clk_hw *cp110_register_gate(const char *name,
+					  const char *parent_name,
+					  struct regmap *regmap, u8 bit_idx)
 {
 	struct cp110_gate_clk *gate;
-	struct clk *clk;
+	struct clk_hw *hw;
 	struct clk_init_data init;
+	int ret;
 
 	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
 	if (!gate)
@@ -146,39 +147,37 @@ static struct clk *cp110_register_gate(c
 	gate->bit_idx = bit_idx;
 	gate->hw.init = &init;
 
-	clk = clk_register(NULL, &gate->hw);
-	if (IS_ERR(clk))
+	hw = &gate->hw;
+	ret = clk_hw_register(NULL, hw);
+	if (ret) {
 		kfree(gate);
+		hw = ERR_PTR(ret);
+	}
 
-	return clk;
+	return hw;
 }
 
-static void cp110_unregister_gate(struct clk *clk)
+static void cp110_unregister_gate(struct clk_hw *hw)
 {
-	struct clk_hw *hw;
-
-	hw = __clk_get_hw(clk);
-	if (!hw)
-		return;
-
-	clk_unregister(clk);
+	clk_hw_unregister(hw);
 	kfree(to_cp110_gate_clk(hw));
 }
 
-static struct clk *cp110_of_clk_get(struct of_phandle_args *clkspec, void *data)
+static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
+				       void *data)
 {
-	struct clk_onecell_data *clk_data = data;
+	struct clk_hw_onecell_data *clk_data = data;
 	unsigned int type = clkspec->args[0];
 	unsigned int idx = clkspec->args[1];
 
 	if (type == CP110_CLK_TYPE_CORE) {
 		if (idx > CP110_MAX_CORE_CLOCKS)
 			return ERR_PTR(-EINVAL);
-		return clk_data->clks[idx];
+		return clk_data->hws[idx];
 	} else if (type == CP110_CLK_TYPE_GATABLE) {
 		if (idx > CP110_MAX_GATABLE_CLOCKS)
 			return ERR_PTR(-EINVAL);
-		return clk_data->clks[CP110_MAX_CORE_CLOCKS + idx];
+		return clk_data->hws[CP110_MAX_CORE_CLOCKS + idx];
 	}
 
 	return ERR_PTR(-EINVAL);
@@ -189,8 +188,8 @@ static int cp110_syscon_clk_probe(struct
 	struct regmap *regmap;
 	struct device_node *np = pdev->dev.of_node;
 	const char *ppv2_name, *apll_name, *core_name, *eip_name, *nand_name;
-	struct clk_onecell_data *cp110_clk_data;
-	struct clk *clk, **cp110_clks;
+	struct clk_hw_onecell_data *cp110_clk_data;
+	struct clk_hw *hw, **cp110_clks;
 	u32 nand_clk_ctrl;
 	int i, ret;
 
@@ -203,80 +202,75 @@ static int cp110_syscon_clk_probe(struct
 	if (ret)
 		return ret;
 
-	cp110_clks = devm_kcalloc(&pdev->dev, sizeof(struct clk *),
-				  CP110_CLK_NUM, GFP_KERNEL);
-	if (!cp110_clks)
-		return -ENOMEM;
-
-	cp110_clk_data = devm_kzalloc(&pdev->dev,
-				      sizeof(*cp110_clk_data),
+	cp110_clk_data = devm_kzalloc(&pdev->dev, sizeof(*cp110_clk_data) +
+				      sizeof(struct clk_hw *) * CP110_CLK_NUM,
 				      GFP_KERNEL);
 	if (!cp110_clk_data)
 		return -ENOMEM;
 
-	cp110_clk_data->clks = cp110_clks;
-	cp110_clk_data->clk_num = CP110_CLK_NUM;
+	cp110_clks = cp110_clk_data->hws;
+	cp110_clk_data->num = CP110_CLK_NUM;
 
-	/* Register the APLL which is the root of the clk tree */
+	/* Register the APLL which is the root of the hw tree */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_APLL, &apll_name);
-	clk = clk_register_fixed_rate(NULL, apll_name, NULL, 0,
-				      1000 * 1000 * 1000);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
+	hw = clk_hw_register_fixed_rate(NULL, apll_name, NULL, 0,
+					1000 * 1000 * 1000);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
 		goto fail0;
 	}
 
-	cp110_clks[CP110_CORE_APLL] = clk;
+	cp110_clks[CP110_CORE_APLL] = hw;
 
 	/* PPv2 is APLL/3 */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_PPV2, &ppv2_name);
-	clk = clk_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
+	hw = clk_hw_register_fixed_factor(NULL, ppv2_name, apll_name, 0, 1, 3);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
 		goto fail1;
 	}
 
-	cp110_clks[CP110_CORE_PPV2] = clk;
+	cp110_clks[CP110_CORE_PPV2] = hw;
 
 	/* EIP clock is APLL/2 */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_EIP, &eip_name);
-	clk = clk_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
+	hw = clk_hw_register_fixed_factor(NULL, eip_name, apll_name, 0, 1, 2);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
 		goto fail2;
 	}
 
-	cp110_clks[CP110_CORE_EIP] = clk;
+	cp110_clks[CP110_CORE_EIP] = hw;
 
 	/* Core clock is EIP/2 */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_CORE, &core_name);
-	clk = clk_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
+	hw = clk_hw_register_fixed_factor(NULL, core_name, eip_name, 0, 1, 2);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
 		goto fail3;
 	}
 
-	cp110_clks[CP110_CORE_CORE] = clk;
+	cp110_clks[CP110_CORE_CORE] = hw;
 
 	/* NAND can be either APLL/2.5 or core clock */
 	of_property_read_string_index(np, "core-clock-output-names",
 				      CP110_CORE_NAND, &nand_name);
 	if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
-		clk = clk_register_fixed_factor(NULL, nand_name,
-						apll_name, 0, 2, 5);
+		hw = clk_hw_register_fixed_factor(NULL, nand_name,
+						   apll_name, 0, 2, 5);
 	else
-		clk = clk_register_fixed_factor(NULL, nand_name,
-						core_name, 0, 1, 1);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
+		hw = clk_hw_register_fixed_factor(NULL, nand_name,
+						   core_name, 0, 1, 1);
+	if (IS_ERR(hw)) {
+		ret = PTR_ERR(hw);
 		goto fail4;
 	}
 
-	cp110_clks[CP110_CORE_NAND] = clk;
+	cp110_clks[CP110_CORE_NAND] = hw;
 
 	for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
 		const char *parent, *name;
@@ -335,16 +329,16 @@ static int cp110_syscon_clk_probe(struct
 			break;
 		}
 
-		clk = cp110_register_gate(name, parent, regmap, i);
-		if (IS_ERR(clk)) {
-			ret = PTR_ERR(clk);
+		hw = cp110_register_gate(name, parent, regmap, i);
+		if (IS_ERR(hw)) {
+			ret = PTR_ERR(hw);
 			goto fail_gate;
 		}
 
-		cp110_clks[CP110_MAX_CORE_CLOCKS + i] = clk;
+		cp110_clks[CP110_MAX_CORE_CLOCKS + i] = hw;
 	}
 
-	ret = of_clk_add_provider(np, cp110_of_clk_get, cp110_clk_data);
+	ret = of_clk_add_hw_provider(np, cp110_of_clk_get, cp110_clk_data);
 	if (ret)
 		goto fail_clk_add;
 
@@ -355,65 +349,36 @@ static int cp110_syscon_clk_probe(struct
 fail_clk_add:
 fail_gate:
 	for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
-		clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
+		hw = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
 
-		if (clk)
-			cp110_unregister_gate(clk);
+		if (hw)
+			cp110_unregister_gate(hw);
 	}
 
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
+	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
 fail4:
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
+	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
 fail3:
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
+	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
 fail2:
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
+	clk_hw_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
 fail1:
-	clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
+	clk_hw_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
 fail0:
 	return ret;
 }
 
-static int cp110_syscon_clk_remove(struct platform_device *pdev)
-{
-	struct clk **cp110_clks = platform_get_drvdata(pdev);
-	int i;
-
-	of_clk_del_provider(pdev->dev.of_node);
-
-	for (i = 0; i < CP110_MAX_GATABLE_CLOCKS; i++) {
-		struct clk *clk = cp110_clks[CP110_MAX_CORE_CLOCKS + i];
-
-		if (clk)
-			cp110_unregister_gate(clk);
-	}
-
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_NAND]);
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_CORE]);
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_EIP]);
-	clk_unregister_fixed_factor(cp110_clks[CP110_CORE_PPV2]);
-	clk_unregister_fixed_rate(cp110_clks[CP110_CORE_APLL]);
-
-	return 0;
-}
-
 static const struct of_device_id cp110_syscon_of_match[] = {
 	{ .compatible = "marvell,cp110-system-controller0", },
 	{ }
 };
-MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
 
 static struct platform_driver cp110_syscon_driver = {
 	.probe = cp110_syscon_clk_probe,
-	.remove = cp110_syscon_clk_remove,
 	.driver		= {
 		.name	= "marvell-cp110-system-controller0",
 		.of_match_table = cp110_syscon_of_match,
+		.suppress_bind_attrs = true,
 	},
 };
-
-module_platform_driver(cp110_syscon_driver);
-
-MODULE_DESCRIPTION("Marvell CP110 System Controller 0 driver");
-MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(cp110_syscon_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/nxp/clk-lpc18xx-ccu.c linux-libre-4.10-rc8-gnu/drivers/clk/nxp/clk-lpc18xx-ccu.c
--- linux-libre-4.9-gnu/drivers/clk/nxp/clk-lpc18xx-ccu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/nxp/clk-lpc18xx-ccu.c	2017-02-12 16:03:20.000000000 -0500
@@ -277,12 +277,15 @@ static void __init lpc18xx_ccu_init(stru
 	}
 
 	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
-	if (!clk_data)
+	if (!clk_data) {
+		iounmap(reg_base);
 		return;
+	}
 
 	clk_data->num = of_property_count_strings(np, "clock-names");
 	clk_data->name = kcalloc(clk_data->num, sizeof(char *), GFP_KERNEL);
 	if (!clk_data->name) {
+		iounmap(reg_base);
 		kfree(clk_data);
 		return;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/nxp/clk-lpc32xx.c linux-libre-4.10-rc8-gnu/drivers/clk/nxp/clk-lpc32xx.c
--- linux-libre-4.9-gnu/drivers/clk/nxp/clk-lpc32xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/nxp/clk-lpc32xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -1282,13 +1282,13 @@ static struct clk_hw_proto clk_hw_proto[
 
 	LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0),
 	LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL,
-			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+			   CLK_DIVIDER_ONE_BASED),
 	LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0),
 	LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE),
 
 	LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0),
 	LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL,
-			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+			   CLK_DIVIDER_ONE_BASED),
 	LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0),
 	LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE),
 
@@ -1335,8 +1335,7 @@ static struct clk_hw_proto clk_hw_proto[
 	LPC32XX_DEFINE_GATE(USB_DIV_GATE, USB_CTRL, 17, 0),
 	LPC32XX_DEFINE_COMPOSITE(USB_DIV, _NULL, USB_DIV_DIV, USB_DIV_GATE),
 
-	LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL,
-			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
+	LPC32XX_DEFINE_DIV(SD_DIV, MS_CTRL, 0, 4, NULL, CLK_DIVIDER_ONE_BASED),
 	LPC32XX_DEFINE_CLK(SD_GATE, MS_CTRL, BIT(5) | BIT(9), BIT(5) | BIT(9),
 			   0x0, BIT(5) | BIT(9), 0x0, 0x0, clk_mask_ops),
 	LPC32XX_DEFINE_COMPOSITE(SD, _NULL, SD_DIV, SD_GATE),
@@ -1478,6 +1477,20 @@ static struct clk * __init lpc32xx_clk_r
 	return clk;
 }
 
+static void __init lpc32xx_clk_div_quirk(u32 reg, u32 div_mask, u32 gate)
+{
+	u32 val;
+
+	regmap_read(clk_regmap, reg, &val);
+
+	if (!(val & div_mask)) {
+		val &= ~gate;
+		val |= BIT(__ffs(div_mask));
+	}
+
+	regmap_update_bits(clk_regmap, reg, gate | div_mask, val);
+}
+
 static void __init lpc32xx_clk_init(struct device_node *np)
 {
 	unsigned int i;
@@ -1517,6 +1530,17 @@ static void __init lpc32xx_clk_init(stru
 		return;
 	}
 
+	/*
+	 * Divider part of PWM and MS clocks requires a quirk to avoid
+	 * a misinterpretation of formally valid zero value in register
+	 * bitfield, which indicates another clock gate. Instead of
+	 * adding complexity to a gate clock ensure that zero value in
+	 * divider clock is never met in runtime.
+	 */
+	lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf0, BIT(0));
+	lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_PWMCLK_CTRL, 0xf00, BIT(2));
+	lpc32xx_clk_div_quirk(LPC32XX_CLKPWR_MS_CTRL, 0xf, BIT(5) | BIT(9));
+
 	for (i = 1; i < LPC32XX_CLK_MAX; i++) {
 		clk[i] = lpc32xx_clk_register(i);
 		if (IS_ERR(clk[i])) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa25x.c linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa25x.c
--- linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa25x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa25x.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <mach/pxa2xx-regs.h>
+#include <mach/smemc.h>
 
 #include <dt-bindings/clock/pxa-clock.h>
 #include "clk-pxa.h"
@@ -30,6 +31,17 @@ enum {
 	PXA_CORE_TURBO,
 };
 
+#define PXA25x_CLKCFG(T)			\
+	(CLKCFG_FCS |				\
+	 ((T) ? CLKCFG_TURBO : 0))
+#define PXA25x_CCCR(N2, M, L) (N2 << 7 | M << 5 | L)
+
+#define MDCNFG_DRAC2(mdcnfg)	(((mdcnfg) >> 21) & 0x3)
+#define MDCNFG_DRAC0(mdcnfg)	(((mdcnfg) >> 5) & 0x3)
+
+/* Define the refresh period in mSec for the SDRAM and the number of rows */
+#define SDRAM_TREF	64	/* standard 64ms SDRAM */
+
 /*
  * Various clock factors driven by the CCCR register.
  */
@@ -48,6 +60,34 @@ static const char * const get_freq_khz[]
 	"core", "run", "cpll", "memory"
 };
 
+static int get_sdram_rows(void)
+{
+	static int sdram_rows;
+	unsigned int drac2 = 0, drac0 = 0;
+	u32 mdcnfg;
+
+	if (sdram_rows)
+		return sdram_rows;
+
+	mdcnfg = readl_relaxed(MDCNFG);
+
+	if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
+		drac2 = MDCNFG_DRAC2(mdcnfg);
+
+	if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
+		drac0 = MDCNFG_DRAC0(mdcnfg);
+
+	sdram_rows = 1 << (11 + max(drac0, drac2));
+	return sdram_rows;
+}
+
+static u32 mdrefr_dri(unsigned int freq_khz)
+{
+	u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows();
+
+	return interval / 32;
+}
+
 /*
  * Get the clock frequency as reflected by CCCR and the turbo flag.
  * We assume these values have been applied via a fcs.
@@ -139,6 +179,21 @@ static struct desc_clk_cken pxa25x_clock
 			     clk_pxa25x_memory_parents, 0),
 };
 
+/*
+ * In this table, PXA25x_CCCR(N2, M, L) has the following meaning, where :
+ *   - freq_cpll = n * m * L * 3.6864 MHz
+ *   - n = N2 / 2
+ *   - m = 2^(M - 1), where 1 <= M <= 3
+ *   - l = L_clk_mult[L], ie. { 0, 27, 32, 36, 40, 45, 0, }[L]
+ */
+static struct pxa2xx_freq pxa25x_freqs[] = {
+	/* CPU  MEMBUS  CCCR                  DIV2 CCLKCFG      */
+	{ 99532800, 99500, PXA25x_CCCR(2,  1, 1),  1, PXA25x_CLKCFG(1)},
+	{199065600, 99500, PXA25x_CCCR(4,  1, 1),  0, PXA25x_CLKCFG(1)},
+	{298598400, 99500, PXA25x_CCCR(3,  2, 1),  0, PXA25x_CLKCFG(1)},
+	{398131200, 99500, PXA25x_CCCR(4,  2, 1),  0, PXA25x_CLKCFG(1)},
+};
+
 static u8 clk_pxa25x_core_get_parent(struct clk_hw *hw)
 {
 	unsigned long clkcfg;
@@ -151,13 +206,24 @@ static u8 clk_pxa25x_core_get_parent(str
 	return PXA_CORE_RUN;
 }
 
-static unsigned long clk_pxa25x_core_get_rate(struct clk_hw *hw,
-					      unsigned long parent_rate)
+static int clk_pxa25x_core_set_parent(struct clk_hw *hw, u8 index)
 {
-	return parent_rate;
+	if (index > PXA_CORE_TURBO)
+		return -EINVAL;
+
+	pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
+
+	return 0;
 }
+
+static int clk_pxa25x_core_determine_rate(struct clk_hw *hw,
+					  struct clk_rate_request *req)
+{
+	return __clk_mux_determine_rate(hw, req);
+}
+
 PARENTS(clk_pxa25x_core) = { "run", "cpll" };
-MUX_RO_RATE_RO_OPS(clk_pxa25x_core, "core");
+MUX_OPS(clk_pxa25x_core, "core", CLK_SET_RATE_PARENT);
 
 static unsigned long clk_pxa25x_run_get_rate(struct clk_hw *hw,
 					     unsigned long parent_rate)
@@ -182,17 +248,42 @@ static unsigned long clk_pxa25x_cpll_get
 	m = M_clk_mult[(cccr >> 5) & 0x03];
 	n2 = N2_clk_mult[(cccr >> 7) & 0x07];
 
-	if (t)
-		return m * l * n2 * parent_rate / 2;
-	return m * l * parent_rate;
+	return m * l * n2 * parent_rate / 2;
+}
+
+static int clk_pxa25x_cpll_determine_rate(struct clk_hw *hw,
+					  struct clk_rate_request *req)
+{
+	return pxa2xx_determine_rate(req, pxa25x_freqs,
+				     ARRAY_SIZE(pxa25x_freqs));
+}
+
+static int clk_pxa25x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long parent_rate)
+{
+	int i;
+
+	pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
+	for (i = 0; i < ARRAY_SIZE(pxa25x_freqs); i++)
+		if (pxa25x_freqs[i].cpll == rate)
+			break;
+
+	if (i >= ARRAY_SIZE(pxa25x_freqs))
+		return -EINVAL;
+
+	pxa2xx_cpll_change(&pxa25x_freqs[i], mdrefr_dri, MDREFR, CCCR);
+
+	return 0;
 }
 PARENTS(clk_pxa25x_cpll) = { "osc_3_6864mhz" };
-RATE_RO_OPS(clk_pxa25x_cpll, "cpll");
+RATE_OPS(clk_pxa25x_cpll, "cpll");
 
 static void __init pxa25x_register_core(void)
 {
-	clk_register_clk_pxa25x_cpll();
-	clk_register_clk_pxa25x_run();
+	clkdev_pxa_register(CLK_NONE, "cpll", NULL,
+			    clk_register_clk_pxa25x_cpll());
+	clkdev_pxa_register(CLK_NONE, "run", NULL,
+			    clk_register_clk_pxa25x_run());
 	clkdev_pxa_register(CLK_CORE, "core", NULL,
 			    clk_register_clk_pxa25x_core());
 }
@@ -214,7 +305,8 @@ static void __init pxa25x_base_clocks_in
 {
 	pxa25x_register_plls();
 	pxa25x_register_core();
-	clk_register_clk_pxa25x_memory();
+	clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
+			    clk_register_clk_pxa25x_memory());
 }
 
 #define DUMMY_CLK(_con_id, _dev_id, _parent) \
@@ -230,7 +322,7 @@ static struct dummy_clk dummy_clks[] __i
 	DUMMY_CLK("GPIO11_CLK", NULL, "osc_3_6864mhz"),
 	DUMMY_CLK("GPIO12_CLK", NULL, "osc_32_768khz"),
 	DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
-	DUMMY_CLK("OSTIMER0", NULL, "osc_32_768khz"),
+	DUMMY_CLK("OSTIMER0", NULL, "osc_3_6864mhz"),
 	DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa27x.c linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa27x.c
--- linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa27x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa27x.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,8 @@
 #include <linux/clkdev.h>
 #include <linux/of.h>
 
+#include <mach/smemc.h>
+
 #include <dt-bindings/clock/pxa-clock.h>
 #include "clk-pxa.h"
 
@@ -45,11 +47,52 @@ enum {
 	PXA_MEM_RUN,
 };
 
+#define PXA27x_CLKCFG(B, HT, T)			\
+	(CLKCFG_FCS |				\
+	 ((B)  ? CLKCFG_FASTBUS : 0) |		\
+	 ((HT) ? CLKCFG_HALFTURBO : 0) |	\
+	 ((T)  ? CLKCFG_TURBO : 0))
+#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L)
+
+#define MDCNFG_DRAC2(mdcnfg)	(((mdcnfg) >> 21) & 0x3)
+#define MDCNFG_DRAC0(mdcnfg)	(((mdcnfg) >> 5) & 0x3)
+
+/* Define the refresh period in mSec for the SDRAM and the number of rows */
+#define SDRAM_TREF	64	/* standard 64ms SDRAM */
+
 static const char * const get_freq_khz[] = {
 	"core", "run", "cpll", "memory",
 	"system_bus"
 };
 
+static int get_sdram_rows(void)
+{
+	static int sdram_rows;
+	unsigned int drac2 = 0, drac0 = 0;
+	u32 mdcnfg;
+
+	if (sdram_rows)
+		return sdram_rows;
+
+	mdcnfg = readl_relaxed(MDCNFG);
+
+	if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
+		drac2 = MDCNFG_DRAC2(mdcnfg);
+
+	if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
+		drac0 = MDCNFG_DRAC0(mdcnfg);
+
+	sdram_rows = 1 << (11 + max(drac0, drac2));
+	return sdram_rows;
+}
+
+static u32 mdrefr_dri(unsigned int freq_khz)
+{
+	u32 interval = freq_khz * SDRAM_TREF / get_sdram_rows();
+
+	return (interval - 31) / 32;
+}
+
 /*
  * Get the clock frequency as reflected by CCSR and the turbo flag.
  * We assume these values have been applied via a fcs.
@@ -145,6 +188,42 @@ static struct desc_clk_cken pxa27x_clock
 
 };
 
+/*
+ * PXA270 definitions
+ *
+ * For the PXA27x:
+ * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG.
+ *
+ * A = 0 => memory controller clock from table 3-7,
+ * A = 1 => memory controller clock = system bus clock
+ * Run mode frequency	= 13 MHz * L
+ * Turbo mode frequency = 13 MHz * L * N
+ * System bus frequency = 13 MHz * L / (B + 1)
+ *
+ * In CCCR:
+ * A = 1
+ * L = 16	  oscillator to run mode ratio
+ * 2N = 6	  2 * (turbo mode to run mode ratio)
+ *
+ * In CCLKCFG:
+ * B = 1	  Fast bus mode
+ * HT = 0	  Half-Turbo mode
+ * T = 1	  Turbo mode
+ *
+ * For now, just support some of the combinations in table 3-7 of
+ * PXA27x Processor Family Developer's Manual to simplify frequency
+ * change sequences.
+ */
+static struct pxa2xx_freq pxa27x_freqs[] = {
+	{104000000, 104000, PXA27x_CCCR(1,  8, 2), 0, PXA27x_CLKCFG(1, 0, 1) },
+	{156000000, 104000, PXA27x_CCCR(1,  8, 3), 0, PXA27x_CLKCFG(1, 0, 1) },
+	{208000000, 208000, PXA27x_CCCR(0, 16, 2), 1, PXA27x_CLKCFG(0, 0, 1) },
+	{312000000, 208000, PXA27x_CCCR(1, 16, 3), 1, PXA27x_CLKCFG(1, 0, 1) },
+	{416000000, 208000, PXA27x_CCCR(1, 16, 4), 1, PXA27x_CLKCFG(1, 0, 1) },
+	{520000000, 208000, PXA27x_CCCR(1, 16, 5), 1, PXA27x_CLKCFG(1, 0, 1) },
+	{624000000, 208000, PXA27x_CCCR(1, 16, 6), 1, PXA27x_CLKCFG(1, 0, 1) },
+};
+
 static unsigned long clk_pxa27x_cpll_get_rate(struct clk_hw *hw,
 	unsigned long parent_rate)
 {
@@ -162,10 +241,35 @@ static unsigned long clk_pxa27x_cpll_get
 	L  = l * parent_rate;
 	N  = (L * n2) / 2;
 
-	return t ? N : L;
+	return N;
+}
+
+static int clk_pxa27x_cpll_determine_rate(struct clk_hw *hw,
+					  struct clk_rate_request *req)
+{
+	return pxa2xx_determine_rate(req, pxa27x_freqs,
+				     ARRAY_SIZE(pxa27x_freqs));
+}
+
+static int clk_pxa27x_cpll_set_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long parent_rate)
+{
+	int i;
+
+	pr_debug("%s(rate=%lu parent_rate=%lu)\n", __func__, rate, parent_rate);
+	for (i = 0; i < ARRAY_SIZE(pxa27x_freqs); i++)
+		if (pxa27x_freqs[i].cpll == rate)
+			break;
+
+	if (i >= ARRAY_SIZE(pxa27x_freqs))
+		return -EINVAL;
+
+	pxa2xx_cpll_change(&pxa27x_freqs[i], mdrefr_dri, MDREFR, CCCR);
+	return 0;
 }
+
 PARENTS(clk_pxa27x_cpll) = { "osc_13mhz" };
-RATE_RO_OPS(clk_pxa27x_cpll, "cpll");
+RATE_OPS(clk_pxa27x_cpll, "cpll");
 
 static unsigned long clk_pxa27x_lcd_base_get_rate(struct clk_hw *hw,
 						  unsigned long parent_rate)
@@ -217,31 +321,10 @@ static void __init pxa27x_register_plls(
 	clk_register_fixed_factor(NULL, "ppll_312mhz", "osc_13mhz", 0, 24, 1);
 }
 
-static unsigned long clk_pxa27x_core_get_rate(struct clk_hw *hw,
-					      unsigned long parent_rate)
-{
-	unsigned long clkcfg;
-	unsigned int t, ht, b, osc_forced;
-	unsigned long ccsr = readl(CCSR);
-
-	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
-	asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
-	t  = clkcfg & (1 << 0);
-	ht = clkcfg & (1 << 2);
-	b  = clkcfg & (1 << 3);
-
-	if (osc_forced)
-		return parent_rate;
-	if (ht)
-		return parent_rate / 2;
-	else
-		return parent_rate;
-}
-
 static u8 clk_pxa27x_core_get_parent(struct clk_hw *hw)
 {
 	unsigned long clkcfg;
-	unsigned int t, ht, b, osc_forced;
+	unsigned int t, ht, osc_forced;
 	unsigned long ccsr = readl(CCSR);
 
 	osc_forced = ccsr & (1 << CCCR_CPDIS_BIT);
@@ -251,14 +334,30 @@ static u8 clk_pxa27x_core_get_parent(str
 	asm("mrc\tp14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
 	t  = clkcfg & (1 << 0);
 	ht = clkcfg & (1 << 2);
-	b  = clkcfg & (1 << 3);
 
 	if (ht || t)
 		return PXA_CORE_TURBO;
 	return PXA_CORE_RUN;
 }
+
+static int clk_pxa27x_core_set_parent(struct clk_hw *hw, u8 index)
+{
+	if (index > PXA_CORE_TURBO)
+		return -EINVAL;
+
+	pxa2xx_core_turbo_switch(index == PXA_CORE_TURBO);
+
+	return 0;
+}
+
+static int clk_pxa27x_core_determine_rate(struct clk_hw *hw,
+					  struct clk_rate_request *req)
+{
+	return __clk_mux_determine_rate(hw, req);
+}
+
 PARENTS(clk_pxa27x_core) = { "osc_13mhz", "run", "cpll" };
-MUX_RO_RATE_RO_OPS(clk_pxa27x_core, "core");
+MUX_OPS(clk_pxa27x_core, "core", CLK_SET_RATE_PARENT);
 
 static unsigned long clk_pxa27x_run_get_rate(struct clk_hw *hw,
 					     unsigned long parent_rate)
@@ -273,9 +372,10 @@ RATE_RO_OPS(clk_pxa27x_run, "run");
 
 static void __init pxa27x_register_core(void)
 {
-	clk_register_clk_pxa27x_cpll();
-	clk_register_clk_pxa27x_run();
-
+	clkdev_pxa_register(CLK_NONE, "cpll", NULL,
+			    clk_register_clk_pxa27x_cpll());
+	clkdev_pxa_register(CLK_NONE, "run", NULL,
+			    clk_register_clk_pxa27x_run());
 	clkdev_pxa_register(CLK_CORE, "core", NULL,
 			    clk_register_clk_pxa27x_core());
 }
@@ -294,9 +394,9 @@ static unsigned long clk_pxa27x_system_b
 	if (osc_forced)
 		return parent_rate;
 	if (b)
-		return parent_rate / 2;
-	else
 		return parent_rate;
+	else
+		return parent_rate / 2;
 }
 
 static u8 clk_pxa27x_system_bus_get_parent(struct clk_hw *hw)
@@ -385,8 +485,10 @@ static void __init pxa27x_base_clocks_in
 {
 	pxa27x_register_plls();
 	pxa27x_register_core();
-	clk_register_clk_pxa27x_system_bus();
-	clk_register_clk_pxa27x_memory();
+	clkdev_pxa_register(CLK_NONE, "system_bus", NULL,
+			    clk_register_clk_pxa27x_system_bus());
+	clkdev_pxa_register(CLK_NONE, "memory", NULL,
+			    clk_register_clk_pxa27x_memory());
 	clk_register_clk_pxa27x_lcd_base();
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa.c linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa.c
--- linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,27 @@
 #include <dt-bindings/clock/pxa-clock.h>
 #include "clk-pxa.h"
 
-DEFINE_SPINLOCK(lock);
+#define KHz 1000
+#define MHz (1000 * 1000)
+
+#define MDREFR_K0DB4	(1 << 29)	/* SDCLK0 Divide by 4 Control/Status */
+#define MDREFR_K2FREE	(1 << 25)	/* SDRAM Free-Running Control */
+#define MDREFR_K1FREE	(1 << 24)	/* SDRAM Free-Running Control */
+#define MDREFR_K0FREE	(1 << 23)	/* SDRAM Free-Running Control */
+#define MDREFR_SLFRSH	(1 << 22)	/* SDRAM Self-Refresh Control/Status */
+#define MDREFR_APD	(1 << 20)	/* SDRAM/SSRAM Auto-Power-Down Enable */
+#define MDREFR_K2DB2	(1 << 19)	/* SDCLK2 Divide by 2 Control/Status */
+#define MDREFR_K2RUN	(1 << 18)	/* SDCLK2 Run Control/Status */
+#define MDREFR_K1DB2	(1 << 17)	/* SDCLK1 Divide by 2 Control/Status */
+#define MDREFR_K1RUN	(1 << 16)	/* SDCLK1 Run Control/Status */
+#define MDREFR_E1PIN	(1 << 15)	/* SDCKE1 Level Control/Status */
+#define MDREFR_K0DB2	(1 << 14)	/* SDCLK0 Divide by 2 Control/Status */
+#define MDREFR_K0RUN	(1 << 13)	/* SDCLK0 Run Control/Status */
+#define MDREFR_E0PIN	(1 << 12)	/* SDCKE0 Level Control/Status */
+#define MDREFR_DB2_MASK	(MDREFR_K2DB2 | MDREFR_K1DB2)
+#define MDREFR_DRI_MASK	0xFFF
+
+static DEFINE_SPINLOCK(pxa_clk_lock);
 
 static struct clk *pxa_clocks[CLK_MAX];
 static struct clk_onecell_data onecell_data = {
@@ -89,7 +109,7 @@ int __init clk_pxa_cken_init(const struc
 		pxa_clk->lp = clks[i].lp;
 		pxa_clk->hp = clks[i].hp;
 		pxa_clk->gate = clks[i].gate;
-		pxa_clk->gate.lock = &lock;
+		pxa_clk->gate.lock = &pxa_clk_lock;
 		clk = clk_register_composite(NULL, clks[i].name,
 					     clks[i].parent_names, 2,
 					     &pxa_clk->hw, &cken_mux_ops,
@@ -106,3 +126,124 @@ void __init clk_pxa_dt_common_init(struc
 {
 	of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data);
 }
+
+void pxa2xx_core_turbo_switch(bool on)
+{
+	unsigned long flags;
+	unsigned int unused, clkcfg;
+
+	local_irq_save(flags);
+
+	asm("mrc p14, 0, %0, c6, c0, 0" : "=r" (clkcfg));
+	clkcfg &= ~CLKCFG_TURBO & ~CLKCFG_HALFTURBO;
+	if (on)
+		clkcfg |= CLKCFG_TURBO;
+	clkcfg |= CLKCFG_FCS;
+
+	asm volatile(
+	"	b	2f\n"
+	"	.align	5\n"
+	"1:	mcr	p14, 0, %1, c6, c0, 0\n"
+	"	b	3f\n"
+	"2:	b	1b\n"
+	"3:	nop\n"
+		: "=&r" (unused)
+		: "r" (clkcfg)
+		: );
+
+	local_irq_restore(flags);
+}
+
+void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
+			u32 (*mdrefr_dri)(unsigned int), void __iomem *mdrefr,
+			void __iomem *cccr)
+{
+	unsigned int clkcfg = freq->clkcfg;
+	unsigned int unused, preset_mdrefr, postset_mdrefr;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* Calculate the next MDREFR.  If we're slowing down the SDRAM clock
+	 * we need to preset the smaller DRI before the change.	 If we're
+	 * speeding up we need to set the larger DRI value after the change.
+	 */
+	preset_mdrefr = postset_mdrefr = readl(mdrefr);
+	if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(freq->membus_khz)) {
+		preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK);
+		preset_mdrefr |= mdrefr_dri(freq->membus_khz);
+	}
+	postset_mdrefr =
+		(postset_mdrefr & ~MDREFR_DRI_MASK) |
+		mdrefr_dri(freq->membus_khz);
+
+	/* If we're dividing the memory clock by two for the SDRAM clock, this
+	 * must be set prior to the change.  Clearing the divide must be done
+	 * after the change.
+	 */
+	if (freq->div2) {
+		preset_mdrefr  |= MDREFR_DB2_MASK;
+		postset_mdrefr |= MDREFR_DB2_MASK;
+	} else {
+		postset_mdrefr &= ~MDREFR_DB2_MASK;
+	}
+
+	/* Set new the CCCR and prepare CLKCFG */
+	writel(freq->cccr, cccr);
+
+	asm volatile(
+	"	ldr	r4, [%1]\n"
+	"	b	2f\n"
+	"	.align	5\n"
+	"1:	str	%3, [%1]		/* preset the MDREFR */\n"
+	"	mcr	p14, 0, %2, c6, c0, 0	/* set CLKCFG[FCS] */\n"
+	"	str	%4, [%1]		/* postset the MDREFR */\n"
+	"	b	3f\n"
+	"2:	b	1b\n"
+	"3:	nop\n"
+	     : "=&r" (unused)
+	     : "r" (mdrefr), "r" (clkcfg), "r" (preset_mdrefr),
+	       "r" (postset_mdrefr)
+	     : "r4", "r5");
+
+	local_irq_restore(flags);
+}
+
+int pxa2xx_determine_rate(struct clk_rate_request *req,
+			  struct pxa2xx_freq *freqs, int nb_freqs)
+{
+	int i, closest_below = -1, closest_above = -1;
+	unsigned long rate;
+
+	for (i = 0; i < nb_freqs; i++) {
+		rate = freqs[i].cpll;
+		if (rate == req->rate)
+			break;
+		if (rate < req->min_rate)
+			continue;
+		if (rate > req->max_rate)
+			continue;
+		if (rate <= req->rate)
+			closest_below = i;
+		if ((rate >= req->rate) && (closest_above == -1))
+			closest_above = i;
+	}
+
+	req->best_parent_hw = NULL;
+
+	if (i < nb_freqs) {
+		rate = req->rate;
+	} else if (closest_below >= 0) {
+		rate = freqs[closest_below].cpll;
+	} else if (closest_above >= 0) {
+		rate = freqs[closest_above].cpll;
+	} else {
+		pr_debug("%s(rate=%lu) no match\n", __func__, req->rate);
+		return -EINVAL;
+	}
+
+	pr_debug("%s(rate=%lu) rate=%lu\n", __func__, req->rate, rate);
+	req->rate = rate;
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa.h linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa.h
--- linux-libre-4.9-gnu/drivers/clk/pxa/clk-pxa.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/pxa/clk-pxa.h	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,11 @@
 #ifndef _CLK_PXA_
 #define _CLK_PXA_
 
+#define CLKCFG_TURBO		0x1
+#define CLKCFG_FCS		0x2
+#define CLKCFG_HALFTURBO	0x4
+#define CLKCFG_FASTBUS		0x8
+
 #define PARENTS(name) \
 	static const char *const name ## _parents[] __initconst
 #define MUX_RO_RATE_RO_OPS(name, clk_name)			\
@@ -35,10 +40,27 @@
 			NULL, NULL, CLK_GET_RATE_NOCACHE);	\
 	}
 
-#define RATE_RO_OPS(name, clk_name)			\
+#define RATE_RO_OPS(name, clk_name)				\
+	static struct clk_hw name ## _rate_hw;			\
+	static const struct clk_ops name ## _rate_ops = {		\
+		.recalc_rate = name ## _get_rate,		\
+	};							\
+	static struct clk * __init clk_register_ ## name(void)	\
+	{							\
+		return clk_register_composite(NULL, clk_name,	\
+			name ## _parents,			\
+			ARRAY_SIZE(name ## _parents),		\
+			NULL, NULL,				\
+			&name ## _rate_hw, &name ## _rate_ops,	\
+			NULL, NULL, CLK_GET_RATE_NOCACHE);	\
+	}
+
+#define RATE_OPS(name, clk_name)				\
 	static struct clk_hw name ## _rate_hw;			\
 	static struct clk_ops name ## _rate_ops = {		\
 		.recalc_rate = name ## _get_rate,		\
+		.set_rate = name ## _set_rate,			\
+		.determine_rate = name ## _determine_rate,	\
 	};							\
 	static struct clk * __init clk_register_ ## name(void)	\
 	{							\
@@ -50,6 +72,24 @@
 			NULL, NULL, CLK_GET_RATE_NOCACHE);	\
 	}
 
+#define MUX_OPS(name, clk_name, flags)				\
+	static struct clk_hw name ## _mux_hw;			\
+	static const struct clk_ops name ## _mux_ops = {	\
+		.get_parent = name ## _get_parent,		\
+		.set_parent = name ## _set_parent,		\
+		.determine_rate = name ## _determine_rate,	\
+	};							\
+	static struct clk * __init clk_register_ ## name(void)	\
+	{							\
+		return clk_register_composite(NULL, clk_name,	\
+			name ## _parents,			\
+			ARRAY_SIZE(name ## _parents),		\
+			&name ## _mux_hw, &name ## _mux_ops,	\
+			NULL, NULL,				\
+			NULL, NULL,				\
+			CLK_GET_RATE_NOCACHE | flags); \
+	}
+
 /*
  * CKEN clock type
  * This clock takes it source from 2 possible parents :
@@ -95,7 +135,15 @@ struct desc_clk_cken {
 	PXA_CKEN(dev_id, con_id, name, parents, 1, 1, 1, 1,		\
 		 NULL, cken_reg, cken_bit, flag)
 
-static int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
+struct pxa2xx_freq {
+	unsigned long cpll;
+	unsigned int membus_khz;
+	unsigned int cccr;
+	unsigned int div2;
+	unsigned int clkcfg;
+};
+
+static inline int dummy_clk_set_parent(struct clk_hw *hw, u8 index)
 {
 	return 0;
 }
@@ -105,4 +153,11 @@ extern void clkdev_pxa_register(int ckid
 extern int clk_pxa_cken_init(const struct desc_clk_cken *clks, int nb_clks);
 void clk_pxa_dt_common_init(struct device_node *np);
 
+void pxa2xx_core_turbo_switch(bool on);
+void pxa2xx_cpll_change(struct pxa2xx_freq *freq,
+			u32 (*mdrefr_dri)(unsigned int), void __iomem *mdrefr,
+			void __iomem *cccr);
+int pxa2xx_determine_rate(struct clk_rate_request *req,
+			  struct pxa2xx_freq *freqs,  int nb_freqs);
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/clk-alpha-pll.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-alpha-pll.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/clk-alpha-pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-alpha-pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,17 +18,21 @@
 #include <linux/delay.h>
 
 #include "clk-alpha-pll.h"
+#include "common.h"
 
 #define PLL_MODE		0x00
 # define PLL_OUTCTRL		BIT(0)
 # define PLL_BYPASSNL		BIT(1)
 # define PLL_RESET_N		BIT(2)
+# define PLL_OFFLINE_REQ	BIT(7)
 # define PLL_LOCK_COUNT_SHIFT	8
 # define PLL_LOCK_COUNT_MASK	0x3f
 # define PLL_BIAS_COUNT_SHIFT	14
 # define PLL_BIAS_COUNT_MASK	0x3f
 # define PLL_VOTE_FSM_ENA	BIT(20)
+# define PLL_FSM_ENA		BIT(20)
 # define PLL_VOTE_FSM_RESET	BIT(21)
+# define PLL_OFFLINE_ACK	BIT(28)
 # define PLL_ACTIVE_FLAG	BIT(30)
 # define PLL_LOCK_DET		BIT(31)
 
@@ -46,6 +50,7 @@
 #define PLL_USER_CTL_U		0x14
 
 #define PLL_CONFIG_CTL		0x18
+#define PLL_CONFIG_CTL_U	0x20
 #define PLL_TEST_CTL		0x1c
 #define PLL_TEST_CTL_U		0x20
 #define PLL_STATUS		0x24
@@ -55,6 +60,7 @@
  */
 #define ALPHA_REG_BITWIDTH	40
 #define ALPHA_BITWIDTH		32
+#define ALPHA_16BIT_MASK	0xffff
 
 #define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
 					   struct clk_alpha_pll, clkr)
@@ -62,9 +68,10 @@
 #define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
 					   struct clk_alpha_pll_postdiv, clkr)
 
-static int wait_for_pll(struct clk_alpha_pll *pll)
+static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
+			const char *action)
 {
-	u32 val, mask, off;
+	u32 val, off;
 	int count;
 	int ret;
 	const char *name = clk_hw_get_name(&pll->clkr.hw);
@@ -74,26 +81,148 @@ static int wait_for_pll(struct clk_alpha
 	if (ret)
 		return ret;
 
-	if (val & PLL_VOTE_FSM_ENA)
-		mask = PLL_ACTIVE_FLAG;
-	else
-		mask = PLL_LOCK_DET;
-
-	/* Wait for pll to enable. */
 	for (count = 100; count > 0; count--) {
 		ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
 		if (ret)
 			return ret;
-		if ((val & mask) == mask)
+		if (inverse && !(val & mask))
+			return 0;
+		else if ((val & mask) == mask)
 			return 0;
 
 		udelay(1);
 	}
 
-	WARN(1, "%s didn't enable after voting for it!\n", name);
+	WARN(1, "%s failed to %s!\n", name, action);
 	return -ETIMEDOUT;
 }
 
+#define wait_for_pll_enable_active(pll) \
+	wait_for_pll(pll, PLL_ACTIVE_FLAG, 0, "enable")
+
+#define wait_for_pll_enable_lock(pll) \
+	wait_for_pll(pll, PLL_LOCK_DET, 0, "enable")
+
+#define wait_for_pll_disable(pll) \
+	wait_for_pll(pll, PLL_ACTIVE_FLAG, 1, "disable")
+
+#define wait_for_pll_offline(pll) \
+	wait_for_pll(pll, PLL_OFFLINE_ACK, 0, "offline")
+
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+			     const struct alpha_pll_config *config)
+{
+	u32 val, mask;
+	u32 off = pll->offset;
+
+	regmap_write(regmap, off + PLL_L_VAL, config->l);
+	regmap_write(regmap, off + PLL_ALPHA_VAL, config->alpha);
+	regmap_write(regmap, off + PLL_CONFIG_CTL, config->config_ctl_val);
+	regmap_write(regmap, off + PLL_CONFIG_CTL_U, config->config_ctl_hi_val);
+
+	val = config->main_output_mask;
+	val |= config->aux_output_mask;
+	val |= config->aux2_output_mask;
+	val |= config->early_output_mask;
+	val |= config->pre_div_val;
+	val |= config->post_div_val;
+	val |= config->vco_val;
+
+	mask = config->main_output_mask;
+	mask |= config->aux_output_mask;
+	mask |= config->aux2_output_mask;
+	mask |= config->early_output_mask;
+	mask |= config->pre_div_mask;
+	mask |= config->post_div_mask;
+	mask |= config->vco_mask;
+
+	regmap_update_bits(regmap, off + PLL_USER_CTL, mask, val);
+
+	if (pll->flags & SUPPORTS_FSM_MODE)
+		qcom_pll_set_fsm_mode(regmap, off + PLL_MODE, 6, 0);
+}
+
+static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
+{
+	int ret;
+	u32 val, off;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+	off = pll->offset;
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return ret;
+
+	val |= PLL_FSM_ENA;
+
+	if (pll->flags & SUPPORTS_OFFLINE_REQ)
+		val &= ~PLL_OFFLINE_REQ;
+
+	ret = regmap_write(pll->clkr.regmap, off + PLL_MODE, val);
+	if (ret)
+		return ret;
+
+	/* Make sure enable request goes through before waiting for update */
+	mb();
+
+	return wait_for_pll_enable_active(pll);
+}
+
+static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
+{
+	int ret;
+	u32 val, off;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+	off = pll->offset;
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return;
+
+	if (pll->flags & SUPPORTS_OFFLINE_REQ) {
+		ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+					 PLL_OFFLINE_REQ, PLL_OFFLINE_REQ);
+		if (ret)
+			return;
+
+		ret = wait_for_pll_offline(pll);
+		if (ret)
+			return;
+	}
+
+	/* Disable hwfsm */
+	ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
+				 PLL_FSM_ENA, 0);
+	if (ret)
+		return;
+
+	wait_for_pll_disable(pll);
+}
+
+static int pll_is_enabled(struct clk_hw *hw, u32 mask)
+{
+	int ret;
+	u32 val, off;
+	struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
+
+	off = pll->offset;
+	ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
+	if (ret)
+		return ret;
+
+	return !!(val & mask);
+}
+
+static int clk_alpha_pll_hwfsm_is_enabled(struct clk_hw *hw)
+{
+	return pll_is_enabled(hw, PLL_ACTIVE_FLAG);
+}
+
+static int clk_alpha_pll_is_enabled(struct clk_hw *hw)
+{
+	return pll_is_enabled(hw, PLL_LOCK_DET);
+}
+
 static int clk_alpha_pll_enable(struct clk_hw *hw)
 {
 	int ret;
@@ -112,7 +241,7 @@ static int clk_alpha_pll_enable(struct c
 		ret = clk_enable_regmap(hw);
 		if (ret)
 			return ret;
-		return wait_for_pll(pll);
+		return wait_for_pll_enable_active(pll);
 	}
 
 	/* Skip if already enabled */
@@ -136,7 +265,7 @@ static int clk_alpha_pll_enable(struct c
 	if (ret)
 		return ret;
 
-	ret = wait_for_pll(pll);
+	ret = wait_for_pll_enable_lock(pll);
 	if (ret)
 		return ret;
 
@@ -234,9 +363,14 @@ clk_alpha_pll_recalc_rate(struct clk_hw
 	regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
 	if (ctl & PLL_ALPHA_EN) {
 		regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
-		regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high);
-		a = (u64)high << 32 | low;
-		a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+		if (pll->flags & SUPPORTS_16BIT_ALPHA) {
+			a = low & ALPHA_16BIT_MASK;
+		} else {
+			regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U,
+				    &high);
+			a = (u64)high << 32 | low;
+			a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
+		}
 	}
 
 	return alpha_pll_calc_rate(prate, l, a);
@@ -257,11 +391,15 @@ static int clk_alpha_pll_set_rate(struct
 		return -EINVAL;
 	}
 
-	a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
-
 	regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
-	regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a);
-	regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+
+	if (pll->flags & SUPPORTS_16BIT_ALPHA) {
+		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL,
+			     a & ALPHA_16BIT_MASK);
+	} else {
+		a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
+		regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
+	}
 
 	regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
 			   PLL_VCO_MASK << PLL_VCO_SHIFT,
@@ -294,12 +432,23 @@ static long clk_alpha_pll_round_rate(str
 const struct clk_ops clk_alpha_pll_ops = {
 	.enable = clk_alpha_pll_enable,
 	.disable = clk_alpha_pll_disable,
+	.is_enabled = clk_alpha_pll_is_enabled,
 	.recalc_rate = clk_alpha_pll_recalc_rate,
 	.round_rate = clk_alpha_pll_round_rate,
 	.set_rate = clk_alpha_pll_set_rate,
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
 
+const struct clk_ops clk_alpha_pll_hwfsm_ops = {
+	.enable = clk_alpha_pll_hwfsm_enable,
+	.disable = clk_alpha_pll_hwfsm_disable,
+	.is_enabled = clk_alpha_pll_hwfsm_is_enabled,
+	.recalc_rate = clk_alpha_pll_recalc_rate,
+	.round_rate = clk_alpha_pll_round_rate,
+	.set_rate = clk_alpha_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
+
 static unsigned long
 clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/clk-alpha-pll.h linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-alpha-pll.h
--- linux-libre-4.9-gnu/drivers/clk/qcom/clk-alpha-pll.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-alpha-pll.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,10 @@ struct clk_alpha_pll {
 
 	const struct pll_vco *vco_table;
 	size_t num_vco;
+#define SUPPORTS_OFFLINE_REQ	BIT(0)
+#define SUPPORTS_16BIT_ALPHA	BIT(1)
+#define SUPPORTS_FSM_MODE	BIT(2)
+	u8 flags;
 
 	struct clk_regmap clkr;
 };
@@ -51,7 +55,28 @@ struct clk_alpha_pll_postdiv {
 	struct clk_regmap clkr;
 };
 
+struct alpha_pll_config {
+	u32 l;
+	u32 alpha;
+	u32 config_ctl_val;
+	u32 config_ctl_hi_val;
+	u32 main_output_mask;
+	u32 aux_output_mask;
+	u32 aux2_output_mask;
+	u32 early_output_mask;
+	u32 pre_div_val;
+	u32 pre_div_mask;
+	u32 post_div_val;
+	u32 post_div_mask;
+	u32 vco_val;
+	u32 vco_mask;
+};
+
 extern const struct clk_ops clk_alpha_pll_ops;
+extern const struct clk_ops clk_alpha_pll_hwfsm_ops;
 extern const struct clk_ops clk_alpha_pll_postdiv_ops;
 
+void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
+			     const struct alpha_pll_config *config);
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/clk-pll.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-pll.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/clk-pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,16 +23,11 @@
 #include <asm/div64.h>
 
 #include "clk-pll.h"
+#include "common.h"
 
 #define PLL_OUTCTRL		BIT(0)
 #define PLL_BYPASSNL		BIT(1)
 #define PLL_RESET_N		BIT(2)
-#define PLL_LOCK_COUNT_SHIFT	8
-#define PLL_LOCK_COUNT_MASK	0x3f
-#define PLL_BIAS_COUNT_SHIFT	14
-#define PLL_BIAS_COUNT_MASK	0x3f
-#define PLL_VOTE_FSM_ENA	BIT(20)
-#define PLL_VOTE_FSM_RESET	BIT(21)
 
 static int clk_pll_enable(struct clk_hw *hw)
 {
@@ -228,26 +223,6 @@ const struct clk_ops clk_pll_vote_ops =
 };
 EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
 
-static void
-clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap, u8 lock_count)
-{
-	u32 val;
-	u32 mask;
-
-	/* De-assert reset to FSM */
-	regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0);
-
-	/* Program bias count and lock count */
-	val = 1 << PLL_BIAS_COUNT_SHIFT | lock_count << PLL_LOCK_COUNT_SHIFT;
-	mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
-	mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
-	regmap_update_bits(regmap, pll->mode_reg, mask, val);
-
-	/* Enable PLL FSM voting */
-	regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_ENA,
-		PLL_VOTE_FSM_ENA);
-}
-
 static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
 	const struct pll_config *config)
 {
@@ -280,7 +255,7 @@ void clk_pll_configure_sr(struct clk_pll
 {
 	clk_pll_configure(pll, regmap, config);
 	if (fsm_mode)
-		clk_pll_set_fsm_mode(pll, regmap, 8);
+		qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 8);
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
 
@@ -289,7 +264,7 @@ void clk_pll_configure_sr_hpm_lp(struct
 {
 	clk_pll_configure(pll, regmap, config);
 	if (fsm_mode)
-		clk_pll_set_fsm_mode(pll, regmap, 0);
+		qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 0);
 }
 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/clk-rcg2.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-rcg2.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/clk-rcg2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-rcg2.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,11 @@
 #define N_REG			0xc
 #define D_REG			0x10
 
+enum freq_policy {
+	FLOOR,
+	CEIL,
+};
+
 static int clk_rcg2_is_enabled(struct clk_hw *hw)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -176,15 +181,26 @@ clk_rcg2_recalc_rate(struct clk_hw *hw,
 	return calc_rate(parent_rate, m, n, mode, hid_div);
 }
 
-static int _freq_tbl_determine_rate(struct clk_hw *hw,
-		const struct freq_tbl *f, struct clk_rate_request *req)
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+				    struct clk_rate_request *req,
+				    enum freq_policy policy)
 {
 	unsigned long clk_flags, rate = req->rate;
 	struct clk_hw *p;
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	int index;
 
-	f = qcom_find_freq(f, rate);
+	switch (policy) {
+	case FLOOR:
+		f = qcom_find_freq_floor(f, rate);
+		break;
+	case CEIL:
+		f = qcom_find_freq(f, rate);
+		break;
+	default:
+		return -EINVAL;
+	};
+
 	if (!f)
 		return -EINVAL;
 
@@ -221,7 +237,15 @@ static int clk_rcg2_determine_rate(struc
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 
-	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req);
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, CEIL);
+}
+
+static int clk_rcg2_determine_floor_rate(struct clk_hw *hw,
+					 struct clk_rate_request *req)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR);
 }
 
 static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
@@ -265,12 +289,23 @@ static int clk_rcg2_configure(struct clk
 	return update_config(rcg);
 }
 
-static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
+static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
+			       enum freq_policy policy)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	const struct freq_tbl *f;
 
-	f = qcom_find_freq(rcg->freq_tbl, rate);
+	switch (policy) {
+	case FLOOR:
+		f = qcom_find_freq_floor(rcg->freq_tbl, rate);
+		break;
+	case CEIL:
+		f = qcom_find_freq(rcg->freq_tbl, rate);
+		break;
+	default:
+		return -EINVAL;
+	};
+
 	if (!f)
 		return -EINVAL;
 
@@ -280,13 +315,25 @@ static int __clk_rcg2_set_rate(struct cl
 static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
 			    unsigned long parent_rate)
 {
-	return __clk_rcg2_set_rate(hw, rate);
+	return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	return __clk_rcg2_set_rate(hw, rate, FLOOR);
 }
 
 static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
 		unsigned long rate, unsigned long parent_rate, u8 index)
 {
-	return __clk_rcg2_set_rate(hw, rate);
+	return __clk_rcg2_set_rate(hw, rate, CEIL);
+}
+
+static int clk_rcg2_set_floor_rate_and_parent(struct clk_hw *hw,
+		unsigned long rate, unsigned long parent_rate, u8 index)
+{
+	return __clk_rcg2_set_rate(hw, rate, FLOOR);
 }
 
 const struct clk_ops clk_rcg2_ops = {
@@ -300,6 +347,17 @@ const struct clk_ops clk_rcg2_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_rcg2_ops);
 
+const struct clk_ops clk_rcg2_floor_ops = {
+	.is_enabled = clk_rcg2_is_enabled,
+	.get_parent = clk_rcg2_get_parent,
+	.set_parent = clk_rcg2_set_parent,
+	.recalc_rate = clk_rcg2_recalc_rate,
+	.determine_rate = clk_rcg2_determine_floor_rate,
+	.set_rate = clk_rcg2_set_floor_rate,
+	.set_rate_and_parent = clk_rcg2_set_floor_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
+
 static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
 {
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
@@ -323,7 +381,7 @@ static int clk_rcg2_shared_force_enable(
 		pr_err("%s: RCG did not turn on\n", name);
 
 	/* set clock rate */
-	ret = __clk_rcg2_set_rate(hw, rate);
+	ret = __clk_rcg2_set_rate(hw, rate, CEIL);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/clk-rcg.h linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-rcg.h
--- linux-libre-4.9-gnu/drivers/clk/qcom/clk-rcg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-rcg.h	2017-02-12 16:03:20.000000000 -0500
@@ -173,6 +173,7 @@ struct clk_rcg2 {
 #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
 
 extern const struct clk_ops clk_rcg2_ops;
+extern const struct clk_ops clk_rcg2_floor_ops;
 extern const struct clk_ops clk_rcg2_shared_ops;
 extern const struct clk_ops clk_edp_pixel_ops;
 extern const struct clk_ops clk_byte_ops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/clk-rpm.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-rpm.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/clk-rpm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-rpm.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/mfd/qcom_rpm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include <dt-bindings/mfd/qcom-rpm.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
+
+#define QCOM_RPM_MISC_CLK_TYPE				0x306b6c63
+#define QCOM_RPM_SCALING_ENABLE_ID			0x2
+
+#define DEFINE_CLK_RPM(_platform, _name, _active, r_id)			      \
+	static struct clk_rpm _platform##_##_active;			      \
+	static struct clk_rpm _platform##_##_name = {			      \
+		.rpm_clk_id = (r_id),					      \
+		.peer = &_platform##_##_active,				      \
+		.rate = INT_MAX,					      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_rpm_ops,				      \
+			.name = #_name,					      \
+			.parent_names = (const char *[]){ "pxo_board" },      \
+			.num_parents = 1,				      \
+		},							      \
+	};								      \
+	static struct clk_rpm _platform##_##_active = {			      \
+		.rpm_clk_id = (r_id),					      \
+		.peer = &_platform##_##_name,				      \
+		.active_only = true,					      \
+		.rate = INT_MAX,					      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_rpm_ops,				      \
+			.name = #_active,				      \
+			.parent_names = (const char *[]){ "pxo_board" },      \
+			.num_parents = 1,				      \
+		},							      \
+	}
+
+#define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r)	      \
+	static struct clk_rpm _platform##_##_active;			      \
+	static struct clk_rpm _platform##_##_name = {			      \
+		.rpm_clk_id = (r_id),					      \
+		.active_only = true,					      \
+		.peer = &_platform##_##_active,				      \
+		.rate = (r),						      \
+		.branch = true,						      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_rpm_branch_ops,			      \
+			.name = #_name,					      \
+			.parent_names = (const char *[]){ "pxo_board" },      \
+			.num_parents = 1,				      \
+		},							      \
+	};								      \
+	static struct clk_rpm _platform##_##_active = {			      \
+		.rpm_clk_id = (r_id),					      \
+		.peer = &_platform##_##_name,				      \
+		.rate = (r),						      \
+		.branch = true,						      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_rpm_branch_ops,			      \
+			.name = #_active,				      \
+			.parent_names = (const char *[]){ "pxo_board" },      \
+			.num_parents = 1,				      \
+		},							      \
+	}
+
+#define DEFINE_CLK_RPM_CXO_BRANCH(_platform, _name, _active, r_id, r)	      \
+	static struct clk_rpm _platform##_##_active;			      \
+	static struct clk_rpm _platform##_##_name = {			      \
+		.rpm_clk_id = (r_id),					      \
+		.peer = &_platform##_##_active,				      \
+		.rate = (r),						      \
+		.branch = true,						      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_rpm_branch_ops,			      \
+			.name = #_name,					      \
+			.parent_names = (const char *[]){ "cxo_board" },      \
+			.num_parents = 1,				      \
+		},							      \
+	};								      \
+	static struct clk_rpm _platform##_##_active = {			      \
+		.rpm_clk_id = (r_id),					      \
+		.active_only = true,					      \
+		.peer = &_platform##_##_name,				      \
+		.rate = (r),						      \
+		.branch = true,						      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_rpm_branch_ops,			      \
+			.name = #_active,				      \
+			.parent_names = (const char *[]){ "cxo_board" },      \
+			.num_parents = 1,				      \
+		},							      \
+	}
+
+#define to_clk_rpm(_hw) container_of(_hw, struct clk_rpm, hw)
+
+struct clk_rpm {
+	const int rpm_clk_id;
+	const bool active_only;
+	unsigned long rate;
+	bool enabled;
+	bool branch;
+	struct clk_rpm *peer;
+	struct clk_hw hw;
+	struct qcom_rpm *rpm;
+};
+
+struct rpm_cc {
+	struct qcom_rpm *rpm;
+	struct clk_rpm **clks;
+	size_t num_clks;
+};
+
+struct rpm_clk_desc {
+	struct clk_rpm **clks;
+	size_t num_clks;
+};
+
+static DEFINE_MUTEX(rpm_clk_lock);
+
+static int clk_rpm_handoff(struct clk_rpm *r)
+{
+	int ret;
+	u32 value = INT_MAX;
+
+	ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
+			     r->rpm_clk_id, &value, 1);
+	if (ret)
+		return ret;
+	ret = qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,
+			     r->rpm_clk_id, &value, 1);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int clk_rpm_set_rate_active(struct clk_rpm *r, unsigned long rate)
+{
+	u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */
+
+	return qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
+			      r->rpm_clk_id, &value, 1);
+}
+
+static int clk_rpm_set_rate_sleep(struct clk_rpm *r, unsigned long rate)
+{
+	u32 value = DIV_ROUND_UP(rate, 1000); /* to kHz */
+
+	return qcom_rpm_write(r->rpm, QCOM_RPM_SLEEP_STATE,
+			      r->rpm_clk_id, &value, 1);
+}
+
+static void to_active_sleep(struct clk_rpm *r, unsigned long rate,
+			    unsigned long *active, unsigned long *sleep)
+{
+	*active = rate;
+
+	/*
+	 * Active-only clocks don't care what the rate is during sleep. So,
+	 * they vote for zero.
+	 */
+	if (r->active_only)
+		*sleep = 0;
+	else
+		*sleep = *active;
+}
+
+static int clk_rpm_prepare(struct clk_hw *hw)
+{
+	struct clk_rpm *r = to_clk_rpm(hw);
+	struct clk_rpm *peer = r->peer;
+	unsigned long this_rate = 0, this_sleep_rate = 0;
+	unsigned long peer_rate = 0, peer_sleep_rate = 0;
+	unsigned long active_rate, sleep_rate;
+	int ret = 0;
+
+	mutex_lock(&rpm_clk_lock);
+
+	/* Don't send requests to the RPM if the rate has not been set. */
+	if (!r->rate)
+		goto out;
+
+	to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);
+
+	/* Take peer clock's rate into account only if it's enabled. */
+	if (peer->enabled)
+		to_active_sleep(peer, peer->rate,
+				&peer_rate, &peer_sleep_rate);
+
+	active_rate = max(this_rate, peer_rate);
+
+	if (r->branch)
+		active_rate = !!active_rate;
+
+	ret = clk_rpm_set_rate_active(r, active_rate);
+	if (ret)
+		goto out;
+
+	sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+	if (r->branch)
+		sleep_rate = !!sleep_rate;
+
+	ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+	if (ret)
+		/* Undo the active set vote and restore it */
+		ret = clk_rpm_set_rate_active(r, peer_rate);
+
+out:
+	if (!ret)
+		r->enabled = true;
+
+	mutex_unlock(&rpm_clk_lock);
+
+	return ret;
+}
+
+static void clk_rpm_unprepare(struct clk_hw *hw)
+{
+	struct clk_rpm *r = to_clk_rpm(hw);
+	struct clk_rpm *peer = r->peer;
+	unsigned long peer_rate = 0, peer_sleep_rate = 0;
+	unsigned long active_rate, sleep_rate;
+	int ret;
+
+	mutex_lock(&rpm_clk_lock);
+
+	if (!r->rate)
+		goto out;
+
+	/* Take peer clock's rate into account only if it's enabled. */
+	if (peer->enabled)
+		to_active_sleep(peer, peer->rate, &peer_rate,
+				&peer_sleep_rate);
+
+	active_rate = r->branch ? !!peer_rate : peer_rate;
+	ret = clk_rpm_set_rate_active(r, active_rate);
+	if (ret)
+		goto out;
+
+	sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;
+	ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+	if (ret)
+		goto out;
+
+	r->enabled = false;
+
+out:
+	mutex_unlock(&rpm_clk_lock);
+}
+
+static int clk_rpm_set_rate(struct clk_hw *hw,
+			    unsigned long rate, unsigned long parent_rate)
+{
+	struct clk_rpm *r = to_clk_rpm(hw);
+	struct clk_rpm *peer = r->peer;
+	unsigned long active_rate, sleep_rate;
+	unsigned long this_rate = 0, this_sleep_rate = 0;
+	unsigned long peer_rate = 0, peer_sleep_rate = 0;
+	int ret = 0;
+
+	mutex_lock(&rpm_clk_lock);
+
+	if (!r->enabled)
+		goto out;
+
+	to_active_sleep(r, rate, &this_rate, &this_sleep_rate);
+
+	/* Take peer clock's rate into account only if it's enabled. */
+	if (peer->enabled)
+		to_active_sleep(peer, peer->rate,
+				&peer_rate, &peer_sleep_rate);
+
+	active_rate = max(this_rate, peer_rate);
+	ret = clk_rpm_set_rate_active(r, active_rate);
+	if (ret)
+		goto out;
+
+	sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+	ret = clk_rpm_set_rate_sleep(r, sleep_rate);
+	if (ret)
+		goto out;
+
+	r->rate = rate;
+
+out:
+	mutex_unlock(&rpm_clk_lock);
+
+	return ret;
+}
+
+static long clk_rpm_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	/*
+	 * RPM handles rate rounding and we don't have a way to
+	 * know what the rate will be, so just return whatever
+	 * rate is requested.
+	 */
+	return rate;
+}
+
+static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct clk_rpm *r = to_clk_rpm(hw);
+
+	/*
+	 * RPM handles rate rounding and we don't have a way to
+	 * know what the rate will be, so just return whatever
+	 * rate was set.
+	 */
+	return r->rate;
+}
+
+static const struct clk_ops clk_rpm_ops = {
+	.prepare	= clk_rpm_prepare,
+	.unprepare	= clk_rpm_unprepare,
+	.set_rate	= clk_rpm_set_rate,
+	.round_rate	= clk_rpm_round_rate,
+	.recalc_rate	= clk_rpm_recalc_rate,
+};
+
+static const struct clk_ops clk_rpm_branch_ops = {
+	.prepare	= clk_rpm_prepare,
+	.unprepare	= clk_rpm_unprepare,
+	.round_rate	= clk_rpm_round_rate,
+	.recalc_rate	= clk_rpm_recalc_rate,
+};
+
+/* apq8064 */
+DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
+DEFINE_CLK_RPM(apq8064, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
+DEFINE_CLK_RPM(apq8064, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
+DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
+DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
+DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
+
+static struct clk_rpm *apq8064_clks[] = {
+	[RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
+	[RPM_APPS_FABRIC_A_CLK] = &apq8064_afab_a_clk,
+	[RPM_CFPB_CLK] = &apq8064_cfpb_clk,
+	[RPM_CFPB_A_CLK] = &apq8064_cfpb_a_clk,
+	[RPM_DAYTONA_FABRIC_CLK] = &apq8064_daytona_clk,
+	[RPM_DAYTONA_FABRIC_A_CLK] = &apq8064_daytona_a_clk,
+	[RPM_EBI1_CLK] = &apq8064_ebi1_clk,
+	[RPM_EBI1_A_CLK] = &apq8064_ebi1_a_clk,
+	[RPM_MM_FABRIC_CLK] = &apq8064_mmfab_clk,
+	[RPM_MM_FABRIC_A_CLK] = &apq8064_mmfab_a_clk,
+	[RPM_MMFPB_CLK] = &apq8064_mmfpb_clk,
+	[RPM_MMFPB_A_CLK] = &apq8064_mmfpb_a_clk,
+	[RPM_SYS_FABRIC_CLK] = &apq8064_sfab_clk,
+	[RPM_SYS_FABRIC_A_CLK] = &apq8064_sfab_a_clk,
+	[RPM_SFPB_CLK] = &apq8064_sfpb_clk,
+	[RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
+	[RPM_QDSS_CLK] = &apq8064_qdss_clk,
+	[RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
+};
+
+static const struct rpm_clk_desc rpm_clk_apq8064 = {
+	.clks = apq8064_clks,
+	.num_clks = ARRAY_SIZE(apq8064_clks),
+};
+
+static const struct of_device_id rpm_clk_match_table[] = {
+	{ .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, rpm_clk_match_table);
+
+static struct clk_hw *qcom_rpm_clk_hw_get(struct of_phandle_args *clkspec,
+					  void *data)
+{
+	struct rpm_cc *rcc = data;
+	unsigned int idx = clkspec->args[0];
+
+	if (idx >= rcc->num_clks) {
+		pr_err("%s: invalid index %u\n", __func__, idx);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
+}
+
+static int rpm_clk_probe(struct platform_device *pdev)
+{
+	struct rpm_cc *rcc;
+	int ret;
+	size_t num_clks, i;
+	struct qcom_rpm *rpm;
+	struct clk_rpm **rpm_clks;
+	const struct rpm_clk_desc *desc;
+
+	rpm = dev_get_drvdata(pdev->dev.parent);
+	if (!rpm) {
+		dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+		return -ENODEV;
+	}
+
+	desc = of_device_get_match_data(&pdev->dev);
+	if (!desc)
+		return -EINVAL;
+
+	rpm_clks = desc->clks;
+	num_clks = desc->num_clks;
+
+	rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
+	if (!rcc)
+		return -ENOMEM;
+
+	rcc->clks = rpm_clks;
+	rcc->num_clks = num_clks;
+
+	for (i = 0; i < num_clks; i++) {
+		if (!rpm_clks[i])
+			continue;
+
+		rpm_clks[i]->rpm = rpm;
+
+		ret = clk_rpm_handoff(rpm_clks[i]);
+		if (ret)
+			goto err;
+	}
+
+	for (i = 0; i < num_clks; i++) {
+		if (!rpm_clks[i])
+			continue;
+
+		ret = devm_clk_hw_register(&pdev->dev, &rpm_clks[i]->hw);
+		if (ret)
+			goto err;
+	}
+
+	ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_rpm_clk_hw_get,
+				     rcc);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_err(&pdev->dev, "Error registering RPM Clock driver (%d)\n", ret);
+	return ret;
+}
+
+static int rpm_clk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver rpm_clk_driver = {
+	.driver = {
+		.name = "qcom-clk-rpm",
+		.of_match_table = rpm_clk_match_table,
+	},
+	.probe = rpm_clk_probe,
+	.remove = rpm_clk_remove,
+};
+
+static int __init rpm_clk_init(void)
+{
+	return platform_driver_register(&rpm_clk_driver);
+}
+core_initcall(rpm_clk_init);
+
+static void __exit rpm_clk_exit(void)
+{
+	platform_driver_unregister(&rpm_clk_driver);
+}
+module_exit(rpm_clk_exit);
+
+MODULE_DESCRIPTION("Qualcomm RPM Clock Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-clk-rpm");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/clk-smd-rpm.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-smd-rpm.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/clk-smd-rpm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/clk-smd-rpm.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2016, Linaro Limited
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/smd-rpm.h>
+
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/mfd/qcom-rpm.h>
+
+#define QCOM_RPM_KEY_SOFTWARE_ENABLE			0x6e657773
+#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY	0x62636370
+#define QCOM_RPM_SMD_KEY_RATE				0x007a484b
+#define QCOM_RPM_SMD_KEY_ENABLE				0x62616e45
+#define QCOM_RPM_SMD_KEY_STATE				0x54415453
+#define QCOM_RPM_SCALING_ENABLE_ID			0x2
+
+#define __DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id, stat_id,  \
+			     key)					      \
+	static struct clk_smd_rpm _platform##_##_active;		      \
+	static struct clk_smd_rpm _platform##_##_name = {		      \
+		.rpm_res_type = (type),					      \
+		.rpm_clk_id = (r_id),					      \
+		.rpm_status_id = (stat_id),				      \
+		.rpm_key = (key),					      \
+		.peer = &_platform##_##_active,				      \
+		.rate = INT_MAX,					      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_smd_rpm_ops,			      \
+			.name = #_name,					      \
+			.parent_names = (const char *[]){ "xo_board" },       \
+			.num_parents = 1,				      \
+		},							      \
+	};								      \
+	static struct clk_smd_rpm _platform##_##_active = {		      \
+		.rpm_res_type = (type),					      \
+		.rpm_clk_id = (r_id),					      \
+		.rpm_status_id = (stat_id),				      \
+		.active_only = true,					      \
+		.rpm_key = (key),					      \
+		.peer = &_platform##_##_name,				      \
+		.rate = INT_MAX,					      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_smd_rpm_ops,			      \
+			.name = #_active,				      \
+			.parent_names = (const char *[]){ "xo_board" },	      \
+			.num_parents = 1,				      \
+		},							      \
+	}
+
+#define __DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id,    \
+				    stat_id, r, key)			      \
+	static struct clk_smd_rpm _platform##_##_active;		      \
+	static struct clk_smd_rpm _platform##_##_name = {		      \
+		.rpm_res_type = (type),					      \
+		.rpm_clk_id = (r_id),					      \
+		.rpm_status_id = (stat_id),				      \
+		.rpm_key = (key),					      \
+		.branch = true,						      \
+		.peer = &_platform##_##_active,				      \
+		.rate = (r),						      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_smd_rpm_branch_ops,			      \
+			.name = #_name,					      \
+			.parent_names = (const char *[]){ "xo_board" },	      \
+			.num_parents = 1,				      \
+		},							      \
+	};								      \
+	static struct clk_smd_rpm _platform##_##_active = {		      \
+		.rpm_res_type = (type),					      \
+		.rpm_clk_id = (r_id),					      \
+		.rpm_status_id = (stat_id),				      \
+		.active_only = true,					      \
+		.rpm_key = (key),					      \
+		.branch = true,						      \
+		.peer = &_platform##_##_name,				      \
+		.rate = (r),						      \
+		.hw.init = &(struct clk_init_data){			      \
+			.ops = &clk_smd_rpm_branch_ops,			      \
+			.name = #_active,				      \
+			.parent_names = (const char *[]){ "xo_board" },	      \
+			.num_parents = 1,				      \
+		},							      \
+	}
+
+#define DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id)	      \
+		__DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id,   \
+		0, QCOM_RPM_SMD_KEY_RATE)
+
+#define DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type, r_id, r)   \
+		__DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active, type,  \
+		r_id, 0, r, QCOM_RPM_SMD_KEY_ENABLE)
+
+#define DEFINE_CLK_SMD_RPM_QDSS(_platform, _name, _active, type, r_id)	      \
+		__DEFINE_CLK_SMD_RPM(_platform, _name, _active, type, r_id,   \
+		0, QCOM_RPM_SMD_KEY_STATE)
+
+#define DEFINE_CLK_SMD_RPM_XO_BUFFER(_platform, _name, _active, r_id)	      \
+		__DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active,	      \
+		QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000,			      \
+		QCOM_RPM_KEY_SOFTWARE_ENABLE)
+
+#define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_platform, _name, _active, r_id) \
+		__DEFINE_CLK_SMD_RPM_BRANCH(_platform, _name, _active,	      \
+		QCOM_SMD_RPM_CLK_BUF_A, r_id, 0, 1000,			      \
+		QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY)
+
+#define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw)
+
+struct clk_smd_rpm {
+	const int rpm_res_type;
+	const int rpm_key;
+	const int rpm_clk_id;
+	const int rpm_status_id;
+	const bool active_only;
+	bool enabled;
+	bool branch;
+	struct clk_smd_rpm *peer;
+	struct clk_hw hw;
+	unsigned long rate;
+	struct qcom_smd_rpm *rpm;
+};
+
+struct clk_smd_rpm_req {
+	__le32 key;
+	__le32 nbytes;
+	__le32 value;
+};
+
+struct rpm_cc {
+	struct qcom_rpm *rpm;
+	struct clk_smd_rpm **clks;
+	size_t num_clks;
+};
+
+struct rpm_smd_clk_desc {
+	struct clk_smd_rpm **clks;
+	size_t num_clks;
+};
+
+static DEFINE_MUTEX(rpm_smd_clk_lock);
+
+static int clk_smd_rpm_handoff(struct clk_smd_rpm *r)
+{
+	int ret;
+	struct clk_smd_rpm_req req = {
+		.key = cpu_to_le32(r->rpm_key),
+		.nbytes = cpu_to_le32(sizeof(u32)),
+		.value = cpu_to_le32(INT_MAX),
+	};
+
+	ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+				 r->rpm_res_type, r->rpm_clk_id, &req,
+				 sizeof(req));
+	if (ret)
+		return ret;
+	ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+				 r->rpm_res_type, r->rpm_clk_id, &req,
+				 sizeof(req));
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r,
+				       unsigned long rate)
+{
+	struct clk_smd_rpm_req req = {
+		.key = cpu_to_le32(r->rpm_key),
+		.nbytes = cpu_to_le32(sizeof(u32)),
+		.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
+	};
+
+	return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+				  r->rpm_res_type, r->rpm_clk_id, &req,
+				  sizeof(req));
+}
+
+static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r,
+				      unsigned long rate)
+{
+	struct clk_smd_rpm_req req = {
+		.key = cpu_to_le32(r->rpm_key),
+		.nbytes = cpu_to_le32(sizeof(u32)),
+		.value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */
+	};
+
+	return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE,
+				  r->rpm_res_type, r->rpm_clk_id, &req,
+				  sizeof(req));
+}
+
+static void to_active_sleep(struct clk_smd_rpm *r, unsigned long rate,
+			    unsigned long *active, unsigned long *sleep)
+{
+	*active = rate;
+
+	/*
+	 * Active-only clocks don't care what the rate is during sleep. So,
+	 * they vote for zero.
+	 */
+	if (r->active_only)
+		*sleep = 0;
+	else
+		*sleep = *active;
+}
+
+static int clk_smd_rpm_prepare(struct clk_hw *hw)
+{
+	struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+	struct clk_smd_rpm *peer = r->peer;
+	unsigned long this_rate = 0, this_sleep_rate = 0;
+	unsigned long peer_rate = 0, peer_sleep_rate = 0;
+	unsigned long active_rate, sleep_rate;
+	int ret = 0;
+
+	mutex_lock(&rpm_smd_clk_lock);
+
+	/* Don't send requests to the RPM if the rate has not been set. */
+	if (!r->rate)
+		goto out;
+
+	to_active_sleep(r, r->rate, &this_rate, &this_sleep_rate);
+
+	/* Take peer clock's rate into account only if it's enabled. */
+	if (peer->enabled)
+		to_active_sleep(peer, peer->rate,
+				&peer_rate, &peer_sleep_rate);
+
+	active_rate = max(this_rate, peer_rate);
+
+	if (r->branch)
+		active_rate = !!active_rate;
+
+	ret = clk_smd_rpm_set_rate_active(r, active_rate);
+	if (ret)
+		goto out;
+
+	sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+	if (r->branch)
+		sleep_rate = !!sleep_rate;
+
+	ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+	if (ret)
+		/* Undo the active set vote and restore it */
+		ret = clk_smd_rpm_set_rate_active(r, peer_rate);
+
+out:
+	if (!ret)
+		r->enabled = true;
+
+	mutex_unlock(&rpm_smd_clk_lock);
+
+	return ret;
+}
+
+static void clk_smd_rpm_unprepare(struct clk_hw *hw)
+{
+	struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+	struct clk_smd_rpm *peer = r->peer;
+	unsigned long peer_rate = 0, peer_sleep_rate = 0;
+	unsigned long active_rate, sleep_rate;
+	int ret;
+
+	mutex_lock(&rpm_smd_clk_lock);
+
+	if (!r->rate)
+		goto out;
+
+	/* Take peer clock's rate into account only if it's enabled. */
+	if (peer->enabled)
+		to_active_sleep(peer, peer->rate, &peer_rate,
+				&peer_sleep_rate);
+
+	active_rate = r->branch ? !!peer_rate : peer_rate;
+	ret = clk_smd_rpm_set_rate_active(r, active_rate);
+	if (ret)
+		goto out;
+
+	sleep_rate = r->branch ? !!peer_sleep_rate : peer_sleep_rate;
+	ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+	if (ret)
+		goto out;
+
+	r->enabled = false;
+
+out:
+	mutex_unlock(&rpm_smd_clk_lock);
+}
+
+static int clk_smd_rpm_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+	struct clk_smd_rpm *peer = r->peer;
+	unsigned long active_rate, sleep_rate;
+	unsigned long this_rate = 0, this_sleep_rate = 0;
+	unsigned long peer_rate = 0, peer_sleep_rate = 0;
+	int ret = 0;
+
+	mutex_lock(&rpm_smd_clk_lock);
+
+	if (!r->enabled)
+		goto out;
+
+	to_active_sleep(r, rate, &this_rate, &this_sleep_rate);
+
+	/* Take peer clock's rate into account only if it's enabled. */
+	if (peer->enabled)
+		to_active_sleep(peer, peer->rate,
+				&peer_rate, &peer_sleep_rate);
+
+	active_rate = max(this_rate, peer_rate);
+	ret = clk_smd_rpm_set_rate_active(r, active_rate);
+	if (ret)
+		goto out;
+
+	sleep_rate = max(this_sleep_rate, peer_sleep_rate);
+	ret = clk_smd_rpm_set_rate_sleep(r, sleep_rate);
+	if (ret)
+		goto out;
+
+	r->rate = rate;
+
+out:
+	mutex_unlock(&rpm_smd_clk_lock);
+
+	return ret;
+}
+
+static long clk_smd_rpm_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *parent_rate)
+{
+	/*
+	 * RPM handles rate rounding and we don't have a way to
+	 * know what the rate will be, so just return whatever
+	 * rate is requested.
+	 */
+	return rate;
+}
+
+static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct clk_smd_rpm *r = to_clk_smd_rpm(hw);
+
+	/*
+	 * RPM handles rate rounding and we don't have a way to
+	 * know what the rate will be, so just return whatever
+	 * rate was set.
+	 */
+	return r->rate;
+}
+
+static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm)
+{
+	int ret;
+	struct clk_smd_rpm_req req = {
+		.key = cpu_to_le32(QCOM_RPM_SMD_KEY_ENABLE),
+		.nbytes = cpu_to_le32(sizeof(u32)),
+		.value = cpu_to_le32(1),
+	};
+
+	ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE,
+				 QCOM_SMD_RPM_MISC_CLK,
+				 QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
+	if (ret) {
+		pr_err("RPM clock scaling (sleep set) not enabled!\n");
+		return ret;
+	}
+
+	ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE,
+				 QCOM_SMD_RPM_MISC_CLK,
+				 QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req));
+	if (ret) {
+		pr_err("RPM clock scaling (active set) not enabled!\n");
+		return ret;
+	}
+
+	pr_debug("%s: RPM clock scaling is enabled\n", __func__);
+	return 0;
+}
+
+static const struct clk_ops clk_smd_rpm_ops = {
+	.prepare	= clk_smd_rpm_prepare,
+	.unprepare	= clk_smd_rpm_unprepare,
+	.set_rate	= clk_smd_rpm_set_rate,
+	.round_rate	= clk_smd_rpm_round_rate,
+	.recalc_rate	= clk_smd_rpm_recalc_rate,
+};
+
+static const struct clk_ops clk_smd_rpm_branch_ops = {
+	.prepare	= clk_smd_rpm_prepare,
+	.unprepare	= clk_smd_rpm_unprepare,
+	.round_rate	= clk_smd_rpm_round_rate,
+	.recalc_rate	= clk_smd_rpm_recalc_rate,
+};
+
+/* msm8916 */
+DEFINE_CLK_SMD_RPM(msm8916, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
+DEFINE_CLK_SMD_RPM(msm8916, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
+DEFINE_CLK_SMD_RPM(msm8916, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
+DEFINE_CLK_SMD_RPM_QDSS(msm8916, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk1, bb_clk1_a, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, bb_clk2, bb_clk2_a, 2);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk1, rf_clk1_a, 4);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8916, rf_clk2, rf_clk2_a, 5);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk1_pin, bb_clk1_a_pin, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, bb_clk2_pin, bb_clk2_a_pin, 2);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk1_pin, rf_clk1_a_pin, 4);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8916, rf_clk2_pin, rf_clk2_a_pin, 5);
+
+static struct clk_smd_rpm *msm8916_clks[] = {
+	[RPM_SMD_PCNOC_CLK]		= &msm8916_pcnoc_clk,
+	[RPM_SMD_PCNOC_A_CLK]		= &msm8916_pcnoc_a_clk,
+	[RPM_SMD_SNOC_CLK]		= &msm8916_snoc_clk,
+	[RPM_SMD_SNOC_A_CLK]		= &msm8916_snoc_a_clk,
+	[RPM_SMD_BIMC_CLK]		= &msm8916_bimc_clk,
+	[RPM_SMD_BIMC_A_CLK]		= &msm8916_bimc_a_clk,
+	[RPM_SMD_QDSS_CLK]		= &msm8916_qdss_clk,
+	[RPM_SMD_QDSS_A_CLK]		= &msm8916_qdss_a_clk,
+	[RPM_SMD_BB_CLK1]		= &msm8916_bb_clk1,
+	[RPM_SMD_BB_CLK1_A]		= &msm8916_bb_clk1_a,
+	[RPM_SMD_BB_CLK2]		= &msm8916_bb_clk2,
+	[RPM_SMD_BB_CLK2_A]		= &msm8916_bb_clk2_a,
+	[RPM_SMD_RF_CLK1]		= &msm8916_rf_clk1,
+	[RPM_SMD_RF_CLK1_A]		= &msm8916_rf_clk1_a,
+	[RPM_SMD_RF_CLK2]		= &msm8916_rf_clk2,
+	[RPM_SMD_RF_CLK2_A]		= &msm8916_rf_clk2_a,
+	[RPM_SMD_BB_CLK1_PIN]		= &msm8916_bb_clk1_pin,
+	[RPM_SMD_BB_CLK1_A_PIN]		= &msm8916_bb_clk1_a_pin,
+	[RPM_SMD_BB_CLK2_PIN]		= &msm8916_bb_clk2_pin,
+	[RPM_SMD_BB_CLK2_A_PIN]		= &msm8916_bb_clk2_a_pin,
+	[RPM_SMD_RF_CLK1_PIN]		= &msm8916_rf_clk1_pin,
+	[RPM_SMD_RF_CLK1_A_PIN]		= &msm8916_rf_clk1_a_pin,
+	[RPM_SMD_RF_CLK2_PIN]		= &msm8916_rf_clk2_pin,
+	[RPM_SMD_RF_CLK2_A_PIN]		= &msm8916_rf_clk2_a_pin,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_msm8916 = {
+	.clks = msm8916_clks,
+	.num_clks = ARRAY_SIZE(msm8916_clks),
+};
+
+static const struct of_device_id rpm_smd_clk_match_table[] = {
+	{ .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);
+
+static struct clk_hw *qcom_smdrpm_clk_hw_get(struct of_phandle_args *clkspec,
+					     void *data)
+{
+	struct rpm_cc *rcc = data;
+	unsigned int idx = clkspec->args[0];
+
+	if (idx >= rcc->num_clks) {
+		pr_err("%s: invalid index %u\n", __func__, idx);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return rcc->clks[idx] ? &rcc->clks[idx]->hw : ERR_PTR(-ENOENT);
+}
+
+static int rpm_smd_clk_probe(struct platform_device *pdev)
+{
+	struct rpm_cc *rcc;
+	int ret;
+	size_t num_clks, i;
+	struct qcom_smd_rpm *rpm;
+	struct clk_smd_rpm **rpm_smd_clks;
+	const struct rpm_smd_clk_desc *desc;
+
+	rpm = dev_get_drvdata(pdev->dev.parent);
+	if (!rpm) {
+		dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
+		return -ENODEV;
+	}
+
+	desc = of_device_get_match_data(&pdev->dev);
+	if (!desc)
+		return -EINVAL;
+
+	rpm_smd_clks = desc->clks;
+	num_clks = desc->num_clks;
+
+	rcc = devm_kzalloc(&pdev->dev, sizeof(*rcc), GFP_KERNEL);
+	if (!rcc)
+		return -ENOMEM;
+
+	rcc->clks = rpm_smd_clks;
+	rcc->num_clks = num_clks;
+
+	for (i = 0; i < num_clks; i++) {
+		if (!rpm_smd_clks[i])
+			continue;
+
+		rpm_smd_clks[i]->rpm = rpm;
+
+		ret = clk_smd_rpm_handoff(rpm_smd_clks[i]);
+		if (ret)
+			goto err;
+	}
+
+	ret = clk_smd_rpm_enable_scaling(rpm);
+	if (ret)
+		goto err;
+
+	for (i = 0; i < num_clks; i++) {
+		if (!rpm_smd_clks[i])
+			continue;
+
+		ret = devm_clk_hw_register(&pdev->dev, &rpm_smd_clks[i]->hw);
+		if (ret)
+			goto err;
+	}
+
+	ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_smdrpm_clk_hw_get,
+				     rcc);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_err(&pdev->dev, "Error registering SMD clock driver (%d)\n", ret);
+	return ret;
+}
+
+static int rpm_smd_clk_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	return 0;
+}
+
+static struct platform_driver rpm_smd_clk_driver = {
+	.driver = {
+		.name = "qcom-clk-smd-rpm",
+		.of_match_table = rpm_smd_clk_match_table,
+	},
+	.probe = rpm_smd_clk_probe,
+	.remove = rpm_smd_clk_remove,
+};
+
+static int __init rpm_smd_clk_init(void)
+{
+	return platform_driver_register(&rpm_smd_clk_driver);
+}
+core_initcall(rpm_smd_clk_init);
+
+static void __exit rpm_smd_clk_exit(void)
+{
+	platform_driver_unregister(&rpm_smd_clk_driver);
+}
+module_exit(rpm_smd_clk_exit);
+
+MODULE_DESCRIPTION("Qualcomm RPM over SMD Clock Controller Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qcom-clk-smd-rpm");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/common.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/common.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/common.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,6 +46,22 @@ struct freq_tbl *qcom_find_freq(const st
 }
 EXPORT_SYMBOL_GPL(qcom_find_freq);
 
+const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+					    unsigned long rate)
+{
+	const struct freq_tbl *best = NULL;
+
+	for ( ; f->freq; f++) {
+		if (rate >= f->freq)
+			best = f;
+		else
+			break;
+	}
+
+	return best;
+}
+EXPORT_SYMBOL_GPL(qcom_find_freq_floor);
+
 int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
 {
 	int i, num_parents = clk_hw_get_num_parents(hw);
@@ -74,6 +90,27 @@ qcom_cc_map(struct platform_device *pdev
 }
 EXPORT_SYMBOL_GPL(qcom_cc_map);
 
+void
+qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count)
+{
+	u32 val;
+	u32 mask;
+
+	/* De-assert reset to FSM */
+	regmap_update_bits(map, reg, PLL_VOTE_FSM_RESET, 0);
+
+	/* Program bias count and lock count */
+	val = bias_count << PLL_BIAS_COUNT_SHIFT |
+		lock_count << PLL_LOCK_COUNT_SHIFT;
+	mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
+	mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
+	regmap_update_bits(map, reg, mask, val);
+
+	/* Enable PLL FSM voting */
+	regmap_update_bits(map, reg, PLL_VOTE_FSM_ENA, PLL_VOTE_FSM_ENA);
+}
+EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode);
+
 static void qcom_cc_del_clk_provider(void *data)
 {
 	of_clk_del_provider(data);
@@ -153,15 +190,12 @@ int qcom_cc_register_board_clk(struct de
 			       const char *name, unsigned long rate)
 {
 	bool add_factor = true;
-	struct device_node *node;
 
-	/* The RPM clock driver will add the factor clock if present */
-	if (IS_ENABLED(CONFIG_QCOM_RPMCC)) {
-		node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc");
-		if (of_device_is_available(node))
-			add_factor = false;
-		of_node_put(node);
-	}
+	/*
+	 * TODO: The RPM clock driver currently does not support the xo clock.
+	 * When xo is added to the RPM clock driver, we should change this
+	 * function to skip registration of xo factor clocks.
+	 */
 
 	return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/common.h linux-libre-4.10-rc8-gnu/drivers/clk/qcom/common.h
--- linux-libre-4.9-gnu/drivers/clk/qcom/common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/common.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,13 @@ struct freq_tbl;
 struct clk_hw;
 struct parent_map;
 
+#define PLL_LOCK_COUNT_SHIFT	8
+#define PLL_LOCK_COUNT_MASK	0x3f
+#define PLL_BIAS_COUNT_SHIFT	14
+#define PLL_BIAS_COUNT_MASK	0x3f
+#define PLL_VOTE_FSM_ENA	BIT(20)
+#define PLL_VOTE_FSM_RESET	BIT(21)
+
 struct qcom_cc_desc {
 	const struct regmap_config *config;
 	struct clk_regmap **clks;
@@ -34,6 +41,10 @@ struct qcom_cc_desc {
 
 extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
 					     unsigned long rate);
+extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+						   unsigned long rate);
+extern void
+qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count);
 extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
 			       u8 src);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gcc-apq8084.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-apq8084.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gcc-apq8084.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-apq8084.c	2017-02-12 16:03:20.000000000 -0500
@@ -1142,7 +1142,7 @@ static struct clk_rcg2 sdcc1_apps_clk_sr
 		.name = "sdcc1_apps_clk_src",
 		.parent_names = gcc_xo_gpll0_gpll4,
 		.num_parents = 3,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -1156,7 +1156,7 @@ static struct clk_rcg2 sdcc2_apps_clk_sr
 		.name = "sdcc2_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -1170,7 +1170,7 @@ static struct clk_rcg2 sdcc3_apps_clk_sr
 		.name = "sdcc3_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -1184,7 +1184,7 @@ static struct clk_rcg2 sdcc4_apps_clk_sr
 		.name = "sdcc4_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gcc-ipq4019.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-ipq4019.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gcc-ipq4019.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-ipq4019.c	2017-02-12 16:03:20.000000000 -0500
@@ -185,8 +185,7 @@ static struct clk_branch gcc_audio_pwm_c
 };
 
 static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] = {
-	F(19200000, P_XO, 1, 2, 5),
-	F(24000000, P_XO, 1, 1, 2),
+	F(19050000, P_FEPLL200, 10.5, 1, 1),
 	{ }
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gcc-ipq806x.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-ipq806x.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gcc-ipq806x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-ipq806x.c	2017-02-12 16:03:20.000000000 -0500
@@ -2990,11 +2990,11 @@ static int gcc_ipq806x_probe(struct plat
 	struct regmap *regmap;
 	int ret;
 
-	ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
+	ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 25000000);
 	if (ret)
 		return ret;
 
-	ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
+	ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 25000000);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8916.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8916.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8916.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8916.c	2017-02-12 16:03:20.000000000 -0500
@@ -1107,7 +1107,7 @@ static struct clk_rcg2 sdcc1_apps_clk_sr
 		.name = "sdcc1_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -1132,7 +1132,7 @@ static struct clk_rcg2 sdcc2_apps_clk_sr
 		.name = "sdcc2_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8974.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8974.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8974.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8974.c	2017-02-12 16:03:20.000000000 -0500
@@ -872,7 +872,7 @@ static struct clk_init_data sdcc1_apps_c
 	.name = "sdcc1_apps_clk_src",
 	.parent_names = gcc_xo_gpll0,
 	.num_parents = 2,
-	.ops = &clk_rcg2_ops,
+	.ops = &clk_rcg2_floor_ops,
 };
 
 static struct clk_rcg2 sdcc1_apps_clk_src = {
@@ -894,7 +894,7 @@ static struct clk_rcg2 sdcc2_apps_clk_sr
 		.name = "sdcc2_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -908,7 +908,7 @@ static struct clk_rcg2 sdcc3_apps_clk_sr
 		.name = "sdcc3_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -922,7 +922,7 @@ static struct clk_rcg2 sdcc4_apps_clk_sr
 		.name = "sdcc4_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8994.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8994.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8994.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8994.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2300 @@
+/* Copyright (c) 2013-2016, The Linux Foundation. All 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/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8994.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-alpha-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+enum {
+	P_XO,
+	P_GPLL0,
+	P_GPLL4,
+};
+
+static const struct parent_map gcc_xo_gpll0_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+};
+
+static const char * const gcc_xo_gpll0[] = {
+	"xo",
+	"gpll0",
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+	{ P_XO, 0 },
+	{ P_GPLL0, 1 },
+	{ P_GPLL4, 5 },
+};
+
+static const char * const gcc_xo_gpll0_gpll4[] = {
+	"xo",
+	"gpll0",
+	"gpll4",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_fixed_factor xo = {
+	.mult = 1,
+	.div = 1,
+	.hw.init = &(struct clk_init_data)
+	{
+		.name = "xo",
+		.parent_names = (const char *[]) { "xo_board" },
+		.num_parents = 1,
+		.ops = &clk_fixed_factor_ops,
+	},
+};
+
+static struct clk_alpha_pll gpll0_early = {
+	.offset = 0x00000,
+	.clkr = {
+		.enable_reg = 0x1480,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gpll0_early",
+			.parent_names = (const char *[]) { "xo" },
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static struct clk_alpha_pll_postdiv gpll0 = {
+	.offset = 0x00000,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "gpll0",
+		.parent_names = (const char *[]) { "gpll0_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+	},
+};
+
+static struct clk_alpha_pll gpll4_early = {
+	.offset = 0x1dc0,
+	.clkr = {
+		.enable_reg = 0x1480,
+		.enable_mask = BIT(4),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gpll4_early",
+			.parent_names = (const char *[]) { "xo" },
+			.num_parents = 1,
+			.ops = &clk_alpha_pll_ops,
+		},
+	},
+};
+
+static struct clk_alpha_pll_postdiv gpll4 = {
+	.offset = 0x1dc0,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "gpll4",
+		.parent_names = (const char *[]) { "gpll4_early" },
+		.num_parents = 1,
+		.ops = &clk_alpha_pll_postdiv_ops,
+	},
+};
+
+static struct freq_tbl ftbl_ufs_axi_clk_src[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(171430000, P_GPLL0, 3.5, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(240000000, P_GPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ufs_axi_clk_src = {
+	.cmd_rcgr = 0x1d68,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_ufs_axi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "ufs_axi_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_usb30_master_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(125000000, P_GPLL0, 1, 5, 24),
+	{ }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+	.cmd_rcgr = 0x03d4,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_usb30_master_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "usb30_master_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_blsp_i2c_apps_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0660,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup1_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_blspqup_spi_apps_clk_src[] = {
+	F(960000, P_XO, 10, 1, 2),
+	F(4800000, P_XO, 4, 0, 0),
+	F(9600000, P_XO, 2, 0, 0),
+	F(15000000, P_GPLL0, 10, 1, 4),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 12.5, 1, 2),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(48000000, P_GPLL0, 12.5, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr = 0x064c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup1_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x06e0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup2_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr = 0x06cc,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup2_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0760,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup3_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr = 0x074c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup3_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x07e0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup4_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr = 0x07cc,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup4_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0860,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup5_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+	.cmd_rcgr = 0x084c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup5_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x08e0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup6_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+	.cmd_rcgr = 0x08cc,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_qup6_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_blsp_uart_apps_clk_src[] = {
+	F(3686400, P_GPLL0, 1, 96, 15625),
+	F(7372800, P_GPLL0, 1, 192, 15625),
+	F(14745600, P_GPLL0, 1, 384, 15625),
+	F(16000000, P_GPLL0, 5, 2, 15),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	F(32000000, P_GPLL0, 1, 4, 75),
+	F(40000000, P_GPLL0, 15, 0, 0),
+	F(46400000, P_GPLL0, 1, 29, 375),
+	F(48000000, P_GPLL0, 12.5, 0, 0),
+	F(51200000, P_GPLL0, 1, 32, 375),
+	F(56000000, P_GPLL0, 1, 7, 75),
+	F(58982400, P_GPLL0, 1, 1536, 15625),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(63160000, P_GPLL0, 9.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr = 0x068c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_uart1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr = 0x070c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_uart2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr = 0x078c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_uart3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr = 0x080c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_uart4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+	.cmd_rcgr = 0x088c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_uart5_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+	.cmd_rcgr = 0x090c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp1_uart6_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x09a0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup1_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+	.cmd_rcgr = 0x098c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup1_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0a20,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup2_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0a0c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup2_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0aa0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup3_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0a8c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup3_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0b20,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup4_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0b0c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup4_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0ba0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup5_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0b8c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup5_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0c20,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup6_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0c0c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blspqup_spi_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_qup6_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+	.cmd_rcgr = 0x09cc,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_uart1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+	.cmd_rcgr = 0x0a4c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_uart2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+	.cmd_rcgr = 0x0acc,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_uart3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+	.cmd_rcgr = 0x0b4c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_uart4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+	.cmd_rcgr = 0x0bcc,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_uart5_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+	.cmd_rcgr = 0x0c4c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "blsp2_uart6_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_gp1_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+	.cmd_rcgr = 0x1904,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gp1_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "gp1_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_gp2_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+	.cmd_rcgr = 0x1944,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gp2_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "gp2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_gp3_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+	.cmd_rcgr = 0x1984,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gp3_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "gp3_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_pcie_0_aux_clk_src[] = {
+	F(1011000, P_XO, 1, 1, 19),
+	{ }
+};
+
+static struct clk_rcg2 pcie_0_aux_clk_src = {
+	.cmd_rcgr = 0x1b00,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.freq_tbl = ftbl_pcie_0_aux_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "pcie_0_aux_clk_src",
+		.parent_names = (const char *[]) { "xo" },
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_pcie_pipe_clk_src[] = {
+	F(125000000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 pcie_0_pipe_clk_src = {
+	.cmd_rcgr = 0x1adc,
+	.hid_width = 5,
+	.freq_tbl = ftbl_pcie_pipe_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "pcie_0_pipe_clk_src",
+		.parent_names = (const char *[]) { "xo" },
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_pcie_1_aux_clk_src[] = {
+	F(1011000, P_XO, 1, 1, 19),
+	{ }
+};
+
+static struct clk_rcg2 pcie_1_aux_clk_src = {
+	.cmd_rcgr = 0x1b80,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.freq_tbl = ftbl_pcie_1_aux_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "pcie_1_aux_clk_src",
+		.parent_names = (const char *[]) { "xo" },
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 pcie_1_pipe_clk_src = {
+	.cmd_rcgr = 0x1b5c,
+	.hid_width = 5,
+	.freq_tbl = ftbl_pcie_pipe_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "pcie_1_pipe_clk_src",
+		.parent_names = (const char *[]) { "xo" },
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_pdm2_clk_src[] = {
+	F(60000000, P_GPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+	.cmd_rcgr = 0x0cd0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_pdm2_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "pdm2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+	F(144000, P_XO, 16, 3, 25),
+	F(400000, P_XO, 12, 1, 4),
+	F(20000000, P_GPLL0, 15, 1, 2),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(192000000, P_GPLL4, 2, 0, 0),
+	F(384000000, P_GPLL4, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+	.cmd_rcgr = 0x04d0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_gpll4_map,
+	.freq_tbl = ftbl_sdcc1_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "sdcc1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0_gpll4,
+		.num_parents = 3,
+		.ops = &clk_rcg2_floor_ops,
+	},
+};
+
+static struct freq_tbl ftbl_sdcc2_4_apps_clk_src[] = {
+	F(144000, P_XO, 16, 3, 25),
+	F(400000, P_XO, 12, 1, 4),
+	F(20000000, P_GPLL0, 15, 1, 2),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+	.cmd_rcgr = 0x0510,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "sdcc2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_floor_ops,
+	},
+};
+
+static struct clk_rcg2 sdcc3_apps_clk_src = {
+	.cmd_rcgr = 0x0550,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "sdcc3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_floor_ops,
+	},
+};
+
+static struct clk_rcg2 sdcc4_apps_clk_src = {
+	.cmd_rcgr = 0x0590,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_sdcc2_4_apps_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "sdcc4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_floor_ops,
+	},
+};
+
+static struct freq_tbl ftbl_tsif_ref_clk_src[] = {
+	F(105500, P_XO, 1, 1, 182),
+	{ }
+};
+
+static struct clk_rcg2 tsif_ref_clk_src = {
+	.cmd_rcgr = 0x0d90,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.freq_tbl = ftbl_tsif_ref_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "tsif_ref_clk_src",
+		.parent_names = (const char *[]) { "xo" },
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+	.cmd_rcgr = 0x03e8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "usb30_mock_utmi_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_usb3_phy_aux_clk_src[] = {
+	F(1200000, P_XO, 16, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb3_phy_aux_clk_src = {
+	.cmd_rcgr = 0x1414,
+	.hid_width = 5,
+	.freq_tbl = ftbl_usb3_phy_aux_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "usb3_phy_aux_clk_src",
+		.parent_names = (const char *[]) { "xo" },
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_usb_hs_system_clk_src[] = {
+	F(75000000, P_GPLL0, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hs_system_clk_src = {
+	.cmd_rcgr = 0x0490,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_usb_hs_system_clk_src,
+	.clkr.hw.init = &(struct clk_init_data)
+	{
+		.name = "usb_hs_system_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+	.halt_reg = 0x05c4,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(17),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_ahb_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+	.halt_reg = 0x0648,
+	.clkr = {
+		.enable_reg = 0x0648,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup1_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup1_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+	.halt_reg = 0x0644,
+	.clkr = {
+		.enable_reg = 0x0644,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup1_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup1_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+	.halt_reg = 0x06c8,
+	.clkr = {
+		.enable_reg = 0x06c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup2_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup2_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+	.halt_reg = 0x06c4,
+	.clkr = {
+		.enable_reg = 0x06c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup2_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup2_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+	.halt_reg = 0x0748,
+	.clkr = {
+		.enable_reg = 0x0748,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup3_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup3_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+	.halt_reg = 0x0744,
+	.clkr = {
+		.enable_reg = 0x0744,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup3_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup3_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+	.halt_reg = 0x07c8,
+	.clkr = {
+		.enable_reg = 0x07c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup4_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup4_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+	.halt_reg = 0x07c4,
+	.clkr = {
+		.enable_reg = 0x07c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup4_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup4_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+	.halt_reg = 0x0848,
+	.clkr = {
+		.enable_reg = 0x0848,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup5_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup5_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+	.halt_reg = 0x0844,
+	.clkr = {
+		.enable_reg = 0x0844,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup5_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup5_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+	.halt_reg = 0x08c8,
+	.clkr = {
+		.enable_reg = 0x08c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup6_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup6_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+	.halt_reg = 0x08c4,
+	.clkr = {
+		.enable_reg = 0x08c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_qup6_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_qup6_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+	.halt_reg = 0x0684,
+	.clkr = {
+		.enable_reg = 0x0684,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_uart1_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_uart1_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+	.halt_reg = 0x0704,
+	.clkr = {
+		.enable_reg = 0x0704,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_uart2_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_uart2_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+	.halt_reg = 0x0784,
+	.clkr = {
+		.enable_reg = 0x0784,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_uart3_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_uart3_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+	.halt_reg = 0x0804,
+	.clkr = {
+		.enable_reg = 0x0804,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_uart4_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_uart4_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+	.halt_reg = 0x0884,
+	.clkr = {
+		.enable_reg = 0x0884,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_uart5_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_uart5_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+	.halt_reg = 0x0904,
+	.clkr = {
+		.enable_reg = 0x0904,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp1_uart6_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp1_uart6_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+	.halt_reg = 0x0944,
+	.halt_check = BRANCH_HALT_VOTED,
+	.clkr = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(15),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_ahb_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+	.halt_reg = 0x0988,
+	.clkr = {
+		.enable_reg = 0x0988,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup1_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup1_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+	.halt_reg = 0x0984,
+	.clkr = {
+		.enable_reg = 0x0984,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup1_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup1_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+	.halt_reg = 0x0a08,
+	.clkr = {
+		.enable_reg = 0x0a08,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup2_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup2_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+	.halt_reg = 0x0a04,
+	.clkr = {
+		.enable_reg = 0x0a04,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup2_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup2_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+	.halt_reg = 0x0a88,
+	.clkr = {
+		.enable_reg = 0x0a88,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup3_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup3_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+	.halt_reg = 0x0a84,
+	.clkr = {
+		.enable_reg = 0x0a84,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup3_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup3_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+	.halt_reg = 0x0b08,
+	.clkr = {
+		.enable_reg = 0x0b08,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup4_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup4_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+	.halt_reg = 0x0b04,
+	.clkr = {
+		.enable_reg = 0x0b04,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup4_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup4_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
+	.halt_reg = 0x0b88,
+	.clkr = {
+		.enable_reg = 0x0b88,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup5_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup5_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
+	.halt_reg = 0x0b84,
+	.clkr = {
+		.enable_reg = 0x0b84,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup5_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup5_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
+	.halt_reg = 0x0c08,
+	.clkr = {
+		.enable_reg = 0x0c08,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup6_i2c_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup6_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
+	.halt_reg = 0x0c04,
+	.clkr = {
+		.enable_reg = 0x0c04,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_qup6_spi_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_qup6_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+	.halt_reg = 0x09c4,
+	.clkr = {
+		.enable_reg = 0x09c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_uart1_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_uart1_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+	.halt_reg = 0x0a44,
+	.clkr = {
+		.enable_reg = 0x0a44,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_uart2_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_uart2_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart3_apps_clk = {
+	.halt_reg = 0x0ac4,
+	.clkr = {
+		.enable_reg = 0x0ac4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_uart3_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_uart3_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart4_apps_clk = {
+	.halt_reg = 0x0b44,
+	.clkr = {
+		.enable_reg = 0x0b44,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_uart4_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_uart4_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart5_apps_clk = {
+	.halt_reg = 0x0bc4,
+	.clkr = {
+		.enable_reg = 0x0bc4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_uart5_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_uart5_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart6_apps_clk = {
+	.halt_reg = 0x0c44,
+	.clkr = {
+		.enable_reg = 0x0c44,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_blsp2_uart6_apps_clk",
+			.parent_names = (const char *[]) {
+				"blsp2_uart6_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp1_clk = {
+	.halt_reg = 0x1900,
+	.clkr = {
+		.enable_reg = 0x1900,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_gp1_clk",
+			.parent_names = (const char *[]) {
+				"gp1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp2_clk = {
+	.halt_reg = 0x1940,
+	.clkr = {
+		.enable_reg = 0x1940,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_gp2_clk",
+			.parent_names = (const char *[]) {
+				"gp2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp3_clk = {
+	.halt_reg = 0x1980,
+	.clkr = {
+		.enable_reg = 0x1980,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_gp3_clk",
+			.parent_names = (const char *[]) {
+				"gp3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+	.halt_reg = 0x1ad4,
+	.clkr = {
+		.enable_reg = 0x1ad4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_pcie_0_aux_clk",
+			.parent_names = (const char *[]) {
+				"pcie_0_aux_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_0_pipe_clk = {
+	.halt_reg = 0x1ad8,
+	.halt_check = BRANCH_HALT_DELAY,
+	.clkr = {
+		.enable_reg = 0x1ad8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_pcie_0_pipe_clk",
+			.parent_names = (const char *[]) {
+				"pcie_0_pipe_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_aux_clk = {
+	.halt_reg = 0x1b54,
+	.clkr = {
+		.enable_reg = 0x1b54,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_pcie_1_aux_clk",
+			.parent_names = (const char *[]) {
+				"pcie_1_aux_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pcie_1_pipe_clk = {
+	.halt_reg = 0x1b58,
+	.halt_check = BRANCH_HALT_DELAY,
+	.clkr = {
+		.enable_reg = 0x1b58,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_pcie_1_pipe_clk",
+			.parent_names = (const char *[]) {
+				"pcie_1_pipe_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+	.halt_reg = 0x0ccc,
+	.clkr = {
+		.enable_reg = 0x0ccc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_pdm2_clk",
+			.parent_names = (const char *[]) {
+				"pdm2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+	.halt_reg = 0x04c4,
+	.clkr = {
+		.enable_reg = 0x04c4,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_sdcc1_apps_clk",
+			.parent_names = (const char *[]) {
+				"sdcc1_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+	.halt_reg = 0x0504,
+	.clkr = {
+		.enable_reg = 0x0504,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_sdcc2_apps_clk",
+			.parent_names = (const char *[]) {
+				"sdcc2_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc3_apps_clk = {
+	.halt_reg = 0x0544,
+	.clkr = {
+		.enable_reg = 0x0544,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_sdcc3_apps_clk",
+			.parent_names = (const char *[]) {
+				"sdcc3_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc4_apps_clk = {
+	.halt_reg = 0x0584,
+	.clkr = {
+		.enable_reg = 0x0584,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_sdcc4_apps_clk",
+			.parent_names = (const char *[]) {
+				"sdcc4_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sys_noc_ufs_axi_clk = {
+	.halt_reg = 0x1d7c,
+	.clkr = {
+		.enable_reg = 0x1d7c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_sys_noc_ufs_axi_clk",
+			.parent_names = (const char *[]) {
+				"ufs_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
+	.halt_reg = 0x03fc,
+	.clkr = {
+		.enable_reg = 0x03fc,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_sys_noc_usb3_axi_clk",
+			.parent_names = (const char *[]) {
+				"usb30_master_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_ref_clk = {
+	.halt_reg = 0x0d88,
+	.clkr = {
+		.enable_reg = 0x0d88,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_tsif_ref_clk",
+			.parent_names = (const char *[]) {
+				"tsif_ref_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_axi_clk = {
+	.halt_reg = 0x1d48,
+	.clkr = {
+		.enable_reg = 0x1d48,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_ufs_axi_clk",
+			.parent_names = (const char *[]) {
+				"ufs_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_rx_cfg_clk = {
+	.halt_reg = 0x1d54,
+	.clkr = {
+		.enable_reg = 0x1d54,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_ufs_rx_cfg_clk",
+			.parent_names = (const char *[]) {
+				"ufs_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ufs_tx_cfg_clk = {
+	.halt_reg = 0x1d50,
+	.clkr = {
+		.enable_reg = 0x1d50,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_ufs_tx_cfg_clk",
+			.parent_names = (const char *[]) {
+				"ufs_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+	.halt_reg = 0x03c8,
+	.clkr = {
+		.enable_reg = 0x03c8,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_usb30_master_clk",
+			.parent_names = (const char *[]) {
+				"usb30_master_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+	.halt_reg = 0x03d0,
+	.clkr = {
+		.enable_reg = 0x03d0,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_usb30_mock_utmi_clk",
+			.parent_names = (const char *[]) {
+				"usb30_mock_utmi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb3_phy_aux_clk = {
+	.halt_reg = 0x1408,
+	.clkr = {
+		.enable_reg = 0x1408,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_usb3_phy_aux_clk",
+			.parent_names = (const char *[]) {
+				"usb3_phy_aux_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hs_system_clk = {
+	.halt_reg = 0x0484,
+	.clkr = {
+		.enable_reg = 0x0484,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data)
+		{
+			.name = "gcc_usb_hs_system_clk",
+			.parent_names = (const char *[]) {
+				"usb_hs_system_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_regmap *gcc_msm8994_clocks[] = {
+	[GPLL0_EARLY] = &gpll0_early.clkr,
+	[GPLL0] = &gpll0.clkr,
+	[GPLL4_EARLY] = &gpll4_early.clkr,
+	[GPLL4] = &gpll4.clkr,
+	[UFS_AXI_CLK_SRC] = &ufs_axi_clk_src.clkr,
+	[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.clkr,
+	[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.clkr,
+	[BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.clkr,
+	[BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.clkr,
+	[BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.clkr,
+	[BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.clkr,
+	[BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.clkr,
+	[BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.clkr,
+	[BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.clkr,
+	[BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.clkr,
+	[BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.clkr,
+	[BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.clkr,
+	[BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.clkr,
+	[BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.clkr,
+	[BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.clkr,
+	[BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.clkr,
+	[BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.clkr,
+	[BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.clkr,
+	[BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.clkr,
+	[BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.clkr,
+	[BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.clkr,
+	[BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.clkr,
+	[BLSP2_QUP5_I2C_APPS_CLK_SRC] = &blsp2_qup5_i2c_apps_clk_src.clkr,
+	[BLSP2_QUP5_SPI_APPS_CLK_SRC] = &blsp2_qup5_spi_apps_clk_src.clkr,
+	[BLSP2_QUP6_I2C_APPS_CLK_SRC] = &blsp2_qup6_i2c_apps_clk_src.clkr,
+	[BLSP2_QUP6_SPI_APPS_CLK_SRC] = &blsp2_qup6_spi_apps_clk_src.clkr,
+	[BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.clkr,
+	[BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.clkr,
+	[BLSP2_UART3_APPS_CLK_SRC] = &blsp2_uart3_apps_clk_src.clkr,
+	[BLSP2_UART4_APPS_CLK_SRC] = &blsp2_uart4_apps_clk_src.clkr,
+	[BLSP2_UART5_APPS_CLK_SRC] = &blsp2_uart5_apps_clk_src.clkr,
+	[BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.clkr,
+	[GP1_CLK_SRC] = &gp1_clk_src.clkr,
+	[GP2_CLK_SRC] = &gp2_clk_src.clkr,
+	[GP3_CLK_SRC] = &gp3_clk_src.clkr,
+	[PCIE_0_AUX_CLK_SRC] = &pcie_0_aux_clk_src.clkr,
+	[PCIE_0_PIPE_CLK_SRC] = &pcie_0_pipe_clk_src.clkr,
+	[PCIE_1_AUX_CLK_SRC] = &pcie_1_aux_clk_src.clkr,
+	[PCIE_1_PIPE_CLK_SRC] = &pcie_1_pipe_clk_src.clkr,
+	[PDM2_CLK_SRC] = &pdm2_clk_src.clkr,
+	[SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.clkr,
+	[SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.clkr,
+	[SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.clkr,
+	[SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.clkr,
+	[TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.clkr,
+	[USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.clkr,
+	[USB3_PHY_AUX_CLK_SRC] = &usb3_phy_aux_clk_src.clkr,
+	[USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.clkr,
+	[GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
+	[GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.clkr,
+	[GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.clkr,
+	[GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.clkr,
+	[GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.clkr,
+	[GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.clkr,
+	[GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.clkr,
+	[GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.clkr,
+	[GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.clkr,
+	[GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.clkr,
+	[GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.clkr,
+	[GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.clkr,
+	[GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.clkr,
+	[GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.clkr,
+	[GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.clkr,
+	[GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP5_I2C_APPS_CLK] = &gcc_blsp2_qup5_i2c_apps_clk.clkr,
+	[GCC_BLSP2_QUP5_SPI_APPS_CLK] = &gcc_blsp2_qup5_spi_apps_clk.clkr,
+	[GCC_BLSP2_QUP6_I2C_APPS_CLK] = &gcc_blsp2_qup6_i2c_apps_clk.clkr,
+	[GCC_BLSP2_QUP6_SPI_APPS_CLK] = &gcc_blsp2_qup6_spi_apps_clk.clkr,
+	[GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.clkr,
+	[GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.clkr,
+	[GCC_BLSP2_UART3_APPS_CLK] = &gcc_blsp2_uart3_apps_clk.clkr,
+	[GCC_BLSP2_UART4_APPS_CLK] = &gcc_blsp2_uart4_apps_clk.clkr,
+	[GCC_BLSP2_UART5_APPS_CLK] = &gcc_blsp2_uart5_apps_clk.clkr,
+	[GCC_BLSP2_UART6_APPS_CLK] = &gcc_blsp2_uart6_apps_clk.clkr,
+	[GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
+	[GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
+	[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
+	[GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+	[GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+	[GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+	[GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
+	[GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
+	[GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
+	[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
+	[GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
+	[GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
+	[GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr,
+	[GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr,
+	[GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
+	[GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
+	[GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr,
+	[GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr,
+	[GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
+	[GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
+	[GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
+	[GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr,
+};
+
+static const struct regmap_config gcc_msm8994_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x2000,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc gcc_msm8994_desc = {
+	.config = &gcc_msm8994_regmap_config,
+	.clks = gcc_msm8994_clocks,
+	.num_clks = ARRAY_SIZE(gcc_msm8994_clocks),
+};
+
+static const struct of_device_id gcc_msm8994_match_table[] = {
+	{ .compatible = "qcom,gcc-msm8994" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8994_match_table);
+
+static int gcc_msm8994_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct clk *clk;
+
+	clk = devm_clk_register(dev, &xo.hw);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	return qcom_cc_probe(pdev, &gcc_msm8994_desc);
+}
+
+static struct platform_driver gcc_msm8994_driver = {
+	.probe		= gcc_msm8994_probe,
+	.driver		= {
+		.name	= "gcc-msm8994",
+		.of_match_table = gcc_msm8994_match_table,
+	},
+};
+
+static int __init gcc_msm8994_init(void)
+{
+	return platform_driver_register(&gcc_msm8994_driver);
+}
+core_initcall(gcc_msm8994_init);
+
+static void __exit gcc_msm8994_exit(void)
+{
+	platform_driver_unregister(&gcc_msm8994_driver);
+}
+module_exit(gcc_msm8994_exit);
+
+MODULE_DESCRIPTION("Qualcomm GCC MSM8994 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8994");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8996.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8996.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gcc-msm8996.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gcc-msm8996.c	2017-02-12 16:03:20.000000000 -0500
@@ -460,14 +460,22 @@ static struct clk_rcg2 sdcc1_apps_clk_sr
 		.name = "sdcc1_apps_clk_src",
 		.parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
 		.num_parents = 4,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
+static struct freq_tbl ftbl_sdcc1_ice_core_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(300000000, P_GPLL0, 2, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 sdcc1_ice_core_clk_src = {
 	.cmd_rcgr = 0x13024,
 	.hid_width = 5,
 	.parent_map = gcc_xo_gpll0_gpll4_gpll0_early_div_map,
+	.freq_tbl = ftbl_sdcc1_ice_core_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "sdcc1_ice_core_clk_src",
 		.parent_names = gcc_xo_gpll0_gpll4_gpll0_early_div,
@@ -497,7 +505,7 @@ static struct clk_rcg2 sdcc2_apps_clk_sr
 		.name = "sdcc2_apps_clk_src",
 		.parent_names = gcc_xo_gpll0_gpll4,
 		.num_parents = 3,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -511,7 +519,7 @@ static struct clk_rcg2 sdcc3_apps_clk_sr
 		.name = "sdcc3_apps_clk_src",
 		.parent_names = gcc_xo_gpll0_gpll4,
 		.num_parents = 3,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -535,7 +543,7 @@ static struct clk_rcg2 sdcc4_apps_clk_sr
 		.name = "sdcc4_apps_clk_src",
 		.parent_names = gcc_xo_gpll0,
 		.num_parents = 2,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -1230,10 +1238,18 @@ static struct clk_rcg2 ufs_axi_clk_src =
 	},
 };
 
+static const struct freq_tbl ftbl_ufs_ice_core_clk_src[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(300000000, P_GPLL0, 2, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 ufs_ice_core_clk_src = {
 	.cmd_rcgr = 0x76014,
 	.hid_width = 5,
 	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_ufs_ice_core_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "ufs_ice_core_clk_src",
 		.parent_names = gcc_xo_gpll0,
@@ -1242,10 +1258,19 @@ static struct clk_rcg2 ufs_ice_core_clk_
 	},
 };
 
+static const struct freq_tbl ftbl_qspi_ser_clk_src[] = {
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(256000000, P_GPLL4, 1.5, 0, 0),
+	F(300000000, P_GPLL0, 2, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 qspi_ser_clk_src = {
 	.cmd_rcgr = 0x8b00c,
 	.hid_width = 5,
 	.parent_map = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div_map,
+	.freq_tbl = ftbl_qspi_ser_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "qspi_ser_clk_src",
 		.parent_names = gcc_xo_gpll0_gpll1_early_div_gpll1_gpll4_gpll0_early_div,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gdsc.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gdsc.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/gdsc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gdsc.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,7 @@
 #define SW_OVERRIDE_MASK	BIT(2)
 #define HW_CONTROL_MASK		BIT(1)
 #define SW_COLLAPSE_MASK	BIT(0)
+#define GMEM_CLAMP_IO_MASK	BIT(0)
 
 /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
 #define EN_REST_WAIT_VAL	(0x2 << 20)
@@ -55,6 +56,13 @@ static int gdsc_is_enabled(struct gdsc *
 	return !!(val & PWR_ON_MASK);
 }
 
+static int gdsc_hwctrl(struct gdsc *sc, bool en)
+{
+	u32 val = en ? HW_CONTROL_MASK : 0;
+
+	return regmap_update_bits(sc->regmap, sc->gdscr, HW_CONTROL_MASK, val);
+}
+
 static int gdsc_toggle_logic(struct gdsc *sc, bool en)
 {
 	int ret;
@@ -140,6 +148,18 @@ static inline void gdsc_clear_mem_on(str
 		regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0);
 }
 
+static inline void gdsc_deassert_clamp_io(struct gdsc *sc)
+{
+	regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
+			   GMEM_CLAMP_IO_MASK, 0);
+}
+
+static inline void gdsc_assert_clamp_io(struct gdsc *sc)
+{
+	regmap_update_bits(sc->regmap, sc->clamp_io_ctrl,
+			   GMEM_CLAMP_IO_MASK, 1);
+}
+
 static int gdsc_enable(struct generic_pm_domain *domain)
 {
 	struct gdsc *sc = domain_to_gdsc(domain);
@@ -148,6 +168,9 @@ static int gdsc_enable(struct generic_pm
 	if (sc->pwrsts == PWRSTS_ON)
 		return gdsc_deassert_reset(sc);
 
+	if (sc->flags & CLAMP_IO)
+		gdsc_deassert_clamp_io(sc);
+
 	ret = gdsc_toggle_logic(sc, true);
 	if (ret)
 		return ret;
@@ -164,20 +187,39 @@ static int gdsc_enable(struct generic_pm
 	 */
 	udelay(1);
 
+	/* Turn on HW trigger mode if supported */
+	if (sc->flags & HW_CTRL)
+		return gdsc_hwctrl(sc, true);
+
 	return 0;
 }
 
 static int gdsc_disable(struct generic_pm_domain *domain)
 {
 	struct gdsc *sc = domain_to_gdsc(domain);
+	int ret;
 
 	if (sc->pwrsts == PWRSTS_ON)
 		return gdsc_assert_reset(sc);
 
+	/* Turn off HW trigger mode if supported */
+	if (sc->flags & HW_CTRL) {
+		ret = gdsc_hwctrl(sc, false);
+		if (ret < 0)
+			return ret;
+	}
+
 	if (sc->pwrsts & PWRSTS_OFF)
 		gdsc_clear_mem_on(sc);
 
-	return gdsc_toggle_logic(sc, false);
+	ret = gdsc_toggle_logic(sc, false);
+	if (ret)
+		return ret;
+
+	if (sc->flags & CLAMP_IO)
+		gdsc_assert_clamp_io(sc);
+
+	return 0;
 }
 
 static int gdsc_init(struct gdsc *sc)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/gdsc.h linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gdsc.h
--- linux-libre-4.9-gnu/drivers/clk/qcom/gdsc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/gdsc.h	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,7 @@ struct gdsc {
 	struct regmap			*regmap;
 	unsigned int			gdscr;
 	unsigned int			gds_hw_ctrl;
+	unsigned int			clamp_io_ctrl;
 	unsigned int			*cxcs;
 	unsigned int			cxc_count;
 	const u8			pwrsts;
@@ -50,6 +51,8 @@ struct gdsc {
 #define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
 	const u8			flags;
 #define VOTABLE		BIT(0)
+#define CLAMP_IO	BIT(1)
+#define HW_CTRL		BIT(2)
 	struct reset_controller_dev	*rcdev;
 	unsigned int			*resets;
 	unsigned int			reset_count;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/Kconfig linux-libre-4.10-rc8-gnu/drivers/clk/qcom/Kconfig
--- linux-libre-4.9-gnu/drivers/clk/qcom/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,9 @@ config QCOM_GDSC
 	bool
 	select PM_GENERIC_DOMAINS if PM
 
+config QCOM_RPMCC
+	bool
+
 config COMMON_CLK_QCOM
 	tristate "Support for Qualcomm's clock controllers"
 	depends on OF
@@ -9,6 +12,32 @@ config COMMON_CLK_QCOM
 	select REGMAP_MMIO
 	select RESET_CONTROLLER
 
+config QCOM_CLK_RPM
+	tristate "RPM based Clock Controller"
+	depends on COMMON_CLK_QCOM && MFD_QCOM_RPM
+	select QCOM_RPMCC
+	help
+	  The RPM (Resource Power Manager) is a dedicated hardware engine for
+	  managing the shared SoC resources in order to keep the lowest power
+	  profile. It communicates with other hardware subsystems via shared
+	  memory and accepts clock requests, aggregates the requests and turns
+	  the clocks on/off or scales them on demand.
+	  Say Y if you want to support the clocks exposed by the RPM on
+	  platforms such as apq8064, msm8660, msm8960 etc.
+
+config QCOM_CLK_SMD_RPM
+	tristate "RPM over SMD based Clock Controller"
+	depends on COMMON_CLK_QCOM && QCOM_SMD_RPM
+	select QCOM_RPMCC
+	help
+	  The RPM (Resource Power Manager) is a dedicated hardware engine for
+	  managing the shared SoC resources in order to keep the lowest power
+	  profile. It communicates with other hardware subsystems via shared
+	  memory and accepts clock requests, aggregates the requests and turns
+	  the clocks on/off or scales them on demand.
+	  Say Y if you want to support the clocks exposed by the RPM on
+	  platforms such as apq8016, apq8084, msm8974 etc.
+
 config APQ_GCC_8084
 	tristate "APQ8084 Global Clock Controller"
 	select QCOM_GDSC
@@ -132,6 +161,14 @@ config MSM_MMCC_8974
 	  Say Y if you want to support multimedia devices such as display,
 	  graphics, video encode/decode, camera, etc.
 
+config MSM_GCC_8994
+	tristate "MSM8994 Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the global clock controller on msm8994 devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, UFS, SD/eMMC, PCIe, etc.
+
 config MSM_GCC_8996
 	tristate "MSM8996 Global Clock Controller"
 	select QCOM_GDSC
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/lcc-ipq806x.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/lcc-ipq806x.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/lcc-ipq806x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/lcc-ipq806x.c	2017-02-12 16:03:20.000000000 -0500
@@ -443,7 +443,7 @@ static int lcc_ipq806x_probe(struct plat
 		return PTR_ERR(regmap);
 
 	/* Configure the rate of PLL4 if the bootloader hasn't already */
-	val = regmap_read(regmap, 0x0, &val);
+	regmap_read(regmap, 0x0, &val);
 	if (!val)
 		clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);
 	/* Enable PLL4 source on the LPASS Primary PLL Mux */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/Makefile linux-libre-4.10-rc8-gnu/drivers/clk/qcom/Makefile
--- linux-libre-4.9-gnu/drivers/clk/qcom/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,11 @@ obj-$(CONFIG_MSM_GCC_8660) += gcc-msm866
 obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
+obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
 obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
 obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
 obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
+obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o
+obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/qcom/mmcc-msm8996.c linux-libre-4.10-rc8-gnu/drivers/clk/qcom/mmcc-msm8996.c
--- linux-libre-4.9-gnu/drivers/clk/qcom/mmcc-msm8996.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/qcom/mmcc-msm8996.c	2017-02-12 16:03:20.000000000 -0500
@@ -2945,6 +2945,7 @@ static struct gdsc venus_core0_gdsc = {
 		.name = "venus_core0",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = HW_CTRL,
 };
 
 static struct gdsc venus_core1_gdsc = {
@@ -2955,6 +2956,7 @@ static struct gdsc venus_core1_gdsc = {
 		.name = "venus_core1",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = HW_CTRL,
 };
 
 static struct gdsc camss_gdsc = {
@@ -3034,6 +3036,28 @@ static struct gdsc mdss_gdsc = {
 	.pwrsts = PWRSTS_OFF_ON,
 };
 
+static struct gdsc gpu_gdsc = {
+	.gdscr = 0x4034,
+	.gds_hw_ctrl = 0x4038,
+	.pd = {
+		.name = "gpu",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
+};
+
+static struct gdsc gpu_gx_gdsc = {
+	.gdscr = 0x4024,
+	.clamp_io_ctrl = 0x4300,
+	.cxcs = (unsigned int []){ 0x4028 },
+	.cxc_count = 1,
+	.pd = {
+		.name = "gpu_gx",
+	},
+	.pwrsts = PWRSTS_OFF_ON,
+	.flags = CLAMP_IO,
+};
+
 static struct clk_regmap *mmcc_msm8996_clocks[] = {
 	[MMPLL0_EARLY] = &mmpll0_early.clkr,
 	[MMPLL0_PLL] = &mmpll0.clkr,
@@ -3223,6 +3247,8 @@ static struct gdsc *mmcc_msm8996_gdscs[]
 	[CPP_GDSC] = &cpp_gdsc,
 	[FD_GDSC] = &fd_gdsc,
 	[MDSS_GDSC] = &mdss_gdsc,
+	[GPU_GDSC] = &gpu_gdsc,
+	[GPU_GX_GDSC] = &gpu_gx_gdsc,
 };
 
 static const struct qcom_reset_map mmcc_msm8996_resets[] = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/clk-mstp.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-mstp.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/clk-mstp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-mstp.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,12 +37,14 @@
  * @smstpcr: module stop control register
  * @mstpsr: module stop status register (optional)
  * @lock: protects writes to SMSTPCR
+ * @width_8bit: registers are 8-bit, not 32-bit
  */
 struct mstp_clock_group {
 	struct clk_onecell_data data;
 	void __iomem *smstpcr;
 	void __iomem *mstpsr;
 	spinlock_t lock;
+	bool width_8bit;
 };
 
 /**
@@ -59,6 +61,18 @@ struct mstp_clock {
 
 #define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
 
+static inline u32 cpg_mstp_read(struct mstp_clock_group *group,
+				u32 __iomem *reg)
+{
+	return group->width_8bit ? readb(reg) : clk_readl(reg);
+}
+
+static inline void cpg_mstp_write(struct mstp_clock_group *group, u32 val,
+				  u32 __iomem *reg)
+{
+	group->width_8bit ? writeb(val, reg) : clk_writel(val, reg);
+}
+
 static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
 {
 	struct mstp_clock *clock = to_mstp_clock(hw);
@@ -70,12 +84,12 @@ static int cpg_mstp_clock_endisable(stru
 
 	spin_lock_irqsave(&group->lock, flags);
 
-	value = clk_readl(group->smstpcr);
+	value = cpg_mstp_read(group, group->smstpcr);
 	if (enable)
 		value &= ~bitmask;
 	else
 		value |= bitmask;
-	clk_writel(value, group->smstpcr);
+	cpg_mstp_write(group, value, group->smstpcr);
 
 	spin_unlock_irqrestore(&group->lock, flags);
 
@@ -83,7 +97,7 @@ static int cpg_mstp_clock_endisable(stru
 		return 0;
 
 	for (i = 1000; i > 0; --i) {
-		if (!(clk_readl(group->mstpsr) & bitmask))
+		if (!(cpg_mstp_read(group, group->mstpsr) & bitmask))
 			break;
 		cpu_relax();
 	}
@@ -114,9 +128,9 @@ static int cpg_mstp_clock_is_enabled(str
 	u32 value;
 
 	if (group->mstpsr)
-		value = clk_readl(group->mstpsr);
+		value = cpg_mstp_read(group, group->mstpsr);
 	else
-		value = clk_readl(group->smstpcr);
+		value = cpg_mstp_read(group, group->smstpcr);
 
 	return !(value & BIT(clock->bit_index));
 }
@@ -188,6 +202,9 @@ static void __init cpg_mstp_clocks_init(
 		return;
 	}
 
+	if (of_device_is_compatible(np, "renesas,r7s72100-mstp-clocks"))
+		group->width_8bit = true;
+
 	for (i = 0; i < MSTP_MAX_CLOCKS; ++i)
 		clks[i] = ERR_PTR(-ENOENT);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/clk-r8a7778.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-r8a7778.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/clk-r8a7778.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-r8a7778.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/clk/renesas.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 struct r8a7778_cpg {
 	struct clk_onecell_data data;
@@ -83,6 +84,18 @@ static void __init r8a7778_cpg_clocks_in
 	struct clk **clks;
 	unsigned int i;
 	int num_clks;
+	u32 mode;
+
+	if (rcar_rst_read_mode_pins(&mode))
+		return;
+
+	BUG_ON(!(mode & BIT(19)));
+
+	cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
+			 (!!(mode & BIT(12)) << 1) |
+			 (!!(mode & BIT(11)));
+	cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
+			(!!(mode & BIT(1)));
 
 	num_clks = of_property_count_strings(np, "clock-output-names");
 	if (num_clks < 0) {
@@ -130,16 +143,3 @@ static void __init r8a7778_cpg_clocks_in
 
 CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
 	       r8a7778_cpg_clocks_init);
-
-void __init r8a7778_clocks_init(u32 mode)
-{
-	BUG_ON(!(mode & BIT(19)));
-
-	cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
-			 (!!(mode & BIT(12)) << 1) |
-			 (!!(mode & BIT(11)));
-	cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
-			(!!(mode & BIT(1)));
-
-	of_clk_init(NULL);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/clk-r8a7779.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-r8a7779.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/clk-r8a7779.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-r8a7779.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a7779-clock.h>
 
@@ -88,8 +89,6 @@ static const unsigned int cpg_plla_mult[
  * Initialization
  */
 
-static u32 cpg_mode __initdata;
-
 static struct clk * __init
 r8a7779_cpg_register_clock(struct device_node *np, struct r8a7779_cpg *cpg,
 			   const struct cpg_clk_config *config,
@@ -127,6 +126,10 @@ static void __init r8a7779_cpg_clocks_in
 	struct clk **clks;
 	unsigned int i, plla_mult;
 	int num_clks;
+	u32 mode;
+
+	if (rcar_rst_read_mode_pins(&mode))
+		return;
 
 	num_clks = of_property_count_strings(np, "clock-output-names");
 	if (num_clks < 0) {
@@ -148,8 +151,8 @@ static void __init r8a7779_cpg_clocks_in
 	cpg->data.clks = clks;
 	cpg->data.clk_num = num_clks;
 
-	config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(cpg_mode)];
-	plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(cpg_mode)];
+	config = &cpg_clk_configs[CPG_CLK_CONFIG_INDEX(mode)];
+	plla_mult = cpg_plla_mult[CPG_PLLA_MULT_INDEX(mode)];
 
 	for (i = 0; i < num_clks; ++i) {
 		const char *name;
@@ -173,10 +176,3 @@ static void __init r8a7779_cpg_clocks_in
 }
 CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks",
 	       r8a7779_cpg_clocks_init);
-
-void __init r8a7779_clocks_init(u32 mode)
-{
-	cpg_mode = mode;
-
-	of_clk_init(NULL);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/clk-rcar-gen2.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-rcar-gen2.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/clk-rcar-gen2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/clk-rcar-gen2.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 struct rcar_gen2_cpg {
 	struct clk_onecell_data data;
@@ -364,6 +365,23 @@ rcar_gen2_cpg_register_clock(struct devi
 						 4, 0, table, &cpg->lock);
 }
 
+/*
+ * Reset register definitions.
+ */
+#define MODEMR	0xe6160060
+
+static u32 __init rcar_gen2_read_mode_pins(void)
+{
+	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
+	u32 mode;
+
+	BUG_ON(!modemr);
+	mode = ioread32(modemr);
+	iounmap(modemr);
+
+	return mode;
+}
+
 static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
 {
 	const struct cpg_pll_config *config;
@@ -372,6 +390,13 @@ static void __init rcar_gen2_cpg_clocks_
 	unsigned int i;
 	int num_clks;
 
+	if (rcar_rst_read_mode_pins(&cpg_mode)) {
+		/* Backward-compatibility with old DT */
+		pr_warn("%s: failed to obtain mode pins from RST\n",
+			np->full_name);
+		cpg_mode = rcar_gen2_read_mode_pins();
+	}
+
 	num_clks = of_property_count_strings(np, "clock-output-names");
 	if (num_clks < 0) {
 		pr_err("%s: failed to count clocks\n", __func__);
@@ -420,10 +445,3 @@ static void __init rcar_gen2_cpg_clocks_
 }
 CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks",
 	       rcar_gen2_cpg_clocks_init);
-
-void __init rcar_gen2_clocks_init(u32 mode)
-{
-	cpg_mode = mode;
-
-	of_clk_init(NULL);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/Kconfig linux-libre-4.10-rc8-gnu/drivers/clk/renesas/Kconfig
--- linux-libre-4.9-gnu/drivers/clk/renesas/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,7 @@
 config CLK_RENESAS_CPG_MSSR
 	bool
+	default y if ARCH_R8A7743
+	default y if ARCH_R8A7745
 	default y if ARCH_R8A7795
 	default y if ARCH_R8A7796
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/Makefile linux-libre-4.10-rc8-gnu/drivers/clk/renesas/Makefile
--- linux-libre-4.9-gnu/drivers/clk/renesas/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,8 @@ obj-$(CONFIG_ARCH_EMEV2)		+= clk-emev2.o
 obj-$(CONFIG_ARCH_R7S72100)		+= clk-rz.o
 obj-$(CONFIG_ARCH_R8A73A4)		+= clk-r8a73a4.o clk-div6.o
 obj-$(CONFIG_ARCH_R8A7740)		+= clk-r8a7740.o clk-div6.o
+obj-$(CONFIG_ARCH_R8A7743)		+= r8a7743-cpg-mssr.o rcar-gen2-cpg.o
+obj-$(CONFIG_ARCH_R8A7745)		+= r8a7745-cpg-mssr.o rcar-gen2-cpg.o
 obj-$(CONFIG_ARCH_R8A7778)		+= clk-r8a7778.o
 obj-$(CONFIG_ARCH_R8A7779)		+= clk-r8a7779.o
 obj-$(CONFIG_ARCH_R8A7790)		+= clk-rcar-gen2.o clk-div6.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/r8a7743-cpg-mssr.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7743-cpg-mssr.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/r8a7743-cpg-mssr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7743-cpg-mssr.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,270 @@
+/*
+ * r8a7743 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded 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; of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7743-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A7743_CLK_OSC,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+	CLK_USB_EXTAL,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL3,
+	CLK_PLL1_DIV2,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7743_core_clks[] __initconst = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",	CLK_EXTAL),
+	DEF_INPUT("usb_extal",	CLK_USB_EXTAL),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",	CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",	CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",	CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+	DEF_BASE(".pll3",	CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2",	CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+	/* Core Clock Outputs */
+	DEF_BASE("z",    R8A7743_CLK_Z,    CLK_TYPE_GEN2_Z,	CLK_PLL0),
+	DEF_BASE("lb",   R8A7743_CLK_LB,   CLK_TYPE_GEN2_LB,	CLK_PLL1),
+	DEF_BASE("sdh",  R8A7743_CLK_SDH,  CLK_TYPE_GEN2_SDH,	CLK_PLL1),
+	DEF_BASE("sd0",  R8A7743_CLK_SD0,  CLK_TYPE_GEN2_SD0,	CLK_PLL1),
+	DEF_BASE("qspi", R8A7743_CLK_QSPI, CLK_TYPE_GEN2_QSPI,	CLK_PLL1_DIV2),
+	DEF_BASE("rcan", R8A7743_CLK_RCAN, CLK_TYPE_GEN2_RCAN,	CLK_USB_EXTAL),
+
+	DEF_FIXED("zg",    R8A7743_CLK_ZG,	CLK_PLL1,	    3, 1),
+	DEF_FIXED("zx",    R8A7743_CLK_ZX,	CLK_PLL1,	    3, 1),
+	DEF_FIXED("zs",    R8A7743_CLK_ZS,	CLK_PLL1,	    6, 1),
+	DEF_FIXED("hp",    R8A7743_CLK_HP,	CLK_PLL1,	   12, 1),
+	DEF_FIXED("b",     R8A7743_CLK_B,	CLK_PLL1,	   12, 1),
+	DEF_FIXED("p",     R8A7743_CLK_P,	CLK_PLL1,	   24, 1),
+	DEF_FIXED("cl",    R8A7743_CLK_CL,	CLK_PLL1,	   48, 1),
+	DEF_FIXED("m2",    R8A7743_CLK_M2,	CLK_PLL1,	    8, 1),
+	DEF_FIXED("zb3",   R8A7743_CLK_ZB3,	CLK_PLL3,	    4, 1),
+	DEF_FIXED("zb3d2", R8A7743_CLK_ZB3D2,	CLK_PLL3,	    8, 1),
+	DEF_FIXED("ddr",   R8A7743_CLK_DDR,	CLK_PLL3,	    8, 1),
+	DEF_FIXED("mp",    R8A7743_CLK_MP,	CLK_PLL1_DIV2,	   15, 1),
+	DEF_FIXED("cp",    R8A7743_CLK_CP,	CLK_EXTAL,	    2, 1),
+	DEF_FIXED("r",     R8A7743_CLK_R,	CLK_PLL1,	49152, 1),
+	DEF_FIXED("osc",   R8A7743_CLK_OSC,	CLK_PLL1,	12288, 1),
+
+	DEF_DIV6P1("sd2",  R8A7743_CLK_SD2,	CLK_PLL1_DIV2,	0x078),
+	DEF_DIV6P1("sd3",  R8A7743_CLK_SD3,	CLK_PLL1_DIV2,	0x26c),
+	DEF_DIV6P1("mmc0", R8A7743_CLK_MMC0,	CLK_PLL1_DIV2,	0x240),
+};
+
+static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = {
+	DEF_MOD("msiof0",		   0,	R8A7743_CLK_MP),
+	DEF_MOD("vcp0",			 101,	R8A7743_CLK_ZS),
+	DEF_MOD("vpc0",			 103,	R8A7743_CLK_ZS),
+	DEF_MOD("tmu1",			 111,	R8A7743_CLK_P),
+	DEF_MOD("3dg",			 112,	R8A7743_CLK_ZG),
+	DEF_MOD("2d-dmac",		 115,	R8A7743_CLK_ZS),
+	DEF_MOD("fdp1-1",		 118,	R8A7743_CLK_ZS),
+	DEF_MOD("fdp1-0",		 119,	R8A7743_CLK_ZS),
+	DEF_MOD("tmu3",			 121,	R8A7743_CLK_P),
+	DEF_MOD("tmu2",			 122,	R8A7743_CLK_P),
+	DEF_MOD("cmt0",			 124,	R8A7743_CLK_R),
+	DEF_MOD("tmu0",			 125,	R8A7743_CLK_CP),
+	DEF_MOD("vsp1du1",		 127,	R8A7743_CLK_ZS),
+	DEF_MOD("vsp1du0",		 128,	R8A7743_CLK_ZS),
+	DEF_MOD("vsp1-sy",		 131,	R8A7743_CLK_ZS),
+	DEF_MOD("scifa2",		 202,	R8A7743_CLK_MP),
+	DEF_MOD("scifa1",		 203,	R8A7743_CLK_MP),
+	DEF_MOD("scifa0",		 204,	R8A7743_CLK_MP),
+	DEF_MOD("msiof2",		 205,	R8A7743_CLK_MP),
+	DEF_MOD("scifb0",		 206,	R8A7743_CLK_MP),
+	DEF_MOD("scifb1",		 207,	R8A7743_CLK_MP),
+	DEF_MOD("msiof1",		 208,	R8A7743_CLK_MP),
+	DEF_MOD("scifb2",		 216,	R8A7743_CLK_MP),
+	DEF_MOD("sys-dmac1",		 218,	R8A7743_CLK_ZS),
+	DEF_MOD("sys-dmac0",		 219,	R8A7743_CLK_ZS),
+	DEF_MOD("tpu0",			 304,	R8A7743_CLK_CP),
+	DEF_MOD("sdhi3",		 311,	R8A7743_CLK_SD3),
+	DEF_MOD("sdhi2",		 312,	R8A7743_CLK_SD2),
+	DEF_MOD("sdhi0",		 314,	R8A7743_CLK_SD0),
+	DEF_MOD("mmcif0",		 315,	R8A7743_CLK_MMC0),
+	DEF_MOD("iic0",			 318,	R8A7743_CLK_HP),
+	DEF_MOD("pciec",		 319,	R8A7743_CLK_MP),
+	DEF_MOD("iic1",			 323,	R8A7743_CLK_HP),
+	DEF_MOD("usb3.0",		 328,	R8A7743_CLK_MP),
+	DEF_MOD("cmt1",			 329,	R8A7743_CLK_R),
+	DEF_MOD("usbhs-dmac0",		 330,	R8A7743_CLK_HP),
+	DEF_MOD("usbhs-dmac1",		 331,	R8A7743_CLK_HP),
+	DEF_MOD("irqc",			 407,	R8A7743_CLK_CP),
+	DEF_MOD("intc-sys",		 408,	R8A7743_CLK_ZS),
+	DEF_MOD("audio-dmac1",		 501,	R8A7743_CLK_HP),
+	DEF_MOD("audio-dmac0",		 502,	R8A7743_CLK_HP),
+	DEF_MOD("thermal",		 522,	CLK_EXTAL),
+	DEF_MOD("pwm",			 523,	R8A7743_CLK_P),
+	DEF_MOD("usb-ehci",		 703,	R8A7743_CLK_MP),
+	DEF_MOD("usbhs",		 704,	R8A7743_CLK_HP),
+	DEF_MOD("hscif2",		 713,	R8A7743_CLK_ZS),
+	DEF_MOD("scif5",		 714,	R8A7743_CLK_P),
+	DEF_MOD("scif4",		 715,	R8A7743_CLK_P),
+	DEF_MOD("hscif1",		 716,	R8A7743_CLK_ZS),
+	DEF_MOD("hscif0",		 717,	R8A7743_CLK_ZS),
+	DEF_MOD("scif3",		 718,	R8A7743_CLK_P),
+	DEF_MOD("scif2",		 719,	R8A7743_CLK_P),
+	DEF_MOD("scif1",		 720,	R8A7743_CLK_P),
+	DEF_MOD("scif0",		 721,	R8A7743_CLK_P),
+	DEF_MOD("du1",			 723,	R8A7743_CLK_ZX),
+	DEF_MOD("du0",			 724,	R8A7743_CLK_ZX),
+	DEF_MOD("lvds0",		 726,	R8A7743_CLK_ZX),
+	DEF_MOD("ipmmu-sgx",		 800,	R8A7743_CLK_ZX),
+	DEF_MOD("vin2",			 809,	R8A7743_CLK_ZG),
+	DEF_MOD("vin1",			 810,	R8A7743_CLK_ZG),
+	DEF_MOD("vin0",			 811,	R8A7743_CLK_ZG),
+	DEF_MOD("etheravb",		 812,	R8A7743_CLK_HP),
+	DEF_MOD("ether",		 813,	R8A7743_CLK_P),
+	DEF_MOD("sata1",		 814,	R8A7743_CLK_ZS),
+	DEF_MOD("sata0",		 815,	R8A7743_CLK_ZS),
+	DEF_MOD("gpio7",		 904,	R8A7743_CLK_CP),
+	DEF_MOD("gpio6",		 905,	R8A7743_CLK_CP),
+	DEF_MOD("gpio5",		 907,	R8A7743_CLK_CP),
+	DEF_MOD("gpio4",		 908,	R8A7743_CLK_CP),
+	DEF_MOD("gpio3",		 909,	R8A7743_CLK_CP),
+	DEF_MOD("gpio2",		 910,	R8A7743_CLK_CP),
+	DEF_MOD("gpio1",		 911,	R8A7743_CLK_CP),
+	DEF_MOD("gpio0",		 912,	R8A7743_CLK_CP),
+	DEF_MOD("can1",			 915,	R8A7743_CLK_P),
+	DEF_MOD("can0",			 916,	R8A7743_CLK_P),
+	DEF_MOD("qspi_mod",		 917,	R8A7743_CLK_QSPI),
+	DEF_MOD("i2c5",			 925,	R8A7743_CLK_HP),
+	DEF_MOD("iicdvfs",		 926,	R8A7743_CLK_CP),
+	DEF_MOD("i2c4",			 927,	R8A7743_CLK_HP),
+	DEF_MOD("i2c3",			 928,	R8A7743_CLK_HP),
+	DEF_MOD("i2c2",			 929,	R8A7743_CLK_HP),
+	DEF_MOD("i2c1",			 930,	R8A7743_CLK_HP),
+	DEF_MOD("i2c0",			 931,	R8A7743_CLK_HP),
+	DEF_MOD("ssi-all",		1005,	R8A7743_CLK_P),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A7743_CLK_P),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
+	DEF_MOD("scifa3",		1106,	R8A7743_CLK_MP),
+	DEF_MOD("scifa4",		1107,	R8A7743_CLK_MP),
+	DEF_MOD("scifa5",		1108,	R8A7743_CLK_MP),
+};
+
+static const unsigned int r8a7743_crit_mod_clks[] __initconst = {
+	MOD_CLK_ID(408),	/* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *    MD	EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*1
+ *---------------------------------------------------
+ * 0  0  0	15		x172/2	x208/2	x106
+ * 0  0  1	15		x172/2	x208/2	x88
+ * 0  1  0	20		x130/2	x156/2	x80
+ * 0  1  1	20		x130/2	x156/2	x66
+ * 1  0  0	26 / 2		x200/2	x240/2	x122
+ * 1  0  1	26 / 2		x200/2	x240/2	x102
+ * 1  1  0	30 / 2		x172/2	x208/2	x106
+ * 1  1  1	30 / 2		x172/2	x208/2	x88
+ *
+ * *1 :	Table 7.5a indicates VCO output (PLLx = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 12) | \
+					 (((md) & BIT(13)) >> 12) | \
+					 (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+	/* EXTAL div	PLL1 mult	PLL3 mult */
+	{ 1,		208,		106,	},
+	{ 1,		208,		88,	},
+	{ 1,		156,		80,	},
+	{ 1,		156,		66,	},
+	{ 2,		240,		122,	},
+	{ 2,		240,		102,	},
+	{ 2,		208,		106,	},
+	{ 2,		208,		88,	},
+};
+
+static int __init r8a7743_cpg_mssr_init(struct device *dev)
+{
+	const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
+
+	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+	return rcar_gen2_cpg_init(cpg_pll_config, 2, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7743_cpg_mssr_info __initconst = {
+	/* Core Clocks */
+	.core_clks = r8a7743_core_clks,
+	.num_core_clks = ARRAY_SIZE(r8a7743_core_clks),
+	.last_dt_core_clk = LAST_DT_CORE_CLK,
+	.num_total_core_clks = MOD_CLK_BASE,
+
+	/* Module Clocks */
+	.mod_clks = r8a7743_mod_clks,
+	.num_mod_clks = ARRAY_SIZE(r8a7743_mod_clks),
+	.num_hw_mod_clks = 12 * 32,
+
+	/* Critical Module Clocks */
+	.crit_mod_clks = r8a7743_crit_mod_clks,
+	.num_crit_mod_clks = ARRAY_SIZE(r8a7743_crit_mod_clks),
+
+	/* Callbacks */
+	.init = r8a7743_cpg_mssr_init,
+	.cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/r8a7745-cpg-mssr.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7745-cpg-mssr.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/r8a7745-cpg-mssr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7745-cpg-mssr.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,259 @@
+/*
+ * r8a7745 Clock Pulse Generator / Module Standby and Software Reset
+ *
+ * Copyright (C) 2016 Cogent Embedded 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; of the License.
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
+
+#include <dt-bindings/clock/r8a7745-cpg-mssr.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+enum clk_ids {
+	/* Core Clock Outputs exported to DT */
+	LAST_DT_CORE_CLK = R8A7745_CLK_OSC,
+
+	/* External Input Clocks */
+	CLK_EXTAL,
+	CLK_USB_EXTAL,
+
+	/* Internal Core Clocks */
+	CLK_MAIN,
+	CLK_PLL0,
+	CLK_PLL1,
+	CLK_PLL3,
+	CLK_PLL1_DIV2,
+
+	/* Module Clocks */
+	MOD_CLK_BASE
+};
+
+static const struct cpg_core_clk r8a7745_core_clks[] __initconst = {
+	/* External Clock Inputs */
+	DEF_INPUT("extal",	CLK_EXTAL),
+	DEF_INPUT("usb_extal",	CLK_USB_EXTAL),
+
+	/* Internal Core Clocks */
+	DEF_BASE(".main",	CLK_MAIN, CLK_TYPE_GEN2_MAIN, CLK_EXTAL),
+	DEF_BASE(".pll0",	CLK_PLL0, CLK_TYPE_GEN2_PLL0, CLK_MAIN),
+	DEF_BASE(".pll1",	CLK_PLL1, CLK_TYPE_GEN2_PLL1, CLK_MAIN),
+	DEF_BASE(".pll3",	CLK_PLL3, CLK_TYPE_GEN2_PLL3, CLK_MAIN),
+
+	DEF_FIXED(".pll1_div2",	CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
+
+	/* Core Clock Outputs */
+	DEF_BASE("lb",   R8A7745_CLK_LB,   CLK_TYPE_GEN2_LB,	CLK_PLL1),
+	DEF_BASE("sdh",  R8A7745_CLK_SDH,  CLK_TYPE_GEN2_SDH,	CLK_PLL1),
+	DEF_BASE("sd0",  R8A7745_CLK_SD0,  CLK_TYPE_GEN2_SD0,	CLK_PLL1),
+	DEF_BASE("qspi", R8A7745_CLK_QSPI, CLK_TYPE_GEN2_QSPI,	CLK_PLL1_DIV2),
+	DEF_BASE("rcan", R8A7745_CLK_RCAN, CLK_TYPE_GEN2_RCAN,	CLK_USB_EXTAL),
+
+	DEF_FIXED("z2",    R8A7745_CLK_Z2,	CLK_PLL0,	    1, 1),
+	DEF_FIXED("zg",    R8A7745_CLK_ZG,	CLK_PLL1,	    6, 1),
+	DEF_FIXED("zx",    R8A7745_CLK_ZX,	CLK_PLL1,	    3, 1),
+	DEF_FIXED("zs",    R8A7745_CLK_ZS,	CLK_PLL1,	    6, 1),
+	DEF_FIXED("hp",    R8A7745_CLK_HP,	CLK_PLL1,	   12, 1),
+	DEF_FIXED("b",     R8A7745_CLK_B,	CLK_PLL1,	   12, 1),
+	DEF_FIXED("p",     R8A7745_CLK_P,	CLK_PLL1,	   24, 1),
+	DEF_FIXED("cl",    R8A7745_CLK_CL,	CLK_PLL1,	   48, 1),
+	DEF_FIXED("cp",    R8A7745_CLK_CP,	CLK_PLL1,	   48, 1),
+	DEF_FIXED("m2",    R8A7745_CLK_M2,	CLK_PLL1,	    8, 1),
+	DEF_FIXED("zb3",   R8A7745_CLK_ZB3,	CLK_PLL3,	    4, 1),
+	DEF_FIXED("zb3d2", R8A7745_CLK_ZB3D2,	CLK_PLL3,	    8, 1),
+	DEF_FIXED("ddr",   R8A7745_CLK_DDR,	CLK_PLL3,	    8, 1),
+	DEF_FIXED("mp",    R8A7745_CLK_MP,	CLK_PLL1_DIV2,	   15, 1),
+	DEF_FIXED("cpex",  R8A7745_CLK_CPEX,	CLK_EXTAL,	    2, 1),
+	DEF_FIXED("r",     R8A7745_CLK_R,	CLK_PLL1,	49152, 1),
+	DEF_FIXED("osc",   R8A7745_CLK_OSC,	CLK_PLL1,	12288, 1),
+
+	DEF_DIV6P1("sd2",  R8A7745_CLK_SD2,	CLK_PLL1_DIV2,	0x078),
+	DEF_DIV6P1("sd3",  R8A7745_CLK_SD3,	CLK_PLL1_DIV2,	0x26c),
+	DEF_DIV6P1("mmc0", R8A7745_CLK_MMC0,	CLK_PLL1_DIV2,	0x240),
+};
+
+static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
+	DEF_MOD("msiof0",		   0,	R8A7745_CLK_MP),
+	DEF_MOD("vcp0",			 101,	R8A7745_CLK_ZS),
+	DEF_MOD("vpc0",			 103,	R8A7745_CLK_ZS),
+	DEF_MOD("tmu1",			 111,	R8A7745_CLK_P),
+	DEF_MOD("3dg",			 112,	R8A7745_CLK_ZG),
+	DEF_MOD("2d-dmac",		 115,	R8A7745_CLK_ZS),
+	DEF_MOD("fdp1-0",		 119,	R8A7745_CLK_ZS),
+	DEF_MOD("tmu3",			 121,	R8A7745_CLK_P),
+	DEF_MOD("tmu2",			 122,	R8A7745_CLK_P),
+	DEF_MOD("cmt0",			 124,	R8A7745_CLK_R),
+	DEF_MOD("tmu0",			 125,	R8A7745_CLK_CP),
+	DEF_MOD("vsp1du0",		 128,	R8A7745_CLK_ZS),
+	DEF_MOD("vsp1-sy",		 131,	R8A7745_CLK_ZS),
+	DEF_MOD("scifa2",		 202,	R8A7745_CLK_MP),
+	DEF_MOD("scifa1",		 203,	R8A7745_CLK_MP),
+	DEF_MOD("scifa0",		 204,	R8A7745_CLK_MP),
+	DEF_MOD("msiof2",		 205,	R8A7745_CLK_MP),
+	DEF_MOD("scifb0",		 206,	R8A7745_CLK_MP),
+	DEF_MOD("scifb1",		 207,	R8A7745_CLK_MP),
+	DEF_MOD("msiof1",		 208,	R8A7745_CLK_MP),
+	DEF_MOD("scifb2",		 216,	R8A7745_CLK_MP),
+	DEF_MOD("sys-dmac1",		 218,	R8A7745_CLK_ZS),
+	DEF_MOD("sys-dmac0",		 219,	R8A7745_CLK_ZS),
+	DEF_MOD("tpu0",			 304,	R8A7745_CLK_CP),
+	DEF_MOD("sdhi3",		 311,	R8A7745_CLK_SD3),
+	DEF_MOD("sdhi2",		 312,	R8A7745_CLK_SD2),
+	DEF_MOD("sdhi0",		 314,	R8A7745_CLK_SD0),
+	DEF_MOD("mmcif0",		 315,	R8A7745_CLK_MMC0),
+	DEF_MOD("iic0",			 318,	R8A7745_CLK_HP),
+	DEF_MOD("iic1",			 323,	R8A7745_CLK_HP),
+	DEF_MOD("cmt1",			 329,	R8A7745_CLK_R),
+	DEF_MOD("usbhs-dmac0",		 330,	R8A7745_CLK_HP),
+	DEF_MOD("usbhs-dmac1",		 331,	R8A7745_CLK_HP),
+	DEF_MOD("irqc",			 407,	R8A7745_CLK_CP),
+	DEF_MOD("intc-sys",		 408,	R8A7745_CLK_ZS),
+	DEF_MOD("audio-dmac0",		 502,	R8A7745_CLK_HP),
+	DEF_MOD("pwm",			 523,	R8A7745_CLK_P),
+	DEF_MOD("usb-ehci",		 703,	R8A7745_CLK_MP),
+	DEF_MOD("usbhs",		 704,	R8A7745_CLK_HP),
+	DEF_MOD("hscif2",		 713,	R8A7745_CLK_ZS),
+	DEF_MOD("scif5",		 714,	R8A7745_CLK_P),
+	DEF_MOD("scif4",		 715,	R8A7745_CLK_P),
+	DEF_MOD("hscif1",		 716,	R8A7745_CLK_ZS),
+	DEF_MOD("hscif0",		 717,	R8A7745_CLK_ZS),
+	DEF_MOD("scif3",		 718,	R8A7745_CLK_P),
+	DEF_MOD("scif2",		 719,	R8A7745_CLK_P),
+	DEF_MOD("scif1",		 720,	R8A7745_CLK_P),
+	DEF_MOD("scif0",		 721,	R8A7745_CLK_P),
+	DEF_MOD("du0",			 724,	R8A7745_CLK_ZX),
+	DEF_MOD("ipmmu-sgx",		 800,	R8A7745_CLK_ZX),
+	DEF_MOD("vin1",			 810,	R8A7745_CLK_ZG),
+	DEF_MOD("vin0",			 811,	R8A7745_CLK_ZG),
+	DEF_MOD("etheravb",		 812,	R8A7745_CLK_HP),
+	DEF_MOD("ether",		 813,	R8A7745_CLK_P),
+	DEF_MOD("gpio6",		 905,	R8A7745_CLK_CP),
+	DEF_MOD("gpio5",		 907,	R8A7745_CLK_CP),
+	DEF_MOD("gpio4",		 908,	R8A7745_CLK_CP),
+	DEF_MOD("gpio3",		 909,	R8A7745_CLK_CP),
+	DEF_MOD("gpio2",		 910,	R8A7745_CLK_CP),
+	DEF_MOD("gpio1",		 911,	R8A7745_CLK_CP),
+	DEF_MOD("gpio0",		 912,	R8A7745_CLK_CP),
+	DEF_MOD("can1",			 915,	R8A7745_CLK_P),
+	DEF_MOD("can0",			 916,	R8A7745_CLK_P),
+	DEF_MOD("qspi_mod",		 917,	R8A7745_CLK_QSPI),
+	DEF_MOD("i2c5",			 925,	R8A7745_CLK_HP),
+	DEF_MOD("i2c4",			 927,	R8A7745_CLK_HP),
+	DEF_MOD("i2c3",			 928,	R8A7745_CLK_HP),
+	DEF_MOD("i2c2",			 929,	R8A7745_CLK_HP),
+	DEF_MOD("i2c1",			 930,	R8A7745_CLK_HP),
+	DEF_MOD("i2c0",			 931,	R8A7745_CLK_HP),
+	DEF_MOD("ssi-all",		1005,	R8A7745_CLK_P),
+	DEF_MOD("ssi9",			1006,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi8",			1007,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi7",			1008,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi6",			1009,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi5",			1010,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi4",			1011,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi3",			1012,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi2",			1013,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi1",			1014,	MOD_CLK_ID(1005)),
+	DEF_MOD("ssi0",			1015,	MOD_CLK_ID(1005)),
+	DEF_MOD("scu-all",		1017,	R8A7745_CLK_P),
+	DEF_MOD("scu-dvc1",		1018,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-dvc0",		1019,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu1-mix1",	1020,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-ctu0-mix0",	1021,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src9",		1022,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src8",		1023,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src7",		1024,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src6",		1025,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src5",		1026,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src4",		1027,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src3",		1028,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src2",		1029,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src1",		1030,	MOD_CLK_ID(1017)),
+	DEF_MOD("scu-src0",		1031,	MOD_CLK_ID(1017)),
+	DEF_MOD("scifa3",		1106,	R8A7745_CLK_MP),
+	DEF_MOD("scifa4",		1107,	R8A7745_CLK_MP),
+	DEF_MOD("scifa5",		1108,	R8A7745_CLK_MP),
+};
+
+static const unsigned int r8a7745_crit_mod_clks[] __initconst = {
+	MOD_CLK_ID(408),	/* INTC-SYS (GIC) */
+};
+
+/*
+ * CPG Clock Data
+ */
+
+/*
+ *    MD	EXTAL		PLL0	PLL1	PLL3
+ * 14 13 19	(MHz)		*1	*2
+ *---------------------------------------------------
+ * 0  0  0	15		x200/3	x208/2	x106
+ * 0  0  1	15		x200/3	x208/2	x88
+ * 0  1  0	20		x150/3	x156/2	x80
+ * 0  1  1	20		x150/3	x156/2	x66
+ * 1  0  0	26 / 2		x230/3	x240/2	x122
+ * 1  0  1	26 / 2		x230/3	x240/2	x102
+ * 1  1  0	30 / 2		x200/3	x208/2	x106
+ * 1  1  1	30 / 2		x200/3	x208/2	x88
+ *
+ * *1 :	Table 7.5b indicates VCO output (PLL0 = VCO/3)
+ * *2 :	Table 7.5b indicates VCO output (PLL1 = VCO/2)
+ */
+#define CPG_PLL_CONFIG_INDEX(md)	((((md) & BIT(14)) >> 12) | \
+					 (((md) & BIT(13)) >> 12) | \
+					 (((md) & BIT(19)) >> 19))
+
+static const struct rcar_gen2_cpg_pll_config cpg_pll_configs[8] __initconst = {
+	/* EXTAL div	PLL1 mult	PLL3 mult	PLL0 mult */
+	{ 1,		208,		106,		200	},
+	{ 1,		208,		88,		200	},
+	{ 1,		156,		80,		150	},
+	{ 1,		156,		66,		150	},
+	{ 2,		240,		122,		230	},
+	{ 2,		240,		102,		230	},
+	{ 2,		208,		106,		200	},
+	{ 2,		208,		88,		200	},
+};
+
+static int __init r8a7745_cpg_mssr_init(struct device *dev)
+{
+	const struct rcar_gen2_cpg_pll_config *cpg_pll_config;
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
+
+	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
+
+	return rcar_gen2_cpg_init(cpg_pll_config, 3, cpg_mode);
+}
+
+const struct cpg_mssr_info r8a7745_cpg_mssr_info __initconst = {
+	/* Core Clocks */
+	.core_clks = r8a7745_core_clks,
+	.num_core_clks = ARRAY_SIZE(r8a7745_core_clks),
+	.last_dt_core_clk = LAST_DT_CORE_CLK,
+	.num_total_core_clks = MOD_CLK_BASE,
+
+	/* Module Clocks */
+	.mod_clks = r8a7745_mod_clks,
+	.num_mod_clks = ARRAY_SIZE(r8a7745_mod_clks),
+	.num_hw_mod_clks = 12 * 32,
+
+	/* Critical Module Clocks */
+	.crit_mod_clks = r8a7745_crit_mod_clks,
+	.num_crit_mod_clks = ARRAY_SIZE(r8a7745_crit_mod_clks),
+
+	/* Callbacks */
+	.init = r8a7745_cpg_mssr_init,
+	.cpg_clk_register = rcar_gen2_cpg_clk_register,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7795-cpg-mssr.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 
@@ -97,7 +98,7 @@ static const struct cpg_core_clk r8a7795
 	DEF_FIXED("cp",         R8A7795_CLK_CP,    CLK_EXTAL,      2, 1),
 
 	DEF_DIV6P1("mso",       R8A7795_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
-	DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV2, 0x250),
+	DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV4, 0x250),
 	DEF_DIV6P1("canfd",     R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
 	DEF_DIV6P1("csi0",      R8A7795_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
 
@@ -311,7 +312,12 @@ static const struct rcar_gen3_cpg_pll_co
 static int __init r8a7795_cpg_mssr_init(struct device *dev)
 {
 	const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
-	u32 cpg_mode = rcar_gen3_read_mode_pins();
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
 
 	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
 	if (!cpg_pll_config->extal_div) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/r8a7796-cpg-mssr.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7796-cpg-mssr.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/r8a7796-cpg-mssr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/r8a7796-cpg-mssr.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/soc/renesas/rcar-rst.h>
 
 #include <dt-bindings/clock/r8a7796-cpg-mssr.h>
 
@@ -102,6 +103,8 @@ static const struct cpg_core_clk r8a7796
 	DEF_FIXED("cl",         R8A7796_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
 	DEF_FIXED("cp",         R8A7796_CLK_CP,    CLK_EXTAL,      2, 1),
 
+	DEF_DIV6P1("csi0",      R8A7796_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
+
 	DEF_DIV6_RO("osc",      R8A7796_CLK_OSC,   CLK_EXTAL, CPG_RCKCR,  8),
 	DEF_DIV6_RO("r_int",    CLK_RINT,          CLK_EXTAL, CPG_RCKCR, 32),
 
@@ -109,6 +112,14 @@ static const struct cpg_core_clk r8a7796
 };
 
 static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
+	DEF_MOD("scif5",		 202,	R8A7796_CLK_S3D4),
+	DEF_MOD("scif4",		 203,	R8A7796_CLK_S3D4),
+	DEF_MOD("scif3",		 204,	R8A7796_CLK_S3D4),
+	DEF_MOD("scif1",		 206,	R8A7796_CLK_S3D4),
+	DEF_MOD("scif0",		 207,	R8A7796_CLK_S3D4),
+	DEF_MOD("sys-dmac2",		 217,	R8A7796_CLK_S0D3),
+	DEF_MOD("sys-dmac1",		 218,	R8A7796_CLK_S0D3),
+	DEF_MOD("sys-dmac0",		 219,	R8A7796_CLK_S0D3),
 	DEF_MOD("cmt3",			 300,	R8A7796_CLK_R),
 	DEF_MOD("cmt2",			 301,	R8A7796_CLK_R),
 	DEF_MOD("cmt1",			 302,	R8A7796_CLK_R),
@@ -120,7 +131,47 @@ static const struct mssr_mod_clk r8a7796
 	DEF_MOD("sdif0",		 314,	R8A7796_CLK_SD0),
 	DEF_MOD("rwdt0",		 402,	R8A7796_CLK_R),
 	DEF_MOD("intc-ap",		 408,	R8A7796_CLK_S3D1),
+	DEF_MOD("drif7",		 508,	R8A7796_CLK_S3D2),
+	DEF_MOD("drif6",		 509,	R8A7796_CLK_S3D2),
+	DEF_MOD("drif5",		 510,	R8A7796_CLK_S3D2),
+	DEF_MOD("drif4",		 511,	R8A7796_CLK_S3D2),
+	DEF_MOD("drif3",		 512,	R8A7796_CLK_S3D2),
+	DEF_MOD("drif2",		 513,	R8A7796_CLK_S3D2),
+	DEF_MOD("drif1",		 514,	R8A7796_CLK_S3D2),
+	DEF_MOD("drif0",		 515,	R8A7796_CLK_S3D2),
+	DEF_MOD("hscif4",		 516,	R8A7796_CLK_S3D1),
+	DEF_MOD("hscif3",		 517,	R8A7796_CLK_S3D1),
+	DEF_MOD("hscif2",		 518,	R8A7796_CLK_S3D1),
+	DEF_MOD("hscif1",		 519,	R8A7796_CLK_S3D1),
+	DEF_MOD("hscif0",		 520,	R8A7796_CLK_S3D1),
 	DEF_MOD("thermal",		 522,	R8A7796_CLK_CP),
+	DEF_MOD("fcpvd2",		 601,	R8A7796_CLK_S0D2),
+	DEF_MOD("fcpvd1",		 602,	R8A7796_CLK_S0D2),
+	DEF_MOD("fcpvd0",		 603,	R8A7796_CLK_S0D2),
+	DEF_MOD("fcpvb0",		 607,	R8A7796_CLK_S0D1),
+	DEF_MOD("fcpvi0",		 611,	R8A7796_CLK_S0D1),
+	DEF_MOD("fcpf0",		 615,	R8A7796_CLK_S0D1),
+	DEF_MOD("fcpci0",		 617,	R8A7796_CLK_S0D2),
+	DEF_MOD("fcpcs",		 619,	R8A7796_CLK_S0D2),
+	DEF_MOD("vspd2",		 621,	R8A7796_CLK_S0D2),
+	DEF_MOD("vspd1",		 622,	R8A7796_CLK_S0D2),
+	DEF_MOD("vspd0",		 623,	R8A7796_CLK_S0D2),
+	DEF_MOD("vspb",			 626,	R8A7796_CLK_S0D1),
+	DEF_MOD("vspi0",		 631,	R8A7796_CLK_S0D1),
+	DEF_MOD("csi20",		 714,	R8A7796_CLK_CSI0),
+	DEF_MOD("csi40",		 716,	R8A7796_CLK_CSI0),
+	DEF_MOD("du2",			 722,	R8A7796_CLK_S2D1),
+	DEF_MOD("du1",			 723,	R8A7796_CLK_S2D1),
+	DEF_MOD("du0",			 724,	R8A7796_CLK_S2D1),
+	DEF_MOD("lvds",			 727,	R8A7796_CLK_S2D1),
+	DEF_MOD("vin7",			 804,	R8A7796_CLK_S0D2),
+	DEF_MOD("vin6",			 805,	R8A7796_CLK_S0D2),
+	DEF_MOD("vin5",			 806,	R8A7796_CLK_S0D2),
+	DEF_MOD("vin4",			 807,	R8A7796_CLK_S0D2),
+	DEF_MOD("vin3",			 808,	R8A7796_CLK_S0D2),
+	DEF_MOD("vin2",			 809,	R8A7796_CLK_S0D2),
+	DEF_MOD("vin1",			 810,	R8A7796_CLK_S0D2),
+	DEF_MOD("vin0",			 811,	R8A7796_CLK_S0D2),
 	DEF_MOD("etheravb",		 812,	R8A7796_CLK_S0D6),
 	DEF_MOD("gpio7",		 905,	R8A7796_CLK_S3D4),
 	DEF_MOD("gpio6",		 906,	R8A7796_CLK_S3D4),
@@ -130,6 +181,13 @@ static const struct mssr_mod_clk r8a7796
 	DEF_MOD("gpio2",		 910,	R8A7796_CLK_S3D4),
 	DEF_MOD("gpio1",		 911,	R8A7796_CLK_S3D4),
 	DEF_MOD("gpio0",		 912,	R8A7796_CLK_S3D4),
+	DEF_MOD("i2c6",			 918,	R8A7796_CLK_S0D6),
+	DEF_MOD("i2c5",			 919,	R8A7796_CLK_S0D6),
+	DEF_MOD("i2c4",			 927,	R8A7796_CLK_S0D6),
+	DEF_MOD("i2c3",			 928,	R8A7796_CLK_S0D6),
+	DEF_MOD("i2c2",			 929,	R8A7796_CLK_S3D2),
+	DEF_MOD("i2c1",			 930,	R8A7796_CLK_S3D2),
+	DEF_MOD("i2c0",			 931,	R8A7796_CLK_S3D2),
 };
 
 static const unsigned int r8a7796_crit_mod_clks[] __initconst = {
@@ -190,7 +248,12 @@ static const struct rcar_gen3_cpg_pll_co
 static int __init r8a7796_cpg_mssr_init(struct device *dev)
 {
 	const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
-	u32 cpg_mode = rcar_gen3_read_mode_pins();
+	u32 cpg_mode;
+	int error;
+
+	error = rcar_rst_read_mode_pins(&cpg_mode);
+	if (error)
+		return error;
 
 	cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
 	if (!cpg_pll_config->extal_div) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen2-cpg.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen2-cpg.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen2-cpg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen2-cpg.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,371 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded 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/bug.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "renesas-cpg-mssr.h"
+#include "rcar-gen2-cpg.h"
+
+#define CPG_FRQCRB		0x0004
+#define CPG_FRQCRB_KICK		BIT(31)
+#define CPG_SDCKCR		0x0074
+#define CPG_PLL0CR		0x00d8
+#define CPG_PLL0CR_STC_SHIFT	24
+#define CPG_PLL0CR_STC_MASK	(0x7f << CPG_PLL0CR_STC_SHIFT)
+#define CPG_FRQCRC		0x00e0
+#define CPG_FRQCRC_ZFC_SHIFT	8
+#define CPG_FRQCRC_ZFC_MASK	(0x1f << CPG_FRQCRC_ZFC_SHIFT)
+#define CPG_ADSPCKCR		0x025c
+#define CPG_RCANCKCR		0x0270
+
+static spinlock_t cpg_lock;
+
+/*
+ * Z Clock
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.  clk->rate = parent->rate * mult / 32
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+struct cpg_z_clk {
+	struct clk_hw hw;
+	void __iomem *reg;
+	void __iomem *kick_reg;
+};
+
+#define to_z_clk(_hw)	container_of(_hw, struct cpg_z_clk, hw)
+
+static unsigned long cpg_z_clk_recalc_rate(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct cpg_z_clk *zclk = to_z_clk(hw);
+	unsigned int mult;
+	unsigned int val;
+
+	val = (readl(zclk->reg) & CPG_FRQCRC_ZFC_MASK) >> CPG_FRQCRC_ZFC_SHIFT;
+	mult = 32 - val;
+
+	return div_u64((u64)parent_rate * mult, 32);
+}
+
+static long cpg_z_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *parent_rate)
+{
+	unsigned long prate  = *parent_rate;
+	unsigned int mult;
+
+	if (!prate)
+		prate = 1;
+
+	mult = div_u64((u64)rate * 32, prate);
+	mult = clamp(mult, 1U, 32U);
+
+	return *parent_rate / 32 * mult;
+}
+
+static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long parent_rate)
+{
+	struct cpg_z_clk *zclk = to_z_clk(hw);
+	unsigned int mult;
+	u32 val, kick;
+	unsigned int i;
+
+	mult = div_u64((u64)rate * 32, parent_rate);
+	mult = clamp(mult, 1U, 32U);
+
+	if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
+		return -EBUSY;
+
+	val = readl(zclk->reg);
+	val &= ~CPG_FRQCRC_ZFC_MASK;
+	val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT;
+	writel(val, zclk->reg);
+
+	/*
+	 * Set KICK bit in FRQCRB to update hardware setting and wait for
+	 * clock change completion.
+	 */
+	kick = readl(zclk->kick_reg);
+	kick |= CPG_FRQCRB_KICK;
+	writel(kick, zclk->kick_reg);
+
+	/*
+	 * Note: There is no HW information about the worst case latency.
+	 *
+	 * Using experimental measurements, it seems that no more than
+	 * ~10 iterations are needed, independently of the CPU rate.
+	 * Since this value might be dependent on external xtal rate, pll1
+	 * rate or even the other emulation clocks rate, use 1000 as a
+	 * "super" safe value.
+	 */
+	for (i = 1000; i; i--) {
+		if (!(readl(zclk->kick_reg) & CPG_FRQCRB_KICK))
+			return 0;
+
+		cpu_relax();
+	}
+
+	return -ETIMEDOUT;
+}
+
+static const struct clk_ops cpg_z_clk_ops = {
+	.recalc_rate = cpg_z_clk_recalc_rate,
+	.round_rate = cpg_z_clk_round_rate,
+	.set_rate = cpg_z_clk_set_rate,
+};
+
+static struct clk * __init cpg_z_clk_register(const char *name,
+					      const char *parent_name,
+					      void __iomem *base)
+{
+	struct clk_init_data init;
+	struct cpg_z_clk *zclk;
+	struct clk *clk;
+
+	zclk = kzalloc(sizeof(*zclk), GFP_KERNEL);
+	if (!zclk)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &cpg_z_clk_ops;
+	init.flags = 0;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	zclk->reg = base + CPG_FRQCRC;
+	zclk->kick_reg = base + CPG_FRQCRB;
+	zclk->hw.init = &init;
+
+	clk = clk_register(NULL, &zclk->hw);
+	if (IS_ERR(clk))
+		kfree(zclk);
+
+	return clk;
+}
+
+static struct clk * __init cpg_rcan_clk_register(const char *name,
+						 const char *parent_name,
+						 void __iomem *base)
+{
+	struct clk_fixed_factor *fixed;
+	struct clk_gate *gate;
+	struct clk *clk;
+
+	fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
+	if (!fixed)
+		return ERR_PTR(-ENOMEM);
+
+	fixed->mult = 1;
+	fixed->div = 6;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate) {
+		kfree(fixed);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	gate->reg = base + CPG_RCANCKCR;
+	gate->bit_idx = 8;
+	gate->flags = CLK_GATE_SET_TO_DISABLE;
+	gate->lock = &cpg_lock;
+
+	clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+				     &fixed->hw, &clk_fixed_factor_ops,
+				     &gate->hw, &clk_gate_ops, 0);
+	if (IS_ERR(clk)) {
+		kfree(gate);
+		kfree(fixed);
+	}
+
+	return clk;
+}
+
+/* ADSP divisors */
+static const struct clk_div_table cpg_adsp_div_table[] = {
+	{  1,  3 }, {  2,  4 }, {  3,  6 }, {  4,  8 },
+	{  5, 12 }, {  6, 16 }, {  7, 18 }, {  8, 24 },
+	{ 10, 36 }, { 11, 48 }, {  0,  0 },
+};
+
+static struct clk * __init cpg_adsp_clk_register(const char *name,
+						 const char *parent_name,
+						 void __iomem *base)
+{
+	struct clk_divider *div;
+	struct clk_gate *gate;
+	struct clk *clk;
+
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	div->reg = base + CPG_ADSPCKCR;
+	div->width = 4;
+	div->table = cpg_adsp_div_table;
+	div->lock = &cpg_lock;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate) {
+		kfree(div);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	gate->reg = base + CPG_ADSPCKCR;
+	gate->bit_idx = 8;
+	gate->flags = CLK_GATE_SET_TO_DISABLE;
+	gate->lock = &cpg_lock;
+
+	clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+				     &div->hw, &clk_divider_ops,
+				     &gate->hw, &clk_gate_ops, 0);
+	if (IS_ERR(clk)) {
+		kfree(gate);
+		kfree(div);
+	}
+
+	return clk;
+}
+
+/* SDHI divisors */
+static const struct clk_div_table cpg_sdh_div_table[] = {
+	{  0,  2 }, {  1,  3 }, {  2,  4 }, {  3,  6 },
+	{  4,  8 }, {  5, 12 }, {  6, 16 }, {  7, 18 },
+	{  8, 24 }, { 10, 36 }, { 11, 48 }, {  0,  0 },
+};
+
+static const struct clk_div_table cpg_sd01_div_table[] = {
+	{  4,  8 }, {  5, 12 }, {  6, 16 }, {  7, 18 },
+	{  8, 24 }, { 10, 36 }, { 11, 48 }, { 12, 10 },
+	{  0,  0 },
+};
+
+static const struct rcar_gen2_cpg_pll_config *cpg_pll_config __initdata;
+static unsigned int cpg_pll0_div __initdata;
+static u32 cpg_mode __initdata;
+
+struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
+					       const struct cpg_core_clk *core,
+					       const struct cpg_mssr_info *info,
+					       struct clk **clks,
+					       void __iomem *base)
+{
+	const struct clk_div_table *table = NULL;
+	const struct clk *parent;
+	const char *parent_name;
+	unsigned int mult = 1;
+	unsigned int div = 1;
+	unsigned int shift;
+
+	parent = clks[core->parent];
+	if (IS_ERR(parent))
+		return ERR_CAST(parent);
+
+	parent_name = __clk_get_name(parent);
+
+	switch (core->type) {
+	/* R-Car Gen2 */
+	case CLK_TYPE_GEN2_MAIN:
+		div = cpg_pll_config->extal_div;
+		break;
+
+	case CLK_TYPE_GEN2_PLL0:
+		/*
+		 * PLL0 is a  configurable multiplier clock except on R-Car
+		 * V2H/E2. Register the PLL0 clock as a fixed factor clock for
+		 * now as there's no generic multiplier clock implementation and
+		 * we  currently  have no need to change  the multiplier value.
+		 */
+		mult = cpg_pll_config->pll0_mult;
+		div  = cpg_pll0_div;
+		if (!mult) {
+			u32 pll0cr = readl(base + CPG_PLL0CR);
+
+			mult = (((pll0cr & CPG_PLL0CR_STC_MASK) >>
+				 CPG_PLL0CR_STC_SHIFT) + 1) * 2;
+		}
+		break;
+
+	case CLK_TYPE_GEN2_PLL1:
+		mult = cpg_pll_config->pll1_mult / 2;
+		break;
+
+	case CLK_TYPE_GEN2_PLL3:
+		mult = cpg_pll_config->pll3_mult;
+		break;
+
+	case CLK_TYPE_GEN2_Z:
+		return cpg_z_clk_register(core->name, parent_name, base);
+
+	case CLK_TYPE_GEN2_LB:
+		div = cpg_mode & BIT(18) ? 36 : 24;
+		break;
+
+	case CLK_TYPE_GEN2_ADSP:
+		return cpg_adsp_clk_register(core->name, parent_name, base);
+
+	case CLK_TYPE_GEN2_SDH:
+		table = cpg_sdh_div_table;
+		shift = 8;
+		break;
+
+	case CLK_TYPE_GEN2_SD0:
+		table = cpg_sd01_div_table;
+		shift = 4;
+		break;
+
+	case CLK_TYPE_GEN2_SD1:
+		table = cpg_sd01_div_table;
+		shift = 0;
+		break;
+
+	case CLK_TYPE_GEN2_QSPI:
+		div = (cpg_mode & (BIT(3) | BIT(2) | BIT(1))) == BIT(2) ?
+		      8 : 10;
+		break;
+
+	case CLK_TYPE_GEN2_RCAN:
+		return cpg_rcan_clk_register(core->name, parent_name, base);
+
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!table)
+		return clk_register_fixed_factor(NULL, core->name, parent_name,
+						 0, mult, div);
+	else
+		return clk_register_divider_table(NULL, core->name,
+						  parent_name, 0,
+						  base + CPG_SDCKCR, shift, 4,
+						  0, table, &cpg_lock);
+}
+
+int __init rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+			      unsigned int pll0_div, u32 mode)
+{
+	cpg_pll_config = config;
+	cpg_pll0_div = pll0_div;
+	cpg_mode = mode;
+
+	spin_lock_init(&cpg_lock);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen2-cpg.h linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen2-cpg.h
--- linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen2-cpg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen2-cpg.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * R-Car Gen2 Clock Pulse Generator
+ *
+ * Copyright (C) 2016 Cogent Embedded 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; version 2 of the License.
+ */
+
+#ifndef __CLK_RENESAS_RCAR_GEN2_CPG_H__
+#define __CLK_RENESAS_RCAR_GEN2_CPG_H__
+
+enum rcar_gen2_clk_types {
+	CLK_TYPE_GEN2_MAIN = CLK_TYPE_CUSTOM,
+	CLK_TYPE_GEN2_PLL0,
+	CLK_TYPE_GEN2_PLL1,
+	CLK_TYPE_GEN2_PLL3,
+	CLK_TYPE_GEN2_Z,
+	CLK_TYPE_GEN2_LB,
+	CLK_TYPE_GEN2_ADSP,
+	CLK_TYPE_GEN2_SDH,
+	CLK_TYPE_GEN2_SD0,
+	CLK_TYPE_GEN2_SD1,
+	CLK_TYPE_GEN2_QSPI,
+	CLK_TYPE_GEN2_RCAN,
+};
+
+struct rcar_gen2_cpg_pll_config {
+	unsigned int extal_div;
+	unsigned int pll1_mult;
+	unsigned int pll3_mult;
+	unsigned int pll0_mult;		/* leave as zero if PLL0CR exists */
+};
+
+struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
+				       const struct cpg_core_clk *core,
+				       const struct cpg_mssr_info *info,
+				       struct clk **clks, void __iomem *base);
+int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
+		       unsigned int pll0_div, u32 mode);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen3-cpg.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen3-cpg.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen3-cpg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen3-cpg.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,7 +98,7 @@ static int cpg_sd_clock_enable(struct cl
 	u32 val, sd_fc;
 	unsigned int i;
 
-	val = clk_readl(clock->reg);
+	val = readl(clock->reg);
 
 	sd_fc = val & CPG_SD_FC_MASK;
 	for (i = 0; i < clock->div_num; i++)
@@ -111,7 +111,7 @@ static int cpg_sd_clock_enable(struct cl
 	val &= ~(CPG_SD_STP_MASK);
 	val |= clock->div_table[i].val & CPG_SD_STP_MASK;
 
-	clk_writel(val, clock->reg);
+	writel(val, clock->reg);
 
 	return 0;
 }
@@ -120,14 +120,14 @@ static void cpg_sd_clock_disable(struct
 {
 	struct sd_clock *clock = to_sd_clock(hw);
 
-	clk_writel(clk_readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
+	writel(readl(clock->reg) | CPG_SD_STP_MASK, clock->reg);
 }
 
 static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
 {
 	struct sd_clock *clock = to_sd_clock(hw);
 
-	return !(clk_readl(clock->reg) & CPG_SD_STP_MASK);
+	return !(readl(clock->reg) & CPG_SD_STP_MASK);
 }
 
 static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw,
@@ -138,7 +138,7 @@ static unsigned long cpg_sd_clock_recalc
 	u32 val, sd_fc;
 	unsigned int i;
 
-	val = clk_readl(clock->reg);
+	val = readl(clock->reg);
 
 	sd_fc = val & CPG_SD_FC_MASK;
 	for (i = 0; i < clock->div_num; i++)
@@ -189,10 +189,10 @@ static int cpg_sd_clock_set_rate(struct
 	if (i >= clock->div_num)
 		return -EINVAL;
 
-	val = clk_readl(clock->reg);
+	val = readl(clock->reg);
 	val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
 	val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
-	clk_writel(val, clock->reg);
+	writel(val, clock->reg);
 
 	return 0;
 }
@@ -333,23 +333,6 @@ struct clk * __init rcar_gen3_cpg_clk_re
 					 __clk_get_name(parent), 0, mult, div);
 }
 
-/*
- * Reset register definitions.
- */
-#define MODEMR	0xe6160060
-
-u32 __init rcar_gen3_read_mode_pins(void)
-{
-	void __iomem *modemr = ioremap_nocache(MODEMR, 4);
-	u32 mode;
-
-	BUG_ON(!modemr);
-	mode = ioread32(modemr);
-	iounmap(modemr);
-
-	return mode;
-}
-
 int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
 			      unsigned int clk_extalr)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen3-cpg.h linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen3-cpg.h
--- linux-libre-4.9-gnu/drivers/clk/renesas/rcar-gen3-cpg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/rcar-gen3-cpg.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,6 @@ struct rcar_gen3_cpg_pll_config {
 
 #define CPG_RCKCR	0x240
 
-u32 rcar_gen3_read_mode_pins(void);
 struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
 	const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
 	struct clk **clks, void __iomem *base);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/renesas-cpg-mssr.c linux-libre-4.10-rc8-gnu/drivers/clk/renesas/renesas-cpg-mssr.c
--- linux-libre-4.9-gnu/drivers/clk/renesas/renesas-cpg-mssr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/renesas-cpg-mssr.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,9 +33,9 @@
 #include "clk-div6.h"
 
 #ifdef DEBUG
-#define WARN_DEBUG(x)	do { } while (0)
-#else
 #define WARN_DEBUG(x)	WARN_ON(x)
+#else
+#define WARN_DEBUG(x)	do { } while (0)
 #endif
 
 
@@ -146,12 +146,12 @@ static int cpg_mstp_clock_endisable(stru
 		enable ? "ON" : "OFF");
 	spin_lock_irqsave(&priv->mstp_lock, flags);
 
-	value = clk_readl(priv->base + SMSTPCR(reg));
+	value = readl(priv->base + SMSTPCR(reg));
 	if (enable)
 		value &= ~bitmask;
 	else
 		value |= bitmask;
-	clk_writel(value, priv->base + SMSTPCR(reg));
+	writel(value, priv->base + SMSTPCR(reg));
 
 	spin_unlock_irqrestore(&priv->mstp_lock, flags);
 
@@ -159,8 +159,7 @@ static int cpg_mstp_clock_endisable(stru
 		return 0;
 
 	for (i = 1000; i > 0; --i) {
-		if (!(clk_readl(priv->base + MSTPSR(reg)) &
-		      bitmask))
+		if (!(readl(priv->base + MSTPSR(reg)) & bitmask))
 			break;
 		cpu_relax();
 	}
@@ -190,7 +189,7 @@ static int cpg_mstp_clock_is_enabled(str
 	struct cpg_mssr_priv *priv = clock->priv;
 	u32 value;
 
-	value = clk_readl(priv->base + MSTPSR(clock->index / 32));
+	value = readl(priv->base + MSTPSR(clock->index / 32));
 
 	return !(value & BIT(clock->index % 32));
 }
@@ -309,7 +308,7 @@ static void __init cpg_mssr_register_cor
 	return;
 
 fail:
-	dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,",
+	dev_err(dev, "Failed to register %s clock %s: %ld\n", "core",
 		core->name, PTR_ERR(clk));
 }
 
@@ -377,7 +376,7 @@ static void __init cpg_mssr_register_mod
 	return;
 
 fail:
-	dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,",
+	dev_err(dev, "Failed to register %s clock %s: %ld\n", "module",
 		mod->name, PTR_ERR(clk));
 	kfree(clock);
 }
@@ -503,6 +502,18 @@ static int __init cpg_mssr_add_clk_domai
 }
 
 static const struct of_device_id cpg_mssr_match[] = {
+#ifdef CONFIG_ARCH_R8A7743
+	{
+		.compatible = "renesas,r8a7743-cpg-mssr",
+		.data = &r8a7743_cpg_mssr_info,
+	},
+#endif
+#ifdef CONFIG_ARCH_R8A7745
+	{
+		.compatible = "renesas,r8a7745-cpg-mssr",
+		.data = &r8a7745_cpg_mssr_info,
+	},
+#endif
 #ifdef CONFIG_ARCH_R8A7795
 	{
 		.compatible = "renesas,r8a7795-cpg-mssr",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/renesas/renesas-cpg-mssr.h linux-libre-4.10-rc8-gnu/drivers/clk/renesas/renesas-cpg-mssr.h
--- linux-libre-4.9-gnu/drivers/clk/renesas/renesas-cpg-mssr.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/renesas/renesas-cpg-mssr.h	2017-02-12 16:03:20.000000000 -0500
@@ -130,6 +130,8 @@ struct cpg_mssr_info {
 					struct clk **clks, void __iomem *base);
 };
 
+extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
+extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/rockchip/clk-cpu.c linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-cpu.c
--- linux-libre-4.9-gnu/drivers/clk/rockchip/clk-cpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-cpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -124,9 +124,18 @@ static int rockchip_cpuclk_pre_rate_chan
 					   struct clk_notifier_data *ndata)
 {
 	const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data;
+	const struct rockchip_cpuclk_rate_table *rate;
 	unsigned long alt_prate, alt_div;
 	unsigned long flags;
 
+	/* check validity of the new rate */
+	rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate);
+	if (!rate) {
+		pr_err("%s: Invalid rate : %lu for cpuclk\n",
+		       __func__, ndata->new_rate);
+		return -EINVAL;
+	}
+
 	alt_prate = clk_get_rate(cpuclk->alt_parent);
 
 	spin_lock_irqsave(cpuclk->lock, flags);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/rockchip/clk.h linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk.h
--- linux-libre-4.9-gnu/drivers/clk/rockchip/clk.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,21 @@ struct clk;
 #define HIWORD_UPDATE(val, mask, shift) \
 		((val) << (shift) | (mask) << ((shift) + 16))
 
+/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define RK1108_PLL_CON(x)		((x) * 0x4)
+#define RK1108_CLKSEL_CON(x)		((x) * 0x4 + 0x60)
+#define RK1108_CLKGATE_CON(x)		((x) * 0x4 + 0x120)
+#define RK1108_SOFTRST_CON(x)		((x) * 0x4 + 0x180)
+#define RK1108_GLB_SRST_FST		0x1c0
+#define RK1108_GLB_SRST_SND		0x1c4
+#define RK1108_MISC_CON			0x1cc
+#define RK1108_SDMMC_CON0		0x1d8
+#define RK1108_SDMMC_CON1		0x1dc
+#define RK1108_SDIO_CON0		0x1e0
+#define RK1108_SDIO_CON1		0x1e4
+#define RK1108_EMMC_CON0		0x1e8
+#define RK1108_EMMC_CON1		0x1ec
+
 #define RK2928_PLL_CON(x)		((x) * 0x4)
 #define RK2928_MODE_CON		0x40
 #define RK2928_CLKSEL_CON(x)	((x) * 0x4 + 0x44)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/rockchip/clk-pll.c linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-pll.c
--- linux-libre-4.9-gnu/drivers/clk/rockchip/clk-pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -319,7 +319,8 @@ static void rockchip_rk3036_pll_init(str
 
 	if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
 		rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
-		rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+		rate->dsmpd != cur.dsmpd ||
+		(!cur.dsmpd && (rate->frac != cur.frac))) {
 		struct clk *parent = clk_get_parent(hw->clk);
 
 		if (!parent) {
@@ -795,7 +796,8 @@ static void rockchip_rk3399_pll_init(str
 
 	if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
 		rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
-		rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
+		rate->dsmpd != cur.dsmpd ||
+		(!cur.dsmpd && (rate->frac != cur.frac))) {
 		struct clk *parent = clk_get_parent(hw->clk);
 
 		if (!parent) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/rockchip/clk-rk1108.c linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-rk1108.c
--- linux-libre-4.9-gnu/drivers/clk/rockchip/clk-rk1108.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-rk1108.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2016 Rockchip Electronics Co. Ltd.
+ * Author: Shawn Lin <shawn.lin@rock-chips.com>
+ *         Andy Yan <andy.yan@rock-chips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rk1108-cru.h>
+#include "clk.h"
+
+#define RK1108_GRF_SOC_STATUS0	0x480
+
+enum rk1108_plls {
+	apll, dpll, gpll,
+};
+
+static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
+	/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+	RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
+	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
+	RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
+	RK3036_PLL_RATE(  96000000, 1, 64, 4, 4, 1, 0),
+	{ /* sentinel */ },
+};
+
+#define RK1108_DIV_CORE_MASK		0xf
+#define RK1108_DIV_CORE_SHIFT		4
+
+#define RK1108_CLKSEL0(_core_peri_div)	\
+	{				\
+		.reg = RK1108_CLKSEL_CON(1),	\
+		.val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
+				RK1108_DIV_CORE_SHIFT)	\
+	}
+
+#define RK1108_CPUCLK_RATE(_prate, _core_peri_div)			\
+	{								\
+		.prate = _prate,					\
+		.divs = {						\
+			RK1108_CLKSEL0(_core_peri_div),		\
+		},							\
+	}
+
+static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
+	RK1108_CPUCLK_RATE(816000000, 4),
+	RK1108_CPUCLK_RATE(600000000, 4),
+	RK1108_CPUCLK_RATE(312000000, 4),
+};
+
+static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
+	.core_reg = RK1108_CLKSEL_CON(0),
+	.div_core_shift = 0,
+	.div_core_mask = 0x1f,
+	.mux_core_alt = 1,
+	.mux_core_main = 0,
+	.mux_core_shift = 8,
+	.mux_core_mask = 0x1,
+};
+
+PNAME(mux_pll_p)		= { "xin24m", "xin24m"};
+PNAME(mux_ddrphy_p)		= { "dpll_ddr", "gpll_ddr", "apll_ddr" };
+PNAME(mux_armclk_p)		= { "apll_core", "gpll_core", "dpll_core" };
+PNAME(mux_usb480m_pre_p)	= { "usbphy", "xin24m" };
+PNAME(mux_hdmiphy_phy_p)	= { "hdmiphy", "xin24m" };
+PNAME(mux_dclk_hdmiphy_pre_p)	= { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" };
+PNAME(mux_pll_src_4plls_p)	= { "dpll", "hdmiphy", "gpll", "usb480m" };
+PNAME(mux_pll_src_3plls_p)	= { "apll", "gpll", "dpll" };
+PNAME(mux_pll_src_2plls_p)	= { "dpll", "gpll" };
+PNAME(mux_pll_src_apll_gpll_p)	= { "apll", "gpll" };
+PNAME(mux_aclk_peri_src_p)	= { "aclk_peri_src_dpll", "aclk_peri_src_gpll" };
+PNAME(mux_aclk_bus_src_p)	= { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" };
+PNAME(mux_mmc_src_p)		= { "dpll", "gpll", "xin24m", "usb480m" };
+PNAME(mux_pll_src_dpll_gpll_usb480m_p)	= { "dpll", "gpll", "usb480m" };
+PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
+PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
+PNAME(mux_uart2_p)		= { "uart2_src", "uart2_frac", "xin24m" };
+PNAME(mux_sclk_macphy_p)	= { "sclk_macphy_pre", "ext_gmac" };
+PNAME(mux_i2s0_pre_p)		= { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
+PNAME(mux_i2s_out_p)		= { "i2s0_pre", "xin12m" };
+PNAME(mux_i2s1_p)		= { "i2s1_src", "i2s1_frac", "xin12m" };
+PNAME(mux_i2s2_p)		= { "i2s2_src", "i2s2_frac", "xin12m" };
+
+static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
+	[apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
+		     RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
+	[dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
+		     RK1108_PLL_CON(11), 8, 31, 0, NULL),
+	[gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
+		     RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
+};
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
+
+static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
+	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
+	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
+	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
+	MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
+	MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
+	MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
+	MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
+			RK1108_MISC_CON, 13, 2, MFLAGS),
+	MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
+			RK1108_MISC_CON, 15, 2, MFLAGS),
+	/*
+	 * Clock-Architecture Diagram 2
+	 */
+
+	/* PD_CORE */
+	GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 1, GFLAGS),
+	GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 0, GFLAGS),
+	GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 2, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK1108_CLKGATE_CON(0), 5, GFLAGS),
+	COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+			RK1108_CLKGATE_CON(0), 4, GFLAGS),
+	GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(11), 0, GFLAGS),
+	GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(11), 1, GFLAGS),
+
+	/* PD_RKVENC */
+
+	/* PD_RKVDEC */
+
+	/* PD_PMU_wrapper */
+	COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(8), 12, GFLAGS),
+	GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 0, GFLAGS),
+	GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 1, GFLAGS),
+	GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 2, GFLAGS),
+	GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 3, GFLAGS),
+	GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 4, GFLAGS),
+	GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 5, GFLAGS),
+	GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(10), 6, GFLAGS),
+	COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(8), 15, GFLAGS),
+	COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(8), 14, GFLAGS),
+	GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(8), 13, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 4
+	 */
+	COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(6), 0, GFLAGS),
+	GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(17), 0, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
+			RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(7), 2, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
+			RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
+			RK1108_CLKGATE_CON(7), 3, GFLAGS),
+
+	INVERTER(0, "pclk_vip", "ext_vip",
+			RK1108_CLKSEL_CON(31), 8, IFLAGS),
+	GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(7), 6, GFLAGS),
+	GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(18), 10, GFLAGS),
+	GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(6), 5, GFLAGS),
+	GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(6), 4, GFLAGS),
+	COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
+			RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 5
+	 */
+
+	FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+	COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(2), 0, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(8), 0,
+			RK1108_CLKGATE_CON(2), 1, GFLAGS,
+			&rk1108_i2s0_fracmux),
+	GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
+			RK1108_CLKGATE_CON(2), 2, GFLAGS),
+	COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
+			RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
+			RK1108_CLKGATE_CON(2), 3, GFLAGS),
+
+	COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(2), 4, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
+			RK2928_CLKSEL_CON(9), 0,
+			RK2928_CLKGATE_CON(2), 5, GFLAGS,
+			&rk1108_i2s1_fracmux),
+	GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
+			RK1108_CLKGATE_CON(2), 6, GFLAGS),
+
+	COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 8, GFLAGS),
+	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(10), 0,
+			RK1108_CLKGATE_CON(2), 9, GFLAGS,
+			&rk1108_i2s2_fracmux),
+	GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
+			RK1108_CLKGATE_CON(2), 10, GFLAGS),
+
+	/* PD_BUS */
+	GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 0, GFLAGS),
+	GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 1, GFLAGS),
+	GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 2, GFLAGS),
+	COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
+			RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
+			RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(1), 4, GFLAGS),
+	COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
+			RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
+			RK1108_CLKGATE_CON(1), 5, GFLAGS),
+	GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 6, GFLAGS),
+	GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 7, GFLAGS),
+	GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 8, GFLAGS),
+	GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 9, GFLAGS),
+	GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(1), 10, GFLAGS),
+	GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 4, GFLAGS),
+
+	COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 1, GFLAGS),
+	COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 3, GFLAGS),
+	COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 5, GFLAGS),
+
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(16), 0,
+			RK1108_CLKGATE_CON(3), 2, GFLAGS,
+			&rk1108_uart0_fracmux),
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(17), 0,
+			RK1108_CLKGATE_CON(3), 4, GFLAGS,
+			&rk1108_uart1_fracmux),
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(18), 0,
+			RK1108_CLKGATE_CON(3), 6, GFLAGS,
+			&rk1108_uart2_fracmux),
+	GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 10, GFLAGS),
+	GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 11, GFLAGS),
+	GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 12, GFLAGS),
+
+	COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 7, GFLAGS),
+	COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 8, GFLAGS),
+	COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 9, GFLAGS),
+	GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 0, GFLAGS),
+	GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 1, GFLAGS),
+	GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 2, GFLAGS),
+	COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
+			RK1108_CLKGATE_CON(3), 10, GFLAGS),
+	GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 6, GFLAGS),
+	GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 3, GFLAGS),
+	GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 7, GFLAGS),
+	GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 8, GFLAGS),
+	GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(13), 9, GFLAGS),
+
+	GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(14), 0, GFLAGS),
+
+	GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
+	     RK1108_CLKGATE_CON(12), 2, GFLAGS),
+	GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 3, GFLAGS),
+	GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 1, GFLAGS),
+
+	/* PD_DDR */
+	GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 8, GFLAGS),
+	GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 9, GFLAGS),
+	GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 10, GFLAGS),
+	COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
+			DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
+			RK1108_CLKGATE_CON(10), 9, GFLAGS),
+	GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 4, GFLAGS),
+	GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 5, GFLAGS),
+	GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(12), 6, GFLAGS),
+	GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(0), 11, GFLAGS),
+
+	/*
+	 * Clock-Architecture Diagram 6
+	 */
+
+	/* PD_PERI */
+	COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
+			RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
+			RK1108_CLKGATE_CON(4), 5, GFLAGS),
+	GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(15), 13, GFLAGS),
+	COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
+			RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
+			RK1108_CLKGATE_CON(4), 4, GFLAGS),
+	GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(15), 12, GFLAGS),
+
+	GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(4), 1, GFLAGS),
+	GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
+			RK1108_CLKGATE_CON(4), 2, GFLAGS),
+	COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
+			RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(15), 11, GFLAGS),
+
+	COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+			RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
+			RK1108_CLKGATE_CON(5), 0, GFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
+			RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
+			RK1108_CLKGATE_CON(5), 2, GFLAGS),
+	DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
+			RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
+
+	COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
+			RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
+			RK1108_CLKGATE_CON(5), 1, GFLAGS),
+	DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
+			RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
+	GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
+	GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
+	GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
+
+	COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
+			RK1108_CLKGATE_CON(5), 3, GFLAGS),
+	GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
+
+	COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
+			RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
+			RK1108_CLKGATE_CON(5), 4, GFLAGS),
+	GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
+
+	COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
+			RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
+			RK1108_CLKGATE_CON(4), 10, GFLAGS),
+	MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
+			RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
+	GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
+	GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
+	GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),
+
+	MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
+	MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
+
+	MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK1108_SDIO_CON0,  1),
+	MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK1108_SDIO_CON1,  1),
+
+	MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK1108_EMMC_CON0,  1),
+	MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK1108_EMMC_CON1,  1),
+};
+
+static const char *const rk1108_critical_clocks[] __initconst = {
+	"aclk_core",
+	"aclk_bus_src_gpll",
+	"aclk_periph",
+	"hclk_periph",
+	"pclk_periph",
+};
+
+static void __init rk1108_clk_init(struct device_node *np)
+{
+	struct rockchip_clk_provider *ctx;
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base) {
+		pr_err("%s: could not map cru region\n", __func__);
+		return;
+	}
+
+	ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+	if (IS_ERR(ctx)) {
+		pr_err("%s: rockchip clk init failed\n", __func__);
+		iounmap(reg_base);
+		return;
+	}
+
+	rockchip_clk_register_plls(ctx, rk1108_pll_clks,
+				   ARRAY_SIZE(rk1108_pll_clks),
+				   RK1108_GRF_SOC_STATUS0);
+	rockchip_clk_register_branches(ctx, rk1108_clk_branches,
+				  ARRAY_SIZE(rk1108_clk_branches));
+	rockchip_clk_protect_critical(rk1108_critical_clocks,
+				      ARRAY_SIZE(rk1108_critical_clocks));
+
+	rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
+			mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
+			&rk1108_cpuclk_data, rk1108_cpuclk_rates,
+			ARRAY_SIZE(rk1108_cpuclk_rates));
+
+	rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
+				  ROCKCHIP_SOFTRST_HIWORD_MASK);
+
+	rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
+
+	rockchip_clk_of_add_provider(np, ctx);
+}
+CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/rockchip/clk-rk3188.c linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-rk3188.c
--- linux-libre-4.9-gnu/drivers/clk/rockchip/clk-rk3188.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-rk3188.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,6 +89,7 @@ static struct rockchip_pll_rate_table rk
 	RK3066_PLL_RATE( 504000000, 1, 84, 4),
 	RK3066_PLL_RATE( 456000000, 1, 76, 4),
 	RK3066_PLL_RATE( 408000000, 1, 68, 4),
+	RK3066_PLL_RATE( 400000000, 3, 100, 2),
 	RK3066_PLL_RATE( 384000000, 2, 128, 4),
 	RK3066_PLL_RATE( 360000000, 1, 60, 4),
 	RK3066_PLL_RATE( 312000000, 1, 52, 4),
@@ -306,14 +307,14 @@ static struct rockchip_clk_branch common
 			RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
 			RK2928_CLKGATE_CON(0), 2, GFLAGS),
 
-	GATE(0, "aclk_cpu", "aclk_cpu_pre", 0,
+	GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_pre", 0,
 			RK2928_CLKGATE_CON(0), 3, GFLAGS),
 
 	GATE(0, "atclk_cpu", "pclk_cpu_pre", 0,
 			RK2928_CLKGATE_CON(0), 6, GFLAGS),
-	GATE(0, "pclk_cpu", "pclk_cpu_pre", 0,
+	GATE(PCLK_CPU, "pclk_cpu", "pclk_cpu_pre", 0,
 			RK2928_CLKGATE_CON(0), 5, GFLAGS),
-	GATE(0, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
+	GATE(HCLK_CPU, "hclk_cpu", "hclk_cpu_pre", CLK_IGNORE_UNUSED,
 			RK2928_CLKGATE_CON(0), 4, GFLAGS),
 
 	COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, CLK_IGNORE_UNUSED,
@@ -323,12 +324,12 @@ static struct rockchip_clk_branch common
 			RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS,
 			RK2928_CLKGATE_CON(1), 4, GFLAGS),
 
-	GATE(0, "aclk_peri", "aclk_peri_pre", 0,
+	GATE(ACLK_PERI, "aclk_peri", "aclk_peri_pre", 0,
 			RK2928_CLKGATE_CON(2), 1, GFLAGS),
-	COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0,
+	COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_pre", 0,
 			RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
 			RK2928_CLKGATE_CON(2), 2, GFLAGS),
-	COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0,
+	COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_pre", 0,
 			RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
 			RK2928_CLKGATE_CON(2), 3, GFLAGS),
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/rockchip/clk-rk3399.c linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-rk3399.c
--- linux-libre-4.9-gnu/drivers/clk/rockchip/clk-rk3399.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/clk-rk3399.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,7 +77,7 @@ static struct rockchip_pll_rate_table rk
 	RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
 	RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
 	RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
-	RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+	RK3036_PLL_RATE(1000000000, 1, 125, 3, 1, 1, 0),
 	RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
@@ -87,12 +87,13 @@ static struct rockchip_pll_rate_table rk
 	RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
-	RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
+	RK3036_PLL_RATE( 800000000, 1, 100, 3, 1, 1, 0),
 	RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 676000000, 3, 169, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
 	RK3036_PLL_RATE( 594000000, 1, 99, 4, 1, 1, 0),
+	RK3036_PLL_RATE( 533250000, 8, 711, 4, 1, 1, 0),
 	RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
 	RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
 	RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
@@ -410,11 +411,11 @@ static struct rockchip_clk_branch rk3399
 	GATE(SCLK_USB2PHY1_REF, "clk_usb2phy1_ref", "xin24m", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(6), 6, GFLAGS),
 
-	GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", CLK_IGNORE_UNUSED,
+	GATE(0, "clk_usbphy0_480m_src", "clk_usbphy0_480m", 0,
 			RK3399_CLKGATE_CON(13), 12, GFLAGS),
-	GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", CLK_IGNORE_UNUSED,
+	GATE(0, "clk_usbphy1_480m_src", "clk_usbphy1_480m", 0,
 			RK3399_CLKGATE_CON(13), 12, GFLAGS),
-	MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, CLK_IGNORE_UNUSED,
+	MUX(0, "clk_usbphy_480m", mux_usbphy_480m_p, 0,
 			RK3399_CLKSEL_CON(14), 6, 1, MFLAGS),
 
 	MUX(0, "upll", mux_pll_src_24m_usbphy480m_p, 0,
@@ -498,7 +499,7 @@ static struct rockchip_clk_branch rk3399
 			RK3399_CLKGATE_CON(14), 10, GFLAGS),
 	GATE(ACLK_GIC_ADB400_CORE_L_2_GIC, "aclk_core_adb400_core_l_2_gic", "armclkl", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(14), 11, GFLAGS),
-	GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_PVTM_CORE_L, "clk_pvtm_core_l", "xin24m", 0,
 			RK3399_CLKGATE_CON(0), 7, GFLAGS),
 
 	/* big core */
@@ -539,7 +540,7 @@ static struct rockchip_clk_branch rk3399
 	GATE(0, "pclk_dbg_cxcs_pd_core_b", "pclk_dbg_core_b", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(14), 2, GFLAGS),
 
-	GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_PVTM_CORE_B, "clk_pvtm_core_b", "xin24m", 0,
 			RK3399_CLKGATE_CON(1), 7, GFLAGS),
 
 	/* gmac */
@@ -675,18 +676,18 @@ static struct rockchip_clk_branch rk3399
 
 	GATE(PCLK_CENTER_MAIN_NOC, "pclk_center_main_noc", "pclk_ddr", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(18), 10, GFLAGS),
-	GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", CLK_IGNORE_UNUSED,
+	GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_ddr", 0,
 			RK3399_CLKGATE_CON(18), 12, GFLAGS),
 	GATE(PCLK_CIC, "pclk_cic", "pclk_ddr", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(18), 15, GFLAGS),
 	GATE(PCLK_DDR_SGRF, "pclk_ddr_sgrf", "pclk_ddr", CLK_IGNORE_UNUSED,
 			RK3399_CLKGATE_CON(19), 2, GFLAGS),
 
-	GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_PVTM_DDR, "clk_pvtm_ddr", "xin24m", 0,
 			RK3399_CLKGATE_CON(4), 11, GFLAGS),
-	GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_DFIMON0_TIMER, "clk_dfimon0_timer", "xin24m", 0,
 			RK3399_CLKGATE_CON(3), 5, GFLAGS),
-	GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", CLK_IGNORE_UNUSED,
+	GATE(SCLK_DFIMON1_TIMER, "clk_dfimon1_timer", "xin24m", 0,
 			RK3399_CLKGATE_CON(3), 6, GFLAGS),
 
 	/* cci */
@@ -966,7 +967,7 @@ static struct rockchip_clk_branch rk3399
 	GATE(SCLK_INTMEM3, "clk_intmem3", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 5, GFLAGS),
 	GATE(SCLK_INTMEM4, "clk_intmem4", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 6, GFLAGS),
 	GATE(SCLK_INTMEM5, "clk_intmem5", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 7, GFLAGS),
-	GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 8, GFLAGS),
+	GATE(ACLK_DCF, "aclk_dcf", "aclk_perilp0", 0, RK3399_CLKGATE_CON(23), 8, GFLAGS),
 	GATE(ACLK_DMAC0_PERILP, "aclk_dmac0_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 5, GFLAGS),
 	GATE(ACLK_DMAC1_PERILP, "aclk_dmac1_perilp", "aclk_perilp0", 0, RK3399_CLKGATE_CON(25), 6, GFLAGS),
 	GATE(ACLK_PERILP0_NOC, "aclk_perilp0_noc", "aclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 7, GFLAGS),
@@ -980,7 +981,7 @@ static struct rockchip_clk_branch rk3399
 	GATE(HCLK_PERILP0_NOC, "hclk_perilp0_noc", "hclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(25), 8, GFLAGS),
 
 	/* pclk_perilp0 gates */
-	GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", CLK_IGNORE_UNUSED, RK3399_CLKGATE_CON(23), 9, GFLAGS),
+	GATE(PCLK_DCF, "pclk_dcf", "pclk_perilp0", 0, RK3399_CLKGATE_CON(23), 9, GFLAGS),
 
 	/* crypto */
 	COMPOSITE(SCLK_CRYPTO0, "clk_crypto0", mux_pll_src_cpll_gpll_ppll_p, 0,
@@ -1382,8 +1383,8 @@ static struct rockchip_clk_branch rk3399
 	/* clk_test */
 	/* clk_test_pre is controlled by CRU_MISC_CON[3] */
 	COMPOSITE_NOMUX(0, "clk_test", "clk_test_pre", CLK_IGNORE_UNUSED,
-			RK3368_CLKSEL_CON(58), 0, 5, DFLAGS,
-			RK3368_CLKGATE_CON(13), 11, GFLAGS),
+			RK3399_CLKSEL_CON(58), 0, 5, DFLAGS,
+			RK3399_CLKGATE_CON(13), 11, GFLAGS),
 
 	/* ddrc */
 	GATE(0, "clk_ddrc_lpll_src", "lpll", 0, RK3399_CLKGATE_CON(3),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/rockchip/Makefile linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/Makefile
--- linux-libre-4.9-gnu/drivers/clk/rockchip/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/rockchip/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@ obj-y	+= clk-mmc-phase.o
 obj-y	+= clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER)	+= softrst.o
 
+obj-y	+= clk-rk1108.o
 obj-y	+= clk-rk3036.o
 obj-y	+= clk-rk3188.o
 obj-y	+= clk-rk3228.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/samsung/clk-exynos5420.c linux-libre-4.10-rc8-gnu/drivers/clk/samsung/clk-exynos5420.c
--- linux-libre-4.9-gnu/drivers/clk/samsung/clk-exynos5420.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/samsung/clk-exynos5420.c	2017-02-12 16:03:20.000000000 -0500
@@ -586,7 +586,7 @@ static const struct samsung_gate_clock e
 	GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
 				GATE_BUS_TOP, 24, 0, 0),
 	GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
-				GATE_BUS_TOP, 27, 0, 0),
+				GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
 };
 
 static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = {
@@ -956,20 +956,20 @@ static const struct samsung_gate_clock e
 	GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk333_g2d", GATE_IP_G2D, 7, 0, 0),
 
 	GATE(0, "aclk200_fsys", "mout_user_aclk200_fsys",
-			GATE_BUS_FSYS0, 9, CLK_IGNORE_UNUSED, 0),
+			GATE_BUS_FSYS0, 9, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk200_fsys2", "mout_user_aclk200_fsys2",
 			GATE_BUS_FSYS0, 10, CLK_IGNORE_UNUSED, 0),
 
 	GATE(0, "aclk333_g2d", "mout_user_aclk333_g2d",
 			GATE_BUS_TOP, 0, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk266_g2d", "mout_user_aclk266_g2d",
-			GATE_BUS_TOP, 1, CLK_IGNORE_UNUSED, 0),
+			GATE_BUS_TOP, 1, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg",
 			GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk333_432_isp0", "mout_user_aclk333_432_isp0",
 			GATE_BUS_TOP, 5, 0, 0),
 	GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl",
-			GATE_BUS_TOP, 6, CLK_IGNORE_UNUSED, 0),
+			GATE_BUS_TOP, 6, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl",
 			GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk333_432_isp", "mout_user_aclk333_432_isp",
@@ -983,20 +983,20 @@ static const struct samsung_gate_clock e
 	GATE(0, "aclk166", "mout_user_aclk166",
 			GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK333, "aclk333", "mout_user_aclk333",
-			GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0),
+			GATE_BUS_TOP, 15, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
 			GATE_BUS_TOP, 16, 0, 0),
 	GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl",
 			GATE_BUS_TOP, 17, 0, 0),
 	GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1",
-			GATE_BUS_TOP, 18, 0, 0),
+			GATE_BUS_TOP, 18, CLK_IS_CRITICAL, 0),
 	GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24",
 			GATE_BUS_TOP, 28, 0, 0),
 	GATE(CLK_SCLK_HSIC_12M, "sclk_hsic_12m", "ff_hsic_12m",
 			GATE_BUS_TOP, 29, 0, 0),
 
 	GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1",
-			SRC_MASK_TOP2, 24, 0, 0),
+			SRC_MASK_TOP2, 24, CLK_IS_CRITICAL, 0),
 
 	GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk",
 			SRC_MASK_TOP7, 20, 0, 0),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/samsung/clk-exynos5433.c linux-libre-4.10-rc8-gnu/drivers/clk/samsung/clk-exynos5433.c
--- linux-libre-4.9-gnu/drivers/clk/samsung/clk-exynos5433.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/samsung/clk-exynos5433.c	2017-02-12 16:03:20.000000000 -0500
@@ -543,7 +543,7 @@ static const struct samsung_div_clock to
 static const struct samsung_gate_clock top_gate_clks[] __initconst = {
 	/* ENABLE_ACLK_TOP */
 	GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400",
-			ENABLE_ACLK_TOP, 30, 0, 0),
+			ENABLE_ACLK_TOP, 30, CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_IMEM_SSX_266, "aclk_imem_ssx_266",
 			"div_aclk_imem_sssx_266", ENABLE_ACLK_TOP,
 			29, CLK_IGNORE_UNUSED, 0),
@@ -555,25 +555,25 @@ static const struct samsung_gate_clock t
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
 			ENABLE_ACLK_TOP, 24,
-			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+			CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_200",
 			ENABLE_ACLK_TOP, 23,
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_ACLK_PERIC_66, "aclk_peric_66", "div_aclk_peric_66_b",
 			ENABLE_ACLK_TOP, 22,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_PERIS_66, "aclk_peris_66", "div_aclk_peris_66_b",
 			ENABLE_ACLK_TOP, 21,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_MSCL_400, "aclk_mscl_400", "div_aclk_mscl_400",
 			ENABLE_ACLK_TOP, 19,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_FSYS_200, "aclk_fsys_200", "div_aclk_fsys_200",
 			ENABLE_ACLK_TOP, 18,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_GSCL_111, "aclk_gscl_111", "div_aclk_gscl_111",
 			ENABLE_ACLK_TOP, 15,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_GSCL_333, "aclk_gscl_333", "div_aclk_gscl_333",
 			ENABLE_ACLK_TOP, 14,
 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -582,7 +582,7 @@ static const struct samsung_gate_clock t
 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_CAM1_400, "aclk_cam1_400", "div_aclk_cam1_400",
 			ENABLE_ACLK_TOP, 12,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_CAM1_552, "aclk_cam1_552", "div_aclk_cam1_552",
 			ENABLE_ACLK_TOP, 11,
 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -591,7 +591,7 @@ static const struct samsung_gate_clock t
 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_CAM0_400, "aclk_cam0_400", "div_aclk_cam0_400",
 			ENABLE_ACLK_TOP, 9,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_CAM0_552, "aclk_cam0_552", "div_aclk_cam0_552",
 			ENABLE_ACLK_TOP, 8,
 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
@@ -600,19 +600,19 @@ static const struct samsung_gate_clock t
 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_ISP_400, "aclk_isp_400", "div_aclk_isp_400",
 			ENABLE_ACLK_TOP, 6,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_HEVC_400, "aclk_hevc_400", "div_aclk_hevc_400",
 			ENABLE_ACLK_TOP, 5,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_MFC_400, "aclk_mfc_400", "div_aclk_mfc_400",
 			ENABLE_ACLK_TOP, 3,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK_G2D_266, "aclk_g2d_266", "div_aclk_g2d_266",
 			ENABLE_ACLK_TOP, 2,
 			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK_G2D_400, "aclk_g2d_400", "div_aclk_g2d_400",
 			ENABLE_ACLK_TOP, 0,
-			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
+			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 0),
 
 	/* ENABLE_SCLK_TOP_MSCL */
 	GATE(CLK_SCLK_JPEG_MSCL, "sclk_jpeg_mscl", "div_sclk_jpeg",
@@ -1385,7 +1385,7 @@ static const struct samsung_gate_clock m
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_ACLK_DISP_333, "aclk_disp_333", "div_aclk_disp_333",
 			ENABLE_ACLK_MIF3, 1,
-			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
+			CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_ACLK_CPIF_200, "aclk_cpif_200", "div_aclk_cpif_200",
 			ENABLE_ACLK_MIF3, 0,
 			CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
@@ -1929,7 +1929,7 @@ CLK_OF_DECLARE(exynos5433_cmu_peris, "sa
 
 /* list of all parent clock list */
 PNAME(mout_sclk_ufs_mphy_user_p)	= { "oscclk", "sclk_ufs_mphy", };
-PNAME(mout_aclk_fsys_200_user_p)	= { "oscclk", "div_aclk_fsys_200", };
+PNAME(mout_aclk_fsys_200_user_p)	= { "oscclk", "aclk_fsys_200", };
 PNAME(mout_sclk_pcie_100_user_p)	= { "oscclk", "sclk_pcie_100_fsys",};
 PNAME(mout_sclk_ufsunipro_user_p)	= { "oscclk", "sclk_ufsunipro_fsys",};
 PNAME(mout_sclk_mmc2_user_p)		= { "oscclk", "sclk_mmc2_fsys", };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/st/clk-flexgen.c linux-libre-4.10-rc8-gnu/drivers/clk/st/clk-flexgen.c
--- linux-libre-4.9-gnu/drivers/clk/st/clk-flexgen.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/st/clk-flexgen.c	2017-02-12 16:03:20.000000000 -0500
@@ -329,8 +329,10 @@ static void __init st_of_flexgen_setup(s
 		return;
 
 	parents = flexgen_get_parents(np, &num_parents);
-	if (!parents)
+	if (!parents) {
+		iounmap(reg);
 		return;
+	}
 
 	match = of_match_node(flexgen_of_match, np);
 	if (match) {
@@ -394,6 +396,7 @@ static void __init st_of_flexgen_setup(s
 	return;
 
 err:
+	iounmap(reg);
 	if (clk_data)
 		kfree(clk_data->clks);
 	kfree(clk_data);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi/clk-mod0.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi/clk-mod0.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi/clk-mod0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi/clk-mod0.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include "clk-factors.h"
 
 /**
- * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
+ * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
  * MOD0 rate is calculated as follows
  * rate = (parent_rate >> p) / (m + 1);
  */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_div.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_div.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_div.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_div.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include "ccu_mux.h"
 
 /**
- * struct _ccu_div - Internal divider description
+ * struct ccu_div_internal - Internal divider description
  * @shift: Bit offset of the divider in its register
  * @width: Width of the divider field in its register
  * @max: Maximum value allowed for that divider. This is the
@@ -36,7 +36,7 @@
  * It is basically a wrapper around the clk_divider functions
  * arguments.
  */
-struct _ccu_div {
+struct ccu_div_internal {
 	u8			shift;
 	u8			width;
 
@@ -78,7 +78,7 @@ struct _ccu_div {
 struct ccu_div {
 	u32			enable;
 
-	struct _ccu_div		div;
+	struct ccu_div_internal		div;
 	struct ccu_mux_internal	mux;
 	struct ccu_common	common;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_frac.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_frac.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_frac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_frac.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include "ccu_frac.h"
 
 bool ccu_frac_helper_is_enabled(struct ccu_common *common,
-				struct _ccu_frac *cf)
+				struct ccu_frac_internal *cf)
 {
 	if (!(common->features & CCU_FEATURE_FRACTIONAL))
 		return false;
@@ -23,7 +23,7 @@ bool ccu_frac_helper_is_enabled(struct c
 }
 
 void ccu_frac_helper_enable(struct ccu_common *common,
-			    struct _ccu_frac *cf)
+			    struct ccu_frac_internal *cf)
 {
 	unsigned long flags;
 	u32 reg;
@@ -38,7 +38,7 @@ void ccu_frac_helper_enable(struct ccu_c
 }
 
 void ccu_frac_helper_disable(struct ccu_common *common,
-			     struct _ccu_frac *cf)
+			     struct ccu_frac_internal *cf)
 {
 	unsigned long flags;
 	u32 reg;
@@ -53,7 +53,7 @@ void ccu_frac_helper_disable(struct ccu_
 }
 
 bool ccu_frac_helper_has_rate(struct ccu_common *common,
-			      struct _ccu_frac *cf,
+			      struct ccu_frac_internal *cf,
 			      unsigned long rate)
 {
 	if (!(common->features & CCU_FEATURE_FRACTIONAL))
@@ -63,7 +63,7 @@ bool ccu_frac_helper_has_rate(struct ccu
 }
 
 unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
-					struct _ccu_frac *cf)
+					struct ccu_frac_internal *cf)
 {
 	u32 reg;
 
@@ -84,7 +84,7 @@ unsigned long ccu_frac_helper_read_rate(
 }
 
 int ccu_frac_helper_set_rate(struct ccu_common *common,
-			     struct _ccu_frac *cf,
+			     struct ccu_frac_internal *cf,
 			     unsigned long rate)
 {
 	unsigned long flags;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_frac.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_frac.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_frac.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_frac.h	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 
 #include "ccu_common.h"
 
-struct _ccu_frac {
+struct ccu_frac_internal {
 	u32		enable;
 	u32		select;
 
@@ -33,21 +33,21 @@ struct _ccu_frac {
 	}
 
 bool ccu_frac_helper_is_enabled(struct ccu_common *common,
-				struct _ccu_frac *cf);
+				struct ccu_frac_internal *cf);
 void ccu_frac_helper_enable(struct ccu_common *common,
-			    struct _ccu_frac *cf);
+			    struct ccu_frac_internal *cf);
 void ccu_frac_helper_disable(struct ccu_common *common,
-			     struct _ccu_frac *cf);
+			     struct ccu_frac_internal *cf);
 
 bool ccu_frac_helper_has_rate(struct ccu_common *common,
-			      struct _ccu_frac *cf,
+			      struct ccu_frac_internal *cf,
 			      unsigned long rate);
 
 unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
-					struct _ccu_frac *cf);
+					struct ccu_frac_internal *cf);
 
 int ccu_frac_helper_set_rate(struct ccu_common *common,
-			     struct _ccu_frac *cf,
+			     struct ccu_frac_internal *cf,
 			     unsigned long rate);
 
 #endif /* _CCU_FRAC_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_mp.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_mp.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_mp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_mp.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,8 +29,8 @@
 struct ccu_mp {
 	u32			enable;
 
-	struct _ccu_div		m;
-	struct _ccu_div		p;
+	struct ccu_div_internal		m;
+	struct ccu_div_internal		p;
 	struct ccu_mux_internal	mux;
 	struct ccu_common	common;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_mult.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_mult.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_mult.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_mult.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,10 +13,23 @@
 #include "ccu_gate.h"
 #include "ccu_mult.h"
 
+struct _ccu_mult {
+	unsigned long	mult, min, max;
+};
+
 static void ccu_mult_find_best(unsigned long parent, unsigned long rate,
-			       unsigned int max_n, unsigned int *n)
+			       struct _ccu_mult *mult)
 {
-	*n = rate / parent;
+	int _mult;
+
+	_mult = rate / parent;
+	if (_mult < mult->min)
+		_mult = mult->min;
+
+	if (_mult > mult->max)
+		_mult = mult->max;
+
+	mult->mult = _mult;
 }
 
 static unsigned long ccu_mult_round_rate(struct ccu_mux_internal *mux,
@@ -25,11 +38,13 @@ static unsigned long ccu_mult_round_rate
 					void *data)
 {
 	struct ccu_mult *cm = data;
-	unsigned int n;
+	struct _ccu_mult _cm;
 
-	ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n);
+	_cm.min = 1;
+	_cm.max = 1 << cm->mult.width;
+	ccu_mult_find_best(parent_rate, rate, &_cm);
 
-	return parent_rate * n;
+	return parent_rate * _cm.mult;
 }
 
 static void ccu_mult_disable(struct clk_hw *hw)
@@ -83,21 +98,23 @@ static int ccu_mult_set_rate(struct clk_
 			   unsigned long parent_rate)
 {
 	struct ccu_mult *cm = hw_to_ccu_mult(hw);
+	struct _ccu_mult _cm;
 	unsigned long flags;
-	unsigned int n;
 	u32 reg;
 
 	ccu_mux_helper_adjust_parent_for_prediv(&cm->common, &cm->mux, -1,
 						&parent_rate);
 
-	ccu_mult_find_best(parent_rate, rate, 1 << cm->mult.width, &n);
+	_cm.min = cm->mult.min;
+	_cm.max = 1 << cm->mult.width;
+	ccu_mult_find_best(parent_rate, rate, &_cm);
 
 	spin_lock_irqsave(cm->common.lock, flags);
 
 	reg = readl(cm->common.base + cm->common.reg);
 	reg &= ~GENMASK(cm->mult.width + cm->mult.shift - 1, cm->mult.shift);
 
-	writel(reg | ((n - 1) << cm->mult.shift),
+	writel(reg | ((_cm.mult - 1) << cm->mult.shift),
 	       cm->common.base + cm->common.reg);
 
 	spin_unlock_irqrestore(cm->common.lock, flags);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_mult.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_mult.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_mult.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_mult.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,21 +4,26 @@
 #include "ccu_common.h"
 #include "ccu_mux.h"
 
-struct _ccu_mult {
+struct ccu_mult_internal {
 	u8	shift;
 	u8	width;
+	u8	min;
 };
 
-#define _SUNXI_CCU_MULT(_shift, _width)		\
-	{					\
-		.shift	= _shift,		\
-		.width	= _width,		\
+#define _SUNXI_CCU_MULT_MIN(_shift, _width, _min)	\
+	{						\
+		.shift	= _shift,			\
+		.width	= _width,			\
+		.min	= _min,				\
 	}
 
+#define _SUNXI_CCU_MULT(_shift, _width)		\
+	_SUNXI_CCU_MULT_MIN(_shift, _width, 1)
+
 struct ccu_mult {
 	u32			enable;
 
-	struct _ccu_mult	mult;
+	struct ccu_mult_internal	mult;
 	struct ccu_mux_internal	mux;
 	struct ccu_common	common;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nk.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nk.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nk.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,21 +9,24 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/rational.h>
 
 #include "ccu_gate.h"
 #include "ccu_nk.h"
 
+struct _ccu_nk {
+	unsigned long	n, min_n, max_n;
+	unsigned long	k, min_k, max_k;
+};
+
 static void ccu_nk_find_best(unsigned long parent, unsigned long rate,
-			     unsigned int max_n, unsigned int max_k,
-			     unsigned int *n, unsigned int *k)
+			     struct _ccu_nk *nk)
 {
 	unsigned long best_rate = 0;
 	unsigned int best_k = 0, best_n = 0;
 	unsigned int _k, _n;
 
-	for (_k = 1; _k <= max_k; _k++) {
-		for (_n = 1; _n <= max_n; _n++) {
+	for (_k = nk->min_k; _k <= nk->max_k; _k++) {
+		for (_n = nk->min_n; _n <= nk->max_n; _n++) {
 			unsigned long tmp_rate = parent * _n * _k;
 
 			if (tmp_rate > rate)
@@ -37,8 +40,8 @@ static void ccu_nk_find_best(unsigned lo
 		}
 	}
 
-	*k = best_k;
-	*n = best_n;
+	nk->k = best_k;
+	nk->n = best_n;
 }
 
 static void ccu_nk_disable(struct clk_hw *hw)
@@ -89,16 +92,19 @@ static long ccu_nk_round_rate(struct clk
 			      unsigned long *parent_rate)
 {
 	struct ccu_nk *nk = hw_to_ccu_nk(hw);
-	unsigned int n, k;
+	struct _ccu_nk _nk;
 
 	if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate *= nk->fixed_post_div;
 
-	ccu_nk_find_best(*parent_rate, rate,
-			 1 << nk->n.width, 1 << nk->k.width,
-			 &n, &k);
+	_nk.min_n = nk->n.min;
+	_nk.max_n = 1 << nk->n.width;
+	_nk.min_k = nk->k.min;
+	_nk.max_k = 1 << nk->k.width;
+
+	ccu_nk_find_best(*parent_rate, rate, &_nk);
+	rate = *parent_rate * _nk.n * _nk.k;
 
-	rate = *parent_rate * n * k;
 	if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate = rate / nk->fixed_post_div;
 
@@ -110,15 +116,18 @@ static int ccu_nk_set_rate(struct clk_hw
 {
 	struct ccu_nk *nk = hw_to_ccu_nk(hw);
 	unsigned long flags;
-	unsigned int n, k;
+	struct _ccu_nk _nk;
 	u32 reg;
 
 	if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate = rate * nk->fixed_post_div;
 
-	ccu_nk_find_best(parent_rate, rate,
-			 1 << nk->n.width, 1 << nk->k.width,
-			 &n, &k);
+	_nk.min_n = nk->n.min;
+	_nk.max_n = 1 << nk->n.width;
+	_nk.min_k = nk->k.min;
+	_nk.max_k = 1 << nk->k.width;
+
+	ccu_nk_find_best(parent_rate, rate, &_nk);
 
 	spin_lock_irqsave(nk->common.lock, flags);
 
@@ -126,7 +135,7 @@ static int ccu_nk_set_rate(struct clk_hw
 	reg &= ~GENMASK(nk->n.width + nk->n.shift - 1, nk->n.shift);
 	reg &= ~GENMASK(nk->k.width + nk->k.shift - 1, nk->k.shift);
 
-	writel(reg | ((k - 1) << nk->k.shift) | ((n - 1) << nk->n.shift),
+	writel(reg | ((_nk.k - 1) << nk->k.shift) | ((_nk.n - 1) << nk->n.shift),
 	       nk->common.base + nk->common.reg);
 
 	spin_unlock_irqrestore(nk->common.lock, flags);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nk.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nk.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nk.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nk.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,8 +30,8 @@ struct ccu_nk {
 	u32			enable;
 	u32			lock;
 
-	struct _ccu_mult	n;
-	struct _ccu_mult	k;
+	struct ccu_mult_internal	n;
+	struct ccu_mult_internal	k;
 
 	unsigned int		fixed_post_div;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkm.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkm.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkm.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,15 +9,14 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/rational.h>
 
 #include "ccu_gate.h"
 #include "ccu_nkm.h"
 
 struct _ccu_nkm {
-	unsigned long	n, max_n;
-	unsigned long	k, max_k;
-	unsigned long	m, max_m;
+	unsigned long	n, min_n, max_n;
+	unsigned long	k, min_k, max_k;
+	unsigned long	m, min_m, max_m;
 };
 
 static void ccu_nkm_find_best(unsigned long parent, unsigned long rate,
@@ -27,22 +26,22 @@ static void ccu_nkm_find_best(unsigned l
 	unsigned long best_n = 0, best_k = 0, best_m = 0;
 	unsigned long _n, _k, _m;
 
-	for (_k = 1; _k <= nkm->max_k; _k++) {
-		unsigned long tmp_rate;
-
-		rational_best_approximation(rate / _k, parent,
-					    nkm->max_n, nkm->max_m, &_n, &_m);
-
-		tmp_rate = parent * _n * _k / _m;
+	for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
+		for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
+			for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+				unsigned long tmp_rate;
 
-		if (tmp_rate > rate)
-			continue;
+				tmp_rate = parent * _n * _k / _m;
 
-		if ((rate - tmp_rate) < (rate - best_rate)) {
-			best_rate = tmp_rate;
-			best_n = _n;
-			best_k = _k;
-			best_m = _m;
+				if (tmp_rate > rate)
+					continue;
+				if ((rate - tmp_rate) < (rate - best_rate)) {
+					best_rate = tmp_rate;
+					best_n = _n;
+					best_k = _k;
+					best_m = _m;
+				}
+			}
 		}
 	}
 
@@ -101,8 +100,11 @@ static unsigned long ccu_nkm_round_rate(
 	struct ccu_nkm *nkm = data;
 	struct _ccu_nkm _nkm;
 
+	_nkm.min_n = nkm->n.min;
 	_nkm.max_n = 1 << nkm->n.width;
+	_nkm.min_k = nkm->k.min;
 	_nkm.max_k = 1 << nkm->k.width;
+	_nkm.min_m = 1;
 	_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
 
 	ccu_nkm_find_best(parent_rate, rate, &_nkm);
@@ -127,8 +129,11 @@ static int ccu_nkm_set_rate(struct clk_h
 	unsigned long flags;
 	u32 reg;
 
+	_nkm.min_n = nkm->n.min;
 	_nkm.max_n = 1 << nkm->n.width;
+	_nkm.min_k = nkm->k.min;
 	_nkm.max_k = 1 << nkm->k.width;
+	_nkm.min_m = 1;
 	_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
 
 	ccu_nkm_find_best(parent_rate, rate, &_nkm);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkm.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkm.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkm.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,9 +29,9 @@ struct ccu_nkm {
 	u32			enable;
 	u32			lock;
 
-	struct _ccu_mult	n;
-	struct _ccu_mult	k;
-	struct _ccu_div		m;
+	struct ccu_mult_internal	n;
+	struct ccu_mult_internal	k;
+	struct ccu_div_internal		m;
 	struct ccu_mux_internal	mux;
 
 	struct ccu_common	common;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkmp.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkmp.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkmp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkmp.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,16 +9,15 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/rational.h>
 
 #include "ccu_gate.h"
 #include "ccu_nkmp.h"
 
 struct _ccu_nkmp {
-	unsigned long	n, max_n;
-	unsigned long	k, max_k;
-	unsigned long	m, max_m;
-	unsigned long	p, max_p;
+	unsigned long	n, min_n, max_n;
+	unsigned long	k, min_k, max_k;
+	unsigned long	m, min_m, max_m;
+	unsigned long	p, min_p, max_p;
 };
 
 static void ccu_nkmp_find_best(unsigned long parent, unsigned long rate,
@@ -28,25 +27,25 @@ static void ccu_nkmp_find_best(unsigned
 	unsigned long best_n = 0, best_k = 0, best_m = 0, best_p = 0;
 	unsigned long _n, _k, _m, _p;
 
-	for (_k = 1; _k <= nkmp->max_k; _k++) {
-		for (_p = 1; _p <= nkmp->max_p; _p <<= 1) {
-			unsigned long tmp_rate;
-
-			rational_best_approximation(rate / _k, parent / _p,
-						    nkmp->max_n, nkmp->max_m,
-						    &_n, &_m);
+	for (_k = nkmp->min_k; _k <= nkmp->max_k; _k++) {
+		for (_n = nkmp->min_n; _n <= nkmp->max_n; _n++) {
+			for (_m = nkmp->min_m; _m <= nkmp->max_m; _m++) {
+				for (_p = nkmp->min_p; _p <= nkmp->max_p; _p <<= 1) {
+					unsigned long tmp_rate;
 
-			tmp_rate = parent * _n * _k / (_m * _p);
+					tmp_rate = parent * _n * _k / (_m * _p);
 
-			if (tmp_rate > rate)
-				continue;
+					if (tmp_rate > rate)
+						continue;
 
-			if ((rate - tmp_rate) < (rate - best_rate)) {
-				best_rate = tmp_rate;
-				best_n = _n;
-				best_k = _k;
-				best_m = _m;
-				best_p = _p;
+					if ((rate - tmp_rate) < (rate - best_rate)) {
+						best_rate = tmp_rate;
+						best_n = _n;
+						best_k = _k;
+						best_m = _m;
+						best_p = _p;
+					}
+				}
 			}
 		}
 	}
@@ -108,9 +107,13 @@ static long ccu_nkmp_round_rate(struct c
 	struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
 	struct _ccu_nkmp _nkmp;
 
+	_nkmp.min_n = nkmp->n.min;
 	_nkmp.max_n = 1 << nkmp->n.width;
+	_nkmp.min_k = nkmp->k.min;
 	_nkmp.max_k = 1 << nkmp->k.width;
+	_nkmp.min_m = 1;
 	_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+	_nkmp.min_p = 1;
 	_nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
 
 	ccu_nkmp_find_best(*parent_rate, rate, &_nkmp);
@@ -126,9 +129,13 @@ static int ccu_nkmp_set_rate(struct clk_
 	unsigned long flags;
 	u32 reg;
 
+	_nkmp.min_n = 1;
 	_nkmp.max_n = 1 << nkmp->n.width;
+	_nkmp.min_k = 1;
 	_nkmp.max_k = 1 << nkmp->k.width;
+	_nkmp.min_m = 1;
 	_nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
+	_nkmp.min_p = 1;
 	_nkmp.max_p = nkmp->p.max ?: 1 << ((1 << nkmp->p.width) - 1);
 
 	ccu_nkmp_find_best(parent_rate, rate, &_nkmp);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkmp.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkmp.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nkmp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nkmp.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,10 +29,10 @@ struct ccu_nkmp {
 	u32			enable;
 	u32			lock;
 
-	struct _ccu_mult	n;
-	struct _ccu_mult	k;
-	struct _ccu_div		m;
-	struct _ccu_div		p;
+	struct ccu_mult_internal	n;
+	struct ccu_mult_internal	k;
+	struct ccu_div_internal		m;
+	struct ccu_div_internal		p;
 
 	struct ccu_common	common;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nm.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nm.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nm.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,12 +9,42 @@
  */
 
 #include <linux/clk-provider.h>
-#include <linux/rational.h>
 
 #include "ccu_frac.h"
 #include "ccu_gate.h"
 #include "ccu_nm.h"
 
+struct _ccu_nm {
+	unsigned long	n, min_n, max_n;
+	unsigned long	m, min_m, max_m;
+};
+
+static void ccu_nm_find_best(unsigned long parent, unsigned long rate,
+			     struct _ccu_nm *nm)
+{
+	unsigned long best_rate = 0;
+	unsigned long best_n = 0, best_m = 0;
+	unsigned long _n, _m;
+
+	for (_n = nm->min_n; _n <= nm->max_n; _n++) {
+		for (_m = nm->min_m; _m <= nm->max_m; _m++) {
+			unsigned long tmp_rate = parent * _n  / _m;
+
+			if (tmp_rate > rate)
+				continue;
+
+			if ((rate - tmp_rate) < (rate - best_rate)) {
+				best_rate = tmp_rate;
+				best_n = _n;
+				best_m = _m;
+			}
+		}
+	}
+
+	nm->n = best_n;
+	nm->m = best_m;
+}
+
 static void ccu_nm_disable(struct clk_hw *hw)
 {
 	struct ccu_nm *nm = hw_to_ccu_nm(hw);
@@ -61,24 +91,24 @@ static long ccu_nm_round_rate(struct clk
 			      unsigned long *parent_rate)
 {
 	struct ccu_nm *nm = hw_to_ccu_nm(hw);
-	unsigned long max_n, max_m;
-	unsigned long n, m;
+	struct _ccu_nm _nm;
 
-	max_n = 1 << nm->n.width;
-	max_m = nm->m.max ?: 1 << nm->m.width;
+	_nm.min_n = nm->n.min;
+	_nm.max_n = 1 << nm->n.width;
+	_nm.min_m = 1;
+	_nm.max_m = nm->m.max ?: 1 << nm->m.width;
 
-	rational_best_approximation(rate, *parent_rate, max_n, max_m, &n, &m);
+	ccu_nm_find_best(*parent_rate, rate, &_nm);
 
-	return *parent_rate * n / m;
+	return *parent_rate * _nm.n / _nm.m;
 }
 
 static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
 			   unsigned long parent_rate)
 {
 	struct ccu_nm *nm = hw_to_ccu_nm(hw);
+	struct _ccu_nm _nm;
 	unsigned long flags;
-	unsigned long max_n, max_m;
-	unsigned long n, m;
 	u32 reg;
 
 	if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate))
@@ -86,10 +116,12 @@ static int ccu_nm_set_rate(struct clk_hw
 	else
 		ccu_frac_helper_disable(&nm->common, &nm->frac);
 
-	max_n = 1 << nm->n.width;
-	max_m = nm->m.max ?: 1 << nm->m.width;
+	_nm.min_n = 1;
+	_nm.max_n = 1 << nm->n.width;
+	_nm.min_m = 1;
+	_nm.max_m = nm->m.max ?: 1 << nm->m.width;
 
-	rational_best_approximation(rate, parent_rate, max_n, max_m, &n, &m);
+	ccu_nm_find_best(parent_rate, rate, &_nm);
 
 	spin_lock_irqsave(nm->common.lock, flags);
 
@@ -97,7 +129,7 @@ static int ccu_nm_set_rate(struct clk_hw
 	reg &= ~GENMASK(nm->n.width + nm->n.shift - 1, nm->n.shift);
 	reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift);
 
-	writel(reg | ((m - 1) << nm->m.shift) | ((n - 1) << nm->n.shift),
+	writel(reg | ((_nm.m - 1) << nm->m.shift) | ((_nm.n - 1) << nm->n.shift),
 	       nm->common.base + nm->common.reg);
 
 	spin_unlock_irqrestore(nm->common.lock, flags);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nm.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nm.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu_nm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu_nm.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,9 +30,9 @@ struct ccu_nm {
 	u32			enable;
 	u32			lock;
 
-	struct _ccu_mult	n;
-	struct _ccu_div		m;
-	struct _ccu_frac	frac;
+	struct ccu_mult_internal	n;
+	struct ccu_div_internal		m;
+	struct ccu_frac_internal	frac;
 
 	struct ccu_common	common;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,915 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+#include "ccu_phase.h"
+
+#include "ccu-sun50i-a64.h"
+
+static struct ccu_nkmp pll_cpux_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT(8, 5),
+	.k		= _SUNXI_CCU_MULT(4, 2),
+	.m		= _SUNXI_CCU_DIV(0, 2),
+	.p		= _SUNXI_CCU_DIV_MAX(16, 2, 4),
+	.common		= {
+		.reg		= 0x000,
+		.hw.init	= CLK_HW_INIT("pll-cpux",
+					      "osc24M",
+					      &ccu_nkmp_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
+
+/*
+ * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from
+ * the base (2x, 4x and 8x), and one variable divider (the one true
+ * pll audio).
+ *
+ * We don't have any need for the variable divider for now, so we just
+ * hardcode it to match with the clock names
+ */
+#define SUN50I_A64_PLL_AUDIO_REG	0x008
+
+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
+				   "osc24M", 0x008,
+				   8, 7,	/* N */
+				   0, 5,	/* M */
+				   BIT(31),	/* gate */
+				   BIT(28),	/* lock */
+				   CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0",
+					"osc24M", 0x010,
+					8, 7,		/* N */
+					0, 4,		/* M */
+					BIT(24),	/* frac enable */
+					BIT(25),	/* frac select */
+					270000000,	/* frac rate 0 */
+					297000000,	/* frac rate 1 */
+					BIT(31),	/* gate */
+					BIT(28),	/* lock */
+					CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
+					"osc24M", 0x018,
+					8, 7,		/* N */
+					0, 4,		/* M */
+					BIT(24),	/* frac enable */
+					BIT(25),	/* frac select */
+					270000000,	/* frac rate 0 */
+					297000000,	/* frac rate 1 */
+					BIT(31),	/* gate */
+					BIT(28),	/* lock */
+					CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0",
+				    "osc24M", 0x020,
+				    8, 5,	/* N */
+				    4, 2,	/* K */
+				    0, 2,	/* M */
+				    BIT(31),	/* gate */
+				    BIT(28),	/* lock */
+				    CLK_SET_RATE_UNGATE);
+
+static struct ccu_nk pll_periph0_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT(8, 5),
+	.k		= _SUNXI_CCU_MULT_MIN(4, 2, 2),
+	.fixed_post_div	= 2,
+	.common		= {
+		.reg		= 0x028,
+		.features	= CCU_FEATURE_FIXED_POSTDIV,
+		.hw.init	= CLK_HW_INIT("pll-periph0", "osc24M",
+					      &ccu_nk_ops, CLK_SET_RATE_UNGATE),
+	},
+};
+
+static struct ccu_nk pll_periph1_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT(8, 5),
+	.k		= _SUNXI_CCU_MULT_MIN(4, 2, 2),
+	.fixed_post_div	= 2,
+	.common		= {
+		.reg		= 0x02c,
+		.features	= CCU_FEATURE_FIXED_POSTDIV,
+		.hw.init	= CLK_HW_INIT("pll-periph1", "osc24M",
+					      &ccu_nk_ops, CLK_SET_RATE_UNGATE),
+	},
+};
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1",
+					"osc24M", 0x030,
+					8, 7,		/* N */
+					0, 4,		/* M */
+					BIT(24),	/* frac enable */
+					BIT(25),	/* frac select */
+					270000000,	/* frac rate 0 */
+					297000000,	/* frac rate 1 */
+					BIT(31),	/* gate */
+					BIT(28),	/* lock */
+					CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu",
+					"osc24M", 0x038,
+					8, 7,		/* N */
+					0, 4,		/* M */
+					BIT(24),	/* frac enable */
+					BIT(25),	/* frac select */
+					270000000,	/* frac rate 0 */
+					297000000,	/* frac rate 1 */
+					BIT(31),	/* gate */
+					BIT(28),	/* lock */
+					CLK_SET_RATE_UNGATE);
+
+/*
+ * The output function can be changed to something more complex that
+ * we do not handle yet.
+ *
+ * Hardcode the mode so that we don't fall in that case.
+ */
+#define SUN50I_A64_PLL_MIPI_REG		0x040
+
+static struct ccu_nkm pll_mipi_clk = {
+	.enable		= BIT(31),
+	.lock		= BIT(28),
+	.n		= _SUNXI_CCU_MULT(8, 4),
+	.k		= _SUNXI_CCU_MULT_MIN(4, 2, 2),
+	.m		= _SUNXI_CCU_DIV(0, 4),
+	.common		= {
+		.reg		= 0x040,
+		.hw.init	= CLK_HW_INIT("pll-mipi", "pll-video0",
+					      &ccu_nkm_ops, CLK_SET_RATE_UNGATE),
+	},
+};
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_hsic_clk, "pll-hsic",
+					"osc24M", 0x044,
+					8, 7,		/* N */
+					0, 4,		/* M */
+					BIT(24),	/* frac enable */
+					BIT(25),	/* frac select */
+					270000000,	/* frac rate 0 */
+					297000000,	/* frac rate 1 */
+					BIT(31),	/* gate */
+					BIT(28),	/* lock */
+					CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
+					"osc24M", 0x048,
+					8, 7,		/* N */
+					0, 4,		/* M */
+					BIT(24),	/* frac enable */
+					BIT(25),	/* frac select */
+					270000000,	/* frac rate 0 */
+					297000000,	/* frac rate 1 */
+					BIT(31),	/* gate */
+					BIT(28),	/* lock */
+					CLK_SET_RATE_UNGATE);
+
+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
+				   "osc24M", 0x04c,
+				   8, 7,	/* N */
+				   0, 2,	/* M */
+				   BIT(31),	/* gate */
+				   BIT(28),	/* lock */
+				   CLK_SET_RATE_UNGATE);
+
+static const char * const cpux_parents[] = { "osc32k", "osc24M",
+					     "pll-cpux", "pll-cpux" };
+static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents,
+		     0x050, 16, 2, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL);
+
+static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0);
+
+static const char * const ahb1_parents[] = { "osc32k", "osc24M",
+					     "axi", "pll-periph0" };
+static struct ccu_div ahb1_clk = {
+	.div		= _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
+
+	.mux		= {
+		.shift	= 12,
+		.width	= 2,
+
+		.variable_prediv	= {
+			.index	= 3,
+			.shift	= 6,
+			.width	= 2,
+		},
+	},
+
+	.common		= {
+		.reg		= 0x054,
+		.features	= CCU_FEATURE_VARIABLE_PREDIV,
+		.hw.init	= CLK_HW_INIT_PARENTS("ahb1",
+						      ahb1_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static struct clk_div_table apb1_div_table[] = {
+	{ .val = 0, .div = 2 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 8 },
+	{ /* Sentinel */ },
+};
+static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1",
+			   0x054, 8, 2, apb1_div_table, 0);
+
+static const char * const apb2_parents[] = { "osc32k", "osc24M",
+					     "pll-periph0-2x",
+					     "pll-periph0-2x" };
+static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058,
+			     0, 5,	/* M */
+			     16, 2,	/* P */
+			     24, 2,	/* mux */
+			     0);
+
+static const char * const ahb2_parents[] = { "ahb1", "pll-periph0" };
+static const struct ccu_mux_fixed_prediv ahb2_fixed_predivs[] = {
+	{ .index = 1, .div = 2 },
+};
+static struct ccu_mux ahb2_clk = {
+	.mux		= {
+		.shift	= 0,
+		.width	= 1,
+		.fixed_predivs	= ahb2_fixed_predivs,
+		.n_predivs	= ARRAY_SIZE(ahb2_fixed_predivs),
+	},
+
+	.common		= {
+		.reg		= 0x05c,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
+		.hw.init	= CLK_HW_INIT_PARENTS("ahb2",
+						      ahb2_parents,
+						      &ccu_mux_ops,
+						      0),
+	},
+};
+
+static SUNXI_CCU_GATE(bus_mipi_dsi_clk,	"bus-mipi-dsi",	"ahb1",
+		      0x060, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_ce_clk,	"bus-ce",	"ahb1",
+		      0x060, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_dma_clk,	"bus-dma",	"ahb1",
+		      0x060, BIT(6), 0);
+static SUNXI_CCU_GATE(bus_mmc0_clk,	"bus-mmc0",	"ahb1",
+		      0x060, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_mmc1_clk,	"bus-mmc1",	"ahb1",
+		      0x060, BIT(9), 0);
+static SUNXI_CCU_GATE(bus_mmc2_clk,	"bus-mmc2",	"ahb1",
+		      0x060, BIT(10), 0);
+static SUNXI_CCU_GATE(bus_nand_clk,	"bus-nand",	"ahb1",
+		      0x060, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_dram_clk,	"bus-dram",	"ahb1",
+		      0x060, BIT(14), 0);
+static SUNXI_CCU_GATE(bus_emac_clk,	"bus-emac",	"ahb2",
+		      0x060, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_ts_clk,	"bus-ts",	"ahb1",
+		      0x060, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_hstimer_clk,	"bus-hstimer",	"ahb1",
+		      0x060, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_spi0_clk,	"bus-spi0",	"ahb1",
+		      0x060, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_spi1_clk,	"bus-spi1",	"ahb1",
+		      0x060, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_otg_clk,	"bus-otg",	"ahb1",
+		      0x060, BIT(23), 0);
+static SUNXI_CCU_GATE(bus_ehci0_clk,	"bus-ehci0",	"ahb1",
+		      0x060, BIT(24), 0);
+static SUNXI_CCU_GATE(bus_ehci1_clk,	"bus-ehci1",	"ahb2",
+		      0x060, BIT(25), 0);
+static SUNXI_CCU_GATE(bus_ohci0_clk,	"bus-ohci0",	"ahb1",
+		      0x060, BIT(28), 0);
+static SUNXI_CCU_GATE(bus_ohci1_clk,	"bus-ohci1",	"ahb2",
+		      0x060, BIT(29), 0);
+
+static SUNXI_CCU_GATE(bus_ve_clk,	"bus-ve",	"ahb1",
+		      0x064, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_tcon0_clk,	"bus-tcon0",	"ahb1",
+		      0x064, BIT(3), 0);
+static SUNXI_CCU_GATE(bus_tcon1_clk,	"bus-tcon1",	"ahb1",
+		      0x064, BIT(4), 0);
+static SUNXI_CCU_GATE(bus_deinterlace_clk,	"bus-deinterlace",	"ahb1",
+		      0x064, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_csi_clk,	"bus-csi",	"ahb1",
+		      0x064, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_hdmi_clk,	"bus-hdmi",	"ahb1",
+		      0x064, BIT(11), 0);
+static SUNXI_CCU_GATE(bus_de_clk,	"bus-de",	"ahb1",
+		      0x064, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_gpu_clk,	"bus-gpu",	"ahb1",
+		      0x064, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_msgbox_clk,	"bus-msgbox",	"ahb1",
+		      0x064, BIT(21), 0);
+static SUNXI_CCU_GATE(bus_spinlock_clk,	"bus-spinlock",	"ahb1",
+		      0x064, BIT(22), 0);
+
+static SUNXI_CCU_GATE(bus_codec_clk,	"bus-codec",	"apb1",
+		      0x068, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_spdif_clk,	"bus-spdif",	"apb1",
+		      0x068, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_pio_clk,	"bus-pio",	"apb1",
+		      0x068, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_ths_clk,	"bus-ths",	"apb1",
+		      0x068, BIT(8), 0);
+static SUNXI_CCU_GATE(bus_i2s0_clk,	"bus-i2s0",	"apb1",
+		      0x068, BIT(12), 0);
+static SUNXI_CCU_GATE(bus_i2s1_clk,	"bus-i2s1",	"apb1",
+		      0x068, BIT(13), 0);
+static SUNXI_CCU_GATE(bus_i2s2_clk,	"bus-i2s2",	"apb1",
+		      0x068, BIT(14), 0);
+
+static SUNXI_CCU_GATE(bus_i2c0_clk,	"bus-i2c0",	"apb2",
+		      0x06c, BIT(0), 0);
+static SUNXI_CCU_GATE(bus_i2c1_clk,	"bus-i2c1",	"apb2",
+		      0x06c, BIT(1), 0);
+static SUNXI_CCU_GATE(bus_i2c2_clk,	"bus-i2c2",	"apb2",
+		      0x06c, BIT(2), 0);
+static SUNXI_CCU_GATE(bus_scr_clk,	"bus-scr",	"apb2",
+		      0x06c, BIT(5), 0);
+static SUNXI_CCU_GATE(bus_uart0_clk,	"bus-uart0",	"apb2",
+		      0x06c, BIT(16), 0);
+static SUNXI_CCU_GATE(bus_uart1_clk,	"bus-uart1",	"apb2",
+		      0x06c, BIT(17), 0);
+static SUNXI_CCU_GATE(bus_uart2_clk,	"bus-uart2",	"apb2",
+		      0x06c, BIT(18), 0);
+static SUNXI_CCU_GATE(bus_uart3_clk,	"bus-uart3",	"apb2",
+		      0x06c, BIT(19), 0);
+static SUNXI_CCU_GATE(bus_uart4_clk,	"bus-uart4",	"apb2",
+		      0x06c, BIT(20), 0);
+
+static SUNXI_CCU_GATE(bus_dbg_clk,	"bus-dbg",	"ahb1",
+		      0x070, BIT(7), 0);
+
+static struct clk_div_table ths_div_table[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 6 },
+};
+static const char * const ths_parents[] = { "osc24M" };
+static struct ccu_div ths_clk = {
+	.enable	= BIT(31),
+	.div	= _SUNXI_CCU_DIV_TABLE(0, 2, ths_div_table),
+	.mux	= _SUNXI_CCU_MUX(24, 2),
+	.common	= {
+		.reg		= 0x074,
+		.hw.init	= CLK_HW_INIT_PARENTS("ths",
+						      ths_parents,
+						      &ccu_div_ops,
+						      0),
+	},
+};
+
+static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0",
+						     "pll-periph1" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const mmc_default_parents[] = { "osc24M", "pll-periph0-2x",
+						    "pll-periph1-2x" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc_default_parents, 0x088,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc_default_parents, 0x08c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc_default_parents, 0x090,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const ts_parents[] = { "osc24M", "pll-periph0", };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 4,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", mmc_default_parents, 0x09c,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4,
+				  0, 4,		/* M */
+				  16, 2,	/* P */
+				  24, 2,	/* mux */
+				  BIT(31),	/* gate */
+				  0);
+
+static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
+					    "pll-audio-2x", "pll-audio" };
+static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
+			       0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
+			       0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
+			       0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
+			     0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
+		      0x0cc, BIT(8), 0);
+static SUNXI_CCU_GATE(usb_phy1_clk,	"usb-phy1",	"osc24M",
+		      0x0cc, BIT(9), 0);
+static SUNXI_CCU_GATE(usb_hsic_clk,	"usb-hsic",	"pll-hsic",
+		      0x0cc, BIT(10), 0);
+static SUNXI_CCU_GATE(usb_hsic_12m_clk,	"usb-hsic-12M",	"osc12M",
+		      0x0cc, BIT(11), 0);
+static SUNXI_CCU_GATE(usb_ohci0_clk,	"usb-ohci0",	"osc12M",
+		      0x0cc, BIT(16), 0);
+static SUNXI_CCU_GATE(usb_ohci1_clk,	"usb-ohci1",	"usb-ohci0",
+		      0x0cc, BIT(17), 0);
+
+static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents,
+			    0x0f4, 0, 4, 20, 2, CLK_IS_CRITICAL);
+
+static SUNXI_CCU_GATE(dram_ve_clk,	"dram-ve",	"dram",
+		      0x100, BIT(0), 0);
+static SUNXI_CCU_GATE(dram_csi_clk,	"dram-csi",	"dram",
+		      0x100, BIT(1), 0);
+static SUNXI_CCU_GATE(dram_deinterlace_clk,	"dram-deinterlace",	"dram",
+		      0x100, BIT(2), 0);
+static SUNXI_CCU_GATE(dram_ts_clk,	"dram-ts",	"dram",
+		      0x100, BIT(3), 0);
+
+static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" };
+static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
+				 0x104, 0, 4, 24, 3, BIT(31), 0);
+
+static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
+static const u8 tcon0_table[] = { 0, 2, };
+static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
+				     tcon0_table, 0x118, 24, 3, BIT(31),
+				     CLK_SET_RATE_PARENT);
+
+static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
+static const u8 tcon1_table[] = { 0, 2, };
+static struct ccu_div tcon1_clk = {
+	.enable		= BIT(31),
+	.div		= _SUNXI_CCU_DIV(0, 4),
+	.mux		= _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table),
+	.common		= {
+		.reg		= 0x11c,
+		.hw.init	= CLK_HW_INIT_PARENTS("tcon1",
+						      tcon1_parents,
+						      &ccu_div_ops,
+						      CLK_SET_RATE_PARENT),
+	},
+};
+
+static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
+				 0x124, 0, 4, 24, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(csi_misc_clk,	"csi-misc",	"osc24M",
+		      0x130, BIT(31), 0);
+
+static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents,
+				 0x134, 16, 4, 24, 3, BIT(31), 0);
+
+static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", "pll-periph1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", csi_mclk_parents,
+				 0x134, 0, 5, 8, 3, BIT(15), 0);
+
+static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve",
+			     0x13c, 16, 3, BIT(31), 0);
+
+static SUNXI_CCU_GATE(ac_dig_clk,	"ac-dig",	"pll-audio",
+		      0x140, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(ac_dig_4x_clk,	"ac-dig-4x",	"pll-audio-4x",
+		      0x140, BIT(30), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
+		      0x144, BIT(31), 0);
+
+static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
+				 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_GATE(hdmi_ddc_clk,	"hdmi-ddc",	"osc24M",
+		      0x154, BIT(31), 0);
+
+static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x",
+						 "pll-ddr0", "pll-ddr1" };
+static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
+				 0x15c, 0, 3, 24, 2, BIT(31), CLK_IS_CRITICAL);
+
+static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" };
+static const u8 dsi_dphy_table[] = { 0, 2, };
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy",
+				       dsi_dphy_parents, dsi_dphy_table,
+				       0x168, 0, 4, 8, 2, BIT(31), CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
+			     0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
+
+/* Fixed Factor clocks */
+static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 1, 2, 0);
+
+/* We hardcode the divider to 4 for now */
+static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
+			"pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
+			"pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
+			"pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
+			"pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
+static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x",
+			"pll-periph0", 1, 2, 0);
+static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x",
+			"pll-periph1", 1, 2, 0);
+static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x",
+			"pll-video0", 1, 2, CLK_SET_RATE_PARENT);
+
+static struct ccu_common *sun50i_a64_ccu_clks[] = {
+	&pll_cpux_clk.common,
+	&pll_audio_base_clk.common,
+	&pll_video0_clk.common,
+	&pll_ve_clk.common,
+	&pll_ddr0_clk.common,
+	&pll_periph0_clk.common,
+	&pll_periph1_clk.common,
+	&pll_video1_clk.common,
+	&pll_gpu_clk.common,
+	&pll_mipi_clk.common,
+	&pll_hsic_clk.common,
+	&pll_de_clk.common,
+	&pll_ddr1_clk.common,
+	&cpux_clk.common,
+	&axi_clk.common,
+	&ahb1_clk.common,
+	&apb1_clk.common,
+	&apb2_clk.common,
+	&ahb2_clk.common,
+	&bus_mipi_dsi_clk.common,
+	&bus_ce_clk.common,
+	&bus_dma_clk.common,
+	&bus_mmc0_clk.common,
+	&bus_mmc1_clk.common,
+	&bus_mmc2_clk.common,
+	&bus_nand_clk.common,
+	&bus_dram_clk.common,
+	&bus_emac_clk.common,
+	&bus_ts_clk.common,
+	&bus_hstimer_clk.common,
+	&bus_spi0_clk.common,
+	&bus_spi1_clk.common,
+	&bus_otg_clk.common,
+	&bus_ehci0_clk.common,
+	&bus_ehci1_clk.common,
+	&bus_ohci0_clk.common,
+	&bus_ohci1_clk.common,
+	&bus_ve_clk.common,
+	&bus_tcon0_clk.common,
+	&bus_tcon1_clk.common,
+	&bus_deinterlace_clk.common,
+	&bus_csi_clk.common,
+	&bus_hdmi_clk.common,
+	&bus_de_clk.common,
+	&bus_gpu_clk.common,
+	&bus_msgbox_clk.common,
+	&bus_spinlock_clk.common,
+	&bus_codec_clk.common,
+	&bus_spdif_clk.common,
+	&bus_pio_clk.common,
+	&bus_ths_clk.common,
+	&bus_i2s0_clk.common,
+	&bus_i2s1_clk.common,
+	&bus_i2s2_clk.common,
+	&bus_i2c0_clk.common,
+	&bus_i2c1_clk.common,
+	&bus_i2c2_clk.common,
+	&bus_scr_clk.common,
+	&bus_uart0_clk.common,
+	&bus_uart1_clk.common,
+	&bus_uart2_clk.common,
+	&bus_uart3_clk.common,
+	&bus_uart4_clk.common,
+	&bus_dbg_clk.common,
+	&ths_clk.common,
+	&nand_clk.common,
+	&mmc0_clk.common,
+	&mmc1_clk.common,
+	&mmc2_clk.common,
+	&ts_clk.common,
+	&ce_clk.common,
+	&spi0_clk.common,
+	&spi1_clk.common,
+	&i2s0_clk.common,
+	&i2s1_clk.common,
+	&i2s2_clk.common,
+	&spdif_clk.common,
+	&usb_phy0_clk.common,
+	&usb_phy1_clk.common,
+	&usb_hsic_clk.common,
+	&usb_hsic_12m_clk.common,
+	&usb_ohci0_clk.common,
+	&usb_ohci1_clk.common,
+	&dram_clk.common,
+	&dram_ve_clk.common,
+	&dram_csi_clk.common,
+	&dram_deinterlace_clk.common,
+	&dram_ts_clk.common,
+	&de_clk.common,
+	&tcon0_clk.common,
+	&tcon1_clk.common,
+	&deinterlace_clk.common,
+	&csi_misc_clk.common,
+	&csi_sclk_clk.common,
+	&csi_mclk_clk.common,
+	&ve_clk.common,
+	&ac_dig_clk.common,
+	&ac_dig_4x_clk.common,
+	&avs_clk.common,
+	&hdmi_clk.common,
+	&hdmi_ddc_clk.common,
+	&mbus_clk.common,
+	&dsi_dphy_clk.common,
+	&gpu_clk.common,
+};
+
+static struct clk_hw_onecell_data sun50i_a64_hw_clks = {
+	.hws	= {
+		[CLK_OSC_12M]		= &osc12M_clk.hw,
+		[CLK_PLL_CPUX]		= &pll_cpux_clk.common.hw,
+		[CLK_PLL_AUDIO_BASE]	= &pll_audio_base_clk.common.hw,
+		[CLK_PLL_AUDIO]		= &pll_audio_clk.hw,
+		[CLK_PLL_AUDIO_2X]	= &pll_audio_2x_clk.hw,
+		[CLK_PLL_AUDIO_4X]	= &pll_audio_4x_clk.hw,
+		[CLK_PLL_AUDIO_8X]	= &pll_audio_8x_clk.hw,
+		[CLK_PLL_VIDEO0]	= &pll_video0_clk.common.hw,
+		[CLK_PLL_VIDEO0_2X]	= &pll_video0_2x_clk.hw,
+		[CLK_PLL_VE]		= &pll_ve_clk.common.hw,
+		[CLK_PLL_DDR0]		= &pll_ddr0_clk.common.hw,
+		[CLK_PLL_PERIPH0]	= &pll_periph0_clk.common.hw,
+		[CLK_PLL_PERIPH0_2X]	= &pll_periph0_2x_clk.hw,
+		[CLK_PLL_PERIPH1]	= &pll_periph1_clk.common.hw,
+		[CLK_PLL_PERIPH1_2X]	= &pll_periph1_2x_clk.hw,
+		[CLK_PLL_VIDEO1]	= &pll_video1_clk.common.hw,
+		[CLK_PLL_GPU]		= &pll_gpu_clk.common.hw,
+		[CLK_PLL_MIPI]  	= &pll_mipi_clk.common.hw,
+		[CLK_PLL_HSIC]		= &pll_hsic_clk.common.hw,
+		[CLK_PLL_DE]		= &pll_de_clk.common.hw,
+		[CLK_PLL_DDR1]		= &pll_ddr1_clk.common.hw,
+		[CLK_CPUX]		= &cpux_clk.common.hw,
+		[CLK_AXI]		= &axi_clk.common.hw,
+		[CLK_AHB1]		= &ahb1_clk.common.hw,
+		[CLK_APB1]		= &apb1_clk.common.hw,
+		[CLK_APB2]		= &apb2_clk.common.hw,
+		[CLK_AHB2]		= &ahb2_clk.common.hw,
+		[CLK_BUS_MIPI_DSI]	= &bus_mipi_dsi_clk.common.hw,
+		[CLK_BUS_CE]		= &bus_ce_clk.common.hw,
+		[CLK_BUS_DMA]		= &bus_dma_clk.common.hw,
+		[CLK_BUS_MMC0]		= &bus_mmc0_clk.common.hw,
+		[CLK_BUS_MMC1]		= &bus_mmc1_clk.common.hw,
+		[CLK_BUS_MMC2]		= &bus_mmc2_clk.common.hw,
+		[CLK_BUS_NAND]		= &bus_nand_clk.common.hw,
+		[CLK_BUS_DRAM]		= &bus_dram_clk.common.hw,
+		[CLK_BUS_EMAC]		= &bus_emac_clk.common.hw,
+		[CLK_BUS_TS]		= &bus_ts_clk.common.hw,
+		[CLK_BUS_HSTIMER]	= &bus_hstimer_clk.common.hw,
+		[CLK_BUS_SPI0]		= &bus_spi0_clk.common.hw,
+		[CLK_BUS_SPI1]		= &bus_spi1_clk.common.hw,
+		[CLK_BUS_OTG]		= &bus_otg_clk.common.hw,
+		[CLK_BUS_EHCI0]		= &bus_ehci0_clk.common.hw,
+		[CLK_BUS_EHCI1]		= &bus_ehci1_clk.common.hw,
+		[CLK_BUS_OHCI0]		= &bus_ohci0_clk.common.hw,
+		[CLK_BUS_OHCI1]		= &bus_ohci1_clk.common.hw,
+		[CLK_BUS_VE]		= &bus_ve_clk.common.hw,
+		[CLK_BUS_TCON0]		= &bus_tcon0_clk.common.hw,
+		[CLK_BUS_TCON1]		= &bus_tcon1_clk.common.hw,
+		[CLK_BUS_DEINTERLACE]	= &bus_deinterlace_clk.common.hw,
+		[CLK_BUS_CSI]		= &bus_csi_clk.common.hw,
+		[CLK_BUS_HDMI]		= &bus_hdmi_clk.common.hw,
+		[CLK_BUS_DE]		= &bus_de_clk.common.hw,
+		[CLK_BUS_GPU]		= &bus_gpu_clk.common.hw,
+		[CLK_BUS_MSGBOX]	= &bus_msgbox_clk.common.hw,
+		[CLK_BUS_SPINLOCK]	= &bus_spinlock_clk.common.hw,
+		[CLK_BUS_CODEC]		= &bus_codec_clk.common.hw,
+		[CLK_BUS_SPDIF]		= &bus_spdif_clk.common.hw,
+		[CLK_BUS_PIO]		= &bus_pio_clk.common.hw,
+		[CLK_BUS_THS]		= &bus_ths_clk.common.hw,
+		[CLK_BUS_I2S0]		= &bus_i2s0_clk.common.hw,
+		[CLK_BUS_I2S1]		= &bus_i2s1_clk.common.hw,
+		[CLK_BUS_I2S2]		= &bus_i2s2_clk.common.hw,
+		[CLK_BUS_I2C0]		= &bus_i2c0_clk.common.hw,
+		[CLK_BUS_I2C1]		= &bus_i2c1_clk.common.hw,
+		[CLK_BUS_I2C2]		= &bus_i2c2_clk.common.hw,
+		[CLK_BUS_UART0]		= &bus_uart0_clk.common.hw,
+		[CLK_BUS_UART1]		= &bus_uart1_clk.common.hw,
+		[CLK_BUS_UART2]		= &bus_uart2_clk.common.hw,
+		[CLK_BUS_UART3]		= &bus_uart3_clk.common.hw,
+		[CLK_BUS_UART4]		= &bus_uart4_clk.common.hw,
+		[CLK_BUS_SCR]		= &bus_scr_clk.common.hw,
+		[CLK_BUS_DBG]		= &bus_dbg_clk.common.hw,
+		[CLK_THS]		= &ths_clk.common.hw,
+		[CLK_NAND]		= &nand_clk.common.hw,
+		[CLK_MMC0]		= &mmc0_clk.common.hw,
+		[CLK_MMC1]		= &mmc1_clk.common.hw,
+		[CLK_MMC2]		= &mmc2_clk.common.hw,
+		[CLK_TS]		= &ts_clk.common.hw,
+		[CLK_CE]		= &ce_clk.common.hw,
+		[CLK_SPI0]		= &spi0_clk.common.hw,
+		[CLK_SPI1]		= &spi1_clk.common.hw,
+		[CLK_I2S0]		= &i2s0_clk.common.hw,
+		[CLK_I2S1]		= &i2s1_clk.common.hw,
+		[CLK_I2S2]		= &i2s2_clk.common.hw,
+		[CLK_SPDIF]		= &spdif_clk.common.hw,
+		[CLK_USB_PHY0]		= &usb_phy0_clk.common.hw,
+		[CLK_USB_PHY1]		= &usb_phy1_clk.common.hw,
+		[CLK_USB_HSIC]		= &usb_hsic_clk.common.hw,
+		[CLK_USB_HSIC_12M]	= &usb_hsic_12m_clk.common.hw,
+		[CLK_USB_OHCI0]		= &usb_ohci0_clk.common.hw,
+		[CLK_USB_OHCI1]		= &usb_ohci1_clk.common.hw,
+		[CLK_DRAM]		= &dram_clk.common.hw,
+		[CLK_DRAM_VE]		= &dram_ve_clk.common.hw,
+		[CLK_DRAM_CSI]		= &dram_csi_clk.common.hw,
+		[CLK_DRAM_DEINTERLACE]	= &dram_deinterlace_clk.common.hw,
+		[CLK_DRAM_TS]		= &dram_ts_clk.common.hw,
+		[CLK_DE]		= &de_clk.common.hw,
+		[CLK_TCON0]		= &tcon0_clk.common.hw,
+		[CLK_TCON1]		= &tcon1_clk.common.hw,
+		[CLK_DEINTERLACE]	= &deinterlace_clk.common.hw,
+		[CLK_CSI_MISC]		= &csi_misc_clk.common.hw,
+		[CLK_CSI_SCLK]		= &csi_sclk_clk.common.hw,
+		[CLK_CSI_MCLK]		= &csi_mclk_clk.common.hw,
+		[CLK_VE]		= &ve_clk.common.hw,
+		[CLK_AC_DIG]		= &ac_dig_clk.common.hw,
+		[CLK_AC_DIG_4X]		= &ac_dig_4x_clk.common.hw,
+		[CLK_AVS]		= &avs_clk.common.hw,
+		[CLK_HDMI]		= &hdmi_clk.common.hw,
+		[CLK_HDMI_DDC]		= &hdmi_ddc_clk.common.hw,
+		[CLK_MBUS]		= &mbus_clk.common.hw,
+		[CLK_DSI_DPHY]		= &dsi_dphy_clk.common.hw,
+		[CLK_GPU]		= &gpu_clk.common.hw,
+	},
+	.num	= CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun50i_a64_ccu_resets[] = {
+	[RST_USB_PHY0]		=  { 0x0cc, BIT(0) },
+	[RST_USB_PHY1]		=  { 0x0cc, BIT(1) },
+	[RST_USB_HSIC]		=  { 0x0cc, BIT(2) },
+
+	[RST_DRAM]		=  { 0x0f4, BIT(31) },
+	[RST_MBUS]		=  { 0x0fc, BIT(31) },
+
+	[RST_BUS_MIPI_DSI]	=  { 0x2c0, BIT(1) },
+	[RST_BUS_CE]		=  { 0x2c0, BIT(5) },
+	[RST_BUS_DMA]		=  { 0x2c0, BIT(6) },
+	[RST_BUS_MMC0]		=  { 0x2c0, BIT(8) },
+	[RST_BUS_MMC1]		=  { 0x2c0, BIT(9) },
+	[RST_BUS_MMC2]		=  { 0x2c0, BIT(10) },
+	[RST_BUS_NAND]		=  { 0x2c0, BIT(13) },
+	[RST_BUS_DRAM]		=  { 0x2c0, BIT(14) },
+	[RST_BUS_EMAC]		=  { 0x2c0, BIT(17) },
+	[RST_BUS_TS]		=  { 0x2c0, BIT(18) },
+	[RST_BUS_HSTIMER]	=  { 0x2c0, BIT(19) },
+	[RST_BUS_SPI0]		=  { 0x2c0, BIT(20) },
+	[RST_BUS_SPI1]		=  { 0x2c0, BIT(21) },
+	[RST_BUS_OTG]		=  { 0x2c0, BIT(23) },
+	[RST_BUS_EHCI0]		=  { 0x2c0, BIT(24) },
+	[RST_BUS_EHCI1]		=  { 0x2c0, BIT(25) },
+	[RST_BUS_OHCI0]		=  { 0x2c0, BIT(28) },
+	[RST_BUS_OHCI1]		=  { 0x2c0, BIT(29) },
+
+	[RST_BUS_VE]		=  { 0x2c4, BIT(0) },
+	[RST_BUS_TCON0]		=  { 0x2c4, BIT(3) },
+	[RST_BUS_TCON1]		=  { 0x2c4, BIT(4) },
+	[RST_BUS_DEINTERLACE]	=  { 0x2c4, BIT(5) },
+	[RST_BUS_CSI]		=  { 0x2c4, BIT(8) },
+	[RST_BUS_HDMI0]		=  { 0x2c4, BIT(10) },
+	[RST_BUS_HDMI1]		=  { 0x2c4, BIT(11) },
+	[RST_BUS_DE]		=  { 0x2c4, BIT(12) },
+	[RST_BUS_GPU]		=  { 0x2c4, BIT(20) },
+	[RST_BUS_MSGBOX]	=  { 0x2c4, BIT(21) },
+	[RST_BUS_SPINLOCK]	=  { 0x2c4, BIT(22) },
+	[RST_BUS_DBG]		=  { 0x2c4, BIT(31) },
+
+	[RST_BUS_LVDS]		=  { 0x2c8, BIT(0) },
+
+	[RST_BUS_CODEC]		=  { 0x2d0, BIT(0) },
+	[RST_BUS_SPDIF]		=  { 0x2d0, BIT(1) },
+	[RST_BUS_THS]		=  { 0x2d0, BIT(8) },
+	[RST_BUS_I2S0]		=  { 0x2d0, BIT(12) },
+	[RST_BUS_I2S1]		=  { 0x2d0, BIT(13) },
+	[RST_BUS_I2S2]		=  { 0x2d0, BIT(14) },
+
+	[RST_BUS_I2C0]		=  { 0x2d8, BIT(0) },
+	[RST_BUS_I2C1]		=  { 0x2d8, BIT(1) },
+	[RST_BUS_I2C2]		=  { 0x2d8, BIT(2) },
+	[RST_BUS_SCR]		=  { 0x2d8, BIT(5) },
+	[RST_BUS_UART0]		=  { 0x2d8, BIT(16) },
+	[RST_BUS_UART1]		=  { 0x2d8, BIT(17) },
+	[RST_BUS_UART2]		=  { 0x2d8, BIT(18) },
+	[RST_BUS_UART3]		=  { 0x2d8, BIT(19) },
+	[RST_BUS_UART4]		=  { 0x2d8, BIT(20) },
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_ccu_desc = {
+	.ccu_clks	= sun50i_a64_ccu_clks,
+	.num_ccu_clks	= ARRAY_SIZE(sun50i_a64_ccu_clks),
+
+	.hw_clks	= &sun50i_a64_hw_clks,
+
+	.resets		= sun50i_a64_ccu_resets,
+	.num_resets	= ARRAY_SIZE(sun50i_a64_ccu_resets),
+};
+
+static int sun50i_a64_ccu_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	void __iomem *reg;
+	u32 val;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(reg))
+		return PTR_ERR(reg);
+
+	/* Force the PLL-Audio-1x divider to 4 */
+	val = readl(reg + SUN50I_A64_PLL_AUDIO_REG);
+	val &= ~GENMASK(19, 16);
+	writel(val | (3 << 16), reg + SUN50I_A64_PLL_AUDIO_REG);
+
+	writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
+
+	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
+}
+
+static const struct of_device_id sun50i_a64_ccu_ids[] = {
+	{ .compatible = "allwinner,sun50i-a64-ccu" },
+	{ }
+};
+
+static struct platform_driver sun50i_a64_ccu_driver = {
+	.probe	= sun50i_a64_ccu_probe,
+	.driver	= {
+		.name	= "sun50i-a64-ccu",
+		.of_match_table	= sun50i_a64_ccu_ids,
+	},
+};
+builtin_platform_driver(sun50i_a64_ccu_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.h linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.h
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun50i-a64.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.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.
+ */
+
+#ifndef _CCU_SUN50I_A64_H_
+#define _CCU_SUN50I_A64_H_
+
+#include <dt-bindings/clock/sun50i-a64-ccu.h>
+#include <dt-bindings/reset/sun50i-a64-ccu.h>
+
+#define CLK_OSC_12M			0
+#define CLK_PLL_CPUX			1
+#define CLK_PLL_AUDIO_BASE		2
+#define CLK_PLL_AUDIO			3
+#define CLK_PLL_AUDIO_2X		4
+#define CLK_PLL_AUDIO_4X		5
+#define CLK_PLL_AUDIO_8X		6
+#define CLK_PLL_VIDEO0			7
+#define CLK_PLL_VIDEO0_2X		8
+#define CLK_PLL_VE			9
+#define CLK_PLL_DDR0			10
+#define CLK_PLL_PERIPH0			11
+#define CLK_PLL_PERIPH0_2X		12
+#define CLK_PLL_PERIPH1			13
+#define CLK_PLL_PERIPH1_2X		14
+#define CLK_PLL_VIDEO1			15
+#define CLK_PLL_GPU			16
+#define CLK_PLL_MIPI			17
+#define CLK_PLL_HSIC			18
+#define CLK_PLL_DE			19
+#define CLK_PLL_DDR1			20
+#define CLK_CPUX			21
+#define CLK_AXI				22
+#define CLK_APB				23
+#define CLK_AHB1			24
+#define CLK_APB1			25
+#define CLK_APB2			26
+#define CLK_AHB2			27
+
+/* All the bus gates are exported */
+
+/* The first bunch of module clocks are exported */
+
+#define CLK_USB_OHCI0_12M		90
+
+#define CLK_USB_OHCI1_12M		92
+
+#define CLK_DRAM			94
+
+/* All the DRAM gates are exported */
+
+/* Some more module clocks are exported */
+
+#define CLK_MBUS			112
+
+/* And the DSI and GPU module clock is exported */
+
+#define CLK_NUMBER			(CLK_GPU + 1)
+
+#endif /* _CCU_SUN50I_A64_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun8i-a23.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun8i-a23.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun8i-a23.c	2017-02-12 16:03:20.000000000 -0500
@@ -344,10 +344,10 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_c
 static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
 					    "pll-audio-2x", "pll-audio" };
 static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
-			       0x0b0, 16, 2, BIT(31), 0);
+			       0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
-			       0x0b4, 16, 2, BIT(31), 0);
+			       0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 /* TODO: the parent for most of the USB clocks is not known */
 static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
@@ -415,7 +415,7 @@ static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve
 			     0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(ac_dig_clk,	"ac-dig",	"pll-audio",
-		      0x140, BIT(31), 0);
+		      0x140, BIT(31), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
 		      0x144, BIT(31), 0);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun8i-h3.c linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/ccu-sun8i-h3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/ccu-sun8i-h3.c	2017-02-12 16:03:20.000000000 -0500
@@ -394,16 +394,16 @@ static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_c
 static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x",
 					    "pll-audio-2x", "pll-audio" };
 static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents,
-			       0x0b0, 16, 2, BIT(31), 0);
+			       0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents,
-			       0x0b4, 16, 2, BIT(31), 0);
+			       0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents,
-			       0x0b8, 16, 2, BIT(31), 0);
+			       0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_M_WITH_GATE(spdif_clk, "spdif", "pll-audio",
-			     0x0c0, 0, 4, BIT(31), 0);
+			     0x0c0, 0, 4, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(usb_phy0_clk,	"usb-phy0",	"osc24M",
 		      0x0cc, BIT(8), 0);
@@ -466,7 +466,7 @@ static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve
 			     0x13c, 16, 3, BIT(31), 0);
 
 static SUNXI_CCU_GATE(ac_dig_clk,	"ac-dig",	"pll-audio",
-		      0x140, BIT(31), 0);
+		      0x140, BIT(31), CLK_SET_RATE_PARENT);
 static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
 		      0x144, BIT(31), 0);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/Kconfig linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/Kconfig
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -35,17 +35,14 @@ config SUNXI_CCU_NK
 
 config SUNXI_CCU_NKM
 	bool
-	select RATIONAL
 	select SUNXI_CCU_GATE
 
 config SUNXI_CCU_NKMP
 	bool
-	select RATIONAL
 	select SUNXI_CCU_GATE
 
 config SUNXI_CCU_NM
 	bool
-	select RATIONAL
 	select SUNXI_CCU_FRAC
 	select SUNXI_CCU_GATE
 
@@ -56,6 +53,17 @@ config SUNXI_CCU_MP
 
 # SoC Drivers
 
+config SUN50I_A64_CCU
+	bool "Support for the Allwinner A64 CCU"
+	select SUNXI_CCU_DIV
+	select SUNXI_CCU_NK
+	select SUNXI_CCU_NKM
+	select SUNXI_CCU_NKMP
+	select SUNXI_CCU_NM
+	select SUNXI_CCU_MP
+	select SUNXI_CCU_PHASE
+	default ARM64 && ARCH_SUNXI
+
 config SUN6I_A31_CCU
 	bool "Support for the Allwinner A31/A31s CCU"
 	select SUNXI_CCU_DIV
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/sunxi-ng/Makefile linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/Makefile
--- linux-libre-4.9-gnu/drivers/clk/sunxi-ng/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/sunxi-ng/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@ obj-$(CONFIG_SUNXI_CCU_NM)	+= ccu_nm.o
 obj-$(CONFIG_SUNXI_CCU_MP)	+= ccu_mp.o
 
 # SoC support
+obj-$(CONFIG_SUN50I_A64_CCU)	+= ccu-sun50i-a64.o
 obj-$(CONFIG_SUN6I_A31_CCU)	+= ccu-sun6i-a31.o
 obj-$(CONFIG_SUN8I_A23_CCU)	+= ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)	+= ccu-sun8i-a33.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c linux-libre-4.10-rc8-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
--- linux-libre-4.9-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <soc/tegra/fuse.h>
 
@@ -148,7 +148,6 @@ static const struct of_device_id tegra12
 	{ .compatible = "nvidia,tegra124-dfll", },
 	{ },
 };
-MODULE_DEVICE_TABLE(of, tegra124_dfll_fcpu_of_match);
 
 static const struct dev_pm_ops tegra124_dfll_pm_ops = {
 	SET_RUNTIME_PM_OPS(tegra_dfll_runtime_suspend,
@@ -164,20 +163,4 @@ static struct platform_driver tegra124_d
 		.pm = &tegra124_dfll_pm_ops,
 	},
 };
-
-static int __init tegra124_dfll_fcpu_init(void)
-{
-	return platform_driver_register(&tegra124_dfll_fcpu_driver);
-}
-module_init(tegra124_dfll_fcpu_init);
-
-static void __exit tegra124_dfll_fcpu_exit(void)
-{
-	platform_driver_unregister(&tegra124_dfll_fcpu_driver);
-}
-module_exit(tegra124_dfll_fcpu_exit);
-
-MODULE_DESCRIPTION("Tegra124 DFLL clock source driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Aleksandr Frid <afrid@nvidia.com>");
-MODULE_AUTHOR("Paul Walmsley <pwalmsley@nvidia.com>");
+builtin_platform_driver(tegra124_dfll_fcpu_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/tegra/cvb.c linux-libre-4.10-rc8-gnu/drivers/clk/tegra/cvb.c
--- linux-libre-4.9-gnu/drivers/clk/tegra/cvb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/tegra/cvb.c	2017-02-12 16:03:20.000000000 -0500
@@ -92,19 +92,19 @@ static int build_opp_table(struct device
 
 /**
  * tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables
- * @cvb_tables: array of CVB tables
- * @sz: size of the previously mentioned array
+ * @dev: the struct device * for which the OPP table is built
+ * @tables: array of CVB tables
+ * @count: size of the previously mentioned array
  * @process_id: process id of the HW module
  * @speedo_id: speedo id of the HW module
  * @speedo_value: speedo value of the HW module
- * @max_rate: highest safe clock rate
- * @opp_dev: the struct device * for which the OPP table is built
+ * @max_freq: highest safe clock rate
  *
  * On Tegra, a CVB table encodes the relationship between operating voltage
  * and safe maximal frequency for a given module (e.g. GPU or CPU). This
  * function calculates the optimal voltage-frequency operating points
  * for the given arguments and exports them via the OPP library for the
- * given @opp_dev. Returns a pointer to the struct cvb_table that matched
+ * given @dev. Returns a pointer to the struct cvb_table that matched
  * or an ERR_PTR on failure.
  */
 const struct cvb_table *
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/ti/clk-3xxx.c linux-libre-4.10-rc8-gnu/drivers/clk/ti/clk-3xxx.c
--- linux-libre-4.9-gnu/drivers/clk/ti/clk-3xxx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/ti/clk-3xxx.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,13 +22,6 @@
 
 #include "clock.h"
 
-/*
- * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
- * that are sourced by DPLL5, and both of these require this clock
- * to be at 120 MHz for proper operation.
- */
-#define DPLL5_FREQ_FOR_USBHOST		120000000
-
 #define OMAP3430ES2_ST_DSS_IDLE_SHIFT			1
 #define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT		5
 #define OMAP3430ES2_ST_SSI_IDLE_SHIFT			8
@@ -546,14 +539,21 @@ void __init omap3_clk_lock_dpll5(void)
 	struct clk *dpll5_clk;
 	struct clk *dpll5_m2_clk;
 
+	/*
+	 * Errata sprz319f advisory 2.1 documents a USB host clock drift issue
+	 * that can be worked around using specially crafted dpll5 settings
+	 * with a dpll5_m2 divider set to 8. Set the dpll5 rate to 8x the USB
+	 * host clock rate, its .set_rate handler() will detect that frequency
+	 * and use the errata settings.
+	 */
 	dpll5_clk = clk_get(NULL, "dpll5_ck");
-	clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+	clk_set_rate(dpll5_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST * 8);
 	clk_prepare_enable(dpll5_clk);
 
-	/* Program dpll5_m2_clk divider for no division */
+	/* Program dpll5_m2_clk divider */
 	dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
 	clk_prepare_enable(dpll5_m2_clk);
-	clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
+	clk_set_rate(dpll5_m2_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST);
 
 	clk_disable_unprepare(dpll5_m2_clk);
 	clk_disable_unprepare(dpll5_clk);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/ti/clk-7xx.c linux-libre-4.10-rc8-gnu/drivers/clk/ti/clk-7xx.c
--- linux-libre-4.9-gnu/drivers/clk/ti/clk-7xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/ti/clk-7xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -201,7 +201,6 @@ static struct ti_dt_clk dra7xx_clks[] =
 	DT_CLK(NULL, "atl_dpll_clk_mux", "atl_dpll_clk_mux"),
 	DT_CLK(NULL, "atl_gfclk_mux", "atl_gfclk_mux"),
 	DT_CLK(NULL, "dcan1_sys_clk_mux", "dcan1_sys_clk_mux"),
-	DT_CLK(NULL, "gmac_gmii_ref_clk_div", "gmac_gmii_ref_clk_div"),
 	DT_CLK(NULL, "gmac_rft_clk_mux", "gmac_rft_clk_mux"),
 	DT_CLK(NULL, "gpu_core_gclk_mux", "gpu_core_gclk_mux"),
 	DT_CLK(NULL, "gpu_hyd_gclk_mux", "gpu_hyd_gclk_mux"),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/ti/clk-dra7-atl.c linux-libre-4.10-rc8-gnu/drivers/clk/ti/clk-dra7-atl.c
--- linux-libre-4.9-gnu/drivers/clk/ti/clk-dra7-atl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/ti/clk-dra7-atl.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
@@ -295,31 +295,17 @@ static int of_dra7_atl_clk_probe(struct
 	return ret;
 }
 
-static int of_dra7_atl_clk_remove(struct platform_device *pdev)
-{
-	pm_runtime_disable(&pdev->dev);
-
-	return 0;
-}
-
 static const struct of_device_id of_dra7_atl_clk_match_tbl[] = {
 	{ .compatible = "ti,dra7-atl", },
 	{},
 };
-MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
 
 static struct platform_driver dra7_atl_clk_driver = {
 	.driver = {
 		.name = "dra7-atl",
+		.suppress_bind_attrs = true,
 		.of_match_table = of_dra7_atl_clk_match_tbl,
 	},
 	.probe = of_dra7_atl_clk_probe,
-	.remove = of_dra7_atl_clk_remove,
 };
-
-module_platform_driver(dra7_atl_clk_driver);
-
-MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic");
-MODULE_ALIAS("platform:dra7-atl-clock");
-MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(dra7_atl_clk_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/ti/clock.h linux-libre-4.10-rc8-gnu/drivers/clk/ti/clock.h
--- linux-libre-4.9-gnu/drivers/clk/ti/clock.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/ti/clock.h	2017-02-12 16:03:20.000000000 -0500
@@ -257,11 +257,20 @@ long omap2_dpll_round_rate(struct clk_hw
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 				    unsigned long parent_rate);
 
+/*
+ * OMAP3_DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
+ * that are sourced by DPLL5, and both of these require this clock
+ * to be at 120 MHz for proper operation.
+ */
+#define OMAP3_DPLL5_FREQ_FOR_USBHOST	120000000
+
 unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
 			 unsigned long parent_rate);
 int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
 				    unsigned long parent_rate, u8 index);
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long parent_rate);
 void omap3_clk_lock_dpll5(void);
 
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/ti/dpll3xxx.c linux-libre-4.10-rc8-gnu/drivers/clk/ti/dpll3xxx.c
--- linux-libre-4.9-gnu/drivers/clk/ti/dpll3xxx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/ti/dpll3xxx.c	2017-02-12 16:03:20.000000000 -0500
@@ -838,3 +838,70 @@ int omap3_dpll4_set_rate_and_parent(stru
 	return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
 						      index);
 }
+
+/* Apply DM3730 errata sprz319 advisory 2.1. */
+static bool omap3_dpll5_apply_errata(struct clk_hw *hw,
+				     unsigned long parent_rate)
+{
+	struct omap3_dpll5_settings {
+		unsigned int rate, m, n;
+	};
+
+	static const struct omap3_dpll5_settings precomputed[] = {
+		/*
+		 * From DM3730 errata advisory 2.1, table 35 and 36.
+		 * The N value is increased by 1 compared to the tables as the
+		 * errata lists register values while last_rounded_field is the
+		 * real divider value.
+		 */
+		{ 12000000,  80,  0 + 1 },
+		{ 13000000, 443,  5 + 1 },
+		{ 19200000,  50,  0 + 1 },
+		{ 26000000, 443, 11 + 1 },
+		{ 38400000,  25,  0 + 1 }
+	};
+
+	const struct omap3_dpll5_settings *d;
+	struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+	struct dpll_data *dd;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(precomputed); ++i) {
+		if (parent_rate == precomputed[i].rate)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(precomputed))
+		return false;
+
+	d = &precomputed[i];
+
+	/* Update the M, N and rounded rate values and program the DPLL. */
+	dd = clk->dpll_data;
+	dd->last_rounded_m = d->m;
+	dd->last_rounded_n = d->n;
+	dd->last_rounded_rate = div_u64((u64)parent_rate * d->m, d->n);
+	omap3_noncore_dpll_program(clk, 0);
+
+	return true;
+}
+
+/**
+ * omap3_dpll5_set_rate - set rate for omap3 dpll5
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Set rate for the DPLL5 clock. Apply the sprz319 advisory 2.1 on OMAP36xx if
+ * the DPLL is used for USB host (detected through the requested rate).
+ */
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+			 unsigned long parent_rate)
+{
+	if (rate == OMAP3_DPLL5_FREQ_FOR_USBHOST * 8) {
+		if (omap3_dpll5_apply_errata(hw, parent_rate))
+			return 0;
+	}
+
+	return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/ti/dpll.c linux-libre-4.10-rc8-gnu/drivers/clk/ti/dpll.c
--- linux-libre-4.9-gnu/drivers/clk/ti/dpll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/ti/dpll.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,6 +114,18 @@ static const struct clk_ops omap3_dpll_c
 	.round_rate	= &omap2_dpll_round_rate,
 };
 
+static const struct clk_ops omap3_dpll5_ck_ops = {
+	.enable		= &omap3_noncore_dpll_enable,
+	.disable	= &omap3_noncore_dpll_disable,
+	.get_parent	= &omap2_init_dpll_parent,
+	.recalc_rate	= &omap3_dpll_recalc,
+	.set_rate	= &omap3_dpll5_set_rate,
+	.set_parent	= &omap3_noncore_dpll_set_parent,
+	.set_rate_and_parent	= &omap3_noncore_dpll_set_rate_and_parent,
+	.determine_rate	= &omap3_noncore_dpll_determine_rate,
+	.round_rate	= &omap2_dpll_round_rate,
+};
+
 static const struct clk_ops omap3_dpll_per_ck_ops = {
 	.enable		= &omap3_noncore_dpll_enable,
 	.disable	= &omap3_noncore_dpll_disable,
@@ -474,7 +486,12 @@ static void __init of_ti_omap3_dpll_setu
 		.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
 	};
 
-	of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
+	if ((of_machine_is_compatible("ti,omap3630") ||
+	     of_machine_is_compatible("ti,omap36xx")) &&
+	    !strcmp(node->name, "dpll5_ck"))
+		of_ti_dpll_setup(node, &omap3_dpll5_ck_ops, &dd);
+	else
+		of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
 	       of_ti_omap3_dpll_setup);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier-core.c linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier-core.c
--- linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,9 @@ static struct clk_hw *uniphier_clk_regis
 					const struct uniphier_clk_data *data)
 {
 	switch (data->type) {
+	case UNIPHIER_CLK_TYPE_CPUGEAR:
+		return uniphier_clk_register_cpugear(dev, regmap, data->name,
+						     &data->data.cpugear);
 	case UNIPHIER_CLK_TYPE_FIXED_FACTOR:
 		return uniphier_clk_register_fixed_factor(dev, data->name,
 							  &data->data.factor);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier-cpugear.c linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier-cpugear.c
--- linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier-cpugear.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier-cpugear.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+#include "clk-uniphier.h"
+
+#define UNIPHIER_CLK_CPUGEAR_STAT	0	/* status */
+#define UNIPHIER_CLK_CPUGEAR_SET	4	/* set */
+#define UNIPHIER_CLK_CPUGEAR_UPD	8	/* update */
+#define   UNIPHIER_CLK_CPUGEAR_UPD_BIT	BIT(0)
+
+struct uniphier_clk_cpugear {
+	struct clk_hw hw;
+	struct regmap *regmap;
+	unsigned int regbase;
+	unsigned int mask;
+};
+
+#define to_uniphier_clk_cpugear(_hw) \
+			container_of(_hw, struct uniphier_clk_cpugear, hw)
+
+static int uniphier_clk_cpugear_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_write_bits(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+				gear->mask, index);
+	if (ret)
+		return ret;
+
+	ret = regmap_write_bits(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+				UNIPHIER_CLK_CPUGEAR_UPD_BIT,
+				UNIPHIER_CLK_CPUGEAR_UPD_BIT);
+	if (ret)
+		return ret;
+
+	return regmap_read_poll_timeout(gear->regmap,
+				gear->regbase + UNIPHIER_CLK_CPUGEAR_UPD,
+				val, !(val & UNIPHIER_CLK_CPUGEAR_UPD_BIT),
+				0, 1);
+}
+
+static u8 uniphier_clk_cpugear_get_parent(struct clk_hw *hw)
+{
+	struct uniphier_clk_cpugear *gear = to_uniphier_clk_cpugear(hw);
+	int num_parents = clk_hw_get_num_parents(hw);
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(gear->regmap,
+			  gear->regbase + UNIPHIER_CLK_CPUGEAR_STAT, &val);
+	if (ret)
+		return ret;
+
+	val &= gear->mask;
+
+	return val < num_parents ? val : -EINVAL;
+}
+
+static const struct clk_ops uniphier_clk_cpugear_ops = {
+	.determine_rate = __clk_mux_determine_rate,
+	.set_parent = uniphier_clk_cpugear_set_parent,
+	.get_parent = uniphier_clk_cpugear_get_parent,
+};
+
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+					 struct regmap *regmap,
+					 const char *name,
+				const struct uniphier_clk_cpugear_data *data)
+{
+	struct uniphier_clk_cpugear *gear;
+	struct clk_init_data init;
+	int ret;
+
+	gear = devm_kzalloc(dev, sizeof(*gear), GFP_KERNEL);
+	if (!gear)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &uniphier_clk_cpugear_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	init.parent_names = data->parent_names;
+	init.num_parents = data->num_parents,
+
+	gear->regmap = regmap;
+	gear->regbase = data->regbase;
+	gear->mask = data->mask;
+	gear->hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &gear->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &gear->hw;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier.h linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier.h
--- linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,15 +20,24 @@ struct clk_hw;
 struct device;
 struct regmap;
 
-#define UNIPHIER_CLK_MUX_MAX_PARENTS	8
+#define UNIPHIER_CLK_CPUGEAR_MAX_PARENTS	16
+#define UNIPHIER_CLK_MUX_MAX_PARENTS		8
 
 enum uniphier_clk_type {
+	UNIPHIER_CLK_TYPE_CPUGEAR,
 	UNIPHIER_CLK_TYPE_FIXED_FACTOR,
 	UNIPHIER_CLK_TYPE_FIXED_RATE,
 	UNIPHIER_CLK_TYPE_GATE,
 	UNIPHIER_CLK_TYPE_MUX,
 };
 
+struct uniphier_clk_cpugear_data {
+	const char *parent_names[UNIPHIER_CLK_CPUGEAR_MAX_PARENTS];
+	unsigned int num_parents;
+	unsigned int regbase;
+	unsigned int mask;
+};
+
 struct uniphier_clk_fixed_factor_data {
 	const char *parent_name;
 	unsigned int mult;
@@ -58,6 +67,7 @@ struct uniphier_clk_data {
 	enum uniphier_clk_type type;
 	int idx;
 	union {
+		struct uniphier_clk_cpugear_data cpugear;
 		struct uniphier_clk_fixed_factor_data factor;
 		struct uniphier_clk_fixed_rate_data rate;
 		struct uniphier_clk_gate_data gate;
@@ -65,6 +75,20 @@ struct uniphier_clk_data {
 	} data;
 };
 
+#define UNIPHIER_CLK_CPUGEAR(_name, _idx, _regbase, _mask,	\
+			     _num_parents, ...)			\
+	{							\
+		.name = (_name),				\
+		.type = UNIPHIER_CLK_TYPE_CPUGEAR,		\
+		.idx = (_idx),					\
+		.data.cpugear = {				\
+			.parent_names = { __VA_ARGS__ },	\
+			.num_parents = (_num_parents),		\
+			.regbase = (_regbase),			\
+			.mask = (_mask)				\
+		 },						\
+	}
+
 #define UNIPHIER_CLK_FACTOR(_name, _idx, _parent, _mult, _div)	\
 	{							\
 		.name = (_name),				\
@@ -77,7 +101,6 @@ struct uniphier_clk_data {
 		},						\
 	}
 
-
 #define UNIPHIER_CLK_GATE(_name, _idx, _parent, _reg, _bit)	\
 	{							\
 		.name = (_name),				\
@@ -90,7 +113,25 @@ struct uniphier_clk_data {
 		},						\
 	}
 
+#define UNIPHIER_CLK_DIV(parent, div)				\
+	UNIPHIER_CLK_FACTOR(parent "/" #div, -1, parent, 1, div)
+
+#define UNIPHIER_CLK_DIV2(parent, div0, div1)			\
+	UNIPHIER_CLK_DIV(parent, div0),				\
+	UNIPHIER_CLK_DIV(parent, div1)
+
+#define UNIPHIER_CLK_DIV3(parent, div0, div1, div2)		\
+	UNIPHIER_CLK_DIV2(parent, div0, div1),			\
+	UNIPHIER_CLK_DIV(parent, div2)
 
+#define UNIPHIER_CLK_DIV4(parent, div0, div1, div2, div3)	\
+	UNIPHIER_CLK_DIV2(parent, div0, div1),			\
+	UNIPHIER_CLK_DIV2(parent, div2, div3)
+
+struct clk_hw *uniphier_clk_register_cpugear(struct device *dev,
+					     struct regmap *regmap,
+					     const char *name,
+				const struct uniphier_clk_cpugear_data *data);
 struct clk_hw *uniphier_clk_register_fixed_factor(struct device *dev,
 						  const char *name,
 			const struct uniphier_clk_fixed_factor_data *data);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier-sys.c linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier-sys.c
--- linux-libre-4.9-gnu/drivers/clk/uniphier/clk-uniphier-sys.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/clk-uniphier-sys.c	2017-02-12 16:03:20.000000000 -0500
@@ -125,16 +125,35 @@ const struct uniphier_clk_data uniphier_
 };
 
 const struct uniphier_clk_data uniphier_ld11_sys_clk_data[] = {
+	UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 392, 5),		/* 1960 MHz */
+	UNIPHIER_CLK_FACTOR("mpll", -1, "ref", 64, 1),		/* 1600 MHz */
 	UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1),		/* 2000 MHz */
+	UNIPHIER_CLK_FACTOR("vspll", -1, "ref", 80, 1),		/* 2000 MHz */
 	UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34),
 	UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40),
 	UNIPHIER_LD11_SYS_CLK_STDMAC(8),			/* HSC, MIO */
 	UNIPHIER_CLK_FACTOR("usb2", -1, "ref", 24, 25),
+	/* CPU gears */
+	UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8),
+	UNIPHIER_CLK_DIV4("mpll", 2, 3, 4, 8),
+	UNIPHIER_CLK_DIV3("spll", 3, 4, 8),
+	/* Note: both gear1 and gear4 are spll/4.  This is not a bug. */
+	UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8,
+			     "cpll/2", "spll/4", "cpll/3", "spll/3",
+			     "spll/4", "spll/8", "cpll/4", "cpll/8"),
+	UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8,
+			     "mpll/2", "spll/4", "mpll/3", "spll/3",
+			     "spll/4", "spll/8", "mpll/4", "mpll/8"),
 	{ /* sentinel */ }
 };
 
 const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = {
+	UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 88, 1),		/* ARM: 2200 MHz */
+	UNIPHIER_CLK_FACTOR("gppll", -1, "ref", 52, 1),		/* Mali: 1300 MHz */
+	UNIPHIER_CLK_FACTOR("mpll", -1, "ref", 64, 1),		/* Codec: 1600 MHz */
 	UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1),		/* 2000 MHz */
+	UNIPHIER_CLK_FACTOR("s2pll", -1, "ref", 88, 1),		/* IPP: 2200 MHz */
+	UNIPHIER_CLK_FACTOR("vppll", -1, "ref", 504, 5),	/* 2520 MHz */
 	UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34),
 	UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40),
 	UNIPHIER_LD20_SYS_CLK_SD,
@@ -147,5 +166,18 @@ const struct uniphier_clk_data uniphier_
 	UNIPHIER_CLK_GATE("usb30", 14, NULL, 0x210c, 14),
 	UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 12),
 	UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 13),
+	/* CPU gears */
+	UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8),
+	UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8),
+	UNIPHIER_CLK_DIV4("s2pll", 2, 3, 4, 8),
+	UNIPHIER_CLK_CPUGEAR("cpu-ca72", 32, 0x8000, 0xf, 8,
+			     "cpll/2", "spll/2", "cpll/3", "spll/3",
+			     "spll/4", "spll/8", "cpll/4", "cpll/8"),
+	UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8,
+			     "cpll/2", "spll/2", "cpll/3", "spll/3",
+			     "spll/4", "spll/8", "cpll/4", "cpll/8"),
+	UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8,
+			     "s2pll/2", "spll/2", "s2pll/3", "spll/3",
+			     "spll/4", "spll/8", "s2pll/4", "s2pll/8"),
 	{ /* sentinel */ }
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clk/uniphier/Makefile linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/Makefile
--- linux-libre-4.9-gnu/drivers/clk/uniphier/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clk/uniphier/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,8 +1,11 @@
 obj-y	+= clk-uniphier-core.o
+
+obj-y	+= clk-uniphier-cpugear.o
 obj-y	+= clk-uniphier-fixed-factor.o
 obj-y	+= clk-uniphier-fixed-rate.o
 obj-y	+= clk-uniphier-gate.o
 obj-y	+= clk-uniphier-mux.o
+
 obj-y	+= clk-uniphier-sys.o
 obj-y	+= clk-uniphier-mio.o
 obj-y	+= clk-uniphier-peri.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/acpi_pm.c linux-libre-4.10-rc8-gnu/drivers/clocksource/acpi_pm.c
--- linux-libre-4.9-gnu/drivers/clocksource/acpi_pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/acpi_pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,16 +58,16 @@ u32 acpi_pm_read_verified(void)
 	return v2;
 }
 
-static cycle_t acpi_pm_read(struct clocksource *cs)
+static u64 acpi_pm_read(struct clocksource *cs)
 {
-	return (cycle_t)read_pmtmr();
+	return (u64)read_pmtmr();
 }
 
 static struct clocksource clocksource_acpi_pm = {
 	.name		= "acpi_pm",
 	.rating		= 200,
 	.read		= acpi_pm_read,
-	.mask		= (cycle_t)ACPI_PM_MASK,
+	.mask		= (u64)ACPI_PM_MASK,
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -81,9 +81,9 @@ static int __init acpi_pm_good_setup(cha
 }
 __setup("acpi_pm_good", acpi_pm_good_setup);
 
-static cycle_t acpi_pm_read_slow(struct clocksource *cs)
+static u64 acpi_pm_read_slow(struct clocksource *cs)
 {
-	return (cycle_t)acpi_pm_read_verified();
+	return (u64)acpi_pm_read_verified();
 }
 
 static inline void acpi_pm_need_workaround(void)
@@ -145,7 +145,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SE
  */
 static int verify_pmtmr_rate(void)
 {
-	cycle_t value1, value2;
+	u64 value1, value2;
 	unsigned long count, delta;
 
 	mach_prepare_counter();
@@ -175,7 +175,7 @@ static int verify_pmtmr_rate(void)
 
 static int __init init_acpi_pm_clocksource(void)
 {
-	cycle_t value1, value2;
+	u64 value1, value2;
 	unsigned int i, j = 0;
 
 	if (!pmtmr_ioport)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/arc_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/arc_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/arc_timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/arc_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2016-17 Synopsys, Inc. (www.synopsys.com)
+ * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.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.
+ */
+
+/* ARC700 has two 32bit independent prog Timers: TIMER0 and TIMER1, Each can be
+ * programmed to go from @count to @limit and optionally interrupt.
+ * We've designated TIMER0 for clockevents and TIMER1 for clocksource
+ *
+ * ARCv2 based HS38 cores have RTC (in-core) and GFRC (inside ARConnect/MCIP)
+ * which are suitable for UP and SMP based clocksources respectively
+ */
+
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/cpu.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+
+#include <soc/arc/timers.h>
+#include <soc/arc/mcip.h>
+
+
+static unsigned long arc_timer_freq;
+
+static int noinline arc_get_timer_clk(struct device_node *node)
+{
+	struct clk *clk;
+	int ret;
+
+	clk = of_clk_get(node, 0);
+	if (IS_ERR(clk)) {
+		pr_err("timer missing clk");
+		return PTR_ERR(clk);
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clk\n");
+		return ret;
+	}
+
+	arc_timer_freq = clk_get_rate(clk);
+
+	return 0;
+}
+
+/********** Clock Source Device *********/
+
+#ifdef CONFIG_ARC_TIMERS_64BIT
+
+static u64 arc_read_gfrc(struct clocksource *cs)
+{
+	unsigned long flags;
+	u32 l, h;
+
+	local_irq_save(flags);
+
+	__mcip_cmd(CMD_GFRC_READ_LO, 0);
+	l = read_aux_reg(ARC_REG_MCIP_READBACK);
+
+	__mcip_cmd(CMD_GFRC_READ_HI, 0);
+	h = read_aux_reg(ARC_REG_MCIP_READBACK);
+
+	local_irq_restore(flags);
+
+	return (((u64)h) << 32) | l;
+}
+
+static struct clocksource arc_counter_gfrc = {
+	.name   = "ARConnect GFRC",
+	.rating = 400,
+	.read   = arc_read_gfrc,
+	.mask   = CLOCKSOURCE_MASK(64),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init arc_cs_setup_gfrc(struct device_node *node)
+{
+	struct mcip_bcr mp;
+	int ret;
+
+	READ_BCR(ARC_REG_MCIP_BCR, mp);
+	if (!mp.gfrc) {
+		pr_warn("Global-64-bit-Ctr clocksource not detected");
+		return -ENXIO;
+	}
+
+	ret = arc_get_timer_clk(node);
+	if (ret)
+		return ret;
+
+	return clocksource_register_hz(&arc_counter_gfrc, arc_timer_freq);
+}
+CLOCKSOURCE_OF_DECLARE(arc_gfrc, "snps,archs-timer-gfrc", arc_cs_setup_gfrc);
+
+#define AUX_RTC_CTRL	0x103
+#define AUX_RTC_LOW	0x104
+#define AUX_RTC_HIGH	0x105
+
+static u64 arc_read_rtc(struct clocksource *cs)
+{
+	unsigned long status;
+	u32 l, h;
+
+	/*
+	 * hardware has an internal state machine which tracks readout of
+	 * low/high and updates the CTRL.status if
+	 *  - interrupt/exception taken between the two reads
+	 *  - high increments after low has been read
+	 */
+	do {
+		l = read_aux_reg(AUX_RTC_LOW);
+		h = read_aux_reg(AUX_RTC_HIGH);
+		status = read_aux_reg(AUX_RTC_CTRL);
+	} while (!(status & _BITUL(31)));
+
+	return (((u64)h) << 32) | l;
+}
+
+static struct clocksource arc_counter_rtc = {
+	.name   = "ARCv2 RTC",
+	.rating = 350,
+	.read   = arc_read_rtc,
+	.mask   = CLOCKSOURCE_MASK(64),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init arc_cs_setup_rtc(struct device_node *node)
+{
+	struct bcr_timer timer;
+	int ret;
+
+	READ_BCR(ARC_REG_TIMERS_BCR, timer);
+	if (!timer.rtc) {
+		pr_warn("Local-64-bit-Ctr clocksource not detected");
+		return -ENXIO;
+	}
+
+	/* Local to CPU hence not usable in SMP */
+	if (IS_ENABLED(CONFIG_SMP)) {
+		pr_warn("Local-64-bit-Ctr not usable in SMP");
+		return -EINVAL;
+	}
+
+	ret = arc_get_timer_clk(node);
+	if (ret)
+		return ret;
+
+	write_aux_reg(AUX_RTC_CTRL, 1);
+
+	return clocksource_register_hz(&arc_counter_rtc, arc_timer_freq);
+}
+CLOCKSOURCE_OF_DECLARE(arc_rtc, "snps,archs-timer-rtc", arc_cs_setup_rtc);
+
+#endif
+
+/*
+ * 32bit TIMER1 to keep counting monotonically and wraparound
+ */
+
+static u64 arc_read_timer1(struct clocksource *cs)
+{
+	return (u64) read_aux_reg(ARC_REG_TIMER1_CNT);
+}
+
+static struct clocksource arc_counter_timer1 = {
+	.name   = "ARC Timer1",
+	.rating = 300,
+	.read   = arc_read_timer1,
+	.mask   = CLOCKSOURCE_MASK(32),
+	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init arc_cs_setup_timer1(struct device_node *node)
+{
+	int ret;
+
+	/* Local to CPU hence not usable in SMP */
+	if (IS_ENABLED(CONFIG_SMP))
+		return -EINVAL;
+
+	ret = arc_get_timer_clk(node);
+	if (ret)
+		return ret;
+
+	write_aux_reg(ARC_REG_TIMER1_LIMIT, ARC_TIMERN_MAX);
+	write_aux_reg(ARC_REG_TIMER1_CNT, 0);
+	write_aux_reg(ARC_REG_TIMER1_CTRL, TIMER_CTRL_NH);
+
+	return clocksource_register_hz(&arc_counter_timer1, arc_timer_freq);
+}
+
+/********** Clock Event Device *********/
+
+static int arc_timer_irq;
+
+/*
+ * Arm the timer to interrupt after @cycles
+ * The distinction for oneshot/periodic is done in arc_event_timer_ack() below
+ */
+static void arc_timer_event_setup(unsigned int cycles)
+{
+	write_aux_reg(ARC_REG_TIMER0_LIMIT, cycles);
+	write_aux_reg(ARC_REG_TIMER0_CNT, 0);	/* start from 0 */
+
+	write_aux_reg(ARC_REG_TIMER0_CTRL, TIMER_CTRL_IE | TIMER_CTRL_NH);
+}
+
+
+static int arc_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	arc_timer_event_setup(delta);
+	return 0;
+}
+
+static int arc_clkevent_set_periodic(struct clock_event_device *dev)
+{
+	/*
+	 * At X Hz, 1 sec = 1000ms -> X cycles;
+	 *		      10ms -> X / 100 cycles
+	 */
+	arc_timer_event_setup(arc_timer_freq / HZ);
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
+	.name			= "ARC Timer0",
+	.features		= CLOCK_EVT_FEAT_ONESHOT |
+				  CLOCK_EVT_FEAT_PERIODIC,
+	.rating			= 300,
+	.set_next_event		= arc_clkevent_set_next_event,
+	.set_state_periodic	= arc_clkevent_set_periodic,
+};
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	/*
+	 * Note that generic IRQ core could have passed @evt for @dev_id if
+	 * irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
+	 */
+	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
+	int irq_reenable = clockevent_state_periodic(evt);
+
+	/*
+	 * Any write to CTRL reg ACks the interrupt, we rewrite the
+	 * Count when [N]ot [H]alted bit.
+	 * And re-arm it if perioid by [I]nterrupt [E]nable bit
+	 */
+	write_aux_reg(ARC_REG_TIMER0_CTRL, irq_reenable | TIMER_CTRL_NH);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+
+static int arc_timer_starting_cpu(unsigned int cpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(evt, arc_timer_freq, 0, ARC_TIMERN_MAX);
+	enable_percpu_irq(arc_timer_irq, 0);
+	return 0;
+}
+
+static int arc_timer_dying_cpu(unsigned int cpu)
+{
+	disable_percpu_irq(arc_timer_irq);
+	return 0;
+}
+
+/*
+ * clockevent setup for boot CPU
+ */
+static int __init arc_clockevent_setup(struct device_node *node)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
+	int ret;
+
+	arc_timer_irq = irq_of_parse_and_map(node, 0);
+	if (arc_timer_irq <= 0) {
+		pr_err("clockevent: missing irq");
+		return -EINVAL;
+	}
+
+	ret = arc_get_timer_clk(node);
+	if (ret) {
+		pr_err("clockevent: missing clk");
+		return ret;
+	}
+
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(arc_timer_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)", evt);
+	if (ret) {
+		pr_err("clockevent: unable to request irq\n");
+		return ret;
+	}
+
+	ret = cpuhp_setup_state(CPUHP_AP_ARC_TIMER_STARTING,
+				"clockevents/arc/timer:starting",
+				arc_timer_starting_cpu,
+				arc_timer_dying_cpu);
+	if (ret) {
+		pr_err("Failed to setup hotplug state");
+		return ret;
+	}
+	return 0;
+}
+
+static int __init arc_of_timer_init(struct device_node *np)
+{
+	static int init_count = 0;
+	int ret;
+
+	if (!init_count) {
+		init_count = 1;
+		ret = arc_clockevent_setup(np);
+	} else {
+		ret = arc_cs_setup_timer1(np);
+	}
+
+	return ret;
+}
+CLOCKSOURCE_OF_DECLARE(arc_clkevt, "snps,arc-timer", arc_of_timer_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/arm_arch_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/arm_arch_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/arm_arch_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/arm_arch_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,6 +81,7 @@ static struct clock_event_device __percp
 static enum ppi_nr arch_timer_uses_ppi = VIRT_PPI;
 static bool arch_timer_c3stop;
 static bool arch_timer_mem_use_virtual;
+static bool arch_counter_suspend_stop;
 
 static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
 
@@ -561,12 +562,12 @@ static u64 arch_counter_get_cntvct_mem(v
  */
 u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct;
 
-static cycle_t arch_counter_read(struct clocksource *cs)
+static u64 arch_counter_read(struct clocksource *cs)
 {
 	return arch_timer_read_counter();
 }
 
-static cycle_t arch_counter_read_cc(const struct cyclecounter *cc)
+static u64 arch_counter_read_cc(const struct cyclecounter *cc)
 {
 	return arch_timer_read_counter();
 }
@@ -576,7 +577,7 @@ static struct clocksource clocksource_co
 	.rating	= 400,
 	.read	= arch_counter_read,
 	.mask	= CLOCKSOURCE_MASK(56),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_SUSPEND_NONSTOP,
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
 static struct cyclecounter cyclecounter = {
@@ -616,6 +617,8 @@ static void __init arch_counter_register
 		arch_timer_read_counter = arch_counter_get_cntvct_mem;
 	}
 
+	if (!arch_counter_suspend_stop)
+		clocksource_counter.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
 	start_count = arch_timer_read_counter();
 	clocksource_register_hz(&clocksource_counter, arch_timer_rate);
 	cyclecounter.mult = clocksource_counter.mult;
@@ -735,7 +738,7 @@ static int __init arch_timer_register(vo
 
 	/* Register and immediately configure the timer on the boot CPU */
 	err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING,
-				"AP_ARM_ARCH_TIMER_STARTING",
+				"clockevents/arm/arch_timer:starting",
 				arch_timer_starting_cpu, arch_timer_dying_cpu);
 	if (err)
 		goto out_unreg_cpupm;
@@ -907,6 +910,10 @@ static int __init arch_timer_of_init(str
 	    of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
 		arch_timer_uses_ppi = PHYS_SECURE_PPI;
 
+	/* On some systems, the counter stops ticking when in suspend. */
+	arch_counter_suspend_stop = of_property_read_bool(np,
+							 "arm,no-tick-in-suspend");
+
 	return arch_timer_init();
 }
 CLOCKSOURCE_OF_DECLARE(armv7_arch_timer, "arm,armv7-timer", arch_timer_of_init);
@@ -964,8 +971,9 @@ static int __init arch_timer_mem_init(st
 	}
 
 	ret= -ENXIO;
-	base = arch_counter_base = of_iomap(best_frame, 0);
-	if (!base) {
+	base = arch_counter_base = of_io_request_and_map(best_frame, 0,
+							 "arch_mem_timer");
+	if (IS_ERR(base)) {
 		pr_err("arch_timer: Can't map frame's registers\n");
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/arm_global_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/arm_global_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/arm_global_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/arm_global_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -195,7 +195,7 @@ static int gt_dying_cpu(unsigned int cpu
 	return 0;
 }
 
-static cycle_t gt_clocksource_read(struct clocksource *cs)
+static u64 gt_clocksource_read(struct clocksource *cs)
 {
 	return gt_counter_read();
 }
@@ -316,7 +316,7 @@ static int __init global_timer_of_regist
 		goto out_irq;
 	
 	err = cpuhp_setup_state(CPUHP_AP_ARM_GLOBAL_TIMER_STARTING,
-				"AP_ARM_GLOBAL_TIMER_STARTING",
+				"clockevents/arm/global_timer:starting",
 				gt_starting_cpu, gt_dying_cpu);
 	if (err)
 		goto out_irq;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/bcm2835_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/bcm2835_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/bcm2835_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/bcm2835_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -96,7 +96,7 @@ static int __init bcm2835_timer_init(str
 	ret = of_property_read_u32(node, "clock-frequency", &freq);
 	if (ret) {
 		pr_err("Can't read clock-frequency");
-		return ret;
+		goto err_iounmap;
 	}
 
 	system_clock = base + REG_COUNTER_LO;
@@ -108,13 +108,15 @@ static int __init bcm2835_timer_init(str
 	irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
 	if (irq <= 0) {
 		pr_err("Can't parse IRQ");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_iounmap;
 	}
 
 	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
 	if (!timer) {
 		pr_err("Can't allocate timer struct\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_iounmap;
 	}
 
 	timer->control = base + REG_CONTROL;
@@ -133,7 +135,7 @@ static int __init bcm2835_timer_init(str
 	ret = setup_irq(irq, &timer->act);
 	if (ret) {
 		pr_err("Can't set up timer IRQ\n");
-		return ret;
+		goto err_iounmap;
 	}
 
 	clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
@@ -141,6 +143,10 @@ static int __init bcm2835_timer_init(str
 	pr_info("bcm2835: system timer (irq = %d)\n", irq);
 
 	return 0;
+
+err_iounmap:
+	iounmap(base);
+	return ret;
 }
 CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
 			bcm2835_timer_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/cadence_ttc_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/cadence_ttc_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/cadence_ttc_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/cadence_ttc_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -158,11 +158,11 @@ static irqreturn_t ttc_clock_event_inter
  *
  * returns: Current timer counter register value
  **/
-static cycle_t __ttc_clocksource_read(struct clocksource *cs)
+static u64 __ttc_clocksource_read(struct clocksource *cs)
 {
 	struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc;
 
-	return (cycle_t)readl_relaxed(timer->base_addr +
+	return (u64)readl_relaxed(timer->base_addr +
 				TTC_COUNT_VAL_OFFSET);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c linux-libre-4.10-rc8-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c
--- linux-libre-4.9-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/clksrc-dbx500-prcmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 
 static void __iomem *clksrc_dbx500_timer_base;
 
-static cycle_t notrace clksrc_dbx500_prcmu_read(struct clocksource *cs)
+static u64 notrace clksrc_dbx500_prcmu_read(struct clocksource *cs)
 {
 	void __iomem *base = clksrc_dbx500_timer_base;
 	u32 count, count2;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/dummy_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/dummy_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/dummy_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/dummy_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@ static int dummy_timer_starting_cpu(unsi
 static int __init dummy_timer_register(void)
 {
 	return cpuhp_setup_state(CPUHP_AP_DUMMY_TIMER_STARTING,
-				 "AP_DUMMY_TIMER_STARTING",
+				 "clockevents/dummy_timer:starting",
 				 dummy_timer_starting_cpu, NULL);
 }
 early_initcall(dummy_timer_register);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/dw_apb_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/dw_apb_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/dw_apb_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/dw_apb_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -348,7 +348,7 @@ void dw_apb_clocksource_start(struct dw_
 	dw_apb_clocksource_read(dw_cs);
 }
 
-static cycle_t __apbt_read_clocksource(struct clocksource *cs)
+static u64 __apbt_read_clocksource(struct clocksource *cs)
 {
 	u32 current_count;
 	struct dw_apb_clocksource *dw_cs =
@@ -357,7 +357,7 @@ static cycle_t __apbt_read_clocksource(s
 	current_count = apbt_readl_relaxed(&dw_cs->timer,
 					APBTMR_N_CURRENT_VALUE);
 
-	return (cycle_t)~current_count;
+	return (u64)~current_count;
 }
 
 static void apbt_restart_clocksource(struct clocksource *cs)
@@ -416,7 +416,7 @@ void dw_apb_clocksource_register(struct
  *
  * @dw_cs:	The clocksource to read.
  */
-cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs)
+u64 dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs)
 {
-	return (cycle_t)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
+	return (u64)~apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/em_sti.c linux-libre-4.10-rc8-gnu/drivers/clocksource/em_sti.c
--- linux-libre-4.9-gnu/drivers/clocksource/em_sti.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/em_sti.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,9 +110,9 @@ static void em_sti_disable(struct em_sti
 	clk_disable_unprepare(p->clk);
 }
 
-static cycle_t em_sti_count(struct em_sti_priv *p)
+static u64 em_sti_count(struct em_sti_priv *p)
 {
-	cycle_t ticks;
+	u64 ticks;
 	unsigned long flags;
 
 	/* the STI hardware buffers the 48-bit count, but to
@@ -121,14 +121,14 @@ static cycle_t em_sti_count(struct em_st
 	 * Always read STI_COUNT_H before STI_COUNT_L.
 	 */
 	raw_spin_lock_irqsave(&p->lock, flags);
-	ticks = (cycle_t)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32;
+	ticks = (u64)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32;
 	ticks |= em_sti_read(p, STI_COUNT_L);
 	raw_spin_unlock_irqrestore(&p->lock, flags);
 
 	return ticks;
 }
 
-static cycle_t em_sti_set_next(struct em_sti_priv *p, cycle_t next)
+static u64 em_sti_set_next(struct em_sti_priv *p, u64 next)
 {
 	unsigned long flags;
 
@@ -198,7 +198,7 @@ static struct em_sti_priv *cs_to_em_sti(
 	return container_of(cs, struct em_sti_priv, cs);
 }
 
-static cycle_t em_sti_clocksource_read(struct clocksource *cs)
+static u64 em_sti_clocksource_read(struct clocksource *cs)
 {
 	return em_sti_count(cs_to_em_sti(cs));
 }
@@ -271,7 +271,7 @@ static int em_sti_clock_event_next(unsig
 				   struct clock_event_device *ced)
 {
 	struct em_sti_priv *p = ced_to_em_sti(ced);
-	cycle_t next;
+	u64 next;
 	int safe;
 
 	next = em_sti_set_next(p, em_sti_count(p) + delta);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/exynos_mct.c linux-libre-4.10-rc8-gnu/drivers/clocksource/exynos_mct.c
--- linux-libre-4.9-gnu/drivers/clocksource/exynos_mct.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/exynos_mct.c	2017-02-12 16:03:20.000000000 -0500
@@ -183,7 +183,7 @@ static u64 exynos4_read_count_64(void)
 		hi2 = readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_U);
 	} while (hi != hi2);
 
-	return ((cycle_t)hi << 32) | lo;
+	return ((u64)hi << 32) | lo;
 }
 
 /**
@@ -199,7 +199,7 @@ static u32 notrace exynos4_read_count_32
 	return readl_relaxed(reg_base + EXYNOS4_MCT_G_CNT_L);
 }
 
-static cycle_t exynos4_frc_read(struct clocksource *cs)
+static u64 exynos4_frc_read(struct clocksource *cs)
 {
 	return exynos4_read_count_32();
 }
@@ -266,7 +266,7 @@ static void exynos4_mct_comp0_stop(void)
 static void exynos4_mct_comp0_start(bool periodic, unsigned long cycles)
 {
 	unsigned int tcon;
-	cycle_t comp_cycle;
+	u64 comp_cycle;
 
 	tcon = readl_relaxed(reg_base + EXYNOS4_MCT_G_TCON);
 
@@ -495,6 +495,7 @@ static int exynos4_mct_dying_cpu(unsigne
 	if (mct_int_type == MCT_INT_SPI) {
 		if (evt->irq != -1)
 			disable_irq_nosync(evt->irq);
+		exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
 	} else {
 		disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 	}
@@ -552,7 +553,7 @@ static int __init exynos4_timer_resource
 
 	/* Install hotplug callbacks which configure the timer on this CPU */
 	err = cpuhp_setup_state(CPUHP_AP_EXYNOS4_MCT_TIMER_STARTING,
-				"AP_EXYNOS4_MCT_TIMER_STARTING",
+				"clockevents/exynos4/mct_timer:starting",
 				exynos4_mct_starting_cpu,
 				exynos4_mct_dying_cpu);
 	if (err)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/h8300_timer16.c linux-libre-4.10-rc8-gnu/drivers/clocksource/h8300_timer16.c
--- linux-libre-4.9-gnu/drivers/clocksource/h8300_timer16.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/h8300_timer16.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,7 @@ static inline struct timer16_priv *cs_to
 	return container_of(cs, struct timer16_priv, cs);
 }
 
-static cycle_t timer16_clocksource_read(struct clocksource *cs)
+static u64 timer16_clocksource_read(struct clocksource *cs)
 {
 	struct timer16_priv *p = cs_to_priv(cs);
 	unsigned long raw, value;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/h8300_tpu.c linux-libre-4.10-rc8-gnu/drivers/clocksource/h8300_tpu.c
--- linux-libre-4.9-gnu/drivers/clocksource/h8300_tpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/h8300_tpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,7 +64,7 @@ static inline struct tpu_priv *cs_to_pri
 	return container_of(cs, struct tpu_priv, cs);
 }
 
-static cycle_t tpu_clocksource_read(struct clocksource *cs)
+static u64 tpu_clocksource_read(struct clocksource *cs)
 {
 	struct tpu_priv *p = cs_to_priv(cs);
 	unsigned long flags;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/i8253.c linux-libre-4.10-rc8-gnu/drivers/clocksource/i8253.c
--- linux-libre-4.9-gnu/drivers/clocksource/i8253.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/i8253.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@ EXPORT_SYMBOL(i8253_lock);
  * to just read by itself. So use jiffies to emulate a free
  * running counter:
  */
-static cycle_t i8253_read(struct clocksource *cs)
+static u64 i8253_read(struct clocksource *cs)
 {
 	static int old_count;
 	static u32 old_jifs;
@@ -83,7 +83,7 @@ static cycle_t i8253_read(struct clockso
 
 	count = (PIT_LATCH - 1) - count;
 
-	return (cycle_t)(jifs * PIT_LATCH) + count;
+	return (u64)(jifs * PIT_LATCH) + count;
 }
 
 static struct clocksource i8253_cs = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/jcore-pit.c linux-libre-4.10-rc8-gnu/drivers/clocksource/jcore-pit.c
--- linux-libre-4.9-gnu/drivers/clocksource/jcore-pit.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/jcore-pit.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@ static notrace u64 jcore_sched_clock_rea
 	return seclo * NSEC_PER_SEC + nsec;
 }
 
-static cycle_t jcore_clocksource_read(struct clocksource *cs)
+static u64 jcore_clocksource_read(struct clocksource *cs)
 {
 	return jcore_sched_clock_read();
 }
@@ -240,7 +240,7 @@ static int __init jcore_pit_init(struct
 	}
 
 	cpuhp_setup_state(CPUHP_AP_JCORE_TIMER_STARTING,
-			  "AP_JCORE_TIMER_STARTING",
+			  "clockevents/jcore:starting",
 			  jcore_pit_local_init, NULL);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/Kconfig linux-libre-4.10-rc8-gnu/drivers/clocksource/Kconfig
--- linux-libre-4.9-gnu/drivers/clocksource/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -282,6 +282,26 @@ config CLKSRC_MPS2
 	select CLKSRC_MMIO
 	select CLKSRC_OF
 
+config ARC_TIMERS
+	bool "Support for 32-bit TIMERn counters in ARC Cores" if COMPILE_TEST
+	depends on GENERIC_CLOCKEVENTS
+	select CLKSRC_OF
+	help
+	  These are legacy 32-bit TIMER0 and TIMER1 counters found on all ARC cores
+	  (ARC700 as well as ARC HS38).
+	  TIMER0 serves as clockevent while TIMER1 provides clocksource
+
+config ARC_TIMERS_64BIT
+	bool "Support for 64-bit counters in ARC HS38 cores" if COMPILE_TEST
+	depends on GENERIC_CLOCKEVENTS
+	depends on ARC_TIMERS
+	select CLKSRC_OF
+	help
+	  This enables 2 different 64-bit timers: RTC (for UP) and GFRC (for SMP)
+	  RTC is implemented inside the core, while GFRC sits outside the core in
+	  ARConnect IP block. Driver automatically picks one of them for clocksource
+	  as appropriate.
+
 config ARM_ARCH_TIMER
 	bool
 	select CLKSRC_OF if OF
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/Makefile linux-libre-4.10-rc8-gnu/drivers/clocksource/Makefile
--- linux-libre-4.9-gnu/drivers/clocksource/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -51,6 +51,7 @@ obj-$(CONFIG_CLKSRC_TI_32K)	+= timer-ti-
 obj-$(CONFIG_CLKSRC_NPS)	+= timer-nps.o
 obj-$(CONFIG_OXNAS_RPS_TIMER)	+= timer-oxnas-rps.o
 
+obj-$(CONFIG_ARC_TIMERS)		+= arc_timer.o
 obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
 obj-$(CONFIG_ARMV7M_SYSTICK)		+= armv7m_systick.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/metag_generic.c linux-libre-4.10-rc8-gnu/drivers/clocksource/metag_generic.c
--- linux-libre-4.9-gnu/drivers/clocksource/metag_generic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/metag_generic.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ static int metag_timer_set_next_event(un
 	return 0;
 }
 
-static cycle_t metag_clocksource_read(struct clocksource *cs)
+static u64 metag_clocksource_read(struct clocksource *cs)
 {
 	return __core_reg_get(TXTIMER);
 }
@@ -154,6 +154,6 @@ int __init metag_generic_timer_init(void
 
 	/* Hook cpu boot to configure the CPU's timers */
 	return cpuhp_setup_state(CPUHP_AP_METAG_TIMER_STARTING,
-				 "AP_METAG_TIMER_STARTING",
+				 "clockevents/metag:starting",
 				 arch_timer_starting_cpu, NULL);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/mips-gic-timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/mips-gic-timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/mips-gic-timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/mips-gic-timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -120,12 +120,12 @@ static int gic_clockevent_init(void)
 	}
 
 	cpuhp_setup_state(CPUHP_AP_MIPS_GIC_TIMER_STARTING,
-			  "AP_MIPS_GIC_TIMER_STARTING", gic_starting_cpu,
-			  gic_dying_cpu);
+			  "clockevents/mips/gic/timer:starting",
+			  gic_starting_cpu, gic_dying_cpu);
 	return 0;
 }
 
-static cycle_t gic_hpt_read(struct clocksource *cs)
+static u64 gic_hpt_read(struct clocksource *cs)
 {
 	return gic_read_count();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/mmio.c linux-libre-4.10-rc8-gnu/drivers/clocksource/mmio.c
--- linux-libre-4.9-gnu/drivers/clocksource/mmio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/mmio.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,24 +20,24 @@ static inline struct clocksource_mmio *t
 	return container_of(c, struct clocksource_mmio, clksrc);
 }
 
-cycle_t clocksource_mmio_readl_up(struct clocksource *c)
+u64 clocksource_mmio_readl_up(struct clocksource *c)
 {
-	return (cycle_t)readl_relaxed(to_mmio_clksrc(c)->reg);
+	return (u64)readl_relaxed(to_mmio_clksrc(c)->reg);
 }
 
-cycle_t clocksource_mmio_readl_down(struct clocksource *c)
+u64 clocksource_mmio_readl_down(struct clocksource *c)
 {
-	return ~(cycle_t)readl_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
+	return ~(u64)readl_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
 }
 
-cycle_t clocksource_mmio_readw_up(struct clocksource *c)
+u64 clocksource_mmio_readw_up(struct clocksource *c)
 {
-	return (cycle_t)readw_relaxed(to_mmio_clksrc(c)->reg);
+	return (u64)readw_relaxed(to_mmio_clksrc(c)->reg);
 }
 
-cycle_t clocksource_mmio_readw_down(struct clocksource *c)
+u64 clocksource_mmio_readw_down(struct clocksource *c)
 {
-	return ~(cycle_t)readw_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
+	return ~(u64)readw_relaxed(to_mmio_clksrc(c)->reg) & c->mask;
 }
 
 /**
@@ -51,7 +51,7 @@ cycle_t clocksource_mmio_readw_down(stru
  */
 int __init clocksource_mmio_init(void __iomem *base, const char *name,
 	unsigned long hz, int rating, unsigned bits,
-	cycle_t (*read)(struct clocksource *))
+	u64 (*read)(struct clocksource *))
 {
 	struct clocksource_mmio *cs;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/moxart_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/moxart_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/moxart_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/moxart_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -161,19 +161,22 @@ static int __init moxart_timer_init(stru
 	timer->base = of_iomap(node, 0);
 	if (!timer->base) {
 		pr_err("%s: of_iomap failed\n", node->full_name);
-		return -ENXIO;
+		ret = -ENXIO;
+		goto out_free;
 	}
 
 	irq = irq_of_parse_and_map(node, 0);
 	if (irq <= 0) {
 		pr_err("%s: irq_of_parse_and_map failed\n", node->full_name);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_unmap;
 	}
 
 	clk = of_clk_get(node, 0);
 	if (IS_ERR(clk))  {
 		pr_err("%s: of_clk_get failed\n", node->full_name);
-		return PTR_ERR(clk);
+		ret = PTR_ERR(clk);
+		goto out_unmap;
 	}
 
 	pclk = clk_get_rate(clk);
@@ -186,7 +189,8 @@ static int __init moxart_timer_init(stru
 		timer->t1_disable_val = ASPEED_TIMER1_DISABLE;
 	} else {
 		pr_err("%s: unknown platform\n", node->full_name);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_unmap;
 	}
 
 	timer->count_per_tick = DIV_ROUND_CLOSEST(pclk, HZ);
@@ -208,14 +212,14 @@ static int __init moxart_timer_init(stru
 				    clocksource_mmio_readl_down);
 	if (ret) {
 		pr_err("%s: clocksource_mmio_init failed\n", node->full_name);
-		return ret;
+		goto out_unmap;
 	}
 
 	ret = request_irq(irq, moxart_timer_interrupt, IRQF_TIMER,
 			  node->name, &timer->clkevt);
 	if (ret) {
 		pr_err("%s: setup_irq failed\n", node->full_name);
-		return ret;
+		goto out_unmap;
 	}
 
 	/* Clear match registers */
@@ -241,6 +245,12 @@ static int __init moxart_timer_init(stru
 	clockevents_config_and_register(&timer->clkevt, pclk, 0x4, 0xfffffffe);
 
 	return 0;
+
+out_unmap:
+	iounmap(timer->base);
+out_free:
+	kfree(timer);
+	return ret;
 }
 CLOCKSOURCE_OF_DECLARE(moxart, "moxa,moxart-timer", moxart_timer_init);
 CLOCKSOURCE_OF_DECLARE(aspeed, "aspeed,ast2400-timer", moxart_timer_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/mxs_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/mxs_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/mxs_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/mxs_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -97,7 +97,7 @@ static void timrot_irq_acknowledge(void)
 		     HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR);
 }
 
-static cycle_t timrotv1_get_cycles(struct clocksource *cs)
+static u64 timrotv1_get_cycles(struct clocksource *cs)
 {
 	return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1))
 			& 0xffff0000) >> 16);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/pxa_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/pxa_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/pxa_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/pxa_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -220,17 +220,16 @@ CLOCKSOURCE_OF_DECLARE(pxa_timer, "marve
 /*
  * Legacy timer init for non device-tree boards.
  */
-void __init pxa_timer_nodt_init(int irq, void __iomem *base,
-	unsigned long clock_tick_rate)
+void __init pxa_timer_nodt_init(int irq, void __iomem *base)
 {
 	struct clk *clk;
 
 	timer_base = base;
 	clk = clk_get(NULL, "OSTIMER0");
-	if (clk && !IS_ERR(clk))
+	if (clk && !IS_ERR(clk)) {
 		clk_prepare_enable(clk);
-	else
+		pxa_timer_common_init(irq, clk_get_rate(clk));
+	} else {
 		pr_crit("%s: unable to get clk\n", __func__);
-
-	pxa_timer_common_init(irq, clock_tick_rate);
+	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/qcom-timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/qcom-timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/qcom-timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/qcom-timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,7 @@ static struct clock_event_device __percp
 
 static void __iomem *source_base;
 
-static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
+static notrace u64 msm_read_timer_count(struct clocksource *cs)
 {
 	return readl_relaxed(source_base + TIMER_COUNT_VAL);
 }
@@ -182,7 +182,7 @@ static int __init msm_timer_init(u32 dgt
 	} else {
 		/* Install and invoke hotplug callbacks */
 		res = cpuhp_setup_state(CPUHP_AP_QCOM_TIMER_STARTING,
-					"AP_QCOM_TIMER_STARTING",
+					"clockevents/qcom/timer:starting",
 					msm_local_timer_starting_cpu,
 					msm_local_timer_dying_cpu);
 		if (res) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/samsung_pwm_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/samsung_pwm_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/samsung_pwm_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/samsung_pwm_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -307,7 +307,7 @@ static void samsung_clocksource_resume(s
 	samsung_time_start(pwm.source_id, true);
 }
 
-static cycle_t notrace samsung_clocksource_read(struct clocksource *c)
+static u64 notrace samsung_clocksource_read(struct clocksource *c)
 {
 	return ~readl_relaxed(pwm.source_reg);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/scx200_hrt.c linux-libre-4.10-rc8-gnu/drivers/clocksource/scx200_hrt.c
--- linux-libre-4.9-gnu/drivers/clocksource/scx200_hrt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/scx200_hrt.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,10 +43,10 @@ MODULE_PARM_DESC(ppm, "+-adjust to actua
 /* The base timer frequency, * 27 if selected */
 #define HRT_FREQ   1000000
 
-static cycle_t read_hrt(struct clocksource *cs)
+static u64 read_hrt(struct clocksource *cs)
 {
 	/* Read the timer value */
-	return (cycle_t) inl(scx200_cb_base + SCx200_TIMER_OFFSET);
+	return (u64) inl(scx200_cb_base + SCx200_TIMER_OFFSET);
 }
 
 static struct clocksource cs_hrt = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/sh_cmt.c linux-libre-4.10-rc8-gnu/drivers/clocksource/sh_cmt.c
--- linux-libre-4.9-gnu/drivers/clocksource/sh_cmt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/sh_cmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -612,7 +612,7 @@ static struct sh_cmt_channel *cs_to_sh_c
 	return container_of(cs, struct sh_cmt_channel, cs);
 }
 
-static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
+static u64 sh_cmt_clocksource_read(struct clocksource *cs)
 {
 	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
 	unsigned long flags, raw;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/sh_tmu.c linux-libre-4.10-rc8-gnu/drivers/clocksource/sh_tmu.c
--- linux-libre-4.9-gnu/drivers/clocksource/sh_tmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/sh_tmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -255,7 +255,7 @@ static struct sh_tmu_channel *cs_to_sh_t
 	return container_of(cs, struct sh_tmu_channel, cs);
 }
 
-static cycle_t sh_tmu_clocksource_read(struct clocksource *cs)
+static u64 sh_tmu_clocksource_read(struct clocksource *cs)
 {
 	struct sh_tmu_channel *ch = cs_to_sh_tmu(cs);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/tcb_clksrc.c linux-libre-4.10-rc8-gnu/drivers/clocksource/tcb_clksrc.c
--- linux-libre-4.9-gnu/drivers/clocksource/tcb_clksrc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/tcb_clksrc.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@
 
 static void __iomem *tcaddr;
 
-static cycle_t tc_get_cycles(struct clocksource *cs)
+static u64 tc_get_cycles(struct clocksource *cs)
 {
 	unsigned long	flags;
 	u32		lower, upper;
@@ -56,7 +56,7 @@ static cycle_t tc_get_cycles(struct cloc
 	return (upper << 16) | lower;
 }
 
-static cycle_t tc_get_cycles32(struct clocksource *cs)
+static u64 tc_get_cycles32(struct clocksource *cs)
 {
 	return __raw_readl(tcaddr + ATMEL_TC_REG(0, CV));
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/time-armada-370-xp.c linux-libre-4.10-rc8-gnu/drivers/clocksource/time-armada-370-xp.c
--- linux-libre-4.9-gnu/drivers/clocksource/time-armada-370-xp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/time-armada-370-xp.c	2017-02-12 16:03:20.000000000 -0500
@@ -320,7 +320,7 @@ static int __init armada_370_xp_timer_co
 	}
 
 	res = cpuhp_setup_state(CPUHP_AP_ARMADA_TIMER_STARTING,
-				"AP_ARMADA_TIMER_STARTING",
+				"clockevents/armada:starting",
 				armada_370_xp_timer_starting_cpu,
 				armada_370_xp_timer_dying_cpu);
 	if (res) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/time-pistachio.c linux-libre-4.10-rc8-gnu/drivers/clocksource/time-pistachio.c
--- linux-libre-4.9-gnu/drivers/clocksource/time-pistachio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/time-pistachio.c	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@ static inline void gpt_writel(void __iom
 	writel(value, base + 0x20 * gpt_id + offset);
 }
 
-static cycle_t notrace
+static u64 notrace
 pistachio_clocksource_read_cycles(struct clocksource *cs)
 {
 	struct pistachio_clocksource *pcs = to_pistachio_clocksource(cs);
@@ -84,7 +84,7 @@ pistachio_clocksource_read_cycles(struct
 	counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0);
 	raw_spin_unlock_irqrestore(&pcs->lock, flags);
 
-	return (cycle_t)~counter;
+	return (u64)~counter;
 }
 
 static u64 notrace pistachio_read_sched_clock(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/timer-atlas7.c linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-atlas7.c
--- linux-libre-4.9-gnu/drivers/clocksource/timer-atlas7.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-atlas7.c	2017-02-12 16:03:20.000000000 -0500
@@ -85,7 +85,7 @@ static irqreturn_t sirfsoc_timer_interru
 }
 
 /* read 64-bit timer counter */
-static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+static u64 sirfsoc_timer_read(struct clocksource *cs)
 {
 	u64 cycles;
 
@@ -221,7 +221,7 @@ static int __init sirfsoc_clockevent_ini
 
 	/* Install and invoke hotplug callbacks */
 	return cpuhp_setup_state(CPUHP_AP_MARCO_TIMER_STARTING,
-				 "AP_MARCO_TIMER_STARTING",
+				 "clockevents/marco:starting",
 				 sirfsoc_local_timer_starting_cpu,
 				 sirfsoc_local_timer_dying_cpu);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/timer-atmel-pit.c linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-atmel-pit.c
--- linux-libre-4.9-gnu/drivers/clocksource/timer-atmel-pit.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-atmel-pit.c	2017-02-12 16:03:20.000000000 -0500
@@ -73,7 +73,7 @@ static inline void pit_write(void __iome
  * Clocksource:  just a monotonic counter of MCK/16 cycles.
  * We don't care whether or not PIT irqs are enabled.
  */
-static cycle_t read_pit_clk(struct clocksource *cs)
+static u64 read_pit_clk(struct clocksource *cs)
 {
 	struct pit_data *data = clksrc_to_pit_data(cs);
 	unsigned long flags;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/timer-atmel-st.c linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-atmel-st.c
--- linux-libre-4.9-gnu/drivers/clocksource/timer-atmel-st.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-atmel-st.c	2017-02-12 16:03:20.000000000 -0500
@@ -92,7 +92,7 @@ static irqreturn_t at91rm9200_timer_inte
 	return IRQ_NONE;
 }
 
-static cycle_t read_clk32k(struct clocksource *cs)
+static u64 read_clk32k(struct clocksource *cs)
 {
 	return read_CRTR();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/timer-nps.c linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-nps.c
--- linux-libre-4.9-gnu/drivers/clocksource/timer-nps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-nps.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,35 +46,62 @@
 /* This array is per cluster of CPUs (Each NPS400 cluster got 256 CPUs) */
 static void *nps_msu_reg_low_addr[NPS_CLUSTER_NUM] __read_mostly;
 
-static unsigned long nps_timer_rate;
+static int __init nps_get_timer_clk(struct device_node *node,
+			     unsigned long *timer_freq,
+			     struct clk **clk)
+{
+	int ret;
 
-static cycle_t nps_clksrc_read(struct clocksource *clksrc)
+	*clk = of_clk_get(node, 0);
+	ret = PTR_ERR_OR_ZERO(*clk);
+	if (ret) {
+		pr_err("timer missing clk");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(*clk);
+	if (ret) {
+		pr_err("Couldn't enable parent clk\n");
+		clk_put(*clk);
+		return ret;
+	}
+
+	*timer_freq = clk_get_rate(*clk);
+	if (!(*timer_freq)) {
+		pr_err("Couldn't get clk rate\n");
+		clk_disable_unprepare(*clk);
+		clk_put(*clk);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static u64 nps_clksrc_read(struct clocksource *clksrc)
 {
 	int cluster = raw_smp_processor_id() >> NPS_CLUSTER_OFFSET;
 
-	return (cycle_t)ioread32be(nps_msu_reg_low_addr[cluster]);
+	return (u64)ioread32be(nps_msu_reg_low_addr[cluster]);
 }
 
-static int __init nps_setup_clocksource(struct device_node *node,
-					struct clk *clk)
+static int __init nps_setup_clocksource(struct device_node *node)
 {
 	int ret, cluster;
+	struct clk *clk;
+	unsigned long nps_timer1_freq;
+
 
 	for (cluster = 0; cluster < NPS_CLUSTER_NUM; cluster++)
 		nps_msu_reg_low_addr[cluster] =
 			nps_host_reg((cluster << NPS_CLUSTER_OFFSET),
-				 NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
+				     NPS_MSU_BLKID, NPS_MSU_TICK_LOW);
 
-	ret = clk_prepare_enable(clk);
-	if (ret) {
-		pr_err("Couldn't enable parent clock\n");
+	ret = nps_get_timer_clk(node, &nps_timer1_freq, &clk);
+	if (ret)
 		return ret;
-	}
-
-	nps_timer_rate = clk_get_rate(clk);
 
-	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "EZnps-tick",
-				    nps_timer_rate, 301, 32, nps_clksrc_read);
+	ret = clocksource_mmio_init(nps_msu_reg_low_addr, "nps-tick",
+				    nps_timer1_freq, 300, 32, nps_clksrc_read);
 	if (ret) {
 		pr_err("Couldn't register clock source.\n");
 		clk_disable_unprepare(clk);
@@ -83,18 +110,175 @@ static int __init nps_setup_clocksource(
 	return ret;
 }
 
-static int __init nps_timer_init(struct device_node *node)
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
+		       nps_setup_clocksource);
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_src, "ezchip,nps400-timer1",
+		       nps_setup_clocksource);
+
+#ifdef CONFIG_EZNPS_MTM_EXT
+#include <soc/nps/mtm.h>
+
+/* Timer related Aux registers */
+#define NPS_REG_TIMER0_TSI	0xFFFFF850
+#define NPS_REG_TIMER0_LIMIT	0x23
+#define NPS_REG_TIMER0_CTRL	0x22
+#define NPS_REG_TIMER0_CNT	0x21
+
+/*
+ * Interrupt Enabled (IE) - re-arm the timer
+ * Not Halted (NH) - is cleared when working with JTAG (for debug)
+ */
+#define TIMER0_CTRL_IE		BIT(0)
+#define TIMER0_CTRL_NH		BIT(1)
+
+static unsigned long nps_timer0_freq;
+static unsigned long nps_timer0_irq;
+
+static void nps_clkevent_rm_thread(void)
+{
+	int thread;
+	unsigned int cflags, enabled_threads;
+
+	hw_schd_save(&cflags);
+
+	enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI);
+
+	/* remove thread from TSI1 */
+	thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+	enabled_threads &= ~(1 << thread);
+	write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads);
+
+	/* Acknowledge and if needed re-arm the timer */
+	if (!enabled_threads)
+		write_aux_reg(NPS_REG_TIMER0_CTRL, TIMER0_CTRL_NH);
+	else
+		write_aux_reg(NPS_REG_TIMER0_CTRL,
+			      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+}
+
+static void nps_clkevent_add_thread(unsigned long delta)
+{
+	int thread;
+	unsigned int cflags, enabled_threads;
+
+	hw_schd_save(&cflags);
+
+	/* add thread to TSI1 */
+	thread = read_aux_reg(CTOP_AUX_THREAD_ID);
+	enabled_threads = read_aux_reg(NPS_REG_TIMER0_TSI);
+	enabled_threads |= (1 << thread);
+	write_aux_reg(NPS_REG_TIMER0_TSI, enabled_threads);
+
+	/* set next timer event */
+	write_aux_reg(NPS_REG_TIMER0_LIMIT, delta);
+	write_aux_reg(NPS_REG_TIMER0_CNT, 0);
+	write_aux_reg(NPS_REG_TIMER0_CTRL,
+		      TIMER0_CTRL_IE | TIMER0_CTRL_NH);
+
+	hw_schd_restore(cflags);
+}
+
+/*
+ * Whenever anyone tries to change modes, we just mask interrupts
+ * and wait for the next event to get set.
+ */
+static int nps_clkevent_set_state(struct clock_event_device *dev)
+{
+	nps_clkevent_rm_thread();
+	disable_percpu_irq(nps_timer0_irq);
+
+	return 0;
+}
+
+static int nps_clkevent_set_next_event(unsigned long delta,
+				       struct clock_event_device *dev)
+{
+	nps_clkevent_add_thread(delta);
+	enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, nps_clockevent_device) = {
+	.name				=	"NPS Timer0",
+	.features			=	CLOCK_EVT_FEAT_ONESHOT,
+	.rating				=	300,
+	.set_next_event			=	nps_clkevent_set_next_event,
+	.set_state_oneshot		=	nps_clkevent_set_state,
+	.set_state_oneshot_stopped	=	nps_clkevent_set_state,
+	.set_state_shutdown		=	nps_clkevent_set_state,
+	.tick_resume			=	nps_clkevent_set_state,
+};
+
+static irqreturn_t timer_irq_handler(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	nps_clkevent_rm_thread();
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static int nps_timer_starting_cpu(unsigned int cpu)
+{
+	struct clock_event_device *evt = this_cpu_ptr(&nps_clockevent_device);
+
+	evt->cpumask = cpumask_of(smp_processor_id());
+
+	clockevents_config_and_register(evt, nps_timer0_freq, 0, ULONG_MAX);
+	enable_percpu_irq(nps_timer0_irq, IRQ_TYPE_NONE);
+
+	return 0;
+}
+
+static int nps_timer_dying_cpu(unsigned int cpu)
+{
+	disable_percpu_irq(nps_timer0_irq);
+	return 0;
+}
+
+static int __init nps_setup_clockevent(struct device_node *node)
 {
 	struct clk *clk;
+	int ret;
 
-	clk = of_clk_get(node, 0);
-	if (IS_ERR(clk)) {
-		pr_err("Can't get timer clock.\n");
-		return PTR_ERR(clk);
+	nps_timer0_irq = irq_of_parse_and_map(node, 0);
+	if (nps_timer0_irq <= 0) {
+		pr_err("clockevent: missing irq");
+		return -EINVAL;
 	}
 
-	return nps_setup_clocksource(node, clk);
+	ret = nps_get_timer_clk(node, &nps_timer0_freq, &clk);
+	if (ret)
+		return ret;
+
+	/* Needs apriori irq_set_percpu_devid() done in intc map function */
+	ret = request_percpu_irq(nps_timer0_irq, timer_irq_handler,
+				 "Timer0 (per-cpu-tick)",
+				 &nps_clockevent_device);
+	if (ret) {
+		pr_err("Couldn't request irq\n");
+		clk_disable_unprepare(clk);
+		return ret;
+	}
+
+	ret = cpuhp_setup_state(CPUHP_AP_ARC_TIMER_STARTING,
+				"clockevents/nps:starting",
+				nps_timer_starting_cpu,
+				nps_timer_dying_cpu);
+	if (ret) {
+		pr_err("Failed to setup hotplug state");
+		clk_disable_unprepare(clk);
+		free_percpu_irq(nps_timer0_irq, &nps_clockevent_device);
+		return ret;
+	}
+
+	return 0;
 }
 
-CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clksrc, "ezchip,nps400-timer",
-		       nps_timer_init);
+CLOCKSOURCE_OF_DECLARE(ezchip_nps400_clk_evt, "ezchip,nps400-timer0",
+		       nps_setup_clockevent);
+#endif /* CONFIG_EZNPS_MTM_EXT */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/timer-prima2.c linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-prima2.c
--- linux-libre-4.9-gnu/drivers/clocksource/timer-prima2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-prima2.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,7 @@ static irqreturn_t sirfsoc_timer_interru
 }
 
 /* read 64-bit timer counter */
-static cycle_t notrace sirfsoc_timer_read(struct clocksource *cs)
+static u64 notrace sirfsoc_timer_read(struct clocksource *cs)
 {
 	u64 cycles;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/timer-sun5i.c linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-sun5i.c
--- linux-libre-4.9-gnu/drivers/clocksource/timer-sun5i.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-sun5i.c	2017-02-12 16:03:20.000000000 -0500
@@ -152,7 +152,7 @@ static irqreturn_t sun5i_timer_interrupt
 	return IRQ_HANDLED;
 }
 
-static cycle_t sun5i_clksrc_read(struct clocksource *clksrc)
+static u64 sun5i_clksrc_read(struct clocksource *clksrc)
 {
 	struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/timer-ti-32k.c linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-ti-32k.c
--- linux-libre-4.9-gnu/drivers/clocksource/timer-ti-32k.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/timer-ti-32k.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,11 +65,11 @@ static inline struct ti_32k *to_ti_32k(s
 	return container_of(cs, struct ti_32k, cs);
 }
 
-static cycle_t notrace ti_32k_read_cycles(struct clocksource *cs)
+static u64 notrace ti_32k_read_cycles(struct clocksource *cs)
 {
 	struct ti_32k *ti = to_ti_32k(cs);
 
-	return (cycle_t)readl_relaxed(ti->counter);
+	return (u64)readl_relaxed(ti->counter);
 }
 
 static struct ti_32k ti_32k_timer = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/clocksource/vt8500_timer.c linux-libre-4.10-rc8-gnu/drivers/clocksource/vt8500_timer.c
--- linux-libre-4.9-gnu/drivers/clocksource/vt8500_timer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/clocksource/vt8500_timer.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@
 
 static void __iomem *regbase;
 
-static cycle_t vt8500_timer_read(struct clocksource *cs)
+static u64 vt8500_timer_read(struct clocksource *cs)
 {
 	int loops = msecs_to_loops(10);
 	writel(3, regbase + TIMER_CTRL_VAL);
@@ -75,7 +75,7 @@ static int vt8500_timer_set_next_event(u
 				    struct clock_event_device *evt)
 {
 	int loops = msecs_to_loops(10);
-	cycle_t alarm = clocksource.read(&clocksource) + cycles;
+	u64 alarm = clocksource.read(&clocksource) + cycles;
 	while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE)
 						&& --loops)
 		cpu_relax();
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/acpi-cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/acpi-cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/acpi-cpufreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/acpi-cpufreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,6 @@ static inline struct acpi_processor_perf
 static struct cpufreq_driver acpi_cpufreq_driver;
 
 static unsigned int acpi_pstate_strict;
-static struct msr __percpu *msrs;
 
 static bool boost_state(unsigned int cpu)
 {
@@ -104,11 +103,10 @@ static bool boost_state(unsigned int cpu
 	return false;
 }
 
-static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
+static int boost_set_msr(bool enable)
 {
-	u32 cpu;
 	u32 msr_addr;
-	u64 msr_mask;
+	u64 msr_mask, val;
 
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_INTEL:
@@ -120,26 +118,31 @@ static void boost_set_msrs(bool enable,
 		msr_mask = MSR_K7_HWCR_CPB_DIS;
 		break;
 	default:
-		return;
+		return -EINVAL;
 	}
 
-	rdmsr_on_cpus(cpumask, msr_addr, msrs);
+	rdmsrl(msr_addr, val);
 
-	for_each_cpu(cpu, cpumask) {
-		struct msr *reg = per_cpu_ptr(msrs, cpu);
-		if (enable)
-			reg->q &= ~msr_mask;
-		else
-			reg->q |= msr_mask;
-	}
+	if (enable)
+		val &= ~msr_mask;
+	else
+		val |= msr_mask;
 
-	wrmsr_on_cpus(cpumask, msr_addr, msrs);
+	wrmsrl(msr_addr, val);
+	return 0;
+}
+
+static void boost_set_msr_each(void *p_en)
+{
+	bool enable = (bool) p_en;
+
+	boost_set_msr(enable);
 }
 
 static int set_boost(int val)
 {
 	get_online_cpus();
-	boost_set_msrs(val, cpu_online_mask);
+	on_each_cpu(boost_set_msr_each, (void *)(long)val, 1);
 	put_online_cpus();
 	pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");
 
@@ -536,46 +539,24 @@ static void free_acpi_perf_data(void)
 	free_percpu(acpi_perf_data);
 }
 
-static int boost_notify(struct notifier_block *nb, unsigned long action,
-		      void *hcpu)
+static int cpufreq_boost_online(unsigned int cpu)
 {
-	unsigned cpu = (long)hcpu;
-	const struct cpumask *cpumask;
-
-	cpumask = get_cpu_mask(cpu);
+	/*
+	 * On the CPU_UP path we simply keep the boost-disable flag
+	 * in sync with the current global state.
+	 */
+	return boost_set_msr(acpi_cpufreq_driver.boost_enabled);
+}
 
+static int cpufreq_boost_down_prep(unsigned int cpu)
+{
 	/*
 	 * Clear the boost-disable bit on the CPU_DOWN path so that
-	 * this cpu cannot block the remaining ones from boosting. On
-	 * the CPU_UP path we simply keep the boost-disable flag in
-	 * sync with the current global state.
+	 * this cpu cannot block the remaining ones from boosting.
 	 */
-
-	switch (action) {
-	case CPU_DOWN_FAILED:
-	case CPU_DOWN_FAILED_FROZEN:
-	case CPU_ONLINE:
-	case CPU_ONLINE_FROZEN:
-		boost_set_msrs(acpi_cpufreq_driver.boost_enabled, cpumask);
-		break;
-
-	case CPU_DOWN_PREPARE:
-	case CPU_DOWN_PREPARE_FROZEN:
-		boost_set_msrs(1, cpumask);
-		break;
-
-	default:
-		break;
-	}
-
-	return NOTIFY_OK;
+	return boost_set_msr(1);
 }
 
-
-static struct notifier_block boost_nb = {
-	.notifier_call          = boost_notify,
-};
-
 /*
  * acpi_cpufreq_early_init - initialize ACPI P-States library
  *
@@ -922,37 +903,35 @@ static struct cpufreq_driver acpi_cpufre
 	.attr		= acpi_cpufreq_attr,
 };
 
+static enum cpuhp_state acpi_cpufreq_online;
+
 static void __init acpi_cpufreq_boost_init(void)
 {
-	if (boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA)) {
-		msrs = msrs_alloc();
-
-		if (!msrs)
-			return;
-
-		acpi_cpufreq_driver.set_boost = set_boost;
-		acpi_cpufreq_driver.boost_enabled = boost_state(0);
-
-		cpu_notifier_register_begin();
+	int ret;
 
-		/* Force all MSRs to the same value */
-		boost_set_msrs(acpi_cpufreq_driver.boost_enabled,
-			       cpu_online_mask);
+	if (!(boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA)))
+		return;
 
-		__register_cpu_notifier(&boost_nb);
+	acpi_cpufreq_driver.set_boost = set_boost;
+	acpi_cpufreq_driver.boost_enabled = boost_state(0);
 
-		cpu_notifier_register_done();
+	/*
+	 * This calls the online callback on all online cpu and forces all
+	 * MSRs to the same value.
+	 */
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "cpufreq/acpi:online",
+				cpufreq_boost_online, cpufreq_boost_down_prep);
+	if (ret < 0) {
+		pr_err("acpi_cpufreq: failed to register hotplug callbacks\n");
+		return;
 	}
+	acpi_cpufreq_online = ret;
 }
 
 static void acpi_cpufreq_boost_exit(void)
 {
-	if (msrs) {
-		unregister_cpu_notifier(&boost_nb);
-
-		msrs_free(msrs);
-		msrs = NULL;
-	}
+	if (acpi_cpufreq_online > 0)
+		cpuhp_remove_state_nocalls(acpi_cpufreq_online);
 }
 
 static int __init acpi_cpufreq_init(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/brcmstb-avs-cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/brcmstb-avs-cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/brcmstb-avs-cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/brcmstb-avs-cpufreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1068 @@
+/*
+ * CPU frequency scaling for Broadcom SoCs with AVS firmware that
+ * supports DVS or DVFS
+ *
+ * Copyright (c) 2016 Broadcom
+ *
+ * This program is free software; 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.
+ */
+
+/*
+ * "AVS" is the name of a firmware developed at Broadcom. It derives
+ * its name from the technique called "Adaptive Voltage Scaling".
+ * Adaptive voltage scaling was the original purpose of this firmware.
+ * The AVS firmware still supports "AVS mode", where all it does is
+ * adaptive voltage scaling. However, on some newer Broadcom SoCs, the
+ * AVS Firmware, despite its unchanged name, also supports DFS mode and
+ * DVFS mode.
+ *
+ * In the context of this document and the related driver, "AVS" by
+ * itself always means the Broadcom firmware and never refers to the
+ * technique called "Adaptive Voltage Scaling".
+ *
+ * The Broadcom STB AVS CPUfreq driver provides voltage and frequency
+ * scaling on Broadcom SoCs using AVS firmware with support for DFS and
+ * DVFS. The AVS firmware is running on its own co-processor. The
+ * driver supports both uniprocessor (UP) and symmetric multiprocessor
+ * (SMP) systems which share clock and voltage across all CPUs.
+ *
+ * Actual voltage and frequency scaling is done solely by the AVS
+ * firmware. This driver does not change frequency or voltage itself.
+ * It provides a standard CPUfreq interface to the rest of the kernel
+ * and to userland. It interfaces with the AVS firmware to effect the
+ * requested changes and to report back the current system status in a
+ * way that is expected by existing tools.
+ */
+
+#include <linux/cpufreq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#endif
+
+/* Max number of arguments AVS calls take */
+#define AVS_MAX_CMD_ARGS	4
+/*
+ * This macro is used to generate AVS parameter register offsets. For
+ * x >= AVS_MAX_CMD_ARGS, it returns 0 to protect against accidental memory
+ * access outside of the parameter range. (Offset 0 is the first parameter.)
+ */
+#define AVS_PARAM_MULT(x)	((x) < AVS_MAX_CMD_ARGS ? (x) : 0)
+
+/* AVS Mailbox Register offsets */
+#define AVS_MBOX_COMMAND	0x00
+#define AVS_MBOX_STATUS		0x04
+#define AVS_MBOX_VOLTAGE0	0x08
+#define AVS_MBOX_TEMP0		0x0c
+#define AVS_MBOX_PV0		0x10
+#define AVS_MBOX_MV0		0x14
+#define AVS_MBOX_PARAM(x)	(0x18 + AVS_PARAM_MULT(x) * sizeof(u32))
+#define AVS_MBOX_REVISION	0x28
+#define AVS_MBOX_PSTATE		0x2c
+#define AVS_MBOX_HEARTBEAT	0x30
+#define AVS_MBOX_MAGIC		0x34
+#define AVS_MBOX_SIGMA_HVT	0x38
+#define AVS_MBOX_SIGMA_SVT	0x3c
+#define AVS_MBOX_VOLTAGE1	0x40
+#define AVS_MBOX_TEMP1		0x44
+#define AVS_MBOX_PV1		0x48
+#define AVS_MBOX_MV1		0x4c
+#define AVS_MBOX_FREQUENCY	0x50
+
+/* AVS Commands */
+#define AVS_CMD_AVAILABLE	0x00
+#define AVS_CMD_DISABLE		0x10
+#define AVS_CMD_ENABLE		0x11
+#define AVS_CMD_S2_ENTER	0x12
+#define AVS_CMD_S2_EXIT		0x13
+#define AVS_CMD_BBM_ENTER	0x14
+#define AVS_CMD_BBM_EXIT	0x15
+#define AVS_CMD_S3_ENTER	0x16
+#define AVS_CMD_S3_EXIT		0x17
+#define AVS_CMD_BALANCE		0x18
+/* PMAP and P-STATE commands */
+#define AVS_CMD_GET_PMAP	0x30
+#define AVS_CMD_SET_PMAP	0x31
+#define AVS_CMD_GET_PSTATE	0x40
+#define AVS_CMD_SET_PSTATE	0x41
+
+/* Different modes AVS supports (for GET_PMAP/SET_PMAP) */
+#define AVS_MODE_AVS		0x0
+#define AVS_MODE_DFS		0x1
+#define AVS_MODE_DVS		0x2
+#define AVS_MODE_DVFS		0x3
+
+/*
+ * PMAP parameter p1
+ * unused:31-24, mdiv_p0:23-16, unused:15-14, pdiv:13-10 , ndiv_int:9-0
+ */
+#define NDIV_INT_SHIFT		0
+#define NDIV_INT_MASK		0x3ff
+#define PDIV_SHIFT		10
+#define PDIV_MASK		0xf
+#define MDIV_P0_SHIFT		16
+#define MDIV_P0_MASK		0xff
+/*
+ * PMAP parameter p2
+ * mdiv_p4:31-24, mdiv_p3:23-16, mdiv_p2:15:8, mdiv_p1:7:0
+ */
+#define MDIV_P1_SHIFT		0
+#define MDIV_P1_MASK		0xff
+#define MDIV_P2_SHIFT		8
+#define MDIV_P2_MASK		0xff
+#define MDIV_P3_SHIFT		16
+#define MDIV_P3_MASK		0xff
+#define MDIV_P4_SHIFT		24
+#define MDIV_P4_MASK		0xff
+
+/* Different P-STATES AVS supports (for GET_PSTATE/SET_PSTATE) */
+#define AVS_PSTATE_P0		0x0
+#define AVS_PSTATE_P1		0x1
+#define AVS_PSTATE_P2		0x2
+#define AVS_PSTATE_P3		0x3
+#define AVS_PSTATE_P4		0x4
+#define AVS_PSTATE_MAX		AVS_PSTATE_P4
+
+/* CPU L2 Interrupt Controller Registers */
+#define AVS_CPU_L2_SET0		0x04
+#define AVS_CPU_L2_INT_MASK	BIT(31)
+
+/* AVS Command Status Values */
+#define AVS_STATUS_CLEAR	0x00
+/* Command/notification accepted */
+#define AVS_STATUS_SUCCESS	0xf0
+/* Command/notification rejected */
+#define AVS_STATUS_FAILURE	0xff
+/* Invalid command/notification (unknown) */
+#define AVS_STATUS_INVALID	0xf1
+/* Non-AVS modes are not supported */
+#define AVS_STATUS_NO_SUPP	0xf2
+/* Cannot set P-State until P-Map supplied */
+#define AVS_STATUS_NO_MAP	0xf3
+/* Cannot change P-Map after initial P-Map set */
+#define AVS_STATUS_MAP_SET	0xf4
+/* Max AVS status; higher numbers are used for debugging */
+#define AVS_STATUS_MAX		0xff
+
+/* Other AVS related constants */
+#define AVS_LOOP_LIMIT		10000
+#define AVS_TIMEOUT		300 /* in ms; expected completion is < 10ms */
+#define AVS_FIRMWARE_MAGIC	0xa11600d1
+
+#define BRCM_AVS_CPUFREQ_PREFIX	"brcmstb-avs"
+#define BRCM_AVS_CPUFREQ_NAME	BRCM_AVS_CPUFREQ_PREFIX "-cpufreq"
+#define BRCM_AVS_CPU_DATA	"brcm,avs-cpu-data-mem"
+#define BRCM_AVS_CPU_INTR	"brcm,avs-cpu-l2-intr"
+#define BRCM_AVS_HOST_INTR	"sw_intr"
+
+struct pmap {
+	unsigned int mode;
+	unsigned int p1;
+	unsigned int p2;
+	unsigned int state;
+};
+
+struct private_data {
+	void __iomem *base;
+	void __iomem *avs_intr_base;
+	struct device *dev;
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+	struct dentry *debugfs;
+#endif
+	struct completion done;
+	struct semaphore sem;
+	struct pmap pmap;
+};
+
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+
+enum debugfs_format {
+	DEBUGFS_NORMAL,
+	DEBUGFS_FLOAT,
+	DEBUGFS_REV,
+};
+
+struct debugfs_data {
+	struct debugfs_entry *entry;
+	struct private_data *priv;
+};
+
+struct debugfs_entry {
+	char *name;
+	u32 offset;
+	fmode_t mode;
+	enum debugfs_format format;
+};
+
+#define DEBUGFS_ENTRY(name, mode, format)	{ \
+	#name, AVS_MBOX_##name, mode, format \
+}
+
+/*
+ * These are used for debugfs only. Otherwise we use AVS_MBOX_PARAM() directly.
+ */
+#define AVS_MBOX_PARAM1		AVS_MBOX_PARAM(0)
+#define AVS_MBOX_PARAM2		AVS_MBOX_PARAM(1)
+#define AVS_MBOX_PARAM3		AVS_MBOX_PARAM(2)
+#define AVS_MBOX_PARAM4		AVS_MBOX_PARAM(3)
+
+/*
+ * This table stores the name, access permissions and offset for each hardware
+ * register and is used to generate debugfs entries.
+ */
+static struct debugfs_entry debugfs_entries[] = {
+	DEBUGFS_ENTRY(COMMAND, S_IWUSR, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(STATUS, S_IWUSR, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(VOLTAGE0, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(TEMP0, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(PV0, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(MV0, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(PARAM1, S_IWUSR, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(PARAM2, S_IWUSR, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(PARAM3, S_IWUSR, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(PARAM4, S_IWUSR, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(REVISION, 0, DEBUGFS_REV),
+	DEBUGFS_ENTRY(PSTATE, 0, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(HEARTBEAT, 0, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(MAGIC, S_IWUSR, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(SIGMA_HVT, 0, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(SIGMA_SVT, 0, DEBUGFS_NORMAL),
+	DEBUGFS_ENTRY(VOLTAGE1, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(TEMP1, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(PV1, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(MV1, 0, DEBUGFS_FLOAT),
+	DEBUGFS_ENTRY(FREQUENCY, 0, DEBUGFS_NORMAL),
+};
+
+static int brcm_avs_target_index(struct cpufreq_policy *, unsigned int);
+
+static char *__strtolower(char *s)
+{
+	char *p;
+
+	for (p = s; *p; p++)
+		*p = tolower(*p);
+
+	return s;
+}
+
+#endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */
+
+static void __iomem *__map_region(const char *name)
+{
+	struct device_node *np;
+	void __iomem *ptr;
+
+	np = of_find_compatible_node(NULL, NULL, name);
+	if (!np)
+		return NULL;
+
+	ptr = of_iomap(np, 0);
+	of_node_put(np);
+
+	return ptr;
+}
+
+static int __issue_avs_command(struct private_data *priv, int cmd, bool is_send,
+			       u32 args[])
+{
+	unsigned long time_left = msecs_to_jiffies(AVS_TIMEOUT);
+	void __iomem *base = priv->base;
+	unsigned int i;
+	int ret;
+	u32 val;
+
+	ret = down_interruptible(&priv->sem);
+	if (ret)
+		return ret;
+
+	/*
+	 * Make sure no other command is currently running: cmd is 0 if AVS
+	 * co-processor is idle. Due to the guard above, we should almost never
+	 * have to wait here.
+	 */
+	for (i = 0, val = 1; val != 0 && i < AVS_LOOP_LIMIT; i++)
+		val = readl(base + AVS_MBOX_COMMAND);
+
+	/* Give the caller a chance to retry if AVS is busy. */
+	if (i == AVS_LOOP_LIMIT) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	/* Clear status before we begin. */
+	writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
+
+	/* We need to send arguments for this command. */
+	if (args && is_send) {
+		for (i = 0; i < AVS_MAX_CMD_ARGS; i++)
+			writel(args[i], base + AVS_MBOX_PARAM(i));
+	}
+
+	/* Protect from spurious interrupts. */
+	reinit_completion(&priv->done);
+
+	/* Now issue the command & tell firmware to wake up to process it. */
+	writel(cmd, base + AVS_MBOX_COMMAND);
+	writel(AVS_CPU_L2_INT_MASK, priv->avs_intr_base + AVS_CPU_L2_SET0);
+
+	/* Wait for AVS co-processor to finish processing the command. */
+	time_left = wait_for_completion_timeout(&priv->done, time_left);
+
+	/*
+	 * If the AVS status is not in the expected range, it means AVS didn't
+	 * complete our command in time, and we return an error. Also, if there
+	 * is no "time left", we timed out waiting for the interrupt.
+	 */
+	val = readl(base + AVS_MBOX_STATUS);
+	if (time_left == 0 || val == 0 || val > AVS_STATUS_MAX) {
+		dev_err(priv->dev, "AVS command %#x didn't complete in time\n",
+			cmd);
+		dev_err(priv->dev, "    Time left: %u ms, AVS status: %#x\n",
+			jiffies_to_msecs(time_left), val);
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	/* This command returned arguments, so we read them back. */
+	if (args && !is_send) {
+		for (i = 0; i < AVS_MAX_CMD_ARGS; i++)
+			args[i] = readl(base + AVS_MBOX_PARAM(i));
+	}
+
+	/* Clear status to tell AVS co-processor we are done. */
+	writel(AVS_STATUS_CLEAR, base + AVS_MBOX_STATUS);
+
+	/* Convert firmware errors to errno's as much as possible. */
+	switch (val) {
+	case AVS_STATUS_INVALID:
+		ret = -EINVAL;
+		break;
+	case AVS_STATUS_NO_SUPP:
+		ret = -ENOTSUPP;
+		break;
+	case AVS_STATUS_NO_MAP:
+		ret = -ENOENT;
+		break;
+	case AVS_STATUS_MAP_SET:
+		ret = -EEXIST;
+		break;
+	case AVS_STATUS_FAILURE:
+		ret = -EIO;
+		break;
+	}
+
+out:
+	up(&priv->sem);
+
+	return ret;
+}
+
+static irqreturn_t irq_handler(int irq, void *data)
+{
+	struct private_data *priv = data;
+
+	/* AVS command completed execution. Wake up __issue_avs_command(). */
+	complete(&priv->done);
+
+	return IRQ_HANDLED;
+}
+
+static char *brcm_avs_mode_to_string(unsigned int mode)
+{
+	switch (mode) {
+	case AVS_MODE_AVS:
+		return "AVS";
+	case AVS_MODE_DFS:
+		return "DFS";
+	case AVS_MODE_DVS:
+		return "DVS";
+	case AVS_MODE_DVFS:
+		return "DVFS";
+	}
+	return NULL;
+}
+
+static void brcm_avs_parse_p1(u32 p1, unsigned int *mdiv_p0, unsigned int *pdiv,
+			      unsigned int *ndiv)
+{
+	*mdiv_p0 = (p1 >> MDIV_P0_SHIFT) & MDIV_P0_MASK;
+	*pdiv = (p1 >> PDIV_SHIFT) & PDIV_MASK;
+	*ndiv = (p1 >> NDIV_INT_SHIFT) & NDIV_INT_MASK;
+}
+
+static void brcm_avs_parse_p2(u32 p2, unsigned int *mdiv_p1,
+			      unsigned int *mdiv_p2, unsigned int *mdiv_p3,
+			      unsigned int *mdiv_p4)
+{
+	*mdiv_p4 = (p2 >> MDIV_P4_SHIFT) & MDIV_P4_MASK;
+	*mdiv_p3 = (p2 >> MDIV_P3_SHIFT) & MDIV_P3_MASK;
+	*mdiv_p2 = (p2 >> MDIV_P2_SHIFT) & MDIV_P2_MASK;
+	*mdiv_p1 = (p2 >> MDIV_P1_SHIFT) & MDIV_P1_MASK;
+}
+
+static int brcm_avs_get_pmap(struct private_data *priv, struct pmap *pmap)
+{
+	u32 args[AVS_MAX_CMD_ARGS];
+	int ret;
+
+	ret = __issue_avs_command(priv, AVS_CMD_GET_PMAP, false, args);
+	if (ret || !pmap)
+		return ret;
+
+	pmap->mode = args[0];
+	pmap->p1 = args[1];
+	pmap->p2 = args[2];
+	pmap->state = args[3];
+
+	return 0;
+}
+
+static int brcm_avs_set_pmap(struct private_data *priv, struct pmap *pmap)
+{
+	u32 args[AVS_MAX_CMD_ARGS];
+
+	args[0] = pmap->mode;
+	args[1] = pmap->p1;
+	args[2] = pmap->p2;
+	args[3] = pmap->state;
+
+	return __issue_avs_command(priv, AVS_CMD_SET_PMAP, true, args);
+}
+
+static int brcm_avs_get_pstate(struct private_data *priv, unsigned int *pstate)
+{
+	u32 args[AVS_MAX_CMD_ARGS];
+	int ret;
+
+	ret = __issue_avs_command(priv, AVS_CMD_GET_PSTATE, false, args);
+	if (ret)
+		return ret;
+	*pstate = args[0];
+
+	return 0;
+}
+
+static int brcm_avs_set_pstate(struct private_data *priv, unsigned int pstate)
+{
+	u32 args[AVS_MAX_CMD_ARGS];
+
+	args[0] = pstate;
+
+	return __issue_avs_command(priv, AVS_CMD_SET_PSTATE, true, args);
+}
+
+static unsigned long brcm_avs_get_voltage(void __iomem *base)
+{
+	return readl(base + AVS_MBOX_VOLTAGE1);
+}
+
+static unsigned long brcm_avs_get_frequency(void __iomem *base)
+{
+	return readl(base + AVS_MBOX_FREQUENCY) * 1000;	/* in kHz */
+}
+
+/*
+ * We determine which frequencies are supported by cycling through all P-states
+ * and reading back what frequency we are running at for each P-state.
+ */
+static struct cpufreq_frequency_table *
+brcm_avs_get_freq_table(struct device *dev, struct private_data *priv)
+{
+	struct cpufreq_frequency_table *table;
+	unsigned int pstate;
+	int i, ret;
+
+	/* Remember P-state for later */
+	ret = brcm_avs_get_pstate(priv, &pstate);
+	if (ret)
+		return ERR_PTR(ret);
+
+	table = devm_kzalloc(dev, (AVS_PSTATE_MAX + 1) * sizeof(*table),
+			     GFP_KERNEL);
+	if (!table)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = AVS_PSTATE_P0; i <= AVS_PSTATE_MAX; i++) {
+		ret = brcm_avs_set_pstate(priv, i);
+		if (ret)
+			return ERR_PTR(ret);
+		table[i].frequency = brcm_avs_get_frequency(priv->base);
+		table[i].driver_data = i;
+	}
+	table[i].frequency = CPUFREQ_TABLE_END;
+
+	/* Restore P-state */
+	ret = brcm_avs_set_pstate(priv, pstate);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return table;
+}
+
+#ifdef CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+
+#define MANT(x)	(unsigned int)(abs((x)) / 1000)
+#define FRAC(x)	(unsigned int)(abs((x)) - abs((x)) / 1000 * 1000)
+
+static int brcm_avs_debug_show(struct seq_file *s, void *data)
+{
+	struct debugfs_data *dbgfs = s->private;
+	void __iomem *base;
+	u32 val, offset;
+
+	if (!dbgfs) {
+		seq_puts(s, "No device pointer\n");
+		return 0;
+	}
+
+	base = dbgfs->priv->base;
+	offset = dbgfs->entry->offset;
+	val = readl(base + offset);
+	switch (dbgfs->entry->format) {
+	case DEBUGFS_NORMAL:
+		seq_printf(s, "%u\n", val);
+		break;
+	case DEBUGFS_FLOAT:
+		seq_printf(s, "%d.%03d\n", MANT(val), FRAC(val));
+		break;
+	case DEBUGFS_REV:
+		seq_printf(s, "%c.%c.%c.%c\n", (val >> 24 & 0xff),
+			   (val >> 16 & 0xff), (val >> 8 & 0xff),
+			   val & 0xff);
+		break;
+	}
+	seq_printf(s, "0x%08x\n", val);
+
+	return 0;
+}
+
+#undef MANT
+#undef FRAC
+
+static ssize_t brcm_avs_seq_write(struct file *file, const char __user *buf,
+				  size_t size, loff_t *ppos)
+{
+	struct seq_file *s = file->private_data;
+	struct debugfs_data *dbgfs = s->private;
+	struct private_data *priv = dbgfs->priv;
+	void __iomem *base, *avs_intr_base;
+	bool use_issue_command = false;
+	unsigned long val, offset;
+	char str[128];
+	int ret;
+	char *str_ptr = str;
+
+	if (size >= sizeof(str))
+		return -E2BIG;
+
+	memset(str, 0, sizeof(str));
+	ret = copy_from_user(str, buf, size);
+	if (ret)
+		return ret;
+
+	base = priv->base;
+	avs_intr_base = priv->avs_intr_base;
+	offset = dbgfs->entry->offset;
+	/*
+	 * Special case writing to "command" entry only: if the string starts
+	 * with a 'c', we use the driver's __issue_avs_command() function.
+	 * Otherwise, we perform a raw write. This should allow testing of raw
+	 * access as well as using the higher level function. (Raw access
+	 * doesn't clear the firmware return status after issuing the command.)
+	 */
+	if (str_ptr[0] == 'c' && offset == AVS_MBOX_COMMAND) {
+		use_issue_command = true;
+		str_ptr++;
+	}
+	if (kstrtoul(str_ptr, 0, &val) != 0)
+		return -EINVAL;
+
+	/*
+	 * Setting the P-state is a special case. We need to update the CPU
+	 * frequency we report.
+	 */
+	if (val == AVS_CMD_SET_PSTATE) {
+		struct cpufreq_policy *policy;
+		unsigned int pstate;
+
+		policy = cpufreq_cpu_get(smp_processor_id());
+		/* Read back the P-state we are about to set */
+		pstate = readl(base + AVS_MBOX_PARAM(0));
+		if (use_issue_command) {
+			ret = brcm_avs_target_index(policy, pstate);
+			return ret ? ret : size;
+		}
+		policy->cur = policy->freq_table[pstate].frequency;
+	}
+
+	if (use_issue_command) {
+		ret = __issue_avs_command(priv, val, false, NULL);
+	} else {
+		/* Locking here is not perfect, but is only for debug. */
+		ret = down_interruptible(&priv->sem);
+		if (ret)
+			return ret;
+
+		writel(val, base + offset);
+		/* We have to wake up the firmware to process a command. */
+		if (offset == AVS_MBOX_COMMAND)
+			writel(AVS_CPU_L2_INT_MASK,
+			       avs_intr_base + AVS_CPU_L2_SET0);
+		up(&priv->sem);
+	}
+
+	return ret ? ret : size;
+}
+
+static struct debugfs_entry *__find_debugfs_entry(const char *name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++)
+		if (strcasecmp(debugfs_entries[i].name, name) == 0)
+			return &debugfs_entries[i];
+
+	return NULL;
+}
+
+static int brcm_avs_debug_open(struct inode *inode, struct file *file)
+{
+	struct debugfs_data *data;
+	fmode_t fmode;
+	int ret;
+
+	/*
+	 * seq_open(), which is called by single_open(), clears "write" access.
+	 * We need write access to some files, so we preserve our access mode
+	 * and restore it.
+	 */
+	fmode = file->f_mode;
+	/*
+	 * Check access permissions even for root. We don't want to be writing
+	 * to read-only registers. Access for regular users has already been
+	 * checked by the VFS layer.
+	 */
+	if ((fmode & FMODE_WRITER) && !(inode->i_mode & S_IWUSR))
+		return -EACCES;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	/*
+	 * We use the same file system operations for all our debug files. To
+	 * produce specific output, we look up the file name upon opening a
+	 * debugfs entry and map it to a memory offset. This offset is then used
+	 * in the generic "show" function to read a specific register.
+	 */
+	data->entry = __find_debugfs_entry(file->f_path.dentry->d_iname);
+	data->priv = inode->i_private;
+
+	ret = single_open(file, brcm_avs_debug_show, data);
+	if (ret)
+		kfree(data);
+	file->f_mode = fmode;
+
+	return ret;
+}
+
+static int brcm_avs_debug_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq_priv = file->private_data;
+	struct debugfs_data *data = seq_priv->private;
+
+	kfree(data);
+	return single_release(inode, file);
+}
+
+static const struct file_operations brcm_avs_debug_ops = {
+	.open		= brcm_avs_debug_open,
+	.read		= seq_read,
+	.write		= brcm_avs_seq_write,
+	.llseek		= seq_lseek,
+	.release	= brcm_avs_debug_release,
+};
+
+static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev)
+{
+	struct private_data *priv = platform_get_drvdata(pdev);
+	struct dentry *dir;
+	int i;
+
+	if (!priv)
+		return;
+
+	dir = debugfs_create_dir(BRCM_AVS_CPUFREQ_NAME, NULL);
+	if (IS_ERR_OR_NULL(dir))
+		return;
+	priv->debugfs = dir;
+
+	for (i = 0; i < ARRAY_SIZE(debugfs_entries); i++) {
+		/*
+		 * The DEBUGFS_ENTRY macro generates uppercase strings. We
+		 * convert them to lowercase before creating the debugfs
+		 * entries.
+		 */
+		char *entry = __strtolower(debugfs_entries[i].name);
+		fmode_t mode = debugfs_entries[i].mode;
+
+		if (!debugfs_create_file(entry, S_IFREG | S_IRUGO | mode,
+					 dir, priv, &brcm_avs_debug_ops)) {
+			priv->debugfs = NULL;
+			debugfs_remove_recursive(dir);
+			break;
+		}
+	}
+}
+
+static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev)
+{
+	struct private_data *priv = platform_get_drvdata(pdev);
+
+	if (priv && priv->debugfs) {
+		debugfs_remove_recursive(priv->debugfs);
+		priv->debugfs = NULL;
+	}
+}
+
+#else
+
+static void brcm_avs_cpufreq_debug_init(struct platform_device *pdev) {}
+static void brcm_avs_cpufreq_debug_exit(struct platform_device *pdev) {}
+
+#endif /* CONFIG_ARM_BRCMSTB_AVS_CPUFREQ_DEBUG */
+
+/*
+ * To ensure the right firmware is running we need to
+ *    - check the MAGIC matches what we expect
+ *    - brcm_avs_get_pmap() doesn't return -ENOTSUPP or -EINVAL
+ * We need to set up our interrupt handling before calling brcm_avs_get_pmap()!
+ */
+static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
+{
+	u32 magic;
+	int rc;
+
+	rc = brcm_avs_get_pmap(priv, NULL);
+	magic = readl(priv->base + AVS_MBOX_MAGIC);
+
+	return (magic == AVS_FIRMWARE_MAGIC) && (rc != -ENOTSUPP) &&
+		(rc != -EINVAL);
+}
+
+static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
+{
+	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+	struct private_data *priv = policy->driver_data;
+
+	return brcm_avs_get_frequency(priv->base);
+}
+
+static int brcm_avs_target_index(struct cpufreq_policy *policy,
+				 unsigned int index)
+{
+	return brcm_avs_set_pstate(policy->driver_data,
+				  policy->freq_table[index].driver_data);
+}
+
+static int brcm_avs_suspend(struct cpufreq_policy *policy)
+{
+	struct private_data *priv = policy->driver_data;
+	int ret;
+
+	ret = brcm_avs_get_pmap(priv, &priv->pmap);
+	if (ret)
+		return ret;
+
+	/*
+	 * We can't use the P-state returned by brcm_avs_get_pmap(), since
+	 * that's the initial P-state from when the P-map was downloaded to the
+	 * AVS co-processor, not necessarily the P-state we are running at now.
+	 * So, we get the current P-state explicitly.
+	 */
+	return brcm_avs_get_pstate(priv, &priv->pmap.state);
+}
+
+static int brcm_avs_resume(struct cpufreq_policy *policy)
+{
+	struct private_data *priv = policy->driver_data;
+	int ret;
+
+	ret = brcm_avs_set_pmap(priv, &priv->pmap);
+	if (ret == -EEXIST) {
+		struct platform_device *pdev  = cpufreq_get_driver_data();
+		struct device *dev = &pdev->dev;
+
+		dev_warn(dev, "PMAP was already set\n");
+		ret = 0;
+	}
+
+	return ret;
+}
+
+/*
+ * All initialization code that we only want to execute once goes here. Setup
+ * code that can be re-tried on every core (if it failed before) can go into
+ * brcm_avs_cpufreq_init().
+ */
+static int brcm_avs_prepare_init(struct platform_device *pdev)
+{
+	struct private_data *priv;
+	struct device *dev;
+	int host_irq, ret;
+
+	dev = &pdev->dev;
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	sema_init(&priv->sem, 1);
+	init_completion(&priv->done);
+	platform_set_drvdata(pdev, priv);
+
+	priv->base = __map_region(BRCM_AVS_CPU_DATA);
+	if (!priv->base) {
+		dev_err(dev, "Couldn't find property %s in device tree.\n",
+			BRCM_AVS_CPU_DATA);
+		return -ENOENT;
+	}
+
+	priv->avs_intr_base = __map_region(BRCM_AVS_CPU_INTR);
+	if (!priv->avs_intr_base) {
+		dev_err(dev, "Couldn't find property %s in device tree.\n",
+			BRCM_AVS_CPU_INTR);
+		ret = -ENOENT;
+		goto unmap_base;
+	}
+
+	host_irq = platform_get_irq_byname(pdev, BRCM_AVS_HOST_INTR);
+	if (host_irq < 0) {
+		dev_err(dev, "Couldn't find interrupt %s -- %d\n",
+			BRCM_AVS_HOST_INTR, host_irq);
+		ret = host_irq;
+		goto unmap_intr_base;
+	}
+
+	ret = devm_request_irq(dev, host_irq, irq_handler, IRQF_TRIGGER_RISING,
+			       BRCM_AVS_HOST_INTR, priv);
+	if (ret) {
+		dev_err(dev, "IRQ request failed: %s (%d) -- %d\n",
+			BRCM_AVS_HOST_INTR, host_irq, ret);
+		goto unmap_intr_base;
+	}
+
+	if (brcm_avs_is_firmware_loaded(priv))
+		return 0;
+
+	dev_err(dev, "AVS firmware is not loaded or doesn't support DVFS\n");
+	ret = -ENODEV;
+
+unmap_intr_base:
+	iounmap(priv->avs_intr_base);
+unmap_base:
+	iounmap(priv->base);
+	platform_set_drvdata(pdev, NULL);
+
+	return ret;
+}
+
+static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy)
+{
+	struct cpufreq_frequency_table *freq_table;
+	struct platform_device *pdev;
+	struct private_data *priv;
+	struct device *dev;
+	int ret;
+
+	pdev = cpufreq_get_driver_data();
+	priv = platform_get_drvdata(pdev);
+	policy->driver_data = priv;
+	dev = &pdev->dev;
+
+	freq_table = brcm_avs_get_freq_table(dev, priv);
+	if (IS_ERR(freq_table)) {
+		ret = PTR_ERR(freq_table);
+		dev_err(dev, "Couldn't determine frequency table (%d).\n", ret);
+		return ret;
+	}
+
+	ret = cpufreq_table_validate_and_show(policy, freq_table);
+	if (ret) {
+		dev_err(dev, "invalid frequency table: %d\n", ret);
+		return ret;
+	}
+
+	/* All cores share the same clock and thus the same policy. */
+	cpumask_setall(policy->cpus);
+
+	ret = __issue_avs_command(priv, AVS_CMD_ENABLE, false, NULL);
+	if (!ret) {
+		unsigned int pstate;
+
+		ret = brcm_avs_get_pstate(priv, &pstate);
+		if (!ret) {
+			policy->cur = freq_table[pstate].frequency;
+			dev_info(dev, "registered\n");
+			return 0;
+		}
+	}
+
+	dev_err(dev, "couldn't initialize driver (%d)\n", ret);
+
+	return ret;
+}
+
+static ssize_t show_brcm_avs_pstate(struct cpufreq_policy *policy, char *buf)
+{
+	struct private_data *priv = policy->driver_data;
+	unsigned int pstate;
+
+	if (brcm_avs_get_pstate(priv, &pstate))
+		return sprintf(buf, "<unknown>\n");
+
+	return sprintf(buf, "%u\n", pstate);
+}
+
+static ssize_t show_brcm_avs_mode(struct cpufreq_policy *policy, char *buf)
+{
+	struct private_data *priv = policy->driver_data;
+	struct pmap pmap;
+
+	if (brcm_avs_get_pmap(priv, &pmap))
+		return sprintf(buf, "<unknown>\n");
+
+	return sprintf(buf, "%s %u\n", brcm_avs_mode_to_string(pmap.mode),
+		pmap.mode);
+}
+
+static ssize_t show_brcm_avs_pmap(struct cpufreq_policy *policy, char *buf)
+{
+	unsigned int mdiv_p0, mdiv_p1, mdiv_p2, mdiv_p3, mdiv_p4;
+	struct private_data *priv = policy->driver_data;
+	unsigned int ndiv, pdiv;
+	struct pmap pmap;
+
+	if (brcm_avs_get_pmap(priv, &pmap))
+		return sprintf(buf, "<unknown>\n");
+
+	brcm_avs_parse_p1(pmap.p1, &mdiv_p0, &pdiv, &ndiv);
+	brcm_avs_parse_p2(pmap.p2, &mdiv_p1, &mdiv_p2, &mdiv_p3, &mdiv_p4);
+
+	return sprintf(buf, "0x%08x 0x%08x %u %u %u %u %u %u %u %u %u\n",
+		pmap.p1, pmap.p2, ndiv, pdiv, mdiv_p0, mdiv_p1, mdiv_p2,
+		mdiv_p3, mdiv_p4, pmap.mode, pmap.state);
+}
+
+static ssize_t show_brcm_avs_voltage(struct cpufreq_policy *policy, char *buf)
+{
+	struct private_data *priv = policy->driver_data;
+
+	return sprintf(buf, "0x%08lx\n", brcm_avs_get_voltage(priv->base));
+}
+
+static ssize_t show_brcm_avs_frequency(struct cpufreq_policy *policy, char *buf)
+{
+	struct private_data *priv = policy->driver_data;
+
+	return sprintf(buf, "0x%08lx\n", brcm_avs_get_frequency(priv->base));
+}
+
+cpufreq_freq_attr_ro(brcm_avs_pstate);
+cpufreq_freq_attr_ro(brcm_avs_mode);
+cpufreq_freq_attr_ro(brcm_avs_pmap);
+cpufreq_freq_attr_ro(brcm_avs_voltage);
+cpufreq_freq_attr_ro(brcm_avs_frequency);
+
+static struct freq_attr *brcm_avs_cpufreq_attr[] = {
+	&cpufreq_freq_attr_scaling_available_freqs,
+	&brcm_avs_pstate,
+	&brcm_avs_mode,
+	&brcm_avs_pmap,
+	&brcm_avs_voltage,
+	&brcm_avs_frequency,
+	NULL
+};
+
+static struct cpufreq_driver brcm_avs_driver = {
+	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+	.verify		= cpufreq_generic_frequency_table_verify,
+	.target_index	= brcm_avs_target_index,
+	.get		= brcm_avs_cpufreq_get,
+	.suspend	= brcm_avs_suspend,
+	.resume		= brcm_avs_resume,
+	.init		= brcm_avs_cpufreq_init,
+	.attr		= brcm_avs_cpufreq_attr,
+	.name		= BRCM_AVS_CPUFREQ_PREFIX,
+};
+
+static int brcm_avs_cpufreq_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = brcm_avs_prepare_init(pdev);
+	if (ret)
+		return ret;
+
+	brcm_avs_driver.driver_data = pdev;
+	ret = cpufreq_register_driver(&brcm_avs_driver);
+	if (!ret)
+		brcm_avs_cpufreq_debug_init(pdev);
+
+	return ret;
+}
+
+static int brcm_avs_cpufreq_remove(struct platform_device *pdev)
+{
+	struct private_data *priv;
+	int ret;
+
+	ret = cpufreq_unregister_driver(&brcm_avs_driver);
+	if (ret)
+		return ret;
+
+	brcm_avs_cpufreq_debug_exit(pdev);
+
+	priv = platform_get_drvdata(pdev);
+	iounmap(priv->base);
+	iounmap(priv->avs_intr_base);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id brcm_avs_cpufreq_match[] = {
+	{ .compatible = BRCM_AVS_CPU_DATA },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, brcm_avs_cpufreq_match);
+
+static struct platform_driver brcm_avs_cpufreq_platdrv = {
+	.driver = {
+		.name	= BRCM_AVS_CPUFREQ_NAME,
+		.of_match_table = brcm_avs_cpufreq_match,
+	},
+	.probe		= brcm_avs_cpufreq_probe,
+	.remove		= brcm_avs_cpufreq_remove,
+};
+module_platform_driver(brcm_avs_cpufreq_platdrv);
+
+MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
+MODULE_DESCRIPTION("CPUfreq driver for Broadcom STB AVS");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cppc_cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cppc_cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cppc_cpufreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cppc_cpufreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -247,3 +247,10 @@ MODULE_DESCRIPTION("CPUFreq driver based
 MODULE_LICENSE("GPL");
 
 late_initcall(cppc_cpufreq_init);
+
+static const struct acpi_device_id cppc_acpi_ids[] = {
+	{ACPI_PROCESSOR_DEVICE_HID, },
+	{}
+};
+
+MODULE_DEVICE_TABLE(acpi, cppc_acpi_ids);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -1526,7 +1526,10 @@ unsigned int cpufreq_get(unsigned int cp
 
 	if (policy) {
 		down_read(&policy->rwsem);
-		ret_freq = __cpufreq_get(policy);
+
+		if (!policy_is_inactive(policy))
+			ret_freq = __cpufreq_get(policy);
+
 		up_read(&policy->rwsem);
 
 		cpufreq_cpu_put(policy);
@@ -2254,17 +2257,19 @@ static int cpufreq_set_policy(struct cpu
  *	Useful for policy notifiers which have different necessities
  *	at different times.
  */
-int cpufreq_update_policy(unsigned int cpu)
+void cpufreq_update_policy(unsigned int cpu)
 {
 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
 	struct cpufreq_policy new_policy;
-	int ret;
 
 	if (!policy)
-		return -ENODEV;
+		return;
 
 	down_write(&policy->rwsem);
 
+	if (policy_is_inactive(policy))
+		goto unlock;
+
 	pr_debug("updating policy for CPU %u\n", cpu);
 	memcpy(&new_policy, policy, sizeof(*policy));
 	new_policy.min = policy->user_policy.min;
@@ -2275,24 +2280,20 @@ int cpufreq_update_policy(unsigned int c
 	 * -> ask driver for current freq and notify governors about a change
 	 */
 	if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
-		if (cpufreq_suspended) {
-			ret = -EAGAIN;
+		if (cpufreq_suspended)
 			goto unlock;
-		}
+
 		new_policy.cur = cpufreq_update_current_freq(policy);
-		if (WARN_ON(!new_policy.cur)) {
-			ret = -EIO;
+		if (WARN_ON(!new_policy.cur))
 			goto unlock;
-		}
 	}
 
-	ret = cpufreq_set_policy(policy, &new_policy);
+	cpufreq_set_policy(policy, &new_policy);
 
 unlock:
 	up_write(&policy->rwsem);
 
 	cpufreq_cpu_put(policy);
-	return ret;
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_conservative.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_conservative.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_conservative.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_conservative.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,16 +37,16 @@ struct cs_dbs_tuners {
 #define DEF_SAMPLING_DOWN_FACTOR		(1)
 #define MAX_SAMPLING_DOWN_FACTOR		(10)
 
-static inline unsigned int get_freq_target(struct cs_dbs_tuners *cs_tuners,
-					   struct cpufreq_policy *policy)
+static inline unsigned int get_freq_step(struct cs_dbs_tuners *cs_tuners,
+					 struct cpufreq_policy *policy)
 {
-	unsigned int freq_target = (cs_tuners->freq_step * policy->max) / 100;
+	unsigned int freq_step = (cs_tuners->freq_step * policy->max) / 100;
 
 	/* max freq cannot be less than 100. But who knows... */
-	if (unlikely(freq_target == 0))
-		freq_target = DEF_FREQUENCY_STEP;
+	if (unlikely(freq_step == 0))
+		freq_step = DEF_FREQUENCY_STEP;
 
-	return freq_target;
+	return freq_step;
 }
 
 /*
@@ -55,10 +55,10 @@ static inline unsigned int get_freq_targ
  * sampling_down_factor, we check, if current idle time is more than 80%
  * (default), then we try to decrease frequency
  *
- * Any frequency increase takes it to the maximum frequency. Frequency reduction
- * happens at minimum steps of 5% (default) of maximum frequency
+ * Frequency updates happen at minimum steps of 5% (default) of maximum
+ * frequency
  */
-static unsigned int cs_dbs_timer(struct cpufreq_policy *policy)
+static unsigned int cs_dbs_update(struct cpufreq_policy *policy)
 {
 	struct policy_dbs_info *policy_dbs = policy->governor_data;
 	struct cs_policy_dbs_info *dbs_info = to_dbs_info(policy_dbs);
@@ -66,6 +66,7 @@ static unsigned int cs_dbs_timer(struct
 	struct dbs_data *dbs_data = policy_dbs->dbs_data;
 	struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
 	unsigned int load = dbs_update(policy);
+	unsigned int freq_step;
 
 	/*
 	 * break out if we 'cannot' reduce the speed as the user might
@@ -82,6 +83,23 @@ static unsigned int cs_dbs_timer(struct
 	if (requested_freq > policy->max || requested_freq < policy->min)
 		requested_freq = policy->cur;
 
+	freq_step = get_freq_step(cs_tuners, policy);
+
+	/*
+	 * Decrease requested_freq one freq_step for each idle period that
+	 * we didn't update the frequency.
+	 */
+	if (policy_dbs->idle_periods < UINT_MAX) {
+		unsigned int freq_steps = policy_dbs->idle_periods * freq_step;
+
+		if (requested_freq > freq_steps)
+			requested_freq -= freq_steps;
+		else
+			requested_freq = policy->min;
+
+		policy_dbs->idle_periods = UINT_MAX;
+	}
+
 	/* Check for frequency increase */
 	if (load > dbs_data->up_threshold) {
 		dbs_info->down_skip = 0;
@@ -90,7 +108,7 @@ static unsigned int cs_dbs_timer(struct
 		if (requested_freq == policy->max)
 			goto out;
 
-		requested_freq += get_freq_target(cs_tuners, policy);
+		requested_freq += freq_step;
 		if (requested_freq > policy->max)
 			requested_freq = policy->max;
 
@@ -106,16 +124,14 @@ static unsigned int cs_dbs_timer(struct
 
 	/* Check for frequency decrease */
 	if (load < cs_tuners->down_threshold) {
-		unsigned int freq_target;
 		/*
 		 * if we cannot reduce the frequency anymore, break out early
 		 */
 		if (requested_freq == policy->min)
 			goto out;
 
-		freq_target = get_freq_target(cs_tuners, policy);
-		if (requested_freq > freq_target)
-			requested_freq -= freq_target;
+		if (requested_freq > freq_step)
+			requested_freq -= freq_step;
 		else
 			requested_freq = policy->min;
 
@@ -305,7 +321,7 @@ static void cs_start(struct cpufreq_poli
 static struct dbs_governor cs_governor = {
 	.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
 	.kobj_type = { .default_attrs = cs_attributes },
-	.gov_dbs_timer = cs_dbs_timer,
+	.gov_dbs_update = cs_dbs_update,
 	.alloc = cs_alloc,
 	.free = cs_free,
 	.init = cs_init,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq-dt.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq-dt.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq-dt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq-dt.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
 #include "cpufreq-dt.h"
 
 struct private_data {
+	struct opp_table *opp_table;
 	struct device *cpu_dev;
 	struct thermal_cooling_device *cdev;
 	const char *reg_name;
@@ -143,6 +144,7 @@ static int resources_available(void)
 static int cpufreq_init(struct cpufreq_policy *policy)
 {
 	struct cpufreq_frequency_table *freq_table;
+	struct opp_table *opp_table = NULL;
 	struct private_data *priv;
 	struct device *cpu_dev;
 	struct clk *cpu_clk;
@@ -186,8 +188,9 @@ static int cpufreq_init(struct cpufreq_p
 	 */
 	name = find_supply_name(cpu_dev);
 	if (name) {
-		ret = dev_pm_opp_set_regulator(cpu_dev, name);
-		if (ret) {
+		opp_table = dev_pm_opp_set_regulators(cpu_dev, &name, 1);
+		if (IS_ERR(opp_table)) {
+			ret = PTR_ERR(opp_table);
 			dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
 				policy->cpu, ret);
 			goto out_put_clk;
@@ -237,6 +240,7 @@ static int cpufreq_init(struct cpufreq_p
 	}
 
 	priv->reg_name = name;
+	priv->opp_table = opp_table;
 
 	ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
 	if (ret) {
@@ -285,7 +289,7 @@ out_free_priv:
 out_free_opp:
 	dev_pm_opp_of_cpumask_remove_table(policy->cpus);
 	if (name)
-		dev_pm_opp_put_regulator(cpu_dev);
+		dev_pm_opp_put_regulators(opp_table);
 out_put_clk:
 	clk_put(cpu_clk);
 
@@ -300,7 +304,7 @@ static int cpufreq_exit(struct cpufreq_p
 	dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
 	dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
 	if (priv->reg_name)
-		dev_pm_opp_put_regulator(priv->cpu_dev);
+		dev_pm_opp_put_regulators(priv->opp_table);
 
 	clk_put(policy->clk);
 	kfree(priv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq-dt-platdev.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq-dt-platdev.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq-dt-platdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq-dt-platdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,11 @@ static const struct of_device_id machine
 	{ .compatible = "allwinner,sun8i-a83t", },
 	{ .compatible = "allwinner,sun8i-h3", },
 
+	{ .compatible = "apm,xgene-shadowcat", },
+
+	{ .compatible = "arm,integrator-ap", },
+	{ .compatible = "arm,integrator-cp", },
+
 	{ .compatible = "hisilicon,hi6220", },
 
 	{ .compatible = "fsl,imx27", },
@@ -34,6 +39,8 @@ static const struct of_device_id machine
 	{ .compatible = "fsl,imx7d", },
 
 	{ .compatible = "marvell,berlin", },
+	{ .compatible = "marvell,pxa250", },
+	{ .compatible = "marvell,pxa270", },
 
 	{ .compatible = "samsung,exynos3250", },
 	{ .compatible = "samsung,exynos4210", },
@@ -50,6 +57,8 @@ static const struct of_device_id machine
 	{ .compatible = "renesas,r7s72100", },
 	{ .compatible = "renesas,r8a73a4", },
 	{ .compatible = "renesas,r8a7740", },
+	{ .compatible = "renesas,r8a7743", },
+	{ .compatible = "renesas,r8a7745", },
 	{ .compatible = "renesas,r8a7778", },
 	{ .compatible = "renesas,r8a7779", },
 	{ .compatible = "renesas,r8a7790", },
@@ -72,6 +81,12 @@ static const struct of_device_id machine
 
 	{ .compatible = "sigma,tango4" },
 
+	{ .compatible = "socionext,uniphier-pro5", },
+	{ .compatible = "socionext,uniphier-pxs2", },
+	{ .compatible = "socionext,uniphier-ld6b", },
+	{ .compatible = "socionext,uniphier-ld11", },
+	{ .compatible = "socionext,uniphier-ld20", },
+
 	{ .compatible = "ti,am33xx", },
 	{ .compatible = "ti,dra7", },
 	{ .compatible = "ti,omap2", },
@@ -81,6 +96,8 @@ static const struct of_device_id machine
 
 	{ .compatible = "xlnx,zynq-7000", },
 
+	{ .compatible = "zte,zx296718", },
+
 	{ }
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_governor.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_governor.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_governor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_governor.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,7 +61,7 @@ ssize_t store_sampling_rate(struct gov_a
 	 * entries can't be freed concurrently.
 	 */
 	list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
-		mutex_lock(&policy_dbs->timer_mutex);
+		mutex_lock(&policy_dbs->update_mutex);
 		/*
 		 * On 32-bit architectures this may race with the
 		 * sample_delay_ns read in dbs_update_util_handler(), but that
@@ -76,7 +76,7 @@ ssize_t store_sampling_rate(struct gov_a
 		 * taken, so it shouldn't be significant.
 		 */
 		gov_update_sample_delay(policy_dbs, 0);
-		mutex_unlock(&policy_dbs->timer_mutex);
+		mutex_unlock(&policy_dbs->update_mutex);
 	}
 
 	return count;
@@ -117,7 +117,7 @@ unsigned int dbs_update(struct cpufreq_p
 	struct policy_dbs_info *policy_dbs = policy->governor_data;
 	struct dbs_data *dbs_data = policy_dbs->dbs_data;
 	unsigned int ignore_nice = dbs_data->ignore_nice_load;
-	unsigned int max_load = 0;
+	unsigned int max_load = 0, idle_periods = UINT_MAX;
 	unsigned int sampling_rate, io_busy, j;
 
 	/*
@@ -215,9 +215,19 @@ unsigned int dbs_update(struct cpufreq_p
 			j_cdbs->prev_load = load;
 		}
 
+		if (time_elapsed > 2 * sampling_rate) {
+			unsigned int periods = time_elapsed / sampling_rate;
+
+			if (periods < idle_periods)
+				idle_periods = periods;
+		}
+
 		if (load > max_load)
 			max_load = load;
 	}
+
+	policy_dbs->idle_periods = idle_periods;
+
 	return max_load;
 }
 EXPORT_SYMBOL_GPL(dbs_update);
@@ -236,9 +246,9 @@ static void dbs_work_handler(struct work
 	 * Make sure cpufreq_governor_limits() isn't evaluating load or the
 	 * ondemand governor isn't updating the sampling rate in parallel.
 	 */
-	mutex_lock(&policy_dbs->timer_mutex);
-	gov_update_sample_delay(policy_dbs, gov->gov_dbs_timer(policy));
-	mutex_unlock(&policy_dbs->timer_mutex);
+	mutex_lock(&policy_dbs->update_mutex);
+	gov_update_sample_delay(policy_dbs, gov->gov_dbs_update(policy));
+	mutex_unlock(&policy_dbs->update_mutex);
 
 	/* Allow the utilization update handler to queue up more work. */
 	atomic_set(&policy_dbs->work_count, 0);
@@ -348,7 +358,7 @@ static struct policy_dbs_info *alloc_pol
 		return NULL;
 
 	policy_dbs->policy = policy;
-	mutex_init(&policy_dbs->timer_mutex);
+	mutex_init(&policy_dbs->update_mutex);
 	atomic_set(&policy_dbs->work_count, 0);
 	init_irq_work(&policy_dbs->irq_work, dbs_irq_work);
 	INIT_WORK(&policy_dbs->work, dbs_work_handler);
@@ -367,7 +377,7 @@ static void free_policy_dbs_info(struct
 {
 	int j;
 
-	mutex_destroy(&policy_dbs->timer_mutex);
+	mutex_destroy(&policy_dbs->update_mutex);
 
 	for_each_cpu(j, policy_dbs->policy->related_cpus) {
 		struct cpu_dbs_info *j_cdbs = &per_cpu(cpu_dbs, j);
@@ -547,10 +557,10 @@ void cpufreq_dbs_governor_limits(struct
 {
 	struct policy_dbs_info *policy_dbs = policy->governor_data;
 
-	mutex_lock(&policy_dbs->timer_mutex);
+	mutex_lock(&policy_dbs->update_mutex);
 	cpufreq_policy_apply_limits(policy);
 	gov_update_sample_delay(policy_dbs, 0);
 
-	mutex_unlock(&policy_dbs->timer_mutex);
+	mutex_unlock(&policy_dbs->update_mutex);
 }
 EXPORT_SYMBOL_GPL(cpufreq_dbs_governor_limits);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_governor.h linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_governor.h
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_governor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_governor.h	2017-02-12 16:03:20.000000000 -0500
@@ -85,7 +85,7 @@ struct policy_dbs_info {
 	 * Per policy mutex that serializes load evaluation from limit-change
 	 * and work-handler.
 	 */
-	struct mutex timer_mutex;
+	struct mutex update_mutex;
 
 	u64 last_sample_time;
 	s64 sample_delay_ns;
@@ -97,6 +97,7 @@ struct policy_dbs_info {
 	struct list_head list;
 	/* Multiplier for increasing sample delay temporarily. */
 	unsigned int rate_mult;
+	unsigned int idle_periods;	/* For conservative */
 	/* Status indicators */
 	bool is_shared;		/* This object is used by multiple CPUs */
 	bool work_in_progress;	/* Work is being queued up or in progress */
@@ -135,7 +136,7 @@ struct dbs_governor {
 	 */
 	struct dbs_data *gdbs_data;
 
-	unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy);
+	unsigned int (*gov_dbs_update)(struct cpufreq_policy *policy);
 	struct policy_dbs_info *(*alloc)(void);
 	void (*free)(struct policy_dbs_info *policy_dbs);
 	int (*init)(struct dbs_data *dbs_data);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_ondemand.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_ondemand.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_ondemand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_ondemand.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #define MAX_SAMPLING_DOWN_FACTOR		(100000)
 #define MICRO_FREQUENCY_UP_THRESHOLD		(95)
 #define MICRO_FREQUENCY_MIN_SAMPLE_RATE		(10000)
-#define MIN_FREQUENCY_UP_THRESHOLD		(11)
+#define MIN_FREQUENCY_UP_THRESHOLD		(1)
 #define MAX_FREQUENCY_UP_THRESHOLD		(100)
 
 static struct od_ops od_ops;
@@ -169,7 +169,7 @@ static void od_update(struct cpufreq_pol
 	}
 }
 
-static unsigned int od_dbs_timer(struct cpufreq_policy *policy)
+static unsigned int od_dbs_update(struct cpufreq_policy *policy)
 {
 	struct policy_dbs_info *policy_dbs = policy->governor_data;
 	struct dbs_data *dbs_data = policy_dbs->dbs_data;
@@ -191,7 +191,7 @@ static unsigned int od_dbs_timer(struct
 	od_update(policy);
 
 	if (dbs_info->freq_lo) {
-		/* Setup timer for SUB_SAMPLE */
+		/* Setup SUB_SAMPLE */
 		dbs_info->sample_type = OD_SUB_SAMPLE;
 		return dbs_info->freq_hi_delay_us;
 	}
@@ -255,11 +255,11 @@ static ssize_t store_sampling_down_facto
 	list_for_each_entry(policy_dbs, &attr_set->policy_list, list) {
 		/*
 		 * Doing this without locking might lead to using different
-		 * rate_mult values in od_update() and od_dbs_timer().
+		 * rate_mult values in od_update() and od_dbs_update().
 		 */
-		mutex_lock(&policy_dbs->timer_mutex);
+		mutex_lock(&policy_dbs->update_mutex);
 		policy_dbs->rate_mult = 1;
-		mutex_unlock(&policy_dbs->timer_mutex);
+		mutex_unlock(&policy_dbs->update_mutex);
 	}
 
 	return count;
@@ -374,8 +374,7 @@ static int od_init(struct dbs_data *dbs_
 		dbs_data->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
 		/*
 		 * 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.
+		 * not depending on HZ, but fixed (very low).
 		*/
 		dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
 	} else {
@@ -415,7 +414,7 @@ static struct od_ops od_ops = {
 static struct dbs_governor od_dbs_gov = {
 	.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
 	.kobj_type = { .default_attrs = od_attributes },
-	.gov_dbs_timer = od_dbs_timer,
+	.gov_dbs_update = od_dbs_update,
 	.alloc = od_alloc,
 	.free = od_free,
 	.init = od_init,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_stats.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_stats.c
--- linux-libre-4.9-gnu/drivers/cpufreq/cpufreq_stats.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/cpufreq_stats.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,18 @@ static int cpufreq_stats_update(struct c
 	return 0;
 }
 
+static void cpufreq_stats_clear_table(struct cpufreq_stats *stats)
+{
+	unsigned int count = stats->max_state;
+
+	memset(stats->time_in_state, 0, count * sizeof(u64));
+#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
+	memset(stats->trans_table, 0, count * count * sizeof(int));
+#endif
+	stats->last_time = get_jiffies_64();
+	stats->total_trans = 0;
+}
+
 static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf)
 {
 	return sprintf(buf, "%d\n", policy->stats->total_trans);
@@ -64,6 +76,14 @@ static ssize_t show_time_in_state(struct
 	return len;
 }
 
+static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf,
+			   size_t count)
+{
+	/* We don't care what is written to the attribute. */
+	cpufreq_stats_clear_table(policy->stats);
+	return count;
+}
+
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
 static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
 {
@@ -113,10 +133,12 @@ cpufreq_freq_attr_ro(trans_table);
 
 cpufreq_freq_attr_ro(total_trans);
 cpufreq_freq_attr_ro(time_in_state);
+cpufreq_freq_attr_wo(reset);
 
 static struct attribute *default_attrs[] = {
 	&total_trans.attr,
 	&time_in_state.attr,
+	&reset.attr,
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
 	&trans_table.attr,
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/ia64-acpi-cpufreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pal.h>
 
 #include <linux/acpi.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/integrator-cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/integrator-cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/integrator-cpufreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/integrator-cpufreq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,239 +0,0 @@
-/*
- *  Copyright (C) 2001-2002 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * CPU support functions
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/cpufreq.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <asm/mach-types.h>
-#include <asm/hardware/icst.h>
-
-static void __iomem *cm_base;
-/* The cpufreq driver only use the OSC register */
-#define INTEGRATOR_HDR_OSC_OFFSET       0x08
-#define INTEGRATOR_HDR_LOCK_OFFSET      0x14
-
-static struct cpufreq_driver integrator_driver;
-
-static const struct icst_params lclk_params = {
-	.ref		= 24000000,
-	.vco_max	= ICST525_VCO_MAX_5V,
-	.vco_min	= ICST525_VCO_MIN,
-	.vd_min		= 8,
-	.vd_max		= 132,
-	.rd_min		= 24,
-	.rd_max		= 24,
-	.s2div		= icst525_s2div,
-	.idx2s		= icst525_idx2s,
-};
-
-static const struct icst_params cclk_params = {
-	.ref		= 24000000,
-	.vco_max	= ICST525_VCO_MAX_5V,
-	.vco_min	= ICST525_VCO_MIN,
-	.vd_min		= 12,
-	.vd_max		= 160,
-	.rd_min		= 24,
-	.rd_max		= 24,
-	.s2div		= icst525_s2div,
-	.idx2s		= icst525_idx2s,
-};
-
-/*
- * Validate the speed policy.
- */
-static int integrator_verify_policy(struct cpufreq_policy *policy)
-{
-	struct icst_vco vco;
-
-	cpufreq_verify_within_cpu_limits(policy);
-
-	vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
-	policy->max = icst_hz(&cclk_params, vco) / 1000;
-
-	vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
-	policy->min = icst_hz(&cclk_params, vco) / 1000;
-
-	cpufreq_verify_within_cpu_limits(policy);
-	return 0;
-}
-
-
-static int integrator_set_target(struct cpufreq_policy *policy,
-				 unsigned int target_freq,
-				 unsigned int relation)
-{
-	cpumask_t cpus_allowed;
-	int cpu = policy->cpu;
-	struct icst_vco vco;
-	struct cpufreq_freqs freqs;
-	u_int cm_osc;
-
-	/*
-	 * Save this threads cpus_allowed mask.
-	 */
-	cpus_allowed = current->cpus_allowed;
-
-	/*
-	 * Bind to the specified CPU.  When this call returns,
-	 * we should be running on the right CPU.
-	 */
-	set_cpus_allowed_ptr(current, cpumask_of(cpu));
-	BUG_ON(cpu != smp_processor_id());
-
-	/* get current setting */
-	cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
-	if (machine_is_integrator())
-		vco.s = (cm_osc >> 8) & 7;
-	else if (machine_is_cintegrator())
-		vco.s = 1;
-	vco.v = cm_osc & 255;
-	vco.r = 22;
-	freqs.old = icst_hz(&cclk_params, vco) / 1000;
-
-	/* icst_hz_to_vco rounds down -- so we need the next
-	 * larger freq in case of CPUFREQ_RELATION_L.
-	 */
-	if (relation == CPUFREQ_RELATION_L)
-		target_freq += 999;
-	if (target_freq > policy->max)
-		target_freq = policy->max;
-	vco = icst_hz_to_vco(&cclk_params, target_freq * 1000);
-	freqs.new = icst_hz(&cclk_params, vco) / 1000;
-
-	if (freqs.old == freqs.new) {
-		set_cpus_allowed_ptr(current, &cpus_allowed);
-		return 0;
-	}
-
-	cpufreq_freq_transition_begin(policy, &freqs);
-
-	cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
-	if (machine_is_integrator()) {
-		cm_osc &= 0xfffff800;
-		cm_osc |= vco.s << 8;
-	} else if (machine_is_cintegrator()) {
-		cm_osc &= 0xffffff00;
-	}
-	cm_osc |= vco.v;
-
-	__raw_writel(0xa05f, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
-	__raw_writel(cm_osc, cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-	__raw_writel(0, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
-
-	/*
-	 * Restore the CPUs allowed mask.
-	 */
-	set_cpus_allowed_ptr(current, &cpus_allowed);
-
-	cpufreq_freq_transition_end(policy, &freqs, 0);
-
-	return 0;
-}
-
-static unsigned int integrator_get(unsigned int cpu)
-{
-	cpumask_t cpus_allowed;
-	unsigned int current_freq;
-	u_int cm_osc;
-	struct icst_vco vco;
-
-	cpus_allowed = current->cpus_allowed;
-
-	set_cpus_allowed_ptr(current, cpumask_of(cpu));
-	BUG_ON(cpu != smp_processor_id());
-
-	/* detect memory etc. */
-	cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
-	if (machine_is_integrator())
-		vco.s = (cm_osc >> 8) & 7;
-	else
-		vco.s = 1;
-	vco.v = cm_osc & 255;
-	vco.r = 22;
-
-	current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
-
-	set_cpus_allowed_ptr(current, &cpus_allowed);
-
-	return current_freq;
-}
-
-static int integrator_cpufreq_init(struct cpufreq_policy *policy)
-{
-
-	/* set default policy and cpuinfo */
-	policy->max = policy->cpuinfo.max_freq = 160000;
-	policy->min = policy->cpuinfo.min_freq = 12000;
-	policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
-
-	return 0;
-}
-
-static struct cpufreq_driver integrator_driver = {
-	.flags		= CPUFREQ_NEED_INITIAL_FREQ_CHECK,
-	.verify		= integrator_verify_policy,
-	.target		= integrator_set_target,
-	.get		= integrator_get,
-	.init		= integrator_cpufreq_init,
-	.name		= "integrator",
-};
-
-static int __init integrator_cpufreq_probe(struct platform_device *pdev)
-{
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
-
-	cm_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!cm_base)
-		return -ENODEV;
-
-	return cpufreq_register_driver(&integrator_driver);
-}
-
-static int __exit integrator_cpufreq_remove(struct platform_device *pdev)
-{
-	return cpufreq_unregister_driver(&integrator_driver);
-}
-
-static const struct of_device_id integrator_cpufreq_match[] = {
-	{ .compatible = "arm,core-module-integrator"},
-	{ },
-};
-
-MODULE_DEVICE_TABLE(of, integrator_cpufreq_match);
-
-static struct platform_driver integrator_cpufreq_driver = {
-	.driver = {
-		.name = "integrator-cpufreq",
-		.of_match_table = integrator_cpufreq_match,
-	},
-	.remove = __exit_p(integrator_cpufreq_remove),
-};
-
-module_platform_driver_probe(integrator_cpufreq_driver,
-			     integrator_cpufreq_probe);
-
-MODULE_AUTHOR("Russell M. King");
-MODULE_DESCRIPTION("cpufreq driver for ARM Integrator CPUs");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/intel_pstate.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/intel_pstate.c
--- linux-libre-4.9-gnu/drivers/cpufreq/intel_pstate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/intel_pstate.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,8 @@
 #include <asm/cpufeature.h>
 #include <asm/intel-family.h>
 
+#define INTEL_CPUFREQ_TRANSITION_LATENCY	20000
+
 #define ATOM_RATIOS		0x66a
 #define ATOM_VIDS		0x66b
 #define ATOM_TURBO_RATIOS	0x66c
@@ -44,6 +46,7 @@
 
 #ifdef CONFIG_ACPI
 #include <acpi/processor.h>
+#include <acpi/cppc_acpi.h>
 #endif
 
 #define FRAC_BITS 8
@@ -52,6 +55,8 @@
 
 #define EXT_BITS 6
 #define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS)
+#define fp_ext_toint(X) ((X) >> EXT_FRAC_BITS)
+#define int_ext_tofp(X) ((int64_t)(X) << EXT_FRAC_BITS)
 
 static inline int32_t mul_fp(int32_t x, int32_t y)
 {
@@ -122,6 +127,8 @@ struct sample {
  * @scaling:		Scaling factor to  convert frequency to cpufreq
  *			frequency units
  * @turbo_pstate:	Max Turbo P state possible for this platform
+ * @max_freq:		@max_pstate frequency in cpufreq units
+ * @turbo_freq:		@turbo_pstate frequency in cpufreq units
  *
  * Stores the per cpu model P state limits and current P state.
  */
@@ -132,6 +139,8 @@ struct pstate_data {
 	int	max_pstate_physical;
 	int	scaling;
 	int	turbo_pstate;
+	unsigned int max_freq;
+	unsigned int turbo_freq;
 };
 
 /**
@@ -177,6 +186,48 @@ struct _pid {
 };
 
 /**
+ * struct perf_limits - Store user and policy limits
+ * @no_turbo:		User requested turbo state from intel_pstate sysfs
+ * @turbo_disabled:	Platform turbo status either from msr
+ *			MSR_IA32_MISC_ENABLE or when maximum available pstate
+ *			matches the maximum turbo pstate
+ * @max_perf_pct:	Effective maximum performance limit in percentage, this
+ *			is minimum of either limits enforced by cpufreq policy
+ *			or limits from user set limits via intel_pstate sysfs
+ * @min_perf_pct:	Effective minimum performance limit in percentage, this
+ *			is maximum of either limits enforced by cpufreq policy
+ *			or limits from user set limits via intel_pstate sysfs
+ * @max_perf:		This is a scaled value between 0 to 255 for max_perf_pct
+ *			This value is used to limit max pstate
+ * @min_perf:		This is a scaled value between 0 to 255 for min_perf_pct
+ *			This value is used to limit min pstate
+ * @max_policy_pct:	The maximum performance in percentage enforced by
+ *			cpufreq setpolicy interface
+ * @max_sysfs_pct:	The maximum performance in percentage enforced by
+ *			intel pstate sysfs interface, unused when per cpu
+ *			controls are enforced
+ * @min_policy_pct:	The minimum performance in percentage enforced by
+ *			cpufreq setpolicy interface
+ * @min_sysfs_pct:	The minimum performance in percentage enforced by
+ *			intel pstate sysfs interface, unused when per cpu
+ *			controls are enforced
+ *
+ * Storage for user and policy defined limits.
+ */
+struct perf_limits {
+	int no_turbo;
+	int turbo_disabled;
+	int max_perf_pct;
+	int min_perf_pct;
+	int32_t max_perf;
+	int32_t min_perf;
+	int max_policy_pct;
+	int max_sysfs_pct;
+	int min_policy_pct;
+	int min_sysfs_pct;
+};
+
+/**
  * struct cpudata -	Per CPU instance data storage
  * @cpu:		CPU number for this instance data
  * @policy:		CPUFreq policy value
@@ -194,8 +245,19 @@ struct _pid {
  * @prev_cummulative_iowait: IO Wait time difference from last and
  *			current sample
  * @sample:		Storage for storing last Sample data
+ * @perf_limits:	Pointer to perf_limit unique to this CPU
+ *			Not all field in the structure are applicable
+ *			when per cpu controls are enforced
  * @acpi_perf_data:	Stores ACPI perf information read from _PSS
  * @valid_pss_table:	Set to true for valid ACPI _PSS entries found
+ * @epp_powersave:	Last saved HWP energy performance preference
+ *			(EPP) or energy performance bias (EPB),
+ *			when policy switched to performance
+ * @epp_policy:		Last saved policy used to set EPP/EPB
+ * @epp_default:	Power on default HWP energy performance
+ *			preference/bias
+ * @epp_saved:		Saved EPP/EPB during system suspend or CPU offline
+ *			operation
  *
  * This structure stores per CPU instance data for all CPUs.
  */
@@ -217,11 +279,16 @@ struct cpudata {
 	u64	prev_tsc;
 	u64	prev_cummulative_iowait;
 	struct sample sample;
+	struct perf_limits *perf_limits;
 #ifdef CONFIG_ACPI
 	struct acpi_processor_performance acpi_perf_data;
 	bool valid_pss_table;
 #endif
 	unsigned int iowait_boost;
+	s16 epp_powersave;
+	s16 epp_policy;
+	s16 epp_default;
+	s16 epp_saved;
 };
 
 static struct cpudata **all_cpu_data;
@@ -235,7 +302,6 @@ static struct cpudata **all_cpu_data;
  * @p_gain_pct:		PID proportional gain
  * @i_gain_pct:		PID integral gain
  * @d_gain_pct:		PID derivative gain
- * @boost_iowait:	Whether or not to use iowait boosting.
  *
  * Stores per CPU model static PID configuration data.
  */
@@ -247,7 +313,6 @@ struct pstate_adjust_policy {
 	int p_gain_pct;
 	int d_gain_pct;
 	int i_gain_pct;
-	bool boost_iowait;
 };
 
 /**
@@ -291,58 +356,19 @@ static inline int32_t get_target_pstate_
 static struct pstate_adjust_policy pid_params __read_mostly;
 static struct pstate_funcs pstate_funcs __read_mostly;
 static int hwp_active __read_mostly;
+static bool per_cpu_limits __read_mostly;
 
 #ifdef CONFIG_ACPI
 static bool acpi_ppc;
 #endif
 
-/**
- * struct perf_limits - Store user and policy limits
- * @no_turbo:		User requested turbo state from intel_pstate sysfs
- * @turbo_disabled:	Platform turbo status either from msr
- *			MSR_IA32_MISC_ENABLE or when maximum available pstate
- *			matches the maximum turbo pstate
- * @max_perf_pct:	Effective maximum performance limit in percentage, this
- *			is minimum of either limits enforced by cpufreq policy
- *			or limits from user set limits via intel_pstate sysfs
- * @min_perf_pct:	Effective minimum performance limit in percentage, this
- *			is maximum of either limits enforced by cpufreq policy
- *			or limits from user set limits via intel_pstate sysfs
- * @max_perf:		This is a scaled value between 0 to 255 for max_perf_pct
- *			This value is used to limit max pstate
- * @min_perf:		This is a scaled value between 0 to 255 for min_perf_pct
- *			This value is used to limit min pstate
- * @max_policy_pct:	The maximum performance in percentage enforced by
- *			cpufreq setpolicy interface
- * @max_sysfs_pct:	The maximum performance in percentage enforced by
- *			intel pstate sysfs interface
- * @min_policy_pct:	The minimum performance in percentage enforced by
- *			cpufreq setpolicy interface
- * @min_sysfs_pct:	The minimum performance in percentage enforced by
- *			intel pstate sysfs interface
- *
- * Storage for user and policy defined limits.
- */
-struct perf_limits {
-	int no_turbo;
-	int turbo_disabled;
-	int max_perf_pct;
-	int min_perf_pct;
-	int32_t max_perf;
-	int32_t min_perf;
-	int max_policy_pct;
-	int max_sysfs_pct;
-	int min_policy_pct;
-	int min_sysfs_pct;
-};
-
 static struct perf_limits performance_limits = {
 	.no_turbo = 0,
 	.turbo_disabled = 0,
 	.max_perf_pct = 100,
-	.max_perf = int_tofp(1),
+	.max_perf = int_ext_tofp(1),
 	.min_perf_pct = 100,
-	.min_perf = int_tofp(1),
+	.min_perf = int_ext_tofp(1),
 	.max_policy_pct = 100,
 	.max_sysfs_pct = 100,
 	.min_policy_pct = 0,
@@ -353,7 +379,7 @@ static struct perf_limits powersave_limi
 	.no_turbo = 0,
 	.turbo_disabled = 0,
 	.max_perf_pct = 100,
-	.max_perf = int_tofp(1),
+	.max_perf = int_ext_tofp(1),
 	.min_perf_pct = 0,
 	.min_perf = 0,
 	.max_policy_pct = 100,
@@ -368,6 +394,8 @@ static struct perf_limits *limits = &per
 static struct perf_limits *limits = &powersave_limits;
 #endif
 
+static DEFINE_MUTEX(intel_pstate_limits_lock);
+
 #ifdef CONFIG_ACPI
 
 static bool intel_pstate_get_ppc_enable_status(void)
@@ -379,14 +407,67 @@ static bool intel_pstate_get_ppc_enable_
 	return acpi_ppc;
 }
 
+#ifdef CONFIG_ACPI_CPPC_LIB
+
+/* The work item is needed to avoid CPU hotplug locking issues */
+static void intel_pstste_sched_itmt_work_fn(struct work_struct *work)
+{
+	sched_set_itmt_support();
+}
+
+static DECLARE_WORK(sched_itmt_work, intel_pstste_sched_itmt_work_fn);
+
+static void intel_pstate_set_itmt_prio(int cpu)
+{
+	struct cppc_perf_caps cppc_perf;
+	static u32 max_highest_perf = 0, min_highest_perf = U32_MAX;
+	int ret;
+
+	ret = cppc_get_perf_caps(cpu, &cppc_perf);
+	if (ret)
+		return;
+
+	/*
+	 * The priorities can be set regardless of whether or not
+	 * sched_set_itmt_support(true) has been called and it is valid to
+	 * update them at any time after it has been called.
+	 */
+	sched_set_itmt_core_prio(cppc_perf.highest_perf, cpu);
+
+	if (max_highest_perf <= min_highest_perf) {
+		if (cppc_perf.highest_perf > max_highest_perf)
+			max_highest_perf = cppc_perf.highest_perf;
+
+		if (cppc_perf.highest_perf < min_highest_perf)
+			min_highest_perf = cppc_perf.highest_perf;
+
+		if (max_highest_perf > min_highest_perf) {
+			/*
+			 * This code can be run during CPU online under the
+			 * CPU hotplug locks, so sched_set_itmt_support()
+			 * cannot be called from here.  Queue up a work item
+			 * to invoke it.
+			 */
+			schedule_work(&sched_itmt_work);
+		}
+	}
+}
+#else
+static void intel_pstate_set_itmt_prio(int cpu)
+{
+}
+#endif
+
 static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
 {
 	struct cpudata *cpu;
 	int ret;
 	int i;
 
-	if (hwp_active)
+	if (hwp_active) {
+		intel_pstate_set_itmt_prio(policy->cpu);
 		return;
+	}
 
 	if (!intel_pstate_get_ppc_enable_status())
 		return;
@@ -459,11 +540,11 @@ static void intel_pstate_exit_perf_limit
 }
 
 #else
-static void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
+static inline void intel_pstate_init_acpi_perf_limits(struct cpufreq_policy *policy)
 {
 }
 
-static void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
+static inline void intel_pstate_exit_perf_limits(struct cpufreq_policy *policy)
 {
 }
 #endif
@@ -559,24 +640,252 @@ static inline void update_turbo_state(vo
 		 cpu->pstate.max_pstate == cpu->pstate.turbo_pstate);
 }
 
-static void intel_pstate_hwp_set(const struct cpumask *cpumask)
+static s16 intel_pstate_get_epb(struct cpudata *cpu_data)
+{
+	u64 epb;
+	int ret;
+
+	if (!static_cpu_has(X86_FEATURE_EPB))
+		return -ENXIO;
+
+	ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb);
+	if (ret)
+		return (s16)ret;
+
+	return (s16)(epb & 0x0f);
+}
+
+static s16 intel_pstate_get_epp(struct cpudata *cpu_data, u64 hwp_req_data)
+{
+	s16 epp;
+
+	if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+		/*
+		 * When hwp_req_data is 0, means that caller didn't read
+		 * MSR_HWP_REQUEST, so need to read and get EPP.
+		 */
+		if (!hwp_req_data) {
+			epp = rdmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST,
+					    &hwp_req_data);
+			if (epp)
+				return epp;
+		}
+		epp = (hwp_req_data >> 24) & 0xff;
+	} else {
+		/* When there is no EPP present, HWP uses EPB settings */
+		epp = intel_pstate_get_epb(cpu_data);
+	}
+
+	return epp;
+}
+
+static int intel_pstate_set_epb(int cpu, s16 pref)
+{
+	u64 epb;
+	int ret;
+
+	if (!static_cpu_has(X86_FEATURE_EPB))
+		return -ENXIO;
+
+	ret = rdmsrl_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb);
+	if (ret)
+		return ret;
+
+	epb = (epb & ~0x0f) | pref;
+	wrmsrl_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, epb);
+
+	return 0;
+}
+
+/*
+ * EPP/EPB display strings corresponding to EPP index in the
+ * energy_perf_strings[]
+ *	index		String
+ *-------------------------------------
+ *	0		default
+ *	1		performance
+ *	2		balance_performance
+ *	3		balance_power
+ *	4		power
+ */
+static const char * const energy_perf_strings[] = {
+	"default",
+	"performance",
+	"balance_performance",
+	"balance_power",
+	"power",
+	NULL
+};
+
+static int intel_pstate_get_energy_pref_index(struct cpudata *cpu_data)
+{
+	s16 epp;
+	int index = -EINVAL;
+
+	epp = intel_pstate_get_epp(cpu_data, 0);
+	if (epp < 0)
+		return epp;
+
+	if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+		/*
+		 * Range:
+		 *	0x00-0x3F	:	Performance
+		 *	0x40-0x7F	:	Balance performance
+		 *	0x80-0xBF	:	Balance power
+		 *	0xC0-0xFF	:	Power
+		 * The EPP is a 8 bit value, but our ranges restrict the
+		 * value which can be set. Here only using top two bits
+		 * effectively.
+		 */
+		index = (epp >> 6) + 1;
+	} else if (static_cpu_has(X86_FEATURE_EPB)) {
+		/*
+		 * Range:
+		 *	0x00-0x03	:	Performance
+		 *	0x04-0x07	:	Balance performance
+		 *	0x08-0x0B	:	Balance power
+		 *	0x0C-0x0F	:	Power
+		 * The EPB is a 4 bit value, but our ranges restrict the
+		 * value which can be set. Here only using top two bits
+		 * effectively.
+		 */
+		index = (epp >> 2) + 1;
+	}
+
+	return index;
+}
+
+static int intel_pstate_set_energy_pref_index(struct cpudata *cpu_data,
+					      int pref_index)
+{
+	int epp = -EINVAL;
+	int ret;
+
+	if (!pref_index)
+		epp = cpu_data->epp_default;
+
+	mutex_lock(&intel_pstate_limits_lock);
+
+	if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+		u64 value;
+
+		ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, &value);
+		if (ret)
+			goto return_pref;
+
+		value &= ~GENMASK_ULL(31, 24);
+
+		/*
+		 * If epp is not default, convert from index into
+		 * energy_perf_strings to epp value, by shifting 6
+		 * bits left to use only top two bits in epp.
+		 * The resultant epp need to shifted by 24 bits to
+		 * epp position in MSR_HWP_REQUEST.
+		 */
+		if (epp == -EINVAL)
+			epp = (pref_index - 1) << 6;
+
+		value |= (u64)epp << 24;
+		ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value);
+	} else {
+		if (epp == -EINVAL)
+			epp = (pref_index - 1) << 2;
+		ret = intel_pstate_set_epb(cpu_data->cpu, epp);
+	}
+return_pref:
+	mutex_unlock(&intel_pstate_limits_lock);
+
+	return ret;
+}
+
+static ssize_t show_energy_performance_available_preferences(
+				struct cpufreq_policy *policy, char *buf)
+{
+	int i = 0;
+	int ret = 0;
+
+	while (energy_perf_strings[i] != NULL)
+		ret += sprintf(&buf[ret], "%s ", energy_perf_strings[i++]);
+
+	ret += sprintf(&buf[ret], "\n");
+
+	return ret;
+}
+
+cpufreq_freq_attr_ro(energy_performance_available_preferences);
+
+static ssize_t store_energy_performance_preference(
+		struct cpufreq_policy *policy, const char *buf, size_t count)
+{
+	struct cpudata *cpu_data = all_cpu_data[policy->cpu];
+	char str_preference[21];
+	int ret, i = 0;
+
+	ret = sscanf(buf, "%20s", str_preference);
+	if (ret != 1)
+		return -EINVAL;
+
+	while (energy_perf_strings[i] != NULL) {
+		if (!strcmp(str_preference, energy_perf_strings[i])) {
+			intel_pstate_set_energy_pref_index(cpu_data, i);
+			return count;
+		}
+		++i;
+	}
+
+	return -EINVAL;
+}
+
+static ssize_t show_energy_performance_preference(
+				struct cpufreq_policy *policy, char *buf)
+{
+	struct cpudata *cpu_data = all_cpu_data[policy->cpu];
+	int preference;
+
+	preference = intel_pstate_get_energy_pref_index(cpu_data);
+	if (preference < 0)
+		return preference;
+
+	return  sprintf(buf, "%s\n", energy_perf_strings[preference]);
+}
+
+cpufreq_freq_attr_rw(energy_performance_preference);
+
+static struct freq_attr *hwp_cpufreq_attrs[] = {
+	&energy_performance_preference,
+	&energy_performance_available_preferences,
+	NULL,
+};
+
+static void intel_pstate_hwp_set(struct cpufreq_policy *policy)
 {
 	int min, hw_min, max, hw_max, cpu, range, adj_range;
+	struct perf_limits *perf_limits = limits;
 	u64 value, cap;
 
-	for_each_cpu(cpu, cpumask) {
+	for_each_cpu(cpu, policy->cpus) {
+		int max_perf_pct, min_perf_pct;
+		struct cpudata *cpu_data = all_cpu_data[cpu];
+		s16 epp;
+
+		if (per_cpu_limits)
+			perf_limits = all_cpu_data[cpu]->perf_limits;
+
 		rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
 		hw_min = HWP_LOWEST_PERF(cap);
 		hw_max = HWP_HIGHEST_PERF(cap);
 		range = hw_max - hw_min;
 
+		max_perf_pct = perf_limits->max_perf_pct;
+		min_perf_pct = perf_limits->min_perf_pct;
+
 		rdmsrl_on_cpu(cpu, MSR_HWP_REQUEST, &value);
-		adj_range = limits->min_perf_pct * range / 100;
+		adj_range = min_perf_pct * range / 100;
 		min = hw_min + adj_range;
 		value &= ~HWP_MIN_PERF(~0L);
 		value |= HWP_MIN_PERF(min);
 
-		adj_range = limits->max_perf_pct * range / 100;
+		adj_range = max_perf_pct * range / 100;
 		max = hw_min + adj_range;
 		if (limits->no_turbo) {
 			hw_max = HWP_GUARANTEED_PERF(cap);
@@ -586,6 +895,53 @@ static void intel_pstate_hwp_set(const s
 
 		value &= ~HWP_MAX_PERF(~0L);
 		value |= HWP_MAX_PERF(max);
+
+		if (cpu_data->epp_policy == cpu_data->policy)
+			goto skip_epp;
+
+		cpu_data->epp_policy = cpu_data->policy;
+
+		if (cpu_data->epp_saved >= 0) {
+			epp = cpu_data->epp_saved;
+			cpu_data->epp_saved = -EINVAL;
+			goto update_epp;
+		}
+
+		if (cpu_data->policy == CPUFREQ_POLICY_PERFORMANCE) {
+			epp = intel_pstate_get_epp(cpu_data, value);
+			cpu_data->epp_powersave = epp;
+			/* If EPP read was failed, then don't try to write */
+			if (epp < 0)
+				goto skip_epp;
+
+
+			epp = 0;
+		} else {
+			/* skip setting EPP, when saved value is invalid */
+			if (cpu_data->epp_powersave < 0)
+				goto skip_epp;
+
+			/*
+			 * No need to restore EPP when it is not zero. This
+			 * means:
+			 *  - Policy is not changed
+			 *  - user has manually changed
+			 *  - Error reading EPB
+			 */
+			epp = intel_pstate_get_epp(cpu_data, value);
+			if (epp)
+				goto skip_epp;
+
+			epp = cpu_data->epp_powersave;
+		}
+update_epp:
+		if (static_cpu_has(X86_FEATURE_HWP_EPP)) {
+			value &= ~GENMASK_ULL(31, 24);
+			value |= (u64)epp << 24;
+		} else {
+			intel_pstate_set_epb(cpu, epp);
+		}
+skip_epp:
 		wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value);
 	}
 }
@@ -593,16 +949,47 @@ static void intel_pstate_hwp_set(const s
 static int intel_pstate_hwp_set_policy(struct cpufreq_policy *policy)
 {
 	if (hwp_active)
-		intel_pstate_hwp_set(policy->cpus);
+		intel_pstate_hwp_set(policy);
 
 	return 0;
 }
 
-static void intel_pstate_hwp_set_online_cpus(void)
+static int intel_pstate_hwp_save_state(struct cpufreq_policy *policy)
 {
-	get_online_cpus();
-	intel_pstate_hwp_set(cpu_online_mask);
-	put_online_cpus();
+	struct cpudata *cpu_data = all_cpu_data[policy->cpu];
+
+	if (!hwp_active)
+		return 0;
+
+	cpu_data->epp_saved = intel_pstate_get_epp(cpu_data, 0);
+
+	return 0;
+}
+
+static int intel_pstate_resume(struct cpufreq_policy *policy)
+{
+	int ret;
+
+	if (!hwp_active)
+		return 0;
+
+	mutex_lock(&intel_pstate_limits_lock);
+
+	all_cpu_data[policy->cpu]->epp_policy = 0;
+
+	ret = intel_pstate_hwp_set_policy(policy);
+
+	mutex_unlock(&intel_pstate_limits_lock);
+
+	return ret;
+}
+
+static void intel_pstate_update_policies(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		cpufreq_update_policy(cpu);
 }
 
 /************************** debugfs begin ************************/
@@ -640,8 +1027,6 @@ static void __init intel_pstate_debug_ex
 	struct dentry *debugfs_parent;
 	int i = 0;
 
-	if (hwp_active)
-		return;
 	debugfs_parent = debugfs_create_dir("pstate_snb", NULL);
 	if (IS_ERR_OR_NULL(debugfs_parent))
 		return;
@@ -714,16 +1099,20 @@ static ssize_t store_no_turbo(struct kob
 	if (ret != 1)
 		return -EINVAL;
 
+	mutex_lock(&intel_pstate_limits_lock);
+
 	update_turbo_state();
 	if (limits->turbo_disabled) {
 		pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
+		mutex_unlock(&intel_pstate_limits_lock);
 		return -EPERM;
 	}
 
 	limits->no_turbo = clamp_t(int, input, 0, 1);
 
-	if (hwp_active)
-		intel_pstate_hwp_set_online_cpus();
+	mutex_unlock(&intel_pstate_limits_lock);
+
+	intel_pstate_update_policies();
 
 	return count;
 }
@@ -738,6 +1127,8 @@ static ssize_t store_max_perf_pct(struct
 	if (ret != 1)
 		return -EINVAL;
 
+	mutex_lock(&intel_pstate_limits_lock);
+
 	limits->max_sysfs_pct = clamp_t(int, input, 0 , 100);
 	limits->max_perf_pct = min(limits->max_policy_pct,
 				   limits->max_sysfs_pct);
@@ -745,10 +1136,12 @@ static ssize_t store_max_perf_pct(struct
 				   limits->max_perf_pct);
 	limits->max_perf_pct = max(limits->min_perf_pct,
 				   limits->max_perf_pct);
-	limits->max_perf = div_fp(limits->max_perf_pct, 100);
+	limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
+
+	mutex_unlock(&intel_pstate_limits_lock);
+
+	intel_pstate_update_policies();
 
-	if (hwp_active)
-		intel_pstate_hwp_set_online_cpus();
 	return count;
 }
 
@@ -762,6 +1155,8 @@ static ssize_t store_min_perf_pct(struct
 	if (ret != 1)
 		return -EINVAL;
 
+	mutex_lock(&intel_pstate_limits_lock);
+
 	limits->min_sysfs_pct = clamp_t(int, input, 0 , 100);
 	limits->min_perf_pct = max(limits->min_policy_pct,
 				   limits->min_sysfs_pct);
@@ -769,10 +1164,12 @@ static ssize_t store_min_perf_pct(struct
 				   limits->min_perf_pct);
 	limits->min_perf_pct = min(limits->max_perf_pct,
 				   limits->min_perf_pct);
-	limits->min_perf = div_fp(limits->min_perf_pct, 100);
+	limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
+
+	mutex_unlock(&intel_pstate_limits_lock);
+
+	intel_pstate_update_policies();
 
-	if (hwp_active)
-		intel_pstate_hwp_set_online_cpus();
 	return count;
 }
 
@@ -787,8 +1184,6 @@ define_one_global_ro(num_pstates);
 
 static struct attribute *intel_pstate_attributes[] = {
 	&no_turbo.attr,
-	&max_perf_pct.attr,
-	&min_perf_pct.attr,
 	&turbo_pct.attr,
 	&num_pstates.attr,
 	NULL
@@ -805,9 +1200,26 @@ static void __init intel_pstate_sysfs_ex
 
 	intel_pstate_kobject = kobject_create_and_add("intel_pstate",
 						&cpu_subsys.dev_root->kobj);
-	BUG_ON(!intel_pstate_kobject);
+	if (WARN_ON(!intel_pstate_kobject))
+		return;
+
 	rc = sysfs_create_group(intel_pstate_kobject, &intel_pstate_attr_group);
-	BUG_ON(rc);
+	if (WARN_ON(rc))
+		return;
+
+	/*
+	 * If per cpu limits are enforced there are no global limits, so
+	 * return without creating max/min_perf_pct attributes
+	 */
+	if (per_cpu_limits)
+		return;
+
+	rc = sysfs_create_file(intel_pstate_kobject, &max_perf_pct.attr);
+	WARN_ON(rc);
+
+	rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr);
+	WARN_ON(rc);
+
 }
 /************************** sysfs end ************************/
 
@@ -818,6 +1230,28 @@ static void intel_pstate_hwp_enable(stru
 		wrmsrl_on_cpu(cpudata->cpu, MSR_HWP_INTERRUPT, 0x00);
 
 	wrmsrl_on_cpu(cpudata->cpu, MSR_PM_ENABLE, 0x1);
+	cpudata->epp_policy = 0;
+	if (cpudata->epp_default == -EINVAL)
+		cpudata->epp_default = intel_pstate_get_epp(cpudata, 0);
+}
+
+#define MSR_IA32_POWER_CTL_BIT_EE	19
+
+/* Disable energy efficiency optimization */
+static void intel_pstate_disable_ee(int cpu)
+{
+	u64 power_ctl;
+	int ret;
+
+	ret = rdmsrl_on_cpu(cpu, MSR_IA32_POWER_CTL, &power_ctl);
+	if (ret)
+		return;
+
+	if (!(power_ctl & BIT(MSR_IA32_POWER_CTL_BIT_EE))) {
+		pr_info("Disabling energy efficiency optimization\n");
+		power_ctl |= BIT(MSR_IA32_POWER_CTL_BIT_EE);
+		wrmsrl_on_cpu(cpu, MSR_IA32_POWER_CTL, power_ctl);
+	}
 }
 
 static int atom_get_min_pstate(void)
@@ -1045,7 +1479,6 @@ static const struct cpu_defaults silverm
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
-		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = atom_get_max_pstate,
@@ -1067,7 +1500,6 @@ static const struct cpu_defaults airmont
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
-		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = atom_get_max_pstate,
@@ -1109,7 +1541,6 @@ static const struct cpu_defaults bxt_par
 		.p_gain_pct = 14,
 		.d_gain_pct = 0,
 		.i_gain_pct = 4,
-		.boost_iowait = true,
 	},
 	.funcs = {
 		.get_max = core_get_max_pstate,
@@ -1127,20 +1558,24 @@ static void intel_pstate_get_min_max(str
 	int max_perf = cpu->pstate.turbo_pstate;
 	int max_perf_adj;
 	int min_perf;
+	struct perf_limits *perf_limits = limits;
 
 	if (limits->no_turbo || limits->turbo_disabled)
 		max_perf = cpu->pstate.max_pstate;
 
+	if (per_cpu_limits)
+		perf_limits = cpu->perf_limits;
+
 	/*
 	 * performance can be limited by user through sysfs, by cpufreq
 	 * policy, or by cpu specific default values determined through
 	 * experimentation.
 	 */
-	max_perf_adj = fp_toint(max_perf * limits->max_perf);
+	max_perf_adj = fp_ext_toint(max_perf * perf_limits->max_perf);
 	*max = clamp_t(int, max_perf_adj,
 			cpu->pstate.min_pstate, cpu->pstate.turbo_pstate);
 
-	min_perf = fp_toint(max_perf * limits->min_perf);
+	min_perf = fp_ext_toint(max_perf * perf_limits->min_perf);
 	*min = clamp_t(int, min_perf, cpu->pstate.min_pstate, max_perf);
 }
 
@@ -1178,6 +1613,8 @@ static void intel_pstate_get_cpu_pstates
 	cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical();
 	cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
 	cpu->pstate.scaling = pstate_funcs.get_scaling();
+	cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
+	cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
 
 	if (pstate_funcs.get_vid)
 		pstate_funcs.get_vid(cpu);
@@ -1316,15 +1753,19 @@ static inline int32_t get_target_pstate_
 	return cpu->pstate.current_pstate - pid_calc(&cpu->pid, perf_scaled);
 }
 
-static inline void intel_pstate_update_pstate(struct cpudata *cpu, int pstate)
+static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate)
 {
 	int max_perf, min_perf;
 
-	update_turbo_state();
-
 	intel_pstate_get_min_max(cpu, &min_perf, &max_perf);
 	pstate = clamp_t(int, pstate, min_perf, max_perf);
 	trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu);
+	return pstate;
+}
+
+static void intel_pstate_update_pstate(struct cpudata *cpu, int pstate)
+{
+	pstate = intel_pstate_prepare_request(cpu, pstate);
 	if (pstate == cpu->pstate.current_pstate)
 		return;
 
@@ -1342,6 +1783,8 @@ static inline void intel_pstate_adjust_b
 	target_pstate = cpu->policy == CPUFREQ_POLICY_PERFORMANCE ?
 		cpu->pstate.turbo_pstate : pstate_funcs.get_target_pstate(cpu);
 
+	update_turbo_state();
+
 	intel_pstate_update_pstate(cpu, target_pstate);
 
 	sample = &cpu->sample;
@@ -1362,7 +1805,7 @@ static void intel_pstate_update_util(str
 	struct cpudata *cpu = container_of(data, struct cpudata, update_util);
 	u64 delta_ns;
 
-	if (pid_params.boost_iowait) {
+	if (pstate_funcs.get_target_pstate == get_target_pstate_use_cpu_load) {
 		if (flags & SCHED_CPUFREQ_IOWAIT) {
 			cpu->iowait_boost = int_tofp(1);
 		} else if (cpu->iowait_boost) {
@@ -1408,6 +1851,7 @@ static const struct x86_cpu_id intel_pst
 	ICPU(INTEL_FAM6_SKYLAKE_DESKTOP,	core_params),
 	ICPU(INTEL_FAM6_BROADWELL_XEON_D,	core_params),
 	ICPU(INTEL_FAM6_XEON_PHI_KNL,		knl_params),
+	ICPU(INTEL_FAM6_XEON_PHI_KNM,		knl_params),
 	ICPU(INTEL_FAM6_ATOM_GOLDMONT,		bxt_params),
 	{}
 };
@@ -1420,21 +1864,47 @@ static const struct x86_cpu_id intel_pst
 	{}
 };
 
+static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = {
+	ICPU(INTEL_FAM6_KABYLAKE_DESKTOP, core_params),
+	{}
+};
+
 static int intel_pstate_init_cpu(unsigned int cpunum)
 {
 	struct cpudata *cpu;
 
-	if (!all_cpu_data[cpunum])
-		all_cpu_data[cpunum] = kzalloc(sizeof(struct cpudata),
-					       GFP_KERNEL);
-	if (!all_cpu_data[cpunum])
-		return -ENOMEM;
+	cpu = all_cpu_data[cpunum];
+
+	if (!cpu) {
+		unsigned int size = sizeof(struct cpudata);
+
+		if (per_cpu_limits)
+			size += sizeof(struct perf_limits);
+
+		cpu = kzalloc(size, GFP_KERNEL);
+		if (!cpu)
+			return -ENOMEM;
+
+		all_cpu_data[cpunum] = cpu;
+		if (per_cpu_limits)
+			cpu->perf_limits = (struct perf_limits *)(cpu + 1);
+
+		cpu->epp_default = -EINVAL;
+		cpu->epp_powersave = -EINVAL;
+		cpu->epp_saved = -EINVAL;
+	}
 
 	cpu = all_cpu_data[cpunum];
 
 	cpu->cpu = cpunum;
 
 	if (hwp_active) {
+		const struct x86_cpu_id *id;
+
+		id = x86_match_cpu(intel_pstate_cpu_ee_disable_ids);
+		if (id)
+			intel_pstate_disable_ee(cpunum);
+
 		intel_pstate_hwp_enable(cpu);
 		pid_params.sample_rate_ms = 50;
 		pid_params.sample_rate_ns = 50 * NSEC_PER_MSEC;
@@ -1487,18 +1957,57 @@ static void intel_pstate_set_performance
 	limits->no_turbo = 0;
 	limits->turbo_disabled = 0;
 	limits->max_perf_pct = 100;
-	limits->max_perf = int_tofp(1);
+	limits->max_perf = int_ext_tofp(1);
 	limits->min_perf_pct = 100;
-	limits->min_perf = int_tofp(1);
+	limits->min_perf = int_ext_tofp(1);
 	limits->max_policy_pct = 100;
 	limits->max_sysfs_pct = 100;
 	limits->min_policy_pct = 0;
 	limits->min_sysfs_pct = 0;
 }
 
+static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
+					    struct perf_limits *limits)
+{
+
+	limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100,
+					      policy->cpuinfo.max_freq);
+	limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0, 100);
+	if (policy->max == policy->min) {
+		limits->min_policy_pct = limits->max_policy_pct;
+	} else {
+		limits->min_policy_pct = DIV_ROUND_UP(policy->min * 100,
+						      policy->cpuinfo.max_freq);
+		limits->min_policy_pct = clamp_t(int, limits->min_policy_pct,
+						 0, 100);
+	}
+
+	/* Normalize user input to [min_policy_pct, max_policy_pct] */
+	limits->min_perf_pct = max(limits->min_policy_pct,
+				   limits->min_sysfs_pct);
+	limits->min_perf_pct = min(limits->max_policy_pct,
+				   limits->min_perf_pct);
+	limits->max_perf_pct = min(limits->max_policy_pct,
+				   limits->max_sysfs_pct);
+	limits->max_perf_pct = max(limits->min_policy_pct,
+				   limits->max_perf_pct);
+
+	/* Make sure min_perf_pct <= max_perf_pct */
+	limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
+
+	limits->min_perf = div_ext_fp(limits->min_perf_pct, 100);
+	limits->max_perf = div_ext_fp(limits->max_perf_pct, 100);
+	limits->max_perf = round_up(limits->max_perf, EXT_FRAC_BITS);
+	limits->min_perf = round_up(limits->min_perf, EXT_FRAC_BITS);
+
+	pr_debug("cpu:%d max_perf_pct:%d min_perf_pct:%d\n", policy->cpu,
+		 limits->max_perf_pct, limits->min_perf_pct);
+}
+
 static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 {
 	struct cpudata *cpu;
+	struct perf_limits *perf_limits = NULL;
 
 	if (!policy->cpuinfo.max_freq)
 		return -ENODEV;
@@ -1516,41 +2025,32 @@ static int intel_pstate_set_policy(struc
 		policy->max = policy->cpuinfo.max_freq;
 	}
 
-	if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
-		limits = &performance_limits;
-		if (policy->max >= policy->cpuinfo.max_freq) {
+	if (per_cpu_limits)
+		perf_limits = cpu->perf_limits;
+
+	mutex_lock(&intel_pstate_limits_lock);
+
+	if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
+		if (!perf_limits) {
+			limits = &performance_limits;
+			perf_limits = limits;
+		}
+		if (policy->max >= policy->cpuinfo.max_freq &&
+		    !limits->no_turbo) {
 			pr_debug("set performance\n");
-			intel_pstate_set_performance_limits(limits);
+			intel_pstate_set_performance_limits(perf_limits);
 			goto out;
 		}
 	} else {
 		pr_debug("set powersave\n");
-		limits = &powersave_limits;
-	}
-
-	limits->min_policy_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
-	limits->min_policy_pct = clamp_t(int, limits->min_policy_pct, 0 , 100);
-	limits->max_policy_pct = DIV_ROUND_UP(policy->max * 100,
-					      policy->cpuinfo.max_freq);
-	limits->max_policy_pct = clamp_t(int, limits->max_policy_pct, 0 , 100);
-
-	/* Normalize user input to [min_policy_pct, max_policy_pct] */
-	limits->min_perf_pct = max(limits->min_policy_pct,
-				   limits->min_sysfs_pct);
-	limits->min_perf_pct = min(limits->max_policy_pct,
-				   limits->min_perf_pct);
-	limits->max_perf_pct = min(limits->max_policy_pct,
-				   limits->max_sysfs_pct);
-	limits->max_perf_pct = max(limits->min_policy_pct,
-				   limits->max_perf_pct);
-
-	/* Make sure min_perf_pct <= max_perf_pct */
-	limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
+		if (!perf_limits) {
+			limits = &powersave_limits;
+			perf_limits = limits;
+		}
 
-	limits->min_perf = div_fp(limits->min_perf_pct, 100);
-	limits->max_perf = div_fp(limits->max_perf_pct, 100);
-	limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
+	}
 
+	intel_pstate_update_perf_limits(policy, perf_limits);
  out:
 	if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
 		/*
@@ -1565,6 +2065,8 @@ static int intel_pstate_set_policy(struc
 
 	intel_pstate_hwp_set_policy(policy);
 
+	mutex_unlock(&intel_pstate_limits_lock);
+
 	return 0;
 }
 
@@ -1576,25 +2078,46 @@ static int intel_pstate_verify_policy(st
 	    policy->policy != CPUFREQ_POLICY_PERFORMANCE)
 		return -EINVAL;
 
+	/* When per-CPU limits are used, sysfs limits are not used */
+	if (!per_cpu_limits) {
+		unsigned int max_freq, min_freq;
+
+		max_freq = policy->cpuinfo.max_freq *
+						limits->max_sysfs_pct / 100;
+		min_freq = policy->cpuinfo.max_freq *
+						limits->min_sysfs_pct / 100;
+		cpufreq_verify_within_limits(policy, min_freq, max_freq);
+	}
+
 	return 0;
 }
 
+static void intel_cpufreq_stop_cpu(struct cpufreq_policy *policy)
+{
+	intel_pstate_set_min_pstate(all_cpu_data[policy->cpu]);
+}
+
 static void intel_pstate_stop_cpu(struct cpufreq_policy *policy)
 {
-	int cpu_num = policy->cpu;
-	struct cpudata *cpu = all_cpu_data[cpu_num];
+	pr_debug("CPU %d exiting\n", policy->cpu);
 
-	pr_debug("CPU %d exiting\n", cpu_num);
+	intel_pstate_clear_update_util_hook(policy->cpu);
+	if (hwp_active)
+		intel_pstate_hwp_save_state(policy);
+	else
+		intel_cpufreq_stop_cpu(policy);
+}
 
-	intel_pstate_clear_update_util_hook(cpu_num);
+static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
+{
+	intel_pstate_exit_perf_limits(policy);
 
-	if (hwp_active)
-		return;
+	policy->fast_switch_possible = false;
 
-	intel_pstate_set_min_pstate(cpu);
+	return 0;
 }
 
-static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
+static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpudata *cpu;
 	int rc;
@@ -1605,10 +2128,13 @@ static int intel_pstate_cpu_init(struct
 
 	cpu = all_cpu_data[policy->cpu];
 
-	if (limits->min_perf_pct == 100 && limits->max_perf_pct == 100)
-		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-	else
-		policy->policy = CPUFREQ_POLICY_POWERSAVE;
+	/*
+	 * We need sane value in the cpu->perf_limits, so inherit from global
+	 * perf_limits limits, which are seeded with values based on the
+	 * CONFIG_CPU_FREQ_DEFAULT_GOV_*, during boot up.
+	 */
+	if (per_cpu_limits)
+		memcpy(cpu->perf_limits, limits, sizeof(struct perf_limits));
 
 	policy->min = cpu->pstate.min_pstate * cpu->pstate.scaling;
 	policy->max = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
@@ -1621,24 +2147,35 @@ static int intel_pstate_cpu_init(struct
 	policy->cpuinfo.max_freq *= cpu->pstate.scaling;
 
 	intel_pstate_init_acpi_perf_limits(policy);
-	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 	cpumask_set_cpu(policy->cpu, policy->cpus);
 
+	policy->fast_switch_possible = true;
+
 	return 0;
 }
 
-static int intel_pstate_cpu_exit(struct cpufreq_policy *policy)
+static int intel_pstate_cpu_init(struct cpufreq_policy *policy)
 {
-	intel_pstate_exit_perf_limits(policy);
+	int ret = __intel_pstate_cpu_init(policy);
+
+	if (ret)
+		return ret;
+
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	if (limits->min_perf_pct == 100 && limits->max_perf_pct == 100)
+		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+	else
+		policy->policy = CPUFREQ_POLICY_POWERSAVE;
 
 	return 0;
 }
 
-static struct cpufreq_driver intel_pstate_driver = {
+static struct cpufreq_driver intel_pstate = {
 	.flags		= CPUFREQ_CONST_LOOPS,
 	.verify		= intel_pstate_verify_policy,
 	.setpolicy	= intel_pstate_set_policy,
-	.resume		= intel_pstate_hwp_set_policy,
+	.suspend	= intel_pstate_hwp_save_state,
+	.resume		= intel_pstate_resume,
 	.get		= intel_pstate_get,
 	.init		= intel_pstate_cpu_init,
 	.exit		= intel_pstate_cpu_exit,
@@ -1646,6 +2183,122 @@ static struct cpufreq_driver intel_pstat
 	.name		= "intel_pstate",
 };
 
+static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
+{
+	struct cpudata *cpu = all_cpu_data[policy->cpu];
+	struct perf_limits *perf_limits = limits;
+
+	update_turbo_state();
+	policy->cpuinfo.max_freq = limits->turbo_disabled ?
+			cpu->pstate.max_freq : cpu->pstate.turbo_freq;
+
+	cpufreq_verify_within_cpu_limits(policy);
+
+	if (per_cpu_limits)
+		perf_limits = cpu->perf_limits;
+
+	mutex_lock(&intel_pstate_limits_lock);
+
+	intel_pstate_update_perf_limits(policy, perf_limits);
+
+	mutex_unlock(&intel_pstate_limits_lock);
+
+	return 0;
+}
+
+static unsigned int intel_cpufreq_turbo_update(struct cpudata *cpu,
+					       struct cpufreq_policy *policy,
+					       unsigned int target_freq)
+{
+	unsigned int max_freq;
+
+	update_turbo_state();
+
+	max_freq = limits->no_turbo || limits->turbo_disabled ?
+			cpu->pstate.max_freq : cpu->pstate.turbo_freq;
+	policy->cpuinfo.max_freq = max_freq;
+	if (policy->max > max_freq)
+		policy->max = max_freq;
+
+	if (target_freq > max_freq)
+		target_freq = max_freq;
+
+	return target_freq;
+}
+
+static int intel_cpufreq_target(struct cpufreq_policy *policy,
+				unsigned int target_freq,
+				unsigned int relation)
+{
+	struct cpudata *cpu = all_cpu_data[policy->cpu];
+	struct cpufreq_freqs freqs;
+	int target_pstate;
+
+	freqs.old = policy->cur;
+	freqs.new = intel_cpufreq_turbo_update(cpu, policy, target_freq);
+
+	cpufreq_freq_transition_begin(policy, &freqs);
+	switch (relation) {
+	case CPUFREQ_RELATION_L:
+		target_pstate = DIV_ROUND_UP(freqs.new, cpu->pstate.scaling);
+		break;
+	case CPUFREQ_RELATION_H:
+		target_pstate = freqs.new / cpu->pstate.scaling;
+		break;
+	default:
+		target_pstate = DIV_ROUND_CLOSEST(freqs.new, cpu->pstate.scaling);
+		break;
+	}
+	target_pstate = intel_pstate_prepare_request(cpu, target_pstate);
+	if (target_pstate != cpu->pstate.current_pstate) {
+		cpu->pstate.current_pstate = target_pstate;
+		wrmsrl_on_cpu(policy->cpu, MSR_IA32_PERF_CTL,
+			      pstate_funcs.get_val(cpu, target_pstate));
+	}
+	cpufreq_freq_transition_end(policy, &freqs, false);
+
+	return 0;
+}
+
+static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
+					      unsigned int target_freq)
+{
+	struct cpudata *cpu = all_cpu_data[policy->cpu];
+	int target_pstate;
+
+	target_freq = intel_cpufreq_turbo_update(cpu, policy, target_freq);
+	target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling);
+	intel_pstate_update_pstate(cpu, target_pstate);
+	return target_freq;
+}
+
+static int intel_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	int ret = __intel_pstate_cpu_init(policy);
+
+	if (ret)
+		return ret;
+
+	policy->cpuinfo.transition_latency = INTEL_CPUFREQ_TRANSITION_LATENCY;
+	/* This reflects the intel_pstate_get_cpu_pstates() setting. */
+	policy->cur = policy->cpuinfo.min_freq;
+
+	return 0;
+}
+
+static struct cpufreq_driver intel_cpufreq = {
+	.flags		= CPUFREQ_CONST_LOOPS,
+	.verify		= intel_cpufreq_verify_policy,
+	.target		= intel_cpufreq_target,
+	.fast_switch	= intel_cpufreq_fast_switch,
+	.init		= intel_cpufreq_cpu_init,
+	.exit		= intel_pstate_cpu_exit,
+	.stop_cpu	= intel_cpufreq_stop_cpu,
+	.name		= "intel_cpufreq",
+};
+
+static struct cpufreq_driver *intel_pstate_driver = &intel_pstate;
+
 static int no_load __initdata;
 static int no_hwp __initdata;
 static int hwp_only __initdata;
@@ -1672,6 +2325,19 @@ static void __init copy_pid_params(struc
 	pid_params.setpoint = policy->setpoint;
 }
 
+#ifdef CONFIG_ACPI
+static void intel_pstate_use_acpi_profile(void)
+{
+	if (acpi_gbl_FADT.preferred_profile == PM_MOBILE)
+		pstate_funcs.get_target_pstate =
+				get_target_pstate_use_cpu_load;
+}
+#else
+static void intel_pstate_use_acpi_profile(void)
+{
+}
+#endif
+
 static void __init copy_cpu_funcs(struct pstate_funcs *funcs)
 {
 	pstate_funcs.get_max   = funcs->get_max;
@@ -1683,6 +2349,7 @@ static void __init copy_cpu_funcs(struct
 	pstate_funcs.get_vid   = funcs->get_vid;
 	pstate_funcs.get_target_pstate = funcs->get_target_pstate;
 
+	intel_pstate_use_acpi_profile();
 }
 
 #ifdef CONFIG_ACPI
@@ -1796,9 +2463,20 @@ static bool __init intel_pstate_platform
 
 	return false;
 }
+
+static void intel_pstate_request_control_from_smm(void)
+{
+	/*
+	 * It may be unsafe to request P-states control from SMM if _PPC support
+	 * has not been enabled.
+	 */
+	if (acpi_ppc)
+		acpi_processor_pstate_control();
+}
 #else /* CONFIG_ACPI not enabled */
 static inline bool intel_pstate_platform_pwr_mgmt_exists(void) { return false; }
 static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
+static inline void intel_pstate_request_control_from_smm(void) {}
 #endif /* CONFIG_ACPI */
 
 static const struct x86_cpu_id hwp_support_ids[] __initconst = {
@@ -1818,6 +2496,7 @@ static int __init intel_pstate_init(void
 	if (x86_match_cpu(hwp_support_ids) && !no_hwp) {
 		copy_cpu_funcs(&core_params.funcs);
 		hwp_active++;
+		intel_pstate.attr = hwp_cpufreq_attrs;
 		goto hwp_cpu_matched;
 	}
 
@@ -1850,11 +2529,16 @@ hwp_cpu_matched:
 	if (!hwp_active && hwp_only)
 		goto out;
 
-	rc = cpufreq_register_driver(&intel_pstate_driver);
+	intel_pstate_request_control_from_smm();
+
+	rc = cpufreq_register_driver(intel_pstate_driver);
 	if (rc)
 		goto out;
 
-	intel_pstate_debug_expose_params();
+	if (intel_pstate_driver == &intel_pstate && !hwp_active &&
+	    pstate_funcs.get_target_pstate != get_target_pstate_use_cpu_load)
+		intel_pstate_debug_expose_params();
+
 	intel_pstate_sysfs_expose_params();
 
 	if (hwp_active)
@@ -1865,7 +2549,9 @@ out:
 	get_online_cpus();
 	for_each_online_cpu(cpu) {
 		if (all_cpu_data[cpu]) {
-			intel_pstate_clear_update_util_hook(cpu);
+			if (intel_pstate_driver == &intel_pstate)
+				intel_pstate_clear_update_util_hook(cpu);
+
 			kfree(all_cpu_data[cpu]);
 		}
 	}
@@ -1881,8 +2567,13 @@ static int __init intel_pstate_setup(cha
 	if (!str)
 		return -EINVAL;
 
-	if (!strcmp(str, "disable"))
+	if (!strcmp(str, "disable")) {
 		no_load = 1;
+	} else if (!strcmp(str, "passive")) {
+		pr_info("Passive mode enabled\n");
+		intel_pstate_driver = &intel_cpufreq;
+		no_hwp = 1;
+	}
 	if (!strcmp(str, "no_hwp")) {
 		pr_info("HWP disabled\n");
 		no_hwp = 1;
@@ -1891,6 +2582,8 @@ static int __init intel_pstate_setup(cha
 		force_load = 1;
 	if (!strcmp(str, "hwp_only"))
 		hwp_only = 1;
+	if (!strcmp(str, "per_cpu_perf_limits"))
+		per_cpu_limits = true;
 
 #ifdef CONFIG_ACPI
 	if (!strcmp(str, "support_acpi_ppc"))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/Kconfig.arm linux-libre-4.10-rc8-gnu/drivers/cpufreq/Kconfig.arm
--- linux-libre-4.9-gnu/drivers/cpufreq/Kconfig.arm	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/Kconfig.arm	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,27 @@ config ARM_BIG_LITTLE_CPUFREQ
 	help
 	  This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
 
+config ARM_BRCMSTB_AVS_CPUFREQ
+	tristate "Broadcom STB AVS CPUfreq driver"
+	depends on ARCH_BRCMSTB || COMPILE_TEST
+	default y
+	help
+	  Some Broadcom STB SoCs use a co-processor running proprietary firmware
+	  ("AVS") to handle voltage and frequency scaling. This driver provides
+	  a standard CPUfreq interface to to the firmware.
+
+	  Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS.
+
+config ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
+	bool "Broadcom STB AVS CPUfreq driver sysfs debug capability"
+	depends on ARM_BRCMSTB_AVS_CPUFREQ
+	help
+	  Enabling this option turns on debug support via sysfs under
+	  /sys/kernel/debug/brcmstb-avs-cpufreq. It is possible to read all and
+	  write some AVS mailbox registers through sysfs entries.
+
+	  If in doubt, say N.
+
 config ARM_DT_BL_CPUFREQ
 	tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
 	depends on ARM_BIG_LITTLE_CPUFREQ && OF
@@ -60,14 +81,6 @@ config ARM_IMX6Q_CPUFREQ
 
 	  If in doubt, say N.
 
-config ARM_INTEGRATOR
-	tristate "CPUfreq driver for ARM Integrator CPUs"
-	depends on ARCH_INTEGRATOR
-	default y
-	help
-	  This enables the CPUfreq driver for ARM Integrator CPUs.
-	  If in doubt, say Y.
-
 config ARM_KIRKWOOD_CPUFREQ
 	def_bool MACH_KIRKWOOD
 	help
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/Kconfig.x86 linux-libre-4.10-rc8-gnu/drivers/cpufreq/Kconfig.x86
--- linux-libre-4.9-gnu/drivers/cpufreq/Kconfig.x86	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/Kconfig.x86	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,7 @@ config X86_INTEL_PSTATE
        bool "Intel P state control"
        depends on X86
        select ACPI_PROCESSOR if ACPI
+       select ACPI_CPPC_LIB if X86_64 && ACPI && SCHED_MC_PRIO
        help
           This driver provides a P state for Intel core processors.
 	  The driver implements an internal governor and will become
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/Makefile linux-libre-4.10-rc8-gnu/drivers/cpufreq/Makefile
--- linux-libre-4.9-gnu/drivers/cpufreq/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -51,12 +51,12 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ)	+=
 # LITTLE drivers, so that it is probed last.
 obj-$(CONFIG_ARM_DT_BL_CPUFREQ)		+= arm_big_little_dt.o
 
+obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ)	+= brcmstb-avs-cpufreq.o
 obj-$(CONFIG_ARCH_DAVINCI)		+= davinci-cpufreq.o
 obj-$(CONFIG_UX500_SOC_DB8500)		+= dbx500-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ)	+= exynos5440-cpufreq.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ)	+= highbank-cpufreq.o
 obj-$(CONFIG_ARM_IMX6Q_CPUFREQ)		+= imx6q-cpufreq.o
-obj-$(CONFIG_ARM_INTEGRATOR)		+= integrator-cpufreq.o
 obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ)	+= kirkwood-cpufreq.o
 obj-$(CONFIG_ARM_MT8173_CPUFREQ)	+= mt8173-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)	+= omap-cpufreq.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/powernv-cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/powernv-cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/powernv-cpufreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/powernv-cpufreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,10 @@
 #define PMSR_PSAFE_ENABLE	(1UL << 30)
 #define PMSR_SPR_EM_DISABLE	(1UL << 31)
 #define PMSR_MAX(x)		((x >> 32) & 0xFF)
+#define LPSTATE_SHIFT		48
+#define GPSTATE_SHIFT		56
+#define GET_LPSTATE(x)		(((x) >> LPSTATE_SHIFT) & 0xFF)
+#define GET_GPSTATE(x)		(((x) >> GPSTATE_SHIFT) & 0xFF)
 
 #define MAX_RAMP_DOWN_TIME				5120
 /*
@@ -592,7 +596,8 @@ void gpstate_timer_handler(unsigned long
 {
 	struct cpufreq_policy *policy = (struct cpufreq_policy *)data;
 	struct global_pstate_info *gpstates = policy->driver_data;
-	int gpstate_idx;
+	int gpstate_idx, lpstate_idx;
+	unsigned long val;
 	unsigned int time_diff = jiffies_to_msecs(jiffies)
 					- gpstates->last_sampled_time;
 	struct powernv_smp_call_data freq_data;
@@ -600,21 +605,37 @@ void gpstate_timer_handler(unsigned long
 	if (!spin_trylock(&gpstates->gpstate_lock))
 		return;
 
+	/*
+	 * If PMCR was last updated was using fast_swtich then
+	 * We may have wrong in gpstate->last_lpstate_idx
+	 * value. Hence, read from PMCR to get correct data.
+	 */
+	val = get_pmspr(SPRN_PMCR);
+	freq_data.gpstate_id = (s8)GET_GPSTATE(val);
+	freq_data.pstate_id = (s8)GET_LPSTATE(val);
+	if (freq_data.gpstate_id  == freq_data.pstate_id) {
+		reset_gpstates(policy);
+		spin_unlock(&gpstates->gpstate_lock);
+		return;
+	}
+
 	gpstates->last_sampled_time += time_diff;
 	gpstates->elapsed_time += time_diff;
-	freq_data.pstate_id = idx_to_pstate(gpstates->last_lpstate_idx);
 
-	if ((gpstates->last_gpstate_idx == gpstates->last_lpstate_idx) ||
-	    (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME)) {
+	if (gpstates->elapsed_time > MAX_RAMP_DOWN_TIME) {
 		gpstate_idx = pstate_to_idx(freq_data.pstate_id);
+		lpstate_idx = gpstate_idx;
 		reset_gpstates(policy);
 		gpstates->highest_lpstate_idx = gpstate_idx;
 	} else {
+		lpstate_idx = pstate_to_idx(freq_data.pstate_id);
 		gpstate_idx = calc_global_pstate(gpstates->elapsed_time,
 						 gpstates->highest_lpstate_idx,
-						 gpstates->last_lpstate_idx);
+						 lpstate_idx);
 	}
-
+	freq_data.gpstate_id = idx_to_pstate(gpstate_idx);
+	gpstates->last_gpstate_idx = gpstate_idx;
+	gpstates->last_lpstate_idx = lpstate_idx;
 	/*
 	 * If local pstate is equal to global pstate, rampdown is over
 	 * So timer is not required to be queued.
@@ -622,10 +643,6 @@ void gpstate_timer_handler(unsigned long
 	if (gpstate_idx != gpstates->last_lpstate_idx)
 		queue_gpstate_timer(gpstates);
 
-	freq_data.gpstate_id = idx_to_pstate(gpstate_idx);
-	gpstates->last_gpstate_idx = pstate_to_idx(freq_data.gpstate_id);
-	gpstates->last_lpstate_idx = pstate_to_idx(freq_data.pstate_id);
-
 	spin_unlock(&gpstates->gpstate_lock);
 
 	/* Timer may get migrated to a different cpu on cpu hot unplug */
@@ -647,8 +664,14 @@ static int powernv_cpufreq_target_index(
 	if (unlikely(rebooting) && new_index != get_nominal_index())
 		return 0;
 
-	if (!throttled)
+	if (!throttled) {
+		/* we don't want to be preempted while
+		 * checking if the CPU frequency has been throttled
+		 */
+		preempt_disable();
 		powernv_cpufreq_throttle_check(NULL);
+		preempt_enable();
+	}
 
 	cur_msec = jiffies_to_msecs(get_jiffies_64());
 
@@ -752,9 +775,12 @@ static int powernv_cpufreq_cpu_init(stru
 	spin_lock_init(&gpstates->gpstate_lock);
 	ret = cpufreq_table_validate_and_show(policy, powernv_freqs);
 
-	if (ret < 0)
+	if (ret < 0) {
 		kfree(policy->driver_data);
+		return ret;
+	}
 
+	policy->fast_switch_possible = true;
 	return ret;
 }
 
@@ -897,6 +923,20 @@ static void powernv_cpufreq_stop_cpu(str
 	del_timer_sync(&gpstates->timer);
 }
 
+static unsigned int powernv_fast_switch(struct cpufreq_policy *policy,
+					unsigned int target_freq)
+{
+	int index;
+	struct powernv_smp_call_data freq_data;
+
+	index = cpufreq_table_find_index_dl(policy, target_freq);
+	freq_data.pstate_id = powernv_freqs[index].driver_data;
+	freq_data.gpstate_id = powernv_freqs[index].driver_data;
+	set_pstate(&freq_data);
+
+	return powernv_freqs[index].frequency;
+}
+
 static struct cpufreq_driver powernv_cpufreq_driver = {
 	.name		= "powernv-cpufreq",
 	.flags		= CPUFREQ_CONST_LOOPS,
@@ -904,6 +944,7 @@ static struct cpufreq_driver powernv_cpu
 	.exit		= powernv_cpufreq_cpu_exit,
 	.verify		= cpufreq_generic_frequency_table_verify,
 	.target_index	= powernv_cpufreq_target_index,
+	.fast_switch	= powernv_fast_switch,
 	.get		= powernv_cpufreq_get,
 	.stop_cpu	= powernv_cpufreq_stop_cpu,
 	.attr		= powernv_cpu_freq_attr,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpufreq/s3c64xx-cpufreq.c linux-libre-4.10-rc8-gnu/drivers/cpufreq/s3c64xx-cpufreq.c
--- linux-libre-4.9-gnu/drivers/cpufreq/s3c64xx-cpufreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpufreq/s3c64xx-cpufreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -107,7 +107,7 @@ static int s3c64xx_cpufreq_set_target(st
 }
 
 #ifdef CONFIG_REGULATOR
-static void __init s3c64xx_cpufreq_config_regulator(void)
+static void s3c64xx_cpufreq_config_regulator(void)
 {
 	int count, v, i, found;
 	struct cpufreq_frequency_table *freq;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpuidle/cpuidle.c linux-libre-4.10-rc8-gnu/drivers/cpuidle/cpuidle.c
--- linux-libre-4.9-gnu/drivers/cpuidle/cpuidle.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpuidle/cpuidle.c	2017-02-12 16:03:20.000000000 -0500
@@ -97,7 +97,23 @@ static int find_deepest_state(struct cpu
 	return ret;
 }
 
-#ifdef CONFIG_SUSPEND
+/**
+ * cpuidle_use_deepest_state - Set/clear governor override flag.
+ * @enable: New value of the flag.
+ *
+ * Set/unset the current CPU to use the deepest idle state (override governors
+ * going forward if set).
+ */
+void cpuidle_use_deepest_state(bool enable)
+{
+	struct cpuidle_device *dev;
+
+	preempt_disable();
+	dev = cpuidle_get_device();
+	dev->use_deepest_state = enable;
+	preempt_enable();
+}
+
 /**
  * cpuidle_find_deepest_state - Find the deepest available idle state.
  * @drv: cpuidle driver for the given CPU.
@@ -109,6 +125,7 @@ int cpuidle_find_deepest_state(struct cp
 	return find_deepest_state(drv, dev, UINT_MAX, 0, false);
 }
 
+#ifdef CONFIG_SUSPEND
 static void enter_freeze_proper(struct cpuidle_driver *drv,
 				struct cpuidle_device *dev, int index)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpuidle/cpuidle-powernv.c linux-libre-4.10-rc8-gnu/drivers/cpuidle/cpuidle-powernv.c
--- linux-libre-4.9-gnu/drivers/cpuidle/cpuidle-powernv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpuidle/cpuidle-powernv.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 
 #define POWERNV_THRESHOLD_LATENCY_NS 200000
 
-struct cpuidle_driver powernv_idle_driver = {
+static struct cpuidle_driver powernv_idle_driver = {
 	.name             = "powernv_idle",
 	.owner            = THIS_MODULE,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpuidle/dt_idle_states.c linux-libre-4.10-rc8-gnu/drivers/cpuidle/dt_idle_states.c
--- linux-libre-4.9-gnu/drivers/cpuidle/dt_idle_states.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpuidle/dt_idle_states.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,12 @@ static int init_state_node(struct cpuidl
 	 * state enter function.
 	 */
 	idle_state->enter = match_id->data;
+	/*
+	 * Since this is not a "coupled" state, it's safe to assume interrupts
+	 * won't be enabled when it exits allowing the tick to be frozen
+	 * safely. So enter() can be also enter_freeze() callback.
+	 */
+	idle_state->enter_freeze = match_id->data;
 
 	err = of_property_read_u32(state_node, "wakeup-latency-us",
 				   &idle_state->exit_latency);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpuidle/governor.c linux-libre-4.10-rc8-gnu/drivers/cpuidle/governor.c
--- linux-libre-4.9-gnu/drivers/cpuidle/governor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpuidle/governor.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,6 @@
  */
 
 #include <linux/mutex.h>
-#include <linux/module.h>
 #include <linux/cpuidle.h>
 
 #include "cpuidle.h"
@@ -53,14 +52,11 @@ int cpuidle_switch_governor(struct cpuid
 	if (cpuidle_curr_governor) {
 		list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
 			cpuidle_disable_device(dev);
-		module_put(cpuidle_curr_governor->owner);
 	}
 
 	cpuidle_curr_governor = gov;
 
 	if (gov) {
-		if (!try_module_get(cpuidle_curr_governor->owner))
-			return -EINVAL;
 		list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
 			cpuidle_enable_device(dev);
 		cpuidle_install_idle_handler();
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpuidle/governors/ladder.c linux-libre-4.10-rc8-gnu/drivers/cpuidle/governors/ladder.c
--- linux-libre-4.9-gnu/drivers/cpuidle/governors/ladder.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpuidle/governors/ladder.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,12 +15,11 @@
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
 #include <linux/pm_qos.h>
-#include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/tick.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define PROMOTION_COUNT 4
 #define DEMOTION_COUNT 1
@@ -177,7 +176,6 @@ static struct cpuidle_governor ladder_go
 	.enable =	ladder_enable_device,
 	.select =	ladder_select_state,
 	.reflect =	ladder_reflect,
-	.owner =	THIS_MODULE,
 };
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpuidle/governors/menu.c linux-libre-4.10-rc8-gnu/drivers/cpuidle/governors/menu.c
--- linux-libre-4.9-gnu/drivers/cpuidle/governors/menu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpuidle/governors/menu.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,6 @@
 #include <linux/tick.h>
 #include <linux/sched.h>
 #include <linux/math64.h>
-#include <linux/module.h>
 
 /*
  * Please note when changing the tuning values:
@@ -484,7 +483,6 @@ static struct cpuidle_governor menu_gove
 	.enable =	menu_enable_device,
 	.select =	menu_select,
 	.reflect =	menu_reflect,
-	.owner =	THIS_MODULE,
 };
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/cpuidle/sysfs.c linux-libre-4.10-rc8-gnu/drivers/cpuidle/sysfs.c
--- linux-libre-4.9-gnu/drivers/cpuidle/sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/cpuidle/sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -403,8 +403,10 @@ static int cpuidle_add_state_sysfs(struc
 	/* state statistics */
 	for (i = 0; i < drv->state_count; i++) {
 		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
-		if (!kobj)
+		if (!kobj) {
+			ret = -ENOMEM;
 			goto error_state;
+		}
 		kobj->state = &drv->states[i];
 		kobj->state_usage = &device->states_usage[i];
 		init_completion(&kobj->kobj_unregister);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/amcc/crypto4xx_core.c linux-libre-4.10-rc8-gnu/drivers/crypto/amcc/crypto4xx_core.c
--- linux-libre-4.9-gnu/drivers/crypto/amcc/crypto4xx_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/amcc/crypto4xx_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -135,8 +135,7 @@ int crypto4xx_alloc_sa(struct crypto4xx_
 	ctx->sa_out = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4,
 					 &ctx->sa_out_dma_addr, GFP_ATOMIC);
 	if (ctx->sa_out == NULL) {
-		dma_free_coherent(ctx->dev->core_dev->device,
-				  ctx->sa_len * 4,
+		dma_free_coherent(ctx->dev->core_dev->device, size * 4,
 				  ctx->sa_in, ctx->sa_in_dma_addr);
 		return -ENOMEM;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/atmel-aes.c linux-libre-4.10-rc8-gnu/drivers/crypto/atmel-aes.c
--- linux-libre-4.9-gnu/drivers/crypto/atmel-aes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/atmel-aes.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,7 @@
 #include <crypto/scatterwalk.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
+#include <crypto/xts.h>
 #include <crypto/internal/aead.h>
 #include <linux/platform_data/crypto-atmel.h>
 #include <dt-bindings/dma/at91.h>
@@ -68,6 +69,7 @@
 #define AES_FLAGS_CFB8		(AES_MR_OPMOD_CFB | AES_MR_CFBS_8b)
 #define AES_FLAGS_CTR		AES_MR_OPMOD_CTR
 #define AES_FLAGS_GCM		AES_MR_OPMOD_GCM
+#define AES_FLAGS_XTS		AES_MR_OPMOD_XTS
 
 #define AES_FLAGS_MODE_MASK	(AES_FLAGS_OPMODE_MASK |	\
 				 AES_FLAGS_ENCRYPT |		\
@@ -89,6 +91,7 @@ struct atmel_aes_caps {
 	bool			has_cfb64;
 	bool			has_ctr32;
 	bool			has_gcm;
+	bool			has_xts;
 	u32			max_burst_size;
 };
 
@@ -135,6 +138,12 @@ struct atmel_aes_gcm_ctx {
 	atmel_aes_fn_t		ghash_resume;
 };
 
+struct atmel_aes_xts_ctx {
+	struct atmel_aes_base_ctx	base;
+
+	u32			key2[AES_KEYSIZE_256 / sizeof(u32)];
+};
+
 struct atmel_aes_reqctx {
 	unsigned long		mode;
 };
@@ -282,6 +291,20 @@ static const char *atmel_aes_reg_name(u3
 		snprintf(tmp, sz, "GCMHR[%u]", (offset - AES_GCMHR(0)) >> 2);
 		break;
 
+	case AES_TWR(0):
+	case AES_TWR(1):
+	case AES_TWR(2):
+	case AES_TWR(3):
+		snprintf(tmp, sz, "TWR[%u]", (offset - AES_TWR(0)) >> 2);
+		break;
+
+	case AES_ALPHAR(0):
+	case AES_ALPHAR(1):
+	case AES_ALPHAR(2):
+	case AES_ALPHAR(3):
+		snprintf(tmp, sz, "ALPHAR[%u]", (offset - AES_ALPHAR(0)) >> 2);
+		break;
+
 	default:
 		snprintf(tmp, sz, "0x%02x", offset);
 		break;
@@ -317,7 +340,7 @@ static inline void atmel_aes_write(struc
 		char tmp[16];
 
 		dev_vdbg(dd->dev, "write 0x%08x into %s\n", value,
-			 atmel_aes_reg_name(offset, tmp));
+			 atmel_aes_reg_name(offset, tmp, sizeof(tmp)));
 	}
 #endif /* VERBOSE_DEBUG */
 
@@ -453,15 +476,15 @@ static inline int atmel_aes_complete(str
 	return err;
 }
 
-static void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
-				 const u32 *iv)
+static void atmel_aes_write_ctrl_key(struct atmel_aes_dev *dd, bool use_dma,
+				     const u32 *iv, const u32 *key, int keylen)
 {
 	u32 valmr = 0;
 
 	/* MR register must be set before IV registers */
-	if (dd->ctx->keylen == AES_KEYSIZE_128)
+	if (keylen == AES_KEYSIZE_128)
 		valmr |= AES_MR_KEYSIZE_128;
-	else if (dd->ctx->keylen == AES_KEYSIZE_192)
+	else if (keylen == AES_KEYSIZE_192)
 		valmr |= AES_MR_KEYSIZE_192;
 	else
 		valmr |= AES_MR_KEYSIZE_256;
@@ -478,13 +501,19 @@ static void atmel_aes_write_ctrl(struct
 
 	atmel_aes_write(dd, AES_MR, valmr);
 
-	atmel_aes_write_n(dd, AES_KEYWR(0), dd->ctx->key,
-			  SIZE_IN_WORDS(dd->ctx->keylen));
+	atmel_aes_write_n(dd, AES_KEYWR(0), key, SIZE_IN_WORDS(keylen));
 
 	if (iv && (valmr & AES_MR_OPMOD_MASK) != AES_MR_OPMOD_ECB)
 		atmel_aes_write_block(dd, AES_IVR(0), iv);
 }
 
+static inline void atmel_aes_write_ctrl(struct atmel_aes_dev *dd, bool use_dma,
+					const u32 *iv)
+
+{
+	atmel_aes_write_ctrl_key(dd, use_dma, iv,
+				 dd->ctx->key, dd->ctx->keylen);
+}
 
 /* CPU transfer */
 
@@ -1769,6 +1798,137 @@ static struct aead_alg aes_gcm_alg = {
 };
 
 
+/* xts functions */
+
+static inline struct atmel_aes_xts_ctx *
+atmel_aes_xts_ctx_cast(struct atmel_aes_base_ctx *ctx)
+{
+	return container_of(ctx, struct atmel_aes_xts_ctx, base);
+}
+
+static int atmel_aes_xts_process_data(struct atmel_aes_dev *dd);
+
+static int atmel_aes_xts_start(struct atmel_aes_dev *dd)
+{
+	struct atmel_aes_xts_ctx *ctx = atmel_aes_xts_ctx_cast(dd->ctx);
+	struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+	struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+	unsigned long flags;
+	int err;
+
+	atmel_aes_set_mode(dd, rctx);
+
+	err = atmel_aes_hw_init(dd);
+	if (err)
+		return atmel_aes_complete(dd, err);
+
+	/* Compute the tweak value from req->info with ecb(aes). */
+	flags = dd->flags;
+	dd->flags &= ~AES_FLAGS_MODE_MASK;
+	dd->flags |= (AES_FLAGS_ECB | AES_FLAGS_ENCRYPT);
+	atmel_aes_write_ctrl_key(dd, false, NULL,
+				 ctx->key2, ctx->base.keylen);
+	dd->flags = flags;
+
+	atmel_aes_write_block(dd, AES_IDATAR(0), req->info);
+	return atmel_aes_wait_for_data_ready(dd, atmel_aes_xts_process_data);
+}
+
+static int atmel_aes_xts_process_data(struct atmel_aes_dev *dd)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+	bool use_dma = (req->nbytes >= ATMEL_AES_DMA_THRESHOLD);
+	u32 tweak[AES_BLOCK_SIZE / sizeof(u32)];
+	static const u32 one[AES_BLOCK_SIZE / sizeof(u32)] = {cpu_to_le32(1), };
+	u8 *tweak_bytes = (u8 *)tweak;
+	int i;
+
+	/* Read the computed ciphered tweak value. */
+	atmel_aes_read_block(dd, AES_ODATAR(0), tweak);
+	/*
+	 * Hardware quirk:
+	 * the order of the ciphered tweak bytes need to be reversed before
+	 * writing them into the ODATARx registers.
+	 */
+	for (i = 0; i < AES_BLOCK_SIZE/2; ++i) {
+		u8 tmp = tweak_bytes[AES_BLOCK_SIZE - 1 - i];
+
+		tweak_bytes[AES_BLOCK_SIZE - 1 - i] = tweak_bytes[i];
+		tweak_bytes[i] = tmp;
+	}
+
+	/* Process the data. */
+	atmel_aes_write_ctrl(dd, use_dma, NULL);
+	atmel_aes_write_block(dd, AES_TWR(0), tweak);
+	atmel_aes_write_block(dd, AES_ALPHAR(0), one);
+	if (use_dma)
+		return atmel_aes_dma_start(dd, req->src, req->dst, req->nbytes,
+					   atmel_aes_transfer_complete);
+
+	return atmel_aes_cpu_start(dd, req->src, req->dst, req->nbytes,
+				   atmel_aes_transfer_complete);
+}
+
+static int atmel_aes_xts_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
+				unsigned int keylen)
+{
+	struct atmel_aes_xts_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	int err;
+
+	err = xts_check_key(crypto_ablkcipher_tfm(tfm), key, keylen);
+	if (err)
+		return err;
+
+	memcpy(ctx->base.key, key, keylen/2);
+	memcpy(ctx->key2, key + keylen/2, keylen/2);
+	ctx->base.keylen = keylen/2;
+
+	return 0;
+}
+
+static int atmel_aes_xts_encrypt(struct ablkcipher_request *req)
+{
+	return atmel_aes_crypt(req, AES_FLAGS_XTS | AES_FLAGS_ENCRYPT);
+}
+
+static int atmel_aes_xts_decrypt(struct ablkcipher_request *req)
+{
+	return atmel_aes_crypt(req, AES_FLAGS_XTS);
+}
+
+static int atmel_aes_xts_cra_init(struct crypto_tfm *tfm)
+{
+	struct atmel_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct atmel_aes_reqctx);
+	ctx->base.start = atmel_aes_xts_start;
+
+	return 0;
+}
+
+static struct crypto_alg aes_xts_alg = {
+	.cra_name		= "xts(aes)",
+	.cra_driver_name	= "atmel-xts-aes",
+	.cra_priority		= ATMEL_AES_PRIORITY,
+	.cra_flags		= CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		= AES_BLOCK_SIZE,
+	.cra_ctxsize		= sizeof(struct atmel_aes_xts_ctx),
+	.cra_alignmask		= 0xf,
+	.cra_type		= &crypto_ablkcipher_type,
+	.cra_module		= THIS_MODULE,
+	.cra_init		= atmel_aes_xts_cra_init,
+	.cra_exit		= atmel_aes_cra_exit,
+	.cra_u.ablkcipher = {
+		.min_keysize	= 2 * AES_MIN_KEY_SIZE,
+		.max_keysize	= 2 * AES_MAX_KEY_SIZE,
+		.ivsize		= AES_BLOCK_SIZE,
+		.setkey		= atmel_aes_xts_setkey,
+		.encrypt	= atmel_aes_xts_encrypt,
+		.decrypt	= atmel_aes_xts_decrypt,
+	}
+};
+
+
 /* Probe functions */
 
 static int atmel_aes_buff_init(struct atmel_aes_dev *dd)
@@ -1877,6 +2037,9 @@ static void atmel_aes_unregister_algs(st
 {
 	int i;
 
+	if (dd->caps.has_xts)
+		crypto_unregister_alg(&aes_xts_alg);
+
 	if (dd->caps.has_gcm)
 		crypto_unregister_aead(&aes_gcm_alg);
 
@@ -1909,8 +2072,16 @@ static int atmel_aes_register_algs(struc
 			goto err_aes_gcm_alg;
 	}
 
+	if (dd->caps.has_xts) {
+		err = crypto_register_alg(&aes_xts_alg);
+		if (err)
+			goto err_aes_xts_alg;
+	}
+
 	return 0;
 
+err_aes_xts_alg:
+	crypto_unregister_aead(&aes_gcm_alg);
 err_aes_gcm_alg:
 	crypto_unregister_alg(&aes_cfb64_alg);
 err_aes_cfb64_alg:
@@ -1928,6 +2099,7 @@ static void atmel_aes_get_cap(struct atm
 	dd->caps.has_cfb64 = 0;
 	dd->caps.has_ctr32 = 0;
 	dd->caps.has_gcm = 0;
+	dd->caps.has_xts = 0;
 	dd->caps.max_burst_size = 1;
 
 	/* keep only major version number */
@@ -1937,6 +2109,7 @@ static void atmel_aes_get_cap(struct atm
 		dd->caps.has_cfb64 = 1;
 		dd->caps.has_ctr32 = 1;
 		dd->caps.has_gcm = 1;
+		dd->caps.has_xts = 1;
 		dd->caps.max_burst_size = 4;
 		break;
 	case 0x200:
@@ -2138,7 +2311,7 @@ aes_dd_err:
 
 static int atmel_aes_remove(struct platform_device *pdev)
 {
-	static struct atmel_aes_dev *aes_dd;
+	struct atmel_aes_dev *aes_dd;
 
 	aes_dd = platform_get_drvdata(pdev);
 	if (!aes_dd)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/atmel-aes-regs.h linux-libre-4.10-rc8-gnu/drivers/crypto/atmel-aes-regs.h
--- linux-libre-4.9-gnu/drivers/crypto/atmel-aes-regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/atmel-aes-regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
 #define AES_MR_OPMOD_CFB		(0x3 << 12)
 #define AES_MR_OPMOD_CTR		(0x4 << 12)
 #define AES_MR_OPMOD_GCM		(0x5 << 12)
+#define AES_MR_OPMOD_XTS		(0x6 << 12)
 #define AES_MR_LOD				(0x1 << 15)
 #define AES_MR_CFBS_MASK		(0x7 << 16)
 #define AES_MR_CFBS_128b		(0x0 << 16)
@@ -67,6 +68,9 @@
 #define AES_CTRR	0x98
 #define AES_GCMHR(x)	(0x9c + ((x) * 0x04))
 
+#define AES_TWR(x)	(0xc0 + ((x) * 0x04))
+#define AES_ALPHAR(x)	(0xd0 + ((x) * 0x04))
+
 #define AES_HW_VERSION	0xFC
 
 #endif /* __ATMEL_AES_REGS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/caamalg.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamalg.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/caamalg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamalg.c	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,7 @@
  * caam - Freescale FSL CAAM support for crypto API
  *
  * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2016 NXP
  *
  * Based on talitos crypto API driver.
  *
@@ -53,6 +54,7 @@
 #include "error.h"
 #include "sg_sw_sec4.h"
 #include "key_gen.h"
+#include "caamalg_desc.h"
 
 /*
  * crypto alg
@@ -62,8 +64,6 @@
 #define CAAM_MAX_KEY_SIZE		(AES_MAX_KEY_SIZE + \
 					 CTR_RFC3686_NONCE_SIZE + \
 					 SHA512_DIGEST_SIZE * 2)
-/* max IV is max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
-#define CAAM_MAX_IV_LENGTH		16
 
 #define AEAD_DESC_JOB_IO_LEN		(DESC_JOB_IO_LEN + CAAM_CMD_SZ * 2)
 #define GCM_DESC_JOB_IO_LEN		(AEAD_DESC_JOB_IO_LEN + \
@@ -71,37 +71,6 @@
 #define AUTHENC_DESC_JOB_IO_LEN		(AEAD_DESC_JOB_IO_LEN + \
 					 CAAM_CMD_SZ * 5)
 
-/* length of descriptors text */
-#define DESC_AEAD_BASE			(4 * CAAM_CMD_SZ)
-#define DESC_AEAD_ENC_LEN		(DESC_AEAD_BASE + 11 * CAAM_CMD_SZ)
-#define DESC_AEAD_DEC_LEN		(DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
-#define DESC_AEAD_GIVENC_LEN		(DESC_AEAD_ENC_LEN + 9 * CAAM_CMD_SZ)
-
-/* Note: Nonce is counted in enckeylen */
-#define DESC_AEAD_CTR_RFC3686_LEN	(4 * CAAM_CMD_SZ)
-
-#define DESC_AEAD_NULL_BASE		(3 * CAAM_CMD_SZ)
-#define DESC_AEAD_NULL_ENC_LEN		(DESC_AEAD_NULL_BASE + 11 * CAAM_CMD_SZ)
-#define DESC_AEAD_NULL_DEC_LEN		(DESC_AEAD_NULL_BASE + 13 * CAAM_CMD_SZ)
-
-#define DESC_GCM_BASE			(3 * CAAM_CMD_SZ)
-#define DESC_GCM_ENC_LEN		(DESC_GCM_BASE + 16 * CAAM_CMD_SZ)
-#define DESC_GCM_DEC_LEN		(DESC_GCM_BASE + 12 * CAAM_CMD_SZ)
-
-#define DESC_RFC4106_BASE		(3 * CAAM_CMD_SZ)
-#define DESC_RFC4106_ENC_LEN		(DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ)
-#define DESC_RFC4106_DEC_LEN		(DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ)
-
-#define DESC_RFC4543_BASE		(3 * CAAM_CMD_SZ)
-#define DESC_RFC4543_ENC_LEN		(DESC_RFC4543_BASE + 11 * CAAM_CMD_SZ)
-#define DESC_RFC4543_DEC_LEN		(DESC_RFC4543_BASE + 12 * CAAM_CMD_SZ)
-
-#define DESC_ABLKCIPHER_BASE		(3 * CAAM_CMD_SZ)
-#define DESC_ABLKCIPHER_ENC_LEN		(DESC_ABLKCIPHER_BASE + \
-					 20 * CAAM_CMD_SZ)
-#define DESC_ABLKCIPHER_DEC_LEN		(DESC_ABLKCIPHER_BASE + \
-					 15 * CAAM_CMD_SZ)
-
 #define DESC_MAX_USED_BYTES		(CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN)
 #define DESC_MAX_USED_LEN		(DESC_MAX_USED_BYTES / CAAM_CMD_SZ)
 
@@ -117,8 +86,7 @@
 
 static void dbg_dump_sg(const char *level, const char *prefix_str,
 			int prefix_type, int rowsize, int groupsize,
-			struct scatterlist *sg, size_t tlen, bool ascii,
-			bool may_sleep)
+			struct scatterlist *sg, size_t tlen, bool ascii)
 {
 	struct scatterlist *it;
 	void *it_page;
@@ -152,7 +120,6 @@ static struct list_head alg_list;
 struct caam_alg_entry {
 	int class1_alg_type;
 	int class2_alg_type;
-	int alg_op;
 	bool rfc3686;
 	bool geniv;
 };
@@ -163,52 +130,6 @@ struct caam_aead_alg {
 	bool registered;
 };
 
-/* Set DK bit in class 1 operation if shared */
-static inline void append_dec_op1(u32 *desc, u32 type)
-{
-	u32 *jump_cmd, *uncond_jump_cmd;
-
-	/* DK bit is valid only for AES */
-	if ((type & OP_ALG_ALGSEL_MASK) != OP_ALG_ALGSEL_AES) {
-		append_operation(desc, type | OP_ALG_AS_INITFINAL |
-				 OP_ALG_DECRYPT);
-		return;
-	}
-
-	jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
-	append_operation(desc, type | OP_ALG_AS_INITFINAL |
-			 OP_ALG_DECRYPT);
-	uncond_jump_cmd = append_jump(desc, JUMP_TEST_ALL);
-	set_jump_tgt_here(desc, jump_cmd);
-	append_operation(desc, type | OP_ALG_AS_INITFINAL |
-			 OP_ALG_DECRYPT | OP_ALG_AAI_DK);
-	set_jump_tgt_here(desc, uncond_jump_cmd);
-}
-
-/*
- * For aead functions, read payload and write payload,
- * both of which are specified in req->src and req->dst
- */
-static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
-{
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
-			     KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
-}
-
-/*
- * For ablkcipher encrypt and decrypt, read from req->src and
- * write to req->dst
- */
-static inline void ablkcipher_append_src_dst(u32 *desc)
-{
-	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 |
-			     KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
-}
-
 /*
  * per-session context
  */
@@ -220,147 +141,36 @@ struct caam_ctx {
 	dma_addr_t sh_desc_enc_dma;
 	dma_addr_t sh_desc_dec_dma;
 	dma_addr_t sh_desc_givenc_dma;
-	u32 class1_alg_type;
-	u32 class2_alg_type;
-	u32 alg_op;
 	u8 key[CAAM_MAX_KEY_SIZE];
 	dma_addr_t key_dma;
-	unsigned int enckeylen;
-	unsigned int split_key_len;
-	unsigned int split_key_pad_len;
+	struct alginfo adata;
+	struct alginfo cdata;
 	unsigned int authsize;
 };
 
-static void append_key_aead(u32 *desc, struct caam_ctx *ctx,
-			    int keys_fit_inline, bool is_rfc3686)
-{
-	u32 *nonce;
-	unsigned int enckeylen = ctx->enckeylen;
-
-	/*
-	 * RFC3686 specific:
-	 *	| ctx->key = {AUTH_KEY, ENC_KEY, NONCE}
-	 *	| enckeylen = encryption key size + nonce size
-	 */
-	if (is_rfc3686)
-		enckeylen -= CTR_RFC3686_NONCE_SIZE;
-
-	if (keys_fit_inline) {
-		append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
-				  ctx->split_key_len, CLASS_2 |
-				  KEY_DEST_MDHA_SPLIT | KEY_ENC);
-		append_key_as_imm(desc, (void *)ctx->key +
-				  ctx->split_key_pad_len, enckeylen,
-				  enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	} else {
-		append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
-			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
-		append_key(desc, ctx->key_dma + ctx->split_key_pad_len,
-			   enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	}
-
-	/* Load Counter into CONTEXT1 reg */
-	if (is_rfc3686) {
-		nonce = (u32 *)((void *)ctx->key + ctx->split_key_pad_len +
-			       enckeylen);
-		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
-				   LDST_CLASS_IND_CCB |
-				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
-		append_move(desc,
-			    MOVE_SRC_OUTFIFO |
-			    MOVE_DEST_CLASS1CTX |
-			    (16 << MOVE_OFFSET_SHIFT) |
-			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
-	}
-}
-
-static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
-				  int keys_fit_inline, bool is_rfc3686)
-{
-	u32 *key_jump_cmd;
-
-	/* Note: Context registers are saved. */
-	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
-
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-
-	append_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
-
-	set_jump_tgt_here(desc, key_jump_cmd);
-}
-
 static int aead_null_set_sh_desc(struct crypto_aead *aead)
 {
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline = false;
-	u32 *key_jump_cmd, *jump_cmd, *read_move_cmd, *write_move_cmd;
 	u32 *desc;
+	int rem_bytes = CAAM_DESC_BYTES_MAX - AEAD_DESC_JOB_IO_LEN -
+			ctx->adata.keylen_pad;
 
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	if (DESC_AEAD_NULL_ENC_LEN + AEAD_DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_AEAD_NULL_ENC_LEN) {
+		ctx->adata.key_inline = true;
+		ctx->adata.key_virt = ctx->key;
+	} else {
+		ctx->adata.key_inline = false;
+		ctx->adata.key_dma = ctx->key_dma;
+	}
 
 	/* aead_encrypt shared descriptor */
 	desc = ctx->sh_desc_enc;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
-				  ctx->split_key_len, CLASS_2 |
-				  KEY_DEST_MDHA_SPLIT | KEY_ENC);
-	else
-		append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
-			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* assoclen + cryptlen = seqinlen */
-	append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/* Prepare to read and write cryptlen + assoclen bytes */
-	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/*
-	 * MOVE_LEN opcode is not available in all SEC HW revisions,
-	 * thus need to do some magic, i.e. self-patch the descriptor
-	 * buffer.
-	 */
-	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
-				    MOVE_DEST_MATH3 |
-				    (0x6 << MOVE_LEN_SHIFT));
-	write_move_cmd = append_move(desc, MOVE_SRC_MATH3 |
-				     MOVE_DEST_DESCBUF |
-				     MOVE_WAITCOMP |
-				     (0x8 << MOVE_LEN_SHIFT));
-
-	/* Class 2 operation */
-	append_operation(desc, ctx->class2_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* Read and write cryptlen bytes */
-	aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
-
-	set_move_tgt_here(desc, read_move_cmd);
-	set_move_tgt_here(desc, write_move_cmd);
-	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
-	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
-		    MOVE_AUX_LS);
-
-	/* Write ICV */
-	append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
-			 LDST_SRCDST_BYTE_CONTEXT);
-
+	cnstr_shdsc_aead_null_encap(desc, &ctx->adata, ctx->authsize);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -368,84 +178,22 @@ static int aead_null_set_sh_desc(struct
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR,
-		       "aead null enc shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_AEAD_NULL_DEC_LEN + DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
-
-	desc = ctx->sh_desc_dec;
+	if (rem_bytes >= DESC_AEAD_NULL_DEC_LEN) {
+		ctx->adata.key_inline = true;
+		ctx->adata.key_virt = ctx->key;
+	} else {
+		ctx->adata.key_inline = false;
+		ctx->adata.key_dma = ctx->key_dma;
+	}
 
 	/* aead_decrypt shared descriptor */
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
-				  ctx->split_key_len, CLASS_2 |
-				  KEY_DEST_MDHA_SPLIT | KEY_ENC);
-	else
-		append_key(desc, ctx->key_dma, ctx->split_key_len, CLASS_2 |
-			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* Class 2 operation */
-	append_operation(desc, ctx->class2_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
-
-	/* assoclen + cryptlen = seqoutlen */
-	append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-
-	/* Prepare to read and write cryptlen + assoclen bytes */
-	append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
-
-	/*
-	 * MOVE_LEN opcode is not available in all SEC HW revisions,
-	 * thus need to do some magic, i.e. self-patch the descriptor
-	 * buffer.
-	 */
-	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
-				    MOVE_DEST_MATH2 |
-				    (0x6 << MOVE_LEN_SHIFT));
-	write_move_cmd = append_move(desc, MOVE_SRC_MATH2 |
-				     MOVE_DEST_DESCBUF |
-				     MOVE_WAITCOMP |
-				     (0x8 << MOVE_LEN_SHIFT));
-
-	/* Read and write cryptlen bytes */
-	aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
-
-	/*
-	 * Insert a NOP here, since we need at least 4 instructions between
-	 * code patching the descriptor buffer and the location being patched.
-	 */
-	jump_cmd = append_jump(desc, JUMP_TEST_ALL);
-	set_jump_tgt_here(desc, jump_cmd);
-
-	set_move_tgt_here(desc, read_move_cmd);
-	set_move_tgt_here(desc, write_move_cmd);
-	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
-	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
-		    MOVE_AUX_LS);
-	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
-
-	/* Load ICV */
-	append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 |
-			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
-
+	desc = ctx->sh_desc_dec;
+	cnstr_shdsc_aead_null_decap(desc, &ctx->adata, ctx->authsize);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -453,12 +201,6 @@ static int aead_null_set_sh_desc(struct
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR,
-		       "aead null dec shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	return 0;
 }
@@ -470,11 +212,11 @@ static int aead_set_sh_desc(struct crypt
 	unsigned int ivsize = crypto_aead_ivsize(aead);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline;
-	u32 geniv, moveiv;
 	u32 ctx1_iv_off = 0;
-	u32 *desc;
-	const bool ctr_mode = ((ctx->class1_alg_type & OP_ALG_AAI_MASK) ==
+	u32 *desc, *nonce = NULL;
+	u32 inl_mask;
+	unsigned int data_len[2];
+	const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) ==
 			       OP_ALG_AAI_CTR_MOD128);
 	const bool is_rfc3686 = alg->caam.rfc3686;
 
@@ -482,7 +224,7 @@ static int aead_set_sh_desc(struct crypt
 		return 0;
 
 	/* NULL encryption / decryption */
-	if (!ctx->enckeylen)
+	if (!ctx->cdata.keylen)
 		return aead_null_set_sh_desc(aead);
 
 	/*
@@ -497,8 +239,14 @@ static int aead_set_sh_desc(struct crypt
 	 * RFC3686 specific:
 	 *	CONTEXT1[255:128] = {NONCE, IV, COUNTER}
 	 */
-	if (is_rfc3686)
+	if (is_rfc3686) {
 		ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE;
+		nonce = (u32 *)((void *)ctx->key + ctx->adata.keylen_pad +
+				ctx->cdata.keylen - CTR_RFC3686_NONCE_SIZE);
+	}
+
+	data_len[0] = ctx->adata.keylen_pad;
+	data_len[1] = ctx->cdata.keylen;
 
 	if (alg->caam.geniv)
 		goto skip_enc;
@@ -507,54 +255,29 @@ static int aead_set_sh_desc(struct crypt
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_AEAD_ENC_LEN + AUTHENC_DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len + ctx->enckeylen +
-	    (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0) <=
-	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
-
-	/* aead_encrypt shared descriptor */
-	desc = ctx->sh_desc_enc;
-
-	/* Note: Context registers are saved. */
-	init_sh_desc_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
-
-	/* Class 2 operation */
-	append_operation(desc, ctx->class2_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* Read and write assoclen bytes */
-	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/* Skip assoc data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
-	/* read assoc before reading payload */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
-				      FIFOLDST_VLF);
-
-	/* Load Counter into CONTEXT1 reg */
-	if (is_rfc3686)
-		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
-				     LDST_SRCDST_BYTE_CONTEXT |
-				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
-				      LDST_OFFSET_SHIFT));
+	if (desc_inline_query(DESC_AEAD_ENC_LEN +
+			      (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0),
+			      AUTHENC_DESC_JOB_IO_LEN, data_len, &inl_mask,
+			      ARRAY_SIZE(data_len)) < 0)
+		return -EINVAL;
 
-	/* Class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
+	if (inl_mask & 1)
+		ctx->adata.key_virt = ctx->key;
+	else
+		ctx->adata.key_dma = ctx->key_dma;
 
-	/* Read and write cryptlen bytes */
-	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+	if (inl_mask & 2)
+		ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad;
+	else
+		ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad;
 
-	/* Write ICV */
-	append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
-			 LDST_SRCDST_BYTE_CONTEXT);
+	ctx->adata.key_inline = !!(inl_mask & 1);
+	ctx->cdata.key_inline = !!(inl_mask & 2);
 
+	/* aead_encrypt shared descriptor */
+	desc = ctx->sh_desc_enc;
+	cnstr_shdsc_aead_encap(desc, &ctx->cdata, &ctx->adata, ctx->authsize,
+			       is_rfc3686, nonce, ctx1_iv_off);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -562,79 +285,36 @@ static int aead_set_sh_desc(struct crypt
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "aead enc shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 skip_enc:
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_AEAD_DEC_LEN + AUTHENC_DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len + ctx->enckeylen +
-	    (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0) <=
-	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
-
-	/* aead_decrypt shared descriptor */
-	desc = ctx->sh_desc_dec;
-
-	/* Note: Context registers are saved. */
-	init_sh_desc_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
-
-	/* Class 2 operation */
-	append_operation(desc, ctx->class2_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+	if (desc_inline_query(DESC_AEAD_DEC_LEN +
+			      (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0),
+			      AUTHENC_DESC_JOB_IO_LEN, data_len, &inl_mask,
+			      ARRAY_SIZE(data_len)) < 0)
+		return -EINVAL;
 
-	/* Read and write assoclen bytes */
-	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-	if (alg->caam.geniv)
-		append_math_add_imm_u32(desc, VARSEQOUTLEN, REG3, IMM, ivsize);
+	if (inl_mask & 1)
+		ctx->adata.key_virt = ctx->key;
 	else
-		append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/* Skip assoc data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
-	/* read assoc before reading payload */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
-			     KEY_VLF);
-
-	if (alg->caam.geniv) {
-		append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
-				LDST_SRCDST_BYTE_CONTEXT |
-				(ctx1_iv_off << LDST_OFFSET_SHIFT));
-		append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO |
-			    (ctx1_iv_off << MOVE_OFFSET_SHIFT) | ivsize);
-	}
-
-	/* Load Counter into CONTEXT1 reg */
-	if (is_rfc3686)
-		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
-				     LDST_SRCDST_BYTE_CONTEXT |
-				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
-				      LDST_OFFSET_SHIFT));
+		ctx->adata.key_dma = ctx->key_dma;
 
-	/* Choose operation */
-	if (ctr_mode)
-		append_operation(desc, ctx->class1_alg_type |
-				 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT);
+	if (inl_mask & 2)
+		ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad;
 	else
-		append_dec_op1(desc, ctx->class1_alg_type);
-
-	/* Read and write cryptlen bytes */
-	append_math_add(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-	aead_append_src_dst(desc, FIFOLD_TYPE_MSG);
+		ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad;
 
-	/* Load ICV */
-	append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS2 |
-			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+	ctx->adata.key_inline = !!(inl_mask & 1);
+	ctx->cdata.key_inline = !!(inl_mask & 2);
 
+	/* aead_decrypt shared descriptor */
+	desc = ctx->sh_desc_dec;
+	cnstr_shdsc_aead_decap(desc, &ctx->cdata, &ctx->adata, ivsize,
+			       ctx->authsize, alg->caam.geniv, is_rfc3686,
+			       nonce, ctx1_iv_off);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -642,11 +322,6 @@ skip_enc:
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "aead dec shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	if (!alg->caam.geniv)
 		goto skip_givenc;
@@ -655,93 +330,30 @@ skip_enc:
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_AEAD_GIVENC_LEN + AUTHENC_DESC_JOB_IO_LEN +
-	    ctx->split_key_pad_len + ctx->enckeylen +
-	    (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0) <=
-	    CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
-
-	/* aead_givencrypt shared descriptor */
-	desc = ctx->sh_desc_enc;
-
-	/* Note: Context registers are saved. */
-	init_sh_desc_key_aead(desc, ctx, keys_fit_inline, is_rfc3686);
-
-	if (is_rfc3686)
-		goto copy_iv;
-
-	/* Generate IV */
-	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
-		NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
-		NFIFOENTRY_PTYPE_RND | (ivsize << NFIFOENTRY_DLEN_SHIFT);
-	append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
-			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
-	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
-	append_move(desc, MOVE_WAITCOMP |
-		    MOVE_SRC_INFIFO | MOVE_DEST_CLASS1CTX |
-		    (ctx1_iv_off << MOVE_OFFSET_SHIFT) |
-		    (ivsize << MOVE_LEN_SHIFT));
-	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
-
-copy_iv:
-	/* Copy IV to class 1 context */
-	append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_OUTFIFO |
-		    (ctx1_iv_off << MOVE_OFFSET_SHIFT) |
-		    (ivsize << MOVE_LEN_SHIFT));
-
-	/* Return to encryption */
-	append_operation(desc, ctx->class2_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* Read and write assoclen bytes */
-	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/* ivsize + cryptlen = seqoutlen - authsize */
-	append_math_sub_imm_u32(desc, REG3, SEQOUTLEN, IMM, ctx->authsize);
-
-	/* Skip assoc data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
-	/* read assoc before reading payload */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
-			     KEY_VLF);
-
-	/* Copy iv from outfifo to class 2 fifo */
-	moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
-		 NFIFOENTRY_DTYPE_MSG | (ivsize << NFIFOENTRY_DLEN_SHIFT);
-	append_load_imm_u32(desc, moveiv, LDST_CLASS_IND_CCB |
-			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
-	append_load_imm_u32(desc, ivsize, LDST_CLASS_2_CCB |
-			    LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM);
-
-	/* Load Counter into CONTEXT1 reg */
-	if (is_rfc3686)
-		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
-				     LDST_SRCDST_BYTE_CONTEXT |
-				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
-				      LDST_OFFSET_SHIFT));
-
-	/* Class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* Will write ivsize + cryptlen */
-	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	if (desc_inline_query(DESC_AEAD_GIVENC_LEN +
+			      (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0),
+			      AUTHENC_DESC_JOB_IO_LEN, data_len, &inl_mask,
+			      ARRAY_SIZE(data_len)) < 0)
+		return -EINVAL;
 
-	/* Not need to reload iv */
-	append_seq_fifo_load(desc, ivsize,
-			     FIFOLD_CLASS_SKIP);
+	if (inl_mask & 1)
+		ctx->adata.key_virt = ctx->key;
+	else
+		ctx->adata.key_dma = ctx->key_dma;
 
-	/* Will read cryptlen */
-	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+	if (inl_mask & 2)
+		ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad;
+	else
+		ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad;
 
-	/* Write ICV */
-	append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
-			 LDST_SRCDST_BYTE_CONTEXT);
+	ctx->adata.key_inline = !!(inl_mask & 1);
+	ctx->cdata.key_inline = !!(inl_mask & 2);
 
+	/* aead_givencrypt shared descriptor */
+	desc = ctx->sh_desc_enc;
+	cnstr_shdsc_aead_givencap(desc, &ctx->cdata, &ctx->adata, ivsize,
+				  ctx->authsize, is_rfc3686, nonce,
+				  ctx1_iv_off);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -749,11 +361,6 @@ copy_iv:
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "aead givenc shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 skip_givenc:
 	return 0;
@@ -774,12 +381,11 @@ static int gcm_set_sh_desc(struct crypto
 {
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline = false;
-	u32 *key_jump_cmd, *zero_payload_jump_cmd,
-	    *zero_assoc_jump_cmd1, *zero_assoc_jump_cmd2;
 	u32 *desc;
+	int rem_bytes = CAAM_DESC_BYTES_MAX - GCM_DESC_JOB_IO_LEN -
+			ctx->cdata.keylen;
 
-	if (!ctx->enckeylen || !ctx->authsize)
+	if (!ctx->cdata.keylen || !ctx->authsize)
 		return 0;
 
 	/*
@@ -787,82 +393,16 @@ static int gcm_set_sh_desc(struct crypto
 	 * Job Descriptor and Shared Descriptor
 	 * must fit into the 64-word Descriptor h/w Buffer
 	 */
-	if (DESC_GCM_ENC_LEN + GCM_DESC_JOB_IO_LEN +
-	    ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_GCM_ENC_LEN) {
+		ctx->cdata.key_inline = true;
+		ctx->cdata.key_virt = ctx->key;
+	} else {
+		ctx->cdata.key_inline = false;
+		ctx->cdata.key_dma = ctx->key_dma;
+	}
 
 	desc = ctx->sh_desc_enc;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* skip key loading if they are loaded due to sharing */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD | JUMP_COND_SELF);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	else
-		append_key(desc, ctx->key_dma, ctx->enckeylen,
-			   CLASS_1 | KEY_DEST_CLASS_REG);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* if assoclen + cryptlen is ZERO, skip to ICV write */
-	append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-	zero_assoc_jump_cmd2 = append_jump(desc, JUMP_TEST_ALL |
-						 JUMP_COND_MATH_Z);
-
-	/* if assoclen is ZERO, skip reading the assoc data */
-	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-	zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
-						 JUMP_COND_MATH_Z);
-
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/* skip assoc data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
-	/* cryptlen = seqinlen - assoclen */
-	append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
-
-	/* if cryptlen is ZERO jump to zero-payload commands */
-	zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
-					    JUMP_COND_MATH_Z);
-
-	/* read assoc data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
-	set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
-
-	append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/* write encrypted data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
-
-	/* read payload data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
-
-	/* jump the zero-payload commands */
-	append_jump(desc, JUMP_TEST_ALL | 2);
-
-	/* zero-payload commands */
-	set_jump_tgt_here(desc, zero_payload_jump_cmd);
-
-	/* read assoc data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST1);
-
-	/* There is no input data */
-	set_jump_tgt_here(desc, zero_assoc_jump_cmd2);
-
-	/* write ICV */
-	append_seq_store(desc, ctx->authsize, LDST_CLASS_1_CCB |
-			 LDST_SRCDST_BYTE_CONTEXT);
-
+	cnstr_shdsc_gcm_encap(desc, &ctx->cdata, ctx->authsize);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -870,80 +410,21 @@ static int gcm_set_sh_desc(struct crypto
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "gcm enc shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_GCM_DEC_LEN + GCM_DESC_JOB_IO_LEN +
-	    ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_GCM_DEC_LEN) {
+		ctx->cdata.key_inline = true;
+		ctx->cdata.key_virt = ctx->key;
+	} else {
+		ctx->cdata.key_inline = false;
+		ctx->cdata.key_dma = ctx->key_dma;
+	}
 
 	desc = ctx->sh_desc_dec;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* skip key loading if they are loaded due to sharing */
-	key_jump_cmd = append_jump(desc, JUMP_JSL |
-				   JUMP_TEST_ALL | JUMP_COND_SHRD |
-				   JUMP_COND_SELF);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	else
-		append_key(desc, ctx->key_dma, ctx->enckeylen,
-			   CLASS_1 | KEY_DEST_CLASS_REG);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
-
-	/* if assoclen is ZERO, skip reading the assoc data */
-	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
-	zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
-						 JUMP_COND_MATH_Z);
-
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/* skip assoc data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
-	/* read assoc data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
-
-	set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
-
-	/* cryptlen = seqoutlen - assoclen */
-	append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-
-	/* jump to zero-payload command if cryptlen is zero */
-	zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
-					    JUMP_COND_MATH_Z);
-
-	append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-
-	/* store encrypted data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
-
-	/* read payload data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
-
-	/* zero-payload command */
-	set_jump_tgt_here(desc, zero_payload_jump_cmd);
-
-	/* read ICV */
-	append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS1 |
-			     FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
-
+	cnstr_shdsc_gcm_decap(desc, &ctx->cdata, ctx->authsize);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -951,11 +432,6 @@ static int gcm_set_sh_desc(struct crypto
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "gcm dec shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	return 0;
 }
@@ -974,11 +450,11 @@ static int rfc4106_set_sh_desc(struct cr
 {
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline = false;
-	u32 *key_jump_cmd;
 	u32 *desc;
+	int rem_bytes = CAAM_DESC_BYTES_MAX - GCM_DESC_JOB_IO_LEN -
+			ctx->cdata.keylen;
 
-	if (!ctx->enckeylen || !ctx->authsize)
+	if (!ctx->cdata.keylen || !ctx->authsize)
 		return 0;
 
 	/*
@@ -986,62 +462,16 @@ static int rfc4106_set_sh_desc(struct cr
 	 * Job Descriptor and Shared Descriptor
 	 * must fit into the 64-word Descriptor h/w Buffer
 	 */
-	if (DESC_RFC4106_ENC_LEN + GCM_DESC_JOB_IO_LEN +
-	    ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_RFC4106_ENC_LEN) {
+		ctx->cdata.key_inline = true;
+		ctx->cdata.key_virt = ctx->key;
+	} else {
+		ctx->cdata.key_inline = false;
+		ctx->cdata.key_dma = ctx->key_dma;
+	}
 
 	desc = ctx->sh_desc_enc;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* Skip key loading if it is loaded due to sharing */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	else
-		append_key(desc, ctx->key_dma, ctx->enckeylen,
-			   CLASS_1 | KEY_DEST_CLASS_REG);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* Class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/* Read assoc data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
-
-	/* Skip IV */
-	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
-
-	/* Will read cryptlen bytes */
-	append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
-
-	/* Skip assoc data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
-	/* cryptlen = seqoutlen - assoclen */
-	append_math_sub(desc, VARSEQOUTLEN, VARSEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/* Write encrypted data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
-
-	/* Read payload data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
-
-	/* Write ICV */
-	append_seq_store(desc, ctx->authsize, LDST_CLASS_1_CCB |
-			 LDST_SRCDST_BYTE_CONTEXT);
-
+	cnstr_shdsc_rfc4106_encap(desc, &ctx->cdata, ctx->authsize);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -1049,73 +479,21 @@ static int rfc4106_set_sh_desc(struct cr
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "rfc4106 enc shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_RFC4106_DEC_LEN + DESC_JOB_IO_LEN +
-	    ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_RFC4106_DEC_LEN) {
+		ctx->cdata.key_inline = true;
+		ctx->cdata.key_virt = ctx->key;
+	} else {
+		ctx->cdata.key_inline = false;
+		ctx->cdata.key_dma = ctx->key_dma;
+	}
 
 	desc = ctx->sh_desc_dec;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* Skip key loading if it is loaded due to sharing */
-	key_jump_cmd = append_jump(desc, JUMP_JSL |
-				   JUMP_TEST_ALL | JUMP_COND_SHRD);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	else
-		append_key(desc, ctx->key_dma, ctx->enckeylen,
-			   CLASS_1 | KEY_DEST_CLASS_REG);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* Class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
-
-	append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
-	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
-
-	/* Read assoc data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
-
-	/* Skip IV */
-	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
-
-	/* Will read cryptlen bytes */
-	append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG3, CAAM_CMD_SZ);
-
-	/* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
-
-	/* Skip assoc data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
-
-	/* Will write cryptlen bytes */
-	append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-
-	/* Store payload data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
-
-	/* Read encrypted data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
-			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
-
-	/* Read ICV */
-	append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS1 |
-			     FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
-
+	cnstr_shdsc_rfc4106_decap(desc, &ctx->cdata, ctx->authsize);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -1123,11 +501,6 @@ static int rfc4106_set_sh_desc(struct cr
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "rfc4106 dec shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	return 0;
 }
@@ -1147,12 +520,11 @@ static int rfc4543_set_sh_desc(struct cr
 {
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
-	bool keys_fit_inline = false;
-	u32 *key_jump_cmd;
-	u32 *read_move_cmd, *write_move_cmd;
 	u32 *desc;
+	int rem_bytes = CAAM_DESC_BYTES_MAX - GCM_DESC_JOB_IO_LEN -
+			ctx->cdata.keylen;
 
-	if (!ctx->enckeylen || !ctx->authsize)
+	if (!ctx->cdata.keylen || !ctx->authsize)
 		return 0;
 
 	/*
@@ -1160,61 +532,16 @@ static int rfc4543_set_sh_desc(struct cr
 	 * Job Descriptor and Shared Descriptor
 	 * must fit into the 64-word Descriptor h/w Buffer
 	 */
-	if (DESC_RFC4543_ENC_LEN + GCM_DESC_JOB_IO_LEN +
-	    ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_RFC4543_ENC_LEN) {
+		ctx->cdata.key_inline = true;
+		ctx->cdata.key_virt = ctx->key;
+	} else {
+		ctx->cdata.key_inline = false;
+		ctx->cdata.key_dma = ctx->key_dma;
+	}
 
 	desc = ctx->sh_desc_enc;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* Skip key loading if it is loaded due to sharing */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	else
-		append_key(desc, ctx->key_dma, ctx->enckeylen,
-			   CLASS_1 | KEY_DEST_CLASS_REG);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* Class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* assoclen + cryptlen = seqinlen */
-	append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/*
-	 * MOVE_LEN opcode is not available in all SEC HW revisions,
-	 * thus need to do some magic, i.e. self-patch the descriptor
-	 * buffer.
-	 */
-	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 |
-				    (0x6 << MOVE_LEN_SHIFT));
-	write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF |
-				     (0x8 << MOVE_LEN_SHIFT));
-
-	/* Will read assoclen + cryptlen bytes */
-	append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/* Will write assoclen + cryptlen bytes */
-	append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/* Read and write assoclen + cryptlen bytes */
-	aead_append_src_dst(desc, FIFOLD_TYPE_AAD);
-
-	set_move_tgt_here(desc, read_move_cmd);
-	set_move_tgt_here(desc, write_move_cmd);
-	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
-	/* Move payload data to OFIFO */
-	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO);
-
-	/* Write ICV */
-	append_seq_store(desc, ctx->authsize, LDST_CLASS_1_CCB |
-			 LDST_SRCDST_BYTE_CONTEXT);
-
+	cnstr_shdsc_rfc4543_encap(desc, &ctx->cdata, ctx->authsize);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -1222,77 +549,21 @@ static int rfc4543_set_sh_desc(struct cr
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "rfc4543 enc shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	/*
 	 * Job Descriptor and Shared Descriptors
 	 * must all fit into the 64-word Descriptor h/w Buffer
 	 */
-	keys_fit_inline = false;
-	if (DESC_RFC4543_DEC_LEN + GCM_DESC_JOB_IO_LEN +
-	    ctx->enckeylen <= CAAM_DESC_BYTES_MAX)
-		keys_fit_inline = true;
+	if (rem_bytes >= DESC_RFC4543_DEC_LEN) {
+		ctx->cdata.key_inline = true;
+		ctx->cdata.key_virt = ctx->key;
+	} else {
+		ctx->cdata.key_inline = false;
+		ctx->cdata.key_dma = ctx->key_dma;
+	}
 
 	desc = ctx->sh_desc_dec;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* Skip key loading if it is loaded due to sharing */
-	key_jump_cmd = append_jump(desc, JUMP_JSL |
-				   JUMP_TEST_ALL | JUMP_COND_SHRD);
-	if (keys_fit_inline)
-		append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-				  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-	else
-		append_key(desc, ctx->key_dma, ctx->enckeylen,
-			   CLASS_1 | KEY_DEST_CLASS_REG);
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* Class 1 operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT | OP_ALG_ICV_ON);
-
-	/* assoclen + cryptlen = seqoutlen */
-	append_math_sub(desc, REG3, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-
-	/*
-	 * MOVE_LEN opcode is not available in all SEC HW revisions,
-	 * thus need to do some magic, i.e. self-patch the descriptor
-	 * buffer.
-	 */
-	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 |
-				    (0x6 << MOVE_LEN_SHIFT));
-	write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF |
-				     (0x8 << MOVE_LEN_SHIFT));
-
-	/* Will read assoclen + cryptlen bytes */
-	append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-
-	/* Will write assoclen + cryptlen bytes */
-	append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
-
-	/* Store payload data */
-	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
-
-	/* In-snoop assoclen + cryptlen data */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | FIFOLDST_VLF |
-			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST2FLUSH1);
-
-	set_move_tgt_here(desc, read_move_cmd);
-	set_move_tgt_here(desc, write_move_cmd);
-	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
-	/* Move payload data to OFIFO */
-	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO);
-	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
-
-	/* Read ICV */
-	append_seq_fifo_load(desc, ctx->authsize, FIFOLD_CLASS_CLASS1 |
-			     FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
-
+	cnstr_shdsc_rfc4543_decap(desc, &ctx->cdata, ctx->authsize);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -1300,11 +571,6 @@ static int rfc4543_set_sh_desc(struct cr
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "rfc4543 dec shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
 	return 0;
 }
@@ -1320,19 +586,9 @@ static int rfc4543_setauthsize(struct cr
 	return 0;
 }
 
-static u32 gen_split_aead_key(struct caam_ctx *ctx, const u8 *key_in,
-			      u32 authkeylen)
-{
-	return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len,
-			       ctx->split_key_pad_len, key_in, authkeylen,
-			       ctx->alg_op);
-}
-
 static int aead_setkey(struct crypto_aead *aead,
 			       const u8 *key, unsigned int keylen)
 {
-	/* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
-	static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
 	struct device *jrdev = ctx->jrdev;
 	struct crypto_authenc_keys keys;
@@ -1341,33 +597,25 @@ static int aead_setkey(struct crypto_aea
 	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
 		goto badkey;
 
-	/* Pick class 2 key length from algorithm submask */
-	ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
-				      OP_ALG_ALGSEL_SHIFT] * 2;
-	ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
-
-	if (ctx->split_key_pad_len + keys.enckeylen > CAAM_MAX_KEY_SIZE)
-		goto badkey;
-
 #ifdef DEBUG
 	printk(KERN_ERR "keylen %d enckeylen %d authkeylen %d\n",
 	       keys.authkeylen + keys.enckeylen, keys.enckeylen,
 	       keys.authkeylen);
-	printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n",
-	       ctx->split_key_len, ctx->split_key_pad_len);
 	print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
 #endif
 
-	ret = gen_split_aead_key(ctx, keys.authkey, keys.authkeylen);
+	ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, keys.authkey,
+			    keys.authkeylen, CAAM_MAX_KEY_SIZE -
+			    keys.enckeylen);
 	if (ret) {
 		goto badkey;
 	}
 
 	/* postpend encryption key to auth split key */
-	memcpy(ctx->key + ctx->split_key_pad_len, keys.enckey, keys.enckeylen);
+	memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen);
 
-	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len +
+	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->adata.keylen_pad +
 				      keys.enckeylen, DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->key_dma)) {
 		dev_err(jrdev, "unable to map key i/o memory\n");
@@ -1376,14 +624,14 @@ static int aead_setkey(struct crypto_aea
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
-		       ctx->split_key_pad_len + keys.enckeylen, 1);
+		       ctx->adata.keylen_pad + keys.enckeylen, 1);
 #endif
 
-	ctx->enckeylen = keys.enckeylen;
+	ctx->cdata.keylen = keys.enckeylen;
 
 	ret = aead_set_sh_desc(aead);
 	if (ret) {
-		dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len +
+		dma_unmap_single(jrdev, ctx->key_dma, ctx->adata.keylen_pad +
 				 keys.enckeylen, DMA_TO_DEVICE);
 	}
 
@@ -1412,11 +660,11 @@ static int gcm_setkey(struct crypto_aead
 		dev_err(jrdev, "unable to map key i/o memory\n");
 		return -ENOMEM;
 	}
-	ctx->enckeylen = keylen;
+	ctx->cdata.keylen = keylen;
 
 	ret = gcm_set_sh_desc(aead);
 	if (ret) {
-		dma_unmap_single(jrdev, ctx->key_dma, ctx->enckeylen,
+		dma_unmap_single(jrdev, ctx->key_dma, ctx->cdata.keylen,
 				 DMA_TO_DEVICE);
 	}
 
@@ -1444,9 +692,9 @@ static int rfc4106_setkey(struct crypto_
 	 * The last four bytes of the key material are used as the salt value
 	 * in the nonce. Update the AES key length.
 	 */
-	ctx->enckeylen = keylen - 4;
+	ctx->cdata.keylen = keylen - 4;
 
-	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->enckeylen,
+	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->cdata.keylen,
 				      DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->key_dma)) {
 		dev_err(jrdev, "unable to map key i/o memory\n");
@@ -1455,7 +703,7 @@ static int rfc4106_setkey(struct crypto_
 
 	ret = rfc4106_set_sh_desc(aead);
 	if (ret) {
-		dma_unmap_single(jrdev, ctx->key_dma, ctx->enckeylen,
+		dma_unmap_single(jrdev, ctx->key_dma, ctx->cdata.keylen,
 				 DMA_TO_DEVICE);
 	}
 
@@ -1483,9 +731,9 @@ static int rfc4543_setkey(struct crypto_
 	 * The last four bytes of the key material are used as the salt value
 	 * in the nonce. Update the AES key length.
 	 */
-	ctx->enckeylen = keylen - 4;
+	ctx->cdata.keylen = keylen - 4;
 
-	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->enckeylen,
+	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->cdata.keylen,
 				      DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->key_dma)) {
 		dev_err(jrdev, "unable to map key i/o memory\n");
@@ -1494,7 +742,7 @@ static int rfc4543_setkey(struct crypto_
 
 	ret = rfc4543_set_sh_desc(aead);
 	if (ret) {
-		dma_unmap_single(jrdev, ctx->key_dma, ctx->enckeylen,
+		dma_unmap_single(jrdev, ctx->key_dma, ctx->cdata.keylen,
 				 DMA_TO_DEVICE);
 	}
 
@@ -1505,21 +753,18 @@ static int ablkcipher_setkey(struct cryp
 			     const u8 *key, unsigned int keylen)
 {
 	struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
-	struct ablkcipher_tfm *crt = &ablkcipher->base.crt_ablkcipher;
 	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(ablkcipher);
 	const char *alg_name = crypto_tfm_alg_name(tfm);
 	struct device *jrdev = ctx->jrdev;
-	int ret = 0;
-	u32 *key_jump_cmd;
+	unsigned int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 	u32 *desc;
-	u8 *nonce;
-	u32 geniv;
 	u32 ctx1_iv_off = 0;
-	const bool ctr_mode = ((ctx->class1_alg_type & OP_ALG_AAI_MASK) ==
+	const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) ==
 			       OP_ALG_AAI_CTR_MOD128);
 	const bool is_rfc3686 = (ctr_mode &&
 				 (strstr(alg_name, "rfc3686") != NULL));
 
+	memcpy(ctx->key, key, keylen);
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
@@ -1542,60 +787,20 @@ static int ablkcipher_setkey(struct cryp
 		keylen -= CTR_RFC3686_NONCE_SIZE;
 	}
 
-	memcpy(ctx->key, key, keylen);
 	ctx->key_dma = dma_map_single(jrdev, ctx->key, keylen,
 				      DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->key_dma)) {
 		dev_err(jrdev, "unable to map key i/o memory\n");
 		return -ENOMEM;
 	}
-	ctx->enckeylen = keylen;
+	ctx->cdata.keylen = keylen;
+	ctx->cdata.key_virt = ctx->key;
+	ctx->cdata.key_inline = true;
 
 	/* ablkcipher_encrypt shared descriptor */
 	desc = ctx->sh_desc_enc;
-	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-
-	/* Load class1 key only */
-	append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-			  ctx->enckeylen, CLASS_1 |
-			  KEY_DEST_CLASS_REG);
-
-	/* Load nonce into CONTEXT1 reg */
-	if (is_rfc3686) {
-		nonce = (u8 *)key + keylen;
-		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
-				   LDST_CLASS_IND_CCB |
-				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
-		append_move(desc, MOVE_WAITCOMP |
-			    MOVE_SRC_OUTFIFO |
-			    MOVE_DEST_CLASS1CTX |
-			    (16 << MOVE_OFFSET_SHIFT) |
-			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
-	}
-
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* Load iv */
-	append_seq_load(desc, crt->ivsize, LDST_SRCDST_BYTE_CONTEXT |
-			LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
-
-	/* Load counter into CONTEXT1 reg */
-	if (is_rfc3686)
-		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
-				     LDST_SRCDST_BYTE_CONTEXT |
-				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
-				      LDST_OFFSET_SHIFT));
-
-	/* Load operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* Perform operation */
-	ablkcipher_append_src_dst(desc);
-
+	cnstr_shdsc_ablkcipher_encap(desc, &ctx->cdata, ivsize, is_rfc3686,
+				     ctx1_iv_off);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -1603,61 +808,11 @@ static int ablkcipher_setkey(struct cryp
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR,
-		       "ablkcipher enc shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
+
 	/* ablkcipher_decrypt shared descriptor */
 	desc = ctx->sh_desc_dec;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-
-	/* Load class1 key only */
-	append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-			  ctx->enckeylen, CLASS_1 |
-			  KEY_DEST_CLASS_REG);
-
-	/* Load nonce into CONTEXT1 reg */
-	if (is_rfc3686) {
-		nonce = (u8 *)key + keylen;
-		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
-				   LDST_CLASS_IND_CCB |
-				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
-		append_move(desc, MOVE_WAITCOMP |
-			    MOVE_SRC_OUTFIFO |
-			    MOVE_DEST_CLASS1CTX |
-			    (16 << MOVE_OFFSET_SHIFT) |
-			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
-	}
-
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* load IV */
-	append_seq_load(desc, crt->ivsize, LDST_SRCDST_BYTE_CONTEXT |
-			LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
-
-	/* Load counter into CONTEXT1 reg */
-	if (is_rfc3686)
-		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
-				     LDST_SRCDST_BYTE_CONTEXT |
-				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
-				      LDST_OFFSET_SHIFT));
-
-	/* Choose operation */
-	if (ctr_mode)
-		append_operation(desc, ctx->class1_alg_type |
-				 OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT);
-	else
-		append_dec_op1(desc, ctx->class1_alg_type);
-
-	/* Perform operation */
-	ablkcipher_append_src_dst(desc);
-
+	cnstr_shdsc_ablkcipher_decap(desc, &ctx->cdata, ivsize, is_rfc3686,
+				     ctx1_iv_off);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc,
 					      desc_bytes(desc),
 					      DMA_TO_DEVICE);
@@ -1666,76 +821,10 @@ static int ablkcipher_setkey(struct cryp
 		return -ENOMEM;
 	}
 
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR,
-		       "ablkcipher dec shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 	/* ablkcipher_givencrypt shared descriptor */
 	desc = ctx->sh_desc_givenc;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-
-	/* Load class1 key only */
-	append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-			  ctx->enckeylen, CLASS_1 |
-			  KEY_DEST_CLASS_REG);
-
-	/* Load Nonce into CONTEXT1 reg */
-	if (is_rfc3686) {
-		nonce = (u8 *)key + keylen;
-		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
-				   LDST_CLASS_IND_CCB |
-				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
-		append_move(desc, MOVE_WAITCOMP |
-			    MOVE_SRC_OUTFIFO |
-			    MOVE_DEST_CLASS1CTX |
-			    (16 << MOVE_OFFSET_SHIFT) |
-			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
-	}
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/* Generate IV */
-	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
-		NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
-		NFIFOENTRY_PTYPE_RND | (crt->ivsize << NFIFOENTRY_DLEN_SHIFT);
-	append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
-			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
-	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
-	append_move(desc, MOVE_WAITCOMP |
-		    MOVE_SRC_INFIFO |
-		    MOVE_DEST_CLASS1CTX |
-		    (crt->ivsize << MOVE_LEN_SHIFT) |
-		    (ctx1_iv_off << MOVE_OFFSET_SHIFT));
-	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
-
-	/* Copy generated IV to memory */
-	append_seq_store(desc, crt->ivsize,
-			 LDST_SRCDST_BYTE_CONTEXT | LDST_CLASS_1_CCB |
-			 (ctx1_iv_off << LDST_OFFSET_SHIFT));
-
-	/* Load Counter into CONTEXT1 reg */
-	if (is_rfc3686)
-		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
-				     LDST_SRCDST_BYTE_CONTEXT |
-				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
-				      LDST_OFFSET_SHIFT));
-
-	if (ctx1_iv_off)
-		append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | JUMP_COND_NCP |
-			    (1 << JUMP_OFFSET_SHIFT));
-
-	/* Load operation */
-	append_operation(desc, ctx->class1_alg_type |
-			 OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT);
-
-	/* Perform operation */
-	ablkcipher_append_src_dst(desc);
-
+	cnstr_shdsc_ablkcipher_givencap(desc, &ctx->cdata, ivsize, is_rfc3686,
+					ctx1_iv_off);
 	ctx->sh_desc_givenc_dma = dma_map_single(jrdev, desc,
 						 desc_bytes(desc),
 						 DMA_TO_DEVICE);
@@ -1743,14 +832,8 @@ static int ablkcipher_setkey(struct cryp
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR,
-		       "ablkcipher givenc shdesc@" __stringify(__LINE__) ": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
 
-	return ret;
+	return 0;
 }
 
 static int xts_ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
@@ -1758,8 +841,7 @@ static int xts_ablkcipher_setkey(struct
 {
 	struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher);
 	struct device *jrdev = ctx->jrdev;
-	u32 *key_jump_cmd, *desc;
-	__be64 sector_size = cpu_to_be64(512);
+	u32 *desc;
 
 	if (keylen != 2 * AES_MIN_KEY_SIZE  && keylen != 2 * AES_MAX_KEY_SIZE) {
 		crypto_ablkcipher_set_flags(ablkcipher,
@@ -1774,88 +856,23 @@ static int xts_ablkcipher_setkey(struct
 		dev_err(jrdev, "unable to map key i/o memory\n");
 		return -ENOMEM;
 	}
-	ctx->enckeylen = keylen;
+	ctx->cdata.keylen = keylen;
+	ctx->cdata.key_virt = ctx->key;
+	ctx->cdata.key_inline = true;
 
 	/* xts_ablkcipher_encrypt shared descriptor */
 	desc = ctx->sh_desc_enc;
-	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-
-	/* Load class1 keys only */
-	append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-			  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-
-	/* Load sector size with index 40 bytes (0x28) */
-	append_cmd(desc, CMD_LOAD | IMMEDIATE | LDST_SRCDST_BYTE_CONTEXT |
-		   LDST_CLASS_1_CCB | (0x28 << LDST_OFFSET_SHIFT) | 8);
-	append_data(desc, (void *)&sector_size, 8);
-
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/*
-	 * create sequence for loading the sector index
-	 * Upper 8B of IV - will be used as sector index
-	 * Lower 8B of IV - will be discarded
-	 */
-	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
-		   LDST_CLASS_1_CCB | (0x20 << LDST_OFFSET_SHIFT) | 8);
-	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
-
-	/* Load operation */
-	append_operation(desc, ctx->class1_alg_type | OP_ALG_AS_INITFINAL |
-			 OP_ALG_ENCRYPT);
-
-	/* Perform operation */
-	ablkcipher_append_src_dst(desc);
-
+	cnstr_shdsc_xts_ablkcipher_encap(desc, &ctx->cdata);
 	ctx->sh_desc_enc_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
 					      DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->sh_desc_enc_dma)) {
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR,
-		       "xts ablkcipher enc shdesc@" __stringify(__LINE__) ": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
-#endif
 
 	/* xts_ablkcipher_decrypt shared descriptor */
 	desc = ctx->sh_desc_dec;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
-	/* Skip if already shared */
-	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-				   JUMP_COND_SHRD);
-
-	/* Load class1 key only */
-	append_key_as_imm(desc, (void *)ctx->key, ctx->enckeylen,
-			  ctx->enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
-
-	/* Load sector size with index 40 bytes (0x28) */
-	append_cmd(desc, CMD_LOAD | IMMEDIATE | LDST_SRCDST_BYTE_CONTEXT |
-		   LDST_CLASS_1_CCB | (0x28 << LDST_OFFSET_SHIFT) | 8);
-	append_data(desc, (void *)&sector_size, 8);
-
-	set_jump_tgt_here(desc, key_jump_cmd);
-
-	/*
-	 * create sequence for loading the sector index
-	 * Upper 8B of IV - will be used as sector index
-	 * Lower 8B of IV - will be discarded
-	 */
-	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
-		   LDST_CLASS_1_CCB | (0x20 << LDST_OFFSET_SHIFT) | 8);
-	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
-
-	/* Load operation */
-	append_dec_op1(desc, ctx->class1_alg_type);
-
-	/* Perform operation */
-	ablkcipher_append_src_dst(desc);
-
+	cnstr_shdsc_xts_ablkcipher_decap(desc, &ctx->cdata);
 	ctx->sh_desc_dec_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
 					      DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->sh_desc_dec_dma)) {
@@ -1864,31 +881,22 @@ static int xts_ablkcipher_setkey(struct
 		dev_err(jrdev, "unable to map shared descriptor\n");
 		return -ENOMEM;
 	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR,
-		       "xts ablkcipher dec shdesc@" __stringify(__LINE__) ": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
-#endif
 
 	return 0;
 }
 
 /*
  * aead_edesc - s/w-extended aead descriptor
- * @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
  * @src_nents: number of segments in input scatterlist
  * @dst_nents: number of segments in output scatterlist
- * @iv_dma: dma address of iv for checking continuity and link table
- * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
  * @sec4_sg_bytes: length of dma mapped sec4_sg space
  * @sec4_sg_dma: bus physical mapped address of h/w link table
+ * @sec4_sg: pointer to h/w link table
  * @hw_desc: the h/w job descriptor followed by any referenced link tables
  */
 struct aead_edesc {
-	int assoc_nents;
 	int src_nents;
 	int dst_nents;
-	dma_addr_t iv_dma;
 	int sec4_sg_bytes;
 	dma_addr_t sec4_sg_dma;
 	struct sec4_sg_entry *sec4_sg;
@@ -1900,9 +908,9 @@ struct aead_edesc {
  * @src_nents: number of segments in input scatterlist
  * @dst_nents: number of segments in output scatterlist
  * @iv_dma: dma address of iv for checking continuity and link table
- * @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
  * @sec4_sg_bytes: length of dma mapped sec4_sg space
  * @sec4_sg_dma: bus physical mapped address of h/w link table
+ * @sec4_sg: pointer to h/w link table
  * @hw_desc: the h/w job descriptor followed by any referenced link tables
  */
 struct ablkcipher_edesc {
@@ -2019,8 +1027,7 @@ static void ablkcipher_encrypt_done(stru
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
-	edesc = (struct ablkcipher_edesc *)((char *)desc -
-		 offsetof(struct ablkcipher_edesc, hw_desc));
+	edesc = container_of(desc, struct ablkcipher_edesc, hw_desc[0]);
 
 	if (err)
 		caam_jr_strstatus(jrdev, err);
@@ -2031,7 +1038,7 @@ static void ablkcipher_encrypt_done(stru
 		       edesc->src_nents > 1 ? 100 : ivsize, 1);
 	dbg_dump_sg(KERN_ERR, "dst    @"__stringify(__LINE__)": ",
 		    DUMP_PREFIX_ADDRESS, 16, 4, req->dst,
-		    edesc->dst_nents > 1 ? 100 : req->nbytes, 1, true);
+		    edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
 #endif
 
 	ablkcipher_unmap(jrdev, edesc, req);
@@ -2052,8 +1059,7 @@ static void ablkcipher_decrypt_done(stru
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
-	edesc = (struct ablkcipher_edesc *)((char *)desc -
-		 offsetof(struct ablkcipher_edesc, hw_desc));
+	edesc = container_of(desc, struct ablkcipher_edesc, hw_desc[0]);
 	if (err)
 		caam_jr_strstatus(jrdev, err);
 
@@ -2063,7 +1069,7 @@ static void ablkcipher_decrypt_done(stru
 		       ivsize, 1);
 	dbg_dump_sg(KERN_ERR, "dst    @"__stringify(__LINE__)": ",
 		    DUMP_PREFIX_ADDRESS, 16, 4, req->dst,
-		    edesc->dst_nents > 1 ? 100 : req->nbytes, 1, true);
+		    edesc->dst_nents > 1 ? 100 : req->nbytes, 1);
 #endif
 
 	ablkcipher_unmap(jrdev, edesc, req);
@@ -2157,7 +1163,7 @@ static void init_gcm_job(struct aead_req
 			 FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1 | 12 | last);
 	/* Append Salt */
 	if (!generic_gcm)
-		append_data(desc, ctx->key + ctx->enckeylen, 4);
+		append_data(desc, ctx->key + ctx->cdata.keylen, 4);
 	/* Append IV */
 	append_data(desc, req->iv, ivsize);
 	/* End of blank commands */
@@ -2172,7 +1178,7 @@ static void init_authenc_job(struct aead
 						 struct caam_aead_alg, aead);
 	unsigned int ivsize = crypto_aead_ivsize(aead);
 	struct caam_ctx *ctx = crypto_aead_ctx(aead);
-	const bool ctr_mode = ((ctx->class1_alg_type & OP_ALG_AAI_MASK) ==
+	const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) ==
 			       OP_ALG_AAI_CTR_MOD128);
 	const bool is_rfc3686 = alg->caam.rfc3686;
 	u32 *desc = edesc->hw_desc;
@@ -2218,15 +1224,13 @@ static void init_ablkcipher_job(u32 *sh_
 	int len, sec4_sg_index = 0;
 
 #ifdef DEBUG
-	bool may_sleep = ((req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
-					      CRYPTO_TFM_REQ_MAY_SLEEP)) != 0);
 	print_hex_dump(KERN_ERR, "presciv@"__stringify(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, req->info,
 		       ivsize, 1);
 	printk(KERN_ERR "asked=%d, nbytes%d\n", (int)edesc->src_nents ? 100 : req->nbytes, req->nbytes);
 	dbg_dump_sg(KERN_ERR, "src    @"__stringify(__LINE__)": ",
 		    DUMP_PREFIX_ADDRESS, 16, 4, req->src,
-		    edesc->src_nents ? 100 : req->nbytes, 1, may_sleep);
+		    edesc->src_nents ? 100 : req->nbytes, 1);
 #endif
 
 	len = desc_len(sh_desc);
@@ -2278,14 +1282,12 @@ static void init_ablkcipher_giv_job(u32
 	int len, sec4_sg_index = 0;
 
 #ifdef DEBUG
-	bool may_sleep = ((req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
-					      CRYPTO_TFM_REQ_MAY_SLEEP)) != 0);
 	print_hex_dump(KERN_ERR, "presciv@" __stringify(__LINE__) ": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, req->info,
 		       ivsize, 1);
 	dbg_dump_sg(KERN_ERR, "src    @" __stringify(__LINE__) ": ",
 		    DUMP_PREFIX_ADDRESS, 16, 4, req->src,
-		    edesc->src_nents ? 100 : req->nbytes, 1, may_sleep);
+		    edesc->src_nents ? 100 : req->nbytes, 1);
 #endif
 
 	len = desc_len(sh_desc);
@@ -2344,10 +1346,8 @@ static struct aead_edesc *aead_edesc_all
 
 	/* Check if data are contiguous. */
 	all_contig = !src_nents;
-	if (!all_contig) {
-		src_nents = src_nents ? : 1;
+	if (!all_contig)
 		sec4_sg_len = src_nents;
-	}
 
 	sec4_sg_len += dst_nents;
 
@@ -2556,11 +1556,9 @@ static int aead_decrypt(struct aead_requ
 	int ret = 0;
 
 #ifdef DEBUG
-	bool may_sleep = ((req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
-					      CRYPTO_TFM_REQ_MAY_SLEEP)) != 0);
 	dbg_dump_sg(KERN_ERR, "dec src@"__stringify(__LINE__)": ",
 		    DUMP_PREFIX_ADDRESS, 16, 4, req->src,
-		    req->assoclen + req->cryptlen, 1, may_sleep);
+		    req->assoclen + req->cryptlen, 1);
 #endif
 
 	/* allocate extended descriptor */
@@ -2618,16 +1616,33 @@ static struct ablkcipher_edesc *ablkciph
 	if (likely(req->src == req->dst)) {
 		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
 				 DMA_BIDIRECTIONAL);
+		if (unlikely(!sgc)) {
+			dev_err(jrdev, "unable to map source\n");
+			return ERR_PTR(-ENOMEM);
+		}
 	} else {
 		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
 				 DMA_TO_DEVICE);
+		if (unlikely(!sgc)) {
+			dev_err(jrdev, "unable to map source\n");
+			return ERR_PTR(-ENOMEM);
+		}
+
 		sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
 				 DMA_FROM_DEVICE);
+		if (unlikely(!sgc)) {
+			dev_err(jrdev, "unable to map destination\n");
+			dma_unmap_sg(jrdev, req->src, src_nents ? : 1,
+				     DMA_TO_DEVICE);
+			return ERR_PTR(-ENOMEM);
+		}
 	}
 
 	iv_dma = dma_map_single(jrdev, req->info, ivsize, DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, iv_dma)) {
 		dev_err(jrdev, "unable to map IV\n");
+		caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
+			   0, 0, 0);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -2647,6 +1662,8 @@ static struct ablkcipher_edesc *ablkciph
 			GFP_DMA | flags);
 	if (!edesc) {
 		dev_err(jrdev, "could not allocate extended descriptor\n");
+		caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
+			   iv_dma, ivsize, 0, 0);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -2673,6 +1690,9 @@ static struct ablkcipher_edesc *ablkciph
 					    sec4_sg_bytes, DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
 		dev_err(jrdev, "unable to map S/G table\n");
+		caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
+			   iv_dma, ivsize, 0, 0);
+		kfree(edesc);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -2794,11 +1814,26 @@ static struct ablkcipher_edesc *ablkciph
 	if (likely(req->src == req->dst)) {
 		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
 				 DMA_BIDIRECTIONAL);
+		if (unlikely(!sgc)) {
+			dev_err(jrdev, "unable to map source\n");
+			return ERR_PTR(-ENOMEM);
+		}
 	} else {
 		sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
 				 DMA_TO_DEVICE);
+		if (unlikely(!sgc)) {
+			dev_err(jrdev, "unable to map source\n");
+			return ERR_PTR(-ENOMEM);
+		}
+
 		sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
 				 DMA_FROM_DEVICE);
+		if (unlikely(!sgc)) {
+			dev_err(jrdev, "unable to map destination\n");
+			dma_unmap_sg(jrdev, req->src, src_nents ? : 1,
+				     DMA_TO_DEVICE);
+			return ERR_PTR(-ENOMEM);
+		}
 	}
 
 	/*
@@ -2808,6 +1843,8 @@ static struct ablkcipher_edesc *ablkciph
 	iv_dma = dma_map_single(jrdev, greq->giv, ivsize, DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, iv_dma)) {
 		dev_err(jrdev, "unable to map IV\n");
+		caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents, 0,
+			   0, 0, 0);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -2823,6 +1860,8 @@ static struct ablkcipher_edesc *ablkciph
 			GFP_DMA | flags);
 	if (!edesc) {
 		dev_err(jrdev, "could not allocate extended descriptor\n");
+		caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
+			   iv_dma, ivsize, 0, 0);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -2850,6 +1889,9 @@ static struct ablkcipher_edesc *ablkciph
 					    sec4_sg_bytes, DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, edesc->sec4_sg_dma)) {
 		dev_err(jrdev, "unable to map S/G table\n");
+		caam_unmap(jrdev, req->src, req->dst, src_nents, dst_nents,
+			   iv_dma, ivsize, 0, 0);
+		kfree(edesc);
 		return ERR_PTR(-ENOMEM);
 	}
 	edesc->iv_dma = iv_dma;
@@ -2916,7 +1958,6 @@ struct caam_alg_template {
 	} template_u;
 	u32 class1_alg_type;
 	u32 class2_alg_type;
-	u32 alg_op;
 };
 
 static struct caam_alg_template driver_algs[] = {
@@ -3101,7 +2142,6 @@ static struct caam_aead_alg driver_aeads
 		.caam = {
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3123,7 +2163,6 @@ static struct caam_aead_alg driver_aeads
 		.caam = {
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3145,7 +2184,6 @@ static struct caam_aead_alg driver_aeads
 		.caam = {
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3167,7 +2205,6 @@ static struct caam_aead_alg driver_aeads
 		.caam = {
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3189,7 +2226,6 @@ static struct caam_aead_alg driver_aeads
 		.caam = {
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3211,7 +2247,6 @@ static struct caam_aead_alg driver_aeads
 		.caam = {
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3233,7 +2268,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3256,7 +2290,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3279,7 +2312,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3302,7 +2334,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3325,7 +2356,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3348,7 +2378,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3371,7 +2400,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3394,7 +2422,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3417,7 +2444,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3440,7 +2466,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3463,7 +2488,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3486,7 +2510,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3509,7 +2532,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 		}
 	},
 	{
@@ -3532,7 +2554,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		}
 	},
@@ -3556,7 +2577,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3580,7 +2600,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3604,7 +2623,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3628,7 +2646,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3652,7 +2669,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3676,7 +2692,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3700,7 +2715,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3724,7 +2738,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3748,7 +2761,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3772,7 +2784,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3795,7 +2806,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3818,7 +2828,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3841,7 +2850,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3864,7 +2872,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3887,7 +2894,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3910,7 +2916,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3933,7 +2938,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -3956,7 +2960,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -3979,7 +2982,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -4002,7 +3004,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -4025,7 +3026,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 		},
 	},
 	{
@@ -4048,7 +3048,6 @@ static struct caam_aead_alg driver_aeads
 			.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 			.geniv = true,
 		},
 	},
@@ -4073,7 +3072,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 		},
 	},
@@ -4098,7 +3096,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_MD5 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 			.geniv = true,
 		},
@@ -4124,7 +3121,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 		},
 	},
@@ -4149,7 +3145,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA1 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 			.geniv = true,
 		},
@@ -4175,7 +3170,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 		},
 	},
@@ -4200,7 +3194,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA224 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 			.geniv = true,
 		},
@@ -4226,7 +3219,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 		},
 	},
@@ -4251,7 +3243,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA256 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 			.geniv = true,
 		},
@@ -4277,7 +3268,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 		},
 	},
@@ -4302,7 +3292,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA384 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 			.geniv = true,
 		},
@@ -4328,7 +3317,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 		},
 	},
@@ -4353,7 +3341,6 @@ static struct caam_aead_alg driver_aeads
 					   OP_ALG_AAI_CTR_MOD128,
 			.class2_alg_type = OP_ALG_ALGSEL_SHA512 |
 					   OP_ALG_AAI_HMAC_PRECOMP,
-			.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 			.rfc3686 = true,
 			.geniv = true,
 		},
@@ -4375,9 +3362,8 @@ static int caam_init_common(struct caam_
 	}
 
 	/* copy descriptor header template value */
-	ctx->class1_alg_type = OP_TYPE_CLASS1_ALG | caam->class1_alg_type;
-	ctx->class2_alg_type = OP_TYPE_CLASS2_ALG | caam->class2_alg_type;
-	ctx->alg_op = OP_TYPE_CLASS2_ALG | caam->alg_op;
+	ctx->cdata.algtype = OP_TYPE_CLASS1_ALG | caam->class1_alg_type;
+	ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam->class2_alg_type;
 
 	return 0;
 }
@@ -4420,7 +3406,7 @@ static void caam_exit_common(struct caam
 	if (ctx->key_dma &&
 	    !dma_mapping_error(ctx->jrdev, ctx->key_dma))
 		dma_unmap_single(ctx->jrdev, ctx->key_dma,
-				 ctx->enckeylen + ctx->split_key_pad_len,
+				 ctx->cdata.keylen + ctx->adata.keylen_pad,
 				 DMA_TO_DEVICE);
 
 	caam_jr_free(ctx->jrdev);
@@ -4498,7 +3484,6 @@ static struct caam_crypto_alg *caam_alg_
 
 	t_alg->caam.class1_alg_type = template->class1_alg_type;
 	t_alg->caam.class2_alg_type = template->class2_alg_type;
-	t_alg->caam.alg_op = template->alg_op;
 
 	return t_alg;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/caamalg_desc.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamalg_desc.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/caamalg_desc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamalg_desc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1306 @@
+/*
+ * Shared descriptors for aead, ablkcipher algorithms
+ *
+ * Copyright 2016 NXP
+ */
+
+#include "compat.h"
+#include "desc_constr.h"
+#include "caamalg_desc.h"
+
+/*
+ * For aead functions, read payload and write payload,
+ * both of which are specified in req->src and req->dst
+ */
+static inline void aead_append_src_dst(u32 *desc, u32 msg_type)
+{
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH |
+			     KEY_VLF | msg_type | FIFOLD_TYPE_LASTBOTH);
+}
+
+/* Set DK bit in class 1 operation if shared */
+static inline void append_dec_op1(u32 *desc, u32 type)
+{
+	u32 *jump_cmd, *uncond_jump_cmd;
+
+	/* DK bit is valid only for AES */
+	if ((type & OP_ALG_ALGSEL_MASK) != OP_ALG_ALGSEL_AES) {
+		append_operation(desc, type | OP_ALG_AS_INITFINAL |
+				 OP_ALG_DECRYPT);
+		return;
+	}
+
+	jump_cmd = append_jump(desc, JUMP_TEST_ALL | JUMP_COND_SHRD);
+	append_operation(desc, type | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT);
+	uncond_jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+	set_jump_tgt_here(desc, jump_cmd);
+	append_operation(desc, type | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT | OP_ALG_AAI_DK);
+	set_jump_tgt_here(desc, uncond_jump_cmd);
+}
+
+/**
+ * cnstr_shdsc_aead_null_encap - IPSec ESP encapsulation shared descriptor
+ *                               (non-protocol) with no (null) encryption.
+ * @desc: pointer to buffer used for descriptor construction
+ * @adata: pointer to authentication transform definitions. Note that since a
+ *         split key is to be used, the size of the split key itself is
+ *         specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1,
+ *         SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ *
+ * Note: Requires an MDHA split key.
+ */
+void cnstr_shdsc_aead_null_encap(u32 * const desc, struct alginfo *adata,
+				 unsigned int icvsize)
+{
+	u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+	if (adata->key_inline)
+		append_key_as_imm(desc, adata->key_virt, adata->keylen_pad,
+				  adata->keylen, CLASS_2 | KEY_DEST_MDHA_SPLIT |
+				  KEY_ENC);
+	else
+		append_key(desc, adata->key_dma, adata->keylen, CLASS_2 |
+			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* assoclen + cryptlen = seqinlen */
+	append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* Prepare to read and write cryptlen + assoclen bytes */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/*
+	 * MOVE_LEN opcode is not available in all SEC HW revisions,
+	 * thus need to do some magic, i.e. self-patch the descriptor
+	 * buffer.
+	 */
+	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
+				    MOVE_DEST_MATH3 |
+				    (0x6 << MOVE_LEN_SHIFT));
+	write_move_cmd = append_move(desc, MOVE_SRC_MATH3 |
+				     MOVE_DEST_DESCBUF |
+				     MOVE_WAITCOMP |
+				     (0x8 << MOVE_LEN_SHIFT));
+
+	/* Class 2 operation */
+	append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Read and write cryptlen bytes */
+	aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
+
+	set_move_tgt_here(desc, read_move_cmd);
+	set_move_tgt_here(desc, write_move_cmd);
+	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
+		    MOVE_AUX_LS);
+
+	/* Write ICV */
+	append_seq_store(desc, icvsize, LDST_CLASS_2_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "aead null enc shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_aead_null_encap);
+
+/**
+ * cnstr_shdsc_aead_null_decap - IPSec ESP decapsulation shared descriptor
+ *                               (non-protocol) with no (null) decryption.
+ * @desc: pointer to buffer used for descriptor construction
+ * @adata: pointer to authentication transform definitions. Note that since a
+ *         split key is to be used, the size of the split key itself is
+ *         specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1,
+ *         SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ *
+ * Note: Requires an MDHA split key.
+ */
+void cnstr_shdsc_aead_null_decap(u32 * const desc, struct alginfo *adata,
+				 unsigned int icvsize)
+{
+	u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd, *jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+	if (adata->key_inline)
+		append_key_as_imm(desc, adata->key_virt, adata->keylen_pad,
+				  adata->keylen, CLASS_2 |
+				  KEY_DEST_MDHA_SPLIT | KEY_ENC);
+	else
+		append_key(desc, adata->key_dma, adata->keylen, CLASS_2 |
+			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Class 2 operation */
+	append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+	/* assoclen + cryptlen = seqoutlen */
+	append_math_sub(desc, REG2, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+
+	/* Prepare to read and write cryptlen + assoclen bytes */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG2, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG2, CAAM_CMD_SZ);
+
+	/*
+	 * MOVE_LEN opcode is not available in all SEC HW revisions,
+	 * thus need to do some magic, i.e. self-patch the descriptor
+	 * buffer.
+	 */
+	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF |
+				    MOVE_DEST_MATH2 |
+				    (0x6 << MOVE_LEN_SHIFT));
+	write_move_cmd = append_move(desc, MOVE_SRC_MATH2 |
+				     MOVE_DEST_DESCBUF |
+				     MOVE_WAITCOMP |
+				     (0x8 << MOVE_LEN_SHIFT));
+
+	/* Read and write cryptlen bytes */
+	aead_append_src_dst(desc, FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
+
+	/*
+	 * Insert a NOP here, since we need at least 4 instructions between
+	 * code patching the descriptor buffer and the location being patched.
+	 */
+	jump_cmd = append_jump(desc, JUMP_TEST_ALL);
+	set_jump_tgt_here(desc, jump_cmd);
+
+	set_move_tgt_here(desc, read_move_cmd);
+	set_move_tgt_here(desc, write_move_cmd);
+	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO |
+		    MOVE_AUX_LS);
+	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+	/* Load ICV */
+	append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS2 |
+			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "aead null dec shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_aead_null_decap);
+
+static void init_sh_desc_key_aead(u32 * const desc,
+				  struct alginfo * const cdata,
+				  struct alginfo * const adata,
+				  const bool is_rfc3686, u32 *nonce)
+{
+	u32 *key_jump_cmd;
+	unsigned int enckeylen = cdata->keylen;
+
+	/* Note: Context registers are saved. */
+	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/*
+	 * RFC3686 specific:
+	 *	| key = {AUTH_KEY, ENC_KEY, NONCE}
+	 *	| enckeylen = encryption key size + nonce size
+	 */
+	if (is_rfc3686)
+		enckeylen -= CTR_RFC3686_NONCE_SIZE;
+
+	if (adata->key_inline)
+		append_key_as_imm(desc, adata->key_virt, adata->keylen_pad,
+				  adata->keylen, CLASS_2 |
+				  KEY_DEST_MDHA_SPLIT | KEY_ENC);
+	else
+		append_key(desc, adata->key_dma, adata->keylen, CLASS_2 |
+			   KEY_DEST_MDHA_SPLIT | KEY_ENC);
+
+	if (cdata->key_inline)
+		append_key_as_imm(desc, cdata->key_virt, enckeylen,
+				  enckeylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	else
+		append_key(desc, cdata->key_dma, enckeylen, CLASS_1 |
+			   KEY_DEST_CLASS_REG);
+
+	/* Load Counter into CONTEXT1 reg */
+	if (is_rfc3686) {
+		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
+				   LDST_CLASS_IND_CCB |
+				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
+		append_move(desc,
+			    MOVE_SRC_OUTFIFO |
+			    MOVE_DEST_CLASS1CTX |
+			    (16 << MOVE_OFFSET_SHIFT) |
+			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
+	}
+
+	set_jump_tgt_here(desc, key_jump_cmd);
+}
+
+/**
+ * cnstr_shdsc_aead_encap - IPSec ESP encapsulation shared descriptor
+ *                          (non-protocol).
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
+ *         with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
+ * @adata: pointer to authentication transform definitions. Note that since a
+ *         split key is to be used, the size of the split key itself is
+ *         specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1,
+ *         SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
+ * @nonce: pointer to rfc3686 nonce
+ * @ctx1_iv_off: IV offset in CONTEXT1 register
+ *
+ * Note: Requires an MDHA split key.
+ */
+void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
+			    struct alginfo *adata, unsigned int icvsize,
+			    const bool is_rfc3686, u32 *nonce,
+			    const u32 ctx1_iv_off)
+{
+	/* Note: Context registers are saved. */
+	init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
+
+	/* Class 2 operation */
+	append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Read and write assoclen bytes */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/* Skip assoc data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+	/* read assoc before reading payload */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+				      FIFOLDST_VLF);
+
+	/* Load Counter into CONTEXT1 reg */
+	if (is_rfc3686)
+		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
+				     LDST_SRCDST_BYTE_CONTEXT |
+				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
+				      LDST_OFFSET_SHIFT));
+
+	/* Class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Read and write cryptlen bytes */
+	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+
+	/* Write ICV */
+	append_seq_store(desc, icvsize, LDST_CLASS_2_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead enc shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_aead_encap);
+
+/**
+ * cnstr_shdsc_aead_decap - IPSec ESP decapsulation shared descriptor
+ *                          (non-protocol).
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
+ *         with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
+ * @adata: pointer to authentication transform definitions. Note that since a
+ *         split key is to be used, the size of the split key itself is
+ *         specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1,
+ *         SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP.
+ * @ivsize: initialization vector size
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
+ * @nonce: pointer to rfc3686 nonce
+ * @ctx1_iv_off: IV offset in CONTEXT1 register
+ *
+ * Note: Requires an MDHA split key.
+ */
+void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
+			    struct alginfo *adata, unsigned int ivsize,
+			    unsigned int icvsize, const bool geniv,
+			    const bool is_rfc3686, u32 *nonce,
+			    const u32 ctx1_iv_off)
+{
+	/* Note: Context registers are saved. */
+	init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
+
+	/* Class 2 operation */
+	append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+	/* Read and write assoclen bytes */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+	if (geniv)
+		append_math_add_imm_u32(desc, VARSEQOUTLEN, REG3, IMM, ivsize);
+	else
+		append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/* Skip assoc data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+	/* read assoc before reading payload */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+			     KEY_VLF);
+
+	if (geniv) {
+		append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
+				LDST_SRCDST_BYTE_CONTEXT |
+				(ctx1_iv_off << LDST_OFFSET_SHIFT));
+		append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_CLASS2INFIFO |
+			    (ctx1_iv_off << MOVE_OFFSET_SHIFT) | ivsize);
+	}
+
+	/* Load Counter into CONTEXT1 reg */
+	if (is_rfc3686)
+		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
+				     LDST_SRCDST_BYTE_CONTEXT |
+				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
+				      LDST_OFFSET_SHIFT));
+
+	/* Choose operation */
+	if (ctx1_iv_off)
+		append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+				 OP_ALG_DECRYPT);
+	else
+		append_dec_op1(desc, cdata->algtype);
+
+	/* Read and write cryptlen bytes */
+	append_math_add(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+	aead_append_src_dst(desc, FIFOLD_TYPE_MSG);
+
+	/* Load ICV */
+	append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS2 |
+			     FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "aead dec shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_aead_decap);
+
+/**
+ * cnstr_shdsc_aead_givencap - IPSec ESP encapsulation shared descriptor
+ *                             (non-protocol) with HW-generated initialization
+ *                             vector.
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
+ *         with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
+ * @adata: pointer to authentication transform definitions. Note that since a
+ *         split key is to be used, the size of the split key itself is
+ *         specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1,
+ *         SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP.
+ * @ivsize: initialization vector size
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
+ * @nonce: pointer to rfc3686 nonce
+ * @ctx1_iv_off: IV offset in CONTEXT1 register
+ *
+ * Note: Requires an MDHA split key.
+ */
+void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata,
+			       struct alginfo *adata, unsigned int ivsize,
+			       unsigned int icvsize, const bool is_rfc3686,
+			       u32 *nonce, const u32 ctx1_iv_off)
+{
+	u32 geniv, moveiv;
+
+	/* Note: Context registers are saved. */
+	init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce);
+
+	if (is_rfc3686)
+		goto copy_iv;
+
+	/* Generate IV */
+	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
+		NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 |
+		NFIFOENTRY_PTYPE_RND | (ivsize << NFIFOENTRY_DLEN_SHIFT);
+	append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
+			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	append_move(desc, MOVE_WAITCOMP |
+		    MOVE_SRC_INFIFO | MOVE_DEST_CLASS1CTX |
+		    (ctx1_iv_off << MOVE_OFFSET_SHIFT) |
+		    (ivsize << MOVE_LEN_SHIFT));
+	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+copy_iv:
+	/* Copy IV to class 1 context */
+	append_move(desc, MOVE_SRC_CLASS1CTX | MOVE_DEST_OUTFIFO |
+		    (ctx1_iv_off << MOVE_OFFSET_SHIFT) |
+		    (ivsize << MOVE_LEN_SHIFT));
+
+	/* Return to encryption */
+	append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Read and write assoclen bytes */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/* Skip assoc data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+	/* read assoc before reading payload */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG |
+			     KEY_VLF);
+
+	/* Copy iv from outfifo to class 2 fifo */
+	moveiv = NFIFOENTRY_STYPE_OFIFO | NFIFOENTRY_DEST_CLASS2 |
+		 NFIFOENTRY_DTYPE_MSG | (ivsize << NFIFOENTRY_DLEN_SHIFT);
+	append_load_imm_u32(desc, moveiv, LDST_CLASS_IND_CCB |
+			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+	append_load_imm_u32(desc, ivsize, LDST_CLASS_2_CCB |
+			    LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM);
+
+	/* Load Counter into CONTEXT1 reg */
+	if (is_rfc3686)
+		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
+				     LDST_SRCDST_BYTE_CONTEXT |
+				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
+				      LDST_OFFSET_SHIFT));
+
+	/* Class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Will write ivsize + cryptlen */
+	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* Not need to reload iv */
+	append_seq_fifo_load(desc, ivsize,
+			     FIFOLD_CLASS_SKIP);
+
+	/* Will read cryptlen */
+	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | KEY_VLF |
+			     FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LASTBOTH);
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
+
+	/* Write ICV */
+	append_seq_store(desc, icvsize, LDST_CLASS_2_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "aead givenc shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_aead_givencap);
+
+/**
+ * cnstr_shdsc_gcm_encap - gcm encapsulation shared descriptor
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ */
+void cnstr_shdsc_gcm_encap(u32 * const desc, struct alginfo *cdata,
+			   unsigned int icvsize)
+{
+	u32 *key_jump_cmd, *zero_payload_jump_cmd, *zero_assoc_jump_cmd1,
+	    *zero_assoc_jump_cmd2;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* skip key loading if they are loaded due to sharing */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD | JUMP_COND_SELF);
+	if (cdata->key_inline)
+		append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+				  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	else
+		append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
+			   KEY_DEST_CLASS_REG);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* if assoclen + cryptlen is ZERO, skip to ICV write */
+	append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	zero_assoc_jump_cmd2 = append_jump(desc, JUMP_TEST_ALL |
+						 JUMP_COND_MATH_Z);
+
+	/* if assoclen is ZERO, skip reading the assoc data */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+	zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
+					   JUMP_COND_MATH_Z);
+
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/* skip assoc data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+	/* cryptlen = seqinlen - assoclen */
+	append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG3, CAAM_CMD_SZ);
+
+	/* if cryptlen is ZERO jump to zero-payload commands */
+	zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+					    JUMP_COND_MATH_Z);
+
+	/* read assoc data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
+	set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
+
+	append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* write encrypted data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+	/* read payload data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
+
+	/* jump the zero-payload commands */
+	append_jump(desc, JUMP_TEST_ALL | 2);
+
+	/* zero-payload commands */
+	set_jump_tgt_here(desc, zero_payload_jump_cmd);
+
+	/* read assoc data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST1);
+
+	/* There is no input data */
+	set_jump_tgt_here(desc, zero_assoc_jump_cmd2);
+
+	/* write ICV */
+	append_seq_store(desc, icvsize, LDST_CLASS_1_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "gcm enc shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_gcm_encap);
+
+/**
+ * cnstr_shdsc_gcm_decap - gcm decapsulation shared descriptor
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ */
+void cnstr_shdsc_gcm_decap(u32 * const desc, struct alginfo *cdata,
+			   unsigned int icvsize)
+{
+	u32 *key_jump_cmd, *zero_payload_jump_cmd, *zero_assoc_jump_cmd1;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* skip key loading if they are loaded due to sharing */
+	key_jump_cmd = append_jump(desc, JUMP_JSL |
+				   JUMP_TEST_ALL | JUMP_COND_SHRD |
+				   JUMP_COND_SELF);
+	if (cdata->key_inline)
+		append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+				  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	else
+		append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
+			   KEY_DEST_CLASS_REG);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+	/* if assoclen is ZERO, skip reading the assoc data */
+	append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ);
+	zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL |
+						 JUMP_COND_MATH_Z);
+
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/* skip assoc data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+	/* read assoc data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
+
+	set_jump_tgt_here(desc, zero_assoc_jump_cmd1);
+
+	/* cryptlen = seqoutlen - assoclen */
+	append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+
+	/* jump to zero-payload command if cryptlen is zero */
+	zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL |
+					    JUMP_COND_MATH_Z);
+
+	append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+
+	/* store encrypted data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+	/* read payload data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
+
+	/* zero-payload command */
+	set_jump_tgt_here(desc, zero_payload_jump_cmd);
+
+	/* read ICV */
+	append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS1 |
+			     FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "gcm dec shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_gcm_decap);
+
+/**
+ * cnstr_shdsc_rfc4106_encap - IPSec ESP gcm encapsulation shared descriptor
+ *                             (non-protocol).
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ */
+void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize)
+{
+	u32 *key_jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* Skip key loading if it is loaded due to sharing */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+	if (cdata->key_inline)
+		append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+				  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	else
+		append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
+			   KEY_DEST_CLASS_REG);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/* Read assoc data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
+
+	/* Skip IV */
+	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
+
+	/* Will read cryptlen bytes */
+	append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
+
+	/* Skip assoc data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+	/* cryptlen = seqoutlen - assoclen */
+	append_math_sub(desc, VARSEQOUTLEN, VARSEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* Write encrypted data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+	/* Read payload data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
+
+	/* Write ICV */
+	append_seq_store(desc, icvsize, LDST_CLASS_1_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "rfc4106 enc shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_rfc4106_encap);
+
+/**
+ * cnstr_shdsc_rfc4106_decap - IPSec ESP gcm decapsulation shared descriptor
+ *                             (non-protocol).
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ */
+void cnstr_shdsc_rfc4106_decap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize)
+{
+	u32 *key_jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* Skip key loading if it is loaded due to sharing */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+	if (cdata->key_inline)
+		append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+				  cdata->keylen, CLASS_1 |
+				  KEY_DEST_CLASS_REG);
+	else
+		append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
+			   KEY_DEST_CLASS_REG);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+	append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8);
+	append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ);
+
+	/* Read assoc data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1);
+
+	/* Skip IV */
+	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
+
+	/* Will read cryptlen bytes */
+	append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG3, CAAM_CMD_SZ);
+
+	/* Workaround for erratum A-005473 (simultaneous SEQ FIFO skips) */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG);
+
+	/* Skip assoc data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF);
+
+	/* Will write cryptlen bytes */
+	append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+
+	/* Store payload data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+	/* Read encrypted data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF |
+			     FIFOLD_TYPE_MSG | FIFOLD_TYPE_FLUSH1);
+
+	/* Read ICV */
+	append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS1 |
+			     FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "rfc4106 dec shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_rfc4106_decap);
+
+/**
+ * cnstr_shdsc_rfc4543_encap - IPSec ESP gmac encapsulation shared descriptor
+ *                             (non-protocol).
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ */
+void cnstr_shdsc_rfc4543_encap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize)
+{
+	u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* Skip key loading if it is loaded due to sharing */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+	if (cdata->key_inline)
+		append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+				  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	else
+		append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
+			   KEY_DEST_CLASS_REG);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* assoclen + cryptlen = seqinlen */
+	append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/*
+	 * MOVE_LEN opcode is not available in all SEC HW revisions,
+	 * thus need to do some magic, i.e. self-patch the descriptor
+	 * buffer.
+	 */
+	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 |
+				    (0x6 << MOVE_LEN_SHIFT));
+	write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF |
+				     (0x8 << MOVE_LEN_SHIFT));
+
+	/* Will read assoclen + cryptlen bytes */
+	append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* Will write assoclen + cryptlen bytes */
+	append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+	/* Read and write assoclen + cryptlen bytes */
+	aead_append_src_dst(desc, FIFOLD_TYPE_AAD);
+
+	set_move_tgt_here(desc, read_move_cmd);
+	set_move_tgt_here(desc, write_move_cmd);
+	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	/* Move payload data to OFIFO */
+	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO);
+
+	/* Write ICV */
+	append_seq_store(desc, icvsize, LDST_CLASS_1_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "rfc4543 enc shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_rfc4543_encap);
+
+/**
+ * cnstr_shdsc_rfc4543_decap - IPSec ESP gmac decapsulation shared descriptor
+ *                             (non-protocol).
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM.
+ * @icvsize: integrity check value (ICV) size (truncated or full)
+ */
+void cnstr_shdsc_rfc4543_decap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize)
+{
+	u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+	/* Skip key loading if it is loaded due to sharing */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+	if (cdata->key_inline)
+		append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+				  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+	else
+		append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 |
+			   KEY_DEST_CLASS_REG);
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Class 1 operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_DECRYPT | OP_ALG_ICV_ON);
+
+	/* assoclen + cryptlen = seqoutlen */
+	append_math_sub(desc, REG3, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+
+	/*
+	 * MOVE_LEN opcode is not available in all SEC HW revisions,
+	 * thus need to do some magic, i.e. self-patch the descriptor
+	 * buffer.
+	 */
+	read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 |
+				    (0x6 << MOVE_LEN_SHIFT));
+	write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF |
+				     (0x8 << MOVE_LEN_SHIFT));
+
+	/* Will read assoclen + cryptlen bytes */
+	append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+
+	/* Will write assoclen + cryptlen bytes */
+	append_math_sub(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ);
+
+	/* Store payload data */
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | FIFOLDST_VLF);
+
+	/* In-snoop assoclen + cryptlen data */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | FIFOLDST_VLF |
+			     FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST2FLUSH1);
+
+	set_move_tgt_here(desc, read_move_cmd);
+	set_move_tgt_here(desc, write_move_cmd);
+	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	/* Move payload data to OFIFO */
+	append_move(desc, MOVE_SRC_INFIFO_CL | MOVE_DEST_OUTFIFO);
+	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+	/* Read ICV */
+	append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS1 |
+			     FIFOLD_TYPE_ICV | FIFOLD_TYPE_LAST1);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "rfc4543 dec shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_rfc4543_decap);
+
+/*
+ * For ablkcipher encrypt and decrypt, read from req->src and
+ * write to req->dst
+ */
+static inline void ablkcipher_append_src_dst(u32 *desc)
+{
+	append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 |
+			     KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
+	append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
+}
+
+/**
+ * cnstr_shdsc_ablkcipher_encap - ablkcipher encapsulation shared descriptor
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
+ *         with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
+ * @ivsize: initialization vector size
+ * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
+ * @ctx1_iv_off: IV offset in CONTEXT1 register
+ */
+void cnstr_shdsc_ablkcipher_encap(u32 * const desc, struct alginfo *cdata,
+				  unsigned int ivsize, const bool is_rfc3686,
+				  const u32 ctx1_iv_off)
+{
+	u32 *key_jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/* Load class1 key only */
+	append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+			  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+
+	/* Load nonce into CONTEXT1 reg */
+	if (is_rfc3686) {
+		u8 *nonce = cdata->key_virt + cdata->keylen;
+
+		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
+				   LDST_CLASS_IND_CCB |
+				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
+		append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO |
+			    MOVE_DEST_CLASS1CTX | (16 << MOVE_OFFSET_SHIFT) |
+			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
+	}
+
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Load iv */
+	append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
+			LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
+
+	/* Load counter into CONTEXT1 reg */
+	if (is_rfc3686)
+		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
+				     LDST_SRCDST_BYTE_CONTEXT |
+				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
+				      LDST_OFFSET_SHIFT));
+
+	/* Load operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Perform operation */
+	ablkcipher_append_src_dst(desc);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "ablkcipher enc shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_ablkcipher_encap);
+
+/**
+ * cnstr_shdsc_ablkcipher_decap - ablkcipher decapsulation shared descriptor
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
+ *         with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128.
+ * @ivsize: initialization vector size
+ * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
+ * @ctx1_iv_off: IV offset in CONTEXT1 register
+ */
+void cnstr_shdsc_ablkcipher_decap(u32 * const desc, struct alginfo *cdata,
+				  unsigned int ivsize, const bool is_rfc3686,
+				  const u32 ctx1_iv_off)
+{
+	u32 *key_jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/* Load class1 key only */
+	append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+			  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+
+	/* Load nonce into CONTEXT1 reg */
+	if (is_rfc3686) {
+		u8 *nonce = cdata->key_virt + cdata->keylen;
+
+		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
+				   LDST_CLASS_IND_CCB |
+				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
+		append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO |
+			    MOVE_DEST_CLASS1CTX | (16 << MOVE_OFFSET_SHIFT) |
+			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
+	}
+
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* load IV */
+	append_seq_load(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
+			LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
+
+	/* Load counter into CONTEXT1 reg */
+	if (is_rfc3686)
+		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
+				     LDST_SRCDST_BYTE_CONTEXT |
+				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
+				      LDST_OFFSET_SHIFT));
+
+	/* Choose operation */
+	if (ctx1_iv_off)
+		append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+				 OP_ALG_DECRYPT);
+	else
+		append_dec_op1(desc, cdata->algtype);
+
+	/* Perform operation */
+	ablkcipher_append_src_dst(desc);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "ablkcipher dec shdesc@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_ablkcipher_decap);
+
+/**
+ * cnstr_shdsc_ablkcipher_givencap - ablkcipher encapsulation shared descriptor
+ *                                   with HW-generated initialization vector.
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed
+ *         with OP_ALG_AAI_CBC.
+ * @ivsize: initialization vector size
+ * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template
+ * @ctx1_iv_off: IV offset in CONTEXT1 register
+ */
+void cnstr_shdsc_ablkcipher_givencap(u32 * const desc, struct alginfo *cdata,
+				     unsigned int ivsize, const bool is_rfc3686,
+				     const u32 ctx1_iv_off)
+{
+	u32 *key_jump_cmd, geniv;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/* Load class1 key only */
+	append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+			  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+
+	/* Load Nonce into CONTEXT1 reg */
+	if (is_rfc3686) {
+		u8 *nonce = cdata->key_virt + cdata->keylen;
+
+		append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE,
+				   LDST_CLASS_IND_CCB |
+				   LDST_SRCDST_BYTE_OUTFIFO | LDST_IMM);
+		append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO |
+			    MOVE_DEST_CLASS1CTX | (16 << MOVE_OFFSET_SHIFT) |
+			    (CTR_RFC3686_NONCE_SIZE << MOVE_LEN_SHIFT));
+	}
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/* Generate IV */
+	geniv = NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DEST_DECO |
+		NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_LC1 | NFIFOENTRY_PTYPE_RND |
+		(ivsize << NFIFOENTRY_DLEN_SHIFT);
+	append_load_imm_u32(desc, geniv, LDST_CLASS_IND_CCB |
+			    LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM);
+	append_cmd(desc, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+	append_move(desc, MOVE_WAITCOMP | MOVE_SRC_INFIFO |
+		    MOVE_DEST_CLASS1CTX | (ivsize << MOVE_LEN_SHIFT) |
+		    (ctx1_iv_off << MOVE_OFFSET_SHIFT));
+	append_cmd(desc, CMD_LOAD | ENABLE_AUTO_INFO_FIFO);
+
+	/* Copy generated IV to memory */
+	append_seq_store(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
+			 LDST_CLASS_1_CCB | (ctx1_iv_off << LDST_OFFSET_SHIFT));
+
+	/* Load Counter into CONTEXT1 reg */
+	if (is_rfc3686)
+		append_load_imm_be32(desc, 1, LDST_IMM | LDST_CLASS_1_CCB |
+				     LDST_SRCDST_BYTE_CONTEXT |
+				     ((ctx1_iv_off + CTR_RFC3686_IV_SIZE) <<
+				      LDST_OFFSET_SHIFT));
+
+	if (ctx1_iv_off)
+		append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | JUMP_COND_NCP |
+			    (1 << JUMP_OFFSET_SHIFT));
+
+	/* Load operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Perform operation */
+	ablkcipher_append_src_dst(desc);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "ablkcipher givenc shdesc@" __stringify(__LINE__) ": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_ablkcipher_givencap);
+
+/**
+ * cnstr_shdsc_xts_ablkcipher_encap - xts ablkcipher encapsulation shared
+ *                                    descriptor
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_XTS.
+ */
+void cnstr_shdsc_xts_ablkcipher_encap(u32 * const desc, struct alginfo *cdata)
+{
+	__be64 sector_size = cpu_to_be64(512);
+	u32 *key_jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/* Load class1 keys only */
+	append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+			  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+
+	/* Load sector size with index 40 bytes (0x28) */
+	append_load_as_imm(desc, (void *)&sector_size, 8, LDST_CLASS_1_CCB |
+			   LDST_SRCDST_BYTE_CONTEXT |
+			   (0x28 << LDST_OFFSET_SHIFT));
+
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/*
+	 * create sequence for loading the sector index
+	 * Upper 8B of IV - will be used as sector index
+	 * Lower 8B of IV - will be discarded
+	 */
+	append_seq_load(desc, 8, LDST_SRCDST_BYTE_CONTEXT | LDST_CLASS_1_CCB |
+			(0x20 << LDST_OFFSET_SHIFT));
+	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
+
+	/* Load operation */
+	append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL |
+			 OP_ALG_ENCRYPT);
+
+	/* Perform operation */
+	ablkcipher_append_src_dst(desc);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "xts ablkcipher enc shdesc@" __stringify(__LINE__) ": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_xts_ablkcipher_encap);
+
+/**
+ * cnstr_shdsc_xts_ablkcipher_decap - xts ablkcipher decapsulation shared
+ *                                    descriptor
+ * @desc: pointer to buffer used for descriptor construction
+ * @cdata: pointer to block cipher transform definitions
+ *         Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_XTS.
+ */
+void cnstr_shdsc_xts_ablkcipher_decap(u32 * const desc, struct alginfo *cdata)
+{
+	__be64 sector_size = cpu_to_be64(512);
+	u32 *key_jump_cmd;
+
+	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
+	/* Skip if already shared */
+	key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+				   JUMP_COND_SHRD);
+
+	/* Load class1 key only */
+	append_key_as_imm(desc, cdata->key_virt, cdata->keylen,
+			  cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG);
+
+	/* Load sector size with index 40 bytes (0x28) */
+	append_load_as_imm(desc, (void *)&sector_size, 8, LDST_CLASS_1_CCB |
+			   LDST_SRCDST_BYTE_CONTEXT |
+			   (0x28 << LDST_OFFSET_SHIFT));
+
+	set_jump_tgt_here(desc, key_jump_cmd);
+
+	/*
+	 * create sequence for loading the sector index
+	 * Upper 8B of IV - will be used as sector index
+	 * Lower 8B of IV - will be discarded
+	 */
+	append_seq_load(desc, 8, LDST_SRCDST_BYTE_CONTEXT | LDST_CLASS_1_CCB |
+			(0x20 << LDST_OFFSET_SHIFT));
+	append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP);
+
+	/* Load operation */
+	append_dec_op1(desc, cdata->algtype);
+
+	/* Perform operation */
+	ablkcipher_append_src_dst(desc);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR,
+		       "xts ablkcipher dec shdesc@" __stringify(__LINE__) ": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+}
+EXPORT_SYMBOL(cnstr_shdsc_xts_ablkcipher_decap);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FSL CAAM descriptor support");
+MODULE_AUTHOR("Freescale Semiconductor - NMG/STC");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/caamalg_desc.h linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamalg_desc.h
--- linux-libre-4.9-gnu/drivers/crypto/caam/caamalg_desc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamalg_desc.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,97 @@
+/*
+ * Shared descriptors for aead, ablkcipher algorithms
+ *
+ * Copyright 2016 NXP
+ */
+
+#ifndef _CAAMALG_DESC_H_
+#define _CAAMALG_DESC_H_
+
+/* length of descriptors text */
+#define DESC_AEAD_BASE			(4 * CAAM_CMD_SZ)
+#define DESC_AEAD_ENC_LEN		(DESC_AEAD_BASE + 11 * CAAM_CMD_SZ)
+#define DESC_AEAD_DEC_LEN		(DESC_AEAD_BASE + 15 * CAAM_CMD_SZ)
+#define DESC_AEAD_GIVENC_LEN		(DESC_AEAD_ENC_LEN + 7 * CAAM_CMD_SZ)
+
+/* Note: Nonce is counted in cdata.keylen */
+#define DESC_AEAD_CTR_RFC3686_LEN	(4 * CAAM_CMD_SZ)
+
+#define DESC_AEAD_NULL_BASE		(3 * CAAM_CMD_SZ)
+#define DESC_AEAD_NULL_ENC_LEN		(DESC_AEAD_NULL_BASE + 11 * CAAM_CMD_SZ)
+#define DESC_AEAD_NULL_DEC_LEN		(DESC_AEAD_NULL_BASE + 13 * CAAM_CMD_SZ)
+
+#define DESC_GCM_BASE			(3 * CAAM_CMD_SZ)
+#define DESC_GCM_ENC_LEN		(DESC_GCM_BASE + 16 * CAAM_CMD_SZ)
+#define DESC_GCM_DEC_LEN		(DESC_GCM_BASE + 12 * CAAM_CMD_SZ)
+
+#define DESC_RFC4106_BASE		(3 * CAAM_CMD_SZ)
+#define DESC_RFC4106_ENC_LEN		(DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ)
+#define DESC_RFC4106_DEC_LEN		(DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ)
+
+#define DESC_RFC4543_BASE		(3 * CAAM_CMD_SZ)
+#define DESC_RFC4543_ENC_LEN		(DESC_RFC4543_BASE + 11 * CAAM_CMD_SZ)
+#define DESC_RFC4543_DEC_LEN		(DESC_RFC4543_BASE + 12 * CAAM_CMD_SZ)
+
+#define DESC_ABLKCIPHER_BASE		(3 * CAAM_CMD_SZ)
+#define DESC_ABLKCIPHER_ENC_LEN		(DESC_ABLKCIPHER_BASE + \
+					 20 * CAAM_CMD_SZ)
+#define DESC_ABLKCIPHER_DEC_LEN		(DESC_ABLKCIPHER_BASE + \
+					 15 * CAAM_CMD_SZ)
+
+void cnstr_shdsc_aead_null_encap(u32 * const desc, struct alginfo *adata,
+				 unsigned int icvsize);
+
+void cnstr_shdsc_aead_null_decap(u32 * const desc, struct alginfo *adata,
+				 unsigned int icvsize);
+
+void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata,
+			    struct alginfo *adata, unsigned int icvsize,
+			    const bool is_rfc3686, u32 *nonce,
+			    const u32 ctx1_iv_off);
+
+void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata,
+			    struct alginfo *adata, unsigned int ivsize,
+			    unsigned int icvsize, const bool geniv,
+			    const bool is_rfc3686, u32 *nonce,
+			    const u32 ctx1_iv_off);
+
+void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata,
+			       struct alginfo *adata, unsigned int ivsize,
+			       unsigned int icvsize, const bool is_rfc3686,
+			       u32 *nonce, const u32 ctx1_iv_off);
+
+void cnstr_shdsc_gcm_encap(u32 * const desc, struct alginfo *cdata,
+			   unsigned int icvsize);
+
+void cnstr_shdsc_gcm_decap(u32 * const desc, struct alginfo *cdata,
+			   unsigned int icvsize);
+
+void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize);
+
+void cnstr_shdsc_rfc4106_decap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize);
+
+void cnstr_shdsc_rfc4543_encap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize);
+
+void cnstr_shdsc_rfc4543_decap(u32 * const desc, struct alginfo *cdata,
+			       unsigned int icvsize);
+
+void cnstr_shdsc_ablkcipher_encap(u32 * const desc, struct alginfo *cdata,
+				  unsigned int ivsize, const bool is_rfc3686,
+				  const u32 ctx1_iv_off);
+
+void cnstr_shdsc_ablkcipher_decap(u32 * const desc, struct alginfo *cdata,
+				  unsigned int ivsize, const bool is_rfc3686,
+				  const u32 ctx1_iv_off);
+
+void cnstr_shdsc_ablkcipher_givencap(u32 * const desc, struct alginfo *cdata,
+				     unsigned int ivsize, const bool is_rfc3686,
+				     const u32 ctx1_iv_off);
+
+void cnstr_shdsc_xts_ablkcipher_encap(u32 * const desc, struct alginfo *cdata);
+
+void cnstr_shdsc_xts_ablkcipher_decap(u32 * const desc, struct alginfo *cdata);
+
+#endif /* _CAAMALG_DESC_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/caamhash.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamhash.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/caamhash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamhash.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,7 @@
 #define CAAM_MAX_HASH_DIGEST_SIZE	SHA512_DIGEST_SIZE
 
 /* length of descriptors text */
-#define DESC_AHASH_BASE			(4 * CAAM_CMD_SZ)
+#define DESC_AHASH_BASE			(3 * CAAM_CMD_SZ)
 #define DESC_AHASH_UPDATE_LEN		(6 * CAAM_CMD_SZ)
 #define DESC_AHASH_UPDATE_FIRST_LEN	(DESC_AHASH_BASE + 4 * CAAM_CMD_SZ)
 #define DESC_AHASH_FINAL_LEN		(DESC_AHASH_BASE + 5 * CAAM_CMD_SZ)
@@ -103,20 +103,15 @@ struct caam_hash_ctx {
 	u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
 	u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
 	u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
-	u32 sh_desc_finup[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned;
 	dma_addr_t sh_desc_update_dma ____cacheline_aligned;
 	dma_addr_t sh_desc_update_first_dma;
 	dma_addr_t sh_desc_fin_dma;
 	dma_addr_t sh_desc_digest_dma;
-	dma_addr_t sh_desc_finup_dma;
 	struct device *jrdev;
-	u32 alg_type;
-	u32 alg_op;
 	u8 key[CAAM_MAX_HASH_KEY_SIZE];
 	dma_addr_t key_dma;
 	int ctx_len;
-	unsigned int split_key_len;
-	unsigned int split_key_pad_len;
+	struct alginfo adata;
 };
 
 /* ahash state */
@@ -222,89 +217,54 @@ static inline int ctx_map_to_sec4_sg(u32
 	return 0;
 }
 
-/* Common shared descriptor commands */
-static inline void append_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
-{
-	append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
-			  ctx->split_key_len, CLASS_2 |
-			  KEY_DEST_MDHA_SPLIT | KEY_ENC);
-}
-
-/* Append key if it has been set */
-static inline void init_sh_desc_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
-{
-	u32 *key_jump_cmd;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	if (ctx->split_key_len) {
-		/* Skip if already shared */
-		key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
-					   JUMP_COND_SHRD);
-
-		append_key_ahash(desc, ctx);
-
-		set_jump_tgt_here(desc, key_jump_cmd);
-	}
-
-	/* Propagate errors from shared to job descriptor */
-	append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
-}
-
 /*
- * For ahash read data from seqin following state->caam_ctx,
- * and write resulting class2 context to seqout, which may be state->caam_ctx
- * or req->result
+ * For ahash update, final and finup (import_ctx = true)
+ *     import context, read and write to seqout
+ * For ahash firsts and digest (import_ctx = false)
+ *     read and write to seqout
  */
-static inline void ahash_append_load_str(u32 *desc, int digestsize)
+static inline void ahash_gen_sh_desc(u32 *desc, u32 state, int digestsize,
+				     struct caam_hash_ctx *ctx, bool import_ctx)
 {
-	/* Calculate remaining bytes to read */
-	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-
-	/* Read remaining bytes */
-	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 |
-			     FIFOLD_TYPE_MSG | KEY_VLF);
+	u32 op = ctx->adata.algtype;
+	u32 *skip_key_load;
 
-	/* Store class2 context bytes */
-	append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
-			 LDST_SRCDST_BYTE_CONTEXT);
-}
+	init_sh_desc(desc, HDR_SHARE_SERIAL);
 
-/*
- * For ahash update, final and finup, import context, read and write to seqout
- */
-static inline void ahash_ctx_data_to_out(u32 *desc, u32 op, u32 state,
-					 int digestsize,
-					 struct caam_hash_ctx *ctx)
-{
-	init_sh_desc_key_ahash(desc, ctx);
+	/* Append key if it has been set; ahash update excluded */
+	if ((state != OP_ALG_AS_UPDATE) && (ctx->adata.keylen)) {
+		/* Skip key loading if already shared */
+		skip_key_load = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+					    JUMP_COND_SHRD);
 
-	/* Import context from software */
-	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
-		   LDST_CLASS_2_CCB | ctx->ctx_len);
+		append_key_as_imm(desc, ctx->key, ctx->adata.keylen_pad,
+				  ctx->adata.keylen, CLASS_2 |
+				  KEY_DEST_MDHA_SPLIT | KEY_ENC);
 
-	/* Class 2 operation */
-	append_operation(desc, op | state | OP_ALG_ENCRYPT);
+		set_jump_tgt_here(desc, skip_key_load);
 
-	/*
-	 * Load from buf and/or src and write to req->result or state->context
-	 */
-	ahash_append_load_str(desc, digestsize);
-}
+		op |= OP_ALG_AAI_HMAC_PRECOMP;
+	}
 
-/* For ahash firsts and digest, read and write to seqout */
-static inline void ahash_data_to_out(u32 *desc, u32 op, u32 state,
-				     int digestsize, struct caam_hash_ctx *ctx)
-{
-	init_sh_desc_key_ahash(desc, ctx);
+	/* If needed, import context from software */
+	if (import_ctx)
+		append_seq_load(desc, ctx->ctx_len, LDST_CLASS_2_CCB |
+				LDST_SRCDST_BYTE_CONTEXT);
 
 	/* Class 2 operation */
 	append_operation(desc, op | state | OP_ALG_ENCRYPT);
 
 	/*
 	 * Load from buf and/or src and write to req->result or state->context
+	 * Calculate remaining bytes to read
 	 */
-	ahash_append_load_str(desc, digestsize);
+	append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+	/* Read remaining bytes */
+	append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 |
+			     FIFOLD_TYPE_MSG | KEY_VLF);
+	/* Store class2 context bytes */
+	append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
+			 LDST_SRCDST_BYTE_CONTEXT);
 }
 
 static int ahash_set_sh_desc(struct crypto_ahash *ahash)
@@ -312,28 +272,11 @@ static int ahash_set_sh_desc(struct cryp
 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
 	int digestsize = crypto_ahash_digestsize(ahash);
 	struct device *jrdev = ctx->jrdev;
-	u32 have_key = 0;
 	u32 *desc;
 
-	if (ctx->split_key_len)
-		have_key = OP_ALG_AAI_HMAC_PRECOMP;
-
 	/* ahash_update shared descriptor */
 	desc = ctx->sh_desc_update;
-
-	init_sh_desc(desc, HDR_SHARE_SERIAL);
-
-	/* Import context from software */
-	append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
-		   LDST_CLASS_2_CCB | ctx->ctx_len);
-
-	/* Class 2 operation */
-	append_operation(desc, ctx->alg_type | OP_ALG_AS_UPDATE |
-			 OP_ALG_ENCRYPT);
-
-	/* Load data and write to result or context */
-	ahash_append_load_str(desc, ctx->ctx_len);
-
+	ahash_gen_sh_desc(desc, OP_ALG_AS_UPDATE, ctx->ctx_len, ctx, true);
 	ctx->sh_desc_update_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
 						 DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->sh_desc_update_dma)) {
@@ -348,10 +291,7 @@ static int ahash_set_sh_desc(struct cryp
 
 	/* ahash_update_first shared descriptor */
 	desc = ctx->sh_desc_update_first;
-
-	ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INIT,
-			  ctx->ctx_len, ctx);
-
+	ahash_gen_sh_desc(desc, OP_ALG_AS_INIT, ctx->ctx_len, ctx, false);
 	ctx->sh_desc_update_first_dma = dma_map_single(jrdev, desc,
 						       desc_bytes(desc),
 						       DMA_TO_DEVICE);
@@ -367,10 +307,7 @@ static int ahash_set_sh_desc(struct cryp
 
 	/* ahash_final shared descriptor */
 	desc = ctx->sh_desc_fin;
-
-	ahash_ctx_data_to_out(desc, have_key | ctx->alg_type,
-			      OP_ALG_AS_FINALIZE, digestsize, ctx);
-
+	ahash_gen_sh_desc(desc, OP_ALG_AS_FINALIZE, digestsize, ctx, true);
 	ctx->sh_desc_fin_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
 					      DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->sh_desc_fin_dma)) {
@@ -383,30 +320,9 @@ static int ahash_set_sh_desc(struct cryp
 		       desc_bytes(desc), 1);
 #endif
 
-	/* ahash_finup shared descriptor */
-	desc = ctx->sh_desc_finup;
-
-	ahash_ctx_data_to_out(desc, have_key | ctx->alg_type,
-			      OP_ALG_AS_FINALIZE, digestsize, ctx);
-
-	ctx->sh_desc_finup_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
-						DMA_TO_DEVICE);
-	if (dma_mapping_error(jrdev, ctx->sh_desc_finup_dma)) {
-		dev_err(jrdev, "unable to map shared descriptor\n");
-		return -ENOMEM;
-	}
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "ahash finup shdesc@"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, desc,
-		       desc_bytes(desc), 1);
-#endif
-
 	/* ahash_digest shared descriptor */
 	desc = ctx->sh_desc_digest;
-
-	ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INITFINAL,
-			  digestsize, ctx);
-
+	ahash_gen_sh_desc(desc, OP_ALG_AS_INITFINAL, digestsize, ctx, false);
 	ctx->sh_desc_digest_dma = dma_map_single(jrdev, desc,
 						 desc_bytes(desc),
 						 DMA_TO_DEVICE);
@@ -424,14 +340,6 @@ static int ahash_set_sh_desc(struct cryp
 	return 0;
 }
 
-static int gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in,
-			      u32 keylen)
-{
-	return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len,
-			       ctx->split_key_pad_len, key_in, keylen,
-			       ctx->alg_op);
-}
-
 /* Digest hash size if it is too large */
 static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
 			   u32 *keylen, u8 *key_out, u32 digestsize)
@@ -467,7 +375,7 @@ static int hash_digest_key(struct caam_h
 	}
 
 	/* Job descriptor to perform unkeyed hash on key_in */
-	append_operation(desc, ctx->alg_type | OP_ALG_ENCRYPT |
+	append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT |
 			 OP_ALG_AS_INITFINAL);
 	append_seq_in_ptr(desc, src_dma, *keylen, 0);
 	append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
@@ -511,8 +419,6 @@ static int hash_digest_key(struct caam_h
 static int ahash_setkey(struct crypto_ahash *ahash,
 			const u8 *key, unsigned int keylen)
 {
-	/* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
-	static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
 	struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
 	struct device *jrdev = ctx->jrdev;
 	int blocksize = crypto_tfm_alg_blocksize(&ahash->base);
@@ -537,23 +443,12 @@ static int ahash_setkey(struct crypto_ah
 		key = hashed_key;
 	}
 
-	/* Pick class 2 key length from algorithm submask */
-	ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
-				      OP_ALG_ALGSEL_SHIFT] * 2;
-	ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
-
-#ifdef DEBUG
-	printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n",
-	       ctx->split_key_len, ctx->split_key_pad_len);
-	print_hex_dump(KERN_ERR, "key in @"__stringify(__LINE__)": ",
-		       DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
-#endif
-
-	ret = gen_split_hash_key(ctx, key, keylen);
+	ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key, keylen,
+			    CAAM_MAX_HASH_KEY_SIZE);
 	if (ret)
 		goto bad_free_key;
 
-	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len,
+	ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->adata.keylen_pad,
 				      DMA_TO_DEVICE);
 	if (dma_mapping_error(jrdev, ctx->key_dma)) {
 		dev_err(jrdev, "unable to map key i/o memory\n");
@@ -563,14 +458,15 @@ static int ahash_setkey(struct crypto_ah
 #ifdef DEBUG
 	print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
 		       DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
-		       ctx->split_key_pad_len, 1);
+		       ctx->adata.keylen_pad, 1);
 #endif
 
 	ret = ahash_set_sh_desc(ahash);
 	if (ret) {
-		dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len,
+		dma_unmap_single(jrdev, ctx->key_dma, ctx->adata.keylen_pad,
 				 DMA_TO_DEVICE);
 	}
+
  error_free_key:
 	kfree(hashed_key);
 	return ret;
@@ -639,8 +535,7 @@ static void ahash_done(struct device *jr
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
-	edesc = (struct ahash_edesc *)((char *)desc -
-		 offsetof(struct ahash_edesc, hw_desc));
+	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
 	if (err)
 		caam_jr_strstatus(jrdev, err);
 
@@ -674,8 +569,7 @@ static void ahash_done_bi(struct device
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
-	edesc = (struct ahash_edesc *)((char *)desc -
-		 offsetof(struct ahash_edesc, hw_desc));
+	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
 	if (err)
 		caam_jr_strstatus(jrdev, err);
 
@@ -709,8 +603,7 @@ static void ahash_done_ctx_src(struct de
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
-	edesc = (struct ahash_edesc *)((char *)desc -
-		 offsetof(struct ahash_edesc, hw_desc));
+	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
 	if (err)
 		caam_jr_strstatus(jrdev, err);
 
@@ -744,8 +637,7 @@ static void ahash_done_ctx_dst(struct de
 	dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
 #endif
 
-	edesc = (struct ahash_edesc *)((char *)desc -
-		 offsetof(struct ahash_edesc, hw_desc));
+	edesc = container_of(desc, struct ahash_edesc, hw_desc[0]);
 	if (err)
 		caam_jr_strstatus(jrdev, err);
 
@@ -1078,7 +970,7 @@ static int ahash_finup_ctx(struct ahash_
 
 	/* allocate space for base edesc and hw desc commands, link tables */
 	edesc = ahash_edesc_alloc(ctx, sec4_sg_src_index + mapped_nents,
-				  ctx->sh_desc_finup, ctx->sh_desc_finup_dma,
+				  ctx->sh_desc_fin, ctx->sh_desc_fin_dma,
 				  flags);
 	if (!edesc) {
 		dma_unmap_sg(jrdev, req->src, src_nents, DMA_TO_DEVICE);
@@ -1683,7 +1575,6 @@ struct caam_hash_template {
 	unsigned int blocksize;
 	struct ahash_alg template_ahash;
 	u32 alg_type;
-	u32 alg_op;
 };
 
 /* ahash descriptors */
@@ -1709,7 +1600,6 @@ static struct caam_hash_template driver_
 			},
 		},
 		.alg_type = OP_ALG_ALGSEL_SHA1,
-		.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
 	}, {
 		.name = "sha224",
 		.driver_name = "sha224-caam",
@@ -1731,7 +1621,6 @@ static struct caam_hash_template driver_
 			},
 		},
 		.alg_type = OP_ALG_ALGSEL_SHA224,
-		.alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
 	}, {
 		.name = "sha256",
 		.driver_name = "sha256-caam",
@@ -1753,7 +1642,6 @@ static struct caam_hash_template driver_
 			},
 		},
 		.alg_type = OP_ALG_ALGSEL_SHA256,
-		.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
 	}, {
 		.name = "sha384",
 		.driver_name = "sha384-caam",
@@ -1775,7 +1663,6 @@ static struct caam_hash_template driver_
 			},
 		},
 		.alg_type = OP_ALG_ALGSEL_SHA384,
-		.alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
 	}, {
 		.name = "sha512",
 		.driver_name = "sha512-caam",
@@ -1797,7 +1684,6 @@ static struct caam_hash_template driver_
 			},
 		},
 		.alg_type = OP_ALG_ALGSEL_SHA512,
-		.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
 	}, {
 		.name = "md5",
 		.driver_name = "md5-caam",
@@ -1819,14 +1705,12 @@ static struct caam_hash_template driver_
 			},
 		},
 		.alg_type = OP_ALG_ALGSEL_MD5,
-		.alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
 	},
 };
 
 struct caam_hash_alg {
 	struct list_head entry;
 	int alg_type;
-	int alg_op;
 	struct ahash_alg ahash_alg;
 };
 
@@ -1859,10 +1743,10 @@ static int caam_hash_cra_init(struct cry
 		return PTR_ERR(ctx->jrdev);
 	}
 	/* copy descriptor header template value */
-	ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
-	ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_hash->alg_op;
+	ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
 
-	ctx->ctx_len = runninglen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
+	ctx->ctx_len = runninglen[(ctx->adata.algtype &
+				   OP_ALG_ALGSEL_SUBMASK) >>
 				  OP_ALG_ALGSEL_SHIFT];
 
 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
@@ -1893,10 +1777,6 @@ static void caam_hash_cra_exit(struct cr
 		dma_unmap_single(ctx->jrdev, ctx->sh_desc_digest_dma,
 				 desc_bytes(ctx->sh_desc_digest),
 				 DMA_TO_DEVICE);
-	if (ctx->sh_desc_finup_dma &&
-	    !dma_mapping_error(ctx->jrdev, ctx->sh_desc_finup_dma))
-		dma_unmap_single(ctx->jrdev, ctx->sh_desc_finup_dma,
-				 desc_bytes(ctx->sh_desc_finup), DMA_TO_DEVICE);
 
 	caam_jr_free(ctx->jrdev);
 }
@@ -1956,7 +1836,6 @@ caam_hash_alloc(struct caam_hash_templat
 	alg->cra_type = &crypto_ahash_type;
 
 	t_alg->alg_type = template->alg_type;
-	t_alg->alg_op = template->alg_op;
 
 	return t_alg;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/caampkc.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caampkc.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/caampkc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caampkc.c	2017-02-12 16:03:20.000000000 -0500
@@ -395,7 +395,7 @@ static int caam_rsa_set_pub_key(struct c
 				unsigned int keylen)
 {
 	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
-	struct rsa_key raw_key = {0};
+	struct rsa_key raw_key = {NULL};
 	struct caam_rsa_key *rsa_key = &ctx->key;
 	int ret;
 
@@ -441,7 +441,7 @@ static int caam_rsa_set_priv_key(struct
 				 unsigned int keylen)
 {
 	struct caam_rsa_ctx *ctx = akcipher_tfm_ctx(tfm);
-	struct rsa_key raw_key = {0};
+	struct rsa_key raw_key = {NULL};
 	struct caam_rsa_key *rsa_key = &ctx->key;
 	int ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/caamrng.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamrng.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/caamrng.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/caamrng.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@
 
 /* length of descriptors */
 #define DESC_JOB_O_LEN			(CAAM_CMD_SZ * 2 + CAAM_PTR_SZ * 2)
-#define DESC_RNG_LEN			(4 * CAAM_CMD_SZ)
+#define DESC_RNG_LEN			(3 * CAAM_CMD_SZ)
 
 /* Buffer, its dma address and lock */
 struct buf_data {
@@ -100,8 +100,7 @@ static void rng_done(struct device *jrde
 {
 	struct buf_data *bd;
 
-	bd = (struct buf_data *)((char *)desc -
-	      offsetof(struct buf_data, hw_desc));
+	bd = container_of(desc, struct buf_data, hw_desc[0]);
 
 	if (err)
 		caam_jr_strstatus(jrdev, err);
@@ -196,9 +195,6 @@ static inline int rng_create_sh_desc(str
 
 	init_sh_desc(desc, HDR_SHARE_SERIAL);
 
-	/* Propagate errors from shared to job descriptor */
-	append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
-
 	/* Generate random bytes */
 	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
 
@@ -351,7 +347,7 @@ static int __init caam_rng_init(void)
 		pr_err("Job Ring Device allocation for transform failed\n");
 		return PTR_ERR(dev);
 	}
-	rng_ctx = kmalloc(sizeof(*rng_ctx), GFP_DMA);
+	rng_ctx = kmalloc(sizeof(*rng_ctx), GFP_DMA | GFP_KERNEL);
 	if (!rng_ctx) {
 		err = -ENOMEM;
 		goto free_caam_alloc;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/ctrl.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/ctrl.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/ctrl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/ctrl.c	2017-02-12 16:03:20.000000000 -0500
@@ -330,8 +330,8 @@ static int caam_remove(struct platform_d
 	clk_disable_unprepare(ctrlpriv->caam_ipg);
 	clk_disable_unprepare(ctrlpriv->caam_mem);
 	clk_disable_unprepare(ctrlpriv->caam_aclk);
-	clk_disable_unprepare(ctrlpriv->caam_emi_slow);
-
+	if (ctrlpriv->caam_emi_slow)
+		clk_disable_unprepare(ctrlpriv->caam_emi_slow);
 	return 0;
 }
 
@@ -365,11 +365,8 @@ static void kick_trng(struct platform_de
 	 */
 	val = (rd_reg32(&r4tst->rtsdctl) & RTSDCTL_ENT_DLY_MASK)
 	      >> RTSDCTL_ENT_DLY_SHIFT;
-	if (ent_delay <= val) {
-		/* put RNG4 into run mode */
-		clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, 0);
-		return;
-	}
+	if (ent_delay <= val)
+		goto start_rng;
 
 	val = rd_reg32(&r4tst->rtsdctl);
 	val = (val & ~RTSDCTL_ENT_DLY_MASK) |
@@ -381,15 +378,12 @@ static void kick_trng(struct platform_de
 	wr_reg32(&r4tst->rtfrqmax, RTFRQMAX_DISABLE);
 	/* read the control register */
 	val = rd_reg32(&r4tst->rtmctl);
+start_rng:
 	/*
 	 * select raw sampling in both entropy shifter
-	 * and statistical checker
+	 * and statistical checker; ; put RNG4 into run mode
 	 */
-	clrsetbits_32(&val, 0, RTMCTL_SAMP_MODE_RAW_ES_SC);
-	/* put RNG4 into run mode */
-	clrsetbits_32(&val, RTMCTL_PRGM, 0);
-	/* write back the control register */
-	wr_reg32(&r4tst->rtmctl, val);
+	clrsetbits_32(&r4tst->rtmctl, RTMCTL_PRGM, RTMCTL_SAMP_MODE_RAW_ES_SC);
 }
 
 /**
@@ -482,14 +476,16 @@ static int caam_probe(struct platform_de
 	}
 	ctrlpriv->caam_aclk = clk;
 
-	clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
-		dev_err(&pdev->dev,
-			"can't identify CAAM emi_slow clk: %d\n", ret);
-		return ret;
+	if (!of_machine_is_compatible("fsl,imx6ul")) {
+		clk = caam_drv_identify_clk(&pdev->dev, "emi_slow");
+		if (IS_ERR(clk)) {
+			ret = PTR_ERR(clk);
+			dev_err(&pdev->dev,
+				"can't identify CAAM emi_slow clk: %d\n", ret);
+			return ret;
+		}
+		ctrlpriv->caam_emi_slow = clk;
 	}
-	ctrlpriv->caam_emi_slow = clk;
 
 	ret = clk_prepare_enable(ctrlpriv->caam_ipg);
 	if (ret < 0) {
@@ -510,11 +506,13 @@ static int caam_probe(struct platform_de
 		goto disable_caam_mem;
 	}
 
-	ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
-			ret);
-		goto disable_caam_aclk;
+	if (ctrlpriv->caam_emi_slow) {
+		ret = clk_prepare_enable(ctrlpriv->caam_emi_slow);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "can't enable CAAM emi slow clock: %d\n",
+				ret);
+			goto disable_caam_aclk;
+		}
 	}
 
 	/* Get configuration properties from device tree */
@@ -541,13 +539,13 @@ static int caam_probe(struct platform_de
 	else
 		BLOCK_OFFSET = PG_SIZE_64K;
 
-	ctrlpriv->ctrl = (struct caam_ctrl __force *)ctrl;
-	ctrlpriv->assure = (struct caam_assurance __force *)
-			   ((uint8_t *)ctrl +
+	ctrlpriv->ctrl = (struct caam_ctrl __iomem __force *)ctrl;
+	ctrlpriv->assure = (struct caam_assurance __iomem __force *)
+			   ((__force uint8_t *)ctrl +
 			    BLOCK_OFFSET * ASSURE_BLOCK_NUMBER
 			   );
-	ctrlpriv->deco = (struct caam_deco __force *)
-			 ((uint8_t *)ctrl +
+	ctrlpriv->deco = (struct caam_deco __iomem __force *)
+			 ((__force uint8_t *)ctrl +
 			 BLOCK_OFFSET * DECO_BLOCK_NUMBER
 			 );
 
@@ -627,8 +625,8 @@ static int caam_probe(struct platform_de
 					ring);
 				continue;
 			}
-			ctrlpriv->jr[ring] = (struct caam_job_ring __force *)
-					     ((uint8_t *)ctrl +
+			ctrlpriv->jr[ring] = (struct caam_job_ring __iomem __force *)
+					     ((__force uint8_t *)ctrl +
 					     (ring + JR_BLOCK_NUMBER) *
 					      BLOCK_OFFSET
 					     );
@@ -641,8 +639,8 @@ static int caam_probe(struct platform_de
 			!!(rd_reg32(&ctrl->perfmon.comp_parms_ms) &
 			   CTPR_MS_QI_MASK);
 	if (ctrlpriv->qi_present) {
-		ctrlpriv->qi = (struct caam_queue_if __force *)
-			       ((uint8_t *)ctrl +
+		ctrlpriv->qi = (struct caam_queue_if __iomem __force *)
+			       ((__force uint8_t *)ctrl +
 				 BLOCK_OFFSET * QI_BLOCK_NUMBER
 			       );
 		/* This is all that's required to physically enable QI */
@@ -800,7 +798,7 @@ static int caam_probe(struct platform_de
 				    &caam_fops_u32_ro);
 
 	/* Internal covering keys (useful in non-secure mode only) */
-	ctrlpriv->ctl_kek_wrap.data = &ctrlpriv->ctrl->kek[0];
+	ctrlpriv->ctl_kek_wrap.data = (__force void *)&ctrlpriv->ctrl->kek[0];
 	ctrlpriv->ctl_kek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
 	ctrlpriv->ctl_kek = debugfs_create_blob("kek",
 						S_IRUSR |
@@ -808,7 +806,7 @@ static int caam_probe(struct platform_de
 						ctrlpriv->ctl,
 						&ctrlpriv->ctl_kek_wrap);
 
-	ctrlpriv->ctl_tkek_wrap.data = &ctrlpriv->ctrl->tkek[0];
+	ctrlpriv->ctl_tkek_wrap.data = (__force void *)&ctrlpriv->ctrl->tkek[0];
 	ctrlpriv->ctl_tkek_wrap.size = KEK_KEY_SIZE * sizeof(u32);
 	ctrlpriv->ctl_tkek = debugfs_create_blob("tkek",
 						 S_IRUSR |
@@ -816,7 +814,7 @@ static int caam_probe(struct platform_de
 						 ctrlpriv->ctl,
 						 &ctrlpriv->ctl_tkek_wrap);
 
-	ctrlpriv->ctl_tdsk_wrap.data = &ctrlpriv->ctrl->tdsk[0];
+	ctrlpriv->ctl_tdsk_wrap.data = (__force void *)&ctrlpriv->ctrl->tdsk[0];
 	ctrlpriv->ctl_tdsk_wrap.size = KEK_KEY_SIZE * sizeof(u32);
 	ctrlpriv->ctl_tdsk = debugfs_create_blob("tdsk",
 						 S_IRUSR |
@@ -833,7 +831,8 @@ caam_remove:
 iounmap_ctrl:
 	iounmap(ctrl);
 disable_caam_emi_slow:
-	clk_disable_unprepare(ctrlpriv->caam_emi_slow);
+	if (ctrlpriv->caam_emi_slow)
+		clk_disable_unprepare(ctrlpriv->caam_emi_slow);
 disable_caam_aclk:
 	clk_disable_unprepare(ctrlpriv->caam_aclk);
 disable_caam_mem:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/desc_constr.h linux-libre-4.10-rc8-gnu/drivers/crypto/caam/desc_constr.h
--- linux-libre-4.9-gnu/drivers/crypto/caam/desc_constr.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/desc_constr.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,38 +33,39 @@
 
 extern bool caam_little_end;
 
-static inline int desc_len(u32 *desc)
+static inline int desc_len(u32 * const desc)
 {
 	return caam32_to_cpu(*desc) & HDR_DESCLEN_MASK;
 }
 
-static inline int desc_bytes(void *desc)
+static inline int desc_bytes(void * const desc)
 {
 	return desc_len(desc) * CAAM_CMD_SZ;
 }
 
-static inline u32 *desc_end(u32 *desc)
+static inline u32 *desc_end(u32 * const desc)
 {
 	return desc + desc_len(desc);
 }
 
-static inline void *sh_desc_pdb(u32 *desc)
+static inline void *sh_desc_pdb(u32 * const desc)
 {
 	return desc + 1;
 }
 
-static inline void init_desc(u32 *desc, u32 options)
+static inline void init_desc(u32 * const desc, u32 options)
 {
 	*desc = cpu_to_caam32((options | HDR_ONE) + 1);
 }
 
-static inline void init_sh_desc(u32 *desc, u32 options)
+static inline void init_sh_desc(u32 * const desc, u32 options)
 {
 	PRINT_POS;
 	init_desc(desc, CMD_SHARED_DESC_HDR | options);
 }
 
-static inline void init_sh_desc_pdb(u32 *desc, u32 options, size_t pdb_bytes)
+static inline void init_sh_desc_pdb(u32 * const desc, u32 options,
+				    size_t pdb_bytes)
 {
 	u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
 
@@ -72,19 +73,20 @@ static inline void init_sh_desc_pdb(u32
 		     options);
 }
 
-static inline void init_job_desc(u32 *desc, u32 options)
+static inline void init_job_desc(u32 * const desc, u32 options)
 {
 	init_desc(desc, CMD_DESC_HDR | options);
 }
 
-static inline void init_job_desc_pdb(u32 *desc, u32 options, size_t pdb_bytes)
+static inline void init_job_desc_pdb(u32 * const desc, u32 options,
+				     size_t pdb_bytes)
 {
 	u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
 
 	init_job_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT)) | options);
 }
 
-static inline void append_ptr(u32 *desc, dma_addr_t ptr)
+static inline void append_ptr(u32 * const desc, dma_addr_t ptr)
 {
 	dma_addr_t *offset = (dma_addr_t *)desc_end(desc);
 
@@ -94,8 +96,8 @@ static inline void append_ptr(u32 *desc,
 				CAAM_PTR_SZ / CAAM_CMD_SZ);
 }
 
-static inline void init_job_desc_shared(u32 *desc, dma_addr_t ptr, int len,
-					u32 options)
+static inline void init_job_desc_shared(u32 * const desc, dma_addr_t ptr,
+					int len, u32 options)
 {
 	PRINT_POS;
 	init_job_desc(desc, HDR_SHARED | options |
@@ -103,7 +105,7 @@ static inline void init_job_desc_shared(
 	append_ptr(desc, ptr);
 }
 
-static inline void append_data(u32 *desc, void *data, int len)
+static inline void append_data(u32 * const desc, void *data, int len)
 {
 	u32 *offset = desc_end(desc);
 
@@ -114,7 +116,7 @@ static inline void append_data(u32 *desc
 				(len + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ);
 }
 
-static inline void append_cmd(u32 *desc, u32 command)
+static inline void append_cmd(u32 * const desc, u32 command)
 {
 	u32 *cmd = desc_end(desc);
 
@@ -125,7 +127,7 @@ static inline void append_cmd(u32 *desc,
 
 #define append_u32 append_cmd
 
-static inline void append_u64(u32 *desc, u64 data)
+static inline void append_u64(u32 * const desc, u64 data)
 {
 	u32 *offset = desc_end(desc);
 
@@ -142,14 +144,14 @@ static inline void append_u64(u32 *desc,
 }
 
 /* Write command without affecting header, and return pointer to next word */
-static inline u32 *write_cmd(u32 *desc, u32 command)
+static inline u32 *write_cmd(u32 * const desc, u32 command)
 {
 	*desc = cpu_to_caam32(command);
 
 	return desc + 1;
 }
 
-static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len,
+static inline void append_cmd_ptr(u32 * const desc, dma_addr_t ptr, int len,
 				  u32 command)
 {
 	append_cmd(desc, command | len);
@@ -157,7 +159,7 @@ static inline void append_cmd_ptr(u32 *d
 }
 
 /* Write length after pointer, rather than inside command */
-static inline void append_cmd_ptr_extlen(u32 *desc, dma_addr_t ptr,
+static inline void append_cmd_ptr_extlen(u32 * const desc, dma_addr_t ptr,
 					 unsigned int len, u32 command)
 {
 	append_cmd(desc, command);
@@ -166,7 +168,7 @@ static inline void append_cmd_ptr_extlen
 	append_cmd(desc, len);
 }
 
-static inline void append_cmd_data(u32 *desc, void *data, int len,
+static inline void append_cmd_data(u32 * const desc, void *data, int len,
 				   u32 command)
 {
 	append_cmd(desc, command | IMMEDIATE | len);
@@ -174,7 +176,7 @@ static inline void append_cmd_data(u32 *
 }
 
 #define APPEND_CMD_RET(cmd, op) \
-static inline u32 *append_##cmd(u32 *desc, u32 options) \
+static inline u32 *append_##cmd(u32 * const desc, u32 options) \
 { \
 	u32 *cmd = desc_end(desc); \
 	PRINT_POS; \
@@ -184,13 +186,13 @@ static inline u32 *append_##cmd(u32 *des
 APPEND_CMD_RET(jump, JUMP)
 APPEND_CMD_RET(move, MOVE)
 
-static inline void set_jump_tgt_here(u32 *desc, u32 *jump_cmd)
+static inline void set_jump_tgt_here(u32 * const desc, u32 *jump_cmd)
 {
 	*jump_cmd = cpu_to_caam32(caam32_to_cpu(*jump_cmd) |
 				  (desc_len(desc) - (jump_cmd - desc)));
 }
 
-static inline void set_move_tgt_here(u32 *desc, u32 *move_cmd)
+static inline void set_move_tgt_here(u32 * const desc, u32 *move_cmd)
 {
 	u32 val = caam32_to_cpu(*move_cmd);
 
@@ -200,7 +202,7 @@ static inline void set_move_tgt_here(u32
 }
 
 #define APPEND_CMD(cmd, op) \
-static inline void append_##cmd(u32 *desc, u32 options) \
+static inline void append_##cmd(u32 * const desc, u32 options) \
 { \
 	PRINT_POS; \
 	append_cmd(desc, CMD_##op | options); \
@@ -208,7 +210,8 @@ static inline void append_##cmd(u32 *des
 APPEND_CMD(operation, OPERATION)
 
 #define APPEND_CMD_LEN(cmd, op) \
-static inline void append_##cmd(u32 *desc, unsigned int len, u32 options) \
+static inline void append_##cmd(u32 * const desc, unsigned int len, \
+				u32 options) \
 { \
 	PRINT_POS; \
 	append_cmd(desc, CMD_##op | len | options); \
@@ -220,8 +223,8 @@ APPEND_CMD_LEN(seq_fifo_load, SEQ_FIFO_L
 APPEND_CMD_LEN(seq_fifo_store, SEQ_FIFO_STORE)
 
 #define APPEND_CMD_PTR(cmd, op) \
-static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \
-				u32 options) \
+static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
+				unsigned int len, u32 options) \
 { \
 	PRINT_POS; \
 	append_cmd_ptr(desc, ptr, len, CMD_##op | options); \
@@ -231,8 +234,8 @@ APPEND_CMD_PTR(load, LOAD)
 APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
 APPEND_CMD_PTR(fifo_store, FIFO_STORE)
 
-static inline void append_store(u32 *desc, dma_addr_t ptr, unsigned int len,
-				u32 options)
+static inline void append_store(u32 * const desc, dma_addr_t ptr,
+				unsigned int len, u32 options)
 {
 	u32 cmd_src;
 
@@ -249,7 +252,8 @@ static inline void append_store(u32 *des
 }
 
 #define APPEND_SEQ_PTR_INTLEN(cmd, op) \
-static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \
+static inline void append_seq_##cmd##_ptr_intlen(u32 * const desc, \
+						 dma_addr_t ptr, \
 						 unsigned int len, \
 						 u32 options) \
 { \
@@ -263,7 +267,7 @@ APPEND_SEQ_PTR_INTLEN(in, IN)
 APPEND_SEQ_PTR_INTLEN(out, OUT)
 
 #define APPEND_CMD_PTR_TO_IMM(cmd, op) \
-static inline void append_##cmd##_as_imm(u32 *desc, void *data, \
+static inline void append_##cmd##_as_imm(u32 * const desc, void *data, \
 					 unsigned int len, u32 options) \
 { \
 	PRINT_POS; \
@@ -273,7 +277,7 @@ APPEND_CMD_PTR_TO_IMM(load, LOAD);
 APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
 
 #define APPEND_CMD_PTR_EXTLEN(cmd, op) \
-static inline void append_##cmd##_extlen(u32 *desc, dma_addr_t ptr, \
+static inline void append_##cmd##_extlen(u32 * const desc, dma_addr_t ptr, \
 					 unsigned int len, u32 options) \
 { \
 	PRINT_POS; \
@@ -287,7 +291,7 @@ APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_O
  * the size of its type
  */
 #define APPEND_CMD_PTR_LEN(cmd, op, type) \
-static inline void append_##cmd(u32 *desc, dma_addr_t ptr, \
+static inline void append_##cmd(u32 * const desc, dma_addr_t ptr, \
 				type len, u32 options) \
 { \
 	PRINT_POS; \
@@ -304,7 +308,7 @@ APPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_
  * from length of immediate data provided, e.g., split keys
  */
 #define APPEND_CMD_PTR_TO_IMM2(cmd, op) \
-static inline void append_##cmd##_as_imm(u32 *desc, void *data, \
+static inline void append_##cmd##_as_imm(u32 * const desc, void *data, \
 					 unsigned int data_len, \
 					 unsigned int len, u32 options) \
 { \
@@ -315,7 +319,7 @@ static inline void append_##cmd##_as_imm
 APPEND_CMD_PTR_TO_IMM2(key, KEY);
 
 #define APPEND_CMD_RAW_IMM(cmd, op, type) \
-static inline void append_##cmd##_imm_##type(u32 *desc, type immediate, \
+static inline void append_##cmd##_imm_##type(u32 * const desc, type immediate, \
 					     u32 options) \
 { \
 	PRINT_POS; \
@@ -426,3 +430,64 @@ do { \
 	APPEND_MATH_IMM_u64(LSHIFT, desc, dest, src0, src1, data)
 #define append_math_rshift_imm_u64(desc, dest, src0, src1, data) \
 	APPEND_MATH_IMM_u64(RSHIFT, desc, dest, src0, src1, data)
+
+/**
+ * struct alginfo - Container for algorithm details
+ * @algtype: algorithm selector; for valid values, see documentation of the
+ *           functions where it is used.
+ * @keylen: length of the provided algorithm key, in bytes
+ * @keylen_pad: padded length of the provided algorithm key, in bytes
+ * @key: address where algorithm key resides; virtual address if key_inline
+ *       is true, dma (bus) address if key_inline is false.
+ * @key_inline: true - key can be inlined in the descriptor; false - key is
+ *              referenced by the descriptor
+ */
+struct alginfo {
+	u32 algtype;
+	unsigned int keylen;
+	unsigned int keylen_pad;
+	union {
+		dma_addr_t key_dma;
+		void *key_virt;
+	};
+	bool key_inline;
+};
+
+/**
+ * desc_inline_query() - Provide indications on which data items can be inlined
+ *                       and which shall be referenced in a shared descriptor.
+ * @sd_base_len: Shared descriptor base length - bytes consumed by the commands,
+ *               excluding the data items to be inlined (or corresponding
+ *               pointer if an item is not inlined). Each cnstr_* function that
+ *               generates descriptors should have a define mentioning
+ *               corresponding length.
+ * @jd_len: Maximum length of the job descriptor(s) that will be used
+ *          together with the shared descriptor.
+ * @data_len: Array of lengths of the data items trying to be inlined
+ * @inl_mask: 32bit mask with bit x = 1 if data item x can be inlined, 0
+ *            otherwise.
+ * @count: Number of data items (size of @data_len array); must be <= 32
+ *
+ * Return: 0 if data can be inlined / referenced, negative value if not. If 0,
+ *         check @inl_mask for details.
+ */
+static inline int desc_inline_query(unsigned int sd_base_len,
+				    unsigned int jd_len, unsigned int *data_len,
+				    u32 *inl_mask, unsigned int count)
+{
+	int rem_bytes = (int)(CAAM_DESC_BYTES_MAX - sd_base_len - jd_len);
+	unsigned int i;
+
+	*inl_mask = 0;
+	for (i = 0; (i < count) && (rem_bytes > 0); i++) {
+		if (rem_bytes - (int)(data_len[i] +
+			(count - i - 1) * CAAM_PTR_SZ) >= 0) {
+			rem_bytes -= data_len[i];
+			*inl_mask |= (1 << i);
+		} else {
+			rem_bytes -= CAAM_PTR_SZ;
+		}
+	}
+
+	return (rem_bytes >= 0) ? 0 : -1;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/desc.h linux-libre-4.10-rc8-gnu/drivers/crypto/caam/desc.h
--- linux-libre-4.9-gnu/drivers/crypto/caam/desc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/desc.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,12 +22,6 @@
 #define SEC4_SG_LEN_MASK	0x3fffffff	/* Excludes EXT and FINAL */
 #define SEC4_SG_OFFSET_MASK	0x00001fff
 
-struct sec4_sg_entry {
-	u64 ptr;
-	u32 len;
-	u32 bpid_offset;
-};
-
 /* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
 #define MAX_CAAM_DESCSIZE	64
 
@@ -90,8 +84,8 @@ struct sec4_sg_entry {
 #define HDR_ZRO			0x00008000
 
 /* Start Index or SharedDesc Length */
-#define HDR_START_IDX_MASK	0x3f
 #define HDR_START_IDX_SHIFT	16
+#define HDR_START_IDX_MASK	(0x3f << HDR_START_IDX_SHIFT)
 
 /* If shared descriptor header, 6-bit length */
 #define HDR_DESCLEN_SHR_MASK	0x3f
@@ -121,10 +115,10 @@ struct sec4_sg_entry {
 #define HDR_PROP_DNR		0x00000800
 
 /* JobDesc/SharedDesc share property */
-#define HDR_SD_SHARE_MASK	0x03
 #define HDR_SD_SHARE_SHIFT	8
-#define HDR_JD_SHARE_MASK	0x07
+#define HDR_SD_SHARE_MASK	(0x03 << HDR_SD_SHARE_SHIFT)
 #define HDR_JD_SHARE_SHIFT	8
+#define HDR_JD_SHARE_MASK	(0x07 << HDR_JD_SHARE_SHIFT)
 
 #define HDR_SHARE_NEVER		(0x00 << HDR_SD_SHARE_SHIFT)
 #define HDR_SHARE_WAIT		(0x01 << HDR_SD_SHARE_SHIFT)
@@ -235,7 +229,7 @@ struct sec4_sg_entry {
 #define LDST_SRCDST_WORD_DECO_MATH2	(0x0a << LDST_SRCDST_SHIFT)
 #define LDST_SRCDST_WORD_DECO_AAD_SZ	(0x0b << LDST_SRCDST_SHIFT)
 #define LDST_SRCDST_WORD_DECO_MATH3	(0x0b << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_CLASS1_ICV_SZ	(0x0c << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CLASS1_IV_SZ	(0x0c << LDST_SRCDST_SHIFT)
 #define LDST_SRCDST_WORD_ALTDS_CLASS1	(0x0f << LDST_SRCDST_SHIFT)
 #define LDST_SRCDST_WORD_PKHA_A_SZ	(0x10 << LDST_SRCDST_SHIFT)
 #define LDST_SRCDST_WORD_PKHA_B_SZ	(0x11 << LDST_SRCDST_SHIFT)
@@ -400,7 +394,7 @@ struct sec4_sg_entry {
 #define FIFOST_TYPE_PKHA_N	 (0x08 << FIFOST_TYPE_SHIFT)
 #define FIFOST_TYPE_PKHA_A	 (0x0c << FIFOST_TYPE_SHIFT)
 #define FIFOST_TYPE_PKHA_B	 (0x0d << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_AF_SBOX_JKEK (0x10 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_AF_SBOX_JKEK (0x20 << FIFOST_TYPE_SHIFT)
 #define FIFOST_TYPE_AF_SBOX_TKEK (0x21 << FIFOST_TYPE_SHIFT)
 #define FIFOST_TYPE_PKHA_E_JKEK	 (0x22 << FIFOST_TYPE_SHIFT)
 #define FIFOST_TYPE_PKHA_E_TKEK	 (0x23 << FIFOST_TYPE_SHIFT)
@@ -1107,8 +1101,8 @@ struct sec4_sg_entry {
 /* For non-protocol/alg-only op commands */
 #define OP_ALG_TYPE_SHIFT	24
 #define OP_ALG_TYPE_MASK	(0x7 << OP_ALG_TYPE_SHIFT)
-#define OP_ALG_TYPE_CLASS1	2
-#define OP_ALG_TYPE_CLASS2	4
+#define OP_ALG_TYPE_CLASS1	(2 << OP_ALG_TYPE_SHIFT)
+#define OP_ALG_TYPE_CLASS2	(4 << OP_ALG_TYPE_SHIFT)
 
 #define OP_ALG_ALGSEL_SHIFT	16
 #define OP_ALG_ALGSEL_MASK	(0xff << OP_ALG_ALGSEL_SHIFT)
@@ -1249,7 +1243,7 @@ struct sec4_sg_entry {
 #define OP_ALG_PKMODE_MOD_PRIMALITY	0x00f
 
 /* PKHA mode copy-memory functions */
-#define OP_ALG_PKMODE_SRC_REG_SHIFT	13
+#define OP_ALG_PKMODE_SRC_REG_SHIFT	17
 #define OP_ALG_PKMODE_SRC_REG_MASK	(7 << OP_ALG_PKMODE_SRC_REG_SHIFT)
 #define OP_ALG_PKMODE_DST_REG_SHIFT	10
 #define OP_ALG_PKMODE_DST_REG_MASK	(7 << OP_ALG_PKMODE_DST_REG_SHIFT)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/error.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/error.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/error.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/error.c	2017-02-12 16:03:20.000000000 -0500
@@ -146,10 +146,9 @@ static void report_ccb_status(struct dev
 	    strlen(rng_err_id_list[err_id])) {
 		/* RNG-only error */
 		err_str = rng_err_id_list[err_id];
-	} else if (err_id < ARRAY_SIZE(err_id_list))
+	} else {
 		err_str = err_id_list[err_id];
-	else
-		snprintf(err_err_code, sizeof(err_err_code), "%02x", err_id);
+	}
 
 	/*
 	 * CCB ICV check failures are part of normal operation life;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/intern.h linux-libre-4.10-rc8-gnu/drivers/crypto/caam/intern.h
--- linux-libre-4.9-gnu/drivers/crypto/caam/intern.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/intern.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,7 @@ struct caam_drv_private_jr {
 	struct device		*dev;
 	int ridx;
 	struct caam_job_ring __iomem *rregs;	/* JobR's register space */
+	struct tasklet_struct irqtask;
 	int irq;			/* One per queue */
 
 	/* Number of scatterlist crypt transforms active on the JobR */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/jr.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/jr.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/jr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/jr.c	2017-02-12 16:03:20.000000000 -0500
@@ -73,6 +73,8 @@ static int caam_jr_shutdown(struct devic
 
 	ret = caam_reset_hw_jr(dev);
 
+	tasklet_kill(&jrp->irqtask);
+
 	/* Release interrupt */
 	free_irq(jrp->irq, dev);
 
@@ -128,7 +130,7 @@ static irqreturn_t caam_jr_interrupt(int
 
 	/*
 	 * Check the output ring for ready responses, kick
-	 * the threaded irq if jobs done.
+	 * tasklet if jobs done.
 	 */
 	irqstate = rd_reg32(&jrp->rregs->jrintstatus);
 	if (!irqstate)
@@ -150,13 +152,18 @@ static irqreturn_t caam_jr_interrupt(int
 	/* Have valid interrupt at this point, just ACK and trigger */
 	wr_reg32(&jrp->rregs->jrintstatus, irqstate);
 
-	return IRQ_WAKE_THREAD;
+	preempt_disable();
+	tasklet_schedule(&jrp->irqtask);
+	preempt_enable();
+
+	return IRQ_HANDLED;
 }
 
-static irqreturn_t caam_jr_threadirq(int irq, void *st_dev)
+/* Deferred service handler, run as interrupt-fired tasklet */
+static void caam_jr_dequeue(unsigned long devarg)
 {
 	int hw_idx, sw_idx, i, head, tail;
-	struct device *dev = st_dev;
+	struct device *dev = (struct device *)devarg;
 	struct caam_drv_private_jr *jrp = dev_get_drvdata(dev);
 	void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg);
 	u32 *userdesc, userstatus;
@@ -230,8 +237,6 @@ static irqreturn_t caam_jr_threadirq(int
 
 	/* reenable / unmask IRQs */
 	clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0);
-
-	return IRQ_HANDLED;
 }
 
 /**
@@ -389,10 +394,11 @@ static int caam_jr_init(struct device *d
 
 	jrp = dev_get_drvdata(dev);
 
+	tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev);
+
 	/* Connect job ring interrupt handler. */
-	error = request_threaded_irq(jrp->irq, caam_jr_interrupt,
-				     caam_jr_threadirq, IRQF_SHARED,
-				     dev_name(dev), dev);
+	error = request_irq(jrp->irq, caam_jr_interrupt, IRQF_SHARED,
+			    dev_name(dev), dev);
 	if (error) {
 		dev_err(dev, "can't connect JobR %d interrupt (%d)\n",
 			jrp->ridx, jrp->irq);
@@ -454,6 +460,7 @@ out_free_inpring:
 out_free_irq:
 	free_irq(jrp->irq, dev);
 out_kill_deq:
+	tasklet_kill(&jrp->irqtask);
 	return error;
 }
 
@@ -489,7 +496,7 @@ static int caam_jr_probe(struct platform
 		return -ENOMEM;
 	}
 
-	jrpriv->rregs = (struct caam_job_ring __force *)ctrl;
+	jrpriv->rregs = (struct caam_job_ring __iomem __force *)ctrl;
 
 	if (sizeof(dma_addr_t) == sizeof(u64))
 		if (of_device_is_compatible(nprop, "fsl,sec-v5.0-job-ring"))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/Kconfig linux-libre-4.10-rc8-gnu/drivers/crypto/caam/Kconfig
--- linux-libre-4.9-gnu/drivers/crypto/caam/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -74,7 +74,7 @@ config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THL
 
 config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
 	tristate "Register algorithm implementations with the Crypto API"
-	depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+	depends on CRYPTO_DEV_FSL_CAAM_JR
 	default y
 	select CRYPTO_AEAD
 	select CRYPTO_AUTHENC
@@ -89,7 +89,7 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
 
 config CRYPTO_DEV_FSL_CAAM_AHASH_API
 	tristate "Register hash algorithm implementations with Crypto API"
-	depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+	depends on CRYPTO_DEV_FSL_CAAM_JR
 	default y
 	select CRYPTO_HASH
 	help
@@ -101,7 +101,7 @@ config CRYPTO_DEV_FSL_CAAM_AHASH_API
 
 config CRYPTO_DEV_FSL_CAAM_PKC_API
         tristate "Register public key cryptography implementations with Crypto API"
-        depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+        depends on CRYPTO_DEV_FSL_CAAM_JR
         default y
         select CRYPTO_RSA
         help
@@ -113,7 +113,7 @@ config CRYPTO_DEV_FSL_CAAM_PKC_API
 
 config CRYPTO_DEV_FSL_CAAM_RNG_API
 	tristate "Register caam device for hwrng API"
-	depends on CRYPTO_DEV_FSL_CAAM && CRYPTO_DEV_FSL_CAAM_JR
+	depends on CRYPTO_DEV_FSL_CAAM_JR
 	default y
 	select CRYPTO_RNG
 	select HW_RANDOM
@@ -134,3 +134,6 @@ config CRYPTO_DEV_FSL_CAAM_DEBUG
 	help
 	  Selecting this will enable printing of various debug
 	  information in the CAAM driver.
+
+config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC
+	def_tristate CRYPTO_DEV_FSL_CAAM_CRYPTO_API
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/key_gen.c linux-libre-4.10-rc8-gnu/drivers/crypto/caam/key_gen.c
--- linux-libre-4.9-gnu/drivers/crypto/caam/key_gen.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/key_gen.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,36 @@
 #include "desc_constr.h"
 #include "key_gen.h"
 
+/**
+ * split_key_len - Compute MDHA split key length for a given algorithm
+ * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1,
+ *        SHA224, SHA384, SHA512.
+ *
+ * Return: MDHA split key length
+ */
+static inline u32 split_key_len(u32 hash)
+{
+	/* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
+	static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
+	u32 idx;
+
+	idx = (hash & OP_ALG_ALGSEL_SUBMASK) >> OP_ALG_ALGSEL_SHIFT;
+
+	return (u32)(mdpadlen[idx] * 2);
+}
+
+/**
+ * split_key_pad_len - Compute MDHA split key pad length for a given algorithm
+ * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1,
+ *        SHA224, SHA384, SHA512.
+ *
+ * Return: MDHA split key pad length
+ */
+static inline u32 split_key_pad_len(u32 hash)
+{
+	return ALIGN(split_key_len(hash), 16);
+}
+
 void split_key_done(struct device *dev, u32 *desc, u32 err,
 			   void *context)
 {
@@ -41,15 +71,29 @@ Split key generation--------------------
 [06] 0x64260028    fifostr: class2 mdsplit-jdk len=40
 			@0xffe04000
 */
-int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
-		  int split_key_pad_len, const u8 *key_in, u32 keylen,
-		  u32 alg_op)
+int gen_split_key(struct device *jrdev, u8 *key_out,
+		  struct alginfo * const adata, const u8 *key_in, u32 keylen,
+		  int max_keylen)
 {
 	u32 *desc;
 	struct split_key_result result;
 	dma_addr_t dma_addr_in, dma_addr_out;
 	int ret = -ENOMEM;
 
+	adata->keylen = split_key_len(adata->algtype & OP_ALG_ALGSEL_MASK);
+	adata->keylen_pad = split_key_pad_len(adata->algtype &
+					      OP_ALG_ALGSEL_MASK);
+
+#ifdef DEBUG
+	dev_err(jrdev, "split keylen %d split keylen padded %d\n",
+		adata->keylen, adata->keylen_pad);
+	print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1);
+#endif
+
+	if (adata->keylen_pad > max_keylen)
+		return -EINVAL;
+
 	desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
 	if (!desc) {
 		dev_err(jrdev, "unable to allocate key input memory\n");
@@ -63,7 +107,7 @@ int gen_split_key(struct device *jrdev,
 		goto out_free;
 	}
 
-	dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len,
+	dma_addr_out = dma_map_single(jrdev, key_out, adata->keylen_pad,
 				      DMA_FROM_DEVICE);
 	if (dma_mapping_error(jrdev, dma_addr_out)) {
 		dev_err(jrdev, "unable to map key output memory\n");
@@ -74,7 +118,9 @@ int gen_split_key(struct device *jrdev,
 	append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
 
 	/* Sets MDHA up into an HMAC-INIT */
-	append_operation(desc, alg_op | OP_ALG_DECRYPT | OP_ALG_AS_INIT);
+	append_operation(desc, (adata->algtype & OP_ALG_ALGSEL_MASK) |
+			 OP_ALG_AAI_HMAC | OP_TYPE_CLASS2_ALG | OP_ALG_DECRYPT |
+			 OP_ALG_AS_INIT);
 
 	/*
 	 * do a FIFO_LOAD of zero, this will trigger the internal key expansion
@@ -87,7 +133,7 @@ int gen_split_key(struct device *jrdev,
 	 * FIFO_STORE with the explicit split-key content store
 	 * (0x26 output type)
 	 */
-	append_fifo_store(desc, dma_addr_out, split_key_len,
+	append_fifo_store(desc, dma_addr_out, adata->keylen,
 			  LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
 
 #ifdef DEBUG
@@ -108,11 +154,11 @@ int gen_split_key(struct device *jrdev,
 #ifdef DEBUG
 		print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
 			       DUMP_PREFIX_ADDRESS, 16, 4, key_out,
-			       split_key_pad_len, 1);
+			       adata->keylen_pad, 1);
 #endif
 	}
 
-	dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len,
+	dma_unmap_single(jrdev, dma_addr_out, adata->keylen_pad,
 			 DMA_FROM_DEVICE);
 out_unmap_in:
 	dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/key_gen.h linux-libre-4.10-rc8-gnu/drivers/crypto/caam/key_gen.h
--- linux-libre-4.9-gnu/drivers/crypto/caam/key_gen.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/key_gen.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,6 @@ struct split_key_result {
 
 void split_key_done(struct device *dev, u32 *desc, u32 err, void *context);
 
-int gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
-		    int split_key_pad_len, const u8 *key_in, u32 keylen,
-		    u32 alg_op);
+int gen_split_key(struct device *jrdev, u8 *key_out,
+		  struct alginfo * const adata, const u8 *key_in, u32 keylen,
+		  int max_keylen);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/Makefile linux-libre-4.10-rc8-gnu/drivers/crypto/caam/Makefile
--- linux-libre-4.9-gnu/drivers/crypto/caam/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,7 @@ endif
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC) += caamalg_desc.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/caam/sg_sw_sec4.h linux-libre-4.10-rc8-gnu/drivers/crypto/caam/sg_sw_sec4.h
--- linux-libre-4.9-gnu/drivers/crypto/caam/sg_sw_sec4.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/caam/sg_sw_sec4.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,11 @@
 
 #include "regs.h"
 
-struct sec4_sg_entry;
+struct sec4_sg_entry {
+	u64 ptr;
+	u32 len;
+	u32 bpid_offset;
+};
 
 /*
  * convert single dma address to h/w link table format
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev.c linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev.c
--- linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@ struct ccp_tasklet_data {
 };
 
 /* Human-readable error strings */
-char *ccp_error_codes[] = {
+static char *ccp_error_codes[] = {
 	"",
 	"ERR 01: ILLEGAL_ENGINE",
 	"ERR 02: ILLEGAL_KEY_ID",
@@ -478,6 +478,10 @@ struct ccp_device *ccp_alloc_struct(stru
 	ccp->sb_count = KSB_COUNT;
 	ccp->sb_start = 0;
 
+	/* Initialize the wait queues */
+	init_waitqueue_head(&ccp->sb_queue);
+	init_waitqueue_head(&ccp->suspend_queue);
+
 	ccp->ord = ccp_increment_unit_ordinal();
 	snprintf(ccp->name, MAX_CCP_NAME_LEN, "ccp-%u", ccp->ord);
 	snprintf(ccp->rngname, MAX_CCP_NAME_LEN, "ccp-%u-rng", ccp->ord);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev.h linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev.h
--- linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev.h	2017-02-12 16:03:20.000000000 -0500
@@ -238,6 +238,7 @@ struct ccp_dma_chan {
 	struct ccp_device *ccp;
 
 	spinlock_t lock;
+	struct list_head created;
 	struct list_head pending;
 	struct list_head active;
 	struct list_head complete;
@@ -278,7 +279,7 @@ struct ccp_cmd_queue {
 	/* Private LSB that is assigned to this queue, or -1 if none.
 	 * Bitmap for my private LSB, unused otherwise
 	 */
-	unsigned int lsb;
+	int lsb;
 	DECLARE_BITMAP(lsbmap, PLSB_MAP_SIZE);
 
 	/* Queue processing thread */
@@ -515,7 +516,6 @@ struct ccp_op {
 		struct ccp_passthru_op passthru;
 		struct ccp_ecc_op ecc;
 	} u;
-	struct ccp_mem key;
 };
 
 static inline u32 ccp_addr_lo(struct ccp_dma_info *info)
@@ -541,23 +541,23 @@ static inline u32 ccp_addr_hi(struct ccp
  * word 7: upper 16 bits of key pointer; key memory type
  */
 struct dword0 {
-	__le32 soc:1;
-	__le32 ioc:1;
-	__le32 rsvd1:1;
-	__le32 init:1;
-	__le32 eom:1;		/* AES/SHA only */
-	__le32 function:15;
-	__le32 engine:4;
-	__le32 prot:1;
-	__le32 rsvd2:7;
+	unsigned int soc:1;
+	unsigned int ioc:1;
+	unsigned int rsvd1:1;
+	unsigned int init:1;
+	unsigned int eom:1;		/* AES/SHA only */
+	unsigned int function:15;
+	unsigned int engine:4;
+	unsigned int prot:1;
+	unsigned int rsvd2:7;
 };
 
 struct dword3 {
-	__le32 src_hi:16;
-	__le32 src_mem:2;
-	__le32 lsb_cxt_id:8;
-	__le32 rsvd1:5;
-	__le32 fixed:1;
+	unsigned int  src_hi:16;
+	unsigned int  src_mem:2;
+	unsigned int  lsb_cxt_id:8;
+	unsigned int  rsvd1:5;
+	unsigned int  fixed:1;
 };
 
 union dword4 {
@@ -567,18 +567,18 @@ union dword4 {
 
 union dword5 {
 	struct {
-		__le32 dst_hi:16;
-		__le32 dst_mem:2;
-		__le32 rsvd1:13;
-		__le32 fixed:1;
+		unsigned int  dst_hi:16;
+		unsigned int  dst_mem:2;
+		unsigned int  rsvd1:13;
+		unsigned int  fixed:1;
 	} fields;
 	__le32 sha_len_hi;
 };
 
 struct dword7 {
-	__le32 key_hi:16;
-	__le32 key_mem:2;
-	__le32 rsvd1:14;
+	unsigned int  key_hi:16;
+	unsigned int  key_mem:2;
+	unsigned int  rsvd1:14;
 };
 
 struct ccp5_desc {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev-v3.c linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev-v3.c
--- linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev-v3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev-v3.c	2017-02-12 16:03:20.000000000 -0500
@@ -404,10 +404,6 @@ static int ccp_init(struct ccp_device *c
 		goto e_pool;
 	}
 
-	/* Initialize the queues used to wait for KSB space and suspend */
-	init_waitqueue_head(&ccp->sb_queue);
-	init_waitqueue_head(&ccp->suspend_queue);
-
 	dev_dbg(dev, "Starting threads...\n");
 	/* Create a kthread for each queue */
 	for (i = 0; i < ccp->cmd_q_count; i++) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev-v5.c linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev-v5.c
--- linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dev-v5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dev-v5.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,12 @@
 
 #include "ccp-dev.h"
 
+/* Allocate the requested number of contiguous LSB slots
+ * from the LSB bitmap. Look in the private range for this
+ * queue first; failing that, check the public area.
+ * If no space is available, wait around.
+ * Return: first slot number
+ */
 static u32 ccp_lsb_alloc(struct ccp_cmd_queue *cmd_q, unsigned int count)
 {
 	struct ccp_device *ccp;
@@ -50,7 +56,7 @@ static u32 ccp_lsb_alloc(struct ccp_cmd_
 			bitmap_set(ccp->lsbmap, start, count);
 
 			mutex_unlock(&ccp->sb_mutex);
-			return start * LSB_ITEM_SIZE;
+			return start;
 		}
 
 		ccp->sb_avail = 0;
@@ -63,17 +69,18 @@ static u32 ccp_lsb_alloc(struct ccp_cmd_
 	}
 }
 
+/* Free a number of LSB slots from the bitmap, starting at
+ * the indicated starting slot number.
+ */
 static void ccp_lsb_free(struct ccp_cmd_queue *cmd_q, unsigned int start,
 			 unsigned int count)
 {
-	int lsbno = start / LSB_SIZE;
-
 	if (!start)
 		return;
 
-	if (cmd_q->lsb == lsbno) {
+	if (cmd_q->lsb == start) {
 		/* An entry from the private LSB */
-		bitmap_clear(cmd_q->lsbmap, start % LSB_SIZE, count);
+		bitmap_clear(cmd_q->lsbmap, start, count);
 	} else {
 		/* From the shared LSBs */
 		struct ccp_device *ccp = cmd_q->ccp;
@@ -396,7 +403,7 @@ static int ccp5_perform_rsa(struct ccp_o
 	CCP5_CMD_PROT(&desc) = 0;
 
 	function.raw = 0;
-	CCP_RSA_SIZE(&function) = op->u.rsa.mod_size;
+	CCP_RSA_SIZE(&function) = op->u.rsa.mod_size >> 3;
 	CCP5_CMD_FUNCTION(&desc) = function.raw;
 
 	CCP5_CMD_LEN(&desc) = op->u.rsa.input_len;
@@ -411,10 +418,10 @@ static int ccp5_perform_rsa(struct ccp_o
 	CCP5_CMD_DST_HI(&desc) = ccp_addr_hi(&op->dst.u.dma);
 	CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SYSTEM;
 
-	/* Key (Exponent) is in external memory */
-	CCP5_CMD_KEY_LO(&desc) = ccp_addr_lo(&op->exp.u.dma);
-	CCP5_CMD_KEY_HI(&desc) = ccp_addr_hi(&op->exp.u.dma);
-	CCP5_CMD_KEY_MEM(&desc) = CCP_MEMTYPE_SYSTEM;
+	/* Exponent is in LSB memory */
+	CCP5_CMD_KEY_LO(&desc) = op->sb_key * LSB_ITEM_SIZE;
+	CCP5_CMD_KEY_HI(&desc) = 0;
+	CCP5_CMD_KEY_MEM(&desc) = CCP_MEMTYPE_SB;
 
 	return ccp5_do_cmd(&desc, op->cmd_q);
 }
@@ -751,9 +758,6 @@ static int ccp5_init(struct ccp_device *
 		goto e_pool;
 	}
 
-	/* Initialize the queue used to suspend */
-	init_waitqueue_head(&ccp->suspend_queue);
-
 	dev_dbg(dev, "Loading LSB map...\n");
 	/* Copy the private LSB mask to the public registers */
 	status_lo = ioread32(ccp->io_regs + LSB_PRIVATE_MASK_LO_OFFSET);
@@ -955,7 +959,7 @@ static irqreturn_t ccp5_irq_handler(int
 static void ccp5_config(struct ccp_device *ccp)
 {
 	/* Public side */
-	iowrite32(0x00001249, ccp->io_regs + CMD5_REQID_CONFIG_OFFSET);
+	iowrite32(0x0, ccp->io_regs + CMD5_REQID_CONFIG_OFFSET);
 }
 
 static void ccp5other_config(struct ccp_device *ccp)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dmaengine.c linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dmaengine.c
--- linux-libre-4.9-gnu/drivers/crypto/ccp/ccp-dmaengine.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/ccp/ccp-dmaengine.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,6 +63,7 @@ static void ccp_free_chan_resources(stru
 	ccp_free_desc_resources(chan->ccp, &chan->complete);
 	ccp_free_desc_resources(chan->ccp, &chan->active);
 	ccp_free_desc_resources(chan->ccp, &chan->pending);
+	ccp_free_desc_resources(chan->ccp, &chan->created);
 
 	spin_unlock_irqrestore(&chan->lock, flags);
 }
@@ -273,6 +274,7 @@ static dma_cookie_t ccp_tx_submit(struct
 	spin_lock_irqsave(&chan->lock, flags);
 
 	cookie = dma_cookie_assign(tx_desc);
+	list_del(&desc->entry);
 	list_add_tail(&desc->entry, &chan->pending);
 
 	spin_unlock_irqrestore(&chan->lock, flags);
@@ -426,7 +428,7 @@ static struct ccp_dma_desc *ccp_create_d
 
 	spin_lock_irqsave(&chan->lock, sflags);
 
-	list_add_tail(&desc->entry, &chan->pending);
+	list_add_tail(&desc->entry, &chan->created);
 
 	spin_unlock_irqrestore(&chan->lock, sflags);
 
@@ -610,6 +612,7 @@ static int ccp_terminate_all(struct dma_
 	/*TODO: Purge the complete list? */
 	ccp_free_desc_resources(chan->ccp, &chan->active);
 	ccp_free_desc_resources(chan->ccp, &chan->pending);
+	ccp_free_desc_resources(chan->ccp, &chan->created);
 
 	spin_unlock_irqrestore(&chan->lock, flags);
 
@@ -679,6 +682,7 @@ int ccp_dmaengine_register(struct ccp_de
 		chan->ccp = ccp;
 
 		spin_lock_init(&chan->lock);
+		INIT_LIST_HEAD(&chan->created);
 		INIT_LIST_HEAD(&chan->pending);
 		INIT_LIST_HEAD(&chan->active);
 		INIT_LIST_HEAD(&chan->complete);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_algo.c linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_algo.c
--- linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_algo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_algo.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,6 +54,12 @@
 #include <crypto/algapi.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
+#include <crypto/authenc.h>
+#include <crypto/internal/aead.h>
+#include <crypto/null.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/aead.h>
+#include <crypto/scatterwalk.h>
 #include <crypto/internal/hash.h>
 
 #include "t4fw_api.h"
@@ -62,6 +68,11 @@
 #include "chcr_algo.h"
 #include "chcr_crypto.h"
 
+static inline  struct chcr_aead_ctx *AEAD_CTX(struct chcr_context *ctx)
+{
+	return ctx->crypto_ctx->aeadctx;
+}
+
 static inline struct ablk_ctx *ABLK_CTX(struct chcr_context *ctx)
 {
 	return ctx->crypto_ctx->ablkctx;
@@ -72,6 +83,16 @@ static inline struct hmac_ctx *HMAC_CTX(
 	return ctx->crypto_ctx->hmacctx;
 }
 
+static inline struct chcr_gcm_ctx *GCM_CTX(struct chcr_aead_ctx *gctx)
+{
+	return gctx->ctx->gcm;
+}
+
+static inline struct chcr_authenc_ctx *AUTHENC_CTX(struct chcr_aead_ctx *gctx)
+{
+	return gctx->ctx->authenc;
+}
+
 static inline struct uld_ctx *ULD_CTX(struct chcr_context *ctx)
 {
 	return ctx->dev->u_ctx;
@@ -94,12 +115,37 @@ static inline unsigned int sgl_len(unsig
 	return (3 * n) / 2 + (n & 1) + 2;
 }
 
+static void chcr_verify_tag(struct aead_request *req, u8 *input, int *err)
+{
+	u8 temp[SHA512_DIGEST_SIZE];
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	int authsize = crypto_aead_authsize(tfm);
+	struct cpl_fw6_pld *fw6_pld;
+	int cmp = 0;
+
+	fw6_pld = (struct cpl_fw6_pld *)input;
+	if ((get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) ||
+	    (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_GCM)) {
+		cmp = memcmp(&fw6_pld->data[2], (fw6_pld + 1), authsize);
+	} else {
+
+		sg_pcopy_to_buffer(req->src, sg_nents(req->src), temp,
+				authsize, req->assoclen +
+				req->cryptlen - authsize);
+		cmp = memcmp(temp, (fw6_pld + 1), authsize);
+	}
+	if (cmp)
+		*err = -EBADMSG;
+	else
+		*err = 0;
+}
+
 /*
  *	chcr_handle_resp - Unmap the DMA buffers associated with the request
  *	@req: crypto request
  */
 int chcr_handle_resp(struct crypto_async_request *req, unsigned char *input,
-		     int error_status)
+			 int err)
 {
 	struct crypto_tfm *tfm = req->tfm;
 	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
@@ -109,17 +155,33 @@ int chcr_handle_resp(struct crypto_async
 	unsigned int digestsize, updated_digestsize;
 
 	switch (tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
+	case CRYPTO_ALG_TYPE_AEAD:
+		ctx_req.req.aead_req = (struct aead_request *)req;
+		ctx_req.ctx.reqctx = aead_request_ctx(ctx_req.req.aead_req);
+		dma_unmap_sg(&u_ctx->lldi.pdev->dev, ctx_req.ctx.reqctx->dst,
+			     ctx_req.ctx.reqctx->dst_nents, DMA_FROM_DEVICE);
+		if (ctx_req.ctx.reqctx->skb) {
+			kfree_skb(ctx_req.ctx.reqctx->skb);
+			ctx_req.ctx.reqctx->skb = NULL;
+		}
+		if (ctx_req.ctx.reqctx->verify == VERIFY_SW) {
+			chcr_verify_tag(ctx_req.req.aead_req, input,
+					&err);
+			ctx_req.ctx.reqctx->verify = VERIFY_HW;
+		}
+		break;
+
 	case CRYPTO_ALG_TYPE_BLKCIPHER:
 		ctx_req.req.ablk_req = (struct ablkcipher_request *)req;
 		ctx_req.ctx.ablk_ctx =
 			ablkcipher_request_ctx(ctx_req.req.ablk_req);
-		if (!error_status) {
+		if (!err) {
 			fw6_pld = (struct cpl_fw6_pld *)input;
 			memcpy(ctx_req.req.ablk_req->info, &fw6_pld->data[2],
 			       AES_BLOCK_SIZE);
 		}
 		dma_unmap_sg(&u_ctx->lldi.pdev->dev, ctx_req.req.ablk_req->dst,
-			     ABLK_CTX(ctx)->dst_nents, DMA_FROM_DEVICE);
+			     ctx_req.ctx.ablk_ctx->dst_nents, DMA_FROM_DEVICE);
 		if (ctx_req.ctx.ablk_ctx->skb) {
 			kfree_skb(ctx_req.ctx.ablk_ctx->skb);
 			ctx_req.ctx.ablk_ctx->skb = NULL;
@@ -138,8 +200,10 @@ int chcr_handle_resp(struct crypto_async
 			updated_digestsize = SHA256_DIGEST_SIZE;
 		else if (digestsize == SHA384_DIGEST_SIZE)
 			updated_digestsize = SHA512_DIGEST_SIZE;
-		if (ctx_req.ctx.ahash_ctx->skb)
+		if (ctx_req.ctx.ahash_ctx->skb) {
+			kfree_skb(ctx_req.ctx.ahash_ctx->skb);
 			ctx_req.ctx.ahash_ctx->skb = NULL;
+		}
 		if (ctx_req.ctx.ahash_ctx->result == 1) {
 			ctx_req.ctx.ahash_ctx->result = 0;
 			memcpy(ctx_req.req.ahash_req->result, input +
@@ -150,11 +214,9 @@ int chcr_handle_resp(struct crypto_async
 			       sizeof(struct cpl_fw6_pld),
 			       updated_digestsize);
 		}
-		kfree(ctx_req.ctx.ahash_ctx->dummy_payload_ptr);
-		ctx_req.ctx.ahash_ctx->dummy_payload_ptr = NULL;
 		break;
 	}
-	return 0;
+	return err;
 }
 
 /*
@@ -178,40 +240,81 @@ static inline unsigned int calc_tx_flits
 	return flits + sgl_len(cnt);
 }
 
-static struct shash_desc *chcr_alloc_shash(unsigned int ds)
+static inline void get_aes_decrypt_key(unsigned char *dec_key,
+				       const unsigned char *key,
+				       unsigned int keylength)
+{
+	u32 temp;
+	u32 w_ring[MAX_NK];
+	int i, j, k;
+	u8  nr, nk;
+
+	switch (keylength) {
+	case AES_KEYLENGTH_128BIT:
+		nk = KEYLENGTH_4BYTES;
+		nr = NUMBER_OF_ROUNDS_10;
+		break;
+	case AES_KEYLENGTH_192BIT:
+		nk = KEYLENGTH_6BYTES;
+		nr = NUMBER_OF_ROUNDS_12;
+		break;
+	case AES_KEYLENGTH_256BIT:
+		nk = KEYLENGTH_8BYTES;
+		nr = NUMBER_OF_ROUNDS_14;
+		break;
+	default:
+		return;
+	}
+	for (i = 0; i < nk; i++)
+		w_ring[i] = be32_to_cpu(*(u32 *)&key[4 * i]);
+
+	i = 0;
+	temp = w_ring[nk - 1];
+	while (i + nk < (nr + 1) * 4) {
+		if (!(i % nk)) {
+			/* RotWord(temp) */
+			temp = (temp << 8) | (temp >> 24);
+			temp = aes_ks_subword(temp);
+			temp ^= round_constant[i / nk];
+		} else if (nk == 8 && (i % 4 == 0)) {
+			temp = aes_ks_subword(temp);
+		}
+		w_ring[i % nk] ^= temp;
+		temp = w_ring[i % nk];
+		i++;
+	}
+	i--;
+	for (k = 0, j = i % nk; k < nk; k++) {
+		*((u32 *)dec_key + k) = htonl(w_ring[j]);
+		j--;
+		if (j < 0)
+			j += nk;
+	}
+}
+
+static struct crypto_shash *chcr_alloc_shash(unsigned int ds)
 {
 	struct crypto_shash *base_hash = NULL;
-	struct shash_desc *desc;
 
 	switch (ds) {
 	case SHA1_DIGEST_SIZE:
-		base_hash = crypto_alloc_shash("sha1-generic", 0, 0);
+		base_hash = crypto_alloc_shash("sha1", 0, 0);
 		break;
 	case SHA224_DIGEST_SIZE:
-		base_hash = crypto_alloc_shash("sha224-generic", 0, 0);
+		base_hash = crypto_alloc_shash("sha224", 0, 0);
 		break;
 	case SHA256_DIGEST_SIZE:
-		base_hash = crypto_alloc_shash("sha256-generic", 0, 0);
+		base_hash = crypto_alloc_shash("sha256", 0, 0);
 		break;
 	case SHA384_DIGEST_SIZE:
-		base_hash = crypto_alloc_shash("sha384-generic", 0, 0);
+		base_hash = crypto_alloc_shash("sha384", 0, 0);
 		break;
 	case SHA512_DIGEST_SIZE:
-		base_hash = crypto_alloc_shash("sha512-generic", 0, 0);
+		base_hash = crypto_alloc_shash("sha512", 0, 0);
 		break;
 	}
-	if (IS_ERR(base_hash)) {
-		pr_err("Can not allocate sha-generic algo.\n");
-		return (void *)base_hash;
-	}
 
-	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(base_hash),
-		       GFP_KERNEL);
-	if (!desc)
-		return ERR_PTR(-ENOMEM);
-	desc->tfm = base_hash;
-	desc->flags = crypto_shash_get_flags(base_hash);
-	return desc;
+	return base_hash;
 }
 
 static int chcr_compute_partial_hash(struct shash_desc *desc,
@@ -279,31 +382,18 @@ static inline int is_hmac(struct crypto_
 	struct chcr_alg_template *chcr_crypto_alg =
 		container_of(__crypto_ahash_alg(alg), struct chcr_alg_template,
 			     alg.hash);
-	if ((chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK) ==
-	    CRYPTO_ALG_SUB_TYPE_HASH_HMAC)
+	if (chcr_crypto_alg->type == CRYPTO_ALG_TYPE_HMAC)
 		return 1;
 	return 0;
 }
 
-static inline unsigned int ch_nents(struct scatterlist *sg,
-				    unsigned int *total_size)
-{
-	unsigned int nents;
-
-	for (nents = 0, *total_size = 0; sg; sg = sg_next(sg)) {
-		nents++;
-		*total_size += sg->length;
-	}
-	return nents;
-}
-
 static void write_phys_cpl(struct cpl_rx_phys_dsgl *phys_cpl,
 			   struct scatterlist *sg,
 			   struct phys_sge_parm *sg_param)
 {
 	struct phys_sge_pairs *to;
-	unsigned int out_buf_size = sg_param->obsize;
-	unsigned int nents = sg_param->nents, i, j, tot_len = 0;
+	int out_buf_size = sg_param->obsize;
+	unsigned int nents = sg_param->nents, i, j = 0;
 
 	phys_cpl->op_to_tid = htonl(CPL_RX_PHYS_DSGL_OPCODE_V(CPL_RX_PHYS_DSGL)
 				    | CPL_RX_PHYS_DSGL_ISRDMA_V(0));
@@ -321,25 +411,24 @@ static void write_phys_cpl(struct cpl_rx
 				       sizeof(struct cpl_rx_phys_dsgl));
 
 	for (i = 0; nents; to++) {
-		for (j = i; (nents && (j < (8 + i))); j++, nents--) {
-			to->len[j] = htons(sg->length);
+		for (j = 0; j < 8 && nents; j++, nents--) {
+			out_buf_size -= sg_dma_len(sg);
+			to->len[j] = htons(sg_dma_len(sg));
 			to->addr[j] = cpu_to_be64(sg_dma_address(sg));
-			if (out_buf_size) {
-				if (tot_len + sg_dma_len(sg) >= out_buf_size) {
-					to->len[j] = htons(out_buf_size -
-							   tot_len);
-					return;
-				}
-				tot_len += sg_dma_len(sg);
-			}
 			sg = sg_next(sg);
 		}
 	}
+	if (out_buf_size) {
+		j--;
+		to--;
+		to->len[j] = htons(ntohs(to->len[j]) + (out_buf_size));
+	}
 }
 
-static inline unsigned
-int map_writesg_phys_cpl(struct device *dev, struct cpl_rx_phys_dsgl *phys_cpl,
-			 struct scatterlist *sg, struct phys_sge_parm *sg_param)
+static inline int map_writesg_phys_cpl(struct device *dev,
+					struct cpl_rx_phys_dsgl *phys_cpl,
+					struct scatterlist *sg,
+					struct phys_sge_parm *sg_param)
 {
 	if (!sg || !sg_param->nents)
 		return 0;
@@ -353,6 +442,14 @@ int map_writesg_phys_cpl(struct device *
 	return 0;
 }
 
+static inline int get_aead_subtype(struct crypto_aead *aead)
+{
+	struct aead_alg *alg = crypto_aead_alg(aead);
+	struct chcr_alg_template *chcr_crypto_alg =
+		container_of(alg, struct chcr_alg_template, alg.aead);
+	return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK;
+}
+
 static inline int get_cryptoalg_subtype(struct crypto_tfm *tfm)
 {
 	struct crypto_alg *alg = tfm->__crt_alg;
@@ -362,8 +459,23 @@ static inline int get_cryptoalg_subtype(
 	return chcr_crypto_alg->type & CRYPTO_ALG_SUB_TYPE_MASK;
 }
 
+static inline void write_buffer_to_skb(struct sk_buff *skb,
+					unsigned int *frags,
+					char *bfr,
+					u8 bfr_len)
+{
+	skb->len += bfr_len;
+	skb->data_len += bfr_len;
+	skb->truesize += bfr_len;
+	get_page(virt_to_page(bfr));
+	skb_fill_page_desc(skb, *frags, virt_to_page(bfr),
+			   offset_in_page(bfr), bfr_len);
+	(*frags)++;
+}
+
+
 static inline void
-write_sg_data_page_desc(struct sk_buff *skb, unsigned int *frags,
+write_sg_to_skb(struct sk_buff *skb, unsigned int *frags,
 			struct scatterlist *sg, unsigned int count)
 {
 	struct page *spage;
@@ -372,8 +484,9 @@ write_sg_data_page_desc(struct sk_buff *
 	skb->len += count;
 	skb->data_len += count;
 	skb->truesize += count;
+
 	while (count > 0) {
-		if (sg && (!(sg->length)))
+		if (!sg || (!(sg->length)))
 			break;
 		spage = sg_page(sg);
 		get_page(spage);
@@ -389,29 +502,25 @@ static int generate_copy_rrkey(struct ab
 			       struct _key_ctx *key_ctx)
 {
 	if (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) {
-		get_aes_decrypt_key(key_ctx->key, ablkctx->key,
-				    ablkctx->enckey_len << 3);
-		memset(key_ctx->key + ablkctx->enckey_len, 0,
-		       CHCR_AES_MAX_KEY_LEN - ablkctx->enckey_len);
+		memcpy(key_ctx->key, ablkctx->rrkey, ablkctx->enckey_len);
 	} else {
 		memcpy(key_ctx->key,
 		       ablkctx->key + (ablkctx->enckey_len >> 1),
 		       ablkctx->enckey_len >> 1);
-		get_aes_decrypt_key(key_ctx->key + (ablkctx->enckey_len >> 1),
-				    ablkctx->key, ablkctx->enckey_len << 2);
+		memcpy(key_ctx->key + (ablkctx->enckey_len >> 1),
+		       ablkctx->rrkey, ablkctx->enckey_len >> 1);
 	}
 	return 0;
 }
 
 static inline void create_wreq(struct chcr_context *ctx,
-			       struct fw_crypto_lookaside_wr *wreq,
+			       struct chcr_wr *chcr_req,
 			       void *req, struct sk_buff *skb,
 			       int kctx_len, int hash_sz,
-			       unsigned int phys_dsgl)
+			       int is_iv,
+			       unsigned int sc_len)
 {
 	struct uld_ctx *u_ctx = ULD_CTX(ctx);
-	struct ulp_txpkt *ulptx = (struct ulp_txpkt *)(wreq + 1);
-	struct ulptx_idata *sc_imm = (struct ulptx_idata *)(ulptx + 1);
 	int iv_loc = IV_DSGL;
 	int qid = u_ctx->lldi.rxq_ids[ctx->tx_channel_id];
 	unsigned int immdatalen = 0, nr_frags = 0;
@@ -423,27 +532,27 @@ static inline void create_wreq(struct ch
 		nr_frags = skb_shinfo(skb)->nr_frags;
 	}
 
-	wreq->op_to_cctx_size = FILL_WR_OP_CCTX_SIZE(immdatalen,
-						     (kctx_len >> 4));
-	wreq->pld_size_hash_size =
+	chcr_req->wreq.op_to_cctx_size = FILL_WR_OP_CCTX_SIZE(immdatalen,
+				((sizeof(chcr_req->key_ctx) + kctx_len) >> 4));
+	chcr_req->wreq.pld_size_hash_size =
 		htonl(FW_CRYPTO_LOOKASIDE_WR_PLD_SIZE_V(sgl_lengths[nr_frags]) |
 		      FW_CRYPTO_LOOKASIDE_WR_HASH_SIZE_V(hash_sz));
-	wreq->len16_pkd = htonl(FW_CRYPTO_LOOKASIDE_WR_LEN16_V(DIV_ROUND_UP(
+	chcr_req->wreq.len16_pkd =
+		htonl(FW_CRYPTO_LOOKASIDE_WR_LEN16_V(DIV_ROUND_UP(
 				    (calc_tx_flits_ofld(skb) * 8), 16)));
-	wreq->cookie = cpu_to_be64((uintptr_t)req);
-	wreq->rx_chid_to_rx_q_id =
+	chcr_req->wreq.cookie = cpu_to_be64((uintptr_t)req);
+	chcr_req->wreq.rx_chid_to_rx_q_id =
 		FILL_WR_RX_Q_ID(ctx->dev->tx_channel_id, qid,
-				(hash_sz) ? IV_NOP : iv_loc);
+				is_iv ? iv_loc : IV_NOP);
 
-	ulptx->cmd_dest = FILL_ULPTX_CMD_DEST(ctx->dev->tx_channel_id);
-	ulptx->len = htonl((DIV_ROUND_UP((calc_tx_flits_ofld(skb) * 8),
-					 16) - ((sizeof(*wreq)) >> 4)));
+	chcr_req->ulptx.cmd_dest = FILL_ULPTX_CMD_DEST(ctx->dev->tx_channel_id);
+	chcr_req->ulptx.len = htonl((DIV_ROUND_UP((calc_tx_flits_ofld(skb) * 8),
+					16) - ((sizeof(chcr_req->wreq)) >> 4)));
 
-	sc_imm->cmd_more = FILL_CMD_MORE(immdatalen);
-	sc_imm->len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) + kctx_len +
-				  ((hash_sz) ? DUMMY_BYTES :
-				  (sizeof(struct cpl_rx_phys_dsgl) +
-				   phys_dsgl)) + immdatalen);
+	chcr_req->sc_imm.cmd_more = FILL_CMD_MORE(immdatalen);
+	chcr_req->sc_imm.len = cpu_to_be32(sizeof(struct cpl_tx_sec_pdu) +
+				   sizeof(chcr_req->key_ctx) +
+				   kctx_len + sc_len + immdatalen);
 }
 
 /**
@@ -454,86 +563,83 @@ static inline void create_wreq(struct ch
  *	@op_type:	encryption or decryption
  */
 static struct sk_buff
-*create_cipher_wr(struct crypto_async_request *req_base,
-		  struct chcr_context *ctx, unsigned short qid,
+*create_cipher_wr(struct ablkcipher_request *req,
+		  unsigned short qid,
 		  unsigned short op_type)
 {
-	struct ablkcipher_request *req = (struct ablkcipher_request *)req_base;
 	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	struct chcr_context *ctx = crypto_ablkcipher_ctx(tfm);
 	struct uld_ctx *u_ctx = ULD_CTX(ctx);
 	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
 	struct sk_buff *skb = NULL;
-	struct _key_ctx *key_ctx;
-	struct fw_crypto_lookaside_wr *wreq;
-	struct cpl_tx_sec_pdu *sec_cpl;
+	struct chcr_wr *chcr_req;
 	struct cpl_rx_phys_dsgl *phys_cpl;
-	struct chcr_blkcipher_req_ctx *req_ctx = ablkcipher_request_ctx(req);
+	struct chcr_blkcipher_req_ctx *reqctx = ablkcipher_request_ctx(req);
 	struct phys_sge_parm sg_param;
-	unsigned int frags = 0, transhdr_len, phys_dsgl, dst_bufsize = 0;
+	unsigned int frags = 0, transhdr_len, phys_dsgl;
 	unsigned int ivsize = crypto_ablkcipher_ivsize(tfm), kctx_len;
+	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+			GFP_ATOMIC;
 
 	if (!req->info)
 		return ERR_PTR(-EINVAL);
-	ablkctx->dst_nents = ch_nents(req->dst, &dst_bufsize);
-	ablkctx->enc = op_type;
-
+	reqctx->dst_nents = sg_nents_for_len(req->dst, req->nbytes);
+	if (reqctx->dst_nents <= 0) {
+		pr_err("AES:Invalid Destination sg lists\n");
+		return ERR_PTR(-EINVAL);
+	}
 	if ((ablkctx->enckey_len == 0) || (ivsize > AES_BLOCK_SIZE) ||
-	    (req->nbytes <= 0) || (req->nbytes % AES_BLOCK_SIZE))
+	    (req->nbytes <= 0) || (req->nbytes % AES_BLOCK_SIZE)) {
+		pr_err("AES: Invalid value of Key Len %d nbytes %d IV Len %d\n",
+		       ablkctx->enckey_len, req->nbytes, ivsize);
 		return ERR_PTR(-EINVAL);
+	}
 
-	phys_dsgl = get_space_for_phys_dsgl(ablkctx->dst_nents);
+	phys_dsgl = get_space_for_phys_dsgl(reqctx->dst_nents);
 
-	kctx_len = sizeof(*key_ctx) +
-		(DIV_ROUND_UP(ablkctx->enckey_len, 16) * 16);
+	kctx_len = (DIV_ROUND_UP(ablkctx->enckey_len, 16) * 16);
 	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, phys_dsgl);
-	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)),
-			GFP_ATOMIC);
+	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)), flags);
 	if (!skb)
 		return ERR_PTR(-ENOMEM);
 	skb_reserve(skb, sizeof(struct sge_opaque_hdr));
-	wreq = (struct fw_crypto_lookaside_wr *)__skb_put(skb, transhdr_len);
-
-	sec_cpl = (struct cpl_tx_sec_pdu *)((u8 *)wreq + SEC_CPL_OFFSET);
-	sec_cpl->op_ivinsrtofst =
-		FILL_SEC_CPL_OP_IVINSR(ctx->dev->tx_channel_id, 2, 1, 1);
+	chcr_req = (struct chcr_wr *)__skb_put(skb, transhdr_len);
+	memset(chcr_req, 0, transhdr_len);
+	chcr_req->sec_cpl.op_ivinsrtofst =
+		FILL_SEC_CPL_OP_IVINSR(ctx->dev->tx_channel_id, 2, 1);
 
-	sec_cpl->pldlen = htonl(ivsize + req->nbytes);
-	sec_cpl->aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(0, 0,
-								ivsize + 1, 0);
+	chcr_req->sec_cpl.pldlen = htonl(ivsize + req->nbytes);
+	chcr_req->sec_cpl.aadstart_cipherstop_hi =
+			FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, ivsize + 1, 0);
 
-	sec_cpl->cipherstop_lo_authinsert =  FILL_SEC_CPL_AUTHINSERT(0, 0,
-								     0, 0);
-	sec_cpl->seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(op_type, 0,
+	chcr_req->sec_cpl.cipherstop_lo_authinsert =
+			FILL_SEC_CPL_AUTHINSERT(0, 0, 0, 0);
+	chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(op_type, 0,
 							 ablkctx->ciph_mode,
-							 0, 0, ivsize >> 1, 1);
-	sec_cpl->ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 0,
+							 0, 0, ivsize >> 1);
+	chcr_req->sec_cpl.ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 0,
 							  0, 1, phys_dsgl);
 
-	key_ctx = (struct _key_ctx *)((u8 *)sec_cpl + sizeof(*sec_cpl));
-	key_ctx->ctx_hdr = ablkctx->key_ctx_hdr;
+	chcr_req->key_ctx.ctx_hdr = ablkctx->key_ctx_hdr;
 	if (op_type == CHCR_DECRYPT_OP) {
-		if (generate_copy_rrkey(ablkctx, key_ctx))
-			goto map_fail1;
+		generate_copy_rrkey(ablkctx, &chcr_req->key_ctx);
 	} else {
 		if (ablkctx->ciph_mode == CHCR_SCMD_CIPHER_MODE_AES_CBC) {
-			memcpy(key_ctx->key, ablkctx->key, ablkctx->enckey_len);
+			memcpy(chcr_req->key_ctx.key, ablkctx->key,
+			       ablkctx->enckey_len);
 		} else {
-			memcpy(key_ctx->key, ablkctx->key +
+			memcpy(chcr_req->key_ctx.key, ablkctx->key +
 			       (ablkctx->enckey_len >> 1),
 			       ablkctx->enckey_len >> 1);
-			memcpy(key_ctx->key +
+			memcpy(chcr_req->key_ctx.key +
 			       (ablkctx->enckey_len >> 1),
 			       ablkctx->key,
 			       ablkctx->enckey_len >> 1);
 		}
 	}
-	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)key_ctx + kctx_len);
-
-	memcpy(ablkctx->iv, req->info, ivsize);
-	sg_init_table(&ablkctx->iv_sg, 1);
-	sg_set_buf(&ablkctx->iv_sg, ablkctx->iv, ivsize);
-	sg_param.nents = ablkctx->dst_nents;
-	sg_param.obsize = dst_bufsize;
+	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
+	sg_param.nents = reqctx->dst_nents;
+	sg_param.obsize = req->nbytes;
 	sg_param.qid = qid;
 	sg_param.align = 1;
 	if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, req->dst,
@@ -541,10 +647,12 @@ static struct sk_buff
 		goto map_fail1;
 
 	skb_set_transport_header(skb, transhdr_len);
-	write_sg_data_page_desc(skb, &frags, &ablkctx->iv_sg, ivsize);
-	write_sg_data_page_desc(skb, &frags, req->src, req->nbytes);
-	create_wreq(ctx, wreq, req, skb, kctx_len, 0, phys_dsgl);
-	req_ctx->skb = skb;
+	memcpy(reqctx->iv, req->info, ivsize);
+	write_buffer_to_skb(skb, &frags, reqctx->iv, ivsize);
+	write_sg_to_skb(skb, &frags, req->src, req->nbytes);
+	create_wreq(ctx, chcr_req, req, skb, kctx_len, 0, 1,
+			sizeof(struct cpl_rx_phys_dsgl) + phys_dsgl);
+	reqctx->skb = skb;
 	skb_get(skb);
 	return skb;
 map_fail1:
@@ -557,15 +665,9 @@ static int chcr_aes_cbc_setkey(struct cr
 {
 	struct chcr_context *ctx = crypto_ablkcipher_ctx(tfm);
 	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
-	struct ablkcipher_alg *alg = crypto_ablkcipher_alg(tfm);
 	unsigned int ck_size, context_size;
 	u16 alignment = 0;
 
-	if ((keylen < alg->min_keysize) || (keylen > alg->max_keysize))
-		goto badkey_err;
-
-	memcpy(ablkctx->key, key, keylen);
-	ablkctx->enckey_len = keylen;
 	if (keylen == AES_KEYSIZE_128) {
 		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
 	} else if (keylen == AES_KEYSIZE_192) {
@@ -576,7 +678,9 @@ static int chcr_aes_cbc_setkey(struct cr
 	} else {
 		goto badkey_err;
 	}
-
+	memcpy(ablkctx->key, key, keylen);
+	ablkctx->enckey_len = keylen;
+	get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, keylen << 3);
 	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD +
 			keylen + alignment) >> 4;
 
@@ -592,16 +696,18 @@ badkey_err:
 
 static int cxgb4_is_crypto_q_full(struct net_device *dev, unsigned int idx)
 {
-	int ret = 0;
-	struct sge_ofld_txq *q;
 	struct adapter *adap = netdev2adap(dev);
+	struct sge_uld_txq_info *txq_info =
+		adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
+	struct sge_uld_txq *txq;
+	int ret = 0;
 
 	local_bh_disable();
-	q = &adap->sge.ofldtxq[idx];
-	spin_lock(&q->sendq.lock);
-	if (q->full)
+	txq = &txq_info->uldtxq[idx];
+	spin_lock(&txq->sendq.lock);
+	if (txq->full)
 		ret = -1;
-	spin_unlock(&q->sendq.lock);
+	spin_unlock(&txq->sendq.lock);
 	local_bh_enable();
 	return ret;
 }
@@ -610,7 +716,6 @@ static int chcr_aes_encrypt(struct ablkc
 {
 	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
 	struct chcr_context *ctx = crypto_ablkcipher_ctx(tfm);
-	struct crypto_async_request *req_base = &req->base;
 	struct uld_ctx *u_ctx = ULD_CTX(ctx);
 	struct sk_buff *skb;
 
@@ -620,8 +725,7 @@ static int chcr_aes_encrypt(struct ablkc
 			return -EBUSY;
 	}
 
-	skb = create_cipher_wr(req_base, ctx,
-			       u_ctx->lldi.rxq_ids[ctx->tx_channel_id],
+	skb = create_cipher_wr(req, u_ctx->lldi.rxq_ids[ctx->tx_channel_id],
 			       CHCR_ENCRYPT_OP);
 	if (IS_ERR(skb)) {
 		pr_err("chcr : %s : Failed to form WR. No memory\n", __func__);
@@ -637,7 +741,6 @@ static int chcr_aes_decrypt(struct ablkc
 {
 	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
 	struct chcr_context *ctx = crypto_ablkcipher_ctx(tfm);
-	struct crypto_async_request *req_base = &req->base;
 	struct uld_ctx *u_ctx = ULD_CTX(ctx);
 	struct sk_buff *skb;
 
@@ -647,7 +750,7 @@ static int chcr_aes_decrypt(struct ablkc
 			return -EBUSY;
 	}
 
-	skb = create_cipher_wr(req_base, ctx, u_ctx->lldi.rxq_ids[0],
+	skb = create_cipher_wr(req, u_ctx->lldi.rxq_ids[0],
 			       CHCR_DECRYPT_OP);
 	if (IS_ERR(skb)) {
 		pr_err("chcr : %s : Failed to form WR. No memory\n", __func__);
@@ -674,11 +777,11 @@ static int chcr_device_init(struct chcr_
 		}
 		u_ctx = ULD_CTX(ctx);
 		rxq_perchan = u_ctx->lldi.nrxq / u_ctx->lldi.nchan;
-		ctx->dev->tx_channel_id = 0;
 		rxq_idx = ctx->dev->tx_channel_id * rxq_perchan;
 		rxq_idx += id % rxq_perchan;
 		spin_lock(&ctx->dev->lock_chcr_dev);
 		ctx->tx_channel_id = rxq_idx;
+		ctx->dev->tx_channel_id = !ctx->dev->tx_channel_id;
 		spin_unlock(&ctx->dev->lock_chcr_dev);
 	}
 out:
@@ -727,50 +830,33 @@ static int get_alg_config(struct algo_pa
 	return 0;
 }
 
-static inline int
-write_buffer_data_page_desc(struct chcr_ahash_req_ctx *req_ctx,
-			    struct sk_buff *skb, unsigned int *frags, char *bfr,
-			    u8 bfr_len)
+static inline void chcr_free_shash(struct crypto_shash *base_hash)
 {
-	void *page_ptr = NULL;
-
-	skb->len += bfr_len;
-	skb->data_len += bfr_len;
-	skb->truesize += bfr_len;
-	page_ptr = kmalloc(CHCR_HASH_MAX_BLOCK_SIZE_128, GFP_ATOMIC | GFP_DMA);
-	if (!page_ptr)
-		return -ENOMEM;
-	get_page(virt_to_page(page_ptr));
-	req_ctx->dummy_payload_ptr = page_ptr;
-	memcpy(page_ptr, bfr, bfr_len);
-	skb_fill_page_desc(skb, *frags, virt_to_page(page_ptr),
-			   offset_in_page(page_ptr), bfr_len);
-	(*frags)++;
-	return 0;
+		crypto_free_shash(base_hash);
 }
 
 /**
- *	create_final_hash_wr - Create hash work request
+ *	create_hash_wr - Create hash work request
  *	@req - Cipher req base
  */
-static struct sk_buff *create_final_hash_wr(struct ahash_request *req,
-					    struct hash_wr_param *param)
+static struct sk_buff *create_hash_wr(struct ahash_request *req,
+				      struct hash_wr_param *param)
 {
 	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(req);
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
 	struct chcr_context *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
 	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
 	struct sk_buff *skb = NULL;
-	struct _key_ctx *key_ctx;
-	struct fw_crypto_lookaside_wr *wreq;
-	struct cpl_tx_sec_pdu *sec_cpl;
+	struct chcr_wr *chcr_req;
 	unsigned int frags = 0, transhdr_len, iopad_alignment = 0;
 	unsigned int digestsize = crypto_ahash_digestsize(tfm);
-	unsigned int kctx_len = sizeof(*key_ctx);
+	unsigned int kctx_len = 0;
 	u8 hash_size_in_response = 0;
+	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+		GFP_ATOMIC;
 
 	iopad_alignment = KEYCTX_ALIGN_PAD(digestsize);
-	kctx_len += param->alg_prm.result_size + iopad_alignment;
+	kctx_len = param->alg_prm.result_size + iopad_alignment;
 	if (param->opad_needed)
 		kctx_len += param->alg_prm.result_size + iopad_alignment;
 
@@ -779,54 +865,54 @@ static struct sk_buff *create_final_hash
 	else
 		hash_size_in_response = param->alg_prm.result_size;
 	transhdr_len = HASH_TRANSHDR_SIZE(kctx_len);
-	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)),
-			GFP_ATOMIC);
+	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)), flags);
 	if (!skb)
 		return skb;
 
 	skb_reserve(skb, sizeof(struct sge_opaque_hdr));
-	wreq = (struct fw_crypto_lookaside_wr *)__skb_put(skb, transhdr_len);
-	memset(wreq, 0, transhdr_len);
+	chcr_req = (struct chcr_wr *)__skb_put(skb, transhdr_len);
+	memset(chcr_req, 0, transhdr_len);
 
-	sec_cpl = (struct cpl_tx_sec_pdu *)((u8 *)wreq + SEC_CPL_OFFSET);
-	sec_cpl->op_ivinsrtofst =
-		FILL_SEC_CPL_OP_IVINSR(ctx->dev->tx_channel_id, 2, 0, 0);
-	sec_cpl->pldlen = htonl(param->bfr_len + param->sg_len);
+	chcr_req->sec_cpl.op_ivinsrtofst =
+		FILL_SEC_CPL_OP_IVINSR(ctx->dev->tx_channel_id, 2, 0);
+	chcr_req->sec_cpl.pldlen = htonl(param->bfr_len + param->sg_len);
 
-	sec_cpl->aadstart_cipherstop_hi =
+	chcr_req->sec_cpl.aadstart_cipherstop_hi =
 		FILL_SEC_CPL_CIPHERSTOP_HI(0, 0, 0, 0);
-	sec_cpl->cipherstop_lo_authinsert =
+	chcr_req->sec_cpl.cipherstop_lo_authinsert =
 		FILL_SEC_CPL_AUTHINSERT(0, 1, 0, 0);
-	sec_cpl->seqno_numivs =
+	chcr_req->sec_cpl.seqno_numivs =
 		FILL_SEC_CPL_SCMD0_SEQNO(0, 0, 0, param->alg_prm.auth_mode,
-					 param->opad_needed, 0, 0);
+					 param->opad_needed, 0);
 
-	sec_cpl->ivgen_hdrlen =
+	chcr_req->sec_cpl.ivgen_hdrlen =
 		FILL_SEC_CPL_IVGEN_HDRLEN(param->last, param->more, 0, 1, 0, 0);
 
-	key_ctx = (struct _key_ctx *)((u8 *)sec_cpl + sizeof(*sec_cpl));
-	memcpy(key_ctx->key, req_ctx->partial_hash, param->alg_prm.result_size);
+	memcpy(chcr_req->key_ctx.key, req_ctx->partial_hash,
+	       param->alg_prm.result_size);
 
 	if (param->opad_needed)
-		memcpy(key_ctx->key + ((param->alg_prm.result_size <= 32) ? 32 :
-				       CHCR_HASH_MAX_DIGEST_SIZE),
+		memcpy(chcr_req->key_ctx.key +
+		       ((param->alg_prm.result_size <= 32) ? 32 :
+			CHCR_HASH_MAX_DIGEST_SIZE),
 		       hmacctx->opad, param->alg_prm.result_size);
 
-	key_ctx->ctx_hdr = FILL_KEY_CTX_HDR(CHCR_KEYCTX_NO_KEY,
+	chcr_req->key_ctx.ctx_hdr = FILL_KEY_CTX_HDR(CHCR_KEYCTX_NO_KEY,
 					    param->alg_prm.mk_size, 0,
 					    param->opad_needed,
-					    (kctx_len >> 4));
-	sec_cpl->scmd1 = cpu_to_be64((u64)param->scmd1);
+					    ((kctx_len +
+					     sizeof(chcr_req->key_ctx)) >> 4));
+	chcr_req->sec_cpl.scmd1 = cpu_to_be64((u64)param->scmd1);
 
 	skb_set_transport_header(skb, transhdr_len);
 	if (param->bfr_len != 0)
-		write_buffer_data_page_desc(req_ctx, skb, &frags, req_ctx->bfr,
-					    param->bfr_len);
+		write_buffer_to_skb(skb, &frags, req_ctx->reqbfr,
+				    param->bfr_len);
 	if (param->sg_len != 0)
-		write_sg_data_page_desc(skb, &frags, req->src, param->sg_len);
+		write_sg_to_skb(skb, &frags, req->src, param->sg_len);
 
-	create_wreq(ctx, wreq, req, skb, kctx_len, hash_size_in_response,
-		    0);
+	create_wreq(ctx, chcr_req, req, skb, kctx_len, hash_size_in_response, 0,
+			DUMMY_BYTES);
 	req_ctx->skb = skb;
 	skb_get(skb);
 	return skb;
@@ -852,34 +938,40 @@ static int chcr_ahash_update(struct ahas
 			return -EBUSY;
 	}
 
-	if (nbytes + req_ctx->bfr_len >= bs) {
-		remainder = (nbytes + req_ctx->bfr_len) % bs;
-		nbytes = nbytes + req_ctx->bfr_len - remainder;
+	if (nbytes + req_ctx->reqlen >= bs) {
+		remainder = (nbytes + req_ctx->reqlen) % bs;
+		nbytes = nbytes + req_ctx->reqlen - remainder;
 	} else {
-		sg_pcopy_to_buffer(req->src, sg_nents(req->src), req_ctx->bfr +
-				   req_ctx->bfr_len, nbytes, 0);
-		req_ctx->bfr_len += nbytes;
+		sg_pcopy_to_buffer(req->src, sg_nents(req->src), req_ctx->reqbfr
+				   + req_ctx->reqlen, nbytes, 0);
+		req_ctx->reqlen += nbytes;
 		return 0;
 	}
 
 	params.opad_needed = 0;
 	params.more = 1;
 	params.last = 0;
-	params.sg_len = nbytes - req_ctx->bfr_len;
-	params.bfr_len = req_ctx->bfr_len;
+	params.sg_len = nbytes - req_ctx->reqlen;
+	params.bfr_len = req_ctx->reqlen;
 	params.scmd1 = 0;
 	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
 	req_ctx->result = 0;
 	req_ctx->data_len += params.sg_len + params.bfr_len;
-	skb = create_final_hash_wr(req, &params);
+	skb = create_hash_wr(req, &params);
 	if (!skb)
 		return -ENOMEM;
 
-	req_ctx->bfr_len = remainder;
-	if (remainder)
+	if (remainder) {
+		u8 *temp;
+		/* Swap buffers */
+		temp = req_ctx->reqbfr;
+		req_ctx->reqbfr = req_ctx->skbfr;
+		req_ctx->skbfr = temp;
 		sg_pcopy_to_buffer(req->src, sg_nents(req->src),
-				   req_ctx->bfr, remainder, req->nbytes -
+				   req_ctx->reqbfr, remainder, req->nbytes -
 				   remainder);
+	}
+	req_ctx->reqlen = remainder;
 	skb->dev = u_ctx->lldi.ports[0];
 	set_wr_txq(skb, CPL_PRIORITY_DATA, ctx->tx_channel_id);
 	chcr_send_wr(skb);
@@ -915,10 +1007,10 @@ static int chcr_ahash_final(struct ahash
 	params.sg_len = 0;
 	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
 	req_ctx->result = 1;
-	params.bfr_len = req_ctx->bfr_len;
+	params.bfr_len = req_ctx->reqlen;
 	req_ctx->data_len += params.bfr_len + params.sg_len;
-	if (req_ctx->bfr && (req_ctx->bfr_len == 0)) {
-		create_last_hash_block(req_ctx->bfr, bs, req_ctx->data_len);
+	if (req_ctx->reqlen == 0) {
+		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
 		params.last = 0;
 		params.more = 1;
 		params.scmd1 = 0;
@@ -929,7 +1021,10 @@ static int chcr_ahash_final(struct ahash
 		params.last = 1;
 		params.more = 0;
 	}
-	skb = create_final_hash_wr(req, &params);
+	skb = create_hash_wr(req, &params);
+	if (!skb)
+		return -ENOMEM;
+
 	skb->dev = u_ctx->lldi.ports[0];
 	set_wr_txq(skb, CPL_PRIORITY_DATA, ctx->tx_channel_id);
 	chcr_send_wr(skb);
@@ -961,12 +1056,12 @@ static int chcr_ahash_finup(struct ahash
 		params.opad_needed = 0;
 
 	params.sg_len = req->nbytes;
-	params.bfr_len = req_ctx->bfr_len;
+	params.bfr_len = req_ctx->reqlen;
 	get_alg_config(&params.alg_prm, crypto_ahash_digestsize(rtfm));
 	req_ctx->data_len += params.bfr_len + params.sg_len;
 	req_ctx->result = 1;
-	if (req_ctx->bfr && (req_ctx->bfr_len + req->nbytes) == 0) {
-		create_last_hash_block(req_ctx->bfr, bs, req_ctx->data_len);
+	if ((req_ctx->reqlen + req->nbytes) == 0) {
+		create_last_hash_block(req_ctx->reqbfr, bs, req_ctx->data_len);
 		params.last = 0;
 		params.more = 1;
 		params.scmd1 = 0;
@@ -977,9 +1072,10 @@ static int chcr_ahash_finup(struct ahash
 		params.more = 0;
 	}
 
-	skb = create_final_hash_wr(req, &params);
+	skb = create_hash_wr(req, &params);
 	if (!skb)
 		return -ENOMEM;
+
 	skb->dev = u_ctx->lldi.ports[0];
 	set_wr_txq(skb, CPL_PRIORITY_DATA, ctx->tx_channel_id);
 	chcr_send_wr(skb);
@@ -1021,13 +1117,13 @@ static int chcr_ahash_digest(struct ahas
 	req_ctx->result = 1;
 	req_ctx->data_len += params.bfr_len + params.sg_len;
 
-	if (req_ctx->bfr && req->nbytes == 0) {
-		create_last_hash_block(req_ctx->bfr, bs, 0);
+	if (req->nbytes == 0) {
+		create_last_hash_block(req_ctx->reqbfr, bs, 0);
 		params.more = 1;
 		params.bfr_len = bs;
 	}
 
-	skb = create_final_hash_wr(req, &params);
+	skb = create_hash_wr(req, &params);
 	if (!skb)
 		return -ENOMEM;
 
@@ -1042,12 +1138,12 @@ static int chcr_ahash_export(struct ahas
 	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
 	struct chcr_ahash_req_ctx *state = out;
 
-	state->bfr_len = req_ctx->bfr_len;
+	state->reqlen = req_ctx->reqlen;
 	state->data_len = req_ctx->data_len;
-	memcpy(state->bfr, req_ctx->bfr, CHCR_HASH_MAX_BLOCK_SIZE_128);
+	memcpy(state->bfr1, req_ctx->reqbfr, req_ctx->reqlen);
 	memcpy(state->partial_hash, req_ctx->partial_hash,
 	       CHCR_HASH_MAX_DIGEST_SIZE);
-	return 0;
+		return 0;
 }
 
 static int chcr_ahash_import(struct ahash_request *areq, const void *in)
@@ -1055,10 +1151,11 @@ static int chcr_ahash_import(struct ahas
 	struct chcr_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
 	struct chcr_ahash_req_ctx *state = (struct chcr_ahash_req_ctx *)in;
 
-	req_ctx->bfr_len = state->bfr_len;
+	req_ctx->reqlen = state->reqlen;
 	req_ctx->data_len = state->data_len;
-	req_ctx->dummy_payload_ptr = NULL;
-	memcpy(req_ctx->bfr, state->bfr, CHCR_HASH_MAX_BLOCK_SIZE_128);
+	req_ctx->reqbfr = req_ctx->bfr1;
+	req_ctx->skbfr = req_ctx->bfr2;
+	memcpy(req_ctx->bfr1, state->bfr1, CHCR_HASH_MAX_BLOCK_SIZE_128);
 	memcpy(req_ctx->partial_hash, state->partial_hash,
 	       CHCR_HASH_MAX_DIGEST_SIZE);
 	return 0;
@@ -1073,15 +1170,16 @@ static int chcr_ahash_setkey(struct cryp
 	unsigned int bs = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
 	unsigned int i, err = 0, updated_digestsize;
 
-	/*
-	 * use the key to calculate the ipad and opad. ipad will sent with the
+	SHASH_DESC_ON_STACK(shash, hmacctx->base_hash);
+
+	/* use the key to calculate the ipad and opad. ipad will sent with the
 	 * first request's data. opad will be sent with the final hash result
 	 * ipad in hmacctx->ipad and opad in hmacctx->opad location
 	 */
-	if (!hmacctx->desc)
-		return -EINVAL;
+	shash->tfm = hmacctx->base_hash;
+	shash->flags = crypto_shash_get_flags(hmacctx->base_hash);
 	if (keylen > bs) {
-		err = crypto_shash_digest(hmacctx->desc, key, keylen,
+		err = crypto_shash_digest(shash, key, keylen,
 					  hmacctx->ipad);
 		if (err)
 			goto out;
@@ -1102,13 +1200,13 @@ static int chcr_ahash_setkey(struct cryp
 		updated_digestsize = SHA256_DIGEST_SIZE;
 	else if (digestsize == SHA384_DIGEST_SIZE)
 		updated_digestsize = SHA512_DIGEST_SIZE;
-	err = chcr_compute_partial_hash(hmacctx->desc, hmacctx->ipad,
+	err = chcr_compute_partial_hash(shash, hmacctx->ipad,
 					hmacctx->ipad, digestsize);
 	if (err)
 		goto out;
 	chcr_change_order(hmacctx->ipad, updated_digestsize);
 
-	err = chcr_compute_partial_hash(hmacctx->desc, hmacctx->opad,
+	err = chcr_compute_partial_hash(shash, hmacctx->opad,
 					hmacctx->opad, digestsize);
 	if (err)
 		goto out;
@@ -1122,28 +1220,29 @@ static int chcr_aes_xts_setkey(struct cr
 {
 	struct chcr_context *ctx = crypto_ablkcipher_ctx(tfm);
 	struct ablk_ctx *ablkctx = ABLK_CTX(ctx);
-	int status = 0;
 	unsigned short context_size = 0;
 
-	if ((key_len == (AES_KEYSIZE_128 << 1)) ||
-	    (key_len == (AES_KEYSIZE_256 << 1))) {
-		memcpy(ablkctx->key, key, key_len);
-		ablkctx->enckey_len = key_len;
-		context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len) >> 4;
-		ablkctx->key_ctx_hdr =
-			FILL_KEY_CTX_HDR((key_len == AES_KEYSIZE_256) ?
-					 CHCR_KEYCTX_CIPHER_KEY_SIZE_128 :
-					 CHCR_KEYCTX_CIPHER_KEY_SIZE_256,
-					 CHCR_KEYCTX_NO_KEY, 1,
-					 0, context_size);
-		ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_XTS;
-	} else {
+	if ((key_len != (AES_KEYSIZE_128 << 1)) &&
+	    (key_len != (AES_KEYSIZE_256 << 1))) {
 		crypto_tfm_set_flags((struct crypto_tfm *)tfm,
 				     CRYPTO_TFM_RES_BAD_KEY_LEN);
 		ablkctx->enckey_len = 0;
-		status = -EINVAL;
+		return -EINVAL;
+
 	}
-	return status;
+
+	memcpy(ablkctx->key, key, key_len);
+	ablkctx->enckey_len = key_len;
+	get_aes_decrypt_key(ablkctx->rrkey, ablkctx->key, key_len << 2);
+	context_size = (KEY_CONTEXT_HDR_SALT_AND_PAD + key_len) >> 4;
+	ablkctx->key_ctx_hdr =
+		FILL_KEY_CTX_HDR((key_len == AES_KEYSIZE_256) ?
+				 CHCR_KEYCTX_CIPHER_KEY_SIZE_128 :
+				 CHCR_KEYCTX_CIPHER_KEY_SIZE_256,
+				 CHCR_KEYCTX_NO_KEY, 1,
+				 0, context_size);
+	ablkctx->ciph_mode = CHCR_SCMD_CIPHER_MODE_AES_XTS;
+	return 0;
 }
 
 static int chcr_sha_init(struct ahash_request *areq)
@@ -1153,8 +1252,9 @@ static int chcr_sha_init(struct ahash_re
 	int digestsize =  crypto_ahash_digestsize(tfm);
 
 	req_ctx->data_len = 0;
-	req_ctx->dummy_payload_ptr = NULL;
-	req_ctx->bfr_len = 0;
+	req_ctx->reqlen = 0;
+	req_ctx->reqbfr = req_ctx->bfr1;
+	req_ctx->skbfr = req_ctx->bfr2;
 	req_ctx->skb = NULL;
 	req_ctx->result = 0;
 	copy_hash_init_values(req_ctx->partial_hash, digestsize);
@@ -1202,29 +1302,1187 @@ static int chcr_hmac_cra_init(struct cry
 
 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
 				 sizeof(struct chcr_ahash_req_ctx));
-	hmacctx->desc = chcr_alloc_shash(digestsize);
-	if (IS_ERR(hmacctx->desc))
-		return PTR_ERR(hmacctx->desc);
+	hmacctx->base_hash = chcr_alloc_shash(digestsize);
+	if (IS_ERR(hmacctx->base_hash))
+		return PTR_ERR(hmacctx->base_hash);
 	return chcr_device_init(crypto_tfm_ctx(tfm));
 }
 
-static void chcr_free_shash(struct shash_desc *desc)
-{
-	crypto_free_shash(desc->tfm);
-	kfree(desc);
-}
-
 static void chcr_hmac_cra_exit(struct crypto_tfm *tfm)
 {
 	struct chcr_context *ctx = crypto_tfm_ctx(tfm);
 	struct hmac_ctx *hmacctx = HMAC_CTX(ctx);
 
-	if (hmacctx->desc) {
-		chcr_free_shash(hmacctx->desc);
-		hmacctx->desc = NULL;
+	if (hmacctx->base_hash) {
+		chcr_free_shash(hmacctx->base_hash);
+		hmacctx->base_hash = NULL;
+	}
+}
+
+static int chcr_copy_assoc(struct aead_request *req,
+				struct chcr_aead_ctx *ctx)
+{
+	SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null);
+
+	skcipher_request_set_tfm(skreq, ctx->null);
+	skcipher_request_set_callback(skreq, aead_request_flags(req),
+			NULL, NULL);
+	skcipher_request_set_crypt(skreq, req->src, req->dst, req->assoclen,
+			NULL);
+
+	return crypto_skcipher_encrypt(skreq);
+}
+
+static unsigned char get_hmac(unsigned int authsize)
+{
+	switch (authsize) {
+	case ICV_8:
+		return CHCR_SCMD_HMAC_CTRL_PL1;
+	case ICV_10:
+		return CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
+	case ICV_12:
+		return CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
+	}
+	return CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
+}
+
+
+static struct sk_buff *create_authenc_wr(struct aead_request *req,
+					 unsigned short qid,
+					 int size,
+					 unsigned short op_type)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct chcr_context *ctx = crypto_aead_ctx(tfm);
+	struct uld_ctx *u_ctx = ULD_CTX(ctx);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
+	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
+	struct sk_buff *skb = NULL;
+	struct chcr_wr *chcr_req;
+	struct cpl_rx_phys_dsgl *phys_cpl;
+	struct phys_sge_parm sg_param;
+	struct scatterlist *src;
+	unsigned int frags = 0, transhdr_len;
+	unsigned int ivsize = crypto_aead_ivsize(tfm), dst_size = 0;
+	unsigned int   kctx_len = 0;
+	unsigned short stop_offset = 0;
+	unsigned int  assoclen = req->assoclen;
+	unsigned int  authsize = crypto_aead_authsize(tfm);
+	int err = 0;
+	int null = 0;
+	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+		GFP_ATOMIC;
+
+	if (aeadctx->enckey_len == 0 || (req->cryptlen == 0))
+		goto err;
+
+	if (op_type && req->cryptlen < crypto_aead_authsize(tfm))
+		goto err;
+
+	if (sg_nents_for_len(req->src, req->assoclen + req->cryptlen) < 0)
+		goto err;
+	src = scatterwalk_ffwd(reqctx->srcffwd, req->src, req->assoclen);
+	reqctx->dst = src;
+
+	if (req->src != req->dst) {
+		err = chcr_copy_assoc(req, aeadctx);
+		if (err)
+			return ERR_PTR(err);
+		reqctx->dst = scatterwalk_ffwd(reqctx->dstffwd, req->dst,
+					       req->assoclen);
+	}
+	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_NULL) {
+		null = 1;
+		assoclen = 0;
+	}
+	reqctx->dst_nents = sg_nents_for_len(reqctx->dst, req->cryptlen +
+					     (op_type ? -authsize : authsize));
+	if (reqctx->dst_nents <= 0) {
+		pr_err("AUTHENC:Invalid Destination sg entries\n");
+		goto err;
+	}
+	dst_size = get_space_for_phys_dsgl(reqctx->dst_nents);
+	kctx_len = (ntohl(KEY_CONTEXT_CTX_LEN_V(aeadctx->key_ctx_hdr)) << 4)
+		- sizeof(chcr_req->key_ctx);
+	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
+	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)), flags);
+	if (!skb)
+		goto err;
+
+	/* LLD is going to write the sge hdr. */
+	skb_reserve(skb, sizeof(struct sge_opaque_hdr));
+
+	/* Write WR */
+	chcr_req = (struct chcr_wr *) __skb_put(skb, transhdr_len);
+	memset(chcr_req, 0, transhdr_len);
+
+	stop_offset = (op_type == CHCR_ENCRYPT_OP) ? 0 : authsize;
+
+	/*
+	 * Input order	is AAD,IV and Payload. where IV should be included as
+	 * the part of authdata. All other fields should be filled according
+	 * to the hardware spec
+	 */
+	chcr_req->sec_cpl.op_ivinsrtofst =
+		FILL_SEC_CPL_OP_IVINSR(ctx->dev->tx_channel_id, 2,
+				       (ivsize ? (assoclen + 1) : 0));
+	chcr_req->sec_cpl.pldlen = htonl(assoclen + ivsize + req->cryptlen);
+	chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
+					assoclen ? 1 : 0, assoclen,
+					assoclen + ivsize + 1,
+					(stop_offset & 0x1F0) >> 4);
+	chcr_req->sec_cpl.cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(
+					stop_offset & 0xF,
+					null ? 0 : assoclen + ivsize + 1,
+					stop_offset, stop_offset);
+	chcr_req->sec_cpl.seqno_numivs = FILL_SEC_CPL_SCMD0_SEQNO(op_type,
+					(op_type == CHCR_ENCRYPT_OP) ? 1 : 0,
+					CHCR_SCMD_CIPHER_MODE_AES_CBC,
+					actx->auth_mode, aeadctx->hmac_ctrl,
+					ivsize >> 1);
+	chcr_req->sec_cpl.ivgen_hdrlen =  FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1,
+					 0, 1, dst_size);
+
+	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
+	if (op_type == CHCR_ENCRYPT_OP)
+		memcpy(chcr_req->key_ctx.key, aeadctx->key,
+		       aeadctx->enckey_len);
+	else
+		memcpy(chcr_req->key_ctx.key, actx->dec_rrkey,
+		       aeadctx->enckey_len);
+
+	memcpy(chcr_req->key_ctx.key + (DIV_ROUND_UP(aeadctx->enckey_len, 16) <<
+					4), actx->h_iopad, kctx_len -
+				(DIV_ROUND_UP(aeadctx->enckey_len, 16) << 4));
+
+	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
+	sg_param.nents = reqctx->dst_nents;
+	sg_param.obsize = req->cryptlen + (op_type ? -authsize : authsize);
+	sg_param.qid = qid;
+	sg_param.align = 0;
+	if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, reqctx->dst,
+				  &sg_param))
+		goto dstmap_fail;
+
+	skb_set_transport_header(skb, transhdr_len);
+
+	if (assoclen) {
+		/* AAD buffer in */
+		write_sg_to_skb(skb, &frags, req->src, assoclen);
+
+	}
+	write_buffer_to_skb(skb, &frags, req->iv, ivsize);
+	write_sg_to_skb(skb, &frags, src, req->cryptlen);
+	create_wreq(ctx, chcr_req, req, skb, kctx_len, size, 1,
+		   sizeof(struct cpl_rx_phys_dsgl) + dst_size);
+	reqctx->skb = skb;
+	skb_get(skb);
+
+	return skb;
+dstmap_fail:
+	/* ivmap_fail: */
+	kfree_skb(skb);
+err:
+	return ERR_PTR(-EINVAL);
+}
+
+static void aes_gcm_empty_pld_pad(struct scatterlist *sg,
+				  unsigned short offset)
+{
+	struct page *spage;
+	unsigned char *addr;
+
+	spage = sg_page(sg);
+	get_page(spage); /* so that it is not freed by NIC */
+#ifdef KMAP_ATOMIC_ARGS
+	addr = kmap_atomic(spage, KM_SOFTIRQ0);
+#else
+	addr = kmap_atomic(spage);
+#endif
+	memset(addr + sg->offset, 0, offset + 1);
+
+	kunmap_atomic(addr);
+}
+
+static int set_msg_len(u8 *block, unsigned int msglen, int csize)
+{
+	__be32 data;
+
+	memset(block, 0, csize);
+	block += csize;
+
+	if (csize >= 4)
+		csize = 4;
+	else if (msglen > (unsigned int)(1 << (8 * csize)))
+		return -EOVERFLOW;
+
+	data = cpu_to_be32(msglen);
+	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
+
+	return 0;
+}
+
+static void generate_b0(struct aead_request *req,
+			struct chcr_aead_ctx *aeadctx,
+			unsigned short op_type)
+{
+	unsigned int l, lp, m;
+	int rc;
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
+	u8 *b0 = reqctx->scratch_pad;
+
+	m = crypto_aead_authsize(aead);
+
+	memcpy(b0, reqctx->iv, 16);
+
+	lp = b0[0];
+	l = lp + 1;
+
+	/* set m, bits 3-5 */
+	*b0 |= (8 * ((m - 2) / 2));
+
+	/* set adata, bit 6, if associated data is used */
+	if (req->assoclen)
+		*b0 |= 64;
+	rc = set_msg_len(b0 + 16 - l,
+			 (op_type == CHCR_DECRYPT_OP) ?
+			 req->cryptlen - m : req->cryptlen, l);
+}
+
+static inline int crypto_ccm_check_iv(const u8 *iv)
+{
+	/* 2 <= L <= 8, so 1 <= L' <= 7. */
+	if (iv[0] < 1 || iv[0] > 7)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ccm_format_packet(struct aead_request *req,
+			     struct chcr_aead_ctx *aeadctx,
+			     unsigned int sub_type,
+			     unsigned short op_type)
+{
+	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
+	int rc = 0;
+
+	if (req->assoclen > T5_MAX_AAD_SIZE) {
+		pr_err("CCM: Unsupported AAD data. It should be < %d\n",
+		       T5_MAX_AAD_SIZE);
+		return -EINVAL;
+	}
+	if (sub_type == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) {
+		reqctx->iv[0] = 3;
+		memcpy(reqctx->iv + 1, &aeadctx->salt[0], 3);
+		memcpy(reqctx->iv + 4, req->iv, 8);
+		memset(reqctx->iv + 12, 0, 4);
+		*((unsigned short *)(reqctx->scratch_pad + 16)) =
+			htons(req->assoclen - 8);
+	} else {
+		memcpy(reqctx->iv, req->iv, 16);
+		*((unsigned short *)(reqctx->scratch_pad + 16)) =
+			htons(req->assoclen);
+	}
+	generate_b0(req, aeadctx, op_type);
+	/* zero the ctr value */
+	memset(reqctx->iv + 15 - reqctx->iv[0], 0, reqctx->iv[0] + 1);
+	return rc;
+}
+
+static void fill_sec_cpl_for_aead(struct cpl_tx_sec_pdu *sec_cpl,
+				  unsigned int dst_size,
+				  struct aead_request *req,
+				  unsigned short op_type,
+					  struct chcr_context *chcrctx)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	unsigned int ivsize = AES_BLOCK_SIZE;
+	unsigned int cipher_mode = CHCR_SCMD_CIPHER_MODE_AES_CCM;
+	unsigned int mac_mode = CHCR_SCMD_AUTH_MODE_CBCMAC;
+	unsigned int c_id = chcrctx->dev->tx_channel_id;
+	unsigned int ccm_xtra;
+	unsigned char tag_offset = 0, auth_offset = 0;
+	unsigned char hmac_ctrl = get_hmac(crypto_aead_authsize(tfm));
+	unsigned int assoclen;
+
+	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
+		assoclen = req->assoclen - 8;
+	else
+		assoclen = req->assoclen;
+	ccm_xtra = CCM_B0_SIZE +
+		((assoclen) ? CCM_AAD_FIELD_SIZE : 0);
+
+	auth_offset = req->cryptlen ?
+		(assoclen + ivsize + 1 + ccm_xtra) : 0;
+	if (op_type == CHCR_DECRYPT_OP) {
+		if (crypto_aead_authsize(tfm) != req->cryptlen)
+			tag_offset = crypto_aead_authsize(tfm);
+		else
+			auth_offset = 0;
+	}
+
+
+	sec_cpl->op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(c_id,
+					 2, (ivsize ?  (assoclen + 1) :  0) +
+					 ccm_xtra);
+	sec_cpl->pldlen =
+		htonl(assoclen + ivsize + req->cryptlen + ccm_xtra);
+	/* For CCM there wil be b0 always. So AAD start will be 1 always */
+	sec_cpl->aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
+					1, assoclen + ccm_xtra, assoclen
+					+ ivsize + 1 + ccm_xtra, 0);
+
+	sec_cpl->cipherstop_lo_authinsert = FILL_SEC_CPL_AUTHINSERT(0,
+					auth_offset, tag_offset,
+					(op_type == CHCR_ENCRYPT_OP) ? 0 :
+					crypto_aead_authsize(tfm));
+	sec_cpl->seqno_numivs =  FILL_SEC_CPL_SCMD0_SEQNO(op_type,
+					(op_type == CHCR_ENCRYPT_OP) ? 0 : 1,
+					cipher_mode, mac_mode, hmac_ctrl,
+					ivsize >> 1);
+
+	sec_cpl->ivgen_hdrlen = FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1, 0,
+					1, dst_size);
+}
+
+int aead_ccm_validate_input(unsigned short op_type,
+			    struct aead_request *req,
+			    struct chcr_aead_ctx *aeadctx,
+			    unsigned int sub_type)
+{
+	if (sub_type != CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309) {
+		if (crypto_ccm_check_iv(req->iv)) {
+			pr_err("CCM: IV check fails\n");
+			return -EINVAL;
+		}
+	} else {
+		if (req->assoclen != 16 && req->assoclen != 20) {
+			pr_err("RFC4309: Invalid AAD length %d\n",
+			       req->assoclen);
+			return -EINVAL;
+		}
+	}
+	if (aeadctx->enckey_len == 0) {
+		pr_err("CCM: Encryption key not set\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+unsigned int fill_aead_req_fields(struct sk_buff *skb,
+				  struct aead_request *req,
+				  struct scatterlist *src,
+				  unsigned int ivsize,
+				  struct chcr_aead_ctx *aeadctx)
+{
+	unsigned int frags = 0;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
+	/* b0 and aad length(if available) */
+
+	write_buffer_to_skb(skb, &frags, reqctx->scratch_pad, CCM_B0_SIZE +
+				(req->assoclen ?  CCM_AAD_FIELD_SIZE : 0));
+	if (req->assoclen) {
+		if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
+			write_sg_to_skb(skb, &frags, req->src,
+					req->assoclen - 8);
+		else
+			write_sg_to_skb(skb, &frags, req->src, req->assoclen);
+	}
+	write_buffer_to_skb(skb, &frags, reqctx->iv, ivsize);
+	if (req->cryptlen)
+		write_sg_to_skb(skb, &frags, src, req->cryptlen);
+
+	return frags;
+}
+
+static struct sk_buff *create_aead_ccm_wr(struct aead_request *req,
+					  unsigned short qid,
+					  int size,
+					  unsigned short op_type)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct chcr_context *ctx = crypto_aead_ctx(tfm);
+	struct uld_ctx *u_ctx = ULD_CTX(ctx);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
+	struct sk_buff *skb = NULL;
+	struct chcr_wr *chcr_req;
+	struct cpl_rx_phys_dsgl *phys_cpl;
+	struct phys_sge_parm sg_param;
+	struct scatterlist *src;
+	unsigned int frags = 0, transhdr_len, ivsize = AES_BLOCK_SIZE;
+	unsigned int dst_size = 0, kctx_len;
+	unsigned int sub_type;
+	unsigned int authsize = crypto_aead_authsize(tfm);
+	int err = 0;
+	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+		GFP_ATOMIC;
+
+
+	if (op_type && req->cryptlen < crypto_aead_authsize(tfm))
+		goto err;
+
+	if (sg_nents_for_len(req->src, req->assoclen + req->cryptlen) < 0)
+		goto err;
+	sub_type = get_aead_subtype(tfm);
+	src = scatterwalk_ffwd(reqctx->srcffwd, req->src, req->assoclen);
+	reqctx->dst = src;
+
+	if (req->src != req->dst) {
+		err = chcr_copy_assoc(req, aeadctx);
+		if (err) {
+			pr_err("AAD copy to destination buffer fails\n");
+			return ERR_PTR(err);
+		}
+		reqctx->dst = scatterwalk_ffwd(reqctx->dstffwd, req->dst,
+					       req->assoclen);
+	}
+	reqctx->dst_nents = sg_nents_for_len(reqctx->dst, req->cryptlen +
+					     (op_type ? -authsize : authsize));
+	if (reqctx->dst_nents <= 0) {
+		pr_err("CCM:Invalid Destination sg entries\n");
+		goto err;
+	}
+
+
+	if (aead_ccm_validate_input(op_type, req, aeadctx, sub_type))
+		goto err;
+
+	dst_size = get_space_for_phys_dsgl(reqctx->dst_nents);
+	kctx_len = ((DIV_ROUND_UP(aeadctx->enckey_len, 16)) << 4) * 2;
+	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
+	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)),  flags);
+
+	if (!skb)
+		goto err;
+
+	skb_reserve(skb, sizeof(struct sge_opaque_hdr));
+
+	chcr_req = (struct chcr_wr *) __skb_put(skb, transhdr_len);
+	memset(chcr_req, 0, transhdr_len);
+
+	fill_sec_cpl_for_aead(&chcr_req->sec_cpl, dst_size, req, op_type, ctx);
+
+	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
+	memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len);
+	memcpy(chcr_req->key_ctx.key + (DIV_ROUND_UP(aeadctx->enckey_len, 16) *
+					16), aeadctx->key, aeadctx->enckey_len);
+
+	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
+	if (ccm_format_packet(req, aeadctx, sub_type, op_type))
+		goto dstmap_fail;
+
+	sg_param.nents = reqctx->dst_nents;
+	sg_param.obsize = req->cryptlen + (op_type ? -authsize : authsize);
+	sg_param.qid = qid;
+	sg_param.align = 0;
+	if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, reqctx->dst,
+				  &sg_param))
+		goto dstmap_fail;
+
+	skb_set_transport_header(skb, transhdr_len);
+	frags = fill_aead_req_fields(skb, req, src, ivsize, aeadctx);
+	create_wreq(ctx, chcr_req, req, skb, kctx_len, 0, 1,
+		    sizeof(struct cpl_rx_phys_dsgl) + dst_size);
+	reqctx->skb = skb;
+	skb_get(skb);
+	return skb;
+dstmap_fail:
+	kfree_skb(skb);
+	skb = NULL;
+err:
+	return ERR_PTR(-EINVAL);
+}
+
+static struct sk_buff *create_gcm_wr(struct aead_request *req,
+				     unsigned short qid,
+				     int size,
+				     unsigned short op_type)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct chcr_context *ctx = crypto_aead_ctx(tfm);
+	struct uld_ctx *u_ctx = ULD_CTX(ctx);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+	struct chcr_aead_reqctx  *reqctx = aead_request_ctx(req);
+	struct sk_buff *skb = NULL;
+	struct chcr_wr *chcr_req;
+	struct cpl_rx_phys_dsgl *phys_cpl;
+	struct phys_sge_parm sg_param;
+	struct scatterlist *src;
+	unsigned int frags = 0, transhdr_len;
+	unsigned int ivsize = AES_BLOCK_SIZE;
+	unsigned int dst_size = 0, kctx_len;
+	unsigned char tag_offset = 0;
+	unsigned int crypt_len = 0;
+	unsigned int authsize = crypto_aead_authsize(tfm);
+	unsigned char hmac_ctrl = get_hmac(authsize);
+	int err = 0;
+	gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+		GFP_ATOMIC;
+
+	/* validate key size */
+	if (aeadctx->enckey_len == 0)
+		goto err;
+
+	if (op_type && req->cryptlen < crypto_aead_authsize(tfm))
+		goto err;
+
+	if (sg_nents_for_len(req->src, req->assoclen + req->cryptlen) < 0)
+		goto err;
+
+	src = scatterwalk_ffwd(reqctx->srcffwd, req->src, req->assoclen);
+	reqctx->dst = src;
+	if (req->src != req->dst) {
+		err = chcr_copy_assoc(req, aeadctx);
+		if (err)
+			return	ERR_PTR(err);
+		reqctx->dst = scatterwalk_ffwd(reqctx->dstffwd, req->dst,
+					       req->assoclen);
+	}
+
+	if (!req->cryptlen)
+		/* null-payload is not supported in the hardware.
+		 * software is sending block size
+		 */
+		crypt_len = AES_BLOCK_SIZE;
+	else
+		crypt_len = req->cryptlen;
+	reqctx->dst_nents = sg_nents_for_len(reqctx->dst, req->cryptlen +
+					     (op_type ? -authsize : authsize));
+	if (reqctx->dst_nents <= 0) {
+		pr_err("GCM:Invalid Destination sg entries\n");
+		goto err;
+	}
+
+
+	dst_size = get_space_for_phys_dsgl(reqctx->dst_nents);
+	kctx_len = ((DIV_ROUND_UP(aeadctx->enckey_len, 16)) << 4) +
+		AEAD_H_SIZE;
+	transhdr_len = CIPHER_TRANSHDR_SIZE(kctx_len, dst_size);
+	skb = alloc_skb((transhdr_len + sizeof(struct sge_opaque_hdr)), flags);
+	if (!skb)
+		goto err;
+
+	/* NIC driver is going to write the sge hdr. */
+	skb_reserve(skb, sizeof(struct sge_opaque_hdr));
+
+	chcr_req = (struct chcr_wr *)__skb_put(skb, transhdr_len);
+	memset(chcr_req, 0, transhdr_len);
+
+	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106)
+		req->assoclen -= 8;
+
+	tag_offset = (op_type == CHCR_ENCRYPT_OP) ? 0 : authsize;
+	chcr_req->sec_cpl.op_ivinsrtofst = FILL_SEC_CPL_OP_IVINSR(
+					ctx->dev->tx_channel_id, 2, (ivsize ?
+					(req->assoclen + 1) : 0));
+	chcr_req->sec_cpl.pldlen = htonl(req->assoclen + ivsize + crypt_len);
+	chcr_req->sec_cpl.aadstart_cipherstop_hi = FILL_SEC_CPL_CIPHERSTOP_HI(
+					req->assoclen ? 1 : 0, req->assoclen,
+					req->assoclen + ivsize + 1, 0);
+	if (req->cryptlen) {
+		chcr_req->sec_cpl.cipherstop_lo_authinsert =
+			FILL_SEC_CPL_AUTHINSERT(0, req->assoclen + ivsize + 1,
+						tag_offset, tag_offset);
+		chcr_req->sec_cpl.seqno_numivs =
+			FILL_SEC_CPL_SCMD0_SEQNO(op_type, (op_type ==
+					CHCR_ENCRYPT_OP) ? 1 : 0,
+					CHCR_SCMD_CIPHER_MODE_AES_GCM,
+					CHCR_SCMD_AUTH_MODE_GHASH, hmac_ctrl,
+					ivsize >> 1);
+	} else {
+		chcr_req->sec_cpl.cipherstop_lo_authinsert =
+			FILL_SEC_CPL_AUTHINSERT(0, 0, 0, 0);
+		chcr_req->sec_cpl.seqno_numivs =
+			FILL_SEC_CPL_SCMD0_SEQNO(op_type,
+					(op_type ==  CHCR_ENCRYPT_OP) ?
+					1 : 0, CHCR_SCMD_CIPHER_MODE_AES_CBC,
+					0, 0, ivsize >> 1);
+	}
+	chcr_req->sec_cpl.ivgen_hdrlen =  FILL_SEC_CPL_IVGEN_HDRLEN(0, 0, 1,
+					0, 1, dst_size);
+	chcr_req->key_ctx.ctx_hdr = aeadctx->key_ctx_hdr;
+	memcpy(chcr_req->key_ctx.key, aeadctx->key, aeadctx->enckey_len);
+	memcpy(chcr_req->key_ctx.key + (DIV_ROUND_UP(aeadctx->enckey_len, 16) *
+				16), GCM_CTX(aeadctx)->ghash_h, AEAD_H_SIZE);
+
+	/* prepare a 16 byte iv */
+	/* S   A   L  T |  IV | 0x00000001 */
+	if (get_aead_subtype(tfm) ==
+	    CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106) {
+		memcpy(reqctx->iv, aeadctx->salt, 4);
+		memcpy(reqctx->iv + 4, req->iv, 8);
+	} else {
+		memcpy(reqctx->iv, req->iv, 12);
+	}
+	*((unsigned int *)(reqctx->iv + 12)) = htonl(0x01);
+
+	phys_cpl = (struct cpl_rx_phys_dsgl *)((u8 *)(chcr_req + 1) + kctx_len);
+	sg_param.nents = reqctx->dst_nents;
+	sg_param.obsize = req->cryptlen + (op_type ? -authsize : authsize);
+	sg_param.qid = qid;
+	sg_param.align = 0;
+	if (map_writesg_phys_cpl(&u_ctx->lldi.pdev->dev, phys_cpl, reqctx->dst,
+				  &sg_param))
+		goto dstmap_fail;
+
+	skb_set_transport_header(skb, transhdr_len);
+
+	write_sg_to_skb(skb, &frags, req->src, req->assoclen);
+
+	write_buffer_to_skb(skb, &frags, reqctx->iv, ivsize);
+
+	if (req->cryptlen) {
+		write_sg_to_skb(skb, &frags, src, req->cryptlen);
+	} else {
+		aes_gcm_empty_pld_pad(req->dst, authsize - 1);
+		write_sg_to_skb(skb, &frags, reqctx->dst, crypt_len);
+
+	}
+
+	create_wreq(ctx, chcr_req, req, skb, kctx_len, size, 1,
+			sizeof(struct cpl_rx_phys_dsgl) + dst_size);
+	reqctx->skb = skb;
+	skb_get(skb);
+	return skb;
+
+dstmap_fail:
+	/* ivmap_fail: */
+	kfree_skb(skb);
+	skb = NULL;
+err:
+	return skb;
+}
+
+
+
+static int chcr_aead_cra_init(struct crypto_aead *tfm)
+{
+	struct chcr_context *ctx = crypto_aead_ctx(tfm);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+
+	crypto_aead_set_reqsize(tfm, sizeof(struct chcr_aead_reqctx));
+	aeadctx->null = crypto_get_default_null_skcipher();
+	if (IS_ERR(aeadctx->null))
+		return PTR_ERR(aeadctx->null);
+	return chcr_device_init(ctx);
+}
+
+static void chcr_aead_cra_exit(struct crypto_aead *tfm)
+{
+	crypto_put_default_null_skcipher();
+}
+
+static int chcr_authenc_null_setauthsize(struct crypto_aead *tfm,
+					unsigned int authsize)
+{
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(crypto_aead_ctx(tfm));
+
+	aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NOP;
+	aeadctx->mayverify = VERIFY_HW;
+	return 0;
+}
+static int chcr_authenc_setauthsize(struct crypto_aead *tfm,
+				    unsigned int authsize)
+{
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(crypto_aead_ctx(tfm));
+	u32 maxauth = crypto_aead_maxauthsize(tfm);
+
+	/*SHA1 authsize in ipsec is 12 instead of 10 i.e maxauthsize / 2 is not
+	 * true for sha1. authsize == 12 condition should be before
+	 * authsize == (maxauth >> 1)
+	 */
+	if (authsize == ICV_4) {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
+		aeadctx->mayverify = VERIFY_HW;
+	} else if (authsize == ICV_6) {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2;
+		aeadctx->mayverify = VERIFY_HW;
+	} else if (authsize == ICV_10) {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
+		aeadctx->mayverify = VERIFY_HW;
+	} else if (authsize == ICV_12) {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
+		aeadctx->mayverify = VERIFY_HW;
+	} else if (authsize == ICV_14) {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
+		aeadctx->mayverify = VERIFY_HW;
+	} else if (authsize == (maxauth >> 1)) {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
+		aeadctx->mayverify = VERIFY_HW;
+	} else if (authsize == maxauth) {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
+		aeadctx->mayverify = VERIFY_HW;
+	} else {
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
+		aeadctx->mayverify = VERIFY_SW;
+	}
+	return 0;
+}
+
+
+static int chcr_gcm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
+{
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(crypto_aead_ctx(tfm));
+
+	switch (authsize) {
+	case ICV_4:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_8:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_12:
+		 aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
+		 aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_14:
+		 aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
+		 aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_16:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_13:
+	case ICV_15:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
+		aeadctx->mayverify = VERIFY_SW;
+		break;
+	default:
+
+		  crypto_tfm_set_flags((struct crypto_tfm *) tfm,
+			CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int chcr_4106_4309_setauthsize(struct crypto_aead *tfm,
+					  unsigned int authsize)
+{
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(crypto_aead_ctx(tfm));
+
+	switch (authsize) {
+	case ICV_8:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_12:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_16:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	default:
+		crypto_tfm_set_flags((struct crypto_tfm *)tfm,
+				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int chcr_ccm_setauthsize(struct crypto_aead *tfm,
+				unsigned int authsize)
+{
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(crypto_aead_ctx(tfm));
+
+	switch (authsize) {
+	case ICV_4:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL1;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_6:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL2;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_8:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_DIV2;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_10:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_12:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_14:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_PL3;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	case ICV_16:
+		aeadctx->hmac_ctrl = CHCR_SCMD_HMAC_CTRL_NO_TRUNC;
+		aeadctx->mayverify = VERIFY_HW;
+		break;
+	default:
+		crypto_tfm_set_flags((struct crypto_tfm *)tfm,
+				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int chcr_aead_ccm_setkey(struct crypto_aead *aead,
+				const u8 *key,
+				unsigned int keylen)
+{
+	struct chcr_context *ctx = crypto_aead_ctx(aead);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+	unsigned char ck_size, mk_size;
+	int key_ctx_size = 0;
+
+	memcpy(aeadctx->key, key, keylen);
+	aeadctx->enckey_len = keylen;
+	key_ctx_size = sizeof(struct _key_ctx) +
+		((DIV_ROUND_UP(keylen, 16)) << 4)  * 2;
+	if (keylen == AES_KEYSIZE_128) {
+		mk_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
+	} else if (keylen == AES_KEYSIZE_192) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
+		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_192;
+	} else if (keylen == AES_KEYSIZE_256) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
+		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
+	} else {
+		crypto_tfm_set_flags((struct crypto_tfm *)aead,
+				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		aeadctx->enckey_len = 0;
+		return	-EINVAL;
+	}
+	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, mk_size, 0, 0,
+						key_ctx_size >> 4);
+	return 0;
+}
+
+static int chcr_aead_rfc4309_setkey(struct crypto_aead *aead, const u8 *key,
+				    unsigned int keylen)
+{
+	struct chcr_context *ctx = crypto_aead_ctx(aead);
+	 struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+
+	if (keylen < 3) {
+		crypto_tfm_set_flags((struct crypto_tfm *)aead,
+				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		aeadctx->enckey_len = 0;
+		return	-EINVAL;
+	}
+	keylen -= 3;
+	memcpy(aeadctx->salt, key + keylen, 3);
+	return chcr_aead_ccm_setkey(aead, key, keylen);
+}
+
+static int chcr_gcm_setkey(struct crypto_aead *aead, const u8 *key,
+			   unsigned int keylen)
+{
+	struct chcr_context *ctx = crypto_aead_ctx(aead);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+	struct chcr_gcm_ctx *gctx = GCM_CTX(aeadctx);
+	struct blkcipher_desc h_desc;
+	struct scatterlist src[1];
+	unsigned int ck_size;
+	int ret = 0, key_ctx_size = 0;
+
+	if (get_aead_subtype(aead) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106 &&
+	    keylen > 3) {
+		keylen -= 4;  /* nonce/salt is present in the last 4 bytes */
+		memcpy(aeadctx->salt, key + keylen, 4);
+	}
+	if (keylen == AES_KEYSIZE_128) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
+	} else if (keylen == AES_KEYSIZE_192) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
+	} else if (keylen == AES_KEYSIZE_256) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
+	} else {
+		crypto_tfm_set_flags((struct crypto_tfm *)aead,
+				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		aeadctx->enckey_len = 0;
+		pr_err("GCM: Invalid key length %d", keylen);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	memcpy(aeadctx->key, key, keylen);
+	aeadctx->enckey_len = keylen;
+	key_ctx_size = sizeof(struct _key_ctx) +
+		((DIV_ROUND_UP(keylen, 16)) << 4) +
+		AEAD_H_SIZE;
+		aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size,
+						CHCR_KEYCTX_MAC_KEY_SIZE_128,
+						0, 0,
+						key_ctx_size >> 4);
+	/* Calculate the H = CIPH(K, 0 repeated 16 times) using sync aes
+	 * blkcipher It will go on key context
+	 */
+	h_desc.tfm = crypto_alloc_blkcipher("cbc(aes-generic)", 0, 0);
+	if (IS_ERR(h_desc.tfm)) {
+		aeadctx->enckey_len = 0;
+		ret = -ENOMEM;
+		goto out;
+	}
+	h_desc.flags = 0;
+	ret = crypto_blkcipher_setkey(h_desc.tfm, key, keylen);
+	if (ret) {
+		aeadctx->enckey_len = 0;
+		goto out1;
+	}
+	memset(gctx->ghash_h, 0, AEAD_H_SIZE);
+	sg_init_one(&src[0], gctx->ghash_h, AEAD_H_SIZE);
+	ret = crypto_blkcipher_encrypt(&h_desc, &src[0], &src[0], AEAD_H_SIZE);
+
+out1:
+	crypto_free_blkcipher(h_desc.tfm);
+out:
+	return ret;
+}
+
+static int chcr_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
+				   unsigned int keylen)
+{
+	struct chcr_context *ctx = crypto_aead_ctx(authenc);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
+	/* it contains auth and cipher key both*/
+	struct crypto_authenc_keys keys;
+	unsigned int bs;
+	unsigned int max_authsize = crypto_aead_alg(authenc)->maxauthsize;
+	int err = 0, i, key_ctx_len = 0;
+	unsigned char ck_size = 0;
+	unsigned char pad[CHCR_HASH_MAX_BLOCK_SIZE_128] = { 0 };
+	struct crypto_shash *base_hash = NULL;
+	struct algo_param param;
+	int align;
+	u8 *o_ptr = NULL;
+
+	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) {
+		crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		goto out;
+	}
+
+	if (get_alg_config(&param, max_authsize)) {
+		pr_err("chcr : Unsupported digest size\n");
+		goto out;
+	}
+	if (keys.enckeylen == AES_KEYSIZE_128) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
+	} else if (keys.enckeylen == AES_KEYSIZE_192) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
+	} else if (keys.enckeylen == AES_KEYSIZE_256) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
+	} else {
+		pr_err("chcr : Unsupported cipher key\n");
+		goto out;
+	}
+
+	/* Copy only encryption key. We use authkey to generate h(ipad) and
+	 * h(opad) so authkey is not needed again. authkeylen size have the
+	 * size of the hash digest size.
+	 */
+	memcpy(aeadctx->key, keys.enckey, keys.enckeylen);
+	aeadctx->enckey_len = keys.enckeylen;
+	get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key,
+			    aeadctx->enckey_len << 3);
+
+	base_hash  = chcr_alloc_shash(max_authsize);
+	if (IS_ERR(base_hash)) {
+		pr_err("chcr : Base driver cannot be loaded\n");
+		goto out;
+	}
+	{
+		SHASH_DESC_ON_STACK(shash, base_hash);
+		shash->tfm = base_hash;
+		shash->flags = crypto_shash_get_flags(base_hash);
+		bs = crypto_shash_blocksize(base_hash);
+		align = KEYCTX_ALIGN_PAD(max_authsize);
+		o_ptr =  actx->h_iopad + param.result_size + align;
+
+		if (keys.authkeylen > bs) {
+			err = crypto_shash_digest(shash, keys.authkey,
+						  keys.authkeylen,
+						  o_ptr);
+			if (err) {
+				pr_err("chcr : Base driver cannot be loaded\n");
+				goto out;
+			}
+			keys.authkeylen = max_authsize;
+		} else
+			memcpy(o_ptr, keys.authkey, keys.authkeylen);
+
+		/* Compute the ipad-digest*/
+		memset(pad + keys.authkeylen, 0, bs - keys.authkeylen);
+		memcpy(pad, o_ptr, keys.authkeylen);
+		for (i = 0; i < bs >> 2; i++)
+			*((unsigned int *)pad + i) ^= IPAD_DATA;
+
+		if (chcr_compute_partial_hash(shash, pad, actx->h_iopad,
+					      max_authsize))
+			goto out;
+		/* Compute the opad-digest */
+		memset(pad + keys.authkeylen, 0, bs - keys.authkeylen);
+		memcpy(pad, o_ptr, keys.authkeylen);
+		for (i = 0; i < bs >> 2; i++)
+			*((unsigned int *)pad + i) ^= OPAD_DATA;
+
+		if (chcr_compute_partial_hash(shash, pad, o_ptr, max_authsize))
+			goto out;
+
+		/* convert the ipad and opad digest to network order */
+		chcr_change_order(actx->h_iopad, param.result_size);
+		chcr_change_order(o_ptr, param.result_size);
+		key_ctx_len = sizeof(struct _key_ctx) +
+			((DIV_ROUND_UP(keys.enckeylen, 16)) << 4) +
+			(param.result_size + align) * 2;
+		aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, param.mk_size,
+						0, 1, key_ctx_len >> 4);
+		actx->auth_mode = param.auth_mode;
+		chcr_free_shash(base_hash);
+
+		return 0;
+	}
+out:
+	aeadctx->enckey_len = 0;
+	if (base_hash)
+		chcr_free_shash(base_hash);
+	return -EINVAL;
+}
+
+static int chcr_aead_digest_null_setkey(struct crypto_aead *authenc,
+					const u8 *key, unsigned int keylen)
+{
+	struct chcr_context *ctx = crypto_aead_ctx(authenc);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(ctx);
+	struct chcr_authenc_ctx *actx = AUTHENC_CTX(aeadctx);
+	struct crypto_authenc_keys keys;
+
+	/* it contains auth and cipher key both*/
+	int key_ctx_len = 0;
+	unsigned char ck_size = 0;
+
+	if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) {
+		crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		goto out;
+	}
+	if (keys.enckeylen == AES_KEYSIZE_128) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_128;
+	} else if (keys.enckeylen == AES_KEYSIZE_192) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_192;
+	} else if (keys.enckeylen == AES_KEYSIZE_256) {
+		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
+	} else {
+		pr_err("chcr : Unsupported cipher key\n");
+		goto out;
+	}
+	memcpy(aeadctx->key, keys.enckey, keys.enckeylen);
+	aeadctx->enckey_len = keys.enckeylen;
+	get_aes_decrypt_key(actx->dec_rrkey, aeadctx->key,
+				    aeadctx->enckey_len << 3);
+	key_ctx_len =  sizeof(struct _key_ctx)
+		+ ((DIV_ROUND_UP(keys.enckeylen, 16)) << 4);
+
+	aeadctx->key_ctx_hdr = FILL_KEY_CTX_HDR(ck_size, CHCR_KEYCTX_NO_KEY, 0,
+						0, key_ctx_len >> 4);
+	actx->auth_mode = CHCR_SCMD_AUTH_MODE_NOP;
+	return 0;
+out:
+	aeadctx->enckey_len = 0;
+	return -EINVAL;
+}
+static int chcr_aead_encrypt(struct aead_request *req)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
+
+	reqctx->verify = VERIFY_HW;
+
+	switch (get_aead_subtype(tfm)) {
+	case CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC:
+	case CRYPTO_ALG_SUB_TYPE_AEAD_NULL:
+		return chcr_aead_op(req, CHCR_ENCRYPT_OP, 0,
+				    create_authenc_wr);
+	case CRYPTO_ALG_SUB_TYPE_AEAD_CCM:
+	case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309:
+		return chcr_aead_op(req, CHCR_ENCRYPT_OP, 0,
+				    create_aead_ccm_wr);
+	default:
+		return chcr_aead_op(req, CHCR_ENCRYPT_OP, 0,
+				    create_gcm_wr);
 	}
 }
 
+static int chcr_aead_decrypt(struct aead_request *req)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct chcr_aead_ctx *aeadctx = AEAD_CTX(crypto_aead_ctx(tfm));
+	struct chcr_aead_reqctx *reqctx = aead_request_ctx(req);
+	int size;
+
+	if (aeadctx->mayverify == VERIFY_SW) {
+		size = crypto_aead_maxauthsize(tfm);
+		reqctx->verify = VERIFY_SW;
+	} else {
+		size = 0;
+		reqctx->verify = VERIFY_HW;
+	}
+
+	switch (get_aead_subtype(tfm)) {
+	case CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC:
+	case CRYPTO_ALG_SUB_TYPE_AEAD_NULL:
+		return chcr_aead_op(req, CHCR_DECRYPT_OP, size,
+				    create_authenc_wr);
+	case CRYPTO_ALG_SUB_TYPE_AEAD_CCM:
+	case CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309:
+		return chcr_aead_op(req, CHCR_DECRYPT_OP, size,
+				    create_aead_ccm_wr);
+	default:
+		return chcr_aead_op(req, CHCR_DECRYPT_OP, size,
+				    create_gcm_wr);
+	}
+}
+
+static int chcr_aead_op(struct aead_request *req,
+			  unsigned short op_type,
+			  int size,
+			  create_wr_t create_wr_fn)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	struct chcr_context *ctx = crypto_aead_ctx(tfm);
+	struct uld_ctx *u_ctx = ULD_CTX(ctx);
+	struct sk_buff *skb;
+
+	if (ctx && !ctx->dev) {
+		pr_err("chcr : %s : No crypto device.\n", __func__);
+		return -ENXIO;
+	}
+	if (cxgb4_is_crypto_q_full(u_ctx->lldi.ports[0],
+				   ctx->tx_channel_id)) {
+		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG))
+			return -EBUSY;
+	}
+
+	/* Form a WR from req */
+	skb = create_wr_fn(req, u_ctx->lldi.rxq_ids[ctx->tx_channel_id], size,
+			   op_type);
+
+	if (IS_ERR(skb) || skb == NULL) {
+		pr_err("chcr : %s : failed to form WR. No memory\n", __func__);
+		return PTR_ERR(skb);
+	}
+
+	skb->dev = u_ctx->lldi.ports[0];
+	set_wr_txq(skb, CPL_PRIORITY_DATA, ctx->tx_channel_id);
+	chcr_send_wr(skb);
+	return -EINPROGRESS;
+}
 static struct chcr_alg_template driver_algs[] = {
 	/* AES-CBC */
 	{
@@ -1232,7 +2490,7 @@ static struct chcr_alg_template driver_a
 		.is_registered = 0,
 		.alg.crypto = {
 			.cra_name		= "cbc(aes)",
-			.cra_driver_name	= "cbc(aes-chcr)",
+			.cra_driver_name	= "cbc-aes-chcr",
 			.cra_priority		= CHCR_CRA_PRIORITY,
 			.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
 				CRYPTO_ALG_ASYNC,
@@ -1259,7 +2517,7 @@ static struct chcr_alg_template driver_a
 		.is_registered = 0,
 		.alg.crypto =   {
 			.cra_name		= "xts(aes)",
-			.cra_driver_name	= "xts(aes-chcr)",
+			.cra_driver_name	= "xts-aes-chcr",
 			.cra_priority		= CHCR_CRA_PRIORITY,
 			.cra_flags		= CRYPTO_ALG_TYPE_BLKCIPHER |
 				CRYPTO_ALG_ASYNC,
@@ -1352,7 +2610,7 @@ static struct chcr_alg_template driver_a
 			.halg.digestsize = SHA1_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha1)",
-				.cra_driver_name = "hmac(sha1-chcr)",
+				.cra_driver_name = "hmac-sha1-chcr",
 				.cra_blocksize = SHA1_BLOCK_SIZE,
 			}
 		}
@@ -1364,7 +2622,7 @@ static struct chcr_alg_template driver_a
 			.halg.digestsize = SHA224_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha224)",
-				.cra_driver_name = "hmac(sha224-chcr)",
+				.cra_driver_name = "hmac-sha224-chcr",
 				.cra_blocksize = SHA224_BLOCK_SIZE,
 			}
 		}
@@ -1376,7 +2634,7 @@ static struct chcr_alg_template driver_a
 			.halg.digestsize = SHA256_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha256)",
-				.cra_driver_name = "hmac(sha256-chcr)",
+				.cra_driver_name = "hmac-sha256-chcr",
 				.cra_blocksize = SHA256_BLOCK_SIZE,
 			}
 		}
@@ -1388,7 +2646,7 @@ static struct chcr_alg_template driver_a
 			.halg.digestsize = SHA384_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha384)",
-				.cra_driver_name = "hmac(sha384-chcr)",
+				.cra_driver_name = "hmac-sha384-chcr",
 				.cra_blocksize = SHA384_BLOCK_SIZE,
 			}
 		}
@@ -1400,11 +2658,205 @@ static struct chcr_alg_template driver_a
 			.halg.digestsize = SHA512_DIGEST_SIZE,
 			.halg.base = {
 				.cra_name = "hmac(sha512)",
-				.cra_driver_name = "hmac(sha512-chcr)",
+				.cra_driver_name = "hmac-sha512-chcr",
 				.cra_blocksize = SHA512_BLOCK_SIZE,
 			}
 		}
 	},
+	/* Add AEAD Algorithms */
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_GCM,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "gcm(aes)",
+				.cra_driver_name = "gcm-aes-chcr",
+				.cra_blocksize	= 1,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_gcm_ctx),
+			},
+			.ivsize = 12,
+			.maxauthsize = GHASH_DIGEST_SIZE,
+			.setkey = chcr_gcm_setkey,
+			.setauthsize = chcr_gcm_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "rfc4106(gcm(aes))",
+				.cra_driver_name = "rfc4106-gcm-aes-chcr",
+				.cra_blocksize	 = 1,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_gcm_ctx),
+
+			},
+			.ivsize = 8,
+			.maxauthsize	= GHASH_DIGEST_SIZE,
+			.setkey = chcr_gcm_setkey,
+			.setauthsize	= chcr_4106_4309_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_CCM,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "ccm(aes)",
+				.cra_driver_name = "ccm-aes-chcr",
+				.cra_blocksize	 = 1,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx),
+
+			},
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize	= GHASH_DIGEST_SIZE,
+			.setkey = chcr_aead_ccm_setkey,
+			.setauthsize	= chcr_ccm_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "rfc4309(ccm(aes))",
+				.cra_driver_name = "rfc4309-ccm-aes-chcr",
+				.cra_blocksize	 = 1,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx),
+
+			},
+			.ivsize = 8,
+			.maxauthsize	= GHASH_DIGEST_SIZE,
+			.setkey = chcr_aead_rfc4309_setkey,
+			.setauthsize = chcr_4106_4309_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "authenc(hmac(sha1),cbc(aes))",
+				.cra_driver_name =
+					"authenc-hmac-sha1-cbc-aes-chcr",
+				.cra_blocksize	 = AES_BLOCK_SIZE,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_authenc_ctx),
+
+			},
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA1_DIGEST_SIZE,
+			.setkey = chcr_authenc_setkey,
+			.setauthsize = chcr_authenc_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+
+				.cra_name = "authenc(hmac(sha256),cbc(aes))",
+				.cra_driver_name =
+					"authenc-hmac-sha256-cbc-aes-chcr",
+				.cra_blocksize	 = AES_BLOCK_SIZE,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_authenc_ctx),
+
+			},
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize	= SHA256_DIGEST_SIZE,
+			.setkey = chcr_authenc_setkey,
+			.setauthsize = chcr_authenc_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "authenc(hmac(sha224),cbc(aes))",
+				.cra_driver_name =
+					"authenc-hmac-sha224-cbc-aes-chcr",
+				.cra_blocksize	 = AES_BLOCK_SIZE,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_authenc_ctx),
+			},
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA224_DIGEST_SIZE,
+			.setkey = chcr_authenc_setkey,
+			.setauthsize = chcr_authenc_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "authenc(hmac(sha384),cbc(aes))",
+				.cra_driver_name =
+					"authenc-hmac-sha384-cbc-aes-chcr",
+				.cra_blocksize	 = AES_BLOCK_SIZE,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_authenc_ctx),
+
+			},
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA384_DIGEST_SIZE,
+			.setkey = chcr_authenc_setkey,
+			.setauthsize = chcr_authenc_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "authenc(hmac(sha512),cbc(aes))",
+				.cra_driver_name =
+					"authenc-hmac-sha512-cbc-aes-chcr",
+				.cra_blocksize	 = AES_BLOCK_SIZE,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_authenc_ctx),
+
+			},
+			.ivsize = AES_BLOCK_SIZE,
+			.maxauthsize = SHA512_DIGEST_SIZE,
+			.setkey = chcr_authenc_setkey,
+			.setauthsize = chcr_authenc_setauthsize,
+		}
+	},
+	{
+		.type = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_SUB_TYPE_AEAD_NULL,
+		.is_registered = 0,
+		.alg.aead = {
+			.base = {
+				.cra_name = "authenc(digest_null,cbc(aes))",
+				.cra_driver_name =
+					"authenc-digest_null-cbc-aes-chcr",
+				.cra_blocksize	 = AES_BLOCK_SIZE,
+				.cra_ctxsize =	sizeof(struct chcr_context) +
+						sizeof(struct chcr_aead_ctx) +
+						sizeof(struct chcr_authenc_ctx),
+
+			},
+			.ivsize  = AES_BLOCK_SIZE,
+			.maxauthsize = 0,
+			.setkey  = chcr_aead_digest_null_setkey,
+			.setauthsize = chcr_authenc_null_setauthsize,
+		}
+	},
 };
 
 /*
@@ -1422,6 +2874,11 @@ static int chcr_unregister_alg(void)
 				crypto_unregister_alg(
 						&driver_algs[i].alg.crypto);
 			break;
+		case CRYPTO_ALG_TYPE_AEAD:
+			if (driver_algs[i].is_registered)
+				crypto_unregister_aead(
+						&driver_algs[i].alg.aead);
+			break;
 		case CRYPTO_ALG_TYPE_AHASH:
 			if (driver_algs[i].is_registered)
 				crypto_unregister_ahash(
@@ -1456,6 +2913,19 @@ static int chcr_register_alg(void)
 			err = crypto_register_alg(&driver_algs[i].alg.crypto);
 			name = driver_algs[i].alg.crypto.cra_driver_name;
 			break;
+		case CRYPTO_ALG_TYPE_AEAD:
+			driver_algs[i].alg.aead.base.cra_priority =
+				CHCR_CRA_PRIORITY;
+			driver_algs[i].alg.aead.base.cra_flags =
+				CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
+			driver_algs[i].alg.aead.encrypt = chcr_aead_encrypt;
+			driver_algs[i].alg.aead.decrypt = chcr_aead_decrypt;
+			driver_algs[i].alg.aead.init = chcr_aead_cra_init;
+			driver_algs[i].alg.aead.exit = chcr_aead_cra_exit;
+			driver_algs[i].alg.aead.base.cra_module = THIS_MODULE;
+			err = crypto_register_aead(&driver_algs[i].alg.aead);
+			name = driver_algs[i].alg.aead.base.cra_driver_name;
+			break;
 		case CRYPTO_ALG_TYPE_AHASH:
 			a_hash = &driver_algs[i].alg.hash;
 			a_hash->update = chcr_ahash_update;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_algo.h linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_algo.h
--- linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_algo.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_algo.h	2017-02-12 16:03:20.000000000 -0500
@@ -108,30 +108,24 @@
 #define IPAD_DATA 0x36363636
 #define OPAD_DATA 0x5c5c5c5c
 
-#define TRANSHDR_SIZE(alignedkctx_len)\
-	(sizeof(struct ulptx_idata) +\
-	 sizeof(struct ulp_txpkt) +\
-	 sizeof(struct fw_crypto_lookaside_wr) +\
-	 sizeof(struct cpl_tx_sec_pdu) +\
-	 (alignedkctx_len))
-#define CIPHER_TRANSHDR_SIZE(alignedkctx_len, sge_pairs) \
-	(TRANSHDR_SIZE(alignedkctx_len) + sge_pairs +\
+#define TRANSHDR_SIZE(kctx_len)\
+	(sizeof(struct chcr_wr) +\
+	 kctx_len)
+#define CIPHER_TRANSHDR_SIZE(kctx_len, sge_pairs) \
+	(TRANSHDR_SIZE((kctx_len)) + (sge_pairs) +\
 	 sizeof(struct cpl_rx_phys_dsgl))
-#define HASH_TRANSHDR_SIZE(alignedkctx_len)\
-	(TRANSHDR_SIZE(alignedkctx_len) + DUMMY_BYTES)
+#define HASH_TRANSHDR_SIZE(kctx_len)\
+	(TRANSHDR_SIZE(kctx_len) + DUMMY_BYTES)
 
-#define SEC_CPL_OFFSET (sizeof(struct fw_crypto_lookaside_wr) + \
-			sizeof(struct ulp_txpkt) + \
-			sizeof(struct ulptx_idata))
 
-#define FILL_SEC_CPL_OP_IVINSR(id, len, hldr, ofst)      \
+#define FILL_SEC_CPL_OP_IVINSR(id, len, ofst)      \
 	htonl( \
 	       CPL_TX_SEC_PDU_OPCODE_V(CPL_TX_SEC_PDU) | \
 	       CPL_TX_SEC_PDU_RXCHID_V((id)) | \
 	       CPL_TX_SEC_PDU_ACKFOLLOWS_V(0) | \
 	       CPL_TX_SEC_PDU_ULPTXLPBK_V(1) | \
 	       CPL_TX_SEC_PDU_CPLLEN_V((len)) | \
-	       CPL_TX_SEC_PDU_PLACEHOLDER_V((hldr)) | \
+	       CPL_TX_SEC_PDU_PLACEHOLDER_V(0) | \
 	       CPL_TX_SEC_PDU_IVINSRTOFST_V((ofst)))
 
 #define  FILL_SEC_CPL_CIPHERSTOP_HI(a_start, a_stop, c_start, c_stop_hi) \
@@ -148,7 +142,7 @@
 		CPL_TX_SEC_PDU_AUTHSTOP_V((a_stop)) | \
 		CPL_TX_SEC_PDU_AUTHINSERT_V((a_inst)))
 
-#define  FILL_SEC_CPL_SCMD0_SEQNO(ctrl, seq, cmode, amode, opad, size, nivs)  \
+#define  FILL_SEC_CPL_SCMD0_SEQNO(ctrl, seq, cmode, amode, opad, size)  \
 		htonl( \
 		SCMD_SEQ_NO_CTRL_V(0) | \
 		SCMD_STATUS_PRESENT_V(0) | \
@@ -159,7 +153,7 @@
 		SCMD_AUTH_MODE_V((amode)) | \
 		SCMD_HMAC_CTRL_V((opad)) | \
 		SCMD_IV_SIZE_V((size)) | \
-		SCMD_NUM_IVS_V((nivs)))
+		SCMD_NUM_IVS_V(0))
 
 #define FILL_SEC_CPL_IVGEN_HDRLEN(last, more, ctx_in, mac, ivdrop, len) htonl( \
 		SCMD_ENB_DBGID_V(0) | \
@@ -264,13 +258,15 @@ enum {
  * where they indicate the size of the integrity check value (ICV)
  */
 enum {
-	AES_CCM_ICV_4   = 4,
-	AES_CCM_ICV_6   = 6,
-	AES_CCM_ICV_8   = 8,
-	AES_CCM_ICV_10  = 10,
-	AES_CCM_ICV_12  = 12,
-	AES_CCM_ICV_14  = 14,
-	AES_CCM_ICV_16 = 16
+	ICV_4  = 4,
+	ICV_6  = 6,
+	ICV_8  = 8,
+	ICV_10 = 10,
+	ICV_12 = 12,
+	ICV_13 = 13,
+	ICV_14 = 14,
+	ICV_15 = 15,
+	ICV_16 = 16
 };
 
 struct hash_op_params {
@@ -394,7 +390,7 @@ static const u8 aes_sbox[256] = {
 	187, 22
 };
 
-static u32 aes_ks_subword(const u32 w)
+static inline u32 aes_ks_subword(const u32 w)
 {
 	u8 bytes[4];
 
@@ -412,61 +408,4 @@ static u32 round_constant[11] = {
 	0x1B000000, 0x36000000, 0x6C000000
 };
 
-/* dec_key - OUTPUT - Reverse round key
- * key - INPUT - key
- * keylength - INPUT - length of the key in number of bits
- */
-static inline void get_aes_decrypt_key(unsigned char *dec_key,
-				       const unsigned char *key,
-				       unsigned int keylength)
-{
-	u32 temp;
-	u32 w_ring[MAX_NK];
-	int i, j, k;
-	u8  nr, nk;
-
-	switch (keylength) {
-	case AES_KEYLENGTH_128BIT:
-		nk = KEYLENGTH_4BYTES;
-		nr = NUMBER_OF_ROUNDS_10;
-		break;
-
-	case AES_KEYLENGTH_192BIT:
-		nk = KEYLENGTH_6BYTES;
-		nr = NUMBER_OF_ROUNDS_12;
-		break;
-	case AES_KEYLENGTH_256BIT:
-		nk = KEYLENGTH_8BYTES;
-		nr = NUMBER_OF_ROUNDS_14;
-		break;
-	default:
-		return;
-	}
-	for (i = 0; i < nk; i++ )
-		w_ring[i] = be32_to_cpu(*(u32 *)&key[4 * i]);
-
-	i = 0;
-	temp = w_ring[nk - 1];
-	while(i + nk < (nr + 1) * 4) {
-		if(!(i % nk)) {
-			/* RotWord(temp) */
-			temp = (temp << 8) | (temp >> 24);
-			temp = aes_ks_subword(temp);
-			temp ^= round_constant[i / nk];
-		}
-		else if (nk == 8 && (i % 4 == 0))
-			temp = aes_ks_subword(temp);
-		w_ring[i % nk] ^= temp;
-		temp = w_ring[i % nk];
-		i++;
-	}
-	i--;
-	for (k = 0, j = i % nk; k < nk; k++) {
-		*((u32 *)dec_key + k) = htonl(w_ring[j]);
-		j--;
-		if(j < 0)
-			j += nk;
-	}
-}
-
 #endif /* __CHCR_ALGO_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_core.c linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_core.c
--- linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,7 @@ static chcr_handler_func work_handlers[N
 static struct cxgb4_uld_info chcr_uld_info = {
 	.name = DRV_MODULE_NAME,
 	.nrxq = MAX_ULD_QSETS,
+	.ntxq = MAX_ULD_QSETS,
 	.rxq_size = 1024,
 	.add = chcr_uld_add,
 	.state_change = chcr_uld_state_change,
@@ -51,6 +52,7 @@ static struct cxgb4_uld_info chcr_uld_in
 int assign_chcr_device(struct chcr_dev **dev)
 {
 	struct uld_ctx *u_ctx;
+	int ret = -ENXIO;
 
 	/*
 	 * Which device to use if multiple devices are available TODO
@@ -58,15 +60,14 @@ int assign_chcr_device(struct chcr_dev *
 	 * must go to the same device to maintain the ordering.
 	 */
 	mutex_lock(&dev_mutex); /* TODO ? */
-	u_ctx = list_first_entry(&uld_ctx_list, struct uld_ctx, entry);
-	if (!u_ctx) {
-		mutex_unlock(&dev_mutex);
-		return -ENXIO;
+	list_for_each_entry(u_ctx, &uld_ctx_list, entry)
+		if (u_ctx && u_ctx->dev) {
+			*dev = u_ctx->dev;
+			ret = 0;
+			break;
 	}
-
-	*dev = u_ctx->dev;
 	mutex_unlock(&dev_mutex);
-	return 0;
+	return ret;
 }
 
 static int chcr_dev_add(struct uld_ctx *u_ctx)
@@ -109,14 +110,12 @@ static int cpl_fw6_pld_handler(struct ch
 	if (ack_err_status) {
 		if (CHK_MAC_ERR_BIT(ack_err_status) ||
 		    CHK_PAD_ERR_BIT(ack_err_status))
-			error_status = -EINVAL;
+			error_status = -EBADMSG;
 	}
 	/* call completion callback with failure status */
 	if (req) {
-		if (!chcr_handle_resp(req, input, error_status))
-			req->complete(req, error_status);
-		else
-			return -EINVAL;
+		error_status = chcr_handle_resp(req, input, error_status);
+		req->complete(req, error_status);
 	} else {
 		pr_err("Incorrect request address from the firmware\n");
 		return -EFAULT;
@@ -126,7 +125,7 @@ static int cpl_fw6_pld_handler(struct ch
 
 int chcr_send_wr(struct sk_buff *skb)
 {
-	return cxgb4_ofld_send(skb->dev, skb);
+	return cxgb4_crypto_send(skb->dev, skb);
 }
 
 static void *chcr_uld_add(const struct cxgb4_lld_info *lld)
@@ -203,10 +202,8 @@ static int chcr_uld_state_change(void *h
 
 static int __init chcr_crypto_init(void)
 {
-	if (cxgb4_register_uld(CXGB4_ULD_CRYPTO, &chcr_uld_info)) {
+	if (cxgb4_register_uld(CXGB4_ULD_CRYPTO, &chcr_uld_info))
 		pr_err("ULD register fail: No chcr crypto support in cxgb4");
-		return -1;
-	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_core.h linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_core.h
--- linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_core.h	2017-02-12 16:03:20.000000000 -0500
@@ -52,13 +52,27 @@
 
 #define MAC_ERROR_BIT		0
 #define CHK_MAC_ERR_BIT(x)	(((x) >> MAC_ERROR_BIT) & 1)
+#define MAX_SALT                4
 
 struct uld_ctx;
 
+struct _key_ctx {
+	__be32 ctx_hdr;
+	u8 salt[MAX_SALT];
+	__be64 reserverd;
+	unsigned char key[0];
+};
+
+struct chcr_wr {
+	struct fw_crypto_lookaside_wr wreq;
+	struct ulp_txpkt ulptx;
+	struct ulptx_idata sc_imm;
+	struct cpl_tx_sec_pdu sec_cpl;
+	struct _key_ctx key_ctx;
+};
+
 struct chcr_dev {
-	/* Request submited to h/w and waiting for response. */
 	spinlock_t lock_chcr_dev;
-	struct crypto_queue pending_queue;
 	struct uld_ctx *u_ctx;
 	unsigned char tx_channel_id;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_crypto.h linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_crypto.h
--- linux-libre-4.9-gnu/drivers/crypto/chelsio/chcr_crypto.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/chcr_crypto.h	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,14 @@
 #ifndef __CHCR_CRYPTO_H__
 #define __CHCR_CRYPTO_H__
 
+#define GHASH_BLOCK_SIZE    16
+#define GHASH_DIGEST_SIZE   16
+
+#define CCM_B0_SIZE             16
+#define CCM_AAD_FIELD_SIZE      2
+#define T5_MAX_AAD_SIZE 512
+
+
 /* Define following if h/w is not dropping the AAD and IV data before
  * giving the processed data
  */
@@ -63,22 +71,36 @@
 #define CHCR_SCMD_AUTH_CTRL_AUTH_CIPHER 0
 #define CHCR_SCMD_AUTH_CTRL_CIPHER_AUTH 1
 
-#define CHCR_SCMD_CIPHER_MODE_NOP           0
-#define CHCR_SCMD_CIPHER_MODE_AES_CBC       1
-#define CHCR_SCMD_CIPHER_MODE_GENERIC_AES   4
-#define CHCR_SCMD_CIPHER_MODE_AES_XTS       6
+#define CHCR_SCMD_CIPHER_MODE_NOP               0
+#define CHCR_SCMD_CIPHER_MODE_AES_CBC           1
+#define CHCR_SCMD_CIPHER_MODE_AES_GCM           2
+#define CHCR_SCMD_CIPHER_MODE_AES_CTR           3
+#define CHCR_SCMD_CIPHER_MODE_GENERIC_AES       4
+#define CHCR_SCMD_CIPHER_MODE_AES_XTS           6
+#define CHCR_SCMD_CIPHER_MODE_AES_CCM           7
 
 #define CHCR_SCMD_AUTH_MODE_NOP             0
 #define CHCR_SCMD_AUTH_MODE_SHA1            1
 #define CHCR_SCMD_AUTH_MODE_SHA224          2
 #define CHCR_SCMD_AUTH_MODE_SHA256          3
+#define CHCR_SCMD_AUTH_MODE_GHASH           4
 #define CHCR_SCMD_AUTH_MODE_SHA512_224      5
 #define CHCR_SCMD_AUTH_MODE_SHA512_256      6
 #define CHCR_SCMD_AUTH_MODE_SHA512_384      7
 #define CHCR_SCMD_AUTH_MODE_SHA512_512      8
+#define CHCR_SCMD_AUTH_MODE_CBCMAC          9
+#define CHCR_SCMD_AUTH_MODE_CMAC            10
 
 #define CHCR_SCMD_HMAC_CTRL_NOP             0
 #define CHCR_SCMD_HMAC_CTRL_NO_TRUNC        1
+#define CHCR_SCMD_HMAC_CTRL_TRUNC_RFC4366   2
+#define CHCR_SCMD_HMAC_CTRL_IPSEC_96BIT     3
+#define CHCR_SCMD_HMAC_CTRL_PL1		    4
+#define CHCR_SCMD_HMAC_CTRL_PL2		    5
+#define CHCR_SCMD_HMAC_CTRL_PL3		    6
+#define CHCR_SCMD_HMAC_CTRL_DIV2	    7
+#define VERIFY_HW 0
+#define VERIFY_SW 1
 
 #define CHCR_SCMD_IVGEN_CTRL_HW             0
 #define CHCR_SCMD_IVGEN_CTRL_SW             1
@@ -106,39 +128,77 @@
 #define IV_IMMEDIATE            1
 #define IV_DSGL			2
 
+#define AEAD_H_SIZE             16
+
 #define CRYPTO_ALG_SUB_TYPE_MASK            0x0f000000
 #define CRYPTO_ALG_SUB_TYPE_HASH_HMAC       0x01000000
+#define CRYPTO_ALG_SUB_TYPE_AEAD_RFC4106    0x02000000
+#define CRYPTO_ALG_SUB_TYPE_AEAD_GCM	    0x03000000
+#define CRYPTO_ALG_SUB_TYPE_AEAD_AUTHENC    0x04000000
+#define CRYPTO_ALG_SUB_TYPE_AEAD_CCM        0x05000000
+#define CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309    0x06000000
+#define CRYPTO_ALG_SUB_TYPE_AEAD_NULL       0x07000000
+#define CRYPTO_ALG_SUB_TYPE_CTR             0x08000000
 #define CRYPTO_ALG_TYPE_HMAC (CRYPTO_ALG_TYPE_AHASH |\
 			      CRYPTO_ALG_SUB_TYPE_HASH_HMAC)
 
-#define MAX_SALT                4
 #define MAX_SCRATCH_PAD_SIZE    32
 
 #define CHCR_HASH_MAX_BLOCK_SIZE_64  64
 #define CHCR_HASH_MAX_BLOCK_SIZE_128 128
 
 /* Aligned to 128 bit boundary */
-struct _key_ctx {
-	__be32 ctx_hdr;
-	u8 salt[MAX_SALT];
-	__be64 reserverd;
-	unsigned char key[0];
-};
 
 struct ablk_ctx {
-	u8 enc;
-	unsigned int processed_len;
 	__be32 key_ctx_hdr;
 	unsigned int enckey_len;
-	unsigned int dst_nents;
-	struct scatterlist iv_sg;
 	u8 key[CHCR_AES_MAX_KEY_LEN];
-	u8 iv[CHCR_MAX_CRYPTO_IV_LEN];
 	unsigned char ciph_mode;
+	u8 rrkey[AES_MAX_KEY_SIZE];
+};
+struct chcr_aead_reqctx {
+	struct	sk_buff	*skb;
+	struct scatterlist *dst;
+	struct scatterlist srcffwd[2];
+	struct scatterlist dstffwd[2];
+	short int dst_nents;
+	u16 verify;
+	u8 iv[CHCR_MAX_CRYPTO_IV_LEN];
+	unsigned char scratch_pad[MAX_SCRATCH_PAD_SIZE];
+};
+
+struct chcr_gcm_ctx {
+	u8 ghash_h[AEAD_H_SIZE];
+};
+
+struct chcr_authenc_ctx {
+	u8 dec_rrkey[AES_MAX_KEY_SIZE];
+	u8 h_iopad[2 * CHCR_HASH_MAX_DIGEST_SIZE];
+	unsigned char auth_mode;
+};
+
+struct __aead_ctx {
+	struct chcr_gcm_ctx gcm[0];
+	struct chcr_authenc_ctx authenc[0];
 };
 
+
+
+struct chcr_aead_ctx {
+	__be32 key_ctx_hdr;
+	unsigned int enckey_len;
+	struct crypto_skcipher *null;
+	u8 salt[MAX_SALT];
+	u8 key[CHCR_AES_MAX_KEY_LEN];
+	u16 hmac_ctrl;
+	u16 mayverify;
+	struct	__aead_ctx ctx[0];
+};
+
+
+
 struct hmac_ctx {
-	struct shash_desc *desc;
+	struct crypto_shash *base_hash;
 	u8 ipad[CHCR_HASH_MAX_BLOCK_SIZE_128];
 	u8 opad[CHCR_HASH_MAX_BLOCK_SIZE_128];
 };
@@ -146,6 +206,7 @@ struct hmac_ctx {
 struct __crypto_ctx {
 	struct hmac_ctx hmacctx[0];
 	struct ablk_ctx ablkctx[0];
+	struct chcr_aead_ctx aeadctx[0];
 };
 
 struct chcr_context {
@@ -156,18 +217,22 @@ struct chcr_context {
 
 struct chcr_ahash_req_ctx {
 	u32 result;
-	char bfr[CHCR_HASH_MAX_BLOCK_SIZE_128];
-	u8 bfr_len;
+	u8 bfr1[CHCR_HASH_MAX_BLOCK_SIZE_128];
+	u8 bfr2[CHCR_HASH_MAX_BLOCK_SIZE_128];
+	u8 *reqbfr;
+	u8 *skbfr;
+	u8 reqlen;
 	/* DMA the partial hash in it */
 	u8 partial_hash[CHCR_HASH_MAX_DIGEST_SIZE];
 	u64 data_len;  /* Data len till time */
-	void *dummy_payload_ptr;
 	/* SKB which is being sent to the hardware for processing */
 	struct sk_buff *skb;
 };
 
 struct chcr_blkcipher_req_ctx {
 	struct sk_buff *skb;
+	unsigned int dst_nents;
+	u8 iv[CHCR_MAX_CRYPTO_IV_LEN];
 };
 
 struct chcr_alg_template {
@@ -176,16 +241,19 @@ struct chcr_alg_template {
 	union {
 		struct crypto_alg crypto;
 		struct ahash_alg hash;
+		struct aead_alg aead;
 	} alg;
 };
 
 struct chcr_req_ctx {
 	union {
 		struct ahash_request *ahash_req;
+		struct aead_request *aead_req;
 		struct ablkcipher_request *ablk_req;
 	} req;
 	union {
 		struct chcr_ahash_req_ctx *ahash_ctx;
+		struct chcr_aead_reqctx *reqctx;
 		struct chcr_blkcipher_req_ctx *ablk_ctx;
 	} ctx;
 };
@@ -195,9 +263,15 @@ struct sge_opaque_hdr {
 	dma_addr_t addr[MAX_SKB_FRAGS + 1];
 };
 
-typedef struct sk_buff *(*create_wr_t)(struct crypto_async_request *req,
-				       struct chcr_context *ctx,
+typedef struct sk_buff *(*create_wr_t)(struct aead_request *req,
 				       unsigned short qid,
+				       int size,
 				       unsigned short op_type);
 
+static int chcr_aead_op(struct aead_request *req_base,
+			  unsigned short op_type,
+			  int size,
+			  create_wr_t create_wr_fn);
+static inline int get_aead_subtype(struct crypto_aead *aead);
+
 #endif /* __CHCR_CRYPTO_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/chelsio/Kconfig linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/Kconfig
--- linux-libre-4.9-gnu/drivers/crypto/chelsio/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/chelsio/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -4,6 +4,7 @@ config CRYPTO_DEV_CHELSIO
 	select CRYPTO_SHA1
 	select CRYPTO_SHA256
 	select CRYPTO_SHA512
+	select CRYPTO_AUTHENC
 	---help---
 	  The Chelsio Crypto Co-processor driver for T6 adapters.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/Kconfig linux-libre-4.10-rc8-gnu/drivers/crypto/Kconfig
--- linux-libre-4.9-gnu/drivers/crypto/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -555,4 +555,6 @@ config CRYPTO_DEV_ROCKCHIP
 
 source "drivers/crypto/chelsio/Kconfig"
 
+source "drivers/crypto/virtio/Kconfig"
+
 endif # CRYPTO_HW
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/Makefile linux-libre-4.10-rc8-gnu/drivers/crypto/Makefile
--- linux-libre-4.9-gnu/drivers/crypto/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -32,3 +32,4 @@ obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
 obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sunxi-ss/
 obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/
 obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/
+obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/marvell/cesa.c linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/cesa.c
--- linux-libre-4.9-gnu/drivers/crypto/marvell/cesa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/cesa.c	2017-02-12 16:03:20.000000000 -0500
@@ -375,10 +375,6 @@ static int mv_cesa_dev_dma_init(struct m
 	if (!dma->padding_pool)
 		return -ENOMEM;
 
-	dma->iv_pool = dmam_pool_create("cesa_iv", dev, 16, 1, 0);
-	if (!dma->iv_pool)
-		return -ENOMEM;
-
 	cesa->dma = dma;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/marvell/cesa.h linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/cesa.h
--- linux-libre-4.9-gnu/drivers/crypto/marvell/cesa.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/cesa.h	2017-02-12 16:03:20.000000000 -0500
@@ -273,11 +273,12 @@ struct mv_cesa_op_ctx {
 #define CESA_TDMA_SRC_IN_SRAM			BIT(30)
 #define CESA_TDMA_END_OF_REQ			BIT(29)
 #define CESA_TDMA_BREAK_CHAIN			BIT(28)
-#define CESA_TDMA_TYPE_MSK			GENMASK(27, 0)
+#define CESA_TDMA_SET_STATE			BIT(27)
+#define CESA_TDMA_TYPE_MSK			GENMASK(26, 0)
 #define CESA_TDMA_DUMMY				0
 #define CESA_TDMA_DATA				1
 #define CESA_TDMA_OP				2
-#define CESA_TDMA_IV				3
+#define CESA_TDMA_RESULT			3
 
 /**
  * struct mv_cesa_tdma_desc - TDMA descriptor
@@ -393,7 +394,6 @@ struct mv_cesa_dev_dma {
 	struct dma_pool *op_pool;
 	struct dma_pool *cache_pool;
 	struct dma_pool *padding_pool;
-	struct dma_pool *iv_pool;
 };
 
 /**
@@ -839,7 +839,7 @@ mv_cesa_tdma_desc_iter_init(struct mv_ce
 	memset(chain, 0, sizeof(*chain));
 }
 
-int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
+int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
 			  u32 size, u32 flags, gfp_t gfp_flags);
 
 struct mv_cesa_op_ctx *mv_cesa_dma_add_op(struct mv_cesa_tdma_chain *chain,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/marvell/cipher.c linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/cipher.c
--- linux-libre-4.9-gnu/drivers/crypto/marvell/cipher.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/cipher.c	2017-02-12 16:03:20.000000000 -0500
@@ -212,7 +212,8 @@ mv_cesa_ablkcipher_complete(struct crypt
 		struct mv_cesa_req *basereq;
 
 		basereq = &creq->base;
-		memcpy(ablkreq->info, basereq->chain.last->data, ivsize);
+		memcpy(ablkreq->info, basereq->chain.last->op->ctx.blkcipher.iv,
+		       ivsize);
 	} else {
 		memcpy_fromio(ablkreq->info,
 			      engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
@@ -373,8 +374,9 @@ static int mv_cesa_ablkcipher_dma_req_in
 
 	/* Add output data for IV */
 	ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
-	ret = mv_cesa_dma_add_iv_op(&basereq->chain, CESA_SA_CRYPT_IV_SRAM_OFFSET,
-				    ivsize, CESA_TDMA_SRC_IN_SRAM, flags);
+	ret = mv_cesa_dma_add_result_op(&basereq->chain, CESA_SA_CFG_SRAM_OFFSET,
+				    CESA_SA_DATA_SRAM_OFFSET,
+				    CESA_TDMA_SRC_IN_SRAM, flags);
 
 	if (ret)
 		goto err_free_tdma;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/marvell/hash.c linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/hash.c
--- linux-libre-4.9-gnu/drivers/crypto/marvell/hash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/hash.c	2017-02-12 16:03:20.000000000 -0500
@@ -280,13 +280,32 @@ static void mv_cesa_ahash_std_prepare(st
 	sreq->offset = 0;
 }
 
+static void mv_cesa_ahash_dma_step(struct ahash_request *req)
+{
+	struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
+	struct mv_cesa_req *base = &creq->base;
+
+	/* We must explicitly set the digest state. */
+	if (base->chain.first->flags & CESA_TDMA_SET_STATE) {
+		struct mv_cesa_engine *engine = base->engine;
+		int i;
+
+		/* Set the hash state in the IVDIG regs. */
+		for (i = 0; i < ARRAY_SIZE(creq->state); i++)
+			writel_relaxed(creq->state[i], engine->regs +
+				       CESA_IVDIG(i));
+	}
+
+	mv_cesa_dma_step(base);
+}
+
 static void mv_cesa_ahash_step(struct crypto_async_request *req)
 {
 	struct ahash_request *ahashreq = ahash_request_cast(req);
 	struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
 
 	if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
-		mv_cesa_dma_step(&creq->base);
+		mv_cesa_ahash_dma_step(ahashreq);
 	else
 		mv_cesa_ahash_std_step(ahashreq);
 }
@@ -311,24 +330,40 @@ static void mv_cesa_ahash_complete(struc
 	int i;
 
 	digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
-	for (i = 0; i < digsize / 4; i++)
-		creq->state[i] = readl_relaxed(engine->regs + CESA_IVDIG(i));
 
-	if (creq->last_req) {
+	if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ &&
+	    (creq->base.chain.last->flags & CESA_TDMA_TYPE_MSK) == CESA_TDMA_RESULT) {
+		__le32 *data = NULL;
+
 		/*
-		 * Hardware's MD5 digest is in little endian format, but
-		 * SHA in big endian format
+		 * Result is already in the correct endianess when the SA is
+		 * used
 		 */
-		if (creq->algo_le) {
-			__le32 *result = (void *)ahashreq->result;
+		data = creq->base.chain.last->op->ctx.hash.hash;
+		for (i = 0; i < digsize / 4; i++)
+			creq->state[i] = cpu_to_le32(data[i]);
 
-			for (i = 0; i < digsize / 4; i++)
-				result[i] = cpu_to_le32(creq->state[i]);
-		} else {
-			__be32 *result = (void *)ahashreq->result;
+		memcpy(ahashreq->result, data, digsize);
+	} else {
+		for (i = 0; i < digsize / 4; i++)
+			creq->state[i] = readl_relaxed(engine->regs +
+						       CESA_IVDIG(i));
+		if (creq->last_req) {
+			/*
+			* Hardware's MD5 digest is in little endian format, but
+			* SHA in big endian format
+			*/
+			if (creq->algo_le) {
+				__le32 *result = (void *)ahashreq->result;
 
-			for (i = 0; i < digsize / 4; i++)
-				result[i] = cpu_to_be32(creq->state[i]);
+				for (i = 0; i < digsize / 4; i++)
+					result[i] = cpu_to_le32(creq->state[i]);
+			} else {
+				__be32 *result = (void *)ahashreq->result;
+
+				for (i = 0; i < digsize / 4; i++)
+					result[i] = cpu_to_be32(creq->state[i]);
+			}
 		}
 	}
 
@@ -503,6 +538,12 @@ mv_cesa_ahash_dma_last_req(struct mv_ces
 						CESA_SA_DESC_CFG_LAST_FRAG,
 				      CESA_SA_DESC_CFG_FRAG_MSK);
 
+		ret = mv_cesa_dma_add_result_op(chain,
+						CESA_SA_CFG_SRAM_OFFSET,
+						CESA_SA_DATA_SRAM_OFFSET,
+						CESA_TDMA_SRC_IN_SRAM, flags);
+		if (ret)
+			return ERR_PTR(-ENOMEM);
 		return op;
 	}
 
@@ -562,11 +603,16 @@ static int mv_cesa_ahash_dma_req_init(st
 	struct mv_cesa_ahash_dma_iter iter;
 	struct mv_cesa_op_ctx *op = NULL;
 	unsigned int frag_len;
+	bool set_state = false;
 	int ret;
+	u32 type;
 
 	basereq->chain.first = NULL;
 	basereq->chain.last = NULL;
 
+	if (!mv_cesa_mac_op_is_first_frag(&creq->op_tmpl))
+		set_state = true;
+
 	if (creq->src_nents) {
 		ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents,
 				 DMA_TO_DEVICE);
@@ -634,7 +680,15 @@ static int mv_cesa_ahash_dma_req_init(st
 		goto err_free_tdma;
 	}
 
-	if (op) {
+	/*
+	 * If results are copied via DMA, this means that this
+	 * request can be directly processed by the engine,
+	 * without partial updates. So we can chain it at the
+	 * DMA level with other requests.
+	 */
+	type = basereq->chain.last->flags & CESA_TDMA_TYPE_MSK;
+
+	if (op && type != CESA_TDMA_RESULT) {
 		/* Add dummy desc to wait for crypto operation end */
 		ret = mv_cesa_dma_add_dummy_end(&basereq->chain, flags);
 		if (ret)
@@ -647,8 +701,19 @@ static int mv_cesa_ahash_dma_req_init(st
 	else
 		creq->cache_ptr = 0;
 
-	basereq->chain.last->flags |= (CESA_TDMA_END_OF_REQ |
-				       CESA_TDMA_BREAK_CHAIN);
+	basereq->chain.last->flags |= CESA_TDMA_END_OF_REQ;
+
+	if (type != CESA_TDMA_RESULT)
+		basereq->chain.last->flags |= CESA_TDMA_BREAK_CHAIN;
+
+	if (set_state) {
+		/*
+		 * Put the CESA_TDMA_SET_STATE flag on the first tdma desc to
+		 * let the step logic know that the IVDIG registers should be
+		 * explicitly set before launching a TDMA chain.
+		 */
+		basereq->chain.first->flags |= CESA_TDMA_SET_STATE;
+	}
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/marvell/tdma.c linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/tdma.c
--- linux-libre-4.9-gnu/drivers/crypto/marvell/tdma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/marvell/tdma.c	2017-02-12 16:03:20.000000000 -0500
@@ -69,9 +69,6 @@ void mv_cesa_dma_cleanup(struct mv_cesa_
 		if (type == CESA_TDMA_OP)
 			dma_pool_free(cesa_dev->dma->op_pool, tdma->op,
 				      le32_to_cpu(tdma->src));
-		else if (type == CESA_TDMA_IV)
-			dma_pool_free(cesa_dev->dma->iv_pool, tdma->data,
-				      le32_to_cpu(tdma->dst));
 
 		tdma = tdma->next;
 		dma_pool_free(cesa_dev->dma->tdma_desc_pool, old_tdma,
@@ -112,7 +109,14 @@ void mv_cesa_tdma_chain(struct mv_cesa_e
 		last->next = dreq->chain.first;
 		engine->chain.last = dreq->chain.last;
 
-		if (!(last->flags & CESA_TDMA_BREAK_CHAIN))
+		/*
+		 * Break the DMA chain if the CESA_TDMA_BREAK_CHAIN is set on
+		 * the last element of the current chain, or if the request
+		 * being queued needs the IV regs to be set before lauching
+		 * the request.
+		 */
+		if (!(last->flags & CESA_TDMA_BREAK_CHAIN) &&
+		    !(dreq->chain.first->flags & CESA_TDMA_SET_STATE))
 			last->next_dma = dreq->chain.first->cur_dma;
 	}
 }
@@ -209,29 +213,37 @@ mv_cesa_dma_add_desc(struct mv_cesa_tdma
 	return new_tdma;
 }
 
-int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
+int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
 			  u32 size, u32 flags, gfp_t gfp_flags)
 {
-
-	struct mv_cesa_tdma_desc *tdma;
-	u8 *iv;
-	dma_addr_t dma_handle;
+	struct mv_cesa_tdma_desc *tdma, *op_desc;
 
 	tdma = mv_cesa_dma_add_desc(chain, gfp_flags);
 	if (IS_ERR(tdma))
 		return PTR_ERR(tdma);
 
-	iv = dma_pool_alloc(cesa_dev->dma->iv_pool, gfp_flags, &dma_handle);
-	if (!iv)
-		return -ENOMEM;
+	/* We re-use an existing op_desc object to retrieve the context
+	 * and result instead of allocating a new one.
+	 * There is at least one object of this type in a CESA crypto
+	 * req, just pick the first one in the chain.
+	 */
+	for (op_desc = chain->first; op_desc; op_desc = op_desc->next) {
+		u32 type = op_desc->flags & CESA_TDMA_TYPE_MSK;
+
+		if (type == CESA_TDMA_OP)
+			break;
+	}
+
+	if (!op_desc)
+		return -EIO;
 
 	tdma->byte_cnt = cpu_to_le32(size | BIT(31));
 	tdma->src = src;
-	tdma->dst = cpu_to_le32(dma_handle);
-	tdma->data = iv;
+	tdma->dst = op_desc->src;
+	tdma->op = op_desc->op;
 
 	flags &= (CESA_TDMA_DST_IN_SRAM | CESA_TDMA_SRC_IN_SRAM);
-	tdma->flags = flags | CESA_TDMA_IV;
+	tdma->flags = flags | CESA_TDMA_RESULT;
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/mv_cesa.c linux-libre-4.10-rc8-gnu/drivers/crypto/mv_cesa.c
--- linux-libre-4.9-gnu/drivers/crypto/mv_cesa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/mv_cesa.c	2017-02-12 16:03:20.000000000 -0500
@@ -1073,7 +1073,7 @@ static int mv_probe(struct platform_devi
 	if (!res)
 		return -ENXIO;
 
-	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
+	cp = devm_kzalloc(&pdev->dev, sizeof(*cp), GFP_KERNEL);
 	if (!cp)
 		return -ENOMEM;
 
@@ -1163,7 +1163,6 @@ err_irq:
 err_thread:
 	kthread_stop(cp->queue_th);
 err:
-	kfree(cp);
 	cpg = NULL;
 	return ret;
 }
@@ -1187,7 +1186,6 @@ static int mv_remove(struct platform_dev
 		clk_put(cp->clk);
 	}
 
-	kfree(cp);
 	cpg = NULL;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/nx/nx.c linux-libre-4.10-rc8-gnu/drivers/crypto/nx/nx.c
--- linux-libre-4.9-gnu/drivers/crypto/nx/nx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/nx/nx.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,6 @@
 #include <linux/scatterlist.h>
 #include <linux/device.h>
 #include <linux/of.h>
-#include <linux/types.h>
 #include <asm/hvcall.h>
 #include <asm/vio.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/padlock-aes.c linux-libre-4.10-rc8-gnu/drivers/crypto/padlock-aes.c
--- linux-libre-4.9-gnu/drivers/crypto/padlock-aes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/padlock-aes.c	2017-02-12 16:03:20.000000000 -0500
@@ -183,8 +183,8 @@ static inline void padlock_store_cword(s
 
 /*
  * While the padlock instructions don't use FP/SSE registers, they
- * generate a spurious DNA fault when cr0.ts is '1'. These instructions
- * should be used only inside the irq_ts_save/restore() context
+ * generate a spurious DNA fault when CR0.TS is '1'.  Fortunately,
+ * the kernel doesn't use CR0.TS.
  */
 
 static inline void rep_xcrypt_ecb(const u8 *input, u8 *output, void *key,
@@ -298,24 +298,18 @@ static inline u8 *padlock_xcrypt_cbc(con
 static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
 	struct aes_ctx *ctx = aes_ctx(tfm);
-	int ts_state;
 
 	padlock_reset_key(&ctx->cword.encrypt);
-	ts_state = irq_ts_save();
 	ecb_crypt(in, out, ctx->E, &ctx->cword.encrypt, 1);
-	irq_ts_restore(ts_state);
 	padlock_store_cword(&ctx->cword.encrypt);
 }
 
 static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
 	struct aes_ctx *ctx = aes_ctx(tfm);
-	int ts_state;
 
 	padlock_reset_key(&ctx->cword.encrypt);
-	ts_state = irq_ts_save();
 	ecb_crypt(in, out, ctx->D, &ctx->cword.decrypt, 1);
-	irq_ts_restore(ts_state);
 	padlock_store_cword(&ctx->cword.encrypt);
 }
 
@@ -346,14 +340,12 @@ static int ecb_aes_encrypt(struct blkcip
 	struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
 	struct blkcipher_walk walk;
 	int err;
-	int ts_state;
 
 	padlock_reset_key(&ctx->cword.encrypt);
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
 
-	ts_state = irq_ts_save();
 	while ((nbytes = walk.nbytes)) {
 		padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
 				   ctx->E, &ctx->cword.encrypt,
@@ -361,7 +353,6 @@ static int ecb_aes_encrypt(struct blkcip
 		nbytes &= AES_BLOCK_SIZE - 1;
 		err = blkcipher_walk_done(desc, &walk, nbytes);
 	}
-	irq_ts_restore(ts_state);
 
 	padlock_store_cword(&ctx->cword.encrypt);
 
@@ -375,14 +366,12 @@ static int ecb_aes_decrypt(struct blkcip
 	struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
 	struct blkcipher_walk walk;
 	int err;
-	int ts_state;
 
 	padlock_reset_key(&ctx->cword.decrypt);
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
 
-	ts_state = irq_ts_save();
 	while ((nbytes = walk.nbytes)) {
 		padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr,
 				   ctx->D, &ctx->cword.decrypt,
@@ -390,7 +379,6 @@ static int ecb_aes_decrypt(struct blkcip
 		nbytes &= AES_BLOCK_SIZE - 1;
 		err = blkcipher_walk_done(desc, &walk, nbytes);
 	}
-	irq_ts_restore(ts_state);
 
 	padlock_store_cword(&ctx->cword.encrypt);
 
@@ -425,14 +413,12 @@ static int cbc_aes_encrypt(struct blkcip
 	struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
 	struct blkcipher_walk walk;
 	int err;
-	int ts_state;
 
 	padlock_reset_key(&ctx->cword.encrypt);
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
 
-	ts_state = irq_ts_save();
 	while ((nbytes = walk.nbytes)) {
 		u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr,
 					    walk.dst.virt.addr, ctx->E,
@@ -442,7 +428,6 @@ static int cbc_aes_encrypt(struct blkcip
 		nbytes &= AES_BLOCK_SIZE - 1;
 		err = blkcipher_walk_done(desc, &walk, nbytes);
 	}
-	irq_ts_restore(ts_state);
 
 	padlock_store_cword(&ctx->cword.decrypt);
 
@@ -456,14 +441,12 @@ static int cbc_aes_decrypt(struct blkcip
 	struct aes_ctx *ctx = blk_aes_ctx(desc->tfm);
 	struct blkcipher_walk walk;
 	int err;
-	int ts_state;
 
 	padlock_reset_key(&ctx->cword.encrypt);
 
 	blkcipher_walk_init(&walk, dst, src, nbytes);
 	err = blkcipher_walk_virt(desc, &walk);
 
-	ts_state = irq_ts_save();
 	while ((nbytes = walk.nbytes)) {
 		padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr,
 				   ctx->D, walk.iv, &ctx->cword.decrypt,
@@ -472,8 +455,6 @@ static int cbc_aes_decrypt(struct blkcip
 		err = blkcipher_walk_done(desc, &walk, nbytes);
 	}
 
-	irq_ts_restore(ts_state);
-
 	padlock_store_cword(&ctx->cword.encrypt);
 
 	return err;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/padlock-sha.c linux-libre-4.10-rc8-gnu/drivers/crypto/padlock-sha.c
--- linux-libre-4.9-gnu/drivers/crypto/padlock-sha.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/padlock-sha.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,6 @@ static int padlock_sha1_finup(struct sha
 	struct sha1_state state;
 	unsigned int space;
 	unsigned int leftover;
-	int ts_state;
 	int err;
 
 	dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
@@ -120,14 +119,11 @@ static int padlock_sha1_finup(struct sha
 
 	memcpy(result, &state.state, SHA1_DIGEST_SIZE);
 
-	/* prevent taking the spurious DNA fault with padlock. */
-	ts_state = irq_ts_save();
 	asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */
 		      : \
 		      : "c"((unsigned long)state.count + count), \
 			"a"((unsigned long)state.count), \
 			"S"(in), "D"(result));
-	irq_ts_restore(ts_state);
 
 	padlock_output_block((uint32_t *)result, (uint32_t *)out, 5);
 
@@ -155,7 +151,6 @@ static int padlock_sha256_finup(struct s
 	struct sha256_state state;
 	unsigned int space;
 	unsigned int leftover;
-	int ts_state;
 	int err;
 
 	dctx->fallback.flags = desc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
@@ -186,14 +181,11 @@ static int padlock_sha256_finup(struct s
 
 	memcpy(result, &state.state, SHA256_DIGEST_SIZE);
 
-	/* prevent taking the spurious DNA fault with padlock. */
-	ts_state = irq_ts_save();
 	asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */
 		      : \
 		      : "c"((unsigned long)state.count + count), \
 			"a"((unsigned long)state.count), \
 			"S"(in), "D"(result));
-	irq_ts_restore(ts_state);
 
 	padlock_output_block((uint32_t *)result, (uint32_t *)out, 8);
 
@@ -312,7 +304,6 @@ static int padlock_sha1_update_nano(stru
 	u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
 		((aligned(STACK_ALIGN)));
 	u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
-	int ts_state;
 
 	partial = sctx->count & 0x3f;
 	sctx->count += len;
@@ -328,23 +319,19 @@ static int padlock_sha1_update_nano(stru
 			memcpy(sctx->buffer + partial, data,
 				done + SHA1_BLOCK_SIZE);
 			src = sctx->buffer;
-			ts_state = irq_ts_save();
 			asm volatile (".byte 0xf3,0x0f,0xa6,0xc8"
 			: "+S"(src), "+D"(dst) \
 			: "a"((long)-1), "c"((unsigned long)1));
-			irq_ts_restore(ts_state);
 			done += SHA1_BLOCK_SIZE;
 			src = data + done;
 		}
 
 		/* Process the left bytes from the input data */
 		if (len - done >= SHA1_BLOCK_SIZE) {
-			ts_state = irq_ts_save();
 			asm volatile (".byte 0xf3,0x0f,0xa6,0xc8"
 			: "+S"(src), "+D"(dst)
 			: "a"((long)-1),
 			"c"((unsigned long)((len - done) / SHA1_BLOCK_SIZE)));
-			irq_ts_restore(ts_state);
 			done += ((len - done) - (len - done) % SHA1_BLOCK_SIZE);
 			src = data + done;
 		}
@@ -401,7 +388,6 @@ static int padlock_sha256_update_nano(st
 	u8 buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
 		((aligned(STACK_ALIGN)));
 	u8 *dst = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
-	int ts_state;
 
 	partial = sctx->count & 0x3f;
 	sctx->count += len;
@@ -417,23 +403,19 @@ static int padlock_sha256_update_nano(st
 			memcpy(sctx->buf + partial, data,
 				done + SHA256_BLOCK_SIZE);
 			src = sctx->buf;
-			ts_state = irq_ts_save();
 			asm volatile (".byte 0xf3,0x0f,0xa6,0xd0"
 			: "+S"(src), "+D"(dst)
 			: "a"((long)-1), "c"((unsigned long)1));
-			irq_ts_restore(ts_state);
 			done += SHA256_BLOCK_SIZE;
 			src = data + done;
 		}
 
 		/* Process the left bytes from input data*/
 		if (len - done >= SHA256_BLOCK_SIZE) {
-			ts_state = irq_ts_save();
 			asm volatile (".byte 0xf3,0x0f,0xa6,0xd0"
 			: "+S"(src), "+D"(dst)
 			: "a"((long)-1),
 			"c"((unsigned long)((len - done) / 64)));
-			irq_ts_restore(ts_state);
 			done += ((len - done) - (len - done) % 64);
 			src = data + done;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c linux-libre-4.10-rc8-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c
--- linux-libre-4.9-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/qat/qat_c62x/adf_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -233,7 +233,7 @@ static int adf_probe(struct pci_dev *pde
 			      &hw_data->accel_capabilities_mask);
 
 	/* Find and map all the device's BARS */
-	i = 0;
+	i = (hw_data->fuses & ADF_DEVICE_FUSECTL_MASK) ? 1 : 0;
 	bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
 	for_each_set_bit(bar_nr, (const unsigned long *)&bar_mask,
 			 ADF_PCI_MAX_BARS * 2) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h linux-libre-4.10-rc8-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h
--- linux-libre-4.9-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/qat/qat_common/adf_accel_devices.h	2017-02-12 16:03:20.000000000 -0500
@@ -69,6 +69,7 @@
 #define ADF_ERRSOU5 (0x3A000 + 0xD8)
 #define ADF_DEVICE_FUSECTL_OFFSET 0x40
 #define ADF_DEVICE_LEGFUSE_OFFSET 0x4C
+#define ADF_DEVICE_FUSECTL_MASK 0x80000000
 #define ADF_PCI_MAX_BARS 3
 #define ADF_DEVICE_NAME_LENGTH 32
 #define ADF_ETR_MAX_RINGS_PER_BANK 16
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/qat/qat_common/qat_hal.c linux-libre-4.10-rc8-gnu/drivers/crypto/qat/qat_common/qat_hal.c
--- linux-libre-4.9-gnu/drivers/crypto/qat/qat_common/qat_hal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/qat/qat_common/qat_hal.c	2017-02-12 16:03:20.000000000 -0500
@@ -456,7 +456,7 @@ static int qat_hal_init_esram(struct icp
 	unsigned int csr_val;
 	int times = 30;
 
-	if (handle->pci_dev->device == ADF_C3XXX_PCI_DEVICE_ID)
+	if (handle->pci_dev->device != ADF_DH895XCC_PCI_DEVICE_ID)
 		return 0;
 
 	csr_val = ADF_CSR_RD(csr_addr, 0);
@@ -716,7 +716,7 @@ int qat_hal_init(struct adf_accel_dev *a
 		(void __iomem *)((uintptr_t)handle->hal_cap_ae_xfer_csr_addr_v +
 				 LOCAL_TO_XFER_REG_OFFSET);
 	handle->pci_dev = pci_info->pci_dev;
-	if (handle->pci_dev->device != ADF_C3XXX_PCI_DEVICE_ID) {
+	if (handle->pci_dev->device == ADF_DH895XCC_PCI_DEVICE_ID) {
 		sram_bar =
 			&pci_info->pci_bars[hw_data->get_sram_bar_id(hw_data)];
 		handle->hal_sram_addr_v = sram_bar->virt_addr;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/sahara.c linux-libre-4.10-rc8-gnu/drivers/crypto/sahara.c
--- linux-libre-4.9-gnu/drivers/crypto/sahara.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/sahara.c	2017-02-12 16:03:20.000000000 -0500
@@ -390,7 +390,7 @@ static void sahara_decode_status(struct
 	if (status & SAHARA_STATUS_MODE_BATCH)
 		dev_dbg(dev->device, "	- Batch Mode.\n");
 	else if (status & SAHARA_STATUS_MODE_DEDICATED)
-		dev_dbg(dev->device, "	- Decidated Mode.\n");
+		dev_dbg(dev->device, "	- Dedicated Mode.\n");
 	else if (status & SAHARA_STATUS_MODE_DEBUG)
 		dev_dbg(dev->device, "	- Debug Mode.\n");
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/talitos.c linux-libre-4.10-rc8-gnu/drivers/crypto/talitos.c
--- linux-libre-4.9-gnu/drivers/crypto/talitos.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/talitos.c	2017-02-12 16:03:20.000000000 -0500
@@ -590,7 +590,7 @@ static void talitos_error(struct device
 		if (v_lo & TALITOS_CCPSR_LO_MDTE)
 			dev_err(dev, "master data transfer error\n");
 		if (v_lo & TALITOS_CCPSR_LO_SGDLZ)
-			dev_err(dev, is_sec1 ? "pointeur not complete error\n"
+			dev_err(dev, is_sec1 ? "pointer not complete error\n"
 					     : "s/g data length zero error\n");
 		if (v_lo & TALITOS_CCPSR_LO_FPZ)
 			dev_err(dev, is_sec1 ? "parity error\n"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/virtio/Kconfig linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/Kconfig
--- linux-libre-4.9-gnu/drivers/crypto/virtio/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+config CRYPTO_DEV_VIRTIO
+	tristate "VirtIO crypto driver"
+	depends on VIRTIO
+	select CRYPTO_AEAD
+	select CRYPTO_AUTHENC
+	select CRYPTO_BLKCIPHER
+	default m
+	help
+	  This driver provides support for virtio crypto device. If you
+	  choose 'M' here, this module will be called virtio_crypto.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/virtio/Makefile linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/Makefile
--- linux-libre-4.9-gnu/drivers/crypto/virtio/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,5 @@
+obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio_crypto.o
+virtio_crypto-objs := \
+	virtio_crypto_algs.o \
+	virtio_crypto_mgr.o \
+	virtio_crypto_core.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_algs.c linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_algs.c
--- linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_algs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_algs.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,540 @@
+ /* Algorithms supported by virtio crypto device
+  *
+  * Authors: Gonglei <arei.gonglei@huawei.com>
+  *
+  * Copyright 2016 HUAWEI TECHNOLOGIES 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.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU 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/scatterlist.h>
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <crypto/scatterwalk.h>
+#include <linux/atomic.h>
+
+#include <uapi/linux/virtio_crypto.h>
+#include "virtio_crypto_common.h"
+
+/*
+ * The algs_lock protects the below global virtio_crypto_active_devs
+ * and crypto algorithms registion.
+ */
+static DEFINE_MUTEX(algs_lock);
+static unsigned int virtio_crypto_active_devs;
+
+static u64 virtio_crypto_alg_sg_nents_length(struct scatterlist *sg)
+{
+	u64 total = 0;
+
+	for (total = 0; sg; sg = sg_next(sg))
+		total += sg->length;
+
+	return total;
+}
+
+static int
+virtio_crypto_alg_validate_key(int key_len, uint32_t *alg)
+{
+	switch (key_len) {
+	case AES_KEYSIZE_128:
+	case AES_KEYSIZE_192:
+	case AES_KEYSIZE_256:
+		*alg = VIRTIO_CRYPTO_CIPHER_AES_CBC;
+		break;
+	default:
+		pr_err("virtio_crypto: Unsupported key length: %d\n",
+			key_len);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int virtio_crypto_alg_ablkcipher_init_session(
+		struct virtio_crypto_ablkcipher_ctx *ctx,
+		uint32_t alg, const uint8_t *key,
+		unsigned int keylen,
+		int encrypt)
+{
+	struct scatterlist outhdr, key_sg, inhdr, *sgs[3];
+	unsigned int tmp;
+	struct virtio_crypto *vcrypto = ctx->vcrypto;
+	int op = encrypt ? VIRTIO_CRYPTO_OP_ENCRYPT : VIRTIO_CRYPTO_OP_DECRYPT;
+	int err;
+	unsigned int num_out = 0, num_in = 0;
+
+	/*
+	 * Avoid to do DMA from the stack, switch to using
+	 * dynamically-allocated for the key
+	 */
+	uint8_t *cipher_key = kmalloc(keylen, GFP_ATOMIC);
+
+	if (!cipher_key)
+		return -ENOMEM;
+
+	memcpy(cipher_key, key, keylen);
+
+	spin_lock(&vcrypto->ctrl_lock);
+	/* Pad ctrl header */
+	vcrypto->ctrl.header.opcode =
+		cpu_to_le32(VIRTIO_CRYPTO_CIPHER_CREATE_SESSION);
+	vcrypto->ctrl.header.algo = cpu_to_le32(alg);
+	/* Set the default dataqueue id to 0 */
+	vcrypto->ctrl.header.queue_id = 0;
+
+	vcrypto->input.status = cpu_to_le32(VIRTIO_CRYPTO_ERR);
+	/* Pad cipher's parameters */
+	vcrypto->ctrl.u.sym_create_session.op_type =
+		cpu_to_le32(VIRTIO_CRYPTO_SYM_OP_CIPHER);
+	vcrypto->ctrl.u.sym_create_session.u.cipher.para.algo =
+		vcrypto->ctrl.header.algo;
+	vcrypto->ctrl.u.sym_create_session.u.cipher.para.keylen =
+		cpu_to_le32(keylen);
+	vcrypto->ctrl.u.sym_create_session.u.cipher.para.op =
+		cpu_to_le32(op);
+
+	sg_init_one(&outhdr, &vcrypto->ctrl, sizeof(vcrypto->ctrl));
+	sgs[num_out++] = &outhdr;
+
+	/* Set key */
+	sg_init_one(&key_sg, cipher_key, keylen);
+	sgs[num_out++] = &key_sg;
+
+	/* Return status and session id back */
+	sg_init_one(&inhdr, &vcrypto->input, sizeof(vcrypto->input));
+	sgs[num_out + num_in++] = &inhdr;
+
+	err = virtqueue_add_sgs(vcrypto->ctrl_vq, sgs, num_out,
+				num_in, vcrypto, GFP_ATOMIC);
+	if (err < 0) {
+		spin_unlock(&vcrypto->ctrl_lock);
+		kzfree(cipher_key);
+		return err;
+	}
+	virtqueue_kick(vcrypto->ctrl_vq);
+
+	/*
+	 * Trapping into the hypervisor, so the request should be
+	 * handled immediately.
+	 */
+	while (!virtqueue_get_buf(vcrypto->ctrl_vq, &tmp) &&
+	       !virtqueue_is_broken(vcrypto->ctrl_vq))
+		cpu_relax();
+
+	if (le32_to_cpu(vcrypto->input.status) != VIRTIO_CRYPTO_OK) {
+		spin_unlock(&vcrypto->ctrl_lock);
+		pr_err("virtio_crypto: Create session failed status: %u\n",
+			le32_to_cpu(vcrypto->input.status));
+		kzfree(cipher_key);
+		return -EINVAL;
+	}
+
+	if (encrypt)
+		ctx->enc_sess_info.session_id =
+			le64_to_cpu(vcrypto->input.session_id);
+	else
+		ctx->dec_sess_info.session_id =
+			le64_to_cpu(vcrypto->input.session_id);
+
+	spin_unlock(&vcrypto->ctrl_lock);
+
+	kzfree(cipher_key);
+	return 0;
+}
+
+static int virtio_crypto_alg_ablkcipher_close_session(
+		struct virtio_crypto_ablkcipher_ctx *ctx,
+		int encrypt)
+{
+	struct scatterlist outhdr, status_sg, *sgs[2];
+	unsigned int tmp;
+	struct virtio_crypto_destroy_session_req *destroy_session;
+	struct virtio_crypto *vcrypto = ctx->vcrypto;
+	int err;
+	unsigned int num_out = 0, num_in = 0;
+
+	spin_lock(&vcrypto->ctrl_lock);
+	vcrypto->ctrl_status.status = VIRTIO_CRYPTO_ERR;
+	/* Pad ctrl header */
+	vcrypto->ctrl.header.opcode =
+		cpu_to_le32(VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION);
+	/* Set the default virtqueue id to 0 */
+	vcrypto->ctrl.header.queue_id = 0;
+
+	destroy_session = &vcrypto->ctrl.u.destroy_session;
+
+	if (encrypt)
+		destroy_session->session_id =
+			cpu_to_le64(ctx->enc_sess_info.session_id);
+	else
+		destroy_session->session_id =
+			cpu_to_le64(ctx->dec_sess_info.session_id);
+
+	sg_init_one(&outhdr, &vcrypto->ctrl, sizeof(vcrypto->ctrl));
+	sgs[num_out++] = &outhdr;
+
+	/* Return status and session id back */
+	sg_init_one(&status_sg, &vcrypto->ctrl_status.status,
+		sizeof(vcrypto->ctrl_status.status));
+	sgs[num_out + num_in++] = &status_sg;
+
+	err = virtqueue_add_sgs(vcrypto->ctrl_vq, sgs, num_out,
+			num_in, vcrypto, GFP_ATOMIC);
+	if (err < 0) {
+		spin_unlock(&vcrypto->ctrl_lock);
+		return err;
+	}
+	virtqueue_kick(vcrypto->ctrl_vq);
+
+	while (!virtqueue_get_buf(vcrypto->ctrl_vq, &tmp) &&
+	       !virtqueue_is_broken(vcrypto->ctrl_vq))
+		cpu_relax();
+
+	if (vcrypto->ctrl_status.status != VIRTIO_CRYPTO_OK) {
+		spin_unlock(&vcrypto->ctrl_lock);
+		pr_err("virtio_crypto: Close session failed status: %u, session_id: 0x%llx\n",
+			vcrypto->ctrl_status.status,
+			destroy_session->session_id);
+
+		return -EINVAL;
+	}
+	spin_unlock(&vcrypto->ctrl_lock);
+
+	return 0;
+}
+
+static int virtio_crypto_alg_ablkcipher_init_sessions(
+		struct virtio_crypto_ablkcipher_ctx *ctx,
+		const uint8_t *key, unsigned int keylen)
+{
+	uint32_t alg;
+	int ret;
+	struct virtio_crypto *vcrypto = ctx->vcrypto;
+
+	if (keylen > vcrypto->max_cipher_key_len) {
+		pr_err("virtio_crypto: the key is too long\n");
+		goto bad_key;
+	}
+
+	if (virtio_crypto_alg_validate_key(keylen, &alg))
+		goto bad_key;
+
+	/* Create encryption session */
+	ret = virtio_crypto_alg_ablkcipher_init_session(ctx,
+			alg, key, keylen, 1);
+	if (ret)
+		return ret;
+	/* Create decryption session */
+	ret = virtio_crypto_alg_ablkcipher_init_session(ctx,
+			alg, key, keylen, 0);
+	if (ret) {
+		virtio_crypto_alg_ablkcipher_close_session(ctx, 1);
+		return ret;
+	}
+	return 0;
+
+bad_key:
+	crypto_tfm_set_flags(ctx->tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	return -EINVAL;
+}
+
+/* Note: kernel crypto API realization */
+static int virtio_crypto_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
+					 const uint8_t *key,
+					 unsigned int keylen)
+{
+	struct virtio_crypto_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
+	int ret;
+
+	if (!ctx->vcrypto) {
+		/* New key */
+		int node = virtio_crypto_get_current_node();
+		struct virtio_crypto *vcrypto =
+				      virtcrypto_get_dev_node(node);
+		if (!vcrypto) {
+			pr_err("virtio_crypto: Could not find a virtio device in the system");
+			return -ENODEV;
+		}
+
+		ctx->vcrypto = vcrypto;
+	} else {
+		/* Rekeying, we should close the created sessions previously */
+		virtio_crypto_alg_ablkcipher_close_session(ctx, 1);
+		virtio_crypto_alg_ablkcipher_close_session(ctx, 0);
+	}
+
+	ret = virtio_crypto_alg_ablkcipher_init_sessions(ctx, key, keylen);
+	if (ret) {
+		virtcrypto_dev_put(ctx->vcrypto);
+		ctx->vcrypto = NULL;
+
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+__virtio_crypto_ablkcipher_do_req(struct virtio_crypto_request *vc_req,
+		struct ablkcipher_request *req,
+		struct data_queue *data_vq,
+		__u8 op)
+{
+	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
+	unsigned int ivsize = crypto_ablkcipher_ivsize(tfm);
+	struct virtio_crypto_ablkcipher_ctx *ctx = vc_req->ablkcipher_ctx;
+	struct virtio_crypto *vcrypto = ctx->vcrypto;
+	struct virtio_crypto_op_data_req *req_data;
+	int src_nents, dst_nents;
+	int err;
+	unsigned long flags;
+	struct scatterlist outhdr, iv_sg, status_sg, **sgs;
+	int i;
+	u64 dst_len;
+	unsigned int num_out = 0, num_in = 0;
+	int sg_total;
+	uint8_t *iv;
+
+	src_nents = sg_nents_for_len(req->src, req->nbytes);
+	dst_nents = sg_nents(req->dst);
+
+	pr_debug("virtio_crypto: Number of sgs (src_nents: %d, dst_nents: %d)\n",
+			src_nents, dst_nents);
+
+	/* Why 3?  outhdr + iv + inhdr */
+	sg_total = src_nents + dst_nents + 3;
+	sgs = kzalloc_node(sg_total * sizeof(*sgs), GFP_ATOMIC,
+				dev_to_node(&vcrypto->vdev->dev));
+	if (!sgs)
+		return -ENOMEM;
+
+	req_data = kzalloc_node(sizeof(*req_data), GFP_ATOMIC,
+				dev_to_node(&vcrypto->vdev->dev));
+	if (!req_data) {
+		kfree(sgs);
+		return -ENOMEM;
+	}
+
+	vc_req->req_data = req_data;
+	vc_req->type = VIRTIO_CRYPTO_SYM_OP_CIPHER;
+	/* Head of operation */
+	if (op) {
+		req_data->header.session_id =
+			cpu_to_le64(ctx->enc_sess_info.session_id);
+		req_data->header.opcode =
+			cpu_to_le32(VIRTIO_CRYPTO_CIPHER_ENCRYPT);
+	} else {
+		req_data->header.session_id =
+			cpu_to_le64(ctx->dec_sess_info.session_id);
+	    req_data->header.opcode =
+			cpu_to_le32(VIRTIO_CRYPTO_CIPHER_DECRYPT);
+	}
+	req_data->u.sym_req.op_type = cpu_to_le32(VIRTIO_CRYPTO_SYM_OP_CIPHER);
+	req_data->u.sym_req.u.cipher.para.iv_len = cpu_to_le32(ivsize);
+	req_data->u.sym_req.u.cipher.para.src_data_len =
+			cpu_to_le32(req->nbytes);
+
+	dst_len = virtio_crypto_alg_sg_nents_length(req->dst);
+	if (unlikely(dst_len > U32_MAX)) {
+		pr_err("virtio_crypto: The dst_len is beyond U32_MAX\n");
+		err = -EINVAL;
+		goto free;
+	}
+
+	pr_debug("virtio_crypto: src_len: %u, dst_len: %llu\n",
+			req->nbytes, dst_len);
+
+	if (unlikely(req->nbytes + dst_len + ivsize +
+		sizeof(vc_req->status) > vcrypto->max_size)) {
+		pr_err("virtio_crypto: The length is too big\n");
+		err = -EINVAL;
+		goto free;
+	}
+
+	req_data->u.sym_req.u.cipher.para.dst_data_len =
+			cpu_to_le32((uint32_t)dst_len);
+
+	/* Outhdr */
+	sg_init_one(&outhdr, req_data, sizeof(*req_data));
+	sgs[num_out++] = &outhdr;
+
+	/* IV */
+
+	/*
+	 * Avoid to do DMA from the stack, switch to using
+	 * dynamically-allocated for the IV
+	 */
+	iv = kzalloc_node(ivsize, GFP_ATOMIC,
+				dev_to_node(&vcrypto->vdev->dev));
+	if (!iv) {
+		err = -ENOMEM;
+		goto free;
+	}
+	memcpy(iv, req->info, ivsize);
+	sg_init_one(&iv_sg, iv, ivsize);
+	sgs[num_out++] = &iv_sg;
+	vc_req->iv = iv;
+
+	/* Source data */
+	for (i = 0; i < src_nents; i++)
+		sgs[num_out++] = &req->src[i];
+
+	/* Destination data */
+	for (i = 0; i < dst_nents; i++)
+		sgs[num_out + num_in++] = &req->dst[i];
+
+	/* Status */
+	sg_init_one(&status_sg, &vc_req->status, sizeof(vc_req->status));
+	sgs[num_out + num_in++] = &status_sg;
+
+	vc_req->sgs = sgs;
+
+	spin_lock_irqsave(&data_vq->lock, flags);
+	err = virtqueue_add_sgs(data_vq->vq, sgs, num_out,
+				num_in, vc_req, GFP_ATOMIC);
+	virtqueue_kick(data_vq->vq);
+	spin_unlock_irqrestore(&data_vq->lock, flags);
+	if (unlikely(err < 0))
+		goto free_iv;
+
+	return 0;
+
+free_iv:
+	kzfree(iv);
+free:
+	kzfree(req_data);
+	kfree(sgs);
+	return err;
+}
+
+static int virtio_crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *atfm = crypto_ablkcipher_reqtfm(req);
+	struct virtio_crypto_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(atfm);
+	struct virtio_crypto_request *vc_req = ablkcipher_request_ctx(req);
+	struct virtio_crypto *vcrypto = ctx->vcrypto;
+	int ret;
+	/* Use the first data virtqueue as default */
+	struct data_queue *data_vq = &vcrypto->data_vq[0];
+
+	vc_req->ablkcipher_ctx = ctx;
+	vc_req->ablkcipher_req = req;
+	ret = __virtio_crypto_ablkcipher_do_req(vc_req, req, data_vq, 1);
+	if (ret < 0) {
+		pr_err("virtio_crypto: Encryption failed!\n");
+		return ret;
+	}
+
+	return -EINPROGRESS;
+}
+
+static int virtio_crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *atfm = crypto_ablkcipher_reqtfm(req);
+	struct virtio_crypto_ablkcipher_ctx *ctx = crypto_ablkcipher_ctx(atfm);
+	struct virtio_crypto_request *vc_req = ablkcipher_request_ctx(req);
+	struct virtio_crypto *vcrypto = ctx->vcrypto;
+	int ret;
+	/* Use the first data virtqueue as default */
+	struct data_queue *data_vq = &vcrypto->data_vq[0];
+
+	vc_req->ablkcipher_ctx = ctx;
+	vc_req->ablkcipher_req = req;
+
+	ret = __virtio_crypto_ablkcipher_do_req(vc_req, req, data_vq, 0);
+	if (ret < 0) {
+		pr_err("virtio_crypto: Decryption failed!\n");
+		return ret;
+	}
+
+	return -EINPROGRESS;
+}
+
+static int virtio_crypto_ablkcipher_init(struct crypto_tfm *tfm)
+{
+	struct virtio_crypto_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct virtio_crypto_request);
+	ctx->tfm = tfm;
+
+	return 0;
+}
+
+static void virtio_crypto_ablkcipher_exit(struct crypto_tfm *tfm)
+{
+	struct virtio_crypto_ablkcipher_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (!ctx->vcrypto)
+		return;
+
+	virtio_crypto_alg_ablkcipher_close_session(ctx, 1);
+	virtio_crypto_alg_ablkcipher_close_session(ctx, 0);
+	virtcrypto_dev_put(ctx->vcrypto);
+	ctx->vcrypto = NULL;
+}
+
+static struct crypto_alg virtio_crypto_algs[] = { {
+	.cra_name = "cbc(aes)",
+	.cra_driver_name = "virtio_crypto_aes_cbc",
+	.cra_priority = 501,
+	.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize = AES_BLOCK_SIZE,
+	.cra_ctxsize  = sizeof(struct virtio_crypto_ablkcipher_ctx),
+	.cra_alignmask = 0,
+	.cra_module = THIS_MODULE,
+	.cra_type = &crypto_ablkcipher_type,
+	.cra_init = virtio_crypto_ablkcipher_init,
+	.cra_exit = virtio_crypto_ablkcipher_exit,
+	.cra_u = {
+	   .ablkcipher = {
+			.setkey = virtio_crypto_ablkcipher_setkey,
+			.decrypt = virtio_crypto_ablkcipher_decrypt,
+			.encrypt = virtio_crypto_ablkcipher_encrypt,
+			.min_keysize = AES_MIN_KEY_SIZE,
+			.max_keysize = AES_MAX_KEY_SIZE,
+			.ivsize = AES_BLOCK_SIZE,
+		},
+	},
+} };
+
+int virtio_crypto_algs_register(void)
+{
+	int ret = 0;
+
+	mutex_lock(&algs_lock);
+	if (++virtio_crypto_active_devs != 1)
+		goto unlock;
+
+	ret = crypto_register_algs(virtio_crypto_algs,
+			ARRAY_SIZE(virtio_crypto_algs));
+	if (ret)
+		virtio_crypto_active_devs--;
+
+unlock:
+	mutex_unlock(&algs_lock);
+	return ret;
+}
+
+void virtio_crypto_algs_unregister(void)
+{
+	mutex_lock(&algs_lock);
+	if (--virtio_crypto_active_devs != 0)
+		goto unlock;
+
+	crypto_unregister_algs(virtio_crypto_algs,
+			ARRAY_SIZE(virtio_crypto_algs));
+
+unlock:
+	mutex_unlock(&algs_lock);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_common.h linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_common.h
--- linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,128 @@
+/* Common header for Virtio crypto device.
+ *
+ * Copyright 2016 HUAWEI TECHNOLOGIES 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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 _VIRTIO_CRYPTO_COMMON_H
+#define _VIRTIO_CRYPTO_COMMON_H
+
+#include <linux/virtio.h>
+#include <linux/crypto.h>
+#include <linux/spinlock.h>
+#include <crypto/aead.h>
+#include <crypto/aes.h>
+#include <crypto/authenc.h>
+
+
+/* Internal representation of a data virtqueue */
+struct data_queue {
+	/* Virtqueue associated with this send _queue */
+	struct virtqueue *vq;
+
+	/* To protect the vq operations for the dataq */
+	spinlock_t lock;
+
+	/* Name of the tx queue: dataq.$index */
+	char name[32];
+};
+
+struct virtio_crypto {
+	struct virtio_device *vdev;
+	struct virtqueue *ctrl_vq;
+	struct data_queue *data_vq;
+
+	/* To protect the vq operations for the controlq */
+	spinlock_t ctrl_lock;
+
+	/* Maximum of data queues supported by the device */
+	u32 max_data_queues;
+
+	/* Number of queue currently used by the driver */
+	u32 curr_queue;
+
+	/* Maximum length of cipher key */
+	u32 max_cipher_key_len;
+	/* Maximum length of authenticated key */
+	u32 max_auth_key_len;
+	/* Maximum size of per request */
+	u64 max_size;
+
+	/* Control VQ buffers: protected by the ctrl_lock */
+	struct virtio_crypto_op_ctrl_req ctrl;
+	struct virtio_crypto_session_input input;
+	struct virtio_crypto_inhdr ctrl_status;
+
+	unsigned long status;
+	atomic_t ref_count;
+	struct list_head list;
+	struct module *owner;
+	uint8_t dev_id;
+
+	/* Does the affinity hint is set for virtqueues? */
+	bool affinity_hint_set;
+};
+
+struct virtio_crypto_sym_session_info {
+	/* Backend session id, which come from the host side */
+	__u64 session_id;
+};
+
+struct virtio_crypto_ablkcipher_ctx {
+	struct virtio_crypto *vcrypto;
+	struct crypto_tfm *tfm;
+
+	struct virtio_crypto_sym_session_info enc_sess_info;
+	struct virtio_crypto_sym_session_info dec_sess_info;
+};
+
+struct virtio_crypto_request {
+	/* Cipher or aead */
+	uint32_t type;
+	uint8_t status;
+	struct virtio_crypto_ablkcipher_ctx *ablkcipher_ctx;
+	struct ablkcipher_request *ablkcipher_req;
+	struct virtio_crypto_op_data_req *req_data;
+	struct scatterlist **sgs;
+	uint8_t *iv;
+};
+
+int virtcrypto_devmgr_add_dev(struct virtio_crypto *vcrypto_dev);
+struct list_head *virtcrypto_devmgr_get_head(void);
+void virtcrypto_devmgr_rm_dev(struct virtio_crypto *vcrypto_dev);
+struct virtio_crypto *virtcrypto_devmgr_get_first(void);
+int virtcrypto_dev_in_use(struct virtio_crypto *vcrypto_dev);
+int virtcrypto_dev_get(struct virtio_crypto *vcrypto_dev);
+void virtcrypto_dev_put(struct virtio_crypto *vcrypto_dev);
+int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev);
+struct virtio_crypto *virtcrypto_get_dev_node(int node);
+int virtcrypto_dev_start(struct virtio_crypto *vcrypto);
+void virtcrypto_dev_stop(struct virtio_crypto *vcrypto);
+
+static inline int virtio_crypto_get_current_node(void)
+{
+	int cpu, node;
+
+	cpu = get_cpu();
+	node = topology_physical_package_id(cpu);
+	put_cpu();
+
+	return node;
+}
+
+int virtio_crypto_algs_register(void);
+void virtio_crypto_algs_unregister(void);
+
+#endif /* _VIRTIO_CRYPTO_COMMON_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_core.c linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_core.c
--- linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,476 @@
+ /* Driver for Virtio crypto device.
+  *
+  * Copyright 2016 HUAWEI TECHNOLOGIES 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.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU 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/err.h>
+#include <linux/module.h>
+#include <linux/virtio_config.h>
+#include <linux/cpu.h>
+
+#include <uapi/linux/virtio_crypto.h>
+#include "virtio_crypto_common.h"
+
+
+static void
+virtcrypto_clear_request(struct virtio_crypto_request *vc_req)
+{
+	if (vc_req) {
+		kzfree(vc_req->iv);
+		kzfree(vc_req->req_data);
+		kfree(vc_req->sgs);
+	}
+}
+
+static void virtcrypto_dataq_callback(struct virtqueue *vq)
+{
+	struct virtio_crypto *vcrypto = vq->vdev->priv;
+	struct virtio_crypto_request *vc_req;
+	unsigned long flags;
+	unsigned int len;
+	struct ablkcipher_request *ablk_req;
+	int error;
+	unsigned int qid = vq->index;
+
+	spin_lock_irqsave(&vcrypto->data_vq[qid].lock, flags);
+	do {
+		virtqueue_disable_cb(vq);
+		while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) {
+			if (vc_req->type == VIRTIO_CRYPTO_SYM_OP_CIPHER) {
+				switch (vc_req->status) {
+				case VIRTIO_CRYPTO_OK:
+					error = 0;
+					break;
+				case VIRTIO_CRYPTO_INVSESS:
+				case VIRTIO_CRYPTO_ERR:
+					error = -EINVAL;
+					break;
+				case VIRTIO_CRYPTO_BADMSG:
+					error = -EBADMSG;
+					break;
+				default:
+					error = -EIO;
+					break;
+				}
+				ablk_req = vc_req->ablkcipher_req;
+				virtcrypto_clear_request(vc_req);
+
+				spin_unlock_irqrestore(
+					&vcrypto->data_vq[qid].lock, flags);
+				/* Finish the encrypt or decrypt process */
+				ablk_req->base.complete(&ablk_req->base, error);
+				spin_lock_irqsave(
+					&vcrypto->data_vq[qid].lock, flags);
+			}
+		}
+	} while (!virtqueue_enable_cb(vq));
+	spin_unlock_irqrestore(&vcrypto->data_vq[qid].lock, flags);
+}
+
+static int virtcrypto_find_vqs(struct virtio_crypto *vi)
+{
+	vq_callback_t **callbacks;
+	struct virtqueue **vqs;
+	int ret = -ENOMEM;
+	int i, total_vqs;
+	const char **names;
+
+	/*
+	 * We expect 1 data virtqueue, followed by
+	 * possible N-1 data queues used in multiqueue mode,
+	 * followed by control vq.
+	 */
+	total_vqs = vi->max_data_queues + 1;
+
+	/* Allocate space for find_vqs parameters */
+	vqs = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL);
+	if (!vqs)
+		goto err_vq;
+	callbacks = kcalloc(total_vqs, sizeof(*callbacks), GFP_KERNEL);
+	if (!callbacks)
+		goto err_callback;
+	names = kcalloc(total_vqs, sizeof(*names), GFP_KERNEL);
+	if (!names)
+		goto err_names;
+
+	/* Parameters for control virtqueue */
+	callbacks[total_vqs - 1] = NULL;
+	names[total_vqs - 1] = "controlq";
+
+	/* Allocate/initialize parameters for data virtqueues */
+	for (i = 0; i < vi->max_data_queues; i++) {
+		callbacks[i] = virtcrypto_dataq_callback;
+		snprintf(vi->data_vq[i].name, sizeof(vi->data_vq[i].name),
+				"dataq.%d", i);
+		names[i] = vi->data_vq[i].name;
+	}
+
+	ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks,
+					 names);
+	if (ret)
+		goto err_find;
+
+	vi->ctrl_vq = vqs[total_vqs - 1];
+
+	for (i = 0; i < vi->max_data_queues; i++) {
+		spin_lock_init(&vi->data_vq[i].lock);
+		vi->data_vq[i].vq = vqs[i];
+	}
+
+	kfree(names);
+	kfree(callbacks);
+	kfree(vqs);
+
+	return 0;
+
+err_find:
+	kfree(names);
+err_names:
+	kfree(callbacks);
+err_callback:
+	kfree(vqs);
+err_vq:
+	return ret;
+}
+
+static int virtcrypto_alloc_queues(struct virtio_crypto *vi)
+{
+	vi->data_vq = kcalloc(vi->max_data_queues, sizeof(*vi->data_vq),
+				GFP_KERNEL);
+	if (!vi->data_vq)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void virtcrypto_clean_affinity(struct virtio_crypto *vi, long hcpu)
+{
+	int i;
+
+	if (vi->affinity_hint_set) {
+		for (i = 0; i < vi->max_data_queues; i++)
+			virtqueue_set_affinity(vi->data_vq[i].vq, -1);
+
+		vi->affinity_hint_set = false;
+	}
+}
+
+static void virtcrypto_set_affinity(struct virtio_crypto *vcrypto)
+{
+	int i = 0;
+	int cpu;
+
+	/*
+	 * In single queue mode, we don't set the cpu affinity.
+	 */
+	if (vcrypto->curr_queue == 1 || vcrypto->max_data_queues == 1) {
+		virtcrypto_clean_affinity(vcrypto, -1);
+		return;
+	}
+
+	/*
+	 * In multiqueue mode, we let the queue to be private to one cpu
+	 * by setting the affinity hint to eliminate the contention.
+	 *
+	 * TODO: adds cpu hotplug support by register cpu notifier.
+	 *
+	 */
+	for_each_online_cpu(cpu) {
+		virtqueue_set_affinity(vcrypto->data_vq[i].vq, cpu);
+		if (++i >= vcrypto->max_data_queues)
+			break;
+	}
+
+	vcrypto->affinity_hint_set = true;
+}
+
+static void virtcrypto_free_queues(struct virtio_crypto *vi)
+{
+	kfree(vi->data_vq);
+}
+
+static int virtcrypto_init_vqs(struct virtio_crypto *vi)
+{
+	int ret;
+
+	/* Allocate send & receive queues */
+	ret = virtcrypto_alloc_queues(vi);
+	if (ret)
+		goto err;
+
+	ret = virtcrypto_find_vqs(vi);
+	if (ret)
+		goto err_free;
+
+	get_online_cpus();
+	virtcrypto_set_affinity(vi);
+	put_online_cpus();
+
+	return 0;
+
+err_free:
+	virtcrypto_free_queues(vi);
+err:
+	return ret;
+}
+
+static int virtcrypto_update_status(struct virtio_crypto *vcrypto)
+{
+	u32 status;
+	int err;
+
+	virtio_cread(vcrypto->vdev,
+	    struct virtio_crypto_config, status, &status);
+
+	/*
+	 * Unknown status bits would be a host error and the driver
+	 * should consider the device to be broken.
+	 */
+	if (status & (~VIRTIO_CRYPTO_S_HW_READY)) {
+		dev_warn(&vcrypto->vdev->dev,
+				"Unknown status bits: 0x%x\n", status);
+
+		virtio_break_device(vcrypto->vdev);
+		return -EPERM;
+	}
+
+	if (vcrypto->status == status)
+		return 0;
+
+	vcrypto->status = status;
+
+	if (vcrypto->status & VIRTIO_CRYPTO_S_HW_READY) {
+		err = virtcrypto_dev_start(vcrypto);
+		if (err) {
+			dev_err(&vcrypto->vdev->dev,
+				"Failed to start virtio crypto device.\n");
+
+			return -EPERM;
+		}
+		dev_info(&vcrypto->vdev->dev, "Accelerator is ready\n");
+	} else {
+		virtcrypto_dev_stop(vcrypto);
+		dev_info(&vcrypto->vdev->dev, "Accelerator is not ready\n");
+	}
+
+	return 0;
+}
+
+static void virtcrypto_del_vqs(struct virtio_crypto *vcrypto)
+{
+	struct virtio_device *vdev = vcrypto->vdev;
+
+	virtcrypto_clean_affinity(vcrypto, -1);
+
+	vdev->config->del_vqs(vdev);
+
+	virtcrypto_free_queues(vcrypto);
+}
+
+static int virtcrypto_probe(struct virtio_device *vdev)
+{
+	int err = -EFAULT;
+	struct virtio_crypto *vcrypto;
+	u32 max_data_queues = 0, max_cipher_key_len = 0;
+	u32 max_auth_key_len = 0;
+	u64 max_size = 0;
+
+	if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
+		return -ENODEV;
+
+	if (!vdev->config->get) {
+		dev_err(&vdev->dev, "%s failure: config access disabled\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (num_possible_nodes() > 1 && dev_to_node(&vdev->dev) < 0) {
+		/*
+		 * If the accelerator is connected to a node with no memory
+		 * there is no point in using the accelerator since the remote
+		 * memory transaction will be very slow.
+		 */
+		dev_err(&vdev->dev, "Invalid NUMA configuration.\n");
+		return -EINVAL;
+	}
+
+	vcrypto = kzalloc_node(sizeof(*vcrypto), GFP_KERNEL,
+					dev_to_node(&vdev->dev));
+	if (!vcrypto)
+		return -ENOMEM;
+
+	virtio_cread(vdev, struct virtio_crypto_config,
+			max_dataqueues, &max_data_queues);
+	if (max_data_queues < 1)
+		max_data_queues = 1;
+
+	virtio_cread(vdev, struct virtio_crypto_config,
+		max_cipher_key_len, &max_cipher_key_len);
+	virtio_cread(vdev, struct virtio_crypto_config,
+		max_auth_key_len, &max_auth_key_len);
+	virtio_cread(vdev, struct virtio_crypto_config,
+		max_size, &max_size);
+
+	/* Add virtio crypto device to global table */
+	err = virtcrypto_devmgr_add_dev(vcrypto);
+	if (err) {
+		dev_err(&vdev->dev, "Failed to add new virtio crypto device.\n");
+		goto free;
+	}
+	vcrypto->owner = THIS_MODULE;
+	vcrypto = vdev->priv = vcrypto;
+	vcrypto->vdev = vdev;
+
+	spin_lock_init(&vcrypto->ctrl_lock);
+
+	/* Use single data queue as default */
+	vcrypto->curr_queue = 1;
+	vcrypto->max_data_queues = max_data_queues;
+	vcrypto->max_cipher_key_len = max_cipher_key_len;
+	vcrypto->max_auth_key_len = max_auth_key_len;
+	vcrypto->max_size = max_size;
+
+	dev_info(&vdev->dev,
+		"max_queues: %u, max_cipher_key_len: %u, max_auth_key_len: %u, max_size 0x%llx\n",
+		vcrypto->max_data_queues,
+		vcrypto->max_cipher_key_len,
+		vcrypto->max_auth_key_len,
+		vcrypto->max_size);
+
+	err = virtcrypto_init_vqs(vcrypto);
+	if (err) {
+		dev_err(&vdev->dev, "Failed to initialize vqs.\n");
+		goto free_dev;
+	}
+	virtio_device_ready(vdev);
+
+	err = virtcrypto_update_status(vcrypto);
+	if (err)
+		goto free_vqs;
+
+	return 0;
+
+free_vqs:
+	vcrypto->vdev->config->reset(vdev);
+	virtcrypto_del_vqs(vcrypto);
+free_dev:
+	virtcrypto_devmgr_rm_dev(vcrypto);
+free:
+	kfree(vcrypto);
+	return err;
+}
+
+static void virtcrypto_free_unused_reqs(struct virtio_crypto *vcrypto)
+{
+	struct virtio_crypto_request *vc_req;
+	int i;
+	struct virtqueue *vq;
+
+	for (i = 0; i < vcrypto->max_data_queues; i++) {
+		vq = vcrypto->data_vq[i].vq;
+		while ((vc_req = virtqueue_detach_unused_buf(vq)) != NULL) {
+			kfree(vc_req->req_data);
+			kfree(vc_req->sgs);
+		}
+	}
+}
+
+static void virtcrypto_remove(struct virtio_device *vdev)
+{
+	struct virtio_crypto *vcrypto = vdev->priv;
+
+	dev_info(&vdev->dev, "Start virtcrypto_remove.\n");
+
+	if (virtcrypto_dev_started(vcrypto))
+		virtcrypto_dev_stop(vcrypto);
+	vdev->config->reset(vdev);
+	virtcrypto_free_unused_reqs(vcrypto);
+	virtcrypto_del_vqs(vcrypto);
+	virtcrypto_devmgr_rm_dev(vcrypto);
+	kfree(vcrypto);
+}
+
+static void virtcrypto_config_changed(struct virtio_device *vdev)
+{
+	struct virtio_crypto *vcrypto = vdev->priv;
+
+	virtcrypto_update_status(vcrypto);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int virtcrypto_freeze(struct virtio_device *vdev)
+{
+	struct virtio_crypto *vcrypto = vdev->priv;
+
+	vdev->config->reset(vdev);
+	virtcrypto_free_unused_reqs(vcrypto);
+	if (virtcrypto_dev_started(vcrypto))
+		virtcrypto_dev_stop(vcrypto);
+
+	virtcrypto_del_vqs(vcrypto);
+	return 0;
+}
+
+static int virtcrypto_restore(struct virtio_device *vdev)
+{
+	struct virtio_crypto *vcrypto = vdev->priv;
+	int err;
+
+	err = virtcrypto_init_vqs(vcrypto);
+	if (err)
+		return err;
+
+	virtio_device_ready(vdev);
+	err = virtcrypto_dev_start(vcrypto);
+	if (err) {
+		dev_err(&vdev->dev, "Failed to start virtio crypto device.\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+#endif
+
+static unsigned int features[] = {
+	/* none */
+};
+
+static struct virtio_device_id id_table[] = {
+	{ VIRTIO_ID_CRYPTO, VIRTIO_DEV_ANY_ID },
+	{ 0 },
+};
+
+static struct virtio_driver virtio_crypto_driver = {
+	.driver.name         = KBUILD_MODNAME,
+	.driver.owner        = THIS_MODULE,
+	.feature_table       = features,
+	.feature_table_size  = ARRAY_SIZE(features),
+	.id_table            = id_table,
+	.probe               = virtcrypto_probe,
+	.remove              = virtcrypto_remove,
+	.config_changed = virtcrypto_config_changed,
+#ifdef CONFIG_PM_SLEEP
+	.freeze = virtcrypto_freeze,
+	.restore = virtcrypto_restore,
+#endif
+};
+
+module_virtio_driver(virtio_crypto_driver);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("virtio crypto device driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gonglei <arei.gonglei@huawei.com>");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_mgr.c linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_mgr.c
--- linux-libre-4.9-gnu/drivers/crypto/virtio/virtio_crypto_mgr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/virtio/virtio_crypto_mgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,264 @@
+ /* Management for virtio crypto devices (refer to adf_dev_mgr.c)
+  *
+  * Copyright 2016 HUAWEI TECHNOLOGIES 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.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU 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/mutex.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include <uapi/linux/virtio_crypto.h>
+#include "virtio_crypto_common.h"
+
+static LIST_HEAD(virtio_crypto_table);
+static uint32_t num_devices;
+
+/* The table_lock protects the above global list and num_devices */
+static DEFINE_MUTEX(table_lock);
+
+#define VIRTIO_CRYPTO_MAX_DEVICES 32
+
+
+/*
+ * virtcrypto_devmgr_add_dev() - Add vcrypto_dev to the acceleration
+ * framework.
+ * @vcrypto_dev:  Pointer to virtio crypto device.
+ *
+ * Function adds virtio crypto device to the global list.
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: 0 on success, error code othewise.
+ */
+int virtcrypto_devmgr_add_dev(struct virtio_crypto *vcrypto_dev)
+{
+	struct list_head *itr;
+
+	mutex_lock(&table_lock);
+	if (num_devices == VIRTIO_CRYPTO_MAX_DEVICES) {
+		pr_info("virtio_crypto: only support up to %d devices\n",
+			    VIRTIO_CRYPTO_MAX_DEVICES);
+		mutex_unlock(&table_lock);
+		return -EFAULT;
+	}
+
+	list_for_each(itr, &virtio_crypto_table) {
+		struct virtio_crypto *ptr =
+				list_entry(itr, struct virtio_crypto, list);
+
+		if (ptr == vcrypto_dev) {
+			mutex_unlock(&table_lock);
+			return -EEXIST;
+		}
+	}
+	atomic_set(&vcrypto_dev->ref_count, 0);
+	list_add_tail(&vcrypto_dev->list, &virtio_crypto_table);
+	vcrypto_dev->dev_id = num_devices++;
+	mutex_unlock(&table_lock);
+	return 0;
+}
+
+struct list_head *virtcrypto_devmgr_get_head(void)
+{
+	return &virtio_crypto_table;
+}
+
+/*
+ * virtcrypto_devmgr_rm_dev() - Remove vcrypto_dev from the acceleration
+ * framework.
+ * @vcrypto_dev:  Pointer to virtio crypto device.
+ *
+ * Function removes virtio crypto device from the acceleration framework.
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: void
+ */
+void virtcrypto_devmgr_rm_dev(struct virtio_crypto *vcrypto_dev)
+{
+	mutex_lock(&table_lock);
+	list_del(&vcrypto_dev->list);
+	num_devices--;
+	mutex_unlock(&table_lock);
+}
+
+/*
+ * virtcrypto_devmgr_get_first()
+ *
+ * Function returns the first virtio crypto device from the acceleration
+ * framework.
+ *
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: pointer to vcrypto_dev or NULL if not found.
+ */
+struct virtio_crypto *virtcrypto_devmgr_get_first(void)
+{
+	struct virtio_crypto *dev = NULL;
+
+	mutex_lock(&table_lock);
+	if (!list_empty(&virtio_crypto_table))
+		dev = list_first_entry(&virtio_crypto_table,
+					struct virtio_crypto,
+				    list);
+	mutex_unlock(&table_lock);
+	return dev;
+}
+
+/*
+ * virtcrypto_dev_in_use() - Check whether vcrypto_dev is currently in use
+ * @vcrypto_dev: Pointer to virtio crypto device.
+ *
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: 1 when device is in use, 0 otherwise.
+ */
+int virtcrypto_dev_in_use(struct virtio_crypto *vcrypto_dev)
+{
+	return atomic_read(&vcrypto_dev->ref_count) != 0;
+}
+
+/*
+ * virtcrypto_dev_get() - Increment vcrypto_dev reference count
+ * @vcrypto_dev: Pointer to virtio crypto device.
+ *
+ * Increment the vcrypto_dev refcount and if this is the first time
+ * incrementing it during this period the vcrypto_dev is in use,
+ * increment the module refcount too.
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: 0 when successful, EFAULT when fail to bump module refcount
+ */
+int virtcrypto_dev_get(struct virtio_crypto *vcrypto_dev)
+{
+	if (atomic_add_return(1, &vcrypto_dev->ref_count) == 1)
+		if (!try_module_get(vcrypto_dev->owner))
+			return -EFAULT;
+	return 0;
+}
+
+/*
+ * virtcrypto_dev_put() - Decrement vcrypto_dev reference count
+ * @vcrypto_dev: Pointer to virtio crypto device.
+ *
+ * Decrement the vcrypto_dev refcount and if this is the last time
+ * decrementing it during this period the vcrypto_dev is in use,
+ * decrement the module refcount too.
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: void
+ */
+void virtcrypto_dev_put(struct virtio_crypto *vcrypto_dev)
+{
+	if (atomic_sub_return(1, &vcrypto_dev->ref_count) == 0)
+		module_put(vcrypto_dev->owner);
+}
+
+/*
+ * virtcrypto_dev_started() - Check whether device has started
+ * @vcrypto_dev: Pointer to virtio crypto device.
+ *
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: 1 when the device has started, 0 otherwise
+ */
+int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev)
+{
+	return (vcrypto_dev->status & VIRTIO_CRYPTO_S_HW_READY);
+}
+
+/*
+ * virtcrypto_get_dev_node() - Get vcrypto_dev on the node.
+ * @node:  Node id the driver works.
+ *
+ * Function returns the virtio crypto device used fewest on the node.
+ *
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: pointer to vcrypto_dev or NULL if not found.
+ */
+struct virtio_crypto *virtcrypto_get_dev_node(int node)
+{
+	struct virtio_crypto *vcrypto_dev = NULL, *tmp_dev;
+	unsigned long best = ~0;
+	unsigned long ctr;
+
+	mutex_lock(&table_lock);
+	list_for_each_entry(tmp_dev, virtcrypto_devmgr_get_head(), list) {
+
+		if ((node == dev_to_node(&tmp_dev->vdev->dev) ||
+		     dev_to_node(&tmp_dev->vdev->dev) < 0) &&
+		    virtcrypto_dev_started(tmp_dev)) {
+			ctr = atomic_read(&tmp_dev->ref_count);
+			if (best > ctr) {
+				vcrypto_dev = tmp_dev;
+				best = ctr;
+			}
+		}
+	}
+
+	if (!vcrypto_dev) {
+		pr_info("virtio_crypto: Could not find a device on node %d\n",
+				node);
+		/* Get any started device */
+		list_for_each_entry(tmp_dev,
+				virtcrypto_devmgr_get_head(), list) {
+			if (virtcrypto_dev_started(tmp_dev)) {
+				vcrypto_dev = tmp_dev;
+				break;
+			}
+		}
+	}
+	mutex_unlock(&table_lock);
+	if (!vcrypto_dev)
+		return NULL;
+
+	virtcrypto_dev_get(vcrypto_dev);
+	return vcrypto_dev;
+}
+
+/*
+ * virtcrypto_dev_start() - Start virtio crypto device
+ * @vcrypto:    Pointer to virtio crypto device.
+ *
+ * Function notifies all the registered services that the virtio crypto device
+ * is ready to be used.
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: 0 on success, EFAULT when fail to register algorithms
+ */
+int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
+{
+	if (virtio_crypto_algs_register()) {
+		pr_err("virtio_crypto: Failed to register crypto algs\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+/*
+ * virtcrypto_dev_stop() - Stop virtio crypto device
+ * @vcrypto:    Pointer to virtio crypto device.
+ *
+ * Function notifies all the registered services that the virtio crypto device
+ * is ready to be used.
+ * To be used by virtio crypto device specific drivers.
+ *
+ * Return: void
+ */
+void virtcrypto_dev_stop(struct virtio_crypto *vcrypto)
+{
+	virtio_crypto_algs_unregister();
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/crypto/vmx/Makefile linux-libre-4.10-rc8-gnu/drivers/crypto/vmx/Makefile
--- linux-libre-4.9-gnu/drivers/crypto/vmx/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/crypto/vmx/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -10,10 +10,12 @@ endif
 quiet_cmd_perl = PERL $@
       cmd_perl = $(PERL) $(<) $(TARGET) > $(@)
 
-$(src)/aesp8-ppc.S: $(src)/aesp8-ppc.pl
-	$(call cmd,perl)
+targets += aesp8-ppc.S ghashp8-ppc.S
+
+$(obj)/aesp8-ppc.S: $(src)/aesp8-ppc.pl FORCE
+	$(call if_changed,perl)
   
-$(src)/ghashp8-ppc.S: $(src)/ghashp8-ppc.pl
-	$(call cmd,perl)
+$(obj)/ghashp8-ppc.S: $(src)/ghashp8-ppc.pl FORCE
+	$(call if_changed,perl)
 
-.PRECIOUS: $(obj)/aesp8-ppc.S $(obj)/ghashp8-ppc.S
+clean-files := aesp8-ppc.S ghashp8-ppc.S
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dax/dax.c linux-libre-4.10-rc8-gnu/drivers/dax/dax.c
--- linux-libre-4.9-gnu/drivers/dax/dax.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dax/dax.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,6 +75,73 @@ struct dax_dev {
 	struct resource res[0];
 };
 
+static ssize_t id_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct dax_region *dax_region;
+	ssize_t rc = -ENXIO;
+
+	device_lock(dev);
+	dax_region = dev_get_drvdata(dev);
+	if (dax_region)
+		rc = sprintf(buf, "%d\n", dax_region->id);
+	device_unlock(dev);
+
+	return rc;
+}
+static DEVICE_ATTR_RO(id);
+
+static ssize_t region_size_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct dax_region *dax_region;
+	ssize_t rc = -ENXIO;
+
+	device_lock(dev);
+	dax_region = dev_get_drvdata(dev);
+	if (dax_region)
+		rc = sprintf(buf, "%llu\n", (unsigned long long)
+				resource_size(&dax_region->res));
+	device_unlock(dev);
+
+	return rc;
+}
+static struct device_attribute dev_attr_region_size = __ATTR(size, 0444,
+		region_size_show, NULL);
+
+static ssize_t align_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct dax_region *dax_region;
+	ssize_t rc = -ENXIO;
+
+	device_lock(dev);
+	dax_region = dev_get_drvdata(dev);
+	if (dax_region)
+		rc = sprintf(buf, "%u\n", dax_region->align);
+	device_unlock(dev);
+
+	return rc;
+}
+static DEVICE_ATTR_RO(align);
+
+static struct attribute *dax_region_attributes[] = {
+	&dev_attr_region_size.attr,
+	&dev_attr_align.attr,
+	&dev_attr_id.attr,
+	NULL,
+};
+
+static const struct attribute_group dax_region_attribute_group = {
+	.name = "dax_region",
+	.attrs = dax_region_attributes,
+};
+
+static const struct attribute_group *dax_region_attribute_groups[] = {
+	&dax_region_attribute_group,
+	NULL,
+};
+
 static struct inode *dax_alloc_inode(struct super_block *sb)
 {
 	return kmem_cache_alloc(dax_cache, GFP_KERNEL);
@@ -200,12 +267,31 @@ void dax_region_put(struct dax_region *d
 }
 EXPORT_SYMBOL_GPL(dax_region_put);
 
+static void dax_region_unregister(void *region)
+{
+	struct dax_region *dax_region = region;
+
+	sysfs_remove_groups(&dax_region->dev->kobj,
+			dax_region_attribute_groups);
+	dax_region_put(dax_region);
+}
+
 struct dax_region *alloc_dax_region(struct device *parent, int region_id,
 		struct resource *res, unsigned int align, void *addr,
 		unsigned long pfn_flags)
 {
 	struct dax_region *dax_region;
 
+	/*
+	 * The DAX core assumes that it can store its private data in
+	 * parent->driver_data. This WARN is a reminder / safeguard for
+	 * developers of device-dax drivers.
+	 */
+	if (dev_get_drvdata(parent)) {
+		dev_WARN(parent, "dax core failed to setup private data\n");
+		return NULL;
+	}
+
 	if (!IS_ALIGNED(res->start, align)
 			|| !IS_ALIGNED(resource_size(res), align))
 		return NULL;
@@ -214,6 +300,7 @@ struct dax_region *alloc_dax_region(stru
 	if (!dax_region)
 		return NULL;
 
+	dev_set_drvdata(parent, dax_region);
 	memcpy(&dax_region->res, res, sizeof(*res));
 	dax_region->pfn_flags = pfn_flags;
 	kref_init(&dax_region->kref);
@@ -222,7 +309,14 @@ struct dax_region *alloc_dax_region(stru
 	dax_region->align = align;
 	dax_region->dev = parent;
 	dax_region->base = addr;
+	if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
+		kfree(dax_region);
+		return NULL;;
+	}
 
+	kref_get(&dax_region->kref);
+	if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region))
+		return NULL;
 	return dax_region;
 }
 EXPORT_SYMBOL_GPL(alloc_dax_region);
@@ -328,7 +422,6 @@ static phys_addr_t pgoff_to_phys(struct
 static int __dax_dev_fault(struct dax_dev *dax_dev, struct vm_area_struct *vma,
 		struct vm_fault *vmf)
 {
-	unsigned long vaddr = (unsigned long) vmf->virtual_address;
 	struct device *dev = &dax_dev->dev;
 	struct dax_region *dax_region;
 	int rc = VM_FAULT_SIGBUS;
@@ -353,7 +446,7 @@ static int __dax_dev_fault(struct dax_de
 
 	pfn = phys_to_pfn_t(phys, dax_region->pfn_flags);
 
-	rc = vm_insert_mixed(vma, vaddr, pfn);
+	rc = vm_insert_mixed(vma, vmf->address, pfn);
 
 	if (rc == -ENOMEM)
 		return VM_FAULT_OOM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dax/pmem.c linux-libre-4.10-rc8-gnu/drivers/dax/pmem.c
--- linux-libre-4.9-gnu/drivers/dax/pmem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dax/pmem.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,8 @@ static int dax_pmem_probe(struct device
 	pfn_sb = nd_pfn->pfn_sb;
 
 	if (!devm_request_mem_region(dev, nsio->res.start,
-				resource_size(&nsio->res), dev_name(dev))) {
+				resource_size(&nsio->res),
+				dev_name(&ndns->dev))) {
 		dev_warn(dev, "could not reserve region %pR\n", &nsio->res);
 		return -EBUSY;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/devfreq/devfreq.c linux-libre-4.10-rc8-gnu/drivers/devfreq/devfreq.c
--- linux-libre-4.9-gnu/drivers/devfreq/devfreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/devfreq/devfreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -593,11 +593,16 @@ struct devfreq *devfreq_add_device(struc
 	list_add(&devfreq->node, &devfreq_list);
 
 	governor = find_devfreq_governor(devfreq->governor_name);
-	if (!IS_ERR(governor))
-		devfreq->governor = governor;
-	if (devfreq->governor)
-		err = devfreq->governor->event_handler(devfreq,
-					DEVFREQ_GOV_START, NULL);
+	if (IS_ERR(governor)) {
+		dev_err(dev, "%s: Unable to find governor for the device\n",
+			__func__);
+		err = PTR_ERR(governor);
+		goto err_init;
+	}
+
+	devfreq->governor = governor;
+	err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START,
+						NULL);
 	if (err) {
 		dev_err(dev, "%s: Unable to start governor for the device\n",
 			__func__);
@@ -850,7 +855,7 @@ err_out:
 EXPORT_SYMBOL(devfreq_add_governor);
 
 /**
- * devfreq_remove_device() - Remove devfreq feature from a device.
+ * devfreq_remove_governor() - Remove devfreq feature from a device.
  * @governor:	the devfreq governor to be removed
  */
 int devfreq_remove_governor(struct devfreq_governor *governor)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/devfreq/event/exynos-nocp.c linux-libre-4.10-rc8-gnu/drivers/devfreq/event/exynos-nocp.c
--- linux-libre-4.9-gnu/drivers/devfreq/event/exynos-nocp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/devfreq/event/exynos-nocp.c	2017-02-12 16:03:20.000000000 -0500
@@ -190,6 +190,7 @@ static const struct of_device_id exynos_
 	{ .compatible = "samsung,exynos5420-nocp", },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, exynos_nocp_id_match);
 
 static struct regmap_config exynos_nocp_regmap_config = {
 	.reg_bits = 32,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/devfreq/event/exynos-ppmu.c linux-libre-4.10-rc8-gnu/drivers/devfreq/event/exynos-ppmu.c
--- linux-libre-4.9-gnu/drivers/devfreq/event/exynos-ppmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/devfreq/event/exynos-ppmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,6 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
@@ -34,7 +33,6 @@ struct exynos_ppmu {
 	unsigned int num_events;
 
 	struct device *dev;
-	struct mutex lock;
 
 	struct exynos_ppmu_data ppmu;
 };
@@ -90,8 +88,6 @@ struct __exynos_ppmu_events {
 	PPMU_EVENT(d1-cpu),
 	PPMU_EVENT(d1-general),
 	PPMU_EVENT(d1-rt),
-
-	{ /* sentinel */ },
 };
 
 static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
@@ -351,6 +347,7 @@ static const struct of_device_id exynos_
 	},
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, exynos_ppmu_id_match);
 
 static struct devfreq_event_ops *exynos_bus_get_ops(struct device_node *np)
 {
@@ -463,7 +460,6 @@ static int exynos_ppmu_probe(struct plat
 	if (!info)
 		return -ENOMEM;
 
-	mutex_init(&info->lock);
 	info->dev = &pdev->dev;
 
 	/* Parse dt data to get resource */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/devfreq/event/rockchip-dfi.c linux-libre-4.10-rc8-gnu/drivers/devfreq/event/rockchip-dfi.c
--- linux-libre-4.9-gnu/drivers/devfreq/event/rockchip-dfi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/devfreq/event/rockchip-dfi.c	2017-02-12 16:03:20.000000000 -0500
@@ -188,6 +188,7 @@ static const struct of_device_id rockchi
 	{ .compatible = "rockchip,rk3399-dfi" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match);
 
 static int rockchip_dfi_probe(struct platform_device *pdev)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/devfreq/exynos-bus.c linux-libre-4.10-rc8-gnu/drivers/devfreq/exynos-bus.c
--- linux-libre-4.9-gnu/drivers/devfreq/exynos-bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/devfreq/exynos-bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@ struct exynos_bus {
 	unsigned int edev_count;
 	struct mutex lock;
 
-	struct dev_pm_opp *curr_opp;
+	unsigned long curr_freq;
 
 	struct regulator *regulator;
 	struct clk *clk;
@@ -99,7 +99,7 @@ static int exynos_bus_target(struct devi
 {
 	struct exynos_bus *bus = dev_get_drvdata(dev);
 	struct dev_pm_opp *new_opp;
-	unsigned long old_freq, new_freq, old_volt, new_volt, tol;
+	unsigned long old_freq, new_freq, new_volt, tol;
 	int ret = 0;
 
 	/* Get new opp-bus instance according to new bus clock */
@@ -113,8 +113,7 @@ static int exynos_bus_target(struct devi
 
 	new_freq = dev_pm_opp_get_freq(new_opp);
 	new_volt = dev_pm_opp_get_voltage(new_opp);
-	old_freq = dev_pm_opp_get_freq(bus->curr_opp);
-	old_volt = dev_pm_opp_get_voltage(bus->curr_opp);
+	old_freq = bus->curr_freq;
 	rcu_read_unlock();
 
 	if (old_freq == new_freq)
@@ -146,7 +145,7 @@ static int exynos_bus_target(struct devi
 			goto out;
 		}
 	}
-	bus->curr_opp = new_opp;
+	bus->curr_freq = new_freq;
 
 	dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
 			old_freq/1000, new_freq/1000);
@@ -163,9 +162,7 @@ static int exynos_bus_get_dev_status(str
 	struct devfreq_event_data edata;
 	int ret;
 
-	rcu_read_lock();
-	stat->current_frequency = dev_pm_opp_get_freq(bus->curr_opp);
-	rcu_read_unlock();
+	stat->current_frequency = bus->curr_freq;
 
 	ret = exynos_bus_get_event(bus, &edata);
 	if (ret < 0) {
@@ -226,7 +223,7 @@ static int exynos_bus_passive_target(str
 	}
 
 	new_freq = dev_pm_opp_get_freq(new_opp);
-	old_freq = dev_pm_opp_get_freq(bus->curr_opp);
+	old_freq = bus->curr_freq;
 	rcu_read_unlock();
 
 	if (old_freq == new_freq)
@@ -242,7 +239,7 @@ static int exynos_bus_passive_target(str
 	}
 
 	*freq = new_freq;
-	bus->curr_opp = new_opp;
+	bus->curr_freq = new_freq;
 
 	dev_dbg(dev, "Set the frequency of bus (%lukHz -> %lukHz)\n",
 			old_freq/1000, new_freq/1000);
@@ -335,6 +332,7 @@ static int exynos_bus_parse_of(struct de
 			      struct exynos_bus *bus)
 {
 	struct device *dev = bus->dev;
+	struct dev_pm_opp *opp;
 	unsigned long rate;
 	int ret;
 
@@ -352,22 +350,23 @@ static int exynos_bus_parse_of(struct de
 	}
 
 	/* Get the freq and voltage from OPP table to scale the bus freq */
-	rcu_read_lock();
 	ret = dev_pm_opp_of_add_table(dev);
 	if (ret < 0) {
 		dev_err(dev, "failed to get OPP table\n");
-		rcu_read_unlock();
 		goto err_clk;
 	}
 
 	rate = clk_get_rate(bus->clk);
-	bus->curr_opp = devfreq_recommended_opp(dev, &rate, 0);
-	if (IS_ERR(bus->curr_opp)) {
+
+	rcu_read_lock();
+	opp = devfreq_recommended_opp(dev, &rate, 0);
+	if (IS_ERR(opp)) {
 		dev_err(dev, "failed to find dev_pm_opp\n");
 		rcu_read_unlock();
-		ret = PTR_ERR(bus->curr_opp);
+		ret = PTR_ERR(opp);
 		goto err_opp;
 	}
+	bus->curr_freq = dev_pm_opp_get_freq(opp);
 	rcu_read_unlock();
 
 	return 0;
@@ -498,7 +497,7 @@ passive:
 	if (IS_ERR(bus->devfreq)) {
 		dev_err(dev,
 			"failed to add devfreq dev with passive governor\n");
-		ret = -EPROBE_DEFER;
+		ret = PTR_ERR(bus->devfreq);
 		goto err;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/devfreq/rk3399_dmc.c linux-libre-4.10-rc8-gnu/drivers/devfreq/rk3399_dmc.c
--- linux-libre-4.9-gnu/drivers/devfreq/rk3399_dmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/devfreq/rk3399_dmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,7 +80,6 @@ struct rk3399_dmcfreq {
 	struct regulator *vdd_center;
 	unsigned long rate, target_rate;
 	unsigned long volt, target_volt;
-	struct dev_pm_opp *curr_opp;
 };
 
 static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
@@ -102,9 +101,6 @@ static int rk3399_dmcfreq_target(struct
 	target_rate = dev_pm_opp_get_freq(opp);
 	target_volt = dev_pm_opp_get_voltage(opp);
 
-	dmcfreq->rate = dev_pm_opp_get_freq(dmcfreq->curr_opp);
-	dmcfreq->volt = dev_pm_opp_get_voltage(dmcfreq->curr_opp);
-
 	rcu_read_unlock();
 
 	if (dmcfreq->rate == target_rate)
@@ -165,7 +161,9 @@ static int rk3399_dmcfreq_target(struct
 	if (err)
 		dev_err(dev, "Cannot to set vol %lu uV\n", target_volt);
 
-	dmcfreq->curr_opp = opp;
+	dmcfreq->rate = target_rate;
+	dmcfreq->volt = target_volt;
+
 out:
 	mutex_unlock(&dmcfreq->lock);
 	return err;
@@ -414,7 +412,6 @@ static int rk3399_dmcfreq_probe(struct p
 	 */
 	if (dev_pm_opp_of_add_table(dev)) {
 		dev_err(dev, "Invalid operating-points in device tree.\n");
-		rcu_read_unlock();
 		return -EINVAL;
 	}
 
@@ -431,12 +428,13 @@ static int rk3399_dmcfreq_probe(struct p
 		rcu_read_unlock();
 		return PTR_ERR(opp);
 	}
+	data->rate = dev_pm_opp_get_freq(opp);
+	data->volt = dev_pm_opp_get_voltage(opp);
 	rcu_read_unlock();
-	data->curr_opp = opp;
 
 	rk3399_devfreq_dmc_profile.initial_freq = data->rate;
 
-	data->devfreq = devfreq_add_device(dev,
+	data->devfreq = devm_devfreq_add_device(dev,
 					   &rk3399_devfreq_dmc_profile,
 					   "simple_ondemand",
 					   &data->ondemand_data);
@@ -454,6 +452,7 @@ static const struct of_device_id rk3399d
 	{ .compatible = "rockchip,rk3399-dmc" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, rk3399dmc_devfreq_of_match);
 
 static struct platform_driver rk3399_dmcfreq_driver = {
 	.probe	= rk3399_dmcfreq_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dio/dio.c linux-libre-4.10-rc8-gnu/drivers/dio/dio.c
--- linux-libre-4.9-gnu/drivers/dio/dio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dio/dio.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/init.h>
 #include <linux/dio.h>
 #include <linux/slab.h>                         /* kmalloc() */
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>                             /* readb() */
 
 struct dio_bus dio_bus = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/amba-pl08x.c linux-libre-4.10-rc8-gnu/drivers/dma/amba-pl08x.c
--- linux-libre-4.9-gnu/drivers/dma/amba-pl08x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/amba-pl08x.c	2017-02-12 16:03:20.000000000 -0500
@@ -1793,6 +1793,13 @@ bool pl08x_filter_id(struct dma_chan *ch
 }
 EXPORT_SYMBOL_GPL(pl08x_filter_id);
 
+static bool pl08x_filter_fn(struct dma_chan *chan, void *chan_id)
+{
+	struct pl08x_dma_chan *plchan = to_pl08x_chan(chan);
+
+	return plchan->cd == chan_id;
+}
+
 /*
  * Just check that the device is there and active
  * TODO: turn this bit on/off depending on the number of physical channels
@@ -2307,6 +2314,10 @@ static int pl08x_probe(struct amba_devic
 			ret = -EINVAL;
 			goto out_no_platdata;
 		}
+	} else {
+		pl08x->slave.filter.map = pl08x->pd->slave_map;
+		pl08x->slave.filter.mapcnt = pl08x->pd->slave_map_len;
+		pl08x->slave.filter.fn = pl08x_filter_fn;
 	}
 
 	/* By default, AHB1 only.  If dualmaster, from platform */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/at_hdmac.c linux-libre-4.10-rc8-gnu/drivers/dma/at_hdmac.c
--- linux-libre-4.9-gnu/drivers/dma/at_hdmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/at_hdmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -111,9 +111,8 @@ static struct at_desc *atc_alloc_descrip
 	struct at_dma	*atdma = to_at_dma(chan->device);
 	dma_addr_t phys;
 
-	desc = dma_pool_alloc(atdma->dma_desc_pool, gfp_flags, &phys);
+	desc = dma_pool_zalloc(atdma->dma_desc_pool, gfp_flags, &phys);
 	if (desc) {
-		memset(desc, 0, sizeof(struct at_desc));
 		INIT_LIST_HEAD(&desc->tx_list);
 		dma_async_tx_descriptor_init(&desc->txd, chan);
 		/* txd.flags will be overwritten in prep functions */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/at_xdmac.c linux-libre-4.10-rc8-gnu/drivers/dma/at_xdmac.c
--- linux-libre-4.9-gnu/drivers/dma/at_xdmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/at_xdmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -221,7 +221,6 @@ struct at_xdmac {
 	int			irq;
 	struct clk		*clk;
 	u32			save_gim;
-	u32			save_gs;
 	struct dma_pool		*at_xdmac_desc_pool;
 	struct at_xdmac_chan	chan[0];
 };
@@ -444,9 +443,8 @@ static struct at_xdmac_desc *at_xdmac_al
 	struct at_xdmac		*atxdmac = to_at_xdmac(chan->device);
 	dma_addr_t		phys;
 
-	desc = dma_pool_alloc(atxdmac->at_xdmac_desc_pool, gfp_flags, &phys);
+	desc = dma_pool_zalloc(atxdmac->at_xdmac_desc_pool, gfp_flags, &phys);
 	if (desc) {
-		memset(desc, 0, sizeof(*desc));
 		INIT_LIST_HEAD(&desc->descs_list);
 		dma_async_tx_descriptor_init(&desc->tx_dma_desc, chan);
 		desc->tx_dma_desc.tx_submit = at_xdmac_tx_submit;
@@ -1896,7 +1894,6 @@ static int atmel_xdmac_resume(struct dev
 	}
 
 	at_xdmac_write(atxdmac, AT_XDMAC_GIE, atxdmac->save_gim);
-	at_xdmac_write(atxdmac, AT_XDMAC_GE, atxdmac->save_gs);
 	list_for_each_entry_safe(chan, _chan, &atxdmac->dma.channels, device_node) {
 		atchan = to_at_xdmac_chan(chan);
 		at_xdmac_chan_write(atchan, AT_XDMAC_CC, atchan->save_cc);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/cppi41.c linux-libre-4.10-rc8-gnu/drivers/dma/cppi41.c
--- linux-libre-4.9-gnu/drivers/dma/cppi41.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/cppi41.c	2017-02-12 16:03:20.000000000 -0500
@@ -153,6 +153,8 @@ struct cppi41_dd {
 
 	/* context for suspend/resume */
 	unsigned int dma_tdfdq;
+
+	bool is_suspended;
 };
 
 #define FIST_COMPLETION_QUEUE	93
@@ -257,6 +259,10 @@ static struct cppi41_channel *desc_to_ch
 	BUG_ON(desc_num >= ALLOC_DECS_NUM);
 	c = cdd->chan_busy[desc_num];
 	cdd->chan_busy[desc_num] = NULL;
+
+	/* Usecount for chan_busy[], paired with push_desc_queue() */
+	pm_runtime_put(cdd->ddev.dev);
+
 	return c;
 }
 
@@ -317,12 +323,12 @@ static irqreturn_t cppi41_irq(int irq, v
 
 		while (val) {
 			u32 desc, len;
-			int error;
 
-			error = pm_runtime_get(cdd->ddev.dev);
-			if (error < 0)
-				dev_err(cdd->ddev.dev, "%s pm runtime get: %i\n",
-					__func__, error);
+			/*
+			 * This should never trigger, see the comments in
+			 * push_desc_queue()
+			 */
+			WARN_ON(cdd->is_suspended);
 
 			q_num = __fls(val);
 			val &= ~(1 << q_num);
@@ -343,9 +349,6 @@ static irqreturn_t cppi41_irq(int irq, v
 			c->residue = pd_trans_len(c->desc->pd6) - len;
 			dma_cookie_complete(&c->txd);
 			dmaengine_desc_get_callback_invoke(&c->txd, NULL);
-
-			pm_runtime_mark_last_busy(cdd->ddev.dev);
-			pm_runtime_put_autosuspend(cdd->ddev.dev);
 		}
 	}
 	return IRQ_HANDLED;
@@ -447,6 +450,15 @@ static void push_desc_queue(struct cppi4
 	 */
 	__iowmb();
 
+	/*
+	 * DMA transfers can take at least 200ms to complete with USB mass
+	 * storage connected. To prevent autosuspend timeouts, we must use
+	 * pm_runtime_get/put() when chan_busy[] is modified. This will get
+	 * cleared in desc_to_chan() or cppi41_stop_chan() depending on the
+	 * outcome of the transfer.
+	 */
+	pm_runtime_get(cdd->ddev.dev);
+
 	desc_phys = lower_32_bits(c->desc_phys);
 	desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
 	WARN_ON(cdd->chan_busy[desc_num]);
@@ -457,20 +469,26 @@ static void push_desc_queue(struct cppi4
 	cppi_writel(reg, cdd->qmgr_mem + QMGR_QUEUE_D(c->q_num));
 }
 
-static void pending_desc(struct cppi41_channel *c)
+/*
+ * Caller must hold cdd->lock to prevent push_desc_queue()
+ * getting called out of order. We have both cppi41_dma_issue_pending()
+ * and cppi41_runtime_resume() call this function.
+ */
+static void cppi41_run_queue(struct cppi41_dd *cdd)
 {
-	struct cppi41_dd *cdd = c->cdd;
-	unsigned long flags;
+	struct cppi41_channel *c, *_c;
 
-	spin_lock_irqsave(&cdd->lock, flags);
-	list_add_tail(&c->node, &cdd->pending);
-	spin_unlock_irqrestore(&cdd->lock, flags);
+	list_for_each_entry_safe(c, _c, &cdd->pending, node) {
+		push_desc_queue(c);
+		list_del(&c->node);
+	}
 }
 
 static void cppi41_dma_issue_pending(struct dma_chan *chan)
 {
 	struct cppi41_channel *c = to_cpp41_chan(chan);
 	struct cppi41_dd *cdd = c->cdd;
+	unsigned long flags;
 	int error;
 
 	error = pm_runtime_get(cdd->ddev.dev);
@@ -482,10 +500,11 @@ static void cppi41_dma_issue_pending(str
 		return;
 	}
 
-	if (likely(pm_runtime_active(cdd->ddev.dev)))
-		push_desc_queue(c);
-	else
-		pending_desc(c);
+	spin_lock_irqsave(&cdd->lock, flags);
+	list_add_tail(&c->node, &cdd->pending);
+	if (!cdd->is_suspended)
+		cppi41_run_queue(cdd);
+	spin_unlock_irqrestore(&cdd->lock, flags);
 
 	pm_runtime_mark_last_busy(cdd->ddev.dev);
 	pm_runtime_put_autosuspend(cdd->ddev.dev);
@@ -705,6 +724,9 @@ static int cppi41_stop_chan(struct dma_c
 	WARN_ON(!cdd->chan_busy[desc_num]);
 	cdd->chan_busy[desc_num] = NULL;
 
+	/* Usecount for chan_busy[], paired with push_desc_queue() */
+	pm_runtime_put(cdd->ddev.dev);
+
 	return 0;
 }
 
@@ -1150,8 +1172,12 @@ static int __maybe_unused cppi41_resume(
 static int __maybe_unused cppi41_runtime_suspend(struct device *dev)
 {
 	struct cppi41_dd *cdd = dev_get_drvdata(dev);
+	unsigned long flags;
 
+	spin_lock_irqsave(&cdd->lock, flags);
+	cdd->is_suspended = true;
 	WARN_ON(!list_empty(&cdd->pending));
+	spin_unlock_irqrestore(&cdd->lock, flags);
 
 	return 0;
 }
@@ -1159,14 +1185,11 @@ static int __maybe_unused cppi41_runtime
 static int __maybe_unused cppi41_runtime_resume(struct device *dev)
 {
 	struct cppi41_dd *cdd = dev_get_drvdata(dev);
-	struct cppi41_channel *c, *_c;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cdd->lock, flags);
-	list_for_each_entry_safe(c, _c, &cdd->pending, node) {
-		push_desc_queue(c);
-		list_del(&c->node);
-	}
+	cdd->is_suspended = false;
+	cppi41_run_queue(cdd);
 	spin_unlock_irqrestore(&cdd->lock, flags);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/dmatest.c linux-libre-4.10-rc8-gnu/drivers/dma/dmatest.c
--- linux-libre-4.9-gnu/drivers/dma/dmatest.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/dmatest.c	2017-02-12 16:03:20.000000000 -0500
@@ -164,7 +164,9 @@ struct dmatest_thread {
 	struct task_struct	*task;
 	struct dma_chan		*chan;
 	u8			**srcs;
+	u8			**usrcs;
 	u8			**dsts;
+	u8			**udsts;
 	enum dma_transaction_type type;
 	bool			done;
 };
@@ -427,10 +429,11 @@ static int dmatest_func(void *data)
 	int			dst_cnt;
 	int			i;
 	ktime_t			ktime, start, diff;
-	ktime_t			filltime = ktime_set(0, 0);
-	ktime_t			comparetime = ktime_set(0, 0);
+	ktime_t			filltime = 0;
+	ktime_t			comparetime = 0;
 	s64			runtime = 0;
 	unsigned long long	total_len = 0;
+	u8			align = 0;
 
 	set_freezable();
 
@@ -441,20 +444,24 @@ static int dmatest_func(void *data)
 	params = &info->params;
 	chan = thread->chan;
 	dev = chan->device;
-	if (thread->type == DMA_MEMCPY)
+	if (thread->type == DMA_MEMCPY) {
+		align = dev->copy_align;
 		src_cnt = dst_cnt = 1;
-	else if (thread->type == DMA_SG)
+	} else if (thread->type == DMA_SG) {
+		align = dev->copy_align;
 		src_cnt = dst_cnt = sg_buffers;
-	else if (thread->type == DMA_XOR) {
+	} else if (thread->type == DMA_XOR) {
 		/* force odd to ensure dst = src */
 		src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
 		dst_cnt = 1;
+		align = dev->xor_align;
 	} else if (thread->type == DMA_PQ) {
 		/* force odd to ensure dst = src */
 		src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
 		dst_cnt = 2;
+		align = dev->pq_align;
 
-		pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL);
+		pq_coefs = kmalloc(params->pq_sources + 1, GFP_KERNEL);
 		if (!pq_coefs)
 			goto err_thread_type;
 
@@ -463,23 +470,47 @@ static int dmatest_func(void *data)
 	} else
 		goto err_thread_type;
 
-	thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL);
+	thread->srcs = kcalloc(src_cnt + 1, sizeof(u8 *), GFP_KERNEL);
 	if (!thread->srcs)
 		goto err_srcs;
+
+	thread->usrcs = kcalloc(src_cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!thread->usrcs)
+		goto err_usrcs;
+
 	for (i = 0; i < src_cnt; i++) {
-		thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL);
-		if (!thread->srcs[i])
+		thread->usrcs[i] = kmalloc(params->buf_size + align,
+					   GFP_KERNEL);
+		if (!thread->usrcs[i])
 			goto err_srcbuf;
+
+		/* align srcs to alignment restriction */
+		if (align)
+			thread->srcs[i] = PTR_ALIGN(thread->usrcs[i], align);
+		else
+			thread->srcs[i] = thread->usrcs[i];
 	}
 	thread->srcs[i] = NULL;
 
-	thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL);
+	thread->dsts = kcalloc(dst_cnt + 1, sizeof(u8 *), GFP_KERNEL);
 	if (!thread->dsts)
 		goto err_dsts;
+
+	thread->udsts = kcalloc(dst_cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!thread->udsts)
+		goto err_udsts;
+
 	for (i = 0; i < dst_cnt; i++) {
-		thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL);
-		if (!thread->dsts[i])
+		thread->udsts[i] = kmalloc(params->buf_size + align,
+					   GFP_KERNEL);
+		if (!thread->udsts[i])
 			goto err_dstbuf;
+
+		/* align dsts to alignment restriction */
+		if (align)
+			thread->dsts[i] = PTR_ALIGN(thread->udsts[i], align);
+		else
+			thread->dsts[i] = thread->udsts[i];
 	}
 	thread->dsts[i] = NULL;
 
@@ -498,20 +529,11 @@ static int dmatest_func(void *data)
 		dma_addr_t srcs[src_cnt];
 		dma_addr_t *dsts;
 		unsigned int src_off, dst_off, len;
-		u8 align = 0;
 		struct scatterlist tx_sg[src_cnt];
 		struct scatterlist rx_sg[src_cnt];
 
 		total_tests++;
 
-		/* honor alignment restrictions */
-		if (thread->type == DMA_MEMCPY || thread->type == DMA_SG)
-			align = dev->copy_align;
-		else if (thread->type == DMA_XOR)
-			align = dev->xor_align;
-		else if (thread->type == DMA_PQ)
-			align = dev->pq_align;
-
 		if (1 << align > params->buf_size) {
 			pr_err("%u-byte buffer too small for %d-byte alignment\n",
 			       params->buf_size, 1 << align);
@@ -549,7 +571,7 @@ static int dmatest_func(void *data)
 			filltime = ktime_add(filltime, diff);
 		}
 
-		um = dmaengine_get_unmap_data(dev->dev, src_cnt+dst_cnt,
+		um = dmaengine_get_unmap_data(dev->dev, src_cnt + dst_cnt,
 					      GFP_KERNEL);
 		if (!um) {
 			failed_tests++;
@@ -729,13 +751,17 @@ static int dmatest_func(void *data)
 
 	ret = 0;
 err_dstbuf:
-	for (i = 0; thread->dsts[i]; i++)
-		kfree(thread->dsts[i]);
+	for (i = 0; thread->udsts[i]; i++)
+		kfree(thread->udsts[i]);
+	kfree(thread->udsts);
+err_udsts:
 	kfree(thread->dsts);
 err_dsts:
 err_srcbuf:
-	for (i = 0; thread->srcs[i]; i++)
-		kfree(thread->srcs[i]);
+	for (i = 0; thread->usrcs[i]; i++)
+		kfree(thread->usrcs[i]);
+	kfree(thread->usrcs);
+err_usrcs:
 	kfree(thread->srcs);
 err_srcs:
 	kfree(pq_coefs);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/dw/core.c linux-libre-4.10-rc8-gnu/drivers/dma/dw/core.c
--- linux-libre-4.9-gnu/drivers/dma/dw/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/dw/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1569,7 +1569,7 @@ int dw_dma_probe(struct dw_dma_chip *chi
 				(dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0;
 		} else {
 			dwc->block_size = pdata->block_size;
-			dwc->nollp = pdata->is_nollp;
+			dwc->nollp = !pdata->multi_block[i];
 		}
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/dw/Kconfig linux-libre-4.10-rc8-gnu/drivers/dma/dw/Kconfig
--- linux-libre-4.9-gnu/drivers/dma/dw/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/dw/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -24,5 +24,5 @@ config DW_DMAC_PCI
 	select DW_DMAC_CORE
 	help
 	  Support the Synopsys DesignWare AHB DMA controller on the
-	  platfroms that enumerate it as a PCI device. For example,
+	  platforms that enumerate it as a PCI device. For example,
 	  Intel Medfield has integrated this GPDMA controller.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/dw/platform.c linux-libre-4.10-rc8-gnu/drivers/dma/dw/platform.c
--- linux-libre-4.9-gnu/drivers/dma/dw/platform.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/dw/platform.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,7 @@ dw_dma_parse_dt(struct platform_device *
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct dw_dma_platform_data *pdata;
-	u32 tmp, arr[DW_DMA_MAX_NR_MASTERS];
+	u32 tmp, arr[DW_DMA_MAX_NR_MASTERS], mb[DW_DMA_MAX_NR_CHANNELS];
 	u32 nr_masters;
 	u32 nr_channels;
 
@@ -118,6 +118,8 @@ dw_dma_parse_dt(struct platform_device *
 
 	if (of_property_read_u32(np, "dma-channels", &nr_channels))
 		return NULL;
+	if (nr_channels > DW_DMA_MAX_NR_CHANNELS)
+		return NULL;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -129,6 +131,12 @@ dw_dma_parse_dt(struct platform_device *
 	if (of_property_read_bool(np, "is_private"))
 		pdata->is_private = true;
 
+	/*
+	 * All known devices, which use DT for configuration, support
+	 * memory-to-memory transfers. So enable it by default.
+	 */
+	pdata->is_memcpy = true;
+
 	if (!of_property_read_u32(np, "chan_allocation_order", &tmp))
 		pdata->chan_allocation_order = (unsigned char)tmp;
 
@@ -146,6 +154,14 @@ dw_dma_parse_dt(struct platform_device *
 			pdata->data_width[tmp] = BIT(arr[tmp] & 0x07);
 	}
 
+	if (!of_property_read_u32_array(np, "multi-block", mb, nr_channels)) {
+		for (tmp = 0; tmp < nr_channels; tmp++)
+			pdata->multi_block[tmp] = mb[tmp];
+	} else {
+		for (tmp = 0; tmp < nr_channels; tmp++)
+			pdata->multi_block[tmp] = 1;
+	}
+
 	return pdata;
 }
 #else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/dw/regs.h linux-libre-4.10-rc8-gnu/drivers/dma/dw/regs.h
--- linux-libre-4.9-gnu/drivers/dma/dw/regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/dw/regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,8 @@
 #include <linux/interrupt.h>
 #include <linux/dmaengine.h>
 
-#define DW_DMA_MAX_NR_CHANNELS	8
+#include "internal.h"
+
 #define DW_DMA_MAX_NR_REQUESTS	16
 
 /* flow controller */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/edma.c linux-libre-4.10-rc8-gnu/drivers/dma/edma.c
--- linux-libre-4.9-gnu/drivers/dma/edma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/edma.c	2017-02-12 16:03:20.000000000 -0500
@@ -2451,6 +2451,9 @@ static int edma_pm_resume(struct device
 	int i;
 	s8 (*queue_priority_mapping)[2];
 
+	/* re initialize dummy slot to dummy param set */
+	edma_write_slot(ecc, ecc->dummy_slot, &dummy_paramset);
+
 	queue_priority_mapping = ecc->info->queue_priority_mapping;
 
 	/* Event queue priority mapping */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/fsl_raid.c linux-libre-4.10-rc8-gnu/drivers/dma/fsl_raid.c
--- linux-libre-4.9-gnu/drivers/dma/fsl_raid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/fsl_raid.c	2017-02-12 16:03:20.000000000 -0500
@@ -881,6 +881,7 @@ static struct of_device_id fsl_re_ids[]
 	{ .compatible = "fsl,raideng-v1.0", },
 	{}
 };
+MODULE_DEVICE_TABLE(of, fsl_re_ids);
 
 static struct platform_driver fsl_re_driver = {
 	.driver = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/hsu/pci.c linux-libre-4.10-rc8-gnu/drivers/dma/hsu/pci.c
--- linux-libre-4.9-gnu/drivers/dma/hsu/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/hsu/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,13 +77,15 @@ static int hsu_pci_probe(struct pci_dev
 	if (!chip)
 		return -ENOMEM;
 
+	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+	if (ret < 0)
+		return ret;
+
 	chip->dev = &pdev->dev;
 	chip->regs = pcim_iomap_table(pdev)[0];
 	chip->length = pci_resource_len(pdev, 0);
 	chip->offset = HSU_PCI_CHAN_OFFSET;
-	chip->irq = pdev->irq;
-
-	pci_enable_msi(pdev);
+	chip->irq = pci_irq_vector(pdev, 0);
 
 	ret = hsu_dma_probe(chip);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/img-mdc-dma.c linux-libre-4.10-rc8-gnu/drivers/dma/img-mdc-dma.c
--- linux-libre-4.9-gnu/drivers/dma/img-mdc-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/img-mdc-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -292,7 +292,7 @@ static struct dma_async_tx_descriptor *m
 	struct mdc_dma *mdma = mchan->mdma;
 	struct mdc_tx_desc *mdesc;
 	struct mdc_hw_list_desc *curr, *prev = NULL;
-	dma_addr_t curr_phys, prev_phys;
+	dma_addr_t curr_phys;
 
 	if (!len)
 		return NULL;
@@ -324,7 +324,6 @@ static struct dma_async_tx_descriptor *m
 				     xfer_size);
 
 		prev = curr;
-		prev_phys = curr_phys;
 
 		mdesc->list_len++;
 		src += xfer_size;
@@ -375,7 +374,7 @@ static struct dma_async_tx_descriptor *m
 	struct mdc_dma *mdma = mchan->mdma;
 	struct mdc_tx_desc *mdesc;
 	struct mdc_hw_list_desc *curr, *prev = NULL;
-	dma_addr_t curr_phys, prev_phys;
+	dma_addr_t curr_phys;
 
 	if (!buf_len && !period_len)
 		return NULL;
@@ -430,7 +429,6 @@ static struct dma_async_tx_descriptor *m
 			}
 
 			prev = curr;
-			prev_phys = curr_phys;
 
 			mdesc->list_len++;
 			buf_addr += xfer_size;
@@ -458,7 +456,7 @@ static struct dma_async_tx_descriptor *m
 	struct mdc_tx_desc *mdesc;
 	struct scatterlist *sg;
 	struct mdc_hw_list_desc *curr, *prev = NULL;
-	dma_addr_t curr_phys, prev_phys;
+	dma_addr_t curr_phys;
 	unsigned int i;
 
 	if (!sgl)
@@ -509,7 +507,6 @@ static struct dma_async_tx_descriptor *m
 			}
 
 			prev = curr;
-			prev_phys = curr_phys;
 
 			mdesc->list_len++;
 			mdesc->list_xfer_size += xfer_size;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/imx-sdma.c linux-libre-4.10-rc8-gnu/drivers/dma/imx-sdma.c
--- linux-libre-4.9-gnu/drivers/dma/imx-sdma.c	2016-12-11 17:43:02.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/imx-sdma.c	2017-02-12 17:26:57.000000000 -0500
@@ -298,6 +298,7 @@ struct sdma_engine;
  * @event_id1		for channels that use 2 events
  * @word_size		peripheral access size
  * @buf_tail		ID of the buffer that was processed
+ * @buf_ptail		ID of the previous buffer that was processed
  * @num_bd		max NUM_BD. number of descriptors currently handling
  */
 struct sdma_channel {
@@ -309,6 +310,7 @@ struct sdma_channel {
 	unsigned int			event_id1;
 	enum dma_slave_buswidth		word_size;
 	unsigned int			buf_tail;
+	unsigned int			buf_ptail;
 	unsigned int			num_bd;
 	unsigned int			period_len;
 	struct sdma_buffer_descriptor	*bd;
@@ -700,6 +702,8 @@ static void sdma_update_channel_loop(str
 		sdmac->chn_real_count = bd->mode.count;
 		bd->mode.status |= BD_DONE;
 		bd->mode.count = sdmac->period_len;
+		sdmac->buf_ptail = sdmac->buf_tail;
+		sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
 
 		/*
 		 * The callback is called from the interrupt context in order
@@ -710,9 +714,6 @@ static void sdma_update_channel_loop(str
 
 		dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
 
-		sdmac->buf_tail++;
-		sdmac->buf_tail %= sdmac->num_bd;
-
 		if (error)
 			sdmac->status = old_status;
 	}
@@ -1186,6 +1187,8 @@ static struct dma_async_tx_descriptor *s
 	sdmac->flags = 0;
 
 	sdmac->buf_tail = 0;
+	sdmac->buf_ptail = 0;
+	sdmac->chn_real_count = 0;
 
 	dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
 			sg_len, channel);
@@ -1288,6 +1291,8 @@ static struct dma_async_tx_descriptor *s
 	sdmac->status = DMA_IN_PROGRESS;
 
 	sdmac->buf_tail = 0;
+	sdmac->buf_ptail = 0;
+	sdmac->chn_real_count = 0;
 	sdmac->period_len = period_len;
 
 	sdmac->flags |= IMX_DMA_SG_LOOP;
@@ -1385,7 +1390,7 @@ static enum dma_status sdma_tx_status(st
 	u32 residue;
 
 	if (sdmac->flags & IMX_DMA_SG_LOOP)
-		residue = (sdmac->num_bd - sdmac->buf_tail) *
+		residue = (sdmac->num_bd - sdmac->buf_ptail) *
 			   sdmac->period_len - sdmac->chn_real_count;
 	else
 		residue = sdmac->chn_count - sdmac->chn_real_count;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/ioat/dma.c linux-libre-4.10-rc8-gnu/drivers/dma/ioat/dma.c
--- linux-libre-4.9-gnu/drivers/dma/ioat/dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/ioat/dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,7 @@
 #include "../dmaengine.h"
 
 static char *chanerr_str[] = {
+	"DMA Transfer Source Address Error",
 	"DMA Transfer Destination Address Error",
 	"Next Descriptor Address Error",
 	"Descriptor Error",
@@ -66,7 +67,6 @@ static char *chanerr_str[] = {
 	"Result Guard Tag verification Error",
 	"Result Application Tag verification Error",
 	"Result Reference Tag verification Error",
-	NULL
 };
 
 static void ioat_eh(struct ioatdma_chan *ioat_chan);
@@ -75,13 +75,10 @@ static void ioat_print_chanerrs(struct i
 {
 	int i;
 
-	for (i = 0; i < 32; i++) {
+	for (i = 0; i < ARRAY_SIZE(chanerr_str); i++) {
 		if ((chanerr >> i) & 1) {
-			if (chanerr_str[i]) {
-				dev_err(to_dev(ioat_chan), "Err(%d): %s\n",
-					i, chanerr_str[i]);
-			} else
-				break;
+			dev_err(to_dev(ioat_chan), "Err(%d): %s\n",
+				i, chanerr_str[i]);
 		}
 	}
 }
@@ -341,15 +338,12 @@ ioat_alloc_ring_ent(struct dma_chan *cha
 {
 	struct ioat_dma_descriptor *hw;
 	struct ioat_ring_ent *desc;
-	struct ioatdma_device *ioat_dma;
 	struct ioatdma_chan *ioat_chan = to_ioat_chan(chan);
 	int chunk;
 	dma_addr_t phys;
 	u8 *pos;
 	off_t offs;
 
-	ioat_dma = to_ioatdma_device(chan->device);
-
 	chunk = idx / IOAT_DESCS_PER_2M;
 	idx &= (IOAT_DESCS_PER_2M - 1);
 	offs = idx * IOAT_DESC_SZ;
@@ -614,11 +608,8 @@ static void __cleanup(struct ioatdma_cha
 
 		tx = &desc->txd;
 		if (tx->cookie) {
-			struct dmaengine_result res;
-
 			dma_cookie_complete(tx);
 			dma_descriptor_unmap(tx);
-			res.result = DMA_TRANS_NOERROR;
 			dmaengine_desc_get_callback_invoke(tx, NULL);
 			tx->callback = NULL;
 			tx->callback_result = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/ioat/hw.h linux-libre-4.10-rc8-gnu/drivers/dma/ioat/hw.h
--- linux-libre-4.9-gnu/drivers/dma/ioat/hw.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/ioat/hw.h	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,8 @@
 #define PCI_DEVICE_ID_INTEL_IOAT_BDX8	0x6f2e
 #define PCI_DEVICE_ID_INTEL_IOAT_BDX9	0x6f2f
 
+#define PCI_DEVICE_ID_INTEL_IOAT_SKX	0x2021
+
 #define IOAT_VER_1_2            0x12    /* Version 1.2 */
 #define IOAT_VER_2_0            0x20    /* Version 2.0 */
 #define IOAT_VER_3_0            0x30    /* Version 3.0 */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/ioat/init.c linux-libre-4.10-rc8-gnu/drivers/dma/ioat/init.c
--- linux-libre-4.9-gnu/drivers/dma/ioat/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/ioat/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -106,6 +106,8 @@ static struct pci_device_id ioat_pci_tbl
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) },
 
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SKX) },
+
 	/* I/OAT v3.3 platforms */
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) },
 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) },
@@ -243,10 +245,15 @@ static bool is_bdx_ioat(struct pci_dev *
 	}
 }
 
+static inline bool is_skx_ioat(struct pci_dev *pdev)
+{
+	return (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_SKX) ? true : false;
+}
+
 static bool is_xeon_cb32(struct pci_dev *pdev)
 {
 	return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) ||
-		is_hsw_ioat(pdev) || is_bdx_ioat(pdev);
+		is_hsw_ioat(pdev) || is_bdx_ioat(pdev) || is_skx_ioat(pdev);
 }
 
 bool is_bwd_ioat(struct pci_dev *pdev)
@@ -340,11 +347,13 @@ static int ioat_dma_self_test(struct ioa
 	dma_src = dma_map_single(dev, src, IOAT_TEST_SIZE, DMA_TO_DEVICE);
 	if (dma_mapping_error(dev, dma_src)) {
 		dev_err(dev, "mapping src buffer failed\n");
+		err = -ENOMEM;
 		goto free_resources;
 	}
 	dma_dest = dma_map_single(dev, dest, IOAT_TEST_SIZE, DMA_FROM_DEVICE);
 	if (dma_mapping_error(dev, dma_dest)) {
 		dev_err(dev, "mapping dest buffer failed\n");
+		err = -ENOMEM;
 		goto unmap_src;
 	}
 	flags = DMA_PREP_INTERRUPT;
@@ -691,7 +700,7 @@ static int ioat_alloc_chan_resources(str
 	/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
 	ioat_chan->completion =
 		dma_pool_zalloc(ioat_chan->ioat_dma->completion_pool,
-				GFP_KERNEL, &ioat_chan->completion_dma);
+				GFP_NOWAIT, &ioat_chan->completion_dma);
 	if (!ioat_chan->completion)
 		return -ENOMEM;
 
@@ -701,7 +710,7 @@ static int ioat_alloc_chan_resources(str
 	       ioat_chan->reg_base + IOAT_CHANCMP_OFFSET_HIGH);
 
 	order = IOAT_MAX_ORDER;
-	ring = ioat_alloc_ring(c, order, GFP_KERNEL);
+	ring = ioat_alloc_ring(c, order, GFP_NOWAIT);
 	if (!ring)
 		return -ENOMEM;
 
@@ -827,16 +836,20 @@ static int ioat_xor_val_self_test(struct
 	op = IOAT_OP_XOR;
 
 	dest_dma = dma_map_page(dev, dest, 0, PAGE_SIZE, DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, dest_dma))
+	if (dma_mapping_error(dev, dest_dma)) {
+		err = -ENOMEM;
 		goto free_resources;
+	}
 
 	for (i = 0; i < IOAT_NUM_SRC_TEST; i++)
 		dma_srcs[i] = DMA_ERROR_CODE;
 	for (i = 0; i < IOAT_NUM_SRC_TEST; i++) {
 		dma_srcs[i] = dma_map_page(dev, xor_srcs[i], 0, PAGE_SIZE,
 					   DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, dma_srcs[i]))
+		if (dma_mapping_error(dev, dma_srcs[i])) {
+			err = -ENOMEM;
 			goto dma_unmap;
+		}
 	}
 	tx = dma->device_prep_dma_xor(dma_chan, dest_dma, dma_srcs,
 				      IOAT_NUM_SRC_TEST, PAGE_SIZE,
@@ -904,8 +917,10 @@ static int ioat_xor_val_self_test(struct
 	for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) {
 		dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE,
 					   DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, dma_srcs[i]))
+		if (dma_mapping_error(dev, dma_srcs[i])) {
+			err = -ENOMEM;
 			goto dma_unmap;
+		}
 	}
 	tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs,
 					  IOAT_NUM_SRC_TEST + 1, PAGE_SIZE,
@@ -957,8 +972,10 @@ static int ioat_xor_val_self_test(struct
 	for (i = 0; i < IOAT_NUM_SRC_TEST + 1; i++) {
 		dma_srcs[i] = dma_map_page(dev, xor_val_srcs[i], 0, PAGE_SIZE,
 					   DMA_TO_DEVICE);
-		if (dma_mapping_error(dev, dma_srcs[i]))
+		if (dma_mapping_error(dev, dma_srcs[i])) {
+			err = -ENOMEM;
 			goto dma_unmap;
+		}
 	}
 	tx = dma->device_prep_dma_xor_val(dma_chan, dma_srcs,
 					  IOAT_NUM_SRC_TEST + 1, PAGE_SIZE,
@@ -1071,7 +1088,6 @@ static int ioat3_dma_probe(struct ioatdm
 	struct dma_device *dma;
 	struct dma_chan *c;
 	struct ioatdma_chan *ioat_chan;
-	bool is_raid_device = false;
 	int err;
 	u16 val16;
 
@@ -1095,7 +1111,6 @@ static int ioat3_dma_probe(struct ioatdm
 		ioat_dma->cap &= ~(IOAT_CAP_XOR|IOAT_CAP_PQ);
 
 	if (ioat_dma->cap & IOAT_CAP_XOR) {
-		is_raid_device = true;
 		dma->max_xor = 8;
 
 		dma_cap_set(DMA_XOR, dma->cap_mask);
@@ -1106,7 +1121,6 @@ static int ioat3_dma_probe(struct ioatdm
 	}
 
 	if (ioat_dma->cap & IOAT_CAP_PQ) {
-		is_raid_device = true;
 
 		dma->device_prep_dma_pq = ioat_prep_pq;
 		dma->device_prep_dma_pq_val = ioat_prep_pq_val;
@@ -1350,6 +1364,8 @@ static int ioat_pci_probe(struct pci_dev
 
 	device->version = readb(device->reg_base + IOAT_VER_OFFSET);
 	if (device->version >= IOAT_VER_3_0) {
+		if (is_skx_ioat(pdev))
+			device->version = IOAT_VER_3_2;
 		err = ioat3_dma_probe(device, ioat_dca_enabled);
 
 		if (device->version >= IOAT_VER_3_3)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/ioat/registers.h linux-libre-4.10-rc8-gnu/drivers/dma/ioat/registers.h
--- linux-libre-4.9-gnu/drivers/dma/ioat/registers.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/ioat/registers.h	2017-02-12 16:03:20.000000000 -0500
@@ -106,8 +106,6 @@
 #define IOAT_DMA_COMP_V1			0x0001	/* Compatibility with DMA version 1 */
 #define IOAT_DMA_COMP_V2			0x0002	/* Compatibility with DMA version 2 */
 
-/* IOAT1 define left for i7300_idle driver to not fail compiling */
-#define IOAT1_CHANSTS_OFFSET		0x04
 #define IOAT_CHANSTS_OFFSET		0x08	/* 64-bit Channel Status Register */
 #define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR	(~0x3fULL)
 #define IOAT_CHANSTS_SOFT_ERR			0x10ULL
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/k3dma.c linux-libre-4.10-rc8-gnu/drivers/dma/k3dma.c
--- linux-libre-4.9-gnu/drivers/dma/k3dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/k3dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -458,13 +458,12 @@ static struct k3_dma_desc_sw *k3_dma_all
 	if (!ds)
 		return NULL;
 
-	ds->desc_hw = dma_pool_alloc(d->pool, GFP_NOWAIT, &ds->desc_hw_lli);
+	ds->desc_hw = dma_pool_zalloc(d->pool, GFP_NOWAIT, &ds->desc_hw_lli);
 	if (!ds->desc_hw) {
 		dev_dbg(chan->device->dev, "vch %p: dma alloc fail\n", &c->vc);
 		kfree(ds);
 		return NULL;
 	}
-	memset(ds->desc_hw, 0, sizeof(struct k3_desc_hw) * num);
 	ds->desc_num = num;
 	return ds;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/Kconfig linux-libre-4.10-rc8-gnu/drivers/dma/Kconfig
--- linux-libre-4.9-gnu/drivers/dma/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -436,6 +436,20 @@ config STE_DMA40
 	help
 	  Support for ST-Ericsson DMA40 controller
 
+config ST_FDMA
+	tristate "ST FDMA dmaengine support"
+	depends on ARCH_STI
+	depends on REMOTEPROC
+	select ST_SLIM_REMOTEPROC
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	help
+	  Enable support for ST FDMA controller.
+	  It supports 16 independent DMA channels, accepts up to 32 DMA requests
+
+	  Say Y here if you have such a chipset.
+	  If unsure, say N.
+
 config STM32_DMA
 	bool "STMicroelectronics STM32 DMA support"
 	depends on ARCH_STM32 || COMPILE_TEST
@@ -480,7 +494,7 @@ config TEGRA20_APB_DMA
 	  or vice versa. It does not support memory to memory data transfer.
 
 config TEGRA210_ADMA
-	bool "NVIDIA Tegra210 ADMA support"
+	tristate "NVIDIA Tegra210 ADMA support"
 	depends on (ARCH_TEGRA_210_SOC || COMPILE_TEST) && PM_CLK
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/Makefile linux-libre-4.10-rc8-gnu/drivers/dma/Makefile
--- linux-libre-4.9-gnu/drivers/dma/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -67,6 +67,7 @@ obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-
 obj-$(CONFIG_TI_EDMA) += edma.o
 obj-$(CONFIG_XGENE_DMA) += xgene-dma.o
 obj-$(CONFIG_ZX_DMA) += zx296702_dma.o
+obj-$(CONFIG_ST_FDMA) += st_fdma.o
 
 obj-y += qcom/
 obj-y += xilinx/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/mic_x100_dma.c linux-libre-4.10-rc8-gnu/drivers/dma/mic_x100_dma.c
--- linux-libre-4.9-gnu/drivers/dma/mic_x100_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/mic_x100_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -554,9 +554,7 @@ static int mic_dma_init(struct mic_dma_d
 	int ret;
 
 	for (i = first_chan; i < first_chan + MIC_DMA_NUM_CHAN; i++) {
-		unsigned long data;
 		ch = &mic_dma_dev->mic_ch[i];
-		data = (unsigned long)ch;
 		ch->ch_num = i;
 		ch->owner = owner;
 		spin_lock_init(&ch->cleanup_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/mv_xor.c linux-libre-4.10-rc8-gnu/drivers/dma/mv_xor.c
--- linux-libre-4.9-gnu/drivers/dma/mv_xor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/mv_xor.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,6 +68,36 @@ static void mv_desc_init(struct mv_xor_d
 	hw_desc->byte_count = byte_count;
 }
 
+/* Populate the descriptor */
+static void mv_xor_config_sg_ll_desc(struct mv_xor_desc_slot *desc,
+				     dma_addr_t dma_src, dma_addr_t dma_dst,
+				     u32 len, struct mv_xor_desc_slot *prev)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+
+	hw_desc->status = XOR_DESC_DMA_OWNED;
+	hw_desc->phy_next_desc = 0;
+	/* Configure for XOR with only one src address -> MEMCPY */
+	hw_desc->desc_command = XOR_DESC_OPERATION_XOR | (0x1 << 0);
+	hw_desc->phy_dest_addr = dma_dst;
+	hw_desc->phy_src_addr[0] = dma_src;
+	hw_desc->byte_count = len;
+
+	if (prev) {
+		struct mv_xor_desc *hw_prev = prev->hw_desc;
+
+		hw_prev->phy_next_desc = desc->async_tx.phys;
+	}
+}
+
+static void mv_xor_desc_config_eod(struct mv_xor_desc_slot *desc)
+{
+	struct mv_xor_desc *hw_desc = desc->hw_desc;
+
+	/* Enable end-of-descriptor interrupt */
+	hw_desc->desc_command |= XOR_DESC_EOD_INT_EN;
+}
+
 static void mv_desc_set_mode(struct mv_xor_desc_slot *desc)
 {
 	struct mv_xor_desc *hw_desc = desc->hw_desc;
@@ -228,8 +258,13 @@ mv_chan_clean_completed_slots(struct mv_
 	list_for_each_entry_safe(iter, _iter, &mv_chan->completed_slots,
 				 node) {
 
-		if (async_tx_test_ack(&iter->async_tx))
+		if (async_tx_test_ack(&iter->async_tx)) {
 			list_move_tail(&iter->node, &mv_chan->free_slots);
+			if (!list_empty(&iter->sg_tx_list)) {
+				list_splice_tail_init(&iter->sg_tx_list,
+							&mv_chan->free_slots);
+			}
+		}
 	}
 	return 0;
 }
@@ -244,11 +279,20 @@ mv_desc_clean_slot(struct mv_xor_desc_sl
 	/* the client is allowed to attach dependent operations
 	 * until 'ack' is set
 	 */
-	if (!async_tx_test_ack(&desc->async_tx))
+	if (!async_tx_test_ack(&desc->async_tx)) {
 		/* move this slot to the completed_slots */
 		list_move_tail(&desc->node, &mv_chan->completed_slots);
-	else
+		if (!list_empty(&desc->sg_tx_list)) {
+			list_splice_tail_init(&desc->sg_tx_list,
+					      &mv_chan->completed_slots);
+		}
+	} else {
 		list_move_tail(&desc->node, &mv_chan->free_slots);
+		if (!list_empty(&desc->sg_tx_list)) {
+			list_splice_tail_init(&desc->sg_tx_list,
+					      &mv_chan->free_slots);
+		}
+	}
 
 	return 0;
 }
@@ -450,6 +494,7 @@ static int mv_xor_alloc_chan_resources(s
 		dma_async_tx_descriptor_init(&slot->async_tx, chan);
 		slot->async_tx.tx_submit = mv_xor_tx_submit;
 		INIT_LIST_HEAD(&slot->node);
+		INIT_LIST_HEAD(&slot->sg_tx_list);
 		dma_desc = mv_chan->dma_desc_pool;
 		slot->async_tx.phys = dma_desc + idx * MV_XOR_SLOT_SIZE;
 		slot->idx = idx++;
@@ -617,6 +662,132 @@ mv_xor_prep_dma_interrupt(struct dma_cha
 	return mv_xor_prep_dma_xor(chan, dest, &src, 1, len, flags);
 }
 
+/**
+ * mv_xor_prep_dma_sg - prepare descriptors for a memory sg transaction
+ * @chan: DMA channel
+ * @dst_sg: Destination scatter list
+ * @dst_sg_len: Number of entries in destination scatter list
+ * @src_sg: Source scatter list
+ * @src_sg_len: Number of entries in source scatter list
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *
+mv_xor_prep_dma_sg(struct dma_chan *chan, struct scatterlist *dst_sg,
+		   unsigned int dst_sg_len, struct scatterlist *src_sg,
+		   unsigned int src_sg_len, unsigned long flags)
+{
+	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
+	struct mv_xor_desc_slot *new;
+	struct mv_xor_desc_slot *first = NULL;
+	struct mv_xor_desc_slot *prev = NULL;
+	size_t len, dst_avail, src_avail;
+	dma_addr_t dma_dst, dma_src;
+	int desc_cnt = 0;
+	int ret;
+
+	dev_dbg(mv_chan_to_devp(mv_chan),
+		"%s dst_sg_len: %d src_sg_len: %d flags: %ld\n",
+		__func__, dst_sg_len, src_sg_len, flags);
+
+	dst_avail = sg_dma_len(dst_sg);
+	src_avail = sg_dma_len(src_sg);
+
+	/* Run until we are out of scatterlist entries */
+	while (true) {
+		/* Allocate and populate the descriptor */
+		desc_cnt++;
+		new = mv_chan_alloc_slot(mv_chan);
+		if (!new) {
+			dev_err(mv_chan_to_devp(mv_chan),
+				"Out of descriptors (desc_cnt=%d)!\n",
+				desc_cnt);
+			goto err;
+		}
+
+		len = min_t(size_t, src_avail, dst_avail);
+		len = min_t(size_t, len, MV_XOR_MAX_BYTE_COUNT);
+		if (len == 0)
+			goto fetch;
+
+		if (len < MV_XOR_MIN_BYTE_COUNT) {
+			dev_err(mv_chan_to_devp(mv_chan),
+				"Transfer size of %zu too small!\n", len);
+			goto err;
+		}
+
+		dma_dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) -
+			dst_avail;
+		dma_src = sg_dma_address(src_sg) + sg_dma_len(src_sg) -
+			src_avail;
+
+		/* Check if a new window needs to get added for 'dst' */
+		ret = mv_xor_add_io_win(mv_chan, dma_dst);
+		if (ret)
+			goto err;
+
+		/* Check if a new window needs to get added for 'src' */
+		ret = mv_xor_add_io_win(mv_chan, dma_src);
+		if (ret)
+			goto err;
+
+		/* Populate the descriptor */
+		mv_xor_config_sg_ll_desc(new, dma_src, dma_dst, len, prev);
+		prev = new;
+		dst_avail -= len;
+		src_avail -= len;
+
+		if (!first)
+			first = new;
+		else
+			list_move_tail(&new->node, &first->sg_tx_list);
+
+fetch:
+		/* Fetch the next dst scatterlist entry */
+		if (dst_avail == 0) {
+			if (dst_sg_len == 0)
+				break;
+
+			/* Fetch the next entry: if there are no more: done */
+			dst_sg = sg_next(dst_sg);
+			if (dst_sg == NULL)
+				break;
+
+			dst_sg_len--;
+			dst_avail = sg_dma_len(dst_sg);
+		}
+
+		/* Fetch the next src scatterlist entry */
+		if (src_avail == 0) {
+			if (src_sg_len == 0)
+				break;
+
+			/* Fetch the next entry: if there are no more: done */
+			src_sg = sg_next(src_sg);
+			if (src_sg == NULL)
+				break;
+
+			src_sg_len--;
+			src_avail = sg_dma_len(src_sg);
+		}
+	}
+
+	/* Set the EOD flag in the last descriptor */
+	mv_xor_desc_config_eod(new);
+	first->async_tx.flags = flags;
+
+	return &first->async_tx;
+
+err:
+	/* Cleanup: Move all descriptors back into the free list */
+	spin_lock_bh(&mv_chan->lock);
+	mv_desc_clean_slot(first, mv_chan);
+	spin_unlock_bh(&mv_chan->lock);
+
+	return NULL;
+}
+
 static void mv_xor_free_chan_resources(struct dma_chan *chan)
 {
 	struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);
@@ -1083,6 +1254,8 @@ mv_xor_channel_add(struct mv_xor_device
 		dma_dev->device_prep_dma_interrupt = mv_xor_prep_dma_interrupt;
 	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask))
 		dma_dev->device_prep_dma_memcpy = mv_xor_prep_dma_memcpy;
+	if (dma_has_cap(DMA_SG, dma_dev->cap_mask))
+		dma_dev->device_prep_dma_sg = mv_xor_prep_dma_sg;
 	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
 		dma_dev->max_xor = 8;
 		dma_dev->device_prep_dma_xor = mv_xor_prep_dma_xor;
@@ -1132,10 +1305,11 @@ mv_xor_channel_add(struct mv_xor_device
 			goto err_free_irq;
 	}
 
-	dev_info(&pdev->dev, "Marvell XOR (%s): ( %s%s%s)\n",
+	dev_info(&pdev->dev, "Marvell XOR (%s): ( %s%s%s%s)\n",
 		 mv_chan->op_in_desc ? "Descriptor Mode" : "Registers Mode",
 		 dma_has_cap(DMA_XOR, dma_dev->cap_mask) ? "xor " : "",
 		 dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask) ? "cpy " : "",
+		 dma_has_cap(DMA_SG, dma_dev->cap_mask) ? "sg " : "",
 		 dma_has_cap(DMA_INTERRUPT, dma_dev->cap_mask) ? "intr " : "");
 
 	dma_async_device_register(dma_dev);
@@ -1378,6 +1552,7 @@ static int mv_xor_probe(struct platform_
 
 			dma_cap_zero(cap_mask);
 			dma_cap_set(DMA_MEMCPY, cap_mask);
+			dma_cap_set(DMA_SG, cap_mask);
 			dma_cap_set(DMA_XOR, cap_mask);
 			dma_cap_set(DMA_INTERRUPT, cap_mask);
 
@@ -1455,12 +1630,7 @@ static struct platform_driver mv_xor_dri
 	},
 };
 
-
-static int __init mv_xor_init(void)
-{
-	return platform_driver_register(&mv_xor_driver);
-}
-device_initcall(mv_xor_init);
+builtin_platform_driver(mv_xor_driver);
 
 /*
 MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/mv_xor.h linux-libre-4.10-rc8-gnu/drivers/dma/mv_xor.h
--- linux-libre-4.9-gnu/drivers/dma/mv_xor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/mv_xor.h	2017-02-12 16:03:20.000000000 -0500
@@ -148,6 +148,7 @@ struct mv_xor_chan {
  */
 struct mv_xor_desc_slot {
 	struct list_head	node;
+	struct list_head	sg_tx_list;
 	enum dma_transaction_type	type;
 	void			*hw_desc;
 	u16			idx;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/nbpfaxi.c linux-libre-4.10-rc8-gnu/drivers/dma/nbpfaxi.c
--- linux-libre-4.9-gnu/drivers/dma/nbpfaxi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/nbpfaxi.c	2017-02-12 16:03:20.000000000 -0500
@@ -225,6 +225,8 @@ struct nbpf_channel {
 struct nbpf_device {
 	struct dma_device dma_dev;
 	void __iomem *base;
+	u32 max_burst_mem_read;
+	u32 max_burst_mem_write;
 	struct clk *clk;
 	const struct nbpf_config *config;
 	unsigned int eirq;
@@ -425,10 +427,33 @@ static void nbpf_chan_configure(struct n
 	nbpf_chan_write(chan, NBPF_CHAN_CFG, NBPF_CHAN_CFG_DMS | chan->dmarq_cfg);
 }
 
-static u32 nbpf_xfer_ds(struct nbpf_device *nbpf, size_t size)
+static u32 nbpf_xfer_ds(struct nbpf_device *nbpf, size_t size,
+			enum dma_transfer_direction direction)
 {
+	int max_burst = nbpf->config->buffer_size * 8;
+
+	if (nbpf->max_burst_mem_read || nbpf->max_burst_mem_write) {
+		switch (direction) {
+		case DMA_MEM_TO_MEM:
+			max_burst = min_not_zero(nbpf->max_burst_mem_read,
+						 nbpf->max_burst_mem_write);
+			break;
+		case DMA_MEM_TO_DEV:
+			if (nbpf->max_burst_mem_read)
+				max_burst = nbpf->max_burst_mem_read;
+			break;
+		case DMA_DEV_TO_MEM:
+			if (nbpf->max_burst_mem_write)
+				max_burst = nbpf->max_burst_mem_write;
+			break;
+		case DMA_DEV_TO_DEV:
+		default:
+			break;
+		}
+	}
+
 	/* Maximum supported bursts depend on the buffer size */
-	return min_t(int, __ffs(size), ilog2(nbpf->config->buffer_size * 8));
+	return min_t(int, __ffs(size), ilog2(max_burst));
 }
 
 static size_t nbpf_xfer_size(struct nbpf_device *nbpf,
@@ -458,7 +483,7 @@ static size_t nbpf_xfer_size(struct nbpf
 		size = burst;
 	}
 
-	return nbpf_xfer_ds(nbpf, size);
+	return nbpf_xfer_ds(nbpf, size, DMA_TRANS_NONE);
 }
 
 /*
@@ -507,7 +532,7 @@ static int nbpf_prep_one(struct nbpf_lin
 	 * transfers we enable the SBE bit and terminate the transfer in our
 	 * .device_pause handler.
 	 */
-	mem_xfer = nbpf_xfer_ds(chan->nbpf, size);
+	mem_xfer = nbpf_xfer_ds(chan->nbpf, size, direction);
 
 	switch (direction) {
 	case DMA_DEV_TO_MEM:
@@ -1313,6 +1338,11 @@ static int nbpf_probe(struct platform_de
 	if (IS_ERR(nbpf->clk))
 		return PTR_ERR(nbpf->clk);
 
+	of_property_read_u32(np, "max-burst-mem-read",
+			     &nbpf->max_burst_mem_read);
+	of_property_read_u32(np, "max-burst-mem-write",
+			     &nbpf->max_burst_mem_write);
+
 	nbpf->config = cfg;
 
 	for (i = 0; irqs < ARRAY_SIZE(irqbuf); i++) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/omap-dma.c linux-libre-4.10-rc8-gnu/drivers/dma/omap-dma.c
--- linux-libre-4.9-gnu/drivers/dma/omap-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/omap-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -166,6 +166,9 @@ enum {
 	CSDP_DST_BURST_16	= 1 << 14,
 	CSDP_DST_BURST_32	= 2 << 14,
 	CSDP_DST_BURST_64	= 3 << 14,
+	CSDP_WRITE_NON_POSTED	= 0 << 16,
+	CSDP_WRITE_POSTED	= 1 << 16,
+	CSDP_WRITE_LAST_NON_POSTED = 2 << 16,
 
 	CICR_TOUT_IE		= BIT(0),	/* OMAP1 only */
 	CICR_DROP_IE		= BIT(1),
@@ -422,7 +425,30 @@ static void omap_dma_start(struct omap_c
 	c->running = true;
 }
 
-static void omap_dma_stop(struct omap_chan *c)
+static void omap_dma_drain_chan(struct omap_chan *c)
+{
+	int i;
+	u32 val;
+
+	/* Wait for sDMA FIFO to drain */
+	for (i = 0; ; i++) {
+		val = omap_dma_chan_read(c, CCR);
+		if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)))
+			break;
+
+		if (i > 100)
+			break;
+
+		udelay(5);
+	}
+
+	if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))
+		dev_err(c->vc.chan.device->dev,
+			"DMA drain did not complete on lch %d\n",
+			c->dma_ch);
+}
+
+static int omap_dma_stop(struct omap_chan *c)
 {
 	struct omap_dmadev *od = to_omap_dma_dev(c->vc.chan.device);
 	uint32_t val;
@@ -435,7 +461,6 @@ static void omap_dma_stop(struct omap_ch
 	val = omap_dma_chan_read(c, CCR);
 	if (od->plat->errata & DMA_ERRATA_i541 && val & CCR_TRIGGER_SRC) {
 		uint32_t sysconfig;
-		unsigned i;
 
 		sysconfig = omap_dma_glbl_read(od, OCP_SYSCONFIG);
 		val = sysconfig & ~DMA_SYSCONFIG_MIDLEMODE_MASK;
@@ -446,27 +471,19 @@ static void omap_dma_stop(struct omap_ch
 		val &= ~CCR_ENABLE;
 		omap_dma_chan_write(c, CCR, val);
 
-		/* Wait for sDMA FIFO to drain */
-		for (i = 0; ; i++) {
-			val = omap_dma_chan_read(c, CCR);
-			if (!(val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE)))
-				break;
-
-			if (i > 100)
-				break;
-
-			udelay(5);
-		}
-
-		if (val & (CCR_RD_ACTIVE | CCR_WR_ACTIVE))
-			dev_err(c->vc.chan.device->dev,
-				"DMA drain did not complete on lch %d\n",
-			        c->dma_ch);
+		if (!(c->ccr & CCR_BUFFERING_DISABLE))
+			omap_dma_drain_chan(c);
 
 		omap_dma_glbl_write(od, OCP_SYSCONFIG, sysconfig);
 	} else {
+		if (!(val & CCR_ENABLE))
+			return -EINVAL;
+
 		val &= ~CCR_ENABLE;
 		omap_dma_chan_write(c, CCR, val);
+
+		if (!(c->ccr & CCR_BUFFERING_DISABLE))
+			omap_dma_drain_chan(c);
 	}
 
 	mb();
@@ -481,8 +498,8 @@ static void omap_dma_stop(struct omap_ch
 
 		omap_dma_chan_write(c, CLNK_CTRL, val);
 	}
-
 	c->running = false;
+	return 0;
 }
 
 static void omap_dma_start_sg(struct omap_chan *c, struct omap_desc *d)
@@ -836,6 +853,8 @@ static enum dma_status omap_dma_tx_statu
 	} else {
 		txstate->residue = 0;
 	}
+	if (ret == DMA_IN_PROGRESS && c->paused)
+		ret = DMA_PAUSED;
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 
 	return ret;
@@ -865,15 +884,18 @@ static struct dma_async_tx_descriptor *o
 	unsigned i, es, en, frame_bytes;
 	bool ll_failed = false;
 	u32 burst;
+	u32 port_window, port_window_bytes;
 
 	if (dir == DMA_DEV_TO_MEM) {
 		dev_addr = c->cfg.src_addr;
 		dev_width = c->cfg.src_addr_width;
 		burst = c->cfg.src_maxburst;
+		port_window = c->cfg.src_port_window_size;
 	} else if (dir == DMA_MEM_TO_DEV) {
 		dev_addr = c->cfg.dst_addr;
 		dev_width = c->cfg.dst_addr_width;
 		burst = c->cfg.dst_maxburst;
+		port_window = c->cfg.dst_port_window_size;
 	} else {
 		dev_err(chan->device->dev, "%s: bad direction?\n", __func__);
 		return NULL;
@@ -894,6 +916,12 @@ static struct dma_async_tx_descriptor *o
 		return NULL;
 	}
 
+	/* When the port_window is used, one frame must cover the window */
+	if (port_window) {
+		burst = port_window;
+		port_window_bytes = port_window * es_bytes[es];
+	}
+
 	/* Now allocate and setup the descriptor. */
 	d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC);
 	if (!d)
@@ -905,11 +933,46 @@ static struct dma_async_tx_descriptor *o
 
 	d->ccr = c->ccr | CCR_SYNC_FRAME;
 	if (dir == DMA_DEV_TO_MEM) {
-		d->ccr |= CCR_DST_AMODE_POSTINC | CCR_SRC_AMODE_CONSTANT;
 		d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
+
+		d->ccr |= CCR_DST_AMODE_POSTINC;
+		if (port_window) {
+			d->ccr |= CCR_SRC_AMODE_DBLIDX;
+
+			if (port_window_bytes >= 64)
+				d->csdp |= CSDP_SRC_BURST_64;
+			else if (port_window_bytes >= 32)
+				d->csdp |= CSDP_SRC_BURST_32;
+			else if (port_window_bytes >= 16)
+				d->csdp |= CSDP_SRC_BURST_16;
+
+		} else {
+			d->ccr |= CCR_SRC_AMODE_CONSTANT;
+		}
 	} else {
-		d->ccr |= CCR_DST_AMODE_CONSTANT | CCR_SRC_AMODE_POSTINC;
 		d->csdp = CSDP_SRC_BURST_64 | CSDP_SRC_PACKED;
+
+		d->ccr |= CCR_SRC_AMODE_POSTINC;
+		if (port_window) {
+			d->ccr |= CCR_DST_AMODE_DBLIDX;
+			d->ei = 1;
+			/*
+			 * One frame covers the port_window and by  configure
+			 * the source frame index to be -1 * (port_window - 1)
+			 * we instruct the sDMA that after a frame is processed
+			 * it should move back to the start of the window.
+			 */
+			d->fi = -(port_window_bytes - 1);
+
+			if (port_window_bytes >= 64)
+				d->csdp |= CSDP_DST_BURST_64;
+			else if (port_window_bytes >= 32)
+				d->csdp |= CSDP_DST_BURST_32;
+			else if (port_window_bytes >= 16)
+				d->csdp |= CSDP_DST_BURST_16;
+		} else {
+			d->ccr |= CCR_DST_AMODE_CONSTANT;
+		}
 	}
 
 	d->cicr = CICR_DROP_IE | CICR_BLOCK_IE;
@@ -927,6 +990,9 @@ static struct dma_async_tx_descriptor *o
 			d->ccr |= CCR_TRIGGER_SRC;
 
 		d->cicr |= CICR_MISALIGNED_ERR_IE | CICR_TRANS_ERR_IE;
+
+		if (port_window)
+			d->csdp |= CSDP_WRITE_LAST_NON_POSTED;
 	}
 	if (od->plat->errata & DMA_ERRATA_PARALLEL_CHANNELS)
 		d->clnk_ctrl = c->dma_ch;
@@ -952,6 +1018,16 @@ static struct dma_async_tx_descriptor *o
 		osg->addr = sg_dma_address(sgent);
 		osg->en = en;
 		osg->fn = sg_dma_len(sgent) / frame_bytes;
+		if (port_window && dir == DMA_DEV_TO_MEM) {
+			osg->ei = 1;
+			/*
+			 * One frame covers the port_window and by  configure
+			 * the source frame index to be -1 * (port_window - 1)
+			 * we instruct the sDMA that after a frame is processed
+			 * it should move back to the start of the window.
+			 */
+			osg->fi = -(port_window_bytes - 1);
+		}
 
 		if (d->using_ll) {
 			osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC,
@@ -1247,10 +1323,8 @@ static int omap_dma_terminate_all(struct
 			omap_dma_stop(c);
 	}
 
-	if (c->cyclic) {
-		c->cyclic = false;
-		c->paused = false;
-	}
+	c->cyclic = false;
+	c->paused = false;
 
 	vchan_get_all_descriptors(&c->vc, &head);
 	spin_unlock_irqrestore(&c->vc.lock, flags);
@@ -1269,28 +1343,66 @@ static void omap_dma_synchronize(struct
 static int omap_dma_pause(struct dma_chan *chan)
 {
 	struct omap_chan *c = to_omap_dma_chan(chan);
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
+	unsigned long flags;
+	int ret = -EINVAL;
+	bool can_pause = false;
 
-	/* Pause/Resume only allowed with cyclic mode */
-	if (!c->cyclic)
-		return -EINVAL;
+	spin_lock_irqsave(&od->irq_lock, flags);
 
-	if (!c->paused) {
-		omap_dma_stop(c);
-		c->paused = true;
+	if (!c->desc)
+		goto out;
+
+	if (c->cyclic)
+		can_pause = true;
+
+	/*
+	 * We do not allow DMA_MEM_TO_DEV transfers to be paused.
+	 * From the AM572x TRM, 16.1.4.18 Disabling a Channel During Transfer:
+	 * "When a channel is disabled during a transfer, the channel undergoes
+	 * an abort, unless it is hardware-source-synchronized …".
+	 * A source-synchronised channel is one where the fetching of data is
+	 * under control of the device. In other words, a device-to-memory
+	 * transfer. So, a destination-synchronised channel (which would be a
+	 * memory-to-device transfer) undergoes an abort if the the CCR_ENABLE
+	 * bit is cleared.
+	 * From 16.1.4.20.4.6.2 Abort: "If an abort trigger occurs, the channel
+	 * aborts immediately after completion of current read/write
+	 * transactions and then the FIFO is cleaned up." The term "cleaned up"
+	 * is not defined. TI recommends to check that RD_ACTIVE and WR_ACTIVE
+	 * are both clear _before_ disabling the channel, otherwise data loss
+	 * will occur.
+	 * The problem is that if the channel is active, then device activity
+	 * can result in DMA activity starting between reading those as both
+	 * clear and the write to DMA_CCR to clear the enable bit hitting the
+	 * hardware. If the DMA hardware can't drain the data in its FIFO to the
+	 * destination, then data loss "might" occur (say if we write to an UART
+	 * and the UART is not accepting any further data).
+	 */
+	else if (c->desc->dir == DMA_DEV_TO_MEM)
+		can_pause = true;
+
+	if (can_pause && !c->paused) {
+		ret = omap_dma_stop(c);
+		if (!ret)
+			c->paused = true;
 	}
+out:
+	spin_unlock_irqrestore(&od->irq_lock, flags);
 
-	return 0;
+	return ret;
 }
 
 static int omap_dma_resume(struct dma_chan *chan)
 {
 	struct omap_chan *c = to_omap_dma_chan(chan);
+	struct omap_dmadev *od = to_omap_dma_dev(chan->device);
+	unsigned long flags;
+	int ret = -EINVAL;
 
-	/* Pause/Resume only allowed with cyclic mode */
-	if (!c->cyclic)
-		return -EINVAL;
+	spin_lock_irqsave(&od->irq_lock, flags);
 
-	if (c->paused) {
+	if (c->paused && c->desc) {
 		mb();
 
 		/* Restore channel link register */
@@ -1298,9 +1410,11 @@ static int omap_dma_resume(struct dma_ch
 
 		omap_dma_start(c, c->desc);
 		c->paused = false;
+		ret = 0;
 	}
+	spin_unlock_irqrestore(&od->irq_lock, flags);
 
-	return 0;
+	return ret;
 }
 
 static int omap_dma_chan_init(struct omap_dmadev *od)
@@ -1339,6 +1453,7 @@ static int omap_dma_probe(struct platfor
 	struct omap_dmadev *od;
 	struct resource *res;
 	int rc, i, irq;
+	u32 lch_count;
 
 	od = devm_kzalloc(&pdev->dev, sizeof(*od), GFP_KERNEL);
 	if (!od)
@@ -1381,20 +1496,31 @@ static int omap_dma_probe(struct platfor
 	spin_lock_init(&od->lock);
 	spin_lock_init(&od->irq_lock);
 
-	if (!pdev->dev.of_node) {
-		od->dma_requests = od->plat->dma_attr->lch_count;
-		if (unlikely(!od->dma_requests))
-			od->dma_requests = OMAP_SDMA_REQUESTS;
-	} else if (of_property_read_u32(pdev->dev.of_node, "dma-requests",
-					&od->dma_requests)) {
+	/* Number of DMA requests */
+	od->dma_requests = OMAP_SDMA_REQUESTS;
+	if (pdev->dev.of_node && of_property_read_u32(pdev->dev.of_node,
+						      "dma-requests",
+						      &od->dma_requests)) {
 		dev_info(&pdev->dev,
 			 "Missing dma-requests property, using %u.\n",
 			 OMAP_SDMA_REQUESTS);
-		od->dma_requests = OMAP_SDMA_REQUESTS;
 	}
 
-	od->lch_map = devm_kcalloc(&pdev->dev, od->dma_requests,
-				   sizeof(*od->lch_map), GFP_KERNEL);
+	/* Number of available logical channels */
+	if (!pdev->dev.of_node) {
+		lch_count = od->plat->dma_attr->lch_count;
+		if (unlikely(!lch_count))
+			lch_count = OMAP_SDMA_CHANNELS;
+	} else if (of_property_read_u32(pdev->dev.of_node, "dma-channels",
+					&lch_count)) {
+		dev_info(&pdev->dev,
+			 "Missing dma-channels property, using %u.\n",
+			 OMAP_SDMA_CHANNELS);
+		lch_count = OMAP_SDMA_CHANNELS;
+	}
+
+	od->lch_map = devm_kcalloc(&pdev->dev, lch_count, sizeof(*od->lch_map),
+				   GFP_KERNEL);
 	if (!od->lch_map)
 		return -ENOMEM;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/pch_dma.c linux-libre-4.10-rc8-gnu/drivers/dma/pch_dma.c
--- linux-libre-4.9-gnu/drivers/dma/pch_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/pch_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -417,10 +417,8 @@ static dma_cookie_t pd_tx_submit(struct
 {
 	struct pch_dma_desc *desc = to_pd_desc(txd);
 	struct pch_dma_chan *pd_chan = to_pd_chan(txd->chan);
-	dma_cookie_t cookie;
 
 	spin_lock(&pd_chan->lock);
-	cookie = dma_cookie_assign(txd);
 
 	if (list_empty(&pd_chan->active_list)) {
 		list_add_tail(&desc->desc_node, &pd_chan->active_list);
@@ -439,9 +437,8 @@ static struct pch_dma_desc *pdc_alloc_de
 	struct pch_dma *pd = to_pd(chan->device);
 	dma_addr_t addr;
 
-	desc = pci_pool_alloc(pd->pool, flags, &addr);
+	desc = pci_pool_zalloc(pd->pool, flags, &addr);
 	if (desc) {
-		memset(desc, 0, sizeof(struct pch_dma_desc));
 		INIT_LIST_HEAD(&desc->tx_list);
 		dma_async_tx_descriptor_init(&desc->txd, chan);
 		desc->txd.tx_submit = pd_tx_submit;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/pl330.c linux-libre-4.10-rc8-gnu/drivers/dma/pl330.c
--- linux-libre-4.9-gnu/drivers/dma/pl330.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/pl330.c	2017-02-12 16:03:20.000000000 -0500
@@ -448,6 +448,9 @@ struct dma_pl330_chan {
 
 	/* for cyclic capability */
 	bool cyclic;
+
+	/* for runtime pm tracking */
+	bool active;
 };
 
 struct pl330_dmac {
@@ -570,7 +573,8 @@ static inline u32 _emit_ADDH(unsigned dr
 
 	buf[0] = CMD_DMAADDH;
 	buf[0] |= (da << 1);
-	*((__le16 *)&buf[1]) = cpu_to_le16(val);
+	buf[1] = val;
+	buf[2] = val >> 8;
 
 	PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n",
 		da == 1 ? "DA" : "SA", val);
@@ -724,7 +728,10 @@ static inline u32 _emit_MOV(unsigned dry
 
 	buf[0] = CMD_DMAMOV;
 	buf[1] = dst;
-	*((__le32 *)&buf[2]) = cpu_to_le32(val);
+	buf[2] = val;
+	buf[3] = val >> 8;
+	buf[4] = val >> 16;
+	buf[5] = val >> 24;
 
 	PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n",
 		dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val);
@@ -899,10 +906,11 @@ static inline u32 _emit_GO(unsigned dry_
 
 	buf[0] = CMD_DMAGO;
 	buf[0] |= (ns << 1);
-
 	buf[1] = chan & 0x7;
-
-	*((__le32 *)&buf[2]) = cpu_to_le32(addr);
+	buf[2] = addr;
+	buf[3] = addr >> 8;
+	buf[4] = addr >> 16;
+	buf[5] = addr >> 24;
 
 	return SZ_DMAGO;
 }
@@ -1691,7 +1699,6 @@ static bool _chan_ns(const struct pl330_
 static struct pl330_thread *pl330_request_channel(struct pl330_dmac *pl330)
 {
 	struct pl330_thread *thrd = NULL;
-	unsigned long flags;
 	int chans, i;
 
 	if (pl330->state == DYING)
@@ -1699,8 +1706,6 @@ static struct pl330_thread *pl330_reques
 
 	chans = pl330->pcfg.num_chan;
 
-	spin_lock_irqsave(&pl330->lock, flags);
-
 	for (i = 0; i < chans; i++) {
 		thrd = &pl330->channels[i];
 		if ((thrd->free) && (!_manager_ns(thrd) ||
@@ -1718,8 +1723,6 @@ static struct pl330_thread *pl330_reques
 		thrd = NULL;
 	}
 
-	spin_unlock_irqrestore(&pl330->lock, flags);
-
 	return thrd;
 }
 
@@ -1737,7 +1740,6 @@ static inline void _free_event(struct pl
 static void pl330_release_channel(struct pl330_thread *thrd)
 {
 	struct pl330_dmac *pl330;
-	unsigned long flags;
 
 	if (!thrd || thrd->free)
 		return;
@@ -1749,10 +1751,8 @@ static void pl330_release_channel(struct
 
 	pl330 = thrd->dmac;
 
-	spin_lock_irqsave(&pl330->lock, flags);
 	_free_event(thrd, thrd->ev);
 	thrd->free = true;
-	spin_unlock_irqrestore(&pl330->lock, flags);
 }
 
 /* Initialize the structure for PL330 configuration, that can be used
@@ -1883,11 +1883,8 @@ static int dmac_alloc_resources(struct p
 
 static int pl330_add(struct pl330_dmac *pl330)
 {
-	void __iomem *regs;
 	int i, ret;
 
-	regs = pl330->base;
-
 	/* Check if we can handle this DMAC */
 	if ((pl330->pcfg.periph_id & 0xfffff) != PERIPH_ID_VAL) {
 		dev_err(pl330->ddma.dev, "PERIPH_ID 0x%x !\n",
@@ -2031,6 +2028,7 @@ static void pl330_tasklet(unsigned long
 		_stop(pch->thread);
 		spin_unlock(&pch->thread->dmac->lock);
 		power_down = true;
+		pch->active = false;
 	} else {
 		/* Make sure the PL330 Channel thread is active */
 		spin_lock(&pch->thread->dmac->lock);
@@ -2050,6 +2048,7 @@ static void pl330_tasklet(unsigned long
 			desc->status = PREP;
 			list_move_tail(&desc->node, &pch->work_list);
 			if (power_down) {
+				pch->active = true;
 				spin_lock(&pch->thread->dmac->lock);
 				_start(pch->thread);
 				spin_unlock(&pch->thread->dmac->lock);
@@ -2115,20 +2114,20 @@ static int pl330_alloc_chan_resources(st
 	struct pl330_dmac *pl330 = pch->dmac;
 	unsigned long flags;
 
-	spin_lock_irqsave(&pch->lock, flags);
+	spin_lock_irqsave(&pl330->lock, flags);
 
 	dma_cookie_init(chan);
 	pch->cyclic = false;
 
 	pch->thread = pl330_request_channel(pl330);
 	if (!pch->thread) {
-		spin_unlock_irqrestore(&pch->lock, flags);
+		spin_unlock_irqrestore(&pl330->lock, flags);
 		return -ENOMEM;
 	}
 
 	tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch);
 
-	spin_unlock_irqrestore(&pch->lock, flags);
+	spin_unlock_irqrestore(&pl330->lock, flags);
 
 	return 1;
 }
@@ -2164,6 +2163,7 @@ static int pl330_terminate_all(struct dm
 	unsigned long flags;
 	struct pl330_dmac *pl330 = pch->dmac;
 	LIST_HEAD(list);
+	bool power_down = false;
 
 	pm_runtime_get_sync(pl330->ddma.dev);
 	spin_lock_irqsave(&pch->lock, flags);
@@ -2174,6 +2174,8 @@ static int pl330_terminate_all(struct dm
 	pch->thread->req[0].desc = NULL;
 	pch->thread->req[1].desc = NULL;
 	pch->thread->req_running = -1;
+	power_down = pch->active;
+	pch->active = false;
 
 	/* Mark all desc done */
 	list_for_each_entry(desc, &pch->submitted_list, node) {
@@ -2191,6 +2193,8 @@ static int pl330_terminate_all(struct dm
 	list_splice_tail_init(&pch->completed_list, &pl330->desc_pool);
 	spin_unlock_irqrestore(&pch->lock, flags);
 	pm_runtime_mark_last_busy(pl330->ddma.dev);
+	if (power_down)
+		pm_runtime_put_autosuspend(pl330->ddma.dev);
 	pm_runtime_put_autosuspend(pl330->ddma.dev);
 
 	return 0;
@@ -2226,12 +2230,13 @@ static int pl330_pause(struct dma_chan *
 static void pl330_free_chan_resources(struct dma_chan *chan)
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
+	struct pl330_dmac *pl330 = pch->dmac;
 	unsigned long flags;
 
 	tasklet_kill(&pch->task);
 
 	pm_runtime_get_sync(pch->dmac->ddma.dev);
-	spin_lock_irqsave(&pch->lock, flags);
+	spin_lock_irqsave(&pl330->lock, flags);
 
 	pl330_release_channel(pch->thread);
 	pch->thread = NULL;
@@ -2239,7 +2244,7 @@ static void pl330_free_chan_resources(st
 	if (pch->cyclic)
 		list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool);
 
-	spin_unlock_irqrestore(&pch->lock, flags);
+	spin_unlock_irqrestore(&pl330->lock, flags);
 	pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
 	pm_runtime_put_autosuspend(pch->dmac->ddma.dev);
 }
@@ -2263,6 +2268,11 @@ static int pl330_get_current_xferred_cou
 	}
 	pm_runtime_mark_last_busy(pch->dmac->ddma.dev);
 	pm_runtime_put_autosuspend(pl330->ddma.dev);
+
+	/* If DMAMOV hasn't finished yet, SAR/DAR can be zero */
+	if (!val)
+		return 0;
+
 	return val - addr;
 }
 
@@ -2350,6 +2360,7 @@ static void pl330_issue_pending(struct d
 		 * updated on work_list emptiness status.
 		 */
 		WARN_ON(list_empty(&pch->submitted_list));
+		pch->active = true;
 		pm_runtime_get_sync(pch->dmac->ddma.dev);
 	}
 	list_splice_tail_init(&pch->submitted_list, &pch->work_list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/pxa_dma.c linux-libre-4.10-rc8-gnu/drivers/dma/pxa_dma.c
--- linux-libre-4.9-gnu/drivers/dma/pxa_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/pxa_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -413,15 +413,6 @@ static inline void pxad_init_debugfs(str
 static inline void pxad_cleanup_debugfs(struct pxad_device *pdev) {}
 #endif
 
-/*
- * In the transition phase where legacy pxa handling is done at the same time as
- * mmp_dma, the DMA physical channel split between the 2 DMA providers is done
- * through legacy_reserved. Legacy code reserves DMA channels by settings
- * corresponding bits in legacy_reserved.
- */
-static u32 legacy_reserved;
-static u32 legacy_unavailable;
-
 static struct pxad_phy *lookup_phy(struct pxad_chan *pchan)
 {
 	int prio, i;
@@ -442,14 +433,10 @@ static struct pxad_phy *lookup_phy(struc
 		for (i = 0; i < pdev->nr_chans; i++) {
 			if (prio != (i & 0xf) >> 2)
 				continue;
-			if ((i < 32) && (legacy_reserved & BIT(i)))
-				continue;
 			phy = &pdev->phys[i];
 			if (!phy->vchan) {
 				phy->vchan = pchan;
 				found = phy;
-				if (i < 32)
-					legacy_unavailable |= BIT(i);
 				goto out_unlock;
 			}
 		}
@@ -469,7 +456,6 @@ static void pxad_free_phy(struct pxad_ch
 	struct pxad_device *pdev = to_pxad_dev(chan->vc.chan.device);
 	unsigned long flags;
 	u32 reg;
-	int i;
 
 	dev_dbg(&chan->vc.chan.dev->device,
 		"%s(): freeing\n", __func__);
@@ -483,9 +469,6 @@ static void pxad_free_phy(struct pxad_ch
 	}
 
 	spin_lock_irqsave(&pdev->phy_lock, flags);
-	for (i = 0; i < 32; i++)
-		if (chan->phy == &pdev->phys[i])
-			legacy_unavailable &= ~BIT(i);
 	chan->phy->vchan = NULL;
 	chan->phy = NULL;
 	spin_unlock_irqrestore(&pdev->phy_lock, flags);
@@ -739,8 +722,6 @@ static irqreturn_t pxad_int_handler(int
 		i = __ffs(dint);
 		dint &= (dint - 1);
 		phy = &pdev->phys[i];
-		if ((i < 32) && (legacy_reserved & BIT(i)))
-			continue;
 		if (pxad_chan_handler(irq, phy) == IRQ_HANDLED)
 			ret = IRQ_HANDLED;
 	}
@@ -1522,15 +1503,6 @@ bool pxad_filter_fn(struct dma_chan *cha
 }
 EXPORT_SYMBOL_GPL(pxad_filter_fn);
 
-int pxad_toggle_reserved_channel(int legacy_channel)
-{
-	if (legacy_unavailable & (BIT(legacy_channel)))
-		return -EBUSY;
-	legacy_reserved ^= BIT(legacy_channel);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(pxad_toggle_reserved_channel);
-
 module_platform_driver(pxad_driver);
 
 MODULE_DESCRIPTION("Marvell PXA Peripheral DMA Driver");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/qcom/hidma.c linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma.c
--- linux-libre-4.9-gnu/drivers/dma/qcom/hidma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,6 +56,7 @@
 #include <linux/irq.h>
 #include <linux/atomic.h>
 #include <linux/pm_runtime.h>
+#include <linux/msi.h>
 
 #include "../dmaengine.h"
 #include "hidma.h"
@@ -70,6 +71,7 @@
 #define HIDMA_ERR_INFO_SW			0xFF
 #define HIDMA_ERR_CODE_UNEXPECTED_TERMINATE	0x0
 #define HIDMA_NR_DEFAULT_DESC			10
+#define HIDMA_MSI_INTS				11
 
 static inline struct hidma_dev *to_hidma_dev(struct dma_device *dmadev)
 {
@@ -553,6 +555,17 @@ static irqreturn_t hidma_chirq_handler(i
 	return hidma_ll_inthandler(chirq, lldev);
 }
 
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+static irqreturn_t hidma_chirq_handler_msi(int chirq, void *arg)
+{
+	struct hidma_lldev **lldevp = arg;
+	struct hidma_dev *dmadev = to_hidma_dev_from_lldev(lldevp);
+
+	return hidma_ll_inthandler_msi(chirq, *lldevp,
+				       1 << (chirq - dmadev->msi_virqbase));
+}
+#endif
+
 static ssize_t hidma_show_values(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
@@ -567,8 +580,13 @@ static ssize_t hidma_show_values(struct
 	return strlen(buf);
 }
 
-static int hidma_create_sysfs_entry(struct hidma_dev *dev, char *name,
-				    int mode)
+static inline void  hidma_sysfs_uninit(struct hidma_dev *dev)
+{
+	device_remove_file(dev->ddev.dev, dev->chid_attrs);
+}
+
+static struct device_attribute*
+hidma_create_sysfs_entry(struct hidma_dev *dev, char *name, int mode)
 {
 	struct device_attribute *attrs;
 	char *name_copy;
@@ -576,18 +594,125 @@ static int hidma_create_sysfs_entry(stru
 	attrs = devm_kmalloc(dev->ddev.dev, sizeof(struct device_attribute),
 			     GFP_KERNEL);
 	if (!attrs)
-		return -ENOMEM;
+		return NULL;
 
 	name_copy = devm_kstrdup(dev->ddev.dev, name, GFP_KERNEL);
 	if (!name_copy)
-		return -ENOMEM;
+		return NULL;
 
 	attrs->attr.name = name_copy;
 	attrs->attr.mode = mode;
 	attrs->show = hidma_show_values;
 	sysfs_attr_init(&attrs->attr);
 
-	return device_create_file(dev->ddev.dev, attrs);
+	return attrs;
+}
+
+static int hidma_sysfs_init(struct hidma_dev *dev)
+{
+	dev->chid_attrs = hidma_create_sysfs_entry(dev, "chid", S_IRUGO);
+	if (!dev->chid_attrs)
+		return -ENOMEM;
+
+	return device_create_file(dev->ddev.dev, dev->chid_attrs);
+}
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+static void hidma_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
+{
+	struct device *dev = msi_desc_to_dev(desc);
+	struct hidma_dev *dmadev = dev_get_drvdata(dev);
+
+	if (!desc->platform.msi_index) {
+		writel(msg->address_lo, dmadev->dev_evca + 0x118);
+		writel(msg->address_hi, dmadev->dev_evca + 0x11C);
+		writel(msg->data, dmadev->dev_evca + 0x120);
+	}
+}
+#endif
+
+static void hidma_free_msis(struct hidma_dev *dmadev)
+{
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	struct device *dev = dmadev->ddev.dev;
+	struct msi_desc *desc;
+
+	/* free allocated MSI interrupts above */
+	for_each_msi_entry(desc, dev)
+		devm_free_irq(dev, desc->irq, &dmadev->lldev);
+
+	platform_msi_domain_free_irqs(dev);
+#endif
+}
+
+static int hidma_request_msi(struct hidma_dev *dmadev,
+			     struct platform_device *pdev)
+{
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+	int rc;
+	struct msi_desc *desc;
+	struct msi_desc *failed_desc = NULL;
+
+	rc = platform_msi_domain_alloc_irqs(&pdev->dev, HIDMA_MSI_INTS,
+					    hidma_write_msi_msg);
+	if (rc)
+		return rc;
+
+	for_each_msi_entry(desc, &pdev->dev) {
+		if (!desc->platform.msi_index)
+			dmadev->msi_virqbase = desc->irq;
+
+		rc = devm_request_irq(&pdev->dev, desc->irq,
+				       hidma_chirq_handler_msi,
+				       0, "qcom-hidma-msi",
+				       &dmadev->lldev);
+		if (rc) {
+			failed_desc = desc;
+			break;
+		}
+	}
+
+	if (rc) {
+		/* free allocated MSI interrupts above */
+		for_each_msi_entry(desc, &pdev->dev) {
+			if (desc == failed_desc)
+				break;
+			devm_free_irq(&pdev->dev, desc->irq,
+				      &dmadev->lldev);
+		}
+	} else {
+		/* Add callback to free MSIs on teardown */
+		hidma_ll_setup_irq(dmadev->lldev, true);
+
+	}
+	if (rc)
+		dev_warn(&pdev->dev,
+			 "failed to request MSI irq, falling back to wired IRQ\n");
+	return rc;
+#else
+	return -EINVAL;
+#endif
+}
+
+static bool hidma_msi_capable(struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+	const char *of_compat;
+	int ret = -EINVAL;
+
+	if (!adev || acpi_disabled) {
+		ret = device_property_read_string(dev, "compatible",
+						  &of_compat);
+		if (ret)
+			return false;
+
+		ret = strcmp(of_compat, "qcom,hidma-1.1");
+	} else {
+#ifdef CONFIG_ACPI
+		ret = strcmp(acpi_device_hid(adev), "QCOM8062");
+#endif
+	}
+	return ret == 0;
 }
 
 static int hidma_probe(struct platform_device *pdev)
@@ -599,6 +724,7 @@ static int hidma_probe(struct platform_d
 	void __iomem *evca;
 	void __iomem *trca;
 	int rc;
+	bool msi;
 
 	pm_runtime_set_autosuspend_delay(&pdev->dev, HIDMA_AUTOSUSPEND_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
@@ -660,6 +786,12 @@ static int hidma_probe(struct platform_d
 	dmadev->ddev.device_terminate_all = hidma_terminate_all;
 	dmadev->ddev.copy_align = 8;
 
+	/*
+	 * Determine the MSI capability of the platform. Old HW doesn't
+	 * support MSI.
+	 */
+	msi = hidma_msi_capable(&pdev->dev);
+
 	device_property_read_u32(&pdev->dev, "desc-count",
 				 &dmadev->nr_descriptors);
 
@@ -688,10 +820,17 @@ static int hidma_probe(struct platform_d
 		goto dmafree;
 	}
 
-	rc = devm_request_irq(&pdev->dev, chirq, hidma_chirq_handler, 0,
-			      "qcom-hidma", dmadev->lldev);
-	if (rc)
-		goto uninit;
+	platform_set_drvdata(pdev, dmadev);
+	if (msi)
+		rc = hidma_request_msi(dmadev, pdev);
+
+	if (!msi || rc) {
+		hidma_ll_setup_irq(dmadev->lldev, false);
+		rc = devm_request_irq(&pdev->dev, chirq, hidma_chirq_handler,
+				      0, "qcom-hidma", dmadev->lldev);
+		if (rc)
+			goto uninit;
+	}
 
 	INIT_LIST_HEAD(&dmadev->ddev.channels);
 	rc = hidma_chan_init(dmadev, 0);
@@ -705,14 +844,16 @@ static int hidma_probe(struct platform_d
 	dmadev->irq = chirq;
 	tasklet_init(&dmadev->task, hidma_issue_task, (unsigned long)dmadev);
 	hidma_debug_init(dmadev);
-	hidma_create_sysfs_entry(dmadev, "chid", S_IRUGO);
+	hidma_sysfs_init(dmadev);
 	dev_info(&pdev->dev, "HI-DMA engine driver registration complete\n");
-	platform_set_drvdata(pdev, dmadev);
 	pm_runtime_mark_last_busy(dmadev->ddev.dev);
 	pm_runtime_put_autosuspend(dmadev->ddev.dev);
 	return 0;
 
 uninit:
+	if (msi)
+		hidma_free_msis(dmadev);
+
 	hidma_debug_uninit(dmadev);
 	hidma_ll_uninit(dmadev->lldev);
 dmafree:
@@ -730,8 +871,13 @@ static int hidma_remove(struct platform_
 
 	pm_runtime_get_sync(dmadev->ddev.dev);
 	dma_async_device_unregister(&dmadev->ddev);
-	devm_free_irq(dmadev->ddev.dev, dmadev->irq, dmadev->lldev);
+	if (!dmadev->lldev->msi_support)
+		devm_free_irq(dmadev->ddev.dev, dmadev->irq, dmadev->lldev);
+	else
+		hidma_free_msis(dmadev);
+
 	tasklet_kill(&dmadev->task);
+	hidma_sysfs_uninit(dmadev);
 	hidma_debug_uninit(dmadev);
 	hidma_ll_uninit(dmadev->lldev);
 	hidma_free(dmadev);
@@ -746,12 +892,15 @@ static int hidma_remove(struct platform_
 #if IS_ENABLED(CONFIG_ACPI)
 static const struct acpi_device_id hidma_acpi_ids[] = {
 	{"QCOM8061"},
+	{"QCOM8062"},
 	{},
 };
+MODULE_DEVICE_TABLE(acpi, hidma_acpi_ids);
 #endif
 
 static const struct of_device_id hidma_match[] = {
 	{.compatible = "qcom,hidma-1.0",},
+	{.compatible = "qcom,hidma-1.1",},
 	{},
 };
 MODULE_DEVICE_TABLE(of, hidma_match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/qcom/hidma_dbg.c linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma_dbg.c
--- linux-libre-4.9-gnu/drivers/dma/qcom/hidma_dbg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma_dbg.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,7 +74,8 @@ static void hidma_ll_devstats(struct seq
 	seq_printf(s, "tre_ring_handle=%pap\n", &lldev->tre_dma);
 	seq_printf(s, "tre_ring_size = 0x%x\n", lldev->tre_ring_size);
 	seq_printf(s, "tre_processed_off = 0x%x\n", lldev->tre_processed_off);
-	seq_printf(s, "pending_tre_count=%d\n", lldev->pending_tre_count);
+	seq_printf(s, "pending_tre_count=%d\n",
+			atomic_read(&lldev->pending_tre_count));
 	seq_printf(s, "evca=%p\n", lldev->evca);
 	seq_printf(s, "evre_ring=%p\n", lldev->evre_ring);
 	seq_printf(s, "evre_ring_handle=%pap\n", &lldev->evre_dma);
@@ -164,7 +165,6 @@ static const struct file_operations hidm
 void hidma_debug_uninit(struct hidma_dev *dmadev)
 {
 	debugfs_remove_recursive(dmadev->debugfs);
-	debugfs_remove_recursive(dmadev->stats);
 }
 
 int hidma_debug_init(struct hidma_dev *dmadev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/qcom/hidma.h linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma.h
--- linux-libre-4.9-gnu/drivers/dma/qcom/hidma.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma.h	2017-02-12 16:03:20.000000000 -0500
@@ -46,6 +46,7 @@ struct hidma_tre {
 };
 
 struct hidma_lldev {
+	bool msi_support;		/* flag indicating MSI support    */
 	bool initialized;		/* initialized flag               */
 	u8 trch_state;			/* trch_state of the device	  */
 	u8 evch_state;			/* evch_state of the device	  */
@@ -58,7 +59,7 @@ struct hidma_lldev {
 	void __iomem *evca;		/* Event Channel address          */
 	struct hidma_tre
 		**pending_tre_list;	/* Pointers to pending TREs	  */
-	s32 pending_tre_count;		/* Number of TREs pending	  */
+	atomic_t pending_tre_count;	/* Number of TREs pending	  */
 
 	void *tre_ring;			/* TRE ring			  */
 	dma_addr_t tre_dma;		/* TRE ring to be shared with HW  */
@@ -114,6 +115,7 @@ struct hidma_dev {
 	int				irq;
 	int				chidx;
 	u32				nr_descriptors;
+	int				msi_virqbase;
 
 	struct hidma_lldev		*lldev;
 	void				__iomem *dev_trca;
@@ -128,6 +130,9 @@ struct hidma_dev {
 	struct dentry			*debugfs;
 	struct dentry			*stats;
 
+	/* sysfs entry for the channel id */
+	struct device_attribute		*chid_attrs;
+
 	/* Task delivering issue_pending */
 	struct tasklet_struct		task;
 };
@@ -145,12 +150,14 @@ int hidma_ll_disable(struct hidma_lldev
 int hidma_ll_enable(struct hidma_lldev *llhndl);
 void hidma_ll_set_transfer_params(struct hidma_lldev *llhndl, u32 tre_ch,
 	dma_addr_t src, dma_addr_t dest, u32 len, u32 flags);
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi);
 int hidma_ll_setup(struct hidma_lldev *lldev);
 struct hidma_lldev *hidma_ll_init(struct device *dev, u32 max_channels,
 			void __iomem *trca, void __iomem *evca,
 			u8 chidx);
 int hidma_ll_uninit(struct hidma_lldev *llhndl);
 irqreturn_t hidma_ll_inthandler(int irq, void *arg);
+irqreturn_t hidma_ll_inthandler_msi(int irq, void *arg, int cause);
 void hidma_cleanup_pending_tre(struct hidma_lldev *llhndl, u8 err_info,
 				u8 err_code);
 int hidma_debug_init(struct hidma_dev *dmadev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/qcom/hidma_ll.c linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma_ll.c
--- linux-libre-4.9-gnu/drivers/dma/qcom/hidma_ll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma_ll.c	2017-02-12 16:03:20.000000000 -0500
@@ -198,13 +198,16 @@ static void hidma_ll_tre_complete(unsign
 	}
 }
 
-static int hidma_post_completed(struct hidma_lldev *lldev, int tre_iterator,
-				u8 err_info, u8 err_code)
+static int hidma_post_completed(struct hidma_lldev *lldev, u8 err_info,
+				u8 err_code)
 {
 	struct hidma_tre *tre;
 	unsigned long flags;
+	u32 tre_iterator;
 
 	spin_lock_irqsave(&lldev->lock, flags);
+
+	tre_iterator = lldev->tre_processed_off;
 	tre = lldev->pending_tre_list[tre_iterator / HIDMA_TRE_SIZE];
 	if (!tre) {
 		spin_unlock_irqrestore(&lldev->lock, flags);
@@ -218,12 +221,14 @@ static int hidma_post_completed(struct h
 	 * Keep track of pending TREs that SW is expecting to receive
 	 * from HW. We got one now. Decrement our counter.
 	 */
-	lldev->pending_tre_count--;
-	if (lldev->pending_tre_count < 0) {
+	if (atomic_dec_return(&lldev->pending_tre_count) < 0) {
 		dev_warn(lldev->dev, "tre count mismatch on completion");
-		lldev->pending_tre_count = 0;
+		atomic_set(&lldev->pending_tre_count, 0);
 	}
 
+	HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
+				 lldev->tre_ring_size);
+	lldev->tre_processed_off = tre_iterator;
 	spin_unlock_irqrestore(&lldev->lock, flags);
 
 	tre->err_info = err_info;
@@ -245,13 +250,11 @@ static int hidma_post_completed(struct h
 static int hidma_handle_tre_completion(struct hidma_lldev *lldev)
 {
 	u32 evre_ring_size = lldev->evre_ring_size;
-	u32 tre_ring_size = lldev->tre_ring_size;
 	u32 err_info, err_code, evre_write_off;
-	u32 tre_iterator, evre_iterator;
+	u32 evre_iterator;
 	u32 num_completed = 0;
 
 	evre_write_off = readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
-	tre_iterator = lldev->tre_processed_off;
 	evre_iterator = lldev->evre_processed_off;
 
 	if ((evre_write_off > evre_ring_size) ||
@@ -274,12 +277,9 @@ static int hidma_handle_tre_completion(s
 		err_code =
 		    (cfg >> HIDMA_EVRE_CODE_BIT_POS) & HIDMA_EVRE_CODE_MASK;
 
-		if (hidma_post_completed(lldev, tre_iterator, err_info,
-					 err_code))
+		if (hidma_post_completed(lldev, err_info, err_code))
 			break;
 
-		HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
-					 tre_ring_size);
 		HIDMA_INCREMENT_ITERATOR(evre_iterator, HIDMA_EVRE_SIZE,
 					 evre_ring_size);
 
@@ -291,21 +291,22 @@ static int hidma_handle_tre_completion(s
 		evre_write_off =
 		    readl_relaxed(lldev->evca + HIDMA_EVCA_WRITE_PTR_REG);
 		num_completed++;
+
+		/*
+		 * An error interrupt might have arrived while we are processing
+		 * the completed interrupt.
+		 */
+		if (!hidma_ll_isenabled(lldev))
+			break;
 	}
 
 	if (num_completed) {
 		u32 evre_read_off = (lldev->evre_processed_off +
 				     HIDMA_EVRE_SIZE * num_completed);
-		u32 tre_read_off = (lldev->tre_processed_off +
-				    HIDMA_TRE_SIZE * num_completed);
-
 		evre_read_off = evre_read_off % evre_ring_size;
-		tre_read_off = tre_read_off % tre_ring_size;
-
 		writel(evre_read_off, lldev->evca + HIDMA_EVCA_DOORBELL_REG);
 
 		/* record the last processed tre offset */
-		lldev->tre_processed_off = tre_read_off;
 		lldev->evre_processed_off = evre_read_off;
 	}
 
@@ -315,27 +316,10 @@ static int hidma_handle_tre_completion(s
 void hidma_cleanup_pending_tre(struct hidma_lldev *lldev, u8 err_info,
 			       u8 err_code)
 {
-	u32 tre_iterator;
-	u32 tre_ring_size = lldev->tre_ring_size;
-	int num_completed = 0;
-	u32 tre_read_off;
-
-	tre_iterator = lldev->tre_processed_off;
-	while (lldev->pending_tre_count) {
-		if (hidma_post_completed(lldev, tre_iterator, err_info,
-					 err_code))
+	while (atomic_read(&lldev->pending_tre_count)) {
+		if (hidma_post_completed(lldev, err_info, err_code))
 			break;
-		HIDMA_INCREMENT_ITERATOR(tre_iterator, HIDMA_TRE_SIZE,
-					 tre_ring_size);
-		num_completed++;
 	}
-	tre_read_off = (lldev->tre_processed_off +
-			HIDMA_TRE_SIZE * num_completed);
-
-	tre_read_off = tre_read_off % tre_ring_size;
-
-	/* record the last processed tre offset */
-	lldev->tre_processed_off = tre_read_off;
 }
 
 static int hidma_ll_reset(struct hidma_lldev *lldev)
@@ -412,12 +396,24 @@ static int hidma_ll_reset(struct hidma_l
  * requests traditionally to the destination, this concept does not apply
  * here for this HW.
  */
-irqreturn_t hidma_ll_inthandler(int chirq, void *arg)
+static void hidma_ll_int_handler_internal(struct hidma_lldev *lldev, int cause)
 {
-	struct hidma_lldev *lldev = arg;
-	u32 status;
-	u32 enable;
-	u32 cause;
+	if (cause & HIDMA_ERR_INT_MASK) {
+		dev_err(lldev->dev, "error 0x%x, disabling...\n",
+				cause);
+
+		/* Clear out pending interrupts */
+		writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+
+		/* No further submissions. */
+		hidma_ll_disable(lldev);
+
+		/* Driver completes the txn and intimates the client.*/
+		hidma_cleanup_pending_tre(lldev, 0xFF,
+					  HIDMA_EVRE_STATUS_ERROR);
+
+		return;
+	}
 
 	/*
 	 * Fine tuned for this HW...
@@ -426,35 +422,28 @@ irqreturn_t hidma_ll_inthandler(int chir
 	 * read and write accessors are used for performance reasons due to
 	 * interrupt delivery guarantees. Do not copy this code blindly and
 	 * expect that to work.
+	 *
+	 * Try to consume as many EVREs as possible.
 	 */
+	hidma_handle_tre_completion(lldev);
+
+	/* We consumed TREs or there are pending TREs or EVREs. */
+	writel_relaxed(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+}
+
+irqreturn_t hidma_ll_inthandler(int chirq, void *arg)
+{
+	struct hidma_lldev *lldev = arg;
+	u32 status;
+	u32 enable;
+	u32 cause;
+
 	status = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_STAT_REG);
 	enable = readl_relaxed(lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
 	cause = status & enable;
 
 	while (cause) {
-		if (cause & HIDMA_ERR_INT_MASK) {
-			dev_err(lldev->dev, "error 0x%x, disabling...\n",
-					cause);
-
-			/* Clear out pending interrupts */
-			writel(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
-
-			/* No further submissions. */
-			hidma_ll_disable(lldev);
-
-			/* Driver completes the txn and intimates the client.*/
-			hidma_cleanup_pending_tre(lldev, 0xFF,
-						  HIDMA_EVRE_STATUS_ERROR);
-			goto out;
-		}
-
-		/*
-		 * Try to consume as many EVREs as possible.
-		 */
-		hidma_handle_tre_completion(lldev);
-
-		/* We consumed TREs or there are pending TREs or EVREs. */
-		writel_relaxed(cause, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+		hidma_ll_int_handler_internal(lldev, cause);
 
 		/*
 		 * Another interrupt might have arrived while we are
@@ -465,7 +454,14 @@ irqreturn_t hidma_ll_inthandler(int chir
 		cause = status & enable;
 	}
 
-out:
+	return IRQ_HANDLED;
+}
+
+irqreturn_t hidma_ll_inthandler_msi(int chirq, void *arg, int cause)
+{
+	struct hidma_lldev *lldev = arg;
+
+	hidma_ll_int_handler_internal(lldev, cause);
 	return IRQ_HANDLED;
 }
 
@@ -548,7 +544,7 @@ void hidma_ll_queue_request(struct hidma
 	tre->err_code = 0;
 	tre->err_info = 0;
 	tre->queued = 1;
-	lldev->pending_tre_count++;
+	atomic_inc(&lldev->pending_tre_count);
 	lldev->tre_write_offset = (lldev->tre_write_offset + HIDMA_TRE_SIZE)
 					% lldev->tre_ring_size;
 	spin_unlock_irqrestore(&lldev->lock, flags);
@@ -564,19 +560,8 @@ int hidma_ll_disable(struct hidma_lldev
 	u32 val;
 	int ret;
 
-	val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
-	lldev->evch_state = HIDMA_CH_STATE(val);
-	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
-	lldev->trch_state = HIDMA_CH_STATE(val);
-
-	/* already suspended by this OS */
-	if ((lldev->trch_state == HIDMA_CH_SUSPENDED) ||
-	    (lldev->evch_state == HIDMA_CH_SUSPENDED))
-		return 0;
-
-	/* already stopped by the manager */
-	if ((lldev->trch_state == HIDMA_CH_STOPPED) ||
-	    (lldev->evch_state == HIDMA_CH_STOPPED))
+	/* The channel needs to be in working state */
+	if (!hidma_ll_isenabled(lldev))
 		return 0;
 
 	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
@@ -654,7 +639,7 @@ int hidma_ll_setup(struct hidma_lldev *l
 	u32 val;
 	u32 nr_tres = lldev->nr_tres;
 
-	lldev->pending_tre_count = 0;
+	atomic_set(&lldev->pending_tre_count, 0);
 	lldev->tre_processed_off = 0;
 	lldev->evre_processed_off = 0;
 	lldev->tre_write_offset = 0;
@@ -691,17 +676,36 @@ int hidma_ll_setup(struct hidma_lldev *l
 	writel(HIDMA_EVRE_SIZE * nr_tres,
 			lldev->evca + HIDMA_EVCA_RING_LEN_REG);
 
-	/* support IRQ only for now */
+	/* configure interrupts */
+	hidma_ll_setup_irq(lldev, lldev->msi_support);
+
+	rc = hidma_ll_enable(lldev);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
+void hidma_ll_setup_irq(struct hidma_lldev *lldev, bool msi)
+{
+	u32 val;
+
+	lldev->msi_support = msi;
+
+	/* disable interrupts again after reset */
+	writel(0, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
+	writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
+	/* support IRQ by default */
 	val = readl(lldev->evca + HIDMA_EVCA_INTCTRL_REG);
 	val &= ~0xF;
-	val |= 0x1;
+	if (!lldev->msi_support)
+		val = val | 0x1;
 	writel(val, lldev->evca + HIDMA_EVCA_INTCTRL_REG);
 
 	/* clear all pending interrupts and enable them */
 	writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_CLR_REG);
 	writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
-
-	return hidma_ll_enable(lldev);
 }
 
 struct hidma_lldev *hidma_ll_init(struct device *dev, u32 nr_tres,
@@ -816,7 +820,7 @@ int hidma_ll_uninit(struct hidma_lldev *
 	tasklet_kill(&lldev->task);
 	memset(lldev->trepool, 0, required_bytes);
 	lldev->trepool = NULL;
-	lldev->pending_tre_count = 0;
+	atomic_set(&lldev->pending_tre_count, 0);
 	lldev->tre_write_offset = 0;
 
 	rc = hidma_ll_reset(lldev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/qcom/hidma_mgmt.c linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma_mgmt.c
--- linux-libre-4.9-gnu/drivers/dma/qcom/hidma_mgmt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/qcom/hidma_mgmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -282,6 +282,7 @@ static const struct acpi_device_id hidma
 	{"QCOM8060"},
 	{},
 };
+MODULE_DEVICE_TABLE(acpi, hidma_mgmt_acpi_ids);
 #endif
 
 static const struct of_device_id hidma_mgmt_match[] = {
@@ -375,8 +376,15 @@ static int __init hidma_mgmt_of_populate
 			ret = PTR_ERR(new_pdev);
 			goto out;
 		}
+		of_node_get(child);
+		new_pdev->dev.of_node = child;
 		of_dma_configure(&new_pdev->dev, child);
-
+		/*
+		 * It is assumed that calling of_msi_configure is safe on
+		 * platforms with or without MSI support.
+		 */
+		of_msi_configure(&new_pdev->dev, child);
+		of_node_put(child);
 		kfree(res);
 		res = NULL;
 	}
@@ -395,7 +403,6 @@ static int __init hidma_mgmt_init(void)
 	for_each_matching_node(child, hidma_mgmt_match) {
 		/* device tree based firmware here */
 		hidma_mgmt_of_populate_channels(child);
-		of_node_put(child);
 	}
 #endif
 	platform_driver_register(&hidma_mgmt_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/s3c24xx-dma.c linux-libre-4.10-rc8-gnu/drivers/dma/s3c24xx-dma.c
--- linux-libre-4.9-gnu/drivers/dma/s3c24xx-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/s3c24xx-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -289,16 +289,11 @@ static
 struct s3c24xx_dma_phy *s3c24xx_dma_get_phy(struct s3c24xx_dma_chan *s3cchan)
 {
 	struct s3c24xx_dma_engine *s3cdma = s3cchan->host;
-	const struct s3c24xx_dma_platdata *pdata = s3cdma->pdata;
-	struct s3c24xx_dma_channel *cdata;
 	struct s3c24xx_dma_phy *phy = NULL;
 	unsigned long flags;
 	int i;
 	int ret;
 
-	if (s3cchan->slave)
-		cdata = &pdata->channels[s3cchan->id];
-
 	for (i = 0; i < s3cdma->pdata->num_phy_channels; i++) {
 		phy = &s3cdma->phy_chans[i];
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/sh/rcar-dmac.c linux-libre-4.10-rc8-gnu/drivers/dma/sh/rcar-dmac.c
--- linux-libre-4.9-gnu/drivers/dma/sh/rcar-dmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/sh/rcar-dmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -986,6 +986,7 @@ static void rcar_dmac_free_chan_resource
 {
 	struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
 	struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
+	struct rcar_dmac_chan_map *map = &rchan->map;
 	struct rcar_dmac_desc_page *page, *_page;
 	struct rcar_dmac_desc *desc;
 	LIST_HEAD(list);
@@ -1019,6 +1020,13 @@ static void rcar_dmac_free_chan_resource
 		free_page((unsigned long)page);
 	}
 
+	/* Remove slave mapping if present. */
+	if (map->slave.xfer_size) {
+		dma_unmap_resource(chan->device->dev, map->addr,
+				   map->slave.xfer_size, map->dir, 0);
+		map->slave.xfer_size = 0;
+	}
+
 	pm_runtime_put(chan->device->dev);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/sh/usb-dmac.c linux-libre-4.10-rc8-gnu/drivers/dma/sh/usb-dmac.c
--- linux-libre-4.9-gnu/drivers/dma/sh/usb-dmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/sh/usb-dmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -652,7 +652,6 @@ static bool usb_dmac_chan_filter(struct
 static struct dma_chan *usb_dmac_of_xlate(struct of_phandle_args *dma_spec,
 					  struct of_dma *ofdma)
 {
-	struct usb_dmac_chan *uchan;
 	struct dma_chan *chan;
 	dma_cap_mask_t mask;
 
@@ -667,8 +666,6 @@ static struct dma_chan *usb_dmac_of_xlat
 	if (!chan)
 		return NULL;
 
-	uchan = to_usb_dmac_chan(chan);
-
 	return chan;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/sirf-dma.c linux-libre-4.10-rc8-gnu/drivers/dma/sirf-dma.c
--- linux-libre-4.9-gnu/drivers/dma/sirf-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/sirf-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -1011,7 +1011,6 @@ static int __maybe_unused sirfsoc_dma_pm
 {
 	struct sirfsoc_dma *sdma = dev_get_drvdata(dev);
 	struct sirfsoc_dma_regs *save = &sdma->regs_save;
-	struct sirfsoc_dma_desc *sdesc;
 	struct sirfsoc_dma_chan *schan;
 	int ch;
 	int ret;
@@ -1044,9 +1043,6 @@ static int __maybe_unused sirfsoc_dma_pm
 		schan = &sdma->channels[ch];
 		if (list_empty(&schan->active))
 			continue;
-		sdesc = list_first_entry(&schan->active,
-			struct sirfsoc_dma_desc,
-			node);
 		save->ctrl[ch] = readl_relaxed(sdma->base +
 			ch * 0x10 + SIRFSOC_DMA_CH_CTRL);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/st_fdma.c linux-libre-4.10-rc8-gnu/drivers/dma/st_fdma.c
--- linux-libre-4.9-gnu/drivers/dma/st_fdma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/st_fdma.c	2017-02-12 17:27:58.000000000 -0500
@@ -0,0 +1,889 @@
+/*
+ * DMA driver for STMicroelectronics STi FDMA controller
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ *
+ * Author: Ludovic Barre <Ludovic.barre@st.com>
+ *	   Peter Griffin <peter.griffin@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/remoteproc.h>
+
+#include "st_fdma.h"
+
+static inline struct st_fdma_chan *to_st_fdma_chan(struct dma_chan *c)
+{
+	return container_of(c, struct st_fdma_chan, vchan.chan);
+}
+
+static struct st_fdma_desc *to_st_fdma_desc(struct virt_dma_desc *vd)
+{
+	return container_of(vd, struct st_fdma_desc, vdesc);
+}
+
+static int st_fdma_dreq_get(struct st_fdma_chan *fchan)
+{
+	struct st_fdma_dev *fdev = fchan->fdev;
+	u32 req_line_cfg = fchan->cfg.req_line;
+	u32 dreq_line;
+	int try = 0;
+
+	/*
+	 * dreq_mask is shared for n channels of fdma, so all accesses must be
+	 * atomic. if the dreq_mask is changed between ffz and set_bit,
+	 * we retry
+	 */
+	do {
+		if (fdev->dreq_mask == ~0L) {
+			dev_err(fdev->dev, "No req lines available\n");
+			return -EINVAL;
+		}
+
+		if (try || req_line_cfg >= ST_FDMA_NR_DREQS) {
+			dev_err(fdev->dev, "Invalid or used req line\n");
+			return -EINVAL;
+		} else {
+			dreq_line = req_line_cfg;
+		}
+
+		try++;
+	} while (test_and_set_bit(dreq_line, &fdev->dreq_mask));
+
+	dev_dbg(fdev->dev, "get dreq_line:%d mask:%#lx\n",
+		dreq_line, fdev->dreq_mask);
+
+	return dreq_line;
+}
+
+static void st_fdma_dreq_put(struct st_fdma_chan *fchan)
+{
+	struct st_fdma_dev *fdev = fchan->fdev;
+
+	dev_dbg(fdev->dev, "put dreq_line:%#x\n", fchan->dreq_line);
+	clear_bit(fchan->dreq_line, &fdev->dreq_mask);
+}
+
+static void st_fdma_xfer_desc(struct st_fdma_chan *fchan)
+{
+	struct virt_dma_desc *vdesc;
+	unsigned long nbytes, ch_cmd, cmd;
+
+	vdesc = vchan_next_desc(&fchan->vchan);
+	if (!vdesc)
+		return;
+
+	fchan->fdesc = to_st_fdma_desc(vdesc);
+	nbytes = fchan->fdesc->node[0].desc->nbytes;
+	cmd = FDMA_CMD_START(fchan->vchan.chan.chan_id);
+	ch_cmd = fchan->fdesc->node[0].pdesc | FDMA_CH_CMD_STA_START;
+
+	/* start the channel for the descriptor */
+	fnode_write(fchan, nbytes, FDMA_CNTN_OFST);
+	fchan_write(fchan, ch_cmd, FDMA_CH_CMD_OFST);
+	writel(cmd,
+		fchan->fdev->slim_rproc->peri + FDMA_CMD_SET_OFST);
+
+	dev_dbg(fchan->fdev->dev, "start chan:%d\n", fchan->vchan.chan.chan_id);
+}
+
+static void st_fdma_ch_sta_update(struct st_fdma_chan *fchan,
+				  unsigned long int_sta)
+{
+	unsigned long ch_sta, ch_err;
+	int ch_id = fchan->vchan.chan.chan_id;
+	struct st_fdma_dev *fdev = fchan->fdev;
+
+	ch_sta = fchan_read(fchan, FDMA_CH_CMD_OFST);
+	ch_err = ch_sta & FDMA_CH_CMD_ERR_MASK;
+	ch_sta &= FDMA_CH_CMD_STA_MASK;
+
+	if (int_sta & FDMA_INT_STA_ERR) {
+		dev_warn(fdev->dev, "chan:%d, error:%ld\n", ch_id, ch_err);
+		fchan->status = DMA_ERROR;
+		return;
+	}
+
+	switch (ch_sta) {
+	case FDMA_CH_CMD_STA_PAUSED:
+		fchan->status = DMA_PAUSED;
+		break;
+
+	case FDMA_CH_CMD_STA_RUNNING:
+		fchan->status = DMA_IN_PROGRESS;
+		break;
+	}
+}
+
+static irqreturn_t st_fdma_irq_handler(int irq, void *dev_id)
+{
+	struct st_fdma_dev *fdev = dev_id;
+	irqreturn_t ret = IRQ_NONE;
+	struct st_fdma_chan *fchan = &fdev->chans[0];
+	unsigned long int_sta, clr;
+
+	int_sta = fdma_read(fdev, FDMA_INT_STA_OFST);
+	clr = int_sta;
+
+	for (; int_sta != 0 ; int_sta >>= 2, fchan++) {
+		if (!(int_sta & (FDMA_INT_STA_CH | FDMA_INT_STA_ERR)))
+			continue;
+
+		spin_lock(&fchan->vchan.lock);
+		st_fdma_ch_sta_update(fchan, int_sta);
+
+		if (fchan->fdesc) {
+			if (!fchan->fdesc->iscyclic) {
+				list_del(&fchan->fdesc->vdesc.node);
+				vchan_cookie_complete(&fchan->fdesc->vdesc);
+				fchan->fdesc = NULL;
+				fchan->status = DMA_COMPLETE;
+			} else {
+				vchan_cyclic_callback(&fchan->fdesc->vdesc);
+			}
+
+			/* Start the next descriptor (if available) */
+			if (!fchan->fdesc)
+				st_fdma_xfer_desc(fchan);
+		}
+
+		spin_unlock(&fchan->vchan.lock);
+		ret = IRQ_HANDLED;
+	}
+
+	fdma_write(fdev, clr, FDMA_INT_CLR_OFST);
+
+	return ret;
+}
+
+static struct dma_chan *st_fdma_of_xlate(struct of_phandle_args *dma_spec,
+					 struct of_dma *ofdma)
+{
+	struct st_fdma_dev *fdev = ofdma->of_dma_data;
+	struct dma_chan *chan;
+	struct st_fdma_chan *fchan;
+	int ret;
+
+	if (dma_spec->args_count < 1)
+		return ERR_PTR(-EINVAL);
+
+	if (fdev->dma_device.dev->of_node != dma_spec->np)
+		return ERR_PTR(-EINVAL);
+
+	ret = rproc_boot(fdev->slim_rproc->rproc);
+	if (ret == -ENOENT)
+		return ERR_PTR(-EPROBE_DEFER);
+	else if (ret)
+		return ERR_PTR(ret);
+
+	chan = dma_get_any_slave_channel(&fdev->dma_device);
+	if (!chan)
+		goto err_chan;
+
+	fchan = to_st_fdma_chan(chan);
+
+	fchan->cfg.of_node = dma_spec->np;
+	fchan->cfg.req_line = dma_spec->args[0];
+	fchan->cfg.req_ctrl = 0;
+	fchan->cfg.type = ST_FDMA_TYPE_FREE_RUN;
+
+	if (dma_spec->args_count > 1)
+		fchan->cfg.req_ctrl = dma_spec->args[1]
+			& FDMA_REQ_CTRL_CFG_MASK;
+
+	if (dma_spec->args_count > 2)
+		fchan->cfg.type = dma_spec->args[2];
+
+	if (fchan->cfg.type == ST_FDMA_TYPE_FREE_RUN) {
+		fchan->dreq_line = 0;
+	} else {
+		fchan->dreq_line = st_fdma_dreq_get(fchan);
+		if (IS_ERR_VALUE(fchan->dreq_line)) {
+			chan = ERR_PTR(fchan->dreq_line);
+			goto err_chan;
+		}
+	}
+
+	dev_dbg(fdev->dev, "xlate req_line:%d type:%d req_ctrl:%#lx\n",
+		fchan->cfg.req_line, fchan->cfg.type, fchan->cfg.req_ctrl);
+
+	return chan;
+
+err_chan:
+	rproc_shutdown(fdev->slim_rproc->rproc);
+	return chan;
+
+}
+
+static void st_fdma_free_desc(struct virt_dma_desc *vdesc)
+{
+	struct st_fdma_desc *fdesc;
+	int i;
+
+	fdesc = to_st_fdma_desc(vdesc);
+	for (i = 0; i < fdesc->n_nodes; i++)
+		dma_pool_free(fdesc->fchan->node_pool, fdesc->node[i].desc,
+			      fdesc->node[i].pdesc);
+	kfree(fdesc);
+}
+
+static struct st_fdma_desc *st_fdma_alloc_desc(struct st_fdma_chan *fchan,
+					       int sg_len)
+{
+	struct st_fdma_desc *fdesc;
+	int i;
+
+	fdesc = kzalloc(sizeof(*fdesc) +
+			sizeof(struct st_fdma_sw_node) * sg_len, GFP_NOWAIT);
+	if (!fdesc)
+		return NULL;
+
+	fdesc->fchan = fchan;
+	fdesc->n_nodes = sg_len;
+	for (i = 0; i < sg_len; i++) {
+		fdesc->node[i].desc = dma_pool_alloc(fchan->node_pool,
+				GFP_NOWAIT, &fdesc->node[i].pdesc);
+		if (!fdesc->node[i].desc)
+			goto err;
+	}
+	return fdesc;
+
+err:
+	while (--i >= 0)
+		dma_pool_free(fchan->node_pool, fdesc->node[i].desc,
+			      fdesc->node[i].pdesc);
+	kfree(fdesc);
+	return NULL;
+}
+
+static int st_fdma_alloc_chan_res(struct dma_chan *chan)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+
+	/* Create the dma pool for descriptor allocation */
+	fchan->node_pool = dma_pool_create(dev_name(&chan->dev->device),
+					    fchan->fdev->dev,
+					    sizeof(struct st_fdma_hw_node),
+					    __alignof__(struct st_fdma_hw_node),
+					    0);
+
+	if (!fchan->node_pool) {
+		dev_err(fchan->fdev->dev, "unable to allocate desc pool\n");
+		return -ENOMEM;
+	}
+
+	dev_dbg(fchan->fdev->dev, "alloc ch_id:%d type:%d\n",
+		fchan->vchan.chan.chan_id, fchan->cfg.type);
+
+	return 0;
+}
+
+static void st_fdma_free_chan_res(struct dma_chan *chan)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	struct rproc *rproc = fchan->fdev->slim_rproc->rproc;
+	unsigned long flags;
+
+	LIST_HEAD(head);
+
+	dev_dbg(fchan->fdev->dev, "%s: freeing chan:%d\n",
+		__func__, fchan->vchan.chan.chan_id);
+
+	if (fchan->cfg.type != ST_FDMA_TYPE_FREE_RUN)
+		st_fdma_dreq_put(fchan);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	fchan->fdesc = NULL;
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	dma_pool_destroy(fchan->node_pool);
+	fchan->node_pool = NULL;
+	memset(&fchan->cfg, 0, sizeof(struct st_fdma_cfg));
+
+	rproc_shutdown(rproc);
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_dma_memcpy(
+	struct dma_chan *chan,	dma_addr_t dst, dma_addr_t src,
+	size_t len, unsigned long flags)
+{
+	struct st_fdma_chan *fchan;
+	struct st_fdma_desc *fdesc;
+	struct st_fdma_hw_node *hw_node;
+
+	if (!len)
+		return NULL;
+
+	fchan = to_st_fdma_chan(chan);
+
+	/* We only require a single descriptor */
+	fdesc = st_fdma_alloc_desc(fchan, 1);
+	if (!fdesc) {
+		dev_err(fchan->fdev->dev, "no memory for desc\n");
+		return NULL;
+	}
+
+	hw_node = fdesc->node[0].desc;
+	hw_node->next = 0;
+	hw_node->control = FDMA_NODE_CTRL_REQ_MAP_FREE_RUN;
+	hw_node->control |= FDMA_NODE_CTRL_SRC_INCR;
+	hw_node->control |= FDMA_NODE_CTRL_DST_INCR;
+	hw_node->control |= FDMA_NODE_CTRL_INT_EON;
+	hw_node->nbytes = len;
+	hw_node->saddr = src;
+	hw_node->daddr = dst;
+	hw_node->generic.length = len;
+	hw_node->generic.sstride = 0;
+	hw_node->generic.dstride = 0;
+
+	return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static int config_reqctrl(struct st_fdma_chan *fchan,
+			  enum dma_transfer_direction direction)
+{
+	u32 maxburst = 0, addr = 0;
+	enum dma_slave_buswidth width;
+	int ch_id = fchan->vchan.chan.chan_id;
+	struct st_fdma_dev *fdev = fchan->fdev;
+
+	switch (direction) {
+
+	case DMA_DEV_TO_MEM:
+		fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_WNR;
+		maxburst = fchan->scfg.src_maxburst;
+		width = fchan->scfg.src_addr_width;
+		addr = fchan->scfg.src_addr;
+		break;
+
+	case DMA_MEM_TO_DEV:
+		fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_WNR;
+		maxburst = fchan->scfg.dst_maxburst;
+		width = fchan->scfg.dst_addr_width;
+		addr = fchan->scfg.dst_addr;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_OPCODE_MASK;
+
+	switch (width) {
+
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+		fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST1;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+		fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST2;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+		fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST4;
+		break;
+
+	case DMA_SLAVE_BUSWIDTH_8_BYTES:
+		fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_OPCODE_LD_ST8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	fchan->cfg.req_ctrl &= ~FDMA_REQ_CTRL_NUM_OPS_MASK;
+	fchan->cfg.req_ctrl |= FDMA_REQ_CTRL_NUM_OPS(maxburst-1);
+	dreq_write(fchan, fchan->cfg.req_ctrl, FDMA_REQ_CTRL_OFST);
+
+	fchan->cfg.dev_addr = addr;
+	fchan->cfg.dir = direction;
+
+	dev_dbg(fdev->dev, "chan:%d config_reqctrl:%#x req_ctrl:%#lx\n",
+		ch_id, addr, fchan->cfg.req_ctrl);
+
+	return 0;
+}
+
+static void fill_hw_node(struct st_fdma_hw_node *hw_node,
+			struct st_fdma_chan *fchan,
+			enum dma_transfer_direction direction)
+{
+	if (direction == DMA_MEM_TO_DEV) {
+		hw_node->control |= FDMA_NODE_CTRL_SRC_INCR;
+		hw_node->control |= FDMA_NODE_CTRL_DST_STATIC;
+		hw_node->daddr = fchan->cfg.dev_addr;
+	} else {
+		hw_node->control |= FDMA_NODE_CTRL_SRC_STATIC;
+		hw_node->control |= FDMA_NODE_CTRL_DST_INCR;
+		hw_node->saddr = fchan->cfg.dev_addr;
+	}
+
+	hw_node->generic.sstride = 0;
+	hw_node->generic.dstride = 0;
+}
+
+static inline struct st_fdma_chan *st_fdma_prep_common(struct dma_chan *chan,
+		size_t len, enum dma_transfer_direction direction)
+{
+	struct st_fdma_chan *fchan;
+
+	if (!chan || !len)
+		return NULL;
+
+	fchan = to_st_fdma_chan(chan);
+
+	if (!is_slave_direction(direction)) {
+		dev_err(fchan->fdev->dev, "bad direction?\n");
+		return NULL;
+	}
+
+	return fchan;
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t buf_addr, size_t len,
+		size_t period_len, enum dma_transfer_direction direction,
+		unsigned long flags)
+{
+	struct st_fdma_chan *fchan;
+	struct st_fdma_desc *fdesc;
+	int sg_len, i;
+
+	fchan = st_fdma_prep_common(chan, len, direction);
+	if (!fchan)
+		return NULL;
+
+	if (!period_len)
+		return NULL;
+
+	if (config_reqctrl(fchan, direction)) {
+		dev_err(fchan->fdev->dev, "bad width or direction\n");
+		return NULL;
+	}
+
+	/* the buffer length must be a multiple of period_len */
+	if (len % period_len != 0) {
+		dev_err(fchan->fdev->dev, "len is not multiple of period\n");
+		return NULL;
+	}
+
+	sg_len = len / period_len;
+	fdesc = st_fdma_alloc_desc(fchan, sg_len);
+	if (!fdesc) {
+		dev_err(fchan->fdev->dev, "no memory for desc\n");
+		return NULL;
+	}
+
+	fdesc->iscyclic = true;
+
+	for (i = 0; i < sg_len; i++) {
+		struct st_fdma_hw_node *hw_node = fdesc->node[i].desc;
+
+		hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc;
+
+		hw_node->control =
+			FDMA_NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line);
+		hw_node->control |= FDMA_NODE_CTRL_INT_EON;
+
+		fill_hw_node(hw_node, fchan, direction);
+
+		if (direction == DMA_MEM_TO_DEV)
+			hw_node->saddr = buf_addr + (i * period_len);
+		else
+			hw_node->daddr = buf_addr + (i * period_len);
+
+		hw_node->nbytes = period_len;
+		hw_node->generic.length = period_len;
+	}
+
+	return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static struct dma_async_tx_descriptor *st_fdma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct st_fdma_chan *fchan;
+	struct st_fdma_desc *fdesc;
+	struct st_fdma_hw_node *hw_node;
+	struct scatterlist *sg;
+	int i;
+
+	fchan = st_fdma_prep_common(chan, sg_len, direction);
+	if (!fchan)
+		return NULL;
+
+	if (!sgl)
+		return NULL;
+
+	fdesc = st_fdma_alloc_desc(fchan, sg_len);
+	if (!fdesc) {
+		dev_err(fchan->fdev->dev, "no memory for desc\n");
+		return NULL;
+	}
+
+	fdesc->iscyclic = false;
+
+	for_each_sg(sgl, sg, sg_len, i) {
+		hw_node = fdesc->node[i].desc;
+
+		hw_node->next = fdesc->node[(i + 1) % sg_len].pdesc;
+		hw_node->control = FDMA_NODE_CTRL_REQ_MAP_DREQ(fchan->dreq_line);
+
+		fill_hw_node(hw_node, fchan, direction);
+
+		if (direction == DMA_MEM_TO_DEV)
+			hw_node->saddr = sg_dma_address(sg);
+		else
+			hw_node->daddr = sg_dma_address(sg);
+
+		hw_node->nbytes = sg_dma_len(sg);
+		hw_node->generic.length = sg_dma_len(sg);
+	}
+
+	/* interrupt at end of last node */
+	hw_node->control |= FDMA_NODE_CTRL_INT_EON;
+
+	return vchan_tx_prep(&fchan->vchan, &fdesc->vdesc, flags);
+}
+
+static size_t st_fdma_desc_residue(struct st_fdma_chan *fchan,
+				   struct virt_dma_desc *vdesc,
+				   bool in_progress)
+{
+	struct st_fdma_desc *fdesc = fchan->fdesc;
+	size_t residue = 0;
+	dma_addr_t cur_addr = 0;
+	int i;
+
+	if (in_progress) {
+		cur_addr = fchan_read(fchan, FDMA_CH_CMD_OFST);
+		cur_addr &= FDMA_CH_CMD_DATA_MASK;
+	}
+
+	for (i = fchan->fdesc->n_nodes - 1 ; i >= 0; i--) {
+		if (cur_addr == fdesc->node[i].pdesc) {
+			residue += fnode_read(fchan, FDMA_CNTN_OFST);
+			break;
+		}
+		residue += fdesc->node[i].desc->nbytes;
+	}
+
+	return residue;
+}
+
+static enum dma_status st_fdma_tx_status(struct dma_chan *chan,
+					 dma_cookie_t cookie,
+					 struct dma_tx_state *txstate)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	struct virt_dma_desc *vd;
+	enum dma_status ret;
+	unsigned long flags;
+
+	ret = dma_cookie_status(chan, cookie, txstate);
+	if (ret == DMA_COMPLETE || !txstate)
+		return ret;
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	vd = vchan_find_desc(&fchan->vchan, cookie);
+	if (fchan->fdesc && cookie == fchan->fdesc->vdesc.tx.cookie)
+		txstate->residue = st_fdma_desc_residue(fchan, vd, true);
+	else if (vd)
+		txstate->residue = st_fdma_desc_residue(fchan, vd, false);
+	else
+		txstate->residue = 0;
+
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	return ret;
+}
+
+static void st_fdma_issue_pending(struct dma_chan *chan)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+
+	if (vchan_issue_pending(&fchan->vchan) && !fchan->fdesc)
+		st_fdma_xfer_desc(fchan);
+
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+}
+
+static int st_fdma_pause(struct dma_chan *chan)
+{
+	unsigned long flags;
+	LIST_HEAD(head);
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	int ch_id = fchan->vchan.chan.chan_id;
+	unsigned long cmd = FDMA_CMD_PAUSE(ch_id);
+
+	dev_dbg(fchan->fdev->dev, "pause chan:%d\n", ch_id);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	if (fchan->fdesc)
+		fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST);
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	return 0;
+}
+
+static int st_fdma_resume(struct dma_chan *chan)
+{
+	unsigned long flags;
+	unsigned long val;
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	int ch_id = fchan->vchan.chan.chan_id;
+
+	dev_dbg(fchan->fdev->dev, "resume chan:%d\n", ch_id);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	if (fchan->fdesc) {
+		val = fchan_read(fchan, FDMA_CH_CMD_OFST);
+		val &= FDMA_CH_CMD_DATA_MASK;
+		fchan_write(fchan, val, FDMA_CH_CMD_OFST);
+	}
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+
+	return 0;
+}
+
+static int st_fdma_terminate_all(struct dma_chan *chan)
+{
+	unsigned long flags;
+	LIST_HEAD(head);
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+	int ch_id = fchan->vchan.chan.chan_id;
+	unsigned long cmd = FDMA_CMD_PAUSE(ch_id);
+
+	dev_dbg(fchan->fdev->dev, "terminate chan:%d\n", ch_id);
+
+	spin_lock_irqsave(&fchan->vchan.lock, flags);
+	fdma_write(fchan->fdev, cmd, FDMA_CMD_SET_OFST);
+	fchan->fdesc = NULL;
+	vchan_get_all_descriptors(&fchan->vchan, &head);
+	spin_unlock_irqrestore(&fchan->vchan.lock, flags);
+	vchan_dma_desc_free_list(&fchan->vchan, &head);
+
+	return 0;
+}
+
+static int st_fdma_slave_config(struct dma_chan *chan,
+				struct dma_slave_config *slave_cfg)
+{
+	struct st_fdma_chan *fchan = to_st_fdma_chan(chan);
+
+	memcpy(&fchan->scfg, slave_cfg, sizeof(fchan->scfg));
+	return 0;
+}
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_11 = {
+	.name = "STiH407",
+	.id = 0,
+};
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_12 = {
+	.name = "STiH407",
+	.id = 1,
+};
+
+static const struct st_fdma_driverdata fdma_mpe31_stih407_13 = {
+	.name = "STiH407",
+	.id = 2,
+};
+
+static const struct of_device_id st_fdma_match[] = {
+	{ .compatible = "st,stih407-fdma-mpe31-11"
+	  , .data = &fdma_mpe31_stih407_11 },
+	{ .compatible = "st,stih407-fdma-mpe31-12"
+	  , .data = &fdma_mpe31_stih407_12 },
+	{ .compatible = "st,stih407-fdma-mpe31-13"
+	  , .data = &fdma_mpe31_stih407_13 },
+	{},
+};
+MODULE_DEVICE_TABLE(of, st_fdma_match);
+
+static int st_fdma_parse_dt(struct platform_device *pdev,
+			const struct st_fdma_driverdata *drvdata,
+			struct st_fdma_dev *fdev)
+{
+	snprintf(fdev->fw_name, FW_NAME_SIZE, "/*(DEBLOBBED)*/",
+		drvdata->name, drvdata->id);
+
+	return of_property_read_u32(pdev->dev.of_node, "dma-channels",
+				    &fdev->nr_channels);
+}
+#define FDMA_DMA_BUSWIDTHS	(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
+
+static void st_fdma_free(struct st_fdma_dev *fdev)
+{
+	struct st_fdma_chan *fchan;
+	int i;
+
+	for (i = 0; i < fdev->nr_channels; i++) {
+		fchan = &fdev->chans[i];
+		list_del(&fchan->vchan.chan.device_node);
+		tasklet_kill(&fchan->vchan.task);
+	}
+}
+
+static int st_fdma_probe(struct platform_device *pdev)
+{
+	struct st_fdma_dev *fdev;
+	const struct of_device_id *match;
+	struct device_node *np = pdev->dev.of_node;
+	const struct st_fdma_driverdata *drvdata;
+	int ret, i;
+
+	match = of_match_device((st_fdma_match), &pdev->dev);
+	if (!match || !match->data) {
+		dev_err(&pdev->dev, "No device match found\n");
+		return -ENODEV;
+	}
+
+	drvdata = match->data;
+
+	fdev = devm_kzalloc(&pdev->dev, sizeof(*fdev), GFP_KERNEL);
+	if (!fdev)
+		return -ENOMEM;
+
+	ret = st_fdma_parse_dt(pdev, drvdata, fdev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to find platform data\n");
+		goto err;
+	}
+
+	fdev->chans = devm_kcalloc(&pdev->dev, fdev->nr_channels,
+				   sizeof(struct st_fdma_chan), GFP_KERNEL);
+	if (!fdev->chans)
+		return -ENOMEM;
+
+	fdev->dev = &pdev->dev;
+	fdev->drvdata = drvdata;
+	platform_set_drvdata(pdev, fdev);
+
+	fdev->irq = platform_get_irq(pdev, 0);
+	if (fdev->irq < 0) {
+		dev_err(&pdev->dev, "Failed to get irq resource\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(&pdev->dev, fdev->irq, st_fdma_irq_handler, 0,
+			       dev_name(&pdev->dev), fdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq (%d)\n", ret);
+		goto err;
+	}
+
+	fdev->slim_rproc = st_slim_rproc_alloc(pdev, fdev->fw_name);
+	if (IS_ERR(fdev->slim_rproc)) {
+		ret = PTR_ERR(fdev->slim_rproc);
+		dev_err(&pdev->dev, "slim_rproc_alloc failed (%d)\n", ret);
+		goto err;
+	}
+
+	/* Initialise list of FDMA channels */
+	INIT_LIST_HEAD(&fdev->dma_device.channels);
+	for (i = 0; i < fdev->nr_channels; i++) {
+		struct st_fdma_chan *fchan = &fdev->chans[i];
+
+		fchan->fdev = fdev;
+		fchan->vchan.desc_free = st_fdma_free_desc;
+		vchan_init(&fchan->vchan, &fdev->dma_device);
+	}
+
+	/* Initialise the FDMA dreq (reserve 0 & 31 for FDMA use) */
+	fdev->dreq_mask = BIT(0) | BIT(31);
+
+	dma_cap_set(DMA_SLAVE, fdev->dma_device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, fdev->dma_device.cap_mask);
+	dma_cap_set(DMA_MEMCPY, fdev->dma_device.cap_mask);
+
+	fdev->dma_device.dev = &pdev->dev;
+	fdev->dma_device.device_alloc_chan_resources = st_fdma_alloc_chan_res;
+	fdev->dma_device.device_free_chan_resources = st_fdma_free_chan_res;
+	fdev->dma_device.device_prep_dma_cyclic	= st_fdma_prep_dma_cyclic;
+	fdev->dma_device.device_prep_slave_sg = st_fdma_prep_slave_sg;
+	fdev->dma_device.device_prep_dma_memcpy = st_fdma_prep_dma_memcpy;
+	fdev->dma_device.device_tx_status = st_fdma_tx_status;
+	fdev->dma_device.device_issue_pending = st_fdma_issue_pending;
+	fdev->dma_device.device_terminate_all = st_fdma_terminate_all;
+	fdev->dma_device.device_config = st_fdma_slave_config;
+	fdev->dma_device.device_pause = st_fdma_pause;
+	fdev->dma_device.device_resume = st_fdma_resume;
+
+	fdev->dma_device.src_addr_widths = FDMA_DMA_BUSWIDTHS;
+	fdev->dma_device.dst_addr_widths = FDMA_DMA_BUSWIDTHS;
+	fdev->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	fdev->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+
+	ret = dma_async_device_register(&fdev->dma_device);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Failed to register DMA device (%d)\n", ret);
+		goto err_rproc;
+	}
+
+	ret = of_dma_controller_register(np, st_fdma_of_xlate, fdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Failed to register controller (%d)\n", ret);
+		goto err_dma_dev;
+	}
+
+	dev_info(&pdev->dev, "ST FDMA engine driver, irq:%d\n", fdev->irq);
+
+	return 0;
+
+err_dma_dev:
+	dma_async_device_unregister(&fdev->dma_device);
+err_rproc:
+	st_fdma_free(fdev);
+	st_slim_rproc_put(fdev->slim_rproc);
+err:
+	return ret;
+}
+
+static int st_fdma_remove(struct platform_device *pdev)
+{
+	struct st_fdma_dev *fdev = platform_get_drvdata(pdev);
+
+	devm_free_irq(&pdev->dev, fdev->irq, fdev);
+	st_slim_rproc_put(fdev->slim_rproc);
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&fdev->dma_device);
+
+	return 0;
+}
+
+static struct platform_driver st_fdma_platform_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = st_fdma_match,
+	},
+	.probe = st_fdma_probe,
+	.remove = st_fdma_remove,
+};
+module_platform_driver(st_fdma_platform_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver");
+MODULE_AUTHOR("Ludovic.barre <Ludovic.barre@st.com>");
+MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>");
+MODULE_ALIAS("platform: " DRIVER_NAME);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/st_fdma.h linux-libre-4.10-rc8-gnu/drivers/dma/st_fdma.h
--- linux-libre-4.9-gnu/drivers/dma/st_fdma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/st_fdma.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,249 @@
+/*
+ * DMA driver header for STMicroelectronics STi FDMA controller
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ *
+ * Author: Ludovic Barre <Ludovic.barre@st.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_ST_FDMA_H
+#define __DMA_ST_FDMA_H
+
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/io.h>
+#include <linux/remoteproc/st_slim_rproc.h>
+#include "virt-dma.h"
+
+#define ST_FDMA_NR_DREQS 32
+#define FW_NAME_SIZE 30
+#define DRIVER_NAME "st-fdma"
+
+/**
+ * struct st_fdma_generic_node - Free running/paced generic node
+ *
+ * @length: Length in bytes of a line in a 2D mem to mem
+ * @sstride: Stride, in bytes, between source lines in a 2D data move
+ * @dstride: Stride, in bytes, between destination lines in a 2D data move
+ */
+struct st_fdma_generic_node {
+	u32 length;
+	u32 sstride;
+	u32 dstride;
+};
+
+/**
+ * struct st_fdma_hw_node - Node structure used by fdma hw
+ *
+ * @next: Pointer to next node
+ * @control: Transfer Control Parameters
+ * @nbytes: Number of Bytes to read
+ * @saddr: Source address
+ * @daddr: Destination address
+ *
+ * @generic: generic node for free running/paced transfert type
+ * 2 others transfert type are possible, but not yet implemented
+ *
+ * The NODE structures must be aligned to a 32 byte boundary
+ */
+struct st_fdma_hw_node {
+	u32 next;
+	u32 control;
+	u32 nbytes;
+	u32 saddr;
+	u32 daddr;
+	union {
+		struct st_fdma_generic_node generic;
+	};
+} __aligned(32);
+
+/*
+ * node control parameters
+ */
+#define FDMA_NODE_CTRL_REQ_MAP_MASK	GENMASK(4, 0)
+#define FDMA_NODE_CTRL_REQ_MAP_FREE_RUN	0x0
+#define FDMA_NODE_CTRL_REQ_MAP_DREQ(n)	((n)&FDMA_NODE_CTRL_REQ_MAP_MASK)
+#define FDMA_NODE_CTRL_REQ_MAP_EXT		FDMA_NODE_CTRL_REQ_MAP_MASK
+#define FDMA_NODE_CTRL_SRC_MASK		GENMASK(6, 5)
+#define FDMA_NODE_CTRL_SRC_STATIC	BIT(5)
+#define FDMA_NODE_CTRL_SRC_INCR		BIT(6)
+#define FDMA_NODE_CTRL_DST_MASK		GENMASK(8, 7)
+#define FDMA_NODE_CTRL_DST_STATIC	BIT(7)
+#define FDMA_NODE_CTRL_DST_INCR		BIT(8)
+#define FDMA_NODE_CTRL_SECURE		BIT(15)
+#define FDMA_NODE_CTRL_PAUSE_EON	BIT(30)
+#define FDMA_NODE_CTRL_INT_EON		BIT(31)
+
+/**
+ * struct st_fdma_sw_node - descriptor structure for link list
+ *
+ * @pdesc: Physical address of desc
+ * @node: link used for putting this into a channel queue
+ */
+struct st_fdma_sw_node {
+	dma_addr_t pdesc;
+	struct st_fdma_hw_node *desc;
+};
+
+#define NAME_SZ 10
+
+struct st_fdma_driverdata {
+	u32 id;
+	char name[NAME_SZ];
+};
+
+struct st_fdma_desc {
+	struct virt_dma_desc vdesc;
+	struct st_fdma_chan *fchan;
+	bool iscyclic;
+	unsigned int n_nodes;
+	struct st_fdma_sw_node node[];
+};
+
+enum st_fdma_type {
+	ST_FDMA_TYPE_FREE_RUN,
+	ST_FDMA_TYPE_PACED,
+};
+
+struct st_fdma_cfg {
+	struct device_node *of_node;
+	enum st_fdma_type type;
+	dma_addr_t dev_addr;
+	enum dma_transfer_direction dir;
+	int req_line; /* request line */
+	long req_ctrl; /* Request control */
+};
+
+struct st_fdma_chan {
+	struct st_fdma_dev *fdev;
+	struct dma_pool *node_pool;
+	struct dma_slave_config scfg;
+	struct st_fdma_cfg cfg;
+
+	int dreq_line;
+
+	struct virt_dma_chan vchan;
+	struct st_fdma_desc *fdesc;
+	enum dma_status	status;
+};
+
+struct st_fdma_dev {
+	struct device *dev;
+	const struct st_fdma_driverdata *drvdata;
+	struct dma_device dma_device;
+
+	struct st_slim_rproc *slim_rproc;
+
+	int irq;
+
+	struct st_fdma_chan *chans;
+
+	spinlock_t dreq_lock;
+	unsigned long dreq_mask;
+
+	u32 nr_channels;
+	char fw_name[FW_NAME_SIZE];
+};
+
+/* Peripheral Registers*/
+
+#define FDMA_CMD_STA_OFST	0xFC0
+#define FDMA_CMD_SET_OFST	0xFC4
+#define FDMA_CMD_CLR_OFST	0xFC8
+#define FDMA_CMD_MASK_OFST	0xFCC
+#define FDMA_CMD_START(ch)		(0x1 << (ch << 1))
+#define FDMA_CMD_PAUSE(ch)		(0x2 << (ch << 1))
+#define FDMA_CMD_FLUSH(ch)		(0x3 << (ch << 1))
+
+#define FDMA_INT_STA_OFST	0xFD0
+#define FDMA_INT_STA_CH			0x1
+#define FDMA_INT_STA_ERR		0x2
+
+#define FDMA_INT_SET_OFST	0xFD4
+#define FDMA_INT_CLR_OFST	0xFD8
+#define FDMA_INT_MASK_OFST	0xFDC
+
+#define fdma_read(fdev, name) \
+	readl((fdev)->slim_rproc->peri + name)
+
+#define fdma_write(fdev, val, name) \
+	writel((val), (fdev)->slim_rproc->peri + name)
+
+/* fchan interface (dmem) */
+#define FDMA_CH_CMD_OFST	0x200
+#define FDMA_CH_CMD_STA_MASK		GENMASK(1, 0)
+#define FDMA_CH_CMD_STA_IDLE		(0x0)
+#define FDMA_CH_CMD_STA_START		(0x1)
+#define FDMA_CH_CMD_STA_RUNNING		(0x2)
+#define FDMA_CH_CMD_STA_PAUSED		(0x3)
+#define FDMA_CH_CMD_ERR_MASK		GENMASK(4, 2)
+#define FDMA_CH_CMD_ERR_INT		(0x0 << 2)
+#define FDMA_CH_CMD_ERR_NAND		(0x1 << 2)
+#define FDMA_CH_CMD_ERR_MCHI		(0x2 << 2)
+#define FDMA_CH_CMD_DATA_MASK		GENMASK(31, 5)
+#define fchan_read(fchan, name) \
+	readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * 0x4 \
+			+ name)
+
+#define fchan_write(fchan, val, name) \
+	writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * 0x4 \
+			+ name)
+
+/* req interface */
+#define FDMA_REQ_CTRL_OFST	0x240
+#define dreq_write(fchan, val, name) \
+	writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+			+ fchan->dreq_line * 0x04 \
+			+ name)
+/* node interface */
+#define FDMA_NODE_SZ 128
+#define FDMA_PTRN_OFST		0x800
+#define FDMA_CNTN_OFST		0x808
+#define FDMA_SADDRN_OFST	0x80c
+#define FDMA_DADDRN_OFST	0x810
+#define fnode_read(fchan, name) \
+	readl((fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \
+			+ name)
+
+#define fnode_write(fchan, val, name) \
+	writel((val), (fchan)->fdev->slim_rproc->mem[ST_SLIM_DMEM].cpu_addr \
+			+ (fchan)->vchan.chan.chan_id * FDMA_NODE_SZ \
+			+ name)
+
+/*
+ * request control bits
+ */
+#define FDMA_REQ_CTRL_NUM_OPS_MASK	GENMASK(31, 24)
+#define FDMA_REQ_CTRL_NUM_OPS(n)	(FDMA_REQ_CTRL_NUM_OPS_MASK & \
+					((n) << 24))
+#define FDMA_REQ_CTRL_INITIATOR_MASK	BIT(22)
+#define FDMA_REQ_CTRL_INIT0		(0x0 << 22)
+#define FDMA_REQ_CTRL_INIT1		(0x1 << 22)
+#define FDMA_REQ_CTRL_INC_ADDR_ON	BIT(21)
+#define FDMA_REQ_CTRL_DATA_SWAP_ON	BIT(17)
+#define FDMA_REQ_CTRL_WNR		BIT(14)
+#define FDMA_REQ_CTRL_OPCODE_MASK	GENMASK(7, 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST1	(0x0 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST2	(0x1 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST4	(0x2 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST8	(0x3 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST16	(0x4 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST32	(0x5 << 4)
+#define FDMA_REQ_CTRL_OPCODE_LD_ST64	(0x6 << 4)
+#define FDMA_REQ_CTRL_HOLDOFF_MASK	GENMASK(2, 0)
+#define FDMA_REQ_CTRL_HOLDOFF(n)	((n) & FDMA_REQ_CTRL_HOLDOFF_MASK)
+
+/* bits used by client to configure request control */
+#define FDMA_REQ_CTRL_CFG_MASK (FDMA_REQ_CTRL_HOLDOFF_MASK | \
+				FDMA_REQ_CTRL_DATA_SWAP_ON | \
+				FDMA_REQ_CTRL_INC_ADDR_ON | \
+				FDMA_REQ_CTRL_INITIATOR_MASK)
+
+#endif	/* __DMA_ST_FDMA_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/stm32-dma.c linux-libre-4.10-rc8-gnu/drivers/dma/stm32-dma.c
--- linux-libre-4.9-gnu/drivers/dma/stm32-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/stm32-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -527,13 +527,12 @@ static irqreturn_t stm32_dma_chan_irq(in
 {
 	struct stm32_dma_chan *chan = devid;
 	struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan);
-	u32 status, scr, sfcr;
+	u32 status, scr;
 
 	spin_lock(&chan->vchan.lock);
 
 	status = stm32_dma_irq_status(chan);
 	scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id));
-	sfcr = stm32_dma_read(dmadev, STM32_DMA_SFCR(chan->id));
 
 	if ((status & STM32_DMA_TCI) && (scr & STM32_DMA_SCR_TCIE)) {
 		stm32_dma_irq_clear(chan, STM32_DMA_TCI);
@@ -574,15 +573,12 @@ static int stm32_dma_set_xfer_param(stru
 	int src_bus_width, dst_bus_width;
 	int src_burst_size, dst_burst_size;
 	u32 src_maxburst, dst_maxburst;
-	dma_addr_t src_addr, dst_addr;
 	u32 dma_scr = 0;
 
 	src_addr_width = chan->dma_sconfig.src_addr_width;
 	dst_addr_width = chan->dma_sconfig.dst_addr_width;
 	src_maxburst = chan->dma_sconfig.src_maxburst;
 	dst_maxburst = chan->dma_sconfig.dst_maxburst;
-	src_addr = chan->dma_sconfig.src_addr;
-	dst_addr = chan->dma_sconfig.dst_addr;
 
 	switch (direction) {
 	case DMA_MEM_TO_DEV:
@@ -884,7 +880,7 @@ static enum dma_status stm32_dma_tx_stat
 	struct virt_dma_desc *vdesc;
 	enum dma_status status;
 	unsigned long flags;
-	u32 residue;
+	u32 residue = 0;
 
 	status = dma_cookie_status(c, cookie, state);
 	if ((status == DMA_COMPLETE) || (!state))
@@ -892,16 +888,12 @@ static enum dma_status stm32_dma_tx_stat
 
 	spin_lock_irqsave(&chan->vchan.lock, flags);
 	vdesc = vchan_find_desc(&chan->vchan, cookie);
-	if (cookie == chan->desc->vdesc.tx.cookie) {
+	if (chan->desc && cookie == chan->desc->vdesc.tx.cookie)
 		residue = stm32_dma_desc_residue(chan, chan->desc,
 						 chan->next_sg);
-	} else if (vdesc) {
+	else if (vdesc)
 		residue = stm32_dma_desc_residue(chan,
 						 to_stm32_dma_desc(vdesc), 0);
-	} else {
-		residue = 0;
-	}
-
 	dma_set_residue(state, residue);
 
 	spin_unlock_irqrestore(&chan->vchan.lock, flags);
@@ -976,21 +968,18 @@ static struct dma_chan *stm32_dma_of_xla
 	struct stm32_dma_chan *chan;
 	struct dma_chan *c;
 
-	if (dma_spec->args_count < 3)
+	if (dma_spec->args_count < 4)
 		return NULL;
 
 	cfg.channel_id = dma_spec->args[0];
 	cfg.request_line = dma_spec->args[1];
 	cfg.stream_config = dma_spec->args[2];
-	cfg.threshold = 0;
+	cfg.threshold = dma_spec->args[3];
 
 	if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >=
 				STM32_DMA_MAX_REQUEST_ID))
 		return NULL;
 
-	if (dma_spec->args_count > 3)
-		cfg.threshold = dma_spec->args[3];
-
 	chan = &dmadev->chan[cfg.channel_id];
 
 	c = dma_get_slave_channel(&chan->vchan.chan);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/ti-dma-crossbar.c linux-libre-4.10-rc8-gnu/drivers/dma/ti-dma-crossbar.c
--- linux-libre-4.9-gnu/drivers/dma/ti-dma-crossbar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/ti-dma-crossbar.c	2017-02-12 16:03:20.000000000 -0500
@@ -149,6 +149,7 @@ static int ti_am335x_xbar_probe(struct p
 	match = of_match_node(ti_am335x_master_match, dma_node);
 	if (!match) {
 		dev_err(&pdev->dev, "DMA master is not supported\n");
+		of_node_put(dma_node);
 		return -EINVAL;
 	}
 
@@ -339,6 +340,7 @@ static int ti_dra7_xbar_probe(struct pla
 	match = of_match_node(ti_dra7_master_match, dma_node);
 	if (!match) {
 		dev_err(&pdev->dev, "DMA master is not supported\n");
+		of_node_put(dma_node);
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma/zx296702_dma.c linux-libre-4.10-rc8-gnu/drivers/dma/zx296702_dma.c
--- linux-libre-4.9-gnu/drivers/dma/zx296702_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma/zx296702_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -435,13 +435,12 @@ static struct zx_dma_desc_sw *zx_alloc_d
 	if (!ds)
 		return NULL;
 
-	ds->desc_hw = dma_pool_alloc(d->pool, GFP_NOWAIT, &ds->desc_hw_lli);
+	ds->desc_hw = dma_pool_zalloc(d->pool, GFP_NOWAIT, &ds->desc_hw_lli);
 	if (!ds->desc_hw) {
 		dev_dbg(chan->device->dev, "vch %p: dma alloc fail\n", &c->vc);
 		kfree(ds);
 		return NULL;
 	}
-	memset(ds->desc_hw, 0, sizeof(struct zx_desc_hw) * num);
 	ds->desc_num = num;
 	return ds;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/dma-buf.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/dma-buf.c
--- linux-libre-4.9-gnu/drivers/dma-buf/dma-buf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/dma-buf.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/dma-buf.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 #include <linux/anon_inodes.h>
 #include <linux/export.h>
 #include <linux/debugfs.h>
@@ -124,7 +124,7 @@ static loff_t dma_buf_llseek(struct file
 	return base + offset;
 }
 
-static void dma_buf_poll_cb(struct fence *fence, struct fence_cb *cb)
+static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
 {
 	struct dma_buf_poll_cb_t *dcb = (struct dma_buf_poll_cb_t *)cb;
 	unsigned long flags;
@@ -140,7 +140,7 @@ static unsigned int dma_buf_poll(struct
 	struct dma_buf *dmabuf;
 	struct reservation_object *resv;
 	struct reservation_object_list *fobj;
-	struct fence *fence_excl;
+	struct dma_fence *fence_excl;
 	unsigned long events;
 	unsigned shared_count, seq;
 
@@ -187,20 +187,20 @@ retry:
 		spin_unlock_irq(&dmabuf->poll.lock);
 
 		if (events & pevents) {
-			if (!fence_get_rcu(fence_excl)) {
+			if (!dma_fence_get_rcu(fence_excl)) {
 				/* force a recheck */
 				events &= ~pevents;
 				dma_buf_poll_cb(NULL, &dcb->cb);
-			} else if (!fence_add_callback(fence_excl, &dcb->cb,
-						       dma_buf_poll_cb)) {
+			} else if (!dma_fence_add_callback(fence_excl, &dcb->cb,
+							   dma_buf_poll_cb)) {
 				events &= ~pevents;
-				fence_put(fence_excl);
+				dma_fence_put(fence_excl);
 			} else {
 				/*
 				 * No callback queued, wake up any additional
 				 * waiters.
 				 */
-				fence_put(fence_excl);
+				dma_fence_put(fence_excl);
 				dma_buf_poll_cb(NULL, &dcb->cb);
 			}
 		}
@@ -222,9 +222,9 @@ retry:
 			goto out;
 
 		for (i = 0; i < shared_count; ++i) {
-			struct fence *fence = rcu_dereference(fobj->shared[i]);
+			struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
 
-			if (!fence_get_rcu(fence)) {
+			if (!dma_fence_get_rcu(fence)) {
 				/*
 				 * fence refcount dropped to zero, this means
 				 * that fobj has been freed
@@ -235,13 +235,13 @@ retry:
 				dma_buf_poll_cb(NULL, &dcb->cb);
 				break;
 			}
-			if (!fence_add_callback(fence, &dcb->cb,
-						dma_buf_poll_cb)) {
-				fence_put(fence);
+			if (!dma_fence_add_callback(fence, &dcb->cb,
+						    dma_buf_poll_cb)) {
+				dma_fence_put(fence);
 				events &= ~POLLOUT;
 				break;
 			}
-			fence_put(fence);
+			dma_fence_put(fence);
 		}
 
 		/* No callback queued, wake up any additional waiters. */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/dma-fence-array.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/dma-fence-array.c
--- linux-libre-4.9-gnu/drivers/dma-buf/dma-fence-array.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/dma-fence-array.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,146 @@
+/*
+ * dma-fence-array: aggregate fences to be waited together
+ *
+ * Copyright (C) 2016 Collabora Ltd
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ * Authors:
+ *	Gustavo Padovan <gustavo@padovan.org>
+ *	Christian König <christian.koenig@amd.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/export.h>
+#include <linux/slab.h>
+#include <linux/dma-fence-array.h>
+
+static const char *dma_fence_array_get_driver_name(struct dma_fence *fence)
+{
+	return "dma_fence_array";
+}
+
+static const char *dma_fence_array_get_timeline_name(struct dma_fence *fence)
+{
+	return "unbound";
+}
+
+static void dma_fence_array_cb_func(struct dma_fence *f,
+				    struct dma_fence_cb *cb)
+{
+	struct dma_fence_array_cb *array_cb =
+		container_of(cb, struct dma_fence_array_cb, cb);
+	struct dma_fence_array *array = array_cb->array;
+
+	if (atomic_dec_and_test(&array->num_pending))
+		dma_fence_signal(&array->base);
+	dma_fence_put(&array->base);
+}
+
+static bool dma_fence_array_enable_signaling(struct dma_fence *fence)
+{
+	struct dma_fence_array *array = to_dma_fence_array(fence);
+	struct dma_fence_array_cb *cb = (void *)(&array[1]);
+	unsigned i;
+
+	for (i = 0; i < array->num_fences; ++i) {
+		cb[i].array = array;
+		/*
+		 * As we may report that the fence is signaled before all
+		 * callbacks are complete, we need to take an additional
+		 * reference count on the array so that we do not free it too
+		 * early. The core fence handling will only hold the reference
+		 * until we signal the array as complete (but that is now
+		 * insufficient).
+		 */
+		dma_fence_get(&array->base);
+		if (dma_fence_add_callback(array->fences[i], &cb[i].cb,
+					   dma_fence_array_cb_func)) {
+			dma_fence_put(&array->base);
+			if (atomic_dec_and_test(&array->num_pending))
+				return false;
+		}
+	}
+
+	return true;
+}
+
+static bool dma_fence_array_signaled(struct dma_fence *fence)
+{
+	struct dma_fence_array *array = to_dma_fence_array(fence);
+
+	return atomic_read(&array->num_pending) <= 0;
+}
+
+static void dma_fence_array_release(struct dma_fence *fence)
+{
+	struct dma_fence_array *array = to_dma_fence_array(fence);
+	unsigned i;
+
+	for (i = 0; i < array->num_fences; ++i)
+		dma_fence_put(array->fences[i]);
+
+	kfree(array->fences);
+	dma_fence_free(fence);
+}
+
+const struct dma_fence_ops dma_fence_array_ops = {
+	.get_driver_name = dma_fence_array_get_driver_name,
+	.get_timeline_name = dma_fence_array_get_timeline_name,
+	.enable_signaling = dma_fence_array_enable_signaling,
+	.signaled = dma_fence_array_signaled,
+	.wait = dma_fence_default_wait,
+	.release = dma_fence_array_release,
+};
+EXPORT_SYMBOL(dma_fence_array_ops);
+
+/**
+ * dma_fence_array_create - Create a custom fence array
+ * @num_fences:		[in]	number of fences to add in the array
+ * @fences:		[in]	array containing the fences
+ * @context:		[in]	fence context to use
+ * @seqno:		[in]	sequence number to use
+ * @signal_on_any:	[in]	signal on any fence in the array
+ *
+ * Allocate a dma_fence_array object and initialize the base fence with
+ * dma_fence_init().
+ * In case of error it returns NULL.
+ *
+ * The caller should allocate the fences array with num_fences size
+ * and fill it with the fences it wants to add to the object. Ownership of this
+ * array is taken and dma_fence_put() is used on each fence on release.
+ *
+ * If @signal_on_any is true the fence array signals if any fence in the array
+ * signals, otherwise it signals when all fences in the array signal.
+ */
+struct dma_fence_array *dma_fence_array_create(int num_fences,
+					       struct dma_fence **fences,
+					       u64 context, unsigned seqno,
+					       bool signal_on_any)
+{
+	struct dma_fence_array *array;
+	size_t size = sizeof(*array);
+
+	/* Allocate the callback structures behind the array. */
+	size += num_fences * sizeof(struct dma_fence_array_cb);
+	array = kzalloc(size, GFP_KERNEL);
+	if (!array)
+		return NULL;
+
+	spin_lock_init(&array->lock);
+	dma_fence_init(&array->base, &dma_fence_array_ops, &array->lock,
+		       context, seqno);
+
+	array->num_fences = num_fences;
+	atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
+	array->fences = fences;
+
+	return array;
+}
+EXPORT_SYMBOL(dma_fence_array_create);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/dma-fence.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/dma-fence.c
--- linux-libre-4.9-gnu/drivers/dma-buf/dma-fence.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/dma-fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,547 @@
+/*
+ * Fence mechanism for dma-buf and to allow for asynchronous dma access
+ *
+ * Copyright (C) 2012 Canonical Ltd
+ * Copyright (C) 2012 Texas Instruments
+ *
+ * Authors:
+ * Rob Clark <robdclark@gmail.com>
+ * Maarten Lankhorst <maarten.lankhorst@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <linux/atomic.h>
+#include <linux/dma-fence.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/dma_fence.h>
+
+EXPORT_TRACEPOINT_SYMBOL(dma_fence_annotate_wait_on);
+EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit);
+
+/*
+ * fence context counter: each execution context should have its own
+ * fence context, this allows checking if fences belong to the same
+ * context or not. One device can have multiple separate contexts,
+ * and they're used if some engine can run independently of another.
+ */
+static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(0);
+
+/**
+ * dma_fence_context_alloc - allocate an array of fence contexts
+ * @num:	[in]	amount of contexts to allocate
+ *
+ * This function will return the first index of the number of fences allocated.
+ * The fence context is used for setting fence->context to a unique number.
+ */
+u64 dma_fence_context_alloc(unsigned num)
+{
+	BUG_ON(!num);
+	return atomic64_add_return(num, &dma_fence_context_counter) - num;
+}
+EXPORT_SYMBOL(dma_fence_context_alloc);
+
+/**
+ * dma_fence_signal_locked - signal completion of a fence
+ * @fence: the fence to signal
+ *
+ * Signal completion for software callbacks on a fence, this will unblock
+ * dma_fence_wait() calls and run all the callbacks added with
+ * dma_fence_add_callback(). Can be called multiple times, but since a fence
+ * can only go from unsignaled to signaled state, it will only be effective
+ * the first time.
+ *
+ * Unlike dma_fence_signal, this function must be called with fence->lock held.
+ */
+int dma_fence_signal_locked(struct dma_fence *fence)
+{
+	struct dma_fence_cb *cur, *tmp;
+	int ret = 0;
+
+	lockdep_assert_held(fence->lock);
+
+	if (WARN_ON(!fence))
+		return -EINVAL;
+
+	if (!ktime_to_ns(fence->timestamp)) {
+		fence->timestamp = ktime_get();
+		smp_mb__before_atomic();
+	}
+
+	if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+		ret = -EINVAL;
+
+		/*
+		 * we might have raced with the unlocked dma_fence_signal,
+		 * still run through all callbacks
+		 */
+	} else
+		trace_dma_fence_signaled(fence);
+
+	list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
+		list_del_init(&cur->node);
+		cur->func(fence, cur);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(dma_fence_signal_locked);
+
+/**
+ * dma_fence_signal - signal completion of a fence
+ * @fence: the fence to signal
+ *
+ * Signal completion for software callbacks on a fence, this will unblock
+ * dma_fence_wait() calls and run all the callbacks added with
+ * dma_fence_add_callback(). Can be called multiple times, but since a fence
+ * can only go from unsignaled to signaled state, it will only be effective
+ * the first time.
+ */
+int dma_fence_signal(struct dma_fence *fence)
+{
+	unsigned long flags;
+
+	if (!fence)
+		return -EINVAL;
+
+	if (!ktime_to_ns(fence->timestamp)) {
+		fence->timestamp = ktime_get();
+		smp_mb__before_atomic();
+	}
+
+	if (test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		return -EINVAL;
+
+	trace_dma_fence_signaled(fence);
+
+	if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
+		struct dma_fence_cb *cur, *tmp;
+
+		spin_lock_irqsave(fence->lock, flags);
+		list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
+			list_del_init(&cur->node);
+			cur->func(fence, cur);
+		}
+		spin_unlock_irqrestore(fence->lock, flags);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dma_fence_signal);
+
+/**
+ * dma_fence_wait_timeout - sleep until the fence gets signaled
+ * or until timeout elapses
+ * @fence:	[in]	the fence to wait on
+ * @intr:	[in]	if true, do an interruptible wait
+ * @timeout:	[in]	timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
+ *
+ * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
+ * remaining timeout in jiffies on success. Other error values may be
+ * returned on custom implementations.
+ *
+ * Performs a synchronous wait on this fence. It is assumed the caller
+ * directly or indirectly (buf-mgr between reservation and committing)
+ * holds a reference to the fence, otherwise the fence might be
+ * freed before return, resulting in undefined behavior.
+ */
+signed long
+dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
+{
+	signed long ret;
+
+	if (WARN_ON(timeout < 0))
+		return -EINVAL;
+
+	trace_dma_fence_wait_start(fence);
+	ret = fence->ops->wait(fence, intr, timeout);
+	trace_dma_fence_wait_end(fence);
+	return ret;
+}
+EXPORT_SYMBOL(dma_fence_wait_timeout);
+
+void dma_fence_release(struct kref *kref)
+{
+	struct dma_fence *fence =
+		container_of(kref, struct dma_fence, refcount);
+
+	trace_dma_fence_destroy(fence);
+
+	BUG_ON(!list_empty(&fence->cb_list));
+
+	if (fence->ops->release)
+		fence->ops->release(fence);
+	else
+		dma_fence_free(fence);
+}
+EXPORT_SYMBOL(dma_fence_release);
+
+void dma_fence_free(struct dma_fence *fence)
+{
+	kfree_rcu(fence, rcu);
+}
+EXPORT_SYMBOL(dma_fence_free);
+
+/**
+ * dma_fence_enable_sw_signaling - enable signaling on fence
+ * @fence:	[in]	the fence to enable
+ *
+ * this will request for sw signaling to be enabled, to make the fence
+ * complete as soon as possible
+ */
+void dma_fence_enable_sw_signaling(struct dma_fence *fence)
+{
+	unsigned long flags;
+
+	if (!test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+			      &fence->flags) &&
+	    !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+		trace_dma_fence_enable_signal(fence);
+
+		spin_lock_irqsave(fence->lock, flags);
+
+		if (!fence->ops->enable_signaling(fence))
+			dma_fence_signal_locked(fence);
+
+		spin_unlock_irqrestore(fence->lock, flags);
+	}
+}
+EXPORT_SYMBOL(dma_fence_enable_sw_signaling);
+
+/**
+ * dma_fence_add_callback - add a callback to be called when the fence
+ * is signaled
+ * @fence:	[in]	the fence to wait on
+ * @cb:		[in]	the callback to register
+ * @func:	[in]	the function to call
+ *
+ * cb will be initialized by dma_fence_add_callback, no initialization
+ * by the caller is required. Any number of callbacks can be registered
+ * to a fence, but a callback can only be registered to one fence at a time.
+ *
+ * Note that the callback can be called from an atomic context.  If
+ * fence is already signaled, this function will return -ENOENT (and
+ * *not* call the callback)
+ *
+ * Add a software callback to the fence. Same restrictions apply to
+ * refcount as it does to dma_fence_wait, however the caller doesn't need to
+ * keep a refcount to fence afterwards: when software access is enabled,
+ * the creator of the fence is required to keep the fence alive until
+ * after it signals with dma_fence_signal. The callback itself can be called
+ * from irq context.
+ *
+ */
+int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb,
+			   dma_fence_func_t func)
+{
+	unsigned long flags;
+	int ret = 0;
+	bool was_set;
+
+	if (WARN_ON(!fence || !func))
+		return -EINVAL;
+
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+		INIT_LIST_HEAD(&cb->node);
+		return -ENOENT;
+	}
+
+	spin_lock_irqsave(fence->lock, flags);
+
+	was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+				   &fence->flags);
+
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		ret = -ENOENT;
+	else if (!was_set) {
+		trace_dma_fence_enable_signal(fence);
+
+		if (!fence->ops->enable_signaling(fence)) {
+			dma_fence_signal_locked(fence);
+			ret = -ENOENT;
+		}
+	}
+
+	if (!ret) {
+		cb->func = func;
+		list_add_tail(&cb->node, &fence->cb_list);
+	} else
+		INIT_LIST_HEAD(&cb->node);
+	spin_unlock_irqrestore(fence->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(dma_fence_add_callback);
+
+/**
+ * dma_fence_remove_callback - remove a callback from the signaling list
+ * @fence:	[in]	the fence to wait on
+ * @cb:		[in]	the callback to remove
+ *
+ * Remove a previously queued callback from the fence. This function returns
+ * true if the callback is successfully removed, or false if the fence has
+ * already been signaled.
+ *
+ * *WARNING*:
+ * Cancelling a callback should only be done if you really know what you're
+ * doing, since deadlocks and race conditions could occur all too easily. For
+ * this reason, it should only ever be done on hardware lockup recovery,
+ * with a reference held to the fence.
+ */
+bool
+dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *cb)
+{
+	unsigned long flags;
+	bool ret;
+
+	spin_lock_irqsave(fence->lock, flags);
+
+	ret = !list_empty(&cb->node);
+	if (ret)
+		list_del_init(&cb->node);
+
+	spin_unlock_irqrestore(fence->lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(dma_fence_remove_callback);
+
+struct default_wait_cb {
+	struct dma_fence_cb base;
+	struct task_struct *task;
+};
+
+static void
+dma_fence_default_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
+{
+	struct default_wait_cb *wait =
+		container_of(cb, struct default_wait_cb, base);
+
+	wake_up_state(wait->task, TASK_NORMAL);
+}
+
+/**
+ * dma_fence_default_wait - default sleep until the fence gets signaled
+ * or until timeout elapses
+ * @fence:	[in]	the fence to wait on
+ * @intr:	[in]	if true, do an interruptible wait
+ * @timeout:	[in]	timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
+ *
+ * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
+ * remaining timeout in jiffies on success. If timeout is zero the value one is
+ * returned if the fence is already signaled for consistency with other
+ * functions taking a jiffies timeout.
+ */
+signed long
+dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout)
+{
+	struct default_wait_cb cb;
+	unsigned long flags;
+	signed long ret = timeout ? timeout : 1;
+	bool was_set;
+
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		return ret;
+
+	spin_lock_irqsave(fence->lock, flags);
+
+	if (intr && signal_pending(current)) {
+		ret = -ERESTARTSYS;
+		goto out;
+	}
+
+	was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+				   &fence->flags);
+
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		goto out;
+
+	if (!was_set) {
+		trace_dma_fence_enable_signal(fence);
+
+		if (!fence->ops->enable_signaling(fence)) {
+			dma_fence_signal_locked(fence);
+			goto out;
+		}
+	}
+
+	cb.base.func = dma_fence_default_wait_cb;
+	cb.task = current;
+	list_add(&cb.base.node, &fence->cb_list);
+
+	while (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) {
+		if (intr)
+			__set_current_state(TASK_INTERRUPTIBLE);
+		else
+			__set_current_state(TASK_UNINTERRUPTIBLE);
+		spin_unlock_irqrestore(fence->lock, flags);
+
+		ret = schedule_timeout(ret);
+
+		spin_lock_irqsave(fence->lock, flags);
+		if (ret > 0 && intr && signal_pending(current))
+			ret = -ERESTARTSYS;
+	}
+
+	if (!list_empty(&cb.base.node))
+		list_del(&cb.base.node);
+	__set_current_state(TASK_RUNNING);
+
+out:
+	spin_unlock_irqrestore(fence->lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(dma_fence_default_wait);
+
+static bool
+dma_fence_test_signaled_any(struct dma_fence **fences, uint32_t count,
+			    uint32_t *idx)
+{
+	int i;
+
+	for (i = 0; i < count; ++i) {
+		struct dma_fence *fence = fences[i];
+		if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
+			if (idx)
+				*idx = i;
+			return true;
+		}
+	}
+	return false;
+}
+
+/**
+ * dma_fence_wait_any_timeout - sleep until any fence gets signaled
+ * or until timeout elapses
+ * @fences:	[in]	array of fences to wait on
+ * @count:	[in]	number of fences to wait on
+ * @intr:	[in]	if true, do an interruptible wait
+ * @timeout:	[in]	timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
+ * @idx:       [out]	the first signaled fence index, meaningful only on
+ *			positive return
+ *
+ * Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if
+ * interrupted, 0 if the wait timed out, or the remaining timeout in jiffies
+ * on success.
+ *
+ * Synchronous waits for the first fence in the array to be signaled. The
+ * caller needs to hold a reference to all fences in the array, otherwise a
+ * fence might be freed before return, resulting in undefined behavior.
+ */
+signed long
+dma_fence_wait_any_timeout(struct dma_fence **fences, uint32_t count,
+			   bool intr, signed long timeout, uint32_t *idx)
+{
+	struct default_wait_cb *cb;
+	signed long ret = timeout;
+	unsigned i;
+
+	if (WARN_ON(!fences || !count || timeout < 0))
+		return -EINVAL;
+
+	if (timeout == 0) {
+		for (i = 0; i < count; ++i)
+			if (dma_fence_is_signaled(fences[i])) {
+				if (idx)
+					*idx = i;
+				return 1;
+			}
+
+		return 0;
+	}
+
+	cb = kcalloc(count, sizeof(struct default_wait_cb), GFP_KERNEL);
+	if (cb == NULL) {
+		ret = -ENOMEM;
+		goto err_free_cb;
+	}
+
+	for (i = 0; i < count; ++i) {
+		struct dma_fence *fence = fences[i];
+
+		if (fence->ops->wait != dma_fence_default_wait) {
+			ret = -EINVAL;
+			goto fence_rm_cb;
+		}
+
+		cb[i].task = current;
+		if (dma_fence_add_callback(fence, &cb[i].base,
+					   dma_fence_default_wait_cb)) {
+			/* This fence is already signaled */
+			if (idx)
+				*idx = i;
+			goto fence_rm_cb;
+		}
+	}
+
+	while (ret > 0) {
+		if (intr)
+			set_current_state(TASK_INTERRUPTIBLE);
+		else
+			set_current_state(TASK_UNINTERRUPTIBLE);
+
+		if (dma_fence_test_signaled_any(fences, count, idx))
+			break;
+
+		ret = schedule_timeout(ret);
+
+		if (ret > 0 && intr && signal_pending(current))
+			ret = -ERESTARTSYS;
+	}
+
+	__set_current_state(TASK_RUNNING);
+
+fence_rm_cb:
+	while (i-- > 0)
+		dma_fence_remove_callback(fences[i], &cb[i].base);
+
+err_free_cb:
+	kfree(cb);
+
+	return ret;
+}
+EXPORT_SYMBOL(dma_fence_wait_any_timeout);
+
+/**
+ * dma_fence_init - Initialize a custom fence.
+ * @fence:	[in]	the fence to initialize
+ * @ops:	[in]	the dma_fence_ops for operations on this fence
+ * @lock:	[in]	the irqsafe spinlock to use for locking this fence
+ * @context:	[in]	the execution context this fence is run on
+ * @seqno:	[in]	a linear increasing sequence number for this context
+ *
+ * Initializes an allocated fence, the caller doesn't have to keep its
+ * refcount after committing with this fence, but it will need to hold a
+ * refcount again if dma_fence_ops.enable_signaling gets called. This can
+ * be used for other implementing other types of fence.
+ *
+ * context and seqno are used for easy comparison between fences, allowing
+ * to check which fence is later by simply using dma_fence_later.
+ */
+void
+dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops,
+	       spinlock_t *lock, u64 context, unsigned seqno)
+{
+	BUG_ON(!lock);
+	BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
+	       !ops->get_driver_name || !ops->get_timeline_name);
+
+	kref_init(&fence->refcount);
+	fence->ops = ops;
+	INIT_LIST_HEAD(&fence->cb_list);
+	fence->lock = lock;
+	fence->context = context;
+	fence->seqno = seqno;
+	fence->flags = 0UL;
+
+	trace_dma_fence_init(fence);
+}
+EXPORT_SYMBOL(dma_fence_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/fence-array.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/fence-array.c
--- linux-libre-4.9-gnu/drivers/dma-buf/fence-array.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/fence-array.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,145 +0,0 @@
-/*
- * fence-array: aggregate fences to be waited together
- *
- * Copyright (C) 2016 Collabora Ltd
- * Copyright (C) 2016 Advanced Micro Devices, Inc.
- * Authors:
- *	Gustavo Padovan <gustavo@padovan.org>
- *	Christian König <christian.koenig@amd.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/export.h>
-#include <linux/slab.h>
-#include <linux/fence-array.h>
-
-static void fence_array_cb_func(struct fence *f, struct fence_cb *cb);
-
-static const char *fence_array_get_driver_name(struct fence *fence)
-{
-	return "fence_array";
-}
-
-static const char *fence_array_get_timeline_name(struct fence *fence)
-{
-	return "unbound";
-}
-
-static void fence_array_cb_func(struct fence *f, struct fence_cb *cb)
-{
-	struct fence_array_cb *array_cb =
-		container_of(cb, struct fence_array_cb, cb);
-	struct fence_array *array = array_cb->array;
-
-	if (atomic_dec_and_test(&array->num_pending))
-		fence_signal(&array->base);
-	fence_put(&array->base);
-}
-
-static bool fence_array_enable_signaling(struct fence *fence)
-{
-	struct fence_array *array = to_fence_array(fence);
-	struct fence_array_cb *cb = (void *)(&array[1]);
-	unsigned i;
-
-	for (i = 0; i < array->num_fences; ++i) {
-		cb[i].array = array;
-		/*
-		 * As we may report that the fence is signaled before all
-		 * callbacks are complete, we need to take an additional
-		 * reference count on the array so that we do not free it too
-		 * early. The core fence handling will only hold the reference
-		 * until we signal the array as complete (but that is now
-		 * insufficient).
-		 */
-		fence_get(&array->base);
-		if (fence_add_callback(array->fences[i], &cb[i].cb,
-				       fence_array_cb_func)) {
-			fence_put(&array->base);
-			if (atomic_dec_and_test(&array->num_pending))
-				return false;
-		}
-	}
-
-	return true;
-}
-
-static bool fence_array_signaled(struct fence *fence)
-{
-	struct fence_array *array = to_fence_array(fence);
-
-	return atomic_read(&array->num_pending) <= 0;
-}
-
-static void fence_array_release(struct fence *fence)
-{
-	struct fence_array *array = to_fence_array(fence);
-	unsigned i;
-
-	for (i = 0; i < array->num_fences; ++i)
-		fence_put(array->fences[i]);
-
-	kfree(array->fences);
-	fence_free(fence);
-}
-
-const struct fence_ops fence_array_ops = {
-	.get_driver_name = fence_array_get_driver_name,
-	.get_timeline_name = fence_array_get_timeline_name,
-	.enable_signaling = fence_array_enable_signaling,
-	.signaled = fence_array_signaled,
-	.wait = fence_default_wait,
-	.release = fence_array_release,
-};
-EXPORT_SYMBOL(fence_array_ops);
-
-/**
- * fence_array_create - Create a custom fence array
- * @num_fences:		[in]	number of fences to add in the array
- * @fences:		[in]	array containing the fences
- * @context:		[in]	fence context to use
- * @seqno:		[in]	sequence number to use
- * @signal_on_any:	[in]	signal on any fence in the array
- *
- * Allocate a fence_array object and initialize the base fence with fence_init().
- * In case of error it returns NULL.
- *
- * The caller should allocate the fences array with num_fences size
- * and fill it with the fences it wants to add to the object. Ownership of this
- * array is taken and fence_put() is used on each fence on release.
- *
- * If @signal_on_any is true the fence array signals if any fence in the array
- * signals, otherwise it signals when all fences in the array signal.
- */
-struct fence_array *fence_array_create(int num_fences, struct fence **fences,
-				       u64 context, unsigned seqno,
-				       bool signal_on_any)
-{
-	struct fence_array *array;
-	size_t size = sizeof(*array);
-
-	/* Allocate the callback structures behind the array. */
-	size += num_fences * sizeof(struct fence_array_cb);
-	array = kzalloc(size, GFP_KERNEL);
-	if (!array)
-		return NULL;
-
-	spin_lock_init(&array->lock);
-	fence_init(&array->base, &fence_array_ops, &array->lock,
-		   context, seqno);
-
-	array->num_fences = num_fences;
-	atomic_set(&array->num_pending, signal_on_any ? 1 : num_fences);
-	array->fences = fences;
-
-	return array;
-}
-EXPORT_SYMBOL(fence_array_create);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/fence.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/fence.c
--- linux-libre-4.9-gnu/drivers/dma-buf/fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/fence.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,532 +0,0 @@
-/*
- * Fence mechanism for dma-buf and to allow for asynchronous dma access
- *
- * Copyright (C) 2012 Canonical Ltd
- * Copyright (C) 2012 Texas Instruments
- *
- * Authors:
- * Rob Clark <robdclark@gmail.com>
- * Maarten Lankhorst <maarten.lankhorst@canonical.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- */
-
-#include <linux/slab.h>
-#include <linux/export.h>
-#include <linux/atomic.h>
-#include <linux/fence.h>
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/fence.h>
-
-EXPORT_TRACEPOINT_SYMBOL(fence_annotate_wait_on);
-EXPORT_TRACEPOINT_SYMBOL(fence_emit);
-
-/*
- * fence context counter: each execution context should have its own
- * fence context, this allows checking if fences belong to the same
- * context or not. One device can have multiple separate contexts,
- * and they're used if some engine can run independently of another.
- */
-static atomic64_t fence_context_counter = ATOMIC64_INIT(0);
-
-/**
- * fence_context_alloc - allocate an array of fence contexts
- * @num:	[in]	amount of contexts to allocate
- *
- * This function will return the first index of the number of fences allocated.
- * The fence context is used for setting fence->context to a unique number.
- */
-u64 fence_context_alloc(unsigned num)
-{
-	BUG_ON(!num);
-	return atomic64_add_return(num, &fence_context_counter) - num;
-}
-EXPORT_SYMBOL(fence_context_alloc);
-
-/**
- * fence_signal_locked - signal completion of a fence
- * @fence: the fence to signal
- *
- * Signal completion for software callbacks on a fence, this will unblock
- * fence_wait() calls and run all the callbacks added with
- * fence_add_callback(). Can be called multiple times, but since a fence
- * can only go from unsignaled to signaled state, it will only be effective
- * the first time.
- *
- * Unlike fence_signal, this function must be called with fence->lock held.
- */
-int fence_signal_locked(struct fence *fence)
-{
-	struct fence_cb *cur, *tmp;
-	int ret = 0;
-
-	if (WARN_ON(!fence))
-		return -EINVAL;
-
-	if (!ktime_to_ns(fence->timestamp)) {
-		fence->timestamp = ktime_get();
-		smp_mb__before_atomic();
-	}
-
-	if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
-		ret = -EINVAL;
-
-		/*
-		 * we might have raced with the unlocked fence_signal,
-		 * still run through all callbacks
-		 */
-	} else
-		trace_fence_signaled(fence);
-
-	list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
-		list_del_init(&cur->node);
-		cur->func(fence, cur);
-	}
-	return ret;
-}
-EXPORT_SYMBOL(fence_signal_locked);
-
-/**
- * fence_signal - signal completion of a fence
- * @fence: the fence to signal
- *
- * Signal completion for software callbacks on a fence, this will unblock
- * fence_wait() calls and run all the callbacks added with
- * fence_add_callback(). Can be called multiple times, but since a fence
- * can only go from unsignaled to signaled state, it will only be effective
- * the first time.
- */
-int fence_signal(struct fence *fence)
-{
-	unsigned long flags;
-
-	if (!fence)
-		return -EINVAL;
-
-	if (!ktime_to_ns(fence->timestamp)) {
-		fence->timestamp = ktime_get();
-		smp_mb__before_atomic();
-	}
-
-	if (test_and_set_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-		return -EINVAL;
-
-	trace_fence_signaled(fence);
-
-	if (test_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags)) {
-		struct fence_cb *cur, *tmp;
-
-		spin_lock_irqsave(fence->lock, flags);
-		list_for_each_entry_safe(cur, tmp, &fence->cb_list, node) {
-			list_del_init(&cur->node);
-			cur->func(fence, cur);
-		}
-		spin_unlock_irqrestore(fence->lock, flags);
-	}
-	return 0;
-}
-EXPORT_SYMBOL(fence_signal);
-
-/**
- * fence_wait_timeout - sleep until the fence gets signaled
- * or until timeout elapses
- * @fence:	[in]	the fence to wait on
- * @intr:	[in]	if true, do an interruptible wait
- * @timeout:	[in]	timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
- *
- * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
- * remaining timeout in jiffies on success. Other error values may be
- * returned on custom implementations.
- *
- * Performs a synchronous wait on this fence. It is assumed the caller
- * directly or indirectly (buf-mgr between reservation and committing)
- * holds a reference to the fence, otherwise the fence might be
- * freed before return, resulting in undefined behavior.
- */
-signed long
-fence_wait_timeout(struct fence *fence, bool intr, signed long timeout)
-{
-	signed long ret;
-
-	if (WARN_ON(timeout < 0))
-		return -EINVAL;
-
-	if (timeout == 0)
-		return fence_is_signaled(fence);
-
-	trace_fence_wait_start(fence);
-	ret = fence->ops->wait(fence, intr, timeout);
-	trace_fence_wait_end(fence);
-	return ret;
-}
-EXPORT_SYMBOL(fence_wait_timeout);
-
-void fence_release(struct kref *kref)
-{
-	struct fence *fence =
-			container_of(kref, struct fence, refcount);
-
-	trace_fence_destroy(fence);
-
-	BUG_ON(!list_empty(&fence->cb_list));
-
-	if (fence->ops->release)
-		fence->ops->release(fence);
-	else
-		fence_free(fence);
-}
-EXPORT_SYMBOL(fence_release);
-
-void fence_free(struct fence *fence)
-{
-	kfree_rcu(fence, rcu);
-}
-EXPORT_SYMBOL(fence_free);
-
-/**
- * fence_enable_sw_signaling - enable signaling on fence
- * @fence:	[in]	the fence to enable
- *
- * this will request for sw signaling to be enabled, to make the fence
- * complete as soon as possible
- */
-void fence_enable_sw_signaling(struct fence *fence)
-{
-	unsigned long flags;
-
-	if (!test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags) &&
-	    !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
-		trace_fence_enable_signal(fence);
-
-		spin_lock_irqsave(fence->lock, flags);
-
-		if (!fence->ops->enable_signaling(fence))
-			fence_signal_locked(fence);
-
-		spin_unlock_irqrestore(fence->lock, flags);
-	}
-}
-EXPORT_SYMBOL(fence_enable_sw_signaling);
-
-/**
- * fence_add_callback - add a callback to be called when the fence
- * is signaled
- * @fence:	[in]	the fence to wait on
- * @cb:		[in]	the callback to register
- * @func:	[in]	the function to call
- *
- * cb will be initialized by fence_add_callback, no initialization
- * by the caller is required. Any number of callbacks can be registered
- * to a fence, but a callback can only be registered to one fence at a time.
- *
- * Note that the callback can be called from an atomic context.  If
- * fence is already signaled, this function will return -ENOENT (and
- * *not* call the callback)
- *
- * Add a software callback to the fence. Same restrictions apply to
- * refcount as it does to fence_wait, however the caller doesn't need to
- * keep a refcount to fence afterwards: when software access is enabled,
- * the creator of the fence is required to keep the fence alive until
- * after it signals with fence_signal. The callback itself can be called
- * from irq context.
- *
- */
-int fence_add_callback(struct fence *fence, struct fence_cb *cb,
-		       fence_func_t func)
-{
-	unsigned long flags;
-	int ret = 0;
-	bool was_set;
-
-	if (WARN_ON(!fence || !func))
-		return -EINVAL;
-
-	if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {
-		INIT_LIST_HEAD(&cb->node);
-		return -ENOENT;
-	}
-
-	spin_lock_irqsave(fence->lock, flags);
-
-	was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags);
-
-	if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-		ret = -ENOENT;
-	else if (!was_set) {
-		trace_fence_enable_signal(fence);
-
-		if (!fence->ops->enable_signaling(fence)) {
-			fence_signal_locked(fence);
-			ret = -ENOENT;
-		}
-	}
-
-	if (!ret) {
-		cb->func = func;
-		list_add_tail(&cb->node, &fence->cb_list);
-	} else
-		INIT_LIST_HEAD(&cb->node);
-	spin_unlock_irqrestore(fence->lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(fence_add_callback);
-
-/**
- * fence_remove_callback - remove a callback from the signaling list
- * @fence:	[in]	the fence to wait on
- * @cb:		[in]	the callback to remove
- *
- * Remove a previously queued callback from the fence. This function returns
- * true if the callback is successfully removed, or false if the fence has
- * already been signaled.
- *
- * *WARNING*:
- * Cancelling a callback should only be done if you really know what you're
- * doing, since deadlocks and race conditions could occur all too easily. For
- * this reason, it should only ever be done on hardware lockup recovery,
- * with a reference held to the fence.
- */
-bool
-fence_remove_callback(struct fence *fence, struct fence_cb *cb)
-{
-	unsigned long flags;
-	bool ret;
-
-	spin_lock_irqsave(fence->lock, flags);
-
-	ret = !list_empty(&cb->node);
-	if (ret)
-		list_del_init(&cb->node);
-
-	spin_unlock_irqrestore(fence->lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(fence_remove_callback);
-
-struct default_wait_cb {
-	struct fence_cb base;
-	struct task_struct *task;
-};
-
-static void
-fence_default_wait_cb(struct fence *fence, struct fence_cb *cb)
-{
-	struct default_wait_cb *wait =
-		container_of(cb, struct default_wait_cb, base);
-
-	wake_up_state(wait->task, TASK_NORMAL);
-}
-
-/**
- * fence_default_wait - default sleep until the fence gets signaled
- * or until timeout elapses
- * @fence:	[in]	the fence to wait on
- * @intr:	[in]	if true, do an interruptible wait
- * @timeout:	[in]	timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
- *
- * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or the
- * remaining timeout in jiffies on success.
- */
-signed long
-fence_default_wait(struct fence *fence, bool intr, signed long timeout)
-{
-	struct default_wait_cb cb;
-	unsigned long flags;
-	signed long ret = timeout;
-	bool was_set;
-
-	if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-		return timeout;
-
-	spin_lock_irqsave(fence->lock, flags);
-
-	if (intr && signal_pending(current)) {
-		ret = -ERESTARTSYS;
-		goto out;
-	}
-
-	was_set = test_and_set_bit(FENCE_FLAG_ENABLE_SIGNAL_BIT, &fence->flags);
-
-	if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-		goto out;
-
-	if (!was_set) {
-		trace_fence_enable_signal(fence);
-
-		if (!fence->ops->enable_signaling(fence)) {
-			fence_signal_locked(fence);
-			goto out;
-		}
-	}
-
-	cb.base.func = fence_default_wait_cb;
-	cb.task = current;
-	list_add(&cb.base.node, &fence->cb_list);
-
-	while (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) {
-		if (intr)
-			__set_current_state(TASK_INTERRUPTIBLE);
-		else
-			__set_current_state(TASK_UNINTERRUPTIBLE);
-		spin_unlock_irqrestore(fence->lock, flags);
-
-		ret = schedule_timeout(ret);
-
-		spin_lock_irqsave(fence->lock, flags);
-		if (ret > 0 && intr && signal_pending(current))
-			ret = -ERESTARTSYS;
-	}
-
-	if (!list_empty(&cb.base.node))
-		list_del(&cb.base.node);
-	__set_current_state(TASK_RUNNING);
-
-out:
-	spin_unlock_irqrestore(fence->lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(fence_default_wait);
-
-static bool
-fence_test_signaled_any(struct fence **fences, uint32_t count)
-{
-	int i;
-
-	for (i = 0; i < count; ++i) {
-		struct fence *fence = fences[i];
-		if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-			return true;
-	}
-	return false;
-}
-
-/**
- * fence_wait_any_timeout - sleep until any fence gets signaled
- * or until timeout elapses
- * @fences:	[in]	array of fences to wait on
- * @count:	[in]	number of fences to wait on
- * @intr:	[in]	if true, do an interruptible wait
- * @timeout:	[in]	timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT
- *
- * Returns -EINVAL on custom fence wait implementation, -ERESTARTSYS if
- * interrupted, 0 if the wait timed out, or the remaining timeout in jiffies
- * on success.
- *
- * Synchronous waits for the first fence in the array to be signaled. The
- * caller needs to hold a reference to all fences in the array, otherwise a
- * fence might be freed before return, resulting in undefined behavior.
- */
-signed long
-fence_wait_any_timeout(struct fence **fences, uint32_t count,
-		       bool intr, signed long timeout)
-{
-	struct default_wait_cb *cb;
-	signed long ret = timeout;
-	unsigned i;
-
-	if (WARN_ON(!fences || !count || timeout < 0))
-		return -EINVAL;
-
-	if (timeout == 0) {
-		for (i = 0; i < count; ++i)
-			if (fence_is_signaled(fences[i]))
-				return 1;
-
-		return 0;
-	}
-
-	cb = kcalloc(count, sizeof(struct default_wait_cb), GFP_KERNEL);
-	if (cb == NULL) {
-		ret = -ENOMEM;
-		goto err_free_cb;
-	}
-
-	for (i = 0; i < count; ++i) {
-		struct fence *fence = fences[i];
-
-		if (fence->ops->wait != fence_default_wait) {
-			ret = -EINVAL;
-			goto fence_rm_cb;
-		}
-
-		cb[i].task = current;
-		if (fence_add_callback(fence, &cb[i].base,
-				       fence_default_wait_cb)) {
-			/* This fence is already signaled */
-			goto fence_rm_cb;
-		}
-	}
-
-	while (ret > 0) {
-		if (intr)
-			set_current_state(TASK_INTERRUPTIBLE);
-		else
-			set_current_state(TASK_UNINTERRUPTIBLE);
-
-		if (fence_test_signaled_any(fences, count))
-			break;
-
-		ret = schedule_timeout(ret);
-
-		if (ret > 0 && intr && signal_pending(current))
-			ret = -ERESTARTSYS;
-	}
-
-	__set_current_state(TASK_RUNNING);
-
-fence_rm_cb:
-	while (i-- > 0)
-		fence_remove_callback(fences[i], &cb[i].base);
-
-err_free_cb:
-	kfree(cb);
-
-	return ret;
-}
-EXPORT_SYMBOL(fence_wait_any_timeout);
-
-/**
- * fence_init - Initialize a custom fence.
- * @fence:	[in]	the fence to initialize
- * @ops:	[in]	the fence_ops for operations on this fence
- * @lock:	[in]	the irqsafe spinlock to use for locking this fence
- * @context:	[in]	the execution context this fence is run on
- * @seqno:	[in]	a linear increasing sequence number for this context
- *
- * Initializes an allocated fence, the caller doesn't have to keep its
- * refcount after committing with this fence, but it will need to hold a
- * refcount again if fence_ops.enable_signaling gets called. This can
- * be used for other implementing other types of fence.
- *
- * context and seqno are used for easy comparison between fences, allowing
- * to check which fence is later by simply using fence_later.
- */
-void
-fence_init(struct fence *fence, const struct fence_ops *ops,
-	     spinlock_t *lock, u64 context, unsigned seqno)
-{
-	BUG_ON(!lock);
-	BUG_ON(!ops || !ops->wait || !ops->enable_signaling ||
-	       !ops->get_driver_name || !ops->get_timeline_name);
-
-	kref_init(&fence->refcount);
-	fence->ops = ops;
-	INIT_LIST_HEAD(&fence->cb_list);
-	fence->lock = lock;
-	fence->context = context;
-	fence->seqno = seqno;
-	fence->flags = 0UL;
-
-	trace_fence_init(fence);
-}
-EXPORT_SYMBOL(fence_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/Kconfig linux-libre-4.10-rc8-gnu/drivers/dma-buf/Kconfig
--- linux-libre-4.9-gnu/drivers/dma-buf/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@ config SYNC_FILE
 	select DMA_SHARED_BUFFER
 	---help---
 	  The Sync File Framework adds explicit syncronization via
-	  userspace. It enables send/receive 'struct fence' objects to/from
+	  userspace. It enables send/receive 'struct dma_fence' objects to/from
 	  userspace via Sync File fds for synchronization between drivers via
 	  userspace components. It has been ported from Android.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/Makefile linux-libre-4.10-rc8-gnu/drivers/dma-buf/Makefile
--- linux-libre-4.9-gnu/drivers/dma-buf/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,3 @@
-obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o
+obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o
 obj-$(CONFIG_SYNC_FILE)		+= sync_file.o
 obj-$(CONFIG_SW_SYNC)		+= sw_sync.o sync_debug.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/reservation.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/reservation.c
--- linux-libre-4.9-gnu/drivers/dma-buf/reservation.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/reservation.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,17 +102,17 @@ EXPORT_SYMBOL(reservation_object_reserve
 static void
 reservation_object_add_shared_inplace(struct reservation_object *obj,
 				      struct reservation_object_list *fobj,
-				      struct fence *fence)
+				      struct dma_fence *fence)
 {
 	u32 i;
 
-	fence_get(fence);
+	dma_fence_get(fence);
 
 	preempt_disable();
 	write_seqcount_begin(&obj->seq);
 
 	for (i = 0; i < fobj->shared_count; ++i) {
-		struct fence *old_fence;
+		struct dma_fence *old_fence;
 
 		old_fence = rcu_dereference_protected(fobj->shared[i],
 						reservation_object_held(obj));
@@ -123,7 +123,7 @@ reservation_object_add_shared_inplace(st
 			write_seqcount_end(&obj->seq);
 			preempt_enable();
 
-			fence_put(old_fence);
+			dma_fence_put(old_fence);
 			return;
 		}
 	}
@@ -143,12 +143,12 @@ static void
 reservation_object_add_shared_replace(struct reservation_object *obj,
 				      struct reservation_object_list *old,
 				      struct reservation_object_list *fobj,
-				      struct fence *fence)
+				      struct dma_fence *fence)
 {
 	unsigned i;
-	struct fence *old_fence = NULL;
+	struct dma_fence *old_fence = NULL;
 
-	fence_get(fence);
+	dma_fence_get(fence);
 
 	if (!old) {
 		RCU_INIT_POINTER(fobj->shared[0], fence);
@@ -165,7 +165,7 @@ reservation_object_add_shared_replace(st
 	fobj->shared_count = old->shared_count;
 
 	for (i = 0; i < old->shared_count; ++i) {
-		struct fence *check;
+		struct dma_fence *check;
 
 		check = rcu_dereference_protected(old->shared[i],
 						reservation_object_held(obj));
@@ -196,7 +196,7 @@ done:
 		kfree_rcu(old, rcu);
 
 	if (old_fence)
-		fence_put(old_fence);
+		dma_fence_put(old_fence);
 }
 
 /**
@@ -208,7 +208,7 @@ done:
  * reservation_object_reserve_shared() has been called.
  */
 void reservation_object_add_shared_fence(struct reservation_object *obj,
-					 struct fence *fence)
+					 struct dma_fence *fence)
 {
 	struct reservation_object_list *old, *fobj = obj->staged;
 
@@ -231,9 +231,9 @@ EXPORT_SYMBOL(reservation_object_add_sha
  * Add a fence to the exclusive slot.  The obj->lock must be held.
  */
 void reservation_object_add_excl_fence(struct reservation_object *obj,
-				       struct fence *fence)
+				       struct dma_fence *fence)
 {
-	struct fence *old_fence = reservation_object_get_excl(obj);
+	struct dma_fence *old_fence = reservation_object_get_excl(obj);
 	struct reservation_object_list *old;
 	u32 i = 0;
 
@@ -242,7 +242,7 @@ void reservation_object_add_excl_fence(s
 		i = old->shared_count;
 
 	if (fence)
-		fence_get(fence);
+		dma_fence_get(fence);
 
 	preempt_disable();
 	write_seqcount_begin(&obj->seq);
@@ -255,11 +255,11 @@ void reservation_object_add_excl_fence(s
 
 	/* inplace update, no shared fences */
 	while (i--)
-		fence_put(rcu_dereference_protected(old->shared[i],
+		dma_fence_put(rcu_dereference_protected(old->shared[i],
 						reservation_object_held(obj)));
 
 	if (old_fence)
-		fence_put(old_fence);
+		dma_fence_put(old_fence);
 }
 EXPORT_SYMBOL(reservation_object_add_excl_fence);
 
@@ -276,26 +276,32 @@ EXPORT_SYMBOL(reservation_object_add_exc
  * Zero or -errno
  */
 int reservation_object_get_fences_rcu(struct reservation_object *obj,
-				      struct fence **pfence_excl,
+				      struct dma_fence **pfence_excl,
 				      unsigned *pshared_count,
-				      struct fence ***pshared)
+				      struct dma_fence ***pshared)
 {
-	unsigned shared_count = 0;
-	unsigned retry = 1;
-	struct fence **shared = NULL, *fence_excl = NULL;
-	int ret = 0;
+	struct dma_fence **shared = NULL;
+	struct dma_fence *fence_excl;
+	unsigned int shared_count;
+	int ret = 1;
 
-	while (retry) {
+	do {
 		struct reservation_object_list *fobj;
 		unsigned seq;
+		unsigned int i;
 
-		seq = read_seqcount_begin(&obj->seq);
+		shared_count = i = 0;
 
 		rcu_read_lock();
+		seq = read_seqcount_begin(&obj->seq);
+
+		fence_excl = rcu_dereference(obj->fence_excl);
+		if (fence_excl && !dma_fence_get_rcu(fence_excl))
+			goto unlock;
 
 		fobj = rcu_dereference(obj->fence);
 		if (fobj) {
-			struct fence **nshared;
+			struct dma_fence **nshared;
 			size_t sz = sizeof(*shared) * fobj->shared_max;
 
 			nshared = krealloc(shared, sz,
@@ -309,52 +315,37 @@ int reservation_object_get_fences_rcu(st
 				}
 
 				ret = -ENOMEM;
-				shared_count = 0;
 				break;
 			}
 			shared = nshared;
-			memcpy(shared, fobj->shared, sz);
 			shared_count = fobj->shared_count;
-		} else
-			shared_count = 0;
-		fence_excl = rcu_dereference(obj->fence_excl);
-
-		retry = read_seqcount_retry(&obj->seq, seq);
-		if (retry)
-			goto unlock;
-
-		if (!fence_excl || fence_get_rcu(fence_excl)) {
-			unsigned i;
 
 			for (i = 0; i < shared_count; ++i) {
-				if (fence_get_rcu(shared[i]))
-					continue;
-
-				/* uh oh, refcount failed, abort and retry */
-				while (i--)
-					fence_put(shared[i]);
-
-				if (fence_excl) {
-					fence_put(fence_excl);
-					fence_excl = NULL;
-				}
-
-				retry = 1;
-				break;
+				shared[i] = rcu_dereference(fobj->shared[i]);
+				if (!dma_fence_get_rcu(shared[i]))
+					break;
 			}
-		} else
-			retry = 1;
+		}
+
+		if (i != shared_count || read_seqcount_retry(&obj->seq, seq)) {
+			while (i--)
+				dma_fence_put(shared[i]);
+			dma_fence_put(fence_excl);
+			goto unlock;
+		}
 
+		ret = 0;
 unlock:
 		rcu_read_unlock();
-	}
-	*pshared_count = shared_count;
-	if (shared_count)
-		*pshared = shared;
-	else {
-		*pshared = NULL;
+	} while (ret);
+
+	if (!shared_count) {
 		kfree(shared);
+		shared = NULL;
 	}
+
+	*pshared_count = shared_count;
+	*pshared = shared;
 	*pfence_excl = fence_excl;
 
 	return ret;
@@ -377,12 +368,9 @@ long reservation_object_wait_timeout_rcu
 					 bool wait_all, bool intr,
 					 unsigned long timeout)
 {
-	struct fence *fence;
+	struct dma_fence *fence;
 	unsigned seq, shared_count, i = 0;
-	long ret = timeout;
-
-	if (!timeout)
-		return reservation_object_test_signaled_rcu(obj, wait_all);
+	long ret = timeout ? timeout : 1;
 
 retry:
 	fence = NULL;
@@ -397,20 +385,18 @@ retry:
 		if (fobj)
 			shared_count = fobj->shared_count;
 
-		if (read_seqcount_retry(&obj->seq, seq))
-			goto unlock_retry;
-
 		for (i = 0; i < shared_count; ++i) {
-			struct fence *lfence = rcu_dereference(fobj->shared[i]);
+			struct dma_fence *lfence = rcu_dereference(fobj->shared[i]);
 
-			if (test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags))
+			if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+				     &lfence->flags))
 				continue;
 
-			if (!fence_get_rcu(lfence))
+			if (!dma_fence_get_rcu(lfence))
 				goto unlock_retry;
 
-			if (fence_is_signaled(lfence)) {
-				fence_put(lfence);
+			if (dma_fence_is_signaled(lfence)) {
+				dma_fence_put(lfence);
 				continue;
 			}
 
@@ -420,18 +406,16 @@ retry:
 	}
 
 	if (!shared_count) {
-		struct fence *fence_excl = rcu_dereference(obj->fence_excl);
-
-		if (read_seqcount_retry(&obj->seq, seq))
-			goto unlock_retry;
+		struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl);
 
 		if (fence_excl &&
-		    !test_bit(FENCE_FLAG_SIGNALED_BIT, &fence_excl->flags)) {
-			if (!fence_get_rcu(fence_excl))
+		    !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+			      &fence_excl->flags)) {
+			if (!dma_fence_get_rcu(fence_excl))
 				goto unlock_retry;
 
-			if (fence_is_signaled(fence_excl))
-				fence_put(fence_excl);
+			if (dma_fence_is_signaled(fence_excl))
+				dma_fence_put(fence_excl);
 			else
 				fence = fence_excl;
 		}
@@ -439,8 +423,13 @@ retry:
 
 	rcu_read_unlock();
 	if (fence) {
-		ret = fence_wait_timeout(fence, intr, ret);
-		fence_put(fence);
+		if (read_seqcount_retry(&obj->seq, seq)) {
+			dma_fence_put(fence);
+			goto retry;
+		}
+
+		ret = dma_fence_wait_timeout(fence, intr, ret);
+		dma_fence_put(fence);
 		if (ret > 0 && wait_all && (i + 1 < shared_count))
 			goto retry;
 	}
@@ -454,18 +443,18 @@ EXPORT_SYMBOL_GPL(reservation_object_wai
 
 
 static inline int
-reservation_object_test_signaled_single(struct fence *passed_fence)
+reservation_object_test_signaled_single(struct dma_fence *passed_fence)
 {
-	struct fence *fence, *lfence = passed_fence;
+	struct dma_fence *fence, *lfence = passed_fence;
 	int ret = 1;
 
-	if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) {
-		fence = fence_get_rcu(lfence);
+	if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) {
+		fence = dma_fence_get_rcu(lfence);
 		if (!fence)
 			return -1;
 
-		ret = !!fence_is_signaled(fence);
-		fence_put(fence);
+		ret = !!dma_fence_is_signaled(fence);
+		dma_fence_put(fence);
 	}
 	return ret;
 }
@@ -484,12 +473,13 @@ bool reservation_object_test_signaled_rc
 					  bool test_all)
 {
 	unsigned seq, shared_count;
-	int ret = true;
+	int ret;
 
+	rcu_read_lock();
 retry:
+	ret = true;
 	shared_count = 0;
 	seq = read_seqcount_begin(&obj->seq);
-	rcu_read_lock();
 
 	if (test_all) {
 		unsigned i;
@@ -500,46 +490,35 @@ retry:
 		if (fobj)
 			shared_count = fobj->shared_count;
 
-		if (read_seqcount_retry(&obj->seq, seq))
-			goto unlock_retry;
-
 		for (i = 0; i < shared_count; ++i) {
-			struct fence *fence = rcu_dereference(fobj->shared[i]);
+			struct dma_fence *fence = rcu_dereference(fobj->shared[i]);
 
 			ret = reservation_object_test_signaled_single(fence);
 			if (ret < 0)
-				goto unlock_retry;
+				goto retry;
 			else if (!ret)
 				break;
 		}
 
-		/*
-		 * There could be a read_seqcount_retry here, but nothing cares
-		 * about whether it's the old or newer fence pointers that are
-		 * signaled. That race could still have happened after checking
-		 * read_seqcount_retry. If you care, use ww_mutex_lock.
-		 */
+		if (read_seqcount_retry(&obj->seq, seq))
+			goto retry;
 	}
 
 	if (!shared_count) {
-		struct fence *fence_excl = rcu_dereference(obj->fence_excl);
-
-		if (read_seqcount_retry(&obj->seq, seq))
-			goto unlock_retry;
+		struct dma_fence *fence_excl = rcu_dereference(obj->fence_excl);
 
 		if (fence_excl) {
 			ret = reservation_object_test_signaled_single(
 								fence_excl);
 			if (ret < 0)
-				goto unlock_retry;
+				goto retry;
+
+			if (read_seqcount_retry(&obj->seq, seq))
+				goto retry;
 		}
 	}
 
 	rcu_read_unlock();
 	return ret;
-
-unlock_retry:
-	rcu_read_unlock();
-	goto retry;
 }
 EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/seqno-fence.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/seqno-fence.c
--- linux-libre-4.9-gnu/drivers/dma-buf/seqno-fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/seqno-fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,35 +21,35 @@
 #include <linux/export.h>
 #include <linux/seqno-fence.h>
 
-static const char *seqno_fence_get_driver_name(struct fence *fence)
+static const char *seqno_fence_get_driver_name(struct dma_fence *fence)
 {
 	struct seqno_fence *seqno_fence = to_seqno_fence(fence);
 
 	return seqno_fence->ops->get_driver_name(fence);
 }
 
-static const char *seqno_fence_get_timeline_name(struct fence *fence)
+static const char *seqno_fence_get_timeline_name(struct dma_fence *fence)
 {
 	struct seqno_fence *seqno_fence = to_seqno_fence(fence);
 
 	return seqno_fence->ops->get_timeline_name(fence);
 }
 
-static bool seqno_enable_signaling(struct fence *fence)
+static bool seqno_enable_signaling(struct dma_fence *fence)
 {
 	struct seqno_fence *seqno_fence = to_seqno_fence(fence);
 
 	return seqno_fence->ops->enable_signaling(fence);
 }
 
-static bool seqno_signaled(struct fence *fence)
+static bool seqno_signaled(struct dma_fence *fence)
 {
 	struct seqno_fence *seqno_fence = to_seqno_fence(fence);
 
 	return seqno_fence->ops->signaled && seqno_fence->ops->signaled(fence);
 }
 
-static void seqno_release(struct fence *fence)
+static void seqno_release(struct dma_fence *fence)
 {
 	struct seqno_fence *f = to_seqno_fence(fence);
 
@@ -57,18 +57,18 @@ static void seqno_release(struct fence *
 	if (f->ops->release)
 		f->ops->release(fence);
 	else
-		fence_free(&f->base);
+		dma_fence_free(&f->base);
 }
 
-static signed long seqno_wait(struct fence *fence, bool intr,
-				signed long timeout)
+static signed long seqno_wait(struct dma_fence *fence, bool intr,
+			      signed long timeout)
 {
 	struct seqno_fence *f = to_seqno_fence(fence);
 
 	return f->ops->wait(fence, intr, timeout);
 }
 
-const struct fence_ops seqno_fence_ops = {
+const struct dma_fence_ops seqno_fence_ops = {
 	.get_driver_name = seqno_fence_get_driver_name,
 	.get_timeline_name = seqno_fence_get_timeline_name,
 	.enable_signaling = seqno_enable_signaling,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/sw_sync.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/sw_sync.c
--- linux-libre-4.9-gnu/drivers/dma-buf/sw_sync.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/sw_sync.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,9 +68,9 @@ struct sw_sync_create_fence_data {
 
 #define SW_SYNC_IOC_INC			_IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
 
-static const struct fence_ops timeline_fence_ops;
+static const struct dma_fence_ops timeline_fence_ops;
 
-static inline struct sync_pt *fence_to_sync_pt(struct fence *fence)
+static inline struct sync_pt *dma_fence_to_sync_pt(struct dma_fence *fence)
 {
 	if (fence->ops != &timeline_fence_ops)
 		return NULL;
@@ -84,7 +84,7 @@ static inline struct sync_pt *fence_to_s
  * Creates a new sync_timeline. Returns the sync_timeline object or NULL in
  * case of error.
  */
-struct sync_timeline *sync_timeline_create(const char *name)
+static struct sync_timeline *sync_timeline_create(const char *name)
 {
 	struct sync_timeline *obj;
 
@@ -93,7 +93,7 @@ struct sync_timeline *sync_timeline_crea
 		return NULL;
 
 	kref_init(&obj->kref);
-	obj->context = fence_context_alloc(1);
+	obj->context = dma_fence_context_alloc(1);
 	strlcpy(obj->name, name, sizeof(obj->name));
 
 	INIT_LIST_HEAD(&obj->child_list_head);
@@ -146,7 +146,7 @@ static void sync_timeline_signal(struct
 
 	list_for_each_entry_safe(pt, next, &obj->active_list_head,
 				 active_list) {
-		if (fence_is_signaled_locked(&pt->base))
+		if (dma_fence_is_signaled_locked(&pt->base))
 			list_del_init(&pt->active_list);
 	}
 
@@ -179,30 +179,30 @@ static struct sync_pt *sync_pt_create(st
 
 	spin_lock_irqsave(&obj->child_list_lock, flags);
 	sync_timeline_get(obj);
-	fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock,
-		   obj->context, value);
+	dma_fence_init(&pt->base, &timeline_fence_ops, &obj->child_list_lock,
+		       obj->context, value);
 	list_add_tail(&pt->child_list, &obj->child_list_head);
 	INIT_LIST_HEAD(&pt->active_list);
 	spin_unlock_irqrestore(&obj->child_list_lock, flags);
 	return pt;
 }
 
-static const char *timeline_fence_get_driver_name(struct fence *fence)
+static const char *timeline_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "sw_sync";
 }
 
-static const char *timeline_fence_get_timeline_name(struct fence *fence)
+static const char *timeline_fence_get_timeline_name(struct dma_fence *fence)
 {
-	struct sync_timeline *parent = fence_parent(fence);
+	struct sync_timeline *parent = dma_fence_parent(fence);
 
 	return parent->name;
 }
 
-static void timeline_fence_release(struct fence *fence)
+static void timeline_fence_release(struct dma_fence *fence)
 {
-	struct sync_pt *pt = fence_to_sync_pt(fence);
-	struct sync_timeline *parent = fence_parent(fence);
+	struct sync_pt *pt = dma_fence_to_sync_pt(fence);
+	struct sync_timeline *parent = dma_fence_parent(fence);
 	unsigned long flags;
 
 	spin_lock_irqsave(fence->lock, flags);
@@ -212,20 +212,20 @@ static void timeline_fence_release(struc
 	spin_unlock_irqrestore(fence->lock, flags);
 
 	sync_timeline_put(parent);
-	fence_free(fence);
+	dma_fence_free(fence);
 }
 
-static bool timeline_fence_signaled(struct fence *fence)
+static bool timeline_fence_signaled(struct dma_fence *fence)
 {
-	struct sync_timeline *parent = fence_parent(fence);
+	struct sync_timeline *parent = dma_fence_parent(fence);
 
 	return (fence->seqno > parent->value) ? false : true;
 }
 
-static bool timeline_fence_enable_signaling(struct fence *fence)
+static bool timeline_fence_enable_signaling(struct dma_fence *fence)
 {
-	struct sync_pt *pt = fence_to_sync_pt(fence);
-	struct sync_timeline *parent = fence_parent(fence);
+	struct sync_pt *pt = dma_fence_to_sync_pt(fence);
+	struct sync_timeline *parent = dma_fence_parent(fence);
 
 	if (timeline_fence_signaled(fence))
 		return false;
@@ -234,26 +234,26 @@ static bool timeline_fence_enable_signal
 	return true;
 }
 
-static void timeline_fence_value_str(struct fence *fence,
+static void timeline_fence_value_str(struct dma_fence *fence,
 				    char *str, int size)
 {
 	snprintf(str, size, "%d", fence->seqno);
 }
 
-static void timeline_fence_timeline_value_str(struct fence *fence,
+static void timeline_fence_timeline_value_str(struct dma_fence *fence,
 					     char *str, int size)
 {
-	struct sync_timeline *parent = fence_parent(fence);
+	struct sync_timeline *parent = dma_fence_parent(fence);
 
 	snprintf(str, size, "%d", parent->value);
 }
 
-static const struct fence_ops timeline_fence_ops = {
+static const struct dma_fence_ops timeline_fence_ops = {
 	.get_driver_name = timeline_fence_get_driver_name,
 	.get_timeline_name = timeline_fence_get_timeline_name,
 	.enable_signaling = timeline_fence_enable_signaling,
 	.signaled = timeline_fence_signaled,
-	.wait = fence_default_wait,
+	.wait = dma_fence_default_wait,
 	.release = timeline_fence_release,
 	.fence_value_str = timeline_fence_value_str,
 	.timeline_value_str = timeline_fence_timeline_value_str,
@@ -316,8 +316,8 @@ static long sw_sync_ioctl_create_fence(s
 	}
 
 	sync_file = sync_file_create(&pt->base);
+	dma_fence_put(&pt->base);
 	if (!sync_file) {
-		fence_put(&pt->base);
 		err = -ENOMEM;
 		goto err;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/sync_debug.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/sync_debug.c
--- linux-libre-4.9-gnu/drivers/dma-buf/sync_debug.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/sync_debug.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,12 +71,13 @@ static const char *sync_status_str(int s
 	return "error";
 }
 
-static void sync_print_fence(struct seq_file *s, struct fence *fence, bool show)
+static void sync_print_fence(struct seq_file *s,
+			     struct dma_fence *fence, bool show)
 {
 	int status = 1;
-	struct sync_timeline *parent = fence_parent(fence);
+	struct sync_timeline *parent = dma_fence_parent(fence);
 
-	if (fence_is_signaled_locked(fence))
+	if (dma_fence_is_signaled_locked(fence))
 		status = fence->status;
 
 	seq_printf(s, "  %s%sfence %s",
@@ -135,10 +136,10 @@ static void sync_print_sync_file(struct
 	int i;
 
 	seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name,
-		   sync_status_str(!fence_is_signaled(sync_file->fence)));
+		   sync_status_str(!dma_fence_is_signaled(sync_file->fence)));
 
-	if (fence_is_array(sync_file->fence)) {
-		struct fence_array *array = to_fence_array(sync_file->fence);
+	if (dma_fence_is_array(sync_file->fence)) {
+		struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
 
 		for (i = 0; i < array->num_fences; ++i)
 			sync_print_fence(s, array->fences[i], true);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/sync_debug.h linux-libre-4.10-rc8-gnu/drivers/dma-buf/sync_debug.h
--- linux-libre-4.9-gnu/drivers/dma-buf/sync_debug.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/sync_debug.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 #include <linux/sync_file.h>
 #include <uapi/linux/sync_file.h>
@@ -45,10 +45,9 @@ struct sync_timeline {
 	struct list_head	sync_timeline_list;
 };
 
-static inline struct sync_timeline *fence_parent(struct fence *fence)
+static inline struct sync_timeline *dma_fence_parent(struct dma_fence *fence)
 {
-	return container_of(fence->lock, struct sync_timeline,
-			    child_list_lock);
+	return container_of(fence->lock, struct sync_timeline, child_list_lock);
 }
 
 /**
@@ -58,7 +57,7 @@ static inline struct sync_timeline *fenc
  * @active_list: sync timeline active child's list
  */
 struct sync_pt {
-	struct fence base;
+	struct dma_fence base;
 	struct list_head child_list;
 	struct list_head active_list;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/dma-buf/sync_file.c linux-libre-4.10-rc8-gnu/drivers/dma-buf/sync_file.c
--- linux-libre-4.9-gnu/drivers/dma-buf/sync_file.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/dma-buf/sync_file.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@ err:
 	return NULL;
 }
 
-static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
+static void fence_check_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
 {
 	struct sync_file *sync_file;
 
@@ -71,7 +71,7 @@ static void fence_check_cb_func(struct f
  * takes ownership of @fence. The sync_file can be released with
  * fput(sync_file->file). Returns the sync_file or NULL in case of error.
  */
-struct sync_file *sync_file_create(struct fence *fence)
+struct sync_file *sync_file_create(struct dma_fence *fence)
 {
 	struct sync_file *sync_file;
 
@@ -79,7 +79,7 @@ struct sync_file *sync_file_create(struc
 	if (!sync_file)
 		return NULL;
 
-	sync_file->fence = fence;
+	sync_file->fence = dma_fence_get(fence);
 
 	snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
 		 fence->ops->get_driver_name(fence),
@@ -121,16 +121,16 @@ err:
  * Ensures @fd references a valid sync_file and returns a fence that
  * represents all fence in the sync_file. On error NULL is returned.
  */
-struct fence *sync_file_get_fence(int fd)
+struct dma_fence *sync_file_get_fence(int fd)
 {
 	struct sync_file *sync_file;
-	struct fence *fence;
+	struct dma_fence *fence;
 
 	sync_file = sync_file_fdget(fd);
 	if (!sync_file)
 		return NULL;
 
-	fence = fence_get(sync_file->fence);
+	fence = dma_fence_get(sync_file->fence);
 	fput(sync_file->file);
 
 	return fence;
@@ -138,22 +138,23 @@ struct fence *sync_file_get_fence(int fd
 EXPORT_SYMBOL(sync_file_get_fence);
 
 static int sync_file_set_fence(struct sync_file *sync_file,
-			       struct fence **fences, int num_fences)
+			       struct dma_fence **fences, int num_fences)
 {
-	struct fence_array *array;
+	struct dma_fence_array *array;
 
 	/*
 	 * The reference for the fences in the new sync_file and held
 	 * in add_fence() during the merge procedure, so for num_fences == 1
 	 * we already own a new reference to the fence. For num_fence > 1
-	 * we own the reference of the fence_array creation.
+	 * we own the reference of the dma_fence_array creation.
 	 */
 	if (num_fences == 1) {
 		sync_file->fence = fences[0];
 		kfree(fences);
 	} else {
-		array = fence_array_create(num_fences, fences,
-					   fence_context_alloc(1), 1, false);
+		array = dma_fence_array_create(num_fences, fences,
+					       dma_fence_context_alloc(1),
+					       1, false);
 		if (!array)
 			return -ENOMEM;
 
@@ -163,10 +164,11 @@ static int sync_file_set_fence(struct sy
 	return 0;
 }
 
-static struct fence **get_fences(struct sync_file *sync_file, int *num_fences)
+static struct dma_fence **get_fences(struct sync_file *sync_file,
+				     int *num_fences)
 {
-	if (fence_is_array(sync_file->fence)) {
-		struct fence_array *array = to_fence_array(sync_file->fence);
+	if (dma_fence_is_array(sync_file->fence)) {
+		struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
 
 		*num_fences = array->num_fences;
 		return array->fences;
@@ -176,12 +178,13 @@ static struct fence **get_fences(struct
 	return &sync_file->fence;
 }
 
-static void add_fence(struct fence **fences, int *i, struct fence *fence)
+static void add_fence(struct dma_fence **fences,
+		      int *i, struct dma_fence *fence)
 {
 	fences[*i] = fence;
 
-	if (!fence_is_signaled(fence)) {
-		fence_get(fence);
+	if (!dma_fence_is_signaled(fence)) {
+		dma_fence_get(fence);
 		(*i)++;
 	}
 }
@@ -200,7 +203,7 @@ static struct sync_file *sync_file_merge
 					 struct sync_file *b)
 {
 	struct sync_file *sync_file;
-	struct fence **fences, **nfences, **a_fences, **b_fences;
+	struct dma_fence **fences, **nfences, **a_fences, **b_fences;
 	int i, i_a, i_b, num_fences, a_num_fences, b_num_fences;
 
 	sync_file = sync_file_alloc();
@@ -226,8 +229,8 @@ static struct sync_file *sync_file_merge
 	 * and sync_file_create, this is a reasonable assumption.
 	 */
 	for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
-		struct fence *pt_a = a_fences[i_a];
-		struct fence *pt_b = b_fences[i_b];
+		struct dma_fence *pt_a = a_fences[i_a];
+		struct dma_fence *pt_b = b_fences[i_b];
 
 		if (pt_a->context < pt_b->context) {
 			add_fence(fences, &i, pt_a);
@@ -255,7 +258,7 @@ static struct sync_file *sync_file_merge
 		add_fence(fences, &i, b_fences[i_b]);
 
 	if (i == 0)
-		fences[i++] = fence_get(a_fences[0]);
+		fences[i++] = dma_fence_get(a_fences[0]);
 
 	if (num_fences > i) {
 		nfences = krealloc(fences, i * sizeof(*fences),
@@ -286,8 +289,8 @@ static void sync_file_free(struct kref *
 						     kref);
 
 	if (test_bit(POLL_ENABLED, &sync_file->fence->flags))
-		fence_remove_callback(sync_file->fence, &sync_file->cb);
-	fence_put(sync_file->fence);
+		dma_fence_remove_callback(sync_file->fence, &sync_file->cb);
+	dma_fence_put(sync_file->fence);
 	kfree(sync_file);
 }
 
@@ -305,14 +308,13 @@ static unsigned int sync_file_poll(struc
 
 	poll_wait(file, &sync_file->wq, wait);
 
-	if (!poll_does_not_wait(wait) &&
-	    !test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
-		if (fence_add_callback(sync_file->fence, &sync_file->cb,
-				       fence_check_cb_func) < 0)
+	if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
+		if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
+					   fence_check_cb_func) < 0)
 			wake_up_all(&sync_file->wq);
 	}
 
-	return fence_is_signaled(sync_file->fence) ? POLLIN : 0;
+	return dma_fence_is_signaled(sync_file->fence) ? POLLIN : 0;
 }
 
 static long sync_file_ioctl_merge(struct sync_file *sync_file,
@@ -370,14 +372,14 @@ err_put_fd:
 	return err;
 }
 
-static void sync_fill_fence_info(struct fence *fence,
+static void sync_fill_fence_info(struct dma_fence *fence,
 				 struct sync_fence_info *info)
 {
 	strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
 		sizeof(info->obj_name));
 	strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
 		sizeof(info->driver_name));
-	if (fence_is_signaled(fence))
+	if (dma_fence_is_signaled(fence))
 		info->status = fence->status >= 0 ? 1 : fence->status;
 	else
 		info->status = 0;
@@ -389,7 +391,7 @@ static long sync_file_ioctl_fence_info(s
 {
 	struct sync_file_info info;
 	struct sync_fence_info *fence_info = NULL;
-	struct fence **fences;
+	struct dma_fence **fences;
 	__u32 size;
 	int num_fences, ret, i;
 
@@ -429,7 +431,7 @@ static long sync_file_ioctl_fence_info(s
 
 no_fences:
 	strlcpy(info.name, sync_file->name, sizeof(info.name));
-	info.status = fence_is_signaled(sync_file->fence);
+	info.status = dma_fence_is_signaled(sync_file->fence);
 	info.num_fences = num_fences;
 
 	if (copy_to_user((void __user *)arg, &info, sizeof(info)))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/altera_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/altera_edac.c
--- linux-libre-4.9-gnu/drivers/edac/altera_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/altera_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,6 @@
 #include <linux/uaccess.h>
 
 #include "altera_edac.h"
-#include "edac_core.h"
 #include "edac_module.h"
 
 #define EDAC_MOD_STR		"altera_edac"
@@ -153,13 +152,17 @@ static ssize_t altr_sdr_mc_err_inject_wr
 	if (count == 3) {
 		edac_printk(KERN_ALERT, EDAC_MC,
 			    "Inject Double bit error\n");
+		local_irq_disable();
 		regmap_write(drvdata->mc_vbase, priv->ce_ue_trgr_offset,
 			     (read_reg | priv->ue_set_mask));
+		local_irq_enable();
 	} else {
 		edac_printk(KERN_ALERT, EDAC_MC,
 			    "Inject Single bit error\n");
+		local_irq_disable();
 		regmap_write(drvdata->mc_vbase,	priv->ce_ue_trgr_offset,
 			     (read_reg | priv->ce_set_mask));
+		local_irq_enable();
 	}
 
 	ptemp[0] = 0x5A5A5A5A;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/amd64_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/amd64_edac.c
--- linux-libre-4.9-gnu/drivers/edac/amd64_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/amd64_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -164,8 +164,23 @@ static inline int amd64_read_dct_pci_cfg
  * other archs, we might not have access to the caches directly.
  */
 
+static inline void __f17h_set_scrubval(struct amd64_pvt *pvt, u32 scrubval)
+{
+	/*
+	 * Fam17h supports scrub values between 0x5 and 0x14. Also, the values
+	 * are shifted down by 0x5, so scrubval 0x5 is written to the register
+	 * as 0x0, scrubval 0x6 as 0x1, etc.
+	 */
+	if (scrubval >= 0x5 && scrubval <= 0x14) {
+		scrubval -= 0x5;
+		pci_write_bits32(pvt->F6, F17H_SCR_LIMIT_ADDR, scrubval, 0xF);
+		pci_write_bits32(pvt->F6, F17H_SCR_BASE_ADDR, 1, 0x1);
+	} else {
+		pci_write_bits32(pvt->F6, F17H_SCR_BASE_ADDR, 0, 0x1);
+	}
+}
 /*
- * scan the scrub rate mapping table for a close or matching bandwidth value to
+ * Scan the scrub rate mapping table for a close or matching bandwidth value to
  * issue. If requested is too big, then use last maximum value found.
  */
 static int __set_scrub_rate(struct amd64_pvt *pvt, u32 new_bw, u32 min_rate)
@@ -196,7 +211,9 @@ static int __set_scrub_rate(struct amd64
 
 	scrubval = scrubrates[i].scrubval;
 
-	if (pvt->fam == 0x15 && pvt->model == 0x60) {
+	if (pvt->fam == 0x17) {
+		__f17h_set_scrubval(pvt, scrubval);
+	} else if (pvt->fam == 0x15 && pvt->model == 0x60) {
 		f15h_select_dct(pvt, 0);
 		pci_write_bits32(pvt->F2, F15H_M60H_SCRCTRL, scrubval, 0x001F);
 		f15h_select_dct(pvt, 1);
@@ -233,18 +250,34 @@ static int set_scrub_rate(struct mem_ctl
 static int get_scrub_rate(struct mem_ctl_info *mci)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
-	u32 scrubval = 0;
 	int i, retval = -EINVAL;
+	u32 scrubval = 0;
 
-	if (pvt->fam == 0x15) {
+	switch (pvt->fam) {
+	case 0x15:
 		/* Erratum #505 */
 		if (pvt->model < 0x10)
 			f15h_select_dct(pvt, 0);
 
 		if (pvt->model == 0x60)
 			amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval);
-	} else
+		break;
+
+	case 0x17:
+		amd64_read_pci_cfg(pvt->F6, F17H_SCR_BASE_ADDR, &scrubval);
+		if (scrubval & BIT(0)) {
+			amd64_read_pci_cfg(pvt->F6, F17H_SCR_LIMIT_ADDR, &scrubval);
+			scrubval &= 0xF;
+			scrubval += 0x5;
+		} else {
+			scrubval = 0;
+		}
+		break;
+
+	default:
 		amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
+		break;
+	}
 
 	scrubval = scrubval & 0x001F;
 
@@ -682,15 +715,33 @@ static int get_channel_from_ecc_syndrome
  */
 static unsigned long determine_edac_cap(struct amd64_pvt *pvt)
 {
-	u8 bit;
 	unsigned long edac_cap = EDAC_FLAG_NONE;
+	u8 bit;
 
-	bit = (pvt->fam > 0xf || pvt->ext_model >= K8_REV_F)
-		? 19
-		: 17;
+	if (pvt->umc) {
+		u8 i, umc_en_mask = 0, dimm_ecc_en_mask = 0;
 
-	if (pvt->dclr0 & BIT(bit))
-		edac_cap = EDAC_FLAG_SECDED;
+		for (i = 0; i < NUM_UMCS; i++) {
+			if (!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT))
+				continue;
+
+			umc_en_mask |= BIT(i);
+
+			/* UMC Configuration bit 12 (DimmEccEn) */
+			if (pvt->umc[i].umc_cfg & BIT(12))
+				dimm_ecc_en_mask |= BIT(i);
+		}
+
+		if (umc_en_mask == dimm_ecc_en_mask)
+			edac_cap = EDAC_FLAG_SECDED;
+	} else {
+		bit = (pvt->fam > 0xf || pvt->ext_model >= K8_REV_F)
+			? 19
+			: 17;
+
+		if (pvt->dclr0 & BIT(bit))
+			edac_cap = EDAC_FLAG_SECDED;
+	}
 
 	return edac_cap;
 }
@@ -729,8 +780,75 @@ static void debug_dump_dramcfg_low(struc
 		 (dclr & BIT(15)) ?  "yes" : "no");
 }
 
+static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
+{
+	u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
+	int dimm, size0, size1;
+
+	edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
+
+	for (dimm = 0; dimm < 4; dimm++) {
+		size0 = 0;
+
+		if (dcsb[dimm*2] & DCSB_CS_ENABLE)
+			size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+
+		size1 = 0;
+		if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
+			size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+
+		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
+				dimm * 2,     size0,
+				dimm * 2 + 1, size1);
+	}
+}
+
+static void __dump_misc_regs_df(struct amd64_pvt *pvt)
+{
+	struct amd64_umc *umc;
+	u32 i, tmp, umc_base;
+
+	for (i = 0; i < NUM_UMCS; i++) {
+		umc_base = get_umc_base(i);
+		umc = &pvt->umc[i];
+
+		edac_dbg(1, "UMC%d DIMM cfg: 0x%x\n", i, umc->dimm_cfg);
+		edac_dbg(1, "UMC%d UMC cfg: 0x%x\n", i, umc->umc_cfg);
+		edac_dbg(1, "UMC%d SDP ctrl: 0x%x\n", i, umc->sdp_ctrl);
+		edac_dbg(1, "UMC%d ECC ctrl: 0x%x\n", i, umc->ecc_ctrl);
+
+		amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_ECC_BAD_SYMBOL, &tmp);
+		edac_dbg(1, "UMC%d ECC bad symbol: 0x%x\n", i, tmp);
+
+		amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_UMC_CAP, &tmp);
+		edac_dbg(1, "UMC%d UMC cap: 0x%x\n", i, tmp);
+		edac_dbg(1, "UMC%d UMC cap high: 0x%x\n", i, umc->umc_cap_hi);
+
+		edac_dbg(1, "UMC%d ECC capable: %s, ChipKill ECC capable: %s\n",
+				i, (umc->umc_cap_hi & BIT(30)) ? "yes" : "no",
+				    (umc->umc_cap_hi & BIT(31)) ? "yes" : "no");
+		edac_dbg(1, "UMC%d All DIMMs support ECC: %s\n",
+				i, (umc->umc_cfg & BIT(12)) ? "yes" : "no");
+		edac_dbg(1, "UMC%d x4 DIMMs present: %s\n",
+				i, (umc->dimm_cfg & BIT(6)) ? "yes" : "no");
+		edac_dbg(1, "UMC%d x16 DIMMs present: %s\n",
+				i, (umc->dimm_cfg & BIT(7)) ? "yes" : "no");
+
+		if (pvt->dram_type == MEM_LRDDR4) {
+			amd_smn_read(pvt->mc_node_id, umc_base + UMCCH_ADDR_CFG, &tmp);
+			edac_dbg(1, "UMC%d LRDIMM %dx rank multiply\n",
+					i, 1 << ((tmp >> 4) & 0x3));
+		}
+
+		debug_display_dimm_sizes_df(pvt, i);
+	}
+
+	edac_dbg(1, "F0x104 (DRAM Hole Address): 0x%08x, base: 0x%08x\n",
+		 pvt->dhar, dhar_base(pvt));
+}
+
 /* Display and decode various NB registers for debug purposes. */
-static void dump_misc_regs(struct amd64_pvt *pvt)
+static void __dump_misc_regs(struct amd64_pvt *pvt)
 {
 	edac_dbg(1, "F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap);
 
@@ -750,8 +868,6 @@ static void dump_misc_regs(struct amd64_
 		 (pvt->fam == 0xf) ? k8_dhar_offset(pvt)
 				   : f10_dhar_offset(pvt));
 
-	edac_dbg(1, "  DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
-
 	debug_display_dimm_sizes(pvt, 0);
 
 	/* everything below this point is Fam10h and above */
@@ -760,13 +876,25 @@ static void dump_misc_regs(struct amd64_
 
 	debug_display_dimm_sizes(pvt, 1);
 
-	amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));
-
 	/* Only if NOT ganged does dclr1 have valid info */
 	if (!dct_ganging_enabled(pvt))
 		debug_dump_dramcfg_low(pvt, pvt->dclr1, 1);
 }
 
+/* Display and decode various NB registers for debug purposes. */
+static void dump_misc_regs(struct amd64_pvt *pvt)
+{
+	if (pvt->umc)
+		__dump_misc_regs_df(pvt);
+	else
+		__dump_misc_regs(pvt);
+
+	edac_dbg(1, "  DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
+
+	amd64_info("using %s syndromes.\n",
+			((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));
+}
+
 /*
  * See BKDG, F2x[1,0][5C:40], F2[1,0][6C:60]
  */
@@ -789,46 +917,78 @@ static void prep_chip_selects(struct amd
  */
 static void read_dct_base_mask(struct amd64_pvt *pvt)
 {
-	int cs;
+	int base_reg0, base_reg1, mask_reg0, mask_reg1, cs;
 
 	prep_chip_selects(pvt);
 
+	if (pvt->umc) {
+		base_reg0 = get_umc_base(0) + UMCCH_BASE_ADDR;
+		base_reg1 = get_umc_base(1) + UMCCH_BASE_ADDR;
+		mask_reg0 = get_umc_base(0) + UMCCH_ADDR_MASK;
+		mask_reg1 = get_umc_base(1) + UMCCH_ADDR_MASK;
+	} else {
+		base_reg0 = DCSB0;
+		base_reg1 = DCSB1;
+		mask_reg0 = DCSM0;
+		mask_reg1 = DCSM1;
+	}
+
 	for_each_chip_select(cs, 0, pvt) {
-		int reg0   = DCSB0 + (cs * 4);
-		int reg1   = DCSB1 + (cs * 4);
+		int reg0   = base_reg0 + (cs * 4);
+		int reg1   = base_reg1 + (cs * 4);
 		u32 *base0 = &pvt->csels[0].csbases[cs];
 		u32 *base1 = &pvt->csels[1].csbases[cs];
 
-		if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
-			edac_dbg(0, "  DCSB0[%d]=0x%08x reg: F2x%x\n",
-				 cs, *base0, reg0);
+		if (pvt->umc) {
+			if (!amd_smn_read(pvt->mc_node_id, reg0, base0))
+				edac_dbg(0, "  DCSB0[%d]=0x%08x reg: 0x%x\n",
+					 cs, *base0, reg0);
 
-		if (pvt->fam == 0xf)
-			continue;
+			if (!amd_smn_read(pvt->mc_node_id, reg1, base1))
+				edac_dbg(0, "  DCSB1[%d]=0x%08x reg: 0x%x\n",
+					 cs, *base1, reg1);
+		} else {
+			if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0))
+				edac_dbg(0, "  DCSB0[%d]=0x%08x reg: F2x%x\n",
+					 cs, *base0, reg0);
 
-		if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))
-			edac_dbg(0, "  DCSB1[%d]=0x%08x reg: F2x%x\n",
-				 cs, *base1, (pvt->fam == 0x10) ? reg1
+			if (pvt->fam == 0xf)
+				continue;
+
+			if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1))
+				edac_dbg(0, "  DCSB1[%d]=0x%08x reg: F2x%x\n",
+					 cs, *base1, (pvt->fam == 0x10) ? reg1
 								: reg0);
+		}
 	}
 
 	for_each_chip_select_mask(cs, 0, pvt) {
-		int reg0   = DCSM0 + (cs * 4);
-		int reg1   = DCSM1 + (cs * 4);
+		int reg0   = mask_reg0 + (cs * 4);
+		int reg1   = mask_reg1 + (cs * 4);
 		u32 *mask0 = &pvt->csels[0].csmasks[cs];
 		u32 *mask1 = &pvt->csels[1].csmasks[cs];
 
-		if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
-			edac_dbg(0, "    DCSM0[%d]=0x%08x reg: F2x%x\n",
-				 cs, *mask0, reg0);
+		if (pvt->umc) {
+			if (!amd_smn_read(pvt->mc_node_id, reg0, mask0))
+				edac_dbg(0, "    DCSM0[%d]=0x%08x reg: 0x%x\n",
+					 cs, *mask0, reg0);
 
-		if (pvt->fam == 0xf)
-			continue;
+			if (!amd_smn_read(pvt->mc_node_id, reg1, mask1))
+				edac_dbg(0, "    DCSM1[%d]=0x%08x reg: 0x%x\n",
+					 cs, *mask1, reg1);
+		} else {
+			if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0))
+				edac_dbg(0, "    DCSM0[%d]=0x%08x reg: F2x%x\n",
+					 cs, *mask0, reg0);
 
-		if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))
-			edac_dbg(0, "    DCSM1[%d]=0x%08x reg: F2x%x\n",
-				 cs, *mask1, (pvt->fam == 0x10) ? reg1
+			if (pvt->fam == 0xf)
+				continue;
+
+			if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1))
+				edac_dbg(0, "    DCSM1[%d]=0x%08x reg: F2x%x\n",
+					 cs, *mask1, (pvt->fam == 0x10) ? reg1
 								: reg0);
+		}
 	}
 }
 
@@ -881,6 +1041,15 @@ static void determine_memory_type(struct
 	case 0x16:
 		goto ddr3;
 
+	case 0x17:
+		if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5))
+			pvt->dram_type = MEM_LRDDR4;
+		else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4))
+			pvt->dram_type = MEM_RDDR4;
+		else
+			pvt->dram_type = MEM_DDR4;
+		return;
+
 	default:
 		WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam);
 		pvt->dram_type = MEM_EMPTY;
@@ -1210,6 +1379,19 @@ static int f1x_early_channel_count(struc
 	return channels;
 }
 
+static int f17_early_channel_count(struct amd64_pvt *pvt)
+{
+	int i, channels = 0;
+
+	/* SDP Control bit 31 (SdpInit) is clear for unused UMC channels */
+	for (i = 0; i < NUM_UMCS; i++)
+		channels += !!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT);
+
+	amd64_info("MCT channel count: %d\n", channels);
+
+	return channels;
+}
+
 static int ddr3_cs_size(unsigned i, bool dct_width)
 {
 	unsigned shift = 0;
@@ -1337,6 +1519,23 @@ static int f16_dbam_to_chip_select(struc
 		return ddr3_cs_size(cs_mode, false);
 }
 
+static int f17_base_addr_to_cs_size(struct amd64_pvt *pvt, u8 umc,
+				    unsigned int cs_mode, int csrow_nr)
+{
+	u32 base_addr = pvt->csels[umc].csbases[csrow_nr];
+
+	/*  Each mask is used for every two base addresses. */
+	u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr >> 1];
+
+	/*  Register [31:1] = Address [39:9]. Size is in kBs here. */
+	u32 size = ((addr_mask >> 1) - (base_addr >> 1) + 1) >> 1;
+
+	edac_dbg(1, "BaseAddr: 0x%x, AddrMask: 0x%x\n", base_addr, addr_mask);
+
+	/* Return size in MBs. */
+	return size >> 10;
+}
+
 static void read_dram_ctl_register(struct amd64_pvt *pvt)
 {
 
@@ -1897,8 +2096,9 @@ static void debug_display_dimm_sizes(str
 
 		size0 = 0;
 		if (dcsb[dimm*2] & DCSB_CS_ENABLE)
-			/* For f15m60h, need multiplier for LRDIMM cs_size
-			 * calculation. We pass 'dimm' value to the dbam_to_cs
+			/*
+			 * For F15m60h, we need multiplier for LRDIMM cs_size
+			 * calculation. We pass dimm value to the dbam_to_cs
 			 * mapper so we can find the multiplier from the
 			 * corresponding DCSM.
 			 */
@@ -1989,6 +2189,15 @@ static struct amd64_family_type family_t
 			.dbam_to_cs		= f16_dbam_to_chip_select,
 		}
 	},
+	[F17_CPUS] = {
+		.ctl_name = "F17h",
+		.f0_id = PCI_DEVICE_ID_AMD_17H_DF_F0,
+		.f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6,
+		.ops = {
+			.early_channel_count	= f17_early_channel_count,
+			.dbam_to_cs		= f17_base_addr_to_cs_size,
+		}
+	},
 };
 
 /*
@@ -2155,7 +2364,7 @@ static int get_channel_from_ecc_syndrome
 	return map_err_sym_to_channel(err_sym, pvt->ecc_sym_sz);
 }
 
-static void __log_bus_error(struct mem_ctl_info *mci, struct err_info *err,
+static void __log_ecc_error(struct mem_ctl_info *mci, struct err_info *err,
 			    u8 ecc_type)
 {
 	enum hw_event_mc_err_type err_type;
@@ -2165,6 +2374,8 @@ static void __log_bus_error(struct mem_c
 		err_type = HW_EVENT_ERR_CORRECTED;
 	else if (ecc_type == 1)
 		err_type = HW_EVENT_ERR_UNCORRECTED;
+	else if (ecc_type == 3)
+		err_type = HW_EVENT_ERR_DEFERRED;
 	else {
 		WARN(1, "Something is rotten in the state of Denmark.\n");
 		return;
@@ -2181,7 +2392,13 @@ static void __log_bus_error(struct mem_c
 		string = "Failed to map error addr to a csrow";
 		break;
 	case ERR_CHANNEL:
-		string = "unknown syndrome - possible error reporting race";
+		string = "Unknown syndrome - possible error reporting race";
+		break;
+	case ERR_SYND:
+		string = "MCA_SYND not valid - unknown syndrome and csrow";
+		break;
+	case ERR_NORM_ADDR:
+		string = "Cannot decode normalized address";
 		break;
 	default:
 		string = "WTF error";
@@ -2227,36 +2444,127 @@ static inline void decode_bus_error(int
 
 	pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, &err);
 
-	__log_bus_error(mci, &err, ecc_type);
+	__log_ecc_error(mci, &err, ecc_type);
+}
+
+/*
+ * To find the UMC channel represented by this bank we need to match on its
+ * instance_id. The instance_id of a bank is held in the lower 32 bits of its
+ * IPID.
+ */
+static int find_umc_channel(struct amd64_pvt *pvt, struct mce *m)
+{
+	u32 umc_instance_id[] = {0x50f00, 0x150f00};
+	u32 instance_id = m->ipid & GENMASK(31, 0);
+	int i, channel = -1;
+
+	for (i = 0; i < ARRAY_SIZE(umc_instance_id); i++)
+		if (umc_instance_id[i] == instance_id)
+			channel = i;
+
+	return channel;
+}
+
+static void decode_umc_error(int node_id, struct mce *m)
+{
+	u8 ecc_type = (m->status >> 45) & 0x3;
+	struct mem_ctl_info *mci;
+	struct amd64_pvt *pvt;
+	struct err_info err;
+	u64 sys_addr;
+
+	mci = edac_mc_find(node_id);
+	if (!mci)
+		return;
+
+	pvt = mci->pvt_info;
+
+	memset(&err, 0, sizeof(err));
+
+	if (m->status & MCI_STATUS_DEFERRED)
+		ecc_type = 3;
+
+	err.channel = find_umc_channel(pvt, m);
+	if (err.channel < 0) {
+		err.err_code = ERR_CHANNEL;
+		goto log_error;
+	}
+
+	if (umc_normaddr_to_sysaddr(m->addr, pvt->mc_node_id, err.channel, &sys_addr)) {
+		err.err_code = ERR_NORM_ADDR;
+		goto log_error;
+	}
+
+	error_address_to_page_and_offset(sys_addr, &err);
+
+	if (!(m->status & MCI_STATUS_SYNDV)) {
+		err.err_code = ERR_SYND;
+		goto log_error;
+	}
+
+	if (ecc_type == 2) {
+		u8 length = (m->synd >> 18) & 0x3f;
+
+		if (length)
+			err.syndrome = (m->synd >> 32) & GENMASK(length - 1, 0);
+		else
+			err.err_code = ERR_CHANNEL;
+	}
+
+	err.csrow = m->synd & 0x7;
+
+log_error:
+	__log_ecc_error(mci, &err, ecc_type);
 }
 
 /*
  * Use pvt->F3 which contains the F3 CPU PCI device to get the related
  * F1 (AddrMap) and F2 (Dct) devices. Return negative value on error.
+ * Reserve F0 and F6 on systems with a UMC.
  */
-static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f2_id)
+static int
+reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2)
 {
+	if (pvt->umc) {
+		pvt->F0 = pci_get_related_function(pvt->F3->vendor, pci_id1, pvt->F3);
+		if (!pvt->F0) {
+			amd64_err("F0 not found, device 0x%x (broken BIOS?)\n", pci_id1);
+			return -ENODEV;
+		}
+
+		pvt->F6 = pci_get_related_function(pvt->F3->vendor, pci_id2, pvt->F3);
+		if (!pvt->F6) {
+			pci_dev_put(pvt->F0);
+			pvt->F0 = NULL;
+
+			amd64_err("F6 not found: device 0x%x (broken BIOS?)\n", pci_id2);
+			return -ENODEV;
+		}
+
+		edac_dbg(1, "F0: %s\n", pci_name(pvt->F0));
+		edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
+		edac_dbg(1, "F6: %s\n", pci_name(pvt->F6));
+
+		return 0;
+	}
+
 	/* Reserve the ADDRESS MAP Device */
-	pvt->F1 = pci_get_related_function(pvt->F3->vendor, f1_id, pvt->F3);
+	pvt->F1 = pci_get_related_function(pvt->F3->vendor, pci_id1, pvt->F3);
 	if (!pvt->F1) {
-		amd64_err("error address map device not found: "
-			  "vendor %x device 0x%x (broken BIOS?)\n",
-			  PCI_VENDOR_ID_AMD, f1_id);
+		amd64_err("F1 not found: device 0x%x (broken BIOS?)\n", pci_id1);
 		return -ENODEV;
 	}
 
 	/* Reserve the DCT Device */
-	pvt->F2 = pci_get_related_function(pvt->F3->vendor, f2_id, pvt->F3);
+	pvt->F2 = pci_get_related_function(pvt->F3->vendor, pci_id2, pvt->F3);
 	if (!pvt->F2) {
 		pci_dev_put(pvt->F1);
 		pvt->F1 = NULL;
 
-		amd64_err("error F2 device not found: "
-			  "vendor %x device 0x%x (broken BIOS?)\n",
-			  PCI_VENDOR_ID_AMD, f2_id);
-
+		amd64_err("F2 not found: device 0x%x (broken BIOS?)\n", pci_id2);
 		return -ENODEV;
 	}
+
 	edac_dbg(1, "F1: %s\n", pci_name(pvt->F1));
 	edac_dbg(1, "F2: %s\n", pci_name(pvt->F2));
 	edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
@@ -2266,8 +2574,69 @@ static int reserve_mc_sibling_devs(struc
 
 static void free_mc_sibling_devs(struct amd64_pvt *pvt)
 {
-	pci_dev_put(pvt->F1);
-	pci_dev_put(pvt->F2);
+	if (pvt->umc) {
+		pci_dev_put(pvt->F0);
+		pci_dev_put(pvt->F6);
+	} else {
+		pci_dev_put(pvt->F1);
+		pci_dev_put(pvt->F2);
+	}
+}
+
+static void determine_ecc_sym_sz(struct amd64_pvt *pvt)
+{
+	pvt->ecc_sym_sz = 4;
+
+	if (pvt->umc) {
+		u8 i;
+
+		for (i = 0; i < NUM_UMCS; i++) {
+			/* Check enabled channels only: */
+			if ((pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) &&
+			    (pvt->umc[i].ecc_ctrl & BIT(7))) {
+				pvt->ecc_sym_sz = 8;
+				break;
+			}
+		}
+
+		return;
+	}
+
+	if (pvt->fam >= 0x10) {
+		u32 tmp;
+
+		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
+		/* F16h has only DCT0, so no need to read dbam1. */
+		if (pvt->fam != 0x16)
+			amd64_read_dct_pci_cfg(pvt, 1, DBAM0, &pvt->dbam1);
+
+		/* F10h, revD and later can do x8 ECC too. */
+		if ((pvt->fam > 0x10 || pvt->model > 7) && tmp & BIT(25))
+			pvt->ecc_sym_sz = 8;
+	}
+}
+
+/*
+ * Retrieve the hardware registers of the memory controller.
+ */
+static void __read_mc_regs_df(struct amd64_pvt *pvt)
+{
+	u8 nid = pvt->mc_node_id;
+	struct amd64_umc *umc;
+	u32 i, umc_base;
+
+	/* Read registers from each UMC */
+	for (i = 0; i < NUM_UMCS; i++) {
+
+		umc_base = get_umc_base(i);
+		umc = &pvt->umc[i];
+
+		amd_smn_read(nid, umc_base + UMCCH_DIMM_CFG, &umc->dimm_cfg);
+		amd_smn_read(nid, umc_base + UMCCH_UMC_CFG, &umc->umc_cfg);
+		amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl);
+		amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl);
+		amd_smn_read(nid, umc_base + UMCCH_UMC_CAP_HI, &umc->umc_cap_hi);
+	}
 }
 
 /*
@@ -2276,24 +2645,31 @@ static void free_mc_sibling_devs(struct
  */
 static void read_mc_regs(struct amd64_pvt *pvt)
 {
-	unsigned range;
+	unsigned int range;
 	u64 msr_val;
-	u32 tmp;
 
 	/*
 	 * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since
-	 * those are Read-As-Zero
+	 * those are Read-As-Zero.
 	 */
 	rdmsrl(MSR_K8_TOP_MEM1, pvt->top_mem);
 	edac_dbg(0, "  TOP_MEM:  0x%016llx\n", pvt->top_mem);
 
-	/* check first whether TOP_MEM2 is enabled */
+	/* Check first whether TOP_MEM2 is enabled: */
 	rdmsrl(MSR_K8_SYSCFG, msr_val);
-	if (msr_val & (1U << 21)) {
+	if (msr_val & BIT(21)) {
 		rdmsrl(MSR_K8_TOP_MEM2, pvt->top_mem2);
 		edac_dbg(0, "  TOP_MEM2: 0x%016llx\n", pvt->top_mem2);
-	} else
+	} else {
 		edac_dbg(0, "  TOP_MEM2 disabled\n");
+	}
+
+	if (pvt->umc) {
+		__read_mc_regs_df(pvt);
+		amd64_read_pci_cfg(pvt->F0, DF_DHAR, &pvt->dhar);
+
+		goto skip;
+	}
 
 	amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap);
 
@@ -2322,8 +2698,6 @@ static void read_mc_regs(struct amd64_pv
 			 dram_dst_node(pvt, range));
 	}
 
-	read_dct_base_mask(pvt);
-
 	amd64_read_pci_cfg(pvt->F1, DHAR, &pvt->dhar);
 	amd64_read_dct_pci_cfg(pvt, 0, DBAM0, &pvt->dbam0);
 
@@ -2337,20 +2711,14 @@ static void read_mc_regs(struct amd64_pv
 		amd64_read_dct_pci_cfg(pvt, 1, DCHR0, &pvt->dchr1);
 	}
 
-	pvt->ecc_sym_sz = 4;
+skip:
+	read_dct_base_mask(pvt);
+
 	determine_memory_type(pvt);
 	edac_dbg(1, "  DIMM type: %s\n", edac_mem_types[pvt->dram_type]);
 
-	if (pvt->fam >= 0x10) {
-		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
-		/* F16h has only DCT0, so no need to read dbam1 */
-		if (pvt->fam != 0x16)
-			amd64_read_dct_pci_cfg(pvt, 1, DBAM0, &pvt->dbam1);
+	determine_ecc_sym_sz(pvt);
 
-		/* F10h, revD and later can do x8 ECC too */
-		if ((pvt->fam > 0x10 || pvt->model > 7) && tmp & BIT(25))
-			pvt->ecc_sym_sz = 8;
-	}
 	dump_misc_regs(pvt);
 }
 
@@ -2420,20 +2788,22 @@ static u32 get_csrow_nr_pages(struct amd
 static int init_csrows(struct mem_ctl_info *mci)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
+	enum edac_type edac_mode = EDAC_NONE;
 	struct csrow_info *csrow;
 	struct dimm_info *dimm;
-	enum edac_type edac_mode;
 	int i, j, empty = 1;
 	int nr_pages = 0;
 	u32 val;
 
-	amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
+	if (!pvt->umc) {
+		amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
 
-	pvt->nbcfg = val;
+		pvt->nbcfg = val;
 
-	edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
-		 pvt->mc_node_id, val,
-		 !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
+		edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
+			 pvt->mc_node_id, val,
+			 !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
+	}
 
 	/*
 	 * We iterate over DCT0 here but we look at DCT1 in parallel, if needed.
@@ -2469,14 +2839,18 @@ static int init_csrows(struct mem_ctl_in
 
 		edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages);
 
-		/*
-		 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
-		 */
-		if (pvt->nbcfg & NBCFG_ECC_ENABLE)
-			edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL) ?
-				    EDAC_S4ECD4ED : EDAC_SECDED;
-		else
-			edac_mode = EDAC_NONE;
+		/* Determine DIMM ECC mode: */
+		if (pvt->umc) {
+			if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED)
+				edac_mode = EDAC_S4ECD4ED;
+			else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED)
+				edac_mode = EDAC_SECDED;
+
+		} else if (pvt->nbcfg & NBCFG_ECC_ENABLE) {
+			edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL)
+					? EDAC_S4ECD4ED
+					: EDAC_SECDED;
+		}
 
 		for (j = 0; j < pvt->channel_count; j++) {
 			dimm = csrow->channels[j]->dimm;
@@ -2539,7 +2913,7 @@ static int toggle_ecc_err_reporting(stru
 
 	if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) {
 		amd64_warn("%s: error allocating mask\n", __func__);
-		return false;
+		return -ENOMEM;
 	}
 
 	get_cpus_on_this_dct_cpumask(cmask, nid);
@@ -2627,7 +3001,6 @@ static void restore_ecc_error_reporting(
 {
 	u32 value, mask = 0x3;		/* UECC/CECC enable */
 
-
 	if (!s->nbctl_valid)
 		return;
 
@@ -2663,20 +3036,50 @@ static const char *ecc_msg =
 
 static bool ecc_enabled(struct pci_dev *F3, u16 nid)
 {
-	u32 value;
-	u8 ecc_en = 0;
 	bool nb_mce_en = false;
+	u8 ecc_en = 0, i;
+	u32 value;
 
-	amd64_read_pci_cfg(F3, NBCFG, &value);
+	if (boot_cpu_data.x86 >= 0x17) {
+		u8 umc_en_mask = 0, ecc_en_mask = 0;
 
-	ecc_en = !!(value & NBCFG_ECC_ENABLE);
-	amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
+		for (i = 0; i < NUM_UMCS; i++) {
+			u32 base = get_umc_base(i);
 
-	nb_mce_en = nb_mce_bank_enabled_on_node(nid);
-	if (!nb_mce_en)
-		amd64_notice("NB MCE bank disabled, set MSR "
-			     "0x%08x[4] on node %d to enable.\n",
-			     MSR_IA32_MCG_CTL, nid);
+			/* Only check enabled UMCs. */
+			if (amd_smn_read(nid, base + UMCCH_SDP_CTRL, &value))
+				continue;
+
+			if (!(value & UMC_SDP_INIT))
+				continue;
+
+			umc_en_mask |= BIT(i);
+
+			if (amd_smn_read(nid, base + UMCCH_UMC_CAP_HI, &value))
+				continue;
+
+			if (value & UMC_ECC_ENABLED)
+				ecc_en_mask |= BIT(i);
+		}
+
+		/* Check whether at least one UMC is enabled: */
+		if (umc_en_mask)
+			ecc_en = umc_en_mask == ecc_en_mask;
+
+		/* Assume UMC MCA banks are enabled. */
+		nb_mce_en = true;
+	} else {
+		amd64_read_pci_cfg(F3, NBCFG, &value);
+
+		ecc_en = !!(value & NBCFG_ECC_ENABLE);
+
+		nb_mce_en = nb_mce_bank_enabled_on_node(nid);
+		if (!nb_mce_en)
+			amd64_notice("NB MCE bank disabled, set MSR 0x%08x[4] on node %d to enable.\n",
+				     MSR_IA32_MCG_CTL, nid);
+	}
+
+	amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
 
 	if (!ecc_en || !nb_mce_en) {
 		amd64_notice("%s", ecc_msg);
@@ -2685,6 +3088,27 @@ static bool ecc_enabled(struct pci_dev *
 	return true;
 }
 
+static inline void
+f17h_determine_edac_ctl_cap(struct mem_ctl_info *mci, struct amd64_pvt *pvt)
+{
+	u8 i, ecc_en = 1, cpk_en = 1;
+
+	for (i = 0; i < NUM_UMCS; i++) {
+		if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) {
+			ecc_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_ENABLED);
+			cpk_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_CHIPKILL_CAP);
+		}
+	}
+
+	/* Set chipkill only if ECC is enabled: */
+	if (ecc_en) {
+		mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
+
+		if (cpk_en)
+			mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+	}
+}
+
 static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
 				 struct amd64_family_type *fam)
 {
@@ -2693,17 +3117,21 @@ static void setup_mci_misc_attrs(struct
 	mci->mtype_cap		= MEM_FLAG_DDR2 | MEM_FLAG_RDDR2;
 	mci->edac_ctl_cap	= EDAC_FLAG_NONE;
 
-	if (pvt->nbcap & NBCAP_SECDED)
-		mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
+	if (pvt->umc) {
+		f17h_determine_edac_ctl_cap(mci, pvt);
+	} else {
+		if (pvt->nbcap & NBCAP_SECDED)
+			mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
 
-	if (pvt->nbcap & NBCAP_CHIPKILL)
-		mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+		if (pvt->nbcap & NBCAP_CHIPKILL)
+			mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
+	}
 
 	mci->edac_cap		= determine_edac_cap(pvt);
 	mci->mod_name		= EDAC_MOD_STR;
 	mci->mod_ver		= EDAC_AMD64_VERSION;
 	mci->ctl_name		= fam->ctl_name;
-	mci->dev_name		= pci_name(pvt->F2);
+	mci->dev_name		= pci_name(pvt->F3);
 	mci->ctl_page_to_phys	= NULL;
 
 	/* memory scrubber interface */
@@ -2759,6 +3187,11 @@ static struct amd64_family_type *per_fam
 		pvt->ops	= &family_types[F16_CPUS].ops;
 		break;
 
+	case 0x17:
+		fam_type	= &family_types[F17_CPUS];
+		pvt->ops	= &family_types[F17_CPUS].ops;
+		break;
+
 	default:
 		amd64_err("Unsupported family!\n");
 		return NULL;
@@ -2789,6 +3222,7 @@ static int init_one_instance(unsigned in
 	struct mem_ctl_info *mci = NULL;
 	struct edac_mc_layer layers[2];
 	struct amd64_pvt *pvt = NULL;
+	u16 pci_id1, pci_id2;
 	int err = 0, ret;
 
 	ret = -ENOMEM;
@@ -2804,10 +3238,23 @@ static int init_one_instance(unsigned in
 	if (!fam_type)
 		goto err_free;
 
-	ret = -ENODEV;
-	err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f2_id);
+	if (pvt->fam >= 0x17) {
+		pvt->umc = kcalloc(NUM_UMCS, sizeof(struct amd64_umc), GFP_KERNEL);
+		if (!pvt->umc) {
+			ret = -ENOMEM;
+			goto err_free;
+		}
+
+		pci_id1 = fam_type->f0_id;
+		pci_id2 = fam_type->f6_id;
+	} else {
+		pci_id1 = fam_type->f1_id;
+		pci_id2 = fam_type->f2_id;
+	}
+
+	err = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2);
 	if (err)
-		goto err_free;
+		goto err_post_init;
 
 	read_mc_regs(pvt);
 
@@ -2857,7 +3304,10 @@ static int init_one_instance(unsigned in
 	if (report_gart_errors)
 		amd_report_gart_errors(true);
 
-	amd_register_ecc_decoder(decode_bus_error);
+	if (pvt->umc)
+		amd_register_ecc_decoder(decode_umc_error);
+	else
+		amd_register_ecc_decoder(decode_bus_error);
 
 	return 0;
 
@@ -2867,6 +3317,10 @@ err_add_mc:
 err_siblings:
 	free_mc_sibling_devs(pvt);
 
+err_post_init:
+	if (pvt->fam >= 0x17)
+		kfree(pvt->umc);
+
 err_free:
 	kfree(pvt);
 
@@ -2893,7 +3347,11 @@ static int probe_one_instance(unsigned i
 		if (!ecc_enable_override)
 			goto err_enable;
 
-		amd64_warn("Forcing ECC on!\n");
+		if (boot_cpu_data.x86 >= 0x17) {
+			amd64_warn("Forcing ECC on is not recommended on newer systems. Please enable ECC in BIOS.");
+			goto err_enable;
+		} else
+			amd64_warn("Forcing ECC on!\n");
 
 		if (!enable_ecc_error_reporting(s, nid, F3))
 			goto err_enable;
@@ -2902,7 +3360,9 @@ static int probe_one_instance(unsigned i
 	ret = init_one_instance(nid);
 	if (ret < 0) {
 		amd64_err("Error probing instance: %d\n", nid);
-		restore_ecc_error_reporting(s, nid, F3);
+
+		if (boot_cpu_data.x86 < 0x17)
+			restore_ecc_error_reporting(s, nid, F3);
 	}
 
 	return ret;
@@ -2938,7 +3398,11 @@ static void remove_one_instance(unsigned
 
 	/* unregister from EDAC MCE */
 	amd_report_gart_errors(false);
-	amd_unregister_ecc_decoder(decode_bus_error);
+
+	if (pvt->umc)
+		amd_unregister_ecc_decoder(decode_umc_error);
+	else
+		amd_unregister_ecc_decoder(decode_bus_error);
 
 	kfree(ecc_stngs[nid]);
 	ecc_stngs[nid] = NULL;
@@ -2963,7 +3427,10 @@ static void setup_pci_device(void)
 		return;
 
 	pvt = mci->pvt_info;
-	pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
+	if (pvt->umc)
+		pci_ctl = edac_pci_create_generic_ctl(&pvt->F0->dev, EDAC_MOD_STR);
+	else
+		pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
 	if (!pci_ctl) {
 		pr_warn("%s(): Unable to create PCI control\n", __func__);
 		pr_warn("%s(): PCI error report via EDAC not set\n", __func__);
@@ -2975,6 +3442,7 @@ static const struct x86_cpu_id amd64_cpu
 	{ X86_VENDOR_AMD, 0x10, X86_MODEL_ANY,	X86_FEATURE_ANY, 0 },
 	{ X86_VENDOR_AMD, 0x15, X86_MODEL_ANY,	X86_FEATURE_ANY, 0 },
 	{ X86_VENDOR_AMD, 0x16, X86_MODEL_ANY,	X86_FEATURE_ANY, 0 },
+	{ X86_VENDOR_AMD, 0x17, X86_MODEL_ANY,	X86_FEATURE_ANY, 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/amd64_edac.h linux-libre-4.10-rc8-gnu/drivers/edac/amd64_edac.h
--- linux-libre-4.9-gnu/drivers/edac/amd64_edac.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/amd64_edac.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/mmzone.h>
 #include <linux/edac.h>
 #include <asm/msr.h>
-#include "edac_core.h"
+#include "edac_module.h"
 #include "mce_amd.h"
 
 #define amd64_debug(fmt, arg...) \
@@ -30,10 +30,10 @@
 	edac_printk(KERN_NOTICE, "amd64", fmt, ##arg)
 
 #define amd64_warn(fmt, arg...) \
-	edac_printk(KERN_WARNING, "amd64", fmt, ##arg)
+	edac_printk(KERN_WARNING, "amd64", "Warning: " fmt, ##arg)
 
 #define amd64_err(fmt, arg...) \
-	edac_printk(KERN_ERR, "amd64", fmt, ##arg)
+	edac_printk(KERN_ERR, "amd64", "Error: " fmt, ##arg)
 
 #define amd64_mc_warn(mci, fmt, arg...) \
 	edac_mc_chipset_printk(mci, KERN_WARNING, "amd64", fmt, ##arg)
@@ -118,6 +118,8 @@
 #define PCI_DEVICE_ID_AMD_16H_NB_F2	0x1532
 #define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581
 #define PCI_DEVICE_ID_AMD_16H_M30H_NB_F2 0x1582
+#define PCI_DEVICE_ID_AMD_17H_DF_F0	0x1460
+#define PCI_DEVICE_ID_AMD_17H_DF_F6	0x1466
 
 /*
  * Function 1 - Address Map
@@ -202,6 +204,8 @@
 #define DCT_SEL_HI			0x114
 
 #define F15H_M60H_SCRCTRL		0x1C8
+#define F17H_SCR_BASE_ADDR		0x48
+#define F17H_SCR_LIMIT_ADDR		0x4C
 
 /*
  * Function 3 - Misc Control
@@ -248,6 +252,31 @@
 /* MSRs */
 #define MSR_MCGCTL_NBE			BIT(4)
 
+/* F17h */
+
+/* F0: */
+#define DF_DHAR				0x104
+
+/* UMC CH register offsets */
+#define UMCCH_BASE_ADDR			0x0
+#define UMCCH_ADDR_MASK			0x20
+#define UMCCH_ADDR_CFG			0x30
+#define UMCCH_DIMM_CFG			0x80
+#define UMCCH_UMC_CFG			0x100
+#define UMCCH_SDP_CTRL			0x104
+#define UMCCH_ECC_CTRL			0x14C
+#define UMCCH_ECC_BAD_SYMBOL		0xD90
+#define UMCCH_UMC_CAP			0xDF0
+#define UMCCH_UMC_CAP_HI		0xDF4
+
+/* UMC CH bitfields */
+#define UMC_ECC_CHIPKILL_CAP		BIT(31)
+#define UMC_ECC_ENABLED			BIT(30)
+
+#define UMC_SDP_INIT			BIT(31)
+
+#define NUM_UMCS			2
+
 enum amd_families {
 	K8_CPUS = 0,
 	F10_CPUS,
@@ -256,6 +285,7 @@ enum amd_families {
 	F15_M60H_CPUS,
 	F16_CPUS,
 	F16_M30H_CPUS,
+	F17_CPUS,
 	NUM_FAMILIES,
 };
 
@@ -288,11 +318,19 @@ struct chip_select {
 	u8 m_cnt;
 };
 
+struct amd64_umc {
+	u32 dimm_cfg;		/* DIMM Configuration reg */
+	u32 umc_cfg;		/* Configuration reg */
+	u32 sdp_ctrl;		/* SDP Control reg */
+	u32 ecc_ctrl;		/* DRAM ECC Control reg */
+	u32 umc_cap_hi;		/* Capabilities High reg */
+};
+
 struct amd64_pvt {
 	struct low_ops *ops;
 
 	/* pci_device handles which we utilize */
-	struct pci_dev *F1, *F2, *F3;
+	struct pci_dev *F0, *F1, *F2, *F3, *F6;
 
 	u16 mc_node_id;		/* MC index of this MC node */
 	u8 fam;			/* CPU family */
@@ -335,6 +373,8 @@ struct amd64_pvt {
 
 	/* cache the dram_type */
 	enum mem_type dram_type;
+
+	struct amd64_umc *umc;	/* UMC registers */
 };
 
 enum err_codes {
@@ -342,6 +382,8 @@ enum err_codes {
 	ERR_NODE	= -1,
 	ERR_CSROW	= -2,
 	ERR_CHANNEL	= -3,
+	ERR_SYND	= -4,
+	ERR_NORM_ADDR	= -5,
 };
 
 struct err_info {
@@ -354,6 +396,12 @@ struct err_info {
 	u32 offset;
 };
 
+static inline u32 get_umc_base(u8 channel)
+{
+	/* ch0: 0x50000, ch1: 0x150000 */
+	return 0x50000 + (!!channel << 20);
+}
+
 static inline u64 get_dram_base(struct amd64_pvt *pvt, u8 i)
 {
 	u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
@@ -422,7 +470,7 @@ struct low_ops {
 
 struct amd64_family_type {
 	const char *ctl_name;
-	u16 f1_id, f2_id;
+	u16 f0_id, f1_id, f2_id, f6_id;
 	struct low_ops ops;
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/amd76x_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/amd76x_edac.c
--- linux-libre-4.9-gnu/drivers/edac/amd76x_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/amd76x_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define AMD76X_REVISION	" Ver: 2.0.2"
 #define EDAC_MOD_STR	"amd76x_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/amd8111_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/amd8111_edac.c
--- linux-libre-4.9-gnu/drivers/edac/amd8111_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/amd8111_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,6 @@
 #include <linux/pci_ids.h>
 #include <asm/io.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 #include "amd8111_edac.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/amd8131_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/amd8131_edac.c
--- linux-libre-4.9-gnu/drivers/edac/amd8131_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/amd8131_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,6 @@
 #include <linux/edac.h>
 #include <linux/pci_ids.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 #include "amd8131_edac.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/cell_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/cell_edac.c
--- linux-libre-4.9-gnu/drivers/edac/cell_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/cell_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <asm/machdep.h>
 #include <asm/cell-regs.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 struct cell_edac_priv
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/cpc925_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/cpc925_edac.c
--- linux-libre-4.9-gnu/drivers/edac/cpc925_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/cpc925_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,6 @@
 #include <linux/platform_device.h>
 #include <linux/gfp.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 #define CPC925_EDAC_REVISION	" Ver: 1.0.0"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/e752x_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/e752x_edac.c
--- linux-libre-4.9-gnu/drivers/edac/e752x_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/e752x_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define E752X_REVISION	" Ver: 2.0.2"
 #define EDAC_MOD_STR	"e752x_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/e7xxx_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/e7xxx_edac.c
--- linux-libre-4.9-gnu/drivers/edac/e7xxx_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/e7xxx_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define	E7XXX_REVISION " Ver: 2.0.2"
 #define	EDAC_MOD_STR	"e7xxx_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_core.h linux-libre-4.10-rc8-gnu/drivers/edac/edac_core.h
--- linux-libre-4.9-gnu/drivers/edac/edac_core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,517 +0,0 @@
-/*
- * Defines, structures, APIs for edac_core module
- *
- * (C) 2007 Linux Networx (http://lnxi.com)
- * This file may be distributed under the terms of the
- * GNU General Public License.
- *
- * Written by Thayne Harbaugh
- * Based on work by Dan Hollis <goemon at anime dot net> and others.
- *	http://www.anime.net/~goemon/linux-ecc/
- *
- * NMI handling support added by
- *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
- *
- * Refactored for multi-source files:
- *	Doug Thompson <norsk5@xmission.com>
- *
- */
-
-#ifndef _EDAC_CORE_H_
-#define _EDAC_CORE_H_
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/smp.h>
-#include <linux/pci.h>
-#include <linux/time.h>
-#include <linux/nmi.h>
-#include <linux/rcupdate.h>
-#include <linux/completion.h>
-#include <linux/kobject.h>
-#include <linux/platform_device.h>
-#include <linux/workqueue.h>
-#include <linux/edac.h>
-
-#define EDAC_DEVICE_NAME_LEN	31
-#define EDAC_ATTRIB_VALUE_LEN	15
-
-#if PAGE_SHIFT < 20
-#define PAGES_TO_MiB(pages)	((pages) >> (20 - PAGE_SHIFT))
-#define MiB_TO_PAGES(mb)	((mb) << (20 - PAGE_SHIFT))
-#else				/* PAGE_SHIFT > 20 */
-#define PAGES_TO_MiB(pages)	((pages) << (PAGE_SHIFT - 20))
-#define MiB_TO_PAGES(mb)	((mb) >> (PAGE_SHIFT - 20))
-#endif
-
-#define edac_printk(level, prefix, fmt, arg...) \
-	printk(level "EDAC " prefix ": " fmt, ##arg)
-
-#define edac_mc_printk(mci, level, fmt, arg...) \
-	printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg)
-
-#define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \
-	printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg)
-
-#define edac_device_printk(ctl, level, fmt, arg...) \
-	printk(level "EDAC DEVICE%d: " fmt, ctl->dev_idx, ##arg)
-
-#define edac_pci_printk(ctl, level, fmt, arg...) \
-	printk(level "EDAC PCI%d: " fmt, ctl->pci_idx, ##arg)
-
-/* prefixes for edac_printk() and edac_mc_printk() */
-#define EDAC_MC "MC"
-#define EDAC_PCI "PCI"
-#define EDAC_DEBUG "DEBUG"
-
-extern const char * const edac_mem_types[];
-
-#ifdef CONFIG_EDAC_DEBUG
-extern int edac_debug_level;
-
-#define edac_dbg(level, fmt, ...)					\
-do {									\
-	if (level <= edac_debug_level)					\
-		edac_printk(KERN_DEBUG, EDAC_DEBUG,			\
-			    "%s: " fmt, __func__, ##__VA_ARGS__);	\
-} while (0)
-
-#else				/* !CONFIG_EDAC_DEBUG */
-
-#define edac_dbg(level, fmt, ...)					\
-do {									\
-	if (0)								\
-		edac_printk(KERN_DEBUG, EDAC_DEBUG,			\
-			    "%s: " fmt, __func__, ##__VA_ARGS__);	\
-} while (0)
-
-#endif				/* !CONFIG_EDAC_DEBUG */
-
-#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \
-	PCI_DEVICE_ID_ ## vend ## _ ## dev
-
-#define edac_dev_name(dev) (dev)->dev_name
-
-#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
-
-/*
- * The following are the structures to provide for a generic
- * or abstract 'edac_device'. This set of structures and the
- * code that implements the APIs for the same, provide for
- * registering EDAC type devices which are NOT standard memory.
- *
- * CPU caches (L1 and L2)
- * DMA engines
- * Core CPU switches
- * Fabric switch units
- * PCIe interface controllers
- * other EDAC/ECC type devices that can be monitored for
- * errors, etc.
- *
- * It allows for a 2 level set of hierarchy. For example:
- *
- * cache could be composed of L1, L2 and L3 levels of cache.
- * Each CPU core would have its own L1 cache, while sharing
- * L2 and maybe L3 caches.
- *
- * View them arranged, via the sysfs presentation:
- * /sys/devices/system/edac/..
- *
- *	mc/		<existing memory device directory>
- *	cpu/cpu0/..	<L1 and L2 block directory>
- *		/L1-cache/ce_count
- *			 /ue_count
- *		/L2-cache/ce_count
- *			 /ue_count
- *	cpu/cpu1/..	<L1 and L2 block directory>
- *		/L1-cache/ce_count
- *			 /ue_count
- *		/L2-cache/ce_count
- *			 /ue_count
- *	...
- *
- *	the L1 and L2 directories would be "edac_device_block's"
- */
-
-struct edac_device_counter {
-	u32 ue_count;
-	u32 ce_count;
-};
-
-/* forward reference */
-struct edac_device_ctl_info;
-struct edac_device_block;
-
-/* edac_dev_sysfs_attribute structure
- *	used for driver sysfs attributes in mem_ctl_info
- *	for extra controls and attributes:
- *		like high level error Injection controls
- */
-struct edac_dev_sysfs_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct edac_device_ctl_info *, char *);
-	ssize_t (*store)(struct edac_device_ctl_info *, const char *, size_t);
-};
-
-/* edac_dev_sysfs_block_attribute structure
- *
- *	used in leaf 'block' nodes for adding controls/attributes
- *
- *	each block in each instance of the containing control structure
- *	can have an array of the following. The show and store functions
- *	will be filled in with the show/store function in the
- *	low level driver.
- *
- *	The 'value' field will be the actual value field used for
- *	counting
- */
-struct edac_dev_sysfs_block_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct kobject *, struct attribute *, char *);
-	ssize_t (*store)(struct kobject *, struct attribute *,
-			const char *, size_t);
-	struct edac_device_block *block;
-
-	unsigned int value;
-};
-
-/* device block control structure */
-struct edac_device_block {
-	struct edac_device_instance *instance;	/* Up Pointer */
-	char name[EDAC_DEVICE_NAME_LEN + 1];
-
-	struct edac_device_counter counters;	/* basic UE and CE counters */
-
-	int nr_attribs;		/* how many attributes */
-
-	/* this block's attributes, could be NULL */
-	struct edac_dev_sysfs_block_attribute *block_attributes;
-
-	/* edac sysfs device control */
-	struct kobject kobj;
-};
-
-/* device instance control structure */
-struct edac_device_instance {
-	struct edac_device_ctl_info *ctl;	/* Up pointer */
-	char name[EDAC_DEVICE_NAME_LEN + 4];
-
-	struct edac_device_counter counters;	/* instance counters */
-
-	u32 nr_blocks;		/* how many blocks */
-	struct edac_device_block *blocks;	/* block array */
-
-	/* edac sysfs device control */
-	struct kobject kobj;
-};
-
-
-/*
- * Abstract edac_device control info structure
- *
- */
-struct edac_device_ctl_info {
-	/* for global list of edac_device_ctl_info structs */
-	struct list_head link;
-
-	struct module *owner;	/* Module owner of this control struct */
-
-	int dev_idx;
-
-	/* Per instance controls for this edac_device */
-	int log_ue;		/* boolean for logging UEs */
-	int log_ce;		/* boolean for logging CEs */
-	int panic_on_ue;	/* boolean for panic'ing on an UE */
-	unsigned poll_msec;	/* number of milliseconds to poll interval */
-	unsigned long delay;	/* number of jiffies for poll_msec */
-
-	/* 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
-	 */
-	struct edac_dev_sysfs_attribute *sysfs_attributes;
-
-	/* pointer to main 'edac' subsys in sysfs */
-	struct bus_type *edac_subsys;
-
-	/* the internal state of this controller instance */
-	int op_state;
-	/* work struct for this instance */
-	struct delayed_work work;
-
-	/* pointer to edac polling checking routine:
-	 *      If NOT NULL: points to polling check routine
-	 *      If NULL: Then assumes INTERRUPT operation, where
-	 *              MC driver will receive events
-	 */
-	void (*edac_check) (struct edac_device_ctl_info * edac_dev);
-
-	struct device *dev;	/* pointer to device structure */
-
-	const char *mod_name;	/* module name */
-	const char *ctl_name;	/* edac controller  name */
-	const char *dev_name;	/* pci/platform/etc... name */
-
-	void *pvt_info;		/* pointer to 'private driver' info */
-
-	unsigned long start_time;	/* edac_device load start time (jiffies) */
-
-	struct completion removal_complete;
-
-	/* sysfs top name under 'edac' directory
-	 * and instance name:
-	 *      cpu/cpu0/...
-	 *      cpu/cpu1/...
-	 *      cpu/cpu2/...
-	 *      ...
-	 */
-	char name[EDAC_DEVICE_NAME_LEN + 1];
-
-	/* Number of instances supported on this control structure
-	 * and the array of those instances
-	 */
-	u32 nr_instances;
-	struct edac_device_instance *instances;
-
-	/* Event counters for the this whole EDAC Device */
-	struct edac_device_counter counters;
-
-	/* edac sysfs device control for the 'name'
-	 * device this structure controls
-	 */
-	struct kobject kobj;
-};
-
-/* To get from the instance's wq to the beginning of the ctl structure */
-#define to_edac_mem_ctl_work(w) \
-		container_of(w, struct mem_ctl_info, work)
-
-#define to_edac_device_ctl_work(w) \
-		container_of(w,struct edac_device_ctl_info,work)
-
-/*
- * The alloc() and free() functions for the 'edac_device' control info
- * structure. A MC driver will allocate one of these for each edac_device
- * it is going to control/register with the EDAC CORE.
- */
-extern struct edac_device_ctl_info *edac_device_alloc_ctl_info(
-		unsigned sizeof_private,
-		char *edac_device_name, unsigned nr_instances,
-		char *edac_block_name, unsigned nr_blocks,
-		unsigned offset_value,
-		struct edac_dev_sysfs_block_attribute *block_attributes,
-		unsigned nr_attribs,
-		int device_index);
-
-/* The offset value can be:
- *	-1 indicating no offset value
- *	0 for zero-based block numbers
- *	1 for 1-based block number
- *	other for other-based block number
- */
-#define	BLOCK_OFFSET_VALUE_OFF	((unsigned) -1)
-
-extern void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info);
-
-#ifdef CONFIG_PCI
-
-struct edac_pci_counter {
-	atomic_t pe_count;
-	atomic_t npe_count;
-};
-
-/*
- * Abstract edac_pci control info structure
- *
- */
-struct edac_pci_ctl_info {
-	/* for global list of edac_pci_ctl_info structs */
-	struct list_head link;
-
-	int pci_idx;
-
-	struct bus_type *edac_subsys;	/* pointer to subsystem */
-
-	/* the internal state of this controller instance */
-	int op_state;
-	/* work struct for this instance */
-	struct delayed_work work;
-
-	/* pointer to edac polling checking routine:
-	 *      If NOT NULL: points to polling check routine
-	 *      If NULL: Then assumes INTERRUPT operation, where
-	 *              MC driver will receive events
-	 */
-	void (*edac_check) (struct edac_pci_ctl_info * edac_dev);
-
-	struct device *dev;	/* pointer to device structure */
-
-	const char *mod_name;	/* module name */
-	const char *ctl_name;	/* edac controller  name */
-	const char *dev_name;	/* pci/platform/etc... name */
-
-	void *pvt_info;		/* pointer to 'private driver' info */
-
-	unsigned long start_time;	/* edac_pci load start time (jiffies) */
-
-	struct completion complete;
-
-	/* sysfs top name under 'edac' directory
-	 * and instance name:
-	 *      cpu/cpu0/...
-	 *      cpu/cpu1/...
-	 *      cpu/cpu2/...
-	 *      ...
-	 */
-	char name[EDAC_DEVICE_NAME_LEN + 1];
-
-	/* Event counters for the this whole EDAC Device */
-	struct edac_pci_counter counters;
-
-	/* edac sysfs device control for the 'name'
-	 * device this structure controls
-	 */
-	struct kobject kobj;
-	struct completion kobj_complete;
-};
-
-#define to_edac_pci_ctl_work(w) \
-		container_of(w, struct edac_pci_ctl_info,work)
-
-/* write all or some bits in a byte-register*/
-static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
-				   u8 mask)
-{
-	if (mask != 0xff) {
-		u8 buf;
-
-		pci_read_config_byte(pdev, offset, &buf);
-		value &= mask;
-		buf &= ~mask;
-		value |= buf;
-	}
-
-	pci_write_config_byte(pdev, offset, value);
-}
-
-/* write all or some bits in a word-register*/
-static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
-				    u16 value, u16 mask)
-{
-	if (mask != 0xffff) {
-		u16 buf;
-
-		pci_read_config_word(pdev, offset, &buf);
-		value &= mask;
-		buf &= ~mask;
-		value |= buf;
-	}
-
-	pci_write_config_word(pdev, offset, value);
-}
-
-/*
- * pci_write_bits32
- *
- * edac local routine to do pci_write_config_dword, but adds
- * a mask parameter. If mask is all ones, ignore the mask.
- * Otherwise utilize the mask to isolate specified bits
- *
- * write all or some bits in a dword-register
- */
-static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
-				    u32 value, u32 mask)
-{
-	if (mask != 0xffffffff) {
-		u32 buf;
-
-		pci_read_config_dword(pdev, offset, &buf);
-		value &= mask;
-		buf &= ~mask;
-		value |= buf;
-	}
-
-	pci_write_config_dword(pdev, offset, value);
-}
-
-#endif				/* CONFIG_PCI */
-
-struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
-				   unsigned n_layers,
-				   struct edac_mc_layer *layers,
-				   unsigned sz_pvt);
-extern int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
-				      const struct attribute_group **groups);
-#define edac_mc_add_mc(mci)	edac_mc_add_mc_with_groups(mci, NULL)
-extern void edac_mc_free(struct mem_ctl_info *mci);
-extern struct mem_ctl_info *edac_mc_find(int idx);
-extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);
-extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev);
-extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
-				      unsigned long page);
-
-void edac_raw_mc_handle_error(const enum hw_event_mc_err_type type,
-			      struct mem_ctl_info *mci,
-			      struct edac_raw_error_desc *e);
-
-void edac_mc_handle_error(const enum hw_event_mc_err_type type,
-			  struct mem_ctl_info *mci,
-			  const u16 error_count,
-			  const unsigned long page_frame_number,
-			  const unsigned long offset_in_page,
-			  const unsigned long syndrome,
-			  const int top_layer,
-			  const int mid_layer,
-			  const int low_layer,
-			  const char *msg,
-			  const char *other_detail);
-
-/*
- * edac_device APIs
- */
-extern int edac_device_add_device(struct edac_device_ctl_info *edac_dev);
-extern struct edac_device_ctl_info *edac_device_del_device(struct device *dev);
-extern void edac_device_handle_ue(struct edac_device_ctl_info *edac_dev,
-				int inst_nr, int block_nr, const char *msg);
-extern void edac_device_handle_ce(struct edac_device_ctl_info *edac_dev,
-				int inst_nr, int block_nr, const char *msg);
-extern int edac_device_alloc_index(void);
-extern const char *edac_layer_name[];
-
-/*
- * edac_pci APIs
- */
-extern struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
-				const char *edac_pci_name);
-
-extern void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci);
-
-extern void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci,
-				unsigned long value);
-
-extern int edac_pci_alloc_index(void);
-extern int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx);
-extern struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev);
-
-extern struct edac_pci_ctl_info *edac_pci_create_generic_ctl(
-				struct device *dev,
-				const char *mod_name);
-
-extern void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci);
-extern int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci);
-extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci);
-
-/*
- * edac misc APIs
- */
-extern char *edac_op_state_to_string(int op_state);
-
-#endif				/* _EDAC_CORE_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_device.c linux-libre-4.10-rc8-gnu/drivers/edac/edac_device.c
--- linux-libre-4.9-gnu/drivers/edac/edac_device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,23 +12,20 @@
  * 19 Jan 2007
  */
 
+#include <asm/page.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
 #include <linux/module.h>
-#include <linux/types.h>
+#include <linux/slab.h>
 #include <linux/smp.h>
-#include <linux/init.h>
+#include <linux/spinlock.h>
 #include <linux/sysctl.h>
-#include <linux/highmem.h>
 #include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/ctype.h>
-#include <linux/workqueue.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
 
-#include "edac_core.h"
+#include "edac_device.h"
 #include "edac_module.h"
 
 /* lock for the list: 'edac_device_list', manipulation of this list
@@ -50,21 +47,6 @@ static void edac_device_dump_device(stru
 }
 #endif				/* CONFIG_EDAC_DEBUG */
 
-
-/*
- * edac_device_alloc_ctl_info()
- *	Allocate a new edac device control info structure
- *
- *	The control structure is allocated in complete chunk
- *	from the OS. It is in turn sub allocated to the
- *	various objects that compose the structure
- *
- *	The structure has a 'nr_instance' array within itself.
- *	Each instance represents a major component
- *		Example:  L1 cache and L2 cache are 2 instance components
- *
- *	Within each instance is an array of 'nr_blocks' blockoffsets
- */
 struct edac_device_ctl_info *edac_device_alloc_ctl_info(
 	unsigned sz_private,
 	char *edac_device_name, unsigned nr_instances,
@@ -244,11 +226,6 @@ struct edac_device_ctl_info *edac_device
 }
 EXPORT_SYMBOL_GPL(edac_device_alloc_ctl_info);
 
-/*
- * edac_device_free_ctl_info()
- *	frees the memory allocated by the edac_device_alloc_ctl_info()
- *	function
- */
 void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info)
 {
 	edac_device_unregister_sysfs_main_kobj(ctl_info);
@@ -460,12 +437,6 @@ void edac_device_reset_delay_period(stru
 	edac_mod_work(&edac_dev->work, jiffs);
 }
 
-/*
- * edac_device_alloc_index: Allocate a unique device index number
- *
- * Return:
- *	allocated index number
- */
 int edac_device_alloc_index(void)
 {
 	static atomic_t device_indexes = ATOMIC_INIT(0);
@@ -474,17 +445,6 @@ int edac_device_alloc_index(void)
 }
 EXPORT_SYMBOL_GPL(edac_device_alloc_index);
 
-/**
- * edac_device_add_device: Insert the 'edac_dev' structure into the
- * edac_device global list and create sysfs entries associated with
- * edac_device structure.
- * @edac_device: pointer to the edac_device structure to be added to the list
- * 'edac_device' structure.
- *
- * Return:
- *	0	Success
- *	!0	Failure
- */
 int edac_device_add_device(struct edac_device_ctl_info *edac_dev)
 {
 	edac_dbg(0, "\n");
@@ -541,19 +501,6 @@ fail0:
 }
 EXPORT_SYMBOL_GPL(edac_device_add_device);
 
-/**
- * edac_device_del_device:
- *	Remove sysfs entries for specified edac_device structure and
- *	then remove edac_device structure from global list
- *
- * @dev:
- *	Pointer to 'struct device' representing edac_device
- *	structure to remove.
- *
- * Return:
- *	Pointer to removed edac_device structure,
- *	OR NULL if device not found.
- */
 struct edac_device_ctl_info *edac_device_del_device(struct device *dev)
 {
 	struct edac_device_ctl_info *edac_dev;
@@ -608,10 +555,6 @@ static inline int edac_device_get_panic_
 	return edac_dev->panic_on_ue;
 }
 
-/*
- * edac_device_handle_ce
- *	perform a common output and handling of an 'edac_dev' CE event
- */
 void edac_device_handle_ce(struct edac_device_ctl_info *edac_dev,
 			int inst_nr, int block_nr, const char *msg)
 {
@@ -654,10 +597,6 @@ void edac_device_handle_ce(struct edac_d
 }
 EXPORT_SYMBOL_GPL(edac_device_handle_ce);
 
-/*
- * edac_device_handle_ue
- *	perform a common output and handling of an 'edac_dev' UE event
- */
 void edac_device_handle_ue(struct edac_device_ctl_info *edac_dev,
 			int inst_nr, int block_nr, const char *msg)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_device.h linux-libre-4.10-rc8-gnu/drivers/edac/edac_device.h
--- linux-libre-4.9-gnu/drivers/edac/edac_device.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_device.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,320 @@
+/*
+ * Defines, structures, APIs for edac_device
+ *
+ * (C) 2007 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ *	http://www.anime.net/~goemon/linux-ecc/
+ *
+ * NMI handling support added by
+ *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
+ *
+ * Refactored for multi-source files:
+ *	Doug Thompson <norsk5@xmission.com>
+ *
+ * Please look at Documentation/driver-api/edac.rst for more info about
+ * EDAC core structs and functions.
+ */
+
+#ifndef _EDAC_DEVICE_H_
+#define _EDAC_DEVICE_H_
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/edac.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/sysfs.h>
+#include <linux/workqueue.h>
+
+
+/*
+ * The following are the structures to provide for a generic
+ * or abstract 'edac_device'. This set of structures and the
+ * code that implements the APIs for the same, provide for
+ * registering EDAC type devices which are NOT standard memory.
+ *
+ * CPU caches (L1 and L2)
+ * DMA engines
+ * Core CPU switches
+ * Fabric switch units
+ * PCIe interface controllers
+ * other EDAC/ECC type devices that can be monitored for
+ * errors, etc.
+ *
+ * It allows for a 2 level set of hierarchy. For example:
+ *
+ * cache could be composed of L1, L2 and L3 levels of cache.
+ * Each CPU core would have its own L1 cache, while sharing
+ * L2 and maybe L3 caches.
+ *
+ * View them arranged, via the sysfs presentation:
+ * /sys/devices/system/edac/..
+ *
+ *	mc/		<existing memory device directory>
+ *	cpu/cpu0/..	<L1 and L2 block directory>
+ *		/L1-cache/ce_count
+ *			 /ue_count
+ *		/L2-cache/ce_count
+ *			 /ue_count
+ *	cpu/cpu1/..	<L1 and L2 block directory>
+ *		/L1-cache/ce_count
+ *			 /ue_count
+ *		/L2-cache/ce_count
+ *			 /ue_count
+ *	...
+ *
+ *	the L1 and L2 directories would be "edac_device_block's"
+ */
+
+struct edac_device_counter {
+	u32 ue_count;
+	u32 ce_count;
+};
+
+/* forward reference */
+struct edac_device_ctl_info;
+struct edac_device_block;
+
+/* edac_dev_sysfs_attribute structure
+ *	used for driver sysfs attributes in mem_ctl_info
+ *	for extra controls and attributes:
+ *		like high level error Injection controls
+ */
+struct edac_dev_sysfs_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct edac_device_ctl_info *, char *);
+	ssize_t (*store)(struct edac_device_ctl_info *, const char *, size_t);
+};
+
+/* edac_dev_sysfs_block_attribute structure
+ *
+ *	used in leaf 'block' nodes for adding controls/attributes
+ *
+ *	each block in each instance of the containing control structure
+ *	can have an array of the following. The show and store functions
+ *	will be filled in with the show/store function in the
+ *	low level driver.
+ *
+ *	The 'value' field will be the actual value field used for
+ *	counting
+ */
+struct edac_dev_sysfs_block_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct kobject *, struct attribute *, char *);
+	ssize_t (*store)(struct kobject *, struct attribute *,
+			const char *, size_t);
+	struct edac_device_block *block;
+
+	unsigned int value;
+};
+
+/* device block control structure */
+struct edac_device_block {
+	struct edac_device_instance *instance;	/* Up Pointer */
+	char name[EDAC_DEVICE_NAME_LEN + 1];
+
+	struct edac_device_counter counters;	/* basic UE and CE counters */
+
+	int nr_attribs;		/* how many attributes */
+
+	/* this block's attributes, could be NULL */
+	struct edac_dev_sysfs_block_attribute *block_attributes;
+
+	/* edac sysfs device control */
+	struct kobject kobj;
+};
+
+/* device instance control structure */
+struct edac_device_instance {
+	struct edac_device_ctl_info *ctl;	/* Up pointer */
+	char name[EDAC_DEVICE_NAME_LEN + 4];
+
+	struct edac_device_counter counters;	/* instance counters */
+
+	u32 nr_blocks;		/* how many blocks */
+	struct edac_device_block *blocks;	/* block array */
+
+	/* edac sysfs device control */
+	struct kobject kobj;
+};
+
+
+/*
+ * Abstract edac_device control info structure
+ *
+ */
+struct edac_device_ctl_info {
+	/* for global list of edac_device_ctl_info structs */
+	struct list_head link;
+
+	struct module *owner;	/* Module owner of this control struct */
+
+	int dev_idx;
+
+	/* Per instance controls for this edac_device */
+	int log_ue;		/* boolean for logging UEs */
+	int log_ce;		/* boolean for logging CEs */
+	int panic_on_ue;	/* boolean for panic'ing on an UE */
+	unsigned poll_msec;	/* number of milliseconds to poll interval */
+	unsigned long delay;	/* number of jiffies for poll_msec */
+
+	/* 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
+	 */
+	struct edac_dev_sysfs_attribute *sysfs_attributes;
+
+	/* pointer to main 'edac' subsys in sysfs */
+	struct bus_type *edac_subsys;
+
+	/* the internal state of this controller instance */
+	int op_state;
+	/* work struct for this instance */
+	struct delayed_work work;
+
+	/* pointer to edac polling checking routine:
+	 *      If NOT NULL: points to polling check routine
+	 *      If NULL: Then assumes INTERRUPT operation, where
+	 *              MC driver will receive events
+	 */
+	void (*edac_check) (struct edac_device_ctl_info * edac_dev);
+
+	struct device *dev;	/* pointer to device structure */
+
+	const char *mod_name;	/* module name */
+	const char *ctl_name;	/* edac controller  name */
+	const char *dev_name;	/* pci/platform/etc... name */
+
+	void *pvt_info;		/* pointer to 'private driver' info */
+
+	unsigned long start_time;	/* edac_device load start time (jiffies) */
+
+	struct completion removal_complete;
+
+	/* sysfs top name under 'edac' directory
+	 * and instance name:
+	 *      cpu/cpu0/...
+	 *      cpu/cpu1/...
+	 *      cpu/cpu2/...
+	 *      ...
+	 */
+	char name[EDAC_DEVICE_NAME_LEN + 1];
+
+	/* Number of instances supported on this control structure
+	 * and the array of those instances
+	 */
+	u32 nr_instances;
+	struct edac_device_instance *instances;
+
+	/* Event counters for the this whole EDAC Device */
+	struct edac_device_counter counters;
+
+	/* edac sysfs device control for the 'name'
+	 * device this structure controls
+	 */
+	struct kobject kobj;
+};
+
+/* To get from the instance's wq to the beginning of the ctl structure */
+#define to_edac_mem_ctl_work(w) \
+		container_of(w, struct mem_ctl_info, work)
+
+#define to_edac_device_ctl_work(w) \
+		container_of(w,struct edac_device_ctl_info,work)
+
+/*
+ * The alloc() and free() functions for the 'edac_device' control info
+ * structure. A MC driver will allocate one of these for each edac_device
+ * it is going to control/register with the EDAC CORE.
+ */
+extern struct edac_device_ctl_info *edac_device_alloc_ctl_info(
+		unsigned sizeof_private,
+		char *edac_device_name, unsigned nr_instances,
+		char *edac_block_name, unsigned nr_blocks,
+		unsigned offset_value,
+		struct edac_dev_sysfs_block_attribute *block_attributes,
+		unsigned nr_attribs,
+		int device_index);
+
+/* The offset value can be:
+ *	-1 indicating no offset value
+ *	0 for zero-based block numbers
+ *	1 for 1-based block number
+ *	other for other-based block number
+ */
+#define	BLOCK_OFFSET_VALUE_OFF	((unsigned) -1)
+
+extern void edac_device_free_ctl_info(struct edac_device_ctl_info *ctl_info);
+
+/**
+ * edac_device_add_device: Insert the 'edac_dev' structure into the
+ *	 edac_device global list and create sysfs entries associated with
+ *	 edac_device structure.
+ *
+ * @edac_dev: pointer to edac_device structure to be added to the list
+ *	'edac_device' structure.
+ *
+ * Returns:
+ *	0 on Success, or an error code on failure
+ */
+extern int edac_device_add_device(struct edac_device_ctl_info *edac_dev);
+
+/**
+ * edac_device_del_device:
+ *	Remove sysfs entries for specified edac_device structure and
+ *	then remove edac_device structure from global list
+ *
+ * @dev:
+ *	Pointer to struct &device representing the edac device
+ *	structure to remove.
+ *
+ * Returns:
+ *	Pointer to removed edac_device structure,
+ *	or %NULL if device not found.
+ */
+extern struct edac_device_ctl_info *edac_device_del_device(struct device *dev);
+
+/**
+ * edac_device_handle_ue():
+ *	perform a common output and handling of an 'edac_dev' UE event
+ *
+ * @edac_dev: pointer to struct &edac_device_ctl_info
+ * @inst_nr: number of the instance where the UE error happened
+ * @block_nr: number of the block where the UE error happened
+ * @msg: message to be printed
+ */
+extern void edac_device_handle_ue(struct edac_device_ctl_info *edac_dev,
+				int inst_nr, int block_nr, const char *msg);
+/**
+ * edac_device_handle_ce():
+ *	perform a common output and handling of an 'edac_dev' CE event
+ *
+ * @edac_dev: pointer to struct &edac_device_ctl_info
+ * @inst_nr: number of the instance where the CE error happened
+ * @block_nr: number of the block where the CE error happened
+ * @msg: message to be printed
+ */
+extern void edac_device_handle_ce(struct edac_device_ctl_info *edac_dev,
+				int inst_nr, int block_nr, const char *msg);
+
+/**
+ * edac_device_alloc_index: Allocate a unique device index number
+ *
+ * Returns:
+ *	allocated index number
+ */
+extern int edac_device_alloc_index(void);
+extern const char *edac_layer_name[];
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_device_sysfs.c linux-libre-4.10-rc8-gnu/drivers/edac/edac_device_sysfs.c
--- linux-libre-4.9-gnu/drivers/edac/edac_device_sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_device_sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * file for managing the edac_device subsystem of devices for EDAC
  *
- * (C) 2007 SoftwareBitMaker 
+ * (C) 2007 SoftwareBitMaker
  *
  * This file may be distributed under the terms of the
  * GNU General Public License.
@@ -15,7 +15,7 @@
 #include <linux/slab.h>
 #include <linux/edac.h>
 
-#include "edac_core.h"
+#include "edac_device.h"
 #include "edac_module.h"
 
 #define EDAC_DEVICE_SYMLINK	"device"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_mc.c linux-libre-4.10-rc8-gnu/drivers/edac/edac_mc.c
--- linux-libre-4.9-gnu/drivers/edac/edac_mc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_mc.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,9 +28,9 @@
 #include <linux/ctype.h>
 #include <linux/edac.h>
 #include <linux/bitops.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/page.h>
-#include "edac_core.h"
+#include "edac_mc.h"
 #include "edac_module.h"
 #include <ras/ras_event.h>
 
@@ -239,30 +239,6 @@ static void _edac_mc_free(struct mem_ctl
 	kfree(mci);
 }
 
-/**
- * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure
- * @mc_num:		Memory controller number
- * @n_layers:		Number of MC hierarchy layers
- * layers:		Describes each layer as seen by the Memory Controller
- * @size_pvt:		size of private storage needed
- *
- *
- * Everything is kmalloc'ed as one big chunk - more efficient.
- * Only can be used if all structures have the same lifetime - otherwise
- * you have to allocate and initialize your own structures.
- *
- * Use edac_mc_free() to free mc structures allocated by this function.
- *
- * NOTE: drivers handle multi-rank memories in different ways: in some
- * drivers, one multi-rank memory stick is mapped as one entry, while, in
- * others, a single multi-rank memory stick would be mapped into several
- * entries. Currently, this function will allocate multiple struct dimm_info
- * on such scenarios, as grouping the multiple ranks require drivers change.
- *
- * Returns:
- *	On failure: NULL
- *	On success: struct mem_ctl_info pointer
- */
 struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
 				   unsigned n_layers,
 				   struct edac_mc_layer *layers,
@@ -460,11 +436,6 @@ error:
 }
 EXPORT_SYMBOL_GPL(edac_mc_alloc);
 
-/**
- * edac_mc_free
- *	'Free' a previously allocated 'mci' structure
- * @mci: pointer to a struct mem_ctl_info structure
- */
 void edac_mc_free(struct mem_ctl_info *mci)
 {
 	edac_dbg(1, "\n");
@@ -482,15 +453,8 @@ void edac_mc_free(struct mem_ctl_info *m
 }
 EXPORT_SYMBOL_GPL(edac_mc_free);
 
-
-/**
- * find_mci_by_dev
- *
- *	scan list of controllers looking for the one that manages
- *	the 'dev' device
- * @dev: pointer to a struct device related with the MCI
- */
-struct mem_ctl_info *find_mci_by_dev(struct device *dev)
+/* Caller must hold mem_ctls_mutex */
+static struct mem_ctl_info *__find_mci_by_dev(struct device *dev)
 {
 	struct mem_ctl_info *mci;
 	struct list_head *item;
@@ -506,6 +470,24 @@ struct mem_ctl_info *find_mci_by_dev(str
 
 	return NULL;
 }
+
+/**
+ * find_mci_by_dev
+ *
+ *	scan list of controllers looking for the one that manages
+ *	the 'dev' device
+ * @dev: pointer to a struct device related with the MCI
+ */
+struct mem_ctl_info *find_mci_by_dev(struct device *dev)
+{
+	struct mem_ctl_info *ret;
+
+	mutex_lock(&mem_ctls_mutex);
+	ret = __find_mci_by_dev(dev);
+	mutex_unlock(&mem_ctls_mutex);
+
+	return ret;
+}
 EXPORT_SYMBOL_GPL(find_mci_by_dev);
 
 /*
@@ -588,7 +570,7 @@ static int add_mc_to_global_list(struct
 
 	insert_before = &mc_devices;
 
-	p = find_mci_by_dev(mci->pdev);
+	p = __find_mci_by_dev(mci->pdev);
 	if (unlikely(p != NULL))
 		goto fail0;
 
@@ -635,44 +617,30 @@ static int del_mc_from_global_list(struc
 	return handlers;
 }
 
-/**
- * edac_mc_find: Search for a mem_ctl_info structure whose index is 'idx'.
- *
- * If found, return a pointer to the structure.
- * Else return NULL.
- *
- * Caller must hold mem_ctls_mutex.
- */
 struct mem_ctl_info *edac_mc_find(int idx)
 {
+	struct mem_ctl_info *mci = NULL;
 	struct list_head *item;
-	struct mem_ctl_info *mci;
+
+	mutex_lock(&mem_ctls_mutex);
 
 	list_for_each(item, &mc_devices) {
 		mci = list_entry(item, struct mem_ctl_info, link);
 
 		if (mci->mc_idx >= idx) {
-			if (mci->mc_idx == idx)
-				return mci;
-
+			if (mci->mc_idx == idx) {
+				goto unlock;
+			}
 			break;
 		}
 	}
 
-	return NULL;
+unlock:
+	mutex_unlock(&mem_ctls_mutex);
+	return mci;
 }
 EXPORT_SYMBOL(edac_mc_find);
 
-/**
- * edac_mc_add_mc_with_groups: Insert the 'mci' structure into the mci
- *	global list and create sysfs entries associated with mci structure
- * @mci: pointer to the mci structure to be added to the list
- * @groups: optional attribute groups for the driver-specific sysfs entries
- *
- * Return:
- *	0	Success
- *	!0	Failure
- */
 
 /* FIXME - should a warning be printed if no error detection? correction? */
 int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
@@ -763,13 +731,6 @@ fail0:
 }
 EXPORT_SYMBOL_GPL(edac_mc_add_mc_with_groups);
 
-/**
- * edac_mc_del_mc: Remove sysfs entries for specified mci structure and
- *                 remove mci structure from global list
- * @pdev: Pointer to 'struct device' representing mci structure to remove.
- *
- * Return pointer to removed mci structure, or NULL if device not found.
- */
 struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
 {
 	struct mem_ctl_info *mci;
@@ -779,7 +740,7 @@ struct mem_ctl_info *edac_mc_del_mc(stru
 	mutex_lock(&mem_ctls_mutex);
 
 	/* find the requested mci struct in the global list */
-	mci = find_mci_by_dev(dev);
+	mci = __find_mci_by_dev(dev);
 	if (mci == NULL) {
 		mutex_unlock(&mem_ctls_mutex);
 		return NULL;
@@ -1033,18 +994,6 @@ static void edac_ue_error(struct mem_ctl
 	edac_inc_ue_error(mci, enable_per_layer_report, pos, error_count);
 }
 
-/**
- * edac_raw_mc_handle_error - reports a memory event to userspace without doing
- *			      anything to discover the error location
- *
- * @type:		severity of the error (CE/UE/Fatal)
- * @mci:		a struct mem_ctl_info pointer
- * @e:			error description
- *
- * This raw function is used internally by edac_mc_handle_error(). It should
- * only be called directly when the hardware error come directly from BIOS,
- * like in the case of APEI GHES driver.
- */
 void edac_raw_mc_handle_error(const enum hw_event_mc_err_type type,
 			      struct mem_ctl_info *mci,
 			      struct edac_raw_error_desc *e)
@@ -1074,24 +1023,6 @@ void edac_raw_mc_handle_error(const enum
 }
 EXPORT_SYMBOL_GPL(edac_raw_mc_handle_error);
 
-/**
- * edac_mc_handle_error - reports a memory event to userspace
- *
- * @type:		severity of the error (CE/UE/Fatal)
- * @mci:		a struct mem_ctl_info pointer
- * @error_count:	Number of errors of the same type
- * @page_frame_number:	mem page where the error occurred
- * @offset_in_page:	offset of the error inside the page
- * @syndrome:		ECC syndrome
- * @top_layer:		Memory layer[0] position
- * @mid_layer:		Memory layer[1] position
- * @low_layer:		Memory layer[2] position
- * @msg:		Message meaningful to the end users that
- *			explains the event
- * @other_detail:	Technical details about the event that
- *			may help hardware manufacturers and
- *			EDAC developers to analyse the event
- */
 void edac_mc_handle_error(const enum hw_event_mc_err_type type,
 			  struct mem_ctl_info *mci,
 			  const u16 error_count,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_mc.h linux-libre-4.10-rc8-gnu/drivers/edac/edac_mc.h
--- linux-libre-4.9-gnu/drivers/edac/edac_mc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_mc.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,245 @@
+/*
+ * Defines, structures, APIs for edac_mc module
+ *
+ * (C) 2007 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ *	http://www.anime.net/~goemon/linux-ecc/
+ *
+ * NMI handling support added by
+ *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
+ *
+ * Refactored for multi-source files:
+ *	Doug Thompson <norsk5@xmission.com>
+ *
+ * Please look at Documentation/driver-api/edac.rst for more info about
+ * EDAC core structs and functions.
+ */
+
+#ifndef _EDAC_MC_H_
+#define _EDAC_MC_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/nmi.h>
+#include <linux/rcupdate.h>
+#include <linux/completion.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/edac.h>
+
+#if PAGE_SHIFT < 20
+#define PAGES_TO_MiB(pages)	((pages) >> (20 - PAGE_SHIFT))
+#define MiB_TO_PAGES(mb)	((mb) << (20 - PAGE_SHIFT))
+#else				/* PAGE_SHIFT > 20 */
+#define PAGES_TO_MiB(pages)	((pages) << (PAGE_SHIFT - 20))
+#define MiB_TO_PAGES(mb)	((mb) >> (PAGE_SHIFT - 20))
+#endif
+
+#define edac_printk(level, prefix, fmt, arg...) \
+	printk(level "EDAC " prefix ": " fmt, ##arg)
+
+#define edac_mc_printk(mci, level, fmt, arg...) \
+	printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg)
+
+#define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \
+	printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg)
+
+#define edac_device_printk(ctl, level, fmt, arg...) \
+	printk(level "EDAC DEVICE%d: " fmt, ctl->dev_idx, ##arg)
+
+#define edac_pci_printk(ctl, level, fmt, arg...) \
+	printk(level "EDAC PCI%d: " fmt, ctl->pci_idx, ##arg)
+
+/* prefixes for edac_printk() and edac_mc_printk() */
+#define EDAC_MC "MC"
+#define EDAC_PCI "PCI"
+#define EDAC_DEBUG "DEBUG"
+
+extern const char * const edac_mem_types[];
+
+#ifdef CONFIG_EDAC_DEBUG
+extern int edac_debug_level;
+
+#define edac_dbg(level, fmt, ...)					\
+do {									\
+	if (level <= edac_debug_level)					\
+		edac_printk(KERN_DEBUG, EDAC_DEBUG,			\
+			    "%s: " fmt, __func__, ##__VA_ARGS__);	\
+} while (0)
+
+#else				/* !CONFIG_EDAC_DEBUG */
+
+#define edac_dbg(level, fmt, ...)					\
+do {									\
+	if (0)								\
+		edac_printk(KERN_DEBUG, EDAC_DEBUG,			\
+			    "%s: " fmt, __func__, ##__VA_ARGS__);	\
+} while (0)
+
+#endif				/* !CONFIG_EDAC_DEBUG */
+
+#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \
+	PCI_DEVICE_ID_ ## vend ## _ ## dev
+
+#define edac_dev_name(dev) (dev)->dev_name
+
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/**
+ * edac_mc_alloc() - Allocate and partially fill a struct &mem_ctl_info.
+ *
+ * @mc_num:		Memory controller number
+ * @n_layers:		Number of MC hierarchy layers
+ * @layers:		Describes each layer as seen by the Memory Controller
+ * @sz_pvt:		size of private storage needed
+ *
+ *
+ * Everything is kmalloc'ed as one big chunk - more efficient.
+ * Only can be used if all structures have the same lifetime - otherwise
+ * you have to allocate and initialize your own structures.
+ *
+ * Use edac_mc_free() to free mc structures allocated by this function.
+ *
+ * .. note::
+ *
+ *   drivers handle multi-rank memories in different ways: in some
+ *   drivers, one multi-rank memory stick is mapped as one entry, while, in
+ *   others, a single multi-rank memory stick would be mapped into several
+ *   entries. Currently, this function will allocate multiple struct dimm_info
+ *   on such scenarios, as grouping the multiple ranks require drivers change.
+ *
+ * Returns:
+ *	On success, return a pointer to struct mem_ctl_info pointer;
+ *	%NULL otherwise
+ */
+struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
+				   unsigned n_layers,
+				   struct edac_mc_layer *layers,
+				   unsigned sz_pvt);
+
+/**
+ * edac_mc_add_mc_with_groups() - Insert the @mci structure into the mci
+ *	global list and create sysfs entries associated with @mci structure.
+ *
+ * @mci: pointer to the mci structure to be added to the list
+ * @groups: optional attribute groups for the driver-specific sysfs entries
+ *
+ * Returns:
+ *	0 on Success, or an error code on failure
+ */
+extern int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
+				      const struct attribute_group **groups);
+#define edac_mc_add_mc(mci)	edac_mc_add_mc_with_groups(mci, NULL)
+
+/**
+ * edac_mc_free() -  Frees a previously allocated @mci structure
+ *
+ * @mci: pointer to a struct mem_ctl_info structure
+ */
+extern void edac_mc_free(struct mem_ctl_info *mci);
+
+/**
+ * edac_mc_find() - Search for a mem_ctl_info structure whose index is @idx.
+ *
+ * @idx: index to be seek
+ *
+ * If found, return a pointer to the structure.
+ * Else return NULL.
+ */
+extern struct mem_ctl_info *edac_mc_find(int idx);
+
+/**
+ * find_mci_by_dev() - Scan list of controllers looking for the one that
+ *	manages the @dev device.
+ *
+ * @dev: pointer to a struct device related with the MCI
+ *
+ * Returns: on success, returns a pointer to struct &mem_ctl_info;
+ * %NULL otherwise.
+ */
+extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);
+
+/**
+ * edac_mc_del_mc() - Remove sysfs entries for mci structure associated with
+ *	@dev and remove mci structure from global list.
+ *
+ * @dev: Pointer to struct &device representing mci structure to remove.
+ *
+ * Returns: pointer to removed mci structure, or %NULL if device not found.
+ */
+extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev);
+
+/**
+ * edac_mc_find_csrow_by_page() - Ancillary routine to identify what csrow
+ *	contains a memory page.
+ *
+ * @mci: pointer to a struct mem_ctl_info structure
+ * @page: memory page to find
+ *
+ * Returns: on success, returns the csrow. -1 if not found.
+ */
+extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
+				      unsigned long page);
+
+/**
+ * edac_raw_mc_handle_error() - Reports a memory event to userspace without
+ *	doing anything to discover the error location.
+ *
+ * @type:		severity of the error (CE/UE/Fatal)
+ * @mci:		a struct mem_ctl_info pointer
+ * @e:			error description
+ *
+ * This raw function is used internally by edac_mc_handle_error(). It should
+ * only be called directly when the hardware error come directly from BIOS,
+ * like in the case of APEI GHES driver.
+ */
+void edac_raw_mc_handle_error(const enum hw_event_mc_err_type type,
+			      struct mem_ctl_info *mci,
+			      struct edac_raw_error_desc *e);
+
+/**
+ * edac_mc_handle_error() - Reports a memory event to userspace.
+ *
+ * @type:		severity of the error (CE/UE/Fatal)
+ * @mci:		a struct mem_ctl_info pointer
+ * @error_count:	Number of errors of the same type
+ * @page_frame_number:	mem page where the error occurred
+ * @offset_in_page:	offset of the error inside the page
+ * @syndrome:		ECC syndrome
+ * @top_layer:		Memory layer[0] position
+ * @mid_layer:		Memory layer[1] position
+ * @low_layer:		Memory layer[2] position
+ * @msg:		Message meaningful to the end users that
+ *			explains the event
+ * @other_detail:	Technical details about the event that
+ *			may help hardware manufacturers and
+ *			EDAC developers to analyse the event
+ */
+void edac_mc_handle_error(const enum hw_event_mc_err_type type,
+			  struct mem_ctl_info *mci,
+			  const u16 error_count,
+			  const unsigned long page_frame_number,
+			  const unsigned long offset_in_page,
+			  const unsigned long syndrome,
+			  const int top_layer,
+			  const int mid_layer,
+			  const int low_layer,
+			  const char *msg,
+			  const char *other_detail);
+
+/*
+ * edac misc APIs
+ */
+extern char *edac_op_state_to_string(int op_state);
+
+#endif				/* _EDAC_MC_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_mc_sysfs.c linux-libre-4.10-rc8-gnu/drivers/edac/edac_mc_sysfs.c
--- linux-libre-4.9-gnu/drivers/edac/edac_mc_sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_mc_sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/uaccess.h>
 
-#include "edac_core.h"
+#include "edac_mc.h"
 #include "edac_module.h"
 
 /* MC EDAC Controls, setable by module parameter, and sysfs */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_module.c linux-libre-4.10-rc8-gnu/drivers/edac/edac_module.c
--- linux-libre-4.9-gnu/drivers/edac/edac_module.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_module.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
  */
 #include <linux/edac.h>
 
-#include "edac_core.h"
+#include "edac_mc.h"
 #include "edac_module.h"
 
 #define EDAC_VERSION "Ver: 3.0.0"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_module.h linux-libre-4.10-rc8-gnu/drivers/edac/edac_module.h
--- linux-libre-4.9-gnu/drivers/edac/edac_module.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_module.h	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,9 @@
 #ifndef	__EDAC_MODULE_H__
 #define	__EDAC_MODULE_H__
 
-#include "edac_core.h"
+#include "edac_mc.h"
+#include "edac_pci.h"
+#include "edac_device.h"
 
 /*
  * INTERNAL EDAC MODULE:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_pci.c linux-libre-4.10-rc8-gnu/drivers/edac/edac_pci.c
--- linux-libre-4.9-gnu/drivers/edac/edac_pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,35 +9,25 @@
  * or implied.
  *
  */
+#include <asm/page.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+#include <linux/highmem.h>
+#include <linux/init.h>
 #include <linux/module.h>
-#include <linux/types.h>
+#include <linux/slab.h>
 #include <linux/smp.h>
-#include <linux/init.h>
+#include <linux/spinlock.h>
 #include <linux/sysctl.h>
-#include <linux/highmem.h>
 #include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/ctype.h>
-#include <linux/workqueue.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
 
-#include "edac_core.h"
+#include "edac_pci.h"
 #include "edac_module.h"
 
 static DEFINE_MUTEX(edac_pci_ctls_mutex);
 static LIST_HEAD(edac_pci_list);
 static atomic_t pci_indexes = ATOMIC_INIT(0);
 
-/*
- * edac_pci_alloc_ctl_info
- *
- *	The alloc() function for the 'edac_pci' control info
- *	structure. The chip driver will allocate one of these for each
- *	edac_pci it is going to control/register with the EDAC CORE.
- */
 struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
 						const char *edac_pci_name)
 {
@@ -68,16 +58,6 @@ struct edac_pci_ctl_info *edac_pci_alloc
 }
 EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info);
 
-/*
- * edac_pci_free_ctl_info()
- *
- *	Last action on the pci control structure.
- *
- *	call the remove sysfs information, which will unregister
- *	this control struct's kobj. When that kobj's ref count
- *	goes to zero, its release function will be call and then
- *	kfree() the memory.
- */
 void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci)
 {
 	edac_dbg(1, "\n");
@@ -215,31 +195,12 @@ static void edac_pci_workq_function(stru
 	mutex_unlock(&edac_pci_ctls_mutex);
 }
 
-/*
- * edac_pci_alloc_index: Allocate a unique PCI index number
- *
- * Return:
- *      allocated index number
- *
- */
 int edac_pci_alloc_index(void)
 {
 	return atomic_inc_return(&pci_indexes) - 1;
 }
 EXPORT_SYMBOL_GPL(edac_pci_alloc_index);
 
-/*
- * edac_pci_add_device: Insert the 'edac_dev' structure into the
- * edac_pci global list and create sysfs entries associated with
- * edac_pci structure.
- * @pci: pointer to the edac_device structure to be added to the list
- * @edac_idx: A unique numeric identifier to be assigned to the
- * 'edac_pci' structure.
- *
- * Return:
- *      0       Success
- *      !0      Failure
- */
 int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
 {
 	edac_dbg(0, "\n");
@@ -285,19 +246,6 @@ fail0:
 }
 EXPORT_SYMBOL_GPL(edac_pci_add_device);
 
-/*
- * edac_pci_del_device()
- * 	Remove sysfs entries for specified edac_pci structure and
- * 	then remove edac_pci structure from global list
- *
- * @dev:
- * 	Pointer to 'struct device' representing edac_pci structure
- * 	to remove
- *
- * Return:
- * 	Pointer to removed edac_pci structure,
- * 	or NULL if device not found
- */
 struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
 {
 	struct edac_pci_ctl_info *pci;
@@ -351,17 +299,6 @@ struct edac_pci_gen_data {
 	int edac_idx;
 };
 
-/*
- * edac_pci_create_generic_ctl
- *
- *	A generic constructor for a PCI parity polling device
- *	Some systems have more than one domain of PCI busses.
- *	For systems with one domain, then this API will
- *	provide for a generic poller.
- *
- *	This routine calls the edac_pci_alloc_ctl_info() for
- *	the generic device, with default values
- */
 struct edac_pci_ctl_info *edac_pci_create_generic_ctl(struct device *dev,
 						const char *mod_name)
 {
@@ -394,11 +331,6 @@ struct edac_pci_ctl_info *edac_pci_creat
 }
 EXPORT_SYMBOL_GPL(edac_pci_create_generic_ctl);
 
-/*
- * edac_pci_release_generic_ctl
- *
- *	The release function of a generic EDAC PCI polling device
- */
 void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci)
 {
 	edac_dbg(0, "pci mod=%s\n", pci->mod_name);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_pci.h linux-libre-4.10-rc8-gnu/drivers/edac/edac_pci.h
--- linux-libre-4.9-gnu/drivers/edac/edac_pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_pci.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,271 @@
+/*
+ * Defines, structures, APIs for edac_pci and edac_pci_sysfs
+ *
+ * (C) 2007 Linux Networx (http://lnxi.com)
+ * This file may be distributed under the terms of the
+ * GNU General Public License.
+ *
+ * Written by Thayne Harbaugh
+ * Based on work by Dan Hollis <goemon at anime dot net> and others.
+ *	http://www.anime.net/~goemon/linux-ecc/
+ *
+ * NMI handling support added by
+ *     Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
+ *
+ * Refactored for multi-source files:
+ *	Doug Thompson <norsk5@xmission.com>
+ *
+ * Please look at Documentation/driver-api/edac.rst for more info about
+ * EDAC core structs and functions.
+ */
+
+#ifndef _EDAC_PCI_H_
+#define _EDAC_PCI_H_
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/edac.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#ifdef CONFIG_PCI
+
+struct edac_pci_counter {
+	atomic_t pe_count;
+	atomic_t npe_count;
+};
+
+/*
+ * Abstract edac_pci control info structure
+ *
+ */
+struct edac_pci_ctl_info {
+	/* for global list of edac_pci_ctl_info structs */
+	struct list_head link;
+
+	int pci_idx;
+
+	struct bus_type *edac_subsys;	/* pointer to subsystem */
+
+	/* the internal state of this controller instance */
+	int op_state;
+	/* work struct for this instance */
+	struct delayed_work work;
+
+	/* pointer to edac polling checking routine:
+	 *      If NOT NULL: points to polling check routine
+	 *      If NULL: Then assumes INTERRUPT operation, where
+	 *              MC driver will receive events
+	 */
+	void (*edac_check) (struct edac_pci_ctl_info * edac_dev);
+
+	struct device *dev;	/* pointer to device structure */
+
+	const char *mod_name;	/* module name */
+	const char *ctl_name;	/* edac controller  name */
+	const char *dev_name;	/* pci/platform/etc... name */
+
+	void *pvt_info;		/* pointer to 'private driver' info */
+
+	unsigned long start_time;	/* edac_pci load start time (jiffies) */
+
+	struct completion complete;
+
+	/* sysfs top name under 'edac' directory
+	 * and instance name:
+	 *      cpu/cpu0/...
+	 *      cpu/cpu1/...
+	 *      cpu/cpu2/...
+	 *      ...
+	 */
+	char name[EDAC_DEVICE_NAME_LEN + 1];
+
+	/* Event counters for the this whole EDAC Device */
+	struct edac_pci_counter counters;
+
+	/* edac sysfs device control for the 'name'
+	 * device this structure controls
+	 */
+	struct kobject kobj;
+};
+
+#define to_edac_pci_ctl_work(w) \
+		container_of(w, struct edac_pci_ctl_info,work)
+
+/* write all or some bits in a byte-register*/
+static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
+				   u8 mask)
+{
+	if (mask != 0xff) {
+		u8 buf;
+
+		pci_read_config_byte(pdev, offset, &buf);
+		value &= mask;
+		buf &= ~mask;
+		value |= buf;
+	}
+
+	pci_write_config_byte(pdev, offset, value);
+}
+
+/* write all or some bits in a word-register*/
+static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
+				    u16 value, u16 mask)
+{
+	if (mask != 0xffff) {
+		u16 buf;
+
+		pci_read_config_word(pdev, offset, &buf);
+		value &= mask;
+		buf &= ~mask;
+		value |= buf;
+	}
+
+	pci_write_config_word(pdev, offset, value);
+}
+
+/*
+ * pci_write_bits32
+ *
+ * edac local routine to do pci_write_config_dword, but adds
+ * a mask parameter. If mask is all ones, ignore the mask.
+ * Otherwise utilize the mask to isolate specified bits
+ *
+ * write all or some bits in a dword-register
+ */
+static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
+				    u32 value, u32 mask)
+{
+	if (mask != 0xffffffff) {
+		u32 buf;
+
+		pci_read_config_dword(pdev, offset, &buf);
+		value &= mask;
+		buf &= ~mask;
+		value |= buf;
+	}
+
+	pci_write_config_dword(pdev, offset, value);
+}
+
+#endif				/* CONFIG_PCI */
+
+/*
+ * edac_pci APIs
+ */
+
+/**
+ * edac_pci_alloc_ctl_info:
+ *	The alloc() function for the 'edac_pci' control info
+ *	structure.
+ *
+ * @sz_pvt: size of the private info at struct &edac_pci_ctl_info
+ * @edac_pci_name: name of the PCI device
+ *
+ * The chip driver will allocate one of these for each
+ * edac_pci it is going to control/register with the EDAC CORE.
+ *
+ * Returns: a pointer to struct &edac_pci_ctl_info on success; %NULL otherwise.
+ */
+extern struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
+				const char *edac_pci_name);
+
+/**
+ * edac_pci_free_ctl_info():
+ *	Last action on the pci control structure.
+ *
+ * @pci: pointer to struct &edac_pci_ctl_info
+ *
+ * Calls the remove sysfs information, which will unregister
+ * this control struct's kobj. When that kobj's ref count
+ * goes to zero, its release function will be call and then
+ * kfree() the memory.
+ */
+extern void edac_pci_free_ctl_info(struct edac_pci_ctl_info *pci);
+
+/**
+ * edac_pci_alloc_index: Allocate a unique PCI index number
+ *
+ * Returns:
+ *      allocated index number
+ *
+ */
+extern int edac_pci_alloc_index(void);
+
+/**
+ * edac_pci_add_device(): Insert the 'edac_dev' structure into the
+ *	edac_pci global list and create sysfs entries associated with
+ *	edac_pci structure.
+ *
+ * @pci: pointer to the edac_device structure to be added to the list
+ * @edac_idx: A unique numeric identifier to be assigned to the
+ *	'edac_pci' structure.
+ *
+ * Returns:
+ *	0 on Success, or an error code on failure
+ */
+extern int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx);
+
+/**
+ * edac_pci_del_device()
+ *	Remove sysfs entries for specified edac_pci structure and
+ *	then remove edac_pci structure from global list
+ *
+ * @dev:
+ *	Pointer to 'struct device' representing edac_pci structure
+ *	to remove
+ *
+ * Returns:
+ *	Pointer to removed edac_pci structure,
+ *	or %NULL if device not found
+ */
+extern struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev);
+
+/**
+ * edac_pci_create_generic_ctl()
+ *	A generic constructor for a PCI parity polling device
+ *	Some systems have more than one domain of PCI busses.
+ *	For systems with one domain, then this API will
+ *	provide for a generic poller.
+ *
+ * @dev: pointer to struct &device;
+ * @mod_name: name of the PCI device
+ *
+ * This routine calls the edac_pci_alloc_ctl_info() for
+ * the generic device, with default values
+ *
+ * Returns: Pointer to struct &edac_pci_ctl_info on success, %NULL on
+ *	failure.
+ */
+extern struct edac_pci_ctl_info *edac_pci_create_generic_ctl(
+				struct device *dev,
+				const char *mod_name);
+
+/**
+ * edac_pci_release_generic_ctl
+ *	The release function of a generic EDAC PCI polling device
+ *
+ * @pci: pointer to struct &edac_pci_ctl_info
+ */
+extern void edac_pci_release_generic_ctl(struct edac_pci_ctl_info *pci);
+
+/**
+ * edac_pci_create_sysfs
+ *	Create the controls/attributes for the specified EDAC PCI device
+ *
+ * @pci: pointer to struct &edac_pci_ctl_info
+ */
+extern int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci);
+
+/**
+ * edac_pci_remove_sysfs()
+ *	remove the controls and attributes for this EDAC PCI device
+ *
+ * @pci: pointer to struct &edac_pci_ctl_info
+ */
+extern void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/edac_pci_sysfs.c linux-libre-4.10-rc8-gnu/drivers/edac/edac_pci_sysfs.c
--- linux-libre-4.9-gnu/drivers/edac/edac_pci_sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/edac_pci_sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/slab.h>
 #include <linux/ctype.h>
 
-#include "edac_core.h"
+#include "edac_pci.h"
 #include "edac_module.h"
 
 #define EDAC_PCI_SYMLINK	"device"
@@ -418,12 +418,6 @@ static void edac_pci_main_kobj_teardown(
 	}
 }
 
-/*
- *
- * edac_pci_create_sysfs
- *
- *	Create the controls/attributes for the specified EDAC PCI device
- */
 int edac_pci_create_sysfs(struct edac_pci_ctl_info *pci)
 {
 	int err;
@@ -459,11 +453,6 @@ unregister_cleanup:
 	return err;
 }
 
-/*
- * edac_pci_remove_sysfs
- *
- *	remove the controls and attributes for this EDAC PCI device
- */
 void edac_pci_remove_sysfs(struct edac_pci_ctl_info *pci)
 {
 	edac_dbg(0, "index=%d\n", pci->pci_idx);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/fsl_ddr_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/fsl_ddr_edac.c
--- linux-libre-4.9-gnu/drivers/edac/fsl_ddr_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/fsl_ddr_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,6 @@
 #include <linux/of_device.h>
 #include <linux/of_address.h>
 #include "edac_module.h"
-#include "edac_core.h"
 #include "fsl_ddr_edac.h"
 
 #define EDAC_MOD_STR	"fsl_ddr_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/ghes_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/ghes_edac.c
--- linux-libre-4.9-gnu/drivers/edac/ghes_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/ghes_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <acpi/ghes.h>
 #include <linux/edac.h>
 #include <linux/dmi.h>
-#include "edac_core.h"
+#include "edac_module.h"
 #include <ras/ras_event.h>
 
 #define GHES_EDAC_REVISION " Ver: 1.0.0"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/highbank_l2_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/highbank_l2_edac.c
--- linux-libre-4.9-gnu/drivers/edac/highbank_l2_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/highbank_l2_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,6 @@
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 #define SR_CLR_SB_ECC_INTR	0x0
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/highbank_mc_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/highbank_mc_edac.c
--- linux-libre-4.9-gnu/drivers/edac/highbank_mc_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/highbank_mc_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
 #include <linux/of_platform.h>
 #include <linux/uaccess.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 /* DDR Ctrlr Error Registers */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i3000_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i3000_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i3000_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i3000_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define I3000_REVISION		"1.1"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i3200_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i3200_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i3200_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i3200_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
 #include <linux/io.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #include <linux/io-64-nonatomic-lo-hi.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i5000_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i5000_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i5000_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i5000_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,7 @@
 #include <linux/edac.h>
 #include <asm/mmzone.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 /*
  * Alter this version for the I5000 module when modifications are made
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i5100_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i5100_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i5100_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i5100_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,6 @@
 #include <linux/mmzone.h>
 #include <linux/debugfs.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 /* register addresses */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i5400_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i5400_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i5400_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i5400_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <linux/edac.h>
 #include <linux/mmzone.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 /*
  * Alter this version for the I5400 module when modifications are made
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i7300_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i7300_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i7300_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i7300_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/edac.h>
 #include <linux/mmzone.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 /*
  * Alter this version for the I7300 module when modifications are made
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i7core_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i7core_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i7core_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i7core_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@
 #include <asm/processor.h>
 #include <asm/div64.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 /* Static vars */
 static LIST_HEAD(i7core_edac_list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i82443bxgx_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i82443bxgx_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i82443bxgx_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i82443bxgx_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 
 
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define I82443_REVISION	"0.1"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i82860_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i82860_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i82860_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i82860_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define  I82860_REVISION " Ver: 2.0.2"
 #define EDAC_MOD_STR	"i82860_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i82875p_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i82875p_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i82875p_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i82875p_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define I82875P_REVISION	" Ver: 2.0.2"
 #define EDAC_MOD_STR		"i82875p_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/i82975x_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/i82975x_edac.c
--- linux-libre-4.9-gnu/drivers/edac/i82975x_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/i82975x_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define I82975X_REVISION	" Ver: 1.0.0"
 #define EDAC_MOD_STR		"i82975x_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/ie31200_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/ie31200_edac.c
--- linux-libre-4.9-gnu/drivers/edac/ie31200_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/ie31200_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@
 #include <linux/edac.h>
 
 #include <linux/io-64-nonatomic-lo-hi.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define IE31200_REVISION "1.0"
 #define EDAC_MOD_STR "ie31200_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/layerscape_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/layerscape_edac.c
--- linux-libre-4.9-gnu/drivers/edac/layerscape_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/layerscape_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include "edac_core.h"
+#include "edac_module.h"
 #include "fsl_ddr_edac.h"
 
 static const struct of_device_id fsl_ddr_mc_err_of_match[] = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/mce_amd.c linux-libre-4.10-rc8-gnu/drivers/edac/mce_amd.c
--- linux-libre-4.9-gnu/drivers/edac/mce_amd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/mce_amd.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@ static struct amd_decoder_ops *fam_ops;
 static u8 xec_mask	 = 0xf;
 
 static bool report_gart_errors;
-static void (*nb_bus_decoder)(int node_id, struct mce *m);
+static void (*decode_dram_ecc)(int node_id, struct mce *m);
 
 void amd_report_gart_errors(bool v)
 {
@@ -18,16 +18,16 @@ EXPORT_SYMBOL_GPL(amd_report_gart_errors
 
 void amd_register_ecc_decoder(void (*f)(int, struct mce *))
 {
-	nb_bus_decoder = f;
+	decode_dram_ecc = f;
 }
 EXPORT_SYMBOL_GPL(amd_register_ecc_decoder);
 
 void amd_unregister_ecc_decoder(void (*f)(int, struct mce *))
 {
-	if (nb_bus_decoder) {
-		WARN_ON(nb_bus_decoder != f);
+	if (decode_dram_ecc) {
+		WARN_ON(decode_dram_ecc != f);
 
-		nb_bus_decoder = NULL;
+		decode_dram_ecc = NULL;
 	}
 }
 EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder);
@@ -763,8 +763,8 @@ static void decode_mc4_mce(struct mce *m
 
 			pr_cont("%s.\n", mc4_mce_desc[xec]);
 
-			if (nb_bus_decoder)
-				nb_bus_decoder(node_id, m);
+			if (decode_dram_ecc)
+				decode_dram_ecc(node_id, m);
 			return;
 		}
 		break;
@@ -851,7 +851,7 @@ static void decode_mc6_mce(struct mce *m
 /* Decode errors according to Scalable MCA specification */
 static void decode_smca_errors(struct mce *m)
 {
-	struct smca_hwid_mcatype *type;
+	struct smca_hwid *hwid;
 	unsigned int bank_type;
 	const char *ip_name;
 	u8 xec = XEC(m->status, xec_mask);
@@ -862,21 +862,28 @@ static void decode_smca_errors(struct mc
 	if (boot_cpu_data.x86 >= 0x17 && m->bank == 4)
 		pr_emerg(HW_ERR "Bank 4 is reserved on Fam17h.\n");
 
-	type = smca_banks[m->bank].type;
-	if (!type)
+	hwid = smca_banks[m->bank].hwid;
+	if (!hwid)
 		return;
 
-	bank_type = type->bank_type;
-	ip_name = smca_bank_names[bank_type].long_name;
+	bank_type = hwid->bank_type;
+	ip_name = smca_get_long_name(bank_type);
 
 	pr_emerg(HW_ERR "%s Extended Error Code: %d\n", ip_name, xec);
 
 	/* Only print the decode of valid error codes */
 	if (xec < smca_mce_descs[bank_type].num_descs &&
-			(type->xec_bitmap & BIT_ULL(xec))) {
+			(hwid->xec_bitmap & BIT_ULL(xec))) {
 		pr_emerg(HW_ERR "%s Error: ", ip_name);
 		pr_cont("%s.\n", smca_mce_descs[bank_type].descs[xec]);
 	}
+
+	/*
+	 * amd_get_nb_id() returns the last level cache id.
+	 * The last level cache on Fam17h is 1 level below the node.
+	 */
+	if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc)
+		decode_dram_ecc(amd_get_nb_id(m->extcpu) >> 1, m);
 }
 
 static inline void amd_decode_err_code(u16 ec)
@@ -957,10 +964,13 @@ int amd_decode_mce(struct notifier_block
 		((m->status & MCI_STATUS_PCC)	? "PCC"	  : "-"),
 		((m->status & MCI_STATUS_ADDRV)	? "AddrV" : "-"));
 
-	if (c->x86 >= 0x15)
-		pr_cont("|%s|%s",
-			((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"),
-			((m->status & MCI_STATUS_POISON)   ? "Poison"   : "-"));
+	if (c->x86 >= 0x15) {
+		pr_cont("|%s", (m->status & MCI_STATUS_DEFERRED ? "Deferred" : "-"));
+
+		/* F15h, bank4, bit 43 is part of McaStatSubCache. */
+		if (c->x86 != 0x15 || m->bank != 4)
+			pr_cont("|%s", (m->status & MCI_STATUS_POISON ? "Poison" : "-"));
+	}
 
 	if (boot_cpu_has(X86_FEATURE_SMCA)) {
 		u32 low, high;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/mpc85xx_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/mpc85xx_edac.c
--- linux-libre-4.9-gnu/drivers/edac/mpc85xx_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/mpc85xx_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,6 @@
 #include <linux/of_platform.h>
 #include <linux/of_device.h>
 #include "edac_module.h"
-#include "edac_core.h"
 #include "mpc85xx_edac.h"
 #include "fsl_ddr_edac.h"
 
@@ -300,6 +299,22 @@ err:
 	return res;
 }
 
+static int mpc85xx_pci_err_remove(struct platform_device *op)
+{
+	struct edac_pci_ctl_info *pci = dev_get_drvdata(&op->dev);
+	struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
+
+	edac_dbg(0, "\n");
+
+	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR, orig_pci_err_cap_dr);
+	out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en);
+
+	edac_pci_del_device(&op->dev);
+	edac_pci_free_ctl_info(pci);
+
+	return 0;
+}
+
 static const struct platform_device_id mpc85xx_pci_err_match[] = {
 	{
 		.name = "mpc85xx-pci-edac"
@@ -309,6 +324,7 @@ static const struct platform_device_id m
 
 static struct platform_driver mpc85xx_pci_err_driver = {
 	.probe = mpc85xx_pci_err_probe,
+	.remove = mpc85xx_pci_err_remove,
 	.id_table = mpc85xx_pci_err_match,
 	.driver = {
 		.name = "mpc85xx_pci_err",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/mv64x60_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/mv64x60_edac.c
--- linux-libre-4.9-gnu/drivers/edac/mv64x60_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/mv64x60_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,6 @@
 #include <linux/edac.h>
 #include <linux/gfp.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 #include "mv64x60_edac.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/octeon_edac-l2c.c linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-l2c.c
--- linux-libre-4.9-gnu/drivers/edac/octeon_edac-l2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-l2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,6 @@
 
 #include <asm/octeon/cvmx.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 #define EDAC_MOD_STR "octeon-l2c"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/octeon_edac-lmc.c linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-lmc.c
--- linux-libre-4.9-gnu/drivers/edac/octeon_edac-lmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-lmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,6 @@
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-lmcx-defs.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 #define OCTEON_MAX_MC 4
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/octeon_edac-pc.c linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-pc.c
--- linux-libre-4.9-gnu/drivers/edac/octeon_edac-pc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-pc.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,6 @@
 #include <linux/io.h>
 #include <linux/edac.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 #include <asm/octeon/cvmx.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/octeon_edac-pci.c linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-pci.c
--- linux-libre-4.9-gnu/drivers/edac/octeon_edac-pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/octeon_edac-pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,6 @@
 #include <asm/octeon/cvmx-pci-defs.h>
 #include <asm/octeon/octeon.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 static void octeon_pci_poll(struct edac_pci_ctl_info *pci)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/pasemi_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/pasemi_edac.c
--- linux-libre-4.9-gnu/drivers/edac/pasemi_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/pasemi_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define MODULE_NAME "pasemi_edac"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/ppc4xx_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/ppc4xx_edac.c
--- linux-libre-4.9-gnu/drivers/edac/ppc4xx_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/ppc4xx_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 
 #include <asm/dcr.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 #include "ppc4xx_edac.h"
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/r82600_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/r82600_edac.c
--- linux-libre-4.9-gnu/drivers/edac/r82600_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/r82600_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/edac.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define R82600_REVISION	" Ver: 2.0.2"
 #define EDAC_MOD_STR	"r82600_edac"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/sb_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/sb_edac.c
--- linux-libre-4.9-gnu/drivers/edac/sb_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/sb_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,10 +23,11 @@
 #include <linux/math64.h>
 #include <linux/mod_devicetable.h>
 #include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
 #include <asm/processor.h>
 #include <asm/mce.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 /* Static vars */
 static LIST_HEAD(sbridge_edac_list);
@@ -3365,12 +3366,13 @@ fail0:
 	{ X86_VENDOR_INTEL, 6, model, 0, (unsigned long)&table }
 
 static const struct x86_cpu_id sbridge_cpuids[] = {
-	ICPU(0x2d, pci_dev_descr_sbridge_table),	/* SANDY_BRIDGE */
-	ICPU(0x3e, pci_dev_descr_ibridge_table),	/* IVY_BRIDGE */
-	ICPU(0x3f, pci_dev_descr_haswell_table),	/* HASWELL */
-	ICPU(0x4f, pci_dev_descr_broadwell_table),	/* BROADWELL */
-	ICPU(0x56, pci_dev_descr_broadwell_table),	/* BROADWELL-DE */
-	ICPU(0x57, pci_dev_descr_knl_table),		/* KNIGHTS_LANDING */
+	ICPU(INTEL_FAM6_SANDYBRIDGE_X,	  pci_dev_descr_sbridge_table),
+	ICPU(INTEL_FAM6_IVYBRIDGE_X,	  pci_dev_descr_ibridge_table),
+	ICPU(INTEL_FAM6_HASWELL_X,	  pci_dev_descr_haswell_table),
+	ICPU(INTEL_FAM6_BROADWELL_X,	  pci_dev_descr_broadwell_table),
+	ICPU(INTEL_FAM6_BROADWELL_XEON_D, pci_dev_descr_broadwell_table),
+	ICPU(INTEL_FAM6_XEON_PHI_KNL,	  pci_dev_descr_knl_table),
+	ICPU(INTEL_FAM6_XEON_PHI_KNM,	  pci_dev_descr_knl_table),
 	{ }
 };
 MODULE_DEVICE_TABLE(x86cpu, sbridge_cpuids);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/skx_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/skx_edac.c
--- linux-libre-4.9-gnu/drivers/edac/skx_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/skx_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,10 +25,11 @@
 #include <linux/math64.h>
 #include <linux/mod_devicetable.h>
 #include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
 #include <asm/processor.h>
 #include <asm/mce.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define SKX_REVISION    " Ver: 1.0 "
 
@@ -262,8 +263,8 @@ fail:
 	return -ENODEV;
 }
 
-const struct x86_cpu_id skx_cpuids[] = {
-	{ X86_VENDOR_INTEL, 6, 0x55, 0, 0 },	/* Skylake */
+static const struct x86_cpu_id skx_cpuids[] = {
+	{ X86_VENDOR_INTEL, 6, INTEL_FAM6_SKYLAKE_X, 0, 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
@@ -1036,7 +1037,7 @@ static void skx_remove(void)
  *	search for all the devices we need
  *	check which DIMMs are present.
  */
-int __init skx_init(void)
+static int __init skx_init(void)
 {
 	const struct x86_cpu_id *id;
 	const struct munit *m;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/synopsys_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/synopsys_edac.c
--- linux-libre-4.9-gnu/drivers/edac/synopsys_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/synopsys_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 /* Number of cs_rows needed per memory controller */
 #define SYNPS_EDAC_NR_CSROWS	1
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/tile_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/tile_edac.c
--- linux-libre-4.9-gnu/drivers/edac/tile_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/tile_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <hv/hypervisor.h>
 #include <hv/drv_mshim_intf.h>
 
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define DRV_NAME	"tile-edac"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/x38_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/x38_edac.c
--- linux-libre-4.9-gnu/drivers/edac/x38_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/x38_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/edac.h>
 
 #include <linux/io-64-nonatomic-lo-hi.h>
-#include "edac_core.h"
+#include "edac_module.h"
 
 #define X38_REVISION		"1.1"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/edac/xgene_edac.c linux-libre-4.10-rc8-gnu/drivers/edac/xgene_edac.c
--- linux-libre-4.9-gnu/drivers/edac/xgene_edac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/edac/xgene_edac.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,6 @@
 #include <linux/of_address.h>
 #include <linux/regmap.h>
 
-#include "edac_core.h"
 #include "edac_module.h"
 
 #define EDAC_MOD_STR			"xgene_edac"
@@ -1602,16 +1601,16 @@ static void xgene_edac_pa_report(struct
 		dev_err(edac_dev->dev, "IOB PA read data RAM error\n");
 	if (reg & IOBPA_M_RDATA_CORRUPT_MASK)
 		dev_err(edac_dev->dev,
-			"Mutilple IOB PA read data RAM error\n");
+			"Multiple IOB PA read data RAM error\n");
 	if (reg & IOBPA_WDATA_CORRUPT_MASK)
 		dev_err(edac_dev->dev, "IOB PA write data RAM error\n");
 	if (reg & IOBPA_M_WDATA_CORRUPT_MASK)
 		dev_err(edac_dev->dev,
-			"Mutilple IOB PA write data RAM error\n");
+			"Multiple IOB PA write data RAM error\n");
 	if (reg & IOBPA_TRANS_CORRUPT_MASK)
 		dev_err(edac_dev->dev, "IOB PA transaction error\n");
 	if (reg & IOBPA_M_TRANS_CORRUPT_MASK)
-		dev_err(edac_dev->dev, "Mutilple IOB PA transaction error\n");
+		dev_err(edac_dev->dev, "Multiple IOB PA transaction error\n");
 	if (reg & IOBPA_REQIDRAM_CORRUPT_MASK)
 		dev_err(edac_dev->dev, "IOB PA transaction ID RAM error\n");
 	if (reg & IOBPA_M_REQIDRAM_CORRUPT_MASK)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/extcon/extcon-arizona.c linux-libre-4.10-rc8-gnu/drivers/extcon/extcon-arizona.c
--- linux-libre-4.9-gnu/drivers/extcon/extcon-arizona.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/extcon/extcon-arizona.c	2017-02-12 16:03:20.000000000 -0500
@@ -274,9 +274,10 @@ static void arizona_extcon_pulse_micbias
 	struct arizona *arizona = info->arizona;
 	const char *widget = arizona_extcon_get_micbias(info);
 	struct snd_soc_dapm_context *dapm = arizona->dapm;
+	struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
 	int ret;
 
-	ret = snd_soc_dapm_force_enable_pin(dapm, widget);
+	ret = snd_soc_component_force_enable_pin(component, widget);
 	if (ret != 0)
 		dev_warn(arizona->dev, "Failed to enable %s: %d\n",
 			 widget, ret);
@@ -284,7 +285,7 @@ static void arizona_extcon_pulse_micbias
 	snd_soc_dapm_sync(dapm);
 
 	if (!arizona->pdata.micd_force_micbias) {
-		ret = snd_soc_dapm_disable_pin(arizona->dapm, widget);
+		ret = snd_soc_component_disable_pin(component, widget);
 		if (ret != 0)
 			dev_warn(arizona->dev, "Failed to disable %s: %d\n",
 				 widget, ret);
@@ -349,6 +350,7 @@ static void arizona_stop_mic(struct ariz
 	struct arizona *arizona = info->arizona;
 	const char *widget = arizona_extcon_get_micbias(info);
 	struct snd_soc_dapm_context *dapm = arizona->dapm;
+	struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
 	bool change;
 	int ret;
 
@@ -356,7 +358,7 @@ static void arizona_stop_mic(struct ariz
 				 ARIZONA_MICD_ENA, 0,
 				 &change);
 
-	ret = snd_soc_dapm_disable_pin(dapm, widget);
+	ret = snd_soc_component_disable_pin(component, widget);
 	if (ret != 0)
 		dev_warn(arizona->dev,
 			 "Failed to disable %s: %d\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/extcon/extcon.c linux-libre-4.10-rc8-gnu/drivers/extcon/extcon.c
--- linux-libre-4.9-gnu/drivers/extcon/extcon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/extcon/extcon.c	2017-02-12 16:03:20.000000000 -0500
@@ -453,7 +453,7 @@ int extcon_sync(struct extcon_dev *edev,
 		dev_err(&edev->dev, "out of memory in extcon_set_state\n");
 		kobject_uevent(&edev->dev.kobj, KOBJ_CHANGE);
 
-		return 0;
+		return -ENOMEM;
 	}
 
 	length = name_show(&edev->dev, NULL, prop_buf);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/extcon/extcon-usb-gpio.c linux-libre-4.10-rc8-gnu/drivers/extcon/extcon-usb-gpio.c
--- linux-libre-4.9-gnu/drivers/extcon/extcon-usb-gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/extcon/extcon-usb-gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,6 @@
 #include <linux/module.h>
 #include <linux/of_gpio.h>
 #include <linux/platform_device.h>
-#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/acpi.h>
@@ -36,7 +35,9 @@ struct usb_extcon_info {
 	struct extcon_dev *edev;
 
 	struct gpio_desc *id_gpiod;
+	struct gpio_desc *vbus_gpiod;
 	int id_irq;
+	int vbus_irq;
 
 	unsigned long debounce_jiffies;
 	struct delayed_work wq_detcable;
@@ -48,31 +49,47 @@ static const unsigned int usb_extcon_cab
 	EXTCON_NONE,
 };
 
+/*
+ * "USB" = VBUS and "USB-HOST" = !ID, so we have:
+ * Both "USB" and "USB-HOST" can't be set as active at the
+ * same time so if "USB-HOST" is active (i.e. ID is 0)  we keep "USB" inactive
+ * even if VBUS is on.
+ *
+ *  State              |    ID   |   VBUS
+ * ----------------------------------------
+ *  [1] USB            |    H    |    H
+ *  [2] none           |    H    |    L
+ *  [3] USB-HOST       |    L    |    H
+ *  [4] USB-HOST       |    L    |    L
+ *
+ * In case we have only one of these signals:
+ * - VBUS only - we want to distinguish between [1] and [2], so ID is always 1.
+ * - ID only - we want to distinguish between [1] and [4], so VBUS = ID.
+*/
 static void usb_extcon_detect_cable(struct work_struct *work)
 {
-	int id;
+	int id, vbus;
 	struct usb_extcon_info *info = container_of(to_delayed_work(work),
 						    struct usb_extcon_info,
 						    wq_detcable);
 
-	/* check ID and update cable state */
-	id = gpiod_get_value_cansleep(info->id_gpiod);
-	if (id) {
-		/*
-		 * ID = 1 means USB HOST cable detached.
-		 * As we don't have event for USB peripheral cable attached,
-		 * we simulate USB peripheral attach here.
-		 */
+	/* check ID and VBUS and update cable state */
+	id = info->id_gpiod ?
+		gpiod_get_value_cansleep(info->id_gpiod) : 1;
+	vbus = info->vbus_gpiod ?
+		gpiod_get_value_cansleep(info->vbus_gpiod) : id;
+
+	/* at first we clean states which are no longer active */
+	if (id)
 		extcon_set_state_sync(info->edev, EXTCON_USB_HOST, false);
-		extcon_set_state_sync(info->edev, EXTCON_USB, true);
-	} else {
-		/*
-		 * ID = 0 means USB HOST cable attached.
-		 * As we don't have event for USB peripheral cable detached,
-		 * we simulate USB peripheral detach here.
-		 */
+	if (!vbus)
 		extcon_set_state_sync(info->edev, EXTCON_USB, false);
+
+	if (!id) {
 		extcon_set_state_sync(info->edev, EXTCON_USB_HOST, true);
+	} else {
+		if (vbus)
+			extcon_set_state_sync(info->edev, EXTCON_USB, true);
 	}
 }
 
@@ -101,12 +118,21 @@ static int usb_extcon_probe(struct platf
 		return -ENOMEM;
 
 	info->dev = dev;
-	info->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
-	if (IS_ERR(info->id_gpiod)) {
-		dev_err(dev, "failed to get ID GPIO\n");
-		return PTR_ERR(info->id_gpiod);
+	info->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id", GPIOD_IN);
+	info->vbus_gpiod = devm_gpiod_get_optional(&pdev->dev, "vbus",
+						   GPIOD_IN);
+
+	if (!info->id_gpiod && !info->vbus_gpiod) {
+		dev_err(dev, "failed to get gpios\n");
+		return -ENODEV;
 	}
 
+	if (IS_ERR(info->id_gpiod))
+		return PTR_ERR(info->id_gpiod);
+
+	if (IS_ERR(info->vbus_gpiod))
+		return PTR_ERR(info->vbus_gpiod);
+
 	info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
 	if (IS_ERR(info->edev)) {
 		dev_err(dev, "failed to allocate extcon device\n");
@@ -119,32 +145,56 @@ static int usb_extcon_probe(struct platf
 		return ret;
 	}
 
-	ret = gpiod_set_debounce(info->id_gpiod,
-				 USB_GPIO_DEBOUNCE_MS * 1000);
+	if (info->id_gpiod)
+		ret = gpiod_set_debounce(info->id_gpiod,
+					 USB_GPIO_DEBOUNCE_MS * 1000);
+	if (!ret && info->vbus_gpiod)
+		ret = gpiod_set_debounce(info->vbus_gpiod,
+					 USB_GPIO_DEBOUNCE_MS * 1000);
+
 	if (ret < 0)
 		info->debounce_jiffies = msecs_to_jiffies(USB_GPIO_DEBOUNCE_MS);
 
 	INIT_DELAYED_WORK(&info->wq_detcable, usb_extcon_detect_cable);
 
-	info->id_irq = gpiod_to_irq(info->id_gpiod);
-	if (info->id_irq < 0) {
-		dev_err(dev, "failed to get ID IRQ\n");
-		return info->id_irq;
+	if (info->id_gpiod) {
+		info->id_irq = gpiod_to_irq(info->id_gpiod);
+		if (info->id_irq < 0) {
+			dev_err(dev, "failed to get ID IRQ\n");
+			return info->id_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
+						usb_irq_handler,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request handler for ID IRQ\n");
+			return ret;
+		}
 	}
 
-	ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
-					usb_irq_handler,
-					IRQF_TRIGGER_RISING |
-					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-					pdev->name, info);
-	if (ret < 0) {
-		dev_err(dev, "failed to request handler for ID IRQ\n");
-		return ret;
+	if (info->vbus_gpiod) {
+		info->vbus_irq = gpiod_to_irq(info->vbus_gpiod);
+		if (info->vbus_irq < 0) {
+			dev_err(dev, "failed to get VBUS IRQ\n");
+			return info->vbus_irq;
+		}
+
+		ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+						usb_irq_handler,
+						IRQF_TRIGGER_RISING |
+						IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+						pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request handler for VBUS IRQ\n");
+			return ret;
+		}
 	}
 
 	platform_set_drvdata(pdev, info);
 	device_init_wakeup(dev, true);
-	dev_pm_set_wake_irq(dev, info->id_irq);
 
 	/* Perform initial detection */
 	usb_extcon_detect_cable(&info->wq_detcable.work);
@@ -157,8 +207,6 @@ static int usb_extcon_remove(struct plat
 	struct usb_extcon_info *info = platform_get_drvdata(pdev);
 
 	cancel_delayed_work_sync(&info->wq_detcable);
-
-	dev_pm_clear_wake_irq(&pdev->dev);
 	device_init_wakeup(&pdev->dev, false);
 
 	return 0;
@@ -170,12 +218,32 @@ static int usb_extcon_suspend(struct dev
 	struct usb_extcon_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
+	if (device_may_wakeup(dev)) {
+		if (info->id_gpiod) {
+			ret = enable_irq_wake(info->id_irq);
+			if (ret)
+				return ret;
+		}
+		if (info->vbus_gpiod) {
+			ret = enable_irq_wake(info->vbus_irq);
+			if (ret) {
+				if (info->id_gpiod)
+					disable_irq_wake(info->id_irq);
+
+				return ret;
+			}
+		}
+	}
+
 	/*
 	 * We don't want to process any IRQs after this point
 	 * as GPIOs used behind I2C subsystem might not be
 	 * accessible until resume completes. So disable IRQ.
 	 */
-	disable_irq(info->id_irq);
+	if (info->id_gpiod)
+		disable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		disable_irq(info->vbus_irq);
 
 	return ret;
 }
@@ -185,7 +253,28 @@ static int usb_extcon_resume(struct devi
 	struct usb_extcon_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
-	enable_irq(info->id_irq);
+	if (device_may_wakeup(dev)) {
+		if (info->id_gpiod) {
+			ret = disable_irq_wake(info->id_irq);
+			if (ret)
+				return ret;
+		}
+		if (info->vbus_gpiod) {
+			ret = disable_irq_wake(info->vbus_irq);
+			if (ret) {
+				if (info->id_gpiod)
+					enable_irq_wake(info->id_irq);
+
+				return ret;
+			}
+		}
+	}
+
+	if (info->id_gpiod)
+		enable_irq(info->id_irq);
+	if (info->vbus_gpiod)
+		enable_irq(info->vbus_irq);
+
 	if (!device_may_wakeup(dev))
 		queue_delayed_work(system_power_efficient_wq,
 				   &info->wq_detcable, 0);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firewire/net.c linux-libre-4.10-rc8-gnu/drivers/firewire/net.c
--- linux-libre-4.9-gnu/drivers/firewire/net.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firewire/net.c	2017-02-12 16:03:20.000000000 -0500
@@ -1368,15 +1368,6 @@ static netdev_tx_t fwnet_tx(struct sk_bu
 	return NETDEV_TX_OK;
 }
 
-static int fwnet_change_mtu(struct net_device *net, int new_mtu)
-{
-	if (new_mtu < 68)
-		return -EINVAL;
-
-	net->mtu = new_mtu;
-	return 0;
-}
-
 static const struct ethtool_ops fwnet_ethtool_ops = {
 	.get_link	= ethtool_op_get_link,
 };
@@ -1385,7 +1376,6 @@ static const struct net_device_ops fwnet
 	.ndo_open       = fwnet_open,
 	.ndo_stop	= fwnet_stop,
 	.ndo_start_xmit = fwnet_tx,
-	.ndo_change_mtu = fwnet_change_mtu,
 };
 
 static void fwnet_init_dev(struct net_device *net)
@@ -1454,7 +1444,6 @@ static int fwnet_probe(struct fw_unit *u
 	struct net_device *net;
 	bool allocated_netdev = false;
 	struct fwnet_device *dev;
-	unsigned max_mtu;
 	int ret;
 	union fwnet_hwaddr *ha;
 
@@ -1493,13 +1482,9 @@ static int fwnet_probe(struct fw_unit *u
 		goto out;
 	dev->local_fifo = dev->handler.offset;
 
-	/*
-	 * Use the RFC 2734 default 1500 octets or the maximum payload
-	 * as initial MTU
-	 */
-	max_mtu = (1 << (card->max_receive + 1))
-		  - sizeof(struct rfc2734_header) - IEEE1394_GASP_HDR_SIZE;
-	net->mtu = min(1500U, max_mtu);
+	net->mtu = 1500U;
+	net->min_mtu = ETH_MIN_MTU;
+	net->max_mtu = 0xfff;
 
 	/* Set our hardware address while we're at it */
 	ha = (union fwnet_hwaddr *)net->dev_addr;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/arm_scpi.c linux-libre-4.10-rc8-gnu/drivers/firmware/arm_scpi.c
--- linux-libre-4.9-gnu/drivers/firmware/arm_scpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/arm_scpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,20 +50,27 @@
 #define CMD_TOKEN_ID_MASK	0xff
 #define CMD_DATA_SIZE_SHIFT	16
 #define CMD_DATA_SIZE_MASK	0x1ff
+#define CMD_LEGACY_DATA_SIZE_SHIFT	20
+#define CMD_LEGACY_DATA_SIZE_MASK	0x1ff
 #define PACK_SCPI_CMD(cmd_id, tx_sz)			\
 	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |	\
 	(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
 #define ADD_SCPI_TOKEN(cmd, token)			\
 	((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
+#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz)				\
+	((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) |			       \
+	(((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
 
 #define CMD_SIZE(cmd)	(((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
+#define CMD_LEGACY_SIZE(cmd)	(((cmd) >> CMD_LEGACY_DATA_SIZE_SHIFT) & \
+					CMD_LEGACY_DATA_SIZE_MASK)
 #define CMD_UNIQ_MASK	(CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
 #define CMD_XTRACT_UNIQ(cmd)	((cmd) & CMD_UNIQ_MASK)
 
 #define SCPI_SLOT		0
 
 #define MAX_DVFS_DOMAINS	8
-#define MAX_DVFS_OPPS		8
+#define MAX_DVFS_OPPS		16
 #define DVFS_LATENCY(hdr)	(le32_to_cpu(hdr) >> 16)
 #define DVFS_OPP_COUNT(hdr)	((le32_to_cpu(hdr) >> 8) & 0xff)
 
@@ -99,6 +106,7 @@ enum scpi_error_codes {
 	SCPI_ERR_MAX
 };
 
+/* SCPI Standard commands */
 enum scpi_std_cmd {
 	SCPI_CMD_INVALID		= 0x00,
 	SCPI_CMD_SCPI_READY		= 0x01,
@@ -132,6 +140,108 @@ enum scpi_std_cmd {
 	SCPI_CMD_COUNT
 };
 
+/* SCPI Legacy Commands */
+enum legacy_scpi_std_cmd {
+	LEGACY_SCPI_CMD_INVALID			= 0x00,
+	LEGACY_SCPI_CMD_SCPI_READY		= 0x01,
+	LEGACY_SCPI_CMD_SCPI_CAPABILITIES	= 0x02,
+	LEGACY_SCPI_CMD_EVENT			= 0x03,
+	LEGACY_SCPI_CMD_SET_CSS_PWR_STATE	= 0x04,
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE	= 0x05,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT	= 0x06,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT	= 0x07,
+	LEGACY_SCPI_CMD_SYS_PWR_STATE		= 0x08,
+	LEGACY_SCPI_CMD_L2_READY		= 0x09,
+	LEGACY_SCPI_CMD_SET_AP_TIMER		= 0x0a,
+	LEGACY_SCPI_CMD_CANCEL_AP_TIME		= 0x0b,
+	LEGACY_SCPI_CMD_DVFS_CAPABILITIES	= 0x0c,
+	LEGACY_SCPI_CMD_GET_DVFS_INFO		= 0x0d,
+	LEGACY_SCPI_CMD_SET_DVFS		= 0x0e,
+	LEGACY_SCPI_CMD_GET_DVFS		= 0x0f,
+	LEGACY_SCPI_CMD_GET_DVFS_STAT		= 0x10,
+	LEGACY_SCPI_CMD_SET_RTC			= 0x11,
+	LEGACY_SCPI_CMD_GET_RTC			= 0x12,
+	LEGACY_SCPI_CMD_CLOCK_CAPABILITIES	= 0x13,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX		= 0x14,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE		= 0x15,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE		= 0x16,
+	LEGACY_SCPI_CMD_PSU_CAPABILITIES	= 0x17,
+	LEGACY_SCPI_CMD_SET_PSU			= 0x18,
+	LEGACY_SCPI_CMD_GET_PSU			= 0x19,
+	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES	= 0x1a,
+	LEGACY_SCPI_CMD_SENSOR_INFO		= 0x1b,
+	LEGACY_SCPI_CMD_SENSOR_VALUE		= 0x1c,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC	= 0x1d,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS	= 0x1e,
+	LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE	= 0x1f,
+	LEGACY_SCPI_CMD_COUNT
+};
+
+/* List all commands that are required to go through the high priority link */
+static int legacy_hpriority_cmds[] = {
+	LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
+	LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
+	LEGACY_SCPI_CMD_SET_DVFS,
+	LEGACY_SCPI_CMD_GET_DVFS,
+	LEGACY_SCPI_CMD_SET_RTC,
+	LEGACY_SCPI_CMD_GET_RTC,
+	LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_SET_PSU,
+	LEGACY_SCPI_CMD_GET_PSU,
+	LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
+	LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
+};
+
+/* List all commands used by this driver, used as indexes */
+enum scpi_drv_cmds {
+	CMD_SCPI_CAPABILITIES = 0,
+	CMD_GET_CLOCK_INFO,
+	CMD_GET_CLOCK_VALUE,
+	CMD_SET_CLOCK_VALUE,
+	CMD_GET_DVFS,
+	CMD_SET_DVFS,
+	CMD_GET_DVFS_INFO,
+	CMD_SENSOR_CAPABILITIES,
+	CMD_SENSOR_INFO,
+	CMD_SENSOR_VALUE,
+	CMD_SET_DEVICE_PWR_STATE,
+	CMD_GET_DEVICE_PWR_STATE,
+	CMD_MAX_COUNT,
+};
+
+static int scpi_std_commands[CMD_MAX_COUNT] = {
+	SCPI_CMD_SCPI_CAPABILITIES,
+	SCPI_CMD_GET_CLOCK_INFO,
+	SCPI_CMD_GET_CLOCK_VALUE,
+	SCPI_CMD_SET_CLOCK_VALUE,
+	SCPI_CMD_GET_DVFS,
+	SCPI_CMD_SET_DVFS,
+	SCPI_CMD_GET_DVFS_INFO,
+	SCPI_CMD_SENSOR_CAPABILITIES,
+	SCPI_CMD_SENSOR_INFO,
+	SCPI_CMD_SENSOR_VALUE,
+	SCPI_CMD_SET_DEVICE_PWR_STATE,
+	SCPI_CMD_GET_DEVICE_PWR_STATE,
+};
+
+static int scpi_legacy_commands[CMD_MAX_COUNT] = {
+	LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
+	-1, /* GET_CLOCK_INFO */
+	LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+	LEGACY_SCPI_CMD_GET_DVFS,
+	LEGACY_SCPI_CMD_SET_DVFS,
+	LEGACY_SCPI_CMD_GET_DVFS_INFO,
+	LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
+	LEGACY_SCPI_CMD_SENSOR_INFO,
+	LEGACY_SCPI_CMD_SENSOR_VALUE,
+	-1, /* SET_DEVICE_PWR_STATE */
+	-1, /* GET_DEVICE_PWR_STATE */
+};
+
 struct scpi_xfer {
 	u32 slot; /* has to be first element */
 	u32 cmd;
@@ -160,7 +270,10 @@ struct scpi_chan {
 struct scpi_drvinfo {
 	u32 protocol_version;
 	u32 firmware_version;
+	bool is_legacy;
 	int num_chans;
+	int *commands;
+	DECLARE_BITMAP(cmd_priority, LEGACY_SCPI_CMD_COUNT);
 	atomic_t next_chan;
 	struct scpi_ops *scpi_ops;
 	struct scpi_chan *channels;
@@ -177,6 +290,11 @@ struct scpi_shared_mem {
 	u8 payload[0];
 } __packed;
 
+struct legacy_scpi_shared_mem {
+	__le32 status;
+	u8 payload[0];
+} __packed;
+
 struct scp_capabilities {
 	__le32 protocol_version;
 	__le32 event_version;
@@ -202,6 +320,12 @@ struct clk_set_value {
 	__le32 rate;
 } __packed;
 
+struct legacy_clk_set_value {
+	__le32 rate;
+	__le16 id;
+	__le16 reserved;
+} __packed;
+
 struct dvfs_info {
 	__le32 header;
 	struct {
@@ -273,19 +397,43 @@ static void scpi_process_cmd(struct scpi
 		return;
 	}
 
-	list_for_each_entry(t, &ch->rx_pending, node)
-		if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
-			list_del(&t->node);
-			match = t;
-			break;
-		}
+	/* Command type is not replied by the SCP Firmware in legacy Mode
+	 * We should consider that command is the head of pending RX commands
+	 * if the list is not empty. In TX only mode, the list would be empty.
+	 */
+	if (scpi_info->is_legacy) {
+		match = list_first_entry(&ch->rx_pending, struct scpi_xfer,
+					 node);
+		list_del(&match->node);
+	} else {
+		list_for_each_entry(t, &ch->rx_pending, node)
+			if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
+				list_del(&t->node);
+				match = t;
+				break;
+			}
+	}
 	/* check if wait_for_completion is in progress or timed-out */
 	if (match && !completion_done(&match->done)) {
-		struct scpi_shared_mem *mem = ch->rx_payload;
-		unsigned int len = min(match->rx_len, CMD_SIZE(cmd));
+		unsigned int len;
+
+		if (scpi_info->is_legacy) {
+			struct legacy_scpi_shared_mem *mem = ch->rx_payload;
+
+			/* RX Length is not replied by the legacy Firmware */
+			len = match->rx_len;
+
+			match->status = le32_to_cpu(mem->status);
+			memcpy_fromio(match->rx_buf, mem->payload, len);
+		} else {
+			struct scpi_shared_mem *mem = ch->rx_payload;
+
+			len = min(match->rx_len, CMD_SIZE(cmd));
+
+			match->status = le32_to_cpu(mem->status);
+			memcpy_fromio(match->rx_buf, mem->payload, len);
+		}
 
-		match->status = le32_to_cpu(mem->status);
-		memcpy_fromio(match->rx_buf, mem->payload, len);
 		if (match->rx_len > len)
 			memset(match->rx_buf + len, 0, match->rx_len - len);
 		complete(&match->done);
@@ -297,7 +445,10 @@ static void scpi_handle_remote_msg(struc
 {
 	struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
 	struct scpi_shared_mem *mem = ch->rx_payload;
-	u32 cmd = le32_to_cpu(mem->command);
+	u32 cmd = 0;
+
+	if (!scpi_info->is_legacy)
+		cmd = le32_to_cpu(mem->command);
 
 	scpi_process_cmd(ch, cmd);
 }
@@ -309,8 +460,13 @@ static void scpi_tx_prepare(struct mbox_
 	struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
 	struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload;
 
-	if (t->tx_buf)
-		memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
+	if (t->tx_buf) {
+		if (scpi_info->is_legacy)
+			memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len);
+		else
+			memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
+	}
+
 	if (t->rx_buf) {
 		if (!(++ch->token))
 			++ch->token;
@@ -319,7 +475,9 @@ static void scpi_tx_prepare(struct mbox_
 		list_add_tail(&t->node, &ch->rx_pending);
 		spin_unlock_irqrestore(&ch->rx_lock, flags);
 	}
-	mem->command = cpu_to_le32(t->cmd);
+
+	if (!scpi_info->is_legacy)
+		mem->command = cpu_to_le32(t->cmd);
 }
 
 static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
@@ -344,23 +502,38 @@ static void put_scpi_xfer(struct scpi_xf
 	mutex_unlock(&ch->xfers_lock);
 }
 
-static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
+static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
 			     void *rx_buf, unsigned int rx_len)
 {
 	int ret;
 	u8 chan;
+	u8 cmd;
 	struct scpi_xfer *msg;
 	struct scpi_chan *scpi_chan;
 
-	chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
+	if (scpi_info->commands[idx] < 0)
+		return -EOPNOTSUPP;
+
+	cmd = scpi_info->commands[idx];
+
+	if (scpi_info->is_legacy)
+		chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0;
+	else
+		chan = atomic_inc_return(&scpi_info->next_chan) %
+			scpi_info->num_chans;
 	scpi_chan = scpi_info->channels + chan;
 
 	msg = get_scpi_xfer(scpi_chan);
 	if (!msg)
 		return -ENOMEM;
 
-	msg->slot = BIT(SCPI_SLOT);
-	msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	if (scpi_info->is_legacy) {
+		msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
+		msg->slot = msg->cmd;
+	} else {
+		msg->slot = BIT(SCPI_SLOT);
+		msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+	}
 	msg->tx_buf = tx_buf;
 	msg->tx_len = tx_len;
 	msg->rx_buf = rx_buf;
@@ -397,7 +570,7 @@ scpi_clk_get_range(u16 clk_id, unsigned
 	struct clk_get_info clk;
 	__le16 le_clk_id = cpu_to_le16(clk_id);
 
-	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
+	ret = scpi_send_message(CMD_GET_CLOCK_INFO, &le_clk_id,
 				sizeof(le_clk_id), &clk, sizeof(clk));
 	if (!ret) {
 		*min = le32_to_cpu(clk.min_rate);
@@ -412,8 +585,9 @@ static unsigned long scpi_clk_get_val(u1
 	struct clk_get_value clk;
 	__le16 le_clk_id = cpu_to_le16(clk_id);
 
-	ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
+	ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
 				sizeof(le_clk_id), &clk, sizeof(clk));
+
 	return ret ? ret : le32_to_cpu(clk.rate);
 }
 
@@ -425,7 +599,19 @@ static int scpi_clk_set_val(u16 clk_id,
 		.rate = cpu_to_le32(rate)
 	};
 
-	return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+	return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+				 &stat, sizeof(stat));
+}
+
+static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+	int stat;
+	struct legacy_clk_set_value clk = {
+		.id = cpu_to_le16(clk_id),
+		.rate = cpu_to_le32(rate)
+	};
+
+	return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
 				 &stat, sizeof(stat));
 }
 
@@ -434,8 +620,9 @@ static int scpi_dvfs_get_idx(u8 domain)
 	int ret;
 	u8 dvfs_idx;
 
-	ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
+	ret = scpi_send_message(CMD_GET_DVFS, &domain, sizeof(domain),
 				&dvfs_idx, sizeof(dvfs_idx));
+
 	return ret ? ret : dvfs_idx;
 }
 
@@ -444,7 +631,7 @@ static int scpi_dvfs_set_idx(u8 domain,
 	int stat;
 	struct dvfs_set dvfs = {domain, index};
 
-	return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
+	return scpi_send_message(CMD_SET_DVFS, &dvfs, sizeof(dvfs),
 				 &stat, sizeof(stat));
 }
 
@@ -468,9 +655,8 @@ static struct scpi_dvfs_info *scpi_dvfs_
 	if (scpi_info->dvfs[domain])	/* data already populated */
 		return scpi_info->dvfs[domain];
 
-	ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
+	ret = scpi_send_message(CMD_GET_DVFS_INFO, &domain, sizeof(domain),
 				&buf, sizeof(buf));
-
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -503,7 +689,7 @@ static int scpi_sensor_get_capability(u1
 	struct sensor_capabilities cap_buf;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
+	ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
 				sizeof(cap_buf));
 	if (!ret)
 		*sensors = le16_to_cpu(cap_buf.sensors);
@@ -517,7 +703,7 @@ static int scpi_sensor_get_info(u16 sens
 	struct _scpi_sensor_info _info;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
+	ret = scpi_send_message(CMD_SENSOR_INFO, &id, sizeof(id),
 				&_info, sizeof(_info));
 	if (!ret) {
 		memcpy(info, &_info, sizeof(*info));
@@ -533,13 +719,19 @@ static int scpi_sensor_get_value(u16 sen
 	struct sensor_value buf;
 	int ret;
 
-	ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
+	ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
 				&buf, sizeof(buf));
-	if (!ret)
+	if (ret)
+		return ret;
+
+	if (scpi_info->is_legacy)
+		/* only 32-bits supported, hi_val can be junk */
+		*val = le32_to_cpu(buf.lo_val);
+	else
 		*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
 			le32_to_cpu(buf.lo_val);
 
-	return ret;
+	return 0;
 }
 
 static int scpi_device_get_power_state(u16 dev_id)
@@ -548,7 +740,7 @@ static int scpi_device_get_power_state(u
 	u8 pstate;
 	__le16 id = cpu_to_le16(dev_id);
 
-	ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
+	ret = scpi_send_message(CMD_GET_DEVICE_PWR_STATE, &id,
 				sizeof(id), &pstate, sizeof(pstate));
 	return ret ? ret : pstate;
 }
@@ -561,7 +753,7 @@ static int scpi_device_set_power_state(u
 		.pstate = pstate,
 	};
 
-	return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
+	return scpi_send_message(CMD_SET_DEVICE_PWR_STATE, &dev_set,
 				 sizeof(dev_set), &stat, sizeof(stat));
 }
 
@@ -591,12 +783,16 @@ static int scpi_init_versions(struct scp
 	int ret;
 	struct scp_capabilities caps;
 
-	ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
+	ret = scpi_send_message(CMD_SCPI_CAPABILITIES, NULL, 0,
 				&caps, sizeof(caps));
 	if (!ret) {
 		info->protocol_version = le32_to_cpu(caps.protocol_version);
 		info->firmware_version = le32_to_cpu(caps.platform_version);
 	}
+	/* Ignore error if not implemented */
+	if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
+		return 0;
+
 	return ret;
 }
 
@@ -681,6 +877,11 @@ static int scpi_alloc_xfer_list(struct d
 	return 0;
 }
 
+static const struct of_device_id legacy_scpi_of_match[] = {
+	{.compatible = "arm,scpi-pre-1.0"},
+	{},
+};
+
 static int scpi_probe(struct platform_device *pdev)
 {
 	int count, idx, ret;
@@ -693,6 +894,9 @@ static int scpi_probe(struct platform_de
 	if (!scpi_info)
 		return -ENOMEM;
 
+	if (of_match_device(legacy_scpi_of_match, &pdev->dev))
+		scpi_info->is_legacy = true;
+
 	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
 	if (count < 0) {
 		dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@@ -755,8 +959,21 @@ err:
 
 	scpi_info->channels = scpi_chan;
 	scpi_info->num_chans = count;
+	scpi_info->commands = scpi_std_commands;
+
 	platform_set_drvdata(pdev, scpi_info);
 
+	if (scpi_info->is_legacy) {
+		/* Replace with legacy variants */
+		scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
+		scpi_info->commands = scpi_legacy_commands;
+
+		/* Fill priority bitmap */
+		for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
+			set_bit(legacy_hpriority_cmds[idx],
+				scpi_info->cmd_priority);
+	}
+
 	ret = scpi_init_versions(scpi_info);
 	if (ret) {
 		dev_err(dev, "incorrect or no SCP firmware found\n");
@@ -781,6 +998,7 @@ err:
 
 static const struct of_device_id scpi_of_match[] = {
 	{.compatible = "arm,scpi"},
+	{.compatible = "arm,scpi-pre-1.0"},
 	{},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/dmi_scan.c linux-libre-4.10-rc8-gnu/drivers/firmware/dmi_scan.c
--- linux-libre-4.9-gnu/drivers/firmware/dmi_scan.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/dmi_scan.c	2017-02-12 16:03:20.000000000 -0500
@@ -560,7 +560,7 @@ static int __init dmi_present(const u8 *
 					dmi_ver >> 16, (dmi_ver >> 8) & 0xFF);
 			}
 			dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
-			printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
+			pr_info("DMI: %s\n", dmi_ids_string);
 			return 0;
 		}
 	}
@@ -588,7 +588,7 @@ static int __init dmi_smbios3_present(co
 				dmi_ver >> 16, (dmi_ver >> 8) & 0xFF,
 				dmi_ver & 0xFF);
 			dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
-			pr_debug("DMI: %s\n", dmi_ids_string);
+			pr_info("DMI: %s\n", dmi_ids_string);
 			return 0;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/apple-properties.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/apple-properties.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/apple-properties.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/apple-properties.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,248 @@
+/*
+ * apple-properties.c - EFI device properties on Macs
+ * Copyright (C) 2016 Lukas Wunner <lukas@wunner.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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) "apple-properties: " fmt
+
+#include <linux/bootmem.h>
+#include <linux/dmi.h>
+#include <linux/efi.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/ucs2_string.h>
+#include <asm/setup.h>
+
+static bool dump_properties __initdata;
+
+static int __init dump_properties_enable(char *arg)
+{
+	dump_properties = true;
+	return 0;
+}
+
+__setup("dump_apple_properties", dump_properties_enable);
+
+struct dev_header {
+	u32 len;
+	u32 prop_count;
+	struct efi_dev_path path[0];
+	/*
+	 * followed by key/value pairs, each key and value preceded by u32 len,
+	 * len includes itself, value may be empty (in which case its len is 4)
+	 */
+};
+
+struct properties_header {
+	u32 len;
+	u32 version;
+	u32 dev_count;
+	struct dev_header dev_header[0];
+};
+
+static u8 one __initdata = 1;
+
+static void __init unmarshal_key_value_pairs(struct dev_header *dev_header,
+					     struct device *dev, void *ptr,
+					     struct property_entry entry[])
+{
+	int i;
+
+	for (i = 0; i < dev_header->prop_count; i++) {
+		int remaining = dev_header->len - (ptr - (void *)dev_header);
+		u32 key_len, val_len;
+		char *key;
+
+		if (sizeof(key_len) > remaining)
+			break;
+
+		key_len = *(typeof(key_len) *)ptr;
+		if (key_len + sizeof(val_len) > remaining ||
+		    key_len < sizeof(key_len) + sizeof(efi_char16_t) ||
+		    *(efi_char16_t *)(ptr + sizeof(key_len)) == 0) {
+			dev_err(dev, "invalid property name len at %#zx\n",
+				ptr - (void *)dev_header);
+			break;
+		}
+
+		val_len = *(typeof(val_len) *)(ptr + key_len);
+		if (key_len + val_len > remaining ||
+		    val_len < sizeof(val_len)) {
+			dev_err(dev, "invalid property val len at %#zx\n",
+				ptr - (void *)dev_header + key_len);
+			break;
+		}
+
+		/* 4 bytes to accommodate UTF-8 code points + null byte */
+		key = kzalloc((key_len - sizeof(key_len)) * 4 + 1, GFP_KERNEL);
+		if (!key) {
+			dev_err(dev, "cannot allocate property name\n");
+			break;
+		}
+		ucs2_as_utf8(key, ptr + sizeof(key_len),
+			     key_len - sizeof(key_len));
+
+		entry[i].name = key;
+		entry[i].is_array = true;
+		entry[i].length = val_len - sizeof(val_len);
+		entry[i].pointer.raw_data = ptr + key_len + sizeof(val_len);
+		if (!entry[i].length) {
+			/* driver core doesn't accept empty properties */
+			entry[i].length = 1;
+			entry[i].pointer.raw_data = &one;
+		}
+
+		if (dump_properties) {
+			dev_info(dev, "property: %s\n", entry[i].name);
+			print_hex_dump(KERN_INFO, pr_fmt(), DUMP_PREFIX_OFFSET,
+				16, 1, entry[i].pointer.raw_data,
+				entry[i].length, true);
+		}
+
+		ptr += key_len + val_len;
+	}
+
+	if (i != dev_header->prop_count) {
+		dev_err(dev, "got %d device properties, expected %u\n", i,
+			dev_header->prop_count);
+		print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+			16, 1, dev_header, dev_header->len, true);
+		return;
+	}
+
+	dev_info(dev, "assigning %d device properties\n", i);
+}
+
+static int __init unmarshal_devices(struct properties_header *properties)
+{
+	size_t offset = offsetof(struct properties_header, dev_header[0]);
+
+	while (offset + sizeof(struct dev_header) < properties->len) {
+		struct dev_header *dev_header = (void *)properties + offset;
+		struct property_entry *entry = NULL;
+		struct device *dev;
+		size_t len;
+		int ret, i;
+		void *ptr;
+
+		if (offset + dev_header->len > properties->len ||
+		    dev_header->len <= sizeof(*dev_header)) {
+			pr_err("invalid len in dev_header at %#zx\n", offset);
+			return -EINVAL;
+		}
+
+		ptr = dev_header->path;
+		len = dev_header->len - sizeof(*dev_header);
+
+		dev = efi_get_device_by_path((struct efi_dev_path **)&ptr, &len);
+		if (IS_ERR(dev)) {
+			pr_err("device path parse error %ld at %#zx:\n",
+			       PTR_ERR(dev), ptr - (void *)dev_header);
+			print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+			       16, 1, dev_header, dev_header->len, true);
+			dev = NULL;
+			goto skip_device;
+		}
+
+		entry = kcalloc(dev_header->prop_count + 1, sizeof(*entry),
+				GFP_KERNEL);
+		if (!entry) {
+			dev_err(dev, "cannot allocate properties\n");
+			goto skip_device;
+		}
+
+		unmarshal_key_value_pairs(dev_header, dev, ptr, entry);
+		if (!entry[0].name)
+			goto skip_device;
+
+		ret = device_add_properties(dev, entry); /* makes deep copy */
+		if (ret)
+			dev_err(dev, "error %d assigning properties\n", ret);
+
+		for (i = 0; entry[i].name; i++)
+			kfree(entry[i].name);
+
+skip_device:
+		kfree(entry);
+		put_device(dev);
+		offset += dev_header->len;
+	}
+
+	return 0;
+}
+
+static int __init map_properties(void)
+{
+	struct properties_header *properties;
+	struct setup_data *data;
+	u32 data_len;
+	u64 pa_data;
+	int ret;
+
+	if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.") &&
+	    !dmi_match(DMI_SYS_VENDOR, "Apple Computer, Inc."))
+		return 0;
+
+	pa_data = boot_params.hdr.setup_data;
+	while (pa_data) {
+		data = ioremap(pa_data, sizeof(*data));
+		if (!data) {
+			pr_err("cannot map setup_data header\n");
+			return -ENOMEM;
+		}
+
+		if (data->type != SETUP_APPLE_PROPERTIES) {
+			pa_data = data->next;
+			iounmap(data);
+			continue;
+		}
+
+		data_len = data->len;
+		iounmap(data);
+
+		data = ioremap(pa_data, sizeof(*data) + data_len);
+		if (!data) {
+			pr_err("cannot map setup_data payload\n");
+			return -ENOMEM;
+		}
+
+		properties = (struct properties_header *)data->data;
+		if (properties->version != 1) {
+			pr_err("unsupported version:\n");
+			print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+			       16, 1, properties, data_len, true);
+			ret = -ENOTSUPP;
+		} else if (properties->len != data_len) {
+			pr_err("length mismatch, expected %u\n", data_len);
+			print_hex_dump(KERN_ERR, pr_fmt(), DUMP_PREFIX_OFFSET,
+			       16, 1, properties, data_len, true);
+			ret = -EINVAL;
+		} else
+			ret = unmarshal_devices(properties);
+
+		/*
+		 * Can only free the setup_data payload but not its header
+		 * to avoid breaking the chain of ->next pointers.
+		 */
+		data->len = 0;
+		iounmap(data);
+		free_bootmem_late(pa_data + sizeof(*data), data_len);
+
+		return ret;
+	}
+	return 0;
+}
+
+fs_initcall(map_properties);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/arm-init.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/arm-init.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/arm-init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/arm-init.c	2017-02-12 16:03:20.000000000 -0500
@@ -244,8 +244,10 @@ void __init efi_init(void)
 	     "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
 	      efi.memmap.desc_version);
 
-	if (uefi_init() < 0)
+	if (uefi_init() < 0) {
+		efi_memmap_unmap();
 		return;
+	}
 
 	reserve_regions();
 	efi_memattr_init();
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/arm-runtime.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/arm-runtime.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/arm-runtime.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/arm-runtime.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@ static struct mm_struct efi_mm = {
 	.mmlist			= LIST_HEAD_INIT(efi_mm.mmlist),
 };
 
-#ifdef CONFIG_ARM64_PTDUMP
+#ifdef CONFIG_ARM64_PTDUMP_DEBUGFS
 #include <asm/ptdump.h>
 
 static struct ptdump_info efi_ptdump_info = {
@@ -53,7 +53,7 @@ static struct ptdump_info efi_ptdump_inf
 
 static int __init ptdump_init(void)
 {
-	return ptdump_register(&efi_ptdump_info, "efi_page_tables");
+	return ptdump_debugfs_register(&efi_ptdump_info, "efi_page_tables");
 }
 device_initcall(ptdump_init);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/dev-path-parser.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/dev-path-parser.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/dev-path-parser.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/dev-path-parser.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,203 @@
+/*
+ * dev-path-parser.c - EFI Device Path parser
+ * Copyright (C) 2016 Lukas Wunner <lukas@wunner.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU 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/acpi.h>
+#include <linux/efi.h>
+#include <linux/pci.h>
+
+struct acpi_hid_uid {
+	struct acpi_device_id hid[2];
+	char uid[11]; /* UINT_MAX + null byte */
+};
+
+static int __init match_acpi_dev(struct device *dev, void *data)
+{
+	struct acpi_hid_uid hid_uid = *(struct acpi_hid_uid *)data;
+	struct acpi_device *adev = to_acpi_device(dev);
+
+	if (acpi_match_device_ids(adev, hid_uid.hid))
+		return 0;
+
+	if (adev->pnp.unique_id)
+		return !strcmp(adev->pnp.unique_id, hid_uid.uid);
+	else
+		return !strcmp("0", hid_uid.uid);
+}
+
+static long __init parse_acpi_path(struct efi_dev_path *node,
+				   struct device *parent, struct device **child)
+{
+	struct acpi_hid_uid hid_uid = {};
+	struct device *phys_dev;
+
+	if (node->length != 12)
+		return -EINVAL;
+
+	sprintf(hid_uid.hid[0].id, "%c%c%c%04X",
+		'A' + ((node->acpi.hid >> 10) & 0x1f) - 1,
+		'A' + ((node->acpi.hid >>  5) & 0x1f) - 1,
+		'A' + ((node->acpi.hid >>  0) & 0x1f) - 1,
+			node->acpi.hid >> 16);
+	sprintf(hid_uid.uid, "%u", node->acpi.uid);
+
+	*child = bus_find_device(&acpi_bus_type, NULL, &hid_uid,
+				 match_acpi_dev);
+	if (!*child)
+		return -ENODEV;
+
+	phys_dev = acpi_get_first_physical_node(to_acpi_device(*child));
+	if (phys_dev) {
+		get_device(phys_dev);
+		put_device(*child);
+		*child = phys_dev;
+	}
+
+	return 0;
+}
+
+static int __init match_pci_dev(struct device *dev, void *data)
+{
+	unsigned int devfn = *(unsigned int *)data;
+
+	return dev_is_pci(dev) && to_pci_dev(dev)->devfn == devfn;
+}
+
+static long __init parse_pci_path(struct efi_dev_path *node,
+				  struct device *parent, struct device **child)
+{
+	unsigned int devfn;
+
+	if (node->length != 6)
+		return -EINVAL;
+	if (!parent)
+		return -EINVAL;
+
+	devfn = PCI_DEVFN(node->pci.dev, node->pci.fn);
+
+	*child = device_find_child(parent, &devfn, match_pci_dev);
+	if (!*child)
+		return -ENODEV;
+
+	return 0;
+}
+
+/*
+ * Insert parsers for further node types here.
+ *
+ * Each parser takes a pointer to the @node and to the @parent (will be NULL
+ * for the first device path node). If a device corresponding to @node was
+ * found below @parent, its reference count should be incremented and the
+ * device returned in @child.
+ *
+ * The return value should be 0 on success or a negative int on failure.
+ * The special return values 0x01 (EFI_DEV_END_INSTANCE) and 0xFF
+ * (EFI_DEV_END_ENTIRE) signal the end of the device path, only
+ * parse_end_path() is supposed to return this.
+ *
+ * Be sure to validate the node length and contents before commencing the
+ * search for a device.
+ */
+
+static long __init parse_end_path(struct efi_dev_path *node,
+				  struct device *parent, struct device **child)
+{
+	if (node->length != 4)
+		return -EINVAL;
+	if (node->sub_type != EFI_DEV_END_INSTANCE &&
+	    node->sub_type != EFI_DEV_END_ENTIRE)
+		return -EINVAL;
+	if (!parent)
+		return -ENODEV;
+
+	*child = get_device(parent);
+	return node->sub_type;
+}
+
+/**
+ * efi_get_device_by_path - find device by EFI Device Path
+ * @node: EFI Device Path
+ * @len: maximum length of EFI Device Path in bytes
+ *
+ * Parse a series of EFI Device Path nodes at @node and find the corresponding
+ * device.  If the device was found, its reference count is incremented and a
+ * pointer to it is returned.  The caller needs to drop the reference with
+ * put_device() after use.  The @node pointer is updated to point to the
+ * location immediately after the "End of Hardware Device Path" node.
+ *
+ * If another Device Path instance follows, @len is decremented by the number
+ * of bytes consumed.  Otherwise @len is set to %0.
+ *
+ * If a Device Path node is malformed or its corresponding device is not found,
+ * @node is updated to point to this offending node and an ERR_PTR is returned.
+ *
+ * If @len is initially %0, the function returns %NULL.  Thus, to iterate over
+ * all instances in a path, the following idiom may be used:
+ *
+ *	while (!IS_ERR_OR_NULL(dev = efi_get_device_by_path(&node, &len))) {
+ *		// do something with dev
+ *		put_device(dev);
+ *	}
+ *	if (IS_ERR(dev))
+ *		// report error
+ *
+ * Devices can only be found if they're already instantiated. Most buses
+ * instantiate devices in the "subsys" initcall level, hence the earliest
+ * initcall level in which this function should be called is "fs".
+ *
+ * Returns the device on success or
+ *	%ERR_PTR(-ENODEV) if no device was found,
+ *	%ERR_PTR(-EINVAL) if a node is malformed or exceeds @len,
+ *	%ERR_PTR(-ENOTSUPP) if support for a node type is not yet implemented.
+ */
+struct device * __init efi_get_device_by_path(struct efi_dev_path **node,
+					      size_t *len)
+{
+	struct device *parent = NULL, *child;
+	long ret = 0;
+
+	if (!*len)
+		return NULL;
+
+	while (!ret) {
+		if (*len < 4 || *len < (*node)->length)
+			ret = -EINVAL;
+		else if ((*node)->type     == EFI_DEV_ACPI &&
+			 (*node)->sub_type == EFI_DEV_BASIC_ACPI)
+			ret = parse_acpi_path(*node, parent, &child);
+		else if ((*node)->type     == EFI_DEV_HW &&
+			 (*node)->sub_type == EFI_DEV_PCI)
+			ret = parse_pci_path(*node, parent, &child);
+		else if (((*node)->type    == EFI_DEV_END_PATH ||
+			  (*node)->type    == EFI_DEV_END_PATH2))
+			ret = parse_end_path(*node, parent, &child);
+		else
+			ret = -ENOTSUPP;
+
+		put_device(parent);
+		if (ret < 0)
+			return ERR_PTR(ret);
+
+		parent = child;
+		*node  = (void *)*node + (*node)->length;
+		*len  -= (*node)->length;
+	}
+
+	if (ret == EFI_DEV_END_ENTIRE)
+		*len = 0;
+
+	return child;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/efi.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/efi.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/efi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/efi.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,10 @@
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/io.h>
+#include <linux/kexec.h>
 #include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/ucs2_string.h>
@@ -48,6 +51,7 @@ struct efi __read_mostly efi = {
 	.esrt			= EFI_INVALID_TABLE_ADDR,
 	.properties_table	= EFI_INVALID_TABLE_ADDR,
 	.mem_attr_table		= EFI_INVALID_TABLE_ADDR,
+	.rng_seed		= EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
 
@@ -259,8 +263,10 @@ static __init int efivar_ssdt_load(void)
 		}
 
 		data = kmalloc(size, GFP_KERNEL);
-		if (!data)
+		if (!data) {
+			ret = -ENOMEM;
 			goto free_entry;
+		}
 
 		ret = efivar_entry_get(entry, NULL, &size, data);
 		if (ret) {
@@ -438,6 +444,7 @@ static __initdata efi_config_table_type_
 	{EFI_SYSTEM_RESOURCE_TABLE_GUID, "ESRT", &efi.esrt},
 	{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
 	{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
+	{LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
 	{NULL_GUID, NULL, NULL},
 };
 
@@ -499,6 +506,29 @@ int __init efi_config_parse_tables(void
 	pr_cont("\n");
 	set_bit(EFI_CONFIG_TABLES, &efi.flags);
 
+	if (efi.rng_seed != EFI_INVALID_TABLE_ADDR) {
+		struct linux_efi_random_seed *seed;
+		u32 size = 0;
+
+		seed = early_memremap(efi.rng_seed, sizeof(*seed));
+		if (seed != NULL) {
+			size = seed->size;
+			early_memunmap(seed, sizeof(*seed));
+		} else {
+			pr_err("Could not map UEFI random seed!\n");
+		}
+		if (size > 0) {
+			seed = early_memremap(efi.rng_seed,
+					      sizeof(*seed) + size);
+			if (seed != NULL) {
+				add_device_randomness(seed->bits, seed->size);
+				early_memunmap(seed, sizeof(*seed) + size);
+			} else {
+				pr_err("Could not map UEFI random seed!\n");
+			}
+		}
+	}
+
 	/* Parse the EFI Properties table if it exists */
 	if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
 		efi_properties_table_t *tbl;
@@ -822,3 +852,47 @@ int efi_status_to_err(efi_status_t statu
 
 	return err;
 }
+
+#ifdef CONFIG_KEXEC
+static int update_efi_random_seed(struct notifier_block *nb,
+				  unsigned long code, void *unused)
+{
+	struct linux_efi_random_seed *seed;
+	u32 size = 0;
+
+	if (!kexec_in_progress)
+		return NOTIFY_DONE;
+
+	seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
+	if (seed != NULL) {
+		size = min(seed->size, 32U);
+		memunmap(seed);
+	} else {
+		pr_err("Could not map UEFI random seed!\n");
+	}
+	if (size > 0) {
+		seed = memremap(efi.rng_seed, sizeof(*seed) + size,
+				MEMREMAP_WB);
+		if (seed != NULL) {
+			seed->size = size;
+			get_random_bytes(seed->bits, seed->size);
+			memunmap(seed);
+		} else {
+			pr_err("Could not map UEFI random seed!\n");
+		}
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block efi_random_seed_nb = {
+	.notifier_call = update_efi_random_seed,
+};
+
+static int register_update_efi_random_seed(void)
+{
+	if (efi.rng_seed == EFI_INVALID_TABLE_ADDR)
+		return 0;
+	return register_reboot_notifier(&efi_random_seed_nb);
+}
+late_initcall(register_update_efi_random_seed);
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/fake_mem.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/fake_mem.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/fake_mem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/fake_mem.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,8 +71,7 @@ void __init efi_fake_memmap(void)
 	}
 
 	/* allocate memory for new EFI memmap */
-	new_memmap_phy = memblock_alloc(efi.memmap.desc_size * new_nr_map,
-					PAGE_SIZE);
+	new_memmap_phy = efi_memmap_alloc(new_nr_map);
 	if (!new_memmap_phy)
 		return;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/Kconfig linux-libre-4.10-rc8-gnu/drivers/firmware/efi/Kconfig
--- linux-libre-4.9-gnu/drivers/firmware/efi/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -129,7 +129,25 @@ config EFI_TEST
 	  Say Y here to enable the runtime services support via /dev/efi_test.
 	  If unsure, say N.
 
+config APPLE_PROPERTIES
+	bool "Apple Device Properties"
+	depends on EFI_STUB && X86
+	select EFI_DEV_PATH_PARSER
+	select UCS2_STRING
+	help
+	  Retrieve properties from EFI on Apple Macs and assign them to
+	  devices, allowing for improved support of Apple hardware.
+	  Properties that would otherwise be missing include the
+	  Thunderbolt Device ROM and GPU configuration data.
+
+	  If unsure, say Y if you have a Mac.  Otherwise N.
+
 endmenu
 
 config UEFI_CPER
 	bool
+
+config EFI_DEV_PATH_PARSER
+	bool
+	depends on ACPI
+	default n
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/libstub/arm-stub.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/arm-stub.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/libstub/arm-stub.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/arm-stub.c	2017-02-12 16:03:20.000000000 -0500
@@ -340,6 +340,8 @@ unsigned long efi_entry(void *handle, ef
 	if (status != EFI_SUCCESS)
 		pr_efi_err(sys_table, "Failed initrd from command line!\n");
 
+	efi_random_get_seed(sys_table);
+
 	new_fdt_addr = fdt_addr;
 	status = allocate_new_fdt_and_exit_boot(sys_table, handle,
 				&new_fdt_addr, dram_base + MAX_FDT_OFFSET,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/libstub/efistub.h linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/efistub.h
--- linux-libre-4.9-gnu/drivers/firmware/efi/libstub/efistub.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/efistub.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,15 @@
  */
 #undef __init
 
+/*
+ * Allow the platform to override the allocation granularity: this allows
+ * systems that have the capability to run with a larger page size to deal
+ * with the allocations for initrd and fdt more efficiently.
+ */
+#ifndef EFI_ALLOC_ALIGN
+#define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
+#endif
+
 void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
 
 efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
@@ -30,14 +39,6 @@ efi_status_t efi_file_close(void *handle
 
 unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-			unsigned long orig_fdt_size,
-			void *fdt, int new_fdt_size, char *cmdline_ptr,
-			u64 initrd_addr, u64 initrd_size,
-			efi_memory_desc_t *memory_map,
-			unsigned long map_size, unsigned long desc_size,
-			u32 desc_ver);
-
 efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
 					    void *handle,
 					    unsigned long *new_fdt_addr,
@@ -62,4 +63,6 @@ efi_status_t efi_random_alloc(efi_system
 
 efi_status_t check_platform_features(efi_system_table_t *sys_table_arg);
 
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg);
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/efi-stub-helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,15 +32,6 @@
 
 static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE;
 
-/*
- * Allow the platform to override the allocation granularity: this allows
- * systems that have the capability to run with a larger page size to deal
- * with the allocations for initrd and fdt more efficiently.
- */
-#ifndef EFI_ALLOC_ALIGN
-#define EFI_ALLOC_ALIGN		EFI_PAGE_SIZE
-#endif
-
 #define EFI_MMAP_NR_SLACK_SLOTS	8
 
 struct file_info {
@@ -186,14 +177,16 @@ efi_status_t efi_high_alloc(efi_system_t
 		goto fail;
 
 	/*
-	 * Enforce minimum alignment that EFI requires when requesting
-	 * a specific address.  We are doing page-based allocations,
-	 * so we must be aligned to a page.
+	 * Enforce minimum alignment that EFI or Linux requires when
+	 * requesting a specific address.  We are doing page-based (or
+	 * larger) allocations, and both the address and size must meet
+	 * alignment constraints.
 	 */
 	if (align < EFI_ALLOC_ALIGN)
 		align = EFI_ALLOC_ALIGN;
 
-	nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
+	size = round_up(size, EFI_ALLOC_ALIGN);
+	nr_pages = size / EFI_PAGE_SIZE;
 again:
 	for (i = 0; i < map_size / desc_size; i++) {
 		efi_memory_desc_t *desc;
@@ -208,7 +201,7 @@ again:
 			continue;
 
 		start = desc->phys_addr;
-		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+		end = start + desc->num_pages * EFI_PAGE_SIZE;
 
 		if (end > max)
 			end = max;
@@ -278,14 +271,16 @@ efi_status_t efi_low_alloc(efi_system_ta
 		goto fail;
 
 	/*
-	 * Enforce minimum alignment that EFI requires when requesting
-	 * a specific address.  We are doing page-based allocations,
-	 * so we must be aligned to a page.
+	 * Enforce minimum alignment that EFI or Linux requires when
+	 * requesting a specific address.  We are doing page-based (or
+	 * larger) allocations, and both the address and size must meet
+	 * alignment constraints.
 	 */
 	if (align < EFI_ALLOC_ALIGN)
 		align = EFI_ALLOC_ALIGN;
 
-	nr_pages = round_up(size, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
+	size = round_up(size, EFI_ALLOC_ALIGN);
+	nr_pages = size / EFI_PAGE_SIZE;
 	for (i = 0; i < map_size / desc_size; i++) {
 		efi_memory_desc_t *desc;
 		unsigned long m = (unsigned long)map;
@@ -300,7 +295,7 @@ efi_status_t efi_low_alloc(efi_system_ta
 			continue;
 
 		start = desc->phys_addr;
-		end = start + desc->num_pages * (1UL << EFI_PAGE_SHIFT);
+		end = start + desc->num_pages * EFI_PAGE_SIZE;
 
 		/*
 		 * Don't allocate at 0x0. It will confuse code that
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/libstub/fdt.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/fdt.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/libstub/fdt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/fdt.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,13 +16,10 @@
 
 #include "efistub.h"
 
-efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
-			unsigned long orig_fdt_size,
-			void *fdt, int new_fdt_size, char *cmdline_ptr,
-			u64 initrd_addr, u64 initrd_size,
-			efi_memory_desc_t *memory_map,
-			unsigned long map_size, unsigned long desc_size,
-			u32 desc_ver)
+static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
+			       unsigned long orig_fdt_size,
+			       void *fdt, int new_fdt_size, char *cmdline_ptr,
+			       u64 initrd_addr, u64 initrd_size)
 {
 	int node, num_rsv;
 	int status;
@@ -101,25 +98,23 @@ efi_status_t update_fdt(efi_system_table
 	if (status)
 		goto fdt_set_fail;
 
-	fdt_val64 = cpu_to_fdt64((u64)(unsigned long)memory_map);
+	fdt_val64 = U64_MAX; /* placeholder */
 	status = fdt_setprop(fdt, node, "linux,uefi-mmap-start",
 			     &fdt_val64,  sizeof(fdt_val64));
 	if (status)
 		goto fdt_set_fail;
 
-	fdt_val32 = cpu_to_fdt32(map_size);
+	fdt_val32 = U32_MAX; /* placeholder */
 	status = fdt_setprop(fdt, node, "linux,uefi-mmap-size",
 			     &fdt_val32,  sizeof(fdt_val32));
 	if (status)
 		goto fdt_set_fail;
 
-	fdt_val32 = cpu_to_fdt32(desc_size);
 	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-size",
 			     &fdt_val32, sizeof(fdt_val32));
 	if (status)
 		goto fdt_set_fail;
 
-	fdt_val32 = cpu_to_fdt32(desc_ver);
 	status = fdt_setprop(fdt, node, "linux,uefi-mmap-desc-ver",
 			     &fdt_val32, sizeof(fdt_val32));
 	if (status)
@@ -148,6 +143,43 @@ fdt_set_fail:
 	return EFI_LOAD_ERROR;
 }
 
+static efi_status_t update_fdt_memmap(void *fdt, struct efi_boot_memmap *map)
+{
+	int node = fdt_path_offset(fdt, "/chosen");
+	u64 fdt_val64;
+	u32 fdt_val32;
+	int err;
+
+	if (node < 0)
+		return EFI_LOAD_ERROR;
+
+	fdt_val64 = cpu_to_fdt64((unsigned long)*map->map);
+	err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-start",
+				  &fdt_val64, sizeof(fdt_val64));
+	if (err)
+		return EFI_LOAD_ERROR;
+
+	fdt_val32 = cpu_to_fdt32(*map->map_size);
+	err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-size",
+				  &fdt_val32, sizeof(fdt_val32));
+	if (err)
+		return EFI_LOAD_ERROR;
+
+	fdt_val32 = cpu_to_fdt32(*map->desc_size);
+	err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-size",
+				  &fdt_val32, sizeof(fdt_val32));
+	if (err)
+		return EFI_LOAD_ERROR;
+
+	fdt_val32 = cpu_to_fdt32(*map->desc_ver);
+	err = fdt_setprop_inplace(fdt, node, "linux,uefi-mmap-desc-ver",
+				  &fdt_val32, sizeof(fdt_val32));
+	if (err)
+		return EFI_LOAD_ERROR;
+
+	return EFI_SUCCESS;
+}
+
 #ifndef EFI_FDT_ALIGN
 #define EFI_FDT_ALIGN EFI_PAGE_SIZE
 #endif
@@ -155,6 +187,7 @@ fdt_set_fail:
 struct exit_boot_struct {
 	efi_memory_desc_t *runtime_map;
 	int *runtime_entry_count;
+	void *new_fdt_addr;
 };
 
 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
@@ -170,7 +203,7 @@ static efi_status_t exit_boot_func(efi_s
 	efi_get_virtmap(*map->map, *map->map_size, *map->desc_size,
 			p->runtime_map, p->runtime_entry_count);
 
-	return EFI_SUCCESS;
+	return update_fdt_memmap(p->new_fdt_addr, map);
 }
 
 /*
@@ -243,20 +276,10 @@ efi_status_t allocate_new_fdt_and_exit_b
 			goto fail;
 		}
 
-		/*
-		 * Now that we have done our final memory allocation (and free)
-		 * we can get the memory map key  needed for
-		 * exit_boot_services().
-		 */
-		status = efi_get_memory_map(sys_table, &map);
-		if (status != EFI_SUCCESS)
-			goto fail_free_new_fdt;
-
 		status = update_fdt(sys_table,
 				    (void *)fdt_addr, fdt_size,
 				    (void *)*new_fdt_addr, new_fdt_size,
-				    cmdline_ptr, initrd_addr, initrd_size,
-				    memory_map, map_size, desc_size, desc_ver);
+				    cmdline_ptr, initrd_addr, initrd_size);
 
 		/* Succeeding the first time is the expected case. */
 		if (status == EFI_SUCCESS)
@@ -266,22 +289,19 @@ efi_status_t allocate_new_fdt_and_exit_b
 			/*
 			 * We need to allocate more space for the new
 			 * device tree, so free existing buffer that is
-			 * too small.  Also free memory map, as we will need
-			 * to get new one that reflects the free/alloc we do
-			 * on the device tree buffer.
+			 * too small.
 			 */
 			efi_free(sys_table, new_fdt_size, *new_fdt_addr);
-			sys_table->boottime->free_pool(memory_map);
 			new_fdt_size += EFI_PAGE_SIZE;
 		} else {
 			pr_efi_err(sys_table, "Unable to construct new device tree.\n");
-			goto fail_free_mmap;
+			goto fail_free_new_fdt;
 		}
 	}
 
-	sys_table->boottime->free_pool(memory_map);
 	priv.runtime_map = runtime_map;
 	priv.runtime_entry_count = &runtime_entry_count;
+	priv.new_fdt_addr = (void *)*new_fdt_addr;
 	status = efi_exit_boot_services(sys_table, handle, &map, &priv,
 					exit_boot_func);
 
@@ -319,9 +339,6 @@ efi_status_t allocate_new_fdt_and_exit_b
 
 	pr_efi_err(sys_table, "Exit boot services failed.\n");
 
-fail_free_mmap:
-	sys_table->boottime->free_pool(memory_map);
-
 fail_free_new_fdt:
 	efi_free(sys_table, new_fdt_size, *new_fdt_addr);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/libstub/Makefile linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/Makefile
--- linux-libre-4.9-gnu/drivers/firmware/efi/libstub/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -6,7 +6,7 @@
 #
 cflags-$(CONFIG_X86_32)		:= -march=i386
 cflags-$(CONFIG_X86_64)		:= -mcmodel=small
-cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+cflags-$(CONFIG_X86)		+= -m$(BITS) -D__KERNEL__ -O2 \
 				   -fPIC -fno-strict-aliasing -mno-red-zone \
 				   -mno-mmx -mno-sse
 
@@ -36,11 +36,11 @@ arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c
 $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
 	$(call if_changed_rule,cc_o_c)
 
-lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o \
+lib-$(CONFIG_EFI_ARMSTUB)	+= arm-stub.o fdt.o string.o random.o \
 				   $(patsubst %.c,lib-%.o,$(arm-deps))
 
 lib-$(CONFIG_ARM)		+= arm32-stub.o
-lib-$(CONFIG_ARM64)		+= arm64-stub.o random.o
+lib-$(CONFIG_ARM64)		+= arm64-stub.o
 CFLAGS_arm64-stub.o 		:= -DTEXT_OFFSET=$(TEXT_OFFSET)
 
 #
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/libstub/random.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/random.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/libstub/random.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/libstub/random.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,7 @@
  */
 
 #include <linux/efi.h>
+#include <linux/log2.h>
 #include <asm/efi.h>
 
 #include "efistub.h"
@@ -41,21 +42,23 @@ efi_status_t efi_get_random_bytes(efi_sy
  */
 static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
 					 unsigned long size,
-					 unsigned long align)
+					 unsigned long align_shift)
 {
-	u64 start, end;
+	unsigned long align = 1UL << align_shift;
+	u64 first_slot, last_slot, region_end;
 
 	if (md->type != EFI_CONVENTIONAL_MEMORY)
 		return 0;
 
-	start = round_up(md->phys_addr, align);
-	end = round_down(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - size,
-			 align);
+	region_end = min((u64)ULONG_MAX, md->phys_addr + md->num_pages*EFI_PAGE_SIZE - 1);
 
-	if (start > end)
+	first_slot = round_up(md->phys_addr, align);
+	last_slot = round_down(region_end - size + 1, align);
+
+	if (first_slot > last_slot)
 		return 0;
 
-	return (end - start + 1) / align;
+	return ((unsigned long)(last_slot - first_slot) >> align_shift) + 1;
 }
 
 /*
@@ -98,7 +101,7 @@ efi_status_t efi_random_alloc(efi_system
 		efi_memory_desc_t *md = (void *)memory_map + map_offset;
 		unsigned long slots;
 
-		slots = get_entry_num_slots(md, size, align);
+		slots = get_entry_num_slots(md, size, ilog2(align));
 		MD_NUM_SLOTS(md) = slots;
 		total_slots += slots;
 	}
@@ -141,3 +144,51 @@ efi_status_t efi_random_alloc(efi_system
 
 	return status;
 }
+
+#define RANDOM_SEED_SIZE	32
+
+efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
+{
+	efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
+	efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
+	efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+	struct efi_rng_protocol *rng;
+	struct linux_efi_random_seed *seed;
+	efi_status_t status;
+
+	status = efi_call_early(locate_protocol, &rng_proto, NULL,
+				(void **)&rng);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
+				sizeof(*seed) + RANDOM_SEED_SIZE,
+				(void **)&seed);
+	if (status != EFI_SUCCESS)
+		return status;
+
+	status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE,
+			      seed->bits);
+	if (status == EFI_UNSUPPORTED)
+		/*
+		 * Use whatever algorithm we have available if the raw algorithm
+		 * is not implemented.
+		 */
+		status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+				      seed->bits);
+
+	if (status != EFI_SUCCESS)
+		goto err_freepool;
+
+	seed->size = RANDOM_SEED_SIZE;
+	status = efi_call_early(install_configuration_table, &rng_table_guid,
+				seed);
+	if (status != EFI_SUCCESS)
+		goto err_freepool;
+
+	return EFI_SUCCESS;
+
+err_freepool:
+	efi_call_early(free_pool, seed);
+	return status;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/Makefile linux-libre-4.10-rc8-gnu/drivers/firmware/efi/Makefile
--- linux-libre-4.9-gnu/drivers/firmware/efi/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@ obj-$(CONFIG_EFI_STUB)			+= libstub/
 obj-$(CONFIG_EFI_FAKE_MEMMAP)		+= fake_mem.o
 obj-$(CONFIG_EFI_BOOTLOADER_CONTROL)	+= efibc.o
 obj-$(CONFIG_EFI_TEST)			+= test/
+obj-$(CONFIG_EFI_DEV_PATH_PARSER)	+= dev-path-parser.o
+obj-$(CONFIG_APPLE_PROPERTIES)		+= apple-properties.o
 
 arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
 obj-$(CONFIG_ARM)			+= $(arm-obj-y)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/memmap.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/memmap.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/memmap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/memmap.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,44 @@
 #include <linux/efi.h>
 #include <linux/io.h>
 #include <asm/early_ioremap.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+
+static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
+{
+	return memblock_alloc(size, 0);
+}
+
+static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
+{
+	unsigned int order = get_order(size);
+	struct page *p = alloc_pages(GFP_KERNEL, order);
+
+	if (!p)
+		return 0;
+
+	return PFN_PHYS(page_to_pfn(p));
+}
+
+/**
+ * efi_memmap_alloc - Allocate memory for the EFI memory map
+ * @num_entries: Number of entries in the allocated map.
+ *
+ * Depending on whether mm_init() has already been invoked or not,
+ * either memblock or "normal" page allocation is used.
+ *
+ * Returns the physical address of the allocated memory map on
+ * success, zero on failure.
+ */
+phys_addr_t __init efi_memmap_alloc(unsigned int num_entries)
+{
+	unsigned long size = num_entries * efi.memmap.desc_size;
+
+	if (slab_is_available())
+		return __efi_memmap_alloc_late(size);
+
+	return __efi_memmap_alloc_early(size);
+}
 
 /**
  * __efi_memmap_init - Common code for mapping the EFI memory map
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/efi/test/efi_test.c linux-libre-4.10-rc8-gnu/drivers/firmware/efi/test/efi_test.c
--- linux-libre-4.9-gnu/drivers/firmware/efi/test/efi_test.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/efi/test/efi_test.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,6 @@
  *
  */
 
-#include <linux/version.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -156,7 +155,7 @@ static long efi_runtime_get_variable(uns
 {
 	struct efi_getvariable __user *getvariable_user;
 	struct efi_getvariable getvariable;
-	unsigned long datasize, prev_datasize, *dz;
+	unsigned long datasize = 0, prev_datasize, *dz;
 	efi_guid_t vendor_guid, *vd = NULL;
 	efi_status_t status;
 	efi_char16_t *name = NULL;
@@ -266,14 +265,10 @@ static long efi_runtime_set_variable(uns
 			return rv;
 	}
 
-	data = kmalloc(setvariable.data_size, GFP_KERNEL);
-	if (!data) {
+	data = memdup_user(setvariable.data, setvariable.data_size);
+	if (IS_ERR(data)) {
 		kfree(name);
-		return -ENOMEM;
-	}
-	if (copy_from_user(data, setvariable.data, setvariable.data_size)) {
-		rv = -EFAULT;
-		goto out;
+		return PTR_ERR(data);
 	}
 
 	status = efi.set_variable(name, &vendor_guid,
@@ -429,7 +424,7 @@ static long efi_runtime_get_nextvariable
 	efi_guid_t *vd = NULL;
 	efi_guid_t vendor_guid;
 	efi_char16_t *name = NULL;
-	int rv;
+	int rv = 0;
 
 	getnextvariablename_user = (struct efi_getnextvariablename __user *)arg;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/Kconfig linux-libre-4.10-rc8-gnu/drivers/firmware/Kconfig
--- linux-libre-4.9-gnu/drivers/firmware/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,17 @@ menu "Firmware Drivers"
 config ARM_PSCI_FW
 	bool
 
+config ARM_PSCI_CHECKER
+	bool "ARM PSCI checker"
+	depends on ARM_PSCI_FW && HOTPLUG_CPU && !TORTURE_TEST
+	help
+	  Run the PSCI checker during startup. This checks that hotplug and
+	  suspend operations work correctly when using PSCI.
+
+	  The torture tests may interfere with the PSCI checker by turning CPUs
+	  on and off through hotplug, so for now torture tests and PSCI checker
+	  are mutually exclusive.
+
 config ARM_SCPI_PROTOCOL
 	tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
 	depends on MAILBOX
@@ -203,6 +214,21 @@ config QCOM_SCM_64
 	def_bool y
 	depends on QCOM_SCM && ARM64
 
+config TI_SCI_PROTOCOL
+	tristate "TI System Control Interface (TISCI) Message Protocol"
+	depends on TI_MESSAGE_MANAGER
+	help
+	  TI System Control Interface (TISCI) Message Protocol is used to manage
+	  compute systems such as ARM, DSP etc with the system controller in
+	  complex System on Chip(SoC) such as those found on certain keystone
+	  generation SoC from TI.
+
+	  System controller provides various facilities including power
+	  management function support.
+
+	  This protocol library is used by client drivers to use the features
+	  provided by the system controller.
+
 config HAVE_ARM_SMCCC
 	bool
 
@@ -210,5 +236,6 @@ source "drivers/firmware/broadcom/Kconfi
 source "drivers/firmware/google/Kconfig"
 source "drivers/firmware/efi/Kconfig"
 source "drivers/firmware/meson/Kconfig"
+source "drivers/firmware/tegra/Kconfig"
 
 endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/Makefile linux-libre-4.10-rc8-gnu/drivers/firmware/Makefile
--- linux-libre-4.9-gnu/drivers/firmware/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,7 @@
 # Makefile for the linux kernel.
 #
 obj-$(CONFIG_ARM_PSCI_FW)	+= psci.o
+obj-$(CONFIG_ARM_PSCI_CHECKER)	+= psci_checker.o
 obj-$(CONFIG_ARM_SCPI_PROTOCOL)	+= arm_scpi.o
 obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o
 obj-$(CONFIG_DMI)		+= dmi_scan.o
@@ -20,9 +21,11 @@ obj-$(CONFIG_QCOM_SCM)		+= qcom_scm.o
 obj-$(CONFIG_QCOM_SCM_64)	+= qcom_scm-64.o
 obj-$(CONFIG_QCOM_SCM_32)	+= qcom_scm-32.o
 CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a
+obj-$(CONFIG_TI_SCI_PROTOCOL)	+= ti_sci.o
 
 obj-y				+= broadcom/
 obj-y				+= meson/
 obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
 obj-$(CONFIG_EFI)		+= efi/
 obj-$(CONFIG_UEFI_CPER)		+= efi/
+obj-y				+= tegra/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/psci.c linux-libre-4.10-rc8-gnu/drivers/firmware/psci.c
--- linux-libre-4.9-gnu/drivers/firmware/psci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/psci.c	2017-02-12 16:03:20.000000000 -0500
@@ -630,7 +630,7 @@ int __init psci_dt_init(void)
 
 	np = of_find_matching_node_and_match(NULL, psci_of_match, &matched_np);
 
-	if (!np)
+	if (!np || !of_device_is_available(np))
 		return -ENODEV;
 
 	init_fn = (psci_initcall_t)matched_np->data;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/psci_checker.c linux-libre-4.10-rc8-gnu/drivers/firmware/psci_checker.c
--- linux-libre-4.9-gnu/drivers/firmware/psci_checker.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/psci_checker.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,490 @@
+/*
+ * This program is free software; you can 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.
+ *
+ * Copyright (C) 2016 ARM Limited
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/atomic.h>
+#include <linux/completion.h>
+#include <linux/cpu.h>
+#include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/preempt.h>
+#include <linux/psci.h>
+#include <linux/slab.h>
+#include <linux/tick.h>
+#include <linux/topology.h>
+
+#include <asm/cpuidle.h>
+
+#include <uapi/linux/psci.h>
+
+#define NUM_SUSPEND_CYCLE (10)
+
+static unsigned int nb_available_cpus;
+static int tos_resident_cpu = -1;
+
+static atomic_t nb_active_threads;
+static struct completion suspend_threads_started =
+	COMPLETION_INITIALIZER(suspend_threads_started);
+static struct completion suspend_threads_done =
+	COMPLETION_INITIALIZER(suspend_threads_done);
+
+/*
+ * We assume that PSCI operations are used if they are available. This is not
+ * necessarily true on arm64, since the decision is based on the
+ * "enable-method" property of each CPU in the DT, but given that there is no
+ * arch-specific way to check this, we assume that the DT is sensible.
+ */
+static int psci_ops_check(void)
+{
+	int migrate_type = -1;
+	int cpu;
+
+	if (!(psci_ops.cpu_off && psci_ops.cpu_on && psci_ops.cpu_suspend)) {
+		pr_warn("Missing PSCI operations, aborting tests\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (psci_ops.migrate_info_type)
+		migrate_type = psci_ops.migrate_info_type();
+
+	if (migrate_type == PSCI_0_2_TOS_UP_MIGRATE ||
+	    migrate_type == PSCI_0_2_TOS_UP_NO_MIGRATE) {
+		/* There is a UP Trusted OS, find on which core it resides. */
+		for_each_online_cpu(cpu)
+			if (psci_tos_resident_on(cpu)) {
+				tos_resident_cpu = cpu;
+				break;
+			}
+		if (tos_resident_cpu == -1)
+			pr_warn("UP Trusted OS resides on no online CPU\n");
+	}
+
+	return 0;
+}
+
+static int find_clusters(const struct cpumask *cpus,
+			 const struct cpumask **clusters)
+{
+	unsigned int nb = 0;
+	cpumask_var_t tmp;
+
+	if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
+		return -ENOMEM;
+	cpumask_copy(tmp, cpus);
+
+	while (!cpumask_empty(tmp)) {
+		const struct cpumask *cluster =
+			topology_core_cpumask(cpumask_any(tmp));
+
+		clusters[nb++] = cluster;
+		cpumask_andnot(tmp, tmp, cluster);
+	}
+
+	free_cpumask_var(tmp);
+	return nb;
+}
+
+/*
+ * offlined_cpus is a temporary array but passing it as an argument avoids
+ * multiple allocations.
+ */
+static unsigned int down_and_up_cpus(const struct cpumask *cpus,
+				     struct cpumask *offlined_cpus)
+{
+	int cpu;
+	int err = 0;
+
+	cpumask_clear(offlined_cpus);
+
+	/* Try to power down all CPUs in the mask. */
+	for_each_cpu(cpu, cpus) {
+		int ret = cpu_down(cpu);
+
+		/*
+		 * cpu_down() checks the number of online CPUs before the TOS
+		 * resident CPU.
+		 */
+		if (cpumask_weight(offlined_cpus) + 1 == nb_available_cpus) {
+			if (ret != -EBUSY) {
+				pr_err("Unexpected return code %d while trying "
+				       "to power down last online CPU %d\n",
+				       ret, cpu);
+				++err;
+			}
+		} else if (cpu == tos_resident_cpu) {
+			if (ret != -EPERM) {
+				pr_err("Unexpected return code %d while trying "
+				       "to power down TOS resident CPU %d\n",
+				       ret, cpu);
+				++err;
+			}
+		} else if (ret != 0) {
+			pr_err("Error occurred (%d) while trying "
+			       "to power down CPU %d\n", ret, cpu);
+			++err;
+		}
+
+		if (ret == 0)
+			cpumask_set_cpu(cpu, offlined_cpus);
+	}
+
+	/* Try to power up all the CPUs that have been offlined. */
+	for_each_cpu(cpu, offlined_cpus) {
+		int ret = cpu_up(cpu);
+
+		if (ret != 0) {
+			pr_err("Error occurred (%d) while trying "
+			       "to power up CPU %d\n", ret, cpu);
+			++err;
+		} else {
+			cpumask_clear_cpu(cpu, offlined_cpus);
+		}
+	}
+
+	/*
+	 * Something went bad at some point and some CPUs could not be turned
+	 * back on.
+	 */
+	WARN_ON(!cpumask_empty(offlined_cpus) ||
+		num_online_cpus() != nb_available_cpus);
+
+	return err;
+}
+
+static int hotplug_tests(void)
+{
+	int err;
+	cpumask_var_t offlined_cpus;
+	int i, nb_cluster;
+	const struct cpumask **clusters;
+	char *page_buf;
+
+	err = -ENOMEM;
+	if (!alloc_cpumask_var(&offlined_cpus, GFP_KERNEL))
+		return err;
+	/* We may have up to nb_available_cpus clusters. */
+	clusters = kmalloc_array(nb_available_cpus, sizeof(*clusters),
+				 GFP_KERNEL);
+	if (!clusters)
+		goto out_free_cpus;
+	page_buf = (char *)__get_free_page(GFP_KERNEL);
+	if (!page_buf)
+		goto out_free_clusters;
+
+	err = 0;
+	nb_cluster = find_clusters(cpu_online_mask, clusters);
+
+	/*
+	 * Of course the last CPU cannot be powered down and cpu_down() should
+	 * refuse doing that.
+	 */
+	pr_info("Trying to turn off and on again all CPUs\n");
+	err += down_and_up_cpus(cpu_online_mask, offlined_cpus);
+
+	/*
+	 * Take down CPUs by cluster this time. When the last CPU is turned
+	 * off, the cluster itself should shut down.
+	 */
+	for (i = 0; i < nb_cluster; ++i) {
+		int cluster_id =
+			topology_physical_package_id(cpumask_any(clusters[i]));
+		ssize_t len = cpumap_print_to_pagebuf(true, page_buf,
+						      clusters[i]);
+		/* Remove trailing newline. */
+		page_buf[len - 1] = '\0';
+		pr_info("Trying to turn off and on again cluster %d "
+			"(CPUs %s)\n", cluster_id, page_buf);
+		err += down_and_up_cpus(clusters[i], offlined_cpus);
+	}
+
+	free_page((unsigned long)page_buf);
+out_free_clusters:
+	kfree(clusters);
+out_free_cpus:
+	free_cpumask_var(offlined_cpus);
+	return err;
+}
+
+static void dummy_callback(unsigned long ignored) {}
+
+static int suspend_cpu(int index, bool broadcast)
+{
+	int ret;
+
+	arch_cpu_idle_enter();
+
+	if (broadcast) {
+		/*
+		 * The local timer will be shut down, we need to enter tick
+		 * broadcast.
+		 */
+		ret = tick_broadcast_enter();
+		if (ret) {
+			/*
+			 * In the absence of hardware broadcast mechanism,
+			 * this CPU might be used to broadcast wakeups, which
+			 * may be why entering tick broadcast has failed.
+			 * There is little the kernel can do to work around
+			 * that, so enter WFI instead (idle state 0).
+			 */
+			cpu_do_idle();
+			ret = 0;
+			goto out_arch_exit;
+		}
+	}
+
+	/*
+	 * Replicate the common ARM cpuidle enter function
+	 * (arm_enter_idle_state).
+	 */
+	ret = CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, index);
+
+	if (broadcast)
+		tick_broadcast_exit();
+
+out_arch_exit:
+	arch_cpu_idle_exit();
+
+	return ret;
+}
+
+static int suspend_test_thread(void *arg)
+{
+	int cpu = (long)arg;
+	int i, nb_suspend = 0, nb_shallow_sleep = 0, nb_err = 0;
+	struct sched_param sched_priority = { .sched_priority = MAX_RT_PRIO-1 };
+	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv;
+	/* No need for an actual callback, we just want to wake up the CPU. */
+	struct timer_list wakeup_timer;
+
+	/* Wait for the main thread to give the start signal. */
+	wait_for_completion(&suspend_threads_started);
+
+	/* Set maximum priority to preempt all other threads on this CPU. */
+	if (sched_setscheduler_nocheck(current, SCHED_FIFO, &sched_priority))
+		pr_warn("Failed to set suspend thread scheduler on CPU %d\n",
+			cpu);
+
+	dev = this_cpu_read(cpuidle_devices);
+	drv = cpuidle_get_cpu_driver(dev);
+
+	pr_info("CPU %d entering suspend cycles, states 1 through %d\n",
+		cpu, drv->state_count - 1);
+
+	setup_timer_on_stack(&wakeup_timer, dummy_callback, 0);
+	for (i = 0; i < NUM_SUSPEND_CYCLE; ++i) {
+		int index;
+		/*
+		 * Test all possible states, except 0 (which is usually WFI and
+		 * doesn't use PSCI).
+		 */
+		for (index = 1; index < drv->state_count; ++index) {
+			struct cpuidle_state *state = &drv->states[index];
+			bool broadcast = state->flags & CPUIDLE_FLAG_TIMER_STOP;
+			int ret;
+
+			/*
+			 * Set the timer to wake this CPU up in some time (which
+			 * should be largely sufficient for entering suspend).
+			 * If the local tick is disabled when entering suspend,
+			 * suspend_cpu() takes care of switching to a broadcast
+			 * tick, so the timer will still wake us up.
+			 */
+			mod_timer(&wakeup_timer, jiffies +
+				  usecs_to_jiffies(state->target_residency));
+
+			/* IRQs must be disabled during suspend operations. */
+			local_irq_disable();
+
+			ret = suspend_cpu(index, broadcast);
+
+			/*
+			 * We have woken up. Re-enable IRQs to handle any
+			 * pending interrupt, do not wait until the end of the
+			 * loop.
+			 */
+			local_irq_enable();
+
+			if (ret == index) {
+				++nb_suspend;
+			} else if (ret >= 0) {
+				/* We did not enter the expected state. */
+				++nb_shallow_sleep;
+			} else {
+				pr_err("Failed to suspend CPU %d: error %d "
+				       "(requested state %d, cycle %d)\n",
+				       cpu, ret, index, i);
+				++nb_err;
+			}
+		}
+	}
+
+	/*
+	 * Disable the timer to make sure that the timer will not trigger
+	 * later.
+	 */
+	del_timer(&wakeup_timer);
+
+	if (atomic_dec_return_relaxed(&nb_active_threads) == 0)
+		complete(&suspend_threads_done);
+
+	/* Give up on RT scheduling and wait for termination. */
+	sched_priority.sched_priority = 0;
+	if (sched_setscheduler_nocheck(current, SCHED_NORMAL, &sched_priority))
+		pr_warn("Failed to set suspend thread scheduler on CPU %d\n",
+			cpu);
+	for (;;) {
+		/* Needs to be set first to avoid missing a wakeup. */
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (kthread_should_stop()) {
+			__set_current_state(TASK_RUNNING);
+			break;
+		}
+		schedule();
+	}
+
+	pr_info("CPU %d suspend test results: success %d, shallow states %d, errors %d\n",
+		cpu, nb_suspend, nb_shallow_sleep, nb_err);
+
+	return nb_err;
+}
+
+static int suspend_tests(void)
+{
+	int i, cpu, err = 0;
+	struct task_struct **threads;
+	int nb_threads = 0;
+
+	threads = kmalloc_array(nb_available_cpus, sizeof(*threads),
+				GFP_KERNEL);
+	if (!threads)
+		return -ENOMEM;
+
+	/*
+	 * Stop cpuidle to prevent the idle tasks from entering a deep sleep
+	 * mode, as it might interfere with the suspend threads on other CPUs.
+	 * This does not prevent the suspend threads from using cpuidle (only
+	 * the idle tasks check this status). Take the idle lock so that
+	 * the cpuidle driver and device look-up can be carried out safely.
+	 */
+	cpuidle_pause_and_lock();
+
+	for_each_online_cpu(cpu) {
+		struct task_struct *thread;
+		/* Check that cpuidle is available on that CPU. */
+		struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
+		struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+
+		if (!dev || !drv) {
+			pr_warn("cpuidle not available on CPU %d, ignoring\n",
+				cpu);
+			continue;
+		}
+
+		thread = kthread_create_on_cpu(suspend_test_thread,
+					       (void *)(long)cpu, cpu,
+					       "psci_suspend_test");
+		if (IS_ERR(thread))
+			pr_err("Failed to create kthread on CPU %d\n", cpu);
+		else
+			threads[nb_threads++] = thread;
+	}
+
+	if (nb_threads < 1) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	atomic_set(&nb_active_threads, nb_threads);
+
+	/*
+	 * Wake up the suspend threads. To avoid the main thread being preempted
+	 * before all the threads have been unparked, the suspend threads will
+	 * wait for the completion of suspend_threads_started.
+	 */
+	for (i = 0; i < nb_threads; ++i)
+		wake_up_process(threads[i]);
+	complete_all(&suspend_threads_started);
+
+	wait_for_completion(&suspend_threads_done);
+
+
+	/* Stop and destroy all threads, get return status. */
+	for (i = 0; i < nb_threads; ++i)
+		err += kthread_stop(threads[i]);
+ out:
+	cpuidle_resume_and_unlock();
+	kfree(threads);
+	return err;
+}
+
+static int __init psci_checker(void)
+{
+	int ret;
+
+	/*
+	 * Since we're in an initcall, we assume that all the CPUs that all
+	 * CPUs that can be onlined have been onlined.
+	 *
+	 * The tests assume that hotplug is enabled but nobody else is using it,
+	 * otherwise the results will be unpredictable. However, since there
+	 * is no userspace yet in initcalls, that should be fine, as long as
+	 * no torture test is running at the same time (see Kconfig).
+	 */
+	nb_available_cpus = num_online_cpus();
+
+	/* Check PSCI operations are set up and working. */
+	ret = psci_ops_check();
+	if (ret)
+		return ret;
+
+	pr_info("PSCI checker started using %u CPUs\n", nb_available_cpus);
+
+	pr_info("Starting hotplug tests\n");
+	ret = hotplug_tests();
+	if (ret == 0)
+		pr_info("Hotplug tests passed OK\n");
+	else if (ret > 0)
+		pr_err("%d error(s) encountered in hotplug tests\n", ret);
+	else {
+		pr_err("Out of memory\n");
+		return ret;
+	}
+
+	pr_info("Starting suspend tests (%d cycles per state)\n",
+		NUM_SUSPEND_CYCLE);
+	ret = suspend_tests();
+	if (ret == 0)
+		pr_info("Suspend tests passed OK\n");
+	else if (ret > 0)
+		pr_err("%d error(s) encountered in suspend tests\n", ret);
+	else {
+		switch (ret) {
+		case -ENOMEM:
+			pr_err("Out of memory\n");
+			break;
+		case -ENODEV:
+			pr_warn("Could not start suspend tests on any CPU\n");
+			break;
+		}
+	}
+
+	pr_info("PSCI checker completed\n");
+	return ret < 0 ? ret : 0;
+}
+late_initcall(psci_checker);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/qcom_scm.c linux-libre-4.10-rc8-gnu/drivers/firmware/qcom_scm.c
--- linux-libre-4.9-gnu/drivers/firmware/qcom_scm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/qcom_scm.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,10 @@
 
 #include "qcom_scm.h"
 
+#define SCM_HAS_CORE_CLK	BIT(0)
+#define SCM_HAS_IFACE_CLK	BIT(1)
+#define SCM_HAS_BUS_CLK		BIT(2)
+
 struct qcom_scm {
 	struct device *dev;
 	struct clk *core_clk;
@@ -323,32 +327,40 @@ EXPORT_SYMBOL(qcom_scm_is_available);
 static int qcom_scm_probe(struct platform_device *pdev)
 {
 	struct qcom_scm *scm;
+	unsigned long clks;
 	int ret;
 
 	scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
 	if (!scm)
 		return -ENOMEM;
 
-	scm->core_clk = devm_clk_get(&pdev->dev, "core");
-	if (IS_ERR(scm->core_clk)) {
-		if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
+	clks = (unsigned long)of_device_get_match_data(&pdev->dev);
+	if (clks & SCM_HAS_CORE_CLK) {
+		scm->core_clk = devm_clk_get(&pdev->dev, "core");
+		if (IS_ERR(scm->core_clk)) {
+			if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev,
+					"failed to acquire core clk\n");
 			return PTR_ERR(scm->core_clk);
-
-		scm->core_clk = NULL;
+		}
 	}
 
-	if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) {
+	if (clks & SCM_HAS_IFACE_CLK) {
 		scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
 		if (IS_ERR(scm->iface_clk)) {
 			if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
-				dev_err(&pdev->dev, "failed to acquire iface clk\n");
+				dev_err(&pdev->dev,
+					"failed to acquire iface clk\n");
 			return PTR_ERR(scm->iface_clk);
 		}
+	}
 
+	if (clks & SCM_HAS_BUS_CLK) {
 		scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
 		if (IS_ERR(scm->bus_clk)) {
 			if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
-				dev_err(&pdev->dev, "failed to acquire bus clk\n");
+				dev_err(&pdev->dev,
+					"failed to acquire bus clk\n");
 			return PTR_ERR(scm->bus_clk);
 		}
 	}
@@ -356,7 +368,9 @@ static int qcom_scm_probe(struct platfor
 	scm->reset.ops = &qcom_scm_pas_reset_ops;
 	scm->reset.nr_resets = 1;
 	scm->reset.of_node = pdev->dev.of_node;
-	reset_controller_register(&scm->reset);
+	ret = devm_reset_controller_register(&pdev->dev, &scm->reset);
+	if (ret)
+		return ret;
 
 	/* vote for max clk rate for highest performance */
 	ret = clk_set_rate(scm->core_clk, INT_MAX);
@@ -372,10 +386,23 @@ static int qcom_scm_probe(struct platfor
 }
 
 static const struct of_device_id qcom_scm_dt_match[] = {
-	{ .compatible = "qcom,scm-apq8064",},
-	{ .compatible = "qcom,scm-msm8660",},
-	{ .compatible = "qcom,scm-msm8960",},
-	{ .compatible = "qcom,scm",},
+	{ .compatible = "qcom,scm-apq8064",
+	  .data = (void *) SCM_HAS_CORE_CLK,
+	},
+	{ .compatible = "qcom,scm-msm8660",
+	  .data = (void *) SCM_HAS_CORE_CLK,
+	},
+	{ .compatible = "qcom,scm-msm8960",
+	  .data = (void *) SCM_HAS_CORE_CLK,
+	},
+	{ .compatible = "qcom,scm-msm8996",
+	  .data = NULL, /* no clocks */
+	},
+	{ .compatible = "qcom,scm",
+	  .data = (void *)(SCM_HAS_CORE_CLK
+			   | SCM_HAS_IFACE_CLK
+			   | SCM_HAS_BUS_CLK),
+	},
 	{}
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/tegra/bpmp.c linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/bpmp.c
--- linux-libre-4.9-gnu/drivers/firmware/tegra/bpmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/bpmp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,868 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/clk/tegra.h>
+#include <linux/genalloc.h>
+#include <linux/mailbox_client.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+
+#include <soc/tegra/bpmp.h>
+#include <soc/tegra/bpmp-abi.h>
+#include <soc/tegra/ivc.h>
+
+#define MSG_ACK		BIT(0)
+#define MSG_RING	BIT(1)
+
+static inline struct tegra_bpmp *
+mbox_client_to_bpmp(struct mbox_client *client)
+{
+	return container_of(client, struct tegra_bpmp, mbox.client);
+}
+
+struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
+{
+	struct platform_device *pdev;
+	struct tegra_bpmp *bpmp;
+	struct device_node *np;
+
+	np = of_parse_phandle(dev->of_node, "nvidia,bpmp", 0);
+	if (!np)
+		return ERR_PTR(-ENOENT);
+
+	pdev = of_find_device_by_node(np);
+	if (!pdev) {
+		bpmp = ERR_PTR(-ENODEV);
+		goto put;
+	}
+
+	bpmp = platform_get_drvdata(pdev);
+	if (!bpmp) {
+		bpmp = ERR_PTR(-EPROBE_DEFER);
+		put_device(&pdev->dev);
+		goto put;
+	}
+
+put:
+	of_node_put(np);
+	return bpmp;
+}
+EXPORT_SYMBOL_GPL(tegra_bpmp_get);
+
+void tegra_bpmp_put(struct tegra_bpmp *bpmp)
+{
+	if (bpmp)
+		put_device(bpmp->dev);
+}
+EXPORT_SYMBOL_GPL(tegra_bpmp_put);
+
+static int tegra_bpmp_channel_get_index(struct tegra_bpmp_channel *channel)
+{
+	return channel - channel->bpmp->channels;
+}
+
+static int
+tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel)
+{
+	struct tegra_bpmp *bpmp = channel->bpmp;
+	unsigned int offset, count;
+	int index;
+
+	offset = bpmp->soc->channels.thread.offset;
+	count = bpmp->soc->channels.thread.count;
+
+	index = tegra_bpmp_channel_get_index(channel);
+	if (index < 0)
+		return index;
+
+	if (index < offset || index >= offset + count)
+		return -EINVAL;
+
+	return index - offset;
+}
+
+static struct tegra_bpmp_channel *
+tegra_bpmp_channel_get_thread(struct tegra_bpmp *bpmp, unsigned int index)
+{
+	unsigned int offset = bpmp->soc->channels.thread.offset;
+	unsigned int count = bpmp->soc->channels.thread.count;
+
+	if (index >= count)
+		return NULL;
+
+	return &bpmp->channels[offset + index];
+}
+
+static struct tegra_bpmp_channel *
+tegra_bpmp_channel_get_tx(struct tegra_bpmp *bpmp)
+{
+	unsigned int offset = bpmp->soc->channels.cpu_tx.offset;
+
+	return &bpmp->channels[offset + smp_processor_id()];
+}
+
+static struct tegra_bpmp_channel *
+tegra_bpmp_channel_get_rx(struct tegra_bpmp *bpmp)
+{
+	unsigned int offset = bpmp->soc->channels.cpu_rx.offset;
+
+	return &bpmp->channels[offset];
+}
+
+static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
+{
+	return (msg->tx.size <= MSG_DATA_MIN_SZ) &&
+	       (msg->rx.size <= MSG_DATA_MIN_SZ) &&
+	       (msg->tx.size == 0 || msg->tx.data) &&
+	       (msg->rx.size == 0 || msg->rx.data);
+}
+
+static bool tegra_bpmp_master_acked(struct tegra_bpmp_channel *channel)
+{
+	void *frame;
+
+	frame = tegra_ivc_read_get_next_frame(channel->ivc);
+	if (IS_ERR(frame)) {
+		channel->ib = NULL;
+		return false;
+	}
+
+	channel->ib = frame;
+
+	return true;
+}
+
+static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel)
+{
+	unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
+	ktime_t end;
+
+	end = ktime_add_us(ktime_get(), timeout);
+
+	do {
+		if (tegra_bpmp_master_acked(channel))
+			return 0;
+	} while (ktime_before(ktime_get(), end));
+
+	return -ETIMEDOUT;
+}
+
+static bool tegra_bpmp_master_free(struct tegra_bpmp_channel *channel)
+{
+	void *frame;
+
+	frame = tegra_ivc_write_get_next_frame(channel->ivc);
+	if (IS_ERR(frame)) {
+		channel->ob = NULL;
+		return false;
+	}
+
+	channel->ob = frame;
+
+	return true;
+}
+
+static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
+{
+	unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
+	ktime_t start, now;
+
+	start = ns_to_ktime(local_clock());
+
+	do {
+		if (tegra_bpmp_master_free(channel))
+			return 0;
+
+		now = ns_to_ktime(local_clock());
+	} while (ktime_us_delta(now, start) < timeout);
+
+	return -ETIMEDOUT;
+}
+
+static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
+					 void *data, size_t size)
+{
+	if (data && size > 0)
+		memcpy(data, channel->ib->data, size);
+
+	return tegra_ivc_read_advance(channel->ivc);
+}
+
+static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
+				       void *data, size_t size)
+{
+	struct tegra_bpmp *bpmp = channel->bpmp;
+	unsigned long flags;
+	ssize_t err;
+	int index;
+
+	index = tegra_bpmp_channel_get_thread_index(channel);
+	if (index < 0)
+		return index;
+
+	spin_lock_irqsave(&bpmp->lock, flags);
+	err = __tegra_bpmp_channel_read(channel, data, size);
+	clear_bit(index, bpmp->threaded.allocated);
+	spin_unlock_irqrestore(&bpmp->lock, flags);
+
+	up(&bpmp->threaded.lock);
+
+	return err;
+}
+
+static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
+					  unsigned int mrq, unsigned long flags,
+					  const void *data, size_t size)
+{
+	channel->ob->code = mrq;
+	channel->ob->flags = flags;
+
+	if (data && size > 0)
+		memcpy(channel->ob->data, data, size);
+
+	return tegra_ivc_write_advance(channel->ivc);
+}
+
+static struct tegra_bpmp_channel *
+tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,
+			  const void *data, size_t size)
+{
+	unsigned long timeout = bpmp->soc->channels.thread.timeout;
+	unsigned int count = bpmp->soc->channels.thread.count;
+	struct tegra_bpmp_channel *channel;
+	unsigned long flags;
+	unsigned int index;
+	int err;
+
+	err = down_timeout(&bpmp->threaded.lock, usecs_to_jiffies(timeout));
+	if (err < 0)
+		return ERR_PTR(err);
+
+	spin_lock_irqsave(&bpmp->lock, flags);
+
+	index = find_first_zero_bit(bpmp->threaded.allocated, count);
+	if (index == count) {
+		channel = ERR_PTR(-EBUSY);
+		goto unlock;
+	}
+
+	channel = tegra_bpmp_channel_get_thread(bpmp, index);
+	if (!channel) {
+		channel = ERR_PTR(-EINVAL);
+		goto unlock;
+	}
+
+	if (!tegra_bpmp_master_free(channel)) {
+		channel = ERR_PTR(-EBUSY);
+		goto unlock;
+	}
+
+	set_bit(index, bpmp->threaded.allocated);
+
+	err = __tegra_bpmp_channel_write(channel, mrq, MSG_ACK | MSG_RING,
+					 data, size);
+	if (err < 0) {
+		clear_bit(index, bpmp->threaded.allocated);
+		goto unlock;
+	}
+
+	set_bit(index, bpmp->threaded.busy);
+
+unlock:
+	spin_unlock_irqrestore(&bpmp->lock, flags);
+	return channel;
+}
+
+static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
+					unsigned int mrq, unsigned long flags,
+					const void *data, size_t size)
+{
+	int err;
+
+	err = tegra_bpmp_wait_master_free(channel);
+	if (err < 0)
+		return err;
+
+	return __tegra_bpmp_channel_write(channel, mrq, flags, data, size);
+}
+
+int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
+			       struct tegra_bpmp_message *msg)
+{
+	struct tegra_bpmp_channel *channel;
+	int err;
+
+	if (WARN_ON(!irqs_disabled()))
+		return -EPERM;
+
+	if (!tegra_bpmp_message_valid(msg))
+		return -EINVAL;
+
+	channel = tegra_bpmp_channel_get_tx(bpmp);
+
+	err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
+				       msg->tx.data, msg->tx.size);
+	if (err < 0)
+		return err;
+
+	err = mbox_send_message(bpmp->mbox.channel, NULL);
+	if (err < 0)
+		return err;
+
+	mbox_client_txdone(bpmp->mbox.channel, 0);
+
+	err = tegra_bpmp_wait_ack(channel);
+	if (err < 0)
+		return err;
+
+	return __tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size);
+}
+EXPORT_SYMBOL_GPL(tegra_bpmp_transfer_atomic);
+
+int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
+			struct tegra_bpmp_message *msg)
+{
+	struct tegra_bpmp_channel *channel;
+	unsigned long timeout;
+	int err;
+
+	if (WARN_ON(irqs_disabled()))
+		return -EPERM;
+
+	if (!tegra_bpmp_message_valid(msg))
+		return -EINVAL;
+
+	channel = tegra_bpmp_write_threaded(bpmp, msg->mrq, msg->tx.data,
+					    msg->tx.size);
+	if (IS_ERR(channel))
+		return PTR_ERR(channel);
+
+	err = mbox_send_message(bpmp->mbox.channel, NULL);
+	if (err < 0)
+		return err;
+
+	mbox_client_txdone(bpmp->mbox.channel, 0);
+
+	timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout);
+
+	err = wait_for_completion_timeout(&channel->completion, timeout);
+	if (err == 0)
+		return -ETIMEDOUT;
+
+	return tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size);
+}
+EXPORT_SYMBOL_GPL(tegra_bpmp_transfer);
+
+static struct tegra_bpmp_mrq *tegra_bpmp_find_mrq(struct tegra_bpmp *bpmp,
+						  unsigned int mrq)
+{
+	struct tegra_bpmp_mrq *entry;
+
+	list_for_each_entry(entry, &bpmp->mrqs, list)
+		if (entry->mrq == mrq)
+			return entry;
+
+	return NULL;
+}
+
+static void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel,
+				  int code, const void *data, size_t size)
+{
+	unsigned long flags = channel->ib->flags;
+	struct tegra_bpmp *bpmp = channel->bpmp;
+	struct tegra_bpmp_mb_data *frame;
+	int err;
+
+	if (WARN_ON(size > MSG_DATA_MIN_SZ))
+		return;
+
+	err = tegra_ivc_read_advance(channel->ivc);
+	if (WARN_ON(err < 0))
+		return;
+
+	if ((flags & MSG_ACK) == 0)
+		return;
+
+	frame = tegra_ivc_write_get_next_frame(channel->ivc);
+	if (WARN_ON(IS_ERR(frame)))
+		return;
+
+	frame->code = code;
+
+	if (data && size > 0)
+		memcpy(frame->data, data, size);
+
+	err = tegra_ivc_write_advance(channel->ivc);
+	if (WARN_ON(err < 0))
+		return;
+
+	if (flags & MSG_RING) {
+		err = mbox_send_message(bpmp->mbox.channel, NULL);
+		if (WARN_ON(err < 0))
+			return;
+
+		mbox_client_txdone(bpmp->mbox.channel, 0);
+	}
+}
+
+static void tegra_bpmp_handle_mrq(struct tegra_bpmp *bpmp,
+				  unsigned int mrq,
+				  struct tegra_bpmp_channel *channel)
+{
+	struct tegra_bpmp_mrq *entry;
+	u32 zero = 0;
+
+	spin_lock(&bpmp->lock);
+
+	entry = tegra_bpmp_find_mrq(bpmp, mrq);
+	if (!entry) {
+		spin_unlock(&bpmp->lock);
+		tegra_bpmp_mrq_return(channel, -EINVAL, &zero, sizeof(zero));
+		return;
+	}
+
+	entry->handler(mrq, channel, entry->data);
+
+	spin_unlock(&bpmp->lock);
+}
+
+int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, unsigned int mrq,
+			   tegra_bpmp_mrq_handler_t handler, void *data)
+{
+	struct tegra_bpmp_mrq *entry;
+	unsigned long flags;
+
+	if (!handler)
+		return -EINVAL;
+
+	entry = devm_kzalloc(bpmp->dev, sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&bpmp->lock, flags);
+
+	entry->mrq = mrq;
+	entry->handler = handler;
+	entry->data = data;
+	list_add(&entry->list, &bpmp->mrqs);
+
+	spin_unlock_irqrestore(&bpmp->lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_bpmp_request_mrq);
+
+void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, void *data)
+{
+	struct tegra_bpmp_mrq *entry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bpmp->lock, flags);
+
+	entry = tegra_bpmp_find_mrq(bpmp, mrq);
+	if (!entry)
+		goto unlock;
+
+	list_del(&entry->list);
+	devm_kfree(bpmp->dev, entry);
+
+unlock:
+	spin_unlock_irqrestore(&bpmp->lock, flags);
+}
+EXPORT_SYMBOL_GPL(tegra_bpmp_free_mrq);
+
+static void tegra_bpmp_mrq_handle_ping(unsigned int mrq,
+				       struct tegra_bpmp_channel *channel,
+				       void *data)
+{
+	struct mrq_ping_request *request;
+	struct mrq_ping_response response;
+
+	request = (struct mrq_ping_request *)channel->ib->data;
+
+	memset(&response, 0, sizeof(response));
+	response.reply = request->challenge << 1;
+
+	tegra_bpmp_mrq_return(channel, 0, &response, sizeof(response));
+}
+
+static int tegra_bpmp_ping(struct tegra_bpmp *bpmp)
+{
+	struct mrq_ping_response response;
+	struct mrq_ping_request request;
+	struct tegra_bpmp_message msg;
+	unsigned long flags;
+	ktime_t start, end;
+	int err;
+
+	memset(&request, 0, sizeof(request));
+	request.challenge = 1;
+
+	memset(&response, 0, sizeof(response));
+
+	memset(&msg, 0, sizeof(msg));
+	msg.mrq = MRQ_PING;
+	msg.tx.data = &request;
+	msg.tx.size = sizeof(request);
+	msg.rx.data = &response;
+	msg.rx.size = sizeof(response);
+
+	local_irq_save(flags);
+	start = ktime_get();
+	err = tegra_bpmp_transfer_atomic(bpmp, &msg);
+	end = ktime_get();
+	local_irq_restore(flags);
+
+	if (!err)
+		dev_dbg(bpmp->dev,
+			"ping ok: challenge: %u, response: %u, time: %lld\n",
+			request.challenge, response.reply,
+			ktime_to_us(ktime_sub(end, start)));
+
+	return err;
+}
+
+static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag,
+				       size_t size)
+{
+	struct mrq_query_tag_request request;
+	struct tegra_bpmp_message msg;
+	unsigned long flags;
+	dma_addr_t phys;
+	void *virt;
+	int err;
+
+	virt = dma_alloc_coherent(bpmp->dev, MSG_DATA_MIN_SZ, &phys,
+				  GFP_KERNEL | GFP_DMA32);
+	if (!virt)
+		return -ENOMEM;
+
+	memset(&request, 0, sizeof(request));
+	request.addr = phys;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.mrq = MRQ_QUERY_TAG;
+	msg.tx.data = &request;
+	msg.tx.size = sizeof(request);
+
+	local_irq_save(flags);
+	err = tegra_bpmp_transfer_atomic(bpmp, &msg);
+	local_irq_restore(flags);
+
+	if (err == 0)
+		strlcpy(tag, virt, size);
+
+	dma_free_coherent(bpmp->dev, MSG_DATA_MIN_SZ, virt, phys);
+
+	return err;
+}
+
+static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
+{
+	unsigned long flags = channel->ob->flags;
+
+	if ((flags & MSG_RING) == 0)
+		return;
+
+	complete(&channel->completion);
+}
+
+static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
+{
+	struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
+	struct tegra_bpmp_channel *channel;
+	unsigned int i, count;
+	unsigned long *busy;
+
+	channel = tegra_bpmp_channel_get_rx(bpmp);
+	count = bpmp->soc->channels.thread.count;
+	busy = bpmp->threaded.busy;
+
+	if (tegra_bpmp_master_acked(channel))
+		tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
+
+	spin_lock(&bpmp->lock);
+
+	for_each_set_bit(i, busy, count) {
+		struct tegra_bpmp_channel *channel;
+
+		channel = tegra_bpmp_channel_get_thread(bpmp, i);
+		if (!channel)
+			continue;
+
+		if (tegra_bpmp_master_acked(channel)) {
+			tegra_bpmp_channel_signal(channel);
+			clear_bit(i, busy);
+		}
+	}
+
+	spin_unlock(&bpmp->lock);
+}
+
+static void tegra_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
+{
+	struct tegra_bpmp *bpmp = data;
+	int err;
+
+	if (WARN_ON(bpmp->mbox.channel == NULL))
+		return;
+
+	err = mbox_send_message(bpmp->mbox.channel, NULL);
+	if (err < 0)
+		return;
+
+	mbox_client_txdone(bpmp->mbox.channel, 0);
+}
+
+static int tegra_bpmp_channel_init(struct tegra_bpmp_channel *channel,
+				   struct tegra_bpmp *bpmp,
+				   unsigned int index)
+{
+	size_t message_size, queue_size;
+	unsigned int offset;
+	int err;
+
+	channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
+				    GFP_KERNEL);
+	if (!channel->ivc)
+		return -ENOMEM;
+
+	message_size = tegra_ivc_align(MSG_MIN_SZ);
+	queue_size = tegra_ivc_total_queue_size(message_size);
+	offset = queue_size * index;
+
+	err = tegra_ivc_init(channel->ivc, NULL,
+			     bpmp->rx.virt + offset, bpmp->rx.phys + offset,
+			     bpmp->tx.virt + offset, bpmp->tx.phys + offset,
+			     1, message_size, tegra_bpmp_ivc_notify,
+			     bpmp);
+	if (err < 0) {
+		dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
+			index, err);
+		return err;
+	}
+
+	init_completion(&channel->completion);
+	channel->bpmp = bpmp;
+
+	return 0;
+}
+
+static void tegra_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
+{
+	/* reset the channel state */
+	tegra_ivc_reset(channel->ivc);
+
+	/* sync the channel state with BPMP */
+	while (tegra_ivc_notified(channel->ivc))
+		;
+}
+
+static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
+{
+	tegra_ivc_cleanup(channel->ivc);
+}
+
+static int tegra_bpmp_probe(struct platform_device *pdev)
+{
+	struct tegra_bpmp_channel *channel;
+	struct tegra_bpmp *bpmp;
+	unsigned int i;
+	char tag[32];
+	size_t size;
+	int err;
+
+	bpmp = devm_kzalloc(&pdev->dev, sizeof(*bpmp), GFP_KERNEL);
+	if (!bpmp)
+		return -ENOMEM;
+
+	bpmp->soc = of_device_get_match_data(&pdev->dev);
+	bpmp->dev = &pdev->dev;
+
+	bpmp->tx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 0);
+	if (!bpmp->tx.pool) {
+		dev_err(&pdev->dev, "TX shmem pool not found\n");
+		return -ENOMEM;
+	}
+
+	bpmp->tx.virt = gen_pool_dma_alloc(bpmp->tx.pool, 4096, &bpmp->tx.phys);
+	if (!bpmp->tx.virt) {
+		dev_err(&pdev->dev, "failed to allocate from TX pool\n");
+		return -ENOMEM;
+	}
+
+	bpmp->rx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 1);
+	if (!bpmp->rx.pool) {
+		dev_err(&pdev->dev, "RX shmem pool not found\n");
+		err = -ENOMEM;
+		goto free_tx;
+	}
+
+	bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
+	if (!bpmp->rx.pool) {
+		dev_err(&pdev->dev, "failed to allocate from RX pool\n");
+		err = -ENOMEM;
+		goto free_tx;
+	}
+
+	INIT_LIST_HEAD(&bpmp->mrqs);
+	spin_lock_init(&bpmp->lock);
+
+	bpmp->threaded.count = bpmp->soc->channels.thread.count;
+	sema_init(&bpmp->threaded.lock, bpmp->threaded.count);
+
+	size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long);
+
+	bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	if (!bpmp->threaded.allocated) {
+		err = -ENOMEM;
+		goto free_rx;
+	}
+
+	bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+	if (!bpmp->threaded.busy) {
+		err = -ENOMEM;
+		goto free_rx;
+	}
+
+	bpmp->num_channels = bpmp->soc->channels.cpu_tx.count +
+			     bpmp->soc->channels.thread.count +
+			     bpmp->soc->channels.cpu_rx.count;
+
+	bpmp->channels = devm_kcalloc(&pdev->dev, bpmp->num_channels,
+				      sizeof(*channel), GFP_KERNEL);
+	if (!bpmp->channels) {
+		err = -ENOMEM;
+		goto free_rx;
+	}
+
+	/* message channel initialization */
+	for (i = 0; i < bpmp->num_channels; i++) {
+		struct tegra_bpmp_channel *channel = &bpmp->channels[i];
+
+		err = tegra_bpmp_channel_init(channel, bpmp, i);
+		if (err < 0)
+			goto cleanup_channels;
+	}
+
+	/* mbox registration */
+	bpmp->mbox.client.dev = &pdev->dev;
+	bpmp->mbox.client.rx_callback = tegra_bpmp_handle_rx;
+	bpmp->mbox.client.tx_block = false;
+	bpmp->mbox.client.knows_txdone = false;
+
+	bpmp->mbox.channel = mbox_request_channel(&bpmp->mbox.client, 0);
+	if (IS_ERR(bpmp->mbox.channel)) {
+		err = PTR_ERR(bpmp->mbox.channel);
+		dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
+		goto cleanup_channels;
+	}
+
+	/* reset message channels */
+	for (i = 0; i < bpmp->num_channels; i++) {
+		struct tegra_bpmp_channel *channel = &bpmp->channels[i];
+
+		tegra_bpmp_channel_reset(channel);
+	}
+
+	err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
+				     tegra_bpmp_mrq_handle_ping, bpmp);
+	if (err < 0)
+		goto free_mbox;
+
+	err = tegra_bpmp_ping(bpmp);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to ping BPMP: %d\n", err);
+		goto free_mrq;
+	}
+
+	err = tegra_bpmp_get_firmware_tag(bpmp, tag, sizeof(tag) - 1);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to get firmware tag: %d\n", err);
+		goto free_mrq;
+	}
+
+	dev_info(&pdev->dev, "firmware: %s\n", tag);
+
+	err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev);
+	if (err < 0)
+		goto free_mrq;
+
+	err = tegra_bpmp_init_clocks(bpmp);
+	if (err < 0)
+		goto free_mrq;
+
+	err = tegra_bpmp_init_resets(bpmp);
+	if (err < 0)
+		goto free_mrq;
+
+	platform_set_drvdata(pdev, bpmp);
+
+	return 0;
+
+free_mrq:
+	tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
+free_mbox:
+	mbox_free_channel(bpmp->mbox.channel);
+cleanup_channels:
+	while (i--)
+		tegra_bpmp_channel_cleanup(&bpmp->channels[i]);
+free_rx:
+	gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
+free_tx:
+	gen_pool_free(bpmp->tx.pool, (unsigned long)bpmp->tx.virt, 4096);
+	return err;
+}
+
+static const struct tegra_bpmp_soc tegra186_soc = {
+	.channels = {
+		.cpu_tx = {
+			.offset = 0,
+			.count = 6,
+			.timeout = 60 * USEC_PER_SEC,
+		},
+		.thread = {
+			.offset = 6,
+			.count = 7,
+			.timeout = 600 * USEC_PER_SEC,
+		},
+		.cpu_rx = {
+			.offset = 13,
+			.count = 1,
+			.timeout = 0,
+		},
+	},
+	.num_resets = 193,
+};
+
+static const struct of_device_id tegra_bpmp_match[] = {
+	{ .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
+	{ }
+};
+
+static struct platform_driver tegra_bpmp_driver = {
+	.driver = {
+		.name = "tegra-bpmp",
+		.of_match_table = tegra_bpmp_match,
+	},
+	.probe = tegra_bpmp_probe,
+};
+
+static int __init tegra_bpmp_init(void)
+{
+	return platform_driver_register(&tegra_bpmp_driver);
+}
+core_initcall(tegra_bpmp_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/tegra/ivc.c linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/ivc.c
--- linux-libre-4.9-gnu/drivers/firmware/tegra/ivc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/ivc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <soc/tegra/ivc.h>
+
+#define TEGRA_IVC_ALIGN 64
+
+/*
+ * IVC channel reset protocol.
+ *
+ * Each end uses its tx_channel.state to indicate its synchronization state.
+ */
+enum tegra_ivc_state {
+	/*
+	 * This value is zero for backwards compatibility with services that
+	 * assume channels to be initially zeroed. Such channels are in an
+	 * initially valid state, but cannot be asynchronously reset, and must
+	 * maintain a valid state at all times.
+	 *
+	 * The transmitting end can enter the established state from the sync or
+	 * ack state when it observes the receiving endpoint in the ack or
+	 * established state, indicating that has cleared the counters in our
+	 * rx_channel.
+	 */
+	TEGRA_IVC_STATE_ESTABLISHED = 0,
+
+	/*
+	 * If an endpoint is observed in the sync state, the remote endpoint is
+	 * allowed to clear the counters it owns asynchronously with respect to
+	 * the current endpoint. Therefore, the current endpoint is no longer
+	 * allowed to communicate.
+	 */
+	TEGRA_IVC_STATE_SYNC,
+
+	/*
+	 * When the transmitting end observes the receiving end in the sync
+	 * state, it can clear the w_count and r_count and transition to the ack
+	 * state. If the remote endpoint observes us in the ack state, it can
+	 * return to the established state once it has cleared its counters.
+	 */
+	TEGRA_IVC_STATE_ACK
+};
+
+/*
+ * This structure is divided into two-cache aligned parts, the first is only
+ * written through the tx.channel pointer, while the second is only written
+ * through the rx.channel pointer. This delineates ownership of the cache
+ * lines, which is critical to performance and necessary in non-cache coherent
+ * implementations.
+ */
+struct tegra_ivc_header {
+	union {
+		struct {
+			/* fields owned by the transmitting end */
+			u32 count;
+			u32 state;
+		};
+
+		u8 pad[TEGRA_IVC_ALIGN];
+	} tx;
+
+	union {
+		/* fields owned by the receiving end */
+		u32 count;
+		u8 pad[TEGRA_IVC_ALIGN];
+	} rx;
+};
+
+static inline void tegra_ivc_invalidate(struct tegra_ivc *ivc, dma_addr_t phys)
+{
+	if (!ivc->peer)
+		return;
+
+	dma_sync_single_for_cpu(ivc->peer, phys, TEGRA_IVC_ALIGN,
+				DMA_FROM_DEVICE);
+}
+
+static inline void tegra_ivc_flush(struct tegra_ivc *ivc, dma_addr_t phys)
+{
+	if (!ivc->peer)
+		return;
+
+	dma_sync_single_for_device(ivc->peer, phys, TEGRA_IVC_ALIGN,
+				   DMA_TO_DEVICE);
+}
+
+static inline bool tegra_ivc_empty(struct tegra_ivc *ivc,
+				   struct tegra_ivc_header *header)
+{
+	/*
+	 * This function performs multiple checks on the same values with
+	 * security implications, so create snapshots with ACCESS_ONCE() to
+	 * ensure that these checks use the same values.
+	 */
+	u32 tx = ACCESS_ONCE(header->tx.count);
+	u32 rx = ACCESS_ONCE(header->rx.count);
+
+	/*
+	 * Perform an over-full check to prevent denial of service attacks
+	 * where a server could be easily fooled into believing that there's
+	 * an extremely large number of frames ready, since receivers are not
+	 * expected to check for full or over-full conditions.
+	 *
+	 * Although the channel isn't empty, this is an invalid case caused by
+	 * a potentially malicious peer, so returning empty is safer, because
+	 * it gives the impression that the channel has gone silent.
+	 */
+	if (tx - rx > ivc->num_frames)
+		return true;
+
+	return tx == rx;
+}
+
+static inline bool tegra_ivc_full(struct tegra_ivc *ivc,
+				  struct tegra_ivc_header *header)
+{
+	u32 tx = ACCESS_ONCE(header->tx.count);
+	u32 rx = ACCESS_ONCE(header->rx.count);
+
+	/*
+	 * Invalid cases where the counters indicate that the queue is over
+	 * capacity also appear full.
+	 */
+	return tx - rx >= ivc->num_frames;
+}
+
+static inline u32 tegra_ivc_available(struct tegra_ivc *ivc,
+				      struct tegra_ivc_header *header)
+{
+	u32 tx = ACCESS_ONCE(header->tx.count);
+	u32 rx = ACCESS_ONCE(header->rx.count);
+
+	/*
+	 * This function isn't expected to be used in scenarios where an
+	 * over-full situation can lead to denial of service attacks. See the
+	 * comment in tegra_ivc_empty() for an explanation about special
+	 * over-full considerations.
+	 */
+	return tx - rx;
+}
+
+static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
+{
+	ACCESS_ONCE(ivc->tx.channel->tx.count) =
+		ACCESS_ONCE(ivc->tx.channel->tx.count) + 1;
+
+	if (ivc->tx.position == ivc->num_frames - 1)
+		ivc->tx.position = 0;
+	else
+		ivc->tx.position++;
+}
+
+static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
+{
+	ACCESS_ONCE(ivc->rx.channel->rx.count) =
+		ACCESS_ONCE(ivc->rx.channel->rx.count) + 1;
+
+	if (ivc->rx.position == ivc->num_frames - 1)
+		ivc->rx.position = 0;
+	else
+		ivc->rx.position++;
+}
+
+static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
+{
+	unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
+
+	/*
+	 * tx.channel->state is set locally, so it is not synchronized with
+	 * state from the remote peer. The remote peer cannot reset its
+	 * transmit counters until we've acknowledged its synchronization
+	 * request, so no additional synchronization is required because an
+	 * asynchronous transition of rx.channel->state to
+	 * TEGRA_IVC_STATE_ACK is not allowed.
+	 */
+	if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
+		return -ECONNRESET;
+
+	/*
+	 * Avoid unnecessary invalidations when performing repeated accesses
+	 * to an IVC channel by checking the old queue pointers first.
+	 *
+	 * Synchronization is only necessary when these pointers indicate
+	 * empty or full.
+	 */
+	if (!tegra_ivc_empty(ivc, ivc->rx.channel))
+		return 0;
+
+	tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
+
+	if (tegra_ivc_empty(ivc, ivc->rx.channel))
+		return -ENOSPC;
+
+	return 0;
+}
+
+static inline int tegra_ivc_check_write(struct tegra_ivc *ivc)
+{
+	unsigned int offset = offsetof(struct tegra_ivc_header, rx.count);
+
+	if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
+		return -ECONNRESET;
+
+	if (!tegra_ivc_full(ivc, ivc->tx.channel))
+		return 0;
+
+	tegra_ivc_invalidate(ivc, ivc->tx.phys + offset);
+
+	if (tegra_ivc_full(ivc, ivc->tx.channel))
+		return -ENOSPC;
+
+	return 0;
+}
+
+static void *tegra_ivc_frame_virt(struct tegra_ivc *ivc,
+				  struct tegra_ivc_header *header,
+				  unsigned int frame)
+{
+	if (WARN_ON(frame >= ivc->num_frames))
+		return ERR_PTR(-EINVAL);
+
+	return (void *)(header + 1) + ivc->frame_size * frame;
+}
+
+static inline dma_addr_t tegra_ivc_frame_phys(struct tegra_ivc *ivc,
+					      dma_addr_t phys,
+					      unsigned int frame)
+{
+	unsigned long offset;
+
+	offset = sizeof(struct tegra_ivc_header) + ivc->frame_size * frame;
+
+	return phys + offset;
+}
+
+static inline void tegra_ivc_invalidate_frame(struct tegra_ivc *ivc,
+					      dma_addr_t phys,
+					      unsigned int frame,
+					      unsigned int offset,
+					      size_t size)
+{
+	if (!ivc->peer || WARN_ON(frame >= ivc->num_frames))
+		return;
+
+	phys = tegra_ivc_frame_phys(ivc, phys, frame) + offset;
+
+	dma_sync_single_for_cpu(ivc->peer, phys, size, DMA_FROM_DEVICE);
+}
+
+static inline void tegra_ivc_flush_frame(struct tegra_ivc *ivc,
+					 dma_addr_t phys,
+					 unsigned int frame,
+					 unsigned int offset,
+					 size_t size)
+{
+	if (!ivc->peer || WARN_ON(frame >= ivc->num_frames))
+		return;
+
+	phys = tegra_ivc_frame_phys(ivc, phys, frame) + offset;
+
+	dma_sync_single_for_device(ivc->peer, phys, size, DMA_TO_DEVICE);
+}
+
+/* directly peek at the next frame rx'ed */
+void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc)
+{
+	int err;
+
+	if (WARN_ON(ivc == NULL))
+		return ERR_PTR(-EINVAL);
+
+	err = tegra_ivc_check_read(ivc);
+	if (err < 0)
+		return ERR_PTR(err);
+
+	/*
+	 * Order observation of ivc->rx.position potentially indicating new
+	 * data before data read.
+	 */
+	smp_rmb();
+
+	tegra_ivc_invalidate_frame(ivc, ivc->rx.phys, ivc->rx.position, 0,
+				   ivc->frame_size);
+
+	return tegra_ivc_frame_virt(ivc, ivc->rx.channel, ivc->rx.position);
+}
+EXPORT_SYMBOL(tegra_ivc_read_get_next_frame);
+
+int tegra_ivc_read_advance(struct tegra_ivc *ivc)
+{
+	unsigned int rx = offsetof(struct tegra_ivc_header, rx.count);
+	unsigned int tx = offsetof(struct tegra_ivc_header, tx.count);
+	int err;
+
+	/*
+	 * No read barriers or synchronization here: the caller is expected to
+	 * have already observed the channel non-empty. This check is just to
+	 * catch programming errors.
+	 */
+	err = tegra_ivc_check_read(ivc);
+	if (err < 0)
+		return err;
+
+	tegra_ivc_advance_rx(ivc);
+
+	tegra_ivc_flush(ivc, ivc->rx.phys + rx);
+
+	/*
+	 * Ensure our write to ivc->rx.position occurs before our read from
+	 * ivc->tx.position.
+	 */
+	smp_mb();
+
+	/*
+	 * Notify only upon transition from full to non-full. The available
+	 * count can only asynchronously increase, so the worst possible
+	 * side-effect will be a spurious notification.
+	 */
+	tegra_ivc_invalidate(ivc, ivc->rx.phys + tx);
+
+	if (tegra_ivc_available(ivc, ivc->rx.channel) == ivc->num_frames - 1)
+		ivc->notify(ivc, ivc->notify_data);
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_ivc_read_advance);
+
+/* directly poke at the next frame to be tx'ed */
+void *tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc)
+{
+	int err;
+
+	err = tegra_ivc_check_write(ivc);
+	if (err < 0)
+		return ERR_PTR(err);
+
+	return tegra_ivc_frame_virt(ivc, ivc->tx.channel, ivc->tx.position);
+}
+EXPORT_SYMBOL(tegra_ivc_write_get_next_frame);
+
+/* advance the tx buffer */
+int tegra_ivc_write_advance(struct tegra_ivc *ivc)
+{
+	unsigned int tx = offsetof(struct tegra_ivc_header, tx.count);
+	unsigned int rx = offsetof(struct tegra_ivc_header, rx.count);
+	int err;
+
+	err = tegra_ivc_check_write(ivc);
+	if (err < 0)
+		return err;
+
+	tegra_ivc_flush_frame(ivc, ivc->tx.phys, ivc->tx.position, 0,
+			      ivc->frame_size);
+
+	/*
+	 * Order any possible stores to the frame before update of
+	 * ivc->tx.position.
+	 */
+	smp_wmb();
+
+	tegra_ivc_advance_tx(ivc);
+	tegra_ivc_flush(ivc, ivc->tx.phys + tx);
+
+	/*
+	 * Ensure our write to ivc->tx.position occurs before our read from
+	 * ivc->rx.position.
+	 */
+	smp_mb();
+
+	/*
+	 * Notify only upon transition from empty to non-empty. The available
+	 * count can only asynchronously decrease, so the worst possible
+	 * side-effect will be a spurious notification.
+	 */
+	tegra_ivc_invalidate(ivc, ivc->tx.phys + rx);
+
+	if (tegra_ivc_available(ivc, ivc->tx.channel) == 1)
+		ivc->notify(ivc, ivc->notify_data);
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_ivc_write_advance);
+
+void tegra_ivc_reset(struct tegra_ivc *ivc)
+{
+	unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
+
+	ivc->tx.channel->tx.state = TEGRA_IVC_STATE_SYNC;
+	tegra_ivc_flush(ivc, ivc->tx.phys + offset);
+	ivc->notify(ivc, ivc->notify_data);
+}
+EXPORT_SYMBOL(tegra_ivc_reset);
+
+/*
+ * =======================================================
+ *  IVC State Transition Table - see tegra_ivc_notified()
+ * =======================================================
+ *
+ *	local	remote	action
+ *	-----	------	-----------------------------------
+ *	SYNC	EST	<none>
+ *	SYNC	ACK	reset counters; move to EST; notify
+ *	SYNC	SYNC	reset counters; move to ACK; notify
+ *	ACK	EST	move to EST; notify
+ *	ACK	ACK	move to EST; notify
+ *	ACK	SYNC	reset counters; move to ACK; notify
+ *	EST	EST	<none>
+ *	EST	ACK	<none>
+ *	EST	SYNC	reset counters; move to ACK; notify
+ *
+ * ===============================================================
+ */
+
+int tegra_ivc_notified(struct tegra_ivc *ivc)
+{
+	unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
+	enum tegra_ivc_state state;
+
+	/* Copy the receiver's state out of shared memory. */
+	tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
+	state = ACCESS_ONCE(ivc->rx.channel->tx.state);
+
+	if (state == TEGRA_IVC_STATE_SYNC) {
+		offset = offsetof(struct tegra_ivc_header, tx.count);
+
+		/*
+		 * Order observation of TEGRA_IVC_STATE_SYNC before stores
+		 * clearing tx.channel.
+		 */
+		smp_rmb();
+
+		/*
+		 * Reset tx.channel counters. The remote end is in the SYNC
+		 * state and won't make progress until we change our state,
+		 * so the counters are not in use at this time.
+		 */
+		ivc->tx.channel->tx.count = 0;
+		ivc->rx.channel->rx.count = 0;
+
+		ivc->tx.position = 0;
+		ivc->rx.position = 0;
+
+		/*
+		 * Ensure that counters appear cleared before new state can be
+		 * observed.
+		 */
+		smp_wmb();
+
+		/*
+		 * Move to ACK state. We have just cleared our counters, so it
+		 * is now safe for the remote end to start using these values.
+		 */
+		ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ACK;
+		tegra_ivc_flush(ivc, ivc->tx.phys + offset);
+
+		/*
+		 * Notify remote end to observe state transition.
+		 */
+		ivc->notify(ivc, ivc->notify_data);
+
+	} else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_SYNC &&
+		   state == TEGRA_IVC_STATE_ACK) {
+		offset = offsetof(struct tegra_ivc_header, tx.count);
+
+		/*
+		 * Order observation of ivc_state_sync before stores clearing
+		 * tx_channel.
+		 */
+		smp_rmb();
+
+		/*
+		 * Reset tx.channel counters. The remote end is in the ACK
+		 * state and won't make progress until we change our state,
+		 * so the counters are not in use at this time.
+		 */
+		ivc->tx.channel->tx.count = 0;
+		ivc->rx.channel->rx.count = 0;
+
+		ivc->tx.position = 0;
+		ivc->rx.position = 0;
+
+		/*
+		 * Ensure that counters appear cleared before new state can be
+		 * observed.
+		 */
+		smp_wmb();
+
+		/*
+		 * Move to ESTABLISHED state. We know that the remote end has
+		 * already cleared its counters, so it is safe to start
+		 * writing/reading on this channel.
+		 */
+		ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
+		tegra_ivc_flush(ivc, ivc->tx.phys + offset);
+
+		/*
+		 * Notify remote end to observe state transition.
+		 */
+		ivc->notify(ivc, ivc->notify_data);
+
+	} else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_ACK) {
+		offset = offsetof(struct tegra_ivc_header, tx.count);
+
+		/*
+		 * At this point, we have observed the peer to be in either
+		 * the ACK or ESTABLISHED state. Next, order observation of
+		 * peer state before storing to tx.channel.
+		 */
+		smp_rmb();
+
+		/*
+		 * Move to ESTABLISHED state. We know that we have previously
+		 * cleared our counters, and we know that the remote end has
+		 * cleared its counters, so it is safe to start writing/reading
+		 * on this channel.
+		 */
+		ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
+		tegra_ivc_flush(ivc, ivc->tx.phys + offset);
+
+		/*
+		 * Notify remote end to observe state transition.
+		 */
+		ivc->notify(ivc, ivc->notify_data);
+
+	} else {
+		/*
+		 * There is no need to handle any further action. Either the
+		 * channel is already fully established, or we are waiting for
+		 * the remote end to catch up with our current state. Refer
+		 * to the diagram in "IVC State Transition Table" above.
+		 */
+	}
+
+	if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
+		return -EAGAIN;
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_ivc_notified);
+
+size_t tegra_ivc_align(size_t size)
+{
+	return ALIGN(size, TEGRA_IVC_ALIGN);
+}
+EXPORT_SYMBOL(tegra_ivc_align);
+
+unsigned tegra_ivc_total_queue_size(unsigned queue_size)
+{
+	if (!IS_ALIGNED(queue_size, TEGRA_IVC_ALIGN)) {
+		pr_err("%s: queue_size (%u) must be %u-byte aligned\n",
+		       __func__, queue_size, TEGRA_IVC_ALIGN);
+		return 0;
+	}
+
+	return queue_size + sizeof(struct tegra_ivc_header);
+}
+EXPORT_SYMBOL(tegra_ivc_total_queue_size);
+
+static int tegra_ivc_check_params(unsigned long rx, unsigned long tx,
+				  unsigned int num_frames, size_t frame_size)
+{
+	BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct tegra_ivc_header, tx.count),
+				 TEGRA_IVC_ALIGN));
+	BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct tegra_ivc_header, rx.count),
+				 TEGRA_IVC_ALIGN));
+	BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct tegra_ivc_header),
+				 TEGRA_IVC_ALIGN));
+
+	if ((uint64_t)num_frames * (uint64_t)frame_size >= 0x100000000UL) {
+		pr_err("num_frames * frame_size overflows\n");
+		return -EINVAL;
+	}
+
+	if (!IS_ALIGNED(frame_size, TEGRA_IVC_ALIGN)) {
+		pr_err("frame size not adequately aligned: %zu\n", frame_size);
+		return -EINVAL;
+	}
+
+	/*
+	 * The headers must at least be aligned enough for counters
+	 * to be accessed atomically.
+	 */
+	if (!IS_ALIGNED(rx, TEGRA_IVC_ALIGN)) {
+		pr_err("IVC channel start not aligned: %#lx\n", rx);
+		return -EINVAL;
+	}
+
+	if (!IS_ALIGNED(tx, TEGRA_IVC_ALIGN)) {
+		pr_err("IVC channel start not aligned: %#lx\n", tx);
+		return -EINVAL;
+	}
+
+	if (rx < tx) {
+		if (rx + frame_size * num_frames > tx) {
+			pr_err("queue regions overlap: %#lx + %zx > %#lx\n",
+			       rx, frame_size * num_frames, tx);
+			return -EINVAL;
+		}
+	} else {
+		if (tx + frame_size * num_frames > rx) {
+			pr_err("queue regions overlap: %#lx + %zx > %#lx\n",
+			       tx, frame_size * num_frames, rx);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
+		   dma_addr_t rx_phys, void *tx, dma_addr_t tx_phys,
+		   unsigned int num_frames, size_t frame_size,
+		   void (*notify)(struct tegra_ivc *ivc, void *data),
+		   void *data)
+{
+	size_t queue_size;
+	int err;
+
+	if (WARN_ON(!ivc || !notify))
+		return -EINVAL;
+
+	/*
+	 * All sizes that can be returned by communication functions should
+	 * fit in an int.
+	 */
+	if (frame_size > INT_MAX)
+		return -E2BIG;
+
+	err = tegra_ivc_check_params((unsigned long)rx, (unsigned long)tx,
+				     num_frames, frame_size);
+	if (err < 0)
+		return err;
+
+	queue_size = tegra_ivc_total_queue_size(num_frames * frame_size);
+
+	if (peer) {
+		ivc->rx.phys = dma_map_single(peer, rx, queue_size,
+					      DMA_BIDIRECTIONAL);
+		if (ivc->rx.phys == DMA_ERROR_CODE)
+			return -ENOMEM;
+
+		ivc->tx.phys = dma_map_single(peer, tx, queue_size,
+					      DMA_BIDIRECTIONAL);
+		if (ivc->tx.phys == DMA_ERROR_CODE) {
+			dma_unmap_single(peer, ivc->rx.phys, queue_size,
+					 DMA_BIDIRECTIONAL);
+			return -ENOMEM;
+		}
+	} else {
+		ivc->rx.phys = rx_phys;
+		ivc->tx.phys = tx_phys;
+	}
+
+	ivc->rx.channel = rx;
+	ivc->tx.channel = tx;
+	ivc->peer = peer;
+	ivc->notify = notify;
+	ivc->notify_data = data;
+	ivc->frame_size = frame_size;
+	ivc->num_frames = num_frames;
+
+	/*
+	 * These values aren't necessarily correct until the channel has been
+	 * reset.
+	 */
+	ivc->tx.position = 0;
+	ivc->rx.position = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(tegra_ivc_init);
+
+void tegra_ivc_cleanup(struct tegra_ivc *ivc)
+{
+	if (ivc->peer) {
+		size_t size = tegra_ivc_total_queue_size(ivc->num_frames *
+							 ivc->frame_size);
+
+		dma_unmap_single(ivc->peer, ivc->rx.phys, size,
+				 DMA_BIDIRECTIONAL);
+		dma_unmap_single(ivc->peer, ivc->tx.phys, size,
+				 DMA_BIDIRECTIONAL);
+	}
+}
+EXPORT_SYMBOL(tegra_ivc_cleanup);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/tegra/Kconfig linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/Kconfig
--- linux-libre-4.9-gnu/drivers/firmware/tegra/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,25 @@
+menu "Tegra firmware driver"
+
+config TEGRA_IVC
+	bool "Tegra IVC protocol"
+	depends on ARCH_TEGRA
+	help
+	  IVC (Inter-VM Communication) protocol is part of the IPC
+	  (Inter Processor Communication) framework on Tegra. It maintains the
+	  data and the different commuication channels in SysRAM or RAM and
+	  keeps the content is synchronization between host CPU and remote
+	  processors.
+
+config TEGRA_BPMP
+	bool "Tegra BPMP driver"
+	depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC
+	help
+	  BPMP (Boot and Power Management Processor) is designed to off-loading
+	  the PM functions which include clock/DVFS/thermal/power from the CPU.
+	  It needs HSP as the HW synchronization and notification module and
+	  IVC module as the message communication protocol.
+
+	  This driver manages the IPC interface between host CPU and the
+	  firmware running on BPMP.
+
+endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/tegra/Makefile linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/Makefile
--- linux-libre-4.9-gnu/drivers/firmware/tegra/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/tegra/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2 @@
+obj-$(CONFIG_TEGRA_BPMP)	+= bpmp.o
+obj-$(CONFIG_TEGRA_IVC)		+= ivc.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/ti_sci.c linux-libre-4.10-rc8-gnu/drivers/firmware/ti_sci.c
--- linux-libre-4.9-gnu/drivers/firmware/ti_sci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/ti_sci.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1991 @@
+/*
+ * Texas Instruments System Control Interface Protocol Driver
+ *
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *	Nishanth Menon
+ *
+ * This program is free software; you can 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/bitmap.h>
+#include <linux/debugfs.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/semaphore.h>
+#include <linux/slab.h>
+#include <linux/soc/ti/ti-msgmgr.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include <linux/reboot.h>
+
+#include "ti_sci.h"
+
+/* List of all TI SCI devices active in system */
+static LIST_HEAD(ti_sci_list);
+/* Protection for the entire list */
+static DEFINE_MUTEX(ti_sci_list_mutex);
+
+/**
+ * struct ti_sci_xfer - Structure representing a message flow
+ * @tx_message:	Transmit message
+ * @rx_len:	Receive message length
+ * @xfer_buf:	Preallocated buffer to store receive message
+ *		Since we work with request-ACK protocol, we can
+ *		reuse the same buffer for the rx path as we
+ *		use for the tx path.
+ * @done:	completion event
+ */
+struct ti_sci_xfer {
+	struct ti_msgmgr_message tx_message;
+	u8 rx_len;
+	u8 *xfer_buf;
+	struct completion done;
+};
+
+/**
+ * struct ti_sci_xfers_info - Structure to manage transfer information
+ * @sem_xfer_count:	Counting Semaphore for managing max simultaneous
+ *			Messages.
+ * @xfer_block:		Preallocated Message array
+ * @xfer_alloc_table:	Bitmap table for allocated messages.
+ *			Index of this bitmap table is also used for message
+ *			sequence identifier.
+ * @xfer_lock:		Protection for message allocation
+ */
+struct ti_sci_xfers_info {
+	struct semaphore sem_xfer_count;
+	struct ti_sci_xfer *xfer_block;
+	unsigned long *xfer_alloc_table;
+	/* protect transfer allocation */
+	spinlock_t xfer_lock;
+};
+
+/**
+ * struct ti_sci_desc - Description of SoC integration
+ * @host_id:		Host identifier representing the compute entity
+ * @max_rx_timeout_ms:	Timeout for communication with SoC (in Milliseconds)
+ * @max_msgs: Maximum number of messages that can be pending
+ *		  simultaneously in the system
+ * @max_msg_size: Maximum size of data per message that can be handled.
+ */
+struct ti_sci_desc {
+	u8 host_id;
+	int max_rx_timeout_ms;
+	int max_msgs;
+	int max_msg_size;
+};
+
+/**
+ * struct ti_sci_info - Structure representing a TI SCI instance
+ * @dev:	Device pointer
+ * @desc:	SoC description for this instance
+ * @nb:	Reboot Notifier block
+ * @d:		Debugfs file entry
+ * @debug_region: Memory region where the debug message are available
+ * @debug_region_size: Debug region size
+ * @debug_buffer: Buffer allocated to copy debug messages.
+ * @handle:	Instance of TI SCI handle to send to clients.
+ * @cl:		Mailbox Client
+ * @chan_tx:	Transmit mailbox channel
+ * @chan_rx:	Receive mailbox channel
+ * @minfo:	Message info
+ * @node:	list head
+ * @users:	Number of users of this instance
+ */
+struct ti_sci_info {
+	struct device *dev;
+	struct notifier_block nb;
+	const struct ti_sci_desc *desc;
+	struct dentry *d;
+	void __iomem *debug_region;
+	char *debug_buffer;
+	size_t debug_region_size;
+	struct ti_sci_handle handle;
+	struct mbox_client cl;
+	struct mbox_chan *chan_tx;
+	struct mbox_chan *chan_rx;
+	struct ti_sci_xfers_info minfo;
+	struct list_head node;
+	/* protected by ti_sci_list_mutex */
+	int users;
+
+};
+
+#define cl_to_ti_sci_info(c)	container_of(c, struct ti_sci_info, cl)
+#define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
+#define reboot_to_ti_sci_info(n) container_of(n, struct ti_sci_info, nb)
+
+#ifdef CONFIG_DEBUG_FS
+
+/**
+ * ti_sci_debug_show() - Helper to dump the debug log
+ * @s:	sequence file pointer
+ * @unused:	unused.
+ *
+ * Return: 0
+ */
+static int ti_sci_debug_show(struct seq_file *s, void *unused)
+{
+	struct ti_sci_info *info = s->private;
+
+	memcpy_fromio(info->debug_buffer, info->debug_region,
+		      info->debug_region_size);
+	/*
+	 * We don't trust firmware to leave NULL terminated last byte (hence
+	 * we have allocated 1 extra 0 byte). Since we cannot guarantee any
+	 * specific data format for debug messages, We just present the data
+	 * in the buffer as is - we expect the messages to be self explanatory.
+	 */
+	seq_puts(s, info->debug_buffer);
+	return 0;
+}
+
+/**
+ * ti_sci_debug_open() - debug file open
+ * @inode:	inode pointer
+ * @file:	file pointer
+ *
+ * Return: result of single_open
+ */
+static int ti_sci_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ti_sci_debug_show, inode->i_private);
+}
+
+/* log file operations */
+static const struct file_operations ti_sci_debug_fops = {
+	.open = ti_sci_debug_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+/**
+ * ti_sci_debugfs_create() - Create log debug file
+ * @pdev:	platform device pointer
+ * @info:	Pointer to SCI entity information
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+static int ti_sci_debugfs_create(struct platform_device *pdev,
+				 struct ti_sci_info *info)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	char debug_name[50] = "ti_sci_debug@";
+
+	/* Debug region is optional */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "debug_messages");
+	info->debug_region = devm_ioremap_resource(dev, res);
+	if (IS_ERR(info->debug_region))
+		return 0;
+	info->debug_region_size = resource_size(res);
+
+	info->debug_buffer = devm_kcalloc(dev, info->debug_region_size + 1,
+					  sizeof(char), GFP_KERNEL);
+	if (!info->debug_buffer)
+		return -ENOMEM;
+	/* Setup NULL termination */
+	info->debug_buffer[info->debug_region_size] = 0;
+
+	info->d = debugfs_create_file(strncat(debug_name, dev_name(dev),
+					      sizeof(debug_name)),
+				      0444, NULL, info, &ti_sci_debug_fops);
+	if (IS_ERR(info->d))
+		return PTR_ERR(info->d);
+
+	dev_dbg(dev, "Debug region => %p, size = %zu bytes, resource: %pr\n",
+		info->debug_region, info->debug_region_size, res);
+	return 0;
+}
+
+/**
+ * ti_sci_debugfs_destroy() - clean up log debug file
+ * @pdev:	platform device pointer
+ * @info:	Pointer to SCI entity information
+ */
+static void ti_sci_debugfs_destroy(struct platform_device *pdev,
+				   struct ti_sci_info *info)
+{
+	if (IS_ERR(info->debug_region))
+		return;
+
+	debugfs_remove(info->d);
+}
+#else /* CONFIG_DEBUG_FS */
+static inline int ti_sci_debugfs_create(struct platform_device *dev,
+					struct ti_sci_info *info)
+{
+	return 0;
+}
+
+static inline void ti_sci_debugfs_destroy(struct platform_device *dev,
+					  struct ti_sci_info *info)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+
+/**
+ * ti_sci_dump_header_dbg() - Helper to dump a message header.
+ * @dev:	Device pointer corresponding to the SCI entity
+ * @hdr:	pointer to header.
+ */
+static inline void ti_sci_dump_header_dbg(struct device *dev,
+					  struct ti_sci_msg_hdr *hdr)
+{
+	dev_dbg(dev, "MSGHDR:type=0x%04x host=0x%02x seq=0x%02x flags=0x%08x\n",
+		hdr->type, hdr->host, hdr->seq, hdr->flags);
+}
+
+/**
+ * ti_sci_rx_callback() - mailbox client callback for receive messages
+ * @cl:	client pointer
+ * @m:	mailbox message
+ *
+ * Processes one received message to appropriate transfer information and
+ * signals completion of the transfer.
+ *
+ * NOTE: This function will be invoked in IRQ context, hence should be
+ * as optimal as possible.
+ */
+static void ti_sci_rx_callback(struct mbox_client *cl, void *m)
+{
+	struct ti_sci_info *info = cl_to_ti_sci_info(cl);
+	struct device *dev = info->dev;
+	struct ti_sci_xfers_info *minfo = &info->minfo;
+	struct ti_msgmgr_message *mbox_msg = m;
+	struct ti_sci_msg_hdr *hdr = (struct ti_sci_msg_hdr *)mbox_msg->buf;
+	struct ti_sci_xfer *xfer;
+	u8 xfer_id;
+
+	xfer_id = hdr->seq;
+
+	/*
+	 * Are we even expecting this?
+	 * NOTE: barriers were implicit in locks used for modifying the bitmap
+	 */
+	if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
+		dev_err(dev, "Message for %d is not expected!\n", xfer_id);
+		return;
+	}
+
+	xfer = &minfo->xfer_block[xfer_id];
+
+	/* Is the message of valid length? */
+	if (mbox_msg->len > info->desc->max_msg_size) {
+		dev_err(dev, "Unable to handle %d xfer(max %d)\n",
+			mbox_msg->len, info->desc->max_msg_size);
+		ti_sci_dump_header_dbg(dev, hdr);
+		return;
+	}
+	if (mbox_msg->len < xfer->rx_len) {
+		dev_err(dev, "Recv xfer %d < expected %d length\n",
+			mbox_msg->len, xfer->rx_len);
+		ti_sci_dump_header_dbg(dev, hdr);
+		return;
+	}
+
+	ti_sci_dump_header_dbg(dev, hdr);
+	/* Take a copy to the rx buffer.. */
+	memcpy(xfer->xfer_buf, mbox_msg->buf, xfer->rx_len);
+	complete(&xfer->done);
+}
+
+/**
+ * ti_sci_get_one_xfer() - Allocate one message
+ * @info:	Pointer to SCI entity information
+ * @msg_type:	Message type
+ * @msg_flags:	Flag to set for the message
+ * @tx_message_size: transmit message size
+ * @rx_message_size: receive message size
+ *
+ * Helper function which is used by various command functions that are
+ * exposed to clients of this driver for allocating a message traffic event.
+ *
+ * This function can sleep depending on pending requests already in the system
+ * for the SCI entity. Further, this also holds a spinlock to maintain integrity
+ * of internal data structures.
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+static struct ti_sci_xfer *ti_sci_get_one_xfer(struct ti_sci_info *info,
+					       u16 msg_type, u32 msg_flags,
+					       size_t tx_message_size,
+					       size_t rx_message_size)
+{
+	struct ti_sci_xfers_info *minfo = &info->minfo;
+	struct ti_sci_xfer *xfer;
+	struct ti_sci_msg_hdr *hdr;
+	unsigned long flags;
+	unsigned long bit_pos;
+	u8 xfer_id;
+	int ret;
+	int timeout;
+
+	/* Ensure we have sane transfer sizes */
+	if (rx_message_size > info->desc->max_msg_size ||
+	    tx_message_size > info->desc->max_msg_size ||
+	    rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
+		return ERR_PTR(-ERANGE);
+
+	/*
+	 * Ensure we have only controlled number of pending messages.
+	 * Ideally, we might just have to wait a single message, be
+	 * conservative and wait 5 times that..
+	 */
+	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms) * 5;
+	ret = down_timeout(&minfo->sem_xfer_count, timeout);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	/* Keep the locked section as small as possible */
+	spin_lock_irqsave(&minfo->xfer_lock, flags);
+	bit_pos = find_first_zero_bit(minfo->xfer_alloc_table,
+				      info->desc->max_msgs);
+	set_bit(bit_pos, minfo->xfer_alloc_table);
+	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+	/*
+	 * We already ensured in probe that we can have max messages that can
+	 * fit in  hdr.seq - NOTE: this improves access latencies
+	 * to predictable O(1) access, BUT, it opens us to risk if
+	 * remote misbehaves with corrupted message sequence responses.
+	 * If that happens, we are going to be messed up anyways..
+	 */
+	xfer_id = (u8)bit_pos;
+
+	xfer = &minfo->xfer_block[xfer_id];
+
+	hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
+	xfer->tx_message.len = tx_message_size;
+	xfer->rx_len = (u8)rx_message_size;
+
+	reinit_completion(&xfer->done);
+
+	hdr->seq = xfer_id;
+	hdr->type = msg_type;
+	hdr->host = info->desc->host_id;
+	hdr->flags = msg_flags;
+
+	return xfer;
+}
+
+/**
+ * ti_sci_put_one_xfer() - Release a message
+ * @minfo:	transfer info pointer
+ * @xfer:	message that was reserved by ti_sci_get_one_xfer
+ *
+ * This holds a spinlock to maintain integrity of internal data structures.
+ */
+static void ti_sci_put_one_xfer(struct ti_sci_xfers_info *minfo,
+				struct ti_sci_xfer *xfer)
+{
+	unsigned long flags;
+	struct ti_sci_msg_hdr *hdr;
+	u8 xfer_id;
+
+	hdr = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
+	xfer_id = hdr->seq;
+
+	/*
+	 * Keep the locked section as small as possible
+	 * NOTE: we might escape with smp_mb and no lock here..
+	 * but just be conservative and symmetric.
+	 */
+	spin_lock_irqsave(&minfo->xfer_lock, flags);
+	clear_bit(xfer_id, minfo->xfer_alloc_table);
+	spin_unlock_irqrestore(&minfo->xfer_lock, flags);
+
+	/* Increment the count for the next user to get through */
+	up(&minfo->sem_xfer_count);
+}
+
+/**
+ * ti_sci_do_xfer() - Do one transfer
+ * @info:	Pointer to SCI entity information
+ * @xfer:	Transfer to initiate and wait for response
+ *
+ * Return: -ETIMEDOUT in case of no response, if transmit error,
+ *	   return corresponding error, else if all goes well,
+ *	   return 0.
+ */
+static inline int ti_sci_do_xfer(struct ti_sci_info *info,
+				 struct ti_sci_xfer *xfer)
+{
+	int ret;
+	int timeout;
+	struct device *dev = info->dev;
+
+	ret = mbox_send_message(info->chan_tx, &xfer->tx_message);
+	if (ret < 0)
+		return ret;
+
+	ret = 0;
+
+	/* And we wait for the response. */
+	timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
+	if (!wait_for_completion_timeout(&xfer->done, timeout)) {
+		dev_err(dev, "Mbox timedout in resp(caller: %pF)\n",
+			(void *)_RET_IP_);
+		ret = -ETIMEDOUT;
+	}
+	/*
+	 * NOTE: we might prefer not to need the mailbox ticker to manage the
+	 * transfer queueing since the protocol layer queues things by itself.
+	 * Unfortunately, we have to kick the mailbox framework after we have
+	 * received our message.
+	 */
+	mbox_client_txdone(info->chan_tx, ret);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
+ * @info:	Pointer to SCI entity information
+ *
+ * Updates the SCI information in the internal data structure.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_get_revision(struct ti_sci_info *info)
+{
+	struct device *dev = info->dev;
+	struct ti_sci_handle *handle = &info->handle;
+	struct ti_sci_version_info *ver = &handle->version;
+	struct ti_sci_msg_resp_version *rev_info;
+	struct ti_sci_xfer *xfer;
+	int ret;
+
+	/* No need to setup flags since it is expected to respond */
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_VERSION,
+				   0x0, sizeof(struct ti_sci_msg_hdr),
+				   sizeof(*rev_info));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+
+	rev_info = (struct ti_sci_msg_resp_version *)xfer->xfer_buf;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	ver->abi_major = rev_info->abi_major;
+	ver->abi_minor = rev_info->abi_minor;
+	ver->firmware_revision = rev_info->firmware_revision;
+	strncpy(ver->firmware_description, rev_info->firmware_description,
+		sizeof(ver->firmware_description));
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+	return ret;
+}
+
+/**
+ * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
+ * @r:	pointer to response buffer
+ *
+ * Return: true if the response was an ACK, else returns false.
+ */
+static inline bool ti_sci_is_response_ack(void *r)
+{
+	struct ti_sci_msg_hdr *hdr = r;
+
+	return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
+}
+
+/**
+ * ti_sci_set_device_state() - Set device state helper
+ * @handle:	pointer to TI SCI handle
+ * @id:		Device identifier
+ * @flags:	flags to setup for the device
+ * @state:	State to move the device to
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
+				   u32 id, u32 flags, u8 state)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_set_device_state *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
+				   flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_set_device_state *)xfer->xfer_buf;
+	req->id = id;
+	req->state = state;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_get_device_state() - Get device state helper
+ * @handle:	Handle to the device
+ * @id:		Device Identifier
+ * @clcnt:	Pointer to Context Loss Count
+ * @resets:	pointer to resets
+ * @p_state:	pointer to p_state
+ * @c_state:	pointer to c_state
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
+				   u32 id,  u32 *clcnt,  u32 *resets,
+				    u8 *p_state,  u8 *c_state)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_get_device_state *req;
+	struct ti_sci_msg_resp_get_device_state *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	if (!clcnt && !resets && !p_state && !c_state)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	/* Response is expected, so need of any flags */
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE,
+				   0, sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_get_device_state *)xfer->xfer_buf;
+	req->id = id;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_get_device_state *)xfer->xfer_buf;
+	if (!ti_sci_is_response_ack(resp)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	if (clcnt)
+		*clcnt = resp->context_loss_count;
+	if (resets)
+		*resets = resp->resets;
+	if (p_state)
+		*p_state = resp->programmed_state;
+	if (c_state)
+		*c_state = resp->current_state;
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_get_device() - command to request for device managed by TISCI
+ * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * @id:		Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * NOTE: The request is for exclusive access for the processor.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
+{
+	return ti_sci_set_device_state(handle, id,
+				       MSG_FLAG_DEVICE_EXCLUSIVE,
+				       MSG_DEVICE_SW_STATE_ON);
+}
+
+/**
+ * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
+ * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * @id:		Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
+{
+	return ti_sci_set_device_state(handle, id,
+				       MSG_FLAG_DEVICE_EXCLUSIVE,
+				       MSG_DEVICE_SW_STATE_RETENTION);
+}
+
+/**
+ * ti_sci_cmd_put_device() - command to release a device managed by TISCI
+ * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * @id:		Device Identifier
+ *
+ * Request for the device - NOTE: the client MUST maintain integrity of
+ * usage count by balancing get_device with put_device. No refcounting is
+ * managed by driver for that purpose.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
+{
+	return ti_sci_set_device_state(handle, id,
+				       0, MSG_DEVICE_SW_STATE_AUTO_OFF);
+}
+
+/**
+ * ti_sci_cmd_dev_is_valid() - Is the device valid
+ * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * @id:		Device Identifier
+ *
+ * Return: 0 if all went fine and the device ID is valid, else return
+ * appropriate error.
+ */
+static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
+{
+	u8 unused;
+
+	/* check the device state which will also tell us if the ID is valid */
+	return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
+}
+
+/**
+ * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
+ * @handle:	Pointer to TISCI handle
+ * @id:		Device Identifier
+ * @count:	Pointer to Context Loss counter to populate
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
+				    u32 *count)
+{
+	return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
+}
+
+/**
+ * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
+ * @handle:	Pointer to TISCI handle
+ * @id:		Device Identifier
+ * @r_state:	true if requested to be idle
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
+				  bool *r_state)
+{
+	int ret;
+	u8 state;
+
+	if (!r_state)
+		return -EINVAL;
+
+	ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
+	if (ret)
+		return ret;
+
+	*r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
+
+	return 0;
+}
+
+/**
+ * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
+ * @handle:	Pointer to TISCI handle
+ * @id:		Device Identifier
+ * @r_state:	true if requested to be stopped
+ * @curr_state:	true if currently stopped.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
+				  bool *r_state,  bool *curr_state)
+{
+	int ret;
+	u8 p_state, c_state;
+
+	if (!r_state && !curr_state)
+		return -EINVAL;
+
+	ret =
+	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
+	if (ret)
+		return ret;
+
+	if (r_state)
+		*r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
+	if (curr_state)
+		*curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
+
+	return 0;
+}
+
+/**
+ * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON
+ * @handle:	Pointer to TISCI handle
+ * @id:		Device Identifier
+ * @r_state:	true if requested to be ON
+ * @curr_state:	true if currently ON and active
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
+				bool *r_state,  bool *curr_state)
+{
+	int ret;
+	u8 p_state, c_state;
+
+	if (!r_state && !curr_state)
+		return -EINVAL;
+
+	ret =
+	    ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
+	if (ret)
+		return ret;
+
+	if (r_state)
+		*r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
+	if (curr_state)
+		*curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
+
+	return 0;
+}
+
+/**
+ * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning
+ * @handle:	Pointer to TISCI handle
+ * @id:		Device Identifier
+ * @curr_state:	true if currently transitioning.
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
+				   bool *curr_state)
+{
+	int ret;
+	u8 state;
+
+	if (!curr_state)
+		return -EINVAL;
+
+	ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
+	if (ret)
+		return ret;
+
+	*curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
+
+	return 0;
+}
+
+/**
+ * ti_sci_cmd_set_device_resets() - command to set resets for device managed
+ *				    by TISCI
+ * @handle:	Pointer to TISCI handle as retrieved by *ti_sci_get_handle
+ * @id:		Device Identifier
+ * @reset_state: Device specific reset bit field
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
+					u32 id, u32 reset_state)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_set_device_resets *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_set_device_resets *)xfer->xfer_buf;
+	req->id = id;
+	req->resets = reset_state;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_get_device_resets() - Get reset state for device managed
+ *				    by TISCI
+ * @handle:		Pointer to TISCI handle
+ * @id:			Device Identifier
+ * @reset_state:	Pointer to reset state to populate
+ *
+ * Return: 0 if all went fine, else return appropriate error.
+ */
+static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
+					u32 id, u32 *reset_state)
+{
+	return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
+				       NULL);
+}
+
+/**
+ * ti_sci_set_clock_state() - Set clock state helper
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @flags:	Header flags as needed
+ * @state:	State to request for the clock.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
+				  u32 dev_id, u8 clk_id,
+				  u32 flags, u8 state)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_set_clock_state *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
+				   flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_set_clock_state *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+	req->request_state = state;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_get_clock_state() - Get clock state helper
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @programmed_state:	State requested for clock to move to
+ * @current_state:	State that the clock is currently in
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
+				      u32 dev_id, u8 clk_id,
+				      u8 *programmed_state, u8 *current_state)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_get_clock_state *req;
+	struct ti_sci_msg_resp_get_clock_state *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	if (!programmed_state && !current_state)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_get_clock_state *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	if (programmed_state)
+		*programmed_state = resp->programmed_state;
+	if (current_state)
+		*current_state = resp->current_state;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
+ * @can_change_freq: 'true' if frequency change is desired, else 'false'
+ * @enable_input_term: 'true' if input termination is desired, else 'false'
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
+				u8 clk_id, bool needs_ssc, bool can_change_freq,
+				bool enable_input_term)
+{
+	u32 flags = 0;
+
+	flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
+	flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
+	flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
+
+	return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
+				      MSG_CLOCK_SW_STATE_REQ);
+}
+
+/**
+ * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ *
+ * NOTE: This clock must have been requested by get_clock previously.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
+				 u32 dev_id, u8 clk_id)
+{
+	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
+				      MSG_CLOCK_SW_STATE_UNREQ);
+}
+
+/**
+ * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ *
+ * NOTE: This clock must have been requested by get_clock previously.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
+				u32 dev_id, u8 clk_id)
+{
+	return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
+				      MSG_CLOCK_SW_STATE_AUTO);
+}
+
+/**
+ * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @req_state: state indicating if the clock is auto managed
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
+				  u32 dev_id, u8 clk_id, bool *req_state)
+{
+	u8 state = 0;
+	int ret;
+
+	if (!req_state)
+		return -EINVAL;
+
+	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
+	if (ret)
+		return ret;
+
+	*req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
+	return 0;
+}
+
+/**
+ * ti_sci_cmd_clk_is_on() - Is the clock ON
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @req_state: state indicating if the clock is managed by us and enabled
+ * @curr_state: state indicating if the clock is ready for operation
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
+				u8 clk_id, bool *req_state, bool *curr_state)
+{
+	u8 c_state = 0, r_state = 0;
+	int ret;
+
+	if (!req_state && !curr_state)
+		return -EINVAL;
+
+	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
+					 &r_state, &c_state);
+	if (ret)
+		return ret;
+
+	if (req_state)
+		*req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
+	if (curr_state)
+		*curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
+	return 0;
+}
+
+/**
+ * ti_sci_cmd_clk_is_off() - Is the clock OFF
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @req_state: state indicating if the clock is managed by us and disabled
+ * @curr_state: state indicating if the clock is NOT ready for operation
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
+				 u8 clk_id, bool *req_state, bool *curr_state)
+{
+	u8 c_state = 0, r_state = 0;
+	int ret;
+
+	if (!req_state && !curr_state)
+		return -EINVAL;
+
+	ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
+					 &r_state, &c_state);
+	if (ret)
+		return ret;
+
+	if (req_state)
+		*req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
+	if (curr_state)
+		*curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
+	return 0;
+}
+
+/**
+ * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @parent_id:	Parent clock identifier to set
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
+				     u32 dev_id, u8 clk_id, u8 parent_id)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_set_clock_parent *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_set_clock_parent *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+	req->parent_id = parent_id;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_parent() - Get current parent clock source
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @parent_id:	Current clock parent
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
+				     u32 dev_id, u8 clk_id, u8 *parent_id)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_get_clock_parent *req;
+	struct ti_sci_msg_resp_get_clock_parent *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle || !parent_id)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_get_clock_parent *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp))
+		ret = -ENODEV;
+	else
+		*parent_id = resp->parent_id;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @num_parents: Returns he number of parents to the current clock.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
+					  u32 dev_id, u8 clk_id,
+					  u8 *num_parents)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_get_clock_num_parents *req;
+	struct ti_sci_msg_resp_get_clock_num_parents *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle || !num_parents)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_get_clock_num_parents *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_get_clock_num_parents *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp))
+		ret = -ENODEV;
+	else
+		*num_parents = resp->num_parents;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ * @target_freq: The target clock frequency in Hz. A frequency will be
+ *		processed as close to this target frequency as possible.
+ * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ * @match_freq:	Frequency match in Hz response.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
+					 u32 dev_id, u8 clk_id, u64 min_freq,
+					 u64 target_freq, u64 max_freq,
+					 u64 *match_freq)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_query_clock_freq *req;
+	struct ti_sci_msg_resp_query_clock_freq *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle || !match_freq)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_query_clock_freq *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+	req->min_freq_hz = min_freq;
+	req->target_freq_hz = target_freq;
+	req->max_freq_hz = max_freq;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp))
+		ret = -ENODEV;
+	else
+		*match_freq = resp->freq_hz;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @min_freq:	The minimum allowable frequency in Hz. This is the minimum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ * @target_freq: The target clock frequency in Hz. A frequency will be
+ *		processed as close to this target frequency as possible.
+ * @max_freq:	The maximum allowable frequency in Hz. This is the maximum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
+				   u32 dev_id, u8 clk_id, u64 min_freq,
+				   u64 target_freq, u64 max_freq)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_set_clock_freq *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_set_clock_freq *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+	req->min_freq_hz = min_freq;
+	req->target_freq_hz = target_freq;
+	req->max_freq_hz = max_freq;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_clk_get_freq() - Get current frequency
+ * @handle:	pointer to TI SCI handle
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @freq:	Currently frequency in Hz
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
+				   u32 dev_id, u8 clk_id, u64 *freq)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_get_clock_freq *req;
+	struct ti_sci_msg_resp_get_clock_freq *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle || !freq)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_get_clock_freq *)xfer->xfer_buf;
+	req->dev_id = dev_id;
+	req->clk_id = clk_id;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp))
+		ret = -ENODEV;
+	else
+		*freq = resp->freq_hz;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_reboot *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SYS_RESET,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_reboot *)xfer->xfer_buf;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp))
+		ret = -ENODEV;
+	else
+		ret = 0;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/*
+ * ti_sci_setup_ops() - Setup the operations structures
+ * @info:	pointer to TISCI pointer
+ */
+static void ti_sci_setup_ops(struct ti_sci_info *info)
+{
+	struct ti_sci_ops *ops = &info->handle.ops;
+	struct ti_sci_core_ops *core_ops = &ops->core_ops;
+	struct ti_sci_dev_ops *dops = &ops->dev_ops;
+	struct ti_sci_clk_ops *cops = &ops->clk_ops;
+
+	core_ops->reboot_device = ti_sci_cmd_core_reboot;
+
+	dops->get_device = ti_sci_cmd_get_device;
+	dops->idle_device = ti_sci_cmd_idle_device;
+	dops->put_device = ti_sci_cmd_put_device;
+
+	dops->is_valid = ti_sci_cmd_dev_is_valid;
+	dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
+	dops->is_idle = ti_sci_cmd_dev_is_idle;
+	dops->is_stop = ti_sci_cmd_dev_is_stop;
+	dops->is_on = ti_sci_cmd_dev_is_on;
+	dops->is_transitioning = ti_sci_cmd_dev_is_trans;
+	dops->set_device_resets = ti_sci_cmd_set_device_resets;
+	dops->get_device_resets = ti_sci_cmd_get_device_resets;
+
+	cops->get_clock = ti_sci_cmd_get_clock;
+	cops->idle_clock = ti_sci_cmd_idle_clock;
+	cops->put_clock = ti_sci_cmd_put_clock;
+	cops->is_auto = ti_sci_cmd_clk_is_auto;
+	cops->is_on = ti_sci_cmd_clk_is_on;
+	cops->is_off = ti_sci_cmd_clk_is_off;
+
+	cops->set_parent = ti_sci_cmd_clk_set_parent;
+	cops->get_parent = ti_sci_cmd_clk_get_parent;
+	cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
+
+	cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
+	cops->set_freq = ti_sci_cmd_clk_set_freq;
+	cops->get_freq = ti_sci_cmd_clk_get_freq;
+}
+
+/**
+ * ti_sci_get_handle() - Get the TI SCI handle for a device
+ * @dev:	Pointer to device for which we want SCI handle
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of TI SCI protocol library.
+ * ti_sci_put_handle must be balanced with successful ti_sci_get_handle
+ * Return: pointer to handle if successful, else:
+ * -EPROBE_DEFER if the instance is not ready
+ * -ENODEV if the required node handler is missing
+ * -EINVAL if invalid conditions are encountered.
+ */
+const struct ti_sci_handle *ti_sci_get_handle(struct device *dev)
+{
+	struct device_node *ti_sci_np;
+	struct list_head *p;
+	struct ti_sci_handle *handle = NULL;
+	struct ti_sci_info *info;
+
+	if (!dev) {
+		pr_err("I need a device pointer\n");
+		return ERR_PTR(-EINVAL);
+	}
+	ti_sci_np = of_get_parent(dev->of_node);
+	if (!ti_sci_np) {
+		dev_err(dev, "No OF information\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	mutex_lock(&ti_sci_list_mutex);
+	list_for_each(p, &ti_sci_list) {
+		info = list_entry(p, struct ti_sci_info, node);
+		if (ti_sci_np == info->dev->of_node) {
+			handle = &info->handle;
+			info->users++;
+			break;
+		}
+	}
+	mutex_unlock(&ti_sci_list_mutex);
+	of_node_put(ti_sci_np);
+
+	if (!handle)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	return handle;
+}
+EXPORT_SYMBOL_GPL(ti_sci_get_handle);
+
+/**
+ * ti_sci_put_handle() - Release the handle acquired by ti_sci_get_handle
+ * @handle:	Handle acquired by ti_sci_get_handle
+ *
+ * NOTE: The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of TI SCI protocol library.
+ * ti_sci_put_handle must be balanced with successful ti_sci_get_handle
+ *
+ * Return: 0 is successfully released
+ * if an error pointer was passed, it returns the error value back,
+ * if null was passed, it returns -EINVAL;
+ */
+int ti_sci_put_handle(const struct ti_sci_handle *handle)
+{
+	struct ti_sci_info *info;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	mutex_lock(&ti_sci_list_mutex);
+	if (!WARN_ON(!info->users))
+		info->users--;
+	mutex_unlock(&ti_sci_list_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ti_sci_put_handle);
+
+static void devm_ti_sci_release(struct device *dev, void *res)
+{
+	const struct ti_sci_handle **ptr = res;
+	const struct ti_sci_handle *handle = *ptr;
+	int ret;
+
+	ret = ti_sci_put_handle(handle);
+	if (ret)
+		dev_err(dev, "failed to put handle %d\n", ret);
+}
+
+/**
+ * devm_ti_sci_get_handle() - Managed get handle
+ * @dev:	device for which we want SCI handle for.
+ *
+ * NOTE: This releases the handle once the device resources are
+ * no longer needed. MUST NOT BE released with ti_sci_put_handle.
+ * The function does not track individual clients of the framework
+ * and is expected to be maintained by caller of TI SCI protocol library.
+ *
+ * Return: 0 if all went fine, else corresponding error.
+ */
+const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev)
+{
+	const struct ti_sci_handle **ptr;
+	const struct ti_sci_handle *handle;
+
+	ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+	handle = ti_sci_get_handle(dev);
+
+	if (!IS_ERR(handle)) {
+		*ptr = handle;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return handle;
+}
+EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle);
+
+static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode,
+				void *cmd)
+{
+	struct ti_sci_info *info = reboot_to_ti_sci_info(nb);
+	const struct ti_sci_handle *handle = &info->handle;
+
+	ti_sci_cmd_core_reboot(handle);
+
+	/* call fail OR pass, we should not be here in the first place */
+	return NOTIFY_BAD;
+}
+
+/* Description for K2G */
+static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
+	.host_id = 2,
+	/* Conservative duration */
+	.max_rx_timeout_ms = 1000,
+	/* Limited by MBOX_TX_QUEUE_LEN. K2G can handle upto 128 messages! */
+	.max_msgs = 20,
+	.max_msg_size = 64,
+};
+
+static const struct of_device_id ti_sci_of_match[] = {
+	{.compatible = "ti,k2g-sci", .data = &ti_sci_pmmc_k2g_desc},
+	{ /* Sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_of_match);
+
+static int ti_sci_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *of_id;
+	const struct ti_sci_desc *desc;
+	struct ti_sci_xfer *xfer;
+	struct ti_sci_info *info = NULL;
+	struct ti_sci_xfers_info *minfo;
+	struct mbox_client *cl;
+	int ret = -EINVAL;
+	int i;
+	int reboot = 0;
+
+	of_id = of_match_device(ti_sci_of_match, dev);
+	if (!of_id) {
+		dev_err(dev, "OF data missing\n");
+		return -EINVAL;
+	}
+	desc = of_id->data;
+
+	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->dev = dev;
+	info->desc = desc;
+	reboot = of_property_read_bool(dev->of_node,
+				       "ti,system-reboot-controller");
+	INIT_LIST_HEAD(&info->node);
+	minfo = &info->minfo;
+
+	/*
+	 * Pre-allocate messages
+	 * NEVER allocate more than what we can indicate in hdr.seq
+	 * if we have data description bug, force a fix..
+	 */
+	if (WARN_ON(desc->max_msgs >=
+		    1 << 8 * sizeof(((struct ti_sci_msg_hdr *)0)->seq)))
+		return -EINVAL;
+
+	minfo->xfer_block = devm_kcalloc(dev,
+					 desc->max_msgs,
+					 sizeof(*minfo->xfer_block),
+					 GFP_KERNEL);
+	if (!minfo->xfer_block)
+		return -ENOMEM;
+
+	minfo->xfer_alloc_table = devm_kzalloc(dev,
+					       BITS_TO_LONGS(desc->max_msgs)
+					       * sizeof(unsigned long),
+					       GFP_KERNEL);
+	if (!minfo->xfer_alloc_table)
+		return -ENOMEM;
+	bitmap_zero(minfo->xfer_alloc_table, desc->max_msgs);
+
+	/* Pre-initialize the buffer pointer to pre-allocated buffers */
+	for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) {
+		xfer->xfer_buf = devm_kcalloc(dev, 1, desc->max_msg_size,
+					      GFP_KERNEL);
+		if (!xfer->xfer_buf)
+			return -ENOMEM;
+
+		xfer->tx_message.buf = xfer->xfer_buf;
+		init_completion(&xfer->done);
+	}
+
+	ret = ti_sci_debugfs_create(pdev, info);
+	if (ret)
+		dev_warn(dev, "Failed to create debug file\n");
+
+	platform_set_drvdata(pdev, info);
+
+	cl = &info->cl;
+	cl->dev = dev;
+	cl->tx_block = false;
+	cl->rx_callback = ti_sci_rx_callback;
+	cl->knows_txdone = true;
+
+	spin_lock_init(&minfo->xfer_lock);
+	sema_init(&minfo->sem_xfer_count, desc->max_msgs);
+
+	info->chan_rx = mbox_request_channel_byname(cl, "rx");
+	if (IS_ERR(info->chan_rx)) {
+		ret = PTR_ERR(info->chan_rx);
+		goto out;
+	}
+
+	info->chan_tx = mbox_request_channel_byname(cl, "tx");
+	if (IS_ERR(info->chan_tx)) {
+		ret = PTR_ERR(info->chan_tx);
+		goto out;
+	}
+	ret = ti_sci_cmd_get_revision(info);
+	if (ret) {
+		dev_err(dev, "Unable to communicate with TISCI(%d)\n", ret);
+		goto out;
+	}
+
+	ti_sci_setup_ops(info);
+
+	if (reboot) {
+		info->nb.notifier_call = tisci_reboot_handler;
+		info->nb.priority = 128;
+
+		ret = register_restart_handler(&info->nb);
+		if (ret) {
+			dev_err(dev, "reboot registration fail(%d)\n", ret);
+			return ret;
+		}
+	}
+
+	dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n",
+		 info->handle.version.abi_major, info->handle.version.abi_minor,
+		 info->handle.version.firmware_revision,
+		 info->handle.version.firmware_description);
+
+	mutex_lock(&ti_sci_list_mutex);
+	list_add_tail(&info->node, &ti_sci_list);
+	mutex_unlock(&ti_sci_list_mutex);
+
+	return of_platform_populate(dev->of_node, NULL, NULL, dev);
+out:
+	if (!IS_ERR(info->chan_tx))
+		mbox_free_channel(info->chan_tx);
+	if (!IS_ERR(info->chan_rx))
+		mbox_free_channel(info->chan_rx);
+	debugfs_remove(info->d);
+	return ret;
+}
+
+static int ti_sci_remove(struct platform_device *pdev)
+{
+	struct ti_sci_info *info;
+	struct device *dev = &pdev->dev;
+	int ret = 0;
+
+	of_platform_depopulate(dev);
+
+	info = platform_get_drvdata(pdev);
+
+	if (info->nb.notifier_call)
+		unregister_restart_handler(&info->nb);
+
+	mutex_lock(&ti_sci_list_mutex);
+	if (info->users)
+		ret = -EBUSY;
+	else
+		list_del(&info->node);
+	mutex_unlock(&ti_sci_list_mutex);
+
+	if (!ret) {
+		ti_sci_debugfs_destroy(pdev, info);
+
+		/* Safe to free channels since no more users */
+		mbox_free_channel(info->chan_tx);
+		mbox_free_channel(info->chan_rx);
+	}
+
+	return ret;
+}
+
+static struct platform_driver ti_sci_driver = {
+	.probe = ti_sci_probe,
+	.remove = ti_sci_remove,
+	.driver = {
+		   .name = "ti-sci",
+		   .of_match_table = of_match_ptr(ti_sci_of_match),
+	},
+};
+module_platform_driver(ti_sci_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface(SCI) driver");
+MODULE_AUTHOR("Nishanth Menon");
+MODULE_ALIAS("platform:ti-sci");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/firmware/ti_sci.h linux-libre-4.10-rc8-gnu/drivers/firmware/ti_sci.h
--- linux-libre-4.9-gnu/drivers/firmware/ti_sci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/firmware/ti_sci.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,492 @@
+/*
+ * Texas Instruments System Control Interface (TISCI) Protocol
+ *
+ * Communication protocol with TI SCI hardware
+ * The system works in a message response protocol
+ * See: http://processors.wiki.ti.com/index.php/TISCI for details
+ *
+ * Copyright (C)  2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * 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 Texas Instruments Incorporated nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TI_SCI_H
+#define __TI_SCI_H
+
+/* Generic Messages */
+#define TI_SCI_MSG_ENABLE_WDT	0x0000
+#define TI_SCI_MSG_WAKE_RESET	0x0001
+#define TI_SCI_MSG_VERSION	0x0002
+#define TI_SCI_MSG_WAKE_REASON	0x0003
+#define TI_SCI_MSG_GOODBYE	0x0004
+#define TI_SCI_MSG_SYS_RESET	0x0005
+
+/* Device requests */
+#define TI_SCI_MSG_SET_DEVICE_STATE	0x0200
+#define TI_SCI_MSG_GET_DEVICE_STATE	0x0201
+#define TI_SCI_MSG_SET_DEVICE_RESETS	0x0202
+
+/* Clock requests */
+#define TI_SCI_MSG_SET_CLOCK_STATE	0x0100
+#define TI_SCI_MSG_GET_CLOCK_STATE	0x0101
+#define TI_SCI_MSG_SET_CLOCK_PARENT	0x0102
+#define TI_SCI_MSG_GET_CLOCK_PARENT	0x0103
+#define TI_SCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104
+#define TI_SCI_MSG_SET_CLOCK_FREQ	0x010c
+#define TI_SCI_MSG_QUERY_CLOCK_FREQ	0x010d
+#define TI_SCI_MSG_GET_CLOCK_FREQ	0x010e
+
+/**
+ * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
+ * @type:	Type of messages: One of TI_SCI_MSG* values
+ * @host:	Host of the message
+ * @seq:	Message identifier indicating a transfer sequence
+ * @flags:	Flag for the message
+ */
+struct ti_sci_msg_hdr {
+	u16 type;
+	u8 host;
+	u8 seq;
+#define TI_SCI_MSG_FLAG(val)			(1 << (val))
+#define TI_SCI_FLAG_REQ_GENERIC_NORESPONSE	0x0
+#define TI_SCI_FLAG_REQ_ACK_ON_RECEIVED		TI_SCI_MSG_FLAG(0)
+#define TI_SCI_FLAG_REQ_ACK_ON_PROCESSED	TI_SCI_MSG_FLAG(1)
+#define TI_SCI_FLAG_RESP_GENERIC_NACK		0x0
+#define TI_SCI_FLAG_RESP_GENERIC_ACK		TI_SCI_MSG_FLAG(1)
+	/* Additional Flags */
+	u32 flags;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_version - Response for a message
+ * @hdr:		Generic header
+ * @firmware_description: String describing the firmware
+ * @firmware_revision:	Firmware revision
+ * @abi_major:		Major version of the ABI that firmware supports
+ * @abi_minor:		Minor version of the ABI that firmware supports
+ *
+ * In general, ABI version changes follow the rule that minor version increments
+ * are backward compatible. Major revision changes in ABI may not be
+ * backward compatible.
+ *
+ * Response to a generic message with message type TI_SCI_MSG_VERSION
+ */
+struct ti_sci_msg_resp_version {
+	struct ti_sci_msg_hdr hdr;
+	char firmware_description[32];
+	u16 firmware_revision;
+	u8 abi_major;
+	u8 abi_minor;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_reboot - Reboot the SoC
+ * @hdr:	Generic Header
+ *
+ * Request type is TI_SCI_MSG_SYS_RESET, responded with a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_reboot {
+	struct ti_sci_msg_hdr hdr;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_device_state - Set the desired state of the device
+ * @hdr:		Generic header
+ * @id:	Indicates which device to modify
+ * @reserved: Reserved space in message, must be 0 for backward compatibility
+ * @state: The desired state of the device.
+ *
+ * Certain flags can also be set to alter the device state:
+ * + MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source.
+ * The meaning of this flag will vary slightly from device to device and from
+ * SoC to SoC but it generally allows the device to wake the SoC out of deep
+ * suspend states.
+ * + MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device.
+ * + MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed
+ * with STATE_RETENTION or STATE_ON, it will claim the device exclusively.
+ * If another host already has this device set to STATE_RETENTION or STATE_ON,
+ * the message will fail. Once successful, other hosts attempting to set
+ * STATE_RETENTION or STATE_ON will fail.
+ *
+ * Request type is TI_SCI_MSG_SET_DEVICE_STATE, responded with a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_set_device_state {
+	/* Additional hdr->flags options */
+#define MSG_FLAG_DEVICE_WAKE_ENABLED	TI_SCI_MSG_FLAG(8)
+#define MSG_FLAG_DEVICE_RESET_ISO	TI_SCI_MSG_FLAG(9)
+#define MSG_FLAG_DEVICE_EXCLUSIVE	TI_SCI_MSG_FLAG(10)
+	struct ti_sci_msg_hdr hdr;
+	u32 id;
+	u32 reserved;
+
+#define MSG_DEVICE_SW_STATE_AUTO_OFF	0
+#define MSG_DEVICE_SW_STATE_RETENTION	1
+#define MSG_DEVICE_SW_STATE_ON		2
+	u8 state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_device_state - Request to get device.
+ * @hdr:		Generic header
+ * @id:		Device Identifier
+ *
+ * Request type is TI_SCI_MSG_GET_DEVICE_STATE, responded device state
+ * information
+ */
+struct ti_sci_msg_req_get_device_state {
+	struct ti_sci_msg_hdr hdr;
+	u32 id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_device_state - Response to get device request.
+ * @hdr:		Generic header
+ * @context_loss_count: Indicates how many times the device has lost context. A
+ *	driver can use this monotonic counter to determine if the device has
+ *	lost context since the last time this message was exchanged.
+ * @resets: Programmed state of the reset lines.
+ * @programmed_state:	The state as programmed by set_device.
+ *			- Uses the MSG_DEVICE_SW_* macros
+ * @current_state:	The actual state of the hardware.
+ *
+ * Response to request TI_SCI_MSG_GET_DEVICE_STATE.
+ */
+struct ti_sci_msg_resp_get_device_state {
+	struct ti_sci_msg_hdr hdr;
+	u32 context_loss_count;
+	u32 resets;
+	u8 programmed_state;
+#define MSG_DEVICE_HW_STATE_OFF		0
+#define MSG_DEVICE_HW_STATE_ON		1
+#define MSG_DEVICE_HW_STATE_TRANS	2
+	u8 current_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_device_resets - Set the desired resets
+ *				configuration of the device
+ * @hdr:		Generic header
+ * @id:	Indicates which device to modify
+ * @resets: A bit field of resets for the device. The meaning, behavior,
+ *	and usage of the reset flags are device specific. 0 for a bit
+ *	indicates releasing the reset represented by that bit while 1
+ *	indicates keeping it held.
+ *
+ * Request type is TI_SCI_MSG_SET_DEVICE_RESETS, responded with a generic
+ * ACK/NACK message.
+ */
+struct ti_sci_msg_req_set_device_resets {
+	struct ti_sci_msg_hdr hdr;
+	u32 id;
+	u32 resets;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_state - Request to setup a Clock state
+ * @hdr:	Generic Header, Certain flags can be set specific to the clocks:
+ *		MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified
+ *		via spread spectrum clocking.
+ *		MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's
+ *		frequency to be changed while it is running so long as it
+ *		is within the min/max limits.
+ *		MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this
+ *		is only applicable to clock inputs on the SoC pseudo-device.
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @request_state: Request the state for the clock to be set to.
+ *		MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock,
+ *		it can be disabled, regardless of the state of the device
+ *		MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to
+ *		automatically manage the state of this clock. If the device
+ *		is enabled, then the clock is enabled. If the device is set
+ *		to off or retention, then the clock is internally set as not
+ *		being required by the device.(default)
+ *		MSG_CLOCK_SW_STATE_REQ:  Configure the clock to be enabled,
+ *		regardless of the state of the device.
+ *
+ * Normally, all required clocks are managed by TISCI entity, this is used
+ * only for specific control *IF* required. Auto managed state is
+ * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote
+ * will explicitly control.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_STATE, response is a generic
+ * ACK or NACK message.
+ */
+struct ti_sci_msg_req_set_clock_state {
+	/* Additional hdr->flags options */
+#define MSG_FLAG_CLOCK_ALLOW_SSC		TI_SCI_MSG_FLAG(8)
+#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE	TI_SCI_MSG_FLAG(9)
+#define MSG_FLAG_CLOCK_INPUT_TERM		TI_SCI_MSG_FLAG(10)
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u8 clk_id;
+#define MSG_CLOCK_SW_STATE_UNREQ	0
+#define MSG_CLOCK_SW_STATE_AUTO		1
+#define MSG_CLOCK_SW_STATE_REQ		2
+	u8 request_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_state - Request for clock state
+ * @hdr:	Generic Header
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to get state of.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_STATE, response is state
+ * of the clock
+ */
+struct ti_sci_msg_req_get_clock_state {
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_state - Response to get clock state
+ * @hdr:	Generic Header
+ * @programmed_state: Any programmed state of the clock. This is one of
+ *		MSG_CLOCK_SW_STATE* values.
+ * @current_state: Current state of the clock. This is one of:
+ *		MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready
+ *		MSG_CLOCK_HW_STATE_READY: Clock is ready
+ *
+ * Response to TI_SCI_MSG_GET_CLOCK_STATE.
+ */
+struct ti_sci_msg_resp_get_clock_state {
+	struct ti_sci_msg_hdr hdr;
+	u8 programmed_state;
+#define MSG_CLOCK_HW_STATE_NOT_READY	0
+#define MSG_CLOCK_HW_STATE_READY	1
+	u8 current_state;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_parent - Set the clock parent
+ * @hdr:	Generic Header
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to modify.
+ * @parent_id:	The new clock parent is selectable by an index via this
+ *		parameter.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_PARENT, response is generic
+ * ACK / NACK message.
+ */
+struct ti_sci_msg_req_set_clock_parent {
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u8 clk_id;
+	u8 parent_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_parent - Get the clock parent
+ * @hdr:	Generic Header
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *		Each device has it's own set of clock inputs. This indexes
+ *		which clock input to get the parent for.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_PARENT, response is parent information
+ */
+struct ti_sci_msg_req_get_clock_parent {
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_parent - Response with clock parent
+ * @hdr:	Generic Header
+ * @parent_id:	The current clock parent
+ *
+ * Response to TI_SCI_MSG_GET_CLOCK_PARENT.
+ */
+struct ti_sci_msg_resp_get_clock_parent {
+	struct ti_sci_msg_hdr hdr;
+	u8 parent_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_num_parents - Request to get clock parents
+ * @hdr:	Generic header
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *
+ * This request provides information about how many clock parent options
+ * are available for a given clock to a device. This is typically used
+ * for input clocks.
+ *
+ * Request type is TI_SCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate
+ * message, or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_get_clock_num_parents {
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_num_parents - Response for get clk parents
+ * @hdr:		Generic header
+ * @num_parents:	Number of clock parents
+ *
+ * Response to TI_SCI_MSG_GET_NUM_CLOCK_PARENTS
+ */
+struct ti_sci_msg_resp_get_clock_num_parents {
+	struct ti_sci_msg_hdr hdr;
+	u8 num_parents;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_query_clock_freq - Request to query a frequency
+ * @hdr:	Generic Header
+ * @dev_id:	Device identifier this request is for
+ * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ * @target_freq_hz: The target clock frequency. A frequency will be found
+ *		as close to this target frequency as possible.
+ * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ * @clk_id:	Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In case of specific requests, TISCI evaluates capability to achieve
+ * requested frequency within provided range and responds with
+ * result message.
+ *
+ * Request type is TI_SCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message,
+ * or NACK in case of inability to satisfy request.
+ */
+struct ti_sci_msg_req_query_clock_freq {
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u64 min_freq_hz;
+	u64 target_freq_hz;
+	u64 max_freq_hz;
+	u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_query_clock_freq - Response to a clock frequency query
+ * @hdr:	Generic Header
+ * @freq_hz:	Frequency that is the best match in Hz.
+ *
+ * Response to request type TI_SCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request
+ * cannot be satisfied, the message will be of type NACK.
+ */
+struct ti_sci_msg_resp_query_clock_freq {
+	struct ti_sci_msg_hdr hdr;
+	u64 freq_hz;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_set_clock_freq - Request to setup a clock frequency
+ * @hdr:	Generic Header
+ * @dev_id:	Device identifier this request is for
+ * @min_freq_hz: The minimum allowable frequency in Hz. This is the minimum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ * @target_freq_hz: The target clock frequency. The clock will be programmed
+ *		at a rate as close to this target frequency as possible.
+ * @max_freq_hz: The maximum allowable frequency in Hz. This is the maximum
+ *		allowable programmed frequency and does not account for clock
+ *		tolerances and jitter.
+ * @clk_id:	Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In case of specific requests, TISCI evaluates capability to achieve
+ * requested range and responds with success/failure message.
+ *
+ * This sets the desired frequency for a clock within an allowable
+ * range. This message will fail on an enabled clock unless
+ * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally,
+ * if other clocks have their frequency modified due to this message,
+ * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled.
+ *
+ * Calling set frequency on a clock input to the SoC pseudo-device will
+ * inform the PMMC of that clock's frequency. Setting a frequency of
+ * zero will indicate the clock is disabled.
+ *
+ * Calling set frequency on clock outputs from the SoC pseudo-device will
+ * function similarly to setting the clock frequency on a device.
+ *
+ * Request type is TI_SCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK
+ * message.
+ */
+struct ti_sci_msg_req_set_clock_freq {
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u64 min_freq_hz;
+	u64 target_freq_hz;
+	u64 max_freq_hz;
+	u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_req_get_clock_freq - Request to get the clock frequency
+ * @hdr:	Generic Header
+ * @dev_id:	Device identifier this request is for
+ * @clk_id:	Clock identifier for the device for this request.
+ *
+ * NOTE: Normally clock frequency management is automatically done by TISCI
+ * entity. In some cases, clock frequencies are configured by host.
+ *
+ * Request type is TI_SCI_MSG_GET_CLOCK_FREQ, responded with clock frequency
+ * that the clock is currently at.
+ */
+struct ti_sci_msg_req_get_clock_freq {
+	struct ti_sci_msg_hdr hdr;
+	u32 dev_id;
+	u8 clk_id;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_get_clock_freq - Response of clock frequency request
+ * @hdr:	Generic Header
+ * @freq_hz:	Frequency that the clock is currently on, in Hz.
+ *
+ * Response to request type TI_SCI_MSG_GET_CLOCK_FREQ.
+ */
+struct ti_sci_msg_resp_get_clock_freq {
+	struct ti_sci_msg_hdr hdr;
+	u64 freq_hz;
+} __packed;
+
+#endif /* __TI_SCI_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/altera-fpga2sdram.c linux-libre-4.10-rc8-gnu/drivers/fpga/altera-fpga2sdram.c
--- linux-libre-4.9-gnu/drivers/fpga/altera-fpga2sdram.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/altera-fpga2sdram.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,180 @@
+/*
+ * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver manages a bridge between an FPGA and the SDRAM used by the ARM
+ * host processor system (HPS).
+ *
+ * The bridge contains 4 read ports, 4 write ports, and 6 command ports.
+ * Reconfiguring these ports requires that no SDRAM transactions occur during
+ * reconfiguration.  The code reconfiguring the ports cannot run out of SDRAM
+ * nor can the FPGA access the SDRAM during reconfiguration.  This driver does
+ * not support reconfiguring the ports.  The ports are configured by code
+ * running out of on chip ram before Linux is started and the configuration
+ * is passed in a handoff register in the system manager.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+#define ALT_SDR_CTL_FPGAPORTRST_OFST		0x80
+#define ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK	0x00003fff
+#define ALT_SDR_CTL_FPGAPORTRST_RD_SHIFT	0
+#define ALT_SDR_CTL_FPGAPORTRST_WR_SHIFT	4
+#define ALT_SDR_CTL_FPGAPORTRST_CTRL_SHIFT	8
+
+/*
+ * From the Cyclone V HPS Memory Map document:
+ *   These registers are used to store handoff information between the
+ *   preloader and the OS. These 8 registers can be used to store any
+ *   information. The contents of these registers have no impact on
+ *   the state of the HPS hardware.
+ */
+#define SYSMGR_ISWGRP_HANDOFF3          (0x8C)
+
+#define F2S_BRIDGE_NAME "fpga2sdram"
+
+struct alt_fpga2sdram_data {
+	struct device *dev;
+	struct regmap *sdrctl;
+	int mask;
+};
+
+static int alt_fpga2sdram_enable_show(struct fpga_bridge *bridge)
+{
+	struct alt_fpga2sdram_data *priv = bridge->priv;
+	int value;
+
+	regmap_read(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST, &value);
+
+	return (value & priv->mask) == priv->mask;
+}
+
+static inline int _alt_fpga2sdram_enable_set(struct alt_fpga2sdram_data *priv,
+					     bool enable)
+{
+	return regmap_update_bits(priv->sdrctl, ALT_SDR_CTL_FPGAPORTRST_OFST,
+				  priv->mask, enable ? priv->mask : 0);
+}
+
+static int alt_fpga2sdram_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_fpga2sdram_enable_set(bridge->priv, enable);
+}
+
+struct prop_map {
+	char *prop_name;
+	u32 *prop_value;
+	u32 prop_max;
+};
+
+static const struct fpga_bridge_ops altera_fpga2sdram_br_ops = {
+	.enable_set = alt_fpga2sdram_enable_set,
+	.enable_show = alt_fpga2sdram_enable_show,
+};
+
+static const struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-fpga2sdram-bridge" },
+	{},
+};
+
+static int alt_fpga_bridge_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct alt_fpga2sdram_data *priv;
+	u32 enable;
+	struct regmap *sysmgr;
+	int ret = 0;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	priv->sdrctl = syscon_regmap_lookup_by_compatible("altr,sdr-ctl");
+	if (IS_ERR(priv->sdrctl)) {
+		dev_err(dev, "regmap for altr,sdr-ctl lookup failed.\n");
+		return PTR_ERR(priv->sdrctl);
+	}
+
+	sysmgr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
+	if (IS_ERR(sysmgr)) {
+		dev_err(dev, "regmap for altr,sys-mgr lookup failed.\n");
+		return PTR_ERR(sysmgr);
+	}
+
+	/* Get f2s bridge configuration saved in handoff register */
+	regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
+
+	ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
+				   &altera_fpga2sdram_br_ops, priv);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
+
+	if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
+		if (enable > 1) {
+			dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
+		} else {
+			dev_info(dev, "%s bridge\n",
+				 (enable ? "enabling" : "disabling"));
+			ret = _alt_fpga2sdram_enable_set(priv, enable);
+			if (ret) {
+				fpga_bridge_unregister(&pdev->dev);
+				return ret;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int alt_fpga_bridge_remove(struct platform_device *pdev)
+{
+	fpga_bridge_unregister(&pdev->dev);
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
+
+static struct platform_driver altera_fpga_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.remove = alt_fpga_bridge_remove,
+	.driver = {
+		.name	= "altera_fpga2sdram_bridge",
+		.of_match_table = of_match_ptr(altera_fpga_of_match),
+	},
+};
+
+module_platform_driver(altera_fpga_driver);
+
+MODULE_DESCRIPTION("Altera SoCFPGA FPGA to SDRAM Bridge");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/altera-freeze-bridge.c linux-libre-4.10-rc8-gnu/drivers/fpga/altera-freeze-bridge.c
--- linux-libre-4.9-gnu/drivers/fpga/altera-freeze-bridge.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/altera-freeze-bridge.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * FPGA Freeze Bridge Controller
+ *
+ *  Copyright (C) 2016 Altera Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/fpga/fpga-bridge.h>
+
+#define FREEZE_CSR_STATUS_OFFSET		0
+#define FREEZE_CSR_CTRL_OFFSET			4
+#define FREEZE_CSR_ILLEGAL_REQ_OFFSET		8
+#define FREEZE_CSR_REG_VERSION			12
+
+#define FREEZE_CSR_SUPPORTED_VERSION		2
+
+#define FREEZE_CSR_STATUS_FREEZE_REQ_DONE	BIT(0)
+#define FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE	BIT(1)
+
+#define FREEZE_CSR_CTRL_FREEZE_REQ		BIT(0)
+#define FREEZE_CSR_CTRL_RESET_REQ		BIT(1)
+#define FREEZE_CSR_CTRL_UNFREEZE_REQ		BIT(2)
+
+#define FREEZE_BRIDGE_NAME			"freeze"
+
+struct altera_freeze_br_data {
+	struct device *dev;
+	void __iomem *base_addr;
+	bool enable;
+};
+
+/*
+ * Poll status until status bit is set or we have a timeout.
+ */
+static int altera_freeze_br_req_ack(struct altera_freeze_br_data *priv,
+				    u32 timeout, u32 req_ack)
+{
+	struct device *dev = priv->dev;
+	void __iomem *csr_illegal_req_addr = priv->base_addr +
+					     FREEZE_CSR_ILLEGAL_REQ_OFFSET;
+	u32 status, illegal, ctrl;
+	int ret = -ETIMEDOUT;
+
+	do {
+		illegal = readl(csr_illegal_req_addr);
+		if (illegal) {
+			dev_err(dev, "illegal request detected 0x%x", illegal);
+
+			writel(1, csr_illegal_req_addr);
+
+			illegal = readl(csr_illegal_req_addr);
+			if (illegal)
+				dev_err(dev, "illegal request not cleared 0x%x",
+					illegal);
+
+			ret = -EINVAL;
+			break;
+		}
+
+		status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
+		dev_dbg(dev, "%s %x %x\n", __func__, status, req_ack);
+		status &= req_ack;
+		if (status) {
+			ctrl = readl(priv->base_addr + FREEZE_CSR_CTRL_OFFSET);
+			dev_dbg(dev, "%s request %x acknowledged %x %x\n",
+				__func__, req_ack, status, ctrl);
+			ret = 0;
+			break;
+		}
+
+		udelay(1);
+	} while (timeout--);
+
+	if (ret == -ETIMEDOUT)
+		dev_err(dev, "%s timeout waiting for 0x%x\n",
+			__func__, req_ack);
+
+	return ret;
+}
+
+static int altera_freeze_br_do_freeze(struct altera_freeze_br_data *priv,
+				      u32 timeout)
+{
+	struct device *dev = priv->dev;
+	void __iomem *csr_ctrl_addr = priv->base_addr +
+				      FREEZE_CSR_CTRL_OFFSET;
+	u32 status;
+	int ret;
+
+	status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
+
+	dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
+
+	if (status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE) {
+		dev_dbg(dev, "%s bridge already disabled %d\n",
+			__func__, status);
+		return 0;
+	} else if (!(status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)) {
+		dev_err(dev, "%s bridge not enabled %d\n", __func__, status);
+		return -EINVAL;
+	}
+
+	writel(FREEZE_CSR_CTRL_FREEZE_REQ, csr_ctrl_addr);
+
+	ret = altera_freeze_br_req_ack(priv, timeout,
+				       FREEZE_CSR_STATUS_FREEZE_REQ_DONE);
+
+	if (ret)
+		writel(0, csr_ctrl_addr);
+	else
+		writel(FREEZE_CSR_CTRL_RESET_REQ, csr_ctrl_addr);
+
+	return ret;
+}
+
+static int altera_freeze_br_do_unfreeze(struct altera_freeze_br_data *priv,
+					u32 timeout)
+{
+	struct device *dev = priv->dev;
+	void __iomem *csr_ctrl_addr = priv->base_addr +
+				      FREEZE_CSR_CTRL_OFFSET;
+	u32 status;
+	int ret;
+
+	writel(0, csr_ctrl_addr);
+
+	status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
+
+	dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
+
+	if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE) {
+		dev_dbg(dev, "%s bridge already enabled %d\n",
+			__func__, status);
+		return 0;
+	} else if (!(status & FREEZE_CSR_STATUS_FREEZE_REQ_DONE)) {
+		dev_err(dev, "%s bridge not frozen %d\n", __func__, status);
+		return -EINVAL;
+	}
+
+	writel(FREEZE_CSR_CTRL_UNFREEZE_REQ, csr_ctrl_addr);
+
+	ret = altera_freeze_br_req_ack(priv, timeout,
+				       FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE);
+
+	status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
+
+	dev_dbg(dev, "%s %d %d\n", __func__, status, readl(csr_ctrl_addr));
+
+	writel(0, csr_ctrl_addr);
+
+	return ret;
+}
+
+/*
+ * enable = 1 : allow traffic through the bridge
+ * enable = 0 : disable traffic through the bridge
+ */
+static int altera_freeze_br_enable_set(struct fpga_bridge *bridge,
+				       bool enable)
+{
+	struct altera_freeze_br_data *priv = bridge->priv;
+	struct fpga_image_info *info = bridge->info;
+	u32 timeout = 0;
+	int ret;
+
+	if (enable) {
+		if (info)
+			timeout = info->enable_timeout_us;
+
+		ret = altera_freeze_br_do_unfreeze(bridge->priv, timeout);
+	} else {
+		if (info)
+			timeout = info->disable_timeout_us;
+
+		ret = altera_freeze_br_do_freeze(bridge->priv, timeout);
+	}
+
+	if (!ret)
+		priv->enable = enable;
+
+	return ret;
+}
+
+static int altera_freeze_br_enable_show(struct fpga_bridge *bridge)
+{
+	struct altera_freeze_br_data *priv = bridge->priv;
+
+	return priv->enable;
+}
+
+static struct fpga_bridge_ops altera_freeze_br_br_ops = {
+	.enable_set = altera_freeze_br_enable_set,
+	.enable_show = altera_freeze_br_enable_show,
+};
+
+static const struct of_device_id altera_freeze_br_of_match[] = {
+	{ .compatible = "altr,freeze-bridge-controller", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_freeze_br_of_match);
+
+static int altera_freeze_br_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+	struct altera_freeze_br_data *priv;
+	struct resource *res;
+	u32 status, revision;
+
+	if (!np)
+		return -ENODEV;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->base_addr))
+		return PTR_ERR(priv->base_addr);
+
+	status = readl(priv->base_addr + FREEZE_CSR_STATUS_OFFSET);
+	if (status & FREEZE_CSR_STATUS_UNFREEZE_REQ_DONE)
+		priv->enable = 1;
+
+	revision = readl(priv->base_addr + FREEZE_CSR_REG_VERSION);
+	if (revision != FREEZE_CSR_SUPPORTED_VERSION)
+		dev_warn(dev,
+			 "%s Freeze Controller unexpected revision %d != %d\n",
+			 __func__, revision, FREEZE_CSR_SUPPORTED_VERSION);
+
+	return fpga_bridge_register(dev, FREEZE_BRIDGE_NAME,
+				    &altera_freeze_br_br_ops, priv);
+}
+
+static int altera_freeze_br_remove(struct platform_device *pdev)
+{
+	fpga_bridge_unregister(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver altera_freeze_br_driver = {
+	.probe = altera_freeze_br_probe,
+	.remove = altera_freeze_br_remove,
+	.driver = {
+		.name	= "altera_freeze_br",
+		.of_match_table = of_match_ptr(altera_freeze_br_of_match),
+	},
+};
+
+module_platform_driver(altera_freeze_br_driver);
+
+MODULE_DESCRIPTION("Altera Freeze Bridge");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/altera-hps2fpga.c linux-libre-4.10-rc8-gnu/drivers/fpga/altera-hps2fpga.c
--- linux-libre-4.9-gnu/drivers/fpga/altera-hps2fpga.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/altera-hps2fpga.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,222 @@
+/*
+ * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * Includes this patch from the mailing list:
+ *   fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters
+ *   Signed-off-by: Anatolij Gustschin <agust@denx.de>
+ *
+ * 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/>.
+ */
+
+/*
+ * This driver manages bridges on a Altera SOCFPGA between the ARM host
+ * processor system (HPS) and the embedded FPGA.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <linux/clk.h>
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/spinlock.h>
+
+#define ALT_L3_REMAP_OFST			0x0
+#define ALT_L3_REMAP_MPUZERO_MSK		0x00000001
+#define ALT_L3_REMAP_H2F_MSK			0x00000008
+#define ALT_L3_REMAP_LWH2F_MSK			0x00000010
+
+#define HPS2FPGA_BRIDGE_NAME			"hps2fpga"
+#define LWHPS2FPGA_BRIDGE_NAME			"lwhps2fpga"
+#define FPGA2HPS_BRIDGE_NAME			"fpga2hps"
+
+struct altera_hps2fpga_data {
+	const char *name;
+	struct reset_control *bridge_reset;
+	struct regmap *l3reg;
+	unsigned int remap_mask;
+	struct clk *clk;
+};
+
+static int alt_hps2fpga_enable_show(struct fpga_bridge *bridge)
+{
+	struct altera_hps2fpga_data *priv = bridge->priv;
+
+	return reset_control_status(priv->bridge_reset);
+}
+
+/* The L3 REMAP register is write only, so keep a cached value. */
+static unsigned int l3_remap_shadow;
+static spinlock_t l3_remap_lock;
+
+static int _alt_hps2fpga_enable_set(struct altera_hps2fpga_data *priv,
+				    bool enable)
+{
+	unsigned long flags;
+	int ret;
+
+	/* bring bridge out of reset */
+	if (enable)
+		ret = reset_control_deassert(priv->bridge_reset);
+	else
+		ret = reset_control_assert(priv->bridge_reset);
+	if (ret)
+		return ret;
+
+	/* Allow bridge to be visible to L3 masters or not */
+	if (priv->remap_mask) {
+		spin_lock_irqsave(&l3_remap_lock, flags);
+		l3_remap_shadow |= ALT_L3_REMAP_MPUZERO_MSK;
+
+		if (enable)
+			l3_remap_shadow |= priv->remap_mask;
+		else
+			l3_remap_shadow &= ~priv->remap_mask;
+
+		ret = regmap_write(priv->l3reg, ALT_L3_REMAP_OFST,
+				   l3_remap_shadow);
+		spin_unlock_irqrestore(&l3_remap_lock, flags);
+	}
+
+	return ret;
+}
+
+static int alt_hps2fpga_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_hps2fpga_enable_set(bridge->priv, enable);
+}
+
+static const struct fpga_bridge_ops altera_hps2fpga_br_ops = {
+	.enable_set = alt_hps2fpga_enable_set,
+	.enable_show = alt_hps2fpga_enable_show,
+};
+
+static struct altera_hps2fpga_data hps2fpga_data  = {
+	.name = HPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_H2F_MSK,
+};
+
+static struct altera_hps2fpga_data lwhps2fpga_data  = {
+	.name = LWHPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_LWH2F_MSK,
+};
+
+static struct altera_hps2fpga_data fpga2hps_data  = {
+	.name = FPGA2HPS_BRIDGE_NAME,
+};
+
+static const struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-hps2fpga-bridge",
+	  .data = &hps2fpga_data },
+	{ .compatible = "altr,socfpga-lwhps2fpga-bridge",
+	  .data = &lwhps2fpga_data },
+	{ .compatible = "altr,socfpga-fpga2hps-bridge",
+	  .data = &fpga2hps_data },
+	{},
+};
+
+static int alt_fpga_bridge_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct altera_hps2fpga_data *priv;
+	const struct of_device_id *of_id;
+	u32 enable;
+	int ret;
+
+	of_id = of_match_device(altera_fpga_of_match, dev);
+	priv = (struct altera_hps2fpga_data *)of_id->data;
+
+	priv->bridge_reset = of_reset_control_get_by_index(dev->of_node, 0);
+	if (IS_ERR(priv->bridge_reset)) {
+		dev_err(dev, "Could not get %s reset control\n", priv->name);
+		return PTR_ERR(priv->bridge_reset);
+	}
+
+	if (priv->remap_mask) {
+		priv->l3reg = syscon_regmap_lookup_by_compatible("altr,l3regs");
+		if (IS_ERR(priv->l3reg)) {
+			dev_err(dev, "regmap for altr,l3regs lookup failed\n");
+			return PTR_ERR(priv->l3reg);
+		}
+	}
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "no clock specified\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "could not enable clock\n");
+		return -EBUSY;
+	}
+
+	spin_lock_init(&l3_remap_lock);
+
+	if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
+		if (enable > 1) {
+			dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
+		} else {
+			dev_info(dev, "%s bridge\n",
+				 (enable ? "enabling" : "disabling"));
+
+			ret = _alt_hps2fpga_enable_set(priv, enable);
+			if (ret) {
+				fpga_bridge_unregister(&pdev->dev);
+				return ret;
+			}
+		}
+	}
+
+	return fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
+				    priv);
+}
+
+static int alt_fpga_bridge_remove(struct platform_device *pdev)
+{
+	struct fpga_bridge *bridge = platform_get_drvdata(pdev);
+	struct altera_hps2fpga_data *priv = bridge->priv;
+
+	fpga_bridge_unregister(&pdev->dev);
+
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
+
+static struct platform_driver alt_fpga_bridge_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.remove = alt_fpga_bridge_remove,
+	.driver = {
+		.name	= "altera_hps2fpga_bridge",
+		.of_match_table = of_match_ptr(altera_fpga_of_match),
+	},
+};
+
+module_platform_driver(alt_fpga_bridge_driver);
+
+MODULE_DESCRIPTION("Altera SoCFPGA HPS to FPGA Bridge");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/fpga-bridge.c linux-libre-4.10-rc8-gnu/drivers/fpga/fpga-bridge.c
--- linux-libre-4.9-gnu/drivers/fpga/fpga-bridge.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/fpga-bridge.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,395 @@
+/*
+ * FPGA Bridge Framework Driver
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+static DEFINE_IDA(fpga_bridge_ida);
+static struct class *fpga_bridge_class;
+
+/* Lock for adding/removing bridges to linked lists*/
+spinlock_t bridge_list_lock;
+
+static int fpga_bridge_of_node_match(struct device *dev, const void *data)
+{
+	return dev->of_node == data;
+}
+
+/**
+ * fpga_bridge_enable - Enable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_enable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "enable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_enable);
+
+/**
+ * fpga_bridge_disable - Disable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_disable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "disable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_disable);
+
+/**
+ * of_fpga_bridge_get - get an exclusive reference to a fpga bridge
+ *
+ * @np: node pointer of a FPGA bridge
+ * @info: fpga image specific information
+ *
+ * Return fpga_bridge struct if successful.
+ * Return -EBUSY if someone already has a reference to the bridge.
+ * Return -ENODEV if @np is not a FPGA Bridge.
+ */
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
+				       struct fpga_image_info *info)
+
+{
+	struct device *dev;
+	struct fpga_bridge *bridge;
+	int ret = -ENODEV;
+
+	dev = class_find_device(fpga_bridge_class, NULL, np,
+				fpga_bridge_of_node_match);
+	if (!dev)
+		goto err_dev;
+
+	bridge = to_fpga_bridge(dev);
+	if (!bridge)
+		goto err_dev;
+
+	bridge->info = info;
+
+	if (!mutex_trylock(&bridge->mutex)) {
+		ret = -EBUSY;
+		goto err_dev;
+	}
+
+	if (!try_module_get(dev->parent->driver->owner))
+		goto err_ll_mod;
+
+	dev_dbg(&bridge->dev, "get\n");
+
+	return bridge;
+
+err_ll_mod:
+	mutex_unlock(&bridge->mutex);
+err_dev:
+	put_device(dev);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+
+/**
+ * fpga_bridge_put - release a reference to a bridge
+ *
+ * @bridge: FPGA bridge
+ */
+void fpga_bridge_put(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "put\n");
+
+	bridge->info = NULL;
+	module_put(bridge->dev.parent->driver->owner);
+	mutex_unlock(&bridge->mutex);
+	put_device(&bridge->dev);
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_put);
+
+/**
+ * fpga_bridges_enable - enable bridges in a list
+ * @bridge_list: list of FPGA bridges
+ *
+ * Enable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_enable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	struct list_head *node;
+	int ret;
+
+	list_for_each(node, bridge_list) {
+		bridge = list_entry(node, struct fpga_bridge, node);
+		ret = fpga_bridge_enable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_enable);
+
+/**
+ * fpga_bridges_disable - disable bridges in a list
+ *
+ * @bridge_list: list of FPGA bridges
+ *
+ * Disable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_disable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	struct list_head *node;
+	int ret;
+
+	list_for_each(node, bridge_list) {
+		bridge = list_entry(node, struct fpga_bridge, node);
+		ret = fpga_bridge_disable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_disable);
+
+/**
+ * fpga_bridges_put - put bridges
+ *
+ * @bridge_list: list of FPGA bridges
+ *
+ * For each bridge in the list, put the bridge and remove it from the list.
+ * If list is empty, do nothing.
+ */
+void fpga_bridges_put(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	struct list_head *node, *next;
+	unsigned long flags;
+
+	list_for_each_safe(node, next, bridge_list) {
+		bridge = list_entry(node, struct fpga_bridge, node);
+
+		fpga_bridge_put(bridge);
+
+		spin_lock_irqsave(&bridge_list_lock, flags);
+		list_del(&bridge->node);
+		spin_unlock_irqrestore(&bridge_list_lock, flags);
+	}
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_put);
+
+/**
+ * fpga_bridges_get_to_list - get a bridge, add it to a list
+ *
+ * @np: node pointer of a FPGA bridge
+ * @info: fpga image specific information
+ * @bridge_list: list of FPGA bridges
+ *
+ * Get an exclusive reference to the bridge and and it to the list.
+ *
+ * Return 0 for success, error code from of_fpga_bridge_get() othewise.
+ */
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct fpga_image_info *info,
+			    struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	unsigned long flags;
+
+	bridge = of_fpga_bridge_get(np, info);
+	if (IS_ERR(bridge))
+		return PTR_ERR(bridge);
+
+	spin_lock_irqsave(&bridge_list_lock, flags);
+	list_add(&bridge->node, bridge_list);
+	spin_unlock_irqrestore(&bridge_list_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
+
+static ssize_t name_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	struct fpga_bridge *bridge = to_fpga_bridge(dev);
+
+	return sprintf(buf, "%s\n", bridge->name);
+}
+
+static ssize_t state_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct fpga_bridge *bridge = to_fpga_bridge(dev);
+	int enable = 1;
+
+	if (bridge->br_ops && bridge->br_ops->enable_show)
+		enable = bridge->br_ops->enable_show(bridge);
+
+	return sprintf(buf, "%s\n", enable ? "enabled" : "disabled");
+}
+
+static DEVICE_ATTR_RO(name);
+static DEVICE_ATTR_RO(state);
+
+static struct attribute *fpga_bridge_attrs[] = {
+	&dev_attr_name.attr,
+	&dev_attr_state.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(fpga_bridge);
+
+/**
+ * fpga_bridge_register - register a fpga bridge driver
+ * @dev:	FPGA bridge device from pdev
+ * @name:	FPGA bridge name
+ * @br_ops:	pointer to structure of fpga bridge ops
+ * @priv:	FPGA bridge private data
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_register(struct device *dev, const char *name,
+			 const struct fpga_bridge_ops *br_ops, void *priv)
+{
+	struct fpga_bridge *bridge;
+	int id, ret = 0;
+
+	if (!name || !strlen(name)) {
+		dev_err(dev, "Attempt to register with no name!\n");
+		return -EINVAL;
+	}
+
+	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
+	if (!bridge)
+		return -ENOMEM;
+
+	id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		ret = id;
+		goto error_kfree;
+	}
+
+	mutex_init(&bridge->mutex);
+	INIT_LIST_HEAD(&bridge->node);
+
+	bridge->name = name;
+	bridge->br_ops = br_ops;
+	bridge->priv = priv;
+
+	device_initialize(&bridge->dev);
+	bridge->dev.class = fpga_bridge_class;
+	bridge->dev.parent = dev;
+	bridge->dev.of_node = dev->of_node;
+	bridge->dev.id = id;
+	dev_set_drvdata(dev, bridge);
+
+	ret = dev_set_name(&bridge->dev, "br%d", id);
+	if (ret)
+		goto error_device;
+
+	ret = device_add(&bridge->dev);
+	if (ret)
+		goto error_device;
+
+	of_platform_populate(dev->of_node, NULL, NULL, dev);
+
+	dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
+		 bridge->name);
+
+	return 0;
+
+error_device:
+	ida_simple_remove(&fpga_bridge_ida, id);
+error_kfree:
+	kfree(bridge);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_register);
+
+/**
+ * fpga_bridge_unregister - unregister a fpga bridge driver
+ * @dev: FPGA bridge device from pdev
+ */
+void fpga_bridge_unregister(struct device *dev)
+{
+	struct fpga_bridge *bridge = dev_get_drvdata(dev);
+
+	/*
+	 * If the low level driver provides a method for putting bridge into
+	 * a desired state upon unregister, do it.
+	 */
+	if (bridge->br_ops && bridge->br_ops->fpga_bridge_remove)
+		bridge->br_ops->fpga_bridge_remove(bridge);
+
+	device_unregister(&bridge->dev);
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
+
+static void fpga_bridge_dev_release(struct device *dev)
+{
+	struct fpga_bridge *bridge = to_fpga_bridge(dev);
+
+	ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
+	kfree(bridge);
+}
+
+static int __init fpga_bridge_dev_init(void)
+{
+	spin_lock_init(&bridge_list_lock);
+
+	fpga_bridge_class = class_create(THIS_MODULE, "fpga_bridge");
+	if (IS_ERR(fpga_bridge_class))
+		return PTR_ERR(fpga_bridge_class);
+
+	fpga_bridge_class->dev_groups = fpga_bridge_groups;
+	fpga_bridge_class->dev_release = fpga_bridge_dev_release;
+
+	return 0;
+}
+
+static void __exit fpga_bridge_dev_exit(void)
+{
+	class_destroy(fpga_bridge_class);
+	ida_destroy(&fpga_bridge_ida);
+}
+
+MODULE_DESCRIPTION("FPGA Bridge Driver");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
+
+subsys_initcall(fpga_bridge_dev_init);
+module_exit(fpga_bridge_dev_exit);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/fpga-mgr.c linux-libre-4.10-rc8-gnu/drivers/fpga/fpga-mgr.c
--- linux-libre-4.9-gnu/drivers/fpga/fpga-mgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/fpga-mgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,19 +32,20 @@ static struct class *fpga_mgr_class;
 /**
  * fpga_mgr_buf_load - load fpga from image in buffer
  * @mgr:	fpga manager
- * @flags:	flags setting fpga confuration modes
+ * @info:	fpga image specific information
  * @buf:	buffer contain fpga image
  * @count:	byte count of buf
  *
  * Step the low level fpga manager through the device-specific steps of getting
  * an FPGA ready to be configured, writing the image to it, then doing whatever
  * post-configuration steps necessary.  This code assumes the caller got the
- * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code.
+ * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is
+ * not an error code.
  *
  * Return: 0 on success, negative error code otherwise.
  */
-int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf,
-		      size_t count)
+int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
+		      const char *buf, size_t count)
 {
 	struct device *dev = &mgr->dev;
 	int ret;
@@ -52,10 +53,12 @@ int fpga_mgr_buf_load(struct fpga_manage
 	/*
 	 * Call the low level driver's write_init function.  This will do the
 	 * device-specific things to get the FPGA into the state where it is
-	 * ready to receive an FPGA image.
+	 * ready to receive an FPGA image. The low level driver only gets to
+	 * see the first initial_header_size bytes in the buffer.
 	 */
 	mgr->state = FPGA_MGR_STATE_WRITE_INIT;
-	ret = mgr->mops->write_init(mgr, flags, buf, count);
+	ret = mgr->mops->write_init(mgr, info, buf,
+				    min(mgr->mops->initial_header_size, count));
 	if (ret) {
 		dev_err(dev, "Error preparing FPGA for writing\n");
 		mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR;
@@ -78,7 +81,7 @@ int fpga_mgr_buf_load(struct fpga_manage
 	 * steps to finish and set the FPGA into operating mode.
 	 */
 	mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE;
-	ret = mgr->mops->write_complete(mgr, flags);
+	ret = mgr->mops->write_complete(mgr, info);
 	if (ret) {
 		dev_err(dev, "Error after writing image data to FPGA\n");
 		mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
@@ -93,17 +96,19 @@ EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
 /**
  * fpga_mgr_firmware_load - request firmware and load to fpga
  * @mgr:	fpga manager
- * @flags:	flags setting fpga confuration modes
+ * @info:	fpga image specific information
  * @image_name:	name of image file on the firmware search path
  *
  * Request an FPGA image using the firmware class, then write out to the FPGA.
  * Update the state before each step to provide info on what step failed if
  * there is a failure.  This code assumes the caller got the mgr pointer
- * from of_fpga_mgr_get() and checked that it is not an error code.
+ * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error
+ * code.
  *
  * Return: 0 on success, negative error code otherwise.
  */
-int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags,
+int fpga_mgr_firmware_load(struct fpga_manager *mgr,
+			   struct fpga_image_info *info,
 			   const char *image_name)
 {
 	struct device *dev = &mgr->dev;
@@ -121,7 +126,7 @@ int fpga_mgr_firmware_load(struct fpga_m
 		return ret;
 	}
 
-	ret = fpga_mgr_buf_load(mgr, flags, fw->data, fw->size);
+	ret = fpga_mgr_buf_load(mgr, info, fw->data, fw->size);
 
 	release_firmware(fw);
 
@@ -181,30 +186,11 @@ static struct attribute *fpga_mgr_attrs[
 };
 ATTRIBUTE_GROUPS(fpga_mgr);
 
-static int fpga_mgr_of_node_match(struct device *dev, const void *data)
-{
-	return dev->of_node == data;
-}
-
-/**
- * of_fpga_mgr_get - get an exclusive reference to a fpga mgr
- * @node:	device node
- *
- * Given a device node, get an exclusive reference to a fpga mgr.
- *
- * Return: fpga manager struct or IS_ERR() condition containing error code.
- */
-struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
+struct fpga_manager *__fpga_mgr_get(struct device *dev)
 {
 	struct fpga_manager *mgr;
-	struct device *dev;
 	int ret = -ENODEV;
 
-	dev = class_find_device(fpga_mgr_class, NULL, node,
-				fpga_mgr_of_node_match);
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
 	mgr = to_fpga_manager(dev);
 	if (!mgr)
 		goto err_dev;
@@ -226,6 +212,55 @@ err_dev:
 	put_device(dev);
 	return ERR_PTR(ret);
 }
+
+static int fpga_mgr_dev_match(struct device *dev, const void *data)
+{
+	return dev->parent == data;
+}
+
+/**
+ * fpga_mgr_get - get an exclusive reference to a fpga mgr
+ * @dev:	parent device that fpga mgr was registered with
+ *
+ * Given a device, get an exclusive reference to a fpga mgr.
+ *
+ * Return: fpga manager struct or IS_ERR() condition containing error code.
+ */
+struct fpga_manager *fpga_mgr_get(struct device *dev)
+{
+	struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev,
+						   fpga_mgr_dev_match);
+	if (!mgr_dev)
+		return ERR_PTR(-ENODEV);
+
+	return __fpga_mgr_get(mgr_dev);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_get);
+
+static int fpga_mgr_of_node_match(struct device *dev, const void *data)
+{
+	return dev->of_node == data;
+}
+
+/**
+ * of_fpga_mgr_get - get an exclusive reference to a fpga mgr
+ * @node:	device node
+ *
+ * Given a device node, get an exclusive reference to a fpga mgr.
+ *
+ * Return: fpga manager struct or IS_ERR() condition containing error code.
+ */
+struct fpga_manager *of_fpga_mgr_get(struct device_node *node)
+{
+	struct device *dev;
+
+	dev = class_find_device(fpga_mgr_class, NULL, node,
+				fpga_mgr_of_node_match);
+	if (!dev)
+		return ERR_PTR(-ENODEV);
+
+	return __fpga_mgr_get(dev);
+}
 EXPORT_SYMBOL_GPL(of_fpga_mgr_get);
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/fpga-region.c linux-libre-4.10-rc8-gnu/drivers/fpga/fpga-region.c
--- linux-libre-4.9-gnu/drivers/fpga/fpga-region.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/fpga-region.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,603 @@
+/*
+ * FPGA Region - Device Tree support for FPGA programming under Linux
+ *
+ *  Copyright (C) 2013-2016 Altera 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+/**
+ * struct fpga_region - FPGA Region structure
+ * @dev: FPGA Region device
+ * @mutex: enforces exclusive reference to region
+ * @bridge_list: list of FPGA bridges specified in region
+ * @info: fpga image specific information
+ */
+struct fpga_region {
+	struct device dev;
+	struct mutex mutex; /* for exclusive reference to region */
+	struct list_head bridge_list;
+	struct fpga_image_info *info;
+};
+
+#define to_fpga_region(d) container_of(d, struct fpga_region, dev)
+
+static DEFINE_IDA(fpga_region_ida);
+static struct class *fpga_region_class;
+
+static const struct of_device_id fpga_region_of_match[] = {
+	{ .compatible = "fpga-region", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, fpga_region_of_match);
+
+static int fpga_region_of_node_match(struct device *dev, const void *data)
+{
+	return dev->of_node == data;
+}
+
+/**
+ * fpga_region_find - find FPGA region
+ * @np: device node of FPGA Region
+ * Caller will need to put_device(&region->dev) when done.
+ * Returns FPGA Region struct or NULL
+ */
+static struct fpga_region *fpga_region_find(struct device_node *np)
+{
+	struct device *dev;
+
+	dev = class_find_device(fpga_region_class, NULL, np,
+				fpga_region_of_node_match);
+	if (!dev)
+		return NULL;
+
+	return to_fpga_region(dev);
+}
+
+/**
+ * fpga_region_get - get an exclusive reference to a fpga region
+ * @region: FPGA Region struct
+ *
+ * Caller should call fpga_region_put() when done with region.
+ *
+ * Return fpga_region struct if successful.
+ * Return -EBUSY if someone already has a reference to the region.
+ * Return -ENODEV if @np is not a FPGA Region.
+ */
+static struct fpga_region *fpga_region_get(struct fpga_region *region)
+{
+	struct device *dev = &region->dev;
+
+	if (!mutex_trylock(&region->mutex)) {
+		dev_dbg(dev, "%s: FPGA Region already in use\n", __func__);
+		return ERR_PTR(-EBUSY);
+	}
+
+	get_device(dev);
+	of_node_get(dev->of_node);
+	if (!try_module_get(dev->parent->driver->owner)) {
+		of_node_put(dev->of_node);
+		put_device(dev);
+		mutex_unlock(&region->mutex);
+		return ERR_PTR(-ENODEV);
+	}
+
+	dev_dbg(&region->dev, "get\n");
+
+	return region;
+}
+
+/**
+ * fpga_region_put - release a reference to a region
+ *
+ * @region: FPGA region
+ */
+static void fpga_region_put(struct fpga_region *region)
+{
+	struct device *dev = &region->dev;
+
+	dev_dbg(&region->dev, "put\n");
+
+	module_put(dev->parent->driver->owner);
+	of_node_put(dev->of_node);
+	put_device(dev);
+	mutex_unlock(&region->mutex);
+}
+
+/**
+ * fpga_region_get_manager - get exclusive reference for FPGA manager
+ * @region: FPGA region
+ *
+ * Get FPGA Manager from "fpga-mgr" property or from ancestor region.
+ *
+ * Caller should call fpga_mgr_put() when done with manager.
+ *
+ * Return: fpga manager struct or IS_ERR() condition containing error code.
+ */
+static struct fpga_manager *fpga_region_get_manager(struct fpga_region *region)
+{
+	struct device *dev = &region->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node  *mgr_node;
+	struct fpga_manager *mgr;
+
+	of_node_get(np);
+	while (np) {
+		if (of_device_is_compatible(np, "fpga-region")) {
+			mgr_node = of_parse_phandle(np, "fpga-mgr", 0);
+			if (mgr_node) {
+				mgr = of_fpga_mgr_get(mgr_node);
+				of_node_put(np);
+				return mgr;
+			}
+		}
+		np = of_get_next_parent(np);
+	}
+	of_node_put(np);
+
+	return ERR_PTR(-EINVAL);
+}
+
+/**
+ * fpga_region_get_bridges - create a list of bridges
+ * @region: FPGA region
+ * @overlay: device node of the overlay
+ *
+ * Create a list of bridges including the parent bridge and the bridges
+ * specified by "fpga-bridges" property.  Note that the
+ * fpga_bridges_enable/disable/put functions are all fine with an empty list
+ * if that happens.
+ *
+ * Caller should call fpga_bridges_put(&region->bridge_list) when
+ * done with the bridges.
+ *
+ * Return 0 for success (even if there are no bridges specified)
+ * or -EBUSY if any of the bridges are in use.
+ */
+static int fpga_region_get_bridges(struct fpga_region *region,
+				   struct device_node *overlay)
+{
+	struct device *dev = &region->dev;
+	struct device_node *region_np = dev->of_node;
+	struct device_node *br, *np, *parent_br = NULL;
+	int i, ret;
+
+	/* If parent is a bridge, add to list */
+	ret = fpga_bridge_get_to_list(region_np->parent, region->info,
+				      &region->bridge_list);
+	if (ret == -EBUSY)
+		return ret;
+
+	if (!ret)
+		parent_br = region_np->parent;
+
+	/* If overlay has a list of bridges, use it. */
+	if (of_parse_phandle(overlay, "fpga-bridges", 0))
+		np = overlay;
+	else
+		np = region_np;
+
+	for (i = 0; ; i++) {
+		br = of_parse_phandle(np, "fpga-bridges", i);
+		if (!br)
+			break;
+
+		/* If parent bridge is in list, skip it. */
+		if (br == parent_br)
+			continue;
+
+		/* If node is a bridge, get it and add to list */
+		ret = fpga_bridge_get_to_list(br, region->info,
+					      &region->bridge_list);
+
+		/* If any of the bridges are in use, give up */
+		if (ret == -EBUSY) {
+			fpga_bridges_put(&region->bridge_list);
+			return -EBUSY;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * fpga_region_program_fpga - program FPGA
+ * @region: FPGA region
+ * @firmware_name: name of FPGA image firmware file
+ * @overlay: device node of the overlay
+ * Program an FPGA using information in the device tree.
+ * Function assumes that there is a firmware-name property.
+ * Return 0 for success or negative error code.
+ */
+static int fpga_region_program_fpga(struct fpga_region *region,
+				    const char *firmware_name,
+				    struct device_node *overlay)
+{
+	struct fpga_manager *mgr;
+	int ret;
+
+	region = fpga_region_get(region);
+	if (IS_ERR(region)) {
+		pr_err("failed to get fpga region\n");
+		return PTR_ERR(region);
+	}
+
+	mgr = fpga_region_get_manager(region);
+	if (IS_ERR(mgr)) {
+		pr_err("failed to get fpga region manager\n");
+		return PTR_ERR(mgr);
+	}
+
+	ret = fpga_region_get_bridges(region, overlay);
+	if (ret) {
+		pr_err("failed to get fpga region bridges\n");
+		goto err_put_mgr;
+	}
+
+	ret = fpga_bridges_disable(&region->bridge_list);
+	if (ret) {
+		pr_err("failed to disable region bridges\n");
+		goto err_put_br;
+	}
+
+	ret = fpga_mgr_firmware_load(mgr, region->info, firmware_name);
+	if (ret) {
+		pr_err("failed to load fpga image\n");
+		goto err_put_br;
+	}
+
+	ret = fpga_bridges_enable(&region->bridge_list);
+	if (ret) {
+		pr_err("failed to enable region bridges\n");
+		goto err_put_br;
+	}
+
+	fpga_mgr_put(mgr);
+	fpga_region_put(region);
+
+	return 0;
+
+err_put_br:
+	fpga_bridges_put(&region->bridge_list);
+err_put_mgr:
+	fpga_mgr_put(mgr);
+	fpga_region_put(region);
+
+	return ret;
+}
+
+/**
+ * child_regions_with_firmware
+ * @overlay: device node of the overlay
+ *
+ * If the overlay adds child FPGA regions, they are not allowed to have
+ * firmware-name property.
+ *
+ * Return 0 for OK or -EINVAL if child FPGA region adds firmware-name.
+ */
+static int child_regions_with_firmware(struct device_node *overlay)
+{
+	struct device_node *child_region;
+	const char *child_firmware_name;
+	int ret = 0;
+
+	of_node_get(overlay);
+
+	child_region = of_find_matching_node(overlay, fpga_region_of_match);
+	while (child_region) {
+		if (!of_property_read_string(child_region, "firmware-name",
+					     &child_firmware_name)) {
+			ret = -EINVAL;
+			break;
+		}
+		child_region = of_find_matching_node(child_region,
+						     fpga_region_of_match);
+	}
+
+	of_node_put(child_region);
+
+	if (ret)
+		pr_err("firmware-name not allowed in child FPGA region: %s",
+		       child_region->full_name);
+
+	return ret;
+}
+
+/**
+ * fpga_region_notify_pre_apply - pre-apply overlay notification
+ *
+ * @region: FPGA region that the overlay was applied to
+ * @nd: overlay notification data
+ *
+ * Called after when an overlay targeted to a FPGA Region is about to be
+ * applied.  Function will check the properties that will be added to the FPGA
+ * region.  If the checks pass, it will program the FPGA.
+ *
+ * The checks are:
+ * The overlay must add either firmware-name or external-fpga-config property
+ * to the FPGA Region.
+ *
+ *   firmware-name        : program the FPGA
+ *   external-fpga-config : FPGA is already programmed
+ *
+ * The overlay can add other FPGA regions, but child FPGA regions cannot have a
+ * firmware-name property since those regions don't exist yet.
+ *
+ * If the overlay that breaks the rules, notifier returns an error and the
+ * overlay is rejected before it goes into the main tree.
+ *
+ * Returns 0 for success or negative error code for failure.
+ */
+static int fpga_region_notify_pre_apply(struct fpga_region *region,
+					struct of_overlay_notify_data *nd)
+{
+	const char *firmware_name = NULL;
+	struct fpga_image_info *info;
+	int ret;
+
+	info = devm_kzalloc(&region->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	region->info = info;
+
+	/* Reject overlay if child FPGA Regions have firmware-name property */
+	ret = child_regions_with_firmware(nd->overlay);
+	if (ret)
+		return ret;
+
+	/* Read FPGA region properties from the overlay */
+	if (of_property_read_bool(nd->overlay, "partial-fpga-config"))
+		info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
+
+	if (of_property_read_bool(nd->overlay, "external-fpga-config"))
+		info->flags |= FPGA_MGR_EXTERNAL_CONFIG;
+
+	of_property_read_string(nd->overlay, "firmware-name", &firmware_name);
+
+	of_property_read_u32(nd->overlay, "region-unfreeze-timeout-us",
+			     &info->enable_timeout_us);
+
+	of_property_read_u32(nd->overlay, "region-freeze-timeout-us",
+			     &info->disable_timeout_us);
+
+	/* If FPGA was externally programmed, don't specify firmware */
+	if ((info->flags & FPGA_MGR_EXTERNAL_CONFIG) && firmware_name) {
+		pr_err("error: specified firmware and external-fpga-config");
+		return -EINVAL;
+	}
+
+	/* FPGA is already configured externally.  We're done. */
+	if (info->flags & FPGA_MGR_EXTERNAL_CONFIG)
+		return 0;
+
+	/* If we got this far, we should be programming the FPGA */
+	if (!firmware_name) {
+		pr_err("should specify firmware-name or external-fpga-config\n");
+		return -EINVAL;
+	}
+
+	return fpga_region_program_fpga(region, firmware_name, nd->overlay);
+}
+
+/**
+ * fpga_region_notify_post_remove - post-remove overlay notification
+ *
+ * @region: FPGA region that was targeted by the overlay that was removed
+ * @nd: overlay notification data
+ *
+ * Called after an overlay has been removed if the overlay's target was a
+ * FPGA region.
+ */
+static void fpga_region_notify_post_remove(struct fpga_region *region,
+					   struct of_overlay_notify_data *nd)
+{
+	fpga_bridges_disable(&region->bridge_list);
+	fpga_bridges_put(&region->bridge_list);
+	devm_kfree(&region->dev, region->info);
+	region->info = NULL;
+}
+
+/**
+ * of_fpga_region_notify - reconfig notifier for dynamic DT changes
+ * @nb:		notifier block
+ * @action:	notifier action
+ * @arg:	reconfig data
+ *
+ * This notifier handles programming a FPGA when a "firmware-name" property is
+ * added to a fpga-region.
+ *
+ * Returns NOTIFY_OK or error if FPGA programming fails.
+ */
+static int of_fpga_region_notify(struct notifier_block *nb,
+				 unsigned long action, void *arg)
+{
+	struct of_overlay_notify_data *nd = arg;
+	struct fpga_region *region;
+	int ret;
+
+	switch (action) {
+	case OF_OVERLAY_PRE_APPLY:
+		pr_debug("%s OF_OVERLAY_PRE_APPLY\n", __func__);
+		break;
+	case OF_OVERLAY_POST_APPLY:
+		pr_debug("%s OF_OVERLAY_POST_APPLY\n", __func__);
+		return NOTIFY_OK;       /* not for us */
+	case OF_OVERLAY_PRE_REMOVE:
+		pr_debug("%s OF_OVERLAY_PRE_REMOVE\n", __func__);
+		return NOTIFY_OK;       /* not for us */
+	case OF_OVERLAY_POST_REMOVE:
+		pr_debug("%s OF_OVERLAY_POST_REMOVE\n", __func__);
+		break;
+	default:			/* should not happen */
+		return NOTIFY_OK;
+	}
+
+	region = fpga_region_find(nd->target);
+	if (!region)
+		return NOTIFY_OK;
+
+	ret = 0;
+	switch (action) {
+	case OF_OVERLAY_PRE_APPLY:
+		ret = fpga_region_notify_pre_apply(region, nd);
+		break;
+
+	case OF_OVERLAY_POST_REMOVE:
+		fpga_region_notify_post_remove(region, nd);
+		break;
+	}
+
+	put_device(&region->dev);
+
+	if (ret)
+		return notifier_from_errno(ret);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block fpga_region_of_nb = {
+	.notifier_call = of_fpga_region_notify,
+};
+
+static int fpga_region_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct fpga_region *region;
+	int id, ret = 0;
+
+	region = kzalloc(sizeof(*region), GFP_KERNEL);
+	if (!region)
+		return -ENOMEM;
+
+	id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
+	if (id < 0) {
+		ret = id;
+		goto err_kfree;
+	}
+
+	mutex_init(&region->mutex);
+	INIT_LIST_HEAD(&region->bridge_list);
+
+	device_initialize(&region->dev);
+	region->dev.class = fpga_region_class;
+	region->dev.parent = dev;
+	region->dev.of_node = np;
+	region->dev.id = id;
+	dev_set_drvdata(dev, region);
+
+	ret = dev_set_name(&region->dev, "region%d", id);
+	if (ret)
+		goto err_remove;
+
+	ret = device_add(&region->dev);
+	if (ret)
+		goto err_remove;
+
+	of_platform_populate(np, fpga_region_of_match, NULL, &region->dev);
+
+	dev_info(dev, "FPGA Region probed\n");
+
+	return 0;
+
+err_remove:
+	ida_simple_remove(&fpga_region_ida, id);
+err_kfree:
+	kfree(region);
+
+	return ret;
+}
+
+static int fpga_region_remove(struct platform_device *pdev)
+{
+	struct fpga_region *region = platform_get_drvdata(pdev);
+
+	device_unregister(&region->dev);
+
+	return 0;
+}
+
+static struct platform_driver fpga_region_driver = {
+	.probe = fpga_region_probe,
+	.remove = fpga_region_remove,
+	.driver = {
+		.name	= "fpga-region",
+		.of_match_table = of_match_ptr(fpga_region_of_match),
+	},
+};
+
+static void fpga_region_dev_release(struct device *dev)
+{
+	struct fpga_region *region = to_fpga_region(dev);
+
+	ida_simple_remove(&fpga_region_ida, region->dev.id);
+	kfree(region);
+}
+
+/**
+ * fpga_region_init - init function for fpga_region class
+ * Creates the fpga_region class and registers a reconfig notifier.
+ */
+static int __init fpga_region_init(void)
+{
+	int ret;
+
+	fpga_region_class = class_create(THIS_MODULE, "fpga_region");
+	if (IS_ERR(fpga_region_class))
+		return PTR_ERR(fpga_region_class);
+
+	fpga_region_class->dev_release = fpga_region_dev_release;
+
+	ret = of_overlay_notifier_register(&fpga_region_of_nb);
+	if (ret)
+		goto err_class;
+
+	ret = platform_driver_register(&fpga_region_driver);
+	if (ret)
+		goto err_plat;
+
+	return 0;
+
+err_plat:
+	of_overlay_notifier_unregister(&fpga_region_of_nb);
+err_class:
+	class_destroy(fpga_region_class);
+	ida_destroy(&fpga_region_ida);
+	return ret;
+}
+
+static void __exit fpga_region_exit(void)
+{
+	platform_driver_unregister(&fpga_region_driver);
+	of_overlay_notifier_unregister(&fpga_region_of_nb);
+	class_destroy(fpga_region_class);
+	ida_destroy(&fpga_region_ida);
+}
+
+subsys_initcall(fpga_region_init);
+module_exit(fpga_region_exit);
+
+MODULE_DESCRIPTION("FPGA Region");
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/Kconfig linux-libre-4.10-rc8-gnu/drivers/fpga/Kconfig
--- linux-libre-4.9-gnu/drivers/fpga/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -13,12 +13,26 @@ config FPGA
 
 if FPGA
 
+config FPGA_REGION
+	tristate "FPGA Region"
+	depends on OF && FPGA_BRIDGE
+	help
+	  FPGA Regions allow loading FPGA images under control of
+	  the Device Tree.
+
 config FPGA_MGR_SOCFPGA
 	tristate "Altera SOCFPGA FPGA Manager"
-	depends on ARCH_SOCFPGA
+	depends on ARCH_SOCFPGA || COMPILE_TEST
 	help
 	  FPGA manager driver support for Altera SOCFPGA.
 
+config FPGA_MGR_SOCFPGA_A10
+	tristate "Altera SoCFPGA Arria10"
+	depends on ARCH_SOCFPGA || COMPILE_TEST
+	select REGMAP_MMIO
+	help
+	  FPGA manager driver support for Altera Arria10 SoCFPGA.
+
 config FPGA_MGR_ZYNQ_FPGA
 	tristate "Xilinx Zynq FPGA"
 	depends on ARCH_ZYNQ || COMPILE_TEST
@@ -26,6 +40,29 @@ config FPGA_MGR_ZYNQ_FPGA
 	help
 	  FPGA manager driver support for Xilinx Zynq FPGAs.
 
+config FPGA_BRIDGE
+	tristate "FPGA Bridge Framework"
+	depends on OF
+	help
+	  Say Y here if you want to support bridges connected between host
+	  processors and FPGAs or between FPGAs.
+
+config SOCFPGA_FPGA_BRIDGE
+	tristate "Altera SoCFPGA FPGA Bridges"
+	depends on ARCH_SOCFPGA && FPGA_BRIDGE
+	help
+	  Say Y to enable drivers for FPGA bridges for Altera SOCFPGA
+	  devices.
+
+config ALTERA_FREEZE_BRIDGE
+	tristate "Altera FPGA Freeze Bridge"
+	depends on ARCH_SOCFPGA && FPGA_BRIDGE
+	help
+	  Say Y to enable drivers for Altera FPGA Freeze bridges.  A
+	  freeze bridge is a bridge that exists in the FPGA fabric to
+	  isolate one region of the FPGA from the busses while that
+	  region is being reprogrammed.
+
 endif # FPGA
 
 endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/Makefile linux-libre-4.10-rc8-gnu/drivers/fpga/Makefile
--- linux-libre-4.9-gnu/drivers/fpga/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -7,4 +7,13 @@ obj-$(CONFIG_FPGA)			+= fpga-mgr.o
 
 # FPGA Manager Drivers
 obj-$(CONFIG_FPGA_MGR_SOCFPGA)		+= socfpga.o
+obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10)	+= socfpga-a10.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
+
+# FPGA Bridge Drivers
+obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
+obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE)	+= altera-hps2fpga.o altera-fpga2sdram.o
+obj-$(CONFIG_ALTERA_FREEZE_BRIDGE)	+= altera-freeze-bridge.o
+
+# High Level Interfaces
+obj-$(CONFIG_FPGA_REGION)		+= fpga-region.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/socfpga-a10.c linux-libre-4.10-rc8-gnu/drivers/fpga/socfpga-a10.c
--- linux-libre-4.9-gnu/drivers/fpga/socfpga-a10.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/socfpga-a10.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,557 @@
+/*
+ * FPGA Manager Driver for Altera Arria10 SoCFPGA
+ *
+ * Copyright (C) 2015-2016 Altera 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
+
+#define A10_FPGAMGR_DCLKCNT_OFST				0x08
+#define A10_FPGAMGR_DCLKSTAT_OFST				0x0c
+#define A10_FPGAMGR_IMGCFG_CTL_00_OFST				0x70
+#define A10_FPGAMGR_IMGCFG_CTL_01_OFST				0x74
+#define A10_FPGAMGR_IMGCFG_CTL_02_OFST				0x78
+#define A10_FPGAMGR_IMGCFG_STAT_OFST				0x80
+
+#define A10_FPGAMGR_DCLKSTAT_DCLKDONE				BIT(0)
+
+#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG		BIT(0)
+#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS		BIT(1)
+#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE		BIT(2)
+#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG			BIT(8)
+#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE		BIT(16)
+#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE		BIT(24)
+
+#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG		BIT(0)
+#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST		BIT(16)
+#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE			BIT(24)
+
+#define A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL			BIT(0)
+#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK		(BIT(16) | BIT(17))
+#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT			16
+#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH			BIT(24)
+#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT		24
+
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR			BIT(0)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE		BIT(1)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE			BIT(2)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN			BIT(4)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN			BIT(6)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY			BIT(9)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE			BIT(10)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR			BIT(11)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN			BIT(12)
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK	(BIT(16) | BIT(17) | BIT(18))
+#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT		        16
+
+/* FPGA CD Ratio Value */
+#define CDRATIO_x1						0x0
+#define CDRATIO_x2						0x1
+#define CDRATIO_x4						0x2
+#define CDRATIO_x8						0x3
+
+/* Configuration width 16/32 bit */
+#define CFGWDTH_32						1
+#define CFGWDTH_16						0
+
+/*
+ * struct a10_fpga_priv - private data for fpga manager
+ * @regmap: regmap for register access
+ * @fpga_data_addr: iomap for single address data register to FPGA
+ * @clk: clock
+ */
+struct a10_fpga_priv {
+	struct regmap *regmap;
+	void __iomem *fpga_data_addr;
+	struct clk *clk;
+};
+
+static bool socfpga_a10_fpga_writeable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case A10_FPGAMGR_DCLKCNT_OFST:
+	case A10_FPGAMGR_DCLKSTAT_OFST:
+	case A10_FPGAMGR_IMGCFG_CTL_00_OFST:
+	case A10_FPGAMGR_IMGCFG_CTL_01_OFST:
+	case A10_FPGAMGR_IMGCFG_CTL_02_OFST:
+		return true;
+	}
+	return false;
+}
+
+static bool socfpga_a10_fpga_readable_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case A10_FPGAMGR_DCLKCNT_OFST:
+	case A10_FPGAMGR_DCLKSTAT_OFST:
+	case A10_FPGAMGR_IMGCFG_CTL_00_OFST:
+	case A10_FPGAMGR_IMGCFG_CTL_01_OFST:
+	case A10_FPGAMGR_IMGCFG_CTL_02_OFST:
+	case A10_FPGAMGR_IMGCFG_STAT_OFST:
+		return true;
+	}
+	return false;
+}
+
+static const struct regmap_config socfpga_a10_fpga_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.writeable_reg = socfpga_a10_fpga_writeable_reg,
+	.readable_reg = socfpga_a10_fpga_readable_reg,
+	.max_register = A10_FPGAMGR_IMGCFG_STAT_OFST,
+	.cache_type = REGCACHE_NONE,
+};
+
+/*
+ * from the register map description of cdratio in imgcfg_ctrl_02:
+ *  Normal Configuration    : 32bit Passive Parallel
+ *  Partial Reconfiguration : 16bit Passive Parallel
+ */
+static void socfpga_a10_fpga_set_cfg_width(struct a10_fpga_priv *priv,
+					   int width)
+{
+	width <<= A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT;
+
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH, width);
+}
+
+static void socfpga_a10_fpga_generate_dclks(struct a10_fpga_priv *priv,
+					    u32 count)
+{
+	u32 val;
+
+	/* Clear any existing DONE status. */
+	regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,
+		     A10_FPGAMGR_DCLKSTAT_DCLKDONE);
+
+	/* Issue the DCLK regmap. */
+	regmap_write(priv->regmap, A10_FPGAMGR_DCLKCNT_OFST, count);
+
+	/* wait till the dclkcnt done */
+	regmap_read_poll_timeout(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, val,
+				 val, 1, 100);
+
+	/* Clear DONE status. */
+	regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST,
+		     A10_FPGAMGR_DCLKSTAT_DCLKDONE);
+}
+
+#define RBF_ENCRYPTION_MODE_OFFSET		69
+#define RBF_DECOMPRESS_OFFSET			229
+
+static int socfpga_a10_fpga_encrypted(u32 *buf32, size_t buf32_size)
+{
+	if (buf32_size < RBF_ENCRYPTION_MODE_OFFSET + 1)
+		return -EINVAL;
+
+	/* Is the bitstream encrypted? */
+	return ((buf32[RBF_ENCRYPTION_MODE_OFFSET] >> 2) & 3) != 0;
+}
+
+static int socfpga_a10_fpga_compressed(u32 *buf32, size_t buf32_size)
+{
+	if (buf32_size < RBF_DECOMPRESS_OFFSET + 1)
+		return -EINVAL;
+
+	/* Is the bitstream compressed? */
+	return !((buf32[RBF_DECOMPRESS_OFFSET] >> 1) & 1);
+}
+
+static unsigned int socfpga_a10_fpga_get_cd_ratio(unsigned int cfg_width,
+						  bool encrypt, bool compress)
+{
+	unsigned int cd_ratio;
+
+	/*
+	 * cd ratio is dependent on cfg width and whether the bitstream
+	 * is encrypted and/or compressed.
+	 *
+	 * | width | encr. | compr. | cd ratio |
+	 * |  16   |   0   |   0    |     1    |
+	 * |  16   |   0   |   1    |     4    |
+	 * |  16   |   1   |   0    |     2    |
+	 * |  16   |   1   |   1    |     4    |
+	 * |  32   |   0   |   0    |     1    |
+	 * |  32   |   0   |   1    |     8    |
+	 * |  32   |   1   |   0    |     4    |
+	 * |  32   |   1   |   1    |     8    |
+	 */
+	if (!compress && !encrypt)
+		return CDRATIO_x1;
+
+	if (compress)
+		cd_ratio = CDRATIO_x4;
+	else
+		cd_ratio = CDRATIO_x2;
+
+	/* If 32 bit, double the cd ratio by incrementing the field  */
+	if (cfg_width == CFGWDTH_32)
+		cd_ratio += 1;
+
+	return cd_ratio;
+}
+
+static int socfpga_a10_fpga_set_cdratio(struct fpga_manager *mgr,
+					unsigned int cfg_width,
+					const char *buf, size_t count)
+{
+	struct a10_fpga_priv *priv = mgr->priv;
+	unsigned int cd_ratio;
+	int encrypt, compress;
+
+	encrypt = socfpga_a10_fpga_encrypted((u32 *)buf, count / 4);
+	if (encrypt < 0)
+		return -EINVAL;
+
+	compress = socfpga_a10_fpga_compressed((u32 *)buf, count / 4);
+	if (compress < 0)
+		return -EINVAL;
+
+	cd_ratio = socfpga_a10_fpga_get_cd_ratio(cfg_width, encrypt, compress);
+
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK,
+			   cd_ratio << A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT);
+
+	return 0;
+}
+
+static u32 socfpga_a10_fpga_read_stat(struct a10_fpga_priv *priv)
+{
+	u32 val;
+
+	regmap_read(priv->regmap, A10_FPGAMGR_IMGCFG_STAT_OFST, &val);
+
+	return val;
+}
+
+static int socfpga_a10_fpga_wait_for_pr_ready(struct a10_fpga_priv *priv)
+{
+	u32 reg, i;
+
+	for (i = 0; i < 10 ; i++) {
+		reg = socfpga_a10_fpga_read_stat(priv);
+
+		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)
+			return -EINVAL;
+
+		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int socfpga_a10_fpga_wait_for_pr_done(struct a10_fpga_priv *priv)
+{
+	u32 reg, i;
+
+	for (i = 0; i < 10 ; i++) {
+		reg = socfpga_a10_fpga_read_stat(priv);
+
+		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR)
+			return -EINVAL;
+
+		if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE)
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+/* Start the FPGA programming by initialize the FPGA Manager */
+static int socfpga_a10_fpga_write_init(struct fpga_manager *mgr,
+				       struct fpga_image_info *info,
+				       const char *buf, size_t count)
+{
+	struct a10_fpga_priv *priv = mgr->priv;
+	unsigned int cfg_width;
+	u32 msel, stat, mask;
+	int ret;
+
+	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG)
+		cfg_width = CFGWDTH_16;
+	else
+		return -EINVAL;
+
+	/* Check for passive parallel (msel == 000 or 001) */
+	msel = socfpga_a10_fpga_read_stat(priv);
+	msel &= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK;
+	msel >>= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT;
+	if ((msel != 0) && (msel != 1)) {
+		dev_dbg(&mgr->dev, "Fail: invalid msel=%d\n", msel);
+		return -EINVAL;
+	}
+
+	/* Make sure no external devices are interfering */
+	stat = socfpga_a10_fpga_read_stat(priv);
+	mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN |
+	       A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN;
+	if ((stat & mask) != mask)
+		return -EINVAL;
+
+	/* Set cfg width */
+	socfpga_a10_fpga_set_cfg_width(priv, cfg_width);
+
+	/* Determine cd ratio from bitstream header and set cd ratio */
+	ret = socfpga_a10_fpga_set_cdratio(mgr, cfg_width, buf, count);
+	if (ret)
+		return ret;
+
+	/*
+	 * Clear s2f_nce to enable chip select.  Leave pr_request
+	 * unasserted and override disabled.
+	 */
+	regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
+		     A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);
+
+	/* Set cfg_ctrl to enable s2f dclk and data */
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL,
+			   A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL);
+
+	/*
+	 * Disable overrides not needed for pr.
+	 * s2f_config==1 leaves reset deasseted.
+	 */
+	regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_00_OFST,
+		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG |
+		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS |
+		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE |
+		     A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG);
+
+	/* Enable override for data, dclk, nce, and pr_request to CSS */
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, 0);
+
+	/* Send some clocks to clear out any errors */
+	socfpga_a10_fpga_generate_dclks(priv, 256);
+
+	/* Assert pr_request */
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST);
+
+	/* Provide 2048 DCLKs before starting the config data streaming. */
+	socfpga_a10_fpga_generate_dclks(priv, 0x7ff);
+
+	/* Wait for pr_ready */
+	return socfpga_a10_fpga_wait_for_pr_ready(priv);
+}
+
+/*
+ * write data to the FPGA data register
+ */
+static int socfpga_a10_fpga_write(struct fpga_manager *mgr, const char *buf,
+				  size_t count)
+{
+	struct a10_fpga_priv *priv = mgr->priv;
+	u32 *buffer_32 = (u32 *)buf;
+	size_t i = 0;
+
+	if (count <= 0)
+		return -EINVAL;
+
+	/* Write out the complete 32-bit chunks */
+	while (count >= sizeof(u32)) {
+		writel(buffer_32[i++], priv->fpga_data_addr);
+		count -= sizeof(u32);
+	}
+
+	/* Write out remaining non 32-bit chunks */
+	switch (count) {
+	case 3:
+		writel(buffer_32[i++] & 0x00ffffff, priv->fpga_data_addr);
+		break;
+	case 2:
+		writel(buffer_32[i++] & 0x0000ffff, priv->fpga_data_addr);
+		break;
+	case 1:
+		writel(buffer_32[i++] & 0x000000ff, priv->fpga_data_addr);
+		break;
+	case 0:
+		break;
+	default:
+		/* This will never happen */
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int socfpga_a10_fpga_write_complete(struct fpga_manager *mgr,
+					   struct fpga_image_info *info)
+{
+	struct a10_fpga_priv *priv = mgr->priv;
+	u32 reg;
+	int ret;
+
+	/* Wait for pr_done */
+	ret = socfpga_a10_fpga_wait_for_pr_done(priv);
+
+	/* Clear pr_request */
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST, 0);
+
+	/* Send some clocks to clear out any errors */
+	socfpga_a10_fpga_generate_dclks(priv, 256);
+
+	/* Disable s2f dclk and data */
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, 0);
+
+	/* Deassert chip select */
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE);
+
+	/* Disable data, dclk, nce, and pr_request override to CSS */
+	regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG,
+			   A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG);
+
+	/* Return any errors regarding pr_done or pr_error */
+	if (ret)
+		return ret;
+
+	/* Final check */
+	reg = socfpga_a10_fpga_read_stat(priv);
+
+	if (((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE) == 0) ||
+	    ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) == 0) ||
+	    ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)) {
+		dev_dbg(&mgr->dev,
+			"Timeout in final check. Status=%08xf\n", reg);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static enum fpga_mgr_states socfpga_a10_fpga_state(struct fpga_manager *mgr)
+{
+	struct a10_fpga_priv *priv = mgr->priv;
+	u32 reg = socfpga_a10_fpga_read_stat(priv);
+
+	if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE)
+		return FPGA_MGR_STATE_OPERATING;
+
+	if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY)
+		return FPGA_MGR_STATE_WRITE;
+
+	if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR)
+		return FPGA_MGR_STATE_WRITE_COMPLETE_ERR;
+
+	if ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)
+		return FPGA_MGR_STATE_RESET;
+
+	return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = {
+	.initial_header_size = (RBF_DECOMPRESS_OFFSET + 1) * 4,
+	.state = socfpga_a10_fpga_state,
+	.write_init = socfpga_a10_fpga_write_init,
+	.write = socfpga_a10_fpga_write,
+	.write_complete = socfpga_a10_fpga_write_complete,
+};
+
+static int socfpga_a10_fpga_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct a10_fpga_priv *priv;
+	void __iomem *reg_base;
+	struct resource *res;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	/* First mmio base is for register access */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	reg_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(reg_base))
+		return PTR_ERR(reg_base);
+
+	/* Second mmio base is for writing FPGA image data */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	priv->fpga_data_addr = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->fpga_data_addr))
+		return PTR_ERR(priv->fpga_data_addr);
+
+	/* regmap for register access */
+	priv->regmap = devm_regmap_init_mmio(dev, reg_base,
+					     &socfpga_a10_fpga_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return -ENODEV;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "no clock specified\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "could not enable clock\n");
+		return -EBUSY;
+	}
+
+	return fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager",
+				 &socfpga_a10_fpga_mgr_ops, priv);
+}
+
+static int socfpga_a10_fpga_remove(struct platform_device *pdev)
+{
+	struct fpga_manager *mgr = platform_get_drvdata(pdev);
+	struct a10_fpga_priv *priv = mgr->priv;
+
+	fpga_mgr_unregister(&pdev->dev);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static const struct of_device_id socfpga_a10_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-a10-fpga-mgr", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match);
+
+static struct platform_driver socfpga_a10_fpga_driver = {
+	.probe = socfpga_a10_fpga_probe,
+	.remove = socfpga_a10_fpga_remove,
+	.driver = {
+		.name	= "socfpga_a10_fpga_manager",
+		.of_match_table = socfpga_a10_fpga_of_match,
+	},
+};
+
+module_platform_driver(socfpga_a10_fpga_driver);
+
+MODULE_AUTHOR("Alan Tull <atull@opensource.altera.com>");
+MODULE_DESCRIPTION("SoCFPGA Arria10 FPGA Manager");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/socfpga.c linux-libre-4.10-rc8-gnu/drivers/fpga/socfpga.c
--- linux-libre-4.9-gnu/drivers/fpga/socfpga.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/socfpga.c	2017-02-12 16:03:20.000000000 -0500
@@ -407,13 +407,14 @@ static int socfpga_fpga_reset(struct fpg
 /*
  * Prepare the FPGA to receive the configuration data.
  */
-static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr, u32 flags,
+static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr,
+					   struct fpga_image_info *info,
 					   const char *buf, size_t count)
 {
 	struct socfpga_fpga_priv *priv = mgr->priv;
 	int ret;
 
-	if (flags & FPGA_MGR_PARTIAL_RECONFIG) {
+	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
 		dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
 		return -EINVAL;
 	}
@@ -478,7 +479,7 @@ static int socfpga_fpga_ops_configure_wr
 }
 
 static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr,
-					       u32 flags)
+					       struct fpga_image_info *info)
 {
 	struct socfpga_fpga_priv *priv = mgr->priv;
 	u32 status;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/fpga/zynq-fpga.c linux-libre-4.10-rc8-gnu/drivers/fpga/zynq-fpga.c
--- linux-libre-4.9-gnu/drivers/fpga/zynq-fpga.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/fpga/zynq-fpga.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,7 +118,6 @@
 #define FPGA_RST_NONE_MASK		0x0
 
 struct zynq_fpga_priv {
-	struct device *dev;
 	int irq;
 	struct clk *clk;
 
@@ -175,7 +174,8 @@ static irqreturn_t zynq_fpga_isr(int irq
 	return IRQ_HANDLED;
 }
 
-static int zynq_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags,
+static int zynq_fpga_ops_write_init(struct fpga_manager *mgr,
+				    struct fpga_image_info *info,
 				    const char *buf, size_t count)
 {
 	struct zynq_fpga_priv *priv;
@@ -189,7 +189,7 @@ static int zynq_fpga_ops_write_init(stru
 		return err;
 
 	/* don't globally reset PL if we're doing partial reconfig */
-	if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+	if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
 		/* assert AXI interface resets */
 		regmap_write(priv->slcr, SLCR_FPGA_RST_CTRL_OFFSET,
 			     FPGA_RST_ALL_MASK);
@@ -217,7 +217,7 @@ static int zynq_fpga_ops_write_init(stru
 					     INIT_POLL_DELAY,
 					     INIT_POLL_TIMEOUT);
 		if (err) {
-			dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+			dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
 			goto out_err;
 		}
 
@@ -231,7 +231,7 @@ static int zynq_fpga_ops_write_init(stru
 					     INIT_POLL_DELAY,
 					     INIT_POLL_TIMEOUT);
 		if (err) {
-			dev_err(priv->dev, "Timeout waiting for !PCFG_INIT");
+			dev_err(&mgr->dev, "Timeout waiting for !PCFG_INIT\n");
 			goto out_err;
 		}
 
@@ -245,7 +245,7 @@ static int zynq_fpga_ops_write_init(stru
 					     INIT_POLL_DELAY,
 					     INIT_POLL_TIMEOUT);
 		if (err) {
-			dev_err(priv->dev, "Timeout waiting for PCFG_INIT");
+			dev_err(&mgr->dev, "Timeout waiting for PCFG_INIT\n");
 			goto out_err;
 		}
 	}
@@ -262,7 +262,7 @@ static int zynq_fpga_ops_write_init(stru
 	/* check that we have room in the command queue */
 	status = zynq_fpga_read(priv, STATUS_OFFSET);
 	if (status & STATUS_DMA_Q_F) {
-		dev_err(priv->dev, "DMA command queue full");
+		dev_err(&mgr->dev, "DMA command queue full\n");
 		err = -EBUSY;
 		goto out_err;
 	}
@@ -295,7 +295,8 @@ static int zynq_fpga_ops_write(struct fp
 	in_count = count;
 	priv = mgr->priv;
 
-	kbuf = dma_alloc_coherent(priv->dev, count, &dma_addr, GFP_KERNEL);
+	kbuf =
+	    dma_alloc_coherent(mgr->dev.parent, count, &dma_addr, GFP_KERNEL);
 	if (!kbuf)
 		return -ENOMEM;
 
@@ -331,19 +332,19 @@ static int zynq_fpga_ops_write(struct fp
 	zynq_fpga_write(priv, INT_STS_OFFSET, intr_status);
 
 	if (!((intr_status & IXR_D_P_DONE_MASK) == IXR_D_P_DONE_MASK)) {
-		dev_err(priv->dev, "Error configuring FPGA");
+		dev_err(&mgr->dev, "Error configuring FPGA\n");
 		err = -EFAULT;
 	}
 
 	clk_disable(priv->clk);
 
 out_free:
-	dma_free_coherent(priv->dev, in_count, kbuf, dma_addr);
-
+	dma_free_coherent(mgr->dev.parent, count, kbuf, dma_addr);
 	return err;
 }
 
-static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr, u32 flags)
+static int zynq_fpga_ops_write_complete(struct fpga_manager *mgr,
+					struct fpga_image_info *info)
 {
 	struct zynq_fpga_priv *priv = mgr->priv;
 	int err;
@@ -364,7 +365,7 @@ static int zynq_fpga_ops_write_complete(
 		return err;
 
 	/* for the partial reconfig case we didn't touch the level shifters */
-	if (!(flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+	if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
 		/* enable level shifters from PL to PS */
 		regmap_write(priv->slcr, SLCR_LVL_SHFTR_EN_OFFSET,
 			     LVL_SHFTR_ENABLE_PL_TO_PS);
@@ -416,8 +417,6 @@ static int zynq_fpga_probe(struct platfo
 	if (!priv)
 		return -ENOMEM;
 
-	priv->dev = dev;
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->io_base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(priv->io_base))
@@ -426,7 +425,7 @@ static int zynq_fpga_probe(struct platfo
 	priv->slcr = syscon_regmap_lookup_by_phandle(dev->of_node,
 		"syscon");
 	if (IS_ERR(priv->slcr)) {
-		dev_err(dev, "unable to get zynq-slcr regmap");
+		dev_err(dev, "unable to get zynq-slcr regmap\n");
 		return PTR_ERR(priv->slcr);
 	}
 
@@ -434,38 +433,41 @@ static int zynq_fpga_probe(struct platfo
 
 	priv->irq = platform_get_irq(pdev, 0);
 	if (priv->irq < 0) {
-		dev_err(dev, "No IRQ available");
+		dev_err(dev, "No IRQ available\n");
 		return priv->irq;
 	}
 
-	err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0,
-			       dev_name(dev), priv);
-	if (err) {
-		dev_err(dev, "unable to request IRQ");
-		return err;
-	}
-
 	priv->clk = devm_clk_get(dev, "ref_clk");
 	if (IS_ERR(priv->clk)) {
-		dev_err(dev, "input clock not found");
+		dev_err(dev, "input clock not found\n");
 		return PTR_ERR(priv->clk);
 	}
 
 	err = clk_prepare_enable(priv->clk);
 	if (err) {
-		dev_err(dev, "unable to enable clock");
+		dev_err(dev, "unable to enable clock\n");
 		return err;
 	}
 
 	/* unlock the device */
 	zynq_fpga_write(priv, UNLOCK_OFFSET, UNLOCK_MASK);
 
+	zynq_fpga_write(priv, INT_MASK_OFFSET, 0xFFFFFFFF);
+	zynq_fpga_write(priv, INT_STS_OFFSET, IXR_ALL_MASK);
+	err = devm_request_irq(dev, priv->irq, zynq_fpga_isr, 0, dev_name(dev),
+			       priv);
+	if (err) {
+		dev_err(dev, "unable to request IRQ\n");
+		clk_disable_unprepare(priv->clk);
+		return err;
+	}
+
 	clk_disable(priv->clk);
 
 	err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
 				&zynq_fpga_ops, priv);
 	if (err) {
-		dev_err(dev, "unable to register FPGA manager");
+		dev_err(dev, "unable to register FPGA manager\n");
 		clk_unprepare(priv->clk);
 		return err;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-adnp.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-adnp.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-adnp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-adnp.c	2017-02-12 16:03:20.000000000 -0500
@@ -468,17 +468,19 @@ static int adnp_irq_setup(struct adnp *a
 		return err;
 	}
 
-	err = gpiochip_irqchip_add(chip,
-				   &adnp_irq_chip,
-				   0,
-				   handle_simple_irq,
-				   IRQ_TYPE_NONE);
+	err = gpiochip_irqchip_add_nested(chip,
+					  &adnp_irq_chip,
+					  0,
+					  handle_simple_irq,
+					  IRQ_TYPE_NONE);
 	if (err) {
 		dev_err(chip->parent,
 			"could not connect irqchip to gpiochip\n");
 		return err;
 	}
 
+	gpiochip_set_nested_irqchip(chip, &adnp_irq_chip, adnp->client->irq);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-altera-a10sr.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-altera-a10sr.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-altera-a10sr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-altera-a10sr.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,130 @@
+/*
+ *  Copyright Intel Corporation (C) 2014-2016. All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * GPIO driver for  Altera Arria10 MAX5 System Resource Chip
+ *
+ * Adapted from gpio-tps65910.c
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/mfd/altera-a10sr.h>
+#include <linux/module.h>
+
+/**
+ * struct altr_a10sr_gpio - Altera Max5 GPIO device private data structure
+ * @gp:   : instance of the gpio_chip
+ * @regmap: the regmap from the parent device.
+ */
+struct altr_a10sr_gpio {
+	struct gpio_chip gp;
+	struct regmap *regmap;
+};
+
+static int altr_a10sr_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
+	int ret, val;
+
+	ret = regmap_read(gpio->regmap, ALTR_A10SR_PBDSW_REG, &val);
+	if (ret < 0)
+		return ret;
+
+	return !!(val & BIT(offset - ALTR_A10SR_LED_VALID_SHIFT));
+}
+
+static void altr_a10sr_gpio_set(struct gpio_chip *chip, unsigned int offset,
+				int value)
+{
+	struct altr_a10sr_gpio *gpio = gpiochip_get_data(chip);
+
+	regmap_update_bits(gpio->regmap, ALTR_A10SR_LED_REG,
+			   BIT(ALTR_A10SR_LED_VALID_SHIFT + offset),
+			   value ? BIT(ALTR_A10SR_LED_VALID_SHIFT + offset)
+			   : 0);
+}
+
+static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
+					   unsigned int nr)
+{
+	if (nr >= (ALTR_A10SR_IN_VALID_RANGE_LO - ALTR_A10SR_LED_VALID_SHIFT))
+		return 0;
+	return -EINVAL;
+}
+
+static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
+					    unsigned int nr, int value)
+{
+	if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
+		return 0;
+	return -EINVAL;
+}
+
+static struct gpio_chip altr_a10sr_gc = {
+	.label = "altr_a10sr_gpio",
+	.owner = THIS_MODULE,
+	.get = altr_a10sr_gpio_get,
+	.set = altr_a10sr_gpio_set,
+	.direction_input = altr_a10sr_gpio_direction_input,
+	.direction_output = altr_a10sr_gpio_direction_output,
+	.can_sleep = true,
+	.ngpio = 12,
+	.base = -1,
+};
+
+static int altr_a10sr_gpio_probe(struct platform_device *pdev)
+{
+	struct altr_a10sr_gpio *gpio;
+	int ret;
+	struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
+
+	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
+	if (!gpio)
+		return -ENOMEM;
+
+	gpio->regmap = a10sr->regmap;
+
+	gpio->gp = altr_a10sr_gc;
+
+	gpio->gp.of_node = pdev->dev.of_node;
+
+	ret = devm_gpiochip_add_data(&pdev->dev, &gpio->gp, gpio);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, gpio);
+
+	return 0;
+}
+
+static const struct of_device_id altr_a10sr_gpio_of_match[] = {
+	{ .compatible = "altr,a10sr-gpio" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, altr_a10sr_gpio_of_match);
+
+static struct platform_driver altr_a10sr_gpio_driver = {
+	.probe = altr_a10sr_gpio_probe,
+	.driver = {
+		.name	= "altr_a10sr_gpio",
+		.of_match_table = of_match_ptr(altr_a10sr_gpio_of_match),
+	},
+};
+module_platform_driver(altr_a10sr_gpio_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>");
+MODULE_DESCRIPTION("Altera Arria10 System Resource Chip GPIO");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-arizona.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-arizona.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-arizona.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-arizona.c	2017-02-12 16:03:20.000000000 -0500
@@ -137,15 +137,10 @@ static int arizona_gpio_probe(struct pla
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
 			ret);
-		goto err;
+		return ret;
 	}
 
-	platform_set_drvdata(pdev, arizona_gpio);
-
-	return ret;
-
-err:
-	return ret;
+	return 0;
 }
 
 static struct platform_driver arizona_gpio_driver = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-axp209.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-axp209.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-axp209.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-axp209.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,13 +64,9 @@ static int axp20x_gpio_get(struct gpio_c
 {
 	struct axp20x_gpio *gpio = gpiochip_get_data(chip);
 	unsigned int val;
-	int reg, ret;
-
-	reg = axp20x_gpio_get_reg(offset);
-	if (reg < 0)
-		return reg;
+	int ret;
 
-	ret = regmap_read(gpio->regmap, reg, &val);
+	ret = regmap_read(gpio->regmap, AXP20X_GPIO20_SS, &val);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-crystalcove.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-crystalcove.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-crystalcove.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-crystalcove.c	2017-02-12 16:03:20.000000000 -0500
@@ -351,8 +351,8 @@ static int crystalcove_gpio_probe(struct
 		return retval;
 	}
 
-	gpiochip_irqchip_add(&cg->chip, &crystalcove_irqchip, 0,
-			     handle_simple_irq, IRQ_TYPE_NONE);
+	gpiochip_irqchip_add_nested(&cg->chip, &crystalcove_irqchip, 0,
+				    handle_simple_irq, IRQ_TYPE_NONE);
 
 	retval = request_threaded_irq(irq, NULL, crystalcove_gpio_irq_handler,
 				      IRQF_ONESHOT, KBUILD_MODNAME, cg);
@@ -362,6 +362,8 @@ static int crystalcove_gpio_probe(struct
 		return retval;
 	}
 
+	gpiochip_set_nested_irqchip(&cg->chip, &crystalcove_irqchip, irq);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-davinci.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-davinci.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-davinci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-davinci.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,6 +40,7 @@ struct davinci_gpio_regs {
 typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq);
 
 #define BINTEN	0x8 /* GPIO Interrupt Per-Bank Enable Register */
+#define MAX_LABEL_SIZE 20
 
 static void __iomem *gpio_base;
 
@@ -201,6 +202,7 @@ static int davinci_gpio_probe(struct pla
 	struct davinci_gpio_regs __iomem *regs;
 	struct device *dev = &pdev->dev;
 	struct resource *res;
+	char label[MAX_LABEL_SIZE];
 
 	pdata = davinci_gpio_get_pdata(pdev);
 	if (!pdata) {
@@ -237,7 +239,10 @@ static int davinci_gpio_probe(struct pla
 		return PTR_ERR(gpio_base);
 
 	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
-		chips[i].chip.label = "DaVinci";
+		snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", i);
+		chips[i].chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
+		if (!chips[i].chip.label)
+			return -ENOMEM;
 
 		chips[i].chip.direction_input = davinci_direction_in;
 		chips[i].chip.get = davinci_gpio_get;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-dln2.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-dln2.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-dln2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-dln2.c	2017-02-12 16:03:20.000000000 -0500
@@ -467,7 +467,6 @@ static int dln2_gpio_probe(struct platfo
 	dln2->gpio.base = -1;
 	dln2->gpio.ngpio = pins;
 	dln2->gpio.can_sleep = true;
-	dln2->gpio.irq_not_threaded = true;
 	dln2->gpio.set = dln2_gpio_set;
 	dln2->gpio.get = dln2_gpio_get;
 	dln2->gpio.request = dln2_gpio_request;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-etraxfs.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-etraxfs.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-etraxfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-etraxfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -471,9 +471,4 @@ static struct platform_driver etraxfs_gp
 	.probe	= etraxfs_gpio_probe,
 };
 
-static int __init etraxfs_gpio_init(void)
-{
-	return platform_driver_register(&etraxfs_gpio_driver);
-}
-
-device_initcall(etraxfs_gpio_init);
+builtin_platform_driver(etraxfs_gpio_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-htc-egpio.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-htc-egpio.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-htc-egpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-htc-egpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/platform_data/gpio-htc-egpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/init.h>
 
 struct egpio_chip {
 	int              reg_start;
@@ -160,10 +160,14 @@ static int egpio_get(struct gpio_chip *c
 	bit   = egpio_bit(ei, offset);
 	reg   = egpio->reg_start + egpio_pos(ei, offset);
 
-	value = egpio_readw(ei, reg);
-	pr_debug("readw(%p + %x) = %x\n",
-			ei->base_addr, reg << ei->bus_shift, value);
-	return !!(value & bit);
+	if (test_bit(offset, &egpio->is_out)) {
+		return !!(egpio->cached_values & (1 << offset));
+	} else {
+		value = egpio_readw(ei, reg);
+		pr_debug("readw(%p + %x) = %x\n",
+			 ei->base_addr, reg << ei->bus_shift, value);
+		return !!(value & bit);
+	}
 }
 
 static int egpio_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -225,6 +229,15 @@ static int egpio_direction_output(struct
 	}
 }
 
+static int egpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+	struct egpio_chip *egpio;
+
+	egpio = gpiochip_get_data(chip);
+
+	return !test_bit(offset, &egpio->is_out);
+}
+
 static void egpio_write_cache(struct egpio_info *ei)
 {
 	int               i;
@@ -327,6 +340,7 @@ static int __init egpio_probe(struct pla
 		chip->set             = egpio_set;
 		chip->direction_input = egpio_direction_input;
 		chip->direction_output = egpio_direction_output;
+		chip->get_direction   = egpio_get_direction;
 		chip->base            = pdata->chip[i].gpio_base;
 		chip->ngpio           = pdata->chip[i].num_gpios;
 
@@ -367,24 +381,6 @@ fail:
 	return ret;
 }
 
-static int __exit egpio_remove(struct platform_device *pdev)
-{
-	struct egpio_info *ei = platform_get_drvdata(pdev);
-	unsigned int      irq, irq_end;
-
-	if (ei->chained_irq) {
-		irq_end = ei->irq_start + ei->nirqs;
-		for (irq = ei->irq_start; irq < irq_end; irq++) {
-			irq_set_chip_and_handler(irq, NULL, NULL);
-			irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
-		}
-		irq_set_chained_handler(ei->chained_irq, NULL);
-		device_init_wakeup(&pdev->dev, 0);
-	}
-
-	return 0;
-}
-
 #ifdef CONFIG_PM
 static int egpio_suspend(struct platform_device *pdev, pm_message_t state)
 {
@@ -416,8 +412,8 @@ static int egpio_resume(struct platform_
 static struct platform_driver egpio_driver = {
 	.driver = {
 		.name = "htc-egpio",
+		.suppress_bind_attrs = true,
 	},
-	.remove       = __exit_p(egpio_remove),
 	.suspend      = egpio_suspend,
 	.resume       = egpio_resume,
 };
@@ -426,15 +422,5 @@ static int __init egpio_init(void)
 {
 	return platform_driver_probe(&egpio_driver, egpio_probe);
 }
-
-static void __exit egpio_exit(void)
-{
-	platform_driver_unregister(&egpio_driver);
-}
-
 /* start early for dependencies */
 subsys_initcall(egpio_init);
-module_exit(egpio_exit)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kevin O'Connor <kevin@koconnor.net>");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-intel-mid.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-intel-mid.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-intel-mid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-intel-mid.c	2017-02-12 16:03:20.000000000 -0500
@@ -421,9 +421,4 @@ static struct pci_driver intel_gpio_driv
 	},
 };
 
-static int __init intel_gpio_init(void)
-{
-	return pci_register_driver(&intel_gpio_driver);
-}
-
-device_initcall(intel_gpio_init);
+builtin_pci_driver(intel_gpio_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpiolib-acpi.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib-acpi.c
--- linux-libre-4.9-gnu/drivers/gpio/gpiolib-acpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib-acpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -468,7 +468,8 @@ static int acpi_gpio_property_lookup(str
 	int ret;
 
 	memset(&args, 0, sizeof(args));
-	ret = acpi_node_get_property_reference(fwnode, propname, index, &args);
+	ret = __acpi_node_get_property_reference(fwnode, propname, index, 3,
+						 &args);
 	if (ret) {
 		struct acpi_device *adev = to_acpi_device_node(fwnode);
 
@@ -483,13 +484,13 @@ static int acpi_gpio_property_lookup(str
 	 * on returned args.
 	 */
 	lookup->adev = args.adev;
-	if (args.nargs >= 2) {
-		lookup->index = args.args[0];
-		lookup->pin_index = args.args[1];
-		/* 3rd argument, if present is used to specify active_low. */
-		if (args.nargs >= 3)
-			lookup->active_low = !!args.args[2];
-	}
+	if (args.nargs != 3)
+		return -EPROTO;
+
+	lookup->index = args.args[0];
+	lookup->pin_index = args.args[1];
+	lookup->active_low = !!args.args[2];
+
 	return 0;
 }
 
@@ -859,6 +860,77 @@ static void acpi_gpiochip_free_regions(s
 	}
 }
 
+static struct gpio_desc *acpi_gpiochip_parse_own_gpio(
+	struct acpi_gpio_chip *achip, struct fwnode_handle *fwnode,
+	const char **name, unsigned int *lflags, unsigned int *dflags)
+{
+	struct gpio_chip *chip = achip->chip;
+	struct gpio_desc *desc;
+	u32 gpios[2];
+	int ret;
+
+	*lflags = 0;
+	*dflags = 0;
+	*name = NULL;
+
+	ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios,
+					     ARRAY_SIZE(gpios));
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	ret = acpi_gpiochip_pin_to_gpio_offset(chip->gpiodev, gpios[0]);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	desc = gpiochip_get_desc(chip, ret);
+	if (IS_ERR(desc))
+		return desc;
+
+	if (gpios[1])
+		*lflags |= GPIO_ACTIVE_LOW;
+
+	if (fwnode_property_present(fwnode, "input"))
+		*dflags |= GPIOD_IN;
+	else if (fwnode_property_present(fwnode, "output-low"))
+		*dflags |= GPIOD_OUT_LOW;
+	else if (fwnode_property_present(fwnode, "output-high"))
+		*dflags |= GPIOD_OUT_HIGH;
+	else
+		return ERR_PTR(-EINVAL);
+
+	fwnode_property_read_string(fwnode, "line-name", name);
+
+	return desc;
+}
+
+static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
+{
+	struct gpio_chip *chip = achip->chip;
+	struct fwnode_handle *fwnode;
+
+	device_for_each_child_node(chip->parent, fwnode) {
+		unsigned int lflags, dflags;
+		struct gpio_desc *desc;
+		const char *name;
+		int ret;
+
+		if (!fwnode_property_present(fwnode, "gpio-hog"))
+			continue;
+
+		desc = acpi_gpiochip_parse_own_gpio(achip, fwnode, &name,
+						    &lflags, &dflags);
+		if (IS_ERR(desc))
+			continue;
+
+		ret = gpiod_hog(desc, name, lflags, dflags);
+		if (ret) {
+			dev_err(chip->parent, "Failed to hog GPIO\n");
+			fwnode_handle_put(fwnode);
+			return;
+		}
+	}
+}
+
 void acpi_gpiochip_add(struct gpio_chip *chip)
 {
 	struct acpi_gpio_chip *acpi_gpio;
@@ -889,7 +961,11 @@ void acpi_gpiochip_add(struct gpio_chip
 		return;
 	}
 
+	if (!chip->names)
+		devprop_gpiochip_set_names(chip);
+
 	acpi_gpiochip_request_regions(acpi_gpio);
+	acpi_gpiochip_scan_gpios(acpi_gpio);
 	acpi_walk_dep_device_list(handle);
 }
 
@@ -918,18 +994,27 @@ void acpi_gpiochip_remove(struct gpio_ch
 	kfree(acpi_gpio);
 }
 
-static unsigned int acpi_gpio_package_count(const union acpi_object *obj)
+static int acpi_gpio_package_count(const union acpi_object *obj)
 {
 	const union acpi_object *element = obj->package.elements;
 	const union acpi_object *end = element + obj->package.count;
 	unsigned int count = 0;
 
 	while (element < end) {
-		if (element->type == ACPI_TYPE_LOCAL_REFERENCE)
+		switch (element->type) {
+		case ACPI_TYPE_LOCAL_REFERENCE:
+			element += 3;
+			/* Fallthrough */
+		case ACPI_TYPE_INTEGER:
+			element++;
 			count++;
+			break;
 
-		element++;
+		default:
+			return -EPROTO;
+		}
 	}
+
 	return count;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpiolib.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib.c
--- linux-libre-4.9-gnu/drivers/gpio/gpiolib.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib.c	2017-02-12 16:03:20.000000000 -0500
@@ -986,7 +986,8 @@ static int gpio_chrdev_open(struct inode
 		return -ENODEV;
 	get_device(&gdev->dev);
 	filp->private_data = gdev;
-	return 0;
+
+	return nonseekable_open(inode, filp);
 }
 
 /**
@@ -1011,7 +1012,7 @@ static const struct file_operations gpio
 	.release = gpio_chrdev_release,
 	.open = gpio_chrdev_open,
 	.owner = THIS_MODULE,
-	.llseek = noop_llseek,
+	.llseek = no_llseek,
 	.unlocked_ioctl = gpio_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl = gpio_ioctl_compat,
@@ -1316,12 +1317,12 @@ void gpiochip_remove(struct gpio_chip *c
 
 	/* FIXME: should the legacy sysfs handling be moved to gpio_device? */
 	gpiochip_sysfs_unregister(gdev);
+	gpiochip_free_hogs(chip);
 	/* Numb the device, cancelling all outstanding operations */
 	gdev->chip = NULL;
 	gpiochip_irqchip_remove(chip);
 	acpi_gpiochip_remove(chip);
 	gpiochip_remove_pin_ranges(chip);
-	gpiochip_free_hogs(chip);
 	of_gpiochip_remove(chip);
 	/*
 	 * We accept no more calls into the driver from this point, so
@@ -1512,7 +1513,7 @@ static bool gpiochip_irqchip_irq_valid(c
 }
 
 /**
- * gpiochip_set_chained_irqchip() - sets a chained irqchip to a gpiochip
+ * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip
  * @gpiochip: the gpiochip to set the irqchip chain to
  * @irqchip: the irqchip to chain to the gpiochip
  * @parent_irq: the irq number corresponding to the parent IRQ for this
@@ -1521,10 +1522,10 @@ static bool gpiochip_irqchip_irq_valid(c
  * coming out of the gpiochip. If the interrupt is nested rather than
  * cascaded, pass NULL in this handler argument
  */
-void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
-				  struct irq_chip *irqchip,
-				  int parent_irq,
-				  irq_flow_handler_t parent_handler)
+static void gpiochip_set_cascaded_irqchip(struct gpio_chip *gpiochip,
+					  struct irq_chip *irqchip,
+					  int parent_irq,
+					  irq_flow_handler_t parent_handler)
 {
 	unsigned int offset;
 
@@ -1548,7 +1549,7 @@ void gpiochip_set_chained_irqchip(struct
 		irq_set_chained_handler_and_data(parent_irq, parent_handler,
 						 gpiochip);
 
-		gpiochip->irq_parent = parent_irq;
+		gpiochip->irq_chained_parent = parent_irq;
 	}
 
 	/* Set the parent IRQ for all affected IRQs */
@@ -1559,9 +1560,48 @@ void gpiochip_set_chained_irqchip(struct
 			       parent_irq);
 	}
 }
+
+/**
+ * gpiochip_set_chained_irqchip() - connects a chained irqchip to a gpiochip
+ * @gpiochip: the gpiochip to set the irqchip chain to
+ * @irqchip: the irqchip to chain to the gpiochip
+ * @parent_irq: the irq number corresponding to the parent IRQ for this
+ * chained irqchip
+ * @parent_handler: the parent interrupt handler for the accumulated IRQ
+ * coming out of the gpiochip. If the interrupt is nested rather than
+ * cascaded, pass NULL in this handler argument
+ */
+void gpiochip_set_chained_irqchip(struct gpio_chip *gpiochip,
+				  struct irq_chip *irqchip,
+				  int parent_irq,
+				  irq_flow_handler_t parent_handler)
+{
+	gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
+				      parent_handler);
+}
 EXPORT_SYMBOL_GPL(gpiochip_set_chained_irqchip);
 
 /**
+ * gpiochip_set_nested_irqchip() - connects a nested irqchip to a gpiochip
+ * @gpiochip: the gpiochip to set the irqchip nested handler to
+ * @irqchip: the irqchip to nest to the gpiochip
+ * @parent_irq: the irq number corresponding to the parent IRQ for this
+ * nested irqchip
+ */
+void gpiochip_set_nested_irqchip(struct gpio_chip *gpiochip,
+				 struct irq_chip *irqchip,
+				 int parent_irq)
+{
+	if (!gpiochip->irq_nested) {
+		chip_err(gpiochip, "tried to nest a chained gpiochip\n");
+		return;
+	}
+	gpiochip_set_cascaded_irqchip(gpiochip, irqchip, parent_irq,
+				      NULL);
+}
+EXPORT_SYMBOL_GPL(gpiochip_set_nested_irqchip);
+
+/**
  * gpiochip_irq_map() - maps an IRQ into a GPIO irqchip
  * @d: the irqdomain used by this irqchip
  * @irq: the global irq number used by this GPIO irqchip irq
@@ -1583,8 +1623,8 @@ static int gpiochip_irq_map(struct irq_d
 	 */
 	irq_set_lockdep_class(irq, chip->lock_key);
 	irq_set_chip_and_handler(irq, chip->irqchip, chip->irq_handler);
-	/* Chips that can sleep need nested thread handlers */
-	if (chip->can_sleep && !chip->irq_not_threaded)
+	/* Chips that use nested thread handlers have them marked */
+	if (chip->irq_nested)
 		irq_set_nested_thread(irq, 1);
 	irq_set_noprobe(irq);
 
@@ -1602,7 +1642,7 @@ static void gpiochip_irq_unmap(struct ir
 {
 	struct gpio_chip *chip = d->host_data;
 
-	if (chip->can_sleep)
+	if (chip->irq_nested)
 		irq_set_nested_thread(irq, 0);
 	irq_set_chip_and_handler(irq, NULL, NULL);
 	irq_set_chip_data(irq, NULL);
@@ -1657,9 +1697,9 @@ static void gpiochip_irqchip_remove(stru
 
 	acpi_gpiochip_free_interrupts(gpiochip);
 
-	if (gpiochip->irq_parent) {
-		irq_set_chained_handler(gpiochip->irq_parent, NULL);
-		irq_set_handler_data(gpiochip->irq_parent, NULL);
+	if (gpiochip->irq_chained_parent) {
+		irq_set_chained_handler(gpiochip->irq_chained_parent, NULL);
+		irq_set_handler_data(gpiochip->irq_chained_parent, NULL);
 	}
 
 	/* Remove all IRQ mappings and delete the domain */
@@ -1683,7 +1723,7 @@ static void gpiochip_irqchip_remove(stru
 }
 
 /**
- * gpiochip_irqchip_add() - adds an irqchip to a gpiochip
+ * gpiochip_irqchip_add_key() - adds an irqchip to a gpiochip
  * @gpiochip: the gpiochip to add the irqchip to
  * @irqchip: the irqchip to add to the gpiochip
  * @first_irq: if not dynamically assigned, the base (first) IRQ to
@@ -1691,6 +1731,8 @@ static void gpiochip_irqchip_remove(stru
  * @handler: the irq handler to use (often a predefined irq core function)
  * @type: the default type for IRQs on this irqchip, pass IRQ_TYPE_NONE
  * to have the core avoid setting up any default type in the hardware.
+ * @nested: whether this is a nested irqchip calling handle_nested_irq()
+ * in its IRQ handler
  * @lock_key: lockdep class
  *
  * This function closely associates a certain irqchip with a certain
@@ -1707,12 +1749,13 @@ static void gpiochip_irqchip_remove(stru
  * the pins on the gpiochip can generate a unique IRQ. Everything else
  * need to be open coded.
  */
-int _gpiochip_irqchip_add(struct gpio_chip *gpiochip,
-			  struct irq_chip *irqchip,
-			  unsigned int first_irq,
-			  irq_flow_handler_t handler,
-			  unsigned int type,
-			  struct lock_class_key *lock_key)
+int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
+			     struct irq_chip *irqchip,
+			     unsigned int first_irq,
+			     irq_flow_handler_t handler,
+			     unsigned int type,
+			     bool nested,
+			     struct lock_class_key *lock_key)
 {
 	struct device_node *of_node;
 	bool irq_base_set = false;
@@ -1726,6 +1769,7 @@ int _gpiochip_irqchip_add(struct gpio_ch
 		pr_err("missing gpiochip .dev parent pointer\n");
 		return -EINVAL;
 	}
+	gpiochip->irq_nested = nested;
 	of_node = gpiochip->parent->of_node;
 #ifdef CONFIG_OF_GPIO
 	/*
@@ -1796,7 +1840,7 @@ int _gpiochip_irqchip_add(struct gpio_ch
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(_gpiochip_irqchip_add);
+EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_key);
 
 #else /* CONFIG_GPIOLIB_IRQCHIP */
 
@@ -2223,6 +2267,7 @@ EXPORT_SYMBOL_GPL(gpiod_direction_input)
 static int _gpiod_direction_output_raw(struct gpio_desc *desc, int value)
 {
 	struct gpio_chip *gc = desc->gdev->chip;
+	int val = !!value;
 	int ret;
 
 	/* GPIOs used for IRQs shall not be set as output */
@@ -2242,7 +2287,7 @@ static int _gpiod_direction_output_raw(s
 				goto set_output_value;
 		}
 		/* Emulate open drain by not actively driving the line high */
-		if (value)
+		if (val)
 			return gpiod_direction_input(desc);
 	}
 	else if (test_bit(FLAG_OPEN_SOURCE, &desc->flags)) {
@@ -2253,7 +2298,7 @@ static int _gpiod_direction_output_raw(s
 				goto set_output_value;
 		}
 		/* Emulate open source by not actively driving the line low */
-		if (!value)
+		if (!val)
 			return gpiod_direction_input(desc);
 	} else {
 		/* Make sure to disable open drain/source hardware, if any */
@@ -2271,10 +2316,10 @@ set_output_value:
 		return -EIO;
 	}
 
-	ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), value);
+	ret = gc->direction_output(gc, gpio_chip_hwgpio(desc), val);
 	if (!ret)
 		set_bit(FLAG_IS_OUT, &desc->flags);
-	trace_gpio_value(desc_to_gpio(desc), 0, value);
+	trace_gpio_value(desc_to_gpio(desc), 0, val);
 	trace_gpio_direction(desc_to_gpio(desc), 0, ret);
 	return ret;
 }
@@ -2314,6 +2359,8 @@ int gpiod_direction_output(struct gpio_d
 	VALIDATE_DESC(desc);
 	if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
 		value = !value;
+	else
+		value = !!value;
 	return _gpiod_direction_output_raw(desc, value);
 }
 EXPORT_SYMBOL_GPL(gpiod_direction_output);
@@ -2758,6 +2805,15 @@ int gpiochip_lock_as_irq(struct gpio_chi
 	}
 
 	set_bit(FLAG_USED_AS_IRQ, &desc->flags);
+
+	/*
+	 * If the consumer has not set up a label (such as when the
+	 * IRQ is referenced from .to_irq()) we set up a label here
+	 * so it is clear this is used as an interrupt.
+	 */
+	if (!desc->label)
+		desc_set_label(desc, "interrupt");
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
@@ -2772,10 +2828,17 @@ EXPORT_SYMBOL_GPL(gpiochip_lock_as_irq);
  */
 void gpiochip_unlock_as_irq(struct gpio_chip *chip, unsigned int offset)
 {
-	if (offset >= chip->ngpio)
+	struct gpio_desc *desc;
+
+	desc = gpiochip_get_desc(chip, offset);
+	if (IS_ERR(desc))
 		return;
 
-	clear_bit(FLAG_USED_AS_IRQ, &chip->gpiodev->descs[offset].flags);
+	clear_bit(FLAG_USED_AS_IRQ, &desc->flags);
+
+	/* If we only had this marking, erase it */
+	if (desc->label && !strcmp(desc->label, "interrupt"))
+		desc_set_label(desc, NULL);
 }
 EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
 
@@ -3170,7 +3233,7 @@ static int gpiod_configure_flags(struct
 	/* Process flags */
 	if (dflags & GPIOD_FLAGS_BIT_DIR_OUT)
 		status = gpiod_direction_output(desc,
-					      dflags & GPIOD_FLAGS_BIT_DIR_VAL);
+				!!(dflags & GPIOD_FLAGS_BIT_DIR_VAL));
 	else
 		status = gpiod_direction_input(desc);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpiolib-devprop.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib-devprop.c
--- linux-libre-4.9-gnu/drivers/gpio/gpiolib-devprop.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib-devprop.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,67 @@
+/*
+ * Device property helpers for GPIO chips.
+ *
+ * Copyright (C) 2016, 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/property.h>
+#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+
+#include "gpiolib.h"
+
+/**
+ * devprop_gpiochip_set_names - Set GPIO line names using device properties
+ * @chip: GPIO chip whose lines should be named, if possible
+ *
+ * Looks for device property "gpio-line-names" and if it exists assigns
+ * GPIO line names for the chip. The memory allocated for the assigned
+ * names belong to the underlying firmware node and should not be released
+ * by the caller.
+ */
+void devprop_gpiochip_set_names(struct gpio_chip *chip)
+{
+	struct gpio_device *gdev = chip->gpiodev;
+	const char **names;
+	int ret, i;
+
+	if (!chip->parent) {
+		dev_warn(&gdev->dev, "GPIO chip parent is NULL\n");
+		return;
+	}
+
+	ret = device_property_read_string_array(chip->parent, "gpio-line-names",
+						NULL, 0);
+	if (ret < 0)
+		return;
+
+	if (ret != gdev->ngpio) {
+		dev_warn(chip->parent,
+			 "names %d do not match number of GPIOs %d\n", ret,
+			 gdev->ngpio);
+		return;
+	}
+
+	names = kcalloc(gdev->ngpio, sizeof(*names), GFP_KERNEL);
+	if (!names)
+		return;
+
+	ret = device_property_read_string_array(chip->parent, "gpio-line-names",
+						names, gdev->ngpio);
+	if (ret < 0) {
+		dev_warn(chip->parent, "failed to read GPIO line names\n");
+		kfree(names);
+		return;
+	}
+
+	for (i = 0; i < gdev->ngpio; i++)
+		gdev->descs[i].name = names[i];
+
+	kfree(names);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpiolib.h linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib.h
--- linux-libre-4.9-gnu/drivers/gpio/gpiolib.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib.h	2017-02-12 16:03:20.000000000 -0500
@@ -209,6 +209,8 @@ static int __maybe_unused gpio_chip_hwgp
 	return desc - &desc->gdev->descs[0];
 }
 
+void devprop_gpiochip_set_names(struct gpio_chip *chip);
+
 /* With descriptor prefix */
 
 #define gpiod_emerg(desc, fmt, ...)					       \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpiolib-of.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib-of.c
--- linux-libre-4.9-gnu/drivers/gpio/gpiolib-of.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpiolib-of.c	2017-02-12 16:03:20.000000000 -0500
@@ -226,51 +226,6 @@ static struct gpio_desc *of_parse_own_gp
 }
 
 /**
- * of_gpiochip_set_names() - set up the names of the lines
- * @chip: GPIO chip whose lines should be named, if possible
- */
-static void of_gpiochip_set_names(struct gpio_chip *gc)
-{
-	struct gpio_device *gdev = gc->gpiodev;
-	struct device_node *np = gc->of_node;
-	int i;
-	int nstrings;
-
-	nstrings = of_property_count_strings(np, "gpio-line-names");
-	if (nstrings <= 0)
-		/* Lines names not present */
-		return;
-
-	/* This is normally not what you want */
-	if (gdev->ngpio != nstrings)
-		dev_info(&gdev->dev, "gpio-line-names specifies %d line "
-			 "names but there are %d lines on the chip\n",
-			 nstrings, gdev->ngpio);
-
-	/*
-	 * Make sure to not index beyond the end of the number of descriptors
-	 * of the GPIO device.
-	 */
-	for (i = 0; i < gdev->ngpio; i++) {
-		const char *name;
-		int ret;
-
-		ret = of_property_read_string_index(np,
-						    "gpio-line-names",
-						    i,
-						    &name);
-		if (ret) {
-			if (ret != -ENODATA)
-                                dev_err(&gdev->dev,
-                                        "unable to name line %d: %d\n",
-                                        i, ret);
-			break;
-		}
-		gdev->descs[i].name = name;
-	}
-}
-
-/**
  * of_gpiochip_scan_gpios - Scan gpio-controller for gpio definitions
  * @chip:	gpio chip to act on
  *
@@ -296,8 +251,10 @@ static int of_gpiochip_scan_gpios(struct
 			continue;
 
 		ret = gpiod_hog(desc, name, lflags, dflags);
-		if (ret < 0)
+		if (ret < 0) {
+			of_node_put(np);
 			return ret;
+		}
 	}
 
 	return 0;
@@ -526,7 +483,7 @@ int of_gpiochip_add(struct gpio_chip *ch
 
 	/* If the chip defines names itself, these take precedence */
 	if (!chip->names)
-		of_gpiochip_set_names(chip);
+		devprop_gpiochip_set_names(chip);
 
 	of_node_get(chip->of_node);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-max732x.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-max732x.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-max732x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-max732x.c	2017-02-12 16:03:20.000000000 -0500
@@ -520,20 +520,19 @@ static int max732x_irq_setup(struct max7
 				client->irq);
 			return ret;
 		}
-		ret =  gpiochip_irqchip_add(&chip->gpio_chip,
-					    &max732x_irq_chip,
-					    irq_base,
-					    handle_simple_irq,
-					    IRQ_TYPE_NONE);
+		ret =  gpiochip_irqchip_add_nested(&chip->gpio_chip,
+						   &max732x_irq_chip,
+						   irq_base,
+						   handle_simple_irq,
+						   IRQ_TYPE_NONE);
 		if (ret) {
 			dev_err(&client->dev,
 				"could not connect irqchip to gpiochip\n");
 			return ret;
 		}
-		gpiochip_set_chained_irqchip(&chip->gpio_chip,
-					     &max732x_irq_chip,
-					     client->irq,
-					     NULL);
+		gpiochip_set_nested_irqchip(&chip->gpio_chip,
+					    &max732x_irq_chip,
+					    client->irq);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-max77620.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-max77620.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-max77620.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-max77620.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,9 +21,6 @@ struct max77620_gpio {
 	struct gpio_chip	gpio_chip;
 	struct regmap		*rmap;
 	struct device		*dev;
-	int			gpio_irq;
-	int			irq_base;
-	int			gpio_base;
 };
 
 static const struct regmap_irq max77620_gpio_irqs[] = {
@@ -254,7 +251,6 @@ static int max77620_gpio_probe(struct pl
 
 	mgpio->rmap = chip->rmap;
 	mgpio->dev = &pdev->dev;
-	mgpio->gpio_irq = gpio_irq;
 
 	mgpio->gpio_chip.label = pdev->name;
 	mgpio->gpio_chip.parent = &pdev->dev;
@@ -268,7 +264,6 @@ static int max77620_gpio_probe(struct pl
 	mgpio->gpio_chip.ngpio = MAX77620_GPIO_NR;
 	mgpio->gpio_chip.can_sleep = 1;
 	mgpio->gpio_chip.base = -1;
-	mgpio->irq_base = -1;
 #ifdef CONFIG_OF_GPIO
 	mgpio->gpio_chip.of_node = pdev->dev.parent->of_node;
 #endif
@@ -281,9 +276,8 @@ static int max77620_gpio_probe(struct pl
 		return ret;
 	}
 
-	mgpio->gpio_base = mgpio->gpio_chip.base;
-	ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, mgpio->gpio_irq,
-				       IRQF_ONESHOT, mgpio->irq_base,
+	ret = devm_regmap_add_irq_chip(&pdev->dev, chip->rmap, gpio_irq,
+				       IRQF_ONESHOT, -1,
 				       &max77620_gpio_irq_chip,
 				       &chip->gpio_irq_data);
 	if (ret < 0) {
@@ -296,6 +290,7 @@ static int max77620_gpio_probe(struct pl
 
 static const struct platform_device_id max77620_gpio_devtype[] = {
 	{ .name = "max77620-gpio", },
+	{ .name = "max20024-gpio", },
 	{},
 };
 MODULE_DEVICE_TABLE(platform, max77620_gpio_devtype);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-mb86s7x.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-mb86s7x.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-mb86s7x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-mb86s7x.c	2017-02-12 16:03:20.000000000 -0500
@@ -217,8 +217,4 @@ static struct platform_driver mb86s70_gp
 	.remove = mb86s70_gpio_remove,
 };
 
-static int __init mb86s70_gpio_init(void)
-{
-	return platform_driver_register(&mb86s70_gpio_driver);
-}
-device_initcall(mb86s70_gpio_init);
+builtin_platform_driver(mb86s70_gpio_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-mcp23s08.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-mcp23s08.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-mcp23s08.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-mcp23s08.c	2017-02-12 16:03:20.000000000 -0500
@@ -473,21 +473,20 @@ static int mcp23s08_irq_setup(struct mcp
 		return err;
 	}
 
-	err =  gpiochip_irqchip_add(chip,
-				    &mcp23s08_irq_chip,
-				    0,
-				    handle_simple_irq,
-				    IRQ_TYPE_NONE);
+	err =  gpiochip_irqchip_add_nested(chip,
+					   &mcp23s08_irq_chip,
+					   0,
+					   handle_simple_irq,
+					   IRQ_TYPE_NONE);
 	if (err) {
 		dev_err(chip->parent,
 			"could not connect irqchip to gpiochip: %d\n", err);
 		return err;
 	}
 
-	gpiochip_set_chained_irqchip(chip,
-				     &mcp23s08_irq_chip,
-				     mcp->irq,
-				     NULL);
+	gpiochip_set_nested_irqchip(chip,
+				    &mcp23s08_irq_chip,
+				    mcp->irq);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-merrifield.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-merrifield.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-merrifield.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-merrifield.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@
 
 #include <linux/bitops.h>
 #include <linux/gpio/driver.h>
+#include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -161,6 +162,34 @@ static int mrfld_gpio_direction_output(s
 	return 0;
 }
 
+static int mrfld_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+	void __iomem *gpdr = gpio_reg(chip, offset, GPDR);
+
+	return (readl(gpdr) & BIT(offset % 32)) ? GPIOF_DIR_OUT : GPIOF_DIR_IN;
+}
+
+static int mrfld_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset,
+				   unsigned int debounce)
+{
+	struct mrfld_gpio *priv = gpiochip_get_data(chip);
+	void __iomem *gfbr = gpio_reg(chip, offset, GFBR);
+	unsigned long flags;
+	u32 value;
+
+	raw_spin_lock_irqsave(&priv->lock, flags);
+
+	if (debounce)
+		value = readl(gfbr) & ~BIT(offset % 32);
+	else
+		value = readl(gfbr) | BIT(offset % 32);
+	writel(value, gfbr);
+
+	raw_spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
 static void mrfld_irq_ack(struct irq_data *d)
 {
 	struct mrfld_gpio *priv = irq_data_get_irq_chip_data(d);
@@ -384,6 +413,8 @@ static int mrfld_gpio_probe(struct pci_d
 	priv->chip.direction_output = mrfld_gpio_direction_output;
 	priv->chip.get = mrfld_gpio_get;
 	priv->chip.set = mrfld_gpio_set;
+	priv->chip.get_direction = mrfld_gpio_get_direction;
+	priv->chip.set_debounce = mrfld_gpio_set_debounce;
 	priv->chip.base = gpio_base;
 	priv->chip.ngpio = MRFLD_NGPIO;
 	priv->chip.can_sleep = false;
@@ -411,7 +442,7 @@ static int mrfld_gpio_probe(struct pci_d
 	}
 
 	retval = gpiochip_irqchip_add(&priv->chip, &mrfld_irqchip, irq_base,
-				      handle_simple_irq, IRQ_TYPE_NONE);
+				      handle_bad_irq, IRQ_TYPE_NONE);
 	if (retval) {
 		dev_err(&pdev->dev, "could not connect irqchip to gpiochip\n");
 		return retval;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-mxs.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-mxs.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-mxs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-mxs.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,10 +87,15 @@ static int mxs_gpio_set_irq_type(struct
 	u32 val;
 	u32 pin_mask = 1 << d->hwirq;
 	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	struct irq_chip_type *ct = irq_data_get_chip_type(d);
 	struct mxs_gpio_port *port = gc->private;
 	void __iomem *pin_addr;
 	int edge;
 
+	if (!(ct->type & type))
+		if (irq_setup_alt_chip(d, type))
+			return -EINVAL;
+
 	port->both_edges &= ~pin_mask;
 	switch (type) {
 	case IRQ_TYPE_EDGE_BOTH:
@@ -119,10 +124,13 @@ static int mxs_gpio_set_irq_type(struct
 
 	/* set level or edge */
 	pin_addr = port->base + PINCTRL_IRQLEV(port);
-	if (edge & GPIO_INT_LEV_MASK)
+	if (edge & GPIO_INT_LEV_MASK) {
 		writel(pin_mask, pin_addr + MXS_SET);
-	else
+		writel(pin_mask, port->base + PINCTRL_IRQEN(port) + MXS_SET);
+	} else {
 		writel(pin_mask, pin_addr + MXS_CLR);
+		writel(pin_mask, port->base + PINCTRL_PIN2IRQ(port) + MXS_SET);
+	}
 
 	/* set polarity */
 	pin_addr = port->base + PINCTRL_IRQPOL(port);
@@ -197,26 +205,42 @@ static int mxs_gpio_set_wake_irq(struct
 	return 0;
 }
 
-static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
+static int mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
 {
 	struct irq_chip_generic *gc;
 	struct irq_chip_type *ct;
 
-	gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base,
+	gc = irq_alloc_generic_chip("gpio-mxs", 2, irq_base,
 				    port->base, handle_level_irq);
 	if (!gc)
 		return -ENOMEM;
 
 	gc->private = port;
 
-	ct = gc->chip_types;
+	ct = &gc->chip_types[0];
+	ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
 	ct->chip.irq_ack = irq_gc_ack_set_bit;
-	ct->chip.irq_mask = irq_gc_mask_clr_bit;
-	ct->chip.irq_unmask = irq_gc_mask_set_bit;
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
 	ct->chip.irq_set_type = mxs_gpio_set_irq_type;
 	ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
+	ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
 	ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
-	ct->regs.mask = PINCTRL_IRQEN(port);
+	ct->regs.enable = PINCTRL_PIN2IRQ(port) + MXS_SET;
+	ct->regs.disable = PINCTRL_PIN2IRQ(port) + MXS_CLR;
+
+	ct = &gc->chip_types[1];
+	ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	ct->chip.irq_ack = irq_gc_ack_set_bit;
+	ct->chip.irq_mask = irq_gc_mask_disable_reg;
+	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+	ct->chip.irq_set_type = mxs_gpio_set_irq_type;
+	ct->chip.irq_set_wake = mxs_gpio_set_wake_irq;
+	ct->chip.flags = IRQCHIP_SET_TYPE_MASKED;
+	ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR;
+	ct->regs.enable = PINCTRL_IRQEN(port) + MXS_SET;
+	ct->regs.disable = PINCTRL_IRQEN(port) + MXS_CLR;
+	ct->handler = handle_level_irq;
 
 	irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
 			       IRQ_NOREQUEST, 0);
@@ -297,11 +321,8 @@ static int mxs_gpio_probe(struct platfor
 	}
 	port->base = base;
 
-	/*
-	 * select the pin interrupt functionality but initially
-	 * disable the interrupts
-	 */
-	writel(~0U, port->base + PINCTRL_PIN2IRQ(port));
+	/* initially disable the interrupts */
+	writel(0, port->base + PINCTRL_PIN2IRQ(port));
 	writel(0, port->base + PINCTRL_IRQEN(port));
 
 	/* clear address has to be used to clear IRQSTAT bits */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-pca953x.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-pca953x.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-pca953x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-pca953x.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,6 +74,7 @@ static const struct i2c_device_id pca953
 	{ "max7312", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "max7313", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "max7315", 8  | PCA953X_TYPE | PCA_INT, },
+	{ "max7318", 16 | PCA953X_TYPE | PCA_INT, },
 	{ "pca6107", 8  | PCA953X_TYPE | PCA_INT, },
 	{ "tca6408", 8  | PCA953X_TYPE | PCA_INT, },
 	{ "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
@@ -635,20 +636,20 @@ static int pca953x_irq_setup(struct pca9
 			return ret;
 		}
 
-		ret =  gpiochip_irqchip_add(&chip->gpio_chip,
-					    &pca953x_irq_chip,
-					    irq_base,
-					    handle_simple_irq,
-					    IRQ_TYPE_NONE);
+		ret =  gpiochip_irqchip_add_nested(&chip->gpio_chip,
+						   &pca953x_irq_chip,
+						   irq_base,
+						   handle_simple_irq,
+						   IRQ_TYPE_NONE);
 		if (ret) {
 			dev_err(&client->dev,
 				"could not connect irqchip to gpiochip\n");
 			return ret;
 		}
 
-		gpiochip_set_chained_irqchip(&chip->gpio_chip,
-					     &pca953x_irq_chip,
-					     client->irq, NULL);
+		gpiochip_set_nested_irqchip(&chip->gpio_chip,
+					    &pca953x_irq_chip,
+					    client->irq);
 	}
 
 	return 0;
@@ -907,6 +908,7 @@ static const struct of_device_id pca953x
 	{ .compatible = "maxim,max7312", .data = OF_953X(16, PCA_INT), },
 	{ .compatible = "maxim,max7313", .data = OF_953X(16, PCA_INT), },
 	{ .compatible = "maxim,max7315", .data = OF_953X( 8, PCA_INT), },
+	{ .compatible = "maxim,max7318", .data = OF_953X(16, PCA_INT), },
 
 	{ .compatible = "ti,pca6107", .data = OF_953X( 8, PCA_INT), },
 	{ .compatible = "ti,pca9536", .data = OF_953X( 4, 0), },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-pcf857x.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-pcf857x.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-pcf857x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-pcf857x.c	2017-02-12 16:03:20.000000000 -0500
@@ -378,9 +378,10 @@ static int pcf857x_probe(struct i2c_clie
 
 	/* Enable irqchip if we have an interrupt */
 	if (client->irq) {
-		status = gpiochip_irqchip_add(&gpio->chip, &pcf857x_irq_chip,
-					      0, handle_level_irq,
-					      IRQ_TYPE_NONE);
+		status = gpiochip_irqchip_add_nested(&gpio->chip,
+						     &pcf857x_irq_chip,
+						     0, handle_level_irq,
+						     IRQ_TYPE_NONE);
 		if (status) {
 			dev_err(&client->dev, "cannot add irqchip\n");
 			goto fail;
@@ -393,8 +394,8 @@ static int pcf857x_probe(struct i2c_clie
 		if (status)
 			goto fail;
 
-		gpiochip_set_chained_irqchip(&gpio->chip, &pcf857x_irq_chip,
-					     client->irq, NULL);
+		gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
+					    client->irq);
 		gpio->irq_parent = client->irq;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-pl061.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-pl061.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-pl061.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-pl061.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,6 @@
 #include <linux/gpio.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
-#include <linux/amba/pl061.h>
 #include <linux/slab.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/pm.h>
@@ -50,11 +49,12 @@ struct pl061_context_save_regs {
 };
 #endif
 
-struct pl061_gpio {
+struct pl061 {
 	spinlock_t		lock;
 
 	void __iomem		*base;
 	struct gpio_chip	gc;
+	int			parent_irq;
 
 #ifdef CONFIG_PM
 	struct pl061_context_save_regs csave_regs;
@@ -63,22 +63,22 @@ struct pl061_gpio {
 
 static int pl061_get_direction(struct gpio_chip *gc, unsigned offset)
 {
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 
-	return !(readb(chip->base + GPIODIR) & BIT(offset));
+	return !(readb(pl061->base + GPIODIR) & BIT(offset));
 }
 
 static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
 {
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 	unsigned long flags;
 	unsigned char gpiodir;
 
-	spin_lock_irqsave(&chip->lock, flags);
-	gpiodir = readb(chip->base + GPIODIR);
+	spin_lock_irqsave(&pl061->lock, flags);
+	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir &= ~(BIT(offset));
-	writeb(gpiodir, chip->base + GPIODIR);
-	spin_unlock_irqrestore(&chip->lock, flags);
+	writeb(gpiodir, pl061->base + GPIODIR);
+	spin_unlock_irqrestore(&pl061->lock, flags);
 
 	return 0;
 }
@@ -86,44 +86,44 @@ static int pl061_direction_input(struct
 static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
 		int value)
 {
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 	unsigned long flags;
 	unsigned char gpiodir;
 
-	spin_lock_irqsave(&chip->lock, flags);
-	writeb(!!value << offset, chip->base + (BIT(offset + 2)));
-	gpiodir = readb(chip->base + GPIODIR);
+	spin_lock_irqsave(&pl061->lock, flags);
+	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
+	gpiodir = readb(pl061->base + GPIODIR);
 	gpiodir |= BIT(offset);
-	writeb(gpiodir, chip->base + GPIODIR);
+	writeb(gpiodir, pl061->base + GPIODIR);
 
 	/*
 	 * gpio value is set again, because pl061 doesn't allow to set value of
 	 * a gpio pin before configuring it in OUT mode.
 	 */
-	writeb(!!value << offset, chip->base + (BIT(offset + 2)));
-	spin_unlock_irqrestore(&chip->lock, flags);
+	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
+	spin_unlock_irqrestore(&pl061->lock, flags);
 
 	return 0;
 }
 
 static int pl061_get_value(struct gpio_chip *gc, unsigned offset)
 {
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 
-	return !!readb(chip->base + (BIT(offset + 2)));
+	return !!readb(pl061->base + (BIT(offset + 2)));
 }
 
 static void pl061_set_value(struct gpio_chip *gc, unsigned offset, int value)
 {
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 
-	writeb(!!value << offset, chip->base + (BIT(offset + 2)));
+	writeb(!!value << offset, pl061->base + (BIT(offset + 2)));
 }
 
 static int pl061_irq_type(struct irq_data *d, unsigned trigger)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 	int offset = irqd_to_hwirq(d);
 	unsigned long flags;
 	u8 gpiois, gpioibe, gpioiev;
@@ -143,11 +143,11 @@ static int pl061_irq_type(struct irq_dat
 	}
 
 
-	spin_lock_irqsave(&chip->lock, flags);
+	spin_lock_irqsave(&pl061->lock, flags);
 
-	gpioiev = readb(chip->base + GPIOIEV);
-	gpiois = readb(chip->base + GPIOIS);
-	gpioibe = readb(chip->base + GPIOIBE);
+	gpioiev = readb(pl061->base + GPIOIEV);
+	gpiois = readb(pl061->base + GPIOIS);
+	gpioibe = readb(pl061->base + GPIOIBE);
 
 	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
 		bool polarity = trigger & IRQ_TYPE_LEVEL_HIGH;
@@ -199,11 +199,11 @@ static int pl061_irq_type(struct irq_dat
 			 offset);
 	}
 
-	writeb(gpiois, chip->base + GPIOIS);
-	writeb(gpioibe, chip->base + GPIOIBE);
-	writeb(gpioiev, chip->base + GPIOIEV);
+	writeb(gpiois, pl061->base + GPIOIS);
+	writeb(gpioibe, pl061->base + GPIOIBE);
+	writeb(gpioiev, pl061->base + GPIOIEV);
 
-	spin_unlock_irqrestore(&chip->lock, flags);
+	spin_unlock_irqrestore(&pl061->lock, flags);
 
 	return 0;
 }
@@ -213,12 +213,12 @@ static void pl061_irq_handler(struct irq
 	unsigned long pending;
 	int offset;
 	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 	struct irq_chip *irqchip = irq_desc_get_chip(desc);
 
 	chained_irq_enter(irqchip, desc);
 
-	pending = readb(chip->base + GPIOMIS);
+	pending = readb(pl061->base + GPIOMIS);
 	if (pending) {
 		for_each_set_bit(offset, &pending, PL061_GPIO_NR)
 			generic_handle_irq(irq_find_mapping(gc->irqdomain,
@@ -231,27 +231,27 @@ static void pl061_irq_handler(struct irq
 static void pl061_irq_mask(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 	u8 gpioie;
 
-	spin_lock(&chip->lock);
-	gpioie = readb(chip->base + GPIOIE) & ~mask;
-	writeb(gpioie, chip->base + GPIOIE);
-	spin_unlock(&chip->lock);
+	spin_lock(&pl061->lock);
+	gpioie = readb(pl061->base + GPIOIE) & ~mask;
+	writeb(gpioie, pl061->base + GPIOIE);
+	spin_unlock(&pl061->lock);
 }
 
 static void pl061_irq_unmask(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 	u8 gpioie;
 
-	spin_lock(&chip->lock);
-	gpioie = readb(chip->base + GPIOIE) | mask;
-	writeb(gpioie, chip->base + GPIOIE);
-	spin_unlock(&chip->lock);
+	spin_lock(&pl061->lock);
+	gpioie = readb(pl061->base + GPIOIE) | mask;
+	writeb(gpioie, pl061->base + GPIOIE);
+	spin_unlock(&pl061->lock);
 }
 
 /**
@@ -265,19 +265,20 @@ static void pl061_irq_unmask(struct irq_
 static void pl061_irq_ack(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct pl061_gpio *chip = gpiochip_get_data(gc);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 	u8 mask = BIT(irqd_to_hwirq(d) % PL061_GPIO_NR);
 
-	spin_lock(&chip->lock);
-	writeb(mask, chip->base + GPIOIC);
-	spin_unlock(&chip->lock);
+	spin_lock(&pl061->lock);
+	writeb(mask, pl061->base + GPIOIC);
+	spin_unlock(&pl061->lock);
 }
 
 static int pl061_irq_set_wake(struct irq_data *d, unsigned int state)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct pl061 *pl061 = gpiochip_get_data(gc);
 
-	return irq_set_irq_wake(gc->irq_parent, state);
+	return irq_set_irq_wake(pl061->parent_irq, state);
 }
 
 static struct irq_chip pl061_irqchip = {
@@ -292,81 +293,60 @@ static struct irq_chip pl061_irqchip = {
 static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct device *dev = &adev->dev;
-	struct pl061_platform_data *pdata = dev_get_platdata(dev);
-	struct pl061_gpio *chip;
-	int ret, irq, i, irq_base;
+	struct pl061 *pl061;
+	int ret, irq;
 
-	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
-	if (chip == NULL)
+	pl061 = devm_kzalloc(dev, sizeof(*pl061), GFP_KERNEL);
+	if (pl061 == NULL)
 		return -ENOMEM;
 
-	if (pdata) {
-		chip->gc.base = pdata->gpio_base;
-		irq_base = pdata->irq_base;
-		if (irq_base <= 0) {
-			dev_err(&adev->dev, "invalid IRQ base in pdata\n");
-			return -ENODEV;
-		}
-	} else {
-		chip->gc.base = -1;
-		irq_base = 0;
-	}
-
-	chip->base = devm_ioremap_resource(dev, &adev->res);
-	if (IS_ERR(chip->base))
-		return PTR_ERR(chip->base);
+	pl061->base = devm_ioremap_resource(dev, &adev->res);
+	if (IS_ERR(pl061->base))
+		return PTR_ERR(pl061->base);
 
-	spin_lock_init(&chip->lock);
+	spin_lock_init(&pl061->lock);
 	if (of_property_read_bool(dev->of_node, "gpio-ranges")) {
-		chip->gc.request = gpiochip_generic_request;
-		chip->gc.free = gpiochip_generic_free;
+		pl061->gc.request = gpiochip_generic_request;
+		pl061->gc.free = gpiochip_generic_free;
 	}
 
-	chip->gc.get_direction = pl061_get_direction;
-	chip->gc.direction_input = pl061_direction_input;
-	chip->gc.direction_output = pl061_direction_output;
-	chip->gc.get = pl061_get_value;
-	chip->gc.set = pl061_set_value;
-	chip->gc.ngpio = PL061_GPIO_NR;
-	chip->gc.label = dev_name(dev);
-	chip->gc.parent = dev;
-	chip->gc.owner = THIS_MODULE;
+	pl061->gc.base = -1;
+	pl061->gc.get_direction = pl061_get_direction;
+	pl061->gc.direction_input = pl061_direction_input;
+	pl061->gc.direction_output = pl061_direction_output;
+	pl061->gc.get = pl061_get_value;
+	pl061->gc.set = pl061_set_value;
+	pl061->gc.ngpio = PL061_GPIO_NR;
+	pl061->gc.label = dev_name(dev);
+	pl061->gc.parent = dev;
+	pl061->gc.owner = THIS_MODULE;
 
-	ret = gpiochip_add_data(&chip->gc, chip);
+	ret = gpiochip_add_data(&pl061->gc, pl061);
 	if (ret)
 		return ret;
 
 	/*
 	 * irq_chip support
 	 */
-	writeb(0, chip->base + GPIOIE); /* disable irqs */
+	writeb(0, pl061->base + GPIOIE); /* disable irqs */
 	irq = adev->irq[0];
 	if (irq < 0) {
 		dev_err(&adev->dev, "invalid IRQ\n");
 		return -ENODEV;
 	}
+	pl061->parent_irq = irq;
 
-	ret = gpiochip_irqchip_add(&chip->gc, &pl061_irqchip,
-				   irq_base, handle_bad_irq,
+	ret = gpiochip_irqchip_add(&pl061->gc, &pl061_irqchip,
+				   0, handle_bad_irq,
 				   IRQ_TYPE_NONE);
 	if (ret) {
 		dev_info(&adev->dev, "could not add irqchip\n");
 		return ret;
 	}
-	gpiochip_set_chained_irqchip(&chip->gc, &pl061_irqchip,
+	gpiochip_set_chained_irqchip(&pl061->gc, &pl061_irqchip,
 				     irq, pl061_irq_handler);
 
-	for (i = 0; i < PL061_GPIO_NR; i++) {
-		if (pdata) {
-			if (pdata->directions & (BIT(i)))
-				pl061_direction_output(&chip->gc, i,
-						pdata->values & (BIT(i)));
-			else
-				pl061_direction_input(&chip->gc, i);
-		}
-	}
-
-	amba_set_drvdata(adev, chip);
+	amba_set_drvdata(adev, pl061);
 	dev_info(&adev->dev, "PL061 GPIO chip @%pa registered\n",
 		 &adev->res.start);
 
@@ -376,20 +356,20 @@ static int pl061_probe(struct amba_devic
 #ifdef CONFIG_PM
 static int pl061_suspend(struct device *dev)
 {
-	struct pl061_gpio *chip = dev_get_drvdata(dev);
+	struct pl061 *pl061 = dev_get_drvdata(dev);
 	int offset;
 
-	chip->csave_regs.gpio_data = 0;
-	chip->csave_regs.gpio_dir = readb(chip->base + GPIODIR);
-	chip->csave_regs.gpio_is = readb(chip->base + GPIOIS);
-	chip->csave_regs.gpio_ibe = readb(chip->base + GPIOIBE);
-	chip->csave_regs.gpio_iev = readb(chip->base + GPIOIEV);
-	chip->csave_regs.gpio_ie = readb(chip->base + GPIOIE);
+	pl061->csave_regs.gpio_data = 0;
+	pl061->csave_regs.gpio_dir = readb(pl061->base + GPIODIR);
+	pl061->csave_regs.gpio_is = readb(pl061->base + GPIOIS);
+	pl061->csave_regs.gpio_ibe = readb(pl061->base + GPIOIBE);
+	pl061->csave_regs.gpio_iev = readb(pl061->base + GPIOIEV);
+	pl061->csave_regs.gpio_ie = readb(pl061->base + GPIOIE);
 
 	for (offset = 0; offset < PL061_GPIO_NR; offset++) {
-		if (chip->csave_regs.gpio_dir & (BIT(offset)))
-			chip->csave_regs.gpio_data |=
-				pl061_get_value(&chip->gc, offset) << offset;
+		if (pl061->csave_regs.gpio_dir & (BIT(offset)))
+			pl061->csave_regs.gpio_data |=
+				pl061_get_value(&pl061->gc, offset) << offset;
 	}
 
 	return 0;
@@ -397,22 +377,22 @@ static int pl061_suspend(struct device *
 
 static int pl061_resume(struct device *dev)
 {
-	struct pl061_gpio *chip = dev_get_drvdata(dev);
+	struct pl061 *pl061 = dev_get_drvdata(dev);
 	int offset;
 
 	for (offset = 0; offset < PL061_GPIO_NR; offset++) {
-		if (chip->csave_regs.gpio_dir & (BIT(offset)))
-			pl061_direction_output(&chip->gc, offset,
-					chip->csave_regs.gpio_data &
+		if (pl061->csave_regs.gpio_dir & (BIT(offset)))
+			pl061_direction_output(&pl061->gc, offset,
+					pl061->csave_regs.gpio_data &
 					(BIT(offset)));
 		else
-			pl061_direction_input(&chip->gc, offset);
+			pl061_direction_input(&pl061->gc, offset);
 	}
 
-	writeb(chip->csave_regs.gpio_is, chip->base + GPIOIS);
-	writeb(chip->csave_regs.gpio_ibe, chip->base + GPIOIBE);
-	writeb(chip->csave_regs.gpio_iev, chip->base + GPIOIEV);
-	writeb(chip->csave_regs.gpio_ie, chip->base + GPIOIE);
+	writeb(pl061->csave_regs.gpio_is, pl061->base + GPIOIS);
+	writeb(pl061->csave_regs.gpio_ibe, pl061->base + GPIOIBE);
+	writeb(pl061->csave_regs.gpio_iev, pl061->base + GPIOIEV);
+	writeb(pl061->csave_regs.gpio_ie, pl061->base + GPIOIE);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-stmpe.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-stmpe.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-stmpe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-stmpe.c	2017-02-12 16:03:20.000000000 -0500
@@ -413,7 +413,7 @@ static irqreturn_t stmpe_gpio_irq(int ir
 		    stmpe->partnum != STMPE1801) {
 			stmpe_reg_write(stmpe, statmsbreg + i, status[i]);
 			stmpe_reg_write(stmpe,
-					stmpe->regs[STMPE_IDX_GPEDR_LSB + i],
+					stmpe->regs[STMPE_IDX_GPEDR_MSB] + i,
 					status[i]);
 		}
 	}
@@ -484,21 +484,20 @@ static int stmpe_gpio_probe(struct platf
 				if (stmpe_gpio->norequest_mask & BIT(i))
 					clear_bit(i, stmpe_gpio->chip.irq_valid_mask);
 		}
-		ret =  gpiochip_irqchip_add(&stmpe_gpio->chip,
-					    &stmpe_gpio_irq_chip,
-					    0,
-					    handle_simple_irq,
-					    IRQ_TYPE_NONE);
+		ret =  gpiochip_irqchip_add_nested(&stmpe_gpio->chip,
+						   &stmpe_gpio_irq_chip,
+						   0,
+						   handle_simple_irq,
+						   IRQ_TYPE_NONE);
 		if (ret) {
 			dev_err(&pdev->dev,
 				"could not connect irqchip to gpiochip\n");
 			goto out_disable;
 		}
 
-		gpiochip_set_chained_irqchip(&stmpe_gpio->chip,
-					     &stmpe_gpio_irq_chip,
-					     irq,
-					     NULL);
+		gpiochip_set_nested_irqchip(&stmpe_gpio->chip,
+					    &stmpe_gpio_irq_chip,
+					    irq);
 	}
 
 	platform_set_drvdata(pdev, stmpe_gpio);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-sx150x.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-sx150x.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-sx150x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-sx150x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,792 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * Driver for Semtech SX150X I2C GPIO Expanders
- *
- * Author: Gregory Bean <gbean@codeaurora.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 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/gpio.h>
-#include <linux/i2c.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
-
-#define NO_UPDATE_PENDING	-1
-
-/* The chip models of sx150x */
-#define SX150X_123 0
-#define SX150X_456 1
-#define SX150X_789 2
-
-struct sx150x_123_pri {
-	u8 reg_pld_mode;
-	u8 reg_pld_table0;
-	u8 reg_pld_table1;
-	u8 reg_pld_table2;
-	u8 reg_pld_table3;
-	u8 reg_pld_table4;
-	u8 reg_advance;
-};
-
-struct sx150x_456_pri {
-	u8 reg_pld_mode;
-	u8 reg_pld_table0;
-	u8 reg_pld_table1;
-	u8 reg_pld_table2;
-	u8 reg_pld_table3;
-	u8 reg_pld_table4;
-	u8 reg_advance;
-};
-
-struct sx150x_789_pri {
-	u8 reg_drain;
-	u8 reg_polarity;
-	u8 reg_clock;
-	u8 reg_misc;
-	u8 reg_reset;
-	u8 ngpios;
-};
-
-struct sx150x_device_data {
-	u8 model;
-	u8 reg_pullup;
-	u8 reg_pulldn;
-	u8 reg_dir;
-	u8 reg_data;
-	u8 reg_irq_mask;
-	u8 reg_irq_src;
-	u8 reg_sense;
-	u8 ngpios;
-	union {
-		struct sx150x_123_pri x123;
-		struct sx150x_456_pri x456;
-		struct sx150x_789_pri x789;
-	} pri;
-};
-
-/**
- * struct sx150x_platform_data - config data for SX150x driver
- * @gpio_base: The index number of the first GPIO assigned to this
- *             GPIO expander.  The expander will create a block of
- *             consecutively numbered gpios beginning at the given base,
- *             with the size of the block depending on the model of the
- *             expander chip.
- * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO
- *                instead of as an oscillator, increasing the size of the
- *                GP(I)O pool created by this expander by one.  The
- *                output-only GPO pin will be added at the end of the block.
- * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor
- *                 for each IO line in the expander.  Setting the bit at
- *                 position n will enable the pull-up for the IO at
- *                 the corresponding offset.  For chips with fewer than
- *                 16 IO pins, high-end bits are ignored.
- * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down
- *                 resistor for each IO line in the expander. Setting the
- *                 bit at position n will enable the pull-down for the IO at
- *                 the corresponding offset.  For chips with fewer than
- *                 16 IO pins, high-end bits are ignored.
- * @io_polarity: A bit-mask which enables polarity inversion for each IO line
- *               in the expander.  Setting the bit at position n inverts
- *               the polarity of that IO line, while clearing it results
- *               in normal polarity. For chips with fewer than 16 IO pins,
- *               high-end bits are ignored.
- * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line
- *               is connected, via which it reports interrupt events
- *               across all GPIO lines.  This must be a real,
- *               pre-existing IRQ line.
- *               Setting this value < 0 disables the irq_chip functionality
- *               of the driver.
- * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based
- *            IRQ lines will appear.  Similarly to gpio_base, the expander
- *            will create a block of irqs beginning at this number.
- *            This value is ignored if irq_summary is < 0.
- * @reset_during_probe: If set to true, the driver will trigger a full
- *                      reset of the chip at the beginning of the probe
- *                      in order to place it in a known state.
- */
-struct sx150x_platform_data {
-	unsigned gpio_base;
-	bool     oscio_is_gpo;
-	u16      io_pullup_ena;
-	u16      io_pulldn_ena;
-	u16      io_polarity;
-	int      irq_summary;
-	unsigned irq_base;
-	bool     reset_during_probe;
-};
-
-struct sx150x_chip {
-	struct gpio_chip                 gpio_chip;
-	struct i2c_client               *client;
-	const struct sx150x_device_data *dev_cfg;
-	int                              irq_summary;
-	int                              irq_base;
-	int				 irq_update;
-	u32                              irq_sense;
-	u32				 irq_masked;
-	u32				 dev_sense;
-	u32				 dev_masked;
-	struct irq_chip                  irq_chip;
-	struct mutex                     lock;
-};
-
-static const struct sx150x_device_data sx150x_devices[] = {
-	[0] = { /* sx1508q */
-		.model = SX150X_789,
-		.reg_pullup	= 0x03,
-		.reg_pulldn	= 0x04,
-		.reg_dir	= 0x07,
-		.reg_data	= 0x08,
-		.reg_irq_mask	= 0x09,
-		.reg_irq_src	= 0x0c,
-		.reg_sense	= 0x0b,
-		.pri.x789 = {
-			.reg_drain	= 0x05,
-			.reg_polarity	= 0x06,
-			.reg_clock	= 0x0f,
-			.reg_misc	= 0x10,
-			.reg_reset	= 0x7d,
-		},
-		.ngpios = 8,
-	},
-	[1] = { /* sx1509q */
-		.model = SX150X_789,
-		.reg_pullup	= 0x07,
-		.reg_pulldn	= 0x09,
-		.reg_dir	= 0x0f,
-		.reg_data	= 0x11,
-		.reg_irq_mask	= 0x13,
-		.reg_irq_src	= 0x19,
-		.reg_sense	= 0x17,
-		.pri.x789 = {
-			.reg_drain	= 0x0b,
-			.reg_polarity	= 0x0d,
-			.reg_clock	= 0x1e,
-			.reg_misc	= 0x1f,
-			.reg_reset	= 0x7d,
-		},
-		.ngpios	= 16
-	},
-	[2] = { /* sx1506q */
-		.model = SX150X_456,
-		.reg_pullup	= 0x05,
-		.reg_pulldn	= 0x07,
-		.reg_dir	= 0x03,
-		.reg_data	= 0x01,
-		.reg_irq_mask	= 0x09,
-		.reg_irq_src	= 0x0f,
-		.reg_sense	= 0x0d,
-		.pri.x456 = {
-			.reg_pld_mode	= 0x21,
-			.reg_pld_table0	= 0x23,
-			.reg_pld_table1	= 0x25,
-			.reg_pld_table2	= 0x27,
-			.reg_pld_table3	= 0x29,
-			.reg_pld_table4	= 0x2b,
-			.reg_advance	= 0xad,
-		},
-		.ngpios	= 16
-	},
-	[3] = { /* sx1502q */
-		.model = SX150X_123,
-		.reg_pullup	= 0x02,
-		.reg_pulldn	= 0x03,
-		.reg_dir	= 0x01,
-		.reg_data	= 0x00,
-		.reg_irq_mask	= 0x05,
-		.reg_irq_src	= 0x08,
-		.reg_sense	= 0x07,
-		.pri.x123 = {
-			.reg_pld_mode	= 0x10,
-			.reg_pld_table0	= 0x11,
-			.reg_pld_table1	= 0x12,
-			.reg_pld_table2	= 0x13,
-			.reg_pld_table3	= 0x14,
-			.reg_pld_table4	= 0x15,
-			.reg_advance	= 0xad,
-		},
-		.ngpios	= 8,
-	},
-};
-
-static const struct i2c_device_id sx150x_id[] = {
-	{"sx1508q", 0},
-	{"sx1509q", 1},
-	{"sx1506q", 2},
-	{"sx1502q", 3},
-	{}
-};
-
-static const struct of_device_id sx150x_of_match[] = {
-	{ .compatible = "semtech,sx1508q" },
-	{ .compatible = "semtech,sx1509q" },
-	{ .compatible = "semtech,sx1506q" },
-	{ .compatible = "semtech,sx1502q" },
-	{},
-};
-
-static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val)
-{
-	s32 err = i2c_smbus_write_byte_data(client, reg, val);
-
-	if (err < 0)
-		dev_warn(&client->dev,
-			"i2c write fail: can't write %02x to %02x: %d\n",
-			val, reg, err);
-	return err;
-}
-
-static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val)
-{
-	s32 err = i2c_smbus_read_byte_data(client, reg);
-
-	if (err >= 0)
-		*val = err;
-	else
-		dev_warn(&client->dev,
-			"i2c read fail: can't read from %02x: %d\n",
-			reg, err);
-	return err;
-}
-
-static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset)
-{
-	return (chip->dev_cfg->ngpios == offset);
-}
-
-/*
- * These utility functions solve the common problem of locating and setting
- * configuration bits.  Configuration bits are grouped into registers
- * whose indexes increase downwards.  For example, with eight-bit registers,
- * sixteen gpios would have their config bits grouped in the following order:
- * REGISTER N-1 [ f e d c b a 9 8 ]
- *          N   [ 7 6 5 4 3 2 1 0 ]
- *
- * For multi-bit configurations, the pattern gets wider:
- * REGISTER N-3 [ f f e e d d c c ]
- *          N-2 [ b b a a 9 9 8 8 ]
- *          N-1 [ 7 7 6 6 5 5 4 4 ]
- *          N   [ 3 3 2 2 1 1 0 0 ]
- *
- * Given the address of the starting register 'N', the index of the gpio
- * whose configuration we seek to change, and the width in bits of that
- * configuration, these functions allow us to locate the correct
- * register and mask the correct bits.
- */
-static inline void sx150x_find_cfg(u8 offset, u8 width,
-				u8 *reg, u8 *mask, u8 *shift)
-{
-	*reg   -= offset * width / 8;
-	*mask   = (1 << width) - 1;
-	*shift  = (offset * width) % 8;
-	*mask <<= *shift;
-}
-
-static s32 sx150x_write_cfg(struct sx150x_chip *chip,
-			u8 offset, u8 width, u8 reg, u8 val)
-{
-	u8  mask;
-	u8  data;
-	u8  shift;
-	s32 err;
-
-	sx150x_find_cfg(offset, width, &reg, &mask, &shift);
-	err = sx150x_i2c_read(chip->client, reg, &data);
-	if (err < 0)
-		return err;
-
-	data &= ~mask;
-	data |= (val << shift) & mask;
-	return sx150x_i2c_write(chip->client, reg, data);
-}
-
-static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset)
-{
-	u8  reg = chip->dev_cfg->reg_data;
-	u8  mask;
-	u8  data;
-	u8  shift;
-	s32 err;
-
-	sx150x_find_cfg(offset, 1, &reg, &mask, &shift);
-	err = sx150x_i2c_read(chip->client, reg, &data);
-	if (err >= 0)
-		err = (data & mask) != 0 ? 1 : 0;
-
-	return err;
-}
-
-static void sx150x_set_oscio(struct sx150x_chip *chip, int val)
-{
-	sx150x_i2c_write(chip->client,
-			chip->dev_cfg->pri.x789.reg_clock,
-			(val ? 0x1f : 0x10));
-}
-
-static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val)
-{
-	sx150x_write_cfg(chip,
-			offset,
-			1,
-			chip->dev_cfg->reg_data,
-			(val ? 1 : 0));
-}
-
-static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset)
-{
-	return sx150x_write_cfg(chip,
-				offset,
-				1,
-				chip->dev_cfg->reg_dir,
-				1);
-}
-
-static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val)
-{
-	int err;
-
-	err = sx150x_write_cfg(chip,
-			offset,
-			1,
-			chip->dev_cfg->reg_data,
-			(val ? 1 : 0));
-	if (err >= 0)
-		err = sx150x_write_cfg(chip,
-				offset,
-				1,
-				chip->dev_cfg->reg_dir,
-				0);
-	return err;
-}
-
-static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(gc);
-	int status = -EINVAL;
-
-	if (!offset_is_oscio(chip, offset)) {
-		mutex_lock(&chip->lock);
-		status = sx150x_get_io(chip, offset);
-		mutex_unlock(&chip->lock);
-	}
-
-	return (status < 0) ? status : !!status;
-}
-
-static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(gc);
-
-	mutex_lock(&chip->lock);
-	if (offset_is_oscio(chip, offset))
-		sx150x_set_oscio(chip, val);
-	else
-		sx150x_set_io(chip, offset, val);
-	mutex_unlock(&chip->lock);
-}
-
-static int sx150x_gpio_set_single_ended(struct gpio_chip *gc,
-					unsigned offset,
-                                        enum single_ended_mode mode)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(gc);
-
-	/* On the SX160X 789 we can set open drain */
-	if (chip->dev_cfg->model != SX150X_789)
-		return -ENOTSUPP;
-
-	if (mode == LINE_MODE_PUSH_PULL)
-		return sx150x_write_cfg(chip,
-					offset,
-					1,
-					chip->dev_cfg->pri.x789.reg_drain,
-					0);
-
-	if (mode == LINE_MODE_OPEN_DRAIN)
-		return sx150x_write_cfg(chip,
-					offset,
-					1,
-					chip->dev_cfg->pri.x789.reg_drain,
-					1);
-	return -ENOTSUPP;
-}
-
-static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(gc);
-	int status = -EINVAL;
-
-	if (!offset_is_oscio(chip, offset)) {
-		mutex_lock(&chip->lock);
-		status = sx150x_io_input(chip, offset);
-		mutex_unlock(&chip->lock);
-	}
-	return status;
-}
-
-static int sx150x_gpio_direction_output(struct gpio_chip *gc,
-					unsigned offset,
-					int val)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(gc);
-	int status = 0;
-
-	if (!offset_is_oscio(chip, offset)) {
-		mutex_lock(&chip->lock);
-		status = sx150x_io_output(chip, offset, val);
-		mutex_unlock(&chip->lock);
-	}
-	return status;
-}
-
-static void sx150x_irq_mask(struct irq_data *d)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
-	unsigned n = d->hwirq;
-
-	chip->irq_masked |= (1 << n);
-	chip->irq_update = n;
-}
-
-static void sx150x_irq_unmask(struct irq_data *d)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
-	unsigned n = d->hwirq;
-
-	chip->irq_masked &= ~(1 << n);
-	chip->irq_update = n;
-}
-
-static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
-	unsigned n, val = 0;
-
-	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-		return -EINVAL;
-
-	n = d->hwirq;
-
-	if (flow_type & IRQ_TYPE_EDGE_RISING)
-		val |= 0x1;
-	if (flow_type & IRQ_TYPE_EDGE_FALLING)
-		val |= 0x2;
-
-	chip->irq_sense &= ~(3UL << (n * 2));
-	chip->irq_sense |= val << (n * 2);
-	chip->irq_update = n;
-	return 0;
-}
-
-static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id)
-{
-	struct sx150x_chip *chip = (struct sx150x_chip *)dev_id;
-	unsigned nhandled = 0;
-	unsigned sub_irq;
-	unsigned n;
-	s32 err;
-	u8 val;
-	int i;
-
-	for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) {
-		err = sx150x_i2c_read(chip->client,
-				      chip->dev_cfg->reg_irq_src - i,
-				      &val);
-		if (err < 0)
-			continue;
-
-		sx150x_i2c_write(chip->client,
-				chip->dev_cfg->reg_irq_src - i,
-				val);
-		for (n = 0; n < 8; ++n) {
-			if (val & (1 << n)) {
-				sub_irq = irq_find_mapping(
-					chip->gpio_chip.irqdomain,
-					(i * 8) + n);
-				handle_nested_irq(sub_irq);
-				++nhandled;
-			}
-		}
-	}
-
-	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
-}
-
-static void sx150x_irq_bus_lock(struct irq_data *d)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
-
-	mutex_lock(&chip->lock);
-}
-
-static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
-{
-	struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d));
-	unsigned n;
-
-	if (chip->irq_update == NO_UPDATE_PENDING)
-		goto out;
-
-	n = chip->irq_update;
-	chip->irq_update = NO_UPDATE_PENDING;
-
-	/* Avoid updates if nothing changed */
-	if (chip->dev_sense == chip->irq_sense &&
-	    chip->dev_masked == chip->irq_masked)
-		goto out;
-
-	chip->dev_sense = chip->irq_sense;
-	chip->dev_masked = chip->irq_masked;
-
-	if (chip->irq_masked & (1 << n)) {
-		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
-		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
-	} else {
-		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
-		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
-				 chip->irq_sense >> (n * 2));
-	}
-out:
-	mutex_unlock(&chip->lock);
-}
-
-static void sx150x_init_chip(struct sx150x_chip *chip,
-			struct i2c_client *client,
-			kernel_ulong_t driver_data,
-			struct sx150x_platform_data *pdata)
-{
-	mutex_init(&chip->lock);
-
-	chip->client                     = client;
-	chip->dev_cfg                    = &sx150x_devices[driver_data];
-	chip->gpio_chip.parent              = &client->dev;
-	chip->gpio_chip.label            = client->name;
-	chip->gpio_chip.direction_input  = sx150x_gpio_direction_input;
-	chip->gpio_chip.direction_output = sx150x_gpio_direction_output;
-	chip->gpio_chip.get              = sx150x_gpio_get;
-	chip->gpio_chip.set              = sx150x_gpio_set;
-	chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended;
-	chip->gpio_chip.base             = pdata->gpio_base;
-	chip->gpio_chip.can_sleep        = true;
-	chip->gpio_chip.ngpio            = chip->dev_cfg->ngpios;
-#ifdef CONFIG_OF_GPIO
-	chip->gpio_chip.of_node          = client->dev.of_node;
-	chip->gpio_chip.of_gpio_n_cells  = 2;
-#endif
-	if (pdata->oscio_is_gpo)
-		++chip->gpio_chip.ngpio;
-
-	chip->irq_chip.name                = client->name;
-	chip->irq_chip.irq_mask            = sx150x_irq_mask;
-	chip->irq_chip.irq_unmask          = sx150x_irq_unmask;
-	chip->irq_chip.irq_set_type        = sx150x_irq_set_type;
-	chip->irq_chip.irq_bus_lock        = sx150x_irq_bus_lock;
-	chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
-	chip->irq_summary                  = -1;
-	chip->irq_base                     = -1;
-	chip->irq_masked                   = ~0;
-	chip->irq_sense                    = 0;
-	chip->dev_masked                   = ~0;
-	chip->dev_sense                    = 0;
-	chip->irq_update		   = NO_UPDATE_PENDING;
-}
-
-static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
-{
-	int err = 0;
-	unsigned n;
-
-	for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n)
-		err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8));
-	return err;
-}
-
-static int sx150x_reset(struct sx150x_chip *chip)
-{
-	int err;
-
-	err = i2c_smbus_write_byte_data(chip->client,
-					chip->dev_cfg->pri.x789.reg_reset,
-					0x12);
-	if (err < 0)
-		return err;
-
-	err = i2c_smbus_write_byte_data(chip->client,
-					chip->dev_cfg->pri.x789.reg_reset,
-					0x34);
-	return err;
-}
-
-static int sx150x_init_hw(struct sx150x_chip *chip,
-			struct sx150x_platform_data *pdata)
-{
-	int err = 0;
-
-	if (pdata->reset_during_probe) {
-		err = sx150x_reset(chip);
-		if (err < 0)
-			return err;
-	}
-
-	if (chip->dev_cfg->model == SX150X_789)
-		err = sx150x_i2c_write(chip->client,
-				chip->dev_cfg->pri.x789.reg_misc,
-				0x01);
-	else if (chip->dev_cfg->model == SX150X_456)
-		err = sx150x_i2c_write(chip->client,
-				chip->dev_cfg->pri.x456.reg_advance,
-				0x04);
-	else
-		err = sx150x_i2c_write(chip->client,
-				chip->dev_cfg->pri.x123.reg_advance,
-				0x00);
-	if (err < 0)
-		return err;
-
-	err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup,
-			pdata->io_pullup_ena);
-	if (err < 0)
-		return err;
-
-	err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn,
-			pdata->io_pulldn_ena);
-	if (err < 0)
-		return err;
-
-	if (chip->dev_cfg->model == SX150X_789) {
-		err = sx150x_init_io(chip,
-				chip->dev_cfg->pri.x789.reg_polarity,
-				pdata->io_polarity);
-		if (err < 0)
-			return err;
-	} else if (chip->dev_cfg->model == SX150X_456) {
-		/* Set all pins to work in normal mode */
-		err = sx150x_init_io(chip,
-				chip->dev_cfg->pri.x456.reg_pld_mode,
-				0);
-		if (err < 0)
-			return err;
-	} else {
-		/* Set all pins to work in normal mode */
-		err = sx150x_init_io(chip,
-				chip->dev_cfg->pri.x123.reg_pld_mode,
-				0);
-		if (err < 0)
-			return err;
-	}
-
-
-	if (pdata->oscio_is_gpo)
-		sx150x_set_oscio(chip, 0);
-
-	return err;
-}
-
-static int sx150x_install_irq_chip(struct sx150x_chip *chip,
-				int irq_summary,
-				int irq_base)
-{
-	int err;
-
-	chip->irq_summary = irq_summary;
-	chip->irq_base    = irq_base;
-
-	/* Add gpio chip to irq subsystem */
-	err = gpiochip_irqchip_add(&chip->gpio_chip,
-		&chip->irq_chip, chip->irq_base,
-		handle_edge_irq, IRQ_TYPE_EDGE_BOTH);
-	if (err) {
-		dev_err(&chip->client->dev,
-			"could not connect irqchip to gpiochip\n");
-		return  err;
-	}
-
-	err = devm_request_threaded_irq(&chip->client->dev,
-			irq_summary, NULL, sx150x_irq_thread_fn,
-			IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING,
-			chip->irq_chip.name, chip);
-	if (err < 0) {
-		chip->irq_summary = -1;
-		chip->irq_base    = -1;
-	}
-
-	return err;
-}
-
-static int sx150x_probe(struct i2c_client *client,
-				const struct i2c_device_id *id)
-{
-	static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA |
-				     I2C_FUNC_SMBUS_WRITE_WORD_DATA;
-	struct sx150x_platform_data *pdata;
-	struct sx150x_chip *chip;
-	int rc;
-
-	pdata = dev_get_platdata(&client->dev);
-	if (!pdata)
-		return -EINVAL;
-
-	if (!i2c_check_functionality(client->adapter, i2c_funcs))
-		return -ENOSYS;
-
-	chip = devm_kzalloc(&client->dev,
-		sizeof(struct sx150x_chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	sx150x_init_chip(chip, client, id->driver_data, pdata);
-	rc = sx150x_init_hw(chip, pdata);
-	if (rc < 0)
-		return rc;
-
-	rc = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip);
-	if (rc)
-		return rc;
-
-	if (pdata->irq_summary >= 0) {
-		rc = sx150x_install_irq_chip(chip,
-					pdata->irq_summary,
-					pdata->irq_base);
-		if (rc < 0)
-			return rc;
-	}
-
-	i2c_set_clientdata(client, chip);
-
-	return 0;
-}
-
-static struct i2c_driver sx150x_driver = {
-	.driver = {
-		.name = "sx150x",
-		.of_match_table = of_match_ptr(sx150x_of_match),
-	},
-	.probe    = sx150x_probe,
-	.id_table = sx150x_id,
-};
-
-static int __init sx150x_init(void)
-{
-	return i2c_add_driver(&sx150x_driver);
-}
-subsys_initcall(sx150x_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-tc3589x.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-tc3589x.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-tc3589x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-tc3589x.c	2017-02-12 16:03:20.000000000 -0500
@@ -337,21 +337,20 @@ static int tc3589x_gpio_probe(struct pla
 		return ret;
 	}
 
-	ret =  gpiochip_irqchip_add(&tc3589x_gpio->chip,
-				    &tc3589x_gpio_irq_chip,
-				    0,
-				    handle_simple_irq,
-				    IRQ_TYPE_NONE);
+	ret =  gpiochip_irqchip_add_nested(&tc3589x_gpio->chip,
+					   &tc3589x_gpio_irq_chip,
+					   0,
+					   handle_simple_irq,
+					   IRQ_TYPE_NONE);
 	if (ret) {
 		dev_err(&pdev->dev,
 			"could not connect irqchip to gpiochip\n");
 		return ret;
 	}
 
-	gpiochip_set_chained_irqchip(&tc3589x_gpio->chip,
-				     &tc3589x_gpio_irq_chip,
-				     irq,
-				     NULL);
+	gpiochip_set_nested_irqchip(&tc3589x_gpio->chip,
+				    &tc3589x_gpio_irq_chip,
+				    irq);
 
 	platform_set_drvdata(pdev, tc3589x_gpio);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-tps65218.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-tps65218.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-tps65218.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-tps65218.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/gpio/driver.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/mfd/tps65218.h>
 
 struct tps65218_gpio {
@@ -30,7 +31,7 @@ static int tps65218_gpio_get(struct gpio
 	unsigned int val;
 	int ret;
 
-	ret = tps65218_reg_read(tps65218, TPS65218_REG_ENABLE2, &val);
+	ret = regmap_read(tps65218->regmap, TPS65218_REG_ENABLE2, &val);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-vf610.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-vf610.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-vf610.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-vf610.c	2017-02-12 16:03:20.000000000 -0500
@@ -283,8 +283,4 @@ static struct platform_driver vf610_gpio
 	.probe		= vf610_gpio_probe,
 };
 
-static int __init gpio_vf610_init(void)
-{
-	return platform_driver_register(&vf610_gpio_driver);
-}
-device_initcall(gpio_vf610_init);
+builtin_platform_driver(vf610_gpio_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/gpio-wcove.c linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-wcove.c
--- linux-libre-4.9-gnu/drivers/gpio/gpio-wcove.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/gpio-wcove.c	2017-02-12 16:03:20.000000000 -0500
@@ -426,8 +426,8 @@ static int wcove_gpio_probe(struct platf
 		return ret;
 	}
 
-	ret = gpiochip_irqchip_add(&wg->chip, &wcove_irqchip, 0,
-			     handle_simple_irq, IRQ_TYPE_NONE);
+	ret = gpiochip_irqchip_add_nested(&wg->chip, &wcove_irqchip, 0,
+					  handle_simple_irq, IRQ_TYPE_NONE);
 	if (ret) {
 		dev_err(dev, "Failed to add irqchip: %d\n", ret);
 		return ret;
@@ -446,6 +446,8 @@ static int wcove_gpio_probe(struct platf
 		return ret;
 	}
 
+	gpiochip_set_nested_irqchip(&wg->chip, &wcove_irqchip, virq);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpio/Kconfig
--- linux-libre-4.9-gnu/drivers/gpio/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -167,7 +167,7 @@ config GPIO_DWAPB
 
 config GPIO_EM
 	tristate "Emma Mobile GPIO"
-	depends on ARM && OF_GPIO
+	depends on (ARCH_EMEV2 || COMPILE_TEST) && OF_GPIO
 	help
 	  Say yes here to support GPIO on Renesas Emma Mobile SoCs.
 
@@ -451,7 +451,7 @@ config GPIO_VR41XX
 
 config GPIO_VX855
 	tristate "VIA VX855/VX875 GPIO"
-	depends on PCI
+	depends on (X86 || COMPILE_TEST) && PCI
 	select MFD_CORE
 	select MFD_VX855
 	help
@@ -520,6 +520,7 @@ config GPIO_ZYNQ
 
 config GPIO_ZX
 	bool "ZTE ZX GPIO support"
+	depends on ARCH_ZX || COMPILE_TEST
 	select GPIOLIB_IRQCHIP
 	help
 	  Say yes here to support the GPIO device on ZTE ZX SoCs.
@@ -603,7 +604,7 @@ config GPIO_IT87
 
 config GPIO_SCH
 	tristate "Intel SCH/TunnelCreek/Centerton/Quark X1000 GPIO"
-	depends on PCI
+	depends on (X86 || COMPILE_TEST) && PCI
 	select MFD_CORE
 	select LPC_SCH
 	help
@@ -777,16 +778,13 @@ config GPIO_PCF857X
 	  platform-neutral GPIO calls.
 
 config GPIO_SX150X
-	bool "Semtech SX150x I2C GPIO expander"
-	depends on I2C=y
-	select GPIOLIB_IRQCHIP
+	bool "Semtech SX150x I2C GPIO expander (deprecated)"
+	depends on PINCTRL && I2C=y
+	select PINCTRL_SX150X
 	default n
 	help
-	  Say yes here to provide support for Semtech SX150-series I2C
-	  GPIO expanders. Compatible models include:
-
-	  8 bits:  sx1508q
-	  16 bits: sx1509q
+	  Say yes here to provide support for Semtech SX150x-series I2C
+	  GPIO expanders. The GPIO driver was replaced by a Pinctrl version.
 
 config GPIO_TPIC2810
 	tristate "TPIC2810 8-Bit I2C GPO expander"
@@ -798,6 +796,7 @@ config GPIO_TPIC2810
 
 config GPIO_TS4900
 	tristate "Technologic Systems FPGA I2C GPIO"
+	depends on SOC_IMX6 || COMPILE_TEST
 	select REGMAP_I2C
 	help
 	  Say yes here to enabled the GPIO driver for Technologic's FPGA core.
@@ -814,6 +813,14 @@ config GPIO_ADP5520
 	  This option enables support for on-chip GPIO found
 	  on Analog Devices ADP5520 PMICs.
 
+config GPIO_ALTERA_A10SR
+	tristate "Altera Arria10 System Resource GPIO"
+	depends on MFD_ALTERA_A10SR
+	help
+	  Driver for Arria10 Development Kit GPIO expansion which
+	  includes reads of pushbuttons and DIP switches as well
+	  as writes to LEDs.
+
 config GPIO_ARIZONA
 	tristate "Wolfson Microelectronics Arizona class devices"
 	depends on MFD_ARIZONA
@@ -822,7 +829,7 @@ config GPIO_ARIZONA
 
 config GPIO_CRYSTAL_COVE
 	tristate "GPIO support for Crystal Cove PMIC"
-	depends on INTEL_SOC_PMIC
+	depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
 	select GPIOLIB_IRQCHIP
 	help
 	  Support for GPIO pins on Crystal Cove PMIC.
@@ -835,6 +842,7 @@ config GPIO_CRYSTAL_COVE
 
 config GPIO_CS5535
 	tristate "AMD CS5535/CS5536 GPIO support"
+	depends on X86 || MIPS || COMPILE_TEST
 	depends on MFD_CS5535
 	help
 	  The AMD CS5535 and CS5536 southbridges support 28 GPIO pins that
@@ -927,7 +935,7 @@ config GPIO_MAX77620
 
 config GPIO_MSIC
 	bool "Intel MSIC mixed signal gpio support"
-	depends on MFD_INTEL_MSIC
+	depends on (X86 || COMPILE_TEST) && MFD_INTEL_MSIC
 	help
 	  Enable support for GPIO on intel MSIC controllers found in
 	  intel MID devices
@@ -1028,7 +1036,7 @@ config GPIO_UCB1400
 
 config GPIO_WHISKEY_COVE
 	tristate "GPIO support for Whiskey Cove PMIC"
-	depends on INTEL_SOC_PMIC
+	depends on (X86 || COMPILE_TEST) && INTEL_SOC_PMIC
 	select GPIOLIB_IRQCHIP
 	help
 	  Support for GPIO pins on Whiskey Cove PMIC.
@@ -1067,6 +1075,7 @@ menu "PCI GPIO expanders"
 
 config GPIO_AMD8111
 	tristate "AMD 8111 GPIO driver"
+	depends on X86 || COMPILE_TEST
 	help
 	  The AMD 8111 south bridge contains 32 GPIO pins which can be used.
 
@@ -1108,6 +1117,7 @@ config GPIO_MERRIFIELD
 
 config GPIO_ML_IOH
 	tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
+	depends on X86 || COMPILE_TEST
 	select GENERIC_IRQ_CHIP
 	help
 	  ML7213 is companion chip for Intel Atom E6xx series.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpio/Makefile linux-libre-4.10-rc8-gnu/drivers/gpio/Makefile
--- linux-libre-4.9-gnu/drivers/gpio/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpio/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG
 obj-$(CONFIG_GPIOLIB)		+= devres.o
 obj-$(CONFIG_GPIOLIB)		+= gpiolib.o
 obj-$(CONFIG_GPIOLIB)		+= gpiolib-legacy.o
+obj-$(CONFIG_GPIOLIB)		+= gpiolib-devprop.o
 obj-$(CONFIG_OF_GPIO)		+= gpiolib-of.o
 obj-$(CONFIG_GPIO_SYSFS)	+= gpiolib-sysfs.o
 obj-$(CONFIG_GPIO_ACPI)		+= gpiolib-acpi.o
@@ -24,6 +25,7 @@ obj-$(CONFIG_GPIO_ADNP)		+= gpio-adnp.o
 obj-$(CONFIG_GPIO_ADP5520)	+= gpio-adp5520.o
 obj-$(CONFIG_GPIO_ADP5588)	+= gpio-adp5588.o
 obj-$(CONFIG_GPIO_ALTERA)  	+= gpio-altera.o
+obj-$(CONFIG_GPIO_ALTERA_A10SR)	+= gpio-altera-a10sr.o
 obj-$(CONFIG_GPIO_AMD8111)	+= gpio-amd8111.o
 obj-$(CONFIG_GPIO_AMDPT)	+= gpio-amdpt.o
 obj-$(CONFIG_GPIO_ARIZONA)	+= gpio-arizona.o
@@ -102,7 +104,6 @@ obj-$(CONFIG_GPIO_SPEAR_SPICS)	+= gpio-s
 obj-$(CONFIG_GPIO_STA2X11)	+= gpio-sta2x11.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_STP_XWAY)	+= gpio-stp-xway.o
-obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
 obj-$(CONFIG_GPIO_SYSCON)	+= gpio-syscon.o
 obj-$(CONFIG_GPIO_TB10X)	+= gpio-tb10x.o
 obj-$(CONFIG_GPIO_TC3589X)	+= gpio-tc3589x.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c	2017-02-12 16:03:20.000000000 -0500
@@ -265,14 +265,14 @@ static int acp_hw_init(void *handle)
 
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	const struct amdgpu_ip_block_version *ip_version =
+	const struct amdgpu_ip_block *ip_block =
 		amdgpu_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ACP);
 
-	if (!ip_version)
+	if (!ip_block)
 		return -EINVAL;
 
 	r = amd_acp_hw_init(adev->acp.cgs_device,
-			    ip_version->major, ip_version->minor);
+			    ip_block->version->major, ip_block->version->minor);
 	/* -ENODEV means board uses AZ rather than ACP */
 	if (r == -ENODEV)
 		return 0;
@@ -459,7 +459,7 @@ static int acp_set_powergating_state(voi
 	return 0;
 }
 
-const struct amd_ip_funcs acp_ip_funcs = {
+static const struct amd_ip_funcs acp_ip_funcs = {
 	.name = "acp_ip",
 	.early_init = acp_early_init,
 	.late_init = NULL,
@@ -475,3 +475,12 @@ const struct amd_ip_funcs acp_ip_funcs =
 	.set_clockgating_state = acp_set_clockgating_state,
 	.set_powergating_state = acp_set_powergating_state,
 };
+
+const struct amdgpu_ip_block_version acp_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_ACP,
+	.major = 2,
+	.minor = 2,
+	.rev = 0,
+	.funcs = &acp_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,6 @@ struct amdgpu_acp {
 	struct acp_pm_domain *acp_genpd;
 };
 
-extern const struct amd_ip_funcs acp_ip_funcs;
+extern const struct amdgpu_ip_block_version acp_ip_block;
 
 #endif /* __AMDGPU_ACP_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c	2017-02-12 16:03:20.000000000 -0500
@@ -1115,49 +1115,6 @@ int amdgpu_atombios_get_memory_pll_divid
 	return 0;
 }
 
-uint32_t amdgpu_atombios_get_engine_clock(struct amdgpu_device *adev)
-{
-	GET_ENGINE_CLOCK_PS_ALLOCATION args;
-	int index = GetIndexIntoMasterTable(COMMAND, GetEngineClock);
-
-	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-	return le32_to_cpu(args.ulReturnEngineClock);
-}
-
-uint32_t amdgpu_atombios_get_memory_clock(struct amdgpu_device *adev)
-{
-	GET_MEMORY_CLOCK_PS_ALLOCATION args;
-	int index = GetIndexIntoMasterTable(COMMAND, GetMemoryClock);
-
-	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-	return le32_to_cpu(args.ulReturnMemoryClock);
-}
-
-void amdgpu_atombios_set_engine_clock(struct amdgpu_device *adev,
-				      uint32_t eng_clock)
-{
-	SET_ENGINE_CLOCK_PS_ALLOCATION args;
-	int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock);
-
-	args.ulTargetEngineClock = cpu_to_le32(eng_clock);	/* 10 khz */
-
-	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
-void amdgpu_atombios_set_memory_clock(struct amdgpu_device *adev,
-				      uint32_t mem_clock)
-{
-	SET_MEMORY_CLOCK_PS_ALLOCATION args;
-	int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock);
-
-	if (adev->flags & AMD_IS_APU)
-		return;
-
-	args.ulTargetMemoryClock = cpu_to_le32(mem_clock);	/* 10 khz */
-
-	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
 void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev,
 					     u32 eng_clock, u32 mem_clock)
 {
@@ -1256,45 +1213,6 @@ int amdgpu_atombios_get_leakage_vddc_bas
 	return amdgpu_atombios_get_max_vddc(adev, VOLTAGE_TYPE_VDDC, leakage_idx, voltage);
 }
 
-void amdgpu_atombios_set_voltage(struct amdgpu_device *adev,
-				 u16 voltage_level,
-				 u8 voltage_type)
-{
-	union set_voltage args;
-	int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
-	u8 frev, crev, volt_index = voltage_level;
-
-	if (!amdgpu_atom_parse_cmd_header(adev->mode_info.atom_context, index, &frev, &crev))
-		return;
-
-	/* 0xff01 is a flag rather then an actual voltage */
-	if (voltage_level == 0xff01)
-		return;
-
-	switch (crev) {
-	case 1:
-		args.v1.ucVoltageType = voltage_type;
-		args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
-		args.v1.ucVoltageIndex = volt_index;
-		break;
-	case 2:
-		args.v2.ucVoltageType = voltage_type;
-		args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
-		args.v2.usVoltageLevel = cpu_to_le16(voltage_level);
-		break;
-	case 3:
-		args.v3.ucVoltageType = voltage_type;
-		args.v3.ucVoltageMode = ATOM_SET_VOLTAGE;
-		args.v3.usVoltageLevel = cpu_to_le16(voltage_level);
-		break;
-	default:
-		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
-		return;
-	}
-
-	amdgpu_atom_execute_table(adev->mode_info.atom_context, index, (uint32_t *)&args);
-}
-
 int amdgpu_atombios_get_leakage_id_from_vbios(struct amdgpu_device *adev,
 					      u16 *leakage_id)
 {
@@ -1784,6 +1702,19 @@ void amdgpu_atombios_scratch_regs_restor
 		WREG32(mmBIOS_SCRATCH_0 + i, adev->bios_scratch[i]);
 }
 
+void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev,
+					      bool hung)
+{
+	u32 tmp = RREG32(mmBIOS_SCRATCH_3);
+
+	if (hung)
+		tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+	else
+		tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+
+	WREG32(mmBIOS_SCRATCH_3, tmp);
+}
+
 /* Atom needs data in little endian format
  * so swap as appropriate when copying data to
  * or from atom. Note that atom operates on
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.h	2017-02-12 16:03:20.000000000 -0500
@@ -163,16 +163,6 @@ int amdgpu_atombios_get_memory_pll_divid
 					    bool strobe_mode,
 					    struct atom_mpll_param *mpll_param);
 
-uint32_t amdgpu_atombios_get_engine_clock(struct amdgpu_device *adev);
-uint32_t amdgpu_atombios_get_memory_clock(struct amdgpu_device *adev);
-void amdgpu_atombios_set_engine_clock(struct amdgpu_device *adev,
-				      uint32_t eng_clock);
-void amdgpu_atombios_set_memory_clock(struct amdgpu_device *adev,
-				      uint32_t mem_clock);
-void amdgpu_atombios_set_voltage(struct amdgpu_device *adev,
-				 u16 voltage_level,
-				 u8 voltage_type);
-
 void amdgpu_atombios_set_engine_dram_timings(struct amdgpu_device *adev,
 					     u32 eng_clock, u32 mem_clock);
 
@@ -206,6 +196,8 @@ void amdgpu_atombios_scratch_regs_lock(s
 void amdgpu_atombios_scratch_regs_init(struct amdgpu_device *adev);
 void amdgpu_atombios_scratch_regs_save(struct amdgpu_device *adev);
 void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev);
+void amdgpu_atombios_scratch_regs_engine_hung(struct amdgpu_device *adev,
+					      bool hung);
 
 void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le);
 int amdgpu_atombios_get_max_vddc(struct amdgpu_device *adev, u8 voltage_type,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@ static int amdgpu_benchmark_do_move(stru
 {
 	unsigned long start_jiffies;
 	unsigned long end_jiffies;
-	struct fence *fence = NULL;
+	struct dma_fence *fence = NULL;
 	int i, r;
 
 	start_jiffies = jiffies;
@@ -43,17 +43,17 @@ static int amdgpu_benchmark_do_move(stru
 				       false);
 		if (r)
 			goto exit_do_move;
-		r = fence_wait(fence, false);
+		r = dma_fence_wait(fence, false);
 		if (r)
 			goto exit_do_move;
-		fence_put(fence);
+		dma_fence_put(fence);
 	}
 	end_jiffies = jiffies;
 	r = jiffies_to_msecs(end_jiffies - start_jiffies);
 
 exit_do_move:
 	if (fence)
-		fence_put(fence);
+		dma_fence_put(fence);
 	return r;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,10 +70,11 @@ static bool igp_read_bios_from_vram(stru
 		return false;
 	}
 	adev->bios = kmalloc(size, GFP_KERNEL);
-	if (adev->bios == NULL) {
+	if (!adev->bios) {
 		iounmap(bios);
 		return false;
 	}
+	adev->bios_size = size;
 	memcpy_fromio(adev->bios, bios, size);
 	iounmap(bios);
 	return true;
@@ -103,6 +104,7 @@ bool amdgpu_read_bios(struct amdgpu_devi
 		pci_unmap_rom(adev->pdev, bios);
 		return false;
 	}
+	adev->bios_size = size;
 	memcpy_fromio(adev->bios, bios, size);
 	pci_unmap_rom(adev->pdev, bios);
 	return true;
@@ -135,6 +137,7 @@ static bool amdgpu_read_bios_from_rom(st
 		DRM_ERROR("no memory to allocate for BIOS\n");
 		return false;
 	}
+	adev->bios_size = len;
 
 	/* read complete BIOS */
 	return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
@@ -159,6 +162,7 @@ static bool amdgpu_read_platform_bios(st
 	if (adev->bios == NULL) {
 		return false;
 	}
+	adev->bios_size = size;
 
 	return true;
 }
@@ -273,6 +277,7 @@ static bool amdgpu_atrm_get_bios(struct
 		kfree(adev->bios);
 		return false;
 	}
+	adev->bios_size = size;
 	return true;
 }
 #else
@@ -300,8 +305,9 @@ static bool amdgpu_acpi_vfct_bios(struct
 	GOP_VBIOS_CONTENT *vbios;
 	VFCT_IMAGE_HEADER *vhdr;
 
-	if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
+	if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
 		return false;
+	tbl_size = hdr->length;
 	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
 		DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
 		goto out_unmap;
@@ -334,6 +340,7 @@ static bool amdgpu_acpi_vfct_bios(struct
 	}
 
 	adev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
+	adev->bios_size = vhdr->ImageLength;
 	ret = !!adev->bios;
 
 out_unmap:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c	2016-12-11 17:41:18.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c	2017-02-12 17:24:06.000000000 -0500
@@ -146,7 +146,8 @@ static int amdgpu_cgs_alloc_gpu_mem(stru
 	switch(type) {
 	case CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB:
 	case CGS_GPU_MEM_TYPE__VISIBLE_FB:
-		flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+		flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+			AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
 		domain = AMDGPU_GEM_DOMAIN_VRAM;
 		if (max_offset > adev->mc.real_vram_size)
 			return -EINVAL;
@@ -157,7 +158,8 @@ static int amdgpu_cgs_alloc_gpu_mem(stru
 		break;
 	case CGS_GPU_MEM_TYPE__INVISIBLE_CONTIG_FB:
 	case CGS_GPU_MEM_TYPE__INVISIBLE_FB:
-		flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
+		flags = AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
+			AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
 		domain = AMDGPU_GEM_DOMAIN_VRAM;
 		if (adev->mc.visible_vram_size < adev->mc.real_vram_size) {
 			place.fpfn =
@@ -240,7 +242,7 @@ static int amdgpu_cgs_gmap_gpu_mem(struc
 	r = amdgpu_bo_reserve(obj, false);
 	if (unlikely(r != 0))
 		return r;
-	r = amdgpu_bo_pin_restricted(obj, AMDGPU_GEM_DOMAIN_GTT,
+	r = amdgpu_bo_pin_restricted(obj, obj->prefered_domains,
 				     min_offset, max_offset, mcaddr);
 	amdgpu_bo_unreserve(obj);
 	return r;
@@ -624,11 +626,11 @@ static int amdgpu_cgs_set_clockgating_st
 	int i, r = -1;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
 
-		if (adev->ip_blocks[i].type == block_type) {
-			r = adev->ip_blocks[i].funcs->set_clockgating_state(
+		if (adev->ip_blocks[i].version->type == block_type) {
+			r = adev->ip_blocks[i].version->funcs->set_clockgating_state(
 								(void *)adev,
 									state);
 			break;
@@ -645,11 +647,11 @@ static int amdgpu_cgs_set_powergating_st
 	int i, r = -1;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
 
-		if (adev->ip_blocks[i].type == block_type) {
-			r = adev->ip_blocks[i].funcs->set_powergating_state(
+		if (adev->ip_blocks[i].version->type == block_type) {
+			r = adev->ip_blocks[i].version->funcs->set_powergating_state(
 								(void *)adev,
 									state);
 			break;
@@ -685,15 +687,21 @@ static uint32_t fw_type_convert(struct c
 		result = AMDGPU_UCODE_ID_CP_MEC1;
 		break;
 	case CGS_UCODE_ID_CP_MEC_JT2:
-		if (adev->asic_type == CHIP_TONGA || adev->asic_type == CHIP_POLARIS11
-		  || adev->asic_type == CHIP_POLARIS10)
-			result = AMDGPU_UCODE_ID_CP_MEC2;
-		else
+		/* for VI. JT2 should be the same as JT1, because:
+			1, MEC2 and MEC1 use exactly same FW.
+			2, JT2 is not pached but JT1 is.
+		*/
+		if (adev->asic_type >= CHIP_TOPAZ)
 			result = AMDGPU_UCODE_ID_CP_MEC1;
+		else
+			result = AMDGPU_UCODE_ID_CP_MEC2;
 		break;
 	case CGS_UCODE_ID_RLC_G:
 		result = AMDGPU_UCODE_ID_RLC_G;
 		break;
+	case CGS_UCODE_ID_STORAGE:
+		result = AMDGPU_UCODE_ID_STORAGE;
+		break;
 	default:
 		DRM_ERROR("Firmware type not supported\n");
 	}
@@ -715,7 +723,7 @@ static uint16_t amdgpu_get_firmware_vers
 					enum cgs_ucode_id type)
 {
 	CGS_FUNC_ADEV;
-	uint16_t fw_version;
+	uint16_t fw_version = 0;
 
 	switch (type) {
 		case CGS_UCODE_ID_SDMA0:
@@ -745,9 +753,11 @@ static uint16_t amdgpu_get_firmware_vers
 		case CGS_UCODE_ID_RLC_G:
 			fw_version = adev->gfx.rlc_fw_version;
 			break;
+		case CGS_UCODE_ID_STORAGE:
+			break;
 		default:
 			DRM_ERROR("firmware type %d do not have version\n", type);
-			fw_version = 0;
+			break;
 	}
 	return fw_version;
 }
@@ -776,12 +786,18 @@ static int amdgpu_cgs_get_firmware_info(
 
 		if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
 		    (type == CGS_UCODE_ID_CP_MEC_JT2)) {
-			gpu_addr += le32_to_cpu(header->jt_offset) << 2;
+			gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
 			data_size = le32_to_cpu(header->jt_size) << 2;
 		}
-		info->mc_addr = gpu_addr;
+
+		info->kptr = ucode->kaddr;
 		info->image_size = data_size;
+		info->mc_addr = gpu_addr;
 		info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
+
+		if (CGS_UCODE_ID_CP_MEC == type)
+			info->image_size = (header->jt_offset) << 2;
+
 		info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
 		info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
 	} else {
@@ -824,6 +840,9 @@ static int amdgpu_cgs_get_firmware_info(
 				else if (type == CGS_UCODE_ID_SMU_SK)
 					strcpy(fw_name, "/*(DEBLOBBED)*/");
 				break;
+			case CHIP_POLARIS12:
+				strcpy(fw_name, "/*(DEBLOBBED)*/");
+				break;
 			default:
 				DRM_ERROR("SMC firmware not supported\n");
 				return -EINVAL;
@@ -860,6 +879,12 @@ static int amdgpu_cgs_get_firmware_info(
 	return 0;
 }
 
+static int amdgpu_cgs_is_virtualization_enabled(void *cgs_device)
+{
+	CGS_FUNC_ADEV;
+	return amdgpu_sriov_vf(adev);
+}
+
 static int amdgpu_cgs_query_system_info(struct cgs_device *cgs_device,
 					struct cgs_system_info *sys_info)
 {
@@ -1213,6 +1238,7 @@ static const struct cgs_ops amdgpu_cgs_o
 	amdgpu_cgs_notify_dpm_enabled,
 	amdgpu_cgs_call_acpi_method,
 	amdgpu_cgs_query_system_info,
+	amdgpu_cgs_is_virtualization_enabled
 };
 
 static const struct cgs_os_ops amdgpu_cgs_os_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c	2017-02-12 16:03:20.000000000 -0500
@@ -1517,88 +1517,6 @@ static const struct drm_connector_funcs
 	.force = amdgpu_connector_dvi_force,
 };
 
-static struct drm_encoder *
-amdgpu_connector_virtual_encoder(struct drm_connector *connector)
-{
-	int enc_id = connector->encoder_ids[0];
-	struct drm_encoder *encoder;
-	int i;
-	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-		if (connector->encoder_ids[i] == 0)
-			break;
-
-		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
-		if (!encoder)
-			continue;
-
-		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
-			return encoder;
-	}
-
-	/* pick the first one */
-	if (enc_id)
-		return drm_encoder_find(connector->dev, enc_id);
-	return NULL;
-}
-
-static int amdgpu_connector_virtual_get_modes(struct drm_connector *connector)
-{
-	struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector);
-
-	if (encoder) {
-		amdgpu_connector_add_common_modes(encoder, connector);
-	}
-
-	return 0;
-}
-
-static int amdgpu_connector_virtual_mode_valid(struct drm_connector *connector,
-					   struct drm_display_mode *mode)
-{
-	return MODE_OK;
-}
-
-static int
-amdgpu_connector_virtual_dpms(struct drm_connector *connector, int mode)
-{
-	return 0;
-}
-
-static enum drm_connector_status
-
-amdgpu_connector_virtual_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-static int
-amdgpu_connector_virtual_set_property(struct drm_connector *connector,
-				  struct drm_property *property,
-				  uint64_t val)
-{
-	return 0;
-}
-
-static void amdgpu_connector_virtual_force(struct drm_connector *connector)
-{
-	return;
-}
-
-static const struct drm_connector_helper_funcs amdgpu_connector_virtual_helper_funcs = {
-	.get_modes = amdgpu_connector_virtual_get_modes,
-	.mode_valid = amdgpu_connector_virtual_mode_valid,
-	.best_encoder = amdgpu_connector_virtual_encoder,
-};
-
-static const struct drm_connector_funcs amdgpu_connector_virtual_funcs = {
-	.dpms = amdgpu_connector_virtual_dpms,
-	.detect = amdgpu_connector_virtual_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.set_property = amdgpu_connector_virtual_set_property,
-	.destroy = amdgpu_connector_destroy,
-	.force = amdgpu_connector_virtual_force,
-};
-
 void
 amdgpu_connector_add(struct amdgpu_device *adev,
 		      uint32_t connector_id,
@@ -1982,17 +1900,6 @@ amdgpu_connector_add(struct amdgpu_devic
 			subpixel_order = SubPixelHorizontalRGB;
 			connector->interlace_allowed = false;
 			connector->doublescan_allowed = false;
-			break;
-		case DRM_MODE_CONNECTOR_VIRTUAL:
-			amdgpu_dig_connector = kzalloc(sizeof(struct amdgpu_connector_atom_dig), GFP_KERNEL);
-			if (!amdgpu_dig_connector)
-				goto failed;
-			amdgpu_connector->con_priv = amdgpu_dig_connector;
-			drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_virtual_funcs, connector_type);
-			drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_virtual_helper_funcs);
-			subpixel_order = SubPixelHorizontalRGB;
-			connector->interlace_allowed = false;
-			connector->doublescan_allowed = false;
 			break;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -83,6 +83,13 @@ int amdgpu_cs_get_ring(struct amdgpu_dev
 		}
 		break;
 	}
+
+	if (!(*out_ring && (*out_ring)->adev)) {
+		DRM_ERROR("Ring %d is not initialized on IP %d\n",
+			  ring, ip_type);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -355,6 +362,7 @@ static void amdgpu_cs_report_moved_bytes
 static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p,
 				 struct amdgpu_bo *bo)
 {
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	u64 initial_bytes_moved;
 	uint32_t domain;
 	int r;
@@ -372,9 +380,9 @@ static int amdgpu_cs_bo_validate(struct
 
 retry:
 	amdgpu_ttm_placement_from_domain(bo, domain);
-	initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
+	initial_bytes_moved = atomic64_read(&adev->num_bytes_moved);
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
-	p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
+	p->bytes_moved += atomic64_read(&adev->num_bytes_moved) -
 		initial_bytes_moved;
 
 	if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
@@ -387,9 +395,9 @@ retry:
 
 /* Last resort, try to evict something from the current working set */
 static bool amdgpu_cs_try_evict(struct amdgpu_cs_parser *p,
-				struct amdgpu_bo_list_entry *lobj)
+				struct amdgpu_bo *validated)
 {
-	uint32_t domain = lobj->robj->allowed_domains;
+	uint32_t domain = validated->allowed_domains;
 	int r;
 
 	if (!p->evictable)
@@ -400,11 +408,12 @@ static bool amdgpu_cs_try_evict(struct a
 
 		struct amdgpu_bo_list_entry *candidate = p->evictable;
 		struct amdgpu_bo *bo = candidate->robj;
+		struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 		u64 initial_bytes_moved;
 		uint32_t other;
 
 		/* If we reached our current BO we can forget it */
-		if (candidate == lobj)
+		if (candidate->robj == validated)
 			break;
 
 		other = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
@@ -420,9 +429,9 @@ static bool amdgpu_cs_try_evict(struct a
 
 		/* Good we can try to move this BO somewhere else */
 		amdgpu_ttm_placement_from_domain(bo, other);
-		initial_bytes_moved = atomic64_read(&bo->adev->num_bytes_moved);
+		initial_bytes_moved = atomic64_read(&adev->num_bytes_moved);
 		r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
-		p->bytes_moved += atomic64_read(&bo->adev->num_bytes_moved) -
+		p->bytes_moved += atomic64_read(&adev->num_bytes_moved) -
 			initial_bytes_moved;
 
 		if (unlikely(r))
@@ -437,6 +446,23 @@ static bool amdgpu_cs_try_evict(struct a
 	return false;
 }
 
+static int amdgpu_cs_validate(void *param, struct amdgpu_bo *bo)
+{
+	struct amdgpu_cs_parser *p = param;
+	int r;
+
+	do {
+		r = amdgpu_cs_bo_validate(p, bo);
+	} while (r == -ENOMEM && amdgpu_cs_try_evict(p, bo));
+	if (r)
+		return r;
+
+	if (bo->shadow)
+		r = amdgpu_cs_bo_validate(p, bo->shadow);
+
+	return r;
+}
+
 static int amdgpu_cs_list_validate(struct amdgpu_cs_parser *p,
 			    struct list_head *validated)
 {
@@ -464,18 +490,10 @@ static int amdgpu_cs_list_validate(struc
 		if (p->evictable == lobj)
 			p->evictable = NULL;
 
-		do {
-			r = amdgpu_cs_bo_validate(p, bo);
-		} while (r == -ENOMEM && amdgpu_cs_try_evict(p, lobj));
+		r = amdgpu_cs_validate(p, bo);
 		if (r)
 			return r;
 
-		if (bo->shadow) {
-			r = amdgpu_cs_bo_validate(p, bo);
-			if (r)
-				return r;
-		}
-
 		if (binding_userptr) {
 			drm_free_large(lobj->user_pages);
 			lobj->user_pages = NULL;
@@ -594,14 +612,19 @@ static int amdgpu_cs_parser_bos(struct a
 		list_splice(&need_pages, &p->validated);
 	}
 
-	amdgpu_vm_get_pt_bos(p->adev, &fpriv->vm, &duplicates);
-
 	p->bytes_moved_threshold = amdgpu_cs_get_threshold_for_moves(p->adev);
 	p->bytes_moved = 0;
 	p->evictable = list_last_entry(&p->validated,
 				       struct amdgpu_bo_list_entry,
 				       tv.head);
 
+	r = amdgpu_vm_validate_pt_bos(p->adev, &fpriv->vm,
+				      amdgpu_cs_validate, p);
+	if (r) {
+		DRM_ERROR("amdgpu_vm_validate_pt_bos() failed.\n");
+		goto error_validate;
+	}
+
 	r = amdgpu_cs_list_validate(p, &duplicates);
 	if (r) {
 		DRM_ERROR("amdgpu_cs_list_validate(duplicates) failed.\n");
@@ -720,7 +743,7 @@ static void amdgpu_cs_parser_fini(struct
 		ttm_eu_backoff_reservation(&parser->ticket,
 					   &parser->validated);
 	}
-	fence_put(parser->fence);
+	dma_fence_put(parser->fence);
 
 	if (parser->ctx)
 		amdgpu_ctx_put(parser->ctx);
@@ -757,7 +780,7 @@ static int amdgpu_bo_vm_update_pte(struc
 
 	if (p->bo_list) {
 		for (i = 0; i < p->bo_list->num_entries; i++) {
-			struct fence *f;
+			struct dma_fence *f;
 
 			/* ignore duplicates */
 			bo = p->bo_list->array[i].robj;
@@ -807,13 +830,14 @@ static int amdgpu_cs_ib_vm_chunk(struct
 
 	/* Only for UVD/VCE VM emulation */
 	if (ring->funcs->parse_cs) {
-		p->job->vm = NULL;
 		for (i = 0; i < p->job->num_ibs; i++) {
 			r = amdgpu_ring_parse_cs(ring, p, i);
 			if (r)
 				return r;
 		}
-	} else {
+	}
+
+	if (p->job->vm) {
 		p->job->vm_pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
 
 		r = amdgpu_bo_vm_update_pte(p, vm);
@@ -824,16 +848,6 @@ static int amdgpu_cs_ib_vm_chunk(struct
 	return amdgpu_cs_sync_rings(p);
 }
 
-static int amdgpu_cs_handle_lockup(struct amdgpu_device *adev, int r)
-{
-	if (r == -EDEADLK) {
-		r = amdgpu_gpu_reset(adev);
-		if (!r)
-			r = -EAGAIN;
-	}
-	return r;
-}
-
 static int amdgpu_cs_ib_fill(struct amdgpu_device *adev,
 			     struct amdgpu_cs_parser *parser)
 {
@@ -902,7 +916,7 @@ static int amdgpu_cs_ib_fill(struct amdg
 			offset = ((uint64_t)m->it.start) * AMDGPU_GPU_PAGE_SIZE;
 			kptr += chunk_ib->va_start - offset;
 
-			r =  amdgpu_ib_get(adev, NULL, chunk_ib->ib_bytes, ib);
+			r =  amdgpu_ib_get(adev, vm, chunk_ib->ib_bytes, ib);
 			if (r) {
 				DRM_ERROR("Failed to get ib !\n");
 				return r;
@@ -917,9 +931,9 @@ static int amdgpu_cs_ib_fill(struct amdg
 				return r;
 			}
 
-			ib->gpu_addr = chunk_ib->va_start;
 		}
 
+		ib->gpu_addr = chunk_ib->va_start;
 		ib->length_dw = chunk_ib->ib_bytes / 4;
 		ib->flags = chunk_ib->flags;
 		j++;
@@ -927,8 +941,8 @@ static int amdgpu_cs_ib_fill(struct amdg
 
 	/* UVD & VCE fw doesn't support user fences */
 	if (parser->job->uf_addr && (
-	    parser->job->ring->type == AMDGPU_RING_TYPE_UVD ||
-	    parser->job->ring->type == AMDGPU_RING_TYPE_VCE))
+	    parser->job->ring->funcs->type == AMDGPU_RING_TYPE_UVD ||
+	    parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE))
 		return -EINVAL;
 
 	return 0;
@@ -957,7 +971,7 @@ static int amdgpu_cs_dependencies(struct
 		for (j = 0; j < num_deps; ++j) {
 			struct amdgpu_ring *ring;
 			struct amdgpu_ctx *ctx;
-			struct fence *fence;
+			struct dma_fence *fence;
 
 			r = amdgpu_cs_get_ring(adev, deps[j].ip_type,
 					       deps[j].ip_instance,
@@ -979,7 +993,7 @@ static int amdgpu_cs_dependencies(struct
 			} else if (fence) {
 				r = amdgpu_sync_fence(adev, &p->job->sync,
 						      fence);
-				fence_put(fence);
+				dma_fence_put(fence);
 				amdgpu_ctx_put(ctx);
 				if (r)
 					return r;
@@ -1009,7 +1023,7 @@ static int amdgpu_cs_submit(struct amdgp
 
 	job->owner = p->filp;
 	job->fence_ctx = entity->fence_context;
-	p->fence = fence_get(&job->base.s_fence->finished);
+	p->fence = dma_fence_get(&job->base.s_fence->finished);
 	cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence);
 	job->uf_sequence = cs->out.handle;
 	amdgpu_job_free_resources(job);
@@ -1037,29 +1051,29 @@ int amdgpu_cs_ioctl(struct drm_device *d
 	r = amdgpu_cs_parser_init(&parser, data);
 	if (r) {
 		DRM_ERROR("Failed to initialize parser !\n");
-		amdgpu_cs_parser_fini(&parser, r, false);
-		r = amdgpu_cs_handle_lockup(adev, r);
-		return r;
-	}
-	r = amdgpu_cs_parser_bos(&parser, data);
-	if (r == -ENOMEM)
-		DRM_ERROR("Not enough memory for command submission!\n");
-	else if (r && r != -ERESTARTSYS)
-		DRM_ERROR("Failed to process the buffer list %d!\n", r);
-	else if (!r) {
-		reserved_buffers = true;
-		r = amdgpu_cs_ib_fill(adev, &parser);
+		goto out;
 	}
 
-	if (!r) {
-		r = amdgpu_cs_dependencies(adev, &parser);
-		if (r)
-			DRM_ERROR("Failed in the dependencies handling %d!\n", r);
+	r = amdgpu_cs_parser_bos(&parser, data);
+	if (r) {
+		if (r == -ENOMEM)
+			DRM_ERROR("Not enough memory for command submission!\n");
+		else if (r != -ERESTARTSYS)
+			DRM_ERROR("Failed to process the buffer list %d!\n", r);
+		goto out;
 	}
 
+	reserved_buffers = true;
+	r = amdgpu_cs_ib_fill(adev, &parser);
 	if (r)
 		goto out;
 
+	r = amdgpu_cs_dependencies(adev, &parser);
+	if (r) {
+		DRM_ERROR("Failed in the dependencies handling %d!\n", r);
+		goto out;
+	}
+
 	for (i = 0; i < parser.job->num_ibs; i++)
 		trace_amdgpu_cs(&parser, i);
 
@@ -1071,7 +1085,6 @@ int amdgpu_cs_ioctl(struct drm_device *d
 
 out:
 	amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
-	r = amdgpu_cs_handle_lockup(adev, r);
 	return r;
 }
 
@@ -1092,7 +1105,7 @@ int amdgpu_cs_wait_ioctl(struct drm_devi
 	unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout);
 	struct amdgpu_ring *ring = NULL;
 	struct amdgpu_ctx *ctx;
-	struct fence *fence;
+	struct dma_fence *fence;
 	long r;
 
 	r = amdgpu_cs_get_ring(adev, wait->in.ip_type, wait->in.ip_instance,
@@ -1108,8 +1121,8 @@ int amdgpu_cs_wait_ioctl(struct drm_devi
 	if (IS_ERR(fence))
 		r = PTR_ERR(fence);
 	else if (fence) {
-		r = fence_wait_timeout(fence, true, timeout);
-		fence_put(fence);
+		r = dma_fence_wait_timeout(fence, true, timeout);
+		dma_fence_put(fence);
 	} else
 		r = 1;
 
@@ -1124,6 +1137,180 @@ int amdgpu_cs_wait_ioctl(struct drm_devi
 }
 
 /**
+ * amdgpu_cs_get_fence - helper to get fence from drm_amdgpu_fence
+ *
+ * @adev: amdgpu device
+ * @filp: file private
+ * @user: drm_amdgpu_fence copied from user space
+ */
+static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev,
+					     struct drm_file *filp,
+					     struct drm_amdgpu_fence *user)
+{
+	struct amdgpu_ring *ring;
+	struct amdgpu_ctx *ctx;
+	struct dma_fence *fence;
+	int r;
+
+	r = amdgpu_cs_get_ring(adev, user->ip_type, user->ip_instance,
+			       user->ring, &ring);
+	if (r)
+		return ERR_PTR(r);
+
+	ctx = amdgpu_ctx_get(filp->driver_priv, user->ctx_id);
+	if (ctx == NULL)
+		return ERR_PTR(-EINVAL);
+
+	fence = amdgpu_ctx_get_fence(ctx, ring, user->seq_no);
+	amdgpu_ctx_put(ctx);
+
+	return fence;
+}
+
+/**
+ * amdgpu_cs_wait_all_fence - wait on all fences to signal
+ *
+ * @adev: amdgpu device
+ * @filp: file private
+ * @wait: wait parameters
+ * @fences: array of drm_amdgpu_fence
+ */
+static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev,
+				     struct drm_file *filp,
+				     union drm_amdgpu_wait_fences *wait,
+				     struct drm_amdgpu_fence *fences)
+{
+	uint32_t fence_count = wait->in.fence_count;
+	unsigned int i;
+	long r = 1;
+
+	for (i = 0; i < fence_count; i++) {
+		struct dma_fence *fence;
+		unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns);
+
+		fence = amdgpu_cs_get_fence(adev, filp, &fences[i]);
+		if (IS_ERR(fence))
+			return PTR_ERR(fence);
+		else if (!fence)
+			continue;
+
+		r = dma_fence_wait_timeout(fence, true, timeout);
+		if (r < 0)
+			return r;
+
+		if (r == 0)
+			break;
+	}
+
+	memset(wait, 0, sizeof(*wait));
+	wait->out.status = (r > 0);
+
+	return 0;
+}
+
+/**
+ * amdgpu_cs_wait_any_fence - wait on any fence to signal
+ *
+ * @adev: amdgpu device
+ * @filp: file private
+ * @wait: wait parameters
+ * @fences: array of drm_amdgpu_fence
+ */
+static int amdgpu_cs_wait_any_fence(struct amdgpu_device *adev,
+				    struct drm_file *filp,
+				    union drm_amdgpu_wait_fences *wait,
+				    struct drm_amdgpu_fence *fences)
+{
+	unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout_ns);
+	uint32_t fence_count = wait->in.fence_count;
+	uint32_t first = ~0;
+	struct dma_fence **array;
+	unsigned int i;
+	long r;
+
+	/* Prepare the fence array */
+	array = kcalloc(fence_count, sizeof(struct dma_fence *), GFP_KERNEL);
+
+	if (array == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < fence_count; i++) {
+		struct dma_fence *fence;
+
+		fence = amdgpu_cs_get_fence(adev, filp, &fences[i]);
+		if (IS_ERR(fence)) {
+			r = PTR_ERR(fence);
+			goto err_free_fence_array;
+		} else if (fence) {
+			array[i] = fence;
+		} else { /* NULL, the fence has been already signaled */
+			r = 1;
+			goto out;
+		}
+	}
+
+	r = dma_fence_wait_any_timeout(array, fence_count, true, timeout,
+				       &first);
+	if (r < 0)
+		goto err_free_fence_array;
+
+out:
+	memset(wait, 0, sizeof(*wait));
+	wait->out.status = (r > 0);
+	wait->out.first_signaled = first;
+	/* set return value 0 to indicate success */
+	r = 0;
+
+err_free_fence_array:
+	for (i = 0; i < fence_count; i++)
+		dma_fence_put(array[i]);
+	kfree(array);
+
+	return r;
+}
+
+/**
+ * amdgpu_cs_wait_fences_ioctl - wait for multiple command submissions to finish
+ *
+ * @dev: drm device
+ * @data: data from userspace
+ * @filp: file private
+ */
+int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp)
+{
+	struct amdgpu_device *adev = dev->dev_private;
+	union drm_amdgpu_wait_fences *wait = data;
+	uint32_t fence_count = wait->in.fence_count;
+	struct drm_amdgpu_fence *fences_user;
+	struct drm_amdgpu_fence *fences;
+	int r;
+
+	/* Get the fences from userspace */
+	fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence),
+			GFP_KERNEL);
+	if (fences == NULL)
+		return -ENOMEM;
+
+	fences_user = (void __user *)(unsigned long)(wait->in.fences);
+	if (copy_from_user(fences, fences_user,
+		sizeof(struct drm_amdgpu_fence) * fence_count)) {
+		r = -EFAULT;
+		goto err_free_fences;
+	}
+
+	if (wait->in.wait_all)
+		r = amdgpu_cs_wait_all_fences(adev, filp, wait, fences);
+	else
+		r = amdgpu_cs_wait_any_fence(adev, filp, wait, fences);
+
+err_free_fences:
+	kfree(fences);
+
+	return r;
+}
+
+/**
  * amdgpu_cs_find_bo_va - find bo_va for VM address
  *
  * @parser: command submission parser context
@@ -1196,6 +1383,15 @@ int amdgpu_cs_sysvm_access_required(stru
 		r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem);
 		if (unlikely(r))
 			return r;
+
+		if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
+			continue;
+
+		bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
+		amdgpu_ttm_placement_from_domain(bo, bo->allowed_domains);
+		r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+		if (unlikely(r))
+			return r;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@ static int amdgpu_ctx_init(struct amdgpu
 	kref_init(&ctx->refcount);
 	spin_lock_init(&ctx->ring_lock);
 	ctx->fences = kcalloc(amdgpu_sched_jobs * AMDGPU_MAX_RINGS,
-			      sizeof(struct fence*), GFP_KERNEL);
+			      sizeof(struct dma_fence*), GFP_KERNEL);
 	if (!ctx->fences)
 		return -ENOMEM;
 
@@ -55,18 +55,18 @@ static int amdgpu_ctx_init(struct amdgpu
 		r = amd_sched_entity_init(&ring->sched, &ctx->rings[i].entity,
 					  rq, amdgpu_sched_jobs);
 		if (r)
-			break;
+			goto failed;
 	}
 
-	if (i < adev->num_rings) {
-		for (j = 0; j < i; j++)
-			amd_sched_entity_fini(&adev->rings[j]->sched,
-					      &ctx->rings[j].entity);
-		kfree(ctx->fences);
-		ctx->fences = NULL;
-		return r;
-	}
 	return 0;
+
+failed:
+	for (j = 0; j < i; j++)
+		amd_sched_entity_fini(&adev->rings[j]->sched,
+				      &ctx->rings[j].entity);
+	kfree(ctx->fences);
+	ctx->fences = NULL;
+	return r;
 }
 
 static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx)
@@ -79,7 +79,7 @@ static void amdgpu_ctx_fini(struct amdgp
 
 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
 		for (j = 0; j < amdgpu_sched_jobs; ++j)
-			fence_put(ctx->rings[i].fences[j]);
+			dma_fence_put(ctx->rings[i].fences[j]);
 	kfree(ctx->fences);
 	ctx->fences = NULL;
 
@@ -241,39 +241,39 @@ int amdgpu_ctx_put(struct amdgpu_ctx *ct
 }
 
 uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring,
-			      struct fence *fence)
+			      struct dma_fence *fence)
 {
 	struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx];
 	uint64_t seq = cring->sequence;
 	unsigned idx = 0;
-	struct fence *other = NULL;
+	struct dma_fence *other = NULL;
 
 	idx = seq & (amdgpu_sched_jobs - 1);
 	other = cring->fences[idx];
 	if (other) {
 		signed long r;
-		r = fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT);
+		r = dma_fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT);
 		if (r < 0)
 			DRM_ERROR("Error (%ld) waiting for fence!\n", r);
 	}
 
-	fence_get(fence);
+	dma_fence_get(fence);
 
 	spin_lock(&ctx->ring_lock);
 	cring->fences[idx] = fence;
 	cring->sequence++;
 	spin_unlock(&ctx->ring_lock);
 
-	fence_put(other);
+	dma_fence_put(other);
 
 	return seq;
 }
 
-struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
-				   struct amdgpu_ring *ring, uint64_t seq)
+struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
+				       struct amdgpu_ring *ring, uint64_t seq)
 {
 	struct amdgpu_ctx_ring *cring = & ctx->rings[ring->idx];
-	struct fence *fence;
+	struct dma_fence *fence;
 
 	spin_lock(&ctx->ring_lock);
 
@@ -288,7 +288,7 @@ struct fence *amdgpu_ctx_get_fence(struc
 		return NULL;
 	}
 
-	fence = fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]);
+	fence = dma_fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]);
 	spin_unlock(&ctx->ring_lock);
 
 	return fence;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c	2016-12-11 17:41:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c	2017-02-12 17:24:10.000000000 -0500
@@ -73,6 +73,7 @@ static const char *amdgpu_asic_name[] =
 	"STONEY",
 	"POLARIS10",
 	"POLARIS11",
+	"POLARIS12",
 	"LAST",
 };
 
@@ -264,7 +265,8 @@ static int amdgpu_vram_scratch_init(stru
 	if (adev->vram_scratch.robj == NULL) {
 		r = amdgpu_bo_create(adev, AMDGPU_GPU_PAGE_SIZE,
 				     PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
-				     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+				     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+				     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 				     NULL, NULL, &adev->vram_scratch.robj);
 		if (r) {
 			return r;
@@ -442,13 +444,9 @@ void amdgpu_doorbell_get_kfd_info(struct
 static void amdgpu_wb_fini(struct amdgpu_device *adev)
 {
 	if (adev->wb.wb_obj) {
-		if (!amdgpu_bo_reserve(adev->wb.wb_obj, false)) {
-			amdgpu_bo_kunmap(adev->wb.wb_obj);
-			amdgpu_bo_unpin(adev->wb.wb_obj);
-			amdgpu_bo_unreserve(adev->wb.wb_obj);
-		}
-		amdgpu_bo_unref(&adev->wb.wb_obj);
-		adev->wb.wb = NULL;
+		amdgpu_bo_free_kernel(&adev->wb.wb_obj,
+				      &adev->wb.gpu_addr,
+				      (void **)&adev->wb.wb);
 		adev->wb.wb_obj = NULL;
 	}
 }
@@ -467,33 +465,14 @@ static int amdgpu_wb_init(struct amdgpu_
 	int r;
 
 	if (adev->wb.wb_obj == NULL) {
-		r = amdgpu_bo_create(adev, AMDGPU_MAX_WB * 4, PAGE_SIZE, true,
-				     AMDGPU_GEM_DOMAIN_GTT, 0,  NULL, NULL,
-				     &adev->wb.wb_obj);
+		r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * 4,
+					    PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
+					    &adev->wb.wb_obj, &adev->wb.gpu_addr,
+					    (void **)&adev->wb.wb);
 		if (r) {
 			dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
 			return r;
 		}
-		r = amdgpu_bo_reserve(adev->wb.wb_obj, false);
-		if (unlikely(r != 0)) {
-			amdgpu_wb_fini(adev);
-			return r;
-		}
-		r = amdgpu_bo_pin(adev->wb.wb_obj, AMDGPU_GEM_DOMAIN_GTT,
-				&adev->wb.gpu_addr);
-		if (r) {
-			amdgpu_bo_unreserve(adev->wb.wb_obj);
-			dev_warn(adev->dev, "(%d) pin WB bo failed\n", r);
-			amdgpu_wb_fini(adev);
-			return r;
-		}
-		r = amdgpu_bo_kmap(adev->wb.wb_obj, (void **)&adev->wb.wb);
-		amdgpu_bo_unreserve(adev->wb.wb_obj);
-		if (r) {
-			dev_warn(adev->dev, "(%d) map WB bo failed\n", r);
-			amdgpu_wb_fini(adev);
-			return r;
-		}
 
 		adev->wb.num_wb = AMDGPU_MAX_WB;
 		memset(&adev->wb.used, 0, sizeof(adev->wb.used));
@@ -1038,6 +1017,13 @@ static void amdgpu_check_arguments(struc
 			 amdgpu_vm_block_size);
 		amdgpu_vm_block_size = 9;
 	}
+
+	if (amdgpu_vram_page_split != -1 && (amdgpu_vram_page_split < 16 ||
+	    !amdgpu_check_pot_argument(amdgpu_vram_page_split))) {
+		dev_warn(adev->dev, "invalid VRAM page split (%d)\n",
+			 amdgpu_vram_page_split);
+		amdgpu_vram_page_split = 1024;
+	}
 }
 
 /**
@@ -1112,11 +1098,11 @@ int amdgpu_set_clockgating_state(struct
 	int i, r = 0;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_blocks[i].type == block_type) {
-			r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
-									    state);
+		if (adev->ip_blocks[i].version->type == block_type) {
+			r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+										     state);
 			if (r)
 				return r;
 			break;
@@ -1132,11 +1118,11 @@ int amdgpu_set_powergating_state(struct
 	int i, r = 0;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_blocks[i].type == block_type) {
-			r = adev->ip_blocks[i].funcs->set_powergating_state((void *)adev,
-									    state);
+		if (adev->ip_blocks[i].version->type == block_type) {
+			r = adev->ip_blocks[i].version->funcs->set_powergating_state((void *)adev,
+										     state);
 			if (r)
 				return r;
 			break;
@@ -1151,10 +1137,10 @@ int amdgpu_wait_for_idle(struct amdgpu_d
 	int i, r;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_blocks[i].type == block_type) {
-			r = adev->ip_blocks[i].funcs->wait_for_idle((void *)adev);
+		if (adev->ip_blocks[i].version->type == block_type) {
+			r = adev->ip_blocks[i].version->funcs->wait_for_idle((void *)adev);
 			if (r)
 				return r;
 			break;
@@ -1170,23 +1156,22 @@ bool amdgpu_is_idle(struct amdgpu_device
 	int i;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_blocks[i].type == block_type)
-			return adev->ip_blocks[i].funcs->is_idle((void *)adev);
+		if (adev->ip_blocks[i].version->type == block_type)
+			return adev->ip_blocks[i].version->funcs->is_idle((void *)adev);
 	}
 	return true;
 
 }
 
-const struct amdgpu_ip_block_version * amdgpu_get_ip_block(
-					struct amdgpu_device *adev,
-					enum amd_ip_block_type type)
+struct amdgpu_ip_block * amdgpu_get_ip_block(struct amdgpu_device *adev,
+					     enum amd_ip_block_type type)
 {
 	int i;
 
 	for (i = 0; i < adev->num_ip_blocks; i++)
-		if (adev->ip_blocks[i].type == type)
+		if (adev->ip_blocks[i].version->type == type)
 			return &adev->ip_blocks[i];
 
 	return NULL;
@@ -1207,38 +1192,75 @@ int amdgpu_ip_block_version_cmp(struct a
 				enum amd_ip_block_type type,
 				u32 major, u32 minor)
 {
-	const struct amdgpu_ip_block_version *ip_block;
-	ip_block = amdgpu_get_ip_block(adev, type);
+	struct amdgpu_ip_block *ip_block = amdgpu_get_ip_block(adev, type);
 
-	if (ip_block && ((ip_block->major > major) ||
-			((ip_block->major == major) &&
-			(ip_block->minor >= minor))))
+	if (ip_block && ((ip_block->version->major > major) ||
+			((ip_block->version->major == major) &&
+			(ip_block->version->minor >= minor))))
 		return 0;
 
 	return 1;
 }
 
-static void amdgpu_whether_enable_virtual_display(struct amdgpu_device *adev)
+/**
+ * amdgpu_ip_block_add
+ *
+ * @adev: amdgpu_device pointer
+ * @ip_block_version: pointer to the IP to add
+ *
+ * Adds the IP block driver information to the collection of IPs
+ * on the asic.
+ */
+int amdgpu_ip_block_add(struct amdgpu_device *adev,
+			const struct amdgpu_ip_block_version *ip_block_version)
+{
+	if (!ip_block_version)
+		return -EINVAL;
+
+	adev->ip_blocks[adev->num_ip_blocks++].version = ip_block_version;
+
+	return 0;
+}
+
+static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
 {
 	adev->enable_virtual_display = false;
 
 	if (amdgpu_virtual_display) {
 		struct drm_device *ddev = adev->ddev;
 		const char *pci_address_name = pci_name(ddev->pdev);
-		char *pciaddstr, *pciaddstr_tmp, *pciaddname;
+		char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname;
 
 		pciaddstr = kstrdup(amdgpu_virtual_display, GFP_KERNEL);
 		pciaddstr_tmp = pciaddstr;
-		while ((pciaddname = strsep(&pciaddstr_tmp, ";"))) {
+		while ((pciaddname_tmp = strsep(&pciaddstr_tmp, ";"))) {
+			pciaddname = strsep(&pciaddname_tmp, ",");
 			if (!strcmp(pci_address_name, pciaddname)) {
+				long num_crtc;
+				int res = -1;
+
 				adev->enable_virtual_display = true;
+
+				if (pciaddname_tmp)
+					res = kstrtol(pciaddname_tmp, 10,
+						      &num_crtc);
+
+				if (!res) {
+					if (num_crtc < 1)
+						num_crtc = 1;
+					if (num_crtc > 6)
+						num_crtc = 6;
+					adev->mode_info.num_crtc = num_crtc;
+				} else {
+					adev->mode_info.num_crtc = 1;
+				}
 				break;
 			}
 		}
 
-		DRM_INFO("virtual display string:%s, %s:virtual_display:%d\n",
-				 amdgpu_virtual_display, pci_address_name,
-				 adev->enable_virtual_display);
+		DRM_INFO("virtual display string:%s, %s:virtual_display:%d, num_crtc:%d\n",
+			 amdgpu_virtual_display, pci_address_name,
+			 adev->enable_virtual_display, adev->mode_info.num_crtc);
 
 		kfree(pciaddstr);
 	}
@@ -1248,7 +1270,7 @@ static int amdgpu_early_init(struct amdg
 {
 	int i, r;
 
-	amdgpu_whether_enable_virtual_display(adev);
+	amdgpu_device_enable_virtual_display(adev);
 
 	switch (adev->asic_type) {
 	case CHIP_TOPAZ:
@@ -1256,6 +1278,7 @@ static int amdgpu_early_init(struct amdg
 	case CHIP_FIJI:
 	case CHIP_POLARIS11:
 	case CHIP_POLARIS10:
+	case CHIP_POLARIS12:
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
 		if (adev->asic_type == CHIP_CARRIZO || adev->asic_type == CHIP_STONEY)
@@ -1300,33 +1323,24 @@ static int amdgpu_early_init(struct amdg
 		return -EINVAL;
 	}
 
-	adev->ip_block_status = kcalloc(adev->num_ip_blocks,
-					sizeof(struct amdgpu_ip_block_status), GFP_KERNEL);
-	if (adev->ip_block_status == NULL)
-		return -ENOMEM;
-
-	if (adev->ip_blocks == NULL) {
-		DRM_ERROR("No IP blocks found!\n");
-		return r;
-	}
-
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 		if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
 			DRM_ERROR("disabled ip block: %d\n", i);
-			adev->ip_block_status[i].valid = false;
+			adev->ip_blocks[i].status.valid = false;
 		} else {
-			if (adev->ip_blocks[i].funcs->early_init) {
-				r = adev->ip_blocks[i].funcs->early_init((void *)adev);
+			if (adev->ip_blocks[i].version->funcs->early_init) {
+				r = adev->ip_blocks[i].version->funcs->early_init((void *)adev);
 				if (r == -ENOENT) {
-					adev->ip_block_status[i].valid = false;
+					adev->ip_blocks[i].status.valid = false;
 				} else if (r) {
-					DRM_ERROR("early_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+					DRM_ERROR("early_init of IP block <%s> failed %d\n",
+						  adev->ip_blocks[i].version->funcs->name, r);
 					return r;
 				} else {
-					adev->ip_block_status[i].valid = true;
+					adev->ip_blocks[i].status.valid = true;
 				}
 			} else {
-				adev->ip_block_status[i].valid = true;
+				adev->ip_blocks[i].status.valid = true;
 			}
 		}
 	}
@@ -1342,22 +1356,23 @@ static int amdgpu_init(struct amdgpu_dev
 	int i, r;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
+		r = adev->ip_blocks[i].version->funcs->sw_init((void *)adev);
 		if (r) {
-			DRM_ERROR("sw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+			DRM_ERROR("sw_init of IP block <%s> failed %d\n",
+				  adev->ip_blocks[i].version->funcs->name, r);
 			return r;
 		}
-		adev->ip_block_status[i].sw = true;
+		adev->ip_blocks[i].status.sw = true;
 		/* need to do gmc hw init early so we can allocate gpu mem */
-		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
+		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
 			r = amdgpu_vram_scratch_init(adev);
 			if (r) {
 				DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r);
 				return r;
 			}
-			r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
+			r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
 			if (r) {
 				DRM_ERROR("hw_init %d failed %d\n", i, r);
 				return r;
@@ -1367,22 +1382,23 @@ static int amdgpu_init(struct amdgpu_dev
 				DRM_ERROR("amdgpu_wb_init failed %d\n", r);
 				return r;
 			}
-			adev->ip_block_status[i].hw = true;
+			adev->ip_blocks[i].status.hw = true;
 		}
 	}
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].sw)
+		if (!adev->ip_blocks[i].status.sw)
 			continue;
 		/* gmc hw init is done early */
-		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC)
+		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC)
 			continue;
-		r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
+		r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
 		if (r) {
-			DRM_ERROR("hw_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+			DRM_ERROR("hw_init of IP block <%s> failed %d\n",
+				  adev->ip_blocks[i].version->funcs->name, r);
 			return r;
 		}
-		adev->ip_block_status[i].hw = true;
+		adev->ip_blocks[i].status.hw = true;
 	}
 
 	return 0;
@@ -1393,25 +1409,26 @@ static int amdgpu_late_init(struct amdgp
 	int i = 0, r;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_blocks[i].funcs->late_init) {
-			r = adev->ip_blocks[i].funcs->late_init((void *)adev);
+		if (adev->ip_blocks[i].version->funcs->late_init) {
+			r = adev->ip_blocks[i].version->funcs->late_init((void *)adev);
 			if (r) {
-				DRM_ERROR("late_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+				DRM_ERROR("late_init of IP block <%s> failed %d\n",
+					  adev->ip_blocks[i].version->funcs->name, r);
 				return r;
 			}
-			adev->ip_block_status[i].late_initialized = true;
+			adev->ip_blocks[i].status.late_initialized = true;
 		}
 		/* skip CG for VCE/UVD, it's handled specially */
-		if (adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_UVD &&
-		    adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_VCE) {
+		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
+		    adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) {
 			/* enable clockgating to save power */
-			r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
-									    AMD_CG_STATE_GATE);
+			r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+										     AMD_CG_STATE_GATE);
 			if (r) {
 				DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n",
-					  adev->ip_blocks[i].funcs->name, r);
+					  adev->ip_blocks[i].version->funcs->name, r);
 				return r;
 			}
 		}
@@ -1426,68 +1443,77 @@ static int amdgpu_fini(struct amdgpu_dev
 
 	/* need to disable SMC first */
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].hw)
+		if (!adev->ip_blocks[i].status.hw)
 			continue;
-		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) {
+		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) {
 			/* ungate blocks before hw fini so that we can shutdown the blocks safely */
-			r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
-									    AMD_CG_STATE_UNGATE);
+			r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+										     AMD_CG_STATE_UNGATE);
 			if (r) {
 				DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n",
-					  adev->ip_blocks[i].funcs->name, r);
+					  adev->ip_blocks[i].version->funcs->name, r);
 				return r;
 			}
-			r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
+			r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
 			/* XXX handle errors */
 			if (r) {
 				DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
-					  adev->ip_blocks[i].funcs->name, r);
+					  adev->ip_blocks[i].version->funcs->name, r);
 			}
-			adev->ip_block_status[i].hw = false;
+			adev->ip_blocks[i].status.hw = false;
 			break;
 		}
 	}
 
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
-		if (!adev->ip_block_status[i].hw)
+		if (!adev->ip_blocks[i].status.hw)
 			continue;
-		if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
+		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
 			amdgpu_wb_fini(adev);
 			amdgpu_vram_scratch_fini(adev);
 		}
-		/* ungate blocks before hw fini so that we can shutdown the blocks safely */
-		r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
-								    AMD_CG_STATE_UNGATE);
-		if (r) {
-			DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
-			return r;
+
+		if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
+			adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_VCE) {
+			/* ungate blocks before hw fini so that we can shutdown the blocks safely */
+			r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+										     AMD_CG_STATE_UNGATE);
+			if (r) {
+				DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n",
+					  adev->ip_blocks[i].version->funcs->name, r);
+				return r;
+			}
 		}
-		r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
+
+		r = adev->ip_blocks[i].version->funcs->hw_fini((void *)adev);
 		/* XXX handle errors */
 		if (r) {
-			DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+			DRM_DEBUG("hw_fini of IP block <%s> failed %d\n",
+				  adev->ip_blocks[i].version->funcs->name, r);
 		}
-		adev->ip_block_status[i].hw = false;
+
+		adev->ip_blocks[i].status.hw = false;
 	}
 
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
-		if (!adev->ip_block_status[i].sw)
+		if (!adev->ip_blocks[i].status.sw)
 			continue;
-		r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
+		r = adev->ip_blocks[i].version->funcs->sw_fini((void *)adev);
 		/* XXX handle errors */
 		if (r) {
-			DRM_DEBUG("sw_fini of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+			DRM_DEBUG("sw_fini of IP block <%s> failed %d\n",
+				  adev->ip_blocks[i].version->funcs->name, r);
 		}
-		adev->ip_block_status[i].sw = false;
-		adev->ip_block_status[i].valid = false;
+		adev->ip_blocks[i].status.sw = false;
+		adev->ip_blocks[i].status.valid = false;
 	}
 
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
-		if (!adev->ip_block_status[i].late_initialized)
+		if (!adev->ip_blocks[i].status.late_initialized)
 			continue;
-		if (adev->ip_blocks[i].funcs->late_fini)
-			adev->ip_blocks[i].funcs->late_fini((void *)adev);
-		adev->ip_block_status[i].late_initialized = false;
+		if (adev->ip_blocks[i].version->funcs->late_fini)
+			adev->ip_blocks[i].version->funcs->late_fini((void *)adev);
+		adev->ip_blocks[i].status.late_initialized = false;
 	}
 
 	return 0;
@@ -1505,21 +1531,23 @@ int amdgpu_suspend(struct amdgpu_device
 	}
 
 	for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
 		/* ungate blocks so that suspend can properly shut them down */
 		if (i != AMD_IP_BLOCK_TYPE_SMC) {
-			r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
-									    AMD_CG_STATE_UNGATE);
+			r = adev->ip_blocks[i].version->funcs->set_clockgating_state((void *)adev,
+										     AMD_CG_STATE_UNGATE);
 			if (r) {
-				DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+				DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n",
+					  adev->ip_blocks[i].version->funcs->name, r);
 			}
 		}
 		/* XXX handle errors */
-		r = adev->ip_blocks[i].funcs->suspend(adev);
+		r = adev->ip_blocks[i].version->funcs->suspend(adev);
 		/* XXX handle errors */
 		if (r) {
-			DRM_ERROR("suspend of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+			DRM_ERROR("suspend of IP block <%s> failed %d\n",
+				  adev->ip_blocks[i].version->funcs->name, r);
 		}
 	}
 
@@ -1531,11 +1559,12 @@ static int amdgpu_resume(struct amdgpu_d
 	int i, r;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		r = adev->ip_blocks[i].funcs->resume(adev);
+		r = adev->ip_blocks[i].version->funcs->resume(adev);
 		if (r) {
-			DRM_ERROR("resume of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r);
+			DRM_ERROR("resume of IP block <%s> failed %d\n",
+				  adev->ip_blocks[i].version->funcs->name, r);
 			return r;
 		}
 	}
@@ -1586,7 +1615,7 @@ int amdgpu_device_init(struct amdgpu_dev
 	adev->vm_manager.vm_pte_funcs = NULL;
 	adev->vm_manager.vm_pte_num_rings = 0;
 	adev->gart.gart_funcs = NULL;
-	adev->fence_context = fence_context_alloc(AMDGPU_MAX_RINGS);
+	adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS);
 
 	adev->smc_rreg = &amdgpu_invalid_rreg;
 	adev->smc_wreg = &amdgpu_invalid_wreg;
@@ -1846,8 +1875,6 @@ void amdgpu_device_fini(struct amdgpu_de
 	amdgpu_fence_driver_fini(adev);
 	amdgpu_fbdev_fini(adev);
 	r = amdgpu_fini(adev);
-	kfree(adev->ip_block_status);
-	adev->ip_block_status = NULL;
 	adev->accel_working = false;
 	/* free i2c buses */
 	amdgpu_i2c_fini(adev);
@@ -1943,7 +1970,10 @@ int amdgpu_device_suspend(struct drm_dev
 
 	r = amdgpu_suspend(adev);
 
-	/* evict remaining vram memory */
+	/* evict remaining vram memory
+	 * This second call to evict vram is to evict the gart page table
+	 * using the CPU.
+	 */
 	amdgpu_bo_evict_vram(adev);
 
 	amdgpu_atombios_scratch_regs_save(adev);
@@ -2085,13 +2115,13 @@ static bool amdgpu_check_soft_reset(stru
 	bool asic_hang = false;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_blocks[i].funcs->check_soft_reset)
-			adev->ip_block_status[i].hang =
-				adev->ip_blocks[i].funcs->check_soft_reset(adev);
-		if (adev->ip_block_status[i].hang) {
-			DRM_INFO("IP block:%d is hang!\n", i);
+		if (adev->ip_blocks[i].version->funcs->check_soft_reset)
+			adev->ip_blocks[i].status.hang =
+				adev->ip_blocks[i].version->funcs->check_soft_reset(adev);
+		if (adev->ip_blocks[i].status.hang) {
+			DRM_INFO("IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name);
 			asic_hang = true;
 		}
 	}
@@ -2103,11 +2133,11 @@ static int amdgpu_pre_soft_reset(struct
 	int i, r = 0;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_block_status[i].hang &&
-		    adev->ip_blocks[i].funcs->pre_soft_reset) {
-			r = adev->ip_blocks[i].funcs->pre_soft_reset(adev);
+		if (adev->ip_blocks[i].status.hang &&
+		    adev->ip_blocks[i].version->funcs->pre_soft_reset) {
+			r = adev->ip_blocks[i].version->funcs->pre_soft_reset(adev);
 			if (r)
 				return r;
 		}
@@ -2121,13 +2151,13 @@ static bool amdgpu_need_full_reset(struc
 	int i;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if ((adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) ||
-		    (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) ||
-		    (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_ACP) ||
-		    (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_DCE)) {
-			if (adev->ip_block_status[i].hang) {
+		if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) ||
+		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) ||
+		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) ||
+		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE)) {
+			if (adev->ip_blocks[i].status.hang) {
 				DRM_INFO("Some block need full reset!\n");
 				return true;
 			}
@@ -2141,11 +2171,11 @@ static int amdgpu_soft_reset(struct amdg
 	int i, r = 0;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_block_status[i].hang &&
-		    adev->ip_blocks[i].funcs->soft_reset) {
-			r = adev->ip_blocks[i].funcs->soft_reset(adev);
+		if (adev->ip_blocks[i].status.hang &&
+		    adev->ip_blocks[i].version->funcs->soft_reset) {
+			r = adev->ip_blocks[i].version->funcs->soft_reset(adev);
 			if (r)
 				return r;
 		}
@@ -2159,11 +2189,11 @@ static int amdgpu_post_soft_reset(struct
 	int i, r = 0;
 
 	for (i = 0; i < adev->num_ip_blocks; i++) {
-		if (!adev->ip_block_status[i].valid)
+		if (!adev->ip_blocks[i].status.valid)
 			continue;
-		if (adev->ip_block_status[i].hang &&
-		    adev->ip_blocks[i].funcs->post_soft_reset)
-			r = adev->ip_blocks[i].funcs->post_soft_reset(adev);
+		if (adev->ip_blocks[i].status.hang &&
+		    adev->ip_blocks[i].version->funcs->post_soft_reset)
+			r = adev->ip_blocks[i].version->funcs->post_soft_reset(adev);
 		if (r)
 			return r;
 	}
@@ -2182,7 +2212,7 @@ bool amdgpu_need_backup(struct amdgpu_de
 static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev,
 					   struct amdgpu_ring *ring,
 					   struct amdgpu_bo *bo,
-					   struct fence **fence)
+					   struct dma_fence **fence)
 {
 	uint32_t domain;
 	int r;
@@ -2298,30 +2328,30 @@ retry:
 		if (need_full_reset && amdgpu_need_backup(adev)) {
 			struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
 			struct amdgpu_bo *bo, *tmp;
-			struct fence *fence = NULL, *next = NULL;
+			struct dma_fence *fence = NULL, *next = NULL;
 
 			DRM_INFO("recover vram bo from shadow\n");
 			mutex_lock(&adev->shadow_list_lock);
 			list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
 				amdgpu_recover_vram_from_shadow(adev, ring, bo, &next);
 				if (fence) {
-					r = fence_wait(fence, false);
+					r = dma_fence_wait(fence, false);
 					if (r) {
 						WARN(r, "recovery from shadow isn't comleted\n");
 						break;
 					}
 				}
 
-				fence_put(fence);
+				dma_fence_put(fence);
 				fence = next;
 			}
 			mutex_unlock(&adev->shadow_list_lock);
 			if (fence) {
-				r = fence_wait(fence, false);
+				r = dma_fence_wait(fence, false);
 				if (r)
 					WARN(r, "recovery from shadow isn't comleted\n");
 			}
-			fence_put(fence);
+			dma_fence_put(fence);
 		}
 		for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
 			struct amdgpu_ring *ring = adev->rings[i];
@@ -2471,9 +2501,6 @@ int amdgpu_debugfs_add_files(struct amdg
 	adev->debugfs_count = i;
 #if defined(CONFIG_DEBUG_FS)
 	drm_debugfs_create_files(files, nfiles,
-				 adev->ddev->control->debugfs_root,
-				 adev->ddev->control);
-	drm_debugfs_create_files(files, nfiles,
 				 adev->ddev->primary->debugfs_root,
 				 adev->ddev->primary);
 #endif
@@ -2488,9 +2515,6 @@ static void amdgpu_debugfs_remove_files(
 	for (i = 0; i < adev->debugfs_count; i++) {
 		drm_debugfs_remove_files(adev->debugfs[i].files,
 					 adev->debugfs[i].num_files,
-					 adev->ddev->control);
-		drm_debugfs_remove_files(adev->debugfs[i].files,
-					 adev->debugfs[i].num_files,
 					 adev->ddev->primary);
 	}
 #endif
@@ -2501,7 +2525,7 @@ static void amdgpu_debugfs_remove_files(
 static ssize_t amdgpu_debugfs_regs_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 	bool pm_pg_lock, use_bank;
@@ -2517,6 +2541,13 @@ static ssize_t amdgpu_debugfs_regs_read(
 		se_bank = (*pos >> 24) & 0x3FF;
 		sh_bank = (*pos >> 34) & 0x3FF;
 		instance_bank = (*pos >> 44) & 0x3FF;
+
+		if (se_bank == 0x3FF)
+			se_bank = 0xFFFFFFFF;
+		if (sh_bank == 0x3FF)
+			sh_bank = 0xFFFFFFFF;
+		if (instance_bank == 0x3FF)
+			instance_bank = 0xFFFFFFFF;
 		use_bank = 1;
 	} else {
 		use_bank = 0;
@@ -2525,8 +2556,8 @@ static ssize_t amdgpu_debugfs_regs_read(
 	*pos &= 0x3FFFF;
 
 	if (use_bank) {
-		if (sh_bank >= adev->gfx.config.max_sh_per_se ||
-		    se_bank >= adev->gfx.config.max_shader_engines)
+		if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
+		    (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines))
 			return -EINVAL;
 		mutex_lock(&adev->grbm_idx_mutex);
 		amdgpu_gfx_select_se_sh(adev, se_bank,
@@ -2570,13 +2601,48 @@ end:
 static ssize_t amdgpu_debugfs_regs_write(struct file *f, const char __user *buf,
 					 size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
+	bool pm_pg_lock, use_bank;
+	unsigned instance_bank, sh_bank, se_bank;
 
 	if (size & 0x3 || *pos & 0x3)
 		return -EINVAL;
 
+	/* are we reading registers for which a PG lock is necessary? */
+	pm_pg_lock = (*pos >> 23) & 1;
+
+	if (*pos & (1ULL << 62)) {
+		se_bank = (*pos >> 24) & 0x3FF;
+		sh_bank = (*pos >> 34) & 0x3FF;
+		instance_bank = (*pos >> 44) & 0x3FF;
+
+		if (se_bank == 0x3FF)
+			se_bank = 0xFFFFFFFF;
+		if (sh_bank == 0x3FF)
+			sh_bank = 0xFFFFFFFF;
+		if (instance_bank == 0x3FF)
+			instance_bank = 0xFFFFFFFF;
+		use_bank = 1;
+	} else {
+		use_bank = 0;
+	}
+
+	*pos &= 0x3FFFF;
+
+	if (use_bank) {
+		if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) ||
+		    (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines))
+			return -EINVAL;
+		mutex_lock(&adev->grbm_idx_mutex);
+		amdgpu_gfx_select_se_sh(adev, se_bank,
+					sh_bank, instance_bank);
+	}
+
+	if (pm_pg_lock)
+		mutex_lock(&adev->pm.mutex);
+
 	while (size) {
 		uint32_t value;
 
@@ -2595,13 +2661,21 @@ static ssize_t amdgpu_debugfs_regs_write
 		size -= 4;
 	}
 
+	if (use_bank) {
+		amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+		mutex_unlock(&adev->grbm_idx_mutex);
+	}
+
+	if (pm_pg_lock)
+		mutex_unlock(&adev->pm.mutex);
+
 	return result;
 }
 
 static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -2628,7 +2702,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
 static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user *buf,
 					 size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -2656,7 +2730,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_
 static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -2683,7 +2757,7 @@ static ssize_t amdgpu_debugfs_regs_didt_
 static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user *buf,
 					 size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -2711,7 +2785,7 @@ static ssize_t amdgpu_debugfs_regs_didt_
 static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -2738,7 +2812,7 @@ static ssize_t amdgpu_debugfs_regs_smc_r
 static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user *buf,
 					 size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -2766,7 +2840,7 @@ static ssize_t amdgpu_debugfs_regs_smc_w
 static ssize_t amdgpu_debugfs_gca_config_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 	uint32_t *config, no_regs = 0;
@@ -2836,7 +2910,7 @@ static ssize_t amdgpu_debugfs_gca_config
 static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	int idx, r;
 	int32_t value;
 
@@ -2857,6 +2931,116 @@ static ssize_t amdgpu_debugfs_sensor_rea
 	return !r ? 4 : r;
 }
 
+static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf,
+					size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	int r, x;
+	ssize_t result=0;
+	uint32_t offset, se, sh, cu, wave, simd, data[32];
+
+	if (size & 3 || *pos & 3)
+		return -EINVAL;
+
+	/* decode offset */
+	offset = (*pos & 0x7F);
+	se = ((*pos >> 7) & 0xFF);
+	sh = ((*pos >> 15) & 0xFF);
+	cu = ((*pos >> 23) & 0xFF);
+	wave = ((*pos >> 31) & 0xFF);
+	simd = ((*pos >> 37) & 0xFF);
+
+	/* switch to the specific se/sh/cu */
+	mutex_lock(&adev->grbm_idx_mutex);
+	amdgpu_gfx_select_se_sh(adev, se, sh, cu);
+
+	x = 0;
+	if (adev->gfx.funcs->read_wave_data)
+		adev->gfx.funcs->read_wave_data(adev, simd, wave, data, &x);
+
+	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+	mutex_unlock(&adev->grbm_idx_mutex);
+
+	if (!x)
+		return -EINVAL;
+
+	while (size && (offset < x * 4)) {
+		uint32_t value;
+
+		value = data[offset >> 2];
+		r = put_user(value, (uint32_t *)buf);
+		if (r)
+			return r;
+
+		result += 4;
+		buf += 4;
+		offset += 4;
+		size -= 4;
+	}
+
+	return result;
+}
+
+static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf,
+					size_t size, loff_t *pos)
+{
+	struct amdgpu_device *adev = f->f_inode->i_private;
+	int r;
+	ssize_t result = 0;
+	uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data;
+
+	if (size & 3 || *pos & 3)
+		return -EINVAL;
+
+	/* decode offset */
+	offset = (*pos & 0xFFF);       /* in dwords */
+	se = ((*pos >> 12) & 0xFF);
+	sh = ((*pos >> 20) & 0xFF);
+	cu = ((*pos >> 28) & 0xFF);
+	wave = ((*pos >> 36) & 0xFF);
+	simd = ((*pos >> 44) & 0xFF);
+	thread = ((*pos >> 52) & 0xFF);
+	bank = ((*pos >> 60) & 1);
+
+	data = kmalloc_array(1024, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* switch to the specific se/sh/cu */
+	mutex_lock(&adev->grbm_idx_mutex);
+	amdgpu_gfx_select_se_sh(adev, se, sh, cu);
+
+	if (bank == 0) {
+		if (adev->gfx.funcs->read_wave_vgprs)
+			adev->gfx.funcs->read_wave_vgprs(adev, simd, wave, thread, offset, size>>2, data);
+	} else {
+		if (adev->gfx.funcs->read_wave_sgprs)
+			adev->gfx.funcs->read_wave_sgprs(adev, simd, wave, offset, size>>2, data);
+	}
+
+	amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
+	mutex_unlock(&adev->grbm_idx_mutex);
+
+	while (size) {
+		uint32_t value;
+
+		value = data[offset++];
+		r = put_user(value, (uint32_t *)buf);
+		if (r) {
+			result = r;
+			goto err;
+		}
+
+		result += 4;
+		buf += 4;
+		size -= 4;
+	}
+
+err:
+	kfree(data);
+	return result;
+}
+
 static const struct file_operations amdgpu_debugfs_regs_fops = {
 	.owner = THIS_MODULE,
 	.read = amdgpu_debugfs_regs_read,
@@ -2894,6 +3078,17 @@ static const struct file_operations amdg
 	.llseek = default_llseek
 };
 
+static const struct file_operations amdgpu_debugfs_wave_fops = {
+	.owner = THIS_MODULE,
+	.read = amdgpu_debugfs_wave_read,
+	.llseek = default_llseek
+};
+static const struct file_operations amdgpu_debugfs_gpr_fops = {
+	.owner = THIS_MODULE,
+	.read = amdgpu_debugfs_gpr_read,
+	.llseek = default_llseek
+};
+
 static const struct file_operations *debugfs_regs[] = {
 	&amdgpu_debugfs_regs_fops,
 	&amdgpu_debugfs_regs_didt_fops,
@@ -2901,6 +3096,8 @@ static const struct file_operations *deb
 	&amdgpu_debugfs_regs_smc_fops,
 	&amdgpu_debugfs_gca_config_fops,
 	&amdgpu_debugfs_sensors_fops,
+	&amdgpu_debugfs_wave_fops,
+	&amdgpu_debugfs_gpr_fops,
 };
 
 static const char *debugfs_regs_names[] = {
@@ -2910,6 +3107,8 @@ static const char *debugfs_regs_names[]
 	"amdgpu_regs_smc",
 	"amdgpu_gca_config",
 	"amdgpu_sensors",
+	"amdgpu_wave",
+	"amdgpu_gpr",
 };
 
 static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,29 +35,29 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_edid.h>
 
-static void amdgpu_flip_callback(struct fence *f, struct fence_cb *cb)
+static void amdgpu_flip_callback(struct dma_fence *f, struct dma_fence_cb *cb)
 {
 	struct amdgpu_flip_work *work =
 		container_of(cb, struct amdgpu_flip_work, cb);
 
-	fence_put(f);
+	dma_fence_put(f);
 	schedule_work(&work->flip_work.work);
 }
 
 static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work,
-				     struct fence **f)
+				     struct dma_fence **f)
 {
-	struct fence *fence= *f;
+	struct dma_fence *fence= *f;
 
 	if (fence == NULL)
 		return false;
 
 	*f = NULL;
 
-	if (!fence_add_callback(fence, &work->cb, amdgpu_flip_callback))
+	if (!dma_fence_add_callback(fence, &work->cb, amdgpu_flip_callback))
 		return true;
 
-	fence_put(fence);
+	dma_fence_put(fence);
 	return false;
 }
 
@@ -68,9 +68,9 @@ static void amdgpu_flip_work_func(struct
 	struct amdgpu_flip_work *work =
 		container_of(delayed_work, struct amdgpu_flip_work, flip_work);
 	struct amdgpu_device *adev = work->adev;
-	struct amdgpu_crtc *amdgpuCrtc = adev->mode_info.crtcs[work->crtc_id];
+	struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[work->crtc_id];
 
-	struct drm_crtc *crtc = &amdgpuCrtc->base;
+	struct drm_crtc *crtc = &amdgpu_crtc->base;
 	unsigned long flags;
 	unsigned i;
 	int vpos, hpos;
@@ -85,14 +85,14 @@ static void amdgpu_flip_work_func(struct
 	/* Wait until we're out of the vertical blank period before the one
 	 * targeted by the flip
 	 */
-	if (amdgpuCrtc->enabled &&
+	if (amdgpu_crtc->enabled &&
 	    (amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0,
 					&vpos, &hpos, NULL, NULL,
 					&crtc->hwmode)
 	     & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
 	    (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
 	    (int)(work->target_vblank -
-		  amdgpu_get_vblank_counter_kms(adev->ddev, amdgpuCrtc->crtc_id)) > 0) {
+		  amdgpu_get_vblank_counter_kms(adev->ddev, amdgpu_crtc->crtc_id)) > 0) {
 		schedule_delayed_work(&work->flip_work, usecs_to_jiffies(1000));
 		return;
 	}
@@ -104,12 +104,12 @@ static void amdgpu_flip_work_func(struct
 	adev->mode_info.funcs->page_flip(adev, work->crtc_id, work->base, work->async);
 
 	/* Set the flip status */
-	amdgpuCrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
+	amdgpu_crtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
 	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
 
 
 	DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: %p,\n",
-					 amdgpuCrtc->crtc_id, amdgpuCrtc, work);
+					 amdgpu_crtc->crtc_id, amdgpu_crtc, work);
 
 }
 
@@ -187,7 +187,7 @@ int amdgpu_crtc_page_flip_target(struct
 		goto cleanup;
 	}
 
-	r = amdgpu_bo_pin_restricted(new_abo, AMDGPU_GEM_DOMAIN_VRAM, 0, 0, &base);
+	r = amdgpu_bo_pin(new_abo, AMDGPU_GEM_DOMAIN_VRAM, &base);
 	if (unlikely(r != 0)) {
 		r = -EINVAL;
 		DRM_ERROR("failed to pin new abo buffer before flip\n");
@@ -244,9 +244,9 @@ unreserve:
 
 cleanup:
 	amdgpu_bo_unref(&work->old_abo);
-	fence_put(work->excl);
+	dma_fence_put(work->excl);
 	for (i = 0; i < work->shared_count; ++i)
-		fence_put(work->shared[i]);
+		dma_fence_put(work->shared[i]);
 	kfree(work->shared);
 	kfree(work);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c	2017-02-12 16:03:20.000000000 -0500
@@ -553,9 +553,10 @@ int amdgpu_parse_extended_power_table(st
 				entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *)
 					((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record));
 			}
-			for (i = 0; i < states->numEntries; i++) {
-				if (i >= AMDGPU_MAX_VCE_LEVELS)
-					break;
+			adev->pm.dpm.num_of_vce_states =
+					states->numEntries > AMD_MAX_VCE_LEVELS ?
+					AMD_MAX_VCE_LEVELS : states->numEntries;
+			for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
 				vce_clk = (VCEClockInfo *)
 					((u8 *)&array->entries[0] +
 					 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo)));
@@ -955,3 +956,12 @@ u8 amdgpu_encode_pci_lane_width(u32 lane
 
 	return encoded_lanes[lanes];
 }
+
+struct amd_vce_state*
+amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx)
+{
+	if (idx < adev->pm.dpm.num_of_vce_states)
+		return &adev->pm.dpm.vce_states[idx];
+
+	return NULL;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,453 @@
 #ifndef __AMDGPU_DPM_H__
 #define __AMDGPU_DPM_H__
 
+enum amdgpu_int_thermal_type {
+	THERMAL_TYPE_NONE,
+	THERMAL_TYPE_EXTERNAL,
+	THERMAL_TYPE_EXTERNAL_GPIO,
+	THERMAL_TYPE_RV6XX,
+	THERMAL_TYPE_RV770,
+	THERMAL_TYPE_ADT7473_WITH_INTERNAL,
+	THERMAL_TYPE_EVERGREEN,
+	THERMAL_TYPE_SUMO,
+	THERMAL_TYPE_NI,
+	THERMAL_TYPE_SI,
+	THERMAL_TYPE_EMC2103_WITH_INTERNAL,
+	THERMAL_TYPE_CI,
+	THERMAL_TYPE_KV,
+};
+
+enum amdgpu_dpm_auto_throttle_src {
+	AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL,
+	AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL
+};
+
+enum amdgpu_dpm_event_src {
+	AMDGPU_DPM_EVENT_SRC_ANALOG = 0,
+	AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1,
+	AMDGPU_DPM_EVENT_SRC_DIGITAL = 2,
+	AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
+	AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
+};
+
+#define SCLK_DEEP_SLEEP_MASK 0x8
+
+struct amdgpu_ps {
+	u32 caps; /* vbios flags */
+	u32 class; /* vbios flags */
+	u32 class2; /* vbios flags */
+	/* UVD clocks */
+	u32 vclk;
+	u32 dclk;
+	/* VCE clocks */
+	u32 evclk;
+	u32 ecclk;
+	bool vce_active;
+	enum amd_vce_level vce_level;
+	/* asic priv */
+	void *ps_priv;
+};
+
+struct amdgpu_dpm_thermal {
+	/* thermal interrupt work */
+	struct work_struct work;
+	/* low temperature threshold */
+	int                min_temp;
+	/* high temperature threshold */
+	int                max_temp;
+	/* was last interrupt low to high or high to low */
+	bool               high_to_low;
+	/* interrupt source */
+	struct amdgpu_irq_src	irq;
+};
+
+enum amdgpu_clk_action
+{
+	AMDGPU_SCLK_UP = 1,
+	AMDGPU_SCLK_DOWN
+};
+
+struct amdgpu_blacklist_clocks
+{
+	u32 sclk;
+	u32 mclk;
+	enum amdgpu_clk_action action;
+};
+
+struct amdgpu_clock_and_voltage_limits {
+	u32 sclk;
+	u32 mclk;
+	u16 vddc;
+	u16 vddci;
+};
+
+struct amdgpu_clock_array {
+	u32 count;
+	u32 *values;
+};
+
+struct amdgpu_clock_voltage_dependency_entry {
+	u32 clk;
+	u16 v;
+};
+
+struct amdgpu_clock_voltage_dependency_table {
+	u32 count;
+	struct amdgpu_clock_voltage_dependency_entry *entries;
+};
+
+union amdgpu_cac_leakage_entry {
+	struct {
+		u16 vddc;
+		u32 leakage;
+	};
+	struct {
+		u16 vddc1;
+		u16 vddc2;
+		u16 vddc3;
+	};
+};
+
+struct amdgpu_cac_leakage_table {
+	u32 count;
+	union amdgpu_cac_leakage_entry *entries;
+};
+
+struct amdgpu_phase_shedding_limits_entry {
+	u16 voltage;
+	u32 sclk;
+	u32 mclk;
+};
+
+struct amdgpu_phase_shedding_limits_table {
+	u32 count;
+	struct amdgpu_phase_shedding_limits_entry *entries;
+};
+
+struct amdgpu_uvd_clock_voltage_dependency_entry {
+	u32 vclk;
+	u32 dclk;
+	u16 v;
+};
+
+struct amdgpu_uvd_clock_voltage_dependency_table {
+	u8 count;
+	struct amdgpu_uvd_clock_voltage_dependency_entry *entries;
+};
+
+struct amdgpu_vce_clock_voltage_dependency_entry {
+	u32 ecclk;
+	u32 evclk;
+	u16 v;
+};
+
+struct amdgpu_vce_clock_voltage_dependency_table {
+	u8 count;
+	struct amdgpu_vce_clock_voltage_dependency_entry *entries;
+};
+
+struct amdgpu_ppm_table {
+	u8 ppm_design;
+	u16 cpu_core_number;
+	u32 platform_tdp;
+	u32 small_ac_platform_tdp;
+	u32 platform_tdc;
+	u32 small_ac_platform_tdc;
+	u32 apu_tdp;
+	u32 dgpu_tdp;
+	u32 dgpu_ulv_power;
+	u32 tj_max;
+};
+
+struct amdgpu_cac_tdp_table {
+	u16 tdp;
+	u16 configurable_tdp;
+	u16 tdc;
+	u16 battery_power_limit;
+	u16 small_power_limit;
+	u16 low_cac_leakage;
+	u16 high_cac_leakage;
+	u16 maximum_power_delivery_limit;
+};
+
+struct amdgpu_dpm_dynamic_state {
+	struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk;
+	struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk;
+	struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk;
+	struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk;
+	struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk;
+	struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table;
+	struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table;
+	struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table;
+	struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table;
+	struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk;
+	struct amdgpu_clock_array valid_sclk_values;
+	struct amdgpu_clock_array valid_mclk_values;
+	struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc;
+	struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac;
+	u32 mclk_sclk_ratio;
+	u32 sclk_mclk_delta;
+	u16 vddc_vddci_delta;
+	u16 min_vddc_for_pcie_gen2;
+	struct amdgpu_cac_leakage_table cac_leakage_table;
+	struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table;
+	struct amdgpu_ppm_table *ppm_table;
+	struct amdgpu_cac_tdp_table *cac_tdp_table;
+};
+
+struct amdgpu_dpm_fan {
+	u16 t_min;
+	u16 t_med;
+	u16 t_high;
+	u16 pwm_min;
+	u16 pwm_med;
+	u16 pwm_high;
+	u8 t_hyst;
+	u32 cycle_delay;
+	u16 t_max;
+	u8 control_mode;
+	u16 default_max_fan_pwm;
+	u16 default_fan_output_sensitivity;
+	u16 fan_output_sensitivity;
+	bool ucode_fan_control;
+};
+
+enum amdgpu_pcie_gen {
+	AMDGPU_PCIE_GEN1 = 0,
+	AMDGPU_PCIE_GEN2 = 1,
+	AMDGPU_PCIE_GEN3 = 2,
+	AMDGPU_PCIE_GEN_INVALID = 0xffff
+};
+
+enum amdgpu_dpm_forced_level {
+	AMDGPU_DPM_FORCED_LEVEL_AUTO = 0,
+	AMDGPU_DPM_FORCED_LEVEL_LOW = 1,
+	AMDGPU_DPM_FORCED_LEVEL_HIGH = 2,
+	AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3,
+};
+
+struct amdgpu_dpm_funcs {
+	int (*get_temperature)(struct amdgpu_device *adev);
+	int (*pre_set_power_state)(struct amdgpu_device *adev);
+	int (*set_power_state)(struct amdgpu_device *adev);
+	void (*post_set_power_state)(struct amdgpu_device *adev);
+	void (*display_configuration_changed)(struct amdgpu_device *adev);
+	u32 (*get_sclk)(struct amdgpu_device *adev, bool low);
+	u32 (*get_mclk)(struct amdgpu_device *adev, bool low);
+	void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps);
+	void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m);
+	int (*force_performance_level)(struct amdgpu_device *adev, enum amdgpu_dpm_forced_level level);
+	bool (*vblank_too_short)(struct amdgpu_device *adev);
+	void (*powergate_uvd)(struct amdgpu_device *adev, bool gate);
+	void (*powergate_vce)(struct amdgpu_device *adev, bool gate);
+	void (*enable_bapm)(struct amdgpu_device *adev, bool enable);
+	void (*set_fan_control_mode)(struct amdgpu_device *adev, u32 mode);
+	u32 (*get_fan_control_mode)(struct amdgpu_device *adev);
+	int (*set_fan_speed_percent)(struct amdgpu_device *adev, u32 speed);
+	int (*get_fan_speed_percent)(struct amdgpu_device *adev, u32 *speed);
+	int (*force_clock_level)(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t mask);
+	int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf);
+	int (*get_sclk_od)(struct amdgpu_device *adev);
+	int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value);
+	int (*get_mclk_od)(struct amdgpu_device *adev);
+	int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value);
+	int (*check_state_equal)(struct amdgpu_device *adev,
+				struct amdgpu_ps *cps,
+				struct amdgpu_ps *rps,
+				bool *equal);
+
+	struct amd_vce_state* (*get_vce_clock_state)(struct amdgpu_device *adev, unsigned idx);
+};
+
+#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
+#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev))
+#define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev))
+#define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev))
+#define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps))
+#define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev))
+#define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e))
+
+#define amdgpu_dpm_read_sensor(adev, idx, value) \
+	((adev)->pp_enabled ? \
+		(adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value)) : \
+		-EINVAL)
+
+#define amdgpu_dpm_get_temperature(adev) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \
+	      (adev)->pm.funcs->get_temperature((adev)))
+
+#define amdgpu_dpm_set_fan_control_mode(adev, m) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \
+	      (adev)->pm.funcs->set_fan_control_mode((adev), (m)))
+
+#define amdgpu_dpm_get_fan_control_mode(adev) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \
+	      (adev)->pm.funcs->get_fan_control_mode((adev)))
+
+#define amdgpu_dpm_set_fan_speed_percent(adev, s) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
+	      (adev)->pm.funcs->set_fan_speed_percent((adev), (s)))
+
+#define amdgpu_dpm_get_fan_speed_percent(adev, s) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
+	      (adev)->pm.funcs->get_fan_speed_percent((adev), (s)))
+
+#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_fan_speed_rpm((adev)->powerplay.pp_handle, (s)) : \
+	      -EINVAL)
+
+#define amdgpu_dpm_get_sclk(adev, l) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \
+		(adev)->pm.funcs->get_sclk((adev), (l)))
+
+#define amdgpu_dpm_get_mclk(adev, l)  \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \
+	      (adev)->pm.funcs->get_mclk((adev), (l)))
+
+
+#define amdgpu_dpm_force_performance_level(adev, l) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \
+	      (adev)->pm.funcs->force_performance_level((adev), (l)))
+
+#define amdgpu_dpm_powergate_uvd(adev, g) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \
+	      (adev)->pm.funcs->powergate_uvd((adev), (g)))
+
+#define amdgpu_dpm_powergate_vce(adev, g) \
+	((adev)->pp_enabled ?						\
+	      (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \
+	      (adev)->pm.funcs->powergate_vce((adev), (g)))
+
+#define amdgpu_dpm_get_current_power_state(adev) \
+	(adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_get_performance_level(adev) \
+	(adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_get_pp_num_states(adev, data) \
+	(adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)
+
+#define amdgpu_dpm_get_pp_table(adev, table) \
+	(adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)
+
+#define amdgpu_dpm_set_pp_table(adev, buf, size) \
+	(adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)
+
+#define amdgpu_dpm_print_clock_levels(adev, type, buf) \
+	(adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)
+
+#define amdgpu_dpm_force_clock_level(adev, type, level) \
+		(adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)
+
+#define amdgpu_dpm_get_sclk_od(adev) \
+	(adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)
+
+#define amdgpu_dpm_set_sclk_od(adev, value) \
+	(adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)
+
+#define amdgpu_dpm_get_mclk_od(adev) \
+	((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle))
+
+#define amdgpu_dpm_set_mclk_od(adev, value) \
+	((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value))
+
+#define amdgpu_dpm_dispatch_task(adev, event_id, input, output)		\
+	(adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
+
+#define amgdpu_dpm_check_state_equal(adev, cps, rps, equal) (adev)->pm.funcs->check_state_equal((adev), (cps),(rps),(equal))
+
+#define amdgpu_dpm_get_vce_clock_state(adev, i)				\
+	((adev)->pp_enabled ?						\
+	 (adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i)) : \
+	 (adev)->pm.funcs->get_vce_clock_state((adev), (i)))
+
+struct amdgpu_dpm {
+	struct amdgpu_ps        *ps;
+	/* number of valid power states */
+	int                     num_ps;
+	/* current power state that is active */
+	struct amdgpu_ps        *current_ps;
+	/* requested power state */
+	struct amdgpu_ps        *requested_ps;
+	/* boot up power state */
+	struct amdgpu_ps        *boot_ps;
+	/* default uvd power state */
+	struct amdgpu_ps        *uvd_ps;
+	/* vce requirements */
+	u32                  num_of_vce_states;
+	struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS];
+	enum amd_vce_level vce_level;
+	enum amd_pm_state_type state;
+	enum amd_pm_state_type user_state;
+	enum amd_pm_state_type last_state;
+	enum amd_pm_state_type last_user_state;
+	u32                     platform_caps;
+	u32                     voltage_response_time;
+	u32                     backbias_response_time;
+	void                    *priv;
+	u32			new_active_crtcs;
+	int			new_active_crtc_count;
+	u32			current_active_crtcs;
+	int			current_active_crtc_count;
+	struct amdgpu_dpm_dynamic_state dyn_state;
+	struct amdgpu_dpm_fan fan;
+	u32 tdp_limit;
+	u32 near_tdp_limit;
+	u32 near_tdp_limit_adjusted;
+	u32 sq_ramping_threshold;
+	u32 cac_leakage;
+	u16 tdp_od_limit;
+	u32 tdp_adjustment;
+	u16 load_line_slope;
+	bool power_control;
+	bool ac_power;
+	/* special states active */
+	bool                    thermal_active;
+	bool                    uvd_active;
+	bool                    vce_active;
+	/* thermal handling */
+	struct amdgpu_dpm_thermal thermal;
+	/* forced levels */
+	enum amdgpu_dpm_forced_level forced_level;
+};
+
+struct amdgpu_pm {
+	struct mutex		mutex;
+	u32                     current_sclk;
+	u32                     current_mclk;
+	u32                     default_sclk;
+	u32                     default_mclk;
+	struct amdgpu_i2c_chan *i2c_bus;
+	/* internal thermal controller on rv6xx+ */
+	enum amdgpu_int_thermal_type int_thermal_type;
+	struct device	        *int_hwmon_dev;
+	/* fan control parameters */
+	bool                    no_fan;
+	u8                      fan_pulses_per_revolution;
+	u8                      fan_min_rpm;
+	u8                      fan_max_rpm;
+	/* dpm */
+	bool                    dpm_enabled;
+	bool                    sysfs_initialized;
+	struct amdgpu_dpm       dpm;
+	const struct firmware	*fw;	/* SMC firmware */
+	uint32_t                fw_version;
+	const struct amdgpu_dpm_funcs *funcs;
+	uint32_t                pcie_gen_mask;
+	uint32_t                pcie_mlw_mask;
+	struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */
+};
+
 #define R600_SSTU_DFLT                               0
 #define R600_SST_DFLT                                0x00C8
 
@@ -82,4 +529,7 @@ u16 amdgpu_get_pcie_lane_support(struct
 				 u16 default_lanes);
 u8 amdgpu_encode_pci_lane_width(u32 lanes);
 
+struct amd_vce_state*
+amdgpu_get_vce_clock_state(struct amdgpu_device *adev, unsigned idx);
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,9 +58,10 @@
  * - 3.6.0 - kmd involves use CONTEXT_CONTROL in ring buffer.
  * - 3.7.0 - Add support for VCE clock list packet
  * - 3.8.0 - Add support raster config init in the kernel
+ * - 3.9.0 - Add support for memory query info about VRAM and GTT.
  */
 #define KMS_DRIVER_MAJOR	3
-#define KMS_DRIVER_MINOR	8
+#define KMS_DRIVER_MINOR	9
 #define KMS_DRIVER_PATCHLEVEL	0
 
 int amdgpu_vram_limit = 0;
@@ -85,12 +86,13 @@ int amdgpu_vm_size = 64;
 int amdgpu_vm_block_size = -1;
 int amdgpu_vm_fault_stop = 0;
 int amdgpu_vm_debug = 0;
+int amdgpu_vram_page_split = 1024;
 int amdgpu_exp_hw_support = 0;
 int amdgpu_sched_jobs = 32;
 int amdgpu_sched_hw_submission = 2;
 int amdgpu_powerplay = -1;
-int amdgpu_powercontainment = 1;
-int amdgpu_sclk_deep_sleep_en = 1;
+int amdgpu_no_evict = 0;
+int amdgpu_direct_gma_size = 0;
 unsigned amdgpu_pcie_gen_cap = 0;
 unsigned amdgpu_pcie_lane_cap = 0;
 unsigned amdgpu_cg_mask = 0xffffffff;
@@ -165,6 +167,9 @@ module_param_named(vm_fault_stop, amdgpu
 MODULE_PARM_DESC(vm_debug, "Debug VM handling (0 = disabled (default), 1 = enabled)");
 module_param_named(vm_debug, amdgpu_vm_debug, int, 0644);
 
+MODULE_PARM_DESC(vram_page_split, "Number of pages after we split VRAM allocations (default 1024, -1 = disable)");
+module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444);
+
 MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))");
 module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444);
 
@@ -177,14 +182,14 @@ module_param_named(sched_hw_submission,
 MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))");
 module_param_named(powerplay, amdgpu_powerplay, int, 0444);
 
-MODULE_PARM_DESC(powercontainment, "Power Containment (1 = enable (default), 0 = disable)");
-module_param_named(powercontainment, amdgpu_powercontainment, int, 0444);
-
 MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))");
 module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444);
 
-MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)");
-module_param_named(sclkdeepsleep, amdgpu_sclk_deep_sleep_en, int, 0444);
+MODULE_PARM_DESC(no_evict, "Support pinning request from user space (1 = enable, 0 = disable (default))");
+module_param_named(no_evict, amdgpu_no_evict, int, 0444);
+
+MODULE_PARM_DESC(direct_gma_size, "Direct GMA size in megabytes (max 96MB)");
+module_param_named(direct_gma_size, amdgpu_direct_gma_size, int, 0444);
 
 MODULE_PARM_DESC(pcie_gen_cap, "PCIE Gen Caps (0: autodetect (default))");
 module_param_named(pcie_gen_cap, amdgpu_pcie_gen_cap, uint, 0444);
@@ -201,7 +206,8 @@ module_param_named(pg_mask, amdgpu_pg_ma
 MODULE_PARM_DESC(disable_cu, "Disable CUs (se.sh.cu,...)");
 module_param_named(disable_cu, amdgpu_disable_cu, charp, 0444);
 
-MODULE_PARM_DESC(virtual_display, "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x;xxxx:xx:xx.x)");
+MODULE_PARM_DESC(virtual_display,
+		 "Enable virtual display feature (the virtual_display will be set like xxxx:xx:xx.x,x;xxxx:xx:xx.x,x)");
 module_param_named(virtual_display, amdgpu_virtual_display, charp, 0444);
 
 static const struct pci_device_id pciidlist[] = {
@@ -381,6 +387,7 @@ static const struct pci_device_id pciidl
 	{0x1002, 0x6939, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TONGA},
 	/* fiji */
 	{0x1002, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI},
+	{0x1002, 0x730F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_FIJI},
 	/* carrizo */
 	{0x1002, 0x9870, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
 	{0x1002, 0x9874, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CARRIZO|AMD_IS_APU},
@@ -411,6 +418,13 @@ static const struct pci_device_id pciidl
 	{0x1002, 0x67CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
 	{0x1002, 0x67CC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
 	{0x1002, 0x67CF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS10},
+	/* Polaris12 */
+	{0x1002, 0x6980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+	{0x1002, 0x6981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+	{0x1002, 0x6985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+	{0x1002, 0x6986, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+	{0x1002, 0x6987, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
+	{0x1002, 0x699F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_POLARIS12},
 
 	{0, 0, 0}
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,27 +75,21 @@ amdgpufb_release(struct fb_info *info, i
 
 static struct fb_ops amdgpufb_ops = {
 	.owner = THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_open = amdgpufb_open,
 	.fb_release = amdgpufb_release,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 
-int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tiled)
+int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int cpp, bool tiled)
 {
 	int aligned = width;
 	int pitch_mask = 0;
 
-	switch (bpp / 8) {
+	switch (cpp) {
 	case 1:
 		pitch_mask = 255;
 		break;
@@ -110,7 +104,7 @@ int amdgpu_align_pitch(struct amdgpu_dev
 
 	aligned += pitch_mask;
 	aligned &= ~pitch_mask;
-	return aligned;
+	return aligned * cpp;
 }
 
 static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
@@ -139,20 +133,21 @@ static int amdgpufb_create_pinned_object
 	int ret;
 	int aligned_size, size;
 	int height = mode_cmd->height;
-	u32 bpp, depth;
+	u32 cpp;
 
-	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+	cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
 
 	/* need to align pitch with crtc limits */
-	mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, bpp,
-						  fb_tiled) * ((bpp + 1) / 8);
+	mode_cmd->pitches[0] = amdgpu_align_pitch(adev, mode_cmd->width, cpp,
+						  fb_tiled);
 
 	height = ALIGN(mode_cmd->height, 8);
 	size = mode_cmd->pitches[0] * height;
 	aligned_size = ALIGN(size, PAGE_SIZE);
 	ret = amdgpu_gem_object_create(adev, aligned_size, 0,
 				       AMDGPU_GEM_DOMAIN_VRAM,
-				       AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+				       AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+				       AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 				       true, &gobj);
 	if (ret) {
 		printk(KERN_ERR "failed to allocate framebuffer (%d)\n",
@@ -176,7 +171,7 @@ static int amdgpufb_create_pinned_object
 	}
 
 
-	ret = amdgpu_bo_pin_restricted(abo, AMDGPU_GEM_DOMAIN_VRAM, 0, 0, NULL);
+	ret = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM, NULL);
 	if (ret) {
 		amdgpu_bo_unreserve(abo);
 		goto out_unref;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@
  */
 
 struct amdgpu_fence {
-	struct fence base;
+	struct dma_fence base;
 
 	/* RB, DMA, etc. */
 	struct amdgpu_ring		*ring;
@@ -74,8 +74,8 @@ void amdgpu_fence_slab_fini(void)
 /*
  * Cast helper
  */
-static const struct fence_ops amdgpu_fence_ops;
-static inline struct amdgpu_fence *to_amdgpu_fence(struct fence *f)
+static const struct dma_fence_ops amdgpu_fence_ops;
+static inline struct amdgpu_fence *to_amdgpu_fence(struct dma_fence *f)
 {
 	struct amdgpu_fence *__f = container_of(f, struct amdgpu_fence, base);
 
@@ -131,11 +131,11 @@ static u32 amdgpu_fence_read(struct amdg
  * Emits a fence command on the requested ring (all asics).
  * Returns 0 on success, -ENOMEM on failure.
  */
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **f)
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f)
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_fence *fence;
-	struct fence *old, **ptr;
+	struct dma_fence *old, **ptr;
 	uint32_t seq;
 
 	fence = kmem_cache_alloc(amdgpu_fence_slab, GFP_KERNEL);
@@ -144,10 +144,10 @@ int amdgpu_fence_emit(struct amdgpu_ring
 
 	seq = ++ring->fence_drv.sync_seq;
 	fence->ring = ring;
-	fence_init(&fence->base, &amdgpu_fence_ops,
-		   &ring->fence_drv.lock,
-		   adev->fence_context + ring->idx,
-		   seq);
+	dma_fence_init(&fence->base, &amdgpu_fence_ops,
+		       &ring->fence_drv.lock,
+		       adev->fence_context + ring->idx,
+		       seq);
 	amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
 			       seq, AMDGPU_FENCE_FLAG_INT);
 
@@ -156,12 +156,12 @@ int amdgpu_fence_emit(struct amdgpu_ring
 	 * emitting the fence would mess up the hardware ring buffer.
 	 */
 	old = rcu_dereference_protected(*ptr, 1);
-	if (old && !fence_is_signaled(old)) {
+	if (old && !dma_fence_is_signaled(old)) {
 		DRM_INFO("rcu slot is busy\n");
-		fence_wait(old, false);
+		dma_fence_wait(old, false);
 	}
 
-	rcu_assign_pointer(*ptr, fence_get(&fence->base));
+	rcu_assign_pointer(*ptr, dma_fence_get(&fence->base));
 
 	*f = &fence->base;
 
@@ -212,7 +212,7 @@ void amdgpu_fence_process(struct amdgpu_
 	seq &= drv->num_fences_mask;
 
 	do {
-		struct fence *fence, **ptr;
+		struct dma_fence *fence, **ptr;
 
 		++last_seq;
 		last_seq &= drv->num_fences_mask;
@@ -225,13 +225,13 @@ void amdgpu_fence_process(struct amdgpu_
 		if (!fence)
 			continue;
 
-		r = fence_signal(fence);
+		r = dma_fence_signal(fence);
 		if (!r)
-			FENCE_TRACE(fence, "signaled from irq context\n");
+			DMA_FENCE_TRACE(fence, "signaled from irq context\n");
 		else
 			BUG();
 
-		fence_put(fence);
+		dma_fence_put(fence);
 	} while (last_seq != seq);
 }
 
@@ -261,7 +261,7 @@ static void amdgpu_fence_fallback(unsign
 int amdgpu_fence_wait_empty(struct amdgpu_ring *ring)
 {
 	uint64_t seq = ACCESS_ONCE(ring->fence_drv.sync_seq);
-	struct fence *fence, **ptr;
+	struct dma_fence *fence, **ptr;
 	int r;
 
 	if (!seq)
@@ -270,14 +270,14 @@ int amdgpu_fence_wait_empty(struct amdgp
 	ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask];
 	rcu_read_lock();
 	fence = rcu_dereference(*ptr);
-	if (!fence || !fence_get_rcu(fence)) {
+	if (!fence || !dma_fence_get_rcu(fence)) {
 		rcu_read_unlock();
 		return 0;
 	}
 	rcu_read_unlock();
 
-	r = fence_wait(fence, false);
-	fence_put(fence);
+	r = dma_fence_wait(fence, false);
+	dma_fence_put(fence);
 	return r;
 }
 
@@ -382,24 +382,27 @@ int amdgpu_fence_driver_init_ring(struct
 	if (!ring->fence_drv.fences)
 		return -ENOMEM;
 
-	timeout = msecs_to_jiffies(amdgpu_lockup_timeout);
-	if (timeout == 0) {
-		/*
-		 * FIXME:
-		 * Delayed workqueue cannot use it directly,
-		 * so the scheduler will not use delayed workqueue if
-		 * MAX_SCHEDULE_TIMEOUT is set.
-		 * Currently keep it simple and silly.
-		 */
-		timeout = MAX_SCHEDULE_TIMEOUT;
-	}
-	r = amd_sched_init(&ring->sched, &amdgpu_sched_ops,
-			   num_hw_submission,
-			   timeout, ring->name);
-	if (r) {
-		DRM_ERROR("Failed to create scheduler on ring %s.\n",
-			  ring->name);
-		return r;
+	/* No need to setup the GPU scheduler for KIQ ring */
+	if (ring->funcs->type != AMDGPU_RING_TYPE_KIQ) {
+		timeout = msecs_to_jiffies(amdgpu_lockup_timeout);
+		if (timeout == 0) {
+			/*
+			 * FIXME:
+			 * Delayed workqueue cannot use it directly,
+			 * so the scheduler will not use delayed workqueue if
+			 * MAX_SCHEDULE_TIMEOUT is set.
+			 * Currently keep it simple and silly.
+			 */
+			timeout = MAX_SCHEDULE_TIMEOUT;
+		}
+		r = amd_sched_init(&ring->sched, &amdgpu_sched_ops,
+				   num_hw_submission,
+				   timeout, ring->name);
+		if (r) {
+			DRM_ERROR("Failed to create scheduler on ring %s.\n",
+				  ring->name);
+			return r;
+		}
 	}
 
 	return 0;
@@ -453,7 +456,7 @@ void amdgpu_fence_driver_fini(struct amd
 		amd_sched_fini(&ring->sched);
 		del_timer_sync(&ring->fence_drv.fallback_timer);
 		for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
-			fence_put(ring->fence_drv.fences[j]);
+			dma_fence_put(ring->fence_drv.fences[j]);
 		kfree(ring->fence_drv.fences);
 		ring->fence_drv.fences = NULL;
 		ring->fence_drv.initialized = false;
@@ -542,12 +545,12 @@ void amdgpu_fence_driver_force_completio
  * Common fence implementation
  */
 
-static const char *amdgpu_fence_get_driver_name(struct fence *fence)
+static const char *amdgpu_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "amdgpu";
 }
 
-static const char *amdgpu_fence_get_timeline_name(struct fence *f)
+static const char *amdgpu_fence_get_timeline_name(struct dma_fence *f)
 {
 	struct amdgpu_fence *fence = to_amdgpu_fence(f);
 	return (const char *)fence->ring->name;
@@ -561,7 +564,7 @@ static const char *amdgpu_fence_get_time
  * to fence_queue that checks if this fence is signaled, and if so it
  * signals the fence and removes itself.
  */
-static bool amdgpu_fence_enable_signaling(struct fence *f)
+static bool amdgpu_fence_enable_signaling(struct dma_fence *f)
 {
 	struct amdgpu_fence *fence = to_amdgpu_fence(f);
 	struct amdgpu_ring *ring = fence->ring;
@@ -569,7 +572,7 @@ static bool amdgpu_fence_enable_signalin
 	if (!timer_pending(&ring->fence_drv.fallback_timer))
 		amdgpu_fence_schedule_fallback(ring);
 
-	FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
+	DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", ring->idx);
 
 	return true;
 }
@@ -583,7 +586,7 @@ static bool amdgpu_fence_enable_signalin
  */
 static void amdgpu_fence_free(struct rcu_head *rcu)
 {
-	struct fence *f = container_of(rcu, struct fence, rcu);
+	struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
 	struct amdgpu_fence *fence = to_amdgpu_fence(f);
 	kmem_cache_free(amdgpu_fence_slab, fence);
 }
@@ -596,16 +599,16 @@ static void amdgpu_fence_free(struct rcu
  * This function is called when the reference count becomes zero.
  * It just RCU schedules freeing up the fence.
  */
-static void amdgpu_fence_release(struct fence *f)
+static void amdgpu_fence_release(struct dma_fence *f)
 {
 	call_rcu(&f->rcu, amdgpu_fence_free);
 }
 
-static const struct fence_ops amdgpu_fence_ops = {
+static const struct dma_fence_ops amdgpu_fence_ops = {
 	.get_driver_name = amdgpu_fence_get_driver_name,
 	.get_timeline_name = amdgpu_fence_get_timeline_name,
 	.enable_signaling = amdgpu_fence_enable_signaling,
-	.wait = fence_default_wait,
+	.wait = dma_fence_default_wait,
 	.release = amdgpu_fence_release,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c	2017-02-12 16:03:20.000000000 -0500
@@ -126,7 +126,8 @@ int amdgpu_gart_table_vram_alloc(struct
 	if (adev->gart.robj == NULL) {
 		r = amdgpu_bo_create(adev, adev->gart.table_size,
 				     PAGE_SIZE, true, AMDGPU_GEM_DOMAIN_VRAM,
-				     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+				     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+				     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 				     NULL, NULL, &adev->gart.robj);
 		if (r) {
 			return r;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -116,10 +116,11 @@ void amdgpu_gem_force_release(struct amd
  * Call from drm_gem_handle_create which appear in both new and open ioctl
  * case.
  */
-int amdgpu_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv)
+int amdgpu_gem_object_open(struct drm_gem_object *obj,
+			   struct drm_file *file_priv)
 {
 	struct amdgpu_bo *abo = gem_to_amdgpu_bo(obj);
-	struct amdgpu_device *adev = abo->adev;
+	struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
 	struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
 	struct amdgpu_vm *vm = &fpriv->vm;
 	struct amdgpu_bo_va *bo_va;
@@ -142,7 +143,7 @@ void amdgpu_gem_object_close(struct drm_
 			     struct drm_file *file_priv)
 {
 	struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
-	struct amdgpu_device *adev = bo->adev;
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
 	struct amdgpu_vm *vm = &fpriv->vm;
 
@@ -407,10 +408,8 @@ int amdgpu_gem_wait_idle_ioctl(struct dr
 		return -ENOENT;
 	}
 	robj = gem_to_amdgpu_bo(gobj);
-	if (timeout == 0)
-		ret = reservation_object_test_signaled_rcu(robj->tbo.resv, true);
-	else
-		ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, timeout);
+	ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true,
+						  timeout);
 
 	/* ret == 0 means not signaled,
 	 * ret > 0 means signaled
@@ -470,6 +469,16 @@ out:
 	return r;
 }
 
+static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
+{
+	unsigned domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
+
+	/* if anything is swapped out don't swap it in here,
+	   just abort and wait for the next CS */
+
+	return domain == AMDGPU_GEM_DOMAIN_CPU ? -ERESTARTSYS : 0;
+}
+
 /**
  * amdgpu_gem_va_update_vm -update the bo_va in its VM
  *
@@ -480,7 +489,8 @@ out:
  * vital here, so they are not reported back to userspace.
  */
 static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
-				    struct amdgpu_bo_va *bo_va, uint32_t operation)
+				    struct amdgpu_bo_va *bo_va,
+				    uint32_t operation)
 {
 	struct ttm_validate_buffer tv, *entry;
 	struct amdgpu_bo_list_entry vm_pd;
@@ -503,7 +513,6 @@ static void amdgpu_gem_va_update_vm(stru
 	if (r)
 		goto error_print;
 
-	amdgpu_vm_get_pt_bos(adev, bo_va->vm, &duplicates);
 	list_for_each_entry(entry, &list, head) {
 		domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
 		/* if anything is swapped out don't swap it in here,
@@ -511,13 +520,10 @@ static void amdgpu_gem_va_update_vm(stru
 		if (domain == AMDGPU_GEM_DOMAIN_CPU)
 			goto error_unreserve;
 	}
-	list_for_each_entry(entry, &duplicates, head) {
-		domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
-		/* if anything is swapped out don't swap it in here,
-		   just abort and wait for the next CS */
-		if (domain == AMDGPU_GEM_DOMAIN_CPU)
-			goto error_unreserve;
-	}
+	r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
+				      NULL);
+	if (r)
+		goto error_unreserve;
 
 	r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
 	if (r)
@@ -538,8 +544,6 @@ error_print:
 		DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
 }
 
-
-
 int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *filp)
 {
@@ -549,7 +553,8 @@ int amdgpu_gem_va_ioctl(struct drm_devic
 	struct amdgpu_fpriv *fpriv = filp->driver_priv;
 	struct amdgpu_bo *abo;
 	struct amdgpu_bo_va *bo_va;
-	struct ttm_validate_buffer tv, tv_pd;
+	struct amdgpu_bo_list_entry vm_pd;
+	struct ttm_validate_buffer tv;
 	struct ww_acquire_ctx ticket;
 	struct list_head list, duplicates;
 	uint32_t invalid_flags, va_flags = 0;
@@ -594,9 +599,7 @@ int amdgpu_gem_va_ioctl(struct drm_devic
 	tv.shared = true;
 	list_add(&tv.head, &list);
 
-	tv_pd.bo = &fpriv->vm.page_directory->tbo;
-	tv_pd.shared = true;
-	list_add(&tv_pd.head, &list);
+	amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd);
 
 	r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
 	if (r) {
@@ -704,7 +707,8 @@ int amdgpu_mode_dumb_create(struct drm_f
 	uint32_t handle;
 	int r;
 
-	args->pitch = amdgpu_align_pitch(adev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
+	args->pitch = amdgpu_align_pitch(adev, args->width,
+					 DIV_ROUND_UP(args->bpp, 8), 0);
 	args->size = (u64)args->pitch * args->height;
 	args->size = ALIGN(args->size, PAGE_SIZE);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@
  */
 #include <drm/drmP.h>
 #include "amdgpu.h"
+#include "amdgpu_gfx.h"
 
 /*
  * GPU scratch registers helpers function.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 int amdgpu_gfx_scratch_get(struct amdgpu_device *adev, uint32_t *reg);
 void amdgpu_gfx_scratch_free(struct amdgpu_device *adev, uint32_t reg);
 
-unsigned amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se, unsigned max_sh);
+void amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se,
+		unsigned max_sh);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -164,10 +164,13 @@ static int amdgpu_gtt_mgr_new(struct ttm
 	spin_unlock(&mgr->lock);
 
 	node = kzalloc(sizeof(*node), GFP_KERNEL);
-	if (!node)
-		return -ENOMEM;
+	if (!node) {
+		r = -ENOMEM;
+		goto err_out;
+	}
 
 	node->start = AMDGPU_BO_INVALID_OFFSET;
+	node->size = mem->num_pages;
 	mem->mm_node = node;
 
 	if (place->fpfn || place->lpfn || place->flags & TTM_PL_FLAG_TOPDOWN) {
@@ -175,12 +178,20 @@ static int amdgpu_gtt_mgr_new(struct ttm
 		if (unlikely(r)) {
 			kfree(node);
 			mem->mm_node = NULL;
+			r = 0;
+			goto err_out;
 		}
 	} else {
 		mem->start = node->start;
 	}
 
 	return 0;
+err_out:
+	spin_lock(&mgr->lock);
+	mgr->available += mem->num_pages;
+	spin_unlock(&mgr->lock);
+
+	return r;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/kref.h>
 #include <linux/interval_tree.h>
 #include <linux/hashtable.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 #include <ttm/ttm_bo_api.h>
 #include <ttm/ttm_bo_driver.h>
@@ -53,7 +53,11 @@
 #include "amdgpu_ucode.h"
 #include "amdgpu_ttm.h"
 #include "amdgpu_gds.h"
+#include "amdgpu_sync.h"
+#include "amdgpu_ring.h"
+#include "amdgpu_vm.h"
 #include "amd_powerplay.h"
+#include "amdgpu_dpm.h"
 #include "amdgpu_acp.h"
 
 #include "gpu_scheduler.h"
@@ -88,15 +92,16 @@ extern int amdgpu_vm_debug;
 extern int amdgpu_sched_jobs;
 extern int amdgpu_sched_hw_submission;
 extern int amdgpu_powerplay;
-extern int amdgpu_powercontainment;
+extern int amdgpu_no_evict;
+extern int amdgpu_direct_gma_size;
 extern unsigned amdgpu_pcie_gen_cap;
 extern unsigned amdgpu_pcie_lane_cap;
 extern unsigned amdgpu_cg_mask;
 extern unsigned amdgpu_pg_mask;
 extern char *amdgpu_disable_cu;
-extern int amdgpu_sclk_deep_sleep_en;
 extern char *amdgpu_virtual_display;
 extern unsigned amdgpu_pp_feature_mask;
+extern int amdgpu_vram_page_split;
 
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS	        3000
 #define AMDGPU_MAX_USEC_TIMEOUT			100000	/* 100 ms */
@@ -107,12 +112,6 @@ extern unsigned amdgpu_pp_feature_mask;
 #define AMDGPUFB_CONN_LIMIT			4
 #define AMDGPU_BIOS_NUM_SCRATCH			8
 
-/* max number of rings */
-#define AMDGPU_MAX_RINGS			16
-#define AMDGPU_MAX_GFX_RINGS			1
-#define AMDGPU_MAX_COMPUTE_RINGS		8
-#define AMDGPU_MAX_VCE_RINGS			3
-
 /* max number of IP instances */
 #define AMDGPU_MAX_SDMA_INSTANCES		2
 
@@ -152,8 +151,6 @@ extern unsigned amdgpu_pp_feature_mask;
 
 struct amdgpu_device;
 struct amdgpu_ib;
-struct amdgpu_vm;
-struct amdgpu_ring;
 struct amdgpu_cs_parser;
 struct amdgpu_job;
 struct amdgpu_irq_src;
@@ -198,21 +195,38 @@ int amdgpu_wait_for_idle(struct amdgpu_d
 bool amdgpu_is_idle(struct amdgpu_device *adev,
 		    enum amd_ip_block_type block_type);
 
+#define AMDGPU_MAX_IP_NUM 16
+
+struct amdgpu_ip_block_status {
+	bool valid;
+	bool sw;
+	bool hw;
+	bool late_initialized;
+	bool hang;
+};
+
 struct amdgpu_ip_block_version {
-	enum amd_ip_block_type type;
-	u32 major;
-	u32 minor;
-	u32 rev;
+	const enum amd_ip_block_type type;
+	const u32 major;
+	const u32 minor;
+	const u32 rev;
 	const struct amd_ip_funcs *funcs;
 };
 
+struct amdgpu_ip_block {
+	struct amdgpu_ip_block_status status;
+	const struct amdgpu_ip_block_version *version;
+};
+
 int amdgpu_ip_block_version_cmp(struct amdgpu_device *adev,
 				enum amd_ip_block_type type,
 				u32 major, u32 minor);
 
-const struct amdgpu_ip_block_version * amdgpu_get_ip_block(
-					struct amdgpu_device *adev,
-					enum amd_ip_block_type type);
+struct amdgpu_ip_block * amdgpu_get_ip_block(struct amdgpu_device *adev,
+					     enum amd_ip_block_type type);
+
+int amdgpu_ip_block_add(struct amdgpu_device *adev,
+			const struct amdgpu_ip_block_version *ip_block_version);
 
 /* provided by hw blocks that can move/clear data.  e.g., gfx or sdma */
 struct amdgpu_buffer_funcs {
@@ -286,47 +300,6 @@ struct amdgpu_ih_funcs {
 	void (*set_rptr)(struct amdgpu_device *adev);
 };
 
-/* provided by hw blocks that expose a ring buffer for commands */
-struct amdgpu_ring_funcs {
-	/* ring read/write ptr handling */
-	u32 (*get_rptr)(struct amdgpu_ring *ring);
-	u32 (*get_wptr)(struct amdgpu_ring *ring);
-	void (*set_wptr)(struct amdgpu_ring *ring);
-	/* validating and patching of IBs */
-	int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx);
-	/* command emit functions */
-	void (*emit_ib)(struct amdgpu_ring *ring,
-			struct amdgpu_ib *ib,
-			unsigned vm_id, bool ctx_switch);
-	void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
-			   uint64_t seq, unsigned flags);
-	void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
-	void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
-			      uint64_t pd_addr);
-	void (*emit_hdp_flush)(struct amdgpu_ring *ring);
-	void (*emit_hdp_invalidate)(struct amdgpu_ring *ring);
-	void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
-				uint32_t gds_base, uint32_t gds_size,
-				uint32_t gws_base, uint32_t gws_size,
-				uint32_t oa_base, uint32_t oa_size);
-	/* testing functions */
-	int (*test_ring)(struct amdgpu_ring *ring);
-	int (*test_ib)(struct amdgpu_ring *ring, long timeout);
-	/* insert NOP packets */
-	void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
-	/* pad the indirect buffer to the necessary number of dw */
-	void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
-	unsigned (*init_cond_exec)(struct amdgpu_ring *ring);
-	void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset);
-	/* note usage for clock and power gating */
-	void (*begin_use)(struct amdgpu_ring *ring);
-	void (*end_use)(struct amdgpu_ring *ring);
-	void (*emit_switch_buffer) (struct amdgpu_ring *ring);
-	void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
-	unsigned (*get_emit_ib_size) (struct amdgpu_ring *ring);
-	unsigned (*get_dma_frame_size) (struct amdgpu_ring *ring);
-};
-
 /*
  * BIOS.
  */
@@ -364,47 +337,6 @@ struct amdgpu_clock {
 };
 
 /*
- * Fences.
- */
-struct amdgpu_fence_driver {
-	uint64_t			gpu_addr;
-	volatile uint32_t		*cpu_addr;
-	/* sync_seq is protected by ring emission lock */
-	uint32_t			sync_seq;
-	atomic_t			last_seq;
-	bool				initialized;
-	struct amdgpu_irq_src		*irq_src;
-	unsigned			irq_type;
-	struct timer_list		fallback_timer;
-	unsigned			num_fences_mask;
-	spinlock_t			lock;
-	struct fence			**fences;
-};
-
-/* some special values for the owner field */
-#define AMDGPU_FENCE_OWNER_UNDEFINED	((void*)0ul)
-#define AMDGPU_FENCE_OWNER_VM		((void*)1ul)
-
-#define AMDGPU_FENCE_FLAG_64BIT         (1 << 0)
-#define AMDGPU_FENCE_FLAG_INT           (1 << 1)
-
-int amdgpu_fence_driver_init(struct amdgpu_device *adev);
-void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
-void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev);
-
-int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
-				  unsigned num_hw_submission);
-int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
-				   struct amdgpu_irq_src *irq_src,
-				   unsigned irq_type);
-void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
-void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct fence **fence);
-void amdgpu_fence_process(struct amdgpu_ring *ring);
-int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
-unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
-
-/*
  * BO.
  */
 struct amdgpu_bo_list_entry {
@@ -427,7 +359,7 @@ struct amdgpu_bo_va_mapping {
 struct amdgpu_bo_va {
 	/* protected by bo being reserved */
 	struct list_head		bo_list;
-	struct fence		        *last_pt_update;
+	struct dma_fence	        *last_pt_update;
 	unsigned			ref_count;
 
 	/* protected by vm mutex and spinlock */
@@ -465,7 +397,6 @@ struct amdgpu_bo {
 	 */
 	struct list_head		va;
 	/* Constant after initialization */
-	struct amdgpu_device		*adev;
 	struct drm_gem_object		gem_base;
 	struct amdgpu_bo		*parent;
 	struct amdgpu_bo		*shadow;
@@ -544,7 +475,7 @@ struct amdgpu_sa_bo {
 	struct amdgpu_sa_manager	*manager;
 	unsigned			soffset;
 	unsigned			eoffset;
-	struct fence		        *fence;
+	struct dma_fence	        *fence;
 };
 
 /*
@@ -562,27 +493,6 @@ int amdgpu_mode_dumb_create(struct drm_f
 int amdgpu_mode_dumb_mmap(struct drm_file *filp,
 			  struct drm_device *dev,
 			  uint32_t handle, uint64_t *offset_p);
-/*
- * Synchronization
- */
-struct amdgpu_sync {
-	DECLARE_HASHTABLE(fences, 4);
-	struct fence	        *last_vm_update;
-};
-
-void amdgpu_sync_create(struct amdgpu_sync *sync);
-int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
-		      struct fence *f);
-int amdgpu_sync_resv(struct amdgpu_device *adev,
-		     struct amdgpu_sync *sync,
-		     struct reservation_object *resv,
-		     void *owner);
-struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
-				     struct amdgpu_ring *ring);
-struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
-void amdgpu_sync_free(struct amdgpu_sync *sync);
-int amdgpu_sync_init(void);
-void amdgpu_sync_fini(void);
 int amdgpu_fence_slab_init(void);
 void amdgpu_fence_slab_fini(void);
 
@@ -704,10 +614,10 @@ struct amdgpu_flip_work {
 	uint64_t			base;
 	struct drm_pending_vblank_event *event;
 	struct amdgpu_bo		*old_abo;
-	struct fence			*excl;
+	struct dma_fence		*excl;
 	unsigned			shared_count;
-	struct fence			**shared;
-	struct fence_cb			cb;
+	struct dma_fence		**shared;
+	struct dma_fence_cb		cb;
 	bool				async;
 };
 
@@ -724,14 +634,6 @@ struct amdgpu_ib {
 	uint32_t			flags;
 };
 
-enum amdgpu_ring_type {
-	AMDGPU_RING_TYPE_GFX,
-	AMDGPU_RING_TYPE_COMPUTE,
-	AMDGPU_RING_TYPE_SDMA,
-	AMDGPU_RING_TYPE_UVD,
-	AMDGPU_RING_TYPE_VCE
-};
-
 extern const struct amd_sched_backend_ops amdgpu_sched_ops;
 
 int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
@@ -743,214 +645,7 @@ void amdgpu_job_free_resources(struct am
 void amdgpu_job_free(struct amdgpu_job *job);
 int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
 		      struct amd_sched_entity *entity, void *owner,
-		      struct fence **f);
-
-struct amdgpu_ring {
-	struct amdgpu_device		*adev;
-	const struct amdgpu_ring_funcs	*funcs;
-	struct amdgpu_fence_driver	fence_drv;
-	struct amd_gpu_scheduler	sched;
-
-	struct amdgpu_bo	*ring_obj;
-	volatile uint32_t	*ring;
-	unsigned		rptr_offs;
-	unsigned		wptr;
-	unsigned		wptr_old;
-	unsigned		ring_size;
-	unsigned		max_dw;
-	int			count_dw;
-	uint64_t		gpu_addr;
-	uint32_t		align_mask;
-	uint32_t		ptr_mask;
-	bool			ready;
-	u32			nop;
-	u32			idx;
-	u32			me;
-	u32			pipe;
-	u32			queue;
-	struct amdgpu_bo	*mqd_obj;
-	u32			doorbell_index;
-	bool			use_doorbell;
-	unsigned		wptr_offs;
-	unsigned		fence_offs;
-	uint64_t		current_ctx;
-	enum amdgpu_ring_type	type;
-	char			name[16];
-	unsigned		cond_exe_offs;
-	u64			cond_exe_gpu_addr;
-	volatile u32		*cond_exe_cpu_addr;
-#if defined(CONFIG_DEBUG_FS)
-	struct dentry *ent;
-#endif
-};
-
-/*
- * VM
- */
-
-/* maximum number of VMIDs */
-#define AMDGPU_NUM_VM	16
-
-/* Maximum number of PTEs the hardware can write with one command */
-#define AMDGPU_VM_MAX_UPDATE_SIZE	0x3FFFF
-
-/* number of entries in page table */
-#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size)
-
-/* PTBs (Page Table Blocks) need to be aligned to 32K */
-#define AMDGPU_VM_PTB_ALIGN_SIZE   32768
-
-/* LOG2 number of continuous pages for the fragment field */
-#define AMDGPU_LOG2_PAGES_PER_FRAG 4
-
-#define AMDGPU_PTE_VALID	(1 << 0)
-#define AMDGPU_PTE_SYSTEM	(1 << 1)
-#define AMDGPU_PTE_SNOOPED	(1 << 2)
-
-/* VI only */
-#define AMDGPU_PTE_EXECUTABLE	(1 << 4)
-
-#define AMDGPU_PTE_READABLE	(1 << 5)
-#define AMDGPU_PTE_WRITEABLE	(1 << 6)
-
-#define AMDGPU_PTE_FRAG(x)	((x & 0x1f) << 7)
-
-/* How to programm VM fault handling */
-#define AMDGPU_VM_FAULT_STOP_NEVER	0
-#define AMDGPU_VM_FAULT_STOP_FIRST	1
-#define AMDGPU_VM_FAULT_STOP_ALWAYS	2
-
-struct amdgpu_vm_pt {
-	struct amdgpu_bo_list_entry	entry;
-	uint64_t			addr;
-	uint64_t			shadow_addr;
-};
-
-struct amdgpu_vm {
-	/* tree of virtual addresses mapped */
-	struct rb_root		va;
-
-	/* protecting invalidated */
-	spinlock_t		status_lock;
-
-	/* BOs moved, but not yet updated in the PT */
-	struct list_head	invalidated;
-
-	/* BOs cleared in the PT because of a move */
-	struct list_head	cleared;
-
-	/* BO mappings freed, but not yet updated in the PT */
-	struct list_head	freed;
-
-	/* contains the page directory */
-	struct amdgpu_bo	*page_directory;
-	unsigned		max_pde_used;
-	struct fence		*page_directory_fence;
-	uint64_t		last_eviction_counter;
-
-	/* array of page tables, one for each page directory entry */
-	struct amdgpu_vm_pt	*page_tables;
-
-	/* for id and flush management per ring */
-	struct amdgpu_vm_id	*ids[AMDGPU_MAX_RINGS];
-
-	/* protecting freed */
-	spinlock_t		freed_lock;
-
-	/* Scheduler entity for page table updates */
-	struct amd_sched_entity	entity;
-
-	/* client id */
-	u64                     client_id;
-};
-
-struct amdgpu_vm_id {
-	struct list_head	list;
-	struct fence		*first;
-	struct amdgpu_sync	active;
-	struct fence		*last_flush;
-	atomic64_t		owner;
-
-	uint64_t		pd_gpu_addr;
-	/* last flushed PD/PT update */
-	struct fence		*flushed_updates;
-
-	uint32_t                current_gpu_reset_count;
-
-	uint32_t		gds_base;
-	uint32_t		gds_size;
-	uint32_t		gws_base;
-	uint32_t		gws_size;
-	uint32_t		oa_base;
-	uint32_t		oa_size;
-};
-
-struct amdgpu_vm_manager {
-	/* Handling of VMIDs */
-	struct mutex				lock;
-	unsigned				num_ids;
-	struct list_head			ids_lru;
-	struct amdgpu_vm_id			ids[AMDGPU_NUM_VM];
-
-	/* Handling of VM fences */
-	u64					fence_context;
-	unsigned				seqno[AMDGPU_MAX_RINGS];
-
-	uint32_t				max_pfn;
-	/* vram base address for page table entry  */
-	u64					vram_base_offset;
-	/* is vm enabled? */
-	bool					enabled;
-	/* vm pte handling */
-	const struct amdgpu_vm_pte_funcs        *vm_pte_funcs;
-	struct amdgpu_ring                      *vm_pte_rings[AMDGPU_MAX_RINGS];
-	unsigned				vm_pte_num_rings;
-	atomic_t				vm_pte_next_ring;
-	/* client id counter */
-	atomic64_t				client_counter;
-};
-
-void amdgpu_vm_manager_init(struct amdgpu_device *adev);
-void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
-void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
-void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
-			 struct list_head *validated,
-			 struct amdgpu_bo_list_entry *entry);
-void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-			  struct list_head *duplicates);
-void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
-				  struct amdgpu_vm *vm);
-int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
-		      struct amdgpu_sync *sync, struct fence *fence,
-		      struct amdgpu_job *job);
-int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
-void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
-int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
-				    struct amdgpu_vm *vm);
-int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
-			  struct amdgpu_vm *vm);
-int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-			     struct amdgpu_sync *sync);
-int amdgpu_vm_bo_update(struct amdgpu_device *adev,
-			struct amdgpu_bo_va *bo_va,
-			bool clear);
-void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
-			     struct amdgpu_bo *bo);
-struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
-				       struct amdgpu_bo *bo);
-struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
-				      struct amdgpu_vm *vm,
-				      struct amdgpu_bo *bo);
-int amdgpu_vm_bo_map(struct amdgpu_device *adev,
-		     struct amdgpu_bo_va *bo_va,
-		     uint64_t addr, uint64_t offset,
-		     uint64_t size, uint32_t flags);
-int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
-		       struct amdgpu_bo_va *bo_va,
-		       uint64_t addr);
-void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
-		      struct amdgpu_bo_va *bo_va);
+		      struct dma_fence **f);
 
 /*
  * context related structures
@@ -958,7 +653,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_devi
 
 struct amdgpu_ctx_ring {
 	uint64_t		sequence;
-	struct fence		**fences;
+	struct dma_fence	**fences;
 	struct amd_sched_entity	entity;
 };
 
@@ -967,7 +662,7 @@ struct amdgpu_ctx {
 	struct amdgpu_device    *adev;
 	unsigned		reset_counter;
 	spinlock_t		ring_lock;
-	struct fence            **fences;
+	struct dma_fence	**fences;
 	struct amdgpu_ctx_ring	rings[AMDGPU_MAX_RINGS];
 	bool preamble_presented;
 };
@@ -983,8 +678,8 @@ struct amdgpu_ctx *amdgpu_ctx_get(struct
 int amdgpu_ctx_put(struct amdgpu_ctx *ctx);
 
 uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring,
-			      struct fence *fence);
-struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
+			      struct dma_fence *fence);
+struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
 				   struct amdgpu_ring *ring, uint64_t seq);
 
 int amdgpu_ctx_ioctl(struct drm_device *dev, void *data,
@@ -1094,6 +789,16 @@ struct amdgpu_scratch {
 /*
  * GFX configurations
  */
+#define AMDGPU_GFX_MAX_SE 4
+#define AMDGPU_GFX_MAX_SH_PER_SE 2
+
+struct amdgpu_rb_config {
+	uint32_t rb_backend_disable;
+	uint32_t user_rb_backend_disable;
+	uint32_t raster_config;
+	uint32_t raster_config_1;
+};
+
 struct amdgpu_gca_config {
 	unsigned max_shader_engines;
 	unsigned max_tile_pipes;
@@ -1122,6 +827,8 @@ struct amdgpu_gca_config {
 
 	uint32_t tile_mode_array[32];
 	uint32_t macrotile_mode_array[16];
+
+	struct amdgpu_rb_config rb_config[AMDGPU_GFX_MAX_SE][AMDGPU_GFX_MAX_SH_PER_SE];
 };
 
 struct amdgpu_cu_info {
@@ -1134,6 +841,9 @@ struct amdgpu_gfx_funcs {
 	/* get the gpu clock counter */
 	uint64_t (*get_gpu_clock_counter)(struct amdgpu_device *adev);
 	void (*select_se_sh)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 instance);
+	void (*read_wave_data)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields);
+	void (*read_wave_vgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t thread, uint32_t start, uint32_t size, uint32_t *dst);
+	void (*read_wave_sgprs)(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t start, uint32_t size, uint32_t *dst);
 };
 
 struct amdgpu_gfx {
@@ -1182,23 +892,13 @@ struct amdgpu_gfx {
 int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
 		  unsigned size, struct amdgpu_ib *ib);
 void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
-		    struct fence *f);
+		    struct dma_fence *f);
 int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
-		       struct amdgpu_ib *ib, struct fence *last_vm_update,
-		       struct amdgpu_job *job, struct fence **f);
+		       struct amdgpu_ib *ib, struct dma_fence *last_vm_update,
+		       struct amdgpu_job *job, struct dma_fence **f);
 int amdgpu_ib_pool_init(struct amdgpu_device *adev);
 void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
 int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
-int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
-void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
-void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
-void amdgpu_ring_commit(struct amdgpu_ring *ring);
-void amdgpu_ring_undo(struct amdgpu_ring *ring);
-int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
-		     unsigned ring_size, u32 nop, u32 align_mask,
-		     struct amdgpu_irq_src *irq_src, unsigned irq_type,
-		     enum amdgpu_ring_type ring_type);
-void amdgpu_ring_fini(struct amdgpu_ring *ring);
 
 /*
  * CS.
@@ -1226,7 +926,7 @@ struct amdgpu_cs_parser {
 	struct amdgpu_bo_list		*bo_list;
 	struct amdgpu_bo_list_entry	vm_pd;
 	struct list_head		validated;
-	struct fence			*fence;
+	struct dma_fence		*fence;
 	uint64_t			bytes_moved_threshold;
 	uint64_t			bytes_moved;
 	struct amdgpu_bo_list_entry	*evictable;
@@ -1246,7 +946,7 @@ struct amdgpu_job {
 	struct amdgpu_ring	*ring;
 	struct amdgpu_sync	sync;
 	struct amdgpu_ib	*ibs;
-	struct fence		*fence; /* the hw fence */
+	struct dma_fence	*fence; /* the hw fence */
 	uint32_t		preamble_status;
 	uint32_t		num_ibs;
 	void			*owner;
@@ -1295,354 +995,6 @@ struct amdgpu_wb {
 int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb);
 void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb);
 
-
-
-enum amdgpu_int_thermal_type {
-	THERMAL_TYPE_NONE,
-	THERMAL_TYPE_EXTERNAL,
-	THERMAL_TYPE_EXTERNAL_GPIO,
-	THERMAL_TYPE_RV6XX,
-	THERMAL_TYPE_RV770,
-	THERMAL_TYPE_ADT7473_WITH_INTERNAL,
-	THERMAL_TYPE_EVERGREEN,
-	THERMAL_TYPE_SUMO,
-	THERMAL_TYPE_NI,
-	THERMAL_TYPE_SI,
-	THERMAL_TYPE_EMC2103_WITH_INTERNAL,
-	THERMAL_TYPE_CI,
-	THERMAL_TYPE_KV,
-};
-
-enum amdgpu_dpm_auto_throttle_src {
-	AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL,
-	AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL
-};
-
-enum amdgpu_dpm_event_src {
-	AMDGPU_DPM_EVENT_SRC_ANALOG = 0,
-	AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1,
-	AMDGPU_DPM_EVENT_SRC_DIGITAL = 2,
-	AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3,
-	AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4
-};
-
-#define AMDGPU_MAX_VCE_LEVELS 6
-
-enum amdgpu_vce_level {
-	AMDGPU_VCE_LEVEL_AC_ALL = 0,     /* AC, All cases */
-	AMDGPU_VCE_LEVEL_DC_EE = 1,      /* DC, entropy encoding */
-	AMDGPU_VCE_LEVEL_DC_LL_LOW = 2,  /* DC, low latency queue, res <= 720 */
-	AMDGPU_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
-	AMDGPU_VCE_LEVEL_DC_GP_LOW = 4,  /* DC, general purpose queue, res <= 720 */
-	AMDGPU_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
-};
-
-struct amdgpu_ps {
-	u32 caps; /* vbios flags */
-	u32 class; /* vbios flags */
-	u32 class2; /* vbios flags */
-	/* UVD clocks */
-	u32 vclk;
-	u32 dclk;
-	/* VCE clocks */
-	u32 evclk;
-	u32 ecclk;
-	bool vce_active;
-	enum amdgpu_vce_level vce_level;
-	/* asic priv */
-	void *ps_priv;
-};
-
-struct amdgpu_dpm_thermal {
-	/* thermal interrupt work */
-	struct work_struct work;
-	/* low temperature threshold */
-	int                min_temp;
-	/* high temperature threshold */
-	int                max_temp;
-	/* was last interrupt low to high or high to low */
-	bool               high_to_low;
-	/* interrupt source */
-	struct amdgpu_irq_src	irq;
-};
-
-enum amdgpu_clk_action
-{
-	AMDGPU_SCLK_UP = 1,
-	AMDGPU_SCLK_DOWN
-};
-
-struct amdgpu_blacklist_clocks
-{
-	u32 sclk;
-	u32 mclk;
-	enum amdgpu_clk_action action;
-};
-
-struct amdgpu_clock_and_voltage_limits {
-	u32 sclk;
-	u32 mclk;
-	u16 vddc;
-	u16 vddci;
-};
-
-struct amdgpu_clock_array {
-	u32 count;
-	u32 *values;
-};
-
-struct amdgpu_clock_voltage_dependency_entry {
-	u32 clk;
-	u16 v;
-};
-
-struct amdgpu_clock_voltage_dependency_table {
-	u32 count;
-	struct amdgpu_clock_voltage_dependency_entry *entries;
-};
-
-union amdgpu_cac_leakage_entry {
-	struct {
-		u16 vddc;
-		u32 leakage;
-	};
-	struct {
-		u16 vddc1;
-		u16 vddc2;
-		u16 vddc3;
-	};
-};
-
-struct amdgpu_cac_leakage_table {
-	u32 count;
-	union amdgpu_cac_leakage_entry *entries;
-};
-
-struct amdgpu_phase_shedding_limits_entry {
-	u16 voltage;
-	u32 sclk;
-	u32 mclk;
-};
-
-struct amdgpu_phase_shedding_limits_table {
-	u32 count;
-	struct amdgpu_phase_shedding_limits_entry *entries;
-};
-
-struct amdgpu_uvd_clock_voltage_dependency_entry {
-	u32 vclk;
-	u32 dclk;
-	u16 v;
-};
-
-struct amdgpu_uvd_clock_voltage_dependency_table {
-	u8 count;
-	struct amdgpu_uvd_clock_voltage_dependency_entry *entries;
-};
-
-struct amdgpu_vce_clock_voltage_dependency_entry {
-	u32 ecclk;
-	u32 evclk;
-	u16 v;
-};
-
-struct amdgpu_vce_clock_voltage_dependency_table {
-	u8 count;
-	struct amdgpu_vce_clock_voltage_dependency_entry *entries;
-};
-
-struct amdgpu_ppm_table {
-	u8 ppm_design;
-	u16 cpu_core_number;
-	u32 platform_tdp;
-	u32 small_ac_platform_tdp;
-	u32 platform_tdc;
-	u32 small_ac_platform_tdc;
-	u32 apu_tdp;
-	u32 dgpu_tdp;
-	u32 dgpu_ulv_power;
-	u32 tj_max;
-};
-
-struct amdgpu_cac_tdp_table {
-	u16 tdp;
-	u16 configurable_tdp;
-	u16 tdc;
-	u16 battery_power_limit;
-	u16 small_power_limit;
-	u16 low_cac_leakage;
-	u16 high_cac_leakage;
-	u16 maximum_power_delivery_limit;
-};
-
-struct amdgpu_dpm_dynamic_state {
-	struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk;
-	struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk;
-	struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk;
-	struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk;
-	struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk;
-	struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table;
-	struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table;
-	struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table;
-	struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table;
-	struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk;
-	struct amdgpu_clock_array valid_sclk_values;
-	struct amdgpu_clock_array valid_mclk_values;
-	struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc;
-	struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac;
-	u32 mclk_sclk_ratio;
-	u32 sclk_mclk_delta;
-	u16 vddc_vddci_delta;
-	u16 min_vddc_for_pcie_gen2;
-	struct amdgpu_cac_leakage_table cac_leakage_table;
-	struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table;
-	struct amdgpu_ppm_table *ppm_table;
-	struct amdgpu_cac_tdp_table *cac_tdp_table;
-};
-
-struct amdgpu_dpm_fan {
-	u16 t_min;
-	u16 t_med;
-	u16 t_high;
-	u16 pwm_min;
-	u16 pwm_med;
-	u16 pwm_high;
-	u8 t_hyst;
-	u32 cycle_delay;
-	u16 t_max;
-	u8 control_mode;
-	u16 default_max_fan_pwm;
-	u16 default_fan_output_sensitivity;
-	u16 fan_output_sensitivity;
-	bool ucode_fan_control;
-};
-
-enum amdgpu_pcie_gen {
-	AMDGPU_PCIE_GEN1 = 0,
-	AMDGPU_PCIE_GEN2 = 1,
-	AMDGPU_PCIE_GEN3 = 2,
-	AMDGPU_PCIE_GEN_INVALID = 0xffff
-};
-
-enum amdgpu_dpm_forced_level {
-	AMDGPU_DPM_FORCED_LEVEL_AUTO = 0,
-	AMDGPU_DPM_FORCED_LEVEL_LOW = 1,
-	AMDGPU_DPM_FORCED_LEVEL_HIGH = 2,
-	AMDGPU_DPM_FORCED_LEVEL_MANUAL = 3,
-};
-
-struct amdgpu_vce_state {
-	/* vce clocks */
-	u32 evclk;
-	u32 ecclk;
-	/* gpu clocks */
-	u32 sclk;
-	u32 mclk;
-	u8 clk_idx;
-	u8 pstate;
-};
-
-struct amdgpu_dpm_funcs {
-	int (*get_temperature)(struct amdgpu_device *adev);
-	int (*pre_set_power_state)(struct amdgpu_device *adev);
-	int (*set_power_state)(struct amdgpu_device *adev);
-	void (*post_set_power_state)(struct amdgpu_device *adev);
-	void (*display_configuration_changed)(struct amdgpu_device *adev);
-	u32 (*get_sclk)(struct amdgpu_device *adev, bool low);
-	u32 (*get_mclk)(struct amdgpu_device *adev, bool low);
-	void (*print_power_state)(struct amdgpu_device *adev, struct amdgpu_ps *ps);
-	void (*debugfs_print_current_performance_level)(struct amdgpu_device *adev, struct seq_file *m);
-	int (*force_performance_level)(struct amdgpu_device *adev, enum amdgpu_dpm_forced_level level);
-	bool (*vblank_too_short)(struct amdgpu_device *adev);
-	void (*powergate_uvd)(struct amdgpu_device *adev, bool gate);
-	void (*powergate_vce)(struct amdgpu_device *adev, bool gate);
-	void (*enable_bapm)(struct amdgpu_device *adev, bool enable);
-	void (*set_fan_control_mode)(struct amdgpu_device *adev, u32 mode);
-	u32 (*get_fan_control_mode)(struct amdgpu_device *adev);
-	int (*set_fan_speed_percent)(struct amdgpu_device *adev, u32 speed);
-	int (*get_fan_speed_percent)(struct amdgpu_device *adev, u32 *speed);
-	int (*force_clock_level)(struct amdgpu_device *adev, enum pp_clock_type type, uint32_t mask);
-	int (*print_clock_levels)(struct amdgpu_device *adev, enum pp_clock_type type, char *buf);
-	int (*get_sclk_od)(struct amdgpu_device *adev);
-	int (*set_sclk_od)(struct amdgpu_device *adev, uint32_t value);
-	int (*get_mclk_od)(struct amdgpu_device *adev);
-	int (*set_mclk_od)(struct amdgpu_device *adev, uint32_t value);
-};
-
-struct amdgpu_dpm {
-	struct amdgpu_ps        *ps;
-	/* number of valid power states */
-	int                     num_ps;
-	/* current power state that is active */
-	struct amdgpu_ps        *current_ps;
-	/* requested power state */
-	struct amdgpu_ps        *requested_ps;
-	/* boot up power state */
-	struct amdgpu_ps        *boot_ps;
-	/* default uvd power state */
-	struct amdgpu_ps        *uvd_ps;
-	/* vce requirements */
-	struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS];
-	enum amdgpu_vce_level vce_level;
-	enum amd_pm_state_type state;
-	enum amd_pm_state_type user_state;
-	u32                     platform_caps;
-	u32                     voltage_response_time;
-	u32                     backbias_response_time;
-	void                    *priv;
-	u32			new_active_crtcs;
-	int			new_active_crtc_count;
-	u32			current_active_crtcs;
-	int			current_active_crtc_count;
-	struct amdgpu_dpm_dynamic_state dyn_state;
-	struct amdgpu_dpm_fan fan;
-	u32 tdp_limit;
-	u32 near_tdp_limit;
-	u32 near_tdp_limit_adjusted;
-	u32 sq_ramping_threshold;
-	u32 cac_leakage;
-	u16 tdp_od_limit;
-	u32 tdp_adjustment;
-	u16 load_line_slope;
-	bool power_control;
-	bool ac_power;
-	/* special states active */
-	bool                    thermal_active;
-	bool                    uvd_active;
-	bool                    vce_active;
-	/* thermal handling */
-	struct amdgpu_dpm_thermal thermal;
-	/* forced levels */
-	enum amdgpu_dpm_forced_level forced_level;
-};
-
-struct amdgpu_pm {
-	struct mutex		mutex;
-	u32                     current_sclk;
-	u32                     current_mclk;
-	u32                     default_sclk;
-	u32                     default_mclk;
-	struct amdgpu_i2c_chan *i2c_bus;
-	/* internal thermal controller on rv6xx+ */
-	enum amdgpu_int_thermal_type int_thermal_type;
-	struct device	        *int_hwmon_dev;
-	/* fan control parameters */
-	bool                    no_fan;
-	u8                      fan_pulses_per_revolution;
-	u8                      fan_min_rpm;
-	u8                      fan_max_rpm;
-	/* dpm */
-	bool                    dpm_enabled;
-	bool                    sysfs_initialized;
-	struct amdgpu_dpm       dpm;
-	const struct firmware	*fw;	/* SMC firmware */
-	uint32_t                fw_version;
-	const struct amdgpu_dpm_funcs *funcs;
-	uint32_t                pcie_gen_mask;
-	uint32_t                pcie_mlw_mask;
-	struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */
-};
-
 void amdgpu_get_pcie_info(struct amdgpu_device *adev);
 
 /*
@@ -1863,6 +1215,8 @@ int amdgpu_gem_op_ioctl(struct drm_devic
 			struct drm_file *filp);
 int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
 int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
+int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *filp);
 
 int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *filp);
@@ -1940,14 +1294,6 @@ typedef void (*amdgpu_wreg_t)(struct amd
 typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
 typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
 
-struct amdgpu_ip_block_status {
-	bool valid;
-	bool sw;
-	bool hw;
-	bool late_initialized;
-	bool hang;
-};
-
 struct amdgpu_device {
 	struct device			*dev;
 	struct drm_device		*ddev;
@@ -1986,6 +1332,7 @@ struct amdgpu_device {
 
 	/* BIOS */
 	uint8_t				*bios;
+	uint32_t			bios_size;
 	bool				is_atom_bios;
 	struct amdgpu_bo		*stollen_vga_memory;
 	uint32_t			bios_scratch[AMDGPU_BIOS_NUM_SCRATCH];
@@ -2103,9 +1450,8 @@ struct amdgpu_device {
 	/* GDS */
 	struct amdgpu_gds		gds;
 
-	const struct amdgpu_ip_block_version *ip_blocks;
+	struct amdgpu_ip_block          ip_blocks[AMDGPU_MAX_IP_NUM];
 	int				num_ip_blocks;
-	struct amdgpu_ip_block_status	*ip_block_status;
 	struct mutex	mn_lock;
 	DECLARE_HASHTABLE(mn_hash, 7);
 
@@ -2128,6 +1474,11 @@ struct amdgpu_device {
 
 };
 
+static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
+{
+	return container_of(bdev, struct amdgpu_device, mman.bdev);
+}
+
 bool amdgpu_device_is_px(struct drm_device *dev);
 int amdgpu_device_init(struct amdgpu_device *adev,
 		       struct drm_device *ddev,
@@ -2279,15 +1630,12 @@ amdgpu_get_sdma_instance(struct amdgpu_r
 #define amdgpu_ring_pad_ib(r, ib) ((r)->funcs->pad_ib((r), (ib)))
 #define amdgpu_ring_init_cond_exec(r) (r)->funcs->init_cond_exec((r))
 #define amdgpu_ring_patch_cond_exec(r,o) (r)->funcs->patch_cond_exec((r),(o))
-#define amdgpu_ring_get_emit_ib_size(r) (r)->funcs->get_emit_ib_size((r))
-#define amdgpu_ring_get_dma_frame_size(r) (r)->funcs->get_dma_frame_size((r))
 #define amdgpu_ih_get_wptr(adev) (adev)->irq.ih_funcs->get_wptr((adev))
 #define amdgpu_ih_decode_iv(adev, iv) (adev)->irq.ih_funcs->decode_iv((adev), (iv))
 #define amdgpu_ih_set_rptr(adev) (adev)->irq.ih_funcs->set_rptr((adev))
 #define amdgpu_display_set_vga_render_state(adev, r) (adev)->mode_info.funcs->set_vga_render_state((adev), (r))
 #define amdgpu_display_vblank_get_counter(adev, crtc) (adev)->mode_info.funcs->vblank_get_counter((adev), (crtc))
 #define amdgpu_display_vblank_wait(adev, crtc) (adev)->mode_info.funcs->vblank_wait((adev), (crtc))
-#define amdgpu_display_is_display_hung(adev) (adev)->mode_info.funcs->is_display_hung((adev))
 #define amdgpu_display_backlight_set_level(adev, e, l) (adev)->mode_info.funcs->backlight_set_level((e), (l))
 #define amdgpu_display_backlight_get_level(adev, e) (adev)->mode_info.funcs->backlight_get_level((e))
 #define amdgpu_display_hpd_sense(adev, h) (adev)->mode_info.funcs->hpd_sense((adev), (h))
@@ -2302,108 +1650,8 @@ amdgpu_get_sdma_instance(struct amdgpu_r
 #define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s))
 #define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib),  (s), (d), (b))
 #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b))
-#define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev))
-#define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev))
-#define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev))
-#define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev))
-#define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps))
-#define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev))
-#define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e))
 #define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev))
 #define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance))
-
-#define amdgpu_dpm_read_sensor(adev, idx, value) \
-	((adev)->pp_enabled ? \
-		(adev)->powerplay.pp_funcs->read_sensor(adev->powerplay.pp_handle, (idx), (value)) : \
-		-EINVAL)
-
-#define amdgpu_dpm_get_temperature(adev) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \
-	      (adev)->pm.funcs->get_temperature((adev)))
-
-#define amdgpu_dpm_set_fan_control_mode(adev, m) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \
-	      (adev)->pm.funcs->set_fan_control_mode((adev), (m)))
-
-#define amdgpu_dpm_get_fan_control_mode(adev) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \
-	      (adev)->pm.funcs->get_fan_control_mode((adev)))
-
-#define amdgpu_dpm_set_fan_speed_percent(adev, s) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
-	      (adev)->pm.funcs->set_fan_speed_percent((adev), (s)))
-
-#define amdgpu_dpm_get_fan_speed_percent(adev, s) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \
-	      (adev)->pm.funcs->get_fan_speed_percent((adev), (s)))
-
-#define amdgpu_dpm_get_sclk(adev, l) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \
-		(adev)->pm.funcs->get_sclk((adev), (l)))
-
-#define amdgpu_dpm_get_mclk(adev, l)  \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \
-	      (adev)->pm.funcs->get_mclk((adev), (l)))
-
-
-#define amdgpu_dpm_force_performance_level(adev, l) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \
-	      (adev)->pm.funcs->force_performance_level((adev), (l)))
-
-#define amdgpu_dpm_powergate_uvd(adev, g) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \
-	      (adev)->pm.funcs->powergate_uvd((adev), (g)))
-
-#define amdgpu_dpm_powergate_vce(adev, g) \
-	((adev)->pp_enabled ?						\
-	      (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \
-	      (adev)->pm.funcs->powergate_vce((adev), (g)))
-
-#define amdgpu_dpm_get_current_power_state(adev) \
-	(adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)
-
-#define amdgpu_dpm_get_performance_level(adev) \
-	(adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)
-
-#define amdgpu_dpm_get_pp_num_states(adev, data) \
-	(adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)
-
-#define amdgpu_dpm_get_pp_table(adev, table) \
-	(adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)
-
-#define amdgpu_dpm_set_pp_table(adev, buf, size) \
-	(adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)
-
-#define amdgpu_dpm_print_clock_levels(adev, type, buf) \
-	(adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)
-
-#define amdgpu_dpm_force_clock_level(adev, type, level) \
-		(adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)
-
-#define amdgpu_dpm_get_sclk_od(adev) \
-	(adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)
-
-#define amdgpu_dpm_set_sclk_od(adev, value) \
-	(adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)
-
-#define amdgpu_dpm_get_mclk_od(adev) \
-	((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle))
-
-#define amdgpu_dpm_set_mclk_od(adev, value) \
-	((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value))
-
-#define amdgpu_dpm_dispatch_task(adev, event_id, input, output)		\
-	(adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output))
-
 #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a))
 
 /* Common functions */
@@ -2434,8 +1682,6 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct
 void amdgpu_vram_location(struct amdgpu_device *adev, struct amdgpu_mc *mc, u64 base);
 void amdgpu_gtt_location(struct amdgpu_device *adev, struct amdgpu_mc *mc);
 void amdgpu_ttm_set_active_vram_size(struct amdgpu_device *adev, u64 size);
-u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev);
-int amdgpu_ttm_global_init(struct amdgpu_device *adev);
 int amdgpu_ttm_init(struct amdgpu_device *adev);
 void amdgpu_ttm_fini(struct amdgpu_device *adev);
 void amdgpu_program_register_sequence(struct amdgpu_device *adev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,7 @@ int amdgpu_ib_get(struct amdgpu_device *
  * Free an IB (all asics).
  */
 void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
-		    struct fence *f)
+		    struct dma_fence *f)
 {
 	amdgpu_sa_bo_free(adev, &ib->sa_bo, f);
 }
@@ -116,8 +116,8 @@ void amdgpu_ib_free(struct amdgpu_device
  * to SI there was just a DE IB.
  */
 int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
-		       struct amdgpu_ib *ibs, struct fence *last_vm_update,
-		       struct amdgpu_job *job, struct fence **f)
+		       struct amdgpu_ib *ibs, struct dma_fence *last_vm_update,
+		       struct amdgpu_job *job, struct dma_fence **f)
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib *ib = &ibs[0];
@@ -152,8 +152,8 @@ int amdgpu_ib_schedule(struct amdgpu_rin
 		return -EINVAL;
 	}
 
-	alloc_size = amdgpu_ring_get_dma_frame_size(ring) +
-		num_ibs * amdgpu_ring_get_emit_ib_size(ring);
+	alloc_size = ring->funcs->emit_frame_size + num_ibs *
+		ring->funcs->emit_ib_size;
 
 	r = amdgpu_ring_alloc(ring, alloc_size);
 	if (r) {
@@ -161,7 +161,7 @@ int amdgpu_ib_schedule(struct amdgpu_rin
 		return r;
 	}
 
-	if (ring->type == AMDGPU_RING_TYPE_SDMA && ring->funcs->init_cond_exec)
+	if (ring->funcs->init_cond_exec)
 		patch_offset = amdgpu_ring_init_cond_exec(ring);
 
 	if (vm) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -424,15 +424,6 @@ int amdgpu_irq_get(struct amdgpu_device
 	return 0;
 }
 
-bool amdgpu_irq_get_delayed(struct amdgpu_device *adev,
-			struct amdgpu_irq_src *src,
-			unsigned type)
-{
-	if ((type >= src->num_types) || !src->enabled_types)
-		return false;
-	return atomic_inc_return(&src->enabled_types[type]) == 1;
-}
-
 /**
  * amdgpu_irq_put - disable interrupt
  *
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.h	2017-02-12 16:03:20.000000000 -0500
@@ -88,9 +88,6 @@ int amdgpu_irq_update(struct amdgpu_devi
 		      unsigned type);
 int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
 		   unsigned type);
-bool amdgpu_irq_get_delayed(struct amdgpu_device *adev,
-			    struct amdgpu_irq_src *src,
-			    unsigned type);
 int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
 		   unsigned type);
 bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,7 +81,7 @@ int amdgpu_job_alloc_with_ib(struct amdg
 
 void amdgpu_job_free_resources(struct amdgpu_job *job)
 {
-	struct fence *f;
+	struct dma_fence *f;
 	unsigned i;
 
 	/* use sched fence if available */
@@ -95,7 +95,7 @@ static void amdgpu_job_free_cb(struct am
 {
 	struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base);
 
-	fence_put(job->fence);
+	dma_fence_put(job->fence);
 	amdgpu_sync_free(&job->sync);
 	kfree(job);
 }
@@ -104,14 +104,14 @@ void amdgpu_job_free(struct amdgpu_job *
 {
 	amdgpu_job_free_resources(job);
 
-	fence_put(job->fence);
+	dma_fence_put(job->fence);
 	amdgpu_sync_free(&job->sync);
 	kfree(job);
 }
 
 int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring,
 		      struct amd_sched_entity *entity, void *owner,
-		      struct fence **f)
+		      struct dma_fence **f)
 {
 	int r;
 	job->ring = ring;
@@ -125,19 +125,19 @@ int amdgpu_job_submit(struct amdgpu_job
 
 	job->owner = owner;
 	job->fence_ctx = entity->fence_context;
-	*f = fence_get(&job->base.s_fence->finished);
+	*f = dma_fence_get(&job->base.s_fence->finished);
 	amdgpu_job_free_resources(job);
 	amd_sched_entity_push_job(&job->base);
 
 	return 0;
 }
 
-static struct fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
+static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
 {
 	struct amdgpu_job *job = to_amdgpu_job(sched_job);
 	struct amdgpu_vm *vm = job->vm;
 
-	struct fence *fence = amdgpu_sync_get_fence(&job->sync);
+	struct dma_fence *fence = amdgpu_sync_get_fence(&job->sync);
 
 	if (fence == NULL && vm && !job->vm_id) {
 		struct amdgpu_ring *ring = job->ring;
@@ -155,9 +155,9 @@ static struct fence *amdgpu_job_dependen
 	return fence;
 }
 
-static struct fence *amdgpu_job_run(struct amd_sched_job *sched_job)
+static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job)
 {
-	struct fence *fence = NULL;
+	struct dma_fence *fence = NULL;
 	struct amdgpu_job *job;
 	int r;
 
@@ -176,8 +176,8 @@ static struct fence *amdgpu_job_run(stru
 		DRM_ERROR("Error scheduling IBs (%d)\n", r);
 
 	/* if gpu reset, hw fence will be replaced here */
-	fence_put(job->fence);
-	job->fence = fence_get(fence);
+	dma_fence_put(job->fence);
+	job->fence = dma_fence_get(fence);
 	amdgpu_job_free_resources(job);
 	return fence;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -308,10 +308,10 @@ static int amdgpu_info_ioctl(struct drm_
 		}
 
 		for (i = 0; i < adev->num_ip_blocks; i++) {
-			if (adev->ip_blocks[i].type == type &&
-			    adev->ip_block_status[i].valid) {
-				ip.hw_ip_version_major = adev->ip_blocks[i].major;
-				ip.hw_ip_version_minor = adev->ip_blocks[i].minor;
+			if (adev->ip_blocks[i].version->type == type &&
+			    adev->ip_blocks[i].status.valid) {
+				ip.hw_ip_version_major = adev->ip_blocks[i].version->major;
+				ip.hw_ip_version_minor = adev->ip_blocks[i].version->minor;
 				ip.capabilities_flags = 0;
 				ip.available_rings = ring_mask;
 				ip.ib_start_alignment = ib_start_alignment;
@@ -347,8 +347,8 @@ static int amdgpu_info_ioctl(struct drm_
 		}
 
 		for (i = 0; i < adev->num_ip_blocks; i++)
-			if (adev->ip_blocks[i].type == type &&
-			    adev->ip_block_status[i].valid &&
+			if (adev->ip_blocks[i].version->type == type &&
+			    adev->ip_blocks[i].status.valid &&
 			    count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
 				count++;
 
@@ -413,6 +413,36 @@ static int amdgpu_info_ioctl(struct drm_
 		return copy_to_user(out, &vram_gtt,
 				    min((size_t)size, sizeof(vram_gtt))) ? -EFAULT : 0;
 	}
+	case AMDGPU_INFO_MEMORY: {
+		struct drm_amdgpu_memory_info mem;
+
+		memset(&mem, 0, sizeof(mem));
+		mem.vram.total_heap_size = adev->mc.real_vram_size;
+		mem.vram.usable_heap_size =
+			adev->mc.real_vram_size - adev->vram_pin_size;
+		mem.vram.heap_usage = atomic64_read(&adev->vram_usage);
+		mem.vram.max_allocation = mem.vram.usable_heap_size * 3 / 4;
+
+		mem.cpu_accessible_vram.total_heap_size =
+			adev->mc.visible_vram_size;
+		mem.cpu_accessible_vram.usable_heap_size =
+			adev->mc.visible_vram_size -
+			(adev->vram_pin_size - adev->invisible_pin_size);
+		mem.cpu_accessible_vram.heap_usage =
+			atomic64_read(&adev->vram_vis_usage);
+		mem.cpu_accessible_vram.max_allocation =
+			mem.cpu_accessible_vram.usable_heap_size * 3 / 4;
+
+		mem.gtt.total_heap_size = adev->mc.gtt_size;
+		mem.gtt.usable_heap_size =
+			adev->mc.gtt_size - adev->gart_pin_size;
+		mem.gtt.heap_usage = atomic64_read(&adev->gtt_usage);
+		mem.gtt.max_allocation = mem.gtt.usable_heap_size * 3 / 4;
+
+		return copy_to_user(out, &mem,
+				    min((size_t)size, sizeof(mem)))
+				    ? -EFAULT : 0;
+	}
 	case AMDGPU_INFO_READ_MMR_REG: {
 		unsigned n, alloc_size;
 		uint32_t *regs;
@@ -475,6 +505,8 @@ static int amdgpu_info_ioctl(struct drm_
 		dev_info.ids_flags = 0;
 		if (adev->flags & AMD_IS_APU)
 			dev_info.ids_flags |= AMDGPU_IDS_FLAGS_FUSION;
+		if (amdgpu_sriov_vf(adev))
+			dev_info.ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
 		dev_info.virtual_address_offset = AMDGPU_VA_RESERVED_SIZE;
 		dev_info.virtual_address_max = (uint64_t)adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
 		dev_info.virtual_address_alignment = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE);
@@ -494,6 +526,50 @@ static int amdgpu_info_ioctl(struct drm_
 		return copy_to_user(out, &dev_info,
 				    min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
 	}
+	case AMDGPU_INFO_VCE_CLOCK_TABLE: {
+		unsigned i;
+		struct drm_amdgpu_info_vce_clock_table vce_clk_table = {};
+		struct amd_vce_state *vce_state;
+
+		for (i = 0; i < AMDGPU_VCE_CLOCK_TABLE_ENTRIES; i++) {
+			vce_state = amdgpu_dpm_get_vce_clock_state(adev, i);
+			if (vce_state) {
+				vce_clk_table.entries[i].sclk = vce_state->sclk;
+				vce_clk_table.entries[i].mclk = vce_state->mclk;
+				vce_clk_table.entries[i].eclk = vce_state->evclk;
+				vce_clk_table.num_valid_entries++;
+			}
+		}
+
+		return copy_to_user(out, &vce_clk_table,
+				    min((size_t)size, sizeof(vce_clk_table))) ? -EFAULT : 0;
+	}
+	case AMDGPU_INFO_VBIOS: {
+		uint32_t bios_size = adev->bios_size;
+
+		switch (info->vbios_info.type) {
+		case AMDGPU_INFO_VBIOS_SIZE:
+			return copy_to_user(out, &bios_size,
+					min((size_t)size, sizeof(bios_size)))
+					? -EFAULT : 0;
+		case AMDGPU_INFO_VBIOS_IMAGE: {
+			uint8_t *bios;
+			uint32_t bios_offset = info->vbios_info.offset;
+
+			if (bios_offset >= bios_size)
+				return -EINVAL;
+
+			bios = adev->bios + bios_offset;
+			return copy_to_user(out, bios,
+					    min((size_t)size, (size_t)(bios_size - bios_offset)))
+					? -EFAULT : 0;
+		}
+		default:
+			DRM_DEBUG_KMS("Invalid request %d\n",
+					info->vbios_info.type);
+			return -EINVAL;
+		}
+	}
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->query);
 		return -EINVAL;
@@ -775,6 +851,7 @@ const struct drm_ioctl_desc amdgpu_ioctl
 	DRM_IOCTL_DEF_DRV(AMDGPU_CS, amdgpu_cs_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(AMDGPU_INFO, amdgpu_info_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_CS, amdgpu_cs_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(AMDGPU_WAIT_FENCES, amdgpu_cs_wait_fences_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c	2017-02-12 16:03:20.000000000 -0500
@@ -285,7 +285,7 @@ free_rmn:
 int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
 {
 	unsigned long end = addr + amdgpu_bo_size(bo) - 1;
-	struct amdgpu_device *adev = bo->adev;
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	struct amdgpu_mn *rmn;
 	struct amdgpu_mn_node *node = NULL;
 	struct list_head bos;
@@ -340,7 +340,7 @@ int amdgpu_mn_register(struct amdgpu_bo
  */
 void amdgpu_mn_unregister(struct amdgpu_bo *bo)
 {
-	struct amdgpu_device *adev = bo->adev;
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	struct amdgpu_mn *rmn;
 	struct list_head *head;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h	2017-02-12 16:03:20.000000000 -0500
@@ -271,8 +271,6 @@ struct amdgpu_display_funcs {
 	u32 (*vblank_get_counter)(struct amdgpu_device *adev, int crtc);
 	/* wait for vblank */
 	void (*vblank_wait)(struct amdgpu_device *adev, int crtc);
-	/* is dce hung */
-	bool (*is_display_hung)(struct amdgpu_device *adev);
 	/* set backlight level */
 	void (*backlight_set_level)(struct amdgpu_encoder *amdgpu_encoder,
 				    u8 level);
@@ -341,8 +339,6 @@ struct amdgpu_mode_info {
 	int			num_dig; /* number of dig blocks */
 	int			disp_priority;
 	const struct amdgpu_display_funcs *funcs;
-	struct hrtimer vblank_timer;
-	enum amdgpu_interrupt_state vsync_timer_enabled;
 };
 
 #define AMDGPU_MAX_BL_LEVEL 0xFF
@@ -413,6 +409,9 @@ struct amdgpu_crtc {
 	u32 wm_high;
 	u32 lb_vblank_lead_lines;
 	struct drm_display_mode hw_mode;
+	/* for virtual dce */
+	struct hrtimer vblank_timer;
+	enum amdgpu_interrupt_state vsync_timer_enabled;
 };
 
 struct amdgpu_encoder_atom_dig {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,18 +88,19 @@ static void amdgpu_update_memory_usage(s
 
 static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
 {
+	struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
 	struct amdgpu_bo *bo;
 
 	bo = container_of(tbo, struct amdgpu_bo, tbo);
 
-	amdgpu_update_memory_usage(bo->adev, &bo->tbo.mem, NULL);
+	amdgpu_update_memory_usage(adev, &bo->tbo.mem, NULL);
 
 	drm_gem_object_release(&bo->gem_base);
 	amdgpu_bo_unref(&bo->parent);
 	if (!list_empty(&bo->shadow_list)) {
-		mutex_lock(&bo->adev->shadow_list_lock);
+		mutex_lock(&adev->shadow_list_lock);
 		list_del_init(&bo->shadow_list);
-		mutex_unlock(&bo->adev->shadow_list_lock);
+		mutex_unlock(&adev->shadow_list_lock);
 	}
 	kfree(bo->metadata);
 	kfree(bo);
@@ -121,20 +122,14 @@ static void amdgpu_ttm_placement_init(st
 
 	if (domain & AMDGPU_GEM_DOMAIN_VRAM) {
 		unsigned visible_pfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
+		unsigned lpfn = 0;
 
-		if (flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS &&
-		    !(flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
-		    adev->mc.visible_vram_size < adev->mc.real_vram_size) {
-			places[c].fpfn = visible_pfn;
-			places[c].lpfn = 0;
-			places[c].flags = TTM_PL_FLAG_WC |
-				TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM |
-				TTM_PL_FLAG_TOPDOWN;
-			c++;
-		}
+		/* This forces a reallocation if the flag wasn't set before */
+		if (flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
+			lpfn = adev->mc.real_vram_size >> PAGE_SHIFT;
 
 		places[c].fpfn = 0;
-		places[c].lpfn = 0;
+		places[c].lpfn = lpfn;
 		places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
 			TTM_PL_FLAG_VRAM;
 		if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED)
@@ -205,8 +200,10 @@ static void amdgpu_ttm_placement_init(st
 
 void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain)
 {
-	amdgpu_ttm_placement_init(abo->adev, &abo->placement,
-				  abo->placements, domain, abo->flags);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
+
+	amdgpu_ttm_placement_init(adev, &abo->placement, abo->placements,
+				  domain, abo->flags);
 }
 
 static void amdgpu_fill_placement_to_bo(struct amdgpu_bo *bo,
@@ -245,7 +242,8 @@ int amdgpu_bo_create_kernel(struct amdgp
 	int r;
 
 	r = amdgpu_bo_create(adev, size, align, true, domain,
-			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+			     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 			     NULL, NULL, bo_ptr);
 	if (r) {
 		dev_err(adev->dev, "(%d) failed to allocate kernel bo\n", r);
@@ -351,7 +349,6 @@ int amdgpu_bo_create_restricted(struct a
 		kfree(bo);
 		return r;
 	}
-	bo->adev = adev;
 	INIT_LIST_HEAD(&bo->shadow_list);
 	INIT_LIST_HEAD(&bo->va);
 	bo->prefered_domains = domain & (AMDGPU_GEM_DOMAIN_VRAM |
@@ -374,39 +371,36 @@ int amdgpu_bo_create_restricted(struct a
 
 	amdgpu_fill_placement_to_bo(bo, placement);
 	/* Kernel allocation are uninterruptible */
+
+	if (!resv) {
+		bool locked;
+
+		reservation_object_init(&bo->tbo.ttm_resv);
+		locked = ww_mutex_trylock(&bo->tbo.ttm_resv.lock);
+		WARN_ON(!locked);
+	}
 	r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
 			&bo->placement, page_align, !kernel, NULL,
-			acc_size, sg, resv, &amdgpu_ttm_bo_destroy);
-	if (unlikely(r != 0)) {
+			acc_size, sg, resv ? resv : &bo->tbo.ttm_resv,
+			&amdgpu_ttm_bo_destroy);
+	if (unlikely(r != 0))
 		return r;
-	}
 
 	if (flags & AMDGPU_GEM_CREATE_VRAM_CLEARED &&
 	    bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) {
-		struct fence *fence;
-
-		if (adev->mman.buffer_funcs_ring == NULL ||
-		   !adev->mman.buffer_funcs_ring->ready) {
-			r = -EBUSY;
-			goto fail_free;
-		}
-
-		r = amdgpu_bo_reserve(bo, false);
-		if (unlikely(r != 0))
-			goto fail_free;
+		struct dma_fence *fence;
 
-		amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
-		r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
-		if (unlikely(r != 0))
+		r = amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
+		if (unlikely(r))
 			goto fail_unreserve;
 
-		amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence);
 		amdgpu_bo_fence(bo, fence, false);
-		amdgpu_bo_unreserve(bo);
-		fence_put(bo->tbo.moving);
-		bo->tbo.moving = fence_get(fence);
-		fence_put(fence);
+		dma_fence_put(bo->tbo.moving);
+		bo->tbo.moving = dma_fence_get(fence);
+		dma_fence_put(fence);
 	}
+	if (!resv)
+		ww_mutex_unlock(&bo->tbo.resv->lock);
 	*bo_ptr = bo;
 
 	trace_amdgpu_bo_create(bo);
@@ -414,8 +408,7 @@ int amdgpu_bo_create_restricted(struct a
 	return 0;
 
 fail_unreserve:
-	amdgpu_bo_unreserve(bo);
-fail_free:
+	ww_mutex_unlock(&bo->tbo.resv->lock);
 	amdgpu_bo_unref(&bo);
 	return r;
 }
@@ -491,7 +484,7 @@ int amdgpu_bo_backup_to_shadow(struct am
 			       struct amdgpu_ring *ring,
 			       struct amdgpu_bo *bo,
 			       struct reservation_object *resv,
-			       struct fence **fence,
+			       struct dma_fence **fence,
 			       bool direct)
 
 {
@@ -523,7 +516,7 @@ int amdgpu_bo_restore_from_shadow(struct
 				  struct amdgpu_ring *ring,
 				  struct amdgpu_bo *bo,
 				  struct reservation_object *resv,
-				  struct fence **fence,
+				  struct dma_fence **fence,
 				  bool direct)
 
 {
@@ -616,6 +609,7 @@ int amdgpu_bo_pin_restricted(struct amdg
 			     u64 min_offset, u64 max_offset,
 			     u64 *gpu_addr)
 {
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	int r, i;
 	unsigned fpfn, lpfn;
 
@@ -643,18 +637,20 @@ int amdgpu_bo_pin_restricted(struct amdg
 
 		return 0;
 	}
+
+	bo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
 	amdgpu_ttm_placement_from_domain(bo, domain);
 	for (i = 0; i < bo->placement.num_placement; i++) {
 		/* force to pin into visible video ram */
 		if ((bo->placements[i].flags & TTM_PL_FLAG_VRAM) &&
 		    !(bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS) &&
 		    (!max_offset || max_offset >
-		     bo->adev->mc.visible_vram_size)) {
+		     adev->mc.visible_vram_size)) {
 			if (WARN_ON_ONCE(min_offset >
-					 bo->adev->mc.visible_vram_size))
+					 adev->mc.visible_vram_size))
 				return -EINVAL;
 			fpfn = min_offset >> PAGE_SHIFT;
-			lpfn = bo->adev->mc.visible_vram_size >> PAGE_SHIFT;
+			lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT;
 		} else {
 			fpfn = min_offset >> PAGE_SHIFT;
 			lpfn = max_offset >> PAGE_SHIFT;
@@ -669,12 +665,12 @@ int amdgpu_bo_pin_restricted(struct amdg
 
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
 	if (unlikely(r)) {
-		dev_err(bo->adev->dev, "%p pin failed\n", bo);
+		dev_err(adev->dev, "%p pin failed\n", bo);
 		goto error;
 	}
 	r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem);
 	if (unlikely(r)) {
-		dev_err(bo->adev->dev, "%p bind failed\n", bo);
+		dev_err(adev->dev, "%p bind failed\n", bo);
 		goto error;
 	}
 
@@ -682,11 +678,11 @@ int amdgpu_bo_pin_restricted(struct amdg
 	if (gpu_addr != NULL)
 		*gpu_addr = amdgpu_bo_gpu_offset(bo);
 	if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
-		bo->adev->vram_pin_size += amdgpu_bo_size(bo);
+		adev->vram_pin_size += amdgpu_bo_size(bo);
 		if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
-			bo->adev->invisible_pin_size += amdgpu_bo_size(bo);
+			adev->invisible_pin_size += amdgpu_bo_size(bo);
 	} else if (domain == AMDGPU_GEM_DOMAIN_GTT) {
-		bo->adev->gart_pin_size += amdgpu_bo_size(bo);
+		adev->gart_pin_size += amdgpu_bo_size(bo);
 	}
 
 error:
@@ -700,10 +696,11 @@ int amdgpu_bo_pin(struct amdgpu_bo *bo,
 
 int amdgpu_bo_unpin(struct amdgpu_bo *bo)
 {
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	int r, i;
 
 	if (!bo->pin_count) {
-		dev_warn(bo->adev->dev, "%p unpin not necessary\n", bo);
+		dev_warn(adev->dev, "%p unpin not necessary\n", bo);
 		return 0;
 	}
 	bo->pin_count--;
@@ -715,16 +712,16 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo
 	}
 	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
 	if (unlikely(r)) {
-		dev_err(bo->adev->dev, "%p validate failed for unpin\n", bo);
+		dev_err(adev->dev, "%p validate failed for unpin\n", bo);
 		goto error;
 	}
 
 	if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
-		bo->adev->vram_pin_size -= amdgpu_bo_size(bo);
+		adev->vram_pin_size -= amdgpu_bo_size(bo);
 		if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
-			bo->adev->invisible_pin_size -= amdgpu_bo_size(bo);
+			adev->invisible_pin_size -= amdgpu_bo_size(bo);
 	} else if (bo->tbo.mem.mem_type == TTM_PL_TT) {
-		bo->adev->gart_pin_size -= amdgpu_bo_size(bo);
+		adev->gart_pin_size -= amdgpu_bo_size(bo);
 	}
 
 error:
@@ -854,6 +851,7 @@ int amdgpu_bo_get_metadata(struct amdgpu
 void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
 			   struct ttm_mem_reg *new_mem)
 {
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
 	struct amdgpu_bo *abo;
 	struct ttm_mem_reg *old_mem = &bo->mem;
 
@@ -861,21 +859,21 @@ void amdgpu_bo_move_notify(struct ttm_bu
 		return;
 
 	abo = container_of(bo, struct amdgpu_bo, tbo);
-	amdgpu_vm_bo_invalidate(abo->adev, abo);
+	amdgpu_vm_bo_invalidate(adev, abo);
 
 	/* update statistics */
 	if (!new_mem)
 		return;
 
 	/* move_notify is called before move happens */
-	amdgpu_update_memory_usage(abo->adev, &bo->mem, new_mem);
+	amdgpu_update_memory_usage(adev, &bo->mem, new_mem);
 
 	trace_amdgpu_ttm_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
 }
 
 int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
 {
-	struct amdgpu_device *adev;
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
 	struct amdgpu_bo *abo;
 	unsigned long offset, size, lpfn;
 	int i, r;
@@ -884,13 +882,14 @@ int amdgpu_bo_fault_reserve_notify(struc
 		return 0;
 
 	abo = container_of(bo, struct amdgpu_bo, tbo);
-	adev = abo->adev;
 	if (bo->mem.mem_type != TTM_PL_VRAM)
 		return 0;
 
 	size = bo->mem.num_pages << PAGE_SHIFT;
 	offset = bo->mem.start << PAGE_SHIFT;
-	if ((offset + size) <= adev->mc.visible_vram_size)
+	/* TODO: figure out how to map scattered VRAM to the CPU */
+	if ((offset + size) <= adev->mc.visible_vram_size &&
+	    (abo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS))
 		return 0;
 
 	/* Can't move a pinned BO to visible VRAM */
@@ -898,6 +897,7 @@ int amdgpu_bo_fault_reserve_notify(struc
 		return -EINVAL;
 
 	/* hurrah the memory is not visible ! */
+	abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
 	amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM);
 	lpfn =	adev->mc.visible_vram_size >> PAGE_SHIFT;
 	for (i = 0; i < abo->placement.num_placement; i++) {
@@ -931,7 +931,7 @@ int amdgpu_bo_fault_reserve_notify(struc
  * @shared: true if fence should be added shared
  *
  */
-void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
+void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
 		     bool shared)
 {
 	struct reservation_object *resv = bo->tbo.resv;
@@ -959,6 +959,8 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_b
 	WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) &&
 		     !bo->pin_count);
 	WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET);
+	WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM &&
+		     !(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS));
 
 	return bo->tbo.offset;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h	2017-02-12 16:03:20.000000000 -0500
@@ -71,12 +71,13 @@ static inline unsigned amdgpu_mem_type_t
  */
 static inline int amdgpu_bo_reserve(struct amdgpu_bo *bo, bool no_intr)
 {
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
 	int r;
 
 	r = ttm_bo_reserve(&bo->tbo, !no_intr, false, NULL);
 	if (unlikely(r != 0)) {
 		if (r != -ERESTARTSYS)
-			dev_err(bo->adev->dev, "%p reserve failed\n", bo);
+			dev_err(adev->dev, "%p reserve failed\n", bo);
 		return r;
 	}
 	return 0;
@@ -156,19 +157,19 @@ int amdgpu_bo_get_metadata(struct amdgpu
 void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
 				  struct ttm_mem_reg *new_mem);
 int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
-void amdgpu_bo_fence(struct amdgpu_bo *bo, struct fence *fence,
+void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
 		     bool shared);
 u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo);
 int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
 			       struct amdgpu_ring *ring,
 			       struct amdgpu_bo *bo,
 			       struct reservation_object *resv,
-			       struct fence **fence, bool direct);
+			       struct dma_fence **fence, bool direct);
 int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
 				  struct amdgpu_ring *ring,
 				  struct amdgpu_bo *bo,
 				  struct reservation_object *resv,
-				  struct fence **fence,
+				  struct dma_fence **fence,
 				  bool direct);
 
 
@@ -200,7 +201,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma
 		     unsigned size, unsigned align);
 void amdgpu_sa_bo_free(struct amdgpu_device *adev,
 			      struct amdgpu_sa_bo **sa_bo,
-			      struct fence *fence);
+			      struct dma_fence *fence);
 #if defined(CONFIG_DEBUG_FS)
 void amdgpu_sa_bo_dump_debug_info(struct amdgpu_sa_manager *sa_manager,
 					 struct seq_file *m);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -737,6 +737,21 @@ static ssize_t amdgpu_hwmon_get_pwm1(str
 	return sprintf(buf, "%i\n", speed);
 }
 
+static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct amdgpu_device *adev = dev_get_drvdata(dev);
+	int err;
+	u32 speed;
+
+	err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed);
+	if (err)
+		return err;
+
+	return sprintf(buf, "%i\n", speed);
+}
+
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1);
@@ -744,6 +759,7 @@ static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO
 static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_enable, amdgpu_hwmon_set_pwm1_enable, 0);
 static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0);
 static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0);
 
 static struct attribute *hwmon_attributes[] = {
 	&sensor_dev_attr_temp1_input.dev_attr.attr,
@@ -753,6 +769,7 @@ static struct attribute *hwmon_attribute
 	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
 	&sensor_dev_attr_pwm1_min.dev_attr.attr,
 	&sensor_dev_attr_pwm1_max.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
 	NULL
 };
 
@@ -804,6 +821,10 @@ static umode_t hwmon_attributes_visible(
 	     attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
 		return 0;
 
+	/* requires powerplay */
+	if (attr == &sensor_dev_attr_fan1_input.dev_attr.attr)
+		return 0;
+
 	return effective_mode;
 }
 
@@ -986,10 +1007,10 @@ restart_search:
 
 static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev)
 {
-	int i;
 	struct amdgpu_ps *ps;
 	enum amd_pm_state_type dpm_state;
 	int ret;
+	bool equal;
 
 	/* if dpm init failed */
 	if (!adev->pm.dpm_enabled)
@@ -1009,46 +1030,6 @@ static void amdgpu_dpm_change_power_stat
 	else
 		return;
 
-	/* no need to reprogram if nothing changed unless we are on BTC+ */
-	if (adev->pm.dpm.current_ps == adev->pm.dpm.requested_ps) {
-		/* vce just modifies an existing state so force a change */
-		if (ps->vce_active != adev->pm.dpm.vce_active)
-			goto force;
-		if (adev->flags & AMD_IS_APU) {
-			/* for APUs if the num crtcs changed but state is the same,
-			 * all we need to do is update the display configuration.
-			 */
-			if (adev->pm.dpm.new_active_crtcs != adev->pm.dpm.current_active_crtcs) {
-				/* update display watermarks based on new power state */
-				amdgpu_display_bandwidth_update(adev);
-				/* update displays */
-				amdgpu_dpm_display_configuration_changed(adev);
-				adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
-				adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
-			}
-			return;
-		} else {
-			/* for BTC+ if the num crtcs hasn't changed and state is the same,
-			 * nothing to do, if the num crtcs is > 1 and state is the same,
-			 * update display configuration.
-			 */
-			if (adev->pm.dpm.new_active_crtcs ==
-			    adev->pm.dpm.current_active_crtcs) {
-				return;
-			} else if ((adev->pm.dpm.current_active_crtc_count > 1) &&
-				   (adev->pm.dpm.new_active_crtc_count > 1)) {
-				/* update display watermarks based on new power state */
-				amdgpu_display_bandwidth_update(adev);
-				/* update displays */
-				amdgpu_dpm_display_configuration_changed(adev);
-				adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
-				adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
-				return;
-			}
-		}
-	}
-
-force:
 	if (amdgpu_dpm == 1) {
 		printk("switching from power state:\n");
 		amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps);
@@ -1059,31 +1040,21 @@ force:
 	/* update whether vce is active */
 	ps->vce_active = adev->pm.dpm.vce_active;
 
+	amdgpu_dpm_display_configuration_changed(adev);
+
 	ret = amdgpu_dpm_pre_set_power_state(adev);
 	if (ret)
 		return;
 
-	/* update display watermarks based on new power state */
-	amdgpu_display_bandwidth_update(adev);
+	if ((0 != amgdpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)))
+		equal = false;
 
-	/* wait for the rings to drain */
-	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
-		struct amdgpu_ring *ring = adev->rings[i];
-		if (ring && ring->ready)
-			amdgpu_fence_wait_empty(ring);
-	}
+	if (equal)
+		return;
 
-	/* program the new power state */
 	amdgpu_dpm_set_power_state(adev);
-
-	/* update current power state */
-	adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps;
-
 	amdgpu_dpm_post_set_power_state(adev);
 
-	/* update displays */
-	amdgpu_dpm_display_configuration_changed(adev);
-
 	adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs;
 	adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count;
 
@@ -1135,7 +1106,7 @@ void amdgpu_dpm_enable_vce(struct amdgpu
 			mutex_lock(&adev->pm.mutex);
 			adev->pm.dpm.vce_active = true;
 			/* XXX select vce level based on ring/task */
-			adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL;
+			adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
 			mutex_unlock(&adev->pm.mutex);
 		} else {
 			mutex_lock(&adev->pm.mutex);
@@ -1276,20 +1247,20 @@ void amdgpu_pm_compute_clocks(struct amd
 	struct drm_device *ddev = adev->ddev;
 	struct drm_crtc *crtc;
 	struct amdgpu_crtc *amdgpu_crtc;
+	int i = 0;
 
 	if (!adev->pm.dpm_enabled)
 		return;
 
-	if (adev->pp_enabled) {
-		int i = 0;
+	amdgpu_display_bandwidth_update(adev);
 
-		amdgpu_display_bandwidth_update(adev);
-		for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
-			struct amdgpu_ring *ring = adev->rings[i];
-			if (ring && ring->ready)
-				amdgpu_fence_wait_empty(ring);
-		}
+	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
+		struct amdgpu_ring *ring = adev->rings[i];
+		if (ring && ring->ready)
+			amdgpu_fence_wait_empty(ring);
+	}
 
+	if (adev->pp_enabled) {
 		amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL);
 	} else {
 		mutex_lock(&adev->pm.mutex);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,6 +98,7 @@ static int amdgpu_pp_early_init(void *ha
 	switch (adev->asic_type) {
 	case CHIP_POLARIS11:
 	case CHIP_POLARIS10:
+	case CHIP_POLARIS12:
 	case CHIP_TONGA:
 	case CHIP_FIJI:
 	case CHIP_TOPAZ:
@@ -155,9 +156,6 @@ static int amdgpu_pp_sw_init(void *handl
 		ret = adev->powerplay.ip_funcs->sw_init(
 					adev->powerplay.pp_handle);
 
-	if (adev->pp_enabled)
-		adev->pm.dpm_enabled = true;
-
 	return ret;
 }
 
@@ -187,6 +185,9 @@ static int amdgpu_pp_hw_init(void *handl
 		ret = adev->powerplay.ip_funcs->hw_init(
 					adev->powerplay.pp_handle);
 
+	if ((amdgpu_dpm != 0) && !amdgpu_sriov_vf(adev))
+		adev->pm.dpm_enabled = true;
+
 	return ret;
 }
 
@@ -299,7 +300,7 @@ static int amdgpu_pp_soft_reset(void *ha
 	return ret;
 }
 
-const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
+static const struct amd_ip_funcs amdgpu_pp_ip_funcs = {
 	.name = "amdgpu_powerplay",
 	.early_init = amdgpu_pp_early_init,
 	.late_init = amdgpu_pp_late_init,
@@ -316,3 +317,12 @@ const struct amd_ip_funcs amdgpu_pp_ip_f
 	.set_clockgating_state = amdgpu_pp_set_clockgating_state,
 	.set_powergating_state = amdgpu_pp_set_powergating_state,
 };
+
+const struct amdgpu_ip_block_version amdgpu_pp_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SMC,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &amdgpu_pp_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,11 +23,11 @@
  *
  */
 
-#ifndef __AMDGPU_POPWERPLAY_H__
-#define __AMDGPU_POPWERPLAY_H__
+#ifndef __AMDGPU_POWERPLAY_H__
+#define __AMDGPU_POWERPLAY_H__
 
 #include "amd_shared.h"
 
-extern const struct amd_ip_funcs amdgpu_pp_ip_funcs;
+extern const struct amdgpu_ip_block_version amdgpu_pp_ip_block;
 
-#endif /* __AMDSOC_DM_H__ */
+#endif /* __AMDGPU_POWERPLAY_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,7 +65,7 @@ int amdgpu_ring_alloc(struct amdgpu_ring
 {
 	/* Align requested size with padding so unlock_commit can
 	 * pad safely */
-	ndw = (ndw + ring->align_mask) & ~ring->align_mask;
+	ndw = (ndw + ring->funcs->align_mask) & ~ring->funcs->align_mask;
 
 	/* Make sure we aren't trying to allocate more space
 	 * than the maximum for one submission
@@ -94,7 +94,7 @@ void amdgpu_ring_insert_nop(struct amdgp
 	int i;
 
 	for (i = 0; i < count; i++)
-		amdgpu_ring_write(ring, ring->nop);
+		amdgpu_ring_write(ring, ring->funcs->nop);
 }
 
 /** amdgpu_ring_generic_pad_ib - pad IB with NOP packets
@@ -106,8 +106,8 @@ void amdgpu_ring_insert_nop(struct amdgp
  */
 void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib)
 {
-	while (ib->length_dw & ring->align_mask)
-		ib->ptr[ib->length_dw++] = ring->nop;
+	while (ib->length_dw & ring->funcs->align_mask)
+		ib->ptr[ib->length_dw++] = ring->funcs->nop;
 }
 
 /**
@@ -125,8 +125,9 @@ void amdgpu_ring_commit(struct amdgpu_ri
 	uint32_t count;
 
 	/* We pad to match fetch size */
-	count = ring->align_mask + 1 - (ring->wptr & ring->align_mask);
-	count %= ring->align_mask + 1;
+	count = ring->funcs->align_mask + 1 -
+		(ring->wptr & ring->funcs->align_mask);
+	count %= ring->funcs->align_mask + 1;
 	ring->funcs->insert_nop(ring, count);
 
 	mb();
@@ -163,9 +164,8 @@ void amdgpu_ring_undo(struct amdgpu_ring
  * Returns 0 on success, error on failure.
  */
 int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
-		     unsigned max_dw, u32 nop, u32 align_mask,
-		     struct amdgpu_irq_src *irq_src, unsigned irq_type,
-		     enum amdgpu_ring_type ring_type)
+		     unsigned max_dw, struct amdgpu_irq_src *irq_src,
+		     unsigned irq_type)
 {
 	int r;
 
@@ -216,9 +216,6 @@ int amdgpu_ring_init(struct amdgpu_devic
 
 	ring->ring_size = roundup_pow_of_two(max_dw * 4 *
 					     amdgpu_sched_hw_submission);
-	ring->align_mask = align_mask;
-	ring->nop = nop;
-	ring->type = ring_type;
 
 	/* Allocate ring buffer */
 	if (ring->ring_obj == NULL) {
@@ -283,7 +280,7 @@ void amdgpu_ring_fini(struct amdgpu_ring
 static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
-	struct amdgpu_ring *ring = (struct amdgpu_ring*)f->f_inode->i_private;
+	struct amdgpu_ring *ring = file_inode(f)->i_private;
 	int r, i;
 	uint32_t value, result, early[3];
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian König
+ */
+#ifndef __AMDGPU_RING_H__
+#define __AMDGPU_RING_H__
+
+#include "gpu_scheduler.h"
+
+/* max number of rings */
+#define AMDGPU_MAX_RINGS		16
+#define AMDGPU_MAX_GFX_RINGS		1
+#define AMDGPU_MAX_COMPUTE_RINGS	8
+#define AMDGPU_MAX_VCE_RINGS		3
+
+/* some special values for the owner field */
+#define AMDGPU_FENCE_OWNER_UNDEFINED	((void*)0ul)
+#define AMDGPU_FENCE_OWNER_VM		((void*)1ul)
+
+#define AMDGPU_FENCE_FLAG_64BIT         (1 << 0)
+#define AMDGPU_FENCE_FLAG_INT           (1 << 1)
+
+enum amdgpu_ring_type {
+	AMDGPU_RING_TYPE_GFX,
+	AMDGPU_RING_TYPE_COMPUTE,
+	AMDGPU_RING_TYPE_SDMA,
+	AMDGPU_RING_TYPE_UVD,
+	AMDGPU_RING_TYPE_VCE,
+	AMDGPU_RING_TYPE_KIQ
+};
+
+struct amdgpu_device;
+struct amdgpu_ring;
+struct amdgpu_ib;
+struct amdgpu_cs_parser;
+
+/*
+ * Fences.
+ */
+struct amdgpu_fence_driver {
+	uint64_t			gpu_addr;
+	volatile uint32_t		*cpu_addr;
+	/* sync_seq is protected by ring emission lock */
+	uint32_t			sync_seq;
+	atomic_t			last_seq;
+	bool				initialized;
+	struct amdgpu_irq_src		*irq_src;
+	unsigned			irq_type;
+	struct timer_list		fallback_timer;
+	unsigned			num_fences_mask;
+	spinlock_t			lock;
+	struct dma_fence		**fences;
+};
+
+int amdgpu_fence_driver_init(struct amdgpu_device *adev);
+void amdgpu_fence_driver_fini(struct amdgpu_device *adev);
+void amdgpu_fence_driver_force_completion(struct amdgpu_device *adev);
+
+int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring,
+				  unsigned num_hw_submission);
+int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
+				   struct amdgpu_irq_src *irq_src,
+				   unsigned irq_type);
+void amdgpu_fence_driver_suspend(struct amdgpu_device *adev);
+void amdgpu_fence_driver_resume(struct amdgpu_device *adev);
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence);
+void amdgpu_fence_process(struct amdgpu_ring *ring);
+int amdgpu_fence_wait_empty(struct amdgpu_ring *ring);
+unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
+
+/*
+ * Rings.
+ */
+
+/* provided by hw blocks that expose a ring buffer for commands */
+struct amdgpu_ring_funcs {
+	enum amdgpu_ring_type	type;
+	uint32_t		align_mask;
+	u32			nop;
+
+	/* ring read/write ptr handling */
+	u32 (*get_rptr)(struct amdgpu_ring *ring);
+	u32 (*get_wptr)(struct amdgpu_ring *ring);
+	void (*set_wptr)(struct amdgpu_ring *ring);
+	/* validating and patching of IBs */
+	int (*parse_cs)(struct amdgpu_cs_parser *p, uint32_t ib_idx);
+	/* constants to calculate how many DW are needed for an emit */
+	unsigned emit_frame_size;
+	unsigned emit_ib_size;
+	/* command emit functions */
+	void (*emit_ib)(struct amdgpu_ring *ring,
+			struct amdgpu_ib *ib,
+			unsigned vm_id, bool ctx_switch);
+	void (*emit_fence)(struct amdgpu_ring *ring, uint64_t addr,
+			   uint64_t seq, unsigned flags);
+	void (*emit_pipeline_sync)(struct amdgpu_ring *ring);
+	void (*emit_vm_flush)(struct amdgpu_ring *ring, unsigned vm_id,
+			      uint64_t pd_addr);
+	void (*emit_hdp_flush)(struct amdgpu_ring *ring);
+	void (*emit_hdp_invalidate)(struct amdgpu_ring *ring);
+	void (*emit_gds_switch)(struct amdgpu_ring *ring, uint32_t vmid,
+				uint32_t gds_base, uint32_t gds_size,
+				uint32_t gws_base, uint32_t gws_size,
+				uint32_t oa_base, uint32_t oa_size);
+	/* testing functions */
+	int (*test_ring)(struct amdgpu_ring *ring);
+	int (*test_ib)(struct amdgpu_ring *ring, long timeout);
+	/* insert NOP packets */
+	void (*insert_nop)(struct amdgpu_ring *ring, uint32_t count);
+	/* pad the indirect buffer to the necessary number of dw */
+	void (*pad_ib)(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
+	unsigned (*init_cond_exec)(struct amdgpu_ring *ring);
+	void (*patch_cond_exec)(struct amdgpu_ring *ring, unsigned offset);
+	/* note usage for clock and power gating */
+	void (*begin_use)(struct amdgpu_ring *ring);
+	void (*end_use)(struct amdgpu_ring *ring);
+	void (*emit_switch_buffer) (struct amdgpu_ring *ring);
+	void (*emit_cntxcntl) (struct amdgpu_ring *ring, uint32_t flags);
+};
+
+struct amdgpu_ring {
+	struct amdgpu_device		*adev;
+	const struct amdgpu_ring_funcs	*funcs;
+	struct amdgpu_fence_driver	fence_drv;
+	struct amd_gpu_scheduler	sched;
+
+	struct amdgpu_bo	*ring_obj;
+	volatile uint32_t	*ring;
+	unsigned		rptr_offs;
+	unsigned		wptr;
+	unsigned		wptr_old;
+	unsigned		ring_size;
+	unsigned		max_dw;
+	int			count_dw;
+	uint64_t		gpu_addr;
+	uint32_t		ptr_mask;
+	bool			ready;
+	u32			idx;
+	u32			me;
+	u32			pipe;
+	u32			queue;
+	struct amdgpu_bo	*mqd_obj;
+	u32			doorbell_index;
+	bool			use_doorbell;
+	unsigned		wptr_offs;
+	unsigned		fence_offs;
+	uint64_t		current_ctx;
+	char			name[16];
+	unsigned		cond_exe_offs;
+	u64			cond_exe_gpu_addr;
+	volatile u32		*cond_exe_cpu_addr;
+#if defined(CONFIG_DEBUG_FS)
+	struct dentry *ent;
+#endif
+};
+
+int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
+void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
+void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
+void amdgpu_ring_commit(struct amdgpu_ring *ring);
+void amdgpu_ring_undo(struct amdgpu_ring *ring);
+int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
+		     unsigned ring_size, struct amdgpu_irq_src *irq_src,
+		     unsigned irq_type);
+void amdgpu_ring_fini(struct amdgpu_ring *ring);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c	2017-02-12 16:03:20.000000000 -0500
@@ -147,7 +147,7 @@ static void amdgpu_sa_bo_remove_locked(s
 	}
 	list_del_init(&sa_bo->olist);
 	list_del_init(&sa_bo->flist);
-	fence_put(sa_bo->fence);
+	dma_fence_put(sa_bo->fence);
 	kfree(sa_bo);
 }
 
@@ -161,7 +161,7 @@ static void amdgpu_sa_bo_try_free(struct
 	sa_bo = list_entry(sa_manager->hole->next, struct amdgpu_sa_bo, olist);
 	list_for_each_entry_safe_from(sa_bo, tmp, &sa_manager->olist, olist) {
 		if (sa_bo->fence == NULL ||
-		    !fence_is_signaled(sa_bo->fence)) {
+		    !dma_fence_is_signaled(sa_bo->fence)) {
 			return;
 		}
 		amdgpu_sa_bo_remove_locked(sa_bo);
@@ -244,7 +244,7 @@ static bool amdgpu_sa_event(struct amdgp
 }
 
 static bool amdgpu_sa_bo_next_hole(struct amdgpu_sa_manager *sa_manager,
-				   struct fence **fences,
+				   struct dma_fence **fences,
 				   unsigned *tries)
 {
 	struct amdgpu_sa_bo *best_bo = NULL;
@@ -272,7 +272,7 @@ static bool amdgpu_sa_bo_next_hole(struc
 		sa_bo = list_first_entry(&sa_manager->flist[i],
 					 struct amdgpu_sa_bo, flist);
 
-		if (!fence_is_signaled(sa_bo->fence)) {
+		if (!dma_fence_is_signaled(sa_bo->fence)) {
 			fences[i] = sa_bo->fence;
 			continue;
 		}
@@ -314,7 +314,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma
 		     struct amdgpu_sa_bo **sa_bo,
 		     unsigned size, unsigned align)
 {
-	struct fence *fences[AMDGPU_SA_NUM_FENCE_LISTS];
+	struct dma_fence *fences[AMDGPU_SA_NUM_FENCE_LISTS];
 	unsigned tries[AMDGPU_SA_NUM_FENCE_LISTS];
 	unsigned count;
 	int i, r;
@@ -327,9 +327,8 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma
 		return -EINVAL;
 
 	*sa_bo = kmalloc(sizeof(struct amdgpu_sa_bo), GFP_KERNEL);
-	if ((*sa_bo) == NULL) {
+	if (!(*sa_bo))
 		return -ENOMEM;
-	}
 	(*sa_bo)->manager = sa_manager;
 	(*sa_bo)->fence = NULL;
 	INIT_LIST_HEAD(&(*sa_bo)->olist);
@@ -356,14 +355,15 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma
 
 		for (i = 0, count = 0; i < AMDGPU_SA_NUM_FENCE_LISTS; ++i)
 			if (fences[i])
-				fences[count++] = fence_get(fences[i]);
+				fences[count++] = dma_fence_get(fences[i]);
 
 		if (count) {
 			spin_unlock(&sa_manager->wq.lock);
-			t = fence_wait_any_timeout(fences, count, false,
-						   MAX_SCHEDULE_TIMEOUT);
+			t = dma_fence_wait_any_timeout(fences, count, false,
+						       MAX_SCHEDULE_TIMEOUT,
+						       NULL);
 			for (i = 0; i < count; ++i)
-				fence_put(fences[i]);
+				dma_fence_put(fences[i]);
 
 			r = (t > 0) ? 0 : t;
 			spin_lock(&sa_manager->wq.lock);
@@ -384,7 +384,7 @@ int amdgpu_sa_bo_new(struct amdgpu_sa_ma
 }
 
 void amdgpu_sa_bo_free(struct amdgpu_device *adev, struct amdgpu_sa_bo **sa_bo,
-		       struct fence *fence)
+		       struct dma_fence *fence)
 {
 	struct amdgpu_sa_manager *sa_manager;
 
@@ -394,10 +394,10 @@ void amdgpu_sa_bo_free(struct amdgpu_dev
 
 	sa_manager = (*sa_bo)->manager;
 	spin_lock(&sa_manager->wq.lock);
-	if (fence && !fence_is_signaled(fence)) {
+	if (fence && !dma_fence_is_signaled(fence)) {
 		uint32_t idx;
 
-		(*sa_bo)->fence = fence_get(fence);
+		(*sa_bo)->fence = dma_fence_get(fence);
 		idx = fence->context % AMDGPU_SA_NUM_FENCE_LISTS;
 		list_add_tail(&(*sa_bo)->flist, &sa_manager->flist[idx]);
 	} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 
 struct amdgpu_sync_entry {
 	struct hlist_node	node;
-	struct fence		*fence;
+	struct dma_fence	*fence;
 };
 
 static struct kmem_cache *amdgpu_sync_slab;
@@ -60,7 +60,8 @@ void amdgpu_sync_create(struct amdgpu_sy
  *
  * Test if the fence was issued by us.
  */
-static bool amdgpu_sync_same_dev(struct amdgpu_device *adev, struct fence *f)
+static bool amdgpu_sync_same_dev(struct amdgpu_device *adev,
+				 struct dma_fence *f)
 {
 	struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
 
@@ -81,7 +82,7 @@ static bool amdgpu_sync_same_dev(struct
  *
  * Extract who originally created the fence.
  */
-static void *amdgpu_sync_get_owner(struct fence *f)
+static void *amdgpu_sync_get_owner(struct dma_fence *f)
 {
 	struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
 
@@ -99,13 +100,14 @@ static void *amdgpu_sync_get_owner(struc
  *
  * Either keep the existing fence or the new one, depending which one is later.
  */
-static void amdgpu_sync_keep_later(struct fence **keep, struct fence *fence)
+static void amdgpu_sync_keep_later(struct dma_fence **keep,
+				   struct dma_fence *fence)
 {
-	if (*keep && fence_is_later(*keep, fence))
+	if (*keep && dma_fence_is_later(*keep, fence))
 		return;
 
-	fence_put(*keep);
-	*keep = fence_get(fence);
+	dma_fence_put(*keep);
+	*keep = dma_fence_get(fence);
 }
 
 /**
@@ -117,7 +119,7 @@ static void amdgpu_sync_keep_later(struc
  * Tries to add the fence to an existing hash entry. Returns true when an entry
  * was found, false otherwise.
  */
-static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct fence *f)
+static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f)
 {
 	struct amdgpu_sync_entry *e;
 
@@ -139,7 +141,7 @@ static bool amdgpu_sync_add_later(struct
  *
  */
 int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
-		      struct fence *f)
+		      struct dma_fence *f)
 {
 	struct amdgpu_sync_entry *e;
 
@@ -158,7 +160,7 @@ int amdgpu_sync_fence(struct amdgpu_devi
 		return -ENOMEM;
 
 	hash_add(sync->fences, &e->node, f->context);
-	e->fence = fence_get(f);
+	e->fence = dma_fence_get(f);
 	return 0;
 }
 
@@ -177,7 +179,7 @@ int amdgpu_sync_resv(struct amdgpu_devic
 		     void *owner)
 {
 	struct reservation_object_list *flist;
-	struct fence *f;
+	struct dma_fence *f;
 	void *fence_owner;
 	unsigned i;
 	int r = 0;
@@ -231,15 +233,15 @@ int amdgpu_sync_resv(struct amdgpu_devic
  * Returns the next fence not signaled yet without removing it from the sync
  * object.
  */
-struct fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
-				     struct amdgpu_ring *ring)
+struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
+					 struct amdgpu_ring *ring)
 {
 	struct amdgpu_sync_entry *e;
 	struct hlist_node *tmp;
 	int i;
 
 	hash_for_each_safe(sync->fences, i, tmp, e, node) {
-		struct fence *f = e->fence;
+		struct dma_fence *f = e->fence;
 		struct amd_sched_fence *s_fence = to_amd_sched_fence(f);
 
 		if (ring && s_fence) {
@@ -247,16 +249,16 @@ struct fence *amdgpu_sync_peek_fence(str
 			 * when they are scheduled.
 			 */
 			if (s_fence->sched == &ring->sched) {
-				if (fence_is_signaled(&s_fence->scheduled))
+				if (dma_fence_is_signaled(&s_fence->scheduled))
 					continue;
 
 				return &s_fence->scheduled;
 			}
 		}
 
-		if (fence_is_signaled(f)) {
+		if (dma_fence_is_signaled(f)) {
 			hash_del(&e->node);
-			fence_put(f);
+			dma_fence_put(f);
 			kmem_cache_free(amdgpu_sync_slab, e);
 			continue;
 		}
@@ -274,11 +276,11 @@ struct fence *amdgpu_sync_peek_fence(str
  *
  * Get and removes the next fence from the sync object not signaled yet.
  */
-struct fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
+struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync)
 {
 	struct amdgpu_sync_entry *e;
 	struct hlist_node *tmp;
-	struct fence *f;
+	struct dma_fence *f;
 	int i;
 
 	hash_for_each_safe(sync->fences, i, tmp, e, node) {
@@ -288,10 +290,10 @@ struct fence *amdgpu_sync_get_fence(stru
 		hash_del(&e->node);
 		kmem_cache_free(amdgpu_sync_slab, e);
 
-		if (!fence_is_signaled(f))
+		if (!dma_fence_is_signaled(f))
 			return f;
 
-		fence_put(f);
+		dma_fence_put(f);
 	}
 	return NULL;
 }
@@ -311,11 +313,11 @@ void amdgpu_sync_free(struct amdgpu_sync
 
 	hash_for_each_safe(sync->fences, i, tmp, e, node) {
 		hash_del(&e->node);
-		fence_put(e->fence);
+		dma_fence_put(e->fence);
 		kmem_cache_free(amdgpu_sync_slab, e);
 	}
 
-	fence_put(sync->last_vm_update);
+	dma_fence_put(sync->last_vm_update);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian König
+ */
+#ifndef __AMDGPU_SYNC_H__
+#define __AMDGPU_SYNC_H__
+
+#include <linux/hashtable.h>
+
+struct dma_fence;
+struct reservation_object;
+struct amdgpu_device;
+struct amdgpu_ring;
+
+/*
+ * Container for fences used to sync command submissions.
+ */
+struct amdgpu_sync {
+	DECLARE_HASHTABLE(fences, 4);
+	struct dma_fence	*last_vm_update;
+};
+
+void amdgpu_sync_create(struct amdgpu_sync *sync);
+int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
+		      struct dma_fence *f);
+int amdgpu_sync_resv(struct amdgpu_device *adev,
+		     struct amdgpu_sync *sync,
+		     struct reservation_object *resv,
+		     void *owner);
+struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
+				     struct amdgpu_ring *ring);
+struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
+void amdgpu_sync_free(struct amdgpu_sync *sync);
+int amdgpu_sync_init(void);
+void amdgpu_sync_fini(void);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c	2017-02-12 16:03:20.000000000 -0500
@@ -78,7 +78,7 @@ static void amdgpu_do_test_moves(struct
 		void *gtt_map, *vram_map;
 		void **gtt_start, **gtt_end;
 		void **vram_start, **vram_end;
-		struct fence *fence = NULL;
+		struct dma_fence *fence = NULL;
 
 		r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
 				     AMDGPU_GEM_DOMAIN_GTT, 0, NULL,
@@ -118,13 +118,13 @@ static void amdgpu_do_test_moves(struct
 			goto out_lclean_unpin;
 		}
 
-		r = fence_wait(fence, false);
+		r = dma_fence_wait(fence, false);
 		if (r) {
 			DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
 			goto out_lclean_unpin;
 		}
 
-		fence_put(fence);
+		dma_fence_put(fence);
 
 		r = amdgpu_bo_kmap(vram_obj, &vram_map);
 		if (r) {
@@ -163,13 +163,13 @@ static void amdgpu_do_test_moves(struct
 			goto out_lclean_unpin;
 		}
 
-		r = fence_wait(fence, false);
+		r = dma_fence_wait(fence, false);
 		if (r) {
 			DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
 			goto out_lclean_unpin;
 		}
 
-		fence_put(fence);
+		dma_fence_put(fence);
 
 		r = amdgpu_bo_kmap(gtt_obj[i], &gtt_map);
 		if (r) {
@@ -216,7 +216,7 @@ out_lclean:
 			amdgpu_bo_unref(&gtt_obj[i]);
 		}
 		if (fence)
-			fence_put(fence);
+			dma_fence_put(fence);
 		break;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@ TRACE_EVENT(amdgpu_cs_ioctl,
 			     __field(struct amdgpu_device *, adev)
 			     __field(struct amd_sched_job *, sched_job)
 			     __field(struct amdgpu_ib *, ib)
-			     __field(struct fence *, fence)
+			     __field(struct dma_fence *, fence)
 			     __field(char *, ring_name)
 			     __field(u32, num_ibs)
 			     ),
@@ -129,7 +129,7 @@ TRACE_EVENT(amdgpu_sched_run_job,
 			     __field(struct amdgpu_device *, adev)
 			     __field(struct amd_sched_job *, sched_job)
 			     __field(struct amdgpu_ib *, ib)
-			     __field(struct fence *, fence)
+			     __field(struct dma_fence *, fence)
 			     __field(char *, ring_name)
 			     __field(u32, num_ibs)
 			     ),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,6 @@
 #include <ttm/ttm_placement.h>
 #include <ttm/ttm_module.h>
 #include <ttm/ttm_page_alloc.h>
-#include <ttm/ttm_memory.h>
 #include <drm/drmP.h>
 #include <drm/amdgpu_drm.h>
 #include <linux/seq_file.h>
@@ -51,16 +50,6 @@
 static int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev);
 static void amdgpu_ttm_debugfs_fini(struct amdgpu_device *adev);
 
-static struct amdgpu_device *amdgpu_get_adev(struct ttm_bo_device *bdev)
-{
-	struct amdgpu_mman *mman;
-	struct amdgpu_device *adev;
-
-	mman = container_of(bdev, struct amdgpu_mman, bdev);
-	adev = container_of(mman, struct amdgpu_device, mman);
-	return adev;
-}
-
 
 /*
  * Global memory.
@@ -75,7 +64,7 @@ static void amdgpu_ttm_mem_global_releas
 	ttm_mem_global_release(ref->object);
 }
 
-int amdgpu_ttm_global_init(struct amdgpu_device *adev)
+static int amdgpu_ttm_global_init(struct amdgpu_device *adev)
 {
 	struct drm_global_reference *global_ref;
 	struct amdgpu_ring *ring;
@@ -150,7 +139,7 @@ static int amdgpu_init_mem_type(struct t
 {
 	struct amdgpu_device *adev;
 
-	adev = amdgpu_get_adev(bdev);
+	adev = amdgpu_ttm_adev(bdev);
 
 	switch (type) {
 	case TTM_PL_SYSTEM:
@@ -168,7 +157,7 @@ static int amdgpu_init_mem_type(struct t
 		break;
 	case TTM_PL_VRAM:
 		/* "On-card" video ram */
-		man->func = &ttm_bo_manager_func;
+		man->func = &amdgpu_vram_mgr_func;
 		man->gpu_offset = adev->mc.vram_start;
 		man->flags = TTM_MEMTYPE_FLAG_FIXED |
 			     TTM_MEMTYPE_FLAG_MAPPABLE;
@@ -195,6 +184,7 @@ static int amdgpu_init_mem_type(struct t
 static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
 				struct ttm_placement *placement)
 {
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
 	struct amdgpu_bo *abo;
 	static struct ttm_place placements = {
 		.fpfn = 0,
@@ -213,7 +203,7 @@ static void amdgpu_evict_flags(struct tt
 	abo = container_of(bo, struct amdgpu_bo, tbo);
 	switch (bo->mem.mem_type) {
 	case TTM_PL_VRAM:
-		if (abo->adev->mman.buffer_funcs_ring->ready == false) {
+		if (adev->mman.buffer_funcs_ring->ready == false) {
 			amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU);
 		} else {
 			amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT);
@@ -229,7 +219,7 @@ static void amdgpu_evict_flags(struct tt
 				 * allocating address space for the BO.
 				 */
 				abo->placements[i].lpfn =
-					abo->adev->mc.gtt_size >> PAGE_SHIFT;
+					adev->mc.gtt_size >> PAGE_SHIFT;
 			}
 		}
 		break;
@@ -260,63 +250,115 @@ static void amdgpu_move_null(struct ttm_
 	new_mem->mm_node = NULL;
 }
 
-static int amdgpu_move_blit(struct ttm_buffer_object *bo,
-			bool evict, bool no_wait_gpu,
-			struct ttm_mem_reg *new_mem,
-			struct ttm_mem_reg *old_mem)
+static int amdgpu_mm_node_addr(struct ttm_buffer_object *bo,
+			       struct drm_mm_node *mm_node,
+			       struct ttm_mem_reg *mem,
+			       uint64_t *addr)
 {
-	struct amdgpu_device *adev;
-	struct amdgpu_ring *ring;
-	uint64_t old_start, new_start;
-	struct fence *fence;
 	int r;
 
-	adev = amdgpu_get_adev(bo->bdev);
-	ring = adev->mman.buffer_funcs_ring;
-
-	switch (old_mem->mem_type) {
+	switch (mem->mem_type) {
 	case TTM_PL_TT:
-		r = amdgpu_ttm_bind(bo, old_mem);
+		r = amdgpu_ttm_bind(bo, mem);
 		if (r)
 			return r;
 
 	case TTM_PL_VRAM:
-		old_start = (u64)old_mem->start << PAGE_SHIFT;
-		old_start += bo->bdev->man[old_mem->mem_type].gpu_offset;
+		*addr = mm_node->start << PAGE_SHIFT;
+		*addr += bo->bdev->man[mem->mem_type].gpu_offset;
 		break;
 	default:
-		DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
+		DRM_ERROR("Unknown placement %d\n", mem->mem_type);
 		return -EINVAL;
 	}
-	switch (new_mem->mem_type) {
-	case TTM_PL_TT:
-		r = amdgpu_ttm_bind(bo, new_mem);
-		if (r)
-			return r;
 
-	case TTM_PL_VRAM:
-		new_start = (u64)new_mem->start << PAGE_SHIFT;
-		new_start += bo->bdev->man[new_mem->mem_type].gpu_offset;
-		break;
-	default:
-		DRM_ERROR("Unknown placement %d\n", old_mem->mem_type);
-		return -EINVAL;
-	}
+	return 0;
+}
+
+static int amdgpu_move_blit(struct ttm_buffer_object *bo,
+			    bool evict, bool no_wait_gpu,
+			    struct ttm_mem_reg *new_mem,
+			    struct ttm_mem_reg *old_mem)
+{
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
+	struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
+
+	struct drm_mm_node *old_mm, *new_mm;
+	uint64_t old_start, old_size, new_start, new_size;
+	unsigned long num_pages;
+	struct dma_fence *fence = NULL;
+	int r;
+
+	BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0);
+
 	if (!ring->ready) {
 		DRM_ERROR("Trying to move memory with ring turned off.\n");
 		return -EINVAL;
 	}
 
-	BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0);
+	old_mm = old_mem->mm_node;
+	r = amdgpu_mm_node_addr(bo, old_mm, old_mem, &old_start);
+	if (r)
+		return r;
+	old_size = old_mm->size;
 
-	r = amdgpu_copy_buffer(ring, old_start, new_start,
-			       new_mem->num_pages * PAGE_SIZE, /* bytes */
-			       bo->resv, &fence, false);
+
+	new_mm = new_mem->mm_node;
+	r = amdgpu_mm_node_addr(bo, new_mm, new_mem, &new_start);
 	if (r)
 		return r;
+	new_size = new_mm->size;
+
+	num_pages = new_mem->num_pages;
+	while (num_pages) {
+		unsigned long cur_pages = min(old_size, new_size);
+		struct dma_fence *next;
+
+		r = amdgpu_copy_buffer(ring, old_start, new_start,
+				       cur_pages * PAGE_SIZE,
+				       bo->resv, &next, false);
+		if (r)
+			goto error;
+
+		dma_fence_put(fence);
+		fence = next;
+
+		num_pages -= cur_pages;
+		if (!num_pages)
+			break;
+
+		old_size -= cur_pages;
+		if (!old_size) {
+			r = amdgpu_mm_node_addr(bo, ++old_mm, old_mem,
+						&old_start);
+			if (r)
+				goto error;
+			old_size = old_mm->size;
+		} else {
+			old_start += cur_pages * PAGE_SIZE;
+		}
+
+		new_size -= cur_pages;
+		if (!new_size) {
+			r = amdgpu_mm_node_addr(bo, ++new_mm, new_mem,
+						&new_start);
+			if (r)
+				goto error;
+
+			new_size = new_mm->size;
+		} else {
+			new_start += cur_pages * PAGE_SIZE;
+		}
+	}
 
 	r = ttm_bo_pipeline_move(bo, fence, evict, new_mem);
-	fence_put(fence);
+	dma_fence_put(fence);
+	return r;
+
+error:
+	if (fence)
+		dma_fence_wait(fence, false);
+	dma_fence_put(fence);
 	return r;
 }
 
@@ -332,7 +374,7 @@ static int amdgpu_move_vram_ram(struct t
 	struct ttm_placement placement;
 	int r;
 
-	adev = amdgpu_get_adev(bo->bdev);
+	adev = amdgpu_ttm_adev(bo->bdev);
 	tmp_mem = *new_mem;
 	tmp_mem.mm_node = NULL;
 	placement.num_placement = 1;
@@ -379,7 +421,7 @@ static int amdgpu_move_ram_vram(struct t
 	struct ttm_place placements;
 	int r;
 
-	adev = amdgpu_get_adev(bo->bdev);
+	adev = amdgpu_ttm_adev(bo->bdev);
 	tmp_mem = *new_mem;
 	tmp_mem.mm_node = NULL;
 	placement.num_placement = 1;
@@ -422,7 +464,7 @@ static int amdgpu_bo_move(struct ttm_buf
 	if (WARN_ON_ONCE(abo->pin_count > 0))
 		return -EINVAL;
 
-	adev = amdgpu_get_adev(bo->bdev);
+	adev = amdgpu_ttm_adev(bo->bdev);
 
 	/* remember the eviction */
 	if (evict)
@@ -475,7 +517,7 @@ memcpy:
 static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
 	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
-	struct amdgpu_device *adev = amdgpu_get_adev(bdev);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
 
 	mem->bus.addr = NULL;
 	mem->bus.offset = 0;
@@ -607,7 +649,7 @@ release_pages:
 /* prepare the sg table with the user pages */
 static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
 {
-	struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
 	struct amdgpu_ttm_tt *gtt = (void *)ttm;
 	unsigned nents;
 	int r;
@@ -639,7 +681,7 @@ release_sg:
 
 static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
 {
-	struct amdgpu_device *adev = amdgpu_get_adev(ttm->bdev);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
 	struct amdgpu_ttm_tt *gtt = (void *)ttm;
 	struct sg_page_iter sg_iter;
 
@@ -799,7 +841,7 @@ static struct ttm_tt *amdgpu_ttm_tt_crea
 	struct amdgpu_device *adev;
 	struct amdgpu_ttm_tt *gtt;
 
-	adev = amdgpu_get_adev(bdev);
+	adev = amdgpu_ttm_adev(bdev);
 
 	gtt = kzalloc(sizeof(struct amdgpu_ttm_tt), GFP_KERNEL);
 	if (gtt == NULL) {
@@ -843,7 +885,7 @@ static int amdgpu_ttm_tt_populate(struct
 		return 0;
 	}
 
-	adev = amdgpu_get_adev(ttm->bdev);
+	adev = amdgpu_ttm_adev(ttm->bdev);
 
 #ifdef CONFIG_SWIOTLB
 	if (swiotlb_nr_tbl()) {
@@ -889,7 +931,7 @@ static void amdgpu_ttm_tt_unpopulate(str
 	if (slave)
 		return;
 
-	adev = amdgpu_get_adev(ttm->bdev);
+	adev = amdgpu_ttm_adev(ttm->bdev);
 
 #ifdef CONFIG_SWIOTLB
 	if (swiotlb_nr_tbl()) {
@@ -1012,7 +1054,7 @@ uint32_t amdgpu_ttm_tt_pte_flags(struct
 
 static void amdgpu_ttm_lru_removal(struct ttm_buffer_object *tbo)
 {
-	struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
 	unsigned i, j;
 
 	for (i = 0; i < AMDGPU_TTM_LRU_SIZE; ++i) {
@@ -1029,7 +1071,7 @@ static void amdgpu_ttm_lru_removal(struc
 
 static struct amdgpu_mman_lru *amdgpu_ttm_lru(struct ttm_buffer_object *tbo)
 {
-	struct amdgpu_device *adev = amdgpu_get_adev(tbo->bdev);
+	struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev);
 	unsigned log2_size = min(ilog2(tbo->num_pages),
 				 AMDGPU_TTM_LRU_SIZE - 1);
 
@@ -1060,12 +1102,37 @@ static struct list_head *amdgpu_ttm_swap
 	return res;
 }
 
+static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
+					    const struct ttm_place *place)
+{
+	if (bo->mem.mem_type == TTM_PL_VRAM &&
+	    bo->mem.start == AMDGPU_BO_INVALID_OFFSET) {
+		unsigned long num_pages = bo->mem.num_pages;
+		struct drm_mm_node *node = bo->mem.mm_node;
+
+		/* Check each drm MM node individually */
+		while (num_pages) {
+			if (place->fpfn < (node->start + node->size) &&
+			    !(place->lpfn && place->lpfn <= node->start))
+				return true;
+
+			num_pages -= node->size;
+			++node;
+		}
+
+		return false;
+	}
+
+	return ttm_bo_eviction_valuable(bo, place);
+}
+
 static struct ttm_bo_driver amdgpu_bo_driver = {
 	.ttm_tt_create = &amdgpu_ttm_tt_create,
 	.ttm_tt_populate = &amdgpu_ttm_tt_populate,
 	.ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate,
 	.invalidate_caches = &amdgpu_invalidate_caches,
 	.init_mem_type = &amdgpu_init_mem_type,
+	.eviction_valuable = amdgpu_ttm_bo_eviction_valuable,
 	.evict_flags = &amdgpu_evict_flags,
 	.move = &amdgpu_bo_move,
 	.verify_access = &amdgpu_verify_access,
@@ -1083,6 +1150,10 @@ int amdgpu_ttm_init(struct amdgpu_device
 	unsigned i, j;
 	int r;
 
+	r = amdgpu_ttm_global_init(adev);
+	if (r) {
+		return r;
+	}
 	/* No others user of address space so set it to 0 */
 	r = ttm_bo_device_init(&adev->mman.bdev,
 			       adev->mman.bo_global_ref.ref.object,
@@ -1119,7 +1190,8 @@ int amdgpu_ttm_init(struct amdgpu_device
 
 	r = amdgpu_bo_create(adev, 256 * 1024, PAGE_SIZE, true,
 			     AMDGPU_GEM_DOMAIN_VRAM,
-			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+			     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 			     NULL, NULL, &adev->stollen_vga_memory);
 	if (r) {
 		return r;
@@ -1247,7 +1319,7 @@ int amdgpu_copy_buffer(struct amdgpu_rin
 		       uint64_t dst_offset,
 		       uint32_t byte_count,
 		       struct reservation_object *resv,
-		       struct fence **fence, bool direct_submit)
+		       struct dma_fence **fence, bool direct_submit)
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_job *job;
@@ -1294,7 +1366,7 @@ int amdgpu_copy_buffer(struct amdgpu_rin
 	if (direct_submit) {
 		r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs,
 				       NULL, NULL, fence);
-		job->fence = fence_get(*fence);
+		job->fence = dma_fence_get(*fence);
 		if (r)
 			DRM_ERROR("Error scheduling IBs (%d)\n", r);
 		amdgpu_job_free(job);
@@ -1313,28 +1385,40 @@ error_free:
 }
 
 int amdgpu_fill_buffer(struct amdgpu_bo *bo,
-		uint32_t src_data,
-		struct reservation_object *resv,
-		struct fence **fence)
+		       uint32_t src_data,
+		       struct reservation_object *resv,
+		       struct dma_fence **fence)
 {
-	struct amdgpu_device *adev = bo->adev;
-	struct amdgpu_job *job;
+	struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+	uint32_t max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
 	struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring;
 
-	uint32_t max_bytes, byte_count;
-	uint64_t dst_offset;
+	struct drm_mm_node *mm_node;
+	unsigned long num_pages;
 	unsigned int num_loops, num_dw;
-	unsigned int i;
+
+	struct amdgpu_job *job;
 	int r;
 
-	byte_count = bo->tbo.num_pages << PAGE_SHIFT;
-	max_bytes = adev->mman.buffer_funcs->fill_max_bytes;
-	num_loops = DIV_ROUND_UP(byte_count, max_bytes);
+	if (!ring->ready) {
+		DRM_ERROR("Trying to clear memory with ring turned off.\n");
+		return -EINVAL;
+	}
+
+	num_pages = bo->tbo.num_pages;
+	mm_node = bo->tbo.mem.mm_node;
+	num_loops = 0;
+	while (num_pages) {
+		uint32_t byte_count = mm_node->size << PAGE_SHIFT;
+
+		num_loops += DIV_ROUND_UP(byte_count, max_bytes);
+		num_pages -= mm_node->size;
+		++mm_node;
+	}
 	num_dw = num_loops * adev->mman.buffer_funcs->fill_num_dw;
 
 	/* for IB padding */
-	while (num_dw & 0x7)
-		num_dw++;
+	num_dw += 64;
 
 	r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, &job);
 	if (r)
@@ -1342,28 +1426,43 @@ int amdgpu_fill_buffer(struct amdgpu_bo
 
 	if (resv) {
 		r = amdgpu_sync_resv(adev, &job->sync, resv,
-				AMDGPU_FENCE_OWNER_UNDEFINED);
+				     AMDGPU_FENCE_OWNER_UNDEFINED);
 		if (r) {
 			DRM_ERROR("sync failed (%d).\n", r);
 			goto error_free;
 		}
 	}
 
-	dst_offset = bo->tbo.mem.start << PAGE_SHIFT;
-	for (i = 0; i < num_loops; i++) {
-		uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
+	num_pages = bo->tbo.num_pages;
+	mm_node = bo->tbo.mem.mm_node;
 
-		amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data,
-				dst_offset, cur_size_in_bytes);
+	while (num_pages) {
+		uint32_t byte_count = mm_node->size << PAGE_SHIFT;
+		uint64_t dst_addr;
 
-		dst_offset += cur_size_in_bytes;
-		byte_count -= cur_size_in_bytes;
+		r = amdgpu_mm_node_addr(&bo->tbo, mm_node,
+					&bo->tbo.mem, &dst_addr);
+		if (r)
+			return r;
+
+		while (byte_count) {
+			uint32_t cur_size_in_bytes = min(byte_count, max_bytes);
+
+			amdgpu_emit_fill_buffer(adev, &job->ibs[0], src_data,
+						dst_addr, cur_size_in_bytes);
+
+			dst_addr += cur_size_in_bytes;
+			byte_count -= cur_size_in_bytes;
+		}
+
+		num_pages -= mm_node->size;
+		++mm_node;
 	}
 
 	amdgpu_ring_pad_ib(ring, &job->ibs[0]);
 	WARN_ON(job->ibs[0].length_dw > num_dw);
 	r = amdgpu_job_submit(job, ring, &adev->mman.entity,
-			AMDGPU_FENCE_OWNER_UNDEFINED, fence);
+			      AMDGPU_FENCE_OWNER_UNDEFINED, fence);
 	if (r)
 		goto error_free;
 
@@ -1412,7 +1511,7 @@ static const struct drm_info_list amdgpu
 static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf,
 				    size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -1456,7 +1555,7 @@ static const struct file_operations amdg
 static ssize_t amdgpu_ttm_gtt_read(struct file *f, char __user *buf,
 				   size_t size, loff_t *pos)
 {
-	struct amdgpu_device *adev = f->f_inode->i_private;
+	struct amdgpu_device *adev = file_inode(f)->i_private;
 	ssize_t result = 0;
 	int r;
 
@@ -1554,8 +1653,3 @@ static void amdgpu_ttm_debugfs_fini(stru
 
 #endif
 }
-
-u64 amdgpu_ttm_get_gtt_mem_size(struct amdgpu_device *adev)
-{
-	return ttm_get_kernel_zone_memory_size(adev->mman.mem_global_ref.object);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h	2017-02-12 16:03:20.000000000 -0500
@@ -66,6 +66,7 @@ struct amdgpu_mman {
 };
 
 extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func;
+extern const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func;
 
 int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
 			 struct ttm_buffer_object *tbo,
@@ -77,11 +78,11 @@ int amdgpu_copy_buffer(struct amdgpu_rin
 		       uint64_t dst_offset,
 		       uint32_t byte_count,
 		       struct reservation_object *resv,
-		       struct fence **fence, bool direct_submit);
+		       struct dma_fence **fence, bool direct_submit);
 int amdgpu_fill_buffer(struct amdgpu_bo *bo,
 			uint32_t src_data,
 			struct reservation_object *resv,
-			struct fence **fence);
+			struct dma_fence **fence);
 
 int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma);
 bool amdgpu_ttm_is_bound(struct ttm_tt *ttm);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c	2017-02-12 16:03:20.000000000 -0500
@@ -228,6 +228,9 @@ static int amdgpu_ucode_init_single_fw(s
 	ucode->mc_addr = mc_addr;
 	ucode->kaddr = kptr;
 
+	if (ucode->ucode_id == AMDGPU_UCODE_ID_STORAGE)
+		return 0;
+
 	header = (const struct common_firmware_header *)ucode->fw->data;
 	memcpy(ucode->kaddr, (void *)((uint8_t *)ucode->fw->data +
 		le32_to_cpu(header->ucode_array_offset_bytes)),
@@ -236,6 +239,31 @@ static int amdgpu_ucode_init_single_fw(s
 	return 0;
 }
 
+static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode,
+				uint64_t mc_addr, void *kptr)
+{
+	const struct gfx_firmware_header_v1_0 *header = NULL;
+	const struct common_firmware_header *comm_hdr = NULL;
+	uint8_t* src_addr = NULL;
+	uint8_t* dst_addr = NULL;
+
+	if (NULL == ucode->fw)
+		return 0;
+
+	comm_hdr = (const struct common_firmware_header *)ucode->fw->data;
+	header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+	dst_addr = ucode->kaddr +
+			   ALIGN(le32_to_cpu(comm_hdr->ucode_size_bytes),
+			   PAGE_SIZE);
+	src_addr = (uint8_t *)ucode->fw->data +
+			   le32_to_cpu(comm_hdr->ucode_array_offset_bytes) +
+			   (le32_to_cpu(header->jt_offset) * 4);
+	memcpy(dst_addr, src_addr, le32_to_cpu(header->jt_size) * 4);
+
+	return 0;
+}
+
+
 int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
 {
 	struct amdgpu_bo **bo = &adev->firmware.fw_buf;
@@ -247,7 +275,8 @@ int amdgpu_ucode_init_bo(struct amdgpu_d
 	const struct common_firmware_header *header = NULL;
 
 	err = amdgpu_bo_create(adev, adev->firmware.fw_size, PAGE_SIZE, true,
-			       AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL, bo);
+				amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
+				0, NULL, NULL, bo);
 	if (err) {
 		dev_err(adev->dev, "(%d) Firmware buffer allocate failed\n", err);
 		goto failed;
@@ -259,7 +288,8 @@ int amdgpu_ucode_init_bo(struct amdgpu_d
 		goto failed_reserve;
 	}
 
-	err = amdgpu_bo_pin(*bo, AMDGPU_GEM_DOMAIN_GTT, &fw_mc_addr);
+	err = amdgpu_bo_pin(*bo, amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
+				&fw_mc_addr);
 	if (err) {
 		dev_err(adev->dev, "(%d) Firmware buffer pin failed\n", err);
 		goto failed_pin;
@@ -279,6 +309,13 @@ int amdgpu_ucode_init_bo(struct amdgpu_d
 			header = (const struct common_firmware_header *)ucode->fw->data;
 			amdgpu_ucode_init_single_fw(ucode, fw_mc_addr + fw_offset,
 						    fw_buf_ptr + fw_offset);
+			if (i == AMDGPU_UCODE_ID_CP_MEC1) {
+				const struct gfx_firmware_header_v1_0 *cp_hdr;
+				cp_hdr = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
+				amdgpu_ucode_patch_jt(ucode, fw_mc_addr + fw_offset,
+						    fw_buf_ptr + fw_offset);
+				fw_offset += ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
+			}
 			fw_offset += ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h	2017-02-12 16:03:20.000000000 -0500
@@ -130,6 +130,7 @@ enum AMDGPU_UCODE_ID {
 	AMDGPU_UCODE_ID_CP_MEC1,
 	AMDGPU_UCODE_ID_CP_MEC2,
 	AMDGPU_UCODE_ID_RLC_G,
+	AMDGPU_UCODE_ID_STORAGE,
 	AMDGPU_UCODE_ID_MAXIMUM,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c	2016-12-11 17:40:56.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c	2017-02-12 17:23:37.000000000 -0500
@@ -65,6 +65,7 @@
 #define FIRMWARE_STONEY		"/*(DEBLOBBED)*/"
 #define FIRMWARE_POLARIS10	"/*(DEBLOBBED)*/"
 #define FIRMWARE_POLARIS11	"/*(DEBLOBBED)*/"
+#define FIRMWARE_POLARIS12	"/*(DEBLOBBED)*/"
 
 /**
  * amdgpu_uvd_cs_ctx - Command submission parser context
@@ -140,6 +141,9 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
 	case CHIP_POLARIS11:
 		fw_name = FIRMWARE_POLARIS11;
 		break;
+	case CHIP_POLARIS12:
+		fw_name = FIRMWARE_POLARIS12;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -324,7 +328,7 @@ void amdgpu_uvd_free_handles(struct amdg
 	for (i = 0; i < adev->uvd.max_handles; ++i) {
 		uint32_t handle = atomic_read(&adev->uvd.handles[i]);
 		if (handle != 0 && adev->uvd.filp[i] == filp) {
-			struct fence *fence;
+			struct dma_fence *fence;
 
 			r = amdgpu_uvd_get_destroy_msg(ring, handle,
 						       false, &fence);
@@ -333,8 +337,8 @@ void amdgpu_uvd_free_handles(struct amdg
 				continue;
 			}
 
-			fence_wait(fence, false);
-			fence_put(fence);
+			dma_fence_wait(fence, false);
+			dma_fence_put(fence);
 
 			adev->uvd.filp[i] = NULL;
 			atomic_set(&adev->uvd.handles[i], 0);
@@ -351,6 +355,18 @@ static void amdgpu_uvd_force_into_uvd_se
 	}
 }
 
+static u64 amdgpu_uvd_get_addr_from_ctx(struct amdgpu_uvd_cs_ctx *ctx)
+{
+	uint32_t lo, hi;
+	uint64_t addr;
+
+	lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0);
+	hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1);
+	addr = ((uint64_t)lo) | (((uint64_t)hi) << 32);
+
+	return addr;
+}
+
 /**
  * amdgpu_uvd_cs_pass1 - first parsing round
  *
@@ -363,14 +379,10 @@ static int amdgpu_uvd_cs_pass1(struct am
 {
 	struct amdgpu_bo_va_mapping *mapping;
 	struct amdgpu_bo *bo;
-	uint32_t cmd, lo, hi;
-	uint64_t addr;
+	uint32_t cmd;
+	uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx);
 	int r = 0;
 
-	lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0);
-	hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1);
-	addr = ((uint64_t)lo) | (((uint64_t)hi) << 32);
-
 	mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo);
 	if (mapping == NULL) {
 		DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr);
@@ -689,18 +701,16 @@ static int amdgpu_uvd_cs_pass2(struct am
 {
 	struct amdgpu_bo_va_mapping *mapping;
 	struct amdgpu_bo *bo;
-	uint32_t cmd, lo, hi;
+	uint32_t cmd;
 	uint64_t start, end;
-	uint64_t addr;
+	uint64_t addr = amdgpu_uvd_get_addr_from_ctx(ctx);
 	int r;
 
-	lo = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data0);
-	hi = amdgpu_get_ib_value(ctx->parser, ctx->ib_idx, ctx->data1);
-	addr = ((uint64_t)lo) | (((uint64_t)hi) << 32);
-
 	mapping = amdgpu_cs_find_mapping(ctx->parser, addr, &bo);
-	if (mapping == NULL)
+	if (mapping == NULL) {
+		DRM_ERROR("Can't find BO for addr 0x%08Lx\n", addr);
 		return -EINVAL;
+	}
 
 	start = amdgpu_bo_gpu_offset(bo);
 
@@ -867,6 +877,9 @@ int amdgpu_uvd_ring_parse_cs(struct amdg
 	struct amdgpu_ib *ib = &parser->job->ibs[ib_idx];
 	int r;
 
+	parser->job->vm = NULL;
+	ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
+
 	if (ib->length_dw % 16) {
 		DRM_ERROR("UVD IB length (%d) not 16 dwords aligned!\n",
 			  ib->length_dw);
@@ -881,10 +894,13 @@ int amdgpu_uvd_ring_parse_cs(struct amdg
 	ctx.buf_sizes = buf_sizes;
 	ctx.ib_idx = ib_idx;
 
-	/* first round, make sure the buffers are actually in the UVD segment */
-	r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass1);
-	if (r)
-		return r;
+	/* first round only required on chips without UVD 64 bit address support */
+	if (!parser->adev->uvd.address_64_bit) {
+		/* first round, make sure the buffers are actually in the UVD segment */
+		r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass1);
+		if (r)
+			return r;
+	}
 
 	/* second round, patch buffer addresses into the command stream */
 	r = amdgpu_uvd_cs_packets(&ctx, amdgpu_uvd_cs_pass2);
@@ -900,14 +916,14 @@ int amdgpu_uvd_ring_parse_cs(struct amdg
 }
 
 static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
-			       bool direct, struct fence **fence)
+			       bool direct, struct dma_fence **fence)
 {
 	struct ttm_validate_buffer tv;
 	struct ww_acquire_ctx ticket;
 	struct list_head head;
 	struct amdgpu_job *job;
 	struct amdgpu_ib *ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	struct amdgpu_device *adev = ring->adev;
 	uint64_t addr;
 	int i, r;
@@ -922,7 +938,7 @@ static int amdgpu_uvd_send_msg(struct am
 	if (r)
 		return r;
 
-	if (!bo->adev->uvd.address_64_bit) {
+	if (!ring->adev->uvd.address_64_bit) {
 		amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
 		amdgpu_uvd_force_into_uvd_segment(bo);
 	}
@@ -951,7 +967,7 @@ static int amdgpu_uvd_send_msg(struct am
 
 	if (direct) {
 		r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
-		job->fence = fence_get(f);
+		job->fence = dma_fence_get(f);
 		if (r)
 			goto err_free;
 
@@ -966,9 +982,9 @@ static int amdgpu_uvd_send_msg(struct am
 	ttm_eu_fence_buffer_objects(&ticket, &head, f);
 
 	if (fence)
-		*fence = fence_get(f);
+		*fence = dma_fence_get(f);
 	amdgpu_bo_unref(&bo);
-	fence_put(f);
+	dma_fence_put(f);
 
 	return 0;
 
@@ -984,7 +1000,7 @@ err:
    crash the vcpu so just try to emmit a dummy create/destroy msg to
    avoid this */
 int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-			      struct fence **fence)
+			      struct dma_fence **fence)
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_bo *bo;
@@ -993,7 +1009,8 @@ int amdgpu_uvd_get_create_msg(struct amd
 
 	r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
 			     AMDGPU_GEM_DOMAIN_VRAM,
-			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+			     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 			     NULL, NULL, &bo);
 	if (r)
 		return r;
@@ -1033,7 +1050,7 @@ int amdgpu_uvd_get_create_msg(struct amd
 }
 
 int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-			       bool direct, struct fence **fence)
+			       bool direct, struct dma_fence **fence)
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_bo *bo;
@@ -1042,7 +1059,8 @@ int amdgpu_uvd_get_destroy_msg(struct am
 
 	r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true,
 			     AMDGPU_GEM_DOMAIN_VRAM,
-			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+			     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 			     NULL, NULL, &bo);
 	if (r)
 		return r;
@@ -1119,7 +1137,7 @@ void amdgpu_uvd_ring_end_use(struct amdg
  */
 int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 {
-	struct fence *fence;
+	struct dma_fence *fence;
 	long r;
 
 	r = amdgpu_uvd_get_create_msg(ring, 1, NULL);
@@ -1134,7 +1152,7 @@ int amdgpu_uvd_ring_test_ib(struct amdgp
 		goto error;
 	}
 
-	r = fence_wait_timeout(fence, false, timeout);
+	r = dma_fence_wait_timeout(fence, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out.\n");
 		r = -ETIMEDOUT;
@@ -1145,7 +1163,7 @@ int amdgpu_uvd_ring_test_ib(struct amdgp
 		r = 0;
 	}
 
-	fence_put(fence);
+	dma_fence_put(fence);
 
 error:
 	return r;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,9 +29,9 @@ int amdgpu_uvd_sw_fini(struct amdgpu_dev
 int amdgpu_uvd_suspend(struct amdgpu_device *adev);
 int amdgpu_uvd_resume(struct amdgpu_device *adev);
 int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-			      struct fence **fence);
+			      struct dma_fence **fence);
 int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-			       bool direct, struct fence **fence);
+			       bool direct, struct dma_fence **fence);
 void amdgpu_uvd_free_handles(struct amdgpu_device *adev,
 			     struct drm_file *filp);
 int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c	2016-12-11 17:40:59.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c	2017-02-12 17:23:40.000000000 -0500
@@ -52,6 +52,7 @@
 #define FIRMWARE_STONEY		"/*(DEBLOBBED)*/"
 #define FIRMWARE_POLARIS10	"/*(DEBLOBBED)*/"
 #define FIRMWARE_POLARIS11         "/*(DEBLOBBED)*/"
+#define FIRMWARE_POLARIS12         "/*(DEBLOBBED)*/"
 
 #ifdef CONFIG_DRM_AMDGPU_CIK
 /*(DEBLOBBED)*/
@@ -112,6 +113,9 @@ int amdgpu_vce_sw_init(struct amdgpu_dev
 	case CHIP_POLARIS11:
 		fw_name = FIRMWARE_POLARIS11;
 		break;
+	case CHIP_POLARIS12:
+		fw_name = FIRMWARE_POLARIS12;
+		break;
 
 	default:
 		return -EINVAL;
@@ -148,7 +152,8 @@ int amdgpu_vce_sw_init(struct amdgpu_dev
 
 	r = amdgpu_bo_create(adev, size, PAGE_SIZE, true,
 			     AMDGPU_GEM_DOMAIN_VRAM,
-			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+			     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+			     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 			     NULL, NULL, &adev->vce.vcpu_bo);
 	if (r) {
 		dev_err(adev->dev, "(%d) failed to allocate VCE bo\n", r);
@@ -386,12 +391,12 @@ void amdgpu_vce_free_handles(struct amdg
  * Open up a stream for HW test
  */
 int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-			      struct fence **fence)
+			      struct dma_fence **fence)
 {
 	const unsigned ib_size_dw = 1024;
 	struct amdgpu_job *job;
 	struct amdgpu_ib *ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	uint64_t dummy;
 	int i, r;
 
@@ -441,14 +446,14 @@ int amdgpu_vce_get_create_msg(struct amd
 		ib->ptr[i] = 0x0;
 
 	r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
-	job->fence = fence_get(f);
+	job->fence = dma_fence_get(f);
 	if (r)
 		goto err;
 
 	amdgpu_job_free(job);
 	if (fence)
-		*fence = fence_get(f);
-	fence_put(f);
+		*fence = dma_fence_get(f);
+	dma_fence_put(f);
 	return 0;
 
 err:
@@ -467,12 +472,12 @@ err:
  * Close up a stream for HW test or if userspace failed to do so
  */
 int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-			       bool direct, struct fence **fence)
+			       bool direct, struct dma_fence **fence)
 {
 	const unsigned ib_size_dw = 1024;
 	struct amdgpu_job *job;
 	struct amdgpu_ib *ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	int i, r;
 
 	r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
@@ -504,7 +509,7 @@ int amdgpu_vce_get_destroy_msg(struct am
 
 	if (direct) {
 		r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f);
-		job->fence = fence_get(f);
+		job->fence = dma_fence_get(f);
 		if (r)
 			goto err;
 
@@ -517,8 +522,8 @@ int amdgpu_vce_get_destroy_msg(struct am
 	}
 
 	if (fence)
-		*fence = fence_get(f);
-	fence_put(f);
+		*fence = dma_fence_get(f);
+	dma_fence_put(f);
 	return 0;
 
 err:
@@ -632,6 +637,9 @@ int amdgpu_vce_ring_parse_cs(struct amdg
 	uint32_t *size = &tmp;
 	int i, r, idx = 0;
 
+	p->job->vm = NULL;
+	ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
+
 	r = amdgpu_cs_sysvm_access_required(p);
 	if (r)
 		return r;
@@ -779,6 +787,96 @@ out:
 }
 
 /**
+ * amdgpu_vce_cs_parse_vm - parse the command stream in VM mode
+ *
+ * @p: parser context
+ *
+ */
+int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx)
+{
+	struct amdgpu_ib *ib = &p->job->ibs[ib_idx];
+	int session_idx = -1;
+	uint32_t destroyed = 0;
+	uint32_t created = 0;
+	uint32_t allocated = 0;
+	uint32_t tmp, handle = 0;
+	int i, r = 0, idx = 0;
+
+	while (idx < ib->length_dw) {
+		uint32_t len = amdgpu_get_ib_value(p, ib_idx, idx);
+		uint32_t cmd = amdgpu_get_ib_value(p, ib_idx, idx + 1);
+
+		if ((len < 8) || (len & 3)) {
+			DRM_ERROR("invalid VCE command length (%d)!\n", len);
+			r = -EINVAL;
+			goto out;
+		}
+
+		switch (cmd) {
+		case 0x00000001: /* session */
+			handle = amdgpu_get_ib_value(p, ib_idx, idx + 2);
+			session_idx = amdgpu_vce_validate_handle(p, handle,
+								 &allocated);
+			if (session_idx < 0) {
+				r = session_idx;
+				goto out;
+			}
+			break;
+
+		case 0x01000001: /* create */
+			created |= 1 << session_idx;
+			if (destroyed & (1 << session_idx)) {
+				destroyed &= ~(1 << session_idx);
+				allocated |= 1 << session_idx;
+
+			} else if (!(allocated & (1 << session_idx))) {
+				DRM_ERROR("Handle already in use!\n");
+				r = -EINVAL;
+				goto out;
+			}
+
+			break;
+
+		case 0x02000001: /* destroy */
+			destroyed |= 1 << session_idx;
+			break;
+
+		default:
+			break;
+		}
+
+		if (session_idx == -1) {
+			DRM_ERROR("no session command at start of IB\n");
+			r = -EINVAL;
+			goto out;
+		}
+
+		idx += len / 4;
+	}
+
+	if (allocated & ~created) {
+		DRM_ERROR("New session without create command!\n");
+		r = -ENOENT;
+	}
+
+out:
+	if (!r) {
+		/* No error, free all destroyed handle slots */
+		tmp = destroyed;
+		amdgpu_ib_free(p->adev, ib, NULL);
+	} else {
+		/* Error during parsing, free all allocated handle slots */
+		tmp = allocated;
+	}
+
+	for (i = 0; i < AMDGPU_MAX_VCE_HANDLES; ++i)
+		if (tmp & (1 << i))
+			atomic_set(&p->adev->vce.handles[i], 0);
+
+	return r;
+}
+
+/**
  * amdgpu_vce_ring_emit_ib - execute indirect buffer
  *
  * @ring: engine to use
@@ -814,18 +912,6 @@ void amdgpu_vce_ring_emit_fence(struct a
 	amdgpu_ring_write(ring, VCE_CMD_END);
 }
 
-unsigned amdgpu_vce_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		4; /* amdgpu_vce_ring_emit_ib */
-}
-
-unsigned amdgpu_vce_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		6; /* amdgpu_vce_ring_emit_fence  x1 no user fence */
-}
-
 /**
  * amdgpu_vce_ring_test_ring - test if VCE ring is working
  *
@@ -874,7 +960,7 @@ int amdgpu_vce_ring_test_ring(struct amd
  */
 int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 {
-	struct fence *fence = NULL;
+	struct dma_fence *fence = NULL;
 	long r;
 
 	/* skip vce ring1/2 ib test for now, since it's not reliable */
@@ -893,7 +979,7 @@ int amdgpu_vce_ring_test_ib(struct amdgp
 		goto error;
 	}
 
-	r = fence_wait_timeout(fence, false, timeout);
+	r = dma_fence_wait_timeout(fence, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out.\n");
 		r = -ETIMEDOUT;
@@ -904,6 +990,6 @@ int amdgpu_vce_ring_test_ib(struct amdgp
 		r = 0;
 	}
 error:
-	fence_put(fence);
+	dma_fence_put(fence);
 	return r;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,11 +29,12 @@ int amdgpu_vce_sw_fini(struct amdgpu_dev
 int amdgpu_vce_suspend(struct amdgpu_device *adev);
 int amdgpu_vce_resume(struct amdgpu_device *adev);
 int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
-			      struct fence **fence);
+			      struct dma_fence **fence);
 int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
-			       bool direct, struct fence **fence);
+			       bool direct, struct dma_fence **fence);
 void amdgpu_vce_free_handles(struct amdgpu_device *adev, struct drm_file *filp);
 int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx);
+int amdgpu_vce_ring_parse_cs_vm(struct amdgpu_cs_parser *p, uint32_t ib_idx);
 void amdgpu_vce_ring_emit_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib,
 			     unsigned vm_id, bool ctx_switch);
 void amdgpu_vce_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
  *          Alex Deucher
  *          Jerome Glisse
  */
-#include <linux/fence-array.h>
+#include <linux/dma-fence-array.h>
 #include <drm/drmP.h>
 #include <drm/amdgpu_drm.h>
 #include "amdgpu.h"
@@ -116,38 +116,43 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_v
 }
 
 /**
- * amdgpu_vm_get_bos - add the vm BOs to a duplicates list
+ * amdgpu_vm_validate_pt_bos - validate the page table BOs
  *
  * @adev: amdgpu device pointer
  * @vm: vm providing the BOs
- * @duplicates: head of duplicates list
+ * @validate: callback to do the validation
+ * @param: parameter for the validation callback
  *
- * Add the page directory to the BO duplicates list
- * for command submission.
+ * Validate the page table BOs on command submission if neccessary.
  */
-void amdgpu_vm_get_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-			  struct list_head *duplicates)
+int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+			      int (*validate)(void *p, struct amdgpu_bo *bo),
+			      void *param)
 {
 	uint64_t num_evictions;
 	unsigned i;
+	int r;
 
 	/* We only need to validate the page tables
 	 * if they aren't already valid.
 	 */
 	num_evictions = atomic64_read(&adev->num_evictions);
 	if (num_evictions == vm->last_eviction_counter)
-		return;
+		return 0;
 
 	/* add the vm page table to the list */
 	for (i = 0; i <= vm->max_pde_used; ++i) {
-		struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry;
+		struct amdgpu_bo *bo = vm->page_tables[i].bo;
 
-		if (!entry->robj)
+		if (!bo)
 			continue;
 
-		list_add(&entry->tv.head, duplicates);
+		r = validate(param, bo);
+		if (r)
+			return r;
 	}
 
+	return 0;
 }
 
 /**
@@ -166,12 +171,12 @@ void amdgpu_vm_move_pt_bos_in_lru(struct
 
 	spin_lock(&glob->lru_lock);
 	for (i = 0; i <= vm->max_pde_used; ++i) {
-		struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry;
+		struct amdgpu_bo *bo = vm->page_tables[i].bo;
 
-		if (!entry->robj)
+		if (!bo)
 			continue;
 
-		ttm_bo_move_to_lru_tail(&entry->robj->tbo);
+		ttm_bo_move_to_lru_tail(&bo->tbo);
 	}
 	spin_unlock(&glob->lru_lock);
 }
@@ -194,14 +199,14 @@ static bool amdgpu_vm_is_gpu_reset(struc
  * Allocate an id for the vm, adding fences to the sync obj as necessary.
  */
 int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
-		      struct amdgpu_sync *sync, struct fence *fence,
+		      struct amdgpu_sync *sync, struct dma_fence *fence,
 		      struct amdgpu_job *job)
 {
 	struct amdgpu_device *adev = ring->adev;
 	uint64_t fence_context = adev->fence_context + ring->idx;
-	struct fence *updates = sync->last_vm_update;
+	struct dma_fence *updates = sync->last_vm_update;
 	struct amdgpu_vm_id *id, *idle;
-	struct fence **fences;
+	struct dma_fence **fences;
 	unsigned i;
 	int r = 0;
 
@@ -225,17 +230,17 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *
 	if (&idle->list == &adev->vm_manager.ids_lru) {
 		u64 fence_context = adev->vm_manager.fence_context + ring->idx;
 		unsigned seqno = ++adev->vm_manager.seqno[ring->idx];
-		struct fence_array *array;
+		struct dma_fence_array *array;
 		unsigned j;
 
 		for (j = 0; j < i; ++j)
-			fence_get(fences[j]);
+			dma_fence_get(fences[j]);
 
-		array = fence_array_create(i, fences, fence_context,
+		array = dma_fence_array_create(i, fences, fence_context,
 					   seqno, true);
 		if (!array) {
 			for (j = 0; j < i; ++j)
-				fence_put(fences[j]);
+				dma_fence_put(fences[j]);
 			kfree(fences);
 			r = -ENOMEM;
 			goto error;
@@ -243,7 +248,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *
 
 
 		r = amdgpu_sync_fence(ring->adev, sync, &array->base);
-		fence_put(&array->base);
+		dma_fence_put(&array->base);
 		if (r)
 			goto error;
 
@@ -257,7 +262,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *
 	/* Check if we can use a VMID already assigned to this VM */
 	i = ring->idx;
 	do {
-		struct fence *flushed;
+		struct dma_fence *flushed;
 
 		id = vm->ids[i++];
 		if (i == AMDGPU_MAX_RINGS)
@@ -279,12 +284,12 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *
 			continue;
 
 		if (id->last_flush->context != fence_context &&
-		    !fence_is_signaled(id->last_flush))
+		    !dma_fence_is_signaled(id->last_flush))
 			continue;
 
 		flushed  = id->flushed_updates;
 		if (updates &&
-		    (!flushed || fence_is_later(updates, flushed)))
+		    (!flushed || dma_fence_is_later(updates, flushed)))
 			continue;
 
 		/* Good we can use this VMID. Remember this submission as
@@ -315,14 +320,14 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *
 	if (r)
 		goto error;
 
-	fence_put(id->first);
-	id->first = fence_get(fence);
+	dma_fence_put(id->first);
+	id->first = dma_fence_get(fence);
 
-	fence_put(id->last_flush);
+	dma_fence_put(id->last_flush);
 	id->last_flush = NULL;
 
-	fence_put(id->flushed_updates);
-	id->flushed_updates = fence_get(updates);
+	dma_fence_put(id->flushed_updates);
+	id->flushed_updates = dma_fence_get(updates);
 
 	id->pd_gpu_addr = job->vm_pd_addr;
 	id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter);
@@ -341,9 +346,9 @@ error:
 static bool amdgpu_vm_ring_has_compute_vm_bug(struct amdgpu_ring *ring)
 {
 	struct amdgpu_device *adev = ring->adev;
-	const struct amdgpu_ip_block_version *ip_block;
+	const struct amdgpu_ip_block *ip_block;
 
-	if (ring->type != AMDGPU_RING_TYPE_COMPUTE)
+	if (ring->funcs->type != AMDGPU_RING_TYPE_COMPUTE)
 		/* only compute rings */
 		return false;
 
@@ -351,10 +356,10 @@ static bool amdgpu_vm_ring_has_compute_v
 	if (!ip_block)
 		return false;
 
-	if (ip_block->major <= 7) {
+	if (ip_block->version->major <= 7) {
 		/* gfx7 has no workaround */
 		return true;
-	} else if (ip_block->major == 8) {
+	} else if (ip_block->version->major == 8) {
 		if (adev->gfx.mec_fw_version >= 673)
 			/* gfx8 is fixed in MEC firmware 673 */
 			return false;
@@ -393,7 +398,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *
 
 	if (ring->funcs->emit_vm_flush && (job->vm_needs_flush ||
 	    amdgpu_vm_is_gpu_reset(adev, id))) {
-		struct fence *fence;
+		struct dma_fence *fence;
 
 		trace_amdgpu_vm_flush(job->vm_pd_addr, ring->idx, job->vm_id);
 		amdgpu_ring_emit_vm_flush(ring, job->vm_id, job->vm_pd_addr);
@@ -403,7 +408,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *
 			return r;
 
 		mutex_lock(&adev->vm_manager.lock);
-		fence_put(id->last_flush);
+		dma_fence_put(id->last_flush);
 		id->last_flush = fence;
 		mutex_unlock(&adev->vm_manager.lock);
 	}
@@ -525,70 +530,6 @@ static void amdgpu_vm_do_copy_ptes(struc
 }
 
 /**
- * amdgpu_vm_clear_bo - initially clear the page dir/table
- *
- * @adev: amdgpu_device pointer
- * @bo: bo to clear
- *
- * need to reserve bo first before calling it.
- */
-static int amdgpu_vm_clear_bo(struct amdgpu_device *adev,
-			      struct amdgpu_vm *vm,
-			      struct amdgpu_bo *bo)
-{
-	struct amdgpu_ring *ring;
-	struct fence *fence = NULL;
-	struct amdgpu_job *job;
-	struct amdgpu_pte_update_params params;
-	unsigned entries;
-	uint64_t addr;
-	int r;
-
-	ring = container_of(vm->entity.sched, struct amdgpu_ring, sched);
-
-	r = reservation_object_reserve_shared(bo->tbo.resv);
-	if (r)
-		return r;
-
-	r = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
-	if (r)
-		goto error;
-
-	r = amdgpu_ttm_bind(&bo->tbo, &bo->tbo.mem);
-	if (r)
-		goto error;
-
-	addr = amdgpu_bo_gpu_offset(bo);
-	entries = amdgpu_bo_size(bo) / 8;
-
-	r = amdgpu_job_alloc_with_ib(adev, 64, &job);
-	if (r)
-		goto error;
-
-	memset(&params, 0, sizeof(params));
-	params.adev = adev;
-	params.ib = &job->ibs[0];
-	amdgpu_vm_do_set_ptes(&params, addr, 0, entries, 0, 0);
-	amdgpu_ring_pad_ib(ring, &job->ibs[0]);
-
-	WARN_ON(job->ibs[0].length_dw > 64);
-	r = amdgpu_job_submit(job, ring, &vm->entity,
-			      AMDGPU_FENCE_OWNER_VM, &fence);
-	if (r)
-		goto error_free;
-
-	amdgpu_bo_fence(bo, fence, true);
-	fence_put(fence);
-	return 0;
-
-error_free:
-	amdgpu_job_free(job);
-
-error:
-	return r;
-}
-
-/**
  * amdgpu_vm_map_gart - Resolve gart mapping of addr
  *
  * @pages_addr: optional DMA address to use for lookup
@@ -612,32 +553,35 @@ static uint64_t amdgpu_vm_map_gart(const
 	return result;
 }
 
-static int amdgpu_vm_update_pd_or_shadow(struct amdgpu_device *adev,
-					 struct amdgpu_vm *vm,
-					 bool shadow)
+/*
+ * amdgpu_vm_update_pdes - make sure that page directory is valid
+ *
+ * @adev: amdgpu_device pointer
+ * @vm: requested vm
+ * @start: start of GPU address range
+ * @end: end of GPU address range
+ *
+ * Allocates new page tables if necessary
+ * and updates the page directory.
+ * Returns 0 for success, error for failure.
+ */
+int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
+				    struct amdgpu_vm *vm)
 {
+	struct amdgpu_bo *shadow;
 	struct amdgpu_ring *ring;
-	struct amdgpu_bo *pd = shadow ? vm->page_directory->shadow :
-		vm->page_directory;
-	uint64_t pd_addr;
+	uint64_t pd_addr, shadow_addr;
 	uint32_t incr = AMDGPU_VM_PTE_COUNT * 8;
-	uint64_t last_pde = ~0, last_pt = ~0;
+	uint64_t last_pde = ~0, last_pt = ~0, last_shadow = ~0;
 	unsigned count = 0, pt_idx, ndw;
 	struct amdgpu_job *job;
 	struct amdgpu_pte_update_params params;
-	struct fence *fence = NULL;
+	struct dma_fence *fence = NULL;
 
 	int r;
 
-	if (!pd)
-		return 0;
-
-	r = amdgpu_ttm_bind(&pd->tbo, &pd->tbo.mem);
-	if (r)
-		return r;
-
-	pd_addr = amdgpu_bo_gpu_offset(pd);
 	ring = container_of(vm->entity.sched, struct amdgpu_ring, sched);
+	shadow = vm->page_directory->shadow;
 
 	/* padding, etc. */
 	ndw = 64;
@@ -645,6 +589,17 @@ static int amdgpu_vm_update_pd_or_shadow
 	/* assume the worst case */
 	ndw += vm->max_pde_used * 6;
 
+	pd_addr = amdgpu_bo_gpu_offset(vm->page_directory);
+	if (shadow) {
+		r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem);
+		if (r)
+			return r;
+		shadow_addr = amdgpu_bo_gpu_offset(shadow);
+		ndw *= 2;
+	} else {
+		shadow_addr = 0;
+	}
+
 	r = amdgpu_job_alloc_with_ib(adev, ndw * 4, &job);
 	if (r)
 		return r;
@@ -655,30 +610,26 @@ static int amdgpu_vm_update_pd_or_shadow
 
 	/* walk over the address space and update the page directory */
 	for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) {
-		struct amdgpu_bo *bo = vm->page_tables[pt_idx].entry.robj;
+		struct amdgpu_bo *bo = vm->page_tables[pt_idx].bo;
 		uint64_t pde, pt;
 
 		if (bo == NULL)
 			continue;
 
 		if (bo->shadow) {
-			struct amdgpu_bo *shadow = bo->shadow;
+			struct amdgpu_bo *pt_shadow = bo->shadow;
 
-			r = amdgpu_ttm_bind(&shadow->tbo, &shadow->tbo.mem);
+			r = amdgpu_ttm_bind(&pt_shadow->tbo,
+					    &pt_shadow->tbo.mem);
 			if (r)
 				return r;
 		}
 
 		pt = amdgpu_bo_gpu_offset(bo);
-		if (!shadow) {
-			if (vm->page_tables[pt_idx].addr == pt)
-				continue;
-			vm->page_tables[pt_idx].addr = pt;
-		} else {
-			if (vm->page_tables[pt_idx].shadow_addr == pt)
-				continue;
-			vm->page_tables[pt_idx].shadow_addr = pt;
-		}
+		if (vm->page_tables[pt_idx].addr == pt)
+			continue;
+
+		vm->page_tables[pt_idx].addr = pt;
 
 		pde = pd_addr + pt_idx * 8;
 		if (((last_pde + 8 * count) != pde) ||
@@ -686,6 +637,13 @@ static int amdgpu_vm_update_pd_or_shadow
 		    (count == AMDGPU_VM_MAX_UPDATE_SIZE)) {
 
 			if (count) {
+				if (shadow)
+					amdgpu_vm_do_set_ptes(&params,
+							      last_shadow,
+							      last_pt, count,
+							      incr,
+							      AMDGPU_PTE_VALID);
+
 				amdgpu_vm_do_set_ptes(&params, last_pde,
 						      last_pt, count, incr,
 						      AMDGPU_PTE_VALID);
@@ -693,34 +651,44 @@ static int amdgpu_vm_update_pd_or_shadow
 
 			count = 1;
 			last_pde = pde;
+			last_shadow = shadow_addr + pt_idx * 8;
 			last_pt = pt;
 		} else {
 			++count;
 		}
 	}
 
-	if (count)
+	if (count) {
+		if (vm->page_directory->shadow)
+			amdgpu_vm_do_set_ptes(&params, last_shadow, last_pt,
+					      count, incr, AMDGPU_PTE_VALID);
+
 		amdgpu_vm_do_set_ptes(&params, last_pde, last_pt,
 				      count, incr, AMDGPU_PTE_VALID);
+	}
 
-	if (params.ib->length_dw != 0) {
-		amdgpu_ring_pad_ib(ring, params.ib);
-		amdgpu_sync_resv(adev, &job->sync, pd->tbo.resv,
+	if (params.ib->length_dw == 0) {
+		amdgpu_job_free(job);
+		return 0;
+	}
+
+	amdgpu_ring_pad_ib(ring, params.ib);
+	amdgpu_sync_resv(adev, &job->sync, vm->page_directory->tbo.resv,
+			 AMDGPU_FENCE_OWNER_VM);
+	if (shadow)
+		amdgpu_sync_resv(adev, &job->sync, shadow->tbo.resv,
 				 AMDGPU_FENCE_OWNER_VM);
-		WARN_ON(params.ib->length_dw > ndw);
-		r = amdgpu_job_submit(job, ring, &vm->entity,
-				      AMDGPU_FENCE_OWNER_VM, &fence);
-		if (r)
-			goto error_free;
 
-		amdgpu_bo_fence(pd, fence, true);
-		fence_put(vm->page_directory_fence);
-		vm->page_directory_fence = fence_get(fence);
-		fence_put(fence);
+	WARN_ON(params.ib->length_dw > ndw);
+	r = amdgpu_job_submit(job, ring, &vm->entity,
+			      AMDGPU_FENCE_OWNER_VM, &fence);
+	if (r)
+		goto error_free;
 
-	} else {
-		amdgpu_job_free(job);
-	}
+	amdgpu_bo_fence(vm->page_directory, fence, true);
+	dma_fence_put(vm->page_directory_fence);
+	vm->page_directory_fence = dma_fence_get(fence);
+	dma_fence_put(fence);
 
 	return 0;
 
@@ -729,29 +697,6 @@ error_free:
 	return r;
 }
 
-/*
- * amdgpu_vm_update_pdes - make sure that page directory is valid
- *
- * @adev: amdgpu_device pointer
- * @vm: requested vm
- * @start: start of GPU address range
- * @end: end of GPU address range
- *
- * Allocates new page tables if necessary
- * and updates the page directory.
- * Returns 0 for success, error for failure.
- */
-int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
-                                   struct amdgpu_vm *vm)
-{
-	int r;
-
-	r = amdgpu_vm_update_pd_or_shadow(adev, vm, true);
-	if (r)
-		return r;
-	return amdgpu_vm_update_pd_or_shadow(adev, vm, false);
-}
-
 /**
  * amdgpu_vm_update_ptes - make sure that page tables are valid
  *
@@ -781,11 +726,11 @@ static void amdgpu_vm_update_ptes(struct
 	/* initialize the variables */
 	addr = start;
 	pt_idx = addr >> amdgpu_vm_block_size;
-	pt = vm->page_tables[pt_idx].entry.robj;
+	pt = vm->page_tables[pt_idx].bo;
 	if (params->shadow) {
 		if (!pt->shadow)
 			return;
-		pt = vm->page_tables[pt_idx].entry.robj->shadow;
+		pt = pt->shadow;
 	}
 	if ((addr & ~mask) == (end & ~mask))
 		nptes = end - addr;
@@ -804,11 +749,11 @@ static void amdgpu_vm_update_ptes(struct
 	/* walk over the address space and update the page tables */
 	while (addr < end) {
 		pt_idx = addr >> amdgpu_vm_block_size;
-		pt = vm->page_tables[pt_idx].entry.robj;
+		pt = vm->page_tables[pt_idx].bo;
 		if (params->shadow) {
 			if (!pt->shadow)
 				return;
-			pt = vm->page_tables[pt_idx].entry.robj->shadow;
+			pt = pt->shadow;
 		}
 
 		if ((addr & ~mask) == (end & ~mask))
@@ -929,20 +874,20 @@ static void amdgpu_vm_frag_ptes(struct a
  * Returns 0 for success, -EINVAL for failure.
  */
 static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev,
-				       struct fence *exclusive,
+				       struct dma_fence *exclusive,
 				       uint64_t src,
 				       dma_addr_t *pages_addr,
 				       struct amdgpu_vm *vm,
 				       uint64_t start, uint64_t last,
 				       uint32_t flags, uint64_t addr,
-				       struct fence **fence)
+				       struct dma_fence **fence)
 {
 	struct amdgpu_ring *ring;
 	void *owner = AMDGPU_FENCE_OWNER_VM;
 	unsigned nptes, ncmds, ndw;
 	struct amdgpu_job *job;
 	struct amdgpu_pte_update_params params;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	int r;
 
 	memset(&params, 0, sizeof(params));
@@ -1045,10 +990,10 @@ static int amdgpu_vm_bo_update_mapping(s
 
 	amdgpu_bo_fence(vm->page_directory, f, true);
 	if (fence) {
-		fence_put(*fence);
-		*fence = fence_get(f);
+		dma_fence_put(*fence);
+		*fence = dma_fence_get(f);
 	}
-	fence_put(f);
+	dma_fence_put(f);
 	return 0;
 
 error_free:
@@ -1065,8 +1010,8 @@ error_free:
  * @pages_addr: DMA addresses to use for mapping
  * @vm: requested vm
  * @mapping: mapped range and flags to use for the update
- * @addr: addr to set the area to
  * @flags: HW flags for the mapping
+ * @nodes: array of drm_mm_nodes with the MC addresses
  * @fence: optional resulting fence
  *
  * Split the mapping into smaller chunks so that each update fits
@@ -1074,17 +1019,16 @@ error_free:
  * Returns 0 for success, -EINVAL for failure.
  */
 static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
-				      struct fence *exclusive,
+				      struct dma_fence *exclusive,
 				      uint32_t gtt_flags,
 				      dma_addr_t *pages_addr,
 				      struct amdgpu_vm *vm,
 				      struct amdgpu_bo_va_mapping *mapping,
-				      uint32_t flags, uint64_t addr,
-				      struct fence **fence)
+				      uint32_t flags,
+				      struct drm_mm_node *nodes,
+				      struct dma_fence **fence)
 {
-	const uint64_t max_size = 64ULL * 1024ULL * 1024ULL / AMDGPU_GPU_PAGE_SIZE;
-
-	uint64_t src = 0, start = mapping->it.start;
+	uint64_t pfn, src = 0, start = mapping->it.start;
 	int r;
 
 	/* normally,bo_va->flags only contians READABLE and WIRTEABLE bit go here
@@ -1097,23 +1041,40 @@ static int amdgpu_vm_bo_split_mapping(st
 
 	trace_amdgpu_vm_bo_update(mapping);
 
-	if (pages_addr) {
-		if (flags == gtt_flags)
-			src = adev->gart.table_addr + (addr >> 12) * 8;
-		addr = 0;
+	pfn = mapping->offset >> PAGE_SHIFT;
+	if (nodes) {
+		while (pfn >= nodes->size) {
+			pfn -= nodes->size;
+			++nodes;
+		}
 	}
-	addr += mapping->offset;
 
-	if (!pages_addr || src)
-		return amdgpu_vm_bo_update_mapping(adev, exclusive,
-						   src, pages_addr, vm,
-						   start, mapping->it.last,
-						   flags, addr, fence);
+	do {
+		uint64_t max_entries;
+		uint64_t addr, last;
 
-	while (start != mapping->it.last + 1) {
-		uint64_t last;
+		if (nodes) {
+			addr = nodes->start << PAGE_SHIFT;
+			max_entries = (nodes->size - pfn) *
+				(PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE);
+		} else {
+			addr = 0;
+			max_entries = S64_MAX;
+		}
 
-		last = min((uint64_t)mapping->it.last, start + max_size - 1);
+		if (pages_addr) {
+			if (flags == gtt_flags)
+				src = adev->gart.table_addr +
+					(addr >> AMDGPU_GPU_PAGE_SHIFT) * 8;
+			else
+				max_entries = min(max_entries, 16ull * 1024ull);
+			addr = 0;
+		} else if (flags & AMDGPU_PTE_VALID) {
+			addr += adev->vm_manager.vram_base_offset;
+		}
+		addr += pfn << PAGE_SHIFT;
+
+		last = min((uint64_t)mapping->it.last, start + max_entries - 1);
 		r = amdgpu_vm_bo_update_mapping(adev, exclusive,
 						src, pages_addr, vm,
 						start, last, flags, addr,
@@ -1121,9 +1082,14 @@ static int amdgpu_vm_bo_split_mapping(st
 		if (r)
 			return r;
 
+		pfn += last - start + 1;
+		if (nodes && nodes->size == pfn) {
+			pfn = 0;
+			++nodes;
+		}
 		start = last + 1;
-		addr += max_size * AMDGPU_GPU_PAGE_SIZE;
-	}
+
+	} while (unlikely(start != mapping->it.last + 1));
 
 	return 0;
 }
@@ -1147,40 +1113,30 @@ int amdgpu_vm_bo_update(struct amdgpu_de
 	dma_addr_t *pages_addr = NULL;
 	uint32_t gtt_flags, flags;
 	struct ttm_mem_reg *mem;
-	struct fence *exclusive;
-	uint64_t addr;
+	struct drm_mm_node *nodes;
+	struct dma_fence *exclusive;
 	int r;
 
 	if (clear) {
 		mem = NULL;
-		addr = 0;
+		nodes = NULL;
 		exclusive = NULL;
 	} else {
 		struct ttm_dma_tt *ttm;
 
 		mem = &bo_va->bo->tbo.mem;
-		addr = (u64)mem->start << PAGE_SHIFT;
-		switch (mem->mem_type) {
-		case TTM_PL_TT:
+		nodes = mem->mm_node;
+		if (mem->mem_type == TTM_PL_TT) {
 			ttm = container_of(bo_va->bo->tbo.ttm, struct
 					   ttm_dma_tt, ttm);
 			pages_addr = ttm->dma_address;
-			break;
-
-		case TTM_PL_VRAM:
-			addr += adev->vm_manager.vram_base_offset;
-			break;
-
-		default:
-			break;
 		}
-
 		exclusive = reservation_object_get_excl(bo_va->bo->tbo.resv);
 	}
 
 	flags = amdgpu_ttm_tt_pte_flags(adev, bo_va->bo->tbo.ttm, mem);
 	gtt_flags = (amdgpu_ttm_is_bound(bo_va->bo->tbo.ttm) &&
-		adev == bo_va->bo->adev) ? flags : 0;
+		adev == amdgpu_ttm_adev(bo_va->bo->tbo.bdev)) ? flags : 0;
 
 	spin_lock(&vm->status_lock);
 	if (!list_empty(&bo_va->vm_status))
@@ -1190,7 +1146,7 @@ int amdgpu_vm_bo_update(struct amdgpu_de
 	list_for_each_entry(mapping, &bo_va->invalids, list) {
 		r = amdgpu_vm_bo_split_mapping(adev, exclusive,
 					       gtt_flags, pages_addr, vm,
-					       mapping, flags, addr,
+					       mapping, flags, nodes,
 					       &bo_va->last_pt_update);
 		if (r)
 			return r;
@@ -1405,18 +1361,18 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
 	/* walk over the address space and allocate the page tables */
 	for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) {
 		struct reservation_object *resv = vm->page_directory->tbo.resv;
-		struct amdgpu_bo_list_entry *entry;
 		struct amdgpu_bo *pt;
 
-		entry = &vm->page_tables[pt_idx].entry;
-		if (entry->robj)
+		if (vm->page_tables[pt_idx].bo)
 			continue;
 
 		r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8,
 				     AMDGPU_GPU_PAGE_SIZE, true,
 				     AMDGPU_GEM_DOMAIN_VRAM,
 				     AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
-				     AMDGPU_GEM_CREATE_SHADOW,
+				     AMDGPU_GEM_CREATE_SHADOW |
+				     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
+				     AMDGPU_GEM_CREATE_VRAM_CLEARED,
 				     NULL, resv, &pt);
 		if (r)
 			goto error_free;
@@ -1426,27 +1382,7 @@ int amdgpu_vm_bo_map(struct amdgpu_devic
 		 */
 		pt->parent = amdgpu_bo_ref(vm->page_directory);
 
-		r = amdgpu_vm_clear_bo(adev, vm, pt);
-		if (r) {
-			amdgpu_bo_unref(&pt->shadow);
-			amdgpu_bo_unref(&pt);
-			goto error_free;
-		}
-
-		if (pt->shadow) {
-			r = amdgpu_vm_clear_bo(adev, vm, pt->shadow);
-			if (r) {
-				amdgpu_bo_unref(&pt->shadow);
-				amdgpu_bo_unref(&pt);
-				goto error_free;
-			}
-		}
-
-		entry->robj = pt;
-		entry->priority = 0;
-		entry->tv.bo = &entry->robj->tbo;
-		entry->tv.shared = true;
-		entry->user_pages = NULL;
+		vm->page_tables[pt_idx].bo = pt;
 		vm->page_tables[pt_idx].addr = 0;
 	}
 
@@ -1547,7 +1483,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_devi
 		kfree(mapping);
 	}
 
-	fence_put(bo_va->last_pt_update);
+	dma_fence_put(bo_va->last_pt_update);
 	kfree(bo_va);
 }
 
@@ -1626,7 +1562,9 @@ int amdgpu_vm_init(struct amdgpu_device
 	r = amdgpu_bo_create(adev, pd_size, align, true,
 			     AMDGPU_GEM_DOMAIN_VRAM,
 			     AMDGPU_GEM_CREATE_NO_CPU_ACCESS |
-			     AMDGPU_GEM_CREATE_SHADOW,
+			     AMDGPU_GEM_CREATE_SHADOW |
+			     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
+			     AMDGPU_GEM_CREATE_VRAM_CLEARED,
 			     NULL, NULL, &vm->page_directory);
 	if (r)
 		goto error_free_sched_entity;
@@ -1635,24 +1573,11 @@ int amdgpu_vm_init(struct amdgpu_device
 	if (r)
 		goto error_free_page_directory;
 
-	r = amdgpu_vm_clear_bo(adev, vm, vm->page_directory);
-	if (r)
-		goto error_unreserve;
-
-	if (vm->page_directory->shadow) {
-		r = amdgpu_vm_clear_bo(adev, vm, vm->page_directory->shadow);
-		if (r)
-			goto error_unreserve;
-	}
-
 	vm->last_eviction_counter = atomic64_read(&adev->num_evictions);
 	amdgpu_bo_unreserve(vm->page_directory);
 
 	return 0;
 
-error_unreserve:
-	amdgpu_bo_unreserve(vm->page_directory);
-
 error_free_page_directory:
 	amdgpu_bo_unref(&vm->page_directory->shadow);
 	amdgpu_bo_unref(&vm->page_directory);
@@ -1697,7 +1622,7 @@ void amdgpu_vm_fini(struct amdgpu_device
 	}
 
 	for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) {
-		struct amdgpu_bo *pt = vm->page_tables[i].entry.robj;
+		struct amdgpu_bo *pt = vm->page_tables[i].bo;
 
 		if (!pt)
 			continue;
@@ -1709,7 +1634,7 @@ void amdgpu_vm_fini(struct amdgpu_device
 
 	amdgpu_bo_unref(&vm->page_directory->shadow);
 	amdgpu_bo_unref(&vm->page_directory);
-	fence_put(vm->page_directory_fence);
+	dma_fence_put(vm->page_directory_fence);
 }
 
 /**
@@ -1733,7 +1658,8 @@ void amdgpu_vm_manager_init(struct amdgp
 			      &adev->vm_manager.ids_lru);
 	}
 
-	adev->vm_manager.fence_context = fence_context_alloc(AMDGPU_MAX_RINGS);
+	adev->vm_manager.fence_context =
+		dma_fence_context_alloc(AMDGPU_MAX_RINGS);
 	for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
 		adev->vm_manager.seqno[i] = 0;
 
@@ -1755,9 +1681,9 @@ void amdgpu_vm_manager_fini(struct amdgp
 	for (i = 0; i < AMDGPU_NUM_VM; ++i) {
 		struct amdgpu_vm_id *id = &adev->vm_manager.ids[i];
 
-		fence_put(adev->vm_manager.ids[i].first);
+		dma_fence_put(adev->vm_manager.ids[i].first);
 		amdgpu_sync_free(&adev->vm_manager.ids[i].active);
-		fence_put(id->flushed_updates);
-		fence_put(id->last_flush);
+		dma_fence_put(id->flushed_updates);
+		dma_fence_put(id->last_flush);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian König
+ */
+#ifndef __AMDGPU_VM_H__
+#define __AMDGPU_VM_H__
+
+#include <linux/rbtree.h>
+
+#include "gpu_scheduler.h"
+#include "amdgpu_sync.h"
+#include "amdgpu_ring.h"
+
+struct amdgpu_bo_va;
+struct amdgpu_job;
+struct amdgpu_bo_list_entry;
+
+/*
+ * GPUVM handling
+ */
+
+/* maximum number of VMIDs */
+#define AMDGPU_NUM_VM	16
+
+/* Maximum number of PTEs the hardware can write with one command */
+#define AMDGPU_VM_MAX_UPDATE_SIZE	0x3FFFF
+
+/* number of entries in page table */
+#define AMDGPU_VM_PTE_COUNT (1 << amdgpu_vm_block_size)
+
+/* PTBs (Page Table Blocks) need to be aligned to 32K */
+#define AMDGPU_VM_PTB_ALIGN_SIZE   32768
+
+/* LOG2 number of continuous pages for the fragment field */
+#define AMDGPU_LOG2_PAGES_PER_FRAG 4
+
+#define AMDGPU_PTE_VALID	(1 << 0)
+#define AMDGPU_PTE_SYSTEM	(1 << 1)
+#define AMDGPU_PTE_SNOOPED	(1 << 2)
+
+/* VI only */
+#define AMDGPU_PTE_EXECUTABLE	(1 << 4)
+
+#define AMDGPU_PTE_READABLE	(1 << 5)
+#define AMDGPU_PTE_WRITEABLE	(1 << 6)
+
+#define AMDGPU_PTE_FRAG(x)	((x & 0x1f) << 7)
+
+/* How to programm VM fault handling */
+#define AMDGPU_VM_FAULT_STOP_NEVER	0
+#define AMDGPU_VM_FAULT_STOP_FIRST	1
+#define AMDGPU_VM_FAULT_STOP_ALWAYS	2
+
+struct amdgpu_vm_pt {
+	struct amdgpu_bo	*bo;
+	uint64_t		addr;
+};
+
+struct amdgpu_vm {
+	/* tree of virtual addresses mapped */
+	struct rb_root		va;
+
+	/* protecting invalidated */
+	spinlock_t		status_lock;
+
+	/* BOs moved, but not yet updated in the PT */
+	struct list_head	invalidated;
+
+	/* BOs cleared in the PT because of a move */
+	struct list_head	cleared;
+
+	/* BO mappings freed, but not yet updated in the PT */
+	struct list_head	freed;
+
+	/* contains the page directory */
+	struct amdgpu_bo	*page_directory;
+	unsigned		max_pde_used;
+	struct dma_fence		*page_directory_fence;
+	uint64_t		last_eviction_counter;
+
+	/* array of page tables, one for each page directory entry */
+	struct amdgpu_vm_pt	*page_tables;
+
+	/* for id and flush management per ring */
+	struct amdgpu_vm_id	*ids[AMDGPU_MAX_RINGS];
+
+	/* protecting freed */
+	spinlock_t		freed_lock;
+
+	/* Scheduler entity for page table updates */
+	struct amd_sched_entity	entity;
+
+	/* client id */
+	u64                     client_id;
+};
+
+struct amdgpu_vm_id {
+	struct list_head	list;
+	struct dma_fence		*first;
+	struct amdgpu_sync	active;
+	struct dma_fence		*last_flush;
+	atomic64_t		owner;
+
+	uint64_t		pd_gpu_addr;
+	/* last flushed PD/PT update */
+	struct dma_fence		*flushed_updates;
+
+	uint32_t                current_gpu_reset_count;
+
+	uint32_t		gds_base;
+	uint32_t		gds_size;
+	uint32_t		gws_base;
+	uint32_t		gws_size;
+	uint32_t		oa_base;
+	uint32_t		oa_size;
+};
+
+struct amdgpu_vm_manager {
+	/* Handling of VMIDs */
+	struct mutex				lock;
+	unsigned				num_ids;
+	struct list_head			ids_lru;
+	struct amdgpu_vm_id			ids[AMDGPU_NUM_VM];
+
+	/* Handling of VM fences */
+	u64					fence_context;
+	unsigned				seqno[AMDGPU_MAX_RINGS];
+
+	uint32_t				max_pfn;
+	/* vram base address for page table entry  */
+	u64					vram_base_offset;
+	/* is vm enabled? */
+	bool					enabled;
+	/* vm pte handling */
+	const struct amdgpu_vm_pte_funcs        *vm_pte_funcs;
+	struct amdgpu_ring                      *vm_pte_rings[AMDGPU_MAX_RINGS];
+	unsigned				vm_pte_num_rings;
+	atomic_t				vm_pte_next_ring;
+	/* client id counter */
+	atomic64_t				client_counter;
+};
+
+void amdgpu_vm_manager_init(struct amdgpu_device *adev);
+void amdgpu_vm_manager_fini(struct amdgpu_device *adev);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm,
+			 struct list_head *validated,
+			 struct amdgpu_bo_list_entry *entry);
+int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+			      int (*callback)(void *p, struct amdgpu_bo *bo),
+			      void *param);
+void amdgpu_vm_move_pt_bos_in_lru(struct amdgpu_device *adev,
+				  struct amdgpu_vm *vm);
+int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
+		      struct amdgpu_sync *sync, struct dma_fence *fence,
+		      struct amdgpu_job *job);
+int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
+void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
+int amdgpu_vm_update_page_directory(struct amdgpu_device *adev,
+				    struct amdgpu_vm *vm);
+int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
+			  struct amdgpu_vm *vm);
+int amdgpu_vm_clear_invalids(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+			     struct amdgpu_sync *sync);
+int amdgpu_vm_bo_update(struct amdgpu_device *adev,
+			struct amdgpu_bo_va *bo_va,
+			bool clear);
+void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev,
+			     struct amdgpu_bo *bo);
+struct amdgpu_bo_va *amdgpu_vm_bo_find(struct amdgpu_vm *vm,
+				       struct amdgpu_bo *bo);
+struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev,
+				      struct amdgpu_vm *vm,
+				      struct amdgpu_bo *bo);
+int amdgpu_vm_bo_map(struct amdgpu_device *adev,
+		     struct amdgpu_bo_va *bo_va,
+		     uint64_t addr, uint64_t offset,
+		     uint64_t size, uint32_t flags);
+int amdgpu_vm_bo_unmap(struct amdgpu_device *adev,
+		       struct amdgpu_bo_va *bo_va,
+		       uint64_t addr);
+void amdgpu_vm_bo_rmv(struct amdgpu_device *adev,
+		      struct amdgpu_bo_va *bo_va);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Christian König
+ */
+
+#include <drm/drmP.h>
+#include "amdgpu.h"
+
+struct amdgpu_vram_mgr {
+	struct drm_mm mm;
+	spinlock_t lock;
+};
+
+/**
+ * amdgpu_vram_mgr_init - init VRAM manager and DRM MM
+ *
+ * @man: TTM memory type manager
+ * @p_size: maximum size of VRAM
+ *
+ * Allocate and initialize the VRAM manager.
+ */
+static int amdgpu_vram_mgr_init(struct ttm_mem_type_manager *man,
+				unsigned long p_size)
+{
+	struct amdgpu_vram_mgr *mgr;
+
+	mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+	if (!mgr)
+		return -ENOMEM;
+
+	drm_mm_init(&mgr->mm, 0, p_size);
+	spin_lock_init(&mgr->lock);
+	man->priv = mgr;
+	return 0;
+}
+
+/**
+ * amdgpu_vram_mgr_fini - free and destroy VRAM manager
+ *
+ * @man: TTM memory type manager
+ *
+ * Destroy and free the VRAM manager, returns -EBUSY if ranges are still
+ * allocated inside it.
+ */
+static int amdgpu_vram_mgr_fini(struct ttm_mem_type_manager *man)
+{
+	struct amdgpu_vram_mgr *mgr = man->priv;
+
+	spin_lock(&mgr->lock);
+	if (!drm_mm_clean(&mgr->mm)) {
+		spin_unlock(&mgr->lock);
+		return -EBUSY;
+	}
+
+	drm_mm_takedown(&mgr->mm);
+	spin_unlock(&mgr->lock);
+	kfree(mgr);
+	man->priv = NULL;
+	return 0;
+}
+
+/**
+ * amdgpu_vram_mgr_new - allocate new ranges
+ *
+ * @man: TTM memory type manager
+ * @tbo: TTM BO we need this range for
+ * @place: placement flags and restrictions
+ * @mem: the resulting mem object
+ *
+ * Allocate VRAM for the given BO.
+ */
+static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
+			       struct ttm_buffer_object *tbo,
+			       const struct ttm_place *place,
+			       struct ttm_mem_reg *mem)
+{
+	struct amdgpu_bo *bo = container_of(tbo, struct amdgpu_bo, tbo);
+	struct amdgpu_vram_mgr *mgr = man->priv;
+	struct drm_mm *mm = &mgr->mm;
+	struct drm_mm_node *nodes;
+	enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT;
+	enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT;
+	unsigned long lpfn, num_nodes, pages_per_node, pages_left;
+	unsigned i;
+	int r;
+
+	lpfn = place->lpfn;
+	if (!lpfn)
+		lpfn = man->size;
+
+	if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS ||
+	    place->lpfn || amdgpu_vram_page_split == -1) {
+		pages_per_node = ~0ul;
+		num_nodes = 1;
+	} else {
+		pages_per_node = max((uint32_t)amdgpu_vram_page_split,
+				     mem->page_alignment);
+		num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node);
+	}
+
+	nodes = kcalloc(num_nodes, sizeof(*nodes), GFP_KERNEL);
+	if (!nodes)
+		return -ENOMEM;
+
+	if (place->flags & TTM_PL_FLAG_TOPDOWN) {
+		sflags = DRM_MM_SEARCH_BELOW;
+		aflags = DRM_MM_CREATE_TOP;
+	}
+
+	pages_left = mem->num_pages;
+
+	spin_lock(&mgr->lock);
+	for (i = 0; i < num_nodes; ++i) {
+		unsigned long pages = min(pages_left, pages_per_node);
+		uint32_t alignment = mem->page_alignment;
+
+		if (pages == pages_per_node)
+			alignment = pages_per_node;
+		else
+			sflags |= DRM_MM_SEARCH_BEST;
+
+		r = drm_mm_insert_node_in_range_generic(mm, &nodes[i], pages,
+							alignment, 0,
+							place->fpfn, lpfn,
+							sflags, aflags);
+		if (unlikely(r))
+			goto error;
+
+		pages_left -= pages;
+	}
+	spin_unlock(&mgr->lock);
+
+	mem->start = num_nodes == 1 ? nodes[0].start : AMDGPU_BO_INVALID_OFFSET;
+	mem->mm_node = nodes;
+
+	return 0;
+
+error:
+	while (i--)
+		drm_mm_remove_node(&nodes[i]);
+	spin_unlock(&mgr->lock);
+
+	kfree(nodes);
+	return r == -ENOSPC ? 0 : r;
+}
+
+/**
+ * amdgpu_vram_mgr_del - free ranges
+ *
+ * @man: TTM memory type manager
+ * @tbo: TTM BO we need this range for
+ * @place: placement flags and restrictions
+ * @mem: TTM memory object
+ *
+ * Free the allocated VRAM again.
+ */
+static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man,
+				struct ttm_mem_reg *mem)
+{
+	struct amdgpu_vram_mgr *mgr = man->priv;
+	struct drm_mm_node *nodes = mem->mm_node;
+	unsigned pages = mem->num_pages;
+
+	if (!mem->mm_node)
+		return;
+
+	spin_lock(&mgr->lock);
+	while (pages) {
+		pages -= nodes->size;
+		drm_mm_remove_node(nodes);
+		++nodes;
+	}
+	spin_unlock(&mgr->lock);
+
+	kfree(mem->mm_node);
+	mem->mm_node = NULL;
+}
+
+/**
+ * amdgpu_vram_mgr_debug - dump VRAM table
+ *
+ * @man: TTM memory type manager
+ * @prefix: text prefix
+ *
+ * Dump the table content using printk.
+ */
+static void amdgpu_vram_mgr_debug(struct ttm_mem_type_manager *man,
+				  const char *prefix)
+{
+	struct amdgpu_vram_mgr *mgr = man->priv;
+
+	spin_lock(&mgr->lock);
+	drm_mm_debug_table(&mgr->mm, prefix);
+	spin_unlock(&mgr->lock);
+}
+
+const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func = {
+	amdgpu_vram_mgr_init,
+	amdgpu_vram_mgr_fini,
+	amdgpu_vram_mgr_new,
+	amdgpu_vram_mgr_del,
+	amdgpu_vram_mgr_debug
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@
 #include "atom.h"
 #include "atom-bits.h"
 #include "atombios_encoders.h"
+#include "atombios_crtc.h"
 #include "amdgpu_atombios.h"
 #include "amdgpu_pll.h"
 #include "amdgpu_connectors.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c	2016-12-11 17:41:31.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/ci_dpm.c	2017-02-12 17:24:25.000000000 -0500
@@ -884,9 +884,6 @@ static void ci_dpm_powergate_uvd(struct
 {
 	struct ci_power_info *pi = ci_get_pi(adev);
 
-	if (pi->uvd_power_gated == gate)
-		return;
-
 	pi->uvd_power_gated = gate;
 
 	ci_update_uvd_dpm(adev, gate);
@@ -957,6 +954,12 @@ static void ci_apply_state_adjust_rules(
 		sclk = ps->performance_levels[0].sclk;
 	}
 
+	if (adev->pm.pm_display_cfg.min_core_set_clock > sclk)
+		sclk = adev->pm.pm_display_cfg.min_core_set_clock;
+
+	if (adev->pm.pm_display_cfg.min_mem_set_clock > mclk)
+		mclk = adev->pm.pm_display_cfg.min_mem_set_clock;
+
 	if (rps->vce_active) {
 		if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk)
 			sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk;
@@ -2198,6 +2201,11 @@ static int ci_upload_firmware(struct amd
 	struct ci_power_info *pi = ci_get_pi(adev);
 	int i, ret;
 
+	if (amdgpu_ci_is_smc_running(adev)) {
+		DRM_INFO("smc is running, no need to load smc firmware\n");
+		return 0;
+	}
+
 	for (i = 0; i < adev->usec_timeout; i++) {
 		if (RREG32_SMC(ixRCU_UC_EVENTS) & RCU_UC_EVENTS__boot_seq_done_MASK)
 			break;
@@ -4187,8 +4195,10 @@ static int ci_update_uvd_dpm(struct amdg
 {
 	struct ci_power_info *pi = ci_get_pi(adev);
 	u32 tmp;
+	int ret = 0;
 
 	if (!gate) {
+		/* turn the clocks on when decoding */
 		if (pi->caps_uvd_dpm ||
 		    (adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count <= 0))
 			pi->smc_state_table.UvdBootLevel = 0;
@@ -4200,9 +4210,14 @@ static int ci_update_uvd_dpm(struct amdg
 		tmp &= ~DPM_TABLE_475__UvdBootLevel_MASK;
 		tmp |= (pi->smc_state_table.UvdBootLevel << DPM_TABLE_475__UvdBootLevel__SHIFT);
 		WREG32_SMC(ixDPM_TABLE_475, tmp);
+		ret = ci_enable_uvd_dpm(adev, true);
+	} else {
+		ret = ci_enable_uvd_dpm(adev, false);
+		if (ret)
+			return ret;
 	}
 
-	return ci_enable_uvd_dpm(adev, !gate);
+	return ret;
 }
 
 static u8 ci_get_vce_boot_level(struct amdgpu_device *adev)
@@ -4244,13 +4259,12 @@ static int ci_update_vce_dpm(struct amdg
 
 			ret = ci_enable_vce_dpm(adev, true);
 		} else {
+			ret = ci_enable_vce_dpm(adev, false);
+			if (ret)
+				return ret;
 			/* turn the clocks off when not encoding */
 			ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
 							    AMD_CG_STATE_GATE);
-			if (ret)
-				return ret;
-
-			ret = ci_enable_vce_dpm(adev, false);
 		}
 	}
 	return ret;
@@ -5216,6 +5230,7 @@ static void ci_update_current_ps(struct
 	pi->current_rps = *rps;
 	pi->current_ps = *new_ps;
 	pi->current_rps.ps_priv = &pi->current_ps;
+	adev->pm.dpm.current_ps = &pi->current_rps;
 }
 
 static void ci_update_requested_ps(struct amdgpu_device *adev,
@@ -5227,6 +5242,7 @@ static void ci_update_requested_ps(struc
 	pi->requested_rps = *rps;
 	pi->requested_ps = *new_ps;
 	pi->requested_rps.ps_priv = &pi->requested_ps;
+	adev->pm.dpm.requested_ps = &pi->requested_rps;
 }
 
 static int ci_dpm_pre_set_power_state(struct amdgpu_device *adev)
@@ -5264,8 +5280,6 @@ static int ci_dpm_enable(struct amdgpu_d
 	struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps;
 	int ret;
 
-	if (amdgpu_ci_is_smc_running(adev))
-		return -EINVAL;
 	if (pi->voltage_control != CISLANDS_VOLTAGE_CONTROL_NONE) {
 		ci_enable_voltage_control(adev);
 		ret = ci_construct_voltage_tables(adev);
@@ -5686,7 +5700,7 @@ static int ci_parse_power_table(struct a
 	adev->pm.dpm.num_ps = state_array->ucNumEntries;
 
 	/* fill in the vce power states */
-	for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) {
+	for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
 		u32 sclk, mclk;
 		clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
 		clock_info = (union pplib_clock_info *)
@@ -5871,7 +5885,7 @@ static int ci_dpm_init(struct amdgpu_dev
 	pi->pcie_dpm_key_disabled = 0;
 	pi->thermal_sclk_dpm_enabled = 0;
 
-	if (amdgpu_sclk_deep_sleep_en)
+	if (amdgpu_pp_feature_mask & SCLK_DEEP_SLEEP_MASK)
 		pi->caps_sclk_ds = true;
 	else
 		pi->caps_sclk_ds = false;
@@ -5974,7 +5988,7 @@ static int ci_dpm_init(struct amdgpu_dev
 			tmp |= CNB_PWRMGT_CNTL__DPM_ENABLED_MASK;
 			break;
 		default:
-			DRM_ERROR("Invalid PCC GPIO: %u!\n", gpio.shift);
+			DRM_INFO("Invalid PCC GPIO: %u!\n", gpio.shift);
 			break;
 		}
 		WREG32_SMC(ixCNB_PWRMGT_CNTL, tmp);
@@ -6066,7 +6080,7 @@ ci_dpm_debugfs_print_current_performance
 		activity_percent = activity_percent > 100 ? 100 : activity_percent;
 	}
 
-	seq_printf(m, "uvd %sabled\n", pi->uvd_enabled ? "en" : "dis");
+	seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en");
 	seq_printf(m, "vce %sabled\n", rps->vce_active ? "en" : "dis");
 	seq_printf(m, "power level avg    sclk: %u mclk: %u\n",
 		   sclk, mclk);
@@ -6091,6 +6105,56 @@ static void ci_dpm_print_power_state(str
 	amdgpu_dpm_print_ps_status(adev, rps);
 }
 
+static inline bool ci_are_power_levels_equal(const struct ci_pl *ci_cpl1,
+						const struct ci_pl *ci_cpl2)
+{
+	return ((ci_cpl1->mclk == ci_cpl2->mclk) &&
+		  (ci_cpl1->sclk == ci_cpl2->sclk) &&
+		  (ci_cpl1->pcie_gen == ci_cpl2->pcie_gen) &&
+		  (ci_cpl1->pcie_lane == ci_cpl2->pcie_lane));
+}
+
+static int ci_check_state_equal(struct amdgpu_device *adev,
+				struct amdgpu_ps *cps,
+				struct amdgpu_ps *rps,
+				bool *equal)
+{
+	struct ci_ps *ci_cps;
+	struct ci_ps *ci_rps;
+	int i;
+
+	if (adev == NULL || cps == NULL || rps == NULL || equal == NULL)
+		return -EINVAL;
+
+	ci_cps = ci_get_ps(cps);
+	ci_rps = ci_get_ps(rps);
+
+	if (ci_cps == NULL) {
+		*equal = false;
+		return 0;
+	}
+
+	if (ci_cps->performance_level_count != ci_rps->performance_level_count) {
+
+		*equal = false;
+		return 0;
+	}
+
+	for (i = 0; i < ci_cps->performance_level_count; i++) {
+		if (!ci_are_power_levels_equal(&(ci_cps->performance_levels[i]),
+					&(ci_rps->performance_levels[i]))) {
+			*equal = false;
+			return 0;
+		}
+	}
+
+	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
+	*equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk));
+	*equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk));
+
+	return 0;
+}
+
 static u32 ci_dpm_get_sclk(struct amdgpu_device *adev, bool low)
 {
 	struct ci_power_info *pi = ci_get_pi(adev);
@@ -6286,12 +6350,19 @@ static int ci_dpm_suspend(void *handle)
 
 	if (adev->pm.dpm_enabled) {
 		mutex_lock(&adev->pm.mutex);
-		/* disable dpm */
-		ci_dpm_disable(adev);
-		/* reset the power state */
-		adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps;
+		amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
+			       AMDGPU_THERMAL_IRQ_LOW_TO_HIGH);
+		amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq,
+			       AMDGPU_THERMAL_IRQ_HIGH_TO_LOW);
+		adev->pm.dpm.last_user_state = adev->pm.dpm.user_state;
+		adev->pm.dpm.last_state = adev->pm.dpm.state;
+		adev->pm.dpm.user_state = POWER_STATE_TYPE_INTERNAL_BOOT;
+		adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_BOOT;
 		mutex_unlock(&adev->pm.mutex);
+		amdgpu_pm_compute_clocks(adev);
+
 	}
+
 	return 0;
 }
 
@@ -6309,6 +6380,8 @@ static int ci_dpm_resume(void *handle)
 			adev->pm.dpm_enabled = false;
 		else
 			adev->pm.dpm_enabled = true;
+		adev->pm.dpm.user_state = adev->pm.dpm.last_user_state;
+		adev->pm.dpm.state = adev->pm.dpm.last_state;
 		mutex_unlock(&adev->pm.mutex);
 		if (adev->pm.dpm_enabled)
 			amdgpu_pm_compute_clocks(adev);
@@ -6643,6 +6716,8 @@ static const struct amdgpu_dpm_funcs ci_
 	.set_sclk_od = ci_dpm_set_sclk_od,
 	.get_mclk_od = ci_dpm_get_mclk_od,
 	.set_mclk_od = ci_dpm_set_mclk_od,
+	.check_state_equal = ci_check_state_equal,
+	.get_vce_clock_state = amdgpu_get_vce_clock_state,
 };
 
 static void ci_dpm_set_dpm_funcs(struct amdgpu_device *adev)
@@ -6661,3 +6736,12 @@ static void ci_dpm_set_irq_funcs(struct
 	adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;
 	adev->pm.dpm.thermal.irq.funcs = &ci_dpm_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version ci_dpm_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SMC,
+	.major = 7,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &ci_dpm_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik.c	2017-02-12 16:03:20.000000000 -0500
@@ -1189,18 +1189,6 @@ static int cik_gpu_pci_config_reset(stru
 	return r;
 }
 
-static void cik_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hung)
-{
-	u32 tmp = RREG32(mmBIOS_SCRATCH_3);
-
-	if (hung)
-		tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-	else
-		tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-
-	WREG32(mmBIOS_SCRATCH_3, tmp);
-}
-
 /**
  * cik_asic_reset - soft reset GPU
  *
@@ -1213,11 +1201,12 @@ static void cik_set_bios_scratch_engine_
 static int cik_asic_reset(struct amdgpu_device *adev)
 {
 	int r;
-	cik_set_bios_scratch_engine_hung(adev, true);
+
+	amdgpu_atombios_scratch_regs_engine_hung(adev, true);
 
 	r = cik_gpu_pci_config_reset(adev);
 
-	cik_set_bios_scratch_engine_hung(adev, false);
+	amdgpu_atombios_scratch_regs_engine_hung(adev, false);
 
 	return r;
 }
@@ -1641,745 +1630,6 @@ static void cik_detect_hw_virtualization
 		adev->virtualization.virtual_caps |= AMDGPU_PASSTHROUGH_MODE;
 }
 
-static const struct amdgpu_ip_block_version bonaire_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &dce_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version bonaire_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version hawaii_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 5,
-		.rev = 0,
-		.funcs = &dce_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version hawaii_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 5,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version kabini_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &dce_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version kabini_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version mullins_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &dce_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version mullins_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version kaveri_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &dce_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version kaveri_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 8,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &gfx_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cik_sdma_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 4,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &uvd_v4_2_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v2_0_ip_funcs,
-	},
-};
-
-int cik_set_ip_blocks(struct amdgpu_device *adev)
-{
-	if (adev->enable_virtual_display) {
-		switch (adev->asic_type) {
-		case CHIP_BONAIRE:
-			adev->ip_blocks = bonaire_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks_vd);
-			break;
-		case CHIP_HAWAII:
-			adev->ip_blocks = hawaii_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks_vd);
-			break;
-		case CHIP_KAVERI:
-			adev->ip_blocks = kaveri_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks_vd);
-			break;
-		case CHIP_KABINI:
-			adev->ip_blocks = kabini_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks_vd);
-			break;
-		case CHIP_MULLINS:
-			adev->ip_blocks = mullins_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks_vd);
-			break;
-		default:
-			/* FIXME: not supported yet */
-			return -EINVAL;
-		}
-	} else {
-		switch (adev->asic_type) {
-		case CHIP_BONAIRE:
-			adev->ip_blocks = bonaire_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(bonaire_ip_blocks);
-			break;
-		case CHIP_HAWAII:
-			adev->ip_blocks = hawaii_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(hawaii_ip_blocks);
-			break;
-		case CHIP_KAVERI:
-			adev->ip_blocks = kaveri_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(kaveri_ip_blocks);
-			break;
-		case CHIP_KABINI:
-			adev->ip_blocks = kabini_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(kabini_ip_blocks);
-			break;
-		case CHIP_MULLINS:
-			adev->ip_blocks = mullins_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(mullins_ip_blocks);
-			break;
-		default:
-			/* FIXME: not supported yet */
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
 static const struct amdgpu_asic_funcs cik_asic_funcs =
 {
 	.read_disabled_bios = &cik_read_disabled_bios,
@@ -2612,7 +1862,7 @@ static int cik_common_set_powergating_st
 	return 0;
 }
 
-const struct amd_ip_funcs cik_common_ip_funcs = {
+static const struct amd_ip_funcs cik_common_ip_funcs = {
 	.name = "cik_common",
 	.early_init = cik_common_early_init,
 	.late_init = NULL,
@@ -2628,3 +1878,79 @@ const struct amd_ip_funcs cik_common_ip_
 	.set_clockgating_state = cik_common_set_clockgating_state,
 	.set_powergating_state = cik_common_set_powergating_state,
 };
+
+static const struct amdgpu_ip_block_version cik_common_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_COMMON,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &cik_common_ip_funcs,
+};
+
+int cik_set_ip_blocks(struct amdgpu_device *adev)
+{
+	switch (adev->asic_type) {
+	case CHIP_BONAIRE:
+		amdgpu_ip_block_add(adev, &cik_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+		amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v8_2_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block);
+		amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+		break;
+	case CHIP_HAWAII:
+		amdgpu_ip_block_add(adev, &cik_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+		amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v8_5_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v7_3_ip_block);
+		amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+		break;
+	case CHIP_KAVERI:
+		amdgpu_ip_block_add(adev, &cik_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+		amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v8_1_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v7_1_ip_block);
+		amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+		break;
+	case CHIP_KABINI:
+	case CHIP_MULLINS:
+		amdgpu_ip_block_add(adev, &cik_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v7_0_ip_block);
+		amdgpu_ip_block_add(adev, &cik_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v8_3_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block);
+		amdgpu_ip_block_add(adev, &cik_sdma_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v4_2_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v2_0_ip_block);
+		break;
+	default:
+		/* FIXME: not supported yet */
+		return -EINVAL;
+	}
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cikd.h	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,14 @@
 #define CRTC4_REGISTER_OFFSET                 (0x477c - 0x1b7c)
 #define CRTC5_REGISTER_OFFSET                 (0x4a7c - 0x1b7c)
 
+/* hpd instance offsets */
+#define HPD0_REGISTER_OFFSET                 (0x1807 - 0x1807)
+#define HPD1_REGISTER_OFFSET                 (0x180a - 0x1807)
+#define HPD2_REGISTER_OFFSET                 (0x180d - 0x1807)
+#define HPD3_REGISTER_OFFSET                 (0x1810 - 0x1807)
+#define HPD4_REGISTER_OFFSET                 (0x1813 - 0x1807)
+#define HPD5_REGISTER_OFFSET                 (0x1816 - 0x1807)
+
 #define BONAIRE_GB_ADDR_CONFIG_GOLDEN        0x12010001
 #define HAWAII_GB_ADDR_CONFIG_GOLDEN         0x12011003
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,6 @@
 #ifndef __CIK_H__
 #define __CIK_H__
 
-extern const struct amd_ip_funcs cik_common_ip_funcs;
-
 void cik_srbm_select(struct amdgpu_device *adev,
 		     u32 me, u32 pipe, u32 queue, u32 vmid);
 int cik_set_ip_blocks(struct amdgpu_device *adev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.c	2017-02-12 16:03:20.000000000 -0500
@@ -413,7 +413,7 @@ static int cik_ih_set_powergating_state(
 	return 0;
 }
 
-const struct amd_ip_funcs cik_ih_ip_funcs = {
+static const struct amd_ip_funcs cik_ih_ip_funcs = {
 	.name = "cik_ih",
 	.early_init = cik_ih_early_init,
 	.late_init = NULL,
@@ -441,3 +441,12 @@ static void cik_ih_set_interrupt_funcs(s
 	if (adev->irq.ih_funcs == NULL)
 		adev->irq.ih_funcs = &cik_ih_funcs;
 }
+
+const struct amdgpu_ip_block_version cik_ih_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_IH,
+	.major = 2,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &cik_ih_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_ih.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __CIK_IH_H__
 #define __CIK_IH_H__
 
-extern const struct amd_ip_funcs cik_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version cik_ih_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c	2016-12-11 17:41:34.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.c	2017-02-12 17:24:31.000000000 -0500
@@ -197,10 +197,10 @@ static void cik_sdma_ring_insert_nop(str
 
 	for (i = 0; i < count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
-			amdgpu_ring_write(ring, ring->nop |
+			amdgpu_ring_write(ring, ring->funcs->nop |
 					  SDMA_NOP_COUNT(count - 1));
 		else
-			amdgpu_ring_write(ring, ring->nop);
+			amdgpu_ring_write(ring, ring->funcs->nop);
 }
 
 /**
@@ -613,7 +613,7 @@ static int cik_sdma_ring_test_ib(struct
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	unsigned index;
 	u32 tmp = 0;
 	u64 gpu_addr;
@@ -646,7 +646,7 @@ static int cik_sdma_ring_test_ib(struct
 	if (r)
 		goto err1;
 
-	r = fence_wait_timeout(f, false, timeout);
+	r = dma_fence_wait_timeout(f, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out\n");
 		r = -ETIMEDOUT;
@@ -666,7 +666,7 @@ static int cik_sdma_ring_test_ib(struct
 
 err1:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 err0:
 	amdgpu_wb_free(adev, index);
 	return r;
@@ -839,22 +839,6 @@ static void cik_sdma_ring_emit_vm_flush(
 	amdgpu_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */
 }
 
-static unsigned cik_sdma_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		7 + 4; /* cik_sdma_ring_emit_ib */
-}
-
-static unsigned cik_sdma_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		6 + /* cik_sdma_ring_emit_hdp_flush */
-		3 + /* cik_sdma_ring_emit_hdp_invalidate */
-		6 + /* cik_sdma_ring_emit_pipeline_sync */
-		12 + /* cik_sdma_ring_emit_vm_flush */
-		9 + 9 + 9; /* cik_sdma_ring_emit_fence x3 for user fence, vm fence */
-}
-
 static void cik_enable_sdma_mgcg(struct amdgpu_device *adev,
 				 bool enable)
 {
@@ -950,11 +934,10 @@ static int cik_sdma_sw_init(void *handle
 		ring->ring_obj = NULL;
 		sprintf(ring->name, "sdma%d", i);
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0), 0xf,
 				     &adev->sdma.trap_irq,
 				     (i == 0) ?
-				     AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
-				     AMDGPU_RING_TYPE_SDMA);
+				     AMDGPU_SDMA_IRQ_TRAP0 :
+				     AMDGPU_SDMA_IRQ_TRAP1);
 		if (r)
 			return r;
 	}
@@ -1198,7 +1181,7 @@ static int cik_sdma_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs cik_sdma_ip_funcs = {
+static const struct amd_ip_funcs cik_sdma_ip_funcs = {
 	.name = "cik_sdma",
 	.early_init = cik_sdma_early_init,
 	.late_init = NULL,
@@ -1216,10 +1199,19 @@ const struct amd_ip_funcs cik_sdma_ip_fu
 };
 
 static const struct amdgpu_ring_funcs cik_sdma_ring_funcs = {
+	.type = AMDGPU_RING_TYPE_SDMA,
+	.align_mask = 0xf,
+	.nop = SDMA_PACKET(SDMA_OPCODE_NOP, 0, 0),
 	.get_rptr = cik_sdma_ring_get_rptr,
 	.get_wptr = cik_sdma_ring_get_wptr,
 	.set_wptr = cik_sdma_ring_set_wptr,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		6 + /* cik_sdma_ring_emit_hdp_flush */
+		3 + /* cik_sdma_ring_emit_hdp_invalidate */
+		6 + /* cik_sdma_ring_emit_pipeline_sync */
+		12 + /* cik_sdma_ring_emit_vm_flush */
+		9 + 9 + 9, /* cik_sdma_ring_emit_fence x3 for user fence, vm fence */
+	.emit_ib_size = 7 + 4, /* cik_sdma_ring_emit_ib */
 	.emit_ib = cik_sdma_ring_emit_ib,
 	.emit_fence = cik_sdma_ring_emit_fence,
 	.emit_pipeline_sync = cik_sdma_ring_emit_pipeline_sync,
@@ -1230,8 +1222,6 @@ static const struct amdgpu_ring_funcs ci
 	.test_ib = cik_sdma_ring_test_ib,
 	.insert_nop = cik_sdma_ring_insert_nop,
 	.pad_ib = cik_sdma_ring_pad_ib,
-	.get_emit_ib_size = cik_sdma_ring_get_emit_ib_size,
-	.get_dma_frame_size = cik_sdma_ring_get_dma_frame_size,
 };
 
 static void cik_sdma_set_ring_funcs(struct amdgpu_device *adev)
@@ -1343,3 +1333,12 @@ static void cik_sdma_set_vm_pte_funcs(st
 		adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
 	}
 }
+
+const struct amdgpu_ip_block_version cik_sdma_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SDMA,
+	.major = 2,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &cik_sdma_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cik_sdma.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __CIK_SDMA_H__
 #define __CIK_SDMA_H__
 
-extern const struct amd_ip_funcs cik_sdma_ip_funcs;
+extern const struct amdgpu_ip_block_version cik_sdma_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cz_dpm.c	2017-02-12 16:03:20.000000000 -0500
@@ -438,7 +438,7 @@ static int cz_dpm_init(struct amdgpu_dev
 		pi->caps_td_ramping = true;
 		pi->caps_tcp_ramping = true;
 	}
-	if (amdgpu_sclk_deep_sleep_en)
+	if (amdgpu_pp_feature_mask & SCLK_DEEP_SLEEP_MASK)
 		pi->caps_sclk_ds = true;
 	else
 		pi->caps_sclk_ds = false;
@@ -1250,7 +1250,8 @@ static void cz_update_current_ps(struct
 
 	pi->current_ps = *ps;
 	pi->current_rps = *rps;
-	pi->current_rps.ps_priv = ps;
+	pi->current_rps.ps_priv = &pi->current_ps;
+	adev->pm.dpm.current_ps = &pi->current_rps;
 
 }
 
@@ -1262,7 +1263,8 @@ static void cz_update_requested_ps(struc
 
 	pi->requested_ps = *ps;
 	pi->requested_rps = *rps;
-	pi->requested_rps.ps_priv = ps;
+	pi->requested_rps.ps_priv = &pi->requested_ps;
+	adev->pm.dpm.requested_ps = &pi->requested_rps;
 
 }
 
@@ -2109,9 +2111,8 @@ static void cz_dpm_powergate_uvd(struct
 
 	if (gate) {
 		if (pi->caps_uvd_pg) {
-			/* disable clockgating so we can properly shut down the block */
 			ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
-							    AMD_CG_STATE_UNGATE);
+							    AMD_CG_STATE_GATE);
 			if (ret) {
 				DRM_ERROR("UVD DPM Power Gating failed to set clockgating state\n");
 				return;
@@ -2157,9 +2158,8 @@ static void cz_dpm_powergate_uvd(struct
 				return;
 			}
 
-			/* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
 			ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
-							    AMD_CG_STATE_GATE);
+							    AMD_CG_STATE_UNGATE);
 			if (ret) {
 				DRM_ERROR("UVD DPM Power Gating Failed to set clockgating state\n");
 				return;
@@ -2257,6 +2257,18 @@ static void cz_dpm_powergate_vce(struct
 	}
 }
 
+static int cz_check_state_equal(struct amdgpu_device *adev,
+				struct amdgpu_ps *cps,
+				struct amdgpu_ps *rps,
+				bool *equal)
+{
+	if (equal == NULL)
+		return -EINVAL;
+
+	*equal = false;
+	return 0;
+}
+
 const struct amd_ip_funcs cz_dpm_ip_funcs = {
 	.name = "cz_dpm",
 	.early_init = cz_dpm_early_init,
@@ -2289,6 +2301,7 @@ static const struct amdgpu_dpm_funcs cz_
 	.vblank_too_short = NULL,
 	.powergate_uvd = cz_dpm_powergate_uvd,
 	.powergate_vce = cz_dpm_powergate_vce,
+	.check_state_equal = cz_check_state_equal,
 };
 
 static void cz_dpm_set_funcs(struct amdgpu_device *adev)
@@ -2296,3 +2309,12 @@ static void cz_dpm_set_funcs(struct amdg
 	if (NULL == adev->pm.funcs)
 		adev->pm.funcs = &cz_dpm_funcs;
 }
+
+const struct amdgpu_ip_block_version cz_dpm_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SMC,
+	.major = 8,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &cz_dpm_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.c	2017-02-12 16:03:20.000000000 -0500
@@ -394,7 +394,7 @@ static int cz_ih_set_powergating_state(v
 	return 0;
 }
 
-const struct amd_ip_funcs cz_ih_ip_funcs = {
+static const struct amd_ip_funcs cz_ih_ip_funcs = {
 	.name = "cz_ih",
 	.early_init = cz_ih_early_init,
 	.late_init = NULL,
@@ -423,3 +423,11 @@ static void cz_ih_set_interrupt_funcs(st
 		adev->irq.ih_funcs = &cz_ih_funcs;
 }
 
+const struct amdgpu_ip_block_version cz_ih_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_IH,
+	.major = 3,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &cz_ih_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/cz_ih.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __CZ_IH_H__
 #define __CZ_IH_H__
 
-extern const struct amd_ip_funcs cz_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version cz_ih_ip_block;
 
 #endif /* __CZ_IH_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@
 #include "atombios_encoders.h"
 #include "amdgpu_pll.h"
 #include "amdgpu_connectors.h"
+#include "dce_v10_0.h"
 
 #include "dce/dce_10_0_d.h"
 #include "dce/dce_10_0_sh_mask.h"
@@ -330,33 +331,12 @@ static int dce_v10_0_crtc_get_scanoutpos
 static bool dce_v10_0_hpd_sense(struct amdgpu_device *adev,
 			       enum amdgpu_hpd_id hpd)
 {
-	int idx;
 	bool connected = false;
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		idx = 0;
-		break;
-	case AMDGPU_HPD_2:
-		idx = 1;
-		break;
-	case AMDGPU_HPD_3:
-		idx = 2;
-		break;
-	case AMDGPU_HPD_4:
-		idx = 3;
-		break;
-	case AMDGPU_HPD_5:
-		idx = 4;
-		break;
-	case AMDGPU_HPD_6:
-		idx = 5;
-		break;
-	default:
+	if (hpd >= adev->mode_info.num_hpd)
 		return connected;
-	}
 
-	if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[idx]) &
+	if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[hpd]) &
 	    DC_HPD_INT_STATUS__DC_HPD_SENSE_MASK)
 		connected = true;
 
@@ -376,37 +356,16 @@ static void dce_v10_0_hpd_set_polarity(s
 {
 	u32 tmp;
 	bool connected = dce_v10_0_hpd_sense(adev, hpd);
-	int idx;
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		idx = 0;
-		break;
-	case AMDGPU_HPD_2:
-		idx = 1;
-		break;
-	case AMDGPU_HPD_3:
-		idx = 2;
-		break;
-	case AMDGPU_HPD_4:
-		idx = 3;
-		break;
-	case AMDGPU_HPD_5:
-		idx = 4;
-		break;
-	case AMDGPU_HPD_6:
-		idx = 5;
-		break;
-	default:
+	if (hpd >= adev->mode_info.num_hpd)
 		return;
-	}
 
-	tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+	tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd]);
 	if (connected)
 		tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 0);
 	else
 		tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 1);
-	WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+	WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd], tmp);
 }
 
 /**
@@ -422,33 +381,12 @@ static void dce_v10_0_hpd_init(struct am
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
 	u32 tmp;
-	int idx;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			idx = 0;
-			break;
-		case AMDGPU_HPD_2:
-			idx = 1;
-			break;
-		case AMDGPU_HPD_3:
-			idx = 2;
-			break;
-		case AMDGPU_HPD_4:
-			idx = 3;
-			break;
-		case AMDGPU_HPD_5:
-			idx = 4;
-			break;
-		case AMDGPU_HPD_6:
-			idx = 5;
-			break;
-		default:
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
 			continue;
-		}
 
 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
 		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -457,24 +395,24 @@ static void dce_v10_0_hpd_init(struct am
 			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
 			 * also avoid interrupt storms during dpms.
 			 */
-			tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+			tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 			tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0);
-			WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+			WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 			continue;
 		}
 
-		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1);
-		WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+		WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
-		tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx]);
+		tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
 				    DC_HPD_CONNECT_INT_DELAY,
 				    AMDGPU_HPD_CONNECT_INT_DELAY_IN_MS);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
 				    DC_HPD_DISCONNECT_INT_DELAY,
 				    AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS);
-		WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx], tmp);
+		WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
 		dce_v10_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
 		amdgpu_irq_get(adev, &adev->hpd_irq,
@@ -495,37 +433,16 @@ static void dce_v10_0_hpd_fini(struct am
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
 	u32 tmp;
-	int idx;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			idx = 0;
-			break;
-		case AMDGPU_HPD_2:
-			idx = 1;
-			break;
-		case AMDGPU_HPD_3:
-			idx = 2;
-			break;
-		case AMDGPU_HPD_4:
-			idx = 3;
-			break;
-		case AMDGPU_HPD_5:
-			idx = 4;
-			break;
-		case AMDGPU_HPD_6:
-			idx = 5;
-			break;
-		default:
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
 			continue;
-		}
 
-		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 0);
-		WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+		WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
 		amdgpu_irq_put(adev, &adev->hpd_irq,
 			       amdgpu_connector->hpd.hpd);
@@ -2115,7 +2032,7 @@ static int dce_v10_0_crtc_do_set_base(st
 	u32 tmp, viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
-	char *format_name;
+	struct drm_format_name_buf format_name;
 
 	/* no fb bound */
 	if (!atomic && !crtc->primary->fb) {
@@ -2227,9 +2144,8 @@ static int dce_v10_0_crtc_do_set_base(st
 		bypass_lut = true;
 		break;
 	default:
-		format_name = drm_get_format_name(target_fb->pixel_format);
-		DRM_ERROR("Unsupported screen format %s\n", format_name);
-		kfree(format_name);
+		DRM_ERROR("Unsupported screen format %s\n",
+		          drm_get_format_name(target_fb->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
@@ -2577,6 +2493,9 @@ static int dce_v10_0_cursor_move_locked(
 	struct amdgpu_device *adev = crtc->dev->dev_private;
 	int xorigin = 0, yorigin = 0;
 
+	amdgpu_crtc->cursor_x = x;
+	amdgpu_crtc->cursor_y = y;
+
 	/* avivo cursor are offset into the total surface */
 	x += crtc->x;
 	y += crtc->y;
@@ -2596,9 +2515,6 @@ static int dce_v10_0_cursor_move_locked(
 	WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
 	       ((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
-	amdgpu_crtc->cursor_x = x;
-	amdgpu_crtc->cursor_y = y;
-
 	return 0;
 }
 
@@ -2661,12 +2577,11 @@ static int dce_v10_0_crtc_cursor_set2(st
 		return ret;
 	}
 
-	amdgpu_crtc->cursor_width = width;
-	amdgpu_crtc->cursor_height = height;
-
 	dce_v10_0_lock_cursor(crtc, true);
 
-	if (hot_x != amdgpu_crtc->cursor_hot_x ||
+	if (width != amdgpu_crtc->cursor_width ||
+	    height != amdgpu_crtc->cursor_height ||
+	    hot_x != amdgpu_crtc->cursor_hot_x ||
 	    hot_y != amdgpu_crtc->cursor_hot_y) {
 		int x, y;
 
@@ -2675,6 +2590,8 @@ static int dce_v10_0_crtc_cursor_set2(st
 
 		dce_v10_0_cursor_move_locked(crtc, x, y);
 
+		amdgpu_crtc->cursor_width = width;
+		amdgpu_crtc->cursor_height = height;
 		amdgpu_crtc->cursor_hot_x = hot_x;
 		amdgpu_crtc->cursor_hot_y = hot_y;
 	}
@@ -3548,7 +3465,7 @@ static int dce_v10_0_set_powergating_sta
 	return 0;
 }
 
-const struct amd_ip_funcs dce_v10_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v10_0_ip_funcs = {
 	.name = "dce_v10_0",
 	.early_init = dce_v10_0_early_init,
 	.late_init = NULL,
@@ -3833,7 +3750,6 @@ static const struct amdgpu_display_funcs
 	.bandwidth_update = &dce_v10_0_bandwidth_update,
 	.vblank_get_counter = &dce_v10_0_vblank_get_counter,
 	.vblank_wait = &dce_v10_0_vblank_wait,
-	.is_display_hung = &dce_v10_0_is_display_hung,
 	.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
 	.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
 	.hpd_sense = &dce_v10_0_hpd_sense,
@@ -3879,3 +3795,21 @@ static void dce_v10_0_set_irq_funcs(stru
 	adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
 	adev->hpd_irq.funcs = &dce_v10_0_hpd_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version dce_v10_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 10,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &dce_v10_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v10_1_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 10,
+	.minor = 1,
+	.rev = 0,
+	.funcs = &dce_v10_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v10_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,9 @@
 #ifndef __DCE_V10_0_H__
 #define __DCE_V10_0_H__
 
-extern const struct amd_ip_funcs dce_v10_0_ip_funcs;
+
+extern const struct amdgpu_ip_block_version dce_v10_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v10_1_ip_block;
 
 void dce_v10_0_disable_dce(struct amdgpu_device *adev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@
 #include "atombios_encoders.h"
 #include "amdgpu_pll.h"
 #include "amdgpu_connectors.h"
+#include "dce_v11_0.h"
 
 #include "dce/dce_11_0_d.h"
 #include "dce/dce_11_0_sh_mask.h"
@@ -166,6 +167,7 @@ static void dce_v11_0_init_golden_regist
 						 (const u32)ARRAY_SIZE(stoney_golden_settings_a11));
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		amdgpu_program_register_sequence(adev,
 						 polaris11_golden_settings_a11,
 						 (const u32)ARRAY_SIZE(polaris11_golden_settings_a11));
@@ -346,33 +348,12 @@ static int dce_v11_0_crtc_get_scanoutpos
 static bool dce_v11_0_hpd_sense(struct amdgpu_device *adev,
 			       enum amdgpu_hpd_id hpd)
 {
-	int idx;
 	bool connected = false;
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		idx = 0;
-		break;
-	case AMDGPU_HPD_2:
-		idx = 1;
-		break;
-	case AMDGPU_HPD_3:
-		idx = 2;
-		break;
-	case AMDGPU_HPD_4:
-		idx = 3;
-		break;
-	case AMDGPU_HPD_5:
-		idx = 4;
-		break;
-	case AMDGPU_HPD_6:
-		idx = 5;
-		break;
-	default:
+	if (hpd >= adev->mode_info.num_hpd)
 		return connected;
-	}
 
-	if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[idx]) &
+	if (RREG32(mmDC_HPD_INT_STATUS + hpd_offsets[hpd]) &
 	    DC_HPD_INT_STATUS__DC_HPD_SENSE_MASK)
 		connected = true;
 
@@ -392,37 +373,16 @@ static void dce_v11_0_hpd_set_polarity(s
 {
 	u32 tmp;
 	bool connected = dce_v11_0_hpd_sense(adev, hpd);
-	int idx;
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		idx = 0;
-		break;
-	case AMDGPU_HPD_2:
-		idx = 1;
-		break;
-	case AMDGPU_HPD_3:
-		idx = 2;
-		break;
-	case AMDGPU_HPD_4:
-		idx = 3;
-		break;
-	case AMDGPU_HPD_5:
-		idx = 4;
-		break;
-	case AMDGPU_HPD_6:
-		idx = 5;
-		break;
-	default:
+	if (hpd >= adev->mode_info.num_hpd)
 		return;
-	}
 
-	tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+	tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd]);
 	if (connected)
 		tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 0);
 	else
 		tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY, 1);
-	WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+	WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[hpd], tmp);
 }
 
 /**
@@ -438,33 +398,12 @@ static void dce_v11_0_hpd_init(struct am
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
 	u32 tmp;
-	int idx;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			idx = 0;
-			break;
-		case AMDGPU_HPD_2:
-			idx = 1;
-			break;
-		case AMDGPU_HPD_3:
-			idx = 2;
-			break;
-		case AMDGPU_HPD_4:
-			idx = 3;
-			break;
-		case AMDGPU_HPD_5:
-			idx = 4;
-			break;
-		case AMDGPU_HPD_6:
-			idx = 5;
-			break;
-		default:
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
 			continue;
-		}
 
 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
 		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -473,24 +412,24 @@ static void dce_v11_0_hpd_init(struct am
 			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
 			 * also avoid interrupt storms during dpms.
 			 */
-			tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx]);
+			tmp = RREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 			tmp = REG_SET_FIELD(tmp, DC_HPD_INT_CONTROL, DC_HPD_INT_EN, 0);
-			WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[idx], tmp);
+			WREG32(mmDC_HPD_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 			continue;
 		}
 
-		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 1);
-		WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+		WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
-		tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx]);
+		tmp = RREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
 				    DC_HPD_CONNECT_INT_DELAY,
 				    AMDGPU_HPD_CONNECT_INT_DELAY_IN_MS);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_TOGGLE_FILT_CNTL,
 				    DC_HPD_DISCONNECT_INT_DELAY,
 				    AMDGPU_HPD_DISCONNECT_INT_DELAY_IN_MS);
-		WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[idx], tmp);
+		WREG32(mmDC_HPD_TOGGLE_FILT_CNTL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
 		dce_v11_0_hpd_set_polarity(adev, amdgpu_connector->hpd.hpd);
 		amdgpu_irq_get(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
@@ -510,37 +449,16 @@ static void dce_v11_0_hpd_fini(struct am
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
 	u32 tmp;
-	int idx;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			idx = 0;
-			break;
-		case AMDGPU_HPD_2:
-			idx = 1;
-			break;
-		case AMDGPU_HPD_3:
-			idx = 2;
-			break;
-		case AMDGPU_HPD_4:
-			idx = 3;
-			break;
-		case AMDGPU_HPD_5:
-			idx = 4;
-			break;
-		case AMDGPU_HPD_6:
-			idx = 5;
-			break;
-		default:
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
 			continue;
-		}
 
-		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[idx]);
+		tmp = RREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
 		tmp = REG_SET_FIELD(tmp, DC_HPD_CONTROL, DC_HPD_EN, 0);
-		WREG32(mmDC_HPD_CONTROL + hpd_offsets[idx], tmp);
+		WREG32(mmDC_HPD_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
 		amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
 	}
@@ -691,6 +609,7 @@ static int dce_v11_0_get_num_crtc (struc
 		num_crtc = 6;
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		num_crtc = 5;
 		break;
 	default:
@@ -1672,6 +1591,7 @@ static int dce_v11_0_audio_init(struct a
 		adev->mode_info.audio.num_pins = 8;
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		adev->mode_info.audio.num_pins = 6;
 		break;
 	default:
@@ -2096,7 +2016,7 @@ static int dce_v11_0_crtc_do_set_base(st
 	u32 tmp, viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
-	char *format_name;
+	struct drm_format_name_buf format_name;
 
 	/* no fb bound */
 	if (!atomic && !crtc->primary->fb) {
@@ -2208,9 +2128,8 @@ static int dce_v11_0_crtc_do_set_base(st
 		bypass_lut = true;
 		break;
 	default:
-		format_name = drm_get_format_name(target_fb->pixel_format);
-		DRM_ERROR("Unsupported screen format %s\n", format_name);
-		kfree(format_name);
+		DRM_ERROR("Unsupported screen format %s\n",
+		          drm_get_format_name(target_fb->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
@@ -2472,7 +2391,8 @@ static u32 dce_v11_0_pick_pll(struct drm
 	int pll;
 
 	if ((adev->asic_type == CHIP_POLARIS10) ||
-	    (adev->asic_type == CHIP_POLARIS11)) {
+	    (adev->asic_type == CHIP_POLARIS11) ||
+	    (adev->asic_type == CHIP_POLARIS12)) {
 		struct amdgpu_encoder *amdgpu_encoder =
 			to_amdgpu_encoder(amdgpu_crtc->encoder);
 		struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv;
@@ -2593,6 +2513,9 @@ static int dce_v11_0_cursor_move_locked(
 	struct amdgpu_device *adev = crtc->dev->dev_private;
 	int xorigin = 0, yorigin = 0;
 
+	amdgpu_crtc->cursor_x = x;
+	amdgpu_crtc->cursor_y = y;
+
 	/* avivo cursor are offset into the total surface */
 	x += crtc->x;
 	y += crtc->y;
@@ -2612,9 +2535,6 @@ static int dce_v11_0_cursor_move_locked(
 	WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
 	       ((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
-	amdgpu_crtc->cursor_x = x;
-	amdgpu_crtc->cursor_y = y;
-
 	return 0;
 }
 
@@ -2677,12 +2597,11 @@ static int dce_v11_0_crtc_cursor_set2(st
 		return ret;
 	}
 
-	amdgpu_crtc->cursor_width = width;
-	amdgpu_crtc->cursor_height = height;
-
 	dce_v11_0_lock_cursor(crtc, true);
 
-	if (hot_x != amdgpu_crtc->cursor_hot_x ||
+	if (width != amdgpu_crtc->cursor_width ||
+	    height != amdgpu_crtc->cursor_height ||
+	    hot_x != amdgpu_crtc->cursor_hot_x ||
 	    hot_y != amdgpu_crtc->cursor_hot_y) {
 		int x, y;
 
@@ -2691,6 +2610,8 @@ static int dce_v11_0_crtc_cursor_set2(st
 
 		dce_v11_0_cursor_move_locked(crtc, x, y);
 
+		amdgpu_crtc->cursor_width = width;
+		amdgpu_crtc->cursor_height = height;
 		amdgpu_crtc->cursor_hot_x = hot_x;
 		amdgpu_crtc->cursor_hot_y = hot_y;
 	}
@@ -2897,7 +2818,8 @@ static int dce_v11_0_crtc_mode_set(struc
 		return -EINVAL;
 
 	if ((adev->asic_type == CHIP_POLARIS10) ||
-	    (adev->asic_type == CHIP_POLARIS11)) {
+	    (adev->asic_type == CHIP_POLARIS11) ||
+	    (adev->asic_type == CHIP_POLARIS12)) {
 		struct amdgpu_encoder *amdgpu_encoder =
 			to_amdgpu_encoder(amdgpu_crtc->encoder);
 		int encoder_mode =
@@ -3067,6 +2989,7 @@ static int dce_v11_0_early_init(void *ha
 		adev->mode_info.num_dig = 6;
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		adev->mode_info.num_hpd = 5;
 		adev->mode_info.num_dig = 5;
 		break;
@@ -3176,7 +3099,8 @@ static int dce_v11_0_hw_init(void *handl
 	amdgpu_atombios_crtc_powergate_init(adev);
 	amdgpu_atombios_encoder_init_dig(adev);
 	if ((adev->asic_type == CHIP_POLARIS10) ||
-	    (adev->asic_type == CHIP_POLARIS11)) {
+	    (adev->asic_type == CHIP_POLARIS11) ||
+	    (adev->asic_type == CHIP_POLARIS12)) {
 		amdgpu_atombios_crtc_set_dce_clock(adev, adev->clock.default_dispclk,
 						   DCE_CLOCK_TYPE_DISPCLK, ATOM_GCK_DFS);
 		amdgpu_atombios_crtc_set_dce_clock(adev, 0,
@@ -3605,7 +3529,7 @@ static int dce_v11_0_set_powergating_sta
 	return 0;
 }
 
-const struct amd_ip_funcs dce_v11_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v11_0_ip_funcs = {
 	.name = "dce_v11_0",
 	.early_init = dce_v11_0_early_init,
 	.late_init = NULL,
@@ -3889,7 +3813,6 @@ static const struct amdgpu_display_funcs
 	.bandwidth_update = &dce_v11_0_bandwidth_update,
 	.vblank_get_counter = &dce_v11_0_vblank_get_counter,
 	.vblank_wait = &dce_v11_0_vblank_wait,
-	.is_display_hung = &dce_v11_0_is_display_hung,
 	.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
 	.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
 	.hpd_sense = &dce_v11_0_hpd_sense,
@@ -3935,3 +3858,21 @@ static void dce_v11_0_set_irq_funcs(stru
 	adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
 	adev->hpd_irq.funcs = &dce_v11_0_hpd_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version dce_v11_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 11,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &dce_v11_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v11_2_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 11,
+	.minor = 2,
+	.rev = 0,
+	.funcs = &dce_v11_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v11_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,8 @@
 #ifndef __DCE_V11_0_H__
 #define __DCE_V11_0_H__
 
-extern const struct amd_ip_funcs dce_v11_0_ip_funcs;
+extern const struct amdgpu_ip_block_version dce_v11_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v11_2_ip_block;
 
 void dce_v11_0_disable_dce(struct amdgpu_device *adev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,8 +30,19 @@
 #include "atombios_encoders.h"
 #include "amdgpu_pll.h"
 #include "amdgpu_connectors.h"
-#include "si/si_reg.h"
-#include "si/sid.h"
+
+#include "bif/bif_3_0_d.h"
+#include "bif/bif_3_0_sh_mask.h"
+#include "oss/oss_1_0_d.h"
+#include "oss/oss_1_0_sh_mask.h"
+#include "gca/gfx_6_0_d.h"
+#include "gca/gfx_6_0_sh_mask.h"
+#include "gmc/gmc_6_0_d.h"
+#include "gmc/gmc_6_0_sh_mask.h"
+#include "dce/dce_6_0_d.h"
+#include "dce/dce_6_0_sh_mask.h"
+#include "gca/gfx_7_2_enum.h"
+#include "si_enums.h"
 
 static void dce_v6_0_set_display_funcs(struct amdgpu_device *adev);
 static void dce_v6_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -46,6 +57,16 @@ static const u32 crtc_offsets[6] =
 	SI_CRTC5_REGISTER_OFFSET
 };
 
+static const u32 hpd_offsets[] =
+{
+	mmDC_HPD1_INT_STATUS - mmDC_HPD1_INT_STATUS,
+	mmDC_HPD2_INT_STATUS - mmDC_HPD1_INT_STATUS,
+	mmDC_HPD3_INT_STATUS - mmDC_HPD1_INT_STATUS,
+	mmDC_HPD4_INT_STATUS - mmDC_HPD1_INT_STATUS,
+	mmDC_HPD5_INT_STATUS - mmDC_HPD1_INT_STATUS,
+	mmDC_HPD6_INT_STATUS - mmDC_HPD1_INT_STATUS,
+};
+
 static const uint32_t dig_offsets[] = {
 	SI_CRTC0_REGISTER_OFFSET,
 	SI_CRTC1_REGISTER_OFFSET,
@@ -63,46 +84,37 @@ static const struct {
 	uint32_t	hpd;
 
 } interrupt_status_offsets[6] = { {
-	.reg = DISP_INTERRUPT_STATUS,
+	.reg = mmDISP_INTERRUPT_STATUS,
 	.vblank = DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT_MASK,
 	.vline = DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT_MASK,
 	.hpd = DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT_MASK
 }, {
-	.reg = DISP_INTERRUPT_STATUS_CONTINUE,
+	.reg = mmDISP_INTERRUPT_STATUS_CONTINUE,
 	.vblank = DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT_MASK,
 	.vline = DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT_MASK,
 	.hpd = DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT_MASK
 }, {
-	.reg = DISP_INTERRUPT_STATUS_CONTINUE2,
+	.reg = mmDISP_INTERRUPT_STATUS_CONTINUE2,
 	.vblank = DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT_MASK,
 	.vline = DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT_MASK,
 	.hpd = DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT_MASK
 }, {
-	.reg = DISP_INTERRUPT_STATUS_CONTINUE3,
+	.reg = mmDISP_INTERRUPT_STATUS_CONTINUE3,
 	.vblank = DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT_MASK,
 	.vline = DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT_MASK,
 	.hpd = DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT_MASK
 }, {
-	.reg = DISP_INTERRUPT_STATUS_CONTINUE4,
+	.reg = mmDISP_INTERRUPT_STATUS_CONTINUE4,
 	.vblank = DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT_MASK,
 	.vline = DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT_MASK,
 	.hpd = DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT_MASK
 }, {
-	.reg = DISP_INTERRUPT_STATUS_CONTINUE5,
+	.reg = mmDISP_INTERRUPT_STATUS_CONTINUE5,
 	.vblank = DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT_MASK,
 	.vline = DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT_MASK,
 	.hpd = DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK
 } };
 
-static const uint32_t hpd_int_control_offsets[6] = {
-	DC_HPD1_INT_CONTROL,
-	DC_HPD2_INT_CONTROL,
-	DC_HPD3_INT_CONTROL,
-	DC_HPD4_INT_CONTROL,
-	DC_HPD5_INT_CONTROL,
-	DC_HPD6_INT_CONTROL,
-};
-
 static u32 dce_v6_0_audio_endpt_rreg(struct amdgpu_device *adev,
 				     u32 block_offset, u32 reg)
 {
@@ -118,7 +130,7 @@ static void dce_v6_0_audio_endpt_wreg(st
 
 static bool dce_v6_0_is_in_vblank(struct amdgpu_device *adev, int crtc)
 {
-	if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
+	if (RREG32(mmCRTC_STATUS + crtc_offsets[crtc]) & CRTC_STATUS__CRTC_V_BLANK_MASK)
 		return true;
 	else
 		return false;
@@ -128,8 +140,8 @@ static bool dce_v6_0_is_counter_moving(s
 {
 	u32 pos1, pos2;
 
-	pos1 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
-	pos2 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+	pos1 = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
+	pos2 = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
 
 	if (pos1 != pos2)
 		return true;
@@ -151,7 +163,7 @@ static void dce_v6_0_vblank_wait(struct
 	if (crtc >= adev->mode_info.num_crtc)
 		return;
 
-	if (!(RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN))
+	if (!(RREG32(mmCRTC_CONTROL + crtc_offsets[crtc]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK))
 		return;
 
 	/* depending on when we hit vblank, we may be close to active; if so,
@@ -179,7 +191,7 @@ static u32 dce_v6_0_vblank_get_counter(s
 	if (crtc >= adev->mode_info.num_crtc)
 		return 0;
 	else
-		return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
+		return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
 }
 
 static void dce_v6_0_pageflip_interrupt_init(struct amdgpu_device *adev)
@@ -219,16 +231,16 @@ static void dce_v6_0_page_flip(struct am
 	struct amdgpu_crtc *amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
 
 	/* flip at hsync for async, default is vsync */
-	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, async ?
-	       EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, async ?
+	       GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK : 0);
 	/* update the scanout addresses */
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(crtc_base));
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
 	       (u32)crtc_base);
 
 	/* post the write */
-	RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
+	RREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset);
 }
 
 static int dce_v6_0_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
@@ -236,8 +248,8 @@ static int dce_v6_0_crtc_get_scanoutpos(
 {
 	if ((crtc < 0) || (crtc >= adev->mode_info.num_crtc))
 		return -EINVAL;
-	*vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + crtc_offsets[crtc]);
-	*position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
+	*vbl = RREG32(mmCRTC_V_BLANK_START_END + crtc_offsets[crtc]);
+	*position = RREG32(mmCRTC_STATUS_POSITION + crtc_offsets[crtc]);
 
 	return 0;
 
@@ -257,34 +269,11 @@ static bool dce_v6_0_hpd_sense(struct am
 {
 	bool connected = false;
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case AMDGPU_HPD_2:
-		if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case AMDGPU_HPD_3:
-		if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case AMDGPU_HPD_4:
-		if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case AMDGPU_HPD_5:
-		if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	case AMDGPU_HPD_6:
-		if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE)
-			connected = true;
-		break;
-	default:
-		break;
-	}
+	if (hpd >= adev->mode_info.num_hpd)
+		return connected;
+
+	if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) & DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
+		connected = true;
 
 	return connected;
 }
@@ -303,58 +292,15 @@ static void dce_v6_0_hpd_set_polarity(st
 	u32 tmp;
 	bool connected = dce_v6_0_hpd_sense(adev, hpd);
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		tmp = RREG32(DC_HPD1_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD1_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_2:
-		tmp = RREG32(DC_HPD2_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD2_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_3:
-		tmp = RREG32(DC_HPD3_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD3_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_4:
-		tmp = RREG32(DC_HPD4_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD4_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_5:
-		tmp = RREG32(DC_HPD5_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD5_INT_CONTROL, tmp);
-			break;
-	case AMDGPU_HPD_6:
-		tmp = RREG32(DC_HPD6_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPDx_INT_POLARITY;
-		else
-			tmp |= DC_HPDx_INT_POLARITY;
-		WREG32(DC_HPD6_INT_CONTROL, tmp);
-		break;
-	default:
-		break;
-	}
+	if (hpd >= adev->mode_info.num_hpd)
+		return;
+
+	tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
+	if (connected)
+		tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+	else
+		tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+	WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
 }
 
 /**
@@ -369,34 +315,17 @@ static void dce_v6_0_hpd_init(struct amd
 {
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
-	u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) |
-		DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN;
+	u32 tmp;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			WREG32(DC_HPD1_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_2:
-			WREG32(DC_HPD2_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_3:
-			WREG32(DC_HPD3_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_4:
-			WREG32(DC_HPD4_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_5:
-			WREG32(DC_HPD5_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_6:
-			WREG32(DC_HPD6_CONTROL, tmp);
-			break;
-		default:
-			break;
-		}
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+			continue;
+
+		tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+		tmp |= DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+		WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
 		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -405,34 +334,9 @@ static void dce_v6_0_hpd_init(struct amd
 			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
 			 * also avoid interrupt storms during dpms.
 			 */
-			u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
-
-			switch (amdgpu_connector->hpd.hpd) {
-			case AMDGPU_HPD_1:
-				dc_hpd_int_cntl_reg = DC_HPD1_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_2:
-				dc_hpd_int_cntl_reg = DC_HPD2_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_3:
-				dc_hpd_int_cntl_reg = DC_HPD3_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_4:
-				dc_hpd_int_cntl_reg = DC_HPD4_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_5:
-				dc_hpd_int_cntl_reg = DC_HPD5_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_6:
-				dc_hpd_int_cntl_reg = DC_HPD6_INT_CONTROL;
-				break;
-			default:
-				continue;
-			}
-
-			dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
-			dc_hpd_int_cntl &= ~DC_HPDx_INT_EN;
-			WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+			tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+			tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
+			WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 			continue;
 		}
 
@@ -454,46 +358,25 @@ static void dce_v6_0_hpd_fini(struct amd
 {
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
+	u32 tmp;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			WREG32(DC_HPD1_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_2:
-			WREG32(DC_HPD2_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_3:
-			WREG32(DC_HPD3_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_4:
-			WREG32(DC_HPD4_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_5:
-			WREG32(DC_HPD5_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_6:
-			WREG32(DC_HPD6_CONTROL, 0);
-			break;
-		default:
-			break;
-		}
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+			continue;
+
+		tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+		tmp &= ~DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+		WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0);
+
 		amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
 	}
 }
 
 static u32 dce_v6_0_hpd_get_gpio_reg(struct amdgpu_device *adev)
 {
-	return SI_DC_GPIO_HPD_A;
-}
-
-static bool dce_v6_0_is_display_hung(struct amdgpu_device *adev)
-{
-	DRM_INFO("xxxx: dce_v6_0_is_display_hung ----no imp!!!!!\n");
-
-	return true;
+	return mmDC_GPIO_HPD_A;
 }
 
 static u32 evergreen_get_vblank_counter(struct amdgpu_device* adev, int crtc)
@@ -501,7 +384,7 @@ static u32 evergreen_get_vblank_counter(
 	if (crtc >= adev->mode_info.num_crtc)
 		return 0;
 	else
-		return RREG32(CRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
+		return RREG32(mmCRTC_STATUS_FRAME_COUNT + crtc_offsets[crtc]);
 }
 
 static void dce_v6_0_stop_mc_access(struct amdgpu_device *adev,
@@ -510,25 +393,25 @@ static void dce_v6_0_stop_mc_access(stru
 	u32 crtc_enabled, tmp, frame_count;
 	int i, j;
 
-	save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
-	save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
+	save->vga_render_control = RREG32(mmVGA_RENDER_CONTROL);
+	save->vga_hdp_control = RREG32(mmVGA_HDP_CONTROL);
 
 	/* disable VGA render */
-	WREG32(VGA_RENDER_CONTROL, 0);
+	WREG32(mmVGA_RENDER_CONTROL, 0);
 
 	/* blank the display controllers */
 	for (i = 0; i < adev->mode_info.num_crtc; i++) {
-		crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN;
+		crtc_enabled = RREG32(mmCRTC_CONTROL + crtc_offsets[i]) & CRTC_CONTROL__CRTC_MASTER_EN_MASK;
 		if (crtc_enabled) {
 			save->crtc_enabled[i] = true;
-			tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
+			tmp = RREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i]);
 
-			if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) {
+			if (!(tmp & CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK)) {
 				dce_v6_0_vblank_wait(adev, i);
-				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
-				tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
-				WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
-				WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+				tmp |= CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK;
+				WREG32(mmCRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
 			}
 			/* wait for the next frame */
 			frame_count = evergreen_get_vblank_counter(adev, i);
@@ -539,11 +422,11 @@ static void dce_v6_0_stop_mc_access(stru
 			}
 
 			/* XXX this is a hack to avoid strange behavior with EFI on certain systems */
-			WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
-			tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
-			tmp &= ~EVERGREEN_CRTC_MASTER_EN;
-			WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp);
-			WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+			tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
+			tmp &= ~CRTC_CONTROL__CRTC_MASTER_EN_MASK;
+			WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
+			WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
 			save->crtc_enabled[i] = false;
 			/* ***** */
 		} else {
@@ -560,41 +443,40 @@ static void dce_v6_0_resume_mc_access(st
 
 	/* update crtc base addresses */
 	for (i = 0; i < adev->mode_info.num_crtc; i++) {
-		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
 		       upper_32_bits(adev->mc.vram_start));
-		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
+		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i],
 		       upper_32_bits(adev->mc.vram_start));
-		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
+		WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i],
 		       (u32)adev->mc.vram_start);
-		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
+		WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i],
 		       (u32)adev->mc.vram_start);
 	}
 
-	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start));
-	WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)adev->mc.vram_start);
+	WREG32(mmVGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(adev->mc.vram_start));
+	WREG32(mmVGA_MEMORY_BASE_ADDRESS, (u32)adev->mc.vram_start);
 
 	/* unlock regs and wait for update */
 	for (i = 0; i < adev->mode_info.num_crtc; i++) {
 		if (save->crtc_enabled[i]) {
-			tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]);
-			if ((tmp & 0x7) != 3) {
+			tmp = RREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i]);
+			if ((tmp & 0x7) != 0) {
 				tmp &= ~0x7;
-				tmp |= 0x3;
-				WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp);
+				WREG32(mmMASTER_UPDATE_MODE + crtc_offsets[i], tmp);
 			}
-			tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
-			if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) {
-				tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK;
-				WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp);
+			tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+			if (tmp & GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK) {
+				tmp &= ~GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK;
+				WREG32(mmGRPH_UPDATE + crtc_offsets[i], tmp);
 			}
-			tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]);
+			tmp = RREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i]);
 			if (tmp & 1) {
 				tmp &= ~1;
-				WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
+				WREG32(mmMASTER_UPDATE_LOCK + crtc_offsets[i], tmp);
 			}
 			for (j = 0; j < adev->usec_timeout; j++) {
-				tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]);
-				if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0)
+				tmp = RREG32(mmGRPH_UPDATE + crtc_offsets[i]);
+				if ((tmp & GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK) == 0)
 					break;
 				udelay(1);
 			}
@@ -602,19 +484,62 @@ static void dce_v6_0_resume_mc_access(st
 	}
 
 	/* Unlock vga access */
-	WREG32(VGA_HDP_CONTROL, save->vga_hdp_control);
+	WREG32(mmVGA_HDP_CONTROL, save->vga_hdp_control);
 	mdelay(1);
-	WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
+	WREG32(mmVGA_RENDER_CONTROL, save->vga_render_control);
 
 }
 
 static void dce_v6_0_set_vga_render_state(struct amdgpu_device *adev,
 					  bool render)
 {
-	if (!render) 
-		WREG32(R_000300_VGA_RENDER_CONTROL,
-			RREG32(R_000300_VGA_RENDER_CONTROL) & C_000300_VGA_VSTATUS_CNTL);
+	if (!render)
+		WREG32(mmVGA_RENDER_CONTROL,
+			RREG32(mmVGA_RENDER_CONTROL) & VGA_VSTATUS_CNTL);
+
+}
+
+static int dce_v6_0_get_num_crtc(struct amdgpu_device *adev)
+{
+	int num_crtc = 0;
 
+	switch (adev->asic_type) {
+	case CHIP_TAHITI:
+	case CHIP_PITCAIRN:
+	case CHIP_VERDE:
+		num_crtc = 6;
+		break;
+	case CHIP_OLAND:
+		num_crtc = 2;
+		break;
+	default:
+		num_crtc = 0;
+	}
+	return num_crtc;
+}
+
+void dce_v6_0_disable_dce(struct amdgpu_device *adev)
+{
+	/*Disable VGA render and enabled crtc, if has DCE engine*/
+	if (amdgpu_atombios_has_dce_engine_info(adev)) {
+		u32 tmp;
+		int crtc_enabled, i;
+
+		dce_v6_0_set_vga_render_state(adev, false);
+
+		/*Disable crtc*/
+		for (i = 0; i < dce_v6_0_get_num_crtc(adev); i++) {
+			crtc_enabled = RREG32(mmCRTC_CONTROL + crtc_offsets[i]) &
+				CRTC_CONTROL__CRTC_MASTER_EN_MASK;
+			if (crtc_enabled) {
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 1);
+				tmp = RREG32(mmCRTC_CONTROL + crtc_offsets[i]);
+				tmp &= ~CRTC_CONTROL__CRTC_MASTER_EN_MASK;
+				WREG32(mmCRTC_CONTROL + crtc_offsets[i], tmp);
+				WREG32(mmCRTC_UPDATE_LOCK + crtc_offsets[i], 0);
+			}
+		}
+	}
 }
 
 static void dce_v6_0_program_fmt(struct drm_encoder *encoder)
@@ -647,19 +572,23 @@ static void dce_v6_0_program_fmt(struct
 	case 6:
 		if (dither == AMDGPU_FMT_DITHER_ENABLE)
 			/* XXX sort out optimal dither settings */
-			tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
-				FMT_SPATIAL_DITHER_EN);
+			tmp |= (FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE_MASK |
+				FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE_MASK |
+				FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN_MASK);
 		else
-			tmp |= FMT_TRUNCATE_EN;
+			tmp |= FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN_MASK;
 		break;
 	case 8:
 		if (dither == AMDGPU_FMT_DITHER_ENABLE)
 			/* XXX sort out optimal dither settings */
-			tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
-				FMT_RGB_RANDOM_ENABLE |
-				FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH);
+			tmp |= (FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE_MASK |
+				FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE_MASK |
+				FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE_MASK |
+				FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN_MASK |
+				FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH_MASK);
 		else
-			tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH);
+			tmp |= (FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN_MASK |
+				FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH_MASK);
 		break;
 	case 10:
 	default:
@@ -667,7 +596,7 @@ static void dce_v6_0_program_fmt(struct
 		break;
 	}
 
-	WREG32(FMT_BIT_DEPTH_CONTROL + amdgpu_crtc->crtc_offset, tmp);
+	WREG32(mmFMT_BIT_DEPTH_CONTROL + amdgpu_crtc->crtc_offset, tmp);
 }
 
 /**
@@ -681,7 +610,7 @@ static void dce_v6_0_program_fmt(struct
  */
 static u32 si_get_number_of_dram_channels(struct amdgpu_device *adev)
 {
-	u32 tmp = RREG32(MC_SHARED_CHMAP);
+	u32 tmp = RREG32(mmMC_SHARED_CHMAP);
 
 	switch ((tmp & MC_SHARED_CHMAP__NOOFCHAN_MASK) >> MC_SHARED_CHMAP__NOOFCHAN__SHIFT) {
 	case 0:
@@ -1178,28 +1107,28 @@ static void dce_v6_0_program_watermarks(
 	}
 
 	/* select wm A */
-	arb_control3 = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
+	arb_control3 = RREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
 	tmp = arb_control3;
 	tmp &= ~LATENCY_WATERMARK_MASK(3);
 	tmp |= LATENCY_WATERMARK_MASK(1);
-	WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
-	WREG32(DPG_PIPE_LATENCY_CONTROL + amdgpu_crtc->crtc_offset,
-	       (LATENCY_LOW_WATERMARK(latency_watermark_a) |
-		LATENCY_HIGH_WATERMARK(line_time)));
+	WREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
+	WREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((latency_watermark_a << DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT)  |
+		(line_time << DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT)));
 	/* select wm B */
-	tmp = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
+	tmp = RREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset);
 	tmp &= ~LATENCY_WATERMARK_MASK(3);
 	tmp |= LATENCY_WATERMARK_MASK(2);
-	WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
-	WREG32(DPG_PIPE_LATENCY_CONTROL + amdgpu_crtc->crtc_offset,
-	       (LATENCY_LOW_WATERMARK(latency_watermark_b) |
-		LATENCY_HIGH_WATERMARK(line_time)));
+	WREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, tmp);
+	WREG32(mmDPG_PIPE_URGENCY_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((latency_watermark_b << DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT) |
+		(line_time << DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT)));
 	/* restore original selection */
-	WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, arb_control3);
+	WREG32(mmDPG_PIPE_ARBITRATION_CONTROL3 + amdgpu_crtc->crtc_offset, arb_control3);
 
 	/* write the priority marks */
-	WREG32(PRIORITY_A_CNT + amdgpu_crtc->crtc_offset, priority_a_cnt);
-	WREG32(PRIORITY_B_CNT + amdgpu_crtc->crtc_offset, priority_b_cnt);
+	WREG32(mmPRIORITY_A_CNT + amdgpu_crtc->crtc_offset, priority_a_cnt);
+	WREG32(mmPRIORITY_B_CNT + amdgpu_crtc->crtc_offset, priority_b_cnt);
 
 	/* save values for DPM */
 	amdgpu_crtc->line_time = line_time;
@@ -1217,7 +1146,7 @@ static u32 dce_v6_0_line_buffer_adjust(s
 	/*
 	 * Line Buffer Setup
 	 * There are 3 line buffers, each one shared by 2 display controllers.
-	 * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
+	 * mmDC_LB_MEMORY_SPLIT controls how that line buffer is shared between
 	 * the display controllers.  The paritioning is done via one of four
 	 * preset allocations specified in bits 21:20:
 	 *  0 - half lb
@@ -1240,14 +1169,14 @@ static u32 dce_v6_0_line_buffer_adjust(s
 		buffer_alloc = 0;
 	}
 
-	WREG32(DC_LB_MEMORY_SPLIT + amdgpu_crtc->crtc_offset,
+	WREG32(mmDC_LB_MEMORY_SPLIT + amdgpu_crtc->crtc_offset,
 	       DC_LB_MEMORY_CONFIG(tmp));
 
-	WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
-	       DMIF_BUFFERS_ALLOCATED(buffer_alloc));
+	WREG32(mmPIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
+	       (buffer_alloc << PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT));
 	for (i = 0; i < adev->usec_timeout; i++) {
-		if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
-		    DMIF_BUFFERS_ALLOCATED_COMPLETED)
+		if (RREG32(mmPIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
+		    PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK)
 			break;
 		udelay(1);
 	}
@@ -1489,12 +1418,12 @@ static void dce_v6_0_afmt_fini(struct am
 
 static const u32 vga_control_regs[6] =
 {
-	AVIVO_D1VGA_CONTROL,
-	AVIVO_D2VGA_CONTROL,
-	EVERGREEN_D3VGA_CONTROL,
-	EVERGREEN_D4VGA_CONTROL,
-	EVERGREEN_D5VGA_CONTROL,
-	EVERGREEN_D6VGA_CONTROL,
+	mmD1VGA_CONTROL,
+	mmD2VGA_CONTROL,
+	mmD3VGA_CONTROL,
+	mmD4VGA_CONTROL,
+	mmD5VGA_CONTROL,
+	mmD6VGA_CONTROL,
 };
 
 static void dce_v6_0_vga_enable(struct drm_crtc *crtc, bool enable)
@@ -1514,7 +1443,7 @@ static void dce_v6_0_grph_enable(struct
 	struct drm_device *dev = crtc->dev;
 	struct amdgpu_device *adev = dev->dev_private;
 
-	WREG32(EVERGREEN_GRPH_ENABLE + amdgpu_crtc->crtc_offset, enable ? 1 : 0);
+	WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, enable ? 1 : 0);
 }
 
 static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
@@ -1530,10 +1459,11 @@ static int dce_v6_0_crtc_do_set_base(str
 	struct amdgpu_bo *abo;
 	uint64_t fb_location, tiling_flags;
 	uint32_t fb_format, fb_pitch_pixels, pipe_config;
-	u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
+	u32 fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_NONE);
 	u32 viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
+	struct drm_format_name_buf format_name;
 
 	/* no fb bound */
 	if (!atomic && !crtc->primary->fb) {
@@ -1573,71 +1503,71 @@ static int dce_v6_0_crtc_do_set_base(str
 
 	switch (target_fb->pixel_format) {
 	case DRM_FORMAT_C8:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_8BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_INDEXED));
 		break;
 	case DRM_FORMAT_XRGB4444:
 	case DRM_FORMAT_ARGB4444:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB4444));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_ARGB4444));
 #ifdef __BIG_ENDIAN
-		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+		fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
 #endif
 		break;
 	case DRM_FORMAT_XRGB1555:
 	case DRM_FORMAT_ARGB1555:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB1555));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_ARGB1555));
 #ifdef __BIG_ENDIAN
-		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+		fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
 #endif
 		break;
 	case DRM_FORMAT_BGRX5551:
 	case DRM_FORMAT_BGRA5551:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA5551));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_BGRA5551));
 #ifdef __BIG_ENDIAN
-		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+		fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
 #endif
 		break;
 	case DRM_FORMAT_RGB565:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_16BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_ARGB565));
 #ifdef __BIG_ENDIAN
-		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16);
+		fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN16);
 #endif
 		break;
 	case DRM_FORMAT_XRGB8888:
 	case DRM_FORMAT_ARGB8888:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_32BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_ARGB8888));
 #ifdef __BIG_ENDIAN
-		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+		fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN32);
 #endif
 		break;
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_ARGB2101010:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB2101010));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_32BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_ARGB2101010));
 #ifdef __BIG_ENDIAN
-		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+		fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN32);
 #endif
 		/* Greater 8 bpc fb needs to bypass hw-lut to retain precision */
 		bypass_lut = true;
 		break;
 	case DRM_FORMAT_BGRX1010102:
 	case DRM_FORMAT_BGRA1010102:
-		fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) |
-			     EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_BGRA1010102));
+		fb_format = (GRPH_DEPTH(GRPH_DEPTH_32BPP) |
+			     GRPH_FORMAT(GRPH_FORMAT_BGRA1010102));
 #ifdef __BIG_ENDIAN
-		fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32);
+		fb_swap = GRPH_ENDIAN_SWAP(GRPH_ENDIAN_8IN32);
 #endif
 		/* Greater 8 bpc fb needs to bypass hw-lut to retain precision */
 		bypass_lut = true;
 		break;
 	default:
 		DRM_ERROR("Unsupported screen format %s\n",
-			  drm_get_format_name(target_fb->pixel_format));
+		          drm_get_format_name(target_fb->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
@@ -1650,75 +1580,75 @@ static int dce_v6_0_crtc_do_set_base(str
 		tile_split = AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT);
 		num_banks = AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
 
-		fb_format |= EVERGREEN_GRPH_NUM_BANKS(num_banks);
-		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_2D_TILED_THIN1);
-		fb_format |= EVERGREEN_GRPH_TILE_SPLIT(tile_split);
-		fb_format |= EVERGREEN_GRPH_BANK_WIDTH(bankw);
-		fb_format |= EVERGREEN_GRPH_BANK_HEIGHT(bankh);
-		fb_format |= EVERGREEN_GRPH_MACRO_TILE_ASPECT(mtaspect);
+		fb_format |= GRPH_NUM_BANKS(num_banks);
+		fb_format |= GRPH_ARRAY_MODE(GRPH_ARRAY_2D_TILED_THIN1);
+		fb_format |= GRPH_TILE_SPLIT(tile_split);
+		fb_format |= GRPH_BANK_WIDTH(bankw);
+		fb_format |= GRPH_BANK_HEIGHT(bankh);
+		fb_format |= GRPH_MACRO_TILE_ASPECT(mtaspect);
 	} else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == ARRAY_1D_TILED_THIN1) {
-		fb_format |= EVERGREEN_GRPH_ARRAY_MODE(EVERGREEN_GRPH_ARRAY_1D_TILED_THIN1);
+		fb_format |= GRPH_ARRAY_MODE(GRPH_ARRAY_1D_TILED_THIN1);
 	}
 
 	pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
-	fb_format |= SI_GRPH_PIPE_CONFIG(pipe_config);
+	fb_format |= GRPH_PIPE_CONFIG(pipe_config);
 
 	dce_v6_0_vga_enable(crtc, false);
 
 	/* Make sure surface address is updated at vertical blank rather than
 	 * horizontal blank
 	 */
-	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmGRPH_FLIP_CONTROL + amdgpu_crtc->crtc_offset, 0);
 
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+	WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(fb_location));
-	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
-	       (u32)fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
-	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
-	       (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK);
-	WREG32(EVERGREEN_GRPH_CONTROL + amdgpu_crtc->crtc_offset, fb_format);
-	WREG32(EVERGREEN_GRPH_SWAP_CONTROL + amdgpu_crtc->crtc_offset, fb_swap);
+	WREG32(mmGRPH_PRIMARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+	       (u32)fb_location & GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS_MASK);
+	WREG32(mmGRPH_SECONDARY_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+	       (u32) fb_location & GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS_MASK);
+	WREG32(mmGRPH_CONTROL + amdgpu_crtc->crtc_offset, fb_format);
+	WREG32(mmGRPH_SWAP_CNTL + amdgpu_crtc->crtc_offset, fb_swap);
 
 	/*
 	 * The LUT only has 256 slots for indexing by a 8 bpc fb. Bypass the LUT
 	 * for > 8 bpc scanout to avoid truncation of fb indices to 8 msb's, to
 	 * retain the full precision throughout the pipeline.
 	 */
-	WREG32_P(EVERGREEN_GRPH_LUT_10BIT_BYPASS_CONTROL + amdgpu_crtc->crtc_offset,
-		 (bypass_lut ? EVERGREEN_LUT_10BIT_BYPASS_EN : 0),
-		 ~EVERGREEN_LUT_10BIT_BYPASS_EN);
+	WREG32_P(mmGRPH_LUT_10BIT_BYPASS + amdgpu_crtc->crtc_offset,
+		 (bypass_lut ? GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN_MASK : 0),
+		 ~GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN_MASK);
 
 	if (bypass_lut)
 		DRM_DEBUG_KMS("Bypassing hardware LUT due to 10 bit fb scanout.\n");
 
-	WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + amdgpu_crtc->crtc_offset, 0);
-	WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + amdgpu_crtc->crtc_offset, 0);
-	WREG32(EVERGREEN_GRPH_X_START + amdgpu_crtc->crtc_offset, 0);
-	WREG32(EVERGREEN_GRPH_Y_START + amdgpu_crtc->crtc_offset, 0);
-	WREG32(EVERGREEN_GRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
-	WREG32(EVERGREEN_GRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
+	WREG32(mmGRPH_SURFACE_OFFSET_X + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmGRPH_SURFACE_OFFSET_Y + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmGRPH_X_START + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmGRPH_Y_START + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmGRPH_X_END + amdgpu_crtc->crtc_offset, target_fb->width);
+	WREG32(mmGRPH_Y_END + amdgpu_crtc->crtc_offset, target_fb->height);
 
 	fb_pitch_pixels = target_fb->pitches[0] / (target_fb->bits_per_pixel / 8);
-	WREG32(EVERGREEN_GRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
+	WREG32(mmGRPH_PITCH + amdgpu_crtc->crtc_offset, fb_pitch_pixels);
 
 	dce_v6_0_grph_enable(crtc, true);
 
-	WREG32(EVERGREEN_DESKTOP_HEIGHT + amdgpu_crtc->crtc_offset,
+	WREG32(mmDESKTOP_HEIGHT + amdgpu_crtc->crtc_offset,
 		       target_fb->height);
 	x &= ~3;
 	y &= ~1;
-	WREG32(EVERGREEN_VIEWPORT_START + amdgpu_crtc->crtc_offset,
+	WREG32(mmVIEWPORT_START + amdgpu_crtc->crtc_offset,
 	       (x << 16) | y);
 	viewport_w = crtc->mode.hdisplay;
 	viewport_h = (crtc->mode.vdisplay + 1) & ~1;
 
-	WREG32(EVERGREEN_VIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
+	WREG32(mmVIEWPORT_SIZE + amdgpu_crtc->crtc_offset,
 	       (viewport_w << 16) | viewport_h);
 
 	/* set pageflip to happen anywhere in vblank interval */
-	WREG32(EVERGREEN_MASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
 
 	if (!atomic && fb && fb != crtc->primary->fb) {
 		amdgpu_fb = to_amdgpu_framebuffer(fb);
@@ -1745,10 +1675,10 @@ static void dce_v6_0_set_interleave(stru
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-		WREG32(EVERGREEN_DATA_FORMAT + amdgpu_crtc->crtc_offset,
-		       EVERGREEN_INTERLEAVE_EN);
+		WREG32(mmDATA_FORMAT + amdgpu_crtc->crtc_offset,
+		       INTERLEAVE_EN);
 	else
-		WREG32(EVERGREEN_DATA_FORMAT + amdgpu_crtc->crtc_offset, 0);
+		WREG32(mmDATA_FORMAT + amdgpu_crtc->crtc_offset, 0);
 }
 
 static void dce_v6_0_crtc_load_lut(struct drm_crtc *crtc)
@@ -1761,54 +1691,52 @@ static void dce_v6_0_crtc_load_lut(struc
 
 	DRM_DEBUG_KMS("%d\n", amdgpu_crtc->crtc_id);
 
-	WREG32(NI_INPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
-	       (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) |
-		NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS)));
-	WREG32(NI_PRESCALE_GRPH_CONTROL + amdgpu_crtc->crtc_offset,
-	       NI_GRPH_PRESCALE_BYPASS);
-	WREG32(NI_PRESCALE_OVL_CONTROL + amdgpu_crtc->crtc_offset,
-	       NI_OVL_PRESCALE_BYPASS);
-	WREG32(NI_INPUT_GAMMA_CONTROL + amdgpu_crtc->crtc_offset,
-	       (NI_GRPH_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT) |
-		NI_OVL_INPUT_GAMMA_MODE(NI_INPUT_GAMMA_USE_LUT)));
-
-
+	WREG32(mmINPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((0 << INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE__SHIFT) |
+		(0 << INPUT_CSC_CONTROL__INPUT_CSC_OVL_MODE__SHIFT)));
+	WREG32(mmPRESCALE_GRPH_CONTROL + amdgpu_crtc->crtc_offset,
+	       PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS_MASK);
+	WREG32(mmPRESCALE_OVL_CONTROL + amdgpu_crtc->crtc_offset,
+	       PRESCALE_OVL_CONTROL__OVL_PRESCALE_BYPASS_MASK);
+	WREG32(mmINPUT_GAMMA_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((0 << INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE__SHIFT) |
+		(0 << INPUT_GAMMA_CONTROL__OVL_INPUT_GAMMA_MODE__SHIFT)));
 
-	WREG32(EVERGREEN_DC_LUT_CONTROL + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmDC_LUT_CONTROL + amdgpu_crtc->crtc_offset, 0);
 
-	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0);
-	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0);
-	WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_RED + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmDC_LUT_BLACK_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmDC_LUT_BLACK_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmDC_LUT_BLACK_OFFSET_RED + amdgpu_crtc->crtc_offset, 0);
 
-	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0xffff);
-	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0xffff);
-	WREG32(EVERGREEN_DC_LUT_WHITE_OFFSET_RED + amdgpu_crtc->crtc_offset, 0xffff);
+	WREG32(mmDC_LUT_WHITE_OFFSET_BLUE + amdgpu_crtc->crtc_offset, 0xffff);
+	WREG32(mmDC_LUT_WHITE_OFFSET_GREEN + amdgpu_crtc->crtc_offset, 0xffff);
+	WREG32(mmDC_LUT_WHITE_OFFSET_RED + amdgpu_crtc->crtc_offset, 0xffff);
 
-	WREG32(EVERGREEN_DC_LUT_RW_MODE + amdgpu_crtc->crtc_offset, 0);
-	WREG32(EVERGREEN_DC_LUT_WRITE_EN_MASK + amdgpu_crtc->crtc_offset, 0x00000007);
+	WREG32(mmDC_LUT_RW_MODE + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmDC_LUT_WRITE_EN_MASK + amdgpu_crtc->crtc_offset, 0x00000007);
 
-	WREG32(EVERGREEN_DC_LUT_RW_INDEX + amdgpu_crtc->crtc_offset, 0);
+	WREG32(mmDC_LUT_RW_INDEX + amdgpu_crtc->crtc_offset, 0);
 	for (i = 0; i < 256; i++) {
-		WREG32(EVERGREEN_DC_LUT_30_COLOR + amdgpu_crtc->crtc_offset,
+		WREG32(mmDC_LUT_30_COLOR + amdgpu_crtc->crtc_offset,
 		       (amdgpu_crtc->lut_r[i] << 20) |
 		       (amdgpu_crtc->lut_g[i] << 10) |
 		       (amdgpu_crtc->lut_b[i] << 0));
 	}
 
-	WREG32(NI_DEGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
-	       (NI_GRPH_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
-		NI_OVL_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
-		NI_ICON_DEGAMMA_MODE(NI_DEGAMMA_BYPASS) |
-		NI_CURSOR_DEGAMMA_MODE(NI_DEGAMMA_BYPASS)));
-	WREG32(NI_GAMUT_REMAP_CONTROL + amdgpu_crtc->crtc_offset,
-	       (NI_GRPH_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS) |
-		NI_OVL_GAMUT_REMAP_MODE(NI_GAMUT_REMAP_BYPASS)));
-	WREG32(NI_REGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
-	       (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
-		NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
-	WREG32(NI_OUTPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
-	       (NI_OUTPUT_CSC_GRPH_MODE(0) |
-		NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
+	WREG32(mmDEGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((0 << DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE__SHIFT) |
+		(0 << DEGAMMA_CONTROL__OVL_DEGAMMA_MODE__SHIFT) |
+		ICON_DEGAMMA_MODE(0) |
+		(0 << DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE__SHIFT)));
+	WREG32(mmGAMUT_REMAP_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((0 << GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE__SHIFT) |
+		(0 << GAMUT_REMAP_CONTROL__OVL_GAMUT_REMAP_MODE__SHIFT)));
+	WREG32(mmREGAMMA_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((0 << REGAMMA_CONTROL__GRPH_REGAMMA_MODE__SHIFT) |
+		(0 << REGAMMA_CONTROL__OVL_REGAMMA_MODE__SHIFT)));
+	WREG32(mmOUTPUT_CSC_CONTROL + amdgpu_crtc->crtc_offset,
+	       ((0 << OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE__SHIFT) |
+		(0 << OUTPUT_CSC_CONTROL__OUTPUT_CSC_OVL_MODE__SHIFT)));
 	/* XXX match this to the depth of the crtc fmt block, move to modeset? */
 	WREG32(0x1a50 + amdgpu_crtc->crtc_offset, 0);
 
@@ -1887,12 +1815,12 @@ static void dce_v6_0_lock_cursor(struct
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	uint32_t cur_lock;
 
-	cur_lock = RREG32(EVERGREEN_CUR_UPDATE + amdgpu_crtc->crtc_offset);
+	cur_lock = RREG32(mmCUR_UPDATE + amdgpu_crtc->crtc_offset);
 	if (lock)
-		cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
+		cur_lock |= CUR_UPDATE__CURSOR_UPDATE_LOCK_MASK;
 	else
-		cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
-	WREG32(EVERGREEN_CUR_UPDATE + amdgpu_crtc->crtc_offset, cur_lock);
+		cur_lock &= ~CUR_UPDATE__CURSOR_UPDATE_LOCK_MASK;
+	WREG32(mmCUR_UPDATE + amdgpu_crtc->crtc_offset, cur_lock);
 }
 
 static void dce_v6_0_hide_cursor(struct drm_crtc *crtc)
@@ -1900,9 +1828,9 @@ static void dce_v6_0_hide_cursor(struct
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	struct amdgpu_device *adev = crtc->dev->dev_private;
 
-	WREG32_IDX(EVERGREEN_CUR_CONTROL + amdgpu_crtc->crtc_offset,
-		   EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
-		   EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
+	WREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset,
+		   (CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) |
+		   (CURSOR_URGENT_1_2 << CUR_CONTROL__CURSOR_URGENT_CONTROL__SHIFT));
 
 
 }
@@ -1912,15 +1840,15 @@ static void dce_v6_0_show_cursor(struct
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	struct amdgpu_device *adev = crtc->dev->dev_private;
 
-	WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
+	WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset,
 	       upper_32_bits(amdgpu_crtc->cursor_addr));
-	WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
+	WREG32(mmCUR_SURFACE_ADDRESS + amdgpu_crtc->crtc_offset,
 	       lower_32_bits(amdgpu_crtc->cursor_addr));
 
-	WREG32_IDX(EVERGREEN_CUR_CONTROL + amdgpu_crtc->crtc_offset,
-		   EVERGREEN_CURSOR_EN |
-		   EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
-		   EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
+	WREG32_IDX(mmCUR_CONTROL + amdgpu_crtc->crtc_offset,
+		   CUR_CONTROL__CURSOR_EN_MASK |
+		   (CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) |
+		   (CURSOR_URGENT_1_2 << CUR_CONTROL__CURSOR_URGENT_CONTROL__SHIFT));
 
 }
 
@@ -1933,6 +1861,9 @@ static int dce_v6_0_cursor_move_locked(s
 
 	int w = amdgpu_crtc->cursor_width;
 
+	amdgpu_crtc->cursor_x = x;
+	amdgpu_crtc->cursor_y = y;
+
 	/* avivo cursor are offset into the total surface */
 	x += crtc->x;
 	y += crtc->y;
@@ -1947,13 +1878,11 @@ static int dce_v6_0_cursor_move_locked(s
 		y = 0;
 	}
 
-	WREG32(EVERGREEN_CUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
-	WREG32(EVERGREEN_CUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
-	WREG32(EVERGREEN_CUR_SIZE + amdgpu_crtc->crtc_offset,
+	WREG32(mmCUR_POSITION + amdgpu_crtc->crtc_offset, (x << 16) | y);
+	WREG32(mmCUR_HOT_SPOT + amdgpu_crtc->crtc_offset, (xorigin << 16) | yorigin);
+	WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
 	       ((w - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
-	amdgpu_crtc->cursor_x = x;
-	amdgpu_crtc->cursor_y = y;
 	return 0;
 }
 
@@ -2016,12 +1945,11 @@ static int dce_v6_0_crtc_cursor_set2(str
 		return ret;
 	}
 
-	amdgpu_crtc->cursor_width = width;
-	amdgpu_crtc->cursor_height = height;
-
 	dce_v6_0_lock_cursor(crtc, true);
 
-	if (hot_x != amdgpu_crtc->cursor_hot_x ||
+	if (width != amdgpu_crtc->cursor_width ||
+	    height != amdgpu_crtc->cursor_height ||
+	    hot_x != amdgpu_crtc->cursor_hot_x ||
 	    hot_y != amdgpu_crtc->cursor_hot_y) {
 		int x, y;
 
@@ -2030,6 +1958,8 @@ static int dce_v6_0_crtc_cursor_set2(str
 
 		dce_v6_0_cursor_move_locked(crtc, x, y);
 
+		amdgpu_crtc->cursor_width = width;
+		amdgpu_crtc->cursor_height = height;
 		amdgpu_crtc->cursor_hot_x = hot_x;
 		amdgpu_crtc->cursor_hot_y = hot_y;
 	}
@@ -2117,13 +2047,13 @@ static void dce_v6_0_crtc_dpms(struct dr
 		type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
 		amdgpu_irq_update(adev, &adev->crtc_irq, type);
 		amdgpu_irq_update(adev, &adev->pageflip_irq, type);
-		drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
+		drm_crtc_vblank_on(crtc);
 		dce_v6_0_crtc_load_lut(crtc);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		drm_vblank_pre_modeset(dev, amdgpu_crtc->crtc_id);
+		drm_crtc_vblank_off(crtc);
 		if (amdgpu_crtc->enabled)
 			amdgpu_atombios_crtc_blank(crtc, ATOM_ENABLE);
 		amdgpu_atombios_crtc_enable(crtc, ATOM_DISABLE);
@@ -2338,21 +2268,20 @@ static int dce_v6_0_early_init(void *han
 	dce_v6_0_set_display_funcs(adev);
 	dce_v6_0_set_irq_funcs(adev);
 
+	adev->mode_info.num_crtc = dce_v6_0_get_num_crtc(adev);
+
 	switch (adev->asic_type) {
 	case CHIP_TAHITI:
 	case CHIP_PITCAIRN:
 	case CHIP_VERDE:
-		adev->mode_info.num_crtc = 6;
 		adev->mode_info.num_hpd = 6;
 		adev->mode_info.num_dig = 6;
 		break;
 	case CHIP_OLAND:
-		adev->mode_info.num_crtc = 2;
 		adev->mode_info.num_hpd = 2;
 		adev->mode_info.num_dig = 2;
 		break;
 	default:
-		/* FIXME: not supported yet */
 		return -EINVAL;
 	}
 
@@ -2556,14 +2485,14 @@ static void dce_v6_0_set_crtc_vblank_int
 
 	switch (state) {
 	case AMDGPU_IRQ_STATE_DISABLE:
-		interrupt_mask = RREG32(INT_MASK + reg_block);
+		interrupt_mask = RREG32(mmINT_MASK + reg_block);
 		interrupt_mask &= ~VBLANK_INT_MASK;
-		WREG32(INT_MASK + reg_block, interrupt_mask);
+		WREG32(mmINT_MASK + reg_block, interrupt_mask);
 		break;
 	case AMDGPU_IRQ_STATE_ENABLE:
-		interrupt_mask = RREG32(INT_MASK + reg_block);
+		interrupt_mask = RREG32(mmINT_MASK + reg_block);
 		interrupt_mask |= VBLANK_INT_MASK;
-		WREG32(INT_MASK + reg_block, interrupt_mask);
+		WREG32(mmINT_MASK + reg_block, interrupt_mask);
 		break;
 	default:
 		break;
@@ -2582,42 +2511,23 @@ static int dce_v6_0_set_hpd_interrupt_st
 					    unsigned type,
 					    enum amdgpu_interrupt_state state)
 {
-	u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
+	u32 dc_hpd_int_cntl;
 
-	switch (type) {
-	case AMDGPU_HPD_1:
-		dc_hpd_int_cntl_reg = DC_HPD1_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_2:
-		dc_hpd_int_cntl_reg = DC_HPD2_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_3:
-		dc_hpd_int_cntl_reg = DC_HPD3_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_4:
-		dc_hpd_int_cntl_reg = DC_HPD4_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_5:
-		dc_hpd_int_cntl_reg = DC_HPD5_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_6:
-		dc_hpd_int_cntl_reg = DC_HPD6_INT_CONTROL;
-		break;
-	default:
+	if (type >= adev->mode_info.num_hpd) {
 		DRM_DEBUG("invalid hdp %d\n", type);
 		return 0;
 	}
 
 	switch (state) {
 	case AMDGPU_IRQ_STATE_DISABLE:
-		dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
-		dc_hpd_int_cntl &= ~(DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-		WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+		dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
+		dc_hpd_int_cntl &= ~DC_HPDx_INT_EN;
+		WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
 		break;
 	case AMDGPU_IRQ_STATE_ENABLE:
-		dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
-		dc_hpd_int_cntl |= (DC_HPDx_INT_EN | DC_HPDx_RX_INT_EN);
-		WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+		dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
+		dc_hpd_int_cntl |= DC_HPDx_INT_EN;
+		WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
 		break;
 	default:
 		break;
@@ -2685,7 +2595,7 @@ static int dce_v6_0_crtc_irq(struct amdg
 	switch (entry->src_data) {
 	case 0: /* vblank */
 		if (disp_int & interrupt_status_offsets[crtc].vblank)
-			WREG32(VBLANK_STATUS + crtc_offsets[crtc], VBLANK_ACK);
+			WREG32(mmVBLANK_STATUS + crtc_offsets[crtc], VBLANK_ACK);
 		else
 			DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
 
@@ -2696,7 +2606,7 @@ static int dce_v6_0_crtc_irq(struct amdg
 		break;
 	case 1: /* vline */
 		if (disp_int & interrupt_status_offsets[crtc].vline)
-			WREG32(VLINE_STATUS + crtc_offsets[crtc], VLINE_ACK);
+			WREG32(mmVLINE_STATUS + crtc_offsets[crtc], VLINE_ACK);
 		else
 			DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
 
@@ -2722,12 +2632,12 @@ static int dce_v6_0_set_pageflip_interru
 		return -EINVAL;
 	}
 
-	reg = RREG32(GRPH_INT_CONTROL + crtc_offsets[type]);
+	reg = RREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type]);
 	if (state == AMDGPU_IRQ_STATE_DISABLE)
-		WREG32(GRPH_INT_CONTROL + crtc_offsets[type],
+		WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
 		       reg & ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
 	else
-		WREG32(GRPH_INT_CONTROL + crtc_offsets[type],
+		WREG32(mmGRPH_INTERRUPT_CONTROL + crtc_offsets[type],
 		       reg | GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK);
 
 	return 0;
@@ -2750,9 +2660,9 @@ static int dce_v6_0_pageflip_irq(struct
 		return -EINVAL;
 	}
 
-	if (RREG32(GRPH_INT_STATUS + crtc_offsets[crtc_id]) &
+	if (RREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id]) &
 	    GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK)
-		WREG32(GRPH_INT_STATUS + crtc_offsets[crtc_id],
+		WREG32(mmGRPH_INTERRUPT_STATUS + crtc_offsets[crtc_id],
 		       GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK);
 
 	/* IRQ could occur when in initial stage */
@@ -2790,7 +2700,7 @@ static int dce_v6_0_hpd_irq(struct amdgp
 			    struct amdgpu_irq_src *source,
 			    struct amdgpu_iv_entry *entry)
 {
-	uint32_t disp_int, mask, int_control, tmp;
+	uint32_t disp_int, mask, tmp;
 	unsigned hpd;
 
 	if (entry->src_data >= adev->mode_info.num_hpd) {
@@ -2801,12 +2711,11 @@ static int dce_v6_0_hpd_irq(struct amdgp
 	hpd = entry->src_data;
 	disp_int = RREG32(interrupt_status_offsets[hpd].reg);
 	mask = interrupt_status_offsets[hpd].hpd;
-	int_control = hpd_int_control_offsets[hpd];
 
 	if (disp_int & mask) {
-		tmp = RREG32(int_control);
+		tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
 		tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
-		WREG32(int_control, tmp);
+		WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
 		schedule_work(&adev->hotplug_work);
 		DRM_INFO("IH: HPD%d\n", hpd + 1);
 	}
@@ -2827,7 +2736,7 @@ static int dce_v6_0_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs dce_v6_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v6_0_ip_funcs = {
 	.name = "dce_v6_0",
 	.early_init = dce_v6_0_early_init,
 	.late_init = NULL,
@@ -3122,7 +3031,6 @@ static const struct amdgpu_display_funcs
 	.bandwidth_update = &dce_v6_0_bandwidth_update,
 	.vblank_get_counter = &dce_v6_0_vblank_get_counter,
 	.vblank_wait = &dce_v6_0_vblank_wait,
-	.is_display_hung = &dce_v6_0_is_display_hung,
 	.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
 	.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
 	.hpd_sense = &dce_v6_0_hpd_sense,
@@ -3168,3 +3076,21 @@ static void dce_v6_0_set_irq_funcs(struc
 	adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
 	adev->hpd_irq.funcs = &dce_v6_0_hpd_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version dce_v6_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 6,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &dce_v6_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v6_4_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 6,
+	.minor = 4,
+	.rev = 0,
+	.funcs = &dce_v6_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v6_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,9 @@
 #ifndef __DCE_V6_0_H__
 #define __DCE_V6_0_H__
 
-extern const struct amd_ip_funcs dce_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version dce_v6_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v6_4_ip_block;
+
+void dce_v6_0_disable_dce(struct amdgpu_device *adev);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@
 #include "atombios_encoders.h"
 #include "amdgpu_pll.h"
 #include "amdgpu_connectors.h"
+#include "dce_v8_0.h"
 
 #include "dce/dce_8_0_d.h"
 #include "dce/dce_8_0_sh_mask.h"
@@ -56,6 +57,16 @@ static const u32 crtc_offsets[6] =
 	CRTC5_REGISTER_OFFSET
 };
 
+static const u32 hpd_offsets[] =
+{
+	HPD0_REGISTER_OFFSET,
+	HPD1_REGISTER_OFFSET,
+	HPD2_REGISTER_OFFSET,
+	HPD3_REGISTER_OFFSET,
+	HPD4_REGISTER_OFFSET,
+	HPD5_REGISTER_OFFSET
+};
+
 static const uint32_t dig_offsets[] = {
 	CRTC0_REGISTER_OFFSET,
 	CRTC1_REGISTER_OFFSET,
@@ -104,15 +115,6 @@ static const struct {
 	.hpd = DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK
 } };
 
-static const uint32_t hpd_int_control_offsets[6] = {
-	mmDC_HPD1_INT_CONTROL,
-	mmDC_HPD2_INT_CONTROL,
-	mmDC_HPD3_INT_CONTROL,
-	mmDC_HPD4_INT_CONTROL,
-	mmDC_HPD5_INT_CONTROL,
-	mmDC_HPD6_INT_CONTROL,
-};
-
 static u32 dce_v8_0_audio_endpt_rreg(struct amdgpu_device *adev,
 				     u32 block_offset, u32 reg)
 {
@@ -278,34 +280,12 @@ static bool dce_v8_0_hpd_sense(struct am
 {
 	bool connected = false;
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		if (RREG32(mmDC_HPD1_INT_STATUS) & DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
-			connected = true;
-		break;
-	case AMDGPU_HPD_2:
-		if (RREG32(mmDC_HPD2_INT_STATUS) & DC_HPD2_INT_STATUS__DC_HPD2_SENSE_MASK)
-			connected = true;
-		break;
-	case AMDGPU_HPD_3:
-		if (RREG32(mmDC_HPD3_INT_STATUS) & DC_HPD3_INT_STATUS__DC_HPD3_SENSE_MASK)
-			connected = true;
-		break;
-	case AMDGPU_HPD_4:
-		if (RREG32(mmDC_HPD4_INT_STATUS) & DC_HPD4_INT_STATUS__DC_HPD4_SENSE_MASK)
-			connected = true;
-		break;
-	case AMDGPU_HPD_5:
-		if (RREG32(mmDC_HPD5_INT_STATUS) & DC_HPD5_INT_STATUS__DC_HPD5_SENSE_MASK)
-			connected = true;
-		break;
-	case AMDGPU_HPD_6:
-		if (RREG32(mmDC_HPD6_INT_STATUS) & DC_HPD6_INT_STATUS__DC_HPD6_SENSE_MASK)
-			connected = true;
-		break;
-	default:
-		break;
-	}
+	if (hpd >= adev->mode_info.num_hpd)
+		return connected;
+
+	if (RREG32(mmDC_HPD1_INT_STATUS + hpd_offsets[hpd]) &
+	    DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK)
+		connected = true;
 
 	return connected;
 }
@@ -324,58 +304,15 @@ static void dce_v8_0_hpd_set_polarity(st
 	u32 tmp;
 	bool connected = dce_v8_0_hpd_sense(adev, hpd);
 
-	switch (hpd) {
-	case AMDGPU_HPD_1:
-		tmp = RREG32(mmDC_HPD1_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
-		else
-			tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
-		WREG32(mmDC_HPD1_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_2:
-		tmp = RREG32(mmDC_HPD2_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK;
-		else
-			tmp |= DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK;
-		WREG32(mmDC_HPD2_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_3:
-		tmp = RREG32(mmDC_HPD3_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK;
-		else
-			tmp |= DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK;
-		WREG32(mmDC_HPD3_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_4:
-		tmp = RREG32(mmDC_HPD4_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK;
-		else
-			tmp |= DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK;
-		WREG32(mmDC_HPD4_INT_CONTROL, tmp);
-		break;
-	case AMDGPU_HPD_5:
-		tmp = RREG32(mmDC_HPD5_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK;
-		else
-			tmp |= DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK;
-		WREG32(mmDC_HPD5_INT_CONTROL, tmp);
-			break;
-	case AMDGPU_HPD_6:
-		tmp = RREG32(mmDC_HPD6_INT_CONTROL);
-		if (connected)
-			tmp &= ~DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK;
-		else
-			tmp |= DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK;
-		WREG32(mmDC_HPD6_INT_CONTROL, tmp);
-		break;
-	default:
-		break;
-	}
+	if (hpd >= adev->mode_info.num_hpd)
+		return;
+
+	tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
+	if (connected)
+		tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+	else
+		tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK;
+	WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
 }
 
 /**
@@ -390,35 +327,17 @@ static void dce_v8_0_hpd_init(struct amd
 {
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
-	u32 tmp = (0x9c4 << DC_HPD1_CONTROL__DC_HPD1_CONNECTION_TIMER__SHIFT) |
-		(0xfa << DC_HPD1_CONTROL__DC_HPD1_RX_INT_TIMER__SHIFT) |
-		DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+	u32 tmp;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			WREG32(mmDC_HPD1_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_2:
-			WREG32(mmDC_HPD2_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_3:
-			WREG32(mmDC_HPD3_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_4:
-			WREG32(mmDC_HPD4_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_5:
-			WREG32(mmDC_HPD5_CONTROL, tmp);
-			break;
-		case AMDGPU_HPD_6:
-			WREG32(mmDC_HPD6_CONTROL, tmp);
-			break;
-		default:
-			break;
-		}
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+			continue;
+
+		tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+		tmp |= DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+		WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 
 		if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
 		    connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
@@ -427,34 +346,9 @@ static void dce_v8_0_hpd_init(struct amd
 			 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
 			 * also avoid interrupt storms during dpms.
 			 */
-			u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
-
-			switch (amdgpu_connector->hpd.hpd) {
-			case AMDGPU_HPD_1:
-				dc_hpd_int_cntl_reg = mmDC_HPD1_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_2:
-				dc_hpd_int_cntl_reg = mmDC_HPD2_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_3:
-				dc_hpd_int_cntl_reg = mmDC_HPD3_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_4:
-				dc_hpd_int_cntl_reg = mmDC_HPD4_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_5:
-				dc_hpd_int_cntl_reg = mmDC_HPD5_INT_CONTROL;
-				break;
-			case AMDGPU_HPD_6:
-				dc_hpd_int_cntl_reg = mmDC_HPD6_INT_CONTROL;
-				break;
-			default:
-				continue;
-			}
-
-			dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
-			dc_hpd_int_cntl &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
-			WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+			tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+			tmp &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
+			WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], tmp);
 			continue;
 		}
 
@@ -475,32 +369,18 @@ static void dce_v8_0_hpd_fini(struct amd
 {
 	struct drm_device *dev = adev->ddev;
 	struct drm_connector *connector;
+	u32 tmp;
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
 
-		switch (amdgpu_connector->hpd.hpd) {
-		case AMDGPU_HPD_1:
-			WREG32(mmDC_HPD1_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_2:
-			WREG32(mmDC_HPD2_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_3:
-			WREG32(mmDC_HPD3_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_4:
-			WREG32(mmDC_HPD4_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_5:
-			WREG32(mmDC_HPD5_CONTROL, 0);
-			break;
-		case AMDGPU_HPD_6:
-			WREG32(mmDC_HPD6_CONTROL, 0);
-			break;
-		default:
-			break;
-		}
+		if (amdgpu_connector->hpd.hpd >= adev->mode_info.num_hpd)
+			continue;
+
+		tmp = RREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd]);
+		tmp &= ~DC_HPD1_CONTROL__DC_HPD1_EN_MASK;
+		WREG32(mmDC_HPD1_CONTROL + hpd_offsets[amdgpu_connector->hpd.hpd], 0);
+
 		amdgpu_irq_put(adev, &adev->hpd_irq, amdgpu_connector->hpd.hpd);
 	}
 }
@@ -2030,7 +1910,7 @@ static int dce_v8_0_crtc_do_set_base(str
 	u32 viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
-	char *format_name;
+	struct drm_format_name_buf format_name;
 
 	/* no fb bound */
 	if (!atomic && !crtc->primary->fb) {
@@ -2135,9 +2015,8 @@ static int dce_v8_0_crtc_do_set_base(str
 		bypass_lut = true;
 		break;
 	default:
-		format_name = drm_get_format_name(target_fb->pixel_format);
-		DRM_ERROR("Unsupported screen format %s\n", format_name);
-		kfree(format_name);
+		DRM_ERROR("Unsupported screen format %s\n",
+		          drm_get_format_name(target_fb->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
@@ -2465,6 +2344,9 @@ static int dce_v8_0_cursor_move_locked(s
 	struct amdgpu_device *adev = crtc->dev->dev_private;
 	int xorigin = 0, yorigin = 0;
 
+	amdgpu_crtc->cursor_x = x;
+	amdgpu_crtc->cursor_y = y;
+
 	/* avivo cursor are offset into the total surface */
 	x += crtc->x;
 	y += crtc->y;
@@ -2484,9 +2366,6 @@ static int dce_v8_0_cursor_move_locked(s
 	WREG32(mmCUR_SIZE + amdgpu_crtc->crtc_offset,
 	       ((amdgpu_crtc->cursor_width - 1) << 16) | (amdgpu_crtc->cursor_height - 1));
 
-	amdgpu_crtc->cursor_x = x;
-	amdgpu_crtc->cursor_y = y;
-
 	return 0;
 }
 
@@ -2549,12 +2428,11 @@ static int dce_v8_0_crtc_cursor_set2(str
 		return ret;
 	}
 
-	amdgpu_crtc->cursor_width = width;
-	amdgpu_crtc->cursor_height = height;
-
 	dce_v8_0_lock_cursor(crtc, true);
 
-	if (hot_x != amdgpu_crtc->cursor_hot_x ||
+	if (width != amdgpu_crtc->cursor_width ||
+	    height != amdgpu_crtc->cursor_height ||
+	    hot_x != amdgpu_crtc->cursor_hot_x ||
 	    hot_y != amdgpu_crtc->cursor_hot_y) {
 		int x, y;
 
@@ -2563,6 +2441,8 @@ static int dce_v8_0_crtc_cursor_set2(str
 
 		dce_v8_0_cursor_move_locked(crtc, x, y);
 
+		amdgpu_crtc->cursor_width = width;
+		amdgpu_crtc->cursor_height = height;
 		amdgpu_crtc->cursor_hot_x = hot_x;
 		amdgpu_crtc->cursor_hot_y = hot_y;
 	}
@@ -3198,42 +3078,23 @@ static int dce_v8_0_set_hpd_interrupt_st
 					    unsigned type,
 					    enum amdgpu_interrupt_state state)
 {
-	u32 dc_hpd_int_cntl_reg, dc_hpd_int_cntl;
+	u32 dc_hpd_int_cntl;
 
-	switch (type) {
-	case AMDGPU_HPD_1:
-		dc_hpd_int_cntl_reg = mmDC_HPD1_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_2:
-		dc_hpd_int_cntl_reg = mmDC_HPD2_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_3:
-		dc_hpd_int_cntl_reg = mmDC_HPD3_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_4:
-		dc_hpd_int_cntl_reg = mmDC_HPD4_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_5:
-		dc_hpd_int_cntl_reg = mmDC_HPD5_INT_CONTROL;
-		break;
-	case AMDGPU_HPD_6:
-		dc_hpd_int_cntl_reg = mmDC_HPD6_INT_CONTROL;
-		break;
-	default:
+	if (type >= adev->mode_info.num_hpd) {
 		DRM_DEBUG("invalid hdp %d\n", type);
 		return 0;
 	}
 
 	switch (state) {
 	case AMDGPU_IRQ_STATE_DISABLE:
-		dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
+		dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
 		dc_hpd_int_cntl &= ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
-		WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+		WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
 		break;
 	case AMDGPU_IRQ_STATE_ENABLE:
-		dc_hpd_int_cntl = RREG32(dc_hpd_int_cntl_reg);
+		dc_hpd_int_cntl = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type]);
 		dc_hpd_int_cntl |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK;
-		WREG32(dc_hpd_int_cntl_reg, dc_hpd_int_cntl);
+		WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[type], dc_hpd_int_cntl);
 		break;
 	default:
 		break;
@@ -3406,7 +3267,7 @@ static int dce_v8_0_hpd_irq(struct amdgp
 			    struct amdgpu_irq_src *source,
 			    struct amdgpu_iv_entry *entry)
 {
-	uint32_t disp_int, mask, int_control, tmp;
+	uint32_t disp_int, mask, tmp;
 	unsigned hpd;
 
 	if (entry->src_data >= adev->mode_info.num_hpd) {
@@ -3417,12 +3278,11 @@ static int dce_v8_0_hpd_irq(struct amdgp
 	hpd = entry->src_data;
 	disp_int = RREG32(interrupt_status_offsets[hpd].reg);
 	mask = interrupt_status_offsets[hpd].hpd;
-	int_control = hpd_int_control_offsets[hpd];
 
 	if (disp_int & mask) {
-		tmp = RREG32(int_control);
+		tmp = RREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd]);
 		tmp |= DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK;
-		WREG32(int_control, tmp);
+		WREG32(mmDC_HPD1_INT_CONTROL + hpd_offsets[hpd], tmp);
 		schedule_work(&adev->hotplug_work);
 		DRM_DEBUG("IH: HPD%d\n", hpd + 1);
 	}
@@ -3443,7 +3303,7 @@ static int dce_v8_0_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs dce_v8_0_ip_funcs = {
+static const struct amd_ip_funcs dce_v8_0_ip_funcs = {
 	.name = "dce_v8_0",
 	.early_init = dce_v8_0_early_init,
 	.late_init = NULL,
@@ -3727,7 +3587,6 @@ static const struct amdgpu_display_funcs
 	.bandwidth_update = &dce_v8_0_bandwidth_update,
 	.vblank_get_counter = &dce_v8_0_vblank_get_counter,
 	.vblank_wait = &dce_v8_0_vblank_wait,
-	.is_display_hung = &dce_v8_0_is_display_hung,
 	.backlight_set_level = &amdgpu_atombios_encoder_set_backlight_level,
 	.backlight_get_level = &amdgpu_atombios_encoder_get_backlight_level,
 	.hpd_sense = &dce_v8_0_hpd_sense,
@@ -3773,3 +3632,48 @@ static void dce_v8_0_set_irq_funcs(struc
 	adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
 	adev->hpd_irq.funcs = &dce_v8_0_hpd_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version dce_v8_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 8,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_1_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 8,
+	.minor = 1,
+	.rev = 0,
+	.funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_2_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 8,
+	.minor = 2,
+	.rev = 0,
+	.funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_3_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 8,
+	.minor = 3,
+	.rev = 0,
+	.funcs = &dce_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version dce_v8_5_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 8,
+	.minor = 5,
+	.rev = 0,
+	.funcs = &dce_v8_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_v8_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,11 @@
 #ifndef __DCE_V8_0_H__
 #define __DCE_V8_0_H__
 
-extern const struct amd_ip_funcs dce_v8_0_ip_funcs;
+extern const struct amdgpu_ip_block_version dce_v8_0_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_1_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_2_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_3_ip_block;
+extern const struct amdgpu_ip_block_version dce_v8_5_ip_block;
 
 void dce_v8_0_disable_dce(struct amdgpu_device *adev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,9 @@
 #include "atom.h"
 #include "amdgpu_pll.h"
 #include "amdgpu_connectors.h"
+#ifdef CONFIG_DRM_AMDGPU_SI
+#include "dce_v6_0.h"
+#endif
 #ifdef CONFIG_DRM_AMDGPU_CIK
 #include "dce_v8_0.h"
 #endif
@@ -34,11 +37,13 @@
 #include "dce_v11_0.h"
 #include "dce_virtual.h"
 
+#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
+
+
 static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
 static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
-static int dce_virtual_pageflip_irq(struct amdgpu_device *adev,
-				  struct amdgpu_irq_src *source,
-				  struct amdgpu_iv_entry *entry);
+static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
+					      int index);
 
 /**
  * dce_virtual_vblank_wait - vblank wait asic callback.
@@ -90,15 +95,18 @@ static u32 dce_virtual_hpd_get_gpio_reg(
 	return 0;
 }
 
-static bool dce_virtual_is_display_hung(struct amdgpu_device *adev)
-{
-	return false;
-}
-
 static void dce_virtual_stop_mc_access(struct amdgpu_device *adev,
 			      struct amdgpu_mode_mc_save *save)
 {
 	switch (adev->asic_type) {
+#ifdef CONFIG_DRM_AMDGPU_SI
+	case CHIP_TAHITI:
+	case CHIP_PITCAIRN:
+	case CHIP_VERDE:
+	case CHIP_OLAND:
+		dce_v6_0_disable_dce(adev);
+		break;
+#endif
 #ifdef CONFIG_DRM_AMDGPU_CIK
 	case CHIP_BONAIRE:
 	case CHIP_HAWAII:
@@ -119,6 +127,9 @@ static void dce_virtual_stop_mc_access(s
 		dce_v11_0_disable_dce(adev);
 		break;
 	case CHIP_TOPAZ:
+#ifdef CONFIG_DRM_AMDGPU_SI
+	case CHIP_HAINAN:
+#endif
 		/* no DCE */
 		return;
 	default:
@@ -195,16 +206,15 @@ static void dce_virtual_crtc_dpms(struct
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		amdgpu_crtc->enabled = true;
-		/* Make sure VBLANK and PFLIP interrupts are still enabled */
+		/* Make sure VBLANK interrupts are still enabled */
 		type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
 		amdgpu_irq_update(adev, &adev->crtc_irq, type);
-		amdgpu_irq_update(adev, &adev->pageflip_irq, type);
-		drm_vblank_on(dev, amdgpu_crtc->crtc_id);
+		drm_crtc_vblank_on(crtc);
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		drm_vblank_off(dev, amdgpu_crtc->crtc_id);
+		drm_crtc_vblank_off(crtc);
 		amdgpu_crtc->enabled = false;
 		break;
 	}
@@ -264,24 +274,6 @@ static bool dce_virtual_crtc_mode_fixup(
 				     const struct drm_display_mode *mode,
 				     struct drm_display_mode *adjusted_mode)
 {
-	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-	struct drm_encoder *encoder;
-
-	/* assign the encoder to the amdgpu crtc to avoid repeated lookups later */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		if (encoder->crtc == crtc) {
-			amdgpu_crtc->encoder = encoder;
-			amdgpu_crtc->connector = amdgpu_get_connector_for_encoder(encoder);
-			break;
-		}
-	}
-	if ((amdgpu_crtc->encoder == NULL) || (amdgpu_crtc->connector == NULL)) {
-		amdgpu_crtc->encoder = NULL;
-		amdgpu_crtc->connector = NULL;
-		return false;
-	}
-
 	return true;
 }
 
@@ -341,6 +333,7 @@ static int dce_virtual_crtc_init(struct
 	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
 	amdgpu_crtc->encoder = NULL;
 	amdgpu_crtc->connector = NULL;
+	amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
 	drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
 
 	return 0;
@@ -350,48 +343,121 @@ static int dce_virtual_early_init(void *
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	adev->mode_info.vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
 	dce_virtual_set_display_funcs(adev);
 	dce_virtual_set_irq_funcs(adev);
 
-	adev->mode_info.num_crtc = 1;
 	adev->mode_info.num_hpd = 1;
 	adev->mode_info.num_dig = 1;
 	return 0;
 }
 
-static bool dce_virtual_get_connector_info(struct amdgpu_device *adev)
+static struct drm_encoder *
+dce_virtual_encoder(struct drm_connector *connector)
 {
-	struct amdgpu_i2c_bus_rec ddc_bus;
-	struct amdgpu_router router;
-	struct amdgpu_hpd hpd;
+	int enc_id = connector->encoder_ids[0];
+	struct drm_encoder *encoder;
+	int i;
 
-	/* look up gpio for ddc, hpd */
-	ddc_bus.valid = false;
-	hpd.hpd = AMDGPU_HPD_NONE;
-	/* needed for aux chan transactions */
-	ddc_bus.hpd = hpd.hpd;
+	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+		if (connector->encoder_ids[i] == 0)
+			break;
 
-	memset(&router, 0, sizeof(router));
-	router.ddc_valid = false;
-	router.cd_valid = false;
-	amdgpu_display_add_connector(adev,
-				      0,
-				      ATOM_DEVICE_CRT1_SUPPORT,
-				      DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus,
-				      CONNECTOR_OBJECT_ID_VIRTUAL,
-				      &hpd,
-				      &router);
+		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+		if (!encoder)
+			continue;
 
-	amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL,
-							ATOM_DEVICE_CRT1_SUPPORT,
-							0);
+		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
+			return encoder;
+	}
 
-	amdgpu_link_encoder_connector(adev->ddev);
+	/* pick the first one */
+	if (enc_id)
+		return drm_encoder_find(connector->dev, enc_id);
+	return NULL;
+}
 
-	return true;
+static int dce_virtual_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode = NULL;
+	unsigned i;
+	static const struct mode_size {
+		int w;
+		int h;
+	} common_modes[17] = {
+		{ 640,  480},
+		{ 720,  480},
+		{ 800,  600},
+		{ 848,  480},
+		{1024,  768},
+		{1152,  768},
+		{1280,  720},
+		{1280,  800},
+		{1280,  854},
+		{1280,  960},
+		{1280, 1024},
+		{1440,  900},
+		{1400, 1050},
+		{1680, 1050},
+		{1600, 1200},
+		{1920, 1080},
+		{1920, 1200}
+	};
+
+	for (i = 0; i < 17; i++) {
+		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
+		drm_mode_probed_add(connector, mode);
+	}
+
+	return 0;
+}
+
+static int dce_virtual_mode_valid(struct drm_connector *connector,
+				  struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static int
+dce_virtual_dpms(struct drm_connector *connector, int mode)
+{
+	return 0;
+}
+
+static int
+dce_virtual_set_property(struct drm_connector *connector,
+			 struct drm_property *property,
+			 uint64_t val)
+{
+	return 0;
+}
+
+static void dce_virtual_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+static void dce_virtual_force(struct drm_connector *connector)
+{
+	return;
 }
 
+static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
+	.get_modes = dce_virtual_get_modes,
+	.mode_valid = dce_virtual_mode_valid,
+	.best_encoder = dce_virtual_encoder,
+};
+
+static const struct drm_connector_funcs dce_virtual_connector_funcs = {
+	.dpms = dce_virtual_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = dce_virtual_set_property,
+	.destroy = dce_virtual_destroy,
+	.force = dce_virtual_force,
+};
+
 static int dce_virtual_sw_init(void *handle)
 {
 	int r, i;
@@ -420,16 +486,16 @@ static int dce_virtual_sw_init(void *han
 	adev->ddev->mode_config.max_width = 16384;
 	adev->ddev->mode_config.max_height = 16384;
 
-	/* allocate crtcs */
+	/* allocate crtcs, encoders, connectors */
 	for (i = 0; i < adev->mode_info.num_crtc; i++) {
 		r = dce_virtual_crtc_init(adev, i);
 		if (r)
 			return r;
+		r = dce_virtual_connector_encoder_init(adev, i);
+		if (r)
+			return r;
 	}
 
-	dce_virtual_get_connector_info(adev);
-	amdgpu_print_display_setup(adev->ddev);
-
 	drm_kms_helper_poll_init(adev->ddev);
 
 	adev->mode_info.mode_config_initialized = true;
@@ -496,7 +562,7 @@ static int dce_virtual_set_powergating_s
 	return 0;
 }
 
-const struct amd_ip_funcs dce_virtual_ip_funcs = {
+static const struct amd_ip_funcs dce_virtual_ip_funcs = {
 	.name = "dce_virtual",
 	.early_init = dce_virtual_early_init,
 	.late_init = NULL,
@@ -526,8 +592,8 @@ static void dce_virtual_encoder_commit(s
 
 static void
 dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
-		      struct drm_display_mode *mode,
-		      struct drm_display_mode *adjusted_mode)
+			     struct drm_display_mode *mode,
+			     struct drm_display_mode *adjusted_mode)
 {
 	return;
 }
@@ -547,10 +613,6 @@ static bool dce_virtual_encoder_mode_fix
 				    const struct drm_display_mode *mode,
 				    struct drm_display_mode *adjusted_mode)
 {
-
-	/* set the active encoder to connector routing */
-	amdgpu_encoder_set_active_device(encoder);
-
 	return true;
 }
 
@@ -565,56 +627,48 @@ static const struct drm_encoder_helper_f
 
 static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
 {
-	struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder);
-
-	kfree(amdgpu_encoder->enc_priv);
 	drm_encoder_cleanup(encoder);
-	kfree(amdgpu_encoder);
+	kfree(encoder);
 }
 
 static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
 	.destroy = dce_virtual_encoder_destroy,
 };
 
-static void dce_virtual_encoder_add(struct amdgpu_device *adev,
-				 uint32_t encoder_enum,
-				 uint32_t supported_device,
-				 u16 caps)
+static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
+					      int index)
 {
-	struct drm_device *dev = adev->ddev;
 	struct drm_encoder *encoder;
-	struct amdgpu_encoder *amdgpu_encoder;
+	struct drm_connector *connector;
 
-	/* see if we already added it */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		amdgpu_encoder = to_amdgpu_encoder(encoder);
-		if (amdgpu_encoder->encoder_enum == encoder_enum) {
-			amdgpu_encoder->devices |= supported_device;
-			return;
-		}
+	/* add a new encoder */
+	encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
+	if (!encoder)
+		return -ENOMEM;
+	encoder->possible_crtcs = 1 << index;
+	drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs,
+			 DRM_MODE_ENCODER_VIRTUAL, NULL);
+	drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
 
+	connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
+	if (!connector) {
+		kfree(encoder);
+		return -ENOMEM;
 	}
 
-	/* add a new one */
-	amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL);
-	if (!amdgpu_encoder)
-		return;
+	/* add a new connector */
+	drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs,
+			   DRM_MODE_CONNECTOR_VIRTUAL);
+	drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+	drm_connector_register(connector);
 
-	encoder = &amdgpu_encoder->base;
-	encoder->possible_crtcs = 0x1;
-	amdgpu_encoder->enc_priv = NULL;
-	amdgpu_encoder->encoder_enum = encoder_enum;
-	amdgpu_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-	amdgpu_encoder->devices = supported_device;
-	amdgpu_encoder->rmx_type = RMX_OFF;
-	amdgpu_encoder->underscan_type = UNDERSCAN_OFF;
-	amdgpu_encoder->is_ext_encoder = false;
-	amdgpu_encoder->caps = caps;
+	/* link them */
+	drm_mode_connector_attach_encoder(connector, encoder);
 
-	drm_encoder_init(dev, encoder, &dce_virtual_encoder_funcs,
-					 DRM_MODE_ENCODER_VIRTUAL, NULL);
-	drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
-	DRM_INFO("[FM]encoder: %d is VIRTUAL\n", amdgpu_encoder->encoder_id);
+	return 0;
 }
 
 static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
@@ -622,7 +676,6 @@ static const struct amdgpu_display_funcs
 	.bandwidth_update = &dce_virtual_bandwidth_update,
 	.vblank_get_counter = &dce_virtual_vblank_get_counter,
 	.vblank_wait = &dce_virtual_vblank_wait,
-	.is_display_hung = &dce_virtual_is_display_hung,
 	.backlight_set_level = NULL,
 	.backlight_get_level = NULL,
 	.hpd_sense = &dce_virtual_hpd_sense,
@@ -630,8 +683,8 @@ static const struct amdgpu_display_funcs
 	.hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
 	.page_flip = &dce_virtual_page_flip,
 	.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
-	.add_encoder = &dce_virtual_encoder_add,
-	.add_connector = &amdgpu_connector_add,
+	.add_encoder = NULL,
+	.add_connector = NULL,
 	.stop_mc_access = &dce_virtual_stop_mc_access,
 	.resume_mc_access = &dce_virtual_resume_mc_access,
 };
@@ -642,107 +695,13 @@ static void dce_virtual_set_display_func
 		adev->mode_info.funcs = &dce_virtual_display_funcs;
 }
 
-static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
-{
-	struct amdgpu_mode_info *mode_info = container_of(vblank_timer, struct amdgpu_mode_info ,vblank_timer);
-	struct amdgpu_device *adev = container_of(mode_info, struct amdgpu_device ,mode_info);
-	unsigned crtc = 0;
-	drm_handle_vblank(adev->ddev, crtc);
-	dce_virtual_pageflip_irq(adev, NULL, NULL);
-	hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
-	return HRTIMER_NORESTART;
-}
-
-static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
-						     int crtc,
-						     enum amdgpu_interrupt_state state)
-{
-	if (crtc >= adev->mode_info.num_crtc) {
-		DRM_DEBUG("invalid crtc %d\n", crtc);
-		return;
-	}
-
-	if (state && !adev->mode_info.vsync_timer_enabled) {
-		DRM_DEBUG("Enable software vsync timer\n");
-		hrtimer_init(&adev->mode_info.vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-		hrtimer_set_expires(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD));
-		adev->mode_info.vblank_timer.function = dce_virtual_vblank_timer_handle;
-		hrtimer_start(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
-	} else if (!state && adev->mode_info.vsync_timer_enabled) {
-		DRM_DEBUG("Disable software vsync timer\n");
-		hrtimer_cancel(&adev->mode_info.vblank_timer);
-	}
-
-	adev->mode_info.vsync_timer_enabled = state;
-	DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
-}
-
-
-static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
-                                       struct amdgpu_irq_src *source,
-                                       unsigned type,
-                                       enum amdgpu_interrupt_state state)
-{
-	switch (type) {
-	case AMDGPU_CRTC_IRQ_VBLANK1:
-		dce_virtual_set_crtc_vblank_interrupt_state(adev, 0, state);
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-static void dce_virtual_crtc_vblank_int_ack(struct amdgpu_device *adev,
-					  int crtc)
-{
-	if (crtc >= adev->mode_info.num_crtc) {
-		DRM_DEBUG("invalid crtc %d\n", crtc);
-		return;
-	}
-}
-
-static int dce_virtual_crtc_irq(struct amdgpu_device *adev,
-			      struct amdgpu_irq_src *source,
-			      struct amdgpu_iv_entry *entry)
-{
-	unsigned crtc = 0;
-	unsigned irq_type = AMDGPU_CRTC_IRQ_VBLANK1;
-
-	dce_virtual_crtc_vblank_int_ack(adev, crtc);
-
-	if (amdgpu_irq_enabled(adev, source, irq_type)) {
-		drm_handle_vblank(adev->ddev, crtc);
-	}
-	dce_virtual_pageflip_irq(adev, NULL, NULL);
-	DRM_DEBUG("IH: D%d vblank\n", crtc + 1);
-	return 0;
-}
-
-static int dce_virtual_set_pageflip_irq_state(struct amdgpu_device *adev,
-					    struct amdgpu_irq_src *src,
-					    unsigned type,
-					    enum amdgpu_interrupt_state state)
-{
-	if (type >= adev->mode_info.num_crtc) {
-		DRM_ERROR("invalid pageflip crtc %d\n", type);
-		return -EINVAL;
-	}
-	DRM_DEBUG("[FM]set pageflip irq type %d state %d\n", type, state);
-
-	return 0;
-}
-
-static int dce_virtual_pageflip_irq(struct amdgpu_device *adev,
-				  struct amdgpu_irq_src *source,
-				  struct amdgpu_iv_entry *entry)
+static int dce_virtual_pageflip(struct amdgpu_device *adev,
+				unsigned crtc_id)
 {
 	unsigned long flags;
-	unsigned crtc_id = 0;
 	struct amdgpu_crtc *amdgpu_crtc;
 	struct amdgpu_flip_work *works;
 
-	crtc_id = 0;
 	amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
 
 	if (crtc_id >= adev->mode_info.num_crtc) {
@@ -781,22 +740,79 @@ static int dce_virtual_pageflip_irq(stru
 	return 0;
 }
 
+static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
+{
+	struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
+						       struct amdgpu_crtc, vblank_timer);
+	struct drm_device *ddev = amdgpu_crtc->base.dev;
+	struct amdgpu_device *adev = ddev->dev_private;
+
+	drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
+	dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
+	hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
+		      HRTIMER_MODE_REL);
+
+	return HRTIMER_NORESTART;
+}
+
+static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
+							int crtc,
+							enum amdgpu_interrupt_state state)
+{
+	if (crtc >= adev->mode_info.num_crtc) {
+		DRM_DEBUG("invalid crtc %d\n", crtc);
+		return;
+	}
+
+	if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
+		DRM_DEBUG("Enable software vsync timer\n");
+		hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer,
+			     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer,
+				    DCE_VIRTUAL_VBLANK_PERIOD);
+		adev->mode_info.crtcs[crtc]->vblank_timer.function =
+			dce_virtual_vblank_timer_handle;
+		hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer,
+			      DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
+	} else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
+		DRM_DEBUG("Disable software vsync timer\n");
+		hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer);
+	}
+
+	adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
+	DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
+}
+
+
+static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
+					  struct amdgpu_irq_src *source,
+					  unsigned type,
+					  enum amdgpu_interrupt_state state)
+{
+	if (type > AMDGPU_CRTC_IRQ_VBLANK6)
+		return -EINVAL;
+
+	dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
+
+	return 0;
+}
+
 static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
 	.set = dce_virtual_set_crtc_irq_state,
-	.process = dce_virtual_crtc_irq,
-};
-
-static const struct amdgpu_irq_src_funcs dce_virtual_pageflip_irq_funcs = {
-	.set = dce_virtual_set_pageflip_irq_state,
-	.process = dce_virtual_pageflip_irq,
+	.process = NULL,
 };
 
 static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
 {
 	adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
 	adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
-
-	adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
-	adev->pageflip_irq.funcs = &dce_virtual_pageflip_irq_funcs;
 }
 
+const struct amdgpu_ip_block_version dce_virtual_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_DCE,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &dce_virtual_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/dce_virtual.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,7 @@
 #ifndef __DCE_VIRTUAL_H__
 #define __DCE_VIRTUAL_H__
 
-extern const struct amd_ip_funcs dce_virtual_ip_funcs;
-#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
+extern const struct amdgpu_ip_block_version dce_virtual_ip_block;
 
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c	2016-12-11 17:41:53.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c	2017-02-12 17:25:00.000000000 -0500
@@ -26,15 +26,18 @@
 #include "amdgpu_gfx.h"
 #include "amdgpu_ucode.h"
 #include "si/clearstate_si.h"
-#include "si/sid.h"
-
-#define GFX6_NUM_GFX_RINGS     1
-#define GFX6_NUM_COMPUTE_RINGS 2
-#define STATIC_PER_CU_PG_ENABLE                    (1 << 3)
-#define DYN_PER_CU_PG_ENABLE                       (1 << 2)
-#define RLC_SAVE_AND_RESTORE_STARTING_OFFSET 0x90
-#define RLC_CLEAR_STATE_DESCRIPTOR_OFFSET    0x3D
-
+#include "bif/bif_3_0_d.h"
+#include "bif/bif_3_0_sh_mask.h"
+#include "oss/oss_1_0_d.h"
+#include "oss/oss_1_0_sh_mask.h"
+#include "gca/gfx_6_0_d.h"
+#include "gca/gfx_6_0_sh_mask.h"
+#include "gmc/gmc_6_0_d.h"
+#include "gmc/gmc_6_0_sh_mask.h"
+#include "dce/dce_6_0_d.h"
+#include "dce/dce_6_0_sh_mask.h"
+#include "gca/gfx_7_2_enum.h"
+#include "si_enums.h"
 
 static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev);
 static void gfx_v6_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -47,6 +50,15 @@ static void gfx_v6_0_get_csb_buffer(stru
 //static void gfx_v6_0_init_cp_pg_table(struct amdgpu_device *adev);
 static void gfx_v6_0_init_pg(struct amdgpu_device *adev);
 
+#define ARRAY_MODE(x)					((x) << GB_TILE_MODE0__ARRAY_MODE__SHIFT)
+#define PIPE_CONFIG(x)					((x) << GB_TILE_MODE0__PIPE_CONFIG__SHIFT)
+#define TILE_SPLIT(x)					((x) << GB_TILE_MODE0__TILE_SPLIT__SHIFT)
+#define MICRO_TILE_MODE(x)				((x) << 0)
+#define SAMPLE_SPLIT(x)					((x) << GB_TILE_MODE0__SAMPLE_SPLIT__SHIFT)
+#define BANK_WIDTH(x)					((x) << 14)
+#define BANK_HEIGHT(x)					((x) << 16)
+#define MACRO_TILE_ASPECT(x)				((x) << 18)
+#define NUM_BANKS(x)					((x) << 20)
 
 static const u32 verde_rlc_save_restore_register_list[] =
 {
@@ -376,487 +388,882 @@ static void gfx_v6_0_tiling_mode_table_i
 		break;
 	}
 
-	if (adev->asic_type == CHIP_VERDE ||
-		adev->asic_type == CHIP_OLAND ||
-		adev->asic_type == CHIP_HAINAN) {
+	if (adev->asic_type == CHIP_VERDE) {
 		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
 			switch (reg_offset) {
 			case 0:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 1: 
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 1:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
 			case 2:
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 3:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 3:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
 				break;
-			case 4:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 4:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16));
+				break;
+			case 5:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
 				break;
-			case 5:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 6:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
 				break;
-			case 6:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 7:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
-			case 7:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 8:
+				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED));
+				break;
+			case 9:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16));
+				break;
+			case 10:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 8: 
-				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 11:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 9:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 12:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 10:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 13:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16));
+				break;
+			case 14:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 11:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 15:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 12:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 16:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 17:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
 						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
+				break;
+			case 18:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16));
+				break;
+			case 19:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
 				break;
-			case 13:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 20:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THICK) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
 						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
+				break;
+			case 21:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
+				break;
+			case 22:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
 				break;
-			case 14:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 23:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
 				break;
-			case 15:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 24:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
 				break;
-			case 16:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 25:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 26:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 27:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 28:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 29:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 30:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			default:
+				continue;
+			}
+			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
+			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
+		}
+	} else if (adev->asic_type == CHIP_OLAND ||
+	    adev->asic_type == CHIP_HAINAN) {
+		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
+			switch (reg_offset) {
+			case 0:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 1:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 2:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 3:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
+				break;
+			case 4:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2));
+				break;
+			case 5:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
 				break;
-			case 17:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+			case 6:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
+				break;
+			case 7:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
+				break;
+			case 8:
+				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED));
+				break;
+			case 9:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2));
+				break;
+			case 10:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 11:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 12:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 21:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+			case 13:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2));
+				break;
+			case 14:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
-						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 22:  
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+			case 15:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 16:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
+				break;
+			case 17:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
 						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
+				break;
+			case 18:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+						 PIPE_CONFIG(ADDR_SURF_P2));
+				break;
+			case 19:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
+				break;
+			case 20:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THICK) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
+				break;
+			case 21:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
 				break;
-			case 23: 
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+			case 22:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
+				break;
+			case 23:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
 				break;
-			case 24: 
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+			case 24:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_8_BANK));
 				break;
-			case 25: 
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+			case 25:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
+				break;
+			case 26:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
+				break;
+			case 27:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
-						 NUM_BANKS(ADDR_SURF_8_BANK) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
+				break;
+			case 28:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
+				break;
+			case 29:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
+				break;
+			case 30:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P2) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
 				break;
 			default:
-				gb_tile_moden = 0;
-				break;
+				continue;
 			}
 			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(GB_TILE_MODE0 + reg_offset, gb_tile_moden);
+			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
 		}
 	} else if ((adev->asic_type == CHIP_TAHITI) || (adev->asic_type == CHIP_PITCAIRN)) {
 		for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) {
 			switch (reg_offset) {
-			case 0:  /* non-AA compressed depth or any compressed stencil */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 0:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 1:  /* 2xAA/4xAA compressed depth only */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 1:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 2:  /* 8xAA compressed depth only */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 2:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 3:  /* 2xAA/4xAA compressed depth with stencil (for depth buffer) */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 3:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
 				break;
-			case 4:  /* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
-						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+			case 4:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16));
 				break;
-			case 5:  /* Uncompressed 16bpp depth - and stencil buffer allocated with it */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 5:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
-			case 6:  /* Uncompressed 32bpp depth - and stencil buffer allocated with it */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+			case 6:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
-			case 7:  /* Uncompressed 8bpp stencil without depth (drivers typically do not use) */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
+			case 7:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
-			case 8:  /* 1D and 1D Array Surfaces */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
-						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+			case 8:
+				gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED));
 				break;
-			case 9:  /* Displayable maps. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
-						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+			case 9:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16));
 				break;
-			case 10:  /* Display 8bpp. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 10:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 11:  /* Display 16bpp. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 11:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 12:  /* Display 32bpp. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+			case 12:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 13:  /* Thin. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
-						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+			case 13:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16));
 				break;
-			case 14:  /* Thin 8 bpp. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 14:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 15:  /* Thin 16 bpp. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 15:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 16:  /* Thin 32 bpp. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 16:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_16_BANK));
 				break;
-			case 17:  /* Thin 64 bpp. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 17:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(split_equal_to_row_size) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
 						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
+				break;
+			case 18:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_1D_TILED_THICK) |
+						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16));
+				break;
+			case 19:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_XTHICK) |
+						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_16_BANK) |
+						 TILE_SPLIT(split_equal_to_row_size));
 				break;
-			case 21:  /* 8 bpp PRT. */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 20:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THICK) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
-						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
 						 NUM_BANKS(ADDR_SURF_16_BANK) |
-						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 TILE_SPLIT(split_equal_to_row_size));
 				break;
-			case 22:  /* 16 bpp PRT */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 21:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
+				break;
+			case 22:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
 						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4));
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_4_BANK));
 				break;
-			case 23:  /* 32 bpp PRT */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 23:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
-			case 24:  /* 64 bpp PRT */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+			case 24:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
-						 NUM_BANKS(ADDR_SURF_16_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
-			case 25:  /* 128 bpp PRT */
-				gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
-						 MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
-						 PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
+			case 25:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
 						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
-						 NUM_BANKS(ADDR_SURF_8_BANK) |
 						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
-						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
-						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
-			default:
-				gb_tile_moden = 0;
+			case 26:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 27:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 28:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
 				break;
+			case 29:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_1KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			case 30:
+				gb_tile_moden = (MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
+						 ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
+						 PIPE_CONFIG(ADDR_SURF_P4_8x16) |
+						 TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) |
+						 BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
+						 BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
+						 MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) |
+						 NUM_BANKS(ADDR_SURF_2_BANK));
+				break;
+			default:
+				continue;
 			}
 			adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden;
-			WREG32(GB_TILE_MODE0 + reg_offset, gb_tile_moden);
+			WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden);
 		}
 	} else{
 
@@ -871,19 +1278,23 @@ static void gfx_v6_0_select_se_sh(struct
 	u32 data;
 
 	if (instance == 0xffffffff)
-		data = INSTANCE_BROADCAST_WRITES;
+		data = REG_SET_FIELD(0, GRBM_GFX_INDEX, INSTANCE_BROADCAST_WRITES, 1);
 	else
-		data = INSTANCE_INDEX(instance);
+		data = REG_SET_FIELD(0, GRBM_GFX_INDEX, INSTANCE_INDEX, instance);
 
 	if ((se_num == 0xffffffff) && (sh_num == 0xffffffff))
-		data |= SH_BROADCAST_WRITES | SE_BROADCAST_WRITES;
+		data |= GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK |
+			GRBM_GFX_INDEX__SE_BROADCAST_WRITES_MASK;
 	else if (se_num == 0xffffffff)
-		data |= SE_BROADCAST_WRITES | SH_INDEX(sh_num);
+		data |= GRBM_GFX_INDEX__SE_BROADCAST_WRITES_MASK |
+			(sh_num << GRBM_GFX_INDEX__SH_INDEX__SHIFT);
 	else if (sh_num == 0xffffffff)
-		data |= SH_BROADCAST_WRITES | SE_INDEX(se_num);
+		data |= GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK |
+			(se_num << GRBM_GFX_INDEX__SE_INDEX__SHIFT);
 	else
-		data |= SH_INDEX(sh_num) | SE_INDEX(se_num);
-	WREG32(GRBM_GFX_INDEX, data);
+		data |= (sh_num << GRBM_GFX_INDEX__SH_INDEX__SHIFT) |
+			(se_num << GRBM_GFX_INDEX__SE_INDEX__SHIFT);
+	WREG32(mmGRBM_GFX_INDEX, data);
 }
 
 static u32 gfx_v6_0_create_bitmask(u32 bit_width)
@@ -897,11 +1308,11 @@ static u32 gfx_v6_0_get_rb_disabled(stru
 {
 	u32 data, mask;
 
-	data = RREG32(CC_RB_BACKEND_DISABLE);
-	data &= BACKEND_DISABLE_MASK;
-	data |= RREG32(GC_USER_RB_BACKEND_DISABLE);
+	data = RREG32(mmCC_RB_BACKEND_DISABLE);
+	data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK;
+	data |= RREG32(mmGC_USER_RB_BACKEND_DISABLE);
 
-	data >>= BACKEND_DISABLE_SHIFT;
+	data >>= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT;
 
 	mask = gfx_v6_0_create_bitmask(max_rb_num_per_se / sh_per_se);
 
@@ -913,14 +1324,23 @@ static void gfx_v6_0_raster_config(struc
 	switch (adev->asic_type) {
 	case CHIP_TAHITI:
 	case CHIP_PITCAIRN:
-		*rconf |= RB_XSEL2(2) | RB_XSEL | PKR_MAP(2) | PKR_YSEL(1) |
-			  SE_MAP(2) | SE_XSEL(2) | SE_YSEL(2);
+		*rconf |=
+			   (2 << PA_SC_RASTER_CONFIG__RB_XSEL2__SHIFT) |
+			   (1 << PA_SC_RASTER_CONFIG__RB_XSEL__SHIFT) |
+			   (2 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT) |
+			   (1 << PA_SC_RASTER_CONFIG__PKR_YSEL__SHIFT) |
+			   (2 << PA_SC_RASTER_CONFIG__SE_MAP__SHIFT) |
+			   (2 << PA_SC_RASTER_CONFIG__SE_XSEL__SHIFT) |
+			   (2 << PA_SC_RASTER_CONFIG__SE_YSEL__SHIFT);
 		break;
 	case CHIP_VERDE:
-		*rconf |= RB_XSEL | PKR_MAP(2) | PKR_YSEL(1);
+		*rconf |=
+			   (1 << PA_SC_RASTER_CONFIG__RB_XSEL__SHIFT) |
+			   (2 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT) |
+			   (1 << PA_SC_RASTER_CONFIG__PKR_YSEL__SHIFT);
 		break;
 	case CHIP_OLAND:
-		*rconf |= RB_YSEL;
+		*rconf |= (1 << PA_SC_RASTER_CONFIG__RB_YSEL__SHIFT);
 		break;
 	case CHIP_HAINAN:
 		*rconf |= 0x0;
@@ -958,24 +1378,24 @@ static void gfx_v6_0_write_harvested_ras
 		int idx = (se / 2) * 2;
 
 		if ((num_se > 1) && (!se_mask[idx] || !se_mask[idx + 1])) {
-			raster_config_se &= ~SE_MAP_MASK;
+			raster_config_se &= ~PA_SC_RASTER_CONFIG__SE_MAP_MASK;
 
 			if (!se_mask[idx]) {
-				raster_config_se |= SE_MAP(RASTER_CONFIG_SE_MAP_3);
+				raster_config_se |= RASTER_CONFIG_SE_MAP_3 << PA_SC_RASTER_CONFIG__SE_MAP__SHIFT;
 			} else {
-				raster_config_se |= SE_MAP(RASTER_CONFIG_SE_MAP_0);
+				raster_config_se |= RASTER_CONFIG_SE_MAP_0 << PA_SC_RASTER_CONFIG__SE_MAP__SHIFT;
 			}
 		}
 
 		pkr0_mask &= rb_mask;
 		pkr1_mask &= rb_mask;
 		if (rb_per_se > 2 && (!pkr0_mask || !pkr1_mask)) {
-			raster_config_se &= ~PKR_MAP_MASK;
+			raster_config_se &= ~PA_SC_RASTER_CONFIG__PKR_MAP_MASK;
 
 			if (!pkr0_mask) {
-				raster_config_se |= PKR_MAP(RASTER_CONFIG_PKR_MAP_3);
+				raster_config_se |= RASTER_CONFIG_PKR_MAP_3 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT;
 			} else {
-				raster_config_se |= PKR_MAP(RASTER_CONFIG_PKR_MAP_0);
+				raster_config_se |= RASTER_CONFIG_PKR_MAP_0 << PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT;
 			}
 		}
 
@@ -986,14 +1406,14 @@ static void gfx_v6_0_write_harvested_ras
 			rb0_mask &= rb_mask;
 			rb1_mask &= rb_mask;
 			if (!rb0_mask || !rb1_mask) {
-				raster_config_se &= ~RB_MAP_PKR0_MASK;
+				raster_config_se &= ~PA_SC_RASTER_CONFIG__RB_MAP_PKR0_MASK;
 
 				if (!rb0_mask) {
 					raster_config_se |=
-						RB_MAP_PKR0(RASTER_CONFIG_RB_MAP_3);
+						RASTER_CONFIG_RB_MAP_3 << PA_SC_RASTER_CONFIG__RB_MAP_PKR0__SHIFT;
 				} else {
 					raster_config_se |=
-						RB_MAP_PKR0(RASTER_CONFIG_RB_MAP_0);
+						RASTER_CONFIG_RB_MAP_0 << PA_SC_RASTER_CONFIG__RB_MAP_PKR0__SHIFT;
 				}
 			}
 
@@ -1003,14 +1423,14 @@ static void gfx_v6_0_write_harvested_ras
 				rb0_mask &= rb_mask;
 				rb1_mask &= rb_mask;
 				if (!rb0_mask || !rb1_mask) {
-					raster_config_se &= ~RB_MAP_PKR1_MASK;
+					raster_config_se &= ~PA_SC_RASTER_CONFIG__RB_MAP_PKR1_MASK;
 
 					if (!rb0_mask) {
 						raster_config_se |=
-							RB_MAP_PKR1(RASTER_CONFIG_RB_MAP_3);
+							RASTER_CONFIG_RB_MAP_3 << PA_SC_RASTER_CONFIG__RB_MAP_PKR1__SHIFT;
 					} else {
 						raster_config_se |=
-							RB_MAP_PKR1(RASTER_CONFIG_RB_MAP_0);
+							RASTER_CONFIG_RB_MAP_0 << PA_SC_RASTER_CONFIG__RB_MAP_PKR1__SHIFT;
 					}
 				}
 			}
@@ -1018,7 +1438,7 @@ static void gfx_v6_0_write_harvested_ras
 
 		/* GRBM_GFX_INDEX has a different offset on SI */
 		gfx_v6_0_select_se_sh(adev, se, 0xffffffff, 0xffffffff);
-		WREG32(PA_SC_RASTER_CONFIG, raster_config_se);
+		WREG32(mmPA_SC_RASTER_CONFIG, raster_config_se);
 	}
 
 	/* GRBM_GFX_INDEX has a different offset on SI */
@@ -1040,7 +1460,7 @@ static void gfx_v6_0_setup_rb(struct amd
 		for (j = 0; j < sh_per_se; j++) {
 			gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
 			data = gfx_v6_0_get_rb_disabled(adev, max_rb_num_per_se, sh_per_se);
-			disabled_rbs |= data << ((i * sh_per_se + j) * TAHITI_RB_BITMAP_WIDTH_PER_SH);
+			disabled_rbs |= data << ((i * sh_per_se + j) * 2);
 		}
 	}
 	gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
@@ -1082,7 +1502,7 @@ static void gfx_v6_0_setup_rb(struct amd
 
 		if (!adev->gfx.config.backend_enable_mask ||
 				adev->gfx.config.num_rbs >= num_rb_pipes)
-			WREG32(PA_SC_RASTER_CONFIG, data);
+			WREG32(mmPA_SC_RASTER_CONFIG, data);
 		else
 			gfx_v6_0_write_harvested_raster_configs(adev, data,
 								adev->gfx.config.backend_enable_mask,
@@ -1101,11 +1521,11 @@ static u32 gfx_v6_0_get_cu_enabled(struc
 {
 	u32 data, mask;
 
-	data = RREG32(CC_GC_SHADER_ARRAY_CONFIG);
-	data &= INACTIVE_CUS_MASK;
-	data |= RREG32(GC_USER_SHADER_ARRAY_CONFIG);
+	data = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG);
+	data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
+	data |= RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
 
-	data >>= INACTIVE_CUS_SHIFT;
+	data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
 
 	mask = gfx_v6_0_create_bitmask(cu_per_sh);
 
@@ -1125,7 +1545,7 @@ static void gfx_v6_0_setup_spi(struct am
 	for (i = 0; i < se_num; i++) {
 		for (j = 0; j < sh_per_se; j++) {
 			gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
-			data = RREG32(SPI_STATIC_THREAD_MGMT_3);
+			data = RREG32(mmSPI_STATIC_THREAD_MGMT_3);
 			active_cu = gfx_v6_0_get_cu_enabled(adev, cu_per_sh);
 
 			mask = 1;
@@ -1133,7 +1553,7 @@ static void gfx_v6_0_setup_spi(struct am
 				mask <<= k;
 				if (active_cu & mask) {
 					data &= ~mask;
-					WREG32(SPI_STATIC_THREAD_MGMT_3, data);
+					WREG32(mmSPI_STATIC_THREAD_MGMT_3, data);
 					break;
 				}
 			}
@@ -1186,7 +1606,6 @@ static void gfx_v6_0_gpu_init(struct amd
 		adev->gfx.config.sc_earlyz_tile_fifo_size = 0x130;
 		gb_addr_config = TAHITI_GB_ADDR_CONFIG_GOLDEN;
 		break;
-
 	case CHIP_VERDE:
 		adev->gfx.config.max_shader_engines = 1;
 		adev->gfx.config.max_tile_pipes = 4;
@@ -1243,18 +1662,18 @@ static void gfx_v6_0_gpu_init(struct amd
 		break;
 	}
 
-	WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
-	WREG32(SRBM_INT_CNTL, 1);
-	WREG32(SRBM_INT_ACK, 1);
+	WREG32(mmGRBM_CNTL, (0xff << GRBM_CNTL__READ_TIMEOUT__SHIFT));
+	WREG32(mmSRBM_INT_CNTL, 1);
+	WREG32(mmSRBM_INT_ACK, 1);
 
-	WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
+	WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK);
 
-	mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
-	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
+	mc_shared_chmap = RREG32(mmMC_SHARED_CHMAP);
+	mc_arb_ramcfg = RREG32(mmMC_ARB_RAMCFG);
 
 	adev->gfx.config.num_tile_pipes = adev->gfx.config.max_tile_pipes;
 	adev->gfx.config.mem_max_burst_length_bytes = 256;
-	tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT;
+	tmp = (mc_arb_ramcfg & MC_ARB_RAMCFG__NOOFCOLS_MASK) >> MC_ARB_RAMCFG__NOOFCOLS__SHIFT;
 	adev->gfx.config.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
 	if (adev->gfx.config.mem_row_size_in_kb > 4)
 		adev->gfx.config.mem_row_size_in_kb = 4;
@@ -1262,32 +1681,33 @@ static void gfx_v6_0_gpu_init(struct amd
 	adev->gfx.config.num_gpus = 1;
 	adev->gfx.config.multi_gpu_tile_size = 64;
 
-	gb_addr_config &= ~ROW_SIZE_MASK;
+	gb_addr_config &= ~GB_ADDR_CONFIG__ROW_SIZE_MASK;
 	switch (adev->gfx.config.mem_row_size_in_kb) {
 	case 1:
 	default:
-		gb_addr_config |= ROW_SIZE(0);
+		gb_addr_config |= 0 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
 		break;
 	case 2:
-		gb_addr_config |= ROW_SIZE(1);
+		gb_addr_config |= 1 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
 		break;
 	case 4:
-		gb_addr_config |= ROW_SIZE(2);
+		gb_addr_config |= 2 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
 		break;
 	}
 	adev->gfx.config.gb_addr_config = gb_addr_config;
 
-	WREG32(GB_ADDR_CONFIG, gb_addr_config);
-	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
-	WREG32(DMIF_ADDR_CALC, gb_addr_config);
-	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
-	WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
-	WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
+	WREG32(mmGB_ADDR_CONFIG, gb_addr_config);
+	WREG32(mmDMIF_ADDR_CONFIG, gb_addr_config);
+	WREG32(mmDMIF_ADDR_CALC, gb_addr_config);
+	WREG32(mmHDP_ADDR_CONFIG, gb_addr_config);
+	WREG32(mmDMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
+	WREG32(mmDMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
+
 #if 0
 	if (adev->has_uvd) {
-		WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
-		WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
-		WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
+		WREG32(mmUVD_UDEC_ADDR_CONFIG, gb_addr_config);
+		WREG32(mmUVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
+		WREG32(mmUVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);
 	}
 #endif
 	gfx_v6_0_tiling_mode_table_init(adev);
@@ -1302,45 +1722,48 @@ static void gfx_v6_0_gpu_init(struct amd
 
 	gfx_v6_0_get_cu_info(adev);
 
-	WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) |
-				     ROQ_IB2_START(0x2b)));
-	WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
+	WREG32(mmCP_QUEUE_THRESHOLDS, ((0x16 << CP_QUEUE_THRESHOLDS__ROQ_IB1_START__SHIFT) |
+				       (0x2b << CP_QUEUE_THRESHOLDS__ROQ_IB2_START__SHIFT)));
+	WREG32(mmCP_MEQ_THRESHOLDS, (0x30 << CP_MEQ_THRESHOLDS__MEQ1_START__SHIFT) |
+				    (0x60 << CP_MEQ_THRESHOLDS__MEQ2_START__SHIFT));
 
-	sx_debug_1 = RREG32(SX_DEBUG_1);
-	WREG32(SX_DEBUG_1, sx_debug_1);
+	sx_debug_1 = RREG32(mmSX_DEBUG_1);
+	WREG32(mmSX_DEBUG_1, sx_debug_1);
 
-	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4));
+	WREG32(mmSPI_CONFIG_CNTL_1, (4 << SPI_CONFIG_CNTL_1__VTX_DONE_DELAY__SHIFT));
 
-	WREG32(PA_SC_FIFO_SIZE, (SC_FRONTEND_PRIM_FIFO_SIZE(adev->gfx.config.sc_prim_fifo_size_frontend) |
-				 SC_BACKEND_PRIM_FIFO_SIZE(adev->gfx.config.sc_prim_fifo_size_backend) |
-				 SC_HIZ_TILE_FIFO_SIZE(adev->gfx.config.sc_hiz_tile_fifo_size) |
-				 SC_EARLYZ_TILE_FIFO_SIZE(adev->gfx.config.sc_earlyz_tile_fifo_size)));
+	WREG32(mmPA_SC_FIFO_SIZE, ((adev->gfx.config.sc_prim_fifo_size_frontend << PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT) |
+				   (adev->gfx.config.sc_prim_fifo_size_backend << PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE__SHIFT) |
+				   (adev->gfx.config.sc_hiz_tile_fifo_size << PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE__SHIFT) |
+				   (adev->gfx.config.sc_earlyz_tile_fifo_size << PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE__SHIFT)));
 
-	WREG32(VGT_NUM_INSTANCES, 1);
-	WREG32(CP_PERFMON_CNTL, 0);
-	WREG32(SQ_CONFIG, 0);
-	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
-					  FORCE_EOV_MAX_REZ_CNT(255)));
+	WREG32(mmVGT_NUM_INSTANCES, 1);
+	WREG32(mmCP_PERFMON_CNTL, 0);
+	WREG32(mmSQ_CONFIG, 0);
+	WREG32(mmPA_SC_FORCE_EOV_MAX_CNTS, ((4095 << PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT__SHIFT) |
+					  (255 << PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT__SHIFT)));
 
-	WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) |
-	       AUTO_INVLD_EN(ES_AND_GS_AUTO));
+	WREG32(mmVGT_CACHE_INVALIDATION,
+		(VC_AND_TC << VGT_CACHE_INVALIDATION__CACHE_INVALIDATION__SHIFT) |
+		(ES_AND_GS_AUTO << VGT_CACHE_INVALIDATION__AUTO_INVLD_EN__SHIFT));
 
-	WREG32(VGT_GS_VERTEX_REUSE, 16);
-	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
+	WREG32(mmVGT_GS_VERTEX_REUSE, 16);
+	WREG32(mmPA_SC_LINE_STIPPLE_STATE, 0);
 
-	WREG32(CB_PERFCOUNTER0_SELECT0, 0);
-	WREG32(CB_PERFCOUNTER0_SELECT1, 0);
-	WREG32(CB_PERFCOUNTER1_SELECT0, 0);
-	WREG32(CB_PERFCOUNTER1_SELECT1, 0);
-	WREG32(CB_PERFCOUNTER2_SELECT0, 0);
-	WREG32(CB_PERFCOUNTER2_SELECT1, 0);
-	WREG32(CB_PERFCOUNTER3_SELECT0, 0);
-	WREG32(CB_PERFCOUNTER3_SELECT1, 0);
+	WREG32(mmCB_PERFCOUNTER0_SELECT0, 0);
+	WREG32(mmCB_PERFCOUNTER0_SELECT1, 0);
+	WREG32(mmCB_PERFCOUNTER1_SELECT0, 0);
+	WREG32(mmCB_PERFCOUNTER1_SELECT1, 0);
+	WREG32(mmCB_PERFCOUNTER2_SELECT0, 0);
+	WREG32(mmCB_PERFCOUNTER2_SELECT1, 0);
+	WREG32(mmCB_PERFCOUNTER3_SELECT0, 0);
+	WREG32(mmCB_PERFCOUNTER3_SELECT1, 0);
 
-	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
-	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
+	hdp_host_path_cntl = RREG32(mmHDP_HOST_PATH_CNTL);
+	WREG32(mmHDP_HOST_PATH_CNTL, hdp_host_path_cntl);
 
-	WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
+	WREG32(mmPA_CL_ENHANCE, PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA_MASK |
+				(3 << PA_CL_ENHANCE__NUM_CLIP_SEQ__SHIFT));
 
 	udelay(50);
 }
@@ -1351,7 +1774,7 @@ static void gfx_v6_0_scratch_init(struct
 	int i;
 
 	adev->gfx.scratch.num_reg = 7;
-	adev->gfx.scratch.reg_base = SCRATCH_REG0;
+	adev->gfx.scratch.reg_base = mmSCRATCH_REG0;
 	for (i = 0; i < adev->gfx.scratch.num_reg; i++) {
 		adev->gfx.scratch.free[i] = true;
 		adev->gfx.scratch.reg[i] = adev->gfx.scratch.reg_base + i;
@@ -1407,11 +1830,18 @@ static void gfx_v6_0_ring_emit_hdp_flush
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
 				 WRITE_DATA_DST_SEL(0)));
-	amdgpu_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL);
+	amdgpu_ring_write(ring, mmHDP_MEM_COHERENCY_FLUSH_CNTL);
 	amdgpu_ring_write(ring, 0);
 	amdgpu_ring_write(ring, 0x1);
 }
 
+static void gfx_v6_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
+{
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+		EVENT_INDEX(0));
+}
+
 /**
  * gfx_v6_0_ring_emit_hdp_invalidate - emit an hdp invalidate on the cp
  *
@@ -1425,7 +1855,7 @@ static void gfx_v6_0_ring_emit_hdp_inval
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
 				 WRITE_DATA_DST_SEL(0)));
-	amdgpu_ring_write(ring, HDP_DEBUG0);
+	amdgpu_ring_write(ring, mmHDP_DEBUG0);
 	amdgpu_ring_write(ring, 0);
 	amdgpu_ring_write(ring, 0x1);
 }
@@ -1437,7 +1867,7 @@ static void gfx_v6_0_ring_emit_fence(str
 	bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
 	/* flush read cache over gart */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
-	amdgpu_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START));
+	amdgpu_ring_write(ring, (mmCP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START));
 	amdgpu_ring_write(ring, 0);
 	amdgpu_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
 	amdgpu_ring_write(ring, PACKET3_TCL1_ACTION_ENA |
@@ -1452,7 +1882,8 @@ static void gfx_v6_0_ring_emit_fence(str
 	amdgpu_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5));
 	amdgpu_ring_write(ring, addr & 0xfffffffc);
 	amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
-				DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
+				((write64bit ? 2 : 1) << CP_EOP_DONE_DATA_CNTL__DATA_SEL__SHIFT) |
+				((int_sel ? 2 : 0) << CP_EOP_DONE_DATA_CNTL__INT_SEL__SHIFT));
 	amdgpu_ring_write(ring, lower_32_bits(seq));
 	amdgpu_ring_write(ring, upper_32_bits(seq));
 }
@@ -1499,7 +1930,7 @@ static int gfx_v6_0_ring_test_ib(struct
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	uint32_t scratch;
 	uint32_t tmp = 0;
 	long r;
@@ -1525,7 +1956,7 @@ static int gfx_v6_0_ring_test_ib(struct
 	if (r)
 		goto err2;
 
-	r = fence_wait_timeout(f, false, timeout);
+	r = dma_fence_wait_timeout(f, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out\n");
 		r = -ETIMEDOUT;
@@ -1546,7 +1977,7 @@ static int gfx_v6_0_ring_test_ib(struct
 
 err2:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 err1:
 	amdgpu_gfx_scratch_free(adev, scratch);
 	return r;
@@ -1555,11 +1986,13 @@ err1:
 static void gfx_v6_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
 {
 	int i;
-	if (enable)
-		WREG32(CP_ME_CNTL, 0);
-	else {
-		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT));
-		WREG32(SCRATCH_UMSK, 0);
+	if (enable) {
+		WREG32(mmCP_ME_CNTL, 0);
+	} else {
+		WREG32(mmCP_ME_CNTL, (CP_ME_CNTL__ME_HALT_MASK |
+				      CP_ME_CNTL__PFP_HALT_MASK |
+				      CP_ME_CNTL__CE_HALT_MASK));
+		WREG32(mmSCRATCH_UMSK, 0);
 		for (i = 0; i < adev->gfx.num_gfx_rings; i++)
 			adev->gfx.gfx_ring[i].ready = false;
 		for (i = 0; i < adev->gfx.num_compute_rings; i++)
@@ -1593,34 +2026,33 @@ static int gfx_v6_0_cp_gfx_load_microcod
 	fw_data = (const __le32 *)
 		(adev->gfx.pfp_fw->data + le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
 	fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
-	WREG32(CP_PFP_UCODE_ADDR, 0);
+	WREG32(mmCP_PFP_UCODE_ADDR, 0);
 	for (i = 0; i < fw_size; i++)
-		WREG32(CP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
-	WREG32(CP_PFP_UCODE_ADDR, 0);
+		WREG32(mmCP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
+	WREG32(mmCP_PFP_UCODE_ADDR, 0);
 
 	/* CE */
 	fw_data = (const __le32 *)
 		(adev->gfx.ce_fw->data + le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
 	fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
-	WREG32(CP_CE_UCODE_ADDR, 0);
+	WREG32(mmCP_CE_UCODE_ADDR, 0);
 	for (i = 0; i < fw_size; i++)
-		WREG32(CP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
-	WREG32(CP_CE_UCODE_ADDR, 0);
+		WREG32(mmCP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
+	WREG32(mmCP_CE_UCODE_ADDR, 0);
 
 	/* ME */
 	fw_data = (const __be32 *)
 		(adev->gfx.me_fw->data + le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
 	fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
-	WREG32(CP_ME_RAM_WADDR, 0);
+	WREG32(mmCP_ME_RAM_WADDR, 0);
 	for (i = 0; i < fw_size; i++)
-		WREG32(CP_ME_RAM_DATA, le32_to_cpup(fw_data++));
-	WREG32(CP_ME_RAM_WADDR, 0);
-
+		WREG32(mmCP_ME_RAM_DATA, le32_to_cpup(fw_data++));
+	WREG32(mmCP_ME_RAM_WADDR, 0);
 
-	WREG32(CP_PFP_UCODE_ADDR, 0);
-	WREG32(CP_CE_UCODE_ADDR, 0);
-	WREG32(CP_ME_RAM_WADDR, 0);
-	WREG32(CP_ME_RAM_RADDR, 0);
+	WREG32(mmCP_PFP_UCODE_ADDR, 0);
+	WREG32(mmCP_CE_UCODE_ADDR, 0);
+	WREG32(mmCP_ME_RAM_WADDR, 0);
+	WREG32(mmCP_ME_RAM_RADDR, 0);
 	return 0;
 }
 
@@ -1697,14 +2129,14 @@ static int gfx_v6_0_cp_gfx_resume(struct
 	int r;
 	u64 rptr_addr;
 
-	WREG32(CP_SEM_WAIT_TIMER, 0x0);
-	WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
+	WREG32(mmCP_SEM_WAIT_TIMER, 0x0);
+	WREG32(mmCP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
 
 	/* Set the write pointer delay */
-	WREG32(CP_RB_WPTR_DELAY, 0);
+	WREG32(mmCP_RB_WPTR_DELAY, 0);
 
-	WREG32(CP_DEBUG, 0);
-	WREG32(SCRATCH_ADDR, 0);
+	WREG32(mmCP_DEBUG, 0);
+	WREG32(mmSCRATCH_ADDR, 0);
 
 	/* ring 0 - compute and gfx */
 	/* Set ring buffer size */
@@ -1715,24 +2147,24 @@ static int gfx_v6_0_cp_gfx_resume(struct
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
-	WREG32(CP_RB0_CNTL, tmp);
+	WREG32(mmCP_RB0_CNTL, tmp);
 
 	/* Initialize the ring buffer's read and write pointers */
-	WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(mmCP_RB0_CNTL, tmp | CP_RB0_CNTL__RB_RPTR_WR_ENA_MASK);
 	ring->wptr = 0;
-	WREG32(CP_RB0_WPTR, ring->wptr);
+	WREG32(mmCP_RB0_WPTR, ring->wptr);
 
 	/* set the wb address whether it's enabled or not */
 	rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
-	WREG32(CP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
-	WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+	WREG32(mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
+	WREG32(mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
 
-	WREG32(SCRATCH_UMSK, 0);
+	WREG32(mmSCRATCH_UMSK, 0);
 
 	mdelay(1);
-	WREG32(CP_RB0_CNTL, tmp);
+	WREG32(mmCP_RB0_CNTL, tmp);
 
-	WREG32(CP_RB0_BASE, ring->gpu_addr >> 8);
+	WREG32(mmCP_RB0_BASE, ring->gpu_addr >> 8);
 
 	/* start the rings */
 	gfx_v6_0_cp_gfx_start(adev);
@@ -1756,11 +2188,11 @@ static u32 gfx_v6_0_ring_get_wptr(struct
 	struct amdgpu_device *adev = ring->adev;
 
 	if (ring == &adev->gfx.gfx_ring[0])
-		return RREG32(CP_RB0_WPTR);
+		return RREG32(mmCP_RB0_WPTR);
 	else if (ring == &adev->gfx.compute_ring[0])
-		return RREG32(CP_RB1_WPTR);
+		return RREG32(mmCP_RB1_WPTR);
 	else if (ring == &adev->gfx.compute_ring[1])
-		return RREG32(CP_RB2_WPTR);
+		return RREG32(mmCP_RB2_WPTR);
 	else
 		BUG();
 }
@@ -1769,8 +2201,8 @@ static void gfx_v6_0_ring_set_wptr_gfx(s
 {
 	struct amdgpu_device *adev = ring->adev;
 
-	WREG32(CP_RB0_WPTR, ring->wptr);
-	(void)RREG32(CP_RB0_WPTR);
+	WREG32(mmCP_RB0_WPTR, ring->wptr);
+	(void)RREG32(mmCP_RB0_WPTR);
 }
 
 static void gfx_v6_0_ring_set_wptr_compute(struct amdgpu_ring *ring)
@@ -1778,11 +2210,11 @@ static void gfx_v6_0_ring_set_wptr_compu
 	struct amdgpu_device *adev = ring->adev;
 
 	if (ring == &adev->gfx.compute_ring[0]) {
-		WREG32(CP_RB1_WPTR, ring->wptr);
-		(void)RREG32(CP_RB1_WPTR);
+		WREG32(mmCP_RB1_WPTR, ring->wptr);
+		(void)RREG32(mmCP_RB1_WPTR);
 	} else if (ring == &adev->gfx.compute_ring[1]) {
-		WREG32(CP_RB2_WPTR, ring->wptr);
-		(void)RREG32(CP_RB2_WPTR);
+		WREG32(mmCP_RB2_WPTR, ring->wptr);
+		(void)RREG32(mmCP_RB2_WPTR);
 	} else {
 		BUG();
 	}
@@ -1794,7 +2226,7 @@ static int gfx_v6_0_cp_compute_resume(st
 	struct amdgpu_ring *ring;
 	u32 tmp;
 	u32 rb_bufsz;
-	int r;
+	int i, r;
 	u64 rptr_addr;
 
 	/* ring1  - compute only */
@@ -1806,19 +2238,19 @@ static int gfx_v6_0_cp_compute_resume(st
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
-	WREG32(CP_RB1_CNTL, tmp);
+	WREG32(mmCP_RB1_CNTL, tmp);
 
-	WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(mmCP_RB1_CNTL, tmp | CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK);
 	ring->wptr = 0;
-	WREG32(CP_RB1_WPTR, ring->wptr);
+	WREG32(mmCP_RB1_WPTR, ring->wptr);
 
 	rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
-	WREG32(CP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
-	WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+	WREG32(mmCP_RB1_RPTR_ADDR, lower_32_bits(rptr_addr));
+	WREG32(mmCP_RB1_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
 
 	mdelay(1);
-	WREG32(CP_RB1_CNTL, tmp);
-	WREG32(CP_RB1_BASE, ring->gpu_addr >> 8);
+	WREG32(mmCP_RB1_CNTL, tmp);
+	WREG32(mmCP_RB1_BASE, ring->gpu_addr >> 8);
 
 	ring = &adev->gfx.compute_ring[1];
 	rb_bufsz = order_base_2(ring->ring_size / 8);
@@ -1826,32 +2258,27 @@ static int gfx_v6_0_cp_compute_resume(st
 #ifdef __BIG_ENDIAN
 	tmp |= BUF_SWAP_32BIT;
 #endif
-	WREG32(CP_RB2_CNTL, tmp);
+	WREG32(mmCP_RB2_CNTL, tmp);
 
-	WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(mmCP_RB2_CNTL, tmp | CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK);
 	ring->wptr = 0;
-	WREG32(CP_RB2_WPTR, ring->wptr);
+	WREG32(mmCP_RB2_WPTR, ring->wptr);
 	rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
-	WREG32(CP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr));
-	WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
+	WREG32(mmCP_RB2_RPTR_ADDR, lower_32_bits(rptr_addr));
+	WREG32(mmCP_RB2_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
 
 	mdelay(1);
-	WREG32(CP_RB2_CNTL, tmp);
-	WREG32(CP_RB2_BASE, ring->gpu_addr >> 8);
-
-	adev->gfx.compute_ring[0].ready = true;
-	adev->gfx.compute_ring[1].ready = true;
+	WREG32(mmCP_RB2_CNTL, tmp);
+	WREG32(mmCP_RB2_BASE, ring->gpu_addr >> 8);
 
-	r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[0]);
-	if (r) {
-		adev->gfx.compute_ring[0].ready = false;
-		return r;
-	}
+	adev->gfx.compute_ring[0].ready = false;
+	adev->gfx.compute_ring[1].ready = false;
 
-	r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[1]);
-	if (r) {
-		adev->gfx.compute_ring[1].ready = false;
-		return r;
+	for (i = 0; i < 2; i++) {
+		r = amdgpu_ring_test_ring(&adev->gfx.compute_ring[i]);
+		if (r)
+			return r;
+		adev->gfx.compute_ring[i].ready = true;
 	}
 
 	return 0;
@@ -1869,24 +2296,26 @@ static int gfx_v6_0_cp_load_microcode(st
 
 static void gfx_v6_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
 					       bool enable)
-{	
-	u32 tmp = RREG32(CP_INT_CNTL_RING0);
+{
+	u32 tmp = RREG32(mmCP_INT_CNTL_RING0);
 	u32 mask;
 	int i;
 
 	if (enable)
-		tmp |= (CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
+		tmp |= (CP_INT_CNTL__CNTX_BUSY_INT_ENABLE_MASK |
+			CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE_MASK);
 	else
-		tmp &= ~(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
-	WREG32(CP_INT_CNTL_RING0, tmp);
+		tmp &= ~(CP_INT_CNTL__CNTX_BUSY_INT_ENABLE_MASK |
+			 CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE_MASK);
+	WREG32(mmCP_INT_CNTL_RING0, tmp);
 
 	if (!enable) {
 		/* read a gfx register */
-		tmp = RREG32(DB_DEPTH_INFO);
+		tmp = RREG32(mmDB_DEPTH_INFO);
 
 		mask = RLC_BUSY_STATUS | GFX_POWER_STATUS | GFX_CLOCK_STATUS | GFX_LS_STATUS;
 		for (i = 0; i < adev->usec_timeout; i++) {
-			if ((RREG32(RLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS))
+			if ((RREG32(mmRLC_STAT) & mask) == (GFX_CLOCK_STATUS | GFX_POWER_STATUS))
 				break;
 			udelay(1);
 		}
@@ -1917,7 +2346,7 @@ static int gfx_v6_0_cp_resume(struct amd
 
 static void gfx_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 {
-	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
 	uint32_t seq = ring->fence_drv.sync_seq;
 	uint64_t addr = ring->fence_drv.gpu_addr;
 
@@ -1943,16 +2372,16 @@ static void gfx_v6_0_ring_emit_pipeline_
 static void gfx_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 					unsigned vm_id, uint64_t pd_addr)
 {
-	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
 
 	/* write new base address */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
 				 WRITE_DATA_DST_SEL(0)));
 	if (vm_id < 8) {
-		amdgpu_ring_write(ring, (VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id ));
+		amdgpu_ring_write(ring, (mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + vm_id ));
 	} else {
-		amdgpu_ring_write(ring, (VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (vm_id - 8)));
+		amdgpu_ring_write(ring, (mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + (vm_id - 8)));
 	}
 	amdgpu_ring_write(ring, 0);
 	amdgpu_ring_write(ring, pd_addr >> 12);
@@ -1961,7 +2390,7 @@ static void gfx_v6_0_ring_emit_vm_flush(
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(1) |
 				 WRITE_DATA_DST_SEL(0)));
-	amdgpu_ring_write(ring, VM_INVALIDATE_REQUEST);
+	amdgpu_ring_write(ring, mmVM_INVALIDATE_REQUEST);
 	amdgpu_ring_write(ring, 0);
 	amdgpu_ring_write(ring, 1 << vm_id);
 
@@ -1969,7 +2398,7 @@ static void gfx_v6_0_ring_emit_vm_flush(
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WAIT_REG_MEM, 5));
 	amdgpu_ring_write(ring, (WAIT_REG_MEM_FUNCTION(0) |  /* always */
 				 WAIT_REG_MEM_ENGINE(0))); /* me */
-	amdgpu_ring_write(ring, VM_INVALIDATE_REQUEST);
+	amdgpu_ring_write(ring, mmVM_INVALIDATE_REQUEST);
 	amdgpu_ring_write(ring, 0);
 	amdgpu_ring_write(ring, 0); /* ref */
 	amdgpu_ring_write(ring, 0); /* mask */
@@ -2048,7 +2477,6 @@ static int gfx_v6_0_rlc_init(struct amdg
 	if (src_ptr) {
 		/* save restore block */
 		if (adev->gfx.rlc.save_restore_obj == NULL) {
-
 			r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
 					     AMDGPU_GEM_DOMAIN_VRAM,
 					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
@@ -2143,20 +2571,12 @@ static int gfx_v6_0_rlc_init(struct amdg
 
 static void gfx_v6_0_enable_lbpw(struct amdgpu_device *adev, bool enable)
 {
-	u32 tmp;
-
-	tmp = RREG32(RLC_LB_CNTL);
-	if (enable)
-		tmp |= LOAD_BALANCE_ENABLE;
-	else
-		tmp &= ~LOAD_BALANCE_ENABLE;
-	WREG32(RLC_LB_CNTL, tmp);
+	WREG32_FIELD(RLC_LB_CNTL, LOAD_BALANCE_ENABLE, enable ? 1 : 0);
 
 	if (!enable) {
 		gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
-		WREG32(SPI_LB_CU_MASK, 0x00ff);
+		WREG32(mmSPI_LB_CU_MASK, 0x00ff);
 	}
-
 }
 
 static void gfx_v6_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
@@ -2164,13 +2584,13 @@ static void gfx_v6_0_wait_for_rlc_serdes
 	int i;
 
 	for (i = 0; i < adev->usec_timeout; i++) {
-		if (RREG32(RLC_SERDES_MASTER_BUSY_0) == 0)
+		if (RREG32(mmRLC_SERDES_MASTER_BUSY_0) == 0)
 			break;
 		udelay(1);
 	}
 
 	for (i = 0; i < adev->usec_timeout; i++) {
-		if (RREG32(RLC_SERDES_MASTER_BUSY_1) == 0)
+		if (RREG32(mmRLC_SERDES_MASTER_BUSY_1) == 0)
 			break;
 		udelay(1);
 	}
@@ -2180,20 +2600,20 @@ static void gfx_v6_0_update_rlc(struct a
 {
 	u32 tmp;
 
-	tmp = RREG32(RLC_CNTL);
+	tmp = RREG32(mmRLC_CNTL);
 	if (tmp != rlc)
-		WREG32(RLC_CNTL, rlc);
+		WREG32(mmRLC_CNTL, rlc);
 }
 
 static u32 gfx_v6_0_halt_rlc(struct amdgpu_device *adev)
 {
 	u32 data, orig;
 
-	orig = data = RREG32(RLC_CNTL);
+	orig = data = RREG32(mmRLC_CNTL);
 
-	if (data & RLC_ENABLE) {
-		data &= ~RLC_ENABLE;
-		WREG32(RLC_CNTL, data);
+	if (data & RLC_CNTL__RLC_ENABLE_F32_MASK) {
+		data &= ~RLC_CNTL__RLC_ENABLE_F32_MASK;
+		WREG32(mmRLC_CNTL, data);
 
 		gfx_v6_0_wait_for_rlc_serdes(adev);
 	}
@@ -2203,7 +2623,7 @@ static u32 gfx_v6_0_halt_rlc(struct amdg
 
 static void gfx_v6_0_rlc_stop(struct amdgpu_device *adev)
 {
-	WREG32(RLC_CNTL, 0);
+	WREG32(mmRLC_CNTL, 0);
 
 	gfx_v6_0_enable_gui_idle_interrupt(adev, false);
 	gfx_v6_0_wait_for_rlc_serdes(adev);
@@ -2211,7 +2631,7 @@ static void gfx_v6_0_rlc_stop(struct amd
 
 static void gfx_v6_0_rlc_start(struct amdgpu_device *adev)
 {
-	WREG32(RLC_CNTL, RLC_ENABLE);
+	WREG32(mmRLC_CNTL, RLC_CNTL__RLC_ENABLE_F32_MASK);
 
 	gfx_v6_0_enable_gui_idle_interrupt(adev, true);
 
@@ -2220,13 +2640,9 @@ static void gfx_v6_0_rlc_start(struct am
 
 static void gfx_v6_0_rlc_reset(struct amdgpu_device *adev)
 {
-	u32 tmp = RREG32(GRBM_SOFT_RESET);
-
-	tmp |= SOFT_RESET_RLC;
-	WREG32(GRBM_SOFT_RESET, tmp);
+	WREG32_FIELD(GRBM_SOFT_RESET, SOFT_RESET_RLC, 1);
 	udelay(50);
-	tmp &= ~SOFT_RESET_RLC;
-	WREG32(GRBM_SOFT_RESET, tmp);
+	WREG32_FIELD(GRBM_SOFT_RESET, SOFT_RESET_RLC, 0);
 	udelay(50);
 }
 
@@ -2235,11 +2651,12 @@ static bool gfx_v6_0_lbpw_supported(stru
 	u32 tmp;
 
 	/* Enable LBPW only for DDR3 */
-	tmp = RREG32(MC_SEQ_MISC0);
+	tmp = RREG32(mmMC_SEQ_MISC0);
 	if ((tmp & 0xF0000000) == 0xB0000000)
 		return true;
 	return false;
 }
+
 static void gfx_v6_0_init_cg(struct amdgpu_device *adev)
 {
 }
@@ -2260,15 +2677,15 @@ static int gfx_v6_0_rlc_resume(struct am
 	gfx_v6_0_init_pg(adev);
 	gfx_v6_0_init_cg(adev);
 
-	WREG32(RLC_RL_BASE, 0);
-	WREG32(RLC_RL_SIZE, 0);
-	WREG32(RLC_LB_CNTL, 0);
-	WREG32(RLC_LB_CNTR_MAX, 0xffffffff);
-	WREG32(RLC_LB_CNTR_INIT, 0);
-	WREG32(RLC_LB_INIT_CU_MASK, 0xffffffff);
+	WREG32(mmRLC_RL_BASE, 0);
+	WREG32(mmRLC_RL_SIZE, 0);
+	WREG32(mmRLC_LB_CNTL, 0);
+	WREG32(mmRLC_LB_CNTR_MAX, 0xffffffff);
+	WREG32(mmRLC_LB_CNTR_INIT, 0);
+	WREG32(mmRLC_LB_INIT_CU_MASK, 0xffffffff);
 
-	WREG32(RLC_MC_CNTL, 0);
-	WREG32(RLC_UCODE_CNTL, 0);
+	WREG32(mmRLC_MC_CNTL, 0);
+	WREG32(mmRLC_UCODE_CNTL, 0);
 
 	hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
 	fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
@@ -2278,10 +2695,10 @@ static int gfx_v6_0_rlc_resume(struct am
 	amdgpu_ucode_print_rlc_hdr(&hdr->header);
 
 	for (i = 0; i < fw_size; i++) {
-		WREG32(RLC_UCODE_ADDR, i);
-		WREG32(RLC_UCODE_DATA, le32_to_cpup(fw_data++));
+		WREG32(mmRLC_UCODE_ADDR, i);
+		WREG32(mmRLC_UCODE_DATA, le32_to_cpup(fw_data++));
 	}
-	WREG32(RLC_UCODE_ADDR, 0);
+	WREG32(mmRLC_UCODE_ADDR, 0);
 
 	gfx_v6_0_enable_lbpw(adev, gfx_v6_0_lbpw_supported(adev));
 	gfx_v6_0_rlc_start(adev);
@@ -2293,38 +2710,38 @@ static void gfx_v6_0_enable_cgcg(struct
 {
 	u32 data, orig, tmp;
 
-	orig = data = RREG32(RLC_CGCG_CGLS_CTRL);
+	orig = data = RREG32(mmRLC_CGCG_CGLS_CTRL);
 
 	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
 		gfx_v6_0_enable_gui_idle_interrupt(adev, true);
 
-		WREG32(RLC_GCPM_GENERAL_3, 0x00000080);
+		WREG32(mmRLC_GCPM_GENERAL_3, 0x00000080);
 
 		tmp = gfx_v6_0_halt_rlc(adev);
 
-		WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
-		WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
-		WREG32(RLC_SERDES_WR_CTRL, 0x00b000ff);
+		WREG32(mmRLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
+		WREG32(mmRLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
+		WREG32(mmRLC_SERDES_WR_CTRL, 0x00b000ff);
 
 		gfx_v6_0_wait_for_rlc_serdes(adev);
 		gfx_v6_0_update_rlc(adev, tmp);
 
-		WREG32(RLC_SERDES_WR_CTRL, 0x007000ff);
+		WREG32(mmRLC_SERDES_WR_CTRL, 0x007000ff);
 
-		data |= CGCG_EN | CGLS_EN;
+		data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
 	} else {
 		gfx_v6_0_enable_gui_idle_interrupt(adev, false);
 
-		RREG32(CB_CGTT_SCLK_CTRL);
-		RREG32(CB_CGTT_SCLK_CTRL);
-		RREG32(CB_CGTT_SCLK_CTRL);
-		RREG32(CB_CGTT_SCLK_CTRL);
+		RREG32(mmCB_CGTT_SCLK_CTRL);
+		RREG32(mmCB_CGTT_SCLK_CTRL);
+		RREG32(mmCB_CGTT_SCLK_CTRL);
+		RREG32(mmCB_CGTT_SCLK_CTRL);
 
-		data &= ~(CGCG_EN | CGLS_EN);
+		data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
 	}
 
 	if (orig != data)
-		WREG32(RLC_CGCG_CGLS_CTRL, data);
+		WREG32(mmRLC_CGCG_CGLS_CTRL, data);
 
 }
 
@@ -2334,51 +2751,51 @@ static void gfx_v6_0_enable_mgcg(struct
 	u32 data, orig, tmp = 0;
 
 	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
-		orig = data = RREG32(CGTS_SM_CTRL_REG);
+		orig = data = RREG32(mmCGTS_SM_CTRL_REG);
 		data = 0x96940200;
 		if (orig != data)
-			WREG32(CGTS_SM_CTRL_REG, data);
+			WREG32(mmCGTS_SM_CTRL_REG, data);
 
 		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) {
-			orig = data = RREG32(CP_MEM_SLP_CNTL);
-			data |= CP_MEM_LS_EN;
+			orig = data = RREG32(mmCP_MEM_SLP_CNTL);
+			data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
 			if (orig != data)
-				WREG32(CP_MEM_SLP_CNTL, data);
+				WREG32(mmCP_MEM_SLP_CNTL, data);
 		}
 
-		orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
+		orig = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
 		data &= 0xffffffc0;
 		if (orig != data)
-			WREG32(RLC_CGTT_MGCG_OVERRIDE, data);
+			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
 
 		tmp = gfx_v6_0_halt_rlc(adev);
 
-		WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
-		WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
-		WREG32(RLC_SERDES_WR_CTRL, 0x00d000ff);
+		WREG32(mmRLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
+		WREG32(mmRLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
+		WREG32(mmRLC_SERDES_WR_CTRL, 0x00d000ff);
 
 		gfx_v6_0_update_rlc(adev, tmp);
 	} else {
-		orig = data = RREG32(RLC_CGTT_MGCG_OVERRIDE);
+		orig = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
 		data |= 0x00000003;
 		if (orig != data)
-			WREG32(RLC_CGTT_MGCG_OVERRIDE, data);
+			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data);
 
-		data = RREG32(CP_MEM_SLP_CNTL);
-		if (data & CP_MEM_LS_EN) {
-			data &= ~CP_MEM_LS_EN;
-			WREG32(CP_MEM_SLP_CNTL, data);
+		data = RREG32(mmCP_MEM_SLP_CNTL);
+		if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) {
+			data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
+			WREG32(mmCP_MEM_SLP_CNTL, data);
 		}
-		orig = data = RREG32(CGTS_SM_CTRL_REG);
-		data |= LS_OVERRIDE | OVERRIDE;
+		orig = data = RREG32(mmCGTS_SM_CTRL_REG);
+		data |= CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK | CGTS_SM_CTRL_REG__OVERRIDE_MASK;
 		if (orig != data)
-			WREG32(CGTS_SM_CTRL_REG, data);
+			WREG32(mmCGTS_SM_CTRL_REG, data);
 
 		tmp = gfx_v6_0_halt_rlc(adev);
 
-		WREG32(RLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
-		WREG32(RLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
-		WREG32(RLC_SERDES_WR_CTRL, 0x00e000ff);
+		WREG32(mmRLC_SERDES_WR_MASTER_MASK_0, 0xffffffff);
+		WREG32(mmRLC_SERDES_WR_MASTER_MASK_1, 0xffffffff);
+		WREG32(mmRLC_SERDES_WR_CTRL, 0x00e000ff);
 
 		gfx_v6_0_update_rlc(adev, tmp);
 	}
@@ -2398,6 +2815,7 @@ static void gfx_v6_0_update_cg(struct am
 	gfx_v6_0_enable_gui_idle_interrupt(adev, true);
 }
 */
+
 static void gfx_v6_0_enable_sclk_slowdown_on_pu(struct amdgpu_device *adev,
 						bool enable)
 {
@@ -2412,13 +2830,13 @@ static void gfx_v6_0_enable_cp_pg(struct
 {
 	u32 data, orig;
 
-	orig = data = RREG32(RLC_PG_CNTL);
+	orig = data = RREG32(mmRLC_PG_CNTL);
 	if (enable && (adev->pg_flags & AMD_PG_SUPPORT_CP))
 		data &= ~0x8000;
 	else
 		data |= 0x8000;
 	if (orig != data)
-		WREG32(RLC_PG_CNTL, data);
+		WREG32(mmRLC_PG_CNTL, data);
 }
 
 static void gfx_v6_0_enable_gds_pg(struct amdgpu_device *adev, bool enable)
@@ -2495,26 +2913,13 @@ static void gfx_v6_0_init_cp_pg_table(st
 static void gfx_v6_0_enable_gfx_cgpg(struct amdgpu_device *adev,
 				     bool enable)
 {
-
-	u32 tmp;
-
 	if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
-		tmp = RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10);
-		WREG32(RLC_TTOP_D, tmp);
-
-		tmp = RREG32(RLC_PG_CNTL);
-		tmp |= GFX_PG_ENABLE;
-		WREG32(RLC_PG_CNTL, tmp);
-
-		tmp = RREG32(RLC_AUTO_PG_CTRL);
-		tmp |= AUTO_PG_EN;
-		WREG32(RLC_AUTO_PG_CTRL, tmp);
+		WREG32(mmRLC_TTOP_D, RLC_PUD(0x10) | RLC_PDD(0x10) | RLC_TTPD(0x10) | RLC_MSD(0x10));
+		WREG32_FIELD(RLC_PG_CNTL, GFX_POWER_GATING_ENABLE, 1);
+		WREG32_FIELD(RLC_AUTO_PG_CTRL, AUTO_PG_EN, 1);
 	} else {
-		tmp = RREG32(RLC_AUTO_PG_CTRL);
-		tmp &= ~AUTO_PG_EN;
-		WREG32(RLC_AUTO_PG_CTRL, tmp);
-
-		tmp = RREG32(DB_RENDER_CONTROL);
+		WREG32_FIELD(RLC_AUTO_PG_CTRL, AUTO_PG_EN, 0);
+		(void)RREG32(mmDB_RENDER_CONTROL);
 	}
 }
 
@@ -2527,8 +2932,8 @@ static u32 gfx_v6_0_get_cu_active_bitmap
 
 	mutex_lock(&adev->grbm_idx_mutex);
 	gfx_v6_0_select_se_sh(adev, se, sh, 0xffffffff);
-	tmp = RREG32(CC_GC_SHADER_ARRAY_CONFIG);
-	tmp1 = RREG32(GC_USER_SHADER_ARRAY_CONFIG);
+	tmp = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG);
+	tmp1 = RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
 	gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
 	mutex_unlock(&adev->grbm_idx_mutex);
 
@@ -2571,12 +2976,8 @@ static void gfx_v6_0_init_ao_cu_mask(str
 		}
 	}
 
-	WREG32(RLC_PG_AO_CU_MASK, tmp);
-
-	tmp = RREG32(RLC_MAX_PG_CU);
-	tmp &= ~MAX_PU_CU_MASK;
-	tmp |= MAX_PU_CU(active_cu_number);
-	WREG32(RLC_MAX_PG_CU, tmp);
+	WREG32(mmRLC_PG_AO_CU_MASK, tmp);
+	WREG32_FIELD(RLC_MAX_PG_CU, MAX_POWERED_UP_CU, active_cu_number);
 }
 
 static void gfx_v6_0_enable_gfx_static_mgpg(struct amdgpu_device *adev,
@@ -2584,13 +2985,13 @@ static void gfx_v6_0_enable_gfx_static_m
 {
 	u32 data, orig;
 
-	orig = data = RREG32(RLC_PG_CNTL);
+	orig = data = RREG32(mmRLC_PG_CNTL);
 	if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG))
-		data |= STATIC_PER_CU_PG_ENABLE;
+		data |= RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
 	else
-		data &= ~STATIC_PER_CU_PG_ENABLE;
+		data &= ~RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK;
 	if (orig != data)
-		WREG32(RLC_PG_CNTL, data);
+		WREG32(mmRLC_PG_CNTL, data);
 }
 
 static void gfx_v6_0_enable_gfx_dynamic_mgpg(struct amdgpu_device *adev,
@@ -2598,33 +2999,28 @@ static void gfx_v6_0_enable_gfx_dynamic_
 {
 	u32 data, orig;
 
-	orig = data = RREG32(RLC_PG_CNTL);
+	orig = data = RREG32(mmRLC_PG_CNTL);
 	if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_DMG))
-		data |= DYN_PER_CU_PG_ENABLE;
+		data |= RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
 	else
-		data &= ~DYN_PER_CU_PG_ENABLE;
+		data &= ~RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK;
 	if (orig != data)
-		WREG32(RLC_PG_CNTL, data);
+		WREG32(mmRLC_PG_CNTL, data);
 }
 
 static void gfx_v6_0_init_gfx_cgpg(struct amdgpu_device *adev)
 {
 	u32 tmp;
 
-	WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
-
-	tmp = RREG32(RLC_PG_CNTL);
-	tmp |= GFX_PG_SRC;
-	WREG32(RLC_PG_CNTL, tmp);
-
-	WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
-
-	tmp = RREG32(RLC_AUTO_PG_CTRL);
+	WREG32(mmRLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
+	WREG32_FIELD(RLC_PG_CNTL, GFX_POWER_GATING_SRC, 1);
+	WREG32(mmRLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
 
-	tmp &= ~GRBM_REG_SGIT_MASK;
-	tmp |= GRBM_REG_SGIT(0x700);
-	tmp &= ~PG_AFTER_GRBM_REG_ST_MASK;
-	WREG32(RLC_AUTO_PG_CTRL, tmp);
+	tmp = RREG32(mmRLC_AUTO_PG_CTRL);
+	tmp &= ~RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD_MASK;
+	tmp |= (0x700 << RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD__SHIFT);
+	tmp &= ~RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD_MASK;
+	WREG32(mmRLC_AUTO_PG_CTRL, tmp);
 }
 
 static void gfx_v6_0_update_gfx_pg(struct amdgpu_device *adev, bool enable)
@@ -2680,7 +3076,6 @@ static void gfx_v6_0_get_csb_buffer(stru
 
 	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
 	buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
-
 	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_CONTEXT_CONTROL, 1));
 	buffer[count++] = cpu_to_le32(0x80000000);
 	buffer[count++] = cpu_to_le32(0x80000000);
@@ -2700,7 +3095,7 @@ static void gfx_v6_0_get_csb_buffer(stru
 	}
 
 	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 1));
-	buffer[count++] = cpu_to_le32(PA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
+	buffer[count++] = cpu_to_le32(mmPA_SC_RASTER_CONFIG - PACKET3_SET_CONTEXT_REG_START);
 
 	switch (adev->asic_type) {
 	case CHIP_TAHITI:
@@ -2743,16 +3138,16 @@ static void gfx_v6_0_init_pg(struct amdg
 			gfx_v6_0_enable_cp_pg(adev, true);
 			gfx_v6_0_enable_gds_pg(adev, true);
 		} else {
-			WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
-			WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
+			WREG32(mmRLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
+			WREG32(mmRLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
 
 		}
 		gfx_v6_0_init_ao_cu_mask(adev);
 		gfx_v6_0_update_gfx_pg(adev, true);
 	} else {
 
-		WREG32(RLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
-		WREG32(RLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
+		WREG32(mmRLC_SAVE_AND_RESTORE_BASE, adev->gfx.rlc.save_restore_gpu_addr >> 8);
+		WREG32(mmRLC_CLEAR_STATE_RESTORE_BASE, adev->gfx.rlc.clear_state_gpu_addr >> 8);
 	}
 }
 
@@ -2777,50 +3172,86 @@ static uint64_t gfx_v6_0_get_gpu_clock_c
 	uint64_t clock;
 
 	mutex_lock(&adev->gfx.gpu_clock_mutex);
-	WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1);
-	clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) |
-	        ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
+	WREG32(mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
+	clock = (uint64_t)RREG32(mmRLC_GPU_CLOCK_COUNT_LSB) |
+	        ((uint64_t)RREG32(mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
 	mutex_unlock(&adev->gfx.gpu_clock_mutex);
 	return clock;
 }
 
 static void gfx_v6_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
 {
+	if (flags & AMDGPU_HAVE_CTX_SWITCH)
+		gfx_v6_0_ring_emit_vgt_flush(ring);
 	amdgpu_ring_write(ring, PACKET3(PACKET3_CONTEXT_CONTROL, 1));
 	amdgpu_ring_write(ring, 0x80000000);
 	amdgpu_ring_write(ring, 0);
 }
 
-static unsigned gfx_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
+
+static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
 {
-	return
-		6; /* gfx_v6_0_ring_emit_ib */
+	WREG32(mmSQ_IND_INDEX,
+		(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+		(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+		(address << SQ_IND_INDEX__INDEX__SHIFT) |
+		(SQ_IND_INDEX__FORCE_READ_MASK));
+	return RREG32(mmSQ_IND_DATA);
 }
 
-static unsigned gfx_v6_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring)
+static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
+			   uint32_t wave, uint32_t thread,
+			   uint32_t regno, uint32_t num, uint32_t *out)
 {
-	return
-		5 + /* gfx_v6_0_ring_emit_hdp_flush */
-		5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
-		14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
-		7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */
-		17 + 6 + /* gfx_v6_0_ring_emit_vm_flush */
-		3; /* gfx_v6_ring_emit_cntxcntl */
+	WREG32(mmSQ_IND_INDEX,
+		(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+		(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+		(regno << SQ_IND_INDEX__INDEX__SHIFT) |
+		(thread << SQ_IND_INDEX__THREAD_ID__SHIFT) |
+		(SQ_IND_INDEX__FORCE_READ_MASK) |
+		(SQ_IND_INDEX__AUTO_INCR_MASK));
+	while (num--)
+		*(out++) = RREG32(mmSQ_IND_DATA);
 }
 
-static unsigned gfx_v6_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring)
+static void gfx_v6_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
 {
-	return
-		5 + /* gfx_v6_0_ring_emit_hdp_flush */
-		5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
-		7 + /* gfx_v6_0_ring_emit_pipeline_sync */
-		17 + /* gfx_v6_0_ring_emit_vm_flush */
-		14 + 14 + 14; /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
+	/* type 0 wave data */
+	dst[(*no_fields)++] = 0;
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+}
+
+static void gfx_v6_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+				     uint32_t wave, uint32_t start,
+				     uint32_t size, uint32_t *dst)
+{
+	wave_read_regs(
+		adev, simd, wave, 0,
+		start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
 }
 
 static const struct amdgpu_gfx_funcs gfx_v6_0_gfx_funcs = {
 	.get_gpu_clock_counter = &gfx_v6_0_get_gpu_clock_counter,
 	.select_se_sh = &gfx_v6_0_select_se_sh,
+	.read_wave_data = &gfx_v6_0_read_wave_data,
+	.read_wave_sgprs = &gfx_v6_0_read_wave_sgprs,
 };
 
 static int gfx_v6_0_early_init(void *handle)
@@ -2873,9 +3304,7 @@ static int gfx_v6_0_sw_init(void *handle
 		ring->ring_obj = NULL;
 		sprintf(ring->name, "gfx");
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     0x80000000, 0xf,
-				     &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
-				     AMDGPU_RING_TYPE_GFX);
+				     &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP);
 		if (r)
 			return r;
 	}
@@ -2897,9 +3326,7 @@ static int gfx_v6_0_sw_init(void *handle
 		sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue);
 		irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     0x80000000, 0xf,
-				     &adev->gfx.eop_irq, irq_type,
-				     AMDGPU_RING_TYPE_COMPUTE);
+				     &adev->gfx.eop_irq, irq_type);
 		if (r)
 			return r;
 	}
@@ -2975,7 +3402,7 @@ static bool gfx_v6_0_is_idle(void *handl
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	if (RREG32(GRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK)
+	if (RREG32(mmGRBM_STATUS) & GRBM_STATUS__GUI_ACTIVE_MASK)
 		return false;
 	else
 		return true;
@@ -3006,14 +3433,14 @@ static void gfx_v6_0_set_gfx_eop_interru
 
 	switch (state) {
 	case AMDGPU_IRQ_STATE_DISABLE:
-		cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
-		cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
-		WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+		cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
+		cp_int_cntl &= ~CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
+		WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
 		break;
 	case AMDGPU_IRQ_STATE_ENABLE:
-		cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
-		cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
-		WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+		cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
+		cp_int_cntl |= CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK;
+		WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
 		break;
 	default:
 		break;
@@ -3028,27 +3455,27 @@ static void gfx_v6_0_set_compute_eop_int
 	switch (state){
 	case AMDGPU_IRQ_STATE_DISABLE:
 		if (ring == 0) {
-			cp_int_cntl = RREG32(CP_INT_CNTL_RING1);
-			cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
-			WREG32(CP_INT_CNTL_RING1, cp_int_cntl);
+			cp_int_cntl = RREG32(mmCP_INT_CNTL_RING1);
+			cp_int_cntl &= ~CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE_MASK;
+			WREG32(mmCP_INT_CNTL_RING1, cp_int_cntl);
 			break;
 		} else {
-			cp_int_cntl = RREG32(CP_INT_CNTL_RING2);
-			cp_int_cntl &= ~CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
-			WREG32(CP_INT_CNTL_RING2, cp_int_cntl);
+			cp_int_cntl = RREG32(mmCP_INT_CNTL_RING2);
+			cp_int_cntl &= ~CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE_MASK;
+			WREG32(mmCP_INT_CNTL_RING2, cp_int_cntl);
 			break;
 
 		}
 	case AMDGPU_IRQ_STATE_ENABLE:
 		if (ring == 0) {
-			cp_int_cntl = RREG32(CP_INT_CNTL_RING1);
-			cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
-			WREG32(CP_INT_CNTL_RING1, cp_int_cntl);
+			cp_int_cntl = RREG32(mmCP_INT_CNTL_RING1);
+			cp_int_cntl |= CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE_MASK;
+			WREG32(mmCP_INT_CNTL_RING1, cp_int_cntl);
 			break;
 		} else {
-			cp_int_cntl = RREG32(CP_INT_CNTL_RING2);
-			cp_int_cntl |= CP_INT_CNTL_RING__TIME_STAMP_INT_ENABLE_MASK;
-			WREG32(CP_INT_CNTL_RING2, cp_int_cntl);
+			cp_int_cntl = RREG32(mmCP_INT_CNTL_RING2);
+			cp_int_cntl |= CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE_MASK;
+			WREG32(mmCP_INT_CNTL_RING2, cp_int_cntl);
 			break;
 
 		}
@@ -3069,14 +3496,14 @@ static int gfx_v6_0_set_priv_reg_fault_s
 
 	switch (state) {
 	case AMDGPU_IRQ_STATE_DISABLE:
-		cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+		cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
 		cp_int_cntl &= ~CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK;
-		WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+		WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
 		break;
 	case AMDGPU_IRQ_STATE_ENABLE:
-		cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+		cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
 		cp_int_cntl |= CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK;
-		WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+		WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
 		break;
 	default:
 		break;
@@ -3094,14 +3521,14 @@ static int gfx_v6_0_set_priv_inst_fault_
 
 	switch (state) {
 	case AMDGPU_IRQ_STATE_DISABLE:
-		cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+		cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
 		cp_int_cntl &= ~CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK;
-		WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+		WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
 		break;
 	case AMDGPU_IRQ_STATE_ENABLE:
-		cp_int_cntl = RREG32(CP_INT_CNTL_RING0);
+		cp_int_cntl = RREG32(mmCP_INT_CNTL_RING0);
 		cp_int_cntl |= CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK;
-		WREG32(CP_INT_CNTL_RING0, cp_int_cntl);
+		WREG32(mmCP_INT_CNTL_RING0, cp_int_cntl);
 		break;
 	default:
 		break;
@@ -3141,7 +3568,7 @@ static int gfx_v6_0_eop_irq(struct amdgp
 		break;
 	case 1:
 	case 2:
-		amdgpu_fence_process(&adev->gfx.compute_ring[entry->ring_id -1]);
+		amdgpu_fence_process(&adev->gfx.compute_ring[entry->ring_id - 1]);
 		break;
 	default:
 		break;
@@ -3214,7 +3641,7 @@ static int gfx_v6_0_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs gfx_v6_0_ip_funcs = {
+static const struct amd_ip_funcs gfx_v6_0_ip_funcs = {
 	.name = "gfx_v6_0",
 	.early_init = gfx_v6_0_early_init,
 	.late_init = NULL,
@@ -3232,10 +3659,20 @@ const struct amd_ip_funcs gfx_v6_0_ip_fu
 };
 
 static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_gfx = {
+	.type = AMDGPU_RING_TYPE_GFX,
+	.align_mask = 0xff,
+	.nop = 0x80000000,
 	.get_rptr = gfx_v6_0_ring_get_rptr,
 	.get_wptr = gfx_v6_0_ring_get_wptr,
 	.set_wptr = gfx_v6_0_ring_set_wptr_gfx,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		5 + /* gfx_v6_0_ring_emit_hdp_flush */
+		5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
+		14 + 14 + 14 + /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
+		7 + 4 + /* gfx_v6_0_ring_emit_pipeline_sync */
+		17 + 6 + /* gfx_v6_0_ring_emit_vm_flush */
+		3 + 2, /* gfx_v6_ring_emit_cntxcntl including vgt flush */
+	.emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
 	.emit_ib = gfx_v6_0_ring_emit_ib,
 	.emit_fence = gfx_v6_0_ring_emit_fence,
 	.emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync,
@@ -3246,15 +3683,22 @@ static const struct amdgpu_ring_funcs gf
 	.test_ib = gfx_v6_0_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
 	.emit_cntxcntl = gfx_v6_ring_emit_cntxcntl,
-	.get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_gfx,
 };
 
 static const struct amdgpu_ring_funcs gfx_v6_0_ring_funcs_compute = {
+	.type = AMDGPU_RING_TYPE_COMPUTE,
+	.align_mask = 0xff,
+	.nop = 0x80000000,
 	.get_rptr = gfx_v6_0_ring_get_rptr,
 	.get_wptr = gfx_v6_0_ring_get_wptr,
 	.set_wptr = gfx_v6_0_ring_set_wptr_compute,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		5 + /* gfx_v6_0_ring_emit_hdp_flush */
+		5 + /* gfx_v6_0_ring_emit_hdp_invalidate */
+		7 + /* gfx_v6_0_ring_emit_pipeline_sync */
+		17 + /* gfx_v6_0_ring_emit_vm_flush */
+		14 + 14 + 14, /* gfx_v6_0_ring_emit_fence x3 for user fence, vm fence */
+	.emit_ib_size = 6, /* gfx_v6_0_ring_emit_ib */
 	.emit_ib = gfx_v6_0_ring_emit_ib,
 	.emit_fence = gfx_v6_0_ring_emit_fence,
 	.emit_pipeline_sync = gfx_v6_0_ring_emit_pipeline_sync,
@@ -3264,8 +3708,6 @@ static const struct amdgpu_ring_funcs gf
 	.test_ring = gfx_v6_0_ring_test_ring,
 	.test_ib = gfx_v6_0_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
-	.get_emit_ib_size = gfx_v6_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = gfx_v6_0_ring_get_dma_frame_size_compute,
 };
 
 static void gfx_v6_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -3337,3 +3779,12 @@ static void gfx_v6_0_get_cu_info(struct
 	cu_info->number = active_cu_number;
 	cu_info->ao_cu_mask = ao_cu_mask;
 }
+
+const struct amdgpu_ip_block_version gfx_v6_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GFX,
+	.major = 6,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &gfx_v6_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v6_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __GFX_V6_0_H__
 #define __GFX_V6_0_H__
 
-extern const struct amd_ip_funcs gfx_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gfx_v6_0_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c	2016-12-11 17:41:39.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c	2017-02-12 17:24:39.000000000 -0500
@@ -2048,9 +2048,9 @@ static int gfx_v7_0_ring_test_ring(struc
 static void gfx_v7_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
 {
 	u32 ref_and_mask;
-	int usepfp = ring->type == AMDGPU_RING_TYPE_COMPUTE ? 0 : 1;
+	int usepfp = ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE ? 0 : 1;
 
-	if (ring->type == AMDGPU_RING_TYPE_COMPUTE) {
+	if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
 		switch (ring->me) {
 		case 1:
 			ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe;
@@ -2076,6 +2076,18 @@ static void gfx_v7_0_ring_emit_hdp_flush
 	amdgpu_ring_write(ring, 0x20); /* poll interval */
 }
 
+static void gfx_v7_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
+{
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
+		EVENT_INDEX(4));
+
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+		EVENT_INDEX(0));
+}
+
+
 /**
  * gfx_v7_0_ring_emit_hdp_invalidate - emit an hdp invalidate on the cp
  *
@@ -2231,6 +2243,7 @@ static void gfx_v7_ring_emit_cntxcntl(st
 
 	dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */
 	if (flags & AMDGPU_HAVE_CTX_SWITCH) {
+		gfx_v7_0_ring_emit_vgt_flush(ring);
 		/* set load_global_config & load_global_uconfig */
 		dw2 |= 0x8001;
 		/* set load_cs_sh_regs */
@@ -2257,7 +2270,7 @@ static int gfx_v7_0_ring_test_ib(struct
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	uint32_t scratch;
 	uint32_t tmp = 0;
 	long r;
@@ -2283,7 +2296,7 @@ static int gfx_v7_0_ring_test_ib(struct
 	if (r)
 		goto err2;
 
-	r = fence_wait_timeout(f, false, timeout);
+	r = dma_fence_wait_timeout(f, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out\n");
 		r = -ETIMEDOUT;
@@ -2304,7 +2317,7 @@ static int gfx_v7_0_ring_test_ib(struct
 
 err2:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 err1:
 	amdgpu_gfx_scratch_free(adev, scratch);
 	return r;
@@ -3193,7 +3206,7 @@ static int gfx_v7_0_cp_resume(struct amd
  */
 static void gfx_v7_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 {
-	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
 	uint32_t seq = ring->fence_drv.sync_seq;
 	uint64_t addr = ring->fence_drv.gpu_addr;
 
@@ -3233,7 +3246,7 @@ static void gfx_v7_0_ring_emit_pipeline_
 static void gfx_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 					unsigned vm_id, uint64_t pd_addr)
 {
-	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -3362,7 +3375,8 @@ static int gfx_v7_0_rlc_init(struct amdg
 		if (adev->gfx.rlc.save_restore_obj == NULL) {
 			r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
 					     AMDGPU_GEM_DOMAIN_VRAM,
-					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+					     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 					     NULL, NULL,
 					     &adev->gfx.rlc.save_restore_obj);
 			if (r) {
@@ -3406,7 +3420,8 @@ static int gfx_v7_0_rlc_init(struct amdg
 		if (adev->gfx.rlc.clear_state_obj == NULL) {
 			r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
 					     AMDGPU_GEM_DOMAIN_VRAM,
-					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+					     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 					     NULL, NULL,
 					     &adev->gfx.rlc.clear_state_obj);
 			if (r) {
@@ -3446,7 +3461,8 @@ static int gfx_v7_0_rlc_init(struct amdg
 		if (adev->gfx.rlc.cp_table_obj == NULL) {
 			r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true,
 					     AMDGPU_GEM_DOMAIN_VRAM,
-					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+					     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 					     NULL, NULL,
 					     &adev->gfx.rlc.cp_table_obj);
 			if (r) {
@@ -4325,44 +4341,69 @@ static void gfx_v7_0_ring_emit_gds_switc
 	amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base));
 }
 
-static unsigned gfx_v7_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring)
+static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
 {
-	return
-		4; /* gfx_v7_0_ring_emit_ib_gfx */
+	WREG32(mmSQ_IND_INDEX,
+		(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+		(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+		(address << SQ_IND_INDEX__INDEX__SHIFT) |
+		(SQ_IND_INDEX__FORCE_READ_MASK));
+	return RREG32(mmSQ_IND_DATA);
 }
 
-static unsigned gfx_v7_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring)
+static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
+			   uint32_t wave, uint32_t thread,
+			   uint32_t regno, uint32_t num, uint32_t *out)
 {
-	return
-		20 + /* gfx_v7_0_ring_emit_gds_switch */
-		7 + /* gfx_v7_0_ring_emit_hdp_flush */
-		5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
-		12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */
-		7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */
-		17 + 6 + /* gfx_v7_0_ring_emit_vm_flush */
-		3; /* gfx_v7_ring_emit_cntxcntl */
+	WREG32(mmSQ_IND_INDEX,
+		(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+		(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+		(regno << SQ_IND_INDEX__INDEX__SHIFT) |
+		(thread << SQ_IND_INDEX__THREAD_ID__SHIFT) |
+		(SQ_IND_INDEX__FORCE_READ_MASK) |
+		(SQ_IND_INDEX__AUTO_INCR_MASK));
+	while (num--)
+		*(out++) = RREG32(mmSQ_IND_DATA);
 }
 
-static unsigned gfx_v7_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring)
+static void gfx_v7_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
 {
-	return
-		4; /* gfx_v7_0_ring_emit_ib_compute */
+	/* type 0 wave data */
+	dst[(*no_fields)++] = 0;
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
 }
 
-static unsigned gfx_v7_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring)
+static void gfx_v7_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+				     uint32_t wave, uint32_t start,
+				     uint32_t size, uint32_t *dst)
 {
-	return
-		20 + /* gfx_v7_0_ring_emit_gds_switch */
-		7 + /* gfx_v7_0_ring_emit_hdp_flush */
-		5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
-		7 + /* gfx_v7_0_ring_emit_pipeline_sync */
-		17 + /* gfx_v7_0_ring_emit_vm_flush */
-		7 + 7 + 7; /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */
+	wave_read_regs(
+		adev, simd, wave, 0,
+		start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
 }
 
 static const struct amdgpu_gfx_funcs gfx_v7_0_gfx_funcs = {
 	.get_gpu_clock_counter = &gfx_v7_0_get_gpu_clock_counter,
 	.select_se_sh = &gfx_v7_0_select_se_sh,
+	.read_wave_data = &gfx_v7_0_read_wave_data,
+	.read_wave_sgprs = &gfx_v7_0_read_wave_sgprs,
 };
 
 static const struct amdgpu_rlc_funcs gfx_v7_0_rlc_funcs = {
@@ -4614,9 +4655,7 @@ static int gfx_v7_0_sw_init(void *handle
 		ring->ring_obj = NULL;
 		sprintf(ring->name, "gfx");
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
-				     &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
-				     AMDGPU_RING_TYPE_GFX);
+				     &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP);
 		if (r)
 			return r;
 	}
@@ -4641,9 +4680,7 @@ static int gfx_v7_0_sw_init(void *handle
 		irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
 		/* type-2 packets are deprecated on MEC, use type-3 instead */
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
-				     &adev->gfx.eop_irq, irq_type,
-				     AMDGPU_RING_TYPE_COMPUTE);
+				     &adev->gfx.eop_irq, irq_type);
 		if (r)
 			return r;
 	}
@@ -5094,7 +5131,7 @@ static int gfx_v7_0_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
+static const struct amd_ip_funcs gfx_v7_0_ip_funcs = {
 	.name = "gfx_v7_0",
 	.early_init = gfx_v7_0_early_init,
 	.late_init = gfx_v7_0_late_init,
@@ -5112,10 +5149,21 @@ const struct amd_ip_funcs gfx_v7_0_ip_fu
 };
 
 static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_gfx = {
+	.type = AMDGPU_RING_TYPE_GFX,
+	.align_mask = 0xff,
+	.nop = PACKET3(PACKET3_NOP, 0x3FFF),
 	.get_rptr = gfx_v7_0_ring_get_rptr,
 	.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
 	.set_wptr = gfx_v7_0_ring_set_wptr_gfx,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		20 + /* gfx_v7_0_ring_emit_gds_switch */
+		7 + /* gfx_v7_0_ring_emit_hdp_flush */
+		5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
+		12 + 12 + 12 + /* gfx_v7_0_ring_emit_fence_gfx x3 for user fence, vm fence */
+		7 + 4 + /* gfx_v7_0_ring_emit_pipeline_sync */
+		17 + 6 + /* gfx_v7_0_ring_emit_vm_flush */
+		3 + 4, /* gfx_v7_ring_emit_cntxcntl including vgt flush*/
+	.emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_gfx */
 	.emit_ib = gfx_v7_0_ring_emit_ib_gfx,
 	.emit_fence = gfx_v7_0_ring_emit_fence_gfx,
 	.emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync,
@@ -5128,15 +5176,23 @@ static const struct amdgpu_ring_funcs gf
 	.insert_nop = amdgpu_ring_insert_nop,
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.emit_cntxcntl = gfx_v7_ring_emit_cntxcntl,
-	.get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_gfx,
-	.get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_gfx,
 };
 
 static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = {
+	.type = AMDGPU_RING_TYPE_COMPUTE,
+	.align_mask = 0xff,
+	.nop = PACKET3(PACKET3_NOP, 0x3FFF),
 	.get_rptr = gfx_v7_0_ring_get_rptr,
 	.get_wptr = gfx_v7_0_ring_get_wptr_compute,
 	.set_wptr = gfx_v7_0_ring_set_wptr_compute,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		20 + /* gfx_v7_0_ring_emit_gds_switch */
+		7 + /* gfx_v7_0_ring_emit_hdp_flush */
+		5 + /* gfx_v7_0_ring_emit_hdp_invalidate */
+		7 + /* gfx_v7_0_ring_emit_pipeline_sync */
+		17 + /* gfx_v7_0_ring_emit_vm_flush */
+		7 + 7 + 7, /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */
+	.emit_ib_size =	4, /* gfx_v7_0_ring_emit_ib_compute */
 	.emit_ib = gfx_v7_0_ring_emit_ib_compute,
 	.emit_fence = gfx_v7_0_ring_emit_fence_compute,
 	.emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync,
@@ -5148,8 +5204,6 @@ static const struct amdgpu_ring_funcs gf
 	.test_ib = gfx_v7_0_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
 	.pad_ib = amdgpu_ring_generic_pad_ib,
-	.get_emit_ib_size = gfx_v7_0_ring_get_emit_ib_size_compute,
-	.get_dma_frame_size = gfx_v7_0_ring_get_dma_frame_size_compute,
 };
 
 static void gfx_v7_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -5260,3 +5314,39 @@ static void gfx_v7_0_get_cu_info(struct
 	cu_info->number = active_cu_number;
 	cu_info->ao_cu_mask = ao_cu_mask;
 }
+
+const struct amdgpu_ip_block_version gfx_v7_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GFX,
+	.major = 7,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &gfx_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v7_1_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GFX,
+	.major = 7,
+	.minor = 1,
+	.rev = 0,
+	.funcs = &gfx_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v7_2_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GFX,
+	.major = 7,
+	.minor = 2,
+	.rev = 0,
+	.funcs = &gfx_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v7_3_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GFX,
+	.major = 7,
+	.minor = 3,
+	.rev = 0,
+	.funcs = &gfx_v7_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,9 @@
 #ifndef __GFX_V7_0_H__
 #define __GFX_V7_0_H__
 
-extern const struct amd_ip_funcs gfx_v7_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gfx_v7_0_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v7_1_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v7_2_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v7_3_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c	2016-12-11 17:41:05.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c	2017-02-12 17:23:48.000000000 -0500
@@ -25,6 +25,7 @@
 #include "amdgpu.h"
 #include "amdgpu_gfx.h"
 #include "vi.h"
+#include "vi_structs.h"
 #include "vid.h"
 #include "amdgpu_ucode.h"
 #include "amdgpu_atombios.h"
@@ -122,6 +123,7 @@ static const u32 golden_settings_tonga_a
 	mmPA_SC_ENHANCE, 0xffffffff, 0x20000001,
 	mmPA_SC_FIFO_DEPTH_CNTL, 0x000003ff, 0x000000fc,
 	mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000,
+	mmRLC_CGCG_CGLS_CTRL, 0x00000003, 0x0000003c,
 	mmSQ_RANDOM_WAVE_PRI, 0x001fffff, 0x000006fd,
 	mmTA_CNTL_AUX, 0x000f000f, 0x000b0000,
 	mmTCC_CTRL, 0x00100000, 0xf31fff7f,
@@ -642,6 +644,7 @@ static void gfx_v8_0_init_golden_registe
 						 (const u32)ARRAY_SIZE(tonga_golden_common_all));
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		amdgpu_program_register_sequence(adev,
 						 golden_settings_polaris11_a11,
 						 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -752,7 +755,7 @@ static int gfx_v8_0_ring_test_ib(struct
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	uint32_t scratch;
 	uint32_t tmp = 0;
 	long r;
@@ -778,7 +781,7 @@ static int gfx_v8_0_ring_test_ib(struct
 	if (r)
 		goto err2;
 
-	r = fence_wait_timeout(f, false, timeout);
+	r = dma_fence_wait_timeout(f, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out.\n");
 		r = -ETIMEDOUT;
@@ -798,7 +801,7 @@ static int gfx_v8_0_ring_test_ib(struct
 	}
 err2:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 err1:
 	amdgpu_gfx_scratch_free(adev, scratch);
 	return r;
@@ -856,6 +859,9 @@ static int gfx_v8_0_init_microcode(struc
 	case CHIP_POLARIS10:
 		chip_name = "polaris10";
 		break;
+	case CHIP_POLARIS12:
+		chip_name = "polaris12";
+		break;
 	case CHIP_STONEY:
 		chip_name = "stoney";
 		break;
@@ -1012,6 +1018,19 @@ static int gfx_v8_0_init_microcode(struc
 		adev->firmware.fw_size +=
 			ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
 
+		/* we need account JT in */
+		cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
+		adev->firmware.fw_size +=
+			ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
+
+		if (amdgpu_sriov_vf(adev)) {
+			info = &adev->firmware.ucode[AMDGPU_UCODE_ID_STORAGE];
+			info->ucode_id = AMDGPU_UCODE_ID_STORAGE;
+			info->fw = adev->gfx.mec_fw;
+			adev->firmware.fw_size +=
+				ALIGN(le32_to_cpu(64 * PAGE_SIZE), PAGE_SIZE);
+		}
+
 		if (adev->gfx.mec2_fw) {
 			info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2];
 			info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
@@ -1081,34 +1100,8 @@ static void gfx_v8_0_get_csb_buffer(stru
 	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_SET_CONTEXT_REG, 2));
 	buffer[count++] = cpu_to_le32(mmPA_SC_RASTER_CONFIG -
 			PACKET3_SET_CONTEXT_REG_START);
-	switch (adev->asic_type) {
-	case CHIP_TONGA:
-	case CHIP_POLARIS10:
-		buffer[count++] = cpu_to_le32(0x16000012);
-		buffer[count++] = cpu_to_le32(0x0000002A);
-		break;
-	case CHIP_POLARIS11:
-		buffer[count++] = cpu_to_le32(0x16000012);
-		buffer[count++] = cpu_to_le32(0x00000000);
-		break;
-	case CHIP_FIJI:
-		buffer[count++] = cpu_to_le32(0x3a00161a);
-		buffer[count++] = cpu_to_le32(0x0000002e);
-		break;
-	case CHIP_TOPAZ:
-	case CHIP_CARRIZO:
-		buffer[count++] = cpu_to_le32(0x00000002);
-		buffer[count++] = cpu_to_le32(0x00000000);
-		break;
-	case CHIP_STONEY:
-		buffer[count++] = cpu_to_le32(0x00000000);
-		buffer[count++] = cpu_to_le32(0x00000000);
-		break;
-	default:
-		buffer[count++] = cpu_to_le32(0x00000000);
-		buffer[count++] = cpu_to_le32(0x00000000);
-		break;
-	}
+	buffer[count++] = cpu_to_le32(adev->gfx.config.rb_config[0][0].raster_config);
+	buffer[count++] = cpu_to_le32(adev->gfx.config.rb_config[0][0].raster_config_1);
 
 	buffer[count++] = cpu_to_le32(PACKET3(PACKET3_PREAMBLE_CNTL, 0));
 	buffer[count++] = cpu_to_le32(PACKET3_PREAMBLE_END_CLEAR_STATE);
@@ -1227,7 +1220,8 @@ static int gfx_v8_0_rlc_init(struct amdg
 		if (adev->gfx.rlc.clear_state_obj == NULL) {
 			r = amdgpu_bo_create(adev, dws * 4, PAGE_SIZE, true,
 					     AMDGPU_GEM_DOMAIN_VRAM,
-					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+					     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 					     NULL, NULL,
 					     &adev->gfx.rlc.clear_state_obj);
 			if (r) {
@@ -1269,7 +1263,8 @@ static int gfx_v8_0_rlc_init(struct amdg
 		if (adev->gfx.rlc.cp_table_obj == NULL) {
 			r = amdgpu_bo_create(adev, adev->gfx.rlc.cp_table_size, PAGE_SIZE, true,
 					     AMDGPU_GEM_DOMAIN_VRAM,
-					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
+					     AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
+					     AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS,
 					     NULL, NULL,
 					     &adev->gfx.rlc.cp_table_obj);
 			if (r) {
@@ -1337,7 +1332,7 @@ static int gfx_v8_0_mec_init(struct amdg
 
 	if (adev->gfx.mec.hpd_eop_obj == NULL) {
 		r = amdgpu_bo_create(adev,
-				     adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe * MEC_HPD_SIZE * 2,
+				     adev->gfx.mec.num_queue * MEC_HPD_SIZE,
 				     PAGE_SIZE, true,
 				     AMDGPU_GEM_DOMAIN_GTT, 0, NULL, NULL,
 				     &adev->gfx.mec.hpd_eop_obj);
@@ -1366,7 +1361,7 @@ static int gfx_v8_0_mec_init(struct amdg
 		return r;
 	}
 
-	memset(hpd, 0, adev->gfx.mec.num_mec *adev->gfx.mec.num_pipe * MEC_HPD_SIZE * 2);
+	memset(hpd, 0, adev->gfx.mec.num_queue * MEC_HPD_SIZE);
 
 	amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj);
 	amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj);
@@ -1529,7 +1524,7 @@ static int gfx_v8_0_do_edc_gpr_workaroun
 {
 	struct amdgpu_ring *ring = &adev->gfx.compute_ring[0];
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	int r, i;
 	u32 tmp;
 	unsigned total_size, vgpr_offset, sgpr_offset;
@@ -1662,7 +1657,7 @@ static int gfx_v8_0_do_edc_gpr_workaroun
 	}
 
 	/* wait for the GPU to finish processing the IB */
-	r = fence_wait(f, false);
+	r = dma_fence_wait(f, false);
 	if (r) {
 		DRM_ERROR("amdgpu: fence wait failed (%d).\n", r);
 		goto fail;
@@ -1683,7 +1678,7 @@ static int gfx_v8_0_do_edc_gpr_workaroun
 
 fail:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 
 	return r;
 }
@@ -1732,6 +1727,7 @@ static int gfx_v8_0_gpu_early_init(struc
 		gb_addr_config = TONGA_GB_ADDR_CONFIG_GOLDEN;
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		ret = amdgpu_atombios_get_gfx_info(adev);
 		if (ret)
 			return ret;
@@ -1999,10 +1995,8 @@ static int gfx_v8_0_sw_init(void *handle
 			ring->doorbell_index = AMDGPU_DOORBELL_GFX_RING0;
 		}
 
-		r = amdgpu_ring_init(adev, ring, 1024,
-				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
-				     &adev->gfx.eop_irq, AMDGPU_CP_IRQ_GFX_EOP,
-				     AMDGPU_RING_TYPE_GFX);
+		r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
+				     AMDGPU_CP_IRQ_GFX_EOP);
 		if (r)
 			return r;
 	}
@@ -2026,10 +2020,8 @@ static int gfx_v8_0_sw_init(void *handle
 		sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
 		irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
 		/* type-2 packets are deprecated on MEC, use type-3 instead */
-		r = amdgpu_ring_init(adev, ring, 1024,
-				     PACKET3(PACKET3_NOP, 0x3FFF), 0xf,
-				     &adev->gfx.eop_irq, irq_type,
-				     AMDGPU_RING_TYPE_COMPUTE);
+		r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
+				     irq_type);
 		if (r)
 			return r;
 	}
@@ -2650,6 +2642,7 @@ static void gfx_v8_0_tiling_mode_table_i
 
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
 				PIPE_CONFIG(ADDR_SURF_P4_16x16) |
 				TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
@@ -3471,6 +3464,7 @@ gfx_v8_0_raster_config(struct amdgpu_dev
 		*rconf1 |= 0x0;
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		*rconf |= RB_MAP_PKR0(2) | RB_XSEL2(1) | SE_MAP(2) |
 			  SE_XSEL(1) | SE_YSEL(1);
 		*rconf1 |= 0x0;
@@ -3633,6 +3627,21 @@ static void gfx_v8_0_setup_rb(struct amd
 							num_rb_pipes);
 	}
 
+	/* cache the values for userspace */
+	for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+		for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+			gfx_v8_0_select_se_sh(adev, i, j, 0xffffffff);
+			adev->gfx.config.rb_config[i][j].rb_backend_disable =
+				RREG32(mmCC_RB_BACKEND_DISABLE);
+			adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
+				RREG32(mmGC_USER_RB_BACKEND_DISABLE);
+			adev->gfx.config.rb_config[i][j].raster_config =
+				RREG32(mmPA_SC_RASTER_CONFIG);
+			adev->gfx.config.rb_config[i][j].raster_config_1 =
+				RREG32(mmPA_SC_RASTER_CONFIG_1);
+		}
+	}
+	gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
 	mutex_unlock(&adev->grbm_idx_mutex);
 }
 
@@ -3859,7 +3868,7 @@ static int gfx_v8_0_init_save_restore_li
 	int list_size;
 	unsigned int *register_list_format =
 		kmalloc(adev->gfx.rlc.reg_list_format_size_bytes, GFP_KERNEL);
-	if (register_list_format == NULL)
+	if (!register_list_format)
 		return -ENOMEM;
 	memcpy(register_list_format, adev->gfx.rlc.register_list_format,
 			adev->gfx.rlc.reg_list_format_size_bytes);
@@ -3902,8 +3911,12 @@ static int gfx_v8_0_init_save_restore_li
 	temp = mmRLC_SRM_INDEX_CNTL_ADDR_0;
 	data = mmRLC_SRM_INDEX_CNTL_DATA_0;
 	for (i = 0; i < sizeof(unique_indices) / sizeof(int); i++) {
-		amdgpu_mm_wreg(adev, temp + i, unique_indices[i] & 0x3FFFF, false);
-		amdgpu_mm_wreg(adev, data + i, unique_indices[i] >> 20, false);
+		if (unique_indices[i] != 0) {
+			amdgpu_mm_wreg(adev, temp + i,
+					unique_indices[i] & 0x3FFFF, false);
+			amdgpu_mm_wreg(adev, data + i,
+					unique_indices[i] >> 20, false);
+		}
 	}
 	kfree(register_list_format);
 
@@ -3919,20 +3932,17 @@ static void gfx_v8_0_init_power_gating(s
 {
 	uint32_t data;
 
-	if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
-			      AMD_PG_SUPPORT_GFX_SMG |
-			      AMD_PG_SUPPORT_GFX_DMG)) {
-		WREG32_FIELD(CP_RB_WPTR_POLL_CNTL, IDLE_POLL_COUNT, 0x60);
+	WREG32_FIELD(CP_RB_WPTR_POLL_CNTL, IDLE_POLL_COUNT, 0x60);
 
-		data = REG_SET_FIELD(0, RLC_PG_DELAY, POWER_UP_DELAY, 0x10);
-		data = REG_SET_FIELD(data, RLC_PG_DELAY, POWER_DOWN_DELAY, 0x10);
-		data = REG_SET_FIELD(data, RLC_PG_DELAY, CMD_PROPAGATE_DELAY, 0x10);
-		data = REG_SET_FIELD(data, RLC_PG_DELAY, MEM_SLEEP_DELAY, 0x10);
-		WREG32(mmRLC_PG_DELAY, data);
+	data = REG_SET_FIELD(0, RLC_PG_DELAY, POWER_UP_DELAY, 0x10);
+	data = REG_SET_FIELD(data, RLC_PG_DELAY, POWER_DOWN_DELAY, 0x10);
+	data = REG_SET_FIELD(data, RLC_PG_DELAY, CMD_PROPAGATE_DELAY, 0x10);
+	data = REG_SET_FIELD(data, RLC_PG_DELAY, MEM_SLEEP_DELAY, 0x10);
+	WREG32(mmRLC_PG_DELAY, data);
+
+	WREG32_FIELD(RLC_PG_DELAY_2, SERDES_CMD_DELAY, 0x3);
+	WREG32_FIELD(RLC_AUTO_PG_CTRL, GRBM_REG_SAVE_GFX_IDLE_THRESHOLD, 0x55f0);
 
-		WREG32_FIELD(RLC_PG_DELAY_2, SERDES_CMD_DELAY, 0x3);
-		WREG32_FIELD(RLC_AUTO_PG_CTRL, GRBM_REG_SAVE_GFX_IDLE_THRESHOLD, 0x55f0);
-	}
 }
 
 static void cz_enable_sck_slow_down_on_power_up(struct amdgpu_device *adev,
@@ -3949,41 +3959,38 @@ static void cz_enable_sck_slow_down_on_p
 
 static void cz_enable_cp_power_gating(struct amdgpu_device *adev, bool enable)
 {
-	WREG32_FIELD(RLC_PG_CNTL, CP_PG_DISABLE, enable ? 1 : 0);
+	WREG32_FIELD(RLC_PG_CNTL, CP_PG_DISABLE, enable ? 0 : 1);
 }
 
 static void gfx_v8_0_init_pg(struct amdgpu_device *adev)
 {
-	if (adev->pg_flags & (AMD_PG_SUPPORT_GFX_PG |
-			      AMD_PG_SUPPORT_GFX_SMG |
-			      AMD_PG_SUPPORT_GFX_DMG |
-			      AMD_PG_SUPPORT_CP |
-			      AMD_PG_SUPPORT_GDS |
-			      AMD_PG_SUPPORT_RLC_SMU_HS)) {
+	if ((adev->asic_type == CHIP_CARRIZO) ||
+	    (adev->asic_type == CHIP_STONEY)) {
 		gfx_v8_0_init_csb(adev);
 		gfx_v8_0_init_save_restore_list(adev);
 		gfx_v8_0_enable_save_restore_machine(adev);
-
-		if ((adev->asic_type == CHIP_CARRIZO) ||
-		    (adev->asic_type == CHIP_STONEY)) {
-			WREG32(mmRLC_JUMP_TABLE_RESTORE, adev->gfx.rlc.cp_table_gpu_addr >> 8);
-			gfx_v8_0_init_power_gating(adev);
-			WREG32(mmRLC_PG_ALWAYS_ON_CU_MASK, adev->gfx.cu_info.ao_cu_mask);
-			if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) {
-				cz_enable_sck_slow_down_on_power_up(adev, true);
-				cz_enable_sck_slow_down_on_power_down(adev, true);
-			} else {
-				cz_enable_sck_slow_down_on_power_up(adev, false);
-				cz_enable_sck_slow_down_on_power_down(adev, false);
-			}
-			if (adev->pg_flags & AMD_PG_SUPPORT_CP)
-				cz_enable_cp_power_gating(adev, true);
-			else
-				cz_enable_cp_power_gating(adev, false);
-		} else if (adev->asic_type == CHIP_POLARIS11) {
-			gfx_v8_0_init_power_gating(adev);
+		WREG32(mmRLC_JUMP_TABLE_RESTORE, adev->gfx.rlc.cp_table_gpu_addr >> 8);
+		gfx_v8_0_init_power_gating(adev);
+		WREG32(mmRLC_PG_ALWAYS_ON_CU_MASK, adev->gfx.cu_info.ao_cu_mask);
+		if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) {
+			cz_enable_sck_slow_down_on_power_up(adev, true);
+			cz_enable_sck_slow_down_on_power_down(adev, true);
+		} else {
+			cz_enable_sck_slow_down_on_power_up(adev, false);
+			cz_enable_sck_slow_down_on_power_down(adev, false);
 		}
+		if (adev->pg_flags & AMD_PG_SUPPORT_CP)
+			cz_enable_cp_power_gating(adev, true);
+		else
+			cz_enable_cp_power_gating(adev, false);
+	} else if ((adev->asic_type == CHIP_POLARIS11) ||
+		   (adev->asic_type == CHIP_POLARIS12)) {
+		gfx_v8_0_init_csb(adev);
+		gfx_v8_0_init_save_restore_list(adev);
+		gfx_v8_0_enable_save_restore_machine(adev);
+		gfx_v8_0_init_power_gating(adev);
 	}
+
 }
 
 static void gfx_v8_0_rlc_stop(struct amdgpu_device *adev)
@@ -4051,7 +4058,8 @@ static int gfx_v8_0_rlc_resume(struct am
 		 RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
 	WREG32(mmRLC_CGCG_CGLS_CTRL, tmp);
 	if (adev->asic_type == CHIP_POLARIS11 ||
-	    adev->asic_type == CHIP_POLARIS10) {
+	    adev->asic_type == CHIP_POLARIS10 ||
+	    adev->asic_type == CHIP_POLARIS12) {
 		tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D);
 		tmp &= ~0x3;
 		WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp);
@@ -4239,6 +4247,7 @@ static int gfx_v8_0_cp_gfx_start(struct
 		amdgpu_ring_write(ring, 0x0000002A);
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		amdgpu_ring_write(ring, 0x16000012);
 		amdgpu_ring_write(ring, 0x00000000);
 		break;
@@ -4285,7 +4294,7 @@ static int gfx_v8_0_cp_gfx_resume(struct
 	struct amdgpu_ring *ring;
 	u32 tmp;
 	u32 rb_bufsz;
-	u64 rb_addr, rptr_addr;
+	u64 rb_addr, rptr_addr, wptr_gpu_addr;
 	int r;
 
 	/* Set the write pointer delay */
@@ -4316,6 +4325,9 @@ static int gfx_v8_0_cp_gfx_resume(struct
 	WREG32(mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
 	WREG32(mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & 0xFF);
 
+	wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
+	WREG32(mmCP_RB_WPTR_POLL_ADDR_LO, lower_32_bits(wptr_gpu_addr));
+	WREG32(mmCP_RB_WPTR_POLL_ADDR_HI, upper_32_bits(wptr_gpu_addr));
 	mdelay(1);
 	WREG32(mmCP_RB0_CNTL, tmp);
 
@@ -4421,267 +4433,6 @@ static int gfx_v8_0_cp_compute_load_micr
 	return 0;
 }
 
-struct vi_mqd {
-	uint32_t header;  /* ordinal0 */
-	uint32_t compute_dispatch_initiator;  /* ordinal1 */
-	uint32_t compute_dim_x;  /* ordinal2 */
-	uint32_t compute_dim_y;  /* ordinal3 */
-	uint32_t compute_dim_z;  /* ordinal4 */
-	uint32_t compute_start_x;  /* ordinal5 */
-	uint32_t compute_start_y;  /* ordinal6 */
-	uint32_t compute_start_z;  /* ordinal7 */
-	uint32_t compute_num_thread_x;  /* ordinal8 */
-	uint32_t compute_num_thread_y;  /* ordinal9 */
-	uint32_t compute_num_thread_z;  /* ordinal10 */
-	uint32_t compute_pipelinestat_enable;  /* ordinal11 */
-	uint32_t compute_perfcount_enable;  /* ordinal12 */
-	uint32_t compute_pgm_lo;  /* ordinal13 */
-	uint32_t compute_pgm_hi;  /* ordinal14 */
-	uint32_t compute_tba_lo;  /* ordinal15 */
-	uint32_t compute_tba_hi;  /* ordinal16 */
-	uint32_t compute_tma_lo;  /* ordinal17 */
-	uint32_t compute_tma_hi;  /* ordinal18 */
-	uint32_t compute_pgm_rsrc1;  /* ordinal19 */
-	uint32_t compute_pgm_rsrc2;  /* ordinal20 */
-	uint32_t compute_vmid;  /* ordinal21 */
-	uint32_t compute_resource_limits;  /* ordinal22 */
-	uint32_t compute_static_thread_mgmt_se0;  /* ordinal23 */
-	uint32_t compute_static_thread_mgmt_se1;  /* ordinal24 */
-	uint32_t compute_tmpring_size;  /* ordinal25 */
-	uint32_t compute_static_thread_mgmt_se2;  /* ordinal26 */
-	uint32_t compute_static_thread_mgmt_se3;  /* ordinal27 */
-	uint32_t compute_restart_x;  /* ordinal28 */
-	uint32_t compute_restart_y;  /* ordinal29 */
-	uint32_t compute_restart_z;  /* ordinal30 */
-	uint32_t compute_thread_trace_enable;  /* ordinal31 */
-	uint32_t compute_misc_reserved;  /* ordinal32 */
-	uint32_t compute_dispatch_id;  /* ordinal33 */
-	uint32_t compute_threadgroup_id;  /* ordinal34 */
-	uint32_t compute_relaunch;  /* ordinal35 */
-	uint32_t compute_wave_restore_addr_lo;  /* ordinal36 */
-	uint32_t compute_wave_restore_addr_hi;  /* ordinal37 */
-	uint32_t compute_wave_restore_control;  /* ordinal38 */
-	uint32_t reserved9;  /* ordinal39 */
-	uint32_t reserved10;  /* ordinal40 */
-	uint32_t reserved11;  /* ordinal41 */
-	uint32_t reserved12;  /* ordinal42 */
-	uint32_t reserved13;  /* ordinal43 */
-	uint32_t reserved14;  /* ordinal44 */
-	uint32_t reserved15;  /* ordinal45 */
-	uint32_t reserved16;  /* ordinal46 */
-	uint32_t reserved17;  /* ordinal47 */
-	uint32_t reserved18;  /* ordinal48 */
-	uint32_t reserved19;  /* ordinal49 */
-	uint32_t reserved20;  /* ordinal50 */
-	uint32_t reserved21;  /* ordinal51 */
-	uint32_t reserved22;  /* ordinal52 */
-	uint32_t reserved23;  /* ordinal53 */
-	uint32_t reserved24;  /* ordinal54 */
-	uint32_t reserved25;  /* ordinal55 */
-	uint32_t reserved26;  /* ordinal56 */
-	uint32_t reserved27;  /* ordinal57 */
-	uint32_t reserved28;  /* ordinal58 */
-	uint32_t reserved29;  /* ordinal59 */
-	uint32_t reserved30;  /* ordinal60 */
-	uint32_t reserved31;  /* ordinal61 */
-	uint32_t reserved32;  /* ordinal62 */
-	uint32_t reserved33;  /* ordinal63 */
-	uint32_t reserved34;  /* ordinal64 */
-	uint32_t compute_user_data_0;  /* ordinal65 */
-	uint32_t compute_user_data_1;  /* ordinal66 */
-	uint32_t compute_user_data_2;  /* ordinal67 */
-	uint32_t compute_user_data_3;  /* ordinal68 */
-	uint32_t compute_user_data_4;  /* ordinal69 */
-	uint32_t compute_user_data_5;  /* ordinal70 */
-	uint32_t compute_user_data_6;  /* ordinal71 */
-	uint32_t compute_user_data_7;  /* ordinal72 */
-	uint32_t compute_user_data_8;  /* ordinal73 */
-	uint32_t compute_user_data_9;  /* ordinal74 */
-	uint32_t compute_user_data_10;  /* ordinal75 */
-	uint32_t compute_user_data_11;  /* ordinal76 */
-	uint32_t compute_user_data_12;  /* ordinal77 */
-	uint32_t compute_user_data_13;  /* ordinal78 */
-	uint32_t compute_user_data_14;  /* ordinal79 */
-	uint32_t compute_user_data_15;  /* ordinal80 */
-	uint32_t cp_compute_csinvoc_count_lo;  /* ordinal81 */
-	uint32_t cp_compute_csinvoc_count_hi;  /* ordinal82 */
-	uint32_t reserved35;  /* ordinal83 */
-	uint32_t reserved36;  /* ordinal84 */
-	uint32_t reserved37;  /* ordinal85 */
-	uint32_t cp_mqd_query_time_lo;  /* ordinal86 */
-	uint32_t cp_mqd_query_time_hi;  /* ordinal87 */
-	uint32_t cp_mqd_connect_start_time_lo;  /* ordinal88 */
-	uint32_t cp_mqd_connect_start_time_hi;  /* ordinal89 */
-	uint32_t cp_mqd_connect_end_time_lo;  /* ordinal90 */
-	uint32_t cp_mqd_connect_end_time_hi;  /* ordinal91 */
-	uint32_t cp_mqd_connect_end_wf_count;  /* ordinal92 */
-	uint32_t cp_mqd_connect_end_pq_rptr;  /* ordinal93 */
-	uint32_t cp_mqd_connect_end_pq_wptr;  /* ordinal94 */
-	uint32_t cp_mqd_connect_end_ib_rptr;  /* ordinal95 */
-	uint32_t reserved38;  /* ordinal96 */
-	uint32_t reserved39;  /* ordinal97 */
-	uint32_t cp_mqd_save_start_time_lo;  /* ordinal98 */
-	uint32_t cp_mqd_save_start_time_hi;  /* ordinal99 */
-	uint32_t cp_mqd_save_end_time_lo;  /* ordinal100 */
-	uint32_t cp_mqd_save_end_time_hi;  /* ordinal101 */
-	uint32_t cp_mqd_restore_start_time_lo;  /* ordinal102 */
-	uint32_t cp_mqd_restore_start_time_hi;  /* ordinal103 */
-	uint32_t cp_mqd_restore_end_time_lo;  /* ordinal104 */
-	uint32_t cp_mqd_restore_end_time_hi;  /* ordinal105 */
-	uint32_t reserved40;  /* ordinal106 */
-	uint32_t reserved41;  /* ordinal107 */
-	uint32_t gds_cs_ctxsw_cnt0;  /* ordinal108 */
-	uint32_t gds_cs_ctxsw_cnt1;  /* ordinal109 */
-	uint32_t gds_cs_ctxsw_cnt2;  /* ordinal110 */
-	uint32_t gds_cs_ctxsw_cnt3;  /* ordinal111 */
-	uint32_t reserved42;  /* ordinal112 */
-	uint32_t reserved43;  /* ordinal113 */
-	uint32_t cp_pq_exe_status_lo;  /* ordinal114 */
-	uint32_t cp_pq_exe_status_hi;  /* ordinal115 */
-	uint32_t cp_packet_id_lo;  /* ordinal116 */
-	uint32_t cp_packet_id_hi;  /* ordinal117 */
-	uint32_t cp_packet_exe_status_lo;  /* ordinal118 */
-	uint32_t cp_packet_exe_status_hi;  /* ordinal119 */
-	uint32_t gds_save_base_addr_lo;  /* ordinal120 */
-	uint32_t gds_save_base_addr_hi;  /* ordinal121 */
-	uint32_t gds_save_mask_lo;  /* ordinal122 */
-	uint32_t gds_save_mask_hi;  /* ordinal123 */
-	uint32_t ctx_save_base_addr_lo;  /* ordinal124 */
-	uint32_t ctx_save_base_addr_hi;  /* ordinal125 */
-	uint32_t reserved44;  /* ordinal126 */
-	uint32_t reserved45;  /* ordinal127 */
-	uint32_t cp_mqd_base_addr_lo;  /* ordinal128 */
-	uint32_t cp_mqd_base_addr_hi;  /* ordinal129 */
-	uint32_t cp_hqd_active;  /* ordinal130 */
-	uint32_t cp_hqd_vmid;  /* ordinal131 */
-	uint32_t cp_hqd_persistent_state;  /* ordinal132 */
-	uint32_t cp_hqd_pipe_priority;  /* ordinal133 */
-	uint32_t cp_hqd_queue_priority;  /* ordinal134 */
-	uint32_t cp_hqd_quantum;  /* ordinal135 */
-	uint32_t cp_hqd_pq_base_lo;  /* ordinal136 */
-	uint32_t cp_hqd_pq_base_hi;  /* ordinal137 */
-	uint32_t cp_hqd_pq_rptr;  /* ordinal138 */
-	uint32_t cp_hqd_pq_rptr_report_addr_lo;  /* ordinal139 */
-	uint32_t cp_hqd_pq_rptr_report_addr_hi;  /* ordinal140 */
-	uint32_t cp_hqd_pq_wptr_poll_addr;  /* ordinal141 */
-	uint32_t cp_hqd_pq_wptr_poll_addr_hi;  /* ordinal142 */
-	uint32_t cp_hqd_pq_doorbell_control;  /* ordinal143 */
-	uint32_t cp_hqd_pq_wptr;  /* ordinal144 */
-	uint32_t cp_hqd_pq_control;  /* ordinal145 */
-	uint32_t cp_hqd_ib_base_addr_lo;  /* ordinal146 */
-	uint32_t cp_hqd_ib_base_addr_hi;  /* ordinal147 */
-	uint32_t cp_hqd_ib_rptr;  /* ordinal148 */
-	uint32_t cp_hqd_ib_control;  /* ordinal149 */
-	uint32_t cp_hqd_iq_timer;  /* ordinal150 */
-	uint32_t cp_hqd_iq_rptr;  /* ordinal151 */
-	uint32_t cp_hqd_dequeue_request;  /* ordinal152 */
-	uint32_t cp_hqd_dma_offload;  /* ordinal153 */
-	uint32_t cp_hqd_sema_cmd;  /* ordinal154 */
-	uint32_t cp_hqd_msg_type;  /* ordinal155 */
-	uint32_t cp_hqd_atomic0_preop_lo;  /* ordinal156 */
-	uint32_t cp_hqd_atomic0_preop_hi;  /* ordinal157 */
-	uint32_t cp_hqd_atomic1_preop_lo;  /* ordinal158 */
-	uint32_t cp_hqd_atomic1_preop_hi;  /* ordinal159 */
-	uint32_t cp_hqd_hq_status0;  /* ordinal160 */
-	uint32_t cp_hqd_hq_control0;  /* ordinal161 */
-	uint32_t cp_mqd_control;  /* ordinal162 */
-	uint32_t cp_hqd_hq_status1;  /* ordinal163 */
-	uint32_t cp_hqd_hq_control1;  /* ordinal164 */
-	uint32_t cp_hqd_eop_base_addr_lo;  /* ordinal165 */
-	uint32_t cp_hqd_eop_base_addr_hi;  /* ordinal166 */
-	uint32_t cp_hqd_eop_control;  /* ordinal167 */
-	uint32_t cp_hqd_eop_rptr;  /* ordinal168 */
-	uint32_t cp_hqd_eop_wptr;  /* ordinal169 */
-	uint32_t cp_hqd_eop_done_events;  /* ordinal170 */
-	uint32_t cp_hqd_ctx_save_base_addr_lo;  /* ordinal171 */
-	uint32_t cp_hqd_ctx_save_base_addr_hi;  /* ordinal172 */
-	uint32_t cp_hqd_ctx_save_control;  /* ordinal173 */
-	uint32_t cp_hqd_cntl_stack_offset;  /* ordinal174 */
-	uint32_t cp_hqd_cntl_stack_size;  /* ordinal175 */
-	uint32_t cp_hqd_wg_state_offset;  /* ordinal176 */
-	uint32_t cp_hqd_ctx_save_size;  /* ordinal177 */
-	uint32_t cp_hqd_gds_resource_state;  /* ordinal178 */
-	uint32_t cp_hqd_error;  /* ordinal179 */
-	uint32_t cp_hqd_eop_wptr_mem;  /* ordinal180 */
-	uint32_t cp_hqd_eop_dones;  /* ordinal181 */
-	uint32_t reserved46;  /* ordinal182 */
-	uint32_t reserved47;  /* ordinal183 */
-	uint32_t reserved48;  /* ordinal184 */
-	uint32_t reserved49;  /* ordinal185 */
-	uint32_t reserved50;  /* ordinal186 */
-	uint32_t reserved51;  /* ordinal187 */
-	uint32_t reserved52;  /* ordinal188 */
-	uint32_t reserved53;  /* ordinal189 */
-	uint32_t reserved54;  /* ordinal190 */
-	uint32_t reserved55;  /* ordinal191 */
-	uint32_t iqtimer_pkt_header;  /* ordinal192 */
-	uint32_t iqtimer_pkt_dw0;  /* ordinal193 */
-	uint32_t iqtimer_pkt_dw1;  /* ordinal194 */
-	uint32_t iqtimer_pkt_dw2;  /* ordinal195 */
-	uint32_t iqtimer_pkt_dw3;  /* ordinal196 */
-	uint32_t iqtimer_pkt_dw4;  /* ordinal197 */
-	uint32_t iqtimer_pkt_dw5;  /* ordinal198 */
-	uint32_t iqtimer_pkt_dw6;  /* ordinal199 */
-	uint32_t iqtimer_pkt_dw7;  /* ordinal200 */
-	uint32_t iqtimer_pkt_dw8;  /* ordinal201 */
-	uint32_t iqtimer_pkt_dw9;  /* ordinal202 */
-	uint32_t iqtimer_pkt_dw10;  /* ordinal203 */
-	uint32_t iqtimer_pkt_dw11;  /* ordinal204 */
-	uint32_t iqtimer_pkt_dw12;  /* ordinal205 */
-	uint32_t iqtimer_pkt_dw13;  /* ordinal206 */
-	uint32_t iqtimer_pkt_dw14;  /* ordinal207 */
-	uint32_t iqtimer_pkt_dw15;  /* ordinal208 */
-	uint32_t iqtimer_pkt_dw16;  /* ordinal209 */
-	uint32_t iqtimer_pkt_dw17;  /* ordinal210 */
-	uint32_t iqtimer_pkt_dw18;  /* ordinal211 */
-	uint32_t iqtimer_pkt_dw19;  /* ordinal212 */
-	uint32_t iqtimer_pkt_dw20;  /* ordinal213 */
-	uint32_t iqtimer_pkt_dw21;  /* ordinal214 */
-	uint32_t iqtimer_pkt_dw22;  /* ordinal215 */
-	uint32_t iqtimer_pkt_dw23;  /* ordinal216 */
-	uint32_t iqtimer_pkt_dw24;  /* ordinal217 */
-	uint32_t iqtimer_pkt_dw25;  /* ordinal218 */
-	uint32_t iqtimer_pkt_dw26;  /* ordinal219 */
-	uint32_t iqtimer_pkt_dw27;  /* ordinal220 */
-	uint32_t iqtimer_pkt_dw28;  /* ordinal221 */
-	uint32_t iqtimer_pkt_dw29;  /* ordinal222 */
-	uint32_t iqtimer_pkt_dw30;  /* ordinal223 */
-	uint32_t iqtimer_pkt_dw31;  /* ordinal224 */
-	uint32_t reserved56;  /* ordinal225 */
-	uint32_t reserved57;  /* ordinal226 */
-	uint32_t reserved58;  /* ordinal227 */
-	uint32_t set_resources_header;  /* ordinal228 */
-	uint32_t set_resources_dw1;  /* ordinal229 */
-	uint32_t set_resources_dw2;  /* ordinal230 */
-	uint32_t set_resources_dw3;  /* ordinal231 */
-	uint32_t set_resources_dw4;  /* ordinal232 */
-	uint32_t set_resources_dw5;  /* ordinal233 */
-	uint32_t set_resources_dw6;  /* ordinal234 */
-	uint32_t set_resources_dw7;  /* ordinal235 */
-	uint32_t reserved59;  /* ordinal236 */
-	uint32_t reserved60;  /* ordinal237 */
-	uint32_t reserved61;  /* ordinal238 */
-	uint32_t reserved62;  /* ordinal239 */
-	uint32_t reserved63;  /* ordinal240 */
-	uint32_t reserved64;  /* ordinal241 */
-	uint32_t reserved65;  /* ordinal242 */
-	uint32_t reserved66;  /* ordinal243 */
-	uint32_t reserved67;  /* ordinal244 */
-	uint32_t reserved68;  /* ordinal245 */
-	uint32_t reserved69;  /* ordinal246 */
-	uint32_t reserved70;  /* ordinal247 */
-	uint32_t reserved71;  /* ordinal248 */
-	uint32_t reserved72;  /* ordinal249 */
-	uint32_t reserved73;  /* ordinal250 */
-	uint32_t reserved74;  /* ordinal251 */
-	uint32_t reserved75;  /* ordinal252 */
-	uint32_t reserved76;  /* ordinal253 */
-	uint32_t reserved77;  /* ordinal254 */
-	uint32_t reserved78;  /* ordinal255 */
-
-	uint32_t reserved_t[256]; /* Reserve 256 dword buffer used by ucode */
-};
-
 static void gfx_v8_0_cp_compute_fini(struct amdgpu_device *adev)
 {
 	int i, r;
@@ -4715,34 +4466,7 @@ static int gfx_v8_0_cp_compute_resume(st
 	u32 *buf;
 	struct vi_mqd *mqd;
 
-	/* init the pipes */
-	mutex_lock(&adev->srbm_mutex);
-	for (i = 0; i < (adev->gfx.mec.num_pipe * adev->gfx.mec.num_mec); i++) {
-		int me = (i < 4) ? 1 : 2;
-		int pipe = (i < 4) ? i : (i - 4);
-
-		eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i * MEC_HPD_SIZE);
-		eop_gpu_addr >>= 8;
-
-		vi_srbm_select(adev, me, pipe, 0, 0);
-
-		/* write the EOP addr */
-		WREG32(mmCP_HQD_EOP_BASE_ADDR, eop_gpu_addr);
-		WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr));
-
-		/* set the VMID assigned */
-		WREG32(mmCP_HQD_VMID, 0);
-
-		/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
-		tmp = RREG32(mmCP_HQD_EOP_CONTROL);
-		tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
-				    (order_base_2(MEC_HPD_SIZE / 4) - 1));
-		WREG32(mmCP_HQD_EOP_CONTROL, tmp);
-	}
-	vi_srbm_select(adev, 0, 0, 0, 0);
-	mutex_unlock(&adev->srbm_mutex);
-
-	/* init the queues.  Just two for now. */
+	/* init the queues.  */
 	for (i = 0; i < adev->gfx.num_compute_rings; i++) {
 		struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
 
@@ -4794,6 +4518,22 @@ static int gfx_v8_0_cp_compute_resume(st
 			       ring->pipe,
 			       ring->queue, 0);
 
+		eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i * MEC_HPD_SIZE);
+		eop_gpu_addr >>= 8;
+
+		/* write the EOP addr */
+		WREG32(mmCP_HQD_EOP_BASE_ADDR, eop_gpu_addr);
+		WREG32(mmCP_HQD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr));
+
+		/* set the VMID assigned */
+		WREG32(mmCP_HQD_VMID, 0);
+
+		/* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
+		tmp = RREG32(mmCP_HQD_EOP_CONTROL);
+		tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
+				    (order_base_2(MEC_HPD_SIZE / 4) - 1));
+		WREG32(mmCP_HQD_EOP_CONTROL, tmp);
+
 		/* disable wptr polling */
 		tmp = RREG32(mmCP_PQ_WPTR_POLL_CNTL);
 		tmp = REG_SET_FIELD(tmp, CP_PQ_WPTR_POLL_CNTL, EN, 0);
@@ -4877,9 +4617,9 @@ static int gfx_v8_0_cp_compute_resume(st
 
 		/* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
 		wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
-		mqd->cp_hqd_pq_wptr_poll_addr = wb_gpu_addr & 0xfffffffc;
+		mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
 		mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
-		WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr);
+		WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR, mqd->cp_hqd_pq_wptr_poll_addr_lo);
 		WREG32(mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
 		       mqd->cp_hqd_pq_wptr_poll_addr_hi);
 
@@ -4889,7 +4629,8 @@ static int gfx_v8_0_cp_compute_resume(st
 			    (adev->asic_type == CHIP_FIJI) ||
 			    (adev->asic_type == CHIP_STONEY) ||
 			    (adev->asic_type == CHIP_POLARIS11) ||
-			    (adev->asic_type == CHIP_POLARIS10)) {
+			    (adev->asic_type == CHIP_POLARIS10) ||
+			    (adev->asic_type == CHIP_POLARIS12)) {
 				WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
 				       AMDGPU_DOORBELL_KIQ << 2);
 				WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
@@ -4925,7 +4666,8 @@ static int gfx_v8_0_cp_compute_resume(st
 		mqd->cp_hqd_persistent_state = tmp;
 		if (adev->asic_type == CHIP_STONEY ||
 			adev->asic_type == CHIP_POLARIS11 ||
-			adev->asic_type == CHIP_POLARIS10) {
+			adev->asic_type == CHIP_POLARIS10 ||
+			adev->asic_type == CHIP_POLARIS12) {
 			tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL);
 			tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1);
 			WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp);
@@ -5050,6 +4792,10 @@ static int gfx_v8_0_hw_fini(void *handle
 
 	amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
 	amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
+	if (amdgpu_sriov_vf(adev)) {
+		pr_debug("For SRIOV client, shouldn't do anything.\n");
+		return 0;
+	}
 	gfx_v8_0_cp_enable(adev, false);
 	gfx_v8_0_rlc_stop(adev);
 	gfx_v8_0_cp_compute_fini(adev);
@@ -5392,9 +5138,70 @@ static void gfx_v8_0_ring_emit_gds_switc
 	amdgpu_ring_write(ring, (1 << (oa_size + oa_base)) - (1 << oa_base));
 }
 
+static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
+{
+	WREG32(mmSQ_IND_INDEX,
+		(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+		(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+		(address << SQ_IND_INDEX__INDEX__SHIFT) |
+		(SQ_IND_INDEX__FORCE_READ_MASK));
+	return RREG32(mmSQ_IND_DATA);
+}
+
+static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
+			   uint32_t wave, uint32_t thread,
+			   uint32_t regno, uint32_t num, uint32_t *out)
+{
+	WREG32(mmSQ_IND_INDEX,
+		(wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
+		(simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
+		(regno << SQ_IND_INDEX__INDEX__SHIFT) |
+		(thread << SQ_IND_INDEX__THREAD_ID__SHIFT) |
+		(SQ_IND_INDEX__FORCE_READ_MASK) |
+		(SQ_IND_INDEX__AUTO_INCR_MASK));
+	while (num--)
+		*(out++) = RREG32(mmSQ_IND_DATA);
+}
+
+static void gfx_v8_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
+{
+	/* type 0 wave data */
+	dst[(*no_fields)++] = 0;
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_STATUS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_PC_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_EXEC_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_HW_ID);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW0);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_INST_DW1);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_GPR_ALLOC);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_LDS_ALLOC);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TRAPSTS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_STS);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TBA_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_LO);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_TMA_HI);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_IB_DBG0);
+	dst[(*no_fields)++] = wave_read_ind(adev, simd, wave, ixSQ_WAVE_M0);
+}
+
+static void gfx_v8_0_read_wave_sgprs(struct amdgpu_device *adev, uint32_t simd,
+				     uint32_t wave, uint32_t start,
+				     uint32_t size, uint32_t *dst)
+{
+	wave_read_regs(
+		adev, simd, wave, 0,
+		start + SQIND_WAVE_SGPRS_OFFSET, size, dst);
+}
+
+
 static const struct amdgpu_gfx_funcs gfx_v8_0_gfx_funcs = {
 	.get_gpu_clock_counter = &gfx_v8_0_get_gpu_clock_counter,
 	.select_se_sh = &gfx_v8_0_select_se_sh,
+	.read_wave_data = &gfx_v8_0_read_wave_data,
+	.read_wave_sgprs = &gfx_v8_0_read_wave_sgprs,
 };
 
 static int gfx_v8_0_early_init(void *handle)
@@ -5439,7 +5246,8 @@ static int gfx_v8_0_late_init(void *hand
 static void gfx_v8_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev,
 						       bool enable)
 {
-	if (adev->asic_type == CHIP_POLARIS11)
+	if ((adev->asic_type == CHIP_POLARIS11) ||
+	    (adev->asic_type == CHIP_POLARIS12))
 		/* Send msg to SMU via Powerplay */
 		amdgpu_set_powergating_state(adev,
 					     AMD_IP_BLOCK_TYPE_SMC,
@@ -5496,14 +5304,11 @@ static int gfx_v8_0_set_powergating_stat
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	bool enable = (state == AMD_PG_STATE_GATE) ? true : false;
 
-	if (!(adev->pg_flags & AMD_PG_SUPPORT_GFX_PG))
-		return 0;
-
 	switch (adev->asic_type) {
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
-		if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)
-			cz_update_gfx_cg_power_gating(adev, enable);
+
+		cz_update_gfx_cg_power_gating(adev, enable);
 
 		if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG) && enable)
 			gfx_v8_0_enable_gfx_static_mg_power_gating(adev, true);
@@ -5516,6 +5321,7 @@ static int gfx_v8_0_set_powergating_stat
 			gfx_v8_0_enable_gfx_dynamic_mg_power_gating(adev, false);
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		if ((adev->pg_flags & AMD_PG_SUPPORT_GFX_SMG) && enable)
 			gfx_v8_0_enable_gfx_static_mg_power_gating(adev, true);
 		else
@@ -5846,29 +5652,24 @@ static void gfx_v8_0_update_coarse_grain
 	adev->gfx.rlc.funcs->enter_safe_mode(adev);
 
 	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
-		/* 1 enable cntx_empty_int_enable/cntx_busy_int_enable/
-		 * Cmp_busy/GFX_Idle interrupts
-		 */
-		gfx_v8_0_enable_gui_idle_interrupt(adev, true);
-
 		temp1 = data1 =	RREG32(mmRLC_CGTT_MGCG_OVERRIDE);
 		data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK;
 		if (temp1 != data1)
 			WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1);
 
-		/* 2 wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
+		/* : wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
-		/* 3 - clear cgcg override */
+		/* 2 - clear cgcg override */
 		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, CLE_BPM_SERDES_CMD);
 
 		/* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */
 		gfx_v8_0_wait_for_rlc_serdes(adev);
 
-		/* 4 - write cmd to set CGLS */
+		/* 3 - write cmd to set CGLS */
 		gfx_v8_0_send_serdes_cmd(adev, BPM_REG_CGLS_EN, SET_BPM_SERDES_CMD);
 
-		/* 5 - enable cgcg */
+		/* 4 - enable cgcg */
 		data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
 
 		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) {
@@ -5886,6 +5687,11 @@ static void gfx_v8_0_update_coarse_grain
 
 		if (temp != data)
 			WREG32(mmRLC_CGCG_CGLS_CTRL, data);
+
+		/* 5 enable cntx_empty_int_enable/cntx_busy_int_enable/
+		 * Cmp_busy/GFX_Idle interrupts
+		 */
+		gfx_v8_0_enable_gui_idle_interrupt(adev, true);
 	} else {
 		/* disable cntx_empty_int_enable & GFX Idle interrupt */
 		gfx_v8_0_enable_gui_idle_interrupt(adev, false);
@@ -5948,25 +5754,49 @@ static int gfx_v8_0_update_gfx_clock_gat
 static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev,
 					  enum amd_clockgating_state state)
 {
-	uint32_t msg_id, pp_state;
+	uint32_t msg_id, pp_state = 0;
+	uint32_t pp_support_state = 0;
 	void *pp_handle = adev->powerplay.pp_handle;
 
-	if (state == AMD_CG_STATE_UNGATE)
-		pp_state = 0;
-	else
-		pp_state = PP_STATE_CG | PP_STATE_LS;
+	if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) {
+			pp_support_state = PP_STATE_SUPPORT_LS;
+			pp_state = PP_STATE_LS;
+		}
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG) {
+			pp_support_state |= PP_STATE_SUPPORT_CG;
+			pp_state |= PP_STATE_CG;
+		}
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
-			PP_BLOCK_GFX_CG,
-			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-			pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+		msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+				PP_BLOCK_GFX_CG,
+				pp_support_state,
+				pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
-			PP_BLOCK_GFX_MG,
-			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-			pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+	if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) {
+			pp_support_state = PP_STATE_SUPPORT_LS;
+			pp_state = PP_STATE_LS;
+		}
+
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG) {
+			pp_support_state |= PP_STATE_SUPPORT_CG;
+			pp_state |= PP_STATE_CG;
+		}
+
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+
+		msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+				PP_BLOCK_GFX_MG,
+				pp_support_state,
+				pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
 	return 0;
 }
@@ -5974,43 +5804,98 @@ static int gfx_v8_0_tonga_update_gfx_clo
 static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev,
 					  enum amd_clockgating_state state)
 {
-	uint32_t msg_id, pp_state;
+
+	uint32_t msg_id, pp_state = 0;
+	uint32_t pp_support_state = 0;
 	void *pp_handle = adev->powerplay.pp_handle;
 
-	if (state == AMD_CG_STATE_UNGATE)
-		pp_state = 0;
-	else
-		pp_state = PP_STATE_CG | PP_STATE_LS;
+	if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) {
+			pp_support_state = PP_STATE_SUPPORT_LS;
+			pp_state = PP_STATE_LS;
+		}
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG) {
+			pp_support_state |= PP_STATE_SUPPORT_CG;
+			pp_state |= PP_STATE_CG;
+		}
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
-			PP_BLOCK_GFX_CG,
-			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-			pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+		msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+				PP_BLOCK_GFX_CG,
+				pp_support_state,
+				pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
-			PP_BLOCK_GFX_3D,
-			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-			pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+	if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS) {
+			pp_support_state = PP_STATE_SUPPORT_LS;
+			pp_state = PP_STATE_LS;
+		}
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG) {
+			pp_support_state |= PP_STATE_SUPPORT_CG;
+			pp_state |= PP_STATE_CG;
+		}
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
-			PP_BLOCK_GFX_MG,
-			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-			pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+		msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+				PP_BLOCK_GFX_3D,
+				pp_support_state,
+				pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
-			PP_BLOCK_GFX_RLC,
-			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-			pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+	if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) {
+			pp_support_state = PP_STATE_SUPPORT_LS;
+			pp_state = PP_STATE_LS;
+		}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG) {
+			pp_support_state |= PP_STATE_SUPPORT_CG;
+			pp_state |= PP_STATE_CG;
+		}
+
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+
+		msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+				PP_BLOCK_GFX_MG,
+				pp_support_state,
+				pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
+
+	if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) {
+		pp_support_state = PP_STATE_SUPPORT_LS;
+
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		else
+			pp_state = PP_STATE_LS;
+
+		msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
+				PP_BLOCK_GFX_RLC,
+				pp_support_state,
+				pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
+
+	if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) {
+		pp_support_state = PP_STATE_SUPPORT_LS;
+
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		else
+			pp_state = PP_STATE_LS;
+		msg_id = PP_CG_MSG_ID(PP_GROUP_GFX,
 			PP_BLOCK_GFX_CP,
-			PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
+			pp_support_state,
 			pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
 	return 0;
 }
@@ -6074,7 +5959,7 @@ static void gfx_v8_0_ring_emit_hdp_flush
 {
 	u32 ref_and_mask, reg_mem_engine;
 
-	if (ring->type == AMDGPU_RING_TYPE_COMPUTE) {
+	if (ring->funcs->type == AMDGPU_RING_TYPE_COMPUTE) {
 		switch (ring->me) {
 		case 1:
 			ref_and_mask = GPU_HDP_FLUSH_DONE__CP2_MASK << ring->pipe;
@@ -6102,6 +5987,18 @@ static void gfx_v8_0_ring_emit_hdp_flush
 	amdgpu_ring_write(ring, 0x20); /* poll interval */
 }
 
+static void gfx_v8_0_ring_emit_vgt_flush(struct amdgpu_ring *ring)
+{
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VS_PARTIAL_FLUSH) |
+		EVENT_INDEX(4));
+
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0));
+	amdgpu_ring_write(ring, EVENT_TYPE(VGT_FLUSH) |
+		EVENT_INDEX(0));
+}
+
+
 static void gfx_v8_0_ring_emit_hdp_invalidate(struct amdgpu_ring *ring)
 {
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
@@ -6176,7 +6073,7 @@ static void gfx_v8_0_ring_emit_fence_gfx
 
 static void gfx_v8_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 {
-	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
+	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
 	uint32_t seq = ring->fence_drv.sync_seq;
 	uint64_t addr = ring->fence_drv.gpu_addr;
 
@@ -6194,11 +6091,7 @@ static void gfx_v8_0_ring_emit_pipeline_
 static void gfx_v8_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
 					unsigned vm_id, uint64_t pd_addr)
 {
-	int usepfp = (ring->type == AMDGPU_RING_TYPE_GFX);
-
-	/* GFX8 emits 128 dw nop to prevent DE do vm_flush before CE finish CEIB */
-	if (usepfp)
-		amdgpu_ring_insert_nop(ring, 128);
+	int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
 
 	amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
 	amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(usepfp) |
@@ -6291,6 +6184,7 @@ static void gfx_v8_ring_emit_cntxcntl(st
 
 	dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */
 	if (flags & AMDGPU_HAVE_CTX_SWITCH) {
+		gfx_v8_0_ring_emit_vgt_flush(ring);
 		/* set load_global_config & load_global_uconfig */
 		dw2 |= 0x8001;
 		/* set load_cs_sh_regs */
@@ -6314,42 +6208,6 @@ static void gfx_v8_ring_emit_cntxcntl(st
 	amdgpu_ring_write(ring, 0);
 }
 
-static unsigned gfx_v8_0_ring_get_emit_ib_size_gfx(struct amdgpu_ring *ring)
-{
-	return
-		4; /* gfx_v8_0_ring_emit_ib_gfx */
-}
-
-static unsigned gfx_v8_0_ring_get_dma_frame_size_gfx(struct amdgpu_ring *ring)
-{
-	return
-		20 + /* gfx_v8_0_ring_emit_gds_switch */
-		7 + /* gfx_v8_0_ring_emit_hdp_flush */
-		5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
-		6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */
-		7 + /* gfx_v8_0_ring_emit_pipeline_sync */
-		256 + 19 + /* gfx_v8_0_ring_emit_vm_flush */
-		2 + /* gfx_v8_ring_emit_sb */
-		3; /* gfx_v8_ring_emit_cntxcntl */
-}
-
-static unsigned gfx_v8_0_ring_get_emit_ib_size_compute(struct amdgpu_ring *ring)
-{
-	return
-		4; /* gfx_v8_0_ring_emit_ib_compute */
-}
-
-static unsigned gfx_v8_0_ring_get_dma_frame_size_compute(struct amdgpu_ring *ring)
-{
-	return
-		20 + /* gfx_v8_0_ring_emit_gds_switch */
-		7 + /* gfx_v8_0_ring_emit_hdp_flush */
-		5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
-		7 + /* gfx_v8_0_ring_emit_pipeline_sync */
-		17 + /* gfx_v8_0_ring_emit_vm_flush */
-		7 + 7 + 7; /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */
-}
-
 static void gfx_v8_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
 						 enum amdgpu_interrupt_state state)
 {
@@ -6495,7 +6353,7 @@ static int gfx_v8_0_priv_inst_irq(struct
 	return 0;
 }
 
-const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
+static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
 	.name = "gfx_v8_0",
 	.early_init = gfx_v8_0_early_init,
 	.late_init = gfx_v8_0_late_init,
@@ -6516,10 +6374,22 @@ const struct amd_ip_funcs gfx_v8_0_ip_fu
 };
 
 static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
+	.type = AMDGPU_RING_TYPE_GFX,
+	.align_mask = 0xff,
+	.nop = PACKET3(PACKET3_NOP, 0x3FFF),
 	.get_rptr = gfx_v8_0_ring_get_rptr,
 	.get_wptr = gfx_v8_0_ring_get_wptr_gfx,
 	.set_wptr = gfx_v8_0_ring_set_wptr_gfx,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		20 + /* gfx_v8_0_ring_emit_gds_switch */
+		7 + /* gfx_v8_0_ring_emit_hdp_flush */
+		5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
+		6 + 6 + 6 +/* gfx_v8_0_ring_emit_fence_gfx x3 for user fence, vm fence */
+		7 + /* gfx_v8_0_ring_emit_pipeline_sync */
+		128 + 19 + /* gfx_v8_0_ring_emit_vm_flush */
+		2 + /* gfx_v8_ring_emit_sb */
+		3 + 4, /* gfx_v8_ring_emit_cntxcntl including vgt flush */
+	.emit_ib_size =	4, /* gfx_v8_0_ring_emit_ib_gfx */
 	.emit_ib = gfx_v8_0_ring_emit_ib_gfx,
 	.emit_fence = gfx_v8_0_ring_emit_fence_gfx,
 	.emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync,
@@ -6533,15 +6403,23 @@ static const struct amdgpu_ring_funcs gf
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.emit_switch_buffer = gfx_v8_ring_emit_sb,
 	.emit_cntxcntl = gfx_v8_ring_emit_cntxcntl,
-	.get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_gfx,
-	.get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_gfx,
 };
 
 static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = {
+	.type = AMDGPU_RING_TYPE_COMPUTE,
+	.align_mask = 0xff,
+	.nop = PACKET3(PACKET3_NOP, 0x3FFF),
 	.get_rptr = gfx_v8_0_ring_get_rptr,
 	.get_wptr = gfx_v8_0_ring_get_wptr_compute,
 	.set_wptr = gfx_v8_0_ring_set_wptr_compute,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		20 + /* gfx_v8_0_ring_emit_gds_switch */
+		7 + /* gfx_v8_0_ring_emit_hdp_flush */
+		5 + /* gfx_v8_0_ring_emit_hdp_invalidate */
+		7 + /* gfx_v8_0_ring_emit_pipeline_sync */
+		17 + /* gfx_v8_0_ring_emit_vm_flush */
+		7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */
+	.emit_ib_size =	4, /* gfx_v8_0_ring_emit_ib_compute */
 	.emit_ib = gfx_v8_0_ring_emit_ib_compute,
 	.emit_fence = gfx_v8_0_ring_emit_fence_compute,
 	.emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync,
@@ -6553,8 +6431,6 @@ static const struct amdgpu_ring_funcs gf
 	.test_ib = gfx_v8_0_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
 	.pad_ib = amdgpu_ring_generic_pad_ib,
-	.get_emit_ib_size = gfx_v8_0_ring_get_emit_ib_size_compute,
-	.get_dma_frame_size = gfx_v8_0_ring_get_dma_frame_size_compute,
 };
 
 static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -6707,3 +6583,21 @@ static void gfx_v8_0_get_cu_info(struct
 	cu_info->number = active_cu_number;
 	cu_info->ao_cu_mask = ao_cu_mask;
 }
+
+const struct amdgpu_ip_block_version gfx_v8_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GFX,
+	.major = 8,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &gfx_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gfx_v8_1_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GFX,
+	.major = 8,
+	.minor = 1,
+	.rev = 0,
+	.funcs = &gfx_v8_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@
 #ifndef __GFX_V8_0_H__
 #define __GFX_V8_0_H__
 
-extern const struct amd_ip_funcs gfx_v8_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gfx_v8_0_ip_block;
+extern const struct amdgpu_ip_block_version gfx_v8_1_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c	2016-12-11 17:41:56.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c	2017-02-12 17:25:03.000000000 -0500
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2014 Advanced Micro Devices, Inc.
  *
@@ -26,7 +25,16 @@
 #include "amdgpu.h"
 #include "gmc_v6_0.h"
 #include "amdgpu_ucode.h"
-#include "si/sid.h"
+
+#include "bif/bif_3_0_d.h"
+#include "bif/bif_3_0_sh_mask.h"
+#include "oss/oss_1_0_d.h"
+#include "oss/oss_1_0_sh_mask.h"
+#include "gmc/gmc_6_0_d.h"
+#include "gmc/gmc_6_0_sh_mask.h"
+#include "dce/dce_6_0_d.h"
+#include "dce/dce_6_0_sh_mask.h"
+#include "si_enums.h"
 
 static void gmc_v6_0_set_gart_funcs(struct amdgpu_device *adev);
 static void gmc_v6_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -34,6 +42,16 @@ static int gmc_v6_0_wait_for_idle(void *
 
 /*(DEBLOBBED)*/
 
+#define MC_SEQ_MISC0__MT__MASK   0xf0000000
+#define MC_SEQ_MISC0__MT__GDDR1  0x10000000
+#define MC_SEQ_MISC0__MT__DDR2   0x20000000
+#define MC_SEQ_MISC0__MT__GDDR3  0x30000000
+#define MC_SEQ_MISC0__MT__GDDR4  0x40000000
+#define MC_SEQ_MISC0__MT__GDDR5  0x50000000
+#define MC_SEQ_MISC0__MT__HBM    0x60000000
+#define MC_SEQ_MISC0__MT__DDR3   0xB0000000
+
+
 static const u32 crtc_offsets[6] =
 {
 	SI_CRTC0_REGISTER_OFFSET,
@@ -54,14 +72,14 @@ static void gmc_v6_0_mc_stop(struct amdg
 
 	gmc_v6_0_wait_for_idle((void *)adev);
 
-	blackout = RREG32(MC_SHARED_BLACKOUT_CNTL);
-	if (REG_GET_FIELD(blackout, mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE) != 1) {
+	blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
+	if (REG_GET_FIELD(blackout, MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE) != 1) {
 		/* Block CPU access */
-		WREG32(BIF_FB_EN, 0);
+		WREG32(mmBIF_FB_EN, 0);
 		/* blackout the MC */
 		blackout = REG_SET_FIELD(blackout,
-					 mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE, 0);
-		WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1);
+					 MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE, 0);
+		WREG32(mmMC_SHARED_BLACKOUT_CNTL, blackout | 1);
 	}
 	/* wait for the MC to settle */
 	udelay(100);
@@ -74,13 +92,13 @@ static void gmc_v6_0_mc_resume(struct am
 	u32 tmp;
 
 	/* unblackout the MC */
-	tmp = RREG32(MC_SHARED_BLACKOUT_CNTL);
-	tmp = REG_SET_FIELD(tmp, mmMC_SHARED_BLACKOUT_CNTL, xxBLACKOUT_MODE, 0);
-	WREG32(MC_SHARED_BLACKOUT_CNTL, tmp);
+	tmp = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
+	tmp = REG_SET_FIELD(tmp, MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE, 0);
+	WREG32(mmMC_SHARED_BLACKOUT_CNTL, tmp);
 	/* allow CPU access */
-	tmp = REG_SET_FIELD(0, mmBIF_FB_EN, xxFB_READ_EN, 1);
-	tmp = REG_SET_FIELD(tmp, mmBIF_FB_EN, xxFB_WRITE_EN, 1);
-	WREG32(BIF_FB_EN, tmp);
+	tmp = REG_SET_FIELD(0, BIF_FB_EN, FB_READ_EN, 1);
+	tmp = REG_SET_FIELD(tmp, BIF_FB_EN, FB_WRITE_EN, 1);
+	WREG32(mmBIF_FB_EN, tmp);
 
 	if (adev->mode_info.num_crtc)
 		amdgpu_display_resume_mc_access(adev, save);
@@ -92,6 +110,7 @@ static int gmc_v6_0_init_microcode(struc
 	const char *chip_name;
 	char fw_name[30];
 	int err;
+	bool is_58_fw = false;
 
 	DRM_DEBUG("\n");
 
@@ -114,7 +133,14 @@ static int gmc_v6_0_init_microcode(struc
 	default: BUG();
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
+	/* this memory configuration requires special firmware */
+	if (((RREG32(mmMC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
+		is_58_fw = true;
+
+	if (is_58_fw)
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/");
+	else
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
 	err = reject_firmware(&adev->mc.fw, fw_name, adev->dev);
 	if (err)
 		goto out;
@@ -155,37 +181,37 @@ static int gmc_v6_0_mc_load_microcode(st
 	new_fw_data = (const __le32 *)
 		(adev->mc.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
 
-	running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
+	running = RREG32(mmMC_SEQ_SUP_CNTL) & MC_SEQ_SUP_CNTL__RUN_MASK;
 
 	if (running == 0) {
 
 		/* reset the engine and set to writable */
-		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
-		WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
+		WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
+		WREG32(mmMC_SEQ_SUP_CNTL, 0x00000010);
 
 		/* load mc io regs */
 		for (i = 0; i < regs_size; i++) {
-			WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
-			WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
+			WREG32(mmMC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
+			WREG32(mmMC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
 		}
 		/* load the MC ucode */
 		for (i = 0; i < ucode_size; i++) {
-			WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
+			WREG32(mmMC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
 		}
 
 		/* put the engine back into the active state */
-		WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
-		WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
-		WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
+		WREG32(mmMC_SEQ_SUP_CNTL, 0x00000008);
+		WREG32(mmMC_SEQ_SUP_CNTL, 0x00000004);
+		WREG32(mmMC_SEQ_SUP_CNTL, 0x00000001);
 
 		/* wait for training to complete */
 		for (i = 0; i < adev->usec_timeout; i++) {
-			if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0)
+			if (RREG32(mmMC_SEQ_TRAIN_WAKEUP_CNTL) & MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D0_MASK)
 				break;
 			udelay(1);
 		}
 		for (i = 0; i < adev->usec_timeout; i++) {
-			if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1)
+			if (RREG32(mmMC_SEQ_TRAIN_WAKEUP_CNTL) & MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D1_MASK)
 				break;
 			udelay(1);
 		}
@@ -222,7 +248,10 @@ static void gmc_v6_0_mc_program(struct a
 		WREG32((0xb08 + j), 0x00000000);
 		WREG32((0xb09 + j), 0x00000000);
 	}
-	WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0);
+	WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
+
+	if (adev->mode_info.num_crtc)
+		amdgpu_display_set_vga_render_state(adev, false);
 
 	gmc_v6_0_mc_stop(adev, &save);
 
@@ -230,30 +259,29 @@ static void gmc_v6_0_mc_program(struct a
 		dev_warn(adev->dev, "Wait for MC idle timedout !\n");
 	}
 
-	WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
+	WREG32(mmVGA_HDP_CONTROL, VGA_HDP_CONTROL__VGA_MEMORY_DISABLE_MASK);
 	/* Update configuration */
-	WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
+	WREG32(mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
 	       adev->mc.vram_start >> 12);
-	WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
+	WREG32(mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
 	       adev->mc.vram_end >> 12);
-	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR,
+	WREG32(mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR,
 	       adev->vram_scratch.gpu_addr >> 12);
 	tmp = ((adev->mc.vram_end >> 24) & 0xFFFF) << 16;
 	tmp |= ((adev->mc.vram_start >> 24) & 0xFFFF);
-	WREG32(MC_VM_FB_LOCATION, tmp);
+	WREG32(mmMC_VM_FB_LOCATION, tmp);
 	/* XXX double check these! */
-	WREG32(HDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8));
-	WREG32(HDP_NONSURFACE_INFO, (2 << 7) | (1 << 30));
-	WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
-	WREG32(MC_VM_AGP_BASE, 0);
-	WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
-	WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
+	WREG32(mmHDP_NONSURFACE_BASE, (adev->mc.vram_start >> 8));
+	WREG32(mmHDP_NONSURFACE_INFO, (2 << 7) | (1 << 30));
+	WREG32(mmHDP_NONSURFACE_SIZE, 0x3FFFFFFF);
+	WREG32(mmMC_VM_AGP_BASE, 0);
+	WREG32(mmMC_VM_AGP_TOP, 0x0FFFFFFF);
+	WREG32(mmMC_VM_AGP_BOT, 0x0FFFFFFF);
 
 	if (gmc_v6_0_wait_for_idle((void *)adev)) {
 		dev_warn(adev->dev, "Wait for MC idle timedout !\n");
 	}
 	gmc_v6_0_mc_resume(adev, &save);
-	amdgpu_display_set_vga_render_state(adev, false);
 }
 
 static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
@@ -262,16 +290,16 @@ static int gmc_v6_0_mc_init(struct amdgp
 	u32 tmp;
 	int chansize, numchan;
 
-	tmp = RREG32(MC_ARB_RAMCFG);
-	if (tmp & CHANSIZE_OVERRIDE) {
+	tmp = RREG32(mmMC_ARB_RAMCFG);
+	if (tmp & (1 << 11)) {
 		chansize = 16;
-	} else if (tmp & CHANSIZE_MASK) {
+	} else if (tmp & MC_ARB_RAMCFG__CHANSIZE_MASK) {
 		chansize = 64;
 	} else {
 		chansize = 32;
 	}
-	tmp = RREG32(MC_SHARED_CHMAP);
-	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+	tmp = RREG32(mmMC_SHARED_CHMAP);
+	switch ((tmp & MC_SHARED_CHMAP__NOOFCHAN_MASK) >> MC_SHARED_CHMAP__NOOFCHAN__SHIFT) {
 	case 0:
 	default:
 		numchan = 1;
@@ -306,15 +334,15 @@ static int gmc_v6_0_mc_init(struct amdgp
 	adev->mc.aper_base = pci_resource_start(adev->pdev, 0);
 	adev->mc.aper_size = pci_resource_len(adev->pdev, 0);
 	/* size in MB on si */
-	adev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
-	adev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+	adev->mc.mc_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+	adev->mc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
 	adev->mc.visible_vram_size = adev->mc.aper_size;
 
 	/* unless the user had overridden it, set the gart
 	 * size equal to the 1024 or vram, whichever is larger.
 	 */
 	if (amdgpu_gart_size == -1)
-		adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+		adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
 	else
 		adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
 
@@ -326,9 +354,9 @@ static int gmc_v6_0_mc_init(struct amdgp
 static void gmc_v6_0_gart_flush_gpu_tlb(struct amdgpu_device *adev,
 					uint32_t vmid)
 {
-	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0);
+	WREG32(mmHDP_MEM_COHERENCY_FLUSH_CNTL, 0);
 
-	WREG32(VM_INVALIDATE_REQUEST, 1 << vmid);
+	WREG32(mmVM_INVALIDATE_REQUEST, 1 << vmid);
 }
 
 static int gmc_v6_0_gart_set_pte_pde(struct amdgpu_device *adev,
@@ -352,20 +380,20 @@ static void gmc_v6_0_set_fault_enable_de
 {
 	u32 tmp;
 
-	tmp = RREG32(VM_CONTEXT1_CNTL);
-	tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
-			    xxRANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
-	tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
-			    xxDUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
-	tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
-			    xxPDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
-	tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
-			    xxVALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
-	tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
-			    xxREAD_PROTECTION_FAULT_ENABLE_DEFAULT, value);
-	tmp = REG_SET_FIELD(tmp, mmVM_CONTEXT1_CNTL,
-			    xxWRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
-	WREG32(VM_CONTEXT1_CNTL, tmp);
+	tmp = RREG32(mmVM_CONTEXT1_CNTL);
+	tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+			    RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+	tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+			    DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+	tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+			    PDE0_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+	tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+			    VALID_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+	tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+			    READ_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+	tmp = REG_SET_FIELD(tmp, VM_CONTEXT1_CNTL,
+			    WRITE_PROTECTION_FAULT_ENABLE_DEFAULT, value);
+	WREG32(mmVM_CONTEXT1_CNTL, tmp);
 }
 
 static int gmc_v6_0_gart_enable(struct amdgpu_device *adev)
@@ -380,33 +408,39 @@ static int gmc_v6_0_gart_enable(struct a
 	if (r)
 		return r;
 	/* Setup TLB control */
-	WREG32(MC_VM_MX_L1_TLB_CNTL,
+	WREG32(mmMC_VM_MX_L1_TLB_CNTL,
 	       (0xA << 7) |
-	       ENABLE_L1_TLB |
-	       ENABLE_L1_FRAGMENT_PROCESSING |
-	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
-	       ENABLE_ADVANCED_DRIVER_MODEL |
-	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+	       MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_TLB_MASK |
+	       MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_FRAGMENT_PROCESSING_MASK |
+	       MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE_MASK |
+	       MC_VM_MX_L1_TLB_CNTL__ENABLE_ADVANCED_DRIVER_MODEL_MASK |
+	       (0UL << MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS__SHIFT));
 	/* Setup L2 cache */
-	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
-	       ENABLE_L2_FRAGMENT_PROCESSING |
-	       ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
-	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
-	       EFFECTIVE_L2_QUEUE_SIZE(7) |
-	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
-	WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
-	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
-	       BANK_SELECT(4) |
-	       L2_CACHE_BIGK_FRAGMENT_SIZE(4));
+	WREG32(mmVM_L2_CNTL,
+	       VM_L2_CNTL__ENABLE_L2_CACHE_MASK |
+	       VM_L2_CNTL__ENABLE_L2_FRAGMENT_PROCESSING_MASK |
+	       VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+	       VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+	       (7UL << VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE__SHIFT) |
+	       (1UL << VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE__SHIFT));
+	WREG32(mmVM_L2_CNTL2,
+	       VM_L2_CNTL2__INVALIDATE_ALL_L1_TLBS_MASK |
+	       VM_L2_CNTL2__INVALIDATE_L2_CACHE_MASK);
+	WREG32(mmVM_L2_CNTL3,
+	       VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY_MASK |
+	       (4UL << VM_L2_CNTL3__BANK_SELECT__SHIFT) |
+	       (4UL << VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE__SHIFT));
 	/* setup context0 */
-	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12);
-	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12);
-	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12);
-	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
+	WREG32(mmVM_CONTEXT0_PAGE_TABLE_START_ADDR, adev->mc.gtt_start >> 12);
+	WREG32(mmVM_CONTEXT0_PAGE_TABLE_END_ADDR, adev->mc.gtt_end >> 12);
+	WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR, adev->gart.table_addr >> 12);
+	WREG32(mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
 			(u32)(adev->dummy_page.addr >> 12));
-	WREG32(VM_CONTEXT0_CNTL2, 0);
-	WREG32(VM_CONTEXT0_CNTL, (ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
-				  RANGE_PROTECTION_FAULT_ENABLE_DEFAULT));
+	WREG32(mmVM_CONTEXT0_CNTL2, 0);
+	WREG32(mmVM_CONTEXT0_CNTL,
+	       VM_CONTEXT0_CNTL__ENABLE_CONTEXT_MASK |
+	       (0UL << VM_CONTEXT0_CNTL__PAGE_TABLE_DEPTH__SHIFT) |
+	       VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK);
 
 	WREG32(0x575, 0);
 	WREG32(0x576, 0);
@@ -414,39 +448,33 @@ static int gmc_v6_0_gart_enable(struct a
 
 	/* empty context1-15 */
 	/* set vm size, must be a multiple of 4 */
-	WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
-	WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, adev->vm_manager.max_pfn - 1);
+	WREG32(mmVM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
+	WREG32(mmVM_CONTEXT1_PAGE_TABLE_END_ADDR, adev->vm_manager.max_pfn - 1);
 	/* Assign the pt base to something valid for now; the pts used for
 	 * the VMs are determined by the application and setup and assigned
 	 * on the fly in the vm part of radeon_gart.c
 	 */
 	for (i = 1; i < 16; i++) {
 		if (i < 8)
-			WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i,
+			WREG32(mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR + i,
 			       adev->gart.table_addr >> 12);
 		else
-			WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8,
+			WREG32(mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR + i - 8,
 			       adev->gart.table_addr >> 12);
 	}
 
 	/* enable context1-15 */
-	WREG32(VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR,
+	WREG32(mmVM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR,
 	       (u32)(adev->dummy_page.addr >> 12));
-	WREG32(VM_CONTEXT1_CNTL2, 4);
-	WREG32(VM_CONTEXT1_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(1) |
-				PAGE_TABLE_BLOCK_SIZE(amdgpu_vm_block_size - 9) |
-				RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
-				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT |
-				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT |
-				DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT |
-				PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT |
-				PDE0_PROTECTION_FAULT_ENABLE_DEFAULT |
-				VALID_PROTECTION_FAULT_ENABLE_INTERRUPT |
-				VALID_PROTECTION_FAULT_ENABLE_DEFAULT |
-				READ_PROTECTION_FAULT_ENABLE_INTERRUPT |
-				READ_PROTECTION_FAULT_ENABLE_DEFAULT |
-				WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT |
-				WRITE_PROTECTION_FAULT_ENABLE_DEFAULT);
+	WREG32(mmVM_CONTEXT1_CNTL2, 4);
+	WREG32(mmVM_CONTEXT1_CNTL,
+	       VM_CONTEXT1_CNTL__ENABLE_CONTEXT_MASK |
+	       (1UL << VM_CONTEXT1_CNTL__PAGE_TABLE_DEPTH__SHIFT) |
+	       ((amdgpu_vm_block_size - 9) << VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT));
+	if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_ALWAYS)
+		gmc_v6_0_set_fault_enable_default(adev, false);
+	else
+		gmc_v6_0_set_fault_enable_default(adev, true);
 
 	gmc_v6_0_gart_flush_gpu_tlb(adev, 0);
 	dev_info(adev->dev, "PCIE GART of %uM enabled (table at 0x%016llX).\n",
@@ -485,19 +513,22 @@ static void gmc_v6_0_gart_disable(struct
 	}*/
 
 	/* Disable all tables */
-	WREG32(VM_CONTEXT0_CNTL, 0);
-	WREG32(VM_CONTEXT1_CNTL, 0);
+	WREG32(mmVM_CONTEXT0_CNTL, 0);
+	WREG32(mmVM_CONTEXT1_CNTL, 0);
 	/* Setup TLB control */
-	WREG32(MC_VM_MX_L1_TLB_CNTL, SYSTEM_ACCESS_MODE_NOT_IN_SYS |
-	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+	WREG32(mmMC_VM_MX_L1_TLB_CNTL,
+	       MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE_MASK |
+	       (0UL << MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS__SHIFT));
 	/* Setup L2 cache */
-	WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
-	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
-	       EFFECTIVE_L2_QUEUE_SIZE(7) |
-	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
-	WREG32(VM_L2_CNTL2, 0);
-	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
-	       L2_CACHE_BIGK_FRAGMENT_SIZE(0));
+	WREG32(mmVM_L2_CNTL,
+	       VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+	       VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE_MASK |
+	       (7UL << VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE__SHIFT) |
+	       (1UL << VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE__SHIFT));
+	WREG32(mmVM_L2_CNTL2, 0);
+	WREG32(mmVM_L2_CNTL3,
+	       VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY_MASK |
+	       (0UL << VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE__SHIFT));
 	amdgpu_gart_table_vram_unpin(adev);
 }
 
@@ -520,7 +551,7 @@ static int gmc_v6_0_vm_init(struct amdgp
 
 	/* base offset of vram pages */
 	if (adev->flags & AMD_IS_APU) {
-		u64 tmp = RREG32(MC_VM_FB_OFFSET);
+		u64 tmp = RREG32(mmMC_VM_FB_OFFSET);
 		tmp <<= 22;
 		adev->vm_manager.vram_base_offset = tmp;
 	} else
@@ -537,19 +568,19 @@ static void gmc_v6_0_vm_decode_fault(str
 				     u32 status, u32 addr, u32 mc_client)
 {
 	u32 mc_id;
-	u32 vmid = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS, xxVMID);
-	u32 protections = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS,
-					xxPROTECTIONS);
+	u32 vmid = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID);
+	u32 protections = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
+					PROTECTIONS);
 	char block[5] = { mc_client >> 24, (mc_client >> 16) & 0xff,
 		(mc_client >> 8) & 0xff, mc_client & 0xff, 0 };
 
-	mc_id = REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS,
-			      xxMEMORY_CLIENT_ID);
+	mc_id = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
+			      MEMORY_CLIENT_ID);
 
 	dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
 	       protections, vmid, addr,
-	       REG_GET_FIELD(status, mmVM_CONTEXT1_PROTECTION_FAULT_STATUS,
-			     xxMEMORY_CLIENT_RW) ?
+	       REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
+			     MEMORY_CLIENT_RW) ?
 	       "write" : "read", block, mc_client, mc_id);
 }
 
@@ -652,7 +683,7 @@ static void gmc_v6_0_enable_hdp_mgcg(str
 {
 	u32 orig, data;
 
-	orig = data = RREG32(HDP_HOST_PATH_CNTL);
+	orig = data = RREG32(mmHDP_HOST_PATH_CNTL);
 
 	if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_MGCG))
 		data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 0);
@@ -660,7 +691,7 @@ static void gmc_v6_0_enable_hdp_mgcg(str
 		data = REG_SET_FIELD(data, HDP_HOST_PATH_CNTL, CLOCK_GATING_DIS, 1);
 
 	if (orig != data)
-		WREG32(HDP_HOST_PATH_CNTL, data);
+		WREG32(mmHDP_HOST_PATH_CNTL, data);
 }
 
 static void gmc_v6_0_enable_hdp_ls(struct amdgpu_device *adev,
@@ -668,7 +699,7 @@ static void gmc_v6_0_enable_hdp_ls(struc
 {
 	u32 orig, data;
 
-	orig = data = RREG32(HDP_MEM_POWER_LS);
+	orig = data = RREG32(mmHDP_MEM_POWER_LS);
 
 	if (enable && (adev->cg_flags & AMDGPU_CG_SUPPORT_HDP_LS))
 		data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 1);
@@ -676,7 +707,7 @@ static void gmc_v6_0_enable_hdp_ls(struc
 		data = REG_SET_FIELD(data, HDP_MEM_POWER_LS, LS_ENABLE, 0);
 
 	if (orig != data)
-		WREG32(HDP_MEM_POWER_LS, data);
+		WREG32(mmHDP_MEM_POWER_LS, data);
 }
 */
 
@@ -710,7 +741,7 @@ static int gmc_v6_0_early_init(void *han
 	if (adev->flags & AMD_IS_APU) {
 		adev->mc.vram_type = AMDGPU_VRAM_TYPE_UNKNOWN;
 	} else {
-		u32 tmp = RREG32(MC_SEQ_MISC0);
+		u32 tmp = RREG32(mmMC_SEQ_MISC0);
 		tmp &= MC_SEQ_MISC0__MT__MASK;
 		adev->mc.vram_type = gmc_v6_0_convert_vram_type(tmp);
 	}
@@ -722,7 +753,10 @@ static int gmc_v6_0_late_init(void *hand
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
+	if (amdgpu_vm_fault_stop != AMDGPU_VM_FAULT_STOP_ALWAYS)
+		return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
+	else
+		return 0;
 }
 
 static int gmc_v6_0_sw_init(void *handle)
@@ -763,11 +797,6 @@ static int gmc_v6_0_sw_init(void *handle
 		return r;
 	}
 
-	r = amdgpu_ttm_global_init(adev);
-	if (r) {
-		return r;
-	}
-
 	r = gmc_v6_0_mc_init(adev);
 	if (r)
 		return r;
@@ -876,7 +905,7 @@ static int gmc_v6_0_resume(void *handle)
 static bool gmc_v6_0_is_idle(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	u32 tmp = RREG32(SRBM_STATUS);
+	u32 tmp = RREG32(mmSRBM_STATUS);
 
 	if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
 		   SRBM_STATUS__MCC_BUSY_MASK | SRBM_STATUS__MCD_BUSY_MASK | SRBM_STATUS__VMC_BUSY_MASK))
@@ -892,7 +921,7 @@ static int gmc_v6_0_wait_for_idle(void *
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
 	for (i = 0; i < adev->usec_timeout; i++) {
-		tmp = RREG32(SRBM_STATUS) & (SRBM_STATUS__MCB_BUSY_MASK |
+		tmp = RREG32(mmSRBM_STATUS) & (SRBM_STATUS__MCB_BUSY_MASK |
 					       SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
 					       SRBM_STATUS__MCC_BUSY_MASK |
 					       SRBM_STATUS__MCD_BUSY_MASK |
@@ -910,17 +939,17 @@ static int gmc_v6_0_soft_reset(void *han
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	struct amdgpu_mode_mc_save save;
 	u32 srbm_soft_reset = 0;
-	u32 tmp = RREG32(SRBM_STATUS);
+	u32 tmp = RREG32(mmSRBM_STATUS);
 
 	if (tmp & SRBM_STATUS__VMC_BUSY_MASK)
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset,
-						mmSRBM_SOFT_RESET, xxSOFT_RESET_VMC, 1);
+						SRBM_SOFT_RESET, SOFT_RESET_VMC, 1);
 
 	if (tmp & (SRBM_STATUS__MCB_BUSY_MASK | SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK |
 		   SRBM_STATUS__MCC_BUSY_MASK | SRBM_STATUS__MCD_BUSY_MASK)) {
 		if (!(adev->flags & AMD_IS_APU))
 			srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset,
-							mmSRBM_SOFT_RESET, xxSOFT_RESET_MC, 1);
+							SRBM_SOFT_RESET, SOFT_RESET_MC, 1);
 	}
 
 	if (srbm_soft_reset) {
@@ -930,17 +959,17 @@ static int gmc_v6_0_soft_reset(void *han
 		}
 
 
-		tmp = RREG32(SRBM_SOFT_RESET);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
 		tmp |= srbm_soft_reset;
 		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
-		WREG32(SRBM_SOFT_RESET, tmp);
-		tmp = RREG32(SRBM_SOFT_RESET);
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
 
 		udelay(50);
 
 		tmp &= ~srbm_soft_reset;
-		WREG32(SRBM_SOFT_RESET, tmp);
-		tmp = RREG32(SRBM_SOFT_RESET);
+		WREG32(mmSRBM_SOFT_RESET, tmp);
+		tmp = RREG32(mmSRBM_SOFT_RESET);
 
 		udelay(50);
 
@@ -966,20 +995,20 @@ static int gmc_v6_0_vm_fault_interrupt_s
 
 	switch (state) {
 	case AMDGPU_IRQ_STATE_DISABLE:
-		tmp = RREG32(VM_CONTEXT0_CNTL);
+		tmp = RREG32(mmVM_CONTEXT0_CNTL);
 		tmp &= ~bits;
-		WREG32(VM_CONTEXT0_CNTL, tmp);
-		tmp = RREG32(VM_CONTEXT1_CNTL);
+		WREG32(mmVM_CONTEXT0_CNTL, tmp);
+		tmp = RREG32(mmVM_CONTEXT1_CNTL);
 		tmp &= ~bits;
-		WREG32(VM_CONTEXT1_CNTL, tmp);
+		WREG32(mmVM_CONTEXT1_CNTL, tmp);
 		break;
 	case AMDGPU_IRQ_STATE_ENABLE:
-		tmp = RREG32(VM_CONTEXT0_CNTL);
+		tmp = RREG32(mmVM_CONTEXT0_CNTL);
 		tmp |= bits;
-		WREG32(VM_CONTEXT0_CNTL, tmp);
-		tmp = RREG32(VM_CONTEXT1_CNTL);
+		WREG32(mmVM_CONTEXT0_CNTL, tmp);
+		tmp = RREG32(mmVM_CONTEXT1_CNTL);
 		tmp |= bits;
-		WREG32(VM_CONTEXT1_CNTL, tmp);
+		WREG32(mmVM_CONTEXT1_CNTL, tmp);
 		break;
 	default:
 		break;
@@ -994,9 +1023,9 @@ static int gmc_v6_0_process_interrupt(st
 {
 	u32 addr, status;
 
-	addr = RREG32(VM_CONTEXT1_PROTECTION_FAULT_ADDR);
-	status = RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS);
-	WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1);
+	addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR);
+	status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS);
+	WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1);
 
 	if (!addr && !status)
 		return 0;
@@ -1004,13 +1033,15 @@ static int gmc_v6_0_process_interrupt(st
 	if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
 		gmc_v6_0_set_fault_enable_default(adev, false);
 
-	dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
-		entry->src_id, entry->src_data);
-	dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
-		addr);
-	dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
-		status);
-	gmc_v6_0_vm_decode_fault(adev, status, addr, 0);
+	if (printk_ratelimit()) {
+		dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
+			entry->src_id, entry->src_data);
+		dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
+			addr);
+		dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+			status);
+		gmc_v6_0_vm_decode_fault(adev, status, addr, 0);
+	}
 
 	return 0;
 }
@@ -1027,7 +1058,7 @@ static int gmc_v6_0_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs gmc_v6_0_ip_funcs = {
+static const struct amd_ip_funcs gmc_v6_0_ip_funcs = {
 	.name = "gmc_v6_0",
 	.early_init = gmc_v6_0_early_init,
 	.late_init = gmc_v6_0_late_init,
@@ -1066,3 +1097,11 @@ static void gmc_v6_0_set_irq_funcs(struc
 	adev->mc.vm_fault.funcs = &gmc_v6_0_irq_funcs;
 }
 
+const struct amdgpu_ip_block_version gmc_v6_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GMC,
+	.major = 6,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &gmc_v6_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __GMC_V6_0_H__
 #define __GMC_V6_0_H__
 
-extern const struct amd_ip_funcs gmc_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gmc_v6_0_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c	2016-12-11 17:41:42.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c	2017-02-12 17:24:43.000000000 -0500
@@ -383,7 +383,7 @@ static int gmc_v7_0_mc_init(struct amdgp
 	 * size equal to the 1024 or vram, whichever is larger.
 	 */
 	if (amdgpu_gart_size == -1)
-		adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+		adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
 	else
 		adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
 
@@ -709,7 +709,7 @@ static void gmc_v7_0_vm_decode_fault(str
 	mc_id = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
 			      MEMORY_CLIENT_ID);
 
-	printk("VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
+	dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
 	       protections, vmid, addr,
 	       REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
 			     MEMORY_CLIENT_RW) ?
@@ -943,11 +943,6 @@ static int gmc_v7_0_sw_init(void *handle
 		return r;
 	}
 
-	r = amdgpu_ttm_global_init(adev);
-	if (r) {
-		return r;
-	}
-
 	r = gmc_v7_0_mc_init(adev);
 	if (r)
 		return r;
@@ -1196,13 +1191,15 @@ static int gmc_v7_0_process_interrupt(st
 	if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
 		gmc_v7_0_set_fault_enable_default(adev, false);
 
-	dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
-		entry->src_id, entry->src_data);
-	dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
-		addr);
-	dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
-		status);
-	gmc_v7_0_vm_decode_fault(adev, status, addr, mc_client);
+	if (printk_ratelimit()) {
+		dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
+			entry->src_id, entry->src_data);
+		dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
+			addr);
+		dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+			status);
+		gmc_v7_0_vm_decode_fault(adev, status, addr, mc_client);
+	}
 
 	return 0;
 }
@@ -1233,7 +1230,7 @@ static int gmc_v7_0_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs gmc_v7_0_ip_funcs = {
+static const struct amd_ip_funcs gmc_v7_0_ip_funcs = {
 	.name = "gmc_v7_0",
 	.early_init = gmc_v7_0_early_init,
 	.late_init = gmc_v7_0_late_init,
@@ -1271,3 +1268,21 @@ static void gmc_v7_0_set_irq_funcs(struc
 	adev->mc.vm_fault.num_types = 1;
 	adev->mc.vm_fault.funcs = &gmc_v7_0_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version gmc_v7_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GMC,
+	.major = 7,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &gmc_v7_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gmc_v7_4_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GMC,
+	.major = 7,
+	.minor = 4,
+	.rev = 0,
+	.funcs = &gmc_v7_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@
 #ifndef __GMC_V7_0_H__
 #define __GMC_V7_0_H__
 
-extern const struct amd_ip_funcs gmc_v7_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gmc_v7_0_ip_block;
+extern const struct amdgpu_ip_block_version gmc_v7_4_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c	2016-12-11 17:41:08.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c	2017-02-12 17:23:52.000000000 -0500
@@ -128,6 +128,7 @@ static void gmc_v8_0_init_golden_registe
 						 (const u32)ARRAY_SIZE(golden_settings_tonga_a11));
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		amdgpu_program_register_sequence(adev,
 						 golden_settings_polaris11_a11,
 						 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -223,6 +224,9 @@ static int gmc_v8_0_init_microcode(struc
 	case CHIP_POLARIS10:
 		chip_name = "polaris10";
 		break;
+	case CHIP_POLARIS12:
+		chip_name = "polaris12";
+		break;
 	case CHIP_FIJI:
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
@@ -470,7 +474,7 @@ static int gmc_v8_0_mc_init(struct amdgp
 	 * size equal to the 1024 or vram, whichever is larger.
 	 */
 	if (amdgpu_gart_size == -1)
-		adev->mc.gtt_size = amdgpu_ttm_get_gtt_mem_size(adev);
+		adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
 	else
 		adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
 
@@ -835,7 +839,7 @@ static void gmc_v8_0_vm_decode_fault(str
 	mc_id = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
 			      MEMORY_CLIENT_ID);
 
-	printk("VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
+	dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n",
 	       protections, vmid, addr,
 	       REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS,
 			     MEMORY_CLIENT_RW) ?
@@ -950,11 +954,6 @@ static int gmc_v8_0_sw_init(void *handle
 		return r;
 	}
 
-	r = amdgpu_ttm_global_init(adev);
-	if (r) {
-		return r;
-	}
-
 	r = gmc_v8_0_mc_init(adev);
 	if (r)
 		return r;
@@ -1240,13 +1239,15 @@ static int gmc_v8_0_process_interrupt(st
 	if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST)
 		gmc_v8_0_set_fault_enable_default(adev, false);
 
-	dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
-		entry->src_id, entry->src_data);
-	dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
-		addr);
-	dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
-		status);
-	gmc_v8_0_vm_decode_fault(adev, status, addr, mc_client);
+	if (printk_ratelimit()) {
+		dev_err(adev->dev, "GPU fault detected: %d 0x%08x\n",
+			entry->src_id, entry->src_data);
+		dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_ADDR   0x%08X\n",
+			addr);
+		dev_err(adev->dev, "  VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n",
+			status);
+		gmc_v8_0_vm_decode_fault(adev, status, addr, mc_client);
+	}
 
 	return 0;
 }
@@ -1435,7 +1436,7 @@ static int gmc_v8_0_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs gmc_v8_0_ip_funcs = {
+static const struct amd_ip_funcs gmc_v8_0_ip_funcs = {
 	.name = "gmc_v8_0",
 	.early_init = gmc_v8_0_early_init,
 	.late_init = gmc_v8_0_late_init,
@@ -1476,3 +1477,30 @@ static void gmc_v8_0_set_irq_funcs(struc
 	adev->mc.vm_fault.num_types = 1;
 	adev->mc.vm_fault.funcs = &gmc_v8_0_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version gmc_v8_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GMC,
+	.major = 8,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &gmc_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gmc_v8_1_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GMC,
+	.major = 8,
+	.minor = 1,
+	.rev = 0,
+	.funcs = &gmc_v8_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version gmc_v8_5_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_GMC,
+	.major = 8,
+	.minor = 5,
+	.rev = 0,
+	.funcs = &gmc_v8_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,8 @@
 #ifndef __GMC_V8_0_H__
 #define __GMC_V8_0_H__
 
-extern const struct amd_ip_funcs gmc_v8_0_ip_funcs;
+extern const struct amdgpu_ip_block_version gmc_v8_0_ip_block;
+extern const struct amdgpu_ip_block_version gmc_v8_1_ip_block;
+extern const struct amdgpu_ip_block_version gmc_v8_5_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.c	2017-02-12 16:03:20.000000000 -0500
@@ -392,7 +392,7 @@ static int iceland_ih_set_powergating_st
 	return 0;
 }
 
-const struct amd_ip_funcs iceland_ih_ip_funcs = {
+static const struct amd_ip_funcs iceland_ih_ip_funcs = {
 	.name = "iceland_ih",
 	.early_init = iceland_ih_early_init,
 	.late_init = NULL,
@@ -421,3 +421,11 @@ static void iceland_ih_set_interrupt_fun
 		adev->irq.ih_funcs = &iceland_ih_funcs;
 }
 
+const struct amdgpu_ip_block_version iceland_ih_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_IH,
+	.major = 2,
+	.minor = 4,
+	.rev = 0,
+	.funcs = &iceland_ih_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/iceland_ih.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __ICELAND_IH_H__
 #define __ICELAND_IH_H__
 
-extern const struct amd_ip_funcs iceland_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version iceland_ih_ip_block;
 
 #endif /* __ICELAND_IH_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/kv_dpm.c	2017-02-12 16:03:20.000000000 -0500
@@ -2796,7 +2796,7 @@ static int kv_parse_power_table(struct a
 	adev->pm.dpm.num_ps = state_array->ucNumEntries;
 
 	/* fill in the vce power states */
-	for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) {
+	for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
 		u32 sclk;
 		clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
 		clock_info = (union pplib_clock_info *)
@@ -2845,7 +2845,7 @@ static int kv_dpm_init(struct amdgpu_dev
 		pi->caps_tcp_ramping = true;
 	}
 
-	if (amdgpu_sclk_deep_sleep_en)
+	if (amdgpu_pp_feature_mask & SCLK_DEEP_SLEEP_MASK)
 		pi->caps_sclk_ds = true;
 	else
 		pi->caps_sclk_ds = false;
@@ -3245,6 +3245,18 @@ static int kv_dpm_set_powergating_state(
 	return 0;
 }
 
+static int kv_check_state_equal(struct amdgpu_device *adev,
+				struct amdgpu_ps *cps,
+				struct amdgpu_ps *rps,
+				bool *equal)
+{
+	if (equal == NULL)
+		return -EINVAL;
+
+	*equal = false;
+	return 0;
+}
+
 const struct amd_ip_funcs kv_dpm_ip_funcs = {
 	.name = "kv_dpm",
 	.early_init = kv_dpm_early_init,
@@ -3275,6 +3287,8 @@ static const struct amdgpu_dpm_funcs kv_
 	.force_performance_level = &kv_dpm_force_performance_level,
 	.powergate_uvd = &kv_dpm_powergate_uvd,
 	.enable_bapm = &kv_dpm_enable_bapm,
+	.get_vce_clock_state = amdgpu_get_vce_clock_state,
+	.check_state_equal = kv_check_state_equal,
 };
 
 static void kv_dpm_set_dpm_funcs(struct amdgpu_device *adev)
@@ -3293,3 +3307,12 @@ static void kv_dpm_set_irq_funcs(struct
 	adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST;
 	adev->pm.dpm.thermal.irq.funcs = &kv_dpm_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version kv_dpm_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SMC,
+	.major = 7,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &kv_dpm_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o
 	atombios_encoders.o amdgpu_sa.o atombios_i2c.o \
 	amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \
 	amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \
-	amdgpu_gtt_mgr.o
+	amdgpu_gtt_mgr.o amdgpu_vram_mgr.o
 
 # add asic specific block
 amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/ObjectID.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/ObjectID.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/ObjectID.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/ObjectID.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,7 +90,6 @@
 #define ENCODER_OBJECT_ID_INTERNAL_VCE            0x24
 #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY3        0x25
 #define ENCODER_OBJECT_ID_INTERNAL_AMCLK          0x27
-#define ENCODER_OBJECT_ID_VIRTUAL                 0x28
 
 #define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO    0xFF
 
@@ -120,7 +119,6 @@
 #define CONNECTOR_OBJECT_ID_eDP                   0x14
 #define CONNECTOR_OBJECT_ID_MXM                   0x15
 #define CONNECTOR_OBJECT_ID_LVDS_eDP              0x16
-#define CONNECTOR_OBJECT_ID_VIRTUAL               0x17
 
 /* deleted */
 
@@ -149,7 +147,6 @@
 #define GRAPH_OBJECT_ENUM_ID5                     0x05
 #define GRAPH_OBJECT_ENUM_ID6                     0x06
 #define GRAPH_OBJECT_ENUM_ID7                     0x07
-#define GRAPH_OBJECT_ENUM_VIRTUAL                 0x08
 
 /****************************************************/
 /* Graphics Object ID Bit definition                */
@@ -411,10 +408,6 @@
                                                   GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
                                                   ENCODER_OBJECT_ID_HDMI_ANX9805 << OBJECT_ID_SHIFT)
 
-#define ENCODER_VIRTUAL_ENUM_VIRTUAL            ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
-                                                  GRAPH_OBJECT_ENUM_VIRTUAL << ENUM_ID_SHIFT |\
-                                                  ENCODER_OBJECT_ID_VIRTUAL << OBJECT_ID_SHIFT)
-
 /****************************************************/
 /* Connector Object ID definition - Shared with BIOS */
 /****************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c	2016-12-11 17:41:11.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c	2017-02-12 17:23:56.000000000 -0500
@@ -231,10 +231,10 @@ static void sdma_v2_4_ring_insert_nop(st
 
 	for (i = 0; i < count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
-			amdgpu_ring_write(ring, ring->nop |
+			amdgpu_ring_write(ring, ring->funcs->nop |
 				SDMA_PKT_NOP_HEADER_COUNT(count - 1));
 		else
-			amdgpu_ring_write(ring, ring->nop);
+			amdgpu_ring_write(ring, ring->funcs->nop);
 }
 
 /**
@@ -667,7 +667,7 @@ static int sdma_v2_4_ring_test_ib(struct
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	unsigned index;
 	u32 tmp = 0;
 	u64 gpu_addr;
@@ -704,7 +704,7 @@ static int sdma_v2_4_ring_test_ib(struct
 	if (r)
 		goto err1;
 
-	r = fence_wait_timeout(f, false, timeout);
+	r = dma_fence_wait_timeout(f, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out\n");
 		r = -ETIMEDOUT;
@@ -724,7 +724,7 @@ static int sdma_v2_4_ring_test_ib(struct
 
 err1:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 err0:
 	amdgpu_wb_free(adev, index);
 	return r;
@@ -774,11 +774,11 @@ static void sdma_v2_4_vm_write_pte(struc
 	unsigned ndw = count * 2;
 
 	ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
-		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
+		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR);
 	ib->ptr[ib->length_dw++] = pe;
 	ib->ptr[ib->length_dw++] = upper_32_bits(pe);
 	ib->ptr[ib->length_dw++] = ndw;
-	for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+	for (; ndw > 0; ndw -= 2) {
 		ib->ptr[ib->length_dw++] = lower_32_bits(value);
 		ib->ptr[ib->length_dw++] = upper_32_bits(value);
 		value += incr;
@@ -901,22 +901,6 @@ static void sdma_v2_4_ring_emit_vm_flush
 			  SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
 }
 
-static unsigned sdma_v2_4_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		7 + 6; /* sdma_v2_4_ring_emit_ib */
-}
-
-static unsigned sdma_v2_4_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		6 + /* sdma_v2_4_ring_emit_hdp_flush */
-		3 + /* sdma_v2_4_ring_emit_hdp_invalidate */
-		6 + /* sdma_v2_4_ring_emit_pipeline_sync */
-		12 + /* sdma_v2_4_ring_emit_vm_flush */
-		10 + 10 + 10; /* sdma_v2_4_ring_emit_fence x3 for user fence, vm fence */
-}
-
 static int sdma_v2_4_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -964,11 +948,10 @@ static int sdma_v2_4_sw_init(void *handl
 		ring->use_doorbell = false;
 		sprintf(ring->name, "sdma%d", i);
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
 				     &adev->sdma.trap_irq,
 				     (i == 0) ?
-				     AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
-				     AMDGPU_RING_TYPE_SDMA);
+				     AMDGPU_SDMA_IRQ_TRAP0 :
+				     AMDGPU_SDMA_IRQ_TRAP1);
 		if (r)
 			return r;
 	}
@@ -1203,7 +1186,7 @@ static int sdma_v2_4_set_powergating_sta
 	return 0;
 }
 
-const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
+static const struct amd_ip_funcs sdma_v2_4_ip_funcs = {
 	.name = "sdma_v2_4",
 	.early_init = sdma_v2_4_early_init,
 	.late_init = NULL,
@@ -1221,10 +1204,19 @@ const struct amd_ip_funcs sdma_v2_4_ip_f
 };
 
 static const struct amdgpu_ring_funcs sdma_v2_4_ring_funcs = {
+	.type = AMDGPU_RING_TYPE_SDMA,
+	.align_mask = 0xf,
+	.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
 	.get_rptr = sdma_v2_4_ring_get_rptr,
 	.get_wptr = sdma_v2_4_ring_get_wptr,
 	.set_wptr = sdma_v2_4_ring_set_wptr,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		6 + /* sdma_v2_4_ring_emit_hdp_flush */
+		3 + /* sdma_v2_4_ring_emit_hdp_invalidate */
+		6 + /* sdma_v2_4_ring_emit_pipeline_sync */
+		12 + /* sdma_v2_4_ring_emit_vm_flush */
+		10 + 10 + 10, /* sdma_v2_4_ring_emit_fence x3 for user fence, vm fence */
+	.emit_ib_size = 7 + 6, /* sdma_v2_4_ring_emit_ib */
 	.emit_ib = sdma_v2_4_ring_emit_ib,
 	.emit_fence = sdma_v2_4_ring_emit_fence,
 	.emit_pipeline_sync = sdma_v2_4_ring_emit_pipeline_sync,
@@ -1235,8 +1227,6 @@ static const struct amdgpu_ring_funcs sd
 	.test_ib = sdma_v2_4_ring_test_ib,
 	.insert_nop = sdma_v2_4_ring_insert_nop,
 	.pad_ib = sdma_v2_4_ring_pad_ib,
-	.get_emit_ib_size = sdma_v2_4_ring_get_emit_ib_size,
-	.get_dma_frame_size = sdma_v2_4_ring_get_dma_frame_size,
 };
 
 static void sdma_v2_4_set_ring_funcs(struct amdgpu_device *adev)
@@ -1349,3 +1339,12 @@ static void sdma_v2_4_set_vm_pte_funcs(s
 		adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
 	}
 }
+
+const struct amdgpu_ip_block_version sdma_v2_4_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SDMA,
+	.major = 2,
+	.minor = 4,
+	.rev = 0,
+	.funcs = &sdma_v2_4_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __SDMA_V2_4_H__
 #define __SDMA_V2_4_H__
 
-extern const struct amd_ip_funcs sdma_v2_4_ip_funcs;
+extern const struct amdgpu_ip_block_version sdma_v2_4_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c	2016-12-11 17:41:15.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c	2017-02-12 17:24:00.000000000 -0500
@@ -196,6 +196,7 @@ static void sdma_v3_0_init_golden_regist
 						 (const u32)ARRAY_SIZE(golden_settings_tonga_a11));
 		break;
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		amdgpu_program_register_sequence(adev,
 						 golden_settings_polaris11_a11,
 						 (const u32)ARRAY_SIZE(golden_settings_polaris11_a11));
@@ -268,6 +269,9 @@ static int sdma_v3_0_init_microcode(stru
 	case CHIP_POLARIS10:
 		chip_name = "polaris10";
 		break;
+	case CHIP_POLARIS12:
+		chip_name = "polaris12";
+		break;
 	case CHIP_CARRIZO:
 		chip_name = "carrizo";
 		break;
@@ -382,10 +386,10 @@ static void sdma_v3_0_ring_insert_nop(st
 
 	for (i = 0; i < count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
-			amdgpu_ring_write(ring, ring->nop |
+			amdgpu_ring_write(ring, ring->funcs->nop |
 				SDMA_PKT_NOP_HEADER_COUNT(count - 1));
 		else
-			amdgpu_ring_write(ring, ring->nop);
+			amdgpu_ring_write(ring, ring->funcs->nop);
 }
 
 /**
@@ -861,7 +865,7 @@ static int sdma_v3_0_ring_test_ib(struct
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	unsigned index;
 	u32 tmp = 0;
 	u64 gpu_addr;
@@ -898,7 +902,7 @@ static int sdma_v3_0_ring_test_ib(struct
 	if (r)
 		goto err1;
 
-	r = fence_wait_timeout(f, false, timeout);
+	r = dma_fence_wait_timeout(f, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out\n");
 		r = -ETIMEDOUT;
@@ -917,7 +921,7 @@ static int sdma_v3_0_ring_test_ib(struct
 	}
 err1:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 err0:
 	amdgpu_wb_free(adev, index);
 	return r;
@@ -967,11 +971,11 @@ static void sdma_v3_0_vm_write_pte(struc
 	unsigned ndw = count * 2;
 
 	ib->ptr[ib->length_dw++] = SDMA_PKT_HEADER_OP(SDMA_OP_WRITE) |
-		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_COPY_LINEAR);
+		SDMA_PKT_HEADER_SUB_OP(SDMA_SUBOP_WRITE_LINEAR);
 	ib->ptr[ib->length_dw++] = lower_32_bits(pe);
 	ib->ptr[ib->length_dw++] = upper_32_bits(pe);
 	ib->ptr[ib->length_dw++] = ndw;
-	for (; ndw > 0; ndw -= 2, --count, pe += 8) {
+	for (; ndw > 0; ndw -= 2) {
 		ib->ptr[ib->length_dw++] = lower_32_bits(value);
 		ib->ptr[ib->length_dw++] = upper_32_bits(value);
 		value += incr;
@@ -1094,22 +1098,6 @@ static void sdma_v3_0_ring_emit_vm_flush
 			  SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
 }
 
-static unsigned sdma_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		7 + 6; /* sdma_v3_0_ring_emit_ib */
-}
-
-static unsigned sdma_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		6 + /* sdma_v3_0_ring_emit_hdp_flush */
-		3 + /* sdma_v3_0_ring_emit_hdp_invalidate */
-		6 + /* sdma_v3_0_ring_emit_pipeline_sync */
-		12 + /* sdma_v3_0_ring_emit_vm_flush */
-		10 + 10 + 10; /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
-}
-
 static int sdma_v3_0_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -1167,11 +1155,10 @@ static int sdma_v3_0_sw_init(void *handl
 
 		sprintf(ring->name, "sdma%d", i);
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP), 0xf,
 				     &adev->sdma.trap_irq,
 				     (i == 0) ?
-				     AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
-				     AMDGPU_RING_TYPE_SDMA);
+				     AMDGPU_SDMA_IRQ_TRAP0 :
+				     AMDGPU_SDMA_IRQ_TRAP1);
 		if (r)
 			return r;
 	}
@@ -1534,7 +1521,7 @@ static int sdma_v3_0_set_powergating_sta
 	return 0;
 }
 
-const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
+static const struct amd_ip_funcs sdma_v3_0_ip_funcs = {
 	.name = "sdma_v3_0",
 	.early_init = sdma_v3_0_early_init,
 	.late_init = NULL,
@@ -1555,10 +1542,19 @@ const struct amd_ip_funcs sdma_v3_0_ip_f
 };
 
 static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
+	.type = AMDGPU_RING_TYPE_SDMA,
+	.align_mask = 0xf,
+	.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
 	.get_rptr = sdma_v3_0_ring_get_rptr,
 	.get_wptr = sdma_v3_0_ring_get_wptr,
 	.set_wptr = sdma_v3_0_ring_set_wptr,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		6 + /* sdma_v3_0_ring_emit_hdp_flush */
+		3 + /* sdma_v3_0_ring_emit_hdp_invalidate */
+		6 + /* sdma_v3_0_ring_emit_pipeline_sync */
+		12 + /* sdma_v3_0_ring_emit_vm_flush */
+		10 + 10 + 10, /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
+	.emit_ib_size = 7 + 6, /* sdma_v3_0_ring_emit_ib */
 	.emit_ib = sdma_v3_0_ring_emit_ib,
 	.emit_fence = sdma_v3_0_ring_emit_fence,
 	.emit_pipeline_sync = sdma_v3_0_ring_emit_pipeline_sync,
@@ -1569,8 +1565,6 @@ static const struct amdgpu_ring_funcs sd
 	.test_ib = sdma_v3_0_ring_test_ib,
 	.insert_nop = sdma_v3_0_ring_insert_nop,
 	.pad_ib = sdma_v3_0_ring_pad_ib,
-	.get_emit_ib_size = sdma_v3_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = sdma_v3_0_ring_get_dma_frame_size,
 };
 
 static void sdma_v3_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -1683,3 +1677,21 @@ static void sdma_v3_0_set_vm_pte_funcs(s
 		adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
 	}
 }
+
+const struct amdgpu_ip_block_version sdma_v3_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SDMA,
+	.major = 3,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &sdma_v3_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version sdma_v3_1_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SDMA,
+	.major = 3,
+	.minor = 1,
+	.rev = 0,
+	.funcs = &sdma_v3_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@
 #ifndef __SDMA_V3_0_H__
 #define __SDMA_V3_0_H__
 
-extern const struct amd_ip_funcs sdma_v3_0_ip_funcs;
+extern const struct amdgpu_ip_block_version sdma_v3_0_ip_block;
+extern const struct amdgpu_ip_block_version sdma_v3_1_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,16 +39,18 @@
 #include "si_dma.h"
 #include "dce_v6_0.h"
 #include "si.h"
+#include "dce_virtual.h"
 
 static const u32 tahiti_golden_registers[] =
 {
+	0x17bc, 0x00000030, 0x00000011,
 	0x2684, 0x00010000, 0x00018208,
 	0x260c, 0xffffffff, 0x00000000,
 	0x260d, 0xf00fffff, 0x00000400,
 	0x260e, 0x0002021c, 0x00020200,
 	0x031e, 0x00000080, 0x00000000,
-	0x340c, 0x000300c0, 0x00800040,
-	0x360c, 0x000300c0, 0x00800040,
+	0x340c, 0x000000c0, 0x00800040,
+	0x360c, 0x000000c0, 0x00800040,
 	0x16ec, 0x000000f0, 0x00000070,
 	0x16f0, 0x00200000, 0x50100000,
 	0x1c0c, 0x31000311, 0x00000011,
@@ -59,7 +61,7 @@ static const u32 tahiti_golden_registers
 	0x22c4, 0x0000ff0f, 0x00000000,
 	0xa293, 0x07ffffff, 0x4e000000,
 	0xa0d4, 0x3f3f3fff, 0x2a00126a,
-	0x000c, 0x000000ff, 0x0040,
+	0x000c, 0xffffffff, 0x0040,
 	0x000d, 0x00000040, 0x00004040,
 	0x2440, 0x07ffffff, 0x03000000,
 	0x23a2, 0x01ff1f3f, 0x00000000,
@@ -72,7 +74,11 @@ static const u32 tahiti_golden_registers
 	0x2234, 0xffffffff, 0x000fff40,
 	0x2235, 0x0000001f, 0x00000010,
 	0x0504, 0x20000000, 0x20fffed8,
-	0x0570, 0x000c0fc0, 0x000c0400
+	0x0570, 0x000c0fc0, 0x000c0400,
+	0x052c, 0x0fffffff, 0xffffffff,
+	0x052d, 0x0fffffff, 0x0fffffff,
+	0x052e, 0x0fffffff, 0x0fffffff,
+	0x052f, 0x0fffffff, 0x0fffffff
 };
 
 static const u32 tahiti_golden_registers2[] =
@@ -82,16 +88,18 @@ static const u32 tahiti_golden_registers
 
 static const u32 tahiti_golden_rlc_registers[] =
 {
+	0x263e, 0xffffffff, 0x12011003,
 	0x3109, 0xffffffff, 0x00601005,
 	0x311f, 0xffffffff, 0x10104040,
 	0x3122, 0xffffffff, 0x0100000a,
 	0x30c5, 0xffffffff, 0x00000800,
 	0x30c3, 0xffffffff, 0x800000f4,
-	0x3d2a, 0xffffffff, 0x00000000
+	0x3d2a, 0x00000008, 0x00000000
 };
 
 static const u32 pitcairn_golden_registers[] =
 {
+	0x17bc, 0x00000030, 0x00000011,
 	0x2684, 0x00010000, 0x00018208,
 	0x260c, 0xffffffff, 0x00000000,
 	0x260d, 0xf00fffff, 0x00000400,
@@ -109,7 +117,7 @@ static const u32 pitcairn_golden_registe
 	0x22c4, 0x0000ff0f, 0x00000000,
 	0xa293, 0x07ffffff, 0x4e000000,
 	0xa0d4, 0x3f3f3fff, 0x2a00126a,
-	0x000c, 0x000000ff, 0x0040,
+	0x000c, 0xffffffff, 0x0040,
 	0x000d, 0x00000040, 0x00004040,
 	0x2440, 0x07ffffff, 0x03000000,
 	0x2418, 0x0000007f, 0x00000020,
@@ -118,11 +126,16 @@ static const u32 pitcairn_golden_registe
 	0x2b04, 0xffffffff, 0x00000000,
 	0x2b03, 0xffffffff, 0x32761054,
 	0x2235, 0x0000001f, 0x00000010,
-	0x0570, 0x000c0fc0, 0x000c0400
+	0x0570, 0x000c0fc0, 0x000c0400,
+	0x052c, 0x0fffffff, 0xffffffff,
+	0x052d, 0x0fffffff, 0x0fffffff,
+	0x052e, 0x0fffffff, 0x0fffffff,
+	0x052f, 0x0fffffff, 0x0fffffff
 };
 
 static const u32 pitcairn_golden_rlc_registers[] =
 {
+	0x263e, 0xffffffff, 0x12011003,
 	0x3109, 0xffffffff, 0x00601004,
 	0x311f, 0xffffffff, 0x10102020,
 	0x3122, 0xffffffff, 0x01000020,
@@ -132,133 +145,134 @@ static const u32 pitcairn_golden_rlc_reg
 
 static const u32 verde_pg_init[] =
 {
-	0xd4f, 0xffffffff, 0x40000,
-	0xd4e, 0xffffffff, 0x200010ff,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x7007,
-	0xd4e, 0xffffffff, 0x300010ff,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x400000,
-	0xd4e, 0xffffffff, 0x100010ff,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x120200,
-	0xd4e, 0xffffffff, 0x500010ff,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x1e1e16,
-	0xd4e, 0xffffffff, 0x600010ff,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x171f1e,
-	0xd4e, 0xffffffff, 0x700010ff,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4f, 0xffffffff, 0x0,
-	0xd4e, 0xffffffff, 0x9ff,
-	0xd40, 0xffffffff, 0x0,
-	0xd41, 0xffffffff, 0x10000800,
-	0xd41, 0xffffffff, 0xf,
-	0xd41, 0xffffffff, 0xf,
-	0xd40, 0xffffffff, 0x4,
-	0xd41, 0xffffffff, 0x1000051e,
-	0xd41, 0xffffffff, 0xffff,
-	0xd41, 0xffffffff, 0xffff,
-	0xd40, 0xffffffff, 0x8,
-	0xd41, 0xffffffff, 0x80500,
-	0xd40, 0xffffffff, 0x12,
-	0xd41, 0xffffffff, 0x9050c,
-	0xd40, 0xffffffff, 0x1d,
-	0xd41, 0xffffffff, 0xb052c,
-	0xd40, 0xffffffff, 0x2a,
-	0xd41, 0xffffffff, 0x1053e,
-	0xd40, 0xffffffff, 0x2d,
-	0xd41, 0xffffffff, 0x10546,
-	0xd40, 0xffffffff, 0x30,
-	0xd41, 0xffffffff, 0xa054e,
-	0xd40, 0xffffffff, 0x3c,
-	0xd41, 0xffffffff, 0x1055f,
-	0xd40, 0xffffffff, 0x3f,
-	0xd41, 0xffffffff, 0x10567,
-	0xd40, 0xffffffff, 0x42,
-	0xd41, 0xffffffff, 0x1056f,
-	0xd40, 0xffffffff, 0x45,
-	0xd41, 0xffffffff, 0x10572,
-	0xd40, 0xffffffff, 0x48,
-	0xd41, 0xffffffff, 0x20575,
-	0xd40, 0xffffffff, 0x4c,
-	0xd41, 0xffffffff, 0x190801,
-	0xd40, 0xffffffff, 0x67,
-	0xd41, 0xffffffff, 0x1082a,
-	0xd40, 0xffffffff, 0x6a,
-	0xd41, 0xffffffff, 0x1b082d,
-	0xd40, 0xffffffff, 0x87,
-	0xd41, 0xffffffff, 0x310851,
-	0xd40, 0xffffffff, 0xba,
-	0xd41, 0xffffffff, 0x891,
-	0xd40, 0xffffffff, 0xbc,
-	0xd41, 0xffffffff, 0x893,
-	0xd40, 0xffffffff, 0xbe,
-	0xd41, 0xffffffff, 0x20895,
-	0xd40, 0xffffffff, 0xc2,
-	0xd41, 0xffffffff, 0x20899,
-	0xd40, 0xffffffff, 0xc6,
-	0xd41, 0xffffffff, 0x2089d,
-	0xd40, 0xffffffff, 0xca,
-	0xd41, 0xffffffff, 0x8a1,
-	0xd40, 0xffffffff, 0xcc,
-	0xd41, 0xffffffff, 0x8a3,
-	0xd40, 0xffffffff, 0xce,
-	0xd41, 0xffffffff, 0x308a5,
-	0xd40, 0xffffffff, 0xd3,
-	0xd41, 0xffffffff, 0x6d08cd,
-	0xd40, 0xffffffff, 0x142,
-	0xd41, 0xffffffff, 0x2000095a,
-	0xd41, 0xffffffff, 0x1,
-	0xd40, 0xffffffff, 0x144,
-	0xd41, 0xffffffff, 0x301f095b,
-	0xd40, 0xffffffff, 0x165,
-	0xd41, 0xffffffff, 0xc094d,
-	0xd40, 0xffffffff, 0x173,
-	0xd41, 0xffffffff, 0xf096d,
-	0xd40, 0xffffffff, 0x184,
-	0xd41, 0xffffffff, 0x15097f,
-	0xd40, 0xffffffff, 0x19b,
-	0xd41, 0xffffffff, 0xc0998,
-	0xd40, 0xffffffff, 0x1a9,
-	0xd41, 0xffffffff, 0x409a7,
-	0xd40, 0xffffffff, 0x1af,
-	0xd41, 0xffffffff, 0xcdc,
-	0xd40, 0xffffffff, 0x1b1,
-	0xd41, 0xffffffff, 0x800,
-	0xd42, 0xffffffff, 0x6c9b2000,
-	0xd44, 0xfc00, 0x2000,
-	0xd51, 0xffffffff, 0xfc0,
-	0xa35, 0x00000100, 0x100
+	0x0d4f, 0xffffffff, 0x40000,
+	0x0d4e, 0xffffffff, 0x200010ff,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x7007,
+	0x0d4e, 0xffffffff, 0x300010ff,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x400000,
+	0x0d4e, 0xffffffff, 0x100010ff,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x120200,
+	0x0d4e, 0xffffffff, 0x500010ff,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x1e1e16,
+	0x0d4e, 0xffffffff, 0x600010ff,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x171f1e,
+	0x0d4e, 0xffffffff, 0x700010ff,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4f, 0xffffffff, 0x0,
+	0x0d4e, 0xffffffff, 0x9ff,
+	0x0d40, 0xffffffff, 0x0,
+	0x0d41, 0xffffffff, 0x10000800,
+	0x0d41, 0xffffffff, 0xf,
+	0x0d41, 0xffffffff, 0xf,
+	0x0d40, 0xffffffff, 0x4,
+	0x0d41, 0xffffffff, 0x1000051e,
+	0x0d41, 0xffffffff, 0xffff,
+	0x0d41, 0xffffffff, 0xffff,
+	0x0d40, 0xffffffff, 0x8,
+	0x0d41, 0xffffffff, 0x80500,
+	0x0d40, 0xffffffff, 0x12,
+	0x0d41, 0xffffffff, 0x9050c,
+	0x0d40, 0xffffffff, 0x1d,
+	0x0d41, 0xffffffff, 0xb052c,
+	0x0d40, 0xffffffff, 0x2a,
+	0x0d41, 0xffffffff, 0x1053e,
+	0x0d40, 0xffffffff, 0x2d,
+	0x0d41, 0xffffffff, 0x10546,
+	0x0d40, 0xffffffff, 0x30,
+	0x0d41, 0xffffffff, 0xa054e,
+	0x0d40, 0xffffffff, 0x3c,
+	0x0d41, 0xffffffff, 0x1055f,
+	0x0d40, 0xffffffff, 0x3f,
+	0x0d41, 0xffffffff, 0x10567,
+	0x0d40, 0xffffffff, 0x42,
+	0x0d41, 0xffffffff, 0x1056f,
+	0x0d40, 0xffffffff, 0x45,
+	0x0d41, 0xffffffff, 0x10572,
+	0x0d40, 0xffffffff, 0x48,
+	0x0d41, 0xffffffff, 0x20575,
+	0x0d40, 0xffffffff, 0x4c,
+	0x0d41, 0xffffffff, 0x190801,
+	0x0d40, 0xffffffff, 0x67,
+	0x0d41, 0xffffffff, 0x1082a,
+	0x0d40, 0xffffffff, 0x6a,
+	0x0d41, 0xffffffff, 0x1b082d,
+	0x0d40, 0xffffffff, 0x87,
+	0x0d41, 0xffffffff, 0x310851,
+	0x0d40, 0xffffffff, 0xba,
+	0x0d41, 0xffffffff, 0x891,
+	0x0d40, 0xffffffff, 0xbc,
+	0x0d41, 0xffffffff, 0x893,
+	0x0d40, 0xffffffff, 0xbe,
+	0x0d41, 0xffffffff, 0x20895,
+	0x0d40, 0xffffffff, 0xc2,
+	0x0d41, 0xffffffff, 0x20899,
+	0x0d40, 0xffffffff, 0xc6,
+	0x0d41, 0xffffffff, 0x2089d,
+	0x0d40, 0xffffffff, 0xca,
+	0x0d41, 0xffffffff, 0x8a1,
+	0x0d40, 0xffffffff, 0xcc,
+	0x0d41, 0xffffffff, 0x8a3,
+	0x0d40, 0xffffffff, 0xce,
+	0x0d41, 0xffffffff, 0x308a5,
+	0x0d40, 0xffffffff, 0xd3,
+	0x0d41, 0xffffffff, 0x6d08cd,
+	0x0d40, 0xffffffff, 0x142,
+	0x0d41, 0xffffffff, 0x2000095a,
+	0x0d41, 0xffffffff, 0x1,
+	0x0d40, 0xffffffff, 0x144,
+	0x0d41, 0xffffffff, 0x301f095b,
+	0x0d40, 0xffffffff, 0x165,
+	0x0d41, 0xffffffff, 0xc094d,
+	0x0d40, 0xffffffff, 0x173,
+	0x0d41, 0xffffffff, 0xf096d,
+	0x0d40, 0xffffffff, 0x184,
+	0x0d41, 0xffffffff, 0x15097f,
+	0x0d40, 0xffffffff, 0x19b,
+	0x0d41, 0xffffffff, 0xc0998,
+	0x0d40, 0xffffffff, 0x1a9,
+	0x0d41, 0xffffffff, 0x409a7,
+	0x0d40, 0xffffffff, 0x1af,
+	0x0d41, 0xffffffff, 0xcdc,
+	0x0d40, 0xffffffff, 0x1b1,
+	0x0d41, 0xffffffff, 0x800,
+	0x0d42, 0xffffffff, 0x6c9b2000,
+	0x0d44, 0xfc00, 0x2000,
+	0x0d51, 0xffffffff, 0xfc0,
+	0x0a35, 0x00000100, 0x100
 };
 
 static const u32 verde_golden_rlc_registers[] =
 {
+	0x263e, 0xffffffff, 0x02010002,
 	0x3109, 0xffffffff, 0x033f1005,
 	0x311f, 0xffffffff, 0x10808020,
 	0x3122, 0xffffffff, 0x00800008,
@@ -268,65 +282,45 @@ static const u32 verde_golden_rlc_regist
 
 static const u32 verde_golden_registers[] =
 {
+	0x17bc, 0x00000030, 0x00000011,
 	0x2684, 0x00010000, 0x00018208,
 	0x260c, 0xffffffff, 0x00000000,
 	0x260d, 0xf00fffff, 0x00000400,
 	0x260e, 0x0002021c, 0x00020200,
 	0x031e, 0x00000080, 0x00000000,
 	0x340c, 0x000300c0, 0x00800040,
-	0x340c, 0x000300c0, 0x00800040,
-	0x360c, 0x000300c0, 0x00800040,
 	0x360c, 0x000300c0, 0x00800040,
 	0x16ec, 0x000000f0, 0x00000070,
 	0x16f0, 0x00200000, 0x50100000,
-
 	0x1c0c, 0x31000311, 0x00000011,
 	0x0ab9, 0x00073ffe, 0x000022a2,
-	0x0ab9, 0x00073ffe, 0x000022a2,
-	0x0ab9, 0x00073ffe, 0x000022a2,
 	0x0903, 0x000007ff, 0x00000000,
-	0x0903, 0x000007ff, 0x00000000,
-	0x0903, 0x000007ff, 0x00000000,
-	0x2285, 0xf000001f, 0x00000007,
-	0x2285, 0xf000001f, 0x00000007,
 	0x2285, 0xf000001f, 0x00000007,
-	0x2285, 0xffffffff, 0x00ffffff,
+	0x22c9, 0xffffffff, 0x00ffffff,
 	0x22c4, 0x0000ff0f, 0x00000000,
-
 	0xa293, 0x07ffffff, 0x4e000000,
 	0xa0d4, 0x3f3f3fff, 0x0000124a,
-	0xa0d4, 0x3f3f3fff, 0x0000124a,
-	0xa0d4, 0x3f3f3fff, 0x0000124a,
-	0x000c, 0x000000ff, 0x0040,
+	0x000c, 0xffffffff, 0x0040,
 	0x000d, 0x00000040, 0x00004040,
 	0x2440, 0x07ffffff, 0x03000000,
-	0x2440, 0x07ffffff, 0x03000000,
-	0x23a2, 0x01ff1f3f, 0x00000000,
-	0x23a3, 0x01ff1f3f, 0x00000000,
 	0x23a2, 0x01ff1f3f, 0x00000000,
 	0x23a1, 0x01ff1f3f, 0x00000000,
-	0x23a1, 0x01ff1f3f, 0x00000000,
-
-	0x23a1, 0x01ff1f3f, 0x00000000,
 	0x2418, 0x0000007f, 0x00000020,
 	0x2542, 0x00010000, 0x00010000,
-	0x2b01, 0x000003ff, 0x00000003,
 	0x2b05, 0x000003ff, 0x00000003,
-	0x2b05, 0x000003ff, 0x00000003,
-	0x2b04, 0xffffffff, 0x00000000,
 	0x2b04, 0xffffffff, 0x00000000,
-	0x2b04, 0xffffffff, 0x00000000,
-	0x2b03, 0xffffffff, 0x00001032,
 	0x2b03, 0xffffffff, 0x00001032,
-	0x2b03, 0xffffffff, 0x00001032,
-	0x2235, 0x0000001f, 0x00000010,
-	0x2235, 0x0000001f, 0x00000010,
 	0x2235, 0x0000001f, 0x00000010,
-	0x0570, 0x000c0fc0, 0x000c0400
+	0x0570, 0x000c0fc0, 0x000c0400,
+	0x052c, 0x0fffffff, 0xffffffff,
+	0x052d, 0x0fffffff, 0x0fffffff,
+	0x052e, 0x0fffffff, 0x0fffffff,
+	0x052f, 0x0fffffff, 0x0fffffff
 };
 
 static const u32 oland_golden_registers[] =
 {
+	0x17bc, 0x00000030, 0x00000011,
 	0x2684, 0x00010000, 0x00018208,
 	0x260c, 0xffffffff, 0x00000000,
 	0x260d, 0xf00fffff, 0x00000400,
@@ -335,7 +329,7 @@ static const u32 oland_golden_registers[
 	0x340c, 0x000300c0, 0x00800040,
 	0x360c, 0x000300c0, 0x00800040,
 	0x16ec, 0x000000f0, 0x00000070,
-	0x16f9, 0x00200000, 0x50100000,
+	0x16f0, 0x00200000, 0x50100000,
 	0x1c0c, 0x31000311, 0x00000011,
 	0x0ab9, 0x00073ffe, 0x000022a2,
 	0x0903, 0x000007ff, 0x00000000,
@@ -344,7 +338,7 @@ static const u32 oland_golden_registers[
 	0x22c4, 0x0000ff0f, 0x00000000,
 	0xa293, 0x07ffffff, 0x4e000000,
 	0xa0d4, 0x3f3f3fff, 0x00000082,
-	0x000c, 0x000000ff, 0x0040,
+	0x000c, 0xffffffff, 0x0040,
 	0x000d, 0x00000040, 0x00004040,
 	0x2440, 0x07ffffff, 0x03000000,
 	0x2418, 0x0000007f, 0x00000020,
@@ -353,11 +347,16 @@ static const u32 oland_golden_registers[
 	0x2b04, 0xffffffff, 0x00000000,
 	0x2b03, 0xffffffff, 0x00003210,
 	0x2235, 0x0000001f, 0x00000010,
-	0x0570, 0x000c0fc0, 0x000c0400
+	0x0570, 0x000c0fc0, 0x000c0400,
+	0x052c, 0x0fffffff, 0xffffffff,
+	0x052d, 0x0fffffff, 0x0fffffff,
+	0x052e, 0x0fffffff, 0x0fffffff,
+	0x052f, 0x0fffffff, 0x0fffffff
 };
 
 static const u32 oland_golden_rlc_registers[] =
 {
+	0x263e, 0xffffffff, 0x02010002,
 	0x3109, 0xffffffff, 0x00601005,
 	0x311f, 0xffffffff, 0x10104040,
 	0x3122, 0xffffffff, 0x0100000a,
@@ -367,22 +366,27 @@ static const u32 oland_golden_rlc_regist
 
 static const u32 hainan_golden_registers[] =
 {
+	0x17bc, 0x00000030, 0x00000011,
 	0x2684, 0x00010000, 0x00018208,
 	0x260c, 0xffffffff, 0x00000000,
 	0x260d, 0xf00fffff, 0x00000400,
 	0x260e, 0x0002021c, 0x00020200,
-	0x4595, 0xff000fff, 0x00000100,
+	0x031e, 0x00000080, 0x00000000,
+	0x3430, 0xff000fff, 0x00000100,
 	0x340c, 0x000300c0, 0x00800040,
 	0x3630, 0xff000fff, 0x00000100,
 	0x360c, 0x000300c0, 0x00800040,
+	0x16ec, 0x000000f0, 0x00000070,
+	0x16f0, 0x00200000, 0x50100000,
+	0x1c0c, 0x31000311, 0x00000011,
 	0x0ab9, 0x00073ffe, 0x000022a2,
 	0x0903, 0x000007ff, 0x00000000,
 	0x2285, 0xf000001f, 0x00000007,
 	0x22c9, 0xffffffff, 0x00ffffff,
 	0x22c4, 0x0000ff0f, 0x00000000,
-	0xa393, 0x07ffffff, 0x4e000000,
+	0xa293, 0x07ffffff, 0x4e000000,
 	0xa0d4, 0x3f3f3fff, 0x00000000,
-	0x000c, 0x000000ff, 0x0040,
+	0x000c, 0xffffffff, 0x0040,
 	0x000d, 0x00000040, 0x00004040,
 	0x2440, 0x03e00000, 0x03600000,
 	0x2418, 0x0000007f, 0x00000020,
@@ -391,12 +395,16 @@ static const u32 hainan_golden_registers
 	0x2b04, 0xffffffff, 0x00000000,
 	0x2b03, 0xffffffff, 0x00003210,
 	0x2235, 0x0000001f, 0x00000010,
-	0x0570, 0x000c0fc0, 0x000c0400
+	0x0570, 0x000c0fc0, 0x000c0400,
+	0x052c, 0x0fffffff, 0xffffffff,
+	0x052d, 0x0fffffff, 0x0fffffff,
+	0x052e, 0x0fffffff, 0x0fffffff,
+	0x052f, 0x0fffffff, 0x0fffffff
 };
 
 static const u32 hainan_golden_registers2[] =
 {
-	0x263e, 0xffffffff, 0x02010001
+	0x263e, 0xffffffff, 0x2011003
 };
 
 static const u32 tahiti_mgcg_cgcg_init[] =
@@ -512,18 +520,18 @@ static const u32 tahiti_mgcg_cgcg_init[]
 	0x21c2, 0xffffffff, 0x00900100,
 	0x311e, 0xffffffff, 0x00000080,
 	0x3101, 0xffffffff, 0x0020003f,
-	0xc, 0xffffffff, 0x0000001c,
-	0xd, 0x000f0000, 0x000f0000,
-	0x583, 0xffffffff, 0x00000100,
-	0x409, 0xffffffff, 0x00000100,
-	0x40b, 0x00000101, 0x00000000,
-	0x82a, 0xffffffff, 0x00000104,
-	0x993, 0x000c0000, 0x000c0000,
-	0x992, 0x000c0000, 0x000c0000,
+	0x000c, 0xffffffff, 0x0000001c,
+	0x000d, 0x000f0000, 0x000f0000,
+	0x0583, 0xffffffff, 0x00000100,
+	0x0409, 0xffffffff, 0x00000100,
+	0x040b, 0x00000101, 0x00000000,
+	0x082a, 0xffffffff, 0x00000104,
+	0x0993, 0x000c0000, 0x000c0000,
+	0x0992, 0x000c0000, 0x000c0000,
 	0x1579, 0xff000fff, 0x00000100,
 	0x157a, 0x00000001, 0x00000001,
-	0xbd4, 0x00000001, 0x00000001,
-	0xc33, 0xc0000fff, 0x00000104,
+	0x0bd4, 0x00000001, 0x00000001,
+	0x0c33, 0xc0000fff, 0x00000104,
 	0x3079, 0x00000001, 0x00000001,
 	0x3430, 0xfffffff0, 0x00000100,
 	0x3630, 0xfffffff0, 0x00000100
@@ -611,16 +619,16 @@ static const u32 pitcairn_mgcg_cgcg_init
 	0x21c2, 0xffffffff, 0x00900100,
 	0x311e, 0xffffffff, 0x00000080,
 	0x3101, 0xffffffff, 0x0020003f,
-	0xc, 0xffffffff, 0x0000001c,
-	0xd, 0x000f0000, 0x000f0000,
-	0x583, 0xffffffff, 0x00000100,
-	0x409, 0xffffffff, 0x00000100,
-	0x40b, 0x00000101, 0x00000000,
-	0x82a, 0xffffffff, 0x00000104,
+	0x000c, 0xffffffff, 0x0000001c,
+	0x000d, 0x000f0000, 0x000f0000,
+	0x0583, 0xffffffff, 0x00000100,
+	0x0409, 0xffffffff, 0x00000100,
+	0x040b, 0x00000101, 0x00000000,
+	0x082a, 0xffffffff, 0x00000104,
 	0x1579, 0xff000fff, 0x00000100,
 	0x157a, 0x00000001, 0x00000001,
-	0xbd4, 0x00000001, 0x00000001,
-	0xc33, 0xc0000fff, 0x00000104,
+	0x0bd4, 0x00000001, 0x00000001,
+	0x0c33, 0xc0000fff, 0x00000104,
 	0x3079, 0x00000001, 0x00000001,
 	0x3430, 0xfffffff0, 0x00000100,
 	0x3630, 0xfffffff0, 0x00000100
@@ -708,18 +716,18 @@ static const u32 verde_mgcg_cgcg_init[]
 	0x21c2, 0xffffffff, 0x00900100,
 	0x311e, 0xffffffff, 0x00000080,
 	0x3101, 0xffffffff, 0x0020003f,
-	0xc, 0xffffffff, 0x0000001c,
-	0xd, 0x000f0000, 0x000f0000,
-	0x583, 0xffffffff, 0x00000100,
-	0x409, 0xffffffff, 0x00000100,
-	0x40b, 0x00000101, 0x00000000,
-	0x82a, 0xffffffff, 0x00000104,
-	0x993, 0x000c0000, 0x000c0000,
-	0x992, 0x000c0000, 0x000c0000,
+	0x000c, 0xffffffff, 0x0000001c,
+	0x000d, 0x000f0000, 0x000f0000,
+	0x0583, 0xffffffff, 0x00000100,
+	0x0409, 0xffffffff, 0x00000100,
+	0x040b, 0x00000101, 0x00000000,
+	0x082a, 0xffffffff, 0x00000104,
+	0x0993, 0x000c0000, 0x000c0000,
+	0x0992, 0x000c0000, 0x000c0000,
 	0x1579, 0xff000fff, 0x00000100,
 	0x157a, 0x00000001, 0x00000001,
-	0xbd4, 0x00000001, 0x00000001,
-	0xc33, 0xc0000fff, 0x00000104,
+	0x0bd4, 0x00000001, 0x00000001,
+	0x0c33, 0xc0000fff, 0x00000104,
 	0x3079, 0x00000001, 0x00000001,
 	0x3430, 0xfffffff0, 0x00000100,
 	0x3630, 0xfffffff0, 0x00000100
@@ -787,18 +795,18 @@ static const u32 oland_mgcg_cgcg_init[]
 	0x21c2, 0xffffffff, 0x00900100,
 	0x311e, 0xffffffff, 0x00000080,
 	0x3101, 0xffffffff, 0x0020003f,
-	0xc, 0xffffffff, 0x0000001c,
-	0xd, 0x000f0000, 0x000f0000,
-	0x583, 0xffffffff, 0x00000100,
-	0x409, 0xffffffff, 0x00000100,
-	0x40b, 0x00000101, 0x00000000,
-	0x82a, 0xffffffff, 0x00000104,
-	0x993, 0x000c0000, 0x000c0000,
-	0x992, 0x000c0000, 0x000c0000,
+	0x000c, 0xffffffff, 0x0000001c,
+	0x000d, 0x000f0000, 0x000f0000,
+	0x0583, 0xffffffff, 0x00000100,
+	0x0409, 0xffffffff, 0x00000100,
+	0x040b, 0x00000101, 0x00000000,
+	0x082a, 0xffffffff, 0x00000104,
+	0x0993, 0x000c0000, 0x000c0000,
+	0x0992, 0x000c0000, 0x000c0000,
 	0x1579, 0xff000fff, 0x00000100,
 	0x157a, 0x00000001, 0x00000001,
-	0xbd4, 0x00000001, 0x00000001,
-	0xc33, 0xc0000fff, 0x00000104,
+	0x0bd4, 0x00000001, 0x00000001,
+	0x0c33, 0xc0000fff, 0x00000104,
 	0x3079, 0x00000001, 0x00000001,
 	0x3430, 0xfffffff0, 0x00000100,
 	0x3630, 0xfffffff0, 0x00000100
@@ -866,15 +874,15 @@ static const u32 hainan_mgcg_cgcg_init[]
 	0x21c2, 0xffffffff, 0x00900100,
 	0x311e, 0xffffffff, 0x00000080,
 	0x3101, 0xffffffff, 0x0020003f,
-	0xc, 0xffffffff, 0x0000001c,
-	0xd, 0x000f0000, 0x000f0000,
-	0x583, 0xffffffff, 0x00000100,
-	0x409, 0xffffffff, 0x00000100,
-	0x82a, 0xffffffff, 0x00000104,
-	0x993, 0x000c0000, 0x000c0000,
-	0x992, 0x000c0000, 0x000c0000,
-	0xbd4, 0x00000001, 0x00000001,
-	0xc33, 0xc0000fff, 0x00000104,
+	0x000c, 0xffffffff, 0x0000001c,
+	0x000d, 0x000f0000, 0x000f0000,
+	0x0583, 0xffffffff, 0x00000100,
+	0x0409, 0xffffffff, 0x00000100,
+	0x082a, 0xffffffff, 0x00000104,
+	0x0993, 0x000c0000, 0x000c0000,
+	0x0992, 0x000c0000, 0x000c0000,
+	0x0bd4, 0x00000001, 0x00000001,
+	0x0c33, 0xc0000fff, 0x00000104,
 	0x3079, 0x00000001, 0x00000001,
 	0x3430, 0xfffffff0, 0x00000100,
 	0x3630, 0xfffffff0, 0x00000100
@@ -905,7 +913,7 @@ static void si_pcie_wreg(struct amdgpu_d
 	spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 }
 
-u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg)
+static u32 si_pciep_rreg(struct amdgpu_device *adev, u32 reg)
 {
 	unsigned long flags;
 	u32 r;
@@ -918,7 +926,7 @@ u32 si_pciep_rreg(struct amdgpu_device *
 	return r;
 }
 
-void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
+static void si_pciep_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
 {
 	unsigned long flags;
 
@@ -1178,6 +1186,8 @@ static int si_common_early_init(void *ha
 			AMD_CG_SUPPORT_HDP_LS |
 			AMD_CG_SUPPORT_HDP_MGCG;
 			adev->pg_flags = 0;
+		adev->external_rev_id = (adev->rev_id == 0) ? 1 :
+					(adev->rev_id == 1) ? 5 : 6;
 		break;
 	case CHIP_PITCAIRN:
 		adev->cg_flags =
@@ -1197,6 +1207,7 @@ static int si_common_early_init(void *ha
 			AMD_CG_SUPPORT_HDP_LS |
 			AMD_CG_SUPPORT_HDP_MGCG;
 		adev->pg_flags = 0;
+		adev->external_rev_id = adev->rev_id + 20;
 		break;
 
 	case CHIP_VERDE:
@@ -1218,7 +1229,7 @@ static int si_common_early_init(void *ha
 			AMD_CG_SUPPORT_HDP_MGCG;
 		adev->pg_flags = 0;
 		//???
-		adev->external_rev_id = adev->rev_id + 0x14;
+		adev->external_rev_id = adev->rev_id + 40;
 		break;
 	case CHIP_OLAND:
 		adev->cg_flags =
@@ -1237,6 +1248,7 @@ static int si_common_early_init(void *ha
 			AMD_CG_SUPPORT_HDP_LS |
 			AMD_CG_SUPPORT_HDP_MGCG;
 		adev->pg_flags = 0;
+		adev->external_rev_id = 60;
 		break;
 	case CHIP_HAINAN:
 		adev->cg_flags =
@@ -1254,6 +1266,7 @@ static int si_common_early_init(void *ha
 			AMD_CG_SUPPORT_HDP_LS |
 			AMD_CG_SUPPORT_HDP_MGCG;
 		adev->pg_flags = 0;
+		adev->external_rev_id = 70;
 		break;
 
 	default:
@@ -1811,7 +1824,7 @@ static int si_common_set_powergating_sta
 	return 0;
 }
 
-const struct amd_ip_funcs si_common_ip_funcs = {
+static const struct amd_ip_funcs si_common_ip_funcs = {
 	.name = "si_common",
 	.early_init = si_common_early_init,
 	.late_init = NULL,
@@ -1828,119 +1841,13 @@ const struct amd_ip_funcs si_common_ip_f
 	.set_powergating_state = si_common_set_powergating_state,
 };
 
-static const struct amdgpu_ip_block_version verde_ip_blocks[] =
-{
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &si_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &si_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &dce_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &si_dma_ip_funcs,
-	},
-/*	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 3,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &si_null_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &si_null_ip_funcs,
-	},
-	*/
-};
-
-
-static const struct amdgpu_ip_block_version hainan_ip_blocks[] =
+static const struct amdgpu_ip_block_version si_common_ip_block =
 {
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &si_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &si_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &si_dma_ip_funcs,
-	},
+	.type = AMD_IP_BLOCK_TYPE_COMMON,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &si_common_ip_funcs,
 };
 
 int si_set_ip_blocks(struct amdgpu_device *adev)
@@ -1949,13 +1856,42 @@ int si_set_ip_blocks(struct amdgpu_devic
 	case CHIP_VERDE:
 	case CHIP_TAHITI:
 	case CHIP_PITCAIRN:
+		amdgpu_ip_block_add(adev, &si_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &si_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &si_dma_ip_block);
+		/* amdgpu_ip_block_add(adev, &uvd_v3_1_ip_block); */
+		/* amdgpu_ip_block_add(adev, &vce_v1_0_ip_block); */
+		break;
 	case CHIP_OLAND:
-		adev->ip_blocks = verde_ip_blocks;
-		adev->num_ip_blocks = ARRAY_SIZE(verde_ip_blocks);
+		amdgpu_ip_block_add(adev, &si_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &si_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v6_4_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &si_dma_ip_block);
+		/* amdgpu_ip_block_add(adev, &uvd_v3_1_ip_block); */
+		/* amdgpu_ip_block_add(adev, &vce_v1_0_ip_block); */
 		break;
 	case CHIP_HAINAN:
-		adev->ip_blocks = hainan_ip_blocks;
-		adev->num_ip_blocks = ARRAY_SIZE(hainan_ip_blocks);
+		amdgpu_ip_block_add(adev, &si_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &si_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &si_dma_ip_block);
 		break;
 	default:
 		BUG();
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -274,7 +274,7 @@ static int si_dma_ring_test_ib(struct am
 {
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_ib ib;
-	struct fence *f = NULL;
+	struct dma_fence *f = NULL;
 	unsigned index;
 	u32 tmp = 0;
 	u64 gpu_addr;
@@ -305,7 +305,7 @@ static int si_dma_ring_test_ib(struct am
 	if (r)
 		goto err1;
 
-	r = fence_wait_timeout(f, false, timeout);
+	r = dma_fence_wait_timeout(f, false, timeout);
 	if (r == 0) {
 		DRM_ERROR("amdgpu: IB test timed out\n");
 		r = -ETIMEDOUT;
@@ -325,7 +325,7 @@ static int si_dma_ring_test_ib(struct am
 
 err1:
 	amdgpu_ib_free(adev, &ib, NULL);
-	fence_put(f);
+	dma_fence_put(f);
 err0:
 	amdgpu_wb_free(adev, index);
 	return r;
@@ -495,22 +495,6 @@ static void si_dma_ring_emit_vm_flush(st
 	amdgpu_ring_write(ring, (0 << 28) | 0x20); /* func(always) | poll interval */
 }
 
-static unsigned si_dma_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		7 + 3; /* si_dma_ring_emit_ib */
-}
-
-static unsigned si_dma_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		3 + /* si_dma_ring_emit_hdp_flush */
-		3 + /* si_dma_ring_emit_hdp_invalidate */
-		6 + /* si_dma_ring_emit_pipeline_sync */
-		12 + /* si_dma_ring_emit_vm_flush */
-		9 + 9 + 9; /* si_dma_ring_emit_fence x3 for user fence, vm fence */
-}
-
 static int si_dma_early_init(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -547,11 +531,10 @@ static int si_dma_sw_init(void *handle)
 		ring->use_doorbell = false;
 		sprintf(ring->name, "sdma%d", i);
 		r = amdgpu_ring_init(adev, ring, 1024,
-				     DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0), 0xf,
 				     &adev->sdma.trap_irq,
 				     (i == 0) ?
-				     AMDGPU_SDMA_IRQ_TRAP0 : AMDGPU_SDMA_IRQ_TRAP1,
-				     AMDGPU_RING_TYPE_SDMA);
+				     AMDGPU_SDMA_IRQ_TRAP0 :
+				     AMDGPU_SDMA_IRQ_TRAP1);
 		if (r)
 			return r;
 	}
@@ -762,7 +745,7 @@ static int si_dma_set_powergating_state(
 	return 0;
 }
 
-const struct amd_ip_funcs si_dma_ip_funcs = {
+static const struct amd_ip_funcs si_dma_ip_funcs = {
 	.name = "si_dma",
 	.early_init = si_dma_early_init,
 	.late_init = NULL,
@@ -780,10 +763,19 @@ const struct amd_ip_funcs si_dma_ip_func
 };
 
 static const struct amdgpu_ring_funcs si_dma_ring_funcs = {
+	.type = AMDGPU_RING_TYPE_SDMA,
+	.align_mask = 0xf,
+	.nop = DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0, 0),
 	.get_rptr = si_dma_ring_get_rptr,
 	.get_wptr = si_dma_ring_get_wptr,
 	.set_wptr = si_dma_ring_set_wptr,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		3 + /* si_dma_ring_emit_hdp_flush */
+		3 + /* si_dma_ring_emit_hdp_invalidate */
+		6 + /* si_dma_ring_emit_pipeline_sync */
+		12 + /* si_dma_ring_emit_vm_flush */
+		9 + 9 + 9, /* si_dma_ring_emit_fence x3 for user fence, vm fence */
+	.emit_ib_size = 7 + 3, /* si_dma_ring_emit_ib */
 	.emit_ib = si_dma_ring_emit_ib,
 	.emit_fence = si_dma_ring_emit_fence,
 	.emit_pipeline_sync = si_dma_ring_emit_pipeline_sync,
@@ -794,8 +786,6 @@ static const struct amdgpu_ring_funcs si
 	.test_ib = si_dma_ring_test_ib,
 	.insert_nop = amdgpu_ring_insert_nop,
 	.pad_ib = si_dma_ring_pad_ib,
-	.get_emit_ib_size = si_dma_ring_get_emit_ib_size,
-	.get_dma_frame_size = si_dma_ring_get_dma_frame_size,
 };
 
 static void si_dma_set_ring_funcs(struct amdgpu_device *adev)
@@ -913,3 +903,12 @@ static void si_dma_set_vm_pte_funcs(stru
 		adev->vm_manager.vm_pte_num_rings = adev->sdma.num_instances;
 	}
 }
+
+const struct amdgpu_ip_block_version si_dma_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SDMA,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &si_dma_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_dma.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __SI_DMA_H__
 #define __SI_DMA_H__
 
-extern const struct amd_ip_funcs si_dma_ip_funcs;
+extern const struct amdgpu_ip_block_version si_dma_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c	2016-12-11 17:41:49.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_dpm.c	2017-02-12 17:24:54.000000000 -0500
@@ -3162,6 +3162,7 @@ static void ni_update_current_ps(struct
 	eg_pi->current_rps = *rps;
 	ni_pi->current_ps = *new_ps;
 	eg_pi->current_rps.ps_priv = &ni_pi->current_ps;
+	adev->pm.dpm.current_ps = &eg_pi->current_rps;
 }
 
 static void ni_update_requested_ps(struct amdgpu_device *adev,
@@ -3174,6 +3175,7 @@ static void ni_update_requested_ps(struc
 	eg_pi->requested_rps = *rps;
 	ni_pi->requested_ps = *new_ps;
 	eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps;
+	adev->pm.dpm.requested_ps = &eg_pi->requested_rps;
 }
 
 static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev,
@@ -3477,29 +3479,6 @@ static void si_apply_state_adjust_rules(
 		    (adev->pdev->device == 0x6817) ||
 		    (adev->pdev->device == 0x6806))
 			max_mclk = 120000;
-	} else if (adev->asic_type == CHIP_VERDE) {
-		if ((adev->pdev->revision == 0x81) ||
-		    (adev->pdev->revision == 0x83) ||
-		    (adev->pdev->revision == 0x87) ||
-		    (adev->pdev->device == 0x6820) ||
-		    (adev->pdev->device == 0x6821) ||
-		    (adev->pdev->device == 0x6822) ||
-		    (adev->pdev->device == 0x6823) ||
-		    (adev->pdev->device == 0x682A) ||
-		    (adev->pdev->device == 0x682B)) {
-			max_sclk = 75000;
-			max_mclk = 80000;
-		}
-	} else if (adev->asic_type == CHIP_OLAND) {
-		if ((adev->pdev->revision == 0xC7) ||
-		    (adev->pdev->revision == 0x80) ||
-		    (adev->pdev->revision == 0x81) ||
-		    (adev->pdev->revision == 0x83) ||
-		    (adev->pdev->device == 0x6604) ||
-		    (adev->pdev->device == 0x6605)) {
-			max_sclk = 75000;
-			max_mclk = 80000;
-		}
 	} else if (adev->asic_type == CHIP_HAINAN) {
 		if ((adev->pdev->revision == 0x81) ||
 		    (adev->pdev->revision == 0x83) ||
@@ -3508,7 +3487,6 @@ static void si_apply_state_adjust_rules(
 		    (adev->pdev->device == 0x6665) ||
 		    (adev->pdev->device == 0x6667)) {
 			max_sclk = 75000;
-			max_mclk = 80000;
 		}
 	}
 	/* Apply dpm quirks */
@@ -7338,7 +7316,7 @@ static int si_parse_power_table(struct a
 	adev->pm.dpm.num_ps = state_array->ucNumEntries;
 
 	/* fill in the vce power states */
-	for (i = 0; i < AMDGPU_MAX_VCE_LEVELS; i++) {
+	for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
 		u32 sclk, mclk;
 		clock_array_index = adev->pm.dpm.vce_states[i].clk_idx;
 		clock_info = (union pplib_clock_info *)
@@ -7675,49 +7653,51 @@ static int si_dpm_init_microcode(struct
 		chip_name = "tahiti";
 		break;
 	case CHIP_PITCAIRN:
-		if ((adev->pdev->revision == 0x81) ||
-		    (adev->pdev->device == 0x6810) ||
-		    (adev->pdev->device == 0x6811) ||
-		    (adev->pdev->device == 0x6816) ||
-		    (adev->pdev->device == 0x6817) ||
-		    (adev->pdev->device == 0x6806))
+		if ((adev->pdev->revision == 0x81) &&
+		    ((adev->pdev->device == 0x6810) ||
+		    (adev->pdev->device == 0x6811)))
 			chip_name = "pitcairn_k";
 		else
 			chip_name = "pitcairn";
 		break;
 	case CHIP_VERDE:
-		if ((adev->pdev->revision == 0x81) ||
-		    (adev->pdev->revision == 0x83) ||
-		    (adev->pdev->revision == 0x87) ||
-		    (adev->pdev->device == 0x6820) ||
-		    (adev->pdev->device == 0x6821) ||
-		    (adev->pdev->device == 0x6822) ||
-		    (adev->pdev->device == 0x6823) ||
-		    (adev->pdev->device == 0x682A) ||
-		    (adev->pdev->device == 0x682B))
+		if (((adev->pdev->device == 0x6820) &&
+			((adev->pdev->revision == 0x81) ||
+			(adev->pdev->revision == 0x83))) ||
+		    ((adev->pdev->device == 0x6821) &&
+			((adev->pdev->revision == 0x83) ||
+			(adev->pdev->revision == 0x87))) ||
+		    ((adev->pdev->revision == 0x87) &&
+			((adev->pdev->device == 0x6823) ||
+			(adev->pdev->device == 0x682b))))
 			chip_name = "verde_k";
 		else
 			chip_name = "verde";
 		break;
 	case CHIP_OLAND:
-		if ((adev->pdev->revision == 0xC7) ||
-		    (adev->pdev->revision == 0x80) ||
-		    (adev->pdev->revision == 0x81) ||
-		    (adev->pdev->revision == 0x83) ||
-		    (adev->pdev->device == 0x6604) ||
-		    (adev->pdev->device == 0x6605))
+		if (((adev->pdev->revision == 0x81) &&
+			((adev->pdev->device == 0x6600) ||
+			(adev->pdev->device == 0x6604) ||
+			(adev->pdev->device == 0x6605) ||
+			(adev->pdev->device == 0x6610))) ||
+		    ((adev->pdev->revision == 0x83) &&
+			(adev->pdev->device == 0x6610)))
 			chip_name = "oland_k";
 		else
 			chip_name = "oland";
 		break;
 	case CHIP_HAINAN:
-		if ((adev->pdev->revision == 0x81) ||
-		    (adev->pdev->revision == 0x83) ||
-		    (adev->pdev->revision == 0xC3) ||
-		    (adev->pdev->device == 0x6664) ||
-		    (adev->pdev->device == 0x6665) ||
-		    (adev->pdev->device == 0x6667))
+		if (((adev->pdev->revision == 0x81) &&
+			(adev->pdev->device == 0x6660)) ||
+		    ((adev->pdev->revision == 0x83) &&
+			((adev->pdev->device == 0x6660) ||
+			(adev->pdev->device == 0x6663) ||
+			(adev->pdev->device == 0x6665) ||
+			 (adev->pdev->device == 0x6667))))
 			chip_name = "hainan_k";
+		else if ((adev->pdev->revision == 0xc3) &&
+			 (adev->pdev->device == 0x6665))
+			chip_name = "banks_k_2";
 		else
 			chip_name = "hainan";
 		break;
@@ -7977,6 +7957,57 @@ static int si_dpm_early_init(void *handl
 	return 0;
 }
 
+static inline bool si_are_power_levels_equal(const struct rv7xx_pl  *si_cpl1,
+						const struct rv7xx_pl *si_cpl2)
+{
+	return ((si_cpl1->mclk == si_cpl2->mclk) &&
+		  (si_cpl1->sclk == si_cpl2->sclk) &&
+		  (si_cpl1->pcie_gen == si_cpl2->pcie_gen) &&
+		  (si_cpl1->vddc == si_cpl2->vddc) &&
+		  (si_cpl1->vddci == si_cpl2->vddci));
+}
+
+static int si_check_state_equal(struct amdgpu_device *adev,
+				struct amdgpu_ps *cps,
+				struct amdgpu_ps *rps,
+				bool *equal)
+{
+	struct si_ps *si_cps;
+	struct si_ps *si_rps;
+	int i;
+
+	if (adev == NULL || cps == NULL || rps == NULL || equal == NULL)
+		return -EINVAL;
+
+	si_cps = si_get_ps(cps);
+	si_rps = si_get_ps(rps);
+
+	if (si_cps == NULL) {
+		printk("si_cps is NULL\n");
+		*equal = false;
+		return 0;
+	}
+
+	if (si_cps->performance_level_count != si_rps->performance_level_count) {
+		*equal = false;
+		return 0;
+	}
+
+	for (i = 0; i < si_cps->performance_level_count; i++) {
+		if (!si_are_power_levels_equal(&(si_cps->performance_levels[i]),
+					&(si_rps->performance_levels[i]))) {
+			*equal = false;
+			return 0;
+		}
+	}
+
+	/* If all performance levels are the same try to use the UVD clocks to break the tie.*/
+	*equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk));
+	*equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk));
+
+	return 0;
+}
+
 
 const struct amd_ip_funcs si_dpm_ip_funcs = {
 	.name = "si_dpm",
@@ -8011,6 +8042,8 @@ static const struct amdgpu_dpm_funcs si_
 	.get_fan_control_mode = &si_dpm_get_fan_control_mode,
 	.set_fan_speed_percent = &si_dpm_set_fan_speed_percent,
 	.get_fan_speed_percent = &si_dpm_get_fan_speed_percent,
+	.check_state_equal = &si_check_state_equal,
+	.get_vce_clock_state = amdgpu_get_vce_clock_state,
 };
 
 static void si_dpm_set_dpm_funcs(struct amdgpu_device *adev)
@@ -8030,3 +8063,11 @@ static void si_dpm_set_irq_funcs(struct
 	adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs;
 }
 
+const struct amdgpu_ip_block_version si_dpm_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_SMC,
+	.major = 6,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &si_dpm_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_enums.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_enums.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_enums.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_enums.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef SI_ENUMS_H
+#define SI_ENUMS_H
+
+#define VBLANK_INT_MASK                (1 << 0)
+#define DC_HPDx_INT_EN                 (1 << 16)
+#define VBLANK_ACK                     (1 << 4)
+#define VLINE_ACK                      (1 << 4)
+
+#define CURSOR_WIDTH 64
+#define CURSOR_HEIGHT 64
+
+#define VGA_VSTATUS_CNTL               0xFFFCFFFF
+#define PRIORITY_MARK_MASK             0x7fff
+#define PRIORITY_OFF                   (1 << 16)
+#define PRIORITY_ALWAYS_ON             (1 << 20)
+#define INTERLEAVE_EN                  (1 << 0)
+
+#define LATENCY_WATERMARK_MASK(x)      ((x) << 16)
+#define DC_LB_MEMORY_CONFIG(x)         ((x) << 20)
+#define ICON_DEGAMMA_MODE(x)           (((x) & 0x3) << 8)
+
+#define GRPH_ENDIAN_SWAP(x)            (((x) & 0x3) << 0)
+#define GRPH_ENDIAN_NONE               0
+#define GRPH_ENDIAN_8IN16              1
+#define GRPH_ENDIAN_8IN32              2
+#define GRPH_ENDIAN_8IN64              3
+
+#define GRPH_DEPTH(x)                  (((x) & 0x3) << 0)
+#define GRPH_DEPTH_8BPP                0
+#define GRPH_DEPTH_16BPP               1
+#define GRPH_DEPTH_32BPP               2
+
+#define GRPH_FORMAT(x)                 (((x) & 0x7) << 8)
+#define GRPH_FORMAT_INDEXED            0
+#define GRPH_FORMAT_ARGB1555           0
+#define GRPH_FORMAT_ARGB565            1
+#define GRPH_FORMAT_ARGB4444           2
+#define GRPH_FORMAT_AI88               3
+#define GRPH_FORMAT_MONO16             4
+#define GRPH_FORMAT_BGRA5551           5
+#define GRPH_FORMAT_ARGB8888           0
+#define GRPH_FORMAT_ARGB2101010        1
+#define GRPH_FORMAT_32BPP_DIG          2
+#define GRPH_FORMAT_8B_ARGB2101010     3
+#define GRPH_FORMAT_BGRA1010102        4
+#define GRPH_FORMAT_8B_BGRA1010102     5
+#define GRPH_FORMAT_RGB111110          6
+#define GRPH_FORMAT_BGR101111          7
+
+#define GRPH_NUM_BANKS(x)              (((x) & 0x3) << 2)
+#define GRPH_ARRAY_MODE(x)             (((x) & 0x7) << 20)
+#define GRPH_ARRAY_LINEAR_GENERAL      0
+#define GRPH_ARRAY_LINEAR_ALIGNED      1
+#define GRPH_ARRAY_1D_TILED_THIN1      2
+#define GRPH_ARRAY_2D_TILED_THIN1      4
+#define GRPH_TILE_SPLIT(x)             (((x) & 0x7) << 13)
+#define GRPH_BANK_WIDTH(x)             (((x) & 0x3) << 6)
+#define GRPH_BANK_HEIGHT(x)            (((x) & 0x3) << 11)
+#define GRPH_MACRO_TILE_ASPECT(x)      (((x) & 0x3) << 18)
+#define GRPH_ARRAY_MODE(x)             (((x) & 0x7) << 20)
+#define GRPH_PIPE_CONFIG(x)                   (((x) & 0x1f) << 24)
+
+#define CURSOR_EN                      (1 << 0)
+#define CURSOR_MODE(x)                 (((x) & 0x3) << 8)
+#define CURSOR_MONO                    0
+#define CURSOR_24_1                    1
+#define CURSOR_24_8_PRE_MULT           2
+#define CURSOR_24_8_UNPRE_MULT         3
+#define CURSOR_2X_MAGNIFY              (1 << 16)
+#define CURSOR_FORCE_MC_ON             (1 << 20)
+#define CURSOR_URGENT_CONTROL(x)       (((x) & 0x7) << 24)
+#define CURSOR_URGENT_ALWAYS           0
+#define CURSOR_URGENT_1_8              1
+#define CURSOR_URGENT_1_4              2
+#define CURSOR_URGENT_3_8              3
+#define CURSOR_URGENT_1_2              4
+#define CURSOR_UPDATE_PENDING          (1 << 0)
+#define CURSOR_UPDATE_TAKEN            (1 << 1)
+#define CURSOR_UPDATE_LOCK             (1 << 16)
+#define CURSOR_DISABLE_MULTIPLE_UPDATE (1 << 24)
+
+#define AMDGPU_NUM_OF_VMIDS                     8
+#define SI_CRTC0_REGISTER_OFFSET                0
+#define SI_CRTC1_REGISTER_OFFSET                0x300
+#define SI_CRTC2_REGISTER_OFFSET                0x2600
+#define SI_CRTC3_REGISTER_OFFSET                0x2900
+#define SI_CRTC4_REGISTER_OFFSET                0x2c00
+#define SI_CRTC5_REGISTER_OFFSET                0x2f00
+
+#define DMA0_REGISTER_OFFSET 0x000
+#define DMA1_REGISTER_OFFSET 0x200
+#define ES_AND_GS_AUTO       3
+#define RADEON_PACKET_TYPE3  3
+#define CE_PARTITION_BASE    3
+#define BUF_SWAP_32BIT       (2 << 16)
+
+#define GFX_POWER_STATUS                           (1 << 1)
+#define GFX_CLOCK_STATUS                           (1 << 2)
+#define GFX_LS_STATUS                              (1 << 3)
+#define RLC_BUSY_STATUS                            (1 << 0)
+
+#define RLC_PUD(x)                               ((x) << 0)
+#define RLC_PUD_MASK                             (0xff << 0)
+#define RLC_PDD(x)                               ((x) << 8)
+#define RLC_PDD_MASK                             (0xff << 8)
+#define RLC_TTPD(x)                              ((x) << 16)
+#define RLC_TTPD_MASK                            (0xff << 16)
+#define RLC_MSD(x)                               ((x) << 24)
+#define RLC_MSD_MASK                             (0xff << 24)
+#define WRITE_DATA_ENGINE_SEL(x) ((x) << 30)
+#define WRITE_DATA_DST_SEL(x) ((x) << 8)
+#define EVENT_TYPE(x) ((x) << 0)
+#define EVENT_INDEX(x) ((x) << 8)
+#define WAIT_REG_MEM_MEM_SPACE(x)               ((x) << 4)
+#define WAIT_REG_MEM_FUNCTION(x)                ((x) << 0)
+#define WAIT_REG_MEM_ENGINE(x)                  ((x) << 8)
+
+#define GFX6_NUM_GFX_RINGS     1
+#define GFX6_NUM_COMPUTE_RINGS 2
+#define RLC_SAVE_AND_RESTORE_STARTING_OFFSET 0x90
+#define RLC_CLEAR_STATE_DESCRIPTOR_OFFSET    0x3D
+
+#define TAHITI_GB_ADDR_CONFIG_GOLDEN        0x12011003
+#define VERDE_GB_ADDR_CONFIG_GOLDEN         0x12010002
+#define HAINAN_GB_ADDR_CONFIG_GOLDEN        0x02010001
+
+#define PACKET3(op, n)  ((RADEON_PACKET_TYPE3 << 30) |                  \
+                         (((op) & 0xFF) << 8) |                         \
+                         ((n) & 0x3FFF) << 16)
+#define PACKET3_COMPUTE(op, n) (PACKET3(op, n) | 1 << 1)
+#define	PACKET3_NOP					0x10
+#define	PACKET3_SET_BASE				0x11
+#define		PACKET3_BASE_INDEX(x)                  ((x) << 0)
+#define	PACKET3_CLEAR_STATE				0x12
+#define	PACKET3_INDEX_BUFFER_SIZE			0x13
+#define	PACKET3_DISPATCH_DIRECT				0x15
+#define	PACKET3_DISPATCH_INDIRECT			0x16
+#define	PACKET3_ALLOC_GDS				0x1B
+#define	PACKET3_WRITE_GDS_RAM				0x1C
+#define	PACKET3_ATOMIC_GDS				0x1D
+#define	PACKET3_ATOMIC					0x1E
+#define	PACKET3_OCCLUSION_QUERY				0x1F
+#define	PACKET3_SET_PREDICATION				0x20
+#define	PACKET3_REG_RMW					0x21
+#define	PACKET3_COND_EXEC				0x22
+#define	PACKET3_PRED_EXEC				0x23
+#define	PACKET3_DRAW_INDIRECT				0x24
+#define	PACKET3_DRAW_INDEX_INDIRECT			0x25
+#define	PACKET3_INDEX_BASE				0x26
+#define	PACKET3_DRAW_INDEX_2				0x27
+#define	PACKET3_CONTEXT_CONTROL				0x28
+#define	PACKET3_INDEX_TYPE				0x2A
+#define	PACKET3_DRAW_INDIRECT_MULTI			0x2C
+#define	PACKET3_DRAW_INDEX_AUTO				0x2D
+#define	PACKET3_DRAW_INDEX_IMMD				0x2E
+#define	PACKET3_NUM_INSTANCES				0x2F
+#define	PACKET3_DRAW_INDEX_MULTI_AUTO			0x30
+#define	PACKET3_INDIRECT_BUFFER_CONST			0x31
+#define	PACKET3_INDIRECT_BUFFER				0x3F
+#define	PACKET3_STRMOUT_BUFFER_UPDATE			0x34
+#define	PACKET3_DRAW_INDEX_OFFSET_2			0x35
+#define	PACKET3_DRAW_INDEX_MULTI_ELEMENT		0x36
+#define	PACKET3_WRITE_DATA				0x37
+#define	PACKET3_DRAW_INDEX_INDIRECT_MULTI		0x38
+#define	PACKET3_MEM_SEMAPHORE				0x39
+#define	PACKET3_MPEG_INDEX				0x3A
+#define	PACKET3_COPY_DW					0x3B
+#define	PACKET3_WAIT_REG_MEM				0x3C
+#define	PACKET3_MEM_WRITE				0x3D
+#define	PACKET3_COPY_DATA				0x40
+#define	PACKET3_CP_DMA					0x41
+#              define PACKET3_CP_DMA_DST_SEL(x)    ((x) << 20)
+#              define PACKET3_CP_DMA_ENGINE(x)     ((x) << 27)
+#              define PACKET3_CP_DMA_SRC_SEL(x)    ((x) << 29)
+#              define PACKET3_CP_DMA_CP_SYNC       (1 << 31)
+#              define PACKET3_CP_DMA_DIS_WC        (1 << 21)
+#              define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22)
+#              define PACKET3_CP_DMA_CMD_DST_SWAP(x) ((x) << 24)
+#              define PACKET3_CP_DMA_CMD_SAS       (1 << 26)
+#              define PACKET3_CP_DMA_CMD_DAS       (1 << 27)
+#              define PACKET3_CP_DMA_CMD_SAIC      (1 << 28)
+#              define PACKET3_CP_DMA_CMD_DAIC      (1 << 29)
+#              define PACKET3_CP_DMA_CMD_RAW_WAIT  (1 << 30)
+#define	PACKET3_PFP_SYNC_ME				0x42
+#define	PACKET3_SURFACE_SYNC				0x43
+#              define PACKET3_DEST_BASE_0_ENA      (1 << 0)
+#              define PACKET3_DEST_BASE_1_ENA      (1 << 1)
+#              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
+#              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
+#              define PACKET3_CB2_DEST_BASE_ENA    (1 << 8)
+#              define PACKET3_CB3_DEST_BASE_ENA    (1 << 9)
+#              define PACKET3_CB4_DEST_BASE_ENA    (1 << 10)
+#              define PACKET3_CB5_DEST_BASE_ENA    (1 << 11)
+#              define PACKET3_CB6_DEST_BASE_ENA    (1 << 12)
+#              define PACKET3_CB7_DEST_BASE_ENA    (1 << 13)
+#              define PACKET3_DB_DEST_BASE_ENA     (1 << 14)
+#              define PACKET3_DEST_BASE_2_ENA      (1 << 19)
+#              define PACKET3_DEST_BASE_3_ENA      (1 << 21)
+#              define PACKET3_TCL1_ACTION_ENA      (1 << 22)
+#              define PACKET3_TC_ACTION_ENA        (1 << 23)
+#              define PACKET3_CB_ACTION_ENA        (1 << 25)
+#              define PACKET3_DB_ACTION_ENA        (1 << 26)
+#              define PACKET3_SH_KCACHE_ACTION_ENA (1 << 27)
+#              define PACKET3_SH_ICACHE_ACTION_ENA (1 << 29)
+#define	PACKET3_ME_INITIALIZE				0x44
+#define		PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
+#define	PACKET3_COND_WRITE				0x45
+#define	PACKET3_EVENT_WRITE				0x46
+#define	PACKET3_EVENT_WRITE_EOP				0x47
+#define	PACKET3_EVENT_WRITE_EOS				0x48
+#define	PACKET3_PREAMBLE_CNTL				0x4A
+#              define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE     (2 << 28)
+#              define PACKET3_PREAMBLE_END_CLEAR_STATE       (3 << 28)
+#define	PACKET3_ONE_REG_WRITE				0x57
+#define	PACKET3_LOAD_CONFIG_REG				0x5F
+#define	PACKET3_LOAD_CONTEXT_REG			0x60
+#define	PACKET3_LOAD_SH_REG				0x61
+#define	PACKET3_SET_CONFIG_REG				0x68
+#define		PACKET3_SET_CONFIG_REG_START			0x00002000
+#define		PACKET3_SET_CONFIG_REG_END			0x00002c00
+#define	PACKET3_SET_CONTEXT_REG				0x69
+#define		PACKET3_SET_CONTEXT_REG_START			0x000a000
+#define		PACKET3_SET_CONTEXT_REG_END			0x000a400
+#define	PACKET3_SET_CONTEXT_REG_INDIRECT		0x73
+#define	PACKET3_SET_RESOURCE_INDIRECT			0x74
+#define	PACKET3_SET_SH_REG				0x76
+#define		PACKET3_SET_SH_REG_START			0x00002c00
+#define		PACKET3_SET_SH_REG_END				0x00003000
+#define	PACKET3_SET_SH_REG_OFFSET			0x77
+#define	PACKET3_ME_WRITE				0x7A
+#define	PACKET3_SCRATCH_RAM_WRITE			0x7D
+#define	PACKET3_SCRATCH_RAM_READ			0x7E
+#define	PACKET3_CE_WRITE				0x7F
+#define	PACKET3_LOAD_CONST_RAM				0x80
+#define	PACKET3_WRITE_CONST_RAM				0x81
+#define	PACKET3_WRITE_CONST_RAM_OFFSET			0x82
+#define	PACKET3_DUMP_CONST_RAM				0x83
+#define	PACKET3_INCREMENT_CE_COUNTER			0x84
+#define	PACKET3_INCREMENT_DE_COUNTER			0x85
+#define	PACKET3_WAIT_ON_CE_COUNTER			0x86
+#define	PACKET3_WAIT_ON_DE_COUNTER			0x87
+#define	PACKET3_WAIT_ON_DE_COUNTER_DIFF			0x88
+#define	PACKET3_SET_CE_DE_COUNTERS			0x89
+#define	PACKET3_WAIT_ON_AVAIL_BUFFER			0x8A
+#define	PACKET3_SWITCH_BUFFER				0x8B
+#define PACKET3_SEM_WAIT_ON_SIGNAL    (0x1 << 12)
+#define PACKET3_SEM_SEL_SIGNAL	    (0x6 << 29)
+#define PACKET3_SEM_SEL_WAIT	    (0x7 << 29)
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,6 @@
 #ifndef __SI_H__
 #define __SI_H__
 
-extern const struct amd_ip_funcs si_common_ip_funcs;
-
 void si_srbm_select(struct amdgpu_device *adev,
 		     u32 me, u32 pipe, u32 queue, u32 vmid);
 int si_set_ip_blocks(struct amdgpu_device *adev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.c	2017-02-12 16:03:20.000000000 -0500
@@ -268,7 +268,7 @@ static int si_ih_set_powergating_state(v
 	return 0;
 }
 
-const struct amd_ip_funcs si_ih_ip_funcs = {
+static const struct amd_ip_funcs si_ih_ip_funcs = {
 	.name = "si_ih",
 	.early_init = si_ih_early_init,
 	.late_init = NULL,
@@ -297,3 +297,11 @@ static void si_ih_set_interrupt_funcs(st
 		adev->irq.ih_funcs = &si_ih_funcs;
 }
 
+const struct amdgpu_ip_block_version si_ih_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_IH,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &si_ih_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/si_ih.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __SI_IH_H__
 #define __SI_IH_H__
 
-extern const struct amd_ip_funcs si_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version si_ih_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.c	2017-02-12 16:03:20.000000000 -0500
@@ -455,7 +455,7 @@ static int tonga_ih_set_powergating_stat
 	return 0;
 }
 
-const struct amd_ip_funcs tonga_ih_ip_funcs = {
+static const struct amd_ip_funcs tonga_ih_ip_funcs = {
 	.name = "tonga_ih",
 	.early_init = tonga_ih_early_init,
 	.late_init = NULL,
@@ -487,3 +487,11 @@ static void tonga_ih_set_interrupt_funcs
 		adev->irq.ih_funcs = &tonga_ih_funcs;
 }
 
+const struct amdgpu_ip_block_version tonga_ih_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_IH,
+	.major = 3,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &tonga_ih_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/tonga_ih.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __TONGA_IH_H__
 #define __TONGA_IH_H__
 
-extern const struct amd_ip_funcs tonga_ih_ip_funcs;
+extern const struct amdgpu_ip_block_version tonga_ih_ip_block;
 
-#endif /* __CZ_IH_H__ */
+#endif /* __TONGA_IH_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,13 +36,18 @@
 
 #include "bif/bif_4_1_d.h"
 
+#include "smu/smu_7_0_1_d.h"
+#include "smu/smu_7_0_1_sh_mask.h"
+
 static void uvd_v4_2_mc_resume(struct amdgpu_device *adev);
-static void uvd_v4_2_init_cg(struct amdgpu_device *adev);
 static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev);
 static void uvd_v4_2_set_irq_funcs(struct amdgpu_device *adev);
 static int uvd_v4_2_start(struct amdgpu_device *adev);
 static void uvd_v4_2_stop(struct amdgpu_device *adev);
-
+static int uvd_v4_2_set_clockgating_state(void *handle,
+				enum amd_clockgating_state state);
+static void uvd_v4_2_set_dcm(struct amdgpu_device *adev,
+			     bool sw_mode);
 /**
  * uvd_v4_2_ring_get_rptr - get read pointer
  *
@@ -116,8 +121,7 @@ static int uvd_v4_2_sw_init(void *handle
 
 	ring = &adev->uvd.ring;
 	sprintf(ring->name, "uvd");
-	r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
-			     &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
+	r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
 
 	return r;
 }
@@ -137,7 +141,8 @@ static int uvd_v4_2_sw_fini(void *handle
 
 	return r;
 }
-
+static void uvd_v4_2_enable_mgcg(struct amdgpu_device *adev,
+				 bool enable);
 /**
  * uvd_v4_2_hw_init - start and test UVD block
  *
@@ -152,9 +157,8 @@ static int uvd_v4_2_hw_init(void *handle
 	uint32_t tmp;
 	int r;
 
-	/* raise clocks while booting up the VCPU */
-	amdgpu_asic_set_uvd_clocks(adev, 53300, 40000);
-
+	uvd_v4_2_enable_mgcg(adev, true);
+	amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
 	r = uvd_v4_2_start(adev);
 	if (r)
 		goto done;
@@ -194,8 +198,6 @@ static int uvd_v4_2_hw_init(void *handle
 	amdgpu_ring_commit(ring);
 
 done:
-	/* lower clocks again */
-	amdgpu_asic_set_uvd_clocks(adev, 0, 0);
 
 	if (!r)
 		DRM_INFO("UVD initialized successfully.\n");
@@ -265,15 +267,14 @@ static int uvd_v4_2_start(struct amdgpu_
 	struct amdgpu_ring *ring = &adev->uvd.ring;
 	uint32_t rb_bufsz;
 	int i, j, r;
-
 	/* disable byte swapping */
 	u32 lmi_swap_cntl = 0;
 	u32 mp_swap_cntl = 0;
 
-	uvd_v4_2_mc_resume(adev);
-
-	/* disable clock gating */
 	WREG32(mmUVD_CGC_GATE, 0);
+	uvd_v4_2_set_dcm(adev, true);
+
+	uvd_v4_2_mc_resume(adev);
 
 	/* disable interupt */
 	WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
@@ -408,6 +409,8 @@ static void uvd_v4_2_stop(struct amdgpu_
 
 	/* Unstall UMC and register bus */
 	WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8));
+
+	uvd_v4_2_set_dcm(adev, false);
 }
 
 /**
@@ -526,20 +529,6 @@ static void uvd_v4_2_ring_emit_ib(struct
 	amdgpu_ring_write(ring, ib->length_dw);
 }
 
-static unsigned uvd_v4_2_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		4; /* uvd_v4_2_ring_emit_ib */
-}
-
-static unsigned uvd_v4_2_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		2 + /* uvd_v4_2_ring_emit_hdp_flush */
-		2 + /* uvd_v4_2_ring_emit_hdp_invalidate */
-		14; /* uvd_v4_2_ring_emit_fence  x1 no user fence */
-}
-
 /**
  * uvd_v4_2_mc_resume - memory controller programming
  *
@@ -580,8 +569,6 @@ static void uvd_v4_2_mc_resume(struct am
 	WREG32(mmUVD_UDEC_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
 	WREG32(mmUVD_UDEC_DB_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
 	WREG32(mmUVD_UDEC_DBW_ADDR_CONFIG, adev->gfx.config.gb_addr_config);
-
-	uvd_v4_2_init_cg(adev);
 }
 
 static void uvd_v4_2_enable_mgcg(struct amdgpu_device *adev,
@@ -591,7 +578,7 @@ static void uvd_v4_2_enable_mgcg(struct
 
 	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {
 		data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
-		data = 0xfff;
+		data |= 0xfff;
 		WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
 
 		orig = data = RREG32(mmUVD_CGC_CTRL);
@@ -615,6 +602,8 @@ static void uvd_v4_2_set_dcm(struct amdg
 {
 	u32 tmp, tmp2;
 
+	WREG32_FIELD(UVD_CGC_GATE, REGS, 0);
+
 	tmp = RREG32(mmUVD_CGC_CTRL);
 	tmp &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK | UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
 	tmp |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
@@ -635,19 +624,6 @@ static void uvd_v4_2_set_dcm(struct amdg
 	WREG32_UVD_CTX(ixUVD_CGC_CTRL2, tmp2);
 }
 
-static void uvd_v4_2_init_cg(struct amdgpu_device *adev)
-{
-	bool hw_mode = true;
-
-	if (hw_mode) {
-		uvd_v4_2_set_dcm(adev, false);
-	} else {
-		u32 tmp = RREG32(mmUVD_CGC_CTRL);
-		tmp &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
-		WREG32(mmUVD_CGC_CTRL, tmp);
-	}
-}
-
 static bool uvd_v4_2_is_idle(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -701,17 +677,6 @@ static int uvd_v4_2_process_interrupt(st
 static int uvd_v4_2_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
-	bool gate = false;
-	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
-		return 0;
-
-	if (state == AMD_CG_STATE_GATE)
-		gate = true;
-
-	uvd_v4_2_enable_mgcg(adev, gate);
-
 	return 0;
 }
 
@@ -727,9 +692,6 @@ static int uvd_v4_2_set_powergating_stat
 	 */
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	if (!(adev->pg_flags & AMD_PG_SUPPORT_UVD))
-		return 0;
-
 	if (state == AMD_PG_STATE_GATE) {
 		uvd_v4_2_stop(adev);
 		return 0;
@@ -738,7 +700,7 @@ static int uvd_v4_2_set_powergating_stat
 	}
 }
 
-const struct amd_ip_funcs uvd_v4_2_ip_funcs = {
+static const struct amd_ip_funcs uvd_v4_2_ip_funcs = {
 	.name = "uvd_v4_2",
 	.early_init = uvd_v4_2_early_init,
 	.late_init = NULL,
@@ -756,10 +718,18 @@ const struct amd_ip_funcs uvd_v4_2_ip_fu
 };
 
 static const struct amdgpu_ring_funcs uvd_v4_2_ring_funcs = {
+	.type = AMDGPU_RING_TYPE_UVD,
+	.align_mask = 0xf,
+	.nop = PACKET0(mmUVD_NO_OP, 0),
 	.get_rptr = uvd_v4_2_ring_get_rptr,
 	.get_wptr = uvd_v4_2_ring_get_wptr,
 	.set_wptr = uvd_v4_2_ring_set_wptr,
 	.parse_cs = amdgpu_uvd_ring_parse_cs,
+	.emit_frame_size =
+		2 + /* uvd_v4_2_ring_emit_hdp_flush */
+		2 + /* uvd_v4_2_ring_emit_hdp_invalidate */
+		14, /* uvd_v4_2_ring_emit_fence  x1 no user fence */
+	.emit_ib_size = 4, /* uvd_v4_2_ring_emit_ib */
 	.emit_ib = uvd_v4_2_ring_emit_ib,
 	.emit_fence = uvd_v4_2_ring_emit_fence,
 	.emit_hdp_flush = uvd_v4_2_ring_emit_hdp_flush,
@@ -770,8 +740,6 @@ static const struct amdgpu_ring_funcs uv
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.begin_use = amdgpu_uvd_ring_begin_use,
 	.end_use = amdgpu_uvd_ring_end_use,
-	.get_emit_ib_size = uvd_v4_2_ring_get_emit_ib_size,
-	.get_dma_frame_size = uvd_v4_2_ring_get_dma_frame_size,
 };
 
 static void uvd_v4_2_set_ring_funcs(struct amdgpu_device *adev)
@@ -789,3 +757,12 @@ static void uvd_v4_2_set_irq_funcs(struc
 	adev->uvd.irq.num_types = 1;
 	adev->uvd.irq.funcs = &uvd_v4_2_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version uvd_v4_2_ip_block =
+{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 4,
+		.minor = 2,
+		.rev = 0,
+		.funcs = &uvd_v4_2_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v4_2.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __UVD_V4_2_H__
 #define __UVD_V4_2_H__
 
-extern const struct amd_ip_funcs uvd_v4_2_ip_funcs;
+extern const struct amdgpu_ip_block_version uvd_v4_2_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,12 +33,17 @@
 #include "oss/oss_2_0_sh_mask.h"
 #include "bif/bif_5_0_d.h"
 #include "vi.h"
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
 
 static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev);
 static void uvd_v5_0_set_irq_funcs(struct amdgpu_device *adev);
 static int uvd_v5_0_start(struct amdgpu_device *adev);
 static void uvd_v5_0_stop(struct amdgpu_device *adev);
-
+static int uvd_v5_0_set_clockgating_state(void *handle,
+					  enum amd_clockgating_state state);
+static void uvd_v5_0_enable_mgcg(struct amdgpu_device *adev,
+				 bool enable);
 /**
  * uvd_v5_0_ring_get_rptr - get read pointer
  *
@@ -112,8 +117,7 @@ static int uvd_v5_0_sw_init(void *handle
 
 	ring = &adev->uvd.ring;
 	sprintf(ring->name, "uvd");
-	r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
-			     &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
+	r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
 
 	return r;
 }
@@ -148,9 +152,6 @@ static int uvd_v5_0_hw_init(void *handle
 	uint32_t tmp;
 	int r;
 
-	/* raise clocks while booting up the VCPU */
-	amdgpu_asic_set_uvd_clocks(adev, 53300, 40000);
-
 	r = uvd_v5_0_start(adev);
 	if (r)
 		goto done;
@@ -188,11 +189,7 @@ static int uvd_v5_0_hw_init(void *handle
 	amdgpu_ring_write(ring, 3);
 
 	amdgpu_ring_commit(ring);
-
 done:
-	/* lower clocks again */
-	amdgpu_asic_set_uvd_clocks(adev, 0, 0);
-
 	if (!r)
 		DRM_INFO("UVD initialized successfully.\n");
 
@@ -225,6 +222,7 @@ static int uvd_v5_0_suspend(void *handle
 	r = uvd_v5_0_hw_fini(adev);
 	if (r)
 		return r;
+	uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_GATE);
 
 	r = amdgpu_uvd_suspend(adev);
 	if (r)
@@ -312,8 +310,9 @@ static int uvd_v5_0_start(struct amdgpu_
 
 	uvd_v5_0_mc_resume(adev);
 
-	/* disable clock gating */
-	WREG32(mmUVD_CGC_GATE, 0);
+	amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
+	uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
+	uvd_v5_0_enable_mgcg(adev, true);
 
 	/* disable interupt */
 	WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
@@ -577,20 +576,6 @@ static void uvd_v5_0_ring_emit_ib(struct
 	amdgpu_ring_write(ring, ib->length_dw);
 }
 
-static unsigned uvd_v5_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		6; /* uvd_v5_0_ring_emit_ib */
-}
-
-static unsigned uvd_v5_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		2 + /* uvd_v5_0_ring_emit_hdp_flush */
-		2 + /* uvd_v5_0_ring_emit_hdp_invalidate */
-		14; /* uvd_v5_0_ring_emit_fence  x1 no user fence */
-}
-
 static bool uvd_v5_0_is_idle(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -641,16 +626,12 @@ static int uvd_v5_0_process_interrupt(st
 	return 0;
 }
 
-static void uvd_v5_0_set_sw_clock_gating(struct amdgpu_device *adev)
+static void uvd_v5_0_enable_clock_gating(struct amdgpu_device *adev, bool enable)
 {
-	uint32_t data, data1, data2, suvd_flags;
+	uint32_t data1, data3, suvd_flags;
 
-	data = RREG32(mmUVD_CGC_CTRL);
 	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
-	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
-
-	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
-		  UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
+	data3 = RREG32(mmUVD_CGC_GATE);
 
 	suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
 		     UVD_SUVD_CGC_GATE__SIT_MASK |
@@ -658,6 +639,51 @@ static void uvd_v5_0_set_sw_clock_gating
 		     UVD_SUVD_CGC_GATE__SCM_MASK |
 		     UVD_SUVD_CGC_GATE__SDB_MASK;
 
+	if (enable) {
+		data3 |= (UVD_CGC_GATE__SYS_MASK     |
+			UVD_CGC_GATE__UDEC_MASK      |
+			UVD_CGC_GATE__MPEG2_MASK     |
+			UVD_CGC_GATE__RBC_MASK       |
+			UVD_CGC_GATE__LMI_MC_MASK    |
+			UVD_CGC_GATE__IDCT_MASK      |
+			UVD_CGC_GATE__MPRD_MASK      |
+			UVD_CGC_GATE__MPC_MASK       |
+			UVD_CGC_GATE__LBSI_MASK      |
+			UVD_CGC_GATE__LRBBM_MASK     |
+			UVD_CGC_GATE__UDEC_RE_MASK   |
+			UVD_CGC_GATE__UDEC_CM_MASK   |
+			UVD_CGC_GATE__UDEC_IT_MASK   |
+			UVD_CGC_GATE__UDEC_DB_MASK   |
+			UVD_CGC_GATE__UDEC_MP_MASK   |
+			UVD_CGC_GATE__WCB_MASK       |
+			UVD_CGC_GATE__JPEG_MASK      |
+			UVD_CGC_GATE__SCPU_MASK);
+		/* only in pg enabled, we can gate clock to vcpu*/
+		if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
+			data3 |= UVD_CGC_GATE__VCPU_MASK;
+		data3 &= ~UVD_CGC_GATE__REGS_MASK;
+		data1 |= suvd_flags;
+	} else {
+		data3 = 0;
+		data1 = 0;
+	}
+
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+	WREG32(mmUVD_CGC_GATE, data3);
+}
+
+static void uvd_v5_0_set_sw_clock_gating(struct amdgpu_device *adev)
+{
+	uint32_t data, data2;
+
+	data = RREG32(mmUVD_CGC_CTRL);
+	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
+
+
+	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
+		  UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
+
+
 	data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
 		(1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER)) |
 		(4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY));
@@ -688,11 +714,8 @@ static void uvd_v5_0_set_sw_clock_gating
 			UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
 			UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
 			UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
-	data1 |= suvd_flags;
 
 	WREG32(mmUVD_CGC_CTRL, data);
-	WREG32(mmUVD_CGC_GATE, 0);
-	WREG32(mmUVD_SUVD_CGC_GATE, data1);
 	WREG32(mmUVD_SUVD_CGC_CTRL, data2);
 }
 
@@ -737,32 +760,54 @@ static void uvd_v5_0_set_hw_clock_gating
 }
 #endif
 
+static void uvd_v5_0_enable_mgcg(struct amdgpu_device *adev,
+				 bool enable)
+{
+	u32 orig, data;
+
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {
+		data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+		data |= 0xfff;
+		WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
+
+		orig = data = RREG32(mmUVD_CGC_CTRL);
+		data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+		if (orig != data)
+			WREG32(mmUVD_CGC_CTRL, data);
+	} else {
+		data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+		data &= ~0xfff;
+		WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
+
+		orig = data = RREG32(mmUVD_CGC_CTRL);
+		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+		if (orig != data)
+			WREG32(mmUVD_CGC_CTRL, data);
+	}
+}
+
 static int uvd_v5_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
-	static int curstate = -1;
 
 	if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
 		return 0;
 
-	if (curstate == state)
-		return 0;
-
-	curstate = state;
 	if (enable) {
-		/* disable HW gating and enable Sw gating */
-		uvd_v5_0_set_sw_clock_gating(adev);
-	} else {
 		/* wait for STATUS to clear */
 		if (uvd_v5_0_wait_for_idle(handle))
 			return -EBUSY;
+		uvd_v5_0_enable_clock_gating(adev, true);
 
 		/* enable HW gates because UVD is idle */
 /*		uvd_v5_0_set_hw_clock_gating(adev); */
+	} else {
+		uvd_v5_0_enable_clock_gating(adev, false);
 	}
 
+	uvd_v5_0_set_sw_clock_gating(adev);
 	return 0;
 }
 
@@ -789,7 +834,7 @@ static int uvd_v5_0_set_powergating_stat
 	}
 }
 
-const struct amd_ip_funcs uvd_v5_0_ip_funcs = {
+static const struct amd_ip_funcs uvd_v5_0_ip_funcs = {
 	.name = "uvd_v5_0",
 	.early_init = uvd_v5_0_early_init,
 	.late_init = NULL,
@@ -807,10 +852,18 @@ const struct amd_ip_funcs uvd_v5_0_ip_fu
 };
 
 static const struct amdgpu_ring_funcs uvd_v5_0_ring_funcs = {
+	.type = AMDGPU_RING_TYPE_UVD,
+	.align_mask = 0xf,
+	.nop = PACKET0(mmUVD_NO_OP, 0),
 	.get_rptr = uvd_v5_0_ring_get_rptr,
 	.get_wptr = uvd_v5_0_ring_get_wptr,
 	.set_wptr = uvd_v5_0_ring_set_wptr,
 	.parse_cs = amdgpu_uvd_ring_parse_cs,
+	.emit_frame_size =
+		2 + /* uvd_v5_0_ring_emit_hdp_flush */
+		2 + /* uvd_v5_0_ring_emit_hdp_invalidate */
+		14, /* uvd_v5_0_ring_emit_fence  x1 no user fence */
+	.emit_ib_size = 6, /* uvd_v5_0_ring_emit_ib */
 	.emit_ib = uvd_v5_0_ring_emit_ib,
 	.emit_fence = uvd_v5_0_ring_emit_fence,
 	.emit_hdp_flush = uvd_v5_0_ring_emit_hdp_flush,
@@ -821,8 +874,6 @@ static const struct amdgpu_ring_funcs uv
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.begin_use = amdgpu_uvd_ring_begin_use,
 	.end_use = amdgpu_uvd_ring_end_use,
-	.get_emit_ib_size = uvd_v5_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = uvd_v5_0_ring_get_dma_frame_size,
 };
 
 static void uvd_v5_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -840,3 +891,12 @@ static void uvd_v5_0_set_irq_funcs(struc
 	adev->uvd.irq.num_types = 1;
 	adev->uvd.irq.funcs = &uvd_v5_0_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version uvd_v5_0_ip_block =
+{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 5,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v5_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v5_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __UVD_V5_0_H__
 #define __UVD_V5_0_H__
 
-extern const struct amd_ip_funcs uvd_v5_0_ip_funcs;
+extern const struct amdgpu_ip_block_version uvd_v5_0_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,10 @@ static void uvd_v6_0_set_irq_funcs(struc
 static int uvd_v6_0_start(struct amdgpu_device *adev);
 static void uvd_v6_0_stop(struct amdgpu_device *adev);
 static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev);
+static int uvd_v6_0_set_clockgating_state(void *handle,
+					  enum amd_clockgating_state state);
+static void uvd_v6_0_enable_mgcg(struct amdgpu_device *adev,
+				 bool enable);
 
 /**
  * uvd_v6_0_ring_get_rptr - get read pointer
@@ -116,8 +120,7 @@ static int uvd_v6_0_sw_init(void *handle
 
 	ring = &adev->uvd.ring;
 	sprintf(ring->name, "uvd");
-	r = amdgpu_ring_init(adev, ring, 512, PACKET0(mmUVD_NO_OP, 0), 0xf,
-			     &adev->uvd.irq, 0, AMDGPU_RING_TYPE_UVD);
+	r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
 
 	return r;
 }
@@ -394,11 +397,11 @@ static int uvd_v6_0_start(struct amdgpu_
 	lmi_swap_cntl = 0;
 	mp_swap_cntl = 0;
 
+	amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
+	uvd_v6_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
+	uvd_v6_0_enable_mgcg(adev, true);
 	uvd_v6_0_mc_resume(adev);
 
-	/* disable clock gating */
-	WREG32_FIELD(UVD_CGC_CTRL, DYN_CLOCK_MODE, 0);
-
 	/* disable interupt */
 	WREG32_FIELD(UVD_MASTINT_EN, VCPU_EN, 0);
 
@@ -725,31 +728,6 @@ static void uvd_v6_0_ring_emit_pipeline_
 	amdgpu_ring_write(ring, 0xE);
 }
 
-static unsigned uvd_v6_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		8; /* uvd_v6_0_ring_emit_ib */
-}
-
-static unsigned uvd_v6_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		2 + /* uvd_v6_0_ring_emit_hdp_flush */
-		2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
-		10 + /* uvd_v6_0_ring_emit_pipeline_sync */
-		14; /* uvd_v6_0_ring_emit_fence x1 no user fence */
-}
-
-static unsigned uvd_v6_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring)
-{
-	return
-		2 + /* uvd_v6_0_ring_emit_hdp_flush */
-		2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
-		10 + /* uvd_v6_0_ring_emit_pipeline_sync */
-		20 + /* uvd_v6_0_ring_emit_vm_flush */
-		14 + 14; /* uvd_v6_0_ring_emit_fence x2 vm fence */
-}
-
 static bool uvd_v6_0_is_idle(void *handle)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -862,22 +840,72 @@ static int uvd_v6_0_process_interrupt(st
 	return 0;
 }
 
+static void uvd_v6_0_enable_clock_gating(struct amdgpu_device *adev, bool enable)
+{
+	uint32_t data1, data3;
+
+	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
+	data3 = RREG32(mmUVD_CGC_GATE);
+
+	data1 |= UVD_SUVD_CGC_GATE__SRE_MASK |
+		     UVD_SUVD_CGC_GATE__SIT_MASK |
+		     UVD_SUVD_CGC_GATE__SMP_MASK |
+		     UVD_SUVD_CGC_GATE__SCM_MASK |
+		     UVD_SUVD_CGC_GATE__SDB_MASK |
+		     UVD_SUVD_CGC_GATE__SRE_H264_MASK |
+		     UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |
+		     UVD_SUVD_CGC_GATE__SIT_H264_MASK |
+		     UVD_SUVD_CGC_GATE__SIT_HEVC_MASK |
+		     UVD_SUVD_CGC_GATE__SCM_H264_MASK |
+		     UVD_SUVD_CGC_GATE__SCM_HEVC_MASK |
+		     UVD_SUVD_CGC_GATE__SDB_H264_MASK |
+		     UVD_SUVD_CGC_GATE__SDB_HEVC_MASK;
+
+	if (enable) {
+		data3 |= (UVD_CGC_GATE__SYS_MASK       |
+			UVD_CGC_GATE__UDEC_MASK      |
+			UVD_CGC_GATE__MPEG2_MASK     |
+			UVD_CGC_GATE__RBC_MASK       |
+			UVD_CGC_GATE__LMI_MC_MASK    |
+			UVD_CGC_GATE__LMI_UMC_MASK   |
+			UVD_CGC_GATE__IDCT_MASK      |
+			UVD_CGC_GATE__MPRD_MASK      |
+			UVD_CGC_GATE__MPC_MASK       |
+			UVD_CGC_GATE__LBSI_MASK      |
+			UVD_CGC_GATE__LRBBM_MASK     |
+			UVD_CGC_GATE__UDEC_RE_MASK   |
+			UVD_CGC_GATE__UDEC_CM_MASK   |
+			UVD_CGC_GATE__UDEC_IT_MASK   |
+			UVD_CGC_GATE__UDEC_DB_MASK   |
+			UVD_CGC_GATE__UDEC_MP_MASK   |
+			UVD_CGC_GATE__WCB_MASK       |
+			UVD_CGC_GATE__JPEG_MASK      |
+			UVD_CGC_GATE__SCPU_MASK      |
+			UVD_CGC_GATE__JPEG2_MASK);
+		/* only in pg enabled, we can gate clock to vcpu*/
+		if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
+			data3 |= UVD_CGC_GATE__VCPU_MASK;
+
+		data3 &= ~UVD_CGC_GATE__REGS_MASK;
+	} else {
+		data3 = 0;
+	}
+
+	WREG32(mmUVD_SUVD_CGC_GATE, data1);
+	WREG32(mmUVD_CGC_GATE, data3);
+}
+
 static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev)
 {
-	uint32_t data, data1, data2, suvd_flags;
+	uint32_t data, data2;
 
 	data = RREG32(mmUVD_CGC_CTRL);
-	data1 = RREG32(mmUVD_SUVD_CGC_GATE);
 	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);
 
+
 	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |
 		  UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);
 
-	suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |
-		     UVD_SUVD_CGC_GATE__SIT_MASK |
-		     UVD_SUVD_CGC_GATE__SMP_MASK |
-		     UVD_SUVD_CGC_GATE__SCM_MASK |
-		     UVD_SUVD_CGC_GATE__SDB_MASK;
 
 	data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |
 		(1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER)) |
@@ -910,11 +938,8 @@ static void uvd_v6_0_set_sw_clock_gating
 			UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |
 			UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |
 			UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);
-	data1 |= suvd_flags;
 
 	WREG32(mmUVD_CGC_CTRL, data);
-	WREG32(mmUVD_CGC_GATE, 0);
-	WREG32(mmUVD_SUVD_CGC_GATE, data1);
 	WREG32(mmUVD_SUVD_CGC_CTRL, data2);
 }
 
@@ -961,44 +986,53 @@ static void uvd_v6_0_set_hw_clock_gating
 }
 #endif
 
-static void uvd_v6_set_bypass_mode(struct amdgpu_device *adev, bool enable)
+static void uvd_v6_0_enable_mgcg(struct amdgpu_device *adev,
+				 bool enable)
 {
-	u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL);
+	u32 orig, data;
 
-	if (enable)
-		tmp |= (GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK |
-			GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK);
-	else
-		tmp &= ~(GCK_DFS_BYPASS_CNTL__BYPASSDCLK_MASK |
-			 GCK_DFS_BYPASS_CNTL__BYPASSVCLK_MASK);
+	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {
+		data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+		data |= 0xfff;
+		WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
 
-	WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp);
+		orig = data = RREG32(mmUVD_CGC_CTRL);
+		data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+		if (orig != data)
+			WREG32(mmUVD_CGC_CTRL, data);
+	} else {
+		data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);
+		data &= ~0xfff;
+		WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);
+
+		orig = data = RREG32(mmUVD_CGC_CTRL);
+		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
+		if (orig != data)
+			WREG32(mmUVD_CGC_CTRL, data);
+	}
 }
 
 static int uvd_v6_0_set_clockgating_state(void *handle,
 					  enum amd_clockgating_state state)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
-	if (adev->asic_type == CHIP_FIJI ||
-	    adev->asic_type == CHIP_POLARIS10)
-		uvd_v6_set_bypass_mode(adev, state == AMD_CG_STATE_GATE ? true : false);
+	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
 
 	if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
 		return 0;
 
-	if (state == AMD_CG_STATE_GATE) {
-		/* disable HW gating and enable Sw gating */
-		uvd_v6_0_set_sw_clock_gating(adev);
-	} else {
+	if (enable) {
 		/* wait for STATUS to clear */
 		if (uvd_v6_0_wait_for_idle(handle))
 			return -EBUSY;
-
+		uvd_v6_0_enable_clock_gating(adev, true);
 		/* enable HW gates because UVD is idle */
 /*		uvd_v6_0_set_hw_clock_gating(adev); */
+	} else {
+		/* disable HW gating and enable Sw gating */
+		uvd_v6_0_enable_clock_gating(adev, false);
 	}
-
+	uvd_v6_0_set_sw_clock_gating(adev);
 	return 0;
 }
 
@@ -1027,7 +1061,7 @@ static int uvd_v6_0_set_powergating_stat
 	}
 }
 
-const struct amd_ip_funcs uvd_v6_0_ip_funcs = {
+static const struct amd_ip_funcs uvd_v6_0_ip_funcs = {
 	.name = "uvd_v6_0",
 	.early_init = uvd_v6_0_early_init,
 	.late_init = NULL,
@@ -1048,10 +1082,19 @@ const struct amd_ip_funcs uvd_v6_0_ip_fu
 };
 
 static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = {
+	.type = AMDGPU_RING_TYPE_UVD,
+	.align_mask = 0xf,
+	.nop = PACKET0(mmUVD_NO_OP, 0),
 	.get_rptr = uvd_v6_0_ring_get_rptr,
 	.get_wptr = uvd_v6_0_ring_get_wptr,
 	.set_wptr = uvd_v6_0_ring_set_wptr,
 	.parse_cs = amdgpu_uvd_ring_parse_cs,
+	.emit_frame_size =
+		2 + /* uvd_v6_0_ring_emit_hdp_flush */
+		2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
+		10 + /* uvd_v6_0_ring_emit_pipeline_sync */
+		14, /* uvd_v6_0_ring_emit_fence x1 no user fence */
+	.emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */
 	.emit_ib = uvd_v6_0_ring_emit_ib,
 	.emit_fence = uvd_v6_0_ring_emit_fence,
 	.emit_hdp_flush = uvd_v6_0_ring_emit_hdp_flush,
@@ -1062,15 +1105,22 @@ static const struct amdgpu_ring_funcs uv
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.begin_use = amdgpu_uvd_ring_begin_use,
 	.end_use = amdgpu_uvd_ring_end_use,
-	.get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size,
 };
 
 static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = {
+	.type = AMDGPU_RING_TYPE_UVD,
+	.align_mask = 0xf,
+	.nop = PACKET0(mmUVD_NO_OP, 0),
 	.get_rptr = uvd_v6_0_ring_get_rptr,
 	.get_wptr = uvd_v6_0_ring_get_wptr,
 	.set_wptr = uvd_v6_0_ring_set_wptr,
-	.parse_cs = NULL,
+	.emit_frame_size =
+		2 + /* uvd_v6_0_ring_emit_hdp_flush */
+		2 + /* uvd_v6_0_ring_emit_hdp_invalidate */
+		10 + /* uvd_v6_0_ring_emit_pipeline_sync */
+		20 + /* uvd_v6_0_ring_emit_vm_flush */
+		14 + 14, /* uvd_v6_0_ring_emit_fence x2 vm fence */
+	.emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */
 	.emit_ib = uvd_v6_0_ring_emit_ib,
 	.emit_fence = uvd_v6_0_ring_emit_fence,
 	.emit_vm_flush = uvd_v6_0_ring_emit_vm_flush,
@@ -1083,8 +1133,6 @@ static const struct amdgpu_ring_funcs uv
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.begin_use = amdgpu_uvd_ring_begin_use,
 	.end_use = amdgpu_uvd_ring_end_use,
-	.get_emit_ib_size = uvd_v6_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = uvd_v6_0_ring_get_dma_frame_size_vm,
 };
 
 static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -1108,3 +1156,30 @@ static void uvd_v6_0_set_irq_funcs(struc
 	adev->uvd.irq.num_types = 1;
 	adev->uvd.irq.funcs = &uvd_v6_0_irq_funcs;
 }
+
+const struct amdgpu_ip_block_version uvd_v6_0_ip_block =
+{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version uvd_v6_2_ip_block =
+{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 2,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version uvd_v6_3_ip_block =
+{
+		.type = AMD_IP_BLOCK_TYPE_UVD,
+		.major = 6,
+		.minor = 3,
+		.rev = 0,
+		.funcs = &uvd_v6_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,8 @@
 #ifndef __UVD_V6_0_H__
 #define __UVD_V6_0_H__
 
-extern const struct amd_ip_funcs uvd_v6_0_ip_funcs;
+extern const struct amdgpu_ip_block_version uvd_v6_0_ip_block;
+extern const struct amdgpu_ip_block_version uvd_v6_2_ip_block;
+extern const struct amdgpu_ip_block_version uvd_v6_3_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -224,8 +224,8 @@ static int vce_v2_0_sw_init(void *handle
 	for (i = 0; i < adev->vce.num_rings; i++) {
 		ring = &adev->vce.ring[i];
 		sprintf(ring->name, "vce%d", i);
-		r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
-				     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
+		r = amdgpu_ring_init(adev, ring, 512,
+				     &adev->vce.irq, 0);
 		if (r)
 			return r;
 	}
@@ -592,7 +592,7 @@ static int vce_v2_0_set_powergating_stat
 		return vce_v2_0_start(adev);
 }
 
-const struct amd_ip_funcs vce_v2_0_ip_funcs = {
+static const struct amd_ip_funcs vce_v2_0_ip_funcs = {
 	.name = "vce_v2_0",
 	.early_init = vce_v2_0_early_init,
 	.late_init = NULL,
@@ -610,10 +610,15 @@ const struct amd_ip_funcs vce_v2_0_ip_fu
 };
 
 static const struct amdgpu_ring_funcs vce_v2_0_ring_funcs = {
+	.type = AMDGPU_RING_TYPE_VCE,
+	.align_mask = 0xf,
+	.nop = VCE_CMD_NO_OP,
 	.get_rptr = vce_v2_0_ring_get_rptr,
 	.get_wptr = vce_v2_0_ring_get_wptr,
 	.set_wptr = vce_v2_0_ring_set_wptr,
 	.parse_cs = amdgpu_vce_ring_parse_cs,
+	.emit_frame_size = 6, /* amdgpu_vce_ring_emit_fence  x1 no user fence */
+	.emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */
 	.emit_ib = amdgpu_vce_ring_emit_ib,
 	.emit_fence = amdgpu_vce_ring_emit_fence,
 	.test_ring = amdgpu_vce_ring_test_ring,
@@ -622,8 +627,6 @@ static const struct amdgpu_ring_funcs vc
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.begin_use = amdgpu_vce_ring_begin_use,
 	.end_use = amdgpu_vce_ring_end_use,
-	.get_emit_ib_size = amdgpu_vce_ring_get_emit_ib_size,
-	.get_dma_frame_size = amdgpu_vce_ring_get_dma_frame_size,
 };
 
 static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -644,3 +647,12 @@ static void vce_v2_0_set_irq_funcs(struc
 	adev->vce.irq.num_types = 1;
 	adev->vce.irq.funcs = &vce_v2_0_irq_funcs;
 };
+
+const struct amdgpu_ip_block_version vce_v2_0_ip_block =
+{
+		.type = AMD_IP_BLOCK_TYPE_VCE,
+		.major = 2,
+		.minor = 0,
+		.rev = 0,
+		.funcs = &vce_v2_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v2_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,6 @@
 #ifndef __VCE_V2_0_H__
 #define __VCE_V2_0_H__
 
-extern const struct amd_ip_funcs vce_v2_0_ip_funcs;
+extern const struct amdgpu_ip_block_version vce_v2_0_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,9 +43,13 @@
 
 #define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT	0x04
 #define GRBM_GFX_INDEX__VCE_INSTANCE_MASK	0x10
+#define GRBM_GFX_INDEX__VCE_ALL_PIPE		0x07
+
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0	0x8616
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1	0x8617
 #define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2	0x8618
+#define mmGRBM_GFX_INDEX_DEFAULT 0xE0000000
+
 #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK	0x02
 
 #define VCE_V3_0_FW_SIZE	(384 * 1024)
@@ -54,6 +58,9 @@
 
 #define FW_52_8_3	((52 << 24) | (8 << 16) | (3 << 8))
 
+#define GET_VCE_INSTANCE(i)  ((i) << GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT \
+					| GRBM_GFX_INDEX__VCE_ALL_PIPE)
+
 static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -134,7 +141,7 @@ static void vce_v3_0_set_vce_sw_clock_ga
 	   accessible but the firmware will throttle the clocks on the
 	   fly as necessary.
 	*/
-	if (gated) {
+	if (!gated) {
 		data = RREG32(mmVCE_CLOCK_GATING_B);
 		data |= 0x1ff;
 		data &= ~0xef0000;
@@ -175,7 +182,7 @@ static void vce_v3_0_set_vce_sw_clock_ga
 		WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
 
 		data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
-		data &= ~0xffc00000;
+		data &= ~0x3ff;
 		WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
 
 		data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
@@ -249,7 +256,7 @@ static int vce_v3_0_start(struct amdgpu_
 		if (adev->vce.harvest_config & (1 << idx))
 			continue;
 
-		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
 		vce_v3_0_mc_resume(adev, idx);
 		WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1);
 
@@ -273,7 +280,7 @@ static int vce_v3_0_start(struct amdgpu_
 		}
 	}
 
-	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	return 0;
@@ -288,7 +295,7 @@ static int vce_v3_0_stop(struct amdgpu_d
 		if (adev->vce.harvest_config & (1 << idx))
 			continue;
 
-		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
 
 		if (adev->asic_type >= CHIP_STONEY)
 			WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x200001);
@@ -306,7 +313,7 @@ static int vce_v3_0_stop(struct amdgpu_d
 			vce_v3_0_set_vce_sw_clock_gating(adev, false);
 	}
 
-	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	return 0;
@@ -320,11 +327,12 @@ static unsigned vce_v3_0_get_harvest_con
 {
 	u32 tmp;
 
-	/* Fiji, Stoney, Polaris10, Polaris11 are single pipe */
+	/* Fiji, Stoney, Polaris10, Polaris11, Polaris12 are single pipe */
 	if ((adev->asic_type == CHIP_FIJI) ||
 	    (adev->asic_type == CHIP_STONEY) ||
 	    (adev->asic_type == CHIP_POLARIS10) ||
-	    (adev->asic_type == CHIP_POLARIS11))
+	    (adev->asic_type == CHIP_POLARIS11) ||
+	    (adev->asic_type == CHIP_POLARIS12))
 		return AMDGPU_VCE_HARVEST_VCE1;
 
 	/* Tonga and CZ are dual or single pipe */
@@ -395,8 +403,7 @@ static int vce_v3_0_sw_init(void *handle
 	for (i = 0; i < adev->vce.num_rings; i++) {
 		ring = &adev->vce.ring[i];
 		sprintf(ring->name, "vce%d", i);
-		r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
-				     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
+		r = amdgpu_ring_init(adev, ring, 512, &adev->vce.irq, 0);
 		if (r)
 			return r;
 	}
@@ -586,17 +593,17 @@ static bool vce_v3_0_check_soft_reset(vo
 	 * VCE team suggest use bit 3--bit 6 for busy status check
 	 */
 	mutex_lock(&adev->grbm_idx_mutex);
-	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+	WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
 	if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
 	}
-	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0x10);
+	WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
 	if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
 		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
 	}
-	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+	WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	if (srbm_soft_reset) {
@@ -734,7 +741,7 @@ static int vce_v3_0_set_clockgating_stat
 		if (adev->vce.harvest_config & (1 << i))
 			continue;
 
-		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, i);
+		WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(i));
 
 		if (enable) {
 			/* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
@@ -753,7 +760,7 @@ static int vce_v3_0_set_clockgating_stat
 		vce_v3_0_set_vce_sw_clock_gating(adev, enable);
 	}
 
-	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+	WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
 	mutex_unlock(&adev->grbm_idx_mutex);
 
 	return 0;
@@ -814,28 +821,7 @@ static void vce_v3_0_emit_pipeline_sync(
 	amdgpu_ring_write(ring, seq);
 }
 
-static unsigned vce_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring)
-{
-	return
-		5; /* vce_v3_0_ring_emit_ib */
-}
-
-static unsigned vce_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring)
-{
-	return
-		4 + /* vce_v3_0_emit_pipeline_sync */
-		6; /* amdgpu_vce_ring_emit_fence x1 no user fence */
-}
-
-static unsigned vce_v3_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring)
-{
-	return
-		6 + /* vce_v3_0_emit_vm_flush */
-		4 + /* vce_v3_0_emit_pipeline_sync */
-		6 + 6; /* amdgpu_vce_ring_emit_fence x2 vm fence */
-}
-
-const struct amd_ip_funcs vce_v3_0_ip_funcs = {
+static const struct amd_ip_funcs vce_v3_0_ip_funcs = {
 	.name = "vce_v3_0",
 	.early_init = vce_v3_0_early_init,
 	.late_init = NULL,
@@ -856,10 +842,17 @@ const struct amd_ip_funcs vce_v3_0_ip_fu
 };
 
 static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = {
+	.type = AMDGPU_RING_TYPE_VCE,
+	.align_mask = 0xf,
+	.nop = VCE_CMD_NO_OP,
 	.get_rptr = vce_v3_0_ring_get_rptr,
 	.get_wptr = vce_v3_0_ring_get_wptr,
 	.set_wptr = vce_v3_0_ring_set_wptr,
 	.parse_cs = amdgpu_vce_ring_parse_cs,
+	.emit_frame_size =
+		4 + /* vce_v3_0_emit_pipeline_sync */
+		6, /* amdgpu_vce_ring_emit_fence x1 no user fence */
+	.emit_ib_size = 5, /* vce_v3_0_ring_emit_ib */
 	.emit_ib = amdgpu_vce_ring_emit_ib,
 	.emit_fence = amdgpu_vce_ring_emit_fence,
 	.test_ring = amdgpu_vce_ring_test_ring,
@@ -868,15 +861,21 @@ static const struct amdgpu_ring_funcs vc
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.begin_use = amdgpu_vce_ring_begin_use,
 	.end_use = amdgpu_vce_ring_end_use,
-	.get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size,
 };
 
 static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = {
+	.type = AMDGPU_RING_TYPE_VCE,
+	.align_mask = 0xf,
+	.nop = VCE_CMD_NO_OP,
 	.get_rptr = vce_v3_0_ring_get_rptr,
 	.get_wptr = vce_v3_0_ring_get_wptr,
 	.set_wptr = vce_v3_0_ring_set_wptr,
-	.parse_cs = NULL,
+	.parse_cs = amdgpu_vce_ring_parse_cs_vm,
+	.emit_frame_size =
+		6 + /* vce_v3_0_emit_vm_flush */
+		4 + /* vce_v3_0_emit_pipeline_sync */
+		6 + 6, /* amdgpu_vce_ring_emit_fence x2 vm fence */
+	.emit_ib_size = 4, /* amdgpu_vce_ring_emit_ib */
 	.emit_ib = vce_v3_0_ring_emit_ib,
 	.emit_vm_flush = vce_v3_0_emit_vm_flush,
 	.emit_pipeline_sync = vce_v3_0_emit_pipeline_sync,
@@ -887,8 +886,6 @@ static const struct amdgpu_ring_funcs vc
 	.pad_ib = amdgpu_ring_generic_pad_ib,
 	.begin_use = amdgpu_vce_ring_begin_use,
 	.end_use = amdgpu_vce_ring_end_use,
-	.get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size,
-	.get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size_vm,
 };
 
 static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
@@ -916,3 +913,30 @@ static void vce_v3_0_set_irq_funcs(struc
 	adev->vce.irq.num_types = 1;
 	adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
 };
+
+const struct amdgpu_ip_block_version vce_v3_0_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_VCE,
+	.major = 3,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &vce_v3_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version vce_v3_1_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_VCE,
+	.major = 3,
+	.minor = 1,
+	.rev = 0,
+	.funcs = &vce_v3_0_ip_funcs,
+};
+
+const struct amdgpu_ip_block_version vce_v3_4_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_VCE,
+	.major = 3,
+	.minor = 4,
+	.rev = 0,
+	.funcs = &vce_v3_0_ip_funcs,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vce_v3_0.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,8 @@
 #ifndef __VCE_V3_0_H__
 #define __VCE_V3_0_H__
 
-extern const struct amd_ip_funcs vce_v3_0_ip_funcs;
+extern const struct amdgpu_ip_block_version vce_v3_0_ip_block;
+extern const struct amdgpu_ip_block_version vce_v3_1_ip_block;
+extern const struct amdgpu_ip_block_version vce_v3_4_ip_block;
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vi.c	2016-12-11 17:41:24.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vi.c	2017-02-12 17:24:17.000000000 -0500
@@ -115,8 +115,8 @@ static u32 vi_smc_rreg(struct amdgpu_dev
 	u32 r;
 
 	spin_lock_irqsave(&adev->smc_idx_lock, flags);
-	WREG32(mmSMC_IND_INDEX_0, (reg));
-	r = RREG32(mmSMC_IND_DATA_0);
+	WREG32(mmSMC_IND_INDEX_11, (reg));
+	r = RREG32(mmSMC_IND_DATA_11);
 	spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
 	return r;
 }
@@ -126,8 +126,8 @@ static void vi_smc_wreg(struct amdgpu_de
 	unsigned long flags;
 
 	spin_lock_irqsave(&adev->smc_idx_lock, flags);
-	WREG32(mmSMC_IND_INDEX_0, (reg));
-	WREG32(mmSMC_IND_DATA_0, (v));
+	WREG32(mmSMC_IND_INDEX_11, (reg));
+	WREG32(mmSMC_IND_DATA_11, (v));
 	spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
 }
 
@@ -304,6 +304,7 @@ static void vi_init_golden_registers(str
 		break;
 	case CHIP_POLARIS11:
 	case CHIP_POLARIS10:
+	case CHIP_POLARIS12:
 	default:
 		break;
 	}
@@ -431,12 +432,12 @@ static bool vi_read_bios_from_rom(struct
 	/* take the smc lock since we are using the smc index */
 	spin_lock_irqsave(&adev->smc_idx_lock, flags);
 	/* set rom index to 0 */
-	WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX);
-	WREG32(mmSMC_IND_DATA_0, 0);
+	WREG32(mmSMC_IND_INDEX_11, ixROM_INDEX);
+	WREG32(mmSMC_IND_DATA_11, 0);
 	/* set index to data for continous read */
-	WREG32(mmSMC_IND_INDEX_0, ixROM_DATA);
+	WREG32(mmSMC_IND_INDEX_11, ixROM_DATA);
 	for (i = 0; i < length_dw; i++)
-		dw_ptr[i] = RREG32(mmSMC_IND_DATA_0);
+		dw_ptr[i] = RREG32(mmSMC_IND_DATA_11);
 	spin_unlock_irqrestore(&adev->smc_idx_lock, flags);
 
 	return true;
@@ -550,21 +551,100 @@ static const struct amdgpu_allowed_regis
 	{mmPA_SC_RASTER_CONFIG_1, false, true},
 };
 
-static uint32_t vi_read_indexed_register(struct amdgpu_device *adev, u32 se_num,
-					 u32 sh_num, u32 reg_offset)
+static uint32_t vi_get_register_value(struct amdgpu_device *adev,
+				      bool indexed, u32 se_num,
+				      u32 sh_num, u32 reg_offset)
 {
-	uint32_t val;
+	if (indexed) {
+		uint32_t val;
+		unsigned se_idx = (se_num == 0xffffffff) ? 0 : se_num;
+		unsigned sh_idx = (sh_num == 0xffffffff) ? 0 : sh_num;
 
-	mutex_lock(&adev->grbm_idx_mutex);
-	if (se_num != 0xffffffff || sh_num != 0xffffffff)
-		amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
+		switch (reg_offset) {
+		case mmCC_RB_BACKEND_DISABLE:
+			return adev->gfx.config.rb_config[se_idx][sh_idx].rb_backend_disable;
+		case mmGC_USER_RB_BACKEND_DISABLE:
+			return adev->gfx.config.rb_config[se_idx][sh_idx].user_rb_backend_disable;
+		case mmPA_SC_RASTER_CONFIG:
+			return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config;
+		case mmPA_SC_RASTER_CONFIG_1:
+			return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config_1;
+		}
 
-	val = RREG32(reg_offset);
+		mutex_lock(&adev->grbm_idx_mutex);
+		if (se_num != 0xffffffff || sh_num != 0xffffffff)
+			amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
 
-	if (se_num != 0xffffffff || sh_num != 0xffffffff)
-		amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
-	mutex_unlock(&adev->grbm_idx_mutex);
-	return val;
+		val = RREG32(reg_offset);
+
+		if (se_num != 0xffffffff || sh_num != 0xffffffff)
+			amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+		mutex_unlock(&adev->grbm_idx_mutex);
+		return val;
+	} else {
+		unsigned idx;
+
+		switch (reg_offset) {
+		case mmGB_ADDR_CONFIG:
+			return adev->gfx.config.gb_addr_config;
+		case mmMC_ARB_RAMCFG:
+			return adev->gfx.config.mc_arb_ramcfg;
+		case mmGB_TILE_MODE0:
+		case mmGB_TILE_MODE1:
+		case mmGB_TILE_MODE2:
+		case mmGB_TILE_MODE3:
+		case mmGB_TILE_MODE4:
+		case mmGB_TILE_MODE5:
+		case mmGB_TILE_MODE6:
+		case mmGB_TILE_MODE7:
+		case mmGB_TILE_MODE8:
+		case mmGB_TILE_MODE9:
+		case mmGB_TILE_MODE10:
+		case mmGB_TILE_MODE11:
+		case mmGB_TILE_MODE12:
+		case mmGB_TILE_MODE13:
+		case mmGB_TILE_MODE14:
+		case mmGB_TILE_MODE15:
+		case mmGB_TILE_MODE16:
+		case mmGB_TILE_MODE17:
+		case mmGB_TILE_MODE18:
+		case mmGB_TILE_MODE19:
+		case mmGB_TILE_MODE20:
+		case mmGB_TILE_MODE21:
+		case mmGB_TILE_MODE22:
+		case mmGB_TILE_MODE23:
+		case mmGB_TILE_MODE24:
+		case mmGB_TILE_MODE25:
+		case mmGB_TILE_MODE26:
+		case mmGB_TILE_MODE27:
+		case mmGB_TILE_MODE28:
+		case mmGB_TILE_MODE29:
+		case mmGB_TILE_MODE30:
+		case mmGB_TILE_MODE31:
+			idx = (reg_offset - mmGB_TILE_MODE0);
+			return adev->gfx.config.tile_mode_array[idx];
+		case mmGB_MACROTILE_MODE0:
+		case mmGB_MACROTILE_MODE1:
+		case mmGB_MACROTILE_MODE2:
+		case mmGB_MACROTILE_MODE3:
+		case mmGB_MACROTILE_MODE4:
+		case mmGB_MACROTILE_MODE5:
+		case mmGB_MACROTILE_MODE6:
+		case mmGB_MACROTILE_MODE7:
+		case mmGB_MACROTILE_MODE8:
+		case mmGB_MACROTILE_MODE9:
+		case mmGB_MACROTILE_MODE10:
+		case mmGB_MACROTILE_MODE11:
+		case mmGB_MACROTILE_MODE12:
+		case mmGB_MACROTILE_MODE13:
+		case mmGB_MACROTILE_MODE14:
+		case mmGB_MACROTILE_MODE15:
+			idx = (reg_offset - mmGB_MACROTILE_MODE0);
+			return adev->gfx.config.macrotile_mode_array[idx];
+		default:
+			return RREG32(reg_offset);
+		}
+	}
 }
 
 static int vi_read_register(struct amdgpu_device *adev, u32 se_num,
@@ -584,6 +664,7 @@ static int vi_read_register(struct amdgp
 	case CHIP_TONGA:
 	case CHIP_POLARIS11:
 	case CHIP_POLARIS10:
+	case CHIP_POLARIS12:
 	case CHIP_CARRIZO:
 	case CHIP_STONEY:
 		asic_register_table = cz_allowed_read_registers;
@@ -599,10 +680,9 @@ static int vi_read_register(struct amdgp
 			if (reg_offset != asic_register_entry->reg_offset)
 				continue;
 			if (!asic_register_entry->untouched)
-				*value = asic_register_entry->grbm_indexed ?
-					vi_read_indexed_register(adev, se_num,
-								 sh_num, reg_offset) :
-					RREG32(reg_offset);
+				*value = vi_get_register_value(adev,
+							       asic_register_entry->grbm_indexed,
+							       se_num, sh_num, reg_offset);
 			return 0;
 		}
 	}
@@ -612,10 +692,9 @@ static int vi_read_register(struct amdgp
 			continue;
 
 		if (!vi_allowed_read_registers[i].untouched)
-			*value = vi_allowed_read_registers[i].grbm_indexed ?
-				vi_read_indexed_register(adev, se_num,
-							 sh_num, reg_offset) :
-				RREG32(reg_offset);
+			*value = vi_get_register_value(adev,
+						       vi_allowed_read_registers[i].grbm_indexed,
+						       se_num, sh_num, reg_offset);
 		return 0;
 	}
 	return -EINVAL;
@@ -646,18 +725,6 @@ static int vi_gpu_pci_config_reset(struc
 	return -EINVAL;
 }
 
-static void vi_set_bios_scratch_engine_hung(struct amdgpu_device *adev, bool hung)
-{
-	u32 tmp = RREG32(mmBIOS_SCRATCH_3);
-
-	if (hung)
-		tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-	else
-		tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
-
-	WREG32(mmBIOS_SCRATCH_3, tmp);
-}
-
 /**
  * vi_asic_reset - soft reset GPU
  *
@@ -671,11 +738,11 @@ static int vi_asic_reset(struct amdgpu_d
 {
 	int r;
 
-	vi_set_bios_scratch_engine_hung(adev, true);
+	amdgpu_atombios_scratch_regs_engine_hung(adev, true);
 
 	r = vi_gpu_pci_config_reset(adev);
 
-	vi_set_bios_scratch_engine_hung(adev, false);
+	amdgpu_atombios_scratch_regs_engine_hung(adev, false);
 
 	return r;
 }
@@ -775,734 +842,6 @@ static void vi_enable_doorbell_aperture(
 	WREG32(mmBIF_DOORBELL_APER_EN, tmp);
 }
 
-/* topaz has no DCE, UVD, VCE */
-static const struct amdgpu_ip_block_version topaz_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &iceland_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &sdma_v2_4_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version topaz_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 7,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &gmc_v7_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 2,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &iceland_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 1,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 2,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &sdma_v2_4_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version tonga_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &tonga_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 10,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &dce_v10_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 5,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &uvd_v5_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version tonga_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &tonga_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 10,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 5,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &uvd_v5_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version fiji_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 5,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &tonga_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 10,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &dce_v10_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &uvd_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version fiji_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 5,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &tonga_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 10,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &uvd_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version polaris11_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &tonga_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 11,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &dce_v11_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 6,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &uvd_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version polaris11_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &tonga_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 7,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 11,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 1,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 6,
-		.minor = 3,
-		.rev = 0,
-		.funcs = &uvd_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 4,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-};
-
-static const struct amdgpu_ip_block_version cz_ip_blocks[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cz_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 11,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &dce_v11_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &uvd_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-#if defined(CONFIG_DRM_AMD_ACP)
-	{
-		.type = AMD_IP_BLOCK_TYPE_ACP,
-		.major = 2,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &acp_ip_funcs,
-	},
-#endif
-};
-
-static const struct amdgpu_ip_block_version cz_ip_blocks_vd[] =
-{
-	/* ORDER MATTERS! */
-	{
-		.type = AMD_IP_BLOCK_TYPE_COMMON,
-		.major = 2,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vi_common_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GMC,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gmc_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_IH,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &cz_ih_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SMC,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &amdgpu_pp_ip_funcs
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_DCE,
-		.major = 11,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &dce_virtual_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_GFX,
-		.major = 8,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &gfx_v8_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_SDMA,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &sdma_v3_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_UVD,
-		.major = 6,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &uvd_v6_0_ip_funcs,
-	},
-	{
-		.type = AMD_IP_BLOCK_TYPE_VCE,
-		.major = 3,
-		.minor = 0,
-		.rev = 0,
-		.funcs = &vce_v3_0_ip_funcs,
-	},
-#if defined(CONFIG_DRM_AMD_ACP)
-	{
-		.type = AMD_IP_BLOCK_TYPE_ACP,
-		.major = 2,
-		.minor = 2,
-		.rev = 0,
-		.funcs = &acp_ip_funcs,
-	},
-#endif
-};
-
-int vi_set_ip_blocks(struct amdgpu_device *adev)
-{
-	if (adev->enable_virtual_display) {
-		switch (adev->asic_type) {
-		case CHIP_TOPAZ:
-			adev->ip_blocks = topaz_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks_vd);
-			break;
-		case CHIP_FIJI:
-			adev->ip_blocks = fiji_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks_vd);
-			break;
-		case CHIP_TONGA:
-			adev->ip_blocks = tonga_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks_vd);
-			break;
-		case CHIP_POLARIS11:
-		case CHIP_POLARIS10:
-			adev->ip_blocks = polaris11_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(polaris11_ip_blocks_vd);
-			break;
-
-		case CHIP_CARRIZO:
-		case CHIP_STONEY:
-			adev->ip_blocks = cz_ip_blocks_vd;
-			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks_vd);
-			break;
-		default:
-			/* FIXME: not supported yet */
-			return -EINVAL;
-		}
-	} else {
-		switch (adev->asic_type) {
-		case CHIP_TOPAZ:
-			adev->ip_blocks = topaz_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(topaz_ip_blocks);
-			break;
-		case CHIP_FIJI:
-			adev->ip_blocks = fiji_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(fiji_ip_blocks);
-			break;
-		case CHIP_TONGA:
-			adev->ip_blocks = tonga_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(tonga_ip_blocks);
-			break;
-		case CHIP_POLARIS11:
-		case CHIP_POLARIS10:
-			adev->ip_blocks = polaris11_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(polaris11_ip_blocks);
-			break;
-		case CHIP_CARRIZO:
-		case CHIP_STONEY:
-			adev->ip_blocks = cz_ip_blocks;
-			adev->num_ip_blocks = ARRAY_SIZE(cz_ip_blocks);
-			break;
-		default:
-			/* FIXME: not supported yet */
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
 #define ATI_REV_ID_FUSE_MACRO__ADDRESS      0xC0014044
 #define ATI_REV_ID_FUSE_MACRO__SHIFT        9
 #define ATI_REV_ID_FUSE_MACRO__MASK         0x00001E00
@@ -1581,25 +920,79 @@ static int vi_common_early_init(void *ha
 			AMD_CG_SUPPORT_HDP_LS |
 			AMD_CG_SUPPORT_ROM_MGCG |
 			AMD_CG_SUPPORT_MC_MGCG |
-			AMD_CG_SUPPORT_MC_LS;
+			AMD_CG_SUPPORT_MC_LS |
+			AMD_CG_SUPPORT_UVD_MGCG;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x3c;
 		break;
 	case CHIP_TONGA:
-		adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG;
+		adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
+			AMD_CG_SUPPORT_GFX_CGCG |
+			AMD_CG_SUPPORT_GFX_CGLS |
+			AMD_CG_SUPPORT_SDMA_MGCG |
+			AMD_CG_SUPPORT_SDMA_LS |
+			AMD_CG_SUPPORT_BIF_LS |
+			AMD_CG_SUPPORT_HDP_MGCG |
+			AMD_CG_SUPPORT_HDP_LS |
+			AMD_CG_SUPPORT_ROM_MGCG |
+			AMD_CG_SUPPORT_MC_MGCG |
+			AMD_CG_SUPPORT_MC_LS |
+			AMD_CG_SUPPORT_DRM_LS |
+			AMD_CG_SUPPORT_UVD_MGCG;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x14;
 		break;
 	case CHIP_POLARIS11:
-		adev->cg_flags = 0;
+		adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
+			AMD_CG_SUPPORT_GFX_RLC_LS |
+			AMD_CG_SUPPORT_GFX_CP_LS |
+			AMD_CG_SUPPORT_GFX_CGCG |
+			AMD_CG_SUPPORT_GFX_CGLS |
+			AMD_CG_SUPPORT_GFX_3D_CGCG |
+			AMD_CG_SUPPORT_GFX_3D_CGLS |
+			AMD_CG_SUPPORT_SDMA_MGCG |
+			AMD_CG_SUPPORT_SDMA_LS |
+			AMD_CG_SUPPORT_BIF_MGCG |
+			AMD_CG_SUPPORT_BIF_LS |
+			AMD_CG_SUPPORT_HDP_MGCG |
+			AMD_CG_SUPPORT_HDP_LS |
+			AMD_CG_SUPPORT_ROM_MGCG |
+			AMD_CG_SUPPORT_MC_MGCG |
+			AMD_CG_SUPPORT_MC_LS |
+			AMD_CG_SUPPORT_DRM_LS |
+			AMD_CG_SUPPORT_UVD_MGCG |
+			AMD_CG_SUPPORT_VCE_MGCG;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x5A;
 		break;
 	case CHIP_POLARIS10:
-		adev->cg_flags = 0;
+		adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
+			AMD_CG_SUPPORT_GFX_RLC_LS |
+			AMD_CG_SUPPORT_GFX_CP_LS |
+			AMD_CG_SUPPORT_GFX_CGCG |
+			AMD_CG_SUPPORT_GFX_CGLS |
+			AMD_CG_SUPPORT_GFX_3D_CGCG |
+			AMD_CG_SUPPORT_GFX_3D_CGLS |
+			AMD_CG_SUPPORT_SDMA_MGCG |
+			AMD_CG_SUPPORT_SDMA_LS |
+			AMD_CG_SUPPORT_BIF_MGCG |
+			AMD_CG_SUPPORT_BIF_LS |
+			AMD_CG_SUPPORT_HDP_MGCG |
+			AMD_CG_SUPPORT_HDP_LS |
+			AMD_CG_SUPPORT_ROM_MGCG |
+			AMD_CG_SUPPORT_MC_MGCG |
+			AMD_CG_SUPPORT_MC_LS |
+			AMD_CG_SUPPORT_DRM_LS |
+			AMD_CG_SUPPORT_UVD_MGCG |
+			AMD_CG_SUPPORT_VCE_MGCG;
 		adev->pg_flags = 0;
 		adev->external_rev_id = adev->rev_id + 0x50;
 		break;
+	case CHIP_POLARIS12:
+		adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG;
+		adev->pg_flags = 0;
+		adev->external_rev_id = adev->rev_id + 0x64;
+		break;
 	case CHIP_CARRIZO:
 		adev->cg_flags = AMD_CG_SUPPORT_UVD_MGCG |
 			AMD_CG_SUPPORT_GFX_MGCG |
@@ -1623,6 +1016,7 @@ static int vi_common_early_init(void *ha
 			adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG |
 				AMD_PG_SUPPORT_GFX_SMG |
 				AMD_PG_SUPPORT_GFX_PIPELINE |
+				AMD_PG_SUPPORT_CP |
 				AMD_PG_SUPPORT_UVD |
 				AMD_PG_SUPPORT_VCE;
 		}
@@ -1648,6 +1042,7 @@ static int vi_common_early_init(void *ha
 		adev->pg_flags = AMD_PG_SUPPORT_GFX_PG |
 			AMD_PG_SUPPORT_GFX_SMG |
 			AMD_PG_SUPPORT_GFX_PIPELINE |
+			AMD_PG_SUPPORT_CP |
 			AMD_PG_SUPPORT_UVD |
 			AMD_PG_SUPPORT_VCE;
 		adev->external_rev_id = adev->rev_id + 0x61;
@@ -1807,57 +1202,118 @@ static void vi_update_rom_medium_grain_c
 static int vi_common_set_clockgating_state_by_smu(void *handle,
 					   enum amd_clockgating_state state)
 {
-	uint32_t msg_id, pp_state;
+	uint32_t msg_id, pp_state = 0;
+	uint32_t pp_support_state = 0;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	void *pp_handle = adev->powerplay.pp_handle;
 
-	if (state == AMD_CG_STATE_UNGATE)
-		pp_state = 0;
-	else
-		pp_state = PP_STATE_CG | PP_STATE_LS;
+	if (adev->cg_flags & (AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_MC_MGCG)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_MC_LS) {
+			pp_support_state = AMD_CG_SUPPORT_MC_LS;
+			pp_state = PP_STATE_LS;
+		}
+		if (adev->cg_flags & AMD_CG_SUPPORT_MC_MGCG) {
+			pp_support_state |= AMD_CG_SUPPORT_MC_MGCG;
+			pp_state |= PP_STATE_CG;
+		}
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			       PP_BLOCK_SYS_MC,
+			       pp_support_state,
+			       pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
-		       PP_BLOCK_SYS_MC,
-		       PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-		       pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+	if (adev->cg_flags & (AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_SDMA_MGCG)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_SDMA_LS) {
+			pp_support_state = AMD_CG_SUPPORT_SDMA_LS;
+			pp_state = PP_STATE_LS;
+		}
+		if (adev->cg_flags & AMD_CG_SUPPORT_SDMA_MGCG) {
+			pp_support_state |= AMD_CG_SUPPORT_SDMA_MGCG;
+			pp_state |= PP_STATE_CG;
+		}
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			       PP_BLOCK_SYS_SDMA,
+			       pp_support_state,
+			       pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
-		       PP_BLOCK_SYS_SDMA,
-		       PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-		       pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+	if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_MGCG)) {
+		if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) {
+			pp_support_state = AMD_CG_SUPPORT_HDP_LS;
+			pp_state = PP_STATE_LS;
+		}
+		if (adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG) {
+			pp_support_state |= AMD_CG_SUPPORT_HDP_MGCG;
+			pp_state |= PP_STATE_CG;
+		}
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			       PP_BLOCK_SYS_HDP,
+			       pp_support_state,
+			       pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
-		       PP_BLOCK_SYS_HDP,
-		       PP_STATE_SUPPORT_CG | PP_STATE_SUPPORT_LS,
-		       pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
-		       PP_BLOCK_SYS_BIF,
-		       PP_STATE_SUPPORT_LS,
-		       pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+	if (adev->cg_flags & AMD_CG_SUPPORT_BIF_LS) {
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		else
+			pp_state = PP_STATE_LS;
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
-		       PP_BLOCK_SYS_BIF,
-		       PP_STATE_SUPPORT_CG,
-		       pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+		msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			       PP_BLOCK_SYS_BIF,
+			       PP_STATE_SUPPORT_LS,
+			        pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
+	if (adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG) {
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		else
+			pp_state = PP_STATE_CG;
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
-		       PP_BLOCK_SYS_DRM,
-		       PP_STATE_SUPPORT_LS,
-		       pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+		msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			       PP_BLOCK_SYS_BIF,
+			       PP_STATE_SUPPORT_CG,
+			       pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 
-	msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
-		       PP_BLOCK_SYS_ROM,
-		       PP_STATE_SUPPORT_CG,
-		       pp_state);
-	amd_set_clockgating_by_smu(pp_handle, msg_id);
+	if (adev->cg_flags & AMD_CG_SUPPORT_DRM_LS) {
+
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		else
+			pp_state = PP_STATE_LS;
+
+		msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			       PP_BLOCK_SYS_DRM,
+			       PP_STATE_SUPPORT_LS,
+			       pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
+
+	if (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG) {
 
+		if (state == AMD_CG_STATE_UNGATE)
+			pp_state = 0;
+		else
+			pp_state = PP_STATE_CG;
+
+		msg_id = PP_CG_MSG_ID(PP_GROUP_SYS,
+			       PP_BLOCK_SYS_ROM,
+			       PP_STATE_SUPPORT_CG,
+			       pp_state);
+		amd_set_clockgating_by_smu(pp_handle, msg_id);
+	}
 	return 0;
 }
 
@@ -1889,6 +1345,7 @@ static int vi_common_set_clockgating_sta
 	case CHIP_TONGA:
 	case CHIP_POLARIS10:
 	case CHIP_POLARIS11:
+	case CHIP_POLARIS12:
 		vi_common_set_clockgating_state_by_smu(adev, state);
 	default:
 		break;
@@ -1902,7 +1359,7 @@ static int vi_common_set_powergating_sta
 	return 0;
 }
 
-const struct amd_ip_funcs vi_common_ip_funcs = {
+static const struct amd_ip_funcs vi_common_ip_funcs = {
 	.name = "vi_common",
 	.early_init = vi_common_early_init,
 	.late_init = NULL,
@@ -1919,3 +1376,111 @@ const struct amd_ip_funcs vi_common_ip_f
 	.set_powergating_state = vi_common_set_powergating_state,
 };
 
+static const struct amdgpu_ip_block_version vi_common_ip_block =
+{
+	.type = AMD_IP_BLOCK_TYPE_COMMON,
+	.major = 1,
+	.minor = 0,
+	.rev = 0,
+	.funcs = &vi_common_ip_funcs,
+};
+
+int vi_set_ip_blocks(struct amdgpu_device *adev)
+{
+	switch (adev->asic_type) {
+	case CHIP_TOPAZ:
+		/* topaz has no DCE, UVD, VCE */
+		amdgpu_ip_block_add(adev, &vi_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v7_4_ip_block);
+		amdgpu_ip_block_add(adev, &iceland_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &sdma_v2_4_ip_block);
+		break;
+	case CHIP_FIJI:
+		amdgpu_ip_block_add(adev, &vi_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v8_5_ip_block);
+		amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v10_1_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v3_0_ip_block);
+		break;
+	case CHIP_TONGA:
+		amdgpu_ip_block_add(adev, &vi_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v10_0_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v5_0_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v3_0_ip_block);
+		break;
+	case CHIP_POLARIS11:
+	case CHIP_POLARIS10:
+	case CHIP_POLARIS12:
+		amdgpu_ip_block_add(adev, &vi_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v8_1_ip_block);
+		amdgpu_ip_block_add(adev, &tonga_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v11_2_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &sdma_v3_1_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v6_3_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v3_4_ip_block);
+		break;
+	case CHIP_CARRIZO:
+		amdgpu_ip_block_add(adev, &vi_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &cz_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v6_0_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v3_1_ip_block);
+#if defined(CONFIG_DRM_AMD_ACP)
+		amdgpu_ip_block_add(adev, &acp_ip_block);
+#endif
+		break;
+	case CHIP_STONEY:
+		amdgpu_ip_block_add(adev, &vi_common_ip_block);
+		amdgpu_ip_block_add(adev, &gmc_v8_0_ip_block);
+		amdgpu_ip_block_add(adev, &cz_ih_ip_block);
+		amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
+		if (adev->enable_virtual_display)
+			amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
+		else
+			amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
+		amdgpu_ip_block_add(adev, &gfx_v8_1_ip_block);
+		amdgpu_ip_block_add(adev, &sdma_v3_0_ip_block);
+		amdgpu_ip_block_add(adev, &uvd_v6_2_ip_block);
+		amdgpu_ip_block_add(adev, &vce_v3_4_ip_block);
+#if defined(CONFIG_DRM_AMD_ACP)
+		amdgpu_ip_block_add(adev, &acp_ip_block);
+#endif
+		break;
+	default:
+		/* FIXME: not supported yet */
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vi.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vi.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/amdgpu/vi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/amdgpu/vi.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,6 @@
 #ifndef __VI_H__
 #define __VI_H__
 
-extern const struct amd_ip_funcs vi_common_ip_funcs;
-
 void vi_srbm_select(struct amdgpu_device *adev,
 		    u32 me, u32 pipe, u32 queue, u32 vmid);
 int vi_set_ip_blocks(struct amdgpu_device *adev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/amd_shared.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/amd_shared.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/amd_shared.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/amd_shared.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #ifndef __AMD_SHARED_H__
 #define __AMD_SHARED_H__
 
-#define AMD_MAX_USEC_TIMEOUT		100000  /* 100 ms */
+#define AMD_MAX_USEC_TIMEOUT		200000  /* 200 ms */
 
 /*
  * Supported ASIC types
@@ -46,6 +46,7 @@ enum amd_asic_type {
 	CHIP_STONEY,
 	CHIP_POLARIS10,
 	CHIP_POLARIS11,
+	CHIP_POLARIS12,
 	CHIP_LAST,
 };
 
@@ -84,6 +85,29 @@ enum amd_powergating_state {
 	AMD_PG_STATE_UNGATE,
 };
 
+struct amd_vce_state {
+	/* vce clocks */
+	u32 evclk;
+	u32 ecclk;
+	/* gpu clocks */
+	u32 sclk;
+	u32 mclk;
+	u8 clk_idx;
+	u8 pstate;
+};
+
+
+#define AMD_MAX_VCE_LEVELS 6
+
+enum amd_vce_level {
+	AMD_VCE_LEVEL_AC_ALL = 0,     /* AC, All cases */
+	AMD_VCE_LEVEL_DC_EE = 1,      /* DC, entropy encoding */
+	AMD_VCE_LEVEL_DC_LL_LOW = 2,  /* DC, low latency queue, res <= 720 */
+	AMD_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
+	AMD_VCE_LEVEL_DC_GP_LOW = 4,  /* DC, general purpose queue, res <= 720 */
+	AMD_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
+};
+
 /* CG flags */
 #define AMD_CG_SUPPORT_GFX_MGCG			(1 << 0)
 #define AMD_CG_SUPPORT_GFX_MGLS			(1 << 1)
@@ -103,6 +127,10 @@ enum amd_powergating_state {
 #define AMD_CG_SUPPORT_HDP_LS			(1 << 15)
 #define AMD_CG_SUPPORT_HDP_MGCG			(1 << 16)
 #define AMD_CG_SUPPORT_ROM_MGCG			(1 << 17)
+#define AMD_CG_SUPPORT_DRM_LS			(1 << 18)
+#define AMD_CG_SUPPORT_BIF_MGCG			(1 << 19)
+#define AMD_CG_SUPPORT_GFX_3D_CGCG		(1 << 20)
+#define AMD_CG_SUPPORT_GFX_3D_CGLS		(1 << 21)
 
 /* PG flags */
 #define AMD_PG_SUPPORT_GFX_PG			(1 << 0)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,661 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 BIF_3_0_D_H
+#define BIF_3_0_D_H
+
+#define ixPB0_DFT_DEBUG_CTRL_REG0 0x1300C
+#define ixPB0_DFT_JIT_INJ_REG0 0x13000
+#define ixPB0_DFT_JIT_INJ_REG1 0x13004
+#define ixPB0_DFT_JIT_INJ_REG2 0x13008
+#define ixPB0_GLB_CTRL_REG0 0x10004
+#define ixPB0_GLB_CTRL_REG1 0x10008
+#define ixPB0_GLB_CTRL_REG2 0x1000C
+#define ixPB0_GLB_CTRL_REG3 0x10010
+#define ixPB0_GLB_CTRL_REG4 0x10014
+#define ixPB0_GLB_CTRL_REG5 0x10018
+#define ixPB0_GLB_OVRD_REG0 0x10030
+#define ixPB0_GLB_OVRD_REG1 0x10034
+#define ixPB0_GLB_OVRD_REG2 0x10038
+#define ixPB0_GLB_SCI_STAT_OVRD_REG0 0x1001C
+#define ixPB0_GLB_SCI_STAT_OVRD_REG1 0x10020
+#define ixPB0_GLB_SCI_STAT_OVRD_REG2 0x10024
+#define ixPB0_GLB_SCI_STAT_OVRD_REG3 0x10028
+#define ixPB0_GLB_SCI_STAT_OVRD_REG4 0x1002C
+#define ixPB0_HW_DEBUG 0x12004
+#define ixPB0_PIF_CNTL 0x0010
+#define ixPB0_PIF_CNTL2 0x0014
+#define ixPB0_PIF_HW_DEBUG 0x0002
+#define ixPB0_PIF_PAIRING 0x0011
+#define ixPB0_PIF_PDNB_OVERRIDE_0 0x0020
+#define ixPB0_PIF_PDNB_OVERRIDE_10 0x0032
+#define ixPB0_PIF_PDNB_OVERRIDE_1 0x0021
+#define ixPB0_PIF_PDNB_OVERRIDE_11 0x0033
+#define ixPB0_PIF_PDNB_OVERRIDE_12 0x0034
+#define ixPB0_PIF_PDNB_OVERRIDE_13 0x0035
+#define ixPB0_PIF_PDNB_OVERRIDE_14 0x0036
+#define ixPB0_PIF_PDNB_OVERRIDE_15 0x0037
+#define ixPB0_PIF_PDNB_OVERRIDE_2 0x0022
+#define ixPB0_PIF_PDNB_OVERRIDE_3 0x0023
+#define ixPB0_PIF_PDNB_OVERRIDE_4 0x0024
+#define ixPB0_PIF_PDNB_OVERRIDE_5 0x0025
+#define ixPB0_PIF_PDNB_OVERRIDE_6 0x0026
+#define ixPB0_PIF_PDNB_OVERRIDE_7 0x0027
+#define ixPB0_PIF_PDNB_OVERRIDE_8 0x0030
+#define ixPB0_PIF_PDNB_OVERRIDE_9 0x0031
+#define ixPB0_PIF_PWRDOWN_0 0x0012
+#define ixPB0_PIF_PWRDOWN_1 0x0013
+#define ixPB0_PIF_PWRDOWN_2 0x0017
+#define ixPB0_PIF_PWRDOWN_3 0x0018
+#define ixPB0_PIF_SC_CTL 0x0016
+#define ixPB0_PIF_SCRATCH 0x0001
+#define ixPB0_PIF_SEQ_STATUS_0 0x0028
+#define ixPB0_PIF_SEQ_STATUS_10 0x003A
+#define ixPB0_PIF_SEQ_STATUS_1 0x0029
+#define ixPB0_PIF_SEQ_STATUS_11 0x003B
+#define ixPB0_PIF_SEQ_STATUS_12 0x003C
+#define ixPB0_PIF_SEQ_STATUS_13 0x003D
+#define ixPB0_PIF_SEQ_STATUS_14 0x003E
+#define ixPB0_PIF_SEQ_STATUS_15 0x003F
+#define ixPB0_PIF_SEQ_STATUS_2 0x002A
+#define ixPB0_PIF_SEQ_STATUS_3 0x002B
+#define ixPB0_PIF_SEQ_STATUS_4 0x002C
+#define ixPB0_PIF_SEQ_STATUS_5 0x002D
+#define ixPB0_PIF_SEQ_STATUS_6 0x002E
+#define ixPB0_PIF_SEQ_STATUS_7 0x002F
+#define ixPB0_PIF_SEQ_STATUS_8 0x0038
+#define ixPB0_PIF_SEQ_STATUS_9 0x0039
+#define ixPB0_PIF_TXPHYSTATUS 0x0015
+#define ixPB0_PLL_LC0_CTRL_REG0 0x14480
+#define ixPB0_PLL_LC0_OVRD_REG0 0x14490
+#define ixPB0_PLL_LC0_OVRD_REG1 0x14494
+#define ixPB0_PLL_LC0_SCI_STAT_OVRD_REG0 0x14500
+#define ixPB0_PLL_LC1_SCI_STAT_OVRD_REG0 0x14504
+#define ixPB0_PLL_LC2_SCI_STAT_OVRD_REG0 0x14508
+#define ixPB0_PLL_LC3_SCI_STAT_OVRD_REG0 0x1450C
+#define ixPB0_PLL_RO0_CTRL_REG0 0x14440
+#define ixPB0_PLL_RO0_OVRD_REG0 0x14450
+#define ixPB0_PLL_RO0_OVRD_REG1 0x14454
+#define ixPB0_PLL_RO0_SCI_STAT_OVRD_REG0 0x14460
+#define ixPB0_PLL_RO1_SCI_STAT_OVRD_REG0 0x14464
+#define ixPB0_PLL_RO2_SCI_STAT_OVRD_REG0 0x14468
+#define ixPB0_PLL_RO3_SCI_STAT_OVRD_REG0 0x1446C
+#define ixPB0_PLL_RO_GLB_CTRL_REG0 0x14000
+#define ixPB0_PLL_RO_GLB_OVRD_REG0 0x14010
+#define ixPB0_RX_GLB_CTRL_REG0 0x16000
+#define ixPB0_RX_GLB_CTRL_REG1 0x16004
+#define ixPB0_RX_GLB_CTRL_REG2 0x16008
+#define ixPB0_RX_GLB_CTRL_REG3 0x1600C
+#define ixPB0_RX_GLB_CTRL_REG4 0x16010
+#define ixPB0_RX_GLB_CTRL_REG5 0x16014
+#define ixPB0_RX_GLB_CTRL_REG6 0x16018
+#define ixPB0_RX_GLB_CTRL_REG7 0x1601C
+#define ixPB0_RX_GLB_CTRL_REG8 0x16020
+#define ixPB0_RX_GLB_OVRD_REG0 0x16030
+#define ixPB0_RX_GLB_OVRD_REG1 0x16034
+#define ixPB0_RX_GLB_SCI_STAT_OVRD_REG0 0x16028
+#define ixPB0_RX_LANE0_CTRL_REG0 0x16440
+#define ixPB0_RX_LANE0_SCI_STAT_OVRD_REG0 0x16448
+#define ixPB0_RX_LANE10_CTRL_REG0 0x17500
+#define ixPB0_RX_LANE10_SCI_STAT_OVRD_REG0 0x17508
+#define ixPB0_RX_LANE11_CTRL_REG0 0x17600
+#define ixPB0_RX_LANE11_SCI_STAT_OVRD_REG0 0x17608
+#define ixPB0_RX_LANE12_CTRL_REG0 0x17840
+#define ixPB0_RX_LANE12_SCI_STAT_OVRD_REG0 0x17848
+#define ixPB0_RX_LANE13_CTRL_REG0 0x17880
+#define ixPB0_RX_LANE13_SCI_STAT_OVRD_REG0 0x17888
+#define ixPB0_RX_LANE14_CTRL_REG0 0x17900
+#define ixPB0_RX_LANE14_SCI_STAT_OVRD_REG0 0x17908
+#define ixPB0_RX_LANE15_CTRL_REG0 0x17A00
+#define ixPB0_RX_LANE15_SCI_STAT_OVRD_REG0 0x17A08
+#define ixPB0_RX_LANE1_CTRL_REG0 0x16480
+#define ixPB0_RX_LANE1_SCI_STAT_OVRD_REG0 0x16488
+#define ixPB0_RX_LANE2_CTRL_REG0 0x16500
+#define ixPB0_RX_LANE2_SCI_STAT_OVRD_REG0 0x16508
+#define ixPB0_RX_LANE3_CTRL_REG0 0x16600
+#define ixPB0_RX_LANE3_SCI_STAT_OVRD_REG0 0x16608
+#define ixPB0_RX_LANE4_CTRL_REG0 0x16800
+#define ixPB0_RX_LANE4_SCI_STAT_OVRD_REG0 0x16848
+#define ixPB0_RX_LANE5_CTRL_REG0 0x16880
+#define ixPB0_RX_LANE5_SCI_STAT_OVRD_REG0 0x16888
+#define ixPB0_RX_LANE6_CTRL_REG0 0x16900
+#define ixPB0_RX_LANE6_SCI_STAT_OVRD_REG0 0x16908
+#define ixPB0_RX_LANE7_CTRL_REG0 0x16A00
+#define ixPB0_RX_LANE7_SCI_STAT_OVRD_REG0 0x16A08
+#define ixPB0_RX_LANE8_CTRL_REG0 0x17440
+#define ixPB0_RX_LANE8_SCI_STAT_OVRD_REG0 0x17448
+#define ixPB0_RX_LANE9_CTRL_REG0 0x17480
+#define ixPB0_RX_LANE9_SCI_STAT_OVRD_REG0 0x17488
+#define ixPB0_STRAP_GLB_REG0 0x12020
+#define ixPB0_STRAP_PLL_REG0 0x12030
+#define ixPB0_STRAP_RX_REG0 0x12028
+#define ixPB0_STRAP_RX_REG1 0x1202C
+#define ixPB0_STRAP_TX_REG0 0x12024
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0 0x18014
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1 0x18018
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2 0x1801C
+#define ixPB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3 0x18020
+#define ixPB0_TX_GLB_CTRL_REG0 0x18000
+#define ixPB0_TX_GLB_LANE_SKEW_CTRL 0x18004
+#define ixPB0_TX_GLB_OVRD_REG0 0x18030
+#define ixPB0_TX_GLB_OVRD_REG1 0x18034
+#define ixPB0_TX_GLB_OVRD_REG2 0x18038
+#define ixPB0_TX_GLB_OVRD_REG3 0x1803C
+#define ixPB0_TX_GLB_OVRD_REG4 0x18040
+#define ixPB0_TX_GLB_SCI_STAT_OVRD_REG0 0x18010
+#define ixPB0_TX_LANE0_CTRL_REG0 0x18440
+#define ixPB0_TX_LANE0_OVRD_REG0 0x18444
+#define ixPB0_TX_LANE0_SCI_STAT_OVRD_REG0 0x18448
+#define ixPB0_TX_LANE10_CTRL_REG0 0x19500
+#define ixPB0_TX_LANE10_OVRD_REG0 0x19504
+#define ixPB0_TX_LANE10_SCI_STAT_OVRD_REG0 0x19508
+#define ixPB0_TX_LANE11_CTRL_REG0 0x19600
+#define ixPB0_TX_LANE11_OVRD_REG0 0x19604
+#define ixPB0_TX_LANE11_SCI_STAT_OVRD_REG0 0x19608
+#define ixPB0_TX_LANE12_CTRL_REG0 0x19840
+#define ixPB0_TX_LANE12_OVRD_REG0 0x19844
+#define ixPB0_TX_LANE12_SCI_STAT_OVRD_REG0 0x19848
+#define ixPB0_TX_LANE13_CTRL_REG0 0x19880
+#define ixPB0_TX_LANE13_OVRD_REG0 0x19884
+#define ixPB0_TX_LANE13_SCI_STAT_OVRD_REG0 0x19888
+#define ixPB0_TX_LANE14_CTRL_REG0 0x19900
+#define ixPB0_TX_LANE14_OVRD_REG0 0x19904
+#define ixPB0_TX_LANE14_SCI_STAT_OVRD_REG0 0x19908
+#define ixPB0_TX_LANE15_CTRL_REG0 0x19A00
+#define ixPB0_TX_LANE15_OVRD_REG0 0x19A04
+#define ixPB0_TX_LANE15_SCI_STAT_OVRD_REG0 0x19A08
+#define ixPB0_TX_LANE1_CTRL_REG0 0x18480
+#define ixPB0_TX_LANE1_OVRD_REG0 0x18484
+#define ixPB0_TX_LANE1_SCI_STAT_OVRD_REG0 0x18488
+#define ixPB0_TX_LANE2_CTRL_REG0 0x18500
+#define ixPB0_TX_LANE2_OVRD_REG0 0x18504
+#define ixPB0_TX_LANE2_SCI_STAT_OVRD_REG0 0x18508
+#define ixPB0_TX_LANE3_CTRL_REG0 0x18600
+#define ixPB0_TX_LANE3_OVRD_REG0 0x18604
+#define ixPB0_TX_LANE3_SCI_STAT_OVRD_REG0 0x18608
+#define ixPB0_TX_LANE4_CTRL_REG0 0x18840
+#define ixPB0_TX_LANE4_OVRD_REG0 0x18844
+#define ixPB0_TX_LANE4_SCI_STAT_OVRD_REG0 0x18848
+#define ixPB0_TX_LANE5_CTRL_REG0 0x18880
+#define ixPB0_TX_LANE5_OVRD_REG0 0x18884
+#define ixPB0_TX_LANE5_SCI_STAT_OVRD_REG0 0x18888
+#define ixPB0_TX_LANE6_CTRL_REG0 0x18900
+#define ixPB0_TX_LANE6_OVRD_REG0 0x18904
+#define ixPB0_TX_LANE6_SCI_STAT_OVRD_REG0 0x18908
+#define ixPB0_TX_LANE7_CTRL_REG0 0x18A00
+#define ixPB0_TX_LANE7_OVRD_REG0 0x18A04
+#define ixPB0_TX_LANE7_SCI_STAT_OVRD_REG0 0x18A08
+#define ixPB0_TX_LANE8_CTRL_REG0 0x19440
+#define ixPB0_TX_LANE8_OVRD_REG0 0x19444
+#define ixPB0_TX_LANE8_SCI_STAT_OVRD_REG0 0x19448
+#define ixPB0_TX_LANE9_CTRL_REG0 0x19480
+#define ixPB0_TX_LANE9_OVRD_REG0 0x19484
+#define ixPB0_TX_LANE9_SCI_STAT_OVRD_REG0 0x19488
+#define ixPB1_DFT_DEBUG_CTRL_REG0 0x1300C
+#define ixPB1_DFT_JIT_INJ_REG0 0x13000
+#define ixPB1_DFT_JIT_INJ_REG1 0x13004
+#define ixPB1_DFT_JIT_INJ_REG2 0x13008
+#define ixPB1_GLB_CTRL_REG0 0x10004
+#define ixPB1_GLB_CTRL_REG1 0x10008
+#define ixPB1_GLB_CTRL_REG2 0x1000C
+#define ixPB1_GLB_CTRL_REG3 0x10010
+#define ixPB1_GLB_CTRL_REG4 0x10014
+#define ixPB1_GLB_CTRL_REG5 0x10018
+#define ixPB1_GLB_OVRD_REG0 0x10030
+#define ixPB1_GLB_OVRD_REG1 0x10034
+#define ixPB1_GLB_OVRD_REG2 0x10038
+#define ixPB1_GLB_SCI_STAT_OVRD_REG0 0x1001C
+#define ixPB1_GLB_SCI_STAT_OVRD_REG1 0x10020
+#define ixPB1_GLB_SCI_STAT_OVRD_REG2 0x10024
+#define ixPB1_GLB_SCI_STAT_OVRD_REG3 0x10028
+#define ixPB1_GLB_SCI_STAT_OVRD_REG4 0x1002C
+#define ixPB1_HW_DEBUG 0x12004
+#define ixPB1_PIF_CNTL 0x0010
+#define ixPB1_PIF_CNTL2 0x0014
+#define ixPB1_PIF_HW_DEBUG 0x0002
+#define ixPB1_PIF_PAIRING 0x0011
+#define ixPB1_PIF_PDNB_OVERRIDE_0 0x0020
+#define ixPB1_PIF_PDNB_OVERRIDE_10 0x0032
+#define ixPB1_PIF_PDNB_OVERRIDE_1 0x0021
+#define ixPB1_PIF_PDNB_OVERRIDE_11 0x0033
+#define ixPB1_PIF_PDNB_OVERRIDE_12 0x0034
+#define ixPB1_PIF_PDNB_OVERRIDE_13 0x0035
+#define ixPB1_PIF_PDNB_OVERRIDE_14 0x0036
+#define ixPB1_PIF_PDNB_OVERRIDE_15 0x0037
+#define ixPB1_PIF_PDNB_OVERRIDE_2 0x0022
+#define ixPB1_PIF_PDNB_OVERRIDE_3 0x0023
+#define ixPB1_PIF_PDNB_OVERRIDE_4 0x0024
+#define ixPB1_PIF_PDNB_OVERRIDE_5 0x0025
+#define ixPB1_PIF_PDNB_OVERRIDE_6 0x0026
+#define ixPB1_PIF_PDNB_OVERRIDE_7 0x0027
+#define ixPB1_PIF_PDNB_OVERRIDE_8 0x0030
+#define ixPB1_PIF_PDNB_OVERRIDE_9 0x0031
+#define ixPB1_PIF_PWRDOWN_0 0x0012
+#define ixPB1_PIF_PWRDOWN_1 0x0013
+#define ixPB1_PIF_PWRDOWN_2 0x0017
+#define ixPB1_PIF_PWRDOWN_3 0x0018
+#define ixPB1_PIF_SC_CTL 0x0016
+#define ixPB1_PIF_SCRATCH 0x0001
+#define ixPB1_PIF_SEQ_STATUS_0 0x0028
+#define ixPB1_PIF_SEQ_STATUS_10 0x003A
+#define ixPB1_PIF_SEQ_STATUS_1 0x0029
+#define ixPB1_PIF_SEQ_STATUS_11 0x003B
+#define ixPB1_PIF_SEQ_STATUS_12 0x003C
+#define ixPB1_PIF_SEQ_STATUS_13 0x003D
+#define ixPB1_PIF_SEQ_STATUS_14 0x003E
+#define ixPB1_PIF_SEQ_STATUS_15 0x003F
+#define ixPB1_PIF_SEQ_STATUS_2 0x002A
+#define ixPB1_PIF_SEQ_STATUS_3 0x002B
+#define ixPB1_PIF_SEQ_STATUS_4 0x002C
+#define ixPB1_PIF_SEQ_STATUS_5 0x002D
+#define ixPB1_PIF_SEQ_STATUS_6 0x002E
+#define ixPB1_PIF_SEQ_STATUS_7 0x002F
+#define ixPB1_PIF_SEQ_STATUS_8 0x0038
+#define ixPB1_PIF_SEQ_STATUS_9 0x0039
+#define ixPB1_PIF_TXPHYSTATUS 0x0015
+#define ixPB1_PLL_LC0_CTRL_REG0 0x14480
+#define ixPB1_PLL_LC0_OVRD_REG0 0x14490
+#define ixPB1_PLL_LC0_OVRD_REG1 0x14494
+#define ixPB1_PLL_LC0_SCI_STAT_OVRD_REG0 0x14500
+#define ixPB1_PLL_LC1_SCI_STAT_OVRD_REG0 0x14504
+#define ixPB1_PLL_LC2_SCI_STAT_OVRD_REG0 0x14508
+#define ixPB1_PLL_LC3_SCI_STAT_OVRD_REG0 0x1450C
+#define ixPB1_PLL_RO0_CTRL_REG0 0x14440
+#define ixPB1_PLL_RO0_OVRD_REG0 0x14450
+#define ixPB1_PLL_RO0_OVRD_REG1 0x14454
+#define ixPB1_PLL_RO0_SCI_STAT_OVRD_REG0 0x14460
+#define ixPB1_PLL_RO1_SCI_STAT_OVRD_REG0 0x14464
+#define ixPB1_PLL_RO2_SCI_STAT_OVRD_REG0 0x14468
+#define ixPB1_PLL_RO3_SCI_STAT_OVRD_REG0 0x1446C
+#define ixPB1_PLL_RO_GLB_CTRL_REG0 0x14000
+#define ixPB1_PLL_RO_GLB_OVRD_REG0 0x14010
+#define ixPB1_RX_GLB_CTRL_REG0 0x16000
+#define ixPB1_RX_GLB_CTRL_REG1 0x16004
+#define ixPB1_RX_GLB_CTRL_REG2 0x16008
+#define ixPB1_RX_GLB_CTRL_REG3 0x1600C
+#define ixPB1_RX_GLB_CTRL_REG4 0x16010
+#define ixPB1_RX_GLB_CTRL_REG5 0x16014
+#define ixPB1_RX_GLB_CTRL_REG6 0x16018
+#define ixPB1_RX_GLB_CTRL_REG7 0x1601C
+#define ixPB1_RX_GLB_CTRL_REG8 0x16020
+#define ixPB1_RX_GLB_OVRD_REG0 0x16030
+#define ixPB1_RX_GLB_OVRD_REG1 0x16034
+#define ixPB1_RX_GLB_SCI_STAT_OVRD_REG0 0x16028
+#define ixPB1_RX_LANE0_CTRL_REG0 0x16440
+#define ixPB1_RX_LANE0_SCI_STAT_OVRD_REG0 0x16448
+#define ixPB1_RX_LANE10_CTRL_REG0 0x17500
+#define ixPB1_RX_LANE10_SCI_STAT_OVRD_REG0 0x17508
+#define ixPB1_RX_LANE11_CTRL_REG0 0x17600
+#define ixPB1_RX_LANE11_SCI_STAT_OVRD_REG0 0x17608
+#define ixPB1_RX_LANE12_CTRL_REG0 0x17840
+#define ixPB1_RX_LANE12_SCI_STAT_OVRD_REG0 0x17848
+#define ixPB1_RX_LANE13_CTRL_REG0 0x17880
+#define ixPB1_RX_LANE13_SCI_STAT_OVRD_REG0 0x17888
+#define ixPB1_RX_LANE14_CTRL_REG0 0x17900
+#define ixPB1_RX_LANE14_SCI_STAT_OVRD_REG0 0x17908
+#define ixPB1_RX_LANE15_CTRL_REG0 0x17A00
+#define ixPB1_RX_LANE15_SCI_STAT_OVRD_REG0 0x17A08
+#define ixPB1_RX_LANE1_CTRL_REG0 0x16480
+#define ixPB1_RX_LANE1_SCI_STAT_OVRD_REG0 0x16488
+#define ixPB1_RX_LANE2_CTRL_REG0 0x16500
+#define ixPB1_RX_LANE2_SCI_STAT_OVRD_REG0 0x16508
+#define ixPB1_RX_LANE3_CTRL_REG0 0x16600
+#define ixPB1_RX_LANE3_SCI_STAT_OVRD_REG0 0x16608
+#define ixPB1_RX_LANE4_CTRL_REG0 0x16800
+#define ixPB1_RX_LANE4_SCI_STAT_OVRD_REG0 0x16848
+#define ixPB1_RX_LANE5_CTRL_REG0 0x16880
+#define ixPB1_RX_LANE5_SCI_STAT_OVRD_REG0 0x16888
+#define ixPB1_RX_LANE6_CTRL_REG0 0x16900
+#define ixPB1_RX_LANE6_SCI_STAT_OVRD_REG0 0x16908
+#define ixPB1_RX_LANE7_CTRL_REG0 0x16A00
+#define ixPB1_RX_LANE7_SCI_STAT_OVRD_REG0 0x16A08
+#define ixPB1_RX_LANE8_CTRL_REG0 0x17440
+#define ixPB1_RX_LANE8_SCI_STAT_OVRD_REG0 0x17448
+#define ixPB1_RX_LANE9_CTRL_REG0 0x17480
+#define ixPB1_RX_LANE9_SCI_STAT_OVRD_REG0 0x17488
+#define ixPB1_STRAP_GLB_REG0 0x12020
+#define ixPB1_STRAP_PLL_REG0 0x12030
+#define ixPB1_STRAP_RX_REG0 0x12028
+#define ixPB1_STRAP_RX_REG1 0x1202C
+#define ixPB1_STRAP_TX_REG0 0x12024
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0 0x18014
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1 0x18018
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2 0x1801C
+#define ixPB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3 0x18020
+#define ixPB1_TX_GLB_CTRL_REG0 0x18000
+#define ixPB1_TX_GLB_LANE_SKEW_CTRL 0x18004
+#define ixPB1_TX_GLB_OVRD_REG0 0x18030
+#define ixPB1_TX_GLB_OVRD_REG1 0x18034
+#define ixPB1_TX_GLB_OVRD_REG2 0x18038
+#define ixPB1_TX_GLB_OVRD_REG3 0x1803C
+#define ixPB1_TX_GLB_OVRD_REG4 0x18040
+#define ixPB1_TX_GLB_SCI_STAT_OVRD_REG0 0x18010
+#define ixPB1_TX_LANE0_CTRL_REG0 0x18440
+#define ixPB1_TX_LANE0_OVRD_REG0 0x18444
+#define ixPB1_TX_LANE0_SCI_STAT_OVRD_REG0 0x18448
+#define ixPB1_TX_LANE10_CTRL_REG0 0x19500
+#define ixPB1_TX_LANE10_OVRD_REG0 0x19504
+#define ixPB1_TX_LANE10_SCI_STAT_OVRD_REG0 0x19508
+#define ixPB1_TX_LANE11_CTRL_REG0 0x19600
+#define ixPB1_TX_LANE11_OVRD_REG0 0x19604
+#define ixPB1_TX_LANE11_SCI_STAT_OVRD_REG0 0x19608
+#define ixPB1_TX_LANE12_CTRL_REG0 0x19840
+#define ixPB1_TX_LANE12_OVRD_REG0 0x19844
+#define ixPB1_TX_LANE12_SCI_STAT_OVRD_REG0 0x19848
+#define ixPB1_TX_LANE13_CTRL_REG0 0x19880
+#define ixPB1_TX_LANE13_OVRD_REG0 0x19884
+#define ixPB1_TX_LANE13_SCI_STAT_OVRD_REG0 0x19888
+#define ixPB1_TX_LANE14_CTRL_REG0 0x19900
+#define ixPB1_TX_LANE14_OVRD_REG0 0x19904
+#define ixPB1_TX_LANE14_SCI_STAT_OVRD_REG0 0x19908
+#define ixPB1_TX_LANE15_CTRL_REG0 0x19A00
+#define ixPB1_TX_LANE15_OVRD_REG0 0x19A04
+#define ixPB1_TX_LANE15_SCI_STAT_OVRD_REG0 0x19A08
+#define ixPB1_TX_LANE1_CTRL_REG0 0x18480
+#define ixPB1_TX_LANE1_OVRD_REG0 0x18484
+#define ixPB1_TX_LANE1_SCI_STAT_OVRD_REG0 0x18488
+#define ixPB1_TX_LANE2_CTRL_REG0 0x18500
+#define ixPB1_TX_LANE2_OVRD_REG0 0x18504
+#define ixPB1_TX_LANE2_SCI_STAT_OVRD_REG0 0x18508
+#define ixPB1_TX_LANE3_CTRL_REG0 0x18600
+#define ixPB1_TX_LANE3_OVRD_REG0 0x18604
+#define ixPB1_TX_LANE3_SCI_STAT_OVRD_REG0 0x18608
+#define ixPB1_TX_LANE4_CTRL_REG0 0x18840
+#define ixPB1_TX_LANE4_OVRD_REG0 0x18844
+#define ixPB1_TX_LANE4_SCI_STAT_OVRD_REG0 0x18848
+#define ixPB1_TX_LANE5_CTRL_REG0 0x18880
+#define ixPB1_TX_LANE5_OVRD_REG0 0x18884
+#define ixPB1_TX_LANE5_SCI_STAT_OVRD_REG0 0x18888
+#define ixPB1_TX_LANE6_CTRL_REG0 0x18900
+#define ixPB1_TX_LANE6_OVRD_REG0 0x18904
+#define ixPB1_TX_LANE6_SCI_STAT_OVRD_REG0 0x18908
+#define ixPB1_TX_LANE7_CTRL_REG0 0x18A00
+#define ixPB1_TX_LANE7_OVRD_REG0 0x18A04
+#define ixPB1_TX_LANE7_SCI_STAT_OVRD_REG0 0x18A08
+#define ixPB1_TX_LANE8_CTRL_REG0 0x19440
+#define ixPB1_TX_LANE8_OVRD_REG0 0x19444
+#define ixPB1_TX_LANE8_SCI_STAT_OVRD_REG0 0x19448
+#define ixPB1_TX_LANE9_CTRL_REG0 0x19480
+#define ixPB1_TX_LANE9_OVRD_REG0 0x19484
+#define ixPB1_TX_LANE9_SCI_STAT_OVRD_REG0 0x19488
+#define ixPCIE_BUS_CNTL 0x0021
+#define ixPCIE_CFG_CNTL 0x003C
+#define ixPCIE_CI_CNTL 0x0020
+#define ixPCIE_CNTL 0x0010
+#define ixPCIE_CNTL2 0x001C
+#define ixPCIE_CONFIG_CNTL 0x0011
+#define ixPCIE_DEBUG_CNTL 0x0012
+#define ixPCIE_ERR_CNTL 0x006A
+#define ixPCIE_F0_DPA_CAP 0x00E0
+#define ixPCIE_F0_DPA_CNTL 0x00E5
+#define ixPCIE_F0_DPA_LATENCY_INDICATOR 0x00E4
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_0 0x00E7
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_1 0x00E8
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_2 0x00E9
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_3 0x00EA
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_4 0x00EB
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_5 0x00EC
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_6 0x00ED
+#define ixPCIE_F0_DPA_SUBSTATE_PWR_ALLOC_7 0x00EE
+#define ixPCIE_FC_CPL 0x0062
+#define ixPCIE_FC_NP 0x0061
+#define ixPCIE_FC_P 0x0060
+#define ixPCIE_HW_DEBUG 0x0002
+#define ixPCIE_I2C_REG_ADDR_EXPAND 0x003A
+#define ixPCIE_I2C_REG_DATA 0x003B
+#define ixPCIE_INT_CNTL 0x001A
+#define ixPCIE_INT_STATUS 0x001B
+#define ixPCIE_LC_BEST_EQ_SETTINGS 0x00B9
+#define ixPCIE_LC_BW_CHANGE_CNTL 0x00B2
+#define ixPCIE_LC_CDR_CNTL 0x00B3
+#define ixPCIE_LC_CNTL 0x00A0
+#define ixPCIE_LC_CNTL2 0x00B1
+#define ixPCIE_LC_CNTL3 0x00B5
+#define ixPCIE_LC_CNTL4 0x00B6
+#define ixPCIE_LC_CNTL5 0x00B7
+#define ixPCIE_LC_FORCE_COEFF 0x00B8
+#define ixPCIE_LC_FORCE_EQ_REQ_COEFF 0x00BA
+#define ixPCIE_LC_LANE_CNTL 0x00B4
+#define ixPCIE_LC_LINK_WIDTH_CNTL 0x00A2
+#define ixPCIE_LC_N_FTS_CNTL 0x00A3
+#define ixPCIE_LC_SPEED_CNTL 0x00A4
+#define ixPCIE_LC_STATE0 0x00A5
+#define ixPCIE_LC_STATE10 0x0026
+#define ixPCIE_LC_STATE1 0x00A6
+#define ixPCIE_LC_STATE11 0x0027
+#define ixPCIE_LC_STATE2 0x00A7
+#define ixPCIE_LC_STATE3 0x00A8
+#define ixPCIE_LC_STATE4 0x00A9
+#define ixPCIE_LC_STATE5 0x00AA
+#define ixPCIE_LC_STATE6 0x0022
+#define ixPCIE_LC_STATE7 0x0023
+#define ixPCIE_LC_STATE8 0x0024
+#define ixPCIE_LC_STATE9 0x0025
+#define ixPCIE_LC_STATUS1 0x0028
+#define ixPCIE_LC_STATUS2 0x0029
+#define ixPCIE_LC_TRAINING_CNTL 0x00A1
+#define ixPCIE_P_BUF_STATUS 0x0041
+#define ixPCIE_P_CNTL 0x0040
+#define ixPCIE_P_DECODER_STATUS 0x0042
+#define ixPCIE_PERF_CNTL_EVENT0_PORT_SEL 0x0093
+#define ixPCIE_PERF_CNTL_EVENT1_PORT_SEL 0x0094
+#define ixPCIE_PERF_CNTL_MST_C_CLK 0x0087
+#define ixPCIE_PERF_CNTL_MST_R_CLK 0x0084
+#define ixPCIE_PERF_CNTL_SLV_NS_C_CLK 0x0090
+#define ixPCIE_PERF_CNTL_SLV_R_CLK 0x008A
+#define ixPCIE_PERF_CNTL_SLV_S_C_CLK 0x008D
+#define ixPCIE_PERF_CNTL_TXCLK 0x0081
+#define ixPCIE_PERF_CNTL_TXCLK2 0x0095
+#define ixPCIE_PERF_COUNT0_MST_C_CLK 0x0088
+#define ixPCIE_PERF_COUNT0_MST_R_CLK 0x0085
+#define ixPCIE_PERF_COUNT0_SLV_NS_C_CLK 0x0091
+#define ixPCIE_PERF_COUNT0_SLV_R_CLK 0x008B
+#define ixPCIE_PERF_COUNT0_SLV_S_C_CLK 0x008E
+#define ixPCIE_PERF_COUNT0_TXCLK 0x0082
+#define ixPCIE_PERF_COUNT0_TXCLK2 0x0096
+#define ixPCIE_PERF_COUNT1_MST_C_CLK 0x0089
+#define ixPCIE_PERF_COUNT1_MST_R_CLK 0x0086
+#define ixPCIE_PERF_COUNT1_SLV_NS_C_CLK 0x0092
+#define ixPCIE_PERF_COUNT1_SLV_R_CLK 0x008C
+#define ixPCIE_PERF_COUNT1_SLV_S_C_CLK 0x008F
+#define ixPCIE_PERF_COUNT1_TXCLK 0x0083
+#define ixPCIE_PERF_COUNT1_TXCLK2 0x0097
+#define ixPCIE_PERF_COUNT_CNTL 0x0080
+#define ixPCIEP_HW_DEBUG 0x0002
+#define ixPCIE_P_MISC_STATUS 0x0043
+#define ixPCIEP_PORT_CNTL 0x0010
+#define ixPCIE_P_PORT_LANE_STATUS 0x0050
+#define ixPCIE_PRBS_CLR 0x00C8
+#define ixPCIE_PRBS_ERRCNT_0 0x00D0
+#define ixPCIE_PRBS_ERRCNT_10 0x00DA
+#define ixPCIE_PRBS_ERRCNT_1 0x00D1
+#define ixPCIE_PRBS_ERRCNT_11 0x00DB
+#define ixPCIE_PRBS_ERRCNT_12 0x00DC
+#define ixPCIE_PRBS_ERRCNT_13 0x00DD
+#define ixPCIE_PRBS_ERRCNT_14 0x00DE
+#define ixPCIE_PRBS_ERRCNT_15 0x00DF
+#define ixPCIE_PRBS_ERRCNT_2 0x00D2
+#define ixPCIE_PRBS_ERRCNT_3 0x00D3
+#define ixPCIE_PRBS_ERRCNT_4 0x00D4
+#define ixPCIE_PRBS_ERRCNT_5 0x00D5
+#define ixPCIE_PRBS_ERRCNT_6 0x00D6
+#define ixPCIE_PRBS_ERRCNT_7 0x00D7
+#define ixPCIE_PRBS_ERRCNT_8 0x00D8
+#define ixPCIE_PRBS_ERRCNT_9 0x00D9
+#define ixPCIE_PRBS_FREERUN 0x00CB
+#define ixPCIE_PRBS_HI_BITCNT 0x00CF
+#define ixPCIE_PRBS_LO_BITCNT 0x00CE
+#define ixPCIE_PRBS_MISC 0x00CC
+#define ixPCIE_PRBS_STATUS1 0x00C9
+#define ixPCIE_PRBS_STATUS2 0x00CA
+#define ixPCIE_PRBS_USER_PATTERN 0x00CD
+#define ixPCIE_P_RCV_L0S_FTS_DET 0x0050
+#define ixPCIEP_RESERVED 0x0000
+#define ixPCIEP_SCRATCH 0x0001
+#define ixPCIEP_STRAP_LC 0x00C0
+#define ixPCIEP_STRAP_MISC 0x00C1
+#define ixPCIE_RESERVED 0x0000
+#define ixPCIE_RX_CNTL 0x0070
+#define ixPCIE_RX_CNTL2 0x001D
+#define ixPCIE_RX_CNTL3 0x0074
+#define ixPCIE_RX_CREDITS_ALLOCATED_CPL 0x0082
+#define ixPCIE_RX_CREDITS_ALLOCATED_NP 0x0081
+#define ixPCIE_RX_CREDITS_ALLOCATED_P 0x0080
+#define ixPCIE_RX_EXPECTED_SEQNUM 0x0071
+#define ixPCIE_RX_LAST_TLP0 0x0031
+#define ixPCIE_RX_LAST_TLP1 0x0032
+#define ixPCIE_RX_LAST_TLP2 0x0033
+#define ixPCIE_RX_LAST_TLP3 0x0034
+#define ixPCIE_RX_NUM_NAK 0x000E
+#define ixPCIE_RX_NUM_NAK_GENERATED 0x000F
+#define ixPCIE_RX_VENDOR_SPECIFIC 0x0072
+#define ixPCIE_SCRATCH 0x0001
+#define ixPCIE_STRAP_F0 0x00B0
+#define ixPCIE_STRAP_F1 0x00B1
+#define ixPCIE_STRAP_F2 0x00B2
+#define ixPCIE_STRAP_F3 0x00B3
+#define ixPCIE_STRAP_F4 0x00B4
+#define ixPCIE_STRAP_F5 0x00B5
+#define ixPCIE_STRAP_F6 0x00B6
+#define ixPCIE_STRAP_F7 0x00B7
+#define ixPCIE_STRAP_I2C_BD 0x00C4
+#define ixPCIE_STRAP_MISC 0x00C0
+#define ixPCIE_STRAP_MISC2 0x00C1
+#define ixPCIE_STRAP_PI 0x00C2
+#define ixPCIE_TX_ACK_LATENCY_LIMIT 0x0026
+#define ixPCIE_TX_CNTL 0x0020
+#define ixPCIE_TX_CREDITS_ADVT_CPL 0x0032
+#define ixPCIE_TX_CREDITS_ADVT_NP 0x0031
+#define ixPCIE_TX_CREDITS_ADVT_P 0x0030
+#define ixPCIE_TX_CREDITS_FCU_THRESHOLD 0x0037
+#define ixPCIE_TX_CREDITS_INIT_CPL 0x0035
+#define ixPCIE_TX_CREDITS_INIT_NP 0x0034
+#define ixPCIE_TX_CREDITS_INIT_P 0x0033
+#define ixPCIE_TX_CREDITS_STATUS 0x0036
+#define ixPCIE_TX_LAST_TLP0 0x0035
+#define ixPCIE_TX_LAST_TLP1 0x0036
+#define ixPCIE_TX_LAST_TLP2 0x0037
+#define ixPCIE_TX_LAST_TLP3 0x0038
+#define ixPCIE_TX_REPLAY 0x0025
+#define ixPCIE_TX_REQUESTER_ID 0x0021
+#define ixPCIE_TX_REQUEST_NUM_CNTL 0x0023
+#define ixPCIE_TX_SEQ 0x0024
+#define ixPCIE_TX_VENDOR_SPECIFIC 0x0022
+#define ixPCIE_WPR_CNTL 0x0030
+#define mmBACO_CNTL 0x14E5
+#define mmBF_ANA_ISO_CNTL 0x14C7
+#define mmBIF_BACO_DEBUG 0x14DF
+#define mmBIF_BACO_DEBUG_LATCH 0x14DC
+#define mmBIF_BACO_MSIC 0x14DE
+#define mmBIF_BUSNUM_CNTL1 0x1525
+#define mmBIF_BUSNUM_CNTL2 0x152B
+#define mmBIF_BUSNUM_LIST0 0x1526
+#define mmBIF_BUSNUM_LIST1 0x1527
+#define mmBIF_BUSY_DELAY_CNTR 0x1529
+#define mmBIF_CLK_PDWN_DELAY_TIMER 0x151F
+#define mmBIF_DEBUG_CNTL 0x151C
+#define mmBIF_DEBUG_MUX 0x151D
+#define mmBIF_DEBUG_OUT 0x151E
+#define mmBIF_DEVFUNCNUM_LIST0 0x14E8
+#define mmBIF_DEVFUNCNUM_LIST1 0x14E7
+#define mmBIF_FB_EN 0x1524
+#define mmBIF_FEATURES_CONTROL_MISC 0x14C2
+#define mmBIF_PERFCOUNTER0_RESULT 0x152D
+#define mmBIF_PERFCOUNTER1_RESULT 0x152E
+#define mmBIF_PERFMON_CNTL 0x152C
+#define mmBIF_PIF_TXCLK_SWITCH_TIMER 0x152F
+#define mmBIF_RESET_EN 0x1511
+#define mmBIF_SCRATCH0 0x150E
+#define mmBIF_SCRATCH1 0x150F
+#define mmBIF_SSA_DISP_LOWER 0x14D2
+#define mmBIF_SSA_DISP_UPPER 0x14D3
+#define mmBIF_SSA_GFX0_LOWER 0x14CA
+#define mmBIF_SSA_GFX0_UPPER 0x14CB
+#define mmBIF_SSA_GFX1_LOWER 0x14CC
+#define mmBIF_SSA_GFX1_UPPER 0x14CD
+#define mmBIF_SSA_GFX2_LOWER 0x14CE
+#define mmBIF_SSA_GFX2_UPPER 0x14CF
+#define mmBIF_SSA_GFX3_LOWER 0x14D0
+#define mmBIF_SSA_GFX3_UPPER 0x14D1
+#define mmBIF_SSA_MC_LOWER 0x14D4
+#define mmBIF_SSA_MC_UPPER 0x14D5
+#define mmBIF_SSA_PWR_STATUS 0x14C8
+#define mmBIF_XDMA_HI 0x14C1
+#define mmBIF_XDMA_LO 0x14C0
+#define mmBIOS_SCRATCH_0 0x05C9
+#define mmBIOS_SCRATCH_10 0x05D3
+#define mmBIOS_SCRATCH_1 0x05CA
+#define mmBIOS_SCRATCH_11 0x05D4
+#define mmBIOS_SCRATCH_12 0x05D5
+#define mmBIOS_SCRATCH_13 0x05D6
+#define mmBIOS_SCRATCH_14 0x05D7
+#define mmBIOS_SCRATCH_15 0x05D8
+#define mmBIOS_SCRATCH_2 0x05CB
+#define mmBIOS_SCRATCH_3 0x05CC
+#define mmBIOS_SCRATCH_4 0x05CD
+#define mmBIOS_SCRATCH_5 0x05CE
+#define mmBIOS_SCRATCH_6 0x05CF
+#define mmBIOS_SCRATCH_7 0x05D0
+#define mmBIOS_SCRATCH_8 0x05D1
+#define mmBIOS_SCRATCH_9 0x05D2
+#define mmBUS_CNTL 0x1508
+#define mmCAPTURE_HOST_BUSNUM 0x153C
+#define mmCLKREQB_PAD_CNTL 0x1521
+#define mmCONFIG_APER_SIZE 0x150C
+#define mmCONFIG_CNTL 0x1509
+#define mmCONFIG_F0_BASE 0x150B
+#define mmCONFIG_MEMSIZE 0x150A
+#define mmCONFIG_REG_APER_SIZE 0x150D
+#define mmHDP_MEM_COHERENCY_FLUSH_CNTL 0x1520
+#define mmHDP_REG_COHERENCY_FLUSH_CNTL 0x1528
+#define mmHOST_BUSNUM 0x153D
+#define mmHW_DEBUG 0x1515
+#define mmIMPCTL_RESET 0x14F5
+#define mmINTERRUPT_CNTL 0x151A
+#define mmINTERRUPT_CNTL2 0x151B
+#define mmMASTER_CREDIT_CNTL 0x1516
+#define mmMM_CFGREGS_CNTL 0x1513
+#define mmMM_DATA 0x0001
+#define mmMM_INDEX 0x0000
+#define mmMM_INDEX_HI 0x0006
+#define mmNEW_REFCLKB_TIMER 0x14EA
+#define mmNEW_REFCLKB_TIMER_1 0x14E9
+#define mmPCIE_DATA 0x000D
+#define mmPCIE_INDEX 0x000C
+#define mmPEER0_FB_OFFSET_HI 0x14F3
+#define mmPEER0_FB_OFFSET_LO 0x14F2
+#define mmPEER1_FB_OFFSET_HI 0x14F1
+#define mmPEER1_FB_OFFSET_LO 0x14F0
+#define mmPEER2_FB_OFFSET_HI 0x14EF
+#define mmPEER2_FB_OFFSET_LO 0x14EE
+#define mmPEER3_FB_OFFSET_HI 0x14ED
+#define mmPEER3_FB_OFFSET_LO 0x14EC
+#define mmPEER_REG_RANGE0 0x153E
+#define mmPEER_REG_RANGE1 0x153F
+#define mmSLAVE_HANG_ERROR 0x153B
+#define mmSLAVE_HANG_PROTECTION_CNTL 0x1536
+#define mmSLAVE_REQ_CREDIT_CNTL 0x1517
+#define mmSMBCLK_PAD_CNTL 0x1523
+#define mmSMBDAT_PAD_CNTL 0x1522
+#define mmSMBUS_BACO_DUMMY 0x14C6
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/bif/bif_3_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8127 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 BIF_3_0_SH_MASK_H
+#define BIF_3_0_SH_MASK_H
+
+#define BACO_CNTL__BACO_ANA_ISO_DIS_MASK 0x00000080L
+#define BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT 0x00000007
+#define BACO_CNTL__BACO_BCLK_OFF_MASK 0x00000002L
+#define BACO_CNTL__BACO_BCLK_OFF__SHIFT 0x00000001
+#define BACO_CNTL__BACO_EN_MASK 0x00000001L
+#define BACO_CNTL__BACO_EN__SHIFT 0x00000000
+#define BACO_CNTL__BACO_HANG_PROTECTION_EN_MASK 0x00000020L
+#define BACO_CNTL__BACO_HANG_PROTECTION_EN__SHIFT 0x00000005
+#define BACO_CNTL__BACO_ISO_DIS_MASK 0x00000004L
+#define BACO_CNTL__BACO_ISO_DIS__SHIFT 0x00000002
+#define BACO_CNTL__BACO_MODE_MASK 0x00000040L
+#define BACO_CNTL__BACO_MODE__SHIFT 0x00000006
+#define BACO_CNTL__BACO_POWER_OFF_MASK 0x00000008L
+#define BACO_CNTL__BACO_POWER_OFF__SHIFT 0x00000003
+#define BACO_CNTL__BACO_RESET_EN_MASK 0x00000010L
+#define BACO_CNTL__BACO_RESET_EN__SHIFT 0x00000004
+#define BACO_CNTL__PWRGOOD_BF_MASK 0x00000200L
+#define BACO_CNTL__PWRGOOD_BF__SHIFT 0x00000009
+#define BACO_CNTL__PWRGOOD_DVO_MASK 0x00001000L
+#define BACO_CNTL__PWRGOOD_DVO__SHIFT 0x0000000c
+#define BACO_CNTL__PWRGOOD_GPIO_MASK 0x00000400L
+#define BACO_CNTL__PWRGOOD_GPIO__SHIFT 0x0000000a
+#define BACO_CNTL__PWRGOOD_MEM_MASK 0x00000800L
+#define BACO_CNTL__PWRGOOD_MEM__SHIFT 0x0000000b
+#define BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK 0x00000100L
+#define BACO_CNTL__RCU_BIF_CONFIG_DONE__SHIFT 0x00000008
+#define BF_ANA_ISO_CNTL__BF_ANA_ISO_DIS_MASK_MASK 0x00000001L
+#define BF_ANA_ISO_CNTL__BF_ANA_ISO_DIS_MASK__SHIFT 0x00000000
+#define BF_ANA_ISO_CNTL__BF_VDDC_ISO_DIS_MASK_MASK 0x00000002L
+#define BF_ANA_ISO_CNTL__BF_VDDC_ISO_DIS_MASK__SHIFT 0x00000001
+#define BIF_BACO_DEBUG__BIF_BACO_SCANDUMP_FLG_MASK 0x00000001L
+#define BIF_BACO_DEBUG__BIF_BACO_SCANDUMP_FLG__SHIFT 0x00000000
+#define BIF_BACO_DEBUG_LATCH__BIF_BACO_LATCH_FLG_MASK 0x00000001L
+#define BIF_BACO_DEBUG_LATCH__BIF_BACO_LATCH_FLG__SHIFT 0x00000000
+#define BIF_BACO_MSIC__BIF_XTALIN_SEL_MASK 0x00000001L
+#define BIF_BACO_MSIC__BIF_XTALIN_SEL__SHIFT 0x00000000
+#define BIF_BUSNUM_CNTL1__ID_MASK_MASK 0x000000ffL
+#define BIF_BUSNUM_CNTL1__ID_MASK__SHIFT 0x00000000
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_EN_MASK 0x00000100L
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_EN__SHIFT 0x00000008
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_SEL_MASK 0x000000ffL
+#define BIF_BUSNUM_CNTL2__AUTOUPDATE_SEL__SHIFT 0x00000000
+#define BIF_BUSNUM_CNTL2__ERROR_MULTIPLE_ID_MATCH_MASK 0x00020000L
+#define BIF_BUSNUM_CNTL2__ERROR_MULTIPLE_ID_MATCH__SHIFT 0x00000011
+#define BIF_BUSNUM_CNTL2__HDPREG_CNTL_MASK 0x00010000L
+#define BIF_BUSNUM_CNTL2__HDPREG_CNTL__SHIFT 0x00000010
+#define BIF_BUSNUM_LIST0__ID0_MASK 0x000000ffL
+#define BIF_BUSNUM_LIST0__ID0__SHIFT 0x00000000
+#define BIF_BUSNUM_LIST0__ID1_MASK 0x0000ff00L
+#define BIF_BUSNUM_LIST0__ID1__SHIFT 0x00000008
+#define BIF_BUSNUM_LIST0__ID2_MASK 0x00ff0000L
+#define BIF_BUSNUM_LIST0__ID2__SHIFT 0x00000010
+#define BIF_BUSNUM_LIST0__ID3_MASK 0xff000000L
+#define BIF_BUSNUM_LIST0__ID3__SHIFT 0x00000018
+#define BIF_BUSNUM_LIST1__ID4_MASK 0x000000ffL
+#define BIF_BUSNUM_LIST1__ID4__SHIFT 0x00000000
+#define BIF_BUSNUM_LIST1__ID5_MASK 0x0000ff00L
+#define BIF_BUSNUM_LIST1__ID5__SHIFT 0x00000008
+#define BIF_BUSNUM_LIST1__ID6_MASK 0x00ff0000L
+#define BIF_BUSNUM_LIST1__ID6__SHIFT 0x00000010
+#define BIF_BUSNUM_LIST1__ID7_MASK 0xff000000L
+#define BIF_BUSNUM_LIST1__ID7__SHIFT 0x00000018
+#define BIF_BUSY_DELAY_CNTR__DELAY_CNT_MASK 0x0000003fL
+#define BIF_BUSY_DELAY_CNTR__DELAY_CNT__SHIFT 0x00000000
+#define BIF_CLK_PDWN_DELAY_TIMER__TIMER_MASK 0x000003ffL
+#define BIF_CLK_PDWN_DELAY_TIMER__TIMER__SHIFT 0x00000000
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK1_MASK 0x00000010L
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK1__SHIFT 0x00000004
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK2_MASK 0x00000020L
+#define BIF_DEBUG_CNTL__DEBUG_BYTESEL_BLK2__SHIFT 0x00000005
+#define BIF_DEBUG_CNTL__DEBUG_EN_MASK 0x00000001L
+#define BIF_DEBUG_CNTL__DEBUG_EN__SHIFT 0x00000000
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK1_MASK 0x00001f00L
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK1__SHIFT 0x00000008
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK2_MASK 0x001f0000L
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_BLK2__SHIFT 0x00000010
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_XSP_MASK 0x01000000L
+#define BIF_DEBUG_CNTL__DEBUG_IDSEL_XSP__SHIFT 0x00000018
+#define BIF_DEBUG_CNTL__DEBUG_MULTIBLOCKEN_MASK 0x00000002L
+#define BIF_DEBUG_CNTL__DEBUG_MULTIBLOCKEN__SHIFT 0x00000001
+#define BIF_DEBUG_CNTL__DEBUG_OUT_EN_MASK 0x00000004L
+#define BIF_DEBUG_CNTL__DEBUG_OUT_EN__SHIFT 0x00000002
+#define BIF_DEBUG_CNTL__DEBUG_PAD_SEL_MASK 0x00000008L
+#define BIF_DEBUG_CNTL__DEBUG_PAD_SEL__SHIFT 0x00000003
+#define BIF_DEBUG_CNTL__DEBUG_SWAP_MASK 0x00000080L
+#define BIF_DEBUG_CNTL__DEBUG_SWAP__SHIFT 0x00000007
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_CLKSEL_MASK 0xc0000000L
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_CLKSEL__SHIFT 0x0000001e
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_EN_MASK 0x00000040L
+#define BIF_DEBUG_CNTL__DEBUG_SYNC_EN__SHIFT 0x00000006
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK1_MASK 0x0000003fL
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK1__SHIFT 0x00000000
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK2_MASK 0x00003f00L
+#define BIF_DEBUG_MUX__DEBUG_MUX_BLK2__SHIFT 0x00000008
+#define BIF_DEBUG_OUT__DEBUG_OUTPUT_MASK 0x0001ffffL
+#define BIF_DEBUG_OUT__DEBUG_OUTPUT__SHIFT 0x00000000
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID0_MASK 0x000000ffL
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID0__SHIFT 0x00000000
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID1_MASK 0x0000ff00L
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID1__SHIFT 0x00000008
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID2_MASK 0x00ff0000L
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID2__SHIFT 0x00000010
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID3_MASK 0xff000000L
+#define BIF_DEVFUNCNUM_LIST0__DEVFUNC_ID3__SHIFT 0x00000018
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID4_MASK 0x000000ffL
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID4__SHIFT 0x00000000
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID5_MASK 0x0000ff00L
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID5__SHIFT 0x00000008
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID6_MASK 0x00ff0000L
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID6__SHIFT 0x00000010
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID7_MASK 0xff000000L
+#define BIF_DEVFUNCNUM_LIST1__DEVFUNC_ID7__SHIFT 0x00000018
+#define BIF_FB_EN__FB_READ_EN_MASK 0x00000001L
+#define BIF_FB_EN__FB_READ_EN__SHIFT 0x00000000
+#define BIF_FB_EN__FB_WRITE_EN_MASK 0x00000002L
+#define BIF_FB_EN__FB_WRITE_EN__SHIFT 0x00000001
+#define BIF_FEATURES_CONTROL_MISC__BIF_MST_CPL_EP_DIS_MASK 0x00000008L
+#define BIF_FEATURES_CONTROL_MISC__BIF_MST_CPL_EP_DIS__SHIFT 0x00000003
+#define BIF_FEATURES_CONTROL_MISC__BIF_SLV_REQ_EP_DIS_MASK 0x00000004L
+#define BIF_FEATURES_CONTROL_MISC__BIF_SLV_REQ_EP_DIS__SHIFT 0x00000002
+#define BIF_FEATURES_CONTROL_MISC__IGNORE_BE_CHECK_GASKET_COMB_DIS_MASK 0x00000100L
+#define BIF_FEATURES_CONTROL_MISC__IGNORE_BE_CHECK_GASKET_COMB_DIS__SHIFT 0x00000008
+#define BIF_FEATURES_CONTROL_MISC__MST_BIF_REQ_EP_DIS_MASK 0x00000001L
+#define BIF_FEATURES_CONTROL_MISC__MST_BIF_REQ_EP_DIS__SHIFT 0x00000000
+#define BIF_FEATURES_CONTROL_MISC__PLL_SWITCH_IMPCTL_CAL_DONE_DIS_MASK 0x00000080L
+#define BIF_FEATURES_CONTROL_MISC__PLL_SWITCH_IMPCTL_CAL_DONE_DIS__SHIFT 0x00000007
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_ALL_DIS_MASK 0x00000020L
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_ALL_DIS__SHIFT 0x00000005
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_PART_DIS_MASK 0x00000040L
+#define BIF_FEATURES_CONTROL_MISC__POST_PSN_ONLY_PKT_REPORT_UR_PART_DIS__SHIFT 0x00000006
+#define BIF_FEATURES_CONTROL_MISC__SLV_BIF_CPL_EP_DIS_MASK 0x00000002L
+#define BIF_FEATURES_CONTROL_MISC__SLV_BIF_CPL_EP_DIS__SHIFT 0x00000001
+#define BIF_FEATURES_CONTROL_MISC__UR_PSN_PKT_REPORT_POISON_DIS_MASK 0x00000010L
+#define BIF_FEATURES_CONTROL_MISC__UR_PSN_PKT_REPORT_POISON_DIS__SHIFT 0x00000004
+#define BIF_PERFCOUNTER0_RESULT__PERFCOUNTER_RESULT_MASK 0xffffffffL
+#define BIF_PERFCOUNTER0_RESULT__PERFCOUNTER_RESULT__SHIFT 0x00000000
+#define BIF_PERFCOUNTER1_RESULT__PERFCOUNTER_RESULT_MASK 0xffffffffL
+#define BIF_PERFCOUNTER1_RESULT__PERFCOUNTER_RESULT__SHIFT 0x00000000
+#define BIF_PERFMON_CNTL__PERFCOUNTER_EN_MASK 0x00000001L
+#define BIF_PERFMON_CNTL__PERFCOUNTER_EN__SHIFT 0x00000000
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET0_MASK 0x00000002L
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET0__SHIFT 0x00000001
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET1_MASK 0x00000004L
+#define BIF_PERFMON_CNTL__PERFCOUNTER_RESET1__SHIFT 0x00000002
+#define BIF_PERFMON_CNTL__PERF_SEL0_MASK 0x00001f00L
+#define BIF_PERFMON_CNTL__PERF_SEL0__SHIFT 0x00000008
+#define BIF_PERFMON_CNTL__PERF_SEL1_MASK 0x0003e000L
+#define BIF_PERFMON_CNTL__PERF_SEL1__SHIFT 0x0000000d
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL0_ACK_TIMER_MASK 0x00000007L
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL0_ACK_TIMER__SHIFT 0x00000000
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL1_ACK_TIMER_MASK 0x00000038L
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL1_ACK_TIMER__SHIFT 0x00000003
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL_SWITCH_TIMER_MASK 0x000003c0L
+#define BIF_PIF_TXCLK_SWITCH_TIMER__PLL_SWITCH_TIMER__SHIFT 0x00000006
+#define BIF_RESET_EN__BIF_COR_RESET_EN_MASK 0x00400000L
+#define BIF_RESET_EN__BIF_COR_RESET_EN__SHIFT 0x00000016
+#define BIF_RESET_EN__CFG_RESET_EN_MASK 0x00000040L
+#define BIF_RESET_EN__CFG_RESET_EN__SHIFT 0x00000006
+#define BIF_RESET_EN__CFG_RESET_PULSE_WIDTH_MASK 0x0003f000L
+#define BIF_RESET_EN__CFG_RESET_PULSE_WIDTH__SHIFT 0x0000000c
+#define BIF_RESET_EN__COR_RESET_EN_MASK 0x00000008L
+#define BIF_RESET_EN__COR_RESET_EN__SHIFT 0x00000003
+#define BIF_RESET_EN__DRV_RESET_DELAY_SEL_MASK 0x000c0000L
+#define BIF_RESET_EN__DRV_RESET_DELAY_SEL__SHIFT 0x00000012
+#define BIF_RESET_EN__DRV_RESET_EN_MASK 0x00000080L
+#define BIF_RESET_EN__DRV_RESET_EN__SHIFT 0x00000007
+#define BIF_RESET_EN__FUNC0_FLR_EN_MASK 0x00800000L
+#define BIF_RESET_EN__FUNC0_FLR_EN__SHIFT 0x00000017
+#define BIF_RESET_EN__FUNC0_RESET_DELAY_SEL_MASK 0x0c000000L
+#define BIF_RESET_EN__FUNC0_RESET_DELAY_SEL__SHIFT 0x0000001a
+#define BIF_RESET_EN__FUNC1_FLR_EN_MASK 0x01000000L
+#define BIF_RESET_EN__FUNC1_FLR_EN__SHIFT 0x00000018
+#define BIF_RESET_EN__FUNC1_RESET_DELAY_SEL_MASK 0x30000000L
+#define BIF_RESET_EN__FUNC1_RESET_DELAY_SEL__SHIFT 0x0000001c
+#define BIF_RESET_EN__FUNC2_FLR_EN_MASK 0x02000000L
+#define BIF_RESET_EN__FUNC2_FLR_EN__SHIFT 0x00000019
+#define BIF_RESET_EN__FUNC2_RESET_DELAY_SEL_MASK 0xc0000000L
+#define BIF_RESET_EN__FUNC2_RESET_DELAY_SEL__SHIFT 0x0000001e
+#define BIF_RESET_EN__HOT_RESET_EN_MASK 0x00000200L
+#define BIF_RESET_EN__HOT_RESET_EN__SHIFT 0x00000009
+#define BIF_RESET_EN__LINK_DISABLE_RESET_EN_MASK 0x00000400L
+#define BIF_RESET_EN__LINK_DISABLE_RESET_EN__SHIFT 0x0000000a
+#define BIF_RESET_EN__LINK_DOWN_RESET_EN_MASK 0x00000800L
+#define BIF_RESET_EN__LINK_DOWN_RESET_EN__SHIFT 0x0000000b
+#define BIF_RESET_EN__PHY_RESET_EN_MASK 0x00000004L
+#define BIF_RESET_EN__PHY_RESET_EN__SHIFT 0x00000002
+#define BIF_RESET_EN__PIF_RSTB_EN_MASK 0x00100000L
+#define BIF_RESET_EN__PIF_RSTB_EN__SHIFT 0x00000014
+#define BIF_RESET_EN__PIF_STRAP_ALLVALID_EN_MASK 0x00200000L
+#define BIF_RESET_EN__PIF_STRAP_ALLVALID_EN__SHIFT 0x00000015
+#define BIF_RESET_EN__REG_RESET_EN_MASK 0x00000010L
+#define BIF_RESET_EN__REG_RESET_EN__SHIFT 0x00000004
+#define BIF_RESET_EN__RESET_CFGREG_ONLY_EN_MASK 0x00000100L
+#define BIF_RESET_EN__RESET_CFGREG_ONLY_EN__SHIFT 0x00000008
+#define BIF_RESET_EN__SOFT_RST_MODE_MASK 0x00000002L
+#define BIF_RESET_EN__SOFT_RST_MODE__SHIFT 0x00000001
+#define BIF_RESET_EN__STY_RESET_EN_MASK 0x00000020L
+#define BIF_RESET_EN__STY_RESET_EN__SHIFT 0x00000005
+#define BIF_SCRATCH0__BIF_SCRATCH0_MASK 0xffffffffL
+#define BIF_SCRATCH0__BIF_SCRATCH0__SHIFT 0x00000000
+#define BIF_SCRATCH1__BIF_SCRATCH1_MASK 0xffffffffL
+#define BIF_SCRATCH1__BIF_SCRATCH1__SHIFT 0x00000000
+#define BIF_SSA_DISP_LOWER__SSA_DISP_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_DISP_LOWER__SSA_DISP_LOWER__SHIFT 0x00000002
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_DISP_LOWER__SSA_DISP_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_DISP_UPPER__SSA_DISP_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_DISP_UPPER__SSA_DISP_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX0_LOWER__SSA_GFX0_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX0_UPPER__SSA_GFX0_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX0_UPPER__SSA_GFX0_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX1_LOWER__SSA_GFX1_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX1_UPPER__SSA_GFX1_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX1_UPPER__SSA_GFX1_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX2_LOWER__SSA_GFX2_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX2_UPPER__SSA_GFX2_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX2_UPPER__SSA_GFX2_UPPER__SHIFT 0x00000002
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_LOWER__SHIFT 0x00000002
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_GFX3_LOWER__SSA_GFX3_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_GFX3_UPPER__SSA_GFX3_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_GFX3_UPPER__SSA_GFX3_UPPER__SHIFT 0x00000002
+#define BIF_SSA_MC_LOWER__SSA_MC_FB_STALL_EN_MASK 0x20000000L
+#define BIF_SSA_MC_LOWER__SSA_MC_FB_STALL_EN__SHIFT 0x0000001d
+#define BIF_SSA_MC_LOWER__SSA_MC_LOWER_MASK 0x0003fffcL
+#define BIF_SSA_MC_LOWER__SSA_MC_LOWER__SHIFT 0x00000002
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_CMP_EN_MASK 0x40000000L
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_CMP_EN__SHIFT 0x0000001e
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_STALL_EN_MASK 0x80000000L
+#define BIF_SSA_MC_LOWER__SSA_MC_REG_STALL_EN__SHIFT 0x0000001f
+#define BIF_SSA_MC_UPPER__SSA_MC_UPPER_MASK 0x0003fffcL
+#define BIF_SSA_MC_UPPER__SSA_MC_UPPER__SHIFT 0x00000002
+#define BIF_SSA_PWR_STATUS__SSA_DISP_PWR_STATUS_MASK 0x00000002L
+#define BIF_SSA_PWR_STATUS__SSA_DISP_PWR_STATUS__SHIFT 0x00000001
+#define BIF_SSA_PWR_STATUS__SSA_GFX_PWR_STATUS_MASK 0x00000001L
+#define BIF_SSA_PWR_STATUS__SSA_GFX_PWR_STATUS__SHIFT 0x00000000
+#define BIF_SSA_PWR_STATUS__SSA_MC_PWR_STATUS_MASK 0x00000004L
+#define BIF_SSA_PWR_STATUS__SSA_MC_PWR_STATUS__SHIFT 0x00000002
+#define BIF_XDMA_HI__BIF_XDMA_UPPER_BOUND_MASK 0x1fffffffL
+#define BIF_XDMA_HI__BIF_XDMA_UPPER_BOUND__SHIFT 0x00000000
+#define BIF_XDMA_LO__BIF_XDMA_APER_EN_MASK 0x80000000L
+#define BIF_XDMA_LO__BIF_XDMA_APER_EN__SHIFT 0x0000001f
+#define BIF_XDMA_LO__BIF_XDMA_LOWER_BOUND_MASK 0x1fffffffL
+#define BIF_XDMA_LO__BIF_XDMA_LOWER_BOUND__SHIFT 0x00000000
+#define BIOS_SCRATCH_0__BIOS_SCRATCH_0_MASK 0xffffffffL
+#define BIOS_SCRATCH_0__BIOS_SCRATCH_0__SHIFT 0x00000000
+#define BIOS_SCRATCH_10__BIOS_SCRATCH_10_MASK 0xffffffffL
+#define BIOS_SCRATCH_10__BIOS_SCRATCH_10__SHIFT 0x00000000
+#define BIOS_SCRATCH_11__BIOS_SCRATCH_11_MASK 0xffffffffL
+#define BIOS_SCRATCH_11__BIOS_SCRATCH_11__SHIFT 0x00000000
+#define BIOS_SCRATCH_12__BIOS_SCRATCH_12_MASK 0xffffffffL
+#define BIOS_SCRATCH_12__BIOS_SCRATCH_12__SHIFT 0x00000000
+#define BIOS_SCRATCH_13__BIOS_SCRATCH_13_MASK 0xffffffffL
+#define BIOS_SCRATCH_13__BIOS_SCRATCH_13__SHIFT 0x00000000
+#define BIOS_SCRATCH_14__BIOS_SCRATCH_14_MASK 0xffffffffL
+#define BIOS_SCRATCH_14__BIOS_SCRATCH_14__SHIFT 0x00000000
+#define BIOS_SCRATCH_15__BIOS_SCRATCH_15_MASK 0xffffffffL
+#define BIOS_SCRATCH_15__BIOS_SCRATCH_15__SHIFT 0x00000000
+#define BIOS_SCRATCH_1__BIOS_SCRATCH_1_MASK 0xffffffffL
+#define BIOS_SCRATCH_1__BIOS_SCRATCH_1__SHIFT 0x00000000
+#define BIOS_SCRATCH_2__BIOS_SCRATCH_2_MASK 0xffffffffL
+#define BIOS_SCRATCH_2__BIOS_SCRATCH_2__SHIFT 0x00000000
+#define BIOS_SCRATCH_3__BIOS_SCRATCH_3_MASK 0xffffffffL
+#define BIOS_SCRATCH_3__BIOS_SCRATCH_3__SHIFT 0x00000000
+#define BIOS_SCRATCH_4__BIOS_SCRATCH_4_MASK 0xffffffffL
+#define BIOS_SCRATCH_4__BIOS_SCRATCH_4__SHIFT 0x00000000
+#define BIOS_SCRATCH_5__BIOS_SCRATCH_5_MASK 0xffffffffL
+#define BIOS_SCRATCH_5__BIOS_SCRATCH_5__SHIFT 0x00000000
+#define BIOS_SCRATCH_6__BIOS_SCRATCH_6_MASK 0xffffffffL
+#define BIOS_SCRATCH_6__BIOS_SCRATCH_6__SHIFT 0x00000000
+#define BIOS_SCRATCH_7__BIOS_SCRATCH_7_MASK 0xffffffffL
+#define BIOS_SCRATCH_7__BIOS_SCRATCH_7__SHIFT 0x00000000
+#define BIOS_SCRATCH_8__BIOS_SCRATCH_8_MASK 0xffffffffL
+#define BIOS_SCRATCH_8__BIOS_SCRATCH_8__SHIFT 0x00000000
+#define BIOS_SCRATCH_9__BIOS_SCRATCH_9_MASK 0xffffffffL
+#define BIOS_SCRATCH_9__BIOS_SCRATCH_9__SHIFT 0x00000000
+#define BUS_CNTL__BIF_ERR_RTR_BKPRESSURE_EN_MASK 0x00000100L
+#define BUS_CNTL__BIF_ERR_RTR_BKPRESSURE_EN__SHIFT 0x00000008
+#define BUS_CNTL__BIOS_ROM_DIS_MASK 0x00000002L
+#define BUS_CNTL__BIOS_ROM_DIS__SHIFT 0x00000001
+#define BUS_CNTL__BIOS_ROM_WRT_EN_MASK 0x00000001L
+#define BUS_CNTL__BIOS_ROM_WRT_EN__SHIFT 0x00000000
+#define BUS_CNTL__PMI_BM_DIS_MASK 0x00000010L
+#define BUS_CNTL__PMI_BM_DIS__SHIFT 0x00000004
+#define BUS_CNTL__PMI_INT_DIS_MASK 0x00000020L
+#define BUS_CNTL__PMI_INT_DIS__SHIFT 0x00000005
+#define BUS_CNTL__PMI_IO_DIS_MASK 0x00000004L
+#define BUS_CNTL__PMI_IO_DIS__SHIFT 0x00000002
+#define BUS_CNTL__PMI_MEM_DIS_MASK 0x00000008L
+#define BUS_CNTL__PMI_MEM_DIS__SHIFT 0x00000003
+#define BUS_CNTL__RD_STALL_IO_WR_MASK 0x00040000L
+#define BUS_CNTL__RD_STALL_IO_WR__SHIFT 0x00000012
+#define BUS_CNTL__SET_AZ_TC_MASK 0x00001c00L
+#define BUS_CNTL__SET_AZ_TC__SHIFT 0x0000000a
+#define BUS_CNTL__SET_MC_TC_MASK 0x0000e000L
+#define BUS_CNTL__SET_MC_TC__SHIFT 0x0000000d
+#define BUS_CNTL__VGA_MEM_COHERENCY_DIS_MASK 0x00000080L
+#define BUS_CNTL__VGA_MEM_COHERENCY_DIS__SHIFT 0x00000007
+#define BUS_CNTL__VGA_REG_COHERENCY_DIS_MASK 0x00000040L
+#define BUS_CNTL__VGA_REG_COHERENCY_DIS__SHIFT 0x00000006
+#define BUS_CNTL__ZERO_BE_RD_EN_MASK 0x00020000L
+#define BUS_CNTL__ZERO_BE_RD_EN__SHIFT 0x00000011
+#define BUS_CNTL__ZERO_BE_WR_EN_MASK 0x00010000L
+#define BUS_CNTL__ZERO_BE_WR_EN__SHIFT 0x00000010
+#define CAPTURE_HOST_BUSNUM__CHECK_EN_MASK 0x00000001L
+#define CAPTURE_HOST_BUSNUM__CHECK_EN__SHIFT 0x00000000
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_A_MASK 0x00000001L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_A__SHIFT 0x00000000
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_CNTL_EN_MASK 0x00001000L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_CNTL_EN__SHIFT 0x0000000c
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_MODE_MASK 0x00000004L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_MODE__SHIFT 0x00000002
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SCHMEN_MASK 0x00000800L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SCHMEN__SHIFT 0x0000000b
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SEL_MASK 0x00000002L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SEL__SHIFT 0x00000001
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SLEWN_MASK 0x00000200L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SLEWN__SHIFT 0x00000009
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN0_MASK 0x00000020L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN0__SHIFT 0x00000005
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN1_MASK 0x00000040L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN1__SHIFT 0x00000006
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN2_MASK 0x00000080L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN2__SHIFT 0x00000007
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN3_MASK 0x00000100L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SN3__SHIFT 0x00000008
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SPARE_MASK 0x00000018L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_SPARE__SHIFT 0x00000003
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_WAKE_MASK 0x00000400L
+#define CLKREQB_PAD_CNTL__CLKREQB_PAD_WAKE__SHIFT 0x0000000a
+#define CONFIG_APER_SIZE__APER_SIZE_MASK 0xffffffffL
+#define CONFIG_APER_SIZE__APER_SIZE__SHIFT 0x00000000
+#define CONFIG_CNTL__CFG_VGA_RAM_EN_MASK 0x00000001L
+#define CONFIG_CNTL__CFG_VGA_RAM_EN__SHIFT 0x00000000
+#define CONFIG_CNTL__GENMO_MONO_ADDRESS_B_MASK 0x00000004L
+#define CONFIG_CNTL__GENMO_MONO_ADDRESS_B__SHIFT 0x00000002
+#define CONFIG_CNTL__GRPH_ADRSEL_MASK 0x00000018L
+#define CONFIG_CNTL__GRPH_ADRSEL__SHIFT 0x00000003
+#define CONFIG_CNTL__VGA_DIS_MASK 0x00000002L
+#define CONFIG_CNTL__VGA_DIS__SHIFT 0x00000001
+#define CONFIG_F0_BASE__F0_BASE_MASK 0xffffffffL
+#define CONFIG_F0_BASE__F0_BASE__SHIFT 0x00000000
+#define CONFIG_MEMSIZE__CONFIG_MEMSIZE_MASK 0xffffffffL
+#define CONFIG_MEMSIZE__CONFIG_MEMSIZE__SHIFT 0x00000000
+#define CONFIG_REG_APER_SIZE__REG_APER_SIZE_MASK 0x000fffffL
+#define CONFIG_REG_APER_SIZE__REG_APER_SIZE__SHIFT 0x00000000
+#define HDP_MEM_COHERENCY_FLUSH_CNTL__HDP_MEM_FLUSH_ADDR_MASK 0x00000001L
+#define HDP_MEM_COHERENCY_FLUSH_CNTL__HDP_MEM_FLUSH_ADDR__SHIFT 0x00000000
+#define HDP_REG_COHERENCY_FLUSH_CNTL__HDP_REG_FLUSH_ADDR_MASK 0x00000001L
+#define HDP_REG_COHERENCY_FLUSH_CNTL__HDP_REG_FLUSH_ADDR__SHIFT 0x00000000
+#define HOST_BUSNUM__HOST_ID_MASK 0x0000ffffL
+#define HOST_BUSNUM__HOST_ID__SHIFT 0x00000000
+#define HW_DEBUG__HW_00_DEBUG_MASK 0x00000001L
+#define HW_DEBUG__HW_00_DEBUG__SHIFT 0x00000000
+#define HW_DEBUG__HW_01_DEBUG_MASK 0x00000002L
+#define HW_DEBUG__HW_01_DEBUG__SHIFT 0x00000001
+#define HW_DEBUG__HW_02_DEBUG_MASK 0x00000004L
+#define HW_DEBUG__HW_02_DEBUG__SHIFT 0x00000002
+#define HW_DEBUG__HW_03_DEBUG_MASK 0x00000008L
+#define HW_DEBUG__HW_03_DEBUG__SHIFT 0x00000003
+#define HW_DEBUG__HW_04_DEBUG_MASK 0x00000010L
+#define HW_DEBUG__HW_04_DEBUG__SHIFT 0x00000004
+#define HW_DEBUG__HW_05_DEBUG_MASK 0x00000020L
+#define HW_DEBUG__HW_05_DEBUG__SHIFT 0x00000005
+#define HW_DEBUG__HW_06_DEBUG_MASK 0x00000040L
+#define HW_DEBUG__HW_06_DEBUG__SHIFT 0x00000006
+#define HW_DEBUG__HW_07_DEBUG_MASK 0x00000080L
+#define HW_DEBUG__HW_07_DEBUG__SHIFT 0x00000007
+#define HW_DEBUG__HW_08_DEBUG_MASK 0x00000100L
+#define HW_DEBUG__HW_08_DEBUG__SHIFT 0x00000008
+#define HW_DEBUG__HW_09_DEBUG_MASK 0x00000200L
+#define HW_DEBUG__HW_09_DEBUG__SHIFT 0x00000009
+#define HW_DEBUG__HW_10_DEBUG_MASK 0x00000400L
+#define HW_DEBUG__HW_10_DEBUG__SHIFT 0x0000000a
+#define HW_DEBUG__HW_11_DEBUG_MASK 0x00000800L
+#define HW_DEBUG__HW_11_DEBUG__SHIFT 0x0000000b
+#define HW_DEBUG__HW_12_DEBUG_MASK 0x00001000L
+#define HW_DEBUG__HW_12_DEBUG__SHIFT 0x0000000c
+#define HW_DEBUG__HW_13_DEBUG_MASK 0x00002000L
+#define HW_DEBUG__HW_13_DEBUG__SHIFT 0x0000000d
+#define HW_DEBUG__HW_14_DEBUG_MASK 0x00004000L
+#define HW_DEBUG__HW_14_DEBUG__SHIFT 0x0000000e
+#define HW_DEBUG__HW_15_DEBUG_MASK 0x00008000L
+#define HW_DEBUG__HW_15_DEBUG__SHIFT 0x0000000f
+#define HW_DEBUG__HW_16_DEBUG_MASK 0x00010000L
+#define HW_DEBUG__HW_16_DEBUG__SHIFT 0x00000010
+#define HW_DEBUG__HW_17_DEBUG_MASK 0x00020000L
+#define HW_DEBUG__HW_17_DEBUG__SHIFT 0x00000011
+#define HW_DEBUG__HW_18_DEBUG_MASK 0x00040000L
+#define HW_DEBUG__HW_18_DEBUG__SHIFT 0x00000012
+#define HW_DEBUG__HW_19_DEBUG_MASK 0x00080000L
+#define HW_DEBUG__HW_19_DEBUG__SHIFT 0x00000013
+#define HW_DEBUG__HW_20_DEBUG_MASK 0x00100000L
+#define HW_DEBUG__HW_20_DEBUG__SHIFT 0x00000014
+#define HW_DEBUG__HW_21_DEBUG_MASK 0x00200000L
+#define HW_DEBUG__HW_21_DEBUG__SHIFT 0x00000015
+#define HW_DEBUG__HW_22_DEBUG_MASK 0x00400000L
+#define HW_DEBUG__HW_22_DEBUG__SHIFT 0x00000016
+#define HW_DEBUG__HW_23_DEBUG_MASK 0x00800000L
+#define HW_DEBUG__HW_23_DEBUG__SHIFT 0x00000017
+#define HW_DEBUG__HW_24_DEBUG_MASK 0x01000000L
+#define HW_DEBUG__HW_24_DEBUG__SHIFT 0x00000018
+#define HW_DEBUG__HW_25_DEBUG_MASK 0x02000000L
+#define HW_DEBUG__HW_25_DEBUG__SHIFT 0x00000019
+#define HW_DEBUG__HW_26_DEBUG_MASK 0x04000000L
+#define HW_DEBUG__HW_26_DEBUG__SHIFT 0x0000001a
+#define HW_DEBUG__HW_27_DEBUG_MASK 0x08000000L
+#define HW_DEBUG__HW_27_DEBUG__SHIFT 0x0000001b
+#define HW_DEBUG__HW_28_DEBUG_MASK 0x10000000L
+#define HW_DEBUG__HW_28_DEBUG__SHIFT 0x0000001c
+#define HW_DEBUG__HW_29_DEBUG_MASK 0x20000000L
+#define HW_DEBUG__HW_29_DEBUG__SHIFT 0x0000001d
+#define HW_DEBUG__HW_30_DEBUG_MASK 0x40000000L
+#define HW_DEBUG__HW_30_DEBUG__SHIFT 0x0000001e
+#define HW_DEBUG__HW_31_DEBUG_MASK 0x80000000L
+#define HW_DEBUG__HW_31_DEBUG__SHIFT 0x0000001f
+#define IMPCTL_RESET__IMP_SW_RESET_MASK 0x00000001L
+#define IMPCTL_RESET__IMP_SW_RESET__SHIFT 0x00000000
+#define INTERRUPT_CNTL2__IH_DUMMY_RD_ADDR_MASK 0xffffffffL
+#define INTERRUPT_CNTL2__IH_DUMMY_RD_ADDR__SHIFT 0x00000000
+#define INTERRUPT_CNTL__GEN_GPIO_INT_EN_MASK 0x00001e00L
+#define INTERRUPT_CNTL__GEN_GPIO_INT_EN__SHIFT 0x00000009
+#define INTERRUPT_CNTL__GEN_IH_INT_EN_MASK 0x00000100L
+#define INTERRUPT_CNTL__GEN_IH_INT_EN__SHIFT 0x00000008
+#define INTERRUPT_CNTL__IH_DUMMY_RD_EN_MASK 0x00000002L
+#define INTERRUPT_CNTL__IH_DUMMY_RD_EN__SHIFT 0x00000001
+#define INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE_MASK 0x00000001L
+#define INTERRUPT_CNTL__IH_DUMMY_RD_OVERRIDE__SHIFT 0x00000000
+#define INTERRUPT_CNTL__IH_INTR_DLY_CNTR_MASK 0x000000f0L
+#define INTERRUPT_CNTL__IH_INTR_DLY_CNTR__SHIFT 0x00000004
+#define INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN_MASK 0x00000008L
+#define INTERRUPT_CNTL__IH_REQ_NONSNOOP_EN__SHIFT 0x00000003
+#define INTERRUPT_CNTL__SELECT_INT_GPIO_OUTPUT_MASK 0x00006000L
+#define INTERRUPT_CNTL__SELECT_INT_GPIO_OUTPUT__SHIFT 0x0000000d
+#define MASTER_CREDIT_CNTL__BIF_AZ_RDRET_CREDIT_MASK 0x003f0000L
+#define MASTER_CREDIT_CNTL__BIF_AZ_RDRET_CREDIT__SHIFT 0x00000010
+#define MASTER_CREDIT_CNTL__BIF_MC_RDRET_CREDIT_MASK 0x0000003fL
+#define MASTER_CREDIT_CNTL__BIF_MC_RDRET_CREDIT__SHIFT 0x00000000
+#define MM_CFGREGS_CNTL__MM_CFG_FUNC_SEL_MASK 0x00000007L
+#define MM_CFGREGS_CNTL__MM_CFG_FUNC_SEL__SHIFT 0x00000000
+#define MM_CFGREGS_CNTL__MM_WR_TO_CFG_EN_MASK 0x00000008L
+#define MM_CFGREGS_CNTL__MM_WR_TO_CFG_EN__SHIFT 0x00000003
+#define MM_DATA__MM_DATA_MASK 0xffffffffL
+#define MM_DATA__MM_DATA__SHIFT 0x00000000
+#define MM_INDEX_HI__MM_OFFSET_HI_MASK 0xffffffffL
+#define MM_INDEX_HI__MM_OFFSET_HI__SHIFT 0x00000000
+#define MM_INDEX__MM_APER_MASK 0x80000000L
+#define MM_INDEX__MM_APER__SHIFT 0x0000001f
+#define MM_INDEX__MM_OFFSET_MASK 0x7fffffffL
+#define MM_INDEX__MM_OFFSET__SHIFT 0x00000000
+#define NEW_REFCLKB_TIMER_1__PHY_PLL_PDWN_TIMER_MASK 0x000003ffL
+#define NEW_REFCLKB_TIMER_1__PHY_PLL_PDWN_TIMER__SHIFT 0x00000000
+#define NEW_REFCLKB_TIMER_1__PLL0_PDNB_EN_MASK 0x00000400L
+#define NEW_REFCLKB_TIMER_1__PLL0_PDNB_EN__SHIFT 0x0000000a
+#define NEW_REFCLKB_TIMER__REFCLK_ON_MASK 0x00200000L
+#define NEW_REFCLKB_TIMER__REFCLK_ON__SHIFT 0x00000015
+#define NEW_REFCLKB_TIMER__REG_STOP_REFCLK_EN_MASK 0x00000001L
+#define NEW_REFCLKB_TIMER__REG_STOP_REFCLK_EN__SHIFT 0x00000000
+#define NEW_REFCLKB_TIMER__STOP_REFCLK_TIMER_MASK 0x001ffffeL
+#define NEW_REFCLKB_TIMER__STOP_REFCLK_TIMER__SHIFT 0x00000001
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN_MASK 0x00000001L
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN__SHIFT 0x00000000
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE_MASK 0x0000003eL
+#define PB0_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE__SHIFT 0x00000001
+#define PB0_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP_MASK 0x00000f00L
+#define PB0_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP__SHIFT 0x00000008
+#define PB0_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN_MASK 0x00800000L
+#define PB0_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN__SHIFT 0x00000017
+#define PB0_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN_MASK 0x00400000L
+#define PB0_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN__SHIFT 0x00000016
+#define PB0_DFT_JIT_INJ_REG0__DFT_NUM_STEPS_MASK 0x0000001fL
+#define PB0_DFT_JIT_INJ_REG0__DFT_NUM_STEPS__SHIFT 0x00000000
+#define PB0_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME_MASK 0xff000000L
+#define PB0_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME__SHIFT 0x00000018
+#define PB0_DFT_JIT_INJ_REG1__DFT_BLOCK_EN_MASK 0x00010000L
+#define PB0_DFT_JIT_INJ_REG1__DFT_BLOCK_EN__SHIFT 0x00000010
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_EN_MASK 0x00000100L
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_EN__SHIFT 0x00000008
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE_MASK 0x000000ffL
+#define PB0_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE__SHIFT 0x00000000
+#define PB0_DFT_JIT_INJ_REG2__DFT_LANE_EN_MASK 0x0000ffffL
+#define PB0_DFT_JIT_INJ_REG2__DFT_LANE_EN__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG0__BACKUP_MASK 0x0000ffffL
+#define PB0_GLB_CTRL_REG0__BACKUP__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG0__CFG_IDLEDET_TH_MASK 0x00030000L
+#define PB0_GLB_CTRL_REG0__CFG_IDLEDET_TH__SHIFT 0x00000010
+#define PB0_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL_MASK 0x00700000L
+#define PB0_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL__SHIFT 0x00000014
+#define PB0_GLB_CTRL_REG0__DBG_RXFEBYP_EN_MASK 0x00800000L
+#define PB0_GLB_CTRL_REG0__DBG_RXFEBYP_EN__SHIFT 0x00000017
+#define PB0_GLB_CTRL_REG0__DBG_RXPRBS_CLR_MASK 0x01000000L
+#define PB0_GLB_CTRL_REG0__DBG_RXPRBS_CLR__SHIFT 0x00000018
+#define PB0_GLB_CTRL_REG0__DBG_RXTOGGLE_EN_MASK 0x02000000L
+#define PB0_GLB_CTRL_REG0__DBG_RXTOGGLE_EN__SHIFT 0x00000019
+#define PB0_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN_MASK 0x04000000L
+#define PB0_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN__SHIFT 0x0000001a
+#define PB0_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE_MASK 0xc0000000L
+#define PB0_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE__SHIFT 0x0000001e
+#define PB0_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV_MASK 0x80000000L
+#define PB0_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV__SHIFT 0x0000001f
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN_MASK 0x00000001L
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL_MASK 0x0000007eL
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL__SHIFT 0x00000001
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN_MASK 0x00000080L
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN__SHIFT 0x00000007
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL_MASK 0x00003f00L
+#define PB0_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL__SHIFT 0x00000008
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN_MASK 0x00004000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN__SHIFT 0x0000000e
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL_MASK 0x003f8000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL__SHIFT 0x0000000f
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN_MASK 0x00400000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN__SHIFT 0x00000016
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL_MASK 0x3f800000L
+#define PB0_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL__SHIFT 0x00000017
+#define PB0_GLB_CTRL_REG1__TST_LOSPDTST_EN_MASK 0x40000000L
+#define PB0_GLB_CTRL_REG1__TST_LOSPDTST_EN__SHIFT 0x0000001e
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN_MASK 0x00000001L
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL_MASK 0x000000feL
+#define PB0_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL__SHIFT 0x00000001
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN_MASK 0x00000100L
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN__SHIFT 0x00000008
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL_MASK 0x0000fe00L
+#define PB0_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL__SHIFT 0x00000009
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN_MASK 0x00010000L
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN__SHIFT 0x00000010
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL_MASK 0x00fe0000L
+#define PB0_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL__SHIFT 0x00000011
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN_MASK 0x01000000L
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN__SHIFT 0x00000018
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL_MASK 0xfe000000L
+#define PB0_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL__SHIFT 0x00000019
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL_MASK 0x00000060L
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL__SHIFT 0x00000005
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL_MASK 0x00000180L
+#define PB0_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL__SHIFT 0x00000007
+#define PB0_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL_MASK 0x00000600L
+#define PB0_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL__SHIFT 0x00000009
+#define PB0_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL_MASK 0x0001c000L
+#define PB0_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL__SHIFT 0x0000000e
+#define PB0_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN_MASK 0x00001000L
+#define PB0_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN__SHIFT 0x0000000c
+#define PB0_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN_MASK 0x00000800L
+#define PB0_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN__SHIFT 0x0000000b
+#define PB0_GLB_CTRL_REG3__DBG_DLL_CLK_SEL_MASK 0x001c0000L
+#define PB0_GLB_CTRL_REG3__DBG_DLL_CLK_SEL__SHIFT 0x00000012
+#define PB0_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE_MASK 0x80000000L
+#define PB0_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE__SHIFT 0x0000001f
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN_MASK 0x00400000L
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN__SHIFT 0x00000016
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL_MASK 0x07800000L
+#define PB0_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL__SHIFT 0x00000017
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN_MASK 0x08000000L
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN__SHIFT 0x0000001b
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL_MASK 0x70000000L
+#define PB0_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL__SHIFT 0x0000001c
+#define PB0_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL_MASK 0x00200000L
+#define PB0_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL__SHIFT 0x00000015
+#define PB0_GLB_CTRL_REG3__RXDBG_SEL_MASK 0x0000001fL
+#define PB0_GLB_CTRL_REG3__RXDBG_SEL__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_EXEC_MASK 0x03c00000L
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_EXEC__SHIFT 0x00000016
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_INST_MASK 0x0000ffffL
+#define PB0_GLB_CTRL_REG4__DBG_RXAPU_INST__SHIFT 0x00000000
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN_MASK 0x00040000L
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN__SHIFT 0x00000012
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL_MASK 0x00030000L
+#define PB0_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL__SHIFT 0x00000010
+#define PB0_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL_MASK 0x04000000L
+#define PB0_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000001a
+#define PB0_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE_MASK 0x10000000L
+#define PB0_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE__SHIFT 0x0000001c
+#define PB0_GLB_CTRL_REG4__PWRGOOD_OVRD_MASK 0x08000000L
+#define PB0_GLB_CTRL_REG4__PWRGOOD_OVRD__SHIFT 0x0000001b
+#define PB0_GLB_CTRL_REG5__DBG_RXAPU_MODE_MASK 0x000000ffL
+#define PB0_GLB_CTRL_REG5__DBG_RXAPU_MODE__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL_MASK 0x0000ffffL
+#define PB0_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB0_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN_MASK 0x00008000L
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN__SHIFT 0x0000000f
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB0_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN_MASK 0x00000004L
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN__SHIFT 0x00000002
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL_MASK 0x00000008L
+#define PB0_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL__SHIFT 0x00000003
+#define PB0_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN_MASK 0x00000001L
+#define PB0_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN_MASK 0x00000002L
+#define PB0_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN__SHIFT 0x00000001
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_EN_MASK 0x00000001L
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_EN__SHIFT 0x00000000
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL_MASK 0x00000002L
+#define PB0_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT_MASK 0x00000010L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT__SHIFT 0x00000004
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE_MASK 0x00100000L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG0__RXIMP_MASK 0x000f0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__RXIMP__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXNIMP_MASK 0x00000f00L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXNIMP__SHIFT 0x00000008
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXPIMP_MASK 0x0000f000L
+#define PB0_GLB_SCI_STAT_OVRD_REG0__TXPIMP__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_0_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_0__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_1_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_1__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_2_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_2__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_3_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG1__MODE_3__SHIFT 0x0000001c
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_4_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_4__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_5_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_5__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_6_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_6__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_7_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG2__MODE_7__SHIFT 0x0000001c
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_10_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_10__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_11_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_11__SHIFT 0x0000001c
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_8_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_8__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_9_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG3__MODE_9__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12_MASK 0x00001000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12__SHIFT 0x0000000c
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13_MASK 0x00002000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13__SHIFT 0x0000000d
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14_MASK 0x00004000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14__SHIFT 0x0000000e
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15_MASK 0x00008000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15__SHIFT 0x0000000f
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12_MASK 0x000c0000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12__SHIFT 0x00000012
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13_MASK 0x00c00000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13__SHIFT 0x00000016
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14_MASK 0x0c000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14__SHIFT 0x0000001a
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15_MASK 0xc0000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15__SHIFT 0x0000001e
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15_MASK 0x00000004L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15__SHIFT 0x00000002
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15_MASK 0x00000002L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15__SHIFT 0x00000001
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15_MASK 0x00000001L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15__SHIFT 0x00000000
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_12_MASK 0x00030000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_12__SHIFT 0x00000010
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_13_MASK 0x00300000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_13__SHIFT 0x00000014
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_14_MASK 0x03000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_14__SHIFT 0x00000018
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_15_MASK 0x30000000L
+#define PB0_GLB_SCI_STAT_OVRD_REG4__MODE_15__SHIFT 0x0000001c
+#define PB0_HW_DEBUG__PB0_HW_00_DEBUG_MASK 0x00000001L
+#define PB0_HW_DEBUG__PB0_HW_00_DEBUG__SHIFT 0x00000000
+#define PB0_HW_DEBUG__PB0_HW_01_DEBUG_MASK 0x00000002L
+#define PB0_HW_DEBUG__PB0_HW_01_DEBUG__SHIFT 0x00000001
+#define PB0_HW_DEBUG__PB0_HW_02_DEBUG_MASK 0x00000004L
+#define PB0_HW_DEBUG__PB0_HW_02_DEBUG__SHIFT 0x00000002
+#define PB0_HW_DEBUG__PB0_HW_03_DEBUG_MASK 0x00000008L
+#define PB0_HW_DEBUG__PB0_HW_03_DEBUG__SHIFT 0x00000003
+#define PB0_HW_DEBUG__PB0_HW_04_DEBUG_MASK 0x00000010L
+#define PB0_HW_DEBUG__PB0_HW_04_DEBUG__SHIFT 0x00000004
+#define PB0_HW_DEBUG__PB0_HW_05_DEBUG_MASK 0x00000020L
+#define PB0_HW_DEBUG__PB0_HW_05_DEBUG__SHIFT 0x00000005
+#define PB0_HW_DEBUG__PB0_HW_06_DEBUG_MASK 0x00000040L
+#define PB0_HW_DEBUG__PB0_HW_06_DEBUG__SHIFT 0x00000006
+#define PB0_HW_DEBUG__PB0_HW_07_DEBUG_MASK 0x00000080L
+#define PB0_HW_DEBUG__PB0_HW_07_DEBUG__SHIFT 0x00000007
+#define PB0_HW_DEBUG__PB0_HW_08_DEBUG_MASK 0x00000100L
+#define PB0_HW_DEBUG__PB0_HW_08_DEBUG__SHIFT 0x00000008
+#define PB0_HW_DEBUG__PB0_HW_09_DEBUG_MASK 0x00000200L
+#define PB0_HW_DEBUG__PB0_HW_09_DEBUG__SHIFT 0x00000009
+#define PB0_HW_DEBUG__PB0_HW_10_DEBUG_MASK 0x00000400L
+#define PB0_HW_DEBUG__PB0_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB0_HW_DEBUG__PB0_HW_11_DEBUG_MASK 0x00000800L
+#define PB0_HW_DEBUG__PB0_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB0_HW_DEBUG__PB0_HW_12_DEBUG_MASK 0x00001000L
+#define PB0_HW_DEBUG__PB0_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB0_HW_DEBUG__PB0_HW_13_DEBUG_MASK 0x00002000L
+#define PB0_HW_DEBUG__PB0_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB0_HW_DEBUG__PB0_HW_14_DEBUG_MASK 0x00004000L
+#define PB0_HW_DEBUG__PB0_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB0_HW_DEBUG__PB0_HW_15_DEBUG_MASK 0x00008000L
+#define PB0_HW_DEBUG__PB0_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB0_HW_DEBUG__PB0_HW_16_DEBUG_MASK 0x00010000L
+#define PB0_HW_DEBUG__PB0_HW_16_DEBUG__SHIFT 0x00000010
+#define PB0_HW_DEBUG__PB0_HW_17_DEBUG_MASK 0x00020000L
+#define PB0_HW_DEBUG__PB0_HW_17_DEBUG__SHIFT 0x00000011
+#define PB0_HW_DEBUG__PB0_HW_18_DEBUG_MASK 0x00040000L
+#define PB0_HW_DEBUG__PB0_HW_18_DEBUG__SHIFT 0x00000012
+#define PB0_HW_DEBUG__PB0_HW_19_DEBUG_MASK 0x00080000L
+#define PB0_HW_DEBUG__PB0_HW_19_DEBUG__SHIFT 0x00000013
+#define PB0_HW_DEBUG__PB0_HW_20_DEBUG_MASK 0x00100000L
+#define PB0_HW_DEBUG__PB0_HW_20_DEBUG__SHIFT 0x00000014
+#define PB0_HW_DEBUG__PB0_HW_21_DEBUG_MASK 0x00200000L
+#define PB0_HW_DEBUG__PB0_HW_21_DEBUG__SHIFT 0x00000015
+#define PB0_HW_DEBUG__PB0_HW_22_DEBUG_MASK 0x00400000L
+#define PB0_HW_DEBUG__PB0_HW_22_DEBUG__SHIFT 0x00000016
+#define PB0_HW_DEBUG__PB0_HW_23_DEBUG_MASK 0x00800000L
+#define PB0_HW_DEBUG__PB0_HW_23_DEBUG__SHIFT 0x00000017
+#define PB0_HW_DEBUG__PB0_HW_24_DEBUG_MASK 0x01000000L
+#define PB0_HW_DEBUG__PB0_HW_24_DEBUG__SHIFT 0x00000018
+#define PB0_HW_DEBUG__PB0_HW_25_DEBUG_MASK 0x02000000L
+#define PB0_HW_DEBUG__PB0_HW_25_DEBUG__SHIFT 0x00000019
+#define PB0_HW_DEBUG__PB0_HW_26_DEBUG_MASK 0x04000000L
+#define PB0_HW_DEBUG__PB0_HW_26_DEBUG__SHIFT 0x0000001a
+#define PB0_HW_DEBUG__PB0_HW_27_DEBUG_MASK 0x08000000L
+#define PB0_HW_DEBUG__PB0_HW_27_DEBUG__SHIFT 0x0000001b
+#define PB0_HW_DEBUG__PB0_HW_28_DEBUG_MASK 0x10000000L
+#define PB0_HW_DEBUG__PB0_HW_28_DEBUG__SHIFT 0x0000001c
+#define PB0_HW_DEBUG__PB0_HW_29_DEBUG_MASK 0x20000000L
+#define PB0_HW_DEBUG__PB0_HW_29_DEBUG__SHIFT 0x0000001d
+#define PB0_HW_DEBUG__PB0_HW_30_DEBUG_MASK 0x40000000L
+#define PB0_HW_DEBUG__PB0_HW_30_DEBUG__SHIFT 0x0000001e
+#define PB0_HW_DEBUG__PB0_HW_31_DEBUG_MASK 0x80000000L
+#define PB0_HW_DEBUG__PB0_HW_31_DEBUG__SHIFT 0x0000001f
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_EN_MASK 0x00000080L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_EN__SHIFT 0x00000007
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0_MASK 0x00000100L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0__SHIFT 0x00000008
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10_MASK 0x00040000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10__SHIFT 0x00000012
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11_MASK 0x00080000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11__SHIFT 0x00000013
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12_MASK 0x00100000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12__SHIFT 0x00000014
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13_MASK 0x00200000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13__SHIFT 0x00000015
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14_MASK 0x00400000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14__SHIFT 0x00000016
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15_MASK 0x00800000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15__SHIFT 0x00000017
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2_MASK 0x00000400L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2__SHIFT 0x0000000a
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3_MASK 0x00000800L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4_MASK 0x00001000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4__SHIFT 0x0000000c
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5_MASK 0x00002000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5__SHIFT 0x0000000d
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6_MASK 0x00004000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6__SHIFT 0x0000000e
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7_MASK 0x00008000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8_MASK 0x00010000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8__SHIFT 0x00000010
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9_MASK 0x00020000L
+#define PB0_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9__SHIFT 0x00000011
+#define PB0_PIF_CNTL2__RXDETECT_SAMPL_TIME_MASK 0x00000006L
+#define PB0_PIF_CNTL2__RXDETECT_SAMPL_TIME__SHIFT 0x00000001
+#define PB0_PIF_CNTL2__RXPHYSTATUS_DELAY_MASK 0x07000000L
+#define PB0_PIF_CNTL2__RXPHYSTATUS_DELAY__SHIFT 0x00000018
+#define PB0_PIF_CNTL__DA_FIFO_RESET_0_MASK 0x00000002L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_0__SHIFT 0x00000001
+#define PB0_PIF_CNTL__DA_FIFO_RESET_1_MASK 0x00000020L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_1__SHIFT 0x00000005
+#define PB0_PIF_CNTL__DA_FIFO_RESET_2_MASK 0x00000200L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_2__SHIFT 0x00000009
+#define PB0_PIF_CNTL__DA_FIFO_RESET_3_MASK 0x00002000L
+#define PB0_PIF_CNTL__DA_FIFO_RESET_3__SHIFT 0x0000000d
+#define PB0_PIF_CNTL__DIVINIT_MODE_MASK 0x00000100L
+#define PB0_PIF_CNTL__DIVINIT_MODE__SHIFT 0x00000008
+#define PB0_PIF_CNTL__EI_CYCLE_OFF_TIME_MASK 0x00700000L
+#define PB0_PIF_CNTL__EI_CYCLE_OFF_TIME__SHIFT 0x00000014
+#define PB0_PIF_CNTL__EI_DET_CYCLE_MODE_MASK 0x00000010L
+#define PB0_PIF_CNTL__EI_DET_CYCLE_MODE__SHIFT 0x00000004
+#define PB0_PIF_CNTL__EXIT_L0S_INIT_DIS_MASK 0x00800000L
+#define PB0_PIF_CNTL__EXIT_L0S_INIT_DIS__SHIFT 0x00000017
+#define PB0_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP_MASK 0x10000000L
+#define PB0_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP__SHIFT 0x0000001c
+#define PB0_PIF_CNTL__IGNORE_TxDataValid_EP_DIS_MASK 0x20000000L
+#define PB0_PIF_CNTL__IGNORE_TxDataValid_EP_DIS__SHIFT 0x0000001d
+#define PB0_PIF_CNTL__LS2_EXIT_TIME_MASK 0x000e0000L
+#define PB0_PIF_CNTL__LS2_EXIT_TIME__SHIFT 0x00000011
+#define PB0_PIF_CNTL__PHYCMD_CR_EN_MODE_MASK 0x00000008L
+#define PB0_PIF_CNTL__PHYCMD_CR_EN_MODE__SHIFT 0x00000003
+#define PB0_PIF_CNTL__PHY_CR_EN_MODE_MASK 0x00000004L
+#define PB0_PIF_CNTL__PHY_CR_EN_MODE__SHIFT 0x00000002
+#define PB0_PIF_CNTL__PLL_BINDING_ENABLE_MASK 0x00000400L
+#define PB0_PIF_CNTL__PLL_BINDING_ENABLE__SHIFT 0x0000000a
+#define PB0_PIF_CNTL__RXDETECT_FIFO_RESET_MODE_MASK 0x00000040L
+#define PB0_PIF_CNTL__RXDETECT_FIFO_RESET_MODE__SHIFT 0x00000006
+#define PB0_PIF_CNTL__RXDETECT_TX_PWR_MODE_MASK 0x00000080L
+#define PB0_PIF_CNTL__RXDETECT_TX_PWR_MODE__SHIFT 0x00000007
+#define PB0_PIF_CNTL__RXEN_GATER_MASK 0x0f000000L
+#define PB0_PIF_CNTL__RXEN_GATER__SHIFT 0x00000018
+#define PB0_PIF_CNTL__SC_CALIB_DONE_CNTL_MASK 0x00000800L
+#define PB0_PIF_CNTL__SC_CALIB_DONE_CNTL__SHIFT 0x0000000b
+#define PB0_PIF_CNTL__SERIAL_CFG_ENABLE_MASK 0x00000001L
+#define PB0_PIF_CNTL__SERIAL_CFG_ENABLE__SHIFT 0x00000000
+#define PB0_PIF_CNTL__TXGND_TIME_MASK 0x00010000L
+#define PB0_PIF_CNTL__TXGND_TIME__SHIFT 0x00000010
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_00_DEBUG_MASK 0x00000001L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_00_DEBUG__SHIFT 0x00000000
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_01_DEBUG_MASK 0x00000002L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_01_DEBUG__SHIFT 0x00000001
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_02_DEBUG_MASK 0x00000004L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_02_DEBUG__SHIFT 0x00000002
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_03_DEBUG_MASK 0x00000008L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_03_DEBUG__SHIFT 0x00000003
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_04_DEBUG_MASK 0x00000010L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_04_DEBUG__SHIFT 0x00000004
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_05_DEBUG_MASK 0x00000020L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_05_DEBUG__SHIFT 0x00000005
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_06_DEBUG_MASK 0x00000040L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_06_DEBUG__SHIFT 0x00000006
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_07_DEBUG_MASK 0x00000080L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_07_DEBUG__SHIFT 0x00000007
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_08_DEBUG_MASK 0x00000100L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_08_DEBUG__SHIFT 0x00000008
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_09_DEBUG_MASK 0x00000200L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_09_DEBUG__SHIFT 0x00000009
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_10_DEBUG_MASK 0x00000400L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_11_DEBUG_MASK 0x00000800L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_12_DEBUG_MASK 0x00001000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_13_DEBUG_MASK 0x00002000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_14_DEBUG_MASK 0x00004000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_15_DEBUG_MASK 0x00008000L
+#define PB0_PIF_HW_DEBUG__PB0_PIF_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB0_PIF_PAIRING__MULTI_PIF_MASK 0x02000000L
+#define PB0_PIF_PAIRING__MULTI_PIF__SHIFT 0x00000019
+#define PB0_PIF_PAIRING__X16_LANE_15_0_MASK 0x00100000L
+#define PB0_PIF_PAIRING__X16_LANE_15_0__SHIFT 0x00000014
+#define PB0_PIF_PAIRING__X2_LANE_1_0_MASK 0x00000001L
+#define PB0_PIF_PAIRING__X2_LANE_1_0__SHIFT 0x00000000
+#define PB0_PIF_PAIRING__X2_LANE_11_10_MASK 0x00000020L
+#define PB0_PIF_PAIRING__X2_LANE_11_10__SHIFT 0x00000005
+#define PB0_PIF_PAIRING__X2_LANE_13_12_MASK 0x00000040L
+#define PB0_PIF_PAIRING__X2_LANE_13_12__SHIFT 0x00000006
+#define PB0_PIF_PAIRING__X2_LANE_15_14_MASK 0x00000080L
+#define PB0_PIF_PAIRING__X2_LANE_15_14__SHIFT 0x00000007
+#define PB0_PIF_PAIRING__X2_LANE_3_2_MASK 0x00000002L
+#define PB0_PIF_PAIRING__X2_LANE_3_2__SHIFT 0x00000001
+#define PB0_PIF_PAIRING__X2_LANE_5_4_MASK 0x00000004L
+#define PB0_PIF_PAIRING__X2_LANE_5_4__SHIFT 0x00000002
+#define PB0_PIF_PAIRING__X2_LANE_7_6_MASK 0x00000008L
+#define PB0_PIF_PAIRING__X2_LANE_7_6__SHIFT 0x00000003
+#define PB0_PIF_PAIRING__X2_LANE_9_8_MASK 0x00000010L
+#define PB0_PIF_PAIRING__X2_LANE_9_8__SHIFT 0x00000004
+#define PB0_PIF_PAIRING__X4_LANE_11_8_MASK 0x00000400L
+#define PB0_PIF_PAIRING__X4_LANE_11_8__SHIFT 0x0000000a
+#define PB0_PIF_PAIRING__X4_LANE_15_12_MASK 0x00000800L
+#define PB0_PIF_PAIRING__X4_LANE_15_12__SHIFT 0x0000000b
+#define PB0_PIF_PAIRING__X4_LANE_3_0_MASK 0x00000100L
+#define PB0_PIF_PAIRING__X4_LANE_3_0__SHIFT 0x00000008
+#define PB0_PIF_PAIRING__X4_LANE_7_4_MASK 0x00000200L
+#define PB0_PIF_PAIRING__X4_LANE_7_4__SHIFT 0x00000009
+#define PB0_PIF_PAIRING__X8_LANE_15_8_MASK 0x00020000L
+#define PB0_PIF_PAIRING__X8_LANE_15_8__SHIFT 0x00000011
+#define PB0_PIF_PAIRING__X8_LANE_7_0_MASK 0x00010000L
+#define PB0_PIF_PAIRING__X8_LANE_7_0__SHIFT 0x00000010
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000b
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9_MASK 0x00000100L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9__SHIFT 0x00000008
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9_MASK 0x00000200L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9__SHIFT 0x00000009
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9_MASK 0x00000010L
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000004
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9_MASK 0x000000e0L
+#define PB0_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000005
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9_MASK 0x00004000L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9__SHIFT 0x0000000e
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9_MASK 0x00038000L
+#define PB0_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000f
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9_MASK 0x00000001L
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000000
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9_MASK 0x0000000eL
+#define PB0_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000001
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9_MASK 0x00000400L
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9__SHIFT 0x0000000a
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9_MASK 0x00003800L
+#define PB0_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000b
+#define PB0_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0__SHIFT 0x00000000
+#define PB0_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1__SHIFT 0x00000000
+#define PB0_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2__SHIFT 0x00000000
+#define PB0_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3_MASK 0x00000008L
+#define PB0_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3__SHIFT 0x00000003
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3_MASK 0x00001c00L
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3__SHIFT 0x0000000a
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3_MASK 0x00000380L
+#define PB0_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3__SHIFT 0x00000007
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3_MASK 0x10000000L
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3__SHIFT 0x0000001c
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3_MASK 0xe0000000L
+#define PB0_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3__SHIFT 0x0000001d
+#define PB0_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3_MASK 0x07000000L
+#define PB0_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3__SHIFT 0x00000018
+#define PB0_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3_MASK 0x00000070L
+#define PB0_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3__SHIFT 0x00000004
+#define PB0_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3_MASK 0x00010000L
+#define PB0_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3__SHIFT 0x00000010
+#define PB0_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3_MASK 0x00000007L
+#define PB0_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3__SHIFT 0x00000000
+#define PB0_PIF_SC_CTL__SC_CALIBRATION_MASK 0x00000001L
+#define PB0_PIF_SC_CTL__SC_CALIBRATION__SHIFT 0x00000000
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0_MASK 0x00000020L
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0__SHIFT 0x00000005
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S_MASK 0x00000010L
+#define PB0_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S__SHIFT 0x00000004
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0_MASK 0x00000008L
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0__SHIFT 0x00000003
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0S_MASK 0x00000004L
+#define PB0_PIF_SC_CTL__SC_EXIT_L1_TO_L0S__SHIFT 0x00000002
+#define PB0_PIF_SC_CTL__SC_LANE_0_RESUME_MASK 0x00010000L
+#define PB0_PIF_SC_CTL__SC_LANE_0_RESUME__SHIFT 0x00000010
+#define PB0_PIF_SC_CTL__SC_LANE_10_RESUME_MASK 0x04000000L
+#define PB0_PIF_SC_CTL__SC_LANE_10_RESUME__SHIFT 0x0000001a
+#define PB0_PIF_SC_CTL__SC_LANE_11_RESUME_MASK 0x08000000L
+#define PB0_PIF_SC_CTL__SC_LANE_11_RESUME__SHIFT 0x0000001b
+#define PB0_PIF_SC_CTL__SC_LANE_12_RESUME_MASK 0x10000000L
+#define PB0_PIF_SC_CTL__SC_LANE_12_RESUME__SHIFT 0x0000001c
+#define PB0_PIF_SC_CTL__SC_LANE_13_RESUME_MASK 0x20000000L
+#define PB0_PIF_SC_CTL__SC_LANE_13_RESUME__SHIFT 0x0000001d
+#define PB0_PIF_SC_CTL__SC_LANE_14_RESUME_MASK 0x40000000L
+#define PB0_PIF_SC_CTL__SC_LANE_14_RESUME__SHIFT 0x0000001e
+#define PB0_PIF_SC_CTL__SC_LANE_15_RESUME_MASK 0x80000000L
+#define PB0_PIF_SC_CTL__SC_LANE_15_RESUME__SHIFT 0x0000001f
+#define PB0_PIF_SC_CTL__SC_LANE_1_RESUME_MASK 0x00020000L
+#define PB0_PIF_SC_CTL__SC_LANE_1_RESUME__SHIFT 0x00000011
+#define PB0_PIF_SC_CTL__SC_LANE_2_RESUME_MASK 0x00040000L
+#define PB0_PIF_SC_CTL__SC_LANE_2_RESUME__SHIFT 0x00000012
+#define PB0_PIF_SC_CTL__SC_LANE_3_RESUME_MASK 0x00080000L
+#define PB0_PIF_SC_CTL__SC_LANE_3_RESUME__SHIFT 0x00000013
+#define PB0_PIF_SC_CTL__SC_LANE_4_RESUME_MASK 0x00100000L
+#define PB0_PIF_SC_CTL__SC_LANE_4_RESUME__SHIFT 0x00000014
+#define PB0_PIF_SC_CTL__SC_LANE_5_RESUME_MASK 0x00200000L
+#define PB0_PIF_SC_CTL__SC_LANE_5_RESUME__SHIFT 0x00000015
+#define PB0_PIF_SC_CTL__SC_LANE_6_RESUME_MASK 0x00400000L
+#define PB0_PIF_SC_CTL__SC_LANE_6_RESUME__SHIFT 0x00000016
+#define PB0_PIF_SC_CTL__SC_LANE_7_RESUME_MASK 0x00800000L
+#define PB0_PIF_SC_CTL__SC_LANE_7_RESUME__SHIFT 0x00000017
+#define PB0_PIF_SC_CTL__SC_LANE_8_RESUME_MASK 0x01000000L
+#define PB0_PIF_SC_CTL__SC_LANE_8_RESUME__SHIFT 0x00000018
+#define PB0_PIF_SC_CTL__SC_LANE_9_RESUME_MASK 0x02000000L
+#define PB0_PIF_SC_CTL__SC_LANE_9_RESUME__SHIFT 0x00000019
+#define PB0_PIF_SC_CTL__SC_PHASE_1_MASK 0x00000100L
+#define PB0_PIF_SC_CTL__SC_PHASE_1__SHIFT 0x00000008
+#define PB0_PIF_SC_CTL__SC_PHASE_2_MASK 0x00000200L
+#define PB0_PIF_SC_CTL__SC_PHASE_2__SHIFT 0x00000009
+#define PB0_PIF_SC_CTL__SC_PHASE_3_MASK 0x00000400L
+#define PB0_PIF_SC_CTL__SC_PHASE_3__SHIFT 0x0000000a
+#define PB0_PIF_SC_CTL__SC_PHASE_4_MASK 0x00000800L
+#define PB0_PIF_SC_CTL__SC_PHASE_4__SHIFT 0x0000000b
+#define PB0_PIF_SC_CTL__SC_PHASE_5_MASK 0x00001000L
+#define PB0_PIF_SC_CTL__SC_PHASE_5__SHIFT 0x0000000c
+#define PB0_PIF_SC_CTL__SC_PHASE_6_MASK 0x00002000L
+#define PB0_PIF_SC_CTL__SC_PHASE_6__SHIFT 0x0000000d
+#define PB0_PIF_SC_CTL__SC_PHASE_7_MASK 0x00004000L
+#define PB0_PIF_SC_CTL__SC_PHASE_7__SHIFT 0x0000000e
+#define PB0_PIF_SC_CTL__SC_PHASE_8_MASK 0x00008000L
+#define PB0_PIF_SC_CTL__SC_PHASE_8__SHIFT 0x0000000f
+#define PB0_PIF_SC_CTL__SC_RXDETECT_MASK 0x00000002L
+#define PB0_PIF_SC_CTL__SC_RXDETECT__SHIFT 0x00000001
+#define PB0_PIF_SC_CTL__SC_SPEED_CHANGE_MASK 0x00000040L
+#define PB0_PIF_SC_CTL__SC_SPEED_CHANGE__SHIFT 0x00000006
+#define PB0_PIF_SCRATCH__PIF_SCRATCH_MASK 0xffffffffL
+#define PB0_PIF_SCRATCH__PIF_SCRATCH__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_0__SEQ_PHASE_0_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_PHASE_0__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_10__SEQ_PHASE_10_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_PHASE_10__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_11__SEQ_PHASE_11_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_PHASE_11__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_12__SEQ_PHASE_12_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_PHASE_12__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_13__SEQ_PHASE_13_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_PHASE_13__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_14__SEQ_PHASE_14_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_PHASE_14__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_15__SEQ_PHASE_15_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_PHASE_15__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_1__SEQ_PHASE_1_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_PHASE_1__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_2__SEQ_PHASE_2_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_PHASE_2__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_3__SEQ_PHASE_3_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_PHASE_3__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_4__SEQ_PHASE_4_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_PHASE_4__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_5__SEQ_PHASE_5_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_PHASE_5__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_6__SEQ_PHASE_6_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_PHASE_6__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_7__SEQ_PHASE_7_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_PHASE_7__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_8__SEQ_PHASE_8_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_PHASE_8__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8__SHIFT 0x00000006
+#define PB0_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9_MASK 0x00000001L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9__SHIFT 0x00000000
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9_MASK 0x00000020L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9__SHIFT 0x00000005
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9_MASK 0x00000010L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9__SHIFT 0x00000004
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9_MASK 0x00000008L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9__SHIFT 0x00000003
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9_MASK 0x00000004L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9__SHIFT 0x00000002
+#define PB0_PIF_SEQ_STATUS_9__SEQ_PHASE_9_MASK 0x00000700L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_PHASE_9__SHIFT 0x00000008
+#define PB0_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9_MASK 0x00000002L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9__SHIFT 0x00000001
+#define PB0_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9_MASK 0x00000040L
+#define PB0_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9__SHIFT 0x00000006
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_0_MASK 0x00000001L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_0__SHIFT 0x00000000
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_10_MASK 0x00000400L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_10__SHIFT 0x0000000a
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_11_MASK 0x00000800L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_11__SHIFT 0x0000000b
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_12_MASK 0x00001000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_12__SHIFT 0x0000000c
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_13_MASK 0x00002000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_13__SHIFT 0x0000000d
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_14_MASK 0x00004000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_14__SHIFT 0x0000000e
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_15_MASK 0x00008000L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_15__SHIFT 0x0000000f
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_1_MASK 0x00000002L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_1__SHIFT 0x00000001
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_2_MASK 0x00000004L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_2__SHIFT 0x00000002
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_3_MASK 0x00000008L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_3__SHIFT 0x00000003
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_4_MASK 0x00000010L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_4__SHIFT 0x00000004
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_5_MASK 0x00000020L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_5__SHIFT 0x00000005
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_6_MASK 0x00000040L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_6__SHIFT 0x00000006
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_7_MASK 0x00000080L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_7__SHIFT 0x00000007
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_8_MASK 0x00000100L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_8__SHIFT 0x00000008
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_9_MASK 0x00000200L
+#define PB0_PIF_TXPHYSTATUS__TXPHYSTATUS_9__SHIFT 0x00000009
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0_MASK 0x00000003L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB0_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0_MASK 0x00000010L
+#define PB0_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0__SHIFT 0x00000004
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0_MASK 0x00000008L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000003
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0_MASK 0x00000007L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0_MASK 0x00000080L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0__SHIFT 0x00000007
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000070L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000004
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0_MASK 0x00000200L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0__SHIFT 0x00000009
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0_MASK 0x00000100L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0__SHIFT 0x00000008
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0_MASK 0x00040000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0__SHIFT 0x00000012
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0_MASK 0x0003fc00L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0__SHIFT 0x0000000a
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0_MASK 0x10000000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0__SHIFT 0x0000001c
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0_MASK 0x0ff80000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0__SHIFT 0x00000013
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0_MASK 0x80000000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0__SHIFT 0x0000001f
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0_MASK 0x60000000L
+#define PB0_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0__SHIFT 0x0000001d
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0_MASK 0x00000008L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000003
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0_MASK 0x00000007L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0_MASK 0x00040000L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0__SHIFT 0x00000012
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0_MASK 0x0003c000L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0__SHIFT 0x0000000e
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000020L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x00000005
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000010L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000004
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00000080L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x00000007
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000040L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x00000006
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0_MASK 0x00000200L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0__SHIFT 0x00000009
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0_MASK 0x00000100L
+#define PB0_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0__SHIFT 0x00000008
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0_MASK 0x00000003L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0_MASK 0x000007f0L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0__SHIFT 0x00000004
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB0_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0_MASK 0x00000800L
+#define PB0_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0__SHIFT 0x0000000b
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0_MASK 0x00000100L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000008
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0_MASK 0x000000ffL
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0_MASK 0x00001000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0__SHIFT 0x0000000c
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000e00L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000009
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0_MASK 0x00004000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0__SHIFT 0x0000000e
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0_MASK 0x00002000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0_MASK 0x10000000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0__SHIFT 0x0000001c
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0_MASK 0x0fff8000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0__SHIFT 0x0000000f
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0_MASK 0x80000000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0__SHIFT 0x0000001f
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0_MASK 0x40000000L
+#define PB0_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0__SHIFT 0x0000001e
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0_MASK 0x00400000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000016
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0_MASK 0x00380000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000013
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0_MASK 0x00000020L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0__SHIFT 0x00000005
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0_MASK 0x0000001fL
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0_MASK 0x00000100L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0__SHIFT 0x00000008
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0_MASK 0x000000c0L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0__SHIFT 0x00000006
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000400L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x0000000a
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000200L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000009
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00001000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x0000000c
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000800L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x0000000b
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0_MASK 0x00004000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0__SHIFT 0x0000000e
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0_MASK 0x00002000L
+#define PB0_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE_MASK 0x00000300L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE__SHIFT 0x00000008
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR_MASK 0x00000070L
+#define PB0_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR__SHIFT 0x00000004
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000200L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000009
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000400L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000a
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000800L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000b
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00100000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000014
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00200000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000015
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00001000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x0000000c
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00002000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000d
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00004000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000e
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00400000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000016
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00800000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000017
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2_MASK 0x00000100L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000008
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000002L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000001
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000004L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x00000002
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000008L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x00000003
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00010000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000010
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00020000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000011
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00000010L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x00000004
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00000020L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x00000005
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00000040L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x00000006
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00040000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000012
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00080000L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000013
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2_MASK 0x00000080L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000007
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC_MASK 0x00000001L
+#define PB0_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1_MASK 0x000003ffL
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2_MASK 0x000ffc00L
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2__SHIFT 0x0000000a
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3_MASK 0x3ff00000L
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE_MASK 0xc0000000L
+#define PB0_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN_MASK 0xc0000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1_MASK 0x0000000fL
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2_MASK 0x000000f0L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2__SHIFT 0x00000004
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3_MASK 0x00000f00L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3__SHIFT 0x00000008
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1_MASK 0x0000f000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2_MASK 0x000f0000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1_MASK 0x01000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2_MASK 0x02000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2__SHIFT 0x00000019
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3_MASK 0x04000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3__SHIFT 0x0000001a
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2_MASK 0x10000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3_MASK 0x20000000L
+#define PB0_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3__SHIFT 0x0000001d
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1_MASK 0x0000f000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2_MASK 0x000f0000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1_MASK 0x03000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2_MASK 0x0c000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2__SHIFT 0x0000001a
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3_MASK 0x30000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD_MASK 0xc0000000L
+#define PB0_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1_MASK 0x00000001L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2_MASK 0x00000002L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2__SHIFT 0x00000001
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3_MASK 0x00000004L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3__SHIFT 0x00000002
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2_MASK 0x0f000000L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3_MASK 0xf0000000L
+#define PB0_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1_MASK 0x00000007L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2_MASK 0x00000038L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2__SHIFT 0x00000003
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3_MASK 0x000001c0L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3__SHIFT 0x00000006
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2_MASK 0x0f000000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3_MASK 0xf0000000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1_MASK 0x00000e00L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1__SHIFT 0x00000009
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2_MASK 0x00007000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3_MASK 0x00038000L
+#define PB0_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3__SHIFT 0x0000000f
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1_MASK 0x0000001fL
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2_MASK 0x000003e0L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2__SHIFT 0x00000005
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3_MASK 0x00007c00L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3__SHIFT 0x0000000a
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1_MASK 0x00008000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1__SHIFT 0x0000000f
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2_MASK 0x00010000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3_MASK 0x00020000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3__SHIFT 0x00000011
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1_MASK 0x00040000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1__SHIFT 0x00000012
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2_MASK 0x00080000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2__SHIFT 0x00000013
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3_MASK 0x00100000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2_MASK 0x10000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3_MASK 0x20000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3__SHIFT 0x0000001d
+#define PB0_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0_MASK 0x40000000L
+#define PB0_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0__SHIFT 0x0000001e
+#define PB0_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1_MASK 0x0000000fL
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2_MASK 0x000000f0L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2__SHIFT 0x00000004
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3_MASK 0x00000f00L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3__SHIFT 0x00000008
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1_MASK 0x0000f000L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2_MASK 0x000f0000L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2__SHIFT 0x00000010
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3_MASK 0x00f00000L
+#define PB0_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3__SHIFT 0x00000014
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x01000000L
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2_MASK 0x04000000L
+#define PB0_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001a
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1_MASK 0x001c0000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1__SHIFT 0x00000012
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2_MASK 0x00e00000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2__SHIFT 0x00000015
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3_MASK 0x07000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3__SHIFT 0x00000018
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1_MASK 0x08000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1__SHIFT 0x0000001b
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2_MASK 0x10000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2__SHIFT 0x0000001c
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3_MASK 0x20000000L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3__SHIFT 0x0000001d
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1_MASK 0x0000000fL
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1__SHIFT 0x00000000
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2_MASK 0x000000f0L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2__SHIFT 0x00000004
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3_MASK 0x00000f00L
+#define PB0_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3__SHIFT 0x00000008
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x00001000L
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x0000000c
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2_MASK 0x00002000L
+#define PB0_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2__SHIFT 0x0000000d
+#define PB0_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2_MASK 0x00020000L
+#define PB0_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000011
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN_MASK 0x80000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN__SHIFT 0x0000001f
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL_MASK 0x40000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL__SHIFT 0x0000001e
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN_MASK 0x00000002L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN__SHIFT 0x00000001
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL_MASK 0x00000001L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL__SHIFT 0x00000000
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN_MASK 0x00000008L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN__SHIFT 0x00000003
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL_MASK 0x00000004L
+#define PB0_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL__SHIFT 0x00000002
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN_MASK 0x20000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN__SHIFT 0x0000001d
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL_MASK 0x10000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL__SHIFT 0x0000001c
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000100L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000008
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x000000c0L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000006
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN_MASK 0x00000400L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN__SHIFT 0x0000000a
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL_MASK 0x00000200L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL__SHIFT 0x00000009
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00001000L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000c
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000800L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x0000000b
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN_MASK 0x00004000L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN__SHIFT 0x0000000e
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL_MASK 0x00002000L
+#define PB0_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL__SHIFT 0x0000000d
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN_MASK 0x00010000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN__SHIFT 0x00000010
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL_MASK 0x00008000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL__SHIFT 0x0000000f
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN_MASK 0x00040000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN__SHIFT 0x00000012
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL_MASK 0x00020000L
+#define PB0_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL__SHIFT 0x00000011
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN_MASK 0x00100000L
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN__SHIFT 0x00000014
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL_MASK 0x00080000L
+#define PB0_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL__SHIFT 0x00000013
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN_MASK 0x00400000L
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN__SHIFT 0x00000016
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL_MASK 0x00200000L
+#define PB0_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL__SHIFT 0x00000015
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN_MASK 0x01000000L
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN__SHIFT 0x00000018
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL_MASK 0x00800000L
+#define PB0_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL__SHIFT 0x00000017
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN_MASK 0x00000002L
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN__SHIFT 0x00000001
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL_MASK 0x00000001L
+#define PB0_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL__SHIFT 0x00000000
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3_MASK 0x00010000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3__SHIFT 0x00000010
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15_MASK 0x00080000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15__SHIFT 0x00000013
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7_MASK 0x00020000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7__SHIFT 0x00000011
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11_MASK 0x00040000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11__SHIFT 0x00000012
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3_MASK 0x00100000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3__SHIFT 0x00000014
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15_MASK 0x00800000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15__SHIFT 0x00000017
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7_MASK 0x00200000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7__SHIFT 0x00000015
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11_MASK 0x00400000L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11__SHIFT 0x00000016
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_RX_LANE0_CTRL_REG0__RX_BACKUP_0_MASK 0x000000ffL
+#define PB0_RX_LANE0_CTRL_REG0__RX_BACKUP_0__SHIFT 0x00000000
+#define PB0_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0_MASK 0x00002000L
+#define PB0_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0__SHIFT 0x0000000d
+#define PB0_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0_MASK 0x00000c00L
+#define PB0_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0__SHIFT 0x0000000a
+#define PB0_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0_MASK 0x00001000L
+#define PB0_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0__SHIFT 0x0000000c
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0_MASK 0x00000008L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0__SHIFT 0x00000003
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0_MASK 0x00000080L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0__SHIFT 0x00000007
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0_MASK 0x00000100L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0__SHIFT 0x00000008
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0_MASK 0x00000200L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0__SHIFT 0x00000009
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0_MASK 0x00000070L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0__SHIFT 0x00000004
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0_MASK 0x00000007L
+#define PB0_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0__SHIFT 0x00000000
+#define PB0_RX_LANE10_CTRL_REG0__RX_BACKUP_10_MASK 0x000000ffL
+#define PB0_RX_LANE10_CTRL_REG0__RX_BACKUP_10__SHIFT 0x00000000
+#define PB0_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10_MASK 0x00002000L
+#define PB0_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10__SHIFT 0x0000000d
+#define PB0_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10_MASK 0x00000c00L
+#define PB0_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10__SHIFT 0x0000000a
+#define PB0_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10_MASK 0x00001000L
+#define PB0_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10__SHIFT 0x0000000c
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10_MASK 0x00000008L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10__SHIFT 0x00000003
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10_MASK 0x00000080L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10__SHIFT 0x00000007
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10_MASK 0x00000100L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10__SHIFT 0x00000008
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10_MASK 0x00000200L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10__SHIFT 0x00000009
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10_MASK 0x00000070L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10__SHIFT 0x00000004
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10_MASK 0x00000007L
+#define PB0_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10__SHIFT 0x00000000
+#define PB0_RX_LANE11_CTRL_REG0__RX_BACKUP_11_MASK 0x000000ffL
+#define PB0_RX_LANE11_CTRL_REG0__RX_BACKUP_11__SHIFT 0x00000000
+#define PB0_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11_MASK 0x00002000L
+#define PB0_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11__SHIFT 0x0000000d
+#define PB0_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11_MASK 0x00000c00L
+#define PB0_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11__SHIFT 0x0000000a
+#define PB0_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11_MASK 0x00001000L
+#define PB0_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11__SHIFT 0x0000000c
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11_MASK 0x00000008L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11__SHIFT 0x00000003
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11_MASK 0x00000080L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11__SHIFT 0x00000007
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11_MASK 0x00000100L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11__SHIFT 0x00000008
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11_MASK 0x00000200L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11__SHIFT 0x00000009
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11_MASK 0x00000070L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11__SHIFT 0x00000004
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11_MASK 0x00000007L
+#define PB0_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11__SHIFT 0x00000000
+#define PB0_RX_LANE12_CTRL_REG0__RX_BACKUP_12_MASK 0x000000ffL
+#define PB0_RX_LANE12_CTRL_REG0__RX_BACKUP_12__SHIFT 0x00000000
+#define PB0_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12_MASK 0x00002000L
+#define PB0_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12__SHIFT 0x0000000d
+#define PB0_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12_MASK 0x00000c00L
+#define PB0_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12__SHIFT 0x0000000a
+#define PB0_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12_MASK 0x00001000L
+#define PB0_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12__SHIFT 0x0000000c
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12_MASK 0x00000008L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12__SHIFT 0x00000003
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12_MASK 0x00000080L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12__SHIFT 0x00000007
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12_MASK 0x00000100L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12__SHIFT 0x00000008
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12_MASK 0x00000200L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12__SHIFT 0x00000009
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12_MASK 0x00000070L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12__SHIFT 0x00000004
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12_MASK 0x00000007L
+#define PB0_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12__SHIFT 0x00000000
+#define PB0_RX_LANE13_CTRL_REG0__RX_BACKUP_13_MASK 0x000000ffL
+#define PB0_RX_LANE13_CTRL_REG0__RX_BACKUP_13__SHIFT 0x00000000
+#define PB0_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13_MASK 0x00002000L
+#define PB0_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13__SHIFT 0x0000000d
+#define PB0_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13_MASK 0x00000c00L
+#define PB0_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13__SHIFT 0x0000000a
+#define PB0_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13_MASK 0x00001000L
+#define PB0_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13__SHIFT 0x0000000c
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13_MASK 0x00000008L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13__SHIFT 0x00000003
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13_MASK 0x00000080L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13__SHIFT 0x00000007
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13_MASK 0x00000100L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13__SHIFT 0x00000008
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13_MASK 0x00000200L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13__SHIFT 0x00000009
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13_MASK 0x00000070L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13__SHIFT 0x00000004
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13_MASK 0x00000007L
+#define PB0_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13__SHIFT 0x00000000
+#define PB0_RX_LANE14_CTRL_REG0__RX_BACKUP_14_MASK 0x000000ffL
+#define PB0_RX_LANE14_CTRL_REG0__RX_BACKUP_14__SHIFT 0x00000000
+#define PB0_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14_MASK 0x00002000L
+#define PB0_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14__SHIFT 0x0000000d
+#define PB0_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14_MASK 0x00000c00L
+#define PB0_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14__SHIFT 0x0000000a
+#define PB0_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14_MASK 0x00001000L
+#define PB0_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14__SHIFT 0x0000000c
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14_MASK 0x00000008L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14__SHIFT 0x00000003
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14_MASK 0x00000080L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14__SHIFT 0x00000007
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14_MASK 0x00000100L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14__SHIFT 0x00000008
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14_MASK 0x00000200L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14__SHIFT 0x00000009
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14_MASK 0x00000070L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14__SHIFT 0x00000004
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14_MASK 0x00000007L
+#define PB0_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14__SHIFT 0x00000000
+#define PB0_RX_LANE15_CTRL_REG0__RX_BACKUP_15_MASK 0x000000ffL
+#define PB0_RX_LANE15_CTRL_REG0__RX_BACKUP_15__SHIFT 0x00000000
+#define PB0_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15_MASK 0x00002000L
+#define PB0_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15__SHIFT 0x0000000d
+#define PB0_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15_MASK 0x00000c00L
+#define PB0_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15__SHIFT 0x0000000a
+#define PB0_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15_MASK 0x00001000L
+#define PB0_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15__SHIFT 0x0000000c
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15_MASK 0x00000008L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15__SHIFT 0x00000003
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15_MASK 0x00000080L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15__SHIFT 0x00000007
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15_MASK 0x00000100L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15__SHIFT 0x00000008
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15_MASK 0x00000200L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15__SHIFT 0x00000009
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15_MASK 0x00000070L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15__SHIFT 0x00000004
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15_MASK 0x00000007L
+#define PB0_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15__SHIFT 0x00000000
+#define PB0_RX_LANE1_CTRL_REG0__RX_BACKUP_1_MASK 0x000000ffL
+#define PB0_RX_LANE1_CTRL_REG0__RX_BACKUP_1__SHIFT 0x00000000
+#define PB0_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1_MASK 0x00002000L
+#define PB0_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1__SHIFT 0x0000000d
+#define PB0_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1_MASK 0x00000c00L
+#define PB0_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1__SHIFT 0x0000000a
+#define PB0_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1_MASK 0x00001000L
+#define PB0_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1__SHIFT 0x0000000c
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1_MASK 0x00000008L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1__SHIFT 0x00000003
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1_MASK 0x00000080L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1__SHIFT 0x00000007
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1_MASK 0x00000100L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1__SHIFT 0x00000008
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1_MASK 0x00000200L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1__SHIFT 0x00000009
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1_MASK 0x00000070L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1__SHIFT 0x00000004
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1_MASK 0x00000007L
+#define PB0_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1__SHIFT 0x00000000
+#define PB0_RX_LANE2_CTRL_REG0__RX_BACKUP_2_MASK 0x000000ffL
+#define PB0_RX_LANE2_CTRL_REG0__RX_BACKUP_2__SHIFT 0x00000000
+#define PB0_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2_MASK 0x00002000L
+#define PB0_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2__SHIFT 0x0000000d
+#define PB0_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2_MASK 0x00000c00L
+#define PB0_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2__SHIFT 0x0000000a
+#define PB0_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2_MASK 0x00001000L
+#define PB0_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2__SHIFT 0x0000000c
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2_MASK 0x00000008L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2__SHIFT 0x00000003
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2_MASK 0x00000080L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2__SHIFT 0x00000007
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2_MASK 0x00000100L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2__SHIFT 0x00000008
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2_MASK 0x00000200L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2__SHIFT 0x00000009
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2_MASK 0x00000070L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2__SHIFT 0x00000004
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2_MASK 0x00000007L
+#define PB0_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2__SHIFT 0x00000000
+#define PB0_RX_LANE3_CTRL_REG0__RX_BACKUP_3_MASK 0x000000ffL
+#define PB0_RX_LANE3_CTRL_REG0__RX_BACKUP_3__SHIFT 0x00000000
+#define PB0_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3_MASK 0x00002000L
+#define PB0_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3__SHIFT 0x0000000d
+#define PB0_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3_MASK 0x00000c00L
+#define PB0_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3__SHIFT 0x0000000a
+#define PB0_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3_MASK 0x00001000L
+#define PB0_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3__SHIFT 0x0000000c
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3_MASK 0x00000008L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3__SHIFT 0x00000003
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3_MASK 0x00000080L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3__SHIFT 0x00000007
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3_MASK 0x00000100L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3__SHIFT 0x00000008
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3_MASK 0x00000200L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3__SHIFT 0x00000009
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3_MASK 0x00000070L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3__SHIFT 0x00000004
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3_MASK 0x00000007L
+#define PB0_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3__SHIFT 0x00000000
+#define PB0_RX_LANE4_CTRL_REG0__RX_BACKUP_4_MASK 0x000000ffL
+#define PB0_RX_LANE4_CTRL_REG0__RX_BACKUP_4__SHIFT 0x00000000
+#define PB0_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4_MASK 0x00002000L
+#define PB0_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4__SHIFT 0x0000000d
+#define PB0_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4_MASK 0x00000c00L
+#define PB0_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4__SHIFT 0x0000000a
+#define PB0_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4_MASK 0x00001000L
+#define PB0_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4__SHIFT 0x0000000c
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4_MASK 0x00000008L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4__SHIFT 0x00000003
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4_MASK 0x00000080L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4__SHIFT 0x00000007
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4_MASK 0x00000100L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4__SHIFT 0x00000008
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4_MASK 0x00000200L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4__SHIFT 0x00000009
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4_MASK 0x00000070L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4__SHIFT 0x00000004
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4_MASK 0x00000007L
+#define PB0_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4__SHIFT 0x00000000
+#define PB0_RX_LANE5_CTRL_REG0__RX_BACKUP_5_MASK 0x000000ffL
+#define PB0_RX_LANE5_CTRL_REG0__RX_BACKUP_5__SHIFT 0x00000000
+#define PB0_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5_MASK 0x00002000L
+#define PB0_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5__SHIFT 0x0000000d
+#define PB0_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5_MASK 0x00000c00L
+#define PB0_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5__SHIFT 0x0000000a
+#define PB0_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5_MASK 0x00001000L
+#define PB0_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5__SHIFT 0x0000000c
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5_MASK 0x00000008L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5__SHIFT 0x00000003
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5_MASK 0x00000080L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5__SHIFT 0x00000007
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5_MASK 0x00000100L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5__SHIFT 0x00000008
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5_MASK 0x00000200L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5__SHIFT 0x00000009
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5_MASK 0x00000070L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5__SHIFT 0x00000004
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5_MASK 0x00000007L
+#define PB0_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5__SHIFT 0x00000000
+#define PB0_RX_LANE6_CTRL_REG0__RX_BACKUP_6_MASK 0x000000ffL
+#define PB0_RX_LANE6_CTRL_REG0__RX_BACKUP_6__SHIFT 0x00000000
+#define PB0_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6_MASK 0x00002000L
+#define PB0_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6__SHIFT 0x0000000d
+#define PB0_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6_MASK 0x00000c00L
+#define PB0_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6__SHIFT 0x0000000a
+#define PB0_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6_MASK 0x00001000L
+#define PB0_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6__SHIFT 0x0000000c
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6_MASK 0x00000008L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6__SHIFT 0x00000003
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6_MASK 0x00000080L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6__SHIFT 0x00000007
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6_MASK 0x00000100L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6__SHIFT 0x00000008
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6_MASK 0x00000200L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6__SHIFT 0x00000009
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6_MASK 0x00000070L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6__SHIFT 0x00000004
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6_MASK 0x00000007L
+#define PB0_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6__SHIFT 0x00000000
+#define PB0_RX_LANE7_CTRL_REG0__RX_BACKUP_7_MASK 0x000000ffL
+#define PB0_RX_LANE7_CTRL_REG0__RX_BACKUP_7__SHIFT 0x00000000
+#define PB0_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7_MASK 0x00002000L
+#define PB0_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7__SHIFT 0x0000000d
+#define PB0_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7_MASK 0x00000c00L
+#define PB0_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7__SHIFT 0x0000000a
+#define PB0_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7_MASK 0x00001000L
+#define PB0_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7__SHIFT 0x0000000c
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7_MASK 0x00000008L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7__SHIFT 0x00000003
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7_MASK 0x00000080L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7__SHIFT 0x00000007
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7_MASK 0x00000100L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7__SHIFT 0x00000008
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7_MASK 0x00000200L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7__SHIFT 0x00000009
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7_MASK 0x00000070L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7__SHIFT 0x00000004
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7_MASK 0x00000007L
+#define PB0_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7__SHIFT 0x00000000
+#define PB0_RX_LANE8_CTRL_REG0__RX_BACKUP_8_MASK 0x000000ffL
+#define PB0_RX_LANE8_CTRL_REG0__RX_BACKUP_8__SHIFT 0x00000000
+#define PB0_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8_MASK 0x00002000L
+#define PB0_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8__SHIFT 0x0000000d
+#define PB0_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8_MASK 0x00000c00L
+#define PB0_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8__SHIFT 0x0000000a
+#define PB0_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8_MASK 0x00001000L
+#define PB0_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8__SHIFT 0x0000000c
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8_MASK 0x00000008L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8__SHIFT 0x00000003
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8_MASK 0x00000080L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8__SHIFT 0x00000007
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8_MASK 0x00000100L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8__SHIFT 0x00000008
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8_MASK 0x00000200L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8__SHIFT 0x00000009
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8_MASK 0x00000070L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8__SHIFT 0x00000004
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8_MASK 0x00000007L
+#define PB0_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8__SHIFT 0x00000000
+#define PB0_RX_LANE9_CTRL_REG0__RX_BACKUP_9_MASK 0x000000ffL
+#define PB0_RX_LANE9_CTRL_REG0__RX_BACKUP_9__SHIFT 0x00000000
+#define PB0_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9_MASK 0x00002000L
+#define PB0_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9__SHIFT 0x0000000d
+#define PB0_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9_MASK 0x00000c00L
+#define PB0_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9__SHIFT 0x0000000a
+#define PB0_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9_MASK 0x00001000L
+#define PB0_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9__SHIFT 0x0000000c
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9_MASK 0x00000008L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9__SHIFT 0x00000003
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9_MASK 0x00000080L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9__SHIFT 0x00000007
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9_MASK 0x00000100L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9__SHIFT 0x00000008
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9_MASK 0x00000200L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9__SHIFT 0x00000009
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9_MASK 0x00000070L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9__SHIFT 0x00000004
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9_MASK 0x00000007L
+#define PB0_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9__SHIFT 0x00000000
+#define PB0_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL_MASK 0x00008000L
+#define PB0_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14_MASK 0x00004000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14__SHIFT 0x0000000e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15_MASK 0x00008000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16_MASK 0x00010000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16__SHIFT 0x00000010
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17_MASK 0x00020000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17__SHIFT 0x00000011
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18_MASK 0x00040000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18__SHIFT 0x00000012
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19_MASK 0x00080000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19__SHIFT 0x00000013
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20_MASK 0x00100000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20__SHIFT 0x00000014
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21_MASK 0x00200000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21__SHIFT 0x00000015
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22_MASK 0x00400000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22__SHIFT 0x00000016
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23_MASK 0x00800000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23__SHIFT 0x00000017
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24_MASK 0x01000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24__SHIFT 0x00000018
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25_MASK 0x02000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25__SHIFT 0x00000019
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26_MASK 0x04000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26__SHIFT 0x0000001a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27_MASK 0x08000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27__SHIFT 0x0000001b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28_MASK 0x10000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28__SHIFT 0x0000001c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29_MASK 0x20000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29__SHIFT 0x0000001d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30_MASK 0x40000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30__SHIFT 0x0000001e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31_MASK 0x80000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31__SHIFT 0x0000001f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3__SHIFT 0x00000003
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35__SHIFT 0x00000003
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46_MASK 0x00004000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46__SHIFT 0x0000000e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47_MASK 0x00008000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48_MASK 0x00010000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48__SHIFT 0x00000010
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49_MASK 0x00020000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49__SHIFT 0x00000011
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50_MASK 0x00040000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50__SHIFT 0x00000012
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51_MASK 0x00080000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51__SHIFT 0x00000013
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52_MASK 0x00100000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52__SHIFT 0x00000014
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53_MASK 0x00200000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53__SHIFT 0x00000015
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54_MASK 0x00400000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54__SHIFT 0x00000016
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55_MASK 0x00800000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55__SHIFT 0x00000017
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56_MASK 0x01000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56__SHIFT 0x00000018
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57_MASK 0x02000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57__SHIFT 0x00000019
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58_MASK 0x04000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58__SHIFT 0x0000001a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59_MASK 0x08000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59__SHIFT 0x0000001b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60_MASK 0x10000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60__SHIFT 0x0000001c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61_MASK 0x20000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61__SHIFT 0x0000001d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62_MASK 0x40000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62__SHIFT 0x0000001e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63_MASK 0x80000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63__SHIFT 0x0000001f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67__SHIFT 0x00000003
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78_MASK 0x00004000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78__SHIFT 0x0000000e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79_MASK 0x00008000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79__SHIFT 0x0000000f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80_MASK 0x00010000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80__SHIFT 0x00000010
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81_MASK 0x00020000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81__SHIFT 0x00000011
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82_MASK 0x00040000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82__SHIFT 0x00000012
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83_MASK 0x00080000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83__SHIFT 0x00000013
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84_MASK 0x00100000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84__SHIFT 0x00000014
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85_MASK 0x00200000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85__SHIFT 0x00000015
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86_MASK 0x00400000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86__SHIFT 0x00000016
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87_MASK 0x00800000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87__SHIFT 0x00000017
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88_MASK 0x01000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88__SHIFT 0x00000018
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89_MASK 0x02000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89__SHIFT 0x00000019
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90_MASK 0x04000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90__SHIFT 0x0000001a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91_MASK 0x08000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91__SHIFT 0x0000001b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92_MASK 0x10000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92__SHIFT 0x0000001c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93_MASK 0x20000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93__SHIFT 0x0000001d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94_MASK 0x40000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94__SHIFT 0x0000001e
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95_MASK 0x80000000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95__SHIFT 0x0000001f
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100_MASK 0x00000010L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100__SHIFT 0x00000004
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101_MASK 0x00000020L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101__SHIFT 0x00000005
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102_MASK 0x00000040L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102__SHIFT 0x00000006
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103_MASK 0x00000080L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103__SHIFT 0x00000007
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104_MASK 0x00000100L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104__SHIFT 0x00000008
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105_MASK 0x00000200L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105__SHIFT 0x00000009
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106_MASK 0x00000400L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106__SHIFT 0x0000000a
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107_MASK 0x00000800L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107__SHIFT 0x0000000b
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108_MASK 0x00001000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108__SHIFT 0x0000000c
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109_MASK 0x00002000L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109__SHIFT 0x0000000d
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96_MASK 0x00000001L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96__SHIFT 0x00000000
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97_MASK 0x00000002L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97__SHIFT 0x00000001
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98_MASK 0x00000004L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98__SHIFT 0x00000002
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99_MASK 0x00000008L
+#define PB0_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99__SHIFT 0x00000003
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1_MASK 0x00000700L
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1__SHIFT 0x00000008
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2_MASK 0x00003800L
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2__SHIFT 0x0000000b
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3_MASK 0x0001c000L
+#define PB0_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3__SHIFT 0x0000000e
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER_MASK 0x00400000L
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER__SHIFT 0x00000016
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN_MASK 0x00200000L
+#define PB0_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN__SHIFT 0x00000015
+#define PB0_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING_MASK 0x00080000L
+#define PB0_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING__SHIFT 0x00000013
+#define PB0_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON_MASK 0x00800000L
+#define PB0_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON__SHIFT 0x00000017
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL_MASK 0x00000007L
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL_MASK 0x00000038L
+#define PB0_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL__SHIFT 0x00000003
+#define PB0_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF_MASK 0x01000000L
+#define PB0_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF__SHIFT 0x00000018
+#define PB0_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS_MASK 0x00100000L
+#define PB0_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS__SHIFT 0x00000014
+#define PB0_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL_MASK 0x00060000L
+#define PB0_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL__SHIFT 0x00000011
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15_MASK 0x40000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15__SHIFT 0x0000001e
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0_MASK 0x00000001L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0__SHIFT 0x00000000
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10_MASK 0x00000400L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10__SHIFT 0x0000000a
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11_MASK 0x00000800L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11__SHIFT 0x0000000b
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12_MASK 0x00001000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12__SHIFT 0x0000000c
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13_MASK 0x00002000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13__SHIFT 0x0000000d
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14_MASK 0x00004000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14__SHIFT 0x0000000e
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15_MASK 0x00008000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15__SHIFT 0x0000000f
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1_MASK 0x00000002L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1__SHIFT 0x00000001
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2_MASK 0x00000004L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2__SHIFT 0x00000002
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3_MASK 0x00000008L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3__SHIFT 0x00000003
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4_MASK 0x00000010L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4__SHIFT 0x00000004
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5_MASK 0x00000020L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5__SHIFT 0x00000005
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6_MASK 0x00000040L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6__SHIFT 0x00000006
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7_MASK 0x00000080L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7__SHIFT 0x00000007
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8_MASK 0x00000100L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8__SHIFT 0x00000008
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9_MASK 0x00000200L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9__SHIFT 0x00000009
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1_MASK 0x00010000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1__SHIFT 0x00000010
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11_MASK 0x00200000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11__SHIFT 0x00000015
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13_MASK 0x00400000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13__SHIFT 0x00000016
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15_MASK 0x00800000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15__SHIFT 0x00000017
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3_MASK 0x00020000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3__SHIFT 0x00000011
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5_MASK 0x00040000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5__SHIFT 0x00000012
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7_MASK 0x00080000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7__SHIFT 0x00000013
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9_MASK 0x00100000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9__SHIFT 0x00000014
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3_MASK 0x01000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3__SHIFT 0x00000018
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15_MASK 0x08000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15__SHIFT 0x0000001b
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7_MASK 0x02000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7__SHIFT 0x00000019
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11_MASK 0x04000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11__SHIFT 0x0000001a
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7_MASK 0x10000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7__SHIFT 0x0000001c
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15_MASK 0x20000000L
+#define PB0_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15__SHIFT 0x0000001d
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000008L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000003
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x00000007L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL_MASK 0x000000f0L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00001e00L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN_MASK 0x00002000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN__SHIFT 0x0000000d
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL_MASK 0x0007c000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL__SHIFT 0x0000000e
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN_MASK 0x00080000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN__SHIFT 0x00000013
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL_MASK 0x01f00000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000014
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN_MASK 0x02000000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN__SHIFT 0x00000019
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL_MASK 0x3c000000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL__SHIFT 0x0000001a
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN_MASK 0x40000000L
+#define PB0_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN__SHIFT 0x0000001e
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL_MASK 0x0000000fL
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN_MASK 0x00000010L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL_MASK 0x00000020L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL__SHIFT 0x00000005
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN_MASK 0x00000040L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN__SHIFT 0x00000006
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00000080L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000007
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00000400L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000a
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000200L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN_MASK 0x00001000L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN__SHIFT 0x0000000c
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL_MASK 0x00000800L
+#define PB0_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL__SHIFT 0x0000000b
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN_MASK 0x00004000L
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN__SHIFT 0x0000000e
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL_MASK 0x00002000L
+#define PB0_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL__SHIFT 0x0000000d
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN_MASK 0x02000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN__SHIFT 0x00000019
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL_MASK 0x01ff8000L
+#define PB0_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL__SHIFT 0x0000000f
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN_MASK 0x08000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN__SHIFT 0x0000001b
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL_MASK 0x04000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL__SHIFT 0x0000001a
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN_MASK 0x20000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN__SHIFT 0x0000001d
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL_MASK 0x10000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL__SHIFT 0x0000001c
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN_MASK 0x80000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN__SHIFT 0x0000001f
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL_MASK 0x40000000L
+#define PB0_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL__SHIFT 0x0000001e
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL_MASK 0x0000f000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL__SHIFT 0x0000000c
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000f0000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000010
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL_MASK 0x01f00000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL__SHIFT 0x00000014
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL_MASK 0x3e000000L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000019
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN_MASK 0x00000800L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN__SHIFT 0x0000000b
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL_MASK 0x00000400L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL__SHIFT 0x0000000a
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN_MASK 0x00000008L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN__SHIFT 0x00000003
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL_MASK 0x00000004L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL__SHIFT 0x00000002
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN_MASK 0x00000020L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN__SHIFT 0x00000005
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL_MASK 0x00000010L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN_MASK 0x00000080L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN__SHIFT 0x00000007
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL_MASK 0x00000040L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL__SHIFT 0x00000006
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN_MASK 0x00000200L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN_MASK 0x00000002L
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN__SHIFT 0x00000001
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL_MASK 0x00000001L
+#define PB0_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL_MASK 0x00003c00L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL__SHIFT 0x0000000a
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0003c000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x0000000e
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL_MASK 0x007c0000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL__SHIFT 0x00000012
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0f800000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000017
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL_MASK 0x0000000fL
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL_MASK 0xf0000000L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL__SHIFT 0x0000001c
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000000f0L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL_MASK 0x00000100L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL__SHIFT 0x00000008
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL_MASK 0x00000200L
+#define PB0_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000009
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0000000fL
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000000
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL_MASK 0x00000010L
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL__SHIFT 0x00000004
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL_MASK 0x00000020L
+#define PB0_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000005
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB0_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0_MASK 0x00000001L
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0__SHIFT 0x00000000
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0_MASK 0x00000002L
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0__SHIFT 0x00000001
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0_MASK 0x00000004L
+#define PB0_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0__SHIFT 0x00000002
+#define PB0_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0_MASK 0x00000008L
+#define PB0_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0__SHIFT 0x00000003
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0_MASK 0x00000002L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0__SHIFT 0x00000001
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0_MASK 0x00000001L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0__SHIFT 0x00000000
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0_MASK 0x00000008L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0__SHIFT 0x00000003
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0_MASK 0x00000004L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0__SHIFT 0x00000002
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0_MASK 0x00000020L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0__SHIFT 0x00000005
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0_MASK 0x00000010L
+#define PB0_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0__SHIFT 0x00000004
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0_MASK 0x00000080L
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0__SHIFT 0x00000007
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0_MASK 0x00000040L
+#define PB0_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0__SHIFT 0x00000006
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0_MASK 0x0000fc00L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0__SHIFT 0x0000000a
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0_MASK 0x00000300L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0__SHIFT 0x00000008
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0_MASK 0x00000080L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0__SHIFT 0x00000007
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0_MASK 0x00000008L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0__SHIFT 0x00000003
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0_MASK 0x00000070L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0__SHIFT 0x00000004
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0_MASK 0x00000007L
+#define PB0_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0__SHIFT 0x00000000
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10_MASK 0x00000001L
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10__SHIFT 0x00000000
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10_MASK 0x00000002L
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10__SHIFT 0x00000001
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10_MASK 0x00000004L
+#define PB0_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10__SHIFT 0x00000002
+#define PB0_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10_MASK 0x00000008L
+#define PB0_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10__SHIFT 0x00000003
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10_MASK 0x00000002L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10__SHIFT 0x00000001
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10_MASK 0x00000001L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10__SHIFT 0x00000000
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10_MASK 0x00000008L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10__SHIFT 0x00000003
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10_MASK 0x00000004L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10__SHIFT 0x00000002
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10_MASK 0x00000020L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10__SHIFT 0x00000005
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10_MASK 0x00000010L
+#define PB0_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10__SHIFT 0x00000004
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10_MASK 0x00000080L
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10__SHIFT 0x00000007
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10_MASK 0x00000040L
+#define PB0_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10__SHIFT 0x00000006
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10_MASK 0x0000fc00L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10__SHIFT 0x0000000a
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10_MASK 0x00000300L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10__SHIFT 0x00000008
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10_MASK 0x00000080L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10__SHIFT 0x00000007
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10_MASK 0x00000008L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10__SHIFT 0x00000003
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10_MASK 0x00000070L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10__SHIFT 0x00000004
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10_MASK 0x00000007L
+#define PB0_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10__SHIFT 0x00000000
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11_MASK 0x00000001L
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11__SHIFT 0x00000000
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11_MASK 0x00000002L
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11__SHIFT 0x00000001
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11_MASK 0x00000004L
+#define PB0_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11__SHIFT 0x00000002
+#define PB0_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11_MASK 0x00000008L
+#define PB0_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11__SHIFT 0x00000003
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11_MASK 0x00000002L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11__SHIFT 0x00000001
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11_MASK 0x00000001L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11__SHIFT 0x00000000
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11_MASK 0x00000008L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11__SHIFT 0x00000003
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11_MASK 0x00000004L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11__SHIFT 0x00000002
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11_MASK 0x00000020L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11__SHIFT 0x00000005
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11_MASK 0x00000010L
+#define PB0_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11__SHIFT 0x00000004
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11_MASK 0x00000080L
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11__SHIFT 0x00000007
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11_MASK 0x00000040L
+#define PB0_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11__SHIFT 0x00000006
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11_MASK 0x0000fc00L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11__SHIFT 0x0000000a
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11_MASK 0x00000300L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11__SHIFT 0x00000008
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11_MASK 0x00000080L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11__SHIFT 0x00000007
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11_MASK 0x00000008L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11__SHIFT 0x00000003
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11_MASK 0x00000070L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11__SHIFT 0x00000004
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11_MASK 0x00000007L
+#define PB0_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11__SHIFT 0x00000000
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12_MASK 0x00000001L
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12__SHIFT 0x00000000
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12_MASK 0x00000002L
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12__SHIFT 0x00000001
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12_MASK 0x00000004L
+#define PB0_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12__SHIFT 0x00000002
+#define PB0_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12_MASK 0x00000008L
+#define PB0_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12__SHIFT 0x00000003
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12_MASK 0x00000002L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12__SHIFT 0x00000001
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12_MASK 0x00000001L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12__SHIFT 0x00000000
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12_MASK 0x00000008L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12__SHIFT 0x00000003
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12_MASK 0x00000004L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12__SHIFT 0x00000002
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12_MASK 0x00000020L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12__SHIFT 0x00000005
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12_MASK 0x00000010L
+#define PB0_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12__SHIFT 0x00000004
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12_MASK 0x00000080L
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12__SHIFT 0x00000007
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12_MASK 0x00000040L
+#define PB0_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12__SHIFT 0x00000006
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12_MASK 0x0000fc00L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12__SHIFT 0x0000000a
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12_MASK 0x00000300L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12__SHIFT 0x00000008
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12_MASK 0x00000080L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12__SHIFT 0x00000007
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12_MASK 0x00000008L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12__SHIFT 0x00000003
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12_MASK 0x00000070L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12__SHIFT 0x00000004
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12_MASK 0x00000007L
+#define PB0_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12__SHIFT 0x00000000
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13_MASK 0x00000001L
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13__SHIFT 0x00000000
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13_MASK 0x00000002L
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13__SHIFT 0x00000001
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13_MASK 0x00000004L
+#define PB0_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13__SHIFT 0x00000002
+#define PB0_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13_MASK 0x00000008L
+#define PB0_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13__SHIFT 0x00000003
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13_MASK 0x00000002L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13__SHIFT 0x00000001
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13_MASK 0x00000001L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13__SHIFT 0x00000000
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13_MASK 0x00000008L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13__SHIFT 0x00000003
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13_MASK 0x00000004L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13__SHIFT 0x00000002
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13_MASK 0x00000020L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13__SHIFT 0x00000005
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13_MASK 0x00000010L
+#define PB0_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13__SHIFT 0x00000004
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13_MASK 0x00000080L
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13__SHIFT 0x00000007
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13_MASK 0x00000040L
+#define PB0_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13__SHIFT 0x00000006
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13_MASK 0x0000fc00L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13__SHIFT 0x0000000a
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13_MASK 0x00000300L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13__SHIFT 0x00000008
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13_MASK 0x00000080L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13__SHIFT 0x00000007
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13_MASK 0x00000008L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13__SHIFT 0x00000003
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13_MASK 0x00000070L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13__SHIFT 0x00000004
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13_MASK 0x00000007L
+#define PB0_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13__SHIFT 0x00000000
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14_MASK 0x00000001L
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14__SHIFT 0x00000000
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14_MASK 0x00000002L
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14__SHIFT 0x00000001
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14_MASK 0x00000004L
+#define PB0_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14__SHIFT 0x00000002
+#define PB0_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14_MASK 0x00000008L
+#define PB0_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14__SHIFT 0x00000003
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14_MASK 0x00000002L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14__SHIFT 0x00000001
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14_MASK 0x00000001L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14__SHIFT 0x00000000
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14_MASK 0x00000008L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14__SHIFT 0x00000003
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14_MASK 0x00000004L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14__SHIFT 0x00000002
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14_MASK 0x00000020L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14__SHIFT 0x00000005
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14_MASK 0x00000010L
+#define PB0_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14__SHIFT 0x00000004
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14_MASK 0x00000080L
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14__SHIFT 0x00000007
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14_MASK 0x00000040L
+#define PB0_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14__SHIFT 0x00000006
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14_MASK 0x0000fc00L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14__SHIFT 0x0000000a
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14_MASK 0x00000300L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14__SHIFT 0x00000008
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14_MASK 0x00000080L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14__SHIFT 0x00000007
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14_MASK 0x00000008L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14__SHIFT 0x00000003
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14_MASK 0x00000070L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14__SHIFT 0x00000004
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14_MASK 0x00000007L
+#define PB0_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14__SHIFT 0x00000000
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15_MASK 0x00000001L
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15__SHIFT 0x00000000
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15_MASK 0x00000002L
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15__SHIFT 0x00000001
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15_MASK 0x00000004L
+#define PB0_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15__SHIFT 0x00000002
+#define PB0_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15_MASK 0x00000008L
+#define PB0_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15__SHIFT 0x00000003
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15_MASK 0x00000002L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15__SHIFT 0x00000001
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15_MASK 0x00000001L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15__SHIFT 0x00000000
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15_MASK 0x00000008L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15__SHIFT 0x00000003
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15_MASK 0x00000004L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15__SHIFT 0x00000002
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15_MASK 0x00000020L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15__SHIFT 0x00000005
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15_MASK 0x00000010L
+#define PB0_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15__SHIFT 0x00000004
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15_MASK 0x00000080L
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15__SHIFT 0x00000007
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15_MASK 0x00000040L
+#define PB0_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15__SHIFT 0x00000006
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15_MASK 0x0000fc00L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15__SHIFT 0x0000000a
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15_MASK 0x00000300L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15__SHIFT 0x00000008
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15_MASK 0x00000080L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15__SHIFT 0x00000007
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15_MASK 0x00000008L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15__SHIFT 0x00000003
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15_MASK 0x00000070L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15__SHIFT 0x00000004
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15_MASK 0x00000007L
+#define PB0_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15__SHIFT 0x00000000
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1_MASK 0x00000001L
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1__SHIFT 0x00000000
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1_MASK 0x00000002L
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1__SHIFT 0x00000001
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1_MASK 0x00000004L
+#define PB0_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1__SHIFT 0x00000002
+#define PB0_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1_MASK 0x00000008L
+#define PB0_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1__SHIFT 0x00000003
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1_MASK 0x00000002L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1__SHIFT 0x00000001
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1_MASK 0x00000001L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1__SHIFT 0x00000000
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1_MASK 0x00000008L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1__SHIFT 0x00000003
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1_MASK 0x00000004L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1__SHIFT 0x00000002
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1_MASK 0x00000020L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1__SHIFT 0x00000005
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1_MASK 0x00000010L
+#define PB0_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1__SHIFT 0x00000004
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1_MASK 0x00000080L
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1__SHIFT 0x00000007
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1_MASK 0x00000040L
+#define PB0_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1__SHIFT 0x00000006
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1_MASK 0x0000fc00L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1__SHIFT 0x0000000a
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1_MASK 0x00000300L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1__SHIFT 0x00000008
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1_MASK 0x00000080L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1__SHIFT 0x00000007
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1_MASK 0x00000008L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1__SHIFT 0x00000003
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1_MASK 0x00000070L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1__SHIFT 0x00000004
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1_MASK 0x00000007L
+#define PB0_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1__SHIFT 0x00000000
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2_MASK 0x00000001L
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2__SHIFT 0x00000000
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2_MASK 0x00000002L
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2__SHIFT 0x00000001
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2_MASK 0x00000004L
+#define PB0_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2__SHIFT 0x00000002
+#define PB0_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2_MASK 0x00000008L
+#define PB0_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2__SHIFT 0x00000003
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2_MASK 0x00000002L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2__SHIFT 0x00000001
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2_MASK 0x00000001L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2__SHIFT 0x00000000
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2_MASK 0x00000008L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2__SHIFT 0x00000003
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2_MASK 0x00000004L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2__SHIFT 0x00000002
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2_MASK 0x00000020L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2__SHIFT 0x00000005
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2_MASK 0x00000010L
+#define PB0_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2__SHIFT 0x00000004
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2_MASK 0x00000080L
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2__SHIFT 0x00000007
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2_MASK 0x00000040L
+#define PB0_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2__SHIFT 0x00000006
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2_MASK 0x0000fc00L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2__SHIFT 0x0000000a
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2_MASK 0x00000300L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2__SHIFT 0x00000008
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2_MASK 0x00000080L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2__SHIFT 0x00000007
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2_MASK 0x00000008L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2__SHIFT 0x00000003
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2_MASK 0x00000070L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2__SHIFT 0x00000004
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2_MASK 0x00000007L
+#define PB0_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2__SHIFT 0x00000000
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3_MASK 0x00000001L
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3__SHIFT 0x00000000
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3_MASK 0x00000002L
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3__SHIFT 0x00000001
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3_MASK 0x00000004L
+#define PB0_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3__SHIFT 0x00000002
+#define PB0_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3_MASK 0x00000008L
+#define PB0_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3__SHIFT 0x00000003
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3_MASK 0x00000002L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3__SHIFT 0x00000001
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3_MASK 0x00000001L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3__SHIFT 0x00000000
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3_MASK 0x00000008L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3__SHIFT 0x00000003
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3_MASK 0x00000004L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3__SHIFT 0x00000002
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3_MASK 0x00000020L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3__SHIFT 0x00000005
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3_MASK 0x00000010L
+#define PB0_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3__SHIFT 0x00000004
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3_MASK 0x00000080L
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3__SHIFT 0x00000007
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3_MASK 0x00000040L
+#define PB0_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3__SHIFT 0x00000006
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3_MASK 0x0000fc00L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3__SHIFT 0x0000000a
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3_MASK 0x00000300L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3__SHIFT 0x00000008
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3_MASK 0x00000080L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3__SHIFT 0x00000007
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3_MASK 0x00000008L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3__SHIFT 0x00000003
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3_MASK 0x00000070L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3__SHIFT 0x00000004
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3_MASK 0x00000007L
+#define PB0_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3__SHIFT 0x00000000
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4_MASK 0x00000001L
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4__SHIFT 0x00000000
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4_MASK 0x00000002L
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4__SHIFT 0x00000001
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4_MASK 0x00000004L
+#define PB0_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4__SHIFT 0x00000002
+#define PB0_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4_MASK 0x00000008L
+#define PB0_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4__SHIFT 0x00000003
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4_MASK 0x00000002L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4__SHIFT 0x00000001
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4_MASK 0x00000001L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4__SHIFT 0x00000000
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4_MASK 0x00000008L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4__SHIFT 0x00000003
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4_MASK 0x00000004L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4__SHIFT 0x00000002
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4_MASK 0x00000020L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4__SHIFT 0x00000005
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4_MASK 0x00000010L
+#define PB0_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4__SHIFT 0x00000004
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4_MASK 0x00000080L
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4__SHIFT 0x00000007
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4_MASK 0x00000040L
+#define PB0_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4__SHIFT 0x00000006
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4_MASK 0x0000fc00L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4__SHIFT 0x0000000a
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4_MASK 0x00000300L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4__SHIFT 0x00000008
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4_MASK 0x00000080L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4__SHIFT 0x00000007
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4_MASK 0x00000008L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4__SHIFT 0x00000003
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4_MASK 0x00000070L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4__SHIFT 0x00000004
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4_MASK 0x00000007L
+#define PB0_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4__SHIFT 0x00000000
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5_MASK 0x00000001L
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5__SHIFT 0x00000000
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5_MASK 0x00000002L
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5__SHIFT 0x00000001
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5_MASK 0x00000004L
+#define PB0_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5__SHIFT 0x00000002
+#define PB0_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5_MASK 0x00000008L
+#define PB0_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5__SHIFT 0x00000003
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5_MASK 0x00000002L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5__SHIFT 0x00000001
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5_MASK 0x00000001L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5__SHIFT 0x00000000
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5_MASK 0x00000008L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5__SHIFT 0x00000003
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5_MASK 0x00000004L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5__SHIFT 0x00000002
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5_MASK 0x00000020L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5__SHIFT 0x00000005
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5_MASK 0x00000010L
+#define PB0_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5__SHIFT 0x00000004
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5_MASK 0x00000080L
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5__SHIFT 0x00000007
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5_MASK 0x00000040L
+#define PB0_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5__SHIFT 0x00000006
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5_MASK 0x0000fc00L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5__SHIFT 0x0000000a
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5_MASK 0x00000300L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5__SHIFT 0x00000008
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5_MASK 0x00000080L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5__SHIFT 0x00000007
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5_MASK 0x00000008L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5__SHIFT 0x00000003
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5_MASK 0x00000070L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5__SHIFT 0x00000004
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5_MASK 0x00000007L
+#define PB0_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5__SHIFT 0x00000000
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6_MASK 0x00000001L
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6__SHIFT 0x00000000
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6_MASK 0x00000002L
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6__SHIFT 0x00000001
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6_MASK 0x00000004L
+#define PB0_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6__SHIFT 0x00000002
+#define PB0_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6_MASK 0x00000008L
+#define PB0_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6__SHIFT 0x00000003
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6_MASK 0x00000002L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6__SHIFT 0x00000001
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6_MASK 0x00000001L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6__SHIFT 0x00000000
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6_MASK 0x00000008L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6__SHIFT 0x00000003
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6_MASK 0x00000004L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6__SHIFT 0x00000002
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6_MASK 0x00000020L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6__SHIFT 0x00000005
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6_MASK 0x00000010L
+#define PB0_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6__SHIFT 0x00000004
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6_MASK 0x00000080L
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6__SHIFT 0x00000007
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6_MASK 0x00000040L
+#define PB0_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6__SHIFT 0x00000006
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6_MASK 0x0000fc00L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6__SHIFT 0x0000000a
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6_MASK 0x00000300L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6__SHIFT 0x00000008
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6_MASK 0x00000080L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6__SHIFT 0x00000007
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6_MASK 0x00000008L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6__SHIFT 0x00000003
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6_MASK 0x00000070L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6__SHIFT 0x00000004
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6_MASK 0x00000007L
+#define PB0_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6__SHIFT 0x00000000
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7_MASK 0x00000001L
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7__SHIFT 0x00000000
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7_MASK 0x00000002L
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7__SHIFT 0x00000001
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7_MASK 0x00000004L
+#define PB0_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7__SHIFT 0x00000002
+#define PB0_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7_MASK 0x00000008L
+#define PB0_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7__SHIFT 0x00000003
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7_MASK 0x00000002L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7__SHIFT 0x00000001
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7_MASK 0x00000001L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7__SHIFT 0x00000000
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7_MASK 0x00000008L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7__SHIFT 0x00000003
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7_MASK 0x00000004L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7__SHIFT 0x00000002
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7_MASK 0x00000020L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7__SHIFT 0x00000005
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7_MASK 0x00000010L
+#define PB0_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7__SHIFT 0x00000004
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7_MASK 0x00000080L
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7__SHIFT 0x00000007
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7_MASK 0x00000040L
+#define PB0_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7__SHIFT 0x00000006
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7_MASK 0x0000fc00L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7__SHIFT 0x0000000a
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7_MASK 0x00000300L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7__SHIFT 0x00000008
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7_MASK 0x00000080L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7__SHIFT 0x00000007
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7_MASK 0x00000008L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7__SHIFT 0x00000003
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7_MASK 0x00000070L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7__SHIFT 0x00000004
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7_MASK 0x00000007L
+#define PB0_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7__SHIFT 0x00000000
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8_MASK 0x00000001L
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8__SHIFT 0x00000000
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8_MASK 0x00000002L
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8__SHIFT 0x00000001
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8_MASK 0x00000004L
+#define PB0_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8__SHIFT 0x00000002
+#define PB0_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8_MASK 0x00000008L
+#define PB0_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8__SHIFT 0x00000003
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8_MASK 0x00000002L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8__SHIFT 0x00000001
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8_MASK 0x00000001L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8__SHIFT 0x00000000
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8_MASK 0x00000008L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8__SHIFT 0x00000003
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8_MASK 0x00000004L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8__SHIFT 0x00000002
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8_MASK 0x00000020L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8__SHIFT 0x00000005
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8_MASK 0x00000010L
+#define PB0_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8__SHIFT 0x00000004
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8_MASK 0x00000080L
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8__SHIFT 0x00000007
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8_MASK 0x00000040L
+#define PB0_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8__SHIFT 0x00000006
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8_MASK 0x0000fc00L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8__SHIFT 0x0000000a
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8_MASK 0x00000300L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8__SHIFT 0x00000008
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8_MASK 0x00000080L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8__SHIFT 0x00000007
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8_MASK 0x00000008L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8__SHIFT 0x00000003
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8_MASK 0x00000070L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8__SHIFT 0x00000004
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8_MASK 0x00000007L
+#define PB0_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8__SHIFT 0x00000000
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9_MASK 0x00000001L
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9__SHIFT 0x00000000
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9_MASK 0x00000002L
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9__SHIFT 0x00000001
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9_MASK 0x00000004L
+#define PB0_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9__SHIFT 0x00000002
+#define PB0_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9_MASK 0x00000008L
+#define PB0_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9__SHIFT 0x00000003
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9_MASK 0x00000002L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9__SHIFT 0x00000001
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9_MASK 0x00000001L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9__SHIFT 0x00000000
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9_MASK 0x00000008L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9__SHIFT 0x00000003
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9_MASK 0x00000004L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9__SHIFT 0x00000002
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9_MASK 0x00000020L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9__SHIFT 0x00000005
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9_MASK 0x00000010L
+#define PB0_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9__SHIFT 0x00000004
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9_MASK 0x00000080L
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9__SHIFT 0x00000007
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9_MASK 0x00000040L
+#define PB0_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9__SHIFT 0x00000006
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9_MASK 0x0000fc00L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9__SHIFT 0x0000000a
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9_MASK 0x00000300L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9__SHIFT 0x00000008
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9_MASK 0x00000080L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9__SHIFT 0x00000007
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9_MASK 0x00000008L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9__SHIFT 0x00000003
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9_MASK 0x00000070L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9__SHIFT 0x00000004
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9_MASK 0x00000007L
+#define PB0_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9__SHIFT 0x00000000
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN_MASK 0x00000001L
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_EN__SHIFT 0x00000000
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE_MASK 0x0000003eL
+#define PB1_DFT_DEBUG_CTRL_REG0__DFT_PHY_DEBUG_MODE__SHIFT 0x00000001
+#define PB1_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP_MASK 0x00000f00L
+#define PB1_DFT_JIT_INJ_REG0__DFT_CLK_PER_STEP__SHIFT 0x00000008
+#define PB1_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN_MASK 0x00800000L
+#define PB1_DFT_JIT_INJ_REG0__DFT_DECR_SWP_EN__SHIFT 0x00000017
+#define PB1_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN_MASK 0x00400000L
+#define PB1_DFT_JIT_INJ_REG0__DFT_INCR_SWP_EN__SHIFT 0x00000016
+#define PB1_DFT_JIT_INJ_REG0__DFT_NUM_STEPS_MASK 0x0000001fL
+#define PB1_DFT_JIT_INJ_REG0__DFT_NUM_STEPS__SHIFT 0x00000000
+#define PB1_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME_MASK 0xff000000L
+#define PB1_DFT_JIT_INJ_REG0__DFT_RECOVERY_TIME__SHIFT 0x00000018
+#define PB1_DFT_JIT_INJ_REG1__DFT_BLOCK_EN_MASK 0x00010000L
+#define PB1_DFT_JIT_INJ_REG1__DFT_BLOCK_EN__SHIFT 0x00000010
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_EN_MASK 0x00000100L
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_EN__SHIFT 0x00000008
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE_MASK 0x000000ffL
+#define PB1_DFT_JIT_INJ_REG1__DFT_BYPASS_VALUE__SHIFT 0x00000000
+#define PB1_DFT_JIT_INJ_REG2__DFT_LANE_EN_MASK 0x0000ffffL
+#define PB1_DFT_JIT_INJ_REG2__DFT_LANE_EN__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG0__BACKUP_MASK 0x0000ffffL
+#define PB1_GLB_CTRL_REG0__BACKUP__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG0__CFG_IDLEDET_TH_MASK 0x00030000L
+#define PB1_GLB_CTRL_REG0__CFG_IDLEDET_TH__SHIFT 0x00000010
+#define PB1_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL_MASK 0x00700000L
+#define PB1_GLB_CTRL_REG0__DBG_RX2TXBYP_SEL__SHIFT 0x00000014
+#define PB1_GLB_CTRL_REG0__DBG_RXFEBYP_EN_MASK 0x00800000L
+#define PB1_GLB_CTRL_REG0__DBG_RXFEBYP_EN__SHIFT 0x00000017
+#define PB1_GLB_CTRL_REG0__DBG_RXPRBS_CLR_MASK 0x01000000L
+#define PB1_GLB_CTRL_REG0__DBG_RXPRBS_CLR__SHIFT 0x00000018
+#define PB1_GLB_CTRL_REG0__DBG_RXTOGGLE_EN_MASK 0x02000000L
+#define PB1_GLB_CTRL_REG0__DBG_RXTOGGLE_EN__SHIFT 0x00000019
+#define PB1_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN_MASK 0x04000000L
+#define PB1_GLB_CTRL_REG0__DBG_TX2RXLBACK_EN__SHIFT 0x0000001a
+#define PB1_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE_MASK 0xc0000000L
+#define PB1_GLB_CTRL_REG0__TXCFG_CMGOOD_RANGE__SHIFT 0x0000001e
+#define PB1_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV_MASK 0x80000000L
+#define PB1_GLB_CTRL_REG1__PLL_CFG_DISPCLK_DIV__SHIFT 0x0000001f
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN_MASK 0x00000001L
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_EN__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL_MASK 0x0000007eL
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_FR_BYP_VAL__SHIFT 0x00000001
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN_MASK 0x00000080L
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_EN__SHIFT 0x00000007
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL_MASK 0x00003f00L
+#define PB1_GLB_CTRL_REG1__RXDBG_CDR_PH_BYP_VAL__SHIFT 0x00000008
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN_MASK 0x00004000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_EN__SHIFT 0x0000000e
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL_MASK 0x003f8000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D0TH_BYP_VAL__SHIFT 0x0000000f
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN_MASK 0x00400000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_EN__SHIFT 0x00000016
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL_MASK 0x3f800000L
+#define PB1_GLB_CTRL_REG1__RXDBG_D1TH_BYP_VAL__SHIFT 0x00000017
+#define PB1_GLB_CTRL_REG1__TST_LOSPDTST_EN_MASK 0x40000000L
+#define PB1_GLB_CTRL_REG1__TST_LOSPDTST_EN__SHIFT 0x0000001e
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN_MASK 0x00000001L
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_EN__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL_MASK 0x000000feL
+#define PB1_GLB_CTRL_REG2__RXDBG_D2TH_BYP_VAL__SHIFT 0x00000001
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN_MASK 0x00000100L
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_EN__SHIFT 0x00000008
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL_MASK 0x0000fe00L
+#define PB1_GLB_CTRL_REG2__RXDBG_D3TH_BYP_VAL__SHIFT 0x00000009
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN_MASK 0x00010000L
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_EN__SHIFT 0x00000010
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL_MASK 0x00fe0000L
+#define PB1_GLB_CTRL_REG2__RXDBG_DXTH_BYP_VAL__SHIFT 0x00000011
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN_MASK 0x01000000L
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_EN__SHIFT 0x00000018
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL_MASK 0xfe000000L
+#define PB1_GLB_CTRL_REG2__RXDBG_ETH_BYP_VAL__SHIFT 0x00000019
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL_MASK 0x00000060L
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF0_SEL__SHIFT 0x00000005
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL_MASK 0x00000180L
+#define PB1_GLB_CTRL_REG3__BG_CFG_LC_REG_VREF1_SEL__SHIFT 0x00000007
+#define PB1_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL_MASK 0x00000600L
+#define PB1_GLB_CTRL_REG3__BG_CFG_RO_REG_VREF_SEL__SHIFT 0x00000009
+#define PB1_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL_MASK 0x0001c000L
+#define PB1_GLB_CTRL_REG3__BG_DBG_ANALOG_SEL__SHIFT 0x0000000e
+#define PB1_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN_MASK 0x00001000L
+#define PB1_GLB_CTRL_REG3__BG_DBG_IREFBYP_EN__SHIFT 0x0000000c
+#define PB1_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN_MASK 0x00000800L
+#define PB1_GLB_CTRL_REG3__BG_DBG_VREFBYP_EN__SHIFT 0x0000000b
+#define PB1_GLB_CTRL_REG3__DBG_DLL_CLK_SEL_MASK 0x001c0000L
+#define PB1_GLB_CTRL_REG3__DBG_DLL_CLK_SEL__SHIFT 0x00000012
+#define PB1_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE_MASK 0x80000000L
+#define PB1_GLB_CTRL_REG3__DBG_RXLEQ_DCATTN_BYP_OVR_DISABLE__SHIFT 0x0000001f
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN_MASK 0x00400000L
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_EN__SHIFT 0x00000016
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL_MASK 0x07800000L
+#define PB1_GLB_CTRL_REG3__DBG_RXPI_OFFSET_BYP_VAL__SHIFT 0x00000017
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN_MASK 0x08000000L
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_EN__SHIFT 0x0000001b
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL_MASK 0x70000000L
+#define PB1_GLB_CTRL_REG3__DBG_RXSWAPDX_BYP_VAL__SHIFT 0x0000001c
+#define PB1_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL_MASK 0x00200000L
+#define PB1_GLB_CTRL_REG3__PLL_DISPCLK_CMOS_SEL__SHIFT 0x00000015
+#define PB1_GLB_CTRL_REG3__RXDBG_SEL_MASK 0x0000001fL
+#define PB1_GLB_CTRL_REG3__RXDBG_SEL__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_EXEC_MASK 0x03c00000L
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_EXEC__SHIFT 0x00000016
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_INST_MASK 0x0000ffffL
+#define PB1_GLB_CTRL_REG4__DBG_RXAPU_INST__SHIFT 0x00000000
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN_MASK 0x00040000L
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_EN__SHIFT 0x00000012
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL_MASK 0x00030000L
+#define PB1_GLB_CTRL_REG4__DBG_RXDFEMUX_BYP_VAL__SHIFT 0x00000010
+#define PB1_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL_MASK 0x04000000L
+#define PB1_GLB_CTRL_REG4__DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000001a
+#define PB1_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE_MASK 0x10000000L
+#define PB1_GLB_CTRL_REG4__DBG_RXRDATA_GATING_DISABLE__SHIFT 0x0000001c
+#define PB1_GLB_CTRL_REG4__PWRGOOD_OVRD_MASK 0x08000000L
+#define PB1_GLB_CTRL_REG4__PWRGOOD_OVRD__SHIFT 0x0000001b
+#define PB1_GLB_CTRL_REG5__DBG_RXAPU_MODE_MASK 0x000000ffL
+#define PB1_GLB_CTRL_REG5__DBG_RXAPU_MODE__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL_MASK 0x0000ffffL
+#define PB1_GLB_OVRD_REG0__TXPDTERM_VAL_OVRD_VAL__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB1_GLB_OVRD_REG0__TXPUTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN_MASK 0x00008000L
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_EN__SHIFT 0x0000000f
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL_MASK 0xffff0000L
+#define PB1_GLB_OVRD_REG1__RXTERM_VAL_OVRD_VAL__SHIFT 0x00000010
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN_MASK 0x00000004L
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_EN__SHIFT 0x00000002
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL_MASK 0x00000008L
+#define PB1_GLB_OVRD_REG1__TST_LOSPDTST_RST_OVRD_VAL__SHIFT 0x00000003
+#define PB1_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN_MASK 0x00000001L
+#define PB1_GLB_OVRD_REG1__TXPDTERM_VAL_OVRD_EN__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN_MASK 0x00000002L
+#define PB1_GLB_OVRD_REG1__TXPUTERM_VAL_OVRD_EN__SHIFT 0x00000001
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_EN_MASK 0x00000001L
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_EN__SHIFT 0x00000000
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL_MASK 0x00000002L
+#define PB1_GLB_OVRD_REG2__BG_PWRON_OVRD_VAL__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_ALL_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT_MASK 0x00000010L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IGNR_IMPCAL_ACTIVE_SCI_UPDT__SHIFT 0x00000004
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE_MASK 0x00100000L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__IMPCAL_ACTIVE__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG0__RXIMP_MASK 0x000f0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__RXIMP__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXNIMP_MASK 0x00000f00L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXNIMP__SHIFT 0x00000008
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXPIMP_MASK 0x0000f000L
+#define PB1_GLB_SCI_STAT_OVRD_REG0__TXPIMP__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_0__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_1__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_2__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__DLL_LOCK_3__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_0__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_1__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_2__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__FREQDIV_3__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_DLL_LOCK_SCI_UPDT_L0T3__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_FREQDIV_SCI_UPDT_L0T3__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__IGNR_MODE_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_0_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_0__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_1_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_1__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_2_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_2__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_3_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG1__MODE_3__SHIFT 0x0000001c
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_4__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_5__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_6__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__DLL_LOCK_7__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_4__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_5__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_6__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__FREQDIV_7__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_DLL_LOCK_SCI_UPDT_L4T7__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_FREQDIV_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__IGNR_MODE_SCI_UPDT_L4T7__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_4_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_4__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_5_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_5__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_6_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_6__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_7_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG2__MODE_7__SHIFT 0x0000001c
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_10__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_11__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_8__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__DLL_LOCK_9__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_10__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_11__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_8__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__FREQDIV_9__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_DLL_LOCK_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_FREQDIV_SCI_UPDT_L8T11__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__IGNR_MODE_SCI_UPDT_L8T11__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_10_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_10__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_11_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_11__SHIFT 0x0000001c
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_8_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_8__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_9_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG3__MODE_9__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12_MASK 0x00001000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_12__SHIFT 0x0000000c
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13_MASK 0x00002000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_13__SHIFT 0x0000000d
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14_MASK 0x00004000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_14__SHIFT 0x0000000e
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15_MASK 0x00008000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__DLL_LOCK_15__SHIFT 0x0000000f
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12_MASK 0x000c0000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_12__SHIFT 0x00000012
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13_MASK 0x00c00000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_13__SHIFT 0x00000016
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14_MASK 0x0c000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_14__SHIFT 0x0000001a
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15_MASK 0xc0000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__FREQDIV_15__SHIFT 0x0000001e
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15_MASK 0x00000004L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_DLL_LOCK_SCI_UPDT_L12T15__SHIFT 0x00000002
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15_MASK 0x00000002L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_FREQDIV_SCI_UPDT_L12T15__SHIFT 0x00000001
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15_MASK 0x00000001L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__IGNR_MODE_SCI_UPDT_L12T15__SHIFT 0x00000000
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_12_MASK 0x00030000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_12__SHIFT 0x00000010
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_13_MASK 0x00300000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_13__SHIFT 0x00000014
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_14_MASK 0x03000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_14__SHIFT 0x00000018
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_15_MASK 0x30000000L
+#define PB1_GLB_SCI_STAT_OVRD_REG4__MODE_15__SHIFT 0x0000001c
+#define PB1_HW_DEBUG__PB1_HW_00_DEBUG_MASK 0x00000001L
+#define PB1_HW_DEBUG__PB1_HW_00_DEBUG__SHIFT 0x00000000
+#define PB1_HW_DEBUG__PB1_HW_01_DEBUG_MASK 0x00000002L
+#define PB1_HW_DEBUG__PB1_HW_01_DEBUG__SHIFT 0x00000001
+#define PB1_HW_DEBUG__PB1_HW_02_DEBUG_MASK 0x00000004L
+#define PB1_HW_DEBUG__PB1_HW_02_DEBUG__SHIFT 0x00000002
+#define PB1_HW_DEBUG__PB1_HW_03_DEBUG_MASK 0x00000008L
+#define PB1_HW_DEBUG__PB1_HW_03_DEBUG__SHIFT 0x00000003
+#define PB1_HW_DEBUG__PB1_HW_04_DEBUG_MASK 0x00000010L
+#define PB1_HW_DEBUG__PB1_HW_04_DEBUG__SHIFT 0x00000004
+#define PB1_HW_DEBUG__PB1_HW_05_DEBUG_MASK 0x00000020L
+#define PB1_HW_DEBUG__PB1_HW_05_DEBUG__SHIFT 0x00000005
+#define PB1_HW_DEBUG__PB1_HW_06_DEBUG_MASK 0x00000040L
+#define PB1_HW_DEBUG__PB1_HW_06_DEBUG__SHIFT 0x00000006
+#define PB1_HW_DEBUG__PB1_HW_07_DEBUG_MASK 0x00000080L
+#define PB1_HW_DEBUG__PB1_HW_07_DEBUG__SHIFT 0x00000007
+#define PB1_HW_DEBUG__PB1_HW_08_DEBUG_MASK 0x00000100L
+#define PB1_HW_DEBUG__PB1_HW_08_DEBUG__SHIFT 0x00000008
+#define PB1_HW_DEBUG__PB1_HW_09_DEBUG_MASK 0x00000200L
+#define PB1_HW_DEBUG__PB1_HW_09_DEBUG__SHIFT 0x00000009
+#define PB1_HW_DEBUG__PB1_HW_10_DEBUG_MASK 0x00000400L
+#define PB1_HW_DEBUG__PB1_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB1_HW_DEBUG__PB1_HW_11_DEBUG_MASK 0x00000800L
+#define PB1_HW_DEBUG__PB1_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB1_HW_DEBUG__PB1_HW_12_DEBUG_MASK 0x00001000L
+#define PB1_HW_DEBUG__PB1_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB1_HW_DEBUG__PB1_HW_13_DEBUG_MASK 0x00002000L
+#define PB1_HW_DEBUG__PB1_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB1_HW_DEBUG__PB1_HW_14_DEBUG_MASK 0x00004000L
+#define PB1_HW_DEBUG__PB1_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB1_HW_DEBUG__PB1_HW_15_DEBUG_MASK 0x00008000L
+#define PB1_HW_DEBUG__PB1_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB1_HW_DEBUG__PB1_HW_16_DEBUG_MASK 0x00010000L
+#define PB1_HW_DEBUG__PB1_HW_16_DEBUG__SHIFT 0x00000010
+#define PB1_HW_DEBUG__PB1_HW_17_DEBUG_MASK 0x00020000L
+#define PB1_HW_DEBUG__PB1_HW_17_DEBUG__SHIFT 0x00000011
+#define PB1_HW_DEBUG__PB1_HW_18_DEBUG_MASK 0x00040000L
+#define PB1_HW_DEBUG__PB1_HW_18_DEBUG__SHIFT 0x00000012
+#define PB1_HW_DEBUG__PB1_HW_19_DEBUG_MASK 0x00080000L
+#define PB1_HW_DEBUG__PB1_HW_19_DEBUG__SHIFT 0x00000013
+#define PB1_HW_DEBUG__PB1_HW_20_DEBUG_MASK 0x00100000L
+#define PB1_HW_DEBUG__PB1_HW_20_DEBUG__SHIFT 0x00000014
+#define PB1_HW_DEBUG__PB1_HW_21_DEBUG_MASK 0x00200000L
+#define PB1_HW_DEBUG__PB1_HW_21_DEBUG__SHIFT 0x00000015
+#define PB1_HW_DEBUG__PB1_HW_22_DEBUG_MASK 0x00400000L
+#define PB1_HW_DEBUG__PB1_HW_22_DEBUG__SHIFT 0x00000016
+#define PB1_HW_DEBUG__PB1_HW_23_DEBUG_MASK 0x00800000L
+#define PB1_HW_DEBUG__PB1_HW_23_DEBUG__SHIFT 0x00000017
+#define PB1_HW_DEBUG__PB1_HW_24_DEBUG_MASK 0x01000000L
+#define PB1_HW_DEBUG__PB1_HW_24_DEBUG__SHIFT 0x00000018
+#define PB1_HW_DEBUG__PB1_HW_25_DEBUG_MASK 0x02000000L
+#define PB1_HW_DEBUG__PB1_HW_25_DEBUG__SHIFT 0x00000019
+#define PB1_HW_DEBUG__PB1_HW_26_DEBUG_MASK 0x04000000L
+#define PB1_HW_DEBUG__PB1_HW_26_DEBUG__SHIFT 0x0000001a
+#define PB1_HW_DEBUG__PB1_HW_27_DEBUG_MASK 0x08000000L
+#define PB1_HW_DEBUG__PB1_HW_27_DEBUG__SHIFT 0x0000001b
+#define PB1_HW_DEBUG__PB1_HW_28_DEBUG_MASK 0x10000000L
+#define PB1_HW_DEBUG__PB1_HW_28_DEBUG__SHIFT 0x0000001c
+#define PB1_HW_DEBUG__PB1_HW_29_DEBUG_MASK 0x20000000L
+#define PB1_HW_DEBUG__PB1_HW_29_DEBUG__SHIFT 0x0000001d
+#define PB1_HW_DEBUG__PB1_HW_30_DEBUG_MASK 0x40000000L
+#define PB1_HW_DEBUG__PB1_HW_30_DEBUG__SHIFT 0x0000001e
+#define PB1_HW_DEBUG__PB1_HW_31_DEBUG_MASK 0x80000000L
+#define PB1_HW_DEBUG__PB1_HW_31_DEBUG__SHIFT 0x0000001f
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_EN_MASK 0x00000080L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_EN__SHIFT 0x00000007
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0_MASK 0x00000100L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_0__SHIFT 0x00000008
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10_MASK 0x00040000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_10__SHIFT 0x00000012
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11_MASK 0x00080000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_11__SHIFT 0x00000013
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12_MASK 0x00100000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_12__SHIFT 0x00000014
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13_MASK 0x00200000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_13__SHIFT 0x00000015
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14_MASK 0x00400000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_14__SHIFT 0x00000016
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15_MASK 0x00800000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_15__SHIFT 0x00000017
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2_MASK 0x00000400L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_2__SHIFT 0x0000000a
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3_MASK 0x00000800L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4_MASK 0x00001000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_4__SHIFT 0x0000000c
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5_MASK 0x00002000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_5__SHIFT 0x0000000d
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6_MASK 0x00004000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_6__SHIFT 0x0000000e
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7_MASK 0x00008000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8_MASK 0x00010000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_8__SHIFT 0x00000010
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9_MASK 0x00020000L
+#define PB1_PIF_CNTL2__RXDETECT_OVERRIDE_VAL_9__SHIFT 0x00000011
+#define PB1_PIF_CNTL2__RXDETECT_SAMPL_TIME_MASK 0x00000006L
+#define PB1_PIF_CNTL2__RXDETECT_SAMPL_TIME__SHIFT 0x00000001
+#define PB1_PIF_CNTL2__RXPHYSTATUS_DELAY_MASK 0x07000000L
+#define PB1_PIF_CNTL2__RXPHYSTATUS_DELAY__SHIFT 0x00000018
+#define PB1_PIF_CNTL__DA_FIFO_RESET_0_MASK 0x00000002L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_0__SHIFT 0x00000001
+#define PB1_PIF_CNTL__DA_FIFO_RESET_1_MASK 0x00000020L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_1__SHIFT 0x00000005
+#define PB1_PIF_CNTL__DA_FIFO_RESET_2_MASK 0x00000200L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_2__SHIFT 0x00000009
+#define PB1_PIF_CNTL__DA_FIFO_RESET_3_MASK 0x00002000L
+#define PB1_PIF_CNTL__DA_FIFO_RESET_3__SHIFT 0x0000000d
+#define PB1_PIF_CNTL__DIVINIT_MODE_MASK 0x00000100L
+#define PB1_PIF_CNTL__DIVINIT_MODE__SHIFT 0x00000008
+#define PB1_PIF_CNTL__EI_CYCLE_OFF_TIME_MASK 0x00700000L
+#define PB1_PIF_CNTL__EI_CYCLE_OFF_TIME__SHIFT 0x00000014
+#define PB1_PIF_CNTL__EI_DET_CYCLE_MODE_MASK 0x00000010L
+#define PB1_PIF_CNTL__EI_DET_CYCLE_MODE__SHIFT 0x00000004
+#define PB1_PIF_CNTL__EXIT_L0S_INIT_DIS_MASK 0x00800000L
+#define PB1_PIF_CNTL__EXIT_L0S_INIT_DIS__SHIFT 0x00000017
+#define PB1_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP_MASK 0x10000000L
+#define PB1_PIF_CNTL__EXTEND_WAIT_FOR_RAMPUP__SHIFT 0x0000001c
+#define PB1_PIF_CNTL__IGNORE_TxDataValid_EP_DIS_MASK 0x20000000L
+#define PB1_PIF_CNTL__IGNORE_TxDataValid_EP_DIS__SHIFT 0x0000001d
+#define PB1_PIF_CNTL__LS2_EXIT_TIME_MASK 0x000e0000L
+#define PB1_PIF_CNTL__LS2_EXIT_TIME__SHIFT 0x00000011
+#define PB1_PIF_CNTL__PHYCMD_CR_EN_MODE_MASK 0x00000008L
+#define PB1_PIF_CNTL__PHYCMD_CR_EN_MODE__SHIFT 0x00000003
+#define PB1_PIF_CNTL__PHY_CR_EN_MODE_MASK 0x00000004L
+#define PB1_PIF_CNTL__PHY_CR_EN_MODE__SHIFT 0x00000002
+#define PB1_PIF_CNTL__PLL_BINDING_ENABLE_MASK 0x00000400L
+#define PB1_PIF_CNTL__PLL_BINDING_ENABLE__SHIFT 0x0000000a
+#define PB1_PIF_CNTL__RXDETECT_FIFO_RESET_MODE_MASK 0x00000040L
+#define PB1_PIF_CNTL__RXDETECT_FIFO_RESET_MODE__SHIFT 0x00000006
+#define PB1_PIF_CNTL__RXDETECT_TX_PWR_MODE_MASK 0x00000080L
+#define PB1_PIF_CNTL__RXDETECT_TX_PWR_MODE__SHIFT 0x00000007
+#define PB1_PIF_CNTL__RXEN_GATER_MASK 0x0f000000L
+#define PB1_PIF_CNTL__RXEN_GATER__SHIFT 0x00000018
+#define PB1_PIF_CNTL__SC_CALIB_DONE_CNTL_MASK 0x00000800L
+#define PB1_PIF_CNTL__SC_CALIB_DONE_CNTL__SHIFT 0x0000000b
+#define PB1_PIF_CNTL__SERIAL_CFG_ENABLE_MASK 0x00000001L
+#define PB1_PIF_CNTL__SERIAL_CFG_ENABLE__SHIFT 0x00000000
+#define PB1_PIF_CNTL__TXGND_TIME_MASK 0x00010000L
+#define PB1_PIF_CNTL__TXGND_TIME__SHIFT 0x00000010
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_00_DEBUG_MASK 0x00000001L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_00_DEBUG__SHIFT 0x00000000
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_01_DEBUG_MASK 0x00000002L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_01_DEBUG__SHIFT 0x00000001
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_02_DEBUG_MASK 0x00000004L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_02_DEBUG__SHIFT 0x00000002
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_03_DEBUG_MASK 0x00000008L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_03_DEBUG__SHIFT 0x00000003
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_04_DEBUG_MASK 0x00000010L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_04_DEBUG__SHIFT 0x00000004
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_05_DEBUG_MASK 0x00000020L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_05_DEBUG__SHIFT 0x00000005
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_06_DEBUG_MASK 0x00000040L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_06_DEBUG__SHIFT 0x00000006
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_07_DEBUG_MASK 0x00000080L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_07_DEBUG__SHIFT 0x00000007
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_08_DEBUG_MASK 0x00000100L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_08_DEBUG__SHIFT 0x00000008
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_09_DEBUG_MASK 0x00000200L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_09_DEBUG__SHIFT 0x00000009
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_10_DEBUG_MASK 0x00000400L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_10_DEBUG__SHIFT 0x0000000a
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_11_DEBUG_MASK 0x00000800L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_11_DEBUG__SHIFT 0x0000000b
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_12_DEBUG_MASK 0x00001000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_12_DEBUG__SHIFT 0x0000000c
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_13_DEBUG_MASK 0x00002000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_13_DEBUG__SHIFT 0x0000000d
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_14_DEBUG_MASK 0x00004000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_14_DEBUG__SHIFT 0x0000000e
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_15_DEBUG_MASK 0x00008000L
+#define PB1_PIF_HW_DEBUG__PB1_PIF_HW_15_DEBUG__SHIFT 0x0000000f
+#define PB1_PIF_PAIRING__MULTI_PIF_MASK 0x02000000L
+#define PB1_PIF_PAIRING__MULTI_PIF__SHIFT 0x00000019
+#define PB1_PIF_PAIRING__X16_LANE_15_0_MASK 0x00100000L
+#define PB1_PIF_PAIRING__X16_LANE_15_0__SHIFT 0x00000014
+#define PB1_PIF_PAIRING__X2_LANE_1_0_MASK 0x00000001L
+#define PB1_PIF_PAIRING__X2_LANE_1_0__SHIFT 0x00000000
+#define PB1_PIF_PAIRING__X2_LANE_11_10_MASK 0x00000020L
+#define PB1_PIF_PAIRING__X2_LANE_11_10__SHIFT 0x00000005
+#define PB1_PIF_PAIRING__X2_LANE_13_12_MASK 0x00000040L
+#define PB1_PIF_PAIRING__X2_LANE_13_12__SHIFT 0x00000006
+#define PB1_PIF_PAIRING__X2_LANE_15_14_MASK 0x00000080L
+#define PB1_PIF_PAIRING__X2_LANE_15_14__SHIFT 0x00000007
+#define PB1_PIF_PAIRING__X2_LANE_3_2_MASK 0x00000002L
+#define PB1_PIF_PAIRING__X2_LANE_3_2__SHIFT 0x00000001
+#define PB1_PIF_PAIRING__X2_LANE_5_4_MASK 0x00000004L
+#define PB1_PIF_PAIRING__X2_LANE_5_4__SHIFT 0x00000002
+#define PB1_PIF_PAIRING__X2_LANE_7_6_MASK 0x00000008L
+#define PB1_PIF_PAIRING__X2_LANE_7_6__SHIFT 0x00000003
+#define PB1_PIF_PAIRING__X2_LANE_9_8_MASK 0x00000010L
+#define PB1_PIF_PAIRING__X2_LANE_9_8__SHIFT 0x00000004
+#define PB1_PIF_PAIRING__X4_LANE_11_8_MASK 0x00000400L
+#define PB1_PIF_PAIRING__X4_LANE_11_8__SHIFT 0x0000000a
+#define PB1_PIF_PAIRING__X4_LANE_15_12_MASK 0x00000800L
+#define PB1_PIF_PAIRING__X4_LANE_15_12__SHIFT 0x0000000b
+#define PB1_PIF_PAIRING__X4_LANE_3_0_MASK 0x00000100L
+#define PB1_PIF_PAIRING__X4_LANE_3_0__SHIFT 0x00000008
+#define PB1_PIF_PAIRING__X4_LANE_7_4_MASK 0x00000200L
+#define PB1_PIF_PAIRING__X4_LANE_7_4__SHIFT 0x00000009
+#define PB1_PIF_PAIRING__X8_LANE_15_8_MASK 0x00020000L
+#define PB1_PIF_PAIRING__X8_LANE_15_8__SHIFT 0x00000011
+#define PB1_PIF_PAIRING__X8_LANE_7_0_MASK 0x00010000L
+#define PB1_PIF_PAIRING__X8_LANE_7_0__SHIFT 0x00000010
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_EN_0__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXEN_OVERRIDE_VAL_0__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_0__RX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_EN_0__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_0__RXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_EN_0__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_0__TX_PDNB_OVERRIDE_VAL_0__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_EN_0__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_0__TXPWR_OVERRIDE_VAL_0__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_EN_10__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXEN_OVERRIDE_VAL_10__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_10__RX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_EN_10__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_10__RXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_EN_10__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_10__TX_PDNB_OVERRIDE_VAL_10__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_EN_10__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_10__TXPWR_OVERRIDE_VAL_10__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_EN_11__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXEN_OVERRIDE_VAL_11__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_11__RX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_EN_11__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_11__RXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_EN_11__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_11__TX_PDNB_OVERRIDE_VAL_11__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_EN_11__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_11__TXPWR_OVERRIDE_VAL_11__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_EN_12__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXEN_OVERRIDE_VAL_12__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_12__RX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_EN_12__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_12__RXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_EN_12__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_12__TX_PDNB_OVERRIDE_VAL_12__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_EN_12__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_12__TXPWR_OVERRIDE_VAL_12__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_EN_13__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXEN_OVERRIDE_VAL_13__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_13__RX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_EN_13__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_13__RXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_EN_13__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_13__TX_PDNB_OVERRIDE_VAL_13__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_EN_13__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_13__TXPWR_OVERRIDE_VAL_13__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_EN_14__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXEN_OVERRIDE_VAL_14__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_14__RX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_EN_14__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_14__RXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_EN_14__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_14__TX_PDNB_OVERRIDE_VAL_14__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_EN_14__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_14__TXPWR_OVERRIDE_VAL_14__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_EN_15__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXEN_OVERRIDE_VAL_15__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_15__RX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_EN_15__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_15__RXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_EN_15__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_15__TX_PDNB_OVERRIDE_VAL_15__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_EN_15__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_15__TXPWR_OVERRIDE_VAL_15__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_EN_1__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXEN_OVERRIDE_VAL_1__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_1__RX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_EN_1__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_1__RXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_EN_1__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_1__TX_PDNB_OVERRIDE_VAL_1__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_EN_1__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_1__TXPWR_OVERRIDE_VAL_1__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_EN_2__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXEN_OVERRIDE_VAL_2__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_2__RX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_EN_2__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_2__RXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_EN_2__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_2__TX_PDNB_OVERRIDE_VAL_2__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_EN_2__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_2__TXPWR_OVERRIDE_VAL_2__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_EN_3__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXEN_OVERRIDE_VAL_3__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_3__RX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_EN_3__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_3__RXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_EN_3__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_3__TX_PDNB_OVERRIDE_VAL_3__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_EN_3__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_3__TXPWR_OVERRIDE_VAL_3__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_EN_4__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXEN_OVERRIDE_VAL_4__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_4__RX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_EN_4__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_4__RXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_EN_4__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_4__TX_PDNB_OVERRIDE_VAL_4__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_EN_4__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_4__TXPWR_OVERRIDE_VAL_4__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_EN_5__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXEN_OVERRIDE_VAL_5__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_5__RX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_EN_5__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_5__RXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_EN_5__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_5__TX_PDNB_OVERRIDE_VAL_5__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_EN_5__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_5__TXPWR_OVERRIDE_VAL_5__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_EN_6__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXEN_OVERRIDE_VAL_6__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_6__RX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_EN_6__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_6__RXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_EN_6__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_6__TX_PDNB_OVERRIDE_VAL_6__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_EN_6__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_6__TXPWR_OVERRIDE_VAL_6__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_EN_7__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXEN_OVERRIDE_VAL_7__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_7__RX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_EN_7__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_7__RXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_EN_7__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_7__TX_PDNB_OVERRIDE_VAL_7__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_EN_7__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_7__TXPWR_OVERRIDE_VAL_7__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_EN_8__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXEN_OVERRIDE_VAL_8__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_8__RX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_EN_8__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_8__RXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_EN_8__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_8__TX_PDNB_OVERRIDE_VAL_8__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_EN_8__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_8__TXPWR_OVERRIDE_VAL_8__SHIFT 0x0000000b
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9_MASK 0x00000100L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_EN_9__SHIFT 0x00000008
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9_MASK 0x00000200L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXEN_OVERRIDE_VAL_9__SHIFT 0x00000009
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9_MASK 0x00000010L
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000004
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9_MASK 0x000000e0L
+#define PB1_PIF_PDNB_OVERRIDE_9__RX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000005
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9_MASK 0x00004000L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_EN_9__SHIFT 0x0000000e
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9_MASK 0x00038000L
+#define PB1_PIF_PDNB_OVERRIDE_9__RXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000f
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9_MASK 0x00000001L
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_EN_9__SHIFT 0x00000000
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9_MASK 0x0000000eL
+#define PB1_PIF_PDNB_OVERRIDE_9__TX_PDNB_OVERRIDE_VAL_9__SHIFT 0x00000001
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9_MASK 0x00000400L
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_EN_9__SHIFT 0x0000000a
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9_MASK 0x00003800L
+#define PB1_PIF_PDNB_OVERRIDE_9__TXPWR_OVERRIDE_VAL_9__SHIFT 0x0000000b
+#define PB1_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_0__FORCE_RXEN_IN_L0s_0__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_OFF_0__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_0__PLL_POWER_STATE_IN_TXS2_0__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_EN_0__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_0__PLLPWR_OVERRIDE_VAL_0__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_0__PLL_RAMP_UP_TIME_0__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_0__RX_POWER_STATE_IN_RXS2_0__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_0__TX2P5CLK_CLOCK_GATING_EN_0__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_0__TX_POWER_STATE_IN_TXS2_0__SHIFT 0x00000000
+#define PB1_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_1__FORCE_RXEN_IN_L0s_1__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_OFF_1__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_1__PLL_POWER_STATE_IN_TXS2_1__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_EN_1__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_1__PLLPWR_OVERRIDE_VAL_1__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_1__PLL_RAMP_UP_TIME_1__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_1__RX_POWER_STATE_IN_RXS2_1__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_1__TX2P5CLK_CLOCK_GATING_EN_1__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_1__TX_POWER_STATE_IN_TXS2_1__SHIFT 0x00000000
+#define PB1_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_2__FORCE_RXEN_IN_L0s_2__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_OFF_2__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_2__PLL_POWER_STATE_IN_TXS2_2__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_EN_2__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_2__PLLPWR_OVERRIDE_VAL_2__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_2__PLL_RAMP_UP_TIME_2__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_2__RX_POWER_STATE_IN_RXS2_2__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_2__TX2P5CLK_CLOCK_GATING_EN_2__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_2__TX_POWER_STATE_IN_TXS2_2__SHIFT 0x00000000
+#define PB1_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3_MASK 0x00000008L
+#define PB1_PIF_PWRDOWN_3__FORCE_RXEN_IN_L0s_3__SHIFT 0x00000003
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3_MASK 0x00001c00L
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_OFF_3__SHIFT 0x0000000a
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3_MASK 0x00000380L
+#define PB1_PIF_PWRDOWN_3__PLL_POWER_STATE_IN_TXS2_3__SHIFT 0x00000007
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3_MASK 0x10000000L
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_EN_3__SHIFT 0x0000001c
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3_MASK 0xe0000000L
+#define PB1_PIF_PWRDOWN_3__PLLPWR_OVERRIDE_VAL_3__SHIFT 0x0000001d
+#define PB1_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3_MASK 0x07000000L
+#define PB1_PIF_PWRDOWN_3__PLL_RAMP_UP_TIME_3__SHIFT 0x00000018
+#define PB1_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3_MASK 0x00000070L
+#define PB1_PIF_PWRDOWN_3__RX_POWER_STATE_IN_RXS2_3__SHIFT 0x00000004
+#define PB1_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3_MASK 0x00010000L
+#define PB1_PIF_PWRDOWN_3__TX2P5CLK_CLOCK_GATING_EN_3__SHIFT 0x00000010
+#define PB1_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3_MASK 0x00000007L
+#define PB1_PIF_PWRDOWN_3__TX_POWER_STATE_IN_TXS2_3__SHIFT 0x00000000
+#define PB1_PIF_SC_CTL__SC_CALIBRATION_MASK 0x00000001L
+#define PB1_PIF_SC_CTL__SC_CALIBRATION__SHIFT 0x00000000
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0_MASK 0x00000020L
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0__SHIFT 0x00000005
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S_MASK 0x00000010L
+#define PB1_PIF_SC_CTL__SC_ENTER_L1_FROM_L0S__SHIFT 0x00000004
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0_MASK 0x00000008L
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0__SHIFT 0x00000003
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0S_MASK 0x00000004L
+#define PB1_PIF_SC_CTL__SC_EXIT_L1_TO_L0S__SHIFT 0x00000002
+#define PB1_PIF_SC_CTL__SC_LANE_0_RESUME_MASK 0x00010000L
+#define PB1_PIF_SC_CTL__SC_LANE_0_RESUME__SHIFT 0x00000010
+#define PB1_PIF_SC_CTL__SC_LANE_10_RESUME_MASK 0x04000000L
+#define PB1_PIF_SC_CTL__SC_LANE_10_RESUME__SHIFT 0x0000001a
+#define PB1_PIF_SC_CTL__SC_LANE_11_RESUME_MASK 0x08000000L
+#define PB1_PIF_SC_CTL__SC_LANE_11_RESUME__SHIFT 0x0000001b
+#define PB1_PIF_SC_CTL__SC_LANE_12_RESUME_MASK 0x10000000L
+#define PB1_PIF_SC_CTL__SC_LANE_12_RESUME__SHIFT 0x0000001c
+#define PB1_PIF_SC_CTL__SC_LANE_13_RESUME_MASK 0x20000000L
+#define PB1_PIF_SC_CTL__SC_LANE_13_RESUME__SHIFT 0x0000001d
+#define PB1_PIF_SC_CTL__SC_LANE_14_RESUME_MASK 0x40000000L
+#define PB1_PIF_SC_CTL__SC_LANE_14_RESUME__SHIFT 0x0000001e
+#define PB1_PIF_SC_CTL__SC_LANE_15_RESUME_MASK 0x80000000L
+#define PB1_PIF_SC_CTL__SC_LANE_15_RESUME__SHIFT 0x0000001f
+#define PB1_PIF_SC_CTL__SC_LANE_1_RESUME_MASK 0x00020000L
+#define PB1_PIF_SC_CTL__SC_LANE_1_RESUME__SHIFT 0x00000011
+#define PB1_PIF_SC_CTL__SC_LANE_2_RESUME_MASK 0x00040000L
+#define PB1_PIF_SC_CTL__SC_LANE_2_RESUME__SHIFT 0x00000012
+#define PB1_PIF_SC_CTL__SC_LANE_3_RESUME_MASK 0x00080000L
+#define PB1_PIF_SC_CTL__SC_LANE_3_RESUME__SHIFT 0x00000013
+#define PB1_PIF_SC_CTL__SC_LANE_4_RESUME_MASK 0x00100000L
+#define PB1_PIF_SC_CTL__SC_LANE_4_RESUME__SHIFT 0x00000014
+#define PB1_PIF_SC_CTL__SC_LANE_5_RESUME_MASK 0x00200000L
+#define PB1_PIF_SC_CTL__SC_LANE_5_RESUME__SHIFT 0x00000015
+#define PB1_PIF_SC_CTL__SC_LANE_6_RESUME_MASK 0x00400000L
+#define PB1_PIF_SC_CTL__SC_LANE_6_RESUME__SHIFT 0x00000016
+#define PB1_PIF_SC_CTL__SC_LANE_7_RESUME_MASK 0x00800000L
+#define PB1_PIF_SC_CTL__SC_LANE_7_RESUME__SHIFT 0x00000017
+#define PB1_PIF_SC_CTL__SC_LANE_8_RESUME_MASK 0x01000000L
+#define PB1_PIF_SC_CTL__SC_LANE_8_RESUME__SHIFT 0x00000018
+#define PB1_PIF_SC_CTL__SC_LANE_9_RESUME_MASK 0x02000000L
+#define PB1_PIF_SC_CTL__SC_LANE_9_RESUME__SHIFT 0x00000019
+#define PB1_PIF_SC_CTL__SC_PHASE_1_MASK 0x00000100L
+#define PB1_PIF_SC_CTL__SC_PHASE_1__SHIFT 0x00000008
+#define PB1_PIF_SC_CTL__SC_PHASE_2_MASK 0x00000200L
+#define PB1_PIF_SC_CTL__SC_PHASE_2__SHIFT 0x00000009
+#define PB1_PIF_SC_CTL__SC_PHASE_3_MASK 0x00000400L
+#define PB1_PIF_SC_CTL__SC_PHASE_3__SHIFT 0x0000000a
+#define PB1_PIF_SC_CTL__SC_PHASE_4_MASK 0x00000800L
+#define PB1_PIF_SC_CTL__SC_PHASE_4__SHIFT 0x0000000b
+#define PB1_PIF_SC_CTL__SC_PHASE_5_MASK 0x00001000L
+#define PB1_PIF_SC_CTL__SC_PHASE_5__SHIFT 0x0000000c
+#define PB1_PIF_SC_CTL__SC_PHASE_6_MASK 0x00002000L
+#define PB1_PIF_SC_CTL__SC_PHASE_6__SHIFT 0x0000000d
+#define PB1_PIF_SC_CTL__SC_PHASE_7_MASK 0x00004000L
+#define PB1_PIF_SC_CTL__SC_PHASE_7__SHIFT 0x0000000e
+#define PB1_PIF_SC_CTL__SC_PHASE_8_MASK 0x00008000L
+#define PB1_PIF_SC_CTL__SC_PHASE_8__SHIFT 0x0000000f
+#define PB1_PIF_SC_CTL__SC_RXDETECT_MASK 0x00000002L
+#define PB1_PIF_SC_CTL__SC_RXDETECT__SHIFT 0x00000001
+#define PB1_PIF_SC_CTL__SC_SPEED_CHANGE_MASK 0x00000040L
+#define PB1_PIF_SC_CTL__SC_SPEED_CHANGE__SHIFT 0x00000006
+#define PB1_PIF_SCRATCH__PIF_SCRATCH_MASK 0xffffffffL
+#define PB1_PIF_SCRATCH__PIF_SCRATCH__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_CALIBRATION_0__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0_0__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_ENTER_L1_FROM_L0S_0__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0_0__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_EXIT_L1_TO_L0S_0__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_0__SEQ_PHASE_0_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_PHASE_0__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_RXDETECT_0__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_0__SEQ_SPEED_CHANGE_0__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_CALIBRATION_10__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0_10__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_ENTER_L1_FROM_L0S_10__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0_10__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_EXIT_L1_TO_L0S_10__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_10__SEQ_PHASE_10_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_PHASE_10__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_RXDETECT_10__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_10__SEQ_SPEED_CHANGE_10__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_CALIBRATION_11__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0_11__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_ENTER_L1_FROM_L0S_11__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0_11__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_EXIT_L1_TO_L0S_11__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_11__SEQ_PHASE_11_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_PHASE_11__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_RXDETECT_11__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_11__SEQ_SPEED_CHANGE_11__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_CALIBRATION_12__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0_12__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_ENTER_L1_FROM_L0S_12__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0_12__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_EXIT_L1_TO_L0S_12__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_12__SEQ_PHASE_12_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_PHASE_12__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_RXDETECT_12__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_12__SEQ_SPEED_CHANGE_12__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_CALIBRATION_13__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0_13__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_ENTER_L1_FROM_L0S_13__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0_13__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_EXIT_L1_TO_L0S_13__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_13__SEQ_PHASE_13_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_PHASE_13__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_RXDETECT_13__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_13__SEQ_SPEED_CHANGE_13__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_CALIBRATION_14__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0_14__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_ENTER_L1_FROM_L0S_14__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0_14__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_EXIT_L1_TO_L0S_14__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_14__SEQ_PHASE_14_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_PHASE_14__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_RXDETECT_14__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_14__SEQ_SPEED_CHANGE_14__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_CALIBRATION_15__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0_15__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_ENTER_L1_FROM_L0S_15__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0_15__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_EXIT_L1_TO_L0S_15__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_15__SEQ_PHASE_15_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_PHASE_15__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_RXDETECT_15__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_15__SEQ_SPEED_CHANGE_15__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_CALIBRATION_1__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0_1__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_ENTER_L1_FROM_L0S_1__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0_1__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_EXIT_L1_TO_L0S_1__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_1__SEQ_PHASE_1_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_PHASE_1__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_RXDETECT_1__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_1__SEQ_SPEED_CHANGE_1__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_CALIBRATION_2__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0_2__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_ENTER_L1_FROM_L0S_2__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0_2__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_EXIT_L1_TO_L0S_2__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_2__SEQ_PHASE_2_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_PHASE_2__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_RXDETECT_2__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_2__SEQ_SPEED_CHANGE_2__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_CALIBRATION_3__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0_3__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_ENTER_L1_FROM_L0S_3__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0_3__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_EXIT_L1_TO_L0S_3__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_3__SEQ_PHASE_3_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_PHASE_3__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_RXDETECT_3__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_3__SEQ_SPEED_CHANGE_3__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_CALIBRATION_4__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0_4__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_ENTER_L1_FROM_L0S_4__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0_4__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_EXIT_L1_TO_L0S_4__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_4__SEQ_PHASE_4_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_PHASE_4__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_RXDETECT_4__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_4__SEQ_SPEED_CHANGE_4__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_CALIBRATION_5__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0_5__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_ENTER_L1_FROM_L0S_5__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0_5__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_EXIT_L1_TO_L0S_5__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_5__SEQ_PHASE_5_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_PHASE_5__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_RXDETECT_5__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_5__SEQ_SPEED_CHANGE_5__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_CALIBRATION_6__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0_6__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_ENTER_L1_FROM_L0S_6__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0_6__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_EXIT_L1_TO_L0S_6__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_6__SEQ_PHASE_6_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_PHASE_6__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_RXDETECT_6__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_6__SEQ_SPEED_CHANGE_6__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_CALIBRATION_7__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0_7__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_ENTER_L1_FROM_L0S_7__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0_7__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_EXIT_L1_TO_L0S_7__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_7__SEQ_PHASE_7_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_PHASE_7__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_RXDETECT_7__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_7__SEQ_SPEED_CHANGE_7__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_CALIBRATION_8__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0_8__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_ENTER_L1_FROM_L0S_8__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0_8__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_EXIT_L1_TO_L0S_8__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_8__SEQ_PHASE_8_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_PHASE_8__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_RXDETECT_8__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_8__SEQ_SPEED_CHANGE_8__SHIFT 0x00000006
+#define PB1_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9_MASK 0x00000001L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_CALIBRATION_9__SHIFT 0x00000000
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9_MASK 0x00000020L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0_9__SHIFT 0x00000005
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9_MASK 0x00000010L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_ENTER_L1_FROM_L0S_9__SHIFT 0x00000004
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9_MASK 0x00000008L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0_9__SHIFT 0x00000003
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9_MASK 0x00000004L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_EXIT_L1_TO_L0S_9__SHIFT 0x00000002
+#define PB1_PIF_SEQ_STATUS_9__SEQ_PHASE_9_MASK 0x00000700L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_PHASE_9__SHIFT 0x00000008
+#define PB1_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9_MASK 0x00000002L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_RXDETECT_9__SHIFT 0x00000001
+#define PB1_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9_MASK 0x00000040L
+#define PB1_PIF_SEQ_STATUS_9__SEQ_SPEED_CHANGE_9__SHIFT 0x00000006
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_0_MASK 0x00000001L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_0__SHIFT 0x00000000
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_10_MASK 0x00000400L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_10__SHIFT 0x0000000a
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_11_MASK 0x00000800L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_11__SHIFT 0x0000000b
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_12_MASK 0x00001000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_12__SHIFT 0x0000000c
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_13_MASK 0x00002000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_13__SHIFT 0x0000000d
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_14_MASK 0x00004000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_14__SHIFT 0x0000000e
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_15_MASK 0x00008000L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_15__SHIFT 0x0000000f
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_1_MASK 0x00000002L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_1__SHIFT 0x00000001
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_2_MASK 0x00000004L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_2__SHIFT 0x00000002
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_3_MASK 0x00000008L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_3__SHIFT 0x00000003
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_4_MASK 0x00000010L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_4__SHIFT 0x00000004
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_5_MASK 0x00000020L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_5__SHIFT 0x00000005
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_6_MASK 0x00000040L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_6__SHIFT 0x00000006
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_7_MASK 0x00000080L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_7__SHIFT 0x00000007
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_8_MASK 0x00000100L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_8__SHIFT 0x00000008
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_9_MASK 0x00000200L
+#define PB1_PIF_TXPHYSTATUS__TXPHYSTATUS_9__SHIFT 0x00000009
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0_MASK 0x00000003L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_DBG_LC_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB1_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0_MASK 0x00000010L
+#define PB1_PLL_LC0_CTRL_REG0__PLL_TST_LC_USAMPLE_EN_0__SHIFT 0x00000004
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0_MASK 0x00000008L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000003
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0_MASK 0x00000007L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0_MASK 0x00000080L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_EN_0__SHIFT 0x00000007
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000070L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000004
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0_MASK 0x00000200L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_EN_0__SHIFT 0x00000009
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0_MASK 0x00000100L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_CORECLK_EN_OVRD_VAL_0__SHIFT 0x00000008
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0_MASK 0x00040000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_EN_0__SHIFT 0x00000012
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0_MASK 0x0003fc00L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_FBDIV_OVRD_VAL_0__SHIFT 0x0000000a
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0_MASK 0x10000000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_EN_0__SHIFT 0x0000001c
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0_MASK 0x0ff80000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_LF_CNTRL_OVRD_VAL_0__SHIFT 0x00000013
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0_MASK 0x80000000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_EN_0__SHIFT 0x0000001f
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0_MASK 0x60000000L
+#define PB1_PLL_LC0_OVRD_REG0__PLL_CFG_LC_REFDIV_OVRD_VAL_0__SHIFT 0x0000001d
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0_MASK 0x00000008L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000003
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0_MASK 0x00000007L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0_MASK 0x00040000L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_EN_0__SHIFT 0x00000012
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0_MASK 0x0003c000L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_CFG_LC_VCO_TUNE_OVRD_VAL_0__SHIFT 0x0000000e
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000020L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x00000005
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000010L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000004
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00000080L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x00000007
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000040L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x00000006
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0_MASK 0x00000200L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_EN_0__SHIFT 0x00000009
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0_MASK 0x00000100L
+#define PB1_PLL_LC0_OVRD_REG1__PLL_LC_PWRON_OVRD_VAL_0__SHIFT 0x00000008
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC0_SCI_STAT_OVRD_REG0__PLL_LC0_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC1_SCI_STAT_OVRD_REG0__PLL_LC1_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC2_SCI_STAT_OVRD_REG0__PLL_LC2_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_LC3_SCI_STAT_OVRD_REG0__PLL_LC3_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0_MASK 0x00000003L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_ANALOG_SEL_0__SHIFT 0x00000000
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0_MASK 0x00000004L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_EXT_RESET_EN_0__SHIFT 0x00000002
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0_MASK 0x000007f0L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_LF_CNTRL_0__SHIFT 0x00000004
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0_MASK 0x00000008L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_DBG_RO_VCTL_ADC_EN_0__SHIFT 0x00000003
+#define PB1_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0_MASK 0x00000800L
+#define PB1_PLL_RO0_CTRL_REG0__PLL_TST_RO_USAMPLE_EN_0__SHIFT 0x0000000b
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0_MASK 0x00000100L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_EN_0__SHIFT 0x00000008
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0_MASK 0x000000ffL
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_BW_CNTRL_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0_MASK 0x00001000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_EN_0__SHIFT 0x0000000c
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0_MASK 0x00000e00L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_DIV_OVRD_VAL_0__SHIFT 0x00000009
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0_MASK 0x00004000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_EN_0__SHIFT 0x0000000e
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0_MASK 0x00002000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_CORECLK_EN_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0_MASK 0x10000000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_EN_0__SHIFT 0x0000001c
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0_MASK 0x0fff8000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_FBDIV_OVRD_VAL_0__SHIFT 0x0000000f
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0_MASK 0x80000000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_EN_0__SHIFT 0x0000001f
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0_MASK 0x40000000L
+#define PB1_PLL_RO0_OVRD_REG0__PLL_CFG_RO_VTOI_BIAS_CNTRL_OVRD_VAL_0__SHIFT 0x0000001e
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0_MASK 0x00400000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_EN_0__SHIFT 0x00000016
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0_MASK 0x00380000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFCLK_SRC_OVRD_VAL_0__SHIFT 0x00000013
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0_MASK 0x00000020L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_EN_0__SHIFT 0x00000005
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0_MASK 0x0000001fL
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_REFDIV_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0_MASK 0x00000100L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_EN_0__SHIFT 0x00000008
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0_MASK 0x000000c0L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_CFG_RO_VCO_MODE_OVRD_VAL_0__SHIFT 0x00000006
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0_MASK 0x00000400L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_EN_0__SHIFT 0x0000000a
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0_MASK 0x00000200L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_LEFT_EN_OVRD_VAL_0__SHIFT 0x00000009
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0_MASK 0x00001000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_EN_0__SHIFT 0x0000000c
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0_MASK 0x00000800L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_HSCLK_RIGHT_EN_OVRD_VAL_0__SHIFT 0x0000000b
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0_MASK 0x00004000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_EN_0__SHIFT 0x0000000e
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0_MASK 0x00002000L
+#define PB1_PLL_RO0_OVRD_REG1__PLL_RO_PWRON_OVRD_VAL_0__SHIFT 0x0000000d
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO0_SCI_STAT_OVRD_REG0__PLL_RO0_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO1_SCI_STAT_OVRD_REG0__PLL_RO1_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO2_SCI_STAT_OVRD_REG0__PLL_RO2_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE_MASK 0x00000300L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_FREQMODE__SHIFT 0x00000008
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT_MASK 0x00000002L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_FREQMODE_SCI_UPDT__SHIFT 0x00000001
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT_MASK 0x00000001L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_IGNR_PLLPWR_SCI_UPDT__SHIFT 0x00000000
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR_MASK 0x00000070L
+#define PB1_PLL_RO3_SCI_STAT_OVRD_REG0__PLL_RO3_PLLPWR__SHIFT 0x00000004
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000200L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000009
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000400L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000a
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000800L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000b
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00100000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000014
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00200000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000015
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00001000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x0000000c
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00002000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x0000000d
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00004000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x0000000e
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00400000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000016
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00800000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000017
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2_MASK 0x00000100L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_LC_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000008
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0_MASK 0x00000002L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS0__SHIFT 0x00000001
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1_MASK 0x00000004L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS1__SHIFT 0x00000002
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2_MASK 0x00000008L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_EN_LUT_ENTRY_LS2__SHIFT 0x00000003
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN_MASK 0x00010000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_LEFT_EN_GATING_EN__SHIFT 0x00000010
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN_MASK 0x00020000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_LEFT_RIGHT_EN_GATING_EN__SHIFT 0x00000011
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0_MASK 0x00000010L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS0__SHIFT 0x00000004
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1_MASK 0x00000020L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS1__SHIFT 0x00000005
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2_MASK 0x00000040L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_EN_LUT_ENTRY_LS2__SHIFT 0x00000006
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN_MASK 0x00040000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_LEFT_EN_GATING_EN__SHIFT 0x00000012
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN_MASK 0x00080000L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_HSCLK_RIGHT_RIGHT_EN_GATING_EN__SHIFT 0x00000013
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2_MASK 0x00000080L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_RO_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000007
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC_MASK 0x00000001L
+#define PB1_PLL_RO_GLB_CTRL_REG0__PLL_TST_LOSPDTST_SRC__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1_MASK 0x000003ffL
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2_MASK 0x000ffc00L
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN2__SHIFT 0x0000000a
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3_MASK 0x3ff00000L
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_MODE_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE_MASK 0xc0000000L
+#define PB1_RX_GLB_CTRL_REG0__RX_CFG_ADAPT_RST_MODE__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN_MASK 0xc0000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_ADAPT_HLD_ASRT_TO_DCLK_EN__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1_MASK 0x0000000fL
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2_MASK 0x000000f0L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN2__SHIFT 0x00000004
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3_MASK 0x00000f00L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_FR_GAIN_GEN3__SHIFT 0x00000008
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1_MASK 0x0000f000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN1__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2_MASK 0x000f0000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PH_GAIN_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1_MASK 0x01000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN1__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2_MASK 0x02000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN2__SHIFT 0x00000019
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3_MASK 0x04000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_CDR_PI_STPSZ_GEN3__SHIFT 0x0000001a
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN1__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2_MASK 0x10000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN2__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3_MASK 0x20000000L
+#define PB1_RX_GLB_CTRL_REG1__RX_CFG_LEQ_DCATTN_BYP_EN_GEN3__SHIFT 0x0000001d
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1_MASK 0x0000f000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN1__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2_MASK 0x000f0000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_CDR_TIME_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1_MASK 0x03000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN1__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2_MASK 0x0c000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN2__SHIFT 0x0000001a
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3_MASK 0x30000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_CFG_LEQ_LOOP_GAIN_GEN3__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD_MASK 0xc0000000L
+#define PB1_RX_GLB_CTRL_REG2__RX_DCLK_EN_ASRT_TO_ADAPT_HLD__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1_MASK 0x00000001L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2_MASK 0x00000002L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN2__SHIFT 0x00000001
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3_MASK 0x00000004L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_CDR_FR_EN_GEN3__SHIFT 0x00000002
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN1__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2_MASK 0x0f000000L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN2__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3_MASK 0xf0000000L
+#define PB1_RX_GLB_CTRL_REG3__RX_CFG_DFE_TIME_GEN3__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1_MASK 0x00000007L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2_MASK 0x00000038L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN2__SHIFT 0x00000003
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3_MASK 0x000001c0L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_BER_GEN3__SHIFT 0x00000006
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN1__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2_MASK 0x0f000000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN2__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3_MASK 0xf0000000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_FOM_TIME_GEN3__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1_MASK 0x00000e00L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN1__SHIFT 0x00000009
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2_MASK 0x00007000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN2__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3_MASK 0x00038000L
+#define PB1_RX_GLB_CTRL_REG4__RX_CFG_LEQ_POLE_BYP_VAL_GEN3__SHIFT 0x0000000f
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1_MASK 0x0000001fL
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2_MASK 0x000003e0L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN2__SHIFT 0x00000005
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3_MASK 0x00007c00L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_DCATTN_BYP_VAL_GEN3__SHIFT 0x0000000a
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1_MASK 0x00008000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN1__SHIFT 0x0000000f
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2_MASK 0x00010000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3_MASK 0x00020000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_POLE_BYP_EN_GEN3__SHIFT 0x00000011
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1_MASK 0x00040000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN1__SHIFT 0x00000012
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2_MASK 0x00080000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN2__SHIFT 0x00000013
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3_MASK 0x00100000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_LEQ_SHUNT_EN_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN1__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2_MASK 0x10000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN2__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3_MASK 0x20000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_CFG_TERM_MODE_GEN3__SHIFT 0x0000001d
+#define PB1_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0_MASK 0x40000000L
+#define PB1_RX_GLB_CTRL_REG5__RX_FORCE_DLL_RST_RXPWR_LS2OFF_TO_LS0__SHIFT 0x0000001e
+#define PB1_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG6__RX_AUX_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1_MASK 0x0000000fL
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2_MASK 0x000000f0L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN2__SHIFT 0x00000004
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3_MASK 0x00000f00L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_LEQ_TIME_GEN3__SHIFT 0x00000008
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1_MASK 0x0000f000L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN1__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2_MASK 0x000f0000L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN2__SHIFT 0x00000010
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3_MASK 0x00f00000L
+#define PB1_RX_GLB_CTRL_REG6__RX_CFG_OC_TIME_GEN3__SHIFT 0x00000014
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x01000000L
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2_MASK 0x04000000L
+#define PB1_RX_GLB_CTRL_REG6__RX_FRONTEND_PWRON_LUT_ENTRY_LS2__SHIFT 0x0000001a
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1_MASK 0x001c0000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN1__SHIFT 0x00000012
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2_MASK 0x00e00000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN2__SHIFT 0x00000015
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3_MASK 0x07000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_CPI_SEL_GEN3__SHIFT 0x00000018
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1_MASK 0x08000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN1__SHIFT 0x0000001b
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2_MASK 0x10000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN2__SHIFT 0x0000001c
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3_MASK 0x20000000L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_DLL_FLOCK_DISABLE_GEN3__SHIFT 0x0000001d
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1_MASK 0x0000000fL
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN1__SHIFT 0x00000000
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2_MASK 0x000000f0L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN2__SHIFT 0x00000004
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3_MASK 0x00000f00L
+#define PB1_RX_GLB_CTRL_REG7__RX_CFG_TH_LOOP_GAIN_GEN3__SHIFT 0x00000008
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0_MASK 0x00001000L
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS0_CDR_EN_0__SHIFT 0x0000000c
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2_MASK 0x00002000L
+#define PB1_RX_GLB_CTRL_REG7__RX_DCLK_EN_LUT_ENTRY_LS2__SHIFT 0x0000000d
+#define PB1_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2_MASK 0x00020000L
+#define PB1_RX_GLB_CTRL_REG7__RX_DLL_PWRON_LUT_ENTRY_LS2__SHIFT 0x00000011
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN_MASK 0x80000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_EN__SHIFT 0x0000001f
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL_MASK 0x40000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_FOM_OVRD_VAL__SHIFT 0x0000001e
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN_MASK 0x00000002L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_EN__SHIFT 0x00000001
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL_MASK 0x00000001L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_HLD_OVRD_VAL__SHIFT 0x00000000
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN_MASK 0x00000008L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_EN__SHIFT 0x00000003
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL_MASK 0x00000004L
+#define PB1_RX_GLB_OVRD_REG0__RX_ADAPT_RST_OVRD_VAL__SHIFT 0x00000002
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN_MASK 0x20000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_EN__SHIFT 0x0000001d
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL_MASK 0x10000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_AUX_PWRON_OVRD_VAL__SHIFT 0x0000001c
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000100L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000008
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x000000c0L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000006
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN_MASK 0x00000400L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_EN__SHIFT 0x0000000a
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL_MASK 0x00000200L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_DLL_FREQ_MODE_OVRD_VAL__SHIFT 0x00000009
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00001000L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000c
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000800L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x0000000b
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN_MASK 0x00004000L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_EN__SHIFT 0x0000000e
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL_MASK 0x00002000L
+#define PB1_RX_GLB_OVRD_REG0__RX_CFG_RCLK_DIV_OVRD_VAL__SHIFT 0x0000000d
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN_MASK 0x00010000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_EN__SHIFT 0x00000010
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL_MASK 0x00008000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DCLK_EN_OVRD_VAL__SHIFT 0x0000000f
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN_MASK 0x00040000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_EN__SHIFT 0x00000012
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL_MASK 0x00020000L
+#define PB1_RX_GLB_OVRD_REG0__RX_DLL_PWRON_OVRD_VAL__SHIFT 0x00000011
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN_MASK 0x00100000L
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_EN__SHIFT 0x00000014
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL_MASK 0x00080000L
+#define PB1_RX_GLB_OVRD_REG0__RX_FRONTEND_PWRON_OVRD_VAL__SHIFT 0x00000013
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN_MASK 0x00400000L
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_EN__SHIFT 0x00000016
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL_MASK 0x00200000L
+#define PB1_RX_GLB_OVRD_REG0__RX_IDLEDET_PWRON_OVRD_VAL__SHIFT 0x00000015
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN_MASK 0x01000000L
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_EN__SHIFT 0x00000018
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL_MASK 0x00800000L
+#define PB1_RX_GLB_OVRD_REG0__RX_TERM_EN_OVRD_VAL__SHIFT 0x00000017
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN_MASK 0x00000002L
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_EN__SHIFT 0x00000001
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL_MASK 0x00000001L
+#define PB1_RX_GLB_OVRD_REG1__RX_ADAPT_TRK_OVRD_VAL__SHIFT 0x00000000
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ELECIDLEDETEN_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_ENABLEFOM_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3_MASK 0x00010000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L0T3__SHIFT 0x00000010
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15_MASK 0x00080000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L12T15__SHIFT 0x00000013
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7_MASK 0x00020000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L4T7__SHIFT 0x00000011
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11_MASK 0x00040000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_REQUESTFOM_SCI_UPDT_L8T11__SHIFT 0x00000012
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3_MASK 0x00100000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L0T3__SHIFT 0x00000014
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15_MASK 0x00800000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L12T15__SHIFT 0x00000017
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7_MASK 0x00200000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L4T7__SHIFT 0x00000015
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11_MASK 0x00400000L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RESPONSEMODE_SCI_UPDT_L8T11__SHIFT 0x00000016
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPRESETHINT_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_RX_GLB_SCI_STAT_OVRD_REG0__IGNR_RXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_RX_LANE0_CTRL_REG0__RX_BACKUP_0_MASK 0x000000ffL
+#define PB1_RX_LANE0_CTRL_REG0__RX_BACKUP_0__SHIFT 0x00000000
+#define PB1_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0_MASK 0x00002000L
+#define PB1_RX_LANE0_CTRL_REG0__RX_CFG_OVR_PWRSF_0__SHIFT 0x0000000d
+#define PB1_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0_MASK 0x00000c00L
+#define PB1_RX_LANE0_CTRL_REG0__RX_DBG_ANALOG_SEL_0__SHIFT 0x0000000a
+#define PB1_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0_MASK 0x00001000L
+#define PB1_RX_LANE0_CTRL_REG0__RX_TST_BSCAN_EN_0__SHIFT 0x0000000c
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0_MASK 0x00000008L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_0__SHIFT 0x00000003
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0_MASK 0x00000080L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__ENABLEFOM_0__SHIFT 0x00000007
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0_MASK 0x00000100L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__REQUESTFOM_0__SHIFT 0x00000008
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0_MASK 0x00000200L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RESPONSEMODE_0__SHIFT 0x00000009
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0_MASK 0x00000070L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPRESETHINT_0__SHIFT 0x00000004
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0_MASK 0x00000007L
+#define PB1_RX_LANE0_SCI_STAT_OVRD_REG0__RXPWR_0__SHIFT 0x00000000
+#define PB1_RX_LANE10_CTRL_REG0__RX_BACKUP_10_MASK 0x000000ffL
+#define PB1_RX_LANE10_CTRL_REG0__RX_BACKUP_10__SHIFT 0x00000000
+#define PB1_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10_MASK 0x00002000L
+#define PB1_RX_LANE10_CTRL_REG0__RX_CFG_OVR_PWRSF_10__SHIFT 0x0000000d
+#define PB1_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10_MASK 0x00000c00L
+#define PB1_RX_LANE10_CTRL_REG0__RX_DBG_ANALOG_SEL_10__SHIFT 0x0000000a
+#define PB1_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10_MASK 0x00001000L
+#define PB1_RX_LANE10_CTRL_REG0__RX_TST_BSCAN_EN_10__SHIFT 0x0000000c
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10_MASK 0x00000008L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_10__SHIFT 0x00000003
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10_MASK 0x00000080L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__ENABLEFOM_10__SHIFT 0x00000007
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10_MASK 0x00000100L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__REQUESTFOM_10__SHIFT 0x00000008
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10_MASK 0x00000200L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RESPONSEMODE_10__SHIFT 0x00000009
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10_MASK 0x00000070L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPRESETHINT_10__SHIFT 0x00000004
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10_MASK 0x00000007L
+#define PB1_RX_LANE10_SCI_STAT_OVRD_REG0__RXPWR_10__SHIFT 0x00000000
+#define PB1_RX_LANE11_CTRL_REG0__RX_BACKUP_11_MASK 0x000000ffL
+#define PB1_RX_LANE11_CTRL_REG0__RX_BACKUP_11__SHIFT 0x00000000
+#define PB1_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11_MASK 0x00002000L
+#define PB1_RX_LANE11_CTRL_REG0__RX_CFG_OVR_PWRSF_11__SHIFT 0x0000000d
+#define PB1_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11_MASK 0x00000c00L
+#define PB1_RX_LANE11_CTRL_REG0__RX_DBG_ANALOG_SEL_11__SHIFT 0x0000000a
+#define PB1_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11_MASK 0x00001000L
+#define PB1_RX_LANE11_CTRL_REG0__RX_TST_BSCAN_EN_11__SHIFT 0x0000000c
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11_MASK 0x00000008L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_11__SHIFT 0x00000003
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11_MASK 0x00000080L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__ENABLEFOM_11__SHIFT 0x00000007
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11_MASK 0x00000100L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__REQUESTFOM_11__SHIFT 0x00000008
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11_MASK 0x00000200L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RESPONSEMODE_11__SHIFT 0x00000009
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11_MASK 0x00000070L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPRESETHINT_11__SHIFT 0x00000004
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11_MASK 0x00000007L
+#define PB1_RX_LANE11_SCI_STAT_OVRD_REG0__RXPWR_11__SHIFT 0x00000000
+#define PB1_RX_LANE12_CTRL_REG0__RX_BACKUP_12_MASK 0x000000ffL
+#define PB1_RX_LANE12_CTRL_REG0__RX_BACKUP_12__SHIFT 0x00000000
+#define PB1_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12_MASK 0x00002000L
+#define PB1_RX_LANE12_CTRL_REG0__RX_CFG_OVR_PWRSF_12__SHIFT 0x0000000d
+#define PB1_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12_MASK 0x00000c00L
+#define PB1_RX_LANE12_CTRL_REG0__RX_DBG_ANALOG_SEL_12__SHIFT 0x0000000a
+#define PB1_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12_MASK 0x00001000L
+#define PB1_RX_LANE12_CTRL_REG0__RX_TST_BSCAN_EN_12__SHIFT 0x0000000c
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12_MASK 0x00000008L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_12__SHIFT 0x00000003
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12_MASK 0x00000080L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__ENABLEFOM_12__SHIFT 0x00000007
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12_MASK 0x00000100L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__REQUESTFOM_12__SHIFT 0x00000008
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12_MASK 0x00000200L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RESPONSEMODE_12__SHIFT 0x00000009
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12_MASK 0x00000070L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPRESETHINT_12__SHIFT 0x00000004
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12_MASK 0x00000007L
+#define PB1_RX_LANE12_SCI_STAT_OVRD_REG0__RXPWR_12__SHIFT 0x00000000
+#define PB1_RX_LANE13_CTRL_REG0__RX_BACKUP_13_MASK 0x000000ffL
+#define PB1_RX_LANE13_CTRL_REG0__RX_BACKUP_13__SHIFT 0x00000000
+#define PB1_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13_MASK 0x00002000L
+#define PB1_RX_LANE13_CTRL_REG0__RX_CFG_OVR_PWRSF_13__SHIFT 0x0000000d
+#define PB1_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13_MASK 0x00000c00L
+#define PB1_RX_LANE13_CTRL_REG0__RX_DBG_ANALOG_SEL_13__SHIFT 0x0000000a
+#define PB1_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13_MASK 0x00001000L
+#define PB1_RX_LANE13_CTRL_REG0__RX_TST_BSCAN_EN_13__SHIFT 0x0000000c
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13_MASK 0x00000008L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_13__SHIFT 0x00000003
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13_MASK 0x00000080L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__ENABLEFOM_13__SHIFT 0x00000007
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13_MASK 0x00000100L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__REQUESTFOM_13__SHIFT 0x00000008
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13_MASK 0x00000200L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RESPONSEMODE_13__SHIFT 0x00000009
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13_MASK 0x00000070L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPRESETHINT_13__SHIFT 0x00000004
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13_MASK 0x00000007L
+#define PB1_RX_LANE13_SCI_STAT_OVRD_REG0__RXPWR_13__SHIFT 0x00000000
+#define PB1_RX_LANE14_CTRL_REG0__RX_BACKUP_14_MASK 0x000000ffL
+#define PB1_RX_LANE14_CTRL_REG0__RX_BACKUP_14__SHIFT 0x00000000
+#define PB1_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14_MASK 0x00002000L
+#define PB1_RX_LANE14_CTRL_REG0__RX_CFG_OVR_PWRSF_14__SHIFT 0x0000000d
+#define PB1_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14_MASK 0x00000c00L
+#define PB1_RX_LANE14_CTRL_REG0__RX_DBG_ANALOG_SEL_14__SHIFT 0x0000000a
+#define PB1_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14_MASK 0x00001000L
+#define PB1_RX_LANE14_CTRL_REG0__RX_TST_BSCAN_EN_14__SHIFT 0x0000000c
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14_MASK 0x00000008L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_14__SHIFT 0x00000003
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14_MASK 0x00000080L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__ENABLEFOM_14__SHIFT 0x00000007
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14_MASK 0x00000100L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__REQUESTFOM_14__SHIFT 0x00000008
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14_MASK 0x00000200L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RESPONSEMODE_14__SHIFT 0x00000009
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14_MASK 0x00000070L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPRESETHINT_14__SHIFT 0x00000004
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14_MASK 0x00000007L
+#define PB1_RX_LANE14_SCI_STAT_OVRD_REG0__RXPWR_14__SHIFT 0x00000000
+#define PB1_RX_LANE15_CTRL_REG0__RX_BACKUP_15_MASK 0x000000ffL
+#define PB1_RX_LANE15_CTRL_REG0__RX_BACKUP_15__SHIFT 0x00000000
+#define PB1_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15_MASK 0x00002000L
+#define PB1_RX_LANE15_CTRL_REG0__RX_CFG_OVR_PWRSF_15__SHIFT 0x0000000d
+#define PB1_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15_MASK 0x00000c00L
+#define PB1_RX_LANE15_CTRL_REG0__RX_DBG_ANALOG_SEL_15__SHIFT 0x0000000a
+#define PB1_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15_MASK 0x00001000L
+#define PB1_RX_LANE15_CTRL_REG0__RX_TST_BSCAN_EN_15__SHIFT 0x0000000c
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15_MASK 0x00000008L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_15__SHIFT 0x00000003
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15_MASK 0x00000080L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__ENABLEFOM_15__SHIFT 0x00000007
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15_MASK 0x00000100L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__REQUESTFOM_15__SHIFT 0x00000008
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15_MASK 0x00000200L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RESPONSEMODE_15__SHIFT 0x00000009
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15_MASK 0x00000070L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPRESETHINT_15__SHIFT 0x00000004
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15_MASK 0x00000007L
+#define PB1_RX_LANE15_SCI_STAT_OVRD_REG0__RXPWR_15__SHIFT 0x00000000
+#define PB1_RX_LANE1_CTRL_REG0__RX_BACKUP_1_MASK 0x000000ffL
+#define PB1_RX_LANE1_CTRL_REG0__RX_BACKUP_1__SHIFT 0x00000000
+#define PB1_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1_MASK 0x00002000L
+#define PB1_RX_LANE1_CTRL_REG0__RX_CFG_OVR_PWRSF_1__SHIFT 0x0000000d
+#define PB1_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1_MASK 0x00000c00L
+#define PB1_RX_LANE1_CTRL_REG0__RX_DBG_ANALOG_SEL_1__SHIFT 0x0000000a
+#define PB1_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1_MASK 0x00001000L
+#define PB1_RX_LANE1_CTRL_REG0__RX_TST_BSCAN_EN_1__SHIFT 0x0000000c
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1_MASK 0x00000008L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_1__SHIFT 0x00000003
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1_MASK 0x00000080L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__ENABLEFOM_1__SHIFT 0x00000007
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1_MASK 0x00000100L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__REQUESTFOM_1__SHIFT 0x00000008
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1_MASK 0x00000200L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RESPONSEMODE_1__SHIFT 0x00000009
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1_MASK 0x00000070L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPRESETHINT_1__SHIFT 0x00000004
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1_MASK 0x00000007L
+#define PB1_RX_LANE1_SCI_STAT_OVRD_REG0__RXPWR_1__SHIFT 0x00000000
+#define PB1_RX_LANE2_CTRL_REG0__RX_BACKUP_2_MASK 0x000000ffL
+#define PB1_RX_LANE2_CTRL_REG0__RX_BACKUP_2__SHIFT 0x00000000
+#define PB1_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2_MASK 0x00002000L
+#define PB1_RX_LANE2_CTRL_REG0__RX_CFG_OVR_PWRSF_2__SHIFT 0x0000000d
+#define PB1_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2_MASK 0x00000c00L
+#define PB1_RX_LANE2_CTRL_REG0__RX_DBG_ANALOG_SEL_2__SHIFT 0x0000000a
+#define PB1_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2_MASK 0x00001000L
+#define PB1_RX_LANE2_CTRL_REG0__RX_TST_BSCAN_EN_2__SHIFT 0x0000000c
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2_MASK 0x00000008L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_2__SHIFT 0x00000003
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2_MASK 0x00000080L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__ENABLEFOM_2__SHIFT 0x00000007
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2_MASK 0x00000100L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__REQUESTFOM_2__SHIFT 0x00000008
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2_MASK 0x00000200L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RESPONSEMODE_2__SHIFT 0x00000009
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2_MASK 0x00000070L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPRESETHINT_2__SHIFT 0x00000004
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2_MASK 0x00000007L
+#define PB1_RX_LANE2_SCI_STAT_OVRD_REG0__RXPWR_2__SHIFT 0x00000000
+#define PB1_RX_LANE3_CTRL_REG0__RX_BACKUP_3_MASK 0x000000ffL
+#define PB1_RX_LANE3_CTRL_REG0__RX_BACKUP_3__SHIFT 0x00000000
+#define PB1_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3_MASK 0x00002000L
+#define PB1_RX_LANE3_CTRL_REG0__RX_CFG_OVR_PWRSF_3__SHIFT 0x0000000d
+#define PB1_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3_MASK 0x00000c00L
+#define PB1_RX_LANE3_CTRL_REG0__RX_DBG_ANALOG_SEL_3__SHIFT 0x0000000a
+#define PB1_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3_MASK 0x00001000L
+#define PB1_RX_LANE3_CTRL_REG0__RX_TST_BSCAN_EN_3__SHIFT 0x0000000c
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3_MASK 0x00000008L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_3__SHIFT 0x00000003
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3_MASK 0x00000080L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__ENABLEFOM_3__SHIFT 0x00000007
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3_MASK 0x00000100L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__REQUESTFOM_3__SHIFT 0x00000008
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3_MASK 0x00000200L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RESPONSEMODE_3__SHIFT 0x00000009
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3_MASK 0x00000070L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPRESETHINT_3__SHIFT 0x00000004
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3_MASK 0x00000007L
+#define PB1_RX_LANE3_SCI_STAT_OVRD_REG0__RXPWR_3__SHIFT 0x00000000
+#define PB1_RX_LANE4_CTRL_REG0__RX_BACKUP_4_MASK 0x000000ffL
+#define PB1_RX_LANE4_CTRL_REG0__RX_BACKUP_4__SHIFT 0x00000000
+#define PB1_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4_MASK 0x00002000L
+#define PB1_RX_LANE4_CTRL_REG0__RX_CFG_OVR_PWRSF_4__SHIFT 0x0000000d
+#define PB1_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4_MASK 0x00000c00L
+#define PB1_RX_LANE4_CTRL_REG0__RX_DBG_ANALOG_SEL_4__SHIFT 0x0000000a
+#define PB1_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4_MASK 0x00001000L
+#define PB1_RX_LANE4_CTRL_REG0__RX_TST_BSCAN_EN_4__SHIFT 0x0000000c
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4_MASK 0x00000008L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_4__SHIFT 0x00000003
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4_MASK 0x00000080L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__ENABLEFOM_4__SHIFT 0x00000007
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4_MASK 0x00000100L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__REQUESTFOM_4__SHIFT 0x00000008
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4_MASK 0x00000200L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RESPONSEMODE_4__SHIFT 0x00000009
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4_MASK 0x00000070L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPRESETHINT_4__SHIFT 0x00000004
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4_MASK 0x00000007L
+#define PB1_RX_LANE4_SCI_STAT_OVRD_REG0__RXPWR_4__SHIFT 0x00000000
+#define PB1_RX_LANE5_CTRL_REG0__RX_BACKUP_5_MASK 0x000000ffL
+#define PB1_RX_LANE5_CTRL_REG0__RX_BACKUP_5__SHIFT 0x00000000
+#define PB1_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5_MASK 0x00002000L
+#define PB1_RX_LANE5_CTRL_REG0__RX_CFG_OVR_PWRSF_5__SHIFT 0x0000000d
+#define PB1_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5_MASK 0x00000c00L
+#define PB1_RX_LANE5_CTRL_REG0__RX_DBG_ANALOG_SEL_5__SHIFT 0x0000000a
+#define PB1_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5_MASK 0x00001000L
+#define PB1_RX_LANE5_CTRL_REG0__RX_TST_BSCAN_EN_5__SHIFT 0x0000000c
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5_MASK 0x00000008L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_5__SHIFT 0x00000003
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5_MASK 0x00000080L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__ENABLEFOM_5__SHIFT 0x00000007
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5_MASK 0x00000100L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__REQUESTFOM_5__SHIFT 0x00000008
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5_MASK 0x00000200L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RESPONSEMODE_5__SHIFT 0x00000009
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5_MASK 0x00000070L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPRESETHINT_5__SHIFT 0x00000004
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5_MASK 0x00000007L
+#define PB1_RX_LANE5_SCI_STAT_OVRD_REG0__RXPWR_5__SHIFT 0x00000000
+#define PB1_RX_LANE6_CTRL_REG0__RX_BACKUP_6_MASK 0x000000ffL
+#define PB1_RX_LANE6_CTRL_REG0__RX_BACKUP_6__SHIFT 0x00000000
+#define PB1_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6_MASK 0x00002000L
+#define PB1_RX_LANE6_CTRL_REG0__RX_CFG_OVR_PWRSF_6__SHIFT 0x0000000d
+#define PB1_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6_MASK 0x00000c00L
+#define PB1_RX_LANE6_CTRL_REG0__RX_DBG_ANALOG_SEL_6__SHIFT 0x0000000a
+#define PB1_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6_MASK 0x00001000L
+#define PB1_RX_LANE6_CTRL_REG0__RX_TST_BSCAN_EN_6__SHIFT 0x0000000c
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6_MASK 0x00000008L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_6__SHIFT 0x00000003
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6_MASK 0x00000080L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__ENABLEFOM_6__SHIFT 0x00000007
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6_MASK 0x00000100L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__REQUESTFOM_6__SHIFT 0x00000008
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6_MASK 0x00000200L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RESPONSEMODE_6__SHIFT 0x00000009
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6_MASK 0x00000070L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPRESETHINT_6__SHIFT 0x00000004
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6_MASK 0x00000007L
+#define PB1_RX_LANE6_SCI_STAT_OVRD_REG0__RXPWR_6__SHIFT 0x00000000
+#define PB1_RX_LANE7_CTRL_REG0__RX_BACKUP_7_MASK 0x000000ffL
+#define PB1_RX_LANE7_CTRL_REG0__RX_BACKUP_7__SHIFT 0x00000000
+#define PB1_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7_MASK 0x00002000L
+#define PB1_RX_LANE7_CTRL_REG0__RX_CFG_OVR_PWRSF_7__SHIFT 0x0000000d
+#define PB1_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7_MASK 0x00000c00L
+#define PB1_RX_LANE7_CTRL_REG0__RX_DBG_ANALOG_SEL_7__SHIFT 0x0000000a
+#define PB1_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7_MASK 0x00001000L
+#define PB1_RX_LANE7_CTRL_REG0__RX_TST_BSCAN_EN_7__SHIFT 0x0000000c
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7_MASK 0x00000008L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_7__SHIFT 0x00000003
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7_MASK 0x00000080L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__ENABLEFOM_7__SHIFT 0x00000007
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7_MASK 0x00000100L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__REQUESTFOM_7__SHIFT 0x00000008
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7_MASK 0x00000200L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RESPONSEMODE_7__SHIFT 0x00000009
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7_MASK 0x00000070L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPRESETHINT_7__SHIFT 0x00000004
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7_MASK 0x00000007L
+#define PB1_RX_LANE7_SCI_STAT_OVRD_REG0__RXPWR_7__SHIFT 0x00000000
+#define PB1_RX_LANE8_CTRL_REG0__RX_BACKUP_8_MASK 0x000000ffL
+#define PB1_RX_LANE8_CTRL_REG0__RX_BACKUP_8__SHIFT 0x00000000
+#define PB1_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8_MASK 0x00002000L
+#define PB1_RX_LANE8_CTRL_REG0__RX_CFG_OVR_PWRSF_8__SHIFT 0x0000000d
+#define PB1_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8_MASK 0x00000c00L
+#define PB1_RX_LANE8_CTRL_REG0__RX_DBG_ANALOG_SEL_8__SHIFT 0x0000000a
+#define PB1_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8_MASK 0x00001000L
+#define PB1_RX_LANE8_CTRL_REG0__RX_TST_BSCAN_EN_8__SHIFT 0x0000000c
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8_MASK 0x00000008L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_8__SHIFT 0x00000003
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8_MASK 0x00000080L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__ENABLEFOM_8__SHIFT 0x00000007
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8_MASK 0x00000100L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__REQUESTFOM_8__SHIFT 0x00000008
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8_MASK 0x00000200L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RESPONSEMODE_8__SHIFT 0x00000009
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8_MASK 0x00000070L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPRESETHINT_8__SHIFT 0x00000004
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8_MASK 0x00000007L
+#define PB1_RX_LANE8_SCI_STAT_OVRD_REG0__RXPWR_8__SHIFT 0x00000000
+#define PB1_RX_LANE9_CTRL_REG0__RX_BACKUP_9_MASK 0x000000ffL
+#define PB1_RX_LANE9_CTRL_REG0__RX_BACKUP_9__SHIFT 0x00000000
+#define PB1_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9_MASK 0x00002000L
+#define PB1_RX_LANE9_CTRL_REG0__RX_CFG_OVR_PWRSF_9__SHIFT 0x0000000d
+#define PB1_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9_MASK 0x00000c00L
+#define PB1_RX_LANE9_CTRL_REG0__RX_DBG_ANALOG_SEL_9__SHIFT 0x0000000a
+#define PB1_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9_MASK 0x00001000L
+#define PB1_RX_LANE9_CTRL_REG0__RX_TST_BSCAN_EN_9__SHIFT 0x0000000c
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9_MASK 0x00000008L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ELECIDLEDETEN_9__SHIFT 0x00000003
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9_MASK 0x00000080L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__ENABLEFOM_9__SHIFT 0x00000007
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9_MASK 0x00000100L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__REQUESTFOM_9__SHIFT 0x00000008
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9_MASK 0x00000200L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RESPONSEMODE_9__SHIFT 0x00000009
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9_MASK 0x00000070L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPRESETHINT_9__SHIFT 0x00000004
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9_MASK 0x00000007L
+#define PB1_RX_LANE9_SCI_STAT_OVRD_REG0__RXPWR_9__SHIFT 0x00000000
+#define PB1_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL_MASK 0x00008000L
+#define PB1_STRAP_GLB_REG0__STRAP_DBG_RXDLL_VREG_REF_SEL__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_0__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_10__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_11__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_12__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_13__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14_MASK 0x00004000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_14__SHIFT 0x0000000e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15_MASK 0x00008000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_15__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16_MASK 0x00010000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_16__SHIFT 0x00000010
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17_MASK 0x00020000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_17__SHIFT 0x00000011
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18_MASK 0x00040000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_18__SHIFT 0x00000012
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19_MASK 0x00080000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_19__SHIFT 0x00000013
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_1__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20_MASK 0x00100000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_20__SHIFT 0x00000014
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21_MASK 0x00200000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_21__SHIFT 0x00000015
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22_MASK 0x00400000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_22__SHIFT 0x00000016
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23_MASK 0x00800000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_23__SHIFT 0x00000017
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24_MASK 0x01000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_24__SHIFT 0x00000018
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25_MASK 0x02000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_25__SHIFT 0x00000019
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26_MASK 0x04000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_26__SHIFT 0x0000001a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27_MASK 0x08000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_27__SHIFT 0x0000001b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28_MASK 0x10000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_28__SHIFT 0x0000001c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29_MASK 0x20000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_29__SHIFT 0x0000001d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_2__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30_MASK 0x40000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_30__SHIFT 0x0000001e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31_MASK 0x80000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_31__SHIFT 0x0000001f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_3__SHIFT 0x00000003
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_4__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_5__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_6__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_7__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_8__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG0__ACCEPT_ENTRY_9__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_32__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_33__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_34__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_35__SHIFT 0x00000003
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_36__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_37__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_38__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_39__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_40__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_41__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_42__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_43__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_44__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_45__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46_MASK 0x00004000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_46__SHIFT 0x0000000e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47_MASK 0x00008000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_47__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48_MASK 0x00010000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_48__SHIFT 0x00000010
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49_MASK 0x00020000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_49__SHIFT 0x00000011
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50_MASK 0x00040000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_50__SHIFT 0x00000012
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51_MASK 0x00080000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_51__SHIFT 0x00000013
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52_MASK 0x00100000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_52__SHIFT 0x00000014
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53_MASK 0x00200000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_53__SHIFT 0x00000015
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54_MASK 0x00400000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_54__SHIFT 0x00000016
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55_MASK 0x00800000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_55__SHIFT 0x00000017
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56_MASK 0x01000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_56__SHIFT 0x00000018
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57_MASK 0x02000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_57__SHIFT 0x00000019
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58_MASK 0x04000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_58__SHIFT 0x0000001a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59_MASK 0x08000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_59__SHIFT 0x0000001b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60_MASK 0x10000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_60__SHIFT 0x0000001c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61_MASK 0x20000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_61__SHIFT 0x0000001d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62_MASK 0x40000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_62__SHIFT 0x0000001e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63_MASK 0x80000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG1__ACCEPT_ENTRY_63__SHIFT 0x0000001f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_64__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_65__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_66__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_67__SHIFT 0x00000003
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_68__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_69__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_70__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_71__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_72__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_73__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_74__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_75__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_76__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_77__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78_MASK 0x00004000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_78__SHIFT 0x0000000e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79_MASK 0x00008000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_79__SHIFT 0x0000000f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80_MASK 0x00010000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_80__SHIFT 0x00000010
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81_MASK 0x00020000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_81__SHIFT 0x00000011
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82_MASK 0x00040000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_82__SHIFT 0x00000012
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83_MASK 0x00080000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_83__SHIFT 0x00000013
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84_MASK 0x00100000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_84__SHIFT 0x00000014
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85_MASK 0x00200000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_85__SHIFT 0x00000015
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86_MASK 0x00400000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_86__SHIFT 0x00000016
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87_MASK 0x00800000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_87__SHIFT 0x00000017
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88_MASK 0x01000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_88__SHIFT 0x00000018
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89_MASK 0x02000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_89__SHIFT 0x00000019
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90_MASK 0x04000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_90__SHIFT 0x0000001a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91_MASK 0x08000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_91__SHIFT 0x0000001b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92_MASK 0x10000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_92__SHIFT 0x0000001c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93_MASK 0x20000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_93__SHIFT 0x0000001d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94_MASK 0x40000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_94__SHIFT 0x0000001e
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95_MASK 0x80000000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG2__ACCEPT_ENTRY_95__SHIFT 0x0000001f
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100_MASK 0x00000010L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_100__SHIFT 0x00000004
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101_MASK 0x00000020L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_101__SHIFT 0x00000005
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102_MASK 0x00000040L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_102__SHIFT 0x00000006
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103_MASK 0x00000080L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_103__SHIFT 0x00000007
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104_MASK 0x00000100L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_104__SHIFT 0x00000008
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105_MASK 0x00000200L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_105__SHIFT 0x00000009
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106_MASK 0x00000400L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_106__SHIFT 0x0000000a
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107_MASK 0x00000800L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_107__SHIFT 0x0000000b
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108_MASK 0x00001000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_108__SHIFT 0x0000000c
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109_MASK 0x00002000L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_109__SHIFT 0x0000000d
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96_MASK 0x00000001L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_96__SHIFT 0x00000000
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97_MASK 0x00000002L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_97__SHIFT 0x00000001
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98_MASK 0x00000004L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_98__SHIFT 0x00000002
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99_MASK 0x00000008L
+#define PB1_TX_GLB_COEFF_ACCEPT_TABLE_REG3__ACCEPT_ENTRY_99__SHIFT 0x00000003
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1_MASK 0x00000700L
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN1__SHIFT 0x00000008
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2_MASK 0x00003800L
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN2__SHIFT 0x0000000b
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3_MASK 0x0001c000L
+#define PB1_TX_GLB_CTRL_REG0__TX_CFG_RPTR_RST_VAL_GEN3__SHIFT 0x0000000e
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER_MASK 0x00400000L
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_DIR_VER__SHIFT 0x00000016
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN_MASK 0x00200000L
+#define PB1_TX_GLB_CTRL_REG0__TX_COEFF_ROUND_EN__SHIFT 0x00000015
+#define PB1_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING_MASK 0x00080000L
+#define PB1_TX_GLB_CTRL_REG0__TX_DATA_CLK_GATING__SHIFT 0x00000013
+#define PB1_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON_MASK 0x00800000L
+#define PB1_TX_GLB_CTRL_REG0__TX_DCLK_EN_LSX_ALWAYS_ON__SHIFT 0x00000017
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL_MASK 0x00000007L
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_ASRT_DLY_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL_MASK 0x00000038L
+#define PB1_TX_GLB_CTRL_REG0__TX_DRV_DATA_DSRT_DLY_VAL__SHIFT 0x00000003
+#define PB1_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF_MASK 0x01000000L
+#define PB1_TX_GLB_CTRL_REG0__TX_FRONTEND_PWRON_IN_OFF__SHIFT 0x00000018
+#define PB1_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS_MASK 0x00100000L
+#define PB1_TX_GLB_CTRL_REG0__TX_PRESET_TABLE_BYPASS__SHIFT 0x00000014
+#define PB1_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL_MASK 0x00060000L
+#define PB1_TX_GLB_CTRL_REG0__TX_STAGGER_CTRL__SHIFT 0x00000011
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15_MASK 0x40000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX16_EN_L0T15__SHIFT 0x0000001e
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0_MASK 0x00000001L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_0__SHIFT 0x00000000
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10_MASK 0x00000400L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_10__SHIFT 0x0000000a
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11_MASK 0x00000800L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_11__SHIFT 0x0000000b
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12_MASK 0x00001000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_12__SHIFT 0x0000000c
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13_MASK 0x00002000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_13__SHIFT 0x0000000d
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14_MASK 0x00004000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_14__SHIFT 0x0000000e
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15_MASK 0x00008000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_15__SHIFT 0x0000000f
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1_MASK 0x00000002L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_1__SHIFT 0x00000001
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2_MASK 0x00000004L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_2__SHIFT 0x00000002
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3_MASK 0x00000008L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_3__SHIFT 0x00000003
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4_MASK 0x00000010L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_4__SHIFT 0x00000004
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5_MASK 0x00000020L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_5__SHIFT 0x00000005
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6_MASK 0x00000040L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_6__SHIFT 0x00000006
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7_MASK 0x00000080L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_7__SHIFT 0x00000007
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8_MASK 0x00000100L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_8__SHIFT 0x00000008
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9_MASK 0x00000200L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX1_EN_9__SHIFT 0x00000009
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1_MASK 0x00010000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L0T1__SHIFT 0x00000010
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11_MASK 0x00200000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L10T11__SHIFT 0x00000015
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13_MASK 0x00400000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L12T13__SHIFT 0x00000016
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15_MASK 0x00800000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L14T15__SHIFT 0x00000017
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3_MASK 0x00020000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L2T3__SHIFT 0x00000011
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5_MASK 0x00040000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L4T5__SHIFT 0x00000012
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7_MASK 0x00080000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L6T7__SHIFT 0x00000013
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9_MASK 0x00100000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX2_EN_L8T9__SHIFT 0x00000014
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3_MASK 0x01000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L0T3__SHIFT 0x00000018
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15_MASK 0x08000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L12T15__SHIFT 0x0000001b
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7_MASK 0x02000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L4T7__SHIFT 0x00000019
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11_MASK 0x04000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX4_EN_L8T11__SHIFT 0x0000001a
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7_MASK 0x10000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L0T7__SHIFT 0x0000001c
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15_MASK 0x20000000L
+#define PB1_TX_GLB_LANE_SKEW_CTRL__TX_CFG_GROUPX8_EN_L8T15__SHIFT 0x0000001d
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN_MASK 0x00000008L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_EN__SHIFT 0x00000003
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL_MASK 0x00000007L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DCLK_DIV_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL_MASK 0x000000f0L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_GEN1_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_EN_OVRD_EN__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00001e00L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN_MASK 0x00002000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV0_TAP_SEL_OVRD_EN__SHIFT 0x0000000d
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL_MASK 0x0007c000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_GEN1_OVRD_VAL__SHIFT 0x0000000e
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN_MASK 0x00080000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_EN_OVRD_EN__SHIFT 0x00000013
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL_MASK 0x01f00000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000014
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN_MASK 0x02000000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV1_TAP_SEL_OVRD_EN__SHIFT 0x00000019
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL_MASK 0x3c000000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_GEN1_OVRD_VAL__SHIFT 0x0000001a
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN_MASK 0x40000000L
+#define PB1_TX_GLB_OVRD_REG0__TX_CFG_DRV2_EN_OVRD_EN__SHIFT 0x0000001e
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL_MASK 0x0000000fL
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN_MASK 0x00000010L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRV2_TAP_SEL_OVRD_EN__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL_MASK 0x00000020L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_GEN1_OVRD_VAL__SHIFT 0x00000005
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN_MASK 0x00000040L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_EN_OVRD_EN__SHIFT 0x00000006
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL_MASK 0x00000080L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_GEN1_OVRD_VAL__SHIFT 0x00000007
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_DRVX_TAP_SEL_OVRD_EN__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN_MASK 0x00000400L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_EN__SHIFT 0x0000000a
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL_MASK 0x00000200L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_PLLCLK_SEL_OVRD_VAL__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN_MASK 0x00001000L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_EN__SHIFT 0x0000000c
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL_MASK 0x00000800L
+#define PB1_TX_GLB_OVRD_REG1__TX_CFG_TCLK_DIV_OVRD_VAL__SHIFT 0x0000000b
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN_MASK 0x00004000L
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_EN__SHIFT 0x0000000e
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL_MASK 0x00002000L
+#define PB1_TX_GLB_OVRD_REG1__TX_CMDET_EN_OVRD_VAL__SHIFT 0x0000000d
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN_MASK 0x02000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_EN__SHIFT 0x00000019
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL_MASK 0x01ff8000L
+#define PB1_TX_GLB_OVRD_REG1__TX_DATA_IN_OVRD_VAL__SHIFT 0x0000000f
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN_MASK 0x08000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_EN__SHIFT 0x0000001b
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL_MASK 0x04000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RPTR_RSTN_OVRD_VAL__SHIFT 0x0000001a
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN_MASK 0x20000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_EN__SHIFT 0x0000001d
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL_MASK 0x10000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_RXDET_EN_OVRD_VAL__SHIFT 0x0000001c
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN_MASK 0x80000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_EN__SHIFT 0x0000001f
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL_MASK 0x40000000L
+#define PB1_TX_GLB_OVRD_REG1__TX_WPTR_RSTN_OVRD_VAL__SHIFT 0x0000001e
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL_MASK 0x0000f000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_EN_GEN2_OVRD_VAL__SHIFT 0x0000000c
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000f0000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV0_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000010
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL_MASK 0x01f00000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_EN_GEN2_OVRD_VAL__SHIFT 0x00000014
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL_MASK 0x3e000000L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_DRV1_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000019
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN_MASK 0x00000800L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_EN__SHIFT 0x0000000b
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL_MASK 0x00000400L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX16_EN_OVRD_VAL__SHIFT 0x0000000a
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN_MASK 0x00000008L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_EN__SHIFT 0x00000003
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL_MASK 0x00000004L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX1_EN_OVRD_VAL__SHIFT 0x00000002
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN_MASK 0x00000020L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_EN__SHIFT 0x00000005
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL_MASK 0x00000010L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX2_EN_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN_MASK 0x00000080L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_EN__SHIFT 0x00000007
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL_MASK 0x00000040L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX4_EN_OVRD_VAL__SHIFT 0x00000006
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN_MASK 0x00000200L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_EN__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG2__TX_CFG_GROUPX8_EN_OVRD_VAL__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN_MASK 0x00000002L
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_EN__SHIFT 0x00000001
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL_MASK 0x00000001L
+#define PB1_TX_GLB_OVRD_REG2__TX_WRITE_EN_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL_MASK 0x00003c00L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_EN_GEN3_OVRD_VAL__SHIFT 0x0000000a
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0003c000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV0_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x0000000e
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL_MASK 0x007c0000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_EN_GEN3_OVRD_VAL__SHIFT 0x00000012
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0f800000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV1_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000017
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL_MASK 0x0000000fL
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN2_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL_MASK 0xf0000000L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_EN_GEN3_OVRD_VAL__SHIFT 0x0000001c
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL_MASK 0x000000f0L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRV2_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL_MASK 0x00000100L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_EN_GEN2_OVRD_VAL__SHIFT 0x00000008
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL_MASK 0x00000200L
+#define PB1_TX_GLB_OVRD_REG3__TX_CFG_DRVX_TAP_SEL_GEN2_OVRD_VAL__SHIFT 0x00000009
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL_MASK 0x0000000fL
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRV2_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000000
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL_MASK 0x00000010L
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_EN_GEN3_OVRD_VAL__SHIFT 0x00000004
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL_MASK 0x00000020L
+#define PB1_TX_GLB_OVRD_REG4__TX_CFG_DRVX_TAP_SEL_GEN3_OVRD_VAL__SHIFT 0x00000005
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3_MASK 0x00000100L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L0T3__SHIFT 0x00000008
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15_MASK 0x00000800L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L12T15__SHIFT 0x0000000b
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7_MASK 0x00000200L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L4T7__SHIFT 0x00000009
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11_MASK 0x00000400L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENTID_SCI_UPDT_L8T11__SHIFT 0x0000000a
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3_MASK 0x00001000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L0T3__SHIFT 0x0000000c
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15_MASK 0x00008000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L12T15__SHIFT 0x0000000f
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7_MASK 0x00002000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L4T7__SHIFT 0x0000000d
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11_MASK 0x00004000L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_COEFFICIENT_SCI_UPDT_L8T11__SHIFT 0x0000000e
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3_MASK 0x00000010L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L0T3__SHIFT 0x00000004
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15_MASK 0x00000080L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L12T15__SHIFT 0x00000007
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7_MASK 0x00000020L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L4T7__SHIFT 0x00000005
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11_MASK 0x00000040L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_INCOHERENTCK_SCI_UPDT_L8T11__SHIFT 0x00000006
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3_MASK 0x00000001L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L0T3__SHIFT 0x00000000
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15_MASK 0x00000008L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L12T15__SHIFT 0x00000003
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7_MASK 0x00000002L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L4T7__SHIFT 0x00000001
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11_MASK 0x00000004L
+#define PB1_TX_GLB_SCI_STAT_OVRD_REG0__IGNR_TXPWR_SCI_UPDT_L8T11__SHIFT 0x00000002
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0_MASK 0x00000001L
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_DISPCLK_MODE_0__SHIFT 0x00000000
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0_MASK 0x00000002L
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_INV_DATA_0__SHIFT 0x00000001
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0_MASK 0x00000004L
+#define PB1_TX_LANE0_CTRL_REG0__TX_CFG_SWING_BOOST_EN_0__SHIFT 0x00000002
+#define PB1_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0_MASK 0x00000008L
+#define PB1_TX_LANE0_CTRL_REG0__TX_DBG_PRBS_EN_0__SHIFT 0x00000003
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0_MASK 0x00000002L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_EN_0__SHIFT 0x00000001
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0_MASK 0x00000001L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_0__SHIFT 0x00000000
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0_MASK 0x00000008L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_0__SHIFT 0x00000003
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0_MASK 0x00000004L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_0__SHIFT 0x00000002
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0_MASK 0x00000020L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_0__SHIFT 0x00000005
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0_MASK 0x00000010L
+#define PB1_TX_LANE0_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_0__SHIFT 0x00000004
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0_MASK 0x00000080L
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_0__SHIFT 0x00000007
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0_MASK 0x00000040L
+#define PB1_TX_LANE0_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_0__SHIFT 0x00000006
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0_MASK 0x0000fc00L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENT_0__SHIFT 0x0000000a
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0_MASK 0x00000300L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__COEFFICIENTID_0__SHIFT 0x00000008
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0_MASK 0x00000080L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__DEEMPH_0__SHIFT 0x00000007
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0_MASK 0x00000008L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__INCOHERENTCK_0__SHIFT 0x00000003
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0_MASK 0x00000070L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXMARG_0__SHIFT 0x00000004
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0_MASK 0x00000007L
+#define PB1_TX_LANE0_SCI_STAT_OVRD_REG0__TXPWR_0__SHIFT 0x00000000
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10_MASK 0x00000001L
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_DISPCLK_MODE_10__SHIFT 0x00000000
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10_MASK 0x00000002L
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_INV_DATA_10__SHIFT 0x00000001
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10_MASK 0x00000004L
+#define PB1_TX_LANE10_CTRL_REG0__TX_CFG_SWING_BOOST_EN_10__SHIFT 0x00000002
+#define PB1_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10_MASK 0x00000008L
+#define PB1_TX_LANE10_CTRL_REG0__TX_DBG_PRBS_EN_10__SHIFT 0x00000003
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10_MASK 0x00000002L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_EN_10__SHIFT 0x00000001
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10_MASK 0x00000001L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_10__SHIFT 0x00000000
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10_MASK 0x00000008L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_10__SHIFT 0x00000003
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10_MASK 0x00000004L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_10__SHIFT 0x00000002
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10_MASK 0x00000020L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_10__SHIFT 0x00000005
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10_MASK 0x00000010L
+#define PB1_TX_LANE10_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_10__SHIFT 0x00000004
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10_MASK 0x00000080L
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_10__SHIFT 0x00000007
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10_MASK 0x00000040L
+#define PB1_TX_LANE10_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_10__SHIFT 0x00000006
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10_MASK 0x0000fc00L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENT_10__SHIFT 0x0000000a
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10_MASK 0x00000300L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__COEFFICIENTID_10__SHIFT 0x00000008
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10_MASK 0x00000080L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__DEEMPH_10__SHIFT 0x00000007
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10_MASK 0x00000008L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__INCOHERENTCK_10__SHIFT 0x00000003
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10_MASK 0x00000070L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXMARG_10__SHIFT 0x00000004
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10_MASK 0x00000007L
+#define PB1_TX_LANE10_SCI_STAT_OVRD_REG0__TXPWR_10__SHIFT 0x00000000
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11_MASK 0x00000001L
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_DISPCLK_MODE_11__SHIFT 0x00000000
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11_MASK 0x00000002L
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_INV_DATA_11__SHIFT 0x00000001
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11_MASK 0x00000004L
+#define PB1_TX_LANE11_CTRL_REG0__TX_CFG_SWING_BOOST_EN_11__SHIFT 0x00000002
+#define PB1_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11_MASK 0x00000008L
+#define PB1_TX_LANE11_CTRL_REG0__TX_DBG_PRBS_EN_11__SHIFT 0x00000003
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11_MASK 0x00000002L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_EN_11__SHIFT 0x00000001
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11_MASK 0x00000001L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_11__SHIFT 0x00000000
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11_MASK 0x00000008L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_11__SHIFT 0x00000003
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11_MASK 0x00000004L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_11__SHIFT 0x00000002
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11_MASK 0x00000020L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_11__SHIFT 0x00000005
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11_MASK 0x00000010L
+#define PB1_TX_LANE11_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_11__SHIFT 0x00000004
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11_MASK 0x00000080L
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_11__SHIFT 0x00000007
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11_MASK 0x00000040L
+#define PB1_TX_LANE11_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_11__SHIFT 0x00000006
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11_MASK 0x0000fc00L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENT_11__SHIFT 0x0000000a
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11_MASK 0x00000300L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__COEFFICIENTID_11__SHIFT 0x00000008
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11_MASK 0x00000080L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__DEEMPH_11__SHIFT 0x00000007
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11_MASK 0x00000008L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__INCOHERENTCK_11__SHIFT 0x00000003
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11_MASK 0x00000070L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXMARG_11__SHIFT 0x00000004
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11_MASK 0x00000007L
+#define PB1_TX_LANE11_SCI_STAT_OVRD_REG0__TXPWR_11__SHIFT 0x00000000
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12_MASK 0x00000001L
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_DISPCLK_MODE_12__SHIFT 0x00000000
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12_MASK 0x00000002L
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_INV_DATA_12__SHIFT 0x00000001
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12_MASK 0x00000004L
+#define PB1_TX_LANE12_CTRL_REG0__TX_CFG_SWING_BOOST_EN_12__SHIFT 0x00000002
+#define PB1_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12_MASK 0x00000008L
+#define PB1_TX_LANE12_CTRL_REG0__TX_DBG_PRBS_EN_12__SHIFT 0x00000003
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12_MASK 0x00000002L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_EN_12__SHIFT 0x00000001
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12_MASK 0x00000001L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_12__SHIFT 0x00000000
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12_MASK 0x00000008L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_12__SHIFT 0x00000003
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12_MASK 0x00000004L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_12__SHIFT 0x00000002
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12_MASK 0x00000020L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_12__SHIFT 0x00000005
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12_MASK 0x00000010L
+#define PB1_TX_LANE12_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_12__SHIFT 0x00000004
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12_MASK 0x00000080L
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_12__SHIFT 0x00000007
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12_MASK 0x00000040L
+#define PB1_TX_LANE12_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_12__SHIFT 0x00000006
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12_MASK 0x0000fc00L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENT_12__SHIFT 0x0000000a
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12_MASK 0x00000300L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__COEFFICIENTID_12__SHIFT 0x00000008
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12_MASK 0x00000080L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__DEEMPH_12__SHIFT 0x00000007
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12_MASK 0x00000008L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__INCOHERENTCK_12__SHIFT 0x00000003
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12_MASK 0x00000070L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXMARG_12__SHIFT 0x00000004
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12_MASK 0x00000007L
+#define PB1_TX_LANE12_SCI_STAT_OVRD_REG0__TXPWR_12__SHIFT 0x00000000
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13_MASK 0x00000001L
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_DISPCLK_MODE_13__SHIFT 0x00000000
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13_MASK 0x00000002L
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_INV_DATA_13__SHIFT 0x00000001
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13_MASK 0x00000004L
+#define PB1_TX_LANE13_CTRL_REG0__TX_CFG_SWING_BOOST_EN_13__SHIFT 0x00000002
+#define PB1_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13_MASK 0x00000008L
+#define PB1_TX_LANE13_CTRL_REG0__TX_DBG_PRBS_EN_13__SHIFT 0x00000003
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13_MASK 0x00000002L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_EN_13__SHIFT 0x00000001
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13_MASK 0x00000001L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_13__SHIFT 0x00000000
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13_MASK 0x00000008L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_13__SHIFT 0x00000003
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13_MASK 0x00000004L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_13__SHIFT 0x00000002
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13_MASK 0x00000020L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_13__SHIFT 0x00000005
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13_MASK 0x00000010L
+#define PB1_TX_LANE13_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_13__SHIFT 0x00000004
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13_MASK 0x00000080L
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_13__SHIFT 0x00000007
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13_MASK 0x00000040L
+#define PB1_TX_LANE13_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_13__SHIFT 0x00000006
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13_MASK 0x0000fc00L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENT_13__SHIFT 0x0000000a
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13_MASK 0x00000300L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__COEFFICIENTID_13__SHIFT 0x00000008
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13_MASK 0x00000080L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__DEEMPH_13__SHIFT 0x00000007
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13_MASK 0x00000008L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__INCOHERENTCK_13__SHIFT 0x00000003
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13_MASK 0x00000070L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXMARG_13__SHIFT 0x00000004
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13_MASK 0x00000007L
+#define PB1_TX_LANE13_SCI_STAT_OVRD_REG0__TXPWR_13__SHIFT 0x00000000
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14_MASK 0x00000001L
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_DISPCLK_MODE_14__SHIFT 0x00000000
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14_MASK 0x00000002L
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_INV_DATA_14__SHIFT 0x00000001
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14_MASK 0x00000004L
+#define PB1_TX_LANE14_CTRL_REG0__TX_CFG_SWING_BOOST_EN_14__SHIFT 0x00000002
+#define PB1_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14_MASK 0x00000008L
+#define PB1_TX_LANE14_CTRL_REG0__TX_DBG_PRBS_EN_14__SHIFT 0x00000003
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14_MASK 0x00000002L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_EN_14__SHIFT 0x00000001
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14_MASK 0x00000001L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_14__SHIFT 0x00000000
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14_MASK 0x00000008L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_14__SHIFT 0x00000003
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14_MASK 0x00000004L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_14__SHIFT 0x00000002
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14_MASK 0x00000020L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_14__SHIFT 0x00000005
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14_MASK 0x00000010L
+#define PB1_TX_LANE14_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_14__SHIFT 0x00000004
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14_MASK 0x00000080L
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_14__SHIFT 0x00000007
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14_MASK 0x00000040L
+#define PB1_TX_LANE14_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_14__SHIFT 0x00000006
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14_MASK 0x0000fc00L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENT_14__SHIFT 0x0000000a
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14_MASK 0x00000300L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__COEFFICIENTID_14__SHIFT 0x00000008
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14_MASK 0x00000080L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__DEEMPH_14__SHIFT 0x00000007
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14_MASK 0x00000008L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__INCOHERENTCK_14__SHIFT 0x00000003
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14_MASK 0x00000070L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXMARG_14__SHIFT 0x00000004
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14_MASK 0x00000007L
+#define PB1_TX_LANE14_SCI_STAT_OVRD_REG0__TXPWR_14__SHIFT 0x00000000
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15_MASK 0x00000001L
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_DISPCLK_MODE_15__SHIFT 0x00000000
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15_MASK 0x00000002L
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_INV_DATA_15__SHIFT 0x00000001
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15_MASK 0x00000004L
+#define PB1_TX_LANE15_CTRL_REG0__TX_CFG_SWING_BOOST_EN_15__SHIFT 0x00000002
+#define PB1_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15_MASK 0x00000008L
+#define PB1_TX_LANE15_CTRL_REG0__TX_DBG_PRBS_EN_15__SHIFT 0x00000003
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15_MASK 0x00000002L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_EN_15__SHIFT 0x00000001
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15_MASK 0x00000001L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_15__SHIFT 0x00000000
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15_MASK 0x00000008L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_15__SHIFT 0x00000003
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15_MASK 0x00000004L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_15__SHIFT 0x00000002
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15_MASK 0x00000020L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_15__SHIFT 0x00000005
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15_MASK 0x00000010L
+#define PB1_TX_LANE15_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_15__SHIFT 0x00000004
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15_MASK 0x00000080L
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_15__SHIFT 0x00000007
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15_MASK 0x00000040L
+#define PB1_TX_LANE15_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_15__SHIFT 0x00000006
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15_MASK 0x0000fc00L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENT_15__SHIFT 0x0000000a
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15_MASK 0x00000300L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__COEFFICIENTID_15__SHIFT 0x00000008
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15_MASK 0x00000080L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__DEEMPH_15__SHIFT 0x00000007
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15_MASK 0x00000008L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__INCOHERENTCK_15__SHIFT 0x00000003
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15_MASK 0x00000070L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXMARG_15__SHIFT 0x00000004
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15_MASK 0x00000007L
+#define PB1_TX_LANE15_SCI_STAT_OVRD_REG0__TXPWR_15__SHIFT 0x00000000
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1_MASK 0x00000001L
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_DISPCLK_MODE_1__SHIFT 0x00000000
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1_MASK 0x00000002L
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_INV_DATA_1__SHIFT 0x00000001
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1_MASK 0x00000004L
+#define PB1_TX_LANE1_CTRL_REG0__TX_CFG_SWING_BOOST_EN_1__SHIFT 0x00000002
+#define PB1_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1_MASK 0x00000008L
+#define PB1_TX_LANE1_CTRL_REG0__TX_DBG_PRBS_EN_1__SHIFT 0x00000003
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1_MASK 0x00000002L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_EN_1__SHIFT 0x00000001
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1_MASK 0x00000001L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_1__SHIFT 0x00000000
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1_MASK 0x00000008L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_1__SHIFT 0x00000003
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1_MASK 0x00000004L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_1__SHIFT 0x00000002
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1_MASK 0x00000020L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_1__SHIFT 0x00000005
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1_MASK 0x00000010L
+#define PB1_TX_LANE1_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_1__SHIFT 0x00000004
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1_MASK 0x00000080L
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_1__SHIFT 0x00000007
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1_MASK 0x00000040L
+#define PB1_TX_LANE1_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_1__SHIFT 0x00000006
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1_MASK 0x0000fc00L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENT_1__SHIFT 0x0000000a
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1_MASK 0x00000300L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__COEFFICIENTID_1__SHIFT 0x00000008
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1_MASK 0x00000080L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__DEEMPH_1__SHIFT 0x00000007
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1_MASK 0x00000008L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__INCOHERENTCK_1__SHIFT 0x00000003
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1_MASK 0x00000070L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXMARG_1__SHIFT 0x00000004
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1_MASK 0x00000007L
+#define PB1_TX_LANE1_SCI_STAT_OVRD_REG0__TXPWR_1__SHIFT 0x00000000
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2_MASK 0x00000001L
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_DISPCLK_MODE_2__SHIFT 0x00000000
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2_MASK 0x00000002L
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_INV_DATA_2__SHIFT 0x00000001
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2_MASK 0x00000004L
+#define PB1_TX_LANE2_CTRL_REG0__TX_CFG_SWING_BOOST_EN_2__SHIFT 0x00000002
+#define PB1_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2_MASK 0x00000008L
+#define PB1_TX_LANE2_CTRL_REG0__TX_DBG_PRBS_EN_2__SHIFT 0x00000003
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2_MASK 0x00000002L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_EN_2__SHIFT 0x00000001
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2_MASK 0x00000001L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_2__SHIFT 0x00000000
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2_MASK 0x00000008L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_2__SHIFT 0x00000003
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2_MASK 0x00000004L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_2__SHIFT 0x00000002
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2_MASK 0x00000020L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_2__SHIFT 0x00000005
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2_MASK 0x00000010L
+#define PB1_TX_LANE2_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_2__SHIFT 0x00000004
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2_MASK 0x00000080L
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_2__SHIFT 0x00000007
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2_MASK 0x00000040L
+#define PB1_TX_LANE2_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_2__SHIFT 0x00000006
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2_MASK 0x0000fc00L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENT_2__SHIFT 0x0000000a
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2_MASK 0x00000300L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__COEFFICIENTID_2__SHIFT 0x00000008
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2_MASK 0x00000080L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__DEEMPH_2__SHIFT 0x00000007
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2_MASK 0x00000008L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__INCOHERENTCK_2__SHIFT 0x00000003
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2_MASK 0x00000070L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXMARG_2__SHIFT 0x00000004
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2_MASK 0x00000007L
+#define PB1_TX_LANE2_SCI_STAT_OVRD_REG0__TXPWR_2__SHIFT 0x00000000
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3_MASK 0x00000001L
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_DISPCLK_MODE_3__SHIFT 0x00000000
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3_MASK 0x00000002L
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_INV_DATA_3__SHIFT 0x00000001
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3_MASK 0x00000004L
+#define PB1_TX_LANE3_CTRL_REG0__TX_CFG_SWING_BOOST_EN_3__SHIFT 0x00000002
+#define PB1_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3_MASK 0x00000008L
+#define PB1_TX_LANE3_CTRL_REG0__TX_DBG_PRBS_EN_3__SHIFT 0x00000003
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3_MASK 0x00000002L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_EN_3__SHIFT 0x00000001
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3_MASK 0x00000001L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_3__SHIFT 0x00000000
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3_MASK 0x00000008L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_3__SHIFT 0x00000003
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3_MASK 0x00000004L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_3__SHIFT 0x00000002
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3_MASK 0x00000020L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_3__SHIFT 0x00000005
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3_MASK 0x00000010L
+#define PB1_TX_LANE3_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_3__SHIFT 0x00000004
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3_MASK 0x00000080L
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_3__SHIFT 0x00000007
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3_MASK 0x00000040L
+#define PB1_TX_LANE3_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_3__SHIFT 0x00000006
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3_MASK 0x0000fc00L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENT_3__SHIFT 0x0000000a
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3_MASK 0x00000300L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__COEFFICIENTID_3__SHIFT 0x00000008
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3_MASK 0x00000080L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__DEEMPH_3__SHIFT 0x00000007
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3_MASK 0x00000008L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__INCOHERENTCK_3__SHIFT 0x00000003
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3_MASK 0x00000070L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXMARG_3__SHIFT 0x00000004
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3_MASK 0x00000007L
+#define PB1_TX_LANE3_SCI_STAT_OVRD_REG0__TXPWR_3__SHIFT 0x00000000
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4_MASK 0x00000001L
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_DISPCLK_MODE_4__SHIFT 0x00000000
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4_MASK 0x00000002L
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_INV_DATA_4__SHIFT 0x00000001
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4_MASK 0x00000004L
+#define PB1_TX_LANE4_CTRL_REG0__TX_CFG_SWING_BOOST_EN_4__SHIFT 0x00000002
+#define PB1_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4_MASK 0x00000008L
+#define PB1_TX_LANE4_CTRL_REG0__TX_DBG_PRBS_EN_4__SHIFT 0x00000003
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4_MASK 0x00000002L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_EN_4__SHIFT 0x00000001
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4_MASK 0x00000001L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_4__SHIFT 0x00000000
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4_MASK 0x00000008L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_4__SHIFT 0x00000003
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4_MASK 0x00000004L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_4__SHIFT 0x00000002
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4_MASK 0x00000020L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_4__SHIFT 0x00000005
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4_MASK 0x00000010L
+#define PB1_TX_LANE4_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_4__SHIFT 0x00000004
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4_MASK 0x00000080L
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_4__SHIFT 0x00000007
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4_MASK 0x00000040L
+#define PB1_TX_LANE4_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_4__SHIFT 0x00000006
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4_MASK 0x0000fc00L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENT_4__SHIFT 0x0000000a
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4_MASK 0x00000300L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__COEFFICIENTID_4__SHIFT 0x00000008
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4_MASK 0x00000080L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__DEEMPH_4__SHIFT 0x00000007
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4_MASK 0x00000008L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__INCOHERENTCK_4__SHIFT 0x00000003
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4_MASK 0x00000070L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXMARG_4__SHIFT 0x00000004
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4_MASK 0x00000007L
+#define PB1_TX_LANE4_SCI_STAT_OVRD_REG0__TXPWR_4__SHIFT 0x00000000
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5_MASK 0x00000001L
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_DISPCLK_MODE_5__SHIFT 0x00000000
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5_MASK 0x00000002L
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_INV_DATA_5__SHIFT 0x00000001
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5_MASK 0x00000004L
+#define PB1_TX_LANE5_CTRL_REG0__TX_CFG_SWING_BOOST_EN_5__SHIFT 0x00000002
+#define PB1_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5_MASK 0x00000008L
+#define PB1_TX_LANE5_CTRL_REG0__TX_DBG_PRBS_EN_5__SHIFT 0x00000003
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5_MASK 0x00000002L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_EN_5__SHIFT 0x00000001
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5_MASK 0x00000001L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_5__SHIFT 0x00000000
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5_MASK 0x00000008L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_5__SHIFT 0x00000003
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5_MASK 0x00000004L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_5__SHIFT 0x00000002
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5_MASK 0x00000020L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_5__SHIFT 0x00000005
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5_MASK 0x00000010L
+#define PB1_TX_LANE5_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_5__SHIFT 0x00000004
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5_MASK 0x00000080L
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_5__SHIFT 0x00000007
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5_MASK 0x00000040L
+#define PB1_TX_LANE5_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_5__SHIFT 0x00000006
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5_MASK 0x0000fc00L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENT_5__SHIFT 0x0000000a
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5_MASK 0x00000300L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__COEFFICIENTID_5__SHIFT 0x00000008
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5_MASK 0x00000080L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__DEEMPH_5__SHIFT 0x00000007
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5_MASK 0x00000008L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__INCOHERENTCK_5__SHIFT 0x00000003
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5_MASK 0x00000070L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXMARG_5__SHIFT 0x00000004
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5_MASK 0x00000007L
+#define PB1_TX_LANE5_SCI_STAT_OVRD_REG0__TXPWR_5__SHIFT 0x00000000
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6_MASK 0x00000001L
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_DISPCLK_MODE_6__SHIFT 0x00000000
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6_MASK 0x00000002L
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_INV_DATA_6__SHIFT 0x00000001
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6_MASK 0x00000004L
+#define PB1_TX_LANE6_CTRL_REG0__TX_CFG_SWING_BOOST_EN_6__SHIFT 0x00000002
+#define PB1_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6_MASK 0x00000008L
+#define PB1_TX_LANE6_CTRL_REG0__TX_DBG_PRBS_EN_6__SHIFT 0x00000003
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6_MASK 0x00000002L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_EN_6__SHIFT 0x00000001
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6_MASK 0x00000001L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_6__SHIFT 0x00000000
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6_MASK 0x00000008L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_6__SHIFT 0x00000003
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6_MASK 0x00000004L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_6__SHIFT 0x00000002
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6_MASK 0x00000020L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_6__SHIFT 0x00000005
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6_MASK 0x00000010L
+#define PB1_TX_LANE6_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_6__SHIFT 0x00000004
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6_MASK 0x00000080L
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_6__SHIFT 0x00000007
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6_MASK 0x00000040L
+#define PB1_TX_LANE6_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_6__SHIFT 0x00000006
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6_MASK 0x0000fc00L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENT_6__SHIFT 0x0000000a
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6_MASK 0x00000300L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__COEFFICIENTID_6__SHIFT 0x00000008
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6_MASK 0x00000080L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__DEEMPH_6__SHIFT 0x00000007
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6_MASK 0x00000008L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__INCOHERENTCK_6__SHIFT 0x00000003
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6_MASK 0x00000070L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXMARG_6__SHIFT 0x00000004
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6_MASK 0x00000007L
+#define PB1_TX_LANE6_SCI_STAT_OVRD_REG0__TXPWR_6__SHIFT 0x00000000
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7_MASK 0x00000001L
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_DISPCLK_MODE_7__SHIFT 0x00000000
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7_MASK 0x00000002L
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_INV_DATA_7__SHIFT 0x00000001
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7_MASK 0x00000004L
+#define PB1_TX_LANE7_CTRL_REG0__TX_CFG_SWING_BOOST_EN_7__SHIFT 0x00000002
+#define PB1_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7_MASK 0x00000008L
+#define PB1_TX_LANE7_CTRL_REG0__TX_DBG_PRBS_EN_7__SHIFT 0x00000003
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7_MASK 0x00000002L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_EN_7__SHIFT 0x00000001
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7_MASK 0x00000001L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_7__SHIFT 0x00000000
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7_MASK 0x00000008L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_7__SHIFT 0x00000003
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7_MASK 0x00000004L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_7__SHIFT 0x00000002
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7_MASK 0x00000020L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_7__SHIFT 0x00000005
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7_MASK 0x00000010L
+#define PB1_TX_LANE7_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_7__SHIFT 0x00000004
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7_MASK 0x00000080L
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_7__SHIFT 0x00000007
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7_MASK 0x00000040L
+#define PB1_TX_LANE7_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_7__SHIFT 0x00000006
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7_MASK 0x0000fc00L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENT_7__SHIFT 0x0000000a
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7_MASK 0x00000300L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__COEFFICIENTID_7__SHIFT 0x00000008
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7_MASK 0x00000080L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__DEEMPH_7__SHIFT 0x00000007
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7_MASK 0x00000008L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__INCOHERENTCK_7__SHIFT 0x00000003
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7_MASK 0x00000070L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXMARG_7__SHIFT 0x00000004
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7_MASK 0x00000007L
+#define PB1_TX_LANE7_SCI_STAT_OVRD_REG0__TXPWR_7__SHIFT 0x00000000
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8_MASK 0x00000001L
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_DISPCLK_MODE_8__SHIFT 0x00000000
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8_MASK 0x00000002L
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_INV_DATA_8__SHIFT 0x00000001
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8_MASK 0x00000004L
+#define PB1_TX_LANE8_CTRL_REG0__TX_CFG_SWING_BOOST_EN_8__SHIFT 0x00000002
+#define PB1_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8_MASK 0x00000008L
+#define PB1_TX_LANE8_CTRL_REG0__TX_DBG_PRBS_EN_8__SHIFT 0x00000003
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8_MASK 0x00000002L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_EN_8__SHIFT 0x00000001
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8_MASK 0x00000001L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_8__SHIFT 0x00000000
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8_MASK 0x00000008L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_8__SHIFT 0x00000003
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8_MASK 0x00000004L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_8__SHIFT 0x00000002
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8_MASK 0x00000020L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_8__SHIFT 0x00000005
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8_MASK 0x00000010L
+#define PB1_TX_LANE8_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_8__SHIFT 0x00000004
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8_MASK 0x00000080L
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_8__SHIFT 0x00000007
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8_MASK 0x00000040L
+#define PB1_TX_LANE8_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_8__SHIFT 0x00000006
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8_MASK 0x0000fc00L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENT_8__SHIFT 0x0000000a
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8_MASK 0x00000300L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__COEFFICIENTID_8__SHIFT 0x00000008
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8_MASK 0x00000080L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__DEEMPH_8__SHIFT 0x00000007
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8_MASK 0x00000008L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__INCOHERENTCK_8__SHIFT 0x00000003
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8_MASK 0x00000070L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXMARG_8__SHIFT 0x00000004
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8_MASK 0x00000007L
+#define PB1_TX_LANE8_SCI_STAT_OVRD_REG0__TXPWR_8__SHIFT 0x00000000
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9_MASK 0x00000001L
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_DISPCLK_MODE_9__SHIFT 0x00000000
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9_MASK 0x00000002L
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_INV_DATA_9__SHIFT 0x00000001
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9_MASK 0x00000004L
+#define PB1_TX_LANE9_CTRL_REG0__TX_CFG_SWING_BOOST_EN_9__SHIFT 0x00000002
+#define PB1_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9_MASK 0x00000008L
+#define PB1_TX_LANE9_CTRL_REG0__TX_DBG_PRBS_EN_9__SHIFT 0x00000003
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9_MASK 0x00000002L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_EN_9__SHIFT 0x00000001
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9_MASK 0x00000001L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DCLK_EN_OVRD_VAL_9__SHIFT 0x00000000
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9_MASK 0x00000008L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_EN_9__SHIFT 0x00000003
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9_MASK 0x00000004L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_DATA_EN_OVRD_VAL_9__SHIFT 0x00000002
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9_MASK 0x00000020L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_EN_9__SHIFT 0x00000005
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9_MASK 0x00000010L
+#define PB1_TX_LANE9_OVRD_REG0__TX_DRV_PWRON_OVRD_VAL_9__SHIFT 0x00000004
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9_MASK 0x00000080L
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_EN_9__SHIFT 0x00000007
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9_MASK 0x00000040L
+#define PB1_TX_LANE9_OVRD_REG0__TX_FRONTEND_PWRON_OVRD_VAL_9__SHIFT 0x00000006
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9_MASK 0x0000fc00L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENT_9__SHIFT 0x0000000a
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9_MASK 0x00000300L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__COEFFICIENTID_9__SHIFT 0x00000008
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9_MASK 0x00000080L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__DEEMPH_9__SHIFT 0x00000007
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9_MASK 0x00000008L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__INCOHERENTCK_9__SHIFT 0x00000003
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9_MASK 0x00000070L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXMARG_9__SHIFT 0x00000004
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9_MASK 0x00000007L
+#define PB1_TX_LANE9_SCI_STAT_OVRD_REG0__TXPWR_9__SHIFT 0x00000000
+#define PCIE_BUS_CNTL__IMMEDIATE_PMI_DIS_MASK 0x00000080L
+#define PCIE_BUS_CNTL__IMMEDIATE_PMI_DIS__SHIFT 0x00000007
+#define PCIE_BUS_CNTL__PMI_INT_DIS_MASK 0x00000040L
+#define PCIE_BUS_CNTL__PMI_INT_DIS__SHIFT 0x00000006
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN2_HIDDEN_REG_MASK 0x00000001L
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN2_HIDDEN_REG__SHIFT 0x00000000
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN3_HIDDEN_REG_MASK 0x00000004L
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_GEN3_HIDDEN_REG__SHIFT 0x00000002
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_HIDDEN_REG_MASK 0x00000002L
+#define PCIE_CFG_CNTL__CFG_EN_DEC_TO_HIDDEN_REG__SHIFT 0x00000001
+#define PCIE_CI_CNTL__CI_MST_CMPL_DUMMY_DATA_MASK 0x00000010L
+#define PCIE_CI_CNTL__CI_MST_CMPL_DUMMY_DATA__SHIFT 0x00000004
+#define PCIE_CI_CNTL__CI_MST_IGNORE_PAGE_ALIGNED_REQUEST_MASK 0x00002000L
+#define PCIE_CI_CNTL__CI_MST_IGNORE_PAGE_ALIGNED_REQUEST__SHIFT 0x0000000d
+#define PCIE_CI_CNTL__CI_RC_ORDERING_DIS_MASK 0x00000200L
+#define PCIE_CI_CNTL__CI_RC_ORDERING_DIS__SHIFT 0x00000009
+#define PCIE_CI_CNTL__CI_SLAVE_GEN_USR_DIS_MASK 0x00000008L
+#define PCIE_CI_CNTL__CI_SLAVE_GEN_USR_DIS__SHIFT 0x00000003
+#define PCIE_CI_CNTL__CI_SLAVE_SPLIT_MODE_MASK 0x00000004L
+#define PCIE_CI_CNTL__CI_SLAVE_SPLIT_MODE__SHIFT 0x00000002
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_DIS_MASK 0x00000400L
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_DIS__SHIFT 0x0000000a
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_MODE_MASK 0x00000800L
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_MODE__SHIFT 0x0000000b
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_SOR_MASK 0x00001000L
+#define PCIE_CI_CNTL__CI_SLV_CPL_ALLOC_SOR__SHIFT 0x0000000c
+#define PCIE_CI_CNTL__CI_SLV_ORDERING_DIS_MASK 0x00000100L
+#define PCIE_CI_CNTL__CI_SLV_ORDERING_DIS__SHIFT 0x00000008
+#define PCIE_CI_CNTL__CI_SLV_RC_RD_REQ_SIZE_MASK 0x000000c0L
+#define PCIE_CI_CNTL__CI_SLV_RC_RD_REQ_SIZE__SHIFT 0x00000006
+#define PCIE_CNTL2__MST_MEM_LS_EN_MASK 0x00040000L
+#define PCIE_CNTL2__MST_MEM_LS_EN__SHIFT 0x00000012
+#define PCIE_CNTL2__MST_MEM_SD_EN_MASK 0x00400000L
+#define PCIE_CNTL2__MST_MEM_SD_EN__SHIFT 0x00000016
+#define PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK 0x00080000L
+#define PCIE_CNTL2__REPLAY_MEM_LS_EN__SHIFT 0x00000013
+#define PCIE_CNTL2__REPLAY_MEM_SD_EN_MASK 0x00800000L
+#define PCIE_CNTL2__REPLAY_MEM_SD_EN__SHIFT 0x00000017
+#define PCIE_CNTL2__RX_NP_MEM_WRITE_ENCODING_MASK 0x1f000000L
+#define PCIE_CNTL2__RX_NP_MEM_WRITE_ENCODING__SHIFT 0x00000018
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_LS_EN_MASK 0x00020000L
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_LS_EN__SHIFT 0x00000011
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_SD_EN_MASK 0x00200000L
+#define PCIE_CNTL2__SLV_MEM_AGGRESSIVE_SD_EN__SHIFT 0x00000015
+#define PCIE_CNTL2__SLV_MEM_LS_EN_MASK 0x00010000L
+#define PCIE_CNTL2__SLV_MEM_LS_EN__SHIFT 0x00000010
+#define PCIE_CNTL2__SLV_MEM_SD_EN_MASK 0x00100000L
+#define PCIE_CNTL2__SLV_MEM_SD_EN__SHIFT 0x00000014
+#define PCIE_CNTL2__TX_ARB_MST_LIMIT_MASK 0x000007c0L
+#define PCIE_CNTL2__TX_ARB_MST_LIMIT__SHIFT 0x00000006
+#define PCIE_CNTL2__TX_ARB_ROUND_ROBIN_EN_MASK 0x00000001L
+#define PCIE_CNTL2__TX_ARB_ROUND_ROBIN_EN__SHIFT 0x00000000
+#define PCIE_CNTL2__TX_ARB_SLV_LIMIT_MASK 0x0000003eL
+#define PCIE_CNTL2__TX_ARB_SLV_LIMIT__SHIFT 0x00000001
+#define PCIE_CNTL__HWINIT_WR_LOCK_MASK 0x00000001L
+#define PCIE_CNTL__HWINIT_WR_LOCK__SHIFT 0x00000000
+#define PCIE_CNTL__LC_HOT_PLUG_DELAY_SEL_MASK 0x0000000eL
+#define PCIE_CNTL__LC_HOT_PLUG_DELAY_SEL__SHIFT 0x00000001
+#define PCIE_CNTL__PCIE_HT_NP_MEM_WRITE_MASK 0x00000200L
+#define PCIE_CNTL__PCIE_HT_NP_MEM_WRITE__SHIFT 0x00000009
+#define PCIE_CNTL__PCIE_MALFORM_ATOMIC_OPS_MASK 0x00000100L
+#define PCIE_CNTL__PCIE_MALFORM_ATOMIC_OPS__SHIFT 0x00000008
+#define PCIE_CNTL__RX_ATS_TRAN_CPL_SPLIT_DIS_MASK 0x00800000L
+#define PCIE_CNTL__RX_ATS_TRAN_CPL_SPLIT_DIS__SHIFT 0x00000017
+#define PCIE_CNTL__RX_CPL_POSTED_REQ_ORD_EN_MASK 0x80000000L
+#define PCIE_CNTL__RX_CPL_POSTED_REQ_ORD_EN__SHIFT 0x0000001f
+#define PCIE_CNTL__RX_RCB_ATS_UC_DIS_MASK 0x00008000L
+#define PCIE_CNTL__RX_RCB_ATS_UC_DIS__SHIFT 0x0000000f
+#define PCIE_CNTL__RX_RCB_CHANNEL_ORDERING_MASK 0x00100000L
+#define PCIE_CNTL__RX_RCB_CHANNEL_ORDERING__SHIFT 0x00000014
+#define PCIE_CNTL__RX_RCB_CPL_TIMEOUT_TEST_MODE_MASK 0x00080000L
+#define PCIE_CNTL__RX_RCB_CPL_TIMEOUT_TEST_MODE__SHIFT 0x00000013
+#define PCIE_CNTL__RX_RCB_INVALID_SIZE_DIS_MASK 0x00020000L
+#define PCIE_CNTL__RX_RCB_INVALID_SIZE_DIS__SHIFT 0x00000011
+#define PCIE_CNTL__RX_RCB_REORDER_EN_MASK 0x00010000L
+#define PCIE_CNTL__RX_RCB_REORDER_EN__SHIFT 0x00000010
+#define PCIE_CNTL__RX_RCB_UNEXP_CPL_DIS_MASK 0x00040000L
+#define PCIE_CNTL__RX_RCB_UNEXP_CPL_DIS__SHIFT 0x00000012
+#define PCIE_CNTL__RX_RCB_WRONG_ATTR_DIS_MASK 0x00200000L
+#define PCIE_CNTL__RX_RCB_WRONG_ATTR_DIS__SHIFT 0x00000015
+#define PCIE_CNTL__RX_RCB_WRONG_FUNCNUM_DIS_MASK 0x00400000L
+#define PCIE_CNTL__RX_RCB_WRONG_FUNCNUM_DIS__SHIFT 0x00000016
+#define PCIE_CNTL__RX_SB_ADJ_PAYLOAD_SIZE_MASK 0x00001c00L
+#define PCIE_CNTL__RX_SB_ADJ_PAYLOAD_SIZE__SHIFT 0x0000000a
+#define PCIE_CNTL__TX_CPL_DEBUG_MASK 0x3f000000L
+#define PCIE_CNTL__TX_CPL_DEBUG__SHIFT 0x00000018
+#define PCIE_CNTL__UR_ERR_REPORT_DIS_MASK 0x00000080L
+#define PCIE_CNTL__UR_ERR_REPORT_DIS__SHIFT 0x00000007
+#define PCIE_CONFIG_CNTL__CI_EXTENDED_TAG_EN_OVERRIDE_MASK 0x02000000L
+#define PCIE_CONFIG_CNTL__CI_EXTENDED_TAG_EN_OVERRIDE__SHIFT 0x00000019
+#define PCIE_CONFIG_CNTL__CI_MAX_PAYLOAD_SIZE_MODE_MASK 0x00010000L
+#define PCIE_CONFIG_CNTL__CI_MAX_PAYLOAD_SIZE_MODE__SHIFT 0x00000010
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_REQUEST_SIZE_MODE_MASK 0x00100000L
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_REQUEST_SIZE_MODE__SHIFT 0x00000014
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_SAFE_MODE_MASK 0x01000000L
+#define PCIE_CONFIG_CNTL__CI_MAX_READ_SAFE_MODE__SHIFT 0x00000018
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_PAYLOAD_SIZE_MASK 0x000e0000L
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_PAYLOAD_SIZE__SHIFT 0x00000011
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_READ_REQUEST_SIZE_MASK 0x00e00000L
+#define PCIE_CONFIG_CNTL__CI_PRIV_MAX_READ_REQUEST_SIZE__SHIFT 0x00000015
+#define PCIE_CONFIG_CNTL__DYN_CLK_LATENCY_MASK 0x0000000fL
+#define PCIE_CONFIG_CNTL__DYN_CLK_LATENCY__SHIFT 0x00000000
+#define PCIE_DATA__PCIE_DATA_MASK 0xffffffffL
+#define PCIE_DATA__PCIE_DATA__SHIFT 0x00000000
+#define PCIE_DEBUG_CNTL__DEBUG_LANE_EN_MASK 0xffff0000L
+#define PCIE_DEBUG_CNTL__DEBUG_LANE_EN__SHIFT 0x00000010
+#define PCIE_DEBUG_CNTL__DEBUG_PORT_EN_MASK 0x000000ffL
+#define PCIE_DEBUG_CNTL__DEBUG_PORT_EN__SHIFT 0x00000000
+#define PCIE_DEBUG_CNTL__DEBUG_SELECT_MASK 0x00000100L
+#define PCIE_DEBUG_CNTL__DEBUG_SELECT__SHIFT 0x00000008
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F0_TIMER_EXPIRED_MASK 0x00000800L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F0_TIMER_EXPIRED__SHIFT 0x0000000b
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F1_TIMER_EXPIRED_MASK 0x00001000L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F1_TIMER_EXPIRED__SHIFT 0x0000000c
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F2_TIMER_EXPIRED_MASK 0x00002000L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_F2_TIMER_EXPIRED__SHIFT 0x0000000d
+#define PCIE_ERR_CNTL__AER_HDR_LOG_TIMEOUT_MASK 0x00000700L
+#define PCIE_ERR_CNTL__AER_HDR_LOG_TIMEOUT__SHIFT 0x00000008
+#define PCIE_ERR_CNTL__CI_NP_SLV_BUF_RD_HALT_STATUS_MASK 0x00008000L
+#define PCIE_ERR_CNTL__CI_NP_SLV_BUF_RD_HALT_STATUS__SHIFT 0x0000000f
+#define PCIE_ERR_CNTL__CI_P_SLV_BUF_RD_HALT_STATUS_MASK 0x00004000L
+#define PCIE_ERR_CNTL__CI_P_SLV_BUF_RD_HALT_STATUS__SHIFT 0x0000000e
+#define PCIE_ERR_CNTL__CI_SLV_BUF_HALT_RESET_MASK 0x00010000L
+#define PCIE_ERR_CNTL__CI_SLV_BUF_HALT_RESET__SHIFT 0x00000010
+#define PCIE_ERR_CNTL__ERR_REPORTING_DIS_MASK 0x00000001L
+#define PCIE_ERR_CNTL__ERR_REPORTING_DIS__SHIFT 0x00000000
+#define PCIE_ERR_CNTL__RX_GENERATE_ECRC_ERR_MASK 0x00000080L
+#define PCIE_ERR_CNTL__RX_GENERATE_ECRC_ERR__SHIFT 0x00000007
+#define PCIE_ERR_CNTL__RX_GENERATE_LCRC_ERR_MASK 0x00000020L
+#define PCIE_ERR_CNTL__RX_GENERATE_LCRC_ERR__SHIFT 0x00000005
+#define PCIE_ERR_CNTL__STRAP_FIRST_RCVD_ERR_LOG_MASK 0x00000002L
+#define PCIE_ERR_CNTL__STRAP_FIRST_RCVD_ERR_LOG__SHIFT 0x00000001
+#define PCIE_ERR_CNTL__TX_GENERATE_ECRC_ERR_MASK 0x00000040L
+#define PCIE_ERR_CNTL__TX_GENERATE_ECRC_ERR__SHIFT 0x00000006
+#define PCIE_ERR_CNTL__TX_GENERATE_LCRC_ERR_MASK 0x00000010L
+#define PCIE_ERR_CNTL__TX_GENERATE_LCRC_ERR__SHIFT 0x00000004
+#define PCIE_F0_DPA_CAP__PWR_ALLOC_SCALE_MASK 0x00003000L
+#define PCIE_F0_DPA_CAP__PWR_ALLOC_SCALE__SHIFT 0x0000000c
+#define PCIE_F0_DPA_CAP__TRANS_LAT_UNIT_MASK 0x00000300L
+#define PCIE_F0_DPA_CAP__TRANS_LAT_UNIT__SHIFT 0x00000008
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_0_MASK 0x00ff0000L
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_0__SHIFT 0x00000010
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_1_MASK 0xff000000L
+#define PCIE_F0_DPA_CAP__TRANS_LAT_VAL_1__SHIFT 0x00000018
+#define PCIE_F0_DPA_CNTL__SUBSTATE_STATUS_MASK 0x0000001fL
+#define PCIE_F0_DPA_CNTL__SUBSTATE_STATUS__SHIFT 0x00000000
+#define PCIE_F0_DPA_LATENCY_INDICATOR__TRANS_LAT_INDICATOR_BITS_MASK 0x000000ffL
+#define PCIE_F0_DPA_LATENCY_INDICATOR__TRANS_LAT_INDICATOR_BITS__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_0__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_0__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_1__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_1__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_2__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_2__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_3__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_3__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_4__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_4__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_5__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_5__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_6__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_6__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_7__SUBSTATE_PWR_ALLOC_MASK 0x000000ffL
+#define PCIE_F0_DPA_SUBSTATE_PWR_ALLOC_7__SUBSTATE_PWR_ALLOC__SHIFT 0x00000000
+#define PCIE_FC_CPL__CPLD_CREDITS_MASK 0x000000ffL
+#define PCIE_FC_CPL__CPLD_CREDITS__SHIFT 0x00000000
+#define PCIE_FC_CPL__CPLH_CREDITS_MASK 0x0000ff00L
+#define PCIE_FC_CPL__CPLH_CREDITS__SHIFT 0x00000008
+#define PCIE_FC_NP__NPD_CREDITS_MASK 0x000000ffL
+#define PCIE_FC_NP__NPD_CREDITS__SHIFT 0x00000000
+#define PCIE_FC_NP__NPH_CREDITS_MASK 0x0000ff00L
+#define PCIE_FC_NP__NPH_CREDITS__SHIFT 0x00000008
+#define PCIE_FC_P__PD_CREDITS_MASK 0x000000ffL
+#define PCIE_FC_P__PD_CREDITS__SHIFT 0x00000000
+#define PCIE_FC_P__PH_CREDITS_MASK 0x0000ff00L
+#define PCIE_FC_P__PH_CREDITS__SHIFT 0x00000008
+#define PCIE_HW_DEBUG__HW_00_DEBUG_MASK 0x00000001L
+#define PCIE_HW_DEBUG__HW_00_DEBUG__SHIFT 0x00000000
+#define PCIE_HW_DEBUG__HW_01_DEBUG_MASK 0x00000002L
+#define PCIE_HW_DEBUG__HW_01_DEBUG__SHIFT 0x00000001
+#define PCIE_HW_DEBUG__HW_02_DEBUG_MASK 0x00000004L
+#define PCIE_HW_DEBUG__HW_02_DEBUG__SHIFT 0x00000002
+#define PCIE_HW_DEBUG__HW_03_DEBUG_MASK 0x00000008L
+#define PCIE_HW_DEBUG__HW_03_DEBUG__SHIFT 0x00000003
+#define PCIE_HW_DEBUG__HW_04_DEBUG_MASK 0x00000010L
+#define PCIE_HW_DEBUG__HW_04_DEBUG__SHIFT 0x00000004
+#define PCIE_HW_DEBUG__HW_05_DEBUG_MASK 0x00000020L
+#define PCIE_HW_DEBUG__HW_05_DEBUG__SHIFT 0x00000005
+#define PCIE_HW_DEBUG__HW_06_DEBUG_MASK 0x00000040L
+#define PCIE_HW_DEBUG__HW_06_DEBUG__SHIFT 0x00000006
+#define PCIE_HW_DEBUG__HW_07_DEBUG_MASK 0x00000080L
+#define PCIE_HW_DEBUG__HW_07_DEBUG__SHIFT 0x00000007
+#define PCIE_HW_DEBUG__HW_08_DEBUG_MASK 0x00000100L
+#define PCIE_HW_DEBUG__HW_08_DEBUG__SHIFT 0x00000008
+#define PCIE_HW_DEBUG__HW_09_DEBUG_MASK 0x00000200L
+#define PCIE_HW_DEBUG__HW_09_DEBUG__SHIFT 0x00000009
+#define PCIE_HW_DEBUG__HW_10_DEBUG_MASK 0x00000400L
+#define PCIE_HW_DEBUG__HW_10_DEBUG__SHIFT 0x0000000a
+#define PCIE_HW_DEBUG__HW_11_DEBUG_MASK 0x00000800L
+#define PCIE_HW_DEBUG__HW_11_DEBUG__SHIFT 0x0000000b
+#define PCIE_HW_DEBUG__HW_12_DEBUG_MASK 0x00001000L
+#define PCIE_HW_DEBUG__HW_12_DEBUG__SHIFT 0x0000000c
+#define PCIE_HW_DEBUG__HW_13_DEBUG_MASK 0x00002000L
+#define PCIE_HW_DEBUG__HW_13_DEBUG__SHIFT 0x0000000d
+#define PCIE_HW_DEBUG__HW_14_DEBUG_MASK 0x00004000L
+#define PCIE_HW_DEBUG__HW_14_DEBUG__SHIFT 0x0000000e
+#define PCIE_HW_DEBUG__HW_15_DEBUG_MASK 0x00008000L
+#define PCIE_HW_DEBUG__HW_15_DEBUG__SHIFT 0x0000000f
+#define PCIE_I2C_REG_ADDR_EXPAND__I2C_REG_ADDR_MASK 0x0001ffffL
+#define PCIE_I2C_REG_ADDR_EXPAND__I2C_REG_ADDR__SHIFT 0x00000000
+#define PCIE_I2C_REG_DATA__I2C_REG_DATA_MASK 0xffffffffL
+#define PCIE_I2C_REG_DATA__I2C_REG_DATA__SHIFT 0x00000000
+#define PCIE_INDEX__PCIE_INDEX_MASK 0x000000ffL
+#define PCIE_INDEX__PCIE_INDEX__SHIFT 0x00000000
+#define PCIE_INT_CNTL__CORR_ERR_INT_EN_MASK 0x00000001L
+#define PCIE_INT_CNTL__CORR_ERR_INT_EN__SHIFT 0x00000000
+#define PCIE_INT_CNTL__FATAL_ERR_INT_EN_MASK 0x00000004L
+#define PCIE_INT_CNTL__FATAL_ERR_INT_EN__SHIFT 0x00000002
+#define PCIE_INT_CNTL__LINK_BW_INT_EN_MASK 0x00000080L
+#define PCIE_INT_CNTL__LINK_BW_INT_EN__SHIFT 0x00000007
+#define PCIE_INT_CNTL__MISC_ERR_INT_EN_MASK 0x00000010L
+#define PCIE_INT_CNTL__MISC_ERR_INT_EN__SHIFT 0x00000004
+#define PCIE_INT_CNTL__NON_FATAL_ERR_INT_EN_MASK 0x00000002L
+#define PCIE_INT_CNTL__NON_FATAL_ERR_INT_EN__SHIFT 0x00000001
+#define PCIE_INT_CNTL__POWER_STATE_CHG_INT_EN_MASK 0x00000040L
+#define PCIE_INT_CNTL__POWER_STATE_CHG_INT_EN__SHIFT 0x00000006
+#define PCIE_INT_CNTL__QUIESCE_RCVD_INT_EN_MASK 0x00000100L
+#define PCIE_INT_CNTL__QUIESCE_RCVD_INT_EN__SHIFT 0x00000008
+#define PCIE_INT_CNTL__USR_DETECTED_INT_EN_MASK 0x00000008L
+#define PCIE_INT_CNTL__USR_DETECTED_INT_EN__SHIFT 0x00000003
+#define PCIE_INT_STATUS__CORR_ERR_INT_STATUS_MASK 0x00000001L
+#define PCIE_INT_STATUS__CORR_ERR_INT_STATUS__SHIFT 0x00000000
+#define PCIE_INT_STATUS__FATAL_ERR_INT_STATUS_MASK 0x00000004L
+#define PCIE_INT_STATUS__FATAL_ERR_INT_STATUS__SHIFT 0x00000002
+#define PCIE_INT_STATUS__LINK_BW_INT_STATUS_MASK 0x00000080L
+#define PCIE_INT_STATUS__LINK_BW_INT_STATUS__SHIFT 0x00000007
+#define PCIE_INT_STATUS__MISC_ERR_INT_STATUS_MASK 0x00000010L
+#define PCIE_INT_STATUS__MISC_ERR_INT_STATUS__SHIFT 0x00000004
+#define PCIE_INT_STATUS__NON_FATAL_ERR_INT_STATUS_MASK 0x00000002L
+#define PCIE_INT_STATUS__NON_FATAL_ERR_INT_STATUS__SHIFT 0x00000001
+#define PCIE_INT_STATUS__POWER_STATE_CHG_INT_STATUS_MASK 0x00000040L
+#define PCIE_INT_STATUS__POWER_STATE_CHG_INT_STATUS__SHIFT 0x00000006
+#define PCIE_INT_STATUS__QUIESCE_RCVD_INT_STATUS_MASK 0x00000100L
+#define PCIE_INT_STATUS__QUIESCE_RCVD_INT_STATUS__SHIFT 0x00000008
+#define PCIE_INT_STATUS__USR_DETECTED_INT_STATUS_MASK 0x00000008L
+#define PCIE_INT_STATUS__USR_DETECTED_INT_STATUS__SHIFT 0x00000003
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_CURSOR_MASK 0x0000fc00L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_CURSOR__SHIFT 0x0000000a
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_FOM_MASK 0x3fc00000L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_FOM__SHIFT 0x00000016
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_POSTCURSOR_MASK 0x003f0000L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_POSTCURSOR__SHIFT 0x00000010
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRECURSOR_MASK 0x000003f0L
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRECURSOR__SHIFT 0x00000004
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRESET_MASK 0x0000000fL
+#define PCIE_LC_BEST_EQ_SETTINGS__LC_BEST_PRESET__SHIFT 0x00000000
+#define PCIE_LC_BW_CHANGE_CNTL__LC_BW_CHANGE_INT_EN_MASK 0x00000001L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_BW_CHANGE_INT_EN__SHIFT 0x00000000
+#define PCIE_LC_BW_CHANGE_CNTL__LC_FAILED_SPEED_NEG_MASK 0x00000020L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_FAILED_SPEED_NEG__SHIFT 0x00000005
+#define PCIE_LC_BW_CHANGE_CNTL__LC_HW_INIT_SPEED_CHANGE_MASK 0x00000002L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_HW_INIT_SPEED_CHANGE__SHIFT 0x00000001
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LINK_BW_NOTIFICATION_DETECT_MODE_MASK 0x00000400L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LINK_BW_NOTIFICATION_DETECT_MODE__SHIFT 0x0000000a
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LONG_LW_CHANGE_MASK 0x00000040L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LONG_LW_CHANGE__SHIFT 0x00000006
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_FAILED_MASK 0x00000200L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_FAILED__SHIFT 0x00000009
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_OTHER_MASK 0x00000100L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_LW_CHANGE_OTHER__SHIFT 0x00000008
+#define PCIE_LC_BW_CHANGE_CNTL__LC_OTHER_INIT_SPEED_CHANGE_MASK 0x00000008L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_OTHER_INIT_SPEED_CHANGE__SHIFT 0x00000003
+#define PCIE_LC_BW_CHANGE_CNTL__LC_RELIABILITY_SPEED_CHANGE_MASK 0x00000010L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_RELIABILITY_SPEED_CHANGE__SHIFT 0x00000004
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SHORT_LW_CHANGE_MASK 0x00000080L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SHORT_LW_CHANGE__SHIFT 0x00000007
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SW_INIT_SPEED_CHANGE_MASK 0x00000004L
+#define PCIE_LC_BW_CHANGE_CNTL__LC_SW_INIT_SPEED_CHANGE__SHIFT 0x00000002
+#define PCIE_LC_CDR_CNTL__LC_CDR_SET_TYPE_MASK 0x03000000L
+#define PCIE_LC_CDR_CNTL__LC_CDR_SET_TYPE__SHIFT 0x00000018
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_OFF_MASK 0x00000fffL
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_OFF__SHIFT 0x00000000
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_SETS_MASK 0x00fff000L
+#define PCIE_LC_CDR_CNTL__LC_CDR_TEST_SETS__SHIFT 0x0000000c
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L1_MASK 0x00020000L
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L1__SHIFT 0x00000011
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L23_MASK 0x00040000L
+#define PCIE_LC_CNTL2__LC_ALLOW_PDWN_IN_L23__SHIFT 0x00000012
+#define PCIE_LC_CNTL2__LC_ASSERT_INACTIVE_DURING_HOLD_MASK 0x00400000L
+#define PCIE_LC_CNTL2__LC_ASSERT_INACTIVE_DURING_HOLD__SHIFT 0x00000016
+#define PCIE_LC_CNTL2__LC_BLOCK_EL_IDLE_IN_L0_MASK 0x00100000L
+#define PCIE_LC_CNTL2__LC_BLOCK_EL_IDLE_IN_L0__SHIFT 0x00000014
+#define PCIE_LC_CNTL2__LC_DEASSERT_RX_EN_IN_L0S_MASK 0x00080000L
+#define PCIE_LC_CNTL2__LC_DEASSERT_RX_EN_IN_L0S__SHIFT 0x00000013
+#define PCIE_LC_CNTL2__LC_DISABLE_INFERRED_ELEC_IDLE_DET_MASK 0x00010000L
+#define PCIE_LC_CNTL2__LC_DISABLE_INFERRED_ELEC_IDLE_DET__SHIFT 0x00000010
+#define PCIE_LC_CNTL2__LC_DISABLE_LOST_SYM_LOCK_ARCS_MASK 0x04000000L
+#define PCIE_LC_CNTL2__LC_DISABLE_LOST_SYM_LOCK_ARCS__SHIFT 0x0000001a
+#define PCIE_LC_CNTL2__LC_ELEC_IDLE_MODE_MASK 0x0000c000L
+#define PCIE_LC_CNTL2__LC_ELEC_IDLE_MODE__SHIFT 0x0000000e
+#define PCIE_LC_CNTL2__LC_ENABLE_INFERRED_ELEC_IDLE_FOR_PI_MASK 0x80000000L
+#define PCIE_LC_CNTL2__LC_ENABLE_INFERRED_ELEC_IDLE_FOR_PI__SHIFT 0x0000001f
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE_MASK 0x00000800L
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE_RESTART_EN_MASK 0x00001000L
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE_RESTART_EN__SHIFT 0x0000000c
+#define PCIE_LC_CNTL2__LC_ILLEGAL_STATE__SHIFT 0x0000000b
+#define PCIE_LC_CNTL2__LC_LINK_BW_NOTIFICATION_DIS_MASK 0x08000000L
+#define PCIE_LC_CNTL2__LC_LINK_BW_NOTIFICATION_DIS__SHIFT 0x0000001b
+#define PCIE_LC_CNTL2__LC_LINK_UP_REVERSAL_EN_MASK 0x00000400L
+#define PCIE_LC_CNTL2__LC_LINK_UP_REVERSAL_EN__SHIFT 0x0000000a
+#define PCIE_LC_CNTL2__LC_LOOK_FOR_BW_REDUCTION_MASK 0x00000080L
+#define PCIE_LC_CNTL2__LC_LOOK_FOR_BW_REDUCTION__SHIFT 0x00000007
+#define PCIE_LC_CNTL2__LC_MORE_TS2_EN_MASK 0x00000100L
+#define PCIE_LC_CNTL2__LC_MORE_TS2_EN__SHIFT 0x00000008
+#define PCIE_LC_CNTL2__LC_PMI_L1_WAIT_FOR_SLV_IDLE_MASK 0x10000000L
+#define PCIE_LC_CNTL2__LC_PMI_L1_WAIT_FOR_SLV_IDLE__SHIFT 0x0000001c
+#define PCIE_LC_CNTL2__LC_PWR_DOWN_NEG_OFF_LANES_MASK 0x02000000L
+#define PCIE_LC_CNTL2__LC_PWR_DOWN_NEG_OFF_LANES__SHIFT 0x00000019
+#define PCIE_LC_CNTL2__LC_RCV_L0_TO_RCV_L0S_DIS_MASK 0x00200000L
+#define PCIE_LC_CNTL2__LC_RCV_L0_TO_RCV_L0S_DIS__SHIFT 0x00000015
+#define PCIE_LC_CNTL2__LC_STATE_TIMED_OUT_MASK 0x00000040L
+#define PCIE_LC_CNTL2__LC_STATE_TIMED_OUT__SHIFT 0x00000006
+#define PCIE_LC_CNTL2__LC_TEST_TIMER_SEL_MASK 0x60000000L
+#define PCIE_LC_CNTL2__LC_TEST_TIMER_SEL__SHIFT 0x0000001d
+#define PCIE_LC_CNTL2__LC_TIMED_OUT_STATE_MASK 0x0000003fL
+#define PCIE_LC_CNTL2__LC_TIMED_OUT_STATE__SHIFT 0x00000000
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_LANES_IN_LW_NEG_MASK 0x01800000L
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_LANES_IN_LW_NEG__SHIFT 0x00000017
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_OTHER_LANES_MODE_MASK 0x00002000L
+#define PCIE_LC_CNTL2__LC_WAIT_FOR_OTHER_LANES_MODE__SHIFT 0x0000000d
+#define PCIE_LC_CNTL2__LC_X12_NEGOTIATION_DIS_MASK 0x00000200L
+#define PCIE_LC_CNTL2__LC_X12_NEGOTIATION_DIS__SHIFT 0x00000009
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_EN_MASK 0x00040000L
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_EN__SHIFT 0x00000012
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_MAX_FAIL_SEL_MASK 0x00180000L
+#define PCIE_LC_CNTL3__LC_AUTO_DISABLE_SPEED_SUPPORT_MAX_FAIL_SEL__SHIFT 0x00000013
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPT_FAILED_MASK 0x00000100L
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPT_FAILED__SHIFT 0x00000008
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK 0x000000c0L
+#define PCIE_LC_CNTL3__LC_AUTO_SPEED_CHANGE_ATTEMPTS_ALLOWED__SHIFT 0x00000006
+#define PCIE_LC_CNTL3__LC_CHIP_BIF_USB_IDLE_EN_MASK 0x00010000L
+#define PCIE_LC_CNTL3__LC_CHIP_BIF_USB_IDLE_EN__SHIFT 0x00000010
+#define PCIE_LC_CNTL3__LC_CLR_FAILED_AUTO_SPD_CHANGE_CNT_MASK 0x00000200L
+#define PCIE_LC_CNTL3__LC_CLR_FAILED_AUTO_SPD_CHANGE_CNT__SHIFT 0x00000009
+#define PCIE_LC_CNTL3__LC_COMP_TO_DETECT_MASK 0x00000010L
+#define PCIE_LC_CNTL3__LC_COMP_TO_DETECT__SHIFT 0x00000004
+#define PCIE_LC_CNTL3__LC_DSC_DONT_ENTER_L23_AFTER_PME_ACK_MASK 0x00800000L
+#define PCIE_LC_CNTL3__LC_DSC_DONT_ENTER_L23_AFTER_PME_ACK__SHIFT 0x00000017
+#define PCIE_LC_CNTL3__LC_EHP_RX_PHY_CMD_MASK 0x00003000L
+#define PCIE_LC_CNTL3__LC_EHP_RX_PHY_CMD__SHIFT 0x0000000c
+#define PCIE_LC_CNTL3__LC_EHP_TX_PHY_CMD_MASK 0x0000c000L
+#define PCIE_LC_CNTL3__LC_EHP_TX_PHY_CMD__SHIFT 0x0000000e
+#define PCIE_LC_CNTL3__LC_ENHANCED_HOT_PLUG_EN_MASK 0x00000400L
+#define PCIE_LC_CNTL3__LC_ENHANCED_HOT_PLUG_EN__SHIFT 0x0000000a
+#define PCIE_LC_CNTL3__LC_FAST_L1_ENTRY_EXIT_EN_MASK 0x00200000L
+#define PCIE_LC_CNTL3__LC_FAST_L1_ENTRY_EXIT_EN__SHIFT 0x00000015
+#define PCIE_LC_CNTL3__LC_GO_TO_RECOVERY_MASK 0x40000000L
+#define PCIE_LC_CNTL3__LC_GO_TO_RECOVERY__SHIFT 0x0000001e
+#define PCIE_LC_CNTL3__LC_HW_VOLTAGE_IF_CONTROL_MASK 0x03000000L
+#define PCIE_LC_CNTL3__LC_HW_VOLTAGE_IF_CONTROL__SHIFT 0x00000018
+#define PCIE_LC_CNTL3__LC_L1_BLOCK_RECONFIG_EN_MASK 0x00020000L
+#define PCIE_LC_CNTL3__LC_L1_BLOCK_RECONFIG_EN__SHIFT 0x00000011
+#define PCIE_LC_CNTL3__LC_N_EIE_SEL_MASK 0x80000000L
+#define PCIE_LC_CNTL3__LC_N_EIE_SEL__SHIFT 0x0000001f
+#define PCIE_LC_CNTL3__LC_RCVD_DEEMPHASIS_MASK 0x00000008L
+#define PCIE_LC_CNTL3__LC_RCVD_DEEMPHASIS__SHIFT 0x00000003
+#define PCIE_LC_CNTL3__LC_RCVR_DET_EN_OVERRIDE_MASK 0x00000800L
+#define PCIE_LC_CNTL3__LC_RCVR_DET_EN_OVERRIDE__SHIFT 0x0000000b
+#define PCIE_LC_CNTL3__LC_RESET_TSX_CNT_IN_RLOCK_EN_MASK 0x00000020L
+#define PCIE_LC_CNTL3__LC_RESET_TSX_CNT_IN_RLOCK_EN__SHIFT 0x00000005
+#define PCIE_LC_CNTL3__LC_RXPHYCMD_INACTIVE_EN_MODE_MASK 0x00400000L
+#define PCIE_LC_CNTL3__LC_RXPHYCMD_INACTIVE_EN_MODE__SHIFT 0x00000016
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS_CNTL_MASK 0x00000006L
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS_CNTL__SHIFT 0x00000001
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS_MASK 0x00000001L
+#define PCIE_LC_CNTL3__LC_SELECT_DEEMPHASIS__SHIFT 0x00000000
+#define PCIE_LC_CNTL3__LC_VOLTAGE_TIMER_SEL_MASK 0x3c000000L
+#define PCIE_LC_CNTL3__LC_VOLTAGE_TIMER_SEL__SHIFT 0x0000001a
+#define PCIE_LC_CNTL4__LC_8GT_SKIP_ORDER_EN_MASK 0x02000000L
+#define PCIE_LC_CNTL4__LC_8GT_SKIP_ORDER_EN__SHIFT 0x00000019
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ_MASK 0x00000010L
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ_REQ_PHASE_MASK 0x00010000L
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ_REQ_PHASE__SHIFT 0x00000010
+#define PCIE_LC_CNTL4__LC_BYPASS_EQ__SHIFT 0x00000004
+#define PCIE_LC_CNTL4__LC_DSC_CHECK_COEFFS_IN_RLOCK_MASK 0x00000400L
+#define PCIE_LC_CNTL4__LC_DSC_CHECK_COEFFS_IN_RLOCK__SHIFT 0x0000000a
+#define PCIE_LC_CNTL4__LC_EQ_SEARCH_MODE_MASK 0x00000300L
+#define PCIE_LC_CNTL4__LC_EQ_SEARCH_MODE__SHIFT 0x00000008
+#define PCIE_LC_CNTL4__LC_EQ_WAIT_FOR_EVAL_DONE_MASK 0x01000000L
+#define PCIE_LC_CNTL4__LC_EQ_WAIT_FOR_EVAL_DONE__SHIFT 0x00000018
+#define PCIE_LC_CNTL4__LC_EXTEND_EIEOS_MASK 0x00000040L
+#define PCIE_LC_CNTL4__LC_EXTEND_EIEOS__SHIFT 0x00000006
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_IN_EQ_REQ_PHASE_MASK 0x00020000L
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_IN_EQ_REQ_PHASE__SHIFT 0x00000011
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_VALUE_MASK 0x003c0000L
+#define PCIE_LC_CNTL4__LC_FORCE_PRESET_VALUE__SHIFT 0x00000012
+#define PCIE_LC_CNTL4__LC_IGNORE_PARITY_MASK 0x00000080L
+#define PCIE_LC_CNTL4__LC_IGNORE_PARITY__SHIFT 0x00000007
+#define PCIE_LC_CNTL4__LC_PCIE_TX_FULL_SWING_MASK 0x00800000L
+#define PCIE_LC_CNTL4__LC_PCIE_TX_FULL_SWING__SHIFT 0x00000017
+#define PCIE_LC_CNTL4__LC_QUIESCE_RCVD_MASK 0x00004000L
+#define PCIE_LC_CNTL4__LC_QUIESCE_RCVD__SHIFT 0x0000000e
+#define PCIE_LC_CNTL4__LC_REDO_EQ_MASK 0x00000020L
+#define PCIE_LC_CNTL4__LC_REDO_EQ__SHIFT 0x00000005
+#define PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK 0x00002000L
+#define PCIE_LC_CNTL4__LC_SET_QUIESCE__SHIFT 0x0000000d
+#define PCIE_LC_CNTL4__LC_TX_ENABLE_BEHAVIOUR_MASK 0x00000003L
+#define PCIE_LC_CNTL4__LC_TX_ENABLE_BEHAVIOUR__SHIFT 0x00000000
+#define PCIE_LC_CNTL4__LC_UNEXPECTED_COEFFS_RCVD_MASK 0x00008000L
+#define PCIE_LC_CNTL4__LC_UNEXPECTED_COEFFS_RCVD__SHIFT 0x0000000f
+#define PCIE_LC_CNTL4__LC_USC_DELAY_DLLPS_MASK 0x00400000L
+#define PCIE_LC_CNTL4__LC_USC_DELAY_DLLPS__SHIFT 0x00000016
+#define PCIE_LC_CNTL4__LC_USC_EQ_NOT_REQD_MASK 0x00000800L
+#define PCIE_LC_CNTL4__LC_USC_EQ_NOT_REQD__SHIFT 0x0000000b
+#define PCIE_LC_CNTL4__LC_USC_GO_TO_EQ_MASK 0x00001000L
+#define PCIE_LC_CNTL4__LC_USC_GO_TO_EQ__SHIFT 0x0000000c
+#define PCIE_LC_CNTL4__LC_WAIT_FOR_MORE_TS_IN_RLOCK_MASK 0xfc000000L
+#define PCIE_LC_CNTL4__LC_WAIT_FOR_MORE_TS_IN_RLOCK__SHIFT 0x0000001a
+#define PCIE_LC_CNTL5__LC_EQ_FS_0_MASK 0x0000003fL
+#define PCIE_LC_CNTL5__LC_EQ_FS_0__SHIFT 0x00000000
+#define PCIE_LC_CNTL5__LC_EQ_FS_8_MASK 0x00000fc0L
+#define PCIE_LC_CNTL5__LC_EQ_FS_8__SHIFT 0x00000006
+#define PCIE_LC_CNTL5__LC_EQ_LF_0_MASK 0x0003f000L
+#define PCIE_LC_CNTL5__LC_EQ_LF_0__SHIFT 0x0000000c
+#define PCIE_LC_CNTL5__LC_EQ_LF_8_MASK 0x00fc0000L
+#define PCIE_LC_CNTL5__LC_EQ_LF_8__SHIFT 0x00000012
+#define PCIE_LC_CNTL__LC_16X_CLEAR_TX_PIPE_MASK 0x000000f0L
+#define PCIE_LC_CNTL__LC_16X_CLEAR_TX_PIPE__SHIFT 0x00000004
+#define PCIE_LC_CNTL__LC_ASPM_TO_L1_DIS_MASK 0x01000000L
+#define PCIE_LC_CNTL__LC_ASPM_TO_L1_DIS__SHIFT 0x00000018
+#define PCIE_LC_CNTL__LC_DELAY_COUNT_MASK 0x06000000L
+#define PCIE_LC_CNTL__LC_DELAY_COUNT__SHIFT 0x00000019
+#define PCIE_LC_CNTL__LC_DELAY_L0S_EXIT_MASK 0x08000000L
+#define PCIE_LC_CNTL__LC_DELAY_L0S_EXIT__SHIFT 0x0000001b
+#define PCIE_LC_CNTL__LC_DELAY_L1_EXIT_MASK 0x10000000L
+#define PCIE_LC_CNTL__LC_DELAY_L1_EXIT__SHIFT 0x0000001c
+#define PCIE_LC_CNTL__LC_DONT_ENTER_L23_IN_D0_MASK 0x00000002L
+#define PCIE_LC_CNTL__LC_DONT_ENTER_L23_IN_D0__SHIFT 0x00000001
+#define PCIE_LC_CNTL__LC_ESCAPE_L1L23_EN_MASK 0x40000000L
+#define PCIE_LC_CNTL__LC_ESCAPE_L1L23_EN__SHIFT 0x0000001e
+#define PCIE_LC_CNTL__LC_EXTEND_WAIT_FOR_EL_IDLE_MASK 0x20000000L
+#define PCIE_LC_CNTL__LC_EXTEND_WAIT_FOR_EL_IDLE__SHIFT 0x0000001d
+#define PCIE_LC_CNTL__LC_FACTOR_IN_EXT_SYNC_MASK 0x00100000L
+#define PCIE_LC_CNTL__LC_FACTOR_IN_EXT_SYNC__SHIFT 0x00000014
+#define PCIE_LC_CNTL__LC_GATE_RCVR_IDLE_MASK 0x80000000L
+#define PCIE_LC_CNTL__LC_GATE_RCVR_IDLE__SHIFT 0x0000001f
+#define PCIE_LC_CNTL__LC_INC_N_FTS_EN_MASK 0x00020000L
+#define PCIE_LC_CNTL__LC_INC_N_FTS_EN__SHIFT 0x00000011
+#define PCIE_LC_CNTL__LC_L0S_INACTIVITY_MASK 0x00000f00L
+#define PCIE_LC_CNTL__LC_L0S_INACTIVITY__SHIFT 0x00000008
+#define PCIE_LC_CNTL__LC_L1_IMMEDIATE_ACK_MASK 0x00800000L
+#define PCIE_LC_CNTL__LC_L1_IMMEDIATE_ACK__SHIFT 0x00000017
+#define PCIE_LC_CNTL__LC_L1_INACTIVITY_MASK 0x0000f000L
+#define PCIE_LC_CNTL__LC_L1_INACTIVITY__SHIFT 0x0000000c
+#define PCIE_LC_CNTL__LC_LOOK_FOR_IDLE_IN_L1L23_MASK 0x000c0000L
+#define PCIE_LC_CNTL__LC_LOOK_FOR_IDLE_IN_L1L23__SHIFT 0x00000012
+#define PCIE_LC_CNTL__LC_PMI_TO_L1_DIS_MASK 0x00010000L
+#define PCIE_LC_CNTL__LC_PMI_TO_L1_DIS__SHIFT 0x00000010
+#define PCIE_LC_CNTL__LC_RESET_L_IDLE_COUNT_EN_MASK 0x00000004L
+#define PCIE_LC_CNTL__LC_RESET_L_IDLE_COUNT_EN__SHIFT 0x00000002
+#define PCIE_LC_CNTL__LC_RESET_LINK_MASK 0x00000008L
+#define PCIE_LC_CNTL__LC_RESET_LINK__SHIFT 0x00000003
+#define PCIE_LC_CNTL__LC_WAIT_FOR_PM_ACK_DIS_MASK 0x00200000L
+#define PCIE_LC_CNTL__LC_WAIT_FOR_PM_ACK_DIS__SHIFT 0x00000015
+#define PCIE_LC_CNTL__LC_WAKE_FROM_L23_MASK 0x00400000L
+#define PCIE_LC_CNTL__LC_WAKE_FROM_L23__SHIFT 0x00000016
+#define PCIE_LC_FORCE_COEFF__LC_3X3_COEFF_SEARCH_EN_MASK 0x00080000L
+#define PCIE_LC_FORCE_COEFF__LC_3X3_COEFF_SEARCH_EN__SHIFT 0x00000013
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_COEFF_MASK 0x00000001L
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_COEFF__SHIFT 0x00000000
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_CURSOR_MASK 0x00001f80L
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_CURSOR__SHIFT 0x00000007
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_POST_CURSOR_MASK 0x0007e000L
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_POST_CURSOR__SHIFT 0x0000000d
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_PRE_CURSOR_MASK 0x0000007eL
+#define PCIE_LC_FORCE_COEFF__LC_FORCE_PRE_CURSOR__SHIFT 0x00000001
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_COEFF_IN_EQ_REQ_PHASE_MASK 0x00000001L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_COEFF_IN_EQ_REQ_PHASE__SHIFT 0x00000000
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_CURSOR_REQ_MASK 0x00001f80L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_CURSOR_REQ__SHIFT 0x00000007
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_POST_CURSOR_REQ_MASK 0x0007e000L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_POST_CURSOR_REQ__SHIFT 0x0000000d
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_PRE_CURSOR_REQ_MASK 0x0000007eL
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FORCE_PRE_CURSOR_REQ__SHIFT 0x00000001
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FS_OTHER_END_MASK 0x01f80000L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_FS_OTHER_END__SHIFT 0x00000013
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_LF_OTHER_END_MASK 0x7e000000L
+#define PCIE_LC_FORCE_EQ_REQ_COEFF__LC_LF_OTHER_END__SHIFT 0x00000019
+#define PCIE_LC_LANE_CNTL__LC_CORRUPTED_LANES_MASK 0x0000ffffL
+#define PCIE_LC_LANE_CNTL__LC_CORRUPTED_LANES__SHIFT 0x00000000
+#define PCIE_LC_LANE_CNTL__LC_LANE_DIS_MASK 0xffff0000L
+#define PCIE_LC_LANE_CNTL__LC_LANE_DIS__SHIFT 0x00000010
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DEASSERT_TX_PDNB_MASK 0x00010000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DEASSERT_TX_PDNB__SHIFT 0x00000010
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DUAL_END_RECONFIG_EN_MASK 0x00080000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DUAL_END_RECONFIG_EN__SHIFT 0x00000013
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYN_LANES_PWR_STATE_MASK 0x00600000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYN_LANES_PWR_STATE__SHIFT 0x00000015
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYNLINK_MST_EN_MASK 0x00040000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_DYNLINK_MST_EN__SHIFT 0x00000012
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_EQ_REVERSAL_LOGIC_EN_MASK 0x00800000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_EQ_REVERSAL_LOGIC_EN__SHIFT 0x00000017
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_L1_RECONFIG_EN_MASK 0x00020000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_L1_RECONFIG_EN__SHIFT 0x00000011
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_MASK 0x00000007L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x00000004
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH__SHIFT 0x00000000
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_ARC_MISSING_ESCAPE_MASK 0x00000080L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_ARC_MISSING_ESCAPE__SHIFT 0x00000007
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_NOW_MASK 0x00000100L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RECONFIG_NOW__SHIFT 0x00000008
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATE_EN_MASK 0x00000400L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATE_EN__SHIFT 0x0000000a
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATION_SUPPORT_MASK 0x00000200L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_RENEGOTIATION_SUPPORT__SHIFT 0x00000009
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_SHORT_RECONFIG_EN_MASK 0x00000800L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_SHORT_RECONFIG_EN__SHIFT 0x0000000b
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_TIMER_SEL_MASK 0x00008000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_TIMER_SEL__SHIFT 0x0000000f
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_WAIT_FOR_RCVR_DIS_MASK 0x00004000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCFG_WAIT_FOR_RCVR_DIS__SHIFT 0x0000000e
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_CAPABLE_MASK 0x00100000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_CAPABLE__SHIFT 0x00000014
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_DIS_MASK 0x00002000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_DIS__SHIFT 0x0000000d
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_SUPPORT_MASK 0x00001000L
+#define PCIE_LC_LINK_WIDTH_CNTL__LC_UPCONFIGURE_SUPPORT__SHIFT 0x0000000c
+#define PCIE_LC_N_FTS_CNTL__LC_N_FTS_MASK 0xff000000L
+#define PCIE_LC_N_FTS_CNTL__LC_N_FTS__SHIFT 0x00000018
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_FTS_BEFORE_RECOVERY_MASK 0x00000200L
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_FTS_BEFORE_RECOVERY__SHIFT 0x00000009
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_LIMIT_MASK 0x00ff0000L
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_LIMIT__SHIFT 0x00000010
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_MASK 0x000000ffL
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_OVERRIDE_EN_MASK 0x00000100L
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS_OVERRIDE_EN__SHIFT 0x00000008
+#define PCIE_LC_N_FTS_CNTL__LC_XMIT_N_FTS__SHIFT 0x00000000
+#define PCIE_LC_SPEED_CNTL__LC_1_OR_MORE_TS2_SPEED_ARC_EN_MASK 0x00020000L
+#define PCIE_LC_SPEED_CNTL__LC_1_OR_MORE_TS2_SPEED_ARC_EN__SHIFT 0x00000011
+#define PCIE_LC_SPEED_CNTL__LC_AUTO_RECOVERY_DIS_MASK 0x00400000L
+#define PCIE_LC_SPEED_CNTL__LC_AUTO_RECOVERY_DIS__SHIFT 0x00000016
+#define PCIE_LC_SPEED_CNTL__LC_CHECK_DATA_RATE_MASK 0x04000000L
+#define PCIE_LC_SPEED_CNTL__LC_CHECK_DATA_RATE__SHIFT 0x0000001a
+#define PCIE_LC_SPEED_CNTL__LC_CLR_FAILED_SPD_CHANGE_CNT_MASK 0x00010000L
+#define PCIE_LC_SPEED_CNTL__LC_CLR_FAILED_SPD_CHANGE_CNT__SHIFT 0x00000010
+#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0x00006000L
+#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0x0000000d
+#define PCIE_LC_SPEED_CNTL__LC_DATA_RATE_ADVERTISED_MASK 0x03000000L
+#define PCIE_LC_SPEED_CNTL__LC_DATA_RATE_ADVERTISED__SHIFT 0x00000018
+#define PCIE_LC_SPEED_CNTL__LC_DELAY_COEFF_UPDATE_DIS_MASK 0x80000000L
+#define PCIE_LC_SPEED_CNTL__LC_DELAY_COEFF_UPDATE_DIS__SHIFT 0x0000001f
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CHECK_EQTS_IN_RCFG_MASK 0x40000000L
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CHECK_EQTS_IN_RCFG__SHIFT 0x0000001e
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CLR_TARGET_SPD_CHANGE_STATUS_MASK 0x00008000L
+#define PCIE_LC_SPEED_CNTL__LC_DONT_CLR_TARGET_SPD_CHANGE_STATUS__SHIFT 0x0000000f
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_HW_SPEED_CHANGE_MASK 0x00000100L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_HW_SPEED_CHANGE__SHIFT 0x00000008
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK 0x00000040L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE__SHIFT 0x00000006
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_HW_SPEED_CHANGE_MASK 0x00000080L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_HW_SPEED_CHANGE__SHIFT 0x00000007
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_SW_SPEED_CHANGE_MASK 0x00000020L
+#define PCIE_LC_SPEED_CNTL__LC_FORCE_EN_SW_SPEED_CHANGE__SHIFT 0x00000005
+#define PCIE_LC_SPEED_CNTL__LC_GEN2_EN_STRAP_MASK 0x00000001L
+#define PCIE_LC_SPEED_CNTL__LC_GEN2_EN_STRAP__SHIFT 0x00000000
+#define PCIE_LC_SPEED_CNTL__LC_GEN3_EN_STRAP_MASK 0x00000002L
+#define PCIE_LC_SPEED_CNTL__LC_GEN3_EN_STRAP__SHIFT 0x00000001
+#define PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK 0x00000200L
+#define PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE__SHIFT 0x00000009
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L0s_EN_MASK 0x10000000L
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L0s_EN__SHIFT 0x0000001c
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L1_EN_MASK 0x20000000L
+#define PCIE_LC_SPEED_CNTL__LC_INIT_SPEED_NEG_IN_L1_EN__SHIFT 0x0000001d
+#define PCIE_LC_SPEED_CNTL__LC_MULT_UPSTREAM_AUTO_SPD_CHNG_EN_MASK 0x08000000L
+#define PCIE_LC_SPEED_CNTL__LC_MULT_UPSTREAM_AUTO_SPD_CHNG_EN__SHIFT 0x0000001b
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN2_MASK 0x00040000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN2__SHIFT 0x00000012
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN3_MASK 0x00100000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_EVER_SENT_GEN3__SHIFT 0x00000014
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN2_MASK 0x00080000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN2__SHIFT 0x00000013
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN3_MASK 0x00200000L
+#define PCIE_LC_SPEED_CNTL__LC_OTHER_SIDE_SUPPORTS_GEN3__SHIFT 0x00000015
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPT_FAILED_MASK 0x00001000L
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPT_FAILED__SHIFT 0x0000000c
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK 0x00000c00L
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_ATTEMPTS_ALLOWED__SHIFT 0x0000000a
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_STATUS_MASK 0x00800000L
+#define PCIE_LC_SPEED_CNTL__LC_SPEED_CHANGE_STATUS__SHIFT 0x00000017
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE_EN_MASK 0x00000004L
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE_EN__SHIFT 0x00000002
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE_MASK 0x00000018L
+#define PCIE_LC_SPEED_CNTL__LC_TARGET_LINK_SPEED_OVERRIDE__SHIFT 0x00000003
+#define PCIE_LC_STATE0__LC_CURRENT_STATE_MASK 0x0000003fL
+#define PCIE_LC_STATE0__LC_CURRENT_STATE__SHIFT 0x00000000
+#define PCIE_LC_STATE0__LC_PREV_STATE1_MASK 0x00003f00L
+#define PCIE_LC_STATE0__LC_PREV_STATE1__SHIFT 0x00000008
+#define PCIE_LC_STATE0__LC_PREV_STATE2_MASK 0x003f0000L
+#define PCIE_LC_STATE0__LC_PREV_STATE2__SHIFT 0x00000010
+#define PCIE_LC_STATE0__LC_PREV_STATE3_MASK 0x3f000000L
+#define PCIE_LC_STATE0__LC_PREV_STATE3__SHIFT 0x00000018
+#define PCIE_LC_STATE10__LC_PREV_STATE40_MASK 0x0000003fL
+#define PCIE_LC_STATE10__LC_PREV_STATE40__SHIFT 0x00000000
+#define PCIE_LC_STATE10__LC_PREV_STATE41_MASK 0x00003f00L
+#define PCIE_LC_STATE10__LC_PREV_STATE41__SHIFT 0x00000008
+#define PCIE_LC_STATE10__LC_PREV_STATE42_MASK 0x003f0000L
+#define PCIE_LC_STATE10__LC_PREV_STATE42__SHIFT 0x00000010
+#define PCIE_LC_STATE10__LC_PREV_STATE43_MASK 0x3f000000L
+#define PCIE_LC_STATE10__LC_PREV_STATE43__SHIFT 0x00000018
+#define PCIE_LC_STATE11__LC_PREV_STATE44_MASK 0x0000003fL
+#define PCIE_LC_STATE11__LC_PREV_STATE44__SHIFT 0x00000000
+#define PCIE_LC_STATE11__LC_PREV_STATE45_MASK 0x00003f00L
+#define PCIE_LC_STATE11__LC_PREV_STATE45__SHIFT 0x00000008
+#define PCIE_LC_STATE11__LC_PREV_STATE46_MASK 0x003f0000L
+#define PCIE_LC_STATE11__LC_PREV_STATE46__SHIFT 0x00000010
+#define PCIE_LC_STATE11__LC_PREV_STATE47_MASK 0x3f000000L
+#define PCIE_LC_STATE11__LC_PREV_STATE47__SHIFT 0x00000018
+#define PCIE_LC_STATE1__LC_PREV_STATE4_MASK 0x0000003fL
+#define PCIE_LC_STATE1__LC_PREV_STATE4__SHIFT 0x00000000
+#define PCIE_LC_STATE1__LC_PREV_STATE5_MASK 0x00003f00L
+#define PCIE_LC_STATE1__LC_PREV_STATE5__SHIFT 0x00000008
+#define PCIE_LC_STATE1__LC_PREV_STATE6_MASK 0x003f0000L
+#define PCIE_LC_STATE1__LC_PREV_STATE6__SHIFT 0x00000010
+#define PCIE_LC_STATE1__LC_PREV_STATE7_MASK 0x3f000000L
+#define PCIE_LC_STATE1__LC_PREV_STATE7__SHIFT 0x00000018
+#define PCIE_LC_STATE2__LC_PREV_STATE10_MASK 0x003f0000L
+#define PCIE_LC_STATE2__LC_PREV_STATE10__SHIFT 0x00000010
+#define PCIE_LC_STATE2__LC_PREV_STATE11_MASK 0x3f000000L
+#define PCIE_LC_STATE2__LC_PREV_STATE11__SHIFT 0x00000018
+#define PCIE_LC_STATE2__LC_PREV_STATE8_MASK 0x0000003fL
+#define PCIE_LC_STATE2__LC_PREV_STATE8__SHIFT 0x00000000
+#define PCIE_LC_STATE2__LC_PREV_STATE9_MASK 0x00003f00L
+#define PCIE_LC_STATE2__LC_PREV_STATE9__SHIFT 0x00000008
+#define PCIE_LC_STATE3__LC_PREV_STATE12_MASK 0x0000003fL
+#define PCIE_LC_STATE3__LC_PREV_STATE12__SHIFT 0x00000000
+#define PCIE_LC_STATE3__LC_PREV_STATE13_MASK 0x00003f00L
+#define PCIE_LC_STATE3__LC_PREV_STATE13__SHIFT 0x00000008
+#define PCIE_LC_STATE3__LC_PREV_STATE14_MASK 0x003f0000L
+#define PCIE_LC_STATE3__LC_PREV_STATE14__SHIFT 0x00000010
+#define PCIE_LC_STATE3__LC_PREV_STATE15_MASK 0x3f000000L
+#define PCIE_LC_STATE3__LC_PREV_STATE15__SHIFT 0x00000018
+#define PCIE_LC_STATE4__LC_PREV_STATE16_MASK 0x0000003fL
+#define PCIE_LC_STATE4__LC_PREV_STATE16__SHIFT 0x00000000
+#define PCIE_LC_STATE4__LC_PREV_STATE17_MASK 0x00003f00L
+#define PCIE_LC_STATE4__LC_PREV_STATE17__SHIFT 0x00000008
+#define PCIE_LC_STATE4__LC_PREV_STATE18_MASK 0x003f0000L
+#define PCIE_LC_STATE4__LC_PREV_STATE18__SHIFT 0x00000010
+#define PCIE_LC_STATE4__LC_PREV_STATE19_MASK 0x3f000000L
+#define PCIE_LC_STATE4__LC_PREV_STATE19__SHIFT 0x00000018
+#define PCIE_LC_STATE5__LC_PREV_STATE20_MASK 0x0000003fL
+#define PCIE_LC_STATE5__LC_PREV_STATE20__SHIFT 0x00000000
+#define PCIE_LC_STATE5__LC_PREV_STATE21_MASK 0x00003f00L
+#define PCIE_LC_STATE5__LC_PREV_STATE21__SHIFT 0x00000008
+#define PCIE_LC_STATE5__LC_PREV_STATE22_MASK 0x003f0000L
+#define PCIE_LC_STATE5__LC_PREV_STATE22__SHIFT 0x00000010
+#define PCIE_LC_STATE5__LC_PREV_STATE23_MASK 0x3f000000L
+#define PCIE_LC_STATE5__LC_PREV_STATE23__SHIFT 0x00000018
+#define PCIE_LC_STATE6__LC_PREV_STATE24_MASK 0x0000003fL
+#define PCIE_LC_STATE6__LC_PREV_STATE24__SHIFT 0x00000000
+#define PCIE_LC_STATE6__LC_PREV_STATE25_MASK 0x00003f00L
+#define PCIE_LC_STATE6__LC_PREV_STATE25__SHIFT 0x00000008
+#define PCIE_LC_STATE6__LC_PREV_STATE26_MASK 0x003f0000L
+#define PCIE_LC_STATE6__LC_PREV_STATE26__SHIFT 0x00000010
+#define PCIE_LC_STATE6__LC_PREV_STATE27_MASK 0x3f000000L
+#define PCIE_LC_STATE6__LC_PREV_STATE27__SHIFT 0x00000018
+#define PCIE_LC_STATE7__LC_PREV_STATE28_MASK 0x0000003fL
+#define PCIE_LC_STATE7__LC_PREV_STATE28__SHIFT 0x00000000
+#define PCIE_LC_STATE7__LC_PREV_STATE29_MASK 0x00003f00L
+#define PCIE_LC_STATE7__LC_PREV_STATE29__SHIFT 0x00000008
+#define PCIE_LC_STATE7__LC_PREV_STATE30_MASK 0x003f0000L
+#define PCIE_LC_STATE7__LC_PREV_STATE30__SHIFT 0x00000010
+#define PCIE_LC_STATE7__LC_PREV_STATE31_MASK 0x3f000000L
+#define PCIE_LC_STATE7__LC_PREV_STATE31__SHIFT 0x00000018
+#define PCIE_LC_STATE8__LC_PREV_STATE32_MASK 0x0000003fL
+#define PCIE_LC_STATE8__LC_PREV_STATE32__SHIFT 0x00000000
+#define PCIE_LC_STATE8__LC_PREV_STATE33_MASK 0x00003f00L
+#define PCIE_LC_STATE8__LC_PREV_STATE33__SHIFT 0x00000008
+#define PCIE_LC_STATE8__LC_PREV_STATE34_MASK 0x003f0000L
+#define PCIE_LC_STATE8__LC_PREV_STATE34__SHIFT 0x00000010
+#define PCIE_LC_STATE8__LC_PREV_STATE35_MASK 0x3f000000L
+#define PCIE_LC_STATE8__LC_PREV_STATE35__SHIFT 0x00000018
+#define PCIE_LC_STATE9__LC_PREV_STATE36_MASK 0x0000003fL
+#define PCIE_LC_STATE9__LC_PREV_STATE36__SHIFT 0x00000000
+#define PCIE_LC_STATE9__LC_PREV_STATE37_MASK 0x00003f00L
+#define PCIE_LC_STATE9__LC_PREV_STATE37__SHIFT 0x00000008
+#define PCIE_LC_STATE9__LC_PREV_STATE38_MASK 0x003f0000L
+#define PCIE_LC_STATE9__LC_PREV_STATE38__SHIFT 0x00000010
+#define PCIE_LC_STATE9__LC_PREV_STATE39_MASK 0x3f000000L
+#define PCIE_LC_STATE9__LC_PREV_STATE39__SHIFT 0x00000018
+#define PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK 0x000000e0L
+#define PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH__SHIFT 0x00000005
+#define PCIE_LC_STATUS1__LC_OPERATING_LINK_WIDTH_MASK 0x0000001cL
+#define PCIE_LC_STATUS1__LC_OPERATING_LINK_WIDTH__SHIFT 0x00000002
+#define PCIE_LC_STATUS1__LC_REVERSE_RCVR_MASK 0x00000001L
+#define PCIE_LC_STATUS1__LC_REVERSE_RCVR__SHIFT 0x00000000
+#define PCIE_LC_STATUS1__LC_REVERSE_XMIT_MASK 0x00000002L
+#define PCIE_LC_STATUS1__LC_REVERSE_XMIT__SHIFT 0x00000001
+#define PCIE_LC_STATUS2__LC_TOTAL_INACTIVE_LANES_MASK 0x0000ffffL
+#define PCIE_LC_STATUS2__LC_TOTAL_INACTIVE_LANES__SHIFT 0x00000000
+#define PCIE_LC_STATUS2__LC_TURN_ON_LANE_MASK 0xffff0000L
+#define PCIE_LC_STATUS2__LC_TURN_ON_LANE__SHIFT 0x00000010
+#define PCIE_LC_TRAINING_CNTL__LC_ALLOW_TX_L1_CONTROL_MASK 0x10000000L
+#define PCIE_LC_TRAINING_CNTL__LC_ALLOW_TX_L1_CONTROL__SHIFT 0x0000001c
+#define PCIE_LC_TRAINING_CNTL__LC_ASPM_L1_NAK_TIMER_SEL_MASK 0x00c00000L
+#define PCIE_LC_TRAINING_CNTL__LC_ASPM_L1_NAK_TIMER_SEL__SHIFT 0x00000016
+#define PCIE_LC_TRAINING_CNTL__LC_AUTONOMOUS_CHANGE_OFF_MASK 0x00020000L
+#define PCIE_LC_TRAINING_CNTL__LC_AUTONOMOUS_CHANGE_OFF__SHIFT 0x00000011
+#define PCIE_LC_TRAINING_CNTL__LC_COMPLIANCE_RECEIVE_MASK 0x00000010L
+#define PCIE_LC_TRAINING_CNTL__LC_COMPLIANCE_RECEIVE__SHIFT 0x00000004
+#define PCIE_LC_TRAINING_CNTL__LC_DISABLE_TRAINING_BIT_ARCH_MASK 0x00002000L
+#define PCIE_LC_TRAINING_CNTL__LC_DISABLE_TRAINING_BIT_ARCH__SHIFT 0x0000000d
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_R_SPEED_MASK 0x01000000L
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_R_SPEED__SHIFT 0x00000018
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_TEST_MASK 0x02000000L
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_DEASSERT_RX_EN_IN_TEST__SHIFT 0x00000019
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_GO_TO_L0S_IF_L1_ARMED_MASK 0x00000800L
+#define PCIE_LC_TRAINING_CNTL__LC_DONT_GO_TO_L0S_IF_L1_ARMED__SHIFT 0x0000000b
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_EQ_REQ_TIME_MASK 0xc0000000L
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_EQ_REQ_TIME__SHIFT 0x0000001e
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_WAIT_FOR_SKP_MASK 0x00010000L
+#define PCIE_LC_TRAINING_CNTL__LC_EXTEND_WAIT_FOR_SKP__SHIFT 0x00000010
+#define PCIE_LC_TRAINING_CNTL__LC_HW_LINK_DIS_EN_MASK 0x00080000L
+#define PCIE_LC_TRAINING_CNTL__LC_HW_LINK_DIS_EN__SHIFT 0x00000013
+#define PCIE_LC_TRAINING_CNTL__LC_INIT_SPD_CHG_WITH_CSR_EN_MASK 0x00001000L
+#define PCIE_LC_TRAINING_CNTL__LC_INIT_SPD_CHG_WITH_CSR_EN__SHIFT 0x0000000c
+#define PCIE_LC_TRAINING_CNTL__LC_L0S_L1_TRAINING_CNTL_EN_MASK 0x00000040L
+#define PCIE_LC_TRAINING_CNTL__LC_L0S_L1_TRAINING_CNTL_EN__SHIFT 0x00000006
+#define PCIE_LC_TRAINING_CNTL__LC_L1_LONG_WAKE_FIX_EN_MASK 0x00000080L
+#define PCIE_LC_TRAINING_CNTL__LC_L1_LONG_WAKE_FIX_EN__SHIFT 0x00000007
+#define PCIE_LC_TRAINING_CNTL__LC_LINK_DIS_BY_HW_MASK 0x00100000L
+#define PCIE_LC_TRAINING_CNTL__LC_LINK_DIS_BY_HW__SHIFT 0x00000014
+#define PCIE_LC_TRAINING_CNTL__LC_LOOK_FOR_MORE_NON_MATCHING_TS1_MASK 0x00000020L
+#define PCIE_LC_TRAINING_CNTL__LC_LOOK_FOR_MORE_NON_MATCHING_TS1__SHIFT 0x00000005
+#define PCIE_LC_TRAINING_CNTL__LC_POWER_STATE_MASK 0x00000700L
+#define PCIE_LC_TRAINING_CNTL__LC_POWER_STATE__SHIFT 0x00000008
+#define PCIE_LC_TRAINING_CNTL__LC_RESET_ASPM_L1_NAK_TIMER_MASK 0x04000000L
+#define PCIE_LC_TRAINING_CNTL__LC_RESET_ASPM_L1_NAK_TIMER__SHIFT 0x0000001a
+#define PCIE_LC_TRAINING_CNTL__LC_SHORT_RCFG_TIMEOUT_MASK 0x08000000L
+#define PCIE_LC_TRAINING_CNTL__LC_SHORT_RCFG_TIMEOUT__SHIFT 0x0000001b
+#define PCIE_LC_TRAINING_CNTL__LC_STATIC_TX_PIPE_COUNT_EN_MASK 0x00200000L
+#define PCIE_LC_TRAINING_CNTL__LC_STATIC_TX_PIPE_COUNT_EN__SHIFT 0x00000015
+#define PCIE_LC_TRAINING_CNTL__LC_TRAINING_CNTL_MASK 0x0000000fL
+#define PCIE_LC_TRAINING_CNTL__LC_TRAINING_CNTL__SHIFT 0x00000000
+#define PCIE_LC_TRAINING_CNTL__LC_UPCONFIGURE_CAP_OFF_MASK 0x00040000L
+#define PCIE_LC_TRAINING_CNTL__LC_UPCONFIGURE_CAP_OFF__SHIFT 0x00000012
+#define PCIE_LC_TRAINING_CNTL__LC_WAIT_FOR_FOM_VALID_AFTER_TRACK_MASK 0x20000000L
+#define PCIE_LC_TRAINING_CNTL__LC_WAIT_FOR_FOM_VALID_AFTER_TRACK__SHIFT 0x0000001d
+#define PCIE_P_BUF_STATUS__P_OVERFLOW_ERR_MASK 0x0000ffffL
+#define PCIE_P_BUF_STATUS__P_OVERFLOW_ERR__SHIFT 0x00000000
+#define PCIE_P_BUF_STATUS__P_UNDERFLOW_ERR_MASK 0xffff0000L
+#define PCIE_P_BUF_STATUS__P_UNDERFLOW_ERR__SHIFT 0x00000010
+#define PCIE_P_CNTL__P_ALWAYS_USE_FAST_TXCLK_MASK 0x00002000L
+#define PCIE_P_CNTL__P_ALWAYS_USE_FAST_TXCLK__SHIFT 0x0000000d
+#define PCIE_P_CNTL__P_BLK_LOCK_MODE_MASK 0x00001000L
+#define PCIE_P_CNTL__P_BLK_LOCK_MODE__SHIFT 0x0000000c
+#define PCIE_P_CNTL__P_ELASTDESKEW_HW_DEBUG_MASK 0x00000008L
+#define PCIE_P_CNTL__P_ELASTDESKEW_HW_DEBUG__SHIFT 0x00000003
+#define PCIE_P_CNTL__P_ELEC_IDLE_MODE_MASK 0x0000c000L
+#define PCIE_P_CNTL__P_ELEC_IDLE_MODE__SHIFT 0x0000000e
+#define PCIE_P_CNTL__P_IGNORE_CRC_ERR_MASK 0x00000010L
+#define PCIE_P_CNTL__P_IGNORE_CRC_ERR__SHIFT 0x00000004
+#define PCIE_P_CNTL__P_IGNORE_EDB_ERR_MASK 0x00000040L
+#define PCIE_P_CNTL__P_IGNORE_EDB_ERR__SHIFT 0x00000006
+#define PCIE_P_CNTL__P_IGNORE_IDL_ERR_MASK 0x00000080L
+#define PCIE_P_CNTL__P_IGNORE_IDL_ERR__SHIFT 0x00000007
+#define PCIE_P_CNTL__P_IGNORE_LEN_ERR_MASK 0x00000020L
+#define PCIE_P_CNTL__P_IGNORE_LEN_ERR__SHIFT 0x00000005
+#define PCIE_P_CNTL__P_IGNORE_TOK_ERR_MASK 0x00000100L
+#define PCIE_P_CNTL__P_IGNORE_TOK_ERR__SHIFT 0x00000008
+#define PCIE_P_CNTL__P_PWRDN_EN_MASK 0x00000001L
+#define PCIE_P_CNTL__P_PWRDN_EN__SHIFT 0x00000000
+#define PCIE_P_CNTL__P_SYMALIGN_HW_DEBUG_MASK 0x00000004L
+#define PCIE_P_CNTL__P_SYMALIGN_HW_DEBUG__SHIFT 0x00000002
+#define PCIE_P_CNTL__P_SYMALIGN_MODE_MASK 0x00000002L
+#define PCIE_P_CNTL__P_SYMALIGN_MODE__SHIFT 0x00000001
+#define PCIE_P_DECODER_STATUS__P_DECODE_ERR_MASK 0x0000ffffL
+#define PCIE_P_DECODER_STATUS__P_DECODE_ERR__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_C_CLK_MASK 0x00000f00L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_C_CLK__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_R_CLK_MASK 0x000000f0L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_MST_R_CLK__SHIFT 0x00000004
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_NS_C_CLK_MASK 0x00f00000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_NS_C_CLK__SHIFT 0x00000014
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_R_CLK_MASK 0x0000f000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_R_CLK__SHIFT 0x0000000c
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_S_C_CLK_MASK 0x000f0000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_SLV_S_C_CLK__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK2_MASK 0x0f000000L
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK2__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK_MASK 0x0000000fL
+#define PCIE_PERF_CNTL_EVENT0_PORT_SEL__PERF0_PORT_SEL_TXCLK__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_C_CLK_MASK 0x00000f00L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_C_CLK__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_R_CLK_MASK 0x000000f0L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_MST_R_CLK__SHIFT 0x00000004
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_NS_C_CLK_MASK 0x00f00000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_NS_C_CLK__SHIFT 0x00000014
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_R_CLK_MASK 0x0000f000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_R_CLK__SHIFT 0x0000000c
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_S_C_CLK_MASK 0x000f0000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_SLV_S_C_CLK__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK2_MASK 0x0f000000L
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK2__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK_MASK 0x0000000fL
+#define PCIE_PERF_CNTL_EVENT1_PORT_SEL__PERF1_PORT_SEL_TXCLK__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_MST_C_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_MST_C_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_MST_R_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_MST_R_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_SLV_NS_C_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_SLV_R_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_SLV_R_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_SLV_S_C_CLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_TXCLK2__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_TXCLK2__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_TXCLK2__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_TXCLK2__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_TXCLK2__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_CNTL_TXCLK__COUNTER0_UPPER_MASK 0x00ff0000L
+#define PCIE_PERF_CNTL_TXCLK__COUNTER0_UPPER__SHIFT 0x00000010
+#define PCIE_PERF_CNTL_TXCLK__COUNTER1_UPPER_MASK 0xff000000L
+#define PCIE_PERF_CNTL_TXCLK__COUNTER1_UPPER__SHIFT 0x00000018
+#define PCIE_PERF_CNTL_TXCLK__EVENT0_SEL_MASK 0x000000ffL
+#define PCIE_PERF_CNTL_TXCLK__EVENT0_SEL__SHIFT 0x00000000
+#define PCIE_PERF_CNTL_TXCLK__EVENT1_SEL_MASK 0x0000ff00L
+#define PCIE_PERF_CNTL_TXCLK__EVENT1_SEL__SHIFT 0x00000008
+#define PCIE_PERF_COUNT0_MST_C_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_MST_C_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_MST_R_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_MST_R_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_SLV_NS_C_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_SLV_NS_C_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_SLV_R_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_SLV_R_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_SLV_S_C_CLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_SLV_S_C_CLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_TXCLK2__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_TXCLK2__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT0_TXCLK__COUNTER0_MASK 0xffffffffL
+#define PCIE_PERF_COUNT0_TXCLK__COUNTER0__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_MST_C_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_MST_C_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_MST_R_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_MST_R_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_SLV_NS_C_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_SLV_NS_C_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_SLV_R_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_SLV_R_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_SLV_S_C_CLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_SLV_S_C_CLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_TXCLK2__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_TXCLK2__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT1_TXCLK__COUNTER1_MASK 0xffffffffL
+#define PCIE_PERF_COUNT1_TXCLK__COUNTER1__SHIFT 0x00000000
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_EN_MASK 0x00000001L
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_EN__SHIFT 0x00000000
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_RESET_MASK 0x00000004L
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_COUNT_RESET__SHIFT 0x00000002
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_SHADOW_WR_MASK 0x00000002L
+#define PCIE_PERF_COUNT_CNTL__GLOBAL_SHADOW_WR__SHIFT 0x00000001
+#define PCIEP_HW_DEBUG__HW_00_DEBUG_MASK 0x00000001L
+#define PCIEP_HW_DEBUG__HW_00_DEBUG__SHIFT 0x00000000
+#define PCIEP_HW_DEBUG__HW_01_DEBUG_MASK 0x00000002L
+#define PCIEP_HW_DEBUG__HW_01_DEBUG__SHIFT 0x00000001
+#define PCIEP_HW_DEBUG__HW_02_DEBUG_MASK 0x00000004L
+#define PCIEP_HW_DEBUG__HW_02_DEBUG__SHIFT 0x00000002
+#define PCIEP_HW_DEBUG__HW_03_DEBUG_MASK 0x00000008L
+#define PCIEP_HW_DEBUG__HW_03_DEBUG__SHIFT 0x00000003
+#define PCIEP_HW_DEBUG__HW_04_DEBUG_MASK 0x00000010L
+#define PCIEP_HW_DEBUG__HW_04_DEBUG__SHIFT 0x00000004
+#define PCIEP_HW_DEBUG__HW_05_DEBUG_MASK 0x00000020L
+#define PCIEP_HW_DEBUG__HW_05_DEBUG__SHIFT 0x00000005
+#define PCIEP_HW_DEBUG__HW_06_DEBUG_MASK 0x00000040L
+#define PCIEP_HW_DEBUG__HW_06_DEBUG__SHIFT 0x00000006
+#define PCIEP_HW_DEBUG__HW_07_DEBUG_MASK 0x00000080L
+#define PCIEP_HW_DEBUG__HW_07_DEBUG__SHIFT 0x00000007
+#define PCIEP_HW_DEBUG__HW_08_DEBUG_MASK 0x00000100L
+#define PCIEP_HW_DEBUG__HW_08_DEBUG__SHIFT 0x00000008
+#define PCIEP_HW_DEBUG__HW_09_DEBUG_MASK 0x00000200L
+#define PCIEP_HW_DEBUG__HW_09_DEBUG__SHIFT 0x00000009
+#define PCIEP_HW_DEBUG__HW_10_DEBUG_MASK 0x00000400L
+#define PCIEP_HW_DEBUG__HW_10_DEBUG__SHIFT 0x0000000a
+#define PCIEP_HW_DEBUG__HW_11_DEBUG_MASK 0x00000800L
+#define PCIEP_HW_DEBUG__HW_11_DEBUG__SHIFT 0x0000000b
+#define PCIEP_HW_DEBUG__HW_12_DEBUG_MASK 0x00001000L
+#define PCIEP_HW_DEBUG__HW_12_DEBUG__SHIFT 0x0000000c
+#define PCIEP_HW_DEBUG__HW_13_DEBUG_MASK 0x00002000L
+#define PCIEP_HW_DEBUG__HW_13_DEBUG__SHIFT 0x0000000d
+#define PCIEP_HW_DEBUG__HW_14_DEBUG_MASK 0x00004000L
+#define PCIEP_HW_DEBUG__HW_14_DEBUG__SHIFT 0x0000000e
+#define PCIEP_HW_DEBUG__HW_15_DEBUG_MASK 0x00008000L
+#define PCIEP_HW_DEBUG__HW_15_DEBUG__SHIFT 0x0000000f
+#define PCIE_P_MISC_STATUS__P_DESKEW_ERR_MASK 0x000000ffL
+#define PCIE_P_MISC_STATUS__P_DESKEW_ERR__SHIFT 0x00000000
+#define PCIE_P_MISC_STATUS__P_SYMUNLOCK_ERR_MASK 0xffff0000L
+#define PCIE_P_MISC_STATUS__P_SYMUNLOCK_ERR__SHIFT 0x00000010
+#define PCIE_PORT_DATA__PCIE_DATA_MASK 0xffffffffL
+#define PCIE_PORT_DATA__PCIE_DATA__SHIFT 0x00000000
+#define PCIE_PORT_INDEX__PCIE_INDEX_MASK 0x000000ffL
+#define PCIE_PORT_INDEX__PCIE_INDEX__SHIFT 0x00000000
+#define PCIEP_PORT_CNTL__CI_SLV_CPL_STATIC_ALLOC_LIMIT_S_MASK 0x00007f00L
+#define PCIEP_PORT_CNTL__CI_SLV_CPL_STATIC_ALLOC_LIMIT_S__SHIFT 0x00000008
+#define PCIEP_PORT_CNTL__CI_SNOOP_OVERRIDE_MASK 0x00000002L
+#define PCIEP_PORT_CNTL__CI_SNOOP_OVERRIDE__SHIFT 0x00000001
+#define PCIEP_PORT_CNTL__HOTPLUG_MSG_EN_MASK 0x00000004L
+#define PCIEP_PORT_CNTL__HOTPLUG_MSG_EN__SHIFT 0x00000002
+#define PCIEP_PORT_CNTL__NATIVE_PME_EN_MASK 0x00000008L
+#define PCIEP_PORT_CNTL__NATIVE_PME_EN__SHIFT 0x00000003
+#define PCIEP_PORT_CNTL__PMI_BM_DIS_MASK 0x00000020L
+#define PCIEP_PORT_CNTL__PMI_BM_DIS__SHIFT 0x00000005
+#define PCIEP_PORT_CNTL__PWR_FAULT_EN_MASK 0x00000010L
+#define PCIEP_PORT_CNTL__PWR_FAULT_EN__SHIFT 0x00000004
+#define PCIEP_PORT_CNTL__SEQNUM_DEBUG_MODE_MASK 0x00000040L
+#define PCIEP_PORT_CNTL__SEQNUM_DEBUG_MODE__SHIFT 0x00000006
+#define PCIEP_PORT_CNTL__SLV_PORT_REQ_EN_MASK 0x00000001L
+#define PCIEP_PORT_CNTL__SLV_PORT_REQ_EN__SHIFT 0x00000000
+#define PCIE_P_PORT_LANE_STATUS__PHY_LINK_WIDTH_MASK 0x0000007eL
+#define PCIE_P_PORT_LANE_STATUS__PHY_LINK_WIDTH__SHIFT 0x00000001
+#define PCIE_P_PORT_LANE_STATUS__PORT_LANE_REVERSAL_MASK 0x00000001L
+#define PCIE_P_PORT_LANE_STATUS__PORT_LANE_REVERSAL__SHIFT 0x00000000
+#define PCIE_PRBS_CLR__PRBS_CHECKER_DEBUG_BUS_SELECT_MASK 0x000f0000L
+#define PCIE_PRBS_CLR__PRBS_CHECKER_DEBUG_BUS_SELECT__SHIFT 0x00000010
+#define PCIE_PRBS_CLR__PRBS_CLR_MASK 0x0000ffffL
+#define PCIE_PRBS_CLR__PRBS_CLR__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_0__PRBS_ERRCNT_0_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_0__PRBS_ERRCNT_0__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_10__PRBS_ERRCNT_10_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_10__PRBS_ERRCNT_10__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_11__PRBS_ERRCNT_11_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_11__PRBS_ERRCNT_11__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_12__PRBS_ERRCNT_12_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_12__PRBS_ERRCNT_12__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_13__PRBS_ERRCNT_13_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_13__PRBS_ERRCNT_13__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_14__PRBS_ERRCNT_14_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_14__PRBS_ERRCNT_14__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_15__PRBS_ERRCNT_15_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_15__PRBS_ERRCNT_15__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_1__PRBS_ERRCNT_1_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_1__PRBS_ERRCNT_1__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_2__PRBS_ERRCNT_2_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_2__PRBS_ERRCNT_2__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_3__PRBS_ERRCNT_3_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_3__PRBS_ERRCNT_3__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_4__PRBS_ERRCNT_4_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_4__PRBS_ERRCNT_4__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_5__PRBS_ERRCNT_5_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_5__PRBS_ERRCNT_5__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_6__PRBS_ERRCNT_6_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_6__PRBS_ERRCNT_6__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_7__PRBS_ERRCNT_7_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_7__PRBS_ERRCNT_7__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_8__PRBS_ERRCNT_8_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_8__PRBS_ERRCNT_8__SHIFT 0x00000000
+#define PCIE_PRBS_ERRCNT_9__PRBS_ERRCNT_9_MASK 0xffffffffL
+#define PCIE_PRBS_ERRCNT_9__PRBS_ERRCNT_9__SHIFT 0x00000000
+#define PCIE_PRBS_FREERUN__PRBS_FREERUN_MASK 0x0000ffffL
+#define PCIE_PRBS_FREERUN__PRBS_FREERUN__SHIFT 0x00000000
+#define PCIE_PRBS_HI_BITCNT__PRBS_HI_BITCNT_MASK 0x000000ffL
+#define PCIE_PRBS_HI_BITCNT__PRBS_HI_BITCNT__SHIFT 0x00000000
+#define PCIE_PRBS_LO_BITCNT__PRBS_LO_BITCNT_MASK 0xffffffffL
+#define PCIE_PRBS_LO_BITCNT__PRBS_LO_BITCNT__SHIFT 0x00000000
+#define PCIE_PRBS_MISC__PRBS_8BIT_SEL_MASK 0x00000010L
+#define PCIE_PRBS_MISC__PRBS_8BIT_SEL__SHIFT 0x00000004
+#define PCIE_PRBS_MISC__PRBS_CHK_ERR_MASK_MASK 0xffff0000L
+#define PCIE_PRBS_MISC__PRBS_CHK_ERR_MASK__SHIFT 0x00000010
+#define PCIE_PRBS_MISC__PRBS_COMMA_NUM_MASK 0x00000060L
+#define PCIE_PRBS_MISC__PRBS_COMMA_NUM__SHIFT 0x00000005
+#define PCIE_PRBS_MISC__PRBS_DATA_RATE_MASK 0x0000c000L
+#define PCIE_PRBS_MISC__PRBS_DATA_RATE__SHIFT 0x0000000e
+#define PCIE_PRBS_MISC__PRBS_EN_MASK 0x00000001L
+#define PCIE_PRBS_MISC__PRBS_EN__SHIFT 0x00000000
+#define PCIE_PRBS_MISC__PRBS_LOCK_CNT_MASK 0x00000f80L
+#define PCIE_PRBS_MISC__PRBS_LOCK_CNT__SHIFT 0x00000007
+#define PCIE_PRBS_MISC__PRBS_TEST_MODE_MASK 0x00000006L
+#define PCIE_PRBS_MISC__PRBS_TEST_MODE__SHIFT 0x00000001
+#define PCIE_PRBS_MISC__PRBS_USER_PATTERN_TOGGLE_MASK 0x00000008L
+#define PCIE_PRBS_MISC__PRBS_USER_PATTERN_TOGGLE__SHIFT 0x00000003
+#define PCIE_PRBS_STATUS1__PRBS_ERRSTAT_MASK 0x0000ffffL
+#define PCIE_PRBS_STATUS1__PRBS_ERRSTAT__SHIFT 0x00000000
+#define PCIE_PRBS_STATUS1__PRBS_LOCKED_MASK 0xffff0000L
+#define PCIE_PRBS_STATUS1__PRBS_LOCKED__SHIFT 0x00000010
+#define PCIE_PRBS_STATUS2__PRBS_BITCNT_DONE_MASK 0x0000ffffL
+#define PCIE_PRBS_STATUS2__PRBS_BITCNT_DONE__SHIFT 0x00000000
+#define PCIE_PRBS_USER_PATTERN__PRBS_USER_PATTERN_MASK 0x3fffffffL
+#define PCIE_PRBS_USER_PATTERN__PRBS_USER_PATTERN__SHIFT 0x00000000
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MAX_MASK 0x0000ff00L
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MAX__SHIFT 0x00000008
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MIN_MASK 0x000000ffL
+#define PCIE_P_RCV_L0S_FTS_DET__P_RCV_L0S_FTS_DET_MIN__SHIFT 0x00000000
+#define PCIEP_RESERVED__PCIEP_RESERVED_MASK 0xffffffffL
+#define PCIEP_RESERVED__PCIEP_RESERVED__SHIFT 0x00000000
+#define PCIEP_SCRATCH__PCIEP_SCRATCH_MASK 0xffffffffL
+#define PCIEP_SCRATCH__PCIEP_SCRATCH__SHIFT 0x00000000
+#define PCIEP_STRAP_LC__STRAP_AUTO_RC_SPEED_NEGOTIATION_DIS_MASK 0x00008000L
+#define PCIEP_STRAP_LC__STRAP_AUTO_RC_SPEED_NEGOTIATION_DIS__SHIFT 0x0000000f
+#define PCIEP_STRAP_LC__STRAP_BYPASS_RCVR_DET_MASK 0x00000800L
+#define PCIEP_STRAP_LC__STRAP_BYPASS_RCVR_DET__SHIFT 0x0000000b
+#define PCIEP_STRAP_LC__STRAP_COMPLIANCE_DIS_MASK 0x00001000L
+#define PCIEP_STRAP_LC__STRAP_COMPLIANCE_DIS__SHIFT 0x0000000c
+#define PCIEP_STRAP_LC__STRAP_FORCE_COMPLIANCE_MASK 0x00002000L
+#define PCIEP_STRAP_LC__STRAP_FORCE_COMPLIANCE__SHIFT 0x0000000d
+#define PCIEP_STRAP_LC__STRAP_FTS_yTSx_COUNT_MASK 0x00000003L
+#define PCIEP_STRAP_LC__STRAP_FTS_yTSx_COUNT__SHIFT 0x00000000
+#define PCIEP_STRAP_LC__STRAP_LANE_NEGOTIATION_MASK 0x00070000L
+#define PCIEP_STRAP_LC__STRAP_LANE_NEGOTIATION__SHIFT 0x00000010
+#define PCIEP_STRAP_LC__STRAP_LONG_yTSx_COUNT_MASK 0x0000000cL
+#define PCIEP_STRAP_LC__STRAP_LONG_yTSx_COUNT__SHIFT 0x00000002
+#define PCIEP_STRAP_LC__STRAP_MED_yTSx_COUNT_MASK 0x00000030L
+#define PCIEP_STRAP_LC__STRAP_MED_yTSx_COUNT__SHIFT 0x00000004
+#define PCIEP_STRAP_LC__STRAP_REVERSE_LC_LANES_MASK 0x00004000L
+#define PCIEP_STRAP_LC__STRAP_REVERSE_LC_LANES__SHIFT 0x0000000e
+#define PCIEP_STRAP_LC__STRAP_SHORT_yTSx_COUNT_MASK 0x000000c0L
+#define PCIEP_STRAP_LC__STRAP_SHORT_yTSx_COUNT__SHIFT 0x00000006
+#define PCIEP_STRAP_LC__STRAP_SKIP_INTERVAL_MASK 0x00000700L
+#define PCIEP_STRAP_LC__STRAP_SKIP_INTERVAL__SHIFT 0x00000008
+#define PCIEP_STRAP_MISC__STRAP_E2E_PREFIX_EN_MASK 0x00000002L
+#define PCIEP_STRAP_MISC__STRAP_E2E_PREFIX_EN__SHIFT 0x00000001
+#define PCIEP_STRAP_MISC__STRAP_EXTENDED_FMT_SUPPORTED_MASK 0x00000004L
+#define PCIEP_STRAP_MISC__STRAP_EXTENDED_FMT_SUPPORTED__SHIFT 0x00000002
+#define PCIEP_STRAP_MISC__STRAP_OBFF_SUPPORTED_MASK 0x00000018L
+#define PCIEP_STRAP_MISC__STRAP_OBFF_SUPPORTED__SHIFT 0x00000003
+#define PCIEP_STRAP_MISC__STRAP_REVERSE_LANES_MASK 0x00000001L
+#define PCIEP_STRAP_MISC__STRAP_REVERSE_LANES__SHIFT 0x00000000
+#define PCIE_RESERVED__PCIE_RESERVED_MASK 0xffffffffL
+#define PCIE_RESERVED__PCIE_RESERVED__SHIFT 0x00000000
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_ATSTRANSREQ_UR_MASK 0x00000008L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_ATSTRANSREQ_UR__SHIFT 0x00000003
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVALIDPASID_UR_MASK 0x00000001L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVALIDPASID_UR__SHIFT 0x00000000
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVCPL_UR_MASK 0x00000020L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_INVCPL_UR__SHIFT 0x00000005
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_PAGEREQMSG_UR_MASK 0x00000010L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_PAGEREQMSG_UR__SHIFT 0x00000004
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMRD_UR_MASK 0x00000002L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMRD_UR__SHIFT 0x00000001
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMWR_UR_MASK 0x00000004L
+#define PCIE_RX_CNTL2__RX_IGNORE_EP_TRANSMWR_UR__SHIFT 0x00000002
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVCPLPASID_UR_MASK 0x00000010L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVCPLPASID_UR__SHIFT 0x00000004
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVREQ_UR_MASK 0x00000008L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_INVREQ_UR__SHIFT 0x00000003
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_PRGRESPMSG_UR_MASK 0x00000004L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_PRGRESPMSG_UR__SHIFT 0x00000002
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMRDPASID_UR_MASK 0x00000001L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMRDPASID_UR__SHIFT 0x00000000
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMWRPASID_UR_MASK 0x00000002L
+#define PCIE_RX_CNTL3__RX_IGNORE_RC_TRANSMWRPASID_UR__SHIFT 0x00000001
+#define PCIE_RX_CNTL__RX_FC_INIT_FROM_REG_MASK 0x00008000L
+#define PCIE_RX_CNTL__RX_FC_INIT_FROM_REG__SHIFT 0x0000000f
+#define PCIE_RX_CNTL__RX_GEN_ONE_NAK_MASK 0x00004000L
+#define PCIE_RX_CNTL__RX_GEN_ONE_NAK__SHIFT 0x0000000e
+#define PCIE_RX_CNTL__RX_IGNORE_AT_ERR_MASK 0x00001000L
+#define PCIE_RX_CNTL__RX_IGNORE_AT_ERR__SHIFT 0x0000000c
+#define PCIE_RX_CNTL__RX_IGNORE_BE_ERR_MASK 0x00000002L
+#define PCIE_RX_CNTL__RX_IGNORE_BE_ERR__SHIFT 0x00000001
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_ERR_MASK 0x00000010L
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_ERR__SHIFT 0x00000004
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_UR_MASK 0x00000400L
+#define PCIE_RX_CNTL__RX_IGNORE_CFG_UR__SHIFT 0x0000000a
+#define PCIE_RX_CNTL__RX_IGNORE_CPL_ERR_MASK 0x00000020L
+#define PCIE_RX_CNTL__RX_IGNORE_CPL_ERR__SHIFT 0x00000005
+#define PCIE_RX_CNTL__RX_IGNORE_CPLPREFIX_ERR_MASK 0x00800000L
+#define PCIE_RX_CNTL__RX_IGNORE_CPLPREFIX_ERR__SHIFT 0x00000017
+#define PCIE_RX_CNTL__RX_IGNORE_CRC_ERR_MASK 0x00000008L
+#define PCIE_RX_CNTL__RX_IGNORE_CRC_ERR__SHIFT 0x00000003
+#define PCIE_RX_CNTL__RX_IGNORE_EP_ERR_MASK 0x00000040L
+#define PCIE_RX_CNTL__RX_IGNORE_EP_ERR__SHIFT 0x00000006
+#define PCIE_RX_CNTL__RX_IGNORE_INVALIDPASID_ERR_MASK 0x01000000L
+#define PCIE_RX_CNTL__RX_IGNORE_INVALIDPASID_ERR__SHIFT 0x00000018
+#define PCIE_RX_CNTL__RX_IGNORE_IO_ERR_MASK 0x00000001L
+#define PCIE_RX_CNTL__RX_IGNORE_IO_ERR__SHIFT 0x00000000
+#define PCIE_RX_CNTL__RX_IGNORE_IO_UR_MASK 0x00000800L
+#define PCIE_RX_CNTL__RX_IGNORE_IO_UR__SHIFT 0x0000000b
+#define PCIE_RX_CNTL__RX_IGNORE_LEN_MISMATCH_ERR_MASK 0x00000080L
+#define PCIE_RX_CNTL__RX_IGNORE_LEN_MISMATCH_ERR__SHIFT 0x00000007
+#define PCIE_RX_CNTL__RX_IGNORE_MAX_PAYLOAD_ERR_MASK 0x00000100L
+#define PCIE_RX_CNTL__RX_IGNORE_MAX_PAYLOAD_ERR__SHIFT 0x00000008
+#define PCIE_RX_CNTL__RX_IGNORE_MAXPREFIX_ERR_MASK 0x00400000L
+#define PCIE_RX_CNTL__RX_IGNORE_MAXPREFIX_ERR__SHIFT 0x00000016
+#define PCIE_RX_CNTL__RX_IGNORE_MSG_ERR_MASK 0x00000004L
+#define PCIE_RX_CNTL__RX_IGNORE_MSG_ERR__SHIFT 0x00000002
+#define PCIE_RX_CNTL__RX_IGNORE_NOT_PASID_UR_MASK 0x02000000L
+#define PCIE_RX_CNTL__RX_IGNORE_NOT_PASID_UR__SHIFT 0x00000019
+#define PCIE_RX_CNTL__RX_IGNORE_SHORTPREFIX_ERR_MASK 0x00200000L
+#define PCIE_RX_CNTL__RX_IGNORE_SHORTPREFIX_ERR__SHIFT 0x00000015
+#define PCIE_RX_CNTL__RX_IGNORE_TC_ERR_MASK 0x00000200L
+#define PCIE_RX_CNTL__RX_IGNORE_TC_ERR__SHIFT 0x00000009
+#define PCIE_RX_CNTL__RX_NAK_IF_FIFO_FULL_MASK 0x00002000L
+#define PCIE_RX_CNTL__RX_NAK_IF_FIFO_FULL__SHIFT 0x0000000d
+#define PCIE_RX_CNTL__RX_PCIE_CPL_TIMEOUT_DIS_MASK 0x00100000L
+#define PCIE_RX_CNTL__RX_PCIE_CPL_TIMEOUT_DIS__SHIFT 0x00000014
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT_MASK 0x00070000L
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT_MODE_MASK 0x00080000L
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT_MODE__SHIFT 0x00000013
+#define PCIE_RX_CNTL__RX_RCB_CPL_TIMEOUT__SHIFT 0x00000010
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLD_MASK 0x00000fffL
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLD__SHIFT 0x00000000
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLH_MASK 0x00ff0000L
+#define PCIE_RX_CREDITS_ALLOCATED_CPL__RX_CREDITS_ALLOCATED_CPLH__SHIFT 0x00000010
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPD_MASK 0x00000fffL
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPD__SHIFT 0x00000000
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPH_MASK 0x00ff0000L
+#define PCIE_RX_CREDITS_ALLOCATED_NP__RX_CREDITS_ALLOCATED_NPH__SHIFT 0x00000010
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PD_MASK 0x00000fffL
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PD__SHIFT 0x00000000
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PH_MASK 0x00ff0000L
+#define PCIE_RX_CREDITS_ALLOCATED_P__RX_CREDITS_ALLOCATED_PH__SHIFT 0x00000010
+#define PCIE_RX_EXPECTED_SEQNUM__RX_EXPECTED_SEQNUM_MASK 0x00000fffL
+#define PCIE_RX_EXPECTED_SEQNUM__RX_EXPECTED_SEQNUM__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP0__RX_LAST_TLP0_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP0__RX_LAST_TLP0__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP1__RX_LAST_TLP1_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP1__RX_LAST_TLP1__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP2__RX_LAST_TLP2_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP2__RX_LAST_TLP2__SHIFT 0x00000000
+#define PCIE_RX_LAST_TLP3__RX_LAST_TLP3_MASK 0xffffffffL
+#define PCIE_RX_LAST_TLP3__RX_LAST_TLP3__SHIFT 0x00000000
+#define PCIE_RX_NUM_NAK_GENERATED__RX_NUM_NAK_GENERATED_MASK 0xffffffffL
+#define PCIE_RX_NUM_NAK_GENERATED__RX_NUM_NAK_GENERATED__SHIFT 0x00000000
+#define PCIE_RX_NUM_NAK__RX_NUM_NAK_MASK 0xffffffffL
+#define PCIE_RX_NUM_NAK__RX_NUM_NAK__SHIFT 0x00000000
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_DATA_MASK 0x00ffffffL
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_DATA__SHIFT 0x00000000
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_STATUS_MASK 0x01000000L
+#define PCIE_RX_VENDOR_SPECIFIC__RX_VENDOR_STATUS__SHIFT 0x00000018
+#define PCIE_SCRATCH__PCIE_SCRATCH_MASK 0xffffffffL
+#define PCIE_SCRATCH__PCIE_SCRATCH__SHIFT 0x00000000
+#define PCIE_STRAP_F0__STRAP_F0_ACS_EN_MASK 0x00000040L
+#define PCIE_STRAP_F0__STRAP_F0_ACS_EN__SHIFT 0x00000006
+#define PCIE_STRAP_F0__STRAP_F0_AER_EN_MASK 0x00000020L
+#define PCIE_STRAP_F0__STRAP_F0_AER_EN__SHIFT 0x00000005
+#define PCIE_STRAP_F0__STRAP_F0_ATS_EN_MASK 0x00000400L
+#define PCIE_STRAP_F0__STRAP_F0_ATS_EN__SHIFT 0x0000000a
+#define PCIE_STRAP_F0__STRAP_F0_BAR_EN_MASK 0x00000080L
+#define PCIE_STRAP_F0__STRAP_F0_BAR_EN__SHIFT 0x00000007
+#define PCIE_STRAP_F0__STRAP_F0_DPA_EN_MASK 0x00000200L
+#define PCIE_STRAP_F0__STRAP_F0_DPA_EN__SHIFT 0x00000009
+#define PCIE_STRAP_F0__STRAP_F0_DSN_EN_MASK 0x00000010L
+#define PCIE_STRAP_F0__STRAP_F0_DSN_EN__SHIFT 0x00000004
+#define PCIE_STRAP_F0__STRAP_F0_EN_MASK 0x00000001L
+#define PCIE_STRAP_F0__STRAP_F0_EN__SHIFT 0x00000000
+#define PCIE_STRAP_F0__STRAP_F0_LEGACY_DEVICE_TYPE_EN_MASK 0x00000002L
+#define PCIE_STRAP_F0__STRAP_F0_LEGACY_DEVICE_TYPE_EN__SHIFT 0x00000001
+#define PCIE_STRAP_F0__STRAP_F0_MSI_EN_MASK 0x00000004L
+#define PCIE_STRAP_F0__STRAP_F0_MSI_EN__SHIFT 0x00000002
+#define PCIE_STRAP_F0__STRAP_F0_PAGE_REQ_EN_MASK 0x00000800L
+#define PCIE_STRAP_F0__STRAP_F0_PAGE_REQ_EN__SHIFT 0x0000000b
+#define PCIE_STRAP_F0__STRAP_F0_PASID_EN_MASK 0x00001000L
+#define PCIE_STRAP_F0__STRAP_F0_PASID_EN__SHIFT 0x0000000c
+#define PCIE_STRAP_F0__STRAP_F0_PWR_EN_MASK 0x00000100L
+#define PCIE_STRAP_F0__STRAP_F0_PWR_EN__SHIFT 0x00000008
+#define PCIE_STRAP_F0__STRAP_F0_VC_EN_MASK 0x00000008L
+#define PCIE_STRAP_F0__STRAP_F0_VC_EN__SHIFT 0x00000003
+#define PCIE_STRAP_F1__STRAP_F1_ACS_EN_MASK 0x00000040L
+#define PCIE_STRAP_F1__STRAP_F1_ACS_EN__SHIFT 0x00000006
+#define PCIE_STRAP_F1__STRAP_F1_AER_EN_MASK 0x00000020L
+#define PCIE_STRAP_F1__STRAP_F1_AER_EN__SHIFT 0x00000005
+#define PCIE_STRAP_F1__STRAP_F1_ATS_EN_MASK 0x00000400L
+#define PCIE_STRAP_F1__STRAP_F1_ATS_EN__SHIFT 0x0000000a
+#define PCIE_STRAP_F1__STRAP_F1_BAR_EN_MASK 0x00000080L
+#define PCIE_STRAP_F1__STRAP_F1_BAR_EN__SHIFT 0x00000007
+#define PCIE_STRAP_F1__STRAP_F1_DPA_EN_MASK 0x00000200L
+#define PCIE_STRAP_F1__STRAP_F1_DPA_EN__SHIFT 0x00000009
+#define PCIE_STRAP_F1__STRAP_F1_DSN_EN_MASK 0x00000010L
+#define PCIE_STRAP_F1__STRAP_F1_DSN_EN__SHIFT 0x00000004
+#define PCIE_STRAP_F1__STRAP_F1_EN_MASK 0x00000001L
+#define PCIE_STRAP_F1__STRAP_F1_EN__SHIFT 0x00000000
+#define PCIE_STRAP_F1__STRAP_F1_LEGACY_DEVICE_TYPE_EN_MASK 0x00000002L
+#define PCIE_STRAP_F1__STRAP_F1_LEGACY_DEVICE_TYPE_EN__SHIFT 0x00000001
+#define PCIE_STRAP_F1__STRAP_F1_MSI_EN_MASK 0x00000004L
+#define PCIE_STRAP_F1__STRAP_F1_MSI_EN__SHIFT 0x00000002
+#define PCIE_STRAP_F1__STRAP_F1_PAGE_REQ_EN_MASK 0x00000800L
+#define PCIE_STRAP_F1__STRAP_F1_PAGE_REQ_EN__SHIFT 0x0000000b
+#define PCIE_STRAP_F1__STRAP_F1_PASID_EN_MASK 0x00001000L
+#define PCIE_STRAP_F1__STRAP_F1_PASID_EN__SHIFT 0x0000000c
+#define PCIE_STRAP_F1__STRAP_F1_PWR_EN_MASK 0x00000100L
+#define PCIE_STRAP_F1__STRAP_F1_PWR_EN__SHIFT 0x00000008
+#define PCIE_STRAP_F1__STRAP_F1_VC_EN_MASK 0x00000008L
+#define PCIE_STRAP_F1__STRAP_F1_VC_EN__SHIFT 0x00000003
+#define PCIE_STRAP_F2__STRAP_F2_ACS_EN_MASK 0x00000040L
+#define PCIE_STRAP_F2__STRAP_F2_ACS_EN__SHIFT 0x00000006
+#define PCIE_STRAP_F2__STRAP_F2_AER_EN_MASK 0x00000020L
+#define PCIE_STRAP_F2__STRAP_F2_AER_EN__SHIFT 0x00000005
+#define PCIE_STRAP_F2__STRAP_F2_ATS_EN_MASK 0x00000400L
+#define PCIE_STRAP_F2__STRAP_F2_ATS_EN__SHIFT 0x0000000a
+#define PCIE_STRAP_F2__STRAP_F2_BAR_EN_MASK 0x00000080L
+#define PCIE_STRAP_F2__STRAP_F2_BAR_EN__SHIFT 0x00000007
+#define PCIE_STRAP_F2__STRAP_F2_DPA_EN_MASK 0x00000200L
+#define PCIE_STRAP_F2__STRAP_F2_DPA_EN__SHIFT 0x00000009
+#define PCIE_STRAP_F2__STRAP_F2_DSN_EN_MASK 0x00000010L
+#define PCIE_STRAP_F2__STRAP_F2_DSN_EN__SHIFT 0x00000004
+#define PCIE_STRAP_F2__STRAP_F2_EN_MASK 0x00000001L
+#define PCIE_STRAP_F2__STRAP_F2_EN__SHIFT 0x00000000
+#define PCIE_STRAP_F2__STRAP_F2_LEGACY_DEVICE_TYPE_EN_MASK 0x00000002L
+#define PCIE_STRAP_F2__STRAP_F2_LEGACY_DEVICE_TYPE_EN__SHIFT 0x00000001
+#define PCIE_STRAP_F2__STRAP_F2_MSI_EN_MASK 0x00000004L
+#define PCIE_STRAP_F2__STRAP_F2_MSI_EN__SHIFT 0x00000002
+#define PCIE_STRAP_F2__STRAP_F2_PAGE_REQ_EN_MASK 0x00000800L
+#define PCIE_STRAP_F2__STRAP_F2_PAGE_REQ_EN__SHIFT 0x0000000b
+#define PCIE_STRAP_F2__STRAP_F2_PASID_EN_MASK 0x00001000L
+#define PCIE_STRAP_F2__STRAP_F2_PASID_EN__SHIFT 0x0000000c
+#define PCIE_STRAP_F2__STRAP_F2_PWR_EN_MASK 0x00000100L
+#define PCIE_STRAP_F2__STRAP_F2_PWR_EN__SHIFT 0x00000008
+#define PCIE_STRAP_F2__STRAP_F2_VC_EN_MASK 0x00000008L
+#define PCIE_STRAP_F2__STRAP_F2_VC_EN__SHIFT 0x00000003
+#define PCIE_STRAP_F3__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F3__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F4__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F4__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F5__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F5__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F6__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F6__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_F7__RESERVED_MASK 0xffffffffL
+#define PCIE_STRAP_F7__RESERVED__SHIFT 0x00000000
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_DBG_I2C_EN_MASK 0x00000080L
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_DBG_I2C_EN__SHIFT 0x00000007
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_I2C_SLV_ADR_MASK 0x0000007fL
+#define PCIE_STRAP_I2C_BD__STRAP_BIF_I2C_SLV_ADR__SHIFT 0x00000000
+#define PCIE_STRAP_MISC2__STRAP_GEN2_COMPLIANCE_MASK 0x00000002L
+#define PCIE_STRAP_MISC2__STRAP_GEN2_COMPLIANCE__SHIFT 0x00000001
+#define PCIE_STRAP_MISC2__STRAP_GEN3_COMPLIANCE_MASK 0x00000008L
+#define PCIE_STRAP_MISC2__STRAP_GEN3_COMPLIANCE__SHIFT 0x00000003
+#define PCIE_STRAP_MISC2__STRAP_MSTCPL_TIMEOUT_EN_MASK 0x00000004L
+#define PCIE_STRAP_MISC2__STRAP_MSTCPL_TIMEOUT_EN__SHIFT 0x00000002
+#define PCIE_STRAP_MISC__STRAP_CLK_PM_EN_MASK 0x01000000L
+#define PCIE_STRAP_MISC__STRAP_CLK_PM_EN__SHIFT 0x00000018
+#define PCIE_STRAP_MISC__STRAP_ECN1P1_EN_MASK 0x02000000L
+#define PCIE_STRAP_MISC__STRAP_ECN1P1_EN__SHIFT 0x00000019
+#define PCIE_STRAP_MISC__STRAP_EXT_VC_COUNT_MASK 0x04000000L
+#define PCIE_STRAP_MISC__STRAP_EXT_VC_COUNT__SHIFT 0x0000001a
+#define PCIE_STRAP_MISC__STRAP_FLR_EN_MASK 0x40000000L
+#define PCIE_STRAP_MISC__STRAP_FLR_EN__SHIFT 0x0000001e
+#define PCIE_STRAP_MISC__STRAP_LINK_CONFIG_MASK 0x0000000fL
+#define PCIE_STRAP_MISC__STRAP_LINK_CONFIG__SHIFT 0x00000000
+#define PCIE_STRAP_MISC__STRAP_MAX_PASID_WIDTH_MASK 0x00001f00L
+#define PCIE_STRAP_MISC__STRAP_MAX_PASID_WIDTH__SHIFT 0x00000008
+#define PCIE_STRAP_MISC__STRAP_MST_ADR64_EN_MASK 0x20000000L
+#define PCIE_STRAP_MISC__STRAP_MST_ADR64_EN__SHIFT 0x0000001d
+#define PCIE_STRAP_MISC__STRAP_PASID_EXE_PERMISSION_SUPPORTED_MASK 0x00002000L
+#define PCIE_STRAP_MISC__STRAP_PASID_EXE_PERMISSION_SUPPORTED__SHIFT 0x0000000d
+#define PCIE_STRAP_MISC__STRAP_PASID_GLOBAL_INVALIDATE_SUPPORTED_MASK 0x00008000L
+#define PCIE_STRAP_MISC__STRAP_PASID_GLOBAL_INVALIDATE_SUPPORTED__SHIFT 0x0000000f
+#define PCIE_STRAP_MISC__STRAP_PASID_PRIV_MODE_SUPPORTED_MASK 0x00004000L
+#define PCIE_STRAP_MISC__STRAP_PASID_PRIV_MODE_SUPPORTED__SHIFT 0x0000000e
+#define PCIE_STRAP_MISC__STRAP_REVERSE_ALL_MASK 0x10000000L
+#define PCIE_STRAP_MISC__STRAP_REVERSE_ALL__SHIFT 0x0000001c
+#define PCIE_STRAP_PI__STRAP_QUICKSIM_START_MASK 0x00000001L
+#define PCIE_STRAP_PI__STRAP_QUICKSIM_START__SHIFT 0x00000000
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_MODE_MASK 0x20000000L
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_MODE__SHIFT 0x0000001d
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_PATTERN_MASK 0x10000000L
+#define PCIE_STRAP_PI__STRAP_TEST_TOGGLE_PATTERN__SHIFT 0x0000001c
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT_MASK 0x00000fffL
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT_OVERWRITE_MASK 0x00001000L
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT_OVERWRITE__SHIFT 0x0000000c
+#define PCIE_TX_ACK_LATENCY_LIMIT__TX_ACK_LATENCY_LIMIT__SHIFT 0x00000000
+#define PCIE_TX_CNTL__TX_CLEAR_EXTRA_PM_REQS_MASK 0x00400000L
+#define PCIE_TX_CNTL__TX_CLEAR_EXTRA_PM_REQS__SHIFT 0x00000016
+#define PCIE_TX_CNTL__TX_CPL_PASS_P_MASK 0x00100000L
+#define PCIE_TX_CNTL__TX_CPL_PASS_P__SHIFT 0x00000014
+#define PCIE_TX_CNTL__TX_FC_UPDATE_TIMEOUT_DIS_MASK 0x00800000L
+#define PCIE_TX_CNTL__TX_FC_UPDATE_TIMEOUT_DIS__SHIFT 0x00000017
+#define PCIE_TX_CNTL__TX_FLUSH_TLP_DIS_MASK 0x00008000L
+#define PCIE_TX_CNTL__TX_FLUSH_TLP_DIS__SHIFT 0x0000000f
+#define PCIE_TX_CNTL__TX_NP_PASS_P_MASK 0x00200000L
+#define PCIE_TX_CNTL__TX_NP_PASS_P__SHIFT 0x00000015
+#define PCIE_TX_CNTL__TX_PACK_PACKET_DIS_MASK 0x00004000L
+#define PCIE_TX_CNTL__TX_PACK_PACKET_DIS__SHIFT 0x0000000e
+#define PCIE_TX_CNTL__TX_RO_OVERRIDE_MASK 0x00003000L
+#define PCIE_TX_CNTL__TX_RO_OVERRIDE__SHIFT 0x0000000c
+#define PCIE_TX_CNTL__TX_SNR_OVERRIDE_MASK 0x00000c00L
+#define PCIE_TX_CNTL__TX_SNR_OVERRIDE__SHIFT 0x0000000a
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_ADVT_CPL__TX_CREDITS_ADVT_CPLH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_ADVT_NP__TX_CREDITS_ADVT_NPH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_ADVT_P__TX_CREDITS_ADVT_PH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC0_MASK 0x00000700L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC0__SHIFT 0x00000008
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC1_MASK 0x07000000L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_CPL_VC1__SHIFT 0x00000018
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC0_MASK 0x00000070L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC0__SHIFT 0x00000004
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC1_MASK 0x00700000L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_NP_VC1__SHIFT 0x00000014
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC0_MASK 0x00000007L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC0__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC1_MASK 0x00070000L
+#define PCIE_TX_CREDITS_FCU_THRESHOLD__TX_FCU_THRESHOLD_P_VC1__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_INIT_CPL__TX_CREDITS_INIT_CPLH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_INIT_NP__TX_CREDITS_INIT_NPH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PD_MASK 0x00000fffL
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PH_MASK 0x00ff0000L
+#define PCIE_TX_CREDITS_INIT_P__TX_CREDITS_INIT_PH__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLD_MASK 0x00100000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLD__SHIFT 0x00000014
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLH_MASK 0x00200000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_CPLH__SHIFT 0x00000015
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPD_MASK 0x00040000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPD__SHIFT 0x00000012
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPH_MASK 0x00080000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_NPH__SHIFT 0x00000013
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PD_MASK 0x00010000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PD__SHIFT 0x00000010
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PH_MASK 0x00020000L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_CUR_STATUS_PH__SHIFT 0x00000011
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLD_MASK 0x00000010L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLD__SHIFT 0x00000004
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLH_MASK 0x00000020L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_CPLH__SHIFT 0x00000005
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPD_MASK 0x00000004L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPD__SHIFT 0x00000002
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPH_MASK 0x00000008L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_NPH__SHIFT 0x00000003
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PD_MASK 0x00000001L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PD__SHIFT 0x00000000
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PH_MASK 0x00000002L
+#define PCIE_TX_CREDITS_STATUS__TX_CREDITS_ERR_PH__SHIFT 0x00000001
+#define PCIE_TX_LAST_TLP0__TX_LAST_TLP0_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP0__TX_LAST_TLP0__SHIFT 0x00000000
+#define PCIE_TX_LAST_TLP1__TX_LAST_TLP1_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP1__TX_LAST_TLP1__SHIFT 0x00000000
+#define PCIE_TX_LAST_TLP2__TX_LAST_TLP2_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP2__TX_LAST_TLP2__SHIFT 0x00000000
+#define PCIE_TX_LAST_TLP3__TX_LAST_TLP3_MASK 0xffffffffL
+#define PCIE_TX_LAST_TLP3__TX_LAST_TLP3__SHIFT 0x00000000
+#define PCIE_TX_REPLAY__TX_REPLAY_NUM_MASK 0x00000007L
+#define PCIE_TX_REPLAY__TX_REPLAY_NUM__SHIFT 0x00000000
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER_MASK 0xffff0000L
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER_OVERWRITE_MASK 0x00008000L
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER_OVERWRITE__SHIFT 0x0000000f
+#define PCIE_TX_REPLAY__TX_REPLAY_TIMER__SHIFT 0x00000010
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_BUS_MASK 0x0000ff00L
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_BUS__SHIFT 0x00000008
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_DEVICE_MASK 0x000000f8L
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_DEVICE__SHIFT 0x00000003
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_FUNCTION_MASK 0x00000007L
+#define PCIE_TX_REQUESTER_ID__TX_REQUESTER_ID_FUNCTION__SHIFT 0x00000000
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_EN_MASK 0x80000000L
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_EN__SHIFT 0x0000001f
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_MASK 0x3f000000L
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP__SHIFT 0x00000018
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_VC1_EN_MASK 0x40000000L
+#define PCIE_TX_REQUEST_NUM_CNTL__TX_NUM_OUTSTANDING_NP_VC1_EN__SHIFT 0x0000001e
+#define PCIE_TX_SEQ__TX_ACKD_SEQ_MASK 0x0fff0000L
+#define PCIE_TX_SEQ__TX_ACKD_SEQ__SHIFT 0x00000010
+#define PCIE_TX_SEQ__TX_NEXT_TRANSMIT_SEQ_MASK 0x00000fffL
+#define PCIE_TX_SEQ__TX_NEXT_TRANSMIT_SEQ__SHIFT 0x00000000
+#define PCIE_TX_VENDOR_SPECIFIC__TX_VENDOR_DATA_MASK 0x00ffffffL
+#define PCIE_TX_VENDOR_SPECIFIC__TX_VENDOR_DATA__SHIFT 0x00000000
+#define PCIE_WPR_CNTL__WPR_RESET_COR_EN_MASK 0x00000008L
+#define PCIE_WPR_CNTL__WPR_RESET_COR_EN__SHIFT 0x00000003
+#define PCIE_WPR_CNTL__WPR_RESET_HOT_RST_EN_MASK 0x00000001L
+#define PCIE_WPR_CNTL__WPR_RESET_HOT_RST_EN__SHIFT 0x00000000
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DIS_EN_MASK 0x00000004L
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DIS_EN__SHIFT 0x00000002
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DWN_EN_MASK 0x00000002L
+#define PCIE_WPR_CNTL__WPR_RESET_LNK_DWN_EN__SHIFT 0x00000001
+#define PCIE_WPR_CNTL__WPR_RESET_PHY_EN_MASK 0x00000040L
+#define PCIE_WPR_CNTL__WPR_RESET_PHY_EN__SHIFT 0x00000006
+#define PCIE_WPR_CNTL__WPR_RESET_REG_EN_MASK 0x00000010L
+#define PCIE_WPR_CNTL__WPR_RESET_REG_EN__SHIFT 0x00000004
+#define PCIE_WPR_CNTL__WPR_RESET_STY_EN_MASK 0x00000020L
+#define PCIE_WPR_CNTL__WPR_RESET_STY_EN__SHIFT 0x00000005
+#define PEER0_FB_OFFSET_HI__PEER0_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER0_FB_OFFSET_HI__PEER0_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER0_FB_OFFSET_LO__PEER0_FB_EN_MASK 0x80000000L
+#define PEER0_FB_OFFSET_LO__PEER0_FB_EN__SHIFT 0x0000001f
+#define PEER0_FB_OFFSET_LO__PEER0_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER0_FB_OFFSET_LO__PEER0_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER1_FB_OFFSET_HI__PEER1_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER1_FB_OFFSET_HI__PEER1_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER1_FB_OFFSET_LO__PEER1_FB_EN_MASK 0x80000000L
+#define PEER1_FB_OFFSET_LO__PEER1_FB_EN__SHIFT 0x0000001f
+#define PEER1_FB_OFFSET_LO__PEER1_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER1_FB_OFFSET_LO__PEER1_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER2_FB_OFFSET_HI__PEER2_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER2_FB_OFFSET_HI__PEER2_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER2_FB_OFFSET_LO__PEER2_FB_EN_MASK 0x80000000L
+#define PEER2_FB_OFFSET_LO__PEER2_FB_EN__SHIFT 0x0000001f
+#define PEER2_FB_OFFSET_LO__PEER2_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER2_FB_OFFSET_LO__PEER2_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER3_FB_OFFSET_HI__PEER3_FB_OFFSET_HI_MASK 0x000fffffL
+#define PEER3_FB_OFFSET_HI__PEER3_FB_OFFSET_HI__SHIFT 0x00000000
+#define PEER3_FB_OFFSET_LO__PEER3_FB_EN_MASK 0x80000000L
+#define PEER3_FB_OFFSET_LO__PEER3_FB_EN__SHIFT 0x0000001f
+#define PEER3_FB_OFFSET_LO__PEER3_FB_OFFSET_LO_MASK 0x000fffffL
+#define PEER3_FB_OFFSET_LO__PEER3_FB_OFFSET_LO__SHIFT 0x00000000
+#define PEER_REG_RANGE0__END_ADDR_MASK 0xffff0000L
+#define PEER_REG_RANGE0__END_ADDR__SHIFT 0x00000010
+#define PEER_REG_RANGE0__START_ADDR_MASK 0x0000ffffL
+#define PEER_REG_RANGE0__START_ADDR__SHIFT 0x00000000
+#define PEER_REG_RANGE1__END_ADDR_MASK 0xffff0000L
+#define PEER_REG_RANGE1__END_ADDR__SHIFT 0x00000010
+#define PEER_REG_RANGE1__START_ADDR_MASK 0x0000ffffL
+#define PEER_REG_RANGE1__START_ADDR__SHIFT 0x00000000
+#define SLAVE_HANG_ERROR__AUDIO_HANG_ERROR_MASK 0x00000010L
+#define SLAVE_HANG_ERROR__AUDIO_HANG_ERROR__SHIFT 0x00000004
+#define SLAVE_HANG_ERROR__CEC_HANG_ERROR_MASK 0x00000020L
+#define SLAVE_HANG_ERROR__CEC_HANG_ERROR__SHIFT 0x00000005
+#define SLAVE_HANG_ERROR__HDP_HANG_ERROR_MASK 0x00000002L
+#define SLAVE_HANG_ERROR__HDP_HANG_ERROR__SHIFT 0x00000001
+#define SLAVE_HANG_ERROR__ROM_HANG_ERROR_MASK 0x00000008L
+#define SLAVE_HANG_ERROR__ROM_HANG_ERROR__SHIFT 0x00000003
+#define SLAVE_HANG_ERROR__SRBM_HANG_ERROR_MASK 0x00000001L
+#define SLAVE_HANG_ERROR__SRBM_HANG_ERROR__SHIFT 0x00000000
+#define SLAVE_HANG_ERROR__VGA_HANG_ERROR_MASK 0x00000004L
+#define SLAVE_HANG_ERROR__VGA_HANG_ERROR__SHIFT 0x00000002
+#define SLAVE_HANG_PROTECTION_CNTL__HANG_PROTECTION_TIMER_SEL_MASK 0x0000000eL
+#define SLAVE_HANG_PROTECTION_CNTL__HANG_PROTECTION_TIMER_SEL__SHIFT 0x00000001
+#define SLAVE_REQ_CREDIT_CNTL__BIF_AZ_REQ_CREDIT_MASK 0x00100000L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_AZ_REQ_CREDIT__SHIFT 0x00000014
+#define SLAVE_REQ_CREDIT_CNTL__BIF_HDP_REQ_CREDIT_MASK 0x00007c00L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_HDP_REQ_CREDIT__SHIFT 0x0000000a
+#define SLAVE_REQ_CREDIT_CNTL__BIF_ROM_REQ_CREDIT_MASK 0x00008000L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_ROM_REQ_CREDIT__SHIFT 0x0000000f
+#define SLAVE_REQ_CREDIT_CNTL__BIF_SRBM_REQ_CREDIT_MASK 0x0000001fL
+#define SLAVE_REQ_CREDIT_CNTL__BIF_SRBM_REQ_CREDIT__SHIFT 0x00000000
+#define SLAVE_REQ_CREDIT_CNTL__BIF_VGA_REQ_CREDIT_MASK 0x000001e0L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_VGA_REQ_CREDIT__SHIFT 0x00000005
+#define SLAVE_REQ_CREDIT_CNTL__BIF_XDMA_REQ_CREDIT_MASK 0x7e000000L
+#define SLAVE_REQ_CREDIT_CNTL__BIF_XDMA_REQ_CREDIT__SHIFT 0x00000019
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_A_MASK 0x00000001L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_A__SHIFT 0x00000000
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_CNTL_EN_MASK 0x00001000L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_CNTL_EN__SHIFT 0x0000000c
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_MODE_MASK 0x00000004L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_MODE__SHIFT 0x00000002
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SCHMEN_MASK 0x00000800L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SCHMEN__SHIFT 0x0000000b
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SEL_MASK 0x00000002L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SEL__SHIFT 0x00000001
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SLEWN_MASK 0x00000200L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SLEWN__SHIFT 0x00000009
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN0_MASK 0x00000020L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN0__SHIFT 0x00000005
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN1_MASK 0x00000040L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN1__SHIFT 0x00000006
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN2_MASK 0x00000080L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN2__SHIFT 0x00000007
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN3_MASK 0x00000100L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SN3__SHIFT 0x00000008
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SPARE_MASK 0x00000018L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_SPARE__SHIFT 0x00000003
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_WAKE_MASK 0x00000400L
+#define SMBCLK_PAD_CNTL__SMBCLK_PAD_WAKE__SHIFT 0x0000000a
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_A_MASK 0x00000001L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_A__SHIFT 0x00000000
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_CNTL_EN_MASK 0x00001000L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_CNTL_EN__SHIFT 0x0000000c
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_MODE_MASK 0x00000004L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_MODE__SHIFT 0x00000002
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SCHMEN_MASK 0x00000800L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SCHMEN__SHIFT 0x0000000b
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SEL_MASK 0x00000002L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SEL__SHIFT 0x00000001
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SLEWN_MASK 0x00000200L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SLEWN__SHIFT 0x00000009
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN0_MASK 0x00000020L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN0__SHIFT 0x00000005
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN1_MASK 0x00000040L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN1__SHIFT 0x00000006
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN2_MASK 0x00000080L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN2__SHIFT 0x00000007
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN3_MASK 0x00000100L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SN3__SHIFT 0x00000008
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SPARE_MASK 0x00000018L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_SPARE__SHIFT 0x00000003
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_WAKE_MASK 0x00000400L
+#define SMBDAT_PAD_CNTL__SMBDAT_PAD_WAKE__SHIFT 0x0000000a
+#define SMBUS_BACO_DUMMY__SMBUS_BACO_DUMMY_DATA_MASK 0xffffffffL
+#define SMBUS_BACO_DUMMY__SMBUS_BACO_DUMMY_DATA__SHIFT 0x00000000
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,4457 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 DCE_6_0_D_H
+#define DCE_6_0_D_H
+
+#define ixATTR00 0x0000
+#define ixATTR01 0x0001
+#define ixATTR02 0x0002
+#define ixATTR03 0x0003
+#define ixATTR04 0x0004
+#define ixATTR05 0x0005
+#define ixATTR06 0x0006
+#define ixATTR07 0x0007
+#define ixATTR08 0x0008
+#define ixATTR09 0x0009
+#define ixATTR0A 0x000A
+#define ixATTR0B 0x000B
+#define ixATTR0C 0x000C
+#define ixATTR0D 0x000D
+#define ixATTR0E 0x000E
+#define ixATTR0F 0x000F
+#define ixATTR10 0x0010
+#define ixATTR11 0x0011
+#define ixATTR12 0x0012
+#define ixATTR13 0x0013
+#define ixATTR14 0x0014
+#define ixAUDIO_DESCRIPTOR0 0x0001
+#define ixAUDIO_DESCRIPTOR10 0x000B
+#define ixAUDIO_DESCRIPTOR1 0x0002
+#define ixAUDIO_DESCRIPTOR11 0x000C
+#define ixAUDIO_DESCRIPTOR12 0x000D
+#define ixAUDIO_DESCRIPTOR13 0x000E
+#define ixAUDIO_DESCRIPTOR2 0x0003
+#define ixAUDIO_DESCRIPTOR3 0x0004
+#define ixAUDIO_DESCRIPTOR4 0x0005
+#define ixAUDIO_DESCRIPTOR5 0x0006
+#define ixAUDIO_DESCRIPTOR6 0x0007
+#define ixAUDIO_DESCRIPTOR7 0x0008
+#define ixAUDIO_DESCRIPTOR8 0x0009
+#define ixAUDIO_DESCRIPTOR9 0x000A
+#define ixAZALIA_CUMULATIVE_LATENCY_COUNT 0x0003
+#define ixAZALIA_CUMULATIVE_REQUEST_COUNT 0x0004
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID 0x0003
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT 0x0002
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER 0x0004
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING 0x0009
+#define ixAZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE 0x0008
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x0001
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS 0x0005
+#define ixAZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES 0x0006
+#define ixAZALIA_F0_CODEC_CONVERTER_PIN_DEBUG 0x0000
+#define ixAZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL 0x0007
+#define ixAZALIA_F0_CODEC_PIN_ASSOCIATION_INFO 0x0062
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 0x0028
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10 0x0032
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1 0x0029
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11 0x0033
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12 0x0034
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13 0x0035
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2 0x002A
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3 0x002B
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4 0x002C
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5 0x002D
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6 0x002E
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7 0x002F
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8 0x0030
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9 0x0031
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER 0x0025
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL 0x0054
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE 0x0036
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2 0x0057
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE 0x0058
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 0x0056
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR 0x0038
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC 0x0037
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE 0x0023
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0 0x003A
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1 0x003B
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2 0x003C
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3 0x003D
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4 0x003E
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5 0x003F
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6 0x0040
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7 0x0041
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8 0x0042
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE 0x0022
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE 0x0055
+#define ixAZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL 0x0024
+#define ixAZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x0020
+#define ixAZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES 0x0021
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0 0x0059
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1 0x005A
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2 0x005B
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3 0x005C
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4 0x005D
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5 0x005E
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6 0x005F
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7 0x0060
+#define ixAZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8 0x0061
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID 0x2706
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT 0x2200
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER 0x270D
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2 0x270E
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3 0x273E
+#define ixAZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE 0x2770
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x2F09
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS 0x2F0B
+#define ixAZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES 0x2F0A
+#define ixAZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL 0x2724
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION 0x1770
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE 0x1705
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESET 0x17FF
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID 0x1720
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2 0x1721
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3 0x1722
+#define ixAZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4 0x1723
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE 0x1F05
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES 0x1F0F
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS 0x1F0B
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT 0x1F04
+#define ixAZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES 0x1F0A
+#define ixAZALIA_F2_CODEC_PIN_ASSOCIATION_INFO 0x3793
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR 0x3776
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA 0x3776
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA 0x3781
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX 0x3780
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION 0x3771
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO 0x3772
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_HBR 0x377C
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC 0x377B
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID 0x0000
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE 0x3777
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE 0x3785
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE 0x3778
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE 0x3786
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE 0x3779
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE 0x3787
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE 0x377A
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE 0x3788
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE 0x3789
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PORTID0 0x0003
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PORTID1 0x0004
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID 0x0001
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT 0x371C
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2 0x371D
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3 0x371E
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4 0x371F
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY 0x3702
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE 0x3709
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION 0x3770
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN 0x0002
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE 0x3708
+#define ixAZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL 0x3707
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES 0x3F09
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES 0x3F0C
+#define ixAZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH 0x3F0E
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID 0x0F02
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT 0x0F04
+#define ixAZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID 0x0F00
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0 0x378A
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1 0x378B
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2 0x378C
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3 0x378D
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4 0x378E
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5 0x378F
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6 0x3790
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7 0x3791
+#define ixAZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8 0x3792
+#define ixAZALIA_FIFO_SIZE_CONTROL 0x0000
+#define ixAZALIA_LATENCY_COUNTER_CONTROL 0x0001
+#define ixAZALIA_STREAM_DEBUG 0x0005
+#define ixAZALIA_WORSTCASE_LATENCY_COUNT 0x0002
+#define ixCRT00 0x0000
+#define ixCRT01 0x0001
+#define ixCRT02 0x0002
+#define ixCRT03 0x0003
+#define ixCRT04 0x0004
+#define ixCRT05 0x0005
+#define ixCRT06 0x0006
+#define ixCRT07 0x0007
+#define ixCRT08 0x0008
+#define ixCRT09 0x0009
+#define ixCRT0A 0x000A
+#define ixCRT0B 0x000B
+#define ixCRT0C 0x000C
+#define ixCRT0D 0x000D
+#define ixCRT0E 0x000E
+#define ixCRT0F 0x000F
+#define ixCRT10 0x0010
+#define ixCRT11 0x0011
+#define ixCRT12 0x0012
+#define ixCRT13 0x0013
+#define ixCRT14 0x0014
+#define ixCRT15 0x0015
+#define ixCRT16 0x0016
+#define ixCRT17 0x0017
+#define ixCRT18 0x0018
+#define ixCRT1E 0x001E
+#define ixCRT1F 0x001F
+#define ixCRT22 0x0022
+#define ixDCIO_DEBUG10 0x0010
+#define ixDCIO_DEBUG1 0x0001
+#define ixDCIO_DEBUG11 0x0011
+#define ixDCIO_DEBUG12 0x0012
+#define ixDCIO_DEBUG13 0x0013
+#define ixDCIO_DEBUG2 0x0002
+#define ixDCIO_DEBUG3 0x0003
+#define ixDCIO_DEBUG4 0x0004
+#define ixDCIO_DEBUG5 0x0005
+#define ixDCIO_DEBUG6 0x0006
+#define ixDCIO_DEBUG7 0x0007
+#define ixDCIO_DEBUG8 0x0008
+#define ixDCIO_DEBUG9 0x0009
+#define ixDCIO_DEBUGA 0x000A
+#define ixDCIO_DEBUGB 0x000B
+#define ixDCIO_DEBUGC 0x000C
+#define ixDCIO_DEBUGD 0x000D
+#define ixDCIO_DEBUGE 0x000E
+#define ixDCIO_DEBUGF 0x000F
+#define ixDCIO_DEBUG_ID 0x0000
+#define ixDMIF_DEBUG02_CORE0 0x0002
+#define ixDMIF_DEBUG02_CORE1 0x000A
+#define ixDP_AUX1_DEBUG_A 0x0010
+#define ixDP_AUX1_DEBUG_B 0x0011
+#define ixDP_AUX1_DEBUG_C 0x0012
+#define ixDP_AUX1_DEBUG_D 0x0013
+#define ixDP_AUX1_DEBUG_E 0x0014
+#define ixDP_AUX1_DEBUG_F 0x0015
+#define ixDP_AUX1_DEBUG_G 0x0016
+#define ixDP_AUX1_DEBUG_H 0x0017
+#define ixDP_AUX1_DEBUG_I 0x0018
+#define ixDP_AUX2_DEBUG_A 0x0020
+#define ixDP_AUX2_DEBUG_B 0x0021
+#define ixDP_AUX2_DEBUG_C 0x0022
+#define ixDP_AUX2_DEBUG_D 0x0023
+#define ixDP_AUX2_DEBUG_E 0x0024
+#define ixDP_AUX2_DEBUG_F 0x0025
+#define ixDP_AUX2_DEBUG_G 0x0026
+#define ixDP_AUX2_DEBUG_H 0x0027
+#define ixDP_AUX2_DEBUG_I 0x0028
+#define ixDP_AUX3_DEBUG_A 0x0030
+#define ixDP_AUX3_DEBUG_B 0x0031
+#define ixDP_AUX3_DEBUG_C 0x0032
+#define ixDP_AUX3_DEBUG_D 0x0033
+#define ixDP_AUX3_DEBUG_E 0x0034
+#define ixDP_AUX3_DEBUG_F 0x0035
+#define ixDP_AUX3_DEBUG_G 0x0036
+#define ixDP_AUX3_DEBUG_H 0x0037
+#define ixDP_AUX3_DEBUG_I 0x0038
+#define ixDP_AUX4_DEBUG_A 0x0040
+#define ixDP_AUX4_DEBUG_B 0x0041
+#define ixDP_AUX4_DEBUG_C 0x0042
+#define ixDP_AUX4_DEBUG_D 0x0043
+#define ixDP_AUX4_DEBUG_E 0x0044
+#define ixDP_AUX4_DEBUG_F 0x0045
+#define ixDP_AUX4_DEBUG_G 0x0046
+#define ixDP_AUX4_DEBUG_H 0x0047
+#define ixDP_AUX4_DEBUG_I 0x0048
+#define ixDP_AUX5_DEBUG_A 0x0070
+#define ixDP_AUX5_DEBUG_B 0x0071
+#define ixDP_AUX5_DEBUG_C 0x0072
+#define ixDP_AUX5_DEBUG_D 0x0073
+#define ixDP_AUX5_DEBUG_E 0x0074
+#define ixDP_AUX5_DEBUG_F 0x0075
+#define ixDP_AUX5_DEBUG_G 0x0076
+#define ixDP_AUX5_DEBUG_H 0x0077
+#define ixDP_AUX5_DEBUG_I 0x0078
+#define ixDP_AUX6_DEBUG_A 0x0080
+#define ixDP_AUX6_DEBUG_B 0x0081
+#define ixDP_AUX6_DEBUG_C 0x0082
+#define ixDP_AUX6_DEBUG_D 0x0083
+#define ixDP_AUX6_DEBUG_E 0x0084
+#define ixDP_AUX6_DEBUG_F 0x0085
+#define ixDP_AUX6_DEBUG_G 0x0086
+#define ixDP_AUX6_DEBUG_H 0x0087
+#define ixDP_AUX6_DEBUG_I 0x0088
+#define ixFMT_DEBUG0 0x0001
+#define ixFMT_DEBUG1 0x0002
+#define ixFMT_DEBUG2 0x0003
+#define ixFMT_DEBUG_ID 0x0000
+#define ixGRA00 0x0000
+#define ixGRA01 0x0001
+#define ixGRA02 0x0002
+#define ixGRA03 0x0003
+#define ixGRA04 0x0004
+#define ixGRA05 0x0005
+#define ixGRA06 0x0006
+#define ixGRA07 0x0007
+#define ixGRA08 0x0008
+#define ixIDDCCIF02_DBG_DCCIF_C 0x0009
+#define ixIDDCCIF04_DBG_DCCIF_E 0x000B
+#define ixIDDCCIF05_DBG_DCCIF_F 0x000C
+#define ixMVP_DEBUG_12 0x000C
+#define ixMVP_DEBUG_13 0x000D
+#define ixMVP_DEBUG_14 0x000E
+#define ixMVP_DEBUG_15 0x000F
+#define ixMVP_DEBUG_16 0x0010
+#define ixMVP_DEBUG_17 0x0011
+#define ixSEQ00 0x0000
+#define ixSEQ01 0x0001
+#define ixSEQ02 0x0002
+#define ixSEQ03 0x0003
+#define ixSEQ04 0x0004
+#define ixSINK_DESCRIPTION0 0x0005
+#define ixSINK_DESCRIPTION10 0x000F
+#define ixSINK_DESCRIPTION1 0x0006
+#define ixSINK_DESCRIPTION11 0x0010
+#define ixSINK_DESCRIPTION12 0x0011
+#define ixSINK_DESCRIPTION13 0x0012
+#define ixSINK_DESCRIPTION14 0x0013
+#define ixSINK_DESCRIPTION15 0x0014
+#define ixSINK_DESCRIPTION16 0x0015
+#define ixSINK_DESCRIPTION17 0x0016
+#define ixSINK_DESCRIPTION2 0x0007
+#define ixSINK_DESCRIPTION3 0x0008
+#define ixSINK_DESCRIPTION4 0x0009
+#define ixSINK_DESCRIPTION5 0x000A
+#define ixSINK_DESCRIPTION6 0x000B
+#define ixSINK_DESCRIPTION7 0x000C
+#define ixSINK_DESCRIPTION8 0x000D
+#define ixSINK_DESCRIPTION9 0x000E
+#define ixVGADCC_DBG_DCCIF_C 0x007E
+#define mmABM_TEST_DEBUG_DATA 0x169F
+#define mmABM_TEST_DEBUG_INDEX 0x169E
+#define mmAFMT_60958_0 0x1C41
+#define mmAFMT_60958_1 0x1C42
+#define mmAFMT_60958_2 0x1C48
+#define mmAFMT_AUDIO_CRC_CONTROL 0x1C43
+#define mmAFMT_AUDIO_CRC_RESULT 0x1C49
+#define mmAFMT_AUDIO_DBG_DTO_CNTL 0x1C52
+#define mmAFMT_AUDIO_INFO0 0x1C3F
+#define mmAFMT_AUDIO_INFO1 0x1C40
+#define mmAFMT_AUDIO_PACKET_CONTROL 0x1C4B
+#define mmAFMT_AUDIO_PACKET_CONTROL2 0x1C17
+#define mmAFMT_AUDIO_SRC_CONTROL 0x1C4F
+#define mmAFMT_AVI_INFO0 0x1C21
+#define mmAFMT_AVI_INFO1 0x1C22
+#define mmAFMT_AVI_INFO2 0x1C23
+#define mmAFMT_AVI_INFO3 0x1C24
+#define mmAFMT_GENERIC_0 0x1C28
+#define mmAFMT_GENERIC_1 0x1C29
+#define mmAFMT_GENERIC_2 0x1C2A
+#define mmAFMT_GENERIC_3 0x1C2B
+#define mmAFMT_GENERIC_4 0x1C2C
+#define mmAFMT_GENERIC_5 0x1C2D
+#define mmAFMT_GENERIC_6 0x1C2E
+#define mmAFMT_GENERIC_7 0x1C2F
+#define mmAFMT_GENERIC_HDR 0x1C27
+#define mmAFMT_INFOFRAME_CONTROL0 0x1C4D
+#define mmAFMT_INTERRUPT_STATUS 0x1C14
+#define mmAFMT_ISRC1_0 0x1C18
+#define mmAFMT_ISRC1_1 0x1C19
+#define mmAFMT_ISRC1_2 0x1C1A
+#define mmAFMT_ISRC1_3 0x1C1B
+#define mmAFMT_ISRC1_4 0x1C1C
+#define mmAFMT_ISRC2_0 0x1C1D
+#define mmAFMT_ISRC2_1 0x1C1E
+#define mmAFMT_ISRC2_2 0x1C1F
+#define mmAFMT_ISRC2_3 0x1C20
+#define mmAFMT_MPEG_INFO0 0x1C25
+#define mmAFMT_MPEG_INFO1 0x1C26
+#define mmAFMT_RAMP_CONTROL0 0x1C44
+#define mmAFMT_RAMP_CONTROL1 0x1C45
+#define mmAFMT_RAMP_CONTROL2 0x1C46
+#define mmAFMT_RAMP_CONTROL3 0x1C47
+#define mmAFMT_STATUS 0x1C4A
+#define mmAFMT_VBI_PACKET_CONTROL 0x1C4C
+#define mmATTRDR 0x00F0
+#define mmATTRDW 0x00F0
+#define mmATTRX 0x00F0
+#define mmAUX_ARB_CONTROL 0x1882
+#define mmAUX_CONTROL 0x1880
+#define mmAUX_DPHY_RX_CONTROL0 0x188A
+#define mmAUX_DPHY_RX_CONTROL1 0x188B
+#define mmAUX_DPHY_RX_STATUS 0x188D
+#define mmAUX_DPHY_TX_CONTROL 0x1889
+#define mmAUX_DPHY_TX_REF_CONTROL 0x1888
+#define mmAUX_DPHY_TX_STATUS 0x188C
+#define mmAUX_GTC_SYNC_CONTROL 0x188E
+#define mmAUX_GTC_SYNC_DATA 0x1890
+#define mmAUX_INTERRUPT_CONTROL 0x1883
+#define mmAUX_LS_DATA 0x1887
+#define mmAUX_LS_STATUS 0x1885
+#define mmAUXN_IMPCAL 0x190C
+#define mmAUXP_IMPCAL 0x190B
+#define mmAUX_SW_CONTROL 0x1881
+#define mmAUX_SW_DATA 0x1886
+#define mmAUX_SW_STATUS 0x1884
+#define mmAZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER 0x17C9
+#define mmAZALIA_AUDIO_DTO 0x17BA
+#define mmAZALIA_AUDIO_DTO_CONTROL 0x17BB
+#define mmAZALIA_BDL_DMA_CONTROL 0x17BF
+#define mmAZALIA_CONTROLLER_DEBUG 0x17CF
+#define mmAZALIA_CORB_DMA_CONTROL 0x17C1
+#define mmAZALIA_CYCLIC_BUFFER_SYNC 0x17CA
+#define mmAZALIA_DATA_DMA_CONTROL 0x17BE
+#define mmAZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL 0x17D5
+#define mmAZALIA_F0_CODEC_DEBUG 0x17DF
+#define mmAZALIA_F0_CODEC_ENDPOINT_DATA 0x1781
+#define mmAZALIA_F0_CODEC_ENDPOINT_INDEX 0x1780
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION 0x17DE
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE 0x17DB
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESET 0x17DC
+#define mmAZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID 0x17DD
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE 0x17D7
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES 0x17DA
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS 0x17D9
+#define mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES 0x17D8
+#define mmAZALIA_F0_CODEC_RESYNC_FIFO_CONTROL 0x17D6
+#define mmAZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID 0x17D3
+#define mmAZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID 0x17D2
+#define mmAZALIA_GLOBAL_CAPABILITIES 0x17CB
+#define mmAZALIA_OUTPUT_PAYLOAD_CAPABILITY 0x17CC
+#define mmAZALIA_OUTPUT_STREAM_ARBITER_CONTROL 0x17CD
+#define mmAZALIA_RIRB_AND_DP_CONTROL 0x17C0
+#define mmAZALIA_SCLK_CONTROL 0x17BC
+#define mmAZALIA_STREAM_DATA 0x17E9
+#define mmAZALIA_STREAM_INDEX 0x17E8
+#define mmAZALIA_UNDERFLOW_FILLER_SAMPLE 0x17BD
+#define mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1781
+#define mmAZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1780
+#define mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1787
+#define mmAZF0ENDPOINT1_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1786
+#define mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_DATA 0x178D
+#define mmAZF0ENDPOINT2_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x178C
+#define mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1793
+#define mmAZF0ENDPOINT3_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1792
+#define mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_DATA 0x1799
+#define mmAZF0ENDPOINT4_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x1798
+#define mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_DATA 0x179F
+#define mmAZF0ENDPOINT5_AZALIA_F0_CODEC_ENDPOINT_INDEX 0x179E
+#define mmAZF0STREAM0_AZALIA_STREAM_DATA 0x17E9
+#define mmAZF0STREAM0_AZALIA_STREAM_INDEX 0x17E8
+#define mmAZF0STREAM1_AZALIA_STREAM_DATA 0x17ED
+#define mmAZF0STREAM1_AZALIA_STREAM_INDEX 0x17EC
+#define mmAZF0STREAM2_AZALIA_STREAM_DATA 0x17F1
+#define mmAZF0STREAM2_AZALIA_STREAM_INDEX 0x17F0
+#define mmAZF0STREAM3_AZALIA_STREAM_DATA 0x17F5
+#define mmAZF0STREAM3_AZALIA_STREAM_INDEX 0x17F4
+#define mmAZF0STREAM4_AZALIA_STREAM_DATA 0x17F9
+#define mmAZF0STREAM4_AZALIA_STREAM_INDEX 0x17F8
+#define mmAZF0STREAM5_AZALIA_STREAM_DATA 0x17FD
+#define mmAZF0STREAM5_AZALIA_STREAM_INDEX 0x17FC
+#define mmAZ_TEST_DEBUG_DATA 0x17D1
+#define mmAZ_TEST_DEBUG_INDEX 0x17D0
+#define mmBL1_PWM_ABM_CNTL 0x162E
+#define mmBL1_PWM_AMBIENT_LIGHT_LEVEL 0x1628
+#define mmBL1_PWM_BL_UPDATE_SAMPLE_RATE 0x162F
+#define mmBL1_PWM_CURRENT_ABM_LEVEL 0x162B
+#define mmBL1_PWM_FINAL_DUTY_CYCLE 0x162C
+#define mmBL1_PWM_GRP2_REG_LOCK 0x1630
+#define mmBL1_PWM_MINIMUM_DUTY_CYCLE 0x162D
+#define mmBL1_PWM_TARGET_ABM_LEVEL 0x162A
+#define mmBL1_PWM_USER_LEVEL 0x1629
+#define mmBL_PWM_CNTL 0x191E
+#define mmBL_PWM_CNTL2 0x191F
+#define mmBL_PWM_GRP1_REG_LOCK 0x1921
+#define mmBL_PWM_PERIOD_CNTL 0x1920
+#define mmBPHYC_DAC_AUTO_CALIB_CONTROL 0x19FE
+#define mmBPHYC_DAC_MACRO_CNTL 0x19FD
+#define mmCC_DC_PIPE_DIS 0x177F
+#define mmCC_RCU_DC_AUDIO_PORT_CONNECTIVITY 0x17D4
+#define mmCOMM_MATRIXA_TRANS_C11_C12 0x1A43
+#define mmCOMM_MATRIXA_TRANS_C13_C14 0x1A44
+#define mmCOMM_MATRIXA_TRANS_C21_C22 0x1A45
+#define mmCOMM_MATRIXA_TRANS_C23_C24 0x1A46
+#define mmCOMM_MATRIXA_TRANS_C31_C32 0x1A47
+#define mmCOMM_MATRIXA_TRANS_C33_C34 0x1A48
+#define mmCOMM_MATRIXB_TRANS_C11_C12 0x1A49
+#define mmCOMM_MATRIXB_TRANS_C13_C14 0x1A4A
+#define mmCOMM_MATRIXB_TRANS_C21_C22 0x1A4B
+#define mmCOMM_MATRIXB_TRANS_C23_C24 0x1A4C
+#define mmCOMM_MATRIXB_TRANS_C31_C32 0x1A4D
+#define mmCOMM_MATRIXB_TRANS_C33_C34 0x1A4E
+#define mmCRTC0_CRTC_3D_STRUCTURE_CONTROL 0x1B78
+#define mmCRTC0_CRTC_ALLOW_STOP_OFF_V_CNT 0x1BC3
+#define mmCRTC0_CRTC_BLACK_COLOR 0x1BA2
+#define mmCRTC0_CRTC_BLANK_CONTROL 0x1B9D
+#define mmCRTC0_CRTC_BLANK_DATA_COLOR 0x1BA1
+#define mmCRTC0_CRTC_CONTROL 0x1B9C
+#define mmCRTC0_CRTC_COUNT_CONTROL 0x1BA9
+#define mmCRTC0_CRTC_COUNT_RESET 0x1BAA
+#define mmCRTC0_CRTC_DCFE_CLOCK_CONTROL 0x1B7C
+#define mmCRTC0_CRTC_DOUBLE_BUFFER_CONTROL 0x1BB6
+#define mmCRTC0_CRTC_DTMTEST_CNTL 0x1B92
+#define mmCRTC0_CRTC_DTMTEST_STATUS_POSITION 0x1B93
+#define mmCRTC0_CRTC_FLOW_CONTROL 0x1B99
+#define mmCRTC0_CRTC_FORCE_COUNT_NOW_CNTL 0x1B98
+#define mmCRTC0_CRTC_GSL_CONTROL 0x1B7B
+#define mmCRTC0_CRTC_GSL_VSYNC_GAP 0x1B79
+#define mmCRTC0_CRTC_GSL_WINDOW 0x1B7A
+#define mmCRTC0_CRTC_H_BLANK_EARLY_NUM 0x1B7D
+#define mmCRTC0_CRTC_H_BLANK_START_END 0x1B81
+#define mmCRTC0_CRTC_H_SYNC_A 0x1B82
+#define mmCRTC0_CRTC_H_SYNC_A_CNTL 0x1B83
+#define mmCRTC0_CRTC_H_SYNC_B 0x1B84
+#define mmCRTC0_CRTC_H_SYNC_B_CNTL 0x1B85
+#define mmCRTC0_CRTC_H_TOTAL 0x1B80
+#define mmCRTC0_CRTC_INTERLACE_CONTROL 0x1B9E
+#define mmCRTC0_CRTC_INTERLACE_STATUS 0x1B9F
+#define mmCRTC0_CRTC_INTERRUPT_CONTROL 0x1BB4
+#define mmCRTC0_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x1BAB
+#define mmCRTC0_CRTC_MASTER_EN 0x1BC2
+#define mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT 0x1BBF
+#define mmCRTC0_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x1BC0
+#define mmCRTC0_CRTC_MVP_STATUS 0x1BC1
+#define mmCRTC0_CRTC_NOM_VERT_POSITION 0x1BA5
+#define mmCRTC0_CRTC_OVERSCAN_COLOR 0x1BA0
+#define mmCRTC0_CRTC_SNAPSHOT_CONTROL 0x1BB0
+#define mmCRTC0_CRTC_SNAPSHOT_FRAME 0x1BB2
+#define mmCRTC0_CRTC_SNAPSHOT_POSITION 0x1BB1
+#define mmCRTC0_CRTC_SNAPSHOT_STATUS 0x1BAF
+#define mmCRTC0_CRTC_START_LINE_CONTROL 0x1BB3
+#define mmCRTC0_CRTC_STATUS 0x1BA3
+#define mmCRTC0_CRTC_STATUS_FRAME_COUNT 0x1BA6
+#define mmCRTC0_CRTC_STATUS_HV_COUNT 0x1BA8
+#define mmCRTC0_CRTC_STATUS_POSITION 0x1BA4
+#define mmCRTC0_CRTC_STATUS_VF_COUNT 0x1BA7
+#define mmCRTC0_CRTC_STEREO_CONTROL 0x1BAE
+#define mmCRTC0_CRTC_STEREO_FORCE_NEXT_EYE 0x1B9B
+#define mmCRTC0_CRTC_STEREO_STATUS 0x1BAD
+#define mmCRTC0_CRTC_TEST_DEBUG_DATA 0x1BC7
+#define mmCRTC0_CRTC_TEST_DEBUG_INDEX 0x1BC6
+#define mmCRTC0_CRTC_TEST_PATTERN_COLOR 0x1BBC
+#define mmCRTC0_CRTC_TEST_PATTERN_CONTROL 0x1BBA
+#define mmCRTC0_CRTC_TEST_PATTERN_PARAMETERS 0x1BBB
+#define mmCRTC0_CRTC_TRIGA_CNTL 0x1B94
+#define mmCRTC0_CRTC_TRIGA_MANUAL_TRIG 0x1B95
+#define mmCRTC0_CRTC_TRIGB_CNTL 0x1B96
+#define mmCRTC0_CRTC_TRIGB_MANUAL_TRIG 0x1B97
+#define mmCRTC0_CRTC_UPDATE_LOCK 0x1BB5
+#define mmCRTC0_CRTC_VBI_END 0x1B86
+#define mmCRTC0_CRTC_V_BLANK_START_END 0x1B8D
+#define mmCRTC0_CRTC_VERT_SYNC_CONTROL 0x1BAC
+#define mmCRTC0_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x1BB7
+#define mmCRTC0_CRTC_V_SYNC_A 0x1B8E
+#define mmCRTC0_CRTC_V_SYNC_A_CNTL 0x1B8F
+#define mmCRTC0_CRTC_V_SYNC_B 0x1B90
+#define mmCRTC0_CRTC_V_SYNC_B_CNTL 0x1B91
+#define mmCRTC0_CRTC_VSYNC_NOM_INT_STATUS 0x1B8C
+#define mmCRTC0_CRTC_V_TOTAL 0x1B87
+#define mmCRTC0_CRTC_V_TOTAL_CONTROL 0x1B8A
+#define mmCRTC0_CRTC_V_TOTAL_INT_STATUS 0x1B8B
+#define mmCRTC0_CRTC_V_TOTAL_MAX 0x1B89
+#define mmCRTC0_CRTC_V_TOTAL_MIN 0x1B88
+#define mmCRTC0_CRTC_V_UPDATE_INT_STATUS 0x1BC4
+#define mmCRTC0_DCFE_DBG_SEL 0x1B7E
+#define mmCRTC0_DCFE_MEM_LIGHT_SLEEP_CNTL 0x1B7F
+#define mmCRTC0_MASTER_UPDATE_LOCK 0x1BBD
+#define mmCRTC0_MASTER_UPDATE_MODE 0x1BBE
+#define mmCRTC0_PIXEL_RATE_CNTL 0x0140
+#define mmCRTC1_CRTC_3D_STRUCTURE_CONTROL 0x1E78
+#define mmCRTC1_CRTC_ALLOW_STOP_OFF_V_CNT 0x1EC3
+#define mmCRTC1_CRTC_BLACK_COLOR 0x1EA2
+#define mmCRTC1_CRTC_BLANK_CONTROL 0x1E9D
+#define mmCRTC1_CRTC_BLANK_DATA_COLOR 0x1EA1
+#define mmCRTC1_CRTC_CONTROL 0x1E9C
+#define mmCRTC1_CRTC_COUNT_CONTROL 0x1EA9
+#define mmCRTC1_CRTC_COUNT_RESET 0x1EAA
+#define mmCRTC1_CRTC_DCFE_CLOCK_CONTROL 0x1E7C
+#define mmCRTC1_CRTC_DOUBLE_BUFFER_CONTROL 0x1EB6
+#define mmCRTC1_CRTC_DTMTEST_CNTL 0x1E92
+#define mmCRTC1_CRTC_DTMTEST_STATUS_POSITION 0x1E93
+#define mmCRTC1_CRTC_FLOW_CONTROL 0x1E99
+#define mmCRTC1_CRTC_FORCE_COUNT_NOW_CNTL 0x1E98
+#define mmCRTC1_CRTC_GSL_CONTROL 0x1E7B
+#define mmCRTC1_CRTC_GSL_VSYNC_GAP 0x1E79
+#define mmCRTC1_CRTC_GSL_WINDOW 0x1E7A
+#define mmCRTC1_CRTC_H_BLANK_EARLY_NUM 0x1E7D
+#define mmCRTC1_CRTC_H_BLANK_START_END 0x1E81
+#define mmCRTC1_CRTC_H_SYNC_A 0x1E82
+#define mmCRTC1_CRTC_H_SYNC_A_CNTL 0x1E83
+#define mmCRTC1_CRTC_H_SYNC_B 0x1E84
+#define mmCRTC1_CRTC_H_SYNC_B_CNTL 0x1E85
+#define mmCRTC1_CRTC_H_TOTAL 0x1E80
+#define mmCRTC1_CRTC_INTERLACE_CONTROL 0x1E9E
+#define mmCRTC1_CRTC_INTERLACE_STATUS 0x1E9F
+#define mmCRTC1_CRTC_INTERRUPT_CONTROL 0x1EB4
+#define mmCRTC1_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x1EAB
+#define mmCRTC1_CRTC_MASTER_EN 0x1EC2
+#define mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT 0x1EBF
+#define mmCRTC1_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x1EC0
+#define mmCRTC1_CRTC_MVP_STATUS 0x1EC1
+#define mmCRTC1_CRTC_NOM_VERT_POSITION 0x1EA5
+#define mmCRTC1_CRTC_OVERSCAN_COLOR 0x1EA0
+#define mmCRTC1_CRTC_SNAPSHOT_CONTROL 0x1EB0
+#define mmCRTC1_CRTC_SNAPSHOT_FRAME 0x1EB2
+#define mmCRTC1_CRTC_SNAPSHOT_POSITION 0x1EB1
+#define mmCRTC1_CRTC_SNAPSHOT_STATUS 0x1EAF
+#define mmCRTC1_CRTC_START_LINE_CONTROL 0x1EB3
+#define mmCRTC1_CRTC_STATUS 0x1EA3
+#define mmCRTC1_CRTC_STATUS_FRAME_COUNT 0x1EA6
+#define mmCRTC1_CRTC_STATUS_HV_COUNT 0x1EA8
+#define mmCRTC1_CRTC_STATUS_POSITION 0x1EA4
+#define mmCRTC1_CRTC_STATUS_VF_COUNT 0x1EA7
+#define mmCRTC1_CRTC_STEREO_CONTROL 0x1EAE
+#define mmCRTC1_CRTC_STEREO_FORCE_NEXT_EYE 0x1E9B
+#define mmCRTC1_CRTC_STEREO_STATUS 0x1EAD
+#define mmCRTC1_CRTC_TEST_DEBUG_DATA 0x1EC7
+#define mmCRTC1_CRTC_TEST_DEBUG_INDEX 0x1EC6
+#define mmCRTC1_CRTC_TEST_PATTERN_COLOR 0x1EBC
+#define mmCRTC1_CRTC_TEST_PATTERN_CONTROL 0x1EBA
+#define mmCRTC1_CRTC_TEST_PATTERN_PARAMETERS 0x1EBB
+#define mmCRTC1_CRTC_TRIGA_CNTL 0x1E94
+#define mmCRTC1_CRTC_TRIGA_MANUAL_TRIG 0x1E95
+#define mmCRTC1_CRTC_TRIGB_CNTL 0x1E96
+#define mmCRTC1_CRTC_TRIGB_MANUAL_TRIG 0x1E97
+#define mmCRTC1_CRTC_UPDATE_LOCK 0x1EB5
+#define mmCRTC1_CRTC_VBI_END 0x1E86
+#define mmCRTC1_CRTC_V_BLANK_START_END 0x1E8D
+#define mmCRTC1_CRTC_VERT_SYNC_CONTROL 0x1EAC
+#define mmCRTC1_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x1EB7
+#define mmCRTC1_CRTC_V_SYNC_A 0x1E8E
+#define mmCRTC1_CRTC_V_SYNC_A_CNTL 0x1E8F
+#define mmCRTC1_CRTC_V_SYNC_B 0x1E90
+#define mmCRTC1_CRTC_V_SYNC_B_CNTL 0x1E91
+#define mmCRTC1_CRTC_VSYNC_NOM_INT_STATUS 0x1E8C
+#define mmCRTC1_CRTC_V_TOTAL 0x1E87
+#define mmCRTC1_CRTC_V_TOTAL_CONTROL 0x1E8A
+#define mmCRTC1_CRTC_V_TOTAL_INT_STATUS 0x1E8B
+#define mmCRTC1_CRTC_V_TOTAL_MAX 0x1E89
+#define mmCRTC1_CRTC_V_TOTAL_MIN 0x1E88
+#define mmCRTC1_CRTC_V_UPDATE_INT_STATUS 0x1EC4
+#define mmCRTC1_DCFE_DBG_SEL 0x1E7E
+#define mmCRTC1_DCFE_MEM_LIGHT_SLEEP_CNTL 0x1E7F
+#define mmCRTC1_MASTER_UPDATE_LOCK 0x1EBD
+#define mmCRTC1_MASTER_UPDATE_MODE 0x1EBE
+#define mmCRTC1_PIXEL_RATE_CNTL 0x0144
+#define mmCRTC2_CRTC_3D_STRUCTURE_CONTROL 0x4178
+#define mmCRTC2_CRTC_ALLOW_STOP_OFF_V_CNT 0x41C3
+#define mmCRTC2_CRTC_BLACK_COLOR 0x41A2
+#define mmCRTC2_CRTC_BLANK_CONTROL 0x419D
+#define mmCRTC2_CRTC_BLANK_DATA_COLOR 0x41A1
+#define mmCRTC2_CRTC_CONTROL 0x419C
+#define mmCRTC2_CRTC_COUNT_CONTROL 0x41A9
+#define mmCRTC2_CRTC_COUNT_RESET 0x41AA
+#define mmCRTC2_CRTC_DCFE_CLOCK_CONTROL 0x417C
+#define mmCRTC2_CRTC_DOUBLE_BUFFER_CONTROL 0x41B6
+#define mmCRTC2_CRTC_DTMTEST_CNTL 0x4192
+#define mmCRTC2_CRTC_DTMTEST_STATUS_POSITION 0x4193
+#define mmCRTC2_CRTC_FLOW_CONTROL 0x4199
+#define mmCRTC2_CRTC_FORCE_COUNT_NOW_CNTL 0x4198
+#define mmCRTC2_CRTC_GSL_CONTROL 0x417B
+#define mmCRTC2_CRTC_GSL_VSYNC_GAP 0x4179
+#define mmCRTC2_CRTC_GSL_WINDOW 0x417A
+#define mmCRTC2_CRTC_H_BLANK_EARLY_NUM 0x417D
+#define mmCRTC2_CRTC_H_BLANK_START_END 0x4181
+#define mmCRTC2_CRTC_H_SYNC_A 0x4182
+#define mmCRTC2_CRTC_H_SYNC_A_CNTL 0x4183
+#define mmCRTC2_CRTC_H_SYNC_B 0x4184
+#define mmCRTC2_CRTC_H_SYNC_B_CNTL 0x4185
+#define mmCRTC2_CRTC_H_TOTAL 0x4180
+#define mmCRTC2_CRTC_INTERLACE_CONTROL 0x419E
+#define mmCRTC2_CRTC_INTERLACE_STATUS 0x419F
+#define mmCRTC2_CRTC_INTERRUPT_CONTROL 0x41B4
+#define mmCRTC2_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x41AB
+#define mmCRTC2_CRTC_MASTER_EN 0x41C2
+#define mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT 0x41BF
+#define mmCRTC2_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x41C0
+#define mmCRTC2_CRTC_MVP_STATUS 0x41C1
+#define mmCRTC2_CRTC_NOM_VERT_POSITION 0x41A5
+#define mmCRTC2_CRTC_OVERSCAN_COLOR 0x41A0
+#define mmCRTC2_CRTC_SNAPSHOT_CONTROL 0x41B0
+#define mmCRTC2_CRTC_SNAPSHOT_FRAME 0x41B2
+#define mmCRTC2_CRTC_SNAPSHOT_POSITION 0x41B1
+#define mmCRTC2_CRTC_SNAPSHOT_STATUS 0x41AF
+#define mmCRTC2_CRTC_START_LINE_CONTROL 0x41B3
+#define mmCRTC2_CRTC_STATUS 0x41A3
+#define mmCRTC2_CRTC_STATUS_FRAME_COUNT 0x41A6
+#define mmCRTC2_CRTC_STATUS_HV_COUNT 0x41A8
+#define mmCRTC2_CRTC_STATUS_POSITION 0x41A4
+#define mmCRTC2_CRTC_STATUS_VF_COUNT 0x41A7
+#define mmCRTC2_CRTC_STEREO_CONTROL 0x41AE
+#define mmCRTC2_CRTC_STEREO_FORCE_NEXT_EYE 0x419B
+#define mmCRTC2_CRTC_STEREO_STATUS 0x41AD
+#define mmCRTC2_CRTC_TEST_DEBUG_DATA 0x41C7
+#define mmCRTC2_CRTC_TEST_DEBUG_INDEX 0x41C6
+#define mmCRTC2_CRTC_TEST_PATTERN_COLOR 0x41BC
+#define mmCRTC2_CRTC_TEST_PATTERN_CONTROL 0x41BA
+#define mmCRTC2_CRTC_TEST_PATTERN_PARAMETERS 0x41BB
+#define mmCRTC2_CRTC_TRIGA_CNTL 0x4194
+#define mmCRTC2_CRTC_TRIGA_MANUAL_TRIG 0x4195
+#define mmCRTC2_CRTC_TRIGB_CNTL 0x4196
+#define mmCRTC2_CRTC_TRIGB_MANUAL_TRIG 0x4197
+#define mmCRTC2_CRTC_UPDATE_LOCK 0x41B5
+#define mmCRTC2_CRTC_VBI_END 0x4186
+#define mmCRTC2_CRTC_V_BLANK_START_END 0x418D
+#define mmCRTC2_CRTC_VERT_SYNC_CONTROL 0x41AC
+#define mmCRTC2_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x41B7
+#define mmCRTC2_CRTC_V_SYNC_A 0x418E
+#define mmCRTC2_CRTC_V_SYNC_A_CNTL 0x418F
+#define mmCRTC2_CRTC_V_SYNC_B 0x4190
+#define mmCRTC2_CRTC_V_SYNC_B_CNTL 0x4191
+#define mmCRTC2_CRTC_VSYNC_NOM_INT_STATUS 0x418C
+#define mmCRTC2_CRTC_V_TOTAL 0x4187
+#define mmCRTC2_CRTC_V_TOTAL_CONTROL 0x418A
+#define mmCRTC2_CRTC_V_TOTAL_INT_STATUS 0x418B
+#define mmCRTC2_CRTC_V_TOTAL_MAX 0x4189
+#define mmCRTC2_CRTC_V_TOTAL_MIN 0x4188
+#define mmCRTC2_CRTC_V_UPDATE_INT_STATUS 0x41C4
+#define mmCRTC2_DCFE_DBG_SEL 0x417E
+#define mmCRTC2_DCFE_MEM_LIGHT_SLEEP_CNTL 0x417F
+#define mmCRTC2_MASTER_UPDATE_LOCK 0x41BD
+#define mmCRTC2_MASTER_UPDATE_MODE 0x41BE
+#define mmCRTC2_PIXEL_RATE_CNTL 0x0148
+#define mmCRTC3_CRTC_3D_STRUCTURE_CONTROL 0x4478
+#define mmCRTC3_CRTC_ALLOW_STOP_OFF_V_CNT 0x44C3
+#define mmCRTC3_CRTC_BLACK_COLOR 0x44A2
+#define mmCRTC3_CRTC_BLANK_CONTROL 0x449D
+#define mmCRTC3_CRTC_BLANK_DATA_COLOR 0x44A1
+#define mmCRTC3_CRTC_CONTROL 0x449C
+#define mmCRTC3_CRTC_COUNT_CONTROL 0x44A9
+#define mmCRTC3_CRTC_COUNT_RESET 0x44AA
+#define mmCRTC3_CRTC_DCFE_CLOCK_CONTROL 0x447C
+#define mmCRTC3_CRTC_DOUBLE_BUFFER_CONTROL 0x44B6
+#define mmCRTC3_CRTC_DTMTEST_CNTL 0x4492
+#define mmCRTC3_CRTC_DTMTEST_STATUS_POSITION 0x4493
+#define mmCRTC3_CRTC_FLOW_CONTROL 0x4499
+#define mmCRTC3_CRTC_FORCE_COUNT_NOW_CNTL 0x4498
+#define mmCRTC3_CRTC_GSL_CONTROL 0x447B
+#define mmCRTC3_CRTC_GSL_VSYNC_GAP 0x4479
+#define mmCRTC3_CRTC_GSL_WINDOW 0x447A
+#define mmCRTC3_CRTC_H_BLANK_EARLY_NUM 0x447D
+#define mmCRTC3_CRTC_H_BLANK_START_END 0x4481
+#define mmCRTC3_CRTC_H_SYNC_A 0x4482
+#define mmCRTC3_CRTC_H_SYNC_A_CNTL 0x4483
+#define mmCRTC3_CRTC_H_SYNC_B 0x4484
+#define mmCRTC3_CRTC_H_SYNC_B_CNTL 0x4485
+#define mmCRTC3_CRTC_H_TOTAL 0x4480
+#define mmCRTC3_CRTC_INTERLACE_CONTROL 0x449E
+#define mmCRTC3_CRTC_INTERLACE_STATUS 0x449F
+#define mmCRTC3_CRTC_INTERRUPT_CONTROL 0x44B4
+#define mmCRTC3_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x44AB
+#define mmCRTC3_CRTC_MASTER_EN 0x44C2
+#define mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT 0x44BF
+#define mmCRTC3_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x44C0
+#define mmCRTC3_CRTC_MVP_STATUS 0x44C1
+#define mmCRTC3_CRTC_NOM_VERT_POSITION 0x44A5
+#define mmCRTC3_CRTC_OVERSCAN_COLOR 0x44A0
+#define mmCRTC3_CRTC_SNAPSHOT_CONTROL 0x44B0
+#define mmCRTC3_CRTC_SNAPSHOT_FRAME 0x44B2
+#define mmCRTC3_CRTC_SNAPSHOT_POSITION 0x44B1
+#define mmCRTC3_CRTC_SNAPSHOT_STATUS 0x44AF
+#define mmCRTC3_CRTC_START_LINE_CONTROL 0x44B3
+#define mmCRTC3_CRTC_STATUS 0x44A3
+#define mmCRTC3_CRTC_STATUS_FRAME_COUNT 0x44A6
+#define mmCRTC3_CRTC_STATUS_HV_COUNT 0x44A8
+#define mmCRTC3_CRTC_STATUS_POSITION 0x44A4
+#define mmCRTC3_CRTC_STATUS_VF_COUNT 0x44A7
+#define mmCRTC3_CRTC_STEREO_CONTROL 0x44AE
+#define mmCRTC3_CRTC_STEREO_FORCE_NEXT_EYE 0x449B
+#define mmCRTC3_CRTC_STEREO_STATUS 0x44AD
+#define mmCRTC3_CRTC_TEST_DEBUG_DATA 0x44C7
+#define mmCRTC3_CRTC_TEST_DEBUG_INDEX 0x44C6
+#define mmCRTC3_CRTC_TEST_PATTERN_COLOR 0x44BC
+#define mmCRTC3_CRTC_TEST_PATTERN_CONTROL 0x44BA
+#define mmCRTC3_CRTC_TEST_PATTERN_PARAMETERS 0x44BB
+#define mmCRTC3_CRTC_TRIGA_CNTL 0x4494
+#define mmCRTC3_CRTC_TRIGA_MANUAL_TRIG 0x4495
+#define mmCRTC3_CRTC_TRIGB_CNTL 0x4496
+#define mmCRTC3_CRTC_TRIGB_MANUAL_TRIG 0x4497
+#define mmCRTC3_CRTC_UPDATE_LOCK 0x44B5
+#define mmCRTC3_CRTC_VBI_END 0x4486
+#define mmCRTC3_CRTC_V_BLANK_START_END 0x448D
+#define mmCRTC3_CRTC_VERT_SYNC_CONTROL 0x44AC
+#define mmCRTC3_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x44B7
+#define mmCRTC3_CRTC_V_SYNC_A 0x448E
+#define mmCRTC3_CRTC_V_SYNC_A_CNTL 0x448F
+#define mmCRTC3_CRTC_V_SYNC_B 0x4490
+#define mmCRTC3_CRTC_V_SYNC_B_CNTL 0x4491
+#define mmCRTC3_CRTC_VSYNC_NOM_INT_STATUS 0x448C
+#define mmCRTC3_CRTC_V_TOTAL 0x4487
+#define mmCRTC3_CRTC_V_TOTAL_CONTROL 0x448A
+#define mmCRTC3_CRTC_V_TOTAL_INT_STATUS 0x448B
+#define mmCRTC3_CRTC_V_TOTAL_MAX 0x4489
+#define mmCRTC3_CRTC_V_TOTAL_MIN 0x4488
+#define mmCRTC3_CRTC_V_UPDATE_INT_STATUS 0x44C4
+#define mmCRTC3_DCFE_DBG_SEL 0x447E
+#define mmCRTC3_DCFE_MEM_LIGHT_SLEEP_CNTL 0x447F
+#define mmCRTC_3D_STRUCTURE_CONTROL 0x1B78
+#define mmCRTC3_MASTER_UPDATE_LOCK 0x44BD
+#define mmCRTC3_MASTER_UPDATE_MODE 0x44BE
+#define mmCRTC3_PIXEL_RATE_CNTL 0x014C
+#define mmCRTC4_CRTC_3D_STRUCTURE_CONTROL 0x4778
+#define mmCRTC4_CRTC_ALLOW_STOP_OFF_V_CNT 0x47C3
+#define mmCRTC4_CRTC_BLACK_COLOR 0x47A2
+#define mmCRTC4_CRTC_BLANK_CONTROL 0x479D
+#define mmCRTC4_CRTC_BLANK_DATA_COLOR 0x47A1
+#define mmCRTC4_CRTC_CONTROL 0x479C
+#define mmCRTC4_CRTC_COUNT_CONTROL 0x47A9
+#define mmCRTC4_CRTC_COUNT_RESET 0x47AA
+#define mmCRTC4_CRTC_DCFE_CLOCK_CONTROL 0x477C
+#define mmCRTC4_CRTC_DOUBLE_BUFFER_CONTROL 0x47B6
+#define mmCRTC4_CRTC_DTMTEST_CNTL 0x4792
+#define mmCRTC4_CRTC_DTMTEST_STATUS_POSITION 0x4793
+#define mmCRTC4_CRTC_FLOW_CONTROL 0x4799
+#define mmCRTC4_CRTC_FORCE_COUNT_NOW_CNTL 0x4798
+#define mmCRTC4_CRTC_GSL_CONTROL 0x477B
+#define mmCRTC4_CRTC_GSL_VSYNC_GAP 0x4779
+#define mmCRTC4_CRTC_GSL_WINDOW 0x477A
+#define mmCRTC4_CRTC_H_BLANK_EARLY_NUM 0x477D
+#define mmCRTC4_CRTC_H_BLANK_START_END 0x4781
+#define mmCRTC4_CRTC_H_SYNC_A 0x4782
+#define mmCRTC4_CRTC_H_SYNC_A_CNTL 0x4783
+#define mmCRTC4_CRTC_H_SYNC_B 0x4784
+#define mmCRTC4_CRTC_H_SYNC_B_CNTL 0x4785
+#define mmCRTC4_CRTC_H_TOTAL 0x4780
+#define mmCRTC4_CRTC_INTERLACE_CONTROL 0x479E
+#define mmCRTC4_CRTC_INTERLACE_STATUS 0x479F
+#define mmCRTC4_CRTC_INTERRUPT_CONTROL 0x47B4
+#define mmCRTC4_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x47AB
+#define mmCRTC4_CRTC_MASTER_EN 0x47C2
+#define mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT 0x47BF
+#define mmCRTC4_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x47C0
+#define mmCRTC4_CRTC_MVP_STATUS 0x47C1
+#define mmCRTC4_CRTC_NOM_VERT_POSITION 0x47A5
+#define mmCRTC4_CRTC_OVERSCAN_COLOR 0x47A0
+#define mmCRTC4_CRTC_SNAPSHOT_CONTROL 0x47B0
+#define mmCRTC4_CRTC_SNAPSHOT_FRAME 0x47B2
+#define mmCRTC4_CRTC_SNAPSHOT_POSITION 0x47B1
+#define mmCRTC4_CRTC_SNAPSHOT_STATUS 0x47AF
+#define mmCRTC4_CRTC_START_LINE_CONTROL 0x47B3
+#define mmCRTC4_CRTC_STATUS 0x47A3
+#define mmCRTC4_CRTC_STATUS_FRAME_COUNT 0x47A6
+#define mmCRTC4_CRTC_STATUS_HV_COUNT 0x47A8
+#define mmCRTC4_CRTC_STATUS_POSITION 0x47A4
+#define mmCRTC4_CRTC_STATUS_VF_COUNT 0x47A7
+#define mmCRTC4_CRTC_STEREO_CONTROL 0x47AE
+#define mmCRTC4_CRTC_STEREO_FORCE_NEXT_EYE 0x479B
+#define mmCRTC4_CRTC_STEREO_STATUS 0x47AD
+#define mmCRTC4_CRTC_TEST_DEBUG_DATA 0x47C7
+#define mmCRTC4_CRTC_TEST_DEBUG_INDEX 0x47C6
+#define mmCRTC4_CRTC_TEST_PATTERN_COLOR 0x47BC
+#define mmCRTC4_CRTC_TEST_PATTERN_CONTROL 0x47BA
+#define mmCRTC4_CRTC_TEST_PATTERN_PARAMETERS 0x47BB
+#define mmCRTC4_CRTC_TRIGA_CNTL 0x4794
+#define mmCRTC4_CRTC_TRIGA_MANUAL_TRIG 0x4795
+#define mmCRTC4_CRTC_TRIGB_CNTL 0x4796
+#define mmCRTC4_CRTC_TRIGB_MANUAL_TRIG 0x4797
+#define mmCRTC4_CRTC_UPDATE_LOCK 0x47B5
+#define mmCRTC4_CRTC_VBI_END 0x4786
+#define mmCRTC4_CRTC_V_BLANK_START_END 0x478D
+#define mmCRTC4_CRTC_VERT_SYNC_CONTROL 0x47AC
+#define mmCRTC4_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x47B7
+#define mmCRTC4_CRTC_V_SYNC_A 0x478E
+#define mmCRTC4_CRTC_V_SYNC_A_CNTL 0x478F
+#define mmCRTC4_CRTC_V_SYNC_B 0x4790
+#define mmCRTC4_CRTC_V_SYNC_B_CNTL 0x4791
+#define mmCRTC4_CRTC_VSYNC_NOM_INT_STATUS 0x478C
+#define mmCRTC4_CRTC_V_TOTAL 0x4787
+#define mmCRTC4_CRTC_V_TOTAL_CONTROL 0x478A
+#define mmCRTC4_CRTC_V_TOTAL_INT_STATUS 0x478B
+#define mmCRTC4_CRTC_V_TOTAL_MAX 0x4789
+#define mmCRTC4_CRTC_V_TOTAL_MIN 0x4788
+#define mmCRTC4_CRTC_V_UPDATE_INT_STATUS 0x47C4
+#define mmCRTC4_DCFE_DBG_SEL 0x477E
+#define mmCRTC4_DCFE_MEM_LIGHT_SLEEP_CNTL 0x477F
+#define mmCRTC4_MASTER_UPDATE_LOCK 0x47BD
+#define mmCRTC4_MASTER_UPDATE_MODE 0x47BE
+#define mmCRTC4_PIXEL_RATE_CNTL 0x0150
+#define mmCRTC5_CRTC_3D_STRUCTURE_CONTROL 0x4A78
+#define mmCRTC5_CRTC_ALLOW_STOP_OFF_V_CNT 0x4AC3
+#define mmCRTC5_CRTC_BLACK_COLOR 0x4AA2
+#define mmCRTC5_CRTC_BLANK_CONTROL 0x4A9D
+#define mmCRTC5_CRTC_BLANK_DATA_COLOR 0x4AA1
+#define mmCRTC5_CRTC_CONTROL 0x4A9C
+#define mmCRTC5_CRTC_COUNT_CONTROL 0x4AA9
+#define mmCRTC5_CRTC_COUNT_RESET 0x4AAA
+#define mmCRTC5_CRTC_DCFE_CLOCK_CONTROL 0x4A7C
+#define mmCRTC5_CRTC_DOUBLE_BUFFER_CONTROL 0x4AB6
+#define mmCRTC5_CRTC_DTMTEST_CNTL 0x4A92
+#define mmCRTC5_CRTC_DTMTEST_STATUS_POSITION 0x4A93
+#define mmCRTC5_CRTC_FLOW_CONTROL 0x4A99
+#define mmCRTC5_CRTC_FORCE_COUNT_NOW_CNTL 0x4A98
+#define mmCRTC5_CRTC_GSL_CONTROL 0x4A7B
+#define mmCRTC5_CRTC_GSL_VSYNC_GAP 0x4A79
+#define mmCRTC5_CRTC_GSL_WINDOW 0x4A7A
+#define mmCRTC5_CRTC_H_BLANK_EARLY_NUM 0x4A7D
+#define mmCRTC5_CRTC_H_BLANK_START_END 0x4A81
+#define mmCRTC5_CRTC_H_SYNC_A 0x4A82
+#define mmCRTC5_CRTC_H_SYNC_A_CNTL 0x4A83
+#define mmCRTC5_CRTC_H_SYNC_B 0x4A84
+#define mmCRTC5_CRTC_H_SYNC_B_CNTL 0x4A85
+#define mmCRTC5_CRTC_H_TOTAL 0x4A80
+#define mmCRTC5_CRTC_INTERLACE_CONTROL 0x4A9E
+#define mmCRTC5_CRTC_INTERLACE_STATUS 0x4A9F
+#define mmCRTC5_CRTC_INTERRUPT_CONTROL 0x4AB4
+#define mmCRTC5_CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x4AAB
+#define mmCRTC5_CRTC_MASTER_EN 0x4AC2
+#define mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT 0x4ABF
+#define mmCRTC5_CRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x4AC0
+#define mmCRTC5_CRTC_MVP_STATUS 0x4AC1
+#define mmCRTC5_CRTC_NOM_VERT_POSITION 0x4AA5
+#define mmCRTC5_CRTC_OVERSCAN_COLOR 0x4AA0
+#define mmCRTC5_CRTC_SNAPSHOT_CONTROL 0x4AB0
+#define mmCRTC5_CRTC_SNAPSHOT_FRAME 0x4AB2
+#define mmCRTC5_CRTC_SNAPSHOT_POSITION 0x4AB1
+#define mmCRTC5_CRTC_SNAPSHOT_STATUS 0x4AAF
+#define mmCRTC5_CRTC_START_LINE_CONTROL 0x4AB3
+#define mmCRTC5_CRTC_STATUS 0x4AA3
+#define mmCRTC5_CRTC_STATUS_FRAME_COUNT 0x4AA6
+#define mmCRTC5_CRTC_STATUS_HV_COUNT 0x4AA8
+#define mmCRTC5_CRTC_STATUS_POSITION 0x4AA4
+#define mmCRTC5_CRTC_STATUS_VF_COUNT 0x4AA7
+#define mmCRTC5_CRTC_STEREO_CONTROL 0x4AAE
+#define mmCRTC5_CRTC_STEREO_FORCE_NEXT_EYE 0x4A9B
+#define mmCRTC5_CRTC_STEREO_STATUS 0x4AAD
+#define mmCRTC5_CRTC_TEST_DEBUG_DATA 0x4AC7
+#define mmCRTC5_CRTC_TEST_DEBUG_INDEX 0x4AC6
+#define mmCRTC5_CRTC_TEST_PATTERN_COLOR 0x4ABC
+#define mmCRTC5_CRTC_TEST_PATTERN_CONTROL 0x4ABA
+#define mmCRTC5_CRTC_TEST_PATTERN_PARAMETERS 0x4ABB
+#define mmCRTC5_CRTC_TRIGA_CNTL 0x4A94
+#define mmCRTC5_CRTC_TRIGA_MANUAL_TRIG 0x4A95
+#define mmCRTC5_CRTC_TRIGB_CNTL 0x4A96
+#define mmCRTC5_CRTC_TRIGB_MANUAL_TRIG 0x4A97
+#define mmCRTC5_CRTC_UPDATE_LOCK 0x4AB5
+#define mmCRTC5_CRTC_VBI_END 0x4A86
+#define mmCRTC5_CRTC_V_BLANK_START_END 0x4A8D
+#define mmCRTC5_CRTC_VERT_SYNC_CONTROL 0x4AAC
+#define mmCRTC5_CRTC_VGA_PARAMETER_CAPTURE_MODE 0x4AB7
+#define mmCRTC5_CRTC_V_SYNC_A 0x4A8E
+#define mmCRTC5_CRTC_V_SYNC_A_CNTL 0x4A8F
+#define mmCRTC5_CRTC_V_SYNC_B 0x4A90
+#define mmCRTC5_CRTC_V_SYNC_B_CNTL 0x4A91
+#define mmCRTC5_CRTC_VSYNC_NOM_INT_STATUS 0x4A8C
+#define mmCRTC5_CRTC_V_TOTAL 0x4A87
+#define mmCRTC5_CRTC_V_TOTAL_CONTROL 0x4A8A
+#define mmCRTC5_CRTC_V_TOTAL_INT_STATUS 0x4A8B
+#define mmCRTC5_CRTC_V_TOTAL_MAX 0x4A89
+#define mmCRTC5_CRTC_V_TOTAL_MIN 0x4A88
+#define mmCRTC5_CRTC_V_UPDATE_INT_STATUS 0x4AC4
+#define mmCRTC5_DCFE_DBG_SEL 0x4A7E
+#define mmCRTC5_DCFE_MEM_LIGHT_SLEEP_CNTL 0x4A7F
+#define mmCRTC5_MASTER_UPDATE_LOCK 0x4ABD
+#define mmCRTC5_MASTER_UPDATE_MODE 0x4ABE
+#define mmCRTC5_PIXEL_RATE_CNTL 0x0154
+#define mmCRTC8_DATA 0x00ED
+#define mmCRTC8_IDX 0x00ED
+#define mmCRTC_ALLOW_STOP_OFF_V_CNT 0x1BC3
+#define mmCRTC_BLACK_COLOR 0x1BA2
+#define mmCRTC_BLANK_CONTROL 0x1B9D
+#define mmCRTC_BLANK_DATA_COLOR 0x1BA1
+#define mmCRTC_CONTROL 0x1B9C
+#define mmCRTC_COUNT_CONTROL 0x1BA9
+#define mmCRTC_COUNT_RESET 0x1BAA
+#define mmCRTC_DCFE_CLOCK_CONTROL 0x1B7C
+#define mmCRTC_DOUBLE_BUFFER_CONTROL 0x1BB6
+#define mmCRTC_DTMTEST_CNTL 0x1B92
+#define mmCRTC_DTMTEST_STATUS_POSITION 0x1B93
+#define mmCRTC_FLOW_CONTROL 0x1B99
+#define mmCRTC_FORCE_COUNT_NOW_CNTL 0x1B98
+#define mmCRTC_GSL_CONTROL 0x1B7B
+#define mmCRTC_GSL_VSYNC_GAP 0x1B79
+#define mmCRTC_GSL_WINDOW 0x1B7A
+#define mmCRTC_H_BLANK_EARLY_NUM 0x1B7D
+#define mmCRTC_H_BLANK_START_END 0x1B81
+#define mmCRTC_H_SYNC_A 0x1B82
+#define mmCRTC_H_SYNC_A_CNTL 0x1B83
+#define mmCRTC_H_SYNC_B 0x1B84
+#define mmCRTC_H_SYNC_B_CNTL 0x1B85
+#define mmCRTC_H_TOTAL 0x1B80
+#define mmCRTC_INTERLACE_CONTROL 0x1B9E
+#define mmCRTC_INTERLACE_STATUS 0x1B9F
+#define mmCRTC_INTERRUPT_CONTROL 0x1BB4
+#define mmCRTC_MANUAL_FORCE_VSYNC_NEXT_LINE 0x1BAB
+#define mmCRTC_MASTER_EN 0x1BC2
+#define mmCRTC_MVP_INBAND_CNTL_INSERT 0x1BBF
+#define mmCRTC_MVP_INBAND_CNTL_INSERT_TIMER 0x1BC0
+#define mmCRTC_MVP_STATUS 0x1BC1
+#define mmCRTC_NOM_VERT_POSITION 0x1BA5
+#define mmCRTC_OVERSCAN_COLOR 0x1BA0
+#define mmCRTC_SNAPSHOT_CONTROL 0x1BB0
+#define mmCRTC_SNAPSHOT_FRAME 0x1BB2
+#define mmCRTC_SNAPSHOT_POSITION 0x1BB1
+#define mmCRTC_SNAPSHOT_STATUS 0x1BAF
+#define mmCRTC_START_LINE_CONTROL 0x1BB3
+#define mmCRTC_STATUS 0x1BA3
+#define mmCRTC_STATUS_FRAME_COUNT 0x1BA6
+#define mmCRTC_STATUS_HV_COUNT 0x1BA8
+#define mmCRTC_STATUS_POSITION 0x1BA4
+#define mmCRTC_STATUS_VF_COUNT 0x1BA7
+#define mmCRTC_STEREO_CONTROL 0x1BAE
+#define mmCRTC_STEREO_FORCE_NEXT_EYE 0x1B9B
+#define mmCRTC_STEREO_STATUS 0x1BAD
+#define mmCRTC_TEST_DEBUG_DATA 0x1BC7
+#define mmCRTC_TEST_DEBUG_INDEX 0x1BC6
+#define mmCRTC_TEST_PATTERN_COLOR 0x1BBC
+#define mmCRTC_TEST_PATTERN_CONTROL 0x1BBA
+#define mmCRTC_TEST_PATTERN_PARAMETERS 0x1BBB
+#define mmCRTC_TRIGA_CNTL 0x1B94
+#define mmCRTC_TRIGA_MANUAL_TRIG 0x1B95
+#define mmCRTC_TRIGB_CNTL 0x1B96
+#define mmCRTC_TRIGB_MANUAL_TRIG 0x1B97
+#define mmCRTC_UPDATE_LOCK 0x1BB5
+#define mmCRTC_VBI_END 0x1B86
+#define mmCRTC_V_BLANK_START_END 0x1B8D
+#define mmCRTC_VERT_SYNC_CONTROL 0x1BAC
+#define mmCRTC_VGA_PARAMETER_CAPTURE_MODE 0x1BB7
+#define mmCRTC_V_SYNC_A 0x1B8E
+#define mmCRTC_V_SYNC_A_CNTL 0x1B8F
+#define mmCRTC_V_SYNC_B 0x1B90
+#define mmCRTC_V_SYNC_B_CNTL 0x1B91
+#define mmCRTC_VSYNC_NOM_INT_STATUS 0x1B8C
+#define mmCRTC_V_TOTAL 0x1B87
+#define mmCRTC_V_TOTAL_CONTROL 0x1B8A
+#define mmCRTC_V_TOTAL_INT_STATUS 0x1B8B
+#define mmCRTC_V_TOTAL_MAX 0x1B89
+#define mmCRTC_V_TOTAL_MIN 0x1B88
+#define mmCRTC_V_UPDATE_INT_STATUS 0x1BC4
+#define mmCUR_COLOR1 0x1A6C
+#define mmCUR_COLOR2 0x1A6D
+#define mmCUR_CONTROL 0x1A66
+#define mmCUR_HOT_SPOT 0x1A6B
+#define mmCUR_POSITION 0x1A6A
+#define mmCUR_REQUEST_FILTER_CNTL 0x1A99
+#define mmCUR_SIZE 0x1A68
+#define mmCUR_SURFACE_ADDRESS 0x1A67
+#define mmCUR_SURFACE_ADDRESS_HIGH 0x1A69
+#define mmCUR_UPDATE 0x1A6E
+#define mmD1VGA_CONTROL 0x00CC
+#define mmD2VGA_CONTROL 0x00CE
+#define mmD3VGA_CONTROL 0x00F8
+#define mmD4VGA_CONTROL 0x00F9
+#define mmD5VGA_CONTROL 0x00FA
+#define mmD6VGA_CONTROL 0x00FB
+#define mmDAC_AUTODETECT_CONTROL 0x19EE
+#define mmDAC_AUTODETECT_CONTROL2 0x19EF
+#define mmDAC_AUTODETECT_CONTROL3 0x19F0
+#define mmDAC_AUTODETECT_INT_CONTROL 0x19F2
+#define mmDAC_AUTODETECT_STATUS 0x19F1
+#define mmDAC_CLK_ENABLE 0x0128
+#define mmDAC_COMPARATOR_ENABLE 0x19F7
+#define mmDAC_COMPARATOR_OUTPUT 0x19F8
+#define mmDAC_CONTROL 0x19F6
+#define mmDAC_CRC_CONTROL 0x19E7
+#define mmDAC_CRC_EN 0x19E6
+#define mmDAC_CRC_SIG_CONTROL 0x19EB
+#define mmDAC_CRC_SIG_CONTROL_MASK 0x19E9
+#define mmDAC_CRC_SIG_RGB 0x19EA
+#define mmDAC_CRC_SIG_RGB_MASK 0x19E8
+#define mmDAC_DATA 0x00F2
+#define mmDAC_DFT_CONFIG 0x19FA
+#define mmDAC_ENABLE 0x19E4
+#define mmDAC_FIFO_STATUS 0x19FB
+#define mmDAC_FORCE_DATA 0x19F4
+#define mmDAC_FORCE_OUTPUT_CNTL 0x19F3
+#define mmDAC_MACRO_CNTL_RESERVED0 0x19FC
+#define mmDAC_MACRO_CNTL_RESERVED1 0x19FD
+#define mmDAC_MACRO_CNTL_RESERVED2 0x19FE
+#define mmDAC_MACRO_CNTL_RESERVED3 0x19FF
+#define mmDAC_MASK 0x00F1
+#define mmDAC_POWERDOWN 0x19F5
+#define mmDAC_PWR_CNTL 0x19F9
+#define mmDAC_R_INDEX 0x00F1
+#define mmDAC_SOURCE_SELECT 0x19E5
+#define mmDAC_STEREOSYNC_SELECT 0x19ED
+#define mmDAC_SYNC_TRISTATE_CONTROL 0x19EC
+#define mmDAC_W_INDEX 0x00F2
+#define mmDC_ABM1_ACE_CNTL_MISC 0x1641
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_0 0x163A
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_1 0x163B
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_2 0x163C
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_3 0x163D
+#define mmDC_ABM1_ACE_OFFSET_SLOPE_4 0x163E
+#define mmDC_ABM1_ACE_THRES_12 0x163F
+#define mmDC_ABM1_ACE_THRES_34 0x1640
+#define mmDC_ABM1_BL_MASTER_LOCK 0x169C
+#define mmDC_ABM1_CNTL 0x1638
+#define mmDC_ABM1_DEBUG_MISC 0x1649
+#define mmDC_ABM1_HG_BIN_1_32_SHIFT_FLAG 0x1656
+#define mmDC_ABM1_HG_BIN_17_24_SHIFT_INDEX 0x1659
+#define mmDC_ABM1_HG_BIN_1_8_SHIFT_INDEX 0x1657
+#define mmDC_ABM1_HG_BIN_25_32_SHIFT_INDEX 0x165A
+#define mmDC_ABM1_HG_BIN_9_16_SHIFT_INDEX 0x1658
+#define mmDC_ABM1_HGLS_REG_READ_PROGRESS 0x164A
+#define mmDC_ABM1_HG_MISC_CTRL 0x164B
+#define mmDC_ABM1_HG_RESULT_10 0x1664
+#define mmDC_ABM1_HG_RESULT_1 0x165B
+#define mmDC_ABM1_HG_RESULT_11 0x1665
+#define mmDC_ABM1_HG_RESULT_12 0x1666
+#define mmDC_ABM1_HG_RESULT_13 0x1667
+#define mmDC_ABM1_HG_RESULT_14 0x1668
+#define mmDC_ABM1_HG_RESULT_15 0x1669
+#define mmDC_ABM1_HG_RESULT_16 0x166A
+#define mmDC_ABM1_HG_RESULT_17 0x166B
+#define mmDC_ABM1_HG_RESULT_18 0x166C
+#define mmDC_ABM1_HG_RESULT_19 0x166D
+#define mmDC_ABM1_HG_RESULT_20 0x166E
+#define mmDC_ABM1_HG_RESULT_2 0x165C
+#define mmDC_ABM1_HG_RESULT_21 0x166F
+#define mmDC_ABM1_HG_RESULT_22 0x1670
+#define mmDC_ABM1_HG_RESULT_23 0x1671
+#define mmDC_ABM1_HG_RESULT_24 0x1672
+#define mmDC_ABM1_HG_RESULT_3 0x165D
+#define mmDC_ABM1_HG_RESULT_4 0x165E
+#define mmDC_ABM1_HG_RESULT_5 0x165F
+#define mmDC_ABM1_HG_RESULT_6 0x1660
+#define mmDC_ABM1_HG_RESULT_7 0x1661
+#define mmDC_ABM1_HG_RESULT_8 0x1662
+#define mmDC_ABM1_HG_RESULT_9 0x1663
+#define mmDC_ABM1_HG_SAMPLE_RATE 0x1654
+#define mmDC_ABM1_IPCSC_COEFF_SEL 0x1639
+#define mmDC_ABM1_LS_FILTERED_MIN_MAX_LUMA 0x164E
+#define mmDC_ABM1_LS_MAX_PIXEL_VALUE_COUNT 0x1653
+#define mmDC_ABM1_LS_MIN_MAX_LUMA 0x164D
+#define mmDC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES 0x1651
+#define mmDC_ABM1_LS_MIN_PIXEL_VALUE_COUNT 0x1652
+#define mmDC_ABM1_LS_OVR_SCAN_BIN 0x1650
+#define mmDC_ABM1_LS_PIXEL_COUNT 0x164F
+#define mmDC_ABM1_LS_SAMPLE_RATE 0x1655
+#define mmDC_ABM1_LS_SUM_OF_LUMA 0x164C
+#define mmDC_ABM1_OVERSCAN_PIXEL_VALUE 0x169B
+#define mmDCCG_AUDIO_DTO0_MODULE 0x016D
+#define mmDCCG_AUDIO_DTO0_PHASE 0x016C
+#define mmDCCG_AUDIO_DTO1_MODULE 0x0171
+#define mmDCCG_AUDIO_DTO1_PHASE 0x0170
+#define mmDCCG_AUDIO_DTO_SOURCE 0x016B
+#define mmDCCG_CAC_STATUS 0x0137
+#define mmDCCG_GATE_DISABLE_CNTL 0x0134
+#define mmDCCG_GTC_CNTL 0x0120
+#define mmDCCG_GTC_CURRENT 0x0123
+#define mmDCCG_GTC_DTO_MODULO 0x0122
+#define mmDCCG_PERFMON_CNTL 0x0133
+#define mmDCCG_PLL0_PLL_ANALOG 0x1708
+#define mmDCCG_PLL0_PLL_CNTL 0x1707
+#define mmDCCG_PLL0_PLL_DEBUG_CNTL 0x170B
+#define mmDCCG_PLL0_PLL_DISPCLK_CURRENT_DTO_PHASE 0x170F
+#define mmDCCG_PLL0_PLL_DISPCLK_DTO_CNTL 0x170E
+#define mmDCCG_PLL0_PLL_DS_CNTL 0x1705
+#define mmDCCG_PLL0_PLL_FB_DIV 0x1701
+#define mmDCCG_PLL0_PLL_IDCLK_CNTL 0x1706
+#define mmDCCG_PLL0_PLL_POST_DIV 0x1702
+#define mmDCCG_PLL0_PLL_REF_DIV 0x1700
+#define mmDCCG_PLL0_PLL_SS_AMOUNT_DSFRAC 0x1703
+#define mmDCCG_PLL0_PLL_SS_CNTL 0x1704
+#define mmDCCG_PLL0_PLL_UNLOCK_DETECT_CNTL 0x170A
+#define mmDCCG_PLL0_PLL_UPDATE_CNTL 0x170D
+#define mmDCCG_PLL0_PLL_UPDATE_LOCK 0x170C
+#define mmDCCG_PLL0_PLL_VREG_CNTL 0x1709
+#define mmDCCG_PLL1_PLL_ANALOG 0x1718
+#define mmDCCG_PLL1_PLL_CNTL 0x1717
+#define mmDCCG_PLL1_PLL_DEBUG_CNTL 0x171B
+#define mmDCCG_PLL1_PLL_DISPCLK_CURRENT_DTO_PHASE 0x171F
+#define mmDCCG_PLL1_PLL_DISPCLK_DTO_CNTL 0x171E
+#define mmDCCG_PLL1_PLL_DS_CNTL 0x1715
+#define mmDCCG_PLL1_PLL_FB_DIV 0x1711
+#define mmDCCG_PLL1_PLL_IDCLK_CNTL 0x1716
+#define mmDCCG_PLL1_PLL_POST_DIV 0x1712
+#define mmDCCG_PLL1_PLL_REF_DIV 0x1710
+#define mmDCCG_PLL1_PLL_SS_AMOUNT_DSFRAC 0x1713
+#define mmDCCG_PLL1_PLL_SS_CNTL 0x1714
+#define mmDCCG_PLL1_PLL_UNLOCK_DETECT_CNTL 0x171A
+#define mmDCCG_PLL1_PLL_UPDATE_CNTL 0x171D
+#define mmDCCG_PLL1_PLL_UPDATE_LOCK 0x171C
+#define mmDCCG_PLL1_PLL_VREG_CNTL 0x1719
+#define mmDCCG_PLL2_PLL_ANALOG 0x1728
+#define mmDCCG_PLL2_PLL_CNTL 0x1727
+#define mmDCCG_PLL2_PLL_DEBUG_CNTL 0x172B
+#define mmDCCG_PLL2_PLL_DISPCLK_CURRENT_DTO_PHASE 0x172F
+#define mmDCCG_PLL2_PLL_DISPCLK_DTO_CNTL 0x172E
+#define mmDCCG_PLL2_PLL_DS_CNTL 0x1725
+#define mmDCCG_PLL2_PLL_FB_DIV 0x1721
+#define mmDCCG_PLL2_PLL_IDCLK_CNTL 0x1726
+#define mmDCCG_PLL2_PLL_POST_DIV 0x1722
+#define mmDCCG_PLL2_PLL_REF_DIV 0x1720
+#define mmDCCG_PLL2_PLL_SS_AMOUNT_DSFRAC 0x1723
+#define mmDCCG_PLL2_PLL_SS_CNTL 0x1724
+#define mmDCCG_PLL2_PLL_UNLOCK_DETECT_CNTL 0x172A
+#define mmDCCG_PLL2_PLL_UPDATE_CNTL 0x172D
+#define mmDCCG_PLL2_PLL_UPDATE_LOCK 0x172C
+#define mmDCCG_PLL2_PLL_VREG_CNTL 0x1729
+#define mmDCCG_SOFT_RESET 0x015F
+#define mmDCCG_TEST_CLK_SEL 0x017E
+#define mmDCCG_TEST_DEBUG_DATA 0x017D
+#define mmDCCG_TEST_DEBUG_INDEX 0x017C
+#define mmDCCG_VPCLK_CNTL 0x031F
+#define mmDCDEBUG_BUS_CLK1_SEL 0x1860
+#define mmDCDEBUG_BUS_CLK2_SEL 0x1861
+#define mmDCDEBUG_BUS_CLK3_SEL 0x1862
+#define mmDCDEBUG_BUS_CLK4_SEL 0x1863
+#define mmDCDEBUG_OUT_CNTL 0x186B
+#define mmDCDEBUG_OUT_DATA 0x186E
+#define mmDCDEBUG_OUT_PIN_OVERRIDE 0x186A
+#define mmDC_DMCU_SCRATCH 0x1618
+#define mmDC_DVODATA_CONFIG 0x1905
+#define mmDCFE0_SOFT_RESET 0x0158
+#define mmDCFE1_SOFT_RESET 0x0159
+#define mmDCFE2_SOFT_RESET 0x015A
+#define mmDCFE3_SOFT_RESET 0x015B
+#define mmDCFE4_SOFT_RESET 0x015C
+#define mmDCFE5_SOFT_RESET 0x015D
+#define mmDCFE_DBG_SEL 0x1B7E
+#define mmDCFE_MEM_LIGHT_SLEEP_CNTL 0x1B7F
+#define mmDC_GENERICA 0x1900
+#define mmDC_GENERICB 0x1901
+#define mmDC_GPIO_DDC1_A 0x194D
+#define mmDC_GPIO_DDC1_EN 0x194E
+#define mmDC_GPIO_DDC1_MASK 0x194C
+#define mmDC_GPIO_DDC1_Y 0x194F
+#define mmDC_GPIO_DDC2_A 0x1951
+#define mmDC_GPIO_DDC2_EN 0x1952
+#define mmDC_GPIO_DDC2_MASK 0x1950
+#define mmDC_GPIO_DDC2_Y 0x1953
+#define mmDC_GPIO_DDC3_A 0x1955
+#define mmDC_GPIO_DDC3_EN 0x1956
+#define mmDC_GPIO_DDC3_MASK 0x1954
+#define mmDC_GPIO_DDC3_Y 0x1957
+#define mmDC_GPIO_DDC4_A 0x1959
+#define mmDC_GPIO_DDC4_EN 0x195A
+#define mmDC_GPIO_DDC4_MASK 0x1958
+#define mmDC_GPIO_DDC4_Y 0x195B
+#define mmDC_GPIO_DDC5_A 0x195D
+#define mmDC_GPIO_DDC5_EN 0x195E
+#define mmDC_GPIO_DDC5_MASK 0x195C
+#define mmDC_GPIO_DDC5_Y 0x195F
+#define mmDC_GPIO_DDC6_A 0x1961
+#define mmDC_GPIO_DDC6_EN 0x1962
+#define mmDC_GPIO_DDC6_MASK 0x1960
+#define mmDC_GPIO_DDC6_Y 0x1963
+#define mmDC_GPIO_DDCVGA_A 0x1971
+#define mmDC_GPIO_DDCVGA_EN 0x1972
+#define mmDC_GPIO_DDCVGA_MASK 0x1970
+#define mmDC_GPIO_DDCVGA_Y 0x1973
+#define mmDC_GPIO_DEBUG 0x1904
+#define mmDC_GPIO_DVODATA_A 0x1949
+#define mmDC_GPIO_DVODATA_EN 0x194A
+#define mmDC_GPIO_DVODATA_MASK 0x1948
+#define mmDC_GPIO_DVODATA_Y 0x194B
+#define mmDC_GPIO_GENERIC_A 0x1945
+#define mmDC_GPIO_GENERIC_EN 0x1946
+#define mmDC_GPIO_GENERIC_MASK 0x1944
+#define mmDC_GPIO_GENERIC_Y 0x1947
+#define mmDC_GPIO_GENLK_A 0x1969
+#define mmDC_GPIO_GENLK_EN 0x196A
+#define mmDC_GPIO_GENLK_MASK 0x1968
+#define mmDC_GPIO_GENLK_Y 0x196B
+#define mmDC_GPIO_HPD_A 0x196D
+#define mmDC_GPIO_HPD_EN 0x196E
+#define mmDC_GPIO_HPD_MASK 0x196C
+#define mmDC_GPIO_HPD_Y 0x196F
+#define mmDC_GPIO_I2CPAD_A 0x1975
+#define mmDC_GPIO_I2CPAD_EN 0x1976
+#define mmDC_GPIO_I2CPAD_MASK 0x1974
+#define mmDC_GPIO_I2CPAD_STRENGTH 0x197A
+#define mmDC_GPIO_I2CPAD_Y 0x1977
+#define mmDC_GPIO_PAD_STRENGTH_1 0x1978
+#define mmDC_GPIO_PAD_STRENGTH_2 0x1979
+#define mmDC_GPIO_PWRSEQ_A 0x1941
+#define mmDC_GPIO_PWRSEQ_EN 0x1942
+#define mmDC_GPIO_PWRSEQ_MASK 0x1940
+#define mmDC_GPIO_PWRSEQ_Y 0x1943
+#define mmDC_GPIO_SYNCA_A 0x1965
+#define mmDC_GPIO_SYNCA_EN 0x1966
+#define mmDC_GPIO_SYNCA_MASK 0x1964
+#define mmDC_GPIO_SYNCA_Y 0x1967
+#define mmDC_GPU_TIMER_READ 0x1929
+#define mmDC_GPU_TIMER_READ_CNTL 0x192A
+#define mmDC_GPU_TIMER_START_POSITION_P_FLIP 0x1928
+#define mmDC_GPU_TIMER_START_POSITION_V_UPDATE 0x1927
+#define mmDC_HPD1_CONTROL 0x1809
+#define mmDC_HPD1_FAST_TRAIN_CNTL 0x1864
+#define mmDC_HPD1_INT_CONTROL 0x1808
+#define mmDC_HPD1_INT_STATUS 0x1807
+#define mmDC_HPD1_TOGGLE_FILT_CNTL 0x18BC
+#define mmDC_HPD2_CONTROL 0x180C
+#define mmDC_HPD2_FAST_TRAIN_CNTL 0x1865
+#define mmDC_HPD2_INT_CONTROL 0x180B
+#define mmDC_HPD2_INT_STATUS 0x180A
+#define mmDC_HPD2_TOGGLE_FILT_CNTL 0x18BD
+#define mmDC_HPD3_CONTROL 0x180F
+#define mmDC_HPD3_FAST_TRAIN_CNTL 0x1866
+#define mmDC_HPD3_INT_CONTROL 0x180E
+#define mmDC_HPD3_INT_STATUS 0x180D
+#define mmDC_HPD3_TOGGLE_FILT_CNTL 0x18BE
+#define mmDC_HPD4_CONTROL 0x1812
+#define mmDC_HPD4_FAST_TRAIN_CNTL 0x1867
+#define mmDC_HPD4_INT_CONTROL 0x1811
+#define mmDC_HPD4_INT_STATUS 0x1810
+#define mmDC_HPD4_TOGGLE_FILT_CNTL 0x18FC
+#define mmDC_HPD5_CONTROL 0x1815
+#define mmDC_HPD5_FAST_TRAIN_CNTL 0x1868
+#define mmDC_HPD5_INT_CONTROL 0x1814
+#define mmDC_HPD5_INT_STATUS 0x1813
+#define mmDC_HPD5_TOGGLE_FILT_CNTL 0x18FD
+#define mmDC_HPD6_CONTROL 0x1818
+#define mmDC_HPD6_FAST_TRAIN_CNTL 0x1869
+#define mmDC_HPD6_INT_CONTROL 0x1817
+#define mmDC_HPD6_INT_STATUS 0x1816
+#define mmDC_HPD6_TOGGLE_FILT_CNTL 0x18FE
+#define mmDC_I2C_ARBITRATION 0x181A
+#define mmDC_I2C_CONTROL 0x1819
+#define mmDC_I2C_DATA 0x1833
+#define mmDC_I2C_DDC1_HW_STATUS 0x181D
+#define mmDC_I2C_DDC1_SETUP 0x1824
+#define mmDC_I2C_DDC1_SPEED 0x1823
+#define mmDC_I2C_DDC2_HW_STATUS 0x181E
+#define mmDC_I2C_DDC2_SETUP 0x1826
+#define mmDC_I2C_DDC2_SPEED 0x1825
+#define mmDC_I2C_DDC3_HW_STATUS 0x181F
+#define mmDC_I2C_DDC3_SETUP 0x1828
+#define mmDC_I2C_DDC3_SPEED 0x1827
+#define mmDC_I2C_DDC4_HW_STATUS 0x1820
+#define mmDC_I2C_DDC4_SETUP 0x182A
+#define mmDC_I2C_DDC4_SPEED 0x1829
+#define mmDC_I2C_DDC5_HW_STATUS 0x1821
+#define mmDC_I2C_DDC5_SETUP 0x182C
+#define mmDC_I2C_DDC5_SPEED 0x182B
+#define mmDC_I2C_DDC6_HW_STATUS 0x1822
+#define mmDC_I2C_DDC6_SETUP 0x182E
+#define mmDC_I2C_DDC6_SPEED 0x182D
+#define mmDC_I2C_DDCVGA_HW_STATUS 0x1855
+#define mmDC_I2C_DDCVGA_SETUP 0x1857
+#define mmDC_I2C_DDCVGA_SPEED 0x1856
+#define mmDC_I2C_EDID_DETECT_CTRL 0x186F
+#define mmDC_I2C_INTERRUPT_CONTROL 0x181B
+#define mmDC_I2C_SW_STATUS 0x181C
+#define mmDC_I2C_TRANSACTION0 0x182F
+#define mmDC_I2C_TRANSACTION1 0x1830
+#define mmDC_I2C_TRANSACTION2 0x1831
+#define mmDC_I2C_TRANSACTION3 0x1832
+#define mmDCI_CLK_CNTL 0x031E
+#define mmDCI_CLK_RAMP_CNTL 0x0324
+#define mmDCI_DEBUG_CONFIG 0x0323
+#define mmDCI_MEM_PWR_CNTL 0x0326
+#define mmDCI_MEM_PWR_STATE 0x031B
+#define mmDCI_MEM_PWR_STATE2 0x0322
+#define mmDCIO_DEBUG 0x192E
+#define mmDCIO_GSL0_CNTL 0x1924
+#define mmDCIO_GSL1_CNTL 0x1925
+#define mmDCIO_GSL2_CNTL 0x1926
+#define mmDCIO_GSL_GENLK_PAD_CNTL 0x1922
+#define mmDCIO_GSL_SWAPLOCK_PAD_CNTL 0x1923
+#define mmDCIO_IMPCAL_CNTL_AB 0x190D
+#define mmDCIO_IMPCAL_CNTL_CD 0x1911
+#define mmDCIO_IMPCAL_CNTL_EF 0x1915
+#define mmDCIO_TEST_DEBUG_DATA 0x1930
+#define mmDCIO_TEST_DEBUG_INDEX 0x192F
+#define mmDCIO_UNIPHY0_UNIPHY_ANG_BIST_CNTL 0x198C
+#define mmDCIO_UNIPHY0_UNIPHY_CHANNEL_XBAR_CNTL 0x198E
+#define mmDCIO_UNIPHY0_UNIPHY_DATA_SYNCHRONIZATION 0x198A
+#define mmDCIO_UNIPHY0_UNIPHY_LINK_CNTL 0x198D
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_CONTROL1 0x1986
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_CONTROL2 0x1987
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_FBDIV 0x1985
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_SS_CNTL 0x1989
+#define mmDCIO_UNIPHY0_UNIPHY_PLL_SS_STEP_SIZE 0x1988
+#define mmDCIO_UNIPHY0_UNIPHY_POWER_CONTROL 0x1984
+#define mmDCIO_UNIPHY0_UNIPHY_REG_TEST_OUTPUT 0x198B
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL1 0x1980
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL2 0x1981
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL3 0x1982
+#define mmDCIO_UNIPHY0_UNIPHY_TX_CONTROL4 0x1983
+#define mmDCIO_UNIPHY1_UNIPHY_ANG_BIST_CNTL 0x199C
+#define mmDCIO_UNIPHY1_UNIPHY_CHANNEL_XBAR_CNTL 0x199E
+#define mmDCIO_UNIPHY1_UNIPHY_DATA_SYNCHRONIZATION 0x199A
+#define mmDCIO_UNIPHY1_UNIPHY_LINK_CNTL 0x199D
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_CONTROL1 0x1996
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_CONTROL2 0x1997
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_FBDIV 0x1995
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_SS_CNTL 0x1999
+#define mmDCIO_UNIPHY1_UNIPHY_PLL_SS_STEP_SIZE 0x1998
+#define mmDCIO_UNIPHY1_UNIPHY_POWER_CONTROL 0x1994
+#define mmDCIO_UNIPHY1_UNIPHY_REG_TEST_OUTPUT 0x199B
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL1 0x1990
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL2 0x1991
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL3 0x1992
+#define mmDCIO_UNIPHY1_UNIPHY_TX_CONTROL4 0x1993
+#define mmDCIO_UNIPHY2_UNIPHY_ANG_BIST_CNTL 0x19AC
+#define mmDCIO_UNIPHY2_UNIPHY_CHANNEL_XBAR_CNTL 0x19AE
+#define mmDCIO_UNIPHY2_UNIPHY_DATA_SYNCHRONIZATION 0x19AA
+#define mmDCIO_UNIPHY2_UNIPHY_LINK_CNTL 0x19AD
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_CONTROL1 0x19A6
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_CONTROL2 0x19A7
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_FBDIV 0x19A5
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_SS_CNTL 0x19A9
+#define mmDCIO_UNIPHY2_UNIPHY_PLL_SS_STEP_SIZE 0x19A8
+#define mmDCIO_UNIPHY2_UNIPHY_POWER_CONTROL 0x19A4
+#define mmDCIO_UNIPHY2_UNIPHY_REG_TEST_OUTPUT 0x19AB
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL1 0x19A0
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL2 0x19A1
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL3 0x19A2
+#define mmDCIO_UNIPHY2_UNIPHY_TX_CONTROL4 0x19A3
+#define mmDCIO_UNIPHY3_UNIPHY_ANG_BIST_CNTL 0x19BC
+#define mmDCIO_UNIPHY3_UNIPHY_CHANNEL_XBAR_CNTL 0x19BE
+#define mmDCIO_UNIPHY3_UNIPHY_DATA_SYNCHRONIZATION 0x19BA
+#define mmDCIO_UNIPHY3_UNIPHY_LINK_CNTL 0x19BD
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_CONTROL1 0x19B6
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_CONTROL2 0x19B7
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_FBDIV 0x19B5
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_SS_CNTL 0x19B9
+#define mmDCIO_UNIPHY3_UNIPHY_PLL_SS_STEP_SIZE 0x19B8
+#define mmDCIO_UNIPHY3_UNIPHY_POWER_CONTROL 0x19B4
+#define mmDCIO_UNIPHY3_UNIPHY_REG_TEST_OUTPUT 0x19BB
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL1 0x19B0
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL2 0x19B1
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL3 0x19B2
+#define mmDCIO_UNIPHY3_UNIPHY_TX_CONTROL4 0x19B3
+#define mmDCIO_UNIPHY4_UNIPHY_ANG_BIST_CNTL 0x19CC
+#define mmDCIO_UNIPHY4_UNIPHY_CHANNEL_XBAR_CNTL 0x19CE
+#define mmDCIO_UNIPHY4_UNIPHY_DATA_SYNCHRONIZATION 0x19CA
+#define mmDCIO_UNIPHY4_UNIPHY_LINK_CNTL 0x19CD
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_CONTROL1 0x19C6
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_CONTROL2 0x19C7
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_FBDIV 0x19C5
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_SS_CNTL 0x19C9
+#define mmDCIO_UNIPHY4_UNIPHY_PLL_SS_STEP_SIZE 0x19C8
+#define mmDCIO_UNIPHY4_UNIPHY_POWER_CONTROL 0x19C4
+#define mmDCIO_UNIPHY4_UNIPHY_REG_TEST_OUTPUT 0x19CB
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL1 0x19C0
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL2 0x19C1
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL3 0x19C2
+#define mmDCIO_UNIPHY4_UNIPHY_TX_CONTROL4 0x19C3
+#define mmDCIO_UNIPHY5_UNIPHY_ANG_BIST_CNTL 0x19DC
+#define mmDCIO_UNIPHY5_UNIPHY_CHANNEL_XBAR_CNTL 0x19DE
+#define mmDCIO_UNIPHY5_UNIPHY_DATA_SYNCHRONIZATION 0x19DA
+#define mmDCIO_UNIPHY5_UNIPHY_LINK_CNTL 0x19DD
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_CONTROL1 0x19D6
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_CONTROL2 0x19D7
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_FBDIV 0x19D5
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_SS_CNTL 0x19D9
+#define mmDCIO_UNIPHY5_UNIPHY_PLL_SS_STEP_SIZE 0x19D8
+#define mmDCIO_UNIPHY5_UNIPHY_POWER_CONTROL 0x19D4
+#define mmDCIO_UNIPHY5_UNIPHY_REG_TEST_OUTPUT 0x19DB
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL1 0x19D0
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL2 0x19D1
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL3 0x19D2
+#define mmDCIO_UNIPHY5_UNIPHY_TX_CONTROL4 0x19D3
+#define mmDCI_SOFT_RESET 0x015E
+#define mmDCI_TEST_DEBUG_DATA 0x0321
+#define mmDCI_TEST_DEBUG_INDEX 0x0320
+#define mmDC_LUT_30_COLOR 0x1A7C
+#define mmDC_LUT_AUTOFILL 0x1A7F
+#define mmDC_LUT_BLACK_OFFSET_BLUE 0x1A81
+#define mmDC_LUT_BLACK_OFFSET_GREEN 0x1A82
+#define mmDC_LUT_BLACK_OFFSET_RED 0x1A83
+#define mmDC_LUT_CONTROL 0x1A80
+#define mmDC_LUT_PWL_DATA 0x1A7B
+#define mmDC_LUT_RW_INDEX 0x1A79
+#define mmDC_LUT_RW_MODE 0x1A78
+#define mmDC_LUT_SEQ_COLOR 0x1A7A
+#define mmDC_LUT_VGA_ACCESS_ENABLE 0x1A7D
+#define mmDC_LUT_WHITE_OFFSET_BLUE 0x1A84
+#define mmDC_LUT_WHITE_OFFSET_GREEN 0x1A85
+#define mmDC_LUT_WHITE_OFFSET_RED 0x1A86
+#define mmDC_LUT_WRITE_EN_MASK 0x1A7E
+#define mmDC_MVP_LB_CONTROL 0x1ADB
+#define mmDCO_CLK_CNTL 0x192B
+#define mmDCO_CLK_RAMP_CNTL 0x192C
+#define mmDCO_LIGHT_SLEEP_DIS 0x1907
+#define mmDCO_MEM_POWER_STATE 0x1906
+#define mmDCO_SOFT_RESET 0x0167
+#define mmDCP0_COMM_MATRIXA_TRANS_C11_C12 0x1A43
+#define mmDCP0_COMM_MATRIXA_TRANS_C13_C14 0x1A44
+#define mmDCP0_COMM_MATRIXA_TRANS_C21_C22 0x1A45
+#define mmDCP0_COMM_MATRIXA_TRANS_C23_C24 0x1A46
+#define mmDCP0_COMM_MATRIXA_TRANS_C31_C32 0x1A47
+#define mmDCP0_COMM_MATRIXA_TRANS_C33_C34 0x1A48
+#define mmDCP0_COMM_MATRIXB_TRANS_C11_C12 0x1A49
+#define mmDCP0_COMM_MATRIXB_TRANS_C13_C14 0x1A4A
+#define mmDCP0_COMM_MATRIXB_TRANS_C21_C22 0x1A4B
+#define mmDCP0_COMM_MATRIXB_TRANS_C23_C24 0x1A4C
+#define mmDCP0_COMM_MATRIXB_TRANS_C31_C32 0x1A4D
+#define mmDCP0_COMM_MATRIXB_TRANS_C33_C34 0x1A4E
+#define mmDCP0_CUR_COLOR1 0x1A6C
+#define mmDCP0_CUR_COLOR2 0x1A6D
+#define mmDCP0_CUR_CONTROL 0x1A66
+#define mmDCP0_CUR_HOT_SPOT 0x1A6B
+#define mmDCP0_CUR_POSITION 0x1A6A
+#define mmDCP0_CUR_REQUEST_FILTER_CNTL 0x1A99
+#define mmDCP0_CUR_SIZE 0x1A68
+#define mmDCP0_CUR_SURFACE_ADDRESS 0x1A67
+#define mmDCP0_CUR_SURFACE_ADDRESS_HIGH 0x1A69
+#define mmDCP0_CUR_UPDATE 0x1A6E
+#define mmDCP0_DC_LUT_30_COLOR 0x1A7C
+#define mmDCP0_DC_LUT_AUTOFILL 0x1A7F
+#define mmDCP0_DC_LUT_BLACK_OFFSET_BLUE 0x1A81
+#define mmDCP0_DC_LUT_BLACK_OFFSET_GREEN 0x1A82
+#define mmDCP0_DC_LUT_BLACK_OFFSET_RED 0x1A83
+#define mmDCP0_DC_LUT_CONTROL 0x1A80
+#define mmDCP0_DC_LUT_PWL_DATA 0x1A7B
+#define mmDCP0_DC_LUT_RW_INDEX 0x1A79
+#define mmDCP0_DC_LUT_RW_MODE 0x1A78
+#define mmDCP0_DC_LUT_SEQ_COLOR 0x1A7A
+#define mmDCP0_DC_LUT_VGA_ACCESS_ENABLE 0x1A7D
+#define mmDCP0_DC_LUT_WHITE_OFFSET_BLUE 0x1A84
+#define mmDCP0_DC_LUT_WHITE_OFFSET_GREEN 0x1A85
+#define mmDCP0_DC_LUT_WHITE_OFFSET_RED 0x1A86
+#define mmDCP0_DC_LUT_WRITE_EN_MASK 0x1A7E
+#define mmDCP0_DCP_CRC_CONTROL 0x1A87
+#define mmDCP0_DCP_CRC_CURRENT 0x1A89
+#define mmDCP0_DCP_CRC_LAST 0x1A8B
+#define mmDCP0_DCP_CRC_MASK 0x1A88
+#define mmDCP0_DCP_DEBUG 0x1A8D
+#define mmDCP0_DCP_DEBUG2 0x1A98
+#define mmDCP0_DCP_FP_CONVERTED_FIELD 0x1A65
+#define mmDCP0_DCP_GSL_CONTROL 0x1A90
+#define mmDCP0_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x1A91
+#define mmDCP0_DCP_RANDOM_SEEDS 0x1A61
+#define mmDCP0_DCP_SPATIAL_DITHER_CNTL 0x1A60
+#define mmDCP0_DCP_TEST_DEBUG_DATA 0x1A96
+#define mmDCP0_DCP_TEST_DEBUG_INDEX 0x1A95
+#define mmDCP0_DEGAMMA_CONTROL 0x1A58
+#define mmDCP0_DENORM_CONTROL 0x1A50
+#define mmDCP0_GAMUT_REMAP_C11_C12 0x1A5A
+#define mmDCP0_GAMUT_REMAP_C13_C14 0x1A5B
+#define mmDCP0_GAMUT_REMAP_C21_C22 0x1A5C
+#define mmDCP0_GAMUT_REMAP_C23_C24 0x1A5D
+#define mmDCP0_GAMUT_REMAP_C31_C32 0x1A5E
+#define mmDCP0_GAMUT_REMAP_C33_C34 0x1A5F
+#define mmDCP0_GAMUT_REMAP_CONTROL 0x1A59
+#define mmDCP0_GRPH_COMPRESS_PITCH 0x1A1A
+#define mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS 0x1A19
+#define mmDCP0_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x1A1B
+#define mmDCP0_GRPH_CONTROL 0x1A01
+#define mmDCP0_GRPH_DFQ_CONTROL 0x1A14
+#define mmDCP0_GRPH_DFQ_STATUS 0x1A15
+#define mmDCP0_GRPH_ENABLE 0x1A00
+#define mmDCP0_GRPH_FLIP_CONTROL 0x1A12
+#define mmDCP0_GRPH_INTERRUPT_CONTROL 0x1A17
+#define mmDCP0_GRPH_INTERRUPT_STATUS 0x1A16
+#define mmDCP0_GRPH_LUT_10BIT_BYPASS 0x1A02
+#define mmDCP0_GRPH_PITCH 0x1A06
+#define mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS 0x1A04
+#define mmDCP0_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1A07
+#define mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS 0x1A05
+#define mmDCP0_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A08
+#define mmDCP0_GRPH_STEREOSYNC_FLIP 0x1A97
+#define mmDCP0_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x1A18
+#define mmDCP0_GRPH_SURFACE_ADDRESS_INUSE 0x1A13
+#define mmDCP0_GRPH_SURFACE_OFFSET_X 0x1A09
+#define mmDCP0_GRPH_SURFACE_OFFSET_Y 0x1A0A
+#define mmDCP0_GRPH_SWAP_CNTL 0x1A03
+#define mmDCP0_GRPH_UPDATE 0x1A11
+#define mmDCP0_GRPH_X_END 0x1A0D
+#define mmDCP0_GRPH_X_START 0x1A0B
+#define mmDCP0_GRPH_Y_END 0x1A0E
+#define mmDCP0_GRPH_Y_START 0x1A0C
+#define mmDCP0_INPUT_CSC_C11_C12 0x1A36
+#define mmDCP0_INPUT_CSC_C13_C14 0x1A37
+#define mmDCP0_INPUT_CSC_C21_C22 0x1A38
+#define mmDCP0_INPUT_CSC_C23_C24 0x1A39
+#define mmDCP0_INPUT_CSC_C31_C32 0x1A3A
+#define mmDCP0_INPUT_CSC_C33_C34 0x1A3B
+#define mmDCP0_INPUT_CSC_CONTROL 0x1A35
+#define mmDCP0_INPUT_GAMMA_CONTROL 0x1A10
+#define mmDCP0_KEY_CONTROL 0x1A53
+#define mmDCP0_KEY_RANGE_ALPHA 0x1A54
+#define mmDCP0_KEY_RANGE_BLUE 0x1A57
+#define mmDCP0_KEY_RANGE_GREEN 0x1A56
+#define mmDCP0_KEY_RANGE_RED 0x1A55
+#define mmDCP0_OUTPUT_CSC_C11_C12 0x1A3D
+#define mmDCP0_OUTPUT_CSC_C13_C14 0x1A3E
+#define mmDCP0_OUTPUT_CSC_C21_C22 0x1A3F
+#define mmDCP0_OUTPUT_CSC_C23_C24 0x1A40
+#define mmDCP0_OUTPUT_CSC_C31_C32 0x1A41
+#define mmDCP0_OUTPUT_CSC_C33_C34 0x1A42
+#define mmDCP0_OUTPUT_CSC_CONTROL 0x1A3C
+#define mmDCP0_OUT_ROUND_CONTROL 0x1A51
+#define mmDCP0_OVL_CONTROL1 0x1A1D
+#define mmDCP0_OVL_CONTROL2 0x1A1E
+#define mmDCP0_OVL_DFQ_CONTROL 0x1A29
+#define mmDCP0_OVL_DFQ_STATUS 0x1A2A
+#define mmDCP0_OVL_ENABLE 0x1A1C
+#define mmDCP0_OVL_END 0x1A26
+#define mmDCP0_OVL_PITCH 0x1A21
+#define mmDCP0_OVLSCL_EDGE_PIXEL_CNTL 0x1A2C
+#define mmDCP0_OVL_SECONDARY_SURFACE_ADDRESS 0x1A92
+#define mmDCP0_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A94
+#define mmDCP0_OVL_START 0x1A25
+#define mmDCP0_OVL_STEREOSYNC_FLIP 0x1A93
+#define mmDCP0_OVL_SURFACE_ADDRESS 0x1A20
+#define mmDCP0_OVL_SURFACE_ADDRESS_HIGH 0x1A22
+#define mmDCP0_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x1A2B
+#define mmDCP0_OVL_SURFACE_ADDRESS_INUSE 0x1A28
+#define mmDCP0_OVL_SURFACE_OFFSET_X 0x1A23
+#define mmDCP0_OVL_SURFACE_OFFSET_Y 0x1A24
+#define mmDCP0_OVL_SWAP_CNTL 0x1A1F
+#define mmDCP0_OVL_UPDATE 0x1A27
+#define mmDCP0_PRESCALE_GRPH_CONTROL 0x1A2D
+#define mmDCP0_PRESCALE_OVL_CONTROL 0x1A31
+#define mmDCP0_PRESCALE_VALUES_GRPH_B 0x1A30
+#define mmDCP0_PRESCALE_VALUES_GRPH_G 0x1A2F
+#define mmDCP0_PRESCALE_VALUES_GRPH_R 0x1A2E
+#define mmDCP0_PRESCALE_VALUES_OVL_CB 0x1A32
+#define mmDCP0_PRESCALE_VALUES_OVL_CR 0x1A34
+#define mmDCP0_PRESCALE_VALUES_OVL_Y 0x1A33
+#define mmDCP0_REGAMMA_CNTLA_END_CNTL1 0x1AA6
+#define mmDCP0_REGAMMA_CNTLA_END_CNTL2 0x1AA7
+#define mmDCP0_REGAMMA_CNTLA_REGION_0_1 0x1AA8
+#define mmDCP0_REGAMMA_CNTLA_REGION_10_11 0x1AAD
+#define mmDCP0_REGAMMA_CNTLA_REGION_12_13 0x1AAE
+#define mmDCP0_REGAMMA_CNTLA_REGION_14_15 0x1AAF
+#define mmDCP0_REGAMMA_CNTLA_REGION_2_3 0x1AA9
+#define mmDCP0_REGAMMA_CNTLA_REGION_4_5 0x1AAA
+#define mmDCP0_REGAMMA_CNTLA_REGION_6_7 0x1AAB
+#define mmDCP0_REGAMMA_CNTLA_REGION_8_9 0x1AAC
+#define mmDCP0_REGAMMA_CNTLA_SLOPE_CNTL 0x1AA5
+#define mmDCP0_REGAMMA_CNTLA_START_CNTL 0x1AA4
+#define mmDCP0_REGAMMA_CNTLB_END_CNTL1 0x1AB2
+#define mmDCP0_REGAMMA_CNTLB_END_CNTL2 0x1AB3
+#define mmDCP0_REGAMMA_CNTLB_REGION_0_1 0x1AB4
+#define mmDCP0_REGAMMA_CNTLB_REGION_10_11 0x1AB9
+#define mmDCP0_REGAMMA_CNTLB_REGION_12_13 0x1ABA
+#define mmDCP0_REGAMMA_CNTLB_REGION_14_15 0x1ABB
+#define mmDCP0_REGAMMA_CNTLB_REGION_2_3 0x1AB5
+#define mmDCP0_REGAMMA_CNTLB_REGION_4_5 0x1AB6
+#define mmDCP0_REGAMMA_CNTLB_REGION_6_7 0x1AB7
+#define mmDCP0_REGAMMA_CNTLB_REGION_8_9 0x1AB8
+#define mmDCP0_REGAMMA_CNTLB_SLOPE_CNTL 0x1AB1
+#define mmDCP0_REGAMMA_CNTLB_START_CNTL 0x1AB0
+#define mmDCP0_REGAMMA_CONTROL 0x1AA0
+#define mmDCP0_REGAMMA_LUT_DATA 0x1AA2
+#define mmDCP0_REGAMMA_LUT_INDEX 0x1AA1
+#define mmDCP0_REGAMMA_LUT_WRITE_EN_MASK 0x1AA3
+#define mmDCP1_COMM_MATRIXA_TRANS_C11_C12 0x1D43
+#define mmDCP1_COMM_MATRIXA_TRANS_C13_C14 0x1D44
+#define mmDCP1_COMM_MATRIXA_TRANS_C21_C22 0x1D45
+#define mmDCP1_COMM_MATRIXA_TRANS_C23_C24 0x1D46
+#define mmDCP1_COMM_MATRIXA_TRANS_C31_C32 0x1D47
+#define mmDCP1_COMM_MATRIXA_TRANS_C33_C34 0x1D48
+#define mmDCP1_COMM_MATRIXB_TRANS_C11_C12 0x1D49
+#define mmDCP1_COMM_MATRIXB_TRANS_C13_C14 0x1D4A
+#define mmDCP1_COMM_MATRIXB_TRANS_C21_C22 0x1D4B
+#define mmDCP1_COMM_MATRIXB_TRANS_C23_C24 0x1D4C
+#define mmDCP1_COMM_MATRIXB_TRANS_C31_C32 0x1D4D
+#define mmDCP1_COMM_MATRIXB_TRANS_C33_C34 0x1D4E
+#define mmDCP1_CUR_COLOR1 0x1D6C
+#define mmDCP1_CUR_COLOR2 0x1D6D
+#define mmDCP1_CUR_CONTROL 0x1D66
+#define mmDCP1_CUR_HOT_SPOT 0x1D6B
+#define mmDCP1_CUR_POSITION 0x1D6A
+#define mmDCP1_CUR_REQUEST_FILTER_CNTL 0x1D99
+#define mmDCP1_CUR_SIZE 0x1D68
+#define mmDCP1_CUR_SURFACE_ADDRESS 0x1D67
+#define mmDCP1_CUR_SURFACE_ADDRESS_HIGH 0x1D69
+#define mmDCP1_CUR_UPDATE 0x1D6E
+#define mmDCP1_DC_LUT_30_COLOR 0x1D7C
+#define mmDCP1_DC_LUT_AUTOFILL 0x1D7F
+#define mmDCP1_DC_LUT_BLACK_OFFSET_BLUE 0x1D81
+#define mmDCP1_DC_LUT_BLACK_OFFSET_GREEN 0x1D82
+#define mmDCP1_DC_LUT_BLACK_OFFSET_RED 0x1D83
+#define mmDCP1_DC_LUT_CONTROL 0x1D80
+#define mmDCP1_DC_LUT_PWL_DATA 0x1D7B
+#define mmDCP1_DC_LUT_RW_INDEX 0x1D79
+#define mmDCP1_DC_LUT_RW_MODE 0x1D78
+#define mmDCP1_DC_LUT_SEQ_COLOR 0x1D7A
+#define mmDCP1_DC_LUT_VGA_ACCESS_ENABLE 0x1D7D
+#define mmDCP1_DC_LUT_WHITE_OFFSET_BLUE 0x1D84
+#define mmDCP1_DC_LUT_WHITE_OFFSET_GREEN 0x1D85
+#define mmDCP1_DC_LUT_WHITE_OFFSET_RED 0x1D86
+#define mmDCP1_DC_LUT_WRITE_EN_MASK 0x1D7E
+#define mmDCP1_DCP_CRC_CONTROL 0x1D87
+#define mmDCP1_DCP_CRC_CURRENT 0x1D89
+#define mmDCP1_DCP_CRC_LAST 0x1D8B
+#define mmDCP1_DCP_CRC_MASK 0x1D88
+#define mmDCP1_DCP_DEBUG 0x1D8D
+#define mmDCP1_DCP_DEBUG2 0x1D98
+#define mmDCP1_DCP_FP_CONVERTED_FIELD 0x1D65
+#define mmDCP1_DCP_GSL_CONTROL 0x1D90
+#define mmDCP1_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x1D91
+#define mmDCP1_DCP_RANDOM_SEEDS 0x1D61
+#define mmDCP1_DCP_SPATIAL_DITHER_CNTL 0x1D60
+#define mmDCP1_DCP_TEST_DEBUG_DATA 0x1D96
+#define mmDCP1_DCP_TEST_DEBUG_INDEX 0x1D95
+#define mmDCP1_DEGAMMA_CONTROL 0x1D58
+#define mmDCP1_DENORM_CONTROL 0x1D50
+#define mmDCP1_GAMUT_REMAP_C11_C12 0x1D5A
+#define mmDCP1_GAMUT_REMAP_C13_C14 0x1D5B
+#define mmDCP1_GAMUT_REMAP_C21_C22 0x1D5C
+#define mmDCP1_GAMUT_REMAP_C23_C24 0x1D5D
+#define mmDCP1_GAMUT_REMAP_C31_C32 0x1D5E
+#define mmDCP1_GAMUT_REMAP_C33_C34 0x1D5F
+#define mmDCP1_GAMUT_REMAP_CONTROL 0x1D59
+#define mmDCP1_GRPH_COMPRESS_PITCH 0x1D1A
+#define mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS 0x1D19
+#define mmDCP1_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x1D1B
+#define mmDCP1_GRPH_CONTROL 0x1D01
+#define mmDCP1_GRPH_DFQ_CONTROL 0x1D14
+#define mmDCP1_GRPH_DFQ_STATUS 0x1D15
+#define mmDCP1_GRPH_ENABLE 0x1D00
+#define mmDCP1_GRPH_FLIP_CONTROL 0x1D12
+#define mmDCP1_GRPH_INTERRUPT_CONTROL 0x1D17
+#define mmDCP1_GRPH_INTERRUPT_STATUS 0x1D16
+#define mmDCP1_GRPH_LUT_10BIT_BYPASS 0x1D02
+#define mmDCP1_GRPH_PITCH 0x1D06
+#define mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS 0x1D04
+#define mmDCP1_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1D07
+#define mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS 0x1D05
+#define mmDCP1_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1D08
+#define mmDCP1_GRPH_STEREOSYNC_FLIP 0x1D97
+#define mmDCP1_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x1D18
+#define mmDCP1_GRPH_SURFACE_ADDRESS_INUSE 0x1D13
+#define mmDCP1_GRPH_SURFACE_OFFSET_X 0x1D09
+#define mmDCP1_GRPH_SURFACE_OFFSET_Y 0x1D0A
+#define mmDCP1_GRPH_SWAP_CNTL 0x1D03
+#define mmDCP1_GRPH_UPDATE 0x1D11
+#define mmDCP1_GRPH_X_END 0x1D0D
+#define mmDCP1_GRPH_X_START 0x1D0B
+#define mmDCP1_GRPH_Y_END 0x1D0E
+#define mmDCP1_GRPH_Y_START 0x1D0C
+#define mmDCP1_INPUT_CSC_C11_C12 0x1D36
+#define mmDCP1_INPUT_CSC_C13_C14 0x1D37
+#define mmDCP1_INPUT_CSC_C21_C22 0x1D38
+#define mmDCP1_INPUT_CSC_C23_C24 0x1D39
+#define mmDCP1_INPUT_CSC_C31_C32 0x1D3A
+#define mmDCP1_INPUT_CSC_C33_C34 0x1D3B
+#define mmDCP1_INPUT_CSC_CONTROL 0x1D35
+#define mmDCP1_INPUT_GAMMA_CONTROL 0x1D10
+#define mmDCP1_KEY_CONTROL 0x1D53
+#define mmDCP1_KEY_RANGE_ALPHA 0x1D54
+#define mmDCP1_KEY_RANGE_BLUE 0x1D57
+#define mmDCP1_KEY_RANGE_GREEN 0x1D56
+#define mmDCP1_KEY_RANGE_RED 0x1D55
+#define mmDCP1_OUTPUT_CSC_C11_C12 0x1D3D
+#define mmDCP1_OUTPUT_CSC_C13_C14 0x1D3E
+#define mmDCP1_OUTPUT_CSC_C21_C22 0x1D3F
+#define mmDCP1_OUTPUT_CSC_C23_C24 0x1D40
+#define mmDCP1_OUTPUT_CSC_C31_C32 0x1D41
+#define mmDCP1_OUTPUT_CSC_C33_C34 0x1D42
+#define mmDCP1_OUTPUT_CSC_CONTROL 0x1D3C
+#define mmDCP1_OUT_ROUND_CONTROL 0x1D51
+#define mmDCP1_OVL_CONTROL1 0x1D1D
+#define mmDCP1_OVL_CONTROL2 0x1D1E
+#define mmDCP1_OVL_DFQ_CONTROL 0x1D29
+#define mmDCP1_OVL_DFQ_STATUS 0x1D2A
+#define mmDCP1_OVL_ENABLE 0x1D1C
+#define mmDCP1_OVL_END 0x1D26
+#define mmDCP1_OVL_PITCH 0x1D21
+#define mmDCP1_OVLSCL_EDGE_PIXEL_CNTL 0x1D2C
+#define mmDCP1_OVL_SECONDARY_SURFACE_ADDRESS 0x1D92
+#define mmDCP1_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x1D94
+#define mmDCP1_OVL_START 0x1D25
+#define mmDCP1_OVL_STEREOSYNC_FLIP 0x1D93
+#define mmDCP1_OVL_SURFACE_ADDRESS 0x1D20
+#define mmDCP1_OVL_SURFACE_ADDRESS_HIGH 0x1D22
+#define mmDCP1_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x1D2B
+#define mmDCP1_OVL_SURFACE_ADDRESS_INUSE 0x1D28
+#define mmDCP1_OVL_SURFACE_OFFSET_X 0x1D23
+#define mmDCP1_OVL_SURFACE_OFFSET_Y 0x1D24
+#define mmDCP1_OVL_SWAP_CNTL 0x1D1F
+#define mmDCP1_OVL_UPDATE 0x1D27
+#define mmDCP1_PRESCALE_GRPH_CONTROL 0x1D2D
+#define mmDCP1_PRESCALE_OVL_CONTROL 0x1D31
+#define mmDCP1_PRESCALE_VALUES_GRPH_B 0x1D30
+#define mmDCP1_PRESCALE_VALUES_GRPH_G 0x1D2F
+#define mmDCP1_PRESCALE_VALUES_GRPH_R 0x1D2E
+#define mmDCP1_PRESCALE_VALUES_OVL_CB 0x1D32
+#define mmDCP1_PRESCALE_VALUES_OVL_CR 0x1D34
+#define mmDCP1_PRESCALE_VALUES_OVL_Y 0x1D33
+#define mmDCP1_REGAMMA_CNTLA_END_CNTL1 0x1DA6
+#define mmDCP1_REGAMMA_CNTLA_END_CNTL2 0x1DA7
+#define mmDCP1_REGAMMA_CNTLA_REGION_0_1 0x1DA8
+#define mmDCP1_REGAMMA_CNTLA_REGION_10_11 0x1DAD
+#define mmDCP1_REGAMMA_CNTLA_REGION_12_13 0x1DAE
+#define mmDCP1_REGAMMA_CNTLA_REGION_14_15 0x1DAF
+#define mmDCP1_REGAMMA_CNTLA_REGION_2_3 0x1DA9
+#define mmDCP1_REGAMMA_CNTLA_REGION_4_5 0x1DAA
+#define mmDCP1_REGAMMA_CNTLA_REGION_6_7 0x1DAB
+#define mmDCP1_REGAMMA_CNTLA_REGION_8_9 0x1DAC
+#define mmDCP1_REGAMMA_CNTLA_SLOPE_CNTL 0x1DA5
+#define mmDCP1_REGAMMA_CNTLA_START_CNTL 0x1DA4
+#define mmDCP1_REGAMMA_CNTLB_END_CNTL1 0x1DB2
+#define mmDCP1_REGAMMA_CNTLB_END_CNTL2 0x1DB3
+#define mmDCP1_REGAMMA_CNTLB_REGION_0_1 0x1DB4
+#define mmDCP1_REGAMMA_CNTLB_REGION_10_11 0x1DB9
+#define mmDCP1_REGAMMA_CNTLB_REGION_12_13 0x1DBA
+#define mmDCP1_REGAMMA_CNTLB_REGION_14_15 0x1DBB
+#define mmDCP1_REGAMMA_CNTLB_REGION_2_3 0x1DB5
+#define mmDCP1_REGAMMA_CNTLB_REGION_4_5 0x1DB6
+#define mmDCP1_REGAMMA_CNTLB_REGION_6_7 0x1DB7
+#define mmDCP1_REGAMMA_CNTLB_REGION_8_9 0x1DB8
+#define mmDCP1_REGAMMA_CNTLB_SLOPE_CNTL 0x1DB1
+#define mmDCP1_REGAMMA_CNTLB_START_CNTL 0x1DB0
+#define mmDCP1_REGAMMA_CONTROL 0x1DA0
+#define mmDCP1_REGAMMA_LUT_DATA 0x1DA2
+#define mmDCP1_REGAMMA_LUT_INDEX 0x1DA1
+#define mmDCP1_REGAMMA_LUT_WRITE_EN_MASK 0x1DA3
+#define mmDCP2_COMM_MATRIXA_TRANS_C11_C12 0x4043
+#define mmDCP2_COMM_MATRIXA_TRANS_C13_C14 0x4044
+#define mmDCP2_COMM_MATRIXA_TRANS_C21_C22 0x4045
+#define mmDCP2_COMM_MATRIXA_TRANS_C23_C24 0x4046
+#define mmDCP2_COMM_MATRIXA_TRANS_C31_C32 0x4047
+#define mmDCP2_COMM_MATRIXA_TRANS_C33_C34 0x4048
+#define mmDCP2_COMM_MATRIXB_TRANS_C11_C12 0x4049
+#define mmDCP2_COMM_MATRIXB_TRANS_C13_C14 0x404A
+#define mmDCP2_COMM_MATRIXB_TRANS_C21_C22 0x404B
+#define mmDCP2_COMM_MATRIXB_TRANS_C23_C24 0x404C
+#define mmDCP2_COMM_MATRIXB_TRANS_C31_C32 0x404D
+#define mmDCP2_COMM_MATRIXB_TRANS_C33_C34 0x404E
+#define mmDCP2_CUR_COLOR1 0x406C
+#define mmDCP2_CUR_COLOR2 0x406D
+#define mmDCP2_CUR_CONTROL 0x4066
+#define mmDCP2_CUR_HOT_SPOT 0x406B
+#define mmDCP2_CUR_POSITION 0x406A
+#define mmDCP2_CUR_REQUEST_FILTER_CNTL 0x4099
+#define mmDCP2_CUR_SIZE 0x4068
+#define mmDCP2_CUR_SURFACE_ADDRESS 0x4067
+#define mmDCP2_CUR_SURFACE_ADDRESS_HIGH 0x4069
+#define mmDCP2_CUR_UPDATE 0x406E
+#define mmDCP2_DC_LUT_30_COLOR 0x407C
+#define mmDCP2_DC_LUT_AUTOFILL 0x407F
+#define mmDCP2_DC_LUT_BLACK_OFFSET_BLUE 0x4081
+#define mmDCP2_DC_LUT_BLACK_OFFSET_GREEN 0x4082
+#define mmDCP2_DC_LUT_BLACK_OFFSET_RED 0x4083
+#define mmDCP2_DC_LUT_CONTROL 0x4080
+#define mmDCP2_DC_LUT_PWL_DATA 0x407B
+#define mmDCP2_DC_LUT_RW_INDEX 0x4079
+#define mmDCP2_DC_LUT_RW_MODE 0x4078
+#define mmDCP2_DC_LUT_SEQ_COLOR 0x407A
+#define mmDCP2_DC_LUT_VGA_ACCESS_ENABLE 0x407D
+#define mmDCP2_DC_LUT_WHITE_OFFSET_BLUE 0x4084
+#define mmDCP2_DC_LUT_WHITE_OFFSET_GREEN 0x4085
+#define mmDCP2_DC_LUT_WHITE_OFFSET_RED 0x4086
+#define mmDCP2_DC_LUT_WRITE_EN_MASK 0x407E
+#define mmDCP2_DCP_CRC_CONTROL 0x4087
+#define mmDCP2_DCP_CRC_CURRENT 0x4089
+#define mmDCP2_DCP_CRC_LAST 0x408B
+#define mmDCP2_DCP_CRC_MASK 0x4088
+#define mmDCP2_DCP_DEBUG 0x408D
+#define mmDCP2_DCP_DEBUG2 0x4098
+#define mmDCP2_DCP_FP_CONVERTED_FIELD 0x4065
+#define mmDCP2_DCP_GSL_CONTROL 0x4090
+#define mmDCP2_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4091
+#define mmDCP2_DCP_RANDOM_SEEDS 0x4061
+#define mmDCP2_DCP_SPATIAL_DITHER_CNTL 0x4060
+#define mmDCP2_DCP_TEST_DEBUG_DATA 0x4096
+#define mmDCP2_DCP_TEST_DEBUG_INDEX 0x4095
+#define mmDCP2_DEGAMMA_CONTROL 0x4058
+#define mmDCP2_DENORM_CONTROL 0x4050
+#define mmDCP2_GAMUT_REMAP_C11_C12 0x405A
+#define mmDCP2_GAMUT_REMAP_C13_C14 0x405B
+#define mmDCP2_GAMUT_REMAP_C21_C22 0x405C
+#define mmDCP2_GAMUT_REMAP_C23_C24 0x405D
+#define mmDCP2_GAMUT_REMAP_C31_C32 0x405E
+#define mmDCP2_GAMUT_REMAP_C33_C34 0x405F
+#define mmDCP2_GAMUT_REMAP_CONTROL 0x4059
+#define mmDCP2_GRPH_COMPRESS_PITCH 0x401A
+#define mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS 0x4019
+#define mmDCP2_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x401B
+#define mmDCP2_GRPH_CONTROL 0x4001
+#define mmDCP2_GRPH_DFQ_CONTROL 0x4014
+#define mmDCP2_GRPH_DFQ_STATUS 0x4015
+#define mmDCP2_GRPH_ENABLE 0x4000
+#define mmDCP2_GRPH_FLIP_CONTROL 0x4012
+#define mmDCP2_GRPH_INTERRUPT_CONTROL 0x4017
+#define mmDCP2_GRPH_INTERRUPT_STATUS 0x4016
+#define mmDCP2_GRPH_LUT_10BIT_BYPASS 0x4002
+#define mmDCP2_GRPH_PITCH 0x4006
+#define mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS 0x4004
+#define mmDCP2_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4007
+#define mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS 0x4005
+#define mmDCP2_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4008
+#define mmDCP2_GRPH_STEREOSYNC_FLIP 0x4097
+#define mmDCP2_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4018
+#define mmDCP2_GRPH_SURFACE_ADDRESS_INUSE 0x4013
+#define mmDCP2_GRPH_SURFACE_OFFSET_X 0x4009
+#define mmDCP2_GRPH_SURFACE_OFFSET_Y 0x400A
+#define mmDCP2_GRPH_SWAP_CNTL 0x4003
+#define mmDCP2_GRPH_UPDATE 0x4011
+#define mmDCP2_GRPH_X_END 0x400D
+#define mmDCP2_GRPH_X_START 0x400B
+#define mmDCP2_GRPH_Y_END 0x400E
+#define mmDCP2_GRPH_Y_START 0x400C
+#define mmDCP2_INPUT_CSC_C11_C12 0x4036
+#define mmDCP2_INPUT_CSC_C13_C14 0x4037
+#define mmDCP2_INPUT_CSC_C21_C22 0x4038
+#define mmDCP2_INPUT_CSC_C23_C24 0x4039
+#define mmDCP2_INPUT_CSC_C31_C32 0x403A
+#define mmDCP2_INPUT_CSC_C33_C34 0x403B
+#define mmDCP2_INPUT_CSC_CONTROL 0x4035
+#define mmDCP2_INPUT_GAMMA_CONTROL 0x4010
+#define mmDCP2_KEY_CONTROL 0x4053
+#define mmDCP2_KEY_RANGE_ALPHA 0x4054
+#define mmDCP2_KEY_RANGE_BLUE 0x4057
+#define mmDCP2_KEY_RANGE_GREEN 0x4056
+#define mmDCP2_KEY_RANGE_RED 0x4055
+#define mmDCP2_OUTPUT_CSC_C11_C12 0x403D
+#define mmDCP2_OUTPUT_CSC_C13_C14 0x403E
+#define mmDCP2_OUTPUT_CSC_C21_C22 0x403F
+#define mmDCP2_OUTPUT_CSC_C23_C24 0x4040
+#define mmDCP2_OUTPUT_CSC_C31_C32 0x4041
+#define mmDCP2_OUTPUT_CSC_C33_C34 0x4042
+#define mmDCP2_OUTPUT_CSC_CONTROL 0x403C
+#define mmDCP2_OUT_ROUND_CONTROL 0x4051
+#define mmDCP2_OVL_CONTROL1 0x401D
+#define mmDCP2_OVL_CONTROL2 0x401E
+#define mmDCP2_OVL_DFQ_CONTROL 0x4029
+#define mmDCP2_OVL_DFQ_STATUS 0x402A
+#define mmDCP2_OVL_ENABLE 0x401C
+#define mmDCP2_OVL_END 0x4026
+#define mmDCP2_OVL_PITCH 0x4021
+#define mmDCP2_OVLSCL_EDGE_PIXEL_CNTL 0x402C
+#define mmDCP2_OVL_SECONDARY_SURFACE_ADDRESS 0x4092
+#define mmDCP2_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4094
+#define mmDCP2_OVL_START 0x4025
+#define mmDCP2_OVL_STEREOSYNC_FLIP 0x4093
+#define mmDCP2_OVL_SURFACE_ADDRESS 0x4020
+#define mmDCP2_OVL_SURFACE_ADDRESS_HIGH 0x4022
+#define mmDCP2_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x402B
+#define mmDCP2_OVL_SURFACE_ADDRESS_INUSE 0x4028
+#define mmDCP2_OVL_SURFACE_OFFSET_X 0x4023
+#define mmDCP2_OVL_SURFACE_OFFSET_Y 0x4024
+#define mmDCP2_OVL_SWAP_CNTL 0x401F
+#define mmDCP2_OVL_UPDATE 0x4027
+#define mmDCP2_PRESCALE_GRPH_CONTROL 0x402D
+#define mmDCP2_PRESCALE_OVL_CONTROL 0x4031
+#define mmDCP2_PRESCALE_VALUES_GRPH_B 0x4030
+#define mmDCP2_PRESCALE_VALUES_GRPH_G 0x402F
+#define mmDCP2_PRESCALE_VALUES_GRPH_R 0x402E
+#define mmDCP2_PRESCALE_VALUES_OVL_CB 0x4032
+#define mmDCP2_PRESCALE_VALUES_OVL_CR 0x4034
+#define mmDCP2_PRESCALE_VALUES_OVL_Y 0x4033
+#define mmDCP2_REGAMMA_CNTLA_END_CNTL1 0x40A6
+#define mmDCP2_REGAMMA_CNTLA_END_CNTL2 0x40A7
+#define mmDCP2_REGAMMA_CNTLA_REGION_0_1 0x40A8
+#define mmDCP2_REGAMMA_CNTLA_REGION_10_11 0x40AD
+#define mmDCP2_REGAMMA_CNTLA_REGION_12_13 0x40AE
+#define mmDCP2_REGAMMA_CNTLA_REGION_14_15 0x40AF
+#define mmDCP2_REGAMMA_CNTLA_REGION_2_3 0x40A9
+#define mmDCP2_REGAMMA_CNTLA_REGION_4_5 0x40AA
+#define mmDCP2_REGAMMA_CNTLA_REGION_6_7 0x40AB
+#define mmDCP2_REGAMMA_CNTLA_REGION_8_9 0x40AC
+#define mmDCP2_REGAMMA_CNTLA_SLOPE_CNTL 0x40A5
+#define mmDCP2_REGAMMA_CNTLA_START_CNTL 0x40A4
+#define mmDCP2_REGAMMA_CNTLB_END_CNTL1 0x40B2
+#define mmDCP2_REGAMMA_CNTLB_END_CNTL2 0x40B3
+#define mmDCP2_REGAMMA_CNTLB_REGION_0_1 0x40B4
+#define mmDCP2_REGAMMA_CNTLB_REGION_10_11 0x40B9
+#define mmDCP2_REGAMMA_CNTLB_REGION_12_13 0x40BA
+#define mmDCP2_REGAMMA_CNTLB_REGION_14_15 0x40BB
+#define mmDCP2_REGAMMA_CNTLB_REGION_2_3 0x40B5
+#define mmDCP2_REGAMMA_CNTLB_REGION_4_5 0x40B6
+#define mmDCP2_REGAMMA_CNTLB_REGION_6_7 0x40B7
+#define mmDCP2_REGAMMA_CNTLB_REGION_8_9 0x40B8
+#define mmDCP2_REGAMMA_CNTLB_SLOPE_CNTL 0x40B1
+#define mmDCP2_REGAMMA_CNTLB_START_CNTL 0x40B0
+#define mmDCP2_REGAMMA_CONTROL 0x40A0
+#define mmDCP2_REGAMMA_LUT_DATA 0x40A2
+#define mmDCP2_REGAMMA_LUT_INDEX 0x40A1
+#define mmDCP2_REGAMMA_LUT_WRITE_EN_MASK 0x40A3
+#define mmDCP3_COMM_MATRIXA_TRANS_C11_C12 0x4343
+#define mmDCP3_COMM_MATRIXA_TRANS_C13_C14 0x4344
+#define mmDCP3_COMM_MATRIXA_TRANS_C21_C22 0x4345
+#define mmDCP3_COMM_MATRIXA_TRANS_C23_C24 0x4346
+#define mmDCP3_COMM_MATRIXA_TRANS_C31_C32 0x4347
+#define mmDCP3_COMM_MATRIXA_TRANS_C33_C34 0x4348
+#define mmDCP3_COMM_MATRIXB_TRANS_C11_C12 0x4349
+#define mmDCP3_COMM_MATRIXB_TRANS_C13_C14 0x434A
+#define mmDCP3_COMM_MATRIXB_TRANS_C21_C22 0x434B
+#define mmDCP3_COMM_MATRIXB_TRANS_C23_C24 0x434C
+#define mmDCP3_COMM_MATRIXB_TRANS_C31_C32 0x434D
+#define mmDCP3_COMM_MATRIXB_TRANS_C33_C34 0x434E
+#define mmDCP3_CUR_COLOR1 0x436C
+#define mmDCP3_CUR_COLOR2 0x436D
+#define mmDCP3_CUR_CONTROL 0x4366
+#define mmDCP3_CUR_HOT_SPOT 0x436B
+#define mmDCP3_CUR_POSITION 0x436A
+#define mmDCP3_CUR_REQUEST_FILTER_CNTL 0x4399
+#define mmDCP3_CUR_SIZE 0x4368
+#define mmDCP3_CUR_SURFACE_ADDRESS 0x4367
+#define mmDCP3_CUR_SURFACE_ADDRESS_HIGH 0x4369
+#define mmDCP3_CUR_UPDATE 0x436E
+#define mmDCP3_DC_LUT_30_COLOR 0x437C
+#define mmDCP3_DC_LUT_AUTOFILL 0x437F
+#define mmDCP3_DC_LUT_BLACK_OFFSET_BLUE 0x4381
+#define mmDCP3_DC_LUT_BLACK_OFFSET_GREEN 0x4382
+#define mmDCP3_DC_LUT_BLACK_OFFSET_RED 0x4383
+#define mmDCP3_DC_LUT_CONTROL 0x4380
+#define mmDCP3_DC_LUT_PWL_DATA 0x437B
+#define mmDCP3_DC_LUT_RW_INDEX 0x4379
+#define mmDCP3_DC_LUT_RW_MODE 0x4378
+#define mmDCP3_DC_LUT_SEQ_COLOR 0x437A
+#define mmDCP3_DC_LUT_VGA_ACCESS_ENABLE 0x437D
+#define mmDCP3_DC_LUT_WHITE_OFFSET_BLUE 0x4384
+#define mmDCP3_DC_LUT_WHITE_OFFSET_GREEN 0x4385
+#define mmDCP3_DC_LUT_WHITE_OFFSET_RED 0x4386
+#define mmDCP3_DC_LUT_WRITE_EN_MASK 0x437E
+#define mmDCP3_DCP_CRC_CONTROL 0x4387
+#define mmDCP3_DCP_CRC_CURRENT 0x4389
+#define mmDCP3_DCP_CRC_LAST 0x438B
+#define mmDCP3_DCP_CRC_MASK 0x4388
+#define mmDCP3_DCP_DEBUG 0x438D
+#define mmDCP3_DCP_DEBUG2 0x4398
+#define mmDCP3_DCP_FP_CONVERTED_FIELD 0x4365
+#define mmDCP3_DCP_GSL_CONTROL 0x4390
+#define mmDCP3_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4391
+#define mmDCP3_DCP_RANDOM_SEEDS 0x4361
+#define mmDCP3_DCP_SPATIAL_DITHER_CNTL 0x4360
+#define mmDCP3_DCP_TEST_DEBUG_DATA 0x4396
+#define mmDCP3_DCP_TEST_DEBUG_INDEX 0x4395
+#define mmDCP3_DEGAMMA_CONTROL 0x4358
+#define mmDCP3_DENORM_CONTROL 0x4350
+#define mmDCP3_GAMUT_REMAP_C11_C12 0x435A
+#define mmDCP3_GAMUT_REMAP_C13_C14 0x435B
+#define mmDCP3_GAMUT_REMAP_C21_C22 0x435C
+#define mmDCP3_GAMUT_REMAP_C23_C24 0x435D
+#define mmDCP3_GAMUT_REMAP_C31_C32 0x435E
+#define mmDCP3_GAMUT_REMAP_C33_C34 0x435F
+#define mmDCP3_GAMUT_REMAP_CONTROL 0x4359
+#define mmDCP3_GRPH_COMPRESS_PITCH 0x431A
+#define mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS 0x4319
+#define mmDCP3_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x431B
+#define mmDCP3_GRPH_CONTROL 0x4301
+#define mmDCP3_GRPH_DFQ_CONTROL 0x4314
+#define mmDCP3_GRPH_DFQ_STATUS 0x4315
+#define mmDCP3_GRPH_ENABLE 0x4300
+#define mmDCP3_GRPH_FLIP_CONTROL 0x4312
+#define mmDCP3_GRPH_INTERRUPT_CONTROL 0x4317
+#define mmDCP3_GRPH_INTERRUPT_STATUS 0x4316
+#define mmDCP3_GRPH_LUT_10BIT_BYPASS 0x4302
+#define mmDCP3_GRPH_PITCH 0x4306
+#define mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS 0x4304
+#define mmDCP3_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4307
+#define mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS 0x4305
+#define mmDCP3_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4308
+#define mmDCP3_GRPH_STEREOSYNC_FLIP 0x4397
+#define mmDCP3_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4318
+#define mmDCP3_GRPH_SURFACE_ADDRESS_INUSE 0x4313
+#define mmDCP3_GRPH_SURFACE_OFFSET_X 0x4309
+#define mmDCP3_GRPH_SURFACE_OFFSET_Y 0x430A
+#define mmDCP3_GRPH_SWAP_CNTL 0x4303
+#define mmDCP3_GRPH_UPDATE 0x4311
+#define mmDCP3_GRPH_X_END 0x430D
+#define mmDCP3_GRPH_X_START 0x430B
+#define mmDCP3_GRPH_Y_END 0x430E
+#define mmDCP3_GRPH_Y_START 0x430C
+#define mmDCP3_INPUT_CSC_C11_C12 0x4336
+#define mmDCP3_INPUT_CSC_C13_C14 0x4337
+#define mmDCP3_INPUT_CSC_C21_C22 0x4338
+#define mmDCP3_INPUT_CSC_C23_C24 0x4339
+#define mmDCP3_INPUT_CSC_C31_C32 0x433A
+#define mmDCP3_INPUT_CSC_C33_C34 0x433B
+#define mmDCP3_INPUT_CSC_CONTROL 0x4335
+#define mmDCP3_INPUT_GAMMA_CONTROL 0x4310
+#define mmDCP3_KEY_CONTROL 0x4353
+#define mmDCP3_KEY_RANGE_ALPHA 0x4354
+#define mmDCP3_KEY_RANGE_BLUE 0x4357
+#define mmDCP3_KEY_RANGE_GREEN 0x4356
+#define mmDCP3_KEY_RANGE_RED 0x4355
+#define mmDCP3_OUTPUT_CSC_C11_C12 0x433D
+#define mmDCP3_OUTPUT_CSC_C13_C14 0x433E
+#define mmDCP3_OUTPUT_CSC_C21_C22 0x433F
+#define mmDCP3_OUTPUT_CSC_C23_C24 0x4340
+#define mmDCP3_OUTPUT_CSC_C31_C32 0x4341
+#define mmDCP3_OUTPUT_CSC_C33_C34 0x4342
+#define mmDCP3_OUTPUT_CSC_CONTROL 0x433C
+#define mmDCP3_OUT_ROUND_CONTROL 0x4351
+#define mmDCP3_OVL_CONTROL1 0x431D
+#define mmDCP3_OVL_CONTROL2 0x431E
+#define mmDCP3_OVL_DFQ_CONTROL 0x4329
+#define mmDCP3_OVL_DFQ_STATUS 0x432A
+#define mmDCP3_OVL_ENABLE 0x431C
+#define mmDCP3_OVL_END 0x4326
+#define mmDCP3_OVL_PITCH 0x4321
+#define mmDCP3_OVLSCL_EDGE_PIXEL_CNTL 0x432C
+#define mmDCP3_OVL_SECONDARY_SURFACE_ADDRESS 0x4392
+#define mmDCP3_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4394
+#define mmDCP3_OVL_START 0x4325
+#define mmDCP3_OVL_STEREOSYNC_FLIP 0x4393
+#define mmDCP3_OVL_SURFACE_ADDRESS 0x4320
+#define mmDCP3_OVL_SURFACE_ADDRESS_HIGH 0x4322
+#define mmDCP3_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x432B
+#define mmDCP3_OVL_SURFACE_ADDRESS_INUSE 0x4328
+#define mmDCP3_OVL_SURFACE_OFFSET_X 0x4323
+#define mmDCP3_OVL_SURFACE_OFFSET_Y 0x4324
+#define mmDCP3_OVL_SWAP_CNTL 0x431F
+#define mmDCP3_OVL_UPDATE 0x4327
+#define mmDCP3_PRESCALE_GRPH_CONTROL 0x432D
+#define mmDCP3_PRESCALE_OVL_CONTROL 0x4331
+#define mmDCP3_PRESCALE_VALUES_GRPH_B 0x4330
+#define mmDCP3_PRESCALE_VALUES_GRPH_G 0x432F
+#define mmDCP3_PRESCALE_VALUES_GRPH_R 0x432E
+#define mmDCP3_PRESCALE_VALUES_OVL_CB 0x4332
+#define mmDCP3_PRESCALE_VALUES_OVL_CR 0x4334
+#define mmDCP3_PRESCALE_VALUES_OVL_Y 0x4333
+#define mmDCP3_REGAMMA_CNTLA_END_CNTL1 0x43A6
+#define mmDCP3_REGAMMA_CNTLA_END_CNTL2 0x43A7
+#define mmDCP3_REGAMMA_CNTLA_REGION_0_1 0x43A8
+#define mmDCP3_REGAMMA_CNTLA_REGION_10_11 0x43AD
+#define mmDCP3_REGAMMA_CNTLA_REGION_12_13 0x43AE
+#define mmDCP3_REGAMMA_CNTLA_REGION_14_15 0x43AF
+#define mmDCP3_REGAMMA_CNTLA_REGION_2_3 0x43A9
+#define mmDCP3_REGAMMA_CNTLA_REGION_4_5 0x43AA
+#define mmDCP3_REGAMMA_CNTLA_REGION_6_7 0x43AB
+#define mmDCP3_REGAMMA_CNTLA_REGION_8_9 0x43AC
+#define mmDCP3_REGAMMA_CNTLA_SLOPE_CNTL 0x43A5
+#define mmDCP3_REGAMMA_CNTLA_START_CNTL 0x43A4
+#define mmDCP3_REGAMMA_CNTLB_END_CNTL1 0x43B2
+#define mmDCP3_REGAMMA_CNTLB_END_CNTL2 0x43B3
+#define mmDCP3_REGAMMA_CNTLB_REGION_0_1 0x43B4
+#define mmDCP3_REGAMMA_CNTLB_REGION_10_11 0x43B9
+#define mmDCP3_REGAMMA_CNTLB_REGION_12_13 0x43BA
+#define mmDCP3_REGAMMA_CNTLB_REGION_14_15 0x43BB
+#define mmDCP3_REGAMMA_CNTLB_REGION_2_3 0x43B5
+#define mmDCP3_REGAMMA_CNTLB_REGION_4_5 0x43B6
+#define mmDCP3_REGAMMA_CNTLB_REGION_6_7 0x43B7
+#define mmDCP3_REGAMMA_CNTLB_REGION_8_9 0x43B8
+#define mmDCP3_REGAMMA_CNTLB_SLOPE_CNTL 0x43B1
+#define mmDCP3_REGAMMA_CNTLB_START_CNTL 0x43B0
+#define mmDCP3_REGAMMA_CONTROL 0x43A0
+#define mmDCP3_REGAMMA_LUT_DATA 0x43A2
+#define mmDCP3_REGAMMA_LUT_INDEX 0x43A1
+#define mmDCP3_REGAMMA_LUT_WRITE_EN_MASK 0x43A3
+#define mmDCP4_COMM_MATRIXA_TRANS_C11_C12 0x4643
+#define mmDCP4_COMM_MATRIXA_TRANS_C13_C14 0x4644
+#define mmDCP4_COMM_MATRIXA_TRANS_C21_C22 0x4645
+#define mmDCP4_COMM_MATRIXA_TRANS_C23_C24 0x4646
+#define mmDCP4_COMM_MATRIXA_TRANS_C31_C32 0x4647
+#define mmDCP4_COMM_MATRIXA_TRANS_C33_C34 0x4648
+#define mmDCP4_COMM_MATRIXB_TRANS_C11_C12 0x4649
+#define mmDCP4_COMM_MATRIXB_TRANS_C13_C14 0x464A
+#define mmDCP4_COMM_MATRIXB_TRANS_C21_C22 0x464B
+#define mmDCP4_COMM_MATRIXB_TRANS_C23_C24 0x464C
+#define mmDCP4_COMM_MATRIXB_TRANS_C31_C32 0x464D
+#define mmDCP4_COMM_MATRIXB_TRANS_C33_C34 0x464E
+#define mmDCP4_CUR_COLOR1 0x466C
+#define mmDCP4_CUR_COLOR2 0x466D
+#define mmDCP4_CUR_CONTROL 0x4666
+#define mmDCP4_CUR_HOT_SPOT 0x466B
+#define mmDCP4_CUR_POSITION 0x466A
+#define mmDCP4_CUR_REQUEST_FILTER_CNTL 0x4699
+#define mmDCP4_CUR_SIZE 0x4668
+#define mmDCP4_CUR_SURFACE_ADDRESS 0x4667
+#define mmDCP4_CUR_SURFACE_ADDRESS_HIGH 0x4669
+#define mmDCP4_CUR_UPDATE 0x466E
+#define mmDCP4_DC_LUT_30_COLOR 0x467C
+#define mmDCP4_DC_LUT_AUTOFILL 0x467F
+#define mmDCP4_DC_LUT_BLACK_OFFSET_BLUE 0x4681
+#define mmDCP4_DC_LUT_BLACK_OFFSET_GREEN 0x4682
+#define mmDCP4_DC_LUT_BLACK_OFFSET_RED 0x4683
+#define mmDCP4_DC_LUT_CONTROL 0x4680
+#define mmDCP4_DC_LUT_PWL_DATA 0x467B
+#define mmDCP4_DC_LUT_RW_INDEX 0x4679
+#define mmDCP4_DC_LUT_RW_MODE 0x4678
+#define mmDCP4_DC_LUT_SEQ_COLOR 0x467A
+#define mmDCP4_DC_LUT_VGA_ACCESS_ENABLE 0x467D
+#define mmDCP4_DC_LUT_WHITE_OFFSET_BLUE 0x4684
+#define mmDCP4_DC_LUT_WHITE_OFFSET_GREEN 0x4685
+#define mmDCP4_DC_LUT_WHITE_OFFSET_RED 0x4686
+#define mmDCP4_DC_LUT_WRITE_EN_MASK 0x467E
+#define mmDCP4_DCP_CRC_CONTROL 0x4687
+#define mmDCP4_DCP_CRC_CURRENT 0x4689
+#define mmDCP4_DCP_CRC_LAST 0x468B
+#define mmDCP4_DCP_CRC_MASK 0x4688
+#define mmDCP4_DCP_DEBUG 0x468D
+#define mmDCP4_DCP_DEBUG2 0x4698
+#define mmDCP4_DCP_FP_CONVERTED_FIELD 0x4665
+#define mmDCP4_DCP_GSL_CONTROL 0x4690
+#define mmDCP4_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4691
+#define mmDCP4_DCP_RANDOM_SEEDS 0x4661
+#define mmDCP4_DCP_SPATIAL_DITHER_CNTL 0x4660
+#define mmDCP4_DCP_TEST_DEBUG_DATA 0x4696
+#define mmDCP4_DCP_TEST_DEBUG_INDEX 0x4695
+#define mmDCP4_DEGAMMA_CONTROL 0x4658
+#define mmDCP4_DENORM_CONTROL 0x4650
+#define mmDCP4_GAMUT_REMAP_C11_C12 0x465A
+#define mmDCP4_GAMUT_REMAP_C13_C14 0x465B
+#define mmDCP4_GAMUT_REMAP_C21_C22 0x465C
+#define mmDCP4_GAMUT_REMAP_C23_C24 0x465D
+#define mmDCP4_GAMUT_REMAP_C31_C32 0x465E
+#define mmDCP4_GAMUT_REMAP_C33_C34 0x465F
+#define mmDCP4_GAMUT_REMAP_CONTROL 0x4659
+#define mmDCP4_GRPH_COMPRESS_PITCH 0x461A
+#define mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS 0x4619
+#define mmDCP4_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x461B
+#define mmDCP4_GRPH_CONTROL 0x4601
+#define mmDCP4_GRPH_DFQ_CONTROL 0x4614
+#define mmDCP4_GRPH_DFQ_STATUS 0x4615
+#define mmDCP4_GRPH_ENABLE 0x4600
+#define mmDCP4_GRPH_FLIP_CONTROL 0x4612
+#define mmDCP4_GRPH_INTERRUPT_CONTROL 0x4617
+#define mmDCP4_GRPH_INTERRUPT_STATUS 0x4616
+#define mmDCP4_GRPH_LUT_10BIT_BYPASS 0x4602
+#define mmDCP4_GRPH_PITCH 0x4606
+#define mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS 0x4604
+#define mmDCP4_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4607
+#define mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS 0x4605
+#define mmDCP4_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4608
+#define mmDCP4_GRPH_STEREOSYNC_FLIP 0x4697
+#define mmDCP4_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4618
+#define mmDCP4_GRPH_SURFACE_ADDRESS_INUSE 0x4613
+#define mmDCP4_GRPH_SURFACE_OFFSET_X 0x4609
+#define mmDCP4_GRPH_SURFACE_OFFSET_Y 0x460A
+#define mmDCP4_GRPH_SWAP_CNTL 0x4603
+#define mmDCP4_GRPH_UPDATE 0x4611
+#define mmDCP4_GRPH_X_END 0x460D
+#define mmDCP4_GRPH_X_START 0x460B
+#define mmDCP4_GRPH_Y_END 0x460E
+#define mmDCP4_GRPH_Y_START 0x460C
+#define mmDCP4_INPUT_CSC_C11_C12 0x4636
+#define mmDCP4_INPUT_CSC_C13_C14 0x4637
+#define mmDCP4_INPUT_CSC_C21_C22 0x4638
+#define mmDCP4_INPUT_CSC_C23_C24 0x4639
+#define mmDCP4_INPUT_CSC_C31_C32 0x463A
+#define mmDCP4_INPUT_CSC_C33_C34 0x463B
+#define mmDCP4_INPUT_CSC_CONTROL 0x4635
+#define mmDCP4_INPUT_GAMMA_CONTROL 0x4610
+#define mmDCP4_KEY_CONTROL 0x4653
+#define mmDCP4_KEY_RANGE_ALPHA 0x4654
+#define mmDCP4_KEY_RANGE_BLUE 0x4657
+#define mmDCP4_KEY_RANGE_GREEN 0x4656
+#define mmDCP4_KEY_RANGE_RED 0x4655
+#define mmDCP4_OUTPUT_CSC_C11_C12 0x463D
+#define mmDCP4_OUTPUT_CSC_C13_C14 0x463E
+#define mmDCP4_OUTPUT_CSC_C21_C22 0x463F
+#define mmDCP4_OUTPUT_CSC_C23_C24 0x4640
+#define mmDCP4_OUTPUT_CSC_C31_C32 0x4641
+#define mmDCP4_OUTPUT_CSC_C33_C34 0x4642
+#define mmDCP4_OUTPUT_CSC_CONTROL 0x463C
+#define mmDCP4_OUT_ROUND_CONTROL 0x4651
+#define mmDCP4_OVL_CONTROL1 0x461D
+#define mmDCP4_OVL_CONTROL2 0x461E
+#define mmDCP4_OVL_DFQ_CONTROL 0x4629
+#define mmDCP4_OVL_DFQ_STATUS 0x462A
+#define mmDCP4_OVL_ENABLE 0x461C
+#define mmDCP4_OVL_END 0x4626
+#define mmDCP4_OVL_PITCH 0x4621
+#define mmDCP4_OVLSCL_EDGE_PIXEL_CNTL 0x462C
+#define mmDCP4_OVL_SECONDARY_SURFACE_ADDRESS 0x4692
+#define mmDCP4_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4694
+#define mmDCP4_OVL_START 0x4625
+#define mmDCP4_OVL_STEREOSYNC_FLIP 0x4693
+#define mmDCP4_OVL_SURFACE_ADDRESS 0x4620
+#define mmDCP4_OVL_SURFACE_ADDRESS_HIGH 0x4622
+#define mmDCP4_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x462B
+#define mmDCP4_OVL_SURFACE_ADDRESS_INUSE 0x4628
+#define mmDCP4_OVL_SURFACE_OFFSET_X 0x4623
+#define mmDCP4_OVL_SURFACE_OFFSET_Y 0x4624
+#define mmDCP4_OVL_SWAP_CNTL 0x461F
+#define mmDCP4_OVL_UPDATE 0x4627
+#define mmDCP4_PRESCALE_GRPH_CONTROL 0x462D
+#define mmDCP4_PRESCALE_OVL_CONTROL 0x4631
+#define mmDCP4_PRESCALE_VALUES_GRPH_B 0x4630
+#define mmDCP4_PRESCALE_VALUES_GRPH_G 0x462F
+#define mmDCP4_PRESCALE_VALUES_GRPH_R 0x462E
+#define mmDCP4_PRESCALE_VALUES_OVL_CB 0x4632
+#define mmDCP4_PRESCALE_VALUES_OVL_CR 0x4634
+#define mmDCP4_PRESCALE_VALUES_OVL_Y 0x4633
+#define mmDCP4_REGAMMA_CNTLA_END_CNTL1 0x46A6
+#define mmDCP4_REGAMMA_CNTLA_END_CNTL2 0x46A7
+#define mmDCP4_REGAMMA_CNTLA_REGION_0_1 0x46A8
+#define mmDCP4_REGAMMA_CNTLA_REGION_10_11 0x46AD
+#define mmDCP4_REGAMMA_CNTLA_REGION_12_13 0x46AE
+#define mmDCP4_REGAMMA_CNTLA_REGION_14_15 0x46AF
+#define mmDCP4_REGAMMA_CNTLA_REGION_2_3 0x46A9
+#define mmDCP4_REGAMMA_CNTLA_REGION_4_5 0x46AA
+#define mmDCP4_REGAMMA_CNTLA_REGION_6_7 0x46AB
+#define mmDCP4_REGAMMA_CNTLA_REGION_8_9 0x46AC
+#define mmDCP4_REGAMMA_CNTLA_SLOPE_CNTL 0x46A5
+#define mmDCP4_REGAMMA_CNTLA_START_CNTL 0x46A4
+#define mmDCP4_REGAMMA_CNTLB_END_CNTL1 0x46B2
+#define mmDCP4_REGAMMA_CNTLB_END_CNTL2 0x46B3
+#define mmDCP4_REGAMMA_CNTLB_REGION_0_1 0x46B4
+#define mmDCP4_REGAMMA_CNTLB_REGION_10_11 0x46B9
+#define mmDCP4_REGAMMA_CNTLB_REGION_12_13 0x46BA
+#define mmDCP4_REGAMMA_CNTLB_REGION_14_15 0x46BB
+#define mmDCP4_REGAMMA_CNTLB_REGION_2_3 0x46B5
+#define mmDCP4_REGAMMA_CNTLB_REGION_4_5 0x46B6
+#define mmDCP4_REGAMMA_CNTLB_REGION_6_7 0x46B7
+#define mmDCP4_REGAMMA_CNTLB_REGION_8_9 0x46B8
+#define mmDCP4_REGAMMA_CNTLB_SLOPE_CNTL 0x46B1
+#define mmDCP4_REGAMMA_CNTLB_START_CNTL 0x46B0
+#define mmDCP4_REGAMMA_CONTROL 0x46A0
+#define mmDCP4_REGAMMA_LUT_DATA 0x46A2
+#define mmDCP4_REGAMMA_LUT_INDEX 0x46A1
+#define mmDCP4_REGAMMA_LUT_WRITE_EN_MASK 0x46A3
+#define mmDCP5_COMM_MATRIXA_TRANS_C11_C12 0x4943
+#define mmDCP5_COMM_MATRIXA_TRANS_C13_C14 0x4944
+#define mmDCP5_COMM_MATRIXA_TRANS_C21_C22 0x4945
+#define mmDCP5_COMM_MATRIXA_TRANS_C23_C24 0x4946
+#define mmDCP5_COMM_MATRIXA_TRANS_C31_C32 0x4947
+#define mmDCP5_COMM_MATRIXA_TRANS_C33_C34 0x4948
+#define mmDCP5_COMM_MATRIXB_TRANS_C11_C12 0x4949
+#define mmDCP5_COMM_MATRIXB_TRANS_C13_C14 0x494A
+#define mmDCP5_COMM_MATRIXB_TRANS_C21_C22 0x494B
+#define mmDCP5_COMM_MATRIXB_TRANS_C23_C24 0x494C
+#define mmDCP5_COMM_MATRIXB_TRANS_C31_C32 0x494D
+#define mmDCP5_COMM_MATRIXB_TRANS_C33_C34 0x494E
+#define mmDCP5_CUR_COLOR1 0x496C
+#define mmDCP5_CUR_COLOR2 0x496D
+#define mmDCP5_CUR_CONTROL 0x4966
+#define mmDCP5_CUR_HOT_SPOT 0x496B
+#define mmDCP5_CUR_POSITION 0x496A
+#define mmDCP5_CUR_REQUEST_FILTER_CNTL 0x4999
+#define mmDCP5_CUR_SIZE 0x4968
+#define mmDCP5_CUR_SURFACE_ADDRESS 0x4967
+#define mmDCP5_CUR_SURFACE_ADDRESS_HIGH 0x4969
+#define mmDCP5_CUR_UPDATE 0x496E
+#define mmDCP5_DC_LUT_30_COLOR 0x497C
+#define mmDCP5_DC_LUT_AUTOFILL 0x497F
+#define mmDCP5_DC_LUT_BLACK_OFFSET_BLUE 0x4981
+#define mmDCP5_DC_LUT_BLACK_OFFSET_GREEN 0x4982
+#define mmDCP5_DC_LUT_BLACK_OFFSET_RED 0x4983
+#define mmDCP5_DC_LUT_CONTROL 0x4980
+#define mmDCP5_DC_LUT_PWL_DATA 0x497B
+#define mmDCP5_DC_LUT_RW_INDEX 0x4979
+#define mmDCP5_DC_LUT_RW_MODE 0x4978
+#define mmDCP5_DC_LUT_SEQ_COLOR 0x497A
+#define mmDCP5_DC_LUT_VGA_ACCESS_ENABLE 0x497D
+#define mmDCP5_DC_LUT_WHITE_OFFSET_BLUE 0x4984
+#define mmDCP5_DC_LUT_WHITE_OFFSET_GREEN 0x4985
+#define mmDCP5_DC_LUT_WHITE_OFFSET_RED 0x4986
+#define mmDCP5_DC_LUT_WRITE_EN_MASK 0x497E
+#define mmDCP5_DCP_CRC_CONTROL 0x4987
+#define mmDCP5_DCP_CRC_CURRENT 0x4989
+#define mmDCP5_DCP_CRC_LAST 0x498B
+#define mmDCP5_DCP_CRC_MASK 0x4988
+#define mmDCP5_DCP_DEBUG 0x498D
+#define mmDCP5_DCP_DEBUG2 0x4998
+#define mmDCP5_DCP_FP_CONVERTED_FIELD 0x4965
+#define mmDCP5_DCP_GSL_CONTROL 0x4990
+#define mmDCP5_DCP_LB_DATA_GAP_BETWEEN_CHUNK 0x4991
+#define mmDCP5_DCP_RANDOM_SEEDS 0x4961
+#define mmDCP5_DCP_SPATIAL_DITHER_CNTL 0x4960
+#define mmDCP5_DCP_TEST_DEBUG_DATA 0x4996
+#define mmDCP5_DCP_TEST_DEBUG_INDEX 0x4995
+#define mmDCP5_DEGAMMA_CONTROL 0x4958
+#define mmDCP5_DENORM_CONTROL 0x4950
+#define mmDCP5_GAMUT_REMAP_C11_C12 0x495A
+#define mmDCP5_GAMUT_REMAP_C13_C14 0x495B
+#define mmDCP5_GAMUT_REMAP_C21_C22 0x495C
+#define mmDCP5_GAMUT_REMAP_C23_C24 0x495D
+#define mmDCP5_GAMUT_REMAP_C31_C32 0x495E
+#define mmDCP5_GAMUT_REMAP_C33_C34 0x495F
+#define mmDCP5_GAMUT_REMAP_CONTROL 0x4959
+#define mmDCP5_GRPH_COMPRESS_PITCH 0x491A
+#define mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS 0x4919
+#define mmDCP5_GRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x491B
+#define mmDCP5_GRPH_CONTROL 0x4901
+#define mmDCP5_GRPH_DFQ_CONTROL 0x4914
+#define mmDCP5_GRPH_DFQ_STATUS 0x4915
+#define mmDCP5_GRPH_ENABLE 0x4900
+#define mmDCP5_GRPH_FLIP_CONTROL 0x4912
+#define mmDCP5_GRPH_INTERRUPT_CONTROL 0x4917
+#define mmDCP5_GRPH_INTERRUPT_STATUS 0x4916
+#define mmDCP5_GRPH_LUT_10BIT_BYPASS 0x4902
+#define mmDCP5_GRPH_PITCH 0x4906
+#define mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS 0x4904
+#define mmDCP5_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x4907
+#define mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS 0x4905
+#define mmDCP5_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x4908
+#define mmDCP5_GRPH_STEREOSYNC_FLIP 0x4997
+#define mmDCP5_GRPH_SURFACE_ADDRESS_HIGH_INUSE 0x4918
+#define mmDCP5_GRPH_SURFACE_ADDRESS_INUSE 0x4913
+#define mmDCP5_GRPH_SURFACE_OFFSET_X 0x4909
+#define mmDCP5_GRPH_SURFACE_OFFSET_Y 0x490A
+#define mmDCP5_GRPH_SWAP_CNTL 0x4903
+#define mmDCP5_GRPH_UPDATE 0x4911
+#define mmDCP5_GRPH_X_END 0x490D
+#define mmDCP5_GRPH_X_START 0x490B
+#define mmDCP5_GRPH_Y_END 0x490E
+#define mmDCP5_GRPH_Y_START 0x490C
+#define mmDCP5_INPUT_CSC_C11_C12 0x4936
+#define mmDCP5_INPUT_CSC_C13_C14 0x4937
+#define mmDCP5_INPUT_CSC_C21_C22 0x4938
+#define mmDCP5_INPUT_CSC_C23_C24 0x4939
+#define mmDCP5_INPUT_CSC_C31_C32 0x493A
+#define mmDCP5_INPUT_CSC_C33_C34 0x493B
+#define mmDCP5_INPUT_CSC_CONTROL 0x4935
+#define mmDCP5_INPUT_GAMMA_CONTROL 0x4910
+#define mmDCP5_KEY_CONTROL 0x4953
+#define mmDCP5_KEY_RANGE_ALPHA 0x4954
+#define mmDCP5_KEY_RANGE_BLUE 0x4957
+#define mmDCP5_KEY_RANGE_GREEN 0x4956
+#define mmDCP5_KEY_RANGE_RED 0x4955
+#define mmDCP5_OUTPUT_CSC_C11_C12 0x493D
+#define mmDCP5_OUTPUT_CSC_C13_C14 0x493E
+#define mmDCP5_OUTPUT_CSC_C21_C22 0x493F
+#define mmDCP5_OUTPUT_CSC_C23_C24 0x4940
+#define mmDCP5_OUTPUT_CSC_C31_C32 0x4941
+#define mmDCP5_OUTPUT_CSC_C33_C34 0x4942
+#define mmDCP5_OUTPUT_CSC_CONTROL 0x493C
+#define mmDCP5_OUT_ROUND_CONTROL 0x4951
+#define mmDCP5_OVL_CONTROL1 0x491D
+#define mmDCP5_OVL_CONTROL2 0x491E
+#define mmDCP5_OVL_DFQ_CONTROL 0x4929
+#define mmDCP5_OVL_DFQ_STATUS 0x492A
+#define mmDCP5_OVL_ENABLE 0x491C
+#define mmDCP5_OVL_END 0x4926
+#define mmDCP5_OVL_PITCH 0x4921
+#define mmDCP5_OVLSCL_EDGE_PIXEL_CNTL 0x492C
+#define mmDCP5_OVL_SECONDARY_SURFACE_ADDRESS 0x4992
+#define mmDCP5_OVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x4994
+#define mmDCP5_OVL_START 0x4925
+#define mmDCP5_OVL_STEREOSYNC_FLIP 0x4993
+#define mmDCP5_OVL_SURFACE_ADDRESS 0x4920
+#define mmDCP5_OVL_SURFACE_ADDRESS_HIGH 0x4922
+#define mmDCP5_OVL_SURFACE_ADDRESS_HIGH_INUSE 0x492B
+#define mmDCP5_OVL_SURFACE_ADDRESS_INUSE 0x4928
+#define mmDCP5_OVL_SURFACE_OFFSET_X 0x4923
+#define mmDCP5_OVL_SURFACE_OFFSET_Y 0x4924
+#define mmDCP5_OVL_SWAP_CNTL 0x491F
+#define mmDCP5_OVL_UPDATE 0x4927
+#define mmDCP5_PRESCALE_GRPH_CONTROL 0x492D
+#define mmDCP5_PRESCALE_OVL_CONTROL 0x4931
+#define mmDCP5_PRESCALE_VALUES_GRPH_B 0x4930
+#define mmDCP5_PRESCALE_VALUES_GRPH_G 0x492F
+#define mmDCP5_PRESCALE_VALUES_GRPH_R 0x492E
+#define mmDCP5_PRESCALE_VALUES_OVL_CB 0x4932
+#define mmDCP5_PRESCALE_VALUES_OVL_CR 0x4934
+#define mmDCP5_PRESCALE_VALUES_OVL_Y 0x4933
+#define mmDCP5_REGAMMA_CNTLA_END_CNTL1 0x49A6
+#define mmDCP5_REGAMMA_CNTLA_END_CNTL2 0x49A7
+#define mmDCP5_REGAMMA_CNTLA_REGION_0_1 0x49A8
+#define mmDCP5_REGAMMA_CNTLA_REGION_10_11 0x49AD
+#define mmDCP5_REGAMMA_CNTLA_REGION_12_13 0x49AE
+#define mmDCP5_REGAMMA_CNTLA_REGION_14_15 0x49AF
+#define mmDCP5_REGAMMA_CNTLA_REGION_2_3 0x49A9
+#define mmDCP5_REGAMMA_CNTLA_REGION_4_5 0x49AA
+#define mmDCP5_REGAMMA_CNTLA_REGION_6_7 0x49AB
+#define mmDCP5_REGAMMA_CNTLA_REGION_8_9 0x49AC
+#define mmDCP5_REGAMMA_CNTLA_SLOPE_CNTL 0x49A5
+#define mmDCP5_REGAMMA_CNTLA_START_CNTL 0x49A4
+#define mmDCP5_REGAMMA_CNTLB_END_CNTL1 0x49B2
+#define mmDCP5_REGAMMA_CNTLB_END_CNTL2 0x49B3
+#define mmDCP5_REGAMMA_CNTLB_REGION_0_1 0x49B4
+#define mmDCP5_REGAMMA_CNTLB_REGION_10_11 0x49B9
+#define mmDCP5_REGAMMA_CNTLB_REGION_12_13 0x49BA
+#define mmDCP5_REGAMMA_CNTLB_REGION_14_15 0x49BB
+#define mmDCP5_REGAMMA_CNTLB_REGION_2_3 0x49B5
+#define mmDCP5_REGAMMA_CNTLB_REGION_4_5 0x49B6
+#define mmDCP5_REGAMMA_CNTLB_REGION_6_7 0x49B7
+#define mmDCP5_REGAMMA_CNTLB_REGION_8_9 0x49B8
+#define mmDCP5_REGAMMA_CNTLB_SLOPE_CNTL 0x49B1
+#define mmDCP5_REGAMMA_CNTLB_START_CNTL 0x49B0
+#define mmDCP5_REGAMMA_CONTROL 0x49A0
+#define mmDCP5_REGAMMA_LUT_DATA 0x49A2
+#define mmDCP5_REGAMMA_LUT_INDEX 0x49A1
+#define mmDCP5_REGAMMA_LUT_WRITE_EN_MASK 0x49A3
+#define mmDC_PAD_EXTERN_SIG 0x1902
+#define mmDCP_CRC_CONTROL 0x1A87
+#define mmDCP_CRC_CURRENT 0x1A89
+#define mmDCP_CRC_LAST 0x1A8B
+#define mmDCP_CRC_MASK 0x1A88
+#define mmDCP_DEBUG 0x1A8D
+#define mmDCP_DEBUG2 0x1A98
+#define mmDCP_FP_CONVERTED_FIELD 0x1A65
+#define mmDC_PGCNTL_STATUS_REG 0x177E
+#define mmDC_PGFSM_CONFIG_REG 0x177C
+#define mmDC_PGFSM_WRITE_REG 0x177D
+#define mmDCP_GSL_CONTROL 0x1A90
+#define mmDCPG_TEST_DEBUG_DATA 0x177B
+#define mmDCPG_TEST_DEBUG_INDEX 0x1779
+#define mmDC_PINSTRAPS 0x1917
+#define mmDCP_LB_DATA_GAP_BETWEEN_CHUNK 0x1A91
+#define mmDCP_RANDOM_SEEDS 0x1A61
+#define mmDCP_SPATIAL_DITHER_CNTL 0x1A60
+#define mmDCP_TEST_DEBUG_DATA 0x1A96
+#define mmDCP_TEST_DEBUG_INDEX 0x1A95
+#define mmDC_RBBMIF_RDWR_CNTL1 0x031A
+#define mmDC_RBBMIF_RDWR_CNTL2 0x031D
+#define mmDC_REF_CLK_CNTL 0x1903
+#define mmDC_XDMA_INTERFACE_CNTL 0x0327
+#define mmDEGAMMA_CONTROL 0x1A58
+#define mmDENORM_CONTROL 0x1A50
+#define mmDENTIST_DISPCLK_CNTL 0x0124
+#define mmDIG0_AFMT_60958_0 0x1C41
+#define mmDIG0_AFMT_60958_1 0x1C42
+#define mmDIG0_AFMT_60958_2 0x1C48
+#define mmDIG0_AFMT_AUDIO_CRC_CONTROL 0x1C43
+#define mmDIG0_AFMT_AUDIO_CRC_RESULT 0x1C49
+#define mmDIG0_AFMT_AUDIO_DBG_DTO_CNTL 0x1C52
+#define mmDIG0_AFMT_AUDIO_INFO0 0x1C3F
+#define mmDIG0_AFMT_AUDIO_INFO1 0x1C40
+#define mmDIG0_AFMT_AUDIO_PACKET_CONTROL 0x1C4B
+#define mmDIG0_AFMT_AUDIO_PACKET_CONTROL2 0x1C17
+#define mmDIG0_AFMT_AUDIO_SRC_CONTROL 0x1C4F
+#define mmDIG0_AFMT_AVI_INFO0 0x1C21
+#define mmDIG0_AFMT_AVI_INFO1 0x1C22
+#define mmDIG0_AFMT_AVI_INFO2 0x1C23
+#define mmDIG0_AFMT_AVI_INFO3 0x1C24
+#define mmDIG0_AFMT_GENERIC_0 0x1C28
+#define mmDIG0_AFMT_GENERIC_1 0x1C29
+#define mmDIG0_AFMT_GENERIC_2 0x1C2A
+#define mmDIG0_AFMT_GENERIC_3 0x1C2B
+#define mmDIG0_AFMT_GENERIC_4 0x1C2C
+#define mmDIG0_AFMT_GENERIC_5 0x1C2D
+#define mmDIG0_AFMT_GENERIC_6 0x1C2E
+#define mmDIG0_AFMT_GENERIC_7 0x1C2F
+#define mmDIG0_AFMT_GENERIC_HDR 0x1C27
+#define mmDIG0_AFMT_INFOFRAME_CONTROL0 0x1C4D
+#define mmDIG0_AFMT_INTERRUPT_STATUS 0x1C14
+#define mmDIG0_AFMT_ISRC1_0 0x1C18
+#define mmDIG0_AFMT_ISRC1_1 0x1C19
+#define mmDIG0_AFMT_ISRC1_2 0x1C1A
+#define mmDIG0_AFMT_ISRC1_3 0x1C1B
+#define mmDIG0_AFMT_ISRC1_4 0x1C1C
+#define mmDIG0_AFMT_ISRC2_0 0x1C1D
+#define mmDIG0_AFMT_ISRC2_1 0x1C1E
+#define mmDIG0_AFMT_ISRC2_2 0x1C1F
+#define mmDIG0_AFMT_ISRC2_3 0x1C20
+#define mmDIG0_AFMT_MPEG_INFO0 0x1C25
+#define mmDIG0_AFMT_MPEG_INFO1 0x1C26
+#define mmDIG0_AFMT_RAMP_CONTROL0 0x1C44
+#define mmDIG0_AFMT_RAMP_CONTROL1 0x1C45
+#define mmDIG0_AFMT_RAMP_CONTROL2 0x1C46
+#define mmDIG0_AFMT_RAMP_CONTROL3 0x1C47
+#define mmDIG0_AFMT_STATUS 0x1C4A
+#define mmDIG0_AFMT_VBI_PACKET_CONTROL 0x1C4C
+#define mmDIG0_DIG_BE_CNTL 0x1C50
+#define mmDIG0_DIG_BE_EN_CNTL 0x1C51
+#define mmDIG0_DIG_CLOCK_PATTERN 0x1C03
+#define mmDIG0_DIG_DISPCLK_SWITCH_CNTL 0x1C08
+#define mmDIG0_DIG_DISPCLK_SWITCH_STATUS 0x1C09
+#define mmDIG0_DIG_FE_CNTL 0x1C00
+#define mmDIG0_DIG_FIFO_STATUS 0x1C0A
+#define mmDIG0_DIG_LANE_ENABLE 0x1C8D
+#define mmDIG0_DIG_OUTPUT_CRC_CNTL 0x1C01
+#define mmDIG0_DIG_OUTPUT_CRC_RESULT 0x1C02
+#define mmDIG0_DIG_RANDOM_PATTERN_SEED 0x1C05
+#define mmDIG0_DIG_TEST_PATTERN 0x1C04
+#define mmDIG0_HDMI_ACR_32_0 0x1C37
+#define mmDIG0_HDMI_ACR_32_1 0x1C38
+#define mmDIG0_HDMI_ACR_44_0 0x1C39
+#define mmDIG0_HDMI_ACR_44_1 0x1C3A
+#define mmDIG0_HDMI_ACR_48_0 0x1C3B
+#define mmDIG0_HDMI_ACR_48_1 0x1C3C
+#define mmDIG0_HDMI_ACR_PACKET_CONTROL 0x1C0F
+#define mmDIG0_HDMI_ACR_STATUS_0 0x1C3D
+#define mmDIG0_HDMI_ACR_STATUS_1 0x1C3E
+#define mmDIG0_HDMI_AUDIO_PACKET_CONTROL 0x1C0E
+#define mmDIG0_HDMI_CONTROL 0x1C0C
+#define mmDIG0_HDMI_GC 0x1C16
+#define mmDIG0_HDMI_GENERIC_PACKET_CONTROL0 0x1C13
+#define mmDIG0_HDMI_GENERIC_PACKET_CONTROL1 0x1C30
+#define mmDIG0_HDMI_INFOFRAME_CONTROL0 0x1C11
+#define mmDIG0_HDMI_INFOFRAME_CONTROL1 0x1C12
+#define mmDIG0_HDMI_STATUS 0x1C0D
+#define mmDIG0_HDMI_VBI_PACKET_CONTROL 0x1C10
+#define mmDIG0_LVDS_DATA_CNTL 0x1C8C
+#define mmDIG0_TMDS_CNTL 0x1C7C
+#define mmDIG0_TMDS_CONTROL0_FEEDBACK 0x1C7E
+#define mmDIG0_TMDS_CONTROL_CHAR 0x1C7D
+#define mmDIG0_TMDS_CTL0_1_GEN_CNTL 0x1C86
+#define mmDIG0_TMDS_CTL2_3_GEN_CNTL 0x1C87
+#define mmDIG0_TMDS_CTL_BITS 0x1C83
+#define mmDIG0_TMDS_DCBALANCER_CONTROL 0x1C84
+#define mmDIG0_TMDS_DEBUG 0x1C82
+#define mmDIG0_TMDS_STEREOSYNC_CTL_SEL 0x1C7F
+#define mmDIG0_TMDS_SYNC_CHAR_PATTERN_0_1 0x1C80
+#define mmDIG0_TMDS_SYNC_CHAR_PATTERN_2_3 0x1C81
+#define mmDIG1_AFMT_60958_0 0x1F41
+#define mmDIG1_AFMT_60958_1 0x1F42
+#define mmDIG1_AFMT_60958_2 0x1F48
+#define mmDIG1_AFMT_AUDIO_CRC_CONTROL 0x1F43
+#define mmDIG1_AFMT_AUDIO_CRC_RESULT 0x1F49
+#define mmDIG1_AFMT_AUDIO_DBG_DTO_CNTL 0x1F52
+#define mmDIG1_AFMT_AUDIO_INFO0 0x1F3F
+#define mmDIG1_AFMT_AUDIO_INFO1 0x1F40
+#define mmDIG1_AFMT_AUDIO_PACKET_CONTROL 0x1F4B
+#define mmDIG1_AFMT_AUDIO_PACKET_CONTROL2 0x1F17
+#define mmDIG1_AFMT_AUDIO_SRC_CONTROL 0x1F4F
+#define mmDIG1_AFMT_AVI_INFO0 0x1F21
+#define mmDIG1_AFMT_AVI_INFO1 0x1F22
+#define mmDIG1_AFMT_AVI_INFO2 0x1F23
+#define mmDIG1_AFMT_AVI_INFO3 0x1F24
+#define mmDIG1_AFMT_GENERIC_0 0x1F28
+#define mmDIG1_AFMT_GENERIC_1 0x1F29
+#define mmDIG1_AFMT_GENERIC_2 0x1F2A
+#define mmDIG1_AFMT_GENERIC_3 0x1F2B
+#define mmDIG1_AFMT_GENERIC_4 0x1F2C
+#define mmDIG1_AFMT_GENERIC_5 0x1F2D
+#define mmDIG1_AFMT_GENERIC_6 0x1F2E
+#define mmDIG1_AFMT_GENERIC_7 0x1F2F
+#define mmDIG1_AFMT_GENERIC_HDR 0x1F27
+#define mmDIG1_AFMT_INFOFRAME_CONTROL0 0x1F4D
+#define mmDIG1_AFMT_INTERRUPT_STATUS 0x1F14
+#define mmDIG1_AFMT_ISRC1_0 0x1F18
+#define mmDIG1_AFMT_ISRC1_1 0x1F19
+#define mmDIG1_AFMT_ISRC1_2 0x1F1A
+#define mmDIG1_AFMT_ISRC1_3 0x1F1B
+#define mmDIG1_AFMT_ISRC1_4 0x1F1C
+#define mmDIG1_AFMT_ISRC2_0 0x1F1D
+#define mmDIG1_AFMT_ISRC2_1 0x1F1E
+#define mmDIG1_AFMT_ISRC2_2 0x1F1F
+#define mmDIG1_AFMT_ISRC2_3 0x1F20
+#define mmDIG1_AFMT_MPEG_INFO0 0x1F25
+#define mmDIG1_AFMT_MPEG_INFO1 0x1F26
+#define mmDIG1_AFMT_RAMP_CONTROL0 0x1F44
+#define mmDIG1_AFMT_RAMP_CONTROL1 0x1F45
+#define mmDIG1_AFMT_RAMP_CONTROL2 0x1F46
+#define mmDIG1_AFMT_RAMP_CONTROL3 0x1F47
+#define mmDIG1_AFMT_STATUS 0x1F4A
+#define mmDIG1_AFMT_VBI_PACKET_CONTROL 0x1F4C
+#define mmDIG1_DIG_BE_CNTL 0x1F50
+#define mmDIG1_DIG_BE_EN_CNTL 0x1F51
+#define mmDIG1_DIG_CLOCK_PATTERN 0x1F03
+#define mmDIG1_DIG_DISPCLK_SWITCH_CNTL 0x1F08
+#define mmDIG1_DIG_DISPCLK_SWITCH_STATUS 0x1F09
+#define mmDIG1_DIG_FE_CNTL 0x1F00
+#define mmDIG1_DIG_FIFO_STATUS 0x1F0A
+#define mmDIG1_DIG_LANE_ENABLE 0x1F8D
+#define mmDIG1_DIG_OUTPUT_CRC_CNTL 0x1F01
+#define mmDIG1_DIG_OUTPUT_CRC_RESULT 0x1F02
+#define mmDIG1_DIG_RANDOM_PATTERN_SEED 0x1F05
+#define mmDIG1_DIG_TEST_PATTERN 0x1F04
+#define mmDIG1_HDMI_ACR_32_0 0x1F37
+#define mmDIG1_HDMI_ACR_32_1 0x1F38
+#define mmDIG1_HDMI_ACR_44_0 0x1F39
+#define mmDIG1_HDMI_ACR_44_1 0x1F3A
+#define mmDIG1_HDMI_ACR_48_0 0x1F3B
+#define mmDIG1_HDMI_ACR_48_1 0x1F3C
+#define mmDIG1_HDMI_ACR_PACKET_CONTROL 0x1F0F
+#define mmDIG1_HDMI_ACR_STATUS_0 0x1F3D
+#define mmDIG1_HDMI_ACR_STATUS_1 0x1F3E
+#define mmDIG1_HDMI_AUDIO_PACKET_CONTROL 0x1F0E
+#define mmDIG1_HDMI_CONTROL 0x1F0C
+#define mmDIG1_HDMI_GC 0x1F16
+#define mmDIG1_HDMI_GENERIC_PACKET_CONTROL0 0x1F13
+#define mmDIG1_HDMI_GENERIC_PACKET_CONTROL1 0x1F30
+#define mmDIG1_HDMI_INFOFRAME_CONTROL0 0x1F11
+#define mmDIG1_HDMI_INFOFRAME_CONTROL1 0x1F12
+#define mmDIG1_HDMI_STATUS 0x1F0D
+#define mmDIG1_HDMI_VBI_PACKET_CONTROL 0x1F10
+#define mmDIG1_LVDS_DATA_CNTL 0x1F8C
+#define mmDIG1_TMDS_CNTL 0x1F7C
+#define mmDIG1_TMDS_CONTROL0_FEEDBACK 0x1F7E
+#define mmDIG1_TMDS_CONTROL_CHAR 0x1F7D
+#define mmDIG1_TMDS_CTL0_1_GEN_CNTL 0x1F86
+#define mmDIG1_TMDS_CTL2_3_GEN_CNTL 0x1F87
+#define mmDIG1_TMDS_CTL_BITS 0x1F83
+#define mmDIG1_TMDS_DCBALANCER_CONTROL 0x1F84
+#define mmDIG1_TMDS_DEBUG 0x1F82
+#define mmDIG1_TMDS_STEREOSYNC_CTL_SEL 0x1F7F
+#define mmDIG1_TMDS_SYNC_CHAR_PATTERN_0_1 0x1F80
+#define mmDIG1_TMDS_SYNC_CHAR_PATTERN_2_3 0x1F81
+#define mmDIG2_AFMT_60958_0 0x4241
+#define mmDIG2_AFMT_60958_1 0x4242
+#define mmDIG2_AFMT_60958_2 0x4248
+#define mmDIG2_AFMT_AUDIO_CRC_CONTROL 0x4243
+#define mmDIG2_AFMT_AUDIO_CRC_RESULT 0x4249
+#define mmDIG2_AFMT_AUDIO_DBG_DTO_CNTL 0x4252
+#define mmDIG2_AFMT_AUDIO_INFO0 0x423F
+#define mmDIG2_AFMT_AUDIO_INFO1 0x4240
+#define mmDIG2_AFMT_AUDIO_PACKET_CONTROL 0x424B
+#define mmDIG2_AFMT_AUDIO_PACKET_CONTROL2 0x4217
+#define mmDIG2_AFMT_AUDIO_SRC_CONTROL 0x424F
+#define mmDIG2_AFMT_AVI_INFO0 0x4221
+#define mmDIG2_AFMT_AVI_INFO1 0x4222
+#define mmDIG2_AFMT_AVI_INFO2 0x4223
+#define mmDIG2_AFMT_AVI_INFO3 0x4224
+#define mmDIG2_AFMT_GENERIC_0 0x4228
+#define mmDIG2_AFMT_GENERIC_1 0x4229
+#define mmDIG2_AFMT_GENERIC_2 0x422A
+#define mmDIG2_AFMT_GENERIC_3 0x422B
+#define mmDIG2_AFMT_GENERIC_4 0x422C
+#define mmDIG2_AFMT_GENERIC_5 0x422D
+#define mmDIG2_AFMT_GENERIC_6 0x422E
+#define mmDIG2_AFMT_GENERIC_7 0x422F
+#define mmDIG2_AFMT_GENERIC_HDR 0x4227
+#define mmDIG2_AFMT_INFOFRAME_CONTROL0 0x424D
+#define mmDIG2_AFMT_INTERRUPT_STATUS 0x4214
+#define mmDIG2_AFMT_ISRC1_0 0x4218
+#define mmDIG2_AFMT_ISRC1_1 0x4219
+#define mmDIG2_AFMT_ISRC1_2 0x421A
+#define mmDIG2_AFMT_ISRC1_3 0x421B
+#define mmDIG2_AFMT_ISRC1_4 0x421C
+#define mmDIG2_AFMT_ISRC2_0 0x421D
+#define mmDIG2_AFMT_ISRC2_1 0x421E
+#define mmDIG2_AFMT_ISRC2_2 0x421F
+#define mmDIG2_AFMT_ISRC2_3 0x4220
+#define mmDIG2_AFMT_MPEG_INFO0 0x4225
+#define mmDIG2_AFMT_MPEG_INFO1 0x4226
+#define mmDIG2_AFMT_RAMP_CONTROL0 0x4244
+#define mmDIG2_AFMT_RAMP_CONTROL1 0x4245
+#define mmDIG2_AFMT_RAMP_CONTROL2 0x4246
+#define mmDIG2_AFMT_RAMP_CONTROL3 0x4247
+#define mmDIG2_AFMT_STATUS 0x424A
+#define mmDIG2_AFMT_VBI_PACKET_CONTROL 0x424C
+#define mmDIG2_DIG_BE_CNTL 0x4250
+#define mmDIG2_DIG_BE_EN_CNTL 0x4251
+#define mmDIG2_DIG_CLOCK_PATTERN 0x4203
+#define mmDIG2_DIG_DISPCLK_SWITCH_CNTL 0x4208
+#define mmDIG2_DIG_DISPCLK_SWITCH_STATUS 0x4209
+#define mmDIG2_DIG_FE_CNTL 0x4200
+#define mmDIG2_DIG_FIFO_STATUS 0x420A
+#define mmDIG2_DIG_LANE_ENABLE 0x428D
+#define mmDIG2_DIG_OUTPUT_CRC_CNTL 0x4201
+#define mmDIG2_DIG_OUTPUT_CRC_RESULT 0x4202
+#define mmDIG2_DIG_RANDOM_PATTERN_SEED 0x4205
+#define mmDIG2_DIG_TEST_PATTERN 0x4204
+#define mmDIG2_HDMI_ACR_32_0 0x4237
+#define mmDIG2_HDMI_ACR_32_1 0x4238
+#define mmDIG2_HDMI_ACR_44_0 0x4239
+#define mmDIG2_HDMI_ACR_44_1 0x423A
+#define mmDIG2_HDMI_ACR_48_0 0x423B
+#define mmDIG2_HDMI_ACR_48_1 0x423C
+#define mmDIG2_HDMI_ACR_PACKET_CONTROL 0x420F
+#define mmDIG2_HDMI_ACR_STATUS_0 0x423D
+#define mmDIG2_HDMI_ACR_STATUS_1 0x423E
+#define mmDIG2_HDMI_AUDIO_PACKET_CONTROL 0x420E
+#define mmDIG2_HDMI_CONTROL 0x420C
+#define mmDIG2_HDMI_GC 0x4216
+#define mmDIG2_HDMI_GENERIC_PACKET_CONTROL0 0x4213
+#define mmDIG2_HDMI_GENERIC_PACKET_CONTROL1 0x4230
+#define mmDIG2_HDMI_INFOFRAME_CONTROL0 0x4211
+#define mmDIG2_HDMI_INFOFRAME_CONTROL1 0x4212
+#define mmDIG2_HDMI_STATUS 0x420D
+#define mmDIG2_HDMI_VBI_PACKET_CONTROL 0x4210
+#define mmDIG2_LVDS_DATA_CNTL 0x428C
+#define mmDIG2_TMDS_CNTL 0x427C
+#define mmDIG2_TMDS_CONTROL0_FEEDBACK 0x427E
+#define mmDIG2_TMDS_CONTROL_CHAR 0x427D
+#define mmDIG2_TMDS_CTL0_1_GEN_CNTL 0x4286
+#define mmDIG2_TMDS_CTL2_3_GEN_CNTL 0x4287
+#define mmDIG2_TMDS_CTL_BITS 0x4283
+#define mmDIG2_TMDS_DCBALANCER_CONTROL 0x4284
+#define mmDIG2_TMDS_DEBUG 0x4282
+#define mmDIG2_TMDS_STEREOSYNC_CTL_SEL 0x427F
+#define mmDIG2_TMDS_SYNC_CHAR_PATTERN_0_1 0x4280
+#define mmDIG2_TMDS_SYNC_CHAR_PATTERN_2_3 0x4281
+#define mmDIG3_AFMT_60958_0 0x4541
+#define mmDIG3_AFMT_60958_1 0x4542
+#define mmDIG3_AFMT_60958_2 0x4548
+#define mmDIG3_AFMT_AUDIO_CRC_CONTROL 0x4543
+#define mmDIG3_AFMT_AUDIO_CRC_RESULT 0x4549
+#define mmDIG3_AFMT_AUDIO_DBG_DTO_CNTL 0x4552
+#define mmDIG3_AFMT_AUDIO_INFO0 0x453F
+#define mmDIG3_AFMT_AUDIO_INFO1 0x4540
+#define mmDIG3_AFMT_AUDIO_PACKET_CONTROL 0x454B
+#define mmDIG3_AFMT_AUDIO_PACKET_CONTROL2 0x4517
+#define mmDIG3_AFMT_AUDIO_SRC_CONTROL 0x454F
+#define mmDIG3_AFMT_AVI_INFO0 0x4521
+#define mmDIG3_AFMT_AVI_INFO1 0x4522
+#define mmDIG3_AFMT_AVI_INFO2 0x4523
+#define mmDIG3_AFMT_AVI_INFO3 0x4524
+#define mmDIG3_AFMT_GENERIC_0 0x4528
+#define mmDIG3_AFMT_GENERIC_1 0x4529
+#define mmDIG3_AFMT_GENERIC_2 0x452A
+#define mmDIG3_AFMT_GENERIC_3 0x452B
+#define mmDIG3_AFMT_GENERIC_4 0x452C
+#define mmDIG3_AFMT_GENERIC_5 0x452D
+#define mmDIG3_AFMT_GENERIC_6 0x452E
+#define mmDIG3_AFMT_GENERIC_7 0x452F
+#define mmDIG3_AFMT_GENERIC_HDR 0x4527
+#define mmDIG3_AFMT_INFOFRAME_CONTROL0 0x454D
+#define mmDIG3_AFMT_INTERRUPT_STATUS 0x4514
+#define mmDIG3_AFMT_ISRC1_0 0x4518
+#define mmDIG3_AFMT_ISRC1_1 0x4519
+#define mmDIG3_AFMT_ISRC1_2 0x451A
+#define mmDIG3_AFMT_ISRC1_3 0x451B
+#define mmDIG3_AFMT_ISRC1_4 0x451C
+#define mmDIG3_AFMT_ISRC2_0 0x451D
+#define mmDIG3_AFMT_ISRC2_1 0x451E
+#define mmDIG3_AFMT_ISRC2_2 0x451F
+#define mmDIG3_AFMT_ISRC2_3 0x4520
+#define mmDIG3_AFMT_MPEG_INFO0 0x4525
+#define mmDIG3_AFMT_MPEG_INFO1 0x4526
+#define mmDIG3_AFMT_RAMP_CONTROL0 0x4544
+#define mmDIG3_AFMT_RAMP_CONTROL1 0x4545
+#define mmDIG3_AFMT_RAMP_CONTROL2 0x4546
+#define mmDIG3_AFMT_RAMP_CONTROL3 0x4547
+#define mmDIG3_AFMT_STATUS 0x454A
+#define mmDIG3_AFMT_VBI_PACKET_CONTROL 0x454C
+#define mmDIG3_DIG_BE_CNTL 0x4550
+#define mmDIG3_DIG_BE_EN_CNTL 0x4551
+#define mmDIG3_DIG_CLOCK_PATTERN 0x4503
+#define mmDIG3_DIG_DISPCLK_SWITCH_CNTL 0x4508
+#define mmDIG3_DIG_DISPCLK_SWITCH_STATUS 0x4509
+#define mmDIG3_DIG_FE_CNTL 0x4500
+#define mmDIG3_DIG_FIFO_STATUS 0x450A
+#define mmDIG3_DIG_LANE_ENABLE 0x458D
+#define mmDIG3_DIG_OUTPUT_CRC_CNTL 0x4501
+#define mmDIG3_DIG_OUTPUT_CRC_RESULT 0x4502
+#define mmDIG3_DIG_RANDOM_PATTERN_SEED 0x4505
+#define mmDIG3_DIG_TEST_PATTERN 0x4504
+#define mmDIG3_HDMI_ACR_32_0 0x4537
+#define mmDIG3_HDMI_ACR_32_1 0x4538
+#define mmDIG3_HDMI_ACR_44_0 0x4539
+#define mmDIG3_HDMI_ACR_44_1 0x453A
+#define mmDIG3_HDMI_ACR_48_0 0x453B
+#define mmDIG3_HDMI_ACR_48_1 0x453C
+#define mmDIG3_HDMI_ACR_PACKET_CONTROL 0x450F
+#define mmDIG3_HDMI_ACR_STATUS_0 0x453D
+#define mmDIG3_HDMI_ACR_STATUS_1 0x453E
+#define mmDIG3_HDMI_AUDIO_PACKET_CONTROL 0x450E
+#define mmDIG3_HDMI_CONTROL 0x450C
+#define mmDIG3_HDMI_GC 0x4516
+#define mmDIG3_HDMI_GENERIC_PACKET_CONTROL0 0x4513
+#define mmDIG3_HDMI_GENERIC_PACKET_CONTROL1 0x4530
+#define mmDIG3_HDMI_INFOFRAME_CONTROL0 0x4511
+#define mmDIG3_HDMI_INFOFRAME_CONTROL1 0x4512
+#define mmDIG3_HDMI_STATUS 0x450D
+#define mmDIG3_HDMI_VBI_PACKET_CONTROL 0x4510
+#define mmDIG3_LVDS_DATA_CNTL 0x458C
+#define mmDIG3_TMDS_CNTL 0x457C
+#define mmDIG3_TMDS_CONTROL0_FEEDBACK 0x457E
+#define mmDIG3_TMDS_CONTROL_CHAR 0x457D
+#define mmDIG3_TMDS_CTL0_1_GEN_CNTL 0x4586
+#define mmDIG3_TMDS_CTL2_3_GEN_CNTL 0x4587
+#define mmDIG3_TMDS_CTL_BITS 0x4583
+#define mmDIG3_TMDS_DCBALANCER_CONTROL 0x4584
+#define mmDIG3_TMDS_DEBUG 0x4582
+#define mmDIG3_TMDS_STEREOSYNC_CTL_SEL 0x457F
+#define mmDIG3_TMDS_SYNC_CHAR_PATTERN_0_1 0x4580
+#define mmDIG3_TMDS_SYNC_CHAR_PATTERN_2_3 0x4581
+#define mmDIG4_AFMT_60958_0 0x4841
+#define mmDIG4_AFMT_60958_1 0x4842
+#define mmDIG4_AFMT_60958_2 0x4848
+#define mmDIG4_AFMT_AUDIO_CRC_CONTROL 0x4843
+#define mmDIG4_AFMT_AUDIO_CRC_RESULT 0x4849
+#define mmDIG4_AFMT_AUDIO_DBG_DTO_CNTL 0x4852
+#define mmDIG4_AFMT_AUDIO_INFO0 0x483F
+#define mmDIG4_AFMT_AUDIO_INFO1 0x4840
+#define mmDIG4_AFMT_AUDIO_PACKET_CONTROL 0x484B
+#define mmDIG4_AFMT_AUDIO_PACKET_CONTROL2 0x4817
+#define mmDIG4_AFMT_AUDIO_SRC_CONTROL 0x484F
+#define mmDIG4_AFMT_AVI_INFO0 0x4821
+#define mmDIG4_AFMT_AVI_INFO1 0x4822
+#define mmDIG4_AFMT_AVI_INFO2 0x4823
+#define mmDIG4_AFMT_AVI_INFO3 0x4824
+#define mmDIG4_AFMT_GENERIC_0 0x4828
+#define mmDIG4_AFMT_GENERIC_1 0x4829
+#define mmDIG4_AFMT_GENERIC_2 0x482A
+#define mmDIG4_AFMT_GENERIC_3 0x482B
+#define mmDIG4_AFMT_GENERIC_4 0x482C
+#define mmDIG4_AFMT_GENERIC_5 0x482D
+#define mmDIG4_AFMT_GENERIC_6 0x482E
+#define mmDIG4_AFMT_GENERIC_7 0x482F
+#define mmDIG4_AFMT_GENERIC_HDR 0x4827
+#define mmDIG4_AFMT_INFOFRAME_CONTROL0 0x484D
+#define mmDIG4_AFMT_INTERRUPT_STATUS 0x4814
+#define mmDIG4_AFMT_ISRC1_0 0x4818
+#define mmDIG4_AFMT_ISRC1_1 0x4819
+#define mmDIG4_AFMT_ISRC1_2 0x481A
+#define mmDIG4_AFMT_ISRC1_3 0x481B
+#define mmDIG4_AFMT_ISRC1_4 0x481C
+#define mmDIG4_AFMT_ISRC2_0 0x481D
+#define mmDIG4_AFMT_ISRC2_1 0x481E
+#define mmDIG4_AFMT_ISRC2_2 0x481F
+#define mmDIG4_AFMT_ISRC2_3 0x4820
+#define mmDIG4_AFMT_MPEG_INFO0 0x4825
+#define mmDIG4_AFMT_MPEG_INFO1 0x4826
+#define mmDIG4_AFMT_RAMP_CONTROL0 0x4844
+#define mmDIG4_AFMT_RAMP_CONTROL1 0x4845
+#define mmDIG4_AFMT_RAMP_CONTROL2 0x4846
+#define mmDIG4_AFMT_RAMP_CONTROL3 0x4847
+#define mmDIG4_AFMT_STATUS 0x484A
+#define mmDIG4_AFMT_VBI_PACKET_CONTROL 0x484C
+#define mmDIG4_DIG_BE_CNTL 0x4850
+#define mmDIG4_DIG_BE_EN_CNTL 0x4851
+#define mmDIG4_DIG_CLOCK_PATTERN 0x4803
+#define mmDIG4_DIG_DISPCLK_SWITCH_CNTL 0x4808
+#define mmDIG4_DIG_DISPCLK_SWITCH_STATUS 0x4809
+#define mmDIG4_DIG_FE_CNTL 0x4800
+#define mmDIG4_DIG_FIFO_STATUS 0x480A
+#define mmDIG4_DIG_LANE_ENABLE 0x488D
+#define mmDIG4_DIG_OUTPUT_CRC_CNTL 0x4801
+#define mmDIG4_DIG_OUTPUT_CRC_RESULT 0x4802
+#define mmDIG4_DIG_RANDOM_PATTERN_SEED 0x4805
+#define mmDIG4_DIG_TEST_PATTERN 0x4804
+#define mmDIG4_HDMI_ACR_32_0 0x4837
+#define mmDIG4_HDMI_ACR_32_1 0x4838
+#define mmDIG4_HDMI_ACR_44_0 0x4839
+#define mmDIG4_HDMI_ACR_44_1 0x483A
+#define mmDIG4_HDMI_ACR_48_0 0x483B
+#define mmDIG4_HDMI_ACR_48_1 0x483C
+#define mmDIG4_HDMI_ACR_PACKET_CONTROL 0x480F
+#define mmDIG4_HDMI_ACR_STATUS_0 0x483D
+#define mmDIG4_HDMI_ACR_STATUS_1 0x483E
+#define mmDIG4_HDMI_AUDIO_PACKET_CONTROL 0x480E
+#define mmDIG4_HDMI_CONTROL 0x480C
+#define mmDIG4_HDMI_GC 0x4816
+#define mmDIG4_HDMI_GENERIC_PACKET_CONTROL0 0x4813
+#define mmDIG4_HDMI_GENERIC_PACKET_CONTROL1 0x4830
+#define mmDIG4_HDMI_INFOFRAME_CONTROL0 0x4811
+#define mmDIG4_HDMI_INFOFRAME_CONTROL1 0x4812
+#define mmDIG4_HDMI_STATUS 0x480D
+#define mmDIG4_HDMI_VBI_PACKET_CONTROL 0x4810
+#define mmDIG4_LVDS_DATA_CNTL 0x488C
+#define mmDIG4_TMDS_CNTL 0x487C
+#define mmDIG4_TMDS_CONTROL0_FEEDBACK 0x487E
+#define mmDIG4_TMDS_CONTROL_CHAR 0x487D
+#define mmDIG4_TMDS_CTL0_1_GEN_CNTL 0x4886
+#define mmDIG4_TMDS_CTL2_3_GEN_CNTL 0x4887
+#define mmDIG4_TMDS_CTL_BITS 0x4883
+#define mmDIG4_TMDS_DCBALANCER_CONTROL 0x4884
+#define mmDIG4_TMDS_DEBUG 0x4882
+#define mmDIG4_TMDS_STEREOSYNC_CTL_SEL 0x487F
+#define mmDIG4_TMDS_SYNC_CHAR_PATTERN_0_1 0x4880
+#define mmDIG4_TMDS_SYNC_CHAR_PATTERN_2_3 0x4881
+#define mmDIG5_AFMT_60958_0 0x4B41
+#define mmDIG5_AFMT_60958_1 0x4B42
+#define mmDIG5_AFMT_60958_2 0x4B48
+#define mmDIG5_AFMT_AUDIO_CRC_CONTROL 0x4B43
+#define mmDIG5_AFMT_AUDIO_CRC_RESULT 0x4B49
+#define mmDIG5_AFMT_AUDIO_DBG_DTO_CNTL 0x4B52
+#define mmDIG5_AFMT_AUDIO_INFO0 0x4B3F
+#define mmDIG5_AFMT_AUDIO_INFO1 0x4B40
+#define mmDIG5_AFMT_AUDIO_PACKET_CONTROL 0x4B4B
+#define mmDIG5_AFMT_AUDIO_PACKET_CONTROL2 0x4B17
+#define mmDIG5_AFMT_AUDIO_SRC_CONTROL 0x4B4F
+#define mmDIG5_AFMT_AVI_INFO0 0x4B21
+#define mmDIG5_AFMT_AVI_INFO1 0x4B22
+#define mmDIG5_AFMT_AVI_INFO2 0x4B23
+#define mmDIG5_AFMT_AVI_INFO3 0x4B24
+#define mmDIG5_AFMT_GENERIC_0 0x4B28
+#define mmDIG5_AFMT_GENERIC_1 0x4B29
+#define mmDIG5_AFMT_GENERIC_2 0x4B2A
+#define mmDIG5_AFMT_GENERIC_3 0x4B2B
+#define mmDIG5_AFMT_GENERIC_4 0x4B2C
+#define mmDIG5_AFMT_GENERIC_5 0x4B2D
+#define mmDIG5_AFMT_GENERIC_6 0x4B2E
+#define mmDIG5_AFMT_GENERIC_7 0x4B2F
+#define mmDIG5_AFMT_GENERIC_HDR 0x4B27
+#define mmDIG5_AFMT_INFOFRAME_CONTROL0 0x4B4D
+#define mmDIG5_AFMT_INTERRUPT_STATUS 0x4B14
+#define mmDIG5_AFMT_ISRC1_0 0x4B18
+#define mmDIG5_AFMT_ISRC1_1 0x4B19
+#define mmDIG5_AFMT_ISRC1_2 0x4B1A
+#define mmDIG5_AFMT_ISRC1_3 0x4B1B
+#define mmDIG5_AFMT_ISRC1_4 0x4B1C
+#define mmDIG5_AFMT_ISRC2_0 0x4B1D
+#define mmDIG5_AFMT_ISRC2_1 0x4B1E
+#define mmDIG5_AFMT_ISRC2_2 0x4B1F
+#define mmDIG5_AFMT_ISRC2_3 0x4B20
+#define mmDIG5_AFMT_MPEG_INFO0 0x4B25
+#define mmDIG5_AFMT_MPEG_INFO1 0x4B26
+#define mmDIG5_AFMT_RAMP_CONTROL0 0x4B44
+#define mmDIG5_AFMT_RAMP_CONTROL1 0x4B45
+#define mmDIG5_AFMT_RAMP_CONTROL2 0x4B46
+#define mmDIG5_AFMT_RAMP_CONTROL3 0x4B47
+#define mmDIG5_AFMT_STATUS 0x4B4A
+#define mmDIG5_AFMT_VBI_PACKET_CONTROL 0x4B4C
+#define mmDIG5_DIG_BE_CNTL 0x4B50
+#define mmDIG5_DIG_BE_EN_CNTL 0x4B51
+#define mmDIG5_DIG_CLOCK_PATTERN 0x4B03
+#define mmDIG5_DIG_DISPCLK_SWITCH_CNTL 0x4B08
+#define mmDIG5_DIG_DISPCLK_SWITCH_STATUS 0x4B09
+#define mmDIG5_DIG_FE_CNTL 0x4B00
+#define mmDIG5_DIG_FIFO_STATUS 0x4B0A
+#define mmDIG5_DIG_LANE_ENABLE 0x4B8D
+#define mmDIG5_DIG_OUTPUT_CRC_CNTL 0x4B01
+#define mmDIG5_DIG_OUTPUT_CRC_RESULT 0x4B02
+#define mmDIG5_DIG_RANDOM_PATTERN_SEED 0x4B05
+#define mmDIG5_DIG_TEST_PATTERN 0x4B04
+#define mmDIG5_HDMI_ACR_32_0 0x4B37
+#define mmDIG5_HDMI_ACR_32_1 0x4B38
+#define mmDIG5_HDMI_ACR_44_0 0x4B39
+#define mmDIG5_HDMI_ACR_44_1 0x4B3A
+#define mmDIG5_HDMI_ACR_48_0 0x4B3B
+#define mmDIG5_HDMI_ACR_48_1 0x4B3C
+#define mmDIG5_HDMI_ACR_PACKET_CONTROL 0x4B0F
+#define mmDIG5_HDMI_ACR_STATUS_0 0x4B3D
+#define mmDIG5_HDMI_ACR_STATUS_1 0x4B3E
+#define mmDIG5_HDMI_AUDIO_PACKET_CONTROL 0x4B0E
+#define mmDIG5_HDMI_CONTROL 0x4B0C
+#define mmDIG5_HDMI_GC 0x4B16
+#define mmDIG5_HDMI_GENERIC_PACKET_CONTROL0 0x4B13
+#define mmDIG5_HDMI_GENERIC_PACKET_CONTROL1 0x4B30
+#define mmDIG5_HDMI_INFOFRAME_CONTROL0 0x4B11
+#define mmDIG5_HDMI_INFOFRAME_CONTROL1 0x4B12
+#define mmDIG5_HDMI_STATUS 0x4B0D
+#define mmDIG5_HDMI_VBI_PACKET_CONTROL 0x4B10
+#define mmDIG5_LVDS_DATA_CNTL 0x4B8C
+#define mmDIG5_TMDS_CNTL 0x4B7C
+#define mmDIG5_TMDS_CONTROL0_FEEDBACK 0x4B7E
+#define mmDIG5_TMDS_CONTROL_CHAR 0x4B7D
+#define mmDIG5_TMDS_CTL0_1_GEN_CNTL 0x4B86
+#define mmDIG5_TMDS_CTL2_3_GEN_CNTL 0x4B87
+#define mmDIG5_TMDS_CTL_BITS 0x4B83
+#define mmDIG5_TMDS_DCBALANCER_CONTROL 0x4B84
+#define mmDIG5_TMDS_DEBUG 0x4B82
+#define mmDIG5_TMDS_STEREOSYNC_CTL_SEL 0x4B7F
+#define mmDIG5_TMDS_SYNC_CHAR_PATTERN_0_1 0x4B80
+#define mmDIG5_TMDS_SYNC_CHAR_PATTERN_2_3 0x4B81
+#define mmDIG_BE_CNTL 0x1C50
+#define mmDIG_BE_EN_CNTL 0x1C51
+#define mmDIG_CLOCK_PATTERN 0x1C03
+#define mmDIG_DISPCLK_SWITCH_CNTL 0x1C08
+#define mmDIG_DISPCLK_SWITCH_STATUS 0x1C09
+#define mmDIG_FE_CNTL 0x1C00
+#define mmDIG_FIFO_STATUS 0x1C0A
+#define mmDIG_LANE_ENABLE 0x1C8D
+#define mmDIG_OUTPUT_CRC_CNTL 0x1C01
+#define mmDIG_OUTPUT_CRC_RESULT 0x1C02
+#define mmDIG_RANDOM_PATTERN_SEED 0x1C05
+#define mmDIG_SOFT_RESET 0x013D
+#define mmDIG_TEST_PATTERN 0x1C04
+#define mmDISPCLK_CGTT_BLK_CTRL_REG 0x0135
+#define mmDISPCLK_FREQ_CHANGE_CNTL 0x0131
+#define mmDISP_INTERRUPT_STATUS 0x183D
+#define mmDISP_INTERRUPT_STATUS_CONTINUE 0x183E
+#define mmDISP_INTERRUPT_STATUS_CONTINUE2 0x183F
+#define mmDISP_INTERRUPT_STATUS_CONTINUE3 0x1840
+#define mmDISP_INTERRUPT_STATUS_CONTINUE4 0x1853
+#define mmDISP_INTERRUPT_STATUS_CONTINUE5 0x1854
+#define mmDISPOUT_STEREOSYNC_SEL 0x18BF
+#define mmDISPPLL_BG_CNTL 0x013C
+#define mmDISP_TIMER_CONTROL 0x1842
+#define mmDMCU_CTRL 0x1600
+#define mmDMCU_ERAM_RD_CTRL 0x160B
+#define mmDMCU_ERAM_RD_DATA 0x160C
+#define mmDMCU_ERAM_WR_CTRL 0x1609
+#define mmDMCU_ERAM_WR_DATA 0x160A
+#define mmDMCU_EVENT_TRIGGER 0x1611
+#define mmDMCU_FW_CHECKSUM_SMPL_BYTE_POS 0x161A
+#define mmDMCU_FW_CS_HI 0x1606
+#define mmDMCU_FW_CS_LO 0x1607
+#define mmDMCU_FW_END_ADDR 0x1604
+#define mmDMCU_FW_ISR_START_ADDR 0x1605
+#define mmDMCU_FW_START_ADDR 0x1603
+#define mmDMCU_INT_CNT 0x1619
+#define mmDMCU_INTERRUPT_STATUS 0x1614
+#define mmDMCU_INTERRUPT_TO_HOST_EN_MASK 0x1615
+#define mmDMCU_INTERRUPT_TO_UC_EN_MASK 0x1616
+#define mmDMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL 0x1617
+#define mmDMCU_IRAM_RD_CTRL 0x160F
+#define mmDMCU_IRAM_RD_DATA 0x1610
+#define mmDMCU_IRAM_WR_CTRL 0x160D
+#define mmDMCU_IRAM_WR_DATA 0x160E
+#define mmDMCU_PC_START_ADDR 0x1602
+#define mmDMCU_RAM_ACCESS_CTRL 0x1608
+#define mmDMCU_STATUS 0x1601
+#define mmDMCU_TEST_DEBUG_DATA 0x1627
+#define mmDMCU_TEST_DEBUG_INDEX 0x1626
+#define mmDMCU_UC_CLK_GATING_CNTL 0x161B
+#define mmDMCU_UC_INTERNAL_INT_STATUS 0x1612
+#define mmDMIF_ADDR_CALC 0x0300
+#define mmDMIF_ADDR_CONFIG 0x02F5
+#define mmDMIF_ARBITRATION_CONTROL 0x02F9
+#define mmDMIF_CONTROL 0x02F6
+#define mmDMIF_HW_DEBUG 0x02F8
+#define mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL1 0x1B30
+#define mmDMIF_PG0_DPG_PIPE_ARBITRATION_CONTROL2 0x1B31
+#define mmDMIF_PG0_DPG_PIPE_DPM_CONTROL 0x1B34
+#define mmDMIF_PG0_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x1B36
+#define mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL 0x1B35
+#define mmDMIF_PG0_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x1B37
+#define mmDMIF_PG0_DPG_PIPE_URGENCY_CONTROL 0x1B33
+#define mmDMIF_PG0_DPG_TEST_DEBUG_DATA 0x1B39
+#define mmDMIF_PG0_DPG_TEST_DEBUG_INDEX 0x1B38
+#define mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL1 0x1E30
+#define mmDMIF_PG1_DPG_PIPE_ARBITRATION_CONTROL2 0x1E31
+#define mmDMIF_PG1_DPG_PIPE_DPM_CONTROL 0x1E34
+#define mmDMIF_PG1_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x1E36
+#define mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL 0x1E35
+#define mmDMIF_PG1_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x1E37
+#define mmDMIF_PG1_DPG_PIPE_URGENCY_CONTROL 0x1E33
+#define mmDMIF_PG1_DPG_TEST_DEBUG_DATA 0x1E39
+#define mmDMIF_PG1_DPG_TEST_DEBUG_INDEX 0x1E38
+#define mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL1 0x4130
+#define mmDMIF_PG2_DPG_PIPE_ARBITRATION_CONTROL2 0x4131
+#define mmDMIF_PG2_DPG_PIPE_DPM_CONTROL 0x4134
+#define mmDMIF_PG2_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4136
+#define mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL 0x4135
+#define mmDMIF_PG2_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4137
+#define mmDMIF_PG2_DPG_PIPE_URGENCY_CONTROL 0x4133
+#define mmDMIF_PG2_DPG_TEST_DEBUG_DATA 0x4139
+#define mmDMIF_PG2_DPG_TEST_DEBUG_INDEX 0x4138
+#define mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL1 0x4430
+#define mmDMIF_PG3_DPG_PIPE_ARBITRATION_CONTROL2 0x4431
+#define mmDMIF_PG3_DPG_PIPE_DPM_CONTROL 0x4434
+#define mmDMIF_PG3_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4436
+#define mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL 0x4435
+#define mmDMIF_PG3_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4437
+#define mmDMIF_PG3_DPG_PIPE_URGENCY_CONTROL 0x4433
+#define mmDMIF_PG3_DPG_TEST_DEBUG_DATA 0x4439
+#define mmDMIF_PG3_DPG_TEST_DEBUG_INDEX 0x4438
+#define mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL1 0x4730
+#define mmDMIF_PG4_DPG_PIPE_ARBITRATION_CONTROL2 0x4731
+#define mmDMIF_PG4_DPG_PIPE_DPM_CONTROL 0x4734
+#define mmDMIF_PG4_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4736
+#define mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL 0x4735
+#define mmDMIF_PG4_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4737
+#define mmDMIF_PG4_DPG_PIPE_URGENCY_CONTROL 0x4733
+#define mmDMIF_PG4_DPG_TEST_DEBUG_DATA 0x4739
+#define mmDMIF_PG4_DPG_TEST_DEBUG_INDEX 0x4738
+#define mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL1 0x4A30
+#define mmDMIF_PG5_DPG_PIPE_ARBITRATION_CONTROL2 0x4A31
+#define mmDMIF_PG5_DPG_PIPE_DPM_CONTROL 0x4A34
+#define mmDMIF_PG5_DPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x4A36
+#define mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL 0x4A35
+#define mmDMIF_PG5_DPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x4A37
+#define mmDMIF_PG5_DPG_PIPE_URGENCY_CONTROL 0x4A33
+#define mmDMIF_PG5_DPG_TEST_DEBUG_DATA 0x4A39
+#define mmDMIF_PG5_DPG_TEST_DEBUG_INDEX 0x4A38
+#define mmDMIF_STATUS 0x02F7
+#define mmDMIF_STATUS2 0x0301
+#define mmDMIF_TEST_DEBUG_DATA 0x0313
+#define mmDMIF_TEST_DEBUG_INDEX 0x0312
+#define mmDOUT_DCE_VCE_CONTROL 0x18FF
+#define mmDOUT_POWER_MANAGEMENT_CNTL 0x1841
+#define mmDOUT_SCRATCH0 0x1844
+#define mmDOUT_SCRATCH1 0x1845
+#define mmDOUT_SCRATCH2 0x1846
+#define mmDOUT_SCRATCH3 0x1847
+#define mmDOUT_SCRATCH4 0x1848
+#define mmDOUT_SCRATCH5 0x1849
+#define mmDOUT_SCRATCH6 0x184A
+#define mmDOUT_SCRATCH7 0x184B
+#define mmDOUT_TEST_DEBUG_DATA 0x184E
+#define mmDOUT_TEST_DEBUG_INDEX 0x184D
+#define mmDP0_DP_CONFIG 0x1CC2
+#define mmDP0_DP_DPHY_8B10B_CNTL 0x1CD3
+#define mmDP0_DP_DPHY_CNTL 0x1CD0
+#define mmDP0_DP_DPHY_CRC_CNTL 0x1CD7
+#define mmDP0_DP_DPHY_CRC_EN 0x1CD6
+#define mmDP0_DP_DPHY_CRC_MST_CNTL 0x1CC6
+#define mmDP0_DP_DPHY_CRC_MST_STATUS 0x1CC7
+#define mmDP0_DP_DPHY_CRC_RESULT 0x1CD8
+#define mmDP0_DP_DPHY_FAST_TRAINING 0x1CCE
+#define mmDP0_DP_DPHY_FAST_TRAINING_STATUS 0x1CE9
+#define mmDP0_DP_DPHY_PRBS_CNTL 0x1CD4
+#define mmDP0_DP_DPHY_SYM0 0x1CD2
+#define mmDP0_DP_DPHY_SYM1 0x1CE0
+#define mmDP0_DP_DPHY_SYM2 0x1CDF
+#define mmDP0_DP_DPHY_TRAINING_PATTERN_SEL 0x1CD1
+#define mmDP0_DP_HBR2_EYE_PATTERN 0x1CC8
+#define mmDP0_DP_LINK_CNTL 0x1CC0
+#define mmDP0_DP_LINK_FRAMING_CNTL 0x1CCC
+#define mmDP0_DP_MSA_COLORIMETRY 0x1CDA
+#define mmDP0_DP_MSA_MISC 0x1CC5
+#define mmDP0_DP_MSA_V_TIMING_OVERRIDE1 0x1CEA
+#define mmDP0_DP_MSA_V_TIMING_OVERRIDE2 0x1CEB
+#define mmDP0_DP_MSE_LINK_TIMING 0x1CE8
+#define mmDP0_DP_MSE_MISC_CNTL 0x1CDB
+#define mmDP0_DP_MSE_RATE_CNTL 0x1CE1
+#define mmDP0_DP_MSE_RATE_UPDATE 0x1CE3
+#define mmDP0_DP_MSE_SAT0 0x1CE4
+#define mmDP0_DP_MSE_SAT1 0x1CE5
+#define mmDP0_DP_MSE_SAT2 0x1CE6
+#define mmDP0_DP_MSE_SAT_UPDATE 0x1CE7
+#define mmDP0_DP_PIXEL_FORMAT 0x1CC1
+#define mmDP0_DP_SEC_AUD_M 0x1CA7
+#define mmDP0_DP_SEC_AUD_M_READBACK 0x1CA8
+#define mmDP0_DP_SEC_AUD_N 0x1CA5
+#define mmDP0_DP_SEC_AUD_N_READBACK 0x1CA6
+#define mmDP0_DP_SEC_CNTL 0x1CA0
+#define mmDP0_DP_SEC_CNTL1 0x1CAB
+#define mmDP0_DP_SEC_FRAMING1 0x1CA1
+#define mmDP0_DP_SEC_FRAMING2 0x1CA2
+#define mmDP0_DP_SEC_FRAMING3 0x1CA3
+#define mmDP0_DP_SEC_FRAMING4 0x1CA4
+#define mmDP0_DP_SEC_PACKET_CNTL 0x1CAA
+#define mmDP0_DP_SEC_TIMESTAMP 0x1CA9
+#define mmDP0_DP_STEER_FIFO 0x1CC4
+#define mmDP0_DP_TEST_DEBUG_DATA 0x1CFD
+#define mmDP0_DP_TEST_DEBUG_INDEX 0x1CFC
+#define mmDP0_DP_VID_INTERRUPT_CNTL 0x1CCF
+#define mmDP0_DP_VID_M 0x1CCB
+#define mmDP0_DP_VID_MSA_VBID 0x1CCD
+#define mmDP0_DP_VID_N 0x1CCA
+#define mmDP0_DP_VID_STREAM_CNTL 0x1CC3
+#define mmDP0_DP_VID_TIMING 0x1CC9
+#define mmDP1_DP_CONFIG 0x1FC2
+#define mmDP1_DP_DPHY_8B10B_CNTL 0x1FD3
+#define mmDP1_DP_DPHY_CNTL 0x1FD0
+#define mmDP1_DP_DPHY_CRC_CNTL 0x1FD7
+#define mmDP1_DP_DPHY_CRC_EN 0x1FD6
+#define mmDP1_DP_DPHY_CRC_MST_CNTL 0x1FC6
+#define mmDP1_DP_DPHY_CRC_MST_STATUS 0x1FC7
+#define mmDP1_DP_DPHY_CRC_RESULT 0x1FD8
+#define mmDP1_DP_DPHY_FAST_TRAINING 0x1FCE
+#define mmDP1_DP_DPHY_FAST_TRAINING_STATUS 0x1FE9
+#define mmDP1_DP_DPHY_PRBS_CNTL 0x1FD4
+#define mmDP1_DP_DPHY_SYM0 0x1FD2
+#define mmDP1_DP_DPHY_SYM1 0x1FE0
+#define mmDP1_DP_DPHY_SYM2 0x1FDF
+#define mmDP1_DP_DPHY_TRAINING_PATTERN_SEL 0x1FD1
+#define mmDP1_DP_HBR2_EYE_PATTERN 0x1FC8
+#define mmDP1_DP_LINK_CNTL 0x1FC0
+#define mmDP1_DP_LINK_FRAMING_CNTL 0x1FCC
+#define mmDP1_DP_MSA_COLORIMETRY 0x1FDA
+#define mmDP1_DP_MSA_MISC 0x1FC5
+#define mmDP1_DP_MSA_V_TIMING_OVERRIDE1 0x1FEA
+#define mmDP1_DP_MSA_V_TIMING_OVERRIDE2 0x1FEB
+#define mmDP1_DP_MSE_LINK_TIMING 0x1FE8
+#define mmDP1_DP_MSE_MISC_CNTL 0x1FDB
+#define mmDP1_DP_MSE_RATE_CNTL 0x1FE1
+#define mmDP1_DP_MSE_RATE_UPDATE 0x1FE3
+#define mmDP1_DP_MSE_SAT0 0x1FE4
+#define mmDP1_DP_MSE_SAT1 0x1FE5
+#define mmDP1_DP_MSE_SAT2 0x1FE6
+#define mmDP1_DP_MSE_SAT_UPDATE 0x1FE7
+#define mmDP1_DP_PIXEL_FORMAT 0x1FC1
+#define mmDP1_DP_SEC_AUD_M 0x1FA7
+#define mmDP1_DP_SEC_AUD_M_READBACK 0x1FA8
+#define mmDP1_DP_SEC_AUD_N 0x1FA5
+#define mmDP1_DP_SEC_AUD_N_READBACK 0x1FA6
+#define mmDP1_DP_SEC_CNTL 0x1FA0
+#define mmDP1_DP_SEC_CNTL1 0x1FAB
+#define mmDP1_DP_SEC_FRAMING1 0x1FA1
+#define mmDP1_DP_SEC_FRAMING2 0x1FA2
+#define mmDP1_DP_SEC_FRAMING3 0x1FA3
+#define mmDP1_DP_SEC_FRAMING4 0x1FA4
+#define mmDP1_DP_SEC_PACKET_CNTL 0x1FAA
+#define mmDP1_DP_SEC_TIMESTAMP 0x1FA9
+#define mmDP1_DP_STEER_FIFO 0x1FC4
+#define mmDP1_DP_TEST_DEBUG_DATA 0x1FFD
+#define mmDP1_DP_TEST_DEBUG_INDEX 0x1FFC
+#define mmDP1_DP_VID_INTERRUPT_CNTL 0x1FCF
+#define mmDP1_DP_VID_M 0x1FCB
+#define mmDP1_DP_VID_MSA_VBID 0x1FCD
+#define mmDP1_DP_VID_N 0x1FCA
+#define mmDP1_DP_VID_STREAM_CNTL 0x1FC3
+#define mmDP1_DP_VID_TIMING 0x1FC9
+#define mmDP2_DP_CONFIG 0x42C2
+#define mmDP2_DP_DPHY_8B10B_CNTL 0x42D3
+#define mmDP2_DP_DPHY_CNTL 0x42D0
+#define mmDP2_DP_DPHY_CRC_CNTL 0x42D7
+#define mmDP2_DP_DPHY_CRC_EN 0x42D6
+#define mmDP2_DP_DPHY_CRC_MST_CNTL 0x42C6
+#define mmDP2_DP_DPHY_CRC_MST_STATUS 0x42C7
+#define mmDP2_DP_DPHY_CRC_RESULT 0x42D8
+#define mmDP2_DP_DPHY_FAST_TRAINING 0x42CE
+#define mmDP2_DP_DPHY_FAST_TRAINING_STATUS 0x42E9
+#define mmDP2_DP_DPHY_PRBS_CNTL 0x42D4
+#define mmDP2_DP_DPHY_SYM0 0x42D2
+#define mmDP2_DP_DPHY_SYM1 0x42E0
+#define mmDP2_DP_DPHY_SYM2 0x42DF
+#define mmDP2_DP_DPHY_TRAINING_PATTERN_SEL 0x42D1
+#define mmDP2_DP_HBR2_EYE_PATTERN 0x42C8
+#define mmDP2_DP_LINK_CNTL 0x42C0
+#define mmDP2_DP_LINK_FRAMING_CNTL 0x42CC
+#define mmDP2_DP_MSA_COLORIMETRY 0x42DA
+#define mmDP2_DP_MSA_MISC 0x42C5
+#define mmDP2_DP_MSA_V_TIMING_OVERRIDE1 0x42EA
+#define mmDP2_DP_MSA_V_TIMING_OVERRIDE2 0x42EB
+#define mmDP2_DP_MSE_LINK_TIMING 0x42E8
+#define mmDP2_DP_MSE_MISC_CNTL 0x42DB
+#define mmDP2_DP_MSE_RATE_CNTL 0x42E1
+#define mmDP2_DP_MSE_RATE_UPDATE 0x42E3
+#define mmDP2_DP_MSE_SAT0 0x42E4
+#define mmDP2_DP_MSE_SAT1 0x42E5
+#define mmDP2_DP_MSE_SAT2 0x42E6
+#define mmDP2_DP_MSE_SAT_UPDATE 0x42E7
+#define mmDP2_DP_PIXEL_FORMAT 0x42C1
+#define mmDP2_DP_SEC_AUD_M 0x42A7
+#define mmDP2_DP_SEC_AUD_M_READBACK 0x42A8
+#define mmDP2_DP_SEC_AUD_N 0x42A5
+#define mmDP2_DP_SEC_AUD_N_READBACK 0x42A6
+#define mmDP2_DP_SEC_CNTL 0x42A0
+#define mmDP2_DP_SEC_CNTL1 0x42AB
+#define mmDP2_DP_SEC_FRAMING1 0x42A1
+#define mmDP2_DP_SEC_FRAMING2 0x42A2
+#define mmDP2_DP_SEC_FRAMING3 0x42A3
+#define mmDP2_DP_SEC_FRAMING4 0x42A4
+#define mmDP2_DP_SEC_PACKET_CNTL 0x42AA
+#define mmDP2_DP_SEC_TIMESTAMP 0x42A9
+#define mmDP2_DP_STEER_FIFO 0x42C4
+#define mmDP2_DP_TEST_DEBUG_DATA 0x42FD
+#define mmDP2_DP_TEST_DEBUG_INDEX 0x42FC
+#define mmDP2_DP_VID_INTERRUPT_CNTL 0x42CF
+#define mmDP2_DP_VID_M 0x42CB
+#define mmDP2_DP_VID_MSA_VBID 0x42CD
+#define mmDP2_DP_VID_N 0x42CA
+#define mmDP2_DP_VID_STREAM_CNTL 0x42C3
+#define mmDP2_DP_VID_TIMING 0x42C9
+#define mmDP3_DP_CONFIG 0x45C2
+#define mmDP3_DP_DPHY_8B10B_CNTL 0x45D3
+#define mmDP3_DP_DPHY_CNTL 0x45D0
+#define mmDP3_DP_DPHY_CRC_CNTL 0x45D7
+#define mmDP3_DP_DPHY_CRC_EN 0x45D6
+#define mmDP3_DP_DPHY_CRC_MST_CNTL 0x45C6
+#define mmDP3_DP_DPHY_CRC_MST_STATUS 0x45C7
+#define mmDP3_DP_DPHY_CRC_RESULT 0x45D8
+#define mmDP3_DP_DPHY_FAST_TRAINING 0x45CE
+#define mmDP3_DP_DPHY_FAST_TRAINING_STATUS 0x45E9
+#define mmDP3_DP_DPHY_PRBS_CNTL 0x45D4
+#define mmDP3_DP_DPHY_SYM0 0x45D2
+#define mmDP3_DP_DPHY_SYM1 0x45E0
+#define mmDP3_DP_DPHY_SYM2 0x45DF
+#define mmDP3_DP_DPHY_TRAINING_PATTERN_SEL 0x45D1
+#define mmDP3_DP_HBR2_EYE_PATTERN 0x45C8
+#define mmDP3_DP_LINK_CNTL 0x45C0
+#define mmDP3_DP_LINK_FRAMING_CNTL 0x45CC
+#define mmDP3_DP_MSA_COLORIMETRY 0x45DA
+#define mmDP3_DP_MSA_MISC 0x45C5
+#define mmDP3_DP_MSA_V_TIMING_OVERRIDE1 0x45EA
+#define mmDP3_DP_MSA_V_TIMING_OVERRIDE2 0x45EB
+#define mmDP3_DP_MSE_LINK_TIMING 0x45E8
+#define mmDP3_DP_MSE_MISC_CNTL 0x45DB
+#define mmDP3_DP_MSE_RATE_CNTL 0x45E1
+#define mmDP3_DP_MSE_RATE_UPDATE 0x45E3
+#define mmDP3_DP_MSE_SAT0 0x45E4
+#define mmDP3_DP_MSE_SAT1 0x45E5
+#define mmDP3_DP_MSE_SAT2 0x45E6
+#define mmDP3_DP_MSE_SAT_UPDATE 0x45E7
+#define mmDP3_DP_PIXEL_FORMAT 0x45C1
+#define mmDP3_DP_SEC_AUD_M 0x45A7
+#define mmDP3_DP_SEC_AUD_M_READBACK 0x45A8
+#define mmDP3_DP_SEC_AUD_N 0x45A5
+#define mmDP3_DP_SEC_AUD_N_READBACK 0x45A6
+#define mmDP3_DP_SEC_CNTL 0x45A0
+#define mmDP3_DP_SEC_CNTL1 0x45AB
+#define mmDP3_DP_SEC_FRAMING1 0x45A1
+#define mmDP3_DP_SEC_FRAMING2 0x45A2
+#define mmDP3_DP_SEC_FRAMING3 0x45A3
+#define mmDP3_DP_SEC_FRAMING4 0x45A4
+#define mmDP3_DP_SEC_PACKET_CNTL 0x45AA
+#define mmDP3_DP_SEC_TIMESTAMP 0x45A9
+#define mmDP3_DP_STEER_FIFO 0x45C4
+#define mmDP3_DP_TEST_DEBUG_DATA 0x45FD
+#define mmDP3_DP_TEST_DEBUG_INDEX 0x45FC
+#define mmDP3_DP_VID_INTERRUPT_CNTL 0x45CF
+#define mmDP3_DP_VID_M 0x45CB
+#define mmDP3_DP_VID_MSA_VBID 0x45CD
+#define mmDP3_DP_VID_N 0x45CA
+#define mmDP3_DP_VID_STREAM_CNTL 0x45C3
+#define mmDP3_DP_VID_TIMING 0x45C9
+#define mmDP4_DP_CONFIG 0x48C2
+#define mmDP4_DP_DPHY_8B10B_CNTL 0x48D3
+#define mmDP4_DP_DPHY_CNTL 0x48D0
+#define mmDP4_DP_DPHY_CRC_CNTL 0x48D7
+#define mmDP4_DP_DPHY_CRC_EN 0x48D6
+#define mmDP4_DP_DPHY_CRC_MST_CNTL 0x48C6
+#define mmDP4_DP_DPHY_CRC_MST_STATUS 0x48C7
+#define mmDP4_DP_DPHY_CRC_RESULT 0x48D8
+#define mmDP4_DP_DPHY_FAST_TRAINING 0x48CE
+#define mmDP4_DP_DPHY_FAST_TRAINING_STATUS 0x48E9
+#define mmDP4_DP_DPHY_PRBS_CNTL 0x48D4
+#define mmDP4_DP_DPHY_SYM0 0x48D2
+#define mmDP4_DP_DPHY_SYM1 0x48E0
+#define mmDP4_DP_DPHY_SYM2 0x48DF
+#define mmDP4_DP_DPHY_TRAINING_PATTERN_SEL 0x48D1
+#define mmDP4_DP_HBR2_EYE_PATTERN 0x48C8
+#define mmDP4_DP_LINK_CNTL 0x48C0
+#define mmDP4_DP_LINK_FRAMING_CNTL 0x48CC
+#define mmDP4_DP_MSA_COLORIMETRY 0x48DA
+#define mmDP4_DP_MSA_MISC 0x48C5
+#define mmDP4_DP_MSA_V_TIMING_OVERRIDE1 0x48EA
+#define mmDP4_DP_MSA_V_TIMING_OVERRIDE2 0x48EB
+#define mmDP4_DP_MSE_LINK_TIMING 0x48E8
+#define mmDP4_DP_MSE_MISC_CNTL 0x48DB
+#define mmDP4_DP_MSE_RATE_CNTL 0x48E1
+#define mmDP4_DP_MSE_RATE_UPDATE 0x48E3
+#define mmDP4_DP_MSE_SAT0 0x48E4
+#define mmDP4_DP_MSE_SAT1 0x48E5
+#define mmDP4_DP_MSE_SAT2 0x48E6
+#define mmDP4_DP_MSE_SAT_UPDATE 0x48E7
+#define mmDP4_DP_PIXEL_FORMAT 0x48C1
+#define mmDP4_DP_SEC_AUD_M 0x48A7
+#define mmDP4_DP_SEC_AUD_M_READBACK 0x48A8
+#define mmDP4_DP_SEC_AUD_N 0x48A5
+#define mmDP4_DP_SEC_AUD_N_READBACK 0x48A6
+#define mmDP4_DP_SEC_CNTL 0x48A0
+#define mmDP4_DP_SEC_CNTL1 0x48AB
+#define mmDP4_DP_SEC_FRAMING1 0x48A1
+#define mmDP4_DP_SEC_FRAMING2 0x48A2
+#define mmDP4_DP_SEC_FRAMING3 0x48A3
+#define mmDP4_DP_SEC_FRAMING4 0x48A4
+#define mmDP4_DP_SEC_PACKET_CNTL 0x48AA
+#define mmDP4_DP_SEC_TIMESTAMP 0x48A9
+#define mmDP4_DP_STEER_FIFO 0x48C4
+#define mmDP4_DP_TEST_DEBUG_DATA 0x48FD
+#define mmDP4_DP_TEST_DEBUG_INDEX 0x48FC
+#define mmDP4_DP_VID_INTERRUPT_CNTL 0x48CF
+#define mmDP4_DP_VID_M 0x48CB
+#define mmDP4_DP_VID_MSA_VBID 0x48CD
+#define mmDP4_DP_VID_N 0x48CA
+#define mmDP4_DP_VID_STREAM_CNTL 0x48C3
+#define mmDP4_DP_VID_TIMING 0x48C9
+#define mmDP5_DP_CONFIG 0x4BC2
+#define mmDP5_DP_DPHY_8B10B_CNTL 0x4BD3
+#define mmDP5_DP_DPHY_CNTL 0x4BD0
+#define mmDP5_DP_DPHY_CRC_CNTL 0x4BD7
+#define mmDP5_DP_DPHY_CRC_EN 0x4BD6
+#define mmDP5_DP_DPHY_CRC_MST_CNTL 0x4BC6
+#define mmDP5_DP_DPHY_CRC_MST_STATUS 0x4BC7
+#define mmDP5_DP_DPHY_CRC_RESULT 0x4BD8
+#define mmDP5_DP_DPHY_FAST_TRAINING 0x4BCE
+#define mmDP5_DP_DPHY_FAST_TRAINING_STATUS 0x4BE9
+#define mmDP5_DP_DPHY_PRBS_CNTL 0x4BD4
+#define mmDP5_DP_DPHY_SYM0 0x4BD2
+#define mmDP5_DP_DPHY_SYM1 0x4BE0
+#define mmDP5_DP_DPHY_SYM2 0x4BDF
+#define mmDP5_DP_DPHY_TRAINING_PATTERN_SEL 0x4BD1
+#define mmDP5_DP_HBR2_EYE_PATTERN 0x4BC8
+#define mmDP5_DP_LINK_CNTL 0x4BC0
+#define mmDP5_DP_LINK_FRAMING_CNTL 0x4BCC
+#define mmDP5_DP_MSA_COLORIMETRY 0x4BDA
+#define mmDP5_DP_MSA_MISC 0x4BC5
+#define mmDP5_DP_MSA_V_TIMING_OVERRIDE1 0x4BEA
+#define mmDP5_DP_MSA_V_TIMING_OVERRIDE2 0x4BEB
+#define mmDP5_DP_MSE_LINK_TIMING 0x4BE8
+#define mmDP5_DP_MSE_MISC_CNTL 0x4BDB
+#define mmDP5_DP_MSE_RATE_CNTL 0x4BE1
+#define mmDP5_DP_MSE_RATE_UPDATE 0x4BE3
+#define mmDP5_DP_MSE_SAT0 0x4BE4
+#define mmDP5_DP_MSE_SAT1 0x4BE5
+#define mmDP5_DP_MSE_SAT2 0x4BE6
+#define mmDP5_DP_MSE_SAT_UPDATE 0x4BE7
+#define mmDP5_DP_PIXEL_FORMAT 0x4BC1
+#define mmDP5_DP_SEC_AUD_M 0x4BA7
+#define mmDP5_DP_SEC_AUD_M_READBACK 0x4BA8
+#define mmDP5_DP_SEC_AUD_N 0x4BA5
+#define mmDP5_DP_SEC_AUD_N_READBACK 0x4BA6
+#define mmDP5_DP_SEC_CNTL 0x4BA0
+#define mmDP5_DP_SEC_CNTL1 0x4BAB
+#define mmDP5_DP_SEC_FRAMING1 0x4BA1
+#define mmDP5_DP_SEC_FRAMING2 0x4BA2
+#define mmDP5_DP_SEC_FRAMING3 0x4BA3
+#define mmDP5_DP_SEC_FRAMING4 0x4BA4
+#define mmDP5_DP_SEC_PACKET_CNTL 0x4BAA
+#define mmDP5_DP_SEC_TIMESTAMP 0x4BA9
+#define mmDP5_DP_STEER_FIFO 0x4BC4
+#define mmDP5_DP_TEST_DEBUG_DATA 0x4BFD
+#define mmDP5_DP_TEST_DEBUG_INDEX 0x4BFC
+#define mmDP5_DP_VID_INTERRUPT_CNTL 0x4BCF
+#define mmDP5_DP_VID_M 0x4BCB
+#define mmDP5_DP_VID_MSA_VBID 0x4BCD
+#define mmDP5_DP_VID_N 0x4BCA
+#define mmDP5_DP_VID_STREAM_CNTL 0x4BC3
+#define mmDP5_DP_VID_TIMING 0x4BC9
+#define mmDP_AUX0_AUX_ARB_CONTROL 0x1882
+#define mmDP_AUX0_AUX_CONTROL 0x1880
+#define mmDP_AUX0_AUX_DPHY_RX_CONTROL0 0x188A
+#define mmDP_AUX0_AUX_DPHY_RX_CONTROL1 0x188B
+#define mmDP_AUX0_AUX_DPHY_RX_STATUS 0x188D
+#define mmDP_AUX0_AUX_DPHY_TX_CONTROL 0x1889
+#define mmDP_AUX0_AUX_DPHY_TX_REF_CONTROL 0x1888
+#define mmDP_AUX0_AUX_DPHY_TX_STATUS 0x188C
+#define mmDP_AUX0_AUX_GTC_SYNC_CONTROL 0x188E
+#define mmDP_AUX0_AUX_GTC_SYNC_DATA 0x1890
+#define mmDP_AUX0_AUX_INTERRUPT_CONTROL 0x1883
+#define mmDP_AUX0_AUX_LS_DATA 0x1887
+#define mmDP_AUX0_AUX_LS_STATUS 0x1885
+#define mmDP_AUX0_AUX_SW_CONTROL 0x1881
+#define mmDP_AUX0_AUX_SW_DATA 0x1886
+#define mmDP_AUX0_AUX_SW_STATUS 0x1884
+#define mmDP_AUX1_AUX_ARB_CONTROL 0x1896
+#define mmDP_AUX1_AUX_CONTROL 0x1894
+#define mmDP_AUX1_AUX_DPHY_RX_CONTROL0 0x189E
+#define mmDP_AUX1_AUX_DPHY_RX_CONTROL1 0x189F
+#define mmDP_AUX1_AUX_DPHY_RX_STATUS 0x18A1
+#define mmDP_AUX1_AUX_DPHY_TX_CONTROL 0x189D
+#define mmDP_AUX1_AUX_DPHY_TX_REF_CONTROL 0x189C
+#define mmDP_AUX1_AUX_DPHY_TX_STATUS 0x18A0
+#define mmDP_AUX1_AUX_GTC_SYNC_CONTROL 0x18A2
+#define mmDP_AUX1_AUX_GTC_SYNC_DATA 0x18A4
+#define mmDP_AUX1_AUX_INTERRUPT_CONTROL 0x1897
+#define mmDP_AUX1_AUX_LS_DATA 0x189B
+#define mmDP_AUX1_AUX_LS_STATUS 0x1899
+#define mmDP_AUX1_AUX_SW_CONTROL 0x1895
+#define mmDP_AUX1_AUX_SW_DATA 0x189A
+#define mmDP_AUX1_AUX_SW_STATUS 0x1898
+#define mmDP_AUX2_AUX_ARB_CONTROL 0x18AA
+#define mmDP_AUX2_AUX_CONTROL 0x18A8
+#define mmDP_AUX2_AUX_DPHY_RX_CONTROL0 0x18B2
+#define mmDP_AUX2_AUX_DPHY_RX_CONTROL1 0x18B3
+#define mmDP_AUX2_AUX_DPHY_RX_STATUS 0x18B5
+#define mmDP_AUX2_AUX_DPHY_TX_CONTROL 0x18B1
+#define mmDP_AUX2_AUX_DPHY_TX_REF_CONTROL 0x18B0
+#define mmDP_AUX2_AUX_DPHY_TX_STATUS 0x18B4
+#define mmDP_AUX2_AUX_GTC_SYNC_CONTROL 0x18B6
+#define mmDP_AUX2_AUX_GTC_SYNC_DATA 0x18B8
+#define mmDP_AUX2_AUX_INTERRUPT_CONTROL 0x18AB
+#define mmDP_AUX2_AUX_LS_DATA 0x18AF
+#define mmDP_AUX2_AUX_LS_STATUS 0x18AD
+#define mmDP_AUX2_AUX_SW_CONTROL 0x18A9
+#define mmDP_AUX2_AUX_SW_DATA 0x18AE
+#define mmDP_AUX2_AUX_SW_STATUS 0x18AC
+#define mmDP_AUX3_AUX_ARB_CONTROL 0x18C2
+#define mmDP_AUX3_AUX_CONTROL 0x18C0
+#define mmDP_AUX3_AUX_DPHY_RX_CONTROL0 0x18CA
+#define mmDP_AUX3_AUX_DPHY_RX_CONTROL1 0x18CB
+#define mmDP_AUX3_AUX_DPHY_RX_STATUS 0x18CD
+#define mmDP_AUX3_AUX_DPHY_TX_CONTROL 0x18C9
+#define mmDP_AUX3_AUX_DPHY_TX_REF_CONTROL 0x18C8
+#define mmDP_AUX3_AUX_DPHY_TX_STATUS 0x18CC
+#define mmDP_AUX3_AUX_GTC_SYNC_CONTROL 0x18CE
+#define mmDP_AUX3_AUX_GTC_SYNC_DATA 0x18D0
+#define mmDP_AUX3_AUX_INTERRUPT_CONTROL 0x18C3
+#define mmDP_AUX3_AUX_LS_DATA 0x18C7
+#define mmDP_AUX3_AUX_LS_STATUS 0x18C5
+#define mmDP_AUX3_AUX_SW_CONTROL 0x18C1
+#define mmDP_AUX3_AUX_SW_DATA 0x18C6
+#define mmDP_AUX3_AUX_SW_STATUS 0x18C4
+#define mmDP_AUX4_AUX_ARB_CONTROL 0x18D6
+#define mmDP_AUX4_AUX_CONTROL 0x18D4
+#define mmDP_AUX4_AUX_DPHY_RX_CONTROL0 0x18DE
+#define mmDP_AUX4_AUX_DPHY_RX_CONTROL1 0x18DF
+#define mmDP_AUX4_AUX_DPHY_RX_STATUS 0x18E1
+#define mmDP_AUX4_AUX_DPHY_TX_CONTROL 0x18DD
+#define mmDP_AUX4_AUX_DPHY_TX_REF_CONTROL 0x18DC
+#define mmDP_AUX4_AUX_DPHY_TX_STATUS 0x18E0
+#define mmDP_AUX4_AUX_GTC_SYNC_CONTROL 0x18E2
+#define mmDP_AUX4_AUX_GTC_SYNC_DATA 0x18E4
+#define mmDP_AUX4_AUX_INTERRUPT_CONTROL 0x18D7
+#define mmDP_AUX4_AUX_LS_DATA 0x18DB
+#define mmDP_AUX4_AUX_LS_STATUS 0x18D9
+#define mmDP_AUX4_AUX_SW_CONTROL 0x18D5
+#define mmDP_AUX4_AUX_SW_DATA 0x18DA
+#define mmDP_AUX4_AUX_SW_STATUS 0x18D8
+#define mmDP_AUX5_AUX_ARB_CONTROL 0x18EA
+#define mmDP_AUX5_AUX_CONTROL 0x18E8
+#define mmDP_AUX5_AUX_DPHY_RX_CONTROL0 0x18F2
+#define mmDP_AUX5_AUX_DPHY_RX_CONTROL1 0x18F3
+#define mmDP_AUX5_AUX_DPHY_RX_STATUS 0x18F5
+#define mmDP_AUX5_AUX_DPHY_TX_CONTROL 0x18F1
+#define mmDP_AUX5_AUX_DPHY_TX_REF_CONTROL 0x18F0
+#define mmDP_AUX5_AUX_DPHY_TX_STATUS 0x18F4
+#define mmDP_AUX5_AUX_GTC_SYNC_CONTROL 0x18F6
+#define mmDP_AUX5_AUX_GTC_SYNC_DATA 0x18F8
+#define mmDP_AUX5_AUX_INTERRUPT_CONTROL 0x18EB
+#define mmDP_AUX5_AUX_LS_DATA 0x18EF
+#define mmDP_AUX5_AUX_LS_STATUS 0x18ED
+#define mmDP_AUX5_AUX_SW_CONTROL 0x18E9
+#define mmDP_AUX5_AUX_SW_DATA 0x18EE
+#define mmDP_AUX5_AUX_SW_STATUS 0x18EC
+#define mmDP_CONFIG 0x1CC2
+#define mmDP_DPHY_8B10B_CNTL 0x1CD3
+#define mmDP_DPHY_CNTL 0x1CD0
+#define mmDP_DPHY_CRC_CNTL 0x1CD7
+#define mmDP_DPHY_CRC_EN 0x1CD6
+#define mmDP_DPHY_CRC_MST_CNTL 0x1CC6
+#define mmDP_DPHY_CRC_MST_STATUS 0x1CC7
+#define mmDP_DPHY_CRC_RESULT 0x1CD8
+#define mmDP_DPHY_FAST_TRAINING 0x1CCE
+#define mmDP_DPHY_FAST_TRAINING_STATUS 0x1CE9
+#define mmDP_DPHY_PRBS_CNTL 0x1CD4
+#define mmDP_DPHY_SYM0 0x1CD2
+#define mmDP_DPHY_SYM1 0x1CE0
+#define mmDP_DPHY_SYM2 0x1CDF
+#define mmDP_DPHY_TRAINING_PATTERN_SEL 0x1CD1
+#define mmDP_DTO0_MODULO 0x0142
+#define mmDP_DTO0_PHASE 0x0141
+#define mmDP_DTO1_MODULO 0x0146
+#define mmDP_DTO1_PHASE 0x0145
+#define mmDP_DTO2_MODULO 0x014A
+#define mmDP_DTO2_PHASE 0x0149
+#define mmDP_DTO3_MODULO 0x014E
+#define mmDP_DTO3_PHASE 0x014D
+#define mmDP_DTO4_MODULO 0x0152
+#define mmDP_DTO4_PHASE 0x0151
+#define mmDP_DTO5_MODULO 0x0156
+#define mmDP_DTO5_PHASE 0x0155
+#define mmDPG_PIPE_ARBITRATION_CONTROL1 0x1B30
+#define mmDPG_PIPE_ARBITRATION_CONTROL2 0x1B31
+#define mmDPG_PIPE_DPM_CONTROL 0x1B34
+#define mmDPG_PIPE_NB_PSTATE_CHANGE_CONTROL 0x1B36
+#define mmDPG_PIPE_STUTTER_CONTROL 0x1B35
+#define mmDPG_PIPE_STUTTER_CONTROL_NONLPTCH 0x1B37
+#define mmDPG_PIPE_URGENCY_CONTROL 0x1B33
+#define mmDPG_TEST_DEBUG_DATA 0x1B39
+#define mmDPG_TEST_DEBUG_INDEX 0x1B38
+#define mmDP_HBR2_EYE_PATTERN 0x1CC8
+#define mmDP_LINK_CNTL 0x1CC0
+#define mmDP_LINK_FRAMING_CNTL 0x1CCC
+#define mmDP_MSA_COLORIMETRY 0x1CDA
+#define mmDP_MSA_MISC 0x1CC5
+#define mmDP_MSA_V_TIMING_OVERRIDE1 0x1CEA
+#define mmDP_MSA_V_TIMING_OVERRIDE2 0x1CEB
+#define mmDP_MSE_LINK_TIMING 0x1CE8
+#define mmDP_MSE_MISC_CNTL 0x1CDB
+#define mmDP_MSE_RATE_CNTL 0x1CE1
+#define mmDP_MSE_RATE_UPDATE 0x1CE3
+#define mmDP_MSE_SAT0 0x1CE4
+#define mmDP_MSE_SAT1 0x1CE5
+#define mmDP_MSE_SAT2 0x1CE6
+#define mmDP_MSE_SAT_UPDATE 0x1CE7
+#define mmDP_PIXEL_FORMAT 0x1CC1
+#define mmDP_SEC_AUD_M 0x1CA7
+#define mmDP_SEC_AUD_M_READBACK 0x1CA8
+#define mmDP_SEC_AUD_N 0x1CA5
+#define mmDP_SEC_AUD_N_READBACK 0x1CA6
+#define mmDP_SEC_CNTL 0x1CA0
+#define mmDP_SEC_CNTL1 0x1CAB
+#define mmDP_SEC_FRAMING1 0x1CA1
+#define mmDP_SEC_FRAMING2 0x1CA2
+#define mmDP_SEC_FRAMING3 0x1CA3
+#define mmDP_SEC_FRAMING4 0x1CA4
+#define mmDP_SEC_PACKET_CNTL 0x1CAA
+#define mmDP_SEC_TIMESTAMP 0x1CA9
+#define mmDP_STEER_FIFO 0x1CC4
+#define mmDP_TEST_DEBUG_DATA 0x1CFD
+#define mmDP_TEST_DEBUG_INDEX 0x1CFC
+#define mmDP_VID_INTERRUPT_CNTL 0x1CCF
+#define mmDP_VID_M 0x1CCB
+#define mmDP_VID_MSA_VBID 0x1CCD
+#define mmDP_VID_N 0x1CCA
+#define mmDP_VID_STREAM_CNTL 0x1CC3
+#define mmDP_VID_TIMING 0x1CC9
+#define mmDVOACLKC_CNTL 0x016A
+#define mmDVOACLKC_MVP_CNTL 0x0169
+#define mmDVOACLKD_CNTL 0x0168
+#define mmDVO_CLK_ENABLE 0x0129
+#define mmDVO_CONTROL 0x185B
+#define mmDVO_CRC2_SIG_MASK 0x185D
+#define mmDVO_CRC2_SIG_RESULT 0x185E
+#define mmDVO_CRC_EN 0x185C
+#define mmDVO_ENABLE 0x1858
+#define mmDVO_FIFO_ERROR_STATUS 0x185F
+#define mmDVO_OUTPUT 0x185A
+#define mmDVO_SKEW_ADJUST 0x197D
+#define mmDVO_SOURCE_SELECT 0x1859
+#define mmDVO_STRENGTH_CONTROL 0x197B
+#define mmDVO_VREF_CONTROL 0x197C
+#define mmEXT_OVERSCAN_LEFT_RIGHT 0x1B5E
+#define mmEXT_OVERSCAN_TOP_BOTTOM 0x1B5F
+#define mmFBC_CLIENT_REGION_MASK 0x16EB
+#define mmFBC_CNTL 0x16D0
+#define mmFBC_COMP_CNTL 0x16D4
+#define mmFBC_COMP_MODE 0x16D5
+#define mmFBC_CSM_REGION_OFFSET_01 0x16E9
+#define mmFBC_CSM_REGION_OFFSET_23 0x16EA
+#define mmFBC_DEBUG0 0x16D6
+#define mmFBC_DEBUG1 0x16D7
+#define mmFBC_DEBUG2 0x16D8
+#define mmFBC_DEBUG_COMP 0x16EC
+#define mmFBC_DEBUG_CSR 0x16ED
+#define mmFBC_DEBUG_CSR_RDATA 0x16EE
+#define mmFBC_DEBUG_CSR_RDATA_HI 0x16F6
+#define mmFBC_DEBUG_CSR_WDATA 0x16EF
+#define mmFBC_DEBUG_CSR_WDATA_HI 0x16F7
+#define mmFBC_IDLE_FORCE_CLEAR_MASK 0x16D2
+#define mmFBC_IDLE_MASK 0x16D1
+#define mmFBC_IND_LUT0 0x16D9
+#define mmFBC_IND_LUT10 0x16E3
+#define mmFBC_IND_LUT1 0x16DA
+#define mmFBC_IND_LUT11 0x16E4
+#define mmFBC_IND_LUT12 0x16E5
+#define mmFBC_IND_LUT13 0x16E6
+#define mmFBC_IND_LUT14 0x16E7
+#define mmFBC_IND_LUT15 0x16E8
+#define mmFBC_IND_LUT2 0x16DB
+#define mmFBC_IND_LUT3 0x16DC
+#define mmFBC_IND_LUT4 0x16DD
+#define mmFBC_IND_LUT5 0x16DE
+#define mmFBC_IND_LUT6 0x16DF
+#define mmFBC_IND_LUT7 0x16E0
+#define mmFBC_IND_LUT8 0x16E1
+#define mmFBC_IND_LUT9 0x16E2
+#define mmFBC_MISC 0x16F0
+#define mmFBC_START_STOP_DELAY 0x16D3
+#define mmFBC_STATUS 0x16F1
+#define mmFBC_TEST_DEBUG_DATA 0x16F5
+#define mmFBC_TEST_DEBUG_INDEX 0x16F4
+#define mmFMT0_FMT_BIT_DEPTH_CONTROL 0x1BF2
+#define mmFMT0_FMT_CLAMP_CNTL 0x1BF9
+#define mmFMT0_FMT_CONTROL 0x1BEE
+#define mmFMT0_FMT_CRC_CNTL 0x1BFA
+#define mmFMT0_FMT_CRC_SIG_BLUE_CONTROL 0x1BFE
+#define mmFMT0_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x1BFC
+#define mmFMT0_FMT_CRC_SIG_RED_GREEN 0x1BFD
+#define mmFMT0_FMT_CRC_SIG_RED_GREEN_MASK 0x1BFB
+#define mmFMT0_FMT_DEBUG_CNTL 0x1BFF
+#define mmFMT0_FMT_DITHER_RAND_B_SEED 0x1BF5
+#define mmFMT0_FMT_DITHER_RAND_G_SEED 0x1BF4
+#define mmFMT0_FMT_DITHER_RAND_R_SEED 0x1BF3
+#define mmFMT0_FMT_DYNAMIC_EXP_CNTL 0x1BED
+#define mmFMT0_FMT_FORCE_DATA_0_1 0x1BF0
+#define mmFMT0_FMT_FORCE_DATA_2_3 0x1BF1
+#define mmFMT0_FMT_FORCE_OUTPUT_CNTL 0x1BEF
+#define mmFMT0_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x1BF6
+#define mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x1BF7
+#define mmFMT0_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x1BF8
+#define mmFMT0_FMT_TEST_DEBUG_DATA 0x1BEC
+#define mmFMT0_FMT_TEST_DEBUG_INDEX 0x1BEB
+#define mmFMT1_FMT_BIT_DEPTH_CONTROL 0x1EF2
+#define mmFMT1_FMT_CLAMP_CNTL 0x1EF9
+#define mmFMT1_FMT_CONTROL 0x1EEE
+#define mmFMT1_FMT_CRC_CNTL 0x1EFA
+#define mmFMT1_FMT_CRC_SIG_BLUE_CONTROL 0x1EFE
+#define mmFMT1_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x1EFC
+#define mmFMT1_FMT_CRC_SIG_RED_GREEN 0x1EFD
+#define mmFMT1_FMT_CRC_SIG_RED_GREEN_MASK 0x1EFB
+#define mmFMT1_FMT_DEBUG_CNTL 0x1EFF
+#define mmFMT1_FMT_DITHER_RAND_B_SEED 0x1EF5
+#define mmFMT1_FMT_DITHER_RAND_G_SEED 0x1EF4
+#define mmFMT1_FMT_DITHER_RAND_R_SEED 0x1EF3
+#define mmFMT1_FMT_DYNAMIC_EXP_CNTL 0x1EED
+#define mmFMT1_FMT_FORCE_DATA_0_1 0x1EF0
+#define mmFMT1_FMT_FORCE_DATA_2_3 0x1EF1
+#define mmFMT1_FMT_FORCE_OUTPUT_CNTL 0x1EEF
+#define mmFMT1_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x1EF6
+#define mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x1EF7
+#define mmFMT1_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x1EF8
+#define mmFMT1_FMT_TEST_DEBUG_DATA 0x1EEC
+#define mmFMT1_FMT_TEST_DEBUG_INDEX 0x1EEB
+#define mmFMT2_FMT_BIT_DEPTH_CONTROL 0x41F2
+#define mmFMT2_FMT_CLAMP_CNTL 0x41F9
+#define mmFMT2_FMT_CONTROL 0x41EE
+#define mmFMT2_FMT_CRC_CNTL 0x41FA
+#define mmFMT2_FMT_CRC_SIG_BLUE_CONTROL 0x41FE
+#define mmFMT2_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x41FC
+#define mmFMT2_FMT_CRC_SIG_RED_GREEN 0x41FD
+#define mmFMT2_FMT_CRC_SIG_RED_GREEN_MASK 0x41FB
+#define mmFMT2_FMT_DEBUG_CNTL 0x41FF
+#define mmFMT2_FMT_DITHER_RAND_B_SEED 0x41F5
+#define mmFMT2_FMT_DITHER_RAND_G_SEED 0x41F4
+#define mmFMT2_FMT_DITHER_RAND_R_SEED 0x41F3
+#define mmFMT2_FMT_DYNAMIC_EXP_CNTL 0x41ED
+#define mmFMT2_FMT_FORCE_DATA_0_1 0x41F0
+#define mmFMT2_FMT_FORCE_DATA_2_3 0x41F1
+#define mmFMT2_FMT_FORCE_OUTPUT_CNTL 0x41EF
+#define mmFMT2_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x41F6
+#define mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x41F7
+#define mmFMT2_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x41F8
+#define mmFMT2_FMT_TEST_DEBUG_DATA 0x41EC
+#define mmFMT2_FMT_TEST_DEBUG_INDEX 0x41EB
+#define mmFMT3_FMT_BIT_DEPTH_CONTROL 0x44F2
+#define mmFMT3_FMT_CLAMP_CNTL 0x44F9
+#define mmFMT3_FMT_CONTROL 0x44EE
+#define mmFMT3_FMT_CRC_CNTL 0x44FA
+#define mmFMT3_FMT_CRC_SIG_BLUE_CONTROL 0x44FE
+#define mmFMT3_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x44FC
+#define mmFMT3_FMT_CRC_SIG_RED_GREEN 0x44FD
+#define mmFMT3_FMT_CRC_SIG_RED_GREEN_MASK 0x44FB
+#define mmFMT3_FMT_DEBUG_CNTL 0x44FF
+#define mmFMT3_FMT_DITHER_RAND_B_SEED 0x44F5
+#define mmFMT3_FMT_DITHER_RAND_G_SEED 0x44F4
+#define mmFMT3_FMT_DITHER_RAND_R_SEED 0x44F3
+#define mmFMT3_FMT_DYNAMIC_EXP_CNTL 0x44ED
+#define mmFMT3_FMT_FORCE_DATA_0_1 0x44F0
+#define mmFMT3_FMT_FORCE_DATA_2_3 0x44F1
+#define mmFMT3_FMT_FORCE_OUTPUT_CNTL 0x44EF
+#define mmFMT3_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x44F6
+#define mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x44F7
+#define mmFMT3_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x44F8
+#define mmFMT3_FMT_TEST_DEBUG_DATA 0x44EC
+#define mmFMT3_FMT_TEST_DEBUG_INDEX 0x44EB
+#define mmFMT4_FMT_BIT_DEPTH_CONTROL 0x47F2
+#define mmFMT4_FMT_CLAMP_CNTL 0x47F9
+#define mmFMT4_FMT_CONTROL 0x47EE
+#define mmFMT4_FMT_CRC_CNTL 0x47FA
+#define mmFMT4_FMT_CRC_SIG_BLUE_CONTROL 0x47FE
+#define mmFMT4_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x47FC
+#define mmFMT4_FMT_CRC_SIG_RED_GREEN 0x47FD
+#define mmFMT4_FMT_CRC_SIG_RED_GREEN_MASK 0x47FB
+#define mmFMT4_FMT_DEBUG_CNTL 0x47FF
+#define mmFMT4_FMT_DITHER_RAND_B_SEED 0x47F5
+#define mmFMT4_FMT_DITHER_RAND_G_SEED 0x47F4
+#define mmFMT4_FMT_DITHER_RAND_R_SEED 0x47F3
+#define mmFMT4_FMT_DYNAMIC_EXP_CNTL 0x47ED
+#define mmFMT4_FMT_FORCE_DATA_0_1 0x47F0
+#define mmFMT4_FMT_FORCE_DATA_2_3 0x47F1
+#define mmFMT4_FMT_FORCE_OUTPUT_CNTL 0x47EF
+#define mmFMT4_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x47F6
+#define mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x47F7
+#define mmFMT4_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x47F8
+#define mmFMT4_FMT_TEST_DEBUG_DATA 0x47EC
+#define mmFMT4_FMT_TEST_DEBUG_INDEX 0x47EB
+#define mmFMT5_FMT_BIT_DEPTH_CONTROL 0x4AF2
+#define mmFMT5_FMT_CLAMP_CNTL 0x4AF9
+#define mmFMT5_FMT_CONTROL 0x4AEE
+#define mmFMT5_FMT_CRC_CNTL 0x4AFA
+#define mmFMT5_FMT_CRC_SIG_BLUE_CONTROL 0x4AFE
+#define mmFMT5_FMT_CRC_SIG_BLUE_CONTROL_MASK 0x4AFC
+#define mmFMT5_FMT_CRC_SIG_RED_GREEN 0x4AFD
+#define mmFMT5_FMT_CRC_SIG_RED_GREEN_MASK 0x4AFB
+#define mmFMT5_FMT_DEBUG_CNTL 0x4AFF
+#define mmFMT5_FMT_DITHER_RAND_B_SEED 0x4AF5
+#define mmFMT5_FMT_DITHER_RAND_G_SEED 0x4AF4
+#define mmFMT5_FMT_DITHER_RAND_R_SEED 0x4AF3
+#define mmFMT5_FMT_DYNAMIC_EXP_CNTL 0x4AED
+#define mmFMT5_FMT_FORCE_DATA_0_1 0x4AF0
+#define mmFMT5_FMT_FORCE_DATA_2_3 0x4AF1
+#define mmFMT5_FMT_FORCE_OUTPUT_CNTL 0x4AEF
+#define mmFMT5_FMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x4AF6
+#define mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x4AF7
+#define mmFMT5_FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x4AF8
+#define mmFMT5_FMT_TEST_DEBUG_DATA 0x4AEC
+#define mmFMT5_FMT_TEST_DEBUG_INDEX 0x4AEB
+#define mmFMT_BIT_DEPTH_CONTROL 0x1BF2
+#define mmFMT_CLAMP_CNTL 0x1BF9
+#define mmFMT_CONTROL 0x1BEE
+#define mmFMT_CRC_CNTL 0x1BFA
+#define mmFMT_CRC_SIG_BLUE_CONTROL 0x1BFE
+#define mmFMT_CRC_SIG_BLUE_CONTROL_MASK 0x1BFC
+#define mmFMT_CRC_SIG_RED_GREEN 0x1BFD
+#define mmFMT_CRC_SIG_RED_GREEN_MASK 0x1BFB
+#define mmFMT_DEBUG_CNTL 0x1BFF
+#define mmFMT_DITHER_RAND_B_SEED 0x1BF5
+#define mmFMT_DITHER_RAND_G_SEED 0x1BF4
+#define mmFMT_DITHER_RAND_R_SEED 0x1BF3
+#define mmFMT_DYNAMIC_EXP_CNTL 0x1BED
+#define mmFMT_FORCE_DATA_0_1 0x1BF0
+#define mmFMT_FORCE_DATA_2_3 0x1BF1
+#define mmFMT_FORCE_OUTPUT_CNTL 0x1BEF
+#define mmFMT_TEMPORAL_DITHER_PATTERN_CONTROL 0x1BF6
+#define mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX 0x1BF7
+#define mmFMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX 0x1BF8
+#define mmFMT_TEST_DEBUG_DATA 0x1BEC
+#define mmFMT_TEST_DEBUG_INDEX 0x1BEB
+#define mmGAMUT_REMAP_C11_C12 0x1A5A
+#define mmGAMUT_REMAP_C13_C14 0x1A5B
+#define mmGAMUT_REMAP_C21_C22 0x1A5C
+#define mmGAMUT_REMAP_C23_C24 0x1A5D
+#define mmGAMUT_REMAP_C31_C32 0x1A5E
+#define mmGAMUT_REMAP_C33_C34 0x1A5F
+#define mmGAMUT_REMAP_CONTROL 0x1A59
+#define mmGENENB 0x00F0
+#define mmGENERIC_I2C_CONTROL 0x1834
+#define mmGENERIC_I2C_DATA 0x183A
+#define mmGENERIC_I2C_INTERRUPT_CONTROL 0x1835
+#define mmGENERIC_I2C_PIN_DEBUG 0x183C
+#define mmGENERIC_I2C_PIN_SELECTION 0x183B
+#define mmGENERIC_I2C_SETUP 0x1838
+#define mmGENERIC_I2C_SPEED 0x1837
+#define mmGENERIC_I2C_STATUS 0x1836
+#define mmGENERIC_I2C_TRANSACTION 0x1839
+#define mmGENFC_RD 0x00F2
+#define mmGENFC_WT 0x00EE
+#define mmGENMO_RD 0x00F3
+#define mmGENMO_WT 0x00F0
+#define mmGENS0 0x00F0
+#define mmGENS1 0x00EE
+#define mmGRPH8_DATA 0x00F3
+#define mmGRPH8_IDX 0x00F3
+#define mmGRPH_COMPRESS_PITCH 0x1A1A
+#define mmGRPH_COMPRESS_SURFACE_ADDRESS 0x1A19
+#define mmGRPH_COMPRESS_SURFACE_ADDRESS_HIGH 0x1A1B
+#define mmGRPH_CONTROL 0x1A01
+#define mmGRPH_DFQ_CONTROL 0x1A14
+#define mmGRPH_DFQ_STATUS 0x1A15
+#define mmGRPH_ENABLE 0x1A00
+#define mmGRPH_FLIP_CONTROL 0x1A12
+#define mmGRPH_INTERRUPT_CONTROL 0x1A17
+#define mmGRPH_INTERRUPT_STATUS 0x1A16
+#define mmGRPH_LUT_10BIT_BYPASS 0x1A02
+#define mmGRPH_PITCH 0x1A06
+#define mmGRPH_PRIMARY_SURFACE_ADDRESS 0x1A04
+#define mmGRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x1A07
+#define mmGRPH_SECONDARY_SURFACE_ADDRESS 0x1A05
+#define mmGRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A08
+#define mmGRPH_STEREOSYNC_FLIP 0x1A97
+#define mmGRPH_SURFACE_ADDRESS_HIGH_INUSE 0x1A18
+#define mmGRPH_SURFACE_ADDRESS_INUSE 0x1A13
+#define mmGRPH_SURFACE_OFFSET_X 0x1A09
+#define mmGRPH_SURFACE_OFFSET_Y 0x1A0A
+#define mmGRPH_SWAP_CNTL 0x1A03
+#define mmGRPH_UPDATE 0x1A11
+#define mmGRPH_X_END 0x1A0D
+#define mmGRPH_X_START 0x1A0B
+#define mmGRPH_Y_END 0x1A0E
+#define mmGRPH_Y_START 0x1A0C
+#define mmHDMI_ACR_32_0 0x1C37
+#define mmHDMI_ACR_32_1 0x1C38
+#define mmHDMI_ACR_44_0 0x1C39
+#define mmHDMI_ACR_44_1 0x1C3A
+#define mmHDMI_ACR_48_0 0x1C3B
+#define mmHDMI_ACR_48_1 0x1C3C
+#define mmHDMI_ACR_PACKET_CONTROL 0x1C0F
+#define mmHDMI_ACR_STATUS_0 0x1C3D
+#define mmHDMI_ACR_STATUS_1 0x1C3E
+#define mmHDMI_AUDIO_PACKET_CONTROL 0x1C0E
+#define mmHDMI_CONTROL 0x1C0C
+#define mmHDMI_GC 0x1C16
+#define mmHDMI_GENERIC_PACKET_CONTROL0 0x1C13
+#define mmHDMI_GENERIC_PACKET_CONTROL1 0x1C30
+#define mmHDMI_INFOFRAME_CONTROL0 0x1C11
+#define mmHDMI_INFOFRAME_CONTROL1 0x1C12
+#define mmHDMI_STATUS 0x1C0D
+#define mmHDMI_VBI_PACKET_CONTROL 0x1C10
+#define mmINPUT_CSC_C11_C12 0x1A36
+#define mmINPUT_CSC_C13_C14 0x1A37
+#define mmINPUT_CSC_C21_C22 0x1A38
+#define mmINPUT_CSC_C23_C24 0x1A39
+#define mmINPUT_CSC_C31_C32 0x1A3A
+#define mmINPUT_CSC_C33_C34 0x1A3B
+#define mmINPUT_CSC_CONTROL 0x1A35
+#define mmINPUT_GAMMA_CONTROL 0x1A10
+#define mmKEY_CONTROL 0x1A53
+#define mmKEY_RANGE_ALPHA 0x1A54
+#define mmKEY_RANGE_BLUE 0x1A57
+#define mmKEY_RANGE_GREEN 0x1A56
+#define mmKEY_RANGE_RED 0x1A55
+#define mmLB0_DC_MVP_LB_CONTROL 0x1ADB
+#define mmLB0_LB_DEBUG 0x1AFC
+#define mmLB0_LB_DEBUG2 0x1AC9
+#define mmLB0_LB_NO_OUTSTANDING_REQ_STATUS 0x1AC8
+#define mmLB0_LB_SYNC_RESET_SEL 0x1ACA
+#define mmLB0_LB_TEST_DEBUG_DATA 0x1AFF
+#define mmLB0_LB_TEST_DEBUG_INDEX 0x1AFE
+#define mmLB0_MVP_AFR_FLIP_FIFO_CNTL 0x1AD9
+#define mmLB0_MVP_AFR_FLIP_MODE 0x1AD8
+#define mmLB0_MVP_FLIP_LINE_NUM_INSERT 0x1ADA
+#define mmLB1_DC_MVP_LB_CONTROL 0x1DDB
+#define mmLB1_LB_DEBUG 0x1DFC
+#define mmLB1_LB_DEBUG2 0x1DC9
+#define mmLB1_LB_NO_OUTSTANDING_REQ_STATUS 0x1DC8
+#define mmLB1_LB_SYNC_RESET_SEL 0x1DCA
+#define mmLB1_LB_TEST_DEBUG_DATA 0x1DFF
+#define mmLB1_LB_TEST_DEBUG_INDEX 0x1DFE
+#define mmLB1_MVP_AFR_FLIP_FIFO_CNTL 0x1DD9
+#define mmLB1_MVP_AFR_FLIP_MODE 0x1DD8
+#define mmLB1_MVP_FLIP_LINE_NUM_INSERT 0x1DDA
+#define mmLB2_DC_MVP_LB_CONTROL 0x40DB
+#define mmLB2_LB_DEBUG 0x40FC
+#define mmLB2_LB_DEBUG2 0x40C9
+#define mmLB2_LB_NO_OUTSTANDING_REQ_STATUS 0x40C8
+#define mmLB2_LB_SYNC_RESET_SEL 0x40CA
+#define mmLB2_LB_TEST_DEBUG_DATA 0x40FF
+#define mmLB2_LB_TEST_DEBUG_INDEX 0x40FE
+#define mmLB2_MVP_AFR_FLIP_FIFO_CNTL 0x40D9
+#define mmLB2_MVP_AFR_FLIP_MODE 0x40D8
+#define mmLB2_MVP_FLIP_LINE_NUM_INSERT 0x40DA
+#define mmLB3_DC_MVP_LB_CONTROL 0x43DB
+#define mmLB3_LB_DEBUG 0x43FC
+#define mmLB3_LB_DEBUG2 0x43C9
+#define mmLB3_LB_NO_OUTSTANDING_REQ_STATUS 0x43C8
+#define mmLB3_LB_SYNC_RESET_SEL 0x43CA
+#define mmLB3_LB_TEST_DEBUG_DATA 0x43FF
+#define mmLB3_LB_TEST_DEBUG_INDEX 0x43FE
+#define mmLB3_MVP_AFR_FLIP_FIFO_CNTL 0x43D9
+#define mmLB3_MVP_AFR_FLIP_MODE 0x43D8
+#define mmLB3_MVP_FLIP_LINE_NUM_INSERT 0x43DA
+#define mmLB4_DC_MVP_LB_CONTROL 0x46DB
+#define mmLB4_LB_DEBUG 0x46FC
+#define mmLB4_LB_DEBUG2 0x46C9
+#define mmLB4_LB_NO_OUTSTANDING_REQ_STATUS 0x46C8
+#define mmLB4_LB_SYNC_RESET_SEL 0x46CA
+#define mmLB4_LB_TEST_DEBUG_DATA 0x46FF
+#define mmLB4_LB_TEST_DEBUG_INDEX 0x46FE
+#define mmLB4_MVP_AFR_FLIP_FIFO_CNTL 0x46D9
+#define mmLB4_MVP_AFR_FLIP_MODE 0x46D8
+#define mmLB4_MVP_FLIP_LINE_NUM_INSERT 0x46DA
+#define mmLB5_DC_MVP_LB_CONTROL 0x49DB
+#define mmLB5_LB_DEBUG 0x49FC
+#define mmLB5_LB_DEBUG2 0x49C9
+#define mmLB5_LB_NO_OUTSTANDING_REQ_STATUS 0x49C8
+#define mmLB5_LB_SYNC_RESET_SEL 0x49CA
+#define mmLB5_LB_TEST_DEBUG_DATA 0x49FF
+#define mmLB5_LB_TEST_DEBUG_INDEX 0x49FE
+#define mmLB5_MVP_AFR_FLIP_FIFO_CNTL 0x49D9
+#define mmLB5_MVP_AFR_FLIP_MODE 0x49D8
+#define mmLB5_MVP_FLIP_LINE_NUM_INSERT 0x49DA
+#define mmLB_DEBUG 0x1AFC
+#define mmLB_DEBUG2 0x1AC9
+#define mmLB_NO_OUTSTANDING_REQ_STATUS 0x1AC8
+#define mmLB_SYNC_RESET_SEL 0x1ACA
+#define mmLB_TEST_DEBUG_DATA 0x1AFF
+#define mmLB_TEST_DEBUG_INDEX 0x1AFE
+#define mmLIGHT_SLEEP_CNTL 0x0132
+#define mmLOW_POWER_TILING_CONTROL 0x0325
+#define mmLVDS_DATA_CNTL 0x1C8C
+#define mmLVTMA_PWRSEQ_CNTL 0x1919
+#define mmLVTMA_PWRSEQ_DELAY1 0x191C
+#define mmLVTMA_PWRSEQ_DELAY2 0x191D
+#define mmLVTMA_PWRSEQ_REF_DIV 0x191B
+#define mmLVTMA_PWRSEQ_STATE 0x191A
+#define mmMASTER_COMM_CMD_REG 0x161F
+#define mmMASTER_COMM_CNTL_REG 0x1620
+#define mmMASTER_COMM_DATA_REG1 0x161C
+#define mmMASTER_COMM_DATA_REG2 0x161D
+#define mmMASTER_COMM_DATA_REG3 0x161E
+#define mmMASTER_UPDATE_LOCK 0x1BBD
+#define mmMASTER_UPDATE_MODE 0x1BBE
+#define mmMC_DC_INTERFACE_NACK_STATUS 0x031C
+#define mmMCIF_CONTROL 0x0314
+#define mmMCIF_MEM_CONTROL 0x0319
+#define mmMCIF_TEST_DEBUG_DATA 0x0317
+#define mmMCIF_TEST_DEBUG_INDEX 0x0316
+#define mmMCIF_VMID 0x0318
+#define mmMCIF_WRITE_COMBINE_CONTROL 0x0315
+#define mmMICROSECOND_TIME_BASE_DIV 0x013B
+#define mmMILLISECOND_TIME_BASE_DIV 0x0130
+#define mmMVP_AFR_FLIP_FIFO_CNTL 0x1AD9
+#define mmMVP_AFR_FLIP_MODE 0x1AD8
+#define mmMVP_BLACK_KEYER 0x1686
+#define mmMVP_CONTROL1 0x1680
+#define mmMVP_CONTROL2 0x1681
+#define mmMVP_CONTROL3 0x168A
+#define mmMVP_CRC_CNTL 0x1687
+#define mmMVP_CRC_RESULT_BLUE_GREEN 0x1688
+#define mmMVP_CRC_RESULT_RED 0x1689
+#define mmMVP_DEBUG 0x168F
+#define mmMVP_FIFO_CONTROL 0x1682
+#define mmMVP_FIFO_STATUS 0x1683
+#define mmMVP_FLIP_LINE_NUM_INSERT 0x1ADA
+#define mmMVP_INBAND_CNTL_CAP 0x1685
+#define mmMVP_RECEIVE_CNT_CNTL1 0x168B
+#define mmMVP_RECEIVE_CNT_CNTL2 0x168C
+#define mmMVP_SLAVE_STATUS 0x1684
+#define mmMVP_TEST_DEBUG_DATA 0x168E
+#define mmMVP_TEST_DEBUG_INDEX 0x168D
+#define mmOUTPUT_CSC_C11_C12 0x1A3D
+#define mmOUTPUT_CSC_C13_C14 0x1A3E
+#define mmOUTPUT_CSC_C21_C22 0x1A3F
+#define mmOUTPUT_CSC_C23_C24 0x1A40
+#define mmOUTPUT_CSC_C31_C32 0x1A41
+#define mmOUTPUT_CSC_C33_C34 0x1A42
+#define mmOUTPUT_CSC_CONTROL 0x1A3C
+#define mmOUT_ROUND_CONTROL 0x1A51
+#define mmOVL_CONTROL1 0x1A1D
+#define mmOVL_CONTROL2 0x1A1E
+#define mmOVL_DFQ_CONTROL 0x1A29
+#define mmOVL_DFQ_STATUS 0x1A2A
+#define mmOVL_ENABLE 0x1A1C
+#define mmOVL_END 0x1A26
+#define mmOVL_PITCH 0x1A21
+#define mmOVLSCL_EDGE_PIXEL_CNTL 0x1A2C
+#define mmOVL_SECONDARY_SURFACE_ADDRESS 0x1A92
+#define mmOVL_SECONDARY_SURFACE_ADDRESS_HIGH 0x1A94
+#define mmOVL_START 0x1A25
+#define mmOVL_STEREOSYNC_FLIP 0x1A93
+#define mmOVL_SURFACE_ADDRESS 0x1A20
+#define mmOVL_SURFACE_ADDRESS_HIGH 0x1A22
+#define mmOVL_SURFACE_ADDRESS_HIGH_INUSE 0x1A2B
+#define mmOVL_SURFACE_ADDRESS_INUSE 0x1A28
+#define mmOVL_SURFACE_OFFSET_X 0x1A23
+#define mmOVL_SURFACE_OFFSET_Y 0x1A24
+#define mmOVL_SWAP_CNTL 0x1A1F
+#define mmOVL_UPDATE 0x1A27
+#define mmPHY_AUX_CNTL 0x197F
+#define mmPIPE0_ARBITRATION_CONTROL3 0x02FA
+#define mmPIPE0_DMIF_BUFFER_CONTROL 0x0328
+#define mmPIPE0_MAX_REQUESTS 0x0302
+#define mmPIPE0_PG_CONFIG 0x1760
+#define mmPIPE0_PG_ENABLE 0x1761
+#define mmPIPE0_PG_STATUS 0x1762
+#define mmPIPE1_ARBITRATION_CONTROL3 0x02FB
+#define mmPIPE1_DMIF_BUFFER_CONTROL 0x0330
+#define mmPIPE1_MAX_REQUESTS 0x0303
+#define mmPIPE1_PG_CONFIG 0x1764
+#define mmPIPE1_PG_ENABLE 0x1765
+#define mmPIPE1_PG_STATUS 0x1766
+#define mmPIPE2_ARBITRATION_CONTROL3 0x02FC
+#define mmPIPE2_DMIF_BUFFER_CONTROL 0x0338
+#define mmPIPE2_MAX_REQUESTS 0x0304
+#define mmPIPE2_PG_CONFIG 0x1768
+#define mmPIPE2_PG_ENABLE 0x1769
+#define mmPIPE2_PG_STATUS 0x176A
+#define mmPIPE3_ARBITRATION_CONTROL3 0x02FD
+#define mmPIPE3_DMIF_BUFFER_CONTROL 0x0340
+#define mmPIPE3_MAX_REQUESTS 0x0305
+#define mmPIPE3_PG_CONFIG 0x176C
+#define mmPIPE3_PG_ENABLE 0x176D
+#define mmPIPE3_PG_STATUS 0x176E
+#define mmPIPE4_ARBITRATION_CONTROL3 0x02FE
+#define mmPIPE4_DMIF_BUFFER_CONTROL 0x0348
+#define mmPIPE4_MAX_REQUESTS 0x0306
+#define mmPIPE4_PG_CONFIG 0x1770
+#define mmPIPE4_PG_ENABLE 0x1771
+#define mmPIPE4_PG_STATUS 0x1772
+#define mmPIPE5_ARBITRATION_CONTROL3 0x02FF
+#define mmPIPE5_DMIF_BUFFER_CONTROL 0x0350
+#define mmPIPE5_MAX_REQUESTS 0x0307
+#define mmPIPE5_PG_CONFIG 0x1774
+#define mmPIPE5_PG_ENABLE 0x1775
+#define mmPIPE5_PG_STATUS 0x1776
+#define mmPIXCLK0_RESYNC_CNTL 0x013A
+#define mmPIXCLK1_RESYNC_CNTL 0x0138
+#define mmPIXCLK2_RESYNC_CNTL 0x0139
+#define mmPLL_ANALOG 0x1708
+#define mmPLL_CNTL 0x1707
+#define mmPLL_DEBUG_CNTL 0x170B
+#define mmPLL_DISPCLK_CURRENT_DTO_PHASE 0x170F
+#define mmPLL_DISPCLK_DTO_CNTL 0x170E
+#define mmPLL_DS_CNTL 0x1705
+#define mmPLL_FB_DIV 0x1701
+#define mmPLL_IDCLK_CNTL 0x1706
+#define mmPLL_POST_DIV 0x1702
+#define mmPLL_REF_DIV 0x1700
+#define mmPLL_SS_AMOUNT_DSFRAC 0x1703
+#define mmPLL_SS_CNTL 0x1704
+#define mmPLL_UNLOCK_DETECT_CNTL 0x170A
+#define mmPLL_UPDATE_CNTL 0x170D
+#define mmPLL_UPDATE_LOCK 0x170C
+#define mmPLL_VREG_CNTL 0x1709
+#define mmPRESCALE_GRPH_CONTROL 0x1A2D
+#define mmPRESCALE_OVL_CONTROL 0x1A31
+#define mmPRESCALE_VALUES_GRPH_B 0x1A30
+#define mmPRESCALE_VALUES_GRPH_G 0x1A2F
+#define mmPRESCALE_VALUES_GRPH_R 0x1A2E
+#define mmPRESCALE_VALUES_OVL_CB 0x1A32
+#define mmPRESCALE_VALUES_OVL_CR 0x1A34
+#define mmPRESCALE_VALUES_OVL_Y 0x1A33
+#define mmREGAMMA_CNTLA_END_CNTL1 0x1AA6
+#define mmREGAMMA_CNTLA_END_CNTL2 0x1AA7
+#define mmREGAMMA_CNTLA_REGION_0_1 0x1AA8
+#define mmREGAMMA_CNTLA_REGION_10_11 0x1AAD
+#define mmREGAMMA_CNTLA_REGION_12_13 0x1AAE
+#define mmREGAMMA_CNTLA_REGION_14_15 0x1AAF
+#define mmREGAMMA_CNTLA_REGION_2_3 0x1AA9
+#define mmREGAMMA_CNTLA_REGION_4_5 0x1AAA
+#define mmREGAMMA_CNTLA_REGION_6_7 0x1AAB
+#define mmREGAMMA_CNTLA_REGION_8_9 0x1AAC
+#define mmREGAMMA_CNTLA_SLOPE_CNTL 0x1AA5
+#define mmREGAMMA_CNTLA_START_CNTL 0x1AA4
+#define mmREGAMMA_CNTLB_END_CNTL1 0x1AB2
+#define mmREGAMMA_CNTLB_END_CNTL2 0x1AB3
+#define mmREGAMMA_CNTLB_REGION_0_1 0x1AB4
+#define mmREGAMMA_CNTLB_REGION_10_11 0x1AB9
+#define mmREGAMMA_CNTLB_REGION_12_13 0x1ABA
+#define mmREGAMMA_CNTLB_REGION_14_15 0x1ABB
+#define mmREGAMMA_CNTLB_REGION_2_3 0x1AB5
+#define mmREGAMMA_CNTLB_REGION_4_5 0x1AB6
+#define mmREGAMMA_CNTLB_REGION_6_7 0x1AB7
+#define mmREGAMMA_CNTLB_REGION_8_9 0x1AB8
+#define mmREGAMMA_CNTLB_SLOPE_CNTL 0x1AB1
+#define mmREGAMMA_CNTLB_START_CNTL 0x1AB0
+#define mmREGAMMA_CONTROL 0x1AA0
+#define mmREGAMMA_LUT_DATA 0x1AA2
+#define mmREGAMMA_LUT_INDEX 0x1AA1
+#define mmREGAMMA_LUT_WRITE_EN_MASK 0x1AA3
+#define mmSCL0_EXT_OVERSCAN_LEFT_RIGHT 0x1B5E
+#define mmSCL0_EXT_OVERSCAN_TOP_BOTTOM 0x1B5F
+#define mmSCL0_SCL_ALU_CONTROL 0x1B54
+#define mmSCL0_SCL_AUTOMATIC_MODE_CONTROL 0x1B47
+#define mmSCL0_SCL_BYPASS_CONTROL 0x1B45
+#define mmSCL0_SCL_COEF_RAM_CONFLICT_STATUS 0x1B55
+#define mmSCL0_SCL_COEF_RAM_SELECT 0x1B40
+#define mmSCL0_SCL_COEF_RAM_TAP_DATA 0x1B41
+#define mmSCL0_SCL_CONTROL 0x1B44
+#define mmSCL0_SCL_DEBUG 0x1B6A
+#define mmSCL0_SCL_DEBUG2 0x1B69
+#define mmSCL0_SCL_F_SHARP_CONTROL 0x1B53
+#define mmSCL0_SCL_HORZ_FILTER_CONTROL 0x1B4A
+#define mmSCL0_SCL_HORZ_FILTER_SCALE_RATIO 0x1B4B
+#define mmSCL0_SCL_MANUAL_REPLICATE_CONTROL 0x1B46
+#define mmSCL0_SCL_MODE_CHANGE_DET1 0x1B60
+#define mmSCL0_SCL_MODE_CHANGE_DET2 0x1B61
+#define mmSCL0_SCL_MODE_CHANGE_DET3 0x1B62
+#define mmSCL0_SCL_MODE_CHANGE_MASK 0x1B63
+#define mmSCL0_SCL_TAP_CONTROL 0x1B43
+#define mmSCL0_SCL_TEST_DEBUG_DATA 0x1B6C
+#define mmSCL0_SCL_TEST_DEBUG_INDEX 0x1B6B
+#define mmSCL0_SCL_UPDATE 0x1B51
+#define mmSCL0_SCL_VERT_FILTER_CONTROL 0x1B4E
+#define mmSCL0_SCL_VERT_FILTER_INIT 0x1B50
+#define mmSCL0_SCL_VERT_FILTER_INIT_BOT 0x1B57
+#define mmSCL0_SCL_VERT_FILTER_SCALE_RATIO 0x1B4F
+#define mmSCL0_VIEWPORT_SIZE 0x1B5D
+#define mmSCL0_VIEWPORT_START 0x1B5C
+#define mmSCL1_EXT_OVERSCAN_LEFT_RIGHT 0x1E5E
+#define mmSCL1_EXT_OVERSCAN_TOP_BOTTOM 0x1E5F
+#define mmSCL1_SCL_ALU_CONTROL 0x1E54
+#define mmSCL1_SCL_AUTOMATIC_MODE_CONTROL 0x1E47
+#define mmSCL1_SCL_BYPASS_CONTROL 0x1E45
+#define mmSCL1_SCL_COEF_RAM_CONFLICT_STATUS 0x1E55
+#define mmSCL1_SCL_COEF_RAM_SELECT 0x1E40
+#define mmSCL1_SCL_COEF_RAM_TAP_DATA 0x1E41
+#define mmSCL1_SCL_CONTROL 0x1E44
+#define mmSCL1_SCL_DEBUG 0x1E6A
+#define mmSCL1_SCL_DEBUG2 0x1E69
+#define mmSCL1_SCL_F_SHARP_CONTROL 0x1E53
+#define mmSCL1_SCL_HORZ_FILTER_CONTROL 0x1E4A
+#define mmSCL1_SCL_HORZ_FILTER_SCALE_RATIO 0x1E4B
+#define mmSCL1_SCL_MANUAL_REPLICATE_CONTROL 0x1E46
+#define mmSCL1_SCL_MODE_CHANGE_DET1 0x1E60
+#define mmSCL1_SCL_MODE_CHANGE_DET2 0x1E61
+#define mmSCL1_SCL_MODE_CHANGE_DET3 0x1E62
+#define mmSCL1_SCL_MODE_CHANGE_MASK 0x1E63
+#define mmSCL1_SCL_TAP_CONTROL 0x1E43
+#define mmSCL1_SCL_TEST_DEBUG_DATA 0x1E6C
+#define mmSCL1_SCL_TEST_DEBUG_INDEX 0x1E6B
+#define mmSCL1_SCL_UPDATE 0x1E51
+#define mmSCL1_SCL_VERT_FILTER_CONTROL 0x1E4E
+#define mmSCL1_SCL_VERT_FILTER_INIT 0x1E50
+#define mmSCL1_SCL_VERT_FILTER_INIT_BOT 0x1E57
+#define mmSCL1_SCL_VERT_FILTER_SCALE_RATIO 0x1E4F
+#define mmSCL1_VIEWPORT_SIZE 0x1E5D
+#define mmSCL1_VIEWPORT_START 0x1E5C
+#define mmSCL2_EXT_OVERSCAN_LEFT_RIGHT 0x415E
+#define mmSCL2_EXT_OVERSCAN_TOP_BOTTOM 0x415F
+#define mmSCL2_SCL_ALU_CONTROL 0x4154
+#define mmSCL2_SCL_AUTOMATIC_MODE_CONTROL 0x4147
+#define mmSCL2_SCL_BYPASS_CONTROL 0x4145
+#define mmSCL2_SCL_COEF_RAM_CONFLICT_STATUS 0x4155
+#define mmSCL2_SCL_COEF_RAM_SELECT 0x4140
+#define mmSCL2_SCL_COEF_RAM_TAP_DATA 0x4141
+#define mmSCL2_SCL_CONTROL 0x4144
+#define mmSCL2_SCL_DEBUG 0x416A
+#define mmSCL2_SCL_DEBUG2 0x4169
+#define mmSCL2_SCL_F_SHARP_CONTROL 0x4153
+#define mmSCL2_SCL_HORZ_FILTER_CONTROL 0x414A
+#define mmSCL2_SCL_HORZ_FILTER_SCALE_RATIO 0x414B
+#define mmSCL2_SCL_MANUAL_REPLICATE_CONTROL 0x4146
+#define mmSCL2_SCL_MODE_CHANGE_DET1 0x4160
+#define mmSCL2_SCL_MODE_CHANGE_DET2 0x4161
+#define mmSCL2_SCL_MODE_CHANGE_DET3 0x4162
+#define mmSCL2_SCL_MODE_CHANGE_MASK 0x4163
+#define mmSCL2_SCL_TAP_CONTROL 0x4143
+#define mmSCL2_SCL_TEST_DEBUG_DATA 0x416C
+#define mmSCL2_SCL_TEST_DEBUG_INDEX 0x416B
+#define mmSCL2_SCL_UPDATE 0x4151
+#define mmSCL2_SCL_VERT_FILTER_CONTROL 0x414E
+#define mmSCL2_SCL_VERT_FILTER_INIT 0x4150
+#define mmSCL2_SCL_VERT_FILTER_INIT_BOT 0x4157
+#define mmSCL2_SCL_VERT_FILTER_SCALE_RATIO 0x414F
+#define mmSCL2_VIEWPORT_SIZE 0x415D
+#define mmSCL2_VIEWPORT_START 0x415C
+#define mmSCL3_EXT_OVERSCAN_LEFT_RIGHT 0x445E
+#define mmSCL3_EXT_OVERSCAN_TOP_BOTTOM 0x445F
+#define mmSCL3_SCL_ALU_CONTROL 0x4454
+#define mmSCL3_SCL_AUTOMATIC_MODE_CONTROL 0x4447
+#define mmSCL3_SCL_BYPASS_CONTROL 0x4445
+#define mmSCL3_SCL_COEF_RAM_CONFLICT_STATUS 0x4455
+#define mmSCL3_SCL_COEF_RAM_SELECT 0x4440
+#define mmSCL3_SCL_COEF_RAM_TAP_DATA 0x4441
+#define mmSCL3_SCL_CONTROL 0x4444
+#define mmSCL3_SCL_DEBUG 0x446A
+#define mmSCL3_SCL_DEBUG2 0x4469
+#define mmSCL3_SCL_F_SHARP_CONTROL 0x4453
+#define mmSCL3_SCL_HORZ_FILTER_CONTROL 0x444A
+#define mmSCL3_SCL_HORZ_FILTER_SCALE_RATIO 0x444B
+#define mmSCL3_SCL_MANUAL_REPLICATE_CONTROL 0x4446
+#define mmSCL3_SCL_MODE_CHANGE_DET1 0x4460
+#define mmSCL3_SCL_MODE_CHANGE_DET2 0x4461
+#define mmSCL3_SCL_MODE_CHANGE_DET3 0x4462
+#define mmSCL3_SCL_MODE_CHANGE_MASK 0x4463
+#define mmSCL3_SCL_TAP_CONTROL 0x4443
+#define mmSCL3_SCL_TEST_DEBUG_DATA 0x446C
+#define mmSCL3_SCL_TEST_DEBUG_INDEX 0x446B
+#define mmSCL3_SCL_UPDATE 0x4451
+#define mmSCL3_SCL_VERT_FILTER_CONTROL 0x444E
+#define mmSCL3_SCL_VERT_FILTER_INIT 0x4450
+#define mmSCL3_SCL_VERT_FILTER_INIT_BOT 0x4457
+#define mmSCL3_SCL_VERT_FILTER_SCALE_RATIO 0x444F
+#define mmSCL3_VIEWPORT_SIZE 0x445D
+#define mmSCL3_VIEWPORT_START 0x445C
+#define mmSCL4_EXT_OVERSCAN_LEFT_RIGHT 0x475E
+#define mmSCL4_EXT_OVERSCAN_TOP_BOTTOM 0x475F
+#define mmSCL4_SCL_ALU_CONTROL 0x4754
+#define mmSCL4_SCL_AUTOMATIC_MODE_CONTROL 0x4747
+#define mmSCL4_SCL_BYPASS_CONTROL 0x4745
+#define mmSCL4_SCL_COEF_RAM_CONFLICT_STATUS 0x4755
+#define mmSCL4_SCL_COEF_RAM_SELECT 0x4740
+#define mmSCL4_SCL_COEF_RAM_TAP_DATA 0x4741
+#define mmSCL4_SCL_CONTROL 0x4744
+#define mmSCL4_SCL_DEBUG 0x476A
+#define mmSCL4_SCL_DEBUG2 0x4769
+#define mmSCL4_SCL_F_SHARP_CONTROL 0x4753
+#define mmSCL4_SCL_HORZ_FILTER_CONTROL 0x474A
+#define mmSCL4_SCL_HORZ_FILTER_SCALE_RATIO 0x474B
+#define mmSCL4_SCL_MANUAL_REPLICATE_CONTROL 0x4746
+#define mmSCL4_SCL_MODE_CHANGE_DET1 0x4760
+#define mmSCL4_SCL_MODE_CHANGE_DET2 0x4761
+#define mmSCL4_SCL_MODE_CHANGE_DET3 0x4762
+#define mmSCL4_SCL_MODE_CHANGE_MASK 0x4763
+#define mmSCL4_SCL_TAP_CONTROL 0x4743
+#define mmSCL4_SCL_TEST_DEBUG_DATA 0x476C
+#define mmSCL4_SCL_TEST_DEBUG_INDEX 0x476B
+#define mmSCL4_SCL_UPDATE 0x4751
+#define mmSCL4_SCL_VERT_FILTER_CONTROL 0x474E
+#define mmSCL4_SCL_VERT_FILTER_INIT 0x4750
+#define mmSCL4_SCL_VERT_FILTER_INIT_BOT 0x4757
+#define mmSCL4_SCL_VERT_FILTER_SCALE_RATIO 0x474F
+#define mmSCL4_VIEWPORT_SIZE 0x475D
+#define mmSCL4_VIEWPORT_START 0x475C
+#define mmSCL5_EXT_OVERSCAN_LEFT_RIGHT 0x4A5E
+#define mmSCL5_EXT_OVERSCAN_TOP_BOTTOM 0x4A5F
+#define mmSCL5_SCL_ALU_CONTROL 0x4A54
+#define mmSCL5_SCL_AUTOMATIC_MODE_CONTROL 0x4A47
+#define mmSCL5_SCL_BYPASS_CONTROL 0x4A45
+#define mmSCL5_SCL_COEF_RAM_CONFLICT_STATUS 0x4A55
+#define mmSCL5_SCL_COEF_RAM_SELECT 0x4A40
+#define mmSCL5_SCL_COEF_RAM_TAP_DATA 0x4A41
+#define mmSCL5_SCL_CONTROL 0x4A44
+#define mmSCL5_SCL_DEBUG 0x4A6A
+#define mmSCL5_SCL_DEBUG2 0x4A69
+#define mmSCL5_SCL_F_SHARP_CONTROL 0x4A53
+#define mmSCL5_SCL_HORZ_FILTER_CONTROL 0x4A4A
+#define mmSCL5_SCL_HORZ_FILTER_SCALE_RATIO 0x4A4B
+#define mmSCL5_SCL_MANUAL_REPLICATE_CONTROL 0x4A46
+#define mmSCL5_SCL_MODE_CHANGE_DET1 0x4A60
+#define mmSCL5_SCL_MODE_CHANGE_DET2 0x4A61
+#define mmSCL5_SCL_MODE_CHANGE_DET3 0x4A62
+#define mmSCL5_SCL_MODE_CHANGE_MASK 0x4A63
+#define mmSCL5_SCL_TAP_CONTROL 0x4A43
+#define mmSCL5_SCL_TEST_DEBUG_DATA 0x4A6C
+#define mmSCL5_SCL_TEST_DEBUG_INDEX 0x4A6B
+#define mmSCL5_SCL_UPDATE 0x4A51
+#define mmSCL5_SCL_VERT_FILTER_CONTROL 0x4A4E
+#define mmSCL5_SCL_VERT_FILTER_INIT 0x4A50
+#define mmSCL5_SCL_VERT_FILTER_INIT_BOT 0x4A57
+#define mmSCL5_SCL_VERT_FILTER_SCALE_RATIO 0x4A4F
+#define mmSCL5_VIEWPORT_SIZE 0x4A5D
+#define mmSCL5_VIEWPORT_START 0x4A5C
+#define mmSCL_ALU_CONTROL 0x1B54
+#define mmSCL_AUTOMATIC_MODE_CONTROL 0x1B47
+#define mmSCL_BYPASS_CONTROL 0x1B45
+#define mmSCL_COEF_RAM_CONFLICT_STATUS 0x1B55
+#define mmSCL_COEF_RAM_SELECT 0x1B40
+#define mmSCL_COEF_RAM_TAP_DATA 0x1B41
+#define mmSCL_CONTROL 0x1B44
+#define mmSCL_DEBUG 0x1B6A
+#define mmSCL_DEBUG2 0x1B69
+#define mmSCL_F_SHARP_CONTROL 0x1B53
+#define mmSCL_HORZ_FILTER_CONTROL 0x1B4A
+#define mmSCL_HORZ_FILTER_SCALE_RATIO 0x1B4B
+#define mmSCLK_CGTT_BLK_CTRL_REG 0x0136
+#define mmSCL_MANUAL_REPLICATE_CONTROL 0x1B46
+#define mmSCL_MODE_CHANGE_DET1 0x1B60
+#define mmSCL_MODE_CHANGE_DET2 0x1B61
+#define mmSCL_MODE_CHANGE_DET3 0x1B62
+#define mmSCL_MODE_CHANGE_MASK 0x1B63
+#define mmSCL_TAP_CONTROL 0x1B43
+#define mmSCL_TEST_DEBUG_DATA 0x1B6C
+#define mmSCL_TEST_DEBUG_INDEX 0x1B6B
+#define mmSCL_UPDATE 0x1B51
+#define mmSCL_VERT_FILTER_CONTROL 0x1B4E
+#define mmSCL_VERT_FILTER_INIT 0x1B50
+#define mmSCL_VERT_FILTER_INIT_BOT 0x1B57
+#define mmSCL_VERT_FILTER_SCALE_RATIO 0x1B4F
+#define mmSEQ8_DATA 0x00F1
+#define mmSEQ8_IDX 0x00F1
+#define mmSLAVE_COMM_CMD_REG 0x1624
+#define mmSLAVE_COMM_CNTL_REG 0x1625
+#define mmSLAVE_COMM_DATA_REG1 0x1621
+#define mmSLAVE_COMM_DATA_REG2 0x1622
+#define mmSLAVE_COMM_DATA_REG3 0x1623
+#define mmSYMCLKA_CLOCK_ENABLE 0x0160
+#define mmSYMCLKB_CLOCK_ENABLE 0x0161
+#define mmSYMCLKC_CLOCK_ENABLE 0x0162
+#define mmSYMCLKD_CLOCK_ENABLE 0x0163
+#define mmSYMCLKE_CLOCK_ENABLE 0x0164
+#define mmSYMCLKF_CLOCK_ENABLE 0x0165
+#define mmTMDS_CNTL 0x1C7C
+#define mmTMDS_CONTROL0_FEEDBACK 0x1C7E
+#define mmTMDS_CONTROL_CHAR 0x1C7D
+#define mmTMDS_CTL0_1_GEN_CNTL 0x1C86
+#define mmTMDS_CTL2_3_GEN_CNTL 0x1C87
+#define mmTMDS_CTL_BITS 0x1C83
+#define mmTMDS_DCBALANCER_CONTROL 0x1C84
+#define mmTMDS_DEBUG 0x1C82
+#define mmTMDS_STEREOSYNC_CTL_SEL 0x1C7F
+#define mmTMDS_SYNC_CHAR_PATTERN_0_1 0x1C80
+#define mmTMDS_SYNC_CHAR_PATTERN_2_3 0x1C81
+#define mmUNIPHYAB_TPG_CONTROL 0x1931
+#define mmUNIPHYAB_TPG_SEED 0x1932
+#define mmUNIPHY_ANG_BIST_CNTL 0x198C
+#define mmUNIPHYCD_TPG_CONTROL 0x1933
+#define mmUNIPHYCD_TPG_SEED 0x1934
+#define mmUNIPHY_CHANNEL_XBAR_CNTL 0x198E
+#define mmUNIPHY_DATA_SYNCHRONIZATION 0x198A
+#define mmUNIPHYEF_TPG_CONTROL 0x1935
+#define mmUNIPHYEF_TPG_SEED 0x1936
+#define mmUNIPHY_IMPCAL_LINKA 0x1908
+#define mmUNIPHY_IMPCAL_LINKB 0x1909
+#define mmUNIPHY_IMPCAL_LINKC 0x190F
+#define mmUNIPHY_IMPCAL_LINKD 0x1910
+#define mmUNIPHY_IMPCAL_LINKE 0x1913
+#define mmUNIPHY_IMPCAL_LINKF 0x1914
+#define mmUNIPHY_IMPCAL_PERIOD 0x190A
+#define mmUNIPHY_IMPCAL_PSW_AB 0x190E
+#define mmUNIPHY_IMPCAL_PSW_CD 0x1912
+#define mmUNIPHY_IMPCAL_PSW_EF 0x1916
+#define mmUNIPHY_LINK_CNTL 0x198D
+#define mmUNIPHY_PLL_CONTROL1 0x1986
+#define mmUNIPHY_PLL_CONTROL2 0x1987
+#define mmUNIPHY_PLL_FBDIV 0x1985
+#define mmUNIPHY_PLL_SS_CNTL 0x1989
+#define mmUNIPHY_PLL_SS_STEP_SIZE 0x1988
+#define mmUNIPHY_POWER_CONTROL 0x1984
+#define mmUNIPHY_REG_TEST_OUTPUT 0x198B
+#define mmUNIPHY_SOFT_RESET 0x0166
+#define mmUNIPHY_TX_CONTROL1 0x1980
+#define mmUNIPHY_TX_CONTROL2 0x1981
+#define mmUNIPHY_TX_CONTROL3 0x1982
+#define mmUNIPHY_TX_CONTROL4 0x1983
+#define mmVGA25_PPLL_ANALOG 0x00E4
+#define mmVGA25_PPLL_FB_DIV 0x00DC
+#define mmVGA25_PPLL_POST_DIV 0x00E0
+#define mmVGA25_PPLL_REF_DIV 0x00D8
+#define mmVGA28_PPLL_ANALOG 0x00E5
+#define mmVGA28_PPLL_FB_DIV 0x00DD
+#define mmVGA28_PPLL_POST_DIV 0x00E1
+#define mmVGA28_PPLL_REF_DIV 0x00D9
+#define mmVGA41_PPLL_ANALOG 0x00E6
+#define mmVGA41_PPLL_FB_DIV 0x00DE
+#define mmVGA41_PPLL_POST_DIV 0x00E2
+#define mmVGA41_PPLL_REF_DIV 0x00DA
+#define mmVGA_CACHE_CONTROL 0x00CB
+#define mmVGA_DEBUG_READBACK_DATA 0x00D7
+#define mmVGA_DEBUG_READBACK_INDEX 0x00D6
+#define mmVGA_DISPBUF1_SURFACE_ADDR 0x00C6
+#define mmVGA_DISPBUF2_SURFACE_ADDR 0x00C8
+#define mmVGA_HDP_CONTROL 0x00CA
+#define mmVGA_HW_DEBUG 0x00CF
+#define mmVGA_INTERRUPT_CONTROL 0x00D1
+#define mmVGA_INTERRUPT_STATUS 0x00D3
+#define mmVGA_MAIN_CONTROL 0x00D4
+#define mmVGA_MEMORY_BASE_ADDRESS 0x00C4
+#define mmVGA_MEMORY_BASE_ADDRESS_HIGH 0x00C9
+#define mmVGA_MEM_READ_PAGE_ADDR 0x0013
+#define mmVGA_MEM_WRITE_PAGE_ADDR 0x0012
+#define mmVGA_MODE_CONTROL 0x00C2
+#define mmVGA_RENDER_CONTROL 0x00C0
+#define mmVGA_SEQUENCER_RESET_CONTROL 0x00C1
+#define mmVGA_SOURCE_SELECT 0x00FC
+#define mmVGA_STATUS 0x00D0
+#define mmVGA_STATUS_CLEAR 0x00D2
+#define mmVGA_SURFACE_PITCH_SELECT 0x00C3
+#define mmVGA_TEST_CONTROL 0x00D5
+#define mmVGA_TEST_DEBUG_DATA 0x00C7
+#define mmVGA_TEST_DEBUG_INDEX 0x00C5
+#define mmVIEWPORT_SIZE 0x1B5D
+#define mmVIEWPORT_START 0x1B5C
+#define mmXDMA_CLOCK_GATING_CNTL 0x0409
+#define mmXDMA_IF_BIF_STATUS 0x0418
+#define mmXDMA_INTERRUPT 0x0406
+#define mmXDMA_LOCAL_SURFACE_TILING1 0x03F4
+#define mmXDMA_LOCAL_SURFACE_TILING2 0x03F5
+#define mmXDMA_MC_PCIE_CLIENT_CONFIG 0x03E9
+#define mmXDMA_MEM_POWER_CNTL 0x040B
+#define mmXDMA_MSTR_CMD_URGENT_CNTL 0x03F6
+#define mmXDMA_MSTR_CNTL 0x03E0
+#define mmXDMA_MSTR_HEIGHT 0x03E3
+#define mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR 0x03F1
+#define mmXDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH 0x03F2
+#define mmXDMA_MSTR_LOCAL_SURFACE_PITCH 0x03F3
+#define mmXDMA_MSTR_MEM_CLIENT_CONFIG 0x03EA
+#define mmXDMA_MSTR_MEM_NACK_STATUS 0x040D
+#define mmXDMA_MSTR_MEM_URGENT_CNTL 0x03F7
+#define mmXDMA_MSTR_PCIE_NACK_STATUS 0x040C
+#define mmXDMA_MSTR_READ_COMMAND 0x03E1
+#define mmXDMA_MSTR_REMOTE_GPU_ADDRESS 0x03E6
+#define mmXDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH 0x03E7
+#define mmXDMA_MSTR_REMOTE_SURFACE_BASE 0x03E4
+#define mmXDMA_MSTR_REMOTE_SURFACE_BASE_HIGH 0x03E5
+#define mmXDMA_MSTR_STATUS 0x03E8
+#define mmXDMA_RBBMIF_RDWR_CNTL 0x040A
+#define mmXDMA_SLV_CNTL 0x03FB
+#define mmXDMA_SLV_FLIP_PENDING 0x0407
+#define mmXDMA_SLV_MEM_CLIENT_CONFIG 0x03FD
+#define mmXDMA_SLV_MEM_NACK_STATUS 0x040F
+#define mmXDMA_SLV_PCIE_NACK_STATUS 0x040E
+#define mmXDMA_SLV_READ_LATENCY_AVE 0x0405
+#define mmXDMA_SLV_READ_LATENCY_MINMAX 0x0404
+#define mmXDMA_SLV_READ_LATENCY_TIMER 0x0412
+#define mmXDMA_SLV_READ_URGENT_CNTL 0x03FF
+#define mmXDMA_SLV_REMOTE_GPU_ADDRESS 0x0402
+#define mmXDMA_SLV_REMOTE_GPU_ADDRESS_HIGH 0x0403
+#define mmXDMA_SLV_SLS_PITCH 0x03FE
+#define mmXDMA_SLV_WB_RATE_CNTL 0x0401
+#define mmXDMA_SLV_WRITE_URGENT_CNTL 0x0400
+#define mmXDMA_TEST_DEBUG_DATA 0x041D
+#define mmXDMA_TEST_DEBUG_INDEX 0x041C
+
+/* Registers that spilled out of sid.h */
+#define mmDATA_FORMAT                              0x1AC0
+#define mmDESKTOP_HEIGHT                           0x1AC1
+#define mmDC_LB_MEMORY_SPLIT                       0x1AC3
+#define mmPRIORITY_A_CNT                           0x1AC6
+#define mmPRIORITY_B_CNT                           0x1AC7
+#define mmDPG_PIPE_ARBITRATION_CONTROL3            0x1B32
+#define mmINT_MASK                                 0x1AD0
+#define mmVLINE_STATUS                             0x1AEE
+#define mmVBLANK_STATUS                            0x1AEF
+
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/dce/dce_6_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,9836 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 DCE_6_0_SH_MASK_H
+#define DCE_6_0_SH_MASK_H
+
+#define ABM_TEST_DEBUG_DATA__ABM_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define ABM_TEST_DEBUG_DATA__ABM_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define ABM_TEST_DEBUG_INDEX__ABM_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define AFMT_60958_0__AFMT_60958_CS_A_MASK 0x00000001L
+#define AFMT_60958_0__AFMT_60958_CS_A__SHIFT 0x00000000
+#define AFMT_60958_0__AFMT_60958_CS_B_MASK 0x00000002L
+#define AFMT_60958_0__AFMT_60958_CS_B__SHIFT 0x00000001
+#define AFMT_60958_0__AFMT_60958_CS_CATEGORY_CODE_MASK 0x0000ff00L
+#define AFMT_60958_0__AFMT_60958_CS_CATEGORY_CODE__SHIFT 0x00000008
+#define AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L_MASK 0x00f00000L
+#define AFMT_60958_0__AFMT_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x00000014
+#define AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY_MASK 0x30000000L
+#define AFMT_60958_0__AFMT_60958_CS_CLOCK_ACCURACY__SHIFT 0x0000001c
+#define AFMT_60958_0__AFMT_60958_CS_C_MASK 0x00000004L
+#define AFMT_60958_0__AFMT_60958_CS_C__SHIFT 0x00000002
+#define AFMT_60958_0__AFMT_60958_CS_D_MASK 0x00000038L
+#define AFMT_60958_0__AFMT_60958_CS_D__SHIFT 0x00000003
+#define AFMT_60958_0__AFMT_60958_CS_MODE_MASK 0x000000c0L
+#define AFMT_60958_0__AFMT_60958_CS_MODE__SHIFT 0x00000006
+#define AFMT_60958_0__AFMT_60958_CS_SAMPLING_FREQUENCY_MASK 0x0f000000L
+#define AFMT_60958_0__AFMT_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x00000018
+#define AFMT_60958_0__AFMT_60958_CS_SOURCE_NUMBER_MASK 0x000f0000L
+#define AFMT_60958_0__AFMT_60958_CS_SOURCE_NUMBER__SHIFT 0x00000010
+#define AFMT_60958_1__AFMT_60958_CS_CHANNEL_NUMBER_R_MASK 0x00f00000L
+#define AFMT_60958_1__AFMT_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x00000014
+#define AFMT_60958_1__AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0x000000f0L
+#define AFMT_60958_1__AFMT_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x00000004
+#define AFMT_60958_1__AFMT_60958_CS_WORD_LENGTH_MASK 0x0000000fL
+#define AFMT_60958_1__AFMT_60958_CS_WORD_LENGTH__SHIFT 0x00000000
+#define AFMT_60958_1__AFMT_60958_VALID_L_MASK 0x00010000L
+#define AFMT_60958_1__AFMT_60958_VALID_L__SHIFT 0x00000010
+#define AFMT_60958_1__AFMT_60958_VALID_R_MASK 0x00040000L
+#define AFMT_60958_1__AFMT_60958_VALID_R__SHIFT 0x00000012
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_2_MASK 0x0000000fL
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x00000000
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_3_MASK 0x000000f0L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x00000004
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_4_MASK 0x00000f00L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x00000008
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_5_MASK 0x0000f000L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x0000000c
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_6_MASK 0x000f0000L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x00000010
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_7_MASK 0x00f00000L
+#define AFMT_60958_2__AFMT_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x00000014
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CH_SEL_MASK 0x0000f000L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CH_SEL__SHIFT 0x0000000c
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CONT_MASK 0x00000010L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_CONT__SHIFT 0x00000004
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_COUNT_MASK 0xffff0000L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_COUNT__SHIFT 0x00000010
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_EN_MASK 0x00000001L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_EN__SHIFT 0x00000000
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_SOURCE_MASK 0x00000100L
+#define AFMT_AUDIO_CRC_CONTROL__AFMT_AUDIO_CRC_SOURCE__SHIFT 0x00000008
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_DONE_MASK 0x00000001L
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_DONE__SHIFT 0x00000000
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC_MASK 0xffffff00L
+#define AFMT_AUDIO_CRC_RESULT__AFMT_AUDIO_CRC__SHIFT 0x00000008
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_BASE_MASK 0x00000100L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_BASE__SHIFT 0x00000008
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_DIV_MASK 0x00070000L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_DIV__SHIFT 0x00000010
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_MULTI_MASK 0x00007000L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_DBG_MULTI__SHIFT 0x0000000c
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_FS_DIV_SEL_MASK 0x00000007L
+#define AFMT_AUDIO_DBG_DTO_CNTL__AFMT_AUDIO_DTO_FS_DIV_SEL__SHIFT 0x00000000
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CC_MASK 0x00000700L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CC__SHIFT 0x00000008
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_MASK 0x000000ffL
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_OFFSET_MASK 0x00ff0000L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM_OFFSET__SHIFT 0x00000010
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CHECKSUM__SHIFT 0x00000000
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CT_MASK 0x00007800L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CT__SHIFT 0x0000000b
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CXT_MASK 0x1f000000L
+#define AFMT_AUDIO_INFO0__AFMT_AUDIO_INFO_CXT__SHIFT 0x00000018
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_CA_MASK 0x000000ffL
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_CA__SHIFT 0x00000000
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_DM_INH_MASK 0x00008000L
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_DM_INH__SHIFT 0x0000000f
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LFEPBL_MASK 0x00030000L
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LFEPBL__SHIFT 0x00000010
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LSV_MASK 0x00007800L
+#define AFMT_AUDIO_INFO1__AFMT_AUDIO_INFO_LSV__SHIFT 0x0000000b
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_60958_OSF_OVRD_MASK 0x10000000L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_60958_OSF_OVRD__SHIFT 0x0000001c
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_CHANNEL_ENABLE_MASK 0x0000ff00L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_CHANNEL_ENABLE__SHIFT 0x00000008
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_OVRD_MASK 0x00000001L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_OVRD__SHIFT 0x00000000
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_SELECT_MASK 0x00000002L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_AUDIO_LAYOUT_SELECT__SHIFT 0x00000001
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_DP_AUDIO_STREAM_ID_MASK 0x00ff0000L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_DP_AUDIO_STREAM_ID__SHIFT 0x00000010
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_HBR_ENABLE_OVRD_MASK 0x01000000L
+#define AFMT_AUDIO_PACKET_CONTROL2__AFMT_HBR_ENABLE_OVRD__SHIFT 0x00000018
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_60958_CS_UPDATE_MASK 0x04000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_60958_CS_UPDATE__SHIFT 0x0000001a
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_CHANNEL_SWAP_MASK 0x01000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_CHANNEL_SWAP__SHIFT 0x00000018
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_FIFO_OVERFLOW_ACK_MASK 0x00800000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_FIFO_OVERFLOW_ACK__SHIFT 0x00000017
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND_MASK 0x00000001L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_SAMPLE_SEND__SHIFT 0x00000000
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_EN_MASK 0x00001000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_EN__SHIFT 0x0000000c
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_MODE_MASK 0x00004000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AUDIO_TEST_MODE__SHIFT 0x0000000e
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AZ_AUDIO_ENABLE_CHG_ACK_MASK 0x40000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_AZ_AUDIO_ENABLE_CHG_ACK__SHIFT 0x0000001e
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_BLANK_TEST_DATA_ON_ENC_ENB_MASK 0x80000000L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_BLANK_TEST_DATA_ON_ENC_ENB__SHIFT 0x0000001f
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_RESET_FIFO_WHEN_AUDIO_DIS_MASK 0x00000800L
+#define AFMT_AUDIO_PACKET_CONTROL__AFMT_RESET_FIFO_WHEN_AUDIO_DIS__SHIFT 0x0000000b
+#define AFMT_AUDIO_SRC_CONTROL__AFMT_AUDIO_SRC_SELECT_MASK 0x00000007L
+#define AFMT_AUDIO_SRC_CONTROL__AFMT_AUDIO_SRC_SELECT__SHIFT 0x00000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_A_MASK 0x00001000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_A__SHIFT 0x0000000c
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_B_MASK 0x00000c00L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_B__SHIFT 0x0000000a
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_CHECKSUM_MASK 0x000000ffL
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_CHECKSUM__SHIFT 0x00000000
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_C_MASK 0x00c00000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_C__SHIFT 0x00000016
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_EC_MASK 0x70000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_EC__SHIFT 0x0000001c
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_ITC_MASK 0x80000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_ITC__SHIFT 0x0000001f
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_M_MASK 0x00300000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_M__SHIFT 0x00000014
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_PB1_RSVD_MASK 0x00008000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_PB1_RSVD__SHIFT 0x0000000f
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Q_MASK 0x0c000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Q__SHIFT 0x0000001a
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_R_MASK 0x000f0000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_R__SHIFT 0x00000010
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_SC_MASK 0x03000000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_SC__SHIFT 0x00000018
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_S_MASK 0x00000300L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_S__SHIFT 0x00000008
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Y_MASK 0x00006000L
+#define AFMT_AVI_INFO0__AFMT_AVI_INFO_Y__SHIFT 0x0000000d
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_CN_MASK 0x00003000L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_CN__SHIFT 0x0000000c
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PB4_RSVD_MASK 0x00000080L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PB4_RSVD__SHIFT 0x00000007
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PR_MASK 0x00000f00L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_PR__SHIFT 0x00000008
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_TOP_MASK 0xffff0000L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_TOP__SHIFT 0x00000010
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_VIC_MASK 0x0000007fL
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_VIC__SHIFT 0x00000000
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_YQ_MASK 0x0000c000L
+#define AFMT_AVI_INFO1__AFMT_AVI_INFO_YQ__SHIFT 0x0000000e
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_BOTTOM_MASK 0x0000ffffL
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_BOTTOM__SHIFT 0x00000000
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_LEFT_MASK 0xffff0000L
+#define AFMT_AVI_INFO2__AFMT_AVI_INFO_LEFT__SHIFT 0x00000010
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_RIGHT_MASK 0x0000ffffL
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_RIGHT__SHIFT 0x00000000
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_VERSION_MASK 0xff000000L
+#define AFMT_AVI_INFO3__AFMT_AVI_INFO_VERSION__SHIFT 0x00000018
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE0_MASK 0x000000ffL
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE0__SHIFT 0x00000000
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE1_MASK 0x0000ff00L
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE1__SHIFT 0x00000008
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE2_MASK 0x00ff0000L
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE2__SHIFT 0x00000010
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE3_MASK 0xff000000L
+#define AFMT_GENERIC_0__AFMT_GENERIC_BYTE3__SHIFT 0x00000018
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE4_MASK 0x000000ffL
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE4__SHIFT 0x00000000
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE5_MASK 0x0000ff00L
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE5__SHIFT 0x00000008
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE6_MASK 0x00ff0000L
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE6__SHIFT 0x00000010
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE7_MASK 0xff000000L
+#define AFMT_GENERIC_1__AFMT_GENERIC_BYTE7__SHIFT 0x00000018
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE10_MASK 0x00ff0000L
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE10__SHIFT 0x00000010
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE11_MASK 0xff000000L
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE11__SHIFT 0x00000018
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE8_MASK 0x000000ffL
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE8__SHIFT 0x00000000
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE9_MASK 0x0000ff00L
+#define AFMT_GENERIC_2__AFMT_GENERIC_BYTE9__SHIFT 0x00000008
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE12_MASK 0x000000ffL
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE12__SHIFT 0x00000000
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE13_MASK 0x0000ff00L
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE13__SHIFT 0x00000008
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE14_MASK 0x00ff0000L
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE14__SHIFT 0x00000010
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE15_MASK 0xff000000L
+#define AFMT_GENERIC_3__AFMT_GENERIC_BYTE15__SHIFT 0x00000018
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE16_MASK 0x000000ffL
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE16__SHIFT 0x00000000
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE17_MASK 0x0000ff00L
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE17__SHIFT 0x00000008
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE18_MASK 0x00ff0000L
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE18__SHIFT 0x00000010
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE19_MASK 0xff000000L
+#define AFMT_GENERIC_4__AFMT_GENERIC_BYTE19__SHIFT 0x00000018
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE20_MASK 0x000000ffL
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE20__SHIFT 0x00000000
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE21_MASK 0x0000ff00L
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE21__SHIFT 0x00000008
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE22_MASK 0x00ff0000L
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE22__SHIFT 0x00000010
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE23_MASK 0xff000000L
+#define AFMT_GENERIC_5__AFMT_GENERIC_BYTE23__SHIFT 0x00000018
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE24_MASK 0x000000ffL
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE24__SHIFT 0x00000000
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE25_MASK 0x0000ff00L
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE25__SHIFT 0x00000008
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE26_MASK 0x00ff0000L
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE26__SHIFT 0x00000010
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE27_MASK 0xff000000L
+#define AFMT_GENERIC_6__AFMT_GENERIC_BYTE27__SHIFT 0x00000018
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE28_MASK 0x000000ffL
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE28__SHIFT 0x00000000
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE29_MASK 0x0000ff00L
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE29__SHIFT 0x00000008
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE30_MASK 0x00ff0000L
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE30__SHIFT 0x00000010
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE31_MASK 0xff000000L
+#define AFMT_GENERIC_7__AFMT_GENERIC_BYTE31__SHIFT 0x00000018
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB0_MASK 0x000000ffL
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB0__SHIFT 0x00000000
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB1_MASK 0x0000ff00L
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB1__SHIFT 0x00000008
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB2_MASK 0x00ff0000L
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB2__SHIFT 0x00000010
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB3_MASK 0xff000000L
+#define AFMT_GENERIC_HDR__AFMT_GENERIC_HB3__SHIFT 0x00000018
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_SOURCE_MASK 0x00000040L
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_SOURCE__SHIFT 0x00000006
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_UPDATE_MASK 0x00000080L
+#define AFMT_INFOFRAME_CONTROL0__AFMT_AUDIO_INFO_UPDATE__SHIFT 0x00000007
+#define AFMT_INFOFRAME_CONTROL0__AFMT_MPEG_INFO_UPDATE_MASK 0x00000400L
+#define AFMT_INFOFRAME_CONTROL0__AFMT_MPEG_INFO_UPDATE__SHIFT 0x0000000a
+#define AFMT_ISRC1_0__AFMT_ISRC_CONTINUE_MASK 0x00000040L
+#define AFMT_ISRC1_0__AFMT_ISRC_CONTINUE__SHIFT 0x00000006
+#define AFMT_ISRC1_0__AFMT_ISRC_STATUS_MASK 0x00000007L
+#define AFMT_ISRC1_0__AFMT_ISRC_STATUS__SHIFT 0x00000000
+#define AFMT_ISRC1_0__AFMT_ISRC_VALID_MASK 0x00000080L
+#define AFMT_ISRC1_0__AFMT_ISRC_VALID__SHIFT 0x00000007
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC0_MASK 0x000000ffL
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC0__SHIFT 0x00000000
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC1_MASK 0x0000ff00L
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC1__SHIFT 0x00000008
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC2_MASK 0x00ff0000L
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC2__SHIFT 0x00000010
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC3_MASK 0xff000000L
+#define AFMT_ISRC1_1__AFMT_UPC_EAN_ISRC3__SHIFT 0x00000018
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC4_MASK 0x000000ffL
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC4__SHIFT 0x00000000
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC5_MASK 0x0000ff00L
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC5__SHIFT 0x00000008
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC6_MASK 0x00ff0000L
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC6__SHIFT 0x00000010
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC7_MASK 0xff000000L
+#define AFMT_ISRC1_2__AFMT_UPC_EAN_ISRC7__SHIFT 0x00000018
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC10_MASK 0x00ff0000L
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC10__SHIFT 0x00000010
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC11_MASK 0xff000000L
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC11__SHIFT 0x00000018
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC8_MASK 0x000000ffL
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC8__SHIFT 0x00000000
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC9_MASK 0x0000ff00L
+#define AFMT_ISRC1_3__AFMT_UPC_EAN_ISRC9__SHIFT 0x00000008
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC12_MASK 0x000000ffL
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC12__SHIFT 0x00000000
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC13_MASK 0x0000ff00L
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC13__SHIFT 0x00000008
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC14_MASK 0x00ff0000L
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC14__SHIFT 0x00000010
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC15_MASK 0xff000000L
+#define AFMT_ISRC1_4__AFMT_UPC_EAN_ISRC15__SHIFT 0x00000018
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC16_MASK 0x000000ffL
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC16__SHIFT 0x00000000
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC17_MASK 0x0000ff00L
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC17__SHIFT 0x00000008
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC18_MASK 0x00ff0000L
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC18__SHIFT 0x00000010
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC19_MASK 0xff000000L
+#define AFMT_ISRC2_0__AFMT_UPC_EAN_ISRC19__SHIFT 0x00000018
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC20_MASK 0x000000ffL
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC20__SHIFT 0x00000000
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC21_MASK 0x0000ff00L
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC21__SHIFT 0x00000008
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC22_MASK 0x00ff0000L
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC22__SHIFT 0x00000010
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC23_MASK 0xff000000L
+#define AFMT_ISRC2_1__AFMT_UPC_EAN_ISRC23__SHIFT 0x00000018
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC24_MASK 0x000000ffL
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC24__SHIFT 0x00000000
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC25_MASK 0x0000ff00L
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC25__SHIFT 0x00000008
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC26_MASK 0x00ff0000L
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC26__SHIFT 0x00000010
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC27_MASK 0xff000000L
+#define AFMT_ISRC2_2__AFMT_UPC_EAN_ISRC27__SHIFT 0x00000018
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC28_MASK 0x000000ffL
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC28__SHIFT 0x00000000
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC29_MASK 0x0000ff00L
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC29__SHIFT 0x00000008
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC30_MASK 0x00ff0000L
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC30__SHIFT 0x00000010
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC31_MASK 0xff000000L
+#define AFMT_ISRC2_3__AFMT_UPC_EAN_ISRC31__SHIFT 0x00000018
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_CHECKSUM_MASK 0x000000ffL
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_CHECKSUM__SHIFT 0x00000000
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB0_MASK 0x0000ff00L
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB0__SHIFT 0x00000008
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB1_MASK 0x00ff0000L
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB1__SHIFT 0x00000010
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB2_MASK 0xff000000L
+#define AFMT_MPEG_INFO0__AFMT_MPEG_INFO_MB2__SHIFT 0x00000018
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_FR_MASK 0x00001000L
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_FR__SHIFT 0x0000000c
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MB3_MASK 0x000000ffL
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MB3__SHIFT 0x00000000
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MF_MASK 0x00000300L
+#define AFMT_MPEG_INFO1__AFMT_MPEG_INFO_MF__SHIFT 0x00000008
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_DATA_SIGN_MASK 0x80000000L
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_DATA_SIGN__SHIFT 0x0000001f
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_MAX_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL0__AFMT_RAMP_MAX_COUNT__SHIFT 0x00000000
+#define AFMT_RAMP_CONTROL1__AFMT_AUDIO_TEST_CH_DISABLE_MASK 0xff000000L
+#define AFMT_RAMP_CONTROL1__AFMT_AUDIO_TEST_CH_DISABLE__SHIFT 0x00000018
+#define AFMT_RAMP_CONTROL1__AFMT_RAMP_MIN_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL1__AFMT_RAMP_MIN_COUNT__SHIFT 0x00000000
+#define AFMT_RAMP_CONTROL2__AFMT_RAMP_INC_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL2__AFMT_RAMP_INC_COUNT__SHIFT 0x00000000
+#define AFMT_RAMP_CONTROL3__AFMT_RAMP_DEC_COUNT_MASK 0x00ffffffL
+#define AFMT_RAMP_CONTROL3__AFMT_RAMP_DEC_COUNT__SHIFT 0x00000000
+#define AFMT_STATUS__AFMT_AUDIO_ENABLE_MASK 0x00000010L
+#define AFMT_STATUS__AFMT_AUDIO_ENABLE__SHIFT 0x00000004
+#define AFMT_STATUS__AFMT_AUDIO_FIFO_OVERFLOW_MASK 0x01000000L
+#define AFMT_STATUS__AFMT_AUDIO_FIFO_OVERFLOW__SHIFT 0x00000018
+#define AFMT_STATUS__AFMT_AZ_AUDIO_ENABLE_CHG_MASK 0x40000000L
+#define AFMT_STATUS__AFMT_AZ_AUDIO_ENABLE_CHG__SHIFT 0x0000001e
+#define AFMT_STATUS__AFMT_AZ_HBR_ENABLE_MASK 0x00000100L
+#define AFMT_STATUS__AFMT_AZ_HBR_ENABLE__SHIFT 0x00000008
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC0_UPDATE_MASK 0x00000004L
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC0_UPDATE__SHIFT 0x00000002
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC2_UPDATE_MASK 0x00000008L
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC2_UPDATE__SHIFT 0x00000003
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC_INDEX_MASK 0xc0000000L
+#define AFMT_VBI_PACKET_CONTROL__AFMT_GENERIC_INDEX__SHIFT 0x0000001e
+#define ATTR00__ATTR_PAL_MASK 0x0000003fL
+#define ATTR00__ATTR_PAL__SHIFT 0x00000000
+#define ATTR01__ATTR_PAL_MASK 0x0000003fL
+#define ATTR01__ATTR_PAL__SHIFT 0x00000000
+#define ATTR02__ATTR_PAL_MASK 0x0000003fL
+#define ATTR02__ATTR_PAL__SHIFT 0x00000000
+#define ATTR03__ATTR_PAL_MASK 0x0000003fL
+#define ATTR03__ATTR_PAL__SHIFT 0x00000000
+#define ATTR04__ATTR_PAL_MASK 0x0000003fL
+#define ATTR04__ATTR_PAL__SHIFT 0x00000000
+#define ATTR05__ATTR_PAL_MASK 0x0000003fL
+#define ATTR05__ATTR_PAL__SHIFT 0x00000000
+#define ATTR06__ATTR_PAL_MASK 0x0000003fL
+#define ATTR06__ATTR_PAL__SHIFT 0x00000000
+#define ATTR07__ATTR_PAL_MASK 0x0000003fL
+#define ATTR07__ATTR_PAL__SHIFT 0x00000000
+#define ATTR08__ATTR_PAL_MASK 0x0000003fL
+#define ATTR08__ATTR_PAL__SHIFT 0x00000000
+#define ATTR09__ATTR_PAL_MASK 0x0000003fL
+#define ATTR09__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0A__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0A__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0B__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0B__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0C__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0C__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0D__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0D__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0E__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0E__ATTR_PAL__SHIFT 0x00000000
+#define ATTR0F__ATTR_PAL_MASK 0x0000003fL
+#define ATTR0F__ATTR_PAL__SHIFT 0x00000000
+#define ATTR10__ATTR_BLINK_EN_MASK 0x00000008L
+#define ATTR10__ATTR_BLINK_EN__SHIFT 0x00000003
+#define ATTR10__ATTR_CSEL_EN_MASK 0x00000080L
+#define ATTR10__ATTR_CSEL_EN__SHIFT 0x00000007
+#define ATTR10__ATTR_GRPH_MODE_MASK 0x00000001L
+#define ATTR10__ATTR_GRPH_MODE__SHIFT 0x00000000
+#define ATTR10__ATTR_LGRPH_EN_MASK 0x00000004L
+#define ATTR10__ATTR_LGRPH_EN__SHIFT 0x00000002
+#define ATTR10__ATTR_MONO_EN_MASK 0x00000002L
+#define ATTR10__ATTR_MONO_EN__SHIFT 0x00000001
+#define ATTR10__ATTR_PANTOPONLY_MASK 0x00000020L
+#define ATTR10__ATTR_PANTOPONLY__SHIFT 0x00000005
+#define ATTR10__ATTR_PCLKBY2_MASK 0x00000040L
+#define ATTR10__ATTR_PCLKBY2__SHIFT 0x00000006
+#define ATTR11__ATTR_OVSC_MASK 0x000000ffL
+#define ATTR11__ATTR_OVSC__SHIFT 0x00000000
+#define ATTR12__ATTR_MAP_EN_MASK 0x0000000fL
+#define ATTR12__ATTR_MAP_EN__SHIFT 0x00000000
+#define ATTR12__ATTR_VSMUX_MASK 0x00000030L
+#define ATTR12__ATTR_VSMUX__SHIFT 0x00000004
+#define ATTR13__ATTR_PPAN_MASK 0x0000000fL
+#define ATTR13__ATTR_PPAN__SHIFT 0x00000000
+#define ATTR14__ATTR_CSEL1_MASK 0x00000003L
+#define ATTR14__ATTR_CSEL1__SHIFT 0x00000000
+#define ATTR14__ATTR_CSEL2_MASK 0x0000000cL
+#define ATTR14__ATTR_CSEL2__SHIFT 0x00000002
+#define ATTRDR__ATTR_DATA_MASK 0x000000ffL
+#define ATTRDR__ATTR_DATA__SHIFT 0x00000000
+#define ATTRDW__ATTR_DATA_MASK 0x000000ffL
+#define ATTRDW__ATTR_DATA__SHIFT 0x00000000
+#define ATTRX__ATTR_IDX_MASK 0x0000001fL
+#define ATTRX__ATTR_IDX__SHIFT 0x00000000
+#define ATTRX__ATTR_PAL_RW_ENB_MASK 0x00000020L
+#define ATTRX__ATTR_PAL_RW_ENB__SHIFT 0x00000005
+#define AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR0__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR10__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR10__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR11__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR11__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR12__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR12__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR13__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR13__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR1__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR1__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR2__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR2__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR3__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR3__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR4__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR4__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR5__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR5__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR6__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR6__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR7__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR7__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR8__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR8__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AUDIO_DESCRIPTOR9__MAX_CHANNELS_MASK 0x00000007L
+#define AUDIO_DESCRIPTOR9__MAX_CHANNELS__SHIFT 0x00000000
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AUX_ARB_CONTROL__AUX_ARB_PRIORITY_MASK 0x00000003L
+#define AUX_ARB_CONTROL__AUX_ARB_PRIORITY__SHIFT 0x00000000
+#define AUX_ARB_CONTROL__AUX_DMCU_DONE_USING_AUX_REG_MASK 0x02000000L
+#define AUX_ARB_CONTROL__AUX_DMCU_DONE_USING_AUX_REG__SHIFT 0x00000019
+#define AUX_ARB_CONTROL__AUX_DMCU_PENDING_USE_AUX_REG_REQ_MASK 0x01000000L
+#define AUX_ARB_CONTROL__AUX_DMCU_PENDING_USE_AUX_REG_REQ__SHIFT 0x00000018
+#define AUX_ARB_CONTROL__AUX_DMCU_USE_AUX_REG_REQ_MASK 0x01000000L
+#define AUX_ARB_CONTROL__AUX_DMCU_USE_AUX_REG_REQ__SHIFT 0x00000018
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_LS_GO_MASK 0x00000400L
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_LS_GO__SHIFT 0x0000000a
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_SW_GO_MASK 0x00000100L
+#define AUX_ARB_CONTROL__AUX_NO_QUEUED_SW_GO__SHIFT 0x00000008
+#define AUX_ARB_CONTROL__AUX_REG_RW_CNTL_STATUS_MASK 0x0000000cL
+#define AUX_ARB_CONTROL__AUX_REG_RW_CNTL_STATUS__SHIFT 0x00000002
+#define AUX_ARB_CONTROL__AUX_SW_DONE_USING_AUX_REG_MASK 0x00020000L
+#define AUX_ARB_CONTROL__AUX_SW_DONE_USING_AUX_REG__SHIFT 0x00000011
+#define AUX_ARB_CONTROL__AUX_SW_PENDING_USE_AUX_REG_REQ_MASK 0x00010000L
+#define AUX_ARB_CONTROL__AUX_SW_PENDING_USE_AUX_REG_REQ__SHIFT 0x00000010
+#define AUX_ARB_CONTROL__AUX_SW_USE_AUX_REG_REQ_MASK 0x00010000L
+#define AUX_ARB_CONTROL__AUX_SW_USE_AUX_REG_REQ__SHIFT 0x00000010
+#define AUX_CONTROL__AUX_DEGLITCH_EN_MASK 0x20000000L
+#define AUX_CONTROL__AUX_DEGLITCH_EN__SHIFT 0x0000001d
+#define AUX_CONTROL__AUX_EN_MASK 0x00000001L
+#define AUX_CONTROL__AUX_EN__SHIFT 0x00000000
+#define AUX_CONTROL__AUX_HPD_SEL_MASK 0x00700000L
+#define AUX_CONTROL__AUX_HPD_SEL__SHIFT 0x00000014
+#define AUX_CONTROL__AUX_IGNORE_HPD_DISCON_MASK 0x00010000L
+#define AUX_CONTROL__AUX_IGNORE_HPD_DISCON__SHIFT 0x00000010
+#define AUX_CONTROL__AUX_IMPCAL_REQ_EN_MASK 0x01000000L
+#define AUX_CONTROL__AUX_IMPCAL_REQ_EN__SHIFT 0x00000018
+#define AUX_CONTROL__AUX_LS_READ_EN_MASK 0x00000100L
+#define AUX_CONTROL__AUX_LS_READ_EN__SHIFT 0x00000008
+#define AUX_CONTROL__AUX_LS_UPDATE_DISABLE_MASK 0x00001000L
+#define AUX_CONTROL__AUX_LS_UPDATE_DISABLE__SHIFT 0x0000000c
+#define AUX_CONTROL__AUX_MODE_DET_EN_MASK 0x00040000L
+#define AUX_CONTROL__AUX_MODE_DET_EN__SHIFT 0x00000012
+#define AUX_CONTROL__AUX_TEST_MODE_MASK 0x10000000L
+#define AUX_CONTROL__AUX_TEST_MODE__SHIFT 0x0000001c
+#define AUX_CONTROL__SPARE_0_MASK 0x40000000L
+#define AUX_CONTROL__SPARE_0__SHIFT 0x0000001e
+#define AUX_CONTROL__SPARE_1_MASK 0x80000000L
+#define AUX_CONTROL__SPARE_1__SHIFT 0x0000001f
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT_MASK 0x00020000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT__SHIFT 0x00000011
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_START_MASK 0x00040000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_START__SHIFT 0x00000012
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_STOP_MASK 0x00080000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_ALLOW_BELOW_THRESHOLD_STOP__SHIFT 0x00000013
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_DETECTION_THRESHOLD_MASK 0x70000000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_DETECTION_THRESHOLD__SHIFT 0x0000001c
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_HALF_SYM_DETECT_LEN_MASK 0x00003000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_HALF_SYM_DETECT_LEN__SHIFT 0x0000000c
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_PHASE_DETECT_LEN_MASK 0x00300000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_PHASE_DETECT_LEN__SHIFT 0x00000014
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_RECEIVE_WINDOW_MASK 0x00000700L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_RECEIVE_WINDOW__SHIFT 0x00000008
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_START_WINDOW_MASK 0x00000070L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_START_WINDOW__SHIFT 0x00000004
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TIMEOUT_LEN_MASK 0x07000000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TIMEOUT_LEN__SHIFT 0x00000018
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TRANSITION_FILTER_EN_MASK 0x00010000L
+#define AUX_DPHY_RX_CONTROL0__AUX_RX_TRANSITION_FILTER_EN__SHIFT 0x00000010
+#define AUX_DPHY_RX_CONTROL1__AUX_RX_PRECHARGE_SKIP_MASK 0x000000ffL
+#define AUX_DPHY_RX_CONTROL1__AUX_RX_PRECHARGE_SKIP__SHIFT 0x00000000
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_FRACT_MASK 0x001f0000L
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_FRACT__SHIFT 0x00000010
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD_MASK 0x3fe00000L
+#define AUX_DPHY_RX_STATUS__AUX_RX_HALF_SYM_PERIOD__SHIFT 0x00000015
+#define AUX_DPHY_RX_STATUS__AUX_RX_STATE_MASK 0x00000007L
+#define AUX_DPHY_RX_STATUS__AUX_RX_STATE__SHIFT 0x00000000
+#define AUX_DPHY_RX_STATUS__AUX_RX_SYNC_VALID_COUNT_MASK 0x00001f00L
+#define AUX_DPHY_RX_STATUS__AUX_RX_SYNC_VALID_COUNT__SHIFT 0x00000008
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_LEN_MASK 0x00000007L
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_LEN__SHIFT 0x00000000
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_SYMBOLS_MASK 0x00003f00L
+#define AUX_DPHY_TX_CONTROL__AUX_TX_PRECHARGE_SYMBOLS__SHIFT 0x00000008
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_RATE_MASK 0x00000030L
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_RATE__SHIFT 0x00000004
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_DIV_MASK 0x01ff0000L
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_DIV__SHIFT 0x00000010
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_SEL_MASK 0x00000001L
+#define AUX_DPHY_TX_REF_CONTROL__AUX_TX_REF_SEL__SHIFT 0x00000000
+#define AUX_DPHY_TX_STATUS__AUX_TX_ACTIVE_MASK 0x00000001L
+#define AUX_DPHY_TX_STATUS__AUX_TX_ACTIVE__SHIFT 0x00000000
+#define AUX_DPHY_TX_STATUS__AUX_TX_HALF_SYM_PERIOD_MASK 0x01ff0000L
+#define AUX_DPHY_TX_STATUS__AUX_TX_HALF_SYM_PERIOD__SHIFT 0x00000010
+#define AUX_DPHY_TX_STATUS__AUX_TX_STATE_MASK 0x00000070L
+#define AUX_DPHY_TX_STATUS__AUX_TX_STATE__SHIFT 0x00000004
+#define AUX_GTC_SYNC_CONTROL__AUX_GTC_SYNC_EN_MASK 0x00000001L
+#define AUX_GTC_SYNC_CONTROL__AUX_GTC_SYNC_EN__SHIFT 0x00000000
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_ACK_MASK 0x00000020L
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_ACK__SHIFT 0x00000005
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_INT_MASK 0x00000010L
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_INT__SHIFT 0x00000004
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_MASK_MASK 0x00000040L
+#define AUX_INTERRUPT_CONTROL__AUX_LS_DONE_MASK__SHIFT 0x00000006
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_ACK_MASK 0x00000002L
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_ACK__SHIFT 0x00000001
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_INT_MASK 0x00000001L
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_INT__SHIFT 0x00000000
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_MASK_MASK 0x00000004L
+#define AUX_INTERRUPT_CONTROL__AUX_SW_DONE_MASK__SHIFT 0x00000002
+#define AUX_LS_DATA__AUX_LS_DATA_MASK 0x0000ff00L
+#define AUX_LS_DATA__AUX_LS_DATA__SHIFT 0x00000008
+#define AUX_LS_DATA__AUX_LS_INDEX_MASK 0x001f0000L
+#define AUX_LS_DATA__AUX_LS_INDEX__SHIFT 0x00000010
+#define AUX_LS_STATUS__AUX_LS_CP_IRQ_MASK 0x20000000L
+#define AUX_LS_STATUS__AUX_LS_CP_IRQ__SHIFT 0x0000001d
+#define AUX_LS_STATUS__AUX_LS_DONE_MASK 0x00000001L
+#define AUX_LS_STATUS__AUX_LS_DONE__SHIFT 0x00000000
+#define AUX_LS_STATUS__AUX_LS_HPD_DISCON_MASK 0x00000200L
+#define AUX_LS_STATUS__AUX_LS_HPD_DISCON__SHIFT 0x00000009
+#define AUX_LS_STATUS__AUX_LS_NON_AUX_MODE_MASK 0x00000800L
+#define AUX_LS_STATUS__AUX_LS_NON_AUX_MODE__SHIFT 0x0000000b
+#define AUX_LS_STATUS__AUX_LS_REPLY_BYTE_COUNT_MASK 0x1f000000L
+#define AUX_LS_STATUS__AUX_LS_REPLY_BYTE_COUNT__SHIFT 0x00000018
+#define AUX_LS_STATUS__AUX_LS_REQ_MASK 0x00000002L
+#define AUX_LS_STATUS__AUX_LS_REQ__SHIFT 0x00000001
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_START_MASK 0x00080000L
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_START__SHIFT 0x00000013
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_STOP_MASK 0x00004000L
+#define AUX_LS_STATUS__AUX_LS_RX_INVALID_STOP__SHIFT 0x0000000e
+#define AUX_LS_STATUS__AUX_LS_RX_MIN_COUNT_VIOL_MASK 0x00001000L
+#define AUX_LS_STATUS__AUX_LS_RX_MIN_COUNT_VIOL__SHIFT 0x0000000c
+#define AUX_LS_STATUS__AUX_LS_RX_OVERFLOW_MASK 0x00000100L
+#define AUX_LS_STATUS__AUX_LS_RX_OVERFLOW__SHIFT 0x00000008
+#define AUX_LS_STATUS__AUX_LS_RX_PARTIAL_BYTE_MASK 0x00000400L
+#define AUX_LS_STATUS__AUX_LS_RX_PARTIAL_BYTE__SHIFT 0x0000000a
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_H_MASK 0x00400000L
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_H__SHIFT 0x00000016
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_L_MASK 0x00800000L
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_INVALID_L__SHIFT 0x00000017
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_NO_DET_MASK 0x00100000L
+#define AUX_LS_STATUS__AUX_LS_RX_RECV_NO_DET__SHIFT 0x00000014
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_H_MASK 0x00040000L
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_H__SHIFT 0x00000012
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_L_MASK 0x00020000L
+#define AUX_LS_STATUS__AUX_LS_RX_SYNC_INVALID_L__SHIFT 0x00000011
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_MASK 0x00000080L
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT__SHIFT 0x00000007
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_STATE_MASK 0x00000070L
+#define AUX_LS_STATUS__AUX_LS_RX_TIMEOUT_STATE__SHIFT 0x00000004
+#define AUX_LS_STATUS__AUX_LS_UPDATED_ACK_MASK 0x80000000L
+#define AUX_LS_STATUS__AUX_LS_UPDATED_ACK__SHIFT 0x0000001f
+#define AUX_LS_STATUS__AUX_LS_UPDATED_MASK 0x40000000L
+#define AUX_LS_STATUS__AUX_LS_UPDATED__SHIFT 0x0000001e
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_AK_MASK 0x00000400L
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_AK__SHIFT 0x0000000a
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR_MASK 0x00000200L
+#define AUXN_IMPCAL__AUXN_CALOUT_ERROR__SHIFT 0x00000009
+#define AUXN_IMPCAL__AUXN_IMPCAL_CALOUT_MASK 0x00000100L
+#define AUXN_IMPCAL__AUXN_IMPCAL_CALOUT__SHIFT 0x00000008
+#define AUXN_IMPCAL__AUXN_IMPCAL_ENABLE_MASK 0x00000001L
+#define AUXN_IMPCAL__AUXN_IMPCAL_ENABLE__SHIFT 0x00000000
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_ENABLE_MASK 0x10000000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_ENABLE__SHIFT 0x0000001c
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE_MASK 0x0f000000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_OVERRIDE__SHIFT 0x00000018
+#define AUXN_IMPCAL__AUXN_IMPCAL_STEP_DELAY_MASK 0x00f00000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_STEP_DELAY__SHIFT 0x00000014
+#define AUXN_IMPCAL__AUXN_IMPCAL_VALUE_MASK 0x000f0000L
+#define AUXN_IMPCAL__AUXN_IMPCAL_VALUE__SHIFT 0x00000010
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_AK_MASK 0x00000400L
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_AK__SHIFT 0x0000000a
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR_MASK 0x00000200L
+#define AUXP_IMPCAL__AUXP_CALOUT_ERROR__SHIFT 0x00000009
+#define AUXP_IMPCAL__AUXP_IMPCAL_CALOUT_MASK 0x00000100L
+#define AUXP_IMPCAL__AUXP_IMPCAL_CALOUT__SHIFT 0x00000008
+#define AUXP_IMPCAL__AUXP_IMPCAL_ENABLE_MASK 0x00000001L
+#define AUXP_IMPCAL__AUXP_IMPCAL_ENABLE__SHIFT 0x00000000
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_ENABLE_MASK 0x10000000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_ENABLE__SHIFT 0x0000001c
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE_MASK 0x0f000000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_OVERRIDE__SHIFT 0x00000018
+#define AUXP_IMPCAL__AUXP_IMPCAL_STEP_DELAY_MASK 0x00f00000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_STEP_DELAY__SHIFT 0x00000014
+#define AUXP_IMPCAL__AUXP_IMPCAL_VALUE_MASK 0x000f0000L
+#define AUXP_IMPCAL__AUXP_IMPCAL_VALUE__SHIFT 0x00000010
+#define AUX_SW_CONTROL__AUX_LS_READ_TRIG_MASK 0x00000004L
+#define AUX_SW_CONTROL__AUX_LS_READ_TRIG__SHIFT 0x00000002
+#define AUX_SW_CONTROL__AUX_SW_GO_MASK 0x00000001L
+#define AUX_SW_CONTROL__AUX_SW_GO__SHIFT 0x00000000
+#define AUX_SW_CONTROL__AUX_SW_START_DELAY_MASK 0x000000f0L
+#define AUX_SW_CONTROL__AUX_SW_START_DELAY__SHIFT 0x00000004
+#define AUX_SW_CONTROL__AUX_SW_WR_BYTES_MASK 0x001f0000L
+#define AUX_SW_CONTROL__AUX_SW_WR_BYTES__SHIFT 0x00000010
+#define AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE_MASK 0x80000000L
+#define AUX_SW_DATA__AUX_SW_AUTOINCREMENT_DISABLE__SHIFT 0x0000001f
+#define AUX_SW_DATA__AUX_SW_DATA_MASK 0x0000ff00L
+#define AUX_SW_DATA__AUX_SW_DATA_RW_MASK 0x00000001L
+#define AUX_SW_DATA__AUX_SW_DATA_RW__SHIFT 0x00000000
+#define AUX_SW_DATA__AUX_SW_DATA__SHIFT 0x00000008
+#define AUX_SW_DATA__AUX_SW_INDEX_MASK 0x001f0000L
+#define AUX_SW_DATA__AUX_SW_INDEX__SHIFT 0x00000010
+#define AUX_SW_STATUS__AUX_ARB_STATUS_MASK 0xc0000000L
+#define AUX_SW_STATUS__AUX_ARB_STATUS__SHIFT 0x0000001e
+#define AUX_SW_STATUS__AUX_SW_DONE_MASK 0x00000001L
+#define AUX_SW_STATUS__AUX_SW_DONE__SHIFT 0x00000000
+#define AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK 0x00000200L
+#define AUX_SW_STATUS__AUX_SW_HPD_DISCON__SHIFT 0x00000009
+#define AUX_SW_STATUS__AUX_SW_NON_AUX_MODE_MASK 0x00000800L
+#define AUX_SW_STATUS__AUX_SW_NON_AUX_MODE__SHIFT 0x0000000b
+#define AUX_SW_STATUS__AUX_SW_REPLY_BYTE_COUNT_MASK 0x1f000000L
+#define AUX_SW_STATUS__AUX_SW_REPLY_BYTE_COUNT__SHIFT 0x00000018
+#define AUX_SW_STATUS__AUX_SW_REQ_MASK 0x00000002L
+#define AUX_SW_STATUS__AUX_SW_REQ__SHIFT 0x00000001
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_START_MASK 0x00080000L
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_START__SHIFT 0x00000013
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK 0x00004000L
+#define AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP__SHIFT 0x0000000e
+#define AUX_SW_STATUS__AUX_SW_RX_MIN_COUNT_VIOL_MASK 0x00001000L
+#define AUX_SW_STATUS__AUX_SW_RX_MIN_COUNT_VIOL__SHIFT 0x0000000c
+#define AUX_SW_STATUS__AUX_SW_RX_OVERFLOW_MASK 0x00000100L
+#define AUX_SW_STATUS__AUX_SW_RX_OVERFLOW__SHIFT 0x00000008
+#define AUX_SW_STATUS__AUX_SW_RX_PARTIAL_BYTE_MASK 0x00000400L
+#define AUX_SW_STATUS__AUX_SW_RX_PARTIAL_BYTE__SHIFT 0x0000000a
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK 0x00400000L
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H__SHIFT 0x00000016
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK 0x00800000L
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L__SHIFT 0x00000017
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK 0x00100000L
+#define AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET__SHIFT 0x00000014
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_H_MASK 0x00040000L
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_H__SHIFT 0x00000012
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_L_MASK 0x00020000L
+#define AUX_SW_STATUS__AUX_SW_RX_SYNC_INVALID_L__SHIFT 0x00000011
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK 0x00000080L
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT__SHIFT 0x00000007
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK 0x00000070L
+#define AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE__SHIFT 0x00000004
+#define AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__APPLICATION_POSITION_IN_CYCLIC_BUFFER_MASK 0xffffffffL
+#define AZALIA_APPLICATION_POSITION_IN_CYCLIC_BUFFER__APPLICATION_POSITION_IN_CYCLIC_BUFFER__SHIFT 0x00000000
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_MODULE_MASK 0xffff0000L
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_MODULE__SHIFT 0x00000010
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_PHASE_MASK 0x0000ffffL
+#define AZALIA_AUDIO_DTO__AZALIA_AUDIO_DTO_PHASE__SHIFT 0x00000000
+#define AZALIA_AUDIO_DTO_CONTROL__AZALIA_AUDIO_FORCE_DTO_MASK 0x00000300L
+#define AZALIA_AUDIO_DTO_CONTROL__AZALIA_AUDIO_FORCE_DTO__SHIFT 0x00000008
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_ISOCHRONOUS_MASK 0x00000030L
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_ISOCHRONOUS__SHIFT 0x00000004
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_NON_SNOOP_MASK 0x00000003L
+#define AZALIA_BDL_DMA_CONTROL__BDL_DMA_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_CONTROLLER_DEBUG__CONTROLLER_DEBUG_MASK 0xffffffffL
+#define AZALIA_CONTROLLER_DEBUG__CONTROLLER_DEBUG__SHIFT 0x00000000
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_ISOCHRONOUS_MASK 0x00000010L
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_ISOCHRONOUS__SHIFT 0x00000004
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_NON_SNOOP_MASK 0x00000001L
+#define AZALIA_CORB_DMA_CONTROL__CORB_DMA_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_CUMULATIVE_LATENCY_COUNT__AZALIA_CUMULATIVE_LATENCY_COUNT_MASK 0xffffffffL
+#define AZALIA_CUMULATIVE_LATENCY_COUNT__AZALIA_CUMULATIVE_LATENCY_COUNT__SHIFT 0x00000000
+#define AZALIA_CUMULATIVE_REQUEST_COUNT__AZALIA_CUMULATIVE_REQUEST_COUNT_MASK 0xffffffffL
+#define AZALIA_CUMULATIVE_REQUEST_COUNT__AZALIA_CUMULATIVE_REQUEST_COUNT__SHIFT 0x00000000
+#define AZALIA_CYCLIC_BUFFER_SYNC__CYCLIC_BUFFER_SYNC_ENABLE_MASK 0x00000001L
+#define AZALIA_CYCLIC_BUFFER_SYNC__CYCLIC_BUFFER_SYNC_ENABLE__SHIFT 0x00000000
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_IOC_GENERATION_METHOD_MASK 0x00010000L
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_IOC_GENERATION_METHOD__SHIFT 0x00000010
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_UNDERFLOW_CONTROL_MASK 0x00020000L
+#define AZALIA_DATA_DMA_CONTROL__AZALIA_UNDERFLOW_CONTROL__SHIFT 0x00000011
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_ISOCHRONOUS_MASK 0x00000030L
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_ISOCHRONOUS__SHIFT 0x00000004
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_NON_SNOOP_MASK 0x00000003L
+#define AZALIA_DATA_DMA_CONTROL__DATA_DMA_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__COMPRESSED_CHANNEL_COUNT_MASK 0x00000070L
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__COMPRESSED_CHANNEL_COUNT__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__HBR_CHANNEL_COUNT_MASK 0x00000007L
+#define AZALIA_F0_CODEC_CHANNEL_COUNT_CONTROL__HBR_CHANNEL_COUNT__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x00000070L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x00000700L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x00003800L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0x0000000b
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x00004000L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0x0000000e
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x00008000L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0x0000000f
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x00007f00L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x00000010L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x00000001L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x00800000L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x00000017
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x00000080L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x00000020L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x00000040L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x00000004L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x00000002L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_GTC_EMBEDDING__PRESENTATION_TIME_EMBEDDING_ENABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x00000010L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F0_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_PIN_DEBUG__AZALIA_DEBUG__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY_MASK 0x00700000L
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL_MASK 0x00000003L
+#define AZALIA_F0_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_DEBUG__CODEC_DEBUG_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_DEBUG__CODEC_DEBUG__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ENDPOINT_DATA__AZALIA_ENDPOINT_REG_DATA_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_ENDPOINT_DATA__AZALIA_ENDPOINT_REG_DATA__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_ENDPOINT_INDEX__AZALIA_ENDPOINT_REG_INDEX__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION_MASK 0x0000003fL
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK_MASK 0x00000200L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET_MASK 0x00000400L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET__SHIFT 0x0000000a
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET_MASK 0x00000001L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3_MASK 0xff000000L
+#define AZALIA_F0_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES_MASK 0x3fffffffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP_MASK 0x40000000L
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP__SHIFT 0x0000001e
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS_MASK 0x80000000L
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS__SHIFT 0x0000001f
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR10__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR11__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR12__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR1__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR2__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR3__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR4__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR5__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR6__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR7__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR8__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR9__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__CHANNEL_ALLOCATION_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__CHANNEL_ALLOCATION__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DOWN_MIX_INHIBIT_MASK 0x80000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DOWN_MIX_INHIBIT__SHIFT 0x0000001f
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DP_CONNECTION_MASK 0x00020000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__DP_CONNECTION__SHIFT 0x00000011
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__EXTRA_CONNECTION_INFO_MASK 0x00fc0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__EXTRA_CONNECTION_INFO__SHIFT 0x00000012
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__HDMI_CONNECTION_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__HDMI_CONNECTION__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LEVEL_SHIFT_MASK 0x78000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__LEVEL_SHIFT__SHIFT 0x0000001b
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__SPEAKER_ALLOCATION_MASK 0x0000007fL
+#define AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER__SPEAKER_ALLOCATION__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED_MASK 0x80000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL__AUDIO_ENABLED__SHIFT 0x0000001f
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_ENABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_ENABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_MUTE_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL1_MUTE__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_CHANNEL_ID_MASK 0x0000f000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_CHANNEL_ID__SHIFT 0x0000000c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_ENABLE_MASK 0x00000100L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_ENABLE__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_MUTE_MASK 0x00000200L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL3_MUTE__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_CHANNEL_ID__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_ENABLE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE_MASK 0x00020000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL5_MUTE__SHIFT 0x00000011
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID_MASK 0xf0000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x0000001c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE_MASK 0x01000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_ENABLE__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE_MASK 0x02000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE2__MULTICHANNEL7_MUTE__SHIFT 0x00000019
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_ENABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_ENABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_MUTE_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL01_MUTE__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_CHANNEL_ID_MASK 0x0000f000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_CHANNEL_ID__SHIFT 0x0000000c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_ENABLE_MASK 0x00000100L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_ENABLE__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_MUTE_MASK 0x00000200L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL23_MUTE__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_CHANNEL_ID_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_CHANNEL_ID__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_ENABLE_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_ENABLE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_MUTE_MASK 0x00020000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL45_MUTE__SHIFT 0x00000011
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_CHANNEL_ID_MASK 0xf0000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_CHANNEL_ID__SHIFT 0x0000001c
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_ENABLE_MASK 0x01000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_ENABLE__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_MUTE_MASK 0x02000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_ENABLE__MULTICHANNEL67_MUTE__SHIFT 0x00000019
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0x0000f000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0x0000000c
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0x000f0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0x000000f0L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0x00000f00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x0000001e
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0x0000000fL
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE_MASK 0x00000010L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR__HBR_ENABLE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__AUDIO_LIPSYNC_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__AUDIO_LIPSYNC__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__VIDEO_LIPSYNC_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC__VIDEO_LIPSYNC__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__MANUFACTURER_ID_MASK 0x0000ffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__MANUFACTURER_ID__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__PRODUCT_ID_MASK 0xffff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0__PRODUCT_ID__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1__SINK_DESCRIPTION_LEN_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1__SINK_DESCRIPTION_LEN__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2__PORT_ID0_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2__PORT_ID0__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3__PORT_ID1_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3__PORT_ID1__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION0_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION0__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION1_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION1__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION2_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION2__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION3_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4__DESCRIPTION3__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION4_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION4__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION5_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION5__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION6_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION6__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION7_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5__DESCRIPTION7__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION10_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION10__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION11_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION11__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION8_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION8__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION9_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6__DESCRIPTION9__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION12_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION12__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION13_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION13__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION14_MASK 0x00ff0000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION14__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION15_MASK 0xff000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7__DESCRIPTION15__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION16_MASK 0x000000ffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION16__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION17_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8__DESCRIPTION17__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x00000080L
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE_MASK 0x10000000L
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_FORCE__SHIFT 0x0000001c
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD_MASK 0x03ffffffL
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE_FORCE__UNSOLICITED_RESPONSE_PAYLOAD__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x0000003fL
+#define AZALIA_F0_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE_MASK 0x00000040L
+#define AZALIA_F0_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x00000040L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x00000006
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x01000000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x00000018
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x00010000L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x00000010
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x00000080L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x00000007
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x00000008L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x00000003
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x00000001L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x00000020L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x00000005
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x00000004L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x00000002
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x00000010L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x00000004
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x00000002L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x00000001
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0x0000ff00L
+#define AZALIA_F0_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x00000008
+#define AZALIA_F0_CODEC_RESYNC_FIFO_CONTROL__RESYNC_FIFO_STARTUP_KEEPOUT_WINDOW_MASK 0x0000003fL
+#define AZALIA_F0_CODEC_RESYNC_FIFO_CONTROL__RESYNC_FIFO_STARTUP_KEEPOUT_WINDOW__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID__SHIFT 0x00000000
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID_MASK 0xffffffffL
+#define AZALIA_F0_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE_MASK 0x00000003L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER_MASK 0x0000003cL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER__SHIFT 0x00000002
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_MASK 0x00000003L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN_MASK 0x00000004L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN__SHIFT 0x00000002
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_MASK 0x00000078L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN_MASK 0x00000080L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN__SHIFT 0x00000007
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH__SHIFT 0x00000003
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_MASK 0x0000003fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000040L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000006
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000010L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_MASK 0x00000060L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A__SHIFT 0x00000005
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID_MASK 0x00000080L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID__SHIFT 0x00000007
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO_MASK 0x00000010L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x00000004
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6_MASK 0x0000000fL
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x00000000
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7_MASK 0x000000f0L
+#define AZALIA_F0_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__CHANNEL_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CHANNEL_STREAM_ID__STREAM_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE_MASK 0x00000070L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__BITS_PER_SAMPLE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__NUMBER_OF_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR_MASK 0x00000700L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_DIVISOR__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE_MASK 0x00003800L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_MULTIPLE__SHIFT 0x0000000b
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE_MASK 0x00004000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__SAMPLE_BASE_RATE__SHIFT 0x0000000e
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_MASK 0x00008000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_R_MASK 0x00008000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE_R__SHIFT 0x0000000f
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_CONVERTER_FORMAT__STREAM_TYPE__SHIFT 0x0000000f
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2__CC_MASK 0x0000007fL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_2__CC__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3__KEEPALIVE_MASK 0x00000080L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER_3__KEEPALIVE__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC_MASK 0x00007f00L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__CC__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY_MASK 0x00000010L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__COPY__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN_MASK 0x00000001L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__DIGEN__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE_MASK 0x00800000L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__KEEPALIVE__SHIFT 0x00000017
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L_MASK 0x00000080L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__L__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO_MASK 0x00000020L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__NON_AUDIO__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO_MASK 0x00000040L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__PRO__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG_MASK 0x00000004L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__VCFG__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V_MASK 0x00000002L
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_DIGITAL_CONVERTER__V__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_CONVERTER_CONTROL_RAMP_RATE__RAMP_RATE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE_MASK 0x00000010L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__FORMAT_OVERRIDE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_STREAM_FORMATS__STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F2_CODEC_CONVERTER_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY_MASK 0x00700000L
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CAPABILITY__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL_MASK 0x00000003L
+#define AZALIA_F2_CODEC_CONVERTER_STRIPE_CONTROL__STRIPE_CONTROL__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION_MASK 0x0000003fL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_CONVERTER_SYNCHRONIZATION__CONVERTER_SYNCHRONIZATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK_MASK 0x00000200L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__CLKSTOPOK__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_ACT__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SET__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET_MASK 0x00000400L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_POWER_STATE__POWER_STATE_SETTINGS_RESET__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET_MASK 0x00000001L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESET__CODEC_RESET__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2__SUBSYSTEM_ID_BYTE1_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_2__SUBSYSTEM_ID_BYTE1__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3__SUBSYSTEM_ID_BYTE2_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_3__SUBSYSTEM_ID_BYTE2__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4__SUBSYSTEM_ID_BYTE3_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID_4__SUBSYSTEM_ID_BYTE3__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE0__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE1__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2_MASK 0x00ff0000L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE2__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3_MASK 0xff000000L
+#define AZALIA_F2_CODEC_FUNCTION_CONTROL_RESPONSE_SUBSYSTEM_ID__SUBSYSTEM_ID_BYTE3__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__AZALIA_CODEC_FUNCTION_PARAMETER_GROUP_TYPE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES_MASK 0x3fffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__AZALIA_CODEC_FUNCTION_PARAMETER_POWER_STATES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP_MASK 0x40000000L
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__CLKSTOP__SHIFT 0x0000001e
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS_MASK 0x80000000L
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_POWER_STATES__EPSS__SHIFT 0x0000001f
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__AZALIA_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_FUNCTION_PARAMETER_SUBORDINATE_NODE_COUNT__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES_MASK 0x001f0000L
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_BIT_CAPABILITIES__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES_MASK 0x00000fffL
+#define AZALIA_F2_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES__AUDIO_RATE_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_ASSOCIATION_INFO__ASSOCIATION_INFO__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA__DESCRIPTOR_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR_DATA__DESCRIPTOR__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__DESCRIPTOR_BYTE_2_MASK 0x00ff0000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__DESCRIPTOR_BYTE_2__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__FORMAT_CODE_MASK 0x00000078L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__FORMAT_CODE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__MAX_CHANNELS_MASK 0x00000007L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__MAX_CHANNELS__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_STEREO_MASK 0xff000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR__SUPPORTED_FREQUENCIES_STEREO__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA__SINK_DATA_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_DATA__SINK_DATA__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX__SINK_INFO_INDEX_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_AUDIO_SINK_INFO_INDEX__SINK_INFO_INDEX__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_CHANNEL_ALLOCATION__CHANNEL_ALLOCATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__DOWN_MIX_INHIBIT_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__DOWN_MIX_INHIBIT__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LEVEL_SHIFT_MASK 0x00000078L
+#define AZALIA_F2_CODEC_PIN_CONTROL_DOWN_MIX_INFO__LEVEL_SHIFT__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_CAPABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_ENABLE_MASK 0x00000010L
+#define AZALIA_F2_CODEC_PIN_CONTROL_HBR__HBR_ENABLE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__AUDIO_LIPSYNC_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__AUDIO_LIPSYNC__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__VIDEO_LIPSYNC_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_LIPSYNC__VIDEO_LIPSYNC__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID__MANUFACTURER_ID_MASK 0x0000ffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_MANUFACTURER_ID__MANUFACTURER_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL01_ENABLE__MULTICHANNEL01_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL1_ENABLE__MULTICHANNEL1_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL23_ENABLE__MULTICHANNEL23_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL3_ENABLE__MULTICHANNEL3_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL45_ENABLE__MULTICHANNEL45_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL5_ENABLE__MULTICHANNEL5_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL67_ENABLE__MULTICHANNEL67_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_CHANNEL_ID__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_ENABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL7_ENABLE__MULTICHANNEL7_MUTE__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_CONTROL_MULTICHANNEL_MODE__MULTICHANNEL_MODE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID0__PORTID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID0__PORTID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID1__PORTID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_PORTID1__PORTID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID__PRODUCT_ID_MASK 0x0000ffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_PRODUCT_ID__PRODUCT_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__COLOR__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_2__MISC__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__CONNECTION_TYPE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_3__DEFAULT_DEVICE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION_MASK 0x0000003fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__LOCATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY_MASK 0x000000c0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT_4__PORT_CONNECTIVITY__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR_MASK 0x0000f000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__COLOR__SHIFT 0x0000000c
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE_MASK 0x000f0000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__CONNECTION_TYPE__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION_MASK 0x000000f0L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_ASSOCIATION__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE_MASK 0x00f00000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__DEFAULT_DEVICE__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION_MASK 0x3f000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__LOCATION__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC_MASK 0x00000f00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__MISC__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY_MASK 0xc0000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__PORT_CONNECTIVITY__SHIFT 0x0000001e
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE_MASK 0x0000000fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT__SEQUENCE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY__CONNECTION_LIST_ENTRY_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_CONNECTION_LIST_ENTRY__CONNECTION_LIST_ENTRY__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE_MASK 0x7fffffffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__IMPEDANCE_SENSE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT_MASK 0x80000000L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_PIN_SENSE__PRESENCE_DETECT__SHIFT 0x0000001f
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__DP_CONNECTION_MASK 0x00000200L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__DP_CONNECTION__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__EXTRA_CONNECTION_INFO_MASK 0x0000fc00L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__EXTRA_CONNECTION_INFO__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__HDMI_CONNECTION_MASK 0x00000100L
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__HDMI_CONNECTION__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__SPEAKER_ALLOCATION_MASK 0x0000007fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_RESPONSE_SPEAKER_ALLOCATION__SPEAKER_ALLOCATION__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN__SINK_DESCRIPTION_LEN_MASK 0x000000ffL
+#define AZALIA_F2_CODEC_PIN_CONTROL_SINK_DESCRIPTION_LEN__SINK_DESCRIPTION_LEN__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__ENABLE__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG_MASK 0x0000003fL
+#define AZALIA_F2_CODEC_PIN_CONTROL_UNSOLICITED_RESPONSE__TAG__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE_MASK 0x00000040L
+#define AZALIA_F2_CODEC_PIN_CONTROL_WIDGET_CONTROL__OUT_ENABLE__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AMPLIFIER_PARAMETER_OVERRIDE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_CHANNEL_CAPABILITIES__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY_MASK 0x000f0000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__AUDIO_WIDGET_CAPABILITIES_DELAY__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST_MASK 0x00000100L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__CONNECTION_LIST__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL_MASK 0x00000200L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__DIGITAL__SHIFT 0x00000009
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__INPUT_AMPLIFIER_PRESENT__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP_MASK 0x00000800L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__LR_SWAP__SHIFT 0x0000000b
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT_MASK 0x00000004L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__OUTPUT_AMPLIFIER_PRESENT__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL_MASK 0x00000400L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__POWER_CONTROL__SHIFT 0x0000000a
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET_MASK 0x00000040L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__PROCESSING_WIDGET__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE_MASK 0x00000020L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__STRIPE__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE_MASK 0x00f00000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__TYPE__SHIFT 0x00000014
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_AUDIO_WIDGET_CAPABILITIES__UNSOLICITED_RESPONSE_CAPABILITY__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS_MASK 0x00000040L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__BALANCED_I_O_PINS__SHIFT 0x00000006
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__DP_MASK 0x01000000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__DP__SHIFT 0x00000018
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE_MASK 0x00010000L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__EAPD_CAPABLE__SHIFT 0x00000010
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI_MASK 0x00000080L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HDMI__SHIFT 0x00000007
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE_MASK 0x00000008L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__HEADPHONE_DRIVE_CAPABLE__SHIFT 0x00000003
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE_MASK 0x00000001L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__IMPEDANCE_SENSE_CAPABLE__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE_MASK 0x00000020L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__INPUT_CAPABLE__SHIFT 0x00000005
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY_MASK 0x00000004L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__JACK_DETECTION_CAPABILITY__SHIFT 0x00000002
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE_MASK 0x00000010L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__OUTPUT_CAPABLE__SHIFT 0x00000004
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED_MASK 0x00000002L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__TRIGGER_REQUIRED__SHIFT 0x00000001
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL_MASK 0x0000ff00L
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CAPABILITIES__VREF_CONTROL__SHIFT 0x00000008
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH__CONNECTION_LIST_LENGTH_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_PIN_PARAMETER_CONNECTION_LIST_LENGTH__CONNECTION_LIST_LENGTH__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_REVISION_ID__AZALIA_CODEC_ROOT_PARAMETER_REVISION_ID__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__AZALIA_CODEC_ROOT_PARAMETER_SUBORDINATE_NODE_COUNT__SHIFT 0x00000000
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID_MASK 0xffffffffL
+#define AZALIA_F2_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__AZALIA_CODEC_ROOT_PARAMETER_VENDOR_AND_DEVICE_ID__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE_MASK 0x00000003L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_MODE__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER_MASK 0x0000003cL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_0__IEC_60958_CS_SOURCE_NUMBER__SHIFT 0x00000002
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_MASK 0x00000003L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN_MASK 0x00000004L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY_OVRRD_EN__SHIFT 0x00000002
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_CLOCK_ACCURACY__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_MASK 0x00000078L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN_MASK 0x00000080L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH_OVRRD_EN__SHIFT 0x00000007
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_1__IEC_60958_CS_WORD_LENGTH__SHIFT 0x00000003
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_MASK 0x0000003fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000040L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000006
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_2__IEC_60958_CS_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN_MASK 0x00000010L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY_OVRRD_EN__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_3__IEC_60958_CS_ORIGINAL_SAMPLING_FREQUENCY__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_MASK 0x00000060L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A__SHIFT 0x00000005
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID_MASK 0x00000080L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_CGMS_A_VALID__SHIFT 0x00000007
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO_MASK 0x00000010L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_MPEG_SURROUND_INFO__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_4__IEC_60958_CS_SAMPLING_FREQUENCY_COEFF__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_L__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_5__IEC_60958_CS_CHANNEL_NUMBER_R__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_2__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_6__IEC_60958_CS_CHANNEL_NUMBER_3__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_4__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_7__IEC_60958_CS_CHANNEL_NUMBER_5__SHIFT 0x00000004
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6_MASK 0x0000000fL
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_6__SHIFT 0x00000000
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7_MASK 0x000000f0L
+#define AZALIA_F2_PIN_CONTROL_CODEC_CS_OVERRIDE_8__IEC_60958_CS_CHANNEL_NUMBER_7__SHIFT 0x00000004
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_FIFO_SIZE_MASK 0x00007f00L
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_FIFO_SIZE__SHIFT 0x00000008
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_LATENCY_SUPPORT_MASK 0x00ff0000L
+#define AZALIA_FIFO_SIZE_CONTROL__MAX_LATENCY_SUPPORT__SHIFT 0x00000010
+#define AZALIA_FIFO_SIZE_CONTROL__MIN_FIFO_SIZE_MASK 0x0000007fL
+#define AZALIA_FIFO_SIZE_CONTROL__MIN_FIFO_SIZE__SHIFT 0x00000000
+#define AZALIA_GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS_MASK 0x00000006L
+#define AZALIA_GLOBAL_CAPABILITIES__NUMBER_OF_SERIAL_DATA_OUTPUT_SIGNALS__SHIFT 0x00000001
+#define AZALIA_LATENCY_COUNTER_CONTROL__AZALIA_LATENCY_COUNTER_RESET_MASK 0x00000001L
+#define AZALIA_LATENCY_COUNTER_CONTROL__AZALIA_LATENCY_COUNTER_RESET__SHIFT 0x00000000
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY_MASK 0x0000ffffL
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTPUT_PAYLOAD_CAPABILITY__SHIFT 0x00000000
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTSTRMPAY_MASK 0xffff0000L
+#define AZALIA_OUTPUT_PAYLOAD_CAPABILITY__OUTSTRMPAY__SHIFT 0x00000010
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__LATENCY_HIDING_LEVEL_MASK 0x000000ffL
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__LATENCY_HIDING_LEVEL__SHIFT 0x00000000
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__SYS_MEM_ACTIVE_ENABLE_MASK 0x00000100L
+#define AZALIA_OUTPUT_STREAM_ARBITER_CONTROL__SYS_MEM_ACTIVE_ENABLE__SHIFT 0x00000008
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_DMA_NON_SNOOP_MASK 0x00000010L
+#define AZALIA_RIRB_AND_DP_CONTROL__DP_DMA_NON_SNOOP__SHIFT 0x00000004
+#define AZALIA_RIRB_AND_DP_CONTROL__RIRB_NON_SNOOP_MASK 0x00000001L
+#define AZALIA_RIRB_AND_DP_CONTROL__RIRB_NON_SNOOP__SHIFT 0x00000000
+#define AZALIA_SCLK_CONTROL__AUDIO_SCLK_CONTROL_MASK 0x00000030L
+#define AZALIA_SCLK_CONTROL__AUDIO_SCLK_CONTROL__SHIFT 0x00000004
+#define AZALIA_STREAM_DATA__AZALIA_STREAM_REG_DATA_MASK 0xffffffffL
+#define AZALIA_STREAM_DATA__AZALIA_STREAM_REG_DATA__SHIFT 0x00000000
+#define AZALIA_STREAM_DEBUG__STREAM_DEBUG_DATA_MASK 0xffffffffL
+#define AZALIA_STREAM_DEBUG__STREAM_DEBUG_DATA__SHIFT 0x00000000
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_INDEX_MASK 0x000000ffL
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_INDEX__SHIFT 0x00000000
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_WRITE_EN_MASK 0x00000100L
+#define AZALIA_STREAM_INDEX__AZALIA_STREAM_REG_WRITE_EN__SHIFT 0x00000008
+#define AZALIA_UNDERFLOW_FILLER_SAMPLE__AZALIA_UNDERFLOW_FILLER_SAMPLE_MASK 0xffffffffL
+#define AZALIA_UNDERFLOW_FILLER_SAMPLE__AZALIA_UNDERFLOW_FILLER_SAMPLE__SHIFT 0x00000000
+#define AZALIA_WORSTCASE_LATENCY_COUNT__AZALIA_WORSTCASE_LATENCY_COUNT_MASK 0xffffffffL
+#define AZALIA_WORSTCASE_LATENCY_COUNT__AZALIA_WORSTCASE_LATENCY_COUNT__SHIFT 0x00000000
+#define AZ_TEST_DEBUG_DATA__AZ_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define AZ_TEST_DEBUG_DATA__AZ_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define AZ_TEST_DEBUG_INDEX__AZ_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_CALC_FINAL_DUTY_CYCLE_EN_MASK 0x00000008L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_CALC_FINAL_DUTY_CYCLE_EN__SHIFT 0x00000003
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_LEVEL_EN_MASK 0x00000004L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_LEVEL_EN__SHIFT 0x00000002
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_STEP_SIZE_MASK 0xffff0000L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_AUTO_UPDATE_CURRENT_ABM_STEP_SIZE__SHIFT 0x00000010
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_ABM_EN_MASK 0x00000001L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_ABM_EN__SHIFT 0x00000000
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_AMBIENT_LEVEL_EN_MASK 0x00000002L
+#define BL1_PWM_ABM_CNTL__BL1_PWM_USE_AMBIENT_LEVEL_EN__SHIFT 0x00000001
+#define BL1_PWM_AMBIENT_LIGHT_LEVEL__BL1_PWM_AMBIENT_LIGHT_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_AMBIENT_LIGHT_LEVEL__BL1_PWM_AMBIENT_LIGHT_LEVEL__SHIFT 0x00000000
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0x00ff0000L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x00000010
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x00000002L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x00000001
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_COUNT_EN_MASK 0x00000001L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_COUNT_EN__SHIFT 0x00000000
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_FRAME_COUNT_MASK 0x0000ff00L
+#define BL1_PWM_BL_UPDATE_SAMPLE_RATE__BL1_PWM_BL_UPDATE_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x00000008
+#define BL1_PWM_CURRENT_ABM_LEVEL__BL1_PWM_CURRENT_ABM_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_CURRENT_ABM_LEVEL__BL1_PWM_CURRENT_ABM_LEVEL__SHIFT 0x00000000
+#define BL1_PWM_FINAL_DUTY_CYCLE__BL1_PWM_FINAL_DUTY_CYCLE_MASK 0x0001ffffL
+#define BL1_PWM_FINAL_DUTY_CYCLE__BL1_PWM_FINAL_DUTY_CYCLE__SHIFT 0x00000000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_FRAME_START_DISP_SEL_MASK 0x000e0000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_FRAME_START_DISP_SEL__SHIFT 0x00000011
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_IGNORE_MASTER_LOCK_EN_MASK 0x80000000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001f
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_READBACK_DB_REG_VALUE_EN_MASK 0x01000000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_READBACK_DB_REG_VALUE_EN__SHIFT 0x00000018
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_LOCK_MASK 0x00000001L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_LOCK__SHIFT 0x00000000
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_UPDATE_PENDING_MASK 0x00000100L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_REG_UPDATE_PENDING__SHIFT 0x00000008
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_UPDATE_AT_FRAME_START_MASK 0x00010000L
+#define BL1_PWM_GRP2_REG_LOCK__BL1_PWM_GRP2_UPDATE_AT_FRAME_START__SHIFT 0x00000010
+#define BL1_PWM_MINIMUM_DUTY_CYCLE__BL1_PWM_MINIMUM_DUTY_CYCLE_MASK 0x0001ffffL
+#define BL1_PWM_MINIMUM_DUTY_CYCLE__BL1_PWM_MINIMUM_DUTY_CYCLE__SHIFT 0x00000000
+#define BL1_PWM_TARGET_ABM_LEVEL__BL1_PWM_TARGET_ABM_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_TARGET_ABM_LEVEL__BL1_PWM_TARGET_ABM_LEVEL__SHIFT 0x00000000
+#define BL1_PWM_USER_LEVEL__BL1_PWM_USER_LEVEL_MASK 0x0001ffffL
+#define BL1_PWM_USER_LEVEL__BL1_PWM_USER_LEVEL__SHIFT 0x00000000
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_BL_OUT_ENABLE_MASK 0x40000000L
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_BL_OUT_ENABLE__SHIFT 0x0000001e
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN_MASK 0x80000000L
+#define BL_PWM_CNTL2__BL_PWM_OVERRIDE_LVTMA_PWRSEQ_EN__SHIFT 0x0000001f
+#define BL_PWM_CNTL2__BL_PWM_POST_FRAME_START_DELAY_BEFORE_UPDATE_MASK 0x0000ffffL
+#define BL_PWM_CNTL2__BL_PWM_POST_FRAME_START_DELAY_BEFORE_UPDATE__SHIFT 0x00000000
+#define BL_PWM_CNTL2__DBG_BL_PWM_INPUT_REFCLK_SELECT_MASK 0x30000000L
+#define BL_PWM_CNTL2__DBG_BL_PWM_INPUT_REFCLK_SELECT__SHIFT 0x0000001c
+#define BL_PWM_CNTL__BL_ACTIVE_INT_FRAC_CNT_MASK 0x0000ffffL
+#define BL_PWM_CNTL__BL_ACTIVE_INT_FRAC_CNT__SHIFT 0x00000000
+#define BL_PWM_CNTL__BL_PWM_EN_MASK 0x80000000L
+#define BL_PWM_CNTL__BL_PWM_EN__SHIFT 0x0000001f
+#define BL_PWM_CNTL__BL_PWM_FRACTIONAL_EN_MASK 0x40000000L
+#define BL_PWM_CNTL__BL_PWM_FRACTIONAL_EN__SHIFT 0x0000001e
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_FRAME_START_DISP_SEL_MASK 0x000e0000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_FRAME_START_DISP_SEL__SHIFT 0x00000011
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN_MASK 0x80000000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001f
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN_MASK 0x01000000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_READBACK_DB_REG_VALUE_EN__SHIFT 0x00000018
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_LOCK_MASK 0x00000001L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_LOCK__SHIFT 0x00000000
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_UPDATE_PENDING_MASK 0x00000100L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_REG_UPDATE_PENDING__SHIFT 0x00000008
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_UPDATE_AT_FRAME_START_MASK 0x00010000L
+#define BL_PWM_GRP1_REG_LOCK__BL_PWM_GRP1_UPDATE_AT_FRAME_START__SHIFT 0x00000010
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_BITCNT_MASK 0x000f0000L
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_BITCNT__SHIFT 0x00000010
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD_MASK 0x0000ffffL
+#define BL_PWM_PERIOD_CNTL__BL_PWM_PERIOD__SHIFT 0x00000000
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_COMPLETE_MASK 0x10000000L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_COMPLETE__SHIFT 0x0000001c
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_DACADJ_EN_MASK 0x00000004L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_DACADJ_EN__SHIFT 0x00000002
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_EN_MASK 0x00000002L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_EN__SHIFT 0x00000001
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_INITB_MASK 0x00000001L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_INITB__SHIFT 0x00000000
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_MASK_MASK 0x00700000L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_MASK__SHIFT 0x00000014
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_WAIT_ADJUST_MASK 0x00003ff0L
+#define BPHYC_DAC_AUTO_CALIB_CONTROL__BPHYC_DAC_CAL_WAIT_ADJUST__SHIFT 0x00000004
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_ANALOG_MONITOR_MASK 0x0f000000L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_ANALOG_MONITOR__SHIFT 0x00000018
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_BANDGAP_ADJUSTMENT_MASK 0x003f0000L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_BANDGAP_ADJUSTMENT__SHIFT 0x00000010
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_COREMON_MASK 0x10000000L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_COREMON__SHIFT 0x0000001c
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_FINE_CONTROL_MASK 0x00003f00L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_FINE_CONTROL__SHIFT 0x00000008
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_LEVEL_MASK 0x00000003L
+#define BPHYC_DAC_MACRO_CNTL__BPHYC_DAC_WHITE_LEVEL__SHIFT 0x00000000
+#define CC_DC_PIPE_DIS__DC_PIPE_DIS_MASK 0x0000007eL
+#define CC_DC_PIPE_DIS__DC_PIPE_DIS__SHIFT 0x00000001
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_MASK 0x00000007L
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_OVERRIDE_ENABLE_MASK 0x00000010L
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY_OVERRIDE_ENABLE__SHIFT 0x00000004
+#define CC_RCU_DC_AUDIO_PORT_CONNECTIVITY__PORT_CONNECTIVITY__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C11_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C11__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C12_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C11_C12__COMM_MATRIXA_TRANS_C12__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C13_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C13__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C14_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C13_C14__COMM_MATRIXA_TRANS_C14__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C21_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C21__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C22_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C21_C22__COMM_MATRIXA_TRANS_C22__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C23_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C23__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C24_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C23_C24__COMM_MATRIXA_TRANS_C24__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C31_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C31__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C32_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C31_C32__COMM_MATRIXA_TRANS_C32__SHIFT 0x00000010
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C33_MASK 0x0000ffffL
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C33__SHIFT 0x00000000
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C34_MASK 0xffff0000L
+#define COMM_MATRIXA_TRANS_C33_C34__COMM_MATRIXA_TRANS_C34__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C11_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C11__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C12_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C11_C12__COMM_MATRIXB_TRANS_C12__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C13_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C13__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C14_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C13_C14__COMM_MATRIXB_TRANS_C14__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C21_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C21__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C22_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C21_C22__COMM_MATRIXB_TRANS_C22__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C23_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C23__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C24_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C23_C24__COMM_MATRIXB_TRANS_C24__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C31_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C31__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C32_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C31_C32__COMM_MATRIXB_TRANS_C32__SHIFT 0x00000010
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C33_MASK 0x0000ffffL
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C33__SHIFT 0x00000000
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C34_MASK 0xffff0000L
+#define COMM_MATRIXB_TRANS_C33_C34__COMM_MATRIXB_TRANS_C34__SHIFT 0x00000010
+#define CRT00__H_TOTAL_MASK 0x000000ffL
+#define CRT00__H_TOTAL__SHIFT 0x00000000
+#define CRT01__H_DISP_END_MASK 0x000000ffL
+#define CRT01__H_DISP_END__SHIFT 0x00000000
+#define CRT02__H_BLANK_START_MASK 0x000000ffL
+#define CRT02__H_BLANK_START__SHIFT 0x00000000
+#define CRT03__CR10CR11_R_DIS_B_MASK 0x00000080L
+#define CRT03__CR10CR11_R_DIS_B__SHIFT 0x00000007
+#define CRT03__H_BLANK_END_MASK 0x0000001fL
+#define CRT03__H_BLANK_END__SHIFT 0x00000000
+#define CRT03__H_DE_SKEW_MASK 0x00000060L
+#define CRT03__H_DE_SKEW__SHIFT 0x00000005
+#define CRT04__H_SYNC_START_MASK 0x000000ffL
+#define CRT04__H_SYNC_START__SHIFT 0x00000000
+#define CRT05__H_BLANK_END_B5_MASK 0x00000080L
+#define CRT05__H_BLANK_END_B5__SHIFT 0x00000007
+#define CRT05__H_SYNC_END_MASK 0x0000001fL
+#define CRT05__H_SYNC_END__SHIFT 0x00000000
+#define CRT05__H_SYNC_SKEW_MASK 0x00000060L
+#define CRT05__H_SYNC_SKEW__SHIFT 0x00000005
+#define CRT06__V_TOTAL_MASK 0x000000ffL
+#define CRT06__V_TOTAL__SHIFT 0x00000000
+#define CRT07__LINE_CMP_B8_MASK 0x00000010L
+#define CRT07__LINE_CMP_B8__SHIFT 0x00000004
+#define CRT07__V_BLANK_START_B8_MASK 0x00000008L
+#define CRT07__V_BLANK_START_B8__SHIFT 0x00000003
+#define CRT07__V_DISP_END_B8_MASK 0x00000002L
+#define CRT07__V_DISP_END_B8__SHIFT 0x00000001
+#define CRT07__V_DISP_END_B9_MASK 0x00000040L
+#define CRT07__V_DISP_END_B9__SHIFT 0x00000006
+#define CRT07__V_SYNC_START_B8_MASK 0x00000004L
+#define CRT07__V_SYNC_START_B8__SHIFT 0x00000002
+#define CRT07__V_SYNC_START_B9_MASK 0x00000080L
+#define CRT07__V_SYNC_START_B9__SHIFT 0x00000007
+#define CRT07__V_TOTAL_B8_MASK 0x00000001L
+#define CRT07__V_TOTAL_B8__SHIFT 0x00000000
+#define CRT07__V_TOTAL_B9_MASK 0x00000020L
+#define CRT07__V_TOTAL_B9__SHIFT 0x00000005
+#define CRT08__BYTE_PAN_MASK 0x00000060L
+#define CRT08__BYTE_PAN__SHIFT 0x00000005
+#define CRT08__ROW_SCAN_START_MASK 0x0000001fL
+#define CRT08__ROW_SCAN_START__SHIFT 0x00000000
+#define CRT09__DOUBLE_CHAR_HEIGHT_MASK 0x00000080L
+#define CRT09__DOUBLE_CHAR_HEIGHT__SHIFT 0x00000007
+#define CRT09__LINE_CMP_B9_MASK 0x00000040L
+#define CRT09__LINE_CMP_B9__SHIFT 0x00000006
+#define CRT09__MAX_ROW_SCAN_MASK 0x0000001fL
+#define CRT09__MAX_ROW_SCAN__SHIFT 0x00000000
+#define CRT09__V_BLANK_START_B9_MASK 0x00000020L
+#define CRT09__V_BLANK_START_B9__SHIFT 0x00000005
+#define CRT0A__CURSOR_DISABLE_MASK 0x00000020L
+#define CRT0A__CURSOR_DISABLE__SHIFT 0x00000005
+#define CRT0A__CURSOR_START_MASK 0x0000001fL
+#define CRT0A__CURSOR_START__SHIFT 0x00000000
+#define CRT0B__CURSOR_END_MASK 0x0000001fL
+#define CRT0B__CURSOR_END__SHIFT 0x00000000
+#define CRT0B__CURSOR_SKEW_MASK 0x00000060L
+#define CRT0B__CURSOR_SKEW__SHIFT 0x00000005
+#define CRT0C__DISP_START_MASK 0x000000ffL
+#define CRT0C__DISP_START__SHIFT 0x00000000
+#define CRT0D__DISP_START_MASK 0x000000ffL
+#define CRT0D__DISP_START__SHIFT 0x00000000
+#define CRT0E__CURSOR_LOC_HI_MASK 0x000000ffL
+#define CRT0E__CURSOR_LOC_HI__SHIFT 0x00000000
+#define CRT0F__CURSOR_LOC_LO_MASK 0x000000ffL
+#define CRT0F__CURSOR_LOC_LO__SHIFT 0x00000000
+#define CRT10__V_SYNC_START_MASK 0x000000ffL
+#define CRT10__V_SYNC_START__SHIFT 0x00000000
+#define CRT11__C0T7_WR_ONLY_MASK 0x00000080L
+#define CRT11__C0T7_WR_ONLY__SHIFT 0x00000007
+#define CRT11__SEL5_REFRESH_CYC_MASK 0x00000040L
+#define CRT11__SEL5_REFRESH_CYC__SHIFT 0x00000006
+#define CRT11__V_INTR_CLR_MASK 0x00000010L
+#define CRT11__V_INTR_CLR__SHIFT 0x00000004
+#define CRT11__V_INTR_EN_MASK 0x00000020L
+#define CRT11__V_INTR_EN__SHIFT 0x00000005
+#define CRT11__V_SYNC_END_MASK 0x0000000fL
+#define CRT11__V_SYNC_END__SHIFT 0x00000000
+#define CRT12__V_DISP_END_MASK 0x000000ffL
+#define CRT12__V_DISP_END__SHIFT 0x00000000
+#define CRT13__DISP_PITCH_MASK 0x000000ffL
+#define CRT13__DISP_PITCH__SHIFT 0x00000000
+#define CRT14__ADDR_CNT_BY4_MASK 0x00000020L
+#define CRT14__ADDR_CNT_BY4__SHIFT 0x00000005
+#define CRT14__DOUBLE_WORD_MASK 0x00000040L
+#define CRT14__DOUBLE_WORD__SHIFT 0x00000006
+#define CRT14__UNDRLN_LOC_MASK 0x0000001fL
+#define CRT14__UNDRLN_LOC__SHIFT 0x00000000
+#define CRT15__V_BLANK_START_MASK 0x000000ffL
+#define CRT15__V_BLANK_START__SHIFT 0x00000000
+#define CRT16__V_BLANK_END_MASK 0x000000ffL
+#define CRT16__V_BLANK_END__SHIFT 0x00000000
+#define CRT17__ADDR_CNT_BY2_MASK 0x00000008L
+#define CRT17__ADDR_CNT_BY2__SHIFT 0x00000003
+#define CRT17__BYTE_MODE_MASK 0x00000040L
+#define CRT17__BYTE_MODE__SHIFT 0x00000006
+#define CRT17__CRTC_SYNC_EN_MASK 0x00000080L
+#define CRT17__CRTC_SYNC_EN__SHIFT 0x00000007
+#define CRT17__RA0_AS_A13B_MASK 0x00000001L
+#define CRT17__RA0_AS_A13B__SHIFT 0x00000000
+#define CRT17__RA1_AS_A14B_MASK 0x00000002L
+#define CRT17__RA1_AS_A14B__SHIFT 0x00000001
+#define CRT17__VCOUNT_BY2_MASK 0x00000004L
+#define CRT17__VCOUNT_BY2__SHIFT 0x00000002
+#define CRT17__WRAP_A15TOA0_MASK 0x00000020L
+#define CRT17__WRAP_A15TOA0__SHIFT 0x00000005
+#define CRT18__LINE_CMP_MASK 0x000000ffL
+#define CRT18__LINE_CMP__SHIFT 0x00000000
+#define CRT1E__GRPH_DEC_RD1_MASK 0x00000002L
+#define CRT1E__GRPH_DEC_RD1__SHIFT 0x00000001
+#define CRT1F__GRPH_DEC_RD0_MASK 0x000000ffL
+#define CRT1F__GRPH_DEC_RD0__SHIFT 0x00000000
+#define CRT22__GRPH_LATCH_DATA_MASK 0x000000ffL
+#define CRT22__GRPH_LATCH_DATA__SHIFT 0x00000000
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_ADD_PIXEL_MASK 0x00000100L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DROP_PIXEL_MASK 0x00000200L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC0_PIXEL_RATE_CNTL__CRTC0_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_ENABLE_MASK 0x00000010L
+#define CRTC0_PIXEL_RATE_CNTL__DP_DTO0_ENABLE__SHIFT 0x00000004
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_ADD_PIXEL_MASK 0x00000100L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DROP_PIXEL_MASK 0x00000200L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC1_PIXEL_RATE_CNTL__CRTC1_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_ENABLE_MASK 0x00000010L
+#define CRTC1_PIXEL_RATE_CNTL__DP_DTO1_ENABLE__SHIFT 0x00000004
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_ADD_PIXEL_MASK 0x00000100L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DROP_PIXEL_MASK 0x00000200L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC2_PIXEL_RATE_CNTL__CRTC2_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_ENABLE_MASK 0x00000010L
+#define CRTC2_PIXEL_RATE_CNTL__DP_DTO2_ENABLE__SHIFT 0x00000004
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_DB_MASK 0x00000010L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_DB__SHIFT 0x00000004
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN_MASK 0x00000001L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_EN__SHIFT 0x00000000
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_MASK 0x000c0000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_MASK 0x00010000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_PENDING_MASK 0x00020000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET_PENDING__SHIFT 0x00000011
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT_RESET__SHIFT 0x00000010
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_F_COUNT__SHIFT 0x00000012
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_STEREO_SEL_OVR_MASK 0x00001000L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_STEREO_SEL_OVR__SHIFT 0x0000000c
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_V_UPDATE_MODE_MASK 0x00000300L
+#define CRTC_3D_STRUCTURE_CONTROL__CRTC_3D_STRUCTURE_V_UPDATE_MODE__SHIFT 0x00000008
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_ADD_PIXEL_MASK 0x00000100L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DROP_PIXEL_MASK 0x00000200L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC3_PIXEL_RATE_CNTL__CRTC3_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_ENABLE_MASK 0x00000010L
+#define CRTC3_PIXEL_RATE_CNTL__DP_DTO3_ENABLE__SHIFT 0x00000004
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_ADD_PIXEL_MASK 0x00000100L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DROP_PIXEL_MASK 0x00000200L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC4_PIXEL_RATE_CNTL__CRTC4_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_ENABLE_MASK 0x00000010L
+#define CRTC4_PIXEL_RATE_CNTL__DP_DTO4_ENABLE__SHIFT 0x00000004
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_ADD_PIXEL_MASK 0x00000100L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_ADD_PIXEL__SHIFT 0x00000008
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_ERROR_COUNT_MASK 0x0fff0000L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_ERROR_COUNT__SHIFT 0x00000010
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_FIFO_ERROR_MASK 0x0000c000L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DISPOUT_FIFO_ERROR__SHIFT 0x0000000e
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DROP_PIXEL_MASK 0x00000200L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_DROP_PIXEL__SHIFT 0x00000009
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_SOURCE_MASK 0x00000003L
+#define CRTC5_PIXEL_RATE_CNTL__CRTC5_PIXEL_RATE_SOURCE__SHIFT 0x00000000
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_ENABLE_MASK 0x00000010L
+#define CRTC5_PIXEL_RATE_CNTL__DP_DTO5_ENABLE__SHIFT 0x00000004
+#define CRTC8_DATA__VCRTC_DATA_MASK 0x000000ffL
+#define CRTC8_DATA__VCRTC_DATA__SHIFT 0x00000000
+#define CRTC8_IDX__VCRTC_IDX_MASK 0x0000003fL
+#define CRTC8_IDX__VCRTC_IDX__SHIFT 0x00000000
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_ALLOW_STOP_OFF_V_CNT_MASK 0x000000ffL
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_ALLOW_STOP_OFF_V_CNT__SHIFT 0x00000000
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_DISABLE_ALLOW_STOP_OFF_V_CNT_MASK 0x00010000L
+#define CRTC_ALLOW_STOP_OFF_V_CNT__CRTC_DISABLE_ALLOW_STOP_OFF_V_CNT__SHIFT 0x00000010
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB_MASK 0x000003ffL
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_B_CB__SHIFT 0x00000000
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y_MASK 0x000ffc00L
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_G_Y__SHIFT 0x0000000a
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR_MASK 0x3ff00000L
+#define CRTC_BLACK_COLOR__CRTC_BLACK_COLOR_R_CR__SHIFT 0x00000014
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN_MASK 0x00000100L
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DATA_EN__SHIFT 0x00000008
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DE_MODE_MASK 0x00010000L
+#define CRTC_BLANK_CONTROL__CRTC_BLANK_DE_MODE__SHIFT 0x00000010
+#define CRTC_BLANK_CONTROL__CRTC_CURRENT_BLANK_STATE_MASK 0x00000001L
+#define CRTC_BLANK_CONTROL__CRTC_CURRENT_BLANK_STATE__SHIFT 0x00000000
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_BLUE_CB_MASK 0x000003ffL
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_BLUE_CB__SHIFT 0x00000000
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_GREEN_Y_MASK 0x000ffc00L
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_GREEN_Y__SHIFT 0x0000000a
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_RED_CR_MASK 0x3ff00000L
+#define CRTC_BLANK_DATA_COLOR__CRTC_BLANK_DATA_COLOR_RED_CR__SHIFT 0x00000014
+#define CRTC_CONTROL__CRTC_CURRENT_MASTER_EN_STATE_MASK 0x00010000L
+#define CRTC_CONTROL__CRTC_CURRENT_MASTER_EN_STATE__SHIFT 0x00000010
+#define CRTC_CONTROL__CRTC_DISABLE_POINT_CNTL_MASK 0x00000300L
+#define CRTC_CONTROL__CRTC_DISABLE_POINT_CNTL__SHIFT 0x00000008
+#define CRTC_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE_MASK 0x01000000L
+#define CRTC_CONTROL__CRTC_DISP_READ_REQUEST_DISABLE__SHIFT 0x00000018
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_CNTL_MASK 0x00002000L
+#define CRTC_CONTROL__CRTC_FIELD_NUMBER_CNTL__SHIFT 0x0000000d
+#define CRTC_CONTROL__CRTC_HBLANK_EARLY_CONTROL_MASK 0x00700000L
+#define CRTC_CONTROL__CRTC_HBLANK_EARLY_CONTROL__SHIFT 0x00000014
+#define CRTC_CONTROL__CRTC_MASTER_EN_MASK 0x00000001L
+#define CRTC_CONTROL__CRTC_MASTER_EN__SHIFT 0x00000000
+#define CRTC_CONTROL__CRTC_SOF_PULL_EN_MASK 0x20000000L
+#define CRTC_CONTROL__CRTC_SOF_PULL_EN__SHIFT 0x0000001d
+#define CRTC_CONTROL__CRTC_START_POINT_CNTL_MASK 0x00001000L
+#define CRTC_CONTROL__CRTC_START_POINT_CNTL__SHIFT 0x0000000c
+#define CRTC_CONTROL__CRTC_SYNC_RESET_SEL_MASK 0x00000010L
+#define CRTC_CONTROL__CRTC_SYNC_RESET_SEL__SHIFT 0x00000004
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN_MASK 0x00000001L
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_COUNT_BY2_EN__SHIFT 0x00000000
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_REPETITION_COUNT_MASK 0x0000001eL
+#define CRTC_COUNT_CONTROL__CRTC_HORZ_REPETITION_COUNT__SHIFT 0x00000001
+#define CRTC_COUNT_RESET__CRTC_RESET_FRAME_COUNT_MASK 0x00000001L
+#define CRTC_COUNT_RESET__CRTC_RESET_FRAME_COUNT__SHIFT 0x00000000
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE_MASK 0x80000000L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE__SHIFT 0x0000001f
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_TEST_CLK_SEL_MASK 0x1f000000L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_TEST_CLK_SEL__SHIFT 0x00000018
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_DCP_GATE_DISABLE_MASK 0x00000100L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_DCP_GATE_DISABLE__SHIFT 0x00000008
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_SCL_GATE_DISABLE_MASK 0x00001000L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_G_SCL_GATE_DISABLE__SHIFT 0x0000000c
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_R_DCFE_GATE_DISABLE_MASK 0x00000010L
+#define CRTC_DCFE_CLOCK_CONTROL__CRTC_DISPCLK_R_DCFE_GATE_DISABLE__SHIFT 0x00000004
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_BLANK_DATA_DOUBLE_BUFFER_EN_MASK 0x00010000L
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_BLANK_DATA_DOUBLE_BUFFER_EN__SHIFT 0x00000010
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_INSTANTLY_MASK 0x00000100L
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_INSTANTLY__SHIFT 0x00000008
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_PENDING_MASK 0x00000001L
+#define CRTC_DOUBLE_BUFFER_CONTROL__CRTC_UPDATE_PENDING__SHIFT 0x00000000
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CLK_DIV_MASK 0x0000001eL
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CLK_DIV__SHIFT 0x00000001
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CRTC_EN_MASK 0x00000001L
+#define CRTC_DTMTEST_CNTL__CRTC_DTMTEST_CRTC_EN__SHIFT 0x00000000
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_HORZ_COUNT_MASK 0x1fff0000L
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_HORZ_COUNT__SHIFT 0x00000010
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_VERT_COUNT_MASK 0x00001fffL
+#define CRTC_DTMTEST_STATUS_POSITION__CRTC_DTMTEST_VERT_COUNT__SHIFT 0x00000000
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_GRANULARITY_MASK 0x00010000L
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_GRANULARITY__SHIFT 0x00000010
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_INPUT_STATUS_MASK 0x01000000L
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_INPUT_STATUS__SHIFT 0x00000018
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_POLARITY_MASK 0x00000100L
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_POLARITY__SHIFT 0x00000008
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_SOURCE_SELECT_MASK 0x0000001fL
+#define CRTC_FLOW_CONTROL__CRTC_FLOW_CONTROL_SOURCE_SELECT__SHIFT 0x00000000
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CHECK_MASK 0x00000010L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CHECK__SHIFT 0x00000004
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CLEAR_MASK 0x01000000L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_CLEAR__SHIFT 0x00000018
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_MODE_MASK 0x00000003L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_MODE__SHIFT 0x00000000
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_OCCURRED_MASK 0x00010000L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_OCCURRED__SHIFT 0x00000010
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_TRIG_SEL_MASK 0x00000100L
+#define CRTC_FORCE_COUNT_NOW_CNTL__CRTC_FORCE_COUNT_NOW_TRIG_SEL__SHIFT 0x00000008
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_ALL_FIELDS_MASK 0x10000000L
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_ALL_FIELDS__SHIFT 0x0000001c
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_LINE_NUM_MASK 0x00001fffL
+#define CRTC_GSL_CONTROL__CRTC_GSL_CHECK_LINE_NUM__SHIFT 0x00000000
+#define CRTC_GSL_CONTROL__CRTC_GSL_FORCE_DELAY_MASK 0x001f0000L
+#define CRTC_GSL_CONTROL__CRTC_GSL_FORCE_DELAY__SHIFT 0x00000010
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_CLEAR_MASK 0x00080000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_CLEAR__SHIFT 0x00000013
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_DELAY_MASK 0x0000ff00L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_DELAY__SHIFT 0x00000008
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_LIMIT_MASK 0x000000ffL
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_LIMIT__SHIFT 0x00000000
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASK 0xff000000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASTER_FASTER_MASK 0x00800000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MASTER_FASTER__SHIFT 0x00000017
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MODE_MASK 0x00060000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_MODE__SHIFT 0x00000011
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_OCCURRED_MASK 0x00100000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_OCCURRED__SHIFT 0x00000014
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP__SHIFT 0x00000018
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_SOURCE_SEL_MASK 0x00010000L
+#define CRTC_GSL_VSYNC_GAP__CRTC_GSL_VSYNC_GAP_SOURCE_SEL__SHIFT 0x00000010
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_END_MASK 0x1fff0000L
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_END__SHIFT 0x00000010
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_START_MASK 0x00001fffL
+#define CRTC_GSL_WINDOW__CRTC_GSL_WINDOW_START__SHIFT 0x00000000
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_DIS_MASK 0x00010000L
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_DIS__SHIFT 0x00000010
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM_MASK 0x000003ffL
+#define CRTC_H_BLANK_EARLY_NUM__CRTC_H_BLANK_EARLY_NUM__SHIFT 0x00000000
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_END_MASK 0x1fff0000L
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_END__SHIFT 0x00000010
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_START_MASK 0x00001fffL
+#define CRTC_H_BLANK_START_END__CRTC_H_BLANK_START__SHIFT 0x00000000
+#define CRTC_H_SYNC_A_CNTL__CRTC_COMP_SYNC_A_EN_MASK 0x00010000L
+#define CRTC_H_SYNC_A_CNTL__CRTC_COMP_SYNC_A_EN__SHIFT 0x00000010
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_CUTOFF_MASK 0x00020000L
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_CUTOFF__SHIFT 0x00000011
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_POL_MASK 0x00000001L
+#define CRTC_H_SYNC_A_CNTL__CRTC_H_SYNC_A_POL__SHIFT 0x00000000
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_END_MASK 0x1fff0000L
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_END__SHIFT 0x00000010
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_START_MASK 0x00001fffL
+#define CRTC_H_SYNC_A__CRTC_H_SYNC_A_START__SHIFT 0x00000000
+#define CRTC_H_SYNC_B_CNTL__CRTC_COMP_SYNC_B_EN_MASK 0x00010000L
+#define CRTC_H_SYNC_B_CNTL__CRTC_COMP_SYNC_B_EN__SHIFT 0x00000010
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_CUTOFF_MASK 0x00020000L
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_CUTOFF__SHIFT 0x00000011
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_POL_MASK 0x00000001L
+#define CRTC_H_SYNC_B_CNTL__CRTC_H_SYNC_B_POL__SHIFT 0x00000000
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_END_MASK 0x1fff0000L
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_END__SHIFT 0x00000010
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_START_MASK 0x00001fffL
+#define CRTC_H_SYNC_B__CRTC_H_SYNC_B_START__SHIFT 0x00000000
+#define CRTC_H_TOTAL__CRTC_H_TOTAL_MASK 0x00001fffL
+#define CRTC_H_TOTAL__CRTC_H_TOTAL__SHIFT 0x00000000
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_ENABLE_MASK 0x00000001L
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_ENABLE__SHIFT 0x00000000
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_FORCE_NEXT_FIELD_MASK 0x00030000L
+#define CRTC_INTERLACE_CONTROL__CRTC_INTERLACE_FORCE_NEXT_FIELD__SHIFT 0x00000010
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_CURRENT_FIELD_MASK 0x00000001L
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_CURRENT_FIELD__SHIFT 0x00000000
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_NEXT_FIELD_MASK 0x00000002L
+#define CRTC_INTERLACE_STATUS__CRTC_INTERLACE_NEXT_FIELD__SHIFT 0x00000001
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_MSK_MASK 0x00000100L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_MSK__SHIFT 0x00000008
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_TYPE_MASK 0x00000200L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_COUNT_NOW_INT_TYPE__SHIFT 0x00000009
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK_MASK 0x00010000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_MSK__SHIFT 0x00000010
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE_MASK 0x00020000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_INT_TYPE__SHIFT 0x00000011
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_MSK_MASK 0x40000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_MSK__SHIFT 0x0000001e
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_TYPE_MASK 0x80000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_GSL_VSYNC_GAP_INT_TYPE__SHIFT 0x0000001f
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_MSK_MASK 0x00000001L
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_MSK__SHIFT 0x00000000
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_TYPE_MASK 0x00000002L
+#define CRTC_INTERRUPT_CONTROL__CRTC_SNAPSHOT_INT_TYPE__SHIFT 0x00000001
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_MSK_MASK 0x01000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_MSK__SHIFT 0x00000018
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_TYPE_MASK 0x04000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGA_INT_TYPE__SHIFT 0x0000001a
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_MSK_MASK 0x02000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_MSK__SHIFT 0x00000019
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_TYPE_MASK 0x08000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_TRIGB_INT_TYPE__SHIFT 0x0000001b
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_MSK_MASK 0x10000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_MSK__SHIFT 0x0000001c
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_TYPE_MASK 0x20000000L
+#define CRTC_INTERRUPT_CONTROL__CRTC_VSYNC_NOM_INT_TYPE__SHIFT 0x0000001d
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK 0x00000010L
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK__SHIFT 0x00000004
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_TYPE_MASK 0x00000020L
+#define CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_TYPE__SHIFT 0x00000005
+#define CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE_MASK 0x00000001L
+#define CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__CRTC_MANUAL_FORCE_VSYNC_NEXT_LINE__SHIFT 0x00000000
+#define CRTC_MASTER_EN__CRTC_MASTER_EN_MASK 0x00000001L
+#define CRTC_MASTER_EN__CRTC_MASTER_EN__SHIFT 0x00000000
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_MASK 0xffffff00L
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_CNTL_CHAR_INSERT__SHIFT 0x00000008
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_OUT_MODE_MASK 0x00000003L
+#define CRTC_MVP_INBAND_CNTL_INSERT__CRTC_MVP_INBAND_OUT_MODE__SHIFT 0x00000000
+#define CRTC_MVP_INBAND_CNTL_INSERT_TIMER__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_TIMER_MASK 0x000000ffL
+#define CRTC_MVP_INBAND_CNTL_INSERT_TIMER__CRTC_MVP_INBAND_CNTL_CHAR_INSERT_TIMER__SHIFT 0x00000000
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR_MASK 0x00100000L
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_CLEAR__SHIFT 0x00000014
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_OCCURRED_MASK 0x00000010L
+#define CRTC_MVP_STATUS__CRTC_AFR_HSYNC_SWITCH_DONE_OCCURRED__SHIFT 0x00000004
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_CLEAR_MASK 0x00010000L
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_CLEAR__SHIFT 0x00000010
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_OCCURRED_MASK 0x00000001L
+#define CRTC_MVP_STATUS__CRTC_FLIP_NOW_OCCURRED__SHIFT 0x00000000
+#define CRTC_NOM_VERT_POSITION__CRTC_VERT_COUNT_NOM_MASK 0x00001fffL
+#define CRTC_NOM_VERT_POSITION__CRTC_VERT_COUNT_NOM__SHIFT 0x00000000
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE_MASK 0x000003ffL
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_BLUE__SHIFT 0x00000000
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN_MASK 0x000ffc00L
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_GREEN__SHIFT 0x0000000a
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED_MASK 0x3ff00000L
+#define CRTC_OVERSCAN_COLOR__CRTC_OVERSCAN_COLOR_RED__SHIFT 0x00000014
+#define CRTC_SNAPSHOT_CONTROL__CRTC_AUTO_SNAPSHOT_TRIG_SEL_MASK 0x00000003L
+#define CRTC_SNAPSHOT_CONTROL__CRTC_AUTO_SNAPSHOT_TRIG_SEL__SHIFT 0x00000000
+#define CRTC_SNAPSHOT_FRAME__CRTC_SNAPSHOT_FRAME_COUNT_MASK 0x00ffffffL
+#define CRTC_SNAPSHOT_FRAME__CRTC_SNAPSHOT_FRAME_COUNT__SHIFT 0x00000000
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_HORZ_COUNT_MASK 0x1fff0000L
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_HORZ_COUNT__SHIFT 0x00000010
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_VERT_COUNT_MASK 0x00001fffL
+#define CRTC_SNAPSHOT_POSITION__CRTC_SNAPSHOT_VERT_COUNT__SHIFT 0x00000000
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_CLEAR_MASK 0x00000002L
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_CLEAR__SHIFT 0x00000001
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_MANUAL_TRIGGER_MASK 0x00000004L
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_MANUAL_TRIGGER__SHIFT 0x00000002
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_OCCURRED_MASK 0x00000001L
+#define CRTC_SNAPSHOT_STATUS__CRTC_SNAPSHOT_OCCURRED__SHIFT 0x00000000
+#define CRTC_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION_MASK 0x000f0000L
+#define CRTC_START_LINE_CONTROL__CRTC_ADVANCED_START_LINE_POSITION__SHIFT 0x00000010
+#define CRTC_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY_MASK 0x00000100L
+#define CRTC_START_LINE_CONTROL__CRTC_INTERLACE_START_LINE_EARLY__SHIFT 0x00000008
+#define CRTC_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY_MASK 0x00000001L
+#define CRTC_START_LINE_CONTROL__CRTC_PROGRESSIVE_START_LINE_EARLY__SHIFT 0x00000000
+#define CRTC_STATUS__CRTC_H_ACTIVE_DISP_MASK 0x00020000L
+#define CRTC_STATUS__CRTC_H_ACTIVE_DISP__SHIFT 0x00000011
+#define CRTC_STATUS__CRTC_H_BLANK_MASK 0x00010000L
+#define CRTC_STATUS__CRTC_H_BLANK__SHIFT 0x00000010
+#define CRTC_STATUS__CRTC_H_SYNC_A_MASK 0x00040000L
+#define CRTC_STATUS__CRTC_H_SYNC_A__SHIFT 0x00000012
+#define CRTC_STATUS__CRTC_V_ACTIVE_DISP_MASK 0x00000002L
+#define CRTC_STATUS__CRTC_V_ACTIVE_DISP__SHIFT 0x00000001
+#define CRTC_STATUS__CRTC_V_BLANK_3D_STRUCTURE_MASK 0x00000020L
+#define CRTC_STATUS__CRTC_V_BLANK_3D_STRUCTURE__SHIFT 0x00000005
+#define CRTC_STATUS__CRTC_V_BLANK_MASK 0x00000001L
+#define CRTC_STATUS__CRTC_V_BLANK__SHIFT 0x00000000
+#define CRTC_STATUS__CRTC_V_START_LINE_MASK 0x00000010L
+#define CRTC_STATUS__CRTC_V_START_LINE__SHIFT 0x00000004
+#define CRTC_STATUS__CRTC_V_SYNC_A_MASK 0x00000004L
+#define CRTC_STATUS__CRTC_V_SYNC_A__SHIFT 0x00000002
+#define CRTC_STATUS__CRTC_V_UPDATE_MASK 0x00000008L
+#define CRTC_STATUS__CRTC_V_UPDATE__SHIFT 0x00000003
+#define CRTC_STATUS_FRAME_COUNT__CRTC_FRAME_COUNT_MASK 0x00ffffffL
+#define CRTC_STATUS_FRAME_COUNT__CRTC_FRAME_COUNT__SHIFT 0x00000000
+#define CRTC_STATUS_HV_COUNT__CRTC_HV_COUNT_MASK 0x1fffffffL
+#define CRTC_STATUS_HV_COUNT__CRTC_HV_COUNT__SHIFT 0x00000000
+#define CRTC_STATUS_POSITION__CRTC_HORZ_COUNT_MASK 0x1fff0000L
+#define CRTC_STATUS_POSITION__CRTC_HORZ_COUNT__SHIFT 0x00000010
+#define CRTC_STATUS_POSITION__CRTC_VERT_COUNT_MASK 0x00001fffL
+#define CRTC_STATUS_POSITION__CRTC_VERT_COUNT__SHIFT 0x00000000
+#define CRTC_STATUS_VF_COUNT__CRTC_VF_COUNT_MASK 0x1fffffffL
+#define CRTC_STATUS_VF_COUNT__CRTC_VF_COUNT__SHIFT 0x00000000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EN_MASK 0x01000000L
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_EN__SHIFT 0x00000018
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_LINE_NUM_MASK 0x00001fffL
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_LINE_NUM__SHIFT 0x00000000
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_POLARITY_MASK 0x00008000L
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_OUTPUT_POLARITY__SHIFT 0x0000000f
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_SELECT_POLARITY_MASK 0x00010000L
+#define CRTC_STEREO_CONTROL__CRTC_STEREO_SYNC_SELECT_POLARITY__SHIFT 0x00000010
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_STEREO_FORCE_NEXT_EYE_MASK 0x00000003L
+#define CRTC_STEREO_FORCE_NEXT_EYE__CRTC_STEREO_FORCE_NEXT_EYE__SHIFT 0x00000000
+#define CRTC_STEREO_STATUS__CRTC_STEREO_CURRENT_EYE_MASK 0x00000001L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_CURRENT_EYE__SHIFT 0x00000000
+#define CRTC_STEREO_STATUS__CRTC_STEREO_FORCE_NEXT_EYE_PENDING_MASK 0x03000000L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_FORCE_NEXT_EYE_PENDING__SHIFT 0x00000018
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_OUTPUT_MASK 0x00000100L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_OUTPUT__SHIFT 0x00000008
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_SELECT_MASK 0x00010000L
+#define CRTC_STEREO_STATUS__CRTC_STEREO_SYNC_SELECT__SHIFT 0x00000010
+#define CRTC_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define CRTC_TEST_DEBUG_DATA__CRTC_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define CRTC_TEST_DEBUG_INDEX__CRTC_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_DATA_MASK 0x0000ffffL
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_DATA__SHIFT 0x00000000
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_MASK_MASK 0x003f0000L
+#define CRTC_TEST_PATTERN_COLOR__CRTC_TEST_PATTERN_MASK__SHIFT 0x00000010
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_COLOR_FORMAT_MASK 0xff000000L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_COLOR_FORMAT__SHIFT 0x00000018
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_DYNAMIC_RANGE_MASK 0x00010000L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_DYNAMIC_RANGE__SHIFT 0x00000010
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_EN_MASK 0x00000001L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_EN__SHIFT 0x00000000
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_MODE_MASK 0x00000700L
+#define CRTC_TEST_PATTERN_CONTROL__CRTC_TEST_PATTERN_MODE__SHIFT 0x00000008
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_HRES_MASK 0x0000f000L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_HRES__SHIFT 0x0000000c
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC0_MASK 0x0000000fL
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC0__SHIFT 0x00000000
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC1_MASK 0x000000f0L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_INC1__SHIFT 0x00000004
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_RAMP0_OFFSET_MASK 0xffff0000L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_RAMP0_OFFSET__SHIFT 0x00000010
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_VRES_MASK 0x00000f00L
+#define CRTC_TEST_PATTERN_PARAMETERS__CRTC_TEST_PATTERN_VRES__SHIFT 0x00000008
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_CLEAR_MASK 0x80000000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_CLEAR__SHIFT 0x0000001f
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_DELAY_MASK 0x1f000000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_DELAY__SHIFT 0x00000018
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FALLING_EDGE_DETECT_CNTL_MASK 0x00030000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FALLING_EDGE_DETECT_CNTL__SHIFT 0x00000010
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FREQUENCY_SELECT_MASK 0x00300000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_FREQUENCY_SELECT__SHIFT 0x00000014
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_INPUT_STATUS_MASK 0x00000200L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_INPUT_STATUS__SHIFT 0x00000009
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_OCCURRED_MASK 0x00000800L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_OCCURRED__SHIFT 0x0000000b
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_SELECT_MASK 0x000000e0L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_SELECT__SHIFT 0x00000005
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_STATUS_MASK 0x00000400L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_POLARITY_STATUS__SHIFT 0x0000000a
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RESYNC_BYPASS_EN_MASK 0x00000100L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RESYNC_BYPASS_EN__SHIFT 0x00000008
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RISING_EDGE_DETECT_CNTL_MASK 0x00003000L
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_RISING_EDGE_DETECT_CNTL__SHIFT 0x0000000c
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_SOURCE_SELECT_MASK 0x0000001fL
+#define CRTC_TRIGA_CNTL__CRTC_TRIGA_SOURCE_SELECT__SHIFT 0x00000000
+#define CRTC_TRIGA_MANUAL_TRIG__CRTC_TRIGA_MANUAL_TRIG_MASK 0x00000001L
+#define CRTC_TRIGA_MANUAL_TRIG__CRTC_TRIGA_MANUAL_TRIG__SHIFT 0x00000000
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR_MASK 0x80000000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_CLEAR__SHIFT 0x0000001f
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY_MASK 0x1f000000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_DELAY__SHIFT 0x00000018
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL_MASK 0x00030000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FALLING_EDGE_DETECT_CNTL__SHIFT 0x00000010
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT_MASK 0x00300000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_FREQUENCY_SELECT__SHIFT 0x00000014
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_INPUT_STATUS_MASK 0x00000200L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_INPUT_STATUS__SHIFT 0x00000009
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_OCCURRED_MASK 0x00000800L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_OCCURRED__SHIFT 0x0000000b
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT_MASK 0x000000e0L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_SELECT__SHIFT 0x00000005
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_STATUS_MASK 0x00000400L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_POLARITY_STATUS__SHIFT 0x0000000a
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RESYNC_BYPASS_EN_MASK 0x00000100L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RESYNC_BYPASS_EN__SHIFT 0x00000008
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL_MASK 0x00003000L
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_RISING_EDGE_DETECT_CNTL__SHIFT 0x0000000c
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT_MASK 0x0000001fL
+#define CRTC_TRIGB_CNTL__CRTC_TRIGB_SOURCE_SELECT__SHIFT 0x00000000
+#define CRTC_TRIGB_MANUAL_TRIG__CRTC_TRIGB_MANUAL_TRIG_MASK 0x00000001L
+#define CRTC_TRIGB_MANUAL_TRIG__CRTC_TRIGB_MANUAL_TRIG__SHIFT 0x00000000
+#define CRTC_UPDATE_LOCK__CRTC_UPDATE_LOCK_MASK 0x00000001L
+#define CRTC_UPDATE_LOCK__CRTC_UPDATE_LOCK__SHIFT 0x00000000
+#define CRTC_VBI_END__CRTC_VBI_H_END_MASK 0x1fff0000L
+#define CRTC_VBI_END__CRTC_VBI_H_END__SHIFT 0x00000010
+#define CRTC_VBI_END__CRTC_VBI_V_END_MASK 0x00001fffL
+#define CRTC_VBI_END__CRTC_VBI_V_END__SHIFT 0x00000000
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_END_MASK 0x1fff0000L
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_END__SHIFT 0x00000010
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_START_MASK 0x00001fffL
+#define CRTC_V_BLANK_START_END__CRTC_V_BLANK_START__SHIFT 0x00000000
+#define CRTC_VERT_SYNC_CONTROL__CRTC_AUTO_FORCE_VSYNC_MODE_MASK 0x00030000L
+#define CRTC_VERT_SYNC_CONTROL__CRTC_AUTO_FORCE_VSYNC_MODE__SHIFT 0x00000010
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR_MASK 0x00000100L
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_CLEAR__SHIFT 0x00000008
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED_MASK 0x00000001L
+#define CRTC_VERT_SYNC_CONTROL__CRTC_FORCE_VSYNC_NEXT_LINE_OCCURRED__SHIFT 0x00000000
+#define CRTC_VGA_PARAMETER_CAPTURE_MODE__CRTC_VGA_PARAMETER_CAPTURE_MODE_MASK 0x00000001L
+#define CRTC_VGA_PARAMETER_CAPTURE_MODE__CRTC_VGA_PARAMETER_CAPTURE_MODE__SHIFT 0x00000000
+#define CRTC_V_SYNC_A_CNTL__CRTC_V_SYNC_A_POL_MASK 0x00000001L
+#define CRTC_V_SYNC_A_CNTL__CRTC_V_SYNC_A_POL__SHIFT 0x00000000
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_END_MASK 0x1fff0000L
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_END__SHIFT 0x00000010
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_START_MASK 0x00001fffL
+#define CRTC_V_SYNC_A__CRTC_V_SYNC_A_START__SHIFT 0x00000000
+#define CRTC_V_SYNC_B_CNTL__CRTC_V_SYNC_B_POL_MASK 0x00000001L
+#define CRTC_V_SYNC_B_CNTL__CRTC_V_SYNC_B_POL__SHIFT 0x00000000
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_END_MASK 0x1fff0000L
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_END__SHIFT 0x00000010
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_START_MASK 0x00001fffL
+#define CRTC_V_SYNC_B__CRTC_V_SYNC_B_START__SHIFT 0x00000000
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_INT_CLEAR_MASK 0x00000010L
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_INT_CLEAR__SHIFT 0x00000004
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM_MASK 0x00000001L
+#define CRTC_VSYNC_NOM_INT_STATUS__CRTC_VSYNC_NOM__SHIFT 0x00000000
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT_MASK 0x00000100L
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_ON_EVENT__SHIFT 0x00000008
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC_MASK 0x00001000L
+#define CRTC_V_TOTAL_CONTROL__CRTC_FORCE_LOCK_TO_MASTER_VSYNC__SHIFT 0x0000000c
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK_MASK 0xffff0000L
+#define CRTC_V_TOTAL_CONTROL__CRTC_SET_V_TOTAL_MIN_MASK__SHIFT 0x00000010
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL_MASK 0x00000010L
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MAX_SEL__SHIFT 0x00000004
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL_MASK 0x00000001L
+#define CRTC_V_TOTAL_CONTROL__CRTC_V_TOTAL_MIN_SEL__SHIFT 0x00000000
+#define CRTC_V_TOTAL__CRTC_V_TOTAL_MASK 0x00001fffL
+#define CRTC_V_TOTAL__CRTC_V_TOTAL__SHIFT 0x00000000
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK_MASK 0x00000100L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_ACK__SHIFT 0x00000008
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000010L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x00000004
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MASK 0x00000001L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MSK_MASK 0x00001000L
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED_MSK__SHIFT 0x0000000c
+#define CRTC_V_TOTAL_INT_STATUS__CRTC_SET_V_TOTAL_MIN_EVENT_OCCURED__SHIFT 0x00000000
+#define CRTC_V_TOTAL_MAX__CRTC_ALLOW_VBLANK_EXTENSION_FOR_MC_TRAINING_MASK 0x00010000L
+#define CRTC_V_TOTAL_MAX__CRTC_ALLOW_VBLANK_EXTENSION_FOR_MC_TRAINING__SHIFT 0x00000010
+#define CRTC_V_TOTAL_MAX__CRTC_V_TOTAL_MAX_MASK 0x00001fffL
+#define CRTC_V_TOTAL_MAX__CRTC_V_TOTAL_MAX__SHIFT 0x00000000
+#define CRTC_V_TOTAL_MIN__CRTC_V_TOTAL_MIN_MASK 0x00001fffL
+#define CRTC_V_TOTAL_MIN__CRTC_V_TOTAL_MIN__SHIFT 0x00000000
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK 0x00000100L
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR__SHIFT 0x00000008
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_OCCURRED_MASK 0x00000001L
+#define CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_OCCURRED__SHIFT 0x00000000
+#define CUR_COLOR1__CUR_COLOR1_BLUE_MASK 0x000000ffL
+#define CUR_COLOR1__CUR_COLOR1_BLUE__SHIFT 0x00000000
+#define CUR_COLOR1__CUR_COLOR1_GREEN_MASK 0x0000ff00L
+#define CUR_COLOR1__CUR_COLOR1_GREEN__SHIFT 0x00000008
+#define CUR_COLOR1__CUR_COLOR1_RED_MASK 0x00ff0000L
+#define CUR_COLOR1__CUR_COLOR1_RED__SHIFT 0x00000010
+#define CUR_COLOR2__CUR_COLOR2_BLUE_MASK 0x000000ffL
+#define CUR_COLOR2__CUR_COLOR2_BLUE__SHIFT 0x00000000
+#define CUR_COLOR2__CUR_COLOR2_GREEN_MASK 0x0000ff00L
+#define CUR_COLOR2__CUR_COLOR2_GREEN__SHIFT 0x00000008
+#define CUR_COLOR2__CUR_COLOR2_RED_MASK 0x00ff0000L
+#define CUR_COLOR2__CUR_COLOR2_RED__SHIFT 0x00000010
+#define CUR_CONTROL__CUR_INV_TRANS_CLAMP_MASK 0x00000010L
+#define CUR_CONTROL__CUR_INV_TRANS_CLAMP__SHIFT 0x00000004
+#define CUR_CONTROL__CURSOR_2X_MAGNIFY_MASK 0x00010000L
+#define CUR_CONTROL__CURSOR_2X_MAGNIFY__SHIFT 0x00000010
+#define CUR_CONTROL__CURSOR_EN_MASK 0x00000001L
+#define CUR_CONTROL__CURSOR_EN__SHIFT 0x00000000
+#define CUR_CONTROL__CURSOR_FORCE_MC_ON_MASK 0x00100000L
+#define CUR_CONTROL__CURSOR_FORCE_MC_ON__SHIFT 0x00000014
+#define CUR_CONTROL__CURSOR_MODE_MASK 0x00000300L
+#define CUR_CONTROL__CURSOR_MODE__SHIFT 0x00000008
+#define CUR_CONTROL__CURSOR_URGENT_CONTROL_MASK 0x07000000L
+#define CUR_CONTROL__CURSOR_URGENT_CONTROL__SHIFT 0x00000018
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_X_MASK 0x003f0000L
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_X__SHIFT 0x00000010
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_Y_MASK 0x0000003fL
+#define CUR_HOT_SPOT__CURSOR_HOT_SPOT_Y__SHIFT 0x00000000
+#define CUR_POSITION__CURSOR_X_POSITION_MASK 0x3fff0000L
+#define CUR_POSITION__CURSOR_X_POSITION__SHIFT 0x00000010
+#define CUR_POSITION__CURSOR_Y_POSITION_MASK 0x00003fffL
+#define CUR_POSITION__CURSOR_Y_POSITION__SHIFT 0x00000000
+#define CUR_REQUEST_FILTER_CNTL__CUR_REQUEST_FILTER_DIS_MASK 0x00000001L
+#define CUR_REQUEST_FILTER_CNTL__CUR_REQUEST_FILTER_DIS__SHIFT 0x00000000
+#define CUR_SIZE__CURSOR_HEIGHT_MASK 0x0000003fL
+#define CUR_SIZE__CURSOR_HEIGHT__SHIFT 0x00000000
+#define CUR_SIZE__CURSOR_WIDTH_MASK 0x003f0000L
+#define CUR_SIZE__CURSOR_WIDTH__SHIFT 0x00000010
+#define CUR_SURFACE_ADDRESS__CURSOR_SURFACE_ADDRESS_MASK 0xffffffffL
+#define CUR_SURFACE_ADDRESS__CURSOR_SURFACE_ADDRESS__SHIFT 0x00000000
+#define CUR_SURFACE_ADDRESS_HIGH__CURSOR_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define CUR_SURFACE_ADDRESS_HIGH__CURSOR_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define CUR_UPDATE__CURSOR_DISABLE_MULTIPLE_UPDATE_MASK 0x01000000L
+#define CUR_UPDATE__CURSOR_DISABLE_MULTIPLE_UPDATE__SHIFT 0x00000018
+#define CUR_UPDATE__CURSOR_UPDATE_LOCK_MASK 0x00010000L
+#define CUR_UPDATE__CURSOR_UPDATE_LOCK__SHIFT 0x00000010
+#define CUR_UPDATE__CURSOR_UPDATE_PENDING_MASK 0x00000001L
+#define CUR_UPDATE__CURSOR_UPDATE_PENDING__SHIFT 0x00000000
+#define CUR_UPDATE__CURSOR_UPDATE_TAKEN_MASK 0x00000002L
+#define CUR_UPDATE__CURSOR_UPDATE_TAKEN__SHIFT 0x00000001
+#define D1VGA_CONTROL__D1VGA_MODE_ENABLE_MASK 0x00000001L
+#define D1VGA_CONTROL__D1VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D1VGA_CONTROL__D1VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D1VGA_CONTROL__D1VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D1VGA_CONTROL__D1VGA_ROTATE_MASK 0x03000000L
+#define D1VGA_CONTROL__D1VGA_ROTATE__SHIFT 0x00000018
+#define D1VGA_CONTROL__D1VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D1VGA_CONTROL__D1VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D1VGA_CONTROL__D1VGA_TIMING_SELECT_MASK 0x00000100L
+#define D1VGA_CONTROL__D1VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D2VGA_CONTROL__D2VGA_MODE_ENABLE_MASK 0x00000001L
+#define D2VGA_CONTROL__D2VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D2VGA_CONTROL__D2VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D2VGA_CONTROL__D2VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D2VGA_CONTROL__D2VGA_ROTATE_MASK 0x03000000L
+#define D2VGA_CONTROL__D2VGA_ROTATE__SHIFT 0x00000018
+#define D2VGA_CONTROL__D2VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D2VGA_CONTROL__D2VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D2VGA_CONTROL__D2VGA_TIMING_SELECT_MASK 0x00000100L
+#define D2VGA_CONTROL__D2VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D3VGA_CONTROL__D3VGA_MODE_ENABLE_MASK 0x00000001L
+#define D3VGA_CONTROL__D3VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D3VGA_CONTROL__D3VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D3VGA_CONTROL__D3VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D3VGA_CONTROL__D3VGA_ROTATE_MASK 0x03000000L
+#define D3VGA_CONTROL__D3VGA_ROTATE__SHIFT 0x00000018
+#define D3VGA_CONTROL__D3VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D3VGA_CONTROL__D3VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D3VGA_CONTROL__D3VGA_TIMING_SELECT_MASK 0x00000100L
+#define D3VGA_CONTROL__D3VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D4VGA_CONTROL__D4VGA_MODE_ENABLE_MASK 0x00000001L
+#define D4VGA_CONTROL__D4VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D4VGA_CONTROL__D4VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D4VGA_CONTROL__D4VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D4VGA_CONTROL__D4VGA_ROTATE_MASK 0x03000000L
+#define D4VGA_CONTROL__D4VGA_ROTATE__SHIFT 0x00000018
+#define D4VGA_CONTROL__D4VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D4VGA_CONTROL__D4VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D4VGA_CONTROL__D4VGA_TIMING_SELECT_MASK 0x00000100L
+#define D4VGA_CONTROL__D4VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D5VGA_CONTROL__D5VGA_MODE_ENABLE_MASK 0x00000001L
+#define D5VGA_CONTROL__D5VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D5VGA_CONTROL__D5VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D5VGA_CONTROL__D5VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D5VGA_CONTROL__D5VGA_ROTATE_MASK 0x03000000L
+#define D5VGA_CONTROL__D5VGA_ROTATE__SHIFT 0x00000018
+#define D5VGA_CONTROL__D5VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D5VGA_CONTROL__D5VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D5VGA_CONTROL__D5VGA_TIMING_SELECT_MASK 0x00000100L
+#define D5VGA_CONTROL__D5VGA_TIMING_SELECT__SHIFT 0x00000008
+#define D6VGA_CONTROL__D6VGA_MODE_ENABLE_MASK 0x00000001L
+#define D6VGA_CONTROL__D6VGA_MODE_ENABLE__SHIFT 0x00000000
+#define D6VGA_CONTROL__D6VGA_OVERSCAN_COLOR_EN_MASK 0x00010000L
+#define D6VGA_CONTROL__D6VGA_OVERSCAN_COLOR_EN__SHIFT 0x00000010
+#define D6VGA_CONTROL__D6VGA_ROTATE_MASK 0x03000000L
+#define D6VGA_CONTROL__D6VGA_ROTATE__SHIFT 0x00000018
+#define D6VGA_CONTROL__D6VGA_SYNC_POLARITY_SELECT_MASK 0x00000200L
+#define D6VGA_CONTROL__D6VGA_SYNC_POLARITY_SELECT__SHIFT 0x00000009
+#define D6VGA_CONTROL__D6VGA_TIMING_SELECT_MASK 0x00000100L
+#define D6VGA_CONTROL__D6VGA_TIMING_SELECT__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_POWERUP_COUNTER_MASK 0x000000ffL
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_POWERUP_COUNTER__SHIFT 0x00000000
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_TESTMODE_MASK 0x00000100L
+#define DAC_AUTODETECT_CONTROL2__DAC_AUTODETECT_TESTMODE__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_IN_DELAY_MASK 0x000000ffL
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_IN_DELAY__SHIFT 0x00000000
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_OUT_DELAY_MASK 0x0000ff00L
+#define DAC_AUTODETECT_CONTROL3__DAC_AUTODET_COMPARATOR_OUT_DELAY__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_CHECK_MASK_MASK 0x00070000L
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_CHECK_MASK__SHIFT 0x00000010
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_FRAME_TIME_COUNTER_MASK 0x0000ff00L
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_FRAME_TIME_COUNTER__SHIFT 0x00000008
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_MODE_MASK 0x00000003L
+#define DAC_AUTODETECT_CONTROL__DAC_AUTODETECT_MODE__SHIFT 0x00000000
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_ACK_MASK 0x00000001L
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_ACK__SHIFT 0x00000000
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_INT_ENABLE_MASK 0x00010000L
+#define DAC_AUTODETECT_INT_CONTROL__DAC_AUTODETECT_INT_ENABLE__SHIFT 0x00000010
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_BLUE_SENSE_MASK 0x03000000L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_BLUE_SENSE__SHIFT 0x00000018
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_CONNECT_MASK 0x00000010L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_CONNECT__SHIFT 0x00000004
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_GREEN_SENSE_MASK 0x00030000L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_GREEN_SENSE__SHIFT 0x00000010
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_RED_SENSE_MASK 0x00000300L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_RED_SENSE__SHIFT 0x00000008
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_STATUS_MASK 0x00000001L
+#define DAC_AUTODETECT_STATUS__DAC_AUTODETECT_STATUS__SHIFT 0x00000000
+#define DAC_CLK_ENABLE__DACA_CLK_ENABLE_MASK 0x00000001L
+#define DAC_CLK_ENABLE__DACA_CLK_ENABLE__SHIFT 0x00000000
+#define DAC_CLK_ENABLE__DACB_CLK_ENABLE_MASK 0x00000010L
+#define DAC_CLK_ENABLE__DACB_CLK_ENABLE__SHIFT 0x00000004
+#define DAC_COMPARATOR_ENABLE__DAC_B_ASYNC_ENABLE_MASK 0x00040000L
+#define DAC_COMPARATOR_ENABLE__DAC_B_ASYNC_ENABLE__SHIFT 0x00000012
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_DDET_REF_EN_MASK 0x00000001L
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_DDET_REF_EN__SHIFT 0x00000000
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_SDET_REF_EN_MASK 0x00000100L
+#define DAC_COMPARATOR_ENABLE__DAC_COMP_SDET_REF_EN__SHIFT 0x00000008
+#define DAC_COMPARATOR_ENABLE__DAC_G_ASYNC_ENABLE_MASK 0x00020000L
+#define DAC_COMPARATOR_ENABLE__DAC_G_ASYNC_ENABLE__SHIFT 0x00000011
+#define DAC_COMPARATOR_ENABLE__DAC_R_ASYNC_ENABLE_MASK 0x00010000L
+#define DAC_COMPARATOR_ENABLE__DAC_R_ASYNC_ENABLE__SHIFT 0x00000010
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_BLUE_MASK 0x00000002L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_BLUE__SHIFT 0x00000001
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_GREEN_MASK 0x00000004L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_GREEN__SHIFT 0x00000002
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_MASK 0x00000001L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_RED_MASK 0x00000008L
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT_RED__SHIFT 0x00000003
+#define DAC_COMPARATOR_OUTPUT__DAC_COMPARATOR_OUTPUT__SHIFT 0x00000000
+#define DAC_CONTROL__DAC_DFORCE_EN_MASK 0x00000001L
+#define DAC_CONTROL__DAC_DFORCE_EN__SHIFT 0x00000000
+#define DAC_CONTROL__DAC_TV_ENABLE_MASK 0x00000100L
+#define DAC_CONTROL__DAC_TV_ENABLE__SHIFT 0x00000008
+#define DAC_CONTROL__DAC_ZSCALE_SHIFT_MASK 0x00010000L
+#define DAC_CONTROL__DAC_ZSCALE_SHIFT__SHIFT 0x00000010
+#define DAC_CRC_CONTROL__DAC_CRC_FIELD_MASK 0x00000001L
+#define DAC_CRC_CONTROL__DAC_CRC_FIELD__SHIFT 0x00000000
+#define DAC_CRC_CONTROL__DAC_CRC_ONLY_BLANKb_MASK 0x00000100L
+#define DAC_CRC_CONTROL__DAC_CRC_ONLY_BLANKb__SHIFT 0x00000008
+#define DAC_CRC_EN__DAC_CRC_CONT_EN_MASK 0x00010000L
+#define DAC_CRC_EN__DAC_CRC_CONT_EN__SHIFT 0x00000010
+#define DAC_CRC_EN__DAC_CRC_EN_MASK 0x00000001L
+#define DAC_CRC_EN__DAC_CRC_EN__SHIFT 0x00000000
+#define DAC_CRC_SIG_CONTROL__DAC_CRC_SIG_CONTROL_MASK 0x0000003fL
+#define DAC_CRC_SIG_CONTROL__DAC_CRC_SIG_CONTROL__SHIFT 0x00000000
+#define DAC_CRC_SIG_CONTROL_MASK__DAC_CRC_SIG_CONTROL_MASK_MASK 0x0000003fL
+#define DAC_CRC_SIG_CONTROL_MASK__DAC_CRC_SIG_CONTROL_MASK__SHIFT 0x00000000
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_BLUE_MASK 0x000003ffL
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_BLUE__SHIFT 0x00000000
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_GREEN_MASK 0x000ffc00L
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_GREEN__SHIFT 0x0000000a
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_RED_MASK 0x3ff00000L
+#define DAC_CRC_SIG_RGB__DAC_CRC_SIG_RED__SHIFT 0x00000014
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_BLUE_MASK_MASK 0x000003ffL
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_BLUE_MASK__SHIFT 0x00000000
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_GREEN_MASK_MASK 0x000ffc00L
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_GREEN_MASK__SHIFT 0x0000000a
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_RED_MASK_MASK 0x3ff00000L
+#define DAC_CRC_SIG_RGB_MASK__DAC_CRC_SIG_RED_MASK__SHIFT 0x00000014
+#define DAC_DATA__DAC_DATA_MASK 0x0000003fL
+#define DAC_DATA__DAC_DATA__SHIFT 0x00000000
+#define DAC_DFT_CONFIG__DAC_DFT_CONFIG_MASK 0xffffffffL
+#define DAC_DFT_CONFIG__DAC_DFT_CONFIG__SHIFT 0x00000000
+#define DAC_ENABLE__DAC_ENABLE_MASK 0x00000001L
+#define DAC_ENABLE__DAC_ENABLE__SHIFT 0x00000000
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ENABLE_MASK 0x00000002L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ENABLE__SHIFT 0x00000001
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_ACK_MASK 0x00000020L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_ACK__SHIFT 0x00000005
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR_MASK 0x00000010L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_ERROR__SHIFT 0x00000004
+#define DAC_ENABLE__DAC_RESYNC_FIFO_POINTER_SKEW_MASK 0x0000000cL
+#define DAC_ENABLE__DAC_RESYNC_FIFO_POINTER_SKEW__SHIFT 0x00000002
+#define DAC_ENABLE__DAC_RESYNC_FIFO_TVOUT_SIM_MASK 0x00000100L
+#define DAC_ENABLE__DAC_RESYNC_FIFO_TVOUT_SIM__SHIFT 0x00000008
+#define DAC_FIFO_STATUS__DAC_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000fc00L
+#define DAC_FIFO_STATUS__DAC_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x0000000a
+#define DAC_FIFO_STATUS__DAC_FIFO_CALIBRATED_MASK 0x20000000L
+#define DAC_FIFO_STATUS__DAC_FIFO_CALIBRATED__SHIFT 0x0000001d
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000L
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x0000001e
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000L
+#define DAC_FIFO_STATUS__DAC_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x0000001f
+#define DAC_FIFO_STATUS__DAC_FIFO_MAXIMUM_LEVEL_MASK 0x000f0000L
+#define DAC_FIFO_STATUS__DAC_FIFO_MAXIMUM_LEVEL__SHIFT 0x00000010
+#define DAC_FIFO_STATUS__DAC_FIFO_MINIMUM_LEVEL_MASK 0x03c00000L
+#define DAC_FIFO_STATUS__DAC_FIFO_MINIMUM_LEVEL__SHIFT 0x00000016
+#define DAC_FIFO_STATUS__DAC_FIFO_OVERWRITE_LEVEL_MASK 0x000000fcL
+#define DAC_FIFO_STATUS__DAC_FIFO_OVERWRITE_LEVEL__SHIFT 0x00000002
+#define DAC_FIFO_STATUS__DAC_FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000002L
+#define DAC_FIFO_STATUS__DAC_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x00000001
+#define DAC_FORCE_DATA__DAC_FORCE_DATA_MASK 0x000003ffL
+#define DAC_FORCE_DATA__DAC_FORCE_DATA__SHIFT 0x00000000
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_EN_MASK 0x00000001L
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_EN__SHIFT 0x00000000
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_ON_BLANKb_ONLY_MASK 0x01000000L
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_ON_BLANKb_ONLY__SHIFT 0x00000018
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_SEL_MASK 0x00000700L
+#define DAC_FORCE_OUTPUT_CNTL__DAC_FORCE_DATA_SEL__SHIFT 0x00000008
+#define DAC_MACRO_CNTL_RESERVED0__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED0__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MACRO_CNTL_RESERVED1__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED1__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MACRO_CNTL_RESERVED2__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED2__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MACRO_CNTL_RESERVED3__DAC_MACRO_CNTL_RESERVED_MASK 0xffffffffL
+#define DAC_MACRO_CNTL_RESERVED3__DAC_MACRO_CNTL_RESERVED__SHIFT 0x00000000
+#define DAC_MASK__DAC_MASK_MASK 0x000000ffL
+#define DAC_MASK__DAC_MASK__SHIFT 0x00000000
+#define DAC_POWERDOWN__DAC_POWERDOWN_BLUE_MASK 0x00000100L
+#define DAC_POWERDOWN__DAC_POWERDOWN_BLUE__SHIFT 0x00000008
+#define DAC_POWERDOWN__DAC_POWERDOWN_GREEN_MASK 0x00010000L
+#define DAC_POWERDOWN__DAC_POWERDOWN_GREEN__SHIFT 0x00000010
+#define DAC_POWERDOWN__DAC_POWERDOWN_MASK 0x00000001L
+#define DAC_POWERDOWN__DAC_POWERDOWN_RED_MASK 0x01000000L
+#define DAC_POWERDOWN__DAC_POWERDOWN_RED__SHIFT 0x00000018
+#define DAC_POWERDOWN__DAC_POWERDOWN__SHIFT 0x00000000
+#define DAC_PWR_CNTL__DAC_BG_MODE_MASK 0x00000003L
+#define DAC_PWR_CNTL__DAC_BG_MODE__SHIFT 0x00000000
+#define DAC_PWR_CNTL__DAC_PWRCNTL_MASK 0x00030000L
+#define DAC_PWR_CNTL__DAC_PWRCNTL__SHIFT 0x00000010
+#define DAC_R_INDEX__DAC_R_INDEX_MASK 0x000000ffL
+#define DAC_R_INDEX__DAC_R_INDEX__SHIFT 0x00000000
+#define DAC_SOURCE_SELECT__DAC_SOURCE_SELECT_MASK 0x00000007L
+#define DAC_SOURCE_SELECT__DAC_SOURCE_SELECT__SHIFT 0x00000000
+#define DAC_SOURCE_SELECT__DAC_TV_SELECT_MASK 0x00000008L
+#define DAC_SOURCE_SELECT__DAC_TV_SELECT__SHIFT 0x00000003
+#define DAC_STEREOSYNC_SELECT__DAC_STEREOSYNC_SELECT_MASK 0x00000007L
+#define DAC_STEREOSYNC_SELECT__DAC_STEREOSYNC_SELECT__SHIFT 0x00000000
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_HSYNCA_TRISTATE_MASK 0x00000001L
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_HSYNCA_TRISTATE__SHIFT 0x00000000
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_SYNCA_TRISTATE_MASK 0x00010000L
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_SYNCA_TRISTATE__SHIFT 0x00000010
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_VSYNCA_TRISTATE_MASK 0x00000100L
+#define DAC_SYNC_TRISTATE_CONTROL__DAC_VSYNCA_TRISTATE__SHIFT 0x00000008
+#define DAC_W_INDEX__DAC_W_INDEX_MASK 0x000000ffL
+#define DAC_W_INDEX__DAC_W_INDEX__SHIFT 0x00000000
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_CLEAR_MASK 0x00000100L
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_CLEAR__SHIFT 0x00000008
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME_MASK 0x00000001L
+#define DC_ABM1_ACE_CNTL_MISC__ABM1_ACE_REG_WR_MISSED_FRAME__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_OFFSET_0_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_OFFSET_0__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_SLOPE_0_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_0__ABM1_ACE_SLOPE_0__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_OFFSET_1_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_OFFSET_1__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_SLOPE_1_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_1__ABM1_ACE_SLOPE_1__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_OFFSET_2_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_OFFSET_2__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_SLOPE_2_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_2__ABM1_ACE_SLOPE_2__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_OFFSET_3_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_OFFSET_3__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_SLOPE_3_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_3__ABM1_ACE_SLOPE_3__SHIFT 0x00000000
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_OFFSET_4_MASK 0x07ff0000L
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_OFFSET_4__SHIFT 0x00000010
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_SLOPE_4_MASK 0x00007fffL
+#define DC_ABM1_ACE_OFFSET_SLOPE_4__ABM1_ACE_SLOPE_4__SHIFT 0x00000000
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_1_MASK 0x000003ffL
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_1__SHIFT 0x00000000
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_2_MASK 0x03ff0000L
+#define DC_ABM1_ACE_THRES_12__ABM1_ACE_THRES_2__SHIFT 0x00000010
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_DBUF_REG_UPDATE_PENDING_MASK 0x40000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_DBUF_REG_UPDATE_PENDING__SHIFT 0x0000001e
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_IGNORE_MASTER_LOCK_EN_MASK 0x10000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001c
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_LOCK_MASK 0x80000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_READBACK_DB_REG_VALUE_EN_MASK 0x20000000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_READBACK_DB_REG_VALUE_EN__SHIFT 0x0000001d
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_3_MASK 0x000003ffL
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_3__SHIFT 0x00000000
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_4_MASK 0x03ff0000L
+#define DC_ABM1_ACE_THRES_34__ABM1_ACE_THRES_4__SHIFT 0x00000010
+#define DC_ABM1_BL_MASTER_LOCK__ABM1_BL_MASTER_LOCK_MASK 0x80000000L
+#define DC_ABM1_BL_MASTER_LOCK__ABM1_BL_MASTER_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_CNTL__ABM1_BLANK_MODE_SUPPORT_ENABLE_MASK 0x80000000L
+#define DC_ABM1_CNTL__ABM1_BLANK_MODE_SUPPORT_ENABLE__SHIFT 0x0000001f
+#define DC_ABM1_CNTL__ABM1_EN_MASK 0x00000001L
+#define DC_ABM1_CNTL__ABM1_EN__SHIFT 0x00000000
+#define DC_ABM1_CNTL__ABM1_SOURCE_SELECT_MASK 0x00000700L
+#define DC_ABM1_CNTL__ABM1_SOURCE_SELECT__SHIFT 0x00000008
+#define DC_ABM1_DEBUG_MISC__ABM1_BL_FORCE_INTERRUPT_MASK 0x00010000L
+#define DC_ABM1_DEBUG_MISC__ABM1_BL_FORCE_INTERRUPT__SHIFT 0x00000010
+#define DC_ABM1_DEBUG_MISC__ABM1_HG_FORCE_INTERRUPT_MASK 0x00000001L
+#define DC_ABM1_DEBUG_MISC__ABM1_HG_FORCE_INTERRUPT__SHIFT 0x00000000
+#define DC_ABM1_DEBUG_MISC__ABM1_LS_FORCE_INTERRUPT_MASK 0x00000100L
+#define DC_ABM1_DEBUG_MISC__ABM1_LS_FORCE_INTERRUPT__SHIFT 0x00000008
+#define DC_ABM1_HG_BIN_1_32_SHIFT_FLAG__ABM1_HG_BIN_1_32_SHIFT_FLAG_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_1_32_SHIFT_FLAG__ABM1_HG_BIN_1_32_SHIFT_FLAG__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_17_24_SHIFT_INDEX__ABM1_HG_BIN_17_24_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_17_24_SHIFT_INDEX__ABM1_HG_BIN_17_24_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_1_8_SHIFT_INDEX__ABM1_HG_BIN_1_8_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_1_8_SHIFT_INDEX__ABM1_HG_BIN_1_8_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_25_32_SHIFT_INDEX__ABM1_HG_BIN_25_32_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_25_32_SHIFT_INDEX__ABM1_HG_BIN_25_32_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HG_BIN_9_16_SHIFT_INDEX__ABM1_HG_BIN_9_16_SHIFT_INDEX_MASK 0xffffffffL
+#define DC_ABM1_HG_BIN_9_16_SHIFT_INDEX__ABM1_HG_BIN_9_16_SHIFT_INDEX__SHIFT 0x00000000
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_IN_PROGRESS_MASK 0x00000004L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_IN_PROGRESS__SHIFT 0x00000002
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_CLEAR_MASK 0x80000000L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x0000001f
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME_MASK 0x00000400L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_BL_REG_READ_MISSED_FRAME__SHIFT 0x0000000a
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_IN_PROGRESS_MASK 0x00000001L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_IN_PROGRESS__SHIFT 0x00000000
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_CLEAR_MASK 0x00010000L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x00000010
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME_MASK 0x00000100L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_HG_REG_READ_MISSED_FRAME__SHIFT 0x00000008
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_IN_PROGRESS_MASK 0x00000002L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_IN_PROGRESS__SHIFT 0x00000001
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_CLEAR_MASK 0x01000000L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_CLEAR__SHIFT 0x00000018
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME_MASK 0x00000200L
+#define DC_ABM1_HGLS_REG_READ_PROGRESS__ABM1_LS_REG_READ_MISSED_FRAME__SHIFT 0x00000009
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_READBACK_DB_REG_VALUE_EN_MASK 0x00800000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_READBACK_DB_REG_VALUE_EN__SHIFT 0x00000017
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_FRAME_START_DISP_SEL_MASK 0x07000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_FRAME_START_DISP_SEL__SHIFT 0x00000018
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_AT_FRAME_START_MASK 0x10000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_AT_FRAME_START__SHIFT 0x0000001c
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_PENDING_MASK 0x40000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_DBUF_HGLS_REG_UPDATE_PENDING__SHIFT 0x0000001e
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_BIN_BITWIDTH_SIZE_SEL_MASK 0x00030000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_BIN_BITWIDTH_SIZE_SEL__SHIFT 0x00000010
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_FINE_MODE_BIN_SEL_MASK 0x00001000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_FINE_MODE_BIN_SEL__SHIFT 0x0000000c
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_IGNORE_MASTER_LOCK_EN_MASK 0x20000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_IGNORE_MASTER_LOCK_EN__SHIFT 0x0000001d
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_NUM_OF_BINS_SEL_MASK 0x00000003L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_NUM_OF_BINS_SEL__SHIFT 0x00000000
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_VMAX_SEL_MASK 0x00000100L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_HG_VMAX_SEL__SHIFT 0x00000008
+#define DC_ABM1_HG_MISC_CTRL__ABM1_OVR_SCAN_PIXEL_PROCESS_EN_MASK 0x00100000L
+#define DC_ABM1_HG_MISC_CTRL__ABM1_OVR_SCAN_PIXEL_PROCESS_EN__SHIFT 0x00000014
+#define DC_ABM1_HG_RESULT_10__ABM1_HG_RESULT_10_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_10__ABM1_HG_RESULT_10__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_11__ABM1_HG_RESULT_11_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_11__ABM1_HG_RESULT_11__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_12__ABM1_HG_RESULT_12_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_12__ABM1_HG_RESULT_12__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_13__ABM1_HG_RESULT_13_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_13__ABM1_HG_RESULT_13__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_14__ABM1_HG_RESULT_14_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_14__ABM1_HG_RESULT_14__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_15__ABM1_HG_RESULT_15_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_15__ABM1_HG_RESULT_15__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_16__ABM1_HG_RESULT_16_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_16__ABM1_HG_RESULT_16__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_17__ABM1_HG_RESULT_17_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_17__ABM1_HG_RESULT_17__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_18__ABM1_HG_RESULT_18_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_18__ABM1_HG_RESULT_18__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_19__ABM1_HG_RESULT_19_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_19__ABM1_HG_RESULT_19__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_1__ABM1_HG_RESULT_1_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_1__ABM1_HG_RESULT_1__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_20__ABM1_HG_RESULT_20_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_20__ABM1_HG_RESULT_20__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_21__ABM1_HG_RESULT_21_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_21__ABM1_HG_RESULT_21__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_22__ABM1_HG_RESULT_22_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_22__ABM1_HG_RESULT_22__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_23__ABM1_HG_RESULT_23_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_23__ABM1_HG_RESULT_23__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_24__ABM1_HG_RESULT_24_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_24__ABM1_HG_RESULT_24__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_2__ABM1_HG_RESULT_2_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_2__ABM1_HG_RESULT_2__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_3__ABM1_HG_RESULT_3_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_3__ABM1_HG_RESULT_3__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_4__ABM1_HG_RESULT_4_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_4__ABM1_HG_RESULT_4__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_5__ABM1_HG_RESULT_5_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_5__ABM1_HG_RESULT_5__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_6__ABM1_HG_RESULT_6_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_6__ABM1_HG_RESULT_6__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_7__ABM1_HG_RESULT_7_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_7__ABM1_HG_RESULT_7__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_8__ABM1_HG_RESULT_8_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_8__ABM1_HG_RESULT_8__SHIFT 0x00000000
+#define DC_ABM1_HG_RESULT_9__ABM1_HG_RESULT_9_MASK 0xffffffffL
+#define DC_ABM1_HG_RESULT_9__ABM1_HG_RESULT_9__SHIFT 0x00000000
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0x00ff0000L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x00000010
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x00000002L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x00000001
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_COUNT_EN_MASK 0x00000001L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_COUNT_EN__SHIFT 0x00000000
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_FRAME_COUNT_MASK 0x0000ff00L
+#define DC_ABM1_HG_SAMPLE_RATE__ABM1_HG_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x00000008
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_B_MASK 0x0000000fL
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_B__SHIFT 0x00000000
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_G_MASK 0x00000f00L
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_G__SHIFT 0x00000008
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_R_MASK 0x000f0000L
+#define DC_ABM1_IPCSC_COEFF_SEL__ABM1_IPCSC_COEFF_SEL_R__SHIFT 0x00000010
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MAX_LUMA_MASK 0x03ff0000L
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MAX_LUMA__SHIFT 0x00000010
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MIN_LUMA_MASK 0x000003ffL
+#define DC_ABM1_LS_FILTERED_MIN_MAX_LUMA__ABM1_LS_FILTERED_MIN_LUMA__SHIFT 0x00000000
+#define DC_ABM1_LS_MAX_PIXEL_VALUE_COUNT__ABM1_LS_MAX_PIXEL_VALUE_COUNT_MASK 0x00ffffffL
+#define DC_ABM1_LS_MAX_PIXEL_VALUE_COUNT__ABM1_LS_MAX_PIXEL_VALUE_COUNT__SHIFT 0x00000000
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MAX_LUMA_MASK 0x03ff0000L
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MAX_LUMA__SHIFT 0x00000010
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MIN_LUMA_MASK 0x000003ffL
+#define DC_ABM1_LS_MIN_MAX_LUMA__ABM1_LS_MIN_LUMA__SHIFT 0x00000000
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MAX_PIXEL_VALUE_THRES_MASK 0x03ff0000L
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MAX_PIXEL_VALUE_THRES__SHIFT 0x00000010
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MIN_PIXEL_VALUE_THRES_MASK 0x000003ffL
+#define DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES__ABM1_LS_MIN_PIXEL_VALUE_THRES__SHIFT 0x00000000
+#define DC_ABM1_LS_MIN_PIXEL_VALUE_COUNT__ABM1_LS_MIN_PIXEL_VALUE_COUNT_MASK 0x00ffffffL
+#define DC_ABM1_LS_MIN_PIXEL_VALUE_COUNT__ABM1_LS_MIN_PIXEL_VALUE_COUNT__SHIFT 0x00000000
+#define DC_ABM1_LS_OVR_SCAN_BIN__ABM1_LS_OVR_SCAN_BIN_MASK 0x00ffffffL
+#define DC_ABM1_LS_OVR_SCAN_BIN__ABM1_LS_OVR_SCAN_BIN__SHIFT 0x00000000
+#define DC_ABM1_LS_PIXEL_COUNT__ABM1_LS_PIXEL_COUNT_MASK 0x00ffffffL
+#define DC_ABM1_LS_PIXEL_COUNT__ABM1_LS_PIXEL_COUNT__SHIFT 0x00000000
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_HGLS_REG_LOCK_MASK 0x80000000L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_HGLS_REG_LOCK__SHIFT 0x0000001f
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET_MASK 0x00ff0000L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_INITIAL_SAMPLE_RATE_COUNT_VALUE_WHEN_RESET__SHIFT 0x00000010
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_RESET_SAMPLE_RATE_FRAME_COUNTER_MASK 0x00000002L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_RESET_SAMPLE_RATE_FRAME_COUNTER__SHIFT 0x00000001
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_COUNT_EN_MASK 0x00000001L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_COUNT_EN__SHIFT 0x00000000
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_FRAME_COUNT_MASK 0x0000ff00L
+#define DC_ABM1_LS_SAMPLE_RATE__ABM1_LS_SAMPLE_RATE_FRAME_COUNT__SHIFT 0x00000008
+#define DC_ABM1_LS_SUM_OF_LUMA__ABM1_LS_SUM_OF_LUMA_MASK 0xffffffffL
+#define DC_ABM1_LS_SUM_OF_LUMA__ABM1_LS_SUM_OF_LUMA__SHIFT 0x00000000
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_B_PIXEL_VALUE_MASK 0x3ff00000L
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_B_PIXEL_VALUE__SHIFT 0x00000014
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_G_PIXEL_VALUE_MASK 0x000ffc00L
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_G_PIXEL_VALUE__SHIFT 0x0000000a
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_R_PIXEL_VALUE_MASK 0x000003ffL
+#define DC_ABM1_OVERSCAN_PIXEL_VALUE__ABM1_OVERSCAN_R_PIXEL_VALUE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO0_MODULE__DCCG_AUDIO_DTO0_MODULE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO0_MODULE__DCCG_AUDIO_DTO0_MODULE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO0_PHASE__DCCG_AUDIO_DTO0_PHASE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO0_PHASE__DCCG_AUDIO_DTO0_PHASE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO1_MODULE__DCCG_AUDIO_DTO1_MODULE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO1_MODULE__DCCG_AUDIO_DTO1_MODULE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO1_PHASE__DCCG_AUDIO_DTO1_PHASE_MASK 0xffffffffL
+#define DCCG_AUDIO_DTO1_PHASE__DCCG_AUDIO_DTO1_PHASE__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_SOURCE_SEL_MASK 0x00000007L
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO0_SOURCE_SEL__SHIFT 0x00000000
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO_SEL_MASK 0x00000010L
+#define DCCG_AUDIO_DTO_SOURCE__DCCG_AUDIO_DTO_SEL__SHIFT 0x00000004
+#define DCCG_CAC_STATUS__CAC_STATUS_RDDATA_MASK 0xffffffffL
+#define DCCG_CAC_STATUS__CAC_STATUS_RDDATA__SHIFT 0x00000000
+#define DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE_MASK 0x00000010L
+#define DCCG_GATE_DISABLE_CNTL__DACACLK_GATE_DISABLE__SHIFT 0x00000004
+#define DCCG_GATE_DISABLE_CNTL__DACBCLK_GATE_DISABLE_MASK 0x00000020L
+#define DCCG_GATE_DISABLE_CNTL__DACBCLK_GATE_DISABLE__SHIFT 0x00000005
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE_MASK 0x00000001L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_DCCG_GATE_DISABLE__SHIFT 0x00000000
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_RAMP_DIV_ID_MASK 0x07000000L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_RAMP_DIV_ID__SHIFT 0x00000018
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE_MASK 0x00000002L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_GATE_DISABLE__SHIFT 0x00000001
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_RAMP_DISABLE_MASK 0x00100000L
+#define DCCG_GATE_DISABLE_CNTL__DISPCLK_R_DCCG_RAMP_DISABLE__SHIFT 0x00000014
+#define DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE_MASK 0x00000040L
+#define DCCG_GATE_DISABLE_CNTL__DVOACLK_GATE_DISABLE__SHIFT 0x00000006
+#define DCCG_GATE_DISABLE_CNTL__PCLK_TV_GATE_DISABLE_MASK 0x00010000L
+#define DCCG_GATE_DISABLE_CNTL__PCLK_TV_GATE_DISABLE__SHIFT 0x00000010
+#define DCCG_GATE_DISABLE_CNTL__SCLK_GATE_DISABLE_MASK 0x00000004L
+#define DCCG_GATE_DISABLE_CNTL__SCLK_GATE_DISABLE__SHIFT 0x00000002
+#define DCCG_GATE_DISABLE_CNTL__SCLK_RAMP_DIV_ID_MASK 0x70000000L
+#define DCCG_GATE_DISABLE_CNTL__SCLK_RAMP_DIV_ID__SHIFT 0x0000001c
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKA_GATE_DISABLE_MASK 0x00000100L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKA_GATE_DISABLE__SHIFT 0x00000008
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKB_GATE_DISABLE_MASK 0x00000200L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKB_GATE_DISABLE__SHIFT 0x00000009
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKC_GATE_DISABLE_MASK 0x00000400L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKC_GATE_DISABLE__SHIFT 0x0000000a
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKD_GATE_DISABLE_MASK 0x00000800L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKD_GATE_DISABLE__SHIFT 0x0000000b
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKE_GATE_DISABLE_MASK 0x00001000L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKE_GATE_DISABLE__SHIFT 0x0000000c
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKF_GATE_DISABLE_MASK 0x00002000L
+#define DCCG_GATE_DISABLE_CNTL__SYMCLKF_GATE_DISABLE__SHIFT 0x0000000d
+#define DCCG_GTC_CNTL__DCCG_GTC_ENABLE_MASK 0x00000001L
+#define DCCG_GTC_CNTL__DCCG_GTC_ENABLE__SHIFT 0x00000000
+#define DCCG_GTC_CURRENT__DCCG_GTC_CURRENT_MASK 0xffffffffL
+#define DCCG_GTC_CURRENT__DCCG_GTC_CURRENT__SHIFT 0x00000000
+#define DCCG_GTC_DTO_MODULO__DCCG_GTC_DTO_MODULO_MASK 0xffffffffL
+#define DCCG_GTC_DTO_MODULO__DCCG_GTC_DTO_MODULO__SHIFT 0x00000000
+#define DCCG_PERFMON_CNTL__DCCG_PERF_CRTC_SEL_MASK 0x00000700L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_CRTC_SEL__SHIFT 0x00000008
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DISPCLK_ENABLE_MASK 0x00000001L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DISPCLK_ENABLE__SHIFT 0x00000000
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DPREFCLK_ENABLE_MASK 0x00000002L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_DPREFCLK_ENABLE__SHIFT 0x00000001
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_HSYNC_MASK 0x00000080L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_HSYNC__SHIFT 0x00000007
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_VSYNC_MASK 0x00000040L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_MODE_VSYNC__SHIFT 0x00000006
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK0_ENABLE_MASK 0x00000010L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK0_ENABLE__SHIFT 0x00000004
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK1_ENABLE_MASK 0x00000004L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK1_ENABLE__SHIFT 0x00000002
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK2_ENABLE_MASK 0x00000008L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_PIXCLK2_ENABLE__SHIFT 0x00000003
+#define DCCG_PERFMON_CNTL__DCCG_PERF_RUN_MASK 0x00000020L
+#define DCCG_PERFMON_CNTL__DCCG_PERF_RUN__SHIFT 0x00000005
+#define DCCG_SOFT_RESET__REFCLK_SOFT_RESET_MASK 0x00000001L
+#define DCCG_SOFT_RESET__REFCLK_SOFT_RESET__SHIFT 0x00000000
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_INV_MASK 0x00010000L
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_INV__SHIFT 0x00000010
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_SEL_MASK 0x000000ffL
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICA_SEL__SHIFT 0x00000000
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_INV_MASK 0x01000000L
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_INV__SHIFT 0x00000018
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_SEL_MASK 0x0000ff00L
+#define DCCG_TEST_CLK_SEL__DCCG_TEST_CLK_GENERICB_SEL__SHIFT 0x00000008
+#define DCCG_TEST_DEBUG_DATA__DCCG_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCCG_TEST_DEBUG_DATA__DCCG_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCCG_TEST_DEBUG_INDEX__DCCG_DBG_SEL_MASK 0x00001000L
+#define DCCG_TEST_DEBUG_INDEX__DCCG_DBG_SEL__SHIFT 0x0000000c
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCCG_TEST_DEBUG_INDEX__DCCG_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DCCG_VPCLK_CNTL__AZ_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCCG_VPCLK_CNTL__AZ_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCCG_VPCLK_CNTL__AZ_MEM_SHUTDOWN_DIS_MASK 0x04000000L
+#define DCCG_VPCLK_CNTL__AZ_MEM_SHUTDOWN_DIS__SHIFT 0x0000001a
+#define DCCG_VPCLK_CNTL__DCCG_VPCLK_POL_MASK 0x00000001L
+#define DCCG_VPCLK_CNTL__DCCG_VPCLK_POL__SHIFT 0x00000000
+#define DCCG_VPCLK_CNTL__DMCU_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCCG_VPCLK_CNTL__DMCU_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCCG_VPCLK_CNTL__DMCU_MEM_SHUTDOWN_DIS_MASK 0x00010000L
+#define DCCG_VPCLK_CNTL__DMCU_MEM_SHUTDOWN_DIS__SHIFT 0x00000010
+#define DCCG_VPCLK_CNTL__DMIF0_LIGHT_SLEEP_DIS_MASK 0x00000100L
+#define DCCG_VPCLK_CNTL__DMIF0_LIGHT_SLEEP_DIS__SHIFT 0x00000008
+#define DCCG_VPCLK_CNTL__DMIF0_MEM_SHUTDOWN_DIS_MASK 0x00100000L
+#define DCCG_VPCLK_CNTL__DMIF0_MEM_SHUTDOWN_DIS__SHIFT 0x00000014
+#define DCCG_VPCLK_CNTL__DMIF1_LIGHT_SLEEP_DIS_MASK 0x00000200L
+#define DCCG_VPCLK_CNTL__DMIF1_LIGHT_SLEEP_DIS__SHIFT 0x00000009
+#define DCCG_VPCLK_CNTL__DMIF1_MEM_SHUTDOWN_DIS_MASK 0x00200000L
+#define DCCG_VPCLK_CNTL__DMIF1_MEM_SHUTDOWN_DIS__SHIFT 0x00000015
+#define DCCG_VPCLK_CNTL__DMIF2_LIGHT_SLEEP_DIS_MASK 0x00000400L
+#define DCCG_VPCLK_CNTL__DMIF2_LIGHT_SLEEP_DIS__SHIFT 0x0000000a
+#define DCCG_VPCLK_CNTL__DMIF2_MEM_SHUTDOWN_DIS_MASK 0x00400000L
+#define DCCG_VPCLK_CNTL__DMIF2_MEM_SHUTDOWN_DIS__SHIFT 0x00000016
+#define DCCG_VPCLK_CNTL__DMIF3_LIGHT_SLEEP_DIS_MASK 0x00000800L
+#define DCCG_VPCLK_CNTL__DMIF3_LIGHT_SLEEP_DIS__SHIFT 0x0000000b
+#define DCCG_VPCLK_CNTL__DMIF3_MEM_SHUTDOWN_DIS_MASK 0x00800000L
+#define DCCG_VPCLK_CNTL__DMIF3_MEM_SHUTDOWN_DIS__SHIFT 0x00000017
+#define DCCG_VPCLK_CNTL__DMIF4_LIGHT_SLEEP_DIS_MASK 0x00001000L
+#define DCCG_VPCLK_CNTL__DMIF4_LIGHT_SLEEP_DIS__SHIFT 0x0000000c
+#define DCCG_VPCLK_CNTL__DMIF4_MEM_SHUTDOWN_DIS_MASK 0x01000000L
+#define DCCG_VPCLK_CNTL__DMIF4_MEM_SHUTDOWN_DIS__SHIFT 0x00000018
+#define DCCG_VPCLK_CNTL__DMIF5_LIGHT_SLEEP_DIS_MASK 0x00002000L
+#define DCCG_VPCLK_CNTL__DMIF5_LIGHT_SLEEP_DIS__SHIFT 0x0000000d
+#define DCCG_VPCLK_CNTL__DMIF5_MEM_SHUTDOWN_DIS_MASK 0x02000000L
+#define DCCG_VPCLK_CNTL__DMIF5_MEM_SHUTDOWN_DIS__SHIFT 0x00000019
+#define DCCG_VPCLK_CNTL__DMIF_XLR_LIGHT_SLEEP_MODE_FORCE_MASK 0x00000020L
+#define DCCG_VPCLK_CNTL__DMIF_XLR_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000005
+#define DCCG_VPCLK_CNTL__DMIF_XLR_MEM_SHUTDOWN_MODE_FORCE_MASK 0x00040000L
+#define DCCG_VPCLK_CNTL__DMIF_XLR_MEM_SHUTDOWN_MODE_FORCE__SHIFT 0x00000012
+#define DCCG_VPCLK_CNTL__FBC_LIGHT_SLEEP_DIS_MASK 0x00004000L
+#define DCCG_VPCLK_CNTL__FBC_LIGHT_SLEEP_DIS__SHIFT 0x0000000e
+#define DCCG_VPCLK_CNTL__FBC_MEM_SHUTDOWN_DIS_MASK 0x00080000L
+#define DCCG_VPCLK_CNTL__FBC_MEM_SHUTDOWN_DIS__SHIFT 0x00000013
+#define DCCG_VPCLK_CNTL__MCIF_LIGHT_SLEEP_MODE_FORCE_MASK 0x00000010L
+#define DCCG_VPCLK_CNTL__MCIF_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000004
+#define DCCG_VPCLK_CNTL__MCIF_MEM_SHUTDOWN_MODE_FORCE_MASK 0x00020000L
+#define DCCG_VPCLK_CNTL__MCIF_MEM_SHUTDOWN_MODE_FORCE__SHIFT 0x00000011
+#define DCCG_VPCLK_CNTL__VGA_LIGHT_SLEEP_MODE_FORCE_MASK 0x00000002L
+#define DCCG_VPCLK_CNTL__VGA_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000001
+#define DCCG_VPCLK_CNTL__VIP_LIGHT_SLEEP_DIS_MASK 0x00008000L
+#define DCCG_VPCLK_CNTL__VIP_LIGHT_SLEEP_DIS__SHIFT 0x0000000f
+#define DCDEBUG_BUS_CLK1_SEL__DCDEBUG_BUS_CLK1_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK1_SEL__DCDEBUG_BUS_CLK1_SEL__SHIFT 0x00000000
+#define DCDEBUG_BUS_CLK2_SEL__DCDEBUG_BUS_CLK2_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK2_SEL__DCDEBUG_BUS_CLK2_SEL__SHIFT 0x00000000
+#define DCDEBUG_BUS_CLK3_SEL__DCDEBUG_BUS_CLK3_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK3_SEL__DCDEBUG_BUS_CLK3_SEL__SHIFT 0x00000000
+#define DCDEBUG_BUS_CLK4_SEL__DCDEBUG_BUS_CLK4_SEL_MASK 0xffffffffL
+#define DCDEBUG_BUS_CLK4_SEL__DCDEBUG_BUS_CLK4_SEL__SHIFT 0x00000000
+#define DCDEBUG_OUT_CNTL__DCDEBUG_BLOCK_SEL_MASK 0x0000001fL
+#define DCDEBUG_OUT_CNTL__DCDEBUG_BLOCK_SEL__SHIFT 0x00000000
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_EN_MASK 0x00000020L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_EN__SHIFT 0x00000005
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_PIN_SEL_MASK 0x00000040L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_PIN_SEL__SHIFT 0x00000006
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_SEL_MASK 0x00300000L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_SEL__SHIFT 0x00000014
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA_EN_MASK 0x00000080L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA_EN__SHIFT 0x00000007
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA_MASK 0x000fff00L
+#define DCDEBUG_OUT_CNTL__DCDEBUG_OUT_TEST_DATA__SHIFT 0x00000008
+#define DCDEBUG_OUT_DATA__DCDEBUG_OUT_DATA_MASK 0xffffffffL
+#define DCDEBUG_OUT_DATA__DCDEBUG_OUT_DATA__SHIFT 0x00000000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_EN_MASK 0x00001000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_EN__SHIFT 0x0000000c
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_PIN_SEL_MASK 0x0000000fL
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_PIN_SEL__SHIFT 0x00000000
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_REGBIT_SEL_MASK 0x000001f0L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE1_REGBIT_SEL__SHIFT 0x00000004
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_EN_MASK 0x10000000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_EN__SHIFT 0x0000001c
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_PIN_SEL_MASK 0x000f0000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_PIN_SEL__SHIFT 0x00000010
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_REGBIT_SEL_MASK 0x01f00000L
+#define DCDEBUG_OUT_PIN_OVERRIDE__DCDEBUG_OUT_OVERRIDE2_REGBIT_SEL__SHIFT 0x00000014
+#define DC_DMCU_SCRATCH__DMCU_SCRATCH_MASK 0xffffffffL
+#define DC_DMCU_SCRATCH__DMCU_SCRATCH__SHIFT 0x00000000
+#define DC_DVODATA_CONFIG__DVO_ALTER_MAPPING_EN_MASK 0x00200000L
+#define DC_DVODATA_CONFIG__DVO_ALTER_MAPPING_EN__SHIFT 0x00000015
+#define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN_MASK 0x00100000L
+#define DC_DVODATA_CONFIG__VIP_ALTER_MAPPING_EN__SHIFT 0x00000014
+#define DC_DVODATA_CONFIG__VIP_MUX_EN_MASK 0x00080000L
+#define DC_DVODATA_CONFIG__VIP_MUX_EN__SHIFT 0x00000013
+#define DCFE0_SOFT_RESET__CRTC0_SOFT_RESET_MASK 0x00000010L
+#define DCFE0_SOFT_RESET__CRTC0_SOFT_RESET__SHIFT 0x00000004
+#define DCFE0_SOFT_RESET__DCP0_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE0_SOFT_RESET__DCP0_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE0_SOFT_RESET__DCP0_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE0_SOFT_RESET__DCP0_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE0_SOFT_RESET__SCL0_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE0_SOFT_RESET__SCL0_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE0_SOFT_RESET__SCL0_SOFT_RESET_MASK 0x00000008L
+#define DCFE0_SOFT_RESET__SCL0_SOFT_RESET__SHIFT 0x00000003
+#define DCFE1_SOFT_RESET__CRTC1_SOFT_RESET_MASK 0x00000010L
+#define DCFE1_SOFT_RESET__CRTC1_SOFT_RESET__SHIFT 0x00000004
+#define DCFE1_SOFT_RESET__DCP1_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE1_SOFT_RESET__DCP1_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE1_SOFT_RESET__DCP1_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE1_SOFT_RESET__DCP1_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE1_SOFT_RESET__SCL1_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE1_SOFT_RESET__SCL1_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE1_SOFT_RESET__SCL1_SOFT_RESET_MASK 0x00000008L
+#define DCFE1_SOFT_RESET__SCL1_SOFT_RESET__SHIFT 0x00000003
+#define DCFE2_SOFT_RESET__CRTC2_SOFT_RESET_MASK 0x00000010L
+#define DCFE2_SOFT_RESET__CRTC2_SOFT_RESET__SHIFT 0x00000004
+#define DCFE2_SOFT_RESET__DCP2_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE2_SOFT_RESET__DCP2_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE2_SOFT_RESET__DCP2_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE2_SOFT_RESET__DCP2_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE2_SOFT_RESET__SCL2_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE2_SOFT_RESET__SCL2_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE2_SOFT_RESET__SCL2_SOFT_RESET_MASK 0x00000008L
+#define DCFE2_SOFT_RESET__SCL2_SOFT_RESET__SHIFT 0x00000003
+#define DCFE3_SOFT_RESET__CRTC3_SOFT_RESET_MASK 0x00000010L
+#define DCFE3_SOFT_RESET__CRTC3_SOFT_RESET__SHIFT 0x00000004
+#define DCFE3_SOFT_RESET__DCP3_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE3_SOFT_RESET__DCP3_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE3_SOFT_RESET__DCP3_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE3_SOFT_RESET__DCP3_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE3_SOFT_RESET__SCL3_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE3_SOFT_RESET__SCL3_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE3_SOFT_RESET__SCL3_SOFT_RESET_MASK 0x00000008L
+#define DCFE3_SOFT_RESET__SCL3_SOFT_RESET__SHIFT 0x00000003
+#define DCFE4_SOFT_RESET__CRTC4_SOFT_RESET_MASK 0x00000010L
+#define DCFE4_SOFT_RESET__CRTC4_SOFT_RESET__SHIFT 0x00000004
+#define DCFE4_SOFT_RESET__DCP4_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE4_SOFT_RESET__DCP4_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE4_SOFT_RESET__DCP4_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE4_SOFT_RESET__DCP4_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE4_SOFT_RESET__SCL4_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE4_SOFT_RESET__SCL4_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE4_SOFT_RESET__SCL4_SOFT_RESET_MASK 0x00000008L
+#define DCFE4_SOFT_RESET__SCL4_SOFT_RESET__SHIFT 0x00000003
+#define DCFE5_SOFT_RESET__CRTC5_SOFT_RESET_MASK 0x00000010L
+#define DCFE5_SOFT_RESET__CRTC5_SOFT_RESET__SHIFT 0x00000004
+#define DCFE5_SOFT_RESET__DCP5_PIXPIPE_SOFT_RESET_MASK 0x00000001L
+#define DCFE5_SOFT_RESET__DCP5_PIXPIPE_SOFT_RESET__SHIFT 0x00000000
+#define DCFE5_SOFT_RESET__DCP5_REQ_SOFT_RESET_MASK 0x00000002L
+#define DCFE5_SOFT_RESET__DCP5_REQ_SOFT_RESET__SHIFT 0x00000001
+#define DCFE5_SOFT_RESET__SCL5_ALU_SOFT_RESET_MASK 0x00000004L
+#define DCFE5_SOFT_RESET__SCL5_ALU_SOFT_RESET__SHIFT 0x00000002
+#define DCFE5_SOFT_RESET__SCL5_SOFT_RESET_MASK 0x00000008L
+#define DCFE5_SOFT_RESET__SCL5_SOFT_RESET__SHIFT 0x00000003
+#define DCFE_DBG_SEL__DCFE_DBG_SEL_MASK 0x0000000fL
+#define DCFE_DBG_SEL__DCFE_DBG_SEL__SHIFT 0x00000000
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_MEM_PWR_STATE_MASK 0x00000300L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_CURSOR_MEM_PWR_STATE__SHIFT 0x00000008
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_MEM_PWR_STATE_MASK 0x00003000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__DCP_LUT_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB1_MEM_SHUTDOWN_DIS_MASK 0x20000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB1_MEM_SHUTDOWN_DIS__SHIFT 0x0000001d
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB2_MEM_SHUTDOWN_DIS_MASK 0x40000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB2_MEM_SHUTDOWN_DIS__SHIFT 0x0000001e
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_LIGHT_SLEEP_DIS_MASK 0x00000010L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_LIGHT_SLEEP_DIS__SHIFT 0x00000004
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_0_MASK 0x00030000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_0__SHIFT 0x00000010
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_1_MASK 0x00c00000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_1__SHIFT 0x00000016
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_2_MASK 0x03000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__LB_MEM_PWR_STATE_2__SHIFT 0x00000018
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__OVLSCL_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__PIPE_MEM_SHUTDOWN_DIS_MASK 0x10000000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__PIPE_MEM_SHUTDOWN_DIS__SHIFT 0x0000001c
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_LIGHT_SLEEP_DIS_MASK 0x00000040L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_LIGHT_SLEEP_DIS__SHIFT 0x00000006
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_MEM_PWR_STATE_MASK 0x00300000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__REGAMMA_LUT_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_LIGHT_SLEEP_DIS_MASK 0x00000020L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_LIGHT_SLEEP_DIS__SHIFT 0x00000005
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCFE_MEM_LIGHT_SLEEP_CNTL__SCL_MEM_PWR_STATE__SHIFT 0x00000012
+#define DC_GENERICA__GENERICA_EN_MASK 0x00000001L
+#define DC_GENERICA__GENERICA_EN__SHIFT 0x00000000
+#define DC_GENERICA__GENERICA_SEL_MASK 0x00000f00L
+#define DC_GENERICA__GENERICA_SEL__SHIFT 0x00000008
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_DIV2_SEL_MASK 0x07000000L
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_DIV2_SEL__SHIFT 0x00000018
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_SEL_MASK 0x00070000L
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_CLK_SEL__SHIFT 0x00000010
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_SSC_CLK_SEL_MASK 0x00700000L
+#define DC_GENERICA__GENERICA_UNIPHY_FBDIV_SSC_CLK_SEL__SHIFT 0x00000014
+#define DC_GENERICA__GENERICA_UNIPHY_REFDIV_CLK_SEL_MASK 0x00007000L
+#define DC_GENERICA__GENERICA_UNIPHY_REFDIV_CLK_SEL__SHIFT 0x0000000c
+#define DC_GENERICB__GENERICB_EN_MASK 0x00000001L
+#define DC_GENERICB__GENERICB_EN__SHIFT 0x00000000
+#define DC_GENERICB__GENERICB_SEL_MASK 0x00000f00L
+#define DC_GENERICB__GENERICB_SEL__SHIFT 0x00000008
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_DIV2_SEL_MASK 0x07000000L
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_DIV2_SEL__SHIFT 0x00000018
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_SEL_MASK 0x00070000L
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_CLK_SEL__SHIFT 0x00000010
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_SSC_CLK_SEL_MASK 0x00700000L
+#define DC_GENERICB__GENERICB_UNIPHY_FBDIV_SSC_CLK_SEL__SHIFT 0x00000014
+#define DC_GENERICB__GENERICB_UNIPHY_REFDIV_CLK_SEL_MASK 0x00007000L
+#define DC_GENERICB__GENERICB_UNIPHY_REFDIV_CLK_SEL__SHIFT 0x0000000c
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC1_EN__DC_GPIO_DDC1DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC1_MASK__ALLOW_HW_DDC1_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC1_MASK__ALLOW_HW_DDC1_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC1_MASK__AUX1_POL_MASK 0x00100000L
+#define DC_GPIO_DDC1_MASK__AUX1_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC1_MASK__AUX_PAD1_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC1_MASK__AUX_PAD1_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC1_MASK__DC_GPIO_DDC1DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC1_Y__DC_GPIO_DDC1DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC2_A__DC_GPIO_DDC2DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC2_EN__DC_GPIO_DDC2DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC2_MASK__ALLOW_HW_DDC2_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC2_MASK__ALLOW_HW_DDC2_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC2_MASK__AUX2_POL_MASK 0x00100000L
+#define DC_GPIO_DDC2_MASK__AUX2_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC2_MASK__AUX_PAD2_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC2_MASK__AUX_PAD2_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC2_MASK__DC_GPIO_DDC2DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC2_Y__DC_GPIO_DDC2DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC3_A__DC_GPIO_DDC3DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC3_EN__DC_GPIO_DDC3DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC3_MASK__ALLOW_HW_DDC3_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC3_MASK__ALLOW_HW_DDC3_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC3_MASK__AUX3_POL_MASK 0x00100000L
+#define DC_GPIO_DDC3_MASK__AUX3_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC3_MASK__AUX_PAD3_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC3_MASK__AUX_PAD3_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC3_MASK__DC_GPIO_DDC3DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC3_Y__DC_GPIO_DDC3DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC4_A__DC_GPIO_DDC4DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC4_EN__DC_GPIO_DDC4DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC4_MASK__ALLOW_HW_DDC4_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC4_MASK__ALLOW_HW_DDC4_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC4_MASK__AUX4_POL_MASK 0x00100000L
+#define DC_GPIO_DDC4_MASK__AUX4_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC4_MASK__AUX_PAD4_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC4_MASK__AUX_PAD4_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC4_MASK__DC_GPIO_DDC4DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC4_Y__DC_GPIO_DDC4DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC5_A__DC_GPIO_DDC5DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC5_EN__DC_GPIO_DDC5DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC5_MASK__ALLOW_HW_DDC5_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC5_MASK__ALLOW_HW_DDC5_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC5_MASK__AUX5_POL_MASK 0x00100000L
+#define DC_GPIO_DDC5_MASK__AUX5_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC5_MASK__AUX_PAD5_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC5_MASK__AUX_PAD5_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC5_MASK__DC_GPIO_DDC5DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC5_Y__DC_GPIO_DDC5DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A_MASK 0x00000001L
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6CLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A_MASK 0x00000100L
+#define DC_GPIO_DDC6_A__DC_GPIO_DDC6DATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDC6_EN__DC_GPIO_DDC6DATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDC6_MASK__ALLOW_HW_DDC6_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDC6_MASK__ALLOW_HW_DDC6_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDC6_MASK__AUX6_POL_MASK 0x00100000L
+#define DC_GPIO_DDC6_MASK__AUX6_POL__SHIFT 0x00000014
+#define DC_GPIO_DDC6_MASK__AUX_PAD6_MODE_MASK 0x00010000L
+#define DC_GPIO_DDC6_MASK__AUX_PAD6_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN_MASK 0x00000010L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_PD_EN__SHIFT 0x00000004
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6CLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDC6_MASK__DC_GPIO_DDC6DATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDC6_Y__DC_GPIO_DDC6DATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGACLK_A__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_A__DC_GPIO_DDCVGADATA_A__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGACLK_EN__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_EN__DC_GPIO_DDCVGADATA_EN__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_MASK__ALLOW_HW_DDCVGA_PD_EN_MASK 0x00400000L
+#define DC_GPIO_DDCVGA_MASK__ALLOW_HW_DDCVGA_PD_EN__SHIFT 0x00000016
+#define DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE_MASK 0x00010000L
+#define DC_GPIO_DDCVGA_MASK__AUX_PADVGA_MODE__SHIFT 0x00000010
+#define DC_GPIO_DDCVGA_MASK__AUXVGA_POL_MASK 0x00100000L
+#define DC_GPIO_DDCVGA_MASK__AUXVGA_POL__SHIFT 0x00000014
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV_MASK 0x00000040L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_RECV__SHIFT 0x00000006
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR_MASK 0x0f000000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGACLK_STR__SHIFT 0x00000018
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_MASK__SHIFT 0x00000008
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN_MASK 0x00001000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_PD_EN__SHIFT 0x0000000c
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV_MASK 0x00004000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_STR_MASK 0xf0000000L
+#define DC_GPIO_DDCVGA_MASK__DC_GPIO_DDCVGADATA_STR__SHIFT 0x0000001c
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y_MASK 0x00000001L
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGACLK_Y__SHIFT 0x00000000
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y_MASK 0x00000100L
+#define DC_GPIO_DDCVGA_Y__DC_GPIO_DDCVGADATA_Y__SHIFT 0x00000008
+#define DC_GPIO_DEBUG__DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL_MASK 0x00010000L
+#define DC_GPIO_DEBUG__DC_GPIO_CHIP_DEBUG_OUT_PIN_SEL__SHIFT 0x00000010
+#define DC_GPIO_DEBUG__DC_GPIO_MACRO_DEBUG_MASK 0x00000300L
+#define DC_GPIO_DEBUG__DC_GPIO_MACRO_DEBUG__SHIFT 0x00000008
+#define DC_GPIO_DEBUG__DC_GPIO_VIP_DEBUG_MASK 0x00000001L
+#define DC_GPIO_DEBUG__DC_GPIO_VIP_DEBUG__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCLK_A_MASK 0x10000000L
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCLK_A__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCNTL_A_MASK 0x07000000L
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVOCNTL_A__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVODATA_A_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_A__DC_GPIO_DVODATA_A__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_A__DC_GPIO_MVP_DVOCNTL_A_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_A__DC_GPIO_MVP_DVOCNTL_A__SHIFT 0x0000001e
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCLK_EN_MASK 0x10000000L
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCLK_EN__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCNTL_EN_MASK 0x07000000L
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVOCNTL_EN__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVODATA_EN_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_EN__DC_GPIO_DVODATA_EN__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_EN__DC_GPIO_MVP_DVOCNTL_EN_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_EN__DC_GPIO_MVP_DVOCNTL_EN__SHIFT 0x0000001e
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCLK_MASK_MASK 0x10000000L
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCLK_MASK__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCNTL_MASK_MASK 0x07000000L
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVOCNTL_MASK__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVODATA_MASK_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_DVODATA_MASK__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_MVP_DVOCNTL_MASK_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_MASK__DC_GPIO_MVP_DVOCNTL_MASK__SHIFT 0x0000001e
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCLK_Y_MASK 0x10000000L
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCLK_Y__SHIFT 0x0000001c
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCNTL_Y_MASK 0x07000000L
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVOCNTL_Y__SHIFT 0x00000018
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVODATA_Y_MASK 0x00ffffffL
+#define DC_GPIO_DVODATA_Y__DC_GPIO_DVODATA_Y__SHIFT 0x00000000
+#define DC_GPIO_DVODATA_Y__DC_GPIO_MVP_DVOCNTL_Y_MASK 0xc0000000L
+#define DC_GPIO_DVODATA_Y__DC_GPIO_MVP_DVOCNTL_Y__SHIFT 0x0000001e
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A_MASK 0x00000001L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICA_A__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A_MASK 0x00000100L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICB_A__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A_MASK 0x00010000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICC_A__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A_MASK 0x00100000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICD_A__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A_MASK 0x00200000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICE_A__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A_MASK 0x00400000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICF_A__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A_MASK 0x00800000L
+#define DC_GPIO_GENERIC_A__DC_GPIO_GENERICG_A__SHIFT 0x00000017
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICA_EN_MASK 0x00000001L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICA_EN__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICB_EN_MASK 0x00000100L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICB_EN__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICC_EN_MASK 0x00010000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICC_EN__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICD_EN_MASK 0x00100000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICD_EN__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICE_EN_MASK 0x00200000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICE_EN__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICF_EN_MASK 0x00400000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICF_EN__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICG_EN_MASK 0x00800000L
+#define DC_GPIO_GENERIC_EN__DC_GPIO_GENERICG_EN__SHIFT 0x00000017
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_MASK_MASK 0x00000001L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_MASK__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_PD_DIS_MASK 0x00000002L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_PD_DIS__SHIFT 0x00000001
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV_MASK 0x00000004L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICA_RECV__SHIFT 0x00000002
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_MASK_MASK 0x00000010L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_MASK__SHIFT 0x00000004
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_PD_DIS_MASK 0x00000020L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_PD_DIS__SHIFT 0x00000005
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV_MASK 0x00000040L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICB_RECV__SHIFT 0x00000006
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_MASK_MASK 0x00000100L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_MASK__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_PD_DIS_MASK 0x00000200L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_PD_DIS__SHIFT 0x00000009
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV_MASK 0x00000400L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICC_RECV__SHIFT 0x0000000a
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_MASK_MASK 0x00001000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_MASK__SHIFT 0x0000000c
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_PD_DIS_MASK 0x00002000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_PD_DIS__SHIFT 0x0000000d
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV_MASK 0x00004000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICD_RECV__SHIFT 0x0000000e
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_MASK_MASK 0x00010000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_MASK__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_PD_DIS_MASK 0x00020000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_PD_DIS__SHIFT 0x00000011
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV_MASK 0x00040000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICE_RECV__SHIFT 0x00000012
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_MASK_MASK 0x00100000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_MASK__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_PD_DIS_MASK 0x00200000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_PD_DIS__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV_MASK 0x00400000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICF_RECV__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_MASK_MASK 0x01000000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_MASK__SHIFT 0x00000018
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_PD_DIS_MASK 0x02000000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_PD_DIS__SHIFT 0x00000019
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV_MASK 0x04000000L
+#define DC_GPIO_GENERIC_MASK__DC_GPIO_GENERICG_RECV__SHIFT 0x0000001a
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICA_Y_MASK 0x00000001L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICA_Y__SHIFT 0x00000000
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICB_Y_MASK 0x00000100L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICB_Y__SHIFT 0x00000008
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICC_Y_MASK 0x00010000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICC_Y__SHIFT 0x00000010
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICD_Y_MASK 0x00100000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICD_Y__SHIFT 0x00000014
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICE_Y_MASK 0x00200000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICE_Y__SHIFT 0x00000015
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICF_Y_MASK 0x00400000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICF_Y__SHIFT 0x00000016
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICG_Y_MASK 0x00800000L
+#define DC_GPIO_GENERIC_Y__DC_GPIO_GENERICG_Y__SHIFT 0x00000017
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A_MASK 0x00000001L
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_CLK_A__SHIFT 0x00000000
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A_MASK 0x00000100L
+#define DC_GPIO_GENLK_A__DC_GPIO_GENLK_VSYNC_A__SHIFT 0x00000008
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A_MASK 0x00010000L
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_A_A__SHIFT 0x00000010
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A_MASK 0x01000000L
+#define DC_GPIO_GENLK_A__DC_GPIO_SWAPLOCK_B_A__SHIFT 0x00000018
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_CLK_EN_MASK 0x00000001L
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_CLK_EN__SHIFT 0x00000000
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_VSYNC_EN_MASK 0x00000100L
+#define DC_GPIO_GENLK_EN__DC_GPIO_GENLK_VSYNC_EN__SHIFT 0x00000008
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_A_EN_MASK 0x00010000L
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_A_EN__SHIFT 0x00000010
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_B_EN_MASK 0x01000000L
+#define DC_GPIO_GENLK_EN__DC_GPIO_SWAPLOCK_B_EN__SHIFT 0x00000018
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_MASK_MASK 0x00000001L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_MASK__SHIFT 0x00000000
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PD_DIS_MASK 0x00000002L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PD_DIS__SHIFT 0x00000001
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PU_EN_MASK 0x00000008L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_PU_EN__SHIFT 0x00000003
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV_MASK 0x00000004L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_CLK_RECV__SHIFT 0x00000002
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_MASK_MASK 0x00000100L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_MASK__SHIFT 0x00000008
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PD_DIS_MASK 0x00000200L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PD_DIS__SHIFT 0x00000009
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PU_EN_MASK 0x00000800L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_PU_EN__SHIFT 0x0000000b
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV_MASK 0x00000400L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_GENLK_VSYNC_RECV__SHIFT 0x0000000a
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_MASK_MASK 0x00010000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_MASK__SHIFT 0x00000010
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PD_DIS_MASK 0x00020000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PD_DIS__SHIFT 0x00000011
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PU_EN_MASK 0x00080000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_PU_EN__SHIFT 0x00000013
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV_MASK 0x00040000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_A_RECV__SHIFT 0x00000012
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_MASK_MASK 0x01000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_MASK__SHIFT 0x00000018
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PD_DIS_MASK 0x02000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PD_DIS__SHIFT 0x00000019
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PU_EN_MASK 0x08000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_PU_EN__SHIFT 0x0000001b
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV_MASK 0x04000000L
+#define DC_GPIO_GENLK_MASK__DC_GPIO_SWAPLOCK_B_RECV__SHIFT 0x0000001a
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_CLK_Y_MASK 0x00000001L
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_CLK_Y__SHIFT 0x00000000
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_VSYNC_Y_MASK 0x00000100L
+#define DC_GPIO_GENLK_Y__DC_GPIO_GENLK_VSYNC_Y__SHIFT 0x00000008
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_A_Y_MASK 0x00010000L
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_A_Y__SHIFT 0x00000010
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_B_Y_MASK 0x01000000L
+#define DC_GPIO_GENLK_Y__DC_GPIO_SWAPLOCK_B_Y__SHIFT 0x00000018
+#define DC_GPIO_HPD_A__DC_GPIO_HPD1_A_MASK 0x00000001L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD1_A__SHIFT 0x00000000
+#define DC_GPIO_HPD_A__DC_GPIO_HPD2_A_MASK 0x00000100L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD2_A__SHIFT 0x00000008
+#define DC_GPIO_HPD_A__DC_GPIO_HPD3_A_MASK 0x00010000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD3_A__SHIFT 0x00000010
+#define DC_GPIO_HPD_A__DC_GPIO_HPD4_A_MASK 0x01000000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD4_A__SHIFT 0x00000018
+#define DC_GPIO_HPD_A__DC_GPIO_HPD5_A_MASK 0x04000000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD5_A__SHIFT 0x0000001a
+#define DC_GPIO_HPD_A__DC_GPIO_HPD6_A_MASK 0x10000000L
+#define DC_GPIO_HPD_A__DC_GPIO_HPD6_A__SHIFT 0x0000001c
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN_MASK 0x00000001L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD1_EN__SHIFT 0x00000000
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN_MASK 0x00000100L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD2_EN__SHIFT 0x00000008
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN_MASK 0x00010000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD3_EN__SHIFT 0x00000010
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN_MASK 0x01000000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD4_EN__SHIFT 0x00000018
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN_MASK 0x04000000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD5_EN__SHIFT 0x0000001a
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN_MASK 0x10000000L
+#define DC_GPIO_HPD_EN__DC_GPIO_HPD6_EN__SHIFT 0x0000001c
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK_MASK 0x00000001L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_MASK__SHIFT 0x00000000
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_PD_DIS_MASK 0x00000010L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_PD_DIS__SHIFT 0x00000004
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV_MASK 0x00000040L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD1_RECV__SHIFT 0x00000006
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK_MASK 0x00000100L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_MASK__SHIFT 0x00000008
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_PD_DIS_MASK 0x00000200L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_PD_DIS__SHIFT 0x00000009
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV_MASK 0x00000400L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD2_RECV__SHIFT 0x0000000a
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK_MASK 0x00010000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_MASK__SHIFT 0x00000010
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_PD_DIS_MASK 0x00020000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_PD_DIS__SHIFT 0x00000011
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV_MASK 0x00040000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD3_RECV__SHIFT 0x00000012
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK_MASK 0x00100000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_MASK__SHIFT 0x00000014
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_PD_DIS_MASK 0x00200000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_PD_DIS__SHIFT 0x00000015
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV_MASK 0x00400000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD4_RECV__SHIFT 0x00000016
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK_MASK 0x01000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_MASK__SHIFT 0x00000018
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_PD_DIS_MASK 0x02000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_PD_DIS__SHIFT 0x00000019
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV_MASK 0x04000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD5_RECV__SHIFT 0x0000001a
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK_MASK 0x10000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_MASK__SHIFT 0x0000001c
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_PD_DIS_MASK 0x20000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_PD_DIS__SHIFT 0x0000001d
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV_MASK 0x40000000L
+#define DC_GPIO_HPD_MASK__DC_GPIO_HPD6_RECV__SHIFT 0x0000001e
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y_MASK 0x00000001L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD1_Y__SHIFT 0x00000000
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y_MASK 0x00000100L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD2_Y__SHIFT 0x00000008
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y_MASK 0x00010000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD3_Y__SHIFT 0x00000010
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y_MASK 0x01000000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD4_Y__SHIFT 0x00000018
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y_MASK 0x04000000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD5_Y__SHIFT 0x0000001a
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y_MASK 0x10000000L
+#define DC_GPIO_HPD_Y__DC_GPIO_HPD6_Y__SHIFT 0x0000001c
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SCL_A__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_A__DC_GPIO_SDA_A__SHIFT 0x00000001
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SCL_EN__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_EN__DC_GPIO_SDA_EN__SHIFT 0x00000001
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_MASK__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_PD_DIS__SHIFT 0x00000001
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV_MASK 0x00000004L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SCL_RECV__SHIFT 0x00000002
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK_MASK 0x00000010L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_MASK__SHIFT 0x00000004
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS_MASK 0x00000020L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_PD_DIS__SHIFT 0x00000005
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV_MASK 0x00000040L
+#define DC_GPIO_I2CPAD_MASK__DC_GPIO_SDA_RECV__SHIFT 0x00000006
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SN_MASK 0x0000000fL
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SN__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SP_MASK 0x000000f0L
+#define DC_GPIO_I2CPAD_STRENGTH__I2C_STRENGTH_SP__SHIFT 0x00000004
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y_MASK 0x00000001L
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SCL_Y__SHIFT 0x00000000
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y_MASK 0x00000002L
+#define DC_GPIO_I2CPAD_Y__DC_GPIO_SDA_Y__SHIFT 0x00000001
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SN_MASK 0x0000000fL
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SN__SHIFT 0x00000000
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK 0x000000f0L
+#define DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT 0x00000004
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SN_MASK 0x0f000000L
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SN__SHIFT 0x00000018
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SP_MASK 0xf0000000L
+#define DC_GPIO_PAD_STRENGTH_1__SYNC_STRENGTH_SP__SHIFT 0x0000001c
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SN_MASK 0x000f0000L
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SN__SHIFT 0x00000010
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SP_MASK 0x00f00000L
+#define DC_GPIO_PAD_STRENGTH_2__PWRSEQ_STRENGTH_SP__SHIFT 0x00000014
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SN_MASK 0x0000000fL
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SN__SHIFT 0x00000000
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SP_MASK 0x000000f0L
+#define DC_GPIO_PAD_STRENGTH_2__STRENGTH_SP__SHIFT 0x00000004
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_BLON_A_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_BLON_A__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_DIGON_A_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_DIGON_A__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_ENA_BL_A_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_A__DC_GPIO_ENA_BL_A__SHIFT 0x00000010
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_BLON_EN_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_BLON_EN__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_DIGON_EN_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_DIGON_EN__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_ENA_BL_EN_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_ENA_BL_EN__SHIFT 0x00000010
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VARY_BL_GENERICA_EN_MASK 0x00000002L
+#define DC_GPIO_PWRSEQ_EN__DC_GPIO_VARY_BL_GENERICA_EN__SHIFT 0x00000001
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_MASK_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_MASK__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_PD_DIS_MASK 0x00000010L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_PD_DIS__SHIFT 0x00000004
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV_MASK 0x00000040L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_BLON_RECV__SHIFT 0x00000006
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_MASK_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_MASK__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_PD_DIS_MASK 0x00001000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_PD_DIS__SHIFT 0x0000000c
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV_MASK 0x00004000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_DIGON_RECV__SHIFT 0x0000000e
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_MASK_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_MASK__SHIFT 0x00000010
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_PD_DIS_MASK 0x00100000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_PD_DIS__SHIFT 0x00000014
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV_MASK 0x00400000L
+#define DC_GPIO_PWRSEQ_MASK__DC_GPIO_ENA_BL_RECV__SHIFT 0x00000016
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_BLON_Y_MASK 0x00000001L
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_BLON_Y__SHIFT 0x00000000
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_DIGON_Y_MASK 0x00000100L
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_DIGON_Y__SHIFT 0x00000008
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_ENA_BL_Y_MASK 0x00010000L
+#define DC_GPIO_PWRSEQ_Y__DC_GPIO_ENA_BL_Y__SHIFT 0x00000010
+#define DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A_MASK 0x00000001L
+#define DC_GPIO_SYNCA_A__DC_GPIO_HSYNCA_A__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A_MASK 0x00000100L
+#define DC_GPIO_SYNCA_A__DC_GPIO_VSYNCA_A__SHIFT 0x00000008
+#define DC_GPIO_SYNCA_EN__DC_GPIO_HSYNCA_EN_MASK 0x00000001L
+#define DC_GPIO_SYNCA_EN__DC_GPIO_HSYNCA_EN__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_EN__DC_GPIO_VSYNCA_EN_MASK 0x00000100L
+#define DC_GPIO_SYNCA_EN__DC_GPIO_VSYNCA_EN__SHIFT 0x00000008
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_CRTC_HSYNC_MASK_MASK 0x07000000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_CRTC_HSYNC_MASK__SHIFT 0x00000018
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_MASK_MASK 0x00000001L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_MASK__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_PD_DIS_MASK 0x00000010L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_PD_DIS__SHIFT 0x00000004
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV_MASK 0x00000040L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_HSYNCA_RECV__SHIFT 0x00000006
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_CRTC_VSYNC_MASK_MASK 0x70000000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_CRTC_VSYNC_MASK__SHIFT 0x0000001c
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_MASK_MASK 0x00000100L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_MASK__SHIFT 0x00000008
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_PD_DIS_MASK 0x00001000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_PD_DIS__SHIFT 0x0000000c
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV_MASK 0x00004000L
+#define DC_GPIO_SYNCA_MASK__DC_GPIO_VSYNCA_RECV__SHIFT 0x0000000e
+#define DC_GPIO_SYNCA_Y__DC_GPIO_HSYNCA_Y_MASK 0x00000001L
+#define DC_GPIO_SYNCA_Y__DC_GPIO_HSYNCA_Y__SHIFT 0x00000000
+#define DC_GPIO_SYNCA_Y__DC_GPIO_VSYNCA_Y_MASK 0x00000100L
+#define DC_GPIO_SYNCA_Y__DC_GPIO_VSYNCA_Y__SHIFT 0x00000008
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_READ_SELECT_MASK 0x0000003fL
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_READ_SELECT__SHIFT 0x00000000
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D1_VSYNC_NOM_MASK 0x00000700L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D1_VSYNC_NOM__SHIFT 0x00000008
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D2_VSYNC_NOM_MASK 0x00003800L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D2_VSYNC_NOM__SHIFT 0x0000000b
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D3_VSYNC_NOM_MASK 0x0001c000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D3_VSYNC_NOM__SHIFT 0x0000000e
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D4_VSYNC_NOM_MASK 0x000e0000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D4_VSYNC_NOM__SHIFT 0x00000011
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D5_VSYNC_NOM_MASK 0x00700000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D5_VSYNC_NOM__SHIFT 0x00000014
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D6_VSYNC_NOM_MASK 0x03800000L
+#define DC_GPU_TIMER_READ_CNTL__DC_GPU_TIMER_START_POSITION_D6_VSYNC_NOM__SHIFT 0x00000017
+#define DC_GPU_TIMER_READ__DC_GPU_TIMER_READ_MASK 0xffffffffL
+#define DC_GPU_TIMER_READ__DC_GPU_TIMER_READ__SHIFT 0x00000000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D1_P_FLIP_MASK 0x00000007L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D1_P_FLIP__SHIFT 0x00000000
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D2_P_FLIP_MASK 0x00000070L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D2_P_FLIP__SHIFT 0x00000004
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D3_P_FLIP_MASK 0x00000700L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D3_P_FLIP__SHIFT 0x00000008
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D4_P_FLIP_MASK 0x00007000L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D4_P_FLIP__SHIFT 0x0000000c
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D5_P_FLIP_MASK 0x00070000L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D5_P_FLIP__SHIFT 0x00000010
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D6_P_FLIP_MASK 0x00700000L
+#define DC_GPU_TIMER_START_POSITION_P_FLIP__DC_GPU_TIMER_START_POSITION_D6_P_FLIP__SHIFT 0x00000014
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D1_V_UPDATE_MASK 0x00000007L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D1_V_UPDATE__SHIFT 0x00000000
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D2_V_UPDATE_MASK 0x00000070L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D2_V_UPDATE__SHIFT 0x00000004
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D3_V_UPDATE_MASK 0x00000700L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D3_V_UPDATE__SHIFT 0x00000008
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D4_V_UPDATE_MASK 0x00007000L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D4_V_UPDATE__SHIFT 0x0000000c
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D5_V_UPDATE_MASK 0x00070000L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D5_V_UPDATE__SHIFT 0x00000010
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D6_V_UPDATE_MASK 0x00700000L
+#define DC_GPU_TIMER_START_POSITION_V_UPDATE__DC_GPU_TIMER_START_POSITION_D6_V_UPDATE__SHIFT 0x00000014
+#define DC_HPD1_CONTROL__DC_HPD1_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD1_CONTROL__DC_HPD1_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD1_CONTROL__DC_HPD1_EN_MASK 0x10000000L
+#define DC_HPD1_CONTROL__DC_HPD1_EN__SHIFT 0x0000001c
+#define DC_HPD1_CONTROL__DC_HPD1_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD1_CONTROL__DC_HPD1_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD1_FAST_TRAIN_CNTL__DC_HPD1_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK 0x00000001L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK__SHIFT 0x00000000
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK 0x00010000L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN__SHIFT 0x00000010
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD1_INT_STATUS__DC_HPD1_INT_STATUS_MASK 0x00000001L
+#define DC_HPD1_INT_STATUS__DC_HPD1_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD1_INT_STATUS__DC_HPD1_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD1_INT_STATUS__DC_HPD1_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE_MASK 0x00000002L
+#define DC_HPD1_INT_STATUS__DC_HPD1_SENSE__SHIFT 0x00000001
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD1_INT_STATUS__DC_HPD1_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD1_TOGGLE_FILT_CNTL__DC_HPD1_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD2_CONTROL__DC_HPD2_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD2_CONTROL__DC_HPD2_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD2_CONTROL__DC_HPD2_EN_MASK 0x10000000L
+#define DC_HPD2_CONTROL__DC_HPD2_EN__SHIFT 0x0000001c
+#define DC_HPD2_CONTROL__DC_HPD2_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD2_CONTROL__DC_HPD2_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD2_FAST_TRAIN_CNTL__DC_HPD2_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_ACK_MASK 0x00000001L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_ACK__SHIFT 0x00000000
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_EN_MASK 0x00010000L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_EN__SHIFT 0x00000010
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD2_INT_CONTROL__DC_HPD2_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD2_INT_STATUS__DC_HPD2_INT_STATUS_MASK 0x00000001L
+#define DC_HPD2_INT_STATUS__DC_HPD2_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD2_INT_STATUS__DC_HPD2_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD2_INT_STATUS__DC_HPD2_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE_MASK 0x00000002L
+#define DC_HPD2_INT_STATUS__DC_HPD2_SENSE__SHIFT 0x00000001
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD2_INT_STATUS__DC_HPD2_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD2_TOGGLE_FILT_CNTL__DC_HPD2_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD3_CONTROL__DC_HPD3_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD3_CONTROL__DC_HPD3_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD3_CONTROL__DC_HPD3_EN_MASK 0x10000000L
+#define DC_HPD3_CONTROL__DC_HPD3_EN__SHIFT 0x0000001c
+#define DC_HPD3_CONTROL__DC_HPD3_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD3_CONTROL__DC_HPD3_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD3_FAST_TRAIN_CNTL__DC_HPD3_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_ACK_MASK 0x00000001L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_ACK__SHIFT 0x00000000
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_EN_MASK 0x00010000L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_EN__SHIFT 0x00000010
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD3_INT_CONTROL__DC_HPD3_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD3_INT_STATUS__DC_HPD3_INT_STATUS_MASK 0x00000001L
+#define DC_HPD3_INT_STATUS__DC_HPD3_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD3_INT_STATUS__DC_HPD3_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD3_INT_STATUS__DC_HPD3_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE_MASK 0x00000002L
+#define DC_HPD3_INT_STATUS__DC_HPD3_SENSE__SHIFT 0x00000001
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD3_INT_STATUS__DC_HPD3_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD3_TOGGLE_FILT_CNTL__DC_HPD3_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD4_CONTROL__DC_HPD4_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD4_CONTROL__DC_HPD4_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD4_CONTROL__DC_HPD4_EN_MASK 0x10000000L
+#define DC_HPD4_CONTROL__DC_HPD4_EN__SHIFT 0x0000001c
+#define DC_HPD4_CONTROL__DC_HPD4_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD4_CONTROL__DC_HPD4_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD4_FAST_TRAIN_CNTL__DC_HPD4_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_ACK_MASK 0x00000001L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_ACK__SHIFT 0x00000000
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_EN_MASK 0x00010000L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_EN__SHIFT 0x00000010
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD4_INT_CONTROL__DC_HPD4_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD4_INT_STATUS__DC_HPD4_INT_STATUS_MASK 0x00000001L
+#define DC_HPD4_INT_STATUS__DC_HPD4_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD4_INT_STATUS__DC_HPD4_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD4_INT_STATUS__DC_HPD4_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE_MASK 0x00000002L
+#define DC_HPD4_INT_STATUS__DC_HPD4_SENSE__SHIFT 0x00000001
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD4_INT_STATUS__DC_HPD4_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD4_TOGGLE_FILT_CNTL__DC_HPD4_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD5_CONTROL__DC_HPD5_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD5_CONTROL__DC_HPD5_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD5_CONTROL__DC_HPD5_EN_MASK 0x10000000L
+#define DC_HPD5_CONTROL__DC_HPD5_EN__SHIFT 0x0000001c
+#define DC_HPD5_CONTROL__DC_HPD5_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD5_CONTROL__DC_HPD5_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD5_FAST_TRAIN_CNTL__DC_HPD5_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_ACK_MASK 0x00000001L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_ACK__SHIFT 0x00000000
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_EN_MASK 0x00010000L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_EN__SHIFT 0x00000010
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD5_INT_CONTROL__DC_HPD5_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD5_INT_STATUS__DC_HPD5_INT_STATUS_MASK 0x00000001L
+#define DC_HPD5_INT_STATUS__DC_HPD5_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD5_INT_STATUS__DC_HPD5_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD5_INT_STATUS__DC_HPD5_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE_MASK 0x00000002L
+#define DC_HPD5_INT_STATUS__DC_HPD5_SENSE__SHIFT 0x00000001
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD5_INT_STATUS__DC_HPD5_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD5_TOGGLE_FILT_CNTL__DC_HPD5_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_HPD6_CONTROL__DC_HPD6_CONNECTION_TIMER_MASK 0x00001fffL
+#define DC_HPD6_CONTROL__DC_HPD6_CONNECTION_TIMER__SHIFT 0x00000000
+#define DC_HPD6_CONTROL__DC_HPD6_EN_MASK 0x10000000L
+#define DC_HPD6_CONTROL__DC_HPD6_EN__SHIFT 0x0000001c
+#define DC_HPD6_CONTROL__DC_HPD6_RX_INT_TIMER_MASK 0x03ff0000L
+#define DC_HPD6_CONTROL__DC_HPD6_RX_INT_TIMER__SHIFT 0x00000010
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_DELAY_MASK 0x000000ffL
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_DELAY__SHIFT 0x00000000
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_EN_MASK 0x01000000L
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_AUX_TX_EN__SHIFT 0x00000018
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_DELAY_MASK 0x000ff000L
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_DELAY__SHIFT 0x0000000c
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_EN_MASK 0x10000000L
+#define DC_HPD6_FAST_TRAIN_CNTL__DC_HPD6_CONNECT_FAST_TRAIN_EN__SHIFT 0x0000001c
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_ACK_MASK 0x00000001L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_ACK__SHIFT 0x00000000
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_EN_MASK 0x00010000L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_EN__SHIFT 0x00000010
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY_MASK 0x00000100L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_INT_POLARITY__SHIFT 0x00000008
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_ACK_MASK 0x00100000L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_ACK__SHIFT 0x00000014
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_EN_MASK 0x01000000L
+#define DC_HPD6_INT_CONTROL__DC_HPD6_RX_INT_EN__SHIFT 0x00000018
+#define DC_HPD6_INT_STATUS__DC_HPD6_INT_STATUS_MASK 0x00000001L
+#define DC_HPD6_INT_STATUS__DC_HPD6_INT_STATUS__SHIFT 0x00000000
+#define DC_HPD6_INT_STATUS__DC_HPD6_RX_INT_STATUS_MASK 0x00000100L
+#define DC_HPD6_INT_STATUS__DC_HPD6_RX_INT_STATUS__SHIFT 0x00000008
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE_DELAYED_MASK 0x00000010L
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE_DELAYED__SHIFT 0x00000004
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE_MASK 0x00000002L
+#define DC_HPD6_INT_STATUS__DC_HPD6_SENSE__SHIFT 0x00000001
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_CON_TIMER_VAL_MASK 0x000ff000L
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_CON_TIMER_VAL__SHIFT 0x0000000c
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_DISCON_TIMER_VAL_MASK 0xff000000L
+#define DC_HPD6_INT_STATUS__DC_HPD6_TOGGLE_FILT_DISCON_TIMER_VAL__SHIFT 0x00000018
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_CONNECT_INT_DELAY_MASK 0x000000ffL
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_CONNECT_INT_DELAY__SHIFT 0x00000000
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_DISCONNECT_INT_DELAY_MASK 0x0ff00000L
+#define DC_HPD6_TOGGLE_FILT_CNTL__DC_HPD6_DISCONNECT_INT_DELAY__SHIFT 0x00000014
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_HW_XFER_MASK 0x00000100L
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_HW_XFER__SHIFT 0x00000008
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_SW_XFER_MASK 0x00001000L
+#define DC_I2C_ARBITRATION__DC_I2C_ABORT_SW_XFER__SHIFT 0x0000000c
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_DONE_USING_I2C_REG_MASK 0x02000000L
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_DONE_USING_I2C_REG__SHIFT 0x00000019
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_USE_I2C_REG_REQ_MASK 0x01000000L
+#define DC_I2C_ARBITRATION__DC_I2C_DMCU_USE_I2C_REG_REQ__SHIFT 0x00000018
+#define DC_I2C_ARBITRATION__DC_I2C_NO_QUEUED_SW_GO_MASK 0x00000010L
+#define DC_I2C_ARBITRATION__DC_I2C_NO_QUEUED_SW_GO__SHIFT 0x00000004
+#define DC_I2C_ARBITRATION__DC_I2C_REG_RW_CNTL_STATUS_MASK 0x0000000cL
+#define DC_I2C_ARBITRATION__DC_I2C_REG_RW_CNTL_STATUS__SHIFT 0x00000002
+#define DC_I2C_ARBITRATION__DC_I2C_SW_DONE_USING_I2C_REG_MASK 0x00200000L
+#define DC_I2C_ARBITRATION__DC_I2C_SW_DONE_USING_I2C_REG__SHIFT 0x00000015
+#define DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_MASK 0x00000003L
+#define DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY__SHIFT 0x00000000
+#define DC_I2C_ARBITRATION__DC_I2C_SW_USE_I2C_REG_REQ_MASK 0x00100000L
+#define DC_I2C_ARBITRATION__DC_I2C_SW_USE_I2C_REG_REQ__SHIFT 0x00000014
+#define DC_I2C_CONTROL__DC_I2C_DBG_REF_SEL_MASK 0x80000000L
+#define DC_I2C_CONTROL__DC_I2C_DBG_REF_SEL__SHIFT 0x0000001f
+#define DC_I2C_CONTROL__DC_I2C_DDC_SELECT_MASK 0x00000700L
+#define DC_I2C_CONTROL__DC_I2C_DDC_SELECT__SHIFT 0x00000008
+#define DC_I2C_CONTROL__DC_I2C_GO_MASK 0x00000001L
+#define DC_I2C_CONTROL__DC_I2C_GO__SHIFT 0x00000000
+#define DC_I2C_CONTROL__DC_I2C_SEND_RESET_MASK 0x00000004L
+#define DC_I2C_CONTROL__DC_I2C_SEND_RESET__SHIFT 0x00000002
+#define DC_I2C_CONTROL__DC_I2C_SOFT_RESET_MASK 0x00000002L
+#define DC_I2C_CONTROL__DC_I2C_SOFT_RESET__SHIFT 0x00000001
+#define DC_I2C_CONTROL__DC_I2C_SW_STATUS_RESET_MASK 0x00000008L
+#define DC_I2C_CONTROL__DC_I2C_SW_STATUS_RESET__SHIFT 0x00000003
+#define DC_I2C_CONTROL__DC_I2C_TRANSACTION_COUNT_MASK 0x00300000L
+#define DC_I2C_CONTROL__DC_I2C_TRANSACTION_COUNT__SHIFT 0x00000014
+#define DC_I2C_DATA__DC_I2C_DATA_MASK 0x0000ff00L
+#define DC_I2C_DATA__DC_I2C_DATA_RW_MASK 0x00000001L
+#define DC_I2C_DATA__DC_I2C_DATA_RW__SHIFT 0x00000000
+#define DC_I2C_DATA__DC_I2C_DATA__SHIFT 0x00000008
+#define DC_I2C_DATA__DC_I2C_INDEX_MASK 0x00ff0000L
+#define DC_I2C_DATA__DC_I2C_INDEX__SHIFT 0x00000010
+#define DC_I2C_DATA__DC_I2C_INDEX_WRITE_MASK 0x80000000L
+#define DC_I2C_DATA__DC_I2C_INDEX_WRITE__SHIFT 0x0000001f
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC1_HW_STATUS__DC_I2C_DDC1_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC1_SETUP__DC_I2C_DDC1_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC1_SPEED__DC_I2C_DDC1_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC2_HW_STATUS__DC_I2C_DDC2_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC2_SETUP__DC_I2C_DDC2_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC2_SPEED__DC_I2C_DDC2_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC3_HW_STATUS__DC_I2C_DDC3_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC3_SETUP__DC_I2C_DDC3_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC3_SPEED__DC_I2C_DDC3_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC4_HW_STATUS__DC_I2C_DDC4_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC4_SETUP__DC_I2C_DDC4_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC4_SPEED__DC_I2C_DDC4_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC5_HW_STATUS__DC_I2C_DDC5_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC5_SETUP__DC_I2C_DDC5_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC5_SPEED__DC_I2C_DDC5_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDC6_HW_STATUS__DC_I2C_DDC6_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDC6_SETUP__DC_I2C_DDC6_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDC6_SPEED__DC_I2C_DDC6_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_NUM_VALID_TRIES_MASK 0x0f000000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_NUM_VALID_TRIES__SHIFT 0x00000018
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATE_MASK 0x70000000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATE__SHIFT 0x0000001c
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATUS_MASK 0x00100000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_EDID_DETECT_STATUS__SHIFT 0x00000014
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_DONE_MASK 0x00000008L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_DONE__SHIFT 0x00000003
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_REQ_MASK 0x00010000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_REQ__SHIFT 0x00000010
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_STATUS_MASK 0x00000003L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_STATUS__SHIFT 0x00000000
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_URG_MASK 0x00020000L
+#define DC_I2C_DDCVGA_HW_STATUS__DC_I2C_DDCVGA_HW_URG__SHIFT 0x00000011
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_CLK_DRIVE_EN_MASK 0x00000080L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_CLK_DRIVE_EN__SHIFT 0x00000007
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_EN_MASK 0x00000001L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_EN__SHIFT 0x00000000
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_SEL_MASK 0x00000002L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_ENABLE_MASK 0x00000010L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_ENABLE__SHIFT 0x00000004
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_MODE_MASK 0x00000020L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_EDID_DETECT_MODE__SHIFT 0x00000005
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_ENABLE_MASK 0x00000040L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_ENABLE__SHIFT 0x00000006
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_TRANSACTION_DELAY_MASK 0x00ff0000L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_INTRA_TRANSACTION_DELAY__SHIFT 0x00000010
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_TIME_LIMIT_MASK 0xff000000L
+#define DC_I2C_DDCVGA_SETUP__DC_I2C_DDCVGA_TIME_LIMIT__SHIFT 0x00000018
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_PRESCALE_MASK 0xffff0000L
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_PRESCALE__SHIFT 0x00000010
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_THRESHOLD_MASK 0x00000003L
+#define DC_I2C_DDCVGA_SPEED__DC_I2C_DDCVGA_THRESHOLD__SHIFT 0x00000000
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_NUM_TRIES_UNTIL_VALID_MASK 0x00f00000L
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_NUM_TRIES_UNTIL_VALID__SHIFT 0x00000014
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_SEND_RESET_MASK 0x10000000L
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_SEND_RESET__SHIFT 0x0000001c
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_WAIT_TIME_MASK 0x0000ffffL
+#define DC_I2C_EDID_DETECT_CTRL__DC_I2C_EDID_DETECT_WAIT_TIME__SHIFT 0x00000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_ACK_MASK 0x00000020L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_ACK__SHIFT 0x00000005
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_INT_MASK 0x00000010L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_INT__SHIFT 0x00000004
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_MASK_MASK 0x00000040L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC1_HW_DONE_MASK__SHIFT 0x00000006
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_ACK_MASK 0x00000200L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_ACK__SHIFT 0x00000009
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_INT_MASK 0x00000100L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_INT__SHIFT 0x00000008
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_MASK_MASK 0x00000400L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC2_HW_DONE_MASK__SHIFT 0x0000000a
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_ACK_MASK 0x00002000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_ACK__SHIFT 0x0000000d
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_INT_MASK 0x00001000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_INT__SHIFT 0x0000000c
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_MASK_MASK 0x00004000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC3_HW_DONE_MASK__SHIFT 0x0000000e
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_ACK_MASK 0x00020000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_ACK__SHIFT 0x00000011
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_INT_MASK 0x00010000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_INT__SHIFT 0x00000010
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_MASK_MASK 0x00040000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC4_HW_DONE_MASK__SHIFT 0x00000012
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_ACK_MASK 0x00200000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_ACK__SHIFT 0x00000015
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_INT_MASK 0x00100000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_INT__SHIFT 0x00000014
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_MASK_MASK 0x00400000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC5_HW_DONE_MASK__SHIFT 0x00000016
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_ACK_MASK 0x02000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_ACK__SHIFT 0x00000019
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_INT_MASK 0x01000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_INT__SHIFT 0x00000018
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_MASK_MASK 0x04000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDC6_HW_DONE_MASK__SHIFT 0x0000001a
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_ACK_MASK 0x10000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_ACK__SHIFT 0x0000001c
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_INT_MASK 0x08000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_INT__SHIFT 0x0000001b
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_MASK_MASK 0x20000000L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_DDCVGA_HW_DONE_MASK__SHIFT 0x0000001d
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_ACK_MASK 0x00000002L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_ACK__SHIFT 0x00000001
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_INT_MASK 0x00000001L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_INT__SHIFT 0x00000000
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_MASK_MASK 0x00000004L
+#define DC_I2C_INTERRUPT_CONTROL__DC_I2C_SW_DONE_MASK__SHIFT 0x00000002
+#define DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK 0x00000010L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED__SHIFT 0x00000004
+#define DC_I2C_SW_STATUS__DC_I2C_SW_BUFFER_OVERFLOW_MASK 0x00000080L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_BUFFER_OVERFLOW__SHIFT 0x00000007
+#define DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK 0x00000004L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_DONE__SHIFT 0x00000002
+#define DC_I2C_SW_STATUS__DC_I2C_SW_INTERRUPTED_MASK 0x00000040L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_INTERRUPTED__SHIFT 0x00000006
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK0_MASK 0x00001000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK0__SHIFT 0x0000000c
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK1_MASK 0x00002000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK1__SHIFT 0x0000000d
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK2_MASK 0x00004000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK2__SHIFT 0x0000000e
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK3_MASK 0x00008000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_NACK3__SHIFT 0x0000000f
+#define DC_I2C_SW_STATUS__DC_I2C_SW_REQ_MASK 0x00040000L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_REQ__SHIFT 0x00000012
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STATUS_MASK 0x00000003L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STATUS__SHIFT 0x00000000
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK 0x00000100L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK__SHIFT 0x00000008
+#define DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK 0x00000020L
+#define DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT__SHIFT 0x00000005
+#define DC_I2C_TRANSACTION0__DC_I2C_COUNT0_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION0__DC_I2C_COUNT0__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION0__DC_I2C_RW0_MASK 0x00000001L
+#define DC_I2C_TRANSACTION0__DC_I2C_RW0__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION0__DC_I2C_START0_MASK 0x00001000L
+#define DC_I2C_TRANSACTION0__DC_I2C_START0__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP0_MASK 0x00002000L
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP0__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP_ON_NACK0_MASK 0x00000100L
+#define DC_I2C_TRANSACTION0__DC_I2C_STOP_ON_NACK0__SHIFT 0x00000008
+#define DC_I2C_TRANSACTION1__DC_I2C_COUNT1_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION1__DC_I2C_COUNT1__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION1__DC_I2C_RW1_MASK 0x00000001L
+#define DC_I2C_TRANSACTION1__DC_I2C_RW1__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION1__DC_I2C_START1_MASK 0x00001000L
+#define DC_I2C_TRANSACTION1__DC_I2C_START1__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP1_MASK 0x00002000L
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP1__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP_ON_NACK1_MASK 0x00000100L
+#define DC_I2C_TRANSACTION1__DC_I2C_STOP_ON_NACK1__SHIFT 0x00000008
+#define DC_I2C_TRANSACTION2__DC_I2C_COUNT2_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION2__DC_I2C_COUNT2__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION2__DC_I2C_RW2_MASK 0x00000001L
+#define DC_I2C_TRANSACTION2__DC_I2C_RW2__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION2__DC_I2C_START2_MASK 0x00001000L
+#define DC_I2C_TRANSACTION2__DC_I2C_START2__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP2_MASK 0x00002000L
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP2__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP_ON_NACK2_MASK 0x00000100L
+#define DC_I2C_TRANSACTION2__DC_I2C_STOP_ON_NACK2__SHIFT 0x00000008
+#define DC_I2C_TRANSACTION3__DC_I2C_COUNT3_MASK 0x00ff0000L
+#define DC_I2C_TRANSACTION3__DC_I2C_COUNT3__SHIFT 0x00000010
+#define DC_I2C_TRANSACTION3__DC_I2C_RW3_MASK 0x00000001L
+#define DC_I2C_TRANSACTION3__DC_I2C_RW3__SHIFT 0x00000000
+#define DC_I2C_TRANSACTION3__DC_I2C_START3_MASK 0x00001000L
+#define DC_I2C_TRANSACTION3__DC_I2C_START3__SHIFT 0x0000000c
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP3_MASK 0x00002000L
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP3__SHIFT 0x0000000d
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP_ON_NACK3_MASK 0x00000100L
+#define DC_I2C_TRANSACTION3__DC_I2C_STOP_ON_NACK3__SHIFT 0x00000008
+#define DCI_CLK_CNTL__DCI_PG_TEST_CLK_SEL_MASK 0xf8000000L
+#define DCI_CLK_CNTL__DCI_PG_TEST_CLK_SEL__SHIFT 0x0000001b
+#define DCI_CLK_CNTL__DCI_TEST_CLK_SEL_MASK 0x0000001fL
+#define DCI_CLK_CNTL__DCI_TEST_CLK_SEL__SHIFT 0x00000000
+#define DCI_CLK_CNTL__DISPCLK_G_DMCU_GATE_DIS_MASK 0x00008000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMCU_GATE_DIS__SHIFT 0x0000000f
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF0_GATE_DIS_MASK 0x00010000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF0_GATE_DIS__SHIFT 0x00000010
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF1_GATE_DIS_MASK 0x00020000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF1_GATE_DIS__SHIFT 0x00000011
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF2_GATE_DIS_MASK 0x00040000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF2_GATE_DIS__SHIFT 0x00000012
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF3_GATE_DIS_MASK 0x00080000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF3_GATE_DIS__SHIFT 0x00000013
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF4_GATE_DIS_MASK 0x00100000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF4_GATE_DIS__SHIFT 0x00000014
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF5_GATE_DIS_MASK 0x00200000L
+#define DCI_CLK_CNTL__DISPCLK_G_DMIF5_GATE_DIS__SHIFT 0x00000015
+#define DCI_CLK_CNTL__DISPCLK_G_FBC_GATE_DIS_MASK 0x00000200L
+#define DCI_CLK_CNTL__DISPCLK_G_FBC_GATE_DIS__SHIFT 0x00000009
+#define DCI_CLK_CNTL__DISPCLK_G_VGA_GATE_DIS_MASK 0x00000800L
+#define DCI_CLK_CNTL__DISPCLK_G_VGA_GATE_DIS__SHIFT 0x0000000b
+#define DCI_CLK_CNTL__DISPCLK_G_VIP_GATE_DIS_MASK 0x00002000L
+#define DCI_CLK_CNTL__DISPCLK_G_VIP_GATE_DIS__SHIFT 0x0000000d
+#define DCI_CLK_CNTL__DISPCLK_M_GATE_DIS_MASK 0x00000040L
+#define DCI_CLK_CNTL__DISPCLK_M_GATE_DIS__SHIFT 0x00000006
+#define DCI_CLK_CNTL__DISPCLK_R_DCI_GATE_DIS_MASK 0x00000020L
+#define DCI_CLK_CNTL__DISPCLK_R_DCI_GATE_DIS__SHIFT 0x00000005
+#define DCI_CLK_CNTL__DISPCLK_R_DMCU_GATE_DIS_MASK 0x00004000L
+#define DCI_CLK_CNTL__DISPCLK_R_DMCU_GATE_DIS__SHIFT 0x0000000e
+#define DCI_CLK_CNTL__DISPCLK_R_VGA_GATE_DIS_MASK 0x00000400L
+#define DCI_CLK_CNTL__DISPCLK_R_VGA_GATE_DIS__SHIFT 0x0000000a
+#define DCI_CLK_CNTL__DISPCLK_R_VIP_GATE_DIS_MASK 0x00001000L
+#define DCI_CLK_CNTL__DISPCLK_R_VIP_GATE_DIS__SHIFT 0x0000000c
+#define DCI_CLK_CNTL__SCLK_G_DMIF_GATE_DIS_MASK 0x00400000L
+#define DCI_CLK_CNTL__SCLK_G_DMIF_GATE_DIS__SHIFT 0x00000016
+#define DCI_CLK_CNTL__SCLK_G_DMIFTRK_GATE_DIS_MASK 0x00800000L
+#define DCI_CLK_CNTL__SCLK_G_DMIFTRK_GATE_DIS__SHIFT 0x00000017
+#define DCI_CLK_CNTL__SCLK_R_AZ_GATE_DIS_MASK 0x00000100L
+#define DCI_CLK_CNTL__SCLK_R_AZ_GATE_DIS__SHIFT 0x00000008
+#define DCI_DEBUG_CONFIG__DCI_DBG_SEL_MASK 0x0000000fL
+#define DCI_DEBUG_CONFIG__DCI_DBG_SEL__SHIFT 0x00000000
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_PWR_STATE_MASK 0x00003000L
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000040L
+#define DCI_MEM_PWR_CNTL__DMIF0_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000006
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000002L
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000001
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000080L
+#define DCI_MEM_PWR_CNTL__DMIF1_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000007
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_PWR_STATE_MASK 0x00030000L
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_PWR_STATE__SHIFT 0x00000010
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000100L
+#define DCI_MEM_PWR_CNTL__DMIF2_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000008
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_PWR_STATE__SHIFT 0x00000012
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000200L
+#define DCI_MEM_PWR_CNTL__DMIF3_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x00000009
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000010L
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000004
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_PWR_STATE_MASK 0x00300000L
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000400L
+#define DCI_MEM_PWR_CNTL__DMIF4_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x0000000a
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_LIGHT_SLEEP_DIS_MASK 0x00000020L
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_LIGHT_SLEEP_DIS__SHIFT 0x00000005
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_PWR_STATE_MASK 0x00c00000L
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_PWR_STATE__SHIFT 0x00000016
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_SHUTDOWN_DIS_MASK 0x00000800L
+#define DCI_MEM_PWR_CNTL__DMIF5_ASYNC_MEM_SHUTDOWN_DIS__SHIFT 0x0000000b
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM1_PWR_STATE_MASK 0x00000003L
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM1_PWR_STATE__SHIFT 0x00000000
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM2_PWR_STATE_MASK 0x0000000cL
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM2_PWR_STATE__SHIFT 0x00000002
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM3_PWR_STATE_MASK 0x00000030L
+#define DCI_MEM_PWR_STATE2__DMCU_ERAM3_PWR_STATE__SHIFT 0x00000004
+#define DCI_MEM_PWR_STATE__AZ_MEM_PWR_STATE_MASK 0x00c00000L
+#define DCI_MEM_PWR_STATE__AZ_MEM_PWR_STATE__SHIFT 0x00000016
+#define DCI_MEM_PWR_STATE__DMCU_IRAM_PWR_STATE_MASK 0x30000000L
+#define DCI_MEM_PWR_STATE__DMCU_IRAM_PWR_STATE__SHIFT 0x0000001c
+#define DCI_MEM_PWR_STATE__DMCU_MEM_PWR_STATE_MASK 0x00000003L
+#define DCI_MEM_PWR_STATE__DMCU_MEM_PWR_STATE__SHIFT 0x00000000
+#define DCI_MEM_PWR_STATE__DMIF0_MEM_PWR_STATE_MASK 0x0000000cL
+#define DCI_MEM_PWR_STATE__DMIF0_MEM_PWR_STATE__SHIFT 0x00000002
+#define DCI_MEM_PWR_STATE__DMIF1_MEM_PWR_STATE_MASK 0x00000030L
+#define DCI_MEM_PWR_STATE__DMIF1_MEM_PWR_STATE__SHIFT 0x00000004
+#define DCI_MEM_PWR_STATE__DMIF2_MEM_PWR_STATE_MASK 0x000000c0L
+#define DCI_MEM_PWR_STATE__DMIF2_MEM_PWR_STATE__SHIFT 0x00000006
+#define DCI_MEM_PWR_STATE__DMIF3_MEM_PWR_STATE_MASK 0x00000300L
+#define DCI_MEM_PWR_STATE__DMIF3_MEM_PWR_STATE__SHIFT 0x00000008
+#define DCI_MEM_PWR_STATE__DMIF4_MEM_PWR_STATE_MASK 0x00000c00L
+#define DCI_MEM_PWR_STATE__DMIF4_MEM_PWR_STATE__SHIFT 0x0000000a
+#define DCI_MEM_PWR_STATE__DMIF5_MEM_PWR_STATE_MASK 0x00003000L
+#define DCI_MEM_PWR_STATE__DMIF5_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM1_PWR_STATE_MASK 0x0c000000L
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM1_PWR_STATE__SHIFT 0x0000001a
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM_PWR_STATE_MASK 0x03000000L
+#define DCI_MEM_PWR_STATE__DMIF_XLR_MEM_PWR_STATE__SHIFT 0x00000018
+#define DCI_MEM_PWR_STATE__FBC_MEM_PWR_STATE_MASK 0x00030000L
+#define DCI_MEM_PWR_STATE__FBC_MEM_PWR_STATE__SHIFT 0x00000010
+#define DCI_MEM_PWR_STATE__MCIF_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCI_MEM_PWR_STATE__MCIF_MEM_PWR_STATE__SHIFT 0x00000012
+#define DCI_MEM_PWR_STATE__VGA_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCI_MEM_PWR_STATE__VGA_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCI_MEM_PWR_STATE__VIP_MEM_PWR_STATE_MASK 0x00300000L
+#define DCI_MEM_PWR_STATE__VIP_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCIO_DEBUG10__DCIO_DIGC_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG10__DCIO_DIGC_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG11__DCIO_DIGD_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG11__DCIO_DIGD_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG12__DCIO_DIGE_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG12__DCIO_DIGE_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG13__DCIO_DIGF_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG13__DCIO_DIGF_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_CLK_TRISTATE_MASK 0x00040000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_CLK_TRISTATE__SHIFT 0x00000012
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_MASK 0x00008000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_PREMUX_MASK 0x00004000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_PREMUX__SHIFT 0x0000000e
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_REG_MASK 0x00002000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0_REG__SHIFT 0x0000000d
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_A0__SHIFT 0x0000000f
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_MASK 0x00100000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_PREMUX_MASK 0x00080000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_PREMUX__SHIFT 0x00000013
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_REG_MASK 0x00010000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN_REG__SHIFT 0x00000010
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_EN__SHIFT 0x00000014
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MASK_REG_MASK 0x00400000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MASK_REG__SHIFT 0x00000016
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MUX_MASK 0x00200000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_MUX__SHIFT 0x00000015
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0_MASK 0x08000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0_PREMUX_MASK 0x04000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0_PREMUX__SHIFT 0x0000001a
+#define DCIO_DEBUG1__DOUT_DCIO_DVOCNTL1_SEL0__SHIFT 0x0000001b
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_ENABLE_MASK 0x00800000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_ENABLE__SHIFT 0x00000017
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_HSYNC_TRISTATE_MASK 0x00020000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_HSYNC_TRISTATE__SHIFT 0x00000011
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_RATE_SEL_MASK 0x02000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_RATE_SEL__SHIFT 0x00000019
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_VSYNC_TRISTATE_MASK 0x01000000L
+#define DCIO_DEBUG1__DOUT_DCIO_DVO_VSYNC_TRISTATE__SHIFT 0x00000018
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCLK_C_MASK 0x00001000L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCLK_C__SHIFT 0x0000000c
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0_MASK 0x000000c0L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0_REG_MASK 0x00000003L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0_REG__SHIFT 0x00000000
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_A0__SHIFT 0x00000006
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN_MASK 0x00000c00L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN_REG_MASK 0x00000030L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN_REG__SHIFT 0x00000004
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_EN__SHIFT 0x0000000a
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_MASK_REG_MASK 0x0000000cL
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_MASK_REG__SHIFT 0x00000002
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_SEL0_MASK 0x00000300L
+#define DCIO_DEBUG1__DOUT_DCIO_MVP_DVOCNTL_SEL0__SHIFT 0x00000008
+#define DCIO_DEBUG2__DCIO_DEBUG2_MASK 0xffffffffL
+#define DCIO_DEBUG2__DCIO_DEBUG2__SHIFT 0x00000000
+#define DCIO_DEBUG3__DCIO_DEBUG3_MASK 0xffffffffL
+#define DCIO_DEBUG3__DCIO_DEBUG3__SHIFT 0x00000000
+#define DCIO_DEBUG4__DCIO_DEBUG4_MASK 0xffffffffL
+#define DCIO_DEBUG4__DCIO_DEBUG4__SHIFT 0x00000000
+#define DCIO_DEBUG5__DCIO_DEBUG5_MASK 0xffffffffL
+#define DCIO_DEBUG5__DCIO_DEBUG5__SHIFT 0x00000000
+#define DCIO_DEBUG6__DCIO_DEBUG6_MASK 0xffffffffL
+#define DCIO_DEBUG6__DCIO_DEBUG6__SHIFT 0x00000000
+#define DCIO_DEBUG7__DCIO_DEBUG7_MASK 0xffffffffL
+#define DCIO_DEBUG7__DCIO_DEBUG7__SHIFT 0x00000000
+#define DCIO_DEBUG8__DCIO_DEBUG8_MASK 0xffffffffL
+#define DCIO_DEBUG8__DCIO_DEBUG8__SHIFT 0x00000000
+#define DCIO_DEBUG9__DCIO_DEBUG9_MASK 0xffffffffL
+#define DCIO_DEBUG9__DCIO_DEBUG9__SHIFT 0x00000000
+#define DCIO_DEBUGA__DCIO_DEBUGA_MASK 0xffffffffL
+#define DCIO_DEBUGA__DCIO_DEBUGA__SHIFT 0x00000000
+#define DCIO_DEBUGB__DCIO_DEBUGB_MASK 0xffffffffL
+#define DCIO_DEBUGB__DCIO_DEBUGB__SHIFT 0x00000000
+#define DCIO_DEBUGC__DCIO_DEBUGC_MASK 0xffffffffL
+#define DCIO_DEBUGC__DCIO_DEBUGC__SHIFT 0x00000000
+#define DCIO_DEBUG__DCIO_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUG__DCIO_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUGD__DCIO_DEBUGD_MASK 0xffffffffL
+#define DCIO_DEBUGD__DCIO_DEBUGD__SHIFT 0x00000000
+#define DCIO_DEBUGE__DCIO_DIGA_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUGE__DCIO_DIGA_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUGF__DCIO_DIGB_DEBUG_MASK 0xffffffffL
+#define DCIO_DEBUGF__DCIO_DIGB_DEBUG__SHIFT 0x00000000
+#define DCIO_DEBUG_ID__DCIO_DEBUG_ID_MASK 0xffffffffL
+#define DCIO_DEBUG_ID__DCIO_DEBUG_ID__SHIFT 0x00000000
+#define DCIO_GSL0_CNTL__DCIO_GSL0_GLOBAL_UNLOCK_SEL_MASK 0x00070000L
+#define DCIO_GSL0_CNTL__DCIO_GSL0_GLOBAL_UNLOCK_SEL__SHIFT 0x00000010
+#define DCIO_GSL0_CNTL__DCIO_GSL0_TIMING_SYNC_SEL_MASK 0x00000700L
+#define DCIO_GSL0_CNTL__DCIO_GSL0_TIMING_SYNC_SEL__SHIFT 0x00000008
+#define DCIO_GSL0_CNTL__DCIO_GSL0_VSYNC_SEL_MASK 0x00000007L
+#define DCIO_GSL0_CNTL__DCIO_GSL0_VSYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL1_CNTL__DCIO_GSL1_GLOBAL_UNLOCK_SEL_MASK 0x00070000L
+#define DCIO_GSL1_CNTL__DCIO_GSL1_GLOBAL_UNLOCK_SEL__SHIFT 0x00000010
+#define DCIO_GSL1_CNTL__DCIO_GSL1_TIMING_SYNC_SEL_MASK 0x00000700L
+#define DCIO_GSL1_CNTL__DCIO_GSL1_TIMING_SYNC_SEL__SHIFT 0x00000008
+#define DCIO_GSL1_CNTL__DCIO_GSL1_VSYNC_SEL_MASK 0x00000007L
+#define DCIO_GSL1_CNTL__DCIO_GSL1_VSYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL2_CNTL__DCIO_GSL2_GLOBAL_UNLOCK_SEL_MASK 0x00070000L
+#define DCIO_GSL2_CNTL__DCIO_GSL2_GLOBAL_UNLOCK_SEL__SHIFT 0x00000010
+#define DCIO_GSL2_CNTL__DCIO_GSL2_TIMING_SYNC_SEL_MASK 0x00000700L
+#define DCIO_GSL2_CNTL__DCIO_GSL2_TIMING_SYNC_SEL__SHIFT 0x00000008
+#define DCIO_GSL2_CNTL__DCIO_GSL2_VSYNC_SEL_MASK 0x00000007L
+#define DCIO_GSL2_CNTL__DCIO_GSL2_VSYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_FLIP_LOCK_SEL_MASK 0x00000030L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_FLIP_LOCK_SEL__SHIFT 0x00000004
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_MASK_MASK 0x00000300L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_MASK__SHIFT 0x00000008
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_TIMING_SYNC_SEL_MASK 0x00000003L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_CLK_GSL_TIMING_SYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_FLIP_LOCK_SEL_MASK 0x00300000L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_FLIP_LOCK_SEL__SHIFT 0x00000014
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_MASK_MASK 0x03000000L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_MASK__SHIFT 0x00000018
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_TIMING_SYNC_SEL_MASK 0x00030000L
+#define DCIO_GSL_GENLK_PAD_CNTL__DCIO_GENLK_VSYNC_GSL_TIMING_SYNC_SEL__SHIFT 0x00000010
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_FLIP_LOCK_SEL_MASK 0x00000030L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_FLIP_LOCK_SEL__SHIFT 0x00000004
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_MASK_MASK 0x00000300L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_MASK__SHIFT 0x00000008
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_TIMING_SYNC_SEL_MASK 0x00000003L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_A_GSL_TIMING_SYNC_SEL__SHIFT 0x00000000
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_FLIP_LOCK_SEL_MASK 0x00300000L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_FLIP_LOCK_SEL__SHIFT 0x00000014
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_MASK_MASK 0x03000000L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_MASK__SHIFT 0x00000018
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_TIMING_SYNC_SEL_MASK 0x00030000L
+#define DCIO_GSL_SWAPLOCK_PAD_CNTL__DCIO_SWAPLOCK_B_GSL_TIMING_SYNC_SEL__SHIFT 0x00000010
+#define DCIO_IMPCAL_CNTL_AB__CALR_CNTL_OVERRIDE_MASK 0x0000000fL
+#define DCIO_IMPCAL_CNTL_AB__CALR_CNTL_OVERRIDE__SHIFT 0x00000000
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_ARB_STATE_MASK 0x00007000L
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_ARB_STATE__SHIFT 0x0000000c
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_SOFT_RESET_MASK 0x00000020L
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_SOFT_RESET__SHIFT 0x00000005
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_STATUS_MASK 0x00000300L
+#define DCIO_IMPCAL_CNTL_AB__IMPCAL_STATUS__SHIFT 0x00000008
+#define DCIO_IMPCAL_CNTL_CD__CALR_CNTL_OVERRIDE_MASK 0x0000000fL
+#define DCIO_IMPCAL_CNTL_CD__CALR_CNTL_OVERRIDE__SHIFT 0x00000000
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_ARB_STATE_MASK 0x00007000L
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_ARB_STATE__SHIFT 0x0000000c
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_SOFT_RESET_MASK 0x00000020L
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_SOFT_RESET__SHIFT 0x00000005
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_STATUS_MASK 0x00000300L
+#define DCIO_IMPCAL_CNTL_CD__IMPCAL_STATUS__SHIFT 0x00000008
+#define DCIO_IMPCAL_CNTL_EF__CALR_CNTL_OVERRIDE_MASK 0x0000000fL
+#define DCIO_IMPCAL_CNTL_EF__CALR_CNTL_OVERRIDE__SHIFT 0x00000000
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_ARB_STATE_MASK 0x00007000L
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_ARB_STATE__SHIFT 0x0000000c
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_SOFT_RESET_MASK 0x00000020L
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_SOFT_RESET__SHIFT 0x00000005
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_STATUS_MASK 0x00000300L
+#define DCIO_IMPCAL_CNTL_EF__IMPCAL_STATUS__SHIFT 0x00000008
+#define DCIO_TEST_DEBUG_DATA__DCIO_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCIO_TEST_DEBUG_DATA__DCIO_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCIO_TEST_DEBUG_INDEX__DCIO_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DCI_SOFT_RESET__DMIF0_SOFT_RESET_MASK 0x00000010L
+#define DCI_SOFT_RESET__DMIF0_SOFT_RESET__SHIFT 0x00000004
+#define DCI_SOFT_RESET__DMIF1_SOFT_RESET_MASK 0x00000020L
+#define DCI_SOFT_RESET__DMIF1_SOFT_RESET__SHIFT 0x00000005
+#define DCI_SOFT_RESET__DMIF2_SOFT_RESET_MASK 0x00000040L
+#define DCI_SOFT_RESET__DMIF2_SOFT_RESET__SHIFT 0x00000006
+#define DCI_SOFT_RESET__DMIF3_SOFT_RESET_MASK 0x00000080L
+#define DCI_SOFT_RESET__DMIF3_SOFT_RESET__SHIFT 0x00000007
+#define DCI_SOFT_RESET__DMIF4_SOFT_RESET_MASK 0x00000100L
+#define DCI_SOFT_RESET__DMIF4_SOFT_RESET__SHIFT 0x00000008
+#define DCI_SOFT_RESET__DMIF5_SOFT_RESET_MASK 0x00000200L
+#define DCI_SOFT_RESET__DMIF5_SOFT_RESET__SHIFT 0x00000009
+#define DCI_SOFT_RESET__DMIFARB_SOFT_RESET_MASK 0x00001000L
+#define DCI_SOFT_RESET__DMIFARB_SOFT_RESET__SHIFT 0x0000000c
+#define DCI_SOFT_RESET__FBC_SOFT_RESET_MASK 0x00000008L
+#define DCI_SOFT_RESET__FBC_SOFT_RESET__SHIFT 0x00000003
+#define DCI_SOFT_RESET__MCIF_SOFT_RESET_MASK 0x00000004L
+#define DCI_SOFT_RESET__MCIF_SOFT_RESET__SHIFT 0x00000002
+#define DCI_SOFT_RESET__VGA_SOFT_RESET_MASK 0x00000001L
+#define DCI_SOFT_RESET__VGA_SOFT_RESET__SHIFT 0x00000000
+#define DCI_SOFT_RESET__VIP_SOFT_RESET_MASK 0x00000002L
+#define DCI_SOFT_RESET__VIP_SOFT_RESET__SHIFT 0x00000001
+#define DCI_TEST_DEBUG_DATA__DCI_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCI_TEST_DEBUG_DATA__DCI_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCI_TEST_DEBUG_INDEX__DCI_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_BLUE_MASK 0x000003ffL
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_BLUE__SHIFT 0x00000000
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_GREEN_MASK 0x000ffc00L
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_GREEN__SHIFT 0x0000000a
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_RED_MASK 0x3ff00000L
+#define DC_LUT_30_COLOR__DC_LUT_COLOR_10_RED__SHIFT 0x00000014
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_DONE_MASK 0x00000002L
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_DONE__SHIFT 0x00000001
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL_MASK 0x00000001L
+#define DC_LUT_AUTOFILL__DC_LUT_AUTOFILL__SHIFT 0x00000000
+#define DC_LUT_BLACK_OFFSET_BLUE__DC_LUT_BLACK_OFFSET_BLUE_MASK 0x0000ffffL
+#define DC_LUT_BLACK_OFFSET_BLUE__DC_LUT_BLACK_OFFSET_BLUE__SHIFT 0x00000000
+#define DC_LUT_BLACK_OFFSET_GREEN__DC_LUT_BLACK_OFFSET_GREEN_MASK 0x0000ffffL
+#define DC_LUT_BLACK_OFFSET_GREEN__DC_LUT_BLACK_OFFSET_GREEN__SHIFT 0x00000000
+#define DC_LUT_BLACK_OFFSET_RED__DC_LUT_BLACK_OFFSET_RED_MASK 0x0000ffffL
+#define DC_LUT_BLACK_OFFSET_RED__DC_LUT_BLACK_OFFSET_RED__SHIFT 0x00000000
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FLOAT_POINT_EN_MASK 0x00000020L
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FLOAT_POINT_EN__SHIFT 0x00000005
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FORMAT_MASK 0x000000c0L
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_FORMAT__SHIFT 0x00000006
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_SIGNED_EN_MASK 0x00000010L
+#define DC_LUT_CONTROL__DC_LUT_DATA_B_SIGNED_EN__SHIFT 0x00000004
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FLOAT_POINT_EN_MASK 0x00002000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FLOAT_POINT_EN__SHIFT 0x0000000d
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FORMAT_MASK 0x0000c000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_FORMAT__SHIFT 0x0000000e
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_SIGNED_EN_MASK 0x00001000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_G_SIGNED_EN__SHIFT 0x0000000c
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FLOAT_POINT_EN_MASK 0x00200000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FLOAT_POINT_EN__SHIFT 0x00000015
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FORMAT_MASK 0x00c00000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_FORMAT__SHIFT 0x00000016
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_SIGNED_EN_MASK 0x00100000L
+#define DC_LUT_CONTROL__DC_LUT_DATA_R_SIGNED_EN__SHIFT 0x00000014
+#define DC_LUT_CONTROL__DC_LUT_INC_B_MASK 0x0000000fL
+#define DC_LUT_CONTROL__DC_LUT_INC_B__SHIFT 0x00000000
+#define DC_LUT_CONTROL__DC_LUT_INC_G_MASK 0x00000f00L
+#define DC_LUT_CONTROL__DC_LUT_INC_G__SHIFT 0x00000008
+#define DC_LUT_CONTROL__DC_LUT_INC_R_MASK 0x000f0000L
+#define DC_LUT_CONTROL__DC_LUT_INC_R__SHIFT 0x00000010
+#define DC_LUT_PWL_DATA__DC_LUT_BASE_MASK 0x0000ffffL
+#define DC_LUT_PWL_DATA__DC_LUT_BASE__SHIFT 0x00000000
+#define DC_LUT_PWL_DATA__DC_LUT_DELTA_MASK 0xffff0000L
+#define DC_LUT_PWL_DATA__DC_LUT_DELTA__SHIFT 0x00000010
+#define DC_LUT_RW_INDEX__DC_LUT_RW_INDEX_MASK 0x000000ffL
+#define DC_LUT_RW_INDEX__DC_LUT_RW_INDEX__SHIFT 0x00000000
+#define DC_LUT_RW_MODE__DC_LUT_RW_MODE_MASK 0x00000001L
+#define DC_LUT_RW_MODE__DC_LUT_RW_MODE__SHIFT 0x00000000
+#define DC_LUT_SEQ_COLOR__DC_LUT_SEQ_COLOR_MASK 0x0000ffffL
+#define DC_LUT_SEQ_COLOR__DC_LUT_SEQ_COLOR__SHIFT 0x00000000
+#define DC_LUT_VGA_ACCESS_ENABLE__DC_LUT_VGA_ACCESS_ENABLE_MASK 0x00000001L
+#define DC_LUT_VGA_ACCESS_ENABLE__DC_LUT_VGA_ACCESS_ENABLE__SHIFT 0x00000000
+#define DC_LUT_WHITE_OFFSET_BLUE__DC_LUT_WHITE_OFFSET_BLUE_MASK 0x0000ffffL
+#define DC_LUT_WHITE_OFFSET_BLUE__DC_LUT_WHITE_OFFSET_BLUE__SHIFT 0x00000000
+#define DC_LUT_WHITE_OFFSET_GREEN__DC_LUT_WHITE_OFFSET_GREEN_MASK 0x0000ffffL
+#define DC_LUT_WHITE_OFFSET_GREEN__DC_LUT_WHITE_OFFSET_GREEN__SHIFT 0x00000000
+#define DC_LUT_WHITE_OFFSET_RED__DC_LUT_WHITE_OFFSET_RED_MASK 0x0000ffffL
+#define DC_LUT_WHITE_OFFSET_RED__DC_LUT_WHITE_OFFSET_RED__SHIFT 0x00000000
+#define DC_LUT_WRITE_EN_MASK__DC_LUT_WRITE_EN_MASK_MASK 0x00000007L
+#define DC_LUT_WRITE_EN_MASK__DC_LUT_WRITE_EN_MASK__SHIFT 0x00000000
+#define DC_MVP_LB_CONTROL__DC_MVP_SPARE_FLOPS_MASK 0x80000000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SPARE_FLOPS__SHIFT 0x0000001f
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_IN_CAP_MASK 0x10000000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_IN_CAP__SHIFT 0x0000001c
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ONE_MASK 0x00001000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ONE__SHIFT 0x0000000c
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO_MASK 0x00010000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_FORCE_ZERO__SHIFT 0x00000010
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_SEL_MASK 0x00000100L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_OUT_SEL__SHIFT 0x00000008
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_STATUS_MASK 0x00100000L
+#define DC_MVP_LB_CONTROL__DC_MVP_SWAP_LOCK_STATUS__SHIFT 0x00000014
+#define DC_MVP_LB_CONTROL__MVP_SWAP_LOCK_IN_MODE_MASK 0x00000003L
+#define DC_MVP_LB_CONTROL__MVP_SWAP_LOCK_IN_MODE__SHIFT 0x00000000
+#define DCO_CLK_CNTL__DCO_TEST_CLK_SEL_MASK 0x0000001fL
+#define DCO_CLK_CNTL__DCO_TEST_CLK_SEL__SHIFT 0x00000000
+#define DCO_CLK_CNTL__DISPCLK_G_ABM_GATE_DIS_MASK 0x00000040L
+#define DCO_CLK_CNTL__DISPCLK_G_ABM_GATE_DIS__SHIFT 0x00000006
+#define DCO_CLK_CNTL__DISPCLK_G_DACA_GATE_DIS_MASK 0x00000100L
+#define DCO_CLK_CNTL__DISPCLK_G_DACA_GATE_DIS__SHIFT 0x00000008
+#define DCO_CLK_CNTL__DISPCLK_G_DACB_GATE_DIS_MASK 0x00000200L
+#define DCO_CLK_CNTL__DISPCLK_G_DACB_GATE_DIS__SHIFT 0x00000009
+#define DCO_CLK_CNTL__DISPCLK_G_DIGA_GATE_DIS_MASK 0x01000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGA_GATE_DIS__SHIFT 0x00000018
+#define DCO_CLK_CNTL__DISPCLK_G_DIGB_GATE_DIS_MASK 0x02000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGB_GATE_DIS__SHIFT 0x00000019
+#define DCO_CLK_CNTL__DISPCLK_G_DIGC_GATE_DIS_MASK 0x04000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGC_GATE_DIS__SHIFT 0x0000001a
+#define DCO_CLK_CNTL__DISPCLK_G_DIGD_GATE_DIS_MASK 0x08000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGD_GATE_DIS__SHIFT 0x0000001b
+#define DCO_CLK_CNTL__DISPCLK_G_DIGE_GATE_DIS_MASK 0x10000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGE_GATE_DIS__SHIFT 0x0000001c
+#define DCO_CLK_CNTL__DISPCLK_G_DIGF_GATE_DIS_MASK 0x20000000L
+#define DCO_CLK_CNTL__DISPCLK_G_DIGF_GATE_DIS__SHIFT 0x0000001d
+#define DCO_CLK_CNTL__DISPCLK_G_DVO_GATE_DIS_MASK 0x00000080L
+#define DCO_CLK_CNTL__DISPCLK_G_DVO_GATE_DIS__SHIFT 0x00000007
+#define DCO_CLK_CNTL__DISPCLK_G_FMT0_GATE_DIS_MASK 0x00010000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT0_GATE_DIS__SHIFT 0x00000010
+#define DCO_CLK_CNTL__DISPCLK_G_FMT1_GATE_DIS_MASK 0x00020000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT1_GATE_DIS__SHIFT 0x00000011
+#define DCO_CLK_CNTL__DISPCLK_G_FMT2_GATE_DIS_MASK 0x00040000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT2_GATE_DIS__SHIFT 0x00000012
+#define DCO_CLK_CNTL__DISPCLK_G_FMT3_GATE_DIS_MASK 0x00080000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT3_GATE_DIS__SHIFT 0x00000013
+#define DCO_CLK_CNTL__DISPCLK_G_FMT4_GATE_DIS_MASK 0x00100000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT4_GATE_DIS__SHIFT 0x00000014
+#define DCO_CLK_CNTL__DISPCLK_G_FMT5_GATE_DIS_MASK 0x00200000L
+#define DCO_CLK_CNTL__DISPCLK_G_FMT5_GATE_DIS__SHIFT 0x00000015
+#define DCO_CLK_CNTL__DISPCLK_R_ABM_GATE_DIS_MASK 0x00001000L
+#define DCO_CLK_CNTL__DISPCLK_R_ABM_GATE_DIS__SHIFT 0x0000000c
+#define DCO_CLK_CNTL__DISPCLK_R_DCO_GATE_DIS_MASK 0x00000020L
+#define DCO_CLK_CNTL__DISPCLK_R_DCO_GATE_DIS__SHIFT 0x00000005
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_ABM_RAMP_DIS_MASK 0x00000040L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_ABM_RAMP_DIS__SHIFT 0x00000006
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACA_RAMP_DIS_MASK 0x00000100L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACA_RAMP_DIS__SHIFT 0x00000008
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACB_RAMP_DIS_MASK 0x00000200L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DACB_RAMP_DIS__SHIFT 0x00000009
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGA_RAMP_DIS_MASK 0x01000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGA_RAMP_DIS__SHIFT 0x00000018
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGB_RAMP_DIS_MASK 0x02000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGB_RAMP_DIS__SHIFT 0x00000019
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGC_RAMP_DIS_MASK 0x04000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGC_RAMP_DIS__SHIFT 0x0000001a
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGD_RAMP_DIS_MASK 0x08000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGD_RAMP_DIS__SHIFT 0x0000001b
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGE_RAMP_DIS_MASK 0x10000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGE_RAMP_DIS__SHIFT 0x0000001c
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGF_RAMP_DIS_MASK 0x20000000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DIGF_RAMP_DIS__SHIFT 0x0000001d
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DVO_RAMP_DIS_MASK 0x00000080L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_DVO_RAMP_DIS__SHIFT 0x00000007
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT0_RAMP_DIS_MASK 0x00010000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT0_RAMP_DIS__SHIFT 0x00000010
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT1_RAMP_DIS_MASK 0x00020000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT1_RAMP_DIS__SHIFT 0x00000011
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT2_RAMP_DIS_MASK 0x00040000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT2_RAMP_DIS__SHIFT 0x00000012
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT3_RAMP_DIS_MASK 0x00080000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT3_RAMP_DIS__SHIFT 0x00000013
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT4_RAMP_DIS_MASK 0x00100000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT4_RAMP_DIS__SHIFT 0x00000014
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT5_RAMP_DIS_MASK 0x00200000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_G_FMT5_RAMP_DIS__SHIFT 0x00000015
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_ABM_RAMP_DIS_MASK 0x00001000L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_ABM_RAMP_DIS__SHIFT 0x0000000c
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_DCO_RAMP_DIS_MASK 0x00000020L
+#define DCO_CLK_RAMP_CNTL__DISPCLK_R_DCO_RAMP_DIS__SHIFT 0x00000005
+#define DCO_LIGHT_SLEEP_DIS__DPA_LIGHT_SLEEP_DIS_MASK 0x00000008L
+#define DCO_LIGHT_SLEEP_DIS__DPA_LIGHT_SLEEP_DIS__SHIFT 0x00000003
+#define DCO_LIGHT_SLEEP_DIS__DPA_MEM_SHUTDOWN_DIS_MASK 0x00020000L
+#define DCO_LIGHT_SLEEP_DIS__DPA_MEM_SHUTDOWN_DIS__SHIFT 0x00000011
+#define DCO_LIGHT_SLEEP_DIS__DPB_LIGHT_SLEEP_DIS_MASK 0x00000010L
+#define DCO_LIGHT_SLEEP_DIS__DPB_LIGHT_SLEEP_DIS__SHIFT 0x00000004
+#define DCO_LIGHT_SLEEP_DIS__DPB_MEM_SHUTDOWN_DIS_MASK 0x00040000L
+#define DCO_LIGHT_SLEEP_DIS__DPB_MEM_SHUTDOWN_DIS__SHIFT 0x00000012
+#define DCO_LIGHT_SLEEP_DIS__DPC_LIGHT_SLEEP_DIS_MASK 0x00000020L
+#define DCO_LIGHT_SLEEP_DIS__DPC_LIGHT_SLEEP_DIS__SHIFT 0x00000005
+#define DCO_LIGHT_SLEEP_DIS__DPC_MEM_SHUTDOWN_DIS_MASK 0x00080000L
+#define DCO_LIGHT_SLEEP_DIS__DPC_MEM_SHUTDOWN_DIS__SHIFT 0x00000013
+#define DCO_LIGHT_SLEEP_DIS__DPD_LIGHT_SLEEP_DIS_MASK 0x00000040L
+#define DCO_LIGHT_SLEEP_DIS__DPD_LIGHT_SLEEP_DIS__SHIFT 0x00000006
+#define DCO_LIGHT_SLEEP_DIS__DPD_MEM_SHUTDOWN_DIS_MASK 0x00100000L
+#define DCO_LIGHT_SLEEP_DIS__DPD_MEM_SHUTDOWN_DIS__SHIFT 0x00000014
+#define DCO_LIGHT_SLEEP_DIS__DPE_LIGHT_SLEEP_DIS_MASK 0x00000080L
+#define DCO_LIGHT_SLEEP_DIS__DPE_LIGHT_SLEEP_DIS__SHIFT 0x00000007
+#define DCO_LIGHT_SLEEP_DIS__DPE_MEM_SHUTDOWN_DIS_MASK 0x00200000L
+#define DCO_LIGHT_SLEEP_DIS__DPE_MEM_SHUTDOWN_DIS__SHIFT 0x00000015
+#define DCO_LIGHT_SLEEP_DIS__DPF_LIGHT_SLEEP_DIS_MASK 0x00000100L
+#define DCO_LIGHT_SLEEP_DIS__DPF_LIGHT_SLEEP_DIS__SHIFT 0x00000008
+#define DCO_LIGHT_SLEEP_DIS__DPF_MEM_SHUTDOWN_DIS_MASK 0x00400000L
+#define DCO_LIGHT_SLEEP_DIS__DPF_MEM_SHUTDOWN_DIS__SHIFT 0x00000016
+#define DCO_LIGHT_SLEEP_DIS__HDMI0_LIGHT_SLEEP_DIS_MASK 0x00000200L
+#define DCO_LIGHT_SLEEP_DIS__HDMI0_LIGHT_SLEEP_DIS__SHIFT 0x00000009
+#define DCO_LIGHT_SLEEP_DIS__HDMI1_LIGHT_SLEEP_DIS_MASK 0x00000400L
+#define DCO_LIGHT_SLEEP_DIS__HDMI1_LIGHT_SLEEP_DIS__SHIFT 0x0000000a
+#define DCO_LIGHT_SLEEP_DIS__HDMI2_LIGHT_SLEEP_DIS_MASK 0x00000800L
+#define DCO_LIGHT_SLEEP_DIS__HDMI2_LIGHT_SLEEP_DIS__SHIFT 0x0000000b
+#define DCO_LIGHT_SLEEP_DIS__HDMI3_LIGHT_SLEEP_DIS_MASK 0x00001000L
+#define DCO_LIGHT_SLEEP_DIS__HDMI3_LIGHT_SLEEP_DIS__SHIFT 0x0000000c
+#define DCO_LIGHT_SLEEP_DIS__HDMI4_LIGHT_SLEEP_DIS_MASK 0x00002000L
+#define DCO_LIGHT_SLEEP_DIS__HDMI4_LIGHT_SLEEP_DIS__SHIFT 0x0000000d
+#define DCO_LIGHT_SLEEP_DIS__HDMI5_LIGHT_SLEEP_DIS_MASK 0x00004000L
+#define DCO_LIGHT_SLEEP_DIS__HDMI5_LIGHT_SLEEP_DIS__SHIFT 0x0000000e
+#define DCO_LIGHT_SLEEP_DIS__I2C_LIGHT_SLEEP_FORCE_MASK 0x00000002L
+#define DCO_LIGHT_SLEEP_DIS__I2C_LIGHT_SLEEP_FORCE__SHIFT 0x00000001
+#define DCO_LIGHT_SLEEP_DIS__MVP_LIGHT_SLEEP_DIS_MASK 0x00000004L
+#define DCO_LIGHT_SLEEP_DIS__MVP_LIGHT_SLEEP_DIS__SHIFT 0x00000002
+#define DCO_LIGHT_SLEEP_DIS__MVP_MEM_SHUTDOWN_DIS_MASK 0x00010000L
+#define DCO_LIGHT_SLEEP_DIS__MVP_MEM_SHUTDOWN_DIS__SHIFT 0x00000010
+#define DCO_LIGHT_SLEEP_DIS__TVOUT_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define DCO_LIGHT_SLEEP_DIS__TVOUT_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define DCO_MEM_POWER_STATE__DPA_MEM_PWR_STATE_MASK 0x000000c0L
+#define DCO_MEM_POWER_STATE__DPA_MEM_PWR_STATE__SHIFT 0x00000006
+#define DCO_MEM_POWER_STATE__DPB_MEM_PWR_STATE_MASK 0x00000300L
+#define DCO_MEM_POWER_STATE__DPB_MEM_PWR_STATE__SHIFT 0x00000008
+#define DCO_MEM_POWER_STATE__DPC_MEM_PWR_STATE_MASK 0x00000c00L
+#define DCO_MEM_POWER_STATE__DPC_MEM_PWR_STATE__SHIFT 0x0000000a
+#define DCO_MEM_POWER_STATE__DPD_MEM_PWR_STATE_MASK 0x00003000L
+#define DCO_MEM_POWER_STATE__DPD_MEM_PWR_STATE__SHIFT 0x0000000c
+#define DCO_MEM_POWER_STATE__DPE_MEM_PWR_STATE_MASK 0x0000c000L
+#define DCO_MEM_POWER_STATE__DPE_MEM_PWR_STATE__SHIFT 0x0000000e
+#define DCO_MEM_POWER_STATE__DPF_MEM_PWR_STATE_MASK 0x00030000L
+#define DCO_MEM_POWER_STATE__DPF_MEM_PWR_STATE__SHIFT 0x00000010
+#define DCO_MEM_POWER_STATE__HDMI0_MEM_PWR_STATE_MASK 0x000c0000L
+#define DCO_MEM_POWER_STATE__HDMI0_MEM_PWR_STATE__SHIFT 0x00000012
+#define DCO_MEM_POWER_STATE__HDMI1_MEM_PWR_STATE_MASK 0x00300000L
+#define DCO_MEM_POWER_STATE__HDMI1_MEM_PWR_STATE__SHIFT 0x00000014
+#define DCO_MEM_POWER_STATE__HDMI2_MEM_PWR_STATE_MASK 0x00c00000L
+#define DCO_MEM_POWER_STATE__HDMI2_MEM_PWR_STATE__SHIFT 0x00000016
+#define DCO_MEM_POWER_STATE__HDMI3_MEM_PWR_STATE_MASK 0x03000000L
+#define DCO_MEM_POWER_STATE__HDMI3_MEM_PWR_STATE__SHIFT 0x00000018
+#define DCO_MEM_POWER_STATE__HDMI4_MEM_PWR_STATE_MASK 0x0c000000L
+#define DCO_MEM_POWER_STATE__HDMI4_MEM_PWR_STATE__SHIFT 0x0000001a
+#define DCO_MEM_POWER_STATE__HDMI5_MEM_PWR_STATE_MASK 0x30000000L
+#define DCO_MEM_POWER_STATE__HDMI5_MEM_PWR_STATE__SHIFT 0x0000001c
+#define DCO_MEM_POWER_STATE__I2C_MEM_PWR_STATE_MASK 0x0000000cL
+#define DCO_MEM_POWER_STATE__I2C_MEM_PWR_STATE__SHIFT 0x00000002
+#define DCO_MEM_POWER_STATE__MVP_MEM_PWR_STATE_MASK 0x00000030L
+#define DCO_MEM_POWER_STATE__MVP_MEM_PWR_STATE__SHIFT 0x00000004
+#define DCO_MEM_POWER_STATE__TVOUT_MEM_PWR_STATE_MASK 0x00000003L
+#define DCO_MEM_POWER_STATE__TVOUT_MEM_PWR_STATE__SHIFT 0x00000000
+#define DCO_SOFT_RESET__ABM_SOFT_RESET_MASK 0x02000000L
+#define DCO_SOFT_RESET__ABM_SOFT_RESET__SHIFT 0x00000019
+#define DCO_SOFT_RESET__DACA_CFG_IF_SOFT_RESET_MASK 0x20000000L
+#define DCO_SOFT_RESET__DACA_CFG_IF_SOFT_RESET__SHIFT 0x0000001d
+#define DCO_SOFT_RESET__DACA_SOFT_RESET_MASK 0x00000001L
+#define DCO_SOFT_RESET__DACA_SOFT_RESET__SHIFT 0x00000000
+#define DCO_SOFT_RESET__DACB_SOFT_RESET_MASK 0x00000002L
+#define DCO_SOFT_RESET__DACB_SOFT_RESET__SHIFT 0x00000001
+#define DCO_SOFT_RESET__DVO_ENABLE_RST_MASK 0x00000008L
+#define DCO_SOFT_RESET__DVO_ENABLE_RST__SHIFT 0x00000003
+#define DCO_SOFT_RESET__DVO_SOFT_RESET_MASK 0x08000000L
+#define DCO_SOFT_RESET__DVO_SOFT_RESET__SHIFT 0x0000001b
+#define DCO_SOFT_RESET__FMT0_SOFT_RESET_MASK 0x00010000L
+#define DCO_SOFT_RESET__FMT0_SOFT_RESET__SHIFT 0x00000010
+#define DCO_SOFT_RESET__FMT1_SOFT_RESET_MASK 0x00020000L
+#define DCO_SOFT_RESET__FMT1_SOFT_RESET__SHIFT 0x00000011
+#define DCO_SOFT_RESET__FMT2_SOFT_RESET_MASK 0x00040000L
+#define DCO_SOFT_RESET__FMT2_SOFT_RESET__SHIFT 0x00000012
+#define DCO_SOFT_RESET__FMT3_SOFT_RESET_MASK 0x00080000L
+#define DCO_SOFT_RESET__FMT3_SOFT_RESET__SHIFT 0x00000013
+#define DCO_SOFT_RESET__FMT4_SOFT_RESET_MASK 0x00100000L
+#define DCO_SOFT_RESET__FMT4_SOFT_RESET__SHIFT 0x00000014
+#define DCO_SOFT_RESET__FMT5_SOFT_RESET_MASK 0x00200000L
+#define DCO_SOFT_RESET__FMT5_SOFT_RESET__SHIFT 0x00000015
+#define DCO_SOFT_RESET__MVP_SOFT_RESET_MASK 0x01000000L
+#define DCO_SOFT_RESET__MVP_SOFT_RESET__SHIFT 0x00000018
+#define DCO_SOFT_RESET__SOFT_RESET_DVO_MASK 0x00000004L
+#define DCO_SOFT_RESET__SOFT_RESET_DVO__SHIFT 0x00000002
+#define DCO_SOFT_RESET__SRBM_SOFT_RESET_ENABLE_MASK 0x10000000L
+#define DCO_SOFT_RESET__SRBM_SOFT_RESET_ENABLE__SHIFT 0x0000001c
+#define DCO_SOFT_RESET__TVOUT_SOFT_RESET_MASK 0x04000000L
+#define DCO_SOFT_RESET__TVOUT_SOFT_RESET__SHIFT 0x0000001a
+#define DC_PAD_EXTERN_SIG__DC_PAD_EXTERN_SIG_SEL_MASK 0x0000000fL
+#define DC_PAD_EXTERN_SIG__DC_PAD_EXTERN_SIG_SEL__SHIFT 0x00000000
+#define DC_PAD_EXTERN_SIG__MVP_PIXEL_SRC_STATUS_MASK 0x00000030L
+#define DC_PAD_EXTERN_SIG__MVP_PIXEL_SRC_STATUS__SHIFT 0x00000004
+#define DCP_CRC_CONTROL__DCP_CRC_ENABLE_MASK 0x00000001L
+#define DCP_CRC_CONTROL__DCP_CRC_ENABLE__SHIFT 0x00000000
+#define DCP_CRC_CONTROL__DCP_CRC_LINE_SEL_MASK 0x00000300L
+#define DCP_CRC_CONTROL__DCP_CRC_LINE_SEL__SHIFT 0x00000008
+#define DCP_CRC_CONTROL__DCP_CRC_SOURCE_SEL_MASK 0x0000001cL
+#define DCP_CRC_CONTROL__DCP_CRC_SOURCE_SEL__SHIFT 0x00000002
+#define DCP_CRC_CURRENT__DCP_CRC_CURRENT_MASK 0xffffffffL
+#define DCP_CRC_CURRENT__DCP_CRC_CURRENT__SHIFT 0x00000000
+#define DCP_CRC_LAST__DCP_CRC_LAST_MASK 0xffffffffL
+#define DCP_CRC_LAST__DCP_CRC_LAST__SHIFT 0x00000000
+#define DCP_CRC_MASK__DCP_CRC_MASK_MASK 0xffffffffL
+#define DCP_CRC_MASK__DCP_CRC_MASK__SHIFT 0x00000000
+#define DCP_DEBUG2__DCP_DEBUG2_MASK 0xffffffffL
+#define DCP_DEBUG2__DCP_DEBUG2__SHIFT 0x00000000
+#define DCP_DEBUG__DCP_DEBUG_MASK 0xffffffffL
+#define DCP_DEBUG__DCP_DEBUG__SHIFT 0x00000000
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_DATA_MASK 0x0003ffffL
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_DATA__SHIFT 0x00000000
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_INDEX_MASK 0x07f00000L
+#define DCP_FP_CONVERTED_FIELD__DCP_FP_CONVERTED_FIELD_INDEX__SHIFT 0x00000014
+#define DC_PGCNTL_STATUS_REG__DCPG_ECO_DEBUG_MASK 0xffff0000L
+#define DC_PGCNTL_STATUS_REG__DCPG_ECO_DEBUG__SHIFT 0x00000010
+#define DC_PGCNTL_STATUS_REG__IPREQ_IGNORE_STATUS_MASK 0x00000004L
+#define DC_PGCNTL_STATUS_REG__IPREQ_IGNORE_STATUS__SHIFT 0x00000002
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_BUSY_MASK 0x00000001L
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_BUSY__SHIFT 0x00000000
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_FORCE_MASK 0x00000002L
+#define DC_PGCNTL_STATUS_REG__SWREQ_RWOP_FORCE__SHIFT 0x00000001
+#define DC_PGFSM_CONFIG_REG__PGFSM_CONFIG_REG_MASK 0xffffffffL
+#define DC_PGFSM_CONFIG_REG__PGFSM_CONFIG_REG__SHIFT 0x00000000
+#define DC_PGFSM_WRITE_REG__PGFSM_WRITE_REG_MASK 0xffffffffL
+#define DC_PGFSM_WRITE_REG__PGFSM_WRITE_REG__SHIFT 0x00000000
+#define DCP_GSL_CONTROL__DCP_GSL0_EN_MASK 0x00000001L
+#define DCP_GSL_CONTROL__DCP_GSL0_EN__SHIFT 0x00000000
+#define DCP_GSL_CONTROL__DCP_GSL1_EN_MASK 0x00000002L
+#define DCP_GSL_CONTROL__DCP_GSL1_EN__SHIFT 0x00000001
+#define DCP_GSL_CONTROL__DCP_GSL2_EN_MASK 0x00000004L
+#define DCP_GSL_CONTROL__DCP_GSL2_EN__SHIFT 0x00000002
+#define DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING_MASK 0x08000000L
+#define DCP_GSL_CONTROL__DCP_GSL_DELAY_SURFACE_UPDATE_PENDING__SHIFT 0x0000001b
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY_MASK 0xf0000000L
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_CHECK_DELAY__SHIFT 0x0000001c
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY_MASK 0x0000f000L
+#define DCP_GSL_CONTROL__DCP_GSL_HSYNC_FLIP_FORCE_DELAY__SHIFT 0x0000000c
+#define DCP_GSL_CONTROL__DCP_GSL_MASTER_EN_MASK 0x00010000L
+#define DCP_GSL_CONTROL__DCP_GSL_MASTER_EN__SHIFT 0x00000010
+#define DCP_GSL_CONTROL__DCP_GSL_MODE_MASK 0x00000300L
+#define DCP_GSL_CONTROL__DCP_GSL_MODE__SHIFT 0x00000008
+#define DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE_MASK 0x03000000L
+#define DCP_GSL_CONTROL__DCP_GSL_SYNC_SOURCE__SHIFT 0x00000018
+#define DCPG_TEST_DEBUG_DATA__DCPG_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCPG_TEST_DEBUG_DATA__DCPG_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCPG_TEST_DEBUG_INDEX__DCPG_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO_MASK 0x0000c000L
+#define DC_PINSTRAPS__DC_PINSTRAPS_AUDIO__SHIFT 0x0000000e
+#define DC_PINSTRAPS__DC_PINSTRAPS_BIF_CEC_DIS_MASK 0x00000400L
+#define DC_PINSTRAPS__DC_PINSTRAPS_BIF_CEC_DIS__SHIFT 0x0000000a
+#define DC_PINSTRAPS__DC_PINSTRAPS_CCBYPASS_MASK 0x00010000L
+#define DC_PINSTRAPS__DC_PINSTRAPS_CCBYPASS__SHIFT 0x00000010
+#define DC_PINSTRAPS__DC_PINSTRAPS_SMS_EN_HARD_MASK 0x00002000L
+#define DC_PINSTRAPS__DC_PINSTRAPS_SMS_EN_HARD__SHIFT 0x0000000d
+#define DC_PINSTRAPS__DC_PINSTRAPS_VIP_DEVICE_MASK 0x00000800L
+#define DC_PINSTRAPS__DC_PINSTRAPS_VIP_DEVICE__SHIFT 0x0000000b
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_20BPP_MASK 0x0000000fL
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_20BPP__SHIFT 0x00000000
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_30BPP_MASK 0x000000f0L
+#define DCP_LB_DATA_GAP_BETWEEN_CHUNK__DCP_LB_GAP_BETWEEN_CHUNK_30BPP__SHIFT 0x00000004
+#define DCP_RANDOM_SEEDS__DCP_RAND_B_SEED_MASK 0x00ff0000L
+#define DCP_RANDOM_SEEDS__DCP_RAND_B_SEED__SHIFT 0x00000010
+#define DCP_RANDOM_SEEDS__DCP_RAND_G_SEED_MASK 0x0000ff00L
+#define DCP_RANDOM_SEEDS__DCP_RAND_G_SEED__SHIFT 0x00000008
+#define DCP_RANDOM_SEEDS__DCP_RAND_R_SEED_MASK 0x000000ffL
+#define DCP_RANDOM_SEEDS__DCP_RAND_R_SEED__SHIFT 0x00000000
+#define DCP_SPATIAL_DITHER_CNTL__DCP_FRAME_RANDOM_ENABLE_MASK 0x00000100L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_FRAME_RANDOM_ENABLE__SHIFT 0x00000008
+#define DCP_SPATIAL_DITHER_CNTL__DCP_HIGHPASS_RANDOM_ENABLE_MASK 0x00000400L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_HIGHPASS_RANDOM_ENABLE__SHIFT 0x0000000a
+#define DCP_SPATIAL_DITHER_CNTL__DCP_RGB_RANDOM_ENABLE_MASK 0x00000200L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_RGB_RANDOM_ENABLE__SHIFT 0x00000009
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_DEPTH_MASK 0x00000040L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_DEPTH__SHIFT 0x00000006
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_EN_MASK 0x00000001L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_EN__SHIFT 0x00000000
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_MODE_MASK 0x00000030L
+#define DCP_SPATIAL_DITHER_CNTL__DCP_SPATIAL_DITHER_MODE__SHIFT 0x00000004
+#define DCP_TEST_DEBUG_DATA__DCP_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DCP_TEST_DEBUG_DATA__DCP_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DCP_TEST_DEBUG_INDEX__DCP_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_DELAY_MASK 0x00000007L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_DELAY__SHIFT 0x00000000
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_TIMEOUT_DIS_MASK 0x00000008L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT0_RDWR_TIMEOUT_DIS__SHIFT 0x00000003
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_DELAY_MASK 0x00000070L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_DELAY__SHIFT 0x00000004
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_TIMEOUT_DIS_MASK 0x00000080L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT1_RDWR_TIMEOUT_DIS__SHIFT 0x00000007
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_DELAY_MASK 0x00000700L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_DELAY__SHIFT 0x00000008
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_TIMEOUT_DIS_MASK 0x00000800L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT2_RDWR_TIMEOUT_DIS__SHIFT 0x0000000b
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_DELAY_MASK 0x00007000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_DELAY__SHIFT 0x0000000c
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_TIMEOUT_DIS_MASK 0x00008000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT3_RDWR_TIMEOUT_DIS__SHIFT 0x0000000f
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_DELAY_MASK 0x00070000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_DELAY__SHIFT 0x00000010
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_TIMEOUT_DIS_MASK 0x00080000L
+#define DC_RBBMIF_RDWR_CNTL1__DC_RBBMIF_CLIENT4_RDWR_TIMEOUT_DIS__SHIFT 0x00000013
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_DELAY_MASK 0x00000007L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_DELAY__SHIFT 0x00000000
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_TIMEOUT_DIS_MASK 0x00000008L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT8_RDWR_TIMEOUT_DIS__SHIFT 0x00000003
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_DELAY_MASK 0x00000070L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_DELAY__SHIFT 0x00000004
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_TIMEOUT_DIS_MASK 0x00000080L
+#define DC_RBBMIF_RDWR_CNTL2__DC_RBBMIF_CLIENT9_RDWR_TIMEOUT_DIS__SHIFT 0x00000007
+#define DC_REF_CLK_CNTL__GENLK_CLK_OUTPUT_SEL_MASK 0x00000300L
+#define DC_REF_CLK_CNTL__GENLK_CLK_OUTPUT_SEL__SHIFT 0x00000008
+#define DC_REF_CLK_CNTL__HSYNCA_OUTPUT_SEL_MASK 0x00000003L
+#define DC_REF_CLK_CNTL__HSYNCA_OUTPUT_SEL__SHIFT 0x00000000
+#define DC_XDMA_INTERFACE_CNTL__DC_FLIP_PENDING_TO_DCP_MASK 0x00400000L
+#define DC_XDMA_INTERFACE_CNTL__DC_FLIP_PENDING_TO_DCP__SHIFT 0x00000016
+#define DC_XDMA_INTERFACE_CNTL__DC_XDMA_FLIP_PENDING_MASK 0x00010000L
+#define DC_XDMA_INTERFACE_CNTL__DC_XDMA_FLIP_PENDING__SHIFT 0x00000010
+#define DC_XDMA_INTERFACE_CNTL__XDMA_M_FLIP_PENDING_TO_DCP_MASK 0x00100000L
+#define DC_XDMA_INTERFACE_CNTL__XDMA_M_FLIP_PENDING_TO_DCP__SHIFT 0x00000014
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_ENABLE_MASK 0x0000003fL
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_ENABLE__SHIFT 0x00000000
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_SEL_MASK 0x00000700L
+#define DC_XDMA_INTERFACE_CNTL__XDMA_PIPE_SEL__SHIFT 0x00000008
+#define DC_XDMA_INTERFACE_CNTL__XDMA_S_FLIP_PENDING_TO_DCP_MASK 0x00200000L
+#define DC_XDMA_INTERFACE_CNTL__XDMA_S_FLIP_PENDING_TO_DCP__SHIFT 0x00000015
+#define DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE_MASK 0x00003000L
+#define DEGAMMA_CONTROL__CURSOR_DEGAMMA_MODE__SHIFT 0x0000000c
+#define DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE_MASK 0x00000003L
+#define DEGAMMA_CONTROL__GRPH_DEGAMMA_MODE__SHIFT 0x00000000
+#define DEGAMMA_CONTROL__OVL_DEGAMMA_MODE_MASK 0x00000030L
+#define DEGAMMA_CONTROL__OVL_DEGAMMA_MODE__SHIFT 0x00000004
+#define DENORM_CONTROL__DENORM_MODE_MASK 0x00000007L
+#define DENORM_CONTROL__DENORM_MODE__SHIFT 0x00000000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE_MASK 0x00080000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_DONE__SHIFT 0x00000013
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_MODE_MASK 0x00018000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHG_MODE__SHIFT 0x0000000f
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHGTOG_MASK 0x00020000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_CHGTOG__SHIFT 0x00000011
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_DONETOG_MASK 0x00040000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_DONETOG__SHIFT 0x00000012
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER_MASK 0x00007f00L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_RDIVIDER__SHIFT 0x00000008
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER_MASK 0x0000007fL
+#define DENTIST_DISPCLK_CNTL__DENTIST_DISPCLK_WDIVIDER__SHIFT 0x00000000
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHG_DONE_MASK 0x00100000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHG_DONE__SHIFT 0x00000014
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHGTOG_MASK 0x00200000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_CHGTOG__SHIFT 0x00000015
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_DONETOG_MASK 0x00400000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_DONETOG__SHIFT 0x00000016
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_WDIVIDER_MASK 0x7f000000L
+#define DENTIST_DISPCLK_CNTL__DENTIST_DPREFCLK_WDIVIDER__SHIFT 0x00000018
+#define DIG_BE_CNTL__DIG_FE_SOURCE_SELECT_MASK 0x00003f00L
+#define DIG_BE_CNTL__DIG_FE_SOURCE_SELECT__SHIFT 0x00000008
+#define DIG_BE_CNTL__DIG_HPD_SELECT_MASK 0x70000000L
+#define DIG_BE_CNTL__DIG_HPD_SELECT__SHIFT 0x0000001c
+#define DIG_BE_CNTL__DIG_MODE_MASK 0x00070000L
+#define DIG_BE_CNTL__DIG_MODE__SHIFT 0x00000010
+#define DIG_BE_EN_CNTL__DIG_ENABLE_MASK 0x00000001L
+#define DIG_BE_EN_CNTL__DIG_ENABLE__SHIFT 0x00000000
+#define DIG_BE_EN_CNTL__DIG_SYMCLK_BE_ON_MASK 0x00000100L
+#define DIG_BE_EN_CNTL__DIG_SYMCLK_BE_ON__SHIFT 0x00000008
+#define DIG_CLOCK_PATTERN__DIG_CLOCK_PATTERN_MASK 0x000003ffL
+#define DIG_CLOCK_PATTERN__DIG_CLOCK_PATTERN__SHIFT 0x00000000
+#define DIG_DISPCLK_SWITCH_CNTL__DIG_DISPCLK_SWITCH_POINT_MASK 0x00000001L
+#define DIG_DISPCLK_SWITCH_CNTL__DIG_DISPCLK_SWITCH_POINT__SHIFT 0x00000000
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK_MASK 0x00000100L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_ACK__SHIFT 0x00000008
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK 0x00000010L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK_MASK 0x00001000L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT_MASK__SHIFT 0x0000000c
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_INT__SHIFT 0x00000004
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED_MASK 0x00000001L
+#define DIG_DISPCLK_SWITCH_STATUS__DIG_DISPCLK_SWITCH_ALLOWED__SHIFT 0x00000000
+#define DIG_FE_CNTL__DIG_DUAL_LINK_ENABLE_MASK 0x00010000L
+#define DIG_FE_CNTL__DIG_DUAL_LINK_ENABLE__SHIFT 0x00000010
+#define DIG_FE_CNTL__DIG_RB_SWITCH_EN_MASK 0x00100000L
+#define DIG_FE_CNTL__DIG_RB_SWITCH_EN__SHIFT 0x00000014
+#define DIG_FE_CNTL__DIG_SOURCE_SELECT_MASK 0x00000007L
+#define DIG_FE_CNTL__DIG_SOURCE_SELECT__SHIFT 0x00000000
+#define DIG_FE_CNTL__DIG_START_MASK 0x00000400L
+#define DIG_FE_CNTL__DIG_START__SHIFT 0x0000000a
+#define DIG_FE_CNTL__DIG_STEREOSYNC_GATE_EN_MASK 0x00000100L
+#define DIG_FE_CNTL__DIG_STEREOSYNC_GATE_EN__SHIFT 0x00000008
+#define DIG_FE_CNTL__DIG_STEREOSYNC_SELECT_MASK 0x00000070L
+#define DIG_FE_CNTL__DIG_STEREOSYNC_SELECT__SHIFT 0x00000004
+#define DIG_FE_CNTL__DIG_SWAP_MASK 0x00040000L
+#define DIG_FE_CNTL__DIG_SWAP__SHIFT 0x00000012
+#define DIG_FE_CNTL__DIG_SYMCLK_FE_ON_MASK 0x01000000L
+#define DIG_FE_CNTL__DIG_SYMCLK_FE_ON__SHIFT 0x00000018
+#define DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000fc00L
+#define DIG_FIFO_STATUS__DIG_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x0000000a
+#define DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED_MASK 0x20000000L
+#define DIG_FIFO_STATUS__DIG_FIFO_CALIBRATED__SHIFT 0x0000001d
+#define DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK_MASK 0x00000100L
+#define DIG_FIFO_STATUS__DIG_FIFO_ERROR_ACK__SHIFT 0x00000008
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000L
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x0000001e
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000L
+#define DIG_FIFO_STATUS__DIG_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x0000001f
+#define DIG_FIFO_STATUS__DIG_FIFO_LEVEL_ERROR_MASK 0x00000001L
+#define DIG_FIFO_STATUS__DIG_FIFO_LEVEL_ERROR__SHIFT 0x00000000
+#define DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL_MASK 0x001f0000L
+#define DIG_FIFO_STATUS__DIG_FIFO_MAXIMUM_LEVEL__SHIFT 0x00000010
+#define DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL_MASK 0x03c00000L
+#define DIG_FIFO_STATUS__DIG_FIFO_MINIMUM_LEVEL__SHIFT 0x00000016
+#define DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL_MASK 0x000000fcL
+#define DIG_FIFO_STATUS__DIG_FIFO_OVERWRITE_LEVEL__SHIFT 0x00000002
+#define DIG_FIFO_STATUS__DIG_FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000002L
+#define DIG_FIFO_STATUS__DIG_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x00000001
+#define DIG_LANE_ENABLE__DIG_CLK_EN_MASK 0x00000100L
+#define DIG_LANE_ENABLE__DIG_CLK_EN__SHIFT 0x00000008
+#define DIG_LANE_ENABLE__DIG_LANE0EN_MASK 0x00000001L
+#define DIG_LANE_ENABLE__DIG_LANE0EN__SHIFT 0x00000000
+#define DIG_LANE_ENABLE__DIG_LANE1EN_MASK 0x00000002L
+#define DIG_LANE_ENABLE__DIG_LANE1EN__SHIFT 0x00000001
+#define DIG_LANE_ENABLE__DIG_LANE2EN_MASK 0x00000004L
+#define DIG_LANE_ENABLE__DIG_LANE2EN__SHIFT 0x00000002
+#define DIG_LANE_ENABLE__DIG_LANE3EN_MASK 0x00000008L
+#define DIG_LANE_ENABLE__DIG_LANE3EN__SHIFT 0x00000003
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_DATA_SEL_MASK 0x00000300L
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_DATA_SEL__SHIFT 0x00000008
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_EN_MASK 0x00000001L
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_EN__SHIFT 0x00000000
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_LINK_SEL_MASK 0x00000010L
+#define DIG_OUTPUT_CRC_CNTL__DIG_OUTPUT_CRC_LINK_SEL__SHIFT 0x00000004
+#define DIG_OUTPUT_CRC_RESULT__DIG_OUTPUT_CRC_RESULT_MASK 0x3fffffffL
+#define DIG_OUTPUT_CRC_RESULT__DIG_OUTPUT_CRC_RESULT__SHIFT 0x00000000
+#define DIG_RANDOM_PATTERN_SEED__DIG_RANDOM_PATTERN_SEED_MASK 0x00ffffffL
+#define DIG_RANDOM_PATTERN_SEED__DIG_RANDOM_PATTERN_SEED__SHIFT 0x00000000
+#define DIG_RANDOM_PATTERN_SEED__DIG_RAN_PAT_DURING_DE_ONLY_MASK 0x01000000L
+#define DIG_RANDOM_PATTERN_SEED__DIG_RAN_PAT_DURING_DE_ONLY__SHIFT 0x00000018
+#define DIG_SOFT_RESET__DIGA_BE_SOFT_RESET_MASK 0x00000002L
+#define DIG_SOFT_RESET__DIGA_BE_SOFT_RESET__SHIFT 0x00000001
+#define DIG_SOFT_RESET__DIGA_FE_SOFT_RESET_MASK 0x00000001L
+#define DIG_SOFT_RESET__DIGA_FE_SOFT_RESET__SHIFT 0x00000000
+#define DIG_SOFT_RESET__DIGB_BE_SOFT_RESET_MASK 0x00000020L
+#define DIG_SOFT_RESET__DIGB_BE_SOFT_RESET__SHIFT 0x00000005
+#define DIG_SOFT_RESET__DIGB_FE_SOFT_RESET_MASK 0x00000010L
+#define DIG_SOFT_RESET__DIGB_FE_SOFT_RESET__SHIFT 0x00000004
+#define DIG_SOFT_RESET__DIGC_BE_SOFT_RESET_MASK 0x00000200L
+#define DIG_SOFT_RESET__DIGC_BE_SOFT_RESET__SHIFT 0x00000009
+#define DIG_SOFT_RESET__DIGC_FE_SOFT_RESET_MASK 0x00000100L
+#define DIG_SOFT_RESET__DIGC_FE_SOFT_RESET__SHIFT 0x00000008
+#define DIG_SOFT_RESET__DIGD_BE_SOFT_RESET_MASK 0x00002000L
+#define DIG_SOFT_RESET__DIGD_BE_SOFT_RESET__SHIFT 0x0000000d
+#define DIG_SOFT_RESET__DIGD_FE_SOFT_RESET_MASK 0x00001000L
+#define DIG_SOFT_RESET__DIGD_FE_SOFT_RESET__SHIFT 0x0000000c
+#define DIG_SOFT_RESET__DIGE_BE_SOFT_RESET_MASK 0x00020000L
+#define DIG_SOFT_RESET__DIGE_BE_SOFT_RESET__SHIFT 0x00000011
+#define DIG_SOFT_RESET__DIGE_FE_SOFT_RESET_MASK 0x00010000L
+#define DIG_SOFT_RESET__DIGE_FE_SOFT_RESET__SHIFT 0x00000010
+#define DIG_SOFT_RESET__DIGF_BE_SOFT_RESET_MASK 0x00200000L
+#define DIG_SOFT_RESET__DIGF_BE_SOFT_RESET__SHIFT 0x00000015
+#define DIG_SOFT_RESET__DIGF_FE_SOFT_RESET_MASK 0x00100000L
+#define DIG_SOFT_RESET__DIGF_FE_SOFT_RESET__SHIFT 0x00000014
+#define DIG_TEST_PATTERN__DIG_HALF_CLOCK_PATTERN_SEL_MASK 0x00000002L
+#define DIG_TEST_PATTERN__DIG_HALF_CLOCK_PATTERN_SEL__SHIFT 0x00000001
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_OUT_EN_MASK 0x00000010L
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_OUT_EN__SHIFT 0x00000004
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_RESET_MASK 0x00000020L
+#define DIG_TEST_PATTERN__DIG_RANDOM_PATTERN_RESET__SHIFT 0x00000005
+#define DIG_TEST_PATTERN__DIG_STATIC_TEST_PATTERN_MASK 0x03ff0000L
+#define DIG_TEST_PATTERN__DIG_STATIC_TEST_PATTERN__SHIFT 0x00000010
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_EXTERNAL_RESET_EN_MASK 0x00000040L
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_EXTERNAL_RESET_EN__SHIFT 0x00000006
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_OUT_EN_MASK 0x00000001L
+#define DIG_TEST_PATTERN__DIG_TEST_PATTERN_OUT_EN__SHIFT 0x00000000
+#define DIG_TEST_PATTERN__LVDS_EYE_PATTERN_MASK 0x00000100L
+#define DIG_TEST_PATTERN__LVDS_EYE_PATTERN__SHIFT 0x00000008
+#define DIG_TEST_PATTERN__LVDS_TEST_CLOCK_DATA_MASK 0x00000004L
+#define DIG_TEST_PATTERN__LVDS_TEST_CLOCK_DATA__SHIFT 0x00000002
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_OFF_DELAY_MASK 0x00000ff0L
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_OFF_DELAY__SHIFT 0x00000004
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_ON_DELAY_MASK 0x0000000fL
+#define DISPCLK_CGTT_BLK_CTRL_REG__DISPCLK_TURN_ON_DELAY__SHIFT 0x00000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_OVR_EN_MASK 0x40000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_OVR_EN__SHIFT 0x0000001e
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_RESET_MASK 0x10000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_RESET__SHIFT 0x0000001c
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_STATE_MASK 0x20000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DCCG_FIFO_ERRDET_STATE__SHIFT 0x0000001d
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_CHG_FWD_CORR_DISABLE_MASK 0x80000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_CHG_FWD_CORR_DISABLE__SHIFT 0x0000001f
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_FREQ_RAMP_DONE_MASK 0x00100000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_FREQ_RAMP_DONE__SHIFT 0x00000014
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_MAX_ERRDET_CYCLES_MASK 0x0e000000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_MAX_ERRDET_CYCLES__SHIFT 0x00000019
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_DELAY_MASK 0x00003fffL
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_DELAY__SHIFT 0x00000000
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_SIZE_MASK 0x000f0000L
+#define DISPCLK_FREQ_CHANGE_CNTL__DISPCLK_STEP_SIZE__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_MASK 0x40000000L
+#define DISP_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT__SHIFT 0x0000001e
+#define DISP_INTERRUPT_STATUS__ABM1_HG_READY_INT_MASK 0x10000000L
+#define DISP_INTERRUPT_STATUS__ABM1_HG_READY_INT__SHIFT 0x0000001c
+#define DISP_INTERRUPT_STATUS__ABM1_LS_READY_INT_MASK 0x20000000L
+#define DISP_INTERRUPT_STATUS__ABM1_LS_READY_INT__SHIFT 0x0000001d
+#define DISP_INTERRUPT_STATUS__AUX1_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS__AUX1_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS__AUX1_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS__AUX1_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__AUX3_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__CRTC3_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DC_HPD3_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DIGC_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DISP_INTERRUPT_STATUS_CONTINUE3_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__DISP_INTERRUPT_STATUS_CONTINUE3__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__LB_D3_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE2__SCL_DISP3_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE2__SCL_DISP3_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__AUX4_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__CRTC4_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DC_HPD4_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DIGD_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DISP_INTERRUPT_STATUS_CONTINUE4_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__DISP_INTERRUPT_STATUS_CONTINUE4__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__LB_D4_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE3__SCL_DISP4_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE3__SCL_DISP4_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__AUX5_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__CRTC5_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DC_HPD5_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DIGE_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DISP_INTERRUPT_STATUS_CONTINUE5_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__DISP_INTERRUPT_STATUS_CONTINUE5__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__LB_D5_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE4__SCL_DISP5_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE4__SCL_DISP5_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__AUX6_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__CRTC6_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DC_HPD6_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__DIGF_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__LB_D6_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE5__SCL_DISP6_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE5__SCL_DISP6_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_LS_DONE_INTERRUPT_MASK 0x00100000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_LS_DONE_INTERRUPT__SHIFT 0x00000014
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_SW_DONE_INTERRUPT_MASK 0x00080000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__AUX2_SW_DONE_INTERRUPT__SHIFT 0x00000013
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS_CONTINUE__CRTC2_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DC_HPD2_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DIGB_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_INTERRUPT_STATUS_CONTINUE2_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_INTERRUPT_STATUS_CONTINUE2__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_TIMER_INTERRUPT_MASK 0x01000000L
+#define DISP_INTERRUPT_STATUS_CONTINUE__DISP_TIMER_INTERRUPT__SHIFT 0x00000018
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS_CONTINUE__LB_D2_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS_CONTINUE__SCL_DISP2_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS_CONTINUE__SCL_DISP2_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_COUNT_NOW_INTERRUPT_MASK 0x00000040L
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_COUNT_NOW_INTERRUPT__SHIFT 0x00000006
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_VSYNC_NEXT_LINE_INTERRUPT_MASK 0x00000020L
+#define DISP_INTERRUPT_STATUS__CRTC1_FORCE_VSYNC_NEXT_LINE_INTERRUPT__SHIFT 0x00000005
+#define DISP_INTERRUPT_STATUS__CRTC1_SET_V_TOTAL_MIN_EVENT_OCCURED_INT_MASK 0x00000400L
+#define DISP_INTERRUPT_STATUS__CRTC1_SET_V_TOTAL_MIN_EVENT_OCCURED_INT__SHIFT 0x0000000a
+#define DISP_INTERRUPT_STATUS__CRTC1_SNAPSHOT_INTERRUPT_MASK 0x00000010L
+#define DISP_INTERRUPT_STATUS__CRTC1_SNAPSHOT_INTERRUPT__SHIFT 0x00000004
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGA_INTERRUPT_MASK 0x00000080L
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGA_INTERRUPT__SHIFT 0x00000007
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGB_INTERRUPT_MASK 0x00000100L
+#define DISP_INTERRUPT_STATUS__CRTC1_TRIGB_INTERRUPT__SHIFT 0x00000008
+#define DISP_INTERRUPT_STATUS__CRTC1_VSYNC_NOM_INTERRUPT_MASK 0x00000200L
+#define DISP_INTERRUPT_STATUS__CRTC1_VSYNC_NOM_INTERRUPT__SHIFT 0x00000009
+#define DISP_INTERRUPT_STATUS__DACA_AUTODETECT_INTERRUPT_MASK 0x00400000L
+#define DISP_INTERRUPT_STATUS__DACA_AUTODETECT_INTERRUPT__SHIFT 0x00000016
+#define DISP_INTERRUPT_STATUS__DACB_AUTODETECT_INTERRUPT_MASK 0x00800000L
+#define DISP_INTERRUPT_STATUS__DACB_AUTODETECT_INTERRUPT__SHIFT 0x00000017
+#define DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT_MASK 0x00020000L
+#define DISP_INTERRUPT_STATUS__DC_HPD1_INTERRUPT__SHIFT 0x00000011
+#define DISP_INTERRUPT_STATUS__DC_HPD1_RX_INTERRUPT_MASK 0x00040000L
+#define DISP_INTERRUPT_STATUS__DC_HPD1_RX_INTERRUPT__SHIFT 0x00000012
+#define DISP_INTERRUPT_STATUS__DC_I2C_HW_DONE_INTERRUPT_MASK 0x02000000L
+#define DISP_INTERRUPT_STATUS__DC_I2C_HW_DONE_INTERRUPT__SHIFT 0x00000019
+#define DISP_INTERRUPT_STATUS__DC_I2C_SW_DONE_INTERRUPT_MASK 0x01000000L
+#define DISP_INTERRUPT_STATUS__DC_I2C_SW_DONE_INTERRUPT__SHIFT 0x00000018
+#define DISP_INTERRUPT_STATUS__DIGA_DISPCLK_SWITCH_ALLOWED_INTERRUPT_MASK 0x00200000L
+#define DISP_INTERRUPT_STATUS__DIGA_DISPCLK_SWITCH_ALLOWED_INTERRUPT__SHIFT 0x00000015
+#define DISP_INTERRUPT_STATUS__DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT_MASK 0x00008000L
+#define DISP_INTERRUPT_STATUS__DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT__SHIFT 0x0000000f
+#define DISP_INTERRUPT_STATUS__DIGA_DP_VID_STREAM_DISABLE_INTERRUPT_MASK 0x00010000L
+#define DISP_INTERRUPT_STATUS__DIGA_DP_VID_STREAM_DISABLE_INTERRUPT__SHIFT 0x00000010
+#define DISP_INTERRUPT_STATUS__DISP_INTERRUPT_STATUS_CONTINUE_MASK 0x80000000L
+#define DISP_INTERRUPT_STATUS__DISP_INTERRUPT_STATUS_CONTINUE__SHIFT 0x0000001f
+#define DISP_INTERRUPT_STATUS__DMCU_SCP_INT_MASK 0x08000000L
+#define DISP_INTERRUPT_STATUS__DMCU_SCP_INT__SHIFT 0x0000001b
+#define DISP_INTERRUPT_STATUS__DMCU_UC_INTERNAL_INT_MASK 0x04000000L
+#define DISP_INTERRUPT_STATUS__DMCU_UC_INTERNAL_INT__SHIFT 0x0000001a
+#define DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT_MASK 0x00000008L
+#define DISP_INTERRUPT_STATUS__LB_D1_VBLANK_INTERRUPT__SHIFT 0x00000003
+#define DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT_MASK 0x00000004L
+#define DISP_INTERRUPT_STATUS__LB_D1_VLINE_INTERRUPT__SHIFT 0x00000002
+#define DISP_INTERRUPT_STATUS__SCL_DISP1_MODE_CHANGE_INTERRUPT_MASK 0x00000001L
+#define DISP_INTERRUPT_STATUS__SCL_DISP1_MODE_CHANGE_INTERRUPT__SHIFT 0x00000000
+#define DISPOUT_STEREOSYNC_SEL__GENERICA_STEREOSYNC_SEL_MASK 0x00000007L
+#define DISPOUT_STEREOSYNC_SEL__GENERICA_STEREOSYNC_SEL__SHIFT 0x00000000
+#define DISPOUT_STEREOSYNC_SEL__GENERICB_STEREOSYNC_SEL_MASK 0x00070000L
+#define DISPOUT_STEREOSYNC_SEL__GENERICB_STEREOSYNC_SEL__SHIFT 0x00000010
+#define DISPPLL_BG_CNTL__DISPPLL_BG_ADJ_MASK 0x000000f0L
+#define DISPPLL_BG_CNTL__DISPPLL_BG_ADJ__SHIFT 0x00000004
+#define DISPPLL_BG_CNTL__DISPPLL_BG_PDN_MASK 0x00000001L
+#define DISPPLL_BG_CNTL__DISPPLL_BG_PDN__SHIFT 0x00000000
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT_MASK 0x01ffffffL
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_COUNT__SHIFT 0x00000000
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE_MASK 0x02000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_ENABLE__SHIFT 0x00000019
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_MASK 0x40000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_MSK_MASK 0x08000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_MSK__SHIFT 0x0000001b
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_RUNNING_MASK 0x04000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_RUNNING__SHIFT 0x0000001a
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT__SHIFT 0x0000001e
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK_MASK 0x20000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_AK__SHIFT 0x0000001d
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT_MASK 0x10000000L
+#define DISP_TIMER_CONTROL__DISP_TIMER_INT_STAT__SHIFT 0x0000001c
+#define DMCU_CTRL__DISABLE_IRQ_TO_UC_MASK 0x00000004L
+#define DMCU_CTRL__DISABLE_IRQ_TO_UC__SHIFT 0x00000002
+#define DMCU_CTRL__DISABLE_XIRQ_TO_UC_MASK 0x00000008L
+#define DMCU_CTRL__DISABLE_XIRQ_TO_UC__SHIFT 0x00000003
+#define DMCU_CTRL__DMCU_ENABLE_MASK 0x00000010L
+#define DMCU_CTRL__DMCU_ENABLE__SHIFT 0x00000004
+#define DMCU_CTRL__IGNORE_PWRMGT_MASK 0x00000002L
+#define DMCU_CTRL__IGNORE_PWRMGT__SHIFT 0x00000001
+#define DMCU_CTRL__RESET_UC_MASK 0x00000001L
+#define DMCU_CTRL__RESET_UC__SHIFT 0x00000000
+#define DMCU_CTRL__UC_REG_RD_TIMEOUT_MASK 0xffc00000L
+#define DMCU_CTRL__UC_REG_RD_TIMEOUT__SHIFT 0x00000016
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_ADDR_MASK 0x0000ffffL
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_ADDR__SHIFT 0x00000000
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BE_MASK 0x000f0000L
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BE__SHIFT 0x00000010
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BYTE_MODE_MASK 0x00100000L
+#define DMCU_ERAM_RD_CTRL__ERAM_RD_BYTE_MODE__SHIFT 0x00000014
+#define DMCU_ERAM_RD_DATA__ERAM_RD_DATA_MASK 0xffffffffL
+#define DMCU_ERAM_RD_DATA__ERAM_RD_DATA__SHIFT 0x00000000
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_ADDR_MASK 0x0000ffffL
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_ADDR__SHIFT 0x00000000
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BE_MASK 0x000f0000L
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BE__SHIFT 0x00000010
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BYTE_MODE_MASK 0x00100000L
+#define DMCU_ERAM_WR_CTRL__ERAM_WR_BYTE_MODE__SHIFT 0x00000014
+#define DMCU_ERAM_WR_DATA__ERAM_WR_DATA_MASK 0xffffffffL
+#define DMCU_ERAM_WR_DATA__ERAM_WR_DATA__SHIFT 0x00000000
+#define DMCU_EVENT_TRIGGER__GEN_SW_INT_TO_UC_MASK 0x00000001L
+#define DMCU_EVENT_TRIGGER__GEN_SW_INT_TO_UC__SHIFT 0x00000000
+#define DMCU_EVENT_TRIGGER__GEN_UC_INTERNAL_INT_TO_HOST_MASK 0x00800000L
+#define DMCU_EVENT_TRIGGER__GEN_UC_INTERNAL_INT_TO_HOST__SHIFT 0x00000017
+#define DMCU_EVENT_TRIGGER__UC_INTERNAL_INT_CODE_MASK 0x007f0000L
+#define DMCU_EVENT_TRIGGER__UC_INTERNAL_INT_CODE__SHIFT 0x00000010
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_HI_SMPL_BYTE_POS_MASK 0x0000000cL
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_HI_SMPL_BYTE_POS__SHIFT 0x00000002
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_LO_SMPL_BYTE_POS_MASK 0x00000003L
+#define DMCU_FW_CHECKSUM_SMPL_BYTE_POS__DMCU_FW_CHECKSUM_LO_SMPL_BYTE_POS__SHIFT 0x00000000
+#define DMCU_FW_CS_HI__FW_CHECKSUM_HI_MASK 0xffffffffL
+#define DMCU_FW_CS_HI__FW_CHECKSUM_HI__SHIFT 0x00000000
+#define DMCU_FW_CS_LO__FW_CHECKSUM_LO_MASK 0xffffffffL
+#define DMCU_FW_CS_LO__FW_CHECKSUM_LO__SHIFT 0x00000000
+#define DMCU_FW_END_ADDR__FW_END_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_FW_END_ADDR__FW_END_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_FW_END_ADDR__FW_END_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_FW_END_ADDR__FW_END_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_FW_ISR_START_ADDR__FW_ISR_START_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_FW_START_ADDR__FW_START_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_FW_START_ADDR__FW_START_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_FW_START_ADDR__FW_START_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_FW_START_ADDR__FW_START_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_INT_CNT__DMCU_ABM1_BL_UPDATE_INT_CNT_MASK 0x00ff0000L
+#define DMCU_INT_CNT__DMCU_ABM1_BL_UPDATE_INT_CNT__SHIFT 0x00000010
+#define DMCU_INT_CNT__DMCU_ABM1_HG_READY_INT_CNT_MASK 0x000000ffL
+#define DMCU_INT_CNT__DMCU_ABM1_HG_READY_INT_CNT__SHIFT 0x00000000
+#define DMCU_INT_CNT__DMCU_ABM1_LS_READY_INT_CNT_MASK 0x0000ff00L
+#define DMCU_INT_CNT__DMCU_ABM1_LS_READY_INT_CNT__SHIFT 0x00000008
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_CLEAR_MASK 0x00000004L
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_CLEAR__SHIFT 0x00000002
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_OCCURRED_MASK 0x00000004L
+#define DMCU_INTERRUPT_STATUS__ABM1_BL_UPDATE_INT_OCCURRED__SHIFT 0x00000002
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_CLEAR_MASK 0x00000001L
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_CLEAR__SHIFT 0x00000000
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_OCCURRED_MASK 0x00000001L
+#define DMCU_INTERRUPT_STATUS__ABM1_HG_READY_INT_OCCURRED__SHIFT 0x00000000
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_CLEAR_MASK 0x00000002L
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_CLEAR__SHIFT 0x00000001
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_OCCURRED_MASK 0x00000002L
+#define DMCU_INTERRUPT_STATUS__ABM1_LS_READY_INT_OCCURRED__SHIFT 0x00000001
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_CLEAR_MASK 0x00040000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_CLEAR__SHIFT 0x00000012
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_OCCURRED_MASK 0x00040000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000012
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_CLEAR_MASK 0x00001000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_CLEAR__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_OCCURRED_MASK 0x00001000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE0_POWER_UP_INT_OCCURRED__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_CLEAR_MASK 0x00080000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_CLEAR__SHIFT 0x00000013
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_OCCURRED_MASK 0x00080000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000013
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_CLEAR_MASK 0x00002000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_CLEAR__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_OCCURRED_MASK 0x00002000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE1_POWER_UP_INT_OCCURRED__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_CLEAR_MASK 0x00100000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_CLEAR__SHIFT 0x00000014
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_OCCURRED_MASK 0x00100000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000014
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_CLEAR_MASK 0x00004000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_CLEAR__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_OCCURRED_MASK 0x00004000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE2_POWER_UP_INT_OCCURRED__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_CLEAR_MASK 0x00200000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_CLEAR__SHIFT 0x00000015
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_OCCURRED_MASK 0x00200000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000015
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_CLEAR_MASK 0x00008000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_CLEAR__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_OCCURRED_MASK 0x00008000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE3_POWER_UP_INT_OCCURRED__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_CLEAR_MASK 0x00400000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_CLEAR__SHIFT 0x00000016
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_OCCURRED_MASK 0x00400000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000016
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_CLEAR_MASK 0x00010000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_CLEAR__SHIFT 0x00000010
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_OCCURRED_MASK 0x00010000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE4_POWER_UP_INT_OCCURRED__SHIFT 0x00000010
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_CLEAR_MASK 0x00800000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_CLEAR__SHIFT 0x00000017
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_OCCURRED_MASK 0x00800000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_DOWN_INT_OCCURRED__SHIFT 0x00000017
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_CLEAR_MASK 0x00020000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_CLEAR__SHIFT 0x00000011
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_OCCURRED_MASK 0x00020000L
+#define DMCU_INTERRUPT_STATUS__DCPG_IHC_DCFE5_POWER_UP_INT_OCCURRED__SHIFT 0x00000011
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_CLEAR_MASK 0x00000100L
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_CLEAR__SHIFT 0x00000008
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_OCCURRED_MASK 0x00000100L
+#define DMCU_INTERRUPT_STATUS__EXTERNAL_SW_INT_OCCURRED__SHIFT 0x00000008
+#define DMCU_INTERRUPT_STATUS__MCP_INT_OCCURRED_MASK 0x00000008L
+#define DMCU_INTERRUPT_STATUS__MCP_INT_OCCURRED__SHIFT 0x00000003
+#define DMCU_INTERRUPT_STATUS__SCP_INT_OCCURRED_MASK 0x00000200L
+#define DMCU_INTERRUPT_STATUS__SCP_INT_OCCURRED__SHIFT 0x00000009
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_CLEAR_MASK 0x00000400L
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_CLEAR__SHIFT 0x0000000a
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_OCCURRED_MASK 0x00000400L
+#define DMCU_INTERRUPT_STATUS__UC_INTERNAL_INT_OCCURRED__SHIFT 0x0000000a
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_CLEAR_MASK 0x00000800L
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_CLEAR__SHIFT 0x0000000b
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_OCCURRED_MASK 0x00000800L
+#define DMCU_INTERRUPT_STATUS__UC_REG_RD_TIMEOUT_INT_OCCURRED__SHIFT 0x0000000b
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_CLEAR_MASK 0x01000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_CLEAR__SHIFT 0x00000018
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_OCCURRED_MASK 0x01000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK1_INT_OCCURRED__SHIFT 0x00000018
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_CLEAR_MASK 0x02000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_CLEAR__SHIFT 0x00000019
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_OCCURRED_MASK 0x02000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK2_INT_OCCURRED__SHIFT 0x00000019
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_CLEAR_MASK 0x04000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_CLEAR__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_OCCURRED_MASK 0x04000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK3_INT_OCCURRED__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_CLEAR_MASK 0x08000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_CLEAR__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_OCCURRED_MASK 0x08000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK4_INT_OCCURRED__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_CLEAR_MASK 0x10000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_CLEAR__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_OCCURRED_MASK 0x10000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK5_INT_OCCURRED__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_CLEAR_MASK 0x20000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_CLEAR__SHIFT 0x0000001d
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_OCCURRED_MASK 0x20000000L
+#define DMCU_INTERRUPT_STATUS__VBLANK6_INT_OCCURRED__SHIFT 0x0000001d
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_BL_UPDATE_INT_MASK_MASK 0x00000004L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_BL_UPDATE_INT_MASK__SHIFT 0x00000002
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_HG_READY_INT_MASK_MASK 0x00000001L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_HG_READY_INT_MASK__SHIFT 0x00000000
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_LS_READY_INT_MASK_MASK 0x00000002L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__ABM1_LS_READY_INT_MASK__SHIFT 0x00000001
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_MASK_MASK 0x00040000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_MASK__SHIFT 0x00000012
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_MASK_MASK 0x00001000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_MASK__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_MASK_MASK 0x00080000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_MASK__SHIFT 0x00000013
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_MASK_MASK 0x00002000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_MASK__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_MASK_MASK 0x00100000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_MASK__SHIFT 0x00000014
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_MASK_MASK 0x00004000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_MASK__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_MASK_MASK 0x00200000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_MASK__SHIFT 0x00000015
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_MASK_MASK 0x00008000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_MASK__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_MASK_MASK 0x00400000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_MASK__SHIFT 0x00000016
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_MASK_MASK 0x00010000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_MASK__SHIFT 0x00000010
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_MASK_MASK 0x00800000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_MASK__SHIFT 0x00000017
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_MASK_MASK 0x00020000L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_MASK__SHIFT 0x00000011
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__SCP_INT_MASK_MASK 0x00000200L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__SCP_INT_MASK__SHIFT 0x00000009
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_INTERNAL_INT_MASK_MASK 0x00000400L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_INTERNAL_INT_MASK__SHIFT 0x0000000a
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_REG_RD_TIMEOUT_INT_MASK_MASK 0x00000800L
+#define DMCU_INTERRUPT_TO_HOST_EN_MASK__UC_REG_RD_TIMEOUT_INT_MASK__SHIFT 0x0000000b
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_BL_UPDATE_INT_TO_UC_EN_MASK 0x00000004L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_BL_UPDATE_INT_TO_UC_EN__SHIFT 0x00000002
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_HG_READY_INT_TO_UC_EN_MASK 0x00000001L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_HG_READY_INT_TO_UC_EN__SHIFT 0x00000000
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_LS_READY_INT_TO_UC_EN_MASK 0x00000002L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__ABM1_LS_READY_INT_TO_UC_EN__SHIFT 0x00000001
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_TO_UC_EN_MASK 0x00040000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000012
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_TO_UC_EN_MASK 0x00001000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE0_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_TO_UC_EN_MASK 0x00080000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000013
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_TO_UC_EN_MASK 0x00002000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE1_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_TO_UC_EN_MASK 0x00100000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000014
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_TO_UC_EN_MASK 0x00004000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE2_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_TO_UC_EN_MASK 0x00200000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000015
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_TO_UC_EN_MASK 0x00008000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE3_POWER_UP_INT_TO_UC_EN__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_TO_UC_EN_MASK 0x00400000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000016
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_TO_UC_EN_MASK 0x00010000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE4_POWER_UP_INT_TO_UC_EN__SHIFT 0x00000010
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_TO_UC_EN_MASK 0x00800000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_DOWN_INT_TO_UC_EN__SHIFT 0x00000017
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_TO_UC_EN_MASK 0x00020000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__DCPG_IHC_DCFE5_POWER_UP_INT_TO_UC_EN__SHIFT 0x00000011
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__EXTERNAL_SW_INT_TO_UC_EN_MASK 0x00000100L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__EXTERNAL_SW_INT_TO_UC_EN__SHIFT 0x00000008
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__MCP_INT_TO_UC_EN_MASK 0x00000008L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__MCP_INT_TO_UC_EN__SHIFT 0x00000003
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK1_INT_TO_UC_EN_MASK 0x01000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK1_INT_TO_UC_EN__SHIFT 0x00000018
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK2_INT_TO_UC_EN_MASK 0x02000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK2_INT_TO_UC_EN__SHIFT 0x00000019
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK3_INT_TO_UC_EN_MASK 0x04000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK3_INT_TO_UC_EN__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK4_INT_TO_UC_EN_MASK 0x08000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK4_INT_TO_UC_EN__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK5_INT_TO_UC_EN_MASK 0x10000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK5_INT_TO_UC_EN__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK6_INT_TO_UC_EN_MASK 0x20000000L
+#define DMCU_INTERRUPT_TO_UC_EN_MASK__VBLANK6_INT_TO_UC_EN__SHIFT 0x0000001d
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_BL_UPDATE_INT_XIRQ_IRQ_SEL_MASK 0x00000004L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_BL_UPDATE_INT_XIRQ_IRQ_SEL__SHIFT 0x00000002
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_HG_READY_INT_XIRQ_IRQ_SEL_MASK 0x00000001L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_HG_READY_INT_XIRQ_IRQ_SEL__SHIFT 0x00000000
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_LS_READY_INT_XIRQ_IRQ_SEL_MASK 0x00000002L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__ABM1_LS_READY_INT_XIRQ_IRQ_SEL__SHIFT 0x00000001
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00040000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000012
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00001000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE0_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000c
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00080000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000013
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00002000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE1_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000d
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00100000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000014
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00004000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE2_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000e
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00200000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000015
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00008000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE3_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x0000000f
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00400000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000016
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00010000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE4_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x00000010
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_DOWN_INT_XIRQ_IRQ_SEL_MASK 0x00800000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_DOWN_INT_XIRQ_IRQ_SEL__SHIFT 0x00000017
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_UP_INT_XIRQ_IRQ_SEL_MASK 0x00020000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__DCPG_IHC_DCFE5_POWER_UP_INT_XIRQ_IRQ_SEL__SHIFT 0x00000011
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__EXTERNAL_SW_INT_XIRQ_IRQ_SEL_MASK 0x00000100L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__EXTERNAL_SW_INT_XIRQ_IRQ_SEL__SHIFT 0x00000008
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__MCP_INT_XIRQ_IRQ_SEL_MASK 0x00000008L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__MCP_INT_XIRQ_IRQ_SEL__SHIFT 0x00000003
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK1_INT_XIRQ_IRQ_SEL_MASK 0x01000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK1_INT_XIRQ_IRQ_SEL__SHIFT 0x00000018
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK2_INT_XIRQ_IRQ_SEL_MASK 0x02000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK2_INT_XIRQ_IRQ_SEL__SHIFT 0x00000019
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK3_INT_XIRQ_IRQ_SEL_MASK 0x04000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK3_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001a
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK4_INT_XIRQ_IRQ_SEL_MASK 0x08000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK4_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001b
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK5_INT_XIRQ_IRQ_SEL_MASK 0x10000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK5_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001c
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK6_INT_XIRQ_IRQ_SEL_MASK 0x20000000L
+#define DMCU_INTERRUPT_TO_UC_XIRQ_IRQ_SEL__VBLANK6_INT_XIRQ_IRQ_SEL__SHIFT 0x0000001d
+#define DMCU_IRAM_RD_CTRL__IRAM_RD_ADDR_MASK 0x000003ffL
+#define DMCU_IRAM_RD_CTRL__IRAM_RD_ADDR__SHIFT 0x00000000
+#define DMCU_IRAM_RD_DATA__IRAM_RD_DATA_MASK 0x000000ffL
+#define DMCU_IRAM_RD_DATA__IRAM_RD_DATA__SHIFT 0x00000000
+#define DMCU_IRAM_WR_CTRL__IRAM_WR_ADDR_MASK 0x000003ffL
+#define DMCU_IRAM_WR_CTRL__IRAM_WR_ADDR__SHIFT 0x00000000
+#define DMCU_IRAM_WR_DATA__IRAM_WR_DATA_MASK 0x000000ffL
+#define DMCU_IRAM_WR_DATA__IRAM_WR_DATA__SHIFT 0x00000000
+#define DMCU_PC_START_ADDR__PC_START_ADDR_LSB_MASK 0x000000ffL
+#define DMCU_PC_START_ADDR__PC_START_ADDR_LSB__SHIFT 0x00000000
+#define DMCU_PC_START_ADDR__PC_START_ADDR_MSB_MASK 0x0000ff00L
+#define DMCU_PC_START_ADDR__PC_START_ADDR_MSB__SHIFT 0x00000008
+#define DMCU_RAM_ACCESS_CTRL__ERAM_HOST_ACCESS_EN_MASK 0x00000010L
+#define DMCU_RAM_ACCESS_CTRL__ERAM_HOST_ACCESS_EN__SHIFT 0x00000004
+#define DMCU_RAM_ACCESS_CTRL__ERAM_RD_ADDR_AUTO_INC_MASK 0x00000002L
+#define DMCU_RAM_ACCESS_CTRL__ERAM_RD_ADDR_AUTO_INC__SHIFT 0x00000001
+#define DMCU_RAM_ACCESS_CTRL__ERAM_WR_ADDR_AUTO_INC_MASK 0x00000001L
+#define DMCU_RAM_ACCESS_CTRL__ERAM_WR_ADDR_AUTO_INC__SHIFT 0x00000000
+#define DMCU_RAM_ACCESS_CTRL__IRAM_HOST_ACCESS_EN_MASK 0x00000020L
+#define DMCU_RAM_ACCESS_CTRL__IRAM_HOST_ACCESS_EN__SHIFT 0x00000005
+#define DMCU_RAM_ACCESS_CTRL__IRAM_RD_ADDR_AUTO_INC_MASK 0x00000008L
+#define DMCU_RAM_ACCESS_CTRL__IRAM_RD_ADDR_AUTO_INC__SHIFT 0x00000003
+#define DMCU_RAM_ACCESS_CTRL__IRAM_WR_ADDR_AUTO_INC_MASK 0x00000004L
+#define DMCU_RAM_ACCESS_CTRL__IRAM_WR_ADDR_AUTO_INC__SHIFT 0x00000002
+#define DMCU_RAM_ACCESS_CTRL__UC_RST_RELEASE_DELAY_CNT_MASK 0x0000ff00L
+#define DMCU_RAM_ACCESS_CTRL__UC_RST_RELEASE_DELAY_CNT__SHIFT 0x00000008
+#define DMCU_STATUS__UC_IN_RESET_MASK 0x00000001L
+#define DMCU_STATUS__UC_IN_RESET__SHIFT 0x00000000
+#define DMCU_STATUS__UC_IN_STOP_MODE_MASK 0x00000004L
+#define DMCU_STATUS__UC_IN_STOP_MODE__SHIFT 0x00000002
+#define DMCU_STATUS__UC_IN_WAIT_MODE_MASK 0x00000002L
+#define DMCU_STATUS__UC_IN_WAIT_MODE__SHIFT 0x00000001
+#define DMCU_TEST_DEBUG_DATA__DMCU_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DMCU_TEST_DEBUG_DATA__DMCU_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DMCU_TEST_DEBUG_INDEX__DMCU_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DMCU_UC_CLK_GATING_CNTL__UC_ERAM_RD_DELAY_MASK 0x00000700L
+#define DMCU_UC_CLK_GATING_CNTL__UC_ERAM_RD_DELAY__SHIFT 0x00000008
+#define DMCU_UC_CLK_GATING_CNTL__UC_IRAM_RD_DELAY_MASK 0x00000007L
+#define DMCU_UC_CLK_GATING_CNTL__UC_IRAM_RD_DELAY__SHIFT 0x00000000
+#define DMCU_UC_CLK_GATING_CNTL__UC_RBBM_RD_CLK_GATING_EN_MASK 0x00010000L
+#define DMCU_UC_CLK_GATING_CNTL__UC_RBBM_RD_CLK_GATING_EN__SHIFT 0x00000010
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_ILLEGAL_OPCODE_TRAP_MASK 0x00000008L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_ILLEGAL_OPCODE_TRAP__SHIFT 0x00000003
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_IRQ_N_PIN_MASK 0x00000001L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_IRQ_N_PIN__SHIFT 0x00000000
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_INPUT_EDGE_MASK 0x00004000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_INPUT_EDGE__SHIFT 0x0000000e
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_OVERFLOW_MASK 0x00008000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_PULSE_ACCUMULATOR_OVERFLOW__SHIFT 0x0000000f
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_REAL_TIME_INTERRUPT_MASK 0x00000200L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_REAL_TIME_INTERRUPT__SHIFT 0x00000009
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_SOFTWARE_INTERRUPT_MASK 0x00000004L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_SOFTWARE_INTERRUPT__SHIFT 0x00000002
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_1_MASK 0x00002000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_1__SHIFT 0x0000000d
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_2_MASK 0x00001000L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_2__SHIFT 0x0000000c
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_3_MASK 0x00000800L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_3__SHIFT 0x0000000b
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_4_OUTPUT_COMPARE_5_MASK 0x00000400L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_INPUT_CAPTURE_4_OUTPUT_COMPARE_5__SHIFT 0x0000000a
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_1_MASK 0x00000080L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_1__SHIFT 0x00000007
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_2_MASK 0x00000040L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_2__SHIFT 0x00000006
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_3_MASK 0x00000020L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_3__SHIFT 0x00000005
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_4_MASK 0x00000010L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OUTPUT_COMPARE_4__SHIFT 0x00000004
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OVERFLOW_MASK 0x00000100L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_TIMER_OVERFLOW__SHIFT 0x00000008
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_XIRQ_N_PIN_MASK 0x00000002L
+#define DMCU_UC_INTERNAL_INT_STATUS__UC_INT_XIRQ_N_PIN__SHIFT 0x00000001
+#define DMIF_ADDR_CALC__ADDR_CONFIG_PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define DMIF_ADDR_CALC__ADDR_CONFIG_PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define DMIF_ADDR_CALC__ADDR_CONFIG_ROW_SIZE_MASK 0x30000000L
+#define DMIF_ADDR_CALC__ADDR_CONFIG_ROW_SIZE__SHIFT 0x0000001c
+#define DMIF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define DMIF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define DMIF_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define DMIF_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define DMIF_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define DMIF_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define DMIF_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define DMIF_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define DMIF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define DMIF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define DMIF_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define DMIF_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define DMIF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define DMIF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define DMIF_ARBITRATION_CONTROL__DMIF_ARBITRATION_REFERENCE_CLOCK_PERIOD_MASK 0x0000ffffL
+#define DMIF_ARBITRATION_CONTROL__DMIF_ARBITRATION_REFERENCE_CLOCK_PERIOD__SHIFT 0x00000000
+#define DMIF_ARBITRATION_CONTROL__PIPE_SWITCH_EFFICIENCY_WEIGHT_MASK 0xffff0000L
+#define DMIF_ARBITRATION_CONTROL__PIPE_SWITCH_EFFICIENCY_WEIGHT__SHIFT 0x00000010
+#define DMIF_CONTROL__DMIF_BUFF_SIZE_MASK 0x00000003L
+#define DMIF_CONTROL__DMIF_BUFF_SIZE__SHIFT 0x00000000
+#define DMIF_CONTROL__DMIF_CHUNK_BUFF_MARGIN_MASK 0x60000000L
+#define DMIF_CONTROL__DMIF_CHUNK_BUFF_MARGIN__SHIFT 0x0000001d
+#define DMIF_CONTROL__DMIF_DELAY_ARBITRATION_MASK 0x1f000000L
+#define DMIF_CONTROL__DMIF_DELAY_ARBITRATION__SHIFT 0x00000018
+#define DMIF_CONTROL__DMIF_DISABLE_EARLY_RECEIVED_LEVEL_COUNT_MASK 0x00000010L
+#define DMIF_CONTROL__DMIF_DISABLE_EARLY_RECEIVED_LEVEL_COUNT__SHIFT 0x00000004
+#define DMIF_CONTROL__DMIF_FORCE_TOTAL_REQ_BURST_SIZE_MASK 0x0000f000L
+#define DMIF_CONTROL__DMIF_FORCE_TOTAL_REQ_BURST_SIZE__SHIFT 0x0000000c
+#define DMIF_CONTROL__DMIF_GROUP_REQUESTS_IN_CHUNK_MASK 0x00000004L
+#define DMIF_CONTROL__DMIF_GROUP_REQUESTS_IN_CHUNK__SHIFT 0x00000002
+#define DMIF_CONTROL__DMIF_MAX_TOTAL_OUTSTANDING_CHUNK_REQUESTS_MASK 0x003f0000L
+#define DMIF_CONTROL__DMIF_MAX_TOTAL_OUTSTANDING_CHUNK_REQUESTS__SHIFT 0x00000010
+#define DMIF_CONTROL__DMIF_REQ_BURST_SIZE_MASK 0x00000700L
+#define DMIF_CONTROL__DMIF_REQ_BURST_SIZE__SHIFT 0x00000008
+#define DMIF_DEBUG02_CORE0__DB_DATA_MASK 0x0000ffffL
+#define DMIF_DEBUG02_CORE0__DB_DATA__SHIFT 0x00000000
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNT_EN_MASK 0x00010000L
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNT_EN__SHIFT 0x00000010
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNTER_MASK 0x0ffe0000L
+#define DMIF_DEBUG02_CORE0__MC_RDRET_COUNTER__SHIFT 0x00000011
+#define DMIF_DEBUG02_CORE1__DB_DATA_MASK 0x0000ffffL
+#define DMIF_DEBUG02_CORE1__DB_DATA__SHIFT 0x00000000
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNT_EN_MASK 0x00010000L
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNT_EN__SHIFT 0x00000010
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNTER_MASK 0x0ffe0000L
+#define DMIF_DEBUG02_CORE1__MC_RDRET_COUNTER__SHIFT 0x00000011
+#define DMIF_HW_DEBUG__DMIF_HW_DEBUG_MASK 0xffffffffL
+#define DMIF_HW_DEBUG__DMIF_HW_DEBUG__SHIFT 0x00000000
+#define DMIF_STATUS2__DMIF_CHUNK_TRACKER_SCLK_STATUS_MASK 0x00000100L
+#define DMIF_STATUS2__DMIF_CHUNK_TRACKER_SCLK_STATUS__SHIFT 0x00000008
+#define DMIF_STATUS2__DMIF_FBC_TRACKER_SCLK_STATUS_MASK 0x00000200L
+#define DMIF_STATUS2__DMIF_FBC_TRACKER_SCLK_STATUS__SHIFT 0x00000009
+#define DMIF_STATUS2__DMIF_PIPE0_DISPCLK_STATUS_MASK 0x00000001L
+#define DMIF_STATUS2__DMIF_PIPE0_DISPCLK_STATUS__SHIFT 0x00000000
+#define DMIF_STATUS2__DMIF_PIPE1_DISPCLK_STATUS_MASK 0x00000002L
+#define DMIF_STATUS2__DMIF_PIPE1_DISPCLK_STATUS__SHIFT 0x00000001
+#define DMIF_STATUS2__DMIF_PIPE2_DISPCLK_STATUS_MASK 0x00000004L
+#define DMIF_STATUS2__DMIF_PIPE2_DISPCLK_STATUS__SHIFT 0x00000002
+#define DMIF_STATUS2__DMIF_PIPE3_DISPCLK_STATUS_MASK 0x00000008L
+#define DMIF_STATUS2__DMIF_PIPE3_DISPCLK_STATUS__SHIFT 0x00000003
+#define DMIF_STATUS2__DMIF_PIPE4_DISPCLK_STATUS_MASK 0x00000010L
+#define DMIF_STATUS2__DMIF_PIPE4_DISPCLK_STATUS__SHIFT 0x00000004
+#define DMIF_STATUS2__DMIF_PIPE5_DISPCLK_STATUS_MASK 0x00000020L
+#define DMIF_STATUS2__DMIF_PIPE5_DISPCLK_STATUS__SHIFT 0x00000005
+#define DMIF_STATUS__DMIF_CLEAR_MC_SEND_ON_IDLE_MASK 0x00003f00L
+#define DMIF_STATUS__DMIF_CLEAR_MC_SEND_ON_IDLE__SHIFT 0x00000008
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_ENABLE_MASK 0x00010000L
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_ENABLE__SHIFT 0x00000010
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_SOURCE_SELECT_MASK 0x00700000L
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_SOURCE_SELECT__SHIFT 0x00000014
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_URGENT_ONLY_MASK 0x00020000L
+#define DMIF_STATUS__DMIF_MC_LATENCY_COUNTER_URGENT_ONLY__SHIFT 0x00000011
+#define DMIF_STATUS__DMIF_MC_SEND_ON_IDLE_MASK 0x0000003fL
+#define DMIF_STATUS__DMIF_MC_SEND_ON_IDLE__SHIFT 0x00000000
+#define DMIF_STATUS__DMIF_PERFORMANCE_COUNTER_SOURCE_SELECT_MASK 0x07000000L
+#define DMIF_STATUS__DMIF_PERFORMANCE_COUNTER_SOURCE_SELECT__SHIFT 0x00000018
+#define DMIF_STATUS__DMIF_UNDERFLOW_MASK 0x10000000L
+#define DMIF_STATUS__DMIF_UNDERFLOW__SHIFT 0x0000001c
+#define DMIF_TEST_DEBUG_DATA__DMIF_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DMIF_TEST_DEBUG_DATA__DMIF_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DMIF_TEST_DEBUG_INDEX__DMIF_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_AUDIO_STREAM_SELECT_MASK 0x00000070L
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_AUDIO_STREAM_SELECT__SHIFT 0x00000004
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_VIDEO_PIPE_SELECT_MASK 0x00000007L
+#define DOUT_DCE_VCE_CONTROL__DC_VCE_VIDEO_PIPE_SELECT__SHIFT 0x00000000
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ALL_BUSY_OFF_MASK 0x00000100L
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ALL_BUSY_OFF__SHIFT 0x00000008
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ASSERT_RESET_MASK 0x00000001L
+#define DOUT_POWER_MANAGEMENT_CNTL__PM_ASSERT_RESET__SHIFT 0x00000000
+#define DOUT_SCRATCH0__DOUT_SCRATCH0_MASK 0xffffffffL
+#define DOUT_SCRATCH0__DOUT_SCRATCH0__SHIFT 0x00000000
+#define DOUT_SCRATCH1__DOUT_SCRATCH1_MASK 0xffffffffL
+#define DOUT_SCRATCH1__DOUT_SCRATCH1__SHIFT 0x00000000
+#define DOUT_SCRATCH2__DOUT_SCRATCH2_MASK 0xffffffffL
+#define DOUT_SCRATCH2__DOUT_SCRATCH2__SHIFT 0x00000000
+#define DOUT_SCRATCH3__DOUT_SCRATCH3_MASK 0xffffffffL
+#define DOUT_SCRATCH3__DOUT_SCRATCH3__SHIFT 0x00000000
+#define DOUT_SCRATCH4__DOUT_SCRATCH4_MASK 0xffffffffL
+#define DOUT_SCRATCH4__DOUT_SCRATCH4__SHIFT 0x00000000
+#define DOUT_SCRATCH5__DOUT_SCRATCH5_MASK 0xffffffffL
+#define DOUT_SCRATCH5__DOUT_SCRATCH5__SHIFT 0x00000000
+#define DOUT_SCRATCH6__DOUT_SCRATCH6_MASK 0xffffffffL
+#define DOUT_SCRATCH6__DOUT_SCRATCH6__SHIFT 0x00000000
+#define DOUT_SCRATCH7__DOUT_SCRATCH7_MASK 0xffffffffL
+#define DOUT_SCRATCH7__DOUT_SCRATCH7__SHIFT 0x00000000
+#define DOUT_TEST_DEBUG_DATA__DOUT_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DOUT_TEST_DEBUG_DATA__DOUT_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DOUT_TEST_DEBUG_INDEX__DOUT_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DP_AUX1_DEBUG_A__DP_AUX1_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_A__DP_AUX1_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_B__DP_AUX1_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_B__DP_AUX1_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_C__DP_AUX1_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_C__DP_AUX1_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_D__DP_AUX1_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_D__DP_AUX1_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_E__DP_AUX1_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_E__DP_AUX1_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_F__DP_AUX1_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_F__DP_AUX1_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_G__DP_AUX1_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_G__DP_AUX1_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_H__DP_AUX1_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_H__DP_AUX1_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX1_DEBUG_I__DP_AUX1_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX1_DEBUG_I__DP_AUX1_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_A__DP_AUX2_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_A__DP_AUX2_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_B__DP_AUX2_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_B__DP_AUX2_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_C__DP_AUX2_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_C__DP_AUX2_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_D__DP_AUX2_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_D__DP_AUX2_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_E__DP_AUX2_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_E__DP_AUX2_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_F__DP_AUX2_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_F__DP_AUX2_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_G__DP_AUX2_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_G__DP_AUX2_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_H__DP_AUX2_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_H__DP_AUX2_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX2_DEBUG_I__DP_AUX2_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX2_DEBUG_I__DP_AUX2_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_A__DP_AUX3_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_A__DP_AUX3_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_B__DP_AUX3_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_B__DP_AUX3_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_C__DP_AUX3_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_C__DP_AUX3_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_D__DP_AUX3_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_D__DP_AUX3_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_E__DP_AUX3_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_E__DP_AUX3_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_F__DP_AUX3_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_F__DP_AUX3_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_G__DP_AUX3_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_G__DP_AUX3_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_H__DP_AUX3_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_H__DP_AUX3_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX3_DEBUG_I__DP_AUX3_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX3_DEBUG_I__DP_AUX3_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_A__DP_AUX4_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_A__DP_AUX4_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_B__DP_AUX4_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_B__DP_AUX4_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_C__DP_AUX4_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_C__DP_AUX4_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_D__DP_AUX4_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_D__DP_AUX4_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_E__DP_AUX4_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_E__DP_AUX4_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_F__DP_AUX4_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_F__DP_AUX4_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_G__DP_AUX4_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_G__DP_AUX4_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_H__DP_AUX4_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_H__DP_AUX4_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX4_DEBUG_I__DP_AUX4_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX4_DEBUG_I__DP_AUX4_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_A__DP_AUX5_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_A__DP_AUX5_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_B__DP_AUX5_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_B__DP_AUX5_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_C__DP_AUX5_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_C__DP_AUX5_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_D__DP_AUX5_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_D__DP_AUX5_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_E__DP_AUX5_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_E__DP_AUX5_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_F__DP_AUX5_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_F__DP_AUX5_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_G__DP_AUX5_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_G__DP_AUX5_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_H__DP_AUX5_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_H__DP_AUX5_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX5_DEBUG_I__DP_AUX5_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX5_DEBUG_I__DP_AUX5_DEBUG_I__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_A__DP_AUX6_DEBUG_A_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_A__DP_AUX6_DEBUG_A__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_B__DP_AUX6_DEBUG_B_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_B__DP_AUX6_DEBUG_B__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_C__DP_AUX6_DEBUG_C_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_C__DP_AUX6_DEBUG_C__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_D__DP_AUX6_DEBUG_D_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_D__DP_AUX6_DEBUG_D__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_E__DP_AUX6_DEBUG_E_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_E__DP_AUX6_DEBUG_E__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_F__DP_AUX6_DEBUG_F_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_F__DP_AUX6_DEBUG_F__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_G__DP_AUX6_DEBUG_G_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_G__DP_AUX6_DEBUG_G__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_H__DP_AUX6_DEBUG_H_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_H__DP_AUX6_DEBUG_H__SHIFT 0x00000000
+#define DP_AUX6_DEBUG_I__DP_AUX6_DEBUG_I_MASK 0xffffffffL
+#define DP_AUX6_DEBUG_I__DP_AUX6_DEBUG_I__SHIFT 0x00000000
+#define DP_CONFIG__DP_UDI_LANES_MASK 0x00000003L
+#define DP_CONFIG__DP_UDI_LANES__SHIFT 0x00000000
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_CUR_DISP_MASK 0x01000000L
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_CUR_DISP__SHIFT 0x00000018
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_EXT_DISP_MASK 0x00010000L
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_EXT_DISP__SHIFT 0x00000010
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_RESET_MASK 0x00000100L
+#define DP_DPHY_8B10B_CNTL__DPHY_8B10B_RESET__SHIFT 0x00000008
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE0_MASK 0x00000001L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE0__SHIFT 0x00000000
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE1_MASK 0x00000002L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE1__SHIFT 0x00000001
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE2_MASK 0x00000004L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE2__SHIFT 0x00000002
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE3_MASK 0x00000008L
+#define DP_DPHY_CNTL__DPHY_ATEST_SEL_LANE3__SHIFT 0x00000003
+#define DP_DPHY_CNTL__DPHY_BYPASS_MASK 0x00010000L
+#define DP_DPHY_CNTL__DPHY_BYPASS__SHIFT 0x00000010
+#define DP_DPHY_CNTL__DPHY_SKEW_BYPASS_MASK 0x01000000L
+#define DP_DPHY_CNTL__DPHY_SKEW_BYPASS__SHIFT 0x00000018
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_FIELD_MASK 0x00000001L
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_FIELD__SHIFT 0x00000000
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_MASK_MASK 0x00ff0000L
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_MASK__SHIFT 0x00000010
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_SEL_MASK 0x00000030L
+#define DP_DPHY_CRC_CNTL__DPHY_CRC_SEL__SHIFT 0x00000004
+#define DP_DPHY_CRC_EN__DPHY_CRC_CONT_EN_MASK 0x00000010L
+#define DP_DPHY_CRC_EN__DPHY_CRC_CONT_EN__SHIFT 0x00000004
+#define DP_DPHY_CRC_EN__DPHY_CRC_EN_MASK 0x00000001L
+#define DP_DPHY_CRC_EN__DPHY_CRC_EN__SHIFT 0x00000000
+#define DP_DPHY_CRC_EN__DPHY_CRC_RESULT_VALID_MASK 0x00000100L
+#define DP_DPHY_CRC_EN__DPHY_CRC_RESULT_VALID__SHIFT 0x00000008
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_FIRST_SLOT_MASK 0x0000003fL
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_FIRST_SLOT__SHIFT 0x00000000
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_LAST_SLOT_MASK 0x00003f00L
+#define DP_DPHY_CRC_MST_CNTL__DPHY_CRC_MST_LAST_SLOT__SHIFT 0x00000008
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_ACK_MASK 0x00010000L
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_ACK__SHIFT 0x00000010
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR_MASK 0x00000100L
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_ERROR__SHIFT 0x00000008
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_LOCK_MASK 0x00000001L
+#define DP_DPHY_CRC_MST_STATUS__DPHY_CRC_MST_PHASE_LOCK__SHIFT 0x00000000
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT1_MASK 0x0000ff00L
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT1__SHIFT 0x00000008
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT2_MASK 0x00ff0000L
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT2__SHIFT 0x00000010
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT3_MASK 0xff000000L
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT3__SHIFT 0x00000018
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT_MASK 0x000000ffL
+#define DP_DPHY_CRC_RESULT__DPHY_CRC_RESULT__SHIFT 0x00000000
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP1_TIME_MASK 0x000fff00L
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP1_TIME__SHIFT 0x00000008
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP2_TIME_MASK 0xfff00000L
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_TP2_TIME__SHIFT 0x00000014
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN_MASK 0x00000004L
+#define DP_DPHY_FAST_TRAINING__DPHY_FAST_TRAINING_VBLANK_EDGE_DETECT_EN__SHIFT 0x00000002
+#define DP_DPHY_FAST_TRAINING__DPHY_RX_FAST_TRAINING_CAPABLE_MASK 0x00000001L
+#define DP_DPHY_FAST_TRAINING__DPHY_RX_FAST_TRAINING_CAPABLE__SHIFT 0x00000000
+#define DP_DPHY_FAST_TRAINING__DPHY_SW_FAST_TRAINING_START_MASK 0x00000002L
+#define DP_DPHY_FAST_TRAINING__DPHY_SW_FAST_TRAINING_START__SHIFT 0x00000001
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_ACK_MASK 0x00001000L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_ACK__SHIFT 0x0000000c
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_MASK_MASK 0x00000100L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_MASK__SHIFT 0x00000008
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_OCCURRED_MASK 0x00000010L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_COMPLETE_OCCURRED__SHIFT 0x00000004
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_STATE_MASK 0x00000007L
+#define DP_DPHY_FAST_TRAINING_STATUS__DPHY_FAST_TRAINING_STATE__SHIFT 0x00000000
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_EN_MASK 0x00000001L
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_EN__SHIFT 0x00000000
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEED_MASK 0x7fffff00L
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEED__SHIFT 0x00000008
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEL_MASK 0x00000030L
+#define DP_DPHY_PRBS_CNTL__DPHY_PRBS_SEL__SHIFT 0x00000004
+#define DP_DPHY_SYM0__DPHY_SYM1_MASK 0x000003ffL
+#define DP_DPHY_SYM0__DPHY_SYM1__SHIFT 0x00000000
+#define DP_DPHY_SYM0__DPHY_SYM2_MASK 0x000ffc00L
+#define DP_DPHY_SYM0__DPHY_SYM2__SHIFT 0x0000000a
+#define DP_DPHY_SYM0__DPHY_SYM3_MASK 0x3ff00000L
+#define DP_DPHY_SYM0__DPHY_SYM3__SHIFT 0x00000014
+#define DP_DPHY_SYM1__DPHY_SYM4_MASK 0x000003ffL
+#define DP_DPHY_SYM1__DPHY_SYM4__SHIFT 0x00000000
+#define DP_DPHY_SYM1__DPHY_SYM5_MASK 0x000ffc00L
+#define DP_DPHY_SYM1__DPHY_SYM5__SHIFT 0x0000000a
+#define DP_DPHY_SYM1__DPHY_SYM6_MASK 0x3ff00000L
+#define DP_DPHY_SYM1__DPHY_SYM6__SHIFT 0x00000014
+#define DP_DPHY_SYM2__DPHY_SYM7_MASK 0x000003ffL
+#define DP_DPHY_SYM2__DPHY_SYM7__SHIFT 0x00000000
+#define DP_DPHY_SYM2__DPHY_SYM8_MASK 0x000ffc00L
+#define DP_DPHY_SYM2__DPHY_SYM8__SHIFT 0x0000000a
+#define DP_DPHY_TRAINING_PATTERN_SEL__DPHY_TRAINING_PATTERN_SEL_MASK 0x00000003L
+#define DP_DPHY_TRAINING_PATTERN_SEL__DPHY_TRAINING_PATTERN_SEL__SHIFT 0x00000000
+#define DP_DTO0_MODULO__DP_DTO0_MODULO_MASK 0xffffffffL
+#define DP_DTO0_MODULO__DP_DTO0_MODULO__SHIFT 0x00000000
+#define DP_DTO0_PHASE__DP_DTO0_PHASE_MASK 0xffffffffL
+#define DP_DTO0_PHASE__DP_DTO0_PHASE__SHIFT 0x00000000
+#define DP_DTO1_MODULO__DP_DTO1_MODULO_MASK 0xffffffffL
+#define DP_DTO1_MODULO__DP_DTO1_MODULO__SHIFT 0x00000000
+#define DP_DTO1_PHASE__DP_DTO1_PHASE_MASK 0xffffffffL
+#define DP_DTO1_PHASE__DP_DTO1_PHASE__SHIFT 0x00000000
+#define DP_DTO2_MODULO__DP_DTO2_MODULO_MASK 0xffffffffL
+#define DP_DTO2_MODULO__DP_DTO2_MODULO__SHIFT 0x00000000
+#define DP_DTO2_PHASE__DP_DTO2_PHASE_MASK 0xffffffffL
+#define DP_DTO2_PHASE__DP_DTO2_PHASE__SHIFT 0x00000000
+#define DP_DTO3_MODULO__DP_DTO3_MODULO_MASK 0xffffffffL
+#define DP_DTO3_MODULO__DP_DTO3_MODULO__SHIFT 0x00000000
+#define DP_DTO3_PHASE__DP_DTO3_PHASE_MASK 0xffffffffL
+#define DP_DTO3_PHASE__DP_DTO3_PHASE__SHIFT 0x00000000
+#define DP_DTO4_MODULO__DP_DTO4_MODULO_MASK 0xffffffffL
+#define DP_DTO4_MODULO__DP_DTO4_MODULO__SHIFT 0x00000000
+#define DP_DTO4_PHASE__DP_DTO4_PHASE_MASK 0xffffffffL
+#define DP_DTO4_PHASE__DP_DTO4_PHASE__SHIFT 0x00000000
+#define DP_DTO5_MODULO__DP_DTO5_MODULO_MASK 0xffffffffL
+#define DP_DTO5_MODULO__DP_DTO5_MODULO__SHIFT 0x00000000
+#define DP_DTO5_PHASE__DP_DTO5_PHASE_MASK 0xffffffffL
+#define DP_DTO5_PHASE__DP_DTO5_PHASE__SHIFT 0x00000000
+#define DPG_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT_MASK 0xffff0000L
+#define DPG_PIPE_ARBITRATION_CONTROL1__BASE_WEIGHT__SHIFT 0x00000010
+#define DPG_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION_MASK 0x0000ffffL
+#define DPG_PIPE_ARBITRATION_CONTROL1__PIXEL_DURATION__SHIFT 0x00000000
+#define DPG_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT_MASK 0x0000ffffL
+#define DPG_PIPE_ARBITRATION_CONTROL2__TIME_WEIGHT__SHIFT 0x00000000
+#define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT_MASK 0xffff0000L
+#define DPG_PIPE_ARBITRATION_CONTROL2__URGENCY_WEIGHT__SHIFT 0x00000010
+#define DPG_PIPE_DPM_CONTROL__DPM_ENABLE_MASK 0x00000001L
+#define DPG_PIPE_DPM_CONTROL__DPM_ENABLE__SHIFT 0x00000000
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE_MASK 0x00000010L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_ENABLE__SHIFT 0x00000004
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON_MASK 0x00000100L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_FORCE_ON__SHIFT 0x00000008
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK_MASK 0x00003000L
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK_MASK__SHIFT 0x0000000c
+#define DPG_PIPE_DPM_CONTROL__MCLK_CHANGE_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT_MASK 0x00000400L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_ALLOW_FOR_URGENT__SHIFT 0x0000000a
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE_MASK 0x00000001L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_ENABLE__SHIFT 0x00000000
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON_MASK 0x00000200L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_FORCE_ON__SHIFT 0x00000009
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST_MASK 0x00000100L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST__SHIFT 0x00000008
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST_MASK 0x00000010L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_URGENT_DURING_REQUEST__SHIFT 0x00000004
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_NB_PSTATE_CHANGE_CONTROL__NB_PSTATE_CHANGE_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH_MASK 0x00000001L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_ENABLE_NONLPTCH__SHIFT 0x00000000
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH_MASK 0x00000010L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_CURSOR_NONLPTCH__SHIFT 0x00000004
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH_MASK 0x00000080L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_FBC_NONLPTCH__SHIFT 0x00000007
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH_MASK 0x00000020L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_ICON_NONLPTCH__SHIFT 0x00000005
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH_MASK 0x00000040L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_IGNORE_VGA_NONLPTCH__SHIFT 0x00000006
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH_MASK 0x00000800L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_SELF_REFRESH_FORCE_ON_NONLPTCH__SHIFT 0x0000000b
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH_MASK 0x00000400L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_URGENT_IN_NOT_SELF_REFRESH_NONLPTCH__SHIFT 0x0000000a
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH_MASK 0x00000200L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_EXCLUDES_VBLANK_NONLPTCH__SHIFT 0x00000009
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH_MASK 0x00000100L
+#define DPG_PIPE_STUTTER_CONTROL_NONLPTCH__STUTTER_WM_HIGH_FORCE_ON_NONLPTCH__SHIFT 0x00000008
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE_MASK 0x00000001L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_ENABLE__SHIFT 0x00000000
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_EXIT_SELF_REFRESH_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR_MASK 0x00000010L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_CURSOR__SHIFT 0x00000004
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC_MASK 0x00000080L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_FBC__SHIFT 0x00000007
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON_MASK 0x00000020L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_ICON__SHIFT 0x00000005
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA_MASK 0x00000040L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_IGNORE_VGA__SHIFT 0x00000006
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON_MASK 0x00000800L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_SELF_REFRESH_FORCE_ON__SHIFT 0x0000000b
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH_MASK 0x00000400L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_URGENT_IN_NOT_SELF_REFRESH__SHIFT 0x0000000a
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK_MASK 0x00000200L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_EXCLUDES_VBLANK__SHIFT 0x00000009
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON_MASK 0x00000100L
+#define DPG_PIPE_STUTTER_CONTROL__STUTTER_WM_HIGH_FORCE_ON__SHIFT 0x00000008
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK_MASK 0xffff0000L
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_HIGH_WATERMARK__SHIFT 0x00000010
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK_MASK 0x0000ffffL
+#define DPG_PIPE_URGENCY_CONTROL__URGENCY_LOW_WATERMARK__SHIFT 0x00000000
+#define DPG_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DPG_TEST_DEBUG_DATA__DPG_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DPG_TEST_DEBUG_INDEX__DPG_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DP_HBR2_EYE_PATTERN__DP_HBR2_EYE_PATTERN_ENABLE_MASK 0x00000001L
+#define DP_HBR2_EYE_PATTERN__DP_HBR2_EYE_PATTERN_ENABLE__SHIFT 0x00000000
+#define DP_LINK_CNTL__DP_EMBEDDED_PANEL_MODE_MASK 0x00020000L
+#define DP_LINK_CNTL__DP_EMBEDDED_PANEL_MODE__SHIFT 0x00000011
+#define DP_LINK_CNTL__DP_LINK_STATUS_MASK 0x00000100L
+#define DP_LINK_CNTL__DP_LINK_STATUS__SHIFT 0x00000008
+#define DP_LINK_CNTL__DP_LINK_TRAINING_COMPLETE_MASK 0x00000010L
+#define DP_LINK_CNTL__DP_LINK_TRAINING_COMPLETE__SHIFT 0x00000004
+#define DP_LINK_FRAMING_CNTL__DP_IDLE_BS_INTERVAL_MASK 0x0003ffffL
+#define DP_LINK_FRAMING_CNTL__DP_IDLE_BS_INTERVAL__SHIFT 0x00000000
+#define DP_LINK_FRAMING_CNTL__DP_VBID_DISABLE_MASK 0x01000000L
+#define DP_LINK_FRAMING_CNTL__DP_VBID_DISABLE__SHIFT 0x00000018
+#define DP_LINK_FRAMING_CNTL__DP_VID_ENHANCED_FRAME_MODE_MASK 0x10000000L
+#define DP_LINK_FRAMING_CNTL__DP_VID_ENHANCED_FRAME_MODE__SHIFT 0x0000001c
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_ENABLE_MASK 0x00000100L
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_ENABLE__SHIFT 0x00000008
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE_MASK 0x000000ffL
+#define DP_MSA_COLORIMETRY__DP_MSA_MISC0_OVERRIDE__SHIFT 0x00000000
+#define DP_MSA_MISC__DP_MSA_MISC1_MASK 0x000000f8L
+#define DP_MSA_MISC__DP_MSA_MISC1__SHIFT 0x00000003
+#define DP_MSA_MISC__DP_MSA_MISC2_MASK 0x0000ff00L
+#define DP_MSA_MISC__DP_MSA_MISC2__SHIFT 0x00000008
+#define DP_MSA_MISC__DP_MSA_MISC3_MASK 0x00ff0000L
+#define DP_MSA_MISC__DP_MSA_MISC3__SHIFT 0x00000010
+#define DP_MSA_MISC__DP_MSA_MISC4_MASK 0xff000000L
+#define DP_MSA_MISC__DP_MSA_MISC4__SHIFT 0x00000018
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TIMING_OVERRIDE_EN_MASK 0x00000001L
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TIMING_OVERRIDE_EN__SHIFT 0x00000000
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TOTAL_OVERRIDE_MASK 0x0001fff0L
+#define DP_MSA_V_TIMING_OVERRIDE1__DP_MSA_V_TOTAL_OVERRIDE__SHIFT 0x00000004
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_END_OVERRIDE_MASK 0x1fff0000L
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_END_OVERRIDE__SHIFT 0x00000010
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_START_OVERRIDE_MASK 0x00001fffL
+#define DP_MSA_V_TIMING_OVERRIDE2__DP_MSA_V_BLANK_START_OVERRIDE__SHIFT 0x00000000
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_FRAME_MASK 0x000003ffL
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_FRAME__SHIFT 0x00000000
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_LINE_MASK 0x00030000L
+#define DP_MSE_LINK_TIMING__DP_MSE_LINK_LINE__SHIFT 0x00000010
+#define DP_MSE_MISC_CNTL__DP_MSE_BLANK_CODE_MASK 0x00000001L
+#define DP_MSE_MISC_CNTL__DP_MSE_BLANK_CODE__SHIFT 0x00000000
+#define DP_MSE_MISC_CNTL__DP_MSE_TIMESTAMP_MODE_MASK 0x00000010L
+#define DP_MSE_MISC_CNTL__DP_MSE_TIMESTAMP_MODE__SHIFT 0x00000004
+#define DP_MSE_MISC_CNTL__DP_MSE_ZERO_ENCODER_MASK 0x00000100L
+#define DP_MSE_MISC_CNTL__DP_MSE_ZERO_ENCODER__SHIFT 0x00000008
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_X_MASK 0xfc000000L
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_X__SHIFT 0x0000001a
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_Y_MASK 0x03ffffffL
+#define DP_MSE_RATE_CNTL__DP_MSE_RATE_Y__SHIFT 0x00000000
+#define DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING_MASK 0x00000001L
+#define DP_MSE_RATE_UPDATE__DP_MSE_RATE_UPDATE_PENDING__SHIFT 0x00000000
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT0_MASK 0x00003f00L
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT0__SHIFT 0x00000008
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT1_MASK 0x3f000000L
+#define DP_MSE_SAT0__DP_MSE_SAT_SLOT_COUNT1__SHIFT 0x00000018
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC0_MASK 0x00000007L
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC0__SHIFT 0x00000000
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC1_MASK 0x00070000L
+#define DP_MSE_SAT0__DP_MSE_SAT_SRC1__SHIFT 0x00000010
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT2_MASK 0x00003f00L
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT2__SHIFT 0x00000008
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT3_MASK 0x3f000000L
+#define DP_MSE_SAT1__DP_MSE_SAT_SLOT_COUNT3__SHIFT 0x00000018
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC2_MASK 0x00000007L
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC2__SHIFT 0x00000000
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC3_MASK 0x00070000L
+#define DP_MSE_SAT1__DP_MSE_SAT_SRC3__SHIFT 0x00000010
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT4_MASK 0x00003f00L
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT4__SHIFT 0x00000008
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT5_MASK 0x3f000000L
+#define DP_MSE_SAT2__DP_MSE_SAT_SLOT_COUNT5__SHIFT 0x00000018
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC4_MASK 0x00000007L
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC4__SHIFT 0x00000000
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC5_MASK 0x00070000L
+#define DP_MSE_SAT2__DP_MSE_SAT_SRC5__SHIFT 0x00000010
+#define DP_MSE_SAT_UPDATE__DP_MSE_16_MTP_KEEPOUT_MASK 0x00000100L
+#define DP_MSE_SAT_UPDATE__DP_MSE_16_MTP_KEEPOUT__SHIFT 0x00000008
+#define DP_MSE_SAT_UPDATE__DP_MSE_SAT_UPDATE_MASK 0x00000003L
+#define DP_MSE_SAT_UPDATE__DP_MSE_SAT_UPDATE__SHIFT 0x00000000
+#define DP_PIXEL_FORMAT__DP_COMPONENT_DEPTH_MASK 0x07000000L
+#define DP_PIXEL_FORMAT__DP_COMPONENT_DEPTH__SHIFT 0x00000018
+#define DP_PIXEL_FORMAT__DP_DYN_RANGE_MASK 0x00000100L
+#define DP_PIXEL_FORMAT__DP_DYN_RANGE__SHIFT 0x00000008
+#define DP_PIXEL_FORMAT__DP_PIXEL_ENCODING_MASK 0x00000003L
+#define DP_PIXEL_FORMAT__DP_PIXEL_ENCODING__SHIFT 0x00000000
+#define DP_PIXEL_FORMAT__DP_YCBCR_RANGE_MASK 0x00010000L
+#define DP_PIXEL_FORMAT__DP_YCBCR_RANGE__SHIFT 0x00000010
+#define DP_SEC_AUD_M__DP_SEC_AUD_M_MASK 0x00ffffffL
+#define DP_SEC_AUD_M__DP_SEC_AUD_M__SHIFT 0x00000000
+#define DP_SEC_AUD_M_READBACK__DP_SEC_AUD_M_READBACK_MASK 0x00ffffffL
+#define DP_SEC_AUD_M_READBACK__DP_SEC_AUD_M_READBACK__SHIFT 0x00000000
+#define DP_SEC_AUD_N__DP_SEC_AUD_N_MASK 0x00ffffffL
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__SHIFT 0x00000000
+#define DP_SEC_AUD_N_READBACK__DP_SEC_AUD_N_READBACK_MASK 0x00ffffffL
+#define DP_SEC_AUD_N_READBACK__DP_SEC_AUD_N_READBACK__SHIFT 0x00000000
+#define DP_SEC_CNTL1__DP_SEC_ISRC_ENABLE_MASK 0x00000001L
+#define DP_SEC_CNTL1__DP_SEC_ISRC_ENABLE__SHIFT 0x00000000
+#define DP_SEC_CNTL__DP_SEC_ACM_ENABLE_MASK 0x00010000L
+#define DP_SEC_CNTL__DP_SEC_ACM_ENABLE__SHIFT 0x00000010
+#define DP_SEC_CNTL__DP_SEC_AIP_ENABLE_MASK 0x00001000L
+#define DP_SEC_CNTL__DP_SEC_AIP_ENABLE__SHIFT 0x0000000c
+#define DP_SEC_CNTL__DP_SEC_ASP_ENABLE_MASK 0x00000010L
+#define DP_SEC_CNTL__DP_SEC_ASP_ENABLE__SHIFT 0x00000004
+#define DP_SEC_CNTL__DP_SEC_ATP_ENABLE_MASK 0x00000100L
+#define DP_SEC_CNTL__DP_SEC_ATP_ENABLE__SHIFT 0x00000008
+#define DP_SEC_CNTL__DP_SEC_AVI_ENABLE_MASK 0x01000000L
+#define DP_SEC_CNTL__DP_SEC_AVI_ENABLE__SHIFT 0x00000018
+#define DP_SEC_CNTL__DP_SEC_GSP0_ENABLE_MASK 0x00100000L
+#define DP_SEC_CNTL__DP_SEC_GSP0_ENABLE__SHIFT 0x00000014
+#define DP_SEC_CNTL__DP_SEC_GSP1_ENABLE_MASK 0x00200000L
+#define DP_SEC_CNTL__DP_SEC_GSP1_ENABLE__SHIFT 0x00000015
+#define DP_SEC_CNTL__DP_SEC_GSP2_ENABLE_MASK 0x00400000L
+#define DP_SEC_CNTL__DP_SEC_GSP2_ENABLE__SHIFT 0x00000016
+#define DP_SEC_CNTL__DP_SEC_GSP3_ENABLE_MASK 0x00800000L
+#define DP_SEC_CNTL__DP_SEC_GSP3_ENABLE__SHIFT 0x00000017
+#define DP_SEC_CNTL__DP_SEC_MPG_ENABLE_MASK 0x10000000L
+#define DP_SEC_CNTL__DP_SEC_MPG_ENABLE__SHIFT 0x0000001c
+#define DP_SEC_CNTL__DP_SEC_STREAM_ENABLE_MASK 0x00000001L
+#define DP_SEC_CNTL__DP_SEC_STREAM_ENABLE__SHIFT 0x00000000
+#define DP_SEC_FRAMING1__DP_SEC_FRAME_START_LOCATION_MASK 0x00000fffL
+#define DP_SEC_FRAMING1__DP_SEC_FRAME_START_LOCATION__SHIFT 0x00000000
+#define DP_SEC_FRAMING1__DP_SEC_VBLANK_TRANSMIT_WIDTH_MASK 0xffff0000L
+#define DP_SEC_FRAMING1__DP_SEC_VBLANK_TRANSMIT_WIDTH__SHIFT 0x00000010
+#define DP_SEC_FRAMING2__DP_SEC_HBLANK_TRANSMIT_WIDTH_MASK 0xffff0000L
+#define DP_SEC_FRAMING2__DP_SEC_HBLANK_TRANSMIT_WIDTH__SHIFT 0x00000010
+#define DP_SEC_FRAMING2__DP_SEC_START_POSITION_MASK 0x0000ffffL
+#define DP_SEC_FRAMING2__DP_SEC_START_POSITION__SHIFT 0x00000000
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_FRAME_SIZE_MASK 0x00003fffL
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_FRAME_SIZE__SHIFT 0x00000000
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_TRANSMIT_WIDTH_MASK 0xffff0000L
+#define DP_SEC_FRAMING3__DP_SEC_IDLE_TRANSMIT_WIDTH__SHIFT 0x00000010
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_MASK 0x10000000L
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE__SHIFT 0x0000001c
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_STATUS_MASK 0x20000000L
+#define DP_SEC_FRAMING4__DP_SEC_AUDIO_MUTE_STATUS__SHIFT 0x0000001d
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_ACK_MASK 0x01000000L
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_ACK__SHIFT 0x00000018
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_STATUS_MASK 0x00100000L
+#define DP_SEC_FRAMING4__DP_SEC_COLLISION_STATUS__SHIFT 0x00000014
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE_MASK 0x00010000L
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CHANNEL_COUNT_OVERRIDE__SHIFT 0x00000010
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CODING_TYPE_MASK 0x0000000eL
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_CODING_TYPE__SHIFT 0x00000001
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_PRIORITY_MASK 0x00000010L
+#define DP_SEC_PACKET_CNTL__DP_SEC_ASP_PRIORITY__SHIFT 0x00000004
+#define DP_SEC_PACKET_CNTL__DP_SEC_VERSION_MASK 0x00003f00L
+#define DP_SEC_PACKET_CNTL__DP_SEC_VERSION__SHIFT 0x00000008
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE_MASK 0x00000001L
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__SHIFT 0x00000000
+#define DP_STEER_FIFO__DP_STEER_FIFO_RESET_MASK 0x00000001L
+#define DP_STEER_FIFO__DP_STEER_FIFO_RESET__SHIFT 0x00000000
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_ACK_MASK 0x00000040L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_ACK__SHIFT 0x00000006
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_FLAG_MASK 0x00000010L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_FLAG__SHIFT 0x00000004
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_INT_MASK 0x00000020L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_INT__SHIFT 0x00000005
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_MASK_MASK 0x00000080L
+#define DP_STEER_FIFO__DP_STEER_OVERFLOW_MASK__SHIFT 0x00000007
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_ACK_MASK 0x00001000L
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_ACK__SHIFT 0x0000000c
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_FLAG_MASK 0x00000100L
+#define DP_STEER_FIFO__DP_TU_OVERFLOW_FLAG__SHIFT 0x00000008
+#define DP_TEST_DEBUG_DATA__DP_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DP_TEST_DEBUG_DATA__DP_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DP_TEST_DEBUG_INDEX__DP_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_ACK_MASK 0x00000002L
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_ACK__SHIFT 0x00000001
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_INT_MASK 0x00000001L
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_INT__SHIFT 0x00000000
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_MASK_MASK 0x00000004L
+#define DP_VID_INTERRUPT_CNTL__DP_VID_STREAM_DISABLE_MASK__SHIFT 0x00000002
+#define DP_VID_M__DP_VID_M_MASK 0x00ffffffL
+#define DP_VID_M__DP_VID_M__SHIFT 0x00000000
+#define DP_VID_MSA_VBID__DP_VID_MSA_LOCATION_MASK 0x00000fffL
+#define DP_VID_MSA_VBID__DP_VID_MSA_LOCATION__SHIFT 0x00000000
+#define DP_VID_MSA_VBID__DP_VID_MSA_TOP_FIELD_MODE_MASK 0x00010000L
+#define DP_VID_MSA_VBID__DP_VID_MSA_TOP_FIELD_MODE__SHIFT 0x00000010
+#define DP_VID_MSA_VBID__DP_VID_VBID_FIELD_POL_MASK 0x01000000L
+#define DP_VID_MSA_VBID__DP_VID_VBID_FIELD_POL__SHIFT 0x00000018
+#define DP_VID_N__DP_VID_N_MASK 0x00ffffffL
+#define DP_VID_N__DP_VID_N__SHIFT 0x00000000
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_CHANGE_KEEPOUT_MASK 0x00100000L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_CHANGE_KEEPOUT__SHIFT 0x00000014
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_DIS_DEFER_MASK 0x00000300L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_DIS_DEFER__SHIFT 0x00000008
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_ENABLE_MASK 0x00000001L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_ENABLE__SHIFT 0x00000000
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_STATUS_MASK 0x00010000L
+#define DP_VID_STREAM_CNTL__DP_VID_STREAM_STATUS__SHIFT 0x00000010
+#define DP_VID_TIMING__DP_VID_M_N_GEN_EN_MASK 0x00000100L
+#define DP_VID_TIMING__DP_VID_M_N_GEN_EN__SHIFT 0x00000008
+#define DP_VID_TIMING__DP_VID_N_DIV_MASK 0xff000000L
+#define DP_VID_TIMING__DP_VID_N_DIV__SHIFT 0x00000018
+#define DP_VID_TIMING__DP_VID_TIMING_MODE_MASK 0x00000001L
+#define DP_VID_TIMING__DP_VID_TIMING_MODE__SHIFT 0x00000000
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_ADJUST_EN_MASK 0x00020000L
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_ADJUST_EN__SHIFT 0x00000011
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_SKEW_CNTL_MASK 0x00001f00L
+#define DVOACLKC_CNTL__DVOACLKC_COARSE_SKEW_CNTL__SHIFT 0x00000008
+#define DVOACLKC_CNTL__DVOACLKC_FINE_ADJUST_EN_MASK 0x00010000L
+#define DVOACLKC_CNTL__DVOACLKC_FINE_ADJUST_EN__SHIFT 0x00000010
+#define DVOACLKC_CNTL__DVOACLKC_FINE_SKEW_CNTL_MASK 0x00000007L
+#define DVOACLKC_CNTL__DVOACLKC_FINE_SKEW_CNTL__SHIFT 0x00000000
+#define DVOACLKC_CNTL__DVOACLKC_IN_PHASE_MASK 0x00040000L
+#define DVOACLKC_CNTL__DVOACLKC_IN_PHASE__SHIFT 0x00000012
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_ADJUST_EN_MASK 0x00020000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_ADJUST_EN__SHIFT 0x00000011
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_SKEW_CNTL_MASK 0x00001f00L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_COARSE_SKEW_CNTL__SHIFT 0x00000008
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_ADJUST_EN_MASK 0x00010000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_ADJUST_EN__SHIFT 0x00000010
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_SKEW_CNTL_MASK 0x00000007L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_FINE_SKEW_CNTL__SHIFT 0x00000000
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_IN_PHASE_MASK 0x00040000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_IN_PHASE__SHIFT 0x00000012
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_SKEW_PHASE_OVERRIDE_MASK 0x00100000L
+#define DVOACLKC_MVP_CNTL__DVOACLKC_MVP_SKEW_PHASE_OVERRIDE__SHIFT 0x00000014
+#define DVOACLKC_MVP_CNTL__MVP_CLK_A_SRC_SEL_MASK 0x03000000L
+#define DVOACLKC_MVP_CNTL__MVP_CLK_A_SRC_SEL__SHIFT 0x00000018
+#define DVOACLKC_MVP_CNTL__MVP_CLK_B_SRC_SEL_MASK 0x30000000L
+#define DVOACLKC_MVP_CNTL__MVP_CLK_B_SRC_SEL__SHIFT 0x0000001c
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_ADJUST_EN_MASK 0x00020000L
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_ADJUST_EN__SHIFT 0x00000011
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_SKEW_CNTL_MASK 0x00001f00L
+#define DVOACLKD_CNTL__DVOACLKD_COARSE_SKEW_CNTL__SHIFT 0x00000008
+#define DVOACLKD_CNTL__DVOACLKD_FINE_ADJUST_EN_MASK 0x00010000L
+#define DVOACLKD_CNTL__DVOACLKD_FINE_ADJUST_EN__SHIFT 0x00000010
+#define DVOACLKD_CNTL__DVOACLKD_FINE_SKEW_CNTL_MASK 0x00000007L
+#define DVOACLKD_CNTL__DVOACLKD_FINE_SKEW_CNTL__SHIFT 0x00000000
+#define DVOACLKD_CNTL__DVOACLKD_IN_PHASE_MASK 0x00040000L
+#define DVOACLKD_CNTL__DVOACLKD_IN_PHASE__SHIFT 0x00000012
+#define DVO_CLK_ENABLE__DVO_CLK_ENABLE_MASK 0x00000001L
+#define DVO_CLK_ENABLE__DVO_CLK_ENABLE__SHIFT 0x00000000
+#define DVO_CONTROL__DVO_COLOR_FORMAT_MASK 0x03000000L
+#define DVO_CONTROL__DVO_COLOR_FORMAT__SHIFT 0x00000018
+#define DVO_CONTROL__DVO_CTL3_MASK 0x80000000L
+#define DVO_CONTROL__DVO_CTL3__SHIFT 0x0000001f
+#define DVO_CONTROL__DVO_DUAL_CHANNEL_EN_MASK 0x00000100L
+#define DVO_CONTROL__DVO_DUAL_CHANNEL_EN__SHIFT 0x00000008
+#define DVO_CONTROL__DVO_INVERT_DVOCLK_MASK 0x00040000L
+#define DVO_CONTROL__DVO_INVERT_DVOCLK__SHIFT 0x00000012
+#define DVO_CONTROL__DVO_RATE_SELECT_MASK 0x00000001L
+#define DVO_CONTROL__DVO_RATE_SELECT__SHIFT 0x00000000
+#define DVO_CONTROL__DVO_RESET_FIFO_MASK 0x00010000L
+#define DVO_CONTROL__DVO_RESET_FIFO__SHIFT 0x00000010
+#define DVO_CONTROL__DVO_SDRCLK_SEL_MASK 0x00000002L
+#define DVO_CONTROL__DVO_SDRCLK_SEL__SHIFT 0x00000001
+#define DVO_CONTROL__DVO_SYNC_PHASE_MASK 0x00020000L
+#define DVO_CONTROL__DVO_SYNC_PHASE__SHIFT 0x00000011
+#define DVO_CRC2_SIG_MASK__DVO_CRC2_SIG_MASK_MASK 0x07ffffffL
+#define DVO_CRC2_SIG_MASK__DVO_CRC2_SIG_MASK__SHIFT 0x00000000
+#define DVO_CRC2_SIG_RESULT__DVO_CRC2_SIG_RESULT_MASK 0x07ffffffL
+#define DVO_CRC2_SIG_RESULT__DVO_CRC2_SIG_RESULT__SHIFT 0x00000000
+#define DVO_CRC_EN__DVO_CRC2_EN_MASK 0x00010000L
+#define DVO_CRC_EN__DVO_CRC2_EN__SHIFT 0x00000010
+#define DVO_ENABLE__DVO_ENABLE_MASK 0x00000001L
+#define DVO_ENABLE__DVO_ENABLE__SHIFT 0x00000000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CAL_AVERAGE_LEVEL_MASK 0x0000fc00L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CAL_AVERAGE_LEVEL__SHIFT 0x0000000a
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CALIBRATED_MASK 0x20000000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_CALIBRATED__SHIFT 0x0000001d
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_ERROR_ACK_MASK 0x00000100L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_ERROR_ACK__SHIFT 0x00000008
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECAL_AVERAGE_MASK 0x40000000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECAL_AVERAGE__SHIFT 0x0000001e
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECOMP_MINMAX_MASK 0x80000000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_FORCE_RECOMP_MINMAX__SHIFT 0x0000001f
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_LEVEL_ERROR_MASK 0x00000001L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_LEVEL_ERROR__SHIFT 0x00000000
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MAXIMUM_LEVEL_MASK 0x000f0000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MAXIMUM_LEVEL__SHIFT 0x00000010
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MINIMUM_LEVEL_MASK 0x03c00000L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_MINIMUM_LEVEL__SHIFT 0x00000016
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_OVERWRITE_LEVEL_MASK 0x000000fcL
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_OVERWRITE_LEVEL__SHIFT 0x00000002
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_USE_OVERWRITE_LEVEL_MASK 0x00000002L
+#define DVO_FIFO_ERROR_STATUS__DVO_FIFO_USE_OVERWRITE_LEVEL__SHIFT 0x00000001
+#define DVO_OUTPUT__DVO_CLOCK_MODE_MASK 0x00000100L
+#define DVO_OUTPUT__DVO_CLOCK_MODE__SHIFT 0x00000008
+#define DVO_OUTPUT__DVO_OUTPUT_ENABLE_MODE_MASK 0x00000003L
+#define DVO_OUTPUT__DVO_OUTPUT_ENABLE_MODE__SHIFT 0x00000000
+#define DVO_SKEW_ADJUST__DVO_SKEW_ADJUST_MASK 0xffffffffL
+#define DVO_SKEW_ADJUST__DVO_SKEW_ADJUST__SHIFT 0x00000000
+#define DVO_SOURCE_SELECT__DVO_SOURCE_SELECT_MASK 0x00000007L
+#define DVO_SOURCE_SELECT__DVO_SOURCE_SELECT__SHIFT 0x00000000
+#define DVO_SOURCE_SELECT__DVO_STEREOSYNC_SELECT_MASK 0x00070000L
+#define DVO_SOURCE_SELECT__DVO_STEREOSYNC_SELECT__SHIFT 0x00000010
+#define DVO_STRENGTH_CONTROL__DVOCLK_SN_MASK 0x0000f000L
+#define DVO_STRENGTH_CONTROL__DVOCLK_SN__SHIFT 0x0000000c
+#define DVO_STRENGTH_CONTROL__DVOCLK_SP_MASK 0x00000f00L
+#define DVO_STRENGTH_CONTROL__DVOCLK_SP__SHIFT 0x00000008
+#define DVO_STRENGTH_CONTROL__DVO_LSB_VMODE_MASK 0x10000000L
+#define DVO_STRENGTH_CONTROL__DVO_LSB_VMODE__SHIFT 0x0000001c
+#define DVO_STRENGTH_CONTROL__DVO_MSB_VMODE_MASK 0x20000000L
+#define DVO_STRENGTH_CONTROL__DVO_MSB_VMODE__SHIFT 0x0000001d
+#define DVO_STRENGTH_CONTROL__DVO_SN_MASK 0x000000f0L
+#define DVO_STRENGTH_CONTROL__DVO_SN__SHIFT 0x00000004
+#define DVO_STRENGTH_CONTROL__DVO_SP_MASK 0x0000000fL
+#define DVO_STRENGTH_CONTROL__DVO_SP__SHIFT 0x00000000
+#define DVO_VREF_CONTROL__DVO_VREFCAL_MASK 0x000000f0L
+#define DVO_VREF_CONTROL__DVO_VREFCAL__SHIFT 0x00000004
+#define DVO_VREF_CONTROL__DVO_VREFPON_MASK 0x00000001L
+#define DVO_VREF_CONTROL__DVO_VREFPON__SHIFT 0x00000000
+#define DVO_VREF_CONTROL__DVO_VREFSEL_MASK 0x00000002L
+#define DVO_VREF_CONTROL__DVO_VREFSEL__SHIFT 0x00000001
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT_MASK 0x0fff0000L
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_LEFT__SHIFT 0x00000010
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT_MASK 0x00000fffL
+#define EXT_OVERSCAN_LEFT_RIGHT__EXT_OVERSCAN_RIGHT__SHIFT 0x00000000
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM_MASK 0x00000fffL
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_BOTTOM__SHIFT 0x00000000
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP_MASK 0x0fff0000L
+#define EXT_OVERSCAN_TOP_BOTTOM__EXT_OVERSCAN_TOP__SHIFT 0x00000010
+#define FBC_CLIENT_REGION_MASK__FBC_MEMORY_REGION_MASK_MASK 0x000f0000L
+#define FBC_CLIENT_REGION_MASK__FBC_MEMORY_REGION_MASK__SHIFT 0x00000010
+#define FBC_CNTL__FBC_COHERENCY_MODE_MASK 0x00030000L
+#define FBC_CNTL__FBC_COHERENCY_MODE__SHIFT 0x00000010
+#define FBC_CNTL__FBC_EN_MASK 0x80000000L
+#define FBC_CNTL__FBC_EN__SHIFT 0x0000001f
+#define FBC_CNTL__FBC_GRPH_COMP_EN_MASK 0x00000001L
+#define FBC_CNTL__FBC_GRPH_COMP_EN__SHIFT 0x00000000
+#define FBC_CNTL__FBC_SOFT_COMPRESS_EN_MASK 0x02000000L
+#define FBC_CNTL__FBC_SOFT_COMPRESS_EN__SHIFT 0x00000019
+#define FBC_CNTL__FBC_SRC_SEL_MASK 0x0000000eL
+#define FBC_CNTL__FBC_SRC_SEL__SHIFT 0x00000001
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO08_EN_MASK 0x00010000L
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO08_EN__SHIFT 0x00000010
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO16_EN_MASK 0x00020000L
+#define FBC_COMP_CNTL__FBC_DEPTH_MONO16_EN__SHIFT 0x00000011
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB04_EN_MASK 0x00040000L
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB04_EN__SHIFT 0x00000012
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB08_EN_MASK 0x00080000L
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB08_EN__SHIFT 0x00000013
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB16_EN_MASK 0x00100000L
+#define FBC_COMP_CNTL__FBC_DEPTH_RGB16_EN__SHIFT 0x00000014
+#define FBC_COMP_CNTL__FBC_MIN_COMPRESSION_MASK 0x0000000fL
+#define FBC_COMP_CNTL__FBC_MIN_COMPRESSION__SHIFT 0x00000000
+#define FBC_COMP_MODE__FBC_DPCM4_RGB_EN_MASK 0x00000100L
+#define FBC_COMP_MODE__FBC_DPCM4_RGB_EN__SHIFT 0x00000008
+#define FBC_COMP_MODE__FBC_DPCM4_YUV_EN_MASK 0x00000400L
+#define FBC_COMP_MODE__FBC_DPCM4_YUV_EN__SHIFT 0x0000000a
+#define FBC_COMP_MODE__FBC_DPCM8_RGB_EN_MASK 0x00000200L
+#define FBC_COMP_MODE__FBC_DPCM8_RGB_EN__SHIFT 0x00000009
+#define FBC_COMP_MODE__FBC_DPCM8_YUV_EN_MASK 0x00000800L
+#define FBC_COMP_MODE__FBC_DPCM8_YUV_EN__SHIFT 0x0000000b
+#define FBC_COMP_MODE__FBC_IND_EN_MASK 0x00010000L
+#define FBC_COMP_MODE__FBC_IND_EN__SHIFT 0x00000010
+#define FBC_COMP_MODE__FBC_RLE_EN_MASK 0x00000001L
+#define FBC_COMP_MODE__FBC_RLE_EN__SHIFT 0x00000000
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_0_MASK 0x000003ffL
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_0__SHIFT 0x00000000
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_1_MASK 0x03ff0000L
+#define FBC_CSM_REGION_OFFSET_01__FBC_CSM_REGION_OFFSET_1__SHIFT 0x00000010
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_2_MASK 0x000003ffL
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_2__SHIFT 0x00000000
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_3_MASK 0x03ff0000L
+#define FBC_CSM_REGION_OFFSET_23__FBC_CSM_REGION_OFFSET_3__SHIFT 0x00000010
+#define FBC_DEBUG0__FBC_COMP_WAKE_DIS_MASK 0x00010000L
+#define FBC_DEBUG0__FBC_COMP_WAKE_DIS__SHIFT 0x00000010
+#define FBC_DEBUG0__FBC_DEBUG0_MASK 0x00fe0000L
+#define FBC_DEBUG0__FBC_DEBUG0__SHIFT 0x00000011
+#define FBC_DEBUG0__FBC_DEBUG_MUX_MASK 0xff000000L
+#define FBC_DEBUG0__FBC_DEBUG_MUX__SHIFT 0x00000018
+#define FBC_DEBUG0__FBC_PERF_MUX0_MASK 0x000000ffL
+#define FBC_DEBUG0__FBC_PERF_MUX0__SHIFT 0x00000000
+#define FBC_DEBUG0__FBC_PERF_MUX1_MASK 0x0000ff00L
+#define FBC_DEBUG0__FBC_PERF_MUX1__SHIFT 0x00000008
+#define FBC_DEBUG1__FBC_DEBUG1_MASK 0xffffffffL
+#define FBC_DEBUG1__FBC_DEBUG1__SHIFT 0x00000000
+#define FBC_DEBUG2__FBC_DEBUG2_MASK 0xffffffffL
+#define FBC_DEBUG2__FBC_DEBUG2__SHIFT 0x00000000
+#define FBC_DEBUG_COMP__FBC_COMP_ADDRESS_TRANSLATION_ENABLE_MASK 0x00000800L
+#define FBC_DEBUG_COMP__FBC_COMP_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x0000000b
+#define FBC_DEBUG_COMP__FBC_COMP_BUSY_HYSTERESIS_MASK 0x000000f0L
+#define FBC_DEBUG_COMP__FBC_COMP_BUSY_HYSTERESIS__SHIFT 0x00000004
+#define FBC_DEBUG_COMP__FBC_COMP_CLK_CNTL_MASK 0x00000300L
+#define FBC_DEBUG_COMP__FBC_COMP_CLK_CNTL__SHIFT 0x00000008
+#define FBC_DEBUG_COMP__FBC_COMP_PRIVILEGED_ACCESS_ENABLE_MASK 0x00000400L
+#define FBC_DEBUG_COMP__FBC_COMP_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x0000000a
+#define FBC_DEBUG_COMP__FBC_COMP_RSIZE_MASK 0x00000008L
+#define FBC_DEBUG_COMP__FBC_COMP_RSIZE__SHIFT 0x00000003
+#define FBC_DEBUG_COMP__FBC_COMP_SWAP_MASK 0x00000003L
+#define FBC_DEBUG_COMP__FBC_COMP_SWAP__SHIFT 0x00000000
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_ADDR_MASK 0x000003ffL
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_ADDR__SHIFT 0x00000000
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_EN_MASK 0x80000000L
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_EN__SHIFT 0x0000001f
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_RD_DATA_MASK 0x00020000L
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_RD_DATA__SHIFT 0x00000011
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_WR_DATA_MASK 0x00010000L
+#define FBC_DEBUG_CSR__FBC_DEBUG_CSR_WR_DATA__SHIFT 0x00000010
+#define FBC_DEBUG_CSR_RDATA__FBC_DEBUG_CSR_RDATA_MASK 0xffffffffL
+#define FBC_DEBUG_CSR_RDATA__FBC_DEBUG_CSR_RDATA__SHIFT 0x00000000
+#define FBC_DEBUG_CSR_RDATA_HI__FBC_DEBUG_CSR_RDATA_HI_MASK 0x000000ffL
+#define FBC_DEBUG_CSR_RDATA_HI__FBC_DEBUG_CSR_RDATA_HI__SHIFT 0x00000000
+#define FBC_DEBUG_CSR_WDATA__FBC_DEBUG_CSR_WDATA_MASK 0xffffffffL
+#define FBC_DEBUG_CSR_WDATA__FBC_DEBUG_CSR_WDATA__SHIFT 0x00000000
+#define FBC_DEBUG_CSR_WDATA_HI__FBC_DEBUG_CSR_WDATA_HI_MASK 0x000000ffL
+#define FBC_DEBUG_CSR_WDATA_HI__FBC_DEBUG_CSR_WDATA_HI__SHIFT 0x00000000
+#define FBC_IDLE_FORCE_CLEAR_MASK__FBC_IDLE_FORCE_CLEAR_MASK_MASK 0xffffffffL
+#define FBC_IDLE_FORCE_CLEAR_MASK__FBC_IDLE_FORCE_CLEAR_MASK__SHIFT 0x00000000
+#define FBC_IDLE_MASK__FBC_IDLE_MASK_MASK 0xffffffffL
+#define FBC_IDLE_MASK__FBC_IDLE_MASK__SHIFT 0x00000000
+#define FBC_IND_LUT0__FBC_IND_LUT0_MASK 0x00ffffffL
+#define FBC_IND_LUT0__FBC_IND_LUT0__SHIFT 0x00000000
+#define FBC_IND_LUT10__FBC_IND_LUT10_MASK 0x00ffffffL
+#define FBC_IND_LUT10__FBC_IND_LUT10__SHIFT 0x00000000
+#define FBC_IND_LUT11__FBC_IND_LUT11_MASK 0x00ffffffL
+#define FBC_IND_LUT11__FBC_IND_LUT11__SHIFT 0x00000000
+#define FBC_IND_LUT12__FBC_IND_LUT12_MASK 0x00ffffffL
+#define FBC_IND_LUT12__FBC_IND_LUT12__SHIFT 0x00000000
+#define FBC_IND_LUT13__FBC_IND_LUT13_MASK 0x00ffffffL
+#define FBC_IND_LUT13__FBC_IND_LUT13__SHIFT 0x00000000
+#define FBC_IND_LUT14__FBC_IND_LUT14_MASK 0x00ffffffL
+#define FBC_IND_LUT14__FBC_IND_LUT14__SHIFT 0x00000000
+#define FBC_IND_LUT15__FBC_IND_LUT15_MASK 0x00ffffffL
+#define FBC_IND_LUT15__FBC_IND_LUT15__SHIFT 0x00000000
+#define FBC_IND_LUT1__FBC_IND_LUT1_MASK 0x00ffffffL
+#define FBC_IND_LUT1__FBC_IND_LUT1__SHIFT 0x00000000
+#define FBC_IND_LUT2__FBC_IND_LUT2_MASK 0x00ffffffL
+#define FBC_IND_LUT2__FBC_IND_LUT2__SHIFT 0x00000000
+#define FBC_IND_LUT3__FBC_IND_LUT3_MASK 0x00ffffffL
+#define FBC_IND_LUT3__FBC_IND_LUT3__SHIFT 0x00000000
+#define FBC_IND_LUT4__FBC_IND_LUT4_MASK 0x00ffffffL
+#define FBC_IND_LUT4__FBC_IND_LUT4__SHIFT 0x00000000
+#define FBC_IND_LUT5__FBC_IND_LUT5_MASK 0x00ffffffL
+#define FBC_IND_LUT5__FBC_IND_LUT5__SHIFT 0x00000000
+#define FBC_IND_LUT6__FBC_IND_LUT6_MASK 0x00ffffffL
+#define FBC_IND_LUT6__FBC_IND_LUT6__SHIFT 0x00000000
+#define FBC_IND_LUT7__FBC_IND_LUT7_MASK 0x00ffffffL
+#define FBC_IND_LUT7__FBC_IND_LUT7__SHIFT 0x00000000
+#define FBC_IND_LUT8__FBC_IND_LUT8_MASK 0x00ffffffL
+#define FBC_IND_LUT8__FBC_IND_LUT8__SHIFT 0x00000000
+#define FBC_IND_LUT9__FBC_IND_LUT9_MASK 0x00ffffffL
+#define FBC_IND_LUT9__FBC_IND_LUT9__SHIFT 0x00000000
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_CLEAR_MASK 0x00010000L
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_CLEAR__SHIFT 0x00000010
+#define FBC_MISC__FBC_DECOMPRESS_ERROR_MASK 0x00000003L
+#define FBC_MISC__FBC_DECOMPRESS_ERROR__SHIFT 0x00000000
+#define FBC_MISC__FBC_DIVIDE_X_MASK 0x00000300L
+#define FBC_MISC__FBC_DIVIDE_X__SHIFT 0x00000008
+#define FBC_MISC__FBC_DIVIDE_Y_MASK 0x00000400L
+#define FBC_MISC__FBC_DIVIDE_Y__SHIFT 0x0000000a
+#define FBC_MISC__FBC_ERROR_PIXEL_MASK 0x000000f0L
+#define FBC_MISC__FBC_ERROR_PIXEL__SHIFT 0x00000004
+#define FBC_MISC__FBC_INVALIDATE_ON_ERROR_MASK 0x00000008L
+#define FBC_MISC__FBC_INVALIDATE_ON_ERROR__SHIFT 0x00000003
+#define FBC_MISC__FBC_RESET_AT_DISABLE_MASK 0x00200000L
+#define FBC_MISC__FBC_RESET_AT_DISABLE__SHIFT 0x00000015
+#define FBC_MISC__FBC_RESET_AT_ENABLE_MASK 0x00100000L
+#define FBC_MISC__FBC_RESET_AT_ENABLE__SHIFT 0x00000014
+#define FBC_MISC__FBC_RSM_UNCOMP_DATA_IMMEDIATELY_MASK 0x00001000L
+#define FBC_MISC__FBC_RSM_UNCOMP_DATA_IMMEDIATELY__SHIFT 0x0000000c
+#define FBC_MISC__FBC_RSM_WRITE_VALUE_MASK 0x00000800L
+#define FBC_MISC__FBC_RSM_WRITE_VALUE__SHIFT 0x0000000b
+#define FBC_MISC__FBC_SLOW_REQ_INTERVAL_MASK 0xf0000000L
+#define FBC_MISC__FBC_SLOW_REQ_INTERVAL__SHIFT 0x0000001c
+#define FBC_MISC__FBC_STOP_ON_ERROR_MASK 0x00000004L
+#define FBC_MISC__FBC_STOP_ON_ERROR__SHIFT 0x00000002
+#define FBC_START_STOP_DELAY__FBC_COMP_START_DELAY_MASK 0x00001f00L
+#define FBC_START_STOP_DELAY__FBC_COMP_START_DELAY__SHIFT 0x00000008
+#define FBC_START_STOP_DELAY__FBC_DECOMP_START_DELAY_MASK 0x0000001fL
+#define FBC_START_STOP_DELAY__FBC_DECOMP_START_DELAY__SHIFT 0x00000000
+#define FBC_START_STOP_DELAY__FBC_DECOMP_STOP_DELAY_MASK 0x00000080L
+#define FBC_START_STOP_DELAY__FBC_DECOMP_STOP_DELAY__SHIFT 0x00000007
+#define FBC_STATUS__FBC_ENABLE_STATUS_MASK 0x00000001L
+#define FBC_STATUS__FBC_ENABLE_STATUS__SHIFT 0x00000000
+#define FBC_TEST_DEBUG_DATA__FBC_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define FBC_TEST_DEBUG_DATA__FBC_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define FBC_TEST_DEBUG_INDEX__FBC_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define FMT_BIT_DEPTH_CONTROL__FMT_25FRC_SEL_MASK 0x0c000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_25FRC_SEL__SHIFT 0x0000001a
+#define FMT_BIT_DEPTH_CONTROL__FMT_50FRC_SEL_MASK 0x30000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_50FRC_SEL__SHIFT 0x0000001c
+#define FMT_BIT_DEPTH_CONTROL__FMT_75FRC_SEL_MASK 0xc0000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_75FRC_SEL__SHIFT 0x0000001e
+#define FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE_MASK 0x00002000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_FRAME_RANDOM_ENABLE__SHIFT 0x0000000d
+#define FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE_MASK 0x00008000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_HIGHPASS_RANDOM_ENABLE__SHIFT 0x0000000f
+#define FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE_MASK 0x00004000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_RGB_RANDOM_ENABLE__SHIFT 0x0000000e
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH_MASK 0x00001000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_DEPTH__SHIFT 0x0000000c
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN_MASK 0x00000100L
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_EN__SHIFT 0x00000008
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_MODE_MASK 0x00000600L
+#define FMT_BIT_DEPTH_CONTROL__FMT_SPATIAL_DITHER_MODE__SHIFT 0x00000009
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_DEPTH_MASK 0x00100000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_DEPTH__SHIFT 0x00000014
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_EN_MASK 0x00010000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_EN__SHIFT 0x00000010
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_OFFSET_MASK 0x00600000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_OFFSET__SHIFT 0x00000015
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_RESET_MASK 0x02000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_DITHER_RESET__SHIFT 0x00000019
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_LEVEL_MASK 0x01000000L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TEMPORAL_LEVEL__SHIFT 0x00000018
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH_MASK 0x00000010L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_DEPTH__SHIFT 0x00000004
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN_MASK 0x00000001L
+#define FMT_BIT_DEPTH_CONTROL__FMT_TRUNCATE_EN__SHIFT 0x00000000
+#define FMT_CLAMP_CNTL__FMT_CLAMP_COLOR_FORMAT_MASK 0x00070000L
+#define FMT_CLAMP_CNTL__FMT_CLAMP_COLOR_FORMAT__SHIFT 0x00000010
+#define FMT_CLAMP_CNTL__FMT_CLAMP_DATA_EN_MASK 0x00000001L
+#define FMT_CLAMP_CNTL__FMT_CLAMP_DATA_EN__SHIFT 0x00000000
+#define FMT_CONTROL__FMT_PIXEL_ENCODING_MASK 0x00010000L
+#define FMT_CONTROL__FMT_PIXEL_ENCODING__SHIFT 0x00000010
+#define FMT_CONTROL__FMT_STEREOSYNC_OVERRIDE_MASK 0x00000001L
+#define FMT_CONTROL__FMT_STEREOSYNC_OVERRIDE__SHIFT 0x00000000
+#define FMT_CONTROL__FMT_STEREOSYNC_OVR_POL_MASK 0x00000010L
+#define FMT_CONTROL__FMT_STEREOSYNC_OVR_POL__SHIFT 0x00000004
+#define FMT_CRC_CNTL__FMT_CRC_CONT_EN_MASK 0x00000010L
+#define FMT_CRC_CNTL__FMT_CRC_CONT_EN__SHIFT 0x00000004
+#define FMT_CRC_CNTL__FMT_CRC_EN_MASK 0x00000001L
+#define FMT_CRC_CNTL__FMT_CRC_EN__SHIFT 0x00000000
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_ENABLE_MASK 0x00100000L
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_ENABLE__SHIFT 0x00000014
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_SELECT_MASK 0x01000000L
+#define FMT_CRC_CNTL__FMT_CRC_EVEN_ODD_PIX_SELECT__SHIFT 0x00000018
+#define FMT_CRC_CNTL__FMT_CRC_INTERLACE_MODE_MASK 0x00003000L
+#define FMT_CRC_CNTL__FMT_CRC_INTERLACE_MODE__SHIFT 0x0000000c
+#define FMT_CRC_CNTL__FMT_CRC_ONLY_BLANKb_MASK 0x00000100L
+#define FMT_CRC_CNTL__FMT_CRC_ONLY_BLANKb__SHIFT 0x00000008
+#define FMT_CRC_CNTL__FMT_CRC_USE_NEW_AND_REPEATED_PIXELS_MASK 0x00010000L
+#define FMT_CRC_CNTL__FMT_CRC_USE_NEW_AND_REPEATED_PIXELS__SHIFT 0x00000010
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_BLUE_MASK 0x0000ffffL
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_BLUE__SHIFT 0x00000000
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_CONTROL_MASK 0xffff0000L
+#define FMT_CRC_SIG_BLUE_CONTROL__FMT_CRC_SIG_CONTROL__SHIFT 0x00000010
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_BLUE_MASK_MASK 0x0000ffffL
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_BLUE_MASK__SHIFT 0x00000000
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_CONTROL_MASK_MASK 0xffff0000L
+#define FMT_CRC_SIG_BLUE_CONTROL_MASK__FMT_CRC_SIG_CONTROL_MASK__SHIFT 0x00000010
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_GREEN_MASK 0xffff0000L
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_GREEN__SHIFT 0x00000010
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_RED_MASK 0x0000ffffL
+#define FMT_CRC_SIG_RED_GREEN__FMT_CRC_SIG_RED__SHIFT 0x00000000
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_GREEN_MASK_MASK 0xffff0000L
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_GREEN_MASK__SHIFT 0x00000010
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_RED_MASK_MASK 0x0000ffffL
+#define FMT_CRC_SIG_RED_GREEN_MASK__FMT_CRC_SIG_RED_MASK__SHIFT 0x00000000
+#define FMT_DEBUG0__FMT_DEBUG0_MASK 0xffffffffL
+#define FMT_DEBUG0__FMT_DEBUG0__SHIFT 0x00000000
+#define FMT_DEBUG1__FMT_DEBUG1_MASK 0xffffffffL
+#define FMT_DEBUG1__FMT_DEBUG1__SHIFT 0x00000000
+#define FMT_DEBUG2__FMT_DEBUG2_MASK 0xffffffffL
+#define FMT_DEBUG2__FMT_DEBUG2__SHIFT 0x00000000
+#define FMT_DEBUG_CNTL__FMT_DEBUG_COLOR_SELECT_MASK 0x00000003L
+#define FMT_DEBUG_CNTL__FMT_DEBUG_COLOR_SELECT__SHIFT 0x00000000
+#define FMT_DEBUG_ID__FMT_DEBUG_ID_MASK 0xffffffffL
+#define FMT_DEBUG_ID__FMT_DEBUG_ID__SHIFT 0x00000000
+#define FMT_DITHER_RAND_B_SEED__FMT_RAND_B_SEED_MASK 0x000000ffL
+#define FMT_DITHER_RAND_B_SEED__FMT_RAND_B_SEED__SHIFT 0x00000000
+#define FMT_DITHER_RAND_G_SEED__FMT_RAND_G_SEED_MASK 0x000000ffL
+#define FMT_DITHER_RAND_G_SEED__FMT_RAND_G_SEED__SHIFT 0x00000000
+#define FMT_DITHER_RAND_R_SEED__FMT_RAND_R_SEED_MASK 0x000000ffL
+#define FMT_DITHER_RAND_R_SEED__FMT_RAND_R_SEED__SHIFT 0x00000000
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_EN_MASK 0x00000001L
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_EN__SHIFT 0x00000000
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_MODE_MASK 0x00000010L
+#define FMT_DYNAMIC_EXP_CNTL__FMT_DYNAMIC_EXP_MODE__SHIFT 0x00000004
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA0_MASK 0x0000ffffL
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA0__SHIFT 0x00000000
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA1_MASK 0xffff0000L
+#define FMT_FORCE_DATA_0_1__FMT_FORCE_DATA1__SHIFT 0x00000010
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA2_MASK 0x0000ffffL
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA2__SHIFT 0x00000000
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA3_MASK 0xffff0000L
+#define FMT_FORCE_DATA_2_3__FMT_FORCE_DATA3__SHIFT 0x00000010
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_EN_MASK 0x00000001L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_EN__SHIFT 0x00000000
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_ON_BLANKb_ONLY_MASK 0x00010000L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_ON_BLANKb_ONLY__SHIFT 0x00000010
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_COLOR_MASK 0x00000700L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_COLOR__SHIFT 0x00000008
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_SLOT_MASK 0x0000f000L
+#define FMT_FORCE_OUTPUT_CNTL__FMT_FORCE_DATA_SEL_SLOT__SHIFT 0x0000000c
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_RGB1_BGR0_MASK 0x00000010L
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_RGB1_BGR0__SHIFT 0x00000004
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_SELECT_MASK 0x00000001L
+#define FMT_TEMPORAL_DITHER_PATTERN_CONTROL__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_SELECT__SHIFT 0x00000000
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX_MASK 0xffffffffL
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_S_MATRIX__SHIFT 0x00000000
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX_MASK 0xffffffffL
+#define FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__FMT_TEMPORAL_DITHER_PROGRAMMABLE_PATTERN_T_MATRIX__SHIFT 0x00000000
+#define FMT_TEST_DEBUG_DATA__FMT_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define FMT_TEST_DEBUG_DATA__FMT_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define FMT_TEST_DEBUG_INDEX__FMT_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C11_MASK 0x0000ffffL
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C11__SHIFT 0x00000000
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C12_MASK 0xffff0000L
+#define GAMUT_REMAP_C11_C12__GAMUT_REMAP_C12__SHIFT 0x00000010
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C13_MASK 0x0000ffffL
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C13__SHIFT 0x00000000
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C14_MASK 0xffff0000L
+#define GAMUT_REMAP_C13_C14__GAMUT_REMAP_C14__SHIFT 0x00000010
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C21_MASK 0x0000ffffL
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C21__SHIFT 0x00000000
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C22_MASK 0xffff0000L
+#define GAMUT_REMAP_C21_C22__GAMUT_REMAP_C22__SHIFT 0x00000010
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C23_MASK 0x0000ffffL
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C23__SHIFT 0x00000000
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C24_MASK 0xffff0000L
+#define GAMUT_REMAP_C23_C24__GAMUT_REMAP_C24__SHIFT 0x00000010
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C31_MASK 0x0000ffffL
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C31__SHIFT 0x00000000
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C32_MASK 0xffff0000L
+#define GAMUT_REMAP_C31_C32__GAMUT_REMAP_C32__SHIFT 0x00000010
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C33_MASK 0x0000ffffL
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C33__SHIFT 0x00000000
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C34_MASK 0xffff0000L
+#define GAMUT_REMAP_C33_C34__GAMUT_REMAP_C34__SHIFT 0x00000010
+#define GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE_MASK 0x00000003L
+#define GAMUT_REMAP_CONTROL__GRPH_GAMUT_REMAP_MODE__SHIFT 0x00000000
+#define GAMUT_REMAP_CONTROL__OVL_GAMUT_REMAP_MODE_MASK 0x00000030L
+#define GAMUT_REMAP_CONTROL__OVL_GAMUT_REMAP_MODE__SHIFT 0x00000004
+#define GENENB__BLK_IO_BASE_MASK 0x000000ffL
+#define GENENB__BLK_IO_BASE__SHIFT 0x00000000
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_DBG_REF_SEL_MASK 0x80000000L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_DBG_REF_SEL__SHIFT 0x0000001f
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_ENABLE_MASK 0x00000008L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_ENABLE__SHIFT 0x00000003
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_GO_MASK 0x00000001L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_GO__SHIFT 0x00000000
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SEND_RESET_MASK 0x00000004L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SEND_RESET__SHIFT 0x00000002
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SOFT_RESET_MASK 0x00000002L
+#define GENERIC_I2C_CONTROL__GENERIC_I2C_SOFT_RESET__SHIFT 0x00000001
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_MASK 0x0000ff00L
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_RW_MASK 0x00000001L
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA_RW__SHIFT 0x00000000
+#define GENERIC_I2C_DATA__GENERIC_I2C_DATA__SHIFT 0x00000008
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_MASK 0x000f0000L
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX__SHIFT 0x00000010
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_WRITE_MASK 0x80000000L
+#define GENERIC_I2C_DATA__GENERIC_I2C_INDEX_WRITE__SHIFT 0x0000001f
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_ACK_MASK 0x00000002L
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_ACK__SHIFT 0x00000001
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_INT_MASK 0x00000001L
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_INT__SHIFT 0x00000000
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_MASK_MASK 0x00000004L
+#define GENERIC_I2C_INTERRUPT_CONTROL__GENERIC_I2C_DONE_MASK__SHIFT 0x00000002
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_EN_MASK 0x00000004L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_EN__SHIFT 0x00000002
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_INPUT_MASK 0x00000002L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_INPUT__SHIFT 0x00000001
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_OUTPUT_MASK 0x00000001L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SCL_OUTPUT__SHIFT 0x00000000
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_EN_MASK 0x00000040L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_EN__SHIFT 0x00000006
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_INPUT_MASK 0x00000020L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_INPUT__SHIFT 0x00000005
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_OUTPUT_MASK 0x00000010L
+#define GENERIC_I2C_PIN_DEBUG__GENERIC_I2C_SDA_OUTPUT__SHIFT 0x00000004
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SCL_PIN_SEL_MASK 0x0000007fL
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SCL_PIN_SEL__SHIFT 0x00000000
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SDA_PIN_SEL_MASK 0x00007f00L
+#define GENERIC_I2C_PIN_SELECTION__GENERIC_I2C_SDA_PIN_SEL__SHIFT 0x00000008
+#define GENERIC_I2C_SETUP__GENERIC_I2C_CLK_DRIVE_EN_MASK 0x00000080L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_CLK_DRIVE_EN__SHIFT 0x00000007
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_EN_MASK 0x00000001L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_EN__SHIFT 0x00000000
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_SEL_MASK 0x00000002L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_DATA_DRIVE_SEL__SHIFT 0x00000001
+#define GENERIC_I2C_SETUP__GENERIC_I2C_INTRA_BYTE_DELAY_MASK 0x0000ff00L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_INTRA_BYTE_DELAY__SHIFT 0x00000008
+#define GENERIC_I2C_SETUP__GENERIC_I2C_TIME_LIMIT_MASK 0xff000000L
+#define GENERIC_I2C_SETUP__GENERIC_I2C_TIME_LIMIT__SHIFT 0x00000018
+#define GENERIC_I2C_SPEED__GENERIC_I2C_DISABLE_FILTER_DURING_STALL_MASK 0x00000010L
+#define GENERIC_I2C_SPEED__GENERIC_I2C_DISABLE_FILTER_DURING_STALL__SHIFT 0x00000004
+#define GENERIC_I2C_SPEED__GENERIC_I2C_PRESCALE_MASK 0xffff0000L
+#define GENERIC_I2C_SPEED__GENERIC_I2C_PRESCALE__SHIFT 0x00000010
+#define GENERIC_I2C_SPEED__GENERIC_I2C_THRESHOLD_MASK 0x00000003L
+#define GENERIC_I2C_SPEED__GENERIC_I2C_THRESHOLD__SHIFT 0x00000000
+#define GENERIC_I2C_STATUS__GENERIC_I2C_ABORTED_MASK 0x00000020L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_ABORTED__SHIFT 0x00000005
+#define GENERIC_I2C_STATUS__GENERIC_I2C_DONE_MASK 0x00000010L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_DONE__SHIFT 0x00000004
+#define GENERIC_I2C_STATUS__GENERIC_I2C_NACK_MASK 0x00000400L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_NACK__SHIFT 0x0000000a
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STATUS_MASK 0x0000000fL
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STATUS__SHIFT 0x00000000
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STOPPED_ON_NACK_MASK 0x00000200L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_STOPPED_ON_NACK__SHIFT 0x00000009
+#define GENERIC_I2C_STATUS__GENERIC_I2C_TIMEOUT_MASK 0x00000040L
+#define GENERIC_I2C_STATUS__GENERIC_I2C_TIMEOUT__SHIFT 0x00000006
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_ACK_ON_READ_MASK 0x00000200L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_ACK_ON_READ__SHIFT 0x00000009
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_COUNT_MASK 0x000f0000L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_COUNT__SHIFT 0x00000010
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_RW_MASK 0x00000001L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_RW__SHIFT 0x00000000
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_START_MASK 0x00001000L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_START__SHIFT 0x0000000c
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_MASK 0x00002000L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_ON_NACK_MASK 0x00000100L
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP_ON_NACK__SHIFT 0x00000008
+#define GENERIC_I2C_TRANSACTION__GENERIC_I2C_STOP__SHIFT 0x0000000d
+#define GENFC_RD__VSYNC_SEL_R_MASK 0x00000008L
+#define GENFC_RD__VSYNC_SEL_R__SHIFT 0x00000003
+#define GENFC_WT__VSYNC_SEL_W_MASK 0x00000008L
+#define GENFC_WT__VSYNC_SEL_W__SHIFT 0x00000003
+#define GENMO_RD__GENMO_MONO_ADDRESS_B_MASK 0x00000001L
+#define GENMO_RD__GENMO_MONO_ADDRESS_B__SHIFT 0x00000000
+#define GENMO_RD__ODD_EVEN_MD_PGSEL_MASK 0x00000020L
+#define GENMO_RD__ODD_EVEN_MD_PGSEL__SHIFT 0x00000005
+#define GENMO_RD__VGA_CKSEL_MASK 0x0000000cL
+#define GENMO_RD__VGA_CKSEL__SHIFT 0x00000002
+#define GENMO_RD__VGA_HSYNC_POL_MASK 0x00000040L
+#define GENMO_RD__VGA_HSYNC_POL__SHIFT 0x00000006
+#define GENMO_RD__VGA_RAM_EN_MASK 0x00000002L
+#define GENMO_RD__VGA_RAM_EN__SHIFT 0x00000001
+#define GENMO_RD__VGA_VSYNC_POL_MASK 0x00000080L
+#define GENMO_RD__VGA_VSYNC_POL__SHIFT 0x00000007
+#define GENMO_WT__GENMO_MONO_ADDRESS_B_MASK 0x00000001L
+#define GENMO_WT__GENMO_MONO_ADDRESS_B__SHIFT 0x00000000
+#define GENMO_WT__ODD_EVEN_MD_PGSEL_MASK 0x00000020L
+#define GENMO_WT__ODD_EVEN_MD_PGSEL__SHIFT 0x00000005
+#define GENMO_WT__VGA_CKSEL_MASK 0x0000000cL
+#define GENMO_WT__VGA_CKSEL__SHIFT 0x00000002
+#define GENMO_WT__VGA_HSYNC_POL_MASK 0x00000040L
+#define GENMO_WT__VGA_HSYNC_POL__SHIFT 0x00000006
+#define GENMO_WT__VGA_RAM_EN_MASK 0x00000002L
+#define GENMO_WT__VGA_RAM_EN__SHIFT 0x00000001
+#define GENMO_WT__VGA_VSYNC_POL_MASK 0x00000080L
+#define GENMO_WT__VGA_VSYNC_POL__SHIFT 0x00000007
+#define GENS0__CRT_INTR_MASK 0x00000080L
+#define GENS0__CRT_INTR__SHIFT 0x00000007
+#define GENS0__SENSE_SWITCH_MASK 0x00000010L
+#define GENS0__SENSE_SWITCH__SHIFT 0x00000004
+#define GENS1__NO_DISPLAY_MASK 0x00000001L
+#define GENS1__NO_DISPLAY__SHIFT 0x00000000
+#define GENS1__PIXEL_READ_BACK_MASK 0x00000030L
+#define GENS1__PIXEL_READ_BACK__SHIFT 0x00000004
+#define GENS1__VGA_VSTATUS_MASK 0x00000008L
+#define GENS1__VGA_VSTATUS__SHIFT 0x00000003
+#define GRA00__GRPH_SET_RESET0_MASK 0x00000001L
+#define GRA00__GRPH_SET_RESET0__SHIFT 0x00000000
+#define GRA00__GRPH_SET_RESET1_MASK 0x00000002L
+#define GRA00__GRPH_SET_RESET1__SHIFT 0x00000001
+#define GRA00__GRPH_SET_RESET2_MASK 0x00000004L
+#define GRA00__GRPH_SET_RESET2__SHIFT 0x00000002
+#define GRA00__GRPH_SET_RESET3_MASK 0x00000008L
+#define GRA00__GRPH_SET_RESET3__SHIFT 0x00000003
+#define GRA01__GRPH_SET_RESET_ENA0_MASK 0x00000001L
+#define GRA01__GRPH_SET_RESET_ENA0__SHIFT 0x00000000
+#define GRA01__GRPH_SET_RESET_ENA1_MASK 0x00000002L
+#define GRA01__GRPH_SET_RESET_ENA1__SHIFT 0x00000001
+#define GRA01__GRPH_SET_RESET_ENA2_MASK 0x00000004L
+#define GRA01__GRPH_SET_RESET_ENA2__SHIFT 0x00000002
+#define GRA01__GRPH_SET_RESET_ENA3_MASK 0x00000008L
+#define GRA01__GRPH_SET_RESET_ENA3__SHIFT 0x00000003
+#define GRA02__GRPH_CCOMP_MASK 0x0000000fL
+#define GRA02__GRPH_CCOMP__SHIFT 0x00000000
+#define GRA03__GRPH_FN_SEL_MASK 0x00000018L
+#define GRA03__GRPH_FN_SEL__SHIFT 0x00000003
+#define GRA03__GRPH_ROTATE_MASK 0x00000007L
+#define GRA03__GRPH_ROTATE__SHIFT 0x00000000
+#define GRA04__GRPH_RMAP_MASK 0x00000003L
+#define GRA04__GRPH_RMAP__SHIFT 0x00000000
+#define GRA05__CGA_ODDEVEN_MASK 0x00000010L
+#define GRA05__CGA_ODDEVEN__SHIFT 0x00000004
+#define GRA05__GRPH_OES_MASK 0x00000020L
+#define GRA05__GRPH_OES__SHIFT 0x00000005
+#define GRA05__GRPH_PACK_MASK 0x00000040L
+#define GRA05__GRPH_PACK__SHIFT 0x00000006
+#define GRA05__GRPH_READ1_MASK 0x00000008L
+#define GRA05__GRPH_READ1__SHIFT 0x00000003
+#define GRA05__GRPH_WRITE_MODE_MASK 0x00000003L
+#define GRA05__GRPH_WRITE_MODE__SHIFT 0x00000000
+#define GRA06__GRPH_ADRSEL_MASK 0x0000000cL
+#define GRA06__GRPH_ADRSEL__SHIFT 0x00000002
+#define GRA06__GRPH_GRAPHICS_MASK 0x00000001L
+#define GRA06__GRPH_GRAPHICS__SHIFT 0x00000000
+#define GRA06__GRPH_ODDEVEN_MASK 0x00000002L
+#define GRA06__GRPH_ODDEVEN__SHIFT 0x00000001
+#define GRA07__GRPH_XCARE0_MASK 0x00000001L
+#define GRA07__GRPH_XCARE0__SHIFT 0x00000000
+#define GRA07__GRPH_XCARE1_MASK 0x00000002L
+#define GRA07__GRPH_XCARE1__SHIFT 0x00000001
+#define GRA07__GRPH_XCARE2_MASK 0x00000004L
+#define GRA07__GRPH_XCARE2__SHIFT 0x00000002
+#define GRA07__GRPH_XCARE3_MASK 0x00000008L
+#define GRA07__GRPH_XCARE3__SHIFT 0x00000003
+#define GRA08__GRPH_BMSK_MASK 0x000000ffL
+#define GRA08__GRPH_BMSK__SHIFT 0x00000000
+#define GRPH8_DATA__GRPH_DATA_MASK 0x000000ffL
+#define GRPH8_DATA__GRPH_DATA__SHIFT 0x00000000
+#define GRPH8_IDX__GRPH_IDX_MASK 0x0000000fL
+#define GRPH8_IDX__GRPH_IDX__SHIFT 0x00000000
+#define GRPH_COMPRESS_PITCH__GRPH_COMPRESS_PITCH_MASK 0x0001ffc0L
+#define GRPH_COMPRESS_PITCH__GRPH_COMPRESS_PITCH__SHIFT 0x00000006
+#define GRPH_COMPRESS_SURFACE_ADDRESS__GRPH_COMPRESS_SURFACE_ADDRESS_MASK 0xffffff00L
+#define GRPH_COMPRESS_SURFACE_ADDRESS__GRPH_COMPRESS_SURFACE_ADDRESS__SHIFT 0x00000008
+#define GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__GRPH_COMPRESS_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__GRPH_COMPRESS_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE_MASK 0x00010000L
+#define GRPH_CONTROL__GRPH_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x00000010
+#define GRPH_CONTROL__GRPH_ARRAY_MODE_MASK 0x00f00000L
+#define GRPH_CONTROL__GRPH_ARRAY_MODE__SHIFT 0x00000014
+#define GRPH_CONTROL__GRPH_BANK_HEIGHT_MASK 0x00001800L
+#define GRPH_CONTROL__GRPH_BANK_HEIGHT__SHIFT 0x0000000b
+#define GRPH_CONTROL__GRPH_BANK_WIDTH_MASK 0x000000c0L
+#define GRPH_CONTROL__GRPH_BANK_WIDTH__SHIFT 0x00000006
+#define GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE_MASK 0x80000000L
+#define GRPH_CONTROL__GRPH_COLOR_EXPANSION_MODE__SHIFT 0x0000001f
+#define GRPH_CONTROL__GRPH_DEPTH_MASK 0x00000003L
+#define GRPH_CONTROL__GRPH_DEPTH__SHIFT 0x00000000
+#define GRPH_CONTROL__GRPH_FORMAT_MASK 0x00000700L
+#define GRPH_CONTROL__GRPH_FORMAT__SHIFT 0x00000008
+#define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT_MASK 0x000c0000L
+#define GRPH_CONTROL__GRPH_MACRO_TILE_ASPECT__SHIFT 0x00000012
+#define GRPH_CONTROL__GRPH_NUM_BANKS_MASK 0x0000000cL
+#define GRPH_CONTROL__GRPH_NUM_BANKS__SHIFT 0x00000002
+#define GRPH_CONTROL__GRPH_PIPE_CONFIG_MASK 0x1f000000L
+#define GRPH_CONTROL__GRPH_PIPE_CONFIG__SHIFT 0x00000018
+#define GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE_MASK 0x00020000L
+#define GRPH_CONTROL__GRPH_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x00000011
+#define GRPH_CONTROL__GRPH_TILE_SPLIT_MASK 0x0000e000L
+#define GRPH_CONTROL__GRPH_TILE_SPLIT__SHIFT 0x0000000d
+#define GRPH_CONTROL__GRPH_Z_MASK 0x00000030L
+#define GRPH_CONTROL__GRPH_Z__SHIFT 0x00000004
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_MIN_FREE_ENTRIES_MASK 0x00000700L
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_MIN_FREE_ENTRIES__SHIFT 0x00000008
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_RESET_MASK 0x00000001L
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_RESET__SHIFT 0x00000000
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_SIZE_MASK 0x00000070L
+#define GRPH_DFQ_CONTROL__GRPH_DFQ_SIZE__SHIFT 0x00000004
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_ACK_MASK 0x00000200L
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_ACK__SHIFT 0x00000009
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_FLAG_MASK 0x00000100L
+#define GRPH_DFQ_STATUS__GRPH_DFQ_RESET_FLAG__SHIFT 0x00000008
+#define GRPH_DFQ_STATUS__GRPH_PRIMARY_DFQ_NUM_ENTRIES_MASK 0x0000000fL
+#define GRPH_DFQ_STATUS__GRPH_PRIMARY_DFQ_NUM_ENTRIES__SHIFT 0x00000000
+#define GRPH_DFQ_STATUS__GRPH_SECONDARY_DFQ_NUM_ENTRIES_MASK 0x000000f0L
+#define GRPH_DFQ_STATUS__GRPH_SECONDARY_DFQ_NUM_ENTRIES__SHIFT 0x00000004
+#define GRPH_ENABLE__GRPH_ENABLE_MASK 0x00000001L
+#define GRPH_ENABLE__GRPH_ENABLE__SHIFT 0x00000000
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN_MASK 0x00000001L
+#define GRPH_FLIP_CONTROL__GRPH_SURFACE_UPDATE_H_RETRACE_EN__SHIFT 0x00000000
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK 0x00000001L
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK__SHIFT 0x00000000
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE_MASK 0x00000100L
+#define GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_TYPE__SHIFT 0x00000008
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK 0x00000100L
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR__SHIFT 0x00000008
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED_MASK 0x00000001L
+#define GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_OCCURRED__SHIFT 0x00000000
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN_MASK 0x00010000L
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_DBL_BUF_EN__SHIFT 0x00000010
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN_MASK 0x00000100L
+#define GRPH_LUT_10BIT_BYPASS__GRPH_LUT_10BIT_BYPASS_EN__SHIFT 0x00000008
+#define GRPH_PITCH__GRPH_PITCH_MASK 0x00007fffL
+#define GRPH_PITCH__GRPH_PITCH__SHIFT 0x00000000
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_DFQ_ENABLE_MASK 0x00000001L
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_DFQ_ENABLE__SHIFT 0x00000000
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS_MASK 0xffffff00L
+#define GRPH_PRIMARY_SURFACE_ADDRESS__GRPH_PRIMARY_SURFACE_ADDRESS__SHIFT 0x00000008
+#define GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_DFQ_ENABLE_MASK 0x00000001L
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_DFQ_ENABLE__SHIFT 0x00000000
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS_MASK 0xffffff00L
+#define GRPH_SECONDARY_SURFACE_ADDRESS__GRPH_SECONDARY_SURFACE_ADDRESS__SHIFT 0x00000008
+#define GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__GRPH_SECONDARY_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING_MASK 0x00010000L
+#define GRPH_STEREOSYNC_FLIP__GRPH_PRIMARY_SURFACE_PENDING__SHIFT 0x00000010
+#define GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING_MASK 0x00020000L
+#define GRPH_STEREOSYNC_FLIP__GRPH_SECONDARY_SURFACE_PENDING__SHIFT 0x00000011
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN_MASK 0x00000001L
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_EN__SHIFT 0x00000000
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE_MASK 0x00000300L
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_FLIP_MODE__SHIFT 0x00000008
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE_MASK 0x10000000L
+#define GRPH_STEREOSYNC_FLIP__GRPH_STEREOSYNC_SELECT_DISABLE__SHIFT 0x0000001c
+#define GRPH_SURFACE_ADDRESS_HIGH_INUSE__GRPH_SURFACE_ADDRESS_HIGH_INUSE_MASK 0x000000ffL
+#define GRPH_SURFACE_ADDRESS_HIGH_INUSE__GRPH_SURFACE_ADDRESS_HIGH_INUSE__SHIFT 0x00000000
+#define GRPH_SURFACE_ADDRESS_INUSE__GRPH_SURFACE_ADDRESS_INUSE_MASK 0xffffff00L
+#define GRPH_SURFACE_ADDRESS_INUSE__GRPH_SURFACE_ADDRESS_INUSE__SHIFT 0x00000008
+#define GRPH_SURFACE_OFFSET_X__GRPH_SURFACE_OFFSET_X_MASK 0x00003fffL
+#define GRPH_SURFACE_OFFSET_X__GRPH_SURFACE_OFFSET_X__SHIFT 0x00000000
+#define GRPH_SURFACE_OFFSET_Y__GRPH_SURFACE_OFFSET_Y_MASK 0x00003fffL
+#define GRPH_SURFACE_OFFSET_Y__GRPH_SURFACE_OFFSET_Y__SHIFT 0x00000000
+#define GRPH_SWAP_CNTL__GRPH_ALPHA_CROSSBAR_MASK 0x00000c00L
+#define GRPH_SWAP_CNTL__GRPH_ALPHA_CROSSBAR__SHIFT 0x0000000a
+#define GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR_MASK 0x00000300L
+#define GRPH_SWAP_CNTL__GRPH_BLUE_CROSSBAR__SHIFT 0x00000008
+#define GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP_MASK 0x00000003L
+#define GRPH_SWAP_CNTL__GRPH_ENDIAN_SWAP__SHIFT 0x00000000
+#define GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR_MASK 0x000000c0L
+#define GRPH_SWAP_CNTL__GRPH_GREEN_CROSSBAR__SHIFT 0x00000006
+#define GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR_MASK 0x00000030L
+#define GRPH_SWAP_CNTL__GRPH_RED_CROSSBAR__SHIFT 0x00000004
+#define GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE_MASK 0x01000000L
+#define GRPH_UPDATE__GRPH_MODE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x00000018
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING_MASK 0x00000001L
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_PENDING__SHIFT 0x00000000
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN_MASK 0x00000002L
+#define GRPH_UPDATE__GRPH_MODE_UPDATE_TAKEN__SHIFT 0x00000001
+#define GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE_MASK 0x10000000L
+#define GRPH_UPDATE__GRPH_SURFACE_DISABLE_MULTIPLE_UPDATE__SHIFT 0x0000001c
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING_MASK 0x00000004L
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_PENDING__SHIFT 0x00000002
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN_MASK 0x00000008L
+#define GRPH_UPDATE__GRPH_SURFACE_UPDATE_TAKEN__SHIFT 0x00000003
+#define GRPH_UPDATE__GRPH_SURFACE_XDMA_PENDING_ENABLE_MASK 0x00000100L
+#define GRPH_UPDATE__GRPH_SURFACE_XDMA_PENDING_ENABLE__SHIFT 0x00000008
+#define GRPH_UPDATE__GRPH_UPDATE_LOCK_MASK 0x00010000L
+#define GRPH_UPDATE__GRPH_UPDATE_LOCK__SHIFT 0x00000010
+#define GRPH_X_END__GRPH_X_END_MASK 0x00007fffL
+#define GRPH_X_END__GRPH_X_END__SHIFT 0x00000000
+#define GRPH_X_START__GRPH_X_START_MASK 0x00003fffL
+#define GRPH_X_START__GRPH_X_START__SHIFT 0x00000000
+#define GRPH_Y_END__GRPH_Y_END_MASK 0x00007fffL
+#define GRPH_Y_END__GRPH_Y_END__SHIFT 0x00000000
+#define GRPH_Y_START__GRPH_Y_START_MASK 0x00003fffL
+#define GRPH_Y_START__GRPH_Y_START__SHIFT 0x00000000
+#define HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK 0xfffff000L
+#define HDMI_ACR_32_0__HDMI_ACR_CTS_32__SHIFT 0x0000000c
+#define HDMI_ACR_32_1__HDMI_ACR_N_32_MASK 0x000fffffL
+#define HDMI_ACR_32_1__HDMI_ACR_N_32__SHIFT 0x00000000
+#define HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK 0xfffff000L
+#define HDMI_ACR_44_0__HDMI_ACR_CTS_44__SHIFT 0x0000000c
+#define HDMI_ACR_44_1__HDMI_ACR_N_44_MASK 0x000fffffL
+#define HDMI_ACR_44_1__HDMI_ACR_N_44__SHIFT 0x00000000
+#define HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK 0xfffff000L
+#define HDMI_ACR_48_0__HDMI_ACR_CTS_48__SHIFT 0x0000000c
+#define HDMI_ACR_48_1__HDMI_ACR_N_48_MASK 0x000fffffL
+#define HDMI_ACR_48_1__HDMI_ACR_N_48__SHIFT 0x00000000
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY_MASK 0x80000000L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUDIO_PRIORITY__SHIFT 0x0000001f
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND_MASK 0x00001000L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_AUTO_SEND__SHIFT 0x0000000c
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_CONT_MASK 0x00000002L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_CONT__SHIFT 0x00000001
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE_MASK 0x00070000L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE__SHIFT 0x00000010
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SELECT_MASK 0x00000030L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SELECT__SHIFT 0x00000004
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SEND_MASK 0x00000001L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SEND__SHIFT 0x00000000
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE_MASK 0x00000100L
+#define HDMI_ACR_PACKET_CONTROL__HDMI_ACR_SOURCE__SHIFT 0x00000008
+#define HDMI_ACR_STATUS_0__HDMI_ACR_CTS_MASK 0xfffff000L
+#define HDMI_ACR_STATUS_0__HDMI_ACR_CTS__SHIFT 0x0000000c
+#define HDMI_ACR_STATUS_1__HDMI_ACR_N_MASK 0x000fffffL
+#define HDMI_ACR_STATUS_1__HDMI_ACR_N__SHIFT 0x00000000
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_DELAY_EN_MASK 0x00000030L
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_DELAY_EN__SHIFT 0x00000004
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_PACKETS_PER_LINE_MASK 0x001f0000L
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_PACKETS_PER_LINE__SHIFT 0x00000010
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_SEND_MAX_PACKETS_MASK 0x00000100L
+#define HDMI_AUDIO_PACKET_CONTROL__HDMI_AUDIO_SEND_MAX_PACKETS__SHIFT 0x00000008
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH_MASK 0x30000000L
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_DEPTH__SHIFT 0x0000001c
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE_MASK 0x01000000L
+#define HDMI_CONTROL__HDMI_DEEP_COLOR_ENABLE__SHIFT 0x00000018
+#define HDMI_CONTROL__HDMI_ERROR_ACK_MASK 0x00000100L
+#define HDMI_CONTROL__HDMI_ERROR_ACK__SHIFT 0x00000008
+#define HDMI_CONTROL__HDMI_ERROR_MASK_MASK 0x00000200L
+#define HDMI_CONTROL__HDMI_ERROR_MASK__SHIFT 0x00000009
+#define HDMI_CONTROL__HDMI_KEEPOUT_MODE_MASK 0x00000001L
+#define HDMI_CONTROL__HDMI_KEEPOUT_MODE__SHIFT 0x00000000
+#define HDMI_CONTROL__HDMI_PACKET_GEN_VERSION_MASK 0x00000010L
+#define HDMI_CONTROL__HDMI_PACKET_GEN_VERSION__SHIFT 0x00000004
+#define HDMI_GC__HDMI_DEFAULT_PHASE_MASK 0x00000010L
+#define HDMI_GC__HDMI_DEFAULT_PHASE__SHIFT 0x00000004
+#define HDMI_GC__HDMI_GC_AVMUTE_CONT_MASK 0x00000004L
+#define HDMI_GC__HDMI_GC_AVMUTE_CONT__SHIFT 0x00000002
+#define HDMI_GC__HDMI_GC_AVMUTE_MASK 0x00000001L
+#define HDMI_GC__HDMI_GC_AVMUTE__SHIFT 0x00000000
+#define HDMI_GC__HDMI_PACKING_PHASE_MASK 0x00000f00L
+#define HDMI_GC__HDMI_PACKING_PHASE_OVERRIDE_MASK 0x00001000L
+#define HDMI_GC__HDMI_PACKING_PHASE_OVERRIDE__SHIFT 0x0000000c
+#define HDMI_GC__HDMI_PACKING_PHASE__SHIFT 0x00000008
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT_MASK 0x00000002L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_CONT__SHIFT 0x00000001
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE_MASK 0x003f0000L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_LINE__SHIFT 0x00000010
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND_MASK 0x00000001L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC0_SEND__SHIFT 0x00000000
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT_MASK 0x00000020L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_CONT__SHIFT 0x00000005
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE_MASK 0x3f000000L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_LINE__SHIFT 0x00000018
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND_MASK 0x00000010L
+#define HDMI_GENERIC_PACKET_CONTROL0__HDMI_GENERIC1_SEND__SHIFT 0x00000004
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_CONT_MASK 0x00000002L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_CONT__SHIFT 0x00000001
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_LINE_MASK 0x003f0000L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_LINE__SHIFT 0x00000010
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_SEND_MASK 0x00000001L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC2_SEND__SHIFT 0x00000000
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_CONT_MASK 0x00000020L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_CONT__SHIFT 0x00000005
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_LINE_MASK 0x3f000000L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_LINE__SHIFT 0x00000018
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_SEND_MASK 0x00000010L
+#define HDMI_GENERIC_PACKET_CONTROL1__HDMI_GENERIC3_SEND__SHIFT 0x00000004
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_CONT_MASK 0x00000020L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_CONT__SHIFT 0x00000005
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_SEND_MASK 0x00000010L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AUDIO_INFO_SEND__SHIFT 0x00000004
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT_MASK 0x00000002L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_CONT__SHIFT 0x00000001
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND_MASK 0x00000001L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_AVI_INFO_SEND__SHIFT 0x00000000
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_CONT_MASK 0x00000200L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_CONT__SHIFT 0x00000009
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_SEND_MASK 0x00000100L
+#define HDMI_INFOFRAME_CONTROL0__HDMI_MPEG_INFO_SEND__SHIFT 0x00000008
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AUDIO_INFO_LINE_MASK 0x00003f00L
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AUDIO_INFO_LINE__SHIFT 0x00000008
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE_MASK 0x0000003fL
+#define HDMI_INFOFRAME_CONTROL1__HDMI_AVI_INFO_LINE__SHIFT 0x00000000
+#define HDMI_INFOFRAME_CONTROL1__HDMI_MPEG_INFO_LINE_MASK 0x003f0000L
+#define HDMI_INFOFRAME_CONTROL1__HDMI_MPEG_INFO_LINE__SHIFT 0x00000010
+#define HDMI_STATUS__HDMI_ACTIVE_AVMUTE_MASK 0x00000001L
+#define HDMI_STATUS__HDMI_ACTIVE_AVMUTE__SHIFT 0x00000000
+#define HDMI_STATUS__HDMI_AUDIO_PACKET_ERROR_MASK 0x00010000L
+#define HDMI_STATUS__HDMI_AUDIO_PACKET_ERROR__SHIFT 0x00000010
+#define HDMI_STATUS__HDMI_ERROR_INT_MASK 0x08000000L
+#define HDMI_STATUS__HDMI_ERROR_INT__SHIFT 0x0000001b
+#define HDMI_STATUS__HDMI_VBI_PACKET_ERROR_MASK 0x00100000L
+#define HDMI_STATUS__HDMI_VBI_PACKET_ERROR__SHIFT 0x00000014
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_CONT_MASK 0x00000020L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_CONT__SHIFT 0x00000005
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_SEND_MASK 0x00000010L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_GC_SEND__SHIFT 0x00000004
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_CONT_MASK 0x00000200L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_CONT__SHIFT 0x00000009
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_LINE_MASK 0x003f0000L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_LINE__SHIFT 0x00000010
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_SEND_MASK 0x00000100L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_ISRC_SEND__SHIFT 0x00000008
+#define HDMI_VBI_PACKET_CONTROL__HDMI_NULL_SEND_MASK 0x00000001L
+#define HDMI_VBI_PACKET_CONTROL__HDMI_NULL_SEND__SHIFT 0x00000000
+#define IDDCCIF02_DBG_DCCIF_C__DBG_DCCIF_C_MASK 0xffffffffL
+#define IDDCCIF02_DBG_DCCIF_C__DBG_DCCIF_C__SHIFT 0x00000000
+#define IDDCCIF04_DBG_DCCIF_E__DBG_DCCIF_E_MASK 0xffffffffL
+#define IDDCCIF04_DBG_DCCIF_E__DBG_DCCIF_E__SHIFT 0x00000000
+#define IDDCCIF05_DBG_DCCIF_F__DBG_DCCIF_F_MASK 0xffffffffL
+#define IDDCCIF05_DBG_DCCIF_F__DBG_DCCIF_F__SHIFT 0x00000000
+#define INPUT_CSC_C11_C12__INPUT_CSC_C11_MASK 0x0000ffffL
+#define INPUT_CSC_C11_C12__INPUT_CSC_C11__SHIFT 0x00000000
+#define INPUT_CSC_C11_C12__INPUT_CSC_C12_MASK 0xffff0000L
+#define INPUT_CSC_C11_C12__INPUT_CSC_C12__SHIFT 0x00000010
+#define INPUT_CSC_C13_C14__INPUT_CSC_C13_MASK 0x0000ffffL
+#define INPUT_CSC_C13_C14__INPUT_CSC_C13__SHIFT 0x00000000
+#define INPUT_CSC_C13_C14__INPUT_CSC_C14_MASK 0xffff0000L
+#define INPUT_CSC_C13_C14__INPUT_CSC_C14__SHIFT 0x00000010
+#define INPUT_CSC_C21_C22__INPUT_CSC_C21_MASK 0x0000ffffL
+#define INPUT_CSC_C21_C22__INPUT_CSC_C21__SHIFT 0x00000000
+#define INPUT_CSC_C21_C22__INPUT_CSC_C22_MASK 0xffff0000L
+#define INPUT_CSC_C21_C22__INPUT_CSC_C22__SHIFT 0x00000010
+#define INPUT_CSC_C23_C24__INPUT_CSC_C23_MASK 0x0000ffffL
+#define INPUT_CSC_C23_C24__INPUT_CSC_C23__SHIFT 0x00000000
+#define INPUT_CSC_C23_C24__INPUT_CSC_C24_MASK 0xffff0000L
+#define INPUT_CSC_C23_C24__INPUT_CSC_C24__SHIFT 0x00000010
+#define INPUT_CSC_C31_C32__INPUT_CSC_C31_MASK 0x0000ffffL
+#define INPUT_CSC_C31_C32__INPUT_CSC_C31__SHIFT 0x00000000
+#define INPUT_CSC_C31_C32__INPUT_CSC_C32_MASK 0xffff0000L
+#define INPUT_CSC_C31_C32__INPUT_CSC_C32__SHIFT 0x00000010
+#define INPUT_CSC_C33_C34__INPUT_CSC_C33_MASK 0x0000ffffL
+#define INPUT_CSC_C33_C34__INPUT_CSC_C33__SHIFT 0x00000000
+#define INPUT_CSC_C33_C34__INPUT_CSC_C34_MASK 0xffff0000L
+#define INPUT_CSC_C33_C34__INPUT_CSC_C34__SHIFT 0x00000010
+#define INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE_MASK 0x00000003L
+#define INPUT_CSC_CONTROL__INPUT_CSC_GRPH_MODE__SHIFT 0x00000000
+#define INPUT_CSC_CONTROL__INPUT_CSC_OVL_MODE_MASK 0x00000030L
+#define INPUT_CSC_CONTROL__INPUT_CSC_OVL_MODE__SHIFT 0x00000004
+#define INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE_MASK 0x00000003L
+#define INPUT_GAMMA_CONTROL__GRPH_INPUT_GAMMA_MODE__SHIFT 0x00000000
+#define INPUT_GAMMA_CONTROL__OVL_INPUT_GAMMA_MODE_MASK 0x00000030L
+#define INPUT_GAMMA_CONTROL__OVL_INPUT_GAMMA_MODE__SHIFT 0x00000004
+#define KEY_CONTROL__GRPH_OVL_HALF_BLEND_MASK 0x10000000L
+#define KEY_CONTROL__GRPH_OVL_HALF_BLEND__SHIFT 0x0000001c
+#define KEY_CONTROL__KEY_MODE_MASK 0x00000006L
+#define KEY_CONTROL__KEY_MODE__SHIFT 0x00000001
+#define KEY_CONTROL__KEY_SELECT_MASK 0x00000001L
+#define KEY_CONTROL__KEY_SELECT__SHIFT 0x00000000
+#define KEY_RANGE_ALPHA__KEY_ALPHA_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_ALPHA__KEY_ALPHA_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_ALPHA__KEY_ALPHA_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_ALPHA__KEY_ALPHA_LOW__SHIFT 0x00000000
+#define KEY_RANGE_BLUE__KEY_BLUE_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_BLUE__KEY_BLUE_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_BLUE__KEY_BLUE_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_BLUE__KEY_BLUE_LOW__SHIFT 0x00000000
+#define KEY_RANGE_GREEN__KEY_GREEN_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_GREEN__KEY_GREEN_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_GREEN__KEY_GREEN_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_GREEN__KEY_GREEN_LOW__SHIFT 0x00000000
+#define KEY_RANGE_RED__KEY_RED_HIGH_MASK 0xffff0000L
+#define KEY_RANGE_RED__KEY_RED_HIGH__SHIFT 0x00000010
+#define KEY_RANGE_RED__KEY_RED_LOW_MASK 0x0000ffffL
+#define KEY_RANGE_RED__KEY_RED_LOW__SHIFT 0x00000000
+#define LB_DEBUG2__LB_DEBUG2_MASK 0xffffffffL
+#define LB_DEBUG2__LB_DEBUG2__SHIFT 0x00000000
+#define LB_DEBUG__LB_DEBUG_MASK 0xffffffffL
+#define LB_DEBUG__LB_DEBUG__SHIFT 0x00000000
+#define LB_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT_MASK 0x00000001L
+#define LB_NO_OUTSTANDING_REQ_STATUS__LB_NO_OUTSTANDING_REQ_STAT__SHIFT 0x00000000
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2_MASK 0x00000010L
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL2__SHIFT 0x00000004
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL_MASK 0x00000003L
+#define LB_SYNC_RESET_SEL__LB_SYNC_RESET_SEL__SHIFT 0x00000000
+#define LB_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define LB_TEST_DEBUG_DATA__LB_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define LB_TEST_DEBUG_INDEX__LB_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define LIGHT_SLEEP_CNTL__LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define LIGHT_SLEEP_CNTL__LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define LIGHT_SLEEP_CNTL__MEM_SHUTDOWN_DIS_MASK 0x00000100L
+#define LIGHT_SLEEP_CNTL__MEM_SHUTDOWN_DIS__SHIFT 0x00000008
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ENABLE_MASK 0x00000001L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ENABLE__SHIFT 0x00000000
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_MODE_MASK 0x00000018L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_MODE__SHIFT 0x00000003
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_BANKS_MASK 0x00000700L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_BANKS__SHIFT 0x00000008
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_PIPES_MASK 0x000000e0L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_NUM_PIPES__SHIFT 0x00000005
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE_MASK 0x00000800L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_PIPE_INTERLEAVE_SIZE__SHIFT 0x0000000b
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROW_SIZE_MASK 0x00007000L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROW_SIZE__SHIFT 0x0000000c
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROWS_PER_CHAN_MASK 0x0fff0000L
+#define LOW_POWER_TILING_CONTROL__LOW_POWER_TILING_ROWS_PER_CHAN__SHIFT 0x00000010
+#define LVDS_DATA_CNTL__LVDS_24BIT_ENABLE_MASK 0x00000001L
+#define LVDS_DATA_CNTL__LVDS_24BIT_ENABLE__SHIFT 0x00000000
+#define LVDS_DATA_CNTL__LVDS_24BIT_FORMAT_MASK 0x00000010L
+#define LVDS_DATA_CNTL__LVDS_24BIT_FORMAT__SHIFT 0x00000004
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_DE_MASK 0x00000100L
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_DE__SHIFT 0x00000008
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_HS_MASK 0x00000400L
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_HS__SHIFT 0x0000000a
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_VS_MASK 0x00000200L
+#define LVDS_DATA_CNTL__LVDS_2ND_CHAN_VS__SHIFT 0x00000009
+#define LVDS_DATA_CNTL__LVDS_2ND_LINK_CNTL_BITS_MASK 0x00007000L
+#define LVDS_DATA_CNTL__LVDS_2ND_LINK_CNTL_BITS__SHIFT 0x0000000c
+#define LVDS_DATA_CNTL__LVDS_DTMG_POL_MASK 0x00040000L
+#define LVDS_DATA_CNTL__LVDS_DTMG_POL__SHIFT 0x00000012
+#define LVDS_DATA_CNTL__LVDS_FP_POL_MASK 0x00010000L
+#define LVDS_DATA_CNTL__LVDS_FP_POL__SHIFT 0x00000010
+#define LVDS_DATA_CNTL__LVDS_LP_POL_MASK 0x00020000L
+#define LVDS_DATA_CNTL__LVDS_LP_POL__SHIFT 0x00000011
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_MASK 0x01000000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_OVRD_MASK 0x02000000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_OVRD__SHIFT 0x00000019
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_POL_MASK 0x04000000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON_POL__SHIFT 0x0000001a
+#define LVTMA_PWRSEQ_CNTL__LVTMA_BLON__SHIFT 0x00000018
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_MASK 0x00010000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_OVRD_MASK 0x00020000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_OVRD__SHIFT 0x00000011
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_POL_MASK 0x00040000L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON_POL__SHIFT 0x00000012
+#define LVTMA_PWRSEQ_CNTL__LVTMA_DIGON__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN_MASK 0x00000002L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_DISABLE_SYNCEN_CONTROL_OF_TX_EN__SHIFT 0x00000001
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_EN_MASK 0x00000001L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_EN__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_TARGET_STATE_MASK 0x00000010L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_PWRSEQ_TARGET_STATE__SHIFT 0x00000004
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_MASK 0x00000100L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_OVRD_MASK 0x00000200L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_OVRD__SHIFT 0x00000009
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_POL_MASK 0x00000400L
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN_POL__SHIFT 0x0000000a
+#define LVTMA_PWRSEQ_CNTL__LVTMA_SYNCEN__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY1_MASK 0x00ff0000L
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY1__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY2_MASK 0xff000000L
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRDN_DELAY2__SHIFT 0x00000018
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY1_MASK 0x000000ffL
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY1__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY2_MASK 0x0000ff00L
+#define LVTMA_PWRSEQ_DELAY1__LVTMA_PWRUP_DELAY2__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_DELAY3_MASK 0x00ff0000L
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_DELAY3__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_MIN_LENGTH_MASK 0x000000ffL
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRDN_MIN_LENGTH__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRUP_DELAY3_MASK 0x0000ff00L
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_PWRUP_DELAY3__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_VARY_BL_OVERRIDE_EN_MASK 0x01000000L
+#define LVTMA_PWRSEQ_DELAY2__LVTMA_VARY_BL_OVERRIDE_EN__SHIFT 0x00000018
+#define LVTMA_PWRSEQ_REF_DIV__BL_PWM_REF_DIV_MASK 0xffff0000L
+#define LVTMA_PWRSEQ_REF_DIV__BL_PWM_REF_DIV__SHIFT 0x00000010
+#define LVTMA_PWRSEQ_REF_DIV__LVTMA_PWRSEQ_REF_DIV_MASK 0x00000fffL
+#define LVTMA_PWRSEQ_REF_DIV__LVTMA_PWRSEQ_REF_DIV__SHIFT 0x00000000
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_BLON_MASK 0x00000008L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_BLON__SHIFT 0x00000003
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DIGON_MASK 0x00000002L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DIGON__SHIFT 0x00000001
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DONE_MASK 0x00000010L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_DONE__SHIFT 0x00000004
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_STATE_MASK 0x00000f00L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_STATE__SHIFT 0x00000008
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_SYNCEN_MASK 0x00000004L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_SYNCEN__SHIFT 0x00000002
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_TARGET_STATE_R_MASK 0x00000001L
+#define LVTMA_PWRSEQ_STATE__LVTMA_PWRSEQ_TARGET_STATE_R__SHIFT 0x00000000
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_CMD_REG__MASTER_COMM_CMD_REG_BYTE3__SHIFT 0x00000018
+#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT_MASK 0x00000001L
+#define MASTER_COMM_CNTL_REG__MASTER_COMM_INTERRUPT__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_DATA_REG1__MASTER_COMM_DATA_REG1_BYTE3__SHIFT 0x00000018
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_DATA_REG2__MASTER_COMM_DATA_REG2_BYTE3__SHIFT 0x00000018
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE0_MASK 0x000000ffL
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE0__SHIFT 0x00000000
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE1_MASK 0x0000ff00L
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE1__SHIFT 0x00000008
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE2_MASK 0x00ff0000L
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE2__SHIFT 0x00000010
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE3_MASK 0xff000000L
+#define MASTER_COMM_DATA_REG3__MASTER_COMM_DATA_REG3_BYTE3__SHIFT 0x00000018
+#define MASTER_UPDATE_LOCK__GSL_CONTROL_MASTER_UPDATE_LOCK_MASK 0x00000100L
+#define MASTER_UPDATE_LOCK__GSL_CONTROL_MASTER_UPDATE_LOCK__SHIFT 0x00000008
+#define MASTER_UPDATE_LOCK__MASTER_UPDATE_LOCK_MASK 0x00000001L
+#define MASTER_UPDATE_LOCK__MASTER_UPDATE_LOCK__SHIFT 0x00000000
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_INTERLACED_MODE_MASK 0x00030000L
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_INTERLACED_MODE__SHIFT 0x00000010
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_MODE_MASK 0x00000007L
+#define MASTER_UPDATE_MODE__MASTER_UPDATE_MODE__SHIFT 0x00000000
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_CLEAR_MASK 0x00000010L
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_CLEAR__SHIFT 0x00000004
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_OCCURRED_MASK 0x00000001L
+#define MC_DC_INTERFACE_NACK_STATUS__DMIF_RDRET_NACK_OCCURRED__SHIFT 0x00000000
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_CLEAR_MASK 0x00100000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_CLEAR__SHIFT 0x00000014
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_OCCURRED_MASK 0x00010000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_RDRET_NACK_OCCURRED__SHIFT 0x00000010
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_CLEAR_MASK 0x10000000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_CLEAR__SHIFT 0x0000001c
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_OCCURRED_MASK 0x01000000L
+#define MC_DC_INTERFACE_NACK_STATUS__MCIF_WRRET_NACK_OCCURRED__SHIFT 0x00000018
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_CLEAR_MASK 0x00001000L
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_CLEAR__SHIFT 0x0000000c
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_OCCURRED_MASK 0x00000100L
+#define MC_DC_INTERFACE_NACK_STATUS__VIP_WRRET_NACK_OCCURRED__SHIFT 0x00000008
+#define MCIF_CONTROL__ADDRESS_TRANSLATION_ENABLE_MASK 0x00000010L
+#define MCIF_CONTROL__ADDRESS_TRANSLATION_ENABLE__SHIFT 0x00000004
+#define MCIF_CONTROL__LOW_READ_URG_LEVEL_MASK 0x00ff0000L
+#define MCIF_CONTROL__LOW_READ_URG_LEVEL__SHIFT 0x00000010
+#define MCIF_CONTROL__MC_CLEAN_DEASSERT_LATENCY_MASK 0x3f000000L
+#define MCIF_CONTROL__MC_CLEAN_DEASSERT_LATENCY__SHIFT 0x00000018
+#define MCIF_CONTROL__MCIF_BUFF_SIZE_MASK 0x00000003L
+#define MCIF_CONTROL__MCIF_BUFF_SIZE__SHIFT 0x00000000
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_ENABLE_MASK 0x40000000L
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_ENABLE__SHIFT 0x0000001e
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_URGENT_ONLY_MASK 0x80000000L
+#define MCIF_CONTROL__MCIF_MC_LATENCY_COUNTER_URGENT_ONLY__SHIFT 0x0000001f
+#define MCIF_CONTROL__MCIF_SLOW_REQ_INTERVAL_MASK 0x0000f000L
+#define MCIF_CONTROL__MCIF_SLOW_REQ_INTERVAL__SHIFT 0x0000000c
+#define MCIF_CONTROL__PRIVILEGED_ACCESS_ENABLE_MASK 0x00000100L
+#define MCIF_CONTROL__PRIVILEGED_ACCESS_ENABLE__SHIFT 0x00000008
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_DIS_MASK 0x00000001L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_DIS__SHIFT 0x00000000
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE_MASK 0x00000030L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_MODE__SHIFT 0x00000004
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_PIPE_MASK 0x00070000L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_PIPE__SHIFT 0x00000010
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_SIZE_MASK 0x00007f00L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_SIZE__SHIFT 0x00000008
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_TYPE_MASK 0x00180000L
+#define MCIF_MEM_CONTROL__MCIFMEM_CACHE_TYPE__SHIFT 0x00000013
+#define MCIF_TEST_DEBUG_DATA__MCIF_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define MCIF_TEST_DEBUG_DATA__MCIF_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define MCIF_TEST_DEBUG_INDEX__MCIF_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define MCIF_VMID__MCIF_WR_VMID_MASK 0x0000000fL
+#define MCIF_VMID__MCIF_WR_VMID__SHIFT 0x00000000
+#define MCIF_VMID__VIP_WR_VMID_MASK 0x000000f0L
+#define MCIF_VMID__VIP_WR_VMID__SHIFT 0x00000004
+#define MCIF_WRITE_COMBINE_CONTROL__MCIF_WRITE_COMBINE_TIMEOUT_MASK 0x000000ffL
+#define MCIF_WRITE_COMBINE_CONTROL__MCIF_WRITE_COMBINE_TIMEOUT__SHIFT 0x00000000
+#define MCIF_WRITE_COMBINE_CONTROL__VIP_WRITE_COMBINE_TIMEOUT_MASK 0x0000ff00L
+#define MCIF_WRITE_COMBINE_CONTROL__VIP_WRITE_COMBINE_TIMEOUT__SHIFT 0x00000008
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL_MASK 0x00100000L
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_CLOCK_SOURCE_SEL__SHIFT 0x00000014
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_DIV_MASK 0x0000007fL
+#define MICROSECOND_TIME_BASE_DIV__MICROSECOND_TIME_BASE_DIV__SHIFT 0x00000000
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_CLOCK_SOURCE_SEL_MASK 0x00020000L
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_CLOCK_SOURCE_SEL__SHIFT 0x00000011
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_DIV_MASK 0x00007f00L
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_DIV__SHIFT 0x00000008
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_SEL_MASK 0x00010000L
+#define MICROSECOND_TIME_BASE_DIV__XTAL_REF_SEL__SHIFT 0x00000010
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL_MASK 0x00100000L
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_CLOCK_SOURCE_SEL__SHIFT 0x00000014
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_DIV_MASK 0x0001ffffL
+#define MILLISECOND_TIME_BASE_DIV__MILLISECOND_TIME_BASE_DIV__SHIFT 0x00000000
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_NUM_ENTRIES_MASK 0x0000000fL
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_NUM_ENTRIES__SHIFT 0x00000000
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_ACK_MASK 0x00001000L
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_ACK__SHIFT 0x0000000c
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_FLAG_MASK 0x00000100L
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_FLAG__SHIFT 0x00000008
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET_MASK 0x00000010L
+#define MVP_AFR_FLIP_FIFO_CNTL__MVP_AFR_FLIP_FIFO_RESET__SHIFT 0x00000004
+#define MVP_AFR_FLIP_MODE__MVP_AFR_FLIP_MODE_MASK 0x00000003L
+#define MVP_AFR_FLIP_MODE__MVP_AFR_FLIP_MODE__SHIFT 0x00000000
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_B_MASK 0x3ff00000L
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_B__SHIFT 0x00000014
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_G_MASK 0x000ffc00L
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_G__SHIFT 0x0000000a
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_R_MASK 0x000003ffL
+#define MVP_BLACK_KEYER__MVP_BLACK_KEYER_R__SHIFT 0x00000000
+#define MVP_CONTROL1__MVP_30BPP_EN_MASK 0x10000000L
+#define MVP_CONTROL1__MVP_30BPP_EN__SHIFT 0x0000001c
+#define MVP_CONTROL1__MVP_ARBITRATION_MODE_FOR_AFR_MANUAL_SWITCH_MODE_MASK 0x00000400L
+#define MVP_CONTROL1__MVP_ARBITRATION_MODE_FOR_AFR_MANUAL_SWITCH_MODE__SHIFT 0x0000000a
+#define MVP_CONTROL1__MVP_CHANNEL_CONTROL_MASK 0x00010000L
+#define MVP_CONTROL1__MVP_CHANNEL_CONTROL__SHIFT 0x00000010
+#define MVP_CONTROL1__MVP_DISABLE_MSB_EXPAND_MASK 0x01000000L
+#define MVP_CONTROL1__MVP_DISABLE_MSB_EXPAND__SHIFT 0x00000018
+#define MVP_CONTROL1__MVP_EN_MASK 0x00000001L
+#define MVP_CONTROL1__MVP_EN__SHIFT 0x00000000
+#define MVP_CONTROL1__MVP_GPU_CHAIN_LOCATION_MASK 0x00300000L
+#define MVP_CONTROL1__MVP_GPU_CHAIN_LOCATION__SHIFT 0x00000014
+#define MVP_CONTROL1__MVP_MIXER_MODE_MASK 0x00000070L
+#define MVP_CONTROL1__MVP_MIXER_MODE__SHIFT 0x00000004
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_DELAY_UNTIL_END_OF_BLANK_MASK 0x00000200L
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_DELAY_UNTIL_END_OF_BLANK__SHIFT 0x00000009
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL_MASK 0x00000100L
+#define MVP_CONTROL1__MVP_MIXER_SLAVE_SEL__SHIFT 0x00000008
+#define MVP_CONTROL1__MVP_RATE_CONTROL_MASK 0x00001000L
+#define MVP_CONTROL1__MVP_RATE_CONTROL__SHIFT 0x0000000c
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_A_MASK 0x40000000L
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_A__SHIFT 0x0000001e
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_B_MASK 0x80000000L
+#define MVP_CONTROL1__MVP_TERMINATION_CNTL_B__SHIFT 0x0000001f
+#define MVP_CONTROL2__MVP_DVOCNTL_MUX_MASK 0x00010000L
+#define MVP_CONTROL2__MVP_DVOCNTL_MUX__SHIFT 0x00000010
+#define MVP_CONTROL2__MVP_FLOW_CONTROL_OUT_EN_MASK 0x00100000L
+#define MVP_CONTROL2__MVP_FLOW_CONTROL_OUT_EN__SHIFT 0x00000014
+#define MVP_CONTROL2__MVP_MUXA_CLK_SEL_MASK 0x00000100L
+#define MVP_CONTROL2__MVP_MUXA_CLK_SEL__SHIFT 0x00000008
+#define MVP_CONTROL2__MVP_MUXB_CLK_SEL_MASK 0x00001000L
+#define MVP_CONTROL2__MVP_MUXB_CLK_SEL__SHIFT 0x0000000c
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL0_SEL_MASK 0x00000001L
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL0_SEL__SHIFT 0x00000000
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL2_SEL_MASK 0x00000010L
+#define MVP_CONTROL2__MVP_MUX_DE_DVOCNTL2_SEL__SHIFT 0x00000004
+#define MVP_CONTROL2__MVP_SWAP_AB_IN_DC_DDR_MASK 0x10000000L
+#define MVP_CONTROL2__MVP_SWAP_AB_IN_DC_DDR__SHIFT 0x0000001c
+#define MVP_CONTROL2__MVP_SWAP_LOCK_OUT_EN_MASK 0x01000000L
+#define MVP_CONTROL2__MVP_SWAP_LOCK_OUT_EN__SHIFT 0x00000018
+#define MVP_CONTROL3__MVP_DDR_SC_AB_SEL_MASK 0x00000010L
+#define MVP_CONTROL3__MVP_DDR_SC_AB_SEL__SHIFT 0x00000004
+#define MVP_CONTROL3__MVP_DDR_SC_B_START_MODE_MASK 0x00000100L
+#define MVP_CONTROL3__MVP_DDR_SC_B_START_MODE__SHIFT 0x00000008
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_CASCADE_EN_MASK 0x00100000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_CASCADE_EN__SHIFT 0x00000014
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_IN_CAP_MASK 0x10000000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_IN_CAP__SHIFT 0x0000001c
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ONE_MASK 0x00001000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ONE__SHIFT 0x0000000c
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ZERO_MASK 0x00010000L
+#define MVP_CONTROL3__MVP_FLOW_CONTROL_OUT_FORCE_ZERO__SHIFT 0x00000010
+#define MVP_CONTROL3__MVP_RESET_IN_BETWEEN_FRAMES_MASK 0x00000001L
+#define MVP_CONTROL3__MVP_RESET_IN_BETWEEN_FRAMES__SHIFT 0x00000000
+#define MVP_CONTROL3__MVP_SWAP_48BIT_EN_MASK 0x01000000L
+#define MVP_CONTROL3__MVP_SWAP_48BIT_EN__SHIFT 0x00000018
+#define MVP_CRC_CNTL__MVP_CRC_BLUE_MASK_MASK 0x000000ffL
+#define MVP_CRC_CNTL__MVP_CRC_BLUE_MASK__SHIFT 0x00000000
+#define MVP_CRC_CNTL__MVP_CRC_CONT_EN_MASK 0x20000000L
+#define MVP_CRC_CNTL__MVP_CRC_CONT_EN__SHIFT 0x0000001d
+#define MVP_CRC_CNTL__MVP_CRC_EN_MASK 0x10000000L
+#define MVP_CRC_CNTL__MVP_CRC_EN__SHIFT 0x0000001c
+#define MVP_CRC_CNTL__MVP_CRC_GREEN_MASK_MASK 0x0000ff00L
+#define MVP_CRC_CNTL__MVP_CRC_GREEN_MASK__SHIFT 0x00000008
+#define MVP_CRC_CNTL__MVP_CRC_RED_MASK_MASK 0x00ff0000L
+#define MVP_CRC_CNTL__MVP_CRC_RED_MASK__SHIFT 0x00000010
+#define MVP_CRC_CNTL__MVP_DC_DDR_CRC_EVEN_ODD_PIX_SEL_MASK 0x40000000L
+#define MVP_CRC_CNTL__MVP_DC_DDR_CRC_EVEN_ODD_PIX_SEL__SHIFT 0x0000001e
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_BLUE_RESULT_MASK 0x0000ffffL
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_BLUE_RESULT__SHIFT 0x00000000
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_GREEN_RESULT_MASK 0xffff0000L
+#define MVP_CRC_RESULT_BLUE_GREEN__MVP_CRC_GREEN_RESULT__SHIFT 0x00000010
+#define MVP_CRC_RESULT_RED__MVP_CRC_RED_RESULT_MASK 0x0000ffffL
+#define MVP_CRC_RESULT_RED__MVP_CRC_RED_RESULT__SHIFT 0x00000000
+#define MVP_DEBUG_05__IDE0_MVP_GPU_CHAIN_LOCATION_MASK 0x00000006L
+#define MVP_DEBUG_05__IDE0_MVP_GPU_CHAIN_LOCATION__SHIFT 0x00000001
+#define MVP_DEBUG_09__IDE4_CRTC2_MVP_GPU_CHAIN_LOCATION_MASK 0x00000006L
+#define MVP_DEBUG_09__IDE4_CRTC2_MVP_GPU_CHAIN_LOCATION__SHIFT 0x00000001
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_H_MASK 0x00000001L
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_H__SHIFT 0x00000000
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A_MASK 0x01fffffeL
+#define MVP_DEBUG_12__IDEC_MVP_DATA_A__SHIFT 0x00000001
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_H_MASK 0x00000001L
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_H__SHIFT 0x00000000
+#define MVP_DEBUG_13__IDED_MVP_DATA_B_MASK 0x01fffffeL
+#define MVP_DEBUG_13__IDED_MVP_DATA_B__SHIFT 0x00000001
+#define MVP_DEBUG_13__IDED_READ_FIFO_ENTRY_DE_B_MASK 0x04000000L
+#define MVP_DEBUG_13__IDED_READ_FIFO_ENTRY_DE_B__SHIFT 0x0000001a
+#define MVP_DEBUG_13__IDED_START_READ_B_MASK 0x02000000L
+#define MVP_DEBUG_13__IDED_START_READ_B__SHIFT 0x00000019
+#define MVP_DEBUG_13__IDED_WRITE_ADD_B_MASK 0x38000000L
+#define MVP_DEBUG_13__IDED_WRITE_ADD_B__SHIFT 0x0000001b
+#define MVP_DEBUG_14__IDEE_CRC_PHASE_MASK 0x00100000L
+#define MVP_DEBUG_14__IDEE_CRC_PHASE__SHIFT 0x00000014
+#define MVP_DEBUG_14__IDEE_CRTC1_CNTL_CAPTURE_START_A_MASK 0x00080000L
+#define MVP_DEBUG_14__IDEE_CRTC1_CNTL_CAPTURE_START_A__SHIFT 0x00000013
+#define MVP_DEBUG_14__IDEE_READ_ADD_MASK 0x00000007L
+#define MVP_DEBUG_14__IDEE_READ_ADD__SHIFT 0x00000000
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_B_MASK 0x00020000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_B__SHIFT 0x00000011
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE_MASK 0x00010000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_DE__SHIFT 0x00000010
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENABLE_MASK 0x00040000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENABLE__SHIFT 0x00000012
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_B_MASK 0x00008000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_B__SHIFT 0x0000000f
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE_MASK 0x00004000L
+#define MVP_DEBUG_14__IDEE_READ_FIFO_ENTRY_DE__SHIFT 0x0000000e
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_A_MASK 0x00000800L
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_A__SHIFT 0x0000000b
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_B_MASK 0x00001000L
+#define MVP_DEBUG_14__IDEE_START_INCR_WR_B__SHIFT 0x0000000c
+#define MVP_DEBUG_14__IDEE_START_READ_B_MASK 0x00000400L
+#define MVP_DEBUG_14__IDEE_START_READ_B__SHIFT 0x0000000a
+#define MVP_DEBUG_14__IDEE_START_READ_MASK 0x00000200L
+#define MVP_DEBUG_14__IDEE_START_READ__SHIFT 0x00000009
+#define MVP_DEBUG_14__IDEE_WRITE2FIFO_MASK 0x00002000L
+#define MVP_DEBUG_14__IDEE_WRITE2FIFO__SHIFT 0x0000000d
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_A_MASK 0x00000038L
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_A__SHIFT 0x00000003
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_B_MASK 0x000001c0L
+#define MVP_DEBUG_14__IDEE_WRITE_ADD_B__SHIFT 0x00000006
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WDATA_MASK 0xfffffff0L
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WDATA__SHIFT 0x00000004
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WEN_MASK 0x00000001L
+#define MVP_DEBUG_15__IDEF_MVP_ASYNC_FIFO_WEN__SHIFT 0x00000000
+#define MVP_DEBUG_16__IDCC_FLOW_CONTROL_OUT_MASK 0x00000008L
+#define MVP_DEBUG_16__IDCC_FLOW_CONTROL_OUT__SHIFT 0x00000003
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_PAUSE_LEVEL_MASK 0x00000004L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_PAUSE_LEVEL__SHIFT 0x00000002
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_STOP_LEVEL_MASK 0x00000002L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_EXCEED_STOP_LEVEL__SHIFT 0x00000001
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_NUM_ENTRIES_MASK 0x00000ff0L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_NUM_ENTRIES__SHIFT 0x00000004
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_OVERFLOW_MASK 0x00001000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_OVERFLOW__SHIFT 0x0000000c
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_READ_MASK 0x00000001L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_READ__SHIFT 0x00000000
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_UNDERFLOW_MASK 0x00002000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_FIFO_UNDERFLOW__SHIFT 0x0000000d
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_READ_ADDR_MASK 0x00ff0000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_READ_ADDR__SHIFT 0x00000010
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_WRITE_ADDR_MASK 0xff000000L
+#define MVP_DEBUG_16__IDCC_MVP_ASYNC_WRITE_ADDR__SHIFT 0x00000018
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_PHASE_MASK 0x00000002L
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_PHASE__SHIFT 0x00000001
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_DATA_MASK 0xfffffffcL
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_DATA__SHIFT 0x00000002
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ_MASK 0x00000001L
+#define MVP_DEBUG_17__IDCD_MVP_ASYNC_FIFO_READ__SHIFT 0x00000000
+#define MVP_DEBUG__MVP_DEBUG_BITS_MASK 0xffffff00L
+#define MVP_DEBUG__MVP_DEBUG_BITS__SHIFT 0x00000008
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_AUTO_VSYNC_FLIP_MASK 0x00000020L
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_AUTO_VSYNC_FLIP__SHIFT 0x00000005
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_MANUAL_HSYNC_FLIP_MASK 0x00000010L
+#define MVP_DEBUG__MVP_DIS_FIX_AFR_MANUAL_HSYNC_FLIP__SHIFT 0x00000004
+#define MVP_DEBUG__MVP_DIS_READ_POINTER_RESET_DELAY_MASK 0x00000080L
+#define MVP_DEBUG__MVP_DIS_READ_POINTER_RESET_DELAY__SHIFT 0x00000007
+#define MVP_DEBUG__MVP_EN_FIX_AFR_MANUAL_SWITCH_IN_SFR_MASK 0x00000040L
+#define MVP_DEBUG__MVP_EN_FIX_AFR_MANUAL_SWITCH_IN_SFR__SHIFT 0x00000006
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_EN_MASK 0x00000002L
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_EN__SHIFT 0x00000001
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_SEL_MASK 0x00000008L
+#define MVP_DEBUG__MVP_FLOW_CONTROL_IN_SEL__SHIFT 0x00000003
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_EN_MASK 0x00000001L
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_EN__SHIFT 0x00000000
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_SEL_MASK 0x00000004L
+#define MVP_DEBUG__MVP_SWAP_LOCK_IN_SEL__SHIFT 0x00000002
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_CNT_MASK 0x00ff0000L
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_CNT__SHIFT 0x00000010
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_WM_MASK 0x0000ff00L
+#define MVP_FIFO_CONTROL__MVP_PAUSE_SLAVE_WM__SHIFT 0x00000008
+#define MVP_FIFO_CONTROL__MVP_STOP_SLAVE_WM_MASK 0x000000ffL
+#define MVP_FIFO_CONTROL__MVP_STOP_SLAVE_WM__SHIFT 0x00000000
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_INT_STATUS_MASK 0x80000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_INT_STATUS__SHIFT 0x0000001f
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_MASK_MASK 0x40000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_ERROR_MASK__SHIFT 0x0000001e
+#define MVP_FIFO_STATUS__MVP_FIFO_LEVEL_MASK 0x000000ffL
+#define MVP_FIFO_STATUS__MVP_FIFO_LEVEL__SHIFT 0x00000000
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_ACK_MASK 0x00010000L
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_ACK__SHIFT 0x00000010
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_MASK 0x00000100L
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_OCCURRED_MASK 0x00001000L
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW_OCCURRED__SHIFT 0x0000000c
+#define MVP_FIFO_STATUS__MVP_FIFO_OVERFLOW__SHIFT 0x00000008
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_ACK_MASK 0x10000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_ACK__SHIFT 0x0000001c
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_MASK 0x00100000L
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_OCCURRED_MASK 0x01000000L
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW_OCCURRED__SHIFT 0x00000018
+#define MVP_FIFO_STATUS__MVP_FIFO_UNDERFLOW__SHIFT 0x00000014
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_AUTO_ENABLE_MASK 0x40000000L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_AUTO_ENABLE__SHIFT 0x0000001e
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MASK 0x007fff00L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MODE_MASK 0x00000003L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT_MODE__SHIFT 0x00000000
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_INSERT__SHIFT 0x00000008
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_OFFSET_MASK 0x3f000000L
+#define MVP_FLIP_LINE_NUM_INSERT__MVP_FLIP_LINE_NUM_OFFSET__SHIFT 0x00000018
+#define MVP_INBAND_CNTL_CAP__MVP_IGNOR_INBAND_CNTL_MASK 0x00000001L
+#define MVP_INBAND_CNTL_CAP__MVP_IGNOR_INBAND_CNTL__SHIFT 0x00000000
+#define MVP_INBAND_CNTL_CAP__MVP_INBAND_CNTL_CHAR_CAP_MASK 0xffffff00L
+#define MVP_INBAND_CNTL_CAP__MVP_INBAND_CNTL_CHAR_CAP__SHIFT 0x00000008
+#define MVP_INBAND_CNTL_CAP__MVP_PASSING_INBAND_CNTL_EN_MASK 0x00000010L
+#define MVP_INBAND_CNTL_CAP__MVP_PASSING_INBAND_CNTL_EN__SHIFT 0x00000004
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_DATA_CHK_EN_MASK 0x80000000L
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_DATA_CHK_EN__SHIFT 0x0000001f
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_LINE_ERROR_CNT_MASK 0x1fff0000L
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_LINE_ERROR_CNT__SHIFT 0x00000010
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_PIXEL_ERROR_CNT_MASK 0x00001fffL
+#define MVP_RECEIVE_CNT_CNTL1__MVP_SLAVE_PIXEL_ERROR_CNT__SHIFT 0x00000000
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_MASK 0x00001fffL
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_RESET_MASK 0x80000000L
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT_RESET__SHIFT 0x0000001f
+#define MVP_RECEIVE_CNT_CNTL2__MVP_SLAVE_FRAME_ERROR_CNT__SHIFT 0x00000000
+#define MVP_SLAVE_STATUS__MVP_SLAVE_LINES_PER_FRAME_RCVED_MASK 0x1fff0000L
+#define MVP_SLAVE_STATUS__MVP_SLAVE_LINES_PER_FRAME_RCVED__SHIFT 0x00000010
+#define MVP_SLAVE_STATUS__MVP_SLAVE_PIXELS_PER_LINE_RCVED_MASK 0x00001fffL
+#define MVP_SLAVE_STATUS__MVP_SLAVE_PIXELS_PER_LINE_RCVED__SHIFT 0x00000000
+#define MVP_TEST_DEBUG_DATA__MVP_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define MVP_TEST_DEBUG_DATA__MVP_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define MVP_TEST_DEBUG_INDEX__MVP_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C11_MASK 0x0000ffffL
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C11__SHIFT 0x00000000
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C12_MASK 0xffff0000L
+#define OUTPUT_CSC_C11_C12__OUTPUT_CSC_C12__SHIFT 0x00000010
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C13_MASK 0x0000ffffL
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C13__SHIFT 0x00000000
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C14_MASK 0xffff0000L
+#define OUTPUT_CSC_C13_C14__OUTPUT_CSC_C14__SHIFT 0x00000010
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C21_MASK 0x0000ffffL
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C21__SHIFT 0x00000000
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C22_MASK 0xffff0000L
+#define OUTPUT_CSC_C21_C22__OUTPUT_CSC_C22__SHIFT 0x00000010
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C23_MASK 0x0000ffffL
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C23__SHIFT 0x00000000
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C24_MASK 0xffff0000L
+#define OUTPUT_CSC_C23_C24__OUTPUT_CSC_C24__SHIFT 0x00000010
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C31_MASK 0x0000ffffL
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C31__SHIFT 0x00000000
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C32_MASK 0xffff0000L
+#define OUTPUT_CSC_C31_C32__OUTPUT_CSC_C32__SHIFT 0x00000010
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C33_MASK 0x0000ffffL
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C33__SHIFT 0x00000000
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C34_MASK 0xffff0000L
+#define OUTPUT_CSC_C33_C34__OUTPUT_CSC_C34__SHIFT 0x00000010
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE_MASK 0x00000007L
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_GRPH_MODE__SHIFT 0x00000000
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_OVL_MODE_MASK 0x00000070L
+#define OUTPUT_CSC_CONTROL__OUTPUT_CSC_OVL_MODE__SHIFT 0x00000004
+#define OUT_ROUND_CONTROL__OUT_ROUND_TRUNC_MODE_MASK 0x0000000fL
+#define OUT_ROUND_CONTROL__OUT_ROUND_TRUNC_MODE__SHIFT 0x00000000
+#define OVL_CONTROL1__OVL_ADDRESS_TRANSLATION_ENABLE_MASK 0x00010000L
+#define OVL_CONTROL1__OVL_ADDRESS_TRANSLATION_ENABLE__SHIFT 0x00000010
+#define OVL_CONTROL1__OVL_ARRAY_MODE_MASK 0x00f00000L
+#define OVL_CONTROL1__OVL_ARRAY_MODE__SHIFT 0x00000014
+#define OVL_CONTROL1__OVL_BANK_HEIGHT_MASK 0x00001800L
+#define OVL_CONTROL1__OVL_BANK_HEIGHT__SHIFT 0x0000000b
+#define OVL_CONTROL1__OVL_BANK_WIDTH_MASK 0x000000c0L
+#define OVL_CONTROL1__OVL_BANK_WIDTH__SHIFT 0x00000006
+#define OVL_CONTROL1__OVL_COLOR_EXPANSION_MODE_MASK 0x01000000L
+#define OVL_CONTROL1__OVL_COLOR_EXPANSION_MODE__SHIFT 0x00000018
+#define OVL_CONTROL1__OVL_DEPTH_MASK 0x00000003L
+#define OVL_CONTROL1__OVL_DEPTH__SHIFT 0x00000000
+#define OVL_CONTROL1__OVL_FORMAT_MASK 0x00000700L
+#define OVL_CONTROL1__OVL_FORMAT__SHIFT 0x00000008
+#define OVL_CONTROL1__OVL_MACRO_TILE_ASPECT_MASK 0x000c0000L
+#define OVL_CONTROL1__OVL_MACRO_TILE_ASPECT__SHIFT 0x00000012
+#define OVL_CONTROL1__OVL_NUM_BANKS_MASK 0x0000000cL
+#define OVL_CONTROL1__OVL_NUM_BANKS__SHIFT 0x00000002
+#define OVL_CONTROL1__OVL_PIPE_CONFIG_MASK 0x3e000000L
+#define OVL_CONTROL1__OVL_PIPE_CONFIG__SHIFT 0x00000019
+#define OVL_CONTROL1__OVL_PRIVILEGED_ACCESS_ENABLE_MASK 0x00020000L
+#define OVL_CONTROL1__OVL_PRIVILEGED_ACCESS_ENABLE__SHIFT 0x00000011
+#define OVL_CONTROL1__OVL_TILE_SPLIT_MASK 0x0000e000L
+#define OVL_CONTROL1__OVL_TILE_SPLIT__SHIFT 0x0000000d
+#define OVL_CONTROL1__OVL_Z_MASK 0x00000030L
+#define OVL_CONTROL1__OVL_Z__SHIFT 0x00000004
+#define OVL_CONTROL2__OVL_HALF_RESOLUTION_ENABLE_MASK 0x00000001L
+#define OVL_CONTROL2__OVL_HALF_RESOLUTION_ENABLE__SHIFT 0x00000000
+#define OVL_DFQ_CONTROL__OVL_DFQ_MIN_FREE_ENTRIES_MASK 0x00000700L
+#define OVL_DFQ_CONTROL__OVL_DFQ_MIN_FREE_ENTRIES__SHIFT 0x00000008
+#define OVL_DFQ_CONTROL__OVL_DFQ_RESET_MASK 0x00000001L
+#define OVL_DFQ_CONTROL__OVL_DFQ_RESET__SHIFT 0x00000000
+#define OVL_DFQ_CONTROL__OVL_DFQ_SIZE_MASK 0x00000070L
+#define OVL_DFQ_CONTROL__OVL_DFQ_SIZE__SHIFT 0x00000004
+#define OVL_DFQ_STATUS__OVL_DFQ_NUM_ENTRIES_MASK 0x0000000fL
+#define OVL_DFQ_STATUS__OVL_DFQ_NUM_ENTRIES__SHIFT 0x00000000
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_ACK_MASK 0x00000200L
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_ACK__SHIFT 0x00000009
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_FLAG_MASK 0x00000100L
+#define OVL_DFQ_STATUS__OVL_DFQ_RESET_FLAG__SHIFT 0x00000008
+#define OVL_DFQ_STATUS__OVL_SECONDARY_DFQ_NUM_ENTRIES_MASK 0x000000f0L
+#define OVL_DFQ_STATUS__OVL_SECONDARY_DFQ_NUM_ENTRIES__SHIFT 0x00000004
+#define OVL_ENABLE__OVL_ENABLE_MASK 0x00000001L
+#define OVL_ENABLE__OVL_ENABLE__SHIFT 0x00000000
+#define OVL_ENABLE__OVLSCL_EN_MASK 0x00000100L
+#define OVL_ENABLE__OVLSCL_EN__SHIFT 0x00000008
+#define OVL_END__OVL_X_END_MASK 0x7fff0000L
+#define OVL_END__OVL_X_END__SHIFT 0x00000010
+#define OVL_END__OVL_Y_END_MASK 0x00007fffL
+#define OVL_END__OVL_Y_END__SHIFT 0x00000000
+#define OVL_PITCH__OVL_PITCH_MASK 0x00007fffL
+#define OVL_PITCH__OVL_PITCH__SHIFT 0x00000000
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_BCB_MASK 0x000003ffL
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_BCB__SHIFT 0x00000000
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_GY_MASK 0x000ffc00L
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_GY__SHIFT 0x0000000a
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_RCR_MASK 0x3ff00000L
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_BLACK_COLOR_RCR__SHIFT 0x00000014
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_EDGE_PIXEL_SEL_MASK 0x80000000L
+#define OVLSCL_EDGE_PIXEL_CNTL__OVLSCL_EDGE_PIXEL_SEL__SHIFT 0x0000001f
+#define OVL_SECONDARY_SURFACE_ADDRESS_HIGH__OVL_SECONDARY_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define OVL_SECONDARY_SURFACE_ADDRESS_HIGH__OVL_SECONDARY_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_DFQ_ENABLE_MASK 0x00000001L
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_DFQ_ENABLE__SHIFT 0x00000000
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_SURFACE_ADDRESS_MASK 0xffffff00L
+#define OVL_SECONDARY_SURFACE_ADDRESS__OVL_SECONDARY_SURFACE_ADDRESS__SHIFT 0x00000008
+#define OVL_START__OVL_X_START_MASK 0x3fff0000L
+#define OVL_START__OVL_X_START__SHIFT 0x00000010
+#define OVL_START__OVL_Y_START_MASK 0x00003fffL
+#define OVL_START__OVL_Y_START__SHIFT 0x00000000
+#define OVL_STEREOSYNC_FLIP__OVL_PRIMARY_SURFACE_PENDING_MASK 0x00010000L
+#define OVL_STEREOSYNC_FLIP__OVL_PRIMARY_SURFACE_PENDING__SHIFT 0x00000010
+#define OVL_STEREOSYNC_FLIP__OVL_SECONDARY_SURFACE_PENDING_MASK 0x00020000L
+#define OVL_STEREOSYNC_FLIP__OVL_SECONDARY_SURFACE_PENDING__SHIFT 0x00000011
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_EN_MASK 0x00000001L
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_EN__SHIFT 0x00000000
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_MODE_MASK 0x00000300L
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_FLIP_MODE__SHIFT 0x00000008
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_SELECT_DISABLE_MASK 0x10000000L
+#define OVL_STEREOSYNC_FLIP__OVL_STEREOSYNC_SELECT_DISABLE__SHIFT 0x0000001c
+#define OVL_SURFACE_ADDRESS_HIGH_INUSE__OVL_SURFACE_ADDRESS_HIGH_INUSE_MASK 0x000000ffL
+#define OVL_SURFACE_ADDRESS_HIGH_INUSE__OVL_SURFACE_ADDRESS_HIGH_INUSE__SHIFT 0x00000000
+#define OVL_SURFACE_ADDRESS_HIGH__OVL_SURFACE_ADDRESS_HIGH_MASK 0x000000ffL
+#define OVL_SURFACE_ADDRESS_HIGH__OVL_SURFACE_ADDRESS_HIGH__SHIFT 0x00000000
+#define OVL_SURFACE_ADDRESS_INUSE__OVL_SURFACE_ADDRESS_INUSE_MASK 0xffffff00L
+#define OVL_SURFACE_ADDRESS_INUSE__OVL_SURFACE_ADDRESS_INUSE__SHIFT 0x00000008
+#define OVL_SURFACE_ADDRESS__OVL_DFQ_ENABLE_MASK 0x00000001L
+#define OVL_SURFACE_ADDRESS__OVL_DFQ_ENABLE__SHIFT 0x00000000
+#define OVL_SURFACE_ADDRESS__OVL_SURFACE_ADDRESS_MASK 0xffffff00L
+#define OVL_SURFACE_ADDRESS__OVL_SURFACE_ADDRESS__SHIFT 0x00000008
+#define OVL_SURFACE_OFFSET_X__OVL_SURFACE_OFFSET_X_MASK 0x00003fffL
+#define OVL_SURFACE_OFFSET_X__OVL_SURFACE_OFFSET_X__SHIFT 0x00000000
+#define OVL_SURFACE_OFFSET_Y__OVL_SURFACE_OFFSET_Y_MASK 0x00003fffL
+#define OVL_SURFACE_OFFSET_Y__OVL_SURFACE_OFFSET_Y__SHIFT 0x00000000
+#define OVL_SWAP_CNTL__OVL_ALPHA_CROSSBAR_MASK 0x00000c00L
+#define OVL_SWAP_CNTL__OVL_ALPHA_CROSSBAR__SHIFT 0x0000000a
+#define OVL_SWAP_CNTL__OVL_BLUE_CROSSBAR_MASK 0x00000300L
+#define OVL_SWAP_CNTL__OVL_BLUE_CROSSBAR__SHIFT 0x00000008
+#define OVL_SWAP_CNTL__OVL_ENDIAN_SWAP_MASK 0x00000003L
+#define OVL_SWAP_CNTL__OVL_ENDIAN_SWAP__SHIFT 0x00000000
+#define OVL_SWAP_CNTL__OVL_GREEN_CROSSBAR_MASK 0x000000c0L
+#define OVL_SWAP_CNTL__OVL_GREEN_CROSSBAR__SHIFT 0x00000006
+#define OVL_SWAP_CNTL__OVL_RED_CROSSBAR_MASK 0x00000030L
+#define OVL_SWAP_CNTL__OVL_RED_CROSSBAR__SHIFT 0x00000004
+#define OVL_UPDATE__OVL_DISABLE_MULTIPLE_UPDATE_MASK 0x01000000L
+#define OVL_UPDATE__OVL_DISABLE_MULTIPLE_UPDATE__SHIFT 0x00000018
+#define OVL_UPDATE__OVL_UPDATE_LOCK_MASK 0x00010000L
+#define OVL_UPDATE__OVL_UPDATE_LOCK__SHIFT 0x00000010
+#define OVL_UPDATE__OVL_UPDATE_PENDING_MASK 0x00000001L
+#define OVL_UPDATE__OVL_UPDATE_PENDING__SHIFT 0x00000000
+#define OVL_UPDATE__OVL_UPDATE_TAKEN_MASK 0x00000002L
+#define OVL_UPDATE__OVL_UPDATE_TAKEN__SHIFT 0x00000001
+#define PHY_AUX_CNTL__AUX_PAD_RXSEL_MASK 0x00010000L
+#define PHY_AUX_CNTL__AUX_PAD_RXSEL__SHIFT 0x00000010
+#define PHY_AUX_CNTL__AUX_PAD_SLEWN_MASK 0x00001000L
+#define PHY_AUX_CNTL__AUX_PAD_SLEWN__SHIFT 0x0000000c
+#define PHY_AUX_CNTL__AUX_PAD_WAKE_MASK 0x00004000L
+#define PHY_AUX_CNTL__AUX_PAD_WAKE__SHIFT 0x0000000e
+#define PIPE0_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE0_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE0_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE0_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE0_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE0_PG_CONFIG__PIPE0_POWER_FORCEON_MASK 0x00000001L
+#define PIPE0_PG_CONFIG__PIPE0_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE0_PG_ENABLE__PIPE0_POWER_GATE_MASK 0x00000001L
+#define PIPE0_PG_ENABLE__PIPE0_POWER_GATE__SHIFT 0x00000000
+#define PIPE0_PG_STATUS__PIPE0_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE0_PG_STATUS__PIPE0_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE0_PG_STATUS__PIPE0_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE0_PG_STATUS__PIPE0_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE0_PG_STATUS__PIPE0_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE1_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE1_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE1_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE1_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE1_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE1_PG_CONFIG__PIPE1_POWER_FORCEON_MASK 0x00000001L
+#define PIPE1_PG_CONFIG__PIPE1_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE1_PG_ENABLE__PIPE1_POWER_GATE_MASK 0x00000001L
+#define PIPE1_PG_ENABLE__PIPE1_POWER_GATE__SHIFT 0x00000000
+#define PIPE1_PG_STATUS__PIPE1_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE1_PG_STATUS__PIPE1_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE1_PG_STATUS__PIPE1_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE1_PG_STATUS__PIPE1_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE1_PG_STATUS__PIPE1_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE2_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE2_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE2_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE2_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE2_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE2_PG_CONFIG__PIPE2_POWER_FORCEON_MASK 0x00000001L
+#define PIPE2_PG_CONFIG__PIPE2_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE2_PG_ENABLE__PIPE2_POWER_GATE_MASK 0x00000001L
+#define PIPE2_PG_ENABLE__PIPE2_POWER_GATE__SHIFT 0x00000000
+#define PIPE2_PG_STATUS__PIPE2_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE2_PG_STATUS__PIPE2_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE2_PG_STATUS__PIPE2_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE2_PG_STATUS__PIPE2_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE2_PG_STATUS__PIPE2_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE3_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE3_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE3_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE3_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE3_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE3_PG_CONFIG__PIPE3_POWER_FORCEON_MASK 0x00000001L
+#define PIPE3_PG_CONFIG__PIPE3_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE3_PG_ENABLE__PIPE3_POWER_GATE_MASK 0x00000001L
+#define PIPE3_PG_ENABLE__PIPE3_POWER_GATE__SHIFT 0x00000000
+#define PIPE3_PG_STATUS__PIPE3_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE3_PG_STATUS__PIPE3_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE3_PG_STATUS__PIPE3_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE3_PG_STATUS__PIPE3_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE3_PG_STATUS__PIPE3_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE4_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE4_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE4_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE4_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE4_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE4_PG_CONFIG__PIPE4_POWER_FORCEON_MASK 0x00000001L
+#define PIPE4_PG_CONFIG__PIPE4_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE4_PG_ENABLE__PIPE4_POWER_GATE_MASK 0x00000001L
+#define PIPE4_PG_ENABLE__PIPE4_POWER_GATE__SHIFT 0x00000000
+#define PIPE4_PG_STATUS__PIPE4_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE4_PG_STATUS__PIPE4_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE4_PG_STATUS__PIPE4_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE4_PG_STATUS__PIPE4_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE4_PG_STATUS__PIPE4_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIPE5_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT_MASK 0x0000ffffL
+#define PIPE5_ARBITRATION_CONTROL3__EFFICIENCY_WEIGHT__SHIFT 0x00000000
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED_MASK 0x00000007L
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATED__SHIFT 0x00000000
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED_MASK 0x00000010L
+#define PIPE5_DMIF_BUFFER_CONTROL__DMIF_BUFFERS_ALLOCATION_COMPLETED__SHIFT 0x00000004
+#define PIPE5_MAX_REQUESTS__MAX_REQUESTS_MASK 0x000003ffL
+#define PIPE5_MAX_REQUESTS__MAX_REQUESTS__SHIFT 0x00000000
+#define PIPE5_PG_CONFIG__PIPE5_POWER_FORCEON_MASK 0x00000001L
+#define PIPE5_PG_CONFIG__PIPE5_POWER_FORCEON__SHIFT 0x00000000
+#define PIPE5_PG_ENABLE__PIPE5_POWER_GATE_MASK 0x00000001L
+#define PIPE5_PG_ENABLE__PIPE5_POWER_GATE__SHIFT 0x00000000
+#define PIPE5_PG_STATUS__PIPE5_DESIRED_PWR_STATE_MASK 0x10000000L
+#define PIPE5_PG_STATUS__PIPE5_DESIRED_PWR_STATE__SHIFT 0x0000001c
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_PWR_STATUS_MASK 0xc0000000L
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_PWR_STATUS__SHIFT 0x0000001e
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_READ_DATA_MASK 0x00ffffffL
+#define PIPE5_PG_STATUS__PIPE5_PGFSM_READ_DATA__SHIFT 0x00000000
+#define PIPE5_PG_STATUS__PIPE5_REQUESTED_PWR_STATE_MASK 0x20000000L
+#define PIPE5_PG_STATUS__PIPE5_REQUESTED_PWR_STATE__SHIFT 0x0000001d
+#define PIXCLK0_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL0_MASK 0x00000030L
+#define PIXCLK0_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL0__SHIFT 0x00000004
+#define PIXCLK0_RESYNC_CNTL__PIXCLK0_RESYNC_ENABLE_MASK 0x00000001L
+#define PIXCLK0_RESYNC_CNTL__PIXCLK0_RESYNC_ENABLE__SHIFT 0x00000000
+#define PIXCLK1_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL1_MASK 0x00000030L
+#define PIXCLK1_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL1__SHIFT 0x00000004
+#define PIXCLK1_RESYNC_CNTL__PIXCLK1_RESYNC_ENABLE_MASK 0x00000001L
+#define PIXCLK1_RESYNC_CNTL__PIXCLK1_RESYNC_ENABLE__SHIFT 0x00000000
+#define PIXCLK2_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL2_MASK 0x00000030L
+#define PIXCLK2_RESYNC_CNTL__DCCG_DEEP_COLOR_CNTL2__SHIFT 0x00000004
+#define PIXCLK2_RESYNC_CNTL__PIXCLK2_RESYNC_ENABLE_MASK 0x00000001L
+#define PIXCLK2_RESYNC_CNTL__PIXCLK2_RESYNC_ENABLE__SHIFT 0x00000000
+#define PLL_ANALOG__PLL_CAL_MODE_MASK 0x0000001fL
+#define PLL_ANALOG__PLL_CAL_MODE__SHIFT 0x00000000
+#define PLL_ANALOG__PLL_CP_MASK 0x00000f00L
+#define PLL_ANALOG__PLL_CP__SHIFT 0x00000008
+#define PLL_ANALOG__PLL_IBIAS_MASK 0xff000000L
+#define PLL_ANALOG__PLL_IBIAS__SHIFT 0x00000018
+#define PLL_ANALOG__PLL_LF_MODE_MASK 0x001ff000L
+#define PLL_ANALOG__PLL_LF_MODE__SHIFT 0x0000000c
+#define PLL_ANALOG__PLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define PLL_ANALOG__PLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define PLL_CNTL__PLL_ANTIGLITCH_RESETB_MASK 0x00000080L
+#define PLL_CNTL__PLL_ANTIGLITCH_RESETB__SHIFT 0x00000007
+#define PLL_CNTL__PLL_ANTI_GLITCH_RESET_MASK 0x00002000L
+#define PLL_CNTL__PLL_ANTI_GLITCH_RESET__SHIFT 0x0000000d
+#define PLL_CNTL__PLL_BYPASS_CAL_MASK 0x00000004L
+#define PLL_CNTL__PLL_BYPASS_CAL__SHIFT 0x00000002
+#define PLL_CNTL__PLL_CAL_BYPASS_REFDIV_MASK 0x00000400L
+#define PLL_CNTL__PLL_CAL_BYPASS_REFDIV__SHIFT 0x0000000a
+#define PLL_CNTL__PLL_CALIB_DONE_MASK 0x00100000L
+#define PLL_CNTL__PLL_CALIB_DONE__SHIFT 0x00000014
+#define PLL_CNTL__PLL_CALREF_MASK 0x00000300L
+#define PLL_CNTL__PLL_CALREF__SHIFT 0x00000008
+#define PLL_CNTL__PLL_DIG_SPARE_MASK 0xfc000000L
+#define PLL_CNTL__PLL_DIG_SPARE__SHIFT 0x0000001a
+#define PLL_CNTL__PLL_LOCKED_MASK 0x00200000L
+#define PLL_CNTL__PLL_LOCKED__SHIFT 0x00000015
+#define PLL_CNTL__PLL_LOCK_FREQ_SEL_MASK 0x00080000L
+#define PLL_CNTL__PLL_LOCK_FREQ_SEL__SHIFT 0x00000013
+#define PLL_CNTL__PLL_PCIE_REFCLK_SEL_MASK 0x00000040L
+#define PLL_CNTL__PLL_PCIE_REFCLK_SEL__SHIFT 0x00000006
+#define PLL_CNTL__PLL_POST_DIV_SRC_MASK 0x00000008L
+#define PLL_CNTL__PLL_POST_DIV_SRC__SHIFT 0x00000003
+#define PLL_CNTL__PLL_POWER_DOWN_MASK 0x00000002L
+#define PLL_CNTL__PLL_POWER_DOWN__SHIFT 0x00000001
+#define PLL_CNTL__PLL_REFCLK_SEL_MASK 0x00001800L
+#define PLL_CNTL__PLL_REFCLK_SEL__SHIFT 0x0000000b
+#define PLL_CNTL__PLL_REF_DIV_SRC_MASK 0x00070000L
+#define PLL_CNTL__PLL_REF_DIV_SRC__SHIFT 0x00000010
+#define PLL_CNTL__PLL_RESET_MASK 0x00000001L
+#define PLL_CNTL__PLL_RESET__SHIFT 0x00000000
+#define PLL_CNTL__PLL_TIMING_MODE_STATUS_MASK 0x03000000L
+#define PLL_CNTL__PLL_TIMING_MODE_STATUS__SHIFT 0x00000018
+#define PLL_CNTL__PLL_VCOREF_MASK 0x00000030L
+#define PLL_CNTL__PLL_VCOREF__SHIFT 0x00000004
+#define PLL_DEBUG_CNTL__PLL_DEBUG_CLK_SEL_MASK 0x00000f00L
+#define PLL_DEBUG_CNTL__PLL_DEBUG_CLK_SEL__SHIFT 0x00000008
+#define PLL_DEBUG_CNTL__PLL_DEBUG_MUXOUT_SEL_MASK 0x000000f0L
+#define PLL_DEBUG_CNTL__PLL_DEBUG_MUXOUT_SEL__SHIFT 0x00000004
+#define PLL_DEBUG_CNTL__PLL_DEBUG_SIGNALS_ENABLE_MASK 0x00000001L
+#define PLL_DEBUG_CNTL__PLL_DEBUG_SIGNALS_ENABLE__SHIFT 0x00000000
+#define PLL_DISPCLK_CURRENT_DTO_PHASE__PLL_DISPCLK_CURRENT_DTO_PHASE_MASK 0x000001ffL
+#define PLL_DISPCLK_CURRENT_DTO_PHASE__PLL_DISPCLK_CURRENT_DTO_PHASE__SHIFT 0x00000000
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_COMPL_DELAY_MASK 0xff000000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_COMPL_DELAY__SHIFT 0x00000018
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_DIS_MASK 0x00010000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_DIS__SHIFT 0x00000010
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_PHASE_MASK 0x000001ffL
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_PHASE__SHIFT 0x00000000
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_ACK_MASK 0x00400000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_ACK__SHIFT 0x00000016
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_MODE_MASK 0x00060000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_MODE__SHIFT 0x00000011
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_PENDING_MASK 0x00100000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_PENDING__SHIFT 0x00000014
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_REQ_MASK 0x00200000L
+#define PLL_DISPCLK_DTO_CNTL__PLL_DISPCLK_DTO_UPDATE_REQ__SHIFT 0x00000015
+#define PLL_DS_CNTL__PLL_DS_FRAC_MASK 0x0000ffffL
+#define PLL_DS_CNTL__PLL_DS_FRAC__SHIFT 0x00000000
+#define PLL_DS_CNTL__PLL_DS_MODE_MASK 0x00040000L
+#define PLL_DS_CNTL__PLL_DS_MODE__SHIFT 0x00000012
+#define PLL_DS_CNTL__PLL_DS_ORDER_MASK 0x00030000L
+#define PLL_DS_CNTL__PLL_DS_ORDER__SHIFT 0x00000010
+#define PLL_DS_CNTL__PLL_DS_PRBS_EN_MASK 0x00080000L
+#define PLL_DS_CNTL__PLL_DS_PRBS_EN__SHIFT 0x00000013
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define PLL_FB_DIV__PLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define PLL_FB_DIV__PLL_FB_DIV_MASK 0x0fff0000L
+#define PLL_FB_DIV__PLL_FB_DIV__SHIFT 0x00000010
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_MASK 0x000f0000L
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_RESET_MASK 0x00000100L
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_RESET__SHIFT 0x00000008
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_SELECT_MASK 0x00001000L
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV_SELECT__SHIFT 0x0000000c
+#define PLL_IDCLK_CNTL__PLL_DIFF_POST_DIV__SHIFT 0x00000010
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_DIFF_EN_MASK 0x00000002L
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_DIFF_EN__SHIFT 0x00000001
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_EN_MASK 0x00000001L
+#define PLL_IDCLK_CNTL__PLL_LTDP_IDCLK_EN__SHIFT 0x00000000
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_DIFF_EN_MASK 0x00000008L
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_DIFF_EN__SHIFT 0x00000003
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_EN_MASK 0x00000004L
+#define PLL_IDCLK_CNTL__PLL_TMDP_IDCLK_EN__SHIFT 0x00000002
+#define PLL_IDCLK_CNTL__PLL_UNIPHY_IDCLK_DIFF_EN_MASK 0x00000010L
+#define PLL_IDCLK_CNTL__PLL_UNIPHY_IDCLK_DIFF_EN__SHIFT 0x00000004
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DISPCLK_MASK 0x00000080L
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DISPCLK__SHIFT 0x00000007
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DPREFCLK_MASK 0x00008000L
+#define PLL_POST_DIV__PLL_POST_DIV1P5_DPREFCLK__SHIFT 0x0000000f
+#define PLL_POST_DIV__PLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define PLL_POST_DIV__PLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define PLL_POST_DIV__PLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define PLL_POST_DIV__PLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define PLL_POST_DIV__PLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define PLL_REF_DIV__PLL_CALIBRATION_REF_DIV_MASK 0x0000f000L
+#define PLL_REF_DIV__PLL_CALIBRATION_REF_DIV__SHIFT 0x0000000c
+#define PLL_REF_DIV__PLL_REF_DIV_MASK 0x000003ffL
+#define PLL_REF_DIV__PLL_REF_DIV__SHIFT 0x00000000
+#define PLL_SS_AMOUNT_DSFRAC__PLL_SS_AMOUNT_DSFRAC_MASK 0x0000ffffL
+#define PLL_SS_AMOUNT_DSFRAC__PLL_SS_AMOUNT_DSFRAC__SHIFT 0x00000000
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_FBDIV_MASK 0x000000ffL
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_FBDIV__SHIFT 0x00000000
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_NFRAC_SLIP_MASK 0x00000f00L
+#define PLL_SS_CNTL__PLL_SS_AMOUNT_NFRAC_SLIP__SHIFT 0x00000008
+#define PLL_SS_CNTL__PLL_SS_EN_MASK 0x00001000L
+#define PLL_SS_CNTL__PLL_SS_EN__SHIFT 0x0000000c
+#define PLL_SS_CNTL__PLL_SS_MODE_MASK 0x00002000L
+#define PLL_SS_CNTL__PLL_SS_MODE__SHIFT 0x0000000d
+#define PLL_SS_CNTL__PLL_SS_STEP_SIZE_DSFRAC_MASK 0xffff0000L
+#define PLL_SS_CNTL__PLL_SS_STEP_SIZE_DSFRAC__SHIFT 0x00000010
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_COUNT_MASK 0x00000070L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_COUNT__SHIFT 0x00000004
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DETECT_ENABLE_MASK 0x00000001L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DETECT_ENABLE__SHIFT 0x00000000
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_RES100_SELECT_MASK 0x00000002L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_DET_RES100_SELECT__SHIFT 0x00000001
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_CLEAR_MASK 0x00000008L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_CLEAR__SHIFT 0x00000003
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_STATUS_MASK 0x00000004L
+#define PLL_UNLOCK_DETECT_CNTL__PLL_UNLOCK_STICKY_STATUS__SHIFT 0x00000002
+#define PLL_UPDATE_CNTL__PLL_AUTO_RESET_DISABLE_MASK 0x00010000L
+#define PLL_UPDATE_CNTL__PLL_AUTO_RESET_DISABLE__SHIFT 0x00000010
+#define PLL_UPDATE_CNTL__PLL_UPDATE_PENDING_MASK 0x00000001L
+#define PLL_UPDATE_CNTL__PLL_UPDATE_PENDING__SHIFT 0x00000000
+#define PLL_UPDATE_CNTL__PLL_UPDATE_POINT_MASK 0x00000100L
+#define PLL_UPDATE_CNTL__PLL_UPDATE_POINT__SHIFT 0x00000008
+#define PLL_UPDATE_LOCK__PLL_UPDATE_LOCK_MASK 0x00000001L
+#define PLL_UPDATE_LOCK__PLL_UPDATE_LOCK__SHIFT 0x00000000
+#define PLL_VREG_CNTL__PLL_VREF_SEL_MASK 0x04000000L
+#define PLL_VREG_CNTL__PLL_VREF_SEL__SHIFT 0x0000001a
+#define PLL_VREG_CNTL__PLL_VREG_BIAS_MASK 0xf0000000L
+#define PLL_VREG_CNTL__PLL_VREG_BIAS__SHIFT 0x0000001c
+#define PLL_VREG_CNTL__PLL_VREG_CNTL_MASK 0x000fffffL
+#define PLL_VREG_CNTL__PLL_VREG_CNTL__SHIFT 0x00000000
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_B_SIGN_MASK 0x00000008L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_B_SIGN__SHIFT 0x00000003
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS_MASK 0x00000010L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_BYPASS__SHIFT 0x00000004
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_G_SIGN_MASK 0x00000004L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_G_SIGN__SHIFT 0x00000002
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_R_SIGN_MASK 0x00000002L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_R_SIGN__SHIFT 0x00000001
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_SELECT_MASK 0x00000001L
+#define PRESCALE_GRPH_CONTROL__GRPH_PRESCALE_SELECT__SHIFT 0x00000000
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_BYPASS_MASK 0x00000010L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_BYPASS__SHIFT 0x00000004
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CB_SIGN_MASK 0x00000002L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CB_SIGN__SHIFT 0x00000001
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CR_SIGN_MASK 0x00000008L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_CR_SIGN__SHIFT 0x00000003
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_SELECT_MASK 0x00000001L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_SELECT__SHIFT 0x00000000
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_Y_SIGN_MASK 0x00000004L
+#define PRESCALE_OVL_CONTROL__OVL_PRESCALE_Y_SIGN__SHIFT 0x00000002
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_BIAS_B_MASK 0x0000ffffL
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_BIAS_B__SHIFT 0x00000000
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_SCALE_B_MASK 0xffff0000L
+#define PRESCALE_VALUES_GRPH_B__GRPH_PRESCALE_SCALE_B__SHIFT 0x00000010
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_BIAS_G_MASK 0x0000ffffL
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_BIAS_G__SHIFT 0x00000000
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_SCALE_G_MASK 0xffff0000L
+#define PRESCALE_VALUES_GRPH_G__GRPH_PRESCALE_SCALE_G__SHIFT 0x00000010
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_BIAS_R_MASK 0x0000ffffL
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_BIAS_R__SHIFT 0x00000000
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_SCALE_R_MASK 0xffff0000L
+#define PRESCALE_VALUES_GRPH_R__GRPH_PRESCALE_SCALE_R__SHIFT 0x00000010
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_BIAS_CB_MASK 0x0000ffffL
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_BIAS_CB__SHIFT 0x00000000
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_SCALE_CB_MASK 0xffff0000L
+#define PRESCALE_VALUES_OVL_CB__OVL_PRESCALE_SCALE_CB__SHIFT 0x00000010
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_BIAS_CR_MASK 0x0000ffffL
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_BIAS_CR__SHIFT 0x00000000
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_SCALE_CR_MASK 0xffff0000L
+#define PRESCALE_VALUES_OVL_CR__OVL_PRESCALE_SCALE_CR__SHIFT 0x00000010
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_BIAS_Y_MASK 0x0000ffffL
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_BIAS_Y__SHIFT 0x00000000
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_SCALE_Y_MASK 0xffff0000L
+#define PRESCALE_VALUES_OVL_Y__OVL_PRESCALE_SCALE_Y__SHIFT 0x00000010
+#define REGAMMA_CNTLA_END_CNTL1__REGAMMA_CNTLA_EXP_REGION_END_MASK 0x0000ffffL
+#define REGAMMA_CNTLA_END_CNTL1__REGAMMA_CNTLA_EXP_REGION_END__SHIFT 0x00000000
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_BASE_MASK 0xffff0000L
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_BASE__SHIFT 0x00000010
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_SLOPE_MASK 0x0000ffffL
+#define REGAMMA_CNTLA_END_CNTL2__REGAMMA_CNTLA_EXP_REGION_END_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION0_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_0_1__REGAMMA_CNTLA_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION10_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_10_11__REGAMMA_CNTLA_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION12_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_12_13__REGAMMA_CNTLA_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION14_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_14_15__REGAMMA_CNTLA_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION2_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_2_3__REGAMMA_CNTLA_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION4_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_4_5__REGAMMA_CNTLA_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION6_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_6_7__REGAMMA_CNTLA_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION8_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLA_REGION_8_9__REGAMMA_CNTLA_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLA_SLOPE_CNTL__REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE_MASK 0x0003ffffL
+#define REGAMMA_CNTLA_SLOPE_CNTL__REGAMMA_CNTLA_EXP_REGION_LINEAR_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_MASK 0x0003ffffL
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_SEGMENT_MASK 0x07f00000L
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START_SEGMENT__SHIFT 0x00000014
+#define REGAMMA_CNTLA_START_CNTL__REGAMMA_CNTLA_EXP_REGION_START__SHIFT 0x00000000
+#define REGAMMA_CNTLB_END_CNTL1__REGAMMA_CNTLB_EXP_REGION_END_MASK 0x0000ffffL
+#define REGAMMA_CNTLB_END_CNTL1__REGAMMA_CNTLB_EXP_REGION_END__SHIFT 0x00000000
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_BASE_MASK 0xffff0000L
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_BASE__SHIFT 0x00000010
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_SLOPE_MASK 0x0000ffffL
+#define REGAMMA_CNTLB_END_CNTL2__REGAMMA_CNTLB_EXP_REGION_END_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION0_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_0_1__REGAMMA_CNTLB_EXP_REGION1_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION10_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_10_11__REGAMMA_CNTLB_EXP_REGION11_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION12_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_12_13__REGAMMA_CNTLB_EXP_REGION13_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION14_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_14_15__REGAMMA_CNTLB_EXP_REGION15_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION2_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_2_3__REGAMMA_CNTLB_EXP_REGION3_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION4_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_4_5__REGAMMA_CNTLB_EXP_REGION5_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION6_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_6_7__REGAMMA_CNTLB_EXP_REGION7_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_LUT_OFFSET_MASK 0x000001ffL
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_LUT_OFFSET__SHIFT 0x00000000
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_NUM_SEGMENTS_MASK 0x00007000L
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION8_NUM_SEGMENTS__SHIFT 0x0000000c
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_LUT_OFFSET_MASK 0x01ff0000L
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_LUT_OFFSET__SHIFT 0x00000010
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_NUM_SEGMENTS_MASK 0x70000000L
+#define REGAMMA_CNTLB_REGION_8_9__REGAMMA_CNTLB_EXP_REGION9_NUM_SEGMENTS__SHIFT 0x0000001c
+#define REGAMMA_CNTLB_SLOPE_CNTL__REGAMMA_CNTLB_EXP_REGION_LINEAR_SLOPE_MASK 0x0003ffffL
+#define REGAMMA_CNTLB_SLOPE_CNTL__REGAMMA_CNTLB_EXP_REGION_LINEAR_SLOPE__SHIFT 0x00000000
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_MASK 0x0003ffffL
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_SEGMENT_MASK 0x07f00000L
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START_SEGMENT__SHIFT 0x00000014
+#define REGAMMA_CNTLB_START_CNTL__REGAMMA_CNTLB_EXP_REGION_START__SHIFT 0x00000000
+#define REGAMMA_CONTROL__GRPH_REGAMMA_MODE_MASK 0x00000007L
+#define REGAMMA_CONTROL__GRPH_REGAMMA_MODE__SHIFT 0x00000000
+#define REGAMMA_CONTROL__OVL_REGAMMA_MODE_MASK 0x00000070L
+#define REGAMMA_CONTROL__OVL_REGAMMA_MODE__SHIFT 0x00000004
+#define REGAMMA_LUT_DATA__REGAMMA_LUT_DATA_MASK 0x0007ffffL
+#define REGAMMA_LUT_DATA__REGAMMA_LUT_DATA__SHIFT 0x00000000
+#define REGAMMA_LUT_INDEX__REGAMMA_LUT_INDEX_MASK 0x000001ffL
+#define REGAMMA_LUT_INDEX__REGAMMA_LUT_INDEX__SHIFT 0x00000000
+#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK_MASK 0x00000007L
+#define REGAMMA_LUT_WRITE_EN_MASK__REGAMMA_LUT_WRITE_EN_MASK__SHIFT 0x00000000
+#define SCL_ALU_CONTROL__SCL_ALU_DISABLE_MASK 0x00000001L
+#define SCL_ALU_CONTROL__SCL_ALU_DISABLE__SHIFT 0x00000000
+#define SCL_BYPASS_CONTROL__SCL_BYPASS_MODE_MASK 0x00000003L
+#define SCL_BYPASS_CONTROL__SCL_BYPASS_MODE__SHIFT 0x00000000
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_ACK_MASK 0x00000100L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_ACK__SHIFT 0x00000008
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_FLAG_MASK 0x00000001L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_FLAG__SHIFT 0x00000000
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_INT_STATUS_MASK 0x00010000L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_INT_STATUS__SHIFT 0x00000010
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_MASK_MASK 0x00001000L
+#define SCL_COEF_RAM_CONFLICT_STATUS__SCL_HOST_CONFLICT_MASK__SHIFT 0x0000000c
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE_MASK 0x00030000L
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_FILTER_TYPE__SHIFT 0x00000010
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_PHASE_MASK 0x00000f00L
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_PHASE__SHIFT 0x00000008
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX_MASK 0x0000000fL
+#define SCL_COEF_RAM_SELECT__SCL_C_RAM_TAP_PAIR_IDX__SHIFT 0x00000000
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN_MASK 0x00008000L
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_EN__SHIFT 0x0000000f
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF_MASK 0x00003fffL
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_EVEN_TAP_COEF__SHIFT 0x00000000
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN_MASK 0x80000000L
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_EN__SHIFT 0x0000001f
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF_MASK 0x3fff0000L
+#define SCL_COEF_RAM_TAP_DATA__SCL_C_RAM_ODD_TAP_COEF__SHIFT 0x00000010
+#define SCL_DEBUG2__SCL_DEBUG2_MASK 0xffffffffL
+#define SCL_DEBUG2__SCL_DEBUG2__SHIFT 0x00000000
+#define SCL_DEBUG__SCL_DEBUG_MASK 0xffffffffL
+#define SCL_DEBUG__SCL_DEBUG__SHIFT 0x00000000
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_EN_MASK 0x00000010L
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_EN__SHIFT 0x00000004
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_SCALE_FACTOR_MASK 0x00000007L
+#define SCL_F_SHARP_CONTROL__SCL_HF_SHARP_SCALE_FACTOR__SHIFT 0x00000000
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_EN_MASK 0x00001000L
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_EN__SHIFT 0x0000000c
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_SCALE_FACTOR_MASK 0x00000700L
+#define SCL_F_SHARP_CONTROL__SCL_VF_SHARP_SCALE_FACTOR__SHIFT 0x00000008
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_FILTER_PICK_NEAREST_MASK 0x00000001L
+#define SCL_HORZ_FILTER_CONTROL__SCL_H_FILTER_PICK_NEAREST__SHIFT 0x00000000
+#define SCL_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO_MASK 0x03ffffffL
+#define SCL_HORZ_FILTER_SCALE_RATIO__SCL_H_SCALE_RATIO__SHIFT 0x00000000
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_OFF_DELAY_MASK 0x00000ff0L
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_OFF_DELAY__SHIFT 0x00000004
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_ON_DELAY_MASK 0x0000000fL
+#define SCLK_CGTT_BLK_CTRL_REG__SCLK_TURN_ON_DELAY__SHIFT 0x00000000
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR_MASK 0x00000f00L
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_H_MANUAL_REPLICATE_FACTOR__SHIFT 0x00000008
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR_MASK 0x0000000fL
+#define SCL_MANUAL_REPLICATE_CONTROL__SCL_V_MANUAL_REPLICATE_FACTOR__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO_MASK 0x0fffff80L
+#define SCL_MODE_CHANGE_DET1__SCL_ALU_H_SCALE_RATIO__SHIFT 0x00000007
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK_MASK 0x00000010L
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_ACK__SHIFT 0x00000004
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE_MASK 0x00000001L
+#define SCL_MODE_CHANGE_DET1__SCL_MODE_CHANGE__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO_MASK 0x001fffffL
+#define SCL_MODE_CHANGE_DET2__SCL_ALU_V_SCALE_RATIO__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT_MASK 0x00003fffL
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_HEIGHT__SHIFT 0x00000000
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH_MASK 0x3fff0000L
+#define SCL_MODE_CHANGE_DET3__SCL_ALU_SOURCE_WIDTH__SHIFT 0x00000010
+#define SCL_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK_MASK 0x00000001L
+#define SCL_MODE_CHANGE_MASK__SCL_MODE_CHANGE_MASK__SHIFT 0x00000000
+#define SCL_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define SCL_TEST_DEBUG_DATA__SCL_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define SCL_TEST_DEBUG_INDEX__SCL_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define SCL_UPDATE__SCL_UPDATE_LOCK_MASK 0x00010000L
+#define SCL_UPDATE__SCL_UPDATE_LOCK__SHIFT 0x00000010
+#define SCL_UPDATE__SCL_UPDATE_PENDING_MASK 0x00000001L
+#define SCL_UPDATE__SCL_UPDATE_PENDING__SHIFT 0x00000000
+#define SCL_UPDATE__SCL_UPDATE_TAKEN_MASK 0x00000100L
+#define SCL_UPDATE__SCL_UPDATE_TAKEN__SHIFT 0x00000008
+#define SCL_VERT_FILTER_CONTROL__SCL_V_FILTER_PICK_NEAREST_MASK 0x00000001L
+#define SCL_VERT_FILTER_CONTROL__SCL_V_FILTER_PICK_NEAREST__SHIFT 0x00000000
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT_MASK 0x0000ffffL
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_FRAC_BOT__SHIFT 0x00000000
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT_MASK 0x00070000L
+#define SCL_VERT_FILTER_INIT_BOT__SCL_V_INIT_INT_BOT__SHIFT 0x00000010
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_FRAC_MASK 0x0000ffffL
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_FRAC__SHIFT 0x00000000
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_INT_MASK 0x00070000L
+#define SCL_VERT_FILTER_INIT__SCL_V_INIT_INT__SHIFT 0x00000010
+#define SCL_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO_MASK 0x03ffffffL
+#define SCL_VERT_FILTER_SCALE_RATIO__SCL_V_SCALE_RATIO__SHIFT 0x00000000
+#define SEQ00__SEQ_RST0B_MASK 0x00000001L
+#define SEQ00__SEQ_RST0B__SHIFT 0x00000000
+#define SEQ00__SEQ_RST1B_MASK 0x00000002L
+#define SEQ00__SEQ_RST1B__SHIFT 0x00000001
+#define SEQ01__SEQ_DOT8_MASK 0x00000001L
+#define SEQ01__SEQ_DOT8__SHIFT 0x00000000
+#define SEQ01__SEQ_MAXBW_MASK 0x00000020L
+#define SEQ01__SEQ_MAXBW__SHIFT 0x00000005
+#define SEQ01__SEQ_PCLKBY2_MASK 0x00000008L
+#define SEQ01__SEQ_PCLKBY2__SHIFT 0x00000003
+#define SEQ01__SEQ_SHIFT2_MASK 0x00000004L
+#define SEQ01__SEQ_SHIFT2__SHIFT 0x00000002
+#define SEQ01__SEQ_SHIFT4_MASK 0x00000010L
+#define SEQ01__SEQ_SHIFT4__SHIFT 0x00000004
+#define SEQ02__SEQ_MAP0_EN_MASK 0x00000001L
+#define SEQ02__SEQ_MAP0_EN__SHIFT 0x00000000
+#define SEQ02__SEQ_MAP1_EN_MASK 0x00000002L
+#define SEQ02__SEQ_MAP1_EN__SHIFT 0x00000001
+#define SEQ02__SEQ_MAP2_EN_MASK 0x00000004L
+#define SEQ02__SEQ_MAP2_EN__SHIFT 0x00000002
+#define SEQ02__SEQ_MAP3_EN_MASK 0x00000008L
+#define SEQ02__SEQ_MAP3_EN__SHIFT 0x00000003
+#define SEQ03__SEQ_FONT_A0_MASK 0x00000020L
+#define SEQ03__SEQ_FONT_A0__SHIFT 0x00000005
+#define SEQ03__SEQ_FONT_A1_MASK 0x00000004L
+#define SEQ03__SEQ_FONT_A1__SHIFT 0x00000002
+#define SEQ03__SEQ_FONT_A2_MASK 0x00000008L
+#define SEQ03__SEQ_FONT_A2__SHIFT 0x00000003
+#define SEQ03__SEQ_FONT_B0_MASK 0x00000010L
+#define SEQ03__SEQ_FONT_B0__SHIFT 0x00000004
+#define SEQ03__SEQ_FONT_B1_MASK 0x00000001L
+#define SEQ03__SEQ_FONT_B1__SHIFT 0x00000000
+#define SEQ03__SEQ_FONT_B2_MASK 0x00000002L
+#define SEQ03__SEQ_FONT_B2__SHIFT 0x00000001
+#define SEQ04__SEQ_256K_MASK 0x00000002L
+#define SEQ04__SEQ_256K__SHIFT 0x00000001
+#define SEQ04__SEQ_CHAIN_MASK 0x00000008L
+#define SEQ04__SEQ_CHAIN__SHIFT 0x00000003
+#define SEQ04__SEQ_ODDEVEN_MASK 0x00000004L
+#define SEQ04__SEQ_ODDEVEN__SHIFT 0x00000002
+#define SEQ8_DATA__SEQ_DATA_MASK 0x000000ffL
+#define SEQ8_DATA__SEQ_DATA__SHIFT 0x00000000
+#define SEQ8_IDX__SEQ_IDX_MASK 0x00000007L
+#define SEQ8_IDX__SEQ_IDX__SHIFT 0x00000000
+#define SINK_DESCRIPTION0__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION0__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION10__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION10__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION11__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION11__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION12__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION12__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION13__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION13__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION14__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION14__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION15__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION15__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION16__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION16__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION17__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION17__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION1__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION1__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION2__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION2__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION3__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION3__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION4__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION4__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION5__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION5__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION6__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION6__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION7__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION7__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION8__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION8__DESCRIPTION__SHIFT 0x00000000
+#define SINK_DESCRIPTION9__DESCRIPTION_MASK 0x000000ffL
+#define SINK_DESCRIPTION9__DESCRIPTION__SHIFT 0x00000000
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_CMD_REG__SLAVE_COMM_CMD_REG_BYTE3__SHIFT 0x00000018
+#define SLAVE_COMM_CNTL_REG__COMM_PORT_MSG_TO_HOST_IN_PROGRESS_MASK 0x00000100L
+#define SLAVE_COMM_CNTL_REG__COMM_PORT_MSG_TO_HOST_IN_PROGRESS__SHIFT 0x00000008
+#define SLAVE_COMM_CNTL_REG__SLAVE_COMM_INTERRUPT_MASK 0x00000001L
+#define SLAVE_COMM_CNTL_REG__SLAVE_COMM_INTERRUPT__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_DATA_REG1__SLAVE_COMM_DATA_REG1_BYTE3__SHIFT 0x00000018
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_DATA_REG2__SLAVE_COMM_DATA_REG2_BYTE3__SHIFT 0x00000018
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE0_MASK 0x000000ffL
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE0__SHIFT 0x00000000
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE1_MASK 0x0000ff00L
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE1__SHIFT 0x00000008
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE2_MASK 0x00ff0000L
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE2__SHIFT 0x00000010
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE3_MASK 0xff000000L
+#define SLAVE_COMM_DATA_REG3__SLAVE_COMM_DATA_REG3_BYTE3__SHIFT 0x00000018
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKA_CLOCK_ENABLE__SYMCLKA_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKB_CLOCK_ENABLE__SYMCLKB_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKC_CLOCK_ENABLE__SYMCLKC_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKD_CLOCK_ENABLE__SYMCLKD_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKE_CLOCK_ENABLE__SYMCLKE_FE_FORCE_SRC__SHIFT 0x00000008
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_CLOCK_ENABLE_MASK 0x00000001L
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_CLOCK_ENABLE__SHIFT 0x00000000
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_EN_MASK 0x00000010L
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_EN__SHIFT 0x00000004
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_SRC_MASK 0x00000700L
+#define SYMCLKF_CLOCK_ENABLE__SYMCLKF_FE_FORCE_SRC__SHIFT 0x00000008
+#define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L
+#define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008
+#define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L
+#define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004
+#define TMDS_CNTL__TMDS_SYNC_PHASE_MASK 0x00000001L
+#define TMDS_CNTL__TMDS_SYNC_PHASE__SHIFT 0x00000000
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_DELAY_MASK 0x00000300L
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_DELAY__SHIFT 0x00000008
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_SELECT_MASK 0x00000003L
+#define TMDS_CONTROL0_FEEDBACK__TMDS_CONTROL0_FEEDBACK_SELECT__SHIFT 0x00000000
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR0_OUT_EN_MASK 0x00000001L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR0_OUT_EN__SHIFT 0x00000000
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR1_OUT_EN_MASK 0x00000002L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR1_OUT_EN__SHIFT 0x00000001
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR2_OUT_EN_MASK 0x00000004L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR2_OUT_EN__SHIFT 0x00000002
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR3_OUT_EN_MASK 0x00000008L
+#define TMDS_CONTROL_CHAR__TMDS_CONTROL_CHAR3_OUT_EN__SHIFT 0x00000003
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_2BIT_COUNTER_EN_MASK 0x80000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_2BIT_COUNTER_EN__SHIFT 0x0000001f
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_DELAY_MASK 0x00000070L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_DELAY__SHIFT 0x00000004
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_INVERT_MASK 0x00000080L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_INVERT__SHIFT 0x00000007
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_MODULATION_MASK 0x00000300L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_MODULATION__SHIFT 0x00000008
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_SEL_MASK 0x0000000fL
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_DATA_SEL__SHIFT 0x00000000
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_FB_SYNC_CONT_MASK 0x00000800L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_FB_SYNC_CONT__SHIFT 0x0000000b
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_PATTERN_OUT_EN_MASK 0x00001000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_PATTERN_OUT_EN__SHIFT 0x0000000c
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_USE_FEEDBACK_PATH_MASK 0x00000400L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL0_USE_FEEDBACK_PATH__SHIFT 0x0000000a
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_DELAY_MASK 0x00700000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_DELAY__SHIFT 0x00000014
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_INVERT_MASK 0x00800000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_INVERT__SHIFT 0x00000017
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_MODULATION_MASK 0x03000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_MODULATION__SHIFT 0x00000018
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_SEL_MASK 0x000f0000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_DATA_SEL__SHIFT 0x00000010
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_FB_SYNC_CONT_MASK 0x08000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_FB_SYNC_CONT__SHIFT 0x0000001b
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_PATTERN_OUT_EN_MASK 0x10000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_PATTERN_OUT_EN__SHIFT 0x0000001c
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_USE_FEEDBACK_PATH_MASK 0x04000000L
+#define TMDS_CTL0_1_GEN_CNTL__TMDS_CTL1_USE_FEEDBACK_PATH__SHIFT 0x0000001a
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_DELAY_MASK 0x00000070L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_DELAY__SHIFT 0x00000004
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_INVERT_MASK 0x00000080L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_INVERT__SHIFT 0x00000007
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_MODULATION_MASK 0x00000300L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_MODULATION__SHIFT 0x00000008
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_SEL_MASK 0x0000000fL
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_DATA_SEL__SHIFT 0x00000000
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_FB_SYNC_CONT_MASK 0x00000800L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_FB_SYNC_CONT__SHIFT 0x0000000b
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_PATTERN_OUT_EN_MASK 0x00001000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_PATTERN_OUT_EN__SHIFT 0x0000000c
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_USE_FEEDBACK_PATH_MASK 0x00000400L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL2_USE_FEEDBACK_PATH__SHIFT 0x0000000a
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_DELAY_MASK 0x00700000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_DELAY__SHIFT 0x00000014
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_INVERT_MASK 0x00800000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_INVERT__SHIFT 0x00000017
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_MODULATION_MASK 0x03000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_MODULATION__SHIFT 0x00000018
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_SEL_MASK 0x000f0000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_DATA_SEL__SHIFT 0x00000010
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_FB_SYNC_CONT_MASK 0x08000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_FB_SYNC_CONT__SHIFT 0x0000001b
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_PATTERN_OUT_EN_MASK 0x10000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_PATTERN_OUT_EN__SHIFT 0x0000001c
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_USE_FEEDBACK_PATH_MASK 0x04000000L
+#define TMDS_CTL2_3_GEN_CNTL__TMDS_CTL3_USE_FEEDBACK_PATH__SHIFT 0x0000001a
+#define TMDS_CTL_BITS__TMDS_CTL0_MASK 0x00000001L
+#define TMDS_CTL_BITS__TMDS_CTL0__SHIFT 0x00000000
+#define TMDS_CTL_BITS__TMDS_CTL1_MASK 0x00000100L
+#define TMDS_CTL_BITS__TMDS_CTL1__SHIFT 0x00000008
+#define TMDS_CTL_BITS__TMDS_CTL2_MASK 0x00010000L
+#define TMDS_CTL_BITS__TMDS_CTL2__SHIFT 0x00000010
+#define TMDS_CTL_BITS__TMDS_CTL3_MASK 0x01000000L
+#define TMDS_CTL_BITS__TMDS_CTL3__SHIFT 0x00000018
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_EN_MASK 0x00000001L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_EN__SHIFT 0x00000000
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_FORCE_MASK 0x01000000L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_FORCE__SHIFT 0x00000018
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_EN_MASK 0x00000100L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_EN__SHIFT 0x00000008
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_IN_MASK 0x000f0000L
+#define TMDS_DCBALANCER_CONTROL__TMDS_DCBALANCER_TEST_IN__SHIFT 0x00000010
+#define TMDS_DCBALANCER_CONTROL__TMDS_SYNC_DCBAL_EN_MASK 0x00000070L
+#define TMDS_DCBALANCER_CONTROL__TMDS_SYNC_DCBAL_EN__SHIFT 0x00000004
+#define TMDS_DEBUG__TMDS_DEBUG_DE_EN_MASK 0x02000000L
+#define TMDS_DEBUG__TMDS_DEBUG_DE_EN__SHIFT 0x00000019
+#define TMDS_DEBUG__TMDS_DEBUG_DE_MASK 0x01000000L
+#define TMDS_DEBUG__TMDS_DEBUG_DE__SHIFT 0x00000018
+#define TMDS_DEBUG__TMDS_DEBUG_EN_MASK 0x00000001L
+#define TMDS_DEBUG__TMDS_DEBUG_EN__SHIFT 0x00000000
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_EN_MASK 0x00000200L
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_EN__SHIFT 0x00000009
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC_MASK 0x00000100L
+#define TMDS_DEBUG__TMDS_DEBUG_HSYNC__SHIFT 0x00000008
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_EN_MASK 0x00020000L
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_EN__SHIFT 0x00000011
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC_MASK 0x00010000L
+#define TMDS_DEBUG__TMDS_DEBUG_VSYNC__SHIFT 0x00000010
+#define TMDS_STEREOSYNC_CTL_SEL__TMDS_STEREOSYNC_CTL_SEL_MASK 0x00000003L
+#define TMDS_STEREOSYNC_CTL_SEL__TMDS_STEREOSYNC_CTL_SEL__SHIFT 0x00000000
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN0_MASK 0x000003ffL
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN0__SHIFT 0x00000000
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN1_MASK 0x03ff0000L
+#define TMDS_SYNC_CHAR_PATTERN_0_1__TMDS_SYNC_CHAR_PATTERN1__SHIFT 0x00000010
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN2_MASK 0x000003ffL
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN2__SHIFT 0x00000000
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN3_MASK 0x03ff0000L
+#define TMDS_SYNC_CHAR_PATTERN_2_3__TMDS_SYNC_CHAR_PATTERN3__SHIFT 0x00000010
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_STATIC_TEST_PATTERN_MASK 0x000003ffL
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_STATIC_TEST_PATTERN__SHIFT 0x00000000
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_EN_MASK 0x00010000L
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_EN__SHIFT 0x00000010
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_SEL_MASK 0x000e0000L
+#define UNIPHYAB_TPG_CONTROL__UNIPHYAB_TPG_SEL__SHIFT 0x00000011
+#define UNIPHYAB_TPG_SEED__UNIPHYAB_TPG_SEED_MASK 0x007fffffL
+#define UNIPHYAB_TPG_SEED__UNIPHYAB_TPG_SEED__SHIFT 0x00000000
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_ERROR_MASK 0x001f0000L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_ERROR__SHIFT 0x00000010
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_RESET_MASK 0x00000002L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_ANG_BIST_RESET__SHIFT 0x00000001
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_PRESETB_MASK 0x01000000L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_PRESETB__SHIFT 0x00000018
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_RX_BIAS_MASK 0x00000f00L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_RX_BIAS__SHIFT 0x00000008
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_TEST_RX_EN_MASK 0x00000001L
+#define UNIPHY_ANG_BIST_CNTL__UNIPHY_TEST_RX_EN__SHIFT 0x00000000
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_STATIC_TEST_PATTERN_MASK 0x000003ffL
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_STATIC_TEST_PATTERN__SHIFT 0x00000000
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_EN_MASK 0x00010000L
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_EN__SHIFT 0x00000010
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_SEL_MASK 0x000e0000L
+#define UNIPHYCD_TPG_CONTROL__UNIPHYCD_TPG_SEL__SHIFT 0x00000011
+#define UNIPHYCD_TPG_SEED__UNIPHYCD_TPG_SEED_MASK 0x007fffffL
+#define UNIPHYCD_TPG_SEED__UNIPHYCD_TPG_SEED__SHIFT 0x00000000
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE_MASK 0x00000003L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL0_XBAR_SOURCE__SHIFT 0x00000000
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE_MASK 0x00000300L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL1_XBAR_SOURCE__SHIFT 0x00000008
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE_MASK 0x00030000L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL2_XBAR_SOURCE__SHIFT 0x00000010
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE_MASK 0x03000000L
+#define UNIPHY_CHANNEL_XBAR_CNTL__UNIPHY_CHANNEL3_XBAR_SOURCE__SHIFT 0x00000018
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_ERROR_MASK 0x00000040L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_ERROR__SHIFT 0x00000006
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_LEVEL_MASK 0x00000030L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYN_LEVEL__SHIFT 0x00000004
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYNSEL_MASK 0x00000001L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DSYNSEL__SHIFT 0x00000000
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DUAL_LINK_PHASE_MASK 0x00010000L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_DUAL_LINK_PHASE__SHIFT 0x00000010
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_LINK_ENABLE_MASK 0x00001000L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_LINK_ENABLE__SHIFT 0x0000000c
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_SOURCE_SELECT_MASK 0x00000100L
+#define UNIPHY_DATA_SYNCHRONIZATION__UNIPHY_SOURCE_SELECT__SHIFT 0x00000008
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_STATIC_TEST_PATTERN_MASK 0x000003ffL
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_STATIC_TEST_PATTERN__SHIFT 0x00000000
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_EN_MASK 0x00010000L
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_EN__SHIFT 0x00000010
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_SEL_MASK 0x000e0000L
+#define UNIPHYEF_TPG_CONTROL__UNIPHYEF_TPG_SEL__SHIFT 0x00000011
+#define UNIPHYEF_TPG_SEED__UNIPHYEF_TPG_SEED_MASK 0x007fffffL
+#define UNIPHYEF_TPG_SEED__UNIPHYEF_TPG_SEED__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_CALOUT_ERROR_LINKA__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_CALOUT_LINKA_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_CALOUT_LINKA__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_ENABLE_LINKA_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_ENABLE_LINKA__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKA_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKA__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_LINKA_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_OVERRIDE_LINKA__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_SEL_LINKA_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_SEL_LINKA__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_STEP_DELAY_LINKA_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_STEP_DELAY_LINKA__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_VALUE_LINKA_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKA__UNIPHY_IMPCAL_VALUE_LINKA__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_CALOUT_ERROR_LINKB__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_CALOUT_LINKB_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_CALOUT_LINKB__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_ENABLE_LINKB_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_ENABLE_LINKB__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKB_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKB__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_LINKB_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_OVERRIDE_LINKB__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_SEL_LINKB_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_SEL_LINKB__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_STEP_DELAY_LINKB_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_STEP_DELAY_LINKB__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_VALUE_LINKB_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKB__UNIPHY_IMPCAL_VALUE_LINKB__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_CALOUT_ERROR_LINKC__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_CALOUT_LINKC_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_CALOUT_LINKC__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_ENABLE_LINKC_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_ENABLE_LINKC__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKC_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKC__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_LINKC_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_OVERRIDE_LINKC__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_SEL_LINKC_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_SEL_LINKC__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_STEP_DELAY_LINKC_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_STEP_DELAY_LINKC__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_VALUE_LINKC_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKC__UNIPHY_IMPCAL_VALUE_LINKC__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_CALOUT_ERROR_LINKD__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_CALOUT_LINKD_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_CALOUT_LINKD__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_ENABLE_LINKD_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_ENABLE_LINKD__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKD_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKD__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_LINKD_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_OVERRIDE_LINKD__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_SEL_LINKD_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_SEL_LINKD__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_STEP_DELAY_LINKD_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_STEP_DELAY_LINKD__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_VALUE_LINKD_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKD__UNIPHY_IMPCAL_VALUE_LINKD__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_CALOUT_ERROR_LINKE__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_CALOUT_LINKE_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_CALOUT_LINKE__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_ENABLE_LINKE_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_ENABLE_LINKE__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKE_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKE__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_LINKE_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_OVERRIDE_LINKE__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_SEL_LINKE_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_SEL_LINKE__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_STEP_DELAY_LINKE_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_STEP_DELAY_LINKE__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_VALUE_LINKE_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKE__UNIPHY_IMPCAL_VALUE_LINKE__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_AK_MASK 0x00000400L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_AK__SHIFT 0x0000000a
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF_MASK 0x00000200L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_CALOUT_ERROR_LINKF__SHIFT 0x00000009
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_CALOUT_LINKF_MASK 0x00000100L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_CALOUT_LINKF__SHIFT 0x00000008
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_ENABLE_LINKF_MASK 0x00000001L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_ENABLE_LINKF__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKF_MASK 0x10000000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_ENABLE_LINKF__SHIFT 0x0000001c
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_LINKF_MASK 0x0f000000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_OVERRIDE_LINKF__SHIFT 0x00000018
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_SEL_LINKF_MASK 0x40000000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_SEL_LINKF__SHIFT 0x0000001e
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_STEP_DELAY_LINKF_MASK 0x00f00000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_STEP_DELAY_LINKF__SHIFT 0x00000014
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_VALUE_LINKF_MASK 0x000f0000L
+#define UNIPHY_IMPCAL_LINKF__UNIPHY_IMPCAL_VALUE_LINKF__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_PERIOD__UNIPHY_IMPCAL_PERIOD_MASK 0xffffffffL
+#define UNIPHY_IMPCAL_PERIOD__UNIPHY_IMPCAL_PERIOD__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKA_MASK 0x00007fffL
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKA__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKB_MASK 0x7fff0000L
+#define UNIPHY_IMPCAL_PSW_AB__UNIPHY_IMPCAL_PSW_LINKB__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKC_MASK 0x00007fffL
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKC__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKD_MASK 0x7fff0000L
+#define UNIPHY_IMPCAL_PSW_CD__UNIPHY_IMPCAL_PSW_LINKD__SHIFT 0x00000010
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKE_MASK 0x00007fffL
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKE__SHIFT 0x00000000
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKF_MASK 0x7fff0000L
+#define UNIPHY_IMPCAL_PSW_EF__UNIPHY_IMPCAL_PSW_LINKF__SHIFT 0x00000010
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL0_INVERT_MASK 0x00001000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL0_INVERT__SHIFT 0x0000000c
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL1_INVERT_MASK 0x00002000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL1_INVERT__SHIFT 0x0000000d
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL2_INVERT_MASK 0x00004000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL2_INVERT__SHIFT 0x0000000e
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL3_INVERT_MASK 0x00008000L
+#define UNIPHY_LINK_CNTL__UNIPHY_CHANNEL3_INVERT__SHIFT 0x0000000f
+#define UNIPHY_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY_MASK 0x00700000L
+#define UNIPHY_LINK_CNTL__UNIPHY_LANE_STAGGER_DELAY__SHIFT 0x00000014
+#define UNIPHY_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK_MASK 0x00030000L
+#define UNIPHY_LINK_CNTL__UNIPHY_LINK_ENABLE_HPD_MASK__SHIFT 0x00000010
+#define UNIPHY_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION_MASK 0x00000700L
+#define UNIPHY_LINK_CNTL__UNIPHY_MINIMUM_PIXVLD_LOW_DURATION__SHIFT 0x00000008
+#define UNIPHY_LINK_CNTL__UNIPHY_PFREQCHG_MASK 0x00000001L
+#define UNIPHY_LINK_CNTL__UNIPHY_PFREQCHG__SHIFT 0x00000000
+#define UNIPHY_LINK_CNTL__UNIPHY_PIXVLD_RESET_MASK 0x00000010L
+#define UNIPHY_LINK_CNTL__UNIPHY_PIXVLD_RESET__SHIFT 0x00000004
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_BW_CNTL_MASK 0x00ff0000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_BW_CNTL__SHIFT 0x00000010
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLK_EN_MASK 0x00000008L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLK_EN__SHIFT 0x00000003
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLKPH_EN_MASK 0x000000f0L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_CLKPH_EN__SHIFT 0x00000004
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_ENABLE_MASK 0x00000001L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_ENABLE__SHIFT 0x00000000
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_EXT_RESET_EN_MASK 0x00000004L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_EXT_RESET_EN__SHIFT 0x00000002
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_LF_CNTL_MASK 0x00007f00L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_LF_CNTL__SHIFT 0x00000008
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_RESET_MASK 0x00000002L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_RESET__SHIFT 0x00000001
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_EN_MASK 0x02000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_EN__SHIFT 0x00000019
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_SRC_MASK 0x01000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_BYPCLK_SRC__SHIFT 0x00000018
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_VCTL_ADC_EN_MASK 0x04000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_PLL_TEST_VCTL_ADC_EN__SHIFT 0x0000001a
+#define UNIPHY_PLL_CONTROL1__UNIPHY_VCO_MODE_MASK 0x30000000L
+#define UNIPHY_PLL_CONTROL1__UNIPHY_VCO_MODE__SHIFT 0x0000001c
+#define UNIPHY_PLL_CONTROL2__UNIPHY_CLKINV_MASK 0x00002000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_CLKINV__SHIFT 0x0000000d
+#define UNIPHY_PLL_CONTROL2__UNIPHY_DPLLSEL_MASK 0x0000000cL
+#define UNIPHY_PLL_CONTROL2__UNIPHY_DPLLSEL__SHIFT 0x00000002
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_EN_MASK 0x00001000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_EN__SHIFT 0x0000000c
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_SEL_MASK 0x00000010L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IDCLK_SEL__SHIFT 0x00000004
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IPCIE_REFCLK_SEL_MASK 0x00000020L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IPCIE_REFCLK_SEL__SHIFT 0x00000005
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IXTALIN_SEL_MASK 0x00000040L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_IXTALIN_SEL__SHIFT 0x00000006
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PCIEREF_CLK_EN_MASK 0x00000800L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PCIEREF_CLK_EN__SHIFT 0x0000000b
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIVFRAC_SEL_MASK 0x00100000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIVFRAC_SEL__SHIFT 0x00000014
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIV_SEL_MASK 0xe0000000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PDIV_SEL__SHIFT 0x0000001d
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_DISPCLK_MODE_MASK 0x00000003L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_DISPCLK_MODE__SHIFT 0x00000000
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFCLK_SRC_MASK 0x00000700L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFCLK_SRC__SHIFT 0x00000008
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFDIV_MASK 0x1f000000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_REFDIV__SHIFT 0x00000018
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_TEST_FBDIV_FRAC_BYPASS_MASK 0x00080000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_TEST_FBDIV_FRAC_BYPASS__SHIFT 0x00000013
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_VTOI_BIAS_CNTL_MASK 0x00010000L
+#define UNIPHY_PLL_CONTROL2__UNIPHY_PLL_VTOI_BIAS_CNTL__SHIFT 0x00000010
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV_FRACTION_MASK 0x0000fffcL
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV_FRACTION__SHIFT 0x00000002
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV_MASK 0x0fff0000L
+#define UNIPHY_PLL_FBDIV__UNIPHY_PLL_FBDIV__SHIFT 0x00000010
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_DSMOD_EN_MASK 0x00001000L
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_DSMOD_EN__SHIFT 0x0000000c
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_EN_MASK 0x00002000L
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_EN__SHIFT 0x0000000d
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_STEP_NUM_MASK 0x00000fffL
+#define UNIPHY_PLL_SS_CNTL__UNIPHY_PLL_SS_STEP_NUM__SHIFT 0x00000000
+#define UNIPHY_PLL_SS_STEP_SIZE__UNIPHY_PLL_SS_STEP_SIZE_MASK 0x03ffffffL
+#define UNIPHY_PLL_SS_STEP_SIZE__UNIPHY_PLL_SS_STEP_SIZE__SHIFT 0x00000000
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ0P45_MASK 0x000f0000L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ0P45__SHIFT 0x00000010
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P00_MASK 0x00000f00L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P00__SHIFT 0x00000008
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P25_MASK 0x0000f000L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGADJ1P25__SHIFT 0x0000000c
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGPDN_MASK 0x00000001L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BGPDN__SHIFT 0x00000000
+#define UNIPHY_POWER_CONTROL__UNIPHY_BIASREF_SEL_MASK 0x00000004L
+#define UNIPHY_POWER_CONTROL__UNIPHY_BIASREF_SEL__SHIFT 0x00000002
+#define UNIPHY_POWER_CONTROL__UNIPHY_RST_LOGIC_MASK 0x00000002L
+#define UNIPHY_POWER_CONTROL__UNIPHY_RST_LOGIC__SHIFT 0x00000001
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_ERROR_MASK 0x01f00000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_ERROR__SHIFT 0x00000014
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_RESET_MASK 0x00008000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_RESET__SHIFT 0x0000000f
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_SEL_MASK 0x00010000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_DIG_BIST_SEL__SHIFT 0x00000010
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_INTRESET_MASK 0x20000000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_INTRESET__SHIFT 0x0000001d
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_FREQ_LOCK_MASK 0x10000000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_FREQ_LOCK__SHIFT 0x0000001c
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_VCTL_ADC_MASK 0x0e000000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_PLL_TEST_VCTL_ADC__SHIFT 0x00000019
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_CNTL_MASK 0x0000001fL
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_CNTL__SHIFT 0x00000000
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_VCTL_EN_MASK 0x00020000L
+#define UNIPHY_REG_TEST_OUTPUT__UNIPHY_TEST_VCTL_EN__SHIFT 0x00000011
+#define UNIPHY_SOFT_RESET__DSYNCA_SOFT_RESET_MASK 0x00000001L
+#define UNIPHY_SOFT_RESET__DSYNCA_SOFT_RESET__SHIFT 0x00000000
+#define UNIPHY_SOFT_RESET__DSYNCB_SOFT_RESET_MASK 0x00000002L
+#define UNIPHY_SOFT_RESET__DSYNCB_SOFT_RESET__SHIFT 0x00000001
+#define UNIPHY_SOFT_RESET__DSYNCC_SOFT_RESET_MASK 0x00000004L
+#define UNIPHY_SOFT_RESET__DSYNCC_SOFT_RESET__SHIFT 0x00000002
+#define UNIPHY_SOFT_RESET__DSYNCD_SOFT_RESET_MASK 0x00000008L
+#define UNIPHY_SOFT_RESET__DSYNCD_SOFT_RESET__SHIFT 0x00000003
+#define UNIPHY_SOFT_RESET__DSYNCE_SOFT_RESET_MASK 0x00000010L
+#define UNIPHY_SOFT_RESET__DSYNCE_SOFT_RESET__SHIFT 0x00000004
+#define UNIPHY_SOFT_RESET__DSYNCF_SOFT_RESET_MASK 0x00000020L
+#define UNIPHY_SOFT_RESET__DSYNCF_SOFT_RESET__SHIFT 0x00000005
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR0_MASK 0x00000007L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR0__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR1_MASK 0x00000070L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR1__SHIFT 0x00000004
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR2_MASK 0x00000700L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR2__SHIFT 0x00000008
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR3_MASK 0x00007000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR3__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR4_MASK 0x00070000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_PREMPH_STR4__SHIFT 0x00000010
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS0_MASK 0x00300000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS0__SHIFT 0x00000014
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS1_MASK 0x00c00000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS1__SHIFT 0x00000016
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS2_MASK 0x03000000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS2__SHIFT 0x00000018
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS3_MASK 0x0c000000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS3__SHIFT 0x0000001a
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS4_MASK 0x30000000L
+#define UNIPHY_TX_CONTROL1__UNIPHY_TX_VS4__SHIFT 0x0000001c
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH0_PC_MASK 0x00000003L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH0_PC__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH1_PC_MASK 0x00000030L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH1_PC__SHIFT 0x00000004
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH2_PC_MASK 0x00000300L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH2_PC__SHIFT 0x00000008
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH3_PC_MASK 0x00003000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH3_PC__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH4_PC_MASK 0x00030000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH4_PC__SHIFT 0x00000010
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH_SEL_MASK 0x00100000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_PREMPH_SEL__SHIFT 0x00000014
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT0_CPSEL_MASK 0x00600000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT0_CPSEL__SHIFT 0x00000015
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT1_CPSEL_MASK 0x01800000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT1_CPSEL__SHIFT 0x00000017
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT2_CPSEL_MASK 0x06000000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT2_CPSEL__SHIFT 0x00000019
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT3_CPSEL_MASK 0x18000000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT3_CPSEL__SHIFT 0x0000001b
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT4_CPSEL_MASK 0x60000000L
+#define UNIPHY_TX_CONTROL2__UNIPHY_RT4_CPSEL__SHIFT 0x0000001d
+#define UNIPHY_TX_CONTROL3__UNIPHY_LVDS_PULLDWN_MASK 0x80000000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_LVDS_PULLDWN__SHIFT 0x0000001f
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL0_MASK 0x00100000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL0__SHIFT 0x00000014
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL1_MASK 0x00200000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL1__SHIFT 0x00000015
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL2_MASK 0x00400000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL2__SHIFT 0x00000016
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL3_MASK 0x00800000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PESEL3__SHIFT 0x00000017
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_CLK_MASK 0x000000f0L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_CLK__SHIFT 0x00000004
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_DAT_MASK 0x00000f00L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_CS_DAT__SHIFT 0x00000008
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_CLK_MASK 0x00000003L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_CLK__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_DAT_MASK 0x0000000cL
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_PW_DAT__SHIFT 0x00000002
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_CLK_MASK 0x00007000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_CLK__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_DAT_MASK 0x00070000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_PREMPH_STR_DAT__SHIFT 0x00000010
+#define UNIPHY_TX_CONTROL3__UNIPHY_TX_VS_ADJ_MASK 0x1f000000L
+#define UNIPHY_TX_CONTROL3__UNIPHY_TX_VS_ADJ__SHIFT 0x00000018
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_CLK_MASK 0x0000001fL
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_CLK__SHIFT 0x00000000
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_DAT_MASK 0x000003e0L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_NVS_DAT__SHIFT 0x00000005
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_CLK_MASK 0x07000000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_CLK__SHIFT 0x00000018
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_DAT_MASK 0x70000000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_OP_DAT__SHIFT 0x0000001c
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_CLK_MASK 0x0001f000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_CLK__SHIFT 0x0000000c
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_DAT_MASK 0x003e0000L
+#define UNIPHY_TX_CONTROL4__UNIPHY_TX_PVS_DAT__SHIFT 0x00000011
+#define VGA25_PPLL_ANALOG__VGA25_CAL_MODE_MASK 0x0000001fL
+#define VGA25_PPLL_ANALOG__VGA25_CAL_MODE__SHIFT 0x00000000
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_CP_MASK 0x00000f00L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_CP__SHIFT 0x00000008
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_IBIAS_MASK 0xff000000L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_IBIAS__SHIFT 0x00000018
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_LF_MODE_MASK 0x001ff000L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_LF_MODE__SHIFT 0x0000000c
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define VGA25_PPLL_ANALOG__VGA25_PPLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV_MASK 0x07ff0000L
+#define VGA25_PPLL_FB_DIV__VGA25_PPLL_FB_DIV__SHIFT 0x00000010
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define VGA25_PPLL_POST_DIV__VGA25_PPLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define VGA25_PPLL_REF_DIV__VGA25_PPLL_REF_DIV_MASK 0x000003ffL
+#define VGA25_PPLL_REF_DIV__VGA25_PPLL_REF_DIV__SHIFT 0x00000000
+#define VGA28_PPLL_ANALOG__VGA28_CAL_MODE_MASK 0x0000001fL
+#define VGA28_PPLL_ANALOG__VGA28_CAL_MODE__SHIFT 0x00000000
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_CP_MASK 0x00000f00L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_CP__SHIFT 0x00000008
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_IBIAS_MASK 0xff000000L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_IBIAS__SHIFT 0x00000018
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_LF_MODE_MASK 0x001ff000L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_LF_MODE__SHIFT 0x0000000c
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define VGA28_PPLL_ANALOG__VGA28_PPLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV_MASK 0x07ff0000L
+#define VGA28_PPLL_FB_DIV__VGA28_PPLL_FB_DIV__SHIFT 0x00000010
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define VGA28_PPLL_POST_DIV__VGA28_PPLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define VGA28_PPLL_REF_DIV__VGA28_PPLL_REF_DIV_MASK 0x000003ffL
+#define VGA28_PPLL_REF_DIV__VGA28_PPLL_REF_DIV__SHIFT 0x00000000
+#define VGA41_PPLL_ANALOG__VGA41_CAL_MODE_MASK 0x0000001fL
+#define VGA41_PPLL_ANALOG__VGA41_CAL_MODE__SHIFT 0x00000000
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_CP_MASK 0x00000f00L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_CP__SHIFT 0x00000008
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_IBIAS_MASK 0xff000000L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_IBIAS__SHIFT 0x00000018
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_LF_MODE_MASK 0x001ff000L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_LF_MODE__SHIFT 0x0000000c
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_PFD_PULSE_SEL_MASK 0x00000060L
+#define VGA41_PPLL_ANALOG__VGA41_PPLL_PFD_PULSE_SEL__SHIFT 0x00000005
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION_CNTL_MASK 0x00000030L
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION_CNTL__SHIFT 0x00000004
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION_MASK 0x0000000fL
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_FRACTION__SHIFT 0x00000000
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV_MASK 0x07ff0000L
+#define VGA41_PPLL_FB_DIV__VGA41_PPLL_FB_DIV__SHIFT 0x00000010
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_DVOCLK_MASK 0x00007f00L
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_DVOCLK__SHIFT 0x00000008
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_IDCLK_MASK 0x007f0000L
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_IDCLK__SHIFT 0x00000010
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_PIXCLK_MASK 0x0000007fL
+#define VGA41_PPLL_POST_DIV__VGA41_PPLL_POST_DIV_PIXCLK__SHIFT 0x00000000
+#define VGA41_PPLL_REF_DIV__VGA41_PPLL_REF_DIV_MASK 0x000003ffL
+#define VGA41_PPLL_REF_DIV__VGA41_PPLL_REF_DIV__SHIFT 0x00000000
+#define VGA_CACHE_CONTROL__VGA_DCCIF_W256ONLY_MASK 0x00100000L
+#define VGA_CACHE_CONTROL__VGA_DCCIF_W256ONLY__SHIFT 0x00000014
+#define VGA_CACHE_CONTROL__VGA_DCCIF_WC_TIMEOUT_MASK 0x3f000000L
+#define VGA_CACHE_CONTROL__VGA_DCCIF_WC_TIMEOUT__SHIFT 0x00000018
+#define VGA_CACHE_CONTROL__VGA_READ_BUFFER_INVALIDATE_MASK 0x00010000L
+#define VGA_CACHE_CONTROL__VGA_READ_BUFFER_INVALIDATE__SHIFT 0x00000010
+#define VGA_CACHE_CONTROL__VGA_READ_CACHE_DISABLE_MASK 0x00000100L
+#define VGA_CACHE_CONTROL__VGA_READ_CACHE_DISABLE__SHIFT 0x00000008
+#define VGA_CACHE_CONTROL__VGA_WRITE_THROUGH_CACHE_DIS_MASK 0x00000001L
+#define VGA_CACHE_CONTROL__VGA_WRITE_THROUGH_CACHE_DIS__SHIFT 0x00000000
+#define VGADCC_DBG_DCCIF_C__DBG_DCCIF_C_MASK 0xffffffffL
+#define VGADCC_DBG_DCCIF_C__DBG_DCCIF_C__SHIFT 0x00000000
+#define VGA_DEBUG_READBACK_DATA__VGA_DEBUG_READBACK_DATA_MASK 0xffffffffL
+#define VGA_DEBUG_READBACK_DATA__VGA_DEBUG_READBACK_DATA__SHIFT 0x00000000
+#define VGA_DEBUG_READBACK_INDEX__VGA_DEBUG_READBACK_INDEX_MASK 0x000000ffL
+#define VGA_DEBUG_READBACK_INDEX__VGA_DEBUG_READBACK_INDEX__SHIFT 0x00000000
+#define VGA_DISPBUF1_SURFACE_ADDR__VGA_DISPBUF1_SURFACE_ADDR_MASK 0x01ffffffL
+#define VGA_DISPBUF1_SURFACE_ADDR__VGA_DISPBUF1_SURFACE_ADDR__SHIFT 0x00000000
+#define VGA_DISPBUF2_SURFACE_ADDR__VGA_DISPBUF2_SURFACE_ADDR_MASK 0x01ffffffL
+#define VGA_DISPBUF2_SURFACE_ADDR__VGA_DISPBUF2_SURFACE_ADDR__SHIFT 0x00000000
+#define VGA_HDP_CONTROL__VGA_MEMORY_DISABLE_MASK 0x00000010L
+#define VGA_HDP_CONTROL__VGA_MEMORY_DISABLE__SHIFT 0x00000004
+#define VGA_HDP_CONTROL__VGA_MEM_PAGE_SELECT_EN_MASK 0x00000001L
+#define VGA_HDP_CONTROL__VGA_MEM_PAGE_SELECT_EN__SHIFT 0x00000000
+#define VGA_HDP_CONTROL__VGA_RBBM_LOCK_DISABLE_MASK 0x00000100L
+#define VGA_HDP_CONTROL__VGA_RBBM_LOCK_DISABLE__SHIFT 0x00000008
+#define VGA_HDP_CONTROL__VGA_SOFT_RESET_MASK 0x00010000L
+#define VGA_HDP_CONTROL__VGA_SOFT_RESET__SHIFT 0x00000010
+#define VGA_HDP_CONTROL__VGA_TEST_RESET_CONTROL_MASK 0x01000000L
+#define VGA_HDP_CONTROL__VGA_TEST_RESET_CONTROL__SHIFT 0x00000018
+#define VGA_HW_DEBUG__VGA_HW_DEBUG_MASK 0xffffffffL
+#define VGA_HW_DEBUG__VGA_HW_DEBUG__SHIFT 0x00000000
+#define VGA_INTERRUPT_CONTROL__VGA_DISPLAY_SWITCH_INT_MASK_MASK 0x00010000L
+#define VGA_INTERRUPT_CONTROL__VGA_DISPLAY_SWITCH_INT_MASK__SHIFT 0x00000010
+#define VGA_INTERRUPT_CONTROL__VGA_MEM_ACCESS_INT_MASK_MASK 0x00000001L
+#define VGA_INTERRUPT_CONTROL__VGA_MEM_ACCESS_INT_MASK__SHIFT 0x00000000
+#define VGA_INTERRUPT_CONTROL__VGA_MODE_AUTO_TRIGGER_INT_MASK_MASK 0x01000000L
+#define VGA_INTERRUPT_CONTROL__VGA_MODE_AUTO_TRIGGER_INT_MASK__SHIFT 0x00000018
+#define VGA_INTERRUPT_CONTROL__VGA_REG_ACCESS_INT_MASK_MASK 0x00000100L
+#define VGA_INTERRUPT_CONTROL__VGA_REG_ACCESS_INT_MASK__SHIFT 0x00000008
+#define VGA_INTERRUPT_STATUS__VGA_DISPLAY_SWITCH_INT_STATUS_MASK 0x00000004L
+#define VGA_INTERRUPT_STATUS__VGA_DISPLAY_SWITCH_INT_STATUS__SHIFT 0x00000002
+#define VGA_INTERRUPT_STATUS__VGA_MEM_ACCESS_INT_STATUS_MASK 0x00000001L
+#define VGA_INTERRUPT_STATUS__VGA_MEM_ACCESS_INT_STATUS__SHIFT 0x00000000
+#define VGA_INTERRUPT_STATUS__VGA_MODE_AUTO_TRIGGER_INT_STATUS_MASK 0x00000008L
+#define VGA_INTERRUPT_STATUS__VGA_MODE_AUTO_TRIGGER_INT_STATUS__SHIFT 0x00000003
+#define VGA_INTERRUPT_STATUS__VGA_REG_ACCESS_INT_STATUS_MASK 0x00000002L
+#define VGA_INTERRUPT_STATUS__VGA_REG_ACCESS_INT_STATUS__SHIFT 0x00000001
+#define VGA_MAIN_CONTROL__VGA_CRTC_TIMEOUT_MASK 0x00000003L
+#define VGA_MAIN_CONTROL__VGA_CRTC_TIMEOUT__SHIFT 0x00000000
+#define VGA_MAIN_CONTROL__VGA_EXTERNAL_DAC_SENSE_MASK 0x20000000L
+#define VGA_MAIN_CONTROL__VGA_EXTERNAL_DAC_SENSE__SHIFT 0x0000001d
+#define VGA_MAIN_CONTROL__VGA_MAIN_TEST_VSTATUS_NO_DISPLAY_CRTC_TIMEOUT_MASK 0x80000000L
+#define VGA_MAIN_CONTROL__VGA_MAIN_TEST_VSTATUS_NO_DISPLAY_CRTC_TIMEOUT__SHIFT 0x0000001f
+#define VGA_MAIN_CONTROL__VGA_READBACK_CRT_INTR_SOURCE_SELECT_MASK 0x03000000L
+#define VGA_MAIN_CONTROL__VGA_READBACK_CRT_INTR_SOURCE_SELECT__SHIFT 0x00000018
+#define VGA_MAIN_CONTROL__VGA_READBACK_NO_DISPLAY_SOURCE_SELECT_MASK 0x00030000L
+#define VGA_MAIN_CONTROL__VGA_READBACK_NO_DISPLAY_SOURCE_SELECT__SHIFT 0x00000010
+#define VGA_MAIN_CONTROL__VGA_READBACK_SENSE_SWITCH_SELECT_MASK 0x04000000L
+#define VGA_MAIN_CONTROL__VGA_READBACK_SENSE_SWITCH_SELECT__SHIFT 0x0000001a
+#define VGA_MAIN_CONTROL__VGA_READBACK_VGA_VSTATUS_SOURCE_SELECT_MASK 0x00000300L
+#define VGA_MAIN_CONTROL__VGA_READBACK_VGA_VSTATUS_SOURCE_SELECT__SHIFT 0x00000008
+#define VGA_MAIN_CONTROL__VGA_READ_URGENT_ENABLE_MASK 0x08000000L
+#define VGA_MAIN_CONTROL__VGA_READ_URGENT_ENABLE__SHIFT 0x0000001b
+#define VGA_MAIN_CONTROL__VGA_RENDER_TIMEOUT_COUNT_MASK 0x00000018L
+#define VGA_MAIN_CONTROL__VGA_RENDER_TIMEOUT_COUNT__SHIFT 0x00000003
+#define VGA_MAIN_CONTROL__VGA_VIRTUAL_VERTICAL_RETRACE_DURATION_MASK 0x000000e0L
+#define VGA_MAIN_CONTROL__VGA_VIRTUAL_VERTICAL_RETRACE_DURATION__SHIFT 0x00000005
+#define VGA_MAIN_CONTROL__VGA_WRITES_URGENT_ENABLE_MASK 0x10000000L
+#define VGA_MAIN_CONTROL__VGA_WRITES_URGENT_ENABLE__SHIFT 0x0000001c
+#define VGA_MEMORY_BASE_ADDRESS_HIGH__VGA_MEMORY_BASE_ADDRESS_HIGH_MASK 0x000000ffL
+#define VGA_MEMORY_BASE_ADDRESS_HIGH__VGA_MEMORY_BASE_ADDRESS_HIGH__SHIFT 0x00000000
+#define VGA_MEMORY_BASE_ADDRESS__VGA_MEMORY_BASE_ADDRESS_MASK 0xffffffffL
+#define VGA_MEMORY_BASE_ADDRESS__VGA_MEMORY_BASE_ADDRESS__SHIFT 0x00000000
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE0_ADDR_MASK 0x000003ffL
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE0_ADDR__SHIFT 0x00000000
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE1_ADDR_MASK 0x03ff0000L
+#define VGA_MEM_READ_PAGE_ADDR__VGA_MEM_READ_PAGE1_ADDR__SHIFT 0x00000010
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE0_ADDR_MASK 0x000003ffL
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE0_ADDR__SHIFT 0x00000000
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE1_ADDR_MASK 0x03ff0000L
+#define VGA_MEM_WRITE_PAGE_ADDR__VGA_MEM_WRITE_PAGE1_ADDR__SHIFT 0x00000010
+#define VGA_MODE_CONTROL__VGA_128K_APERTURE_PAGING_MASK 0x00000100L
+#define VGA_MODE_CONTROL__VGA_128K_APERTURE_PAGING__SHIFT 0x00000008
+#define VGA_MODE_CONTROL__VGA_ATI_LINEAR_MASK 0x00000001L
+#define VGA_MODE_CONTROL__VGA_ATI_LINEAR__SHIFT 0x00000000
+#define VGA_MODE_CONTROL__VGA_LUT_PALETTE_UPDATE_MODE_MASK 0x00000030L
+#define VGA_MODE_CONTROL__VGA_LUT_PALETTE_UPDATE_MODE__SHIFT 0x00000004
+#define VGA_MODE_CONTROL__VGA_TEXT_132_COLUMNS_EN_MASK 0x00010000L
+#define VGA_MODE_CONTROL__VGA_TEXT_132_COLUMNS_EN__SHIFT 0x00000010
+#define VGA_RENDER_CONTROL__VGA_BLINK_MODE_MASK 0x00000060L
+#define VGA_RENDER_CONTROL__VGA_BLINK_MODE__SHIFT 0x00000005
+#define VGA_RENDER_CONTROL__VGA_BLINK_RATE_MASK 0x0000001fL
+#define VGA_RENDER_CONTROL__VGA_BLINK_RATE__SHIFT 0x00000000
+#define VGA_RENDER_CONTROL__VGA_CURSOR_BLINK_INVERT_MASK 0x00000080L
+#define VGA_RENDER_CONTROL__VGA_CURSOR_BLINK_INVERT__SHIFT 0x00000007
+#define VGA_RENDER_CONTROL__VGA_EXTD_ADDR_COUNT_ENABLE_MASK 0x00000100L
+#define VGA_RENDER_CONTROL__VGA_EXTD_ADDR_COUNT_ENABLE__SHIFT 0x00000008
+#define VGA_RENDER_CONTROL__VGA_LOCK_8DOT_MASK 0x01000000L
+#define VGA_RENDER_CONTROL__VGA_LOCK_8DOT__SHIFT 0x00000018
+#define VGA_RENDER_CONTROL__VGAREG_LINECMP_COMPATIBILITY_SEL_MASK 0x02000000L
+#define VGA_RENDER_CONTROL__VGAREG_LINECMP_COMPATIBILITY_SEL__SHIFT 0x00000019
+#define VGA_RENDER_CONTROL__VGA_VSTATUS_CNTL_MASK 0x00030000L
+#define VGA_RENDER_CONTROL__VGA_VSTATUS_CNTL__SHIFT 0x00000010
+#define VGA_SEQUENCER_RESET_CONTROL__D1_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000001L
+#define VGA_SEQUENCER_RESET_CONTROL__D1_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000000
+#define VGA_SEQUENCER_RESET_CONTROL__D1_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000100L
+#define VGA_SEQUENCER_RESET_CONTROL__D1_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x00000008
+#define VGA_SEQUENCER_RESET_CONTROL__D2_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000002L
+#define VGA_SEQUENCER_RESET_CONTROL__D2_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000001
+#define VGA_SEQUENCER_RESET_CONTROL__D2_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000200L
+#define VGA_SEQUENCER_RESET_CONTROL__D2_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x00000009
+#define VGA_SEQUENCER_RESET_CONTROL__D3_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000004L
+#define VGA_SEQUENCER_RESET_CONTROL__D3_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000002
+#define VGA_SEQUENCER_RESET_CONTROL__D3_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000400L
+#define VGA_SEQUENCER_RESET_CONTROL__D3_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000a
+#define VGA_SEQUENCER_RESET_CONTROL__D4_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000008L
+#define VGA_SEQUENCER_RESET_CONTROL__D4_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000003
+#define VGA_SEQUENCER_RESET_CONTROL__D4_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00000800L
+#define VGA_SEQUENCER_RESET_CONTROL__D4_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000b
+#define VGA_SEQUENCER_RESET_CONTROL__D5_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000010L
+#define VGA_SEQUENCER_RESET_CONTROL__D5_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000004
+#define VGA_SEQUENCER_RESET_CONTROL__D5_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00001000L
+#define VGA_SEQUENCER_RESET_CONTROL__D5_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000c
+#define VGA_SEQUENCER_RESET_CONTROL__D6_BLANK_DISPLAY_WHEN_SEQUENCER_RESET_MASK 0x00000020L
+#define VGA_SEQUENCER_RESET_CONTROL__D6_BLANK_DISPLAY_WHEN_SEQUENCER_RESET__SHIFT 0x00000005
+#define VGA_SEQUENCER_RESET_CONTROL__D6_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET_MASK 0x00002000L
+#define VGA_SEQUENCER_RESET_CONTROL__D6_DISABLE_SYNCS_AND_DE_WHEN_SEQUENCER_RESET__SHIFT 0x0000000d
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_ENABLE_MASK 0x00010000L
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_ENABLE__SHIFT 0x00000010
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_INDEX_SELECT_MASK 0x00fc0000L
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_INDEX_SELECT__SHIFT 0x00000012
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_REGISTER_SELECT_MASK 0x00020000L
+#define VGA_SEQUENCER_RESET_CONTROL__VGA_MODE_AUTO_TRIGGER_REGISTER_SELECT__SHIFT 0x00000011
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_A_MASK 0x00000007L
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_A__SHIFT 0x00000000
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_B_MASK 0x00000700L
+#define VGA_SOURCE_SELECT__VGA_SOURCE_SEL_B__SHIFT 0x00000008
+#define VGA_STATUS_CLEAR__VGA_DISPLAY_SWITCH_INT_CLEAR_MASK 0x00010000L
+#define VGA_STATUS_CLEAR__VGA_DISPLAY_SWITCH_INT_CLEAR__SHIFT 0x00000010
+#define VGA_STATUS_CLEAR__VGA_MEM_ACCESS_INT_CLEAR_MASK 0x00000001L
+#define VGA_STATUS_CLEAR__VGA_MEM_ACCESS_INT_CLEAR__SHIFT 0x00000000
+#define VGA_STATUS_CLEAR__VGA_MODE_AUTO_TRIGGER_INT_CLEAR_MASK 0x01000000L
+#define VGA_STATUS_CLEAR__VGA_MODE_AUTO_TRIGGER_INT_CLEAR__SHIFT 0x00000018
+#define VGA_STATUS_CLEAR__VGA_REG_ACCESS_INT_CLEAR_MASK 0x00000100L
+#define VGA_STATUS_CLEAR__VGA_REG_ACCESS_INT_CLEAR__SHIFT 0x00000008
+#define VGA_STATUS__VGA_DISPLAY_SWITCH_STATUS_MASK 0x00000004L
+#define VGA_STATUS__VGA_DISPLAY_SWITCH_STATUS__SHIFT 0x00000002
+#define VGA_STATUS__VGA_MEM_ACCESS_STATUS_MASK 0x00000001L
+#define VGA_STATUS__VGA_MEM_ACCESS_STATUS__SHIFT 0x00000000
+#define VGA_STATUS__VGA_MODE_AUTO_TRIGGER_STATUS_MASK 0x00000008L
+#define VGA_STATUS__VGA_MODE_AUTO_TRIGGER_STATUS__SHIFT 0x00000003
+#define VGA_STATUS__VGA_REG_ACCESS_STATUS_MASK 0x00000002L
+#define VGA_STATUS__VGA_REG_ACCESS_STATUS__SHIFT 0x00000001
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_HEIGHT_SELECT_MASK 0x00000300L
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_HEIGHT_SELECT__SHIFT 0x00000008
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_PITCH_SELECT_MASK 0x00000003L
+#define VGA_SURFACE_PITCH_SELECT__VGA_SURFACE_PITCH_SELECT__SHIFT 0x00000000
+#define VGA_TEST_CONTROL__VGA_TEST_ENABLE_MASK 0x00000001L
+#define VGA_TEST_CONTROL__VGA_TEST_ENABLE__SHIFT 0x00000000
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DISPBUF_SELECT_MASK 0x01000000L
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DISPBUF_SELECT__SHIFT 0x00000018
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DONE_MASK 0x00010000L
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_DONE__SHIFT 0x00000010
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_START_MASK 0x00000100L
+#define VGA_TEST_CONTROL__VGA_TEST_RENDER_START__SHIFT 0x00000008
+#define VGA_TEST_DEBUG_DATA__VGA_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define VGA_TEST_DEBUG_DATA__VGA_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define VGA_TEST_DEBUG_INDEX__VGA_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define VIEWPORT_SIZE__VIEWPORT_HEIGHT_MASK 0x00003fffL
+#define VIEWPORT_SIZE__VIEWPORT_HEIGHT__SHIFT 0x00000000
+#define VIEWPORT_SIZE__VIEWPORT_WIDTH_MASK 0x3fff0000L
+#define VIEWPORT_SIZE__VIEWPORT_WIDTH__SHIFT 0x00000010
+#define VIEWPORT_START__VIEWPORT_X_START_MASK 0x3fff0000L
+#define VIEWPORT_START__VIEWPORT_X_START__SHIFT 0x00000010
+#define VIEWPORT_START__VIEWPORT_Y_START_MASK 0x00003fffL
+#define VIEWPORT_START__VIEWPORT_Y_START__SHIFT 0x00000000
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_GATE_DIS_MASK 0x00008000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_GATE_DIS__SHIFT 0x0000000f
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MSTAT_GATE_DIS_MASK 0x00080000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_MSTAT_GATE_DIS__SHIFT 0x00000013
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SDYN_GATE_DIS_MASK 0x00040000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SDYN_GATE_DIS__SHIFT 0x00000012
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SSTAT_GATE_DIS_MASK 0x00100000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_G_SSTAT_GATE_DIS__SHIFT 0x00000014
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_REG_GATE_DIS_MASK 0x00010000L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_REG_GATE_DIS__SHIFT 0x00000010
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_OFF_DELAY_MASK 0x00000ff0L
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_OFF_DELAY__SHIFT 0x00000004
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_ON_DELAY_MASK 0x0000000fL
+#define XDMA_CLOCK_GATING_CNTL__XDMA_SCLK_TURN_ON_DELAY__SHIFT 0x00000000
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_CLEAR_MASK 0x00000100L
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_CLEAR__SHIFT 0x00000008
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_STATUS_MASK 0x0000000fL
+#define XDMA_IF_BIF_STATUS__XDMA_IF_BIF_ERROR_STATUS__SHIFT 0x00000000
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_ACK_MASK 0x00000400L
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_ACK__SHIFT 0x0000000a
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_MASK_MASK 0x00000200L
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_MASK__SHIFT 0x00000009
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_STAT_MASK 0x00000100L
+#define XDMA_INTERRUPT__XDMA_MSTR_MEM_URGENT_STAT__SHIFT 0x00000008
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_ACK_MASK 0x00004000L
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_ACK__SHIFT 0x0000000e
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_MASK_MASK 0x00002000L
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_MASK__SHIFT 0x0000000d
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_STAT_MASK 0x00001000L
+#define XDMA_INTERRUPT__XDMA_MSTR_UNDERFLOW_STAT__SHIFT 0x0000000c
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_ACK_MASK 0x00040000L
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_ACK__SHIFT 0x00000012
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_MASK_MASK 0x00020000L
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_MASK__SHIFT 0x00000011
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_STAT_MASK 0x00010000L
+#define XDMA_INTERRUPT__XDMA_SLV_READ_URGENT_STAT__SHIFT 0x00000010
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_ARRAY_MODE_MASK 0x0000000fL
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_ARRAY_MODE__SHIFT 0x00000000
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_HEIGHT_MASK 0x00000c00L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_HEIGHT__SHIFT 0x0000000a
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_WIDTH_MASK 0x00000300L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_BANK_WIDTH__SHIFT 0x00000008
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_MACRO_TILE_ASPECT_MASK 0x00003000L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_MACRO_TILE_ASPECT__SHIFT 0x0000000c
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_NUM_BANKS_MASK 0x00300000L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_NUM_BANKS__SHIFT 0x00000014
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_TILE_SPLIT_MASK 0x00000070L
+#define XDMA_LOCAL_SURFACE_TILING1__XDMA_LOCAL_TILE_SPLIT__SHIFT 0x00000004
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_MICRO_TILE_MODE_MASK 0x00c00000L
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_MICRO_TILE_MODE__SHIFT 0x00000016
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_CONFIG_MASK 0xf8000000L
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_CONFIG__SHIFT 0x0000001b
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_INTERLEAVE_SIZE_MASK 0x00000007L
+#define XDMA_LOCAL_SURFACE_TILING2__XDMA_LOCAL_PIPE_INTERLEAVE_SIZE__SHIFT 0x00000000
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_PRIV_MASK 0x00010000L
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_PRIV__SHIFT 0x00000010
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_SWAP_MASK 0x00000300L
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_SWAP__SHIFT 0x00000008
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_VMID_MASK 0x0000f000L
+#define XDMA_MC_PCIE_CLIENT_CONFIG__XDMA_MC_PCIE_VMID__SHIFT 0x0000000c
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_DIS_MASK 0x00000001L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_DIS__SHIFT 0x00000000
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_MODE_FORCE_MASK 0x00010000L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_LIGHT_SLEEP_MODE_FORCE__SHIFT 0x00000010
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_POWER_STATE_MASK 0xc0000000L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_POWER_STATE__SHIFT 0x0000001e
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_DIS_MASK 0x00000100L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_DIS__SHIFT 0x00000008
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_MODE_FORCE_MASK 0x01000000L
+#define XDMA_MEM_POWER_CNTL__XDMA_MEM_SHUTDOWN_MODE_FORCE__SHIFT 0x00000018
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_MSTR_CMD_URGENT_CNTL__XDMA_MSTR_CMD_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_MSTR_CNTL__XDMA_MSTR_DEBUG_MODE_MASK 0x00040000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_DEBUG_MODE__SHIFT 0x00000012
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ENABLE_MASK 0x00010000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_ENABLE__SHIFT 0x00000010
+#define XDMA_MSTR_CNTL__XDMA_MSTR_MEM_READY_MASK 0x00000200L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_MEM_READY__SHIFT 0x00000009
+#define XDMA_MSTR_CNTL__XDMA_MSTR_SOFT_RESET_MASK 0x00100000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_SOFT_RESET__SHIFT 0x00000014
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_ACTIVE_HEIGHT_MASK 0x00003fffL
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_ACTIVE_HEIGHT__SHIFT 0x00000000
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_FRAME_HEIGHT_MASK 0x3fff0000L
+#define XDMA_MSTR_HEIGHT__XDMA_MSTR_FRAME_HEIGHT__SHIFT 0x00000010
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH_MASK 0x000000ffL
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_HIGH__SHIFT 0x00000000
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR_MASK 0xffffffffL
+#define XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__XDMA_MSTR_LOCAL_SURFACE_BASE_ADDR__SHIFT 0x00000000
+#define XDMA_MSTR_LOCAL_SURFACE_PITCH__XDMA_MSTR_LOCAL_SURFACE_PITCH_MASK 0x00003fffL
+#define XDMA_MSTR_LOCAL_SURFACE_PITCH__XDMA_MSTR_LOCAL_SURFACE_PITCH__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_PRIV_MASK 0x00010000L
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_PRIV__SHIFT 0x00000010
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_SWAP_MASK 0x00000300L
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_SWAP__SHIFT 0x00000008
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_VMID_MASK 0x0000f000L
+#define XDMA_MSTR_MEM_CLIENT_CONFIG__XDMA_MSTR_MEM_CLIENT_VMID__SHIFT 0x0000000c
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_CLR_MASK 0x00010000L
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_CLR__SHIFT 0x00000010
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_MASK 0x00003000L
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK__SHIFT 0x0000000c
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_TAG_MASK 0x000003ffL
+#define XDMA_MSTR_MEM_NACK_STATUS__XDMA_MSTR_MEM_NACK_TAG__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_CLIENT_STALL_MASK 0x00000001L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_CLIENT_STALL__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_STALL_DELAY_MASK 0x0000f000L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_STALL_DELAY__SHIFT 0x0000000c
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LIMIT_MASK 0x000000f0L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_LIMIT__SHIFT 0x00000004
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_TIMER_MASK 0xffff0000L
+#define XDMA_MSTR_MEM_URGENT_CNTL__XDMA_MSTR_MEM_URGENT_TIMER__SHIFT 0x00000010
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_CLR_MASK 0x00010000L
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_CLR__SHIFT 0x00000010
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_MASK 0x00003000L
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK__SHIFT 0x0000000c
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_TAG_MASK 0x000003ffL
+#define XDMA_MSTR_PCIE_NACK_STATUS__XDMA_MSTR_PCIE_NACK_TAG__SHIFT 0x00000000
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_PREFETCH_MASK 0x3fff0000L
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_PREFETCH__SHIFT 0x00000010
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_SIZE_MASK 0x00003fffL
+#define XDMA_MSTR_READ_COMMAND__XDMA_MSTR_REQUEST_SIZE__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH_MASK 0x000000ffL
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__XDMA_MSTR_REMOTE_GPU_ADDRESS_HIGH__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS__XDMA_MSTR_REMOTE_GPU_ADDRESS_MASK 0xffffffffL
+#define XDMA_MSTR_REMOTE_GPU_ADDRESS__XDMA_MSTR_REMOTE_GPU_ADDRESS__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH_MASK 0x000000ffL
+#define XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__XDMA_MSTR_REMOTE_SURFACE_BASE_HIGH__SHIFT 0x00000000
+#define XDMA_MSTR_REMOTE_SURFACE_BASE__XDMA_MSTR_REMOTE_SURFACE_BASE_MASK 0xffffffffL
+#define XDMA_MSTR_REMOTE_SURFACE_BASE__XDMA_MSTR_REMOTE_SURFACE_BASE__SHIFT 0x00000000
+#define XDMA_MSTR_STATUS__XDMA_MSTR_VCOUNT_CURRENT_MASK 0x00003fffL
+#define XDMA_MSTR_STATUS__XDMA_MSTR_VCOUNT_CURRENT__SHIFT 0x00000000
+#define XDMA_MSTR_STATUS__XDMA_MSTR_WRITE_LINE_CURRENT_MASK 0x3fff0000L
+#define XDMA_MSTR_STATUS__XDMA_MSTR_WRITE_LINE_CURRENT__SHIFT 0x00000010
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_DELAY_MASK 0x00000007L
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_DELAY__SHIFT 0x00000000
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_TIMEOUT_DIS_MASK 0x00000008L
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_RDWR_TIMEOUT_DIS__SHIFT 0x00000003
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_TIMEOUT_DELAY_MASK 0xffff8000L
+#define XDMA_RBBMIF_RDWR_CNTL__XDMA_RBBMIF_TIMEOUT_DELAY__SHIFT 0x0000000f
+#define XDMA_SLV_CNTL__XDMA_SLV_ACTIVE_MASK 0x00000100L
+#define XDMA_SLV_CNTL__XDMA_SLV_ACTIVE__SHIFT 0x00000008
+#define XDMA_SLV_CNTL__XDMA_SLV_ENABLE_MASK 0x00010000L
+#define XDMA_SLV_CNTL__XDMA_SLV_ENABLE__SHIFT 0x00000010
+#define XDMA_SLV_CNTL__XDMA_SLV_MEM_READY_MASK 0x00000200L
+#define XDMA_SLV_CNTL__XDMA_SLV_MEM_READY__SHIFT 0x00000009
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LAT_TEST_EN_MASK 0x00080000L
+#define XDMA_SLV_CNTL__XDMA_SLV_READ_LAT_TEST_EN__SHIFT 0x00000013
+#define XDMA_SLV_CNTL__XDMA_SLV_SOFT_RESET_MASK 0x00100000L
+#define XDMA_SLV_CNTL__XDMA_SLV_SOFT_RESET__SHIFT 0x00000014
+#define XDMA_SLV_FLIP_PENDING__XDMA_SLV_FLIP_PENDING_MASK 0x00000001L
+#define XDMA_SLV_FLIP_PENDING__XDMA_SLV_FLIP_PENDING__SHIFT 0x00000000
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_PRIV_MASK 0x00010000L
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_PRIV__SHIFT 0x00000010
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_SWAP_MASK 0x00000300L
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_SWAP__SHIFT 0x00000008
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_VMID_MASK 0x0000f000L
+#define XDMA_SLV_MEM_CLIENT_CONFIG__XDMA_SLV_MEM_CLIENT_VMID__SHIFT 0x0000000c
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_CLR_MASK 0x80000000L
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_CLR__SHIFT 0x0000001f
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_MASK 0x00030000L
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK__SHIFT 0x00000010
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_TAG_MASK 0x0000ffffL
+#define XDMA_SLV_MEM_NACK_STATUS__XDMA_SLV_MEM_NACK_TAG__SHIFT 0x00000000
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_CLR_MASK 0x00010000L
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_CLR__SHIFT 0x00000010
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_MASK 0x00003000L
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK__SHIFT 0x0000000c
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_TAG_MASK 0x000003ffL
+#define XDMA_SLV_PCIE_NACK_STATUS__XDMA_SLV_PCIE_NACK_TAG__SHIFT 0x00000000
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_ACC_MASK 0x000fffffL
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_ACC__SHIFT 0x00000000
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_COUNT_MASK 0xfff00000L
+#define XDMA_SLV_READ_LATENCY_AVE__XDMA_SLV_READ_LATENCY_COUNT__SHIFT 0x00000014
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MAX_MASK 0xffff0000L
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MAX__SHIFT 0x00000010
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MIN_MASK 0x0000ffffL
+#define XDMA_SLV_READ_LATENCY_MINMAX__XDMA_SLV_READ_LATENCY_MIN__SHIFT 0x00000000
+#define XDMA_SLV_READ_LATENCY_TIMER__XDMA_SLV_READ_LATENCY_TIMER_MASK 0x0000ffffL
+#define XDMA_SLV_READ_LATENCY_TIMER__XDMA_SLV_READ_LATENCY_TIMER__SHIFT 0x00000000
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_CLIENT_STALL_MASK 0x00000001L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_CLIENT_STALL__SHIFT 0x00000000
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_STALL_DELAY_MASK 0x0000f000L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_STALL_DELAY__SHIFT 0x0000000c
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LIMIT_MASK 0x000000f0L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_LIMIT__SHIFT 0x00000004
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_TIMER_MASK 0xffff0000L
+#define XDMA_SLV_READ_URGENT_CNTL__XDMA_SLV_READ_URGENT_TIMER__SHIFT 0x00000010
+#define XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH_MASK 0x000000ffL
+#define XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__XDMA_SLV_REMOTE_GPU_ADDRESS_HIGH__SHIFT 0x00000000
+#define XDMA_SLV_REMOTE_GPU_ADDRESS__XDMA_SLV_REMOTE_GPU_ADDRESS_MASK 0xffffffffL
+#define XDMA_SLV_REMOTE_GPU_ADDRESS__XDMA_SLV_REMOTE_GPU_ADDRESS__SHIFT 0x00000000
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_PITCH_MASK 0x00003fffL
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_PITCH__SHIFT 0x00000000
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_WIDTH_MASK 0x3fff0000L
+#define XDMA_SLV_SLS_PITCH__XDMA_SLV_SLS_WIDTH__SHIFT 0x00000010
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_PERIOD_MASK 0xffff0000L
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_PERIOD__SHIFT 0x00000010
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_SIZE_MASK 0x000001ffL
+#define XDMA_SLV_WB_RATE_CNTL__XDMA_SLV_WB_BURST_SIZE__SHIFT 0x00000000
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_DELAY_MASK 0x0000f000L
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_DELAY__SHIFT 0x0000000c
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL_MASK 0x00000001L
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_STALL__SHIFT 0x00000000
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_URGENT_LEVEL_MASK 0x00000f00L
+#define XDMA_SLV_WRITE_URGENT_CNTL__XDMA_SLV_WRITE_URGENT_LEVEL__SHIFT 0x00000008
+#define XDMA_TEST_DEBUG_DATA__XDMA_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define XDMA_TEST_DEBUG_DATA__XDMA_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define XDMA_TEST_DEBUG_INDEX__XDMA_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1784 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 GFX_6_0_D_H
+#define GFX_6_0_D_H
+
+#define ixCLIPPER_DEBUG_REG00 0x0000
+#define ixCLIPPER_DEBUG_REG01 0x0001
+#define ixCLIPPER_DEBUG_REG02 0x0002
+#define ixCLIPPER_DEBUG_REG03 0x0003
+#define ixCLIPPER_DEBUG_REG04 0x0004
+#define ixCLIPPER_DEBUG_REG05 0x0005
+#define ixCLIPPER_DEBUG_REG06 0x0006
+#define ixCLIPPER_DEBUG_REG07 0x0007
+#define ixCLIPPER_DEBUG_REG08 0x0008
+#define ixCLIPPER_DEBUG_REG09 0x0009
+#define ixCLIPPER_DEBUG_REG10 0x000A
+#define ixCLIPPER_DEBUG_REG11 0x000B
+#define ixCLIPPER_DEBUG_REG12 0x000C
+#define ixCLIPPER_DEBUG_REG13 0x000D
+#define ixCLIPPER_DEBUG_REG14 0x000E
+#define ixCLIPPER_DEBUG_REG15 0x000F
+#define ixCLIPPER_DEBUG_REG16 0x0010
+#define ixCLIPPER_DEBUG_REG17 0x0011
+#define ixCLIPPER_DEBUG_REG18 0x0012
+#define ixCLIPPER_DEBUG_REG19 0x0013
+#define ixGDS_DEBUG_REG0 0x0000
+#define ixGDS_DEBUG_REG1 0x0001
+#define ixGDS_DEBUG_REG2 0x0002
+#define ixGDS_DEBUG_REG3 0x0003
+#define ixGDS_DEBUG_REG4 0x0004
+#define ixGDS_DEBUG_REG5 0x0005
+#define ixGDS_DEBUG_REG6 0x0006
+#define ixIA_DEBUG_REG0 0x0000
+#define ixIA_DEBUG_REG1 0x0001
+#define ixIA_DEBUG_REG2 0x0002
+#define ixIA_DEBUG_REG3 0x0003
+#define ixIA_DEBUG_REG4 0x0004
+#define ixIA_DEBUG_REG5 0x0005
+#define ixIA_DEBUG_REG6 0x0006
+#define ixIA_DEBUG_REG7 0x0007
+#define ixIA_DEBUG_REG8 0x0008
+#define ixIA_DEBUG_REG9 0x0009
+#define ixPA_SC_DEBUG_REG0 0x0000
+#define ixPA_SC_DEBUG_REG1 0x0001
+#define ixSETUP_DEBUG_REG0 0x0018
+#define ixSETUP_DEBUG_REG1 0x0019
+#define ixSETUP_DEBUG_REG2 0x001A
+#define ixSETUP_DEBUG_REG3 0x001B
+#define ixSETUP_DEBUG_REG4 0x001C
+#define ixSETUP_DEBUG_REG5 0x001D
+#define ixSQ_DEBUG_CTRL_LOCAL 0x0009
+#define ixSQ_DEBUG_STS_LOCAL 0x0008
+#define ixSQ_INTERRUPT_WORD_AUTO 0x20C0
+#define ixSQ_INTERRUPT_WORD_CMN 0x20C0
+#define ixSQ_INTERRUPT_WORD_WAVE 0x20C0
+#define ixSQ_WAVE_EXEC_HI 0x027F
+#define ixSQ_WAVE_EXEC_LO 0x027E
+#define ixSQ_WAVE_GPR_ALLOC 0x0015
+#define ixSQ_WAVE_HW_ID 0x0014
+#define ixSQ_WAVE_IB_DBG0 0x001C
+#define ixSQ_WAVE_IB_STS 0x0017
+#define ixSQ_WAVE_INST_DW0 0x001A
+#define ixSQ_WAVE_INST_DW1 0x001B
+#define ixSQ_WAVE_LDS_ALLOC 0x0016
+#define ixSQ_WAVE_M0 0x027C
+#define ixSQ_WAVE_MODE 0x0011
+#define ixSQ_WAVE_PC_HI 0x0019
+#define ixSQ_WAVE_PC_LO 0x0018
+#define ixSQ_WAVE_STATUS 0x0012
+#define ixSQ_WAVE_TBA_HI 0x026D
+#define ixSQ_WAVE_TBA_LO 0x026C
+#define ixSQ_WAVE_TMA_HI 0x026F
+#define ixSQ_WAVE_TMA_LO 0x026E
+#define ixSQ_WAVE_TRAPSTS 0x0013
+#define ixSQ_WAVE_TTMP0 0x0270
+#define ixSQ_WAVE_TTMP10 0x027A
+#define ixSQ_WAVE_TTMP1 0x0271
+#define ixSQ_WAVE_TTMP11 0x027B
+#define ixSQ_WAVE_TTMP2 0x0272
+#define ixSQ_WAVE_TTMP3 0x0273
+#define ixSQ_WAVE_TTMP4 0x0274
+#define ixSQ_WAVE_TTMP5 0x0275
+#define ixSQ_WAVE_TTMP6 0x0276
+#define ixSQ_WAVE_TTMP7 0x0277
+#define ixSQ_WAVE_TTMP8 0x0278
+#define ixSQ_WAVE_TTMP9 0x0279
+#define ixSXIFCCG_DEBUG_REG0 0x0014
+#define ixSXIFCCG_DEBUG_REG1 0x0015
+#define ixSXIFCCG_DEBUG_REG2 0x0016
+#define ixSXIFCCG_DEBUG_REG3 0x0017
+#define ixVGT_DEBUG_REG0 0x0000
+#define ixVGT_DEBUG_REG10 0x000A
+#define ixVGT_DEBUG_REG1 0x0001
+#define ixVGT_DEBUG_REG11 0x000B
+#define ixVGT_DEBUG_REG12 0x000C
+#define ixVGT_DEBUG_REG13 0x000D
+#define ixVGT_DEBUG_REG14 0x000E
+#define ixVGT_DEBUG_REG15 0x000F
+#define ixVGT_DEBUG_REG16 0x0010
+#define ixVGT_DEBUG_REG17 0x0011
+#define ixVGT_DEBUG_REG18 0x0012
+#define ixVGT_DEBUG_REG19 0x0013
+#define ixVGT_DEBUG_REG20 0x0014
+#define ixVGT_DEBUG_REG2 0x0002
+#define ixVGT_DEBUG_REG21 0x0015
+#define ixVGT_DEBUG_REG22 0x0016
+#define ixVGT_DEBUG_REG23 0x0017
+#define ixVGT_DEBUG_REG24 0x0018
+#define ixVGT_DEBUG_REG25 0x0019
+#define ixVGT_DEBUG_REG26 0x001A
+#define ixVGT_DEBUG_REG27 0x001B
+#define ixVGT_DEBUG_REG28 0x001C
+#define ixVGT_DEBUG_REG29 0x001D
+#define ixVGT_DEBUG_REG30 0x001E
+#define ixVGT_DEBUG_REG3 0x0003
+#define ixVGT_DEBUG_REG31 0x001F
+#define ixVGT_DEBUG_REG32 0x0020
+#define ixVGT_DEBUG_REG33 0x0021
+#define ixVGT_DEBUG_REG34 0x0022
+#define ixVGT_DEBUG_REG35 0x0023
+#define ixVGT_DEBUG_REG36 0x0024
+#define ixVGT_DEBUG_REG4 0x0004
+#define ixVGT_DEBUG_REG5 0x0005
+#define ixVGT_DEBUG_REG6 0x0006
+#define ixVGT_DEBUG_REG7 0x0007
+#define ixVGT_DEBUG_REG8 0x0008
+#define ixVGT_DEBUG_REG9 0x0009
+#define mmBCI_DEBUG_READ 0x24E3
+#define mmCB_BLEND0_CONTROL 0xA1E0
+#define mmCB_BLEND1_CONTROL 0xA1E1
+#define mmCB_BLEND2_CONTROL 0xA1E2
+#define mmCB_BLEND3_CONTROL 0xA1E3
+#define mmCB_BLEND4_CONTROL 0xA1E4
+#define mmCB_BLEND5_CONTROL 0xA1E5
+#define mmCB_BLEND6_CONTROL 0xA1E6
+#define mmCB_BLEND7_CONTROL 0xA1E7
+#define mmCB_BLEND_ALPHA 0xA108
+#define mmCB_BLEND_BLUE 0xA107
+#define mmCB_BLEND_GREEN 0xA106
+#define mmCB_BLEND_RED 0xA105
+#define mmCB_CGTT_SCLK_CTRL 0x2698
+#define mmCB_COLOR0_ATTRIB 0xA31D
+#define mmCB_COLOR0_BASE 0xA318
+#define mmCB_COLOR0_CLEAR_WORD0 0xA323
+#define mmCB_COLOR0_CLEAR_WORD1 0xA324
+#define mmCB_COLOR0_CMASK 0xA31F
+#define mmCB_COLOR0_CMASK_SLICE 0xA320
+#define mmCB_COLOR0_FMASK 0xA321
+#define mmCB_COLOR0_FMASK_SLICE 0xA322
+#define mmCB_COLOR0_INFO 0xA31C
+#define mmCB_COLOR0_PITCH 0xA319
+#define mmCB_COLOR0_SLICE 0xA31A
+#define mmCB_COLOR0_VIEW 0xA31B
+#define mmCB_COLOR1_ATTRIB 0xA32C
+#define mmCB_COLOR1_BASE 0xA327
+#define mmCB_COLOR1_CLEAR_WORD0 0xA332
+#define mmCB_COLOR1_CLEAR_WORD1 0xA333
+#define mmCB_COLOR1_CMASK 0xA32E
+#define mmCB_COLOR1_CMASK_SLICE 0xA32F
+#define mmCB_COLOR1_FMASK 0xA330
+#define mmCB_COLOR1_FMASK_SLICE 0xA331
+#define mmCB_COLOR1_INFO 0xA32B
+#define mmCB_COLOR1_PITCH 0xA328
+#define mmCB_COLOR1_SLICE 0xA329
+#define mmCB_COLOR1_VIEW 0xA32A
+#define mmCB_COLOR2_ATTRIB 0xA33B
+#define mmCB_COLOR2_BASE 0xA336
+#define mmCB_COLOR2_CLEAR_WORD0 0xA341
+#define mmCB_COLOR2_CLEAR_WORD1 0xA342
+#define mmCB_COLOR2_CMASK 0xA33D
+#define mmCB_COLOR2_CMASK_SLICE 0xA33E
+#define mmCB_COLOR2_FMASK 0xA33F
+#define mmCB_COLOR2_FMASK_SLICE 0xA340
+#define mmCB_COLOR2_INFO 0xA33A
+#define mmCB_COLOR2_PITCH 0xA337
+#define mmCB_COLOR2_SLICE 0xA338
+#define mmCB_COLOR2_VIEW 0xA339
+#define mmCB_COLOR3_ATTRIB 0xA34A
+#define mmCB_COLOR3_BASE 0xA345
+#define mmCB_COLOR3_CLEAR_WORD0 0xA350
+#define mmCB_COLOR3_CLEAR_WORD1 0xA351
+#define mmCB_COLOR3_CMASK 0xA34C
+#define mmCB_COLOR3_CMASK_SLICE 0xA34D
+#define mmCB_COLOR3_FMASK 0xA34E
+#define mmCB_COLOR3_FMASK_SLICE 0xA34F
+#define mmCB_COLOR3_INFO 0xA349
+#define mmCB_COLOR3_PITCH 0xA346
+#define mmCB_COLOR3_SLICE 0xA347
+#define mmCB_COLOR3_VIEW 0xA348
+#define mmCB_COLOR4_ATTRIB 0xA359
+#define mmCB_COLOR4_BASE 0xA354
+#define mmCB_COLOR4_CLEAR_WORD0 0xA35F
+#define mmCB_COLOR4_CLEAR_WORD1 0xA360
+#define mmCB_COLOR4_CMASK 0xA35B
+#define mmCB_COLOR4_CMASK_SLICE 0xA35C
+#define mmCB_COLOR4_FMASK 0xA35D
+#define mmCB_COLOR4_FMASK_SLICE 0xA35E
+#define mmCB_COLOR4_INFO 0xA358
+#define mmCB_COLOR4_PITCH 0xA355
+#define mmCB_COLOR4_SLICE 0xA356
+#define mmCB_COLOR4_VIEW 0xA357
+#define mmCB_COLOR5_ATTRIB 0xA368
+#define mmCB_COLOR5_BASE 0xA363
+#define mmCB_COLOR5_CLEAR_WORD0 0xA36E
+#define mmCB_COLOR5_CLEAR_WORD1 0xA36F
+#define mmCB_COLOR5_CMASK 0xA36A
+#define mmCB_COLOR5_CMASK_SLICE 0xA36B
+#define mmCB_COLOR5_FMASK 0xA36C
+#define mmCB_COLOR5_FMASK_SLICE 0xA36D
+#define mmCB_COLOR5_INFO 0xA367
+#define mmCB_COLOR5_PITCH 0xA364
+#define mmCB_COLOR5_SLICE 0xA365
+#define mmCB_COLOR5_VIEW 0xA366
+#define mmCB_COLOR6_ATTRIB 0xA377
+#define mmCB_COLOR6_BASE 0xA372
+#define mmCB_COLOR6_CLEAR_WORD0 0xA37D
+#define mmCB_COLOR6_CLEAR_WORD1 0xA37E
+#define mmCB_COLOR6_CMASK 0xA379
+#define mmCB_COLOR6_CMASK_SLICE 0xA37A
+#define mmCB_COLOR6_FMASK 0xA37B
+#define mmCB_COLOR6_FMASK_SLICE 0xA37C
+#define mmCB_COLOR6_INFO 0xA376
+#define mmCB_COLOR6_PITCH 0xA373
+#define mmCB_COLOR6_SLICE 0xA374
+#define mmCB_COLOR6_VIEW 0xA375
+#define mmCB_COLOR7_ATTRIB 0xA386
+#define mmCB_COLOR7_BASE 0xA381
+#define mmCB_COLOR7_CLEAR_WORD0 0xA38C
+#define mmCB_COLOR7_CLEAR_WORD1 0xA38D
+#define mmCB_COLOR7_CMASK 0xA388
+#define mmCB_COLOR7_CMASK_SLICE 0xA389
+#define mmCB_COLOR7_FMASK 0xA38A
+#define mmCB_COLOR7_FMASK_SLICE 0xA38B
+#define mmCB_COLOR7_INFO 0xA385
+#define mmCB_COLOR7_PITCH 0xA382
+#define mmCB_COLOR7_SLICE 0xA383
+#define mmCB_COLOR7_VIEW 0xA384
+#define mmCB_COLOR_CONTROL 0xA202
+#define mmCB_DEBUG_BUS_10 0x26A2
+#define mmCB_DEBUG_BUS_1 0x2699
+#define mmCB_DEBUG_BUS_11 0x26A3
+#define mmCB_DEBUG_BUS_12 0x26A4
+#define mmCB_DEBUG_BUS_13 0x26A5
+#define mmCB_DEBUG_BUS_14 0x26A6
+#define mmCB_DEBUG_BUS_15 0x26A7
+#define mmCB_DEBUG_BUS_16 0x26A8
+#define mmCB_DEBUG_BUS_17 0x26A9
+#define mmCB_DEBUG_BUS_18 0x26AA
+#define mmCB_DEBUG_BUS_2 0x269A
+#define mmCB_DEBUG_BUS_3 0x269B
+#define mmCB_DEBUG_BUS_4 0x269C
+#define mmCB_DEBUG_BUS_5 0x269D
+#define mmCB_DEBUG_BUS_6 0x269E
+#define mmCB_DEBUG_BUS_7 0x269F
+#define mmCB_DEBUG_BUS_8 0x26A0
+#define mmCB_DEBUG_BUS_9 0x26A1
+#define mmCB_HW_CONTROL 0x2684
+#define mmCB_HW_CONTROL_1 0x2685
+#define mmCB_HW_CONTROL_2 0x2686
+#define mmCB_PERFCOUNTER0_HI 0x2691
+#define mmCB_PERFCOUNTER0_LO 0x2690
+#define mmCB_PERFCOUNTER0_SELECT1 0x2689
+#define mmCB_PERFCOUNTER1_HI 0x2693
+#define mmCB_PERFCOUNTER1_LO 0x2692
+#define mmCB_PERFCOUNTER2_HI 0x2695
+#define mmCB_PERFCOUNTER2_LO 0x2694
+#define mmCB_PERFCOUNTER3_HI 0x2697
+#define mmCB_PERFCOUNTER3_LO 0x2696
+#define mmCB_SHADER_MASK 0xA08F
+#define mmCB_TARGET_MASK 0xA08E
+#define mmCC_GC_SHADER_ARRAY_CONFIG 0x226F
+#define mmCC_RB_BACKEND_DISABLE 0x263D
+#define mmCC_RB_DAISY_CHAIN 0x2641
+#define mmCC_RB_REDUNDANCY 0x263C
+#define mmCC_SQC_BANK_DISABLE 0x2307
+#define mmCGTS_RD_CTRL_REG 0x2455
+#define mmCGTS_RD_REG 0x2456
+#define mmCGTS_SM_CTRL_REG 0x2454
+#define mmCGTS_TCC_DISABLE 0x2452
+#define mmCGTS_USER_TCC_DISABLE 0x2453
+#define mmCGTT_BCI_CLK_CTRL 0x24A9
+#define mmCGTT_CP_CLK_CTRL 0x3059
+#define mmCGTT_GDS_CLK_CTRL 0x25DD
+#define mmCGTT_IA_CLK_CTRL 0x2261
+#define mmCGTT_PA_CLK_CTRL 0x2286
+#define mmCGTT_PC_CLK_CTRL 0x24A8
+#define mmCGTT_RLC_CLK_CTRL 0x30E0
+#define mmCGTT_SC_CLK_CTRL 0x22CA
+#define mmCGTT_SPI_CLK_CTRL 0x2451
+#define mmCGTT_SQ_CLK_CTRL 0x2362
+#define mmCGTT_SQG_CLK_CTRL 0x2363
+#define mmCGTT_SX_CLK_CTRL0 0x240C
+#define mmCGTT_SX_CLK_CTRL1 0x240D
+#define mmCGTT_SX_CLK_CTRL2 0x240E
+#define mmCGTT_SX_CLK_CTRL3 0x240F
+#define mmCGTT_SX_CLK_CTRL4 0x2410
+#define mmCGTT_TCI_CLK_CTRL 0x2B60
+#define mmCGTT_TCP_CLK_CTRL 0x2B15
+#define mmCGTT_VGT_CLK_CTRL 0x225F
+#define mmCOHER_DEST_BASE_0 0xA092
+#define mmCOHER_DEST_BASE_1 0xA093
+#define mmCOHER_DEST_BASE_2 0xA07E
+#define mmCOHER_DEST_BASE_3 0xA07F
+#define mmCOMPUTE_DIM_X 0x2E01
+#define mmCOMPUTE_DIM_Y 0x2E02
+#define mmCOMPUTE_DIM_Z 0x2E03
+#define mmCOMPUTE_DISPATCH_INITIATOR 0x2E00
+#define mmCOMPUTE_NUM_THREAD_X 0x2E07
+#define mmCOMPUTE_NUM_THREAD_Y 0x2E08
+#define mmCOMPUTE_NUM_THREAD_Z 0x2E09
+#define mmCOMPUTE_PGM_HI 0x2E0D
+#define mmCOMPUTE_PGM_LO 0x2E0C
+#define mmCOMPUTE_PGM_RSRC1 0x2E12
+#define mmCOMPUTE_PGM_RSRC2 0x2E13
+#define mmCOMPUTE_RESOURCE_LIMITS 0x2E15
+#define mmCOMPUTE_START_X 0x2E04
+#define mmCOMPUTE_START_Y 0x2E05
+#define mmCOMPUTE_START_Z 0x2E06
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE0 0x2E16
+#define mmCOMPUTE_STATIC_THREAD_MGMT_SE1 0x2E17
+#define mmCOMPUTE_TBA_HI 0x2E0F
+#define mmCOMPUTE_TBA_LO 0x2E0E
+#define mmCOMPUTE_TMA_HI 0x2E11
+#define mmCOMPUTE_TMA_LO 0x2E10
+#define mmCOMPUTE_TMPRING_SIZE 0x2E18
+#define mmCOMPUTE_USER_DATA_0 0x2E40
+#define mmCOMPUTE_USER_DATA_10 0x2E4A
+#define mmCOMPUTE_USER_DATA_1 0x2E41
+#define mmCOMPUTE_USER_DATA_11 0x2E4B
+#define mmCOMPUTE_USER_DATA_12 0x2E4C
+#define mmCOMPUTE_USER_DATA_13 0x2E4D
+#define mmCOMPUTE_USER_DATA_14 0x2E4E
+#define mmCOMPUTE_USER_DATA_15 0x2E4F
+#define mmCOMPUTE_USER_DATA_2 0x2E42
+#define mmCOMPUTE_USER_DATA_3 0x2E43
+#define mmCOMPUTE_USER_DATA_4 0x2E44
+#define mmCOMPUTE_USER_DATA_5 0x2E45
+#define mmCOMPUTE_USER_DATA_6 0x2E46
+#define mmCOMPUTE_USER_DATA_7 0x2E47
+#define mmCOMPUTE_USER_DATA_8 0x2E48
+#define mmCOMPUTE_USER_DATA_9 0x2E49
+#define mmCOMPUTE_VMID 0x2E14
+#define mmCP_APPEND_ADDR_HI 0x2159
+#define mmCP_APPEND_ADDR_LO 0x2158
+#define mmCP_APPEND_DATA 0x215A
+#define mmCP_APPEND_LAST_CS_FENCE 0x215B
+#define mmCP_APPEND_LAST_PS_FENCE 0x215C
+#define mmCP_ATOMIC_PREOP_HI 0x215E
+#define mmCP_ATOMIC_PREOP_LO 0x215D
+#define mmCP_BUSY_STAT 0x219F
+#define mmCP_CE_HEADER_DUMP 0x21A4
+#define mmCP_CE_IB1_BASE_HI 0x21C7
+#define mmCP_CE_IB1_BASE_LO 0x21C6
+#define mmCP_CE_IB1_BUFSZ 0x21C8
+#define mmCP_CE_IB2_BASE_HI 0x21CA
+#define mmCP_CE_IB2_BASE_LO 0x21C9
+#define mmCP_CE_IB2_BUFSZ 0x21CB
+#define mmCP_CE_INIT_BASE_HI 0x21C4
+#define mmCP_CE_INIT_BASE_LO 0x21C3
+#define mmCP_CE_INIT_BUFSZ 0x21C5
+#define mmCP_CEQ1_AVAIL 0x21E6
+#define mmCP_CEQ2_AVAIL 0x21E7
+#define mmCP_CE_ROQ_IB1_STAT 0x21E9
+#define mmCP_CE_ROQ_IB2_STAT 0x21EA
+#define mmCP_CE_ROQ_RB_STAT 0x21E8
+#define mmCP_CE_UCODE_ADDR 0x305A
+#define mmCP_CE_UCODE_DATA 0x305B
+#define mmCP_CMD_DATA 0x21DF
+#define mmCP_CMD_INDEX 0x21DE
+#define mmCP_CNTX_STAT 0x21B8
+#define mmCP_COHER_BASE 0x217E
+#define mmCP_COHER_CNTL 0x217C
+#define mmCP_COHER_SIZE 0x217D
+#define mmCP_COHER_START_DELAY 0x217B
+#define mmCP_COHER_STATUS 0x217F
+#define mmCP_CSF_CNTL 0x21B5
+#define mmCP_CSF_STAT 0x21B4
+#define mmCP_DMA_CNTL 0x218A
+#define mmCP_DMA_ME_COMMAND 0x2184
+#define mmCP_DMA_ME_DST_ADDR 0x2182
+#define mmCP_DMA_ME_DST_ADDR_HI 0x2183
+#define mmCP_DMA_ME_SRC_ADDR 0x2180
+#define mmCP_DMA_ME_SRC_ADDR_HI 0x2181
+#define mmCP_DMA_PFP_COMMAND 0x2189
+#define mmCP_DMA_PFP_DST_ADDR 0x2187
+#define mmCP_DMA_PFP_DST_ADDR_HI 0x2188
+#define mmCP_DMA_PFP_SRC_ADDR 0x2185
+#define mmCP_DMA_PFP_SRC_ADDR_HI 0x2186
+#define mmCP_DMA_READ_TAGS 0x218B
+#define mmCP_ECC_FIRSTOCCURRENCE 0x307A
+#define mmCP_ECC_FIRSTOCCURRENCE_RING0 0x307B
+#define mmCP_ECC_FIRSTOCCURRENCE_RING1 0x307C
+#define mmCP_ECC_FIRSTOCCURRENCE_RING2 0x307D
+#define mmCP_EOP_DONE_ADDR_HI 0x2101
+#define mmCP_EOP_DONE_ADDR_LO 0x2100
+#define mmCP_EOP_DONE_DATA_HI 0x2103
+#define mmCP_EOP_DONE_DATA_LO 0x2102
+#define mmCP_EOP_LAST_FENCE_HI 0x2105
+#define mmCP_EOP_LAST_FENCE_LO 0x2104
+#define mmCP_GDS_ATOMIC0_PREOP_HI 0x2160
+#define mmCP_GDS_ATOMIC0_PREOP_LO 0x215F
+#define mmCP_GDS_ATOMIC1_PREOP_HI 0x2162
+#define mmCP_GDS_ATOMIC1_PREOP_LO 0x2161
+#define mmCP_GRBM_FREE_COUNT 0x21A3
+#define mmCP_IB1_BASE_HI 0x21CD
+#define mmCP_IB1_BASE_LO 0x21CC
+#define mmCP_IB1_BUFSZ 0x21CE
+#define mmCP_IB1_OFFSET 0x2192
+#define mmCP_IB1_PREAMBLE_BEGIN 0x2194
+#define mmCP_IB1_PREAMBLE_END 0x2195
+#define mmCP_IB2_BASE_HI 0x21D0
+#define mmCP_IB2_BASE_LO 0x21CF
+#define mmCP_IB2_BUFSZ 0x21D1
+#define mmCP_IB2_OFFSET 0x2193
+#define mmCP_IB2_PREAMBLE_BEGIN 0x2196
+#define mmCP_IB2_PREAMBLE_END 0x2197
+#define mmCP_INT_CNTL 0x3049
+#define mmCP_INT_CNTL_RING0 0x306A
+#define mmCP_INT_CNTL_RING1 0x306B
+#define mmCP_INT_CNTL_RING2 0x306C
+#define mmCP_INT_STAT_DEBUG 0x21F7
+#define mmCP_INT_STATUS 0x304A
+#define mmCP_INT_STATUS_RING0 0x306D
+#define mmCP_INT_STATUS_RING1 0x306E
+#define mmCP_INT_STATUS_RING2 0x306F
+#define mmCP_MC_PACK_DELAY_CNT 0x21A7
+#define mmCP_ME_CNTL 0x21B6
+#define mmCP_ME_HEADER_DUMP 0x21A1
+#define mmCP_ME_MC_RADDR_HI 0x216E
+#define mmCP_ME_MC_RADDR_LO 0x216D
+#define mmCP_ME_MC_WADDR_HI 0x216A
+#define mmCP_ME_MC_WADDR_LO 0x2169
+#define mmCP_ME_MC_WDATA_HI 0x216C
+#define mmCP_ME_MC_WDATA_LO 0x216B
+#define mmCP_MEM_SLP_CNTL 0x3079
+#define mmCP_ME_PREEMPTION 0x21B9
+#define mmCP_MEQ_AVAIL 0x21DD
+#define mmCP_MEQ_STAT 0x21E5
+#define mmCP_MEQ_THRESHOLDS 0x21D9
+#define mmCP_ME_RAM_DATA 0x3058
+#define mmCP_ME_RAM_RADDR 0x3056
+#define mmCP_ME_RAM_WADDR 0x3057
+#define mmCP_NUM_PRIM_NEEDED_COUNT0_HI 0x210B
+#define mmCP_NUM_PRIM_NEEDED_COUNT0_LO 0x210A
+#define mmCP_NUM_PRIM_NEEDED_COUNT1_HI 0x210F
+#define mmCP_NUM_PRIM_NEEDED_COUNT1_LO 0x210E
+#define mmCP_NUM_PRIM_NEEDED_COUNT2_HI 0x2113
+#define mmCP_NUM_PRIM_NEEDED_COUNT2_LO 0x2112
+#define mmCP_NUM_PRIM_NEEDED_COUNT3_HI 0x2117
+#define mmCP_NUM_PRIM_NEEDED_COUNT3_LO 0x2116
+#define mmCP_NUM_PRIM_WRITTEN_COUNT0_HI 0x2109
+#define mmCP_NUM_PRIM_WRITTEN_COUNT0_LO 0x2108
+#define mmCP_NUM_PRIM_WRITTEN_COUNT1_HI 0x210D
+#define mmCP_NUM_PRIM_WRITTEN_COUNT1_LO 0x210C
+#define mmCP_NUM_PRIM_WRITTEN_COUNT2_HI 0x2111
+#define mmCP_NUM_PRIM_WRITTEN_COUNT2_LO 0x2110
+#define mmCP_NUM_PRIM_WRITTEN_COUNT3_HI 0x2115
+#define mmCP_NUM_PRIM_WRITTEN_COUNT3_LO 0x2114
+#define mmCP_PA_CINVOC_COUNT_HI 0x2129
+#define mmCP_PA_CINVOC_COUNT_LO 0x2128
+#define mmCP_PA_CPRIM_COUNT_HI 0x212B
+#define mmCP_PA_CPRIM_COUNT_LO 0x212A
+#define mmCP_PERFMON_CNTL 0x21FF
+#define mmCP_PERFMON_CNTX_CNTL 0xA0D8
+#define mmCP_PFP_HEADER_DUMP 0x21A2
+#define mmCP_PFP_IB_CONTROL 0x218D
+#define mmCP_PFP_LOAD_CONTROL 0x218E
+#define mmCP_PFP_UCODE_ADDR 0x3054
+#define mmCP_PFP_UCODE_DATA 0x3055
+#define mmCP_PIPE_STATS_ADDR_HI 0x2119
+#define mmCP_PIPE_STATS_ADDR_LO 0x2118
+#define mmCP_PWR_CNTL 0x3078
+#define mmCP_QUEUE_THRESHOLDS 0x21D8
+#define mmCP_RB0_BASE 0x3040
+#define mmCP_RB0_CNTL 0x3041
+#define mmCP_RB0_RPTR 0x21C0
+#define mmCP_RB0_RPTR_ADDR 0x3043
+#define mmCP_RB0_RPTR_ADDR_HI 0x3044
+#define mmCP_RB0_WPTR 0x3045
+#define mmCP_RB1_BASE 0x3060
+#define mmCP_RB1_CNTL 0x3061
+#define mmCP_RB1_RPTR 0x21BF
+#define mmCP_RB1_RPTR_ADDR 0x3062
+#define mmCP_RB1_RPTR_ADDR_HI 0x3063
+#define mmCP_RB1_WPTR 0x3064
+#define mmCP_RB2_BASE 0x3065
+#define mmCP_RB2_CNTL 0x3066
+#define mmCP_RB2_RPTR 0x21BE
+#define mmCP_RB2_RPTR_ADDR 0x3067
+#define mmCP_RB2_RPTR_ADDR_HI 0x3068
+#define mmCP_RB2_WPTR 0x3069
+#define mmCP_RB_BASE 0x3040
+#define mmCP_RB_CNTL 0x3041
+#define mmCP_RB_OFFSET 0x2191
+#define mmCP_RB_RPTR 0x21C0
+#define mmCP_RB_RPTR_ADDR 0x3043
+#define mmCP_RB_RPTR_ADDR_HI 0x3044
+#define mmCP_RB_RPTR_WR 0x3042
+#define mmCP_RB_VMID 0x3051
+#define mmCP_RB_WPTR 0x3045
+#define mmCP_RB_WPTR_DELAY 0x21C1
+#define mmCP_RB_WPTR_POLL_ADDR_HI 0x3047
+#define mmCP_RB_WPTR_POLL_ADDR_LO 0x3046
+#define mmCP_RB_WPTR_POLL_CNTL 0x21C2
+#define mmCP_RING0_PRIORITY 0x304D
+#define mmCP_RING1_PRIORITY 0x304E
+#define mmCP_RING2_PRIORITY 0x304F
+#define mmCP_RINGID 0xA0D9
+#define mmCP_RING_PRIORITY_CNTS 0x304C
+#define mmCP_ROQ1_THRESHOLDS 0x21D5
+#define mmCP_ROQ2_AVAIL 0x21DC
+#define mmCP_ROQ2_THRESHOLDS 0x21D6
+#define mmCP_ROQ_AVAIL 0x21DA
+#define mmCP_ROQ_IB1_STAT 0x21E1
+#define mmCP_ROQ_IB2_STAT 0x21E2
+#define mmCP_ROQ_RB_STAT 0x21E0
+#define mmCP_SC_PSINVOC_COUNT0_HI 0x212D
+#define mmCP_SC_PSINVOC_COUNT0_LO 0x212C
+#define mmCP_SC_PSINVOC_COUNT1_HI 0x212F
+#define mmCP_SC_PSINVOC_COUNT1_LO 0x212E
+#define mmCP_SCRATCH_DATA 0x2190
+#define mmCP_SCRATCH_INDEX 0x218F
+#define mmCP_SEM_INCOMPLETE_TIMER_CNTL 0x2172
+#define mmCP_SEM_WAIT_TIMER 0x216F
+#define mmCP_SIG_SEM_ADDR_HI 0x2171
+#define mmCP_SIG_SEM_ADDR_LO 0x2170
+#define mmCP_STALLED_STAT1 0x219D
+#define mmCP_STALLED_STAT2 0x219E
+#define mmCP_STALLED_STAT3 0x219C
+#define mmCP_STAT 0x21A0
+#define mmCP_ST_BASE_HI 0x21D3
+#define mmCP_ST_BASE_LO 0x21D2
+#define mmCP_ST_BUFSZ 0x21D4
+#define mmCP_STQ_AVAIL 0x21DB
+#define mmCP_STQ_STAT 0x21E3
+#define mmCP_STQ_THRESHOLDS 0x21D7
+#define mmCP_STREAM_OUT_ADDR_HI 0x2107
+#define mmCP_STREAM_OUT_ADDR_LO 0x2106
+#define mmCP_STRMOUT_CNTL 0x213F
+#define mmCP_VGT_CSINVOC_COUNT_HI 0x2131
+#define mmCP_VGT_CSINVOC_COUNT_LO 0x2130
+#define mmCP_VGT_DSINVOC_COUNT_HI 0x2127
+#define mmCP_VGT_DSINVOC_COUNT_LO 0x2126
+#define mmCP_VGT_GSINVOC_COUNT_HI 0x2123
+#define mmCP_VGT_GSINVOC_COUNT_LO 0x2122
+#define mmCP_VGT_GSPRIM_COUNT_HI 0x211F
+#define mmCP_VGT_GSPRIM_COUNT_LO 0x211E
+#define mmCP_VGT_HSINVOC_COUNT_HI 0x2125
+#define mmCP_VGT_HSINVOC_COUNT_LO 0x2124
+#define mmCP_VGT_IAPRIM_COUNT_HI 0x211D
+#define mmCP_VGT_IAPRIM_COUNT_LO 0x211C
+#define mmCP_VGT_IAVERT_COUNT_HI 0x211B
+#define mmCP_VGT_IAVERT_COUNT_LO 0x211A
+#define mmCP_VGT_VSINVOC_COUNT_HI 0x2121
+#define mmCP_VGT_VSINVOC_COUNT_LO 0x2120
+#define mmCP_VMID 0xA0DA
+#define mmCP_WAIT_REG_MEM_TIMEOUT 0x2174
+#define mmCP_WAIT_SEM_ADDR_HI 0x2176
+#define mmCP_WAIT_SEM_ADDR_LO 0x2175
+#define mmCS_COPY_STATE 0xA1F3
+#define mmDB_ALPHA_TO_MASK 0xA2DC
+#define mmDB_CGTT_CLK_CTRL_0 0x261A
+#define mmDB_COUNT_CONTROL 0xA001
+#define mmDB_CREDIT_LIMIT 0x2614
+#define mmDB_DEBUG 0x260C
+#define mmDB_DEBUG2 0x260D
+#define mmDB_DEBUG3 0x260E
+#define mmDB_DEBUG4 0x260F
+#define mmDB_DEPTH_BOUNDS_MAX 0xA009
+#define mmDB_DEPTH_BOUNDS_MIN 0xA008
+#define mmDB_DEPTH_CLEAR 0xA00B
+#define mmDB_DEPTH_CONTROL 0xA200
+#define mmDB_DEPTH_INFO 0xA00F
+#define mmDB_DEPTH_SIZE 0xA016
+#define mmDB_DEPTH_SLICE 0xA017
+#define mmDB_DEPTH_VIEW 0xA002
+#define mmDB_EQAA 0xA201
+#define mmDB_FIFO_DEPTH1 0x2618
+#define mmDB_FIFO_DEPTH2 0x2619
+#define mmDB_FREE_CACHELINES 0x2617
+#define mmDB_HTILE_DATA_BASE 0xA005
+#define mmDB_HTILE_SURFACE 0xA2AF
+#define mmDB_PERFCOUNTER0_HI 0x2602
+#define mmDB_PERFCOUNTER0_LO 0x2601
+#define mmDB_PERFCOUNTER0_SELECT 0x2600
+#define mmDB_PERFCOUNTER1_HI 0x2605
+#define mmDB_PERFCOUNTER1_LO 0x2604
+#define mmDB_PERFCOUNTER1_SELECT 0x2603
+#define mmDB_PERFCOUNTER2_HI 0x2608
+#define mmDB_PERFCOUNTER2_LO 0x2607
+#define mmDB_PERFCOUNTER2_SELECT 0x2606
+#define mmDB_PERFCOUNTER3_HI 0x260B
+#define mmDB_PERFCOUNTER3_LO 0x260A
+#define mmDB_PERFCOUNTER3_SELECT 0x2609
+#define mmDB_PRELOAD_CONTROL 0xA2B2
+#define mmDB_READ_DEBUG_0 0x2620
+#define mmDB_READ_DEBUG_1 0x2621
+#define mmDB_READ_DEBUG_2 0x2622
+#define mmDB_READ_DEBUG_3 0x2623
+#define mmDB_READ_DEBUG_4 0x2624
+#define mmDB_READ_DEBUG_5 0x2625
+#define mmDB_READ_DEBUG_6 0x2626
+#define mmDB_READ_DEBUG_7 0x2627
+#define mmDB_READ_DEBUG_8 0x2628
+#define mmDB_READ_DEBUG_9 0x2629
+#define mmDB_READ_DEBUG_A 0x262A
+#define mmDB_READ_DEBUG_B 0x262B
+#define mmDB_READ_DEBUG_C 0x262C
+#define mmDB_READ_DEBUG_D 0x262D
+#define mmDB_READ_DEBUG_E 0x262E
+#define mmDB_READ_DEBUG_F 0x262F
+#define mmDB_RENDER_CONTROL 0xA000
+#define mmDB_RENDER_OVERRIDE 0xA003
+#define mmDB_RENDER_OVERRIDE2 0xA004
+#define mmDB_SHADER_CONTROL 0xA203
+#define mmDB_SRESULTS_COMPARE_STATE0 0xA2B0
+#define mmDB_SRESULTS_COMPARE_STATE1 0xA2B1
+#define mmDB_STENCIL_CLEAR 0xA00A
+#define mmDB_STENCIL_CONTROL 0xA10B
+#define mmDB_STENCIL_INFO 0xA011
+#define mmDB_STENCIL_READ_BASE 0xA013
+#define mmDB_STENCILREFMASK 0xA10C
+#define mmDB_STENCILREFMASK_BF 0xA10D
+#define mmDB_STENCIL_WRITE_BASE 0xA015
+#define mmDB_SUBTILE_CONTROL 0x2616
+#define mmDB_WATERMARKS 0x2615
+#define mmDB_Z_INFO 0xA010
+#define mmDB_ZPASS_COUNT_HI 0x261D
+#define mmDB_ZPASS_COUNT_LOW 0x261C
+#define mmDB_Z_READ_BASE 0xA012
+#define mmDB_Z_WRITE_BASE 0xA014
+#define mmDEBUG_DATA 0x203D
+#define mmDEBUG_INDEX 0x203C
+#define mmGB_ADDR_CONFIG 0x263E
+#define mmGB_BACKEND_MAP 0x263F
+#define mmGB_EDC_MODE 0x307E
+#define mmGB_GPU_ID 0x2640
+#define mmGB_TILE_MODE0 0x2644
+#define mmGB_TILE_MODE10 0x264E
+#define mmGB_TILE_MODE1 0x2645
+#define mmGB_TILE_MODE11 0x264F
+#define mmGB_TILE_MODE12 0x2650
+#define mmGB_TILE_MODE13 0x2651
+#define mmGB_TILE_MODE14 0x2652
+#define mmGB_TILE_MODE15 0x2653
+#define mmGB_TILE_MODE16 0x2654
+#define mmGB_TILE_MODE17 0x2655
+#define mmGB_TILE_MODE18 0x2656
+#define mmGB_TILE_MODE19 0x2657
+#define mmGB_TILE_MODE20 0x2658
+#define mmGB_TILE_MODE2 0x2646
+#define mmGB_TILE_MODE21 0x2659
+#define mmGB_TILE_MODE22 0x265A
+#define mmGB_TILE_MODE23 0x265B
+#define mmGB_TILE_MODE24 0x265C
+#define mmGB_TILE_MODE25 0x265D
+#define mmGB_TILE_MODE26 0x265E
+#define mmGB_TILE_MODE27 0x265F
+#define mmGB_TILE_MODE28 0x2660
+#define mmGB_TILE_MODE29 0x2661
+#define mmGB_TILE_MODE30 0x2662
+#define mmGB_TILE_MODE3 0x2647
+#define mmGB_TILE_MODE31 0x2663
+#define mmGB_TILE_MODE4 0x2648
+#define mmGB_TILE_MODE5 0x2649
+#define mmGB_TILE_MODE6 0x264A
+#define mmGB_TILE_MODE7 0x264B
+#define mmGB_TILE_MODE8 0x264C
+#define mmGB_TILE_MODE9 0x264D
+#define mmGC_PRIV_MODE 0x3048
+#define mmGC_USER_RB_BACKEND_DISABLE 0x26DF
+#define mmGC_USER_SHADER_ARRAY_CONFIG 0x2270
+#define mmGDS_ATOM_BASE 0x25CE
+#define mmGDS_ATOM_CNTL 0x25CC
+#define mmGDS_ATOM_COMPLETE 0x25CD
+#define mmGDS_ATOM_DST 0x25D2
+#define mmGDS_ATOM_OFFSET0 0x25D0
+#define mmGDS_ATOM_OFFSET1 0x25D1
+#define mmGDS_ATOM_OP 0x25D3
+#define mmGDS_ATOM_READ0 0x25D8
+#define mmGDS_ATOM_READ0_U 0x25D9
+#define mmGDS_ATOM_READ1 0x25DA
+#define mmGDS_ATOM_READ1_U 0x25DB
+#define mmGDS_ATOM_SIZE 0x25CF
+#define mmGDS_ATOM_SRC0 0x25D4
+#define mmGDS_ATOM_SRC0_U 0x25D5
+#define mmGDS_ATOM_SRC1 0x25D6
+#define mmGDS_ATOM_SRC1_U 0x25D7
+#define mmGDS_CNTL_STATUS 0x25C1
+#define mmGDS_CONFIG 0x25C0
+#define mmGDS_DEBUG_CNTL 0x25DE
+#define mmGDS_DEBUG_DATA 0x25DF
+#define mmGDS_ENHANCE 0x25DC
+#define mmGDS_GRBM_SECDED_CNT 0x25E3
+#define mmGDS_GWS_RESOURCE 0x25E1
+#define mmGDS_GWS_RESOURCE_CNTL 0x25E0
+#define mmGDS_OA_DED 0x25E4
+#define mmGDS_PERFCOUNTER0_HI 0x25E7
+#define mmGDS_PERFCOUNTER0_LO 0x25E6
+#define mmGDS_PERFCOUNTER0_SELECT 0x25E5
+#define mmGDS_PERFCOUNTER1_HI 0x25EA
+#define mmGDS_PERFCOUNTER1_LO 0x25E9
+#define mmGDS_PERFCOUNTER1_SELECT 0x25E8
+#define mmGDS_PERFCOUNTER2_HI 0x25ED
+#define mmGDS_PERFCOUNTER2_LO 0x25EC
+#define mmGDS_PERFCOUNTER2_SELECT 0x25EB
+#define mmGDS_PERFCOUNTER3_HI 0x25F0
+#define mmGDS_PERFCOUNTER3_LO 0x25EF
+#define mmGDS_PERFCOUNTER3_SELECT 0x25EE
+#define mmGDS_RD_ADDR 0x25C2
+#define mmGDS_RD_BURST_ADDR 0x25C4
+#define mmGDS_RD_BURST_COUNT 0x25C5
+#define mmGDS_RD_BURST_DATA 0x25C6
+#define mmGDS_RD_DATA 0x25C3
+#define mmGDS_SECDED_CNT 0x25E2
+#define mmGDS_WR_ADDR 0x25C7
+#define mmGDS_WR_BURST_ADDR 0x25C9
+#define mmGDS_WR_BURST_DATA 0x25CA
+#define mmGDS_WR_DATA 0x25C8
+#define mmGDS_WRITE_COMPLETE 0x25CB
+#define mmGFX_COPY_STATE 0xA1F4
+#define mmGRBM_CAM_DATA 0x3001
+#define mmGRBM_CAM_INDEX 0x3000
+#define mmGRBM_CNTL 0x2000
+#define mmGRBM_DEBUG 0x2014
+#define mmGRBM_DEBUG_CNTL 0x2009
+#define mmGRBM_DEBUG_DATA 0x200A
+#define mmGRBM_DEBUG_SNAPSHOT 0x2015
+#define mmGRBM_GFX_CLKEN_CNTL 0x200C
+#define mmGRBM_GFX_INDEX 0x200B
+#define mmGRBM_INT_CNTL 0x2018
+#define mmGRBM_NOWHERE 0x203F
+#define mmGRBM_PERFCOUNTER0_HI 0x201F
+#define mmGRBM_PERFCOUNTER0_LO 0x201E
+#define mmGRBM_PERFCOUNTER0_SELECT 0x201C
+#define mmGRBM_PERFCOUNTER1_HI 0x2021
+#define mmGRBM_PERFCOUNTER1_LO 0x2020
+#define mmGRBM_PERFCOUNTER1_SELECT 0x201D
+#define mmGRBM_PWR_CNTL 0x2003
+#define mmGRBM_READ_ERROR 0x2016
+#define mmGRBM_SCRATCH_REG0 0x2040
+#define mmGRBM_SCRATCH_REG1 0x2041
+#define mmGRBM_SCRATCH_REG2 0x2042
+#define mmGRBM_SCRATCH_REG3 0x2043
+#define mmGRBM_SCRATCH_REG4 0x2044
+#define mmGRBM_SCRATCH_REG5 0x2045
+#define mmGRBM_SCRATCH_REG6 0x2046
+#define mmGRBM_SCRATCH_REG7 0x2047
+#define mmGRBM_SE0_PERFCOUNTER_HI 0x202B
+#define mmGRBM_SE0_PERFCOUNTER_LO 0x202A
+#define mmGRBM_SE0_PERFCOUNTER_SELECT 0x2026
+#define mmGRBM_SE1_PERFCOUNTER_HI 0x202D
+#define mmGRBM_SE1_PERFCOUNTER_LO 0x202C
+#define mmGRBM_SE1_PERFCOUNTER_SELECT 0x2027
+#define mmGRBM_SKEW_CNTL 0x2001
+#define mmGRBM_SOFT_RESET 0x2008
+#define mmGRBM_STATUS 0x2004
+#define mmGRBM_STATUS2 0x2002
+#define mmGRBM_STATUS_SE0 0x2005
+#define mmGRBM_STATUS_SE1 0x2006
+#define mmGRBM_WAIT_IDLE_CLOCKS 0x200D
+#define mmIA_CNTL_STATUS 0x2237
+#define mmIA_DEBUG_CNTL 0x223A
+#define mmIA_DEBUG_DATA 0x223B
+#define mmIA_ENHANCE 0xA29C
+#define mmIA_MULTI_VGT_PARAM 0xA2AA
+#define mmIA_PERFCOUNTER0_HI 0x2225
+#define mmIA_PERFCOUNTER0_LO 0x2224
+#define mmIA_PERFCOUNTER0_SELECT 0x2220
+#define mmIA_PERFCOUNTER1_HI 0x2227
+#define mmIA_PERFCOUNTER1_LO 0x2226
+#define mmIA_PERFCOUNTER1_SELECT 0x2221
+#define mmIA_PERFCOUNTER2_HI 0x2229
+#define mmIA_PERFCOUNTER2_LO 0x2228
+#define mmIA_PERFCOUNTER2_SELECT 0x2222
+#define mmIA_PERFCOUNTER3_HI 0x222B
+#define mmIA_PERFCOUNTER3_LO 0x222A
+#define mmIA_PERFCOUNTER3_SELECT 0x2223
+#define mmIA_VMID_OVERRIDE 0x2260
+#define mmPA_CL_CLIP_CNTL 0xA204
+#define mmPA_CL_CNTL_STATUS 0x2284
+#define mmPA_CL_ENHANCE 0x2285
+#define mmPA_CL_GB_HORZ_CLIP_ADJ 0xA2FC
+#define mmPA_CL_GB_HORZ_DISC_ADJ 0xA2FD
+#define mmPA_CL_GB_VERT_CLIP_ADJ 0xA2FA
+#define mmPA_CL_GB_VERT_DISC_ADJ 0xA2FB
+#define mmPA_CL_NANINF_CNTL 0xA208
+#define mmPA_CL_POINT_CULL_RAD 0xA1F8
+#define mmPA_CL_POINT_SIZE 0xA1F7
+#define mmPA_CL_POINT_X_RAD 0xA1F5
+#define mmPA_CL_POINT_Y_RAD 0xA1F6
+#define mmPA_CL_UCP_0_W 0xA172
+#define mmPA_CL_UCP_0_X 0xA16F
+#define mmPA_CL_UCP_0_Y 0xA170
+#define mmPA_CL_UCP_0_Z 0xA171
+#define mmPA_CL_UCP_1_W 0xA176
+#define mmPA_CL_UCP_1_X 0xA173
+#define mmPA_CL_UCP_1_Y 0xA174
+#define mmPA_CL_UCP_1_Z 0xA175
+#define mmPA_CL_UCP_2_W 0xA17A
+#define mmPA_CL_UCP_2_X 0xA177
+#define mmPA_CL_UCP_2_Y 0xA178
+#define mmPA_CL_UCP_2_Z 0xA179
+#define mmPA_CL_UCP_3_W 0xA17E
+#define mmPA_CL_UCP_3_X 0xA17B
+#define mmPA_CL_UCP_3_Y 0xA17C
+#define mmPA_CL_UCP_3_Z 0xA17D
+#define mmPA_CL_UCP_4_W 0xA182
+#define mmPA_CL_UCP_4_X 0xA17F
+#define mmPA_CL_UCP_4_Y 0xA180
+#define mmPA_CL_UCP_4_Z 0xA181
+#define mmPA_CL_UCP_5_W 0xA186
+#define mmPA_CL_UCP_5_X 0xA183
+#define mmPA_CL_UCP_5_Y 0xA184
+#define mmPA_CL_UCP_5_Z 0xA185
+#define mmPA_CL_VPORT_XOFFSET 0xA110
+#define mmPA_CL_VPORT_XOFFSET_10 0xA14C
+#define mmPA_CL_VPORT_XOFFSET_1 0xA116
+#define mmPA_CL_VPORT_XOFFSET_11 0xA152
+#define mmPA_CL_VPORT_XOFFSET_12 0xA158
+#define mmPA_CL_VPORT_XOFFSET_13 0xA15E
+#define mmPA_CL_VPORT_XOFFSET_14 0xA164
+#define mmPA_CL_VPORT_XOFFSET_15 0xA16A
+#define mmPA_CL_VPORT_XOFFSET_2 0xA11C
+#define mmPA_CL_VPORT_XOFFSET_3 0xA122
+#define mmPA_CL_VPORT_XOFFSET_4 0xA128
+#define mmPA_CL_VPORT_XOFFSET_5 0xA12E
+#define mmPA_CL_VPORT_XOFFSET_6 0xA134
+#define mmPA_CL_VPORT_XOFFSET_7 0xA13A
+#define mmPA_CL_VPORT_XOFFSET_8 0xA140
+#define mmPA_CL_VPORT_XOFFSET_9 0xA146
+#define mmPA_CL_VPORT_XSCALE 0xA10F
+#define mmPA_CL_VPORT_XSCALE_10 0xA14B
+#define mmPA_CL_VPORT_XSCALE_1 0xA115
+#define mmPA_CL_VPORT_XSCALE_11 0xA151
+#define mmPA_CL_VPORT_XSCALE_12 0xA157
+#define mmPA_CL_VPORT_XSCALE_13 0xA15D
+#define mmPA_CL_VPORT_XSCALE_14 0xA163
+#define mmPA_CL_VPORT_XSCALE_15 0xA169
+#define mmPA_CL_VPORT_XSCALE_2 0xA11B
+#define mmPA_CL_VPORT_XSCALE_3 0xA121
+#define mmPA_CL_VPORT_XSCALE_4 0xA127
+#define mmPA_CL_VPORT_XSCALE_5 0xA12D
+#define mmPA_CL_VPORT_XSCALE_6 0xA133
+#define mmPA_CL_VPORT_XSCALE_7 0xA139
+#define mmPA_CL_VPORT_XSCALE_8 0xA13F
+#define mmPA_CL_VPORT_XSCALE_9 0xA145
+#define mmPA_CL_VPORT_YOFFSET 0xA112
+#define mmPA_CL_VPORT_YOFFSET_10 0xA14E
+#define mmPA_CL_VPORT_YOFFSET_1 0xA118
+#define mmPA_CL_VPORT_YOFFSET_11 0xA154
+#define mmPA_CL_VPORT_YOFFSET_12 0xA15A
+#define mmPA_CL_VPORT_YOFFSET_13 0xA160
+#define mmPA_CL_VPORT_YOFFSET_14 0xA166
+#define mmPA_CL_VPORT_YOFFSET_15 0xA16C
+#define mmPA_CL_VPORT_YOFFSET_2 0xA11E
+#define mmPA_CL_VPORT_YOFFSET_3 0xA124
+#define mmPA_CL_VPORT_YOFFSET_4 0xA12A
+#define mmPA_CL_VPORT_YOFFSET_5 0xA130
+#define mmPA_CL_VPORT_YOFFSET_6 0xA136
+#define mmPA_CL_VPORT_YOFFSET_7 0xA13C
+#define mmPA_CL_VPORT_YOFFSET_8 0xA142
+#define mmPA_CL_VPORT_YOFFSET_9 0xA148
+#define mmPA_CL_VPORT_YSCALE 0xA111
+#define mmPA_CL_VPORT_YSCALE_10 0xA14D
+#define mmPA_CL_VPORT_YSCALE_1 0xA117
+#define mmPA_CL_VPORT_YSCALE_11 0xA153
+#define mmPA_CL_VPORT_YSCALE_12 0xA159
+#define mmPA_CL_VPORT_YSCALE_13 0xA15F
+#define mmPA_CL_VPORT_YSCALE_14 0xA165
+#define mmPA_CL_VPORT_YSCALE_15 0xA16B
+#define mmPA_CL_VPORT_YSCALE_2 0xA11D
+#define mmPA_CL_VPORT_YSCALE_3 0xA123
+#define mmPA_CL_VPORT_YSCALE_4 0xA129
+#define mmPA_CL_VPORT_YSCALE_5 0xA12F
+#define mmPA_CL_VPORT_YSCALE_6 0xA135
+#define mmPA_CL_VPORT_YSCALE_7 0xA13B
+#define mmPA_CL_VPORT_YSCALE_8 0xA141
+#define mmPA_CL_VPORT_YSCALE_9 0xA147
+#define mmPA_CL_VPORT_ZOFFSET 0xA114
+#define mmPA_CL_VPORT_ZOFFSET_10 0xA150
+#define mmPA_CL_VPORT_ZOFFSET_1 0xA11A
+#define mmPA_CL_VPORT_ZOFFSET_11 0xA156
+#define mmPA_CL_VPORT_ZOFFSET_12 0xA15C
+#define mmPA_CL_VPORT_ZOFFSET_13 0xA162
+#define mmPA_CL_VPORT_ZOFFSET_14 0xA168
+#define mmPA_CL_VPORT_ZOFFSET_15 0xA16E
+#define mmPA_CL_VPORT_ZOFFSET_2 0xA120
+#define mmPA_CL_VPORT_ZOFFSET_3 0xA126
+#define mmPA_CL_VPORT_ZOFFSET_4 0xA12C
+#define mmPA_CL_VPORT_ZOFFSET_5 0xA132
+#define mmPA_CL_VPORT_ZOFFSET_6 0xA138
+#define mmPA_CL_VPORT_ZOFFSET_7 0xA13E
+#define mmPA_CL_VPORT_ZOFFSET_8 0xA144
+#define mmPA_CL_VPORT_ZOFFSET_9 0xA14A
+#define mmPA_CL_VPORT_ZSCALE 0xA113
+#define mmPA_CL_VPORT_ZSCALE_10 0xA14F
+#define mmPA_CL_VPORT_ZSCALE_1 0xA119
+#define mmPA_CL_VPORT_ZSCALE_11 0xA155
+#define mmPA_CL_VPORT_ZSCALE_12 0xA15B
+#define mmPA_CL_VPORT_ZSCALE_13 0xA161
+#define mmPA_CL_VPORT_ZSCALE_14 0xA167
+#define mmPA_CL_VPORT_ZSCALE_15 0xA16D
+#define mmPA_CL_VPORT_ZSCALE_2 0xA11F
+#define mmPA_CL_VPORT_ZSCALE_3 0xA125
+#define mmPA_CL_VPORT_ZSCALE_4 0xA12B
+#define mmPA_CL_VPORT_ZSCALE_5 0xA131
+#define mmPA_CL_VPORT_ZSCALE_6 0xA137
+#define mmPA_CL_VPORT_ZSCALE_7 0xA13D
+#define mmPA_CL_VPORT_ZSCALE_8 0xA143
+#define mmPA_CL_VPORT_ZSCALE_9 0xA149
+#define mmPA_CL_VS_OUT_CNTL 0xA207
+#define mmPA_CL_VTE_CNTL 0xA206
+#define mmPA_SC_AA_CONFIG 0xA2F8
+#define mmPA_SC_AA_MASK_X0Y0_X1Y0 0xA30E
+#define mmPA_SC_AA_MASK_X0Y1_X1Y1 0xA30F
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0 0xA2FE
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1 0xA2FF
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2 0xA300
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3 0xA301
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0 0xA306
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1 0xA307
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2 0xA308
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3 0xA309
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0 0xA302
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1 0xA303
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2 0xA304
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3 0xA305
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0 0xA30A
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1 0xA30B
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2 0xA30C
+#define mmPA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3 0xA30D
+#define mmPA_SC_CENTROID_PRIORITY_0 0xA2F5
+#define mmPA_SC_CENTROID_PRIORITY_1 0xA2F6
+#define mmPA_SC_CLIPRECT_0_BR 0xA085
+#define mmPA_SC_CLIPRECT_0_TL 0xA084
+#define mmPA_SC_CLIPRECT_1_BR 0xA087
+#define mmPA_SC_CLIPRECT_1_TL 0xA086
+#define mmPA_SC_CLIPRECT_2_BR 0xA089
+#define mmPA_SC_CLIPRECT_2_TL 0xA088
+#define mmPA_SC_CLIPRECT_3_BR 0xA08B
+#define mmPA_SC_CLIPRECT_3_TL 0xA08A
+#define mmPA_SC_CLIPRECT_RULE 0xA083
+#define mmPA_SC_DEBUG_CNTL 0x22F6
+#define mmPA_SC_DEBUG_DATA 0x22F7
+#define mmPA_SC_EDGERULE 0xA08C
+#define mmPA_SC_ENHANCE 0x22FC
+#define mmPA_SC_FIFO_DEPTH_CNTL 0x2295
+#define mmPA_SC_FIFO_SIZE 0x22F3
+#define mmPA_SC_FORCE_EOV_MAX_CNTS 0x22C9
+#define mmPA_SC_GENERIC_SCISSOR_BR 0xA091
+#define mmPA_SC_GENERIC_SCISSOR_TL 0xA090
+#define mmPA_SC_IF_FIFO_SIZE 0x22F5
+#define mmPA_SC_LINE_CNTL 0xA2F7
+#define mmPA_SC_LINE_STIPPLE 0xA283
+#define mmPA_SC_LINE_STIPPLE_STATE 0x22C4
+#define mmPA_SC_MODE_CNTL_0 0xA292
+#define mmPA_SC_MODE_CNTL_1 0xA293
+#define mmPA_SC_PERFCOUNTER0_HI 0x22A9
+#define mmPA_SC_PERFCOUNTER0_LO 0x22A8
+#define mmPA_SC_PERFCOUNTER0_SELECT 0x22A0
+#define mmPA_SC_PERFCOUNTER1_HI 0x22AB
+#define mmPA_SC_PERFCOUNTER1_LO 0x22AA
+#define mmPA_SC_PERFCOUNTER1_SELECT 0x22A1
+#define mmPA_SC_PERFCOUNTER2_HI 0x22AD
+#define mmPA_SC_PERFCOUNTER2_LO 0x22AC
+#define mmPA_SC_PERFCOUNTER2_SELECT 0x22A2
+#define mmPA_SC_PERFCOUNTER3_HI 0x22AF
+#define mmPA_SC_PERFCOUNTER3_LO 0x22AE
+#define mmPA_SC_PERFCOUNTER3_SELECT 0x22A3
+#define mmPA_SC_PERFCOUNTER4_HI 0x22B1
+#define mmPA_SC_PERFCOUNTER4_LO 0x22B0
+#define mmPA_SC_PERFCOUNTER4_SELECT 0x22A4
+#define mmPA_SC_PERFCOUNTER5_HI 0x22B3
+#define mmPA_SC_PERFCOUNTER5_LO 0x22B2
+#define mmPA_SC_PERFCOUNTER5_SELECT 0x22A5
+#define mmPA_SC_PERFCOUNTER6_HI 0x22B5
+#define mmPA_SC_PERFCOUNTER6_LO 0x22B4
+#define mmPA_SC_PERFCOUNTER6_SELECT 0x22A6
+#define mmPA_SC_PERFCOUNTER7_HI 0x22B7
+#define mmPA_SC_PERFCOUNTER7_LO 0x22B6
+#define mmPA_SC_PERFCOUNTER7_SELECT 0x22A7
+#define mmPA_SC_RASTER_CONFIG 0xA0D4
+#define mmPA_SC_SCREEN_SCISSOR_BR 0xA00D
+#define mmPA_SC_SCREEN_SCISSOR_TL 0xA00C
+#define mmPA_SC_VPORT_SCISSOR_0_BR 0xA095
+#define mmPA_SC_VPORT_SCISSOR_0_TL 0xA094
+#define mmPA_SC_VPORT_SCISSOR_10_BR 0xA0A9
+#define mmPA_SC_VPORT_SCISSOR_10_TL 0xA0A8
+#define mmPA_SC_VPORT_SCISSOR_11_BR 0xA0AB
+#define mmPA_SC_VPORT_SCISSOR_11_TL 0xA0AA
+#define mmPA_SC_VPORT_SCISSOR_12_BR 0xA0AD
+#define mmPA_SC_VPORT_SCISSOR_12_TL 0xA0AC
+#define mmPA_SC_VPORT_SCISSOR_13_BR 0xA0AF
+#define mmPA_SC_VPORT_SCISSOR_13_TL 0xA0AE
+#define mmPA_SC_VPORT_SCISSOR_14_BR 0xA0B1
+#define mmPA_SC_VPORT_SCISSOR_14_TL 0xA0B0
+#define mmPA_SC_VPORT_SCISSOR_15_BR 0xA0B3
+#define mmPA_SC_VPORT_SCISSOR_15_TL 0xA0B2
+#define mmPA_SC_VPORT_SCISSOR_1_BR 0xA097
+#define mmPA_SC_VPORT_SCISSOR_1_TL 0xA096
+#define mmPA_SC_VPORT_SCISSOR_2_BR 0xA099
+#define mmPA_SC_VPORT_SCISSOR_2_TL 0xA098
+#define mmPA_SC_VPORT_SCISSOR_3_BR 0xA09B
+#define mmPA_SC_VPORT_SCISSOR_3_TL 0xA09A
+#define mmPA_SC_VPORT_SCISSOR_4_BR 0xA09D
+#define mmPA_SC_VPORT_SCISSOR_4_TL 0xA09C
+#define mmPA_SC_VPORT_SCISSOR_5_BR 0xA09F
+#define mmPA_SC_VPORT_SCISSOR_5_TL 0xA09E
+#define mmPA_SC_VPORT_SCISSOR_6_BR 0xA0A1
+#define mmPA_SC_VPORT_SCISSOR_6_TL 0xA0A0
+#define mmPA_SC_VPORT_SCISSOR_7_BR 0xA0A3
+#define mmPA_SC_VPORT_SCISSOR_7_TL 0xA0A2
+#define mmPA_SC_VPORT_SCISSOR_8_BR 0xA0A5
+#define mmPA_SC_VPORT_SCISSOR_8_TL 0xA0A4
+#define mmPA_SC_VPORT_SCISSOR_9_BR 0xA0A7
+#define mmPA_SC_VPORT_SCISSOR_9_TL 0xA0A6
+#define mmPA_SC_VPORT_ZMAX_0 0xA0B5
+#define mmPA_SC_VPORT_ZMAX_10 0xA0C9
+#define mmPA_SC_VPORT_ZMAX_1 0xA0B7
+#define mmPA_SC_VPORT_ZMAX_11 0xA0CB
+#define mmPA_SC_VPORT_ZMAX_12 0xA0CD
+#define mmPA_SC_VPORT_ZMAX_13 0xA0CF
+#define mmPA_SC_VPORT_ZMAX_14 0xA0D1
+#define mmPA_SC_VPORT_ZMAX_15 0xA0D3
+#define mmPA_SC_VPORT_ZMAX_2 0xA0B9
+#define mmPA_SC_VPORT_ZMAX_3 0xA0BB
+#define mmPA_SC_VPORT_ZMAX_4 0xA0BD
+#define mmPA_SC_VPORT_ZMAX_5 0xA0BF
+#define mmPA_SC_VPORT_ZMAX_6 0xA0C1
+#define mmPA_SC_VPORT_ZMAX_7 0xA0C3
+#define mmPA_SC_VPORT_ZMAX_8 0xA0C5
+#define mmPA_SC_VPORT_ZMAX_9 0xA0C7
+#define mmPA_SC_VPORT_ZMIN_0 0xA0B4
+#define mmPA_SC_VPORT_ZMIN_10 0xA0C8
+#define mmPA_SC_VPORT_ZMIN_1 0xA0B6
+#define mmPA_SC_VPORT_ZMIN_11 0xA0CA
+#define mmPA_SC_VPORT_ZMIN_12 0xA0CC
+#define mmPA_SC_VPORT_ZMIN_13 0xA0CE
+#define mmPA_SC_VPORT_ZMIN_14 0xA0D0
+#define mmPA_SC_VPORT_ZMIN_15 0xA0D2
+#define mmPA_SC_VPORT_ZMIN_2 0xA0B8
+#define mmPA_SC_VPORT_ZMIN_3 0xA0BA
+#define mmPA_SC_VPORT_ZMIN_4 0xA0BC
+#define mmPA_SC_VPORT_ZMIN_5 0xA0BE
+#define mmPA_SC_VPORT_ZMIN_6 0xA0C0
+#define mmPA_SC_VPORT_ZMIN_7 0xA0C2
+#define mmPA_SC_VPORT_ZMIN_8 0xA0C4
+#define mmPA_SC_VPORT_ZMIN_9 0xA0C6
+#define mmPA_SC_WINDOW_OFFSET 0xA080
+#define mmPA_SC_WINDOW_SCISSOR_BR 0xA082
+#define mmPA_SC_WINDOW_SCISSOR_TL 0xA081
+#define mmPA_SU_CNTL_STATUS 0x2294
+#define mmPA_SU_DEBUG_CNTL 0x2280
+#define mmPA_SU_DEBUG_DATA 0x2281
+#define mmPA_SU_HARDWARE_SCREEN_OFFSET 0xA08D
+#define mmPA_SU_LINE_CNTL 0xA282
+#define mmPA_SU_LINE_STIPPLE_CNTL 0xA209
+#define mmPA_SU_LINE_STIPPLE_SCALE 0xA20A
+#define mmPA_SU_LINE_STIPPLE_VALUE 0x2298
+#define mmPA_SU_PERFCOUNTER0_HI 0x228D
+#define mmPA_SU_PERFCOUNTER0_LO 0x228C
+#define mmPA_SU_PERFCOUNTER0_SELECT 0x2288
+#define mmPA_SU_PERFCOUNTER1_HI 0x228F
+#define mmPA_SU_PERFCOUNTER1_LO 0x228E
+#define mmPA_SU_PERFCOUNTER1_SELECT 0x2289
+#define mmPA_SU_PERFCOUNTER2_HI 0x2291
+#define mmPA_SU_PERFCOUNTER2_LO 0x2290
+#define mmPA_SU_PERFCOUNTER2_SELECT 0x228A
+#define mmPA_SU_PERFCOUNTER3_HI 0x2293
+#define mmPA_SU_PERFCOUNTER3_LO 0x2292
+#define mmPA_SU_PERFCOUNTER3_SELECT 0x228B
+#define mmPA_SU_POINT_MINMAX 0xA281
+#define mmPA_SU_POINT_SIZE 0xA280
+#define mmPA_SU_POLY_OFFSET_BACK_OFFSET 0xA2E3
+#define mmPA_SU_POLY_OFFSET_BACK_SCALE 0xA2E2
+#define mmPA_SU_POLY_OFFSET_CLAMP 0xA2DF
+#define mmPA_SU_POLY_OFFSET_DB_FMT_CNTL 0xA2DE
+#define mmPA_SU_POLY_OFFSET_FRONT_OFFSET 0xA2E1
+#define mmPA_SU_POLY_OFFSET_FRONT_SCALE 0xA2E0
+#define mmPA_SU_PRIM_FILTER_CNTL 0xA20B
+#define mmPA_SU_SC_MODE_CNTL 0xA205
+#define mmPA_SU_VTX_CNTL 0xA2F9
+#define mmRAS_BCI_SIGNATURE0 0x339E
+#define mmRAS_BCI_SIGNATURE1 0x339F
+#define mmRAS_CB_SIGNATURE0 0x339D
+#define mmRAS_DB_SIGNATURE0 0x338B
+#define mmRAS_IA_SIGNATURE0 0x3397
+#define mmRAS_IA_SIGNATURE1 0x3398
+#define mmRAS_PA_SIGNATURE0 0x338C
+#define mmRAS_SC_SIGNATURE0 0x338F
+#define mmRAS_SC_SIGNATURE1 0x3390
+#define mmRAS_SC_SIGNATURE2 0x3391
+#define mmRAS_SC_SIGNATURE3 0x3392
+#define mmRAS_SC_SIGNATURE4 0x3393
+#define mmRAS_SC_SIGNATURE5 0x3394
+#define mmRAS_SC_SIGNATURE6 0x3395
+#define mmRAS_SC_SIGNATURE7 0x3396
+#define mmRAS_SIGNATURE_CONTROL 0x3380
+#define mmRAS_SIGNATURE_MASK 0x3381
+#define mmRAS_SPI_SIGNATURE0 0x3399
+#define mmRAS_SPI_SIGNATURE1 0x339A
+#define mmRAS_SQ_SIGNATURE0 0x338E
+#define mmRAS_SX_SIGNATURE0 0x3382
+#define mmRAS_SX_SIGNATURE1 0x3383
+#define mmRAS_SX_SIGNATURE2 0x3384
+#define mmRAS_SX_SIGNATURE3 0x3385
+#define mmRAS_TA_SIGNATURE0 0x339B
+#define mmRAS_TD_SIGNATURE0 0x339C
+#define mmRAS_VGT_SIGNATURE0 0x338D
+#define mmRLC_AUTO_PG_CTRL 0x310D
+#define mmRLC_CAPTURE_GPU_CLOCK_COUNT 0x30D0
+#define mmRLC_CGCG_CGLS_CTRL 0x3101
+#define mmRLC_CGCG_RAMP_CTRL 0x3102
+#define mmRLC_CGTT_MGCG_OVERRIDE 0x3100
+#define mmRLC_CNTL 0x30C0
+#define mmRLC_CU_STATUS 0x3106
+#define mmRLC_DEBUG 0x30CA
+#define mmRLC_DEBUG_SELECT 0x30C9
+#define mmRLC_DRIVER_CPDMA_STATUS 0x30C7
+#define mmRLC_DYN_PG_REQUEST 0x3104
+#define mmRLC_DYN_PG_STATUS 0x3103
+#define mmRLC_GPU_CLOCK_32 0x30D5
+#define mmRLC_GPU_CLOCK_32_RES_SEL 0x30D4
+#define mmRLC_GPU_CLOCK_COUNT_LSB 0x30CE
+#define mmRLC_GPU_CLOCK_COUNT_MSB 0x30CF
+#define mmRLC_LB_ALWAYS_ACTIVE_CU_MASK 0x3108
+#define mmRLC_LB_CNTL 0x30C3
+#define mmRLC_LB_CNTR_INIT 0x30C6
+#define mmRLC_LB_CNTR_MAX 0x30C5
+#define mmRLC_LB_INIT_CU_MASK 0x3107
+#define mmRLC_LB_PARAMS 0x3109
+#define mmRLC_LOAD_BALANCE_CNTR 0x30F6
+#define mmRLC_MAX_PG_CU 0x310C
+#define mmRLC_MC_CNTL 0x30D1
+#define mmRLC_MEM_SLP_CNTL 0x30D8
+#define mmRLC_PERFCOUNTER0_HI 0x30DC
+#define mmRLC_PERFCOUNTER0_LO 0x30DB
+#define mmRLC_PERFCOUNTER0_SELECT 0x30DA
+#define mmRLC_PERFCOUNTER1_HI 0x30DF
+#define mmRLC_PERFCOUNTER1_LO 0x30DE
+#define mmRLC_PERFCOUNTER1_SELECT 0x30DD
+#define mmRLC_PERFMON_CNTL 0x30D9
+#define mmRLC_PG_ALWAYS_ON_CU_MASK 0x310B
+#define mmRLC_PG_CNTL 0x30D7
+#define mmRLC_SAVE_AND_RESTORE_BASE 0x30C4
+#define mmRLC_SERDES_RD_DATA_0 0x3112
+#define mmRLC_SERDES_RD_DATA_1 0x3113
+#define mmRLC_SERDES_RD_DATA_2 0x3114
+#define mmRLC_SERDES_RD_MASTER_INDEX 0x3111
+#define mmRLC_SERDES_WR_CTRL 0x3117
+#define mmRLC_SERDES_WR_DATA 0x3118
+#define mmRLC_SMU_GRBM_REG_SAVE_CTRL 0x310E
+#define mmRLC_SMU_PG_CTRL 0x310F
+#define mmRLC_SMU_PG_WAKE_UP_CTRL 0x3110
+#define mmRLC_SOFT_RESET_GPU 0x30D6
+#define mmRLC_STAT 0x30D3
+#define mmRLC_THREAD1_DELAY 0x310A
+#define mmRLC_UCODE_CNTL 0x30D2
+#define mmSCRATCH_ADDR 0x2151
+#define mmSCRATCH_REG0 0x2140
+#define mmSCRATCH_REG1 0x2141
+#define mmSCRATCH_REG2 0x2142
+#define mmSCRATCH_REG3 0x2143
+#define mmSCRATCH_REG4 0x2144
+#define mmSCRATCH_REG5 0x2145
+#define mmSCRATCH_REG6 0x2146
+#define mmSCRATCH_REG7 0x2147
+#define mmSCRATCH_UMSK 0x2150
+#define mmSPI_ARB_CYCLES_0 0x243D
+#define mmSPI_ARB_CYCLES_1 0x243E
+#define mmSPI_ARB_PRIORITY 0x243C
+#define mmSPI_BARYC_CNTL 0xA1B8
+#define mmSPI_CONFIG_CNTL 0x2440
+#define mmSPI_CONFIG_CNTL_1 0x244F
+#define mmSPI_DEBUG_BUSY 0x2450
+#define mmSPI_DEBUG_CNTL 0x2441
+#define mmSPI_DEBUG_READ 0x2442
+#define mmSPI_GDS_CREDITS 0x24D8
+#define mmSPI_INTERP_CONTROL_0 0xA1B5
+#define mmSPI_LB_CTR_CTRL 0x24D4
+#define mmSPI_LB_CU_MASK 0x24D5
+#define mmSPI_LB_DATA_REG 0x24D6
+#define mmSPI_PERFCOUNTER0_HI 0x2447
+#define mmSPI_PERFCOUNTER0_LO 0x2448
+#define mmSPI_PERFCOUNTER0_SELECT 0x2443
+#define mmSPI_PERFCOUNTER1_HI 0x2449
+#define mmSPI_PERFCOUNTER1_LO 0x244A
+#define mmSPI_PERFCOUNTER1_SELECT 0x2444
+#define mmSPI_PERFCOUNTER2_HI 0x244B
+#define mmSPI_PERFCOUNTER2_LO 0x244C
+#define mmSPI_PERFCOUNTER2_SELECT 0x2445
+#define mmSPI_PERFCOUNTER3_HI 0x244D
+#define mmSPI_PERFCOUNTER3_LO 0x244E
+#define mmSPI_PERFCOUNTER3_SELECT 0x2446
+#define mmSPI_PERFCOUNTER_BINS 0x243F
+#define mmSPI_PG_ENABLE_STATIC_CU_MASK 0x24D7
+#define mmSPI_PS_IN_CONTROL 0xA1B6
+#define mmSPI_PS_INPUT_ADDR 0xA1B4
+#define mmSPI_PS_INPUT_CNTL_0 0xA191
+#define mmSPI_PS_INPUT_CNTL_10 0xA19B
+#define mmSPI_PS_INPUT_CNTL_1 0xA192
+#define mmSPI_PS_INPUT_CNTL_11 0xA19C
+#define mmSPI_PS_INPUT_CNTL_12 0xA19D
+#define mmSPI_PS_INPUT_CNTL_13 0xA19E
+#define mmSPI_PS_INPUT_CNTL_14 0xA19F
+#define mmSPI_PS_INPUT_CNTL_15 0xA1A0
+#define mmSPI_PS_INPUT_CNTL_16 0xA1A1
+#define mmSPI_PS_INPUT_CNTL_17 0xA1A2
+#define mmSPI_PS_INPUT_CNTL_18 0xA1A3
+#define mmSPI_PS_INPUT_CNTL_19 0xA1A4
+#define mmSPI_PS_INPUT_CNTL_20 0xA1A5
+#define mmSPI_PS_INPUT_CNTL_2 0xA193
+#define mmSPI_PS_INPUT_CNTL_21 0xA1A6
+#define mmSPI_PS_INPUT_CNTL_22 0xA1A7
+#define mmSPI_PS_INPUT_CNTL_23 0xA1A8
+#define mmSPI_PS_INPUT_CNTL_24 0xA1A9
+#define mmSPI_PS_INPUT_CNTL_25 0xA1AA
+#define mmSPI_PS_INPUT_CNTL_26 0xA1AB
+#define mmSPI_PS_INPUT_CNTL_27 0xA1AC
+#define mmSPI_PS_INPUT_CNTL_28 0xA1AD
+#define mmSPI_PS_INPUT_CNTL_29 0xA1AE
+#define mmSPI_PS_INPUT_CNTL_30 0xA1AF
+#define mmSPI_PS_INPUT_CNTL_3 0xA194
+#define mmSPI_PS_INPUT_CNTL_31 0xA1B0
+#define mmSPI_PS_INPUT_CNTL_4 0xA195
+#define mmSPI_PS_INPUT_CNTL_5 0xA196
+#define mmSPI_PS_INPUT_CNTL_6 0xA197
+#define mmSPI_PS_INPUT_CNTL_7 0xA198
+#define mmSPI_PS_INPUT_CNTL_8 0xA199
+#define mmSPI_PS_INPUT_CNTL_9 0xA19A
+#define mmSPI_PS_INPUT_ENA 0xA1B3
+#define mmSPI_PS_MAX_WAVE_ID 0x243B
+#define mmSPI_SHADER_COL_FORMAT 0xA1C5
+#define mmSPI_SHADER_PGM_HI_ES 0x2CC9
+#define mmSPI_SHADER_PGM_HI_GS 0x2C89
+#define mmSPI_SHADER_PGM_HI_HS 0x2D09
+#define mmSPI_SHADER_PGM_HI_LS 0x2D49
+#define mmSPI_SHADER_PGM_HI_PS 0x2C09
+#define mmSPI_SHADER_PGM_HI_VS 0x2C49
+#define mmSPI_SHADER_PGM_LO_ES 0x2CC8
+#define mmSPI_SHADER_PGM_LO_GS 0x2C88
+#define mmSPI_SHADER_PGM_LO_HS 0x2D08
+#define mmSPI_SHADER_PGM_LO_LS 0x2D48
+#define mmSPI_SHADER_PGM_LO_PS 0x2C08
+#define mmSPI_SHADER_PGM_LO_VS 0x2C48
+#define mmSPI_SHADER_PGM_RSRC1_ES 0x2CCA
+#define mmSPI_SHADER_PGM_RSRC1_GS 0x2C8A
+#define mmSPI_SHADER_PGM_RSRC1_HS 0x2D0A
+#define mmSPI_SHADER_PGM_RSRC1_LS 0x2D4A
+#define mmSPI_SHADER_PGM_RSRC1_PS 0x2C0A
+#define mmSPI_SHADER_PGM_RSRC1_VS 0x2C4A
+#define mmSPI_SHADER_PGM_RSRC2_ES 0x2CCB
+#define mmSPI_SHADER_PGM_RSRC2_GS 0x2C8B
+#define mmSPI_SHADER_PGM_RSRC2_HS 0x2D0B
+#define mmSPI_SHADER_PGM_RSRC2_LS 0x2D4B
+#define mmSPI_SHADER_PGM_RSRC2_PS 0x2C0B
+#define mmSPI_SHADER_PGM_RSRC2_VS 0x2C4B
+#define mmSPI_SHADER_POS_FORMAT 0xA1C3
+#define mmSPI_SHADER_TBA_HI_ES 0x2CC1
+#define mmSPI_SHADER_TBA_HI_GS 0x2C81
+#define mmSPI_SHADER_TBA_HI_HS 0x2D01
+#define mmSPI_SHADER_TBA_HI_LS 0x2D41
+#define mmSPI_SHADER_TBA_HI_PS 0x2C01
+#define mmSPI_SHADER_TBA_HI_VS 0x2C41
+#define mmSPI_SHADER_TBA_LO_ES 0x2CC0
+#define mmSPI_SHADER_TBA_LO_GS 0x2C80
+#define mmSPI_SHADER_TBA_LO_HS 0x2D00
+#define mmSPI_SHADER_TBA_LO_LS 0x2D40
+#define mmSPI_SHADER_TBA_LO_PS 0x2C00
+#define mmSPI_SHADER_TBA_LO_VS 0x2C40
+#define mmSPI_SHADER_TMA_HI_ES 0x2CC3
+#define mmSPI_SHADER_TMA_HI_GS 0x2C83
+#define mmSPI_SHADER_TMA_HI_HS 0x2D03
+#define mmSPI_SHADER_TMA_HI_LS 0x2D43
+#define mmSPI_SHADER_TMA_HI_PS 0x2C03
+#define mmSPI_SHADER_TMA_HI_VS 0x2C43
+#define mmSPI_SHADER_TMA_LO_ES 0x2CC2
+#define mmSPI_SHADER_TMA_LO_GS 0x2C82
+#define mmSPI_SHADER_TMA_LO_HS 0x2D02
+#define mmSPI_SHADER_TMA_LO_LS 0x2D42
+#define mmSPI_SHADER_TMA_LO_PS 0x2C02
+#define mmSPI_SHADER_TMA_LO_VS 0x2C42
+#define mmSPI_SHADER_USER_DATA_ES_0 0x2CCC
+#define mmSPI_SHADER_USER_DATA_ES_10 0x2CD6
+#define mmSPI_SHADER_USER_DATA_ES_1 0x2CCD
+#define mmSPI_SHADER_USER_DATA_ES_11 0x2CD7
+#define mmSPI_SHADER_USER_DATA_ES_12 0x2CD8
+#define mmSPI_SHADER_USER_DATA_ES_13 0x2CD9
+#define mmSPI_SHADER_USER_DATA_ES_14 0x2CDA
+#define mmSPI_SHADER_USER_DATA_ES_15 0x2CDB
+#define mmSPI_SHADER_USER_DATA_ES_2 0x2CCE
+#define mmSPI_SHADER_USER_DATA_ES_3 0x2CCF
+#define mmSPI_SHADER_USER_DATA_ES_4 0x2CD0
+#define mmSPI_SHADER_USER_DATA_ES_5 0x2CD1
+#define mmSPI_SHADER_USER_DATA_ES_6 0x2CD2
+#define mmSPI_SHADER_USER_DATA_ES_7 0x2CD3
+#define mmSPI_SHADER_USER_DATA_ES_8 0x2CD4
+#define mmSPI_SHADER_USER_DATA_ES_9 0x2CD5
+#define mmSPI_SHADER_USER_DATA_GS_0 0x2C8C
+#define mmSPI_SHADER_USER_DATA_GS_10 0x2C96
+#define mmSPI_SHADER_USER_DATA_GS_1 0x2C8D
+#define mmSPI_SHADER_USER_DATA_GS_11 0x2C97
+#define mmSPI_SHADER_USER_DATA_GS_12 0x2C98
+#define mmSPI_SHADER_USER_DATA_GS_13 0x2C99
+#define mmSPI_SHADER_USER_DATA_GS_14 0x2C9A
+#define mmSPI_SHADER_USER_DATA_GS_15 0x2C9B
+#define mmSPI_SHADER_USER_DATA_GS_2 0x2C8E
+#define mmSPI_SHADER_USER_DATA_GS_3 0x2C8F
+#define mmSPI_SHADER_USER_DATA_GS_4 0x2C90
+#define mmSPI_SHADER_USER_DATA_GS_5 0x2C91
+#define mmSPI_SHADER_USER_DATA_GS_6 0x2C92
+#define mmSPI_SHADER_USER_DATA_GS_7 0x2C93
+#define mmSPI_SHADER_USER_DATA_GS_8 0x2C94
+#define mmSPI_SHADER_USER_DATA_GS_9 0x2C95
+#define mmSPI_SHADER_USER_DATA_HS_0 0x2D0C
+#define mmSPI_SHADER_USER_DATA_HS_10 0x2D16
+#define mmSPI_SHADER_USER_DATA_HS_1 0x2D0D
+#define mmSPI_SHADER_USER_DATA_HS_11 0x2D17
+#define mmSPI_SHADER_USER_DATA_HS_12 0x2D18
+#define mmSPI_SHADER_USER_DATA_HS_13 0x2D19
+#define mmSPI_SHADER_USER_DATA_HS_14 0x2D1A
+#define mmSPI_SHADER_USER_DATA_HS_15 0x2D1B
+#define mmSPI_SHADER_USER_DATA_HS_2 0x2D0E
+#define mmSPI_SHADER_USER_DATA_HS_3 0x2D0F
+#define mmSPI_SHADER_USER_DATA_HS_4 0x2D10
+#define mmSPI_SHADER_USER_DATA_HS_5 0x2D11
+#define mmSPI_SHADER_USER_DATA_HS_6 0x2D12
+#define mmSPI_SHADER_USER_DATA_HS_7 0x2D13
+#define mmSPI_SHADER_USER_DATA_HS_8 0x2D14
+#define mmSPI_SHADER_USER_DATA_HS_9 0x2D15
+#define mmSPI_SHADER_USER_DATA_LS_0 0x2D4C
+#define mmSPI_SHADER_USER_DATA_LS_10 0x2D56
+#define mmSPI_SHADER_USER_DATA_LS_1 0x2D4D
+#define mmSPI_SHADER_USER_DATA_LS_11 0x2D57
+#define mmSPI_SHADER_USER_DATA_LS_12 0x2D58
+#define mmSPI_SHADER_USER_DATA_LS_13 0x2D59
+#define mmSPI_SHADER_USER_DATA_LS_14 0x2D5A
+#define mmSPI_SHADER_USER_DATA_LS_15 0x2D5B
+#define mmSPI_SHADER_USER_DATA_LS_2 0x2D4E
+#define mmSPI_SHADER_USER_DATA_LS_3 0x2D4F
+#define mmSPI_SHADER_USER_DATA_LS_4 0x2D50
+#define mmSPI_SHADER_USER_DATA_LS_5 0x2D51
+#define mmSPI_SHADER_USER_DATA_LS_6 0x2D52
+#define mmSPI_SHADER_USER_DATA_LS_7 0x2D53
+#define mmSPI_SHADER_USER_DATA_LS_8 0x2D54
+#define mmSPI_SHADER_USER_DATA_LS_9 0x2D55
+#define mmSPI_SHADER_USER_DATA_PS_0 0x2C0C
+#define mmSPI_SHADER_USER_DATA_PS_10 0x2C16
+#define mmSPI_SHADER_USER_DATA_PS_1 0x2C0D
+#define mmSPI_SHADER_USER_DATA_PS_11 0x2C17
+#define mmSPI_SHADER_USER_DATA_PS_12 0x2C18
+#define mmSPI_SHADER_USER_DATA_PS_13 0x2C19
+#define mmSPI_SHADER_USER_DATA_PS_14 0x2C1A
+#define mmSPI_SHADER_USER_DATA_PS_15 0x2C1B
+#define mmSPI_SHADER_USER_DATA_PS_2 0x2C0E
+#define mmSPI_SHADER_USER_DATA_PS_3 0x2C0F
+#define mmSPI_SHADER_USER_DATA_PS_4 0x2C10
+#define mmSPI_SHADER_USER_DATA_PS_5 0x2C11
+#define mmSPI_SHADER_USER_DATA_PS_6 0x2C12
+#define mmSPI_SHADER_USER_DATA_PS_7 0x2C13
+#define mmSPI_SHADER_USER_DATA_PS_8 0x2C14
+#define mmSPI_SHADER_USER_DATA_PS_9 0x2C15
+#define mmSPI_SHADER_USER_DATA_VS_0 0x2C4C
+#define mmSPI_SHADER_USER_DATA_VS_10 0x2C56
+#define mmSPI_SHADER_USER_DATA_VS_1 0x2C4D
+#define mmSPI_SHADER_USER_DATA_VS_11 0x2C57
+#define mmSPI_SHADER_USER_DATA_VS_12 0x2C58
+#define mmSPI_SHADER_USER_DATA_VS_13 0x2C59
+#define mmSPI_SHADER_USER_DATA_VS_14 0x2C5A
+#define mmSPI_SHADER_USER_DATA_VS_15 0x2C5B
+#define mmSPI_SHADER_USER_DATA_VS_2 0x2C4E
+#define mmSPI_SHADER_USER_DATA_VS_3 0x2C4F
+#define mmSPI_SHADER_USER_DATA_VS_4 0x2C50
+#define mmSPI_SHADER_USER_DATA_VS_5 0x2C51
+#define mmSPI_SHADER_USER_DATA_VS_6 0x2C52
+#define mmSPI_SHADER_USER_DATA_VS_7 0x2C53
+#define mmSPI_SHADER_USER_DATA_VS_8 0x2C54
+#define mmSPI_SHADER_USER_DATA_VS_9 0x2C55
+#define mmSPI_SHADER_Z_FORMAT 0xA1C4
+#define mmSPI_SLAVE_DEBUG_BUSY 0x24D3
+#define mmSPI_SX_EXPORT_BUFFER_SIZES 0x24D9
+#define mmSPI_SX_SCOREBOARD_BUFFER_SIZES 0x24DA
+#define mmSPI_TMPRING_SIZE 0xA1BA
+#define mmSPI_VS_OUT_CONFIG 0xA1B1
+#define mmSQ_ALU_CLK_CTRL 0x2360
+#define mmSQ_BUF_RSRC_WORD0 0x23C0
+#define mmSQ_BUF_RSRC_WORD1 0x23C1
+#define mmSQ_BUF_RSRC_WORD2 0x23C2
+#define mmSQ_BUF_RSRC_WORD3 0x23C3
+#define mmSQC_CACHES 0x2302
+#define mmSQC_CONFIG 0x2301
+#define mmSQ_CONFIG 0x2300
+#define mmSQC_SECDED_CNT 0x23A0
+#define mmSQ_DEBUG_STS_GLOBAL 0x2309
+#define mmSQ_DED_CNT 0x23A2
+#define mmSQ_DED_INFO 0x23A3
+#define mmSQ_DS_0 0x237F
+#define mmSQ_DS_1 0x237F
+#define mmSQ_EXP_0 0x237F
+#define mmSQ_EXP_1 0x237F
+#define mmSQ_FIFO_SIZES 0x2305
+#define mmSQ_IMG_RSRC_WORD0 0x23C4
+#define mmSQ_IMG_RSRC_WORD1 0x23C5
+#define mmSQ_IMG_RSRC_WORD2 0x23C6
+#define mmSQ_IMG_RSRC_WORD3 0x23C7
+#define mmSQ_IMG_RSRC_WORD4 0x23C8
+#define mmSQ_IMG_RSRC_WORD5 0x23C9
+#define mmSQ_IMG_RSRC_WORD6 0x23CA
+#define mmSQ_IMG_RSRC_WORD7 0x23CB
+#define mmSQ_IMG_SAMP_WORD0 0x23CC
+#define mmSQ_IMG_SAMP_WORD1 0x23CD
+#define mmSQ_IMG_SAMP_WORD2 0x23CE
+#define mmSQ_IMG_SAMP_WORD3 0x23CF
+#define mmSQ_IND_CMD 0x237A
+#define mmSQ_IND_DATA 0x2379
+#define mmSQ_IND_INDEX 0x2378
+#define mmSQ_INST 0x237F
+#define mmSQ_LB_CTR_CTRL 0x2398
+#define mmSQ_LB_DATA_ALU_CYCLES 0x2399
+#define mmSQ_LB_DATA_ALU_STALLS 0x239B
+#define mmSQ_LB_DATA_TEX_CYCLES 0x239A
+#define mmSQ_LB_DATA_TEX_STALLS 0x239C
+#define mmSQ_MIMG_0 0x237F
+#define mmSQ_MIMG_1 0x237F
+#define mmSQ_MTBUF_0 0x237F
+#define mmSQ_MTBUF_1 0x237F
+#define mmSQ_MUBUF_0 0x237F
+#define mmSQ_MUBUF_1 0x237F
+#define mmSQ_PERFCOUNTER0_HI 0x2321
+#define mmSQ_PERFCOUNTER0_LO 0x2320
+#define mmSQ_PERFCOUNTER0_SELECT 0x2340
+#define mmSQ_PERFCOUNTER10_HI 0x2335
+#define mmSQ_PERFCOUNTER10_LO 0x2334
+#define mmSQ_PERFCOUNTER10_SELECT 0x234A
+#define mmSQ_PERFCOUNTER11_HI 0x2337
+#define mmSQ_PERFCOUNTER11_LO 0x2336
+#define mmSQ_PERFCOUNTER11_SELECT 0x234B
+#define mmSQ_PERFCOUNTER12_HI 0x2339
+#define mmSQ_PERFCOUNTER12_LO 0x2338
+#define mmSQ_PERFCOUNTER12_SELECT 0x234C
+#define mmSQ_PERFCOUNTER13_HI 0x233B
+#define mmSQ_PERFCOUNTER13_LO 0x233A
+#define mmSQ_PERFCOUNTER13_SELECT 0x234D
+#define mmSQ_PERFCOUNTER14_HI 0x233D
+#define mmSQ_PERFCOUNTER14_LO 0x233C
+#define mmSQ_PERFCOUNTER14_SELECT 0x234E
+#define mmSQ_PERFCOUNTER15_HI 0x233F
+#define mmSQ_PERFCOUNTER15_LO 0x233E
+#define mmSQ_PERFCOUNTER15_SELECT 0x234F
+#define mmSQ_PERFCOUNTER1_HI 0x2323
+#define mmSQ_PERFCOUNTER1_LO 0x2322
+#define mmSQ_PERFCOUNTER1_SELECT 0x2341
+#define mmSQ_PERFCOUNTER2_HI 0x2325
+#define mmSQ_PERFCOUNTER2_LO 0x2324
+#define mmSQ_PERFCOUNTER2_SELECT 0x2342
+#define mmSQ_PERFCOUNTER3_HI 0x2327
+#define mmSQ_PERFCOUNTER3_LO 0x2326
+#define mmSQ_PERFCOUNTER3_SELECT 0x2343
+#define mmSQ_PERFCOUNTER4_HI 0x2329
+#define mmSQ_PERFCOUNTER4_LO 0x2328
+#define mmSQ_PERFCOUNTER4_SELECT 0x2344
+#define mmSQ_PERFCOUNTER5_HI 0x232B
+#define mmSQ_PERFCOUNTER5_LO 0x232A
+#define mmSQ_PERFCOUNTER5_SELECT 0x2345
+#define mmSQ_PERFCOUNTER6_HI 0x232D
+#define mmSQ_PERFCOUNTER6_LO 0x232C
+#define mmSQ_PERFCOUNTER6_SELECT 0x2346
+#define mmSQ_PERFCOUNTER7_HI 0x232F
+#define mmSQ_PERFCOUNTER7_LO 0x232E
+#define mmSQ_PERFCOUNTER7_SELECT 0x2347
+#define mmSQ_PERFCOUNTER8_HI 0x2331
+#define mmSQ_PERFCOUNTER8_LO 0x2330
+#define mmSQ_PERFCOUNTER8_SELECT 0x2348
+#define mmSQ_PERFCOUNTER9_HI 0x2333
+#define mmSQ_PERFCOUNTER9_LO 0x2332
+#define mmSQ_PERFCOUNTER9_SELECT 0x2349
+#define mmSQ_PERFCOUNTER_CTRL 0x2306
+#define mmSQ_POWER_THROTTLE 0x2396
+#define mmSQ_POWER_THROTTLE2 0x2397
+#define mmSQ_RANDOM_WAVE_PRI 0x2303
+#define mmSQ_REG_CREDITS 0x2304
+#define mmSQ_SEC_CNT 0x23A1
+#define mmSQ_SMRD 0x237F
+#define mmSQ_SOP1 0x237F
+#define mmSQ_SOP2 0x237F
+#define mmSQ_SOPC 0x237F
+#define mmSQ_SOPK 0x237F
+#define mmSQ_SOPP 0x237F
+#define mmSQ_TEX_CLK_CTRL 0x2361
+#define mmSQ_THREAD_TRACE_BASE 0x2380
+#define mmSQ_THREAD_TRACE_CNTR 0x2390
+#define mmSQ_THREAD_TRACE_CTRL 0x238F
+#define mmSQ_THREAD_TRACE_HIWATER 0x2392
+#define mmSQ_THREAD_TRACE_MASK 0x2382
+#define mmSQ_THREAD_TRACE_MODE 0x238E
+#define mmSQ_THREAD_TRACE_PERF_MASK 0x2384
+#define mmSQ_THREAD_TRACE_SIZE 0x2381
+#define mmSQ_THREAD_TRACE_STATUS 0x238D
+#define mmSQ_THREAD_TRACE_TOKEN_MASK 0x2383
+#define mmSQ_THREAD_TRACE_USERDATA_0 0x2388
+#define mmSQ_THREAD_TRACE_USERDATA_1 0x2389
+#define mmSQ_THREAD_TRACE_USERDATA_2 0x238A
+#define mmSQ_THREAD_TRACE_USERDATA_3 0x238B
+#define mmSQ_THREAD_TRACE_WORD_CMN 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_EVENT 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_INST 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_INST_PC_1_OF_2 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_INST_PC_2_OF_2 0x23B1
+#define mmSQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2 0x23B1
+#define mmSQ_THREAD_TRACE_WORD_ISSUE 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_MISC 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_PERF_1_OF_2 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_PERF_2_OF_2 0x23B1
+#define mmSQ_THREAD_TRACE_WORD_REG_1_OF_2 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_REG_2_OF_2 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_TIME 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2 0x23B1
+#define mmSQ_THREAD_TRACE_WORD_WAVE 0x23B0
+#define mmSQ_THREAD_TRACE_WORD_WAVE_START 0x23B0
+#define mmSQ_THREAD_TRACE_WPTR 0x238C
+#define mmSQ_TIME_HI 0x237C
+#define mmSQ_TIME_LO 0x237D
+#define mmSQ_VINTRP 0x237F
+#define mmSQ_VOP1 0x237F
+#define mmSQ_VOP2 0x237F
+#define mmSQ_VOP3_0 0x237F
+#define mmSQ_VOP3_0_SDST_ENC 0x237F
+#define mmSQ_VOP3_1 0x237F
+#define mmSQ_VOPC 0x237F
+#define mmSX_DEBUG_1 0x2418
+#define mmSX_DEBUG_BUSY 0x2414
+#define mmSX_DEBUG_BUSY_2 0x2415
+#define mmSX_DEBUG_BUSY_3 0x2416
+#define mmSX_DEBUG_BUSY_4 0x2417
+#define mmSX_PERFCOUNTER0_HI 0x2421
+#define mmSX_PERFCOUNTER0_LO 0x2420
+#define mmSX_PERFCOUNTER0_SELECT 0x241C
+#define mmSX_PERFCOUNTER1_HI 0x2423
+#define mmSX_PERFCOUNTER1_LO 0x2422
+#define mmSX_PERFCOUNTER1_SELECT 0x241D
+#define mmSX_PERFCOUNTER2_HI 0x2425
+#define mmSX_PERFCOUNTER2_LO 0x2424
+#define mmSX_PERFCOUNTER2_SELECT 0x241E
+#define mmSX_PERFCOUNTER3_HI 0x2427
+#define mmSX_PERFCOUNTER3_LO 0x2426
+#define mmSX_PERFCOUNTER3_SELECT 0x241F
+#define mmTA_BC_BASE_ADDR 0xA020
+#define mmTA_CGTT_CTRL 0x2544
+#define mmTA_CNTL 0x2541
+#define mmTA_CNTL_AUX 0x2542
+#define mmTA_CS_BC_BASE_ADDR 0x2543
+#define mmTA_DEBUG_DATA 0x254D
+#define mmTA_DEBUG_INDEX 0x254C
+#define mmTA_PERFCOUNTER0_HI 0x2556
+#define mmTA_PERFCOUNTER0_LO 0x2555
+#define mmTA_PERFCOUNTER0_SELECT 0x2554
+#define mmTA_PERFCOUNTER1_HI 0x2562
+#define mmTA_PERFCOUNTER1_LO 0x2561
+#define mmTA_PERFCOUNTER1_SELECT 0x2560
+#define mmTA_SCRATCH 0x2564
+#define mmTA_STATUS 0x2548
+#define mmTCA_CGTT_SCLK_CTRL 0x2BC1
+#define mmTCA_CTRL 0x2BC0
+#define mmTCA_PERFCOUNTER0_HI 0x2BD2
+#define mmTCA_PERFCOUNTER0_LO 0x2BD1
+#define mmTCA_PERFCOUNTER0_SELECT 0x2BD0
+#define mmTCA_PERFCOUNTER1_HI 0x2BD5
+#define mmTCA_PERFCOUNTER1_LO 0x2BD4
+#define mmTCA_PERFCOUNTER1_SELECT 0x2BD3
+#define mmTCA_PERFCOUNTER2_HI 0x2BD8
+#define mmTCA_PERFCOUNTER2_LO 0x2BD7
+#define mmTCA_PERFCOUNTER2_SELECT 0x2BD6
+#define mmTCA_PERFCOUNTER3_HI 0x2BDB
+#define mmTCA_PERFCOUNTER3_LO 0x2BDA
+#define mmTCA_PERFCOUNTER3_SELECT 0x2BD9
+#define mmTCC_CGTT_SCLK_CTRL 0x2B81
+#define mmTCC_CTRL 0x2B80
+#define mmTCC_EDC_COUNTER 0x2B82
+#define mmTCC_PERFCOUNTER0_HI 0x2B92
+#define mmTCC_PERFCOUNTER0_LO 0x2B91
+#define mmTCC_PERFCOUNTER0_SELECT 0x2B90
+#define mmTCC_PERFCOUNTER1_HI 0x2B95
+#define mmTCC_PERFCOUNTER1_LO 0x2B94
+#define mmTCC_PERFCOUNTER1_SELECT 0x2B93
+#define mmTCC_PERFCOUNTER2_HI 0x2B98
+#define mmTCC_PERFCOUNTER2_LO 0x2B97
+#define mmTCC_PERFCOUNTER2_SELECT 0x2B96
+#define mmTCC_PERFCOUNTER3_HI 0x2B9B
+#define mmTCC_PERFCOUNTER3_LO 0x2B9A
+#define mmTCC_PERFCOUNTER3_SELECT 0x2B99
+#define mmTCI_CNTL_1 0x2B62
+#define mmTCI_CNTL_2 0x2B63
+#define mmTCI_STATUS 0x2B61
+#define mmTCP_ADDR_CONFIG 0x2B05
+#define mmTCP_BUFFER_ADDR_HASH_CNTL 0x2B16
+#define mmTCP_CHAN_STEER_HI 0x2B04
+#define mmTCP_CHAN_STEER_LO 0x2B03
+#define mmTCP_CNTL 0x2B02
+#define mmTCP_CREDIT 0x2B06
+#define mmTCP_EDC_COUNTER 0x2B17
+#define mmTCP_INVALIDATE 0x2B00
+#define mmTCP_PERFCOUNTER0_HI 0x2B0A
+#define mmTCP_PERFCOUNTER0_LO 0x2B0B
+#define mmTCP_PERFCOUNTER0_SELECT 0x2B09
+#define mmTCP_PERFCOUNTER1_HI 0x2B0D
+#define mmTCP_PERFCOUNTER1_LO 0x2B0E
+#define mmTCP_PERFCOUNTER1_SELECT 0x2B0C
+#define mmTCP_PERFCOUNTER2_HI 0x2B10
+#define mmTCP_PERFCOUNTER2_LO 0x2B11
+#define mmTCP_PERFCOUNTER2_SELECT 0x2B0F
+#define mmTCP_PERFCOUNTER3_HI 0x2B13
+#define mmTCP_PERFCOUNTER3_LO 0x2B14
+#define mmTCP_PERFCOUNTER3_SELECT 0x2B12
+#define mmTCP_STATUS 0x2B01
+#define mmTD_CGTT_CTRL 0x2527
+#define mmTD_CNTL 0x2525
+#define mmTD_DEBUG_DATA 0x2529
+#define mmTD_DEBUG_INDEX 0x2528
+#define mmTD_PERFCOUNTER0_HI 0x252E
+#define mmTD_PERFCOUNTER0_LO 0x252D
+#define mmTD_PERFCOUNTER0_SELECT 0x252C
+#define mmTD_SCRATCH 0x2530
+#define mmTD_STATUS 0x2526
+#define mmUSER_SQC_BANK_DISABLE 0x2308
+#define mmVGT_CACHE_INVALIDATION 0x2231
+#define mmVGT_CNTL_STATUS 0x223C
+#define mmVGT_DEBUG_CNTL 0x2238
+#define mmVGT_DEBUG_DATA 0x2239
+#define mmVGT_DMA_BASE 0xA1FA
+#define mmVGT_DMA_BASE_HI 0xA1F9
+#define mmVGT_DMA_DATA_FIFO_DEPTH 0x222D
+#define mmVGT_DMA_INDEX_TYPE 0xA29F
+#define mmVGT_DMA_MAX_SIZE 0xA29E
+#define mmVGT_DMA_NUM_INSTANCES 0xA2A2
+#define mmVGT_DMA_REQ_FIFO_DEPTH 0x222E
+#define mmVGT_DMA_SIZE 0xA29D
+#define mmVGT_DRAW_INIT_FIFO_DEPTH 0x222F
+#define mmVGT_DRAW_INITIATOR 0xA1FC
+#define mmVGT_ENHANCE 0xA294
+#define mmVGT_ESGS_RING_ITEMSIZE 0xA2AB
+#define mmVGT_ESGS_RING_SIZE 0x2232
+#define mmVGT_ES_PER_GS 0xA296
+#define mmVGT_EVENT_ADDRESS_REG 0xA1FE
+#define mmVGT_EVENT_INITIATOR 0xA2A4
+#define mmVGT_FIFO_DEPTHS 0x2234
+#define mmVGT_GROUP_DECR 0xA28B
+#define mmVGT_GROUP_FIRST_DECR 0xA28A
+#define mmVGT_GROUP_PRIM_TYPE 0xA289
+#define mmVGT_GROUP_VECT_0_CNTL 0xA28C
+#define mmVGT_GROUP_VECT_0_FMT_CNTL 0xA28E
+#define mmVGT_GROUP_VECT_1_CNTL 0xA28D
+#define mmVGT_GROUP_VECT_1_FMT_CNTL 0xA28F
+#define mmVGT_GS_INSTANCE_CNT 0xA2E4
+#define mmVGT_GS_MAX_VERT_OUT 0xA2CE
+#define mmVGT_GS_MODE 0xA290
+#define mmVGT_GS_OUT_PRIM_TYPE 0xA29B
+#define mmVGT_GS_PER_ES 0xA295
+#define mmVGT_GS_PER_VS 0xA297
+#define mmVGT_GS_VERTEX_REUSE 0x2235
+#define mmVGT_GS_VERT_ITEMSIZE 0xA2D7
+#define mmVGT_GS_VERT_ITEMSIZE_1 0xA2D8
+#define mmVGT_GS_VERT_ITEMSIZE_2 0xA2D9
+#define mmVGT_GS_VERT_ITEMSIZE_3 0xA2DA
+#define mmVGT_GSVS_RING_ITEMSIZE 0xA2AC
+#define mmVGT_GSVS_RING_OFFSET_1 0xA298
+#define mmVGT_GSVS_RING_OFFSET_2 0xA299
+#define mmVGT_GSVS_RING_OFFSET_3 0xA29A
+#define mmVGT_GSVS_RING_SIZE 0x2233
+#define mmVGT_HOS_CNTL 0xA285
+#define mmVGT_HOS_MAX_TESS_LEVEL 0xA286
+#define mmVGT_HOS_MIN_TESS_LEVEL 0xA287
+#define mmVGT_HOS_REUSE_DEPTH 0xA288
+#define mmVGT_HS_OFFCHIP_PARAM 0x226C
+#define mmVGT_IMMED_DATA 0xA1FD
+#define mmVGT_INDEX_TYPE 0x2257
+#define mmVGT_INDX_OFFSET 0xA102
+#define mmVGT_INSTANCE_STEP_RATE_0 0xA2A8
+#define mmVGT_INSTANCE_STEP_RATE_1 0xA2A9
+#define mmVGT_LAST_COPY_STATE 0x2230
+#define mmVGT_LS_HS_CONFIG 0xA2D6
+#define mmVGT_MAX_VTX_INDX 0xA100
+#define mmVGT_MC_LAT_CNTL 0x2236
+#define mmVGT_MIN_VTX_INDX 0xA101
+#define mmVGT_MULTI_PRIM_IB_RESET_EN 0xA2A5
+#define mmVGT_MULTI_PRIM_IB_RESET_INDX 0xA103
+#define mmVGT_NUM_INDICES 0x225C
+#define mmVGT_NUM_INSTANCES 0x225D
+#define mmVGT_OUT_DEALLOC_CNTL 0xA317
+#define mmVGT_OUTPUT_PATH_CNTL 0xA284
+#define mmVGT_PERFCOUNTER0_HI 0x224D
+#define mmVGT_PERFCOUNTER0_LO 0x224C
+#define mmVGT_PERFCOUNTER0_SELECT 0x2248
+#define mmVGT_PERFCOUNTER1_HI 0x224F
+#define mmVGT_PERFCOUNTER1_LO 0x224E
+#define mmVGT_PERFCOUNTER1_SELECT 0x2249
+#define mmVGT_PERFCOUNTER2_HI 0x2251
+#define mmVGT_PERFCOUNTER2_LO 0x2250
+#define mmVGT_PERFCOUNTER2_SELECT 0x224A
+#define mmVGT_PERFCOUNTER3_HI 0x2253
+#define mmVGT_PERFCOUNTER3_LO 0x2252
+#define mmVGT_PERFCOUNTER3_SELECT 0x224B
+#define mmVGT_PERFCOUNTER_SEID_MASK 0x2247
+#define mmVGT_PRIMITIVEID_EN 0xA2A1
+#define mmVGT_PRIMITIVEID_RESET 0xA2A3
+#define mmVGT_PRIMITIVE_TYPE 0x2256
+#define mmVGT_REUSE_OFF 0xA2AD
+#define mmVGT_SHADER_STAGES_EN 0xA2D5
+#define mmVGT_STRMOUT_BUFFER_CONFIG 0xA2E6
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_0 0x2258
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_1 0x2259
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_2 0x225A
+#define mmVGT_STRMOUT_BUFFER_FILLED_SIZE_3 0x225B
+#define mmVGT_STRMOUT_BUFFER_OFFSET_0 0xA2B7
+#define mmVGT_STRMOUT_BUFFER_OFFSET_1 0xA2BB
+#define mmVGT_STRMOUT_BUFFER_OFFSET_2 0xA2BF
+#define mmVGT_STRMOUT_BUFFER_OFFSET_3 0xA2C3
+#define mmVGT_STRMOUT_BUFFER_SIZE_0 0xA2B4
+#define mmVGT_STRMOUT_BUFFER_SIZE_1 0xA2B8
+#define mmVGT_STRMOUT_BUFFER_SIZE_2 0xA2BC
+#define mmVGT_STRMOUT_BUFFER_SIZE_3 0xA2C0
+#define mmVGT_STRMOUT_CONFIG 0xA2E5
+#define mmVGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE 0xA2CB
+#define mmVGT_STRMOUT_DRAW_OPAQUE_OFFSET 0xA2CA
+#define mmVGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE 0xA2CC
+#define mmVGT_STRMOUT_VTX_STRIDE_0 0xA2B5
+#define mmVGT_STRMOUT_VTX_STRIDE_1 0xA2B9
+#define mmVGT_STRMOUT_VTX_STRIDE_2 0xA2BD
+#define mmVGT_STRMOUT_VTX_STRIDE_3 0xA2C1
+#define mmVGT_SYS_CONFIG 0x2263
+#define mmVGT_TF_MEMORY_BASE 0x226E
+#define mmVGT_TF_PARAM 0xA2DB
+#define mmVGT_TF_RING_SIZE 0x2262
+#define mmVGT_VERTEX_REUSE_BLOCK_CNTL 0xA316
+#define mmVGT_VTX_CNT_EN 0xA2AE
+#define mmVGT_VTX_VECT_EJECT_REG 0x222C
+
+/* manually added from old sid.h */
+#define mmCB_PERFCOUNTER0_SELECT0                       0x2688
+#define mmCB_PERFCOUNTER1_SELECT0                       0x268A
+#define mmCB_PERFCOUNTER1_SELECT1                       0x268B
+#define mmCB_PERFCOUNTER2_SELECT0                       0x268C
+#define mmCB_PERFCOUNTER2_SELECT1                       0x268D
+#define mmCB_PERFCOUNTER3_SELECT0                       0x268E
+#define mmCB_PERFCOUNTER3_SELECT1                       0x268F
+#define mmCP_COHER_CNTL2                                0x217A
+#define mmCP_DEBUG                                      0x307F
+#define mmRLC_SERDES_MASTER_BUSY_0                      0x3119
+#define mmRLC_SERDES_MASTER_BUSY_1                      0x311A
+#define mmRLC_RL_BASE                                   0x30C1
+#define mmRLC_RL_SIZE                                   0x30C2
+#define mmRLC_UCODE_ADDR                                0x30CB
+#define mmRLC_UCODE_DATA                                0x30CC
+#define mmRLC_GCPM_GENERAL_3                            0x311E
+#define mmRLC_SERDES_WR_MASTER_MASK_0                   0x3115
+#define mmRLC_SERDES_WR_MASTER_MASK_1                   0x3116
+#define mmRLC_TTOP_D                                    0x3105
+#define mmRLC_CLEAR_STATE_RESTORE_BASE                  0x30C8
+#define mmRLC_PG_AO_CU_MASK                             0x310B
+#define mmSPI_STATIC_THREAD_MGMT_3                      0x243A
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_6_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,12821 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 GFX_6_0_SH_MASK_H
+#define GFX_6_0_SH_MASK_H
+
+#define BCI_DEBUG_READ__DATA_MASK 0x00ffffffL
+#define BCI_DEBUG_READ__DATA__SHIFT 0x00000000
+#define CB_BLEND0_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND0_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND0_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND0_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND0_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND0_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND0_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND0_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND0_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND0_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND0_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND0_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND0_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND0_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND0_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND0_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND0_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND0_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND1_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND1_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND1_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND1_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND1_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND1_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND1_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND1_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND1_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND1_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND1_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND1_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND1_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND1_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND1_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND1_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND1_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND1_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND2_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND2_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND2_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND2_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND2_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND2_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND2_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND2_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND2_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND2_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND2_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND2_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND2_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND2_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND2_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND2_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND2_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND2_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND3_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND3_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND3_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND3_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND3_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND3_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND3_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND3_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND3_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND3_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND3_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND3_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND3_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND3_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND3_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND3_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND3_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND3_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND4_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND4_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND4_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND4_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND4_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND4_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND4_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND4_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND4_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND4_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND4_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND4_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND4_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND4_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND4_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND4_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND4_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND4_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND5_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND5_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND5_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND5_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND5_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND5_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND5_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND5_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND5_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND5_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND5_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND5_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND5_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND5_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND5_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND5_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND5_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND5_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND6_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND6_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND6_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND6_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND6_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND6_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND6_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND6_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND6_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND6_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND6_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND6_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND6_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND6_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND6_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND6_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND6_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND6_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND7_CONTROL__ALPHA_COMB_FCN_MASK 0x00e00000L
+#define CB_BLEND7_CONTROL__ALPHA_COMB_FCN__SHIFT 0x00000015
+#define CB_BLEND7_CONTROL__ALPHA_DESTBLEND_MASK 0x1f000000L
+#define CB_BLEND7_CONTROL__ALPHA_DESTBLEND__SHIFT 0x00000018
+#define CB_BLEND7_CONTROL__ALPHA_SRCBLEND_MASK 0x001f0000L
+#define CB_BLEND7_CONTROL__ALPHA_SRCBLEND__SHIFT 0x00000010
+#define CB_BLEND7_CONTROL__COLOR_COMB_FCN_MASK 0x000000e0L
+#define CB_BLEND7_CONTROL__COLOR_COMB_FCN__SHIFT 0x00000005
+#define CB_BLEND7_CONTROL__COLOR_DESTBLEND_MASK 0x00001f00L
+#define CB_BLEND7_CONTROL__COLOR_DESTBLEND__SHIFT 0x00000008
+#define CB_BLEND7_CONTROL__COLOR_SRCBLEND_MASK 0x0000001fL
+#define CB_BLEND7_CONTROL__COLOR_SRCBLEND__SHIFT 0x00000000
+#define CB_BLEND7_CONTROL__DISABLE_ROP3_MASK 0x80000000L
+#define CB_BLEND7_CONTROL__DISABLE_ROP3__SHIFT 0x0000001f
+#define CB_BLEND7_CONTROL__ENABLE_MASK 0x40000000L
+#define CB_BLEND7_CONTROL__ENABLE__SHIFT 0x0000001e
+#define CB_BLEND7_CONTROL__SEPARATE_ALPHA_BLEND_MASK 0x20000000L
+#define CB_BLEND7_CONTROL__SEPARATE_ALPHA_BLEND__SHIFT 0x0000001d
+#define CB_BLEND_ALPHA__BLEND_ALPHA_MASK 0xffffffffL
+#define CB_BLEND_ALPHA__BLEND_ALPHA__SHIFT 0x00000000
+#define CB_BLEND_BLUE__BLEND_BLUE_MASK 0xffffffffL
+#define CB_BLEND_BLUE__BLEND_BLUE__SHIFT 0x00000000
+#define CB_BLEND_GREEN__BLEND_GREEN_MASK 0xffffffffL
+#define CB_BLEND_GREEN__BLEND_GREEN__SHIFT 0x00000000
+#define CB_BLEND_RED__BLEND_RED_MASK 0xffffffffL
+#define CB_BLEND_RED__BLEND_RED__SHIFT 0x00000000
+#define CB_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CB_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CB_CGTT_SCLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CB_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CB_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CB_COLOR0_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR0_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR0_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR0_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR0_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR0_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR0_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR0_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR0_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR0_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR0_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR0_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR0_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR0_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR0_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR0_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR0_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR0_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR0_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR0_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR0_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR0_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR0_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR0_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR0_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR0_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR0_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR0_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR0_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR0_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR0_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR0_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR0_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR0_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR0_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR0_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR0_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR0_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR0_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR0_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR0_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR0_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR0_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR0_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR0_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR0_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR0_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR0_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR0_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR0_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR0_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR0_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR0_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR0_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR0_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR0_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR0_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR0_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR0_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR0_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR0_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR0_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR0_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR1_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR1_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR1_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR1_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR1_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR1_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR1_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR1_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR1_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR1_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR1_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR1_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR1_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR1_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR1_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR1_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR1_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR1_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR1_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR1_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR1_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR1_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR1_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR1_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR1_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR1_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR1_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR1_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR1_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR1_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR1_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR1_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR1_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR1_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR1_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR1_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR1_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR1_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR1_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR1_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR1_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR1_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR1_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR1_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR1_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR1_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR1_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR1_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR1_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR1_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR1_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR1_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR1_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR1_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR1_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR1_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR1_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR1_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR1_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR1_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR1_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR1_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR1_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR2_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR2_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR2_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR2_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR2_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR2_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR2_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR2_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR2_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR2_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR2_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR2_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR2_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR2_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR2_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR2_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR2_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR2_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR2_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR2_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR2_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR2_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR2_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR2_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR2_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR2_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR2_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR2_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR2_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR2_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR2_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR2_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR2_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR2_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR2_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR2_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR2_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR2_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR2_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR2_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR2_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR2_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR2_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR2_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR2_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR2_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR2_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR2_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR2_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR2_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR2_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR2_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR2_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR2_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR2_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR2_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR2_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR2_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR2_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR2_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR2_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR2_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR2_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR3_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR3_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR3_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR3_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR3_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR3_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR3_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR3_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR3_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR3_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR3_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR3_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR3_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR3_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR3_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR3_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR3_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR3_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR3_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR3_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR3_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR3_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR3_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR3_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR3_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR3_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR3_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR3_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR3_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR3_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR3_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR3_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR3_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR3_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR3_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR3_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR3_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR3_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR3_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR3_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR3_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR3_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR3_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR3_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR3_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR3_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR3_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR3_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR3_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR3_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR3_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR3_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR3_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR3_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR3_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR3_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR3_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR3_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR3_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR3_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR3_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR3_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR3_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR4_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR4_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR4_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR4_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR4_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR4_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR4_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR4_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR4_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR4_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR4_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR4_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR4_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR4_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR4_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR4_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR4_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR4_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR4_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR4_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR4_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR4_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR4_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR4_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR4_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR4_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR4_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR4_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR4_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR4_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR4_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR4_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR4_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR4_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR4_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR4_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR4_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR4_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR4_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR4_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR4_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR4_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR4_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR4_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR4_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR4_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR4_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR4_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR4_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR4_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR4_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR4_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR4_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR4_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR4_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR4_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR4_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR4_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR4_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR4_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR4_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR4_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR4_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR5_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR5_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR5_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR5_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR5_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR5_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR5_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR5_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR5_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR5_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR5_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR5_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR5_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR5_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR5_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR5_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR5_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR5_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR5_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR5_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR5_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR5_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR5_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR5_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR5_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR5_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR5_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR5_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR5_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR5_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR5_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR5_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR5_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR5_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR5_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR5_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR5_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR5_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR5_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR5_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR5_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR5_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR5_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR5_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR5_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR5_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR5_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR5_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR5_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR5_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR5_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR5_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR5_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR5_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR5_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR5_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR5_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR5_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR5_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR5_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR5_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR5_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR5_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR6_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR6_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR6_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR6_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR6_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR6_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR6_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR6_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR6_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR6_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR6_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR6_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR6_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR6_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR6_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR6_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR6_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR6_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR6_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR6_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR6_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR6_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR6_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR6_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR6_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR6_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR6_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR6_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR6_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR6_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR6_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR6_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR6_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR6_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR6_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR6_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR6_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR6_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR6_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR6_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR6_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR6_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR6_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR6_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR6_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR6_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR6_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR6_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR6_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR6_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR6_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR6_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR6_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR6_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR6_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR6_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR6_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR6_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR6_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR6_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR6_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR6_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR6_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR7_ATTRIB__FMASK_BANK_HEIGHT_MASK 0x00000c00L
+#define CB_COLOR7_ATTRIB__FMASK_BANK_HEIGHT__SHIFT 0x0000000a
+#define CB_COLOR7_ATTRIB__FMASK_TILE_MODE_INDEX_MASK 0x000003e0L
+#define CB_COLOR7_ATTRIB__FMASK_TILE_MODE_INDEX__SHIFT 0x00000005
+#define CB_COLOR7_ATTRIB__FORCE_DST_ALPHA_1_MASK 0x00020000L
+#define CB_COLOR7_ATTRIB__FORCE_DST_ALPHA_1__SHIFT 0x00000011
+#define CB_COLOR7_ATTRIB__NUM_FRAGMENTS_MASK 0x00018000L
+#define CB_COLOR7_ATTRIB__NUM_FRAGMENTS__SHIFT 0x0000000f
+#define CB_COLOR7_ATTRIB__NUM_SAMPLES_MASK 0x00007000L
+#define CB_COLOR7_ATTRIB__NUM_SAMPLES__SHIFT 0x0000000c
+#define CB_COLOR7_ATTRIB__TILE_MODE_INDEX_MASK 0x0000001fL
+#define CB_COLOR7_ATTRIB__TILE_MODE_INDEX__SHIFT 0x00000000
+#define CB_COLOR7_BASE__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR7_BASE__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR7_CLEAR_WORD0__CLEAR_WORD0_MASK 0xffffffffL
+#define CB_COLOR7_CLEAR_WORD0__CLEAR_WORD0__SHIFT 0x00000000
+#define CB_COLOR7_CLEAR_WORD1__CLEAR_WORD1_MASK 0xffffffffL
+#define CB_COLOR7_CLEAR_WORD1__CLEAR_WORD1__SHIFT 0x00000000
+#define CB_COLOR7_CMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR7_CMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR7_CMASK_SLICE__TILE_MAX_MASK 0x00003fffL
+#define CB_COLOR7_CMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_FMASK__BASE_256B_MASK 0xffffffffL
+#define CB_COLOR7_FMASK__BASE_256B__SHIFT 0x00000000
+#define CB_COLOR7_FMASK_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR7_FMASK_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_INFO__BLEND_BYPASS_MASK 0x00010000L
+#define CB_COLOR7_INFO__BLEND_BYPASS__SHIFT 0x00000010
+#define CB_COLOR7_INFO__BLEND_CLAMP_MASK 0x00008000L
+#define CB_COLOR7_INFO__BLEND_CLAMP__SHIFT 0x0000000f
+#define CB_COLOR7_INFO__BLEND_OPT_DISCARD_PIXEL_MASK 0x03800000L
+#define CB_COLOR7_INFO__BLEND_OPT_DISCARD_PIXEL__SHIFT 0x00000017
+#define CB_COLOR7_INFO__BLEND_OPT_DONT_RD_DST_MASK 0x00700000L
+#define CB_COLOR7_INFO__BLEND_OPT_DONT_RD_DST__SHIFT 0x00000014
+#define CB_COLOR7_INFO__CMASK_IS_LINEAR_MASK 0x00080000L
+#define CB_COLOR7_INFO__CMASK_IS_LINEAR__SHIFT 0x00000013
+#define CB_COLOR7_INFO__COMPRESSION_MASK 0x00004000L
+#define CB_COLOR7_INFO__COMPRESSION__SHIFT 0x0000000e
+#define CB_COLOR7_INFO__COMP_SWAP_MASK 0x00001800L
+#define CB_COLOR7_INFO__COMP_SWAP__SHIFT 0x0000000b
+#define CB_COLOR7_INFO__ENDIAN_MASK 0x00000003L
+#define CB_COLOR7_INFO__ENDIAN__SHIFT 0x00000000
+#define CB_COLOR7_INFO__FAST_CLEAR_MASK 0x00002000L
+#define CB_COLOR7_INFO__FAST_CLEAR__SHIFT 0x0000000d
+#define CB_COLOR7_INFO__FMASK_COMPRESSION_DISABLE_MASK 0x04000000L
+#define CB_COLOR7_INFO__FMASK_COMPRESSION_DISABLE__SHIFT 0x0000001a
+#define CB_COLOR7_INFO__FORMAT_MASK 0x0000007cL
+#define CB_COLOR7_INFO__FORMAT__SHIFT 0x00000002
+#define CB_COLOR7_INFO__LINEAR_GENERAL_MASK 0x00000080L
+#define CB_COLOR7_INFO__LINEAR_GENERAL__SHIFT 0x00000007
+#define CB_COLOR7_INFO__NUMBER_TYPE_MASK 0x00000700L
+#define CB_COLOR7_INFO__NUMBER_TYPE__SHIFT 0x00000008
+#define CB_COLOR7_INFO__ROUND_MODE_MASK 0x00040000L
+#define CB_COLOR7_INFO__ROUND_MODE__SHIFT 0x00000012
+#define CB_COLOR7_INFO__SIMPLE_FLOAT_MASK 0x00020000L
+#define CB_COLOR7_INFO__SIMPLE_FLOAT__SHIFT 0x00000011
+#define CB_COLOR7_PITCH__FMASK_TILE_MAX_MASK 0x7ff00000L
+#define CB_COLOR7_PITCH__FMASK_TILE_MAX__SHIFT 0x00000014
+#define CB_COLOR7_PITCH__TILE_MAX_MASK 0x000007ffL
+#define CB_COLOR7_PITCH__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_SLICE__TILE_MAX_MASK 0x003fffffL
+#define CB_COLOR7_SLICE__TILE_MAX__SHIFT 0x00000000
+#define CB_COLOR7_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define CB_COLOR7_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define CB_COLOR7_VIEW__SLICE_START_MASK 0x000007ffL
+#define CB_COLOR7_VIEW__SLICE_START__SHIFT 0x00000000
+#define CB_COLOR_CONTROL__DEGAMMA_ENABLE_MASK 0x00000008L
+#define CB_COLOR_CONTROL__DEGAMMA_ENABLE__SHIFT 0x00000003
+#define CB_COLOR_CONTROL__MODE_MASK 0x00000070L
+#define CB_COLOR_CONTROL__MODE__SHIFT 0x00000004
+#define CB_COLOR_CONTROL__ROP3_MASK 0x00ff0000L
+#define CB_COLOR_CONTROL__ROP3__SHIFT 0x00000010
+#define CB_DEBUG_BUS_13__AC_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_13__AC_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_13__CACHE_CTRL_BUSY_MASK 0x00000020L
+#define CB_DEBUG_BUS_13__CACHE_CTRL_BUSY__SHIFT 0x00000005
+#define CB_DEBUG_BUS_13__CRW_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_13__CRW_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_13__EVICT_PENDING_MASK 0x00000200L
+#define CB_DEBUG_BUS_13__EVICT_PENDING__SHIFT 0x00000009
+#define CB_DEBUG_BUS_13__FC_RD_PENDING_MASK 0x00000100L
+#define CB_DEBUG_BUS_13__FC_RD_PENDING__SHIFT 0x00000008
+#define CB_DEBUG_BUS_13__FC_WR_PENDING_MASK 0x00000080L
+#define CB_DEBUG_BUS_13__FC_WR_PENDING__SHIFT 0x00000007
+#define CB_DEBUG_BUS_13__LAST_RD_ARB_WINNER_MASK 0x00000400L
+#define CB_DEBUG_BUS_13__LAST_RD_ARB_WINNER__SHIFT 0x0000000a
+#define CB_DEBUG_BUS_13__MC_WR_PENDING_MASK 0x00000040L
+#define CB_DEBUG_BUS_13__MC_WR_PENDING__SHIFT 0x00000006
+#define CB_DEBUG_BUS_13__MU_BUSY_MASK 0x00000002L
+#define CB_DEBUG_BUS_13__MU_BUSY__SHIFT 0x00000001
+#define CB_DEBUG_BUS_13__MU_STATE_MASK 0x0007f800L
+#define CB_DEBUG_BUS_13__MU_STATE__SHIFT 0x0000000b
+#define CB_DEBUG_BUS_13__TILE_INTFC_BUSY_MASK 0x00000001L
+#define CB_DEBUG_BUS_13__TILE_INTFC_BUSY__SHIFT 0x00000000
+#define CB_DEBUG_BUS_13__TQ_BUSY_MASK 0x00000004L
+#define CB_DEBUG_BUS_13__TQ_BUSY__SHIFT 0x00000002
+#define CB_DEBUG_BUS_14__ADDR_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_14__ADDR_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_14__CACHE_CTL_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_14__CACHE_CTL_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_14__CLEAR_BUSY_MASK 0x00000100L
+#define CB_DEBUG_BUS_14__CLEAR_BUSY__SHIFT 0x00000008
+#define CB_DEBUG_BUS_14__FOP_BUSY_MASK 0x00000002L
+#define CB_DEBUG_BUS_14__FOP_BUSY__SHIFT 0x00000001
+#define CB_DEBUG_BUS_14__LAT_BUSY_MASK 0x00000004L
+#define CB_DEBUG_BUS_14__LAT_BUSY__SHIFT 0x00000002
+#define CB_DEBUG_BUS_14__MERGE_BUSY_MASK 0x00000020L
+#define CB_DEBUG_BUS_14__MERGE_BUSY__SHIFT 0x00000005
+#define CB_DEBUG_BUS_14__QUAD_BUSY_MASK 0x00000040L
+#define CB_DEBUG_BUS_14__QUAD_BUSY__SHIFT 0x00000006
+#define CB_DEBUG_BUS_14__TILE_BUSY_MASK 0x00000080L
+#define CB_DEBUG_BUS_14__TILE_BUSY__SHIFT 0x00000007
+#define CB_DEBUG_BUS_14__TILE_RETIREMENT_BUSY_MASK 0x00000001L
+#define CB_DEBUG_BUS_14__TILE_RETIREMENT_BUSY__SHIFT 0x00000000
+#define CB_DEBUG_BUS_15__CS_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_15__CS_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_15__DS_BUSY_MASK 0x00000040L
+#define CB_DEBUG_BUS_15__DS_BUSY__SHIFT 0x00000006
+#define CB_DEBUG_BUS_15__IB_BUSY_MASK 0x00000100L
+#define CB_DEBUG_BUS_15__IB_BUSY__SHIFT 0x00000008
+#define CB_DEBUG_BUS_15__RB_BUSY_MASK 0x00000020L
+#define CB_DEBUG_BUS_15__RB_BUSY__SHIFT 0x00000005
+#define CB_DEBUG_BUS_15__SF_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_15__SF_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_15__SURF_SYNC_START_MASK 0x00000004L
+#define CB_DEBUG_BUS_15__SURF_SYNC_START__SHIFT 0x00000002
+#define CB_DEBUG_BUS_15__SURF_SYNC_STATE_MASK 0x00000003L
+#define CB_DEBUG_BUS_15__SURF_SYNC_STATE__SHIFT 0x00000000
+#define CB_DEBUG_BUS_15__TB_BUSY_MASK 0x00000080L
+#define CB_DEBUG_BUS_15__TB_BUSY__SHIFT 0x00000007
+#define CB_DEBUG_BUS_16__CC_WRREQ_FIFO_EMPTY_MASK 0x00100000L
+#define CB_DEBUG_BUS_16__CC_WRREQ_FIFO_EMPTY__SHIFT 0x00000014
+#define CB_DEBUG_BUS_16__CM_WRREQ_FIFO_EMPTY_MASK 0x00400000L
+#define CB_DEBUG_BUS_16__CM_WRREQ_FIFO_EMPTY__SHIFT 0x00000016
+#define CB_DEBUG_BUS_16__FC_WRREQ_FIFO_EMPTY_MASK 0x00200000L
+#define CB_DEBUG_BUS_16__FC_WRREQ_FIFO_EMPTY__SHIFT 0x00000015
+#define CB_DEBUG_BUS_16__LAST_RD_GRANT_VEC_MASK 0x000003c0L
+#define CB_DEBUG_BUS_16__LAST_RD_GRANT_VEC__SHIFT 0x00000006
+#define CB_DEBUG_BUS_16__LAST_WR_GRANT_VEC_MASK 0x000f0000L
+#define CB_DEBUG_BUS_16__LAST_WR_GRANT_VEC__SHIFT 0x00000010
+#define CB_DEBUG_BUS_16__MC_RDREQ_CREDITS_MASK 0x0000003fL
+#define CB_DEBUG_BUS_16__MC_RDREQ_CREDITS__SHIFT 0x00000000
+#define CB_DEBUG_BUS_16__MC_WRREQ_CREDITS_MASK 0x0000fc00L
+#define CB_DEBUG_BUS_16__MC_WRREQ_CREDITS__SHIFT 0x0000000a
+#define CB_DEBUG_BUS_17__BB_BUSY_MASK 0x00000008L
+#define CB_DEBUG_BUS_17__BB_BUSY__SHIFT 0x00000003
+#define CB_DEBUG_BUS_17__CC_BUSY_MASK 0x00000004L
+#define CB_DEBUG_BUS_17__CC_BUSY__SHIFT 0x00000002
+#define CB_DEBUG_BUS_17__CM_BUSY_MASK 0x00000001L
+#define CB_DEBUG_BUS_17__CM_BUSY__SHIFT 0x00000000
+#define CB_DEBUG_BUS_17__CORE_SCLK_VLD_MASK 0x00000020L
+#define CB_DEBUG_BUS_17__CORE_SCLK_VLD__SHIFT 0x00000005
+#define CB_DEBUG_BUS_17__FC_BUSY_MASK 0x00000002L
+#define CB_DEBUG_BUS_17__FC_BUSY__SHIFT 0x00000001
+#define CB_DEBUG_BUS_17__MA_BUSY_MASK 0x00000010L
+#define CB_DEBUG_BUS_17__MA_BUSY__SHIFT 0x00000004
+#define CB_DEBUG_BUS_17__REG_SCLK0_VLD_MASK 0x00000080L
+#define CB_DEBUG_BUS_17__REG_SCLK0_VLD__SHIFT 0x00000007
+#define CB_DEBUG_BUS_17__REG_SCLK1_VLD_MASK 0x00000040L
+#define CB_DEBUG_BUS_17__REG_SCLK1_VLD__SHIFT 0x00000006
+#define CB_DEBUG_BUS_18__NOT_USED_MASK 0x00ffffffL
+#define CB_DEBUG_BUS_18__NOT_USED__SHIFT 0x00000000
+#define CB_HW_CONTROL_1__CC_CACHE_NUM_TAGS_MASK 0x0001f800L
+#define CB_HW_CONTROL_1__CC_CACHE_NUM_TAGS__SHIFT 0x0000000b
+#define CB_HW_CONTROL_1__CHICKEN_BITS_MASK 0xfc000000L
+#define CB_HW_CONTROL_1__CHICKEN_BITS__SHIFT 0x0000001a
+#define CB_HW_CONTROL_1__CM_CACHE_NUM_TAGS_MASK 0x0000001fL
+#define CB_HW_CONTROL_1__CM_CACHE_NUM_TAGS__SHIFT 0x00000000
+#define CB_HW_CONTROL_1__CM_TILE_FIFO_DEPTH_MASK 0x03fe0000L
+#define CB_HW_CONTROL_1__CM_TILE_FIFO_DEPTH__SHIFT 0x00000011
+#define CB_HW_CONTROL_1__FC_CACHE_NUM_TAGS_MASK 0x000007e0L
+#define CB_HW_CONTROL_1__FC_CACHE_NUM_TAGS__SHIFT 0x00000005
+#define CB_HW_CONTROL_2__CC_EVEN_ODD_FIFO_DEPTH_MASK 0x000000ffL
+#define CB_HW_CONTROL_2__CC_EVEN_ODD_FIFO_DEPTH__SHIFT 0x00000000
+#define CB_HW_CONTROL_2__CHICKEN_BITS_MASK 0xff800000L
+#define CB_HW_CONTROL_2__CHICKEN_BITS__SHIFT 0x00000017
+#define CB_HW_CONTROL_2__FC_RDLAT_QUAD_FIFO_DEPTH_MASK 0x007f8000L
+#define CB_HW_CONTROL_2__FC_RDLAT_QUAD_FIFO_DEPTH__SHIFT 0x0000000f
+#define CB_HW_CONTROL_2__FC_RDLAT_TILE_FIFO_DEPTH_MASK 0x00007f00L
+#define CB_HW_CONTROL_2__FC_RDLAT_TILE_FIFO_DEPTH__SHIFT 0x00000008
+#define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL_MASK 0x00000001L
+#define CB_HW_CONTROL_3__DISABLE_SLOW_MODE_EMPTY_HALF_QUAD_KILL__SHIFT 0x00000000
+#define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE_MASK 0x00010000L
+#define CB_HW_CONTROL__ALLOW_MRT_WITH_DUAL_SOURCE__SHIFT 0x00000010
+#define CB_HW_CONTROL__CC_CACHE_EVICT_POINT_MASK 0x0000f000L
+#define CB_HW_CONTROL__CC_CACHE_EVICT_POINT__SHIFT 0x0000000c
+#define CB_HW_CONTROL__CM_CACHE_EVICT_POINT_MASK 0x0000000fL
+#define CB_HW_CONTROL__CM_CACHE_EVICT_POINT__SHIFT 0x00000000
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_BYPASS_MASK 0x02000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_BYPASS__SHIFT 0x00000019
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DISCARD_PIXEL_MASK 0x04000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DISCARD_PIXEL__SHIFT 0x0000001a
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DONT_RD_DST_MASK 0x01000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_DONT_RD_DST__SHIFT 0x00000018
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_RESULT_EQ_DEST_MASK 0x00200000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_RESULT_EQ_DEST__SHIFT 0x00000015
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_WHEN_DISABLED_SRCALPHA_IS_USED_MASK 0x08000000L
+#define CB_HW_CONTROL__DISABLE_BLEND_OPT_WHEN_DISABLED_SRCALPHA_IS_USED__SHIFT 0x0000001b
+#define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT_MASK 0x40000000L
+#define CB_HW_CONTROL__DISABLE_CC_IB_SERIALIZER_STATE_OPT__SHIFT 0x0000001e
+#define CB_HW_CONTROL__DISABLE_FULL_WRITE_MASK_MASK 0x00400000L
+#define CB_HW_CONTROL__DISABLE_FULL_WRITE_MASK__SHIFT 0x00000016
+#define CB_HW_CONTROL__DISABLE_INTNORM_LE11BPC_CLAMPING_MASK 0x00040000L
+#define CB_HW_CONTROL__DISABLE_INTNORM_LE11BPC_CLAMPING__SHIFT 0x00000012
+#define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE_MASK 0x80000000L
+#define CB_HW_CONTROL__DISABLE_PIXEL_IN_QUAD_FIX_FOR_LINEAR_SURFACE__SHIFT 0x0000001f
+#define CB_HW_CONTROL__DISABLE_RESOLVE_OPT_FOR_SINGLE_FRAG_MASK 0x00800000L
+#define CB_HW_CONTROL__DISABLE_RESOLVE_OPT_FOR_SINGLE_FRAG__SHIFT 0x00000017
+#define CB_HW_CONTROL__FC_CACHE_EVICT_POINT_MASK 0x000003c0L
+#define CB_HW_CONTROL__FC_CACHE_EVICT_POINT__SHIFT 0x00000006
+#define CB_HW_CONTROL__FORCE_ALWAYS_TOGGLE_MASK 0x00100000L
+#define CB_HW_CONTROL__FORCE_ALWAYS_TOGGLE__SHIFT 0x00000014
+#define CB_HW_CONTROL__FORCE_NEEDS_DST_MASK 0x00080000L
+#define CB_HW_CONTROL__FORCE_NEEDS_DST__SHIFT 0x00000013
+#define CB_HW_CONTROL__PRIORITIZE_FC_EVICT_OVER_FOP_RD_ON_BANK_CONFLICT_MASK 0x20000000L
+#define CB_HW_CONTROL__PRIORITIZE_FC_EVICT_OVER_FOP_RD_ON_BANK_CONFLICT__SHIFT 0x0000001d
+#define CB_HW_CONTROL__PRIORITIZE_FC_WR_OVER_FC_RD_ON_CMASK_CONFLICT_MASK 0x10000000L
+#define CB_HW_CONTROL__PRIORITIZE_FC_WR_OVER_FC_RD_ON_CMASK_CONFLICT__SHIFT 0x0000001c
+#define CB_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define CB_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000001ffL
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x0007fc00L
+#define CB_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define CB_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define CB_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define CB_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define CB_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define CB_SHADER_MASK__OUTPUT0_ENABLE_MASK 0x0000000fL
+#define CB_SHADER_MASK__OUTPUT0_ENABLE__SHIFT 0x00000000
+#define CB_SHADER_MASK__OUTPUT1_ENABLE_MASK 0x000000f0L
+#define CB_SHADER_MASK__OUTPUT1_ENABLE__SHIFT 0x00000004
+#define CB_SHADER_MASK__OUTPUT2_ENABLE_MASK 0x00000f00L
+#define CB_SHADER_MASK__OUTPUT2_ENABLE__SHIFT 0x00000008
+#define CB_SHADER_MASK__OUTPUT3_ENABLE_MASK 0x0000f000L
+#define CB_SHADER_MASK__OUTPUT3_ENABLE__SHIFT 0x0000000c
+#define CB_SHADER_MASK__OUTPUT4_ENABLE_MASK 0x000f0000L
+#define CB_SHADER_MASK__OUTPUT4_ENABLE__SHIFT 0x00000010
+#define CB_SHADER_MASK__OUTPUT5_ENABLE_MASK 0x00f00000L
+#define CB_SHADER_MASK__OUTPUT5_ENABLE__SHIFT 0x00000014
+#define CB_SHADER_MASK__OUTPUT6_ENABLE_MASK 0x0f000000L
+#define CB_SHADER_MASK__OUTPUT6_ENABLE__SHIFT 0x00000018
+#define CB_SHADER_MASK__OUTPUT7_ENABLE_MASK 0xf0000000L
+#define CB_SHADER_MASK__OUTPUT7_ENABLE__SHIFT 0x0000001c
+#define CB_TARGET_MASK__TARGET0_ENABLE_MASK 0x0000000fL
+#define CB_TARGET_MASK__TARGET0_ENABLE__SHIFT 0x00000000
+#define CB_TARGET_MASK__TARGET1_ENABLE_MASK 0x000000f0L
+#define CB_TARGET_MASK__TARGET1_ENABLE__SHIFT 0x00000004
+#define CB_TARGET_MASK__TARGET2_ENABLE_MASK 0x00000f00L
+#define CB_TARGET_MASK__TARGET2_ENABLE__SHIFT 0x00000008
+#define CB_TARGET_MASK__TARGET3_ENABLE_MASK 0x0000f000L
+#define CB_TARGET_MASK__TARGET3_ENABLE__SHIFT 0x0000000c
+#define CB_TARGET_MASK__TARGET4_ENABLE_MASK 0x000f0000L
+#define CB_TARGET_MASK__TARGET4_ENABLE__SHIFT 0x00000010
+#define CB_TARGET_MASK__TARGET5_ENABLE_MASK 0x00f00000L
+#define CB_TARGET_MASK__TARGET5_ENABLE__SHIFT 0x00000014
+#define CB_TARGET_MASK__TARGET6_ENABLE_MASK 0x0f000000L
+#define CB_TARGET_MASK__TARGET6_ENABLE__SHIFT 0x00000018
+#define CB_TARGET_MASK__TARGET7_ENABLE_MASK 0xf0000000L
+#define CB_TARGET_MASK__TARGET7_ENABLE__SHIFT 0x0000001c
+#define CC_GC_SHADER_ARRAY_CONFIG__DPFP_RATE_MASK 0x00000006L
+#define CC_GC_SHADER_ARRAY_CONFIG__DPFP_RATE__SHIFT 0x00000001
+#define CC_GC_SHADER_ARRAY_CONFIG__HALF_LDS_MASK 0x00000010L
+#define CC_GC_SHADER_ARRAY_CONFIG__HALF_LDS__SHIFT 0x00000004
+#define CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK 0xffff0000L
+#define CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT 0x00000010
+#define CC_GC_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE_MASK 0x00000008L
+#define CC_GC_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE__SHIFT 0x00000003
+#define CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define CC_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define CC_RB_DAISY_CHAIN__RB_0_MASK 0x0000000fL
+#define CC_RB_DAISY_CHAIN__RB_0__SHIFT 0x00000000
+#define CC_RB_DAISY_CHAIN__RB_1_MASK 0x000000f0L
+#define CC_RB_DAISY_CHAIN__RB_1__SHIFT 0x00000004
+#define CC_RB_DAISY_CHAIN__RB_2_MASK 0x00000f00L
+#define CC_RB_DAISY_CHAIN__RB_2__SHIFT 0x00000008
+#define CC_RB_DAISY_CHAIN__RB_3_MASK 0x0000f000L
+#define CC_RB_DAISY_CHAIN__RB_3__SHIFT 0x0000000c
+#define CC_RB_DAISY_CHAIN__RB_4_MASK 0x000f0000L
+#define CC_RB_DAISY_CHAIN__RB_4__SHIFT 0x00000010
+#define CC_RB_DAISY_CHAIN__RB_5_MASK 0x00f00000L
+#define CC_RB_DAISY_CHAIN__RB_5__SHIFT 0x00000014
+#define CC_RB_DAISY_CHAIN__RB_6_MASK 0x0f000000L
+#define CC_RB_DAISY_CHAIN__RB_6__SHIFT 0x00000018
+#define CC_RB_DAISY_CHAIN__RB_7_MASK 0xf0000000L
+#define CC_RB_DAISY_CHAIN__RB_7__SHIFT 0x0000001c
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY0_MASK 0x00001000L
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY0__SHIFT 0x0000000c
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY1_MASK 0x00100000L
+#define CC_RB_REDUNDANCY__EN_REDUNDANCY1__SHIFT 0x00000014
+#define CC_RB_REDUNDANCY__FAILED_RB0_MASK 0x00000f00L
+#define CC_RB_REDUNDANCY__FAILED_RB0__SHIFT 0x00000008
+#define CC_RB_REDUNDANCY__FAILED_RB1_MASK 0x000f0000L
+#define CC_RB_REDUNDANCY__FAILED_RB1__SHIFT 0x00000010
+#define CC_SQC_BANK_DISABLE__SQC0_BANK_DISABLE_MASK 0x000f0000L
+#define CC_SQC_BANK_DISABLE__SQC0_BANK_DISABLE__SHIFT 0x00000010
+#define CC_SQC_BANK_DISABLE__SQC1_BANK_DISABLE_MASK 0x00f00000L
+#define CC_SQC_BANK_DISABLE__SQC1_BANK_DISABLE__SHIFT 0x00000014
+#define CC_SQC_BANK_DISABLE__SQC2_BANK_DISABLE_MASK 0x0f000000L
+#define CC_SQC_BANK_DISABLE__SQC2_BANK_DISABLE__SHIFT 0x00000018
+#define CC_SQC_BANK_DISABLE__SQC3_BANK_DISABLE_MASK 0xf0000000L
+#define CC_SQC_BANK_DISABLE__SQC3_BANK_DISABLE__SHIFT 0x0000001c
+#define CGTS_RD_CTRL_REG__REG_MUX_SEL_MASK 0x00001f00L
+#define CGTS_RD_CTRL_REG__REG_MUX_SEL__SHIFT 0x00000008
+#define CGTS_RD_CTRL_REG__ROW_MUX_SEL_MASK 0x0000001fL
+#define CGTS_RD_CTRL_REG__ROW_MUX_SEL__SHIFT 0x00000000
+#define CGTS_RD_REG__READ_DATA_MASK 0x00003fffL
+#define CGTS_RD_REG__READ_DATA__SHIFT 0x00000000
+#define CGTS_SM_CTRL_REG__BASE_MODE_MASK 0x00010000L
+#define CGTS_SM_CTRL_REG__BASE_MODE__SHIFT 0x00000010
+#define CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK 0x00400000L
+#define CGTS_SM_CTRL_REG__LS_OVERRIDE__SHIFT 0x00000016
+#define CGTS_SM_CTRL_REG__MGCG_ENABLED_MASK 0x00001000L
+#define CGTS_SM_CTRL_REG__MGCG_ENABLED__SHIFT 0x0000000c
+#define CGTS_SM_CTRL_REG__OFF_SEQ_DELAY_MASK 0x00000ff0L
+#define CGTS_SM_CTRL_REG__OFF_SEQ_DELAY__SHIFT 0x00000004
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK 0x00800000L
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN__SHIFT 0x00000017
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD_MASK 0xff000000L
+#define CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT 0x00000018
+#define CGTS_SM_CTRL_REG__ON_SEQ_DELAY_MASK 0x0000000fL
+#define CGTS_SM_CTRL_REG__ON_SEQ_DELAY__SHIFT 0x00000000
+#define CGTS_SM_CTRL_REG__OVERRIDE_MASK 0x00200000L
+#define CGTS_SM_CTRL_REG__OVERRIDE__SHIFT 0x00000015
+#define CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK 0x00100000L
+#define CGTS_SM_CTRL_REG__SM_MODE_ENABLE__SHIFT 0x00000014
+#define CGTS_SM_CTRL_REG__SM_MODE_MASK 0x000e0000L
+#define CGTS_SM_CTRL_REG__SM_MODE__SHIFT 0x00000011
+#define CGTS_TCC_DISABLE__TCC_DISABLE_MASK 0xffff0000L
+#define CGTS_TCC_DISABLE__TCC_DISABLE__SHIFT 0x00000010
+#define CGTS_USER_TCC_DISABLE__TCC_DISABLE_MASK 0xffff0000L
+#define CGTS_USER_TCC_DISABLE__TCC_DISABLE__SHIFT 0x00000010
+#define CGTT_BCI_CLK_CTRL__CORE0_OVERRIDE_MASK 0x40000000L
+#define CGTT_BCI_CLK_CTRL__CORE0_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_BCI_CLK_CTRL__CORE1_OVERRIDE_MASK 0x20000000L
+#define CGTT_BCI_CLK_CTRL__CORE1_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_BCI_CLK_CTRL__CORE2_OVERRIDE_MASK 0x10000000L
+#define CGTT_BCI_CLK_CTRL__CORE2_OVERRIDE__SHIFT 0x0000001c
+#define CGTT_BCI_CLK_CTRL__CORE3_OVERRIDE_MASK 0x08000000L
+#define CGTT_BCI_CLK_CTRL__CORE3_OVERRIDE__SHIFT 0x0000001b
+#define CGTT_BCI_CLK_CTRL__CORE4_OVERRIDE_MASK 0x04000000L
+#define CGTT_BCI_CLK_CTRL__CORE4_OVERRIDE__SHIFT 0x0000001a
+#define CGTT_BCI_CLK_CTRL__CORE5_OVERRIDE_MASK 0x02000000L
+#define CGTT_BCI_CLK_CTRL__CORE5_OVERRIDE__SHIFT 0x00000019
+#define CGTT_BCI_CLK_CTRL__CORE6_OVERRIDE_MASK 0x01000000L
+#define CGTT_BCI_CLK_CTRL__CORE6_OVERRIDE__SHIFT 0x00000018
+#define CGTT_BCI_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_BCI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_BCI_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_BCI_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_BCI_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_BCI_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_BCI_CLK_CTRL__RESERVED_MASK 0x00fff000L
+#define CGTT_BCI_CLK_CTRL__RESERVED__SHIFT 0x0000000c
+#define CGTT_CP_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_CP_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_CP_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_CP_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000L
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x0000001e
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000L
+#define CGTT_CP_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x0000001f
+#define CGTT_GDS_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_GDS_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_GDS_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_GDS_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_GDS_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_IA_CLK_CTRL__CORE_OVERRIDE_MASK 0x20000000L
+#define CGTT_IA_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_IA_CLK_CTRL__DBG_ENABLE_MASK 0x04000000L
+#define CGTT_IA_CLK_CTRL__DBG_ENABLE__SHIFT 0x0000001a
+#define CGTT_IA_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_IA_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_IA_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_IA_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_IA_CLK_CTRL__PERF_ENABLE_MASK 0x02000000L
+#define CGTT_IA_CLK_CTRL__PERF_ENABLE__SHIFT 0x00000019
+#define CGTT_IA_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_IA_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_IA_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_PA_CLK_CTRL__CL_CLK_OVERRIDE_MASK 0x40000000L
+#define CGTT_PA_CLK_CTRL__CL_CLK_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_PA_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_PA_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_PA_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_PA_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_PA_CLK_CTRL__REG_CLK_OVERRIDE_MASK 0x80000000L
+#define CGTT_PA_CLK_CTRL__REG_CLK_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_PA_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_PA_CLK_CTRL__SU_CLK_OVERRIDE_MASK 0x20000000L
+#define CGTT_PA_CLK_CTRL__SU_CLK_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_PC_CLK_CTRL__BACK_CLK_ON_OVERRIDE_MASK 0x02000000L
+#define CGTT_PC_CLK_CTRL__BACK_CLK_ON_OVERRIDE__SHIFT 0x00000019
+#define CGTT_PC_CLK_CTRL__CORE0_OVERRIDE_MASK 0x40000000L
+#define CGTT_PC_CLK_CTRL__CORE0_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_PC_CLK_CTRL__CORE1_OVERRIDE_MASK 0x20000000L
+#define CGTT_PC_CLK_CTRL__CORE1_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_PC_CLK_CTRL__CORE2_OVERRIDE_MASK 0x10000000L
+#define CGTT_PC_CLK_CTRL__CORE2_OVERRIDE__SHIFT 0x0000001c
+#define CGTT_PC_CLK_CTRL__CORE3_OVERRIDE_MASK 0x08000000L
+#define CGTT_PC_CLK_CTRL__CORE3_OVERRIDE__SHIFT 0x0000001b
+#define CGTT_PC_CLK_CTRL__FRONT_CLK_ON_OVERRIDE_MASK 0x04000000L
+#define CGTT_PC_CLK_CTRL__FRONT_CLK_ON_OVERRIDE__SHIFT 0x0000001a
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OFF_HYST_MASK 0x00fc0000L
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OFF_HYST__SHIFT 0x00000012
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OVERRIDE_MASK 0x01000000L
+#define CGTT_PC_CLK_CTRL__GRP5_CG_OVERRIDE__SHIFT 0x00000018
+#define CGTT_PC_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_PC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_PC_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_PC_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_PC_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_PC_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_RLC_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_RLC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_RLC_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_RLC_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_DYN_MASK 0x40000000L
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_DYN__SHIFT 0x0000001e
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_REG_MASK 0x80000000L
+#define CGTT_RLC_CLK_CTRL__SOFT_OVERRIDE_REG__SHIFT 0x0000001f
+#define CGTT_SC_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SC_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SC_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SC_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SC_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SPI_CLK_CTRL__ALL_CLK_ON_OVERRIDE_MASK 0x04000000L
+#define CGTT_SPI_CLK_CTRL__ALL_CLK_ON_OVERRIDE__SHIFT 0x0000001a
+#define CGTT_SPI_CLK_CTRL__GRP0_OVERRIDE_MASK 0x40000000L
+#define CGTT_SPI_CLK_CTRL__GRP0_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_SPI_CLK_CTRL__GRP1_OVERRIDE_MASK 0x20000000L
+#define CGTT_SPI_CLK_CTRL__GRP1_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_SPI_CLK_CTRL__GRP2_OVERRIDE_MASK 0x10000000L
+#define CGTT_SPI_CLK_CTRL__GRP2_OVERRIDE__SHIFT 0x0000001c
+#define CGTT_SPI_CLK_CTRL__GRP3_OVERRIDE_MASK 0x08000000L
+#define CGTT_SPI_CLK_CTRL__GRP3_OVERRIDE__SHIFT 0x0000001b
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OFF_HYST_MASK 0x00fc0000L
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OFF_HYST__SHIFT 0x00000012
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OVERRIDE_MASK 0x01000000L
+#define CGTT_SPI_CLK_CTRL__GRP5_CG_OVERRIDE__SHIFT 0x00000018
+#define CGTT_SPI_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SPI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SPI_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SPI_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SPI_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_SPI_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_SQ_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000L
+#define CGTT_SQ_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_SQ_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SQ_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SQ_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SQ_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SQ_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_SQ_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_SQG_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000L
+#define CGTT_SQG_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_SQG_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SQG_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SQG_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SQG_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SQG_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_SQG_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL0__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL0__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL0__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL0__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL0__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL0__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL0__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL1__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL1__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL1__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL1__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL1__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL1__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL1__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL2__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL2__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL2__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL2__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL2__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL2__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL2__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL3__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL3__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL3__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL3__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL3__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL3__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL3__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_SX_CLK_CTRL4__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_SX_CLK_CTRL4__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_SX_CLK_CTRL4__ON_DELAY_MASK 0x0000000fL
+#define CGTT_SX_CLK_CTRL4__ON_DELAY__SHIFT 0x00000000
+#define CGTT_SX_CLK_CTRL4__RESERVED_MASK 0x00fff000L
+#define CGTT_SX_CLK_CTRL4__RESERVED__SHIFT 0x0000000c
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_SX_CLK_CTRL4__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_TCI_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_TCI_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_TCI_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_TCI_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_TCI_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_TCP_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_TCP_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_TCP_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_TCP_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_TCP_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CGTT_VGT_CLK_CTRL__CORE_OVERRIDE_MASK 0x40000000L
+#define CGTT_VGT_CLK_CTRL__CORE_OVERRIDE__SHIFT 0x0000001e
+#define CGTT_VGT_CLK_CTRL__DBG_ENABLE_MASK 0x04000000L
+#define CGTT_VGT_CLK_CTRL__DBG_ENABLE__SHIFT 0x0000001a
+#define CGTT_VGT_CLK_CTRL__GS_OVERRIDE_MASK 0x20000000L
+#define CGTT_VGT_CLK_CTRL__GS_OVERRIDE__SHIFT 0x0000001d
+#define CGTT_VGT_CLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define CGTT_VGT_CLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define CGTT_VGT_CLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define CGTT_VGT_CLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define CGTT_VGT_CLK_CTRL__PERF_ENABLE_MASK 0x02000000L
+#define CGTT_VGT_CLK_CTRL__PERF_ENABLE__SHIFT 0x00000019
+#define CGTT_VGT_CLK_CTRL__REG_OVERRIDE_MASK 0x80000000L
+#define CGTT_VGT_CLK_CTRL__REG_OVERRIDE__SHIFT 0x0000001f
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define CGTT_VGT_CLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG00__ALWAYS_ZERO_MASK 0x000000ffL
+#define CLIPPER_DEBUG_REG00__ALWAYS_ZERO__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_empty_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_empty__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG00__ccgen_to_clipcc_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_fifo_empty_MASK 0x00200000L
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_fifo_empty__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_full_MASK 0x00400000L
+#define CLIPPER_DEBUG_REG00__clipcode_fifo_full__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG00__clip_ga_bc_fifo_write_MASK 0x00000100L
+#define CLIPPER_DEBUG_REG00__clip_ga_bc_fifo_write__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_full_MASK 0x00001000L
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_full__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_write_MASK 0x00000800L
+#define CLIPPER_DEBUG_REG00__clip_to_ga_fifo_write__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_empty_MASK 0x00008000L
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_empty__SHIFT 0x0000000f
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_full_MASK 0x00010000L
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_full__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_write_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG00__clip_to_outsm_fifo_write__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_empty_MASK 0x00002000L
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_empty__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_full_MASK 0x00004000L
+#define CLIPPER_DEBUG_REG00__primic_to_clprim_fifo_full__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG00__su_clip_baryc_free_MASK 0x00000600L
+#define CLIPPER_DEBUG_REG00__su_clip_baryc_free__SHIFT 0x00000009
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_empty_MASK 0x00020000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_empty__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_full_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_full__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_write_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clipp_fifo_write__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_empty_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_empty__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_full_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG00__vgt_to_clips_fifo_full__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_empty_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_empty__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_full_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG00__vte_out_clip_fifo_fifo_full__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_empty_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_empty__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_full_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_full__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_write_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG00__vte_out_orig_fifo_fifo_write__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG01__ALWAYS_ZERO_MASK 0x000000ffL
+#define CLIPPER_DEBUG_REG01__ALWAYS_ZERO__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG01__clip_extra_bc_valid_MASK 0x00000700L
+#define CLIPPER_DEBUG_REG01__clip_extra_bc_valid__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG01__clip_ga_bc_fifo_write_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG01__clip_ga_bc_fifo_write__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG01__clip_to_ga_fifo_write_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG01__clip_to_ga_fifo_write__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_deallocate_slot_MASK 0x000e0000L
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_deallocate_slot__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_null_primitive_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_null_primitive__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_vertex_deallocate_MASK 0x0001c000L
+#define CLIPPER_DEBUG_REG01__clip_to_outsm_vertex_deallocate__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG01__clip_vert_vte_valid_MASK 0x00003800L
+#define CLIPPER_DEBUG_REG01__clip_vert_vte_valid__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_advanceread_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_advanceread__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_empty_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_fifo_fifo_empty__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_extra_bc_valid_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_extra_bc_valid__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vertex_store_indx_MASK 0x0c000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vertex_store_indx__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vte_naninf_kill_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG01__vte_out_clip_rd_vte_naninf_kill__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_0_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_1_MASK 0x00400000L
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_1__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_2_MASK 0x00200000L
+#define CLIPPER_DEBUG_REG01__vte_positions_vte_clip_vte_naninf_kill_2__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG02__clip_extra_bc_valid_MASK 0x00000007L
+#define CLIPPER_DEBUG_REG02__clip_extra_bc_valid__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_full_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_full__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_write_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG02__clip_ga_bc_fifo_write__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_extra_bc_coords_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_extra_bc_coords__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_vte_naninf_kill_MASK 0x00200000L
+#define CLIPPER_DEBUG_REG02__clip_to_clipga_vte_naninf_kill__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_full_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_full__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_write_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG02__clip_to_ga_fifo_write__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clipped_prim_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clipped_prim__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clip_seq_indx_MASK 0x000000c0L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_clip_seq_indx__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_end_of_packet_MASK 0x00400000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_end_of_packet__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_advanceread_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_advanceread__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_empty_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_fifo_empty__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_first_prim_of_slot_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_first_prim_of_slot__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_null_primitive_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_null_primitive__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_0_MASK 0x000f0000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_0__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_1_MASK 0x0000f000L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_1__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_2_MASK 0x00000f00L
+#define CLIPPER_DEBUG_REG02__clip_to_outsm_vertex_store_indx_2__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG02__clip_vert_vte_valid_MASK 0x00000038L
+#define CLIPPER_DEBUG_REG02__clip_vert_vte_valid__SHIFT 0x00000003
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG03__clipsm0_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG04__clipsm0_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG05__clipsm1_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG06__clipsm1_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG07__clipsm2_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG08__clipsm2_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_code_or_MASK 0x00003fffL
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_code_or__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_primitive_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_clip_primitive__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_deallocate_slot_MASK 0x07000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_deallocate_slot__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_end_of_packet_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_end_of_packet__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_id_MASK 0x000fc000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_id__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_first_prim_of_slot_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_first_prim_of_slot__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_state_var_indx_MASK 0x00700000L
+#define CLIPPER_DEBUG_REG09__clipsm3_clprim_to_clip_state_var_indx__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_event_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_event__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_null_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_null_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_param_cache_indx_0_MASK 0x000007feL
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_param_cache_indx_0__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_0_MASK 0x1f800000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_0__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_1_MASK 0x007e0000L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_1__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_2_MASK 0x0001f800L
+#define CLIPPER_DEBUG_REG10__clipsm3_clprim_to_clip_vertex_store_indx_2__SHIFT 0x0000000b
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_primitive_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_primitive__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_to_outsm_cnt_MASK 0x00f00000L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_event_MASK 0x00000008L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_event__SHIFT 0x00000003
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_prim_valid_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG11__clipsm0_clip_to_clipga_prim_valid__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG11__clipsm0_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG11__clipsm0_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_primitive_MASK 0x00000040L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_primitive__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_to_outsm_cnt_MASK 0x000f0000L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_event_MASK 0x00000004L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_event__SHIFT 0x00000002
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_prim_valid_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG11__clipsm1_clip_to_clipga_prim_valid__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG11__clipsm1_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG11__clipsm1_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_primitive_MASK 0x00000020L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_primitive__SHIFT 0x00000005
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_to_outsm_cnt_MASK 0x0000f000L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_event_MASK 0x00000002L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_event__SHIFT 0x00000001
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_prim_valid_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG11__clipsm2_clip_to_clipga_prim_valid__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG11__clipsm2_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG11__clipsm2_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_primitive_MASK 0x00000010L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_primitive__SHIFT 0x00000004
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_to_outsm_cnt_MASK 0x00000f00L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_event_MASK 0x00000001L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_event__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_prim_valid_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG11__clipsm3_clip_to_clipga_prim_valid__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG11__clipsm3_inc_clip_to_clipga_clip_to_outsm_cnt_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG11__clipsm3_inc_clip_to_clipga_clip_to_outsm_cnt__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG12__ALWAYS_ZERO_MASK 0x000000ffL
+#define CLIPPER_DEBUG_REG12__ALWAYS_ZERO__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG12__clip_priority_available_clip_verts_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG12__clip_priority_available_clip_verts__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG12__clip_priority_available_vte_out_clip_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG12__clip_priority_available_vte_out_clip__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_load_MASK 0x00c00000L
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_load__SHIFT 0x00000016
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_out_MASK 0x000c0000L
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_out__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_vert_MASK 0x00300000L
+#define CLIPPER_DEBUG_REG12__clip_priority_seq_indx_vert__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_clip_primitive_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_clip_primitive__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG12__clipsm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_clip_primitive_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_clip_primitive__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_prim_valid_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG12__clipsm1_clprim_to_clip_prim_valid__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_clip_primitive_MASK 0x04000000L
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_clip_primitive__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_prim_valid_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG12__clipsm2_clprim_to_clip_prim_valid__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_clip_primitive_MASK 0x01000000L
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_clip_primitive__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_prim_valid_MASK 0x02000000L
+#define CLIPPER_DEBUG_REG12__clipsm3_clprim_to_clip_prim_valid__SHIFT 0x00000019
+#define CLIPPER_DEBUG_REG13__ccgen_to_clipcc_fifo_empty_MASK 0x00010000L
+#define CLIPPER_DEBUG_REG13__ccgen_to_clipcc_fifo_empty__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG13__clipcc_vertex_store_indx_MASK 0x00003000L
+#define CLIPPER_DEBUG_REG13__clipcc_vertex_store_indx__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG13__clipcode_fifo_fifo_empty_MASK 0x00008000L
+#define CLIPPER_DEBUG_REG13__clipcode_fifo_fifo_empty__SHIFT 0x0000000f
+#define CLIPPER_DEBUG_REG13__clip_priority_seq_indx_out_cnt_MASK 0x001e0000L
+#define CLIPPER_DEBUG_REG13__clip_priority_seq_indx_out_cnt__SHIFT 0x00000011
+#define CLIPPER_DEBUG_REG13__clprim_clip_primitive_MASK 0x00000020L
+#define CLIPPER_DEBUG_REG13__clprim_clip_primitive__SHIFT 0x00000005
+#define CLIPPER_DEBUG_REG13__clprim_cull_primitive_MASK 0x00000040L
+#define CLIPPER_DEBUG_REG13__clprim_cull_primitive__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG13__clprim_in_back_state_var_indx_MASK 0x00000007L
+#define CLIPPER_DEBUG_REG13__clprim_in_back_state_var_indx__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_advanceread_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_advanceread__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_contents_MASK 0x1f000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_contents__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_full_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_full__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_write_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_fifo_write__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_clipsm_wait_MASK 0x00800000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_clipsm_wait__SHIFT 0x00000017
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_orig_vertices_MASK 0x00600000L
+#define CLIPPER_DEBUG_REG13__outsm_clr_rd_orig_vertices__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG13__point_clip_candidate_MASK 0x00000008L
+#define CLIPPER_DEBUG_REG13__point_clip_candidate__SHIFT 0x00000003
+#define CLIPPER_DEBUG_REG13__prim_back_valid_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG13__prim_back_valid__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG13__prim_nan_kill_MASK 0x00000010L
+#define CLIPPER_DEBUG_REG13__prim_nan_kill__SHIFT 0x00000004
+#define CLIPPER_DEBUG_REG13__vertval_bits_vertex_cc_next_valid_MASK 0x00000f00L
+#define CLIPPER_DEBUG_REG13__vertval_bits_vertex_cc_next_valid__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG13__vte_out_orig_fifo_fifo_empty_MASK 0x00004000L
+#define CLIPPER_DEBUG_REG13__vte_out_orig_fifo_fifo_empty__SHIFT 0x0000000e
+#define CLIPPER_DEBUG_REG14__clprim_in_back_deallocate_slot_MASK 0x00e00000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_deallocate_slot__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG14__clprim_in_back_end_of_packet_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_end_of_packet__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_id_MASK 0x3f000000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_id__SHIFT 0x00000018
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_event__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG14__clprim_in_back_first_prim_of_slot_MASK 0x00100000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_first_prim_of_slot__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_0_MASK 0x0003f000L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_0__SHIFT 0x0000000c
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_1_MASK 0x00000fc0L
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_1__SHIFT 0x00000006
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_2_MASK 0x0000003fL
+#define CLIPPER_DEBUG_REG14__clprim_in_back_vertex_store_indx_2__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG14__outputclprimtoclip_null_primitive_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG14__outputclprimtoclip_null_primitive__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG14__prim_back_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG14__prim_back_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_0_MASK 0x7c000000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_0__SHIFT 0x0000001a
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_1_MASK 0x03e00000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_1__SHIFT 0x00000015
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_2_MASK 0x001f0000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_fifo_vertex_store_indx_2__SHIFT 0x00000010
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG15__primic_to_clprim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG15__vertval_bits_vertex_vertex_store_msb_MASK 0x0000ffffL
+#define CLIPPER_DEBUG_REG15__vertval_bits_vertex_vertex_store_msb__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG16__sm0_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG16__sm0_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG16__sm0_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG16__sm0_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG16__sm0_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG16__sm0_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG16__sm0_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG16__sm0_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG16__sm0_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG16__sm0_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG16__sm0_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG16__sm0_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG16__sm0_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG16__sm0_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG16__sm0_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG16__sm0_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG16__sm0_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG16__sm0_vertex_clip_cnt__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG17__sm1_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG17__sm1_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG17__sm1_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG17__sm1_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG17__sm1_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG17__sm1_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG17__sm1_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG17__sm1_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG17__sm1_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG17__sm1_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG17__sm1_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG17__sm1_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG17__sm1_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG17__sm1_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG17__sm1_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG17__sm1_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG17__sm1_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG17__sm1_vertex_clip_cnt__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG18__sm2_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG18__sm2_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG18__sm2_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG18__sm2_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG18__sm2_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG18__sm2_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG18__sm2_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG18__sm2_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG18__sm2_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG18__sm2_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG18__sm2_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG18__sm2_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG18__sm2_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG18__sm2_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG18__sm2_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG18__sm2_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG18__sm2_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG18__sm2_vertex_clip_cnt__SHIFT 0x0000000d
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_clipga_clip_to_outsm_cnt_eq0_MASK 0x08000000L
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_clipga_clip_to_outsm_cnt_eq0__SHIFT 0x0000001b
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_outsm_fifo_full_MASK 0x10000000L
+#define CLIPPER_DEBUG_REG19__sm3_clip_to_outsm_fifo_full__SHIFT 0x0000001c
+#define CLIPPER_DEBUG_REG19__sm3_clip_vert_cnt_MASK 0x00001f00L
+#define CLIPPER_DEBUG_REG19__sm3_clip_vert_cnt__SHIFT 0x00000008
+#define CLIPPER_DEBUG_REG19__sm3_clprim_to_clip_prim_valid_MASK 0x80000000L
+#define CLIPPER_DEBUG_REG19__sm3_clprim_to_clip_prim_valid__SHIFT 0x0000001f
+#define CLIPPER_DEBUG_REG19__sm3_current_state_MASK 0x07f00000L
+#define CLIPPER_DEBUG_REG19__sm3_current_state__SHIFT 0x00000014
+#define CLIPPER_DEBUG_REG19__sm3_highest_priority_seq_MASK 0x20000000L
+#define CLIPPER_DEBUG_REG19__sm3_highest_priority_seq__SHIFT 0x0000001d
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_0_MASK 0x00080000L
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_0__SHIFT 0x00000013
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_1_MASK 0x00040000L
+#define CLIPPER_DEBUG_REG19__sm3_inv_to_clip_data_valid_1__SHIFT 0x00000012
+#define CLIPPER_DEBUG_REG19__sm3_outputcliptoclipga_0_MASK 0x40000000L
+#define CLIPPER_DEBUG_REG19__sm3_outputcliptoclipga_0__SHIFT 0x0000001e
+#define CLIPPER_DEBUG_REG19__sm3_prim_end_state_MASK 0x0000007fL
+#define CLIPPER_DEBUG_REG19__sm3_prim_end_state__SHIFT 0x00000000
+#define CLIPPER_DEBUG_REG19__sm3_ps_expand_MASK 0x00000080L
+#define CLIPPER_DEBUG_REG19__sm3_ps_expand__SHIFT 0x00000007
+#define CLIPPER_DEBUG_REG19__sm3_vertex_clip_cnt_MASK 0x0003e000L
+#define CLIPPER_DEBUG_REG19__sm3_vertex_clip_cnt__SHIFT 0x0000000d
+#define COHER_DEST_BASE_0__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_0__DEST_BASE_256B__SHIFT 0x00000000
+#define COHER_DEST_BASE_1__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_1__DEST_BASE_256B__SHIFT 0x00000000
+#define COHER_DEST_BASE_2__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_2__DEST_BASE_256B__SHIFT 0x00000000
+#define COHER_DEST_BASE_3__DEST_BASE_256B_MASK 0xffffffffL
+#define COHER_DEST_BASE_3__DEST_BASE_256B__SHIFT 0x00000000
+#define COMPUTE_DIM_X__SIZE_MASK 0xffffffffL
+#define COMPUTE_DIM_X__SIZE__SHIFT 0x00000000
+#define COMPUTE_DIM_Y__SIZE_MASK 0xffffffffL
+#define COMPUTE_DIM_Y__SIZE__SHIFT 0x00000000
+#define COMPUTE_DIM_Z__SIZE_MASK 0xffffffffL
+#define COMPUTE_DIM_Z__SIZE__SHIFT 0x00000000
+#define COMPUTE_DISPATCH_INITIATOR__COMPUTE_SHADER_EN_MASK 0x00000001L
+#define COMPUTE_DISPATCH_INITIATOR__COMPUTE_SHADER_EN__SHIFT 0x00000000
+#define COMPUTE_DISPATCH_INITIATOR__DATA_ATC_MASK 0x00001000L
+#define COMPUTE_DISPATCH_INITIATOR__DATA_ATC__SHIFT 0x0000000c
+#define COMPUTE_DISPATCH_INITIATOR__DISPATCH_CACHE_CNTL_MASK 0x00000380L
+#define COMPUTE_DISPATCH_INITIATOR__DISPATCH_CACHE_CNTL__SHIFT 0x00000007
+#define COMPUTE_DISPATCH_INITIATOR__FORCE_START_AT_000_MASK 0x00000004L
+#define COMPUTE_DISPATCH_INITIATOR__FORCE_START_AT_000__SHIFT 0x00000002
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_ENBL_MASK 0x00000008L
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_ENBL__SHIFT 0x00000003
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_MODE_MASK 0x00000010L
+#define COMPUTE_DISPATCH_INITIATOR__ORDERED_APPEND_MODE__SHIFT 0x00000004
+#define COMPUTE_DISPATCH_INITIATOR__ORDER_MODE_MASK 0x00000040L
+#define COMPUTE_DISPATCH_INITIATOR__ORDER_MODE__SHIFT 0x00000006
+#define COMPUTE_DISPATCH_INITIATOR__PARTIAL_TG_EN_MASK 0x00000002L
+#define COMPUTE_DISPATCH_INITIATOR__PARTIAL_TG_EN__SHIFT 0x00000001
+#define COMPUTE_DISPATCH_INITIATOR__RESTORE_MASK 0x00004000L
+#define COMPUTE_DISPATCH_INITIATOR__RESTORE__SHIFT 0x0000000e
+#define COMPUTE_DISPATCH_INITIATOR__SCALAR_L1_INV_VOL_MASK 0x00000400L
+#define COMPUTE_DISPATCH_INITIATOR__SCALAR_L1_INV_VOL__SHIFT 0x0000000a
+#define COMPUTE_DISPATCH_INITIATOR__USE_THREAD_DIMENSIONS_MASK 0x00000020L
+#define COMPUTE_DISPATCH_INITIATOR__USE_THREAD_DIMENSIONS__SHIFT 0x00000005
+#define COMPUTE_DISPATCH_INITIATOR__VECTOR_L1_INV_VOL_MASK 0x00000800L
+#define COMPUTE_DISPATCH_INITIATOR__VECTOR_L1_INV_VOL__SHIFT 0x0000000b
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_FULL_MASK 0x0000ffffL
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_FULL__SHIFT 0x00000000
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_PARTIAL_MASK 0xffff0000L
+#define COMPUTE_NUM_THREAD_X__NUM_THREAD_PARTIAL__SHIFT 0x00000010
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_FULL_MASK 0x0000ffffL
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_FULL__SHIFT 0x00000000
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_PARTIAL_MASK 0xffff0000L
+#define COMPUTE_NUM_THREAD_Y__NUM_THREAD_PARTIAL__SHIFT 0x00000010
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_FULL_MASK 0x0000ffffL
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_FULL__SHIFT 0x00000000
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_PARTIAL_MASK 0xffff0000L
+#define COMPUTE_NUM_THREAD_Z__NUM_THREAD_PARTIAL__SHIFT 0x00000010
+#define COMPUTE_PGM_HI__DATA_MASK 0x000000ffL
+#define COMPUTE_PGM_HI__DATA__SHIFT 0x00000000
+#define COMPUTE_PGM_HI__INST_ATC_MASK 0x00000100L
+#define COMPUTE_PGM_HI__INST_ATC__SHIFT 0x00000008
+#define COMPUTE_PGM_LO__DATA_MASK 0xffffffffL
+#define COMPUTE_PGM_LO__DATA__SHIFT 0x00000000
+#define COMPUTE_PGM_RSRC1__BULKY_MASK 0x01000000L
+#define COMPUTE_PGM_RSRC1__BULKY__SHIFT 0x00000018
+#define COMPUTE_PGM_RSRC1__CDBG_USER_MASK 0x02000000L
+#define COMPUTE_PGM_RSRC1__CDBG_USER__SHIFT 0x00000019
+#define COMPUTE_PGM_RSRC1__DEBUG_MODE_MASK 0x00400000L
+#define COMPUTE_PGM_RSRC1__DEBUG_MODE__SHIFT 0x00000016
+#define COMPUTE_PGM_RSRC1__DX10_CLAMP_MASK 0x00200000L
+#define COMPUTE_PGM_RSRC1__DX10_CLAMP__SHIFT 0x00000015
+#define COMPUTE_PGM_RSRC1__FLOAT_MODE_MASK 0x000ff000L
+#define COMPUTE_PGM_RSRC1__FLOAT_MODE__SHIFT 0x0000000c
+#define COMPUTE_PGM_RSRC1__IEEE_MODE_MASK 0x00800000L
+#define COMPUTE_PGM_RSRC1__IEEE_MODE__SHIFT 0x00000017
+#define COMPUTE_PGM_RSRC1__PRIORITY_MASK 0x00000c00L
+#define COMPUTE_PGM_RSRC1__PRIORITY__SHIFT 0x0000000a
+#define COMPUTE_PGM_RSRC1__PRIV_MASK 0x00100000L
+#define COMPUTE_PGM_RSRC1__PRIV__SHIFT 0x00000014
+#define COMPUTE_PGM_RSRC1__SGPRS_MASK 0x000003c0L
+#define COMPUTE_PGM_RSRC1__SGPRS__SHIFT 0x00000006
+#define COMPUTE_PGM_RSRC1__VGPRS_MASK 0x0000003fL
+#define COMPUTE_PGM_RSRC1__VGPRS__SHIFT 0x00000000
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MASK 0x7f000000L
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MSB_MASK 0x00006000L
+#define COMPUTE_PGM_RSRC2__EXCP_EN_MSB__SHIFT 0x0000000d
+#define COMPUTE_PGM_RSRC2__EXCP_EN__SHIFT 0x00000018
+#define COMPUTE_PGM_RSRC2__LDS_SIZE_MASK 0x00ff8000L
+#define COMPUTE_PGM_RSRC2__LDS_SIZE__SHIFT 0x0000000f
+#define COMPUTE_PGM_RSRC2__SCRATCH_EN_MASK 0x00000001L
+#define COMPUTE_PGM_RSRC2__SCRATCH_EN__SHIFT 0x00000000
+#define COMPUTE_PGM_RSRC2__TGID_X_EN_MASK 0x00000080L
+#define COMPUTE_PGM_RSRC2__TGID_X_EN__SHIFT 0x00000007
+#define COMPUTE_PGM_RSRC2__TGID_Y_EN_MASK 0x00000100L
+#define COMPUTE_PGM_RSRC2__TGID_Y_EN__SHIFT 0x00000008
+#define COMPUTE_PGM_RSRC2__TGID_Z_EN_MASK 0x00000200L
+#define COMPUTE_PGM_RSRC2__TGID_Z_EN__SHIFT 0x00000009
+#define COMPUTE_PGM_RSRC2__TG_SIZE_EN_MASK 0x00000400L
+#define COMPUTE_PGM_RSRC2__TG_SIZE_EN__SHIFT 0x0000000a
+#define COMPUTE_PGM_RSRC2__TIDIG_COMP_CNT_MASK 0x00001800L
+#define COMPUTE_PGM_RSRC2__TIDIG_COMP_CNT__SHIFT 0x0000000b
+#define COMPUTE_PGM_RSRC2__TRAP_PRESENT_MASK 0x00000040L
+#define COMPUTE_PGM_RSRC2__TRAP_PRESENT__SHIFT 0x00000006
+#define COMPUTE_PGM_RSRC2__USER_SGPR_MASK 0x0000003eL
+#define COMPUTE_PGM_RSRC2__USER_SGPR__SHIFT 0x00000001
+#define COMPUTE_RESOURCE_LIMITS__CU_GROUP_COUNT_MASK 0x07000000L
+#define COMPUTE_RESOURCE_LIMITS__CU_GROUP_COUNT__SHIFT 0x00000018
+#define COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST_MASK 0x00800000L
+#define COMPUTE_RESOURCE_LIMITS__FORCE_SIMD_DIST__SHIFT 0x00000017
+#define COMPUTE_RESOURCE_LIMITS__LOCK_THRESHOLD_MASK 0x003f0000L
+#define COMPUTE_RESOURCE_LIMITS__LOCK_THRESHOLD__SHIFT 0x00000010
+#define COMPUTE_RESOURCE_LIMITS__SIMD_DEST_CNTL_MASK 0x00400000L
+#define COMPUTE_RESOURCE_LIMITS__SIMD_DEST_CNTL__SHIFT 0x00000016
+#define COMPUTE_RESOURCE_LIMITS__TG_PER_CU_MASK 0x0000f000L
+#define COMPUTE_RESOURCE_LIMITS__TG_PER_CU__SHIFT 0x0000000c
+#define COMPUTE_RESOURCE_LIMITS__WAVES_PER_SH_MASK 0x0000003fL
+#define COMPUTE_RESOURCE_LIMITS__WAVES_PER_SH__SHIFT 0x00000000
+#define COMPUTE_START_X__START_MASK 0xffffffffL
+#define COMPUTE_START_X__START__SHIFT 0x00000000
+#define COMPUTE_START_Y__START_MASK 0xffffffffL
+#define COMPUTE_START_Y__START__SHIFT 0x00000000
+#define COMPUTE_START_Z__START_MASK 0xffffffffL
+#define COMPUTE_START_Z__START__SHIFT 0x00000000
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH0_CU_EN_MASK 0x0000ffffL
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH0_CU_EN__SHIFT 0x00000000
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH1_CU_EN_MASK 0xffff0000L
+#define COMPUTE_STATIC_THREAD_MGMT_SE0__SH1_CU_EN__SHIFT 0x00000010
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH0_CU_EN_MASK 0x0000ffffL
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH0_CU_EN__SHIFT 0x00000000
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH1_CU_EN_MASK 0xffff0000L
+#define COMPUTE_STATIC_THREAD_MGMT_SE1__SH1_CU_EN__SHIFT 0x00000010
+#define COMPUTE_TBA_HI__DATA_MASK 0x000000ffL
+#define COMPUTE_TBA_HI__DATA__SHIFT 0x00000000
+#define COMPUTE_TBA_LO__DATA_MASK 0xffffffffL
+#define COMPUTE_TBA_LO__DATA__SHIFT 0x00000000
+#define COMPUTE_TMA_HI__DATA_MASK 0x000000ffL
+#define COMPUTE_TMA_HI__DATA__SHIFT 0x00000000
+#define COMPUTE_TMA_LO__DATA_MASK 0xffffffffL
+#define COMPUTE_TMA_LO__DATA__SHIFT 0x00000000
+#define COMPUTE_TMPRING_SIZE__WAVESIZE_MASK 0x01fff000L
+#define COMPUTE_TMPRING_SIZE__WAVESIZE__SHIFT 0x0000000c
+#define COMPUTE_TMPRING_SIZE__WAVES_MASK 0x00000fffL
+#define COMPUTE_TMPRING_SIZE__WAVES__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_0__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_0__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_10__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_10__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_11__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_11__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_12__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_12__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_13__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_13__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_14__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_14__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_15__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_15__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_1__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_1__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_2__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_2__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_3__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_3__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_4__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_4__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_5__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_5__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_6__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_6__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_7__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_7__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_8__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_8__DATA__SHIFT 0x00000000
+#define COMPUTE_USER_DATA_9__DATA_MASK 0xffffffffL
+#define COMPUTE_USER_DATA_9__DATA__SHIFT 0x00000000
+#define COMPUTE_VMID__DATA_MASK 0x0000000fL
+#define COMPUTE_VMID__DATA__SHIFT 0x00000000
+#define CP_APPEND_ADDR_HI__COMMAND_MASK 0xe0000000L
+#define CP_APPEND_ADDR_HI__COMMAND__SHIFT 0x0000001d
+#define CP_APPEND_ADDR_HI__CS_PS_SEL_MASK 0x00030000L
+#define CP_APPEND_ADDR_HI__CS_PS_SEL__SHIFT 0x00000010
+#define CP_APPEND_ADDR_HI__MEM_ADDR_HI_MASK 0x000000ffL
+#define CP_APPEND_ADDR_HI__MEM_ADDR_HI__SHIFT 0x00000000
+#define CP_APPEND_ADDR_LO__MEM_ADDR_LO_MASK 0xfffffffcL
+#define CP_APPEND_ADDR_LO__MEM_ADDR_LO__SHIFT 0x00000002
+#define CP_APPEND_DATA__DATA_MASK 0xffffffffL
+#define CP_APPEND_DATA__DATA__SHIFT 0x00000000
+#define CP_APPEND_LAST_CS_FENCE__LAST_FENCE_MASK 0xffffffffL
+#define CP_APPEND_LAST_CS_FENCE__LAST_FENCE__SHIFT 0x00000000
+#define CP_APPEND_LAST_PS_FENCE__LAST_FENCE_MASK 0xffffffffL
+#define CP_APPEND_LAST_PS_FENCE__LAST_FENCE__SHIFT 0x00000000
+#define CP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI_MASK 0xffffffffL
+#define CP_ATOMIC_PREOP_HI__ATOMIC_PREOP_HI__SHIFT 0x00000000
+#define CP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO_MASK 0xffffffffL
+#define CP_ATOMIC_PREOP_LO__ATOMIC_PREOP_LO__SHIFT 0x00000000
+#define CP_BUSY_STAT__CE_PARSING_PACKETS_MASK 0x00400000L
+#define CP_BUSY_STAT__CE_PARSING_PACKETS__SHIFT 0x00000016
+#define CP_BUSY_STAT__COHER_CNT_NEQ_ZERO_MASK 0x00000040L
+#define CP_BUSY_STAT__COHER_CNT_NEQ_ZERO__SHIFT 0x00000006
+#define CP_BUSY_STAT__EOP_DONE_BUSY_MASK 0x00040000L
+#define CP_BUSY_STAT__EOP_DONE_BUSY__SHIFT 0x00000012
+#define CP_BUSY_STAT__GFX_CONTEXT_BUSY_MASK 0x00008000L
+#define CP_BUSY_STAT__GFX_CONTEXT_BUSY__SHIFT 0x0000000f
+#define CP_BUSY_STAT__ME_PARSER_BUSY_MASK 0x00020000L
+#define CP_BUSY_STAT__ME_PARSER_BUSY__SHIFT 0x00000011
+#define CP_BUSY_STAT__ME_PARSING_PACKETS_MASK 0x00000100L
+#define CP_BUSY_STAT__ME_PARSING_PACKETS__SHIFT 0x00000008
+#define CP_BUSY_STAT__PFP_PARSING_PACKETS_MASK 0x00000080L
+#define CP_BUSY_STAT__PFP_PARSING_PACKETS__SHIFT 0x00000007
+#define CP_BUSY_STAT__PIPE_STATS_BUSY_MASK 0x00100000L
+#define CP_BUSY_STAT__PIPE_STATS_BUSY__SHIFT 0x00000014
+#define CP_BUSY_STAT__RCIU_CE_BUSY_MASK 0x00200000L
+#define CP_BUSY_STAT__RCIU_CE_BUSY__SHIFT 0x00000015
+#define CP_BUSY_STAT__RCIU_ME_BUSY_MASK 0x00000400L
+#define CP_BUSY_STAT__RCIU_ME_BUSY__SHIFT 0x0000000a
+#define CP_BUSY_STAT__RCIU_PFP_BUSY_MASK 0x00000200L
+#define CP_BUSY_STAT__RCIU_PFP_BUSY__SHIFT 0x00000009
+#define CP_BUSY_STAT__REG_BUS_FIFO_BUSY_MASK 0x00000001L
+#define CP_BUSY_STAT__REG_BUS_FIFO_BUSY__SHIFT 0x00000000
+#define CP_BUSY_STAT__SEM_CMDFIFO_NOT_EMPTY_MASK 0x00001000L
+#define CP_BUSY_STAT__SEM_CMDFIFO_NOT_EMPTY__SHIFT 0x0000000c
+#define CP_BUSY_STAT__SEM_FAILED_AND_HOLDING_MASK 0x00002000L
+#define CP_BUSY_STAT__SEM_FAILED_AND_HOLDING__SHIFT 0x0000000d
+#define CP_BUSY_STAT__SEM_POLLING_FOR_PASS_MASK 0x00004000L
+#define CP_BUSY_STAT__SEM_POLLING_FOR_PASS__SHIFT 0x0000000e
+#define CP_BUSY_STAT__STRM_OUT_BUSY_MASK 0x00080000L
+#define CP_BUSY_STAT__STRM_OUT_BUSY__SHIFT 0x00000013
+#define CP_CE_HEADER_DUMP__CE_HEADER_DUMP_MASK 0xffffffffL
+#define CP_CE_HEADER_DUMP__CE_HEADER_DUMP__SHIFT 0x00000000
+#define CP_CE_IB1_BASE_HI__IB1_BASE_HI_MASK 0x000000ffL
+#define CP_CE_IB1_BASE_HI__IB1_BASE_HI__SHIFT 0x00000000
+#define CP_CE_IB1_BASE_LO__IB1_BASE_LO_MASK 0xfffffffcL
+#define CP_CE_IB1_BASE_LO__IB1_BASE_LO__SHIFT 0x00000002
+#define CP_CE_IB1_BUFSZ__IB1_BUFSZ_MASK 0x000fffffL
+#define CP_CE_IB1_BUFSZ__IB1_BUFSZ__SHIFT 0x00000000
+#define CP_CE_IB2_BASE_HI__IB2_BASE_HI_MASK 0x000000ffL
+#define CP_CE_IB2_BASE_HI__IB2_BASE_HI__SHIFT 0x00000000
+#define CP_CE_IB2_BASE_LO__IB2_BASE_LO_MASK 0xfffffffcL
+#define CP_CE_IB2_BASE_LO__IB2_BASE_LO__SHIFT 0x00000002
+#define CP_CE_IB2_BUFSZ__IB2_BUFSZ_MASK 0x000fffffL
+#define CP_CE_IB2_BUFSZ__IB2_BUFSZ__SHIFT 0x00000000
+#define CP_CE_INIT_BASE_HI__INIT_BASE_HI_MASK 0x000000ffL
+#define CP_CE_INIT_BASE_HI__INIT_BASE_HI__SHIFT 0x00000000
+#define CP_CE_INIT_BASE_LO__INIT_BASE_LO_MASK 0xffffffe0L
+#define CP_CE_INIT_BASE_LO__INIT_BASE_LO__SHIFT 0x00000005
+#define CP_CE_INIT_BUFSZ__INIT_BUFSZ_MASK 0x00000fffL
+#define CP_CE_INIT_BUFSZ__INIT_BUFSZ__SHIFT 0x00000000
+#define CP_CEQ1_AVAIL__CEQ_CNT_IB1_MASK 0x07ff0000L
+#define CP_CEQ1_AVAIL__CEQ_CNT_IB1__SHIFT 0x00000010
+#define CP_CEQ1_AVAIL__CEQ_CNT_RING_MASK 0x000007ffL
+#define CP_CEQ1_AVAIL__CEQ_CNT_RING__SHIFT 0x00000000
+#define CP_CEQ2_AVAIL__CEQ_CNT_IB2_MASK 0x000007ffL
+#define CP_CEQ2_AVAIL__CEQ_CNT_IB2__SHIFT 0x00000000
+#define CP_CE_ROQ_IB1_STAT__CEQ_RPTR_INDIRECT1_MASK 0x000003ffL
+#define CP_CE_ROQ_IB1_STAT__CEQ_RPTR_INDIRECT1__SHIFT 0x00000000
+#define CP_CE_ROQ_IB1_STAT__CEQ_WPTR_INDIRECT1_MASK 0x03ff0000L
+#define CP_CE_ROQ_IB1_STAT__CEQ_WPTR_INDIRECT1__SHIFT 0x00000010
+#define CP_CE_ROQ_IB2_STAT__CEQ_RPTR_INDIRECT2_MASK 0x000003ffL
+#define CP_CE_ROQ_IB2_STAT__CEQ_RPTR_INDIRECT2__SHIFT 0x00000000
+#define CP_CE_ROQ_IB2_STAT__CEQ_WPTR_INDIRECT2_MASK 0x03ff0000L
+#define CP_CE_ROQ_IB2_STAT__CEQ_WPTR_INDIRECT2__SHIFT 0x00000010
+#define CP_CE_ROQ_RB_STAT__CEQ_RPTR_PRIMARY_MASK 0x000003ffL
+#define CP_CE_ROQ_RB_STAT__CEQ_RPTR_PRIMARY__SHIFT 0x00000000
+#define CP_CE_ROQ_RB_STAT__CEQ_WPTR_PRIMARY_MASK 0x03ff0000L
+#define CP_CE_ROQ_RB_STAT__CEQ_WPTR_PRIMARY__SHIFT 0x00000010
+#define CP_CE_UCODE_ADDR__UCODE_ADDR_MASK 0x00000fffL
+#define CP_CE_UCODE_ADDR__UCODE_ADDR__SHIFT 0x00000000
+#define CP_CE_UCODE_DATA__UCODE_DATA_MASK 0xffffffffL
+#define CP_CE_UCODE_DATA__UCODE_DATA__SHIFT 0x00000000
+#define CP_CMD_DATA__CMD_DATA_MASK 0xffffffffL
+#define CP_CMD_DATA__CMD_DATA__SHIFT 0x00000000
+#define CP_CMD_INDEX__CMD_INDEX_MASK 0x000007ffL
+#define CP_CMD_INDEX__CMD_INDEX__SHIFT 0x00000000
+#define CP_CMD_INDEX__CMD_ME_SEL_MASK 0x00003000L
+#define CP_CMD_INDEX__CMD_ME_SEL__SHIFT 0x0000000c
+#define CP_CMD_INDEX__CMD_QUEUE_SEL_MASK 0x00030000L
+#define CP_CMD_INDEX__CMD_QUEUE_SEL__SHIFT 0x00000010
+#define CP_CNTX_STAT__ACTIVE_GFX_CONTEXTS_MASK 0x0ff00000L
+#define CP_CNTX_STAT__ACTIVE_GFX_CONTEXTS__SHIFT 0x00000014
+#define CP_CNTX_STAT__ACTIVE_HP3D_CONTEXTS_MASK 0x000000ffL
+#define CP_CNTX_STAT__ACTIVE_HP3D_CONTEXTS__SHIFT 0x00000000
+#define CP_CNTX_STAT__CURRENT_GFX_CONTEXT_MASK 0x70000000L
+#define CP_CNTX_STAT__CURRENT_GFX_CONTEXT__SHIFT 0x0000001c
+#define CP_CNTX_STAT__CURRENT_HP3D_CONTEXT_MASK 0x00000700L
+#define CP_CNTX_STAT__CURRENT_HP3D_CONTEXT__SHIFT 0x00000008
+#define CP_COHER_BASE__COHER_BASE_256B_MASK 0xffffffffL
+#define CP_COHER_BASE__COHER_BASE_256B__SHIFT 0x00000000
+#define CP_COHER_BASE_HI__COHER_BASE_HI_256B_MASK 0x000000ffL
+#define CP_COHER_BASE_HI__COHER_BASE_HI_256B__SHIFT 0x00000000
+#define CP_COHER_CNTL__CB0_DEST_BASE_ENA_MASK 0x00000040L
+#define CP_COHER_CNTL__CB0_DEST_BASE_ENA__SHIFT 0x00000006
+#define CP_COHER_CNTL__CB1_DEST_BASE_ENA_MASK 0x00000080L
+#define CP_COHER_CNTL__CB1_DEST_BASE_ENA__SHIFT 0x00000007
+#define CP_COHER_CNTL__CB2_DEST_BASE_ENA_MASK 0x00000100L
+#define CP_COHER_CNTL__CB2_DEST_BASE_ENA__SHIFT 0x00000008
+#define CP_COHER_CNTL__CB3_DEST_BASE_ENA_MASK 0x00000200L
+#define CP_COHER_CNTL__CB3_DEST_BASE_ENA__SHIFT 0x00000009
+#define CP_COHER_CNTL__CB4_DEST_BASE_ENA_MASK 0x00000400L
+#define CP_COHER_CNTL__CB4_DEST_BASE_ENA__SHIFT 0x0000000a
+#define CP_COHER_CNTL__CB5_DEST_BASE_ENA_MASK 0x00000800L
+#define CP_COHER_CNTL__CB5_DEST_BASE_ENA__SHIFT 0x0000000b
+#define CP_COHER_CNTL__CB6_DEST_BASE_ENA_MASK 0x00001000L
+#define CP_COHER_CNTL__CB6_DEST_BASE_ENA__SHIFT 0x0000000c
+#define CP_COHER_CNTL__CB7_DEST_BASE_ENA_MASK 0x00002000L
+#define CP_COHER_CNTL__CB7_DEST_BASE_ENA__SHIFT 0x0000000d
+#define CP_COHER_CNTL__CB_ACTION_ENA_MASK 0x02000000L
+#define CP_COHER_CNTL__CB_ACTION_ENA__SHIFT 0x00000019
+#define CP_COHER_CNTL__DB_ACTION_ENA_MASK 0x04000000L
+#define CP_COHER_CNTL__DB_ACTION_ENA__SHIFT 0x0000001a
+#define CP_COHER_CNTL__DB_DEST_BASE_ENA_MASK 0x00004000L
+#define CP_COHER_CNTL__DB_DEST_BASE_ENA__SHIFT 0x0000000e
+#define CP_COHER_CNTL__DEST_BASE_0_ENA_MASK 0x00000001L
+#define CP_COHER_CNTL__DEST_BASE_0_ENA__SHIFT 0x00000000
+#define CP_COHER_CNTL__DEST_BASE_1_ENA_MASK 0x00000002L
+#define CP_COHER_CNTL__DEST_BASE_1_ENA__SHIFT 0x00000001
+#define CP_COHER_CNTL__DEST_BASE_2_ENA_MASK 0x00080000L
+#define CP_COHER_CNTL__DEST_BASE_2_ENA__SHIFT 0x00000013
+#define CP_COHER_CNTL__DEST_BASE_3_ENA_MASK 0x00200000L
+#define CP_COHER_CNTL__DEST_BASE_3_ENA__SHIFT 0x00000015
+#define CP_COHER_CNTL__SH_ICACHE_ACTION_ENA_MASK 0x20000000L
+#define CP_COHER_CNTL__SH_ICACHE_ACTION_ENA__SHIFT 0x0000001d
+#define CP_COHER_CNTL__SH_KCACHE_ACTION_ENA_MASK 0x08000000L
+#define CP_COHER_CNTL__SH_KCACHE_ACTION_ENA__SHIFT 0x0000001b
+#define CP_COHER_CNTL__SH_KCACHE_VOL_ACTION_ENA_MASK 0x10000000L
+#define CP_COHER_CNTL__SH_KCACHE_VOL_ACTION_ENA__SHIFT 0x0000001c
+#define CP_COHER_CNTL__TC_ACTION_ENA_MASK 0x00800000L
+#define CP_COHER_CNTL__TC_ACTION_ENA__SHIFT 0x00000017
+#define CP_COHER_CNTL__TCL1_ACTION_ENA_MASK 0x00400000L
+#define CP_COHER_CNTL__TCL1_ACTION_ENA__SHIFT 0x00000016
+#define CP_COHER_CNTL__TCL1_VOL_ACTION_ENA_MASK 0x00008000L
+#define CP_COHER_CNTL__TCL1_VOL_ACTION_ENA__SHIFT 0x0000000f
+#define CP_COHER_CNTL__TC_VOL_ACTION_ENA_MASK 0x00010000L
+#define CP_COHER_CNTL__TC_VOL_ACTION_ENA__SHIFT 0x00000010
+#define CP_COHER_CNTL__TC_WB_ACTION_ENA_MASK 0x00040000L
+#define CP_COHER_CNTL__TC_WB_ACTION_ENA__SHIFT 0x00000012
+#define CP_COHER_SIZE__COHER_SIZE_256B_MASK 0xffffffffL
+#define CP_COHER_SIZE__COHER_SIZE_256B__SHIFT 0x00000000
+#define CP_COHER_SIZE_HI__COHER_SIZE_HI_256B_MASK 0x000000ffL
+#define CP_COHER_SIZE_HI__COHER_SIZE_HI_256B__SHIFT 0x00000000
+#define CP_COHER_START_DELAY__START_DELAY_COUNT_MASK 0x0000003fL
+#define CP_COHER_START_DELAY__START_DELAY_COUNT__SHIFT 0x00000000
+#define CP_COHER_STATUS__MATCHING_GFX_CNTX_MASK 0x000000ffL
+#define CP_COHER_STATUS__MATCHING_GFX_CNTX__SHIFT 0x00000000
+#define CP_COHER_STATUS__MEID_MASK 0x03000000L
+#define CP_COHER_STATUS__MEID__SHIFT 0x00000018
+#define CP_COHER_STATUS__PHASE1_STATUS_MASK 0x40000000L
+#define CP_COHER_STATUS__PHASE1_STATUS__SHIFT 0x0000001e
+#define CP_COHER_STATUS__STATUS_MASK 0x80000000L
+#define CP_COHER_STATUS__STATUS__SHIFT 0x0000001f
+#define CP_CSF_CNTL__FETCH_BUFFER_DEPTH_MASK 0x0000000fL
+#define CP_CSF_CNTL__FETCH_BUFFER_DEPTH__SHIFT 0x00000000
+#define CP_CSF_STAT__BUFFER_REQUEST_COUNT_MASK 0x00003f00L
+#define CP_CSF_STAT__BUFFER_REQUEST_COUNT__SHIFT 0x00000008
+#define CP_CSF_STAT__BUFFER_SLOTS_ALLOCATED_MASK 0x0000000fL
+#define CP_CSF_STAT__BUFFER_SLOTS_ALLOCATED__SHIFT 0x00000000
+#define CP_DMA_CNTL__BUFFER_DEPTH_MASK 0x000f0000L
+#define CP_DMA_CNTL__BUFFER_DEPTH__SHIFT 0x00000010
+#define CP_DMA_CNTL__MIN_AVAILSZ_MASK 0x00000030L
+#define CP_DMA_CNTL__MIN_AVAILSZ__SHIFT 0x00000004
+#define CP_DMA_CNTL__PIO_COUNT_MASK 0xc0000000L
+#define CP_DMA_CNTL__PIO_COUNT__SHIFT 0x0000001e
+#define CP_DMA_CNTL__PIO_FIFO_EMPTY_MASK 0x10000000L
+#define CP_DMA_CNTL__PIO_FIFO_EMPTY__SHIFT 0x0000001c
+#define CP_DMA_CNTL__PIO_FIFO_FULL_MASK 0x20000000L
+#define CP_DMA_CNTL__PIO_FIFO_FULL__SHIFT 0x0000001d
+#define CP_DMA_ME_COMMAND__BYTE_COUNT_MASK 0x001fffffL
+#define CP_DMA_ME_COMMAND__BYTE_COUNT__SHIFT 0x00000000
+#define CP_DMA_ME_COMMAND__DAIC_MASK 0x20000000L
+#define CP_DMA_ME_COMMAND__DAIC__SHIFT 0x0000001d
+#define CP_DMA_ME_COMMAND__DAS_MASK 0x08000000L
+#define CP_DMA_ME_COMMAND__DAS__SHIFT 0x0000001b
+#define CP_DMA_ME_COMMAND__DIS_WC_MASK 0x00200000L
+#define CP_DMA_ME_COMMAND__DIS_WC__SHIFT 0x00000015
+#define CP_DMA_ME_COMMAND__DST_SWAP_MASK 0x03000000L
+#define CP_DMA_ME_COMMAND__DST_SWAP__SHIFT 0x00000018
+#define CP_DMA_ME_COMMAND__RAW_WAIT_MASK 0x40000000L
+#define CP_DMA_ME_COMMAND__RAW_WAIT__SHIFT 0x0000001e
+#define CP_DMA_ME_COMMAND__SAIC_MASK 0x10000000L
+#define CP_DMA_ME_COMMAND__SAIC__SHIFT 0x0000001c
+#define CP_DMA_ME_COMMAND__SAS_MASK 0x04000000L
+#define CP_DMA_ME_COMMAND__SAS__SHIFT 0x0000001a
+#define CP_DMA_ME_COMMAND__SRC_SWAP_MASK 0x00c00000L
+#define CP_DMA_ME_COMMAND__SRC_SWAP__SHIFT 0x00000016
+#define CP_DMA_ME_DST_ADDR__DST_ADDR_MASK 0xffffffffL
+#define CP_DMA_ME_DST_ADDR__DST_ADDR__SHIFT 0x00000000
+#define CP_DMA_ME_DST_ADDR_HI__DST_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_ME_DST_ADDR_HI__DST_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_ME_SRC_ADDR_HI__SRC_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_ME_SRC_ADDR_HI__SRC_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_ME_SRC_ADDR__SRC_ADDR_MASK 0xffffffffL
+#define CP_DMA_ME_SRC_ADDR__SRC_ADDR__SHIFT 0x00000000
+#define CP_DMA_PFP_COMMAND__BYTE_COUNT_MASK 0x001fffffL
+#define CP_DMA_PFP_COMMAND__BYTE_COUNT__SHIFT 0x00000000
+#define CP_DMA_PFP_COMMAND__DAIC_MASK 0x20000000L
+#define CP_DMA_PFP_COMMAND__DAIC__SHIFT 0x0000001d
+#define CP_DMA_PFP_COMMAND__DAS_MASK 0x08000000L
+#define CP_DMA_PFP_COMMAND__DAS__SHIFT 0x0000001b
+#define CP_DMA_PFP_COMMAND__DIS_WC_MASK 0x00200000L
+#define CP_DMA_PFP_COMMAND__DIS_WC__SHIFT 0x00000015
+#define CP_DMA_PFP_COMMAND__DST_SWAP_MASK 0x03000000L
+#define CP_DMA_PFP_COMMAND__DST_SWAP__SHIFT 0x00000018
+#define CP_DMA_PFP_COMMAND__RAW_WAIT_MASK 0x40000000L
+#define CP_DMA_PFP_COMMAND__RAW_WAIT__SHIFT 0x0000001e
+#define CP_DMA_PFP_COMMAND__SAIC_MASK 0x10000000L
+#define CP_DMA_PFP_COMMAND__SAIC__SHIFT 0x0000001c
+#define CP_DMA_PFP_COMMAND__SAS_MASK 0x04000000L
+#define CP_DMA_PFP_COMMAND__SAS__SHIFT 0x0000001a
+#define CP_DMA_PFP_COMMAND__SRC_SWAP_MASK 0x00c00000L
+#define CP_DMA_PFP_COMMAND__SRC_SWAP__SHIFT 0x00000016
+#define CP_DMA_PFP_DST_ADDR__DST_ADDR_MASK 0xffffffffL
+#define CP_DMA_PFP_DST_ADDR__DST_ADDR__SHIFT 0x00000000
+#define CP_DMA_PFP_DST_ADDR_HI__DST_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_PFP_DST_ADDR_HI__DST_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_PFP_SRC_ADDR_HI__SRC_ADDR_HI_MASK 0x000000ffL
+#define CP_DMA_PFP_SRC_ADDR_HI__SRC_ADDR_HI__SHIFT 0x00000000
+#define CP_DMA_PFP_SRC_ADDR__SRC_ADDR_MASK 0xffffffffL
+#define CP_DMA_PFP_SRC_ADDR__SRC_ADDR__SHIFT 0x00000000
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_MASK 0x03ffffffL
+#define CP_DMA_READ_TAGS__DMA_READ_TAG__SHIFT 0x00000000
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_VALID_MASK 0x10000000L
+#define CP_DMA_READ_TAGS__DMA_READ_TAG_VALID__SHIFT 0x0000001c
+#define CP_ECC_FIRSTOCCURRENCE__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING0__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE_RING0__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING0__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE_RING0__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE_RING0__VMID__SHIFT 0x00000010
+#define CP_ECC_FIRSTOCCURRENCE_RING1__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE_RING1__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING1__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE_RING1__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE_RING1__VMID__SHIFT 0x00000010
+#define CP_ECC_FIRSTOCCURRENCE_RING2__INTERFACE_MASK 0x00000003L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__INTERFACE__SHIFT 0x00000000
+#define CP_ECC_FIRSTOCCURRENCE_RING2__REQUEST_CLIENT_MASK 0x000000f0L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__REQUEST_CLIENT__SHIFT 0x00000004
+#define CP_ECC_FIRSTOCCURRENCE_RING2__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE_RING2__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE_RING2__VMID__SHIFT 0x00000010
+#define CP_ECC_FIRSTOCCURRENCE__RING_ID_MASK 0x00003c00L
+#define CP_ECC_FIRSTOCCURRENCE__RING_ID__SHIFT 0x0000000a
+#define CP_ECC_FIRSTOCCURRENCE__VMID_MASK 0x000f0000L
+#define CP_ECC_FIRSTOCCURRENCE__VMID__SHIFT 0x00000010
+#define CP_EOP_DONE_ADDR_HI__ADDR_HI_MASK 0x0000ffffL
+#define CP_EOP_DONE_ADDR_HI__ADDR_HI__SHIFT 0x00000000
+#define CP_EOP_DONE_ADDR_LO__ADDR_LO_MASK 0xfffffffcL
+#define CP_EOP_DONE_ADDR_LO__ADDR_LO__SHIFT 0x00000002
+#define CP_EOP_DONE_ADDR_LO__ADDR_SWAP_MASK 0x00000003L
+#define CP_EOP_DONE_ADDR_LO__ADDR_SWAP__SHIFT 0x00000000
+#define CP_EOP_DONE_DATA_CNTL__CNTX_ID_MASK 0x0000ffffL
+#define CP_EOP_DONE_DATA_CNTL__CNTX_ID__SHIFT 0x00000000
+#define CP_EOP_DONE_DATA_CNTL__DATA_SEL_MASK 0xe0000000L
+#define CP_EOP_DONE_DATA_CNTL__DATA_SEL__SHIFT 0x0000001d
+#define CP_EOP_DONE_DATA_CNTL__DST_SEL_MASK 0x00030000L
+#define CP_EOP_DONE_DATA_CNTL__DST_SEL__SHIFT 0x00000010
+#define CP_EOP_DONE_DATA_CNTL__INT_SEL_MASK 0x07000000L
+#define CP_EOP_DONE_DATA_CNTL__INT_SEL__SHIFT 0x00000018
+#define CP_EOP_DONE_DATA_HI__DATA_HI_MASK 0xffffffffL
+#define CP_EOP_DONE_DATA_HI__DATA_HI__SHIFT 0x00000000
+#define CP_EOP_DONE_DATA_LO__DATA_LO_MASK 0xffffffffL
+#define CP_EOP_DONE_DATA_LO__DATA_LO__SHIFT 0x00000000
+#define CP_EOP_LAST_FENCE_HI__LAST_FENCE_HI_MASK 0xffffffffL
+#define CP_EOP_LAST_FENCE_HI__LAST_FENCE_HI__SHIFT 0x00000000
+#define CP_EOP_LAST_FENCE_LO__LAST_FENCE_LO_MASK 0xffffffffL
+#define CP_EOP_LAST_FENCE_LO__LAST_FENCE_LO__SHIFT 0x00000000
+#define CP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI_MASK 0xffffffffL
+#define CP_GDS_ATOMIC0_PREOP_HI__GDS_ATOMIC0_PREOP_HI__SHIFT 0x00000000
+#define CP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO_MASK 0xffffffffL
+#define CP_GDS_ATOMIC0_PREOP_LO__GDS_ATOMIC0_PREOP_LO__SHIFT 0x00000000
+#define CP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI_MASK 0xffffffffL
+#define CP_GDS_ATOMIC1_PREOP_HI__GDS_ATOMIC1_PREOP_HI__SHIFT 0x00000000
+#define CP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO_MASK 0xffffffffL
+#define CP_GDS_ATOMIC1_PREOP_LO__GDS_ATOMIC1_PREOP_LO__SHIFT 0x00000000
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_GDS_MASK 0x00003f00L
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_GDS__SHIFT 0x00000008
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_MASK 0x0000003fL
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_PFP_MASK 0x003f0000L
+#define CP_GRBM_FREE_COUNT__FREE_COUNT_PFP__SHIFT 0x00000010
+#define CP_GRBM_FREE_COUNT__FREE_COUNT__SHIFT 0x00000000
+#define CP_IB1_BASE_HI__IB1_BASE_HI_MASK 0x000000ffL
+#define CP_IB1_BASE_HI__IB1_BASE_HI__SHIFT 0x00000000
+#define CP_IB1_BASE_LO__IB1_BASE_LO_MASK 0xfffffffcL
+#define CP_IB1_BASE_LO__IB1_BASE_LO__SHIFT 0x00000002
+#define CP_IB1_BUFSZ__IB1_BUFSZ_MASK 0x000fffffL
+#define CP_IB1_BUFSZ__IB1_BUFSZ__SHIFT 0x00000000
+#define CP_IB1_OFFSET__IB1_OFFSET_MASK 0x000fffffL
+#define CP_IB1_OFFSET__IB1_OFFSET__SHIFT 0x00000000
+#define CP_IB1_PREAMBLE_BEGIN__IB1_PREAMBLE_BEGIN_MASK 0x000fffffL
+#define CP_IB1_PREAMBLE_BEGIN__IB1_PREAMBLE_BEGIN__SHIFT 0x00000000
+#define CP_IB1_PREAMBLE_END__IB1_PREAMBLE_END_MASK 0x000fffffL
+#define CP_IB1_PREAMBLE_END__IB1_PREAMBLE_END__SHIFT 0x00000000
+#define CP_IB2_BASE_HI__IB2_BASE_HI_MASK 0x000000ffL
+#define CP_IB2_BASE_HI__IB2_BASE_HI__SHIFT 0x00000000
+#define CP_IB2_BASE_LO__IB2_BASE_LO_MASK 0xfffffffcL
+#define CP_IB2_BASE_LO__IB2_BASE_LO__SHIFT 0x00000002
+#define CP_IB2_BUFSZ__IB2_BUFSZ_MASK 0x000fffffL
+#define CP_IB2_BUFSZ__IB2_BUFSZ__SHIFT 0x00000000
+#define CP_IB2_OFFSET__IB2_OFFSET_MASK 0x000fffffL
+#define CP_IB2_OFFSET__IB2_OFFSET__SHIFT 0x00000000
+#define CP_IB2_PREAMBLE_BEGIN__IB2_PREAMBLE_BEGIN_MASK 0x000fffffL
+#define CP_IB2_PREAMBLE_BEGIN__IB2_PREAMBLE_BEGIN__SHIFT 0x00000000
+#define CP_IB2_PREAMBLE_END__IB2_PREAMBLE_END_MASK 0x000fffffL
+#define CP_IB2_PREAMBLE_END__IB2_PREAMBLE_END__SHIFT 0x00000000
+#define CP_INT_CNTL__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING0__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL_RING0__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL_RING0__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL_RING0__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL_RING0__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL_RING0__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL_RING0__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL_RING0__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL_RING0__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL_RING0__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL_RING0__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL_RING0__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL_RING0__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL_RING0__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL_RING0__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL_RING0__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL_RING0__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL_RING0__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_CNTL_RING1__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL_RING1__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL_RING1__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL_RING1__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL_RING1__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL_RING1__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL_RING1__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL_RING1__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL_RING1__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL_RING1__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL_RING1__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL_RING1__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL_RING1__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL_RING1__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL_RING1__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL_RING1__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL_RING1__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL_RING1__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL_RING1__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL_RING1__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL_RING1__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL_RING1__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL_RING1__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_CNTL_RING2__CNTX_BUSY_INT_ENABLE_MASK 0x00080000L
+#define CP_INT_CNTL_RING2__CNTX_BUSY_INT_ENABLE__SHIFT 0x00000013
+#define CP_INT_CNTL_RING2__CNTX_EMPTY_INT_ENABLE_MASK 0x00100000L
+#define CP_INT_CNTL_RING2__CNTX_EMPTY_INT_ENABLE__SHIFT 0x00000014
+#define CP_INT_CNTL_RING2__CP_ECC_ERROR_INT_ENABLE_MASK 0x00004000L
+#define CP_INT_CNTL_RING2__CP_ECC_ERROR_INT_ENABLE__SHIFT 0x0000000e
+#define CP_INT_CNTL_RING2__GENERIC0_INT_ENABLE_MASK 0x80000000L
+#define CP_INT_CNTL_RING2__GENERIC0_INT_ENABLE__SHIFT 0x0000001f
+#define CP_INT_CNTL_RING2__GENERIC1_INT_ENABLE_MASK 0x40000000L
+#define CP_INT_CNTL_RING2__GENERIC1_INT_ENABLE__SHIFT 0x0000001e
+#define CP_INT_CNTL_RING2__GENERIC2_INT_ENABLE_MASK 0x20000000L
+#define CP_INT_CNTL_RING2__GENERIC2_INT_ENABLE__SHIFT 0x0000001d
+#define CP_INT_CNTL_RING2__OPCODE_ERROR_INT_ENABLE_MASK 0x01000000L
+#define CP_INT_CNTL_RING2__OPCODE_ERROR_INT_ENABLE__SHIFT 0x00000018
+#define CP_INT_CNTL_RING2__PRIV_INSTR_INT_ENABLE_MASK 0x00400000L
+#define CP_INT_CNTL_RING2__PRIV_INSTR_INT_ENABLE__SHIFT 0x00000016
+#define CP_INT_CNTL_RING2__PRIV_REG_INT_ENABLE_MASK 0x00800000L
+#define CP_INT_CNTL_RING2__PRIV_REG_INT_ENABLE__SHIFT 0x00000017
+#define CP_INT_CNTL_RING2__RESERVED_BIT_ERROR_INT_ENABLE_MASK 0x08000000L
+#define CP_INT_CNTL_RING2__RESERVED_BIT_ERROR_INT_ENABLE__SHIFT 0x0000001b
+#define CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL_RING2__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL_RING2__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL_RING2__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_CNTL__TIME_STAMP_INT_ENABLE_MASK 0x04000000L
+#define CP_INT_CNTL__TIME_STAMP_INT_ENABLE__SHIFT 0x0000001a
+#define CP_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE_MASK 0x00020000L
+#define CP_INT_CNTL__WRM_POLL_TIMEOUT_INT_ENABLE__SHIFT 0x00000011
+#define CP_INT_STAT_DEBUG__CNTX_BUSY_INT_ASSERTED_MASK 0x00080000L
+#define CP_INT_STAT_DEBUG__CNTX_BUSY_INT_ASSERTED__SHIFT 0x00000013
+#define CP_INT_STAT_DEBUG__CNTX_EMPTY_INT_ASSERTED_MASK 0x00100000L
+#define CP_INT_STAT_DEBUG__CNTX_EMPTY_INT_ASSERTED__SHIFT 0x00000014
+#define CP_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED_MASK 0x00004000L
+#define CP_INT_STAT_DEBUG__CP_ECC_ERROR_INT_ASSERTED__SHIFT 0x0000000e
+#define CP_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED_MASK 0x80000000L
+#define CP_INT_STAT_DEBUG__GENERIC0_INT_ASSERTED__SHIFT 0x0000001f
+#define CP_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED_MASK 0x40000000L
+#define CP_INT_STAT_DEBUG__GENERIC1_INT_ASSERTED__SHIFT 0x0000001e
+#define CP_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED_MASK 0x20000000L
+#define CP_INT_STAT_DEBUG__GENERIC2_INT_ASSERTED__SHIFT 0x0000001d
+#define CP_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED_MASK 0x01000000L
+#define CP_INT_STAT_DEBUG__OPCODE_ERROR_INT_ASSERTED__SHIFT 0x00000018
+#define CP_INT_STAT_DEBUG__PRIV_INSTR_INT_ASSERTED_MASK 0x00400000L
+#define CP_INT_STAT_DEBUG__PRIV_INSTR_INT_ASSERTED__SHIFT 0x00000016
+#define CP_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED_MASK 0x00800000L
+#define CP_INT_STAT_DEBUG__PRIV_REG_INT_ASSERTED__SHIFT 0x00000017
+#define CP_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED_MASK 0x08000000L
+#define CP_INT_STAT_DEBUG__RESERVED_BIT_ERROR_INT_ASSERTED__SHIFT 0x0000001b
+#define CP_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED_MASK 0x04000000L
+#define CP_INT_STAT_DEBUG__TIME_STAMP_INT_ASSERTED__SHIFT 0x0000001a
+#define CP_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED_MASK 0x00020000L
+#define CP_INT_STAT_DEBUG__WRM_POLL_TIMEOUT_INT_ASSERTED__SHIFT 0x00000011
+#define CP_INT_STATUS__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING0__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS_RING0__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS_RING0__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS_RING0__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS_RING0__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS_RING0__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS_RING0__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS_RING0__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS_RING0__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS_RING0__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS_RING0__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS_RING0__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS_RING0__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS_RING0__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS_RING0__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS_RING0__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS_RING0__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS_RING0__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS_RING0__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS_RING0__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING0__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS_RING0__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS_RING0__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS_RING0__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_INT_STATUS_RING1__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS_RING1__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS_RING1__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS_RING1__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS_RING1__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS_RING1__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS_RING1__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS_RING1__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS_RING1__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS_RING1__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS_RING1__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS_RING1__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS_RING1__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS_RING1__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS_RING1__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS_RING1__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS_RING1__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS_RING1__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS_RING1__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS_RING1__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING1__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS_RING1__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS_RING1__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS_RING1__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_INT_STATUS_RING2__CNTX_BUSY_INT_STAT_MASK 0x00080000L
+#define CP_INT_STATUS_RING2__CNTX_BUSY_INT_STAT__SHIFT 0x00000013
+#define CP_INT_STATUS_RING2__CNTX_EMPTY_INT_STAT_MASK 0x00100000L
+#define CP_INT_STATUS_RING2__CNTX_EMPTY_INT_STAT__SHIFT 0x00000014
+#define CP_INT_STATUS_RING2__CP_ECC_ERROR_INT_STAT_MASK 0x00004000L
+#define CP_INT_STATUS_RING2__CP_ECC_ERROR_INT_STAT__SHIFT 0x0000000e
+#define CP_INT_STATUS_RING2__GENERIC0_INT_STAT_MASK 0x80000000L
+#define CP_INT_STATUS_RING2__GENERIC0_INT_STAT__SHIFT 0x0000001f
+#define CP_INT_STATUS_RING2__GENERIC1_INT_STAT_MASK 0x40000000L
+#define CP_INT_STATUS_RING2__GENERIC1_INT_STAT__SHIFT 0x0000001e
+#define CP_INT_STATUS_RING2__GENERIC2_INT_STAT_MASK 0x20000000L
+#define CP_INT_STATUS_RING2__GENERIC2_INT_STAT__SHIFT 0x0000001d
+#define CP_INT_STATUS_RING2__OPCODE_ERROR_INT_STAT_MASK 0x01000000L
+#define CP_INT_STATUS_RING2__OPCODE_ERROR_INT_STAT__SHIFT 0x00000018
+#define CP_INT_STATUS_RING2__PRIV_INSTR_INT_STAT_MASK 0x00400000L
+#define CP_INT_STATUS_RING2__PRIV_INSTR_INT_STAT__SHIFT 0x00000016
+#define CP_INT_STATUS_RING2__PRIV_REG_INT_STAT_MASK 0x00800000L
+#define CP_INT_STATUS_RING2__PRIV_REG_INT_STAT__SHIFT 0x00000017
+#define CP_INT_STATUS_RING2__RESERVED_BIT_ERROR_INT_STAT_MASK 0x08000000L
+#define CP_INT_STATUS_RING2__RESERVED_BIT_ERROR_INT_STAT__SHIFT 0x0000001b
+#define CP_INT_STATUS_RING2__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS_RING2__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS_RING2__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS_RING2__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_INT_STATUS__TIME_STAMP_INT_STAT_MASK 0x04000000L
+#define CP_INT_STATUS__TIME_STAMP_INT_STAT__SHIFT 0x0000001a
+#define CP_INT_STATUS__WRM_POLL_TIMEOUT_INT_STAT_MASK 0x00020000L
+#define CP_INT_STATUS__WRM_POLL_TIMEOUT_INT_STAT__SHIFT 0x00000011
+#define CP_MC_PACK_DELAY_CNT__PACK_DELAY_CNT_MASK 0x0000001fL
+#define CP_MC_PACK_DELAY_CNT__PACK_DELAY_CNT__SHIFT 0x00000000
+#define CP_ME_CNTL__CE_HALT_MASK 0x01000000L
+#define CP_ME_CNTL__CE_HALT__SHIFT 0x00000018
+#define CP_ME_CNTL__CE_INVALIDATE_ICACHE_MASK 0x00000010L
+#define CP_ME_CNTL__CE_INVALIDATE_ICACHE__SHIFT 0x00000004
+#define CP_ME_CNTL__CE_STEP_MASK 0x02000000L
+#define CP_ME_CNTL__CE_STEP__SHIFT 0x00000019
+#define CP_ME_CNTL__ME_HALT_MASK 0x10000000L
+#define CP_ME_CNTL__ME_HALT__SHIFT 0x0000001c
+#define CP_ME_CNTL__ME_INVALIDATE_ICACHE_MASK 0x00000100L
+#define CP_ME_CNTL__ME_INVALIDATE_ICACHE__SHIFT 0x00000008
+#define CP_ME_CNTL__ME_STEP_MASK 0x20000000L
+#define CP_ME_CNTL__ME_STEP__SHIFT 0x0000001d
+#define CP_ME_CNTL__PFP_HALT_MASK 0x04000000L
+#define CP_ME_CNTL__PFP_HALT__SHIFT 0x0000001a
+#define CP_ME_CNTL__PFP_INVALIDATE_ICACHE_MASK 0x00000040L
+#define CP_ME_CNTL__PFP_INVALIDATE_ICACHE__SHIFT 0x00000006
+#define CP_ME_CNTL__PFP_STEP_MASK 0x08000000L
+#define CP_ME_CNTL__PFP_STEP__SHIFT 0x0000001b
+#define CP_ME_HEADER_DUMP__ME_HEADER_DUMP_MASK 0xffffffffL
+#define CP_ME_HEADER_DUMP__ME_HEADER_DUMP__SHIFT 0x00000000
+#define CP_ME_MC_RADDR_HI__ME_MC_RADDR_HI_MASK 0x000000ffL
+#define CP_ME_MC_RADDR_HI__ME_MC_RADDR_HI__SHIFT 0x00000000
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_LO_MASK 0xfffffffcL
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_LO__SHIFT 0x00000002
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_SWAP_MASK 0x00000003L
+#define CP_ME_MC_RADDR_LO__ME_MC_RADDR_SWAP__SHIFT 0x00000000
+#define CP_ME_MC_WADDR_HI__ME_MC_WADDR_HI_MASK 0x000000ffL
+#define CP_ME_MC_WADDR_HI__ME_MC_WADDR_HI__SHIFT 0x00000000
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_LO_MASK 0xfffffffcL
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_LO__SHIFT 0x00000002
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_SWAP_MASK 0x00000003L
+#define CP_ME_MC_WADDR_LO__ME_MC_WADDR_SWAP__SHIFT 0x00000000
+#define CP_ME_MC_WDATA_HI__ME_MC_WDATA_HI_MASK 0xffffffffL
+#define CP_ME_MC_WDATA_HI__ME_MC_WDATA_HI__SHIFT 0x00000000
+#define CP_ME_MC_WDATA_LO__ME_MC_WDATA_LO_MASK 0xffffffffL
+#define CP_ME_MC_WDATA_LO__ME_MC_WDATA_LO__SHIFT 0x00000000
+#define CP_MEM_SLP_CNTL__CP_MEM_DS_EN_MASK 0x00000002L
+#define CP_MEM_SLP_CNTL__CP_MEM_DS_EN__SHIFT 0x00000001
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK 0x00000001L
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_EN__SHIFT 0x00000000
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_OFF_DELAY_MASK 0x00ff0000L
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_OFF_DELAY__SHIFT 0x00000010
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_ON_DELAY_MASK 0x0000ff00L
+#define CP_MEM_SLP_CNTL__CP_MEM_LS_ON_DELAY__SHIFT 0x00000008
+#define CP_MEM_SLP_CNTL__RESERVED1_MASK 0xff000000L
+#define CP_MEM_SLP_CNTL__RESERVED1__SHIFT 0x00000018
+#define CP_MEM_SLP_CNTL__RESERVED_MASK 0x000000fcL
+#define CP_MEM_SLP_CNTL__RESERVED__SHIFT 0x00000002
+#define CP_ME_PREEMPTION__ME_CNTXSW_PREEMPTION_MASK 0x00000001L
+#define CP_ME_PREEMPTION__ME_CNTXSW_PREEMPTION__SHIFT 0x00000000
+#define CP_MEQ_AVAIL__MEQ_CNT_MASK 0x000003ffL
+#define CP_MEQ_AVAIL__MEQ_CNT__SHIFT 0x00000000
+#define CP_MEQ_STAT__MEQ_RPTR_MASK 0x000003ffL
+#define CP_MEQ_STAT__MEQ_RPTR__SHIFT 0x00000000
+#define CP_MEQ_STAT__MEQ_WPTR_MASK 0x03ff0000L
+#define CP_MEQ_STAT__MEQ_WPTR__SHIFT 0x00000010
+#define CP_MEQ_THRESHOLDS__MEQ1_START_MASK 0x000000ffL
+#define CP_MEQ_THRESHOLDS__MEQ1_START__SHIFT 0x00000000
+#define CP_MEQ_THRESHOLDS__MEQ2_START_MASK 0x0000ff00L
+#define CP_MEQ_THRESHOLDS__MEQ2_START__SHIFT 0x00000008
+#define CP_ME_RAM_DATA__ME_RAM_DATA_MASK 0xffffffffL
+#define CP_ME_RAM_DATA__ME_RAM_DATA__SHIFT 0x00000000
+#define CP_ME_RAM_RADDR__ME_RAM_RADDR_MASK 0x00000fffL
+#define CP_ME_RAM_RADDR__ME_RAM_RADDR__SHIFT 0x00000000
+#define CP_ME_RAM_WADDR__ME_RAM_WADDR_MASK 0x00000fffL
+#define CP_ME_RAM_WADDR__ME_RAM_WADDR__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT0_HI__NUM_PRIM_NEEDED_CNT0_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT0_HI__NUM_PRIM_NEEDED_CNT0_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT0_LO__NUM_PRIM_NEEDED_CNT0_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT0_LO__NUM_PRIM_NEEDED_CNT0_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT1_HI__NUM_PRIM_NEEDED_CNT1_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT1_HI__NUM_PRIM_NEEDED_CNT1_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT1_LO__NUM_PRIM_NEEDED_CNT1_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT1_LO__NUM_PRIM_NEEDED_CNT1_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT2_HI__NUM_PRIM_NEEDED_CNT2_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT2_HI__NUM_PRIM_NEEDED_CNT2_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT2_LO__NUM_PRIM_NEEDED_CNT2_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT2_LO__NUM_PRIM_NEEDED_CNT2_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT3_HI__NUM_PRIM_NEEDED_CNT3_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT3_HI__NUM_PRIM_NEEDED_CNT3_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_NEEDED_COUNT3_LO__NUM_PRIM_NEEDED_CNT3_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_NEEDED_COUNT3_LO__NUM_PRIM_NEEDED_CNT3_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT0_HI__NUM_PRIM_WRITTEN_CNT0_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT0_HI__NUM_PRIM_WRITTEN_CNT0_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT0_LO__NUM_PRIM_WRITTEN_CNT0_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT0_LO__NUM_PRIM_WRITTEN_CNT0_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT1_HI__NUM_PRIM_WRITTEN_CNT1_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT1_HI__NUM_PRIM_WRITTEN_CNT1_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT1_LO__NUM_PRIM_WRITTEN_CNT1_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT1_LO__NUM_PRIM_WRITTEN_CNT1_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT2_HI__NUM_PRIM_WRITTEN_CNT2_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT2_HI__NUM_PRIM_WRITTEN_CNT2_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT2_LO__NUM_PRIM_WRITTEN_CNT2_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT2_LO__NUM_PRIM_WRITTEN_CNT2_LO__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT3_HI__NUM_PRIM_WRITTEN_CNT3_HI_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT3_HI__NUM_PRIM_WRITTEN_CNT3_HI__SHIFT 0x00000000
+#define CP_NUM_PRIM_WRITTEN_COUNT3_LO__NUM_PRIM_WRITTEN_CNT3_LO_MASK 0xffffffffL
+#define CP_NUM_PRIM_WRITTEN_COUNT3_LO__NUM_PRIM_WRITTEN_CNT3_LO__SHIFT 0x00000000
+#define CP_PA_CINVOC_COUNT_HI__CINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_PA_CINVOC_COUNT_HI__CINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_PA_CINVOC_COUNT_LO__CINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_PA_CINVOC_COUNT_LO__CINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_PA_CPRIM_COUNT_HI__CPRIM_COUNT_HI_MASK 0xffffffffL
+#define CP_PA_CPRIM_COUNT_HI__CPRIM_COUNT_HI__SHIFT 0x00000000
+#define CP_PA_CPRIM_COUNT_LO__CPRIM_COUNT_LO_MASK 0xffffffffL
+#define CP_PA_CPRIM_COUNT_LO__CPRIM_COUNT_LO__SHIFT 0x00000000
+#define CP_PERFMON_CNTL__PERFMON_ENABLE_MODE_MASK 0x00000300L
+#define CP_PERFMON_CNTL__PERFMON_ENABLE_MODE__SHIFT 0x00000008
+#define CP_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x00000400L
+#define CP_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0x0000000a
+#define CP_PERFMON_CNTL__PERFMON_STATE_MASK 0x0000000fL
+#define CP_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x00000000
+#define CP_PERFMON_CNTL__SPM_PERFMON_STATE_MASK 0x000000f0L
+#define CP_PERFMON_CNTL__SPM_PERFMON_STATE__SHIFT 0x00000004
+#define CP_PERFMON_CNTX_CNTL__PERFMON_ENABLE_MASK 0x80000000L
+#define CP_PERFMON_CNTX_CNTL__PERFMON_ENABLE__SHIFT 0x0000001f
+#define CP_PFP_HEADER_DUMP__PFP_HEADER_DUMP_MASK 0xffffffffL
+#define CP_PFP_HEADER_DUMP__PFP_HEADER_DUMP__SHIFT 0x00000000
+#define CP_PFP_IB_CONTROL__IB_EN_MASK 0x00000001L
+#define CP_PFP_IB_CONTROL__IB_EN__SHIFT 0x00000000
+#define CP_PFP_LOAD_CONTROL__CNTX_REG_EN_MASK 0x00000002L
+#define CP_PFP_LOAD_CONTROL__CNTX_REG_EN__SHIFT 0x00000001
+#define CP_PFP_LOAD_CONTROL__CONFIG_REG_EN_MASK 0x00000001L
+#define CP_PFP_LOAD_CONTROL__CONFIG_REG_EN__SHIFT 0x00000000
+#define CP_PFP_LOAD_CONTROL__SH_CS_REG_EN_MASK 0x01000000L
+#define CP_PFP_LOAD_CONTROL__SH_CS_REG_EN__SHIFT 0x00000018
+#define CP_PFP_LOAD_CONTROL__SH_GFX_REG_EN_MASK 0x00010000L
+#define CP_PFP_LOAD_CONTROL__SH_GFX_REG_EN__SHIFT 0x00000010
+#define CP_PFP_LOAD_CONTROL__UCONFIG_REG_EN_MASK 0x00008000L
+#define CP_PFP_LOAD_CONTROL__UCONFIG_REG_EN__SHIFT 0x0000000f
+#define CP_PFP_UCODE_ADDR__UCODE_ADDR_MASK 0x00000fffL
+#define CP_PFP_UCODE_ADDR__UCODE_ADDR__SHIFT 0x00000000
+#define CP_PFP_UCODE_DATA__UCODE_DATA_MASK 0xffffffffL
+#define CP_PFP_UCODE_DATA__UCODE_DATA__SHIFT 0x00000000
+#define CP_PIPE_STATS_ADDR_HI__PIPE_STATS_ADDR_HI_MASK 0xffffffffL
+#define CP_PIPE_STATS_ADDR_HI__PIPE_STATS_ADDR_HI__SHIFT 0x00000000
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_LO_MASK 0xfffffffcL
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_LO__SHIFT 0x00000002
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_SWAP_MASK 0x00000003L
+#define CP_PIPE_STATS_ADDR_LO__PIPE_STATS_ADDR_SWAP__SHIFT 0x00000000
+#define CP_PWR_CNTL__GFX_CLK_HALT_MASK 0x00000001L
+#define CP_PWR_CNTL__GFX_CLK_HALT__SHIFT 0x00000000
+#define CP_QUEUE_THRESHOLDS__ROQ_IB1_START_MASK 0x0000003fL
+#define CP_QUEUE_THRESHOLDS__ROQ_IB1_START__SHIFT 0x00000000
+#define CP_QUEUE_THRESHOLDS__ROQ_IB2_START_MASK 0x00003f00L
+#define CP_QUEUE_THRESHOLDS__ROQ_IB2_START__SHIFT 0x00000008
+#define CP_RB0_BASE_HI__RB_BASE_HI_MASK 0x000000ffL
+#define CP_RB0_BASE_HI__RB_BASE_HI__SHIFT 0x00000000
+#define CP_RB0_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB0_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB0_CNTL__BUF_SWAP_MASK 0x00030000L
+#define CP_RB0_CNTL__BUF_SWAP__SHIFT 0x00000010
+#define CP_RB0_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB0_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB0_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB0_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB0_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB0_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB0_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB0_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB0_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB0_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB0_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB0_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB0_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB0_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB0_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB0_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB0_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB0_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB0_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB0_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB0_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB0_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB0_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB0_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB0_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB0_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RB1_BASE_HI__RB_BASE_HI_MASK 0x000000ffL
+#define CP_RB1_BASE_HI__RB_BASE_HI__SHIFT 0x00000000
+#define CP_RB1_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB1_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB1_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB1_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB1_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB1_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB1_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB1_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB1_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB1_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB1_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB1_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB1_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB1_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB1_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB1_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB1_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB1_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB1_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB1_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB1_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB1_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB1_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB1_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB1_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB1_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB1_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RB2_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB2_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB2_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB2_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB2_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB2_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB2_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB2_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB2_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB2_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB2_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB2_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB2_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB2_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB2_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB2_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB2_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB2_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB2_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB2_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB2_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB2_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB2_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB2_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB2_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB2_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB2_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB2_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RB_BASE__RB_BASE_MASK 0xffffffffL
+#define CP_RB_BASE__RB_BASE__SHIFT 0x00000000
+#define CP_RB_CNTL__BUF_SWAP_MASK 0x00030000L
+#define CP_RB_CNTL__BUF_SWAP__SHIFT 0x00000010
+#define CP_RB_CNTL__CACHE_POLICY_MASK 0x03000000L
+#define CP_RB_CNTL__CACHE_POLICY__SHIFT 0x00000018
+#define CP_RB_CNTL__MIN_AVAILSZ_MASK 0x00300000L
+#define CP_RB_CNTL__MIN_AVAILSZ__SHIFT 0x00000014
+#define CP_RB_CNTL__MIN_IB_AVAILSZ_MASK 0x00c00000L
+#define CP_RB_CNTL__MIN_IB_AVAILSZ__SHIFT 0x00000016
+#define CP_RB_CNTL__RB_BLKSZ_MASK 0x00003f00L
+#define CP_RB_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define CP_RB_CNTL__RB_BUFSZ_MASK 0x0000003fL
+#define CP_RB_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define CP_RB_CNTL__RB_NO_UPDATE_MASK 0x08000000L
+#define CP_RB_CNTL__RB_NO_UPDATE__SHIFT 0x0000001b
+#define CP_RB_CNTL__RB_RPTR_WR_ENA_MASK 0x80000000L
+#define CP_RB_CNTL__RB_RPTR_WR_ENA__SHIFT 0x0000001f
+#define CP_RB_CNTL__RB_VOLATILE_MASK 0x04000000L
+#define CP_RB_CNTL__RB_VOLATILE__SHIFT 0x0000001a
+#define CP_RB_OFFSET__RB_OFFSET_MASK 0x000fffffL
+#define CP_RB_OFFSET__RB_OFFSET__SHIFT 0x00000000
+#define CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK 0x000000ffL
+#define CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI__SHIFT 0x00000000
+#define CP_RB_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xfffffffcL
+#define CP_RB_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000002
+#define CP_RB_RPTR_ADDR__RB_RPTR_SWAP_MASK 0x00000003L
+#define CP_RB_RPTR_ADDR__RB_RPTR_SWAP__SHIFT 0x00000000
+#define CP_RB_RPTR__RB_RPTR_MASK 0x000fffffL
+#define CP_RB_RPTR__RB_RPTR__SHIFT 0x00000000
+#define CP_RB_RPTR_WR__RB_RPTR_WR_MASK 0x000fffffL
+#define CP_RB_RPTR_WR__RB_RPTR_WR__SHIFT 0x00000000
+#define CP_RB_VMID__RB0_VMID_MASK 0x0000000fL
+#define CP_RB_VMID__RB0_VMID__SHIFT 0x00000000
+#define CP_RB_VMID__RB1_VMID_MASK 0x00000f00L
+#define CP_RB_VMID__RB1_VMID__SHIFT 0x00000008
+#define CP_RB_VMID__RB2_VMID_MASK 0x000f0000L
+#define CP_RB_VMID__RB2_VMID__SHIFT 0x00000010
+#define CP_RB_WPTR_DELAY__PRE_WRITE_LIMIT_MASK 0xf0000000L
+#define CP_RB_WPTR_DELAY__PRE_WRITE_LIMIT__SHIFT 0x0000001c
+#define CP_RB_WPTR_DELAY__PRE_WRITE_TIMER_MASK 0x0fffffffL
+#define CP_RB_WPTR_DELAY__PRE_WRITE_TIMER__SHIFT 0x00000000
+#define CP_RB_WPTR_POLL_ADDR_HI__OBSOLETE_MASK 0x000000ffL
+#define CP_RB_WPTR_POLL_ADDR_HI__OBSOLETE__SHIFT 0x00000000
+#define CP_RB_WPTR_POLL_ADDR_HI__RB_WPTR_POLL_ADDR_HI_MASK 0x000000ffL
+#define CP_RB_WPTR_POLL_ADDR_HI__RB_WPTR_POLL_ADDR_HI__SHIFT 0x00000000
+#define CP_RB_WPTR_POLL_ADDR_LO__OBSOLETE_MASK 0xfffffffcL
+#define CP_RB_WPTR_POLL_ADDR_LO__OBSOLETE__SHIFT 0x00000002
+#define CP_RB_WPTR_POLL_ADDR_LO__RB_WPTR_POLL_ADDR_LO_MASK 0xfffffffcL
+#define CP_RB_WPTR_POLL_ADDR_LO__RB_WPTR_POLL_ADDR_LO__SHIFT 0x00000002
+#define CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT_MASK 0xffff0000L
+#define CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT 0x00000010
+#define CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY_MASK 0x0000ffffL
+#define CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT 0x00000000
+#define CP_RB_WPTR__RB_WPTR_MASK 0x000fffffL
+#define CP_RB_WPTR__RB_WPTR__SHIFT 0x00000000
+#define CP_RING0_PRIORITY__PRIORITY_MASK 0x00000003L
+#define CP_RING0_PRIORITY__PRIORITY__SHIFT 0x00000000
+#define CP_RING1_PRIORITY__PRIORITY_MASK 0x00000003L
+#define CP_RING1_PRIORITY__PRIORITY__SHIFT 0x00000000
+#define CP_RING2_PRIORITY__PRIORITY_MASK 0x00000003L
+#define CP_RING2_PRIORITY__PRIORITY__SHIFT 0x00000000
+#define CP_RINGID__RINGID_MASK 0x00000003L
+#define CP_RINGID__RINGID__SHIFT 0x00000000
+#define CP_RING_PRIORITY_CNTS__PRIORITY1_CNT_MASK 0x000000ffL
+#define CP_RING_PRIORITY_CNTS__PRIORITY1_CNT__SHIFT 0x00000000
+#define CP_RING_PRIORITY_CNTS__PRIORITY2A_CNT_MASK 0x0000ff00L
+#define CP_RING_PRIORITY_CNTS__PRIORITY2A_CNT__SHIFT 0x00000008
+#define CP_RING_PRIORITY_CNTS__PRIORITY2B_CNT_MASK 0x00ff0000L
+#define CP_RING_PRIORITY_CNTS__PRIORITY2B_CNT__SHIFT 0x00000010
+#define CP_RING_PRIORITY_CNTS__PRIORITY3_CNT_MASK 0xff000000L
+#define CP_RING_PRIORITY_CNTS__PRIORITY3_CNT__SHIFT 0x00000018
+#define CP_ROQ1_THRESHOLDS__R0_IB1_START_MASK 0x00ff0000L
+#define CP_ROQ1_THRESHOLDS__R0_IB1_START__SHIFT 0x00000010
+#define CP_ROQ1_THRESHOLDS__R1_IB1_START_MASK 0xff000000L
+#define CP_ROQ1_THRESHOLDS__R1_IB1_START__SHIFT 0x00000018
+#define CP_ROQ1_THRESHOLDS__RB1_START_MASK 0x000000ffL
+#define CP_ROQ1_THRESHOLDS__RB1_START__SHIFT 0x00000000
+#define CP_ROQ1_THRESHOLDS__RB2_START_MASK 0x0000ff00L
+#define CP_ROQ1_THRESHOLDS__RB2_START__SHIFT 0x00000008
+#define CP_ROQ2_AVAIL__ROQ_CNT_IB2_MASK 0x000007ffL
+#define CP_ROQ2_AVAIL__ROQ_CNT_IB2__SHIFT 0x00000000
+#define CP_ROQ2_THRESHOLDS__R0_IB2_START_MASK 0x0000ff00L
+#define CP_ROQ2_THRESHOLDS__R0_IB2_START__SHIFT 0x00000008
+#define CP_ROQ2_THRESHOLDS__R1_IB2_START_MASK 0x00ff0000L
+#define CP_ROQ2_THRESHOLDS__R1_IB2_START__SHIFT 0x00000010
+#define CP_ROQ2_THRESHOLDS__R2_IB1_START_MASK 0x000000ffL
+#define CP_ROQ2_THRESHOLDS__R2_IB1_START__SHIFT 0x00000000
+#define CP_ROQ2_THRESHOLDS__R2_IB2_START_MASK 0xff000000L
+#define CP_ROQ2_THRESHOLDS__R2_IB2_START__SHIFT 0x00000018
+#define CP_ROQ_AVAIL__ROQ_CNT_IB1_MASK 0x07ff0000L
+#define CP_ROQ_AVAIL__ROQ_CNT_IB1__SHIFT 0x00000010
+#define CP_ROQ_AVAIL__ROQ_CNT_RING_MASK 0x000007ffL
+#define CP_ROQ_AVAIL__ROQ_CNT_RING__SHIFT 0x00000000
+#define CP_ROQ_IB1_STAT__ROQ_RPTR_INDIRECT1_MASK 0x000003ffL
+#define CP_ROQ_IB1_STAT__ROQ_RPTR_INDIRECT1__SHIFT 0x00000000
+#define CP_ROQ_IB1_STAT__ROQ_WPTR_INDIRECT1_MASK 0x03ff0000L
+#define CP_ROQ_IB1_STAT__ROQ_WPTR_INDIRECT1__SHIFT 0x00000010
+#define CP_ROQ_IB2_STAT__ROQ_RPTR_INDIRECT2_MASK 0x000003ffL
+#define CP_ROQ_IB2_STAT__ROQ_RPTR_INDIRECT2__SHIFT 0x00000000
+#define CP_ROQ_IB2_STAT__ROQ_WPTR_INDIRECT2_MASK 0x03ff0000L
+#define CP_ROQ_IB2_STAT__ROQ_WPTR_INDIRECT2__SHIFT 0x00000010
+#define CP_ROQ_RB_STAT__ROQ_RPTR_PRIMARY_MASK 0x000003ffL
+#define CP_ROQ_RB_STAT__ROQ_RPTR_PRIMARY__SHIFT 0x00000000
+#define CP_ROQ_RB_STAT__ROQ_WPTR_PRIMARY_MASK 0x03ff0000L
+#define CP_ROQ_RB_STAT__ROQ_WPTR_PRIMARY__SHIFT 0x00000010
+#define CP_SC_PSINVOC_COUNT0_HI__PSINVOC_COUNT0_HI_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT0_HI__PSINVOC_COUNT0_HI__SHIFT 0x00000000
+#define CP_SC_PSINVOC_COUNT0_LO__PSINVOC_COUNT0_LO_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT0_LO__PSINVOC_COUNT0_LO__SHIFT 0x00000000
+#define CP_SC_PSINVOC_COUNT1_HI__OBSOLETE_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT1_HI__OBSOLETE__SHIFT 0x00000000
+#define CP_SC_PSINVOC_COUNT1_LO__OBSOLETE_MASK 0xffffffffL
+#define CP_SC_PSINVOC_COUNT1_LO__OBSOLETE__SHIFT 0x00000000
+#define CP_SCRATCH_DATA__SCRATCH_DATA_MASK 0xffffffffL
+#define CP_SCRATCH_DATA__SCRATCH_DATA__SHIFT 0x00000000
+#define CP_SCRATCH_INDEX__SCRATCH_INDEX_MASK 0x000000ffL
+#define CP_SCRATCH_INDEX__SCRATCH_INDEX__SHIFT 0x00000000
+#define CP_SEM_WAIT_TIMER__SEM_WAIT_TIMER_MASK 0xffffffffL
+#define CP_SEM_WAIT_TIMER__SEM_WAIT_TIMER__SHIFT 0x00000000
+#define CP_SIG_SEM_ADDR_HI__SEM_ADDR_HI_MASK 0x000000ffL
+#define CP_SIG_SEM_ADDR_HI__SEM_ADDR_HI__SHIFT 0x00000000
+#define CP_SIG_SEM_ADDR_HI__SEM_CLIENT_CODE_MASK 0x03000000L
+#define CP_SIG_SEM_ADDR_HI__SEM_CLIENT_CODE__SHIFT 0x00000018
+#define CP_SIG_SEM_ADDR_HI__SEM_SELECT_MASK 0xe0000000L
+#define CP_SIG_SEM_ADDR_HI__SEM_SELECT__SHIFT 0x0000001d
+#define CP_SIG_SEM_ADDR_HI__SEM_SIGNAL_TYPE_MASK 0x00100000L
+#define CP_SIG_SEM_ADDR_HI__SEM_SIGNAL_TYPE__SHIFT 0x00000014
+#define CP_SIG_SEM_ADDR_HI__SEM_USE_MAILBOX_MASK 0x00010000L
+#define CP_SIG_SEM_ADDR_HI__SEM_USE_MAILBOX__SHIFT 0x00000010
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_LO_MASK 0xfffffff8L
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_LO__SHIFT 0x00000003
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_SWAP_MASK 0x00000003L
+#define CP_SIG_SEM_ADDR_LO__SEM_ADDR_SWAP__SHIFT 0x00000000
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_CE_BUFFER_FLAG_MASK 0x00000400L
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_CE_BUFFER_FLAG__SHIFT 0x0000000a
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_DE_BUFFER_FLAG_MASK 0x00000800L
+#define CP_STALLED_STAT1__ME_HAS_ACTIVE_DE_BUFFER_FLAG__SHIFT 0x0000000b
+#define CP_STALLED_STAT1__ME_STALLED_ON_ATOMIC_RTN_DATA_MASK 0x00002000L
+#define CP_STALLED_STAT1__ME_STALLED_ON_ATOMIC_RTN_DATA__SHIFT 0x0000000d
+#define CP_STALLED_STAT1__ME_STALLED_ON_TC_WR_CONFIRM_MASK 0x00001000L
+#define CP_STALLED_STAT1__ME_STALLED_ON_TC_WR_CONFIRM__SHIFT 0x0000000c
+#define CP_STALLED_STAT1__ME_WAITING_ON_MC_READ_DATA_MASK 0x00004000L
+#define CP_STALLED_STAT1__ME_WAITING_ON_MC_READ_DATA__SHIFT 0x0000000e
+#define CP_STALLED_STAT1__ME_WAITING_ON_REG_READ_DATA_MASK 0x00008000L
+#define CP_STALLED_STAT1__ME_WAITING_ON_REG_READ_DATA__SHIFT 0x0000000f
+#define CP_STALLED_STAT1__MIU_WAITING_ON_RDREQ_FREE_MASK 0x00010000L
+#define CP_STALLED_STAT1__MIU_WAITING_ON_RDREQ_FREE__SHIFT 0x00000010
+#define CP_STALLED_STAT1__MIU_WAITING_ON_WRREQ_FREE_MASK 0x00020000L
+#define CP_STALLED_STAT1__MIU_WAITING_ON_WRREQ_FREE__SHIFT 0x00000011
+#define CP_STALLED_STAT1__RBIU_TO_DMA_NOT_RDY_TO_RCV_MASK 0x00000001L
+#define CP_STALLED_STAT1__RBIU_TO_DMA_NOT_RDY_TO_RCV__SHIFT 0x00000000
+#define CP_STALLED_STAT1__RBIU_TO_MEMWR_NOT_RDY_TO_RCV_MASK 0x00000010L
+#define CP_STALLED_STAT1__RBIU_TO_MEMWR_NOT_RDY_TO_RCV__SHIFT 0x00000004
+#define CP_STALLED_STAT1__RBIU_TO_SEM_NOT_RDY_TO_RCV_MASK 0x00000004L
+#define CP_STALLED_STAT1__RBIU_TO_SEM_NOT_RDY_TO_RCV__SHIFT 0x00000002
+#define CP_STALLED_STAT1__RCIU_HALTED_BY_REG_VIOLATION_MASK 0x10000000L
+#define CP_STALLED_STAT1__RCIU_HALTED_BY_REG_VIOLATION__SHIFT 0x0000001c
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_APPEND_READ_MASK 0x10000000L
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_APPEND_READ__SHIFT 0x0000001c
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_DMA_READ_MASK 0x08000000L
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_DMA_READ__SHIFT 0x0000001b
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_ME_READ_MASK 0x04000000L
+#define CP_STALLED_STAT1__RCIU_STALLED_ON_ME_READ__SHIFT 0x0000001a
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GDS_FREE_MASK 0x00800000L
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GDS_FREE__SHIFT 0x00000017
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GRBM_FREE_MASK 0x01000000L
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_GRBM_FREE__SHIFT 0x00000018
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_VGT_FREE_MASK 0x02000000L
+#define CP_STALLED_STAT1__RCIU_WAITING_ON_VGT_FREE__SHIFT 0x00000019
+#define CP_STALLED_STAT2__APPEND_ACTIVE_PARTITION_MASK 0x10000000L
+#define CP_STALLED_STAT2__APPEND_ACTIVE_PARTITION__SHIFT 0x0000001c
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_CS_DONE_MASK 0x02000000L
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_CS_DONE__SHIFT 0x00000019
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_PS_DONE_MASK 0x04000000L
+#define CP_STALLED_STAT2__APPEND_RDY_WAIT_ON_PS_DONE__SHIFT 0x0000001a
+#define CP_STALLED_STAT2__APPEND_WAITING_TO_SEND_MEMWRITE_MASK 0x20000000L
+#define CP_STALLED_STAT2__APPEND_WAITING_TO_SEND_MEMWRITE__SHIFT 0x0000001d
+#define CP_STALLED_STAT2__APPEND_WAIT_ON_WR_CONFIRM_MASK 0x08000000L
+#define CP_STALLED_STAT2__APPEND_WAIT_ON_WR_CONFIRM__SHIFT 0x0000001b
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_SC_EOP_DONE_MASK 0x00200000L
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_SC_EOP_DONE__SHIFT 0x00000015
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_WR_CONFIRM_MASK 0x00400000L
+#define CP_STALLED_STAT2__EOPD_FIFO_NEEDS_WR_CONFIRM__SHIFT 0x00000016
+#define CP_STALLED_STAT2__GFX_CNTX_NOT_AVAIL_TO_ME_MASK 0x00000800L
+#define CP_STALLED_STAT2__GFX_CNTX_NOT_AVAIL_TO_ME__SHIFT 0x0000000b
+#define CP_STALLED_STAT2__MEQ_TO_ME_NOT_RDY_TO_RCV_MASK 0x00010000L
+#define CP_STALLED_STAT2__MEQ_TO_ME_NOT_RDY_TO_RCV__SHIFT 0x00000010
+#define CP_STALLED_STAT2__ME_RCIU_NOT_RDY_TO_RCV_MASK 0x00001000L
+#define CP_STALLED_STAT2__ME_RCIU_NOT_RDY_TO_RCV__SHIFT 0x0000000c
+#define CP_STALLED_STAT2__ME_TO_CONST_NOT_RDY_TO_RCV_MASK 0x00002000L
+#define CP_STALLED_STAT2__ME_TO_CONST_NOT_RDY_TO_RCV__SHIFT 0x0000000d
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_PFP_MASK 0x00004000L
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_PFP__SHIFT 0x0000000e
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_STQ_MASK 0x00040000L
+#define CP_STALLED_STAT2__ME_WAITING_DATA_FROM_STQ__SHIFT 0x00000012
+#define CP_STALLED_STAT2__ME_WAITING_ON_PARTIAL_FLUSH_MASK 0x00008000L
+#define CP_STALLED_STAT2__ME_WAITING_ON_PARTIAL_FLUSH__SHIFT 0x0000000f
+#define CP_STALLED_STAT2__ME_WAIT_ON_AVAIL_BUFFER_MASK 0x00000400L
+#define CP_STALLED_STAT2__ME_WAIT_ON_AVAIL_BUFFER__SHIFT 0x0000000a
+#define CP_STALLED_STAT2__ME_WAIT_ON_CE_COUNTER_MASK 0x00000200L
+#define CP_STALLED_STAT2__ME_WAIT_ON_CE_COUNTER__SHIFT 0x00000009
+#define CP_STALLED_STAT2__PFP_MIU_READ_PENDING_MASK 0x00000040L
+#define CP_STALLED_STAT2__PFP_MIU_READ_PENDING__SHIFT 0x00000006
+#define CP_STALLED_STAT2__PFP_RCIU_READ_PENDING_MASK 0x00000020L
+#define CP_STALLED_STAT2__PFP_RCIU_READ_PENDING__SHIFT 0x00000005
+#define CP_STALLED_STAT2__PFP_STALLED_ON_ATOMIC_RTN_DATA_MASK 0x00100000L
+#define CP_STALLED_STAT2__PFP_STALLED_ON_ATOMIC_RTN_DATA__SHIFT 0x00000014
+#define CP_STALLED_STAT2__PFP_STALLED_ON_TC_WR_CONFIRM_MASK 0x00080000L
+#define CP_STALLED_STAT2__PFP_STALLED_ON_TC_WR_CONFIRM__SHIFT 0x00000013
+#define CP_STALLED_STAT2__PFP_TO_CSF_NOT_RDY_TO_RCV_MASK 0x00000001L
+#define CP_STALLED_STAT2__PFP_TO_CSF_NOT_RDY_TO_RCV__SHIFT 0x00000000
+#define CP_STALLED_STAT2__PFP_TO_MEQ_NOT_RDY_TO_RCV_MASK 0x00000002L
+#define CP_STALLED_STAT2__PFP_TO_MEQ_NOT_RDY_TO_RCV__SHIFT 0x00000001
+#define CP_STALLED_STAT2__PFP_TO_MIU_WRITE_NOT_RDY_TO_RCV_MASK 0x00000080L
+#define CP_STALLED_STAT2__PFP_TO_MIU_WRITE_NOT_RDY_TO_RCV__SHIFT 0x00000007
+#define CP_STALLED_STAT2__PFP_TO_RCIU_NOT_RDY_TO_RCV_MASK 0x00000004L
+#define CP_STALLED_STAT2__PFP_TO_RCIU_NOT_RDY_TO_RCV__SHIFT 0x00000002
+#define CP_STALLED_STAT2__PFP_TO_VGT_WRITES_PENDING_MASK 0x00000010L
+#define CP_STALLED_STAT2__PFP_TO_VGT_WRITES_PENDING__SHIFT 0x00000004
+#define CP_STALLED_STAT2__PFP_WAITING_ON_BUFFER_DATA_MASK 0x00000100L
+#define CP_STALLED_STAT2__PFP_WAITING_ON_BUFFER_DATA__SHIFT 0x00000008
+#define CP_STALLED_STAT2__PIPE_STATS_WR_DATA_PENDING_MASK 0x01000000L
+#define CP_STALLED_STAT2__PIPE_STATS_WR_DATA_PENDING__SHIFT 0x00000018
+#define CP_STALLED_STAT2__STQ_TO_ME_NOT_RDY_TO_RCV_MASK 0x00020000L
+#define CP_STALLED_STAT2__STQ_TO_ME_NOT_RDY_TO_RCV__SHIFT 0x00000011
+#define CP_STALLED_STAT2__STRMO_WR_OF_PRIM_DATA_PENDING_MASK 0x00800000L
+#define CP_STALLED_STAT2__STRMO_WR_OF_PRIM_DATA_PENDING__SHIFT 0x00000017
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_ALL_CLEAN_MASK 0x80000000L
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_ALL_CLEAN__SHIFT 0x0000001f
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_IDLE_CNTXS_MASK 0x40000000L
+#define CP_STALLED_STAT2__SURF_SYNC_NEEDS_IDLE_CNTXS__SHIFT 0x0000001e
+#define CP_STALLED_STAT3__CE_TO_CSF_NOT_RDY_TO_RCV_MASK 0x00000001L
+#define CP_STALLED_STAT3__CE_TO_CSF_NOT_RDY_TO_RCV__SHIFT 0x00000000
+#define CP_STALLED_STAT3__CE_TO_INC_FIFO_NOT_RDY_TO_RCV_MASK 0x00000040L
+#define CP_STALLED_STAT3__CE_TO_INC_FIFO_NOT_RDY_TO_RCV__SHIFT 0x00000006
+#define CP_STALLED_STAT3__CE_TO_MIU_WRITE_NOT_RDY_TO_RCV_MASK 0x00000100L
+#define CP_STALLED_STAT3__CE_TO_MIU_WRITE_NOT_RDY_TO_RCV__SHIFT 0x00000008
+#define CP_STALLED_STAT3__CE_TO_RAM_DUMP_NOT_RDY_MASK 0x00000010L
+#define CP_STALLED_STAT3__CE_TO_RAM_DUMP_NOT_RDY__SHIFT 0x00000004
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_FETCHER_NOT_RDY_TO_RCV_MASK 0x00000002L
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_FETCHER_NOT_RDY_TO_RCV__SHIFT 0x00000001
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_NOT_RDY_MASK 0x00000008L
+#define CP_STALLED_STAT3__CE_TO_RAM_INIT_NOT_RDY__SHIFT 0x00000003
+#define CP_STALLED_STAT3__CE_TO_RAM_WRITE_NOT_RDY_MASK 0x00000020L
+#define CP_STALLED_STAT3__CE_TO_RAM_WRITE_NOT_RDY__SHIFT 0x00000005
+#define CP_STALLED_STAT3__CE_TO_WR_FIFO_NOT_RDY_TO_RCV_MASK 0x00000080L
+#define CP_STALLED_STAT3__CE_TO_WR_FIFO_NOT_RDY_TO_RCV__SHIFT 0x00000007
+#define CP_STALLED_STAT3__CE_WAITING_ON_BUFFER_DATA_MASK 0x00000400L
+#define CP_STALLED_STAT3__CE_WAITING_ON_BUFFER_DATA__SHIFT 0x0000000a
+#define CP_STALLED_STAT3__CE_WAITING_ON_CE_BUFFER_FLAG_MASK 0x00000800L
+#define CP_STALLED_STAT3__CE_WAITING_ON_CE_BUFFER_FLAG__SHIFT 0x0000000b
+#define CP_STALLED_STAT3__CE_WAITING_ON_DATA_FROM_RAM_INIT_FETCHER_MASK 0x00000004L
+#define CP_STALLED_STAT3__CE_WAITING_ON_DATA_FROM_RAM_INIT_FETCHER__SHIFT 0x00000002
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_MASK 0x00001000L
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER__SHIFT 0x0000000c
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_UNDERFLOW_MASK 0x00002000L
+#define CP_STALLED_STAT3__CE_WAITING_ON_DE_COUNTER_UNDERFLOW__SHIFT 0x0000000d
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_FREE_MASK 0x00004000L
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_FREE__SHIFT 0x0000000e
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_TAGS_MASK 0x00008000L
+#define CP_STALLED_STAT3__TCIU_WAITING_ON_TAGS__SHIFT 0x0000000f
+#define CP_STAT__CE_BUSY_MASK 0x04000000L
+#define CP_STAT__CE_BUSY__SHIFT 0x0000001a
+#define CP_STAT__CP_BUSY_MASK 0x80000000L
+#define CP_STAT__CP_BUSY__SHIFT 0x0000001f
+#define CP_STAT__CPC_CPG_BUSY_MASK 0x02000000L
+#define CP_STAT__CPC_CPG_BUSY__SHIFT 0x00000019
+#define CP_STAT__DC_BUSY_MASK 0x00002000L
+#define CP_STAT__DC_BUSY__SHIFT 0x0000000d
+#define CP_STAT__DMA_BUSY_MASK 0x00400000L
+#define CP_STAT__DMA_BUSY__SHIFT 0x00000016
+#define CP_STAT__INTERRUPT_BUSY_MASK 0x00100000L
+#define CP_STAT__INTERRUPT_BUSY__SHIFT 0x00000014
+#define CP_STAT__ME_BUSY_MASK 0x00020000L
+#define CP_STAT__ME_BUSY__SHIFT 0x00000011
+#define CP_STAT__MEQ_BUSY_MASK 0x00010000L
+#define CP_STAT__MEQ_BUSY__SHIFT 0x00000010
+#define CP_STAT__MIU_RDREQ_BUSY_MASK 0x00000080L
+#define CP_STAT__MIU_RDREQ_BUSY__SHIFT 0x00000007
+#define CP_STAT__MIU_WRREQ_BUSY_MASK 0x00000100L
+#define CP_STAT__MIU_WRREQ_BUSY__SHIFT 0x00000008
+#define CP_STAT__PFP_BUSY_MASK 0x00008000L
+#define CP_STAT__PFP_BUSY__SHIFT 0x0000000f
+#define CP_STAT__QUERY_BUSY_MASK 0x00040000L
+#define CP_STAT__QUERY_BUSY__SHIFT 0x00000012
+#define CP_STAT__RCIU_BUSY_MASK 0x00800000L
+#define CP_STAT__RCIU_BUSY__SHIFT 0x00000017
+#define CP_STAT__ROQ_CE_INDIRECT1_BUSY_MASK 0x20000000L
+#define CP_STAT__ROQ_CE_INDIRECT1_BUSY__SHIFT 0x0000001d
+#define CP_STAT__ROQ_CE_INDIRECT2_BUSY_MASK 0x40000000L
+#define CP_STAT__ROQ_CE_INDIRECT2_BUSY__SHIFT 0x0000001e
+#define CP_STAT__ROQ_CE_RING_BUSY_MASK 0x10000000L
+#define CP_STAT__ROQ_CE_RING_BUSY__SHIFT 0x0000001c
+#define CP_STAT__ROQ_INDIRECT1_BUSY_MASK 0x00000400L
+#define CP_STAT__ROQ_INDIRECT1_BUSY__SHIFT 0x0000000a
+#define CP_STAT__ROQ_INDIRECT2_BUSY_MASK 0x00000800L
+#define CP_STAT__ROQ_INDIRECT2_BUSY__SHIFT 0x0000000b
+#define CP_STAT__ROQ_RING_BUSY_MASK 0x00000200L
+#define CP_STAT__ROQ_RING_BUSY__SHIFT 0x00000009
+#define CP_STAT__ROQ_STATE_BUSY_MASK 0x00001000L
+#define CP_STAT__ROQ_STATE_BUSY__SHIFT 0x0000000c
+#define CP_STAT__SCRATCH_RAM_BUSY_MASK 0x01000000L
+#define CP_STAT__SCRATCH_RAM_BUSY__SHIFT 0x00000018
+#define CP_STAT__SEMAPHORE_BUSY_MASK 0x00080000L
+#define CP_STAT__SEMAPHORE_BUSY__SHIFT 0x00000013
+#define CP_STAT__SURFACE_SYNC_BUSY_MASK 0x00200000L
+#define CP_STAT__SURFACE_SYNC_BUSY__SHIFT 0x00000015
+#define CP_STAT__TCIU_BUSY_MASK 0x08000000L
+#define CP_STAT__TCIU_BUSY__SHIFT 0x0000001b
+#define CP_ST_BASE_HI__ST_BASE_HI_MASK 0x000000ffL
+#define CP_ST_BASE_HI__ST_BASE_HI__SHIFT 0x00000000
+#define CP_ST_BASE_LO__ST_BASE_LO_MASK 0xfffffffcL
+#define CP_ST_BASE_LO__ST_BASE_LO__SHIFT 0x00000002
+#define CP_ST_BUFSZ__ST_BUFSZ_MASK 0x000fffffL
+#define CP_ST_BUFSZ__ST_BUFSZ__SHIFT 0x00000000
+#define CP_STQ_AVAIL__STQ_CNT_MASK 0x000001ffL
+#define CP_STQ_AVAIL__STQ_CNT__SHIFT 0x00000000
+#define CP_STQ_STAT__STQ_RPTR_MASK 0x000003ffL
+#define CP_STQ_STAT__STQ_RPTR__SHIFT 0x00000000
+#define CP_STQ_THRESHOLDS__STQ0_START_MASK 0x000000ffL
+#define CP_STQ_THRESHOLDS__STQ0_START__SHIFT 0x00000000
+#define CP_STQ_THRESHOLDS__STQ1_START_MASK 0x0000ff00L
+#define CP_STQ_THRESHOLDS__STQ1_START__SHIFT 0x00000008
+#define CP_STQ_THRESHOLDS__STQ2_START_MASK 0x00ff0000L
+#define CP_STQ_THRESHOLDS__STQ2_START__SHIFT 0x00000010
+#define CP_STREAM_OUT_ADDR_HI__STREAM_OUT_ADDR_HI_MASK 0xffffffffL
+#define CP_STREAM_OUT_ADDR_HI__STREAM_OUT_ADDR_HI__SHIFT 0x00000000
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_LO_MASK 0xfffffffcL
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_LO__SHIFT 0x00000002
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_SWAP_MASK 0x00000003L
+#define CP_STREAM_OUT_ADDR_LO__STREAM_OUT_ADDR_SWAP__SHIFT 0x00000000
+#define CP_STRMOUT_CNTL__OFFSET_UPDATE_DONE_MASK 0x00000001L
+#define CP_STRMOUT_CNTL__OFFSET_UPDATE_DONE__SHIFT 0x00000000
+#define CP_VGT_CSINVOC_COUNT_HI__CSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_CSINVOC_COUNT_HI__CSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_CSINVOC_COUNT_LO__CSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_CSINVOC_COUNT_LO__CSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_DSINVOC_COUNT_HI__DSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_DSINVOC_COUNT_HI__DSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_DSINVOC_COUNT_LO__DSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_DSINVOC_COUNT_LO__DSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_GSINVOC_COUNT_HI__GSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_GSINVOC_COUNT_HI__GSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_GSINVOC_COUNT_LO__GSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_GSINVOC_COUNT_LO__GSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_GSPRIM_COUNT_HI__GSPRIM_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_GSPRIM_COUNT_HI__GSPRIM_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_GSPRIM_COUNT_LO__GSPRIM_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_GSPRIM_COUNT_LO__GSPRIM_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_HSINVOC_COUNT_HI__HSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_HSINVOC_COUNT_HI__HSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_HSINVOC_COUNT_LO__HSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_HSINVOC_COUNT_LO__HSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_IAPRIM_COUNT_HI__IAPRIM_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_IAPRIM_COUNT_HI__IAPRIM_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_IAPRIM_COUNT_LO__IAPRIM_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_IAPRIM_COUNT_LO__IAPRIM_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_IAVERT_COUNT_HI__IAVERT_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_IAVERT_COUNT_HI__IAVERT_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_IAVERT_COUNT_LO__IAVERT_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_IAVERT_COUNT_LO__IAVERT_COUNT_LO__SHIFT 0x00000000
+#define CP_VGT_VSINVOC_COUNT_HI__VSINVOC_COUNT_HI_MASK 0xffffffffL
+#define CP_VGT_VSINVOC_COUNT_HI__VSINVOC_COUNT_HI__SHIFT 0x00000000
+#define CP_VGT_VSINVOC_COUNT_LO__VSINVOC_COUNT_LO_MASK 0xffffffffL
+#define CP_VGT_VSINVOC_COUNT_LO__VSINVOC_COUNT_LO__SHIFT 0x00000000
+#define CP_VMID_PREEMPT__PREEMPT_REQUEST_MASK 0x0000ffffL
+#define CP_VMID_PREEMPT__PREEMPT_REQUEST__SHIFT 0x00000000
+#define CP_VMID_PREEMPT__PREEMPT_STATUS_MASK 0xffff0000L
+#define CP_VMID_PREEMPT__PREEMPT_STATUS__SHIFT 0x00000010
+#define CP_VMID_RESET__RESET_REQUEST_MASK 0x0000ffffL
+#define CP_VMID_RESET__RESET_REQUEST__SHIFT 0x00000000
+#define CP_VMID_RESET__RESET_STATUS_MASK 0xffff0000L
+#define CP_VMID_RESET__RESET_STATUS__SHIFT 0x00000010
+#define CP_VMID__VMID_MASK 0x0000000fL
+#define CP_VMID__VMID__SHIFT 0x00000000
+#define CP_WAIT_REG_MEM_TIMEOUT__WAIT_REG_MEM_TIMEOUT_MASK 0xffffffffL
+#define CP_WAIT_REG_MEM_TIMEOUT__WAIT_REG_MEM_TIMEOUT__SHIFT 0x00000000
+#define CP_WAIT_SEM_ADDR_HI__SEM_ADDR_HI_MASK 0x000000ffL
+#define CP_WAIT_SEM_ADDR_HI__SEM_ADDR_HI__SHIFT 0x00000000
+#define CP_WAIT_SEM_ADDR_HI__SEM_CLIENT_CODE_MASK 0x03000000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_CLIENT_CODE__SHIFT 0x00000018
+#define CP_WAIT_SEM_ADDR_HI__SEM_SELECT_MASK 0xe0000000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_SELECT__SHIFT 0x0000001d
+#define CP_WAIT_SEM_ADDR_HI__SEM_SIGNAL_TYPE_MASK 0x00100000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_SIGNAL_TYPE__SHIFT 0x00000014
+#define CP_WAIT_SEM_ADDR_HI__SEM_USE_MAILBOX_MASK 0x00010000L
+#define CP_WAIT_SEM_ADDR_HI__SEM_USE_MAILBOX__SHIFT 0x00000010
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_LO_MASK 0xfffffff8L
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_LO__SHIFT 0x00000003
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_SWAP_MASK 0x00000003L
+#define CP_WAIT_SEM_ADDR_LO__SEM_ADDR_SWAP__SHIFT 0x00000000
+#define CS_COPY_STATE__SRC_STATE_ID_MASK 0x00000007L
+#define CS_COPY_STATE__SRC_STATE_ID__SHIFT 0x00000000
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_ENABLE_MASK 0x00000001L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_ENABLE__SHIFT 0x00000000
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET0_MASK 0x00000300L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET0__SHIFT 0x00000008
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET1_MASK 0x00000c00L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET1__SHIFT 0x0000000a
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET2_MASK 0x00003000L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET2__SHIFT 0x0000000c
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET3_MASK 0x0000c000L
+#define DB_ALPHA_TO_MASK__ALPHA_TO_MASK_OFFSET3__SHIFT 0x0000000e
+#define DB_ALPHA_TO_MASK__OFFSET_ROUND_MASK 0x00010000L
+#define DB_ALPHA_TO_MASK__OFFSET_ROUND__SHIFT 0x00000010
+#define DB_CGTT_CLK_CTRL_0__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define DB_CGTT_CLK_CTRL_0__OFF_HYSTERESIS__SHIFT 0x00000004
+#define DB_CGTT_CLK_CTRL_0__ON_DELAY_MASK 0x0000000fL
+#define DB_CGTT_CLK_CTRL_0__ON_DELAY__SHIFT 0x00000000
+#define DB_CGTT_CLK_CTRL_0__RESERVED_MASK 0x00fff000L
+#define DB_CGTT_CLK_CTRL_0__RESERVED__SHIFT 0x0000000c
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE0_MASK 0x80000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE1_MASK 0x40000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE2_MASK 0x20000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE3_MASK 0x10000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE4_MASK 0x08000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE5_MASK 0x04000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE6_MASK 0x02000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE7_MASK 0x01000000L
+#define DB_CGTT_CLK_CTRL_0__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define DB_COUNT_CONTROL__DBFAIL_ENABLE_MASK 0x00f00000L
+#define DB_COUNT_CONTROL__DBFAIL_ENABLE__SHIFT 0x00000014
+#define DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS_MASK 0x00000002L
+#define DB_COUNT_CONTROL__PERFECT_ZPASS_COUNTS__SHIFT 0x00000001
+#define DB_COUNT_CONTROL__SAMPLE_RATE_MASK 0x00000070L
+#define DB_COUNT_CONTROL__SAMPLE_RATE__SHIFT 0x00000004
+#define DB_COUNT_CONTROL__SFAIL_ENABLE_MASK 0x000f0000L
+#define DB_COUNT_CONTROL__SFAIL_ENABLE__SHIFT 0x00000010
+#define DB_COUNT_CONTROL__SLICE_EVEN_ENABLE_MASK 0x0f000000L
+#define DB_COUNT_CONTROL__SLICE_EVEN_ENABLE__SHIFT 0x00000018
+#define DB_COUNT_CONTROL__SLICE_ODD_ENABLE_MASK 0xf0000000L
+#define DB_COUNT_CONTROL__SLICE_ODD_ENABLE__SHIFT 0x0000001c
+#define DB_COUNT_CONTROL__ZFAIL_ENABLE_MASK 0x0000f000L
+#define DB_COUNT_CONTROL__ZFAIL_ENABLE__SHIFT 0x0000000c
+#define DB_COUNT_CONTROL__ZPASS_ENABLE_MASK 0x00000f00L
+#define DB_COUNT_CONTROL__ZPASS_ENABLE__SHIFT 0x00000008
+#define DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE_MASK 0x00000001L
+#define DB_COUNT_CONTROL__ZPASS_INCREMENT_DISABLE__SHIFT 0x00000000
+#define DB_CREDIT_LIMIT__DB_CB_LQUAD_CREDITS_MASK 0x00001c00L
+#define DB_CREDIT_LIMIT__DB_CB_LQUAD_CREDITS__SHIFT 0x0000000a
+#define DB_CREDIT_LIMIT__DB_CB_TILE_CREDITS_MASK 0x7f000000L
+#define DB_CREDIT_LIMIT__DB_CB_TILE_CREDITS__SHIFT 0x00000018
+#define DB_CREDIT_LIMIT__DB_SC_QUAD_CREDITS_MASK 0x000003e0L
+#define DB_CREDIT_LIMIT__DB_SC_QUAD_CREDITS__SHIFT 0x00000005
+#define DB_CREDIT_LIMIT__DB_SC_TILE_CREDITS_MASK 0x0000001fL
+#define DB_CREDIT_LIMIT__DB_SC_TILE_CREDITS__SHIFT 0x00000000
+#define DB_DEBUG2__ALLOW_COMPZ_BYTE_MASKING_MASK 0x00000001L
+#define DB_DEBUG2__ALLOW_COMPZ_BYTE_MASKING__SHIFT 0x00000000
+#define DB_DEBUG2__CLK_OFF_DELAY_MASK 0x00003e00L
+#define DB_DEBUG2__CLK_OFF_DELAY__SHIFT 0x00000009
+#define DB_DEBUG2__DISABLE_DTT_DATA_FORWARDING_MASK 0x00040000L
+#define DB_DEBUG2__DISABLE_DTT_DATA_FORWARDING__SHIFT 0x00000012
+#define DB_DEBUG2__DISABLE_HTILE_PAIRED_PIPES_MASK 0x00010000L
+#define DB_DEBUG2__DISABLE_HTILE_PAIRED_PIPES__SHIFT 0x00000010
+#define DB_DEBUG2__DISABLE_NULL_EOT_FORWARDING_MASK 0x00020000L
+#define DB_DEBUG2__DISABLE_NULL_EOT_FORWARDING__SHIFT 0x00000011
+#define DB_DEBUG2__DISABLE_PREZL_CB_STALL_REZ_MASK 0x00000100L
+#define DB_DEBUG2__DISABLE_PREZL_CB_STALL_REZ__SHIFT 0x00000008
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_MASK 0x00000020L
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_REZ_MASK 0x00000080L
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL_REZ__SHIFT 0x00000007
+#define DB_DEBUG2__DISABLE_PREZL_LPF_STALL__SHIFT 0x00000005
+#define DB_DEBUG2__DISABLE_PREZL_VIEWPORT_STALL_MASK 0x20000000L
+#define DB_DEBUG2__DISABLE_PREZL_VIEWPORT_STALL__SHIFT 0x0000001d
+#define DB_DEBUG2__DISABLE_QUAD_COHERENCY_STALL_MASK 0x00080000L
+#define DB_DEBUG2__DISABLE_QUAD_COHERENCY_STALL__SHIFT 0x00000013
+#define DB_DEBUG2__DISABLE_SINGLE_STENCIL_QUAD_SUMM_MASK 0x80000000L
+#define DB_DEBUG2__DISABLE_SINGLE_STENCIL_QUAD_SUMM__SHIFT 0x0000001f
+#define DB_DEBUG2__DISABLE_TC_MASK_L0_CACHE_MASK 0x00000004L
+#define DB_DEBUG2__DISABLE_TC_MASK_L0_CACHE__SHIFT 0x00000002
+#define DB_DEBUG2__DISABLE_TC_ZRANGE_L0_CACHE_MASK 0x00000002L
+#define DB_DEBUG2__DISABLE_TC_ZRANGE_L0_CACHE__SHIFT 0x00000001
+#define DB_DEBUG2__DISABLE_TILE_COVERED_FOR_PS_ITER_MASK 0x00004000L
+#define DB_DEBUG2__DISABLE_TILE_COVERED_FOR_PS_ITER__SHIFT 0x0000000e
+#define DB_DEBUG2__DISABLE_WRITE_STALL_ON_RDWR_CONFLICT_MASK 0x80000000L
+#define DB_DEBUG2__DISABLE_WRITE_STALL_ON_RDWR_CONFLICT__SHIFT 0x0000001f
+#define DB_DEBUG2__DTR_PREZ_STALLS_FOR_ETF_ROOM_MASK 0x00000010L
+#define DB_DEBUG2__DTR_PREZ_STALLS_FOR_ETF_ROOM__SHIFT 0x00000004
+#define DB_DEBUG2__DTR_ROUND_ROBIN_ARB_MASK 0x00000008L
+#define DB_DEBUG2__DTR_ROUND_ROBIN_ARB__SHIFT 0x00000003
+#define DB_DEBUG2__ENABLE_PREZL_CB_STALL_MASK 0x00000040L
+#define DB_DEBUG2__ENABLE_PREZL_CB_STALL__SHIFT 0x00000006
+#define DB_DEBUG2__ENABLE_PREZ_OF_REZ_SUMM_MASK 0x10000000L
+#define DB_DEBUG2__ENABLE_PREZ_OF_REZ_SUMM__SHIFT 0x0000001c
+#define DB_DEBUG2__ENABLE_SUBTILE_GROUPING_MASK 0x00008000L
+#define DB_DEBUG2__ENABLE_SUBTILE_GROUPING__SHIFT 0x0000000f
+#define DB_DEBUG3__ALLOW_RF2P_RW_COLLISION_MASK 0x00020000L
+#define DB_DEBUG3__ALLOW_RF2P_RW_COLLISION__SHIFT 0x00000011
+#define DB_DEBUG3__DB_EXTRA_DEBUG3_MASK 0xfc000000L
+#define DB_DEBUG3__DB_EXTRA_DEBUG3__SHIFT 0x0000001a
+#define DB_DEBUG3__DISABLE_DI_DT_STALL_MASK 0x02000000L
+#define DB_DEBUG3__DISABLE_DI_DT_STALL__SHIFT 0x00000019
+#define DB_DEBUG3__DISABLE_EQAA_A2M_PERF_OPT_MASK 0x01000000L
+#define DB_DEBUG3__DISABLE_EQAA_A2M_PERF_OPT__SHIFT 0x00000018
+#define DB_DEBUG3__DISABLE_HIZ_ON_VPORT_CLAMP_MASK 0x00000010L
+#define DB_DEBUG3__DISABLE_HIZ_ON_VPORT_CLAMP__SHIFT 0x00000004
+#define DB_DEBUG3__DISABLE_HZ_TC_WRITE_COMBINE_MASK 0x00200000L
+#define DB_DEBUG3__DISABLE_HZ_TC_WRITE_COMBINE__SHIFT 0x00000015
+#define DB_DEBUG3__DISABLE_OP_DF_BYPASS_MASK 0x00004000L
+#define DB_DEBUG3__DISABLE_OP_DF_BYPASS__SHIFT 0x0000000e
+#define DB_DEBUG3__DISABLE_OP_DF_DIRECT_FEEDBACK_MASK 0x00010000L
+#define DB_DEBUG3__DISABLE_OP_DF_DIRECT_FEEDBACK__SHIFT 0x00000010
+#define DB_DEBUG3__DISABLE_OP_DF_WRITE_COMBINE_MASK 0x00008000L
+#define DB_DEBUG3__DISABLE_OP_DF_WRITE_COMBINE__SHIFT 0x0000000f
+#define DB_DEBUG3__DISABLE_OP_S_DATA_FORWARDING_MASK 0x00080000L
+#define DB_DEBUG3__DISABLE_OP_S_DATA_FORWARDING__SHIFT 0x00000013
+#define DB_DEBUG3__DISABLE_OP_Z_DATA_FORWARDING_MASK 0x00002000L
+#define DB_DEBUG3__DISABLE_OP_Z_DATA_FORWARDING__SHIFT 0x0000000d
+#define DB_DEBUG3__DISABLE_OVERRASTERIZATION_FIX_MASK 0x08000000L
+#define DB_DEBUG3__DISABLE_OVERRASTERIZATION_FIX__SHIFT 0x0000001b
+#define DB_DEBUG3__DISABLE_RAM_READ_SUPPRESION_ON_FWD_MASK 0x00800000L
+#define DB_DEBUG3__DISABLE_RAM_READ_SUPPRESION_ON_FWD__SHIFT 0x00000017
+#define DB_DEBUG3__DISABLE_RECOMP_TO_1ZPLANE_WITHOUT_FASTOP_MASK 0x00000800L
+#define DB_DEBUG3__DISABLE_RECOMP_TO_1ZPLANE_WITHOUT_FASTOP__SHIFT 0x0000000b
+#define DB_DEBUG3__DISABLE_REDUNDANT_PLANE_FLUSHES_OPT_MASK 0x00000400L
+#define DB_DEBUG3__DISABLE_REDUNDANT_PLANE_FLUSHES_OPT__SHIFT 0x0000000a
+#define DB_DEBUG3__DISABLE_TCP_CAM_BYPASS_MASK 0x00000080L
+#define DB_DEBUG3__DISABLE_TCP_CAM_BYPASS__SHIFT 0x00000007
+#define DB_DEBUG3__DISABLE_TC_UPDATE_WRITE_COMBINE_MASK 0x00100000L
+#define DB_DEBUG3__DISABLE_TC_UPDATE_WRITE_COMBINE__SHIFT 0x00000014
+#define DB_DEBUG3__DISABLE_TL_SSO_NULL_SUPPRESSION_MASK 0x00000008L
+#define DB_DEBUG3__DISABLE_TL_SSO_NULL_SUPPRESSION__SHIFT 0x00000003
+#define DB_DEBUG3__DISABLE_ZCMP_DIRTY_SUPPRESSION_MASK 0x00000100L
+#define DB_DEBUG3__DISABLE_ZCMP_DIRTY_SUPPRESSION__SHIFT 0x00000008
+#define DB_DEBUG3__DONT_DELETE_CONTEXT_SUSPEND_MASK 0x20000000L
+#define DB_DEBUG3__DONT_DELETE_CONTEXT_SUSPEND__SHIFT 0x0000001d
+#define DB_DEBUG3__DONT_INSERT_CONTEXT_SUSPEND_MASK 0x10000000L
+#define DB_DEBUG3__DONT_INSERT_CONTEXT_SUSPEND__SHIFT 0x0000001c
+#define DB_DEBUG3__ENABLE_DB_PROCESS_RESET_MASK 0x04000000L
+#define DB_DEBUG3__ENABLE_DB_PROCESS_RESET__SHIFT 0x0000001a
+#define DB_DEBUG3__ENABLE_INCOHERENT_EQAA_READS_MASK 0x00001000L
+#define DB_DEBUG3__ENABLE_INCOHERENT_EQAA_READS__SHIFT 0x0000000c
+#define DB_DEBUG3__ENABLE_RECOMP_ZDIRTY_SUPPRESSION_OPT_MASK 0x00400000L
+#define DB_DEBUG3__ENABLE_RECOMP_ZDIRTY_SUPPRESSION_OPT__SHIFT 0x00000016
+#define DB_DEBUG3__ENABLE_TC_MA_ROUND_ROBIN_ARB_MASK 0x00800000L
+#define DB_DEBUG3__ENABLE_TC_MA_ROUND_ROBIN_ARB__SHIFT 0x00000017
+#define DB_DEBUG3__EQAA_INTERPOLATE_COMP_Z_MASK 0x00000020L
+#define DB_DEBUG3__EQAA_INTERPOLATE_COMP_Z__SHIFT 0x00000005
+#define DB_DEBUG3__EQAA_INTERPOLATE_SRC_Z_MASK 0x00000040L
+#define DB_DEBUG3__EQAA_INTERPOLATE_SRC_Z__SHIFT 0x00000006
+#define DB_DEBUG3__FORCE_DB_IS_GOOD_MASK 0x00000004L
+#define DB_DEBUG3__FORCE_DB_IS_GOOD__SHIFT 0x00000002
+#define DB_DEBUG3__SLOW_PREZ_TO_A2M_OMASK_RATE_MASK 0x00040000L
+#define DB_DEBUG3__SLOW_PREZ_TO_A2M_OMASK_RATE__SHIFT 0x00000012
+#define DB_DEBUG4__DB_EXTRA_DEBUG4_MASK 0xffffffc0L
+#define DB_DEBUG4__DB_EXTRA_DEBUG4__SHIFT 0x00000006
+#define DB_DEBUG4__DISABLE_PREZ_POSTZ_DTILE_CONFLICT_STALL_MASK 0x00000020L
+#define DB_DEBUG4__DISABLE_PREZ_POSTZ_DTILE_CONFLICT_STALL__SHIFT 0x00000005
+#define DB_DEBUG4__DISABLE_QC_STENCIL_MASK_SUMMATION_MASK 0x00000002L
+#define DB_DEBUG4__DISABLE_QC_STENCIL_MASK_SUMMATION__SHIFT 0x00000001
+#define DB_DEBUG4__DISABLE_QC_Z_MASK_SUMMATION_MASK 0x00000001L
+#define DB_DEBUG4__DISABLE_QC_Z_MASK_SUMMATION__SHIFT 0x00000000
+#define DB_DEBUG4__DISABLE_RESUMM_TO_SINGLE_STENCIL_MASK 0x00000004L
+#define DB_DEBUG4__DISABLE_RESUMM_TO_SINGLE_STENCIL__SHIFT 0x00000002
+#define DB_DEBUG__DEBUG_DEPTH_COMPRESS_DISABLE_MASK 0x00000002L
+#define DB_DEBUG__DEBUG_DEPTH_COMPRESS_DISABLE__SHIFT 0x00000001
+#define DB_DEBUG__DEBUG_FAST_STENCIL_DISABLE_MASK 0x00008000L
+#define DB_DEBUG__DEBUG_FAST_STENCIL_DISABLE__SHIFT 0x0000000f
+#define DB_DEBUG__DEBUG_FAST_Z_DISABLE_MASK 0x00004000L
+#define DB_DEBUG__DEBUG_FAST_Z_DISABLE__SHIFT 0x0000000e
+#define DB_DEBUG__DEBUG_FORCE_DEPTH_READ_MASK 0x00000040L
+#define DB_DEBUG__DEBUG_FORCE_DEPTH_READ__SHIFT 0x00000006
+#define DB_DEBUG__DEBUG_FORCE_FULL_Z_RANGE_MASK 0x00180000L
+#define DB_DEBUG__DEBUG_FORCE_FULL_Z_RANGE__SHIFT 0x00000013
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE0_MASK 0x00000c00L
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE0__SHIFT 0x0000000a
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE1_MASK 0x00003000L
+#define DB_DEBUG__DEBUG_FORCE_HIS_ENABLE1__SHIFT 0x0000000c
+#define DB_DEBUG__DEBUG_FORCE_HIZ_ENABLE_MASK 0x00000300L
+#define DB_DEBUG__DEBUG_FORCE_HIZ_ENABLE__SHIFT 0x00000008
+#define DB_DEBUG__DEBUG_FORCE_STENCIL_READ_MASK 0x00000080L
+#define DB_DEBUG__DEBUG_FORCE_STENCIL_READ__SHIFT 0x00000007
+#define DB_DEBUG__DEBUG_NOOP_CULL_DISABLE_MASK 0x00010000L
+#define DB_DEBUG__DEBUG_NOOP_CULL_DISABLE__SHIFT 0x00000010
+#define DB_DEBUG__DEBUG_STENCIL_COMPRESS_DISABLE_MASK 0x00000001L
+#define DB_DEBUG__DEBUG_STENCIL_COMPRESS_DISABLE__SHIFT 0x00000000
+#define DB_DEBUG__DECOMPRESS_AFTER_N_ZPLANES_MASK 0x0f000000L
+#define DB_DEBUG__DECOMPRESS_AFTER_N_ZPLANES__SHIFT 0x00000018
+#define DB_DEBUG__DEPTH_CACHE_FORCE_MISS_MASK 0x00040000L
+#define DB_DEBUG__DEPTH_CACHE_FORCE_MISS__SHIFT 0x00000012
+#define DB_DEBUG__DISABLE_DEPTH_SURFACE_SYNC_MASK 0x40000000L
+#define DB_DEBUG__DISABLE_DEPTH_SURFACE_SYNC__SHIFT 0x0000001e
+#define DB_DEBUG__DISABLE_HTILE_SURFACE_SYNC_MASK 0x80000000L
+#define DB_DEBUG__DISABLE_HTILE_SURFACE_SYNC__SHIFT 0x0000001f
+#define DB_DEBUG__DISABLE_SUMM_SQUADS_MASK 0x00020000L
+#define DB_DEBUG__DISABLE_SUMM_SQUADS__SHIFT 0x00000011
+#define DB_DEBUG__DISABLE_VPORT_ZPLANE_OPTIMIZATION_MASK 0x00800000L
+#define DB_DEBUG__DISABLE_VPORT_ZPLANE_OPTIMIZATION__SHIFT 0x00000017
+#define DB_DEBUG__FETCH_FULL_STENCIL_TILE_MASK 0x00000008L
+#define DB_DEBUG__FETCH_FULL_STENCIL_TILE__SHIFT 0x00000003
+#define DB_DEBUG__FETCH_FULL_Z_TILE_MASK 0x00000004L
+#define DB_DEBUG__FETCH_FULL_Z_TILE__SHIFT 0x00000002
+#define DB_DEBUG__FORCE_MISS_IF_NOT_INFLIGHT_MASK 0x20000000L
+#define DB_DEBUG__FORCE_MISS_IF_NOT_INFLIGHT__SHIFT 0x0000001d
+#define DB_DEBUG__FORCE_Z_MODE_MASK 0x00000030L
+#define DB_DEBUG__FORCE_Z_MODE__SHIFT 0x00000004
+#define DB_DEBUG__NEVER_FREE_Z_ONLY_MASK 0x00200000L
+#define DB_DEBUG__NEVER_FREE_Z_ONLY__SHIFT 0x00000015
+#define DB_DEBUG__ONE_FREE_IN_FLIGHT_MASK 0x10000000L
+#define DB_DEBUG__ONE_FREE_IN_FLIGHT__SHIFT 0x0000001c
+#define DB_DEBUG__ZPASS_COUNTS_LOOK_AT_PIPE_STAT_EVENTS_MASK 0x00400000L
+#define DB_DEBUG__ZPASS_COUNTS_LOOK_AT_PIPE_STAT_EVENTS__SHIFT 0x00000016
+#define DB_DEPTH_BOUNDS_MAX__MAX_MASK 0xffffffffL
+#define DB_DEPTH_BOUNDS_MAX__MAX__SHIFT 0x00000000
+#define DB_DEPTH_BOUNDS_MIN__MIN_MASK 0xffffffffL
+#define DB_DEPTH_BOUNDS_MIN__MIN__SHIFT 0x00000000
+#define DB_DEPTH_CLEAR__DEPTH_CLEAR_MASK 0xffffffffL
+#define DB_DEPTH_CLEAR__DEPTH_CLEAR__SHIFT 0x00000000
+#define DB_DEPTH_CONTROL__BACKFACE_ENABLE_MASK 0x00000080L
+#define DB_DEPTH_CONTROL__BACKFACE_ENABLE__SHIFT 0x00000007
+#define DB_DEPTH_CONTROL__DEPTH_BOUNDS_ENABLE_MASK 0x00000008L
+#define DB_DEPTH_CONTROL__DEPTH_BOUNDS_ENABLE__SHIFT 0x00000003
+#define DB_DEPTH_CONTROL__DISABLE_COLOR_WRITES_ON_DEPTH_PASS_MASK 0x80000000L
+#define DB_DEPTH_CONTROL__DISABLE_COLOR_WRITES_ON_DEPTH_PASS__SHIFT 0x0000001f
+#define DB_DEPTH_CONTROL__ENABLE_COLOR_WRITES_ON_DEPTH_FAIL_MASK 0x40000000L
+#define DB_DEPTH_CONTROL__ENABLE_COLOR_WRITES_ON_DEPTH_FAIL__SHIFT 0x0000001e
+#define DB_DEPTH_CONTROL__STENCIL_ENABLE_MASK 0x00000001L
+#define DB_DEPTH_CONTROL__STENCIL_ENABLE__SHIFT 0x00000000
+#define DB_DEPTH_CONTROL__STENCILFUNC_BF_MASK 0x00700000L
+#define DB_DEPTH_CONTROL__STENCILFUNC_BF__SHIFT 0x00000014
+#define DB_DEPTH_CONTROL__STENCILFUNC_MASK 0x00000700L
+#define DB_DEPTH_CONTROL__STENCILFUNC__SHIFT 0x00000008
+#define DB_DEPTH_CONTROL__Z_ENABLE_MASK 0x00000002L
+#define DB_DEPTH_CONTROL__Z_ENABLE__SHIFT 0x00000001
+#define DB_DEPTH_CONTROL__ZFUNC_MASK 0x00000070L
+#define DB_DEPTH_CONTROL__ZFUNC__SHIFT 0x00000004
+#define DB_DEPTH_CONTROL__Z_WRITE_ENABLE_MASK 0x00000004L
+#define DB_DEPTH_CONTROL__Z_WRITE_ENABLE__SHIFT 0x00000002
+#define DB_DEPTH_INFO__ADDR5_SWIZZLE_MASK_MASK 0x0000000fL
+#define DB_DEPTH_INFO__ADDR5_SWIZZLE_MASK__SHIFT 0x00000000
+#define DB_DEPTH_INFO__ARRAY_MODE_MASK 0x000000f0L
+#define DB_DEPTH_INFO__ARRAY_MODE__SHIFT 0x00000004
+#define DB_DEPTH_INFO__BANK_HEIGHT_MASK 0x00018000L
+#define DB_DEPTH_INFO__BANK_HEIGHT__SHIFT 0x0000000f
+#define DB_DEPTH_INFO__BANK_WIDTH_MASK 0x00006000L
+#define DB_DEPTH_INFO__BANK_WIDTH__SHIFT 0x0000000d
+#define DB_DEPTH_INFO__MACRO_TILE_ASPECT_MASK 0x00060000L
+#define DB_DEPTH_INFO__MACRO_TILE_ASPECT__SHIFT 0x00000011
+#define DB_DEPTH_INFO__NUM_BANKS_MASK 0x00180000L
+#define DB_DEPTH_INFO__NUM_BANKS__SHIFT 0x00000013
+#define DB_DEPTH_INFO__PIPE_CONFIG_MASK 0x00001f00L
+#define DB_DEPTH_INFO__PIPE_CONFIG__SHIFT 0x00000008
+#define DB_DEPTH_SIZE__HEIGHT_TILE_MAX_MASK 0x003ff800L
+#define DB_DEPTH_SIZE__HEIGHT_TILE_MAX__SHIFT 0x0000000b
+#define DB_DEPTH_SIZE__PITCH_TILE_MAX_MASK 0x000007ffL
+#define DB_DEPTH_SIZE__PITCH_TILE_MAX__SHIFT 0x00000000
+#define DB_DEPTH_SLICE__SLICE_TILE_MAX_MASK 0x003fffffL
+#define DB_DEPTH_SLICE__SLICE_TILE_MAX__SHIFT 0x00000000
+#define DB_DEPTH_VIEW__SLICE_MAX_MASK 0x00ffe000L
+#define DB_DEPTH_VIEW__SLICE_MAX__SHIFT 0x0000000d
+#define DB_DEPTH_VIEW__SLICE_START_MASK 0x000007ffL
+#define DB_DEPTH_VIEW__SLICE_START__SHIFT 0x00000000
+#define DB_DEPTH_VIEW__STENCIL_READ_ONLY_MASK 0x02000000L
+#define DB_DEPTH_VIEW__STENCIL_READ_ONLY__SHIFT 0x00000019
+#define DB_DEPTH_VIEW__Z_READ_ONLY_MASK 0x01000000L
+#define DB_DEPTH_VIEW__Z_READ_ONLY__SHIFT 0x00000018
+#define DB_EQAA__ALPHA_TO_MASK_EQAA_DISABLE_MASK 0x00200000L
+#define DB_EQAA__ALPHA_TO_MASK_EQAA_DISABLE__SHIFT 0x00000015
+#define DB_EQAA__ALPHA_TO_MASK_NUM_SAMPLES_MASK 0x00007000L
+#define DB_EQAA__ALPHA_TO_MASK_NUM_SAMPLES__SHIFT 0x0000000c
+#define DB_EQAA__ENABLE_POSTZ_OVERRASTERIZATION_MASK 0x08000000L
+#define DB_EQAA__ENABLE_POSTZ_OVERRASTERIZATION__SHIFT 0x0000001b
+#define DB_EQAA__HIGH_QUALITY_INTERSECTIONS_MASK 0x00010000L
+#define DB_EQAA__HIGH_QUALITY_INTERSECTIONS__SHIFT 0x00000010
+#define DB_EQAA__INCOHERENT_EQAA_READS_MASK 0x00020000L
+#define DB_EQAA__INCOHERENT_EQAA_READS__SHIFT 0x00000011
+#define DB_EQAA__INTERPOLATE_COMP_Z_MASK 0x00040000L
+#define DB_EQAA__INTERPOLATE_COMP_Z__SHIFT 0x00000012
+#define DB_EQAA__INTERPOLATE_SRC_Z_MASK 0x00080000L
+#define DB_EQAA__INTERPOLATE_SRC_Z__SHIFT 0x00000013
+#define DB_EQAA__MASK_EXPORT_NUM_SAMPLES_MASK 0x00000700L
+#define DB_EQAA__MASK_EXPORT_NUM_SAMPLES__SHIFT 0x00000008
+#define DB_EQAA__MAX_ANCHOR_SAMPLES_MASK 0x00000007L
+#define DB_EQAA__MAX_ANCHOR_SAMPLES__SHIFT 0x00000000
+#define DB_EQAA__OVERRASTERIZATION_AMOUNT_MASK 0x07000000L
+#define DB_EQAA__OVERRASTERIZATION_AMOUNT__SHIFT 0x00000018
+#define DB_EQAA__PS_ITER_SAMPLES_MASK 0x00000070L
+#define DB_EQAA__PS_ITER_SAMPLES__SHIFT 0x00000004
+#define DB_EQAA__STATIC_ANCHOR_ASSOCIATIONS_MASK 0x00100000L
+#define DB_EQAA__STATIC_ANCHOR_ASSOCIATIONS__SHIFT 0x00000014
+#define DB_FIFO_DEPTH1__LTILE_PROBE_FIFO_DEPTH_MASK 0x1fe00000L
+#define DB_FIFO_DEPTH1__LTILE_PROBE_FIFO_DEPTH__SHIFT 0x00000015
+#define DB_FIFO_DEPTH1__MCC_DEPTH_MASK 0x0000fc00L
+#define DB_FIFO_DEPTH1__MCC_DEPTH__SHIFT 0x0000000a
+#define DB_FIFO_DEPTH1__MI_RDREQ_FIFO_DEPTH_MASK 0x0000001fL
+#define DB_FIFO_DEPTH1__MI_RDREQ_FIFO_DEPTH__SHIFT 0x00000000
+#define DB_FIFO_DEPTH1__MI_WRREQ_FIFO_DEPTH_MASK 0x000003e0L
+#define DB_FIFO_DEPTH1__MI_WRREQ_FIFO_DEPTH__SHIFT 0x00000005
+#define DB_FIFO_DEPTH1__QC_DEPTH_MASK 0x001f0000L
+#define DB_FIFO_DEPTH1__QC_DEPTH__SHIFT 0x00000010
+#define DB_FIFO_DEPTH2__EQUAD_FIFO_DEPTH_MASK 0x000000ffL
+#define DB_FIFO_DEPTH2__EQUAD_FIFO_DEPTH__SHIFT 0x00000000
+#define DB_FIFO_DEPTH2__ETILE_OP_FIFO_DEPTH_MASK 0x00007f00L
+#define DB_FIFO_DEPTH2__ETILE_OP_FIFO_DEPTH__SHIFT 0x00000008
+#define DB_FIFO_DEPTH2__LQUAD_FIFO_DEPTH_MASK 0x01ff8000L
+#define DB_FIFO_DEPTH2__LQUAD_FIFO_DEPTH__SHIFT 0x0000000f
+#define DB_FIFO_DEPTH2__LTILE_OP_FIFO_DEPTH_MASK 0xfe000000L
+#define DB_FIFO_DEPTH2__LTILE_OP_FIFO_DEPTH__SHIFT 0x00000019
+#define DB_FREE_CACHELINES__FREE_DTILE_DEPTH_MASK 0x0000007fL
+#define DB_FREE_CACHELINES__FREE_DTILE_DEPTH__SHIFT 0x00000000
+#define DB_FREE_CACHELINES__FREE_HTILE_DEPTH_MASK 0x01e00000L
+#define DB_FREE_CACHELINES__FREE_HTILE_DEPTH__SHIFT 0x00000015
+#define DB_FREE_CACHELINES__FREE_PLANE_DEPTH_MASK 0x00003f80L
+#define DB_FREE_CACHELINES__FREE_PLANE_DEPTH__SHIFT 0x00000007
+#define DB_FREE_CACHELINES__FREE_Z_DEPTH_MASK 0x001fc000L
+#define DB_FREE_CACHELINES__FREE_Z_DEPTH__SHIFT 0x0000000e
+#define DB_FREE_CACHELINES__QUAD_READ_REQS_MASK 0xfe000000L
+#define DB_FREE_CACHELINES__QUAD_READ_REQS__SHIFT 0x00000019
+#define DB_HTILE_DATA_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_HTILE_DATA_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE_MASK 0x00010000L
+#define DB_HTILE_SURFACE__DST_OUTSIDE_ZERO_TO_ONE__SHIFT 0x00000010
+#define DB_HTILE_SURFACE__FULL_CACHE_MASK 0x00000002L
+#define DB_HTILE_SURFACE__FULL_CACHE__SHIFT 0x00000001
+#define DB_HTILE_SURFACE__HTILE_USES_PRELOAD_WIN_MASK 0x00000004L
+#define DB_HTILE_SURFACE__HTILE_USES_PRELOAD_WIN__SHIFT 0x00000002
+#define DB_HTILE_SURFACE__LINEAR_MASK 0x00000001L
+#define DB_HTILE_SURFACE__LINEAR__SHIFT 0x00000000
+#define DB_HTILE_SURFACE__PREFETCH_HEIGHT_MASK 0x0000fc00L
+#define DB_HTILE_SURFACE__PREFETCH_HEIGHT__SHIFT 0x0000000a
+#define DB_HTILE_SURFACE__PREFETCH_WIDTH_MASK 0x000003f0L
+#define DB_HTILE_SURFACE__PREFETCH_WIDTH__SHIFT 0x00000004
+#define DB_HTILE_SURFACE__PRELOAD_MASK 0x00000008L
+#define DB_HTILE_SURFACE__PRELOAD__SHIFT 0x00000003
+#define DB_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define DB_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define DB_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define DB_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define DB_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define DB_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define DB_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define DB_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define DB_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define DB_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define DB_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define DB_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define DB_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define DB_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define DB_PRELOAD_CONTROL__MAX_X_MASK 0x00ff0000L
+#define DB_PRELOAD_CONTROL__MAX_X__SHIFT 0x00000010
+#define DB_PRELOAD_CONTROL__MAX_Y_MASK 0xff000000L
+#define DB_PRELOAD_CONTROL__MAX_Y__SHIFT 0x00000018
+#define DB_PRELOAD_CONTROL__START_X_MASK 0x000000ffL
+#define DB_PRELOAD_CONTROL__START_X__SHIFT 0x00000000
+#define DB_PRELOAD_CONTROL__START_Y_MASK 0x0000ff00L
+#define DB_PRELOAD_CONTROL__START_Y__SHIFT 0x00000008
+#define DB_READ_DEBUG_0__BUSY_DATA0_MASK 0xffffffffL
+#define DB_READ_DEBUG_0__BUSY_DATA0__SHIFT 0x00000000
+#define DB_READ_DEBUG_1__BUSY_DATA1_MASK 0xffffffffL
+#define DB_READ_DEBUG_1__BUSY_DATA1__SHIFT 0x00000000
+#define DB_READ_DEBUG_2__BUSY_DATA2_MASK 0xffffffffL
+#define DB_READ_DEBUG_2__BUSY_DATA2__SHIFT 0x00000000
+#define DB_READ_DEBUG_3__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_3__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_4__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_4__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_5__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_5__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_6__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_6__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_7__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_7__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_8__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_8__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_9__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_9__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_A__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_A__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_B__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_B__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_C__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_C__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_D__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_D__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_E__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_E__DEBUG_DATA__SHIFT 0x00000000
+#define DB_READ_DEBUG_F__DEBUG_DATA_MASK 0xffffffffL
+#define DB_READ_DEBUG_F__DEBUG_DATA__SHIFT 0x00000000
+#define DB_RENDER_CONTROL__COPY_CENTROID_MASK 0x00000080L
+#define DB_RENDER_CONTROL__COPY_CENTROID__SHIFT 0x00000007
+#define DB_RENDER_CONTROL__COPY_SAMPLE_MASK 0x00000f00L
+#define DB_RENDER_CONTROL__COPY_SAMPLE__SHIFT 0x00000008
+#define DB_RENDER_CONTROL__DEPTH_CLEAR_ENABLE_MASK 0x00000001L
+#define DB_RENDER_CONTROL__DEPTH_CLEAR_ENABLE__SHIFT 0x00000000
+#define DB_RENDER_CONTROL__DEPTH_COMPRESS_DISABLE_MASK 0x00000040L
+#define DB_RENDER_CONTROL__DEPTH_COMPRESS_DISABLE__SHIFT 0x00000006
+#define DB_RENDER_CONTROL__DEPTH_COPY_MASK 0x00000004L
+#define DB_RENDER_CONTROL__DEPTH_COPY__SHIFT 0x00000002
+#define DB_RENDER_CONTROL__RESUMMARIZE_ENABLE_MASK 0x00000010L
+#define DB_RENDER_CONTROL__RESUMMARIZE_ENABLE__SHIFT 0x00000004
+#define DB_RENDER_CONTROL__STENCIL_CLEAR_ENABLE_MASK 0x00000002L
+#define DB_RENDER_CONTROL__STENCIL_CLEAR_ENABLE__SHIFT 0x00000001
+#define DB_RENDER_CONTROL__STENCIL_COMPRESS_DISABLE_MASK 0x00000020L
+#define DB_RENDER_CONTROL__STENCIL_COMPRESS_DISABLE__SHIFT 0x00000005
+#define DB_RENDER_CONTROL__STENCIL_COPY_MASK 0x00000008L
+#define DB_RENDER_CONTROL__STENCIL_COPY__SHIFT 0x00000003
+#define DB_RENDER_OVERRIDE2__DECOMPRESS_Z_ON_FLUSH_MASK 0x00000100L
+#define DB_RENDER_OVERRIDE2__DECOMPRESS_Z_ON_FLUSH__SHIFT 0x00000008
+#define DB_RENDER_OVERRIDE2__DEPTH_BOUNDS_HIER_DEPTH_DISABLE_MASK 0x00000400L
+#define DB_RENDER_OVERRIDE2__DEPTH_BOUNDS_HIER_DEPTH_DISABLE__SHIFT 0x0000000a
+#define DB_RENDER_OVERRIDE2__DISABLE_COLOR_ON_VALIDATION_MASK 0x00000080L
+#define DB_RENDER_OVERRIDE2__DISABLE_COLOR_ON_VALIDATION__SHIFT 0x00000007
+#define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS_MASK 0x00800000L
+#define DB_RENDER_OVERRIDE2__DISABLE_FAST_PASS__SHIFT 0x00000017
+#define DB_RENDER_OVERRIDE2__DISABLE_REG_SNOOP_MASK 0x00000200L
+#define DB_RENDER_OVERRIDE2__DISABLE_REG_SNOOP__SHIFT 0x00000009
+#define DB_RENDER_OVERRIDE2__DISABLE_SMEM_EXPCLEAR_OPTIMIZATION_MASK 0x00000040L
+#define DB_RENDER_OVERRIDE2__DISABLE_SMEM_EXPCLEAR_OPTIMIZATION__SHIFT 0x00000006
+#define DB_RENDER_OVERRIDE2__DISABLE_ZMASK_EXPCLEAR_OPTIMIZATION_MASK 0x00000020L
+#define DB_RENDER_OVERRIDE2__DISABLE_ZMASK_EXPCLEAR_OPTIMIZATION__SHIFT 0x00000005
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_BF_MASK 0x001c0000L
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_BF__SHIFT 0x00000012
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_FF_MASK 0x00038000L
+#define DB_RENDER_OVERRIDE2__HIS_SFUNC_FF__SHIFT 0x0000000f
+#define DB_RENDER_OVERRIDE2__HIZ_ZFUNC_MASK 0x00007000L
+#define DB_RENDER_OVERRIDE2__HIZ_ZFUNC__SHIFT 0x0000000c
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL_MASK 0x00000003L
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_CONTROL__SHIFT 0x00000000
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN_MASK 0x0000001cL
+#define DB_RENDER_OVERRIDE2__PARTIAL_SQUAD_LAUNCH_COUNTDOWN__SHIFT 0x00000002
+#define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS_MASK 0x00400000L
+#define DB_RENDER_OVERRIDE2__PRESERVE_SRESULTS__SHIFT 0x00000016
+#define DB_RENDER_OVERRIDE2__PRESERVE_ZRANGE_MASK 0x00200000L
+#define DB_RENDER_OVERRIDE2__PRESERVE_ZRANGE__SHIFT 0x00000015
+#define DB_RENDER_OVERRIDE2__SEPARATE_HIZS_FUNC_ENABLE_MASK 0x00000800L
+#define DB_RENDER_OVERRIDE2__SEPARATE_HIZS_FUNC_ENABLE__SHIFT 0x0000000b
+#define DB_RENDER_OVERRIDE__DISABLE_FULLY_COVERED_MASK 0x00040000L
+#define DB_RENDER_OVERRIDE__DISABLE_FULLY_COVERED__SHIFT 0x00000012
+#define DB_RENDER_OVERRIDE__DISABLE_TILE_RATE_TILES_MASK 0x04000000L
+#define DB_RENDER_OVERRIDE__DISABLE_TILE_RATE_TILES__SHIFT 0x0000001a
+#define DB_RENDER_OVERRIDE__DISABLE_VIEWPORT_CLAMP_MASK 0x00010000L
+#define DB_RENDER_OVERRIDE__DISABLE_VIEWPORT_CLAMP__SHIFT 0x00000010
+#define DB_RENDER_OVERRIDE__FAST_STENCIL_DISABLE_MASK 0x00000100L
+#define DB_RENDER_OVERRIDE__FAST_STENCIL_DISABLE__SHIFT 0x00000008
+#define DB_RENDER_OVERRIDE__FAST_Z_DISABLE_MASK 0x00000080L
+#define DB_RENDER_OVERRIDE__FAST_Z_DISABLE__SHIFT 0x00000007
+#define DB_RENDER_OVERRIDE__FORCE_COLOR_KILL_MASK 0x00000400L
+#define DB_RENDER_OVERRIDE__FORCE_COLOR_KILL__SHIFT 0x0000000a
+#define DB_RENDER_OVERRIDE__FORCE_FULL_Z_RANGE_MASK 0x00006000L
+#define DB_RENDER_OVERRIDE__FORCE_FULL_Z_RANGE__SHIFT 0x0000000d
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE0_MASK 0x0000000cL
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE0__SHIFT 0x00000002
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE1_MASK 0x00000030L
+#define DB_RENDER_OVERRIDE__FORCE_HIS_ENABLE1__SHIFT 0x00000004
+#define DB_RENDER_OVERRIDE__FORCE_HIZ_ENABLE_MASK 0x00000003L
+#define DB_RENDER_OVERRIDE__FORCE_HIZ_ENABLE__SHIFT 0x00000000
+#define DB_RENDER_OVERRIDE__FORCE_QC_SMASK_CONFLICT_MASK 0x00008000L
+#define DB_RENDER_OVERRIDE__FORCE_QC_SMASK_CONFLICT__SHIFT 0x0000000f
+#define DB_RENDER_OVERRIDE__FORCE_SHADER_Z_ORDER_MASK 0x00000040L
+#define DB_RENDER_OVERRIDE__FORCE_SHADER_Z_ORDER__SHIFT 0x00000006
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_DIRTY_MASK 0x10000000L
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_DIRTY__SHIFT 0x0000001c
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_READ_MASK 0x00001000L
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_READ__SHIFT 0x0000000c
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_VALID_MASK 0x40000000L
+#define DB_RENDER_OVERRIDE__FORCE_STENCIL_VALID__SHIFT 0x0000001e
+#define DB_RENDER_OVERRIDE__FORCE_Z_DIRTY_MASK 0x08000000L
+#define DB_RENDER_OVERRIDE__FORCE_Z_DIRTY__SHIFT 0x0000001b
+#define DB_RENDER_OVERRIDE__FORCE_Z_LIMIT_SUMM_MASK 0x00180000L
+#define DB_RENDER_OVERRIDE__FORCE_Z_LIMIT_SUMM__SHIFT 0x00000013
+#define DB_RENDER_OVERRIDE__FORCE_Z_READ_MASK 0x00000800L
+#define DB_RENDER_OVERRIDE__FORCE_Z_READ__SHIFT 0x0000000b
+#define DB_RENDER_OVERRIDE__FORCE_Z_VALID_MASK 0x20000000L
+#define DB_RENDER_OVERRIDE__FORCE_Z_VALID__SHIFT 0x0000001d
+#define DB_RENDER_OVERRIDE__IGNORE_SC_ZRANGE_MASK 0x00020000L
+#define DB_RENDER_OVERRIDE__IGNORE_SC_ZRANGE__SHIFT 0x00000011
+#define DB_RENDER_OVERRIDE__MAX_TILES_IN_DTT_MASK 0x03e00000L
+#define DB_RENDER_OVERRIDE__MAX_TILES_IN_DTT__SHIFT 0x00000015
+#define DB_RENDER_OVERRIDE__NOOP_CULL_DISABLE_MASK 0x00000200L
+#define DB_RENDER_OVERRIDE__NOOP_CULL_DISABLE__SHIFT 0x00000009
+#define DB_RENDER_OVERRIDE__PRESERVE_COMPRESSION_MASK 0x80000000L
+#define DB_RENDER_OVERRIDE__PRESERVE_COMPRESSION__SHIFT 0x0000001f
+#define DB_SHADER_CONTROL__ALPHA_TO_MASK_DISABLE_MASK 0x00000800L
+#define DB_SHADER_CONTROL__ALPHA_TO_MASK_DISABLE__SHIFT 0x0000000b
+#define DB_SHADER_CONTROL__CONSERVATIVE_Z_EXPORT_MASK 0x00006000L
+#define DB_SHADER_CONTROL__CONSERVATIVE_Z_EXPORT__SHIFT 0x0000000d
+#define DB_SHADER_CONTROL__COVERAGE_TO_MASK_ENABLE_MASK 0x00000080L
+#define DB_SHADER_CONTROL__COVERAGE_TO_MASK_ENABLE__SHIFT 0x00000007
+#define DB_SHADER_CONTROL__DEPTH_BEFORE_SHADER_MASK 0x00001000L
+#define DB_SHADER_CONTROL__DEPTH_BEFORE_SHADER__SHIFT 0x0000000c
+#define DB_SHADER_CONTROL__EXEC_ON_HIER_FAIL_MASK 0x00000200L
+#define DB_SHADER_CONTROL__EXEC_ON_HIER_FAIL__SHIFT 0x00000009
+#define DB_SHADER_CONTROL__EXEC_ON_NOOP_MASK 0x00000400L
+#define DB_SHADER_CONTROL__EXEC_ON_NOOP__SHIFT 0x0000000a
+#define DB_SHADER_CONTROL__KILL_ENABLE_MASK 0x00000040L
+#define DB_SHADER_CONTROL__KILL_ENABLE__SHIFT 0x00000006
+#define DB_SHADER_CONTROL__MASK_EXPORT_ENABLE_MASK 0x00000100L
+#define DB_SHADER_CONTROL__MASK_EXPORT_ENABLE__SHIFT 0x00000008
+#define DB_SHADER_CONTROL__STENCIL_OP_VAL_EXPORT_ENABLE_MASK 0x00000004L
+#define DB_SHADER_CONTROL__STENCIL_OP_VAL_EXPORT_ENABLE__SHIFT 0x00000002
+#define DB_SHADER_CONTROL__STENCIL_TEST_VAL_EXPORT_ENABLE_MASK 0x00000002L
+#define DB_SHADER_CONTROL__STENCIL_TEST_VAL_EXPORT_ENABLE__SHIFT 0x00000001
+#define DB_SHADER_CONTROL__Z_EXPORT_ENABLE_MASK 0x00000001L
+#define DB_SHADER_CONTROL__Z_EXPORT_ENABLE__SHIFT 0x00000000
+#define DB_SHADER_CONTROL__Z_ORDER_MASK 0x00000030L
+#define DB_SHADER_CONTROL__Z_ORDER__SHIFT 0x00000004
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0_MASK 0x00000007L
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREFUNC0__SHIFT 0x00000000
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREMASK0_MASK 0x000ff000L
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREMASK0__SHIFT 0x0000000c
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0_MASK 0x00000ff0L
+#define DB_SRESULTS_COMPARE_STATE0__COMPAREVALUE0__SHIFT 0x00000004
+#define DB_SRESULTS_COMPARE_STATE0__ENABLE0_MASK 0x01000000L
+#define DB_SRESULTS_COMPARE_STATE0__ENABLE0__SHIFT 0x00000018
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREFUNC1_MASK 0x00000007L
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREFUNC1__SHIFT 0x00000000
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREMASK1_MASK 0x000ff000L
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREMASK1__SHIFT 0x0000000c
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREVALUE1_MASK 0x00000ff0L
+#define DB_SRESULTS_COMPARE_STATE1__COMPAREVALUE1__SHIFT 0x00000004
+#define DB_SRESULTS_COMPARE_STATE1__ENABLE1_MASK 0x01000000L
+#define DB_SRESULTS_COMPARE_STATE1__ENABLE1__SHIFT 0x00000018
+#define DB_STENCIL_CLEAR__CLEAR_MASK 0x000000ffL
+#define DB_STENCIL_CLEAR__CLEAR__SHIFT 0x00000000
+#define DB_STENCIL_CONTROL__STENCILFAIL_BF_MASK 0x0000f000L
+#define DB_STENCIL_CONTROL__STENCILFAIL_BF__SHIFT 0x0000000c
+#define DB_STENCIL_CONTROL__STENCILFAIL_MASK 0x0000000fL
+#define DB_STENCIL_CONTROL__STENCILFAIL__SHIFT 0x00000000
+#define DB_STENCIL_CONTROL__STENCILZFAIL_BF_MASK 0x00f00000L
+#define DB_STENCIL_CONTROL__STENCILZFAIL_BF__SHIFT 0x00000014
+#define DB_STENCIL_CONTROL__STENCILZFAIL_MASK 0x00000f00L
+#define DB_STENCIL_CONTROL__STENCILZFAIL__SHIFT 0x00000008
+#define DB_STENCIL_CONTROL__STENCILZPASS_BF_MASK 0x000f0000L
+#define DB_STENCIL_CONTROL__STENCILZPASS_BF__SHIFT 0x00000010
+#define DB_STENCIL_CONTROL__STENCILZPASS_MASK 0x000000f0L
+#define DB_STENCIL_CONTROL__STENCILZPASS__SHIFT 0x00000004
+#define DB_STENCIL_INFO__ALLOW_EXPCLEAR_MASK 0x08000000L
+#define DB_STENCIL_INFO__ALLOW_EXPCLEAR__SHIFT 0x0000001b
+#define DB_STENCIL_INFO__FORMAT_MASK 0x00000001L
+#define DB_STENCIL_INFO__FORMAT__SHIFT 0x00000000
+#define DB_STENCIL_INFO__TILE_MODE_INDEX_MASK 0x00700000L
+#define DB_STENCIL_INFO__TILE_MODE_INDEX__SHIFT 0x00000014
+#define DB_STENCIL_INFO__TILE_SPLIT_MASK 0x0000e000L
+#define DB_STENCIL_INFO__TILE_SPLIT__SHIFT 0x0000000d
+#define DB_STENCIL_INFO__TILE_STENCIL_DISABLE_MASK 0x20000000L
+#define DB_STENCIL_INFO__TILE_STENCIL_DISABLE__SHIFT 0x0000001d
+#define DB_STENCIL_READ_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_STENCIL_READ_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_STENCILREFMASK_BF__STENCILMASK_BF_MASK 0x0000ff00L
+#define DB_STENCILREFMASK_BF__STENCILMASK_BF__SHIFT 0x00000008
+#define DB_STENCILREFMASK_BF__STENCILOPVAL_BF_MASK 0xff000000L
+#define DB_STENCILREFMASK_BF__STENCILOPVAL_BF__SHIFT 0x00000018
+#define DB_STENCILREFMASK_BF__STENCILTESTVAL_BF_MASK 0x000000ffL
+#define DB_STENCILREFMASK_BF__STENCILTESTVAL_BF__SHIFT 0x00000000
+#define DB_STENCILREFMASK_BF__STENCILWRITEMASK_BF_MASK 0x00ff0000L
+#define DB_STENCILREFMASK_BF__STENCILWRITEMASK_BF__SHIFT 0x00000010
+#define DB_STENCILREFMASK__STENCILMASK_MASK 0x0000ff00L
+#define DB_STENCILREFMASK__STENCILMASK__SHIFT 0x00000008
+#define DB_STENCILREFMASK__STENCILOPVAL_MASK 0xff000000L
+#define DB_STENCILREFMASK__STENCILOPVAL__SHIFT 0x00000018
+#define DB_STENCILREFMASK__STENCILTESTVAL_MASK 0x000000ffL
+#define DB_STENCILREFMASK__STENCILTESTVAL__SHIFT 0x00000000
+#define DB_STENCILREFMASK__STENCILWRITEMASK_MASK 0x00ff0000L
+#define DB_STENCILREFMASK__STENCILWRITEMASK__SHIFT 0x00000010
+#define DB_STENCIL_WRITE_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_STENCIL_WRITE_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_SUBTILE_CONTROL__MSAA16_X_MASK 0x00030000L
+#define DB_SUBTILE_CONTROL__MSAA16_X__SHIFT 0x00000010
+#define DB_SUBTILE_CONTROL__MSAA16_Y_MASK 0x000c0000L
+#define DB_SUBTILE_CONTROL__MSAA16_Y__SHIFT 0x00000012
+#define DB_SUBTILE_CONTROL__MSAA1_X_MASK 0x00000003L
+#define DB_SUBTILE_CONTROL__MSAA1_X__SHIFT 0x00000000
+#define DB_SUBTILE_CONTROL__MSAA1_Y_MASK 0x0000000cL
+#define DB_SUBTILE_CONTROL__MSAA1_Y__SHIFT 0x00000002
+#define DB_SUBTILE_CONTROL__MSAA2_X_MASK 0x00000030L
+#define DB_SUBTILE_CONTROL__MSAA2_X__SHIFT 0x00000004
+#define DB_SUBTILE_CONTROL__MSAA2_Y_MASK 0x000000c0L
+#define DB_SUBTILE_CONTROL__MSAA2_Y__SHIFT 0x00000006
+#define DB_SUBTILE_CONTROL__MSAA4_X_MASK 0x00000300L
+#define DB_SUBTILE_CONTROL__MSAA4_X__SHIFT 0x00000008
+#define DB_SUBTILE_CONTROL__MSAA4_Y_MASK 0x00000c00L
+#define DB_SUBTILE_CONTROL__MSAA4_Y__SHIFT 0x0000000a
+#define DB_SUBTILE_CONTROL__MSAA8_X_MASK 0x00003000L
+#define DB_SUBTILE_CONTROL__MSAA8_X__SHIFT 0x0000000c
+#define DB_SUBTILE_CONTROL__MSAA8_Y_MASK 0x0000c000L
+#define DB_SUBTILE_CONTROL__MSAA8_Y__SHIFT 0x0000000e
+#define DB_WATERMARKS__AUTO_FLUSH_HTILE_MASK 0x40000000L
+#define DB_WATERMARKS__AUTO_FLUSH_HTILE__SHIFT 0x0000001e
+#define DB_WATERMARKS__AUTO_FLUSH_QUAD_MASK 0x80000000L
+#define DB_WATERMARKS__AUTO_FLUSH_QUAD__SHIFT 0x0000001f
+#define DB_WATERMARKS__DEPTH_CACHELINE_FREE_MASK 0x07f00000L
+#define DB_WATERMARKS__DEPTH_CACHELINE_FREE__SHIFT 0x00000014
+#define DB_WATERMARKS__DEPTH_FLUSH_MASK 0x000007e0L
+#define DB_WATERMARKS__DEPTH_FLUSH__SHIFT 0x00000005
+#define DB_WATERMARKS__DEPTH_FREE_MASK 0x0000001fL
+#define DB_WATERMARKS__DEPTH_FREE__SHIFT 0x00000000
+#define DB_WATERMARKS__DEPTH_PENDING_FREE_MASK 0x000f8000L
+#define DB_WATERMARKS__DEPTH_PENDING_FREE__SHIFT 0x0000000f
+#define DB_WATERMARKS__EARLY_Z_PANIC_DISABLE_MASK 0x08000000L
+#define DB_WATERMARKS__EARLY_Z_PANIC_DISABLE__SHIFT 0x0000001b
+#define DB_WATERMARKS__FORCE_SUMMARIZE_MASK 0x00007800L
+#define DB_WATERMARKS__FORCE_SUMMARIZE__SHIFT 0x0000000b
+#define DB_WATERMARKS__LATE_Z_PANIC_DISABLE_MASK 0x10000000L
+#define DB_WATERMARKS__LATE_Z_PANIC_DISABLE__SHIFT 0x0000001c
+#define DB_WATERMARKS__RE_Z_PANIC_DISABLE_MASK 0x20000000L
+#define DB_WATERMARKS__RE_Z_PANIC_DISABLE__SHIFT 0x0000001d
+#define DB_Z_INFO__ALLOW_EXPCLEAR_MASK 0x08000000L
+#define DB_Z_INFO__ALLOW_EXPCLEAR__SHIFT 0x0000001b
+#define DB_Z_INFO__FORMAT_MASK 0x00000003L
+#define DB_Z_INFO__FORMAT__SHIFT 0x00000000
+#define DB_Z_INFO__NUM_SAMPLES_MASK 0x0000000cL
+#define DB_Z_INFO__NUM_SAMPLES__SHIFT 0x00000002
+#define DB_Z_INFO__READ_SIZE_MASK 0x10000000L
+#define DB_Z_INFO__READ_SIZE__SHIFT 0x0000001c
+#define DB_Z_INFO__TILE_MODE_INDEX_MASK 0x00700000L
+#define DB_Z_INFO__TILE_MODE_INDEX__SHIFT 0x00000014
+#define DB_Z_INFO__TILE_SPLIT_MASK 0x0000e000L
+#define DB_Z_INFO__TILE_SPLIT__SHIFT 0x0000000d
+#define DB_Z_INFO__TILE_SURFACE_ENABLE_MASK 0x20000000L
+#define DB_Z_INFO__TILE_SURFACE_ENABLE__SHIFT 0x0000001d
+#define DB_Z_INFO__ZRANGE_PRECISION_MASK 0x80000000L
+#define DB_Z_INFO__ZRANGE_PRECISION__SHIFT 0x0000001f
+#define DB_ZPASS_COUNT_HI__COUNT_HI_MASK 0x7fffffffL
+#define DB_ZPASS_COUNT_HI__COUNT_HI__SHIFT 0x00000000
+#define DB_ZPASS_COUNT_LOW__COUNT_LOW_MASK 0xffffffffL
+#define DB_ZPASS_COUNT_LOW__COUNT_LOW__SHIFT 0x00000000
+#define DB_Z_READ_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_Z_READ_BASE__BASE_256B__SHIFT 0x00000000
+#define DB_Z_WRITE_BASE__BASE_256B_MASK 0xffffffffL
+#define DB_Z_WRITE_BASE__BASE_256B__SHIFT 0x00000000
+#define DEBUG_DATA__DEBUG_DATA_MASK 0xffffffffL
+#define DEBUG_DATA__DEBUG_DATA__SHIFT 0x00000000
+#define DEBUG_INDEX__DEBUG_INDEX_MASK 0x0003ffffL
+#define DEBUG_INDEX__DEBUG_INDEX__SHIFT 0x00000000
+#define GB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define GB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define GB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define GB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define GB_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define GB_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define GB_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define GB_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define GB_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define GB_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define GB_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define GB_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define GB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define GB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define GB_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define GB_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define GB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define GB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define GB_BACKEND_MAP__BACKEND_MAP_MASK 0xffffffffL
+#define GB_BACKEND_MAP__BACKEND_MAP__SHIFT 0x00000000
+#define GB_EDC_MODE__BYPASS_MASK 0x80000000L
+#define GB_EDC_MODE__BYPASS__SHIFT 0x0000001f
+#define GB_EDC_MODE__DED_MODE_MASK 0x00300000L
+#define GB_EDC_MODE__DED_MODE__SHIFT 0x00000014
+#define GB_EDC_MODE__FORCE_SEC_ON_DED_MASK 0x00010000L
+#define GB_EDC_MODE__FORCE_SEC_ON_DED__SHIFT 0x00000010
+#define GB_EDC_MODE__PROP_FED_MASK 0x20000000L
+#define GB_EDC_MODE__PROP_FED__SHIFT 0x0000001d
+#define GB_GPU_ID__GPU_ID_MASK 0x0000000fL
+#define GB_GPU_ID__GPU_ID__SHIFT 0x00000000
+#define GB_TILE_MODE0__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE0__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE0__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE0__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE0__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE0__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE0__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE0__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE0__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE0__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE10__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE10__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE10__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE10__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE10__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE10__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE10__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE10__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE10__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE10__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE11__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE11__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE11__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE11__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE11__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE11__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE11__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE11__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE11__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE11__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE12__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE12__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE12__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE12__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE12__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE12__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE12__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE12__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE12__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE12__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE13__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE13__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE13__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE13__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE13__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE13__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE13__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE13__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE13__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE13__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE14__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE14__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE14__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE14__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE14__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE14__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE14__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE14__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE14__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE14__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE15__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE15__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE15__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE15__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE15__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE15__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE15__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE15__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE15__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE15__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE16__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE16__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE16__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE16__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE16__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE16__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE16__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE16__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE16__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE16__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE17__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE17__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE17__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE17__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE17__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE17__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE17__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE17__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE17__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE17__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE18__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE18__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE18__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE18__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE18__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE18__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE18__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE18__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE18__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE18__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE19__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE19__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE19__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE19__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE19__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE19__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE19__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE19__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE19__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE19__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE1__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE1__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE1__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE1__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE1__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE1__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE1__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE1__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE1__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE1__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE20__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE20__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE20__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE20__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE20__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE20__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE20__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE20__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE20__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE20__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE21__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE21__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE21__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE21__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE21__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE21__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE21__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE21__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE21__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE21__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE22__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE22__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE22__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE22__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE22__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE22__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE22__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE22__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE22__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE22__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE23__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE23__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE23__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE23__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE23__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE23__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE23__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE23__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE23__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE23__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE24__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE24__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE24__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE24__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE24__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE24__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE24__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE24__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE24__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE24__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE25__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE25__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE25__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE25__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE25__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE25__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE25__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE25__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE25__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE25__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE26__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE26__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE26__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE26__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE26__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE26__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE26__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE26__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE26__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE26__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE27__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE27__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE27__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE27__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE27__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE27__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE27__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE27__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE27__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE27__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE28__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE28__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE28__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE28__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE28__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE28__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE28__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE28__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE28__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE28__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE29__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE29__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE29__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE29__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE29__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE29__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE29__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE29__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE29__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE29__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE2__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE2__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE2__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE2__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE2__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE2__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE2__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE2__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE2__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE2__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE30__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE30__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE30__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE30__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE30__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE30__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE30__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE30__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE30__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE30__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE31__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE31__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE31__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE31__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE31__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE31__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE31__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE31__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE31__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE31__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE3__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE3__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE3__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE3__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE3__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE3__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE3__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE3__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE3__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE3__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE4__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE4__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE4__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE4__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE4__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE4__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE4__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE4__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE4__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE4__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE5__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE5__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE5__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE5__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE5__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE5__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE5__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE5__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE5__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE5__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE6__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE6__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE6__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE6__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE6__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE6__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE6__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE6__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE6__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE6__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE7__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE7__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE7__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE7__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE7__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE7__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE7__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE7__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE7__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE7__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE8__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE8__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE8__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE8__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE8__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE8__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE8__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE8__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE8__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE8__TILE_SPLIT__SHIFT 0x0000000b
+#define GB_TILE_MODE9__ARRAY_MODE_MASK 0x0000003cL
+#define GB_TILE_MODE9__ARRAY_MODE__SHIFT 0x00000002
+#define GB_TILE_MODE9__MICRO_TILE_MODE_NEW_MASK 0x01c00000L
+#define GB_TILE_MODE9__MICRO_TILE_MODE_NEW__SHIFT 0x00000016
+#define GB_TILE_MODE9__PIPE_CONFIG_MASK 0x000007c0L
+#define GB_TILE_MODE9__PIPE_CONFIG__SHIFT 0x00000006
+#define GB_TILE_MODE9__SAMPLE_SPLIT_MASK 0x06000000L
+#define GB_TILE_MODE9__SAMPLE_SPLIT__SHIFT 0x00000019
+#define GB_TILE_MODE9__TILE_SPLIT_MASK 0x00003800L
+#define GB_TILE_MODE9__TILE_SPLIT__SHIFT 0x0000000b
+#define GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define GC_USER_SHADER_ARRAY_CONFIG__DPFP_RATE_MASK 0x00000006L
+#define GC_USER_SHADER_ARRAY_CONFIG__DPFP_RATE__SHIFT 0x00000001
+#define GC_USER_SHADER_ARRAY_CONFIG__HALF_LDS_MASK 0x00000010L
+#define GC_USER_SHADER_ARRAY_CONFIG__HALF_LDS__SHIFT 0x00000004
+#define GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK 0xffff0000L
+#define GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT 0x00000010
+#define GC_USER_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE_MASK 0x00000008L
+#define GC_USER_SHADER_ARRAY_CONFIG__SQC_BALANCE_DISABLE__SHIFT 0x00000003
+#define GDS_ATOM_BASE__BASE_MASK 0x0000ffffL
+#define GDS_ATOM_BASE__BASE__SHIFT 0x00000000
+#define GDS_ATOM_BASE__UNUSED_MASK 0xffff0000L
+#define GDS_ATOM_BASE__UNUSED__SHIFT 0x00000010
+#define GDS_ATOM_CNTL__AINC_MASK 0x0000003fL
+#define GDS_ATOM_CNTL__AINC__SHIFT 0x00000000
+#define GDS_ATOM_CNTL__DMODE_MASK 0x00000100L
+#define GDS_ATOM_CNTL__DMODE__SHIFT 0x00000008
+#define GDS_ATOM_CNTL__UNUSED1_MASK 0x000000c0L
+#define GDS_ATOM_CNTL__UNUSED1__SHIFT 0x00000006
+#define GDS_ATOM_CNTL__UNUSED2_MASK 0xfffffe00L
+#define GDS_ATOM_CNTL__UNUSED2__SHIFT 0x00000009
+#define GDS_ATOM_COMPLETE__COMPLETE_MASK 0x00000001L
+#define GDS_ATOM_COMPLETE__COMPLETE__SHIFT 0x00000000
+#define GDS_ATOM_COMPLETE__UNUSED_MASK 0xfffffffeL
+#define GDS_ATOM_COMPLETE__UNUSED__SHIFT 0x00000001
+#define GDS_ATOM_DST__DST_MASK 0xffffffffL
+#define GDS_ATOM_DST__DST__SHIFT 0x00000000
+#define GDS_ATOM_OFFSET0__OFFSET0_MASK 0x000000ffL
+#define GDS_ATOM_OFFSET0__OFFSET0__SHIFT 0x00000000
+#define GDS_ATOM_OFFSET0__UNUSED_MASK 0xffffff00L
+#define GDS_ATOM_OFFSET0__UNUSED__SHIFT 0x00000008
+#define GDS_ATOM_OFFSET1__OFFSET1_MASK 0x000000ffL
+#define GDS_ATOM_OFFSET1__OFFSET1__SHIFT 0x00000000
+#define GDS_ATOM_OFFSET1__UNUSED_MASK 0xffffff00L
+#define GDS_ATOM_OFFSET1__UNUSED__SHIFT 0x00000008
+#define GDS_ATOM_OP__OP_MASK 0x000000ffL
+#define GDS_ATOM_OP__OP__SHIFT 0x00000000
+#define GDS_ATOM_OP__UNUSED_MASK 0xffffff00L
+#define GDS_ATOM_OP__UNUSED__SHIFT 0x00000008
+#define GDS_ATOM_READ0__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ0__DATA__SHIFT 0x00000000
+#define GDS_ATOM_READ0_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ0_U__DATA__SHIFT 0x00000000
+#define GDS_ATOM_READ1__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ1__DATA__SHIFT 0x00000000
+#define GDS_ATOM_READ1_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_READ1_U__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SIZE__SIZE_MASK 0x0000ffffL
+#define GDS_ATOM_SIZE__SIZE__SHIFT 0x00000000
+#define GDS_ATOM_SIZE__UNUSED_MASK 0xffff0000L
+#define GDS_ATOM_SIZE__UNUSED__SHIFT 0x00000010
+#define GDS_ATOM_SRC0__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC0__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SRC0_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC0_U__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SRC1__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC1__DATA__SHIFT 0x00000000
+#define GDS_ATOM_SRC1_U__DATA_MASK 0xffffffffL
+#define GDS_ATOM_SRC1_U__DATA__SHIFT 0x00000000
+#define GDS_CNTL_STATUS__DS_ADDR_CONFLICT_MASK 0x00000010L
+#define GDS_CNTL_STATUS__DS_ADDR_CONFLICT__SHIFT 0x00000004
+#define GDS_CNTL_STATUS__DS_BANK_CONFLICT_MASK 0x00000008L
+#define GDS_CNTL_STATUS__DS_BANK_CONFLICT__SHIFT 0x00000003
+#define GDS_CNTL_STATUS__DS_RD_CLAMP_MASK 0x00000040L
+#define GDS_CNTL_STATUS__DS_RD_CLAMP__SHIFT 0x00000006
+#define GDS_CNTL_STATUS__DS_WR_CLAMP_MASK 0x00000020L
+#define GDS_CNTL_STATUS__DS_WR_CLAMP__SHIFT 0x00000005
+#define GDS_CNTL_STATUS__GDS_BUSY_MASK 0x00000001L
+#define GDS_CNTL_STATUS__GDS_BUSY__SHIFT 0x00000000
+#define GDS_CNTL_STATUS__GRBM_WBUF_BUSY_MASK 0x00000002L
+#define GDS_CNTL_STATUS__GRBM_WBUF_BUSY__SHIFT 0x00000001
+#define GDS_CNTL_STATUS__ORD_APP_BUSY_MASK 0x00000004L
+#define GDS_CNTL_STATUS__ORD_APP_BUSY__SHIFT 0x00000002
+#define GDS_CONFIG__SH0_GPR_PHASE_SEL_MASK 0x00000006L
+#define GDS_CONFIG__SH0_GPR_PHASE_SEL__SHIFT 0x00000001
+#define GDS_CONFIG__SH1_GPR_PHASE_SEL_MASK 0x00000018L
+#define GDS_CONFIG__SH1_GPR_PHASE_SEL__SHIFT 0x00000003
+#define GDS_CONFIG__SH2_GPR_PHASE_SEL_MASK 0x00000060L
+#define GDS_CONFIG__SH2_GPR_PHASE_SEL__SHIFT 0x00000005
+#define GDS_CONFIG__SH3_GPR_PHASE_SEL_MASK 0x00000180L
+#define GDS_CONFIG__SH3_GPR_PHASE_SEL__SHIFT 0x00000007
+#define GDS_DEBUG_CNTL__GDS_DEBUG_INDX_MASK 0x0000001fL
+#define GDS_DEBUG_CNTL__GDS_DEBUG_INDX__SHIFT 0x00000000
+#define GDS_DEBUG_CNTL__UNUSED_MASK 0xffffffe0L
+#define GDS_DEBUG_CNTL__UNUSED__SHIFT 0x00000005
+#define GDS_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define GDS_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define GDS_DEBUG_REG0__buff_write_MASK 0x00020000L
+#define GDS_DEBUG_REG0__buff_write__SHIFT 0x00000011
+#define GDS_DEBUG_REG0__cstate_MASK 0x0001e000L
+#define GDS_DEBUG_REG0__cstate__SHIFT 0x0000000d
+#define GDS_DEBUG_REG0__flush_request_MASK 0x00040000L
+#define GDS_DEBUG_REG0__flush_request__SHIFT 0x00000012
+#define GDS_DEBUG_REG0__last_pixel_ptr_MASK 0x00001000L
+#define GDS_DEBUG_REG0__last_pixel_ptr__SHIFT 0x0000000c
+#define GDS_DEBUG_REG0__spare1_MASK 0x00000001L
+#define GDS_DEBUG_REG0__spare1__SHIFT 0x00000000
+#define GDS_DEBUG_REG0__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG0__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG0__wbuf_fifo_empty_MASK 0x00100000L
+#define GDS_DEBUG_REG0__wbuf_fifo_empty__SHIFT 0x00000014
+#define GDS_DEBUG_REG0__wbuf_fifo_full_MASK 0x00200000L
+#define GDS_DEBUG_REG0__wbuf_fifo_full__SHIFT 0x00000015
+#define GDS_DEBUG_REG0__wr_buffer_wr_complete_MASK 0x00080000L
+#define GDS_DEBUG_REG0__wr_buffer_wr_complete__SHIFT 0x00000013
+#define GDS_DEBUG_REG0__write_buff_valid_MASK 0x00000040L
+#define GDS_DEBUG_REG0__write_buff_valid__SHIFT 0x00000006
+#define GDS_DEBUG_REG0__wr_pixel_nxt_ptr_MASK 0x00000f80L
+#define GDS_DEBUG_REG0__wr_pixel_nxt_ptr__SHIFT 0x00000007
+#define GDS_DEBUG_REG1__addr_fifo_empty_MASK 0x00200000L
+#define GDS_DEBUG_REG1__addr_fifo_empty__SHIFT 0x00000015
+#define GDS_DEBUG_REG1__addr_fifo_full_MASK 0x00100000L
+#define GDS_DEBUG_REG1__addr_fifo_full__SHIFT 0x00000014
+#define GDS_DEBUG_REG1__awaiting_data_MASK 0x00080000L
+#define GDS_DEBUG_REG1__awaiting_data__SHIFT 0x00000013
+#define GDS_DEBUG_REG1__buffer_invalid_MASK 0x00800000L
+#define GDS_DEBUG_REG1__buffer_invalid__SHIFT 0x00000017
+#define GDS_DEBUG_REG1__buffer_loaded_MASK 0x00400000L
+#define GDS_DEBUG_REG1__buffer_loaded__SHIFT 0x00000016
+#define GDS_DEBUG_REG1__data_ready_MASK 0x00040000L
+#define GDS_DEBUG_REG1__data_ready__SHIFT 0x00000012
+#define GDS_DEBUG_REG1__pixel_addr_MASK 0x0001fffcL
+#define GDS_DEBUG_REG1__pixel_addr__SHIFT 0x00000002
+#define GDS_DEBUG_REG1__pixel_vld_MASK 0x00020000L
+#define GDS_DEBUG_REG1__pixel_vld__SHIFT 0x00000011
+#define GDS_DEBUG_REG1__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG1__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG1__tag_hit_MASK 0x00000001L
+#define GDS_DEBUG_REG1__tag_hit__SHIFT 0x00000000
+#define GDS_DEBUG_REG1__tag_miss_MASK 0x00000002L
+#define GDS_DEBUG_REG1__tag_miss__SHIFT 0x00000001
+#define GDS_DEBUG_REG2__app_sel_MASK 0x000000f0L
+#define GDS_DEBUG_REG2__app_sel__SHIFT 0x00000004
+#define GDS_DEBUG_REG2__cmd_write_MASK 0x00000008L
+#define GDS_DEBUG_REG2__cmd_write__SHIFT 0x00000003
+#define GDS_DEBUG_REG2__ds_credit_avail_MASK 0x00000002L
+#define GDS_DEBUG_REG2__ds_credit_avail__SHIFT 0x00000001
+#define GDS_DEBUG_REG2__ds_full_MASK 0x00000001L
+#define GDS_DEBUG_REG2__ds_full__SHIFT 0x00000000
+#define GDS_DEBUG_REG2__ord_idx_free_MASK 0x00000004L
+#define GDS_DEBUG_REG2__ord_idx_free__SHIFT 0x00000002
+#define GDS_DEBUG_REG2__req_MASK 0x007fff00L
+#define GDS_DEBUG_REG2__req__SHIFT 0x00000008
+#define GDS_DEBUG_REG2__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG2__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG3__pipe0_busy_num_MASK 0x00007800L
+#define GDS_DEBUG_REG3__pipe0_busy_num__SHIFT 0x0000000b
+#define GDS_DEBUG_REG3__pipe_num_busy_MASK 0x000007ffL
+#define GDS_DEBUG_REG3__pipe_num_busy__SHIFT 0x00000000
+#define GDS_DEBUG_REG3__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG3__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG4__cmd_write_MASK 0x00020000L
+#define GDS_DEBUG_REG4__cmd_write__SHIFT 0x00000011
+#define GDS_DEBUG_REG4__credit_cnt_gt0_MASK 0x00010000L
+#define GDS_DEBUG_REG4__credit_cnt_gt0__SHIFT 0x00000010
+#define GDS_DEBUG_REG4__cur_reso_barrier_MASK 0x00002000L
+#define GDS_DEBUG_REG4__cur_reso_barrier__SHIFT 0x0000000d
+#define GDS_DEBUG_REG4__cur_reso_cnt_gt0_MASK 0x00008000L
+#define GDS_DEBUG_REG4__cur_reso_cnt_gt0__SHIFT 0x0000000f
+#define GDS_DEBUG_REG4__cur_reso_fed_MASK 0x00001000L
+#define GDS_DEBUG_REG4__cur_reso_fed__SHIFT 0x0000000c
+#define GDS_DEBUG_REG4__cur_reso_flag_MASK 0x00004000L
+#define GDS_DEBUG_REG4__cur_reso_flag__SHIFT 0x0000000e
+#define GDS_DEBUG_REG4__cur_reso_head_dirty_MASK 0x00000400L
+#define GDS_DEBUG_REG4__cur_reso_head_dirty__SHIFT 0x0000000a
+#define GDS_DEBUG_REG4__cur_reso_head_flag_MASK 0x00000800L
+#define GDS_DEBUG_REG4__cur_reso_head_flag__SHIFT 0x0000000b
+#define GDS_DEBUG_REG4__cur_reso_head_valid_MASK 0x00000200L
+#define GDS_DEBUG_REG4__cur_reso_head_valid__SHIFT 0x00000009
+#define GDS_DEBUG_REG4__cur_reso_MASK 0x000001f8L
+#define GDS_DEBUG_REG4__cur_reso__SHIFT 0x00000003
+#define GDS_DEBUG_REG4__grbm_gws_reso_rd_MASK 0x00080000L
+#define GDS_DEBUG_REG4__grbm_gws_reso_rd__SHIFT 0x00000013
+#define GDS_DEBUG_REG4__grbm_gws_reso_wr_MASK 0x00040000L
+#define GDS_DEBUG_REG4__grbm_gws_reso_wr__SHIFT 0x00000012
+#define GDS_DEBUG_REG4__gws_bulkfree_MASK 0x00200000L
+#define GDS_DEBUG_REG4__gws_bulkfree__SHIFT 0x00000015
+#define GDS_DEBUG_REG4__gws_busy_MASK 0x00000001L
+#define GDS_DEBUG_REG4__gws_busy__SHIFT 0x00000000
+#define GDS_DEBUG_REG4__gws_out_stall_MASK 0x00000004L
+#define GDS_DEBUG_REG4__gws_out_stall__SHIFT 0x00000002
+#define GDS_DEBUG_REG4__gws_req_MASK 0x00000002L
+#define GDS_DEBUG_REG4__gws_req__SHIFT 0x00000001
+#define GDS_DEBUG_REG4__ram_gws_re_MASK 0x00400000L
+#define GDS_DEBUG_REG4__ram_gws_re__SHIFT 0x00000016
+#define GDS_DEBUG_REG4__ram_gws_we_MASK 0x00800000L
+#define GDS_DEBUG_REG4__ram_gws_we__SHIFT 0x00000017
+#define GDS_DEBUG_REG4__ram_read_busy_MASK 0x00100000L
+#define GDS_DEBUG_REG4__ram_read_busy__SHIFT 0x00000014
+#define GDS_DEBUG_REG4__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG4__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG5__alloc_opco_error_MASK 0x00000004L
+#define GDS_DEBUG_REG5__alloc_opco_error__SHIFT 0x00000002
+#define GDS_DEBUG_REG5__dealloc_opco_error_MASK 0x00000008L
+#define GDS_DEBUG_REG5__dealloc_opco_error__SHIFT 0x00000003
+#define GDS_DEBUG_REG5__dec_error_MASK 0x00000002L
+#define GDS_DEBUG_REG5__dec_error__SHIFT 0x00000001
+#define GDS_DEBUG_REG5__error_ds_address_MASK 0x003fff00L
+#define GDS_DEBUG_REG5__error_ds_address__SHIFT 0x00000008
+#define GDS_DEBUG_REG5__spare1_MASK 0xffc00000L
+#define GDS_DEBUG_REG5__spare1__SHIFT 0x00000016
+#define GDS_DEBUG_REG5__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG5__spare__SHIFT 0x00000018
+#define GDS_DEBUG_REG5__wrap_opco_error_MASK 0x00000010L
+#define GDS_DEBUG_REG5__wrap_opco_error__SHIFT 0x00000004
+#define GDS_DEBUG_REG5__write_dis_MASK 0x00000001L
+#define GDS_DEBUG_REG5__write_dis__SHIFT 0x00000000
+#define GDS_DEBUG_REG6__counters_busy_MASK 0x001fffe0L
+#define GDS_DEBUG_REG6__counters_busy__SHIFT 0x00000005
+#define GDS_DEBUG_REG6__counters_enabled_MASK 0x0000001eL
+#define GDS_DEBUG_REG6__counters_enabled__SHIFT 0x00000001
+#define GDS_DEBUG_REG6__oa_busy_MASK 0x00000001L
+#define GDS_DEBUG_REG6__oa_busy__SHIFT 0x00000000
+#define GDS_DEBUG_REG6__spare_MASK 0xff000000L
+#define GDS_DEBUG_REG6__spare__SHIFT 0x00000018
+#define GDS_ENHANCE__AUTO_INC_INDEX_MASK 0x00010000L
+#define GDS_ENHANCE__AUTO_INC_INDEX__SHIFT 0x00000010
+#define GDS_ENHANCE__MISC_MASK 0x0000ffffL
+#define GDS_ENHANCE__MISC__SHIFT 0x00000000
+#define GDS_ENHANCE__UNUSED_MASK 0xffff0000L
+#define GDS_ENHANCE__UNUSED__SHIFT 0x00000010
+#define GDS_GRBM_SECDED_CNT__DED_MASK 0xffff0000L
+#define GDS_GRBM_SECDED_CNT__DED__SHIFT 0x00000010
+#define GDS_GRBM_SECDED_CNT__SEC_MASK 0x0000ffffL
+#define GDS_GRBM_SECDED_CNT__SEC__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_CNTL__INDEX_MASK 0x0000003fL
+#define GDS_GWS_RESOURCE_CNTL__INDEX__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_CNTL__UNUSED_MASK 0xffffffc0L
+#define GDS_GWS_RESOURCE_CNTL__UNUSED__SHIFT 0x00000006
+#define GDS_GWS_RESOURCE_CNT__RESOURCE_CNT_MASK 0x0000ffffL
+#define GDS_GWS_RESOURCE_CNT__RESOURCE_CNT__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_CNT__UNUSED_MASK 0xffff0000L
+#define GDS_GWS_RESOURCE_CNT__UNUSED__SHIFT 0x00000010
+#define GDS_GWS_RESOURCE__COUNTER_MASK 0x00001ffeL
+#define GDS_GWS_RESOURCE__COUNTER__SHIFT 0x00000001
+#define GDS_GWS_RESOURCE__DED_MASK 0x00004000L
+#define GDS_GWS_RESOURCE__DED__SHIFT 0x0000000e
+#define GDS_GWS_RESOURCE__FLAG_MASK 0x00000001L
+#define GDS_GWS_RESOURCE__FLAG__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE__HEAD_FLAG_MASK 0x10000000L
+#define GDS_GWS_RESOURCE__HEAD_FLAG__SHIFT 0x0000001c
+#define GDS_GWS_RESOURCE__HEAD_QUEUE_MASK 0x07ff0000L
+#define GDS_GWS_RESOURCE__HEAD_QUEUE__SHIFT 0x00000010
+#define GDS_GWS_RESOURCE__HEAD_VALID_MASK 0x08000000L
+#define GDS_GWS_RESOURCE__HEAD_VALID__SHIFT 0x0000001b
+#define GDS_GWS_RESOURCE__RELEASE_ALL_MASK 0x00008000L
+#define GDS_GWS_RESOURCE__RELEASE_ALL__SHIFT 0x0000000f
+#define GDS_GWS_RESOURCE_RESET__RESET_MASK 0x00000001L
+#define GDS_GWS_RESOURCE_RESET__RESET__SHIFT 0x00000000
+#define GDS_GWS_RESOURCE_RESET__RESOURCE_ID_MASK 0x0000ff00L
+#define GDS_GWS_RESOURCE_RESET__RESOURCE_ID__SHIFT 0x00000008
+#define GDS_GWS_RESOURCE__TYPE_MASK 0x00002000L
+#define GDS_GWS_RESOURCE__TYPE__SHIFT 0x0000000d
+#define GDS_GWS_RESOURCE__UNUSED1_MASK 0xe0000000L
+#define GDS_GWS_RESOURCE__UNUSED1__SHIFT 0x0000001d
+#define GDS_OA_DED__ME0_CS_DED_MASK 0x00000004L
+#define GDS_OA_DED__ME0_CS_DED__SHIFT 0x00000002
+#define GDS_OA_DED__ME0_GFXHP3D_PIX_DED_MASK 0x00000001L
+#define GDS_OA_DED__ME0_GFXHP3D_PIX_DED__SHIFT 0x00000000
+#define GDS_OA_DED__ME0_GFXHP3D_VTX_DED_MASK 0x00000002L
+#define GDS_OA_DED__ME0_GFXHP3D_VTX_DED__SHIFT 0x00000001
+#define GDS_OA_DED__ME1_PIPE0_DED_MASK 0x00000010L
+#define GDS_OA_DED__ME1_PIPE0_DED__SHIFT 0x00000004
+#define GDS_OA_DED__ME1_PIPE1_DED_MASK 0x00000020L
+#define GDS_OA_DED__ME1_PIPE1_DED__SHIFT 0x00000005
+#define GDS_OA_DED__ME1_PIPE2_DED_MASK 0x00000040L
+#define GDS_OA_DED__ME1_PIPE2_DED__SHIFT 0x00000006
+#define GDS_OA_DED__ME1_PIPE3_DED_MASK 0x00000080L
+#define GDS_OA_DED__ME1_PIPE3_DED__SHIFT 0x00000007
+#define GDS_OA_DED__ME2_PIPE0_DED_MASK 0x00000100L
+#define GDS_OA_DED__ME2_PIPE0_DED__SHIFT 0x00000008
+#define GDS_OA_DED__ME2_PIPE1_DED_MASK 0x00000200L
+#define GDS_OA_DED__ME2_PIPE1_DED__SHIFT 0x00000009
+#define GDS_OA_DED__ME2_PIPE2_DED_MASK 0x00000400L
+#define GDS_OA_DED__ME2_PIPE2_DED__SHIFT 0x0000000a
+#define GDS_OA_DED__ME2_PIPE3_DED_MASK 0x00000800L
+#define GDS_OA_DED__ME2_PIPE3_DED__SHIFT 0x0000000b
+#define GDS_OA_DED__UNUSED0_MASK 0x00000008L
+#define GDS_OA_DED__UNUSED0__SHIFT 0x00000003
+#define GDS_OA_DED__UNUSED1_MASK 0xfffff000L
+#define GDS_OA_DED__UNUSED1__SHIFT 0x0000000c
+#define GDS_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2_MASK 0x000003ffL
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x00000000
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GDS_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GDS_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GDS_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GDS_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define GDS_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define GDS_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define GDS_RD_ADDR__READ_ADDR_MASK 0xffffffffL
+#define GDS_RD_ADDR__READ_ADDR__SHIFT 0x00000000
+#define GDS_RD_BURST_ADDR__BURST_ADDR_MASK 0xffffffffL
+#define GDS_RD_BURST_ADDR__BURST_ADDR__SHIFT 0x00000000
+#define GDS_RD_BURST_COUNT__BURST_COUNT_MASK 0xffffffffL
+#define GDS_RD_BURST_COUNT__BURST_COUNT__SHIFT 0x00000000
+#define GDS_RD_BURST_DATA__BURST_DATA_MASK 0xffffffffL
+#define GDS_RD_BURST_DATA__BURST_DATA__SHIFT 0x00000000
+#define GDS_RD_DATA__READ_DATA_MASK 0xffffffffL
+#define GDS_RD_DATA__READ_DATA__SHIFT 0x00000000
+#define GDS_SECDED_CNT__DED_MASK 0xffff0000L
+#define GDS_SECDED_CNT__DED__SHIFT 0x00000010
+#define GDS_SECDED_CNT__SEC_MASK 0x0000ffffL
+#define GDS_SECDED_CNT__SEC__SHIFT 0x00000000
+#define GDS_WR_ADDR__WRITE_ADDR_MASK 0xffffffffL
+#define GDS_WR_ADDR__WRITE_ADDR__SHIFT 0x00000000
+#define GDS_WR_BURST_ADDR__WRITE_ADDR_MASK 0xffffffffL
+#define GDS_WR_BURST_ADDR__WRITE_ADDR__SHIFT 0x00000000
+#define GDS_WR_BURST_DATA__WRITE_DATA_MASK 0xffffffffL
+#define GDS_WR_BURST_DATA__WRITE_DATA__SHIFT 0x00000000
+#define GDS_WR_DATA__WRITE_DATA_MASK 0xffffffffL
+#define GDS_WR_DATA__WRITE_DATA__SHIFT 0x00000000
+#define GDS_WRITE_COMPLETE__WRITE_COMPLETE_MASK 0xffffffffL
+#define GDS_WRITE_COMPLETE__WRITE_COMPLETE__SHIFT 0x00000000
+#define GFX_COPY_STATE__SRC_STATE_ID_MASK 0x00000007L
+#define GFX_COPY_STATE__SRC_STATE_ID__SHIFT 0x00000000
+#define GRBM_CAM_DATA__CAM_ADDR_MASK 0x0000ffffL
+#define GRBM_CAM_DATA__CAM_ADDR__SHIFT 0x00000000
+#define GRBM_CAM_DATA__CAM_REMAPADDR_MASK 0xffff0000L
+#define GRBM_CAM_DATA__CAM_REMAPADDR__SHIFT 0x00000010
+#define GRBM_CAM_INDEX__CAM_INDEX_MASK 0x00000007L
+#define GRBM_CAM_INDEX__CAM_INDEX__SHIFT 0x00000000
+#define GRBM_CNTL__READ_TIMEOUT_MASK 0x000000ffL
+#define GRBM_CNTL__READ_TIMEOUT__SHIFT 0x00000000
+#define GRBM_DEBUG_CNTL__GRBM_DEBUG_INDEX_MASK 0x0000003fL
+#define GRBM_DEBUG_CNTL__GRBM_DEBUG_INDEX__SHIFT 0x00000000
+#define GRBM_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define GRBM_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define GRBM_DEBUG__DISABLE_READ_TIMEOUT_MASK 0x00000040L
+#define GRBM_DEBUG__DISABLE_READ_TIMEOUT__SHIFT 0x00000006
+#define GRBM_DEBUG__GFX_CLOCK_DOMAIN_OVERRIDE_MASK 0x00001000L
+#define GRBM_DEBUG__GFX_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x0000000c
+#define GRBM_DEBUG__HYSTERESIS_GUI_ACTIVE_MASK 0x00000f00L
+#define GRBM_DEBUG__HYSTERESIS_GUI_ACTIVE__SHIFT 0x00000008
+#define GRBM_DEBUG__IGNORE_FAO_MASK 0x00000020L
+#define GRBM_DEBUG__IGNORE_FAO__SHIFT 0x00000005
+#define GRBM_DEBUG__IGNORE_RDY_MASK 0x00000002L
+#define GRBM_DEBUG__IGNORE_RDY__SHIFT 0x00000001
+#define GRBM_DEBUG_SNAPSHOT__CPF_RDY_MASK 0x00000001L
+#define GRBM_DEBUG_SNAPSHOT__CPF_RDY__SHIFT 0x00000000
+#define GRBM_DEBUG_SNAPSHOT__CPG_RDY_MASK 0x00000002L
+#define GRBM_DEBUG_SNAPSHOT__CPG_RDY__SHIFT 0x00000001
+#define GRBM_DEBUG__SNAPSHOT_FREE_CNTRS_MASK 0x00000080L
+#define GRBM_DEBUG__SNAPSHOT_FREE_CNTRS__SHIFT 0x00000007
+#define GRBM_DEBUG_SNAPSHOT__GDS_RDY_MASK 0x00000200L
+#define GRBM_DEBUG_SNAPSHOT__GDS_RDY__SHIFT 0x00000009
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY0_MASK 0x00000040L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY0__SHIFT 0x00000006
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY1_MASK 0x00004000L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE0_RDY1__SHIFT 0x0000000e
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY0_MASK 0x00000080L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY0__SHIFT 0x00000007
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY1_MASK 0x00008000L
+#define GRBM_DEBUG_SNAPSHOT__SE0SPI_ME0PIPE1_RDY1__SHIFT 0x0000000f
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY0_MASK 0x00000100L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY0__SHIFT 0x00000008
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY1_MASK 0x00010000L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE0_RDY1__SHIFT 0x00000010
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY0_MASK 0x00000200L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY0__SHIFT 0x00000009
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY1_MASK 0x00020000L
+#define GRBM_DEBUG_SNAPSHOT__SE1SPI_ME0PIPE1_RDY1__SHIFT 0x00000011
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY0_MASK 0x00000400L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY0__SHIFT 0x0000000a
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY1_MASK 0x00040000L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE0_RDY1__SHIFT 0x00000012
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY0_MASK 0x00000800L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY0__SHIFT 0x0000000b
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY1_MASK 0x00080000L
+#define GRBM_DEBUG_SNAPSHOT__SE2SPI_ME0PIPE1_RDY1__SHIFT 0x00000013
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY0_MASK 0x00001000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY0__SHIFT 0x0000000c
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY1_MASK 0x00100000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE0_RDY1__SHIFT 0x00000014
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY0_MASK 0x00002000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY0__SHIFT 0x0000000d
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY1_MASK 0x00200000L
+#define GRBM_DEBUG_SNAPSHOT__SE3SPI_ME0PIPE1_RDY1__SHIFT 0x00000015
+#define GRBM_DEBUG_SNAPSHOT__SRBM_RDY_MASK 0x00000002L
+#define GRBM_DEBUG_SNAPSHOT__SRBM_RDY__SHIFT 0x00000001
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE0_RDY_MASK 0x00000008L
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE0_RDY__SHIFT 0x00000003
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE1_RDY_MASK 0x00000010L
+#define GRBM_DEBUG_SNAPSHOT__WD_ME0PIPE1_RDY__SHIFT 0x00000004
+#define GRBM_GFX_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define GRBM_GFX_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define GRBM_GFX_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define GRBM_GFX_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK 0x40000000L
+#define GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES__SHIFT 0x0000001e
+#define GRBM_GFX_INDEX__INSTANCE_INDEX_MASK 0x000000ffL
+#define GRBM_GFX_INDEX__INSTANCE_INDEX__SHIFT 0x00000000
+#define GRBM_GFX_INDEX__SE_BROADCAST_WRITES_MASK 0x80000000L
+#define GRBM_GFX_INDEX__SE_BROADCAST_WRITES__SHIFT 0x0000001f
+#define GRBM_GFX_INDEX__SE_INDEX_MASK 0x00ff0000L
+#define GRBM_GFX_INDEX__SE_INDEX__SHIFT 0x00000010
+#define GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK 0x20000000L
+#define GRBM_GFX_INDEX__SH_BROADCAST_WRITES__SHIFT 0x0000001d
+#define GRBM_GFX_INDEX__SH_INDEX_MASK 0x0000ff00L
+#define GRBM_GFX_INDEX__SH_INDEX__SHIFT 0x00000008
+#define GRBM_INT_CNTL__GUI_IDLE_INT_ENABLE_MASK 0x00080000L
+#define GRBM_INT_CNTL__GUI_IDLE_INT_ENABLE__SHIFT 0x00000013
+#define GRBM_INT_CNTL__RDERR_INT_ENABLE_MASK 0x00000001L
+#define GRBM_INT_CNTL__RDERR_INT_ENABLE__SHIFT 0x00000000
+#define GRBM_NOWHERE__DATA_MASK 0xffffffffL
+#define GRBM_NOWHERE__DATA__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x02000000L
+#define GRBM_PERFCOUNTER0_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000019
+#define GRBM_PERFCOUNTER0_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_PERFCOUNTER0_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_PERFCOUNTER0_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_PERFCOUNTER0_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_PERFCOUNTER0_SELECT__CP_BUSY_USER_DEFINED_MASK_MASK 0x00400000L
+#define GRBM_PERFCOUNTER0_SELECT__CP_BUSY_USER_DEFINED_MASK__SHIFT 0x00000016
+#define GRBM_PERFCOUNTER0_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_PERFCOUNTER0_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_PERFCOUNTER0_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_PERFCOUNTER0_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_PERFCOUNTER0_SELECT__GDS_BUSY_USER_DEFINED_MASK_MASK 0x01000000L
+#define GRBM_PERFCOUNTER0_SELECT__GDS_BUSY_USER_DEFINED_MASK__SHIFT 0x00000018
+#define GRBM_PERFCOUNTER0_SELECT__GRBM_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_PERFCOUNTER0_SELECT__GRBM_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_PERFCOUNTER0_SELECT__IA_BUSY_USER_DEFINED_MASK_MASK 0x00800000L
+#define GRBM_PERFCOUNTER0_SELECT__IA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000017
+#define GRBM_PERFCOUNTER0_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_PERFCOUNTER0_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER0_SELECT__RLC_BUSY_USER_DEFINED_MASK_MASK 0x04000000L
+#define GRBM_PERFCOUNTER0_SELECT__RLC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001a
+#define GRBM_PERFCOUNTER0_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_PERFCOUNTER0_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_PERFCOUNTER0_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_PERFCOUNTER0_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_PERFCOUNTER0_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00004000L
+#define GRBM_PERFCOUNTER0_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000e
+#define GRBM_PERFCOUNTER0_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_PERFCOUNTER0_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_PERFCOUNTER0_SELECT__TC_BUSY_USER_DEFINED_MASK_MASK 0x08000000L
+#define GRBM_PERFCOUNTER0_SELECT__TC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001b
+#define GRBM_PERFCOUNTER0_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_PERFCOUNTER0_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_PERFCOUNTER0_SELECT__WD_BUSY_USER_DEFINED_MASK_MASK 0x10000000L
+#define GRBM_PERFCOUNTER0_SELECT__WD_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001c
+#define GRBM_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER1_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x02000000L
+#define GRBM_PERFCOUNTER1_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000019
+#define GRBM_PERFCOUNTER1_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_PERFCOUNTER1_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_PERFCOUNTER1_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_PERFCOUNTER1_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_PERFCOUNTER1_SELECT__CP_BUSY_USER_DEFINED_MASK_MASK 0x00400000L
+#define GRBM_PERFCOUNTER1_SELECT__CP_BUSY_USER_DEFINED_MASK__SHIFT 0x00000016
+#define GRBM_PERFCOUNTER1_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_PERFCOUNTER1_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_PERFCOUNTER1_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_PERFCOUNTER1_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_PERFCOUNTER1_SELECT__GDS_BUSY_USER_DEFINED_MASK_MASK 0x01000000L
+#define GRBM_PERFCOUNTER1_SELECT__GDS_BUSY_USER_DEFINED_MASK__SHIFT 0x00000018
+#define GRBM_PERFCOUNTER1_SELECT__GRBM_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_PERFCOUNTER1_SELECT__GRBM_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_PERFCOUNTER1_SELECT__IA_BUSY_USER_DEFINED_MASK_MASK 0x00800000L
+#define GRBM_PERFCOUNTER1_SELECT__IA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000017
+#define GRBM_PERFCOUNTER1_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_PERFCOUNTER1_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_PERFCOUNTER1_SELECT__RLC_BUSY_USER_DEFINED_MASK_MASK 0x04000000L
+#define GRBM_PERFCOUNTER1_SELECT__RLC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001a
+#define GRBM_PERFCOUNTER1_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_PERFCOUNTER1_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_PERFCOUNTER1_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_PERFCOUNTER1_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_PERFCOUNTER1_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00004000L
+#define GRBM_PERFCOUNTER1_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000e
+#define GRBM_PERFCOUNTER1_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_PERFCOUNTER1_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_PERFCOUNTER1_SELECT__TC_BUSY_USER_DEFINED_MASK_MASK 0x08000000L
+#define GRBM_PERFCOUNTER1_SELECT__TC_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001b
+#define GRBM_PERFCOUNTER1_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_PERFCOUNTER1_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_PERFCOUNTER1_SELECT__WD_BUSY_USER_DEFINED_MASK_MASK 0x10000000L
+#define GRBM_PERFCOUNTER1_SELECT__WD_BUSY_USER_DEFINED_MASK__SHIFT 0x0000001c
+#define GRBM_PWR_CNTL__REQ_TYPE_MASK 0x0000000fL
+#define GRBM_PWR_CNTL__REQ_TYPE__SHIFT 0x00000000
+#define GRBM_PWR_CNTL__RSP_TYPE_MASK 0x000000f0L
+#define GRBM_PWR_CNTL__RSP_TYPE__SHIFT 0x00000004
+#define GRBM_READ_ERROR2__READ_REQUESTER_GDS_DMA_MASK 0x00080000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_GDS_DMA__SHIFT 0x00000013
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_CF_MASK 0x00100000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_CF__SHIFT 0x00000014
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_PF_MASK 0x00200000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE0_PF__SHIFT 0x00000015
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_CF_MASK 0x00400000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_CF__SHIFT 0x00000016
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_PF_MASK 0x00800000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME0PIPE1_PF__SHIFT 0x00000017
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE0_MASK 0x01000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE0__SHIFT 0x00000018
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE1_MASK 0x02000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE1__SHIFT 0x00000019
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE2_MASK 0x04000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE2__SHIFT 0x0000001a
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE3_MASK 0x08000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME1PIPE3__SHIFT 0x0000001b
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE0_MASK 0x10000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE0__SHIFT 0x0000001c
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE1_MASK 0x20000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE1__SHIFT 0x0000001d
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE2_MASK 0x40000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE2__SHIFT 0x0000001e
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE3_MASK 0x80000000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_ME2PIPE3__SHIFT 0x0000001f
+#define GRBM_READ_ERROR2__READ_REQUESTER_RLC_MASK 0x00040000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_RLC__SHIFT 0x00000012
+#define GRBM_READ_ERROR2__READ_REQUESTER_SRBM_MASK 0x00020000L
+#define GRBM_READ_ERROR2__READ_REQUESTER_SRBM__SHIFT 0x00000011
+#define GRBM_READ_ERROR__READ_ADDRESS_MASK 0x0003fffcL
+#define GRBM_READ_ERROR__READ_ADDRESS__SHIFT 0x00000002
+#define GRBM_READ_ERROR__READ_ERROR_MASK 0x80000000L
+#define GRBM_READ_ERROR__READ_ERROR__SHIFT 0x0000001f
+#define GRBM_READ_ERROR__READ_MEID_MASK 0x00c00000L
+#define GRBM_READ_ERROR__READ_MEID__SHIFT 0x00000016
+#define GRBM_READ_ERROR__READ_PIPEID_MASK 0x00300000L
+#define GRBM_READ_ERROR__READ_PIPEID__SHIFT 0x00000014
+#define GRBM_SCRATCH_REG0__SCRATCH_REG0_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG0__SCRATCH_REG0__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG1__SCRATCH_REG1_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG1__SCRATCH_REG1__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG2__SCRATCH_REG2_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG2__SCRATCH_REG2__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG3__SCRATCH_REG3_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG3__SCRATCH_REG3__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG4__SCRATCH_REG4_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG4__SCRATCH_REG4__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG5__SCRATCH_REG5_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG5__SCRATCH_REG5__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG6__SCRATCH_REG6_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG6__SCRATCH_REG6__SHIFT 0x00000000
+#define GRBM_SCRATCH_REG7__SCRATCH_REG7_MASK 0xffffffffL
+#define GRBM_SCRATCH_REG7__SCRATCH_REG7__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_SE0_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_SE0_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_SE0_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_SE0_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_SE0_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_SE0_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_SE0_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_SE0_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_SE0_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00008000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000f
+#define GRBM_SE0_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_SE0_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_SE0_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_SE0_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_SE1_PERFCOUNTER_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define GRBM_SE1_PERFCOUNTER_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define GRBM_SE1_PERFCOUNTER_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define GRBM_SE1_PERFCOUNTER_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define GRBM_SE1_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK_MASK 0x00200000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__BCI_BUSY_USER_DEFINED_MASK__SHIFT 0x00000015
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK_MASK 0x00040000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000012
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK_MASK 0x00000800L
+#define GRBM_SE1_PERFCOUNTER_SELECT__CB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000b
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK_MASK 0x00020000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_BUSY_USER_DEFINED_MASK__SHIFT 0x00000011
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK_MASK 0x00000400L
+#define GRBM_SE1_PERFCOUNTER_SELECT__DB_CLEAN_USER_DEFINED_MASK__SHIFT 0x0000000a
+#define GRBM_SE1_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK_MASK 0x00100000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__PA_BUSY_USER_DEFINED_MASK__SHIFT 0x00000014
+#define GRBM_SE1_PERFCOUNTER_SELECT__PERF_SEL_MASK 0x0000003fL
+#define GRBM_SE1_PERFCOUNTER_SELECT__PERF_SEL__SHIFT 0x00000000
+#define GRBM_SE1_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK_MASK 0x00010000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__SC_BUSY_USER_DEFINED_MASK__SHIFT 0x00000010
+#define GRBM_SE1_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK_MASK 0x00008000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__SPI_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000f
+#define GRBM_SE1_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK_MASK 0x00002000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__SX_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000d
+#define GRBM_SE1_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK_MASK 0x00001000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__TA_BUSY_USER_DEFINED_MASK__SHIFT 0x0000000c
+#define GRBM_SE1_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK_MASK 0x00080000L
+#define GRBM_SE1_PERFCOUNTER_SELECT__VGT_BUSY_USER_DEFINED_MASK__SHIFT 0x00000013
+#define GRBM_SKEW_CNTL__SKEW_COUNT_MASK 0x00000fc0L
+#define GRBM_SKEW_CNTL__SKEW_COUNT__SHIFT 0x00000006
+#define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD_MASK 0x0000003fL
+#define GRBM_SKEW_CNTL__SKEW_TOP_THRESHOLD__SHIFT 0x00000000
+#define GRBM_SOFT_RESET__SOFT_RESET_CPC_MASK 0x00040000L
+#define GRBM_SOFT_RESET__SOFT_RESET_CPC__SHIFT 0x00000012
+#define GRBM_SOFT_RESET__SOFT_RESET_CPF_MASK 0x00020000L
+#define GRBM_SOFT_RESET__SOFT_RESET_CPF__SHIFT 0x00000011
+#define GRBM_SOFT_RESET__SOFT_RESET_CPG_MASK 0x00080000L
+#define GRBM_SOFT_RESET__SOFT_RESET_CPG__SHIFT 0x00000013
+#define GRBM_SOFT_RESET__SOFT_RESET_CP_MASK 0x00000001L
+#define GRBM_SOFT_RESET__SOFT_RESET_CP__SHIFT 0x00000000
+#define GRBM_SOFT_RESET__SOFT_RESET_GFX_MASK 0x00010000L
+#define GRBM_SOFT_RESET__SOFT_RESET_GFX__SHIFT 0x00000010
+#define GRBM_SOFT_RESET__SOFT_RESET_RLC_MASK 0x00000004L
+#define GRBM_SOFT_RESET__SOFT_RESET_RLC__SHIFT 0x00000002
+#define GRBM_STATUS2__CPC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS2__CPC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS2__CPF_BUSY_MASK 0x10000000L
+#define GRBM_STATUS2__CPF_BUSY__SHIFT 0x0000001c
+#define GRBM_STATUS2__CPG_BUSY_MASK 0x40000000L
+#define GRBM_STATUS2__CPG_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS2__ME0PIPE1_CF_RQ_PENDING_MASK 0x00000010L
+#define GRBM_STATUS2__ME0PIPE1_CF_RQ_PENDING__SHIFT 0x00000004
+#define GRBM_STATUS2__ME0PIPE1_CMDFIFO_AVAIL_MASK 0x0000000fL
+#define GRBM_STATUS2__ME0PIPE1_CMDFIFO_AVAIL__SHIFT 0x00000000
+#define GRBM_STATUS2__ME0PIPE1_PF_RQ_PENDING_MASK 0x00000020L
+#define GRBM_STATUS2__ME0PIPE1_PF_RQ_PENDING__SHIFT 0x00000005
+#define GRBM_STATUS2__ME1PIPE0_RQ_PENDING_MASK 0x00000040L
+#define GRBM_STATUS2__ME1PIPE0_RQ_PENDING__SHIFT 0x00000006
+#define GRBM_STATUS2__ME1PIPE1_RQ_PENDING_MASK 0x00000080L
+#define GRBM_STATUS2__ME1PIPE1_RQ_PENDING__SHIFT 0x00000007
+#define GRBM_STATUS2__ME1PIPE2_RQ_PENDING_MASK 0x00000100L
+#define GRBM_STATUS2__ME1PIPE2_RQ_PENDING__SHIFT 0x00000008
+#define GRBM_STATUS2__ME1PIPE3_RQ_PENDING_MASK 0x00000200L
+#define GRBM_STATUS2__ME1PIPE3_RQ_PENDING__SHIFT 0x00000009
+#define GRBM_STATUS2__ME2PIPE0_RQ_PENDING_MASK 0x00000400L
+#define GRBM_STATUS2__ME2PIPE0_RQ_PENDING__SHIFT 0x0000000a
+#define GRBM_STATUS2__ME2PIPE1_RQ_PENDING_MASK 0x00000800L
+#define GRBM_STATUS2__ME2PIPE1_RQ_PENDING__SHIFT 0x0000000b
+#define GRBM_STATUS2__ME2PIPE2_RQ_PENDING_MASK 0x00001000L
+#define GRBM_STATUS2__ME2PIPE2_RQ_PENDING__SHIFT 0x0000000c
+#define GRBM_STATUS2__ME2PIPE3_RQ_PENDING_MASK 0x00002000L
+#define GRBM_STATUS2__ME2PIPE3_RQ_PENDING__SHIFT 0x0000000d
+#define GRBM_STATUS2__RLC_BUSY_MASK 0x00000100L
+#define GRBM_STATUS2__RLC_BUSY__SHIFT 0x00000008
+#define GRBM_STATUS2__RLC_RQ_PENDING_MASK 0x00000001L
+#define GRBM_STATUS2__RLC_RQ_PENDING__SHIFT 0x00000000
+#define GRBM_STATUS2__TC_BUSY_MASK 0x00000200L
+#define GRBM_STATUS2__TC_BUSY__SHIFT 0x00000009
+#define GRBM_STATUS__BCI_BUSY_MASK 0x00800000L
+#define GRBM_STATUS__BCI_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS__CB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS__CB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS__CB_CLEAN_MASK 0x00002000L
+#define GRBM_STATUS__CB_CLEAN__SHIFT 0x0000000d
+#define GRBM_STATUS__CP_BUSY_MASK 0x20000000L
+#define GRBM_STATUS__CP_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS__CP_COHERENCY_BUSY_MASK 0x10000000L
+#define GRBM_STATUS__CP_COHERENCY_BUSY__SHIFT 0x0000001c
+#define GRBM_STATUS__DB_BUSY_MASK 0x04000000L
+#define GRBM_STATUS__DB_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS__DB_CLEAN_MASK 0x00001000L
+#define GRBM_STATUS__DB_CLEAN__SHIFT 0x0000000c
+#define GRBM_STATUS__GDS_BUSY_MASK 0x00008000L
+#define GRBM_STATUS__GDS_BUSY__SHIFT 0x0000000f
+#define GRBM_STATUS__GDS_DMA_RQ_PENDING_MASK 0x00000200L
+#define GRBM_STATUS__GDS_DMA_RQ_PENDING__SHIFT 0x00000009
+#define GRBM_STATUS__GUI_ACTIVE_MASK 0x80000000L
+#define GRBM_STATUS__GUI_ACTIVE__SHIFT 0x0000001f
+#define GRBM_STATUS__IA_BUSY_MASK 0x00080000L
+#define GRBM_STATUS__IA_BUSY_NO_DMA_MASK 0x00040000L
+#define GRBM_STATUS__IA_BUSY_NO_DMA__SHIFT 0x00000012
+#define GRBM_STATUS__IA_BUSY__SHIFT 0x00000013
+#define GRBM_STATUS__ME0PIPE0_CF_RQ_PENDING_MASK 0x00000080L
+#define GRBM_STATUS__ME0PIPE0_CF_RQ_PENDING__SHIFT 0x00000007
+#define GRBM_STATUS__ME0PIPE0_CMDFIFO_AVAIL_MASK 0x0000000fL
+#define GRBM_STATUS__ME0PIPE0_CMDFIFO_AVAIL__SHIFT 0x00000000
+#define GRBM_STATUS__ME0PIPE0_PF_RQ_PENDING_MASK 0x00000100L
+#define GRBM_STATUS__ME0PIPE0_PF_RQ_PENDING__SHIFT 0x00000008
+#define GRBM_STATUS__PA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS__PA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS__SC_BUSY_MASK 0x01000000L
+#define GRBM_STATUS__SC_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE0__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE0__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE0__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE0__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE0__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE0__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE0__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE0__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE0__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE0__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE0__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE0__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE0__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE0__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE0__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE0__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE0__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE0__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE0__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE0__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE0__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE0__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS_SE1__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE1__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE1__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE1__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE1__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE1__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE1__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE1__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE1__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE1__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE1__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE1__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE1__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE1__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE1__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE1__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE1__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE1__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE1__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE1__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE1__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE1__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS_SE2__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE2__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE2__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE2__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE2__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE2__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE2__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE2__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE2__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE2__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE2__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE2__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE2__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE2__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE2__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE2__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE2__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE2__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE2__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE2__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE2__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE2__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS_SE3__BCI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS_SE3__BCI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS_SE3__CB_BUSY_MASK 0x80000000L
+#define GRBM_STATUS_SE3__CB_BUSY__SHIFT 0x0000001f
+#define GRBM_STATUS_SE3__CB_CLEAN_MASK 0x00000004L
+#define GRBM_STATUS_SE3__CB_CLEAN__SHIFT 0x00000002
+#define GRBM_STATUS_SE3__DB_BUSY_MASK 0x40000000L
+#define GRBM_STATUS_SE3__DB_BUSY__SHIFT 0x0000001e
+#define GRBM_STATUS_SE3__DB_CLEAN_MASK 0x00000002L
+#define GRBM_STATUS_SE3__DB_CLEAN__SHIFT 0x00000001
+#define GRBM_STATUS_SE3__PA_BUSY_MASK 0x01000000L
+#define GRBM_STATUS_SE3__PA_BUSY__SHIFT 0x00000018
+#define GRBM_STATUS_SE3__SC_BUSY_MASK 0x20000000L
+#define GRBM_STATUS_SE3__SC_BUSY__SHIFT 0x0000001d
+#define GRBM_STATUS_SE3__SPI_BUSY_MASK 0x08000000L
+#define GRBM_STATUS_SE3__SPI_BUSY__SHIFT 0x0000001b
+#define GRBM_STATUS_SE3__SX_BUSY_MASK 0x04000000L
+#define GRBM_STATUS_SE3__SX_BUSY__SHIFT 0x0000001a
+#define GRBM_STATUS_SE3__TA_BUSY_MASK 0x02000000L
+#define GRBM_STATUS_SE3__TA_BUSY__SHIFT 0x00000019
+#define GRBM_STATUS_SE3__VGT_BUSY_MASK 0x00800000L
+#define GRBM_STATUS_SE3__VGT_BUSY__SHIFT 0x00000017
+#define GRBM_STATUS__SPI_BUSY_MASK 0x00400000L
+#define GRBM_STATUS__SPI_BUSY__SHIFT 0x00000016
+#define GRBM_STATUS__SRBM_RQ_PENDING_MASK 0x00000020L
+#define GRBM_STATUS__SRBM_RQ_PENDING__SHIFT 0x00000005
+#define GRBM_STATUS__SX_BUSY_MASK 0x00100000L
+#define GRBM_STATUS__SX_BUSY__SHIFT 0x00000014
+#define GRBM_STATUS__TA_BUSY_MASK 0x00004000L
+#define GRBM_STATUS__TA_BUSY__SHIFT 0x0000000e
+#define GRBM_STATUS__VGT_BUSY_MASK 0x00020000L
+#define GRBM_STATUS__VGT_BUSY__SHIFT 0x00000011
+#define GRBM_STATUS__WD_BUSY_MASK 0x00200000L
+#define GRBM_STATUS__WD_BUSY_NO_DMA_MASK 0x00010000L
+#define GRBM_STATUS__WD_BUSY_NO_DMA__SHIFT 0x00000010
+#define GRBM_STATUS__WD_BUSY__SHIFT 0x00000015
+#define GRBM_WAIT_IDLE_CLOCKS__WAIT_IDLE_CLOCKS_MASK 0x000000ffL
+#define GRBM_WAIT_IDLE_CLOCKS__WAIT_IDLE_CLOCKS__SHIFT 0x00000000
+#define IA_CNTL_STATUS__IA_ADC_BUSY_MASK 0x00000010L
+#define IA_CNTL_STATUS__IA_ADC_BUSY__SHIFT 0x00000004
+#define IA_CNTL_STATUS__IA_BUSY_MASK 0x00000001L
+#define IA_CNTL_STATUS__IA_BUSY__SHIFT 0x00000000
+#define IA_CNTL_STATUS__IA_DMA_BUSY_MASK 0x00000002L
+#define IA_CNTL_STATUS__IA_DMA_BUSY__SHIFT 0x00000001
+#define IA_CNTL_STATUS__IA_DMA_REQ_BUSY_MASK 0x00000004L
+#define IA_CNTL_STATUS__IA_DMA_REQ_BUSY__SHIFT 0x00000002
+#define IA_CNTL_STATUS__IA_GRP_BUSY_MASK 0x00000008L
+#define IA_CNTL_STATUS__IA_GRP_BUSY__SHIFT 0x00000003
+#define IA_DEBUG_CNTL__IA_DEBUG_INDX_MASK 0x0000003fL
+#define IA_DEBUG_CNTL__IA_DEBUG_INDX__SHIFT 0x00000000
+#define IA_DEBUG_CNTL__IA_DEBUG_SEL_BUS_B_MASK 0x00000040L
+#define IA_DEBUG_CNTL__IA_DEBUG_SEL_BUS_B__SHIFT 0x00000006
+#define IA_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define IA_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define IA_DEBUG_REG0__core_clk_busy_MASK 0x04000000L
+#define IA_DEBUG_REG0__core_clk_busy__SHIFT 0x0000001a
+#define IA_DEBUG_REG0__dma_busy_MASK 0x00000040L
+#define IA_DEBUG_REG0__dma_busy__SHIFT 0x00000006
+#define IA_DEBUG_REG0__dma_grp_hp_valid_MASK 0x00001000L
+#define IA_DEBUG_REG0__dma_grp_hp_valid__SHIFT 0x0000000c
+#define IA_DEBUG_REG0__dma_grp_valid_MASK 0x00000400L
+#define IA_DEBUG_REG0__dma_grp_valid__SHIFT 0x0000000a
+#define IA_DEBUG_REG0__dma_req_busy_MASK 0x00000020L
+#define IA_DEBUG_REG0__dma_req_busy__SHIFT 0x00000005
+#define IA_DEBUG_REG0__grp_busy_MASK 0x00000100L
+#define IA_DEBUG_REG0__grp_busy__SHIFT 0x00000008
+#define IA_DEBUG_REG0__grp_dma_hp_read_MASK 0x00002000L
+#define IA_DEBUG_REG0__grp_dma_hp_read__SHIFT 0x0000000d
+#define IA_DEBUG_REG0__grp_dma_read_MASK 0x00000800L
+#define IA_DEBUG_REG0__grp_dma_read__SHIFT 0x0000000b
+#define IA_DEBUG_REG0__ia_busy_extended_MASK 0x00000001L
+#define IA_DEBUG_REG0__ia_busy_extended__SHIFT 0x00000000
+#define IA_DEBUG_REG0__ia_busy_MASK 0x00000004L
+#define IA_DEBUG_REG0__ia_busy__SHIFT 0x00000002
+#define IA_DEBUG_REG0__ia_nodma_busy_extended_MASK 0x00000002L
+#define IA_DEBUG_REG0__ia_nodma_busy_extended__SHIFT 0x00000001
+#define IA_DEBUG_REG0__ia_nodma_busy_MASK 0x00000008L
+#define IA_DEBUG_REG0__ia_nodma_busy__SHIFT 0x00000003
+#define IA_DEBUG_REG0__mc_xl8r_busy_MASK 0x00000080L
+#define IA_DEBUG_REG0__mc_xl8r_busy__SHIFT 0x00000007
+#define IA_DEBUG_REG0__reg_clk_busy_MASK 0x01000000L
+#define IA_DEBUG_REG0__reg_clk_busy__SHIFT 0x00000018
+#define IA_DEBUG_REG0__sclk_core_vld_MASK 0x20000000L
+#define IA_DEBUG_REG0__sclk_core_vld__SHIFT 0x0000001d
+#define IA_DEBUG_REG0__sclk_reg_vld_MASK 0x10000000L
+#define IA_DEBUG_REG0__sclk_reg_vld__SHIFT 0x0000001c
+#define IA_DEBUG_REG0__SPARE0_MASK 0x00000010L
+#define IA_DEBUG_REG0__SPARE0__SHIFT 0x00000004
+#define IA_DEBUG_REG0__SPARE1_MASK 0x00000200L
+#define IA_DEBUG_REG0__SPARE1__SHIFT 0x00000009
+#define IA_DEBUG_REG0__SPARE2_MASK 0x00ffc000L
+#define IA_DEBUG_REG0__SPARE2__SHIFT 0x0000000e
+#define IA_DEBUG_REG0__SPARE3_MASK 0x00100000L
+#define IA_DEBUG_REG0__SPARE3__SHIFT 0x00000014
+#define IA_DEBUG_REG0__SPARE4_MASK 0x08000000L
+#define IA_DEBUG_REG0__SPARE4__SHIFT 0x0000001b
+#define IA_DEBUG_REG0__SPARE5_MASK 0x40000000L
+#define IA_DEBUG_REG0__SPARE5__SHIFT 0x0000001e
+#define IA_DEBUG_REG0__SPARE6_MASK 0x80000000L
+#define IA_DEBUG_REG0__SPARE6__SHIFT 0x0000001f
+#define IA_DEBUG_REG1__current_data_valid_MASK 0x10000000L
+#define IA_DEBUG_REG1__current_data_valid__SHIFT 0x0000001c
+#define IA_DEBUG_REG1__discard_1st_chunk_MASK 0x00000100L
+#define IA_DEBUG_REG1__discard_1st_chunk__SHIFT 0x00000008
+#define IA_DEBUG_REG1__discard_2nd_chunk_MASK 0x00000200L
+#define IA_DEBUG_REG1__discard_2nd_chunk__SHIFT 0x00000009
+#define IA_DEBUG_REG1__dma_buf_type_q_MASK 0x00000060L
+#define IA_DEBUG_REG1__dma_buf_type_q__SHIFT 0x00000005
+#define IA_DEBUG_REG1__dma_data_fifo_empty_q_MASK 0x00004000L
+#define IA_DEBUG_REG1__dma_data_fifo_empty_q__SHIFT 0x0000000e
+#define IA_DEBUG_REG1__dma_data_fifo_full_MASK 0x00008000L
+#define IA_DEBUG_REG1__dma_data_fifo_full__SHIFT 0x0000000f
+#define IA_DEBUG_REG1__dma_grp_valid_MASK 0x04000000L
+#define IA_DEBUG_REG1__dma_grp_valid__SHIFT 0x0000001a
+#define IA_DEBUG_REG1__dma_input_fifo_empty_MASK 0x00000001L
+#define IA_DEBUG_REG1__dma_input_fifo_empty__SHIFT 0x00000000
+#define IA_DEBUG_REG1__dma_input_fifo_full_MASK 0x00000002L
+#define IA_DEBUG_REG1__dma_input_fifo_full__SHIFT 0x00000001
+#define IA_DEBUG_REG1__dma_mask_fifo_empty_MASK 0x00002000L
+#define IA_DEBUG_REG1__dma_mask_fifo_empty__SHIFT 0x0000000d
+#define IA_DEBUG_REG1__dma_mask_fifo_we_MASK 0x40000000L
+#define IA_DEBUG_REG1__dma_mask_fifo_we__SHIFT 0x0000001e
+#define IA_DEBUG_REG1__dma_rdreq_dr_q_MASK 0x00000008L
+#define IA_DEBUG_REG1__dma_rdreq_dr_q__SHIFT 0x00000003
+#define IA_DEBUG_REG1__dma_req_fifo_empty_MASK 0x00010000L
+#define IA_DEBUG_REG1__dma_req_fifo_empty__SHIFT 0x00000010
+#define IA_DEBUG_REG1__dma_req_fifo_full_MASK 0x00020000L
+#define IA_DEBUG_REG1__dma_req_fifo_full__SHIFT 0x00000011
+#define IA_DEBUG_REG1__dma_req_path_q_MASK 0x00000080L
+#define IA_DEBUG_REG1__dma_req_path_q__SHIFT 0x00000007
+#define IA_DEBUG_REG1__dma_ret_data_we_q_MASK 0x80000000L
+#define IA_DEBUG_REG1__dma_ret_data_we_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG1__dma_skid_fifo_empty_MASK 0x01000000L
+#define IA_DEBUG_REG1__dma_skid_fifo_empty__SHIFT 0x00000018
+#define IA_DEBUG_REG1__dma_skid_fifo_full_MASK 0x02000000L
+#define IA_DEBUG_REG1__dma_skid_fifo_full__SHIFT 0x00000019
+#define IA_DEBUG_REG1__dma_tc_ret_sel_q_MASK 0x00000800L
+#define IA_DEBUG_REG1__dma_tc_ret_sel_q__SHIFT 0x0000000b
+#define IA_DEBUG_REG1__dma_zero_indices_q_MASK 0x00000010L
+#define IA_DEBUG_REG1__dma_zero_indices_q__SHIFT 0x00000004
+#define IA_DEBUG_REG1__grp_dma_read_MASK 0x08000000L
+#define IA_DEBUG_REG1__grp_dma_read__SHIFT 0x0000001b
+#define IA_DEBUG_REG1__last_rdreq_in_dma_op_MASK 0x00001000L
+#define IA_DEBUG_REG1__last_rdreq_in_dma_op__SHIFT 0x0000000c
+#define IA_DEBUG_REG1__out_of_range_r2_q_MASK 0x20000000L
+#define IA_DEBUG_REG1__out_of_range_r2_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG1__second_tc_ret_data_q_MASK 0x00000400L
+#define IA_DEBUG_REG1__second_tc_ret_data_q__SHIFT 0x0000000a
+#define IA_DEBUG_REG1__stage2_dr_MASK 0x00040000L
+#define IA_DEBUG_REG1__stage2_dr__SHIFT 0x00000012
+#define IA_DEBUG_REG1__stage2_rtr_MASK 0x00080000L
+#define IA_DEBUG_REG1__stage2_rtr__SHIFT 0x00000013
+#define IA_DEBUG_REG1__stage3_dr_MASK 0x00100000L
+#define IA_DEBUG_REG1__stage3_dr__SHIFT 0x00000014
+#define IA_DEBUG_REG1__stage3_rtr_MASK 0x00200000L
+#define IA_DEBUG_REG1__stage3_rtr__SHIFT 0x00000015
+#define IA_DEBUG_REG1__stage4_dr_MASK 0x00400000L
+#define IA_DEBUG_REG1__stage4_dr__SHIFT 0x00000016
+#define IA_DEBUG_REG1__stage4_rtr_MASK 0x00800000L
+#define IA_DEBUG_REG1__stage4_rtr__SHIFT 0x00000017
+#define IA_DEBUG_REG1__start_new_packet_MASK 0x00000004L
+#define IA_DEBUG_REG1__start_new_packet__SHIFT 0x00000002
+#define IA_DEBUG_REG2__hp_current_data_valid_MASK 0x10000000L
+#define IA_DEBUG_REG2__hp_current_data_valid__SHIFT 0x0000001c
+#define IA_DEBUG_REG2__hp_discard_1st_chunk_MASK 0x00000100L
+#define IA_DEBUG_REG2__hp_discard_1st_chunk__SHIFT 0x00000008
+#define IA_DEBUG_REG2__hp_discard_2nd_chunk_MASK 0x00000200L
+#define IA_DEBUG_REG2__hp_discard_2nd_chunk__SHIFT 0x00000009
+#define IA_DEBUG_REG2__hp_dma_buf_type_q_MASK 0x00000060L
+#define IA_DEBUG_REG2__hp_dma_buf_type_q__SHIFT 0x00000005
+#define IA_DEBUG_REG2__hp_dma_data_fifo_empty_q_MASK 0x00004000L
+#define IA_DEBUG_REG2__hp_dma_data_fifo_empty_q__SHIFT 0x0000000e
+#define IA_DEBUG_REG2__hp_dma_data_fifo_full_MASK 0x00008000L
+#define IA_DEBUG_REG2__hp_dma_data_fifo_full__SHIFT 0x0000000f
+#define IA_DEBUG_REG2__hp_dma_grp_valid_MASK 0x04000000L
+#define IA_DEBUG_REG2__hp_dma_grp_valid__SHIFT 0x0000001a
+#define IA_DEBUG_REG2__hp_dma_input_fifo_empty_MASK 0x00000001L
+#define IA_DEBUG_REG2__hp_dma_input_fifo_empty__SHIFT 0x00000000
+#define IA_DEBUG_REG2__hp_dma_input_fifo_full_MASK 0x00000002L
+#define IA_DEBUG_REG2__hp_dma_input_fifo_full__SHIFT 0x00000001
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_empty_MASK 0x00002000L
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_empty__SHIFT 0x0000000d
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_we_MASK 0x40000000L
+#define IA_DEBUG_REG2__hp_dma_mask_fifo_we__SHIFT 0x0000001e
+#define IA_DEBUG_REG2__hp_dma_rdreq_dr_q_MASK 0x00000008L
+#define IA_DEBUG_REG2__hp_dma_rdreq_dr_q__SHIFT 0x00000003
+#define IA_DEBUG_REG2__hp_dma_req_fifo_empty_MASK 0x00010000L
+#define IA_DEBUG_REG2__hp_dma_req_fifo_empty__SHIFT 0x00000010
+#define IA_DEBUG_REG2__hp_dma_req_fifo_full_MASK 0x00020000L
+#define IA_DEBUG_REG2__hp_dma_req_fifo_full__SHIFT 0x00000011
+#define IA_DEBUG_REG2__hp_dma_req_path_q_MASK 0x00000080L
+#define IA_DEBUG_REG2__hp_dma_req_path_q__SHIFT 0x00000007
+#define IA_DEBUG_REG2__hp_dma_ret_data_we_q_MASK 0x80000000L
+#define IA_DEBUG_REG2__hp_dma_ret_data_we_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_empty_MASK 0x01000000L
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_empty__SHIFT 0x00000018
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_full_MASK 0x02000000L
+#define IA_DEBUG_REG2__hp_dma_skid_fifo_full__SHIFT 0x00000019
+#define IA_DEBUG_REG2__hp_dma_tc_ret_sel_q_MASK 0x00000800L
+#define IA_DEBUG_REG2__hp_dma_tc_ret_sel_q__SHIFT 0x0000000b
+#define IA_DEBUG_REG2__hp_dma_zero_indices_q_MASK 0x00000010L
+#define IA_DEBUG_REG2__hp_dma_zero_indices_q__SHIFT 0x00000004
+#define IA_DEBUG_REG2__hp_grp_dma_read_MASK 0x08000000L
+#define IA_DEBUG_REG2__hp_grp_dma_read__SHIFT 0x0000001b
+#define IA_DEBUG_REG2__hp_last_rdreq_in_dma_op_MASK 0x00001000L
+#define IA_DEBUG_REG2__hp_last_rdreq_in_dma_op__SHIFT 0x0000000c
+#define IA_DEBUG_REG2__hp_out_of_range_r2_q_MASK 0x20000000L
+#define IA_DEBUG_REG2__hp_out_of_range_r2_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG2__hp_second_tc_ret_data_q_MASK 0x00000400L
+#define IA_DEBUG_REG2__hp_second_tc_ret_data_q__SHIFT 0x0000000a
+#define IA_DEBUG_REG2__hp_stage2_dr_MASK 0x00040000L
+#define IA_DEBUG_REG2__hp_stage2_dr__SHIFT 0x00000012
+#define IA_DEBUG_REG2__hp_stage2_rtr_MASK 0x00080000L
+#define IA_DEBUG_REG2__hp_stage2_rtr__SHIFT 0x00000013
+#define IA_DEBUG_REG2__hp_stage3_dr_MASK 0x00100000L
+#define IA_DEBUG_REG2__hp_stage3_dr__SHIFT 0x00000014
+#define IA_DEBUG_REG2__hp_stage3_rtr_MASK 0x00200000L
+#define IA_DEBUG_REG2__hp_stage3_rtr__SHIFT 0x00000015
+#define IA_DEBUG_REG2__hp_stage4_dr_MASK 0x00400000L
+#define IA_DEBUG_REG2__hp_stage4_dr__SHIFT 0x00000016
+#define IA_DEBUG_REG2__hp_stage4_rtr_MASK 0x00800000L
+#define IA_DEBUG_REG2__hp_stage4_rtr__SHIFT 0x00000017
+#define IA_DEBUG_REG2__hp_start_new_packet_MASK 0x00000004L
+#define IA_DEBUG_REG2__hp_start_new_packet__SHIFT 0x00000002
+#define IA_DEBUG_REG3__discard_1st_chunk_MASK 0x04000000L
+#define IA_DEBUG_REG3__discard_1st_chunk__SHIFT 0x0000001a
+#define IA_DEBUG_REG3__discard_2nd_chunk_MASK 0x08000000L
+#define IA_DEBUG_REG3__discard_2nd_chunk__SHIFT 0x0000001b
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_eop_out_MASK 0x00000008L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_eop_out__SHIFT 0x00000003
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_null_out_MASK 0x00000004L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_null_out__SHIFT 0x00000002
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_read_MASK 0x00000002L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_read__SHIFT 0x00000001
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_use_tc_out_MASK 0x00000010L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_use_tc_out__SHIFT 0x00000004
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_valid_MASK 0x00000001L
+#define IA_DEBUG_REG3__dma_pipe0_rdreq_valid__SHIFT 0x00000000
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_eop_out_MASK 0x00000800L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_eop_out__SHIFT 0x0000000b
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_null_out_MASK 0x00000400L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_null_out__SHIFT 0x0000000a
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_read_MASK 0x00000200L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_read__SHIFT 0x00000009
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_use_tc_out_MASK 0x00001000L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_use_tc_out__SHIFT 0x0000000c
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_valid_MASK 0x00000100L
+#define IA_DEBUG_REG3__dma_pipe1_rdreq_valid__SHIFT 0x00000008
+#define IA_DEBUG_REG3__dma_rdreq_send_out_MASK 0x00008000L
+#define IA_DEBUG_REG3__dma_rdreq_send_out__SHIFT 0x0000000f
+#define IA_DEBUG_REG3__grp_dma_draw_is_pipe0_MASK 0x00000020L
+#define IA_DEBUG_REG3__grp_dma_draw_is_pipe0__SHIFT 0x00000005
+#define IA_DEBUG_REG3__ia_mc_rdreq_rtr_q_MASK 0x00002000L
+#define IA_DEBUG_REG3__ia_mc_rdreq_rtr_q__SHIFT 0x0000000d
+#define IA_DEBUG_REG3__ia_tc_rdreq_rtr_q_MASK 0x00040000L
+#define IA_DEBUG_REG3__ia_tc_rdreq_rtr_q__SHIFT 0x00000012
+#define IA_DEBUG_REG3__IA_TC_rdreq_send_out_MASK 0x20000000L
+#define IA_DEBUG_REG3__IA_TC_rdreq_send_out__SHIFT 0x0000001d
+#define IA_DEBUG_REG3__last_tc_req_p1_MASK 0x10000000L
+#define IA_DEBUG_REG3__last_tc_req_p1__SHIFT 0x0000001c
+#define IA_DEBUG_REG3__mc_out_rtr_MASK 0x00004000L
+#define IA_DEBUG_REG3__mc_out_rtr__SHIFT 0x0000000e
+#define IA_DEBUG_REG3__must_service_pipe0_req_MASK 0x00000040L
+#define IA_DEBUG_REG3__must_service_pipe0_req__SHIFT 0x00000006
+#define IA_DEBUG_REG3__pair0_valid_p1_MASK 0x00100000L
+#define IA_DEBUG_REG3__pair0_valid_p1__SHIFT 0x00000014
+#define IA_DEBUG_REG3__pair1_valid_p1_MASK 0x00200000L
+#define IA_DEBUG_REG3__pair1_valid_p1__SHIFT 0x00000015
+#define IA_DEBUG_REG3__pair2_valid_p1_MASK 0x00400000L
+#define IA_DEBUG_REG3__pair2_valid_p1__SHIFT 0x00000016
+#define IA_DEBUG_REG3__pair3_valid_p1_MASK 0x00800000L
+#define IA_DEBUG_REG3__pair3_valid_p1__SHIFT 0x00000017
+#define IA_DEBUG_REG3__pipe0_dr_MASK 0x00010000L
+#define IA_DEBUG_REG3__pipe0_dr__SHIFT 0x00000010
+#define IA_DEBUG_REG3__pipe0_rtr_MASK 0x00020000L
+#define IA_DEBUG_REG3__pipe0_rtr__SHIFT 0x00000011
+#define IA_DEBUG_REG3__send_pipe1_req_MASK 0x00000080L
+#define IA_DEBUG_REG3__send_pipe1_req__SHIFT 0x00000007
+#define IA_DEBUG_REG3__TAP_IA_rdret_vld_in_MASK 0x80000000L
+#define IA_DEBUG_REG3__TAP_IA_rdret_vld_in__SHIFT 0x0000001f
+#define IA_DEBUG_REG3__TC_IA_rdret_valid_in_MASK 0x40000000L
+#define IA_DEBUG_REG3__TC_IA_rdret_valid_in__SHIFT 0x0000001e
+#define IA_DEBUG_REG3__tc_out_rtr_MASK 0x00080000L
+#define IA_DEBUG_REG3__tc_out_rtr__SHIFT 0x00000013
+#define IA_DEBUG_REG3__tc_req_count_q_MASK 0x03000000L
+#define IA_DEBUG_REG3__tc_req_count_q__SHIFT 0x00000018
+#define IA_DEBUG_REG4__current_shift_is_vect1_q_MASK 0x80000000L
+#define IA_DEBUG_REG4__current_shift_is_vect1_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG4__di_event_flag_p1_q_MASK 0x00100000L
+#define IA_DEBUG_REG4__di_event_flag_p1_q__SHIFT 0x00000014
+#define IA_DEBUG_REG4__di_first_group_of_draw_q_MASK 0x20000000L
+#define IA_DEBUG_REG4__di_first_group_of_draw_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG4__di_major_mode_p1_q_MASK 0x00010000L
+#define IA_DEBUG_REG4__di_major_mode_p1_q__SHIFT 0x00000010
+#define IA_DEBUG_REG4__di_source_select_p1_q_MASK 0x0c000000L
+#define IA_DEBUG_REG4__di_source_select_p1_q__SHIFT 0x0000001a
+#define IA_DEBUG_REG4__di_state_sel_p1_q_MASK 0x00e00000L
+#define IA_DEBUG_REG4__di_state_sel_p1_q__SHIFT 0x00000015
+#define IA_DEBUG_REG4__draw_opaq_active_q_MASK 0x02000000L
+#define IA_DEBUG_REG4__draw_opaq_active_q__SHIFT 0x00000019
+#define IA_DEBUG_REG4__draw_opaq_en_p1_q_MASK 0x01000000L
+#define IA_DEBUG_REG4__draw_opaq_en_p1_q__SHIFT 0x00000018
+#define IA_DEBUG_REG4__grp_se0_fifo_empty_MASK 0x00000040L
+#define IA_DEBUG_REG4__grp_se0_fifo_empty__SHIFT 0x00000006
+#define IA_DEBUG_REG4__grp_se0_fifo_full_MASK 0x00000080L
+#define IA_DEBUG_REG4__grp_se0_fifo_full__SHIFT 0x00000007
+#define IA_DEBUG_REG4__gs_mode_p1_q_MASK 0x000e0000L
+#define IA_DEBUG_REG4__gs_mode_p1_q__SHIFT 0x00000011
+#define IA_DEBUG_REG4__ia_se1vgt_prim_rtr_q_MASK 0x00008000L
+#define IA_DEBUG_REG4__ia_se1vgt_prim_rtr_q__SHIFT 0x0000000f
+#define IA_DEBUG_REG4__ia_vgt_prim_rtr_q_MASK 0x00004000L
+#define IA_DEBUG_REG4__ia_vgt_prim_rtr_q__SHIFT 0x0000000e
+#define IA_DEBUG_REG4__last_shift_of_draw_MASK 0x40000000L
+#define IA_DEBUG_REG4__last_shift_of_draw__SHIFT 0x0000001e
+#define IA_DEBUG_REG4__pipe0_dr_MASK 0x00000001L
+#define IA_DEBUG_REG4__pipe0_dr__SHIFT 0x00000000
+#define IA_DEBUG_REG4__pipe0_rtr_MASK 0x00000100L
+#define IA_DEBUG_REG4__pipe0_rtr__SHIFT 0x00000008
+#define IA_DEBUG_REG4__pipe1_dr_MASK 0x00000002L
+#define IA_DEBUG_REG4__pipe1_dr__SHIFT 0x00000001
+#define IA_DEBUG_REG4__pipe1_rtr_MASK 0x00000200L
+#define IA_DEBUG_REG4__pipe1_rtr__SHIFT 0x00000009
+#define IA_DEBUG_REG4__pipe2_dr_MASK 0x00000004L
+#define IA_DEBUG_REG4__pipe2_dr__SHIFT 0x00000002
+#define IA_DEBUG_REG4__pipe2_rtr_MASK 0x00000400L
+#define IA_DEBUG_REG4__pipe2_rtr__SHIFT 0x0000000a
+#define IA_DEBUG_REG4__pipe3_dr_MASK 0x00000008L
+#define IA_DEBUG_REG4__pipe3_dr__SHIFT 0x00000003
+#define IA_DEBUG_REG4__pipe3_rtr_MASK 0x00000800L
+#define IA_DEBUG_REG4__pipe3_rtr__SHIFT 0x0000000b
+#define IA_DEBUG_REG4__pipe4_dr_MASK 0x00000010L
+#define IA_DEBUG_REG4__pipe4_dr__SHIFT 0x00000004
+#define IA_DEBUG_REG4__pipe4_rtr_MASK 0x00001000L
+#define IA_DEBUG_REG4__pipe4_rtr__SHIFT 0x0000000c
+#define IA_DEBUG_REG4__pipe5_dr_MASK 0x00000020L
+#define IA_DEBUG_REG4__pipe5_dr__SHIFT 0x00000005
+#define IA_DEBUG_REG4__pipe5_rtr_MASK 0x00002000L
+#define IA_DEBUG_REG4__pipe5_rtr__SHIFT 0x0000000d
+#define IA_DEBUG_REG4__ready_to_read_di_MASK 0x10000000L
+#define IA_DEBUG_REG4__ready_to_read_di__SHIFT 0x0000001c
+#define IA_DEBUG_REG5__di_index_counter_q_15_0_MASK 0x0000ffffL
+#define IA_DEBUG_REG5__di_index_counter_q_15_0__SHIFT 0x00000000
+#define IA_DEBUG_REG5__draw_input_fifo_empty_MASK 0x80000000L
+#define IA_DEBUG_REG5__draw_input_fifo_empty__SHIFT 0x0000001f
+#define IA_DEBUG_REG5__draw_input_fifo_full_MASK 0x40000000L
+#define IA_DEBUG_REG5__draw_input_fifo_full__SHIFT 0x0000001e
+#define IA_DEBUG_REG5__instanceid_13_0_MASK 0x3fff0000L
+#define IA_DEBUG_REG5__instanceid_13_0__SHIFT 0x00000010
+#define IA_DEBUG_REG6__after_group_partial_MASK 0x00400000L
+#define IA_DEBUG_REG6__after_group_partial__SHIFT 0x00000016
+#define IA_DEBUG_REG6__current_shift_q_MASK 0x0000000fL
+#define IA_DEBUG_REG6__current_shift_q__SHIFT 0x00000000
+#define IA_DEBUG_REG6__current_stride_pre_MASK 0x000000f0L
+#define IA_DEBUG_REG6__current_stride_pre__SHIFT 0x00000004
+#define IA_DEBUG_REG6__current_stride_q_MASK 0x00001f00L
+#define IA_DEBUG_REG6__current_stride_q__SHIFT 0x00000008
+#define IA_DEBUG_REG6__curr_prim_partial_MASK 0x00008000L
+#define IA_DEBUG_REG6__curr_prim_partial__SHIFT 0x0000000f
+#define IA_DEBUG_REG6__extract_group_MASK 0x00800000L
+#define IA_DEBUG_REG6__extract_group__SHIFT 0x00000017
+#define IA_DEBUG_REG6__first_group_partial_MASK 0x00002000L
+#define IA_DEBUG_REG6__first_group_partial__SHIFT 0x0000000d
+#define IA_DEBUG_REG6__grp_shift_debug_data_MASK 0xff000000L
+#define IA_DEBUG_REG6__grp_shift_debug_data__SHIFT 0x00000018
+#define IA_DEBUG_REG6__next_group_partial_MASK 0x00200000L
+#define IA_DEBUG_REG6__next_group_partial__SHIFT 0x00000015
+#define IA_DEBUG_REG6__next_stride_q_MASK 0x001f0000L
+#define IA_DEBUG_REG6__next_stride_q__SHIFT 0x00000010
+#define IA_DEBUG_REG6__second_group_partial_MASK 0x00004000L
+#define IA_DEBUG_REG6__second_group_partial__SHIFT 0x0000000e
+#define IA_DEBUG_REG7__indx_shift_is_one_p2_q_MASK 0x02000000L
+#define IA_DEBUG_REG7__indx_shift_is_one_p2_q__SHIFT 0x00000019
+#define IA_DEBUG_REG7__indx_shift_is_two_p2_q_MASK 0x04000000L
+#define IA_DEBUG_REG7__indx_shift_is_two_p2_q__SHIFT 0x0000001a
+#define IA_DEBUG_REG7__indx_stride_is_four_p2_q_MASK 0x08000000L
+#define IA_DEBUG_REG7__indx_stride_is_four_p2_q__SHIFT 0x0000001b
+#define IA_DEBUG_REG7__last_group_of_draw_p2_q_MASK 0x00800000L
+#define IA_DEBUG_REG7__last_group_of_draw_p2_q__SHIFT 0x00000017
+#define IA_DEBUG_REG7__num_indx_in_group_p2_q_MASK 0x00700000L
+#define IA_DEBUG_REG7__num_indx_in_group_p2_q__SHIFT 0x00000014
+#define IA_DEBUG_REG7__reset_indx_state_q_MASK 0x0000000fL
+#define IA_DEBUG_REG7__reset_indx_state_q__SHIFT 0x00000000
+#define IA_DEBUG_REG7__shift_event_flag_p2_q_MASK 0x01000000L
+#define IA_DEBUG_REG7__shift_event_flag_p2_q__SHIFT 0x00000018
+#define IA_DEBUG_REG7__shift_prim0_partial_p3_q_MASK 0x80000000L
+#define IA_DEBUG_REG7__shift_prim0_partial_p3_q__SHIFT 0x0000001f
+#define IA_DEBUG_REG7__shift_prim0_reset_p3_q_MASK 0x40000000L
+#define IA_DEBUG_REG7__shift_prim0_reset_p3_q__SHIFT 0x0000001e
+#define IA_DEBUG_REG7__shift_prim1_partial_p3_q_MASK 0x20000000L
+#define IA_DEBUG_REG7__shift_prim1_partial_p3_q__SHIFT 0x0000001d
+#define IA_DEBUG_REG7__shift_prim1_reset_p3_q_MASK 0x10000000L
+#define IA_DEBUG_REG7__shift_prim1_reset_p3_q__SHIFT 0x0000001c
+#define IA_DEBUG_REG7__shift_vect0_reset_match_p2_q_MASK 0x0000f000L
+#define IA_DEBUG_REG7__shift_vect0_reset_match_p2_q__SHIFT 0x0000000c
+#define IA_DEBUG_REG7__shift_vect1_reset_match_p2_q_MASK 0x000f0000L
+#define IA_DEBUG_REG7__shift_vect1_reset_match_p2_q__SHIFT 0x00000010
+#define IA_DEBUG_REG7__shift_vect1_valid_p2_q_MASK 0x00000f00L
+#define IA_DEBUG_REG7__shift_vect1_valid_p2_q__SHIFT 0x00000008
+#define IA_DEBUG_REG7__shift_vect_valid_p2_q_MASK 0x000000f0L
+#define IA_DEBUG_REG7__shift_vect_valid_p2_q__SHIFT 0x00000004
+#define IA_DEBUG_REG8__di_prim_type_p1_q_MASK 0x0000001fL
+#define IA_DEBUG_REG8__di_prim_type_p1_q__SHIFT 0x00000000
+#define IA_DEBUG_REG8__grp_components_valid_MASK 0xf0000000L
+#define IA_DEBUG_REG8__grp_components_valid__SHIFT 0x0000001c
+#define IA_DEBUG_REG8__grp_continued_MASK 0x00000800L
+#define IA_DEBUG_REG8__grp_continued__SHIFT 0x0000000b
+#define IA_DEBUG_REG8__grp_eopg_MASK 0x04000000L
+#define IA_DEBUG_REG8__grp_eopg__SHIFT 0x0000001a
+#define IA_DEBUG_REG8__grp_eop_MASK 0x02000000L
+#define IA_DEBUG_REG8__grp_eop__SHIFT 0x00000019
+#define IA_DEBUG_REG8__grp_event_flag_MASK 0x08000000L
+#define IA_DEBUG_REG8__grp_event_flag__SHIFT 0x0000001b
+#define IA_DEBUG_REG8__grp_null_primitive_MASK 0x01000000L
+#define IA_DEBUG_REG8__grp_null_primitive__SHIFT 0x00000018
+#define IA_DEBUG_REG8__grp_output_path_MASK 0x00e00000L
+#define IA_DEBUG_REG8__grp_output_path__SHIFT 0x00000015
+#define IA_DEBUG_REG8__grp_state_sel_MASK 0x00007000L
+#define IA_DEBUG_REG8__grp_state_sel__SHIFT 0x0000000c
+#define IA_DEBUG_REG8__grp_sub_prim_type_MASK 0x001f8000L
+#define IA_DEBUG_REG8__grp_sub_prim_type__SHIFT 0x0000000f
+#define IA_DEBUG_REG8__last_group_of_inst_p5_q_MASK 0x00000100L
+#define IA_DEBUG_REG8__last_group_of_inst_p5_q__SHIFT 0x00000008
+#define IA_DEBUG_REG8__shift_prim0_null_flag_p5_q_MASK 0x00000400L
+#define IA_DEBUG_REG8__shift_prim0_null_flag_p5_q__SHIFT 0x0000000a
+#define IA_DEBUG_REG8__shift_prim1_null_flag_p5_q_MASK 0x00000200L
+#define IA_DEBUG_REG8__shift_prim1_null_flag_p5_q__SHIFT 0x00000009
+#define IA_DEBUG_REG8__shift_vect_end_of_packet_p5_q_MASK 0x00000080L
+#define IA_DEBUG_REG8__shift_vect_end_of_packet_p5_q__SHIFT 0x00000007
+#define IA_DEBUG_REG8__two_cycle_xfer_p1_q_MASK 0x00000020L
+#define IA_DEBUG_REG8__two_cycle_xfer_p1_q__SHIFT 0x00000005
+#define IA_DEBUG_REG8__two_prim_input_p1_q_MASK 0x00000040L
+#define IA_DEBUG_REG8__two_prim_input_p1_q__SHIFT 0x00000006
+#define IA_DEBUG_REG9__eopg_between_prims_p6_MASK 0x00000400L
+#define IA_DEBUG_REG9__eopg_between_prims_p6__SHIFT 0x0000000a
+#define IA_DEBUG_REG9__eopg_on_last_prim_p6_MASK 0x00000200L
+#define IA_DEBUG_REG9__eopg_on_last_prim_p6__SHIFT 0x00000009
+#define IA_DEBUG_REG9__gfx_se_switch_p6_MASK 0x00000002L
+#define IA_DEBUG_REG9__gfx_se_switch_p6__SHIFT 0x00000001
+#define IA_DEBUG_REG9__grp_se1_fifo_empty_MASK 0x00040000L
+#define IA_DEBUG_REG9__grp_se1_fifo_empty__SHIFT 0x00000012
+#define IA_DEBUG_REG9__grp_se1_fifo_full_MASK 0x00080000L
+#define IA_DEBUG_REG9__grp_se1_fifo_full__SHIFT 0x00000013
+#define IA_DEBUG_REG9__null_eoi_xfer_prim0_p6_MASK 0x00000008L
+#define IA_DEBUG_REG9__null_eoi_xfer_prim0_p6__SHIFT 0x00000003
+#define IA_DEBUG_REG9__null_eoi_xfer_prim1_p6_MASK 0x00000004L
+#define IA_DEBUG_REG9__null_eoi_xfer_prim1_p6__SHIFT 0x00000002
+#define IA_DEBUG_REG9__prim0_eoi_p6_MASK 0x00000020L
+#define IA_DEBUG_REG9__prim0_eoi_p6__SHIFT 0x00000005
+#define IA_DEBUG_REG9__prim0_valid_eopg_p6_MASK 0x00000080L
+#define IA_DEBUG_REG9__prim0_valid_eopg_p6__SHIFT 0x00000007
+#define IA_DEBUG_REG9__prim1_eoi_p6_MASK 0x00000010L
+#define IA_DEBUG_REG9__prim1_eoi_p6__SHIFT 0x00000004
+#define IA_DEBUG_REG9__prim1_to_other_se_p6_MASK 0x00000100L
+#define IA_DEBUG_REG9__prim1_to_other_se_p6__SHIFT 0x00000008
+#define IA_DEBUG_REG9__prim1_valid_eopg_p6_MASK 0x00000040L
+#define IA_DEBUG_REG9__prim1_valid_eopg_p6__SHIFT 0x00000006
+#define IA_DEBUG_REG9__prim1_xfer_p6_MASK 0x00020000L
+#define IA_DEBUG_REG9__prim1_xfer_p6__SHIFT 0x00000011
+#define IA_DEBUG_REG9__prim_count_eq_group_size_p6_MASK 0x00000800L
+#define IA_DEBUG_REG9__prim_count_eq_group_size_p6__SHIFT 0x0000000b
+#define IA_DEBUG_REG9__prim_counter_q_MASK 0xfffc0000L
+#define IA_DEBUG_REG9__prim_counter_q__SHIFT 0x00000012
+#define IA_DEBUG_REG9__prim_count_gt_group_size_p6_MASK 0x00001000L
+#define IA_DEBUG_REG9__prim_count_gt_group_size_p6__SHIFT 0x0000000c
+#define IA_DEBUG_REG9__send_to_se1_p6_MASK 0x00000001L
+#define IA_DEBUG_REG9__send_to_se1_p6__SHIFT 0x00000000
+#define IA_DEBUG_REG9__shift_vect_end_of_packet_p5_q_MASK 0x00010000L
+#define IA_DEBUG_REG9__shift_vect_end_of_packet_p5_q__SHIFT 0x00000010
+#define IA_DEBUG_REG9__SPARE0_MASK 0x00004000L
+#define IA_DEBUG_REG9__SPARE0__SHIFT 0x0000000e
+#define IA_DEBUG_REG9__SPARE1_MASK 0x00008000L
+#define IA_DEBUG_REG9__SPARE1__SHIFT 0x0000000f
+#define IA_DEBUG_REG9__two_prim_output_p5_q_MASK 0x00002000L
+#define IA_DEBUG_REG9__two_prim_output_p5_q__SHIFT 0x0000000d
+#define IA_ENHANCE__MISC_MASK 0xffffffffL
+#define IA_ENHANCE__MISC__SHIFT 0x00000000
+#define IA_MULTI_VGT_PARAM__PARTIAL_ES_WAVE_ON_MASK 0x00040000L
+#define IA_MULTI_VGT_PARAM__PARTIAL_ES_WAVE_ON__SHIFT 0x00000012
+#define IA_MULTI_VGT_PARAM__PARTIAL_VS_WAVE_ON_MASK 0x00010000L
+#define IA_MULTI_VGT_PARAM__PARTIAL_VS_WAVE_ON__SHIFT 0x00000010
+#define IA_MULTI_VGT_PARAM__PRIMGROUP_SIZE_MASK 0x0000ffffL
+#define IA_MULTI_VGT_PARAM__PRIMGROUP_SIZE__SHIFT 0x00000000
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOI_MASK 0x00080000L
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOI__SHIFT 0x00000013
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOP_MASK 0x00020000L
+#define IA_MULTI_VGT_PARAM__SWITCH_ON_EOP__SHIFT 0x00000011
+#define IA_MULTI_VGT_PARAM__WD_SWITCH_ON_EOP_MASK 0x00100000L
+#define IA_MULTI_VGT_PARAM__WD_SWITCH_ON_EOP__SHIFT 0x00000014
+#define IA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define IA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define IA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define IA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define IA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define IA_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define IA_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define IA_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define IA_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define IA_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define IA_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define IA_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define IA_VMID_OVERRIDE__ENABLE_MASK 0x00000001L
+#define IA_VMID_OVERRIDE__ENABLE__SHIFT 0x00000000
+#define IA_VMID_OVERRIDE__VMID_MASK 0x0000001eL
+#define IA_VMID_OVERRIDE__VMID__SHIFT 0x00000001
+#define PA_CL_CLIP_CNTL__BOUNDARY_EDGE_FLAG_ENA_MASK 0x00040000L
+#define PA_CL_CLIP_CNTL__BOUNDARY_EDGE_FLAG_ENA__SHIFT 0x00000012
+#define PA_CL_CLIP_CNTL__CLIP_DISABLE_MASK 0x00010000L
+#define PA_CL_CLIP_CNTL__CLIP_DISABLE__SHIFT 0x00000010
+#define PA_CL_CLIP_CNTL__DIS_CLIP_ERR_DETECT_MASK 0x00100000L
+#define PA_CL_CLIP_CNTL__DIS_CLIP_ERR_DETECT__SHIFT 0x00000014
+#define PA_CL_CLIP_CNTL__DX_CLIP_SPACE_DEF_MASK 0x00080000L
+#define PA_CL_CLIP_CNTL__DX_CLIP_SPACE_DEF__SHIFT 0x00000013
+#define PA_CL_CLIP_CNTL__DX_LINEAR_ATTR_CLIP_ENA_MASK 0x01000000L
+#define PA_CL_CLIP_CNTL__DX_LINEAR_ATTR_CLIP_ENA__SHIFT 0x00000018
+#define PA_CL_CLIP_CNTL__DX_RASTERIZATION_KILL_MASK 0x00400000L
+#define PA_CL_CLIP_CNTL__DX_RASTERIZATION_KILL__SHIFT 0x00000016
+#define PA_CL_CLIP_CNTL__PS_UCP_MODE_MASK 0x0000c000L
+#define PA_CL_CLIP_CNTL__PS_UCP_MODE__SHIFT 0x0000000e
+#define PA_CL_CLIP_CNTL__PS_UCP_Y_SCALE_NEG_MASK 0x00002000L
+#define PA_CL_CLIP_CNTL__PS_UCP_Y_SCALE_NEG__SHIFT 0x0000000d
+#define PA_CL_CLIP_CNTL__UCP_CULL_ONLY_ENA_MASK 0x00020000L
+#define PA_CL_CLIP_CNTL__UCP_CULL_ONLY_ENA__SHIFT 0x00000011
+#define PA_CL_CLIP_CNTL__UCP_ENA_0_MASK 0x00000001L
+#define PA_CL_CLIP_CNTL__UCP_ENA_0__SHIFT 0x00000000
+#define PA_CL_CLIP_CNTL__UCP_ENA_1_MASK 0x00000002L
+#define PA_CL_CLIP_CNTL__UCP_ENA_1__SHIFT 0x00000001
+#define PA_CL_CLIP_CNTL__UCP_ENA_2_MASK 0x00000004L
+#define PA_CL_CLIP_CNTL__UCP_ENA_2__SHIFT 0x00000002
+#define PA_CL_CLIP_CNTL__UCP_ENA_3_MASK 0x00000008L
+#define PA_CL_CLIP_CNTL__UCP_ENA_3__SHIFT 0x00000003
+#define PA_CL_CLIP_CNTL__UCP_ENA_4_MASK 0x00000010L
+#define PA_CL_CLIP_CNTL__UCP_ENA_4__SHIFT 0x00000004
+#define PA_CL_CLIP_CNTL__UCP_ENA_5_MASK 0x00000020L
+#define PA_CL_CLIP_CNTL__UCP_ENA_5__SHIFT 0x00000005
+#define PA_CL_CLIP_CNTL__VTE_VPORT_PROVOKE_DISABLE_MASK 0x02000000L
+#define PA_CL_CLIP_CNTL__VTE_VPORT_PROVOKE_DISABLE__SHIFT 0x00000019
+#define PA_CL_CLIP_CNTL__VTX_KILL_OR_MASK 0x00200000L
+#define PA_CL_CLIP_CNTL__VTX_KILL_OR__SHIFT 0x00000015
+#define PA_CL_CLIP_CNTL__ZCLIP_FAR_DISABLE_MASK 0x08000000L
+#define PA_CL_CLIP_CNTL__ZCLIP_FAR_DISABLE__SHIFT 0x0000001b
+#define PA_CL_CLIP_CNTL__ZCLIP_NEAR_DISABLE_MASK 0x04000000L
+#define PA_CL_CLIP_CNTL__ZCLIP_NEAR_DISABLE__SHIFT 0x0000001a
+#define PA_CL_CNTL_STATUS__CL_BUSY_MASK 0x80000000L
+#define PA_CL_CNTL_STATUS__CL_BUSY__SHIFT 0x0000001f
+#define PA_CL_ENHANCE__CLIPPED_PRIM_SEQ_STALL_MASK 0x00000008L
+#define PA_CL_ENHANCE__CLIPPED_PRIM_SEQ_STALL__SHIFT 0x00000003
+#define PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA_MASK 0x00000001L
+#define PA_CL_ENHANCE__CLIP_VTX_REORDER_ENA__SHIFT 0x00000000
+#define PA_CL_ENHANCE__ECO_SPARE0_MASK 0x80000000L
+#define PA_CL_ENHANCE__ECO_SPARE0__SHIFT 0x0000001f
+#define PA_CL_ENHANCE__ECO_SPARE1_MASK 0x40000000L
+#define PA_CL_ENHANCE__ECO_SPARE1__SHIFT 0x0000001e
+#define PA_CL_ENHANCE__ECO_SPARE2_MASK 0x20000000L
+#define PA_CL_ENHANCE__ECO_SPARE2__SHIFT 0x0000001d
+#define PA_CL_ENHANCE__ECO_SPARE3_MASK 0x10000000L
+#define PA_CL_ENHANCE__ECO_SPARE3__SHIFT 0x0000001c
+#define PA_CL_ENHANCE__NUM_CLIP_SEQ_MASK 0x00000006L
+#define PA_CL_ENHANCE__NUM_CLIP_SEQ__SHIFT 0x00000001
+#define PA_CL_ENHANCE__VE_NAN_PROC_DISABLE_MASK 0x00000010L
+#define PA_CL_ENHANCE__VE_NAN_PROC_DISABLE__SHIFT 0x00000004
+#define PA_CL_ENHANCE__XTRA_DEBUG_REG_SEL_MASK 0x00000020L
+#define PA_CL_ENHANCE__XTRA_DEBUG_REG_SEL__SHIFT 0x00000005
+#define PA_CL_GB_HORZ_CLIP_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_HORZ_CLIP_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_GB_HORZ_DISC_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_HORZ_DISC_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_GB_VERT_CLIP_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_VERT_CLIP_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_GB_VERT_DISC_ADJ__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_GB_VERT_DISC_ADJ__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_NANINF_CNTL__VS_CLIP_DIST_INF_DISCARD_MASK 0x00004000L
+#define PA_CL_NANINF_CNTL__VS_CLIP_DIST_INF_DISCARD__SHIFT 0x0000000e
+#define PA_CL_NANINF_CNTL__VS_W_INF_RETAIN_MASK 0x00002000L
+#define PA_CL_NANINF_CNTL__VS_W_INF_RETAIN__SHIFT 0x0000000d
+#define PA_CL_NANINF_CNTL__VS_W_NAN_TO_INF_MASK 0x00001000L
+#define PA_CL_NANINF_CNTL__VS_W_NAN_TO_INF__SHIFT 0x0000000c
+#define PA_CL_NANINF_CNTL__VS_XY_INF_RETAIN_MASK 0x00000200L
+#define PA_CL_NANINF_CNTL__VS_XY_INF_RETAIN__SHIFT 0x00000009
+#define PA_CL_NANINF_CNTL__VS_XY_NAN_TO_INF_MASK 0x00000100L
+#define PA_CL_NANINF_CNTL__VS_XY_NAN_TO_INF__SHIFT 0x00000008
+#define PA_CL_NANINF_CNTL__VS_Z_INF_RETAIN_MASK 0x00000800L
+#define PA_CL_NANINF_CNTL__VS_Z_INF_RETAIN__SHIFT 0x0000000b
+#define PA_CL_NANINF_CNTL__VS_Z_NAN_TO_INF_MASK 0x00000400L
+#define PA_CL_NANINF_CNTL__VS_Z_NAN_TO_INF__SHIFT 0x0000000a
+#define PA_CL_NANINF_CNTL__VTE_0XNANINF_IS_0_MASK 0x00000008L
+#define PA_CL_NANINF_CNTL__VTE_0XNANINF_IS_0__SHIFT 0x00000003
+#define PA_CL_NANINF_CNTL__VTE_NO_OUTPUT_NEG_0_MASK 0x00100000L
+#define PA_CL_NANINF_CNTL__VTE_NO_OUTPUT_NEG_0__SHIFT 0x00000014
+#define PA_CL_NANINF_CNTL__VTE_W_INF_DISCARD_MASK 0x00000004L
+#define PA_CL_NANINF_CNTL__VTE_W_INF_DISCARD__SHIFT 0x00000002
+#define PA_CL_NANINF_CNTL__VTE_W_NAN_RETAIN_MASK 0x00000040L
+#define PA_CL_NANINF_CNTL__VTE_W_NAN_RETAIN__SHIFT 0x00000006
+#define PA_CL_NANINF_CNTL__VTE_W_RECIP_NAN_IS_0_MASK 0x00000080L
+#define PA_CL_NANINF_CNTL__VTE_W_RECIP_NAN_IS_0__SHIFT 0x00000007
+#define PA_CL_NANINF_CNTL__VTE_XY_INF_DISCARD_MASK 0x00000001L
+#define PA_CL_NANINF_CNTL__VTE_XY_INF_DISCARD__SHIFT 0x00000000
+#define PA_CL_NANINF_CNTL__VTE_XY_NAN_RETAIN_MASK 0x00000010L
+#define PA_CL_NANINF_CNTL__VTE_XY_NAN_RETAIN__SHIFT 0x00000004
+#define PA_CL_NANINF_CNTL__VTE_Z_INF_DISCARD_MASK 0x00000002L
+#define PA_CL_NANINF_CNTL__VTE_Z_INF_DISCARD__SHIFT 0x00000001
+#define PA_CL_NANINF_CNTL__VTE_Z_NAN_RETAIN_MASK 0x00000020L
+#define PA_CL_NANINF_CNTL__VTE_Z_NAN_RETAIN__SHIFT 0x00000005
+#define PA_CL_POINT_CULL_RAD__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_CULL_RAD__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_POINT_SIZE__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_SIZE__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_POINT_X_RAD__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_X_RAD__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_POINT_Y_RAD__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_POINT_Y_RAD__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_0_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_0_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_1_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_1_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_2_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_2_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_3_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_3_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_4_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_4_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_W__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_W__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_X__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_X__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_Y__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_Y__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_UCP_5_Z__DATA_REGISTER_MASK 0xffffffffL
+#define PA_CL_UCP_5_Z__DATA_REGISTER__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_10__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_10__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_11__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_11__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_12__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_12__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_13__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_13__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_14__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_14__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_15__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_15__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_1__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_1__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_2__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_2__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_3__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_3__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_4__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_4__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_5__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_5__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_6__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_6__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_7__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_7__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_8__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_8__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET_9__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET_9__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XOFFSET__VPORT_XOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_XOFFSET__VPORT_XOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_10__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_10__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_11__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_11__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_12__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_12__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_13__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_13__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_14__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_14__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_15__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_15__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_1__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_1__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_2__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_2__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_3__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_3__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_4__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_4__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_5__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_5__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_6__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_6__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_7__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_7__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_8__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_8__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE_9__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE_9__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_XSCALE__VPORT_XSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_XSCALE__VPORT_XSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_10__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_10__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_11__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_11__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_12__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_12__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_13__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_13__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_14__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_14__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_15__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_15__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_1__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_1__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_2__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_2__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_3__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_3__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_4__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_4__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_5__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_5__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_6__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_6__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_7__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_7__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_8__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_8__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET_9__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET_9__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YOFFSET__VPORT_YOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_YOFFSET__VPORT_YOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_10__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_10__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_11__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_11__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_12__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_12__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_13__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_13__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_14__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_14__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_15__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_15__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_1__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_1__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_2__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_2__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_3__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_3__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_4__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_4__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_5__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_5__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_6__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_6__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_7__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_7__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_8__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_8__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE_9__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE_9__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_YSCALE__VPORT_YSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_YSCALE__VPORT_YSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_10__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_10__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_11__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_11__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_12__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_12__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_13__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_13__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_14__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_14__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_15__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_15__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_1__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_1__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_2__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_2__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_3__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_3__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_4__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_4__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_5__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_5__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_6__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_6__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_7__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_7__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_8__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_8__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET_9__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET_9__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZOFFSET__VPORT_ZOFFSET_MASK 0xffffffffL
+#define PA_CL_VPORT_ZOFFSET__VPORT_ZOFFSET__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_10__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_10__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_11__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_11__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_12__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_12__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_13__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_13__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_14__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_14__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_15__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_15__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_1__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_1__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_2__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_2__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_3__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_3__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_4__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_4__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_5__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_5__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_6__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_6__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_7__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_7__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_8__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_8__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE_9__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE_9__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VPORT_ZSCALE__VPORT_ZSCALE_MASK 0xffffffffL
+#define PA_CL_VPORT_ZSCALE__VPORT_ZSCALE__SHIFT 0x00000000
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0_MASK 0x00000001L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_0__SHIFT 0x00000000
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_1_MASK 0x00000002L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_1__SHIFT 0x00000001
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_2_MASK 0x00000004L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_2__SHIFT 0x00000002
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_3_MASK 0x00000008L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_3__SHIFT 0x00000003
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_4_MASK 0x00000010L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_4__SHIFT 0x00000004
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_5_MASK 0x00000020L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_5__SHIFT 0x00000005
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_6_MASK 0x00000040L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_6__SHIFT 0x00000006
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_7_MASK 0x00000080L
+#define PA_CL_VS_OUT_CNTL__CLIP_DIST_ENA_7__SHIFT 0x00000007
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_0_MASK 0x00000100L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_0__SHIFT 0x00000008
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_1_MASK 0x00000200L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_1__SHIFT 0x00000009
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_2_MASK 0x00000400L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_2__SHIFT 0x0000000a
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_3_MASK 0x00000800L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_3__SHIFT 0x0000000b
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_4_MASK 0x00001000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_4__SHIFT 0x0000000c
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_5_MASK 0x00002000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_5__SHIFT 0x0000000d
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_6_MASK 0x00004000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_6__SHIFT 0x0000000e
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_7_MASK 0x00008000L
+#define PA_CL_VS_OUT_CNTL__CULL_DIST_ENA_7__SHIFT 0x0000000f
+#define PA_CL_VS_OUT_CNTL__USE_VTX_EDGE_FLAG_MASK 0x00020000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_EDGE_FLAG__SHIFT 0x00000011
+#define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG_MASK 0x02000000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_GS_CUT_FLAG__SHIFT 0x00000019
+#define PA_CL_VS_OUT_CNTL__USE_VTX_KILL_FLAG_MASK 0x00100000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_KILL_FLAG__SHIFT 0x00000014
+#define PA_CL_VS_OUT_CNTL__USE_VTX_POINT_SIZE_MASK 0x00010000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_POINT_SIZE__SHIFT 0x00000010
+#define PA_CL_VS_OUT_CNTL__USE_VTX_RENDER_TARGET_INDX_MASK 0x00040000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_RENDER_TARGET_INDX__SHIFT 0x00000012
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VIEWPORT_INDX_MASK 0x00080000L
+#define PA_CL_VS_OUT_CNTL__USE_VTX_VIEWPORT_INDX__SHIFT 0x00000013
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST0_VEC_ENA_MASK 0x00400000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST0_VEC_ENA__SHIFT 0x00000016
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST1_VEC_ENA_MASK 0x00800000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_CCDIST1_VEC_ENA__SHIFT 0x00000017
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA_MASK 0x01000000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_SIDE_BUS_ENA__SHIFT 0x00000018
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_VEC_ENA_MASK 0x00200000L
+#define PA_CL_VS_OUT_CNTL__VS_OUT_MISC_VEC_ENA__SHIFT 0x00000015
+#define PA_CL_VTE_CNTL__PERFCOUNTER_REF_MASK 0x00000800L
+#define PA_CL_VTE_CNTL__PERFCOUNTER_REF__SHIFT 0x0000000b
+#define PA_CL_VTE_CNTL__VPORT_X_OFFSET_ENA_MASK 0x00000002L
+#define PA_CL_VTE_CNTL__VPORT_X_OFFSET_ENA__SHIFT 0x00000001
+#define PA_CL_VTE_CNTL__VPORT_X_SCALE_ENA_MASK 0x00000001L
+#define PA_CL_VTE_CNTL__VPORT_X_SCALE_ENA__SHIFT 0x00000000
+#define PA_CL_VTE_CNTL__VPORT_Y_OFFSET_ENA_MASK 0x00000008L
+#define PA_CL_VTE_CNTL__VPORT_Y_OFFSET_ENA__SHIFT 0x00000003
+#define PA_CL_VTE_CNTL__VPORT_Y_SCALE_ENA_MASK 0x00000004L
+#define PA_CL_VTE_CNTL__VPORT_Y_SCALE_ENA__SHIFT 0x00000002
+#define PA_CL_VTE_CNTL__VPORT_Z_OFFSET_ENA_MASK 0x00000020L
+#define PA_CL_VTE_CNTL__VPORT_Z_OFFSET_ENA__SHIFT 0x00000005
+#define PA_CL_VTE_CNTL__VPORT_Z_SCALE_ENA_MASK 0x00000010L
+#define PA_CL_VTE_CNTL__VPORT_Z_SCALE_ENA__SHIFT 0x00000004
+#define PA_CL_VTE_CNTL__VTX_W0_FMT_MASK 0x00000400L
+#define PA_CL_VTE_CNTL__VTX_W0_FMT__SHIFT 0x0000000a
+#define PA_CL_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100L
+#define PA_CL_VTE_CNTL__VTX_XY_FMT__SHIFT 0x00000008
+#define PA_CL_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200L
+#define PA_CL_VTE_CNTL__VTX_Z_FMT__SHIFT 0x00000009
+#define PA_SC_AA_CONFIG__AA_MASK_CENTROID_DTMN_MASK 0x00000010L
+#define PA_SC_AA_CONFIG__AA_MASK_CENTROID_DTMN__SHIFT 0x00000004
+#define PA_SC_AA_CONFIG__DETAIL_TO_EXPOSED_MODE_MASK 0x03000000L
+#define PA_SC_AA_CONFIG__DETAIL_TO_EXPOSED_MODE__SHIFT 0x00000018
+#define PA_SC_AA_CONFIG__MAX_SAMPLE_DIST_MASK 0x0001e000L
+#define PA_SC_AA_CONFIG__MAX_SAMPLE_DIST__SHIFT 0x0000000d
+#define PA_SC_AA_CONFIG__MSAA_EXPOSED_SAMPLES_MASK 0x00700000L
+#define PA_SC_AA_CONFIG__MSAA_EXPOSED_SAMPLES__SHIFT 0x00000014
+#define PA_SC_AA_CONFIG__MSAA_NUM_SAMPLES_MASK 0x00000007L
+#define PA_SC_AA_CONFIG__MSAA_NUM_SAMPLES__SHIFT 0x00000000
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X0Y0_MASK 0x0000ffffL
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X0Y0__SHIFT 0x00000000
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X1Y0_MASK 0xffff0000L
+#define PA_SC_AA_MASK_X0Y0_X1Y0__AA_MASK_X1Y0__SHIFT 0x00000010
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X0Y1_MASK 0x0000ffffL
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X0Y1__SHIFT 0x00000000
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X1Y1_MASK 0xffff0000L
+#define PA_SC_AA_MASK_X0Y1_X1Y1__AA_MASK_X1Y1__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y0_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X0Y1_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y0_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S0_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S1_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S2_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_0__S3_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S4_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S5_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S6_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_1__S7_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S10_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S11_Y__SHIFT 0x0000001c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S8_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_2__S9_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_X_MASK 0x0000000fL
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_X__SHIFT 0x00000000
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_Y_MASK 0x000000f0L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S12_Y__SHIFT 0x00000004
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_X_MASK 0x00000f00L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_X__SHIFT 0x00000008
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_Y_MASK 0x0000f000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S13_Y__SHIFT 0x0000000c
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_X_MASK 0x000f0000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_X__SHIFT 0x00000010
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_Y_MASK 0x00f00000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S14_Y__SHIFT 0x00000014
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_X_MASK 0x0f000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_X__SHIFT 0x00000018
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_Y_MASK 0xf0000000L
+#define PA_SC_AA_SAMPLE_LOCS_PIXEL_X1Y1_3__S15_Y__SHIFT 0x0000001c
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_0_MASK 0x0000000fL
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_0__SHIFT 0x00000000
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_1_MASK 0x000000f0L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_1__SHIFT 0x00000004
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_2_MASK 0x00000f00L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_2__SHIFT 0x00000008
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_3_MASK 0x0000f000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_3__SHIFT 0x0000000c
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_4_MASK 0x000f0000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_4__SHIFT 0x00000010
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_5_MASK 0x00f00000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_5__SHIFT 0x00000014
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_6_MASK 0x0f000000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_6__SHIFT 0x00000018
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_7_MASK 0xf0000000L
+#define PA_SC_CENTROID_PRIORITY_0__DISTANCE_7__SHIFT 0x0000001c
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_10_MASK 0x00000f00L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_10__SHIFT 0x00000008
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_11_MASK 0x0000f000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_11__SHIFT 0x0000000c
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_12_MASK 0x000f0000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_12__SHIFT 0x00000010
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_13_MASK 0x00f00000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_13__SHIFT 0x00000014
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_14_MASK 0x0f000000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_14__SHIFT 0x00000018
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_15_MASK 0xf0000000L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_15__SHIFT 0x0000001c
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_8_MASK 0x0000000fL
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_8__SHIFT 0x00000000
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_9_MASK 0x000000f0L
+#define PA_SC_CENTROID_PRIORITY_1__DISTANCE_9__SHIFT 0x00000004
+#define PA_SC_CLIPRECT_0_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_0_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_0_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_0_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_0_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_0_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_0_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_0_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_1_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_1_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_1_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_1_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_1_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_1_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_1_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_1_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_2_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_2_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_2_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_2_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_2_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_2_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_2_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_2_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_3_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_3_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_3_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_3_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_3_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_CLIPRECT_3_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_CLIPRECT_3_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_CLIPRECT_3_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_CLIPRECT_RULE__CLIP_RULE_MASK 0x0000ffffL
+#define PA_SC_CLIPRECT_RULE__CLIP_RULE__SHIFT 0x00000000
+#define PA_SC_DEBUG_CNTL__SC_DEBUG_INDX_MASK 0x0000003fL
+#define PA_SC_DEBUG_CNTL__SC_DEBUG_INDX__SHIFT 0x00000000
+#define PA_SC_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define PA_SC_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define PA_SC_DEBUG_REG0__REG0_FIELD0_MASK 0x00000003L
+#define PA_SC_DEBUG_REG0__REG0_FIELD0__SHIFT 0x00000000
+#define PA_SC_DEBUG_REG0__REG0_FIELD1_MASK 0x0000000cL
+#define PA_SC_DEBUG_REG0__REG0_FIELD1__SHIFT 0x00000002
+#define PA_SC_DEBUG_REG1__REG1_FIELD0_MASK 0x00000003L
+#define PA_SC_DEBUG_REG1__REG1_FIELD0__SHIFT 0x00000000
+#define PA_SC_DEBUG_REG1__REG1_FIELD1_MASK 0x0000000cL
+#define PA_SC_DEBUG_REG1__REG1_FIELD1__SHIFT 0x00000002
+#define PA_SC_EDGERULE__ER_LINE_BT_MASK 0xf0000000L
+#define PA_SC_EDGERULE__ER_LINE_BT__SHIFT 0x0000001c
+#define PA_SC_EDGERULE__ER_LINE_LR_MASK 0x0003f000L
+#define PA_SC_EDGERULE__ER_LINE_LR__SHIFT 0x0000000c
+#define PA_SC_EDGERULE__ER_LINE_RL_MASK 0x00fc0000L
+#define PA_SC_EDGERULE__ER_LINE_RL__SHIFT 0x00000012
+#define PA_SC_EDGERULE__ER_LINE_TB_MASK 0x0f000000L
+#define PA_SC_EDGERULE__ER_LINE_TB__SHIFT 0x00000018
+#define PA_SC_EDGERULE__ER_POINT_MASK 0x000000f0L
+#define PA_SC_EDGERULE__ER_POINT__SHIFT 0x00000004
+#define PA_SC_EDGERULE__ER_RECT_MASK 0x00000f00L
+#define PA_SC_EDGERULE__ER_RECT__SHIFT 0x00000008
+#define PA_SC_EDGERULE__ER_TRI_MASK 0x0000000fL
+#define PA_SC_EDGERULE__ER_TRI__SHIFT 0x00000000
+#define PA_SC_ENHANCE__DISABLE_AA_MASK_FULL_FIX_MASK 0x00000004L
+#define PA_SC_ENHANCE__DISABLE_AA_MASK_FULL_FIX__SHIFT 0x00000002
+#define PA_SC_ENHANCE__DISABLE_DUALGRAD_PERF_OPTIMIZATION_MASK 0x00000200L
+#define PA_SC_ENHANCE__DISABLE_DUALGRAD_PERF_OPTIMIZATION__SHIFT 0x00000009
+#define PA_SC_ENHANCE__DISABLE_EOV_ALL_CTRL_ONLY_COMBINATIONS_MASK 0x00004000L
+#define PA_SC_ENHANCE__DISABLE_EOV_ALL_CTRL_ONLY_COMBINATIONS__SHIFT 0x0000000e
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_DESIRED_FIFO_EMPTY_SWITCHING_MASK 0x00200000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_DESIRED_FIFO_EMPTY_SWITCHING__SHIFT 0x00000015
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EMPTY_SWITCHING_HYSTERYSIS_MASK 0x00800000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EMPTY_SWITCHING_HYSTERYSIS__SHIFT 0x00000017
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EOP_SYNC_NULL_PRIMS_LAST_MASK 0x00040000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_EOP_SYNC_NULL_PRIMS_LAST__SHIFT 0x00000012
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_PA_SC_GUIDANCE_MASK 0x00010000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_PA_SC_GUIDANCE__SHIFT 0x00000010
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_SELECTED_FIFO_EMPTY_SWITCHING_MASK 0x00400000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_SELECTED_FIFO_EMPTY_SWITCHING__SHIFT 0x00000016
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_THRESHOLD_SWITCHING_MASK 0x00080000L
+#define PA_SC_ENHANCE__DISABLE_OUT_OF_ORDER_THRESHOLD_SWITCHING__SHIFT 0x00000013
+#define PA_SC_ENHANCE__DISABLE_PA_SC_GUIDANCE_MASK 0x00002000L
+#define PA_SC_ENHANCE__DISABLE_PA_SC_GUIDANCE__SHIFT 0x0000000d
+#define PA_SC_ENHANCE__DISABLE_PW_BUBBLE_COLLAPSE_MASK 0x000000c0L
+#define PA_SC_ENHANCE__DISABLE_PW_BUBBLE_COLLAPSE__SHIFT 0x00000006
+#define PA_SC_ENHANCE__DISABLE_SC_DB_TILE_FIX_MASK 0x00000002L
+#define PA_SC_ENHANCE__DISABLE_SC_DB_TILE_FIX__SHIFT 0x00000001
+#define PA_SC_ENHANCE__DISABLE_SCISSOR_FIX_MASK 0x00000020L
+#define PA_SC_ENHANCE__DISABLE_SCISSOR_FIX__SHIFT 0x00000005
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_PRIM_MASK 0x00000400L
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_PRIM__SHIFT 0x0000000a
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_SUPERTILE_MASK 0x00000800L
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_SUPERTILE__SHIFT 0x0000000b
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_TILE_MASK 0x00001000L
+#define PA_SC_ENHANCE__DISABLE_SC_PROCESS_RESET_TILE__SHIFT 0x0000000c
+#define PA_SC_ENHANCE__ECO_SPARE0_MASK 0x80000000L
+#define PA_SC_ENHANCE__ECO_SPARE0__SHIFT 0x0000001f
+#define PA_SC_ENHANCE__ECO_SPARE1_MASK 0x40000000L
+#define PA_SC_ENHANCE__ECO_SPARE1__SHIFT 0x0000001e
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOCATIONS_MASK 0x00000008L
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOCATIONS__SHIFT 0x00000003
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOC_CENTROID_MASK 0x00000010L
+#define PA_SC_ENHANCE__ENABLE_1XMSAA_SAMPLE_LOC_CENTROID__SHIFT 0x00000004
+#define PA_SC_ENHANCE__ENABLE_MULTICYCLE_BUBBLE_FREEZE_MASK 0x00008000L
+#define PA_SC_ENHANCE__ENABLE_MULTICYCLE_BUBBLE_FREEZE__SHIFT 0x0000000f
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_DESIRED_FIFO_IS_NEXT_FEID_MASK 0x01000000L
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_DESIRED_FIFO_IS_NEXT_FEID__SHIFT 0x00000018
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_POLY_MODE_MASK 0x00020000L
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_POLY_MODE__SHIFT 0x00000011
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_THRESHOLD_SWITCH_AT_EOPG_ONLY_MASK 0x00100000L
+#define PA_SC_ENHANCE__ENABLE_OUT_OF_ORDER_THRESHOLD_SWITCH_AT_EOPG_ONLY__SHIFT 0x00000014
+#define PA_SC_ENHANCE__ENABLE_PA_SC_OUT_OF_ORDER_MASK 0x00000001L
+#define PA_SC_ENHANCE__ENABLE_PA_SC_OUT_OF_ORDER__SHIFT 0x00000000
+#define PA_SC_ENHANCE__SEND_UNLIT_STILES_TO_PACKER_MASK 0x00000100L
+#define PA_SC_ENHANCE__SEND_UNLIT_STILES_TO_PACKER__SHIFT 0x00000008
+#define PA_SC_FIFO_DEPTH_CNTL__DEPTH_MASK 0x000000ffL
+#define PA_SC_FIFO_DEPTH_CNTL__DEPTH__SHIFT 0x00000000
+#define PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE_MASK 0x00007fc0L
+#define PA_SC_FIFO_SIZE__SC_BACKEND_PRIM_FIFO_SIZE__SHIFT 0x00000006
+#define PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE_MASK 0xff800000L
+#define PA_SC_FIFO_SIZE__SC_EARLYZ_TILE_FIFO_SIZE__SHIFT 0x00000017
+#define PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE_MASK 0x0000003fL
+#define PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT 0x00000000
+#define PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE_MASK 0x001f8000L
+#define PA_SC_FIFO_SIZE__SC_HIZ_TILE_FIFO_SIZE__SHIFT 0x0000000f
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT_MASK 0x0000ffffL
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_CLK_CNT__SHIFT 0x00000000
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT_MASK 0xffff0000L
+#define PA_SC_FORCE_EOV_MAX_CNTS__FORCE_EOV_MAX_REZ_CNT__SHIFT 0x00000010
+#define PA_SC_GENERIC_SCISSOR_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_GENERIC_SCISSOR_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_GENERIC_SCISSOR_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_GENERIC_SCISSOR_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_GENERIC_SCISSOR_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_GENERIC_SCISSOR_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_GENERIC_SCISSOR_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_GENERIC_SCISSOR_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_GENERIC_SCISSOR_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_GENERIC_SCISSOR_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_IF_FIFO_SIZE__SC_BCI_IF_FIFO_SIZE_MASK 0x00fc0000L
+#define PA_SC_IF_FIFO_SIZE__SC_BCI_IF_FIFO_SIZE__SHIFT 0x00000012
+#define PA_SC_IF_FIFO_SIZE__SC_DB_QUAD_IF_FIFO_SIZE_MASK 0x00000fc0L
+#define PA_SC_IF_FIFO_SIZE__SC_DB_QUAD_IF_FIFO_SIZE__SHIFT 0x00000006
+#define PA_SC_IF_FIFO_SIZE__SC_DB_TILE_IF_FIFO_SIZE_MASK 0x0000003fL
+#define PA_SC_IF_FIFO_SIZE__SC_DB_TILE_IF_FIFO_SIZE__SHIFT 0x00000000
+#define PA_SC_IF_FIFO_SIZE__SC_SPI_IF_FIFO_SIZE_MASK 0x0003f000L
+#define PA_SC_IF_FIFO_SIZE__SC_SPI_IF_FIFO_SIZE__SHIFT 0x0000000c
+#define PA_SC_LINE_CNTL__DX10_DIAMOND_TEST_ENA_MASK 0x00001000L
+#define PA_SC_LINE_CNTL__DX10_DIAMOND_TEST_ENA__SHIFT 0x0000000c
+#define PA_SC_LINE_CNTL__EXPAND_LINE_WIDTH_MASK 0x00000200L
+#define PA_SC_LINE_CNTL__EXPAND_LINE_WIDTH__SHIFT 0x00000009
+#define PA_SC_LINE_CNTL__LAST_PIXEL_MASK 0x00000400L
+#define PA_SC_LINE_CNTL__LAST_PIXEL__SHIFT 0x0000000a
+#define PA_SC_LINE_CNTL__PERPENDICULAR_ENDCAP_ENA_MASK 0x00000800L
+#define PA_SC_LINE_CNTL__PERPENDICULAR_ENDCAP_ENA__SHIFT 0x0000000b
+#define PA_SC_LINE_STIPPLE__AUTO_RESET_CNTL_MASK 0x60000000L
+#define PA_SC_LINE_STIPPLE__AUTO_RESET_CNTL__SHIFT 0x0000001d
+#define PA_SC_LINE_STIPPLE__LINE_PATTERN_MASK 0x0000ffffL
+#define PA_SC_LINE_STIPPLE__LINE_PATTERN__SHIFT 0x00000000
+#define PA_SC_LINE_STIPPLE__PATTERN_BIT_ORDER_MASK 0x10000000L
+#define PA_SC_LINE_STIPPLE__PATTERN_BIT_ORDER__SHIFT 0x0000001c
+#define PA_SC_LINE_STIPPLE__REPEAT_COUNT_MASK 0x00ff0000L
+#define PA_SC_LINE_STIPPLE__REPEAT_COUNT__SHIFT 0x00000010
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_COUNT_MASK 0x0000ff00L
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_COUNT__SHIFT 0x00000008
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_PTR_MASK 0x0000000fL
+#define PA_SC_LINE_STIPPLE_STATE__CURRENT_PTR__SHIFT 0x00000000
+#define PA_SC_MODE_CNTL_0__LINE_STIPPLE_ENABLE_MASK 0x00000004L
+#define PA_SC_MODE_CNTL_0__LINE_STIPPLE_ENABLE__SHIFT 0x00000002
+#define PA_SC_MODE_CNTL_0__MSAA_ENABLE_MASK 0x00000001L
+#define PA_SC_MODE_CNTL_0__MSAA_ENABLE__SHIFT 0x00000000
+#define PA_SC_MODE_CNTL_0__SEND_UNLIT_STILES_TO_PKR_MASK 0x00000008L
+#define PA_SC_MODE_CNTL_0__SEND_UNLIT_STILES_TO_PKR__SHIFT 0x00000003
+#define PA_SC_MODE_CNTL_0__VPORT_SCISSOR_ENABLE_MASK 0x00000002L
+#define PA_SC_MODE_CNTL_0__VPORT_SCISSOR_ENABLE__SHIFT 0x00000001
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_CNTDWN_ENABLE_MASK 0x02000000L
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_CNTDWN_ENABLE__SHIFT 0x00000019
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_REZ_ENABLE_MASK 0x04000000L
+#define PA_SC_MODE_CNTL_1__FORCE_EOV_REZ_ENABLE__SHIFT 0x0000001a
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_ENABLE_MASK 0x00080000L
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_ENABLE__SHIFT 0x00000013
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE_MASK 0x00f00000L
+#define PA_SC_MODE_CNTL_1__GPU_ID_OVERRIDE__SHIFT 0x00000014
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_DETAIL_MASK_MASK 0x00008000L
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_DETAIL_MASK__SHIFT 0x0000000f
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_HI_Z_MASK 0x00004000L
+#define PA_SC_MODE_CNTL_1__KILL_PIX_POST_HI_Z__SHIFT 0x0000000e
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_PRIM_DISCARD_ENABLE_MASK 0x01000000L
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_PRIM_DISCARD_ENABLE__SHIFT 0x00000018
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_SUPERTILE_ENABLE_MASK 0x00040000L
+#define PA_SC_MODE_CNTL_1__MULTI_GPU_SUPERTILE_ENABLE__SHIFT 0x00000012
+#define PA_SC_MODE_CNTL_1__MULTI_SHADER_ENGINE_PRIM_DISCARD_ENABLE_MASK 0x00020000L
+#define PA_SC_MODE_CNTL_1__MULTI_SHADER_ENGINE_PRIM_DISCARD_ENABLE__SHIFT 0x00000011
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_PRIMITIVE_ENABLE_MASK 0x08000000L
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_PRIMITIVE_ENABLE__SHIFT 0x0000001b
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_WATER_MARK_MASK 0x70000000L
+#define PA_SC_MODE_CNTL_1__OUT_OF_ORDER_WATER_MARK__SHIFT 0x0000001c
+#define PA_SC_MODE_CNTL_1__PS_ITER_SAMPLE_MASK 0x00010000L
+#define PA_SC_MODE_CNTL_1__PS_ITER_SAMPLE__SHIFT 0x00000010
+#define PA_SC_MODE_CNTL_1__SUPERTILE_WALK_ORDER_ENABLE_MASK 0x00000080L
+#define PA_SC_MODE_CNTL_1__SUPERTILE_WALK_ORDER_ENABLE__SHIFT 0x00000007
+#define PA_SC_MODE_CNTL_1__TILE_COVER_DISABLE_MASK 0x00000200L
+#define PA_SC_MODE_CNTL_1__TILE_COVER_DISABLE__SHIFT 0x00000009
+#define PA_SC_MODE_CNTL_1__TILE_COVER_NO_SCISSOR_MASK 0x00000400L
+#define PA_SC_MODE_CNTL_1__TILE_COVER_NO_SCISSOR__SHIFT 0x0000000a
+#define PA_SC_MODE_CNTL_1__TILE_WALK_ORDER_ENABLE_MASK 0x00000100L
+#define PA_SC_MODE_CNTL_1__TILE_WALK_ORDER_ENABLE__SHIFT 0x00000008
+#define PA_SC_MODE_CNTL_1__WALK_ALIGN8_PRIM_FITS_ST_MASK 0x00000004L
+#define PA_SC_MODE_CNTL_1__WALK_ALIGN8_PRIM_FITS_ST__SHIFT 0x00000002
+#define PA_SC_MODE_CNTL_1__WALK_ALIGNMENT_MASK 0x00000002L
+#define PA_SC_MODE_CNTL_1__WALK_ALIGNMENT__SHIFT 0x00000001
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_ENABLE_MASK 0x00000008L
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_ENABLE__SHIFT 0x00000003
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_SIZE_MASK 0x00000070L
+#define PA_SC_MODE_CNTL_1__WALK_FENCE_SIZE__SHIFT 0x00000004
+#define PA_SC_MODE_CNTL_1__WALK_SIZE_MASK 0x00000001L
+#define PA_SC_MODE_CNTL_1__WALK_SIZE__SHIFT 0x00000000
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_EXTENT_MASK 0x00000800L
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_EXTENT__SHIFT 0x0000000b
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_OFFSET_MASK 0x00001000L
+#define PA_SC_MODE_CNTL_1__ZMM_LINE_OFFSET__SHIFT 0x0000000c
+#define PA_SC_MODE_CNTL_1__ZMM_RECT_EXTENT_MASK 0x00002000L
+#define PA_SC_MODE_CNTL_1__ZMM_RECT_EXTENT__SHIFT 0x0000000d
+#define PA_SC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define PA_SC_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define PA_SC_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SC_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER4_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER4_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER4_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER4_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER4_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER4_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER5_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER5_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER5_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER5_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER5_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER5_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER6_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER6_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER6_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER6_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER6_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER6_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER7_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER7_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER7_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SC_PERFCOUNTER7_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SC_PERFCOUNTER7_SELECT__PERF_SEL_MASK 0x000001ffL
+#define PA_SC_PERFCOUNTER7_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_MAP_MASK 0x00000003L
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_MAP__SHIFT 0x00000000
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_XSEL_MASK 0x0000000cL
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_XSEL__SHIFT 0x00000002
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_YSEL_MASK 0x00000030L
+#define PA_SC_RASTER_CONFIG_1__SE_PAIR_YSEL__SHIFT 0x00000004
+#define PA_SC_RASTER_CONFIG__PKR_MAP_MASK 0x00000300L
+#define PA_SC_RASTER_CONFIG__PKR_MAP__SHIFT 0x00000008
+#define PA_SC_RASTER_CONFIG__PKR_XSEL2_MASK 0x0000c000L
+#define PA_SC_RASTER_CONFIG__PKR_XSEL2__SHIFT 0x0000000e
+#define PA_SC_RASTER_CONFIG__PKR_XSEL_MASK 0x00000c00L
+#define PA_SC_RASTER_CONFIG__PKR_XSEL__SHIFT 0x0000000a
+#define PA_SC_RASTER_CONFIG__PKR_YSEL_MASK 0x00003000L
+#define PA_SC_RASTER_CONFIG__PKR_YSEL__SHIFT 0x0000000c
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR0_MASK 0x00000003L
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR0__SHIFT 0x00000000
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR1_MASK 0x0000000cL
+#define PA_SC_RASTER_CONFIG__RB_MAP_PKR1__SHIFT 0x00000002
+#define PA_SC_RASTER_CONFIG__RB_XSEL2_MASK 0x00000030L
+#define PA_SC_RASTER_CONFIG__RB_XSEL2__SHIFT 0x00000004
+#define PA_SC_RASTER_CONFIG__RB_XSEL_MASK 0x00000040L
+#define PA_SC_RASTER_CONFIG__RB_XSEL__SHIFT 0x00000006
+#define PA_SC_RASTER_CONFIG__RB_YSEL_MASK 0x00000080L
+#define PA_SC_RASTER_CONFIG__RB_YSEL__SHIFT 0x00000007
+#define PA_SC_RASTER_CONFIG__SC_MAP_MASK 0x00030000L
+#define PA_SC_RASTER_CONFIG__SC_MAP__SHIFT 0x00000010
+#define PA_SC_RASTER_CONFIG__SC_XSEL_MASK 0x000c0000L
+#define PA_SC_RASTER_CONFIG__SC_XSEL__SHIFT 0x00000012
+#define PA_SC_RASTER_CONFIG__SC_YSEL_MASK 0x00300000L
+#define PA_SC_RASTER_CONFIG__SC_YSEL__SHIFT 0x00000014
+#define PA_SC_RASTER_CONFIG__SE_MAP_MASK 0x03000000L
+#define PA_SC_RASTER_CONFIG__SE_MAP__SHIFT 0x00000018
+#define PA_SC_RASTER_CONFIG__SE_XSEL_MASK 0x0c000000L
+#define PA_SC_RASTER_CONFIG__SE_XSEL__SHIFT 0x0000001a
+#define PA_SC_RASTER_CONFIG__SE_YSEL_MASK 0x30000000L
+#define PA_SC_RASTER_CONFIG__SE_YSEL__SHIFT 0x0000001c
+#define PA_SC_SCREEN_SCISSOR_BR__BR_X_MASK 0x0000ffffL
+#define PA_SC_SCREEN_SCISSOR_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_SCREEN_SCISSOR_BR__BR_Y_MASK 0xffff0000L
+#define PA_SC_SCREEN_SCISSOR_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_SCREEN_SCISSOR_TL__TL_X_MASK 0x0000ffffL
+#define PA_SC_SCREEN_SCISSOR_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_SCREEN_SCISSOR_TL__TL_Y_MASK 0xffff0000L
+#define PA_SC_SCREEN_SCISSOR_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_0_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_0_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_0_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_0_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_10_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_10_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_10_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_10_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_11_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_11_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_11_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_11_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_12_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_12_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_12_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_12_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_13_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_13_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_13_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_13_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_14_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_14_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_14_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_14_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_15_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_15_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_15_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_15_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_1_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_1_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_1_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_1_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_2_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_2_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_2_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_2_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_3_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_3_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_3_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_3_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_4_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_4_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_4_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_4_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_5_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_5_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_5_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_5_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_6_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_6_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_6_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_6_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_7_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_7_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_7_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_7_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_8_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_8_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_8_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_8_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_9_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_VPORT_SCISSOR_9_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_VPORT_SCISSOR_9_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_VPORT_SCISSOR_9_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SC_VPORT_ZMAX_0__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_0__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_10__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_10__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_11__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_11__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_12__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_12__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_13__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_13__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_14__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_14__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_15__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_15__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_1__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_1__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_2__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_2__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_3__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_3__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_4__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_4__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_5__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_5__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_6__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_6__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_7__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_7__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_8__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_8__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMAX_9__VPORT_ZMAX_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMAX_9__VPORT_ZMAX__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_0__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_0__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_10__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_10__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_11__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_11__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_12__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_12__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_13__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_13__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_14__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_14__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_15__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_15__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_1__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_1__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_2__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_2__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_3__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_3__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_4__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_4__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_5__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_5__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_6__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_6__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_7__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_7__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_8__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_8__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_VPORT_ZMIN_9__VPORT_ZMIN_MASK 0xffffffffL
+#define PA_SC_VPORT_ZMIN_9__VPORT_ZMIN__SHIFT 0x00000000
+#define PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET_MASK 0x0000ffffL
+#define PA_SC_WINDOW_OFFSET__WINDOW_X_OFFSET__SHIFT 0x00000000
+#define PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET_MASK 0xffff0000L
+#define PA_SC_WINDOW_OFFSET__WINDOW_Y_OFFSET__SHIFT 0x00000010
+#define PA_SC_WINDOW_SCISSOR_BR__BR_X_MASK 0x00007fffL
+#define PA_SC_WINDOW_SCISSOR_BR__BR_X__SHIFT 0x00000000
+#define PA_SC_WINDOW_SCISSOR_BR__BR_Y_MASK 0x7fff0000L
+#define PA_SC_WINDOW_SCISSOR_BR__BR_Y__SHIFT 0x00000010
+#define PA_SC_WINDOW_SCISSOR_TL__TL_X_MASK 0x00007fffL
+#define PA_SC_WINDOW_SCISSOR_TL__TL_X__SHIFT 0x00000000
+#define PA_SC_WINDOW_SCISSOR_TL__TL_Y_MASK 0x7fff0000L
+#define PA_SC_WINDOW_SCISSOR_TL__TL_Y__SHIFT 0x00000010
+#define PA_SC_WINDOW_SCISSOR_TL__WINDOW_OFFSET_DISABLE_MASK 0x80000000L
+#define PA_SC_WINDOW_SCISSOR_TL__WINDOW_OFFSET_DISABLE__SHIFT 0x0000001f
+#define PA_SU_CNTL_STATUS__SU_BUSY_MASK 0x80000000L
+#define PA_SU_CNTL_STATUS__SU_BUSY__SHIFT 0x0000001f
+#define PA_SU_DEBUG_CNTL__SU_DEBUG_INDX_MASK 0x0000001fL
+#define PA_SU_DEBUG_CNTL__SU_DEBUG_INDX__SHIFT 0x00000000
+#define PA_SU_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define PA_SU_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_X_MASK 0x000001ffL
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_X__SHIFT 0x00000000
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_Y_MASK 0x01ff0000L
+#define PA_SU_HARDWARE_SCREEN_OFFSET__HW_SCREEN_OFFSET_Y__SHIFT 0x00000010
+#define PA_SU_LINE_CNTL__WIDTH_MASK 0x0000ffffL
+#define PA_SU_LINE_CNTL__WIDTH__SHIFT 0x00000000
+#define PA_SU_LINE_STIPPLE_CNTL__DIAMOND_ADJUST_MASK 0x00000010L
+#define PA_SU_LINE_STIPPLE_CNTL__DIAMOND_ADJUST__SHIFT 0x00000004
+#define PA_SU_LINE_STIPPLE_CNTL__EXPAND_FULL_LENGTH_MASK 0x00000004L
+#define PA_SU_LINE_STIPPLE_CNTL__EXPAND_FULL_LENGTH__SHIFT 0x00000002
+#define PA_SU_LINE_STIPPLE_CNTL__FRACTIONAL_ACCUM_MASK 0x00000008L
+#define PA_SU_LINE_STIPPLE_CNTL__FRACTIONAL_ACCUM__SHIFT 0x00000003
+#define PA_SU_LINE_STIPPLE_CNTL__LINE_STIPPLE_RESET_MASK 0x00000003L
+#define PA_SU_LINE_STIPPLE_CNTL__LINE_STIPPLE_RESET__SHIFT 0x00000000
+#define PA_SU_LINE_STIPPLE_SCALE__LINE_STIPPLE_SCALE_MASK 0xffffffffL
+#define PA_SU_LINE_STIPPLE_SCALE__LINE_STIPPLE_SCALE__SHIFT 0x00000000
+#define PA_SU_LINE_STIPPLE_VALUE__LINE_STIPPLE_VALUE_MASK 0x00ffffffL
+#define PA_SU_LINE_STIPPLE_VALUE__LINE_STIPPLE_VALUE__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0x0000ffffL
+#define PA_SU_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define PA_SU_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define PA_SU_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define PA_SU_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define PA_SU_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define PA_SU_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define PA_SU_POINT_MINMAX__MAX_SIZE_MASK 0xffff0000L
+#define PA_SU_POINT_MINMAX__MAX_SIZE__SHIFT 0x00000010
+#define PA_SU_POINT_MINMAX__MIN_SIZE_MASK 0x0000ffffL
+#define PA_SU_POINT_MINMAX__MIN_SIZE__SHIFT 0x00000000
+#define PA_SU_POINT_SIZE__HEIGHT_MASK 0x0000ffffL
+#define PA_SU_POINT_SIZE__HEIGHT__SHIFT 0x00000000
+#define PA_SU_POINT_SIZE__WIDTH_MASK 0xffff0000L
+#define PA_SU_POINT_SIZE__WIDTH__SHIFT 0x00000010
+#define PA_SU_POLY_OFFSET_BACK_OFFSET__OFFSET_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_BACK_OFFSET__OFFSET__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_BACK_SCALE__SCALE_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_BACK_SCALE__SCALE__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_CLAMP__CLAMP_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_CLAMP__CLAMP__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_DB_IS_FLOAT_FMT_MASK 0x00000100L
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_DB_IS_FLOAT_FMT__SHIFT 0x00000008
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_NEG_NUM_DB_BITS_MASK 0x000000ffL
+#define PA_SU_POLY_OFFSET_DB_FMT_CNTL__POLY_OFFSET_NEG_NUM_DB_BITS__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_FRONT_OFFSET__OFFSET_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_FRONT_OFFSET__OFFSET__SHIFT 0x00000000
+#define PA_SU_POLY_OFFSET_FRONT_SCALE__SCALE_MASK 0xffffffffL
+#define PA_SU_POLY_OFFSET_FRONT_SCALE__SCALE__SHIFT 0x00000000
+#define PA_SU_PRIM_FILTER_CNTL__LINE_EXPAND_ENA_MASK 0x00000020L
+#define PA_SU_PRIM_FILTER_CNTL__LINE_EXPAND_ENA__SHIFT 0x00000005
+#define PA_SU_PRIM_FILTER_CNTL__LINE_FILTER_DISABLE_MASK 0x00000002L
+#define PA_SU_PRIM_FILTER_CNTL__LINE_FILTER_DISABLE__SHIFT 0x00000001
+#define PA_SU_PRIM_FILTER_CNTL__POINT_EXPAND_ENA_MASK 0x00000040L
+#define PA_SU_PRIM_FILTER_CNTL__POINT_EXPAND_ENA__SHIFT 0x00000006
+#define PA_SU_PRIM_FILTER_CNTL__POINT_FILTER_DISABLE_MASK 0x00000004L
+#define PA_SU_PRIM_FILTER_CNTL__POINT_FILTER_DISABLE__SHIFT 0x00000002
+#define PA_SU_PRIM_FILTER_CNTL__PRIM_EXPAND_CONSTANT_MASK 0x0000ff00L
+#define PA_SU_PRIM_FILTER_CNTL__PRIM_EXPAND_CONSTANT__SHIFT 0x00000008
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_EXPAND_ENA_MASK 0x00000080L
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_EXPAND_ENA__SHIFT 0x00000007
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_FILTER_DISABLE_MASK 0x00000008L
+#define PA_SU_PRIM_FILTER_CNTL__RECTANGLE_FILTER_DISABLE__SHIFT 0x00000003
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_EXPAND_ENA_MASK 0x00000010L
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_EXPAND_ENA__SHIFT 0x00000004
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_FILTER_DISABLE_MASK 0x00000001L
+#define PA_SU_PRIM_FILTER_CNTL__TRIANGLE_FILTER_DISABLE__SHIFT 0x00000000
+#define PA_SU_PRIM_FILTER_CNTL__XMAX_RIGHT_EXCLUSION_MASK 0x40000000L
+#define PA_SU_PRIM_FILTER_CNTL__XMAX_RIGHT_EXCLUSION__SHIFT 0x0000001e
+#define PA_SU_PRIM_FILTER_CNTL__YMAX_BOTTOM_EXCLUSION_MASK 0x80000000L
+#define PA_SU_PRIM_FILTER_CNTL__YMAX_BOTTOM_EXCLUSION__SHIFT 0x0000001f
+#define PA_SU_SC_MODE_CNTL__CULL_BACK_MASK 0x00000002L
+#define PA_SU_SC_MODE_CNTL__CULL_BACK__SHIFT 0x00000001
+#define PA_SU_SC_MODE_CNTL__CULL_FRONT_MASK 0x00000001L
+#define PA_SU_SC_MODE_CNTL__CULL_FRONT__SHIFT 0x00000000
+#define PA_SU_SC_MODE_CNTL__FACE_MASK 0x00000004L
+#define PA_SU_SC_MODE_CNTL__FACE__SHIFT 0x00000002
+#define PA_SU_SC_MODE_CNTL__MULTI_PRIM_IB_ENA_MASK 0x00200000L
+#define PA_SU_SC_MODE_CNTL__MULTI_PRIM_IB_ENA__SHIFT 0x00000015
+#define PA_SU_SC_MODE_CNTL__PERSP_CORR_DIS_MASK 0x00100000L
+#define PA_SU_SC_MODE_CNTL__PERSP_CORR_DIS__SHIFT 0x00000014
+#define PA_SU_SC_MODE_CNTL__POLYMODE_BACK_PTYPE_MASK 0x00000700L
+#define PA_SU_SC_MODE_CNTL__POLYMODE_BACK_PTYPE__SHIFT 0x00000008
+#define PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE_MASK 0x000000e0L
+#define PA_SU_SC_MODE_CNTL__POLYMODE_FRONT_PTYPE__SHIFT 0x00000005
+#define PA_SU_SC_MODE_CNTL__POLY_MODE_MASK 0x00000018L
+#define PA_SU_SC_MODE_CNTL__POLY_MODE__SHIFT 0x00000003
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_BACK_ENABLE_MASK 0x00001000L
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_BACK_ENABLE__SHIFT 0x0000000c
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_FRONT_ENABLE_MASK 0x00000800L
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_FRONT_ENABLE__SHIFT 0x0000000b
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_PARA_ENABLE_MASK 0x00002000L
+#define PA_SU_SC_MODE_CNTL__POLY_OFFSET_PARA_ENABLE__SHIFT 0x0000000d
+#define PA_SU_SC_MODE_CNTL__PROVOKING_VTX_LAST_MASK 0x00080000L
+#define PA_SU_SC_MODE_CNTL__PROVOKING_VTX_LAST__SHIFT 0x00000013
+#define PA_SU_SC_MODE_CNTL__VTX_WINDOW_OFFSET_ENABLE_MASK 0x00010000L
+#define PA_SU_SC_MODE_CNTL__VTX_WINDOW_OFFSET_ENABLE__SHIFT 0x00000010
+#define PA_SU_VTX_CNTL__PIX_CENTER_MASK 0x00000001L
+#define PA_SU_VTX_CNTL__PIX_CENTER__SHIFT 0x00000000
+#define PA_SU_VTX_CNTL__QUANT_MODE_MASK 0x00000038L
+#define PA_SU_VTX_CNTL__QUANT_MODE__SHIFT 0x00000003
+#define PA_SU_VTX_CNTL__ROUND_MODE_MASK 0x00000006L
+#define PA_SU_VTX_CNTL__ROUND_MODE__SHIFT 0x00000001
+#define RAS_BCI_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_BCI_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_BCI_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_BCI_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_CB_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_CB_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_DB_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_DB_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_IA_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_IA_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_IA_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_IA_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_PA_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_PA_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE2__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE2__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE3__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE3__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE4__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE4__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE5__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE5__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE6__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE6__SIGNATURE__SHIFT 0x00000000
+#define RAS_SC_SIGNATURE7__SIGNATURE_MASK 0xffffffffL
+#define RAS_SC_SIGNATURE7__SIGNATURE__SHIFT 0x00000000
+#define RAS_SIGNATURE_CONTROL__ENABLE_MASK 0x00000001L
+#define RAS_SIGNATURE_CONTROL__ENABLE__SHIFT 0x00000000
+#define RAS_SIGNATURE_MASK__INPUT_BUS_MASK_MASK 0xffffffffL
+#define RAS_SIGNATURE_MASK__INPUT_BUS_MASK__SHIFT 0x00000000
+#define RAS_SPI_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SPI_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SPI_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_SPI_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_SQ_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SQ_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE1__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE1__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE2__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE2__SIGNATURE__SHIFT 0x00000000
+#define RAS_SX_SIGNATURE3__SIGNATURE_MASK 0xffffffffL
+#define RAS_SX_SIGNATURE3__SIGNATURE__SHIFT 0x00000000
+#define RAS_TA_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_TA_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_TD_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_TD_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RAS_VGT_SIGNATURE0__SIGNATURE_MASK 0xffffffffL
+#define RAS_VGT_SIGNATURE0__SIGNATURE__SHIFT 0x00000000
+#define RLC_AUTO_PG_CTRL__AUTO_GRBM_REG_SAVE_ON_IDLE_EN_MASK 0x00000002L
+#define RLC_AUTO_PG_CTRL__AUTO_GRBM_REG_SAVE_ON_IDLE_EN__SHIFT 0x00000001
+#define RLC_AUTO_PG_CTRL__AUTO_PG_EN_MASK 0x00000001L
+#define RLC_AUTO_PG_CTRL__AUTO_PG_EN__SHIFT 0x00000000
+#define RLC_AUTO_PG_CTRL__AUTO_WAKE_UP_EN_MASK 0x00000004L
+#define RLC_AUTO_PG_CTRL__AUTO_WAKE_UP_EN__SHIFT 0x00000002
+#define RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD_MASK 0x0007fff8L
+#define RLC_AUTO_PG_CTRL__GRBM_REG_SAVE_GFX_IDLE_THRESHOLD__SHIFT 0x00000003
+#define RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD_MASK 0xfff80000L
+#define RLC_AUTO_PG_CTRL__PG_AFTER_GRBM_REG_SAVE_THRESHOLD__SHIFT 0x00000013
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__CAPTURE_MASK 0x00000001L
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__CAPTURE__SHIFT 0x00000000
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__RESERVED_MASK 0xfffffffeL
+#define RLC_CAPTURE_GPU_CLOCK_COUNT__RESERVED__SHIFT 0x00000001
+#define RLC_CGCG_CGLS_CTRL__CGCG_CONTROLLER_MASK 0x08000000L
+#define RLC_CGCG_CGLS_CTRL__CGCG_CONTROLLER__SHIFT 0x0000001b
+#define RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK 0x00000001L
+#define RLC_CGCG_CGLS_CTRL__CGCG_EN__SHIFT 0x00000000
+#define RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD_MASK 0x0000ff00L
+#define RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT 0x00000008
+#define RLC_CGCG_CGLS_CTRL__CGCG_REG_CTRL_MASK 0x10000000L
+#define RLC_CGCG_CGLS_CTRL__CGCG_REG_CTRL__SHIFT 0x0000001c
+#define RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK 0x00000002L
+#define RLC_CGCG_CGLS_CTRL__CGLS_EN__SHIFT 0x00000001
+#define RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY_MASK 0x000000fcL
+#define RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT 0x00000002
+#define RLC_CGCG_CGLS_CTRL__SLEEP_MODE_MASK 0x60000000L
+#define RLC_CGCG_CGLS_CTRL__SLEEP_MODE__SHIFT 0x0000001d
+#define RLC_CGCG_CGLS_CTRL__SPARE_MASK 0x80000000L
+#define RLC_CGCG_CGLS_CTRL__SPARE__SHIFT 0x0000001f
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_START_UNIT_MASK 0x0000000fL
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_START_UNIT__SHIFT 0x00000000
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_STEP_UNIT_MASK 0x000000f0L
+#define RLC_CGCG_RAMP_CTRL__DOWN_DIV_STEP_UNIT__SHIFT 0x00000004
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_CNT_MASK 0x0fff0000L
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_CNT__SHIFT 0x00000010
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_UNIT_MASK 0xf0000000L
+#define RLC_CGCG_RAMP_CTRL__STEP_DELAY_UNIT__SHIFT 0x0000001c
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_START_UNIT_MASK 0x00000f00L
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_START_UNIT__SHIFT 0x00000008
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_STEP_UNIT_MASK 0x0000f000L
+#define RLC_CGCG_RAMP_CTRL__UP_DIV_STEP_UNIT__SHIFT 0x0000000c
+#define RLC_CGTT_MGCG_OVERRIDE__OVERRIDE_MASK 0xffffffffL
+#define RLC_CGTT_MGCG_OVERRIDE__OVERRIDE__SHIFT 0x00000000
+#define RLC_CNTL__FORCE_RETRY_MASK 0x00000002L
+#define RLC_CNTL__FORCE_RETRY__SHIFT 0x00000001
+#define RLC_CNTL__READ_CACHE_DISABLE_MASK 0x00000004L
+#define RLC_CNTL__READ_CACHE_DISABLE__SHIFT 0x00000002
+#define RLC_CNTL__RESERVED_MASK 0xffffff00L
+#define RLC_CNTL__RESERVED__SHIFT 0x00000008
+#define RLC_CNTL__RLC_ENABLE_F32_MASK 0x00000001L
+#define RLC_CNTL__RLC_ENABLE_F32__SHIFT 0x00000000
+#define RLC_CNTL__RLC_STEP_F32_MASK 0x00000008L
+#define RLC_CNTL__RLC_STEP_F32__SHIFT 0x00000003
+#define RLC_CNTL__SOFT_RESET_DEBUG_MODE_MASK 0x00000010L
+#define RLC_CNTL__SOFT_RESET_DEBUG_MODE__SHIFT 0x00000004
+#define RLC_CU_STATUS__WORK_PENDING_MASK 0xffffffffL
+#define RLC_CU_STATUS__WORK_PENDING__SHIFT 0x00000000
+#define RLC_DEBUG__DATA_MASK 0xffffffffL
+#define RLC_DEBUG__DATA__SHIFT 0x00000000
+#define RLC_DEBUG_SELECT__RESERVED_MASK 0xffff8000L
+#define RLC_DEBUG_SELECT__RESERVED__SHIFT 0x0000000f
+#define RLC_DEBUG_SELECT__SELECT_MASK 0x000000ffL
+#define RLC_DEBUG_SELECT__SELECT__SHIFT 0x00000000
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_ACK_MASK 0x00000010L
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_ACK__SHIFT 0x00000004
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_REQUEST_MASK 0x00000001L
+#define RLC_DRIVER_CPDMA_STATUS__DRIVER_REQUEST__SHIFT 0x00000000
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED1_MASK 0x0000000eL
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED1__SHIFT 0x00000001
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED_MASK 0xffffffe0L
+#define RLC_DRIVER_CPDMA_STATUS__RESERVED__SHIFT 0x00000005
+#define RLC_DYN_PG_REQUEST__PG_REQUEST_CU_MASK_MASK 0xffffffffL
+#define RLC_DYN_PG_REQUEST__PG_REQUEST_CU_MASK__SHIFT 0x00000000
+#define RLC_DYN_PG_STATUS__PG_STATUS_CU_MASK_MASK 0xffffffffL
+#define RLC_DYN_PG_STATUS__PG_STATUS_CU_MASK__SHIFT 0x00000000
+#define RLC_GPM_SCRATCH_ADDR__ADDR_MASK 0x000001ffL
+#define RLC_GPM_SCRATCH_ADDR__ADDR__SHIFT 0x00000000
+#define RLC_GPM_SCRATCH_ADDR__RESERVED_MASK 0xfffffe00L
+#define RLC_GPM_SCRATCH_ADDR__RESERVED__SHIFT 0x00000009
+#define RLC_GPU_CLOCK_32__GPU_CLOCK_32_MASK 0xffffffffL
+#define RLC_GPU_CLOCK_32__GPU_CLOCK_32__SHIFT 0x00000000
+#define RLC_GPU_CLOCK_32_RES_SEL__RESERVED_MASK 0xffffffc0L
+#define RLC_GPU_CLOCK_32_RES_SEL__RESERVED__SHIFT 0x00000006
+#define RLC_GPU_CLOCK_32_RES_SEL__RES_SEL_MASK 0x0000003fL
+#define RLC_GPU_CLOCK_32_RES_SEL__RES_SEL__SHIFT 0x00000000
+#define RLC_GPU_CLOCK_COUNT_LSB__GPU_CLOCKS_LSB_MASK 0xffffffffL
+#define RLC_GPU_CLOCK_COUNT_LSB__GPU_CLOCKS_LSB__SHIFT 0x00000000
+#define RLC_GPU_CLOCK_COUNT_MSB__GPU_CLOCKS_MSB_MASK 0xffffffffL
+#define RLC_GPU_CLOCK_COUNT_MSB__GPU_CLOCKS_MSB__SHIFT 0x00000000
+#define RLC_LB_ALWAYS_ACTIVE_CU_MASK__ALWAYS_ACTIVE_CU_MASK_MASK 0xffffffffL
+#define RLC_LB_ALWAYS_ACTIVE_CU_MASK__ALWAYS_ACTIVE_CU_MASK__SHIFT 0x00000000
+#define RLC_LB_CNTL__CU_MASK_USED_OFF_HYST_MASK 0x00000ff0L
+#define RLC_LB_CNTL__CU_MASK_USED_OFF_HYST__SHIFT 0x00000004
+#define RLC_LB_CNTL__LB_CNT_CP_BUSY_MASK 0x00000002L
+#define RLC_LB_CNTL__LB_CNT_CP_BUSY__SHIFT 0x00000001
+#define RLC_LB_CNTL__LB_CNT_REG_INC_MASK 0x00000008L
+#define RLC_LB_CNTL__LB_CNT_REG_INC__SHIFT 0x00000003
+#define RLC_LB_CNTL__LB_CNT_SPIM_ACTIVE_MASK 0x00000004L
+#define RLC_LB_CNTL__LB_CNT_SPIM_ACTIVE__SHIFT 0x00000002
+#define RLC_LB_CNTL__LOAD_BALANCE_ENABLE_MASK 0x00000001L
+#define RLC_LB_CNTL__LOAD_BALANCE_ENABLE__SHIFT 0x00000000
+#define RLC_LB_CNTL__RESERVED_MASK 0xfffffff0L
+#define RLC_LB_CNTL__RESERVED__SHIFT 0x00000004
+#define RLC_LB_CNTR_INIT__LB_CNTR_INIT_MASK 0xffffffffL
+#define RLC_LB_CNTR_INIT__LB_CNTR_INIT__SHIFT 0x00000000
+#define RLC_LB_CNTR_MAX__LB_CNTR_MAX_MASK 0xffffffffL
+#define RLC_LB_CNTR_MAX__LB_CNTR_MAX__SHIFT 0x00000000
+#define RLC_LB_INIT_CU_MASK__INIT_CU_MASK_MASK 0xffffffffL
+#define RLC_LB_INIT_CU_MASK__INIT_CU_MASK__SHIFT 0x00000000
+#define RLC_LB_PARAMS__FIFO_SAMPLES_MASK 0x000000feL
+#define RLC_LB_PARAMS__FIFO_SAMPLES__SHIFT 0x00000001
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLE_INTERVAL_MASK 0xffff0000L
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLE_INTERVAL__SHIFT 0x00000010
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLES_MASK 0x0000ff00L
+#define RLC_LB_PARAMS__PG_IDLE_SAMPLES__SHIFT 0x00000008
+#define RLC_LB_PARAMS__SKIP_L2_CHECK_MASK 0x00000001L
+#define RLC_LB_PARAMS__SKIP_L2_CHECK__SHIFT 0x00000000
+#define RLC_LOAD_BALANCE_CNTR__RLC_LOAD_BALANCE_CNTR_MASK 0xffffffffL
+#define RLC_LOAD_BALANCE_CNTR__RLC_LOAD_BALANCE_CNTR__SHIFT 0x00000000
+#define RLC_MAX_PG_CU__MAX_POWERED_UP_CU_MASK 0x000000ffL
+#define RLC_MAX_PG_CU__MAX_POWERED_UP_CU__SHIFT 0x00000000
+#define RLC_MAX_PG_CU__SPARE_MASK 0xffffff00L
+#define RLC_MAX_PG_CU__SPARE__SHIFT 0x00000008
+#define RLC_MC_CNTL__RDNFO_STALL_MASK 0x10000000L
+#define RLC_MC_CNTL__RDNFO_STALL__SHIFT 0x0000001c
+#define RLC_MC_CNTL__RDNFO_URG_MASK 0x00f00000L
+#define RLC_MC_CNTL__RDNFO_URG__SHIFT 0x00000014
+#define RLC_MC_CNTL__RDREQ_PRIV_MASK 0x08000000L
+#define RLC_MC_CNTL__RDREQ_PRIV__SHIFT 0x0000001b
+#define RLC_MC_CNTL__RDREQ_SWAP_MASK 0x03000000L
+#define RLC_MC_CNTL__RDREQ_SWAP__SHIFT 0x00000018
+#define RLC_MC_CNTL__RDREQ_TRAN_MASK 0x04000000L
+#define RLC_MC_CNTL__RDREQ_TRAN__SHIFT 0x0000001a
+#define RLC_MC_CNTL__RESERVED_B_MASK 0x000fe000L
+#define RLC_MC_CNTL__RESERVED_B__SHIFT 0x0000000d
+#define RLC_MC_CNTL__RESERVED_MASK 0xe0000000L
+#define RLC_MC_CNTL__RESERVED__SHIFT 0x0000001d
+#define RLC_MC_CNTL__WRNFO_STALL_MASK 0x00000010L
+#define RLC_MC_CNTL__WRNFO_STALL__SHIFT 0x00000004
+#define RLC_MC_CNTL__WRNFO_URG_MASK 0x000001e0L
+#define RLC_MC_CNTL__WRNFO_URG__SHIFT 0x00000005
+#define RLC_MC_CNTL__WRREQ_DW_IMASK_MASK 0x00001e00L
+#define RLC_MC_CNTL__WRREQ_DW_IMASK__SHIFT 0x00000009
+#define RLC_MC_CNTL__WRREQ_PRIV_MASK 0x00000008L
+#define RLC_MC_CNTL__WRREQ_PRIV__SHIFT 0x00000003
+#define RLC_MC_CNTL__WRREQ_SWAP_MASK 0x00000003L
+#define RLC_MC_CNTL__WRREQ_SWAP__SHIFT 0x00000000
+#define RLC_MC_CNTL__WRREQ_TRAN_MASK 0x00000004L
+#define RLC_MC_CNTL__WRREQ_TRAN__SHIFT 0x00000002
+#define RLC_MEM_SLP_CNTL__RESERVED1_MASK 0xff000000L
+#define RLC_MEM_SLP_CNTL__RESERVED1__SHIFT 0x00000018
+#define RLC_MEM_SLP_CNTL__RESERVED_MASK 0x000000fcL
+#define RLC_MEM_SLP_CNTL__RESERVED__SHIFT 0x00000002
+#define RLC_MEM_SLP_CNTL__RLC_MEM_DS_EN_MASK 0x00000002L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_DS_EN__SHIFT 0x00000001
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK 0x00000001L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN__SHIFT 0x00000000
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_OFF_DELAY_MASK 0x00ff0000L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_OFF_DELAY__SHIFT 0x00000010
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_ON_DELAY_MASK 0x0000ff00L
+#define RLC_MEM_SLP_CNTL__RLC_MEM_LS_ON_DELAY__SHIFT 0x00000008
+#define RLC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define RLC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define RLC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define RLC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define RLC_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define RLC_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define RLC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define RLC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define RLC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define RLC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define RLC_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define RLC_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define RLC_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x00000400L
+#define RLC_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0x0000000a
+#define RLC_PERFMON_CNTL__PERFMON_STATE_MASK 0x00000007L
+#define RLC_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x00000000
+#define RLC_PG_ALWAYS_ON_CU_MASK__AON_CU_MASK_MASK 0xffffffffL
+#define RLC_PG_ALWAYS_ON_CU_MASK__AON_CU_MASK__SHIFT 0x00000000
+#define RLC_PG_CNTL__CHUB_HANDSHAKE_ENABLE_MASK 0x00010000L
+#define RLC_PG_CNTL__CHUB_HANDSHAKE_ENABLE__SHIFT 0x00000010
+#define RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE_MASK 0x00000004L
+#define RLC_PG_CNTL__DYN_PER_CU_PG_ENABLE__SHIFT 0x00000002
+#define RLC_PG_CNTL__GFX_POWER_GATING_ENABLE_MASK 0x00000001L
+#define RLC_PG_CNTL__GFX_POWER_GATING_ENABLE__SHIFT 0x00000000
+#define RLC_PG_CNTL__GFX_POWER_GATING_SRC_MASK 0x00000002L
+#define RLC_PG_CNTL__GFX_POWER_GATING_SRC__SHIFT 0x00000001
+#define RLC_PG_CNTL__PG_ERROR_STATUS_MASK 0xff000000L
+#define RLC_PG_CNTL__PG_ERROR_STATUS__SHIFT 0x00000018
+#define RLC_PG_CNTL__RESERVED1_MASK 0x00f80000L
+#define RLC_PG_CNTL__RESERVED1__SHIFT 0x00000013
+#define RLC_PG_CNTL__RESERVED_MASK 0xfffffff0L
+#define RLC_PG_CNTL__RESERVED__SHIFT 0x00000004
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE_MASK 0x00040000L
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PD_ENABLE__SHIFT 0x00000012
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE_MASK 0x00020000L
+#define RLC_PG_CNTL__SMU_CLK_SLOWDOWN_ON_PU_ENABLE__SHIFT 0x00000011
+#define RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE_MASK 0x00000008L
+#define RLC_PG_CNTL__STATIC_PER_CU_PG_ENABLE__SHIFT 0x00000003
+#define RLC_SAVE_AND_RESTORE_BASE__BASE_MASK 0xffffffffL
+#define RLC_SAVE_AND_RESTORE_BASE__BASE__SHIFT 0x00000000
+#define RLC_SERDES_RD_DATA_0__DATA_MASK 0xffffffffL
+#define RLC_SERDES_RD_DATA_0__DATA__SHIFT 0x00000000
+#define RLC_SERDES_RD_DATA_1__DATA_MASK 0xffffffffL
+#define RLC_SERDES_RD_DATA_1__DATA__SHIFT 0x00000000
+#define RLC_SERDES_RD_DATA_2__DATA_MASK 0xffffffffL
+#define RLC_SERDES_RD_DATA_2__DATA__SHIFT 0x00000000
+#define RLC_SERDES_RD_MASTER_INDEX__CU_ID_MASK 0x0000000fL
+#define RLC_SERDES_RD_MASTER_INDEX__CU_ID__SHIFT 0x00000000
+#define RLC_SERDES_RD_MASTER_INDEX__DATA_REG_ID_MASK 0x0000c000L
+#define RLC_SERDES_RD_MASTER_INDEX__DATA_REG_ID__SHIFT 0x0000000e
+#define RLC_SERDES_RD_MASTER_INDEX__NON_SE_MASK 0x00003800L
+#define RLC_SERDES_RD_MASTER_INDEX__NON_SE__SHIFT 0x0000000b
+#define RLC_SERDES_RD_MASTER_INDEX__SE_ID_MASK 0x000001c0L
+#define RLC_SERDES_RD_MASTER_INDEX__SE_ID__SHIFT 0x00000006
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_ID_MASK 0x00000200L
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_ID__SHIFT 0x00000009
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU_MASK 0x00000400L
+#define RLC_SERDES_RD_MASTER_INDEX__SE_NONCU__SHIFT 0x0000000a
+#define RLC_SERDES_RD_MASTER_INDEX__SH_ID_MASK 0x00000030L
+#define RLC_SERDES_RD_MASTER_INDEX__SH_ID__SHIFT 0x00000004
+#define RLC_SERDES_RD_MASTER_INDEX__SPARE_MASK 0xffffc000L
+#define RLC_SERDES_RD_MASTER_INDEX__SPARE__SHIFT 0x0000000e
+#define RLC_SERDES_WR_CTRL__BPM_ADDR_MASK 0x000000ffL
+#define RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT 0x00000000
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_0_MASK 0x00100000L
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_0__SHIFT 0x00000014
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_1_MASK 0x00200000L
+#define RLC_SERDES_WR_CTRL__CGCG_OVERRIDE_1__SHIFT 0x00000015
+#define RLC_SERDES_WR_CTRL__CGLS_DISABLE_MASK 0x00020000L
+#define RLC_SERDES_WR_CTRL__CGLS_DISABLE__SHIFT 0x00000011
+#define RLC_SERDES_WR_CTRL__CGLS_ENABLE_MASK 0x00010000L
+#define RLC_SERDES_WR_CTRL__CGLS_ENABLE__SHIFT 0x00000010
+#define RLC_SERDES_WR_CTRL__CGLS_OFF_MASK 0x00080000L
+#define RLC_SERDES_WR_CTRL__CGLS_OFF__SHIFT 0x00000013
+#define RLC_SERDES_WR_CTRL__CGLS_ON_MASK 0x00040000L
+#define RLC_SERDES_WR_CTRL__CGLS_ON__SHIFT 0x00000012
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_0_MASK 0x00400000L
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_0__SHIFT 0x00000016
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_1_MASK 0x00800000L
+#define RLC_SERDES_WR_CTRL__MGCG_OVERRIDE_1__SHIFT 0x00000017
+#define RLC_SERDES_WR_CTRL__P1_SELECT_MASK 0x00000400L
+#define RLC_SERDES_WR_CTRL__P1_SELECT__SHIFT 0x0000000a
+#define RLC_SERDES_WR_CTRL__P2_SELECT_MASK 0x00000800L
+#define RLC_SERDES_WR_CTRL__P2_SELECT__SHIFT 0x0000000b
+#define RLC_SERDES_WR_CTRL__POWER_DOWN_MASK 0x00000100L
+#define RLC_SERDES_WR_CTRL__POWER_DOWN__SHIFT 0x00000008
+#define RLC_SERDES_WR_CTRL__POWER_UP_MASK 0x00000200L
+#define RLC_SERDES_WR_CTRL__POWER_UP__SHIFT 0x00000009
+#define RLC_SERDES_WR_CTRL__READ_COMMAND_MASK 0x00002000L
+#define RLC_SERDES_WR_CTRL__READ_COMMAND__SHIFT 0x0000000d
+#define RLC_SERDES_WR_CTRL__REG_ADDR_MASK 0xf0000000L
+#define RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT 0x0000001c
+#define RLC_SERDES_WR_CTRL__RESERVED_1_MASK 0x0000c000L
+#define RLC_SERDES_WR_CTRL__RESERVED_1__SHIFT 0x0000000e
+#define RLC_SERDES_WR_CTRL__RESERVED_2_MASK 0x0f000000L
+#define RLC_SERDES_WR_CTRL__RESERVED_2__SHIFT 0x00000018
+#define RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK 0x00001000L
+#define RLC_SERDES_WR_CTRL__WRITE_COMMAND__SHIFT 0x0000000c
+#define RLC_SERDES_WR_DATA__DATA_MASK 0xffffffffL
+#define RLC_SERDES_WR_DATA__DATA__SHIFT 0x00000000
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__SPARE_MASK 0xfffffffeL
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__SPARE__SHIFT 0x00000001
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__START_GRBM_REG_SAVE_MASK 0x00000001L
+#define RLC_SMU_GRBM_REG_SAVE_CTRL__START_GRBM_REG_SAVE__SHIFT 0x00000000
+#define RLC_SMU_PG_CTRL__SPARE_MASK 0xfffffffeL
+#define RLC_SMU_PG_CTRL__SPARE__SHIFT 0x00000001
+#define RLC_SMU_PG_CTRL__START_PG_MASK 0x00000001L
+#define RLC_SMU_PG_CTRL__START_PG__SHIFT 0x00000000
+#define RLC_SMU_PG_WAKE_UP_CTRL__SPARE_MASK 0xfffffffeL
+#define RLC_SMU_PG_WAKE_UP_CTRL__SPARE__SHIFT 0x00000001
+#define RLC_SMU_PG_WAKE_UP_CTRL__START_PG_WAKE_UP_MASK 0x00000001L
+#define RLC_SMU_PG_WAKE_UP_CTRL__START_PG_WAKE_UP__SHIFT 0x00000000
+#define RLC_SOFT_RESET_GPU__RESERVED_MASK 0xfffffffeL
+#define RLC_SOFT_RESET_GPU__RESERVED__SHIFT 0x00000001
+#define RLC_SOFT_RESET_GPU__SOFT_RESET_GPU_MASK 0x00000001L
+#define RLC_SOFT_RESET_GPU__SOFT_RESET_GPU__SHIFT 0x00000000
+#define RLC_STATIC_PG_STATUS__PG_STATUS_CU_MASK_MASK 0xffffffffL
+#define RLC_STATIC_PG_STATUS__PG_STATUS_CU_MASK__SHIFT 0x00000000
+#define RLC_STAT__RESERVED_MASK 0xfffffff0L
+#define RLC_STAT__RESERVED__SHIFT 0x00000004
+#define RLC_STAT__RLC_BUSY_MASK 0x00000001L
+#define RLC_STAT__RLC_BUSY__SHIFT 0x00000000
+#define RLC_STAT__RLC_GPM_BUSY_MASK 0x00000002L
+#define RLC_STAT__RLC_GPM_BUSY__SHIFT 0x00000001
+#define RLC_STAT__RLC_SPM_BUSY_MASK 0x00000004L
+#define RLC_STAT__RLC_SPM_BUSY__SHIFT 0x00000002
+#define RLC_THREAD1_DELAY__CU_IDEL_DELAY_MASK 0x000000ffL
+#define RLC_THREAD1_DELAY__CU_IDEL_DELAY__SHIFT 0x00000000
+#define RLC_THREAD1_DELAY__LBPW_INNER_LOOP_DELAY_MASK 0x0000ff00L
+#define RLC_THREAD1_DELAY__LBPW_INNER_LOOP_DELAY__SHIFT 0x00000008
+#define RLC_THREAD1_DELAY__LBPW_OUTER_LOOP_DELAY_MASK 0x00ff0000L
+#define RLC_THREAD1_DELAY__LBPW_OUTER_LOOP_DELAY__SHIFT 0x00000010
+#define RLC_THREAD1_DELAY__SPARE_MASK 0xff000000L
+#define RLC_THREAD1_DELAY__SPARE__SHIFT 0x00000018
+#define RLC_UCODE_CNTL__RLC_UCODE_FLAGS_MASK 0xffffffffL
+#define RLC_UCODE_CNTL__RLC_UCODE_FLAGS__SHIFT 0x00000000
+#define SCRATCH_ADDR__OBSOLETE_ADDR_MASK 0xffffffffL
+#define SCRATCH_ADDR__OBSOLETE_ADDR__SHIFT 0x00000000
+#define SCRATCH_REG0__SCRATCH_REG0_MASK 0xffffffffL
+#define SCRATCH_REG0__SCRATCH_REG0__SHIFT 0x00000000
+#define SCRATCH_REG1__SCRATCH_REG1_MASK 0xffffffffL
+#define SCRATCH_REG1__SCRATCH_REG1__SHIFT 0x00000000
+#define SCRATCH_REG2__SCRATCH_REG2_MASK 0xffffffffL
+#define SCRATCH_REG2__SCRATCH_REG2__SHIFT 0x00000000
+#define SCRATCH_REG3__SCRATCH_REG3_MASK 0xffffffffL
+#define SCRATCH_REG3__SCRATCH_REG3__SHIFT 0x00000000
+#define SCRATCH_REG4__SCRATCH_REG4_MASK 0xffffffffL
+#define SCRATCH_REG4__SCRATCH_REG4__SHIFT 0x00000000
+#define SCRATCH_REG5__SCRATCH_REG5_MASK 0xffffffffL
+#define SCRATCH_REG5__SCRATCH_REG5__SHIFT 0x00000000
+#define SCRATCH_REG6__SCRATCH_REG6_MASK 0xffffffffL
+#define SCRATCH_REG6__SCRATCH_REG6__SHIFT 0x00000000
+#define SCRATCH_REG7__SCRATCH_REG7_MASK 0xffffffffL
+#define SCRATCH_REG7__SCRATCH_REG7__SHIFT 0x00000000
+#define SCRATCH_UMSK__OBSOLETE_SWAP_MASK 0x00030000L
+#define SCRATCH_UMSK__OBSOLETE_SWAP__SHIFT 0x00000010
+#define SCRATCH_UMSK__OBSOLETE_UMSK_MASK 0x000000ffL
+#define SCRATCH_UMSK__OBSOLETE_UMSK__SHIFT 0x00000000
+#define SETUP_DEBUG_REG0__cl_dyn_sclk_vld_MASK 0x80000000L
+#define SETUP_DEBUG_REG0__cl_dyn_sclk_vld__SHIFT 0x0000001f
+#define SETUP_DEBUG_REG0__event_gated_MASK 0x10000000L
+#define SETUP_DEBUG_REG0__event_gated__SHIFT 0x0000001c
+#define SETUP_DEBUG_REG0__event_id_gated_MASK 0x0fc00000L
+#define SETUP_DEBUG_REG0__event_id_gated__SHIFT 0x00000016
+#define SETUP_DEBUG_REG0__geom_busy_MASK 0x00200000L
+#define SETUP_DEBUG_REG0__geom_busy__SHIFT 0x00000015
+#define SETUP_DEBUG_REG0__geom_enable_MASK 0x00008000L
+#define SETUP_DEBUG_REG0__geom_enable__SHIFT 0x0000000f
+#define SETUP_DEBUG_REG0__ge_stallb_MASK 0x00004000L
+#define SETUP_DEBUG_REG0__ge_stallb__SHIFT 0x0000000e
+#define SETUP_DEBUG_REG0__pfifo_busy_MASK 0x00080000L
+#define SETUP_DEBUG_REG0__pfifo_busy__SHIFT 0x00000013
+#define SETUP_DEBUG_REG0__pmode_prim_gated_MASK 0x20000000L
+#define SETUP_DEBUG_REG0__pmode_prim_gated__SHIFT 0x0000001d
+#define SETUP_DEBUG_REG0__pmode_state_MASK 0x00003f00L
+#define SETUP_DEBUG_REG0__pmode_state__SHIFT 0x00000008
+#define SETUP_DEBUG_REG0__su_baryc_cntl_state_MASK 0x00000003L
+#define SETUP_DEBUG_REG0__su_baryc_cntl_state__SHIFT 0x00000000
+#define SETUP_DEBUG_REG0__su_clip_baryc_free_MASK 0x00030000L
+#define SETUP_DEBUG_REG0__su_clip_baryc_free__SHIFT 0x00000010
+#define SETUP_DEBUG_REG0__su_clip_rtr_MASK 0x00040000L
+#define SETUP_DEBUG_REG0__su_clip_rtr__SHIFT 0x00000012
+#define SETUP_DEBUG_REG0__su_cntl_busy_MASK 0x00100000L
+#define SETUP_DEBUG_REG0__su_cntl_busy__SHIFT 0x00000014
+#define SETUP_DEBUG_REG0__su_cntl_state_MASK 0x0000003cL
+#define SETUP_DEBUG_REG0__su_cntl_state__SHIFT 0x00000002
+#define SETUP_DEBUG_REG0__su_dyn_sclk_vld_MASK 0x40000000L
+#define SETUP_DEBUG_REG0__su_dyn_sclk_vld__SHIFT 0x0000001e
+#define SETUP_DEBUG_REG1__x_sort0_gated_23_8_MASK 0xffff0000L
+#define SETUP_DEBUG_REG1__x_sort0_gated_23_8__SHIFT 0x00000010
+#define SETUP_DEBUG_REG1__y_sort0_gated_23_8_MASK 0x0000ffffL
+#define SETUP_DEBUG_REG1__y_sort0_gated_23_8__SHIFT 0x00000000
+#define SETUP_DEBUG_REG2__x_sort1_gated_23_8_MASK 0xffff0000L
+#define SETUP_DEBUG_REG2__x_sort1_gated_23_8__SHIFT 0x00000010
+#define SETUP_DEBUG_REG2__y_sort1_gated_23_8_MASK 0x0000ffffL
+#define SETUP_DEBUG_REG2__y_sort1_gated_23_8__SHIFT 0x00000000
+#define SETUP_DEBUG_REG3__x_sort2_gated_23_8_MASK 0xffff0000L
+#define SETUP_DEBUG_REG3__x_sort2_gated_23_8__SHIFT 0x00000010
+#define SETUP_DEBUG_REG3__y_sort2_gated_23_8_MASK 0x0000ffffL
+#define SETUP_DEBUG_REG3__y_sort2_gated_23_8__SHIFT 0x00000000
+#define SETUP_DEBUG_REG4__attr_indx_sort0_gated_MASK 0x00003fffL
+#define SETUP_DEBUG_REG4__attr_indx_sort0_gated__SHIFT 0x00000000
+#define SETUP_DEBUG_REG4__backfacing_gated_MASK 0x00008000L
+#define SETUP_DEBUG_REG4__backfacing_gated__SHIFT 0x0000000f
+#define SETUP_DEBUG_REG4__clipped_gated_MASK 0x00080000L
+#define SETUP_DEBUG_REG4__clipped_gated__SHIFT 0x00000013
+#define SETUP_DEBUG_REG4__dealloc_slot_gated_MASK 0x00700000L
+#define SETUP_DEBUG_REG4__dealloc_slot_gated__SHIFT 0x00000014
+#define SETUP_DEBUG_REG4__diamond_rule_gated_MASK 0x03000000L
+#define SETUP_DEBUG_REG4__diamond_rule_gated__SHIFT 0x00000018
+#define SETUP_DEBUG_REG4__eop_gated_MASK 0x80000000L
+#define SETUP_DEBUG_REG4__eop_gated__SHIFT 0x0000001f
+#define SETUP_DEBUG_REG4__fpov_gated_MASK 0x60000000L
+#define SETUP_DEBUG_REG4__fpov_gated__SHIFT 0x0000001d
+#define SETUP_DEBUG_REG4__null_prim_gated_MASK 0x00004000L
+#define SETUP_DEBUG_REG4__null_prim_gated__SHIFT 0x0000000e
+#define SETUP_DEBUG_REG4__st_indx_gated_MASK 0x00070000L
+#define SETUP_DEBUG_REG4__st_indx_gated__SHIFT 0x00000010
+#define SETUP_DEBUG_REG4__type_gated_MASK 0x1c000000L
+#define SETUP_DEBUG_REG4__type_gated__SHIFT 0x0000001a
+#define SETUP_DEBUG_REG4__xmajor_gated_MASK 0x00800000L
+#define SETUP_DEBUG_REG4__xmajor_gated__SHIFT 0x00000017
+#define SETUP_DEBUG_REG5__attr_indx_sort1_gated_MASK 0x0fffc000L
+#define SETUP_DEBUG_REG5__attr_indx_sort1_gated__SHIFT 0x0000000e
+#define SETUP_DEBUG_REG5__attr_indx_sort2_gated_MASK 0x00003fffL
+#define SETUP_DEBUG_REG5__attr_indx_sort2_gated__SHIFT 0x00000000
+#define SETUP_DEBUG_REG5__pa_reg_sclk_vld_MASK 0x80000000L
+#define SETUP_DEBUG_REG5__pa_reg_sclk_vld__SHIFT 0x0000001f
+#define SETUP_DEBUG_REG5__provoking_vtx_gated_MASK 0x30000000L
+#define SETUP_DEBUG_REG5__provoking_vtx_gated__SHIFT 0x0000001c
+#define SETUP_DEBUG_REG5__valid_prim_gated_MASK 0x40000000L
+#define SETUP_DEBUG_REG5__valid_prim_gated__SHIFT 0x0000001e
+#define SPI_ARB_CYCLES_0__TS0_DURATION_MASK 0x0000ffffL
+#define SPI_ARB_CYCLES_0__TS0_DURATION__SHIFT 0x00000000
+#define SPI_ARB_CYCLES_0__TS1_DURATION_MASK 0xffff0000L
+#define SPI_ARB_CYCLES_0__TS1_DURATION__SHIFT 0x00000010
+#define SPI_ARB_CYCLES_1__TS2_DURATION_MASK 0x0000ffffL
+#define SPI_ARB_CYCLES_1__TS2_DURATION__SHIFT 0x00000000
+#define SPI_ARB_CYCLES_1__TS3_DURATION_MASK 0xffff0000L
+#define SPI_ARB_CYCLES_1__TS3_DURATION__SHIFT 0x00000010
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS0_MASK 0x00000007L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS0__SHIFT 0x00000000
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS1_MASK 0x00000038L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS1__SHIFT 0x00000003
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS2_MASK 0x000001c0L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS2__SHIFT 0x00000006
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS3_MASK 0x00000e00L
+#define SPI_ARB_PRIORITY__PIPE_ORDER_TS3__SHIFT 0x00000009
+#define SPI_ARB_PRIORITY__TS0_DUR_MULT_MASK 0x00003000L
+#define SPI_ARB_PRIORITY__TS0_DUR_MULT__SHIFT 0x0000000c
+#define SPI_ARB_PRIORITY__TS1_DUR_MULT_MASK 0x0000c000L
+#define SPI_ARB_PRIORITY__TS1_DUR_MULT__SHIFT 0x0000000e
+#define SPI_ARB_PRIORITY__TS2_DUR_MULT_MASK 0x00030000L
+#define SPI_ARB_PRIORITY__TS2_DUR_MULT__SHIFT 0x00000010
+#define SPI_ARB_PRIORITY__TS3_DUR_MULT_MASK 0x000c0000L
+#define SPI_ARB_PRIORITY__TS3_DUR_MULT__SHIFT 0x00000012
+#define SPI_BARYC_CNTL__FRONT_FACE_ALL_BITS_MASK 0x01000000L
+#define SPI_BARYC_CNTL__FRONT_FACE_ALL_BITS__SHIFT 0x00000018
+#define SPI_BARYC_CNTL__LINEAR_CENTER_CNTL_MASK 0x00000100L
+#define SPI_BARYC_CNTL__LINEAR_CENTER_CNTL__SHIFT 0x00000008
+#define SPI_BARYC_CNTL__LINEAR_CENTROID_CNTL_MASK 0x00001000L
+#define SPI_BARYC_CNTL__LINEAR_CENTROID_CNTL__SHIFT 0x0000000c
+#define SPI_BARYC_CNTL__PERSP_CENTER_CNTL_MASK 0x00000001L
+#define SPI_BARYC_CNTL__PERSP_CENTER_CNTL__SHIFT 0x00000000
+#define SPI_BARYC_CNTL__PERSP_CENTROID_CNTL_MASK 0x00000010L
+#define SPI_BARYC_CNTL__PERSP_CENTROID_CNTL__SHIFT 0x00000004
+#define SPI_BARYC_CNTL__POS_FLOAT_LOCATION_MASK 0x00030000L
+#define SPI_BARYC_CNTL__POS_FLOAT_LOCATION__SHIFT 0x00000010
+#define SPI_BARYC_CNTL__POS_FLOAT_ULC_MASK 0x00100000L
+#define SPI_BARYC_CNTL__POS_FLOAT_ULC__SHIFT 0x00000014
+#define SPI_CONFIG_CNTL_1__CRC_SIMD_ID_WADDR_DISABLE_MASK 0x00000100L
+#define SPI_CONFIG_CNTL_1__CRC_SIMD_ID_WADDR_DISABLE__SHIFT 0x00000008
+#define SPI_CONFIG_CNTL_1__INTERP_ONE_PRIM_PER_ROW_MASK 0x00000010L
+#define SPI_CONFIG_CNTL_1__INTERP_ONE_PRIM_PER_ROW__SHIFT 0x00000004
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_CNT_MASK 0x00003c00L
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_CNT__SHIFT 0x0000000a
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_MODE_MASK 0x00000200L
+#define SPI_CONFIG_CNTL_1__LBPW_CU_CHK_MODE__SHIFT 0x00000009
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_ENABLE_MASK 0x00000040L
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_ENABLE__SHIFT 0x00000006
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_SIZE_MASK 0xffff0000L
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_SIZE__SHIFT 0x00000010
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_STRICT_MASK 0x00000080L
+#define SPI_CONFIG_CNTL_1__PC_LIMIT_STRICT__SHIFT 0x00000007
+#define SPI_CONFIG_CNTL_1__VTX_DONE_DELAY_MASK 0x0000000fL
+#define SPI_CONFIG_CNTL_1__VTX_DONE_DELAY__SHIFT 0x00000000
+#define SPI_CONFIG_CNTL__ENABLE_SQG_BOP_EVENTS_MASK 0x02000000L
+#define SPI_CONFIG_CNTL__ENABLE_SQG_BOP_EVENTS__SHIFT 0x00000019
+#define SPI_CONFIG_CNTL__ENABLE_SQG_TOP_EVENTS_MASK 0x01000000L
+#define SPI_CONFIG_CNTL__ENABLE_SQG_TOP_EVENTS__SHIFT 0x00000018
+#define SPI_CONFIG_CNTL__EXP_PRIORITY_ORDER_MASK 0x00e00000L
+#define SPI_CONFIG_CNTL__EXP_PRIORITY_ORDER__SHIFT 0x00000015
+#define SPI_CONFIG_CNTL__GPR_WRITE_PRIORITY_MASK 0x001fffffL
+#define SPI_CONFIG_CNTL__GPR_WRITE_PRIORITY__SHIFT 0x00000000
+#define SPI_CONFIG_CNTL__RSRC_MGMT_RESET_MASK 0x04000000L
+#define SPI_CONFIG_CNTL__RSRC_MGMT_RESET__SHIFT 0x0000001a
+#define SPI_CONFIG_CNTL__TTRACE_STALL_ALL_MASK 0x08000000L
+#define SPI_CONFIG_CNTL__TTRACE_STALL_ALL__SHIFT 0x0000001b
+#define SPI_DEBUG_BUSY__CS0_BUSY_MASK 0x00000080L
+#define SPI_DEBUG_BUSY__CS0_BUSY__SHIFT 0x00000007
+#define SPI_DEBUG_BUSY__CS1_BUSY_MASK 0x00000100L
+#define SPI_DEBUG_BUSY__CS1_BUSY__SHIFT 0x00000008
+#define SPI_DEBUG_BUSY__CS2_BUSY_MASK 0x00000200L
+#define SPI_DEBUG_BUSY__CS2_BUSY__SHIFT 0x00000009
+#define SPI_DEBUG_BUSY__CS3_BUSY_MASK 0x00000800L
+#define SPI_DEBUG_BUSY__CS3_BUSY__SHIFT 0x0000000b
+#define SPI_DEBUG_BUSY__CS4_BUSY_MASK 0x00001000L
+#define SPI_DEBUG_BUSY__CS4_BUSY__SHIFT 0x0000000c
+#define SPI_DEBUG_BUSY__CS5_BUSY_MASK 0x00002000L
+#define SPI_DEBUG_BUSY__CS5_BUSY__SHIFT 0x0000000d
+#define SPI_DEBUG_BUSY__CS6_BUSY_MASK 0x00004000L
+#define SPI_DEBUG_BUSY__CS6_BUSY__SHIFT 0x0000000e
+#define SPI_DEBUG_BUSY__CS7_BUSY_MASK 0x00008000L
+#define SPI_DEBUG_BUSY__CS7_BUSY__SHIFT 0x0000000f
+#define SPI_DEBUG_BUSY__CSG_BUSY_MASK 0x00000080L
+#define SPI_DEBUG_BUSY__CSG_BUSY__SHIFT 0x00000007
+#define SPI_DEBUG_BUSY__ES_BUSY_MASK 0x00000004L
+#define SPI_DEBUG_BUSY__ES_BUSY__SHIFT 0x00000002
+#define SPI_DEBUG_BUSY__EVENT_CLCTR_BUSY_MASK 0x00008000L
+#define SPI_DEBUG_BUSY__EVENT_CLCTR_BUSY__SHIFT 0x0000000f
+#define SPI_DEBUG_BUSY__GRBM_BUSY_MASK 0x00010000L
+#define SPI_DEBUG_BUSY__GRBM_BUSY__SHIFT 0x00000010
+#define SPI_DEBUG_BUSY__GS_BUSY_MASK 0x00000008L
+#define SPI_DEBUG_BUSY__GS_BUSY__SHIFT 0x00000003
+#define SPI_DEBUG_BUSY__HS_BUSY_MASK 0x00000002L
+#define SPI_DEBUG_BUSY__HS_BUSY__SHIFT 0x00000001
+#define SPI_DEBUG_BUSY__LDS_WR_CTL0_BUSY_MASK 0x00000400L
+#define SPI_DEBUG_BUSY__LDS_WR_CTL0_BUSY__SHIFT 0x0000000a
+#define SPI_DEBUG_BUSY__LDS_WR_CTL1_BUSY_MASK 0x00000800L
+#define SPI_DEBUG_BUSY__LDS_WR_CTL1_BUSY__SHIFT 0x0000000b
+#define SPI_DEBUG_BUSY__LS_BUSY_MASK 0x00000001L
+#define SPI_DEBUG_BUSY__LS_BUSY__SHIFT 0x00000000
+#define SPI_DEBUG_BUSY__PC_DEALLOC_BUSY_MASK 0x00100000L
+#define SPI_DEBUG_BUSY__PC_DEALLOC_BUSY__SHIFT 0x00000014
+#define SPI_DEBUG_BUSY__PS0_BUSY_MASK 0x00000020L
+#define SPI_DEBUG_BUSY__PS0_BUSY__SHIFT 0x00000005
+#define SPI_DEBUG_BUSY__PS1_BUSY_MASK 0x00000040L
+#define SPI_DEBUG_BUSY__PS1_BUSY__SHIFT 0x00000006
+#define SPI_DEBUG_BUSY__RSRC_ALLOC0_BUSY_MASK 0x00001000L
+#define SPI_DEBUG_BUSY__RSRC_ALLOC0_BUSY__SHIFT 0x0000000c
+#define SPI_DEBUG_BUSY__RSRC_ALLOC1_BUSY_MASK 0x00002000L
+#define SPI_DEBUG_BUSY__RSRC_ALLOC1_BUSY__SHIFT 0x0000000d
+#define SPI_DEBUG_BUSY__SPIS_BUSY_MASK 0x00020000L
+#define SPI_DEBUG_BUSY__SPIS_BUSY__SHIFT 0x00000011
+#define SPI_DEBUG_BUSY__VS_BUSY_MASK 0x00000010L
+#define SPI_DEBUG_BUSY__VS_BUSY__SHIFT 0x00000004
+#define SPI_DEBUG_CNTL__DEBUG_GRBM_OVERRIDE_MASK 0x00000001L
+#define SPI_DEBUG_CNTL__DEBUG_GRBM_OVERRIDE__SHIFT 0x00000000
+#define SPI_DEBUG_CNTL__DEBUG_GROUP_SEL_MASK 0x000003e0L
+#define SPI_DEBUG_CNTL__DEBUG_GROUP_SEL__SHIFT 0x00000005
+#define SPI_DEBUG_CNTL__DEBUG_PIPE_SEL_MASK 0x0e000000L
+#define SPI_DEBUG_CNTL__DEBUG_PIPE_SEL__SHIFT 0x00000019
+#define SPI_DEBUG_CNTL__DEBUG_REG_EN_MASK 0x80000000L
+#define SPI_DEBUG_CNTL__DEBUG_REG_EN__SHIFT 0x0000001f
+#define SPI_DEBUG_CNTL__DEBUG_SH_SEL_MASK 0x00010000L
+#define SPI_DEBUG_CNTL__DEBUG_SH_SEL__SHIFT 0x00000010
+#define SPI_DEBUG_CNTL__DEBUG_SIMD_SEL_MASK 0x0000fc00L
+#define SPI_DEBUG_CNTL__DEBUG_SIMD_SEL__SHIFT 0x0000000a
+#define SPI_DEBUG_CNTL__DEBUG_THREAD_TYPE_SEL_MASK 0x0000001eL
+#define SPI_DEBUG_CNTL__DEBUG_THREAD_TYPE_SEL__SHIFT 0x00000001
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_0_MASK 0x00020000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_0__SHIFT 0x00000011
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_1_MASK 0x00040000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_1__SHIFT 0x00000012
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_2_MASK 0x00080000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_2__SHIFT 0x00000013
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_3_MASK 0x00100000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_3__SHIFT 0x00000014
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_4_MASK 0x00200000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_4__SHIFT 0x00000015
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_5_MASK 0x00400000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_5__SHIFT 0x00000016
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_6_MASK 0x00800000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_6__SHIFT 0x00000017
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_7_MASK 0x01000000L
+#define SPI_DEBUG_CNTL__SPI_ECO_SPARE_7__SHIFT 0x00000018
+#define SPI_DEBUG_READ__DATA_MASK 0x00ffffffL
+#define SPI_DEBUG_READ__DATA__SHIFT 0x00000000
+#define SPI_GDS_CREDITS__DS_CMD_CREDITS_MASK 0x0000ff00L
+#define SPI_GDS_CREDITS__DS_CMD_CREDITS__SHIFT 0x00000008
+#define SPI_GDS_CREDITS__DS_DATA_CREDITS_MASK 0x000000ffL
+#define SPI_GDS_CREDITS__DS_DATA_CREDITS__SHIFT 0x00000000
+#define SPI_GDS_CREDITS__UNUSED_MASK 0xffff0000L
+#define SPI_GDS_CREDITS__UNUSED__SHIFT 0x00000010
+#define SPI_INTERP_CONTROL_0__FLAT_SHADE_ENA_MASK 0x00000001L
+#define SPI_INTERP_CONTROL_0__FLAT_SHADE_ENA__SHIFT 0x00000000
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_ENA_MASK 0x00000002L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_ENA__SHIFT 0x00000001
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_W_MASK 0x00003800L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_W__SHIFT 0x0000000b
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_X_MASK 0x0000001cL
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_X__SHIFT 0x00000002
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Y_MASK 0x000000e0L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Y__SHIFT 0x00000005
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Z_MASK 0x00000700L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_OVRD_Z__SHIFT 0x00000008
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_TOP_1_MASK 0x00004000L
+#define SPI_INTERP_CONTROL_0__PNT_SPRITE_TOP_1__SHIFT 0x0000000e
+#define SPI_LB_CTR_CTRL__LOAD_MASK 0x00000001L
+#define SPI_LB_CTR_CTRL__LOAD__SHIFT 0x00000000
+#define SPI_LB_CU_MASK__CU_MASK_MASK 0x0000ffffL
+#define SPI_LB_CU_MASK__CU_MASK__SHIFT 0x00000000
+#define SPI_LB_DATA_REG__CNT_DATA_MASK 0xffffffffL
+#define SPI_LB_DATA_REG__CNT_DATA__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER2_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SPI_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SPI_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER3_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SPI_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define SPI_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SPI_PERFCOUNTER_BINS__BIN0_MAX_MASK 0x000000f0L
+#define SPI_PERFCOUNTER_BINS__BIN0_MAX__SHIFT 0x00000004
+#define SPI_PERFCOUNTER_BINS__BIN0_MIN_MASK 0x0000000fL
+#define SPI_PERFCOUNTER_BINS__BIN0_MIN__SHIFT 0x00000000
+#define SPI_PERFCOUNTER_BINS__BIN1_MAX_MASK 0x0000f000L
+#define SPI_PERFCOUNTER_BINS__BIN1_MAX__SHIFT 0x0000000c
+#define SPI_PERFCOUNTER_BINS__BIN1_MIN_MASK 0x00000f00L
+#define SPI_PERFCOUNTER_BINS__BIN1_MIN__SHIFT 0x00000008
+#define SPI_PERFCOUNTER_BINS__BIN2_MAX_MASK 0x00f00000L
+#define SPI_PERFCOUNTER_BINS__BIN2_MAX__SHIFT 0x00000014
+#define SPI_PERFCOUNTER_BINS__BIN2_MIN_MASK 0x000f0000L
+#define SPI_PERFCOUNTER_BINS__BIN2_MIN__SHIFT 0x00000010
+#define SPI_PERFCOUNTER_BINS__BIN3_MAX_MASK 0xf0000000L
+#define SPI_PERFCOUNTER_BINS__BIN3_MAX__SHIFT 0x0000001c
+#define SPI_PERFCOUNTER_BINS__BIN3_MIN_MASK 0x0f000000L
+#define SPI_PERFCOUNTER_BINS__BIN3_MIN__SHIFT 0x00000018
+#define SPI_PG_ENABLE_STATIC_CU_MASK__CU_MASK_MASK 0x0000ffffL
+#define SPI_PG_ENABLE_STATIC_CU_MASK__CU_MASK__SHIFT 0x00000000
+#define SPI_PS_IN_CONTROL__BC_OPTIMIZE_DISABLE_MASK 0x00004000L
+#define SPI_PS_IN_CONTROL__BC_OPTIMIZE_DISABLE__SHIFT 0x0000000e
+#define SPI_PS_IN_CONTROL__NUM_INTERP_MASK 0x0000003fL
+#define SPI_PS_IN_CONTROL__NUM_INTERP__SHIFT 0x00000000
+#define SPI_PS_IN_CONTROL__PARAM_GEN_MASK 0x00000040L
+#define SPI_PS_IN_CONTROL__PARAM_GEN__SHIFT 0x00000006
+#define SPI_PS_INPUT_ADDR__ANCILLARY_ENA_MASK 0x00002000L
+#define SPI_PS_INPUT_ADDR__ANCILLARY_ENA__SHIFT 0x0000000d
+#define SPI_PS_INPUT_ADDR__FRONT_FACE_ENA_MASK 0x00001000L
+#define SPI_PS_INPUT_ADDR__FRONT_FACE_ENA__SHIFT 0x0000000c
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTER_ENA_MASK 0x00000020L
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTER_ENA__SHIFT 0x00000005
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTROID_ENA_MASK 0x00000040L
+#define SPI_PS_INPUT_ADDR__LINEAR_CENTROID_ENA__SHIFT 0x00000006
+#define SPI_PS_INPUT_ADDR__LINEAR_SAMPLE_ENA_MASK 0x00000010L
+#define SPI_PS_INPUT_ADDR__LINEAR_SAMPLE_ENA__SHIFT 0x00000004
+#define SPI_PS_INPUT_ADDR__LINE_STIPPLE_TEX_ENA_MASK 0x00000080L
+#define SPI_PS_INPUT_ADDR__LINE_STIPPLE_TEX_ENA__SHIFT 0x00000007
+#define SPI_PS_INPUT_ADDR__PERSP_CENTER_ENA_MASK 0x00000002L
+#define SPI_PS_INPUT_ADDR__PERSP_CENTER_ENA__SHIFT 0x00000001
+#define SPI_PS_INPUT_ADDR__PERSP_CENTROID_ENA_MASK 0x00000004L
+#define SPI_PS_INPUT_ADDR__PERSP_CENTROID_ENA__SHIFT 0x00000002
+#define SPI_PS_INPUT_ADDR__PERSP_PULL_MODEL_ENA_MASK 0x00000008L
+#define SPI_PS_INPUT_ADDR__PERSP_PULL_MODEL_ENA__SHIFT 0x00000003
+#define SPI_PS_INPUT_ADDR__PERSP_SAMPLE_ENA_MASK 0x00000001L
+#define SPI_PS_INPUT_ADDR__PERSP_SAMPLE_ENA__SHIFT 0x00000000
+#define SPI_PS_INPUT_ADDR__POS_FIXED_PT_ENA_MASK 0x00008000L
+#define SPI_PS_INPUT_ADDR__POS_FIXED_PT_ENA__SHIFT 0x0000000f
+#define SPI_PS_INPUT_ADDR__POS_W_FLOAT_ENA_MASK 0x00000800L
+#define SPI_PS_INPUT_ADDR__POS_W_FLOAT_ENA__SHIFT 0x0000000b
+#define SPI_PS_INPUT_ADDR__POS_X_FLOAT_ENA_MASK 0x00000100L
+#define SPI_PS_INPUT_ADDR__POS_X_FLOAT_ENA__SHIFT 0x00000008
+#define SPI_PS_INPUT_ADDR__POS_Y_FLOAT_ENA_MASK 0x00000200L
+#define SPI_PS_INPUT_ADDR__POS_Y_FLOAT_ENA__SHIFT 0x00000009
+#define SPI_PS_INPUT_ADDR__POS_Z_FLOAT_ENA_MASK 0x00000400L
+#define SPI_PS_INPUT_ADDR__POS_Z_FLOAT_ENA__SHIFT 0x0000000a
+#define SPI_PS_INPUT_ADDR__SAMPLE_COVERAGE_ENA_MASK 0x00004000L
+#define SPI_PS_INPUT_ADDR__SAMPLE_COVERAGE_ENA__SHIFT 0x0000000e
+#define SPI_PS_INPUT_CNTL_0__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_0__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_0__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_0__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_0__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_0__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_0__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_0__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_0__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_0__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_10__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_10__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_10__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_10__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_10__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_10__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_10__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_10__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_10__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_10__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_11__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_11__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_11__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_11__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_11__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_11__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_11__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_11__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_11__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_11__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_12__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_12__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_12__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_12__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_12__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_12__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_12__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_12__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_12__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_12__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_13__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_13__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_13__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_13__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_13__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_13__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_13__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_13__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_13__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_13__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_14__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_14__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_14__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_14__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_14__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_14__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_14__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_14__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_14__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_14__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_15__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_15__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_15__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_15__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_15__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_15__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_15__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_15__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_15__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_15__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_16__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_16__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_16__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_16__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_16__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_16__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_16__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_16__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_16__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_16__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_17__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_17__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_17__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_17__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_17__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_17__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_17__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_17__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_17__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_17__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_18__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_18__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_18__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_18__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_18__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_18__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_18__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_18__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_18__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_18__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_19__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_19__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_19__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_19__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_19__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_19__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_19__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_19__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_19__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_19__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_1__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_1__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_1__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_1__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_1__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_1__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_1__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_1__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_1__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_1__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_20__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_20__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_20__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_20__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_20__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_20__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_20__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_21__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_21__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_21__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_21__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_21__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_21__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_21__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_22__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_22__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_22__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_22__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_22__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_22__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_22__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_23__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_23__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_23__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_23__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_23__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_23__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_23__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_24__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_24__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_24__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_24__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_24__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_24__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_24__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_25__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_25__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_25__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_25__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_25__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_25__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_25__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_26__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_26__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_26__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_26__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_26__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_26__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_26__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_27__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_27__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_27__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_27__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_27__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_27__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_27__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_28__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_28__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_28__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_28__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_28__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_28__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_28__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_29__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_29__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_29__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_29__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_29__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_29__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_29__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_2__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_2__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_2__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_2__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_2__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_2__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_2__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_2__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_2__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_2__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_30__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_30__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_30__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_30__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_30__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_30__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_30__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_31__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_31__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_31__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_31__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_31__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_31__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_31__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_3__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_3__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_3__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_3__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_3__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_3__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_3__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_3__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_3__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_3__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_4__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_4__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_4__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_4__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_4__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_4__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_4__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_4__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_4__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_4__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_5__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_5__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_5__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_5__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_5__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_5__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_5__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_5__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_5__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_5__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_6__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_6__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_6__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_6__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_6__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_6__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_6__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_6__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_6__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_6__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_7__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_7__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_7__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_7__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_7__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_7__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_7__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_7__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_7__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_7__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_8__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_8__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_8__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_8__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_8__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_8__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_8__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_8__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_8__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_8__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_CNTL_9__CYL_WRAP_MASK 0x0001e000L
+#define SPI_PS_INPUT_CNTL_9__CYL_WRAP__SHIFT 0x0000000d
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL_MASK 0x00000300L
+#define SPI_PS_INPUT_CNTL_9__DEFAULT_VAL__SHIFT 0x00000008
+#define SPI_PS_INPUT_CNTL_9__DUP_MASK 0x00040000L
+#define SPI_PS_INPUT_CNTL_9__DUP__SHIFT 0x00000012
+#define SPI_PS_INPUT_CNTL_9__FLAT_SHADE_MASK 0x00000400L
+#define SPI_PS_INPUT_CNTL_9__FLAT_SHADE__SHIFT 0x0000000a
+#define SPI_PS_INPUT_CNTL_9__OFFSET_MASK 0x0000003fL
+#define SPI_PS_INPUT_CNTL_9__OFFSET__SHIFT 0x00000000
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX_MASK 0x00020000L
+#define SPI_PS_INPUT_CNTL_9__PT_SPRITE_TEX__SHIFT 0x00000011
+#define SPI_PS_INPUT_ENA__ANCILLARY_ENA_MASK 0x00002000L
+#define SPI_PS_INPUT_ENA__ANCILLARY_ENA__SHIFT 0x0000000d
+#define SPI_PS_INPUT_ENA__FRONT_FACE_ENA_MASK 0x00001000L
+#define SPI_PS_INPUT_ENA__FRONT_FACE_ENA__SHIFT 0x0000000c
+#define SPI_PS_INPUT_ENA__LINEAR_CENTER_ENA_MASK 0x00000020L
+#define SPI_PS_INPUT_ENA__LINEAR_CENTER_ENA__SHIFT 0x00000005
+#define SPI_PS_INPUT_ENA__LINEAR_CENTROID_ENA_MASK 0x00000040L
+#define SPI_PS_INPUT_ENA__LINEAR_CENTROID_ENA__SHIFT 0x00000006
+#define SPI_PS_INPUT_ENA__LINEAR_SAMPLE_ENA_MASK 0x00000010L
+#define SPI_PS_INPUT_ENA__LINEAR_SAMPLE_ENA__SHIFT 0x00000004
+#define SPI_PS_INPUT_ENA__LINE_STIPPLE_TEX_ENA_MASK 0x00000080L
+#define SPI_PS_INPUT_ENA__LINE_STIPPLE_TEX_ENA__SHIFT 0x00000007
+#define SPI_PS_INPUT_ENA__PERSP_CENTER_ENA_MASK 0x00000002L
+#define SPI_PS_INPUT_ENA__PERSP_CENTER_ENA__SHIFT 0x00000001
+#define SPI_PS_INPUT_ENA__PERSP_CENTROID_ENA_MASK 0x00000004L
+#define SPI_PS_INPUT_ENA__PERSP_CENTROID_ENA__SHIFT 0x00000002
+#define SPI_PS_INPUT_ENA__PERSP_PULL_MODEL_ENA_MASK 0x00000008L
+#define SPI_PS_INPUT_ENA__PERSP_PULL_MODEL_ENA__SHIFT 0x00000003
+#define SPI_PS_INPUT_ENA__PERSP_SAMPLE_ENA_MASK 0x00000001L
+#define SPI_PS_INPUT_ENA__PERSP_SAMPLE_ENA__SHIFT 0x00000000
+#define SPI_PS_INPUT_ENA__POS_FIXED_PT_ENA_MASK 0x00008000L
+#define SPI_PS_INPUT_ENA__POS_FIXED_PT_ENA__SHIFT 0x0000000f
+#define SPI_PS_INPUT_ENA__POS_W_FLOAT_ENA_MASK 0x00000800L
+#define SPI_PS_INPUT_ENA__POS_W_FLOAT_ENA__SHIFT 0x0000000b
+#define SPI_PS_INPUT_ENA__POS_X_FLOAT_ENA_MASK 0x00000100L
+#define SPI_PS_INPUT_ENA__POS_X_FLOAT_ENA__SHIFT 0x00000008
+#define SPI_PS_INPUT_ENA__POS_Y_FLOAT_ENA_MASK 0x00000200L
+#define SPI_PS_INPUT_ENA__POS_Y_FLOAT_ENA__SHIFT 0x00000009
+#define SPI_PS_INPUT_ENA__POS_Z_FLOAT_ENA_MASK 0x00000400L
+#define SPI_PS_INPUT_ENA__POS_Z_FLOAT_ENA__SHIFT 0x0000000a
+#define SPI_PS_INPUT_ENA__SAMPLE_COVERAGE_ENA_MASK 0x00004000L
+#define SPI_PS_INPUT_ENA__SAMPLE_COVERAGE_ENA__SHIFT 0x0000000e
+#define SPI_PS_MAX_WAVE_ID__MAX_WAVE_ID_MASK 0x00000fffL
+#define SPI_PS_MAX_WAVE_ID__MAX_WAVE_ID__SHIFT 0x00000000
+#define SPI_SHADER_COL_FORMAT__COL0_EXPORT_FORMAT_MASK 0x0000000fL
+#define SPI_SHADER_COL_FORMAT__COL0_EXPORT_FORMAT__SHIFT 0x00000000
+#define SPI_SHADER_COL_FORMAT__COL1_EXPORT_FORMAT_MASK 0x000000f0L
+#define SPI_SHADER_COL_FORMAT__COL1_EXPORT_FORMAT__SHIFT 0x00000004
+#define SPI_SHADER_COL_FORMAT__COL2_EXPORT_FORMAT_MASK 0x00000f00L
+#define SPI_SHADER_COL_FORMAT__COL2_EXPORT_FORMAT__SHIFT 0x00000008
+#define SPI_SHADER_COL_FORMAT__COL3_EXPORT_FORMAT_MASK 0x0000f000L
+#define SPI_SHADER_COL_FORMAT__COL3_EXPORT_FORMAT__SHIFT 0x0000000c
+#define SPI_SHADER_COL_FORMAT__COL4_EXPORT_FORMAT_MASK 0x000f0000L
+#define SPI_SHADER_COL_FORMAT__COL4_EXPORT_FORMAT__SHIFT 0x00000010
+#define SPI_SHADER_COL_FORMAT__COL5_EXPORT_FORMAT_MASK 0x00f00000L
+#define SPI_SHADER_COL_FORMAT__COL5_EXPORT_FORMAT__SHIFT 0x00000014
+#define SPI_SHADER_COL_FORMAT__COL6_EXPORT_FORMAT_MASK 0x0f000000L
+#define SPI_SHADER_COL_FORMAT__COL6_EXPORT_FORMAT__SHIFT 0x00000018
+#define SPI_SHADER_COL_FORMAT__COL7_EXPORT_FORMAT_MASK 0xf0000000L
+#define SPI_SHADER_COL_FORMAT__COL7_EXPORT_FORMAT__SHIFT 0x0000001c
+#define SPI_SHADER_PGM_HI_ES__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_GS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_HS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_LS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_PS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_HI_VS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_PGM_HI_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_ES__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_GS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_HS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_LS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_PS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_LO_VS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_PGM_LO_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_ES__CACHE_CTL_MASK 0x38000000L
+#define SPI_SHADER_PGM_RSRC1_ES__CACHE_CTL__SHIFT 0x0000001b
+#define SPI_SHADER_PGM_RSRC1_ES__CDBG_USER_MASK 0x40000000L
+#define SPI_SHADER_PGM_RSRC1_ES__CDBG_USER__SHIFT 0x0000001e
+#define SPI_SHADER_PGM_RSRC1_ES__CU_GROUP_ENABLE_MASK 0x04000000L
+#define SPI_SHADER_PGM_RSRC1_ES__CU_GROUP_ENABLE__SHIFT 0x0000001a
+#define SPI_SHADER_PGM_RSRC1_ES__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_ES__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_ES__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_ES__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_ES__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_ES__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_ES__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_ES__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_ES__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_ES__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_ES__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_ES__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_ES__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_ES__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_ES__VGPR_COMP_CNT_MASK 0x03000000L
+#define SPI_SHADER_PGM_RSRC1_ES__VGPR_COMP_CNT__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_ES__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_ES__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_GS__CACHE_CTL_MASK 0x0e000000L
+#define SPI_SHADER_PGM_RSRC1_GS__CACHE_CTL__SHIFT 0x00000019
+#define SPI_SHADER_PGM_RSRC1_GS__CDBG_USER_MASK 0x10000000L
+#define SPI_SHADER_PGM_RSRC1_GS__CDBG_USER__SHIFT 0x0000001c
+#define SPI_SHADER_PGM_RSRC1_GS__CU_GROUP_ENABLE_MASK 0x01000000L
+#define SPI_SHADER_PGM_RSRC1_GS__CU_GROUP_ENABLE__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_GS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_GS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_GS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_GS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_GS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_GS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_GS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_GS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_GS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_GS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_GS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_GS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_GS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_GS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_GS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_GS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_HS__CACHE_CTL_MASK 0x07000000L
+#define SPI_SHADER_PGM_RSRC1_HS__CACHE_CTL__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_HS__CDBG_USER_MASK 0x08000000L
+#define SPI_SHADER_PGM_RSRC1_HS__CDBG_USER__SHIFT 0x0000001b
+#define SPI_SHADER_PGM_RSRC1_HS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_HS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_HS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_HS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_HS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_HS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_HS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_HS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_HS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_HS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_HS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_HS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_HS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_HS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_HS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_HS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_LS__CACHE_CTL_MASK 0x1c000000L
+#define SPI_SHADER_PGM_RSRC1_LS__CACHE_CTL__SHIFT 0x0000001a
+#define SPI_SHADER_PGM_RSRC1_LS__CDBG_USER_MASK 0x20000000L
+#define SPI_SHADER_PGM_RSRC1_LS__CDBG_USER__SHIFT 0x0000001d
+#define SPI_SHADER_PGM_RSRC1_LS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_LS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_LS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_LS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_LS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_LS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_LS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_LS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_LS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_LS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_LS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_LS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_LS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_LS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_LS__VGPR_COMP_CNT_MASK 0x03000000L
+#define SPI_SHADER_PGM_RSRC1_LS__VGPR_COMP_CNT__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_LS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_LS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_PS__CACHE_CTL_MASK 0x0e000000L
+#define SPI_SHADER_PGM_RSRC1_PS__CACHE_CTL__SHIFT 0x00000019
+#define SPI_SHADER_PGM_RSRC1_PS__CDBG_USER_MASK 0x10000000L
+#define SPI_SHADER_PGM_RSRC1_PS__CDBG_USER__SHIFT 0x0000001c
+#define SPI_SHADER_PGM_RSRC1_PS__CU_GROUP_DISABLE_MASK 0x01000000L
+#define SPI_SHADER_PGM_RSRC1_PS__CU_GROUP_DISABLE__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_PS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_PS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_PS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_PS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_PS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_PS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_PS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_PS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_PS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_PS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_PS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_PS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_PS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_PS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_PS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_PS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC1_VS__CACHE_CTL_MASK 0x38000000L
+#define SPI_SHADER_PGM_RSRC1_VS__CACHE_CTL__SHIFT 0x0000001b
+#define SPI_SHADER_PGM_RSRC1_VS__CDBG_USER_MASK 0x40000000L
+#define SPI_SHADER_PGM_RSRC1_VS__CDBG_USER__SHIFT 0x0000001e
+#define SPI_SHADER_PGM_RSRC1_VS__CU_GROUP_ENABLE_MASK 0x04000000L
+#define SPI_SHADER_PGM_RSRC1_VS__CU_GROUP_ENABLE__SHIFT 0x0000001a
+#define SPI_SHADER_PGM_RSRC1_VS__DEBUG_MODE_MASK 0x00400000L
+#define SPI_SHADER_PGM_RSRC1_VS__DEBUG_MODE__SHIFT 0x00000016
+#define SPI_SHADER_PGM_RSRC1_VS__DX10_CLAMP_MASK 0x00200000L
+#define SPI_SHADER_PGM_RSRC1_VS__DX10_CLAMP__SHIFT 0x00000015
+#define SPI_SHADER_PGM_RSRC1_VS__FLOAT_MODE_MASK 0x000ff000L
+#define SPI_SHADER_PGM_RSRC1_VS__FLOAT_MODE__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC1_VS__IEEE_MODE_MASK 0x00800000L
+#define SPI_SHADER_PGM_RSRC1_VS__IEEE_MODE__SHIFT 0x00000017
+#define SPI_SHADER_PGM_RSRC1_VS__PRIORITY_MASK 0x00000c00L
+#define SPI_SHADER_PGM_RSRC1_VS__PRIORITY__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC1_VS__PRIV_MASK 0x00100000L
+#define SPI_SHADER_PGM_RSRC1_VS__PRIV__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC1_VS__SGPRS_MASK 0x000003c0L
+#define SPI_SHADER_PGM_RSRC1_VS__SGPRS__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC1_VS__VGPR_COMP_CNT_MASK 0x03000000L
+#define SPI_SHADER_PGM_RSRC1_VS__VGPR_COMP_CNT__SHIFT 0x00000018
+#define SPI_SHADER_PGM_RSRC1_VS__VGPRS_MASK 0x0000003fL
+#define SPI_SHADER_PGM_RSRC1_VS__VGPRS__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES__EXCP_EN_MASK 0x00007f00L
+#define SPI_SHADER_PGM_RSRC2_ES__EXCP_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_ES_GS__EXCP_EN_MASK 0x0001ff00L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__EXCP_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_ES_GS__LDS_SIZE_MASK 0x1ff00000L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__LDS_SIZE__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC2_ES_GS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_ES_GS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES_GS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_ES_GS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_ES_GS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_ES_GS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_ES__LDS_SIZE_MASK 0x1ff00000L
+#define SPI_SHADER_PGM_RSRC2_ES__LDS_SIZE__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC2_ES__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_ES__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_ES__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_ES__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_ES__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_ES__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_ES__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_ES_VS__EXCP_EN_MASK 0x0001ff00L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__EXCP_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_ES_VS__LDS_SIZE_MASK 0x1ff00000L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__LDS_SIZE__SHIFT 0x00000014
+#define SPI_SHADER_PGM_RSRC2_ES_VS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_ES_VS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_ES_VS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_ES_VS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_ES_VS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_ES_VS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_GS__EXCP_EN_MASK 0x00003f80L
+#define SPI_SHADER_PGM_RSRC2_GS__EXCP_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_GS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_GS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_GS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_GS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_GS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_GS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_HS__EXCP_EN_MASK 0x0000fe00L
+#define SPI_SHADER_PGM_RSRC2_HS__EXCP_EN__SHIFT 0x00000009
+#define SPI_SHADER_PGM_RSRC2_HS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_HS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_HS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_HS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_HS__TG_SIZE_EN_MASK 0x00000100L
+#define SPI_SHADER_PGM_RSRC2_HS__TG_SIZE_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_HS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_HS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_HS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_HS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS_ES__EXCP_EN_MASK 0x01ff0000L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_ES__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS_ES__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS_ES__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS_ES__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS_ES__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS_ES__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS__EXCP_EN_MASK 0x007f0000L
+#define SPI_SHADER_PGM_RSRC2_LS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_HS__EXCP_EN_MASK 0x01ff0000L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_HS__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS_HS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS_HS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS_HS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS_HS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS_HS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_LS_VS__EXCP_EN_MASK 0x01ff0000L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_LS_VS__LDS_SIZE_MASK 0x0000ff80L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__LDS_SIZE__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_LS_VS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_LS_VS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_LS_VS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_LS_VS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_LS_VS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_PS__EXCP_EN_MASK 0x007f0000L
+#define SPI_SHADER_PGM_RSRC2_PS__EXCP_EN__SHIFT 0x00000010
+#define SPI_SHADER_PGM_RSRC2_PS__EXTRA_LDS_SIZE_MASK 0x0000ff00L
+#define SPI_SHADER_PGM_RSRC2_PS__EXTRA_LDS_SIZE__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_PS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_PS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_PS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_PS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_PS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_PS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_PGM_RSRC2_PS__WAVE_CNT_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_PS__WAVE_CNT_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_VS__EXCP_EN_MASK 0x000fe000L
+#define SPI_SHADER_PGM_RSRC2_VS__EXCP_EN__SHIFT 0x0000000d
+#define SPI_SHADER_PGM_RSRC2_VS__OC_LDS_EN_MASK 0x00000080L
+#define SPI_SHADER_PGM_RSRC2_VS__OC_LDS_EN__SHIFT 0x00000007
+#define SPI_SHADER_PGM_RSRC2_VS__SCRATCH_EN_MASK 0x00000001L
+#define SPI_SHADER_PGM_RSRC2_VS__SCRATCH_EN__SHIFT 0x00000000
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE0_EN_MASK 0x00000100L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE0_EN__SHIFT 0x00000008
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE1_EN_MASK 0x00000200L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE1_EN__SHIFT 0x00000009
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE2_EN_MASK 0x00000400L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE2_EN__SHIFT 0x0000000a
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE3_EN_MASK 0x00000800L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_BASE3_EN__SHIFT 0x0000000b
+#define SPI_SHADER_PGM_RSRC2_VS__SO_EN_MASK 0x00001000L
+#define SPI_SHADER_PGM_RSRC2_VS__SO_EN__SHIFT 0x0000000c
+#define SPI_SHADER_PGM_RSRC2_VS__TRAP_PRESENT_MASK 0x00000040L
+#define SPI_SHADER_PGM_RSRC2_VS__TRAP_PRESENT__SHIFT 0x00000006
+#define SPI_SHADER_PGM_RSRC2_VS__USER_SGPR_MASK 0x0000003eL
+#define SPI_SHADER_PGM_RSRC2_VS__USER_SGPR__SHIFT 0x00000001
+#define SPI_SHADER_POS_FORMAT__POS0_EXPORT_FORMAT_MASK 0x0000000fL
+#define SPI_SHADER_POS_FORMAT__POS0_EXPORT_FORMAT__SHIFT 0x00000000
+#define SPI_SHADER_POS_FORMAT__POS1_EXPORT_FORMAT_MASK 0x000000f0L
+#define SPI_SHADER_POS_FORMAT__POS1_EXPORT_FORMAT__SHIFT 0x00000004
+#define SPI_SHADER_POS_FORMAT__POS2_EXPORT_FORMAT_MASK 0x00000f00L
+#define SPI_SHADER_POS_FORMAT__POS2_EXPORT_FORMAT__SHIFT 0x00000008
+#define SPI_SHADER_POS_FORMAT__POS3_EXPORT_FORMAT_MASK 0x0000f000L
+#define SPI_SHADER_POS_FORMAT__POS3_EXPORT_FORMAT__SHIFT 0x0000000c
+#define SPI_SHADER_TBA_HI_ES__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_GS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_HS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_LS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_PS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_HI_VS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TBA_HI_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_ES__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_GS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_HS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_LS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_PS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TBA_LO_VS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TBA_LO_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_ES__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_GS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_HS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_LS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_PS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_HI_VS__MEM_BASE_MASK 0x000000ffL
+#define SPI_SHADER_TMA_HI_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_ES__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_ES__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_GS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_GS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_HS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_HS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_LS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_LS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_PS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_PS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_TMA_LO_VS__MEM_BASE_MASK 0xffffffffL
+#define SPI_SHADER_TMA_LO_VS__MEM_BASE__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_ES_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_ES_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_GS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_GS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_HS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_HS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_LS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_LS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_PS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_PS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_0__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_0__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_10__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_10__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_11__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_11__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_12__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_12__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_13__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_13__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_14__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_14__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_15__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_15__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_1__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_1__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_2__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_2__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_3__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_3__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_4__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_4__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_5__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_5__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_6__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_6__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_7__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_7__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_8__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_8__DATA__SHIFT 0x00000000
+#define SPI_SHADER_USER_DATA_VS_9__DATA_MASK 0xffffffffL
+#define SPI_SHADER_USER_DATA_VS_9__DATA__SHIFT 0x00000000
+#define SPI_SHADER_Z_FORMAT__Z_EXPORT_FORMAT_MASK 0x0000000fL
+#define SPI_SHADER_Z_FORMAT__Z_EXPORT_FORMAT__SHIFT 0x00000000
+#define SPI_SLAVE_DEBUG_BUSY__ES_VTX_BUSY_MASK 0x00000004L
+#define SPI_SLAVE_DEBUG_BUSY__ES_VTX_BUSY__SHIFT 0x00000002
+#define SPI_SLAVE_DEBUG_BUSY__EVENT_CNTL_BUSY_MASK 0x00200000L
+#define SPI_SLAVE_DEBUG_BUSY__EVENT_CNTL_BUSY__SHIFT 0x00000015
+#define SPI_SLAVE_DEBUG_BUSY__GS_VTX_BUSY_MASK 0x00000008L
+#define SPI_SLAVE_DEBUG_BUSY__GS_VTX_BUSY__SHIFT 0x00000003
+#define SPI_SLAVE_DEBUG_BUSY__HS_VTX_BUSY_MASK 0x00000002L
+#define SPI_SLAVE_DEBUG_BUSY__HS_VTX_BUSY__SHIFT 0x00000001
+#define SPI_SLAVE_DEBUG_BUSY__LS_VTX_BUSY_MASK 0x00000001L
+#define SPI_SLAVE_DEBUG_BUSY__LS_VTX_BUSY__SHIFT 0x00000000
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC00_BUSY_MASK 0x00000200L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC00_BUSY__SHIFT 0x00000009
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC01_BUSY_MASK 0x00000400L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC01_BUSY__SHIFT 0x0000000a
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC02_BUSY_MASK 0x00000800L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC02_BUSY__SHIFT 0x0000000b
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC03_BUSY_MASK 0x00001000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC03_BUSY__SHIFT 0x0000000c
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC10_BUSY_MASK 0x00002000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC10_BUSY__SHIFT 0x0000000d
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC11_BUSY_MASK 0x00004000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC11_BUSY__SHIFT 0x0000000e
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC12_BUSY_MASK 0x00008000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC12_BUSY__SHIFT 0x0000000f
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC13_BUSY_MASK 0x00010000L
+#define SPI_SLAVE_DEBUG_BUSY__SGPR_WC13_BUSY__SHIFT 0x00000010
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC00_BUSY_MASK 0x00000020L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC00_BUSY__SHIFT 0x00000005
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC01_BUSY_MASK 0x00000040L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC01_BUSY__SHIFT 0x00000006
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC10_BUSY_MASK 0x00000080L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC10_BUSY__SHIFT 0x00000007
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC11_BUSY_MASK 0x00000100L
+#define SPI_SLAVE_DEBUG_BUSY__VGPR_WC11_BUSY__SHIFT 0x00000008
+#define SPI_SLAVE_DEBUG_BUSY__VS_VTX_BUSY_MASK 0x00000010L
+#define SPI_SLAVE_DEBUG_BUSY__VS_VTX_BUSY__SHIFT 0x00000004
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER0_BUSY_MASK 0x00020000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER0_BUSY__SHIFT 0x00000011
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER1_BUSY_MASK 0x00040000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVEBUFFER1_BUSY__SHIFT 0x00000012
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC0_BUSY_MASK 0x00080000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC0_BUSY__SHIFT 0x00000013
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC1_BUSY_MASK 0x00100000L
+#define SPI_SLAVE_DEBUG_BUSY__WAVE_WC1_BUSY__SHIFT 0x00000014
+#define SPI_SX_EXPORT_BUFFER_SIZES__COLOR_BUFFER_SIZE_MASK 0x0000ffffL
+#define SPI_SX_EXPORT_BUFFER_SIZES__COLOR_BUFFER_SIZE__SHIFT 0x00000000
+#define SPI_SX_EXPORT_BUFFER_SIZES__POSITION_BUFFER_SIZE_MASK 0xffff0000L
+#define SPI_SX_EXPORT_BUFFER_SIZES__POSITION_BUFFER_SIZE__SHIFT 0x00000010
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__COLOR_SCOREBOARD_SIZE_MASK 0x0000ffffL
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__COLOR_SCOREBOARD_SIZE__SHIFT 0x00000000
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__POSITION_SCOREBOARD_SIZE_MASK 0xffff0000L
+#define SPI_SX_SCOREBOARD_BUFFER_SIZES__POSITION_SCOREBOARD_SIZE__SHIFT 0x00000010
+#define SPI_TMPRING_SIZE__WAVESIZE_MASK 0x01fff000L
+#define SPI_TMPRING_SIZE__WAVESIZE__SHIFT 0x0000000c
+#define SPI_TMPRING_SIZE__WAVES_MASK 0x00000fffL
+#define SPI_TMPRING_SIZE__WAVES__SHIFT 0x00000000
+#define SPI_VS_OUT_CONFIG__VS_EXPORT_COUNT_MASK 0x0000003eL
+#define SPI_VS_OUT_CONFIG__VS_EXPORT_COUNT__SHIFT 0x00000001
+#define SPI_VS_OUT_CONFIG__VS_HALF_PACK_MASK 0x00000040L
+#define SPI_VS_OUT_CONFIG__VS_HALF_PACK__SHIFT 0x00000006
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH0_MASK 0x0000ffffL
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH0__SHIFT 0x00000000
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH1_MASK 0xffff0000L
+#define SQ_ALU_CLK_CTRL__FORCE_CU_ON_SH1__SHIFT 0x00000010
+#define SQ_BUF_RSRC_WORD0__BASE_ADDRESS_MASK 0xffffffffL
+#define SQ_BUF_RSRC_WORD0__BASE_ADDRESS__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD1__BASE_ADDRESS_HI_MASK 0x0000ffffL
+#define SQ_BUF_RSRC_WORD1__BASE_ADDRESS_HI__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD1__CACHE_SWIZZLE_MASK 0x40000000L
+#define SQ_BUF_RSRC_WORD1__CACHE_SWIZZLE__SHIFT 0x0000001e
+#define SQ_BUF_RSRC_WORD1__STRIDE_MASK 0x3fff0000L
+#define SQ_BUF_RSRC_WORD1__STRIDE__SHIFT 0x00000010
+#define SQ_BUF_RSRC_WORD1__SWIZZLE_ENABLE_MASK 0x80000000L
+#define SQ_BUF_RSRC_WORD1__SWIZZLE_ENABLE__SHIFT 0x0000001f
+#define SQ_BUF_RSRC_WORD2__NUM_RECORDS_MASK 0xffffffffL
+#define SQ_BUF_RSRC_WORD2__NUM_RECORDS__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD3__ADD_TID_ENABLE_MASK 0x00800000L
+#define SQ_BUF_RSRC_WORD3__ADD_TID_ENABLE__SHIFT 0x00000017
+#define SQ_BUF_RSRC_WORD3__ATC_MASK 0x01000000L
+#define SQ_BUF_RSRC_WORD3__ATC__SHIFT 0x00000018
+#define SQ_BUF_RSRC_WORD3__DATA_FORMAT_MASK 0x00078000L
+#define SQ_BUF_RSRC_WORD3__DATA_FORMAT__SHIFT 0x0000000f
+#define SQ_BUF_RSRC_WORD3__DST_SEL_W_MASK 0x00000e00L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_W__SHIFT 0x00000009
+#define SQ_BUF_RSRC_WORD3__DST_SEL_X_MASK 0x00000007L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_X__SHIFT 0x00000000
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Y_MASK 0x00000038L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Y__SHIFT 0x00000003
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Z_MASK 0x000001c0L
+#define SQ_BUF_RSRC_WORD3__DST_SEL_Z__SHIFT 0x00000006
+#define SQ_BUF_RSRC_WORD3__ELEMENT_SIZE_MASK 0x00180000L
+#define SQ_BUF_RSRC_WORD3__ELEMENT_SIZE__SHIFT 0x00000013
+#define SQ_BUF_RSRC_WORD3__HASH_ENABLE_MASK 0x02000000L
+#define SQ_BUF_RSRC_WORD3__HASH_ENABLE__SHIFT 0x00000019
+#define SQ_BUF_RSRC_WORD3__HEAP_MASK 0x04000000L
+#define SQ_BUF_RSRC_WORD3__HEAP__SHIFT 0x0000001a
+#define SQ_BUF_RSRC_WORD3__INDEX_STRIDE_MASK 0x00600000L
+#define SQ_BUF_RSRC_WORD3__INDEX_STRIDE__SHIFT 0x00000015
+#define SQ_BUF_RSRC_WORD3__MTYPE_MASK 0x38000000L
+#define SQ_BUF_RSRC_WORD3__MTYPE__SHIFT 0x0000001b
+#define SQ_BUF_RSRC_WORD3__NUM_FORMAT_MASK 0x00007000L
+#define SQ_BUF_RSRC_WORD3__NUM_FORMAT__SHIFT 0x0000000c
+#define SQ_BUF_RSRC_WORD3__TYPE_MASK 0xc0000000L
+#define SQ_BUF_RSRC_WORD3__TYPE__SHIFT 0x0000001e
+#define SQC_CACHES__DATA_INVALIDATE_MASK 0x00000002L
+#define SQC_CACHES__DATA_INVALIDATE__SHIFT 0x00000001
+#define SQC_CACHES__INST_INVALIDATE_MASK 0x00000001L
+#define SQC_CACHES__INST_INVALIDATE__SHIFT 0x00000000
+#define SQC_CACHES__INVALIDATE_VOLATILE_MASK 0x00000004L
+#define SQC_CACHES__INVALIDATE_VOLATILE__SHIFT 0x00000002
+#define SQC_CONFIG__DATA_CACHE_SIZE_MASK 0x0000000cL
+#define SQC_CONFIG__DATA_CACHE_SIZE__SHIFT 0x00000002
+#define SQC_CONFIG__FORCE_ALWAYS_MISS_MASK 0x00000080L
+#define SQC_CONFIG__FORCE_ALWAYS_MISS__SHIFT 0x00000007
+#define SQC_CONFIG__FORCE_IN_ORDER_MASK 0x00000100L
+#define SQC_CONFIG__FORCE_IN_ORDER__SHIFT 0x00000008
+#define SQC_CONFIG__HIT_FIFO_DEPTH_MASK 0x00000040L
+#define SQC_CONFIG__HIT_FIFO_DEPTH__SHIFT 0x00000006
+#define SQC_CONFIG__IDENTITY_HASH_BANK_MASK 0x00000200L
+#define SQC_CONFIG__IDENTITY_HASH_BANK__SHIFT 0x00000009
+#define SQC_CONFIG__IDENTITY_HASH_SET_MASK 0x00000400L
+#define SQC_CONFIG__IDENTITY_HASH_SET__SHIFT 0x0000000a
+#define SQC_CONFIG__INST_CACHE_SIZE_MASK 0x00000003L
+#define SQC_CONFIG__INST_CACHE_SIZE__SHIFT 0x00000000
+#define SQC_CONFIG__MISS_FIFO_DEPTH_MASK 0x00000030L
+#define SQC_CONFIG__MISS_FIFO_DEPTH__SHIFT 0x00000004
+#define SQC_CONFIG__PER_VMID_INV_DISABLE_MASK 0x00000800L
+#define SQC_CONFIG__PER_VMID_INV_DISABLE__SHIFT 0x0000000b
+#define SQ_CONFIG__DEBUG_EN_MASK 0x00000100L
+#define SQ_CONFIG__DEBUG_EN__SHIFT 0x00000008
+#define SQ_CONFIG__DISABLE_IB_DEP_CHECK_MASK 0x00000400L
+#define SQ_CONFIG__DISABLE_IB_DEP_CHECK__SHIFT 0x0000000a
+#define SQ_CONFIG__DISABLE_SCA_BYPASS_MASK 0x00000200L
+#define SQ_CONFIG__DISABLE_SCA_BYPASS__SHIFT 0x00000009
+#define SQ_CONFIG__DUA_FLAT_LDS_PINGPONG_DISABLE_MASK 0x00008000L
+#define SQ_CONFIG__DUA_FLAT_LDS_PINGPONG_DISABLE__SHIFT 0x0000000f
+#define SQ_CONFIG__DUA_FLAT_LOCK_ENABLE_MASK 0x00002000L
+#define SQ_CONFIG__DUA_FLAT_LOCK_ENABLE__SHIFT 0x0000000d
+#define SQ_CONFIG__DUA_LDS_BYPASS_DISABLE_MASK 0x00004000L
+#define SQ_CONFIG__DUA_LDS_BYPASS_DISABLE__SHIFT 0x0000000e
+#define SQ_CONFIG__EARLY_TA_DONE_DISABLE_MASK 0x00001000L
+#define SQ_CONFIG__EARLY_TA_DONE_DISABLE__SHIFT 0x0000000c
+#define SQ_CONFIG__ENABLE_SOFT_CLAUSE_MASK 0x00000800L
+#define SQ_CONFIG__ENABLE_SOFT_CLAUSE__SHIFT 0x0000000b
+#define SQ_CONFIG__UNUSED_MASK 0x000000ffL
+#define SQ_CONFIG__UNUSED__SHIFT 0x00000000
+#define SQC_SECDED_CNT__DATA_DED_MASK 0xff000000L
+#define SQC_SECDED_CNT__DATA_DED__SHIFT 0x00000018
+#define SQC_SECDED_CNT__DATA_SEC_MASK 0x00ff0000L
+#define SQC_SECDED_CNT__DATA_SEC__SHIFT 0x00000010
+#define SQC_SECDED_CNT__INST_DED_MASK 0x0000ff00L
+#define SQC_SECDED_CNT__INST_DED__SHIFT 0x00000008
+#define SQC_SECDED_CNT__INST_SEC_MASK 0x000000ffL
+#define SQC_SECDED_CNT__INST_SEC__SHIFT 0x00000000
+#define SQ_DEBUG_CTRL_LOCAL__UNUSED_MASK 0x000000ffL
+#define SQ_DEBUG_CTRL_LOCAL__UNUSED__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0_MASK 0x000000ffL
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX0__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX1_MASK 0x0000ff00L
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_GFX1__SHIFT 0x00000008
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_HOST_MASK 0xff000000L
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_HOST__SHIFT 0x00000018
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_IMMED_MASK 0x00ff0000L
+#define SQ_DEBUG_STS_GLOBAL2__FIFO_LEVEL_IMMED__SHIFT 0x00000010
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_CMD_MASK 0x0000000fL
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_CMD__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_REG_MASK 0x000000f0L
+#define SQ_DEBUG_STS_GLOBAL3__FIFO_LEVEL_HOST_REG__SHIFT 0x00000004
+#define SQ_DEBUG_STS_GLOBAL__BUSY_MASK 0x00000001L
+#define SQ_DEBUG_STS_GLOBAL__BUSY__SHIFT 0x00000000
+#define SQ_DEBUG_STS_GLOBAL__INTERRUPT_MSG_BUSY_MASK 0x00000002L
+#define SQ_DEBUG_STS_GLOBAL__INTERRUPT_MSG_BUSY__SHIFT 0x00000001
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH0_MASK 0x0000fff0L
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH0__SHIFT 0x00000004
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH1_MASK 0x0fff0000L
+#define SQ_DEBUG_STS_GLOBAL__WAVE_LEVEL_SH1__SHIFT 0x00000010
+#define SQ_DEBUG_STS_LOCAL__BUSY_MASK 0x00000001L
+#define SQ_DEBUG_STS_LOCAL__BUSY__SHIFT 0x00000000
+#define SQ_DEBUG_STS_LOCAL__WAVE_LEVEL_MASK 0x000003f0L
+#define SQ_DEBUG_STS_LOCAL__WAVE_LEVEL__SHIFT 0x00000004
+#define SQ_DED_CNT__LDS_DED_MASK 0x0000003fL
+#define SQ_DED_CNT__LDS_DED__SHIFT 0x00000000
+#define SQ_DED_CNT__SGPR_DED_MASK 0x00001f00L
+#define SQ_DED_CNT__SGPR_DED__SHIFT 0x00000008
+#define SQ_DED_CNT__VGPR_DED_MASK 0x01ff0000L
+#define SQ_DED_CNT__VGPR_DED__SHIFT 0x00000010
+#define SQ_DED_INFO__SIMD_ID_MASK 0x00000030L
+#define SQ_DED_INFO__SIMD_ID__SHIFT 0x00000004
+#define SQ_DED_INFO__SOURCE_MASK 0x000001c0L
+#define SQ_DED_INFO__SOURCE__SHIFT 0x00000006
+#define SQ_DED_INFO__VM_ID_MASK 0x00001e00L
+#define SQ_DED_INFO__VM_ID__SHIFT 0x00000009
+#define SQ_DED_INFO__WAVE_ID_MASK 0x0000000fL
+#define SQ_DED_INFO__WAVE_ID__SHIFT 0x00000000
+#define SQ_DS_0__ENCODING_MASK 0xfc000000L
+#define SQ_DS_0__ENCODING__SHIFT 0x0000001a
+#define SQ_DS_0__GDS_MASK 0x00020000L
+#define SQ_DS_0__GDS__SHIFT 0x00000011
+#define SQ_DS_0__OFFSET0_MASK 0x000000ffL
+#define SQ_DS_0__OFFSET0__SHIFT 0x00000000
+#define SQ_DS_0__OFFSET1_MASK 0x0000ff00L
+#define SQ_DS_0__OFFSET1__SHIFT 0x00000008
+#define SQ_DS_0__OP_MASK 0x03fc0000L
+#define SQ_DS_0__OP__SHIFT 0x00000012
+#define SQ_DS_1__ADDR_MASK 0x000000ffL
+#define SQ_DS_1__ADDR__SHIFT 0x00000000
+#define SQ_DS_1__DATA0_MASK 0x0000ff00L
+#define SQ_DS_1__DATA0__SHIFT 0x00000008
+#define SQ_DS_1__DATA1_MASK 0x00ff0000L
+#define SQ_DS_1__DATA1__SHIFT 0x00000010
+#define SQ_DS_1__VDST_MASK 0xff000000L
+#define SQ_DS_1__VDST__SHIFT 0x00000018
+#define SQ_EXP_0__COMPR_MASK 0x00000400L
+#define SQ_EXP_0__COMPR__SHIFT 0x0000000a
+#define SQ_EXP_0__DONE_MASK 0x00000800L
+#define SQ_EXP_0__DONE__SHIFT 0x0000000b
+#define SQ_EXP_0__ENCODING_MASK 0xfc000000L
+#define SQ_EXP_0__ENCODING__SHIFT 0x0000001a
+#define SQ_EXP_0__EN_MASK 0x0000000fL
+#define SQ_EXP_0__EN__SHIFT 0x00000000
+#define SQ_EXP_0__TGT_MASK 0x000003f0L
+#define SQ_EXP_0__TGT__SHIFT 0x00000004
+#define SQ_EXP_0__VM_MASK 0x00001000L
+#define SQ_EXP_0__VM__SHIFT 0x0000000c
+#define SQ_EXP_1__VSRC0_MASK 0x000000ffL
+#define SQ_EXP_1__VSRC0__SHIFT 0x00000000
+#define SQ_EXP_1__VSRC1_MASK 0x0000ff00L
+#define SQ_EXP_1__VSRC1__SHIFT 0x00000008
+#define SQ_EXP_1__VSRC2_MASK 0x00ff0000L
+#define SQ_EXP_1__VSRC2__SHIFT 0x00000010
+#define SQ_EXP_1__VSRC3_MASK 0xff000000L
+#define SQ_EXP_1__VSRC3__SHIFT 0x00000018
+#define SQ_FIFO_SIZES__EXPORT_BUF_SIZE_MASK 0x00030000L
+#define SQ_FIFO_SIZES__EXPORT_BUF_SIZE__SHIFT 0x00000010
+#define SQ_FIFO_SIZES__INTERRUPT_FIFO_SIZE_MASK 0x0000000fL
+#define SQ_FIFO_SIZES__INTERRUPT_FIFO_SIZE__SHIFT 0x00000000
+#define SQ_FIFO_SIZES__TTRACE_FIFO_SIZE_MASK 0x00000f00L
+#define SQ_FIFO_SIZES__TTRACE_FIFO_SIZE__SHIFT 0x00000008
+#define SQ_FIFO_SIZES__VMEM_DATA_FIFO_SIZE_MASK 0x000c0000L
+#define SQ_FIFO_SIZES__VMEM_DATA_FIFO_SIZE__SHIFT 0x00000012
+#define SQ_IMG_RSRC_WORD0__BASE_ADDRESS_MASK 0xffffffffL
+#define SQ_IMG_RSRC_WORD0__BASE_ADDRESS__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD1__BASE_ADDRESS_HI_MASK 0x000000ffL
+#define SQ_IMG_RSRC_WORD1__BASE_ADDRESS_HI__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD1__DATA_FORMAT_MASK 0x03f00000L
+#define SQ_IMG_RSRC_WORD1__DATA_FORMAT__SHIFT 0x00000014
+#define SQ_IMG_RSRC_WORD1__MIN_LOD_MASK 0x000fff00L
+#define SQ_IMG_RSRC_WORD1__MIN_LOD__SHIFT 0x00000008
+#define SQ_IMG_RSRC_WORD1__MTYPE_MASK 0xc0000000L
+#define SQ_IMG_RSRC_WORD1__MTYPE__SHIFT 0x0000001e
+#define SQ_IMG_RSRC_WORD1__NUM_FORMAT_MASK 0x3c000000L
+#define SQ_IMG_RSRC_WORD1__NUM_FORMAT__SHIFT 0x0000001a
+#define SQ_IMG_RSRC_WORD2__HEIGHT_MASK 0x0fffc000L
+#define SQ_IMG_RSRC_WORD2__HEIGHT__SHIFT 0x0000000e
+#define SQ_IMG_RSRC_WORD2__INTERLACED_MASK 0x80000000L
+#define SQ_IMG_RSRC_WORD2__INTERLACED__SHIFT 0x0000001f
+#define SQ_IMG_RSRC_WORD2__PERF_MOD_MASK 0x70000000L
+#define SQ_IMG_RSRC_WORD2__PERF_MOD__SHIFT 0x0000001c
+#define SQ_IMG_RSRC_WORD2__WIDTH_MASK 0x00003fffL
+#define SQ_IMG_RSRC_WORD2__WIDTH__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD3__ATC_MASK 0x08000000L
+#define SQ_IMG_RSRC_WORD3__ATC__SHIFT 0x0000001b
+#define SQ_IMG_RSRC_WORD3__BASE_LEVEL_MASK 0x0000f000L
+#define SQ_IMG_RSRC_WORD3__BASE_LEVEL__SHIFT 0x0000000c
+#define SQ_IMG_RSRC_WORD3__DST_SEL_W_MASK 0x00000e00L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_W__SHIFT 0x00000009
+#define SQ_IMG_RSRC_WORD3__DST_SEL_X_MASK 0x00000007L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_X__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Y_MASK 0x00000038L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Y__SHIFT 0x00000003
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Z_MASK 0x000001c0L
+#define SQ_IMG_RSRC_WORD3__DST_SEL_Z__SHIFT 0x00000006
+#define SQ_IMG_RSRC_WORD3__LAST_LEVEL_MASK 0x000f0000L
+#define SQ_IMG_RSRC_WORD3__LAST_LEVEL__SHIFT 0x00000010
+#define SQ_IMG_RSRC_WORD3__MTYPE_MASK 0x04000000L
+#define SQ_IMG_RSRC_WORD3__MTYPE__SHIFT 0x0000001a
+#define SQ_IMG_RSRC_WORD3__POW2_PAD_MASK 0x02000000L
+#define SQ_IMG_RSRC_WORD3__POW2_PAD__SHIFT 0x00000019
+#define SQ_IMG_RSRC_WORD3__TILING_INDEX_MASK 0x01f00000L
+#define SQ_IMG_RSRC_WORD3__TILING_INDEX__SHIFT 0x00000014
+#define SQ_IMG_RSRC_WORD3__TYPE_MASK 0xf0000000L
+#define SQ_IMG_RSRC_WORD3__TYPE__SHIFT 0x0000001c
+#define SQ_IMG_RSRC_WORD4__DEPTH_MASK 0x00001fffL
+#define SQ_IMG_RSRC_WORD4__DEPTH__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD4__PITCH_MASK 0x07ffe000L
+#define SQ_IMG_RSRC_WORD4__PITCH__SHIFT 0x0000000d
+#define SQ_IMG_RSRC_WORD5__BASE_ARRAY_MASK 0x00001fffL
+#define SQ_IMG_RSRC_WORD5__BASE_ARRAY__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD5__LAST_ARRAY_MASK 0x03ffe000L
+#define SQ_IMG_RSRC_WORD5__LAST_ARRAY__SHIFT 0x0000000d
+#define SQ_IMG_RSRC_WORD6__COUNTER_BANK_ID_MASK 0x000ff000L
+#define SQ_IMG_RSRC_WORD6__COUNTER_BANK_ID__SHIFT 0x0000000c
+#define SQ_IMG_RSRC_WORD6__LOD_HDW_CNT_EN_MASK 0x00100000L
+#define SQ_IMG_RSRC_WORD6__LOD_HDW_CNT_EN__SHIFT 0x00000014
+#define SQ_IMG_RSRC_WORD6__MIN_LOD_WARN_MASK 0x00000fffL
+#define SQ_IMG_RSRC_WORD6__MIN_LOD_WARN__SHIFT 0x00000000
+#define SQ_IMG_RSRC_WORD6__UNUNSED_MASK 0xffe00000L
+#define SQ_IMG_RSRC_WORD6__UNUNSED__SHIFT 0x00000015
+#define SQ_IMG_RSRC_WORD7__UNUNSED_MASK 0xffffffffL
+#define SQ_IMG_RSRC_WORD7__UNUNSED__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD0__ANISO_BIAS_MASK 0x07e00000L
+#define SQ_IMG_SAMP_WORD0__ANISO_BIAS__SHIFT 0x00000015
+#define SQ_IMG_SAMP_WORD0__ANISO_THRESHOLD_MASK 0x00070000L
+#define SQ_IMG_SAMP_WORD0__ANISO_THRESHOLD__SHIFT 0x00000010
+#define SQ_IMG_SAMP_WORD0__CLAMP_X_MASK 0x00000007L
+#define SQ_IMG_SAMP_WORD0__CLAMP_X__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD0__CLAMP_Y_MASK 0x00000038L
+#define SQ_IMG_SAMP_WORD0__CLAMP_Y__SHIFT 0x00000003
+#define SQ_IMG_SAMP_WORD0__CLAMP_Z_MASK 0x000001c0L
+#define SQ_IMG_SAMP_WORD0__CLAMP_Z__SHIFT 0x00000006
+#define SQ_IMG_SAMP_WORD0__DEPTH_COMPARE_FUNC_MASK 0x00007000L
+#define SQ_IMG_SAMP_WORD0__DEPTH_COMPARE_FUNC__SHIFT 0x0000000c
+#define SQ_IMG_SAMP_WORD0__DISABLE_CUBE_WRAP_MASK 0x10000000L
+#define SQ_IMG_SAMP_WORD0__DISABLE_CUBE_WRAP__SHIFT 0x0000001c
+#define SQ_IMG_SAMP_WORD0__FILTER_MODE_MASK 0x60000000L
+#define SQ_IMG_SAMP_WORD0__FILTER_MODE__SHIFT 0x0000001d
+#define SQ_IMG_SAMP_WORD0__FORCE_DEGAMMA_MASK 0x00100000L
+#define SQ_IMG_SAMP_WORD0__FORCE_DEGAMMA__SHIFT 0x00000014
+#define SQ_IMG_SAMP_WORD0__FORCE_UNNORMALIZED_MASK 0x00008000L
+#define SQ_IMG_SAMP_WORD0__FORCE_UNNORMALIZED__SHIFT 0x0000000f
+#define SQ_IMG_SAMP_WORD0__MAX_ANISO_RATIO_MASK 0x00000e00L
+#define SQ_IMG_SAMP_WORD0__MAX_ANISO_RATIO__SHIFT 0x00000009
+#define SQ_IMG_SAMP_WORD0__MC_COORD_TRUNC_MASK 0x00080000L
+#define SQ_IMG_SAMP_WORD0__MC_COORD_TRUNC__SHIFT 0x00000013
+#define SQ_IMG_SAMP_WORD0__TRUNC_COORD_MASK 0x08000000L
+#define SQ_IMG_SAMP_WORD0__TRUNC_COORD__SHIFT 0x0000001b
+#define SQ_IMG_SAMP_WORD1__MAX_LOD_MASK 0x00fff000L
+#define SQ_IMG_SAMP_WORD1__MAX_LOD__SHIFT 0x0000000c
+#define SQ_IMG_SAMP_WORD1__MIN_LOD_MASK 0x00000fffL
+#define SQ_IMG_SAMP_WORD1__MIN_LOD__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD1__PERF_MIP_MASK 0x0f000000L
+#define SQ_IMG_SAMP_WORD1__PERF_MIP__SHIFT 0x00000018
+#define SQ_IMG_SAMP_WORD1__PERF_Z_MASK 0xf0000000L
+#define SQ_IMG_SAMP_WORD1__PERF_Z__SHIFT 0x0000001c
+#define SQ_IMG_SAMP_WORD2__DISABLE_LSB_CEIL_MASK 0x20000000L
+#define SQ_IMG_SAMP_WORD2__DISABLE_LSB_CEIL__SHIFT 0x0000001d
+#define SQ_IMG_SAMP_WORD2__FILTER_PREC_FIX_MASK 0x40000000L
+#define SQ_IMG_SAMP_WORD2__FILTER_PREC_FIX__SHIFT 0x0000001e
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_MASK 0x00003fffL
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_SEC_MASK 0x000fc000L
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS_SEC__SHIFT 0x0000000e
+#define SQ_IMG_SAMP_WORD2__LOD_BIAS__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD2__MIP_FILTER_MASK 0x0c000000L
+#define SQ_IMG_SAMP_WORD2__MIP_FILTER__SHIFT 0x0000001a
+#define SQ_IMG_SAMP_WORD2__MIP_POINT_PRECLAMP_MASK 0x10000000L
+#define SQ_IMG_SAMP_WORD2__MIP_POINT_PRECLAMP__SHIFT 0x0000001c
+#define SQ_IMG_SAMP_WORD2__XY_MAG_FILTER_MASK 0x00300000L
+#define SQ_IMG_SAMP_WORD2__XY_MAG_FILTER__SHIFT 0x00000014
+#define SQ_IMG_SAMP_WORD2__XY_MIN_FILTER_MASK 0x00c00000L
+#define SQ_IMG_SAMP_WORD2__XY_MIN_FILTER__SHIFT 0x00000016
+#define SQ_IMG_SAMP_WORD2__Z_FILTER_MASK 0x03000000L
+#define SQ_IMG_SAMP_WORD2__Z_FILTER__SHIFT 0x00000018
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_PTR_MASK 0x00000fffL
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_PTR__SHIFT 0x00000000
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_TYPE_MASK 0xc0000000L
+#define SQ_IMG_SAMP_WORD3__BORDER_COLOR_TYPE__SHIFT 0x0000001e
+#define SQ_IND_DATA__DATA_MASK 0xffffffffL
+#define SQ_IND_DATA__DATA__SHIFT 0x00000000
+#define SQ_IND_INDEX__AUTO_INCR_MASK 0x00001000L
+#define SQ_IND_INDEX__AUTO_INCR__SHIFT 0x0000000c
+#define SQ_IND_INDEX__FORCE_READ_MASK 0x00002000L
+#define SQ_IND_INDEX__FORCE_READ__SHIFT 0x0000000d
+#define SQ_IND_INDEX__INDEX_MASK 0xffff0000L
+#define SQ_IND_INDEX__INDEX__SHIFT 0x00000010
+#define SQ_IND_INDEX__READ_TIMEOUT_MASK 0x00004000L
+#define SQ_IND_INDEX__READ_TIMEOUT__SHIFT 0x0000000e
+#define SQ_IND_INDEX__SIMD_ID_MASK 0x00000030L
+#define SQ_IND_INDEX__SIMD_ID__SHIFT 0x00000004
+#define SQ_IND_INDEX__THREAD_ID_MASK 0x00000fc0L
+#define SQ_IND_INDEX__THREAD_ID__SHIFT 0x00000006
+#define SQ_IND_INDEX__UNINDEXED_MASK 0x00008000L
+#define SQ_IND_INDEX__UNINDEXED__SHIFT 0x0000000f
+#define SQ_IND_INDEX__WAVE_ID_MASK 0x0000000fL
+#define SQ_IND_INDEX__WAVE_ID__SHIFT 0x00000000
+#define SQ_INST__ENCODING_MASK 0xffffffffL
+#define SQ_INST__ENCODING__SHIFT 0x00000000
+#define SQ_INTERRUPT_WORD_AUTO__CMD_TIMESTAMP_MASK 0x00000010L
+#define SQ_INTERRUPT_WORD_AUTO__CMD_TIMESTAMP__SHIFT 0x00000004
+#define SQ_INTERRUPT_WORD_AUTO__ENCODING_MASK 0x0c000000L
+#define SQ_INTERRUPT_WORD_AUTO__ENCODING__SHIFT 0x0000001a
+#define SQ_INTERRUPT_WORD_AUTO__HOST_CMD_OVERFLOW_MASK 0x00000020L
+#define SQ_INTERRUPT_WORD_AUTO__HOST_CMD_OVERFLOW__SHIFT 0x00000005
+#define SQ_INTERRUPT_WORD_AUTO__HOST_REG_OVERFLOW_MASK 0x00000040L
+#define SQ_INTERRUPT_WORD_AUTO__HOST_REG_OVERFLOW__SHIFT 0x00000006
+#define SQ_INTERRUPT_WORD_AUTO__IMMED_OVERFLOW_MASK 0x00000080L
+#define SQ_INTERRUPT_WORD_AUTO__IMMED_OVERFLOW__SHIFT 0x00000007
+#define SQ_INTERRUPT_WORD_AUTO__REG_TIMESTAMP_MASK 0x00000008L
+#define SQ_INTERRUPT_WORD_AUTO__REG_TIMESTAMP__SHIFT 0x00000003
+#define SQ_INTERRUPT_WORD_AUTO__SE_ID_MASK 0x02000000L
+#define SQ_INTERRUPT_WORD_AUTO__SE_ID__SHIFT 0x00000019
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_BUF_FULL_MASK 0x00000004L
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_BUF_FULL__SHIFT 0x00000002
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE_MASK 0x00000001L
+#define SQ_INTERRUPT_WORD_AUTO__THREAD_TRACE__SHIFT 0x00000000
+#define SQ_INTERRUPT_WORD_AUTO__WLT_MASK 0x00000002L
+#define SQ_INTERRUPT_WORD_AUTO__WLT__SHIFT 0x00000001
+#define SQ_INTERRUPT_WORD_CMN__ENCODING_MASK 0x0c000000L
+#define SQ_INTERRUPT_WORD_CMN__ENCODING__SHIFT 0x0000001a
+#define SQ_INTERRUPT_WORD_CMN__SE_ID_MASK 0x02000000L
+#define SQ_INTERRUPT_WORD_CMN__SE_ID__SHIFT 0x00000019
+#define SQ_INTERRUPT_WORD_WAVE__CU_ID_MASK 0x00f00000L
+#define SQ_INTERRUPT_WORD_WAVE__CU_ID__SHIFT 0x00000014
+#define SQ_INTERRUPT_WORD_WAVE__DATA_MASK 0x000000ffL
+#define SQ_INTERRUPT_WORD_WAVE__DATA__SHIFT 0x00000000
+#define SQ_INTERRUPT_WORD_WAVE__ENCODING_MASK 0x0c000000L
+#define SQ_INTERRUPT_WORD_WAVE__ENCODING__SHIFT 0x0000001a
+#define SQ_INTERRUPT_WORD_WAVE__PRIV_MASK 0x00000200L
+#define SQ_INTERRUPT_WORD_WAVE__PRIV__SHIFT 0x00000009
+#define SQ_INTERRUPT_WORD_WAVE__SE_ID_MASK 0x02000000L
+#define SQ_INTERRUPT_WORD_WAVE__SE_ID__SHIFT 0x00000019
+#define SQ_INTERRUPT_WORD_WAVE__SH_ID_MASK 0x01000000L
+#define SQ_INTERRUPT_WORD_WAVE__SH_ID__SHIFT 0x00000018
+#define SQ_INTERRUPT_WORD_WAVE__SIMD_ID_MASK 0x000c0000L
+#define SQ_INTERRUPT_WORD_WAVE__SIMD_ID__SHIFT 0x00000012
+#define SQ_INTERRUPT_WORD_WAVE__VM_ID_MASK 0x00003c00L
+#define SQ_INTERRUPT_WORD_WAVE__VM_ID__SHIFT 0x0000000a
+#define SQ_INTERRUPT_WORD_WAVE__WAVE_ID_MASK 0x0003c000L
+#define SQ_INTERRUPT_WORD_WAVE__WAVE_ID__SHIFT 0x0000000e
+#define SQ_LB_CTR_CTRL__CLEAR_MASK 0x00000004L
+#define SQ_LB_CTR_CTRL__CLEAR__SHIFT 0x00000002
+#define SQ_LB_CTR_CTRL__LOAD_MASK 0x00000002L
+#define SQ_LB_CTR_CTRL__LOAD__SHIFT 0x00000001
+#define SQ_LB_CTR_CTRL__START_MASK 0x00000001L
+#define SQ_LB_CTR_CTRL__START__SHIFT 0x00000000
+#define SQ_LB_DATA_ALU_CYCLES__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_ALU_CYCLES__DATA__SHIFT 0x00000000
+#define SQ_LB_DATA_ALU_STALLS__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_ALU_STALLS__DATA__SHIFT 0x00000000
+#define SQ_LB_DATA_TEX_CYCLES__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_TEX_CYCLES__DATA__SHIFT 0x00000000
+#define SQ_LB_DATA_TEX_STALLS__DATA_MASK 0xffffffffL
+#define SQ_LB_DATA_TEX_STALLS__DATA__SHIFT 0x00000000
+#define SQ_MIMG_0__DA_MASK 0x00004000L
+#define SQ_MIMG_0__DA__SHIFT 0x0000000e
+#define SQ_MIMG_0__DMASK_MASK 0x00000f00L
+#define SQ_MIMG_0__DMASK__SHIFT 0x00000008
+#define SQ_MIMG_0__ENCODING_MASK 0xfc000000L
+#define SQ_MIMG_0__ENCODING__SHIFT 0x0000001a
+#define SQ_MIMG_0__GLC_MASK 0x00002000L
+#define SQ_MIMG_0__GLC__SHIFT 0x0000000d
+#define SQ_MIMG_0__LWE_MASK 0x00020000L
+#define SQ_MIMG_0__LWE__SHIFT 0x00000011
+#define SQ_MIMG_0__OP_MASK 0x01fc0000L
+#define SQ_MIMG_0__OP__SHIFT 0x00000012
+#define SQ_MIMG_0__R128_MASK 0x00008000L
+#define SQ_MIMG_0__R128__SHIFT 0x0000000f
+#define SQ_MIMG_0__SLC_MASK 0x02000000L
+#define SQ_MIMG_0__SLC__SHIFT 0x00000019
+#define SQ_MIMG_0__TFE_MASK 0x00010000L
+#define SQ_MIMG_0__TFE__SHIFT 0x00000010
+#define SQ_MIMG_0__UNORM_MASK 0x00001000L
+#define SQ_MIMG_0__UNORM__SHIFT 0x0000000c
+#define SQ_MIMG_1__SRSRC_MASK 0x001f0000L
+#define SQ_MIMG_1__SRSRC__SHIFT 0x00000010
+#define SQ_MIMG_1__SSAMP_MASK 0x03e00000L
+#define SQ_MIMG_1__SSAMP__SHIFT 0x00000015
+#define SQ_MIMG_1__VADDR_MASK 0x000000ffL
+#define SQ_MIMG_1__VADDR__SHIFT 0x00000000
+#define SQ_MIMG_1__VDATA_MASK 0x0000ff00L
+#define SQ_MIMG_1__VDATA__SHIFT 0x00000008
+#define SQ_MTBUF_0__ADDR64_MASK 0x00008000L
+#define SQ_MTBUF_0__ADDR64__SHIFT 0x0000000f
+#define SQ_MTBUF_0__DFMT_MASK 0x00780000L
+#define SQ_MTBUF_0__DFMT__SHIFT 0x00000013
+#define SQ_MTBUF_0__ENCODING_MASK 0xfc000000L
+#define SQ_MTBUF_0__ENCODING__SHIFT 0x0000001a
+#define SQ_MTBUF_0__GLC_MASK 0x00004000L
+#define SQ_MTBUF_0__GLC__SHIFT 0x0000000e
+#define SQ_MTBUF_0__IDXEN_MASK 0x00002000L
+#define SQ_MTBUF_0__IDXEN__SHIFT 0x0000000d
+#define SQ_MTBUF_0__NFMT_MASK 0x03800000L
+#define SQ_MTBUF_0__NFMT__SHIFT 0x00000017
+#define SQ_MTBUF_0__OFFEN_MASK 0x00001000L
+#define SQ_MTBUF_0__OFFEN__SHIFT 0x0000000c
+#define SQ_MTBUF_0__OFFSET_MASK 0x00000fffL
+#define SQ_MTBUF_0__OFFSET__SHIFT 0x00000000
+#define SQ_MTBUF_0__OP_MASK 0x00070000L
+#define SQ_MTBUF_0__OP__SHIFT 0x00000010
+#define SQ_MTBUF_1__SLC_MASK 0x00400000L
+#define SQ_MTBUF_1__SLC__SHIFT 0x00000016
+#define SQ_MTBUF_1__SOFFSET_MASK 0xff000000L
+#define SQ_MTBUF_1__SOFFSET__SHIFT 0x00000018
+#define SQ_MTBUF_1__SRSRC_MASK 0x001f0000L
+#define SQ_MTBUF_1__SRSRC__SHIFT 0x00000010
+#define SQ_MTBUF_1__TFE_MASK 0x00800000L
+#define SQ_MTBUF_1__TFE__SHIFT 0x00000017
+#define SQ_MTBUF_1__VADDR_MASK 0x000000ffL
+#define SQ_MTBUF_1__VADDR__SHIFT 0x00000000
+#define SQ_MTBUF_1__VDATA_MASK 0x0000ff00L
+#define SQ_MTBUF_1__VDATA__SHIFT 0x00000008
+#define SQ_MUBUF_0__ADDR64_MASK 0x00008000L
+#define SQ_MUBUF_0__ADDR64__SHIFT 0x0000000f
+#define SQ_MUBUF_0__ENCODING_MASK 0xfc000000L
+#define SQ_MUBUF_0__ENCODING__SHIFT 0x0000001a
+#define SQ_MUBUF_0__GLC_MASK 0x00004000L
+#define SQ_MUBUF_0__GLC__SHIFT 0x0000000e
+#define SQ_MUBUF_0__IDXEN_MASK 0x00002000L
+#define SQ_MUBUF_0__IDXEN__SHIFT 0x0000000d
+#define SQ_MUBUF_0__LDS_MASK 0x00010000L
+#define SQ_MUBUF_0__LDS__SHIFT 0x00000010
+#define SQ_MUBUF_0__OFFEN_MASK 0x00001000L
+#define SQ_MUBUF_0__OFFEN__SHIFT 0x0000000c
+#define SQ_MUBUF_0__OFFSET_MASK 0x00000fffL
+#define SQ_MUBUF_0__OFFSET__SHIFT 0x00000000
+#define SQ_MUBUF_0__OP_MASK 0x01fc0000L
+#define SQ_MUBUF_0__OP__SHIFT 0x00000012
+#define SQ_MUBUF_1__SLC_MASK 0x00400000L
+#define SQ_MUBUF_1__SLC__SHIFT 0x00000016
+#define SQ_MUBUF_1__SOFFSET_MASK 0xff000000L
+#define SQ_MUBUF_1__SOFFSET__SHIFT 0x00000018
+#define SQ_MUBUF_1__SRSRC_MASK 0x001f0000L
+#define SQ_MUBUF_1__SRSRC__SHIFT 0x00000010
+#define SQ_MUBUF_1__TFE_MASK 0x00800000L
+#define SQ_MUBUF_1__TFE__SHIFT 0x00000017
+#define SQ_MUBUF_1__VADDR_MASK 0x000000ffL
+#define SQ_MUBUF_1__VADDR__SHIFT 0x00000000
+#define SQ_MUBUF_1__VDATA_MASK 0x0000ff00L
+#define SQ_MUBUF_1__VDATA__SHIFT 0x00000008
+#define SQ_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER0_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER0_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER0_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER0_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER0_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER0_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER0_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER0_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER10_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER10_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER10_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER10_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER10_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER10_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER10_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER10_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER10_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER10_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER10_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER10_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER10_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER10_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER10_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER10_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER11_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER11_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER11_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER11_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER11_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER11_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER11_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER11_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER11_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER11_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER11_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER11_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER11_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER11_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER11_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER11_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER12_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER12_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER12_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER12_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER12_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER12_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER12_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER12_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER12_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER12_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER12_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER12_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER12_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER12_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER12_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER12_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER13_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER13_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER13_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER13_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER13_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER13_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER13_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER13_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER13_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER13_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER13_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER13_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER13_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER13_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER13_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER13_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER14_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER14_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER14_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER14_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER14_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER14_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER14_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER14_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER14_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER14_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER14_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER14_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER14_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER14_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER14_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER14_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER15_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER15_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER15_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER15_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER15_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER15_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER15_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER15_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER15_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER15_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER15_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER15_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER15_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER15_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER15_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER15_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER1_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER1_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER1_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER1_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER1_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER1_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER1_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER1_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER2_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER2_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER2_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER2_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER2_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER2_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER2_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER2_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER3_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER3_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER3_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER3_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER3_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER3_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER3_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER3_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER4_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER4_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER4_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER4_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER4_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER4_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER4_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER4_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER4_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER4_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER4_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER4_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER4_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER4_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER4_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER4_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER5_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER5_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER5_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER5_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER5_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER5_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER5_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER5_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER5_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER5_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER5_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER5_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER5_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER5_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER5_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER5_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER6_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER6_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER6_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER6_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER6_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER6_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER6_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER6_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER6_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER6_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER6_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER6_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER6_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER6_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER6_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER6_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER7_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER7_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER7_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER7_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER7_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER7_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER7_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER7_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER7_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER7_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER7_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER7_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER7_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER7_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER7_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER7_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER8_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER8_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER8_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER8_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER8_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER8_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER8_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER8_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER8_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER8_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER8_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER8_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER8_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER8_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER8_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER8_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER9_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SQ_PERFCOUNTER9_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SQ_PERFCOUNTER9_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SQ_PERFCOUNTER9_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SQ_PERFCOUNTER9_SELECT__PERF_MODE_MASK 0xf0000000L
+#define SQ_PERFCOUNTER9_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define SQ_PERFCOUNTER9_SELECT__PERF_SEL_MASK 0x000001ffL
+#define SQ_PERFCOUNTER9_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SQ_PERFCOUNTER9_SELECT__SIMD_MASK_MASK 0x0f000000L
+#define SQ_PERFCOUNTER9_SELECT__SIMD_MASK__SHIFT 0x00000018
+#define SQ_PERFCOUNTER9_SELECT__SPM_MODE_MASK 0x00f00000L
+#define SQ_PERFCOUNTER9_SELECT__SPM_MODE__SHIFT 0x00000014
+#define SQ_PERFCOUNTER9_SELECT__SQC_BANK_MASK_MASK 0x0000f000L
+#define SQ_PERFCOUNTER9_SELECT__SQC_BANK_MASK__SHIFT 0x0000000c
+#define SQ_PERFCOUNTER9_SELECT__SQC_CLIENT_MASK_MASK 0x000f0000L
+#define SQ_PERFCOUNTER9_SELECT__SQC_CLIENT_MASK__SHIFT 0x00000010
+#define SQ_PERFCOUNTER_CTRL2__FORCE_EN_MASK 0x00000001L
+#define SQ_PERFCOUNTER_CTRL2__FORCE_EN__SHIFT 0x00000000
+#define SQ_PERFCOUNTER_CTRL__CNTR_RATE_MASK 0x00001f00L
+#define SQ_PERFCOUNTER_CTRL__CNTR_RATE__SHIFT 0x00000008
+#define SQ_PERFCOUNTER_CTRL__CS_EN_MASK 0x00000040L
+#define SQ_PERFCOUNTER_CTRL__CS_EN__SHIFT 0x00000006
+#define SQ_PERFCOUNTER_CTRL__DISABLE_FLUSH_MASK 0x00002000L
+#define SQ_PERFCOUNTER_CTRL__DISABLE_FLUSH__SHIFT 0x0000000d
+#define SQ_PERFCOUNTER_CTRL__ES_EN_MASK 0x00000008L
+#define SQ_PERFCOUNTER_CTRL__ES_EN__SHIFT 0x00000003
+#define SQ_PERFCOUNTER_CTRL__GS_EN_MASK 0x00000004L
+#define SQ_PERFCOUNTER_CTRL__GS_EN__SHIFT 0x00000002
+#define SQ_PERFCOUNTER_CTRL__HS_EN_MASK 0x00000010L
+#define SQ_PERFCOUNTER_CTRL__HS_EN__SHIFT 0x00000004
+#define SQ_PERFCOUNTER_CTRL__LS_EN_MASK 0x00000020L
+#define SQ_PERFCOUNTER_CTRL__LS_EN__SHIFT 0x00000005
+#define SQ_PERFCOUNTER_CTRL__PS_EN_MASK 0x00000001L
+#define SQ_PERFCOUNTER_CTRL__PS_EN__SHIFT 0x00000000
+#define SQ_PERFCOUNTER_CTRL__VS_EN_MASK 0x00000002L
+#define SQ_PERFCOUNTER_CTRL__VS_EN__SHIFT 0x00000001
+#define SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO_MASK 0x78000000L
+#define SQ_POWER_THROTTLE2__LONG_TERM_INTERVAL_RATIO__SHIFT 0x0000001b
+#define SQ_POWER_THROTTLE2__MAX_POWER_DELTA_MASK 0x00003fffL
+#define SQ_POWER_THROTTLE2__MAX_POWER_DELTA__SHIFT 0x00000000
+#define SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE_MASK 0x03ff0000L
+#define SQ_POWER_THROTTLE2__SHORT_TERM_INTERVAL_SIZE__SHIFT 0x00000010
+#define SQ_POWER_THROTTLE2__USE_REF_CLOCK_MASK 0x80000000L
+#define SQ_POWER_THROTTLE2__USE_REF_CLOCK__SHIFT 0x0000001f
+#define SQ_POWER_THROTTLE__MAX_POWER_MASK 0x3fff0000L
+#define SQ_POWER_THROTTLE__MAX_POWER__SHIFT 0x00000010
+#define SQ_POWER_THROTTLE__MIN_POWER_MASK 0x00003fffL
+#define SQ_POWER_THROTTLE__MIN_POWER__SHIFT 0x00000000
+#define SQ_POWER_THROTTLE__PHASE_OFFSET_MASK 0xc0000000L
+#define SQ_POWER_THROTTLE__PHASE_OFFSET__SHIFT 0x0000001e
+#define SQ_RANDOM_WAVE_PRI__RET_MASK 0x0000007fL
+#define SQ_RANDOM_WAVE_PRI__RET__SHIFT 0x00000000
+#define SQ_RANDOM_WAVE_PRI__RNG_MASK 0x001ffc00L
+#define SQ_RANDOM_WAVE_PRI__RNG__SHIFT 0x0000000a
+#define SQ_RANDOM_WAVE_PRI__RUI_MASK 0x00000380L
+#define SQ_RANDOM_WAVE_PRI__RUI__SHIFT 0x00000007
+#define SQ_REG_CREDITS__CMD_CREDITS_MASK 0x00000f00L
+#define SQ_REG_CREDITS__CMD_CREDITS__SHIFT 0x00000008
+#define SQ_REG_CREDITS__CMD_OVERFLOW_MASK 0x80000000L
+#define SQ_REG_CREDITS__CMD_OVERFLOW__SHIFT 0x0000001f
+#define SQ_REG_CREDITS__IMMED_OVERFLOW_MASK 0x40000000L
+#define SQ_REG_CREDITS__IMMED_OVERFLOW__SHIFT 0x0000001e
+#define SQ_REG_CREDITS__REG_BUSY_MASK 0x10000000L
+#define SQ_REG_CREDITS__REG_BUSY__SHIFT 0x0000001c
+#define SQ_REG_CREDITS__SRBM_CREDITS_MASK 0x0000003fL
+#define SQ_REG_CREDITS__SRBM_CREDITS__SHIFT 0x00000000
+#define SQ_REG_CREDITS__SRBM_OVERFLOW_MASK 0x20000000L
+#define SQ_REG_CREDITS__SRBM_OVERFLOW__SHIFT 0x0000001d
+#define SQ_SEC_CNT__LDS_SEC_MASK 0x0000003fL
+#define SQ_SEC_CNT__LDS_SEC__SHIFT 0x00000000
+#define SQ_SEC_CNT__SGPR_SEC_MASK 0x00001f00L
+#define SQ_SEC_CNT__SGPR_SEC__SHIFT 0x00000008
+#define SQ_SEC_CNT__VGPR_SEC_MASK 0x01ff0000L
+#define SQ_SEC_CNT__VGPR_SEC__SHIFT 0x00000010
+#define SQ_SMRD__ENCODING_MASK 0xf8000000L
+#define SQ_SMRD__ENCODING__SHIFT 0x0000001b
+#define SQ_SMRD__IMM_MASK 0x00000100L
+#define SQ_SMRD__IMM__SHIFT 0x00000008
+#define SQ_SMRD__OFFSET_MASK 0x000000ffL
+#define SQ_SMRD__OFFSET__SHIFT 0x00000000
+#define SQ_SMRD__OP_MASK 0x07c00000L
+#define SQ_SMRD__OP__SHIFT 0x00000016
+#define SQ_SMRD__SBASE_MASK 0x00007e00L
+#define SQ_SMRD__SBASE__SHIFT 0x00000009
+#define SQ_SMRD__SDST_MASK 0x003f8000L
+#define SQ_SMRD__SDST__SHIFT 0x0000000f
+#define SQ_SOP1__ENCODING_MASK 0xff800000L
+#define SQ_SOP1__ENCODING__SHIFT 0x00000017
+#define SQ_SOP1__OP_MASK 0x0000ff00L
+#define SQ_SOP1__OP__SHIFT 0x00000008
+#define SQ_SOP1__SDST_MASK 0x007f0000L
+#define SQ_SOP1__SDST__SHIFT 0x00000010
+#define SQ_SOP1__SSRC0_MASK 0x000000ffL
+#define SQ_SOP1__SSRC0__SHIFT 0x00000000
+#define SQ_SOP2__ENCODING_MASK 0xc0000000L
+#define SQ_SOP2__ENCODING__SHIFT 0x0000001e
+#define SQ_SOP2__OP_MASK 0x3f800000L
+#define SQ_SOP2__OP__SHIFT 0x00000017
+#define SQ_SOP2__SDST_MASK 0x007f0000L
+#define SQ_SOP2__SDST__SHIFT 0x00000010
+#define SQ_SOP2__SSRC0_MASK 0x000000ffL
+#define SQ_SOP2__SSRC0__SHIFT 0x00000000
+#define SQ_SOP2__SSRC1_MASK 0x0000ff00L
+#define SQ_SOP2__SSRC1__SHIFT 0x00000008
+#define SQ_SOPC__ENCODING_MASK 0xff800000L
+#define SQ_SOPC__ENCODING__SHIFT 0x00000017
+#define SQ_SOPC__OP_MASK 0x007f0000L
+#define SQ_SOPC__OP__SHIFT 0x00000010
+#define SQ_SOPC__SSRC0_MASK 0x000000ffL
+#define SQ_SOPC__SSRC0__SHIFT 0x00000000
+#define SQ_SOPC__SSRC1_MASK 0x0000ff00L
+#define SQ_SOPC__SSRC1__SHIFT 0x00000008
+#define SQ_SOPK__ENCODING_MASK 0xf0000000L
+#define SQ_SOPK__ENCODING__SHIFT 0x0000001c
+#define SQ_SOPK__OP_MASK 0x0f800000L
+#define SQ_SOPK__OP__SHIFT 0x00000017
+#define SQ_SOPK__SDST_MASK 0x007f0000L
+#define SQ_SOPK__SDST__SHIFT 0x00000010
+#define SQ_SOPK__SIMM16_MASK 0x0000ffffL
+#define SQ_SOPK__SIMM16__SHIFT 0x00000000
+#define SQ_SOPP__ENCODING_MASK 0xff800000L
+#define SQ_SOPP__ENCODING__SHIFT 0x00000017
+#define SQ_SOPP__OP_MASK 0x007f0000L
+#define SQ_SOPP__OP__SHIFT 0x00000010
+#define SQ_SOPP__SIMM16_MASK 0x0000ffffL
+#define SQ_SOPP__SIMM16__SHIFT 0x00000000
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH0_MASK 0x0000ffffL
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH0__SHIFT 0x00000000
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH1_MASK 0xffff0000L
+#define SQ_TEX_CLK_CTRL__FORCE_CU_ON_SH1__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_BASE2__ADDR_HI_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_BASE2__ADDR_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_BASE2__ATC_MASK 0x00000010L
+#define SQ_THREAD_TRACE_BASE2__ATC__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_BASE__ADDR_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_BASE__ADDR__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_CNTR__CNTR_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_CNTR__CNTR__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_CTRL__RESET_BUFFER_MASK 0x80000000L
+#define SQ_THREAD_TRACE_CTRL__RESET_BUFFER__SHIFT 0x0000001f
+#define SQ_THREAD_TRACE_HIWATER__HIWATER_MASK 0x00000007L
+#define SQ_THREAD_TRACE_HIWATER__HIWATER__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_MASK__CU_SEL_MASK 0x0000001fL
+#define SQ_THREAD_TRACE_MASK__CU_SEL__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_MASK__RANDOM_SEED_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_MASK__RANDOM_SEED__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_MASK__REG_STALL_EN_MASK 0x00000080L
+#define SQ_THREAD_TRACE_MASK__REG_STALL_EN__SHIFT 0x00000007
+#define SQ_THREAD_TRACE_MASK__SH_SEL_MASK 0x00000020L
+#define SQ_THREAD_TRACE_MASK__SH_SEL__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_MASK__SPI_STALL_EN_MASK 0x00004000L
+#define SQ_THREAD_TRACE_MASK__SPI_STALL_EN__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_MASK__SQ_STALL_EN_MASK 0x00008000L
+#define SQ_THREAD_TRACE_MASK__SQ_STALL_EN__SHIFT 0x0000000f
+#define SQ_THREAD_TRACE_MASK__VM_ID_MASK_MASK 0x00003000L
+#define SQ_THREAD_TRACE_MASK__VM_ID_MASK__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_MODE__AUTOFLUSH_EN_MASK 0x02000000L
+#define SQ_THREAD_TRACE_MODE__AUTOFLUSH_EN__SHIFT 0x00000019
+#define SQ_THREAD_TRACE_MODE__CAPTURE_MODE_MASK 0x01800000L
+#define SQ_THREAD_TRACE_MODE__CAPTURE_MODE__SHIFT 0x00000017
+#define SQ_THREAD_TRACE_MODE__INTERRUPT_EN_MASK 0x40000000L
+#define SQ_THREAD_TRACE_MODE__INTERRUPT_EN__SHIFT 0x0000001e
+#define SQ_THREAD_TRACE_MODE__ISSUE_MASK_MASK 0x18000000L
+#define SQ_THREAD_TRACE_MODE__ISSUE_MASK__SHIFT 0x0000001b
+#define SQ_THREAD_TRACE_MODE__MASK_CS_MASK 0x001c0000L
+#define SQ_THREAD_TRACE_MODE__MASK_CS__SHIFT 0x00000012
+#define SQ_THREAD_TRACE_MODE__MASK_ES_MASK 0x00000e00L
+#define SQ_THREAD_TRACE_MODE__MASK_ES__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_MODE__MASK_GS_MASK 0x000001c0L
+#define SQ_THREAD_TRACE_MODE__MASK_GS__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_MODE__MASK_HS_MASK 0x00007000L
+#define SQ_THREAD_TRACE_MODE__MASK_HS__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_MODE__MASK_LS_MASK 0x00038000L
+#define SQ_THREAD_TRACE_MODE__MASK_LS__SHIFT 0x0000000f
+#define SQ_THREAD_TRACE_MODE__MASK_PS_MASK 0x00000007L
+#define SQ_THREAD_TRACE_MODE__MASK_PS__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_MODE__MASK_VS_MASK 0x00000038L
+#define SQ_THREAD_TRACE_MODE__MASK_VS__SHIFT 0x00000003
+#define SQ_THREAD_TRACE_MODE__MODE_MASK 0x00600000L
+#define SQ_THREAD_TRACE_MODE__MODE__SHIFT 0x00000015
+#define SQ_THREAD_TRACE_MODE__PRIV_MASK 0x04000000L
+#define SQ_THREAD_TRACE_MODE__PRIV__SHIFT 0x0000001a
+#define SQ_THREAD_TRACE_MODE__TEST_MODE_MASK 0x20000000L
+#define SQ_THREAD_TRACE_MODE__TEST_MODE__SHIFT 0x0000001d
+#define SQ_THREAD_TRACE_MODE__WRAP_MASK 0x80000000L
+#define SQ_THREAD_TRACE_MODE__WRAP__SHIFT 0x0000001f
+#define SQ_THREAD_TRACE_PERF_MASK__SH0_MASK_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_PERF_MASK__SH0_MASK__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_PERF_MASK__SH1_MASK_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_PERF_MASK__SH1_MASK__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_SIZE__SIZE_MASK 0x003fffffL
+#define SQ_THREAD_TRACE_SIZE__SIZE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_STATUS__BUSY_MASK 0x40000000L
+#define SQ_THREAD_TRACE_STATUS__BUSY__SHIFT 0x0000001e
+#define SQ_THREAD_TRACE_STATUS__FINISH_DONE_MASK 0x00070000L
+#define SQ_THREAD_TRACE_STATUS__FINISH_DONE__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_STATUS__FINISH_PENDING_MASK 0x00000007L
+#define SQ_THREAD_TRACE_STATUS__FINISH_PENDING__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_STATUS__FULL_MASK 0x80000000L
+#define SQ_THREAD_TRACE_STATUS__FULL__SHIFT 0x0000001f
+#define SQ_THREAD_TRACE_STATUS__NEW_BUF_MASK 0x20000000L
+#define SQ_THREAD_TRACE_STATUS__NEW_BUF__SHIFT 0x0000001d
+#define SQ_THREAD_TRACE_TOKEN_MASK2__INST_MASK_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_TOKEN_MASK2__INST_MASK__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_DROP_ON_STALL_MASK 0x01000000L
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_DROP_ON_STALL__SHIFT 0x00000018
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_MASK_MASK 0x00ff0000L
+#define SQ_THREAD_TRACE_TOKEN_MASK__REG_MASK__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_TOKEN_MASK__TOKEN_MASK_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_TOKEN_MASK__TOKEN_MASK__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_0__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_0__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_1__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_1__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_2__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_2__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_USERDATA_3__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_USERDATA_3__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_CMN__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_CMN__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_CMN__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_CMN__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_EVENT__EVENT_TYPE_MASK 0x0000fc00L
+#define SQ_THREAD_TRACE_WORD_EVENT__EVENT_TYPE__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_EVENT__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_EVENT__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_EVENT__STAGE_MASK 0x000001c0L
+#define SQ_THREAD_TRACE_WORD_EVENT__STAGE__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_EVENT__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_EVENT__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_EVENT__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_EVENT__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST__INST_TYPE_MASK 0x0000f000L
+#define SQ_THREAD_TRACE_WORD_INST__INST_TYPE__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__PC_LO_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__PC_LO__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__SIMD_ID_MASK 0x00000600L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__SIMD_ID__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__WAVE_ID_MASK 0x000001e0L
+#define SQ_THREAD_TRACE_WORD_INST_PC_1_OF_2__WAVE_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_INST_PC_2_OF_2__PC_HI_MASK 0x00ffffffL
+#define SQ_THREAD_TRACE_WORD_INST_PC_2_OF_2__PC_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST__SIMD_ID_MASK 0x00000600L
+#define SQ_THREAD_TRACE_WORD_INST__SIMD_ID__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_WORD_INST__SIZE_MASK 0x00000800L
+#define SQ_THREAD_TRACE_WORD_INST__SIZE__SHIFT 0x0000000b
+#define SQ_THREAD_TRACE_WORD_INST__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_INST__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_INST__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_INST__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__DATA_LO_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__DATA_LO__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SIMD_ID_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__SIMD_ID__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__WAVE_ID_MASK 0x00003c00L
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_1_OF_2__WAVE_ID__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2__DATA_HI_MASK 0x0000ffffL
+#define SQ_THREAD_TRACE_WORD_INST_USERDATA_2_OF_2__DATA_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_INST__WAVE_ID_MASK 0x000001e0L
+#define SQ_THREAD_TRACE_WORD_INST__WAVE_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST0_MASK 0x00000300L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST0__SHIFT 0x00000008
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST1_MASK 0x00000c00L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST1__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST2_MASK 0x00003000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST2__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST3_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST3__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST4_MASK 0x00030000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST4__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST5_MASK 0x000c0000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST5__SHIFT 0x00000012
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST6_MASK 0x00300000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST6__SHIFT 0x00000014
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST7_MASK 0x00c00000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST7__SHIFT 0x00000016
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST8_MASK 0x03000000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST8__SHIFT 0x00000018
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST9_MASK 0x0c000000L
+#define SQ_THREAD_TRACE_WORD_ISSUE__INST9__SHIFT 0x0000001a
+#define SQ_THREAD_TRACE_WORD_ISSUE__SIMD_ID_MASK 0x00000060L
+#define SQ_THREAD_TRACE_WORD_ISSUE__SIMD_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_ISSUE__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_ISSUE__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_ISSUE__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_ISSUE__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_MISC__MISC_TOKEN_TYPE_MASK 0x000000c0L
+#define SQ_THREAD_TRACE_WORD_MISC__MISC_TOKEN_TYPE__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_MISC__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_MISC__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_MISC__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_MISC__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_MISC__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_MISC__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR0_MASK 0x01fff000L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR0__SHIFT 0x0000000c
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR1_LO_MASK 0xfe000000L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR1_LO__SHIFT 0x00000019
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR_BANK_MASK 0x00000c00L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CNTR_BANK__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_PERF_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR1_HI_MASK 0x0000003fL
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR1_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR2_MASK 0x0007ffc0L
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR2__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR3_MASK 0xfff80000L
+#define SQ_THREAD_TRACE_WORD_PERF_2_OF_2__CNTR3__SHIFT 0x00000013
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__ME_ID_MASK 0x00000180L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__ME_ID__SHIFT 0x00000007
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__PIPE_ID_MASK 0x00000060L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__PIPE_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_ADDR_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_ADDR__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_DROPPED_PREV_MASK 0x00000200L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_DROPPED_PREV__SHIFT 0x00000009
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_OP_MASK 0x00008000L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_OP__SHIFT 0x0000000f
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_PRIV_MASK 0x00004000L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_PRIV__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_TYPE_MASK 0x00001c00L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__REG_TYPE__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_REG_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_REG_2_OF_2__DATA_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_WORD_REG_2_OF_2__DATA__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TIME_LO_MASK 0xffff0000L
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TIME_LO__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_1_OF_2__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2__TIME_HI_MASK 0xffffffffL
+#define SQ_THREAD_TRACE_WORD_TIMESTAMP_2_OF_2__TIME_HI__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_WAVE__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_WAVE__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_WAVE__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_WAVE__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_WAVE__SIMD_ID_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_WAVE__SIMD_ID__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_WAVE_START__COUNT_MASK 0x1fc00000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__COUNT__SHIFT 0x00000016
+#define SQ_THREAD_TRACE_WORD_WAVE_START__CU_ID_MASK 0x000003c0L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__CU_ID__SHIFT 0x00000006
+#define SQ_THREAD_TRACE_WORD_WAVE_START__DISPATCHER_MASK 0x001f0000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__DISPATCHER__SHIFT 0x00000010
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SH_ID_MASK 0x00000020L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SH_ID__SHIFT 0x00000005
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SIMD_ID_MASK 0x0000c000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__SIMD_ID__SHIFT 0x0000000e
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TG_ID_MASK 0xe0000000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TG_ID__SHIFT 0x0000001d
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_WAVE_START__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_WAVE_START__VS_NO_ALLOC_OR_GROUPED_MASK 0x00200000L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__VS_NO_ALLOC_OR_GROUPED__SHIFT 0x00000015
+#define SQ_THREAD_TRACE_WORD_WAVE_START__WAVE_ID_MASK 0x00003c00L
+#define SQ_THREAD_TRACE_WORD_WAVE_START__WAVE_ID__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WORD_WAVE__TIME_DELTA_MASK 0x00000010L
+#define SQ_THREAD_TRACE_WORD_WAVE__TIME_DELTA__SHIFT 0x00000004
+#define SQ_THREAD_TRACE_WORD_WAVE__TOKEN_TYPE_MASK 0x0000000fL
+#define SQ_THREAD_TRACE_WORD_WAVE__TOKEN_TYPE__SHIFT 0x00000000
+#define SQ_THREAD_TRACE_WORD_WAVE__WAVE_ID_MASK 0x00003c00L
+#define SQ_THREAD_TRACE_WORD_WAVE__WAVE_ID__SHIFT 0x0000000a
+#define SQ_THREAD_TRACE_WPTR__READ_OFFSET_MASK 0xc0000000L
+#define SQ_THREAD_TRACE_WPTR__READ_OFFSET__SHIFT 0x0000001e
+#define SQ_THREAD_TRACE_WPTR__WPTR_MASK 0x3fffffffL
+#define SQ_THREAD_TRACE_WPTR__WPTR__SHIFT 0x00000000
+#define SQ_TIME_HI__TIME_MASK 0xffffffffL
+#define SQ_TIME_HI__TIME__SHIFT 0x00000000
+#define SQ_TIME_LO__TIME_MASK 0xffffffffL
+#define SQ_TIME_LO__TIME__SHIFT 0x00000000
+#define SQ_VINTRP__ATTRCHAN_MASK 0x00000300L
+#define SQ_VINTRP__ATTRCHAN__SHIFT 0x00000008
+#define SQ_VINTRP__ATTR_MASK 0x0000fc00L
+#define SQ_VINTRP__ATTR__SHIFT 0x0000000a
+#define SQ_VINTRP__ENCODING_MASK 0xfc000000L
+#define SQ_VINTRP__ENCODING__SHIFT 0x0000001a
+#define SQ_VINTRP__OP_MASK 0x00030000L
+#define SQ_VINTRP__OP__SHIFT 0x00000010
+#define SQ_VINTRP__VDST_MASK 0x03fc0000L
+#define SQ_VINTRP__VDST__SHIFT 0x00000012
+#define SQ_VINTRP__VSRC_MASK 0x000000ffL
+#define SQ_VINTRP__VSRC__SHIFT 0x00000000
+#define SQ_VOP1__ENCODING_MASK 0xfe000000L
+#define SQ_VOP1__ENCODING__SHIFT 0x00000019
+#define SQ_VOP1__OP_MASK 0x0001fe00L
+#define SQ_VOP1__OP__SHIFT 0x00000009
+#define SQ_VOP1__SRC0_MASK 0x000001ffL
+#define SQ_VOP1__SRC0__SHIFT 0x00000000
+#define SQ_VOP1__VDST_MASK 0x01fe0000L
+#define SQ_VOP1__VDST__SHIFT 0x00000011
+#define SQ_VOP2__ENCODING_MASK 0x80000000L
+#define SQ_VOP2__ENCODING__SHIFT 0x0000001f
+#define SQ_VOP2__OP_MASK 0x7e000000L
+#define SQ_VOP2__OP__SHIFT 0x00000019
+#define SQ_VOP2__SRC0_MASK 0x000001ffL
+#define SQ_VOP2__SRC0__SHIFT 0x00000000
+#define SQ_VOP2__VDST_MASK 0x01fe0000L
+#define SQ_VOP2__VDST__SHIFT 0x00000011
+#define SQ_VOP2__VSRC1_MASK 0x0001fe00L
+#define SQ_VOP2__VSRC1__SHIFT 0x00000009
+#define SQ_VOP3_0__ABS_MASK 0x00000700L
+#define SQ_VOP3_0__ABS__SHIFT 0x00000008
+#define SQ_VOP3_0__CLAMP_MASK 0x00000800L
+#define SQ_VOP3_0__CLAMP__SHIFT 0x0000000b
+#define SQ_VOP3_0__ENCODING_MASK 0xfc000000L
+#define SQ_VOP3_0__ENCODING__SHIFT 0x0000001a
+#define SQ_VOP3_0__OP_MASK 0x03fe0000L
+#define SQ_VOP3_0__OP__SHIFT 0x00000011
+#define SQ_VOP3_0_SDST_ENC__ENCODING_MASK 0xfc000000L
+#define SQ_VOP3_0_SDST_ENC__ENCODING__SHIFT 0x0000001a
+#define SQ_VOP3_0_SDST_ENC__OP_MASK 0x03fe0000L
+#define SQ_VOP3_0_SDST_ENC__OP__SHIFT 0x00000011
+#define SQ_VOP3_0_SDST_ENC__SDST_MASK 0x00007f00L
+#define SQ_VOP3_0_SDST_ENC__SDST__SHIFT 0x00000008
+#define SQ_VOP3_0_SDST_ENC__VDST_MASK 0x000000ffL
+#define SQ_VOP3_0_SDST_ENC__VDST__SHIFT 0x00000000
+#define SQ_VOP3_0__VDST_MASK 0x000000ffL
+#define SQ_VOP3_0__VDST__SHIFT 0x00000000
+#define SQ_VOP3_1__NEG_MASK 0xe0000000L
+#define SQ_VOP3_1__NEG__SHIFT 0x0000001d
+#define SQ_VOP3_1__OMOD_MASK 0x18000000L
+#define SQ_VOP3_1__OMOD__SHIFT 0x0000001b
+#define SQ_VOP3_1__SRC0_MASK 0x000001ffL
+#define SQ_VOP3_1__SRC0__SHIFT 0x00000000
+#define SQ_VOP3_1__SRC1_MASK 0x0003fe00L
+#define SQ_VOP3_1__SRC1__SHIFT 0x00000009
+#define SQ_VOP3_1__SRC2_MASK 0x07fc0000L
+#define SQ_VOP3_1__SRC2__SHIFT 0x00000012
+#define SQ_VOPC__ENCODING_MASK 0xfe000000L
+#define SQ_VOPC__ENCODING__SHIFT 0x00000019
+#define SQ_VOPC__OP_MASK 0x01fe0000L
+#define SQ_VOPC__OP__SHIFT 0x00000011
+#define SQ_VOPC__SRC0_MASK 0x000001ffL
+#define SQ_VOPC__SRC0__SHIFT 0x00000000
+#define SQ_VOPC__VSRC1_MASK 0x0001fe00L
+#define SQ_VOPC__VSRC1__SHIFT 0x00000009
+#define SQ_WAVE_EXEC_HI__EXEC_HI_MASK 0xffffffffL
+#define SQ_WAVE_EXEC_HI__EXEC_HI__SHIFT 0x00000000
+#define SQ_WAVE_EXEC_LO__EXEC_LO_MASK 0xffffffffL
+#define SQ_WAVE_EXEC_LO__EXEC_LO__SHIFT 0x00000000
+#define SQ_WAVE_GPR_ALLOC__SGPR_BASE_MASK 0x003f0000L
+#define SQ_WAVE_GPR_ALLOC__SGPR_BASE__SHIFT 0x00000010
+#define SQ_WAVE_GPR_ALLOC__SGPR_SIZE_MASK 0x0f000000L
+#define SQ_WAVE_GPR_ALLOC__SGPR_SIZE__SHIFT 0x00000018
+#define SQ_WAVE_GPR_ALLOC__VGPR_BASE_MASK 0x0000003fL
+#define SQ_WAVE_GPR_ALLOC__VGPR_BASE__SHIFT 0x00000000
+#define SQ_WAVE_GPR_ALLOC__VGPR_SIZE_MASK 0x00003f00L
+#define SQ_WAVE_GPR_ALLOC__VGPR_SIZE__SHIFT 0x00000008
+#define SQ_WAVE_HW_ID__CU_ID_MASK 0x00000f00L
+#define SQ_WAVE_HW_ID__CU_ID__SHIFT 0x00000008
+#define SQ_WAVE_HW_ID__ME_ID_MASK 0xc0000000L
+#define SQ_WAVE_HW_ID__ME_ID__SHIFT 0x0000001e
+#define SQ_WAVE_HW_ID__PIPE_ID_MASK 0x000000c0L
+#define SQ_WAVE_HW_ID__PIPE_ID__SHIFT 0x00000006
+#define SQ_WAVE_HW_ID__QUEUE_ID_MASK 0x07000000L
+#define SQ_WAVE_HW_ID__QUEUE_ID__SHIFT 0x00000018
+#define SQ_WAVE_HW_ID__SE_ID_MASK 0x00002000L
+#define SQ_WAVE_HW_ID__SE_ID__SHIFT 0x0000000d
+#define SQ_WAVE_HW_ID__SH_ID_MASK 0x00001000L
+#define SQ_WAVE_HW_ID__SH_ID__SHIFT 0x0000000c
+#define SQ_WAVE_HW_ID__SIMD_ID_MASK 0x00000030L
+#define SQ_WAVE_HW_ID__SIMD_ID__SHIFT 0x00000004
+#define SQ_WAVE_HW_ID__STATE_ID_MASK 0x38000000L
+#define SQ_WAVE_HW_ID__STATE_ID__SHIFT 0x0000001b
+#define SQ_WAVE_HW_ID__TG_ID_MASK 0x000f0000L
+#define SQ_WAVE_HW_ID__TG_ID__SHIFT 0x00000010
+#define SQ_WAVE_HW_ID__VM_ID_MASK 0x00f00000L
+#define SQ_WAVE_HW_ID__VM_ID__SHIFT 0x00000014
+#define SQ_WAVE_HW_ID__WAVE_ID_MASK 0x0000000fL
+#define SQ_WAVE_HW_ID__WAVE_ID__SHIFT 0x00000000
+#define SQ_WAVE_IB_DBG0__ECC_ST_MASK 0x00c00000L
+#define SQ_WAVE_IB_DBG0__ECC_ST__SHIFT 0x00000016
+#define SQ_WAVE_IB_DBG0__HYB_CNT_MASK 0x06000000L
+#define SQ_WAVE_IB_DBG0__HYB_CNT__SHIFT 0x00000019
+#define SQ_WAVE_IB_DBG0__IBUF_RPTR_MASK 0x00000300L
+#define SQ_WAVE_IB_DBG0__IBUF_RPTR__SHIFT 0x00000008
+#define SQ_WAVE_IB_DBG0__IBUF_ST_MASK 0x00000007L
+#define SQ_WAVE_IB_DBG0__IBUF_ST__SHIFT 0x00000000
+#define SQ_WAVE_IB_DBG0__IBUF_WPTR_MASK 0x00000c00L
+#define SQ_WAVE_IB_DBG0__IBUF_WPTR__SHIFT 0x0000000a
+#define SQ_WAVE_IB_DBG0__INST_STR_ST_MASK 0x00070000L
+#define SQ_WAVE_IB_DBG0__INST_STR_ST__SHIFT 0x00000010
+#define SQ_WAVE_IB_DBG0__IS_HYB_MASK 0x01000000L
+#define SQ_WAVE_IB_DBG0__IS_HYB__SHIFT 0x00000018
+#define SQ_WAVE_IB_DBG0__KILL_MASK 0x08000000L
+#define SQ_WAVE_IB_DBG0__KILL__SHIFT 0x0000001b
+#define SQ_WAVE_IB_DBG0__MISC_CNT_MASK 0x00380000L
+#define SQ_WAVE_IB_DBG0__MISC_CNT__SHIFT 0x00000013
+#define SQ_WAVE_IB_DBG0__NEED_KILL_IFETCH_MASK 0x10000000L
+#define SQ_WAVE_IB_DBG0__NEED_KILL_IFETCH__SHIFT 0x0000001c
+#define SQ_WAVE_IB_DBG0__NEED_NEXT_DW_MASK 0x00000010L
+#define SQ_WAVE_IB_DBG0__NEED_NEXT_DW__SHIFT 0x00000004
+#define SQ_WAVE_IB_DBG0__NO_PREFETCH_CNT_MASK 0x000000e0L
+#define SQ_WAVE_IB_DBG0__NO_PREFETCH_CNT__SHIFT 0x00000005
+#define SQ_WAVE_IB_DBG0__PC_INVALID_MASK 0x00000008L
+#define SQ_WAVE_IB_DBG0__PC_INVALID__SHIFT 0x00000003
+#define SQ_WAVE_IB_STS__EXP_CNT_MASK 0x00000070L
+#define SQ_WAVE_IB_STS__EXP_CNT__SHIFT 0x00000004
+#define SQ_WAVE_IB_STS__LGKM_CNT_MASK 0x00001f00L
+#define SQ_WAVE_IB_STS__LGKM_CNT__SHIFT 0x00000008
+#define SQ_WAVE_IB_STS__VALU_CNT_MASK 0x0000e000L
+#define SQ_WAVE_IB_STS__VALU_CNT__SHIFT 0x0000000d
+#define SQ_WAVE_IB_STS__VM_CNT_MASK 0x0000000fL
+#define SQ_WAVE_IB_STS__VM_CNT__SHIFT 0x00000000
+#define SQ_WAVE_INST_DW0__INST_DW0_MASK 0xffffffffL
+#define SQ_WAVE_INST_DW0__INST_DW0__SHIFT 0x00000000
+#define SQ_WAVE_INST_DW1__INST_DW1_MASK 0xffffffffL
+#define SQ_WAVE_INST_DW1__INST_DW1__SHIFT 0x00000000
+#define SQ_WAVE_LDS_ALLOC__LDS_BASE_MASK 0x000000ffL
+#define SQ_WAVE_LDS_ALLOC__LDS_BASE__SHIFT 0x00000000
+#define SQ_WAVE_LDS_ALLOC__LDS_SIZE_MASK 0x001ff000L
+#define SQ_WAVE_LDS_ALLOC__LDS_SIZE__SHIFT 0x0000000c
+#define SQ_WAVE_M0__M0_MASK 0xffffffffL
+#define SQ_WAVE_M0__M0__SHIFT 0x00000000
+#define SQ_WAVE_MODE__CSP_MASK 0xe0000000L
+#define SQ_WAVE_MODE__CSP__SHIFT 0x0000001d
+#define SQ_WAVE_MODE__DEBUG_EN_MASK 0x00000800L
+#define SQ_WAVE_MODE__DEBUG_EN__SHIFT 0x0000000b
+#define SQ_WAVE_MODE__DX10_CLAMP_MASK 0x00000100L
+#define SQ_WAVE_MODE__DX10_CLAMP__SHIFT 0x00000008
+#define SQ_WAVE_MODE__EXCP_EN_MASK 0x0007f000L
+#define SQ_WAVE_MODE__EXCP_EN__SHIFT 0x0000000c
+#define SQ_WAVE_MODE__FP_DENORM_MASK 0x000000f0L
+#define SQ_WAVE_MODE__FP_DENORM__SHIFT 0x00000004
+#define SQ_WAVE_MODE__FP_ROUND_MASK 0x0000000fL
+#define SQ_WAVE_MODE__FP_ROUND__SHIFT 0x00000000
+#define SQ_WAVE_MODE__IEEE_MASK 0x00000200L
+#define SQ_WAVE_MODE__IEEE__SHIFT 0x00000009
+#define SQ_WAVE_MODE__LOD_CLAMPED_MASK 0x00000400L
+#define SQ_WAVE_MODE__LOD_CLAMPED__SHIFT 0x0000000a
+#define SQ_WAVE_MODE__VSKIP_MASK 0x10000000L
+#define SQ_WAVE_MODE__VSKIP__SHIFT 0x0000001c
+#define SQ_WAVE_PC_HI__PC_HI_MASK 0x000000ffL
+#define SQ_WAVE_PC_HI__PC_HI__SHIFT 0x00000000
+#define SQ_WAVE_PC_LO__PC_LO_MASK 0xffffffffL
+#define SQ_WAVE_PC_LO__PC_LO__SHIFT 0x00000000
+#define SQ_WAVE_STATUS__COND_DBG_SYS_MASK 0x00200000L
+#define SQ_WAVE_STATUS__COND_DBG_SYS__SHIFT 0x00000015
+#define SQ_WAVE_STATUS__COND_DBG_USER_MASK 0x00100000L
+#define SQ_WAVE_STATUS__COND_DBG_USER__SHIFT 0x00000014
+#define SQ_WAVE_STATUS__DATA_ATC_MASK 0x00400000L
+#define SQ_WAVE_STATUS__DATA_ATC__SHIFT 0x00000016
+#define SQ_WAVE_STATUS__DISPATCH_CACHE_CTRL_MASK 0x07000000L
+#define SQ_WAVE_STATUS__DISPATCH_CACHE_CTRL__SHIFT 0x00000018
+#define SQ_WAVE_STATUS__ECC_ERR_MASK 0x00020000L
+#define SQ_WAVE_STATUS__ECC_ERR__SHIFT 0x00000011
+#define SQ_WAVE_STATUS__EXECZ_MASK 0x00000200L
+#define SQ_WAVE_STATUS__EXECZ__SHIFT 0x00000009
+#define SQ_WAVE_STATUS__EXPORT_RDY_MASK 0x00000100L
+#define SQ_WAVE_STATUS__EXPORT_RDY__SHIFT 0x00000008
+#define SQ_WAVE_STATUS__HALT_MASK 0x00002000L
+#define SQ_WAVE_STATUS__HALT__SHIFT 0x0000000d
+#define SQ_WAVE_STATUS__IN_BARRIER_MASK 0x00001000L
+#define SQ_WAVE_STATUS__IN_BARRIER__SHIFT 0x0000000c
+#define SQ_WAVE_STATUS__INST_ATC_MASK 0x00800000L
+#define SQ_WAVE_STATUS__INST_ATC__SHIFT 0x00000017
+#define SQ_WAVE_STATUS__IN_TG_MASK 0x00000800L
+#define SQ_WAVE_STATUS__IN_TG__SHIFT 0x0000000b
+#define SQ_WAVE_STATUS__MUST_EXPORT_MASK 0x08000000L
+#define SQ_WAVE_STATUS__MUST_EXPORT__SHIFT 0x0000001b
+#define SQ_WAVE_STATUS__PERF_EN_MASK 0x00080000L
+#define SQ_WAVE_STATUS__PERF_EN__SHIFT 0x00000013
+#define SQ_WAVE_STATUS__PRIV_MASK 0x00000020L
+#define SQ_WAVE_STATUS__PRIV__SHIFT 0x00000005
+#define SQ_WAVE_STATUS__SCC_MASK 0x00000001L
+#define SQ_WAVE_STATUS__SCC__SHIFT 0x00000000
+#define SQ_WAVE_STATUS__SKIP_EXPORT_MASK 0x00040000L
+#define SQ_WAVE_STATUS__SKIP_EXPORT__SHIFT 0x00000012
+#define SQ_WAVE_STATUS__SPI_PRIO_MASK 0x00000006L
+#define SQ_WAVE_STATUS__SPI_PRIO__SHIFT 0x00000001
+#define SQ_WAVE_STATUS__TRAP_EN_MASK 0x00000040L
+#define SQ_WAVE_STATUS__TRAP_EN__SHIFT 0x00000006
+#define SQ_WAVE_STATUS__TRAP_MASK 0x00004000L
+#define SQ_WAVE_STATUS__TRAP__SHIFT 0x0000000e
+#define SQ_WAVE_STATUS__TTRACE_CU_EN_MASK 0x00008000L
+#define SQ_WAVE_STATUS__TTRACE_CU_EN__SHIFT 0x0000000f
+#define SQ_WAVE_STATUS__TTRACE_EN_MASK 0x00000080L
+#define SQ_WAVE_STATUS__TTRACE_EN__SHIFT 0x00000007
+#define SQ_WAVE_STATUS__VALID_MASK 0x00010000L
+#define SQ_WAVE_STATUS__VALID__SHIFT 0x00000010
+#define SQ_WAVE_STATUS__VCCZ_MASK 0x00000400L
+#define SQ_WAVE_STATUS__VCCZ__SHIFT 0x0000000a
+#define SQ_WAVE_STATUS__WAVE_PRIO_MASK 0x00000018L
+#define SQ_WAVE_STATUS__WAVE_PRIO__SHIFT 0x00000003
+#define SQ_WAVE_TBA_HI__ADDR_HI_MASK 0x000000ffL
+#define SQ_WAVE_TBA_HI__ADDR_HI__SHIFT 0x00000000
+#define SQ_WAVE_TBA_LO__ADDR_LO_MASK 0xffffffffL
+#define SQ_WAVE_TBA_LO__ADDR_LO__SHIFT 0x00000000
+#define SQ_WAVE_TMA_HI__ADDR_HI_MASK 0x000000ffL
+#define SQ_WAVE_TMA_HI__ADDR_HI__SHIFT 0x00000000
+#define SQ_WAVE_TMA_LO__ADDR_LO_MASK 0xffffffffL
+#define SQ_WAVE_TMA_LO__ADDR_LO__SHIFT 0x00000000
+#define SQ_WAVE_TRAPSTS__DP_RATE_MASK 0xe0000000L
+#define SQ_WAVE_TRAPSTS__DP_RATE__SHIFT 0x0000001d
+#define SQ_WAVE_TRAPSTS__EXCP_CYCLE_MASK 0x003f0000L
+#define SQ_WAVE_TRAPSTS__EXCP_CYCLE__SHIFT 0x00000010
+#define SQ_WAVE_TRAPSTS__EXCP_MASK 0x0000007fL
+#define SQ_WAVE_TRAPSTS__EXCP__SHIFT 0x00000000
+#define SQ_WAVE_TTMP0__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP0__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP10__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP10__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP11__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP11__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP1__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP1__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP2__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP2__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP3__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP3__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP4__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP4__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP5__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP5__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP6__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP6__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP7__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP7__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP8__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP8__DATA__SHIFT 0x00000000
+#define SQ_WAVE_TTMP9__DATA_MASK 0xffffffffL
+#define SQ_WAVE_TTMP9__DATA__SHIFT 0x00000000
+#define SX_DEBUG_1__DEBUG_DATA_MASK 0xffffff80L
+#define SX_DEBUG_1__DEBUG_DATA__SHIFT 0x00000007
+#define SX_DEBUG_1__SX_DB_QUAD_CREDIT_MASK 0x0000007fL
+#define SX_DEBUG_1__SX_DB_QUAD_CREDIT__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL1_BUSY_MASK 0x80000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL1_BUSY__SHIFT 0x0000001f
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL2_BUSY_MASK 0x40000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL2_BUSY__SHIFT 0x0000001e
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL3_BUSY_MASK 0x20000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK2_VAL3_BUSY__SHIFT 0x0000001d
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL0_BUSY_MASK 0x10000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL0_BUSY__SHIFT 0x0000001c
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL1_BUSY_MASK 0x08000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL1_BUSY__SHIFT 0x0000001b
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL2_BUSY_MASK 0x04000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL2_BUSY__SHIFT 0x0000001a
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL3_BUSY_MASK 0x02000000L
+#define SX_DEBUG_BUSY_2__COL_BUFF3_BANK3_VAL3_BUSY__SHIFT 0x00000019
+#define SX_DEBUG_BUSY_2__COL_DBIF0_FIFO_BUSY_MASK 0x00800000L
+#define SX_DEBUG_BUSY_2__COL_DBIF0_FIFO_BUSY__SHIFT 0x00000017
+#define SX_DEBUG_BUSY_2__COL_DBIF0_READ_VALID_MASK 0x01000000L
+#define SX_DEBUG_BUSY_2__COL_DBIF0_READ_VALID__SHIFT 0x00000018
+#define SX_DEBUG_BUSY_2__COL_DBIF0_SENDFREE_BUSY_MASK 0x00400000L
+#define SX_DEBUG_BUSY_2__COL_DBIF0_SENDFREE_BUSY__SHIFT 0x00000016
+#define SX_DEBUG_BUSY_2__COL_DBIF1_FIFO_BUSY_MASK 0x00100000L
+#define SX_DEBUG_BUSY_2__COL_DBIF1_FIFO_BUSY__SHIFT 0x00000014
+#define SX_DEBUG_BUSY_2__COL_DBIF1_READ_VALID_MASK 0x00200000L
+#define SX_DEBUG_BUSY_2__COL_DBIF1_READ_VALID__SHIFT 0x00000015
+#define SX_DEBUG_BUSY_2__COL_DBIF1_SENDFREE_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY_2__COL_DBIF1_SENDFREE_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY_2__COL_DBIF2_FIFO_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY_2__COL_DBIF2_FIFO_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY_2__COL_DBIF2_READ_VALID_MASK 0x00040000L
+#define SX_DEBUG_BUSY_2__COL_DBIF2_READ_VALID__SHIFT 0x00000012
+#define SX_DEBUG_BUSY_2__COL_DBIF2_SENDFREE_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY_2__COL_DBIF2_SENDFREE_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY_2__COL_DBIF3_FIFO_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY_2__COL_DBIF3_FIFO_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY_2__COL_DBIF3_READ_VALID_MASK 0x00008000L
+#define SX_DEBUG_BUSY_2__COL_DBIF3_READ_VALID__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY_2__COL_DBIF3_SENDFREE_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY_2__COL_DBIF3_SENDFREE_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY_2__COL_REQ0_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY_2__COL_REQ0_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY_2__COL_REQ0_FREECNT_NE0_MASK 0x00000400L
+#define SX_DEBUG_BUSY_2__COL_REQ0_FREECNT_NE0__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY_2__COL_REQ0_IDLE_MASK 0x00000800L
+#define SX_DEBUG_BUSY_2__COL_REQ0_IDLE__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY_2__COL_REQ1_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY_2__COL_REQ1_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY_2__COL_REQ1_FREECNT_NE0_MASK 0x00000080L
+#define SX_DEBUG_BUSY_2__COL_REQ1_FREECNT_NE0__SHIFT 0x00000007
+#define SX_DEBUG_BUSY_2__COL_REQ1_IDLE_MASK 0x00000100L
+#define SX_DEBUG_BUSY_2__COL_REQ1_IDLE__SHIFT 0x00000008
+#define SX_DEBUG_BUSY_2__COL_REQ2_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY_2__COL_REQ2_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY_2__COL_REQ2_FREECNT_NE0_MASK 0x00000010L
+#define SX_DEBUG_BUSY_2__COL_REQ2_FREECNT_NE0__SHIFT 0x00000004
+#define SX_DEBUG_BUSY_2__COL_REQ2_IDLE_MASK 0x00000020L
+#define SX_DEBUG_BUSY_2__COL_REQ2_IDLE__SHIFT 0x00000005
+#define SX_DEBUG_BUSY_2__COL_REQ3_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY_2__COL_REQ3_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY_2__COL_REQ3_FREECNT_NE0_MASK 0x00000002L
+#define SX_DEBUG_BUSY_2__COL_REQ3_FREECNT_NE0__SHIFT 0x00000001
+#define SX_DEBUG_BUSY_2__COL_REQ3_IDLE_MASK 0x00000004L
+#define SX_DEBUG_BUSY_2__COL_REQ3_IDLE__SHIFT 0x00000002
+#define SX_DEBUG_BUSY_2__COL_SCBD_BUSY_MASK 0x00000001L
+#define SX_DEBUG_BUSY_2__COL_SCBD_BUSY__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL1_BUSY_MASK 0x80000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL1_BUSY__SHIFT 0x0000001f
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL2_BUSY_MASK 0x40000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL2_BUSY__SHIFT 0x0000001e
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL3_BUSY_MASK 0x20000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK2_VAL3_BUSY__SHIFT 0x0000001d
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL0_BUSY_MASK 0x10000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL0_BUSY__SHIFT 0x0000001c
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL1_BUSY_MASK 0x08000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL1_BUSY__SHIFT 0x0000001b
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL2_BUSY_MASK 0x04000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL2_BUSY__SHIFT 0x0000001a
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL3_BUSY_MASK 0x02000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF1_BANK3_VAL3_BUSY__SHIFT 0x00000019
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL0_BUSY_MASK 0x01000000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL0_BUSY__SHIFT 0x00000018
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL1_BUSY_MASK 0x00800000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL1_BUSY__SHIFT 0x00000017
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL2_BUSY_MASK 0x00400000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL2_BUSY__SHIFT 0x00000016
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL3_BUSY_MASK 0x00200000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK0_VAL3_BUSY__SHIFT 0x00000015
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL0_BUSY_MASK 0x00100000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL0_BUSY__SHIFT 0x00000014
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL1_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL1_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL2_BUSY_MASK 0x00040000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL2_BUSY__SHIFT 0x00000012
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL3_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK1_VAL3_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL0_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL0_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL1_BUSY_MASK 0x00008000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL1_BUSY__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL2_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL2_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL3_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK2_VAL3_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL0_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL0_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL1_BUSY_MASK 0x00000800L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL1_BUSY__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL2_BUSY_MASK 0x00000400L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL2_BUSY__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL3_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY_3__COL_BUFF2_BANK3_VAL3_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL0_BUSY_MASK 0x00000100L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL0_BUSY__SHIFT 0x00000008
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL1_BUSY_MASK 0x00000080L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL1_BUSY__SHIFT 0x00000007
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL2_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL2_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL3_BUSY_MASK 0x00000020L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK0_VAL3_BUSY__SHIFT 0x00000005
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL0_BUSY_MASK 0x00000010L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL0_BUSY__SHIFT 0x00000004
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL1_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL1_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL2_BUSY_MASK 0x00000004L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL2_BUSY__SHIFT 0x00000002
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL3_BUSY_MASK 0x00000002L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK1_VAL3_BUSY__SHIFT 0x00000001
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK2_VAL0_BUSY_MASK 0x00000001L
+#define SX_DEBUG_BUSY_3__COL_BUFF3_BANK2_VAL0_BUSY__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL0_BUSY_MASK 0x01000000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL0_BUSY__SHIFT 0x00000018
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL1_BUSY_MASK 0x00800000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL1_BUSY__SHIFT 0x00000017
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL2_BUSY_MASK 0x00400000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL2_BUSY__SHIFT 0x00000016
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL3_BUSY_MASK 0x00200000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK0_VAL3_BUSY__SHIFT 0x00000015
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL0_BUSY_MASK 0x00100000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL0_BUSY__SHIFT 0x00000014
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL1_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL1_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL2_BUSY_MASK 0x00040000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL2_BUSY__SHIFT 0x00000012
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL3_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK1_VAL3_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL0_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL0_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL1_BUSY_MASK 0x00008000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL1_BUSY__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL2_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL2_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL3_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK2_VAL3_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL0_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL0_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL1_BUSY_MASK 0x00000800L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL1_BUSY__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL2_BUSY_MASK 0x00000400L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL2_BUSY__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL3_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY_4__COL_BUFF0_BANK3_VAL3_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL0_BUSY_MASK 0x00000100L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL0_BUSY__SHIFT 0x00000008
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL1_BUSY_MASK 0x00000080L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL1_BUSY__SHIFT 0x00000007
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL2_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL2_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL3_BUSY_MASK 0x00000020L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK0_VAL3_BUSY__SHIFT 0x00000005
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL0_BUSY_MASK 0x00000010L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL0_BUSY__SHIFT 0x00000004
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL1_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL1_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL2_BUSY_MASK 0x00000004L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL2_BUSY__SHIFT 0x00000002
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL3_BUSY_MASK 0x00000002L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK1_VAL3_BUSY__SHIFT 0x00000001
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK2_VAL0_BUSY_MASK 0x00000001L
+#define SX_DEBUG_BUSY_4__COL_BUFF1_BANK2_VAL0_BUSY__SHIFT 0x00000000
+#define SX_DEBUG_BUSY_4__RESERVED_MASK 0xfe000000L
+#define SX_DEBUG_BUSY_4__RESERVED__SHIFT 0x00000019
+#define SX_DEBUG_BUSY__ADDR_BUSYORVAL_MASK 0x80000000L
+#define SX_DEBUG_BUSY__ADDR_BUSYORVAL__SHIFT 0x0000001f
+#define SX_DEBUG_BUSY__CMD_BUSYORVAL_MASK 0x40000000L
+#define SX_DEBUG_BUSY__CMD_BUSYORVAL__SHIFT 0x0000001e
+#define SX_DEBUG_BUSY__PA_SX_BUSY_MASK 0x00000004L
+#define SX_DEBUG_BUSY__PA_SX_BUSY__SHIFT 0x00000002
+#define SX_DEBUG_BUSY__PCCMD_VALID_MASK 0x08000000L
+#define SX_DEBUG_BUSY__PCCMD_VALID__SHIFT 0x0000001b
+#define SX_DEBUG_BUSY__POS_BANK0VAL0_BUSY_MASK 0x00080000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL0_BUSY__SHIFT 0x00000013
+#define SX_DEBUG_BUSY__POS_BANK0VAL1_BUSY_MASK 0x00040000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL1_BUSY__SHIFT 0x00000012
+#define SX_DEBUG_BUSY__POS_BANK0VAL2_BUSY_MASK 0x00020000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL2_BUSY__SHIFT 0x00000011
+#define SX_DEBUG_BUSY__POS_BANK0VAL3_BUSY_MASK 0x00010000L
+#define SX_DEBUG_BUSY__POS_BANK0VAL3_BUSY__SHIFT 0x00000010
+#define SX_DEBUG_BUSY__POS_BANK1VAL0_BUSY_MASK 0x00008000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL0_BUSY__SHIFT 0x0000000f
+#define SX_DEBUG_BUSY__POS_BANK1VAL1_BUSY_MASK 0x00004000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL1_BUSY__SHIFT 0x0000000e
+#define SX_DEBUG_BUSY__POS_BANK1VAL2_BUSY_MASK 0x00002000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL2_BUSY__SHIFT 0x0000000d
+#define SX_DEBUG_BUSY__POS_BANK1VAL3_BUSY_MASK 0x00001000L
+#define SX_DEBUG_BUSY__POS_BANK1VAL3_BUSY__SHIFT 0x0000000c
+#define SX_DEBUG_BUSY__POS_BANK2VAL0_BUSY_MASK 0x00000800L
+#define SX_DEBUG_BUSY__POS_BANK2VAL0_BUSY__SHIFT 0x0000000b
+#define SX_DEBUG_BUSY__POS_BANK2VAL1_BUSY_MASK 0x00000400L
+#define SX_DEBUG_BUSY__POS_BANK2VAL1_BUSY__SHIFT 0x0000000a
+#define SX_DEBUG_BUSY__POS_BANK2VAL2_BUSY_MASK 0x00000200L
+#define SX_DEBUG_BUSY__POS_BANK2VAL2_BUSY__SHIFT 0x00000009
+#define SX_DEBUG_BUSY__POS_BANK2VAL3_BUSY_MASK 0x00000100L
+#define SX_DEBUG_BUSY__POS_BANK2VAL3_BUSY__SHIFT 0x00000008
+#define SX_DEBUG_BUSY__POS_BANK3VAL0_BUSY_MASK 0x00000080L
+#define SX_DEBUG_BUSY__POS_BANK3VAL0_BUSY__SHIFT 0x00000007
+#define SX_DEBUG_BUSY__POS_BANK3VAL1_BUSY_MASK 0x00000040L
+#define SX_DEBUG_BUSY__POS_BANK3VAL1_BUSY__SHIFT 0x00000006
+#define SX_DEBUG_BUSY__POS_BANK3VAL2_BUSY_MASK 0x00000020L
+#define SX_DEBUG_BUSY__POS_BANK3VAL2_BUSY__SHIFT 0x00000005
+#define SX_DEBUG_BUSY__POS_BANK3VAL3_BUSY_MASK 0x00000010L
+#define SX_DEBUG_BUSY__POS_BANK3VAL3_BUSY__SHIFT 0x00000004
+#define SX_DEBUG_BUSY__POS_FREE_OR_VALIDS_MASK 0x00000001L
+#define SX_DEBUG_BUSY__POS_FREE_OR_VALIDS__SHIFT 0x00000000
+#define SX_DEBUG_BUSY__POS_INMUX_VALID_MASK 0x00100000L
+#define SX_DEBUG_BUSY__POS_INMUX_VALID__SHIFT 0x00000014
+#define SX_DEBUG_BUSY__POS_REQUESTER_BUSY_MASK 0x00000002L
+#define SX_DEBUG_BUSY__POS_REQUESTER_BUSY__SHIFT 0x00000001
+#define SX_DEBUG_BUSY__POS_SCBD_BUSY_MASK 0x00000008L
+#define SX_DEBUG_BUSY__POS_SCBD_BUSY__SHIFT 0x00000003
+#define SX_DEBUG_BUSY__VDATA0_VALID_MASK 0x20000000L
+#define SX_DEBUG_BUSY__VDATA0_VALID__SHIFT 0x0000001d
+#define SX_DEBUG_BUSY__VDATA1_VALID_MASK 0x10000000L
+#define SX_DEBUG_BUSY__VDATA1_VALID__SHIFT 0x0000001c
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ1_MASK 0x04000000L
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ1__SHIFT 0x0000001a
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ2_MASK 0x02000000L
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ2__SHIFT 0x00000019
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ3_MASK 0x01000000L
+#define SX_DEBUG_BUSY__WRCTRL0_VALIDQ3__SHIFT 0x00000018
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ1_MASK 0x00800000L
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ1__SHIFT 0x00000017
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ2_MASK 0x00400000L
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ2__SHIFT 0x00000016
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ3_MASK 0x00200000L
+#define SX_DEBUG_BUSY__WRCTRL1_VALIDQ3__SHIFT 0x00000015
+#define SXIFCCG_DEBUG_REG0__point_address_MASK 0x000001c0L
+#define SXIFCCG_DEBUG_REG0__point_address__SHIFT 0x00000006
+#define SXIFCCG_DEBUG_REG0__position_address_MASK 0x0000003fL
+#define SXIFCCG_DEBUG_REG0__position_address__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_advance_MASK 0x80000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_advance__SHIFT 0x0000001f
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_inc_MASK 0x40000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_inc__SHIFT 0x0000001e
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_sel_MASK 0x0c000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_aux_sel__SHIFT 0x0000001a
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_pci_MASK 0x03ff0000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_pci__SHIFT 0x00000010
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_req_mask_MASK 0x0000f000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_req_mask__SHIFT 0x0000000c
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_sp_id_MASK 0x30000000L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_sp_id__SHIFT 0x0000001c
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_state_var_indx_MASK 0x00000e00L
+#define SXIFCCG_DEBUG_REG0__sx_pending_rd_state_var_indx__SHIFT 0x00000009
+#define SXIFCCG_DEBUG_REG1__aux_sel_MASK 0x00300000L
+#define SXIFCCG_DEBUG_REG1__aux_sel__SHIFT 0x00000014
+#define SXIFCCG_DEBUG_REG1__available_positions_MASK 0x0000007fL
+#define SXIFCCG_DEBUG_REG1__available_positions__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_0_MASK 0xf0000000L
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_0__SHIFT 0x0000001c
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_1_MASK 0x0f000000L
+#define SXIFCCG_DEBUG_REG1__pasx_req_cnt_1__SHIFT 0x00000018
+#define SXIFCCG_DEBUG_REG1__statevar_bits_disable_sp_MASK 0x000f0000L
+#define SXIFCCG_DEBUG_REG1__statevar_bits_disable_sp__SHIFT 0x00000010
+#define SXIFCCG_DEBUG_REG1__statevar_bits_vs_out_misc_vec_ena_MASK 0x00008000L
+#define SXIFCCG_DEBUG_REG1__statevar_bits_vs_out_misc_vec_ena__SHIFT 0x0000000f
+#define SXIFCCG_DEBUG_REG1__sx_pending_fifo_contents_MASK 0x00007c00L
+#define SXIFCCG_DEBUG_REG1__sx_pending_fifo_contents__SHIFT 0x0000000a
+#define SXIFCCG_DEBUG_REG1__sx_receive_indx_MASK 0x00000380L
+#define SXIFCCG_DEBUG_REG1__sx_receive_indx__SHIFT 0x00000007
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_0_MASK 0x00800000L
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_0__SHIFT 0x00000017
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_1_MASK 0x00400000L
+#define SXIFCCG_DEBUG_REG1__sx_to_pa_empty_1__SHIFT 0x00000016
+#define SXIFCCG_DEBUG_REG2__param_cache_base_MASK 0x0000007fL
+#define SXIFCCG_DEBUG_REG2__param_cache_base__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG2__req_active_verts_loaded_MASK 0x00008000L
+#define SXIFCCG_DEBUG_REG2__req_active_verts_loaded__SHIFT 0x0000000f
+#define SXIFCCG_DEBUG_REG2__req_active_verts_MASK 0x007f0000L
+#define SXIFCCG_DEBUG_REG2__req_active_verts__SHIFT 0x00000010
+#define SXIFCCG_DEBUG_REG2__sx_aux_MASK 0x00000180L
+#define SXIFCCG_DEBUG_REG2__sx_aux__SHIFT 0x00000007
+#define SXIFCCG_DEBUG_REG2__sx_request_indx_MASK 0x00007e00L
+#define SXIFCCG_DEBUG_REG2__sx_request_indx__SHIFT 0x00000009
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_active_verts_MASK 0xfc000000L
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_active_verts__SHIFT 0x0000001a
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_state_var_indx_MASK 0x03800000L
+#define SXIFCCG_DEBUG_REG2__vgt_to_ccgen_state_var_indx__SHIFT 0x00000017
+#define SXIFCCG_DEBUG_REG3__ALWAYS_ZERO_MASK 0x000000ffL
+#define SXIFCCG_DEBUG_REG3__ALWAYS_ZERO__SHIFT 0x00000000
+#define SXIFCCG_DEBUG_REG3__available_positions_MASK 0x001fc000L
+#define SXIFCCG_DEBUG_REG3__available_positions__SHIFT 0x0000000e
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_fifo_full_MASK 0x20000000L
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_fifo_full__SHIFT 0x0000001d
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_write_MASK 0x80000000L
+#define SXIFCCG_DEBUG_REG3__ccgen_to_clipcc_write__SHIFT 0x0000001f
+#define SXIFCCG_DEBUG_REG3__current_state_MASK 0x00600000L
+#define SXIFCCG_DEBUG_REG3__current_state__SHIFT 0x00000015
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist0_vec_ena_MASK 0x00002000L
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist0_vec_ena__SHIFT 0x0000000d
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist1_vec_ena_MASK 0x00001000L
+#define SXIFCCG_DEBUG_REG3__statevar_bits_vs_out_ccdist1_vec_ena__SHIFT 0x0000000c
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_empty_MASK 0x02000000L
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_empty__SHIFT 0x00000019
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_full_MASK 0x04000000L
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_full__SHIFT 0x0000001a
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_write_MASK 0x40000000L
+#define SXIFCCG_DEBUG_REG3__sx0_receive_fifo_write__SHIFT 0x0000001e
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_empty_MASK 0x00800000L
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_empty__SHIFT 0x00000017
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_entriesavailable_MASK 0x00000f00L
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_entriesavailable__SHIFT 0x00000008
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_full_MASK 0x01000000L
+#define SXIFCCG_DEBUG_REG3__vertex_fifo_full__SHIFT 0x00000018
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_empty_MASK 0x08000000L
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_empty__SHIFT 0x0000001b
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_full_MASK 0x10000000L
+#define SXIFCCG_DEBUG_REG3__vgt_to_ccgen_fifo_full__SHIFT 0x0000001c
+#define SX_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2_MASK 0x000003ffL
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x00000000
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3_MASK 0x000ffc00L
+#define SX_PERFCOUNTER0_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0x0000000a
+#define SX_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER0_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT2_MASK 0x000003ffL
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT2__SHIFT 0x00000000
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT3_MASK 0x000ffc00L
+#define SX_PERFCOUNTER1_SELECT1__PERFCOUNTER_SELECT3__SHIFT 0x0000000a
+#define SX_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER1_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define SX_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER2_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define SX_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define SX_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define SX_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define SX_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define SX_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define SX_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1_MASK 0x000ffc00L
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT1__SHIFT 0x0000000a
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT_MASK 0x000000ffL
+#define SX_PERFCOUNTER3_SELECT__PERFCOUNTER_SELECT__SHIFT 0x00000000
+#define TA_BC_BASE_ADDR__ADDRESS_MASK 0xffffffffL
+#define TA_BC_BASE_ADDR__ADDRESS__SHIFT 0x00000000
+#define TA_BC_BASE_ADDR_HI__ADDRESS_MASK 0x000000ffL
+#define TA_BC_BASE_ADDR_HI__ADDRESS__SHIFT 0x00000000
+#define TA_CGTT_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TA_CGTT_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TA_CGTT_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TA_CGTT_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TA_CGTT_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TA_CGTT_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TA_CGTT_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TA_CGTT_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TA_CGTT_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TA_CGTT_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TA_CGTT_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TA_CGTT_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TA_CGTT_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TA_CNTL__ALIGNER_CREDIT_MASK 0x001f0000L
+#define TA_CNTL__ALIGNER_CREDIT__SHIFT 0x00000010
+#define TA_CNTL_AUX__ANISO_WEIGHT_MODE_MASK 0x00010000L
+#define TA_CNTL_AUX__ANISO_WEIGHT_MODE__SHIFT 0x00000010
+#define TA_CNTL__TC_DATA_CREDIT_MASK 0x0000e000L
+#define TA_CNTL__TC_DATA_CREDIT__SHIFT 0x0000000d
+#define TA_CNTL__TD_FIFO_CREDIT_MASK 0xffc00000L
+#define TA_CNTL__TD_FIFO_CREDIT__SHIFT 0x00000016
+#define TA_CS_BC_BASE_ADDR__ADDRESS_MASK 0xffffffffL
+#define TA_CS_BC_BASE_ADDR__ADDRESS__SHIFT 0x00000000
+#define TA_CS_BC_BASE_ADDR_HI__ADDRESS_MASK 0x000000ffL
+#define TA_CS_BC_BASE_ADDR_HI__ADDRESS__SHIFT 0x00000000
+#define TA_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define TA_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define TA_DEBUG_INDEX__INDEX_MASK 0x0000001fL
+#define TA_DEBUG_INDEX__INDEX__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000000ffL
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x0003fc00L
+#define TA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x0003fc00L
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TA_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TA_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x0003fc00L
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TA_SCRATCH__SCRATCH_MASK 0xffffffffL
+#define TA_SCRATCH__SCRATCH__SHIFT 0x00000000
+#define TA_STATUS__AL_BUSY_MASK 0x40000000L
+#define TA_STATUS__AL_BUSY__SHIFT 0x0000001e
+#define TA_STATUS__BUSY_MASK 0x80000000L
+#define TA_STATUS__BUSY__SHIFT 0x0000001f
+#define TA_STATUS__FA_BUSY_MASK 0x20000000L
+#define TA_STATUS__FA_BUSY__SHIFT 0x0000001d
+#define TA_STATUS__FA_LFIFO_EMPTYB_MASK 0x00200000L
+#define TA_STATUS__FA_LFIFO_EMPTYB__SHIFT 0x00000015
+#define TA_STATUS__FA_PFIFO_EMPTYB_MASK 0x00100000L
+#define TA_STATUS__FA_PFIFO_EMPTYB__SHIFT 0x00000014
+#define TA_STATUS__FA_SFIFO_EMPTYB_MASK 0x00400000L
+#define TA_STATUS__FA_SFIFO_EMPTYB__SHIFT 0x00000016
+#define TA_STATUS__FG_BUSY_MASK 0x02000000L
+#define TA_STATUS__FG_BUSY__SHIFT 0x00000019
+#define TA_STATUS__FG_LFIFO_EMPTYB_MASK 0x00002000L
+#define TA_STATUS__FG_LFIFO_EMPTYB__SHIFT 0x0000000d
+#define TA_STATUS__FG_PFIFO_EMPTYB_MASK 0x00001000L
+#define TA_STATUS__FG_PFIFO_EMPTYB__SHIFT 0x0000000c
+#define TA_STATUS__FG_SFIFO_EMPTYB_MASK 0x00004000L
+#define TA_STATUS__FG_SFIFO_EMPTYB__SHIFT 0x0000000e
+#define TA_STATUS__FL_BUSY_MASK 0x08000000L
+#define TA_STATUS__FL_BUSY__SHIFT 0x0000001b
+#define TA_STATUS__FL_LFIFO_EMPTYB_MASK 0x00020000L
+#define TA_STATUS__FL_LFIFO_EMPTYB__SHIFT 0x00000011
+#define TA_STATUS__FL_PFIFO_EMPTYB_MASK 0x00010000L
+#define TA_STATUS__FL_PFIFO_EMPTYB__SHIFT 0x00000010
+#define TA_STATUS__FL_SFIFO_EMPTYB_MASK 0x00040000L
+#define TA_STATUS__FL_SFIFO_EMPTYB__SHIFT 0x00000012
+#define TA_STATUS__IN_BUSY_MASK 0x01000000L
+#define TA_STATUS__IN_BUSY__SHIFT 0x00000018
+#define TA_STATUS__LA_BUSY_MASK 0x04000000L
+#define TA_STATUS__LA_BUSY__SHIFT 0x0000001a
+#define TA_STATUS__TA_BUSY_MASK 0x10000000L
+#define TA_STATUS__TA_BUSY__SHIFT 0x0000001c
+#define TCA_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TCA_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TCA_CGTT_SCLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TCA_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TCA_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TCA_CTRL__HOLE_TIMEOUT_MASK 0x0000000fL
+#define TCA_CTRL__HOLE_TIMEOUT__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCA_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCA_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCA_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCA_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCA_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCA_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCA_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCA_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCA_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCA_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCA_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCA_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCA_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_CGTT_SCLK_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TCC_CGTT_SCLK_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TCC_CGTT_SCLK_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TCC_CGTT_SCLK_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TCC_CGTT_SCLK_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TCC_CTRL__CACHE_SIZE_MASK 0x00000003L
+#define TCC_CTRL__CACHE_SIZE__SHIFT 0x00000000
+#define TCC_CTRL__LATENCY_FIFO_SIZE_MASK 0x000f0000L
+#define TCC_CTRL__LATENCY_FIFO_SIZE__SHIFT 0x00000010
+#define TCC_CTRL__RATE_MASK 0x0000000cL
+#define TCC_CTRL__RATE__SHIFT 0x00000002
+#define TCC_CTRL__SRC_FIFO_SIZE_MASK 0x0000f000L
+#define TCC_CTRL__SRC_FIFO_SIZE__SHIFT 0x0000000c
+#define TCC_CTRL__WB_OR_INV_ALL_VMIDS_MASK 0x00100000L
+#define TCC_CTRL__WB_OR_INV_ALL_VMIDS__SHIFT 0x00000014
+#define TCC_CTRL__WRITEBACK_MARGIN_MASK 0x000000f0L
+#define TCC_CTRL__WRITEBACK_MARGIN__SHIFT 0x00000004
+#define TCC_EDC_COUNTER__DED_COUNT_MASK 0x000f0000L
+#define TCC_EDC_COUNTER__DED_COUNT__SHIFT 0x00000010
+#define TCC_EDC_COUNTER__SEC_COUNT_MASK 0x0000000fL
+#define TCC_EDC_COUNTER__SEC_COUNT__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCC_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0x0f000000L
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x00000018
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0xf0000000L
+#define TCC_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCC_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCC_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCC_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCC_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCC_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCC_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCC_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCC_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCC_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCC_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCI_CNTL_1__REQ_FIFO_DEPTH_MASK 0x00ff0000L
+#define TCI_CNTL_1__REQ_FIFO_DEPTH__SHIFT 0x00000010
+#define TCI_CNTL_1__WBINVL1_NUM_CYCLES_MASK 0x0000ffffL
+#define TCI_CNTL_1__WBINVL1_NUM_CYCLES__SHIFT 0x00000000
+#define TCI_CNTL_1__WDATA_RAM_DEPTH_MASK 0xff000000L
+#define TCI_CNTL_1__WDATA_RAM_DEPTH__SHIFT 0x00000018
+#define TCI_CNTL_2__L1_INVAL_ON_WBINVL2_MASK 0x00000001L
+#define TCI_CNTL_2__L1_INVAL_ON_WBINVL2__SHIFT 0x00000000
+#define TCI_CNTL_2__TCA_MAX_CREDIT_MASK 0x000001feL
+#define TCI_CNTL_2__TCA_MAX_CREDIT__SHIFT 0x00000001
+#define TCI_STATUS__TCI_BUSY_MASK 0x00000001L
+#define TCI_STATUS__TCI_BUSY__SHIFT 0x00000000
+#define TCP_ADDR_CONFIG__COLHI_WIDTH_MASK 0x000001c0L
+#define TCP_ADDR_CONFIG__COLHI_WIDTH__SHIFT 0x00000006
+#define TCP_ADDR_CONFIG__NUM_BANKS_MASK 0x00000030L
+#define TCP_ADDR_CONFIG__NUM_BANKS__SHIFT 0x00000004
+#define TCP_ADDR_CONFIG__NUM_TCC_BANKS_MASK 0x0000000fL
+#define TCP_ADDR_CONFIG__NUM_TCC_BANKS__SHIFT 0x00000000
+#define TCP_ADDR_CONFIG__RB_SPLIT_COLHI_MASK 0x00000200L
+#define TCP_ADDR_CONFIG__RB_SPLIT_COLHI__SHIFT 0x00000009
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_BITS_MASK 0x00000700L
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_BITS__SHIFT 0x00000008
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_XOR_COUNT_MASK 0x07000000L
+#define TCP_BUFFER_ADDR_HASH_CNTL__BANK_XOR_COUNT__SHIFT 0x00000018
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_BITS_MASK 0x00000007L
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_BITS__SHIFT 0x00000000
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_XOR_COUNT_MASK 0x00070000L
+#define TCP_BUFFER_ADDR_HASH_CNTL__CHANNEL_XOR_COUNT__SHIFT 0x00000010
+#define TCP_CHAN_STEER_HI__CHAN8_MASK 0x0000000fL
+#define TCP_CHAN_STEER_HI__CHAN8__SHIFT 0x00000000
+#define TCP_CHAN_STEER_HI__CHAN9_MASK 0x000000f0L
+#define TCP_CHAN_STEER_HI__CHAN9__SHIFT 0x00000004
+#define TCP_CHAN_STEER_HI__CHANA_MASK 0x00000f00L
+#define TCP_CHAN_STEER_HI__CHANA__SHIFT 0x00000008
+#define TCP_CHAN_STEER_HI__CHANB_MASK 0x0000f000L
+#define TCP_CHAN_STEER_HI__CHANB__SHIFT 0x0000000c
+#define TCP_CHAN_STEER_HI__CHANC_MASK 0x000f0000L
+#define TCP_CHAN_STEER_HI__CHANC__SHIFT 0x00000010
+#define TCP_CHAN_STEER_HI__CHAND_MASK 0x00f00000L
+#define TCP_CHAN_STEER_HI__CHAND__SHIFT 0x00000014
+#define TCP_CHAN_STEER_HI__CHANE_MASK 0x0f000000L
+#define TCP_CHAN_STEER_HI__CHANE__SHIFT 0x00000018
+#define TCP_CHAN_STEER_HI__CHANF_MASK 0xf0000000L
+#define TCP_CHAN_STEER_HI__CHANF__SHIFT 0x0000001c
+#define TCP_CHAN_STEER_LO__CHAN0_MASK 0x0000000fL
+#define TCP_CHAN_STEER_LO__CHAN0__SHIFT 0x00000000
+#define TCP_CHAN_STEER_LO__CHAN1_MASK 0x000000f0L
+#define TCP_CHAN_STEER_LO__CHAN1__SHIFT 0x00000004
+#define TCP_CHAN_STEER_LO__CHAN2_MASK 0x00000f00L
+#define TCP_CHAN_STEER_LO__CHAN2__SHIFT 0x00000008
+#define TCP_CHAN_STEER_LO__CHAN3_MASK 0x0000f000L
+#define TCP_CHAN_STEER_LO__CHAN3__SHIFT 0x0000000c
+#define TCP_CHAN_STEER_LO__CHAN4_MASK 0x000f0000L
+#define TCP_CHAN_STEER_LO__CHAN4__SHIFT 0x00000010
+#define TCP_CHAN_STEER_LO__CHAN5_MASK 0x00f00000L
+#define TCP_CHAN_STEER_LO__CHAN5__SHIFT 0x00000014
+#define TCP_CHAN_STEER_LO__CHAN6_MASK 0x0f000000L
+#define TCP_CHAN_STEER_LO__CHAN6__SHIFT 0x00000018
+#define TCP_CHAN_STEER_LO__CHAN7_MASK 0xf0000000L
+#define TCP_CHAN_STEER_LO__CHAN7__SHIFT 0x0000001c
+#define TCP_CNTL__DISABLE_Z_MAP_MASK 0x10000000L
+#define TCP_CNTL__DISABLE_Z_MAP__SHIFT 0x0000001c
+#define TCP_CNTL__FLAT_BUF_CACHE_SWIZZLE_MASK 0x00000020L
+#define TCP_CNTL__FLAT_BUF_CACHE_SWIZZLE__SHIFT 0x00000005
+#define TCP_CNTL__FLAT_BUF_HASH_ENABLE_MASK 0x00000010L
+#define TCP_CNTL__FLAT_BUF_HASH_ENABLE__SHIFT 0x00000004
+#define TCP_CNTL__FORCE_EOW_TAGRAM_CNT_MASK 0x0fc00000L
+#define TCP_CNTL__FORCE_EOW_TAGRAM_CNT__SHIFT 0x00000016
+#define TCP_CNTL__FORCE_EOW_TOTAL_CNT_MASK 0x001f8000L
+#define TCP_CNTL__FORCE_EOW_TOTAL_CNT__SHIFT 0x0000000f
+#define TCP_CNTL__FORCE_HIT_MASK 0x00000001L
+#define TCP_CNTL__FORCE_HIT__SHIFT 0x00000000
+#define TCP_CNTL__FORCE_MISS_MASK 0x00000002L
+#define TCP_CNTL__FORCE_MISS__SHIFT 0x00000001
+#define TCP_CNTL__INV_ALL_VMIDS_MASK 0x20000000L
+#define TCP_CNTL__INV_ALL_VMIDS__SHIFT 0x0000001d
+#define TCP_CNTL__L1_SIZE_MASK 0x0000000cL
+#define TCP_CNTL__L1_SIZE__SHIFT 0x00000002
+#define TCP_CREDIT__LFIFO_CREDIT_MASK 0x000003ffL
+#define TCP_CREDIT__LFIFO_CREDIT__SHIFT 0x00000000
+#define TCP_CREDIT__REQ_FIFO_CREDIT_MASK 0x007f0000L
+#define TCP_CREDIT__REQ_FIFO_CREDIT__SHIFT 0x00000010
+#define TCP_CREDIT__TD_CREDIT_MASK 0xe0000000L
+#define TCP_CREDIT__TD_CREDIT__SHIFT 0x0000001d
+#define TCP_EDC_COUNTER__DED_COUNT_MASK 0x000f0000L
+#define TCP_EDC_COUNTER__DED_COUNT__SHIFT 0x00000010
+#define TCP_EDC_COUNTER__SEC_COUNT_MASK 0x0000000fL
+#define TCP_EDC_COUNTER__SEC_COUNT__SHIFT 0x00000000
+#define TCP_INVALIDATE__START_MASK 0x00000001L
+#define TCP_INVALIDATE__START__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TCP_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TCP_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER2_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER2_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TCP_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TCP_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TCP_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TCP_PERFCOUNTER3_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TCP_PERFCOUNTER3_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TCP_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TCP_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TCP_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TCP_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TCP_STATUS__TCP_BUSY_MASK 0x00000001L
+#define TCP_STATUS__TCP_BUSY__SHIFT 0x00000000
+#define TD_CGTT_CTRL__OFF_HYSTERESIS_MASK 0x00000ff0L
+#define TD_CGTT_CTRL__OFF_HYSTERESIS__SHIFT 0x00000004
+#define TD_CGTT_CTRL__ON_DELAY_MASK 0x0000000fL
+#define TD_CGTT_CTRL__ON_DELAY__SHIFT 0x00000000
+#define TD_CGTT_CTRL__SOFT_OVERRIDE0_MASK 0x80000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE0__SHIFT 0x0000001f
+#define TD_CGTT_CTRL__SOFT_OVERRIDE1_MASK 0x40000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE1__SHIFT 0x0000001e
+#define TD_CGTT_CTRL__SOFT_OVERRIDE2_MASK 0x20000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE2__SHIFT 0x0000001d
+#define TD_CGTT_CTRL__SOFT_OVERRIDE3_MASK 0x10000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE3__SHIFT 0x0000001c
+#define TD_CGTT_CTRL__SOFT_OVERRIDE4_MASK 0x08000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE4__SHIFT 0x0000001b
+#define TD_CGTT_CTRL__SOFT_OVERRIDE5_MASK 0x04000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE5__SHIFT 0x0000001a
+#define TD_CGTT_CTRL__SOFT_OVERRIDE6_MASK 0x02000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE6__SHIFT 0x00000019
+#define TD_CGTT_CTRL__SOFT_OVERRIDE7_MASK 0x01000000L
+#define TD_CGTT_CTRL__SOFT_OVERRIDE7__SHIFT 0x00000018
+#define TD_CNTL__DISABLE_POWER_THROTTLE_MASK 0x00100000L
+#define TD_CNTL__DISABLE_POWER_THROTTLE__SHIFT 0x00000014
+#define TD_CNTL__EXTEND_LDS_STALL_MASK 0x00000600L
+#define TD_CNTL__EXTEND_LDS_STALL__SHIFT 0x00000009
+#define TD_CNTL__GATHER4_DX9_MODE_MASK 0x00080000L
+#define TD_CNTL__GATHER4_DX9_MODE__SHIFT 0x00000013
+#define TD_CNTL__GATHER4_FLOAT_MODE_MASK 0x00010000L
+#define TD_CNTL__GATHER4_FLOAT_MODE__SHIFT 0x00000010
+#define TD_CNTL__LD_FLOAT_MODE_MASK 0x00040000L
+#define TD_CNTL__LD_FLOAT_MODE__SHIFT 0x00000012
+#define TD_CNTL__LDS_STALL_PHASE_ADJUST_MASK 0x00001800L
+#define TD_CNTL__LDS_STALL_PHASE_ADJUST__SHIFT 0x0000000b
+#define TD_CNTL__PAD_STALL_EN_MASK 0x00000100L
+#define TD_CNTL__PAD_STALL_EN__SHIFT 0x00000008
+#define TD_CNTL__PRECISION_COMPATIBILITY_MASK 0x00008000L
+#define TD_CNTL__PRECISION_COMPATIBILITY__SHIFT 0x0000000f
+#define TD_CNTL__SYNC_PHASE_SH_MASK 0x00000003L
+#define TD_CNTL__SYNC_PHASE_SH__SHIFT 0x00000000
+#define TD_CNTL__SYNC_PHASE_VC_SMX_MASK 0x00000030L
+#define TD_CNTL__SYNC_PHASE_VC_SMX__SHIFT 0x00000004
+#define TD_DEBUG_DATA__DATA_MASK 0x00ffffffL
+#define TD_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define TD_DEBUG_INDEX__INDEX_MASK 0x0000001fL
+#define TD_DEBUG_INDEX__INDEX__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define TD_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define TD_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define TD_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000000ffL
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x0003fc00L
+#define TD_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define TD_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define TD_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define TD_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x0003fc00L
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define TD_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define TD_SCRATCH__SCRATCH_MASK 0xffffffffL
+#define TD_SCRATCH__SCRATCH__SHIFT 0x00000000
+#define TD_STATUS__BUSY_MASK 0x80000000L
+#define TD_STATUS__BUSY__SHIFT 0x0000001f
+#define USER_SQC_BANK_DISABLE__SQC0_BANK_DISABLE_MASK 0x000f0000L
+#define USER_SQC_BANK_DISABLE__SQC0_BANK_DISABLE__SHIFT 0x00000010
+#define USER_SQC_BANK_DISABLE__SQC1_BANK_DISABLE_MASK 0x00f00000L
+#define USER_SQC_BANK_DISABLE__SQC1_BANK_DISABLE__SHIFT 0x00000014
+#define USER_SQC_BANK_DISABLE__SQC2_BANK_DISABLE_MASK 0x0f000000L
+#define USER_SQC_BANK_DISABLE__SQC2_BANK_DISABLE__SHIFT 0x00000018
+#define USER_SQC_BANK_DISABLE__SQC3_BANK_DISABLE_MASK 0xf0000000L
+#define USER_SQC_BANK_DISABLE__SQC3_BANK_DISABLE__SHIFT 0x0000001c
+#define VGT_CACHE_INVALIDATION__AUTO_INVLD_EN_MASK 0x000000c0L
+#define VGT_CACHE_INVALIDATION__AUTO_INVLD_EN__SHIFT 0x00000006
+#define VGT_CACHE_INVALIDATION__CACHE_INVALIDATION_MASK 0x00000003L
+#define VGT_CACHE_INVALIDATION__CACHE_INVALIDATION__SHIFT 0x00000000
+#define VGT_CACHE_INVALIDATION__DIS_RANGE_FULL_INVLD_MASK 0x00000800L
+#define VGT_CACHE_INVALIDATION__DIS_RANGE_FULL_INVLD__SHIFT 0x0000000b
+#define VGT_CACHE_INVALIDATION__ES_LIMIT_MASK 0x001f0000L
+#define VGT_CACHE_INVALIDATION__ES_LIMIT__SHIFT 0x00000010
+#define VGT_CACHE_INVALIDATION__GS_LATE_ALLOC_EN_MASK 0x00001000L
+#define VGT_CACHE_INVALIDATION__GS_LATE_ALLOC_EN__SHIFT 0x0000000c
+#define VGT_CACHE_INVALIDATION__STREAMOUT_FULL_FLUSH_MASK 0x00002000L
+#define VGT_CACHE_INVALIDATION__STREAMOUT_FULL_FLUSH__SHIFT 0x0000000d
+#define VGT_CACHE_INVALIDATION__USE_GS_DONE_MASK 0x00000200L
+#define VGT_CACHE_INVALIDATION__USE_GS_DONE__SHIFT 0x00000009
+#define VGT_CACHE_INVALIDATION__VS_NO_EXTRA_BUFFER_MASK 0x00000020L
+#define VGT_CACHE_INVALIDATION__VS_NO_EXTRA_BUFFER__SHIFT 0x00000005
+#define VGT_CNTL_STATUS__VGT_BUSY_MASK 0x00000001L
+#define VGT_CNTL_STATUS__VGT_BUSY__SHIFT 0x00000000
+#define VGT_CNTL_STATUS__VGT_GS_BUSY_MASK 0x00000080L
+#define VGT_CNTL_STATUS__VGT_GS_BUSY__SHIFT 0x00000007
+#define VGT_CNTL_STATUS__VGT_HS_BUSY_MASK 0x00000100L
+#define VGT_CNTL_STATUS__VGT_HS_BUSY__SHIFT 0x00000008
+#define VGT_CNTL_STATUS__VGT_OUT_BUSY_MASK 0x00000004L
+#define VGT_CNTL_STATUS__VGT_OUT_BUSY__SHIFT 0x00000002
+#define VGT_CNTL_STATUS__VGT_OUT_INDX_BUSY_MASK 0x00000002L
+#define VGT_CNTL_STATUS__VGT_OUT_INDX_BUSY__SHIFT 0x00000001
+#define VGT_CNTL_STATUS__VGT_PI_BUSY_MASK 0x00000040L
+#define VGT_CNTL_STATUS__VGT_PI_BUSY__SHIFT 0x00000006
+#define VGT_CNTL_STATUS__VGT_PT_BUSY_MASK 0x00000008L
+#define VGT_CNTL_STATUS__VGT_PT_BUSY__SHIFT 0x00000003
+#define VGT_CNTL_STATUS__VGT_TE11_BUSY_MASK 0x00000200L
+#define VGT_CNTL_STATUS__VGT_TE11_BUSY__SHIFT 0x00000009
+#define VGT_CNTL_STATUS__VGT_TE_BUSY_MASK 0x00000010L
+#define VGT_CNTL_STATUS__VGT_TE_BUSY__SHIFT 0x00000004
+#define VGT_CNTL_STATUS__VGT_VR_BUSY_MASK 0x00000020L
+#define VGT_CNTL_STATUS__VGT_VR_BUSY__SHIFT 0x00000005
+#define VGT_DEBUG_CNTL__VGT_DEBUG_INDX_MASK 0x0000003fL
+#define VGT_DEBUG_CNTL__VGT_DEBUG_INDX__SHIFT 0x00000000
+#define VGT_DEBUG_CNTL__VGT_DEBUG_SEL_BUS_B_MASK 0x00000040L
+#define VGT_DEBUG_CNTL__VGT_DEBUG_SEL_BUS_B__SHIFT 0x00000006
+#define VGT_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define VGT_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define VGT_DEBUG_REG0__cm_busy_MASK 0x00008000L
+#define VGT_DEBUG_REG0__cm_busy__SHIFT 0x0000000f
+#define VGT_DEBUG_REG0__combined_out_busy_MASK 0x00200000L
+#define VGT_DEBUG_REG0__combined_out_busy__SHIFT 0x00000015
+#define VGT_DEBUG_REG0__core_clk_busy_MASK 0x04000000L
+#define VGT_DEBUG_REG0__core_clk_busy__SHIFT 0x0000001a
+#define VGT_DEBUG_REG0__frmt_busy_MASK 0x00020000L
+#define VGT_DEBUG_REG0__frmt_busy__SHIFT 0x00000011
+#define VGT_DEBUG_REG0__gog_busy_MASK 0x00010000L
+#define VGT_DEBUG_REG0__gog_busy__SHIFT 0x00000010
+#define VGT_DEBUG_REG0__gs_busy_MASK 0x00001000L
+#define VGT_DEBUG_REG0__gs_busy__SHIFT 0x0000000c
+#define VGT_DEBUG_REG0__gs_clk_busy_MASK 0x08000000L
+#define VGT_DEBUG_REG0__gs_clk_busy__SHIFT 0x0000001b
+#define VGT_DEBUG_REG0__pa_interfaces_busy_MASK 0x00800000L
+#define VGT_DEBUG_REG0__pa_interfaces_busy__SHIFT 0x00000017
+#define VGT_DEBUG_REG0__pi_busy_MASK 0x00000100L
+#define VGT_DEBUG_REG0__pi_busy__SHIFT 0x00000008
+#define VGT_DEBUG_REG0__pt_pi_busy_MASK 0x00000400L
+#define VGT_DEBUG_REG0__pt_pi_busy__SHIFT 0x0000000a
+#define VGT_DEBUG_REG0__rcm_busy_MASK 0x00002000L
+#define VGT_DEBUG_REG0__rcm_busy__SHIFT 0x0000000d
+#define VGT_DEBUG_REG0__reg_clk_busy_MASK 0x01000000L
+#define VGT_DEBUG_REG0__reg_clk_busy__SHIFT 0x00000018
+#define VGT_DEBUG_REG0__sclk_core_vld_MASK 0x20000000L
+#define VGT_DEBUG_REG0__sclk_core_vld__SHIFT 0x0000001d
+#define VGT_DEBUG_REG0__sclk_gs_vld_MASK 0x40000000L
+#define VGT_DEBUG_REG0__sclk_gs_vld__SHIFT 0x0000001e
+#define VGT_DEBUG_REG0__SPARE0_MASK 0x80000000L
+#define VGT_DEBUG_REG0__SPARE0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG0__SPARE10_MASK 0x00040000L
+#define VGT_DEBUG_REG0__SPARE10__SHIFT 0x00000012
+#define VGT_DEBUG_REG0__SPARE1_MASK 0x10000000L
+#define VGT_DEBUG_REG0__SPARE1__SHIFT 0x0000001c
+#define VGT_DEBUG_REG0__SPARE2_MASK 0x02000000L
+#define VGT_DEBUG_REG0__SPARE2__SHIFT 0x00000019
+#define VGT_DEBUG_REG0__SPARE3_MASK 0x00100000L
+#define VGT_DEBUG_REG0__SPARE3__SHIFT 0x00000014
+#define VGT_DEBUG_REG0__SPARE4_MASK 0x00000080L
+#define VGT_DEBUG_REG0__SPARE4__SHIFT 0x00000007
+#define VGT_DEBUG_REG0__SPARE5_MASK 0x00000040L
+#define VGT_DEBUG_REG0__SPARE5__SHIFT 0x00000006
+#define VGT_DEBUG_REG0__SPARE6_MASK 0x00000020L
+#define VGT_DEBUG_REG0__SPARE6__SHIFT 0x00000005
+#define VGT_DEBUG_REG0__SPARE7_MASK 0x00000010L
+#define VGT_DEBUG_REG0__SPARE7__SHIFT 0x00000004
+#define VGT_DEBUG_REG0__SPARE8_MASK 0x00000008L
+#define VGT_DEBUG_REG0__SPARE8__SHIFT 0x00000003
+#define VGT_DEBUG_REG0__SPARE9_MASK 0x00000002L
+#define VGT_DEBUG_REG0__SPARE9__SHIFT 0x00000001
+#define VGT_DEBUG_REG0__spi_vs_interfaces_busy_MASK 0x00400000L
+#define VGT_DEBUG_REG0__spi_vs_interfaces_busy__SHIFT 0x00000016
+#define VGT_DEBUG_REG0__te11_pi_busy_MASK 0x00080000L
+#define VGT_DEBUG_REG0__te11_pi_busy__SHIFT 0x00000013
+#define VGT_DEBUG_REG0__te_pi_busy_MASK 0x00000800L
+#define VGT_DEBUG_REG0__te_pi_busy__SHIFT 0x0000000b
+#define VGT_DEBUG_REG0__tm_busy_MASK 0x00004000L
+#define VGT_DEBUG_REG0__tm_busy__SHIFT 0x0000000e
+#define VGT_DEBUG_REG0__vgt_busy_extended_MASK 0x00000001L
+#define VGT_DEBUG_REG0__vgt_busy_extended__SHIFT 0x00000000
+#define VGT_DEBUG_REG0__vgt_busy_MASK 0x00000004L
+#define VGT_DEBUG_REG0__vgt_busy__SHIFT 0x00000002
+#define VGT_DEBUG_REG0__vr_pi_busy_MASK 0x00000200L
+#define VGT_DEBUG_REG0__vr_pi_busy__SHIFT 0x00000009
+#define VGT_DEBUG_REG10__eopg_r2_q_MASK 0x00000020L
+#define VGT_DEBUG_REG10__eopg_r2_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG10__eotg_r2_q_MASK 0x00000040L
+#define VGT_DEBUG_REG10__eotg_r2_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG10__es_rb_space_avail_r2_q_8_0_MASK 0xff800000L
+#define VGT_DEBUG_REG10__es_rb_space_avail_r2_q_8_0__SHIFT 0x00000017
+#define VGT_DEBUG_REG10__gs_rb_space_avail_r3_q_9_0_MASK 0x007fe000L
+#define VGT_DEBUG_REG10__gs_rb_space_avail_r3_q_9_0__SHIFT 0x0000000d
+#define VGT_DEBUG_REG10__index_buffer_depth_r1_q_MASK 0x0000001fL
+#define VGT_DEBUG_REG10__index_buffer_depth_r1_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG10__onchip_gs_en_r0_q_MASK 0x00000180L
+#define VGT_DEBUG_REG10__onchip_gs_en_r0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_q_MASK 0x00001000L
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_qq_MASK 0x00000800L
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_qq__SHIFT 0x0000000b
+#define VGT_DEBUG_REG10__rcm_mem_gsprim_re_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG10__SPARE2_MASK 0x00000600L
+#define VGT_DEBUG_REG10__SPARE2__SHIFT 0x00000009
+#define VGT_DEBUG_REG11__counters_available_r0_MASK 0x00001000L
+#define VGT_DEBUG_REG11__counters_available_r0__SHIFT 0x0000000c
+#define VGT_DEBUG_REG11__counters_avail_r0_MASK 0x00000800L
+#define VGT_DEBUG_REG11__counters_avail_r0__SHIFT 0x0000000b
+#define VGT_DEBUG_REG11__counters_busy_r0_MASK 0x00000400L
+#define VGT_DEBUG_REG11__counters_busy_r0__SHIFT 0x0000000a
+#define VGT_DEBUG_REG11__es_r0_rtr_MASK 0x00100000L
+#define VGT_DEBUG_REG11__es_r0_rtr__SHIFT 0x00000014
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_busy_MASK 0x00000008L
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_busy__SHIFT 0x00000003
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_full_MASK 0x08000000L
+#define VGT_DEBUG_REG11__es_rb_dealloc_fifo_full__SHIFT 0x0000001b
+#define VGT_DEBUG_REG11__es_rb_roll_over_r3_MASK 0x00000200L
+#define VGT_DEBUG_REG11__es_rb_roll_over_r3__SHIFT 0x00000009
+#define VGT_DEBUG_REG11__es_tbl_empty_MASK 0x40000000L
+#define VGT_DEBUG_REG11__es_tbl_empty__SHIFT 0x0000001e
+#define VGT_DEBUG_REG11__gog_tm_vs_event_rtr_MASK 0x00200000L
+#define VGT_DEBUG_REG11__gog_tm_vs_event_rtr__SHIFT 0x00000015
+#define VGT_DEBUG_REG11__gs_issue_rtr_MASK 0x00010000L
+#define VGT_DEBUG_REG11__gs_issue_rtr__SHIFT 0x00000010
+#define VGT_DEBUG_REG11__gs_r0_rtr_MASK 0x00080000L
+#define VGT_DEBUG_REG11__gs_r0_rtr__SHIFT 0x00000013
+#define VGT_DEBUG_REG11__hold_eswave_MASK 0x00000100L
+#define VGT_DEBUG_REG11__hold_eswave__SHIFT 0x00000008
+#define VGT_DEBUG_REG11__no_active_states_r0_MASK 0x80000000L
+#define VGT_DEBUG_REG11__no_active_states_r0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG11__send_event_q_MASK 0x20000000L
+#define VGT_DEBUG_REG11__send_event_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG11__SPARE0_MASK 0x00040000L
+#define VGT_DEBUG_REG11__SPARE0__SHIFT 0x00000012
+#define VGT_DEBUG_REG11__SPARE1_MASK 0x00000020L
+#define VGT_DEBUG_REG11__SPARE1__SHIFT 0x00000005
+#define VGT_DEBUG_REG11__spi_esthread_fifo_busy_MASK 0x00000080L
+#define VGT_DEBUG_REG11__spi_esthread_fifo_busy__SHIFT 0x00000007
+#define VGT_DEBUG_REG11__spi_gsthread_fifo_busy_MASK 0x00000040L
+#define VGT_DEBUG_REG11__spi_gsthread_fifo_busy__SHIFT 0x00000006
+#define VGT_DEBUG_REG11__tm_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG11__tm_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG11__tm_noif_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG11__tm_noif_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG11__tm_out_busy_q_MASK 0x00000004L
+#define VGT_DEBUG_REG11__tm_out_busy_q__SHIFT 0x00000002
+#define VGT_DEBUG_REG11__tm_pt_event_rtr_MASK 0x00020000L
+#define VGT_DEBUG_REG11__tm_pt_event_rtr__SHIFT 0x00000011
+#define VGT_DEBUG_REG11__tm_rcm_es_tbl_rtr_MASK 0x01000000L
+#define VGT_DEBUG_REG11__tm_rcm_es_tbl_rtr__SHIFT 0x00000018
+#define VGT_DEBUG_REG11__tm_rcm_gs_event_rtr_MASK 0x00400000L
+#define VGT_DEBUG_REG11__tm_rcm_gs_event_rtr__SHIFT 0x00000016
+#define VGT_DEBUG_REG11__tm_rcm_gs_tbl_rtr_MASK 0x00800000L
+#define VGT_DEBUG_REG11__tm_rcm_gs_tbl_rtr__SHIFT 0x00000017
+#define VGT_DEBUG_REG11__VGT_SPI_esthread_rtr_q_MASK 0x00008000L
+#define VGT_DEBUG_REG11__VGT_SPI_esthread_rtr_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG11__VGT_SPI_gsthread_rtr_q_MASK 0x00004000L
+#define VGT_DEBUG_REG11__VGT_SPI_gsthread_rtr_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_busy_MASK 0x00000010L
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_busy__SHIFT 0x00000004
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_full_MASK 0x10000000L
+#define VGT_DEBUG_REG11__vs_dealloc_tbl_full__SHIFT 0x0000001c
+#define VGT_DEBUG_REG11__vs_event_fifo_empty_MASK 0x02000000L
+#define VGT_DEBUG_REG11__vs_event_fifo_empty__SHIFT 0x00000019
+#define VGT_DEBUG_REG11__vs_event_fifo_full_MASK 0x04000000L
+#define VGT_DEBUG_REG11__vs_event_fifo_full__SHIFT 0x0000001a
+#define VGT_DEBUG_REG11__vs_event_fifo_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG11__vs_event_fifo_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG12__gs_state0_r0_q_MASK 0x00000007L
+#define VGT_DEBUG_REG12__gs_state0_r0_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG12__gs_state1_r0_q_MASK 0x00000038L
+#define VGT_DEBUG_REG12__gs_state1_r0_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG12__gs_state2_r0_q_MASK 0x000001c0L
+#define VGT_DEBUG_REG12__gs_state2_r0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG12__gs_state3_r0_q_MASK 0x00000e00L
+#define VGT_DEBUG_REG12__gs_state3_r0_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG12__gs_state4_r0_q_MASK 0x00007000L
+#define VGT_DEBUG_REG12__gs_state4_r0_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG12__gs_state5_r0_q_MASK 0x00038000L
+#define VGT_DEBUG_REG12__gs_state5_r0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG12__gs_state6_r0_q_MASK 0x001c0000L
+#define VGT_DEBUG_REG12__gs_state6_r0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG12__gs_state7_r0_q_MASK 0x00e00000L
+#define VGT_DEBUG_REG12__gs_state7_r0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG12__gs_state8_r0_q_MASK 0x07000000L
+#define VGT_DEBUG_REG12__gs_state8_r0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG12__gs_state9_r0_q_MASK 0x38000000L
+#define VGT_DEBUG_REG12__gs_state9_r0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG12__hold_eswave_eop_MASK 0x40000000L
+#define VGT_DEBUG_REG12__hold_eswave_eop__SHIFT 0x0000001e
+#define VGT_DEBUG_REG12__SPARE0_MASK 0x80000000L
+#define VGT_DEBUG_REG12__SPARE0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG13__active_cm_sm_r0_q_MASK 0xf8000000L
+#define VGT_DEBUG_REG13__active_cm_sm_r0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG13__es_tbl_full_MASK 0x01000000L
+#define VGT_DEBUG_REG13__es_tbl_full__SHIFT 0x00000018
+#define VGT_DEBUG_REG13__gsfetch_done_cnt_q_not_0_MASK 0x00800000L
+#define VGT_DEBUG_REG13__gsfetch_done_cnt_q_not_0__SHIFT 0x00000017
+#define VGT_DEBUG_REG13__gsfetch_done_fifo_cnt_q_not_0_MASK 0x00400000L
+#define VGT_DEBUG_REG13__gsfetch_done_fifo_cnt_q_not_0__SHIFT 0x00000016
+#define VGT_DEBUG_REG13__gs_state10_r0_q_MASK 0x00000007L
+#define VGT_DEBUG_REG13__gs_state10_r0_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG13__gs_state11_r0_q_MASK 0x00000038L
+#define VGT_DEBUG_REG13__gs_state11_r0_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG13__gs_state12_r0_q_MASK 0x000001c0L
+#define VGT_DEBUG_REG13__gs_state12_r0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG13__gs_state13_r0_q_MASK 0x00000e00L
+#define VGT_DEBUG_REG13__gs_state13_r0_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG13__gs_state14_r0_q_MASK 0x00007000L
+#define VGT_DEBUG_REG13__gs_state14_r0_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG13__gs_state15_r0_q_MASK 0x00038000L
+#define VGT_DEBUG_REG13__gs_state15_r0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG13__gs_tbl_wrptr_r0_q_3_0_MASK 0x003c0000L
+#define VGT_DEBUG_REG13__gs_tbl_wrptr_r0_q_3_0__SHIFT 0x00000012
+#define VGT_DEBUG_REG13__SPARE0_MASK 0x04000000L
+#define VGT_DEBUG_REG13__SPARE0__SHIFT 0x0000001a
+#define VGT_DEBUG_REG13__SPARE1_MASK 0x02000000L
+#define VGT_DEBUG_REG13__SPARE1__SHIFT 0x00000019
+#define VGT_DEBUG_REG14__es_flush_cnt_busy_q_MASK 0x00000400L
+#define VGT_DEBUG_REG14__es_flush_cnt_busy_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG14__gsfetch_done_fifo_full_MASK 0x00000010L
+#define VGT_DEBUG_REG14__gsfetch_done_fifo_full__SHIFT 0x00000004
+#define VGT_DEBUG_REG14__gsfetch_done_se1_cnt_q_not_0_MASK 0x20000000L
+#define VGT_DEBUG_REG14__gsfetch_done_se1_cnt_q_not_0__SHIFT 0x0000001d
+#define VGT_DEBUG_REG14__gs_rb_space_avail_r0_MASK 0x00000020L
+#define VGT_DEBUG_REG14__gs_rb_space_avail_r0__SHIFT 0x00000005
+#define VGT_DEBUG_REG14__gs_tbl_full_r0_MASK 0x00000800L
+#define VGT_DEBUG_REG14__gs_tbl_full_r0__SHIFT 0x0000000b
+#define VGT_DEBUG_REG14__se1spi_esthread_fifo_busy_MASK 0x08000000L
+#define VGT_DEBUG_REG14__se1spi_esthread_fifo_busy__SHIFT 0x0000001b
+#define VGT_DEBUG_REG14__se1spi_gsthread_fifo_busy_MASK 0x00200000L
+#define VGT_DEBUG_REG14__se1spi_gsthread_fifo_busy__SHIFT 0x00000015
+#define VGT_DEBUG_REG14__smx1_es_done_cnt_r0_q_not_0_MASK 0x04000000L
+#define VGT_DEBUG_REG14__smx1_es_done_cnt_r0_q_not_0__SHIFT 0x0000001a
+#define VGT_DEBUG_REG14__smx_es_done_cnt_r0_q_not_0_MASK 0x00000040L
+#define VGT_DEBUG_REG14__smx_es_done_cnt_r0_q_not_0__SHIFT 0x00000006
+#define VGT_DEBUG_REG14__SPARE0_MASK 0x40000000L
+#define VGT_DEBUG_REG14__SPARE0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG14__SPARE1_MASK 0x10000000L
+#define VGT_DEBUG_REG14__SPARE1__SHIFT 0x0000001c
+#define VGT_DEBUG_REG14__SPARE2_MASK 0x001ff000L
+#define VGT_DEBUG_REG14__SPARE2__SHIFT 0x0000000c
+#define VGT_DEBUG_REG14__SPARE3_MASK 0x0000000fL
+#define VGT_DEBUG_REG14__SPARE3__SHIFT 0x00000000
+#define VGT_DEBUG_REG14__SPARE8_MASK 0x00000180L
+#define VGT_DEBUG_REG14__SPARE8__SHIFT 0x00000007
+#define VGT_DEBUG_REG14__SPARE_MASK 0x01c00000L
+#define VGT_DEBUG_REG14__SPARE__SHIFT 0x00000016
+#define VGT_DEBUG_REG14__VGT_SE1SPI_esthread_rtr_q_MASK 0x80000000L
+#define VGT_DEBUG_REG14__VGT_SE1SPI_esthread_rtr_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG14__VGT_SE1SPI_gsthread_rtr_q_MASK 0x02000000L
+#define VGT_DEBUG_REG14__VGT_SE1SPI_gsthread_rtr_q__SHIFT 0x00000019
+#define VGT_DEBUG_REG14__vs_done_cnt_q_not_0_MASK 0x00000200L
+#define VGT_DEBUG_REG14__vs_done_cnt_q_not_0__SHIFT 0x00000009
+#define VGT_DEBUG_REG15__active_sm_q_MASK 0x000003e0L
+#define VGT_DEBUG_REG15__active_sm_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG15__cm_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG15__cm_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG15__cntr_tbl_wrptr_q_MASK 0x000f8000L
+#define VGT_DEBUG_REG15__cntr_tbl_wrptr_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG15__counters_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG15__counters_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG15__counters_full_MASK 0x00000010L
+#define VGT_DEBUG_REG15__counters_full__SHIFT 0x00000004
+#define VGT_DEBUG_REG15__entry_rdptr_q_MASK 0x00007c00L
+#define VGT_DEBUG_REG15__entry_rdptr_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG15__gs_done_array_q_not_0_MASK 0x10000000L
+#define VGT_DEBUG_REG15__gs_done_array_q_not_0__SHIFT 0x0000001c
+#define VGT_DEBUG_REG15__output_fifo_empty_MASK 0x00000004L
+#define VGT_DEBUG_REG15__output_fifo_empty__SHIFT 0x00000002
+#define VGT_DEBUG_REG15__output_fifo_full_MASK 0x00000008L
+#define VGT_DEBUG_REG15__output_fifo_full__SHIFT 0x00000003
+#define VGT_DEBUG_REG15__SPARE25_MASK 0x03f00000L
+#define VGT_DEBUG_REG15__SPARE25__SHIFT 0x00000014
+#define VGT_DEBUG_REG15__SPARE31_MASK 0xe0000000L
+#define VGT_DEBUG_REG15__SPARE31__SHIFT 0x0000001d
+#define VGT_DEBUG_REG15__st_cut_mode_q_MASK 0x0c000000L
+#define VGT_DEBUG_REG15__st_cut_mode_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG16__gog_busy_MASK 0x00000001L
+#define VGT_DEBUG_REG16__gog_busy__SHIFT 0x00000000
+#define VGT_DEBUG_REG16__gog_out_prim_state_sel_MASK 0x0e000000L
+#define VGT_DEBUG_REG16__gog_out_prim_state_sel__SHIFT 0x00000019
+#define VGT_DEBUG_REG16__gog_state_q_MASK 0x0000000eL
+#define VGT_DEBUG_REG16__gog_state_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG16__gog_tm_vs_event_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG16__gog_tm_vs_event_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG16__indx_valid_r0_q_MASK 0x00080000L
+#define VGT_DEBUG_REG16__indx_valid_r0_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG16__indx_valid_r1_q_MASK 0x00020000L
+#define VGT_DEBUG_REG16__indx_valid_r1_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG16__indx_valid_r2_q_MASK 0x00002000L
+#define VGT_DEBUG_REG16__indx_valid_r2_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG16__multiple_streams_en_r1_q_MASK 0x10000000L
+#define VGT_DEBUG_REG16__multiple_streams_en_r1_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG16__new_vs_thread_r2_MASK 0x80000000L
+#define VGT_DEBUG_REG16__new_vs_thread_r2__SHIFT 0x0000001f
+#define VGT_DEBUG_REG16__num_gs_r2_q_not_0_MASK 0x40000000L
+#define VGT_DEBUG_REG16__num_gs_r2_q_not_0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG16__prim_valid_r0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG16__prim_valid_r0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG16__prim_valid_r1_q_MASK 0x00010000L
+#define VGT_DEBUG_REG16__prim_valid_r1_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG16__prim_valid_r2_q_MASK 0x00004000L
+#define VGT_DEBUG_REG16__prim_valid_r2_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG16__r0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG16__r0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG16__r1_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG16__r1_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG16__r1_upstream_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG16__r1_upstream_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG16__r2_indx_rtr_MASK 0x00000200L
+#define VGT_DEBUG_REG16__r2_indx_rtr__SHIFT 0x00000009
+#define VGT_DEBUG_REG16__r2_prim_rtr_MASK 0x00000100L
+#define VGT_DEBUG_REG16__r2_prim_rtr__SHIFT 0x00000008
+#define VGT_DEBUG_REG16__r2_rtr_MASK 0x00000400L
+#define VGT_DEBUG_REG16__r2_rtr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG16__r2_vs_tbl_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG16__r2_vs_tbl_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG16__r3_force_vs_tbl_we_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG16__r3_force_vs_tbl_we_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG16__send_event_q_MASK 0x00400000L
+#define VGT_DEBUG_REG16__send_event_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG16__SPARE24_MASK 0x01800000L
+#define VGT_DEBUG_REG16__SPARE24__SHIFT 0x00000017
+#define VGT_DEBUG_REG16__valid_r0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG16__valid_r0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG16__valid_r1_q_MASK 0x00040000L
+#define VGT_DEBUG_REG16__valid_r1_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG16__valid_r2_q_MASK 0x00008000L
+#define VGT_DEBUG_REG16__valid_r2_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG16__vert_seen_since_sopg_r2_q_MASK 0x01000000L
+#define VGT_DEBUG_REG16__vert_seen_since_sopg_r2_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG16__vs_vert_count_r2_q_not_0_MASK 0x20000000L
+#define VGT_DEBUG_REG16__vs_vert_count_r2_q_not_0__SHIFT 0x0000001d
+#define VGT_DEBUG_REG17__gog_out_indx_13_0_MASK 0xfffc0000L
+#define VGT_DEBUG_REG17__gog_out_indx_13_0__SHIFT 0x00000012
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx0_5_0_MASK 0x0003f000L
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx0_5_0__SHIFT 0x0000000c
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx1_5_0_MASK 0x00000fc0L
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx1_5_0__SHIFT 0x00000006
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx2_5_0_MASK 0x0000003fL
+#define VGT_DEBUG_REG17__gog_out_prim_rel_indx2_5_0__SHIFT 0x00000000
+#define VGT_DEBUG_REG18__components_valid_r0_q_MASK 0xe0000000L
+#define VGT_DEBUG_REG18__components_valid_r0_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG18__eject_vtx_vect_r1_d_MASK 0x00800000L
+#define VGT_DEBUG_REG18__eject_vtx_vect_r1_d__SHIFT 0x00000017
+#define VGT_DEBUG_REG18__eop_r0_q_MASK 0x00400000L
+#define VGT_DEBUG_REG18__eop_r0_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG18__grp_vr_valid_MASK 0x00000001L
+#define VGT_DEBUG_REG18__grp_vr_valid__SHIFT 0x00000000
+#define VGT_DEBUG_REG18__gs_scenario_a_r0_q_MASK 0x08000000L
+#define VGT_DEBUG_REG18__gs_scenario_a_r0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG18__gs_scenario_b_r0_q_MASK 0x10000000L
+#define VGT_DEBUG_REG18__gs_scenario_b_r0_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG18__indices_to_send_q_MASK 0x00000700L
+#define VGT_DEBUG_REG18__indices_to_send_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG18__indx0_hit_d_MASK 0x00040000L
+#define VGT_DEBUG_REG18__indx0_hit_d__SHIFT 0x00000012
+#define VGT_DEBUG_REG18__indx0_new_d_MASK 0x00002000L
+#define VGT_DEBUG_REG18__indx0_new_d__SHIFT 0x0000000d
+#define VGT_DEBUG_REG18__indx1_hit_d_MASK 0x00020000L
+#define VGT_DEBUG_REG18__indx1_hit_d__SHIFT 0x00000011
+#define VGT_DEBUG_REG18__indx1_new_d_MASK 0x00004000L
+#define VGT_DEBUG_REG18__indx1_new_d__SHIFT 0x0000000e
+#define VGT_DEBUG_REG18__indx2_hit_d_MASK 0x00010000L
+#define VGT_DEBUG_REG18__indx2_hit_d__SHIFT 0x00000010
+#define VGT_DEBUG_REG18__indx2_new_d_MASK 0x00008000L
+#define VGT_DEBUG_REG18__indx2_new_d__SHIFT 0x0000000f
+#define VGT_DEBUG_REG18__last_group_of_instance_r0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG18__last_group_of_instance_r0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG18__last_indx_of_prim_MASK 0x00001000L
+#define VGT_DEBUG_REG18__last_indx_of_prim__SHIFT 0x0000000c
+#define VGT_DEBUG_REG18__null_primitive_r0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG18__null_primitive_r0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG18__out_vr_indx_read_MASK 0x00000040L
+#define VGT_DEBUG_REG18__out_vr_indx_read__SHIFT 0x00000006
+#define VGT_DEBUG_REG18__out_vr_prim_read_MASK 0x00000080L
+#define VGT_DEBUG_REG18__out_vr_prim_read__SHIFT 0x00000007
+#define VGT_DEBUG_REG18__pipe0_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG18__pipe0_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG18__pipe0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG18__pipe0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG18__pipe1_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG18__pipe1_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG18__pipe1_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG18__pipe1_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG18__st_vertex_reuse_off_r0_q_MASK 0x00080000L
+#define VGT_DEBUG_REG18__st_vertex_reuse_off_r0_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG18__sub_prim_type_r0_q_MASK 0x07000000L
+#define VGT_DEBUG_REG18__sub_prim_type_r0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG18__valid_indices_MASK 0x00000800L
+#define VGT_DEBUG_REG18__valid_indices__SHIFT 0x0000000b
+#define VGT_DEBUG_REG18__vr_grp_read_MASK 0x00000008L
+#define VGT_DEBUG_REG18__vr_grp_read__SHIFT 0x00000003
+#define VGT_DEBUG_REG19__buffered_prim_eject_vtx_vect_MASK 0x00080000L
+#define VGT_DEBUG_REG19__buffered_prim_eject_vtx_vect__SHIFT 0x00000013
+#define VGT_DEBUG_REG19__buffered_prim_eop_MASK 0x00040000L
+#define VGT_DEBUG_REG19__buffered_prim_eop__SHIFT 0x00000012
+#define VGT_DEBUG_REG19__buffered_prim_event_MASK 0x00010000L
+#define VGT_DEBUG_REG19__buffered_prim_event__SHIFT 0x00000010
+#define VGT_DEBUG_REG19__buffered_prim_null_primitive_MASK 0x00020000L
+#define VGT_DEBUG_REG19__buffered_prim_null_primitive__SHIFT 0x00000011
+#define VGT_DEBUG_REG19__buffered_prim_type_event_MASK 0x03f00000L
+#define VGT_DEBUG_REG19__buffered_prim_type_event__SHIFT 0x00000014
+#define VGT_DEBUG_REG19__filter_event_MASK 0x80000000L
+#define VGT_DEBUG_REG19__filter_event__SHIFT 0x0000001f
+#define VGT_DEBUG_REG19__hold_prim_MASK 0x00000800L
+#define VGT_DEBUG_REG19__hold_prim__SHIFT 0x0000000b
+#define VGT_DEBUG_REG19__new_packet_q_MASK 0x00008000L
+#define VGT_DEBUG_REG19__new_packet_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG19__null_terminate_vtx_vector_MASK 0x40000000L
+#define VGT_DEBUG_REG19__null_terminate_vtx_vector__SHIFT 0x0000001e
+#define VGT_DEBUG_REG19__num_new_unique_rel_indx_MASK 0x30000000L
+#define VGT_DEBUG_REG19__num_new_unique_rel_indx__SHIFT 0x0000001c
+#define VGT_DEBUG_REG19__pa_clipp_fifo_busy_q_MASK 0x00000020L
+#define VGT_DEBUG_REG19__pa_clipp_fifo_busy_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG19__pa_clips_fifo_busy_q_MASK 0x00000010L
+#define VGT_DEBUG_REG19__pa_clips_fifo_busy_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG19__pa_clipv_fifo_busy_q_MASK 0x00000400L
+#define VGT_DEBUG_REG19__pa_clipv_fifo_busy_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG19__prim_buffer_empty_MASK 0x00000004L
+#define VGT_DEBUG_REG19__prim_buffer_empty__SHIFT 0x00000002
+#define VGT_DEBUG_REG19__prim_buffer_full_MASK 0x00000008L
+#define VGT_DEBUG_REG19__prim_buffer_full__SHIFT 0x00000003
+#define VGT_DEBUG_REG19__separate_out_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG19__separate_out_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG19__separate_out_indx_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG19__separate_out_indx_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG19__spi_vsthread_fifo_busy_q_MASK 0x00000100L
+#define VGT_DEBUG_REG19__spi_vsthread_fifo_busy_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG19__spi_vsvert_fifo_busy_q_MASK 0x00000200L
+#define VGT_DEBUG_REG19__spi_vsvert_fifo_busy_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG19__VGT_PA_clipp_rtr_q_MASK 0x00000080L
+#define VGT_DEBUG_REG19__VGT_PA_clipp_rtr_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG19__VGT_PA_clips_rtr_q_MASK 0x00000040L
+#define VGT_DEBUG_REG19__VGT_PA_clips_rtr_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG19__VGT_PA_clipv_rtr_q_MASK 0x00004000L
+#define VGT_DEBUG_REG19__VGT_PA_clipv_rtr_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vsvert_rtr_q_MASK 0x08000000L
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vsvert_rtr_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vswave_rtr_q_MASK 0x04000000L
+#define VGT_DEBUG_REG19__VGT_SE1SPI_vswave_rtr_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG19__VGT_SPI_vsthread_rtr_q_MASK 0x00001000L
+#define VGT_DEBUG_REG19__VGT_SPI_vsthread_rtr_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG19__VGT_SPI_vsvert_rtr_q_MASK 0x00002000L
+#define VGT_DEBUG_REG19__VGT_SPI_vsvert_rtr_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG1__gog_out_indx_valid_MASK 0x10000000L
+#define VGT_DEBUG_REG1__gog_out_indx_valid__SHIFT 0x0000001c
+#define VGT_DEBUG_REG1__gog_out_prim_valid_MASK 0x40000000L
+#define VGT_DEBUG_REG1__gog_out_prim_valid__SHIFT 0x0000001e
+#define VGT_DEBUG_REG1__gs_pi_read_MASK 0x08000000L
+#define VGT_DEBUG_REG1__gs_pi_read__SHIFT 0x0000001b
+#define VGT_DEBUG_REG1__out_indx_read_MASK 0x20000000L
+#define VGT_DEBUG_REG1__out_indx_read__SHIFT 0x0000001d
+#define VGT_DEBUG_REG1__out_prim_read_MASK 0x80000000L
+#define VGT_DEBUG_REG1__out_prim_read__SHIFT 0x0000001f
+#define VGT_DEBUG_REG1__pi_gs_valid_MASK 0x04000000L
+#define VGT_DEBUG_REG1__pi_gs_valid__SHIFT 0x0000001a
+#define VGT_DEBUG_REG1__pi_pt_valid_MASK 0x00001000L
+#define VGT_DEBUG_REG1__pi_pt_valid__SHIFT 0x0000000c
+#define VGT_DEBUG_REG1__pi_te_valid_MASK 0x00004000L
+#define VGT_DEBUG_REG1__pi_te_valid__SHIFT 0x0000000e
+#define VGT_DEBUG_REG1__pi_vr_valid_MASK 0x00000400L
+#define VGT_DEBUG_REG1__pi_vr_valid__SHIFT 0x0000000a
+#define VGT_DEBUG_REG1__pt_out_indx_valid_MASK 0x00100000L
+#define VGT_DEBUG_REG1__pt_out_indx_valid__SHIFT 0x00000014
+#define VGT_DEBUG_REG1__pt_out_prim_valid_MASK 0x00400000L
+#define VGT_DEBUG_REG1__pt_out_prim_valid__SHIFT 0x00000016
+#define VGT_DEBUG_REG1__pt_pi_read_MASK 0x00002000L
+#define VGT_DEBUG_REG1__pt_pi_read__SHIFT 0x0000000d
+#define VGT_DEBUG_REG1__SPARE0_MASK 0x00000200L
+#define VGT_DEBUG_REG1__SPARE0__SHIFT 0x00000009
+#define VGT_DEBUG_REG1__SPARE10_MASK 0x00200000L
+#define VGT_DEBUG_REG1__SPARE10__SHIFT 0x00000015
+#define VGT_DEBUG_REG1__SPARE11_MASK 0x00080000L
+#define VGT_DEBUG_REG1__SPARE11__SHIFT 0x00000013
+#define VGT_DEBUG_REG1__SPARE12_MASK 0x00020000L
+#define VGT_DEBUG_REG1__SPARE12__SHIFT 0x00000011
+#define VGT_DEBUG_REG1__SPARE1_MASK 0x00000100L
+#define VGT_DEBUG_REG1__SPARE1__SHIFT 0x00000008
+#define VGT_DEBUG_REG1__SPARE23_MASK 0x00800000L
+#define VGT_DEBUG_REG1__SPARE23__SHIFT 0x00000017
+#define VGT_DEBUG_REG1__SPARE25_MASK 0x02000000L
+#define VGT_DEBUG_REG1__SPARE25__SHIFT 0x00000019
+#define VGT_DEBUG_REG1__SPARE2_MASK 0x00000080L
+#define VGT_DEBUG_REG1__SPARE2__SHIFT 0x00000007
+#define VGT_DEBUG_REG1__SPARE3_MASK 0x00000040L
+#define VGT_DEBUG_REG1__SPARE3__SHIFT 0x00000006
+#define VGT_DEBUG_REG1__SPARE4_MASK 0x00000020L
+#define VGT_DEBUG_REG1__SPARE4__SHIFT 0x00000005
+#define VGT_DEBUG_REG1__SPARE5_MASK 0x00000010L
+#define VGT_DEBUG_REG1__SPARE5__SHIFT 0x00000004
+#define VGT_DEBUG_REG1__SPARE6_MASK 0x00000008L
+#define VGT_DEBUG_REG1__SPARE6__SHIFT 0x00000003
+#define VGT_DEBUG_REG1__SPARE7_MASK 0x00000004L
+#define VGT_DEBUG_REG1__SPARE7__SHIFT 0x00000002
+#define VGT_DEBUG_REG1__SPARE8_MASK 0x00000002L
+#define VGT_DEBUG_REG1__SPARE8__SHIFT 0x00000001
+#define VGT_DEBUG_REG1__SPARE9_MASK 0x00000001L
+#define VGT_DEBUG_REG1__SPARE9__SHIFT 0x00000000
+#define VGT_DEBUG_REG1__te_grp_read_MASK 0x00008000L
+#define VGT_DEBUG_REG1__te_grp_read__SHIFT 0x0000000f
+#define VGT_DEBUG_REG1__te_out_data_valid_MASK 0x01000000L
+#define VGT_DEBUG_REG1__te_out_data_valid__SHIFT 0x00000018
+#define VGT_DEBUG_REG1__vr_out_indx_valid_MASK 0x00010000L
+#define VGT_DEBUG_REG1__vr_out_indx_valid__SHIFT 0x00000010
+#define VGT_DEBUG_REG1__vr_out_prim_valid_MASK 0x00040000L
+#define VGT_DEBUG_REG1__vr_out_prim_valid__SHIFT 0x00000012
+#define VGT_DEBUG_REG1__vr_pi_read_MASK 0x00000800L
+#define VGT_DEBUG_REG1__vr_pi_read__SHIFT 0x0000000b
+#define VGT_DEBUG_REG20__alloc_counter_q_MASK 0x003c0000L
+#define VGT_DEBUG_REG20__alloc_counter_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG20__curr_dealloc_distance_q_MASK 0x1fc00000L
+#define VGT_DEBUG_REG20__curr_dealloc_distance_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG20__curr_slot_in_vtx_vect_q_not_0_MASK 0x40000000L
+#define VGT_DEBUG_REG20__curr_slot_in_vtx_vect_q_not_0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexcount_not_0_MASK 0x00010000L
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexcount_not_0__SHIFT 0x00000010
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexindex_MASK 0x0000ffffL
+#define VGT_DEBUG_REG20__dbg_VGT_SPI_vsthread_sovertexindex__SHIFT 0x00000000
+#define VGT_DEBUG_REG20__int_vtx_counter_q_not_0_MASK 0x80000000L
+#define VGT_DEBUG_REG20__int_vtx_counter_q_not_0__SHIFT 0x0000001f
+#define VGT_DEBUG_REG20__new_allocate_q_MASK 0x20000000L
+#define VGT_DEBUG_REG20__new_allocate_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG20__SPARE17_MASK 0x00020000L
+#define VGT_DEBUG_REG20__SPARE17__SHIFT 0x00000011
+#define VGT_DEBUG_REG21__buff_full_p1_MASK 0x01000000L
+#define VGT_DEBUG_REG21__buff_full_p1__SHIFT 0x00000018
+#define VGT_DEBUG_REG21__eopg_p0_q_MASK 0x40000000L
+#define VGT_DEBUG_REG21__eopg_p0_q__SHIFT 0x0000001e
+#define VGT_DEBUG_REG21__eotg_r2_q_MASK 0x04000000L
+#define VGT_DEBUG_REG21__eotg_r2_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG21__full_state_p1_q_MASK 0x00008000L
+#define VGT_DEBUG_REG21__full_state_p1_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG21__indx_count_q_not_0_MASK 0x00002000L
+#define VGT_DEBUG_REG21__indx_count_q_not_0__SHIFT 0x0000000d
+#define VGT_DEBUG_REG21__indx_side_fifo_empty_MASK 0x00000002L
+#define VGT_DEBUG_REG21__indx_side_fifo_empty__SHIFT 0x00000001
+#define VGT_DEBUG_REG21__indx_side_fifo_full_MASK 0x00000080L
+#define VGT_DEBUG_REG21__indx_side_fifo_full__SHIFT 0x00000007
+#define VGT_DEBUG_REG21__indx_side_indx_valid_MASK 0x00010000L
+#define VGT_DEBUG_REG21__indx_side_indx_valid__SHIFT 0x00000010
+#define VGT_DEBUG_REG21__interfaces_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG21__interfaces_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG21__is_event_p0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG21__is_event_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG21__lshs_dealloc_p1_MASK 0x00200000L
+#define VGT_DEBUG_REG21__lshs_dealloc_p1__SHIFT 0x00000015
+#define VGT_DEBUG_REG21__null_r2_q_MASK 0x08000000L
+#define VGT_DEBUG_REG21__null_r2_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG21__out_indx_fifo_empty_MASK 0x00000001L
+#define VGT_DEBUG_REG21__out_indx_fifo_empty__SHIFT 0x00000000
+#define VGT_DEBUG_REG21__out_indx_fifo_full_MASK 0x00000040L
+#define VGT_DEBUG_REG21__out_indx_fifo_full__SHIFT 0x00000006
+#define VGT_DEBUG_REG21__p0_dr_MASK 0x10000000L
+#define VGT_DEBUG_REG21__p0_dr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG21__p0_nobp_MASK 0x80000000L
+#define VGT_DEBUG_REG21__p0_nobp__SHIFT 0x0000001f
+#define VGT_DEBUG_REG21__p0_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG21__p0_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG21__pipe0_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG21__pipe0_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG21__pipe0_rtr_MASK 0x00000100L
+#define VGT_DEBUG_REG21__pipe0_rtr__SHIFT 0x00000008
+#define VGT_DEBUG_REG21__pipe1_dr_MASK 0x00000008L
+#define VGT_DEBUG_REG21__pipe1_dr__SHIFT 0x00000003
+#define VGT_DEBUG_REG21__pipe1_rtr_MASK 0x00000200L
+#define VGT_DEBUG_REG21__pipe1_rtr__SHIFT 0x00000009
+#define VGT_DEBUG_REG21__pipe2_dr_MASK 0x00000010L
+#define VGT_DEBUG_REG21__pipe2_dr__SHIFT 0x00000004
+#define VGT_DEBUG_REG21__pipe2_rtr_MASK 0x00000400L
+#define VGT_DEBUG_REG21__pipe2_rtr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG21__stateid_p0_q_MASK 0x000e0000L
+#define VGT_DEBUG_REG21__stateid_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG21__stream_id_r2_q_MASK 0x00400000L
+#define VGT_DEBUG_REG21__stream_id_r2_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG21__strmout_valid_p1_MASK 0x02000000L
+#define VGT_DEBUG_REG21__strmout_valid_p1__SHIFT 0x00000019
+#define VGT_DEBUG_REG21__vsthread_buff_empty_MASK 0x00000020L
+#define VGT_DEBUG_REG21__vsthread_buff_empty__SHIFT 0x00000005
+#define VGT_DEBUG_REG21__vsthread_buff_full_MASK 0x00000800L
+#define VGT_DEBUG_REG21__vsthread_buff_full__SHIFT 0x0000000b
+#define VGT_DEBUG_REG21__vtx_vect_counter_q_not_0_MASK 0x00800000L
+#define VGT_DEBUG_REG21__vtx_vect_counter_q_not_0__SHIFT 0x00000017
+#define VGT_DEBUG_REG21__wait_for_external_eopg_q_MASK 0x00004000L
+#define VGT_DEBUG_REG21__wait_for_external_eopg_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG22__cm_state16_MASK 0x00000003L
+#define VGT_DEBUG_REG22__cm_state16__SHIFT 0x00000000
+#define VGT_DEBUG_REG22__cm_state17_MASK 0x0000000cL
+#define VGT_DEBUG_REG22__cm_state17__SHIFT 0x00000002
+#define VGT_DEBUG_REG22__cm_state18_MASK 0x00000030L
+#define VGT_DEBUG_REG22__cm_state18__SHIFT 0x00000004
+#define VGT_DEBUG_REG22__cm_state19_MASK 0x000000c0L
+#define VGT_DEBUG_REG22__cm_state19__SHIFT 0x00000006
+#define VGT_DEBUG_REG22__cm_state20_MASK 0x00000300L
+#define VGT_DEBUG_REG22__cm_state20__SHIFT 0x00000008
+#define VGT_DEBUG_REG22__cm_state21_MASK 0x00000c00L
+#define VGT_DEBUG_REG22__cm_state21__SHIFT 0x0000000a
+#define VGT_DEBUG_REG22__cm_state22_MASK 0x00003000L
+#define VGT_DEBUG_REG22__cm_state22__SHIFT 0x0000000c
+#define VGT_DEBUG_REG22__cm_state23_MASK 0x0000c000L
+#define VGT_DEBUG_REG22__cm_state23__SHIFT 0x0000000e
+#define VGT_DEBUG_REG22__cm_state24_MASK 0x00030000L
+#define VGT_DEBUG_REG22__cm_state24__SHIFT 0x00000010
+#define VGT_DEBUG_REG22__cm_state25_MASK 0x000c0000L
+#define VGT_DEBUG_REG22__cm_state25__SHIFT 0x00000012
+#define VGT_DEBUG_REG22__cm_state26_MASK 0x00300000L
+#define VGT_DEBUG_REG22__cm_state26__SHIFT 0x00000014
+#define VGT_DEBUG_REG22__cm_state27_MASK 0x00c00000L
+#define VGT_DEBUG_REG22__cm_state27__SHIFT 0x00000016
+#define VGT_DEBUG_REG22__cm_state28_MASK 0x03000000L
+#define VGT_DEBUG_REG22__cm_state28__SHIFT 0x00000018
+#define VGT_DEBUG_REG22__cm_state29_MASK 0x0c000000L
+#define VGT_DEBUG_REG22__cm_state29__SHIFT 0x0000001a
+#define VGT_DEBUG_REG22__cm_state30_MASK 0x30000000L
+#define VGT_DEBUG_REG22__cm_state30__SHIFT 0x0000001c
+#define VGT_DEBUG_REG22__cm_state31_MASK 0xc0000000L
+#define VGT_DEBUG_REG22__cm_state31__SHIFT 0x0000001e
+#define VGT_DEBUG_REG23__frmt_busy_MASK 0x00000001L
+#define VGT_DEBUG_REG23__frmt_busy__SHIFT 0x00000000
+#define VGT_DEBUG_REG23__new_verts_r2_q_MASK 0x00018000L
+#define VGT_DEBUG_REG23__new_verts_r2_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG23__prim_dr_r2_q_MASK 0x00001000L
+#define VGT_DEBUG_REG23__prim_dr_r2_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG23__prim_fifo_empty_MASK 0x00000200L
+#define VGT_DEBUG_REG23__prim_fifo_empty__SHIFT 0x00000009
+#define VGT_DEBUG_REG23__prim_fifo_full_MASK 0x00000400L
+#define VGT_DEBUG_REG23__prim_fifo_full__SHIFT 0x0000000a
+#define VGT_DEBUG_REG23__prim_r2_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG23__prim_r2_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG23__prim_r3_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG23__prim_r3_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG23__prim_state_sel_r2_q_MASK 0x00e00000L
+#define VGT_DEBUG_REG23__prim_state_sel_r2_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG23__rcm_frmt_prim_rtr_MASK 0x00000004L
+#define VGT_DEBUG_REG23__rcm_frmt_prim_rtr__SHIFT 0x00000002
+#define VGT_DEBUG_REG23__rcm_frmt_vert_rtr_MASK 0x00000002L
+#define VGT_DEBUG_REG23__rcm_frmt_vert_rtr__SHIFT 0x00000001
+#define VGT_DEBUG_REG23__SPARE_MASK 0xff000000L
+#define VGT_DEBUG_REG23__SPARE__SHIFT 0x00000018
+#define VGT_DEBUG_REG23__vert_dr_r0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG23__vert_dr_r0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG23__vert_dr_r1_q_MASK 0x00002000L
+#define VGT_DEBUG_REG23__vert_dr_r1_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG23__vert_dr_r2_q_MASK 0x00000800L
+#define VGT_DEBUG_REG23__vert_dr_r2_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG23__vert_r0_rtr_MASK 0x00000100L
+#define VGT_DEBUG_REG23__vert_r0_rtr__SHIFT 0x00000008
+#define VGT_DEBUG_REG23__vert_r1_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG23__vert_r1_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG23__vert_r2_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG23__vert_r2_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG23__vert_r3_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG23__vert_r3_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG23__verts_sent_r2_q_MASK 0x001e0000L
+#define VGT_DEBUG_REG23__verts_sent_r2_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG24__avail_es_rb_space_r0_q_23_0_MASK 0x00ffffffL
+#define VGT_DEBUG_REG24__avail_es_rb_space_r0_q_23_0__SHIFT 0x00000000
+#define VGT_DEBUG_REG24__dependent_st_cut_mode_q_MASK 0x03000000L
+#define VGT_DEBUG_REG24__dependent_st_cut_mode_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG24__SPARE31_MASK 0xfc000000L
+#define VGT_DEBUG_REG24__SPARE31__SHIFT 0x0000001a
+#define VGT_DEBUG_REG25__active_sm_r0_q_MASK 0x3c000000L
+#define VGT_DEBUG_REG25__active_sm_r0_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG25__add_gs_rb_space_r0_q_MASK 0x80000000L
+#define VGT_DEBUG_REG25__add_gs_rb_space_r0_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG25__add_gs_rb_space_r1_q_MASK 0x40000000L
+#define VGT_DEBUG_REG25__add_gs_rb_space_r1_q__SHIFT 0x0000001e
+#define VGT_DEBUG_REG25__avail_gs_rb_space_r0_q_25_0_MASK 0x03ffffffL
+#define VGT_DEBUG_REG25__avail_gs_rb_space_r0_q_25_0__SHIFT 0x00000000
+#define VGT_DEBUG_REG26__cm_state0_MASK 0x00000003L
+#define VGT_DEBUG_REG26__cm_state0__SHIFT 0x00000000
+#define VGT_DEBUG_REG26__cm_state10_MASK 0x00300000L
+#define VGT_DEBUG_REG26__cm_state10__SHIFT 0x00000014
+#define VGT_DEBUG_REG26__cm_state11_MASK 0x00c00000L
+#define VGT_DEBUG_REG26__cm_state11__SHIFT 0x00000016
+#define VGT_DEBUG_REG26__cm_state12_MASK 0x03000000L
+#define VGT_DEBUG_REG26__cm_state12__SHIFT 0x00000018
+#define VGT_DEBUG_REG26__cm_state13_MASK 0x0c000000L
+#define VGT_DEBUG_REG26__cm_state13__SHIFT 0x0000001a
+#define VGT_DEBUG_REG26__cm_state14_MASK 0x30000000L
+#define VGT_DEBUG_REG26__cm_state14__SHIFT 0x0000001c
+#define VGT_DEBUG_REG26__cm_state15_MASK 0xc0000000L
+#define VGT_DEBUG_REG26__cm_state15__SHIFT 0x0000001e
+#define VGT_DEBUG_REG26__cm_state1_MASK 0x0000000cL
+#define VGT_DEBUG_REG26__cm_state1__SHIFT 0x00000002
+#define VGT_DEBUG_REG26__cm_state2_MASK 0x00000030L
+#define VGT_DEBUG_REG26__cm_state2__SHIFT 0x00000004
+#define VGT_DEBUG_REG26__cm_state3_MASK 0x000000c0L
+#define VGT_DEBUG_REG26__cm_state3__SHIFT 0x00000006
+#define VGT_DEBUG_REG26__cm_state4_MASK 0x00000300L
+#define VGT_DEBUG_REG26__cm_state4__SHIFT 0x00000008
+#define VGT_DEBUG_REG26__cm_state5_MASK 0x00000c00L
+#define VGT_DEBUG_REG26__cm_state5__SHIFT 0x0000000a
+#define VGT_DEBUG_REG26__cm_state6_MASK 0x00003000L
+#define VGT_DEBUG_REG26__cm_state6__SHIFT 0x0000000c
+#define VGT_DEBUG_REG26__cm_state7_MASK 0x0000c000L
+#define VGT_DEBUG_REG26__cm_state7__SHIFT 0x0000000e
+#define VGT_DEBUG_REG26__cm_state8_MASK 0x00030000L
+#define VGT_DEBUG_REG26__cm_state8__SHIFT 0x00000010
+#define VGT_DEBUG_REG26__cm_state9_MASK 0x000c0000L
+#define VGT_DEBUG_REG26__cm_state9__SHIFT 0x00000012
+#define VGT_DEBUG_REG27__eop_p1_q_MASK 0x00000800L
+#define VGT_DEBUG_REG27__eop_p1_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG27__event_flag_p1_q_MASK 0x00000400L
+#define VGT_DEBUG_REG27__event_flag_p1_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG27__first_vsprim_of_gsprim_p0_q_MASK 0x00080000L
+#define VGT_DEBUG_REG27__first_vsprim_of_gsprim_p0_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG27__gsc0_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG27__gsc0_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG27__gsc0_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG27__gsc0_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG27__gsc_2cycle_output_MASK 0x00010000L
+#define VGT_DEBUG_REG27__gsc_2cycle_output__SHIFT 0x00000010
+#define VGT_DEBUG_REG27__gsc_2nd_cycle_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG27__gsc_2nd_cycle_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG27__gsc_eop_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG27__gsc_eop_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG27__gsc_indx_count_p0_q_MASK 0x7ff00000L
+#define VGT_DEBUG_REG27__gsc_indx_count_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG27__gsc_null_primitive_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG27__gsc_null_primitive_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG27__gs_out_prim_type_p0_q_MASK 0x00003000L
+#define VGT_DEBUG_REG27__gs_out_prim_type_p0_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG27__indices_to_send_p0_q_MASK 0x00000300L
+#define VGT_DEBUG_REG27__indices_to_send_p0_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG27__last_indx_of_prim_p1_q_MASK 0x00000080L
+#define VGT_DEBUG_REG27__last_indx_of_prim_p1_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG27__last_indx_of_vsprim_MASK 0x00040000L
+#define VGT_DEBUG_REG27__last_indx_of_vsprim__SHIFT 0x00000012
+#define VGT_DEBUG_REG27__last_vsprim_of_gsprim_MASK 0x80000000L
+#define VGT_DEBUG_REG27__last_vsprim_of_gsprim__SHIFT 0x0000001f
+#define VGT_DEBUG_REG27__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG27__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG27__pipe0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG27__pipe0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG27__pipe1_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG27__pipe1_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG27__pipe1_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG27__pipe1_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG27__tm_pt_event_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG27__tm_pt_event_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG28__advance_inner_point_p1_MASK 0x00800000L
+#define VGT_DEBUG_REG28__advance_inner_point_p1__SHIFT 0x00000017
+#define VGT_DEBUG_REG28__advance_outer_point_p1_MASK 0x00400000L
+#define VGT_DEBUG_REG28__advance_outer_point_p1__SHIFT 0x00000016
+#define VGT_DEBUG_REG28__con_state_q_MASK 0x0000000fL
+#define VGT_DEBUG_REG28__con_state_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG28__first_ring_of_patch_p0_q_MASK 0x00010000L
+#define VGT_DEBUG_REG28__first_ring_of_patch_p0_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG28__last_edge_of_outer_ring_p0_q_MASK 0x00040000L
+#define VGT_DEBUG_REG28__last_edge_of_outer_ring_p0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG28__last_point_of_inner_ring_p1_MASK 0x00100000L
+#define VGT_DEBUG_REG28__last_point_of_inner_ring_p1__SHIFT 0x00000014
+#define VGT_DEBUG_REG28__last_point_of_outer_ring_p1_MASK 0x00080000L
+#define VGT_DEBUG_REG28__last_point_of_outer_ring_p1__SHIFT 0x00000013
+#define VGT_DEBUG_REG28__last_ring_of_patch_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG28__last_ring_of_patch_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG28__next_ring_is_rect_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG28__next_ring_is_rect_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG28__outer_edge_tf_eq_one_p0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG28__outer_edge_tf_eq_one_p0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG28__outer_parity_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG28__outer_parity_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG28__parallel_parity_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG28__parallel_parity_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG28__pipe0_edge_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG28__pipe0_edge_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG28__pipe0_edge_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG28__pipe0_edge_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG28__pipe0_patch_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG28__pipe0_patch_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG28__pipe0_patch_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG28__pipe0_patch_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG28__pipe1_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG28__pipe1_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG28__pipe1_edge_rtr_MASK 0x40000000L
+#define VGT_DEBUG_REG28__pipe1_edge_rtr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG28__pipe1_inner1_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG28__pipe1_inner1_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG28__pipe1_inner2_rtr_MASK 0x10000000L
+#define VGT_DEBUG_REG28__pipe1_inner2_rtr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG28__pipe1_outer1_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG28__pipe1_outer1_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG28__pipe1_outer2_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG28__pipe1_outer2_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG28__pipe1_patch_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG28__pipe1_patch_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG28__pipe1_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG28__pipe1_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG28__process_tri_1st_2nd_half_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG28__process_tri_1st_2nd_half_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG28__process_tri_center_poly_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG28__process_tri_center_poly_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG28__process_tri_middle_p0_q_MASK 0x00000020L
+#define VGT_DEBUG_REG28__process_tri_middle_p0_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG28__second_cycle_q_MASK 0x00000010L
+#define VGT_DEBUG_REG28__second_cycle_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG28__use_stored_inner_q_ring2_MASK 0x80000000L
+#define VGT_DEBUG_REG28__use_stored_inner_q_ring2__SHIFT 0x0000001f
+#define VGT_DEBUG_REG29__advance_inner_point_p1_MASK 0x00800000L
+#define VGT_DEBUG_REG29__advance_inner_point_p1__SHIFT 0x00000017
+#define VGT_DEBUG_REG29__advance_outer_point_p1_MASK 0x00400000L
+#define VGT_DEBUG_REG29__advance_outer_point_p1__SHIFT 0x00000016
+#define VGT_DEBUG_REG29__con_state_q_MASK 0x0000000fL
+#define VGT_DEBUG_REG29__con_state_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG29__first_ring_of_patch_p0_q_MASK 0x00010000L
+#define VGT_DEBUG_REG29__first_ring_of_patch_p0_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG29__last_edge_of_outer_ring_p0_q_MASK 0x00040000L
+#define VGT_DEBUG_REG29__last_edge_of_outer_ring_p0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG29__last_point_of_inner_ring_p1_MASK 0x00100000L
+#define VGT_DEBUG_REG29__last_point_of_inner_ring_p1__SHIFT 0x00000014
+#define VGT_DEBUG_REG29__last_point_of_outer_ring_p1_MASK 0x00080000L
+#define VGT_DEBUG_REG29__last_point_of_outer_ring_p1__SHIFT 0x00000013
+#define VGT_DEBUG_REG29__last_ring_of_patch_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG29__last_ring_of_patch_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG29__next_ring_is_rect_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG29__next_ring_is_rect_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG29__outer_edge_tf_eq_one_p0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG29__outer_edge_tf_eq_one_p0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG29__outer_parity_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG29__outer_parity_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG29__parallel_parity_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG29__parallel_parity_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG29__pipe0_edge_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG29__pipe0_edge_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG29__pipe0_edge_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG29__pipe0_edge_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG29__pipe0_patch_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG29__pipe0_patch_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG29__pipe0_patch_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG29__pipe0_patch_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG29__pipe1_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG29__pipe1_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG29__pipe1_edge_rtr_MASK 0x40000000L
+#define VGT_DEBUG_REG29__pipe1_edge_rtr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG29__pipe1_inner1_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG29__pipe1_inner1_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG29__pipe1_inner2_rtr_MASK 0x10000000L
+#define VGT_DEBUG_REG29__pipe1_inner2_rtr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG29__pipe1_outer1_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG29__pipe1_outer1_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG29__pipe1_outer2_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG29__pipe1_outer2_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG29__pipe1_patch_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG29__pipe1_patch_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG29__pipe1_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG29__pipe1_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG29__process_tri_1st_2nd_half_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG29__process_tri_1st_2nd_half_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG29__process_tri_center_poly_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG29__process_tri_center_poly_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG29__process_tri_middle_p0_q_MASK 0x00000020L
+#define VGT_DEBUG_REG29__process_tri_middle_p0_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG29__second_cycle_q_MASK 0x00000010L
+#define VGT_DEBUG_REG29__second_cycle_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG29__use_stored_inner_q_ring3_MASK 0x80000000L
+#define VGT_DEBUG_REG29__use_stored_inner_q_ring3__SHIFT 0x0000001f
+#define VGT_DEBUG_REG2__grpModBusy_MASK 0x00000080L
+#define VGT_DEBUG_REG2__grpModBusy__SHIFT 0x00000007
+#define VGT_DEBUG_REG2__hs_grp_busy_MASK 0x00000001L
+#define VGT_DEBUG_REG2__hs_grp_busy__SHIFT 0x00000000
+#define VGT_DEBUG_REG2__hsInputFifoEmpty_MASK 0x00001000L
+#define VGT_DEBUG_REG2__hsInputFifoEmpty__SHIFT 0x0000000c
+#define VGT_DEBUG_REG2__hsInputFifoFull_MASK 0x00040000L
+#define VGT_DEBUG_REG2__hsInputFifoFull__SHIFT 0x00000012
+#define VGT_DEBUG_REG2__hs_noif_busy_MASK 0x00000002L
+#define VGT_DEBUG_REG2__hs_noif_busy__SHIFT 0x00000001
+#define VGT_DEBUG_REG2__hs_te11_tess_input_rts_MASK 0x00000040L
+#define VGT_DEBUG_REG2__hs_te11_tess_input_rts__SHIFT 0x00000006
+#define VGT_DEBUG_REG2__hsTifFifoEmpty_MASK 0x00002000L
+#define VGT_DEBUG_REG2__hsTifFifoEmpty__SHIFT 0x0000000d
+#define VGT_DEBUG_REG2__hsTifFifoFull_MASK 0x00080000L
+#define VGT_DEBUG_REG2__hsTifFifoFull__SHIFT 0x00000013
+#define VGT_DEBUG_REG2__hsVertFifoEmpty_MASK 0x00000400L
+#define VGT_DEBUG_REG2__hsVertFifoEmpty__SHIFT 0x0000000a
+#define VGT_DEBUG_REG2__hsVertFifoFull_MASK 0x00010000L
+#define VGT_DEBUG_REG2__hsVertFifoFull__SHIFT 0x00000010
+#define VGT_DEBUG_REG2__hsWaveFifoEmpty_MASK 0x00000800L
+#define VGT_DEBUG_REG2__hsWaveFifoEmpty__SHIFT 0x0000000b
+#define VGT_DEBUG_REG2__hsWaveFifoFull_MASK 0x00020000L
+#define VGT_DEBUG_REG2__hsWaveFifoFull__SHIFT 0x00000011
+#define VGT_DEBUG_REG2__lsFwaveFlag_MASK 0x08000000L
+#define VGT_DEBUG_REG2__lsFwaveFlag__SHIFT 0x0000001b
+#define VGT_DEBUG_REG2__ls_sh_id_MASK 0x04000000L
+#define VGT_DEBUG_REG2__ls_sh_id__SHIFT 0x0000001a
+#define VGT_DEBUG_REG2__lsVertFifoEmpty_MASK 0x00000100L
+#define VGT_DEBUG_REG2__lsVertFifoEmpty__SHIFT 0x00000008
+#define VGT_DEBUG_REG2__lsVertFifoFull_MASK 0x00004000L
+#define VGT_DEBUG_REG2__lsVertFifoFull__SHIFT 0x0000000e
+#define VGT_DEBUG_REG2__lsVertIfBusy_0_MASK 0x00000008L
+#define VGT_DEBUG_REG2__lsVertIfBusy_0__SHIFT 0x00000003
+#define VGT_DEBUG_REG2__lsWaveFifoEmpty_MASK 0x00000200L
+#define VGT_DEBUG_REG2__lsWaveFifoEmpty__SHIFT 0x00000009
+#define VGT_DEBUG_REG2__lsWaveFifoFull_MASK 0x00008000L
+#define VGT_DEBUG_REG2__lsWaveFifoFull__SHIFT 0x0000000f
+#define VGT_DEBUG_REG2__lsWaveIfBusy_0_MASK 0x00000020L
+#define VGT_DEBUG_REG2__lsWaveIfBusy_0__SHIFT 0x00000005
+#define VGT_DEBUG_REG2__lsWaveSendFlush_MASK 0x10000000L
+#define VGT_DEBUG_REG2__lsWaveSendFlush__SHIFT 0x0000001c
+#define VGT_DEBUG_REG2__p0_dr_MASK 0x00400000L
+#define VGT_DEBUG_REG2__p0_dr__SHIFT 0x00000016
+#define VGT_DEBUG_REG2__p0_rtr_MASK 0x00100000L
+#define VGT_DEBUG_REG2__p0_rtr__SHIFT 0x00000014
+#define VGT_DEBUG_REG2__p0_rts_MASK 0x01000000L
+#define VGT_DEBUG_REG2__p0_rts__SHIFT 0x00000018
+#define VGT_DEBUG_REG2__p1_dr_MASK 0x00800000L
+#define VGT_DEBUG_REG2__p1_dr__SHIFT 0x00000017
+#define VGT_DEBUG_REG2__p1_rtr_MASK 0x00200000L
+#define VGT_DEBUG_REG2__p1_rtr__SHIFT 0x00000015
+#define VGT_DEBUG_REG2__p1_rts_MASK 0x02000000L
+#define VGT_DEBUG_REG2__p1_rts__SHIFT 0x00000019
+#define VGT_DEBUG_REG2__SPARE_MASK 0xffffffffL
+#define VGT_DEBUG_REG2__SPARE__SHIFT 0x00000000
+#define VGT_DEBUG_REG2__te11_hs_tess_input_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG2__te11_hs_tess_input_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG2__tfmmIsBusy_MASK 0x00000004L
+#define VGT_DEBUG_REG2__tfmmIsBusy__SHIFT 0x00000002
+#define VGT_DEBUG_REG30__dynamic_hs_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG30__dynamic_hs_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG30__event_or_null_p0_q_MASK 0x00000008L
+#define VGT_DEBUG_REG30__event_or_null_p0_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG30__first_data_chunk_invalid_p0_q_MASK 0x08000000L
+#define VGT_DEBUG_REG30__first_data_chunk_invalid_p0_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG30__first_data_ret_of_req_p0_q_MASK 0x04000000L
+#define VGT_DEBUG_REG30__first_data_ret_of_req_p0_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG30__first_fetch_of_tg_p0_q_MASK 0x02000000L
+#define VGT_DEBUG_REG30__first_fetch_of_tg_p0_q__SHIFT 0x00000019
+#define VGT_DEBUG_REG30__last_tf_of_tg_MASK 0x00080000L
+#define VGT_DEBUG_REG30__last_tf_of_tg__SHIFT 0x00000013
+#define VGT_DEBUG_REG30__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG30__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG30__pipe0_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG30__pipe0_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG30__pipe0_tf_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG30__pipe0_tf_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG30__pipe1_rtr_MASK 0x00000020L
+#define VGT_DEBUG_REG30__pipe1_rtr__SHIFT 0x00000005
+#define VGT_DEBUG_REG30__pipe1_tf_rtr_MASK 0x00000040L
+#define VGT_DEBUG_REG30__pipe1_tf_rtr__SHIFT 0x00000006
+#define VGT_DEBUG_REG30__pipe2_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG30__pipe2_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG30__pipe2_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG30__pipe2_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG30__pipe4_dr_MASK 0x40000000L
+#define VGT_DEBUG_REG30__pipe4_dr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG30__pipe4_rtr_MASK 0x80000000L
+#define VGT_DEBUG_REG30__pipe4_rtr__SHIFT 0x0000001f
+#define VGT_DEBUG_REG30__tf_fetch_state_q_MASK 0x00070000L
+#define VGT_DEBUG_REG30__tf_fetch_state_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG30__tf_pointer_p0_q_MASK 0x00f00000L
+#define VGT_DEBUG_REG30__tf_pointer_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG30__tf_xfer_count_p2_q_MASK 0x30000000L
+#define VGT_DEBUG_REG30__tf_xfer_count_p2_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG30__ttp_patch_fifo_empty_MASK 0x00000200L
+#define VGT_DEBUG_REG30__ttp_patch_fifo_empty__SHIFT 0x00000009
+#define VGT_DEBUG_REG30__ttp_patch_fifo_full_MASK 0x00000100L
+#define VGT_DEBUG_REG30__ttp_patch_fifo_full__SHIFT 0x00000008
+#define VGT_DEBUG_REG30__ttp_tf0_fifo_empty_MASK 0x00000400L
+#define VGT_DEBUG_REG30__ttp_tf0_fifo_empty__SHIFT 0x0000000a
+#define VGT_DEBUG_REG30__ttp_tf1_fifo_empty_MASK 0x00000800L
+#define VGT_DEBUG_REG30__ttp_tf1_fifo_empty__SHIFT 0x0000000b
+#define VGT_DEBUG_REG30__ttp_tf2_fifo_empty_MASK 0x00001000L
+#define VGT_DEBUG_REG30__ttp_tf2_fifo_empty__SHIFT 0x0000000c
+#define VGT_DEBUG_REG30__ttp_tf3_fifo_empty_MASK 0x00002000L
+#define VGT_DEBUG_REG30__ttp_tf3_fifo_empty__SHIFT 0x0000000d
+#define VGT_DEBUG_REG30__ttp_tf4_fifo_empty_MASK 0x00004000L
+#define VGT_DEBUG_REG30__ttp_tf4_fifo_empty__SHIFT 0x0000000e
+#define VGT_DEBUG_REG30__ttp_tf5_fifo_empty_MASK 0x00008000L
+#define VGT_DEBUG_REG30__ttp_tf5_fifo_empty__SHIFT 0x0000000f
+#define VGT_DEBUG_REG31__inner_ring_done_q_MASK 0x80000000L
+#define VGT_DEBUG_REG31__inner_ring_done_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG31__outer_ring_done_q_MASK 0x40000000L
+#define VGT_DEBUG_REG31__outer_ring_done_q__SHIFT 0x0000001e
+#define VGT_DEBUG_REG31__pg_con_inner_point1_rts_MASK 0x00400000L
+#define VGT_DEBUG_REG31__pg_con_inner_point1_rts__SHIFT 0x00000016
+#define VGT_DEBUG_REG31__pg_con_inner_point2_rts_MASK 0x00800000L
+#define VGT_DEBUG_REG31__pg_con_inner_point2_rts__SHIFT 0x00000017
+#define VGT_DEBUG_REG31__pg_con_outer_point1_rts_MASK 0x00100000L
+#define VGT_DEBUG_REG31__pg_con_outer_point1_rts__SHIFT 0x00000014
+#define VGT_DEBUG_REG31__pg_con_outer_point2_rts_MASK 0x00200000L
+#define VGT_DEBUG_REG31__pg_con_outer_point2_rts__SHIFT 0x00000015
+#define VGT_DEBUG_REG31__pg_edge_fifo_empty_MASK 0x02000000L
+#define VGT_DEBUG_REG31__pg_edge_fifo_empty__SHIFT 0x00000019
+#define VGT_DEBUG_REG31__pg_edge_fifo_full_MASK 0x10000000L
+#define VGT_DEBUG_REG31__pg_edge_fifo_full__SHIFT 0x0000001c
+#define VGT_DEBUG_REG31__pg_inner3_perp_fifo_empty_MASK 0x04000000L
+#define VGT_DEBUG_REG31__pg_inner3_perp_fifo_empty__SHIFT 0x0000001a
+#define VGT_DEBUG_REG31__pg_inner_perp_fifo_full_MASK 0x20000000L
+#define VGT_DEBUG_REG31__pg_inner_perp_fifo_full__SHIFT 0x0000001d
+#define VGT_DEBUG_REG31__pg_patch_fifo_empty_MASK 0x01000000L
+#define VGT_DEBUG_REG31__pg_patch_fifo_empty__SHIFT 0x00000018
+#define VGT_DEBUG_REG31__pg_patch_fifo_full_MASK 0x08000000L
+#define VGT_DEBUG_REG31__pg_patch_fifo_full__SHIFT 0x0000001b
+#define VGT_DEBUG_REG31__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG31__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG31__pipe0_rtr_MASK 0x00000002L
+#define VGT_DEBUG_REG31__pipe0_rtr__SHIFT 0x00000001
+#define VGT_DEBUG_REG31__pipe1_inner_dr_MASK 0x00000008L
+#define VGT_DEBUG_REG31__pipe1_inner_dr__SHIFT 0x00000003
+#define VGT_DEBUG_REG31__pipe1_outer_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG31__pipe1_outer_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG31__pipe2_inner_dr_MASK 0x00000020L
+#define VGT_DEBUG_REG31__pipe2_inner_dr__SHIFT 0x00000005
+#define VGT_DEBUG_REG31__pipe2_inner_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG31__pipe2_inner_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG31__pipe2_outer_dr_MASK 0x00000010L
+#define VGT_DEBUG_REG31__pipe2_outer_dr__SHIFT 0x00000004
+#define VGT_DEBUG_REG31__pipe2_outer_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG31__pipe2_outer_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG31__pipe3_inner_dr_MASK 0x00000080L
+#define VGT_DEBUG_REG31__pipe3_inner_dr__SHIFT 0x00000007
+#define VGT_DEBUG_REG31__pipe3_inner_rtr_MASK 0x00008000L
+#define VGT_DEBUG_REG31__pipe3_inner_rtr__SHIFT 0x0000000f
+#define VGT_DEBUG_REG31__pipe3_outer_dr_MASK 0x00000040L
+#define VGT_DEBUG_REG31__pipe3_outer_dr__SHIFT 0x00000006
+#define VGT_DEBUG_REG31__pipe3_outer_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG31__pipe3_outer_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG31__pipe4_inner_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG31__pipe4_inner_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG31__pipe4_inner_rtr_MASK 0x00020000L
+#define VGT_DEBUG_REG31__pipe4_inner_rtr__SHIFT 0x00000011
+#define VGT_DEBUG_REG31__pipe4_outer_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG31__pipe4_outer_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG31__pipe4_outer_rtr_MASK 0x00010000L
+#define VGT_DEBUG_REG31__pipe4_outer_rtr__SHIFT 0x00000010
+#define VGT_DEBUG_REG31__pipe5_inner_dr_MASK 0x00000800L
+#define VGT_DEBUG_REG31__pipe5_inner_dr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG31__pipe5_inner_rtr_MASK 0x00080000L
+#define VGT_DEBUG_REG31__pipe5_inner_rtr__SHIFT 0x00000013
+#define VGT_DEBUG_REG31__pipe5_outer_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG31__pipe5_outer_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG31__pipe5_outer_rtr_MASK 0x00040000L
+#define VGT_DEBUG_REG31__pipe5_outer_rtr__SHIFT 0x00000012
+#define VGT_DEBUG_REG32__event_flag_p5_q_MASK 0x00000100L
+#define VGT_DEBUG_REG32__event_flag_p5_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG32__event_null_special_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG32__event_null_special_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG32__fifos_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG32__fifos_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG32__first_point_of_edge_p5_q_MASK 0x00000400L
+#define VGT_DEBUG_REG32__first_point_of_edge_p5_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG32__first_point_of_patch_p5_q_MASK 0x00000200L
+#define VGT_DEBUG_REG32__first_point_of_patch_p5_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG32__first_ring_of_patch_MASK 0x00000001L
+#define VGT_DEBUG_REG32__first_ring_of_patch__SHIFT 0x00000000
+#define VGT_DEBUG_REG32__inner2_fifos_rtr_MASK 0x01000000L
+#define VGT_DEBUG_REG32__inner2_fifos_rtr__SHIFT 0x00000018
+#define VGT_DEBUG_REG32__inner_fifos_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG32__inner_fifos_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG32__last_edge_of_inner_ring_MASK 0x00000010L
+#define VGT_DEBUG_REG32__last_edge_of_inner_ring__SHIFT 0x00000004
+#define VGT_DEBUG_REG32__last_edge_of_outer_ring_MASK 0x00000004L
+#define VGT_DEBUG_REG32__last_edge_of_outer_ring__SHIFT 0x00000002
+#define VGT_DEBUG_REG32__last_patch_of_tg_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG32__last_patch_of_tg_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG32__last_patch_of_tg_p5_q_MASK 0x00000800L
+#define VGT_DEBUG_REG32__last_patch_of_tg_p5_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG32__last_point_of_inner_edge_MASK 0x00000020L
+#define VGT_DEBUG_REG32__last_point_of_inner_edge__SHIFT 0x00000005
+#define VGT_DEBUG_REG32__last_point_of_outer_edge_MASK 0x00000008L
+#define VGT_DEBUG_REG32__last_point_of_outer_edge__SHIFT 0x00000003
+#define VGT_DEBUG_REG32__last_ring_of_patch_MASK 0x00000002L
+#define VGT_DEBUG_REG32__last_ring_of_patch__SHIFT 0x00000001
+#define VGT_DEBUG_REG32__outer_fifos_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG32__outer_fifos_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG32__pg_edge_fifo2_full_MASK 0x00020000L
+#define VGT_DEBUG_REG32__pg_edge_fifo2_full__SHIFT 0x00000011
+#define VGT_DEBUG_REG32__pg_edge_fifo3_full_MASK 0x00010000L
+#define VGT_DEBUG_REG32__pg_edge_fifo3_full__SHIFT 0x00000010
+#define VGT_DEBUG_REG32__pg_inner2_point_fifo_full_MASK 0x00100000L
+#define VGT_DEBUG_REG32__pg_inner2_point_fifo_full__SHIFT 0x00000014
+#define VGT_DEBUG_REG32__pg_inner3_point_fifo_full_MASK 0x00040000L
+#define VGT_DEBUG_REG32__pg_inner3_point_fifo_full__SHIFT 0x00000012
+#define VGT_DEBUG_REG32__pg_inner_point_fifo_full_MASK 0x00400000L
+#define VGT_DEBUG_REG32__pg_inner_point_fifo_full__SHIFT 0x00000016
+#define VGT_DEBUG_REG32__pg_outer2_point_fifo_full_MASK 0x00200000L
+#define VGT_DEBUG_REG32__pg_outer2_point_fifo_full__SHIFT 0x00000015
+#define VGT_DEBUG_REG32__pg_outer3_point_fifo_full_MASK 0x00080000L
+#define VGT_DEBUG_REG32__pg_outer3_point_fifo_full__SHIFT 0x00000013
+#define VGT_DEBUG_REG32__pg_outer_point_fifo_full_MASK 0x00800000L
+#define VGT_DEBUG_REG32__pg_outer_point_fifo_full__SHIFT 0x00000017
+#define VGT_DEBUG_REG32__pipe5_inner2_rtr_MASK 0x00008000L
+#define VGT_DEBUG_REG32__pipe5_inner2_rtr__SHIFT 0x0000000f
+#define VGT_DEBUG_REG32__pipe5_inner3_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG32__pipe5_inner3_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG32__SPARE_MASK 0x80000000L
+#define VGT_DEBUG_REG32__SPARE__SHIFT 0x0000001f
+#define VGT_DEBUG_REG32__tess_topology_p5_q_MASK 0x00003000L
+#define VGT_DEBUG_REG32__tess_topology_p5_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG33__con_prim_fifo_empty_MASK 0x00040000L
+#define VGT_DEBUG_REG33__con_prim_fifo_empty__SHIFT 0x00000012
+#define VGT_DEBUG_REG33__con_prim_fifo_full_MASK 0x00010000L
+#define VGT_DEBUG_REG33__con_prim_fifo_full__SHIFT 0x00000010
+#define VGT_DEBUG_REG33__con_ring1_busy_MASK 0x80000000L
+#define VGT_DEBUG_REG33__con_ring1_busy__SHIFT 0x0000001f
+#define VGT_DEBUG_REG33__con_ring2_busy_MASK 0x40000000L
+#define VGT_DEBUG_REG33__con_ring2_busy__SHIFT 0x0000001e
+#define VGT_DEBUG_REG33__con_ring3_busy_MASK 0x20000000L
+#define VGT_DEBUG_REG33__con_ring3_busy__SHIFT 0x0000001d
+#define VGT_DEBUG_REG33__con_vert_fifo_empty_MASK 0x00080000L
+#define VGT_DEBUG_REG33__con_vert_fifo_empty__SHIFT 0x00000013
+#define VGT_DEBUG_REG33__con_vert_fifo_full_MASK 0x00020000L
+#define VGT_DEBUG_REG33__con_vert_fifo_full__SHIFT 0x00000011
+#define VGT_DEBUG_REG33__first_prim_of_patch_q_MASK 0x00008000L
+#define VGT_DEBUG_REG33__first_prim_of_patch_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG33__last_patch_of_tg_p0_q_MASK 0x00100000L
+#define VGT_DEBUG_REG33__last_patch_of_tg_p0_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG33__pipe0_patch_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG33__pipe0_patch_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG33__pipe0_patch_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG33__pipe0_patch_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG33__pipe1_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG33__pipe1_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG33__pipe1_patch_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG33__pipe1_patch_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG33__pipe2_dr_MASK 0x00000008L
+#define VGT_DEBUG_REG33__pipe2_dr__SHIFT 0x00000003
+#define VGT_DEBUG_REG33__pipe2_rtr_MASK 0x00000080L
+#define VGT_DEBUG_REG33__pipe2_rtr__SHIFT 0x00000007
+#define VGT_DEBUG_REG33__pipe3_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG33__pipe3_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG33__pipe3_rtr_MASK 0x00000200L
+#define VGT_DEBUG_REG33__pipe3_rtr__SHIFT 0x00000009
+#define VGT_DEBUG_REG33__ring1_in_sync_q_MASK 0x00000800L
+#define VGT_DEBUG_REG33__ring1_in_sync_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG33__ring1_pipe1_dr_MASK 0x00000040L
+#define VGT_DEBUG_REG33__ring1_pipe1_dr__SHIFT 0x00000006
+#define VGT_DEBUG_REG33__ring1_valid_p2_MASK 0x00800000L
+#define VGT_DEBUG_REG33__ring1_valid_p2__SHIFT 0x00000017
+#define VGT_DEBUG_REG33__ring2_in_sync_q_MASK 0x00000400L
+#define VGT_DEBUG_REG33__ring2_in_sync_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG33__ring2_pipe1_dr_MASK 0x00000020L
+#define VGT_DEBUG_REG33__ring2_pipe1_dr__SHIFT 0x00000005
+#define VGT_DEBUG_REG33__ring2_valid_p2_MASK 0x00400000L
+#define VGT_DEBUG_REG33__ring2_valid_p2__SHIFT 0x00000016
+#define VGT_DEBUG_REG33__ring3_in_sync_q_MASK 0x00002000L
+#define VGT_DEBUG_REG33__ring3_in_sync_q__SHIFT 0x0000000d
+#define VGT_DEBUG_REG33__ring3_pipe1_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG33__ring3_pipe1_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG33__ring3_valid_p2_MASK 0x00200000L
+#define VGT_DEBUG_REG33__ring3_valid_p2__SHIFT 0x00000015
+#define VGT_DEBUG_REG33__te11_out_vert_gs_en_MASK 0x10000000L
+#define VGT_DEBUG_REG33__te11_out_vert_gs_en__SHIFT 0x0000001c
+#define VGT_DEBUG_REG33__tess_topology_p0_q_MASK 0x0c000000L
+#define VGT_DEBUG_REG33__tess_topology_p0_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG33__tess_type_p0_q_MASK 0x03000000L
+#define VGT_DEBUG_REG33__tess_type_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG33__tm_te11_event_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG33__tm_te11_event_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG34__advance_inner_point_p1_MASK 0x00800000L
+#define VGT_DEBUG_REG34__advance_inner_point_p1__SHIFT 0x00000017
+#define VGT_DEBUG_REG34__advance_outer_point_p1_MASK 0x00400000L
+#define VGT_DEBUG_REG34__advance_outer_point_p1__SHIFT 0x00000016
+#define VGT_DEBUG_REG34__con_state_q_MASK 0x0000000fL
+#define VGT_DEBUG_REG34__con_state_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG34__first_ring_of_patch_p0_q_MASK 0x00010000L
+#define VGT_DEBUG_REG34__first_ring_of_patch_p0_q__SHIFT 0x00000010
+#define VGT_DEBUG_REG34__last_edge_of_outer_ring_p0_q_MASK 0x00040000L
+#define VGT_DEBUG_REG34__last_edge_of_outer_ring_p0_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG34__last_point_of_inner_ring_p1_MASK 0x00100000L
+#define VGT_DEBUG_REG34__last_point_of_inner_ring_p1__SHIFT 0x00000014
+#define VGT_DEBUG_REG34__last_point_of_outer_ring_p1_MASK 0x00080000L
+#define VGT_DEBUG_REG34__last_point_of_outer_ring_p1__SHIFT 0x00000013
+#define VGT_DEBUG_REG34__last_ring_of_patch_p0_q_MASK 0x00020000L
+#define VGT_DEBUG_REG34__last_ring_of_patch_p0_q__SHIFT 0x00000011
+#define VGT_DEBUG_REG34__next_ring_is_rect_p0_q_MASK 0x01000000L
+#define VGT_DEBUG_REG34__next_ring_is_rect_p0_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG34__outer_edge_tf_eq_one_p0_q_MASK 0x00200000L
+#define VGT_DEBUG_REG34__outer_edge_tf_eq_one_p0_q__SHIFT 0x00000015
+#define VGT_DEBUG_REG34__outer_parity_p0_q_MASK 0x00004000L
+#define VGT_DEBUG_REG34__outer_parity_p0_q__SHIFT 0x0000000e
+#define VGT_DEBUG_REG34__parallel_parity_p0_q_MASK 0x00008000L
+#define VGT_DEBUG_REG34__parallel_parity_p0_q__SHIFT 0x0000000f
+#define VGT_DEBUG_REG34__pipe0_edge_dr_MASK 0x00000200L
+#define VGT_DEBUG_REG34__pipe0_edge_dr__SHIFT 0x00000009
+#define VGT_DEBUG_REG34__pipe0_edge_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG34__pipe0_edge_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG34__pipe0_patch_dr_MASK 0x00000100L
+#define VGT_DEBUG_REG34__pipe0_patch_dr__SHIFT 0x00000008
+#define VGT_DEBUG_REG34__pipe0_patch_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG34__pipe0_patch_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG34__pipe1_dr_MASK 0x00000400L
+#define VGT_DEBUG_REG34__pipe1_dr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG34__pipe1_edge_rtr_MASK 0x40000000L
+#define VGT_DEBUG_REG34__pipe1_edge_rtr__SHIFT 0x0000001e
+#define VGT_DEBUG_REG34__pipe1_inner1_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG34__pipe1_inner1_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG34__pipe1_inner2_rtr_MASK 0x10000000L
+#define VGT_DEBUG_REG34__pipe1_inner2_rtr__SHIFT 0x0000001c
+#define VGT_DEBUG_REG34__pipe1_outer1_rtr_MASK 0x02000000L
+#define VGT_DEBUG_REG34__pipe1_outer1_rtr__SHIFT 0x00000019
+#define VGT_DEBUG_REG34__pipe1_outer2_rtr_MASK 0x04000000L
+#define VGT_DEBUG_REG34__pipe1_outer2_rtr__SHIFT 0x0000001a
+#define VGT_DEBUG_REG34__pipe1_patch_rtr_MASK 0x20000000L
+#define VGT_DEBUG_REG34__pipe1_patch_rtr__SHIFT 0x0000001d
+#define VGT_DEBUG_REG34__pipe1_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG34__pipe1_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG34__process_tri_1st_2nd_half_p0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG34__process_tri_1st_2nd_half_p0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG34__process_tri_center_poly_p0_q_MASK 0x00000080L
+#define VGT_DEBUG_REG34__process_tri_center_poly_p0_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG34__process_tri_middle_p0_q_MASK 0x00000020L
+#define VGT_DEBUG_REG34__process_tri_middle_p0_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG34__second_cycle_q_MASK 0x00000010L
+#define VGT_DEBUG_REG34__second_cycle_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG34__use_stored_inner_q_ring1_MASK 0x80000000L
+#define VGT_DEBUG_REG34__use_stored_inner_q_ring1__SHIFT 0x0000001f
+#define VGT_DEBUG_REG35__event_flag_p1_q_MASK 0x00040000L
+#define VGT_DEBUG_REG35__event_flag_p1_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG35__first_req_of_tg_p1_q_MASK 0x10000000L
+#define VGT_DEBUG_REG35__first_req_of_tg_p1_q__SHIFT 0x0000001c
+#define VGT_DEBUG_REG35__last_req_of_tg_p2_MASK 0x00000800L
+#define VGT_DEBUG_REG35__last_req_of_tg_p2__SHIFT 0x0000000b
+#define VGT_DEBUG_REG35__null_flag_p1_q_MASK 0x00080000L
+#define VGT_DEBUG_REG35__null_flag_p1_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG35__pipe0_dr_MASK 0x00000001L
+#define VGT_DEBUG_REG35__pipe0_dr__SHIFT 0x00000000
+#define VGT_DEBUG_REG35__pipe0_rtr_MASK 0x00000004L
+#define VGT_DEBUG_REG35__pipe0_rtr__SHIFT 0x00000002
+#define VGT_DEBUG_REG35__pipe1_dr_MASK 0x00000002L
+#define VGT_DEBUG_REG35__pipe1_dr__SHIFT 0x00000001
+#define VGT_DEBUG_REG35__pipe1_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG35__pipe1_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG35__second_tf_ret_data_q_MASK 0x08000000L
+#define VGT_DEBUG_REG35__second_tf_ret_data_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG35__spi_vgt_hs_done_cnt_q_MASK 0x0003f000L
+#define VGT_DEBUG_REG35__spi_vgt_hs_done_cnt_q__SHIFT 0x0000000c
+#define VGT_DEBUG_REG35__TC_VGT_rdret_data_in_MASK 0x80000000L
+#define VGT_DEBUG_REG35__TC_VGT_rdret_data_in__SHIFT 0x0000001f
+#define VGT_DEBUG_REG35__tf_data_fifo_busy_q_MASK 0x00000040L
+#define VGT_DEBUG_REG35__tf_data_fifo_busy_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG35__tf_data_fifo_cnt_q_MASK 0x07f00000L
+#define VGT_DEBUG_REG35__tf_data_fifo_cnt_q__SHIFT 0x00000014
+#define VGT_DEBUG_REG35__tf_data_fifo_rtr_q_MASK 0x00000080L
+#define VGT_DEBUG_REG35__tf_data_fifo_rtr_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_empty_MASK 0x00000010L
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_empty__SHIFT 0x00000004
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_full_MASK 0x00000020L
+#define VGT_DEBUG_REG35__tfreq_tg_fifo_full__SHIFT 0x00000005
+#define VGT_DEBUG_REG35__tf_skid_fifo_empty_MASK 0x00000100L
+#define VGT_DEBUG_REG35__tf_skid_fifo_empty__SHIFT 0x00000008
+#define VGT_DEBUG_REG35__tf_skid_fifo_full_MASK 0x00000200L
+#define VGT_DEBUG_REG35__tf_skid_fifo_full__SHIFT 0x00000009
+#define VGT_DEBUG_REG35__VGT_TC_rdnfo_stall_out_MASK 0x40000000L
+#define VGT_DEBUG_REG35__VGT_TC_rdnfo_stall_out__SHIFT 0x0000001e
+#define VGT_DEBUG_REG35__vgt_tc_rdreq_rtr_q_MASK 0x00000400L
+#define VGT_DEBUG_REG35__vgt_tc_rdreq_rtr_q__SHIFT 0x0000000a
+#define VGT_DEBUG_REG35__VGT_TC_rdreq_send_out_MASK 0x20000000L
+#define VGT_DEBUG_REG35__VGT_TC_rdreq_send_out__SHIFT 0x0000001d
+#define VGT_DEBUG_REG3__hsWaveRelInd_MASK 0xfc000000L
+#define VGT_DEBUG_REG3__hsWaveRelInd__SHIFT 0x0000001a
+#define VGT_DEBUG_REG3__lsPatchCnt_MASK 0x03fc0000L
+#define VGT_DEBUG_REG3__lsPatchCnt__SHIFT 0x00000012
+#define VGT_DEBUG_REG3__lsTgRelInd_MASK 0x00000fffL
+#define VGT_DEBUG_REG3__lsTgRelInd__SHIFT 0x00000000
+#define VGT_DEBUG_REG3__lsWaveRelInd_MASK 0x0003f000L
+#define VGT_DEBUG_REG3__lsWaveRelInd__SHIFT 0x0000000c
+#define VGT_DEBUG_REG4__hsCpCnt_MASK 0x1f000000L
+#define VGT_DEBUG_REG4__hsCpCnt__SHIFT 0x00000018
+#define VGT_DEBUG_REG4__hsFwaveFlag_MASK 0x40000000L
+#define VGT_DEBUG_REG4__hsFwaveFlag__SHIFT 0x0000001e
+#define VGT_DEBUG_REG4__hsPatchCnt_MASK 0x000000ffL
+#define VGT_DEBUG_REG4__hsPatchCnt__SHIFT 0x00000000
+#define VGT_DEBUG_REG4__hsPrimId_15_0_MASK 0x00ffff00L
+#define VGT_DEBUG_REG4__hsPrimId_15_0__SHIFT 0x00000008
+#define VGT_DEBUG_REG4__hsWaveSendFlush_MASK 0x20000000L
+#define VGT_DEBUG_REG4__hsWaveSendFlush__SHIFT 0x0000001d
+#define VGT_DEBUG_REG4__SPARE_MASK 0xffffffffL
+#define VGT_DEBUG_REG4__SPARE__SHIFT 0x00000000
+#define VGT_DEBUG_REG5__hsVertCreditCnt_0_MASK 0x0000f800L
+#define VGT_DEBUG_REG5__hsVertCreditCnt_0__SHIFT 0x0000000b
+#define VGT_DEBUG_REG5__hsWaveCreditCnt_0_MASK 0x000000f8L
+#define VGT_DEBUG_REG5__hsWaveCreditCnt_0__SHIFT 0x00000003
+#define VGT_DEBUG_REG5__lsVertCreditCnt_0_MASK 0xf8000000L
+#define VGT_DEBUG_REG5__lsVertCreditCnt_0__SHIFT 0x0000001b
+#define VGT_DEBUG_REG5__lsWaveCreditCnt_0_MASK 0x00f80000L
+#define VGT_DEBUG_REG5__lsWaveCreditCnt_0__SHIFT 0x00000013
+#define VGT_DEBUG_REG5__SPARE1_MASK 0x07000000L
+#define VGT_DEBUG_REG5__SPARE1__SHIFT 0x00000018
+#define VGT_DEBUG_REG5__SPARE2_MASK 0x00070000L
+#define VGT_DEBUG_REG5__SPARE2__SHIFT 0x00000010
+#define VGT_DEBUG_REG5__SPARE3_MASK 0x00000700L
+#define VGT_DEBUG_REG5__SPARE3__SHIFT 0x00000008
+#define VGT_DEBUG_REG5__SPARE4_MASK 0x00000007L
+#define VGT_DEBUG_REG5__SPARE4__SHIFT 0x00000000
+#define VGT_DEBUG_REG6__debug_BASE_MASK 0x0000ffffL
+#define VGT_DEBUG_REG6__debug_BASE__SHIFT 0x00000000
+#define VGT_DEBUG_REG6__debug_SIZE_MASK 0xffff0000L
+#define VGT_DEBUG_REG6__debug_SIZE__SHIFT 0x00000010
+#define VGT_DEBUG_REG7__debug_tfmmFifoEmpty_MASK 0x00000001L
+#define VGT_DEBUG_REG7__debug_tfmmFifoEmpty__SHIFT 0x00000000
+#define VGT_DEBUG_REG7__debug_tfmmFifoFull_MASK 0x00000002L
+#define VGT_DEBUG_REG7__debug_tfmmFifoFull__SHIFT 0x00000001
+#define VGT_DEBUG_REG7__hs_pipe0_dr_MASK 0x00000004L
+#define VGT_DEBUG_REG7__hs_pipe0_dr__SHIFT 0x00000002
+#define VGT_DEBUG_REG7__hs_pipe0_rtr_MASK 0x00000008L
+#define VGT_DEBUG_REG7__hs_pipe0_rtr__SHIFT 0x00000003
+#define VGT_DEBUG_REG7__hs_pipe1_rtr_MASK 0x00000010L
+#define VGT_DEBUG_REG7__hs_pipe1_rtr__SHIFT 0x00000004
+#define VGT_DEBUG_REG7__SPARE_MASK 0x0000ffe0L
+#define VGT_DEBUG_REG7__SPARE__SHIFT 0x00000005
+#define VGT_DEBUG_REG7__TF_addr_MASK 0xffff0000L
+#define VGT_DEBUG_REG7__TF_addr__SHIFT 0x00000010
+#define VGT_DEBUG_REG8__es_gs_rtr_MASK 0x00004000L
+#define VGT_DEBUG_REG8__es_gs_rtr__SHIFT 0x0000000e
+#define VGT_DEBUG_REG8__gs_event_fifo_empty_MASK 0x02000000L
+#define VGT_DEBUG_REG8__gs_event_fifo_empty__SHIFT 0x00000019
+#define VGT_DEBUG_REG8__gs_event_fifo_rtr_MASK 0x00008000L
+#define VGT_DEBUG_REG8__gs_event_fifo_rtr__SHIFT 0x0000000f
+#define VGT_DEBUG_REG8__gsprim_buff_empty_q_MASK 0x04000000L
+#define VGT_DEBUG_REG8__gsprim_buff_empty_q__SHIFT 0x0000001a
+#define VGT_DEBUG_REG8__gsprim_buff_full_q_MASK 0x08000000L
+#define VGT_DEBUG_REG8__gsprim_buff_full_q__SHIFT 0x0000001b
+#define VGT_DEBUG_REG8__gs_tbl_r3_rtr_MASK 0x00020000L
+#define VGT_DEBUG_REG8__gs_tbl_r3_rtr__SHIFT 0x00000011
+#define VGT_DEBUG_REG8__gs_tbl_valid_r3_q_MASK 0x00000020L
+#define VGT_DEBUG_REG8__gs_tbl_valid_r3_q__SHIFT 0x00000005
+#define VGT_DEBUG_REG8__hold_for_es_flush_MASK 0x01000000L
+#define VGT_DEBUG_REG8__hold_for_es_flush__SHIFT 0x00000018
+#define VGT_DEBUG_REG8__prim_skid_fifo_empty_MASK 0x00040000L
+#define VGT_DEBUG_REG8__prim_skid_fifo_empty__SHIFT 0x00000012
+#define VGT_DEBUG_REG8__r0_rtr_MASK 0x00000400L
+#define VGT_DEBUG_REG8__r0_rtr__SHIFT 0x0000000a
+#define VGT_DEBUG_REG8__r1_inst_rtr_MASK 0x00000004L
+#define VGT_DEBUG_REG8__r1_inst_rtr__SHIFT 0x00000002
+#define VGT_DEBUG_REG8__r1_rtr_MASK 0x00000800L
+#define VGT_DEBUG_REG8__r1_rtr__SHIFT 0x0000000b
+#define VGT_DEBUG_REG8__r2_indx_rtr_MASK 0x00001000L
+#define VGT_DEBUG_REG8__r2_indx_rtr__SHIFT 0x0000000c
+#define VGT_DEBUG_REG8__r2_no_bp_rtr_MASK 0x00800000L
+#define VGT_DEBUG_REG8__r2_no_bp_rtr__SHIFT 0x00000017
+#define VGT_DEBUG_REG8__r2_rtr_MASK 0x00002000L
+#define VGT_DEBUG_REG8__r2_rtr__SHIFT 0x0000000d
+#define VGT_DEBUG_REG8__rcm_busy_q_MASK 0x00000001L
+#define VGT_DEBUG_REG8__rcm_busy_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG8__rcm_noif_busy_q_MASK 0x00000002L
+#define VGT_DEBUG_REG8__rcm_noif_busy_q__SHIFT 0x00000001
+#define VGT_DEBUG_REG8__spi_esvert_fifo_busy_q_MASK 0x00000010L
+#define VGT_DEBUG_REG8__spi_esvert_fifo_busy_q__SHIFT 0x00000004
+#define VGT_DEBUG_REG8__spi_gsprim_fifo_busy_q_MASK 0x00000008L
+#define VGT_DEBUG_REG8__spi_gsprim_fifo_busy_q__SHIFT 0x00000003
+#define VGT_DEBUG_REG8__te_prim_fifo_empty_MASK 0x10000000L
+#define VGT_DEBUG_REG8__te_prim_fifo_empty__SHIFT 0x0000001c
+#define VGT_DEBUG_REG8__te_prim_fifo_full_MASK 0x20000000L
+#define VGT_DEBUG_REG8__te_prim_fifo_full__SHIFT 0x0000001d
+#define VGT_DEBUG_REG8__te_vert_fifo_empty_MASK 0x40000000L
+#define VGT_DEBUG_REG8__te_vert_fifo_empty__SHIFT 0x0000001e
+#define VGT_DEBUG_REG8__te_vert_fifo_full_MASK 0x80000000L
+#define VGT_DEBUG_REG8__te_vert_fifo_full__SHIFT 0x0000001f
+#define VGT_DEBUG_REG8__tm_rcm_es_tbl_rtr_MASK 0x00200000L
+#define VGT_DEBUG_REG8__tm_rcm_es_tbl_rtr__SHIFT 0x00000015
+#define VGT_DEBUG_REG8__tm_rcm_gs_event_rtr_MASK 0x00010000L
+#define VGT_DEBUG_REG8__tm_rcm_gs_event_rtr__SHIFT 0x00000010
+#define VGT_DEBUG_REG8__tm_rcm_gs_tbl_rtr_MASK 0x00100000L
+#define VGT_DEBUG_REG8__tm_rcm_gs_tbl_rtr__SHIFT 0x00000014
+#define VGT_DEBUG_REG8__valid_r0_q_MASK 0x00000040L
+#define VGT_DEBUG_REG8__valid_r0_q__SHIFT 0x00000006
+#define VGT_DEBUG_REG8__valid_r1_q_MASK 0x00000080L
+#define VGT_DEBUG_REG8__valid_r1_q__SHIFT 0x00000007
+#define VGT_DEBUG_REG8__valid_r2_MASK 0x00000100L
+#define VGT_DEBUG_REG8__valid_r2_q_MASK 0x00000200L
+#define VGT_DEBUG_REG8__valid_r2_q__SHIFT 0x00000009
+#define VGT_DEBUG_REG8__valid_r2__SHIFT 0x00000008
+#define VGT_DEBUG_REG8__VGT_SPI_esvert_rtr_q_MASK 0x00400000L
+#define VGT_DEBUG_REG8__VGT_SPI_esvert_rtr_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG8__VGT_SPI_gsprim_rtr_q_MASK 0x00080000L
+#define VGT_DEBUG_REG8__VGT_SPI_gsprim_rtr_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG9__eop_indx_r3_MASK 0x00000010L
+#define VGT_DEBUG_REG9__eop_indx_r3__SHIFT 0x00000004
+#define VGT_DEBUG_REG9__eop_prim_r3_MASK 0x00000020L
+#define VGT_DEBUG_REG9__eop_prim_r3__SHIFT 0x00000005
+#define VGT_DEBUG_REG9__es_eov_r3_MASK 0x00000040L
+#define VGT_DEBUG_REG9__es_eov_r3__SHIFT 0x00000006
+#define VGT_DEBUG_REG9__es_per_gs_vert_cnt_r3_q_not_0_MASK 0x02000000L
+#define VGT_DEBUG_REG9__es_per_gs_vert_cnt_r3_q_not_0__SHIFT 0x00000019
+#define VGT_DEBUG_REG9__es_tbl_state_r3_q_0_MASK 0x00000080L
+#define VGT_DEBUG_REG9__es_tbl_state_r3_q_0__SHIFT 0x00000007
+#define VGT_DEBUG_REG9__gs_eov_r3_MASK 0x00000008L
+#define VGT_DEBUG_REG9__gs_eov_r3__SHIFT 0x00000003
+#define VGT_DEBUG_REG9__gs_instancing_state_q_MASK 0x01000000L
+#define VGT_DEBUG_REG9__gs_instancing_state_q__SHIFT 0x00000018
+#define VGT_DEBUG_REG9__gs_pending_state_r3_q_MASK 0x00400000L
+#define VGT_DEBUG_REG9__gs_pending_state_r3_q__SHIFT 0x00000016
+#define VGT_DEBUG_REG9__gs_prim_per_es_ctr_r3_q_not_0_MASK 0x04000000L
+#define VGT_DEBUG_REG9__gs_prim_per_es_ctr_r3_q_not_0__SHIFT 0x0000001a
+#define VGT_DEBUG_REG9__gs_tbl_eop_r3_q_MASK 0x00040000L
+#define VGT_DEBUG_REG9__gs_tbl_eop_r3_q__SHIFT 0x00000012
+#define VGT_DEBUG_REG9__gs_tbl_num_es_per_gs_r3_q_not_0_MASK 0x00000400L
+#define VGT_DEBUG_REG9__gs_tbl_num_es_per_gs_r3_q_not_0__SHIFT 0x0000000a
+#define VGT_DEBUG_REG9__gs_tbl_prim_cnt_r3_q_MASK 0x0003f800L
+#define VGT_DEBUG_REG9__gs_tbl_prim_cnt_r3_q__SHIFT 0x0000000b
+#define VGT_DEBUG_REG9__gs_tbl_state_r3_q_MASK 0x00380000L
+#define VGT_DEBUG_REG9__gs_tbl_state_r3_q__SHIFT 0x00000013
+#define VGT_DEBUG_REG9__indices_to_send_r2_q_MASK 0x00000003L
+#define VGT_DEBUG_REG9__indices_to_send_r2_q__SHIFT 0x00000000
+#define VGT_DEBUG_REG9__invalidate_rb_roll_over_q_MASK 0x00800000L
+#define VGT_DEBUG_REG9__invalidate_rb_roll_over_q__SHIFT 0x00000017
+#define VGT_DEBUG_REG9__off_chip_hs_r2_q_MASK 0x80000000L
+#define VGT_DEBUG_REG9__off_chip_hs_r2_q__SHIFT 0x0000001f
+#define VGT_DEBUG_REG9__pending_es_flush_r3_MASK 0x00000200L
+#define VGT_DEBUG_REG9__pending_es_flush_r3__SHIFT 0x00000009
+#define VGT_DEBUG_REG9__pending_es_send_r3_q_MASK 0x00000100L
+#define VGT_DEBUG_REG9__pending_es_send_r3_q__SHIFT 0x00000008
+#define VGT_DEBUG_REG9__pre_r0_rtr_MASK 0x08000000L
+#define VGT_DEBUG_REG9__pre_r0_rtr__SHIFT 0x0000001b
+#define VGT_DEBUG_REG9__SPARE0_MASK 0x40000000L
+#define VGT_DEBUG_REG9__SPARE0__SHIFT 0x0000001e
+#define VGT_DEBUG_REG9__valid_indices_r3_MASK 0x00000004L
+#define VGT_DEBUG_REG9__valid_indices_r3__SHIFT 0x00000002
+#define VGT_DEBUG_REG9__valid_pre_r0_q_MASK 0x20000000L
+#define VGT_DEBUG_REG9__valid_pre_r0_q__SHIFT 0x0000001d
+#define VGT_DEBUG_REG9__valid_r3_q_MASK 0x10000000L
+#define VGT_DEBUG_REG9__valid_r3_q__SHIFT 0x0000001c
+#define VGT_DMA_BASE__BASE_ADDR_MASK 0xffffffffL
+#define VGT_DMA_BASE__BASE_ADDR__SHIFT 0x00000000
+#define VGT_DMA_BASE_HI__BASE_ADDR_MASK 0x000000ffL
+#define VGT_DMA_BASE_HI__BASE_ADDR__SHIFT 0x00000000
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA_DATA_FIFO_DEPTH_MASK 0x000001ffL
+#define VGT_DMA_DATA_FIFO_DEPTH__DMA_DATA_FIFO_DEPTH__SHIFT 0x00000000
+#define VGT_DMA_INDEX_TYPE__ATC_MASK 0x00000100L
+#define VGT_DMA_INDEX_TYPE__ATC__SHIFT 0x00000008
+#define VGT_DMA_INDEX_TYPE__BUF_TYPE_MASK 0x00000030L
+#define VGT_DMA_INDEX_TYPE__BUF_TYPE__SHIFT 0x00000004
+#define VGT_DMA_INDEX_TYPE__INDEX_TYPE_MASK 0x00000003L
+#define VGT_DMA_INDEX_TYPE__INDEX_TYPE__SHIFT 0x00000000
+#define VGT_DMA_INDEX_TYPE__NOT_EOP_MASK 0x00000200L
+#define VGT_DMA_INDEX_TYPE__NOT_EOP__SHIFT 0x00000009
+#define VGT_DMA_INDEX_TYPE__RDREQ_POLICY_MASK 0x000000c0L
+#define VGT_DMA_INDEX_TYPE__RDREQ_POLICY__SHIFT 0x00000006
+#define VGT_DMA_INDEX_TYPE__REQ_PATH_MASK 0x00000400L
+#define VGT_DMA_INDEX_TYPE__REQ_PATH__SHIFT 0x0000000a
+#define VGT_DMA_INDEX_TYPE__SWAP_MODE_MASK 0x0000000cL
+#define VGT_DMA_INDEX_TYPE__SWAP_MODE__SHIFT 0x00000002
+#define VGT_DMA_MAX_SIZE__MAX_SIZE_MASK 0xffffffffL
+#define VGT_DMA_MAX_SIZE__MAX_SIZE__SHIFT 0x00000000
+#define VGT_DMA_NUM_INSTANCES__NUM_INSTANCES_MASK 0xffffffffL
+#define VGT_DMA_NUM_INSTANCES__NUM_INSTANCES__SHIFT 0x00000000
+#define VGT_DMA_REQ_FIFO_DEPTH__DMA_REQ_FIFO_DEPTH_MASK 0x0000003fL
+#define VGT_DMA_REQ_FIFO_DEPTH__DMA_REQ_FIFO_DEPTH__SHIFT 0x00000000
+#define VGT_DMA_SIZE__NUM_INDICES_MASK 0xffffffffL
+#define VGT_DMA_SIZE__NUM_INDICES__SHIFT 0x00000000
+#define VGT_DRAW_INIT_FIFO_DEPTH__DRAW_INIT_FIFO_DEPTH_MASK 0x0000003fL
+#define VGT_DRAW_INIT_FIFO_DEPTH__DRAW_INIT_FIFO_DEPTH__SHIFT 0x00000000
+#define VGT_DRAW_INITIATOR__MAJOR_MODE_MASK 0x0000000cL
+#define VGT_DRAW_INITIATOR__MAJOR_MODE__SHIFT 0x00000002
+#define VGT_DRAW_INITIATOR__NOT_EOP_MASK 0x00000020L
+#define VGT_DRAW_INITIATOR__NOT_EOP__SHIFT 0x00000005
+#define VGT_DRAW_INITIATOR__SOURCE_SELECT_MASK 0x00000003L
+#define VGT_DRAW_INITIATOR__SOURCE_SELECT__SHIFT 0x00000000
+#define VGT_DRAW_INITIATOR__SPRITE_EN_R6XX_MASK 0x00000010L
+#define VGT_DRAW_INITIATOR__SPRITE_EN_R6XX__SHIFT 0x00000004
+#define VGT_DRAW_INITIATOR__USE_OPAQUE_MASK 0x00000040L
+#define VGT_DRAW_INITIATOR__USE_OPAQUE__SHIFT 0x00000006
+#define VGT_ENHANCE__MISC_MASK 0xffffffffL
+#define VGT_ENHANCE__MISC__SHIFT 0x00000000
+#define VGT_ESGS_RING_ITEMSIZE__ITEMSIZE_MASK 0x00007fffL
+#define VGT_ESGS_RING_ITEMSIZE__ITEMSIZE__SHIFT 0x00000000
+#define VGT_ESGS_RING_SIZE__MEM_SIZE_MASK 0xffffffffL
+#define VGT_ESGS_RING_SIZE__MEM_SIZE__SHIFT 0x00000000
+#define VGT_ES_PER_GS__ES_PER_GS_MASK 0x000007ffL
+#define VGT_ES_PER_GS__ES_PER_GS__SHIFT 0x00000000
+#define VGT_EVENT_ADDRESS_REG__ADDRESS_LOW_MASK 0x0fffffffL
+#define VGT_EVENT_ADDRESS_REG__ADDRESS_LOW__SHIFT 0x00000000
+#define VGT_EVENT_INITIATOR__ADDRESS_HI_MASK 0x07fc0000L
+#define VGT_EVENT_INITIATOR__ADDRESS_HI__SHIFT 0x00000012
+#define VGT_EVENT_INITIATOR__EVENT_TYPE_MASK 0x0000003fL
+#define VGT_EVENT_INITIATOR__EVENT_TYPE__SHIFT 0x00000000
+#define VGT_EVENT_INITIATOR__EXTENDED_EVENT_MASK 0x08000000L
+#define VGT_EVENT_INITIATOR__EXTENDED_EVENT__SHIFT 0x0000001b
+#define VGT_FIFO_DEPTHS__CLIPP_FIFO_DEPTH_MASK 0x003fff00L
+#define VGT_FIFO_DEPTHS__CLIPP_FIFO_DEPTH__SHIFT 0x00000008
+#define VGT_FIFO_DEPTHS__RESERVED_0_MASK 0x00000080L
+#define VGT_FIFO_DEPTHS__RESERVED_0__SHIFT 0x00000007
+#define VGT_FIFO_DEPTHS__RESERVED_1_MASK 0xffc00000L
+#define VGT_FIFO_DEPTHS__RESERVED_1__SHIFT 0x00000016
+#define VGT_FIFO_DEPTHS__VS_DEALLOC_TBL_DEPTH_MASK 0x0000007fL
+#define VGT_FIFO_DEPTHS__VS_DEALLOC_TBL_DEPTH__SHIFT 0x00000000
+#define VGT_GROUP_DECR__DECR_MASK 0x0000000fL
+#define VGT_GROUP_DECR__DECR__SHIFT 0x00000000
+#define VGT_GROUP_FIRST_DECR__FIRST_DECR_MASK 0x0000000fL
+#define VGT_GROUP_FIRST_DECR__FIRST_DECR__SHIFT 0x00000000
+#define VGT_GROUP_PRIM_TYPE__PRIM_ORDER_MASK 0x00070000L
+#define VGT_GROUP_PRIM_TYPE__PRIM_ORDER__SHIFT 0x00000010
+#define VGT_GROUP_PRIM_TYPE__PRIM_TYPE_MASK 0x0000001fL
+#define VGT_GROUP_PRIM_TYPE__PRIM_TYPE__SHIFT 0x00000000
+#define VGT_GROUP_PRIM_TYPE__RETAIN_ORDER_MASK 0x00004000L
+#define VGT_GROUP_PRIM_TYPE__RETAIN_ORDER__SHIFT 0x0000000e
+#define VGT_GROUP_PRIM_TYPE__RETAIN_QUADS_MASK 0x00008000L
+#define VGT_GROUP_PRIM_TYPE__RETAIN_QUADS__SHIFT 0x0000000f
+#define VGT_GROUP_VECT_0_CNTL__COMP_W_EN_MASK 0x00000008L
+#define VGT_GROUP_VECT_0_CNTL__COMP_W_EN__SHIFT 0x00000003
+#define VGT_GROUP_VECT_0_CNTL__COMP_X_EN_MASK 0x00000001L
+#define VGT_GROUP_VECT_0_CNTL__COMP_X_EN__SHIFT 0x00000000
+#define VGT_GROUP_VECT_0_CNTL__COMP_Y_EN_MASK 0x00000002L
+#define VGT_GROUP_VECT_0_CNTL__COMP_Y_EN__SHIFT 0x00000001
+#define VGT_GROUP_VECT_0_CNTL__COMP_Z_EN_MASK 0x00000004L
+#define VGT_GROUP_VECT_0_CNTL__COMP_Z_EN__SHIFT 0x00000002
+#define VGT_GROUP_VECT_0_CNTL__SHIFT_MASK 0x00ff0000L
+#define VGT_GROUP_VECT_0_CNTL__SHIFT__SHIFT 0x00000010
+#define VGT_GROUP_VECT_0_CNTL__STRIDE_MASK 0x0000ff00L
+#define VGT_GROUP_VECT_0_CNTL__STRIDE__SHIFT 0x00000008
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_CONV_MASK 0x0f000000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_CONV__SHIFT 0x00000018
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_OFFSET_MASK 0xf0000000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__W_OFFSET__SHIFT 0x0000001c
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_CONV_MASK 0x0000000fL
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_CONV__SHIFT 0x00000000
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_OFFSET_MASK 0x000000f0L
+#define VGT_GROUP_VECT_0_FMT_CNTL__X_OFFSET__SHIFT 0x00000004
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_CONV_MASK 0x00000f00L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_CONV__SHIFT 0x00000008
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_OFFSET_MASK 0x0000f000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Y_OFFSET__SHIFT 0x0000000c
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_CONV_MASK 0x000f0000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_CONV__SHIFT 0x00000010
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_OFFSET_MASK 0x00f00000L
+#define VGT_GROUP_VECT_0_FMT_CNTL__Z_OFFSET__SHIFT 0x00000014
+#define VGT_GROUP_VECT_1_CNTL__COMP_W_EN_MASK 0x00000008L
+#define VGT_GROUP_VECT_1_CNTL__COMP_W_EN__SHIFT 0x00000003
+#define VGT_GROUP_VECT_1_CNTL__COMP_X_EN_MASK 0x00000001L
+#define VGT_GROUP_VECT_1_CNTL__COMP_X_EN__SHIFT 0x00000000
+#define VGT_GROUP_VECT_1_CNTL__COMP_Y_EN_MASK 0x00000002L
+#define VGT_GROUP_VECT_1_CNTL__COMP_Y_EN__SHIFT 0x00000001
+#define VGT_GROUP_VECT_1_CNTL__COMP_Z_EN_MASK 0x00000004L
+#define VGT_GROUP_VECT_1_CNTL__COMP_Z_EN__SHIFT 0x00000002
+#define VGT_GROUP_VECT_1_CNTL__SHIFT_MASK 0x00ff0000L
+#define VGT_GROUP_VECT_1_CNTL__SHIFT__SHIFT 0x00000010
+#define VGT_GROUP_VECT_1_CNTL__STRIDE_MASK 0x0000ff00L
+#define VGT_GROUP_VECT_1_CNTL__STRIDE__SHIFT 0x00000008
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_CONV_MASK 0x0f000000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_CONV__SHIFT 0x00000018
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_OFFSET_MASK 0xf0000000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__W_OFFSET__SHIFT 0x0000001c
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_CONV_MASK 0x0000000fL
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_CONV__SHIFT 0x00000000
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_OFFSET_MASK 0x000000f0L
+#define VGT_GROUP_VECT_1_FMT_CNTL__X_OFFSET__SHIFT 0x00000004
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_CONV_MASK 0x00000f00L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_CONV__SHIFT 0x00000008
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_OFFSET_MASK 0x0000f000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Y_OFFSET__SHIFT 0x0000000c
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_CONV_MASK 0x000f0000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_CONV__SHIFT 0x00000010
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_OFFSET_MASK 0x00f00000L
+#define VGT_GROUP_VECT_1_FMT_CNTL__Z_OFFSET__SHIFT 0x00000014
+#define VGT_GS_INSTANCE_CNT__CNT_MASK 0x000001fcL
+#define VGT_GS_INSTANCE_CNT__CNT__SHIFT 0x00000002
+#define VGT_GS_INSTANCE_CNT__ENABLE_MASK 0x00000001L
+#define VGT_GS_INSTANCE_CNT__ENABLE__SHIFT 0x00000000
+#define VGT_GS_MAX_VERT_OUT__MAX_VERT_OUT_MASK 0x000007ffL
+#define VGT_GS_MAX_VERT_OUT__MAX_VERT_OUT__SHIFT 0x00000000
+#define VGT_GS_MODE__COMPUTE_MODE_MASK 0x00004000L
+#define VGT_GS_MODE__COMPUTE_MODE__SHIFT 0x0000000e
+#define VGT_GS_MODE__CUT_MODE_MASK 0x00000030L
+#define VGT_GS_MODE__CUT_MODE__SHIFT 0x00000004
+#define VGT_GS_MODE__ELEMENT_INFO_EN_MASK 0x00010000L
+#define VGT_GS_MODE__ELEMENT_INFO_EN__SHIFT 0x00000010
+#define VGT_GS_MODE__ES_PASSTHRU_MASK 0x00002000L
+#define VGT_GS_MODE__ES_PASSTHRU__SHIFT 0x0000000d
+#define VGT_GS_MODE__ES_WRITE_OPTIMIZE_MASK 0x00080000L
+#define VGT_GS_MODE__ES_WRITE_OPTIMIZE__SHIFT 0x00000013
+#define VGT_GS_MODE__FAST_COMPUTE_MODE_MASK 0x00008000L
+#define VGT_GS_MODE__FAST_COMPUTE_MODE__SHIFT 0x0000000f
+#define VGT_GS_MODE__GS_C_PACK_EN_MASK 0x00000800L
+#define VGT_GS_MODE__GS_C_PACK_EN__SHIFT 0x0000000b
+#define VGT_GS_MODE__GS_WRITE_OPTIMIZE_MASK 0x00100000L
+#define VGT_GS_MODE__GS_WRITE_OPTIMIZE__SHIFT 0x00000014
+#define VGT_GS_MODE__MODE_MASK 0x00000007L
+#define VGT_GS_MODE__MODE__SHIFT 0x00000000
+#define VGT_GS_MODE__ONCHIP_MASK 0x00600000L
+#define VGT_GS_MODE__ONCHIP__SHIFT 0x00000015
+#define VGT_GS_MODE__PARTIAL_THD_AT_EOI_MASK 0x00020000L
+#define VGT_GS_MODE__PARTIAL_THD_AT_EOI__SHIFT 0x00000011
+#define VGT_GS_MODE__RESERVED_0_MASK 0x00000008L
+#define VGT_GS_MODE__RESERVED_0__SHIFT 0x00000003
+#define VGT_GS_MODE__RESERVED_1_MASK 0x000007c0L
+#define VGT_GS_MODE__RESERVED_1__SHIFT 0x00000006
+#define VGT_GS_MODE__RESERVED_2_MASK 0x00001000L
+#define VGT_GS_MODE__RESERVED_2__SHIFT 0x0000000c
+#define VGT_GS_MODE__SUPPRESS_CUTS_MASK 0x00040000L
+#define VGT_GS_MODE__SUPPRESS_CUTS__SHIFT 0x00000012
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_1_MASK 0x00003f00L
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_1__SHIFT 0x00000008
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_2_MASK 0x003f0000L
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_2__SHIFT 0x00000010
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_3_MASK 0x0fc00000L
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_3__SHIFT 0x00000016
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE_MASK 0x0000003fL
+#define VGT_GS_OUT_PRIM_TYPE__OUTPRIM_TYPE__SHIFT 0x00000000
+#define VGT_GS_OUT_PRIM_TYPE__UNIQUE_TYPE_PER_STREAM_MASK 0x80000000L
+#define VGT_GS_OUT_PRIM_TYPE__UNIQUE_TYPE_PER_STREAM__SHIFT 0x0000001f
+#define VGT_GS_PER_ES__GS_PER_ES_MASK 0x000007ffL
+#define VGT_GS_PER_ES__GS_PER_ES__SHIFT 0x00000000
+#define VGT_GS_PER_VS__GS_PER_VS_MASK 0x0000000fL
+#define VGT_GS_PER_VS__GS_PER_VS__SHIFT 0x00000000
+#define VGT_GS_VERTEX_REUSE__VERT_REUSE_MASK 0x0000001fL
+#define VGT_GS_VERTEX_REUSE__VERT_REUSE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE_1__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE_1__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE_2__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE_2__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE_3__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE_3__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GS_VERT_ITEMSIZE__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GS_VERT_ITEMSIZE__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GSVS_RING_ITEMSIZE__ITEMSIZE_MASK 0x00007fffL
+#define VGT_GSVS_RING_ITEMSIZE__ITEMSIZE__SHIFT 0x00000000
+#define VGT_GSVS_RING_OFFSET_1__OFFSET_MASK 0x00007fffL
+#define VGT_GSVS_RING_OFFSET_1__OFFSET__SHIFT 0x00000000
+#define VGT_GSVS_RING_OFFSET_2__OFFSET_MASK 0x00007fffL
+#define VGT_GSVS_RING_OFFSET_2__OFFSET__SHIFT 0x00000000
+#define VGT_GSVS_RING_OFFSET_3__OFFSET_MASK 0x00007fffL
+#define VGT_GSVS_RING_OFFSET_3__OFFSET__SHIFT 0x00000000
+#define VGT_GSVS_RING_SIZE__MEM_SIZE_MASK 0xffffffffL
+#define VGT_GSVS_RING_SIZE__MEM_SIZE__SHIFT 0x00000000
+#define VGT_HOS_CNTL__TESS_MODE_MASK 0x00000003L
+#define VGT_HOS_CNTL__TESS_MODE__SHIFT 0x00000000
+#define VGT_HOS_MAX_TESS_LEVEL__MAX_TESS_MASK 0xffffffffL
+#define VGT_HOS_MAX_TESS_LEVEL__MAX_TESS__SHIFT 0x00000000
+#define VGT_HOS_MIN_TESS_LEVEL__MIN_TESS_MASK 0xffffffffL
+#define VGT_HOS_MIN_TESS_LEVEL__MIN_TESS__SHIFT 0x00000000
+#define VGT_HOS_REUSE_DEPTH__REUSE_DEPTH_MASK 0x000000ffL
+#define VGT_HOS_REUSE_DEPTH__REUSE_DEPTH__SHIFT 0x00000000
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_BUFFERING_MASK 0x0000007fL
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_BUFFERING__SHIFT 0x00000000
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY_MASK 0x00000600L
+#define VGT_HS_OFFCHIP_PARAM__OFFCHIP_GRANULARITY__SHIFT 0x00000009
+#define VGT_IMMED_DATA__DATA_MASK 0xffffffffL
+#define VGT_IMMED_DATA__DATA__SHIFT 0x00000000
+#define VGT_INDEX_TYPE__INDEX_TYPE_MASK 0x00000003L
+#define VGT_INDEX_TYPE__INDEX_TYPE__SHIFT 0x00000000
+#define VGT_INDX_OFFSET__INDX_OFFSET_MASK 0xffffffffL
+#define VGT_INDX_OFFSET__INDX_OFFSET__SHIFT 0x00000000
+#define VGT_INSTANCE_STEP_RATE_0__STEP_RATE_MASK 0xffffffffL
+#define VGT_INSTANCE_STEP_RATE_0__STEP_RATE__SHIFT 0x00000000
+#define VGT_INSTANCE_STEP_RATE_1__STEP_RATE_MASK 0xffffffffL
+#define VGT_INSTANCE_STEP_RATE_1__STEP_RATE__SHIFT 0x00000000
+#define VGT_LAST_COPY_STATE__DST_STATE_ID_MASK 0x00070000L
+#define VGT_LAST_COPY_STATE__DST_STATE_ID__SHIFT 0x00000010
+#define VGT_LAST_COPY_STATE__SRC_STATE_ID_MASK 0x00000007L
+#define VGT_LAST_COPY_STATE__SRC_STATE_ID__SHIFT 0x00000000
+#define VGT_LS_HS_CONFIG__HS_NUM_INPUT_CP_MASK 0x00003f00L
+#define VGT_LS_HS_CONFIG__HS_NUM_INPUT_CP__SHIFT 0x00000008
+#define VGT_LS_HS_CONFIG__HS_NUM_OUTPUT_CP_MASK 0x000fc000L
+#define VGT_LS_HS_CONFIG__HS_NUM_OUTPUT_CP__SHIFT 0x0000000e
+#define VGT_LS_HS_CONFIG__NUM_PATCHES_MASK 0x000000ffL
+#define VGT_LS_HS_CONFIG__NUM_PATCHES__SHIFT 0x00000000
+#define VGT_MAX_VTX_INDX__MAX_INDX_MASK 0xffffffffL
+#define VGT_MAX_VTX_INDX__MAX_INDX__SHIFT 0x00000000
+#define VGT_MC_LAT_CNTL__MC_TIME_STAMP_RES_MASK 0x00000003L
+#define VGT_MC_LAT_CNTL__MC_TIME_STAMP_RES__SHIFT 0x00000000
+#define VGT_MIN_VTX_INDX__MIN_INDX_MASK 0xffffffffL
+#define VGT_MIN_VTX_INDX__MIN_INDX__SHIFT 0x00000000
+#define VGT_MULTI_PRIM_IB_RESET_EN__RESET_EN_MASK 0x00000001L
+#define VGT_MULTI_PRIM_IB_RESET_EN__RESET_EN__SHIFT 0x00000000
+#define VGT_MULTI_PRIM_IB_RESET_INDX__RESET_INDX_MASK 0xffffffffL
+#define VGT_MULTI_PRIM_IB_RESET_INDX__RESET_INDX__SHIFT 0x00000000
+#define VGT_NUM_INDICES__NUM_INDICES_MASK 0xffffffffL
+#define VGT_NUM_INDICES__NUM_INDICES__SHIFT 0x00000000
+#define VGT_NUM_INSTANCES__NUM_INSTANCES_MASK 0xffffffffL
+#define VGT_NUM_INSTANCES__NUM_INSTANCES__SHIFT 0x00000000
+#define VGT_OUT_DEALLOC_CNTL__DEALLOC_DIST_MASK 0x0000007fL
+#define VGT_OUT_DEALLOC_CNTL__DEALLOC_DIST__SHIFT 0x00000000
+#define VGT_OUTPUT_PATH_CNTL__PATH_SELECT_MASK 0x00000007L
+#define VGT_OUTPUT_PATH_CNTL__PATH_SELECT__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER0_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER0_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define VGT_PERFCOUNTER0_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER0_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER0_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define VGT_PERFCOUNTER0_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER0_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER1_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER1_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE2_MASK 0xf0000000L
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE2__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE3_MASK 0x0f000000L
+#define VGT_PERFCOUNTER1_SELECT1__PERF_MODE3__SHIFT 0x00000018
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL2_MASK 0x000003ffL
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL2__SHIFT 0x00000000
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL3_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER1_SELECT1__PERF_SEL3__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER1_SELECT__CNTR_MODE_MASK 0x00f00000L
+#define VGT_PERFCOUNTER1_SELECT__CNTR_MODE__SHIFT 0x00000014
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE1_MASK 0x0f000000L
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE1__SHIFT 0x00000018
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER1_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL1_MASK 0x000ffc00L
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL1__SHIFT 0x0000000a
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER2_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER2_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER2_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER2_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER2_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER2_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER2_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER2_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER3_HI__PERFCOUNTER_HI_MASK 0xffffffffL
+#define VGT_PERFCOUNTER3_HI__PERFCOUNTER_HI__SHIFT 0x00000000
+#define VGT_PERFCOUNTER3_LO__PERFCOUNTER_LO_MASK 0xffffffffL
+#define VGT_PERFCOUNTER3_LO__PERFCOUNTER_LO__SHIFT 0x00000000
+#define VGT_PERFCOUNTER3_SELECT__PERF_MODE_MASK 0xf0000000L
+#define VGT_PERFCOUNTER3_SELECT__PERF_MODE__SHIFT 0x0000001c
+#define VGT_PERFCOUNTER3_SELECT__PERF_SEL_MASK 0x000000ffL
+#define VGT_PERFCOUNTER3_SELECT__PERF_SEL__SHIFT 0x00000000
+#define VGT_PERFCOUNTER_SEID_MASK__PERF_SEID_IGNORE_MASK_MASK 0x000000ffL
+#define VGT_PERFCOUNTER_SEID_MASK__PERF_SEID_IGNORE_MASK__SHIFT 0x00000000
+#define VGT_PRIMITIVEID_EN__DISABLE_RESET_ON_EOI_MASK 0x00000002L
+#define VGT_PRIMITIVEID_EN__DISABLE_RESET_ON_EOI__SHIFT 0x00000001
+#define VGT_PRIMITIVEID_EN__PRIMITIVEID_EN_MASK 0x00000001L
+#define VGT_PRIMITIVEID_EN__PRIMITIVEID_EN__SHIFT 0x00000000
+#define VGT_PRIMITIVEID_RESET__VALUE_MASK 0xffffffffL
+#define VGT_PRIMITIVEID_RESET__VALUE__SHIFT 0x00000000
+#define VGT_PRIMITIVE_TYPE__PRIM_TYPE_MASK 0x0000003fL
+#define VGT_PRIMITIVE_TYPE__PRIM_TYPE__SHIFT 0x00000000
+#define VGT_REUSE_OFF__REUSE_OFF_MASK 0x00000001L
+#define VGT_REUSE_OFF__REUSE_OFF__SHIFT 0x00000000
+#define VGT_SHADER_STAGES_EN__DYNAMIC_HS_MASK 0x00000100L
+#define VGT_SHADER_STAGES_EN__DYNAMIC_HS__SHIFT 0x00000008
+#define VGT_SHADER_STAGES_EN__ES_EN_MASK 0x00000018L
+#define VGT_SHADER_STAGES_EN__ES_EN__SHIFT 0x00000003
+#define VGT_SHADER_STAGES_EN__GS_EN_MASK 0x00000020L
+#define VGT_SHADER_STAGES_EN__GS_EN__SHIFT 0x00000005
+#define VGT_SHADER_STAGES_EN__HS_EN_MASK 0x00000004L
+#define VGT_SHADER_STAGES_EN__HS_EN__SHIFT 0x00000002
+#define VGT_SHADER_STAGES_EN__LS_EN_MASK 0x00000003L
+#define VGT_SHADER_STAGES_EN__LS_EN__SHIFT 0x00000000
+#define VGT_SHADER_STAGES_EN__VS_EN_MASK 0x000000c0L
+#define VGT_SHADER_STAGES_EN__VS_EN__SHIFT 0x00000006
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_0_BUFFER_EN_MASK 0x0000000fL
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_0_BUFFER_EN__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_1_BUFFER_EN_MASK 0x000000f0L
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_1_BUFFER_EN__SHIFT 0x00000004
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_2_BUFFER_EN_MASK 0x00000f00L
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_2_BUFFER_EN__SHIFT 0x00000008
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_3_BUFFER_EN_MASK 0x0000f000L
+#define VGT_STRMOUT_BUFFER_CONFIG__STREAM_3_BUFFER_EN__SHIFT 0x0000000c
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_0__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_0__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_1__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_1__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_2__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_2__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_3__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_FILLED_SIZE_3__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_0__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_0__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_1__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_1__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_2__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_2__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_OFFSET_3__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_OFFSET_3__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_0__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_0__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_1__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_1__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_2__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_2__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_BUFFER_SIZE_3__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_BUFFER_SIZE_3__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK 0x00000070L
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK_MASK 0x00000f00L
+#define VGT_STRMOUT_CONFIG__RAST_STREAM_MASK__SHIFT 0x00000008
+#define VGT_STRMOUT_CONFIG__RAST_STREAM__SHIFT 0x00000004
+#define VGT_STRMOUT_CONFIG__STREAMOUT_0_EN_MASK 0x00000001L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_0_EN__SHIFT 0x00000000
+#define VGT_STRMOUT_CONFIG__STREAMOUT_1_EN_MASK 0x00000002L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_1_EN__SHIFT 0x00000001
+#define VGT_STRMOUT_CONFIG__STREAMOUT_2_EN_MASK 0x00000004L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_2_EN__SHIFT 0x00000002
+#define VGT_STRMOUT_CONFIG__STREAMOUT_3_EN_MASK 0x00000008L
+#define VGT_STRMOUT_CONFIG__STREAMOUT_3_EN__SHIFT 0x00000003
+#define VGT_STRMOUT_CONFIG__USE_RAST_STREAM_MASK_MASK 0x80000000L
+#define VGT_STRMOUT_CONFIG__USE_RAST_STREAM_MASK__SHIFT 0x0000001f
+#define VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE__SIZE_MASK 0xffffffffL
+#define VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE__SIZE__SHIFT 0x00000000
+#define VGT_STRMOUT_DRAW_OPAQUE_OFFSET__OFFSET_MASK 0xffffffffL
+#define VGT_STRMOUT_DRAW_OPAQUE_OFFSET__OFFSET__SHIFT 0x00000000
+#define VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE__VERTEX_STRIDE_MASK 0x000001ffL
+#define VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE__VERTEX_STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_0__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_0__STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_1__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_1__STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_2__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_2__STRIDE__SHIFT 0x00000000
+#define VGT_STRMOUT_VTX_STRIDE_3__STRIDE_MASK 0x000003ffL
+#define VGT_STRMOUT_VTX_STRIDE_3__STRIDE__SHIFT 0x00000000
+#define VGT_SYS_CONFIG__ADC_EVENT_FILTER_DISABLE_MASK 0x00000080L
+#define VGT_SYS_CONFIG__ADC_EVENT_FILTER_DISABLE__SHIFT 0x00000007
+#define VGT_SYS_CONFIG__DUAL_CORE_EN_MASK 0x00000001L
+#define VGT_SYS_CONFIG__DUAL_CORE_EN__SHIFT 0x00000000
+#define VGT_SYS_CONFIG__MAX_LS_HS_THDGRP_MASK 0x0000007eL
+#define VGT_SYS_CONFIG__MAX_LS_HS_THDGRP__SHIFT 0x00000001
+#define VGT_TF_MEMORY_BASE__BASE_MASK 0xffffffffL
+#define VGT_TF_MEMORY_BASE__BASE__SHIFT 0x00000000
+#define VGT_TF_PARAM__DEPRECATED_MASK 0x00000200L
+#define VGT_TF_PARAM__DEPRECATED__SHIFT 0x00000009
+#define VGT_TF_PARAM__DISABLE_DONUTS_MASK 0x00004000L
+#define VGT_TF_PARAM__DISABLE_DONUTS__SHIFT 0x0000000e
+#define VGT_TF_PARAM__NUM_DS_WAVES_PER_SIMD_MASK 0x00003c00L
+#define VGT_TF_PARAM__NUM_DS_WAVES_PER_SIMD__SHIFT 0x0000000a
+#define VGT_TF_PARAM__PARTITIONING_MASK 0x0000001cL
+#define VGT_TF_PARAM__PARTITIONING__SHIFT 0x00000002
+#define VGT_TF_PARAM__RDREQ_POLICY_MASK 0x00018000L
+#define VGT_TF_PARAM__RDREQ_POLICY__SHIFT 0x0000000f
+#define VGT_TF_PARAM__RESERVED_REDUC_AXIS_MASK 0x00000100L
+#define VGT_TF_PARAM__RESERVED_REDUC_AXIS__SHIFT 0x00000008
+#define VGT_TF_PARAM__TOPOLOGY_MASK 0x000000e0L
+#define VGT_TF_PARAM__TOPOLOGY__SHIFT 0x00000005
+#define VGT_TF_PARAM__TYPE_MASK 0x00000003L
+#define VGT_TF_PARAM__TYPE__SHIFT 0x00000000
+#define VGT_TF_RING_SIZE__SIZE_MASK 0x0000ffffL
+#define VGT_TF_RING_SIZE__SIZE__SHIFT 0x00000000
+#define VGT_VERTEX_REUSE_BLOCK_CNTL__VTX_REUSE_DEPTH_MASK 0x000000ffL
+#define VGT_VERTEX_REUSE_BLOCK_CNTL__VTX_REUSE_DEPTH__SHIFT 0x00000000
+#define VGT_VTX_CNT_EN__VTX_CNT_EN_MASK 0x00000001L
+#define VGT_VTX_CNT_EN__VTX_CNT_EN__SHIFT 0x00000000
+#define VGT_VTX_VECT_EJECT_REG__PRIM_COUNT_MASK 0x000003ffL
+#define VGT_VTX_VECT_EJECT_REG__PRIM_COUNT__SHIFT 0x00000000
+#define WD_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define WD_DEBUG_DATA__DATA__SHIFT 0x00000000
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1274 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 GMC_6_0_D_H
+#define GMC_6_0_D_H
+
+#define ixMC_IO_DEBUG_ACMD_CLKSEL_D0 0x00CE
+#define ixMC_IO_DEBUG_ACMD_CLKSEL_D1 0x00DE
+#define ixMC_IO_DEBUG_ACMD_MISC_D0 0x00AE
+#define ixMC_IO_DEBUG_ACMD_MISC_D1 0x00BE
+#define ixMC_IO_DEBUG_ACMD_OFSCAL_D0 0x00EE
+#define ixMC_IO_DEBUG_ACMD_OFSCAL_D1 0x00FE
+#define ixMC_IO_DEBUG_ACMD_RXPHASE_D0 0x010E
+#define ixMC_IO_DEBUG_ACMD_RXPHASE_D1 0x011E
+#define ixMC_IO_DEBUG_ACMD_TXBST_PD_D0 0x018E
+#define ixMC_IO_DEBUG_ACMD_TXBST_PD_D1 0x019E
+#define ixMC_IO_DEBUG_ACMD_TXBST_PU_D0 0x01AE
+#define ixMC_IO_DEBUG_ACMD_TXBST_PU_D1 0x01BE
+#define ixMC_IO_DEBUG_ACMD_TXPHASE_D0 0x012E
+#define ixMC_IO_DEBUG_ACMD_TXPHASE_D1 0x013E
+#define ixMC_IO_DEBUG_ACMD_TXSLF_D0 0x016E
+#define ixMC_IO_DEBUG_ACMD_TXSLF_D1 0x017E
+#define ixMC_IO_DEBUG_ADDRH_CLKSEL_D0 0x00CD
+#define ixMC_IO_DEBUG_ADDRH_CLKSEL_D1 0x00DD
+#define ixMC_IO_DEBUG_ADDRH_MISC_D0 0x00AD
+#define ixMC_IO_DEBUG_ADDRH_MISC_D1 0x00BD
+#define ixMC_IO_DEBUG_ADDRH_RXPHASE_D0 0x010D
+#define ixMC_IO_DEBUG_ADDRH_RXPHASE_D1 0x011D
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PD_D0 0x018D
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PD_D1 0x019D
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PU_D0 0x01AD
+#define ixMC_IO_DEBUG_ADDRH_TXBST_PU_D1 0x01BD
+#define ixMC_IO_DEBUG_ADDRH_TXPHASE_D0 0x012D
+#define ixMC_IO_DEBUG_ADDRH_TXPHASE_D1 0x013D
+#define ixMC_IO_DEBUG_ADDRH_TXSLF_D0 0x016D
+#define ixMC_IO_DEBUG_ADDRH_TXSLF_D1 0x017D
+#define ixMC_IO_DEBUG_ADDRL_CLKSEL_D0 0x00CC
+#define ixMC_IO_DEBUG_ADDRL_CLKSEL_D1 0x00DC
+#define ixMC_IO_DEBUG_ADDRL_MISC_D0 0x00AC
+#define ixMC_IO_DEBUG_ADDRL_MISC_D1 0x00BC
+#define ixMC_IO_DEBUG_ADDRL_RXPHASE_D0 0x010C
+#define ixMC_IO_DEBUG_ADDRL_RXPHASE_D1 0x011C
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PD_D0 0x018C
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PD_D1 0x019C
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PU_D0 0x01AC
+#define ixMC_IO_DEBUG_ADDRL_TXBST_PU_D1 0x01BC
+#define ixMC_IO_DEBUG_ADDRL_TXPHASE_D0 0x012C
+#define ixMC_IO_DEBUG_ADDRL_TXPHASE_D1 0x013C
+#define ixMC_IO_DEBUG_ADDRL_TXSLF_D0 0x016C
+#define ixMC_IO_DEBUG_ADDRL_TXSLF_D1 0x017C
+#define ixMC_IO_DEBUG_CK_CLKSEL_D0 0x00CB
+#define ixMC_IO_DEBUG_CK_CLKSEL_D1 0x00DB
+#define ixMC_IO_DEBUG_CK_MISC_D0 0x00AB
+#define ixMC_IO_DEBUG_CK_MISC_D1 0x00BB
+#define ixMC_IO_DEBUG_CK_RXPHASE_D0 0x010B
+#define ixMC_IO_DEBUG_CK_RXPHASE_D1 0x011B
+#define ixMC_IO_DEBUG_CK_TXBST_PD_D0 0x018B
+#define ixMC_IO_DEBUG_CK_TXBST_PD_D1 0x019B
+#define ixMC_IO_DEBUG_CK_TXBST_PU_D0 0x01AB
+#define ixMC_IO_DEBUG_CK_TXBST_PU_D1 0x01BB
+#define ixMC_IO_DEBUG_CK_TXPHASE_D0 0x012B
+#define ixMC_IO_DEBUG_CK_TXPHASE_D1 0x013B
+#define ixMC_IO_DEBUG_CK_TXSLF_D0 0x016B
+#define ixMC_IO_DEBUG_CK_TXSLF_D1 0x017B
+#define ixMC_IO_DEBUG_CMD_CLKSEL_D0 0x00CF
+#define ixMC_IO_DEBUG_CMD_CLKSEL_D1 0x00DF
+#define ixMC_IO_DEBUG_CMD_MISC_D0 0x00AF
+#define ixMC_IO_DEBUG_CMD_MISC_D1 0x00BF
+#define ixMC_IO_DEBUG_CMD_OFSCAL_D0 0x00EF
+#define ixMC_IO_DEBUG_CMD_OFSCAL_D1 0x00FF
+#define ixMC_IO_DEBUG_CMD_RX_EQ_D0 0x01CF
+#define ixMC_IO_DEBUG_CMD_RX_EQ_D1 0x01DF
+#define ixMC_IO_DEBUG_CMD_RXPHASE_D0 0x010F
+#define ixMC_IO_DEBUG_CMD_RXPHASE_D1 0x011F
+#define ixMC_IO_DEBUG_CMD_TXBST_PD_D0 0x018F
+#define ixMC_IO_DEBUG_CMD_TXBST_PD_D1 0x019F
+#define ixMC_IO_DEBUG_CMD_TXBST_PU_D0 0x01AF
+#define ixMC_IO_DEBUG_CMD_TXBST_PU_D1 0x01BF
+#define ixMC_IO_DEBUG_CMD_TXPHASE_D0 0x012F
+#define ixMC_IO_DEBUG_CMD_TXPHASE_D1 0x013F
+#define ixMC_IO_DEBUG_CMD_TXSLF_D0 0x016F
+#define ixMC_IO_DEBUG_CMD_TXSLF_D1 0x017F
+#define ixMC_IO_DEBUG_DBI_CDR_PHSIZE_D0 0x014F
+#define ixMC_IO_DEBUG_DBI_CDR_PHSIZE_D1 0x015F
+#define ixMC_IO_DEBUG_DBI_CLKSEL_D0 0x00C8
+#define ixMC_IO_DEBUG_DBI_CLKSEL_D1 0x00D8
+#define ixMC_IO_DEBUG_DBI_MISC_D0 0x00A8
+#define ixMC_IO_DEBUG_DBI_MISC_D1 0x00B8
+#define ixMC_IO_DEBUG_DBI_OFSCAL_D0 0x00E8
+#define ixMC_IO_DEBUG_DBI_OFSCAL_D1 0x00F8
+#define ixMC_IO_DEBUG_DBI_RX_EQ_D0 0x01C8
+#define ixMC_IO_DEBUG_DBI_RX_EQ_D1 0x01D8
+#define ixMC_IO_DEBUG_DBI_RXPHASE_D0 0x0108
+#define ixMC_IO_DEBUG_DBI_RXPHASE_D1 0x0118
+#define ixMC_IO_DEBUG_DBI_RX_VREF_CAL_D0 0x0148
+#define ixMC_IO_DEBUG_DBI_RX_VREF_CAL_D1 0x0158
+#define ixMC_IO_DEBUG_DBI_TXBST_PD_D0 0x0188
+#define ixMC_IO_DEBUG_DBI_TXBST_PD_D1 0x0198
+#define ixMC_IO_DEBUG_DBI_TXBST_PU_D0 0x01A8
+#define ixMC_IO_DEBUG_DBI_TXBST_PU_D1 0x01B8
+#define ixMC_IO_DEBUG_DBI_TXPHASE_D0 0x0128
+#define ixMC_IO_DEBUG_DBI_TXPHASE_D1 0x0138
+#define ixMC_IO_DEBUG_DBI_TXSLF_D0 0x0168
+#define ixMC_IO_DEBUG_DBI_TXSLF_D1 0x0178
+#define ixMC_IO_DEBUG_DQ0_RX_DYN_PM_D0 0x01CD
+#define ixMC_IO_DEBUG_DQ0_RX_DYN_PM_D1 0x01DD
+#define ixMC_IO_DEBUG_DQ0_RX_EQ_PM_D0 0x01CB
+#define ixMC_IO_DEBUG_DQ0_RX_EQ_PM_D1 0x01DB
+#define ixMC_IO_DEBUG_DQ1_RX_DYN_PM_D0 0x01CE
+#define ixMC_IO_DEBUG_DQ1_RX_DYN_PM_D1 0x01DE
+#define ixMC_IO_DEBUG_DQ1_RX_EQ_PM_D0 0x01CC
+#define ixMC_IO_DEBUG_DQ1_RX_EQ_PM_D1 0x01DC
+#define ixMC_IO_DEBUG_DQB0_CDR_PHSIZE_D0 0x014B
+#define ixMC_IO_DEBUG_DQB0_CDR_PHSIZE_D1 0x015B
+#define ixMC_IO_DEBUG_DQB0H_CLKSEL_D0 0x00C1
+#define ixMC_IO_DEBUG_DQB0H_CLKSEL_D1 0x00D1
+#define ixMC_IO_DEBUG_DQB0H_MISC_D0 0x00A1
+#define ixMC_IO_DEBUG_DQB0H_MISC_D1 0x00B1
+#define ixMC_IO_DEBUG_DQB0H_OFSCAL_D0 0x00E1
+#define ixMC_IO_DEBUG_DQB0H_OFSCAL_D1 0x00F1
+#define ixMC_IO_DEBUG_DQB0H_RX_EQ_D0 0x01C1
+#define ixMC_IO_DEBUG_DQB0H_RX_EQ_D1 0x01D1
+#define ixMC_IO_DEBUG_DQB0H_RXPHASE_D0 0x0101
+#define ixMC_IO_DEBUG_DQB0H_RXPHASE_D1 0x0111
+#define ixMC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0 0x0141
+#define ixMC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1 0x0151
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PD_D0 0x0181
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PD_D1 0x0191
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PU_D0 0x01A1
+#define ixMC_IO_DEBUG_DQB0H_TXBST_PU_D1 0x01B1
+#define ixMC_IO_DEBUG_DQB0H_TXPHASE_D0 0x0121
+#define ixMC_IO_DEBUG_DQB0H_TXPHASE_D1 0x0131
+#define ixMC_IO_DEBUG_DQB0H_TXSLF_D0 0x0161
+#define ixMC_IO_DEBUG_DQB0H_TXSLF_D1 0x0171
+#define ixMC_IO_DEBUG_DQB0L_CLKSEL_D0 0x00C0
+#define ixMC_IO_DEBUG_DQB0L_CLKSEL_D1 0x00D0
+#define ixMC_IO_DEBUG_DQB0L_MISC_D0 0x00A0
+#define ixMC_IO_DEBUG_DQB0L_MISC_D1 0x00B0
+#define ixMC_IO_DEBUG_DQB0L_OFSCAL_D0 0x00E0
+#define ixMC_IO_DEBUG_DQB0L_OFSCAL_D1 0x00F0
+#define ixMC_IO_DEBUG_DQB0L_RX_EQ_D0 0x01C0
+#define ixMC_IO_DEBUG_DQB0L_RX_EQ_D1 0x01D0
+#define ixMC_IO_DEBUG_DQB0L_RXPHASE_D0 0x0100
+#define ixMC_IO_DEBUG_DQB0L_RXPHASE_D1 0x0110
+#define ixMC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0 0x0140
+#define ixMC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1 0x0150
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PD_D0 0x0180
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PD_D1 0x0190
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PU_D0 0x01A0
+#define ixMC_IO_DEBUG_DQB0L_TXBST_PU_D1 0x01B0
+#define ixMC_IO_DEBUG_DQB0L_TXPHASE_D0 0x0120
+#define ixMC_IO_DEBUG_DQB0L_TXPHASE_D1 0x0130
+#define ixMC_IO_DEBUG_DQB0L_TXSLF_D0 0x0160
+#define ixMC_IO_DEBUG_DQB0L_TXSLF_D1 0x0170
+#define ixMC_IO_DEBUG_DQB1_CDR_PHSIZE_D0 0x014C
+#define ixMC_IO_DEBUG_DQB1_CDR_PHSIZE_D1 0x015C
+#define ixMC_IO_DEBUG_DQB1H_CLKSEL_D0 0x00C3
+#define ixMC_IO_DEBUG_DQB1H_CLKSEL_D1 0x00D3
+#define ixMC_IO_DEBUG_DQB1H_MISC_D0 0x00A3
+#define ixMC_IO_DEBUG_DQB1H_MISC_D1 0x00B3
+#define ixMC_IO_DEBUG_DQB1H_OFSCAL_D0 0x00E3
+#define ixMC_IO_DEBUG_DQB1H_OFSCAL_D1 0x00F3
+#define ixMC_IO_DEBUG_DQB1H_RX_EQ_D0 0x01C3
+#define ixMC_IO_DEBUG_DQB1H_RX_EQ_D1 0x01D3
+#define ixMC_IO_DEBUG_DQB1H_RXPHASE_D0 0x0103
+#define ixMC_IO_DEBUG_DQB1H_RXPHASE_D1 0x0113
+#define ixMC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0 0x0143
+#define ixMC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1 0x0153
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PD_D0 0x0183
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PD_D1 0x0193
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PU_D0 0x01A3
+#define ixMC_IO_DEBUG_DQB1H_TXBST_PU_D1 0x01B3
+#define ixMC_IO_DEBUG_DQB1H_TXPHASE_D0 0x0123
+#define ixMC_IO_DEBUG_DQB1H_TXPHASE_D1 0x0133
+#define ixMC_IO_DEBUG_DQB1H_TXSLF_D0 0x0163
+#define ixMC_IO_DEBUG_DQB1H_TXSLF_D1 0x0173
+#define ixMC_IO_DEBUG_DQB1L_CLKSEL_D0 0x00C2
+#define ixMC_IO_DEBUG_DQB1L_CLKSEL_D1 0x00D2
+#define ixMC_IO_DEBUG_DQB1L_MISC_D0 0x00A2
+#define ixMC_IO_DEBUG_DQB1L_MISC_D1 0x00B2
+#define ixMC_IO_DEBUG_DQB1L_OFSCAL_D0 0x00E2
+#define ixMC_IO_DEBUG_DQB1L_OFSCAL_D1 0x00F2
+#define ixMC_IO_DEBUG_DQB1L_RX_EQ_D0 0x01C2
+#define ixMC_IO_DEBUG_DQB1L_RX_EQ_D1 0x01D2
+#define ixMC_IO_DEBUG_DQB1L_RXPHASE_D0 0x0102
+#define ixMC_IO_DEBUG_DQB1L_RXPHASE_D1 0x0112
+#define ixMC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0 0x0142
+#define ixMC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1 0x0152
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PD_D0 0x0182
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PD_D1 0x0192
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PU_D0 0x01A2
+#define ixMC_IO_DEBUG_DQB1L_TXBST_PU_D1 0x01B2
+#define ixMC_IO_DEBUG_DQB1L_TXPHASE_D0 0x0122
+#define ixMC_IO_DEBUG_DQB1L_TXPHASE_D1 0x0132
+#define ixMC_IO_DEBUG_DQB1L_TXSLF_D0 0x0162
+#define ixMC_IO_DEBUG_DQB1L_TXSLF_D1 0x0172
+#define ixMC_IO_DEBUG_DQB2_CDR_PHSIZE_D0 0x014D
+#define ixMC_IO_DEBUG_DQB2_CDR_PHSIZE_D1 0x015D
+#define ixMC_IO_DEBUG_DQB2H_CLKSEL_D0 0x00C5
+#define ixMC_IO_DEBUG_DQB2H_CLKSEL_D1 0x00D5
+#define ixMC_IO_DEBUG_DQB2H_MISC_D0 0x00A5
+#define ixMC_IO_DEBUG_DQB2H_MISC_D1 0x00B5
+#define ixMC_IO_DEBUG_DQB2H_OFSCAL_D0 0x00E5
+#define ixMC_IO_DEBUG_DQB2H_OFSCAL_D1 0x00F5
+#define ixMC_IO_DEBUG_DQB2H_RX_EQ_D0 0x01C5
+#define ixMC_IO_DEBUG_DQB2H_RX_EQ_D1 0x01D5
+#define ixMC_IO_DEBUG_DQB2H_RXPHASE_D0 0x0105
+#define ixMC_IO_DEBUG_DQB2H_RXPHASE_D1 0x0115
+#define ixMC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0 0x0145
+#define ixMC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1 0x0155
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PD_D0 0x0185
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PD_D1 0x0195
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PU_D0 0x01A5
+#define ixMC_IO_DEBUG_DQB2H_TXBST_PU_D1 0x01B5
+#define ixMC_IO_DEBUG_DQB2H_TXPHASE_D0 0x0125
+#define ixMC_IO_DEBUG_DQB2H_TXPHASE_D1 0x0135
+#define ixMC_IO_DEBUG_DQB2H_TXSLF_D0 0x0165
+#define ixMC_IO_DEBUG_DQB2H_TXSLF_D1 0x0175
+#define ixMC_IO_DEBUG_DQB2L_CLKSEL_D0 0x00C4
+#define ixMC_IO_DEBUG_DQB2L_CLKSEL_D1 0x00D4
+#define ixMC_IO_DEBUG_DQB2L_MISC_D0 0x00A4
+#define ixMC_IO_DEBUG_DQB2L_MISC_D1 0x00B4
+#define ixMC_IO_DEBUG_DQB2L_OFSCAL_D0 0x00E4
+#define ixMC_IO_DEBUG_DQB2L_OFSCAL_D1 0x00F4
+#define ixMC_IO_DEBUG_DQB2L_RX_EQ_D0 0x01C4
+#define ixMC_IO_DEBUG_DQB2L_RX_EQ_D1 0x01D4
+#define ixMC_IO_DEBUG_DQB2L_RXPHASE_D0 0x0104
+#define ixMC_IO_DEBUG_DQB2L_RXPHASE_D1 0x0114
+#define ixMC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0 0x0144
+#define ixMC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1 0x0154
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PD_D0 0x0184
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PD_D1 0x0194
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PU_D0 0x01A4
+#define ixMC_IO_DEBUG_DQB2L_TXBST_PU_D1 0x01B4
+#define ixMC_IO_DEBUG_DQB2L_TXPHASE_D0 0x0124
+#define ixMC_IO_DEBUG_DQB2L_TXPHASE_D1 0x0134
+#define ixMC_IO_DEBUG_DQB2L_TXSLF_D0 0x0164
+#define ixMC_IO_DEBUG_DQB2L_TXSLF_D1 0x0174
+#define ixMC_IO_DEBUG_DQB3_CDR_PHSIZE_D0 0x014E
+#define ixMC_IO_DEBUG_DQB3_CDR_PHSIZE_D1 0x015E
+#define ixMC_IO_DEBUG_DQB3H_CLKSEL_D0 0x00C7
+#define ixMC_IO_DEBUG_DQB3H_CLKSEL_D1 0x00D7
+#define ixMC_IO_DEBUG_DQB3H_MISC_D0 0x00A7
+#define ixMC_IO_DEBUG_DQB3H_MISC_D1 0x00B7
+#define ixMC_IO_DEBUG_DQB3H_OFSCAL_D0 0x00E7
+#define ixMC_IO_DEBUG_DQB3H_OFSCAL_D1 0x00F7
+#define ixMC_IO_DEBUG_DQB3H_RX_EQ_D0 0x01C7
+#define ixMC_IO_DEBUG_DQB3H_RX_EQ_D1 0x01D7
+#define ixMC_IO_DEBUG_DQB3H_RXPHASE_D0 0x0107
+#define ixMC_IO_DEBUG_DQB3H_RXPHASE_D1 0x0117
+#define ixMC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0 0x0147
+#define ixMC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1 0x0157
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PD_D0 0x0187
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PD_D1 0x0197
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PU_D0 0x01A7
+#define ixMC_IO_DEBUG_DQB3H_TXBST_PU_D1 0x01B7
+#define ixMC_IO_DEBUG_DQB3H_TXPHASE_D0 0x0127
+#define ixMC_IO_DEBUG_DQB3H_TXPHASE_D1 0x0137
+#define ixMC_IO_DEBUG_DQB3H_TXSLF_D0 0x0167
+#define ixMC_IO_DEBUG_DQB3H_TXSLF_D1 0x0177
+#define ixMC_IO_DEBUG_DQB3L_CLKSEL_D0 0x00C6
+#define ixMC_IO_DEBUG_DQB3L_CLKSEL_D1 0x00D6
+#define ixMC_IO_DEBUG_DQB3L_MISC_D0 0x00A6
+#define ixMC_IO_DEBUG_DQB3L_MISC_D1 0x00B6
+#define ixMC_IO_DEBUG_DQB3L_OFSCAL_D0 0x00E6
+#define ixMC_IO_DEBUG_DQB3L_OFSCAL_D1 0x00F6
+#define ixMC_IO_DEBUG_DQB3L_RX_EQ_D0 0x01C6
+#define ixMC_IO_DEBUG_DQB3L_RX_EQ_D1 0x01D6
+#define ixMC_IO_DEBUG_DQB3L_RXPHASE_D0 0x0106
+#define ixMC_IO_DEBUG_DQB3L_RXPHASE_D1 0x0116
+#define ixMC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0 0x0146
+#define ixMC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1 0x0156
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PD_D0 0x0186
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PD_D1 0x0196
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PU_D0 0x01A6
+#define ixMC_IO_DEBUG_DQB3L_TXBST_PU_D1 0x01B6
+#define ixMC_IO_DEBUG_DQB3L_TXPHASE_D0 0x0126
+#define ixMC_IO_DEBUG_DQB3L_TXPHASE_D1 0x0136
+#define ixMC_IO_DEBUG_DQB3L_TXSLF_D0 0x0166
+#define ixMC_IO_DEBUG_DQB3L_TXSLF_D1 0x0176
+#define ixMC_IO_DEBUG_EDC_CDR_PHSIZE_D0 0x00ED
+#define ixMC_IO_DEBUG_EDC_CDR_PHSIZE_D1 0x00FD
+#define ixMC_IO_DEBUG_EDC_CLKSEL_D0 0x00C9
+#define ixMC_IO_DEBUG_EDC_CLKSEL_D1 0x00D9
+#define ixMC_IO_DEBUG_EDC_MISC_D0 0x00A9
+#define ixMC_IO_DEBUG_EDC_MISC_D1 0x00B9
+#define ixMC_IO_DEBUG_EDC_OFSCAL_D0 0x00E9
+#define ixMC_IO_DEBUG_EDC_OFSCAL_D1 0x00F9
+#define ixMC_IO_DEBUG_EDC_RX_DYN_PM_D0 0x00EC
+#define ixMC_IO_DEBUG_EDC_RX_DYN_PM_D1 0x00FC
+#define ixMC_IO_DEBUG_EDC_RX_EQ_D0 0x01C9
+#define ixMC_IO_DEBUG_EDC_RX_EQ_D1 0x01D9
+#define ixMC_IO_DEBUG_EDC_RX_EQ_PM_D0 0x00EB
+#define ixMC_IO_DEBUG_EDC_RX_EQ_PM_D1 0x00FB
+#define ixMC_IO_DEBUG_EDC_RXPHASE_D0 0x0109
+#define ixMC_IO_DEBUG_EDC_RXPHASE_D1 0x0119
+#define ixMC_IO_DEBUG_EDC_RX_VREF_CAL_D0 0x0149
+#define ixMC_IO_DEBUG_EDC_RX_VREF_CAL_D1 0x0159
+#define ixMC_IO_DEBUG_EDC_TXBST_PD_D0 0x0189
+#define ixMC_IO_DEBUG_EDC_TXBST_PD_D1 0x0199
+#define ixMC_IO_DEBUG_EDC_TXBST_PU_D0 0x01A9
+#define ixMC_IO_DEBUG_EDC_TXBST_PU_D1 0x01B9
+#define ixMC_IO_DEBUG_EDC_TXPHASE_D0 0x0129
+#define ixMC_IO_DEBUG_EDC_TXPHASE_D1 0x0139
+#define ixMC_IO_DEBUG_EDC_TXSLF_D0 0x0169
+#define ixMC_IO_DEBUG_EDC_TXSLF_D1 0x0179
+#define ixMC_IO_DEBUG_UP_0 0x0000
+#define ixMC_IO_DEBUG_UP_100 0x0064
+#define ixMC_IO_DEBUG_UP_10 0x000A
+#define ixMC_IO_DEBUG_UP_101 0x0065
+#define ixMC_IO_DEBUG_UP_102 0x0066
+#define ixMC_IO_DEBUG_UP_103 0x0067
+#define ixMC_IO_DEBUG_UP_104 0x0068
+#define ixMC_IO_DEBUG_UP_105 0x0069
+#define ixMC_IO_DEBUG_UP_106 0x006A
+#define ixMC_IO_DEBUG_UP_107 0x006B
+#define ixMC_IO_DEBUG_UP_108 0x006C
+#define ixMC_IO_DEBUG_UP_109 0x006D
+#define ixMC_IO_DEBUG_UP_1 0x0001
+#define ixMC_IO_DEBUG_UP_110 0x006E
+#define ixMC_IO_DEBUG_UP_11 0x000B
+#define ixMC_IO_DEBUG_UP_111 0x006F
+#define ixMC_IO_DEBUG_UP_112 0x0070
+#define ixMC_IO_DEBUG_UP_113 0x0071
+#define ixMC_IO_DEBUG_UP_114 0x0072
+#define ixMC_IO_DEBUG_UP_115 0x0073
+#define ixMC_IO_DEBUG_UP_116 0x0074
+#define ixMC_IO_DEBUG_UP_117 0x0075
+#define ixMC_IO_DEBUG_UP_118 0x0076
+#define ixMC_IO_DEBUG_UP_119 0x0077
+#define ixMC_IO_DEBUG_UP_120 0x0078
+#define ixMC_IO_DEBUG_UP_12 0x000C
+#define ixMC_IO_DEBUG_UP_121 0x0079
+#define ixMC_IO_DEBUG_UP_122 0x007A
+#define ixMC_IO_DEBUG_UP_123 0x007B
+#define ixMC_IO_DEBUG_UP_124 0x007C
+#define ixMC_IO_DEBUG_UP_125 0x007D
+#define ixMC_IO_DEBUG_UP_126 0x007E
+#define ixMC_IO_DEBUG_UP_127 0x007F
+#define ixMC_IO_DEBUG_UP_128 0x0080
+#define ixMC_IO_DEBUG_UP_129 0x0081
+#define ixMC_IO_DEBUG_UP_130 0x0082
+#define ixMC_IO_DEBUG_UP_13 0x000D
+#define ixMC_IO_DEBUG_UP_131 0x0083
+#define ixMC_IO_DEBUG_UP_132 0x0084
+#define ixMC_IO_DEBUG_UP_133 0x0085
+#define ixMC_IO_DEBUG_UP_134 0x0086
+#define ixMC_IO_DEBUG_UP_135 0x0087
+#define ixMC_IO_DEBUG_UP_136 0x0088
+#define ixMC_IO_DEBUG_UP_137 0x0089
+#define ixMC_IO_DEBUG_UP_138 0x008A
+#define ixMC_IO_DEBUG_UP_139 0x008B
+#define ixMC_IO_DEBUG_UP_140 0x008C
+#define ixMC_IO_DEBUG_UP_14 0x000E
+#define ixMC_IO_DEBUG_UP_141 0x008D
+#define ixMC_IO_DEBUG_UP_142 0x008E
+#define ixMC_IO_DEBUG_UP_143 0x008F
+#define ixMC_IO_DEBUG_UP_144 0x0090
+#define ixMC_IO_DEBUG_UP_145 0x0091
+#define ixMC_IO_DEBUG_UP_146 0x0092
+#define ixMC_IO_DEBUG_UP_147 0x0093
+#define ixMC_IO_DEBUG_UP_148 0x0094
+#define ixMC_IO_DEBUG_UP_149 0x0095
+#define ixMC_IO_DEBUG_UP_150 0x0096
+#define ixMC_IO_DEBUG_UP_15 0x000F
+#define ixMC_IO_DEBUG_UP_151 0x0097
+#define ixMC_IO_DEBUG_UP_152 0x0098
+#define ixMC_IO_DEBUG_UP_153 0x0099
+#define ixMC_IO_DEBUG_UP_154 0x009A
+#define ixMC_IO_DEBUG_UP_155 0x009B
+#define ixMC_IO_DEBUG_UP_156 0x009C
+#define ixMC_IO_DEBUG_UP_157 0x009D
+#define ixMC_IO_DEBUG_UP_158 0x009E
+#define ixMC_IO_DEBUG_UP_159 0x009F
+#define ixMC_IO_DEBUG_UP_16 0x0010
+#define ixMC_IO_DEBUG_UP_17 0x0011
+#define ixMC_IO_DEBUG_UP_18 0x0012
+#define ixMC_IO_DEBUG_UP_19 0x0013
+#define ixMC_IO_DEBUG_UP_20 0x0014
+#define ixMC_IO_DEBUG_UP_2 0x0002
+#define ixMC_IO_DEBUG_UP_21 0x0015
+#define ixMC_IO_DEBUG_UP_22 0x0016
+#define ixMC_IO_DEBUG_UP_23 0x0017
+#define ixMC_IO_DEBUG_UP_24 0x0018
+#define ixMC_IO_DEBUG_UP_25 0x0019
+#define ixMC_IO_DEBUG_UP_26 0x001A
+#define ixMC_IO_DEBUG_UP_27 0x001B
+#define ixMC_IO_DEBUG_UP_28 0x001C
+#define ixMC_IO_DEBUG_UP_29 0x001D
+#define ixMC_IO_DEBUG_UP_30 0x001E
+#define ixMC_IO_DEBUG_UP_3 0x0003
+#define ixMC_IO_DEBUG_UP_31 0x001F
+#define ixMC_IO_DEBUG_UP_32 0x0020
+#define ixMC_IO_DEBUG_UP_33 0x0021
+#define ixMC_IO_DEBUG_UP_34 0x0022
+#define ixMC_IO_DEBUG_UP_35 0x0023
+#define ixMC_IO_DEBUG_UP_36 0x0024
+#define ixMC_IO_DEBUG_UP_37 0x0025
+#define ixMC_IO_DEBUG_UP_38 0x0026
+#define ixMC_IO_DEBUG_UP_39 0x0027
+#define ixMC_IO_DEBUG_UP_40 0x0028
+#define ixMC_IO_DEBUG_UP_4 0x0004
+#define ixMC_IO_DEBUG_UP_41 0x0029
+#define ixMC_IO_DEBUG_UP_42 0x002A
+#define ixMC_IO_DEBUG_UP_43 0x002B
+#define ixMC_IO_DEBUG_UP_44 0x002C
+#define ixMC_IO_DEBUG_UP_45 0x002D
+#define ixMC_IO_DEBUG_UP_46 0x002E
+#define ixMC_IO_DEBUG_UP_47 0x002F
+#define ixMC_IO_DEBUG_UP_48 0x0030
+#define ixMC_IO_DEBUG_UP_49 0x0031
+#define ixMC_IO_DEBUG_UP_50 0x0032
+#define ixMC_IO_DEBUG_UP_5 0x0005
+#define ixMC_IO_DEBUG_UP_51 0x0033
+#define ixMC_IO_DEBUG_UP_52 0x0034
+#define ixMC_IO_DEBUG_UP_53 0x0035
+#define ixMC_IO_DEBUG_UP_54 0x0036
+#define ixMC_IO_DEBUG_UP_55 0x0037
+#define ixMC_IO_DEBUG_UP_56 0x0038
+#define ixMC_IO_DEBUG_UP_57 0x0039
+#define ixMC_IO_DEBUG_UP_58 0x003A
+#define ixMC_IO_DEBUG_UP_59 0x003B
+#define ixMC_IO_DEBUG_UP_60 0x003C
+#define ixMC_IO_DEBUG_UP_6 0x0006
+#define ixMC_IO_DEBUG_UP_61 0x003D
+#define ixMC_IO_DEBUG_UP_62 0x003E
+#define ixMC_IO_DEBUG_UP_63 0x003F
+#define ixMC_IO_DEBUG_UP_64 0x0040
+#define ixMC_IO_DEBUG_UP_65 0x0041
+#define ixMC_IO_DEBUG_UP_66 0x0042
+#define ixMC_IO_DEBUG_UP_67 0x0043
+#define ixMC_IO_DEBUG_UP_68 0x0044
+#define ixMC_IO_DEBUG_UP_69 0x0045
+#define ixMC_IO_DEBUG_UP_70 0x0046
+#define ixMC_IO_DEBUG_UP_7 0x0007
+#define ixMC_IO_DEBUG_UP_71 0x0047
+#define ixMC_IO_DEBUG_UP_72 0x0048
+#define ixMC_IO_DEBUG_UP_73 0x0049
+#define ixMC_IO_DEBUG_UP_74 0x004A
+#define ixMC_IO_DEBUG_UP_75 0x004B
+#define ixMC_IO_DEBUG_UP_76 0x004C
+#define ixMC_IO_DEBUG_UP_77 0x004D
+#define ixMC_IO_DEBUG_UP_78 0x004E
+#define ixMC_IO_DEBUG_UP_79 0x004F
+#define ixMC_IO_DEBUG_UP_80 0x0050
+#define ixMC_IO_DEBUG_UP_8 0x0008
+#define ixMC_IO_DEBUG_UP_81 0x0051
+#define ixMC_IO_DEBUG_UP_82 0x0052
+#define ixMC_IO_DEBUG_UP_83 0x0053
+#define ixMC_IO_DEBUG_UP_84 0x0054
+#define ixMC_IO_DEBUG_UP_85 0x0055
+#define ixMC_IO_DEBUG_UP_86 0x0056
+#define ixMC_IO_DEBUG_UP_87 0x0057
+#define ixMC_IO_DEBUG_UP_88 0x0058
+#define ixMC_IO_DEBUG_UP_89 0x0059
+#define ixMC_IO_DEBUG_UP_90 0x005A
+#define ixMC_IO_DEBUG_UP_9 0x0009
+#define ixMC_IO_DEBUG_UP_91 0x005B
+#define ixMC_IO_DEBUG_UP_92 0x005C
+#define ixMC_IO_DEBUG_UP_93 0x005D
+#define ixMC_IO_DEBUG_UP_94 0x005E
+#define ixMC_IO_DEBUG_UP_95 0x005F
+#define ixMC_IO_DEBUG_UP_96 0x0060
+#define ixMC_IO_DEBUG_UP_97 0x0061
+#define ixMC_IO_DEBUG_UP_98 0x0062
+#define ixMC_IO_DEBUG_UP_99 0x0063
+#define ixMC_IO_DEBUG_WCDR_CDR_PHSIZE_D0 0x01EA
+#define ixMC_IO_DEBUG_WCDR_CDR_PHSIZE_D1 0x01FA
+#define ixMC_IO_DEBUG_WCDR_CLKSEL_D0 0x01E1
+#define ixMC_IO_DEBUG_WCDR_CLKSEL_D1 0x01F1
+#define ixMC_IO_DEBUG_WCDR_MISC_D0 0x01E0
+#define ixMC_IO_DEBUG_WCDR_MISC_D1 0x01F0
+#define ixMC_IO_DEBUG_WCDR_OFSCAL_D0 0x01E2
+#define ixMC_IO_DEBUG_WCDR_OFSCAL_D1 0x01F2
+#define ixMC_IO_DEBUG_WCDR_RX_DYN_PM_D0 0x01EC
+#define ixMC_IO_DEBUG_WCDR_RX_DYN_PM_D1 0x01FC
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_D0 0x01E9
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_D1 0x01F9
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_PM_D0 0x01EB
+#define ixMC_IO_DEBUG_WCDR_RX_EQ_PM_D1 0x01FB
+#define ixMC_IO_DEBUG_WCDR_RXPHASE_D0 0x01E3
+#define ixMC_IO_DEBUG_WCDR_RXPHASE_D1 0x01F3
+#define ixMC_IO_DEBUG_WCDR_RX_VREF_CAL_D0 0x01E5
+#define ixMC_IO_DEBUG_WCDR_RX_VREF_CAL_D1 0x01F5
+#define ixMC_IO_DEBUG_WCDR_TXBST_PD_D0 0x01E7
+#define ixMC_IO_DEBUG_WCDR_TXBST_PD_D1 0x01F7
+#define ixMC_IO_DEBUG_WCDR_TXBST_PU_D0 0x01E8
+#define ixMC_IO_DEBUG_WCDR_TXBST_PU_D1 0x01F8
+#define ixMC_IO_DEBUG_WCDR_TXPHASE_D0 0x01E4
+#define ixMC_IO_DEBUG_WCDR_TXPHASE_D1 0x01F4
+#define ixMC_IO_DEBUG_WCDR_TXSLF_D0 0x01E6
+#define ixMC_IO_DEBUG_WCDR_TXSLF_D1 0x01F6
+#define ixMC_IO_DEBUG_WCK_CLKSEL_D0 0x00CA
+#define ixMC_IO_DEBUG_WCK_CLKSEL_D1 0x00DA
+#define ixMC_IO_DEBUG_WCK_MISC_D0 0x00AA
+#define ixMC_IO_DEBUG_WCK_MISC_D1 0x00BA
+#define ixMC_IO_DEBUG_WCK_OFSCAL_D0 0x00EA
+#define ixMC_IO_DEBUG_WCK_OFSCAL_D1 0x00FA
+#define ixMC_IO_DEBUG_WCK_RX_EQ_D0 0x01CA
+#define ixMC_IO_DEBUG_WCK_RX_EQ_D1 0x01DA
+#define ixMC_IO_DEBUG_WCK_RXPHASE_D0 0x010A
+#define ixMC_IO_DEBUG_WCK_RXPHASE_D1 0x011A
+#define ixMC_IO_DEBUG_WCK_RX_VREF_CAL_D0 0x014A
+#define ixMC_IO_DEBUG_WCK_RX_VREF_CAL_D1 0x015A
+#define ixMC_IO_DEBUG_WCK_TXBST_PD_D0 0x018A
+#define ixMC_IO_DEBUG_WCK_TXBST_PD_D1 0x019A
+#define ixMC_IO_DEBUG_WCK_TXBST_PU_D0 0x01AA
+#define ixMC_IO_DEBUG_WCK_TXBST_PU_D1 0x01BA
+#define ixMC_IO_DEBUG_WCK_TXPHASE_D0 0x012A
+#define ixMC_IO_DEBUG_WCK_TXPHASE_D1 0x013A
+#define ixMC_IO_DEBUG_WCK_TXSLF_D0 0x016A
+#define ixMC_IO_DEBUG_WCK_TXSLF_D1 0x017A
+#define ixMC_TSM_DEBUG_BCNT0 0x0003
+#define ixMC_TSM_DEBUG_BCNT10 0x000D
+#define ixMC_TSM_DEBUG_BCNT1 0x0004
+#define ixMC_TSM_DEBUG_BCNT2 0x0005
+#define ixMC_TSM_DEBUG_BCNT3 0x0006
+#define ixMC_TSM_DEBUG_BCNT4 0x0007
+#define ixMC_TSM_DEBUG_BCNT5 0x0008
+#define ixMC_TSM_DEBUG_BCNT6 0x0009
+#define ixMC_TSM_DEBUG_BCNT7 0x000A
+#define ixMC_TSM_DEBUG_BCNT8 0x000B
+#define ixMC_TSM_DEBUG_BCNT9 0x000C
+#define ixMC_TSM_DEBUG_BKPT 0x0013
+#define ixMC_TSM_DEBUG_FLAG 0x0001
+#define ixMC_TSM_DEBUG_GCNT 0x0000
+#define ixMC_TSM_DEBUG_MISC 0x0002
+#define ixMC_TSM_DEBUG_ST01 0x0010
+#define ixMC_TSM_DEBUG_ST23 0x0011
+#define ixMC_TSM_DEBUG_ST45 0x0012
+#define mmATC_ATS_CNTL 0x0CC9
+#define mmATC_ATS_DEBUG 0x0CCA
+#define mmATC_ATS_DEFAULT_PAGE_CNTL 0x0CD1
+#define mmATC_ATS_DEFAULT_PAGE_LOW 0x0CD0
+#define mmATC_ATS_FAULT_CNTL 0x0CCD
+#define mmATC_ATS_FAULT_DEBUG 0x0CCB
+#define mmATC_ATS_FAULT_STATUS_ADDR 0x0CCF
+#define mmATC_ATS_FAULT_STATUS_INFO 0x0CCE
+#define mmATC_ATS_STATUS 0x0CCC
+#define mmATC_L1_ADDRESS_OFFSET 0x0CDD
+#define mmATC_L1_CNTL 0x0CDC
+#define mmATC_L1RD_DEBUG_TLB 0x0CDE
+#define mmATC_L1RD_STATUS 0x0CE0
+#define mmATC_L1WR_DEBUG_TLB 0x0CDF
+#define mmATC_L1WR_STATUS 0x0CE1
+#define mmATC_L2_CNTL 0x0CD5
+#define mmATC_L2_DEBUG 0x0CD7
+#define mmATC_MISC_CG 0x0CD4
+#define mmATC_VM_APERTURE0_CNTL 0x0CC4
+#define mmATC_VM_APERTURE0_CNTL2 0x0CC6
+#define mmATC_VM_APERTURE0_HIGH_ADDR 0x0CC2
+#define mmATC_VM_APERTURE0_LOW_ADDR 0x0CC0
+#define mmATC_VM_APERTURE1_CNTL 0x0CC5
+#define mmATC_VM_APERTURE1_CNTL2 0x0CC7
+#define mmATC_VM_APERTURE1_HIGH_ADDR 0x0CC3
+#define mmATC_VM_APERTURE1_LOW_ADDR 0x0CC1
+#define mmATC_VMID0_PASID_MAPPING 0x0CE7
+#define mmATC_VMID10_PASID_MAPPING 0x0CF1
+#define mmATC_VMID11_PASID_MAPPING 0x0CF2
+#define mmATC_VMID12_PASID_MAPPING 0x0CF3
+#define mmATC_VMID13_PASID_MAPPING 0x0CF4
+#define mmATC_VMID14_PASID_MAPPING 0x0CF5
+#define mmATC_VMID15_PASID_MAPPING 0x0CF6
+#define mmATC_VMID1_PASID_MAPPING 0x0CE8
+#define mmATC_VMID2_PASID_MAPPING 0x0CE9
+#define mmATC_VMID3_PASID_MAPPING 0x0CEA
+#define mmATC_VMID4_PASID_MAPPING 0x0CEB
+#define mmATC_VMID5_PASID_MAPPING 0x0CEC
+#define mmATC_VMID6_PASID_MAPPING 0x0CED
+#define mmATC_VMID7_PASID_MAPPING 0x0CEE
+#define mmATC_VMID8_PASID_MAPPING 0x0CEF
+#define mmATC_VMID9_PASID_MAPPING 0x0CF0
+#define mmATC_VMID_PASID_MAPPING_UPDATE_STATUS 0x0CE6
+#define mmCC_MC_MAX_CHANNEL 0x096E
+#define mmDLL_CNTL 0x0AE9
+#define mmGMCON_DEBUG 0x0D5F
+#define mmGMCON_MISC 0x0D43
+#define mmGMCON_MISC2 0x0D44
+#define mmGMCON_MISC3 0x0D51
+#define mmGMCON_PERF_MON_CNTL0 0x0D4A
+#define mmGMCON_PERF_MON_CNTL1 0x0D4B
+#define mmGMCON_PERF_MON_RSLT0 0x0D4C
+#define mmGMCON_PERF_MON_RSLT1 0x0D4D
+#define mmGMCON_PGFSM_CONFIG 0x0D4E
+#define mmGMCON_PGFSM_READ 0x0D50
+#define mmGMCON_PGFSM_WRITE 0x0D4F
+#define mmGMCON_RENG_EXECUTE 0x0D42
+#define mmGMCON_RENG_RAM_DATA 0x0D41
+#define mmGMCON_RENG_RAM_INDEX 0x0D40
+#define mmGMCON_STCTRL_REGISTER_SAVE_EXCL_SET0 0x0D48
+#define mmGMCON_STCTRL_REGISTER_SAVE_EXCL_SET1 0x0D49
+#define mmGMCON_STCTRL_REGISTER_SAVE_RANGE0 0x0D45
+#define mmGMCON_STCTRL_REGISTER_SAVE_RANGE1 0x0D46
+#define mmGMCON_STCTRL_REGISTER_SAVE_RANGE2 0x0D47
+#define mmMC_ARB_ADDR_HASH 0x09DC
+#define mmMC_ARB_AGE_RD 0x09E9
+#define mmMC_ARB_AGE_WR 0x09EA
+#define mmMC_ARB_BANKMAP 0x09D7
+#define mmMC_ARB_BURST_TIME 0x0A02
+#define mmMC_ARB_CAC_CNTL 0x09D4
+#define mmMC_ARB_CG 0x09FA
+#define mmMC_ARB_DRAM_TIMING 0x09DD
+#define mmMC_ARB_DRAM_TIMING_1 0x09FC
+#define mmMC_ARB_DRAM_TIMING2 0x09DE
+#define mmMC_ARB_DRAM_TIMING2_1 0x09FF
+#define mmMC_ARB_FED_CNTL 0x09C1
+#define mmMC_ARB_GDEC_RD_CNTL 0x09EE
+#define mmMC_ARB_GDEC_WR_CNTL 0x09EF
+#define mmMC_ARB_GECC2 0x09C9
+#define mmMC_ARB_GECC2_CLI 0x09CA
+#define mmMC_ARB_GECC2_DEBUG 0x09C4
+#define mmMC_ARB_GECC2_DEBUG2 0x09C5
+#define mmMC_ARB_GECC2_MISC 0x09C3
+#define mmMC_ARB_GECC2_STATUS 0x09C2
+#define mmMC_ARB_LAZY0_RD 0x09E5
+#define mmMC_ARB_LAZY0_WR 0x09E6
+#define mmMC_ARB_LAZY1_RD 0x09E7
+#define mmMC_ARB_LAZY1_WR 0x09E8
+#define mmMC_ARB_LM_RD 0x09F0
+#define mmMC_ARB_LM_WR 0x09F1
+#define mmMC_ARB_MINCLKS 0x09DA
+#define mmMC_ARB_MISC 0x09D6
+#define mmMC_ARB_MISC2 0x09D5
+#define mmMC_ARB_PM_CNTL 0x09ED
+#define mmMC_ARB_POP 0x09D9
+#define mmMC_ARB_RAMCFG 0x09D8
+#define mmMC_ARB_REMREQ 0x09F2
+#define mmMC_ARB_REPLAY 0x09F3
+#define mmMC_ARB_RET_CREDITS_RD 0x09F4
+#define mmMC_ARB_RET_CREDITS_WR 0x09F5
+#define mmMC_ARB_RFSH_CNTL 0x09EB
+#define mmMC_ARB_RFSH_RATE 0x09EC
+#define mmMC_ARB_RTT_CNTL0 0x09D0
+#define mmMC_ARB_RTT_CNTL1 0x09D1
+#define mmMC_ARB_RTT_CNTL2 0x09D2
+#define mmMC_ARB_RTT_DATA 0x09CF
+#define mmMC_ARB_RTT_DEBUG 0x09D3
+#define mmMC_ARB_SQM_CNTL 0x09DB
+#define mmMC_ARB_TM_CNTL_RD 0x09E3
+#define mmMC_ARB_TM_CNTL_WR 0x09E4
+#define mmMC_ARB_WCDR 0x09FB
+#define mmMC_ARB_WCDR_2 0x09CE
+#define mmMC_ARB_WTM_CNTL_RD 0x09DF
+#define mmMC_ARB_WTM_CNTL_WR 0x09E0
+#define mmMC_ARB_WTM_GRPWT_RD 0x09E1
+#define mmMC_ARB_WTM_GRPWT_WR 0x09E2
+#define mmMC_BIST_AUTO_CNTL 0x0A06
+#define mmMC_BIST_CMD_CNTL 0x0A8E
+#define mmMC_BIST_CMP_CNTL 0x0A8D
+#define mmMC_BIST_CMP_CNTL_2 0x0AB6
+#define mmMC_BIST_CNTL 0x0A05
+#define mmMC_BIST_DATA_MASK 0x0A12
+#define mmMC_BIST_DATA_WORD0 0x0A0A
+#define mmMC_BIST_DATA_WORD1 0x0A0B
+#define mmMC_BIST_DATA_WORD2 0x0A0C
+#define mmMC_BIST_DATA_WORD3 0x0A0D
+#define mmMC_BIST_DATA_WORD4 0x0A0E
+#define mmMC_BIST_DATA_WORD5 0x0A0F
+#define mmMC_BIST_DATA_WORD6 0x0A10
+#define mmMC_BIST_DATA_WORD7 0x0A11
+#define mmMC_BIST_DIR_CNTL 0x0A07
+#define mmMC_BIST_EADDR 0x0A09
+#define mmMC_BIST_MISMATCH_ADDR 0x0A13
+#define mmMC_BIST_RDATA_EDC 0x0A1D
+#define mmMC_BIST_RDATA_MASK 0x0A1C
+#define mmMC_BIST_RDATA_WORD0 0x0A14
+#define mmMC_BIST_RDATA_WORD1 0x0A15
+#define mmMC_BIST_RDATA_WORD2 0x0A16
+#define mmMC_BIST_RDATA_WORD3 0x0A17
+#define mmMC_BIST_RDATA_WORD4 0x0A18
+#define mmMC_BIST_RDATA_WORD5 0x0A19
+#define mmMC_BIST_RDATA_WORD6 0x0A1A
+#define mmMC_BIST_RDATA_WORD7 0x0A1B
+#define mmMC_BIST_SADDR 0x0A08
+#define mmMC_CG_CONFIG 0x096F
+#define mmMC_CG_CONFIG_MCD 0x0829
+#define mmMC_CG_DATAPORT 0x0A21
+#define mmMC_CITF_CNTL 0x0970
+#define mmMC_CITF_CREDITS_ARB_RD 0x0972
+#define mmMC_CITF_CREDITS_ARB_WR 0x0973
+#define mmMC_CITF_CREDITS_VM 0x0971
+#define mmMC_CITF_CREDITS_XBAR 0x0989
+#define mmMC_CITF_DAGB_CNTL 0x0974
+#define mmMC_CITF_DAGB_DLY 0x0977
+#define mmMC_CITF_INT_CREDITS 0x0975
+#define mmMC_CITF_INT_CREDITS_WR 0x097D
+#define mmMC_CITF_MISC_RD_CG 0x0992
+#define mmMC_CITF_MISC_VM_CG 0x0994
+#define mmMC_CITF_MISC_WR_CG 0x0993
+#define mmMC_CITF_PERF_MON_CNTL2 0x098E
+#define mmMC_CITF_PERF_MON_RSLT2 0x0991
+#define mmMC_CITF_REMREQ 0x097A
+#define mmMC_CITF_RET_MODE 0x0976
+#define mmMC_CITF_WTM_RD_CNTL 0x097F
+#define mmMC_CITF_WTM_WR_CNTL 0x0980
+#define mmMC_CITF_XTRA_ENABLE 0x096D
+#define mmMC_CONFIG 0x0800
+#define mmMC_CONFIG_MCD 0x0828
+#define mmMC_HUB_MISC_DBG 0x0831
+#define mmMC_HUB_MISC_FRAMING 0x0834
+#define mmMC_HUB_MISC_HUB_CG 0x082E
+#define mmMC_HUB_MISC_IDLE_STATUS 0x0847
+#define mmMC_HUB_MISC_OVERRIDE 0x0833
+#define mmMC_HUB_MISC_POWER 0x082D
+#define mmMC_HUB_MISC_SIP_CG 0x0830
+#define mmMC_HUB_MISC_STATUS 0x0832
+#define mmMC_HUB_MISC_VM_CG 0x082F
+#define mmMC_HUB_RDREQ_CNTL 0x083B
+#define mmMC_HUB_RDREQ_CREDITS 0x0844
+#define mmMC_HUB_RDREQ_CREDITS2 0x0845
+#define mmMC_HUB_RDREQ_DMIF 0x0863
+#define mmMC_HUB_RDREQ_DMIF_LIMIT 0x0848
+#define mmMC_HUB_RDREQ_GBL0 0x0856
+#define mmMC_HUB_RDREQ_GBL1 0x0857
+#define mmMC_HUB_RDREQ_HDP 0x085B
+#define mmMC_HUB_RDREQ_MCDW 0x0851
+#define mmMC_HUB_RDREQ_MCDX 0x0852
+#define mmMC_HUB_RDREQ_MCDY 0x0853
+#define mmMC_HUB_RDREQ_MCDZ 0x0854
+#define mmMC_HUB_RDREQ_MCIF 0x0864
+#define mmMC_HUB_RDREQ_RLC 0x085D
+#define mmMC_HUB_RDREQ_SEM 0x085E
+#define mmMC_HUB_RDREQ_SIP 0x0855
+#define mmMC_HUB_RDREQ_SMU 0x0858
+#define mmMC_HUB_RDREQ_STATUS 0x0839
+#define mmMC_HUB_RDREQ_UMC 0x0860
+#define mmMC_HUB_RDREQ_UVD 0x0861
+#define mmMC_HUB_RDREQ_VCE 0x085F
+#define mmMC_HUB_RDREQ_VCEU 0x0866
+#define mmMC_HUB_RDREQ_VMC 0x0865
+#define mmMC_HUB_RDREQ_WTM_CNTL 0x083D
+#define mmMC_HUB_RDREQ_XDMAM 0x0882
+#define mmMC_HUB_SHARED_DAGB_DLY 0x0846
+#define mmMC_HUB_WDP_BP 0x0837
+#define mmMC_HUB_WDP_CNTL 0x0835
+#define mmMC_HUB_WDP_CREDITS 0x083F
+#define mmMC_HUB_WDP_ERR 0x0836
+#define mmMC_HUB_WDP_GBL0 0x0841
+#define mmMC_HUB_WDP_GBL1 0x0842
+#define mmMC_HUB_WDP_HDP 0x0879
+#define mmMC_HUB_WDP_IH 0x0872
+#define mmMC_HUB_WDP_MCDW 0x0867
+#define mmMC_HUB_WDP_MCDX 0x0868
+#define mmMC_HUB_WDP_MCDY 0x0869
+#define mmMC_HUB_WDP_MCDZ 0x086A
+#define mmMC_HUB_WDP_MCIF 0x086F
+#define mmMC_HUB_WDP_MGPU 0x0843
+#define mmMC_HUB_WDP_MGPU2 0x0840
+#define mmMC_HUB_WDP_RLC 0x0873
+#define mmMC_HUB_WDP_SEM 0x0874
+#define mmMC_HUB_WDP_SH0 0x086E
+#define mmMC_HUB_WDP_SH1 0x0876
+#define mmMC_HUB_WDP_SIP 0x086B
+#define mmMC_HUB_WDP_SMU 0x0875
+#define mmMC_HUB_WDP_STATUS 0x0838
+#define mmMC_HUB_WDP_UMC 0x0877
+#define mmMC_HUB_WDP_UVD 0x0878
+#define mmMC_HUB_WDP_VCE 0x0870
+#define mmMC_HUB_WDP_VCEU 0x087F
+#define mmMC_HUB_WDP_WTM_CNTL 0x083E
+#define mmMC_HUB_WDP_XDMA 0x0881
+#define mmMC_HUB_WDP_XDMAM 0x0880
+#define mmMC_HUB_WDP_XDP 0x0871
+#define mmMC_HUB_WRRET_CNTL 0x083C
+#define mmMC_HUB_WRRET_MCDW 0x087B
+#define mmMC_HUB_WRRET_MCDX 0x087C
+#define mmMC_HUB_WRRET_MCDY 0x087D
+#define mmMC_HUB_WRRET_MCDZ 0x087E
+#define mmMC_HUB_WRRET_STATUS 0x083A
+#define mmMC_IMP_CNTL 0x0A36
+#define mmMC_IMP_DEBUG 0x0A37
+#define mmMC_IMP_DQ_STATUS 0x0ABC
+#define mmMC_IMP_STATUS 0x0A38
+#define mmMC_IO_APHY_STR_CNTL_D0 0x0A97
+#define mmMC_IO_APHY_STR_CNTL_D1 0x0A98
+#define mmMC_IO_CDRCNTL1_D0 0x0ADD
+#define mmMC_IO_CDRCNTL1_D1 0x0ADE
+#define mmMC_IO_CDRCNTL2_D0 0x0AE4
+#define mmMC_IO_CDRCNTL2_D1 0x0AE5
+#define mmMC_IO_CDRCNTL_D0 0x0A55
+#define mmMC_IO_CDRCNTL_D1 0x0A56
+#define mmMC_IO_DPHY_STR_CNTL_D0 0x0A4E
+#define mmMC_IO_DPHY_STR_CNTL_D1 0x0A54
+#define mmMC_IO_PAD_CNTL 0x0A73
+#define mmMC_IO_PAD_CNTL_D0 0x0A74
+#define mmMC_IO_PAD_CNTL_D1 0x0A75
+#define mmMC_IO_RXCNTL1_DPHY0_D0 0x0ADF
+#define mmMC_IO_RXCNTL1_DPHY0_D1 0x0AE1
+#define mmMC_IO_RXCNTL1_DPHY1_D0 0x0AE0
+#define mmMC_IO_RXCNTL1_DPHY1_D1 0x0AE2
+#define mmMC_IO_RXCNTL_DPHY0_D0 0x0A4C
+#define mmMC_IO_RXCNTL_DPHY0_D1 0x0A52
+#define mmMC_IO_RXCNTL_DPHY1_D0 0x0A4D
+#define mmMC_IO_RXCNTL_DPHY1_D1 0x0A53
+#define mmMC_IO_TXCNTL_APHY_D0 0x0A4B
+#define mmMC_IO_TXCNTL_APHY_D1 0x0A51
+#define mmMC_IO_TXCNTL_DPHY0_D0 0x0A49
+#define mmMC_IO_TXCNTL_DPHY0_D1 0x0A4F
+#define mmMC_IO_TXCNTL_DPHY1_D0 0x0A4A
+#define mmMC_IO_TXCNTL_DPHY1_D1 0x0A50
+#define mmMCLK_PWRMGT_CNTL 0x0AE8
+#define mmMC_MEM_POWER_LS 0x082A
+#define mmMC_NPL_STATUS 0x0A76
+#define mmMC_PHY_TIMING_2 0x0ACE
+#define mmMC_PHY_TIMING_D0 0x0ACC
+#define mmMC_PHY_TIMING_D1 0x0ACD
+#define mmMC_PMG_AUTO_CFG 0x0A35
+#define mmMC_PMG_AUTO_CMD 0x0A34
+#define mmMC_PMG_CFG 0x0A84
+#define mmMC_PMG_CMD_EMRS 0x0A83
+#define mmMC_PMG_CMD_MRS 0x0AAB
+#define mmMC_PMG_CMD_MRS1 0x0AD1
+#define mmMC_PMG_CMD_MRS2 0x0AD7
+#define mmMC_RD_CB 0x0981
+#define mmMC_RD_DB 0x0982
+#define mmMC_RD_GRP_EXT 0x0978
+#define mmMC_RD_GRP_GFX 0x0803
+#define mmMC_RD_GRP_LCL 0x098A
+#define mmMC_RD_GRP_OTH 0x0807
+#define mmMC_RD_GRP_SYS 0x0805
+#define mmMC_RD_HUB 0x0985
+#define mmMC_RD_TC0 0x0983
+#define mmMC_RD_TC1 0x0984
+#define mmMC_RPB_ARB_CNTL 0x0951
+#define mmMC_RPB_BIF_CNTL 0x0952
+#define mmMC_RPB_CID_QUEUE_EX 0x095A
+#define mmMC_RPB_CID_QUEUE_EX_DATA 0x095B
+#define mmMC_RPB_CID_QUEUE_RD 0x0957
+#define mmMC_RPB_CID_QUEUE_WR 0x0956
+#define mmMC_RPB_CONF 0x094D
+#define mmMC_RPB_DBG1 0x094F
+#define mmMC_RPB_EFF_CNTL 0x0950
+#define mmMC_RPB_IF_CONF 0x094E
+#define mmMC_RPB_PERF_COUNTER_CNTL 0x0958
+#define mmMC_RPB_PERF_COUNTER_STATUS 0x0959
+#define mmMC_RPB_RD_SWITCH_CNTL 0x0955
+#define mmMC_RPB_WR_COMBINE_CNTL 0x0954
+#define mmMC_RPB_WR_SWITCH_CNTL 0x0953
+#define mmMC_SEQ_BIT_REMAP_B0_D0 0x0AA3
+#define mmMC_SEQ_BIT_REMAP_B0_D1 0x0AA7
+#define mmMC_SEQ_BIT_REMAP_B1_D0 0x0AA4
+#define mmMC_SEQ_BIT_REMAP_B1_D1 0x0AA8
+#define mmMC_SEQ_BIT_REMAP_B2_D0 0x0AA5
+#define mmMC_SEQ_BIT_REMAP_B2_D1 0x0AA9
+#define mmMC_SEQ_BIT_REMAP_B3_D0 0x0AA6
+#define mmMC_SEQ_BIT_REMAP_B3_D1 0x0AAA
+#define mmMC_SEQ_BYTE_REMAP_D0 0x0A93
+#define mmMC_SEQ_BYTE_REMAP_D1 0x0A94
+#define mmMC_SEQ_CAS_TIMING 0x0A29
+#define mmMC_SEQ_CAS_TIMING_LP 0x0A9C
+#define mmMC_SEQ_CG 0x0A9A
+#define mmMC_SEQ_CMD 0x0A31
+#define mmMC_SEQ_CNTL 0x0A25
+#define mmMC_SEQ_CNTL_2 0x0AD4
+#define mmMC_SEQ_DRAM 0x0A26
+#define mmMC_SEQ_DRAM_2 0x0A27
+#define mmMC_SEQ_DRAM_ERROR_INSERTION 0x0ACB
+#define mmMC_SEQ_FIFO_CTL 0x0A57
+#define mmMC_SEQ_IO_DEBUG_DATA 0x0A92
+#define mmMC_SEQ_IO_DEBUG_INDEX 0x0A91
+#define mmMC_SEQ_IO_RDBI 0x0AB4
+#define mmMC_SEQ_IO_REDC 0x0AB5
+#define mmMC_SEQ_IO_RESERVE_D0 0x0AB7
+#define mmMC_SEQ_IO_RESERVE_D1 0x0AB8
+#define mmMC_SEQ_IO_RWORD0 0x0AAC
+#define mmMC_SEQ_IO_RWORD1 0x0AAD
+#define mmMC_SEQ_IO_RWORD2 0x0AAE
+#define mmMC_SEQ_IO_RWORD3 0x0AAF
+#define mmMC_SEQ_IO_RWORD4 0x0AB0
+#define mmMC_SEQ_IO_RWORD5 0x0AB1
+#define mmMC_SEQ_IO_RWORD6 0x0AB2
+#define mmMC_SEQ_IO_RWORD7 0x0AB3
+#define mmMC_SEQ_MISC0 0x0A80
+#define mmMC_SEQ_MISC1 0x0A81
+#define mmMC_SEQ_MISC3 0x0A8B
+#define mmMC_SEQ_MISC4 0x0A8C
+#define mmMC_SEQ_MISC5 0x0A95
+#define mmMC_SEQ_MISC6 0x0A96
+#define mmMC_SEQ_MISC7 0x0A99
+#define mmMC_SEQ_MISC8 0x0A5F
+#define mmMC_SEQ_MISC9 0x0AE7
+#define mmMC_SEQ_MISC_TIMING 0x0A2A
+#define mmMC_SEQ_MISC_TIMING2 0x0A2B
+#define mmMC_SEQ_MISC_TIMING2_LP 0x0A9E
+#define mmMC_SEQ_MISC_TIMING_LP 0x0A9D
+#define mmMC_SEQ_MPLL_OVERRIDE 0x0A22
+#define mmMC_SEQ_PERF_CNTL 0x0A77
+#define mmMC_SEQ_PERF_CNTL_1 0x0AFD
+#define mmMC_SEQ_PERF_SEQ_CNT_A_I0 0x0A79
+#define mmMC_SEQ_PERF_SEQ_CNT_A_I1 0x0A7A
+#define mmMC_SEQ_PERF_SEQ_CNT_B_I0 0x0A7B
+#define mmMC_SEQ_PERF_SEQ_CNT_B_I1 0x0A7C
+#define mmMC_SEQ_PERF_SEQ_CNT_C_I0 0x0AD9
+#define mmMC_SEQ_PERF_SEQ_CNT_C_I1 0x0ADA
+#define mmMC_SEQ_PERF_SEQ_CNT_D_I0 0x0ADB
+#define mmMC_SEQ_PERF_SEQ_CNT_D_I1 0x0ADC
+#define mmMC_SEQ_PERF_SEQ_CTL 0x0A78
+#define mmMC_SEQ_PMG_CMD_EMRS_LP 0x0AA1
+#define mmMC_SEQ_PMG_CMD_MRS1_LP 0x0AD2
+#define mmMC_SEQ_PMG_CMD_MRS2_LP 0x0AD8
+#define mmMC_SEQ_PMG_CMD_MRS_LP 0x0AA2
+#define mmMC_SEQ_PMG_PG_HWCNTL 0x0AB9
+#define mmMC_SEQ_PMG_PG_SWCNTL_0 0x0ABA
+#define mmMC_SEQ_PMG_PG_SWCNTL_1 0x0ABB
+#define mmMC_SEQ_PMG_TIMING 0x0A2C
+#define mmMC_SEQ_PMG_TIMING_LP 0x0AD3
+#define mmMC_SEQ_RAS_TIMING 0x0A28
+#define mmMC_SEQ_RAS_TIMING_LP 0x0A9B
+#define mmMC_SEQ_RD_CTL_D0 0x0A2D
+#define mmMC_SEQ_RD_CTL_D0_LP 0x0AC7
+#define mmMC_SEQ_RD_CTL_D1 0x0A2E
+#define mmMC_SEQ_RD_CTL_D1_LP 0x0AC8
+#define mmMC_SEQ_RESERVE_0_S 0x0A1E
+#define mmMC_SEQ_RESERVE_1_S 0x0A1F
+#define mmMC_SEQ_RESERVE_M 0x0A82
+#define mmMC_SEQ_RXFRAMING_BYTE0_D0 0x0A67
+#define mmMC_SEQ_RXFRAMING_BYTE0_D1 0x0A6D
+#define mmMC_SEQ_RXFRAMING_BYTE1_D0 0x0A68
+#define mmMC_SEQ_RXFRAMING_BYTE1_D1 0x0A6E
+#define mmMC_SEQ_RXFRAMING_BYTE2_D0 0x0A69
+#define mmMC_SEQ_RXFRAMING_BYTE2_D1 0x0A6F
+#define mmMC_SEQ_RXFRAMING_BYTE3_D0 0x0A6A
+#define mmMC_SEQ_RXFRAMING_BYTE3_D1 0x0A70
+#define mmMC_SEQ_RXFRAMING_DBI_D0 0x0A6B
+#define mmMC_SEQ_RXFRAMING_DBI_D1 0x0A71
+#define mmMC_SEQ_RXFRAMING_EDC_D0 0x0A6C
+#define mmMC_SEQ_RXFRAMING_EDC_D1 0x0A72
+#define mmMC_SEQ_STATUS_M 0x0A7D
+#define mmMC_SEQ_STATUS_S 0x0A20
+#define mmMC_SEQ_SUP_CNTL 0x0A32
+#define mmMC_SEQ_SUP_DEC_STAT 0x0A88
+#define mmMC_SEQ_SUP_GP0_STAT 0x0A8F
+#define mmMC_SEQ_SUP_GP1_STAT 0x0A90
+#define mmMC_SEQ_SUP_GP2_STAT 0x0A85
+#define mmMC_SEQ_SUP_GP3_STAT 0x0A86
+#define mmMC_SEQ_SUP_IR_STAT 0x0A87
+#define mmMC_SEQ_SUP_PGM 0x0A33
+#define mmMC_SEQ_SUP_PGM_STAT 0x0A89
+#define mmMC_SEQ_SUP_R_PGM 0x0A8A
+#define mmMC_SEQ_TCG_CNTL 0x0ABD
+#define mmMC_SEQ_TIMER_RD 0x0ACA
+#define mmMC_SEQ_TIMER_WR 0x0AC9
+#define mmMC_SEQ_TRAIN_CAPTURE 0x0A3E
+#define mmMC_SEQ_TRAIN_EDC_THRESHOLD 0x0A3B
+#define mmMC_SEQ_TRAIN_EDC_THRESHOLD2 0x0AFE
+#define mmMC_SEQ_TRAIN_EDC_THRESHOLD3 0x0AFF
+#define mmMC_SEQ_TRAIN_TIMING 0x0A40
+#define mmMC_SEQ_TRAIN_WAKEUP_CLEAR 0x0A3F
+#define mmMC_SEQ_TRAIN_WAKEUP_CNTL 0x0A3A
+#define mmMC_SEQ_TRAIN_WAKEUP_EDGE 0x0A3C
+#define mmMC_SEQ_TRAIN_WAKEUP_MASK 0x0A3D
+#define mmMC_SEQ_TSM_BCNT 0x0AC2
+#define mmMC_SEQ_TSM_CTRL 0x0ABE
+#define mmMC_SEQ_TSM_DBI 0x0AC6
+#define mmMC_SEQ_TSM_DEBUG_DATA 0x0AD0
+#define mmMC_SEQ_TSM_DEBUG_INDEX 0x0ACF
+#define mmMC_SEQ_TSM_EDC 0x0AC5
+#define mmMC_SEQ_TSM_FLAG 0x0AC3
+#define mmMC_SEQ_TSM_GCNT 0x0ABF
+#define mmMC_SEQ_TSM_MISC 0x0AE6
+#define mmMC_SEQ_TSM_NCNT 0x0AC1
+#define mmMC_SEQ_TSM_OCNT 0x0AC0
+#define mmMC_SEQ_TSM_UPDATE 0x0AC4
+#define mmMC_SEQ_TSM_WCDR 0x0AE3
+#define mmMC_SEQ_TXFRAMING_BYTE0_D0 0x0A58
+#define mmMC_SEQ_TXFRAMING_BYTE0_D1 0x0A60
+#define mmMC_SEQ_TXFRAMING_BYTE1_D0 0x0A59
+#define mmMC_SEQ_TXFRAMING_BYTE1_D1 0x0A61
+#define mmMC_SEQ_TXFRAMING_BYTE2_D0 0x0A5A
+#define mmMC_SEQ_TXFRAMING_BYTE2_D1 0x0A62
+#define mmMC_SEQ_TXFRAMING_BYTE3_D0 0x0A5B
+#define mmMC_SEQ_TXFRAMING_BYTE3_D1 0x0A63
+#define mmMC_SEQ_TXFRAMING_DBI_D0 0x0A5C
+#define mmMC_SEQ_TXFRAMING_DBI_D1 0x0A64
+#define mmMC_SEQ_TXFRAMING_EDC_D0 0x0A5D
+#define mmMC_SEQ_TXFRAMING_EDC_D1 0x0A65
+#define mmMC_SEQ_TXFRAMING_FCK_D0 0x0A5E
+#define mmMC_SEQ_TXFRAMING_FCK_D1 0x0A66
+#define mmMC_SEQ_VENDOR_ID_I0 0x0A7E
+#define mmMC_SEQ_VENDOR_ID_I1 0x0A7F
+#define mmMC_SEQ_WCDR_CTRL 0x0A39
+#define mmMC_SEQ_WR_CTL_2 0x0AD5
+#define mmMC_SEQ_WR_CTL_2_LP 0x0AD6
+#define mmMC_SEQ_WR_CTL_D0 0x0A2F
+#define mmMC_SEQ_WR_CTL_D0_LP 0x0A9F
+#define mmMC_SEQ_WR_CTL_D1 0x0A30
+#define mmMC_SEQ_WR_CTL_D1_LP 0x0AA0
+#define mmMC_SHARED_BLACKOUT_CNTL 0x082B
+#define mmMC_SHARED_CHMAP 0x0801
+#define mmMC_SHARED_CHREMAP 0x0802
+#define mmMC_TRAIN_EDCCDR_R_D0 0x0A41
+#define mmMC_TRAIN_EDCCDR_R_D1 0x0A42
+#define mmMC_TRAIN_EDC_STATUS_D0 0x0A45
+#define mmMC_TRAIN_EDC_STATUS_D1 0x0A48
+#define mmMC_TRAIN_PRBSERR_0_D0 0x0A43
+#define mmMC_TRAIN_PRBSERR_0_D1 0x0A46
+#define mmMC_TRAIN_PRBSERR_1_D0 0x0A44
+#define mmMC_TRAIN_PRBSERR_1_D1 0x0A47
+#define mmMC_TRAIN_PRBSERR_2_D0 0x0AFB
+#define mmMC_TRAIN_PRBSERR_2_D1 0x0AFC
+#define mmMC_VM_AGP_BASE 0x080C
+#define mmMC_VM_AGP_BOT 0x080B
+#define mmMC_VM_AGP_TOP 0x080A
+#define mmMC_VM_DC_WRITE_CNTL 0x0810
+#define mmMC_VM_DC_WRITE_HIT_REGION_0_HIGH_ADDR 0x0815
+#define mmMC_VM_DC_WRITE_HIT_REGION_0_LOW_ADDR 0x0811
+#define mmMC_VM_DC_WRITE_HIT_REGION_1_HIGH_ADDR 0x0816
+#define mmMC_VM_DC_WRITE_HIT_REGION_1_LOW_ADDR 0x0812
+#define mmMC_VM_DC_WRITE_HIT_REGION_2_HIGH_ADDR 0x0817
+#define mmMC_VM_DC_WRITE_HIT_REGION_2_LOW_ADDR 0x0813
+#define mmMC_VM_DC_WRITE_HIT_REGION_3_HIGH_ADDR 0x0818
+#define mmMC_VM_DC_WRITE_HIT_REGION_3_LOW_ADDR 0x0814
+#define mmMC_VM_FB_LOCATION 0x0809
+#define mmMC_VM_FB_OFFSET 0x081A
+#define mmMC_VM_MB_L1_TLB0_DEBUG 0x0891
+#define mmMC_VM_MB_L1_TLB0_STATUS 0x0895
+#define mmMC_VM_MB_L1_TLB1_STATUS 0x0896
+#define mmMC_VM_MB_L1_TLB2_DEBUG 0x0893
+#define mmMC_VM_MB_L1_TLB2_STATUS 0x0897
+#define mmMC_VM_MB_L1_TLB3_DEBUG 0x08A5
+#define mmMC_VM_MB_L1_TLB3_STATUS 0x08A6
+#define mmMC_VM_MB_L2ARBITER_L2_CREDITS 0x08A1
+#define mmMC_VM_MD_L1_TLB0_DEBUG 0x0998
+#define mmMC_VM_MD_L1_TLB0_STATUS 0x099B
+#define mmMC_VM_MD_L1_TLB1_DEBUG 0x0999
+#define mmMC_VM_MD_L1_TLB1_STATUS 0x099C
+#define mmMC_VM_MD_L1_TLB2_DEBUG 0x099A
+#define mmMC_VM_MD_L1_TLB2_STATUS 0x099D
+#define mmMC_VM_MD_L1_TLB3_DEBUG 0x09A7
+#define mmMC_VM_MD_L1_TLB3_STATUS 0x09A8
+#define mmMC_VM_MD_L2ARBITER_L2_CREDITS 0x09A4
+#define mmMC_VM_MX_L1_TLB_CNTL 0x0819
+#define mmMC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x080F
+#define mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x080E
+#define mmMC_VM_SYSTEM_APERTURE_LOW_ADDR 0x080D
+#define mmMC_WR_CB 0x0986
+#define mmMC_WR_DB 0x0987
+#define mmMC_WR_GRP_EXT 0x0979
+#define mmMC_WR_GRP_GFX 0x0804
+#define mmMC_WR_GRP_LCL 0x098B
+#define mmMC_WR_GRP_OTH 0x0808
+#define mmMC_WR_GRP_SYS 0x0806
+#define mmMC_WR_HUB 0x0988
+#define mmMC_WR_TC0 0x097B
+#define mmMC_WR_TC1 0x097C
+#define mmMC_XBAR_ADDR_DEC 0x0C80
+#define mmMC_XBAR_ARB 0x0C8D
+#define mmMC_XBAR_ARB_MAX_BURST 0x0C8E
+#define mmMC_XBAR_CHTRIREMAP 0x0C8B
+#define mmMC_XBAR_PERF_MON_CNTL0 0x0C8F
+#define mmMC_XBAR_PERF_MON_CNTL1 0x0C90
+#define mmMC_XBAR_PERF_MON_CNTL2 0x0C91
+#define mmMC_XBAR_PERF_MON_MAX_THSH 0x0C96
+#define mmMC_XBAR_PERF_MON_RSLT0 0x0C92
+#define mmMC_XBAR_PERF_MON_RSLT1 0x0C93
+#define mmMC_XBAR_PERF_MON_RSLT2 0x0C94
+#define mmMC_XBAR_PERF_MON_RSLT3 0x0C95
+#define mmMC_XBAR_RDREQ_CREDIT 0x0C83
+#define mmMC_XBAR_RDREQ_PRI_CREDIT 0x0C84
+#define mmMC_XBAR_RDRET_CREDIT1 0x0C87
+#define mmMC_XBAR_RDRET_CREDIT2 0x0C88
+#define mmMC_XBAR_RDRET_PRI_CREDIT1 0x0C89
+#define mmMC_XBAR_RDRET_PRI_CREDIT2 0x0C8A
+#define mmMC_XBAR_REMOTE 0x0C81
+#define mmMC_XBAR_SPARE0 0x0C97
+#define mmMC_XBAR_SPARE1 0x0C98
+#define mmMC_XBAR_TWOCHAN 0x0C8C
+#define mmMC_XBAR_WRREQ_CREDIT 0x0C82
+#define mmMC_XBAR_WRRET_CREDIT1 0x0C85
+#define mmMC_XBAR_WRRET_CREDIT2 0x0C86
+#define mmMC_XPB_CLG_CFG0 0x08E9
+#define mmMC_XPB_CLG_CFG10 0x08F3
+#define mmMC_XPB_CLG_CFG1 0x08EA
+#define mmMC_XPB_CLG_CFG11 0x08F4
+#define mmMC_XPB_CLG_CFG12 0x08F5
+#define mmMC_XPB_CLG_CFG13 0x08F6
+#define mmMC_XPB_CLG_CFG14 0x08F7
+#define mmMC_XPB_CLG_CFG15 0x08F8
+#define mmMC_XPB_CLG_CFG16 0x08F9
+#define mmMC_XPB_CLG_CFG17 0x08FA
+#define mmMC_XPB_CLG_CFG18 0x08FB
+#define mmMC_XPB_CLG_CFG19 0x08FC
+#define mmMC_XPB_CLG_CFG20 0x0928
+#define mmMC_XPB_CLG_CFG2 0x08EB
+#define mmMC_XPB_CLG_CFG21 0x0929
+#define mmMC_XPB_CLG_CFG22 0x092A
+#define mmMC_XPB_CLG_CFG23 0x092B
+#define mmMC_XPB_CLG_CFG24 0x092C
+#define mmMC_XPB_CLG_CFG25 0x092D
+#define mmMC_XPB_CLG_CFG26 0x092E
+#define mmMC_XPB_CLG_CFG27 0x092F
+#define mmMC_XPB_CLG_CFG28 0x0930
+#define mmMC_XPB_CLG_CFG29 0x0931
+#define mmMC_XPB_CLG_CFG30 0x0932
+#define mmMC_XPB_CLG_CFG3 0x08EC
+#define mmMC_XPB_CLG_CFG31 0x0933
+#define mmMC_XPB_CLG_CFG32 0x0936
+#define mmMC_XPB_CLG_CFG33 0x0937
+#define mmMC_XPB_CLG_CFG34 0x0938
+#define mmMC_XPB_CLG_CFG35 0x0939
+#define mmMC_XPB_CLG_CFG36 0x093A
+#define mmMC_XPB_CLG_CFG4 0x08ED
+#define mmMC_XPB_CLG_CFG5 0x08EE
+#define mmMC_XPB_CLG_CFG6 0x08EF
+#define mmMC_XPB_CLG_CFG7 0x08F0
+#define mmMC_XPB_CLG_CFG8 0x08F1
+#define mmMC_XPB_CLG_CFG9 0x08F2
+#define mmMC_XPB_CLG_EXTRA 0x08FD
+#define mmMC_XPB_CLG_EXTRA_RD 0x0935
+#define mmMC_XPB_CLK_GAT 0x091E
+#define mmMC_XPB_INTF_CFG 0x091F
+#define mmMC_XPB_INTF_CFG2 0x0934
+#define mmMC_XPB_INTF_STS 0x0920
+#define mmMC_XPB_LB_ADDR 0x08FE
+#define mmMC_XPB_MAP_INVERT_FLUSH_NUM_LSB 0x0923
+#define mmMC_XPB_MISC_CFG 0x0927
+#define mmMC_XPB_P2P_BAR0 0x0904
+#define mmMC_XPB_P2P_BAR1 0x0905
+#define mmMC_XPB_P2P_BAR2 0x0906
+#define mmMC_XPB_P2P_BAR3 0x0907
+#define mmMC_XPB_P2P_BAR4 0x0908
+#define mmMC_XPB_P2P_BAR5 0x0909
+#define mmMC_XPB_P2P_BAR6 0x090A
+#define mmMC_XPB_P2P_BAR7 0x090B
+#define mmMC_XPB_P2P_BAR_CFG 0x0903
+#define mmMC_XPB_P2P_BAR_DEBUG 0x090D
+#define mmMC_XPB_P2P_BAR_DELTA_ABOVE 0x090E
+#define mmMC_XPB_P2P_BAR_DELTA_BELOW 0x090F
+#define mmMC_XPB_P2P_BAR_SETUP 0x090C
+#define mmMC_XPB_PEER_SYS_BAR0 0x0910
+#define mmMC_XPB_PEER_SYS_BAR1 0x0911
+#define mmMC_XPB_PEER_SYS_BAR2 0x0912
+#define mmMC_XPB_PEER_SYS_BAR3 0x0913
+#define mmMC_XPB_PEER_SYS_BAR4 0x0914
+#define mmMC_XPB_PEER_SYS_BAR5 0x0915
+#define mmMC_XPB_PEER_SYS_BAR6 0x0916
+#define mmMC_XPB_PEER_SYS_BAR7 0x0917
+#define mmMC_XPB_PEER_SYS_BAR8 0x0918
+#define mmMC_XPB_PEER_SYS_BAR9 0x0919
+#define mmMC_XPB_PERF_KNOBS 0x0924
+#define mmMC_XPB_PIPE_STS 0x0921
+#define mmMC_XPB_RTR_DEST_MAP0 0x08DB
+#define mmMC_XPB_RTR_DEST_MAP1 0x08DC
+#define mmMC_XPB_RTR_DEST_MAP2 0x08DD
+#define mmMC_XPB_RTR_DEST_MAP3 0x08DE
+#define mmMC_XPB_RTR_DEST_MAP4 0x08DF
+#define mmMC_XPB_RTR_DEST_MAP5 0x08E0
+#define mmMC_XPB_RTR_DEST_MAP6 0x08E1
+#define mmMC_XPB_RTR_DEST_MAP7 0x08E2
+#define mmMC_XPB_RTR_DEST_MAP8 0x08E3
+#define mmMC_XPB_RTR_DEST_MAP9 0x08E4
+#define mmMC_XPB_RTR_SRC_APRTR0 0x08CD
+#define mmMC_XPB_RTR_SRC_APRTR1 0x08CE
+#define mmMC_XPB_RTR_SRC_APRTR2 0x08CF
+#define mmMC_XPB_RTR_SRC_APRTR3 0x08D0
+#define mmMC_XPB_RTR_SRC_APRTR4 0x08D1
+#define mmMC_XPB_RTR_SRC_APRTR5 0x08D2
+#define mmMC_XPB_RTR_SRC_APRTR6 0x08D3
+#define mmMC_XPB_RTR_SRC_APRTR7 0x08D4
+#define mmMC_XPB_RTR_SRC_APRTR8 0x08D5
+#define mmMC_XPB_RTR_SRC_APRTR9 0x08D6
+#define mmMC_XPB_STICKY 0x0925
+#define mmMC_XPB_STICKY_W1C 0x0926
+#define mmMC_XPB_SUB_CTRL 0x0922
+#define mmMC_XPB_UNC_THRESH_HST 0x08FF
+#define mmMC_XPB_UNC_THRESH_SID 0x0900
+#define mmMC_XPB_WCB_CFG 0x0902
+#define mmMC_XPB_WCB_STS 0x0901
+#define mmMC_XPB_XDMA_PEER_SYS_BAR0 0x091A
+#define mmMC_XPB_XDMA_PEER_SYS_BAR1 0x091B
+#define mmMC_XPB_XDMA_PEER_SYS_BAR2 0x091C
+#define mmMC_XPB_XDMA_PEER_SYS_BAR3 0x091D
+#define mmMC_XPB_XDMA_RTR_DEST_MAP0 0x08E5
+#define mmMC_XPB_XDMA_RTR_DEST_MAP1 0x08E6
+#define mmMC_XPB_XDMA_RTR_DEST_MAP2 0x08E7
+#define mmMC_XPB_XDMA_RTR_DEST_MAP3 0x08E8
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR0 0x08D7
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR1 0x08D8
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR2 0x08D9
+#define mmMC_XPB_XDMA_RTR_SRC_APRTR3 0x08DA
+#define mmMPLL_AD_FUNC_CNTL 0x0AF0
+#define mmMPLL_AD_STATUS 0x0AF6
+#define mmMPLL_CNTL_MODE 0x0AEC
+#define mmMPLL_CONTROL 0x0AF5
+#define mmMPLL_DQ_0_0_STATUS 0x0AF7
+#define mmMPLL_DQ_0_1_STATUS 0x0AF8
+#define mmMPLL_DQ_1_0_STATUS 0x0AF9
+#define mmMPLL_DQ_1_1_STATUS 0x0AFA
+#define mmMPLL_DQ_FUNC_CNTL 0x0AF1
+#define mmMPLL_FUNC_CNTL 0x0AED
+#define mmMPLL_FUNC_CNTL_1 0x0AEE
+#define mmMPLL_FUNC_CNTL_2 0x0AEF
+#define mmMPLL_SEQ_UCODE_1 0x0AEA
+#define mmMPLL_SEQ_UCODE_2 0x0AEB
+#define mmMPLL_SS1 0x0AF3
+#define mmMPLL_SS2 0x0AF4
+#define mmMPLL_TIME 0x0AF2
+#define mmVM_CONTEXT0_CNTL 0x0504
+#define mmVM_CONTEXT0_CNTL2 0x050C
+#define mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x054F
+#define mmVM_CONTEXT0_PAGE_TABLE_END_ADDR 0x055F
+#define mmVM_CONTEXT0_PAGE_TABLE_START_ADDR 0x0557
+#define mmVM_CONTEXT0_PROTECTION_FAULT_ADDR 0x053E
+#define mmVM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR 0x0546
+#define mmVM_CONTEXT0_PROTECTION_FAULT_STATUS 0x0536
+#define mmVM_CONTEXT10_PAGE_TABLE_BASE_ADDR 0x0510
+#define mmVM_CONTEXT11_PAGE_TABLE_BASE_ADDR 0x0511
+#define mmVM_CONTEXT12_PAGE_TABLE_BASE_ADDR 0x0512
+#define mmVM_CONTEXT13_PAGE_TABLE_BASE_ADDR 0x0513
+#define mmVM_CONTEXT14_PAGE_TABLE_BASE_ADDR 0x0514
+#define mmVM_CONTEXT15_PAGE_TABLE_BASE_ADDR 0x0515
+#define mmVM_CONTEXT1_CNTL 0x0505
+#define mmVM_CONTEXT1_CNTL2 0x050D
+#define mmVM_CONTEXT1_PAGE_TABLE_BASE_ADDR 0x0550
+#define mmVM_CONTEXT1_PAGE_TABLE_END_ADDR 0x0560
+#define mmVM_CONTEXT1_PAGE_TABLE_START_ADDR 0x0558
+#define mmVM_CONTEXT1_PROTECTION_FAULT_ADDR 0x053F
+#define mmVM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR 0x0547
+#define mmVM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0537
+#define mmVM_CONTEXT2_PAGE_TABLE_BASE_ADDR 0x0551
+#define mmVM_CONTEXT3_PAGE_TABLE_BASE_ADDR 0x0552
+#define mmVM_CONTEXT4_PAGE_TABLE_BASE_ADDR 0x0553
+#define mmVM_CONTEXT5_PAGE_TABLE_BASE_ADDR 0x0554
+#define mmVM_CONTEXT6_PAGE_TABLE_BASE_ADDR 0x0555
+#define mmVM_CONTEXT7_PAGE_TABLE_BASE_ADDR 0x0556
+#define mmVM_CONTEXT8_PAGE_TABLE_BASE_ADDR 0x050E
+#define mmVM_CONTEXT9_PAGE_TABLE_BASE_ADDR 0x050F
+#define mmVM_CONTEXTS_DISABLE 0x0535
+#define mmVM_DEBUG 0x056F
+#define mmVM_DUMMY_PAGE_FAULT_ADDR 0x0507
+#define mmVM_DUMMY_PAGE_FAULT_CNTL 0x0506
+#define mmVM_FAULT_CLIENT_ID 0x054E
+#define mmVM_INVALIDATE_REQUEST 0x051E
+#define mmVM_INVALIDATE_RESPONSE 0x051F
+#define mmVM_L2_BANK_SELECT_MASKA 0x0572
+#define mmVM_L2_BANK_SELECT_MASKB 0x0573
+#define mmVM_L2_CG 0x0570
+#define mmVM_L2_CNTL 0x0500
+#define mmVM_L2_CNTL2 0x0501
+#define mmVM_L2_CNTL3 0x0502
+#define mmVM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR 0x0576
+#define mmVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR 0x0575
+#define mmVM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET 0x0577
+#define mmVM_L2_STATUS 0x0503
+#define mmVM_PRT_APERTURE0_HIGH_ADDR 0x0530
+#define mmVM_PRT_APERTURE0_LOW_ADDR 0x052C
+#define mmVM_PRT_APERTURE1_HIGH_ADDR 0x0531
+#define mmVM_PRT_APERTURE1_LOW_ADDR 0x052D
+#define mmVM_PRT_APERTURE2_HIGH_ADDR 0x0532
+#define mmVM_PRT_APERTURE2_LOW_ADDR 0x052E
+#define mmVM_PRT_APERTURE3_HIGH_ADDR 0x0533
+#define mmVM_PRT_APERTURE3_LOW_ADDR 0x052F
+#define mmVM_PRT_CNTL 0x0534
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/gmc/gmc_6_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,11895 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 GMC_6_0_SH_MASK_H
+#define GMC_6_0_SH_MASK_H
+
+#define ATC_ATS_CNTL__CREDITS_ATS_RPB_MASK 0x00003f00L
+#define ATC_ATS_CNTL__CREDITS_ATS_RPB__SHIFT 0x00000008
+#define ATC_ATS_CNTL__DEBUG_ECO_MASK 0x000f0000L
+#define ATC_ATS_CNTL__DEBUG_ECO__SHIFT 0x00000010
+#define ATC_ATS_CNTL__DISABLE_ATC_MASK 0x00000001L
+#define ATC_ATS_CNTL__DISABLE_ATC__SHIFT 0x00000000
+#define ATC_ATS_CNTL__DISABLE_PASID_MASK 0x00000004L
+#define ATC_ATS_CNTL__DISABLE_PASID__SHIFT 0x00000002
+#define ATC_ATS_CNTL__DISABLE_PRI_MASK 0x00000002L
+#define ATC_ATS_CNTL__DISABLE_PRI__SHIFT 0x00000001
+#define ATC_ATS_DEBUG__ADDRESS_TRANSLATION_REQUEST_WRITE_PERMS_MASK 0x00000004L
+#define ATC_ATS_DEBUG__ADDRESS_TRANSLATION_REQUEST_WRITE_PERMS__SHIFT 0x00000002
+#define ATC_ATS_DEBUG__DISALLOW_ERR_TO_DONE_MASK 0x00004000L
+#define ATC_ATS_DEBUG__DISALLOW_ERR_TO_DONE__SHIFT 0x0000000e
+#define ATC_ATS_DEBUG__EXE_BIT_MASK 0x00000080L
+#define ATC_ATS_DEBUG__EXE_BIT__SHIFT 0x00000007
+#define ATC_ATS_DEBUG__IDENT_RETURN_MASK 0x00000002L
+#define ATC_ATS_DEBUG__IDENT_RETURN__SHIFT 0x00000001
+#define ATC_ATS_DEBUG__IGNORE_FED_MASK 0x00008000L
+#define ATC_ATS_DEBUG__IGNORE_FED__SHIFT 0x0000000f
+#define ATC_ATS_DEBUG__INVALIDATE_ALL_MASK 0x00000001L
+#define ATC_ATS_DEBUG__INVALIDATE_ALL__SHIFT 0x00000000
+#define ATC_ATS_DEBUG__INVALIDATION_REQUESTS_DISALLOWED_WHEN_ATC_IS_DISABLED_MASK 0x00010000L
+#define ATC_ATS_DEBUG__INVALIDATION_REQUESTS_DISALLOWED_WHEN_ATC_IS_DISABLED__SHIFT 0x00000010
+#define ATC_ATS_DEBUG__NUM_REQUESTS_AT_ERR_MASK 0x00003c00L
+#define ATC_ATS_DEBUG__NUM_REQUESTS_AT_ERR__SHIFT 0x0000000a
+#define ATC_ATS_DEBUG__PAGE_REQUEST_PERMS_MASK 0x00000100L
+#define ATC_ATS_DEBUG__PAGE_REQUEST_PERMS__SHIFT 0x00000008
+#define ATC_ATS_DEBUG__PAGE_REQUESTS_USE_RELAXED_ORDERING_MASK 0x00000020L
+#define ATC_ATS_DEBUG__PAGE_REQUESTS_USE_RELAXED_ORDERING__SHIFT 0x00000005
+#define ATC_ATS_DEBUG__PRIV_BIT_MASK 0x00000040L
+#define ATC_ATS_DEBUG__PRIV_BIT__SHIFT 0x00000006
+#define ATC_ATS_DEBUG__UNTRANSLATED_ONLY_REQUESTS_CARRY_SIZE_MASK 0x00000200L
+#define ATC_ATS_DEBUG__UNTRANSLATED_ONLY_REQUESTS_CARRY_SIZE__SHIFT 0x00000009
+#define ATC_ATS_DEFAULT_PAGE_CNTL__DEFAULT_PAGE_HIGH_MASK 0x0000003cL
+#define ATC_ATS_DEFAULT_PAGE_CNTL__DEFAULT_PAGE_HIGH__SHIFT 0x00000002
+#define ATC_ATS_DEFAULT_PAGE_CNTL__SEND_DEFAULT_PAGE_MASK 0x00000001L
+#define ATC_ATS_DEFAULT_PAGE_CNTL__SEND_DEFAULT_PAGE__SHIFT 0x00000000
+#define ATC_ATS_DEFAULT_PAGE_LOW__DEFAULT_PAGE_MASK 0xffffffffL
+#define ATC_ATS_DEFAULT_PAGE_LOW__DEFAULT_PAGE__SHIFT 0x00000000
+#define ATC_ATS_FAULT_CNTL__FAULT_CRASH_TABLE_MASK 0x03f00000L
+#define ATC_ATS_FAULT_CNTL__FAULT_CRASH_TABLE__SHIFT 0x00000014
+#define ATC_ATS_FAULT_CNTL__FAULT_INTERRUPT_TABLE_MASK 0x0000fc00L
+#define ATC_ATS_FAULT_CNTL__FAULT_INTERRUPT_TABLE__SHIFT 0x0000000a
+#define ATC_ATS_FAULT_CNTL__FAULT_REGISTER_LOG_MASK 0x0000003fL
+#define ATC_ATS_FAULT_CNTL__FAULT_REGISTER_LOG__SHIFT 0x00000000
+#define ATC_ATS_FAULT_DEBUG__ALLOW_SUBSEQUENT_FAULT_STATUS_ADDR_UPDATES_MASK 0x00000100L
+#define ATC_ATS_FAULT_DEBUG__ALLOW_SUBSEQUENT_FAULT_STATUS_ADDR_UPDATES__SHIFT 0x00000008
+#define ATC_ATS_FAULT_DEBUG__CLEAR_FAULT_STATUS_ADDR_MASK 0x00010000L
+#define ATC_ATS_FAULT_DEBUG__CLEAR_FAULT_STATUS_ADDR__SHIFT 0x00000010
+#define ATC_ATS_FAULT_DEBUG__CREDITS_ATS_IH_MASK 0x0000001fL
+#define ATC_ATS_FAULT_DEBUG__CREDITS_ATS_IH__SHIFT 0x00000000
+#define ATC_ATS_FAULT_STATUS_ADDR__PAGE_ADDR_MASK 0xffffffffL
+#define ATC_ATS_FAULT_STATUS_ADDR__PAGE_ADDR__SHIFT 0x00000000
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO2_MASK 0x00010000L
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO2__SHIFT 0x00000010
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO_MASK 0x00008000L
+#define ATC_ATS_FAULT_STATUS_INFO__EXTRA_INFO__SHIFT 0x0000000f
+#define ATC_ATS_FAULT_STATUS_INFO__FAULT_TYPE_MASK 0x0000003fL
+#define ATC_ATS_FAULT_STATUS_INFO__FAULT_TYPE__SHIFT 0x00000000
+#define ATC_ATS_FAULT_STATUS_INFO__INVALIDATION_MASK 0x00020000L
+#define ATC_ATS_FAULT_STATUS_INFO__INVALIDATION__SHIFT 0x00000011
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_ADDR_HIGH_MASK 0x0f000000L
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_ADDR_HIGH__SHIFT 0x00000018
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_REQUEST_MASK 0x00040000L
+#define ATC_ATS_FAULT_STATUS_INFO__PAGE_REQUEST__SHIFT 0x00000012
+#define ATC_ATS_FAULT_STATUS_INFO__STATUS_MASK 0x00f80000L
+#define ATC_ATS_FAULT_STATUS_INFO__STATUS__SHIFT 0x00000013
+#define ATC_ATS_FAULT_STATUS_INFO__VMID_MASK 0x00007c00L
+#define ATC_ATS_FAULT_STATUS_INFO__VMID__SHIFT 0x0000000a
+#define ATC_ATS_STATUS__BUSY_MASK 0x00000001L
+#define ATC_ATS_STATUS__BUSY__SHIFT 0x00000000
+#define ATC_ATS_STATUS__CRASHED_MASK 0x00000002L
+#define ATC_ATS_STATUS__CRASHED__SHIFT 0x00000001
+#define ATC_ATS_STATUS__DEADLOCK_DETECTION_MASK 0x00000004L
+#define ATC_ATS_STATUS__DEADLOCK_DETECTION__SHIFT 0x00000002
+#define ATC_L1_ADDRESS_OFFSET__LOGICAL_ADDRESS_MASK 0xffffffffL
+#define ATC_L1_ADDRESS_OFFSET__LOGICAL_ADDRESS__SHIFT 0x00000000
+#define ATC_L1_CNTL__DONT_NEED_ATS_BEHAVIOR_MASK 0x00000003L
+#define ATC_L1_CNTL__DONT_NEED_ATS_BEHAVIOR__SHIFT 0x00000000
+#define ATC_L1_CNTL__NEED_ATS_BEHAVIOR_MASK 0x00000004L
+#define ATC_L1_CNTL__NEED_ATS_BEHAVIOR__SHIFT 0x00000002
+#define ATC_L1_CNTL__NEED_ATS_SNOOP_DEFAULT_MASK 0x00000010L
+#define ATC_L1_CNTL__NEED_ATS_SNOOP_DEFAULT__SHIFT 0x00000004
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_L2_MASK 0x0003f000L
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_L2__SHIFT 0x0000000c
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_RPB_MASK 0x0ff00000L
+#define ATC_L1RD_DEBUG_TLB__CREDITS_L1_RPB__SHIFT 0x00000014
+#define ATC_L1RD_DEBUG_TLB__DEBUG_ECO_MASK 0x30000000L
+#define ATC_L1RD_DEBUG_TLB__DEBUG_ECO__SHIFT 0x0000001c
+#define ATC_L1RD_DEBUG_TLB__DISABLE_FRAGMENTS_MASK 0x00000001L
+#define ATC_L1RD_DEBUG_TLB__DISABLE_FRAGMENTS__SHIFT 0x00000000
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_CAM_SIZE_MASK 0x000000f0L
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_CAM_SIZE__SHIFT 0x00000004
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE_MASK 0x00000700L
+#define ATC_L1RD_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE__SHIFT 0x00000008
+#define ATC_L1RD_DEBUG_TLB__INVALIDATE_ALL_MASK 0x40000000L
+#define ATC_L1RD_DEBUG_TLB__INVALIDATE_ALL__SHIFT 0x0000001e
+#define ATC_L1RD_STATUS__BAD_NEED_ATS_MASK 0x00000100L
+#define ATC_L1RD_STATUS__BAD_NEED_ATS__SHIFT 0x00000008
+#define ATC_L1RD_STATUS__BUSY_MASK 0x00000001L
+#define ATC_L1RD_STATUS__BUSY__SHIFT 0x00000000
+#define ATC_L1RD_STATUS__DEADLOCK_DETECTION_MASK 0x00000002L
+#define ATC_L1RD_STATUS__DEADLOCK_DETECTION__SHIFT 0x00000001
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_L2_MASK 0x0003f000L
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_L2__SHIFT 0x0000000c
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_RPB_MASK 0x0ff00000L
+#define ATC_L1WR_DEBUG_TLB__CREDITS_L1_RPB__SHIFT 0x00000014
+#define ATC_L1WR_DEBUG_TLB__DEBUG_ECO_MASK 0x30000000L
+#define ATC_L1WR_DEBUG_TLB__DEBUG_ECO__SHIFT 0x0000001c
+#define ATC_L1WR_DEBUG_TLB__DISABLE_FRAGMENTS_MASK 0x00000001L
+#define ATC_L1WR_DEBUG_TLB__DISABLE_FRAGMENTS__SHIFT 0x00000000
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_CAM_SIZE_MASK 0x000000f0L
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_CAM_SIZE__SHIFT 0x00000004
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE_MASK 0x00000700L
+#define ATC_L1WR_DEBUG_TLB__EFFECTIVE_WORK_QUEUE_SIZE__SHIFT 0x00000008
+#define ATC_L1WR_DEBUG_TLB__INVALIDATE_ALL_MASK 0x40000000L
+#define ATC_L1WR_DEBUG_TLB__INVALIDATE_ALL__SHIFT 0x0000001e
+#define ATC_L1WR_STATUS__BAD_NEED_ATS_MASK 0x00000100L
+#define ATC_L1WR_STATUS__BAD_NEED_ATS__SHIFT 0x00000008
+#define ATC_L1WR_STATUS__BUSY_MASK 0x00000001L
+#define ATC_L1WR_STATUS__BUSY__SHIFT 0x00000000
+#define ATC_L1WR_STATUS__DEADLOCK_DETECTION_MASK 0x00000002L
+#define ATC_L1WR_STATUS__DEADLOCK_DETECTION__SHIFT 0x00000001
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READ_REQUESTS_MASK 0x00000003L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READ_REQUESTS__SHIFT 0x00000000
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READS_DEPENDS_ON_ADDR_MOD_MASK 0x00000400L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_READS_DEPENDS_ON_ADDR_MOD__SHIFT 0x0000000a
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITE_REQUESTS_MASK 0x00000030L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITE_REQUESTS__SHIFT 0x00000004
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITES_DEPENDS_ON_ADDR_MOD_MASK 0x00000800L
+#define ATC_L2_CNTL__NUMBER_OF_TRANSLATION_WRITES_DEPENDS_ON_ADDR_MOD__SHIFT 0x0000000b
+#define ATC_L2_DEBUG__CREDITS_L2_ATS_MASK 0x0000003fL
+#define ATC_L2_DEBUG__CREDITS_L2_ATS__SHIFT 0x00000000
+#define ATC_MISC_CG__ENABLE_MASK 0x00040000L
+#define ATC_MISC_CG__ENABLE__SHIFT 0x00000012
+#define ATC_MISC_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define ATC_MISC_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define ATC_MISC_CG__OFFDLY_MASK 0x00000fc0L
+#define ATC_MISC_CG__OFFDLY__SHIFT 0x00000006
+#define ATC_VM_APERTURE0_CNTL2__VMIDS_USING_RANGE_MASK 0x0000ffffL
+#define ATC_VM_APERTURE0_CNTL2__VMIDS_USING_RANGE__SHIFT 0x00000000
+#define ATC_VM_APERTURE0_CNTL__ATS_ACCESS_MODE_MASK 0x00000003L
+#define ATC_VM_APERTURE0_CNTL__ATS_ACCESS_MODE__SHIFT 0x00000000
+#define ATC_VM_APERTURE0_HIGH_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE0_HIGH_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VM_APERTURE0_LOW_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE0_LOW_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_CNTL2__VMIDS_USING_RANGE_MASK 0x0000ffffL
+#define ATC_VM_APERTURE1_CNTL2__VMIDS_USING_RANGE__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_CNTL__ATS_ACCESS_MODE_MASK 0x00000003L
+#define ATC_VM_APERTURE1_CNTL__ATS_ACCESS_MODE__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_HIGH_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE1_HIGH_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VM_APERTURE1_LOW_ADDR__VIRTUAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define ATC_VM_APERTURE1_LOW_ADDR__VIRTUAL_PAGE_NUMBER__SHIFT 0x00000000
+#define ATC_VMID0_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID0_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID0_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID0_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID10_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID10_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID10_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID10_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID11_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID11_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID11_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID11_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID12_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID12_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID12_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID12_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID13_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID13_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID13_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID13_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID14_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID14_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID14_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID14_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID15_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID15_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID15_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID15_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID1_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID1_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID1_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID1_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID2_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID2_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID2_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID2_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID3_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID3_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID3_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID3_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID4_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID4_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID4_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID4_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID5_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID5_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID5_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID5_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID6_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID6_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID6_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID6_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID7_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID7_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID7_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID7_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID8_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID8_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID8_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID8_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID9_PASID_MAPPING__PASID_MASK 0x0000ffffL
+#define ATC_VMID9_PASID_MAPPING__PASID__SHIFT 0x00000000
+#define ATC_VMID9_PASID_MAPPING__VALID_MASK 0x80000000L
+#define ATC_VMID9_PASID_MAPPING__VALID__SHIFT 0x0000001f
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID0_REMAPPING_FINISHED_MASK 0x00000001L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID0_REMAPPING_FINISHED__SHIFT 0x00000000
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID10_REMAPPING_FINISHED_MASK 0x00000400L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID10_REMAPPING_FINISHED__SHIFT 0x0000000a
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID11_REMAPPING_FINISHED_MASK 0x00000800L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID11_REMAPPING_FINISHED__SHIFT 0x0000000b
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID12_REMAPPING_FINISHED_MASK 0x00001000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID12_REMAPPING_FINISHED__SHIFT 0x0000000c
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID13_REMAPPING_FINISHED_MASK 0x00002000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID13_REMAPPING_FINISHED__SHIFT 0x0000000d
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID14_REMAPPING_FINISHED_MASK 0x00004000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID14_REMAPPING_FINISHED__SHIFT 0x0000000e
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID15_REMAPPING_FINISHED_MASK 0x00008000L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID15_REMAPPING_FINISHED__SHIFT 0x0000000f
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID1_REMAPPING_FINISHED_MASK 0x00000002L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID1_REMAPPING_FINISHED__SHIFT 0x00000001
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID2_REMAPPING_FINISHED_MASK 0x00000004L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID2_REMAPPING_FINISHED__SHIFT 0x00000002
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID3_REMAPPING_FINISHED_MASK 0x00000008L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID3_REMAPPING_FINISHED__SHIFT 0x00000003
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID4_REMAPPING_FINISHED_MASK 0x00000010L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID4_REMAPPING_FINISHED__SHIFT 0x00000004
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID5_REMAPPING_FINISHED_MASK 0x00000020L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID5_REMAPPING_FINISHED__SHIFT 0x00000005
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID6_REMAPPING_FINISHED_MASK 0x00000040L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID6_REMAPPING_FINISHED__SHIFT 0x00000006
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID7_REMAPPING_FINISHED_MASK 0x00000080L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID7_REMAPPING_FINISHED__SHIFT 0x00000007
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID8_REMAPPING_FINISHED_MASK 0x00000100L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID8_REMAPPING_FINISHED__SHIFT 0x00000008
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID9_REMAPPING_FINISHED_MASK 0x00000200L
+#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS__VMID9_REMAPPING_FINISHED__SHIFT 0x00000009
+#define CC_MC_MAX_CHANNEL__NOOFCHAN_MASK 0x0000001eL
+#define CC_MC_MAX_CHANNEL__NOOFCHAN__SHIFT 0x00000001
+#define DLL_CNTL__DLL_LOCK_TIME_MASK 0x003ff000L
+#define DLL_CNTL__DLL_LOCK_TIME__SHIFT 0x0000000c
+#define DLL_CNTL__DLL_RESET_TIME_MASK 0x000003ffL
+#define DLL_CNTL__DLL_RESET_TIME__SHIFT 0x00000000
+#define DLL_CNTL__MRDCK0_BYPASS_MASK 0x01000000L
+#define DLL_CNTL__MRDCK0_BYPASS__SHIFT 0x00000018
+#define DLL_CNTL__MRDCK1_BYPASS_MASK 0x02000000L
+#define DLL_CNTL__MRDCK1_BYPASS__SHIFT 0x00000019
+#define DLL_CNTL__PWR2_MODE_MASK 0x04000000L
+#define DLL_CNTL__PWR2_MODE__SHIFT 0x0000001a
+#define GMCON_DEBUG__GFX_CLEAR_MASK 0x00000002L
+#define GMCON_DEBUG__GFX_CLEAR__SHIFT 0x00000001
+#define GMCON_DEBUG__GFX_STALL_MASK 0x00000001L
+#define GMCON_DEBUG__GFX_STALL__SHIFT 0x00000000
+#define GMCON_DEBUG__MISC_FLAGS_MASK 0x3ffffffcL
+#define GMCON_DEBUG__MISC_FLAGS__SHIFT 0x00000002
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE0_MASK 0x00000007L
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE0__SHIFT 0x00000000
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE1_MASK 0x00000038L
+#define GMCON_MISC2__RENG_MEM_POWER_CTRL_OVERRIDE1__SHIFT 0x00000003
+#define GMCON_MISC2__RENG_SR_HOLD_THRESHOLD_MASK 0x0000fc00L
+#define GMCON_MISC2__RENG_SR_HOLD_THRESHOLD__SHIFT 0x0000000a
+#define GMCON_MISC2__STCTRL_EXTEND_GMC_OFFLINE_MASK 0x20000000L
+#define GMCON_MISC2__STCTRL_EXTEND_GMC_OFFLINE__SHIFT 0x0000001d
+#define GMCON_MISC2__STCTRL_IGNORE_ARB_BUSY_MASK 0x10000000L
+#define GMCON_MISC2__STCTRL_IGNORE_ARB_BUSY__SHIFT 0x0000001c
+#define GMCON_MISC2__STCTRL_LPT_TARGET_MASK 0x0fff0000L
+#define GMCON_MISC2__STCTRL_LPT_TARGET__SHIFT 0x00000010
+#define GMCON_MISC3__RENG_DISABLE_MCC_MASK 0x0000003fL
+#define GMCON_MISC3__RENG_DISABLE_MCC__SHIFT 0x00000000
+#define GMCON_MISC3__RENG_DISABLE_MCD_MASK 0x00000fc0L
+#define GMCON_MISC3__RENG_DISABLE_MCD__SHIFT 0x00000006
+#define GMCON_MISC3__STCTRL_FORCE_PGFSM_CMD_DONE_MASK 0x00fff000L
+#define GMCON_MISC3__STCTRL_FORCE_PGFSM_CMD_DONE__SHIFT 0x0000000c
+#define GMCON_MISC__ALLOW_DEEP_SLEEP_MODE_MASK 0x30000000L
+#define GMCON_MISC__ALLOW_DEEP_SLEEP_MODE__SHIFT 0x0000001c
+#define GMCON_MISC__CRITICAL_REGS_LOCK_MASK 0x08000000L
+#define GMCON_MISC__CRITICAL_REGS_LOCK__SHIFT 0x0000001b
+#define GMCON_MISC__RENG_EXECUTE_NOW_MODE_MASK 0x00000400L
+#define GMCON_MISC__RENG_EXECUTE_NOW_MODE__SHIFT 0x0000000a
+#define GMCON_MISC__RENG_EXECUTE_ON_REG_UPDATE_MASK 0x00000800L
+#define GMCON_MISC__RENG_EXECUTE_ON_REG_UPDATE__SHIFT 0x0000000b
+#define GMCON_MISC__RENG_SRBM_CREDITS_MCD_MASK 0x0000f000L
+#define GMCON_MISC__RENG_SRBM_CREDITS_MCD__SHIFT 0x0000000c
+#define GMCON_MISC__STCTRL_DISABLE_ALLOW_SR_MASK 0x02000000L
+#define GMCON_MISC__STCTRL_DISABLE_ALLOW_SR__SHIFT 0x00000019
+#define GMCON_MISC__STCTRL_DISABLE_GMC_OFFLINE_MASK 0x04000000L
+#define GMCON_MISC__STCTRL_DISABLE_GMC_OFFLINE__SHIFT 0x0000001a
+#define GMCON_MISC__STCTRL_FORCE_ALLOW_SR_MASK 0x40000000L
+#define GMCON_MISC__STCTRL_FORCE_ALLOW_SR__SHIFT 0x0000001e
+#define GMCON_MISC__STCTRL_GMC_IDLE_THRESHOLD_MASK 0x00060000L
+#define GMCON_MISC__STCTRL_GMC_IDLE_THRESHOLD__SHIFT 0x00000011
+#define GMCON_MISC__STCTRL_IGNORE_ALLOW_STOP_MASK 0x00400000L
+#define GMCON_MISC__STCTRL_IGNORE_ALLOW_STOP__SHIFT 0x00000016
+#define GMCON_MISC__STCTRL_IGNORE_PRE_SR_MASK 0x00200000L
+#define GMCON_MISC__STCTRL_IGNORE_PRE_SR__SHIFT 0x00000015
+#define GMCON_MISC__STCTRL_IGNORE_PROTECTION_FAULT_MASK 0x01000000L
+#define GMCON_MISC__STCTRL_IGNORE_PROTECTION_FAULT__SHIFT 0x00000018
+#define GMCON_MISC__STCTRL_IGNORE_SR_COMMIT_MASK 0x00800000L
+#define GMCON_MISC__STCTRL_IGNORE_SR_COMMIT__SHIFT 0x00000017
+#define GMCON_MISC__STCTRL_SRBM_IDLE_THRESHOLD_MASK 0x00180000L
+#define GMCON_MISC__STCTRL_SRBM_IDLE_THRESHOLD__SHIFT 0x00000013
+#define GMCON_MISC__STCTRL_STUTTER_EN_MASK 0x00010000L
+#define GMCON_MISC__STCTRL_STUTTER_EN__SHIFT 0x00000010
+#define GMCON_PERF_MON_CNTL0__ALLOW_WRAP_MASK 0x10000000L
+#define GMCON_PERF_MON_CNTL0__ALLOW_WRAP__SHIFT 0x0000001c
+#define GMCON_PERF_MON_CNTL0__START_MODE_MASK 0x03000000L
+#define GMCON_PERF_MON_CNTL0__START_MODE__SHIFT 0x00000018
+#define GMCON_PERF_MON_CNTL0__START_THRESH_MASK 0x00000fffL
+#define GMCON_PERF_MON_CNTL0__START_THRESH__SHIFT 0x00000000
+#define GMCON_PERF_MON_CNTL0__STOP_MODE_MASK 0x0c000000L
+#define GMCON_PERF_MON_CNTL0__STOP_MODE__SHIFT 0x0000001a
+#define GMCON_PERF_MON_CNTL0__STOP_THRESH_MASK 0x00fff000L
+#define GMCON_PERF_MON_CNTL0__STOP_THRESH__SHIFT 0x0000000c
+#define GMCON_PERF_MON_CNTL1__MON0_ID_MASK 0x00fc0000L
+#define GMCON_PERF_MON_CNTL1__MON0_ID__SHIFT 0x00000012
+#define GMCON_PERF_MON_CNTL1__MON1_ID_MASK 0x3f000000L
+#define GMCON_PERF_MON_CNTL1__MON1_ID__SHIFT 0x00000018
+#define GMCON_PERF_MON_CNTL1__START_TRIG_ID_MASK 0x00000fc0L
+#define GMCON_PERF_MON_CNTL1__START_TRIG_ID__SHIFT 0x00000006
+#define GMCON_PERF_MON_CNTL1__STOP_TRIG_ID_MASK 0x0003f000L
+#define GMCON_PERF_MON_CNTL1__STOP_TRIG_ID__SHIFT 0x0000000c
+#define GMCON_PERF_MON_CNTL1__THRESH_CNTR_ID_MASK 0x0000003fL
+#define GMCON_PERF_MON_CNTL1__THRESH_CNTR_ID__SHIFT 0x00000000
+#define GMCON_PERF_MON_RSLT0__COUNT_MASK 0xffffffffL
+#define GMCON_PERF_MON_RSLT0__COUNT__SHIFT 0x00000000
+#define GMCON_PERF_MON_RSLT1__COUNT_MASK 0xffffffffL
+#define GMCON_PERF_MON_RSLT1__COUNT__SHIFT 0x00000000
+#define GMCON_PGFSM_CONFIG__FSM_ADDR_MASK 0x000000ffL
+#define GMCON_PGFSM_CONFIG__FSM_ADDR__SHIFT 0x00000000
+#define GMCON_PGFSM_CONFIG__P1_SELECT_MASK 0x00000400L
+#define GMCON_PGFSM_CONFIG__P1_SELECT__SHIFT 0x0000000a
+#define GMCON_PGFSM_CONFIG__P2_SELECT_MASK 0x00000800L
+#define GMCON_PGFSM_CONFIG__P2_SELECT__SHIFT 0x0000000b
+#define GMCON_PGFSM_CONFIG__POWER_DOWN_MASK 0x00000100L
+#define GMCON_PGFSM_CONFIG__POWER_DOWN__SHIFT 0x00000008
+#define GMCON_PGFSM_CONFIG__POWER_UP_MASK 0x00000200L
+#define GMCON_PGFSM_CONFIG__POWER_UP__SHIFT 0x00000009
+#define GMCON_PGFSM_CONFIG__READ_MASK 0x00002000L
+#define GMCON_PGFSM_CONFIG__READ__SHIFT 0x0000000d
+#define GMCON_PGFSM_CONFIG__REG_ADDR_MASK 0xf0000000L
+#define GMCON_PGFSM_CONFIG__REG_ADDR__SHIFT 0x0000001c
+#define GMCON_PGFSM_CONFIG__RSRVD_MASK 0x07ffc000L
+#define GMCON_PGFSM_CONFIG__RSRVD__SHIFT 0x0000000e
+#define GMCON_PGFSM_CONFIG__SRBM_OVERRIDE_MASK 0x08000000L
+#define GMCON_PGFSM_CONFIG__SRBM_OVERRIDE__SHIFT 0x0000001b
+#define GMCON_PGFSM_CONFIG__WRITE_MASK 0x00001000L
+#define GMCON_PGFSM_CONFIG__WRITE__SHIFT 0x0000000c
+#define GMCON_PGFSM_READ__PGFSM_SELECT_MASK 0x0f000000L
+#define GMCON_PGFSM_READ__PGFSM_SELECT__SHIFT 0x00000018
+#define GMCON_PGFSM_READ__READ_VALUE_MASK 0x00ffffffL
+#define GMCON_PGFSM_READ__READ_VALUE__SHIFT 0x00000000
+#define GMCON_PGFSM_READ__SERDES_MASTER_BUSY_MASK 0x10000000L
+#define GMCON_PGFSM_READ__SERDES_MASTER_BUSY__SHIFT 0x0000001c
+#define GMCON_PGFSM_WRITE__WRITE_VALUE_MASK 0xffffffffL
+#define GMCON_PGFSM_WRITE__WRITE_VALUE__SHIFT 0x00000000
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_DSP_END_PTR_MASK 0x003ff000L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_DSP_END_PTR__SHIFT 0x0000000c
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_END_PTR_MASK 0xffc00000L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_END_PTR__SHIFT 0x00000016
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW_MASK 0x00000002L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW__SHIFT 0x00000001
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW_START_PTR_MASK 0x00000ffcL
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_NOW_START_PTR__SHIFT 0x00000002
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_ON_PWR_UP_MASK 0x00000001L
+#define GMCON_RENG_EXECUTE__RENG_EXECUTE_ON_PWR_UP__SHIFT 0x00000000
+#define GMCON_RENG_RAM_DATA__RENG_RAM_DATA_MASK 0xffffffffL
+#define GMCON_RENG_RAM_DATA__RENG_RAM_DATA__SHIFT 0x00000000
+#define GMCON_RENG_RAM_INDEX__RENG_RAM_INDEX_MASK 0x000003ffL
+#define GMCON_RENG_RAM_INDEX__RENG_RAM_INDEX__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL0_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL0__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL1_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET0__STCTRL_REGISTER_SAVE_EXCL1__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL2_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL2__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL3_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_EXCL_SET1__STCTRL_REGISTER_SAVE_EXCL3__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_BASE0_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_BASE0__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_LIMIT0_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE0__STCTRL_REGISTER_SAVE_LIMIT0__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_BASE1_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_BASE1__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_LIMIT1_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE1__STCTRL_REGISTER_SAVE_LIMIT1__SHIFT 0x00000010
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_BASE2_MASK 0x0000ffffL
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_BASE2__SHIFT 0x00000000
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_LIMIT2_MASK 0xffff0000L
+#define GMCON_STCTRL_REGISTER_SAVE_RANGE2__STCTRL_REGISTER_SAVE_LIMIT2__SHIFT 0x00000010
+#define MC_ARB_ADDR_HASH__BANK_XOR_ENABLE_MASK 0x0000000fL
+#define MC_ARB_ADDR_HASH__BANK_XOR_ENABLE__SHIFT 0x00000000
+#define MC_ARB_ADDR_HASH__COL_XOR_MASK 0x00000ff0L
+#define MC_ARB_ADDR_HASH__COL_XOR__SHIFT 0x00000004
+#define MC_ARB_ADDR_HASH__ROW_XOR_MASK 0x0ffff000L
+#define MC_ARB_ADDR_HASH__ROW_XOR__SHIFT 0x0000000c
+#define MC_ARB_AGE_RD__DIVIDE_GROUP0_MASK 0x01000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP0__SHIFT 0x00000018
+#define MC_ARB_AGE_RD__DIVIDE_GROUP1_MASK 0x02000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP1__SHIFT 0x00000019
+#define MC_ARB_AGE_RD__DIVIDE_GROUP2_MASK 0x04000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP2__SHIFT 0x0000001a
+#define MC_ARB_AGE_RD__DIVIDE_GROUP3_MASK 0x08000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP3__SHIFT 0x0000001b
+#define MC_ARB_AGE_RD__DIVIDE_GROUP4_MASK 0x10000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP4__SHIFT 0x0000001c
+#define MC_ARB_AGE_RD__DIVIDE_GROUP5_MASK 0x20000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP5__SHIFT 0x0000001d
+#define MC_ARB_AGE_RD__DIVIDE_GROUP6_MASK 0x40000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP6__SHIFT 0x0000001e
+#define MC_ARB_AGE_RD__DIVIDE_GROUP7_MASK 0x80000000L
+#define MC_ARB_AGE_RD__DIVIDE_GROUP7__SHIFT 0x0000001f
+#define MC_ARB_AGE_RD__ENABLE_GROUP0_MASK 0x00010000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP0__SHIFT 0x00000010
+#define MC_ARB_AGE_RD__ENABLE_GROUP1_MASK 0x00020000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP1__SHIFT 0x00000011
+#define MC_ARB_AGE_RD__ENABLE_GROUP2_MASK 0x00040000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP2__SHIFT 0x00000012
+#define MC_ARB_AGE_RD__ENABLE_GROUP3_MASK 0x00080000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP3__SHIFT 0x00000013
+#define MC_ARB_AGE_RD__ENABLE_GROUP4_MASK 0x00100000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP4__SHIFT 0x00000014
+#define MC_ARB_AGE_RD__ENABLE_GROUP5_MASK 0x00200000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP5__SHIFT 0x00000015
+#define MC_ARB_AGE_RD__ENABLE_GROUP6_MASK 0x00400000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP6__SHIFT 0x00000016
+#define MC_ARB_AGE_RD__ENABLE_GROUP7_MASK 0x00800000L
+#define MC_ARB_AGE_RD__ENABLE_GROUP7__SHIFT 0x00000017
+#define MC_ARB_AGE_RD__RATE_GROUP0_MASK 0x00000003L
+#define MC_ARB_AGE_RD__RATE_GROUP0__SHIFT 0x00000000
+#define MC_ARB_AGE_RD__RATE_GROUP1_MASK 0x0000000cL
+#define MC_ARB_AGE_RD__RATE_GROUP1__SHIFT 0x00000002
+#define MC_ARB_AGE_RD__RATE_GROUP2_MASK 0x00000030L
+#define MC_ARB_AGE_RD__RATE_GROUP2__SHIFT 0x00000004
+#define MC_ARB_AGE_RD__RATE_GROUP3_MASK 0x000000c0L
+#define MC_ARB_AGE_RD__RATE_GROUP3__SHIFT 0x00000006
+#define MC_ARB_AGE_RD__RATE_GROUP4_MASK 0x00000300L
+#define MC_ARB_AGE_RD__RATE_GROUP4__SHIFT 0x00000008
+#define MC_ARB_AGE_RD__RATE_GROUP5_MASK 0x00000c00L
+#define MC_ARB_AGE_RD__RATE_GROUP5__SHIFT 0x0000000a
+#define MC_ARB_AGE_RD__RATE_GROUP6_MASK 0x00003000L
+#define MC_ARB_AGE_RD__RATE_GROUP6__SHIFT 0x0000000c
+#define MC_ARB_AGE_RD__RATE_GROUP7_MASK 0x0000c000L
+#define MC_ARB_AGE_RD__RATE_GROUP7__SHIFT 0x0000000e
+#define MC_ARB_AGE_WR__DIVIDE_GROUP0_MASK 0x01000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP0__SHIFT 0x00000018
+#define MC_ARB_AGE_WR__DIVIDE_GROUP1_MASK 0x02000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP1__SHIFT 0x00000019
+#define MC_ARB_AGE_WR__DIVIDE_GROUP2_MASK 0x04000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP2__SHIFT 0x0000001a
+#define MC_ARB_AGE_WR__DIVIDE_GROUP3_MASK 0x08000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP3__SHIFT 0x0000001b
+#define MC_ARB_AGE_WR__DIVIDE_GROUP4_MASK 0x10000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP4__SHIFT 0x0000001c
+#define MC_ARB_AGE_WR__DIVIDE_GROUP5_MASK 0x20000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP5__SHIFT 0x0000001d
+#define MC_ARB_AGE_WR__DIVIDE_GROUP6_MASK 0x40000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP6__SHIFT 0x0000001e
+#define MC_ARB_AGE_WR__DIVIDE_GROUP7_MASK 0x80000000L
+#define MC_ARB_AGE_WR__DIVIDE_GROUP7__SHIFT 0x0000001f
+#define MC_ARB_AGE_WR__ENABLE_GROUP0_MASK 0x00010000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP0__SHIFT 0x00000010
+#define MC_ARB_AGE_WR__ENABLE_GROUP1_MASK 0x00020000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP1__SHIFT 0x00000011
+#define MC_ARB_AGE_WR__ENABLE_GROUP2_MASK 0x00040000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP2__SHIFT 0x00000012
+#define MC_ARB_AGE_WR__ENABLE_GROUP3_MASK 0x00080000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP3__SHIFT 0x00000013
+#define MC_ARB_AGE_WR__ENABLE_GROUP4_MASK 0x00100000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP4__SHIFT 0x00000014
+#define MC_ARB_AGE_WR__ENABLE_GROUP5_MASK 0x00200000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP5__SHIFT 0x00000015
+#define MC_ARB_AGE_WR__ENABLE_GROUP6_MASK 0x00400000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP6__SHIFT 0x00000016
+#define MC_ARB_AGE_WR__ENABLE_GROUP7_MASK 0x00800000L
+#define MC_ARB_AGE_WR__ENABLE_GROUP7__SHIFT 0x00000017
+#define MC_ARB_AGE_WR__RATE_GROUP0_MASK 0x00000003L
+#define MC_ARB_AGE_WR__RATE_GROUP0__SHIFT 0x00000000
+#define MC_ARB_AGE_WR__RATE_GROUP1_MASK 0x0000000cL
+#define MC_ARB_AGE_WR__RATE_GROUP1__SHIFT 0x00000002
+#define MC_ARB_AGE_WR__RATE_GROUP2_MASK 0x00000030L
+#define MC_ARB_AGE_WR__RATE_GROUP2__SHIFT 0x00000004
+#define MC_ARB_AGE_WR__RATE_GROUP3_MASK 0x000000c0L
+#define MC_ARB_AGE_WR__RATE_GROUP3__SHIFT 0x00000006
+#define MC_ARB_AGE_WR__RATE_GROUP4_MASK 0x00000300L
+#define MC_ARB_AGE_WR__RATE_GROUP4__SHIFT 0x00000008
+#define MC_ARB_AGE_WR__RATE_GROUP5_MASK 0x00000c00L
+#define MC_ARB_AGE_WR__RATE_GROUP5__SHIFT 0x0000000a
+#define MC_ARB_AGE_WR__RATE_GROUP6_MASK 0x00003000L
+#define MC_ARB_AGE_WR__RATE_GROUP6__SHIFT 0x0000000c
+#define MC_ARB_AGE_WR__RATE_GROUP7_MASK 0x0000c000L
+#define MC_ARB_AGE_WR__RATE_GROUP7__SHIFT 0x0000000e
+#define MC_ARB_BANKMAP__BANK0_MASK 0x0000000fL
+#define MC_ARB_BANKMAP__BANK0__SHIFT 0x00000000
+#define MC_ARB_BANKMAP__BANK1_MASK 0x000000f0L
+#define MC_ARB_BANKMAP__BANK1__SHIFT 0x00000004
+#define MC_ARB_BANKMAP__BANK2_MASK 0x00000f00L
+#define MC_ARB_BANKMAP__BANK2__SHIFT 0x00000008
+#define MC_ARB_BANKMAP__BANK3_MASK 0x0000f000L
+#define MC_ARB_BANKMAP__BANK3__SHIFT 0x0000000c
+#define MC_ARB_BANKMAP__RANK_MASK 0x000f0000L
+#define MC_ARB_BANKMAP__RANK__SHIFT 0x00000010
+#define MC_ARB_BURST_TIME__STATE0_MASK 0x0000001fL
+#define MC_ARB_BURST_TIME__STATE0__SHIFT 0x00000000
+#define MC_ARB_BURST_TIME__STATE1_MASK 0x000003e0L
+#define MC_ARB_BURST_TIME__STATE1__SHIFT 0x00000005
+#define MC_ARB_BURST_TIME__STATE2_MASK 0x00007c00L
+#define MC_ARB_BURST_TIME__STATE2__SHIFT 0x0000000a
+#define MC_ARB_BURST_TIME__STATE3_MASK 0x000f8000L
+#define MC_ARB_BURST_TIME__STATE3__SHIFT 0x0000000f
+#define MC_ARB_CAC_CNTL__ALLOW_OVERFLOW_MASK 0x00002000L
+#define MC_ARB_CAC_CNTL__ALLOW_OVERFLOW__SHIFT 0x0000000d
+#define MC_ARB_CAC_CNTL__ENABLE_MASK 0x00000001L
+#define MC_ARB_CAC_CNTL__ENABLE__SHIFT 0x00000000
+#define MC_ARB_CAC_CNTL__READ_WEIGHT_MASK 0x0000007eL
+#define MC_ARB_CAC_CNTL__READ_WEIGHT__SHIFT 0x00000001
+#define MC_ARB_CAC_CNTL__WRITE_WEIGHT_MASK 0x00001f80L
+#define MC_ARB_CAC_CNTL__WRITE_WEIGHT__SHIFT 0x00000007
+#define MC_ARB_CG__CG_ARB_REQ_MASK 0x000000ffL
+#define MC_ARB_CG__CG_ARB_REQ__SHIFT 0x00000000
+#define MC_ARB_CG__CG_ARB_RESP_MASK 0x0000ff00L
+#define MC_ARB_CG__CG_ARB_RESP__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING_1__ACTRD_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING_1__ACTRD__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING_1__ACTWR_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING_1__ACTWR__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING_1__RASMACTRD_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING_1__RASMACTRD__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING_1__RASMACTWR_MASK 0xff000000L
+#define MC_ARB_DRAM_TIMING_1__RASMACTWR__SHIFT 0x00000018
+#define MC_ARB_DRAM_TIMING2_1__BUS_TURN_MASK 0x1f000000L
+#define MC_ARB_DRAM_TIMING2_1__BUS_TURN__SHIFT 0x00000018
+#define MC_ARB_DRAM_TIMING2_1__RAS2RAS_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING2_1__RAS2RAS__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING2_1__RP_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING2_1__RP__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING2_1__WRPLUSRP_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING2_1__WRPLUSRP__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING2__BUS_TURN_MASK 0x1f000000L
+#define MC_ARB_DRAM_TIMING2__BUS_TURN__SHIFT 0x00000018
+#define MC_ARB_DRAM_TIMING2__RAS2RAS_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING2__RAS2RAS__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING2__RP_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING2__RP__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING2__WRPLUSRP_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING2__WRPLUSRP__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING__ACTRD_MASK 0x000000ffL
+#define MC_ARB_DRAM_TIMING__ACTRD__SHIFT 0x00000000
+#define MC_ARB_DRAM_TIMING__ACTWR_MASK 0x0000ff00L
+#define MC_ARB_DRAM_TIMING__ACTWR__SHIFT 0x00000008
+#define MC_ARB_DRAM_TIMING__RASMACTRD_MASK 0x00ff0000L
+#define MC_ARB_DRAM_TIMING__RASMACTRD__SHIFT 0x00000010
+#define MC_ARB_DRAM_TIMING__RASMACTWR_MASK 0xff000000L
+#define MC_ARB_DRAM_TIMING__RASMACTWR__SHIFT 0x00000018
+#define MC_ARB_FED_CNTL__KEEP_POISON_IN_PAGE_MASK 0x00000010L
+#define MC_ARB_FED_CNTL__KEEP_POISON_IN_PAGE__SHIFT 0x00000004
+#define MC_ARB_FED_CNTL__MODE_MASK 0x00000003L
+#define MC_ARB_FED_CNTL__MODE__SHIFT 0x00000000
+#define MC_ARB_FED_CNTL__WR_ERR_MASK 0x0000000cL
+#define MC_ARB_FED_CNTL__WR_ERR__SHIFT 0x00000002
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT0_MASK 0x0000000fL
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT0__SHIFT 0x00000000
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT1_MASK 0x000000f0L
+#define MC_ARB_GDEC_RD_CNTL__PAGEBIT1__SHIFT 0x00000004
+#define MC_ARB_GDEC_RD_CNTL__REM_DEFAULT_GRP_MASK 0x00003c00L
+#define MC_ARB_GDEC_RD_CNTL__REM_DEFAULT_GRP__SHIFT 0x0000000a
+#define MC_ARB_GDEC_RD_CNTL__USE_RANK_MASK 0x00000100L
+#define MC_ARB_GDEC_RD_CNTL__USE_RANK__SHIFT 0x00000008
+#define MC_ARB_GDEC_RD_CNTL__USE_RSNO_MASK 0x00000200L
+#define MC_ARB_GDEC_RD_CNTL__USE_RSNO__SHIFT 0x00000009
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT0_MASK 0x0000000fL
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT0__SHIFT 0x00000000
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT1_MASK 0x000000f0L
+#define MC_ARB_GDEC_WR_CNTL__PAGEBIT1__SHIFT 0x00000004
+#define MC_ARB_GDEC_WR_CNTL__REM_DEFAULT_GRP_MASK 0x00003c00L
+#define MC_ARB_GDEC_WR_CNTL__REM_DEFAULT_GRP__SHIFT 0x0000000a
+#define MC_ARB_GDEC_WR_CNTL__USE_RANK_MASK 0x00000100L
+#define MC_ARB_GDEC_WR_CNTL__USE_RANK__SHIFT 0x00000008
+#define MC_ARB_GDEC_WR_CNTL__USE_RSNO_MASK 0x00000200L
+#define MC_ARB_GDEC_WR_CNTL__USE_RSNO__SHIFT 0x00000009
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI0_MASK 0x000000ffL
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI0__SHIFT 0x00000000
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI1_MASK 0x0000ff00L
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI1__SHIFT 0x00000008
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI2_MASK 0x00ff0000L
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI2__SHIFT 0x00000010
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI3_MASK 0xff000000L
+#define MC_ARB_GECC2_CLI__NO_GECC_CLI3__SHIFT 0x00000018
+#define MC_ARB_GECC2__CLOSE_BANK_RMW_MASK 0x00004000L
+#define MC_ARB_GECC2__CLOSE_BANK_RMW__SHIFT 0x0000000e
+#define MC_ARB_GECC2__COLFIFO_WATER_MASK 0x001f8000L
+#define MC_ARB_GECC2__COLFIFO_WATER__SHIFT 0x0000000f
+#define MC_ARB_GECC2_DEBUG2__ERR0_START_MASK 0x0000ff00L
+#define MC_ARB_GECC2_DEBUG2__ERR0_START__SHIFT 0x00000008
+#define MC_ARB_GECC2_DEBUG2__ERR1_START_MASK 0x00ff0000L
+#define MC_ARB_GECC2_DEBUG2__ERR1_START__SHIFT 0x00000010
+#define MC_ARB_GECC2_DEBUG2__ERR2_START_MASK 0xff000000L
+#define MC_ARB_GECC2_DEBUG2__ERR2_START__SHIFT 0x00000018
+#define MC_ARB_GECC2_DEBUG2__PERIOD_MASK 0x000000ffL
+#define MC_ARB_GECC2_DEBUG2__PERIOD__SHIFT 0x00000000
+#define MC_ARB_GECC2_DEBUG__DATA_FIELD_MASK 0x00000018L
+#define MC_ARB_GECC2_DEBUG__DATA_FIELD__SHIFT 0x00000003
+#define MC_ARB_GECC2_DEBUG__DIRECTION_MASK 0x00000004L
+#define MC_ARB_GECC2_DEBUG__DIRECTION__SHIFT 0x00000002
+#define MC_ARB_GECC2_DEBUG__NUM_ERR_BITS_MASK 0x00000003L
+#define MC_ARB_GECC2_DEBUG__NUM_ERR_BITS__SHIFT 0x00000000
+#define MC_ARB_GECC2_DEBUG__SW_INJECTION_MASK 0x00000020L
+#define MC_ARB_GECC2_DEBUG__SW_INJECTION__SHIFT 0x00000005
+#define MC_ARB_GECC2__ECC_MODE_MASK 0x00000006L
+#define MC_ARB_GECC2__ECC_MODE__SHIFT 0x00000001
+#define MC_ARB_GECC2__ENABLE_MASK 0x00000001L
+#define MC_ARB_GECC2__ENABLE__SHIFT 0x00000000
+#define MC_ARB_GECC2__EXOR_BANK_SEL_MASK 0x00000060L
+#define MC_ARB_GECC2__EXOR_BANK_SEL__SHIFT 0x00000005
+#define MC_ARB_GECC2_MISC__STREAK_BREAK_MASK 0x0000000fL
+#define MC_ARB_GECC2_MISC__STREAK_BREAK__SHIFT 0x00000000
+#define MC_ARB_GECC2__NO_GECC_CLI_MASK 0x00000780L
+#define MC_ARB_GECC2__NO_GECC_CLI__SHIFT 0x00000007
+#define MC_ARB_GECC2__PAGE_BIT0_MASK 0x00000018L
+#define MC_ARB_GECC2__PAGE_BIT0__SHIFT 0x00000003
+#define MC_ARB_GECC2__READ_ERR_MASK 0x00003800L
+#define MC_ARB_GECC2__READ_ERR__SHIFT 0x0000000b
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR0_MASK 0x00000100L
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR0__SHIFT 0x00000008
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR1_MASK 0x00001000L
+#define MC_ARB_GECC2_STATUS__CORR_CLEAR1__SHIFT 0x0000000c
+#define MC_ARB_GECC2_STATUS__CORR_STS0_MASK 0x00000001L
+#define MC_ARB_GECC2_STATUS__CORR_STS0__SHIFT 0x00000000
+#define MC_ARB_GECC2_STATUS__CORR_STS1_MASK 0x00000010L
+#define MC_ARB_GECC2_STATUS__CORR_STS1__SHIFT 0x00000004
+#define MC_ARB_GECC2_STATUS__FED_CLEAR0_MASK 0x00000400L
+#define MC_ARB_GECC2_STATUS__FED_CLEAR0__SHIFT 0x0000000a
+#define MC_ARB_GECC2_STATUS__FED_CLEAR1_MASK 0x00004000L
+#define MC_ARB_GECC2_STATUS__FED_CLEAR1__SHIFT 0x0000000e
+#define MC_ARB_GECC2_STATUS__FED_STS0_MASK 0x00000004L
+#define MC_ARB_GECC2_STATUS__FED_STS0__SHIFT 0x00000002
+#define MC_ARB_GECC2_STATUS__FED_STS1_MASK 0x00000040L
+#define MC_ARB_GECC2_STATUS__FED_STS1__SHIFT 0x00000006
+#define MC_ARB_GECC2_STATUS__RSVD0_MASK 0x00000008L
+#define MC_ARB_GECC2_STATUS__RSVD0__SHIFT 0x00000003
+#define MC_ARB_GECC2_STATUS__RSVD1_MASK 0x00000080L
+#define MC_ARB_GECC2_STATUS__RSVD1__SHIFT 0x00000007
+#define MC_ARB_GECC2_STATUS__RSVD2_MASK 0x00000800L
+#define MC_ARB_GECC2_STATUS__RSVD2__SHIFT 0x0000000b
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR0_MASK 0x00000200L
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR0__SHIFT 0x00000009
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR1_MASK 0x00002000L
+#define MC_ARB_GECC2_STATUS__UNCORR_CLEAR1__SHIFT 0x0000000d
+#define MC_ARB_GECC2_STATUS__UNCORR_STS0_MASK 0x00000002L
+#define MC_ARB_GECC2_STATUS__UNCORR_STS0__SHIFT 0x00000001
+#define MC_ARB_GECC2_STATUS__UNCORR_STS1_MASK 0x00000020L
+#define MC_ARB_GECC2_STATUS__UNCORR_STS1__SHIFT 0x00000005
+#define MC_ARB_LAZY0_RD__GROUP0_MASK 0x000000ffL
+#define MC_ARB_LAZY0_RD__GROUP0__SHIFT 0x00000000
+#define MC_ARB_LAZY0_RD__GROUP1_MASK 0x0000ff00L
+#define MC_ARB_LAZY0_RD__GROUP1__SHIFT 0x00000008
+#define MC_ARB_LAZY0_RD__GROUP2_MASK 0x00ff0000L
+#define MC_ARB_LAZY0_RD__GROUP2__SHIFT 0x00000010
+#define MC_ARB_LAZY0_RD__GROUP3_MASK 0xff000000L
+#define MC_ARB_LAZY0_RD__GROUP3__SHIFT 0x00000018
+#define MC_ARB_LAZY0_WR__GROUP0_MASK 0x000000ffL
+#define MC_ARB_LAZY0_WR__GROUP0__SHIFT 0x00000000
+#define MC_ARB_LAZY0_WR__GROUP1_MASK 0x0000ff00L
+#define MC_ARB_LAZY0_WR__GROUP1__SHIFT 0x00000008
+#define MC_ARB_LAZY0_WR__GROUP2_MASK 0x00ff0000L
+#define MC_ARB_LAZY0_WR__GROUP2__SHIFT 0x00000010
+#define MC_ARB_LAZY0_WR__GROUP3_MASK 0xff000000L
+#define MC_ARB_LAZY0_WR__GROUP3__SHIFT 0x00000018
+#define MC_ARB_LAZY1_RD__GROUP4_MASK 0x000000ffL
+#define MC_ARB_LAZY1_RD__GROUP4__SHIFT 0x00000000
+#define MC_ARB_LAZY1_RD__GROUP5_MASK 0x0000ff00L
+#define MC_ARB_LAZY1_RD__GROUP5__SHIFT 0x00000008
+#define MC_ARB_LAZY1_RD__GROUP6_MASK 0x00ff0000L
+#define MC_ARB_LAZY1_RD__GROUP6__SHIFT 0x00000010
+#define MC_ARB_LAZY1_RD__GROUP7_MASK 0xff000000L
+#define MC_ARB_LAZY1_RD__GROUP7__SHIFT 0x00000018
+#define MC_ARB_LAZY1_WR__GROUP4_MASK 0x000000ffL
+#define MC_ARB_LAZY1_WR__GROUP4__SHIFT 0x00000000
+#define MC_ARB_LAZY1_WR__GROUP5_MASK 0x0000ff00L
+#define MC_ARB_LAZY1_WR__GROUP5__SHIFT 0x00000008
+#define MC_ARB_LAZY1_WR__GROUP6_MASK 0x00ff0000L
+#define MC_ARB_LAZY1_WR__GROUP6__SHIFT 0x00000010
+#define MC_ARB_LAZY1_WR__GROUP7_MASK 0xff000000L
+#define MC_ARB_LAZY1_WR__GROUP7__SHIFT 0x00000018
+#define MC_ARB_LM_RD__BANKGROUP_CONFIG_MASK 0x00e00000L
+#define MC_ARB_LM_RD__BANKGROUP_CONFIG__SHIFT 0x00000015
+#define MC_ARB_LM_RD__ENABLE_TWO_LIST_MASK 0x00040000L
+#define MC_ARB_LM_RD__ENABLE_TWO_LIST__SHIFT 0x00000012
+#define MC_ARB_LM_RD__POPIDLE_RST_TWOLIST_MASK 0x00080000L
+#define MC_ARB_LM_RD__POPIDLE_RST_TWOLIST__SHIFT 0x00000013
+#define MC_ARB_LM_RD__SKID1_RST_TWOLIST_MASK 0x00100000L
+#define MC_ARB_LM_RD__SKID1_RST_TWOLIST__SHIFT 0x00000014
+#define MC_ARB_LM_RD__STREAK_BREAK_MASK 0x00010000L
+#define MC_ARB_LM_RD__STREAK_BREAK__SHIFT 0x00000010
+#define MC_ARB_LM_RD__STREAK_LIMIT_MASK 0x000000ffL
+#define MC_ARB_LM_RD__STREAK_LIMIT__SHIFT 0x00000000
+#define MC_ARB_LM_RD__STREAK_LIMIT_UBER_MASK 0x0000ff00L
+#define MC_ARB_LM_RD__STREAK_LIMIT_UBER__SHIFT 0x00000008
+#define MC_ARB_LM_RD__STREAK_UBER_MASK 0x00020000L
+#define MC_ARB_LM_RD__STREAK_UBER__SHIFT 0x00000011
+#define MC_ARB_LM_WR__BANKGROUP_CONFIG_MASK 0x00e00000L
+#define MC_ARB_LM_WR__BANKGROUP_CONFIG__SHIFT 0x00000015
+#define MC_ARB_LM_WR__ENABLE_TWO_LIST_MASK 0x00040000L
+#define MC_ARB_LM_WR__ENABLE_TWO_LIST__SHIFT 0x00000012
+#define MC_ARB_LM_WR__POPIDLE_RST_TWOLIST_MASK 0x00080000L
+#define MC_ARB_LM_WR__POPIDLE_RST_TWOLIST__SHIFT 0x00000013
+#define MC_ARB_LM_WR__SKID1_RST_TWOLIST_MASK 0x00100000L
+#define MC_ARB_LM_WR__SKID1_RST_TWOLIST__SHIFT 0x00000014
+#define MC_ARB_LM_WR__STREAK_BREAK_MASK 0x00010000L
+#define MC_ARB_LM_WR__STREAK_BREAK__SHIFT 0x00000010
+#define MC_ARB_LM_WR__STREAK_LIMIT_MASK 0x000000ffL
+#define MC_ARB_LM_WR__STREAK_LIMIT__SHIFT 0x00000000
+#define MC_ARB_LM_WR__STREAK_LIMIT_UBER_MASK 0x0000ff00L
+#define MC_ARB_LM_WR__STREAK_LIMIT_UBER__SHIFT 0x00000008
+#define MC_ARB_LM_WR__STREAK_UBER_MASK 0x00020000L
+#define MC_ARB_LM_WR__STREAK_UBER__SHIFT 0x00000011
+#define MC_ARB_MINCLKS__ARB_RW_SWITCH_MASK 0x00010000L
+#define MC_ARB_MINCLKS__ARB_RW_SWITCH__SHIFT 0x00000010
+#define MC_ARB_MINCLKS__READ_CLKS_MASK 0x000000ffL
+#define MC_ARB_MINCLKS__READ_CLKS__SHIFT 0x00000000
+#define MC_ARB_MINCLKS__WRITE_CLKS_MASK 0x0000ff00L
+#define MC_ARB_MINCLKS__WRITE_CLKS__SHIFT 0x00000008
+#define MC_ARB_MISC2__ARB_DEBUG29_MASK 0x20000000L
+#define MC_ARB_MISC2__ARB_DEBUG29__SHIFT 0x0000001d
+#define MC_ARB_MISC2__GECC_MASK 0x00040000L
+#define MC_ARB_MISC2__GECC_RST_MASK 0x00080000L
+#define MC_ARB_MISC2__GECC_RST__SHIFT 0x00000013
+#define MC_ARB_MISC2__GECC__SHIFT 0x00000012
+#define MC_ARB_MISC2__GECC_STATUS_MASK 0x00100000L
+#define MC_ARB_MISC2__GECC_STATUS__SHIFT 0x00000014
+#define MC_ARB_MISC2__POP_IDLE_REPLAY_MASK 0x00000800L
+#define MC_ARB_MISC2__POP_IDLE_REPLAY__SHIFT 0x0000000b
+#define MC_ARB_MISC2__RDRET_NO_BP_MASK 0x00002000L
+#define MC_ARB_MISC2__RDRET_NO_BP__SHIFT 0x0000000d
+#define MC_ARB_MISC2__RDRET_NO_REORDERING_MASK 0x00001000L
+#define MC_ARB_MISC2__RDRET_NO_REORDERING__SHIFT 0x0000000c
+#define MC_ARB_MISC2__RDRET_SEQ_SKID_MASK 0x0003c000L
+#define MC_ARB_MISC2__RDRET_SEQ_SKID__SHIFT 0x0000000e
+#define MC_ARB_MISC2__REPLAY_DEBUG_MASK 0x10000000L
+#define MC_ARB_MISC2__REPLAY_DEBUG__SHIFT 0x0000001c
+#define MC_ARB_MISC2__SEQ_RDY_POP_IDLE_MASK 0x40000000L
+#define MC_ARB_MISC2__SEQ_RDY_POP_IDLE__SHIFT 0x0000001e
+#define MC_ARB_MISC2__TAGFIFO_THRESHOLD_MASK 0x01e00000L
+#define MC_ARB_MISC2__TAGFIFO_THRESHOLD__SHIFT 0x00000015
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT4_MASK 0x00000040L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT4__SHIFT 0x00000006
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT5_MASK 0x00000080L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT5__SHIFT 0x00000007
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT6_MASK 0x00000100L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT6__SHIFT 0x00000008
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT7_MASK 0x00000200L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT7__SHIFT 0x00000009
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT8_MASK 0x00000400L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_COLBIT8__SHIFT 0x0000000a
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_ENABLE_MASK 0x00000020L
+#define MC_ARB_MISC2__TCCDL4_BANKBIT3_XOR_ENABLE__SHIFT 0x00000005
+#define MC_ARB_MISC2__TCCDL4_REPLAY_EOB_MASK 0x80000000L
+#define MC_ARB_MISC2__TCCDL4_REPLAY_EOB__SHIFT 0x0000001f
+#define MC_ARB_MISC2__WCDR_REPLAY_MASKCNT_MASK 0x0e000000L
+#define MC_ARB_MISC2__WCDR_REPLAY_MASKCNT__SHIFT 0x00000019
+#define MC_ARB_MISC__CALI_ENABLE_MASK 0x00100000L
+#define MC_ARB_MISC__CALI_ENABLE__SHIFT 0x00000014
+#define MC_ARB_MISC__CALI_RATES_MASK 0x00600000L
+#define MC_ARB_MISC__CALI_RATES__SHIFT 0x00000015
+#define MC_ARB_MISC__CHAN_COUPLE_MASK 0x000007f8L
+#define MC_ARB_MISC__CHAN_COUPLE__SHIFT 0x00000003
+#define MC_ARB_MISC__DISPURG_NOSW2WR_MASK 0x01000000L
+#define MC_ARB_MISC__DISPURG_NOSW2WR__SHIFT 0x00000018
+#define MC_ARB_MISC__DISPURG_STALL_MASK 0x02000000L
+#define MC_ARB_MISC__DISPURG_STALL__SHIFT 0x00000019
+#define MC_ARB_MISC__DISPURG_THROTTLE_MASK 0x3c000000L
+#define MC_ARB_MISC__DISPURG_THROTTLE__SHIFT 0x0000001a
+#define MC_ARB_MISC__DISPURGVLD_NOWRT_MASK 0x00800000L
+#define MC_ARB_MISC__DISPURGVLD_NOWRT__SHIFT 0x00000017
+#define MC_ARB_MISC__HARSHNESS_MASK 0x0007f800L
+#define MC_ARB_MISC__HARSHNESS__SHIFT 0x0000000b
+#define MC_ARB_MISC__IDLE_RFSH_MASK 0x00000002L
+#define MC_ARB_MISC__IDLE_RFSH__SHIFT 0x00000001
+#define MC_ARB_MISC__SMART_RDWR_SW_MASK 0x00080000L
+#define MC_ARB_MISC__SMART_RDWR_SW__SHIFT 0x00000013
+#define MC_ARB_MISC__STICKY_RFSH_MASK 0x00000001L
+#define MC_ARB_MISC__STICKY_RFSH__SHIFT 0x00000000
+#define MC_ARB_MISC__STUTTER_RFSH_MASK 0x00000004L
+#define MC_ARB_MISC__STUTTER_RFSH__SHIFT 0x00000002
+#define MC_ARB_PM_CNTL__BLKOUT_ON_D1_MASK 0x00000020L
+#define MC_ARB_PM_CNTL__BLKOUT_ON_D1__SHIFT 0x00000005
+#define MC_ARB_PM_CNTL__IDLE_CNT_MASK 0x00f00000L
+#define MC_ARB_PM_CNTL__IDLE_CNT__SHIFT 0x00000014
+#define MC_ARB_PM_CNTL__IDLE_ON_D1_MASK 0x00000040L
+#define MC_ARB_PM_CNTL__IDLE_ON_D1__SHIFT 0x00000006
+#define MC_ARB_PM_CNTL__IDLE_ON_D2_MASK 0x00040000L
+#define MC_ARB_PM_CNTL__IDLE_ON_D2__SHIFT 0x00000012
+#define MC_ARB_PM_CNTL__IDLE_ON_D3_MASK 0x00080000L
+#define MC_ARB_PM_CNTL__IDLE_ON_D3__SHIFT 0x00000013
+#define MC_ARB_PM_CNTL__OVERRIDE_CGSTATE_MASK 0x00000003L
+#define MC_ARB_PM_CNTL__OVERRIDE_CGSTATE__SHIFT 0x00000000
+#define MC_ARB_PM_CNTL__OVRR_CGRFSH_MASK 0x00000004L
+#define MC_ARB_PM_CNTL__OVRR_CGRFSH__SHIFT 0x00000002
+#define MC_ARB_PM_CNTL__OVRR_CGSQM_MASK 0x00000008L
+#define MC_ARB_PM_CNTL__OVRR_CGSQM__SHIFT 0x00000003
+#define MC_ARB_PM_CNTL__OVRR_PM_MASK 0x00000080L
+#define MC_ARB_PM_CNTL__OVRR_PM__SHIFT 0x00000007
+#define MC_ARB_PM_CNTL__OVRR_PM_STATE_MASK 0x00000300L
+#define MC_ARB_PM_CNTL__OVRR_PM_STATE__SHIFT 0x00000008
+#define MC_ARB_PM_CNTL__OVRR_RD_MASK 0x00000400L
+#define MC_ARB_PM_CNTL__OVRR_RD__SHIFT 0x0000000a
+#define MC_ARB_PM_CNTL__OVRR_RD_STATE_MASK 0x00000800L
+#define MC_ARB_PM_CNTL__OVRR_RD_STATE__SHIFT 0x0000000b
+#define MC_ARB_PM_CNTL__OVRR_RFSH_MASK 0x00004000L
+#define MC_ARB_PM_CNTL__OVRR_RFSH__SHIFT 0x0000000e
+#define MC_ARB_PM_CNTL__OVRR_RFSH_STATE_MASK 0x00008000L
+#define MC_ARB_PM_CNTL__OVRR_RFSH_STATE__SHIFT 0x0000000f
+#define MC_ARB_PM_CNTL__OVRR_WR_MASK 0x00001000L
+#define MC_ARB_PM_CNTL__OVRR_WR__SHIFT 0x0000000c
+#define MC_ARB_PM_CNTL__OVRR_WR_STATE_MASK 0x00002000L
+#define MC_ARB_PM_CNTL__OVRR_WR_STATE__SHIFT 0x0000000d
+#define MC_ARB_PM_CNTL__SRFSH_ON_D1_MASK 0x00000010L
+#define MC_ARB_PM_CNTL__SRFSH_ON_D1__SHIFT 0x00000004
+#define MC_ARB_POP__ALLOW_EOB_BY_WRRET_STALL_MASK 0x00080000L
+#define MC_ARB_POP__ALLOW_EOB_BY_WRRET_STALL__SHIFT 0x00000013
+#define MC_ARB_POP__ENABLE_ARB_MASK 0x00000001L
+#define MC_ARB_POP__ENABLE_ARB__SHIFT 0x00000000
+#define MC_ARB_POP__ENABLE_TWO_PAGE_MASK 0x00040000L
+#define MC_ARB_POP__ENABLE_TWO_PAGE__SHIFT 0x00000012
+#define MC_ARB_POP__POP_DEPTH_MASK 0x0000003cL
+#define MC_ARB_POP__POP_DEPTH__SHIFT 0x00000002
+#define MC_ARB_POP__QUICK_STOP_MASK 0x00020000L
+#define MC_ARB_POP__QUICK_STOP__SHIFT 0x00000011
+#define MC_ARB_POP__SKID_DEPTH_MASK 0x00007000L
+#define MC_ARB_POP__SKID_DEPTH__SHIFT 0x0000000c
+#define MC_ARB_POP__SPEC_OPEN_MASK 0x00000002L
+#define MC_ARB_POP__SPEC_OPEN__SHIFT 0x00000001
+#define MC_ARB_POP__WAIT_AFTER_RFSH_MASK 0x00018000L
+#define MC_ARB_POP__WAIT_AFTER_RFSH__SHIFT 0x0000000f
+#define MC_ARB_POP__WRDATAINDEX_DEPTH_MASK 0x00000fc0L
+#define MC_ARB_POP__WRDATAINDEX_DEPTH__SHIFT 0x00000006
+#define MC_ARB_RAMCFG__CHANSIZE_MASK 0x00000100L
+#define MC_ARB_RAMCFG__CHANSIZE__SHIFT 0x00000008
+#define MC_ARB_RAMCFG__NOOFBANK_MASK 0x00000003L
+#define MC_ARB_RAMCFG__NOOFBANK__SHIFT 0x00000000
+#define MC_ARB_RAMCFG__NOOFCOLS_MASK 0x000000c0L
+#define MC_ARB_RAMCFG__NOOFCOLS__SHIFT 0x00000006
+#define MC_ARB_RAMCFG__NOOFGROUPS_MASK 0x00001000L
+#define MC_ARB_RAMCFG__NOOFGROUPS__SHIFT 0x0000000c
+#define MC_ARB_RAMCFG__NOOFRANKS_MASK 0x00000004L
+#define MC_ARB_RAMCFG__NOOFRANKS__SHIFT 0x00000002
+#define MC_ARB_RAMCFG__NOOFROWS_MASK 0x00000038L
+#define MC_ARB_RAMCFG__NOOFROWS__SHIFT 0x00000003
+#define MC_ARB_REMREQ__RD_WATER_MASK 0x000000ffL
+#define MC_ARB_REMREQ__RD_WATER__SHIFT 0x00000000
+#define MC_ARB_REMREQ__WR_LAZY_TIMER_MASK 0x00f00000L
+#define MC_ARB_REMREQ__WR_LAZY_TIMER__SHIFT 0x00000014
+#define MC_ARB_REMREQ__WR_MAXBURST_SIZE_MASK 0x000f0000L
+#define MC_ARB_REMREQ__WR_MAXBURST_SIZE__SHIFT 0x00000010
+#define MC_ARB_REMREQ__WR_WATER_MASK 0x0000ff00L
+#define MC_ARB_REMREQ__WR_WATER__SHIFT 0x00000008
+#define MC_ARB_REPLAY__BOS_ENABLE_WAIT_CYC_MASK 0x00000080L
+#define MC_ARB_REPLAY__BOS_ENABLE_WAIT_CYC__SHIFT 0x00000007
+#define MC_ARB_REPLAY__BOS_WAIT_CYC_MASK 0x00007f00L
+#define MC_ARB_REPLAY__BOS_WAIT_CYC__SHIFT 0x00000008
+#define MC_ARB_REPLAY__BREAK_ON_STALL_MASK 0x00000040L
+#define MC_ARB_REPLAY__BREAK_ON_STALL__SHIFT 0x00000006
+#define MC_ARB_REPLAY__ENABLE_RD_MASK 0x00000001L
+#define MC_ARB_REPLAY__ENABLE_RD__SHIFT 0x00000000
+#define MC_ARB_REPLAY__ENABLE_WR_MASK 0x00000002L
+#define MC_ARB_REPLAY__ENABLE_WR__SHIFT 0x00000001
+#define MC_ARB_REPLAY__IGNORE_WR_CDC_MASK 0x00000020L
+#define MC_ARB_REPLAY__IGNORE_WR_CDC__SHIFT 0x00000005
+#define MC_ARB_REPLAY__RAW_ENABLE_MASK 0x00000010L
+#define MC_ARB_REPLAY__RAW_ENABLE__SHIFT 0x00000004
+#define MC_ARB_REPLAY__WAW_ENABLE_MASK 0x00000008L
+#define MC_ARB_REPLAY__WAW_ENABLE__SHIFT 0x00000003
+#define MC_ARB_REPLAY__WRACK_MODE_MASK 0x00000004L
+#define MC_ARB_REPLAY__WRACK_MODE__SHIFT 0x00000002
+#define MC_ARB_RET_CREDITS_RD__DISP_MASK 0x00ff0000L
+#define MC_ARB_RET_CREDITS_RD__DISP__SHIFT 0x00000010
+#define MC_ARB_RET_CREDITS_RD__HUB_MASK 0x0000ff00L
+#define MC_ARB_RET_CREDITS_RD__HUB__SHIFT 0x00000008
+#define MC_ARB_RET_CREDITS_RD__LCL_MASK 0x000000ffL
+#define MC_ARB_RET_CREDITS_RD__LCL__SHIFT 0x00000000
+#define MC_ARB_RET_CREDITS_RD__RETURN_CREDIT_MASK 0xff000000L
+#define MC_ARB_RET_CREDITS_RD__RETURN_CREDIT__SHIFT 0x00000018
+#define MC_ARB_RET_CREDITS_WR__HUB_MASK 0x0000ff00L
+#define MC_ARB_RET_CREDITS_WR__HUB__SHIFT 0x00000008
+#define MC_ARB_RET_CREDITS_WR__LCL_MASK 0x000000ffL
+#define MC_ARB_RET_CREDITS_WR__LCL__SHIFT 0x00000000
+#define MC_ARB_RET_CREDITS_WR__RETURN_CREDIT_MASK 0x00ff0000L
+#define MC_ARB_RET_CREDITS_WR__RETURN_CREDIT__SHIFT 0x00000010
+#define MC_ARB_RET_CREDITS_WR__WRRET_SEQ_SKID_MASK 0x0f000000L
+#define MC_ARB_RET_CREDITS_WR__WRRET_SEQ_SKID__SHIFT 0x00000018
+#define MC_ARB_RFSH_CNTL__ACCUM_MASK 0x00000800L
+#define MC_ARB_RFSH_CNTL__ACCUM__SHIFT 0x0000000b
+#define MC_ARB_RFSH_CNTL__ENABLE_MASK 0x00000001L
+#define MC_ARB_RFSH_CNTL__ENABLE__SHIFT 0x00000000
+#define MC_ARB_RFSH_CNTL__URG0_MASK 0x0000003eL
+#define MC_ARB_RFSH_CNTL__URG0__SHIFT 0x00000001
+#define MC_ARB_RFSH_CNTL__URG1_MASK 0x000007c0L
+#define MC_ARB_RFSH_CNTL__URG1__SHIFT 0x00000006
+#define MC_ARB_RFSH_RATE__POWERMODE0_MASK 0x000000ffL
+#define MC_ARB_RFSH_RATE__POWERMODE0__SHIFT 0x00000000
+#define MC_ARB_RTT_CNTL0__BREAK_ON_HARSH_MASK 0x00000100L
+#define MC_ARB_RTT_CNTL0__BREAK_ON_HARSH__SHIFT 0x00000008
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTRD_MASK 0x00000200L
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTRD__SHIFT 0x00000009
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTWR_MASK 0x00000400L
+#define MC_ARB_RTT_CNTL0__BREAK_ON_URGENTWR__SHIFT 0x0000000a
+#define MC_ARB_RTT_CNTL0__DATA_CNTL_MASK 0x01000000L
+#define MC_ARB_RTT_CNTL0__DATA_CNTL__SHIFT 0x00000018
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_0_MASK 0x00008000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_0__SHIFT 0x0000000f
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_1_MASK 0x00010000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_1__SHIFT 0x00000010
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_2_MASK 0x00020000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_2__SHIFT 0x00000011
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_3_MASK 0x00040000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_3__SHIFT 0x00000012
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_4_MASK 0x00080000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_4__SHIFT 0x00000013
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_5_MASK 0x00100000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_5__SHIFT 0x00000014
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_6_MASK 0x00200000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_6__SHIFT 0x00000015
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_7_MASK 0x00400000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_7__SHIFT 0x00000016
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_8_MASK 0x00800000L
+#define MC_ARB_RTT_CNTL0__DEBUG_RSV_8__SHIFT 0x00000017
+#define MC_ARB_RTT_CNTL0__ENABLE_MASK 0x00000001L
+#define MC_ARB_RTT_CNTL0__ENABLE__SHIFT 0x00000000
+#define MC_ARB_RTT_CNTL0__FLUSH_ON_ENTER_MASK 0x00000010L
+#define MC_ARB_RTT_CNTL0__FLUSH_ON_ENTER__SHIFT 0x00000004
+#define MC_ARB_RTT_CNTL0__HARSH_START_MASK 0x00000020L
+#define MC_ARB_RTT_CNTL0__HARSH_START__SHIFT 0x00000005
+#define MC_ARB_RTT_CNTL0__NEIGHBOR_BIT_MASK 0x02000000L
+#define MC_ARB_RTT_CNTL0__NEIGHBOR_BIT__SHIFT 0x00000019
+#define MC_ARB_RTT_CNTL0__START_IDLE_MASK 0x00000002L
+#define MC_ARB_RTT_CNTL0__START_IDLE__SHIFT 0x00000001
+#define MC_ARB_RTT_CNTL0__START_R2W_MASK 0x0000000cL
+#define MC_ARB_RTT_CNTL0__START_R2W_RFSH_MASK 0x00004000L
+#define MC_ARB_RTT_CNTL0__START_R2W_RFSH__SHIFT 0x0000000e
+#define MC_ARB_RTT_CNTL0__START_R2W__SHIFT 0x00000002
+#define MC_ARB_RTT_CNTL0__TPS_HARSH_PRIORITY_MASK 0x00000040L
+#define MC_ARB_RTT_CNTL0__TPS_HARSH_PRIORITY__SHIFT 0x00000006
+#define MC_ARB_RTT_CNTL0__TRAIN_PERIOD_MASK 0x00003800L
+#define MC_ARB_RTT_CNTL0__TRAIN_PERIOD__SHIFT 0x0000000b
+#define MC_ARB_RTT_CNTL0__TWRT_HARSH_PRIORITY_MASK 0x00000080L
+#define MC_ARB_RTT_CNTL0__TWRT_HARSH_PRIORITY__SHIFT 0x00000007
+#define MC_ARB_RTT_CNTL1__WINDOW_DEC_THRESHOLD_MASK 0x000fe000L
+#define MC_ARB_RTT_CNTL1__WINDOW_DEC_THRESHOLD__SHIFT 0x0000000d
+#define MC_ARB_RTT_CNTL1__WINDOW_INC_THRESHOLD_MASK 0x00001fc0L
+#define MC_ARB_RTT_CNTL1__WINDOW_INC_THRESHOLD__SHIFT 0x00000006
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MASK 0x0000001fL
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MAX_MASK 0x01f00000L
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MAX__SHIFT 0x00000014
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MIN_MASK 0x3e000000L
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE_MIN__SHIFT 0x00000019
+#define MC_ARB_RTT_CNTL1__WINDOW_SIZE__SHIFT 0x00000000
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE_COUNT_MASK 0xc0000000L
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE_COUNT__SHIFT 0x0000001e
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE_MASK 0x00000020L
+#define MC_ARB_RTT_CNTL1__WINDOW_UPDATE__SHIFT 0x00000005
+#define MC_ARB_RTT_CNTL2__FILTER_CNTL_MASK 0x00002000L
+#define MC_ARB_RTT_CNTL2__FILTER_CNTL__SHIFT 0x0000000d
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_SIZE_MASK 0x00001000L
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_SIZE__SHIFT 0x0000000c
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_THRESHOLD_MASK 0x00000fc0L
+#define MC_ARB_RTT_CNTL2__PHASE_ADJUST_THRESHOLD__SHIFT 0x00000006
+#define MC_ARB_RTT_CNTL2__SAMPLE_CNT_MASK 0x0000003fL
+#define MC_ARB_RTT_CNTL2__SAMPLE_CNT__SHIFT 0x00000000
+#define MC_ARB_RTT_DATA__PATTERN_MASK 0x000000ffL
+#define MC_ARB_RTT_DATA__PATTERN__SHIFT 0x00000000
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH0_MASK 0x00000003L
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH0__SHIFT 0x00000000
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH1_MASK 0x0000000cL
+#define MC_ARB_RTT_DEBUG__DEBUG_BYTE_CH1__SHIFT 0x00000002
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH0_MASK 0x00000ff0L
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH0__SHIFT 0x00000004
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH1_MASK 0x01fe0000L
+#define MC_ARB_RTT_DEBUG__SHIFTED_PHASE_CH1__SHIFT 0x00000011
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH0_MASK 0x0001f000L
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH0__SHIFT 0x0000000c
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH1_MASK 0x3e000000L
+#define MC_ARB_RTT_DEBUG__WINDOW_SIZE_CH1__SHIFT 0x00000019
+#define MC_ARB_SQM_CNTL__DYN_SQM_ENABLE_MASK 0x00000100L
+#define MC_ARB_SQM_CNTL__DYN_SQM_ENABLE__SHIFT 0x00000008
+#define MC_ARB_SQM_CNTL__MIN_PENAL_MASK 0x000000ffL
+#define MC_ARB_SQM_CNTL__MIN_PENAL__SHIFT 0x00000000
+#define MC_ARB_SQM_CNTL__RATIO_DEBUG_MASK 0xff000000L
+#define MC_ARB_SQM_CNTL__RATIO_DEBUG__SHIFT 0x00000018
+#define MC_ARB_SQM_CNTL__RATIO_MASK 0x00ff0000L
+#define MC_ARB_SQM_CNTL__RATIO__SHIFT 0x00000010
+#define MC_ARB_SQM_CNTL__SQM_RESERVE_MASK 0x0000fe00L
+#define MC_ARB_SQM_CNTL__SQM_RESERVE__SHIFT 0x00000009
+#define MC_ARB_TM_CNTL_RD__BANK_SELECT_MASK 0x00000006L
+#define MC_ARB_TM_CNTL_RD__BANK_SELECT__SHIFT 0x00000001
+#define MC_ARB_TM_CNTL_RD__GROUPBY_RANK_MASK 0x00000001L
+#define MC_ARB_TM_CNTL_RD__GROUPBY_RANK__SHIFT 0x00000000
+#define MC_ARB_TM_CNTL_RD__MATCH_BANK_MASK 0x00000010L
+#define MC_ARB_TM_CNTL_RD__MATCH_BANK__SHIFT 0x00000004
+#define MC_ARB_TM_CNTL_RD__MATCH_RANK_MASK 0x00000008L
+#define MC_ARB_TM_CNTL_RD__MATCH_RANK__SHIFT 0x00000003
+#define MC_ARB_TM_CNTL_WR__BANK_SELECT_MASK 0x00000006L
+#define MC_ARB_TM_CNTL_WR__BANK_SELECT__SHIFT 0x00000001
+#define MC_ARB_TM_CNTL_WR__GROUPBY_RANK_MASK 0x00000001L
+#define MC_ARB_TM_CNTL_WR__GROUPBY_RANK__SHIFT 0x00000000
+#define MC_ARB_TM_CNTL_WR__MATCH_BANK_MASK 0x00000010L
+#define MC_ARB_TM_CNTL_WR__MATCH_BANK__SHIFT 0x00000004
+#define MC_ARB_TM_CNTL_WR__MATCH_RANK_MASK 0x00000008L
+#define MC_ARB_TM_CNTL_WR__MATCH_RANK__SHIFT 0x00000003
+#define MC_ARB_WCDR_2__DEBUG_0_MASK 0x00000200L
+#define MC_ARB_WCDR_2__DEBUG_0__SHIFT 0x00000009
+#define MC_ARB_WCDR_2__DEBUG_1_MASK 0x00000400L
+#define MC_ARB_WCDR_2__DEBUG_1__SHIFT 0x0000000a
+#define MC_ARB_WCDR_2__DEBUG_2_MASK 0x00000800L
+#define MC_ARB_WCDR_2__DEBUG_2__SHIFT 0x0000000b
+#define MC_ARB_WCDR_2__DEBUG_3_MASK 0x00001000L
+#define MC_ARB_WCDR_2__DEBUG_3__SHIFT 0x0000000c
+#define MC_ARB_WCDR_2__DEBUG_4_MASK 0x00002000L
+#define MC_ARB_WCDR_2__DEBUG_4__SHIFT 0x0000000d
+#define MC_ARB_WCDR_2__DEBUG_5_MASK 0x00004000L
+#define MC_ARB_WCDR_2__DEBUG_5__SHIFT 0x0000000e
+#define MC_ARB_WCDR_2__WPRE_INC_STEP_MASK 0x0000000fL
+#define MC_ARB_WCDR_2__WPRE_INC_STEP__SHIFT 0x00000000
+#define MC_ARB_WCDR_2__WPRE_MIN_THRESHOLD_MASK 0x000001f0L
+#define MC_ARB_WCDR_2__WPRE_MIN_THRESHOLD__SHIFT 0x00000004
+#define MC_ARB_WCDR__IDLE_BURST_MASK 0x00001f80L
+#define MC_ARB_WCDR__IDLE_BURST_MODE_MASK 0x00002000L
+#define MC_ARB_WCDR__IDLE_BURST_MODE__SHIFT 0x0000000d
+#define MC_ARB_WCDR__IDLE_BURST__SHIFT 0x00000007
+#define MC_ARB_WCDR__IDLE_DEGLITCH_ENABLE_MASK 0x00010000L
+#define MC_ARB_WCDR__IDLE_DEGLITCH_ENABLE__SHIFT 0x00000010
+#define MC_ARB_WCDR__IDLE_ENABLE_MASK 0x00000001L
+#define MC_ARB_WCDR__IDLE_ENABLE__SHIFT 0x00000000
+#define MC_ARB_WCDR__IDLE_PERIOD_MASK 0x0000007cL
+#define MC_ARB_WCDR__IDLE_PERIOD__SHIFT 0x00000002
+#define MC_ARB_WCDR__IDLE_WAKEUP_MASK 0x0000c000L
+#define MC_ARB_WCDR__IDLE_WAKEUP__SHIFT 0x0000000e
+#define MC_ARB_WCDR__SEQ_IDLE_MASK 0x00000002L
+#define MC_ARB_WCDR__SEQ_IDLE__SHIFT 0x00000001
+#define MC_ARB_WCDR__WPRE_ENABLE_MASK 0x00020000L
+#define MC_ARB_WCDR__WPRE_ENABLE__SHIFT 0x00000011
+#define MC_ARB_WCDR__WPRE_INC_READ_MASK 0x02000000L
+#define MC_ARB_WCDR__WPRE_INC_READ__SHIFT 0x00000019
+#define MC_ARB_WCDR__WPRE_INC_SEQIDLE_MASK 0x08000000L
+#define MC_ARB_WCDR__WPRE_INC_SEQIDLE__SHIFT 0x0000001b
+#define MC_ARB_WCDR__WPRE_INC_SKIDIDLE_MASK 0x04000000L
+#define MC_ARB_WCDR__WPRE_INC_SKIDIDLE__SHIFT 0x0000001a
+#define MC_ARB_WCDR__WPRE_MAX_BURST_MASK 0x01c00000L
+#define MC_ARB_WCDR__WPRE_MAX_BURST__SHIFT 0x00000016
+#define MC_ARB_WCDR__WPRE_THRESHOLD_MASK 0x003c0000L
+#define MC_ARB_WCDR__WPRE_THRESHOLD__SHIFT 0x00000012
+#define MC_ARB_WCDR__WPRE_TWOPAGE_MASK 0x10000000L
+#define MC_ARB_WCDR__WPRE_TWOPAGE__SHIFT 0x0000001c
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP0_MASK 0x00000008L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP0__SHIFT 0x00000003
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP1_MASK 0x00000010L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP1__SHIFT 0x00000004
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP2_MASK 0x00000020L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP2__SHIFT 0x00000005
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP3_MASK 0x00000040L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP4_MASK 0x00000080L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP4__SHIFT 0x00000007
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP5_MASK 0x00000100L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP5__SHIFT 0x00000008
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP6_MASK 0x00000200L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP6__SHIFT 0x00000009
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP7_MASK 0x00000400L
+#define MC_ARB_WTM_CNTL_RD__ALLOW_STUTTER_GRP7__SHIFT 0x0000000a
+#define MC_ARB_WTM_CNTL_RD__HARSH_PRI_MASK 0x00000004L
+#define MC_ARB_WTM_CNTL_RD__HARSH_PRI__SHIFT 0x00000002
+#define MC_ARB_WTM_CNTL_RD__WTMODE_MASK 0x00000003L
+#define MC_ARB_WTM_CNTL_RD__WTMODE__SHIFT 0x00000000
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP0_MASK 0x00000008L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP0__SHIFT 0x00000003
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP1_MASK 0x00000010L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP1__SHIFT 0x00000004
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP2_MASK 0x00000020L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP2__SHIFT 0x00000005
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP3_MASK 0x00000040L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP4_MASK 0x00000080L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP4__SHIFT 0x00000007
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP5_MASK 0x00000100L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP5__SHIFT 0x00000008
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP6_MASK 0x00000200L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP6__SHIFT 0x00000009
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP7_MASK 0x00000400L
+#define MC_ARB_WTM_CNTL_WR__ALLOW_STUTTER_GRP7__SHIFT 0x0000000a
+#define MC_ARB_WTM_CNTL_WR__HARSH_PRI_MASK 0x00000004L
+#define MC_ARB_WTM_CNTL_WR__HARSH_PRI__SHIFT 0x00000002
+#define MC_ARB_WTM_CNTL_WR__WTMODE_MASK 0x00000003L
+#define MC_ARB_WTM_CNTL_WR__WTMODE__SHIFT 0x00000000
+#define MC_ARB_WTM_GRPWT_RD__GRP0_MASK 0x00000003L
+#define MC_ARB_WTM_GRPWT_RD__GRP0__SHIFT 0x00000000
+#define MC_ARB_WTM_GRPWT_RD__GRP1_MASK 0x0000000cL
+#define MC_ARB_WTM_GRPWT_RD__GRP1__SHIFT 0x00000002
+#define MC_ARB_WTM_GRPWT_RD__GRP2_MASK 0x00000030L
+#define MC_ARB_WTM_GRPWT_RD__GRP2__SHIFT 0x00000004
+#define MC_ARB_WTM_GRPWT_RD__GRP3_MASK 0x000000c0L
+#define MC_ARB_WTM_GRPWT_RD__GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_GRPWT_RD__GRP4_MASK 0x00000300L
+#define MC_ARB_WTM_GRPWT_RD__GRP4__SHIFT 0x00000008
+#define MC_ARB_WTM_GRPWT_RD__GRP5_MASK 0x00000c00L
+#define MC_ARB_WTM_GRPWT_RD__GRP5__SHIFT 0x0000000a
+#define MC_ARB_WTM_GRPWT_RD__GRP6_MASK 0x00003000L
+#define MC_ARB_WTM_GRPWT_RD__GRP6__SHIFT 0x0000000c
+#define MC_ARB_WTM_GRPWT_RD__GRP7_MASK 0x0000c000L
+#define MC_ARB_WTM_GRPWT_RD__GRP7__SHIFT 0x0000000e
+#define MC_ARB_WTM_GRPWT_RD__GRP_EXT_MASK 0x00ff0000L
+#define MC_ARB_WTM_GRPWT_RD__GRP_EXT__SHIFT 0x00000010
+#define MC_ARB_WTM_GRPWT_WR__GRP0_MASK 0x00000003L
+#define MC_ARB_WTM_GRPWT_WR__GRP0__SHIFT 0x00000000
+#define MC_ARB_WTM_GRPWT_WR__GRP1_MASK 0x0000000cL
+#define MC_ARB_WTM_GRPWT_WR__GRP1__SHIFT 0x00000002
+#define MC_ARB_WTM_GRPWT_WR__GRP2_MASK 0x00000030L
+#define MC_ARB_WTM_GRPWT_WR__GRP2__SHIFT 0x00000004
+#define MC_ARB_WTM_GRPWT_WR__GRP3_MASK 0x000000c0L
+#define MC_ARB_WTM_GRPWT_WR__GRP3__SHIFT 0x00000006
+#define MC_ARB_WTM_GRPWT_WR__GRP4_MASK 0x00000300L
+#define MC_ARB_WTM_GRPWT_WR__GRP4__SHIFT 0x00000008
+#define MC_ARB_WTM_GRPWT_WR__GRP5_MASK 0x00000c00L
+#define MC_ARB_WTM_GRPWT_WR__GRP5__SHIFT 0x0000000a
+#define MC_ARB_WTM_GRPWT_WR__GRP6_MASK 0x00003000L
+#define MC_ARB_WTM_GRPWT_WR__GRP6__SHIFT 0x0000000c
+#define MC_ARB_WTM_GRPWT_WR__GRP7_MASK 0x0000c000L
+#define MC_ARB_WTM_GRPWT_WR__GRP7__SHIFT 0x0000000e
+#define MC_ARB_WTM_GRPWT_WR__GRP_EXT_MASK 0x00ff0000L
+#define MC_ARB_WTM_GRPWT_WR__GRP_EXT__SHIFT 0x00000010
+#define MC_BIST_AUTO_CNTL__ADR_GEN_MASK 0x000000f0L
+#define MC_BIST_AUTO_CNTL__ADR_GEN__SHIFT 0x00000004
+#define MC_BIST_AUTO_CNTL__ADR_RESET_MASK 0x02000000L
+#define MC_BIST_AUTO_CNTL__ADR_RESET__SHIFT 0x00000019
+#define MC_BIST_AUTO_CNTL__LFSR_KEY_MASK 0x00ffff00L
+#define MC_BIST_AUTO_CNTL__LFSR_KEY__SHIFT 0x00000008
+#define MC_BIST_AUTO_CNTL__LFSR_RESET_MASK 0x01000000L
+#define MC_BIST_AUTO_CNTL__LFSR_RESET__SHIFT 0x00000018
+#define MC_BIST_AUTO_CNTL__MOP_MASK 0x00000003L
+#define MC_BIST_AUTO_CNTL__MOP__SHIFT 0x00000000
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_LOOP_MASK 0x00000004L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_LOOP__SHIFT 0x00000002
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE_MASK 0x00000002L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE__SHIFT 0x00000001
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE_U_MASK 0x00010000L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_MODE_U__SHIFT 0x00000010
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_RUN_MASK 0x00020000L
+#define MC_BIST_CMD_CNTL__CMD_ISSUE_RUN__SHIFT 0x00000011
+#define MC_BIST_CMD_CNTL__DONE_MASK 0x80000000L
+#define MC_BIST_CMD_CNTL__DONE__SHIFT 0x0000001f
+#define MC_BIST_CMD_CNTL__ENABLE_D0_MASK 0x10000000L
+#define MC_BIST_CMD_CNTL__ENABLE_D0__SHIFT 0x0000001c
+#define MC_BIST_CMD_CNTL__ENABLE_D1_MASK 0x20000000L
+#define MC_BIST_CMD_CNTL__ENABLE_D1__SHIFT 0x0000001d
+#define MC_BIST_CMD_CNTL__LOOP_CNT_MAX_MASK 0x0000fff0L
+#define MC_BIST_CMD_CNTL__LOOP_CNT_MAX__SHIFT 0x00000004
+#define MC_BIST_CMD_CNTL__LOOP_CNT_RD_MASK 0x0ffc0000L
+#define MC_BIST_CMD_CNTL__LOOP_CNT_RD__SHIFT 0x00000012
+#define MC_BIST_CMD_CNTL__LOOP_END_CONDITION_MASK 0x00000008L
+#define MC_BIST_CMD_CNTL__LOOP_END_CONDITION__SHIFT 0x00000003
+#define MC_BIST_CMD_CNTL__RESET_MASK 0x00000001L
+#define MC_BIST_CMD_CNTL__RESET__SHIFT 0x00000000
+#define MC_BIST_CMD_CNTL__STATUS_CH_MASK 0x40000000L
+#define MC_BIST_CMD_CNTL__STATUS_CH__SHIFT 0x0000001e
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT_MASK 0x0000001fL
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT_RST_MASK 0x00000100L
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT_RST__SHIFT 0x00000008
+#define MC_BIST_CMP_CNTL_2__DATA_STORE_CNT__SHIFT 0x00000000
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT_MASK 0x0001f000L
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT_RST_MASK 0x00100000L
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT_RST__SHIFT 0x00000014
+#define MC_BIST_CMP_CNTL_2__EDC_STORE_CNT__SHIFT 0x0000000c
+#define MC_BIST_CMP_CNTL__CMP_MASK 0x00030000L
+#define MC_BIST_CMP_CNTL__CMP_MASK_BIT_MASK 0x00000ff0L
+#define MC_BIST_CMP_CNTL__CMP_MASK_BIT__SHIFT 0x00000004
+#define MC_BIST_CMP_CNTL__CMP_MASK_BYTE_MASK 0x0000000fL
+#define MC_BIST_CMP_CNTL__CMP_MASK_BYTE__SHIFT 0x00000000
+#define MC_BIST_CMP_CNTL__CMP__SHIFT 0x00000010
+#define MC_BIST_CMP_CNTL__DATA_STORE_MODE_MASK 0x00300000L
+#define MC_BIST_CMP_CNTL__DATA_STORE_MODE__SHIFT 0x00000014
+#define MC_BIST_CMP_CNTL__DATA_STORE_SEL_MASK 0x00002000L
+#define MC_BIST_CMP_CNTL__DATA_STORE_SEL__SHIFT 0x0000000d
+#define MC_BIST_CMP_CNTL__DAT_MODE_MASK 0x00040000L
+#define MC_BIST_CMP_CNTL__DAT_MODE__SHIFT 0x00000012
+#define MC_BIST_CMP_CNTL__EDC_STORE_MODE_MASK 0x00080000L
+#define MC_BIST_CMP_CNTL__EDC_STORE_MODE__SHIFT 0x00000013
+#define MC_BIST_CMP_CNTL__EDC_STORE_SEL_MASK 0x00004000L
+#define MC_BIST_CMP_CNTL__EDC_STORE_SEL__SHIFT 0x0000000e
+#define MC_BIST_CMP_CNTL__ENABLE_CMD_FIFO_MASK 0x00008000L
+#define MC_BIST_CMP_CNTL__ENABLE_CMD_FIFO__SHIFT 0x0000000f
+#define MC_BIST_CMP_CNTL__LOAD_RTEDC_MASK 0x00001000L
+#define MC_BIST_CMP_CNTL__LOAD_RTEDC__SHIFT 0x0000000c
+#define MC_BIST_CMP_CNTL__MISMATCH_CNT_MASK 0xffc00000L
+#define MC_BIST_CMP_CNTL__MISMATCH_CNT__SHIFT 0x00000016
+#define MC_BIST_CNTL__ADR_MODE_MASK 0x00000020L
+#define MC_BIST_CNTL__ADR_MODE__SHIFT 0x00000005
+#define MC_BIST_CNTL__DAT_MODE_MASK 0x00000040L
+#define MC_BIST_CNTL__DAT_MODE__SHIFT 0x00000006
+#define MC_BIST_CNTL__DONE_MASK 0x40000000L
+#define MC_BIST_CNTL__DONE__SHIFT 0x0000001e
+#define MC_BIST_CNTL__ENABLE_D0_MASK 0x00001000L
+#define MC_BIST_CNTL__ENABLE_D0__SHIFT 0x0000000c
+#define MC_BIST_CNTL__ENABLE_D1_MASK 0x00002000L
+#define MC_BIST_CNTL__ENABLE_D1__SHIFT 0x0000000d
+#define MC_BIST_CNTL__LOAD_RTDATA_CH_MASK 0x00004000L
+#define MC_BIST_CNTL__LOAD_RTDATA_CH__SHIFT 0x0000000e
+#define MC_BIST_CNTL__LOAD_RTDATA_MASK 0x80000000L
+#define MC_BIST_CNTL__LOAD_RTDATA__SHIFT 0x0000001f
+#define MC_BIST_CNTL__LOOP_CNT_MASK 0x0fff0000L
+#define MC_BIST_CNTL__LOOP_CNT__SHIFT 0x00000010
+#define MC_BIST_CNTL__LOOP_MASK 0x00000c00L
+#define MC_BIST_CNTL__LOOP__SHIFT 0x0000000a
+#define MC_BIST_CNTL__MOP_MODE_MASK 0x00000010L
+#define MC_BIST_CNTL__MOP_MODE__SHIFT 0x00000004
+#define MC_BIST_CNTL__PTR_RST_D0_MASK 0x00000004L
+#define MC_BIST_CNTL__PTR_RST_D0__SHIFT 0x00000002
+#define MC_BIST_CNTL__PTR_RST_D1_MASK 0x00000008L
+#define MC_BIST_CNTL__PTR_RST_D1__SHIFT 0x00000003
+#define MC_BIST_CNTL__RESET_MASK 0x00000001L
+#define MC_BIST_CNTL__RESET__SHIFT 0x00000000
+#define MC_BIST_CNTL__RUN_MASK 0x00000002L
+#define MC_BIST_CNTL__RUN__SHIFT 0x00000001
+#define MC_BIST_DATA_MASK__MASK_MASK 0xffffffffL
+#define MC_BIST_DATA_MASK__MASK__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD0__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD0__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD1__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD1__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD2__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD2__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD3__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD3__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD4__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD4__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD5__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD5__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD6__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD6__DATA__SHIFT 0x00000000
+#define MC_BIST_DATA_WORD7__DATA_MASK 0xffffffffL
+#define MC_BIST_DATA_WORD7__DATA__SHIFT 0x00000000
+#define MC_BIST_DIR_CNTL__CMD_RTR_D0_MASK 0x00000040L
+#define MC_BIST_DIR_CNTL__CMD_RTR_D0__SHIFT 0x00000006
+#define MC_BIST_DIR_CNTL__CMD_RTR_D1_MASK 0x00000100L
+#define MC_BIST_DIR_CNTL__CMD_RTR_D1__SHIFT 0x00000008
+#define MC_BIST_DIR_CNTL__DATA_LOAD_MASK 0x00000020L
+#define MC_BIST_DIR_CNTL__DATA_LOAD__SHIFT 0x00000005
+#define MC_BIST_DIR_CNTL__DAT_RTR_D0_MASK 0x00000080L
+#define MC_BIST_DIR_CNTL__DAT_RTR_D0__SHIFT 0x00000007
+#define MC_BIST_DIR_CNTL__DAT_RTR_D1_MASK 0x00000200L
+#define MC_BIST_DIR_CNTL__DAT_RTR_D1__SHIFT 0x00000009
+#define MC_BIST_DIR_CNTL__EOB_MASK 0x00000008L
+#define MC_BIST_DIR_CNTL__EOB__SHIFT 0x00000003
+#define MC_BIST_DIR_CNTL__MOP3_MASK 0x00000400L
+#define MC_BIST_DIR_CNTL__MOP3__SHIFT 0x0000000a
+#define MC_BIST_DIR_CNTL__MOP_LOAD_MASK 0x00000010L
+#define MC_BIST_DIR_CNTL__MOP_LOAD__SHIFT 0x00000004
+#define MC_BIST_DIR_CNTL__MOP_MASK 0x00000007L
+#define MC_BIST_DIR_CNTL__MOP__SHIFT 0x00000000
+#define MC_BIST_EADDR__BANK_MASK 0x0f000000L
+#define MC_BIST_EADDR__BANK__SHIFT 0x00000018
+#define MC_BIST_EADDR__COLH_MASK 0x20000000L
+#define MC_BIST_EADDR__COLH__SHIFT 0x0000001d
+#define MC_BIST_EADDR__COL_MASK 0x000003ffL
+#define MC_BIST_EADDR__COL__SHIFT 0x00000000
+#define MC_BIST_EADDR__RANK_MASK 0x10000000L
+#define MC_BIST_EADDR__RANK__SHIFT 0x0000001c
+#define MC_BIST_EADDR__ROWH_MASK 0xc0000000L
+#define MC_BIST_EADDR__ROWH__SHIFT 0x0000001e
+#define MC_BIST_EADDR__ROW_MASK 0x00fffc00L
+#define MC_BIST_EADDR__ROW__SHIFT 0x0000000a
+#define MC_BIST_MISMATCH_ADDR__BANK_MASK 0x0f000000L
+#define MC_BIST_MISMATCH_ADDR__BANK__SHIFT 0x00000018
+#define MC_BIST_MISMATCH_ADDR__COLH_MASK 0x20000000L
+#define MC_BIST_MISMATCH_ADDR__COLH__SHIFT 0x0000001d
+#define MC_BIST_MISMATCH_ADDR__COL_MASK 0x000003ffL
+#define MC_BIST_MISMATCH_ADDR__COL__SHIFT 0x00000000
+#define MC_BIST_MISMATCH_ADDR__RANK_MASK 0x10000000L
+#define MC_BIST_MISMATCH_ADDR__RANK__SHIFT 0x0000001c
+#define MC_BIST_MISMATCH_ADDR__ROWH_MASK 0xc0000000L
+#define MC_BIST_MISMATCH_ADDR__ROWH__SHIFT 0x0000001e
+#define MC_BIST_MISMATCH_ADDR__ROW_MASK 0x00fffc00L
+#define MC_BIST_MISMATCH_ADDR__ROW__SHIFT 0x0000000a
+#define MC_BIST_RDATA_EDC__EDC_MASK 0xffffffffL
+#define MC_BIST_RDATA_EDC__EDC__SHIFT 0x00000000
+#define MC_BIST_RDATA_MASK__MASK_MASK 0xffffffffL
+#define MC_BIST_RDATA_MASK__MASK__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD0__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD0__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD1__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD1__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD2__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD2__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD3__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD3__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD4__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD4__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD5__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD5__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD6__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD6__RDATA__SHIFT 0x00000000
+#define MC_BIST_RDATA_WORD7__RDATA_MASK 0xffffffffL
+#define MC_BIST_RDATA_WORD7__RDATA__SHIFT 0x00000000
+#define MC_BIST_SADDR__BANK_MASK 0x0f000000L
+#define MC_BIST_SADDR__BANK__SHIFT 0x00000018
+#define MC_BIST_SADDR__COLH_MASK 0x20000000L
+#define MC_BIST_SADDR__COLH__SHIFT 0x0000001d
+#define MC_BIST_SADDR__COL_MASK 0x000003ffL
+#define MC_BIST_SADDR__COL__SHIFT 0x00000000
+#define MC_BIST_SADDR__RANK_MASK 0x10000000L
+#define MC_BIST_SADDR__RANK__SHIFT 0x0000001c
+#define MC_BIST_SADDR__ROWH_MASK 0xc0000000L
+#define MC_BIST_SADDR__ROWH__SHIFT 0x0000001e
+#define MC_BIST_SADDR__ROW_MASK 0x00fffc00L
+#define MC_BIST_SADDR__ROW__SHIFT 0x0000000a
+#define MC_CG_CONFIG__INDEX_MASK 0x003fffc0L
+#define MC_CG_CONFIG__INDEX__SHIFT 0x00000006
+#define MC_CG_CONFIG_MCD__INDEX_MASK 0x1fffe000L
+#define MC_CG_CONFIG_MCD__INDEX__SHIFT 0x0000000d
+#define MC_CG_CONFIG_MCD__MCD0_WR_ENABLE_MASK 0x00000001L
+#define MC_CG_CONFIG_MCD__MCD0_WR_ENABLE__SHIFT 0x00000000
+#define MC_CG_CONFIG_MCD__MCD1_WR_ENABLE_MASK 0x00000002L
+#define MC_CG_CONFIG_MCD__MCD1_WR_ENABLE__SHIFT 0x00000001
+#define MC_CG_CONFIG_MCD__MCD2_WR_ENABLE_MASK 0x00000004L
+#define MC_CG_CONFIG_MCD__MCD2_WR_ENABLE__SHIFT 0x00000002
+#define MC_CG_CONFIG_MCD__MCD3_WR_ENABLE_MASK 0x00000008L
+#define MC_CG_CONFIG_MCD__MCD3_WR_ENABLE__SHIFT 0x00000003
+#define MC_CG_CONFIG_MCD__MCD4_WR_ENABLE_MASK 0x00000010L
+#define MC_CG_CONFIG_MCD__MCD4_WR_ENABLE__SHIFT 0x00000004
+#define MC_CG_CONFIG_MCD__MCD5_WR_ENABLE_MASK 0x00000020L
+#define MC_CG_CONFIG_MCD__MCD5_WR_ENABLE__SHIFT 0x00000005
+#define MC_CG_CONFIG_MCD__MC_RD_ENABLE_MASK 0x00000700L
+#define MC_CG_CONFIG_MCD__MC_RD_ENABLE__SHIFT 0x00000008
+#define MC_CG_CONFIG__MCDW_WR_ENABLE_MASK 0x00000001L
+#define MC_CG_CONFIG__MCDW_WR_ENABLE__SHIFT 0x00000000
+#define MC_CG_CONFIG__MCDX_WR_ENABLE_MASK 0x00000002L
+#define MC_CG_CONFIG__MCDX_WR_ENABLE__SHIFT 0x00000001
+#define MC_CG_CONFIG__MCDY_WR_ENABLE_MASK 0x00000004L
+#define MC_CG_CONFIG__MCDY_WR_ENABLE__SHIFT 0x00000002
+#define MC_CG_CONFIG__MCDZ_WR_ENABLE_MASK 0x00000008L
+#define MC_CG_CONFIG__MCDZ_WR_ENABLE__SHIFT 0x00000003
+#define MC_CG_CONFIG__MC_RD_ENABLE_MASK 0x00000030L
+#define MC_CG_CONFIG__MC_RD_ENABLE__SHIFT 0x00000004
+#define MC_CG_DATAPORT__DATA_FIELD_MASK 0xffffffffL
+#define MC_CG_DATAPORT__DATA_FIELD__SHIFT 0x00000000
+#define MC_CITF_CNTL__EXEMPTPM_MASK 0x00000008L
+#define MC_CITF_CNTL__EXEMPTPM__SHIFT 0x00000003
+#define MC_CITF_CNTL__GFX_IDLE_OVERRIDE_MASK 0x00000030L
+#define MC_CITF_CNTL__GFX_IDLE_OVERRIDE__SHIFT 0x00000004
+#define MC_CITF_CNTL__IGNOREPM_MASK 0x00000004L
+#define MC_CITF_CNTL__IGNOREPM__SHIFT 0x00000002
+#define MC_CITF_CNTL__MCD_SRBM_MASK_ENABLE_MASK 0x00000040L
+#define MC_CITF_CNTL__MCD_SRBM_MASK_ENABLE__SHIFT 0x00000006
+#define MC_CITF_CREDITS_ARB_RD__HUB_PRI_MASK 0x02000000L
+#define MC_CITF_CREDITS_ARB_RD__HUB_PRI__SHIFT 0x00000019
+#define MC_CITF_CREDITS_ARB_RD__LCL_PRI_MASK 0x01000000L
+#define MC_CITF_CREDITS_ARB_RD__LCL_PRI__SHIFT 0x00000018
+#define MC_CITF_CREDITS_ARB_RD__READ_HUB_MASK 0x0000ff00L
+#define MC_CITF_CREDITS_ARB_RD__READ_HUB__SHIFT 0x00000008
+#define MC_CITF_CREDITS_ARB_RD__READ_LCL_MASK 0x000000ffL
+#define MC_CITF_CREDITS_ARB_RD__READ_LCL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_ARB_RD__READ_PRI_MASK 0x00ff0000L
+#define MC_CITF_CREDITS_ARB_RD__READ_PRI__SHIFT 0x00000010
+#define MC_CITF_CREDITS_ARB_WR__HUB_PRI_MASK 0x00010000L
+#define MC_CITF_CREDITS_ARB_WR__HUB_PRI__SHIFT 0x00000010
+#define MC_CITF_CREDITS_ARB_WR__LCL_PRI_MASK 0x00020000L
+#define MC_CITF_CREDITS_ARB_WR__LCL_PRI__SHIFT 0x00000011
+#define MC_CITF_CREDITS_ARB_WR__WRITE_HUB_MASK 0x0000ff00L
+#define MC_CITF_CREDITS_ARB_WR__WRITE_HUB__SHIFT 0x00000008
+#define MC_CITF_CREDITS_ARB_WR__WRITE_LCL_MASK 0x000000ffL
+#define MC_CITF_CREDITS_ARB_WR__WRITE_LCL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_VM__READ_ALL_MASK 0x0000003fL
+#define MC_CITF_CREDITS_VM__READ_ALL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_VM__WRITE_ALL_MASK 0x00000fc0L
+#define MC_CITF_CREDITS_VM__WRITE_ALL__SHIFT 0x00000006
+#define MC_CITF_CREDITS_XBAR__READ_LCL_MASK 0x000000ffL
+#define MC_CITF_CREDITS_XBAR__READ_LCL__SHIFT 0x00000000
+#define MC_CITF_CREDITS_XBAR__WRITE_LCL_MASK 0x0000ff00L
+#define MC_CITF_CREDITS_XBAR__WRITE_LCL__SHIFT 0x00000008
+#define MC_CITF_DAGB_CNTL__CENTER_RD_MAX_BURST_MASK 0x0000001eL
+#define MC_CITF_DAGB_CNTL__CENTER_RD_MAX_BURST__SHIFT 0x00000001
+#define MC_CITF_DAGB_CNTL__CENTER_WR_MAX_BURST_MASK 0x000003c0L
+#define MC_CITF_DAGB_CNTL__CENTER_WR_MAX_BURST__SHIFT 0x00000006
+#define MC_CITF_DAGB_CNTL__DISABLE_SELF_INIT_MASK 0x00000020L
+#define MC_CITF_DAGB_CNTL__DISABLE_SELF_INIT__SHIFT 0x00000005
+#define MC_CITF_DAGB_CNTL__JUMP_AHEAD_MASK 0x00000001L
+#define MC_CITF_DAGB_CNTL__JUMP_AHEAD__SHIFT 0x00000000
+#define MC_CITF_DAGB_DLY__CLI_MASK 0x001f0000L
+#define MC_CITF_DAGB_DLY__CLI__SHIFT 0x00000010
+#define MC_CITF_DAGB_DLY__DLY_MASK 0x0000001fL
+#define MC_CITF_DAGB_DLY__DLY__SHIFT 0x00000000
+#define MC_CITF_DAGB_DLY__POS_MASK 0x1f000000L
+#define MC_CITF_DAGB_DLY__POS__SHIFT 0x00000018
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_HP_MASK 0x00fc0000L
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_HP__SHIFT 0x00000012
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_LP_MASK 0x0003f000L
+#define MC_CITF_INT_CREDITS__CNTR_RD_HUB_LP__SHIFT 0x0000000c
+#define MC_CITF_INT_CREDITS__CNTR_RD_LCL_MASK 0x3f000000L
+#define MC_CITF_INT_CREDITS__CNTR_RD_LCL__SHIFT 0x00000018
+#define MC_CITF_INT_CREDITS__REMRDRET_MASK 0x0000003fL
+#define MC_CITF_INT_CREDITS__REMRDRET__SHIFT 0x00000000
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_HUB_MASK 0x0000003fL
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_HUB__SHIFT 0x00000000
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_LCL_MASK 0x00000fc0L
+#define MC_CITF_INT_CREDITS_WR__CNTR_WR_LCL__SHIFT 0x00000006
+#define MC_CITF_MISC_RD_CG__ENABLE_MASK 0x00040000L
+#define MC_CITF_MISC_RD_CG__ENABLE__SHIFT 0x00000012
+#define MC_CITF_MISC_RD_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_CITF_MISC_RD_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_CITF_MISC_RD_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_CITF_MISC_RD_CG__OFFDLY__SHIFT 0x00000006
+#define MC_CITF_MISC_RD_CG__ONDLY_MASK 0x0000003fL
+#define MC_CITF_MISC_RD_CG__ONDLY__SHIFT 0x00000000
+#define MC_CITF_MISC_RD_CG__RDYDLY_MASK 0x0003f000L
+#define MC_CITF_MISC_RD_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_CITF_MISC_VM_CG__ENABLE_MASK 0x00040000L
+#define MC_CITF_MISC_VM_CG__ENABLE__SHIFT 0x00000012
+#define MC_CITF_MISC_VM_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_CITF_MISC_VM_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_CITF_MISC_VM_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_CITF_MISC_VM_CG__OFFDLY__SHIFT 0x00000006
+#define MC_CITF_MISC_VM_CG__ONDLY_MASK 0x0000003fL
+#define MC_CITF_MISC_VM_CG__ONDLY__SHIFT 0x00000000
+#define MC_CITF_MISC_VM_CG__RDYDLY_MASK 0x0003f000L
+#define MC_CITF_MISC_VM_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_CITF_MISC_WR_CG__ENABLE_MASK 0x00040000L
+#define MC_CITF_MISC_WR_CG__ENABLE__SHIFT 0x00000012
+#define MC_CITF_MISC_WR_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_CITF_MISC_WR_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_CITF_MISC_WR_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_CITF_MISC_WR_CG__OFFDLY__SHIFT 0x00000006
+#define MC_CITF_MISC_WR_CG__ONDLY_MASK 0x0000003fL
+#define MC_CITF_MISC_WR_CG__ONDLY__SHIFT 0x00000000
+#define MC_CITF_MISC_WR_CG__RDYDLY_MASK 0x0003f000L
+#define MC_CITF_MISC_WR_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_CITF_PERF_MON_CNTL2__CID_MASK 0x000001ffL
+#define MC_CITF_PERF_MON_CNTL2__CID__SHIFT 0x00000000
+#define MC_CITF_PERF_MON_RSLT2__CB_RD_BUSY_MASK 0x00000040L
+#define MC_CITF_PERF_MON_RSLT2__CB_RD_BUSY__SHIFT 0x00000006
+#define MC_CITF_PERF_MON_RSLT2__CB_WR_BUSY_MASK 0x00001000L
+#define MC_CITF_PERF_MON_RSLT2__CB_WR_BUSY__SHIFT 0x0000000c
+#define MC_CITF_PERF_MON_RSLT2__DB_RD_BUSY_MASK 0x00000080L
+#define MC_CITF_PERF_MON_RSLT2__DB_RD_BUSY__SHIFT 0x00000007
+#define MC_CITF_PERF_MON_RSLT2__DB_WR_BUSY_MASK 0x00002000L
+#define MC_CITF_PERF_MON_RSLT2__DB_WR_BUSY__SHIFT 0x0000000d
+#define MC_CITF_PERF_MON_RSLT2__SX_WR_BUSY_MASK 0x00004000L
+#define MC_CITF_PERF_MON_RSLT2__SX_WR_BUSY__SHIFT 0x0000000e
+#define MC_CITF_PERF_MON_RSLT2__TC0_RD_BUSY_MASK 0x00000100L
+#define MC_CITF_PERF_MON_RSLT2__TC0_RD_BUSY__SHIFT 0x00000008
+#define MC_CITF_PERF_MON_RSLT2__TC0_WR_BUSY_MASK 0x00010000L
+#define MC_CITF_PERF_MON_RSLT2__TC0_WR_BUSY__SHIFT 0x00000010
+#define MC_CITF_PERF_MON_RSLT2__TC1_RD_BUSY_MASK 0x00000400L
+#define MC_CITF_PERF_MON_RSLT2__TC1_RD_BUSY__SHIFT 0x0000000a
+#define MC_CITF_PERF_MON_RSLT2__TC1_WR_BUSY_MASK 0x00020000L
+#define MC_CITF_PERF_MON_RSLT2__TC1_WR_BUSY__SHIFT 0x00000011
+#define MC_CITF_PERF_MON_RSLT2__TC2_RD_BUSY_MASK 0x00008000L
+#define MC_CITF_PERF_MON_RSLT2__TC2_RD_BUSY__SHIFT 0x0000000f
+#define MC_CITF_PERF_MON_RSLT2__TC2_WR_BUSY_MASK 0x00040000L
+#define MC_CITF_PERF_MON_RSLT2__TC2_WR_BUSY__SHIFT 0x00000012
+#define MC_CITF_PERF_MON_RSLT2__VC0_RD_BUSY_MASK 0x00000200L
+#define MC_CITF_PERF_MON_RSLT2__VC0_RD_BUSY__SHIFT 0x00000009
+#define MC_CITF_PERF_MON_RSLT2__VC1_RD_BUSY_MASK 0x00000800L
+#define MC_CITF_PERF_MON_RSLT2__VC1_RD_BUSY__SHIFT 0x0000000b
+#define MC_CITF_REMREQ__CREDITS_ENABLE_MASK 0x00004000L
+#define MC_CITF_REMREQ__CREDITS_ENABLE__SHIFT 0x0000000e
+#define MC_CITF_REMREQ__READ_CREDITS_MASK 0x0000007fL
+#define MC_CITF_REMREQ__READ_CREDITS__SHIFT 0x00000000
+#define MC_CITF_REMREQ__WRITE_CREDITS_MASK 0x00003f80L
+#define MC_CITF_REMREQ__WRITE_CREDITS__SHIFT 0x00000007
+#define MC_CITF_RET_MODE__INORDER_RD_MASK 0x00000001L
+#define MC_CITF_RET_MODE__INORDER_RD__SHIFT 0x00000000
+#define MC_CITF_RET_MODE__INORDER_WR_MASK 0x00000002L
+#define MC_CITF_RET_MODE__INORDER_WR__SHIFT 0x00000001
+#define MC_CITF_RET_MODE__LCLPRI_RD_MASK 0x00000010L
+#define MC_CITF_RET_MODE__LCLPRI_RD__SHIFT 0x00000004
+#define MC_CITF_RET_MODE__LCLPRI_WR_MASK 0x00000020L
+#define MC_CITF_RET_MODE__LCLPRI_WR__SHIFT 0x00000005
+#define MC_CITF_RET_MODE__REMPRI_RD_MASK 0x00000004L
+#define MC_CITF_RET_MODE__REMPRI_RD__SHIFT 0x00000002
+#define MC_CITF_RET_MODE__REMPRI_WR_MASK 0x00000008L
+#define MC_CITF_RET_MODE__REMPRI_WR__SHIFT 0x00000003
+#define MC_CITF_WTM_RD_CNTL__DISABLE_REMOTE_MASK 0x01000000L
+#define MC_CITF_WTM_RD_CNTL__DISABLE_REMOTE__SHIFT 0x00000018
+#define MC_CITF_WTM_RD_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_CITF_WTM_RD_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_CITF_WTM_RD_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_CITF_WTM_RD_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_CITF_WTM_RD_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_CITF_WTM_RD_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_CITF_WTM_RD_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_CITF_WTM_RD_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_CITF_WTM_RD_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_CITF_WTM_RD_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_CITF_WTM_RD_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_CITF_WTM_RD_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_CITF_WTM_RD_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_CITF_WTM_RD_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_CITF_WTM_RD_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_CITF_WTM_RD_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_CITF_WTM_WR_CNTL__DISABLE_REMOTE_MASK 0x01000000L
+#define MC_CITF_WTM_WR_CNTL__DISABLE_REMOTE__SHIFT 0x00000018
+#define MC_CITF_WTM_WR_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_CITF_WTM_WR_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_CITF_WTM_WR_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_CITF_WTM_WR_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_CITF_WTM_WR_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_CITF_WTM_WR_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_CITF_WTM_WR_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_CITF_WTM_WR_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_CITF_WTM_WR_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_CITF_WTM_WR_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_CITF_WTM_WR_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_CITF_WTM_WR_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_CITF_WTM_WR_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_CITF_WTM_WR_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_CITF_WTM_WR_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_CITF_WTM_WR_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_CITF_XTRA_ENABLE__ARB_DBG_MASK 0x00000f00L
+#define MC_CITF_XTRA_ENABLE__ARB_DBG__SHIFT 0x00000008
+#define MC_CITF_XTRA_ENABLE__CB1_RD_MASK 0x00000001L
+#define MC_CITF_XTRA_ENABLE__CB1_RD__SHIFT 0x00000000
+#define MC_CITF_XTRA_ENABLE__CB1_WR_MASK 0x00000002L
+#define MC_CITF_XTRA_ENABLE__CB1_WR__SHIFT 0x00000001
+#define MC_CITF_XTRA_ENABLE__DB1_RD_MASK 0x00000004L
+#define MC_CITF_XTRA_ENABLE__DB1_RD__SHIFT 0x00000002
+#define MC_CITF_XTRA_ENABLE__DB1_WR_MASK 0x00000008L
+#define MC_CITF_XTRA_ENABLE__DB1_WR__SHIFT 0x00000003
+#define MC_CITF_XTRA_ENABLE__TC2_RD_MASK 0x00000010L
+#define MC_CITF_XTRA_ENABLE__TC2_RD__SHIFT 0x00000004
+#define MC_CITF_XTRA_ENABLE__TC2_WR_MASK 0x00001000L
+#define MC_CITF_XTRA_ENABLE__TC2_WR__SHIFT 0x0000000c
+#define MC_CONFIG__MCC_INDEX_MODE_ENABLE_MASK 0x80000000L
+#define MC_CONFIG__MCC_INDEX_MODE_ENABLE__SHIFT 0x0000001f
+#define MC_CONFIG_MCD__MCD0_WR_ENABLE_MASK 0x00000001L
+#define MC_CONFIG_MCD__MCD0_WR_ENABLE__SHIFT 0x00000000
+#define MC_CONFIG_MCD__MCD1_WR_ENABLE_MASK 0x00000002L
+#define MC_CONFIG_MCD__MCD1_WR_ENABLE__SHIFT 0x00000001
+#define MC_CONFIG_MCD__MCD2_WR_ENABLE_MASK 0x00000004L
+#define MC_CONFIG_MCD__MCD2_WR_ENABLE__SHIFT 0x00000002
+#define MC_CONFIG_MCD__MCD3_WR_ENABLE_MASK 0x00000008L
+#define MC_CONFIG_MCD__MCD3_WR_ENABLE__SHIFT 0x00000003
+#define MC_CONFIG_MCD__MCD4_WR_ENABLE_MASK 0x00000010L
+#define MC_CONFIG_MCD__MCD4_WR_ENABLE__SHIFT 0x00000004
+#define MC_CONFIG_MCD__MCD5_WR_ENABLE_MASK 0x00000020L
+#define MC_CONFIG_MCD__MCD5_WR_ENABLE__SHIFT 0x00000005
+#define MC_CONFIG_MCD__MCD_INDEX_MODE_ENABLE_MASK 0x80000000L
+#define MC_CONFIG_MCD__MCD_INDEX_MODE_ENABLE__SHIFT 0x0000001f
+#define MC_CONFIG_MCD__MC_RD_ENABLE_MASK 0x00000700L
+#define MC_CONFIG_MCD__MC_RD_ENABLE__SHIFT 0x00000008
+#define MC_CONFIG__MCDW_WR_ENABLE_MASK 0x00000001L
+#define MC_CONFIG__MCDW_WR_ENABLE__SHIFT 0x00000000
+#define MC_CONFIG__MCDX_WR_ENABLE_MASK 0x00000002L
+#define MC_CONFIG__MCDX_WR_ENABLE__SHIFT 0x00000001
+#define MC_CONFIG__MCDY_WR_ENABLE_MASK 0x00000004L
+#define MC_CONFIG__MCDY_WR_ENABLE__SHIFT 0x00000002
+#define MC_CONFIG__MCDZ_WR_ENABLE_MASK 0x00000008L
+#define MC_CONFIG__MCDZ_WR_ENABLE__SHIFT 0x00000003
+#define MC_CONFIG__MC_RD_ENABLE_MASK 0x00000030L
+#define MC_CONFIG__MC_RD_ENABLE__SHIFT 0x00000004
+#define MC_HUB_MISC_DBG__SELECT0_MASK 0x0000000fL
+#define MC_HUB_MISC_DBG__SELECT0__SHIFT 0x00000000
+#define MC_HUB_MISC_DBG__SELECT1_MASK 0x000000f0L
+#define MC_HUB_MISC_DBG__SELECT1__SHIFT 0x00000004
+#define MC_HUB_MISC_FRAMING__BITS_MASK 0xffffffffL
+#define MC_HUB_MISC_FRAMING__BITS__SHIFT 0x00000000
+#define MC_HUB_MISC_HUB_CG__ENABLE_MASK 0x00040000L
+#define MC_HUB_MISC_HUB_CG__ENABLE__SHIFT 0x00000012
+#define MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_HUB_MISC_HUB_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_HUB_MISC_HUB_CG__OFFDLY__SHIFT 0x00000006
+#define MC_HUB_MISC_HUB_CG__ONDLY_MASK 0x0000003fL
+#define MC_HUB_MISC_HUB_CG__ONDLY__SHIFT 0x00000000
+#define MC_HUB_MISC_HUB_CG__RDYDLY_MASK 0x0003f000L
+#define MC_HUB_MISC_HUB_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_READ_MASK 0x00000001L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_READ__SHIFT 0x00000000
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_WRITE_MASK 0x00000002L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_CP_WRITE__SHIFT 0x00000001
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_READ_MASK 0x00000400L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_READ__SHIFT 0x0000000a
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_WRITE_MASK 0x00000800L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_DISP_WRITE__SHIFT 0x0000000b
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_READ_MASK 0x00000004L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_READ__SHIFT 0x00000002
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_WRITE_MASK 0x00000008L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_GFX_WRITE__SHIFT 0x00000003
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_READ_MASK 0x00010000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_READ__SHIFT 0x00000010
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_WRITE_MASK 0x00020000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_HDP_WRITE__SHIFT 0x00000011
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_READ_MASK 0x00040000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_READ__SHIFT 0x00000012
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_WRITE_MASK 0x00080000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_OTH_WRITE__SHIFT 0x00000013
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_READ_MASK 0x00000040L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_READ__SHIFT 0x00000006
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_WRITE_MASK 0x00000080L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_RLC_WRITE__SHIFT 0x00000007
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_READ_MASK 0x00004000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_READ__SHIFT 0x0000000e
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_WRITE_MASK 0x00008000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_SMU_WRITE__SHIFT 0x0000000f
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_READ_MASK 0x00001000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_READ__SHIFT 0x0000000c
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_WRITE_MASK 0x00002000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_UVD_WRITE__SHIFT 0x0000000d
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_READ_MASK 0x01000000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_READ__SHIFT 0x00000018
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_WRITE_MASK 0x02000000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VCE_WRITE__SHIFT 0x00000019
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_READ_MASK 0x00100000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_READ__SHIFT 0x00000014
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_WRITE_MASK 0x00200000L
+#define MC_HUB_MISC_IDLE_STATUS__OUTSTANDING_VMC_WRITE__SHIFT 0x00000015
+#define MC_HUB_MISC_OVERRIDE__IDLE_MASK 0x00000003L
+#define MC_HUB_MISC_OVERRIDE__IDLE__SHIFT 0x00000000
+#define MC_HUB_MISC_POWER__PM_BLACKOUT_CNTL_MASK 0x00000018L
+#define MC_HUB_MISC_POWER__PM_BLACKOUT_CNTL__SHIFT 0x00000003
+#define MC_HUB_MISC_POWER__SRBM_GATE_OVERRIDE_MASK 0x00000004L
+#define MC_HUB_MISC_POWER__SRBM_GATE_OVERRIDE__SHIFT 0x00000002
+#define MC_HUB_MISC_SIP_CG__ENABLE_MASK 0x00040000L
+#define MC_HUB_MISC_SIP_CG__ENABLE__SHIFT 0x00000012
+#define MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_HUB_MISC_SIP_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_HUB_MISC_SIP_CG__OFFDLY__SHIFT 0x00000006
+#define MC_HUB_MISC_SIP_CG__ONDLY_MASK 0x0000003fL
+#define MC_HUB_MISC_SIP_CG__ONDLY__SHIFT 0x00000000
+#define MC_HUB_MISC_SIP_CG__RDYDLY_MASK 0x0003f000L
+#define MC_HUB_MISC_SIP_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_HUB_MISC_STATUS__GFX_BUSY_MASK 0x00002000L
+#define MC_HUB_MISC_STATUS__GFX_BUSY__SHIFT 0x0000000d
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDREQ_MASK 0x00000004L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDREQ__SHIFT 0x00000002
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDRET_MASK 0x00000008L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_RDRET__SHIFT 0x00000003
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRREQ_MASK 0x00000010L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRREQ__SHIFT 0x00000004
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRRET_MASK 0x00000020L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_HUB_WRRET__SHIFT 0x00000005
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_READ_MASK 0x00000100L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_READ__SHIFT 0x00000008
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_WRITE_MASK 0x00000200L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_MCD_WRITE__SHIFT 0x00000009
+#define MC_HUB_MISC_STATUS__OUTSTANDING_READ_MASK 0x00000001L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_READ__SHIFT 0x00000000
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_READ_MASK 0x00000040L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_READ__SHIFT 0x00000006
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_WRITE_MASK 0x00000080L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_RPB_WRITE__SHIFT 0x00000007
+#define MC_HUB_MISC_STATUS__OUTSTANDING_WRITE_MASK 0x00000002L
+#define MC_HUB_MISC_STATUS__OUTSTANDING_WRITE__SHIFT 0x00000001
+#define MC_HUB_MISC_STATUS__READ_DEADLOCK_WARNING_MASK 0x00001000L
+#define MC_HUB_MISC_STATUS__READ_DEADLOCK_WARNING__SHIFT 0x0000000c
+#define MC_HUB_MISC_STATUS__RPB_BUSY_MASK 0x00000400L
+#define MC_HUB_MISC_STATUS__RPB_BUSY__SHIFT 0x0000000a
+#define MC_HUB_MISC_STATUS__WRITE_DEADLOCK_WARNING_MASK 0x00000800L
+#define MC_HUB_MISC_STATUS__WRITE_DEADLOCK_WARNING__SHIFT 0x0000000b
+#define MC_HUB_MISC_VM_CG__ENABLE_MASK 0x00040000L
+#define MC_HUB_MISC_VM_CG__ENABLE__SHIFT 0x00000012
+#define MC_HUB_MISC_VM_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_HUB_MISC_VM_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_HUB_MISC_VM_CG__OFFDLY_MASK 0x00000fc0L
+#define MC_HUB_MISC_VM_CG__OFFDLY__SHIFT 0x00000006
+#define MC_HUB_MISC_VM_CG__ONDLY_MASK 0x0000003fL
+#define MC_HUB_MISC_VM_CG__ONDLY__SHIFT 0x00000000
+#define MC_HUB_MISC_VM_CG__RDYDLY_MASK 0x0003f000L
+#define MC_HUB_MISC_VM_CG__RDYDLY__SHIFT 0x0000000c
+#define MC_HUB_RDREQ_CNTL__BREAK_HDP_DEADLOCK_MASK 0x00000200L
+#define MC_HUB_RDREQ_CNTL__BREAK_HDP_DEADLOCK__SHIFT 0x00000009
+#define MC_HUB_RDREQ_CNTL__DEBUG_REG_MASK 0x0001fc00L
+#define MC_HUB_RDREQ_CNTL__DEBUG_REG__SHIFT 0x0000000a
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL0_MASK 0x00020000L
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL0__SHIFT 0x00000011
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL1_MASK 0x00040000L
+#define MC_HUB_RDREQ_CNTL__DISABLE_SELF_INIT_GBL1__SHIFT 0x00000012
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL0_MASK 0x00000004L
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL0__SHIFT 0x00000002
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL1_MASK 0x00000008L
+#define MC_HUB_RDREQ_CNTL__JUMPAHEAD_GBL1__SHIFT 0x00000003
+#define MC_HUB_RDREQ_CNTL__MCDW_STALL_MODE_MASK 0x00000020L
+#define MC_HUB_RDREQ_CNTL__MCDW_STALL_MODE__SHIFT 0x00000005
+#define MC_HUB_RDREQ_CNTL__MCDX_STALL_MODE_MASK 0x00000040L
+#define MC_HUB_RDREQ_CNTL__MCDX_STALL_MODE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_CNTL__MCDY_STALL_MODE_MASK 0x00000080L
+#define MC_HUB_RDREQ_CNTL__MCDY_STALL_MODE__SHIFT 0x00000007
+#define MC_HUB_RDREQ_CNTL__MCDZ_STALL_MODE_MASK 0x00000100L
+#define MC_HUB_RDREQ_CNTL__MCDZ_STALL_MODE__SHIFT 0x00000008
+#define MC_HUB_RDREQ_CNTL__OVERRIDE_STALL_ENABLE_MASK 0x00000010L
+#define MC_HUB_RDREQ_CNTL__OVERRIDE_STALL_ENABLE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_CNTL__PWRXPRESS_MODE_MASK 0x00080000L
+#define MC_HUB_RDREQ_CNTL__PWRXPRESS_MODE__SHIFT 0x00000013
+#define MC_HUB_RDREQ_CNTL__REMOTE_BLACKOUT_MASK 0x00000001L
+#define MC_HUB_RDREQ_CNTL__REMOTE_BLACKOUT__SHIFT 0x00000000
+#define MC_HUB_RDREQ_CREDITS2__STOR1_PRI_MASK 0x000000ffL
+#define MC_HUB_RDREQ_CREDITS2__STOR1_PRI__SHIFT 0x00000000
+#define MC_HUB_RDREQ_CREDITS__STOR0_MASK 0x00ff0000L
+#define MC_HUB_RDREQ_CREDITS__STOR0__SHIFT 0x00000010
+#define MC_HUB_RDREQ_CREDITS__STOR1_MASK 0xff000000L
+#define MC_HUB_RDREQ_CREDITS__STOR1__SHIFT 0x00000018
+#define MC_HUB_RDREQ_CREDITS__VM0_MASK 0x000000ffL
+#define MC_HUB_RDREQ_CREDITS__VM0__SHIFT 0x00000000
+#define MC_HUB_RDREQ_CREDITS__VM1_MASK 0x0000ff00L
+#define MC_HUB_RDREQ_CREDITS__VM1__SHIFT 0x00000008
+#define MC_HUB_RDREQ_DMIF__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_DMIF__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_DMIF__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_DMIF__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_DMIF__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_DMIF__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_DMIF_LIMIT__ENABLE_MASK 0x00000003L
+#define MC_HUB_RDREQ_DMIF_LIMIT__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_DMIF_LIMIT__LIMIT_COUNT_MASK 0x0000007cL
+#define MC_HUB_RDREQ_DMIF_LIMIT__LIMIT_COUNT__SHIFT 0x00000002
+#define MC_HUB_RDREQ_DMIF__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_DMIF__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_DMIF__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_DMIF__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_DMIF__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_DMIF__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_DMIF__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_GBL0__STALL_THRESHOLD_MASK 0x000000ffL
+#define MC_HUB_RDREQ_GBL0__STALL_THRESHOLD__SHIFT 0x00000000
+#define MC_HUB_RDREQ_GBL1__STALL_THRESHOLD_MASK 0x000000ffL
+#define MC_HUB_RDREQ_GBL1__STALL_THRESHOLD__SHIFT 0x00000000
+#define MC_HUB_RDREQ_HDP__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_HDP__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_HDP__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_HDP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_HDP__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_HDP__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_HDP__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_HDP__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_HDP__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_HDP__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_HDP__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_HDP__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_HDP__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_MCDW__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDW__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDW__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDW__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDW__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDW__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDW__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDW__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDW__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDW__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDW__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDW__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDW__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDW__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDW__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDW__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCDX__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDX__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDX__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDX__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDX__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDX__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDX__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDX__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDX__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDX__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDX__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDX__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDX__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDX__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDX__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDX__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCDY__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDY__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDY__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDY__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDY__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDY__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDY__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDY__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDY__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDY__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDY__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDY__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDY__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDY__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDY__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDY__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCDZ__ASK_CREDITS_MASK 0x0003f800L
+#define MC_HUB_RDREQ_MCDZ__ASK_CREDITS__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCDZ__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_RDREQ_MCDZ__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCDZ__BUS_MASK 0x00000004L
+#define MC_HUB_RDREQ_MCDZ__BUS__SHIFT 0x00000002
+#define MC_HUB_RDREQ_MCDZ__DISPLAY_CREDITS_MASK 0x01fc0000L
+#define MC_HUB_RDREQ_MCDZ__DISPLAY_CREDITS__SHIFT 0x00000012
+#define MC_HUB_RDREQ_MCDZ__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCDZ__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCDZ__LAZY_TIMER_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCDZ__LAZY_TIMER__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCDZ__MAXBURST_MASK 0x00000078L
+#define MC_HUB_RDREQ_MCDZ__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCDZ__STALL_THRESHOLD_MASK 0xfe000000L
+#define MC_HUB_RDREQ_MCDZ__STALL_THRESHOLD__SHIFT 0x00000019
+#define MC_HUB_RDREQ_MCIF__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_MCIF__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_MCIF__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_MCIF__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_MCIF__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_MCIF__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_MCIF__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_MCIF__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_MCIF__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_MCIF__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_MCIF__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_MCIF__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_MCIF__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_RLC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_RLC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_RLC__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_RLC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_RLC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_RLC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_RLC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_RLC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_RLC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_RLC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_RLC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_RLC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_RLC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_SEM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_SEM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_SEM__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_SEM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_SEM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_SEM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_SEM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_SEM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_SEM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_SEM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_SEM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_SEM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_SEM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_SIP__ASK_CREDITS_MASK 0x0000007fL
+#define MC_HUB_RDREQ_SIP__ASK_CREDITS__SHIFT 0x00000000
+#define MC_HUB_RDREQ_SIP__DISPLAY_CREDITS_MASK 0x00007f00L
+#define MC_HUB_RDREQ_SIP__DISPLAY_CREDITS__SHIFT 0x00000008
+#define MC_HUB_RDREQ_SIP__DUMMY_MASK 0x00000080L
+#define MC_HUB_RDREQ_SIP__DUMMY__SHIFT 0x00000007
+#define MC_HUB_RDREQ_SMU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_SMU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_SMU__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_SMU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_SMU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_SMU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_SMU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_SMU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_SMU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_SMU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_SMU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_SMU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_SMU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_STATUS__GBL0_BYPASS_STOR_FULL_MASK 0x00000080L
+#define MC_HUB_RDREQ_STATUS__GBL0_BYPASS_STOR_FULL__SHIFT 0x00000007
+#define MC_HUB_RDREQ_STATUS__GBL0_STOR_FULL_MASK 0x00000040L
+#define MC_HUB_RDREQ_STATUS__GBL0_STOR_FULL__SHIFT 0x00000006
+#define MC_HUB_RDREQ_STATUS__GBL0_VM_FULL_MASK 0x00000020L
+#define MC_HUB_RDREQ_STATUS__GBL0_VM_FULL__SHIFT 0x00000005
+#define MC_HUB_RDREQ_STATUS__GBL1_BYPASS_STOR_FULL_MASK 0x00000400L
+#define MC_HUB_RDREQ_STATUS__GBL1_BYPASS_STOR_FULL__SHIFT 0x0000000a
+#define MC_HUB_RDREQ_STATUS__GBL1_STOR_FULL_MASK 0x00000200L
+#define MC_HUB_RDREQ_STATUS__GBL1_STOR_FULL__SHIFT 0x00000009
+#define MC_HUB_RDREQ_STATUS__GBL1_VM_FULL_MASK 0x00000100L
+#define MC_HUB_RDREQ_STATUS__GBL1_VM_FULL__SHIFT 0x00000008
+#define MC_HUB_RDREQ_STATUS__MCDW_RD_AVAIL_MASK 0x00000002L
+#define MC_HUB_RDREQ_STATUS__MCDW_RD_AVAIL__SHIFT 0x00000001
+#define MC_HUB_RDREQ_STATUS__MCDX_RD_AVAIL_MASK 0x00000004L
+#define MC_HUB_RDREQ_STATUS__MCDX_RD_AVAIL__SHIFT 0x00000002
+#define MC_HUB_RDREQ_STATUS__MCDY_RD_AVAIL_MASK 0x00000008L
+#define MC_HUB_RDREQ_STATUS__MCDY_RD_AVAIL__SHIFT 0x00000003
+#define MC_HUB_RDREQ_STATUS__MCDZ_RD_AVAIL_MASK 0x00000010L
+#define MC_HUB_RDREQ_STATUS__MCDZ_RD_AVAIL__SHIFT 0x00000004
+#define MC_HUB_RDREQ_STATUS__PWRXPRESS_ERR_MASK 0x00000800L
+#define MC_HUB_RDREQ_STATUS__PWRXPRESS_ERR__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_STATUS__SIP_AVAIL_MASK 0x00000001L
+#define MC_HUB_RDREQ_STATUS__SIP_AVAIL__SHIFT 0x00000000
+#define MC_HUB_RDREQ_UMC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_UMC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_UMC__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_UMC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_UMC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_UMC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_UMC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_UMC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_UMC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_UMC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_UMC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_UMC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_UMC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_UVD__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_UVD__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_UVD__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_UVD__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_UVD__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_UVD__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_UVD__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_UVD__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_UVD__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_UVD__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_UVD__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_UVD__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_UVD__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_UVD__VM_BYPASS_MASK 0x00010000L
+#define MC_HUB_RDREQ_UVD__VM_BYPASS__SHIFT 0x00000010
+#define MC_HUB_RDREQ_VCE__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_VCE__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_VCE__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_VCE__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_VCE__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_VCE__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_VCE__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_VCE__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_VCE__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_VCE__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_VCE__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_VCE__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_VCE__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_VCEU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_VCEU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_VCEU__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_VCEU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_VCEU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_VCEU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_VCEU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_VCEU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_VCEU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_VCEU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_VCEU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_VCEU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_VCEU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_VMC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_VMC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_VMC__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_VMC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_VMC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_VMC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_VMC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_VMC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_VMC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_VMC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_VMC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_VMC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_VMC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_HUB_RDREQ_WTM_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_HUB_RDREQ_XDMAM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_RDREQ_XDMAM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_RDREQ_XDMAM__ENABLE_MASK 0x00000001L
+#define MC_HUB_RDREQ_XDMAM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_RDREQ_XDMAM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_RDREQ_XDMAM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_RDREQ_XDMAM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_RDREQ_XDMAM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_RDREQ_XDMAM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_RDREQ_XDMAM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_RDREQ_XDMAM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_RDREQ_XDMAM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_RDREQ_XDMAM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_SHARED_DAGB_DLY__CLI_MASK 0x001f0000L
+#define MC_HUB_SHARED_DAGB_DLY__CLI__SHIFT 0x00000010
+#define MC_HUB_SHARED_DAGB_DLY__DLY_MASK 0x0000003fL
+#define MC_HUB_SHARED_DAGB_DLY__DLY__SHIFT 0x00000000
+#define MC_HUB_SHARED_DAGB_DLY__POS_MASK 0x1f000000L
+#define MC_HUB_SHARED_DAGB_DLY__POS__SHIFT 0x00000018
+#define MC_HUB_WDP_BP__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_BP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_BP__RDRET_MASK 0x0003fffeL
+#define MC_HUB_WDP_BP__RDRET__SHIFT 0x00000001
+#define MC_HUB_WDP_BP__WRREQ_MASK 0x3ffc0000L
+#define MC_HUB_WDP_BP__WRREQ__SHIFT 0x00000012
+#define MC_HUB_WDP_CNTL__DEBUG_REG_MASK 0x00001fe0L
+#define MC_HUB_WDP_CNTL__DEBUG_REG__SHIFT 0x00000005
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL0_MASK 0x00002000L
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL0__SHIFT 0x0000000d
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL1_MASK 0x00004000L
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_GBL1__SHIFT 0x0000000e
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_INTERNAL_MASK 0x00008000L
+#define MC_HUB_WDP_CNTL__DISABLE_SELF_INIT_INTERNAL__SHIFT 0x0000000f
+#define MC_HUB_WDP_CNTL__DISP_WAIT_EOP_MASK 0x00040000L
+#define MC_HUB_WDP_CNTL__DISP_WAIT_EOP__SHIFT 0x00000012
+#define MC_HUB_WDP_CNTL__FAIR_CH_SW_MASK 0x00010000L
+#define MC_HUB_WDP_CNTL__FAIR_CH_SW__SHIFT 0x00000010
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL0_MASK 0x00000002L
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL0__SHIFT 0x00000001
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL1_MASK 0x00000004L
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_GBL1__SHIFT 0x00000002
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_INTERNAL_MASK 0x00000008L
+#define MC_HUB_WDP_CNTL__JUMPAHEAD_INTERNAL__SHIFT 0x00000003
+#define MC_HUB_WDP_CNTL__LCLWRREQ_BYPASS_MASK 0x00020000L
+#define MC_HUB_WDP_CNTL__LCLWRREQ_BYPASS__SHIFT 0x00000011
+#define MC_HUB_WDP_CNTL__MCD_WAIT_EOP_MASK 0x00080000L
+#define MC_HUB_WDP_CNTL__MCD_WAIT_EOP__SHIFT 0x00000013
+#define MC_HUB_WDP_CNTL__OVERRIDE_STALL_ENABLE_MASK 0x00000010L
+#define MC_HUB_WDP_CNTL__OVERRIDE_STALL_ENABLE__SHIFT 0x00000004
+#define MC_HUB_WDP_CNTL__SIP_WAIT_EOP_MASK 0x00100000L
+#define MC_HUB_WDP_CNTL__SIP_WAIT_EOP__SHIFT 0x00000014
+#define MC_HUB_WDP_CREDITS__STOR0_MASK 0x00ff0000L
+#define MC_HUB_WDP_CREDITS__STOR0__SHIFT 0x00000010
+#define MC_HUB_WDP_CREDITS__STOR1_MASK 0xff000000L
+#define MC_HUB_WDP_CREDITS__STOR1__SHIFT 0x00000018
+#define MC_HUB_WDP_CREDITS__VM0_MASK 0x000000ffL
+#define MC_HUB_WDP_CREDITS__VM0__SHIFT 0x00000000
+#define MC_HUB_WDP_CREDITS__VM1_MASK 0x0000ff00L
+#define MC_HUB_WDP_CREDITS__VM1__SHIFT 0x00000008
+#define MC_HUB_WDP_ERR__MGPU1_TARG_SYS_MASK 0x00000001L
+#define MC_HUB_WDP_ERR__MGPU1_TARG_SYS__SHIFT 0x00000000
+#define MC_HUB_WDP_ERR__MGPU2_TARG_SYS_MASK 0x00000002L
+#define MC_HUB_WDP_ERR__MGPU2_TARG_SYS__SHIFT 0x00000001
+#define MC_HUB_WDP_GBL0__LAZY_TIMER_MASK 0x000000f0L
+#define MC_HUB_WDP_GBL0__LAZY_TIMER__SHIFT 0x00000004
+#define MC_HUB_WDP_GBL0__MAXBURST_MASK 0x0000000fL
+#define MC_HUB_WDP_GBL0__MAXBURST__SHIFT 0x00000000
+#define MC_HUB_WDP_GBL0__STALL_MODE_MASK 0x00010000L
+#define MC_HUB_WDP_GBL0__STALL_MODE__SHIFT 0x00000010
+#define MC_HUB_WDP_GBL0__STALL_THRESHOLD_MASK 0x0000ff00L
+#define MC_HUB_WDP_GBL0__STALL_THRESHOLD__SHIFT 0x00000008
+#define MC_HUB_WDP_GBL1__LAZY_TIMER_MASK 0x000000f0L
+#define MC_HUB_WDP_GBL1__LAZY_TIMER__SHIFT 0x00000004
+#define MC_HUB_WDP_GBL1__MAXBURST_MASK 0x0000000fL
+#define MC_HUB_WDP_GBL1__MAXBURST__SHIFT 0x00000000
+#define MC_HUB_WDP_GBL1__STALL_MODE_MASK 0x00010000L
+#define MC_HUB_WDP_GBL1__STALL_MODE__SHIFT 0x00000010
+#define MC_HUB_WDP_GBL1__STALL_THRESHOLD_MASK 0x0000ff00L
+#define MC_HUB_WDP_GBL1__STALL_THRESHOLD__SHIFT 0x00000008
+#define MC_HUB_WDP_HDP__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_HDP__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_HDP__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_HDP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_HDP__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_HDP__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_HDP__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_HDP__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_HDP__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_HDP__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_HDP__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_HDP__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_HDP__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_IH__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_IH__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_IH__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_IH__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_IH__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_IH__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_IH__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_IH__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_IH__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_IH__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_IH__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_IH__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_IH__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_IH__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_IH__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_IH__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_MCDW__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDW__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDW__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDW__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDW__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDW__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDW__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDW__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDW__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDW__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDW__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDW__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDW__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDW__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDW__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDW__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCDX__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDX__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDX__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDX__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDX__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDX__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDX__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDX__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDX__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDX__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDX__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDX__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDX__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDX__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDX__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDX__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCDY__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDY__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDY__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDY__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDY__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDY__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDY__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDY__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDY__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDY__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDY__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDY__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDY__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDY__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDY__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDY__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS_MASK 0x00001f80L
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS__SHIFT 0x00000007
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS_W_MASK 0x7f000000L
+#define MC_HUB_WDP_MCDZ__ASK_CREDITS_W__SHIFT 0x00000018
+#define MC_HUB_WDP_MCDZ__BLACKOUT_EXEMPT_MASK 0x00000002L
+#define MC_HUB_WDP_MCDZ__BLACKOUT_EXEMPT__SHIFT 0x00000001
+#define MC_HUB_WDP_MCDZ__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCDZ__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCDZ__LAZY_TIMER_MASK 0x0001e000L
+#define MC_HUB_WDP_MCDZ__LAZY_TIMER__SHIFT 0x0000000d
+#define MC_HUB_WDP_MCDZ__MAXBURST_MASK 0x00000078L
+#define MC_HUB_WDP_MCDZ__MAXBURST__SHIFT 0x00000003
+#define MC_HUB_WDP_MCDZ__STALL_MODE_MASK 0x00000004L
+#define MC_HUB_WDP_MCDZ__STALL_MODE__SHIFT 0x00000002
+#define MC_HUB_WDP_MCDZ__STALL_THRESHOLD_MASK 0x00fe0000L
+#define MC_HUB_WDP_MCDZ__STALL_THRESHOLD__SHIFT 0x00000011
+#define MC_HUB_WDP_MCIF__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_MCIF__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_MCIF__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_MCIF__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_MCIF__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_MCIF__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_MCIF__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_MCIF__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_MCIF__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_MCIF__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_MCIF__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_MCIF__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_MCIF__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_MGPU2__CID2_MASK 0x000000ffL
+#define MC_HUB_WDP_MGPU2__CID2__SHIFT 0x00000000
+#define MC_HUB_WDP_MGPU__CID_MASK 0x0000ff00L
+#define MC_HUB_WDP_MGPU__CID__SHIFT 0x00000008
+#define MC_HUB_WDP_MGPU__ENABLE_MASK 0x00800000L
+#define MC_HUB_WDP_MGPU__ENABLE__SHIFT 0x00000017
+#define MC_HUB_WDP_MGPU__MGPU_PRIORITY_TIME_MASK 0x007f0000L
+#define MC_HUB_WDP_MGPU__MGPU_PRIORITY_TIME__SHIFT 0x00000010
+#define MC_HUB_WDP_MGPU__OTH_PRIORITY_TIME_MASK 0x7f000000L
+#define MC_HUB_WDP_MGPU__OTH_PRIORITY_TIME__SHIFT 0x00000018
+#define MC_HUB_WDP_MGPU__STOR_MASK 0x000000ffL
+#define MC_HUB_WDP_MGPU__STOR__SHIFT 0x00000000
+#define MC_HUB_WDP_RLC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_RLC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_RLC__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_RLC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_RLC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_RLC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_RLC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_RLC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_RLC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_RLC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_RLC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_RLC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_RLC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SEM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SEM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SEM__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SEM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SEM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SEM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SEM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SEM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SEM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SEM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SEM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SEM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SEM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SH0__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SH0__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SH0__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SH0__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SH0__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SH0__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SH0__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SH0__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SH0__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SH0__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SH0__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SH0__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SH0__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SH1__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SH1__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SH1__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SH1__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SH1__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SH1__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SH1__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SH1__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SH1__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SH1__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SH1__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SH1__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SH1__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_SIP__ASK_CREDITS_MASK 0x000001fcL
+#define MC_HUB_WDP_SIP__ASK_CREDITS__SHIFT 0x00000002
+#define MC_HUB_WDP_SIP__STALL_MODE_MASK 0x00000003L
+#define MC_HUB_WDP_SIP__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WDP_SMU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_SMU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_SMU__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_SMU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_SMU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_SMU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_SMU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_SMU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_SMU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_SMU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_SMU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_SMU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_SMU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_STATUS__GBL0_BYPASS_STOR_FULL_MASK 0x00000080L
+#define MC_HUB_WDP_STATUS__GBL0_BYPASS_STOR_FULL__SHIFT 0x00000007
+#define MC_HUB_WDP_STATUS__GBL0_STOR_FULL_MASK 0x00000040L
+#define MC_HUB_WDP_STATUS__GBL0_STOR_FULL__SHIFT 0x00000006
+#define MC_HUB_WDP_STATUS__GBL0_VM_FULL_MASK 0x00000020L
+#define MC_HUB_WDP_STATUS__GBL0_VM_FULL__SHIFT 0x00000005
+#define MC_HUB_WDP_STATUS__GBL1_BYPASS_STOR_FULL_MASK 0x00000400L
+#define MC_HUB_WDP_STATUS__GBL1_BYPASS_STOR_FULL__SHIFT 0x0000000a
+#define MC_HUB_WDP_STATUS__GBL1_STOR_FULL_MASK 0x00000200L
+#define MC_HUB_WDP_STATUS__GBL1_STOR_FULL__SHIFT 0x00000009
+#define MC_HUB_WDP_STATUS__GBL1_VM_FULL_MASK 0x00000100L
+#define MC_HUB_WDP_STATUS__GBL1_VM_FULL__SHIFT 0x00000008
+#define MC_HUB_WDP_STATUS__MCDW_RD_AVAIL_MASK 0x00000002L
+#define MC_HUB_WDP_STATUS__MCDW_RD_AVAIL__SHIFT 0x00000001
+#define MC_HUB_WDP_STATUS__MCDW_WR_AVAIL_MASK 0x00000800L
+#define MC_HUB_WDP_STATUS__MCDW_WR_AVAIL__SHIFT 0x0000000b
+#define MC_HUB_WDP_STATUS__MCDX_RD_AVAIL_MASK 0x00000004L
+#define MC_HUB_WDP_STATUS__MCDX_RD_AVAIL__SHIFT 0x00000002
+#define MC_HUB_WDP_STATUS__MCDX_WR_AVAIL_MASK 0x00001000L
+#define MC_HUB_WDP_STATUS__MCDX_WR_AVAIL__SHIFT 0x0000000c
+#define MC_HUB_WDP_STATUS__MCDY_RD_AVAIL_MASK 0x00000008L
+#define MC_HUB_WDP_STATUS__MCDY_RD_AVAIL__SHIFT 0x00000003
+#define MC_HUB_WDP_STATUS__MCDY_WR_AVAIL_MASK 0x00002000L
+#define MC_HUB_WDP_STATUS__MCDY_WR_AVAIL__SHIFT 0x0000000d
+#define MC_HUB_WDP_STATUS__MCDZ_RD_AVAIL_MASK 0x00000010L
+#define MC_HUB_WDP_STATUS__MCDZ_RD_AVAIL__SHIFT 0x00000004
+#define MC_HUB_WDP_STATUS__MCDZ_WR_AVAIL_MASK 0x00004000L
+#define MC_HUB_WDP_STATUS__MCDZ_WR_AVAIL__SHIFT 0x0000000e
+#define MC_HUB_WDP_STATUS__SIP_AVAIL_MASK 0x00000001L
+#define MC_HUB_WDP_STATUS__SIP_AVAIL__SHIFT 0x00000000
+#define MC_HUB_WDP_UMC__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_UMC__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_UMC__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_UMC__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_UMC__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_UMC__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_UMC__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_UMC__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_UMC__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_UMC__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_UMC__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_UMC__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_UMC__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_UVD__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_UVD__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_UVD__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_UVD__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_UVD__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_UVD__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_UVD__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_UVD__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_UVD__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_UVD__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_UVD__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_UVD__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_UVD__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_UVD__VM_BYPASS_MASK 0x00010000L
+#define MC_HUB_WDP_UVD__VM_BYPASS__SHIFT 0x00000010
+#define MC_HUB_WDP_VCE__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_VCE__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_VCE__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_VCE__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_VCE__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_VCE__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_VCE__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_VCE__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_VCE__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_VCE__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_VCE__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_VCE__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_VCE__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_VCEU__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_VCEU__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_VCEU__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_VCEU__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_VCEU__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_VCEU__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_VCEU__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_VCEU__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_VCEU__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_VCEU__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_VCEU__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_VCEU__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_VCEU__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_WTM_CNTL__GROUP0_DECREMENT_MASK 0x00000007L
+#define MC_HUB_WDP_WTM_CNTL__GROUP0_DECREMENT__SHIFT 0x00000000
+#define MC_HUB_WDP_WTM_CNTL__GROUP1_DECREMENT_MASK 0x00000038L
+#define MC_HUB_WDP_WTM_CNTL__GROUP1_DECREMENT__SHIFT 0x00000003
+#define MC_HUB_WDP_WTM_CNTL__GROUP2_DECREMENT_MASK 0x000001c0L
+#define MC_HUB_WDP_WTM_CNTL__GROUP2_DECREMENT__SHIFT 0x00000006
+#define MC_HUB_WDP_WTM_CNTL__GROUP3_DECREMENT_MASK 0x00000e00L
+#define MC_HUB_WDP_WTM_CNTL__GROUP3_DECREMENT__SHIFT 0x00000009
+#define MC_HUB_WDP_WTM_CNTL__GROUP4_DECREMENT_MASK 0x00007000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP4_DECREMENT__SHIFT 0x0000000c
+#define MC_HUB_WDP_WTM_CNTL__GROUP5_DECREMENT_MASK 0x00038000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP5_DECREMENT__SHIFT 0x0000000f
+#define MC_HUB_WDP_WTM_CNTL__GROUP6_DECREMENT_MASK 0x001c0000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP6_DECREMENT__SHIFT 0x00000012
+#define MC_HUB_WDP_WTM_CNTL__GROUP7_DECREMENT_MASK 0x00e00000L
+#define MC_HUB_WDP_WTM_CNTL__GROUP7_DECREMENT__SHIFT 0x00000015
+#define MC_HUB_WDP_XDMA__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_XDMA__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_XDMA__BYPASS_AVAIL_OVERRIDE_MASK 0x00010000L
+#define MC_HUB_WDP_XDMA__BYPASS_AVAIL_OVERRIDE__SHIFT 0x00000010
+#define MC_HUB_WDP_XDMA__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_XDMA__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_XDMA__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_XDMA__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_XDMA__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_XDMA__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_XDMAM__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_XDMAM__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_XDMAM__BYPASS_AVAIL_OVERRIDE_MASK 0x00010000L
+#define MC_HUB_WDP_XDMAM__BYPASS_AVAIL_OVERRIDE__SHIFT 0x00000010
+#define MC_HUB_WDP_XDMAM__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_XDMAM__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_XDMAM__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_XDMAM__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_XDMAM__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_XDMAM__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_XDMAM__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_XDMAM__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_XDMAM__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_XDMAM__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_XDMAM__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_XDMA__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_XDMA__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_XDMA__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_XDMA__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_XDMA__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WDP_XDP__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_HUB_WDP_XDP__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_HUB_WDP_XDP__ENABLE_MASK 0x00000001L
+#define MC_HUB_WDP_XDP__ENABLE__SHIFT 0x00000000
+#define MC_HUB_WDP_XDP__LAZY_TIMER_MASK 0x00007800L
+#define MC_HUB_WDP_XDP__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_HUB_WDP_XDP__MAXBURST_MASK 0x00000780L
+#define MC_HUB_WDP_XDP__MAXBURST__SHIFT 0x00000007
+#define MC_HUB_WDP_XDP__PRESCALE_MASK 0x00000006L
+#define MC_HUB_WDP_XDP__PRESCALE__SHIFT 0x00000001
+#define MC_HUB_WDP_XDP__STALL_MODE_MASK 0x00000030L
+#define MC_HUB_WDP_XDP__STALL_MODE__SHIFT 0x00000004
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_HUB_WDP_XDP__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_HUB_WRRET_CNTL__BP_ENABLE_MASK 0x00200000L
+#define MC_HUB_WRRET_CNTL__BP_ENABLE__SHIFT 0x00000015
+#define MC_HUB_WRRET_CNTL__BP_MASK 0x001ffffeL
+#define MC_HUB_WRRET_CNTL__BP__SHIFT 0x00000001
+#define MC_HUB_WRRET_CNTL__DEBUG_REG_MASK 0x3fc00000L
+#define MC_HUB_WRRET_CNTL__DEBUG_REG__SHIFT 0x00000016
+#define MC_HUB_WRRET_CNTL__DISABLE_SELF_INIT_MASK 0x40000000L
+#define MC_HUB_WRRET_CNTL__DISABLE_SELF_INIT__SHIFT 0x0000001e
+#define MC_HUB_WRRET_CNTL__FAIR_CH_SW_MASK 0x80000000L
+#define MC_HUB_WRRET_CNTL__FAIR_CH_SW__SHIFT 0x0000001f
+#define MC_HUB_WRRET_CNTL__JUMPAHEAD_MASK 0x00000001L
+#define MC_HUB_WRRET_CNTL__JUMPAHEAD__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDW__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDW__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDW__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDW__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDX__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDX__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDX__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDX__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDY__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDY__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDY__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDY__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_MCDZ__CREDIT_COUNT_MASK 0x000000feL
+#define MC_HUB_WRRET_MCDZ__CREDIT_COUNT__SHIFT 0x00000001
+#define MC_HUB_WRRET_MCDZ__STALL_MODE_MASK 0x00000001L
+#define MC_HUB_WRRET_MCDZ__STALL_MODE__SHIFT 0x00000000
+#define MC_HUB_WRRET_STATUS__MCDW_AVAIL_MASK 0x00000001L
+#define MC_HUB_WRRET_STATUS__MCDW_AVAIL__SHIFT 0x00000000
+#define MC_HUB_WRRET_STATUS__MCDX_AVAIL_MASK 0x00000002L
+#define MC_HUB_WRRET_STATUS__MCDX_AVAIL__SHIFT 0x00000001
+#define MC_HUB_WRRET_STATUS__MCDY_AVAIL_MASK 0x00000004L
+#define MC_HUB_WRRET_STATUS__MCDY_AVAIL__SHIFT 0x00000002
+#define MC_HUB_WRRET_STATUS__MCDZ_AVAIL_MASK 0x00000008L
+#define MC_HUB_WRRET_STATUS__MCDZ_AVAIL__SHIFT 0x00000003
+#define MC_IMP_CNTL__CAL_PWRON_MASK 0x80000000L
+#define MC_IMP_CNTL__CAL_PWRON__SHIFT 0x0000001f
+#define MC_IMP_CNTL__CAL_VREF_MASK 0x007f0000L
+#define MC_IMP_CNTL__CAL_VREFMODE_MASK 0x00000040L
+#define MC_IMP_CNTL__CAL_VREFMODE__SHIFT 0x00000006
+#define MC_IMP_CNTL__CAL_VREF_SEL_MASK 0x00000020L
+#define MC_IMP_CNTL__CAL_VREF_SEL__SHIFT 0x00000005
+#define MC_IMP_CNTL__CAL_VREF__SHIFT 0x00000010
+#define MC_IMP_CNTL__CAL_WHEN_IDLE_MASK 0x20000000L
+#define MC_IMP_CNTL__CAL_WHEN_IDLE__SHIFT 0x0000001d
+#define MC_IMP_CNTL__CAL_WHEN_REFRESH_MASK 0x40000000L
+#define MC_IMP_CNTL__CAL_WHEN_REFRESH__SHIFT 0x0000001e
+#define MC_IMP_CNTL__CLEAR_TIMEOUT_ERR_MASK 0x00000200L
+#define MC_IMP_CNTL__CLEAR_TIMEOUT_ERR__SHIFT 0x00000009
+#define MC_IMP_CNTL__MEM_IO_SAMPLE_CNT_MASK 0x0000e000L
+#define MC_IMP_CNTL__MEM_IO_SAMPLE_CNT__SHIFT 0x0000000d
+#define MC_IMP_CNTL__MEM_IO_UPDATE_RATE_MASK 0x0000001fL
+#define MC_IMP_CNTL__MEM_IO_UPDATE_RATE__SHIFT 0x00000000
+#define MC_IMP_CNTL__TIMEOUT_ERR_MASK 0x00000100L
+#define MC_IMP_CNTL__TIMEOUT_ERR__SHIFT 0x00000008
+#define MC_IMP_DEBUG__DEBUG_CAL_DONE_MASK 0x80000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_DONE__SHIFT 0x0000001f
+#define MC_IMP_DEBUG__DEBUG_CAL_EN_MASK 0x10000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_EN__SHIFT 0x0000001c
+#define MC_IMP_DEBUG__DEBUG_CAL_INTR_MASK 0x40000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_INTR__SHIFT 0x0000001e
+#define MC_IMP_DEBUG__DEBUG_CAL_START_MASK 0x20000000L
+#define MC_IMP_DEBUG__DEBUG_CAL_START__SHIFT 0x0000001d
+#define MC_IMP_DEBUG__PMVCAL_RESERVED_MASK 0x0fff0000L
+#define MC_IMP_DEBUG__PMVCAL_RESERVED__SHIFT 0x00000010
+#define MC_IMP_DEBUG__TIMEOUT_CNTR_MASK 0x0000ff00L
+#define MC_IMP_DEBUG__TIMEOUT_CNTR__SHIFT 0x00000008
+#define MC_IMP_DEBUG__TSTARTUP_CNTR_MASK 0x000000ffL
+#define MC_IMP_DEBUG__TSTARTUP_CNTR__SHIFT 0x00000000
+#define MC_IMP_DQ_STATUS__CH0_DQ_NSTR_MASK 0x0000ff00L
+#define MC_IMP_DQ_STATUS__CH0_DQ_NSTR__SHIFT 0x00000008
+#define MC_IMP_DQ_STATUS__CH0_DQ_PSTR_MASK 0x000000ffL
+#define MC_IMP_DQ_STATUS__CH0_DQ_PSTR__SHIFT 0x00000000
+#define MC_IMP_DQ_STATUS__CH1_DQ_NSTR_MASK 0xff000000L
+#define MC_IMP_DQ_STATUS__CH1_DQ_NSTR__SHIFT 0x00000018
+#define MC_IMP_DQ_STATUS__CH1_DQ_PSTR_MASK 0x00ff0000L
+#define MC_IMP_DQ_STATUS__CH1_DQ_PSTR__SHIFT 0x00000010
+#define MC_IMP_STATUS__NSTR_ACCUM_VAL_MASK 0xff000000L
+#define MC_IMP_STATUS__NSTR_ACCUM_VAL__SHIFT 0x00000018
+#define MC_IMP_STATUS__NSTR_CAL_MASK 0x00ff0000L
+#define MC_IMP_STATUS__NSTR_CAL__SHIFT 0x00000010
+#define MC_IMP_STATUS__PSTR_ACCUM_VAL_MASK 0x0000ff00L
+#define MC_IMP_STATUS__PSTR_ACCUM_VAL__SHIFT 0x00000008
+#define MC_IMP_STATUS__PSTR_CAL_MASK 0x000000ffL
+#define MC_IMP_STATUS__PSTR_CAL__SHIFT 0x00000000
+#define MC_IO_APHY_STR_CNTL_D0__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_APHY_STR_CNTL_D0__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_A_STR_MASK 0x10000000L
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_A_STR__SHIFT 0x0000001c
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_D_RD_STR_MASK 0x20000000L
+#define MC_IO_APHY_STR_CNTL_D0__LOAD_D_RD_STR__SHIFT 0x0000001d
+#define MC_IO_APHY_STR_CNTL_D0__NSTR_OFF_A_MASK 0x00000fc0L
+#define MC_IO_APHY_STR_CNTL_D0__NSTR_OFF_A__SHIFT 0x00000006
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_A_MASK 0x0000003fL
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_A__SHIFT 0x00000000
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_D_RD_MASK 0x0003f000L
+#define MC_IO_APHY_STR_CNTL_D0__PSTR_OFF_D_RD__SHIFT 0x0000000c
+#define MC_IO_APHY_STR_CNTL_D0__USE_A_CAL_MASK 0x01000000L
+#define MC_IO_APHY_STR_CNTL_D0__USE_A_CAL__SHIFT 0x00000018
+#define MC_IO_APHY_STR_CNTL_D0__USE_D_RD_CAL_MASK 0x02000000L
+#define MC_IO_APHY_STR_CNTL_D0__USE_D_RD_CAL__SHIFT 0x00000019
+#define MC_IO_APHY_STR_CNTL_D1__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_APHY_STR_CNTL_D1__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_A_STR_MASK 0x10000000L
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_A_STR__SHIFT 0x0000001c
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_D_RD_STR_MASK 0x20000000L
+#define MC_IO_APHY_STR_CNTL_D1__LOAD_D_RD_STR__SHIFT 0x0000001d
+#define MC_IO_APHY_STR_CNTL_D1__NSTR_OFF_A_MASK 0x00000fc0L
+#define MC_IO_APHY_STR_CNTL_D1__NSTR_OFF_A__SHIFT 0x00000006
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_A_MASK 0x0000003fL
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_A__SHIFT 0x00000000
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_D_RD_MASK 0x0003f000L
+#define MC_IO_APHY_STR_CNTL_D1__PSTR_OFF_D_RD__SHIFT 0x0000000c
+#define MC_IO_APHY_STR_CNTL_D1__USE_A_CAL_MASK 0x01000000L
+#define MC_IO_APHY_STR_CNTL_D1__USE_A_CAL__SHIFT 0x00000018
+#define MC_IO_APHY_STR_CNTL_D1__USE_D_RD_CAL_MASK 0x02000000L
+#define MC_IO_APHY_STR_CNTL_D1__USE_D_RD_CAL__SHIFT 0x00000019
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B0_MASK 0x000000ffL
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B1_MASK 0x0000ff00L
+#define MC_IO_CDRCNTL1_D0__DQ_RXPHASE_B1__SHIFT 0x00000008
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B0_MASK 0x00ff0000L
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B0__SHIFT 0x00000010
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B1_MASK 0xff000000L
+#define MC_IO_CDRCNTL1_D0__WCDR_TXPHASE_B1__SHIFT 0x00000018
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B0_MASK 0x000000ffL
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B1_MASK 0x0000ff00L
+#define MC_IO_CDRCNTL1_D1__DQ_RXPHASE_B1__SHIFT 0x00000008
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B0_MASK 0x00ff0000L
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B0__SHIFT 0x00000010
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B1_MASK 0xff000000L
+#define MC_IO_CDRCNTL1_D1__WCDR_TXPHASE_B1__SHIFT 0x00000018
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL0_MASK 0x00000001L
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL1_MASK 0x00000002L
+#define MC_IO_CDRCNTL2_D0__CDR_FB_SEL1__SHIFT 0x00000001
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR0_MASK 0x00000004L
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR0__SHIFT 0x00000002
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR1_MASK 0x00000008L
+#define MC_IO_CDRCNTL2_D0__EDC_RXEN_OVR1__SHIFT 0x00000003
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS0_MASK 0x00000010L
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS0__SHIFT 0x00000004
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS1_MASK 0x00000020L
+#define MC_IO_CDRCNTL2_D0__TXCDRBYPASS1__SHIFT 0x00000005
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR0_MASK 0x00000040L
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR0__SHIFT 0x00000006
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR1_MASK 0x00000080L
+#define MC_IO_CDRCNTL2_D0__WCK_RXEN_OVR1__SHIFT 0x00000007
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL0_MASK 0x00000001L
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL0__SHIFT 0x00000000
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL1_MASK 0x00000002L
+#define MC_IO_CDRCNTL2_D1__CDR_FB_SEL1__SHIFT 0x00000001
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR0_MASK 0x00000004L
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR0__SHIFT 0x00000002
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR1_MASK 0x00000008L
+#define MC_IO_CDRCNTL2_D1__EDC_RXEN_OVR1__SHIFT 0x00000003
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS0_MASK 0x00000010L
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS0__SHIFT 0x00000004
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS1_MASK 0x00000020L
+#define MC_IO_CDRCNTL2_D1__TXCDRBYPASS1__SHIFT 0x00000005
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR0_MASK 0x00000040L
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR0__SHIFT 0x00000006
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR1_MASK 0x00000080L
+#define MC_IO_CDRCNTL2_D1__WCK_RXEN_OVR1__SHIFT 0x00000007
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B0_MASK 0x00400000L
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B0__SHIFT 0x00000016
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B1_MASK 0x00800000L
+#define MC_IO_CDRCNTL_D0__DQRXCDREN_B1__SHIFT 0x00000017
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B0_MASK 0x10000000L
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B0__SHIFT 0x0000001c
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B1_MASK 0x20000000L
+#define MC_IO_CDRCNTL_D0__DQRXSEL_B1__SHIFT 0x0000001d
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B0_MASK 0x00100000L
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B0__SHIFT 0x00000014
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B1_MASK 0x00200000L
+#define MC_IO_CDRCNTL_D0__DQTXCDREN_B1__SHIFT 0x00000015
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B0_MASK 0x40000000L
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B0__SHIFT 0x0000001e
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B1_MASK 0x80000000L
+#define MC_IO_CDRCNTL_D0__DQTXSEL_B1__SHIFT 0x0000001f
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B01_MASK 0x00000400L
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B01__SHIFT 0x0000000a
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B23_MASK 0x00000800L
+#define MC_IO_CDRCNTL_D0__RXCDRBYPASS_B23__SHIFT 0x0000000b
+#define MC_IO_CDRCNTL_D0__RXCDREN_B01_MASK 0x00000100L
+#define MC_IO_CDRCNTL_D0__RXCDREN_B01__SHIFT 0x00000008
+#define MC_IO_CDRCNTL_D0__RXCDREN_B23_MASK 0x00000200L
+#define MC_IO_CDRCNTL_D0__RXCDREN_B23__SHIFT 0x00000009
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B01_MASK 0x0000f000L
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B01__SHIFT 0x0000000c
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B23_MASK 0x000f0000L
+#define MC_IO_CDRCNTL_D0__RXPHASE1_B23__SHIFT 0x00000010
+#define MC_IO_CDRCNTL_D0__RXPHASE_B01_MASK 0x0000000fL
+#define MC_IO_CDRCNTL_D0__RXPHASE_B01__SHIFT 0x00000000
+#define MC_IO_CDRCNTL_D0__RXPHASE_B23_MASK 0x000000f0L
+#define MC_IO_CDRCNTL_D0__RXPHASE_B23__SHIFT 0x00000004
+#define MC_IO_CDRCNTL_D0__WCDREDC_B0_MASK 0x04000000L
+#define MC_IO_CDRCNTL_D0__WCDREDC_B0__SHIFT 0x0000001a
+#define MC_IO_CDRCNTL_D0__WCDREDC_B1_MASK 0x08000000L
+#define MC_IO_CDRCNTL_D0__WCDREDC_B1__SHIFT 0x0000001b
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B0_MASK 0x01000000L
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B0__SHIFT 0x00000018
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B1_MASK 0x02000000L
+#define MC_IO_CDRCNTL_D0__WCDRRXCDREN_B1__SHIFT 0x00000019
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B0_MASK 0x00400000L
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B0__SHIFT 0x00000016
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B1_MASK 0x00800000L
+#define MC_IO_CDRCNTL_D1__DQRXCDREN_B1__SHIFT 0x00000017
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B0_MASK 0x10000000L
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B0__SHIFT 0x0000001c
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B1_MASK 0x20000000L
+#define MC_IO_CDRCNTL_D1__DQRXSEL_B1__SHIFT 0x0000001d
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B0_MASK 0x00100000L
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B0__SHIFT 0x00000014
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B1_MASK 0x00200000L
+#define MC_IO_CDRCNTL_D1__DQTXCDREN_B1__SHIFT 0x00000015
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B0_MASK 0x40000000L
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B0__SHIFT 0x0000001e
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B1_MASK 0x80000000L
+#define MC_IO_CDRCNTL_D1__DQTXSEL_B1__SHIFT 0x0000001f
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B01_MASK 0x00000400L
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B01__SHIFT 0x0000000a
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B23_MASK 0x00000800L
+#define MC_IO_CDRCNTL_D1__RXCDRBYPASS_B23__SHIFT 0x0000000b
+#define MC_IO_CDRCNTL_D1__RXCDREN_B01_MASK 0x00000100L
+#define MC_IO_CDRCNTL_D1__RXCDREN_B01__SHIFT 0x00000008
+#define MC_IO_CDRCNTL_D1__RXCDREN_B23_MASK 0x00000200L
+#define MC_IO_CDRCNTL_D1__RXCDREN_B23__SHIFT 0x00000009
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B01_MASK 0x0000f000L
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B01__SHIFT 0x0000000c
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B23_MASK 0x000f0000L
+#define MC_IO_CDRCNTL_D1__RXPHASE1_B23__SHIFT 0x00000010
+#define MC_IO_CDRCNTL_D1__RXPHASE_B01_MASK 0x0000000fL
+#define MC_IO_CDRCNTL_D1__RXPHASE_B01__SHIFT 0x00000000
+#define MC_IO_CDRCNTL_D1__RXPHASE_B23_MASK 0x000000f0L
+#define MC_IO_CDRCNTL_D1__RXPHASE_B23__SHIFT 0x00000004
+#define MC_IO_CDRCNTL_D1__WCDREDC_B0_MASK 0x04000000L
+#define MC_IO_CDRCNTL_D1__WCDREDC_B0__SHIFT 0x0000001a
+#define MC_IO_CDRCNTL_D1__WCDREDC_B1_MASK 0x08000000L
+#define MC_IO_CDRCNTL_D1__WCDREDC_B1__SHIFT 0x0000001b
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B0_MASK 0x01000000L
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B0__SHIFT 0x00000018
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B1_MASK 0x02000000L
+#define MC_IO_CDRCNTL_D1__WCDRRXCDREN_B1__SHIFT 0x00000019
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ACMD_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRH_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_ADDRL_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CK_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_CMD_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DBI_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ0_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQ1_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB0L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB1L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB2L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3H_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_DQB3L_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_EDC_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_100__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_100__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_100__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_100__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_100__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_100__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_100__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_100__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_101__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_101__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_101__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_101__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_101__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_101__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_101__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_101__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_102__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_102__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_102__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_102__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_102__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_102__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_102__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_102__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_103__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_103__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_103__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_103__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_103__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_103__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_103__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_103__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_104__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_104__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_104__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_104__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_104__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_104__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_104__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_104__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_105__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_105__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_105__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_105__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_105__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_105__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_105__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_105__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_106__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_106__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_106__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_106__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_106__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_106__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_106__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_106__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_107__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_107__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_107__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_107__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_107__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_107__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_107__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_107__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_108__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_108__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_108__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_108__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_108__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_108__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_108__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_108__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_109__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_109__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_109__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_109__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_109__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_109__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_109__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_109__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_10__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_10__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_10__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_10__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_10__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_10__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_10__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_10__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_110__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_110__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_110__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_110__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_110__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_110__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_110__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_110__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_111__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_111__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_111__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_111__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_111__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_111__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_111__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_111__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_112__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_112__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_112__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_112__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_112__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_112__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_112__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_112__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_113__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_113__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_113__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_113__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_113__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_113__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_113__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_113__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_114__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_114__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_114__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_114__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_114__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_114__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_114__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_114__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_115__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_115__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_115__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_115__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_115__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_115__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_115__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_115__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_116__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_116__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_116__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_116__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_116__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_116__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_116__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_116__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_117__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_117__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_117__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_117__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_117__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_117__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_117__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_117__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_118__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_118__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_118__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_118__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_118__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_118__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_118__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_118__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_119__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_119__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_119__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_119__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_119__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_119__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_119__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_119__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_11__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_11__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_11__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_11__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_11__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_11__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_11__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_11__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_120__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_120__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_120__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_120__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_120__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_120__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_120__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_120__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_121__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_121__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_121__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_121__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_121__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_121__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_121__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_121__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_122__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_122__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_122__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_122__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_122__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_122__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_122__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_122__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_123__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_123__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_123__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_123__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_123__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_123__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_123__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_123__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_124__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_124__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_124__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_124__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_124__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_124__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_124__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_124__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_125__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_125__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_125__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_125__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_125__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_125__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_125__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_125__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_126__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_126__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_126__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_126__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_126__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_126__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_126__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_126__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_127__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_127__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_127__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_127__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_127__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_127__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_127__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_127__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_128__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_128__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_128__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_128__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_128__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_128__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_128__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_128__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_129__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_129__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_129__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_129__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_129__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_129__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_129__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_129__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_12__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_12__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_12__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_12__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_12__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_12__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_12__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_12__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_130__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_130__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_130__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_130__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_130__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_130__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_130__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_130__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_131__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_131__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_131__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_131__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_131__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_131__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_131__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_131__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_132__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_132__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_132__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_132__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_132__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_132__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_132__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_132__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_133__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_133__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_133__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_133__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_133__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_133__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_133__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_133__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_134__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_134__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_134__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_134__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_134__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_134__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_134__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_134__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_135__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_135__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_135__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_135__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_135__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_135__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_135__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_135__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_136__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_136__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_136__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_136__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_136__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_136__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_136__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_136__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_137__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_137__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_137__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_137__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_137__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_137__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_137__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_137__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_138__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_138__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_138__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_138__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_138__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_138__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_138__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_138__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_139__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_139__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_139__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_139__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_139__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_139__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_139__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_139__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_13__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_13__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_13__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_13__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_13__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_13__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_13__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_13__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_140__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_140__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_140__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_140__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_140__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_140__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_140__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_140__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_141__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_141__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_141__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_141__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_141__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_141__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_141__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_141__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_142__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_142__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_142__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_142__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_142__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_142__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_142__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_142__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_143__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_143__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_143__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_143__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_143__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_143__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_143__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_143__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_144__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_144__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_144__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_144__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_144__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_144__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_144__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_144__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_145__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_145__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_145__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_145__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_145__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_145__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_145__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_145__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_146__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_146__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_146__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_146__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_146__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_146__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_146__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_146__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_147__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_147__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_147__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_147__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_147__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_147__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_147__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_147__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_148__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_148__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_148__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_148__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_148__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_148__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_148__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_148__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_149__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_149__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_149__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_149__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_149__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_149__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_149__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_149__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_14__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_14__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_14__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_14__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_14__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_14__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_14__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_14__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_150__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_150__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_150__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_150__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_150__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_150__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_150__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_150__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_151__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_151__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_151__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_151__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_151__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_151__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_151__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_151__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_152__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_152__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_152__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_152__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_152__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_152__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_152__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_152__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_153__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_153__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_153__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_153__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_153__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_153__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_153__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_153__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_154__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_154__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_154__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_154__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_154__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_154__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_154__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_154__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_155__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_155__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_155__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_155__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_155__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_155__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_155__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_155__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_156__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_156__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_156__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_156__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_156__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_156__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_156__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_156__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_157__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_157__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_157__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_157__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_157__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_157__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_157__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_157__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_158__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_158__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_158__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_158__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_158__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_158__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_158__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_158__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_159__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_159__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_159__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_159__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_159__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_159__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_159__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_159__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_15__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_15__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_15__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_15__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_15__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_15__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_15__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_15__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_16__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_16__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_16__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_16__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_16__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_16__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_16__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_16__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_17__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_17__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_17__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_17__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_17__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_17__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_17__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_17__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_18__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_18__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_18__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_18__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_18__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_18__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_18__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_18__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_19__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_19__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_19__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_19__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_19__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_19__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_19__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_19__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_20__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_20__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_20__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_20__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_20__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_20__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_20__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_20__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_21__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_21__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_21__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_21__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_21__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_21__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_21__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_21__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_22__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_22__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_22__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_22__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_22__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_22__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_22__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_22__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_23__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_23__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_23__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_23__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_23__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_23__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_23__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_23__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_24__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_24__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_24__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_24__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_24__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_24__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_24__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_24__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_25__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_25__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_25__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_25__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_25__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_25__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_25__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_25__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_26__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_26__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_26__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_26__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_26__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_26__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_26__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_26__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_27__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_27__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_27__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_27__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_27__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_27__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_27__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_27__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_28__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_28__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_28__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_28__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_28__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_28__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_28__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_28__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_29__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_29__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_29__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_29__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_29__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_29__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_29__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_29__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_2__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_2__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_2__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_2__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_2__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_2__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_2__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_2__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_30__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_30__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_30__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_30__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_30__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_30__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_30__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_30__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_31__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_31__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_31__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_31__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_31__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_31__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_31__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_31__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_32__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_32__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_32__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_32__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_32__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_32__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_32__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_32__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_33__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_33__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_33__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_33__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_33__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_33__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_33__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_33__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_34__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_34__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_34__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_34__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_34__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_34__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_34__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_34__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_35__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_35__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_35__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_35__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_35__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_35__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_35__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_35__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_36__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_36__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_36__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_36__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_36__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_36__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_36__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_36__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_37__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_37__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_37__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_37__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_37__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_37__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_37__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_37__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_38__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_38__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_38__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_38__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_38__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_38__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_38__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_38__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_39__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_39__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_39__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_39__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_39__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_39__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_39__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_39__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_3__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_3__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_3__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_3__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_3__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_3__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_3__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_3__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_40__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_40__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_40__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_40__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_40__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_40__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_40__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_40__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_41__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_41__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_41__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_41__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_41__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_41__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_41__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_41__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_42__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_42__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_42__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_42__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_42__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_42__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_42__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_42__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_43__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_43__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_43__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_43__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_43__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_43__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_43__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_43__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_44__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_44__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_44__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_44__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_44__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_44__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_44__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_44__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_45__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_45__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_45__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_45__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_45__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_45__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_45__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_45__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_46__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_46__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_46__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_46__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_46__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_46__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_46__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_46__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_47__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_47__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_47__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_47__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_47__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_47__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_47__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_47__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_48__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_48__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_48__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_48__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_48__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_48__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_48__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_48__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_49__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_49__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_49__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_49__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_49__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_49__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_49__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_49__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_4__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_4__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_4__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_4__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_4__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_4__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_4__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_4__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_50__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_50__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_50__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_50__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_50__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_50__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_50__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_50__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_51__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_51__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_51__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_51__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_51__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_51__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_51__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_51__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_52__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_52__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_52__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_52__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_52__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_52__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_52__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_52__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_53__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_53__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_53__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_53__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_53__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_53__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_53__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_53__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_54__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_54__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_54__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_54__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_54__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_54__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_54__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_54__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_55__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_55__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_55__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_55__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_55__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_55__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_55__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_55__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_56__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_56__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_56__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_56__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_56__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_56__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_56__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_56__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_57__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_57__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_57__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_57__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_57__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_57__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_57__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_57__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_58__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_58__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_58__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_58__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_58__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_58__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_58__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_58__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_59__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_59__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_59__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_59__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_59__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_59__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_59__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_59__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_5__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_5__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_5__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_5__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_5__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_5__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_5__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_5__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_60__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_60__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_60__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_60__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_60__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_60__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_60__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_60__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_61__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_61__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_61__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_61__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_61__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_61__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_61__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_61__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_62__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_62__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_62__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_62__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_62__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_62__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_62__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_62__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_63__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_63__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_63__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_63__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_63__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_63__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_63__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_63__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_64__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_64__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_64__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_64__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_64__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_64__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_64__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_64__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_65__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_65__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_65__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_65__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_65__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_65__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_65__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_65__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_66__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_66__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_66__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_66__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_66__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_66__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_66__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_66__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_67__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_67__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_67__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_67__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_67__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_67__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_67__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_67__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_68__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_68__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_68__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_68__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_68__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_68__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_68__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_68__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_69__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_69__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_69__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_69__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_69__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_69__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_69__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_69__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_6__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_6__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_6__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_6__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_6__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_6__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_6__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_6__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_70__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_70__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_70__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_70__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_70__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_70__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_70__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_70__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_71__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_71__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_71__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_71__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_71__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_71__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_71__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_71__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_72__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_72__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_72__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_72__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_72__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_72__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_72__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_72__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_73__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_73__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_73__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_73__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_73__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_73__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_73__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_73__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_74__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_74__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_74__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_74__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_74__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_74__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_74__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_74__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_75__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_75__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_75__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_75__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_75__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_75__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_75__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_75__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_76__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_76__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_76__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_76__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_76__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_76__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_76__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_76__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_77__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_77__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_77__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_77__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_77__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_77__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_77__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_77__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_78__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_78__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_78__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_78__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_78__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_78__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_78__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_78__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_79__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_79__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_79__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_79__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_79__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_79__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_79__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_79__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_7__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_7__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_7__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_7__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_7__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_7__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_7__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_7__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_80__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_80__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_80__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_80__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_80__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_80__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_80__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_80__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_81__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_81__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_81__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_81__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_81__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_81__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_81__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_81__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_82__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_82__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_82__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_82__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_82__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_82__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_82__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_82__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_83__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_83__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_83__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_83__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_83__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_83__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_83__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_83__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_84__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_84__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_84__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_84__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_84__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_84__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_84__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_84__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_85__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_85__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_85__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_85__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_85__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_85__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_85__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_85__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_86__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_86__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_86__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_86__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_86__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_86__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_86__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_86__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_87__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_87__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_87__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_87__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_87__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_87__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_87__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_87__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_88__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_88__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_88__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_88__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_88__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_88__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_88__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_88__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_89__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_89__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_89__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_89__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_89__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_89__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_89__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_89__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_8__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_8__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_8__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_8__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_8__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_8__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_8__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_8__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_90__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_90__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_90__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_90__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_90__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_90__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_90__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_90__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_91__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_91__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_91__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_91__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_91__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_91__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_91__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_91__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_92__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_92__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_92__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_92__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_92__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_92__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_92__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_92__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_93__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_93__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_93__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_93__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_93__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_93__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_93__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_93__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_94__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_94__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_94__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_94__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_94__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_94__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_94__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_94__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_95__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_95__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_95__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_95__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_95__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_95__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_95__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_95__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_96__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_96__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_96__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_96__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_96__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_96__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_96__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_96__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_97__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_97__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_97__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_97__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_97__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_97__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_97__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_97__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_98__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_98__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_98__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_98__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_98__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_98__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_98__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_98__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_99__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_99__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_99__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_99__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_99__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_99__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_99__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_99__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_UP_9__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_UP_9__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_UP_9__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_UP_9__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_UP_9__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_UP_9__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_UP_9__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_UP_9__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CDR_PHSIZE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_DYN_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_EQ_PM_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCDR_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_CLKSEL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_MISC_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_MISC_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_OFSCAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_EQ_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_RX_VREF_CAL_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PD_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXBST_PU_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXPHASE_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXSLF_D0__VALUE3__SHIFT 0x00000018
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE0_MASK 0x000000ffL
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE0__SHIFT 0x00000000
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE1_MASK 0x0000ff00L
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE1__SHIFT 0x00000008
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE2_MASK 0x00ff0000L
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE2__SHIFT 0x00000010
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE3_MASK 0xff000000L
+#define MC_IO_DEBUG_WCK_TXSLF_D1__VALUE3__SHIFT 0x00000018
+#define MC_IO_DPHY_STR_CNTL_D0__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_DPHY_STR_CNTL_D0__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_D_STR_MASK 0x10000000L
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_D_STR__SHIFT 0x0000001c
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_S_STR_MASK 0x20000000L
+#define MC_IO_DPHY_STR_CNTL_D0__LOAD_S_STR__SHIFT 0x0000001d
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_D_MASK 0x00000fc0L
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_D__SHIFT 0x00000006
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_S_MASK 0x00fc0000L
+#define MC_IO_DPHY_STR_CNTL_D0__NSTR_OFF_S__SHIFT 0x00000012
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_D_MASK 0x0000003fL
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_D__SHIFT 0x00000000
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_S_MASK 0x0003f000L
+#define MC_IO_DPHY_STR_CNTL_D0__PSTR_OFF_S__SHIFT 0x0000000c
+#define MC_IO_DPHY_STR_CNTL_D0__USE_D_CAL_MASK 0x01000000L
+#define MC_IO_DPHY_STR_CNTL_D0__USE_D_CAL__SHIFT 0x00000018
+#define MC_IO_DPHY_STR_CNTL_D0__USE_S_CAL_MASK 0x02000000L
+#define MC_IO_DPHY_STR_CNTL_D0__USE_S_CAL__SHIFT 0x00000019
+#define MC_IO_DPHY_STR_CNTL_D1__CAL_SEL_MASK 0x0c000000L
+#define MC_IO_DPHY_STR_CNTL_D1__CAL_SEL__SHIFT 0x0000001a
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_D_STR_MASK 0x10000000L
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_D_STR__SHIFT 0x0000001c
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_S_STR_MASK 0x20000000L
+#define MC_IO_DPHY_STR_CNTL_D1__LOAD_S_STR__SHIFT 0x0000001d
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_D_MASK 0x00000fc0L
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_D__SHIFT 0x00000006
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_S_MASK 0x00fc0000L
+#define MC_IO_DPHY_STR_CNTL_D1__NSTR_OFF_S__SHIFT 0x00000012
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_D_MASK 0x0000003fL
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_D__SHIFT 0x00000000
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_S_MASK 0x0003f000L
+#define MC_IO_DPHY_STR_CNTL_D1__PSTR_OFF_S__SHIFT 0x0000000c
+#define MC_IO_DPHY_STR_CNTL_D1__USE_D_CAL_MASK 0x01000000L
+#define MC_IO_DPHY_STR_CNTL_D1__USE_D_CAL__SHIFT 0x00000018
+#define MC_IO_DPHY_STR_CNTL_D1__USE_S_CAL_MASK 0x02000000L
+#define MC_IO_DPHY_STR_CNTL_D1__USE_S_CAL__SHIFT 0x00000019
+#define MC_IO_PAD_CNTL__ATBEN_MASK 0x3f000000L
+#define MC_IO_PAD_CNTL__ATBEN__SHIFT 0x00000018
+#define MC_IO_PAD_CNTL__ATBSEL_D0_MASK 0x80000000L
+#define MC_IO_PAD_CNTL__ATBSEL_D0__SHIFT 0x0000001f
+#define MC_IO_PAD_CNTL__ATBSEL_D1_MASK 0x40000000L
+#define MC_IO_PAD_CNTL__ATBSEL_D1__SHIFT 0x0000001e
+#define MC_IO_PAD_CNTL__ATBSEL_MASK 0x00f00000L
+#define MC_IO_PAD_CNTL__ATBSEL__SHIFT 0x00000014
+#define MC_IO_PAD_CNTL_D0__CK_AUTO_EN_MASK 0x00100000L
+#define MC_IO_PAD_CNTL_D0__CK_AUTO_EN__SHIFT 0x00000014
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_N_MASK 0x00c00000L
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_N__SHIFT 0x00000016
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_P_MASK 0x03000000L
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_P__SHIFT 0x00000018
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_SEL_MASK 0x00200000L
+#define MC_IO_PAD_CNTL_D0__CK_DELAY_SEL__SHIFT 0x00000015
+#define MC_IO_PAD_CNTL_D0__DELAY_ADR_SYNC_MASK 0x00000010L
+#define MC_IO_PAD_CNTL_D0__DELAY_ADR_SYNC__SHIFT 0x00000004
+#define MC_IO_PAD_CNTL_D0__DELAY_CLK_SYNC_MASK 0x00000004L
+#define MC_IO_PAD_CNTL_D0__DELAY_CLK_SYNC__SHIFT 0x00000002
+#define MC_IO_PAD_CNTL_D0__DELAY_CMD_SYNC_MASK 0x00000008L
+#define MC_IO_PAD_CNTL_D0__DELAY_CMD_SYNC__SHIFT 0x00000003
+#define MC_IO_PAD_CNTL_D0__DIFF_STR_MASK 0x20000000L
+#define MC_IO_PAD_CNTL_D0__DIFF_STR__SHIFT 0x0000001d
+#define MC_IO_PAD_CNTL_D0__DISABLE_ADR_MASK 0x00002000L
+#define MC_IO_PAD_CNTL_D0__DISABLE_ADR__SHIFT 0x0000000d
+#define MC_IO_PAD_CNTL_D0__DISABLE_CMD_MASK 0x00001000L
+#define MC_IO_PAD_CNTL_D0__DISABLE_CMD__SHIFT 0x0000000c
+#define MC_IO_PAD_CNTL_D0__EN_RD_STR_DLY_MASK 0x00000800L
+#define MC_IO_PAD_CNTL_D0__EN_RD_STR_DLY__SHIFT 0x0000000b
+#define MC_IO_PAD_CNTL_D0__FORCE_EN_RD_STR_MASK 0x00000400L
+#define MC_IO_PAD_CNTL_D0__FORCE_EN_RD_STR__SHIFT 0x0000000a
+#define MC_IO_PAD_CNTL_D0__GDDR_PWRON_MASK 0x40000000L
+#define MC_IO_PAD_CNTL_D0__GDDR_PWRON__SHIFT 0x0000001e
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_ADR_MASK 0x00000200L
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_ADR__SHIFT 0x00000009
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CLK_MASK 0x00000080L
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CLK__SHIFT 0x00000007
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CMD_MASK 0x00000100L
+#define MC_IO_PAD_CNTL_D0__MEM_FALL_OUT_CMD__SHIFT 0x00000008
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CKE_MASK 0x08000000L
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CKE__SHIFT 0x0000001b
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CLK_MASK 0x80000000L
+#define MC_IO_PAD_CNTL_D0__TXPWROFF_CLK__SHIFT 0x0000001f
+#define MC_IO_PAD_CNTL_D0__UNI_STR_MASK 0x10000000L
+#define MC_IO_PAD_CNTL_D0__UNI_STR__SHIFT 0x0000001c
+#define MC_IO_PAD_CNTL_D0__VREFI_EN_MASK 0x00004000L
+#define MC_IO_PAD_CNTL_D0__VREFI_EN__SHIFT 0x0000000e
+#define MC_IO_PAD_CNTL_D0__VREFI_SEL_MASK 0x000f8000L
+#define MC_IO_PAD_CNTL_D0__VREFI_SEL__SHIFT 0x0000000f
+#define MC_IO_PAD_CNTL_D1__CK_AUTO_EN_MASK 0x00100000L
+#define MC_IO_PAD_CNTL_D1__CK_AUTO_EN__SHIFT 0x00000014
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_N_MASK 0x00c00000L
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_N__SHIFT 0x00000016
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_P_MASK 0x03000000L
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_P__SHIFT 0x00000018
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_SEL_MASK 0x00200000L
+#define MC_IO_PAD_CNTL_D1__CK_DELAY_SEL__SHIFT 0x00000015
+#define MC_IO_PAD_CNTL_D1__DELAY_ADR_SYNC_MASK 0x00000010L
+#define MC_IO_PAD_CNTL_D1__DELAY_ADR_SYNC__SHIFT 0x00000004
+#define MC_IO_PAD_CNTL_D1__DELAY_CLK_SYNC_MASK 0x00000004L
+#define MC_IO_PAD_CNTL_D1__DELAY_CLK_SYNC__SHIFT 0x00000002
+#define MC_IO_PAD_CNTL_D1__DELAY_CMD_SYNC_MASK 0x00000008L
+#define MC_IO_PAD_CNTL_D1__DELAY_CMD_SYNC__SHIFT 0x00000003
+#define MC_IO_PAD_CNTL_D1__DELAY_DATA_SYNC_MASK 0x00000001L
+#define MC_IO_PAD_CNTL_D1__DELAY_DATA_SYNC__SHIFT 0x00000000
+#define MC_IO_PAD_CNTL_D1__DELAY_STR_SYNC_MASK 0x00000002L
+#define MC_IO_PAD_CNTL_D1__DELAY_STR_SYNC__SHIFT 0x00000001
+#define MC_IO_PAD_CNTL_D1__DIFF_STR_MASK 0x20000000L
+#define MC_IO_PAD_CNTL_D1__DIFF_STR__SHIFT 0x0000001d
+#define MC_IO_PAD_CNTL_D1__DISABLE_ADR_MASK 0x00002000L
+#define MC_IO_PAD_CNTL_D1__DISABLE_ADR__SHIFT 0x0000000d
+#define MC_IO_PAD_CNTL_D1__DISABLE_CMD_MASK 0x00001000L
+#define MC_IO_PAD_CNTL_D1__DISABLE_CMD__SHIFT 0x0000000c
+#define MC_IO_PAD_CNTL_D1__EN_RD_STR_DLY_MASK 0x00000800L
+#define MC_IO_PAD_CNTL_D1__EN_RD_STR_DLY__SHIFT 0x0000000b
+#define MC_IO_PAD_CNTL_D1__FORCE_EN_RD_STR_MASK 0x00000400L
+#define MC_IO_PAD_CNTL_D1__FORCE_EN_RD_STR__SHIFT 0x0000000a
+#define MC_IO_PAD_CNTL_D1__GDDR_PWRON_MASK 0x40000000L
+#define MC_IO_PAD_CNTL_D1__GDDR_PWRON__SHIFT 0x0000001e
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_ADR_MASK 0x00000200L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_ADR__SHIFT 0x00000009
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CLK_MASK 0x00000080L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CLK__SHIFT 0x00000007
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CMD_MASK 0x00000100L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_CMD__SHIFT 0x00000008
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_DATA_MASK 0x00000020L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_DATA__SHIFT 0x00000005
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_STR_MASK 0x00000040L
+#define MC_IO_PAD_CNTL_D1__MEM_FALL_OUT_STR__SHIFT 0x00000006
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CKE_MASK 0x08000000L
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CKE__SHIFT 0x0000001b
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CLK_MASK 0x80000000L
+#define MC_IO_PAD_CNTL_D1__TXPWROFF_CLK__SHIFT 0x0000001f
+#define MC_IO_PAD_CNTL_D1__UNI_STR_MASK 0x10000000L
+#define MC_IO_PAD_CNTL_D1__UNI_STR__SHIFT 0x0000001c
+#define MC_IO_PAD_CNTL_D1__VREFI_EN_MASK 0x00004000L
+#define MC_IO_PAD_CNTL_D1__VREFI_EN__SHIFT 0x0000000e
+#define MC_IO_PAD_CNTL_D1__VREFI_SEL_MASK 0x000f8000L
+#define MC_IO_PAD_CNTL_D1__VREFI_SEL__SHIFT 0x0000000f
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MAX_MASK 0x0000ff00L
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MAX__SHIFT 0x00000008
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MIN_MASK 0x000000ffL
+#define MC_IO_PAD_CNTL__MEM_IO_IMP_MIN__SHIFT 0x00000000
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D0_MASK 0x00040000L
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D0__SHIFT 0x00000012
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D1_MASK 0x00080000L
+#define MC_IO_PAD_CNTL__OVL_YCLKON_D1__SHIFT 0x00000013
+#define MC_IO_PAD_CNTL__RXPHASE_GRAY_MASK 0x00020000L
+#define MC_IO_PAD_CNTL__RXPHASE_GRAY__SHIFT 0x00000011
+#define MC_IO_PAD_CNTL__TXPHASE_GRAY_MASK 0x00010000L
+#define MC_IO_PAD_CNTL__TXPHASE_GRAY__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY0_D0__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY0_D0__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY0_D0__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY0_D0__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY0_D0__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL1_DPHY0_D1__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY0_D1__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY0_D1__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY0_D1__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY0_D1__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL1_DPHY1_D0__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY1_D0__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY1_D0__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY1_D0__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY1_D0__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL1_DPHY1_D1__DLL_RSV_MASK 0xf0000000L
+#define MC_IO_RXCNTL1_DPHY1_D1__DLL_RSV__SHIFT 0x0000001c
+#define MC_IO_RXCNTL1_DPHY1_D1__PMD_LOOPBACK_MASK 0x0e000000L
+#define MC_IO_RXCNTL1_DPHY1_D1__PMD_LOOPBACK__SHIFT 0x00000019
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL1_MSB_MASK 0x0000000fL
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL1_MSB__SHIFT 0x00000000
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL2_MSB_MASK 0x000000f0L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL2_MSB__SHIFT 0x00000004
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL3_MASK 0x0000ff00L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFCAL3__SHIFT 0x00000008
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFPDNB_1_MASK 0x00040000L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFPDNB_1__SHIFT 0x00000012
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL2_MASK 0x00010000L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL2__SHIFT 0x00000010
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL3_MASK 0x00020000L
+#define MC_IO_RXCNTL1_DPHY1_D1__VREFSEL3__SHIFT 0x00000011
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY0_D0__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY0_D0__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY0_D0__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY0_D0__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY0_D0__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY0_D0__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY0_D0__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY0_D0__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY0_D0__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY0_D0__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY0_D0__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY0_D0__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY0_D0__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY0_D0__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY0_D0__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY0_D0__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY0_D0__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY0_D0__VREFSEL__SHIFT 0x00000010
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY0_D1__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY0_D1__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY0_D1__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY0_D1__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY0_D1__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY0_D1__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY0_D1__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY0_D1__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY0_D1__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY0_D1__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY0_D1__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY0_D1__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY0_D1__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY0_D1__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY0_D1__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY0_D1__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY0_D1__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY0_D1__VREFSEL__SHIFT 0x00000010
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY1_D0__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY1_D0__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY1_D0__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY1_D0__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY1_D0__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY1_D0__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY1_D0__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY1_D0__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY1_D0__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY1_D0__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY1_D0__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY1_D0__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY1_D0__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY1_D0__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY1_D0__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY1_D0__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY1_D0__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY1_D0__VREFSEL__SHIFT 0x00000010
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B0_MASK 0x00700000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B0__SHIFT 0x00000014
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B1_MASK 0x07000000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_B1__SHIFT 0x00000018
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_M_MASK 0x10000000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_ADJ_M__SHIFT 0x0000001c
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_BW_CTRL_MASK 0xc0000000L
+#define MC_IO_RXCNTL_DPHY1_D1__DLL_BW_CTRL__SHIFT 0x0000001e
+#define MC_IO_RXCNTL_DPHY1_D1__RCVSEL_MASK 0x00000004L
+#define MC_IO_RXCNTL_DPHY1_D1__RCVSEL__SHIFT 0x00000002
+#define MC_IO_RXCNTL_DPHY1_D1__REFCLK_PWRON_MASK 0x20000000L
+#define MC_IO_RXCNTL_DPHY1_D1__REFCLK_PWRON__SHIFT 0x0000001d
+#define MC_IO_RXCNTL_DPHY1_D1__RXBIASSEL_MASK 0x00000003L
+#define MC_IO_RXCNTL_DPHY1_D1__RXBIASSEL__SHIFT 0x00000000
+#define MC_IO_RXCNTL_DPHY1_D1__RXDPWRON_DLY_MASK 0x00000030L
+#define MC_IO_RXCNTL_DPHY1_D1__RXDPWRON_DLY__SHIFT 0x00000004
+#define MC_IO_RXCNTL_DPHY1_D1__RXLP_MASK 0x00000080L
+#define MC_IO_RXCNTL_DPHY1_D1__RXLP__SHIFT 0x00000007
+#define MC_IO_RXCNTL_DPHY1_D1__RXPDNB_MASK 0x00000040L
+#define MC_IO_RXCNTL_DPHY1_D1__RXPDNB__SHIFT 0x00000006
+#define MC_IO_RXCNTL_DPHY1_D1__RX_PEAKSEL_MASK 0x000c0000L
+#define MC_IO_RXCNTL_DPHY1_D1__RX_PEAKSEL__SHIFT 0x00000012
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL_MASK 0x00000f00L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL__SHIFT 0x00000008
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL_STR_MASK 0x0000f000L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFCAL_STR__SHIFT 0x0000000c
+#define MC_IO_RXCNTL_DPHY1_D1__VREFPDNB_MASK 0x00000008L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFPDNB__SHIFT 0x00000003
+#define MC_IO_RXCNTL_DPHY1_D1__VREFSEL_MASK 0x00010000L
+#define MC_IO_RXCNTL_DPHY1_D1__VREFSEL__SHIFT 0x00000010
+#define MC_IO_TXCNTL_APHY_D0__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_APHY_D0__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_APHY_D0__CKE_BIT_MASK 0x40000000L
+#define MC_IO_TXCNTL_APHY_D0__CKE_BIT__SHIFT 0x0000001e
+#define MC_IO_TXCNTL_APHY_D0__CKE_SEL_MASK 0x80000000L
+#define MC_IO_TXCNTL_APHY_D0__CKE_SEL__SHIFT 0x0000001f
+#define MC_IO_TXCNTL_APHY_D0__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_APHY_D0__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_APHY_D0__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_APHY_D0__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_APHY_D0__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_APHY_D0__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_APHY_D0__NDRV_MASK 0x00700000L
+#define MC_IO_TXCNTL_APHY_D0__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_APHY_D0__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_APHY_D0__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_APHY_D0__PMA_LOOPBACK_MASK 0x0000e000L
+#define MC_IO_TXCNTL_APHY_D0__PMA_LOOPBACK__SHIFT 0x0000000d
+#define MC_IO_TXCNTL_APHY_D0__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_APHY_D0__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_APHY_D0__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_APHY_D0__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_APHY_D0__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_APHY_D0__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_APHY_D0__TXBPASS_SEL_MASK 0x00001000L
+#define MC_IO_TXCNTL_APHY_D0__TXBPASS_SEL__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS_DATA_MASK 0x38000000L
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS_DATA__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_APHY_D0__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_APHY_D0__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_APHY_D0__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_APHY_D0__TXRESET_MASK 0x02000000L
+#define MC_IO_TXCNTL_APHY_D0__TXRESET__SHIFT 0x00000019
+#define MC_IO_TXCNTL_APHY_D0__YCLKON_MASK 0x00800000L
+#define MC_IO_TXCNTL_APHY_D0__YCLKON__SHIFT 0x00000017
+#define MC_IO_TXCNTL_APHY_D1__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_APHY_D1__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_APHY_D1__CKE_BIT_MASK 0x40000000L
+#define MC_IO_TXCNTL_APHY_D1__CKE_BIT__SHIFT 0x0000001e
+#define MC_IO_TXCNTL_APHY_D1__CKE_SEL_MASK 0x80000000L
+#define MC_IO_TXCNTL_APHY_D1__CKE_SEL__SHIFT 0x0000001f
+#define MC_IO_TXCNTL_APHY_D1__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_APHY_D1__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_APHY_D1__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_APHY_D1__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_APHY_D1__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_APHY_D1__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_APHY_D1__NDRV_MASK 0x00700000L
+#define MC_IO_TXCNTL_APHY_D1__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_APHY_D1__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_APHY_D1__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_APHY_D1__PMA_LOOPBACK_MASK 0x0000e000L
+#define MC_IO_TXCNTL_APHY_D1__PMA_LOOPBACK__SHIFT 0x0000000d
+#define MC_IO_TXCNTL_APHY_D1__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_APHY_D1__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_APHY_D1__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_APHY_D1__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_APHY_D1__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_APHY_D1__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_APHY_D1__TXBPASS_SEL_MASK 0x00001000L
+#define MC_IO_TXCNTL_APHY_D1__TXBPASS_SEL__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS_DATA_MASK 0x38000000L
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS_DATA__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_APHY_D1__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_APHY_D1__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_APHY_D1__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_APHY_D1__TXRESET_MASK 0x02000000L
+#define MC_IO_TXCNTL_APHY_D1__TXRESET__SHIFT 0x00000019
+#define MC_IO_TXCNTL_APHY_D1__YCLKON_MASK 0x00800000L
+#define MC_IO_TXCNTL_APHY_D1__YCLKON__SHIFT 0x00000017
+#define MC_IO_TXCNTL_DPHY0_D0__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY0_D0__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY0_D0__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY0_D0__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY0_D0__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY0_D0__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY0_D0__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY0_D0__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY0_D0__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY0_D0__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY0_D0__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY0_D0__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY0_D0__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY0_D0__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY0_D0__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY0_D0__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY0_D0__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY0_D0__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY0_D0__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY0_D0__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY0_D0__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY0_D0__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY0_D0__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY0_D0__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY0_D0__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY0_D0__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY0_D0__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_DPHY0_D1__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY0_D1__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY0_D1__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY0_D1__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY0_D1__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY0_D1__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY0_D1__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY0_D1__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY0_D1__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY0_D1__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY0_D1__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY0_D1__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY0_D1__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY0_D1__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY0_D1__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY0_D1__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY0_D1__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY0_D1__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY0_D1__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY0_D1__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY0_D1__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY0_D1__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY0_D1__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY0_D1__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY0_D1__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY0_D1__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY0_D1__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_DPHY1_D0__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY1_D0__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY1_D0__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY1_D0__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY1_D0__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY1_D0__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY1_D0__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY1_D0__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY1_D0__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY1_D0__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY1_D0__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY1_D0__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY1_D0__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY1_D0__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY1_D0__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY1_D0__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY1_D0__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY1_D0__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY1_D0__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY1_D0__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY1_D0__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY1_D0__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY1_D0__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY1_D0__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY1_D0__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY1_D0__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY1_D0__TXPD__SHIFT 0x00000007
+#define MC_IO_TXCNTL_DPHY1_D1__BIASSEL_MASK 0x00000003L
+#define MC_IO_TXCNTL_DPHY1_D1__BIASSEL__SHIFT 0x00000000
+#define MC_IO_TXCNTL_DPHY1_D1__DRVDUTY_MASK 0x0000000cL
+#define MC_IO_TXCNTL_DPHY1_D1__DRVDUTY__SHIFT 0x00000002
+#define MC_IO_TXCNTL_DPHY1_D1__EDCTX_CLKGATE_EN_MASK 0x02000000L
+#define MC_IO_TXCNTL_DPHY1_D1__EDCTX_CLKGATE_EN__SHIFT 0x00000019
+#define MC_IO_TXCNTL_DPHY1_D1__EMPH_MASK 0x00000040L
+#define MC_IO_TXCNTL_DPHY1_D1__EMPH__SHIFT 0x00000006
+#define MC_IO_TXCNTL_DPHY1_D1__LOWCMEN_MASK 0x00000010L
+#define MC_IO_TXCNTL_DPHY1_D1__LOWCMEN__SHIFT 0x00000004
+#define MC_IO_TXCNTL_DPHY1_D1__NDRV_MASK 0x00f00000L
+#define MC_IO_TXCNTL_DPHY1_D1__NDRV__SHIFT 0x00000014
+#define MC_IO_TXCNTL_DPHY1_D1__NTERM_MASK 0x0000f000L
+#define MC_IO_TXCNTL_DPHY1_D1__NTERM__SHIFT 0x0000000c
+#define MC_IO_TXCNTL_DPHY1_D1__PDRV_MASK 0x000f0000L
+#define MC_IO_TXCNTL_DPHY1_D1__PDRV__SHIFT 0x00000010
+#define MC_IO_TXCNTL_DPHY1_D1__PLL_LOOPBCK_MASK 0x08000000L
+#define MC_IO_TXCNTL_DPHY1_D1__PLL_LOOPBCK__SHIFT 0x0000001b
+#define MC_IO_TXCNTL_DPHY1_D1__PTERM_MASK 0x00000f00L
+#define MC_IO_TXCNTL_DPHY1_D1__PTERM__SHIFT 0x00000008
+#define MC_IO_TXCNTL_DPHY1_D1__QDR_MASK 0x00000020L
+#define MC_IO_TXCNTL_DPHY1_D1__QDR__SHIFT 0x00000005
+#define MC_IO_TXCNTL_DPHY1_D1__TSTEN_MASK 0x01000000L
+#define MC_IO_TXCNTL_DPHY1_D1__TSTEN__SHIFT 0x00000018
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS_DATA_MASK 0xf0000000L
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS_DATA__SHIFT 0x0000001c
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS_MASK 0x04000000L
+#define MC_IO_TXCNTL_DPHY1_D1__TXBYPASS__SHIFT 0x0000001a
+#define MC_IO_TXCNTL_DPHY1_D1__TXPD_MASK 0x00000080L
+#define MC_IO_TXCNTL_DPHY1_D1__TXPD__SHIFT 0x00000007
+#define MCLK_PWRMGT_CNTL__DLL_READY_MASK 0x00000040L
+#define MCLK_PWRMGT_CNTL__DLL_READY_READ_MASK 0x01000000L
+#define MCLK_PWRMGT_CNTL__DLL_READY_READ__SHIFT 0x00000018
+#define MCLK_PWRMGT_CNTL__DLL_READY__SHIFT 0x00000006
+#define MCLK_PWRMGT_CNTL__DLL_SPEED_MASK 0x0000001fL
+#define MCLK_PWRMGT_CNTL__DLL_SPEED__SHIFT 0x00000000
+#define MCLK_PWRMGT_CNTL__MC_INT_CNTL_MASK 0x00000080L
+#define MCLK_PWRMGT_CNTL__MC_INT_CNTL__SHIFT 0x00000007
+#define MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK 0x00000100L
+#define MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT 0x00000008
+#define MCLK_PWRMGT_CNTL__MRDCK0_RESET_MASK 0x00010000L
+#define MCLK_PWRMGT_CNTL__MRDCK0_RESET__SHIFT 0x00000010
+#define MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK 0x00000200L
+#define MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT 0x00000009
+#define MCLK_PWRMGT_CNTL__MRDCK1_RESET_MASK 0x00020000L
+#define MCLK_PWRMGT_CNTL__MRDCK1_RESET__SHIFT 0x00000011
+#define MC_MEM_POWER_LS__LS_HOLD_MASK 0x00000fc0L
+#define MC_MEM_POWER_LS__LS_HOLD__SHIFT 0x00000006
+#define MC_MEM_POWER_LS__LS_SETUP_MASK 0x0000003fL
+#define MC_MEM_POWER_LS__LS_SETUP__SHIFT 0x00000000
+#define MC_NPL_STATUS__D0_NDELAY_MASK 0x0000000cL
+#define MC_NPL_STATUS__D0_NDELAY__SHIFT 0x00000002
+#define MC_NPL_STATUS__D0_NEARLY_MASK 0x00000020L
+#define MC_NPL_STATUS__D0_NEARLY__SHIFT 0x00000005
+#define MC_NPL_STATUS__D0_PDELAY_MASK 0x00000003L
+#define MC_NPL_STATUS__D0_PDELAY__SHIFT 0x00000000
+#define MC_NPL_STATUS__D0_PEARLY_MASK 0x00000010L
+#define MC_NPL_STATUS__D0_PEARLY__SHIFT 0x00000004
+#define MC_NPL_STATUS__D1_NDELAY_MASK 0x00000300L
+#define MC_NPL_STATUS__D1_NDELAY__SHIFT 0x00000008
+#define MC_NPL_STATUS__D1_NEARLY_MASK 0x00000800L
+#define MC_NPL_STATUS__D1_NEARLY__SHIFT 0x0000000b
+#define MC_NPL_STATUS__D1_PDELAY_MASK 0x000000c0L
+#define MC_NPL_STATUS__D1_PDELAY__SHIFT 0x00000006
+#define MC_NPL_STATUS__D1_PEARLY_MASK 0x00000400L
+#define MC_NPL_STATUS__D1_PEARLY__SHIFT 0x0000000a
+#define MC_PHY_TIMING_2__ADR_CLKEN_D0_MASK 0x00040000L
+#define MC_PHY_TIMING_2__ADR_CLKEN_D0__SHIFT 0x00000012
+#define MC_PHY_TIMING_2__ADR_CLKEN_D1_MASK 0x00080000L
+#define MC_PHY_TIMING_2__ADR_CLKEN_D1__SHIFT 0x00000013
+#define MC_PHY_TIMING_2__IND_LD_CNT_MASK 0x0000007fL
+#define MC_PHY_TIMING_2__IND_LD_CNT__SHIFT 0x00000000
+#define MC_PHY_TIMING_2__RXC0_FRC_MASK 0x00001000L
+#define MC_PHY_TIMING_2__RXC0_FRC__SHIFT 0x0000000c
+#define MC_PHY_TIMING_2__RXC0_INV_MASK 0x00000100L
+#define MC_PHY_TIMING_2__RXC0_INV__SHIFT 0x00000008
+#define MC_PHY_TIMING_2__RXC1_FRC_MASK 0x00002000L
+#define MC_PHY_TIMING_2__RXC1_FRC__SHIFT 0x0000000d
+#define MC_PHY_TIMING_2__RXC1_INV_MASK 0x00000200L
+#define MC_PHY_TIMING_2__RXC1_INV__SHIFT 0x00000009
+#define MC_PHY_TIMING_2__TXC0_FRC_MASK 0x00004000L
+#define MC_PHY_TIMING_2__TXC0_FRC__SHIFT 0x0000000e
+#define MC_PHY_TIMING_2__TXC0_INV_MASK 0x00000400L
+#define MC_PHY_TIMING_2__TXC0_INV__SHIFT 0x0000000a
+#define MC_PHY_TIMING_2__TXC1_FRC_MASK 0x00008000L
+#define MC_PHY_TIMING_2__TXC1_FRC__SHIFT 0x0000000f
+#define MC_PHY_TIMING_2__TXC1_INV_MASK 0x00000800L
+#define MC_PHY_TIMING_2__TXC1_INV__SHIFT 0x0000000b
+#define MC_PHY_TIMING_2__TX_CDREN_D0_MASK 0x00010000L
+#define MC_PHY_TIMING_2__TX_CDREN_D0__SHIFT 0x00000010
+#define MC_PHY_TIMING_2__TX_CDREN_D1_MASK 0x00020000L
+#define MC_PHY_TIMING_2__TX_CDREN_D1__SHIFT 0x00000011
+#define MC_PHY_TIMING_2__WR_DLY_MASK 0x00f00000L
+#define MC_PHY_TIMING_2__WR_DLY__SHIFT 0x00000014
+#define MC_PHY_TIMING_D0__RXC0_DLY_MASK 0x0000000fL
+#define MC_PHY_TIMING_D0__RXC0_DLY__SHIFT 0x00000000
+#define MC_PHY_TIMING_D0__RXC0_EXT_MASK 0x000000f0L
+#define MC_PHY_TIMING_D0__RXC0_EXT__SHIFT 0x00000004
+#define MC_PHY_TIMING_D0__RXC1_DLY_MASK 0x00000f00L
+#define MC_PHY_TIMING_D0__RXC1_DLY__SHIFT 0x00000008
+#define MC_PHY_TIMING_D0__RXC1_EXT_MASK 0x0000f000L
+#define MC_PHY_TIMING_D0__RXC1_EXT__SHIFT 0x0000000c
+#define MC_PHY_TIMING_D0__TXC0_DLY_MASK 0x00070000L
+#define MC_PHY_TIMING_D0__TXC0_DLY__SHIFT 0x00000010
+#define MC_PHY_TIMING_D0__TXC0_EXT_MASK 0x00f00000L
+#define MC_PHY_TIMING_D0__TXC0_EXT__SHIFT 0x00000014
+#define MC_PHY_TIMING_D0__TXC1_DLY_MASK 0x07000000L
+#define MC_PHY_TIMING_D0__TXC1_DLY__SHIFT 0x00000018
+#define MC_PHY_TIMING_D0__TXC1_EXT_MASK 0xf0000000L
+#define MC_PHY_TIMING_D0__TXC1_EXT__SHIFT 0x0000001c
+#define MC_PHY_TIMING_D1__RXC0_DLY_MASK 0x0000000fL
+#define MC_PHY_TIMING_D1__RXC0_DLY__SHIFT 0x00000000
+#define MC_PHY_TIMING_D1__RXC0_EXT_MASK 0x000000f0L
+#define MC_PHY_TIMING_D1__RXC0_EXT__SHIFT 0x00000004
+#define MC_PHY_TIMING_D1__RXC1_DLY_MASK 0x00000f00L
+#define MC_PHY_TIMING_D1__RXC1_DLY__SHIFT 0x00000008
+#define MC_PHY_TIMING_D1__RXC1_EXT_MASK 0x0000f000L
+#define MC_PHY_TIMING_D1__RXC1_EXT__SHIFT 0x0000000c
+#define MC_PHY_TIMING_D1__TXC0_DLY_MASK 0x00070000L
+#define MC_PHY_TIMING_D1__TXC0_DLY__SHIFT 0x00000010
+#define MC_PHY_TIMING_D1__TXC0_EXT_MASK 0x00f00000L
+#define MC_PHY_TIMING_D1__TXC0_EXT__SHIFT 0x00000014
+#define MC_PHY_TIMING_D1__TXC1_DLY_MASK 0x07000000L
+#define MC_PHY_TIMING_D1__TXC1_DLY__SHIFT 0x00000018
+#define MC_PHY_TIMING_D1__TXC1_EXT_MASK 0xf0000000L
+#define MC_PHY_TIMING_D1__TXC1_EXT__SHIFT 0x0000001c
+#define MC_PMG_AUTO_CFG__DLL_CNT_MASK 0xff000000L
+#define MC_PMG_AUTO_CFG__DLL_CNT__SHIFT 0x00000018
+#define MC_PMG_AUTO_CFG__EXIT_ALLOW_STOP_MASK 0x00000800L
+#define MC_PMG_AUTO_CFG__EXIT_ALLOW_STOP__SHIFT 0x0000000b
+#define MC_PMG_AUTO_CFG__MRS_WAIT_CNT_MASK 0x000f0000L
+#define MC_PMG_AUTO_CFG__MRS_WAIT_CNT__SHIFT 0x00000010
+#define MC_PMG_AUTO_CFG__PREA_SRX_MASK 0x00002000L
+#define MC_PMG_AUTO_CFG__PREA_SRX__SHIFT 0x0000000d
+#define MC_PMG_AUTO_CFG__RFS_SRX_MASK 0x00001000L
+#define MC_PMG_AUTO_CFG__RFS_SRX__SHIFT 0x0000000c
+#define MC_PMG_AUTO_CFG__RST_MRS_MASK 0x00000002L
+#define MC_PMG_AUTO_CFG__RST_MRS__SHIFT 0x00000001
+#define MC_PMG_AUTO_CFG__RXPDNB_MASK 0x00400000L
+#define MC_PMG_AUTO_CFG__RXPDNB__SHIFT 0x00000016
+#define MC_PMG_AUTO_CFG__SCDS_MODE_MASK 0x00000400L
+#define MC_PMG_AUTO_CFG__SCDS_MODE__SHIFT 0x0000000a
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_0_MASK 0x00008000L
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_0__SHIFT 0x0000000f
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_1_MASK 0x00800000L
+#define MC_PMG_AUTO_CFG__SELFREFR_COMMIT_1__SHIFT 0x00000017
+#define MC_PMG_AUTO_CFG__SS_ALWAYS_SLF_MASK 0x00000100L
+#define MC_PMG_AUTO_CFG__SS_ALWAYS_SLF__SHIFT 0x00000008
+#define MC_PMG_AUTO_CFG__SS_S_SLF_MASK 0x00000200L
+#define MC_PMG_AUTO_CFG__SS_S_SLF__SHIFT 0x00000009
+#define MC_PMG_AUTO_CFG__STUTTER_EN_MASK 0x00004000L
+#define MC_PMG_AUTO_CFG__STUTTER_EN__SHIFT 0x0000000e
+#define MC_PMG_AUTO_CFG__SYC_CLK_MASK 0x00000001L
+#define MC_PMG_AUTO_CFG__SYC_CLK__SHIFT 0x00000000
+#define MC_PMG_AUTO_CFG__TRI_MIO_MASK 0x00000004L
+#define MC_PMG_AUTO_CFG__TRI_MIO__SHIFT 0x00000002
+#define MC_PMG_AUTO_CFG__WRITE_DURING_DLOCK_MASK 0x00100000L
+#define MC_PMG_AUTO_CFG__WRITE_DURING_DLOCK__SHIFT 0x00000014
+#define MC_PMG_AUTO_CFG__XSR_TMR_MASK 0x000000f0L
+#define MC_PMG_AUTO_CFG__XSR_TMR__SHIFT 0x00000004
+#define MC_PMG_AUTO_CFG__YCLK_ON_MASK 0x00200000L
+#define MC_PMG_AUTO_CFG__YCLK_ON__SHIFT 0x00000015
+#define MC_PMG_AUTO_CMD__ADR_MASK 0x0001ffffL
+#define MC_PMG_AUTO_CMD__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_AUTO_CMD__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_AUTO_CMD__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_AUTO_CMD__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_AUTO_CMD__ADR__SHIFT 0x00000000
+#define MC_PMG_CFG__DPM_WAKE_MASK 0x00000400L
+#define MC_PMG_CFG__DPM_WAKE__SHIFT 0x0000000a
+#define MC_PMG_CFG__EARLY_ACK_ACPI_MASK 0x00400000L
+#define MC_PMG_CFG__EARLY_ACK_ACPI__SHIFT 0x00000016
+#define MC_PMG_CFG__MRS_WAIT_CNT_MASK 0x000f0000L
+#define MC_PMG_CFG__MRS_WAIT_CNT__SHIFT 0x00000010
+#define MC_PMG_CFG__PREA_SRX_MASK 0x00002000L
+#define MC_PMG_CFG__PREA_SRX__SHIFT 0x0000000d
+#define MC_PMG_CFG__RFS_SRX_MASK 0x00001000L
+#define MC_PMG_CFG__RFS_SRX__SHIFT 0x0000000c
+#define MC_PMG_CFG__RST_EMRS_MASK 0x00000004L
+#define MC_PMG_CFG__RST_EMRS__SHIFT 0x00000002
+#define MC_PMG_CFG__RST_MRS1_MASK 0x00000100L
+#define MC_PMG_CFG__RST_MRS1__SHIFT 0x00000008
+#define MC_PMG_CFG__RST_MRS2_MASK 0x00000200L
+#define MC_PMG_CFG__RST_MRS2__SHIFT 0x00000009
+#define MC_PMG_CFG__RST_MRS_MASK 0x00000002L
+#define MC_PMG_CFG__RST_MRS__SHIFT 0x00000001
+#define MC_PMG_CFG__RXPDNB_MASK 0x02000000L
+#define MC_PMG_CFG__RXPDNB__SHIFT 0x00000019
+#define MC_PMG_CFG__SYC_CLK_MASK 0x00000001L
+#define MC_PMG_CFG__SYC_CLK__SHIFT 0x00000000
+#define MC_PMG_CFG__TRI_MIO_MASK 0x00000008L
+#define MC_PMG_CFG__TRI_MIO__SHIFT 0x00000003
+#define MC_PMG_CFG__WRITE_DURING_DLOCK_MASK 0x00100000L
+#define MC_PMG_CFG__WRITE_DURING_DLOCK__SHIFT 0x00000014
+#define MC_PMG_CFG__XSR_TMR_MASK 0x000000f0L
+#define MC_PMG_CFG__XSR_TMR__SHIFT 0x00000004
+#define MC_PMG_CFG__YCLK_ON_MASK 0x00200000L
+#define MC_PMG_CFG__YCLK_ON__SHIFT 0x00000015
+#define MC_PMG_CFG__ZQCL_SEND_MASK 0x0c000000L
+#define MC_PMG_CFG__ZQCL_SEND__SHIFT 0x0000001a
+#define MC_PMG_CMD_EMRS__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_EMRS__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_EMRS__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_EMRS__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_EMRS__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_EMRS__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_EMRS__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_EMRS__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_EMRS__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_EMRS__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_EMRS__END_MASK 0x00100000L
+#define MC_PMG_CMD_EMRS__END__SHIFT 0x00000014
+#define MC_PMG_CMD_EMRS__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_EMRS__MOP__SHIFT 0x00000010
+#define MC_PMG_CMD_MRS1__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_MRS1__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_MRS1__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_MRS1__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_MRS1__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_MRS1__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_MRS1__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_MRS1__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_MRS1__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_MRS1__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_MRS1__END_MASK 0x00100000L
+#define MC_PMG_CMD_MRS1__END__SHIFT 0x00000014
+#define MC_PMG_CMD_MRS1__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_MRS1__MOP__SHIFT 0x00000010
+#define MC_PMG_CMD_MRS2__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_MRS2__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_MRS2__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_MRS2__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_MRS2__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_MRS2__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_MRS2__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_MRS2__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_MRS2__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_MRS2__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_MRS2__END_MASK 0x00100000L
+#define MC_PMG_CMD_MRS2__END__SHIFT 0x00000014
+#define MC_PMG_CMD_MRS2__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_MRS2__MOP__SHIFT 0x00000010
+#define MC_PMG_CMD_MRS__ADR_MASK 0x0000ffffL
+#define MC_PMG_CMD_MRS__ADR_MSB0_MASK 0x20000000L
+#define MC_PMG_CMD_MRS__ADR_MSB0__SHIFT 0x0000001d
+#define MC_PMG_CMD_MRS__ADR_MSB1_MASK 0x10000000L
+#define MC_PMG_CMD_MRS__ADR_MSB1__SHIFT 0x0000001c
+#define MC_PMG_CMD_MRS__ADR__SHIFT 0x00000000
+#define MC_PMG_CMD_MRS__BNK_MSB_MASK 0x00080000L
+#define MC_PMG_CMD_MRS__BNK_MSB__SHIFT 0x00000013
+#define MC_PMG_CMD_MRS__CSB_MASK 0x00600000L
+#define MC_PMG_CMD_MRS__CSB__SHIFT 0x00000015
+#define MC_PMG_CMD_MRS__END_MASK 0x00100000L
+#define MC_PMG_CMD_MRS__END__SHIFT 0x00000014
+#define MC_PMG_CMD_MRS__MOP_MASK 0x00070000L
+#define MC_PMG_CMD_MRS__MOP__SHIFT 0x00000010
+#define MC_RD_CB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_CB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_CB__ENABLE_MASK 0x00000001L
+#define MC_RD_CB__ENABLE__SHIFT 0x00000000
+#define MC_RD_CB__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_CB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_CB__MAX_BURST_MASK 0x00000780L
+#define MC_RD_CB__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_CB__PRESCALE_MASK 0x00000006L
+#define MC_RD_CB__PRESCALE__SHIFT 0x00000001
+#define MC_RD_CB__STALL_MODE_MASK 0x00000030L
+#define MC_RD_CB__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_CB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_CB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_CB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_CB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_DB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_DB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_DB__ENABLE_MASK 0x00000001L
+#define MC_RD_DB__ENABLE__SHIFT 0x00000000
+#define MC_RD_DB__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_DB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_DB__MAX_BURST_MASK 0x00000780L
+#define MC_RD_DB__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_DB__PRESCALE_MASK 0x00000006L
+#define MC_RD_DB__PRESCALE__SHIFT 0x00000001
+#define MC_RD_DB__STALL_MODE_MASK 0x00000030L
+#define MC_RD_DB__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_DB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_DB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_DB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_DB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_GRP_EXT__DBSTEN0_MASK 0x0000000fL
+#define MC_RD_GRP_EXT__DBSTEN0__SHIFT 0x00000000
+#define MC_RD_GRP_EXT__TC0_MASK 0x000000f0L
+#define MC_RD_GRP_EXT__TC0__SHIFT 0x00000004
+#define MC_RD_GRP_GFX__CP_MASK 0x0000000fL
+#define MC_RD_GRP_GFX__CP__SHIFT 0x00000000
+#define MC_RD_GRP_GFX__XDMAM_MASK 0x000f0000L
+#define MC_RD_GRP_GFX__XDMAM__SHIFT 0x00000010
+#define MC_RD_GRP_LCL__CB0_MASK 0x0000f000L
+#define MC_RD_GRP_LCL__CB0__SHIFT 0x0000000c
+#define MC_RD_GRP_LCL__CBCMASK0_MASK 0x000f0000L
+#define MC_RD_GRP_LCL__CBCMASK0__SHIFT 0x00000010
+#define MC_RD_GRP_LCL__CBFMASK0_MASK 0x00f00000L
+#define MC_RD_GRP_LCL__CBFMASK0__SHIFT 0x00000014
+#define MC_RD_GRP_LCL__DB0_MASK 0x0f000000L
+#define MC_RD_GRP_LCL__DB0__SHIFT 0x00000018
+#define MC_RD_GRP_LCL__DBHTILE0_MASK 0xf0000000L
+#define MC_RD_GRP_LCL__DBHTILE0__SHIFT 0x0000001c
+#define MC_RD_GRP_OTH__HDP_MASK 0x00000f00L
+#define MC_RD_GRP_OTH__HDP__SHIFT 0x00000008
+#define MC_RD_GRP_OTH__SEM_MASK 0x0000f000L
+#define MC_RD_GRP_OTH__SEM__SHIFT 0x0000000c
+#define MC_RD_GRP_OTH__UMC_MASK 0x000f0000L
+#define MC_RD_GRP_OTH__UMC__SHIFT 0x00000010
+#define MC_RD_GRP_OTH__UVD_EXT0_MASK 0x0000000fL
+#define MC_RD_GRP_OTH__UVD_EXT0__SHIFT 0x00000000
+#define MC_RD_GRP_OTH__UVD_EXT1_MASK 0x0f000000L
+#define MC_RD_GRP_OTH__UVD_EXT1__SHIFT 0x00000018
+#define MC_RD_GRP_OTH__UVD_MASK 0x00f00000L
+#define MC_RD_GRP_OTH__UVD__SHIFT 0x00000014
+#define MC_RD_GRP_SYS__DMIF_MASK 0x0000f000L
+#define MC_RD_GRP_SYS__DMIF__SHIFT 0x0000000c
+#define MC_RD_GRP_SYS__MCIF_MASK 0x000f0000L
+#define MC_RD_GRP_SYS__MCIF__SHIFT 0x00000010
+#define MC_RD_GRP_SYS__RLC_MASK 0x0000000fL
+#define MC_RD_GRP_SYS__RLC__SHIFT 0x00000000
+#define MC_RD_GRP_SYS__SMU_MASK 0x00f00000L
+#define MC_RD_GRP_SYS__SMU__SHIFT 0x00000014
+#define MC_RD_GRP_SYS__VCE_MASK 0x0f000000L
+#define MC_RD_GRP_SYS__VCE__SHIFT 0x00000018
+#define MC_RD_GRP_SYS__VCEU_MASK 0xf0000000L
+#define MC_RD_GRP_SYS__VCEU__SHIFT 0x0000001c
+#define MC_RD_GRP_SYS__VMC_MASK 0x000000f0L
+#define MC_RD_GRP_SYS__VMC__SHIFT 0x00000004
+#define MC_RD_HUB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_HUB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_HUB__ENABLE_MASK 0x00000001L
+#define MC_RD_HUB__ENABLE__SHIFT 0x00000000
+#define MC_RD_HUB__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_HUB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_HUB__MAX_BURST_MASK 0x00000780L
+#define MC_RD_HUB__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_HUB__PRESCALE_MASK 0x00000006L
+#define MC_RD_HUB__PRESCALE__SHIFT 0x00000001
+#define MC_RD_HUB__STALL_MODE_MASK 0x00000030L
+#define MC_RD_HUB__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_HUB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_HUB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_HUB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_HUB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_TC0__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_TC0__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_TC0__ENABLE_MASK 0x00000001L
+#define MC_RD_TC0__ENABLE__SHIFT 0x00000000
+#define MC_RD_TC0__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_TC0__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_TC0__MAX_BURST_MASK 0x00000780L
+#define MC_RD_TC0__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_TC0__PRESCALE_MASK 0x00000006L
+#define MC_RD_TC0__PRESCALE__SHIFT 0x00000001
+#define MC_RD_TC0__STALL_MODE_MASK 0x00000030L
+#define MC_RD_TC0__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_TC0__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_TC0__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_TC0__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_TC0__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RD_TC1__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_RD_TC1__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_RD_TC1__ENABLE_MASK 0x00000001L
+#define MC_RD_TC1__ENABLE__SHIFT 0x00000000
+#define MC_RD_TC1__LAZY_TIMER_MASK 0x00007800L
+#define MC_RD_TC1__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_RD_TC1__MAX_BURST_MASK 0x00000780L
+#define MC_RD_TC1__MAX_BURST__SHIFT 0x00000007
+#define MC_RD_TC1__PRESCALE_MASK 0x00000006L
+#define MC_RD_TC1__PRESCALE__SHIFT 0x00000001
+#define MC_RD_TC1__STALL_MODE_MASK 0x00000030L
+#define MC_RD_TC1__STALL_MODE__SHIFT 0x00000004
+#define MC_RD_TC1__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_RD_TC1__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_RD_TC1__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_RD_TC1__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_RPB_ARB_CNTL__ATC_SWITCH_NUM_MASK 0x00ff0000L
+#define MC_RPB_ARB_CNTL__ATC_SWITCH_NUM__SHIFT 0x00000010
+#define MC_RPB_ARB_CNTL__RD_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_ARB_CNTL__RD_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_ARB_CNTL__WR_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_ARB_CNTL__WR_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_BIF_CNTL__ARB_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_BIF_CNTL__ARB_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_BIF_CNTL__XPB_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_BIF_CNTL__XPB_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_CID_QUEUE_EX_DATA__READ_ENTRIES_MASK 0xffff0000L
+#define MC_RPB_CID_QUEUE_EX_DATA__READ_ENTRIES__SHIFT 0x00000010
+#define MC_RPB_CID_QUEUE_EX_DATA__WRITE_ENTRIES_MASK 0x0000ffffL
+#define MC_RPB_CID_QUEUE_EX_DATA__WRITE_ENTRIES__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_EX__OFFSET_MASK 0x0000003eL
+#define MC_RPB_CID_QUEUE_EX__OFFSET__SHIFT 0x00000001
+#define MC_RPB_CID_QUEUE_EX__START_MASK 0x00000001L
+#define MC_RPB_CID_QUEUE_EX__START__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_RD__CLIENT_ID_MASK 0x000000ffL
+#define MC_RPB_CID_QUEUE_RD__CLIENT_ID__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_RD__READ_QUEUE_MASK 0x00000c00L
+#define MC_RPB_CID_QUEUE_RD__READ_QUEUE__SHIFT 0x0000000a
+#define MC_RPB_CID_QUEUE_RD__WRITE_QUEUE_MASK 0x00000300L
+#define MC_RPB_CID_QUEUE_RD__WRITE_QUEUE__SHIFT 0x00000008
+#define MC_RPB_CID_QUEUE_WR__CLIENT_ID_MASK 0x000000ffL
+#define MC_RPB_CID_QUEUE_WR__CLIENT_ID__SHIFT 0x00000000
+#define MC_RPB_CID_QUEUE_WR__READ_QUEUE_MASK 0x00001800L
+#define MC_RPB_CID_QUEUE_WR__READ_QUEUE__SHIFT 0x0000000b
+#define MC_RPB_CID_QUEUE_WR__UPDATE_MASK 0x00002000L
+#define MC_RPB_CID_QUEUE_WR__UPDATE_MODE_MASK 0x00000100L
+#define MC_RPB_CID_QUEUE_WR__UPDATE_MODE__SHIFT 0x00000008
+#define MC_RPB_CID_QUEUE_WR__UPDATE__SHIFT 0x0000000d
+#define MC_RPB_CID_QUEUE_WR__WRITE_QUEUE_MASK 0x00000600L
+#define MC_RPB_CID_QUEUE_WR__WRITE_QUEUE__SHIFT 0x00000009
+#define MC_RPB_CONF__RPB_RD_PCIE_ORDER_MASK 0x00010000L
+#define MC_RPB_CONF__RPB_RD_PCIE_ORDER__SHIFT 0x00000010
+#define MC_RPB_CONF__RPB_WR_PCIE_ORDER_MASK 0x00020000L
+#define MC_RPB_CONF__RPB_WR_PCIE_ORDER__SHIFT 0x00000011
+#define MC_RPB_CONF__XPB_PCIE_ORDER_MASK 0x00008000L
+#define MC_RPB_CONF__XPB_PCIE_ORDER__SHIFT 0x0000000f
+#define MC_RPB_DBG1__DEBUG_BITS_MASK 0xfff00000L
+#define MC_RPB_DBG1__DEBUG_BITS__SHIFT 0x00000014
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD_32B_MASK 0x000fff00L
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD_32B__SHIFT 0x00000008
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD_MASK 0x000000ffL
+#define MC_RPB_DBG1__RPB_BIF_OUTSTANDING_RD__SHIFT 0x00000000
+#define MC_RPB_EFF_CNTL__RD_LAZY_TIMER_MASK 0x0000ff00L
+#define MC_RPB_EFF_CNTL__RD_LAZY_TIMER__SHIFT 0x00000008
+#define MC_RPB_EFF_CNTL__WR_LAZY_TIMER_MASK 0x000000ffL
+#define MC_RPB_EFF_CNTL__WR_LAZY_TIMER__SHIFT 0x00000000
+#define MC_RPB_IF_CONF__OUTSTANDING_WRRET_ASK_MASK 0x0000ff00L
+#define MC_RPB_IF_CONF__OUTSTANDING_WRRET_ASK__SHIFT 0x00000008
+#define MC_RPB_IF_CONF__RPB_BIF_CREDITS_MASK 0x000000ffL
+#define MC_RPB_IF_CONF__RPB_BIF_CREDITS__SHIFT 0x00000000
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_ALL_PERF_COUNTERS_MASK 0x00000008L
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_ALL_PERF_COUNTERS__SHIFT 0x00000003
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_SELECTED_PERF_COUNTER_MASK 0x00000004L
+#define MC_RPB_PERF_COUNTER_CNTL__CLEAR_SELECTED_PERF_COUNTER__SHIFT 0x00000002
+#define MC_RPB_PERF_COUNTER_CNTL__ENABLE_PERF_COUNTERS_MASK 0x000001e0L
+#define MC_RPB_PERF_COUNTER_CNTL__ENABLE_PERF_COUNTERS__SHIFT 0x00000005
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_0_MASK 0x00003e00L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_0__SHIFT 0x00000009
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_1_MASK 0x0007c000L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_1__SHIFT 0x0000000e
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_2_MASK 0x00f80000L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_2__SHIFT 0x00000013
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_3_MASK 0x1f000000L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_ASSIGN_3__SHIFT 0x00000018
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_SELECT_MASK 0x00000003L
+#define MC_RPB_PERF_COUNTER_CNTL__PERF_COUNTER_SELECT__SHIFT 0x00000000
+#define MC_RPB_PERF_COUNTER_CNTL__STOP_ON_COUNTER_SATURATION_MASK 0x00000010L
+#define MC_RPB_PERF_COUNTER_CNTL__STOP_ON_COUNTER_SATURATION__SHIFT 0x00000004
+#define MC_RPB_PERF_COUNTER_STATUS__PERFORMANCE_COUNTER_VALUE_MASK 0xffffffffL
+#define MC_RPB_PERF_COUNTER_STATUS__PERFORMANCE_COUNTER_VALUE__SHIFT 0x00000000
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE0_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE0_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE1_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE1_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE2_SWITCH_NUM_MASK 0x00ff0000L
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE2_SWITCH_NUM__SHIFT 0x00000010
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE3_SWITCH_NUM_MASK 0xff000000L
+#define MC_RPB_RD_SWITCH_CNTL__QUEUE3_SWITCH_NUM__SHIFT 0x00000018
+#define MC_RPB_WR_COMBINE_CNTL__WC_ALIGN_MASK 0x00000080L
+#define MC_RPB_WR_COMBINE_CNTL__WC_ALIGN__SHIFT 0x00000007
+#define MC_RPB_WR_COMBINE_CNTL__WC_ENABLE_MASK 0x00000001L
+#define MC_RPB_WR_COMBINE_CNTL__WC_ENABLE__SHIFT 0x00000000
+#define MC_RPB_WR_COMBINE_CNTL__WC_FLUSH_TIMER_MASK 0x00000078L
+#define MC_RPB_WR_COMBINE_CNTL__WC_FLUSH_TIMER__SHIFT 0x00000003
+#define MC_RPB_WR_COMBINE_CNTL__WC_MAX_PACKET_SIZE_MASK 0x00000006L
+#define MC_RPB_WR_COMBINE_CNTL__WC_MAX_PACKET_SIZE__SHIFT 0x00000001
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE0_SWITCH_NUM_MASK 0x000000ffL
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE0_SWITCH_NUM__SHIFT 0x00000000
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE1_SWITCH_NUM_MASK 0x0000ff00L
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE1_SWITCH_NUM__SHIFT 0x00000008
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE2_SWITCH_NUM_MASK 0x00ff0000L
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE2_SWITCH_NUM__SHIFT 0x00000010
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE3_SWITCH_NUM_MASK 0xff000000L
+#define MC_RPB_WR_SWITCH_CNTL__QUEUE3_SWITCH_NUM__SHIFT 0x00000018
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B0_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B0_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B1_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B1_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B2_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B2_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B3_D0__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT0_MASK 0x00000007L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT0__SHIFT 0x00000000
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT1_MASK 0x00000038L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT1__SHIFT 0x00000003
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT2_MASK 0x000001c0L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT2__SHIFT 0x00000006
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT3_MASK 0x00000e00L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT3__SHIFT 0x00000009
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT4_MASK 0x00007000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT4__SHIFT 0x0000000c
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT5_MASK 0x00038000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT5__SHIFT 0x0000000f
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT6_MASK 0x001c0000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT6__SHIFT 0x00000012
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT7_MASK 0x00e00000L
+#define MC_SEQ_BIT_REMAP_B3_D1__BIT7__SHIFT 0x00000015
+#define MC_SEQ_BYTE_REMAP_D0__BYTE0_MASK 0x00000003L
+#define MC_SEQ_BYTE_REMAP_D0__BYTE0__SHIFT 0x00000000
+#define MC_SEQ_BYTE_REMAP_D0__BYTE1_MASK 0x0000000cL
+#define MC_SEQ_BYTE_REMAP_D0__BYTE1__SHIFT 0x00000002
+#define MC_SEQ_BYTE_REMAP_D0__BYTE2_MASK 0x00000030L
+#define MC_SEQ_BYTE_REMAP_D0__BYTE2__SHIFT 0x00000004
+#define MC_SEQ_BYTE_REMAP_D0__BYTE3_MASK 0x000000c0L
+#define MC_SEQ_BYTE_REMAP_D0__BYTE3__SHIFT 0x00000006
+#define MC_SEQ_BYTE_REMAP_D1__BYTE0_MASK 0x00000003L
+#define MC_SEQ_BYTE_REMAP_D1__BYTE0__SHIFT 0x00000000
+#define MC_SEQ_BYTE_REMAP_D1__BYTE1_MASK 0x0000000cL
+#define MC_SEQ_BYTE_REMAP_D1__BYTE1__SHIFT 0x00000002
+#define MC_SEQ_BYTE_REMAP_D1__BYTE2_MASK 0x00000030L
+#define MC_SEQ_BYTE_REMAP_D1__BYTE2__SHIFT 0x00000004
+#define MC_SEQ_BYTE_REMAP_D1__BYTE3_MASK 0x000000c0L
+#define MC_SEQ_BYTE_REMAP_D1__BYTE3__SHIFT 0x00000006
+#define MC_SEQ_CAS_TIMING_LP__TCCDL_MASK 0x00000e00L
+#define MC_SEQ_CAS_TIMING_LP__TCCDL__SHIFT 0x00000009
+#define MC_SEQ_CAS_TIMING_LP__TCL_MASK 0x1f000000L
+#define MC_SEQ_CAS_TIMING_LP__TCL__SHIFT 0x00000018
+#define MC_SEQ_CAS_TIMING_LP__TNOPR_MASK 0x0000000cL
+#define MC_SEQ_CAS_TIMING_LP__TNOPR__SHIFT 0x00000002
+#define MC_SEQ_CAS_TIMING_LP__TNOPW_MASK 0x00000003L
+#define MC_SEQ_CAS_TIMING_LP__TNOPW__SHIFT 0x00000000
+#define MC_SEQ_CAS_TIMING_LP__TR2R_MASK 0x0000f000L
+#define MC_SEQ_CAS_TIMING_LP__TR2R__SHIFT 0x0000000c
+#define MC_SEQ_CAS_TIMING_LP__TR2W_MASK 0x000001f0L
+#define MC_SEQ_CAS_TIMING_LP__TR2W__SHIFT 0x00000004
+#define MC_SEQ_CAS_TIMING_LP__TW2R_MASK 0x001f0000L
+#define MC_SEQ_CAS_TIMING_LP__TW2R__SHIFT 0x00000010
+#define MC_SEQ_CAS_TIMING__TCCDL_MASK 0x00000e00L
+#define MC_SEQ_CAS_TIMING__TCCDL__SHIFT 0x00000009
+#define MC_SEQ_CAS_TIMING__TCL_MASK 0x1f000000L
+#define MC_SEQ_CAS_TIMING__TCL__SHIFT 0x00000018
+#define MC_SEQ_CAS_TIMING__TNOPR_MASK 0x0000000cL
+#define MC_SEQ_CAS_TIMING__TNOPR__SHIFT 0x00000002
+#define MC_SEQ_CAS_TIMING__TNOPW_MASK 0x00000003L
+#define MC_SEQ_CAS_TIMING__TNOPW__SHIFT 0x00000000
+#define MC_SEQ_CAS_TIMING__TR2R_MASK 0x0000f000L
+#define MC_SEQ_CAS_TIMING__TR2R__SHIFT 0x0000000c
+#define MC_SEQ_CAS_TIMING__TR2W_MASK 0x000001f0L
+#define MC_SEQ_CAS_TIMING__TR2W__SHIFT 0x00000004
+#define MC_SEQ_CAS_TIMING__TW2R_MASK 0x001f0000L
+#define MC_SEQ_CAS_TIMING__TW2R__SHIFT 0x00000010
+#define MC_SEQ_CG__CG_SEQ_REQ_MASK 0x000000ffL
+#define MC_SEQ_CG__CG_SEQ_REQ__SHIFT 0x00000000
+#define MC_SEQ_CG__CG_SEQ_RESP_MASK 0x0000ff00L
+#define MC_SEQ_CG__CG_SEQ_RESP__SHIFT 0x00000008
+#define MC_SEQ_CG__SEQ_CG_REQ_MASK 0x00ff0000L
+#define MC_SEQ_CG__SEQ_CG_REQ__SHIFT 0x00000010
+#define MC_SEQ_CG__SEQ_CG_RESP_MASK 0xff000000L
+#define MC_SEQ_CG__SEQ_CG_RESP__SHIFT 0x00000018
+#define MC_SEQ_CMD__ADR_MASK 0x0000ffffL
+#define MC_SEQ_CMD__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_CMD__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_CMD__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_CMD__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_CMD__ADR__SHIFT 0x00000000
+#define MC_SEQ_CMD__CHAN0_MASK 0x01000000L
+#define MC_SEQ_CMD__CHAN0__SHIFT 0x00000018
+#define MC_SEQ_CMD__CHAN1_MASK 0x02000000L
+#define MC_SEQ_CMD__CHAN1__SHIFT 0x00000019
+#define MC_SEQ_CMD__CSB_MASK 0x00600000L
+#define MC_SEQ_CMD__CSB__SHIFT 0x00000015
+#define MC_SEQ_CMD__END_MASK 0x00100000L
+#define MC_SEQ_CMD__END__SHIFT 0x00000014
+#define MC_SEQ_CMD__MOP_MASK 0x000f0000L
+#define MC_SEQ_CMD__MOP__SHIFT 0x00000010
+#define MC_SEQ_CNTL_2__ARB_RTDAT_WMK_MSB_MASK 0x00000300L
+#define MC_SEQ_CNTL_2__ARB_RTDAT_WMK_MSB__SHIFT 0x00000008
+#define MC_SEQ_CNTL_2__DRST_NSTR_MASK 0x0000fc00L
+#define MC_SEQ_CNTL_2__DRST_NSTR__SHIFT 0x0000000a
+#define MC_SEQ_CNTL_2__DRST_PSTR_MASK 0x003f0000L
+#define MC_SEQ_CNTL_2__DRST_PSTR__SHIFT 0x00000010
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D0_MASK 0x0f000000L
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D0__SHIFT 0x00000018
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D1_MASK 0xf0000000L
+#define MC_SEQ_CNTL_2__PLL_RX_PWRON_D1__SHIFT 0x0000001c
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D0_MASK 0x00400000L
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D0__SHIFT 0x00000016
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D1_MASK 0x00800000L
+#define MC_SEQ_CNTL_2__PLL_TX_PWRON_D1__SHIFT 0x00000017
+#define MC_SEQ_CNTL__ARB_REQCMD_WMK_MASK 0x00f00000L
+#define MC_SEQ_CNTL__ARB_REQCMD_WMK__SHIFT 0x00000014
+#define MC_SEQ_CNTL__ARB_REQDAT_WMK_MASK 0x0f000000L
+#define MC_SEQ_CNTL__ARB_REQDAT_WMK__SHIFT 0x00000018
+#define MC_SEQ_CNTL__ARB_RTDAT_WMK_MASK 0xf0000000L
+#define MC_SEQ_CNTL__ARB_RTDAT_WMK__SHIFT 0x0000001c
+#define MC_SEQ_CNTL__BANKGROUP_ENB_MASK 0x00040000L
+#define MC_SEQ_CNTL__BANKGROUP_ENB__SHIFT 0x00000012
+#define MC_SEQ_CNTL__BANKGROUP_SIZE_MASK 0x00020000L
+#define MC_SEQ_CNTL__BANKGROUP_SIZE__SHIFT 0x00000011
+#define MC_SEQ_CNTL__CHANNEL_DISABLE_MASK 0x00000300L
+#define MC_SEQ_CNTL__CHANNEL_DISABLE__SHIFT 0x00000008
+#define MC_SEQ_CNTL__DAT_INV_MASK 0x00000040L
+#define MC_SEQ_CNTL__DAT_INV__SHIFT 0x00000006
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_BANK_MASK 0x0000000cL
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_BANK__SHIFT 0x00000002
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_COLS_MASK 0x00000003L
+#define MC_SEQ_CNTL__MEM_ADDR_MAP_COLS__SHIFT 0x00000000
+#define MC_SEQ_CNTL__MSK_DF1_MASK 0x00000080L
+#define MC_SEQ_CNTL__MSK_DF1__SHIFT 0x00000007
+#define MC_SEQ_CNTL__MSKOFF_DAT_TH_MASK 0x00008000L
+#define MC_SEQ_CNTL__MSKOFF_DAT_TH__SHIFT 0x0000000f
+#define MC_SEQ_CNTL__MSKOFF_DAT_TL_MASK 0x00004000L
+#define MC_SEQ_CNTL__MSKOFF_DAT_TL__SHIFT 0x0000000e
+#define MC_SEQ_CNTL__RET_HOLD_EOP_MASK 0x00010000L
+#define MC_SEQ_CNTL__RET_HOLD_EOP__SHIFT 0x00000010
+#define MC_SEQ_CNTL__RTR_OVERRIDE_MASK 0x00080000L
+#define MC_SEQ_CNTL__RTR_OVERRIDE__SHIFT 0x00000013
+#define MC_SEQ_CNTL__SAFE_MODE_MASK 0x00000030L
+#define MC_SEQ_CNTL__SAFE_MODE__SHIFT 0x00000004
+#define MC_SEQ_DRAM_2__ADBI_ACT_MASK 0x04000000L
+#define MC_SEQ_DRAM_2__ADBI_ACT__SHIFT 0x0000001a
+#define MC_SEQ_DRAM_2__ADBI_DF1_MASK 0x02000000L
+#define MC_SEQ_DRAM_2__ADBI_DF1__SHIFT 0x00000019
+#define MC_SEQ_DRAM_2__ADR_DBI_ACM_MASK 0x00000004L
+#define MC_SEQ_DRAM_2__ADR_DBI_ACM__SHIFT 0x00000002
+#define MC_SEQ_DRAM_2__ADR_DBI_MASK 0x00000002L
+#define MC_SEQ_DRAM_2__ADR_DBI__SHIFT 0x00000001
+#define MC_SEQ_DRAM_2__ADR_DDR_MASK 0x00000001L
+#define MC_SEQ_DRAM_2__ADR_DDR__SHIFT 0x00000000
+#define MC_SEQ_DRAM_2__BNK_MRS_MASK 0x00002000L
+#define MC_SEQ_DRAM_2__BNK_MRS__SHIFT 0x0000000d
+#define MC_SEQ_DRAM_2__CMD_QDR_MASK 0x00000008L
+#define MC_SEQ_DRAM_2__CMD_QDR__SHIFT 0x00000003
+#define MC_SEQ_DRAM_2__CS_BY16_MASK 0x80000000L
+#define MC_SEQ_DRAM_2__CS_BY16__SHIFT 0x0000001f
+#define MC_SEQ_DRAM_2__DAT_QDR_MASK 0x00000010L
+#define MC_SEQ_DRAM_2__DAT_QDR__SHIFT 0x00000004
+#define MC_SEQ_DRAM_2__DBI_ACT_MASK 0x10000000L
+#define MC_SEQ_DRAM_2__DBI_ACT__SHIFT 0x0000001c
+#define MC_SEQ_DRAM_2__DBI_DF1_MASK 0x08000000L
+#define MC_SEQ_DRAM_2__DBI_DF1__SHIFT 0x0000001b
+#define MC_SEQ_DRAM_2__DBI_EDC_DF1_MASK 0x20000000L
+#define MC_SEQ_DRAM_2__DBI_EDC_DF1__SHIFT 0x0000001d
+#define MC_SEQ_DRAM_2__DBI_OVR_MASK 0x00004000L
+#define MC_SEQ_DRAM_2__DBI_OVR__SHIFT 0x0000000e
+#define MC_SEQ_DRAM_2__DLL_EST_MASK 0x00001000L
+#define MC_SEQ_DRAM_2__DLL_EST__SHIFT 0x0000000c
+#define MC_SEQ_DRAM_2__DQM_EST_MASK 0x00000080L
+#define MC_SEQ_DRAM_2__DQM_EST__SHIFT 0x00000007
+#define MC_SEQ_DRAM_2__PCH_BNK_MASK 0x01000000L
+#define MC_SEQ_DRAM_2__PCH_BNK__SHIFT 0x00000018
+#define MC_SEQ_DRAM_2__PLL_CLR_MASK 0x00000800L
+#define MC_SEQ_DRAM_2__PLL_CLR__SHIFT 0x0000000b
+#define MC_SEQ_DRAM_2__PLL_CNT_MASK 0x00ff0000L
+#define MC_SEQ_DRAM_2__PLL_CNT__SHIFT 0x00000010
+#define MC_SEQ_DRAM_2__PLL_EST_MASK 0x00000400L
+#define MC_SEQ_DRAM_2__PLL_EST__SHIFT 0x0000000a
+#define MC_SEQ_DRAM_2__RDAT_EDC_MASK 0x00000040L
+#define MC_SEQ_DRAM_2__RDAT_EDC__SHIFT 0x00000006
+#define MC_SEQ_DRAM_2__RD_DQS_MASK 0x00000100L
+#define MC_SEQ_DRAM_2__RD_DQS__SHIFT 0x00000008
+#define MC_SEQ_DRAM_2__TESTCHIP_EN_MASK 0x40000000L
+#define MC_SEQ_DRAM_2__TESTCHIP_EN__SHIFT 0x0000001e
+#define MC_SEQ_DRAM_2__TRI_CLK_MASK 0x00008000L
+#define MC_SEQ_DRAM_2__TRI_CLK__SHIFT 0x0000000f
+#define MC_SEQ_DRAM_2__WDAT_EDC_MASK 0x00000020L
+#define MC_SEQ_DRAM_2__WDAT_EDC__SHIFT 0x00000005
+#define MC_SEQ_DRAM_2__WR_DQS_MASK 0x00000200L
+#define MC_SEQ_DRAM_2__WR_DQS__SHIFT 0x00000009
+#define MC_SEQ_DRAM__ADR_2CK_MASK 0x00000001L
+#define MC_SEQ_DRAM__ADR_2CK__SHIFT 0x00000000
+#define MC_SEQ_DRAM__ADR_DF1_MASK 0x00000004L
+#define MC_SEQ_DRAM__ADR_DF1__SHIFT 0x00000002
+#define MC_SEQ_DRAM__ADR_MUX_MASK 0x00000002L
+#define MC_SEQ_DRAM__ADR_MUX__SHIFT 0x00000001
+#define MC_SEQ_DRAM__AP8_MASK 0x00000008L
+#define MC_SEQ_DRAM__AP8__SHIFT 0x00000003
+#define MC_SEQ_DRAM__BO4_MASK 0x00004000L
+#define MC_SEQ_DRAM__BO4__SHIFT 0x0000000e
+#define MC_SEQ_DRAM__CKE_ACT_MASK 0x00002000L
+#define MC_SEQ_DRAM__CKE_ACT__SHIFT 0x0000000d
+#define MC_SEQ_DRAM__CKE_DYN_MASK 0x00001000L
+#define MC_SEQ_DRAM__CKE_DYN__SHIFT 0x0000000c
+#define MC_SEQ_DRAM__DAT_DF1_MASK 0x00000010L
+#define MC_SEQ_DRAM__DAT_DF1__SHIFT 0x00000004
+#define MC_SEQ_DRAM__DAT_INV_MASK 0x01000000L
+#define MC_SEQ_DRAM__DAT_INV__SHIFT 0x00000018
+#define MC_SEQ_DRAM__DLL_CLR_MASK 0x00008000L
+#define MC_SEQ_DRAM__DLL_CLR__SHIFT 0x0000000f
+#define MC_SEQ_DRAM__DLL_CNT_MASK 0x00ff0000L
+#define MC_SEQ_DRAM__DLL_CNT__SHIFT 0x00000010
+#define MC_SEQ_DRAM__DQM_ACT_MASK 0x00000080L
+#define MC_SEQ_DRAM__DQM_ACT__SHIFT 0x00000007
+#define MC_SEQ_DRAM__DQM_DF1_MASK 0x00000040L
+#define MC_SEQ_DRAM__DQM_DF1__SHIFT 0x00000006
+#define MC_SEQ_DRAM__DQS_DF1_MASK 0x00000020L
+#define MC_SEQ_DRAM__DQS_DF1__SHIFT 0x00000005
+#define MC_SEQ_DRAM_ERROR_INSERTION__RX_MASK 0xffff0000L
+#define MC_SEQ_DRAM_ERROR_INSERTION__RX__SHIFT 0x00000010
+#define MC_SEQ_DRAM_ERROR_INSERTION__TX_MASK 0x0000ffffL
+#define MC_SEQ_DRAM_ERROR_INSERTION__TX__SHIFT 0x00000000
+#define MC_SEQ_DRAM__INV_ACM_MASK 0x02000000L
+#define MC_SEQ_DRAM__INV_ACM__SHIFT 0x00000019
+#define MC_SEQ_DRAM__ODT_ACT_MASK 0x08000000L
+#define MC_SEQ_DRAM__ODT_ACT__SHIFT 0x0000001b
+#define MC_SEQ_DRAM__ODT_ENB_MASK 0x04000000L
+#define MC_SEQ_DRAM__ODT_ENB__SHIFT 0x0000001a
+#define MC_SEQ_DRAM__RST_CTL_MASK 0x10000000L
+#define MC_SEQ_DRAM__RST_CTL__SHIFT 0x0000001c
+#define MC_SEQ_DRAM__STB_CNT_MASK 0x00000f00L
+#define MC_SEQ_DRAM__STB_CNT__SHIFT 0x00000008
+#define MC_SEQ_DRAM__TRI_CKE_MASK 0x40000000L
+#define MC_SEQ_DRAM__TRI_CKE__SHIFT 0x0000001e
+#define MC_SEQ_DRAM__TRI_MIO_DYN_MASK 0x20000000L
+#define MC_SEQ_DRAM__TRI_MIO_DYN__SHIFT 0x0000001d
+#define MC_SEQ_FIFO_CTL__CG_DIS_D0_MASK 0x00000100L
+#define MC_SEQ_FIFO_CTL__CG_DIS_D0__SHIFT 0x00000008
+#define MC_SEQ_FIFO_CTL__CG_DIS_D1_MASK 0x00000200L
+#define MC_SEQ_FIFO_CTL__CG_DIS_D1__SHIFT 0x00000009
+#define MC_SEQ_FIFO_CTL__R_LD_INIT_MASK 0x00000030L
+#define MC_SEQ_FIFO_CTL__R_LD_INIT__SHIFT 0x00000004
+#define MC_SEQ_FIFO_CTL__R_SYC_SEL_MASK 0x000000c0L
+#define MC_SEQ_FIFO_CTL__R_SYC_SEL__SHIFT 0x00000006
+#define MC_SEQ_FIFO_CTL__SYC_DLY_MASK 0x00007000L
+#define MC_SEQ_FIFO_CTL__SYC_DLY__SHIFT 0x0000000c
+#define MC_SEQ_FIFO_CTL__W_ASYC_EXT_MASK 0x00030000L
+#define MC_SEQ_FIFO_CTL__W_ASYC_EXT__SHIFT 0x00000010
+#define MC_SEQ_FIFO_CTL__W_DSYC_EXT_MASK 0x000c0000L
+#define MC_SEQ_FIFO_CTL__W_DSYC_EXT__SHIFT 0x00000012
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D0_MASK 0x00000003L
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D0__SHIFT 0x00000000
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D1_MASK 0x00000c00L
+#define MC_SEQ_FIFO_CTL__W_LD_INIT_D1__SHIFT 0x0000000a
+#define MC_SEQ_FIFO_CTL__W_SYC_SEL_MASK 0x0000000cL
+#define MC_SEQ_FIFO_CTL__W_SYC_SEL__SHIFT 0x00000002
+#define MC_SEQ_IO_DEBUG_DATA__IO_DEBUG_DATA_MASK 0xffffffffL
+#define MC_SEQ_IO_DEBUG_DATA__IO_DEBUG_DATA__SHIFT 0x00000000
+#define MC_SEQ_IO_DEBUG_INDEX__IO_DEBUG_INDEX_MASK 0x000001ffL
+#define MC_SEQ_IO_DEBUG_INDEX__IO_DEBUG_INDEX__SHIFT 0x00000000
+#define MC_SEQ_IO_RDBI__MASK_MASK 0xffffffffL
+#define MC_SEQ_IO_RDBI__MASK__SHIFT 0x00000000
+#define MC_SEQ_IO_REDC__EDC_MASK 0xffffffffL
+#define MC_SEQ_IO_REDC__EDC__SHIFT 0x00000000
+#define MC_SEQ_IO_RESERVE_D0__APHY_RSV_MASK 0xff000000L
+#define MC_SEQ_IO_RESERVE_D0__APHY_RSV__SHIFT 0x00000018
+#define MC_SEQ_IO_RESERVE_D0__DPHY0_RSV_MASK 0x00000fffL
+#define MC_SEQ_IO_RESERVE_D0__DPHY0_RSV__SHIFT 0x00000000
+#define MC_SEQ_IO_RESERVE_D0__DPHY1_RSV_MASK 0x00fff000L
+#define MC_SEQ_IO_RESERVE_D0__DPHY1_RSV__SHIFT 0x0000000c
+#define MC_SEQ_IO_RESERVE_D1__APHY_RSV_MASK 0xff000000L
+#define MC_SEQ_IO_RESERVE_D1__APHY_RSV__SHIFT 0x00000018
+#define MC_SEQ_IO_RESERVE_D1__DPHY0_RSV_MASK 0x00000fffL
+#define MC_SEQ_IO_RESERVE_D1__DPHY0_RSV__SHIFT 0x00000000
+#define MC_SEQ_IO_RESERVE_D1__DPHY1_RSV_MASK 0x00fff000L
+#define MC_SEQ_IO_RESERVE_D1__DPHY1_RSV__SHIFT 0x0000000c
+#define MC_SEQ_IO_RWORD0__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD0__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD1__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD1__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD2__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD2__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD3__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD3__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD4__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD4__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD5__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD5__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD6__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD6__RDATA__SHIFT 0x00000000
+#define MC_SEQ_IO_RWORD7__RDATA_MASK 0xffffffffL
+#define MC_SEQ_IO_RWORD7__RDATA__SHIFT 0x00000000
+#define MC_SEQ_MISC0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC3__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC3__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC4__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC4__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC5__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC5__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC6__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC6__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC7__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC7__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC8__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC8__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC9__VALUE_MASK 0xffffffffL
+#define MC_SEQ_MISC9__VALUE__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING2__FAW_MASK 0x00001f00L
+#define MC_SEQ_MISC_TIMING2__FAW__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING2_LP__FAW_MASK 0x00001f00L
+#define MC_SEQ_MISC_TIMING2_LP__FAW__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING2_LP__PA2RDATA_MASK 0x00000007L
+#define MC_SEQ_MISC_TIMING2_LP__PA2RDATA__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING2_LP__PA2WDATA_MASK 0x00000070L
+#define MC_SEQ_MISC_TIMING2_LP__PA2WDATA__SHIFT 0x00000004
+#define MC_SEQ_MISC_TIMING2_LP__TADR_MASK 0x00e00000L
+#define MC_SEQ_MISC_TIMING2_LP__TADR__SHIFT 0x00000015
+#define MC_SEQ_MISC_TIMING2_LP__TFCKTR_MASK 0x0f000000L
+#define MC_SEQ_MISC_TIMING2_LP__TFCKTR__SHIFT 0x00000018
+#define MC_SEQ_MISC_TIMING2_LP__TREDC_MASK 0x0000e000L
+#define MC_SEQ_MISC_TIMING2_LP__TREDC__SHIFT 0x0000000d
+#define MC_SEQ_MISC_TIMING2_LP__TWDATATR_MASK 0xf0000000L
+#define MC_SEQ_MISC_TIMING2_LP__TWDATATR__SHIFT 0x0000001c
+#define MC_SEQ_MISC_TIMING2_LP__TWEDC_MASK 0x001f0000L
+#define MC_SEQ_MISC_TIMING2_LP__TWEDC__SHIFT 0x00000010
+#define MC_SEQ_MISC_TIMING2__PA2RDATA_MASK 0x00000007L
+#define MC_SEQ_MISC_TIMING2__PA2RDATA__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING2__PA2WDATA_MASK 0x00000070L
+#define MC_SEQ_MISC_TIMING2__PA2WDATA__SHIFT 0x00000004
+#define MC_SEQ_MISC_TIMING2__T32AW_MASK 0x01e00000L
+#define MC_SEQ_MISC_TIMING2__T32AW__SHIFT 0x00000015
+#define MC_SEQ_MISC_TIMING2__TREDC_MASK 0x0000e000L
+#define MC_SEQ_MISC_TIMING2__TREDC__SHIFT 0x0000000d
+#define MC_SEQ_MISC_TIMING2__TWDATATR_MASK 0xf0000000L
+#define MC_SEQ_MISC_TIMING2__TWDATATR__SHIFT 0x0000001c
+#define MC_SEQ_MISC_TIMING2__TWEDC_MASK 0x001f0000L
+#define MC_SEQ_MISC_TIMING2__TWEDC__SHIFT 0x00000010
+#define MC_SEQ_MISC_TIMING_LP__TRFC_MASK 0x1ff00000L
+#define MC_SEQ_MISC_TIMING_LP__TRFC__SHIFT 0x00000014
+#define MC_SEQ_MISC_TIMING_LP__TRP_MASK 0x000f8000L
+#define MC_SEQ_MISC_TIMING_LP__TRP_RDA_MASK 0x00003f00L
+#define MC_SEQ_MISC_TIMING_LP__TRP_RDA__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING_LP__TRP__SHIFT 0x0000000f
+#define MC_SEQ_MISC_TIMING_LP__TRP_WRA_MASK 0x0000003fL
+#define MC_SEQ_MISC_TIMING_LP__TRP_WRA__SHIFT 0x00000000
+#define MC_SEQ_MISC_TIMING__TRFC_MASK 0x1ff00000L
+#define MC_SEQ_MISC_TIMING__TRFC__SHIFT 0x00000014
+#define MC_SEQ_MISC_TIMING__TRP_MASK 0x000f8000L
+#define MC_SEQ_MISC_TIMING__TRP_RDA_MASK 0x00003f00L
+#define MC_SEQ_MISC_TIMING__TRP_RDA__SHIFT 0x00000008
+#define MC_SEQ_MISC_TIMING__TRP__SHIFT 0x0000000f
+#define MC_SEQ_MISC_TIMING__TRP_WRA_MASK 0x0000003fL
+#define MC_SEQ_MISC_TIMING__TRP_WRA__SHIFT 0x00000000
+#define MC_SEQ_MPLL_OVERRIDE__AD_PLL_RESET_OVERRIDE_MASK 0x00000001L
+#define MC_SEQ_MPLL_OVERRIDE__AD_PLL_RESET_OVERRIDE__SHIFT 0x00000000
+#define MC_SEQ_MPLL_OVERRIDE__ATGM_CLK_SEL_OVERRIDE_MASK 0x00000020L
+#define MC_SEQ_MPLL_OVERRIDE__ATGM_CLK_SEL_OVERRIDE__SHIFT 0x00000005
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_0_PLL_RESET_OVERRIDE_MASK 0x00000002L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_0_PLL_RESET_OVERRIDE__SHIFT 0x00000001
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_1_PLL_RESET_OVERRIDE_MASK 0x00000004L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_0_1_PLL_RESET_OVERRIDE__SHIFT 0x00000002
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_0_PLL_RESET_OVERRIDE_MASK 0x00000008L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_0_PLL_RESET_OVERRIDE__SHIFT 0x00000003
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_1_PLL_RESET_OVERRIDE_MASK 0x00000010L
+#define MC_SEQ_MPLL_OVERRIDE__DQ_1_1_PLL_RESET_OVERRIDE__SHIFT 0x00000004
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_EN_OVERRIDE_MASK 0x00000040L
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_EN_OVERRIDE__SHIFT 0x00000006
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_SEL_OVERRIDE_MASK 0x00000080L
+#define MC_SEQ_MPLL_OVERRIDE__TEST_BYPASS_CLK_SEL_OVERRIDE__SHIFT 0x00000007
+#define MC_SEQ_PERF_CNTL_1__PAUSE_MASK 0x00000001L
+#define MC_SEQ_PERF_CNTL_1__PAUSE__SHIFT 0x00000000
+#define MC_SEQ_PERF_CNTL_1__SEL_A_MSB_MASK 0x00000100L
+#define MC_SEQ_PERF_CNTL_1__SEL_A_MSB__SHIFT 0x00000008
+#define MC_SEQ_PERF_CNTL_1__SEL_B_MSB_MASK 0x00000200L
+#define MC_SEQ_PERF_CNTL_1__SEL_B_MSB__SHIFT 0x00000009
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_C_MSB_MASK 0x00000400L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_C_MSB__SHIFT 0x0000000a
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_D_MSB_MASK 0x00000800L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH0_D_MSB__SHIFT 0x0000000b
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_A_MSB_MASK 0x00001000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_A_MSB__SHIFT 0x0000000c
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_B_MSB_MASK 0x00002000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_B_MSB__SHIFT 0x0000000d
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_C_MSB_MASK 0x00004000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_C_MSB__SHIFT 0x0000000e
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_D_MSB_MASK 0x00008000L
+#define MC_SEQ_PERF_CNTL_1__SEL_CH1_D_MSB__SHIFT 0x0000000f
+#define MC_SEQ_PERF_CNTL__CNTL_MASK 0xc0000000L
+#define MC_SEQ_PERF_CNTL__CNTL__SHIFT 0x0000001e
+#define MC_SEQ_PERF_CNTL__MONITOR_PERIOD_MASK 0x3fffffffL
+#define MC_SEQ_PERF_CNTL__MONITOR_PERIOD__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_A_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_A_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_A_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_A_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_B_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_B_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_B_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_B_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_C_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_C_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_C_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_C_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_D_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_D_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CNT_D_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_PERF_SEQ_CNT_D_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CTL__SEL_A_MASK 0x0000000fL
+#define MC_SEQ_PERF_SEQ_CTL__SEL_A__SHIFT 0x00000000
+#define MC_SEQ_PERF_SEQ_CTL__SEL_B_MASK 0x000000f0L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_B__SHIFT 0x00000004
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_C_MASK 0x00000f00L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_C__SHIFT 0x00000008
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_D_MASK 0x0000f000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH0_D__SHIFT 0x0000000c
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_A_MASK 0x000f0000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_A__SHIFT 0x00000010
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_B_MASK 0x00f00000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_B__SHIFT 0x00000014
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_C_MASK 0x0f000000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_C__SHIFT 0x00000018
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_D_MASK 0xf0000000L
+#define MC_SEQ_PERF_SEQ_CTL__SEL_CH1_D__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_EMRS_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_EMRS_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_EMRS_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_EMRS_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_EMRS_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_EMRS_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_MRS1_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_MRS1_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_MRS1_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_MRS1_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_MRS1_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_MRS1_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_MRS2_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_MRS2_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_MRS2_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_MRS2_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_MRS2_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_MRS2_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MASK 0x0000ffffL
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB0_MASK 0x20000000L
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB0__SHIFT 0x0000001d
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB1_MASK 0x10000000L
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR_MSB1__SHIFT 0x0000001c
+#define MC_SEQ_PMG_CMD_MRS_LP__ADR__SHIFT 0x00000000
+#define MC_SEQ_PMG_CMD_MRS_LP__BNK_MSB_MASK 0x00080000L
+#define MC_SEQ_PMG_CMD_MRS_LP__BNK_MSB__SHIFT 0x00000013
+#define MC_SEQ_PMG_CMD_MRS_LP__CSB_MASK 0x00600000L
+#define MC_SEQ_PMG_CMD_MRS_LP__CSB__SHIFT 0x00000015
+#define MC_SEQ_PMG_CMD_MRS_LP__END_MASK 0x00100000L
+#define MC_SEQ_PMG_CMD_MRS_LP__END__SHIFT 0x00000014
+#define MC_SEQ_PMG_CMD_MRS_LP__MOP_MASK 0x00070000L
+#define MC_SEQ_PMG_CMD_MRS_LP__MOP__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_HWCNTL__ACAO_MASK 0x00040000L
+#define MC_SEQ_PMG_PG_HWCNTL__ACAO__SHIFT 0x00000012
+#define MC_SEQ_PMG_PG_HWCNTL__AC_DLY_MASK 0x00000300L
+#define MC_SEQ_PMG_PG_HWCNTL__AC_DLY__SHIFT 0x00000008
+#define MC_SEQ_PMG_PG_HWCNTL__D_DLY_MASK 0x000000c0L
+#define MC_SEQ_PMG_PG_HWCNTL__D_DLY__SHIFT 0x00000006
+#define MC_SEQ_PMG_PG_HWCNTL__G_DLY_MASK 0x00003c00L
+#define MC_SEQ_PMG_PG_HWCNTL__G_DLY__SHIFT 0x0000000a
+#define MC_SEQ_PMG_PG_HWCNTL__PWRGATE_EN_MASK 0x00000001L
+#define MC_SEQ_PMG_PG_HWCNTL__PWRGATE_EN__SHIFT 0x00000000
+#define MC_SEQ_PMG_PG_HWCNTL__RXAO_MASK 0x00020000L
+#define MC_SEQ_PMG_PG_HWCNTL__RXAO__SHIFT 0x00000011
+#define MC_SEQ_PMG_PG_HWCNTL__STAGGER_EN_MASK 0x00000002L
+#define MC_SEQ_PMG_PG_HWCNTL__STAGGER_EN__SHIFT 0x00000001
+#define MC_SEQ_PMG_PG_HWCNTL__TPGCG_MASK 0x0000003cL
+#define MC_SEQ_PMG_PG_HWCNTL__TPGCG__SHIFT 0x00000002
+#define MC_SEQ_PMG_PG_HWCNTL__TXAO_MASK 0x00010000L
+#define MC_SEQ_PMG_PG_HWCNTL__TXAO__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_SWCNTL_0__GMCON_SR_COMMIT_MASK 0x80000000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__GMCON_SR_COMMIT__SHIFT 0x0000001f
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMA0_AC_ENB_MASK 0x00010000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMA0_AC_ENB__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_RX_ENB_MASK 0x00000020L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_RX_ENB__SHIFT 0x00000005
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_TX_ENB_MASK 0x00000002L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DBI_TX_ENB__SHIFT 0x00000001
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_RX_ENB_MASK 0x00000010L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_RX_ENB__SHIFT 0x00000004
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_TX_ENB_MASK 0x00000001L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_DQ_TX_ENB__SHIFT 0x00000000
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_RX_ENB_MASK 0x00000040L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_RX_ENB__SHIFT 0x00000006
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_TX_ENB_MASK 0x00000004L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_EDC_TX_ENB__SHIFT 0x00000002
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_RX_ENB_MASK 0x00000080L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_RX_ENB__SHIFT 0x00000007
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_TX_ENB_MASK 0x00000008L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD0_WCLKX_TX_ENB__SHIFT 0x00000003
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_RX_ENB_MASK 0x00002000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_RX_ENB__SHIFT 0x0000000d
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_TX_ENB_MASK 0x00000200L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DBI_TX_ENB__SHIFT 0x00000009
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_RX_ENB_MASK 0x00001000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_RX_ENB__SHIFT 0x0000000c
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_TX_ENB_MASK 0x00000100L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_DQ_TX_ENB__SHIFT 0x00000008
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_RX_ENB_MASK 0x00004000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_RX_ENB__SHIFT 0x0000000e
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_TX_ENB_MASK 0x00000400L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_EDC_TX_ENB__SHIFT 0x0000000a
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_RX_ENB_MASK 0x00008000L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_RX_ENB__SHIFT 0x0000000f
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_TX_ENB_MASK 0x00000800L
+#define MC_SEQ_PMG_PG_SWCNTL_0__PMD1_WCLKX_TX_ENB__SHIFT 0x0000000b
+#define MC_SEQ_PMG_PG_SWCNTL_1__GMCON_SR_COMMIT_MASK 0x80000000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__GMCON_SR_COMMIT__SHIFT 0x0000001f
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMA1_AC_ENB_MASK 0x00010000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMA1_AC_ENB__SHIFT 0x00000010
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_RX_ENB_MASK 0x00000020L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_RX_ENB__SHIFT 0x00000005
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_TX_ENB_MASK 0x00000002L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DBI_TX_ENB__SHIFT 0x00000001
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_RX_ENB_MASK 0x00000010L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_RX_ENB__SHIFT 0x00000004
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_TX_ENB_MASK 0x00000001L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_DQ_TX_ENB__SHIFT 0x00000000
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_RX_ENB_MASK 0x00000040L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_RX_ENB__SHIFT 0x00000006
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_TX_ENB_MASK 0x00000004L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_EDC_TX_ENB__SHIFT 0x00000002
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_RX_ENB_MASK 0x00000080L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_RX_ENB__SHIFT 0x00000007
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_TX_ENB_MASK 0x00000008L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD2_WCLKX_TX_ENB__SHIFT 0x00000003
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_RX_ENB_MASK 0x00002000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_RX_ENB__SHIFT 0x0000000d
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_TX_ENB_MASK 0x00000200L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DBI_TX_ENB__SHIFT 0x00000009
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_RX_ENB_MASK 0x00001000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_RX_ENB__SHIFT 0x0000000c
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_TX_ENB_MASK 0x00000100L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_DQ_TX_ENB__SHIFT 0x00000008
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_RX_ENB_MASK 0x00004000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_RX_ENB__SHIFT 0x0000000e
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_TX_ENB_MASK 0x00000400L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_EDC_TX_ENB__SHIFT 0x0000000a
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_RX_ENB_MASK 0x00008000L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_RX_ENB__SHIFT 0x0000000f
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_TX_ENB_MASK 0x00000800L
+#define MC_SEQ_PMG_PG_SWCNTL_1__PMD3_WCLKX_TX_ENB__SHIFT 0x0000000b
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE_MASK 0x001c0000L
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE__SHIFT 0x00000012
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE_SS_MASK 0xff000000L
+#define MC_SEQ_PMG_TIMING_LP__SEQ_IDLE_SS__SHIFT 0x00000018
+#define MC_SEQ_PMG_TIMING_LP__TCKE_MASK 0x0003f000L
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE_MASK 0x00000f00L
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE_MSB_MASK 0x00800000L
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE_MSB__SHIFT 0x00000017
+#define MC_SEQ_PMG_TIMING_LP__TCKE_PULSE__SHIFT 0x00000008
+#define MC_SEQ_PMG_TIMING_LP__TCKE__SHIFT 0x0000000c
+#define MC_SEQ_PMG_TIMING_LP__TCKSRE_MASK 0x00000007L
+#define MC_SEQ_PMG_TIMING_LP__TCKSRE__SHIFT 0x00000000
+#define MC_SEQ_PMG_TIMING_LP__TCKSRX_MASK 0x00000070L
+#define MC_SEQ_PMG_TIMING_LP__TCKSRX__SHIFT 0x00000004
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE_MASK 0x001c0000L
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE__SHIFT 0x00000012
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE_SS_MASK 0xff000000L
+#define MC_SEQ_PMG_TIMING__SEQ_IDLE_SS__SHIFT 0x00000018
+#define MC_SEQ_PMG_TIMING__TCKE_MASK 0x0003f000L
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE_MASK 0x00000f00L
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE_MSB_MASK 0x00800000L
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE_MSB__SHIFT 0x00000017
+#define MC_SEQ_PMG_TIMING__TCKE_PULSE__SHIFT 0x00000008
+#define MC_SEQ_PMG_TIMING__TCKE__SHIFT 0x0000000c
+#define MC_SEQ_PMG_TIMING__TCKSRE_MASK 0x00000007L
+#define MC_SEQ_PMG_TIMING__TCKSRE__SHIFT 0x00000000
+#define MC_SEQ_PMG_TIMING__TCKSRX_MASK 0x00000070L
+#define MC_SEQ_PMG_TIMING__TCKSRX__SHIFT 0x00000004
+#define MC_SEQ_RAS_TIMING_LP__TRCDRA_MASK 0x000f8000L
+#define MC_SEQ_RAS_TIMING_LP__TRCDRA__SHIFT 0x0000000f
+#define MC_SEQ_RAS_TIMING_LP__TRCDR_MASK 0x00007c00L
+#define MC_SEQ_RAS_TIMING_LP__TRCDR__SHIFT 0x0000000a
+#define MC_SEQ_RAS_TIMING_LP__TRCDWA_MASK 0x000003e0L
+#define MC_SEQ_RAS_TIMING_LP__TRCDWA__SHIFT 0x00000005
+#define MC_SEQ_RAS_TIMING_LP__TRCDW_MASK 0x0000001fL
+#define MC_SEQ_RAS_TIMING_LP__TRCDW__SHIFT 0x00000000
+#define MC_SEQ_RAS_TIMING_LP__TRC_MASK 0x7f000000L
+#define MC_SEQ_RAS_TIMING_LP__TRC__SHIFT 0x00000018
+#define MC_SEQ_RAS_TIMING_LP__TRRD_MASK 0x00f00000L
+#define MC_SEQ_RAS_TIMING_LP__TRRD__SHIFT 0x00000014
+#define MC_SEQ_RAS_TIMING__TRCDRA_MASK 0x000f8000L
+#define MC_SEQ_RAS_TIMING__TRCDRA__SHIFT 0x0000000f
+#define MC_SEQ_RAS_TIMING__TRCDR_MASK 0x00007c00L
+#define MC_SEQ_RAS_TIMING__TRCDR__SHIFT 0x0000000a
+#define MC_SEQ_RAS_TIMING__TRCDWA_MASK 0x000003e0L
+#define MC_SEQ_RAS_TIMING__TRCDWA__SHIFT 0x00000005
+#define MC_SEQ_RAS_TIMING__TRCDW_MASK 0x0000001fL
+#define MC_SEQ_RAS_TIMING__TRCDW__SHIFT 0x00000000
+#define MC_SEQ_RAS_TIMING__TRC_MASK 0x7f000000L
+#define MC_SEQ_RAS_TIMING__TRC__SHIFT 0x00000018
+#define MC_SEQ_RAS_TIMING__TRRD_MASK 0x00f00000L
+#define MC_SEQ_RAS_TIMING__TRRD__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D0_LP__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D0_LP__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D0_LP__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D0_LP__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D0_LP__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D0_LP__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D0_LP__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D0_LP__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D0_LP__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D0_LP__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D0_LP__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D0_LP__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D0_LP__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D0_LP__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D0_LP__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D0_LP__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D0_LP__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D0_LP__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RD_CTL_D0__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D0__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D0__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D0__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D0__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D0__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D0__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D0__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D0__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D0__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D0__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D0__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D0__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D0__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D0__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D0__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D0__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D0__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RD_CTL_D1_LP__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D1_LP__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D1_LP__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D1_LP__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D1_LP__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D1_LP__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D1_LP__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D1_LP__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D1_LP__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D1_LP__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D1_LP__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D1_LP__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D1_LP__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D1_LP__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D1_LP__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D1_LP__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D1_LP__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D1_LP__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RD_CTL_D1__RBS_DLY_MASK 0x01f00000L
+#define MC_SEQ_RD_CTL_D1__RBS_DLY__SHIFT 0x00000014
+#define MC_SEQ_RD_CTL_D1__RBS_WEDC_DLY_MASK 0x3e000000L
+#define MC_SEQ_RD_CTL_D1__RBS_WEDC_DLY__SHIFT 0x00000019
+#define MC_SEQ_RD_CTL_D1__RCV_DLY_MASK 0x00000007L
+#define MC_SEQ_RD_CTL_D1__RCV_DLY__SHIFT 0x00000000
+#define MC_SEQ_RD_CTL_D1__RCV_EXT_MASK 0x000000f8L
+#define MC_SEQ_RD_CTL_D1__RCV_EXT__SHIFT 0x00000003
+#define MC_SEQ_RD_CTL_D1__RST_HLD_MASK 0x0000f000L
+#define MC_SEQ_RD_CTL_D1__RST_HLD__SHIFT 0x0000000c
+#define MC_SEQ_RD_CTL_D1__RST_SEL_MASK 0x00000300L
+#define MC_SEQ_RD_CTL_D1__RST_SEL__SHIFT 0x00000008
+#define MC_SEQ_RD_CTL_D1__RXDPWRON_DLY_MASK 0x00000c00L
+#define MC_SEQ_RD_CTL_D1__RXDPWRON_DLY__SHIFT 0x0000000a
+#define MC_SEQ_RD_CTL_D1__STR_PRE_MASK 0x00010000L
+#define MC_SEQ_RD_CTL_D1__STR_PRE__SHIFT 0x00000010
+#define MC_SEQ_RD_CTL_D1__STR_PST_MASK 0x00020000L
+#define MC_SEQ_RD_CTL_D1__STR_PST__SHIFT 0x00000011
+#define MC_SEQ_RESERVE_0_S__SCLK_FIELD_MASK 0xffffffffL
+#define MC_SEQ_RESERVE_0_S__SCLK_FIELD__SHIFT 0x00000000
+#define MC_SEQ_RESERVE_1_S__SCLK_FIELD_MASK 0xffffffffL
+#define MC_SEQ_RESERVE_1_S__SCLK_FIELD__SHIFT 0x00000000
+#define MC_SEQ_RESERVE_M__MCLK_FIELD_MASK 0xffffffffL
+#define MC_SEQ_RESERVE_M__MCLK_FIELD__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE0_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE1_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE2_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_BYTE3_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_DBI_D0__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_DBI_D1__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_EDC_D0__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_EDC_D0__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC0_MASK 0x0000000fL
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC0__SHIFT 0x00000000
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC1_MASK 0x000000f0L
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC1__SHIFT 0x00000004
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC2_MASK 0x00000f00L
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC2__SHIFT 0x00000008
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC3_MASK 0x0000f000L
+#define MC_SEQ_RXFRAMING_EDC_D1__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_RXFRAMING_EDC_D1__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_STATUS_M__CMD_RDY_D0_MASK 0x00000004L
+#define MC_SEQ_STATUS_M__CMD_RDY_D0__SHIFT 0x00000002
+#define MC_SEQ_STATUS_M__CMD_RDY_D1_MASK 0x00000008L
+#define MC_SEQ_STATUS_M__CMD_RDY_D1__SHIFT 0x00000003
+#define MC_SEQ_STATUS_M__PMG_FSMSTATE_MASK 0x01f00000L
+#define MC_SEQ_STATUS_M__PMG_FSMSTATE__SHIFT 0x00000014
+#define MC_SEQ_STATUS_M__PMG_PWRSTATE_MASK 0x00010000L
+#define MC_SEQ_STATUS_M__PMG_PWRSTATE__SHIFT 0x00000010
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D0_MASK 0x00000001L
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D0__SHIFT 0x00000000
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D1_MASK 0x00000002L
+#define MC_SEQ_STATUS_M__PWRUP_COMPL_D1__SHIFT 0x00000001
+#define MC_SEQ_STATUS_M__SEQ0_ARB_CMD_FIFO_EMPTY_MASK 0x00000100L
+#define MC_SEQ_STATUS_M__SEQ0_ARB_CMD_FIFO_EMPTY__SHIFT 0x00000008
+#define MC_SEQ_STATUS_M__SEQ0_BUSY_HYS_MASK 0x02000000L
+#define MC_SEQ_STATUS_M__SEQ0_BUSY_HYS__SHIFT 0x00000019
+#define MC_SEQ_STATUS_M__SEQ0_BUSY_MASK 0x00004000L
+#define MC_SEQ_STATUS_M__SEQ0_BUSY__SHIFT 0x0000000e
+#define MC_SEQ_STATUS_M__SEQ0_RS_DATA_FIFO_FULL_MASK 0x00001000L
+#define MC_SEQ_STATUS_M__SEQ0_RS_DATA_FIFO_FULL__SHIFT 0x0000000c
+#define MC_SEQ_STATUS_M__SEQ1_ARB_CMD_FIFO_EMPTY_MASK 0x00000200L
+#define MC_SEQ_STATUS_M__SEQ1_ARB_CMD_FIFO_EMPTY__SHIFT 0x00000009
+#define MC_SEQ_STATUS_M__SEQ1_BUSY_HYS_MASK 0x04000000L
+#define MC_SEQ_STATUS_M__SEQ1_BUSY_HYS__SHIFT 0x0000001a
+#define MC_SEQ_STATUS_M__SEQ1_BUSY_MASK 0x00008000L
+#define MC_SEQ_STATUS_M__SEQ1_BUSY__SHIFT 0x0000000f
+#define MC_SEQ_STATUS_M__SEQ1_RS_DATA_FIFO_FULL_MASK 0x00002000L
+#define MC_SEQ_STATUS_M__SEQ1_RS_DATA_FIFO_FULL__SHIFT 0x0000000d
+#define MC_SEQ_STATUS_M__SLF_D0_MASK 0x00000010L
+#define MC_SEQ_STATUS_M__SLF_D0__SHIFT 0x00000004
+#define MC_SEQ_STATUS_M__SLF_D1_MASK 0x00000020L
+#define MC_SEQ_STATUS_M__SLF_D1__SHIFT 0x00000005
+#define MC_SEQ_STATUS_M__SS_SLF_D0_MASK 0x00000040L
+#define MC_SEQ_STATUS_M__SS_SLF_D0__SHIFT 0x00000006
+#define MC_SEQ_STATUS_M__SS_SLF_D1_MASK 0x00000080L
+#define MC_SEQ_STATUS_M__SS_SLF_D1__SHIFT 0x00000007
+#define MC_SEQ_STATUS_S__SEQ0_ARB_CMD_FIFO_FULL_MASK 0x00000010L
+#define MC_SEQ_STATUS_S__SEQ0_ARB_CMD_FIFO_FULL__SHIFT 0x00000004
+#define MC_SEQ_STATUS_S__SEQ0_ARB_DATA_FIFO_FULL_MASK 0x00000001L
+#define MC_SEQ_STATUS_S__SEQ0_ARB_DATA_FIFO_FULL__SHIFT 0x00000000
+#define MC_SEQ_STATUS_S__SEQ0_RS_DATA_FIFO_EMPTY_MASK 0x00000100L
+#define MC_SEQ_STATUS_S__SEQ0_RS_DATA_FIFO_EMPTY__SHIFT 0x00000008
+#define MC_SEQ_STATUS_S__SEQ1_ARB_CMD_FIFO_FULL_MASK 0x00000020L
+#define MC_SEQ_STATUS_S__SEQ1_ARB_CMD_FIFO_FULL__SHIFT 0x00000005
+#define MC_SEQ_STATUS_S__SEQ1_ARB_DATA_FIFO_FULL_MASK 0x00000002L
+#define MC_SEQ_STATUS_S__SEQ1_ARB_DATA_FIFO_FULL__SHIFT 0x00000001
+#define MC_SEQ_STATUS_S__SEQ1_RS_DATA_FIFO_EMPTY_MASK 0x00000200L
+#define MC_SEQ_STATUS_S__SEQ1_RS_DATA_FIFO_EMPTY__SHIFT 0x00000009
+#define MC_SEQ_SUP_CNTL__BKPT_CLEAR_MASK 0x00000080L
+#define MC_SEQ_SUP_CNTL__BKPT_CLEAR__SHIFT 0x00000007
+#define MC_SEQ_SUP_CNTL__FAST_WRITE_MASK 0x00000040L
+#define MC_SEQ_SUP_CNTL__FAST_WRITE__SHIFT 0x00000006
+#define MC_SEQ_SUP_CNTL__PGM_CHKSUM_MASK 0xff800000L
+#define MC_SEQ_SUP_CNTL__PGM_CHKSUM__SHIFT 0x00000017
+#define MC_SEQ_SUP_CNTL__PGM_READ_MASK 0x00000020L
+#define MC_SEQ_SUP_CNTL__PGM_READ__SHIFT 0x00000005
+#define MC_SEQ_SUP_CNTL__PGM_WRITE_MASK 0x00000010L
+#define MC_SEQ_SUP_CNTL__PGM_WRITE__SHIFT 0x00000004
+#define MC_SEQ_SUP_CNTL__RESET_PC_MASK 0x00000008L
+#define MC_SEQ_SUP_CNTL__RESET_PC__SHIFT 0x00000003
+#define MC_SEQ_SUP_CNTL__RUN_MASK 0x00000001L
+#define MC_SEQ_SUP_CNTL__RUN__SHIFT 0x00000000
+#define MC_SEQ_SUP_CNTL__SINGLE_STEP_MASK 0x00000002L
+#define MC_SEQ_SUP_CNTL__SINGLE_STEP__SHIFT 0x00000001
+#define MC_SEQ_SUP_CNTL__SW_WAKE_MASK 0x00000004L
+#define MC_SEQ_SUP_CNTL__SW_WAKE__SHIFT 0x00000002
+#define MC_SEQ_SUP_DEC_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_DEC_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP0_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP0_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP1_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP1_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP2_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP2_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_GP3_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_GP3_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_IR_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_IR_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_PGM__CNTL_MASK 0xffffffffL
+#define MC_SEQ_SUP_PGM__CNTL__SHIFT 0x00000000
+#define MC_SEQ_SUP_PGM_STAT__STATUS_MASK 0xffffffffL
+#define MC_SEQ_SUP_PGM_STAT__STATUS__SHIFT 0x00000000
+#define MC_SEQ_SUP_R_PGM__PGM_MASK 0xffffffffL
+#define MC_SEQ_SUP_R_PGM__PGM__SHIFT 0x00000000
+#define MC_SEQ_TCG_CNTL__AREF_BOTH_MASK 0x04000000L
+#define MC_SEQ_TCG_CNTL__AREF_BOTH__SHIFT 0x0000001a
+#define MC_SEQ_TCG_CNTL__AREF_LAST_MASK 0x02000000L
+#define MC_SEQ_TCG_CNTL__AREF_LAST__SHIFT 0x00000019
+#define MC_SEQ_TCG_CNTL__BURST_NUM_MASK 0x00380000L
+#define MC_SEQ_TCG_CNTL__BURST_NUM__SHIFT 0x00000013
+#define MC_SEQ_TCG_CNTL__DATA_CNT_MASK 0x0000f000L
+#define MC_SEQ_TCG_CNTL__DATA_CNT__SHIFT 0x0000000c
+#define MC_SEQ_TCG_CNTL__DONE_MASK 0x80000000L
+#define MC_SEQ_TCG_CNTL__DONE__SHIFT 0x0000001f
+#define MC_SEQ_TCG_CNTL__ENABLE_D0_MASK 0x00000002L
+#define MC_SEQ_TCG_CNTL__ENABLE_D0__SHIFT 0x00000001
+#define MC_SEQ_TCG_CNTL__ENABLE_D1_MASK 0x00000004L
+#define MC_SEQ_TCG_CNTL__ENABLE_D1__SHIFT 0x00000002
+#define MC_SEQ_TCG_CNTL__FRAME_TRAIN_MASK 0x00040000L
+#define MC_SEQ_TCG_CNTL__FRAME_TRAIN__SHIFT 0x00000012
+#define MC_SEQ_TCG_CNTL__INFINITE_CMD_MASK 0x00000080L
+#define MC_SEQ_TCG_CNTL__INFINITE_CMD__SHIFT 0x00000007
+#define MC_SEQ_TCG_CNTL__ISSUE_AREF_MASK 0x00400000L
+#define MC_SEQ_TCG_CNTL__ISSUE_AREF__SHIFT 0x00000016
+#define MC_SEQ_TCG_CNTL__LOAD_FIFO_MASK 0x00010000L
+#define MC_SEQ_TCG_CNTL__LOAD_FIFO__SHIFT 0x00000010
+#define MC_SEQ_TCG_CNTL__MOP_MASK 0x00000f00L
+#define MC_SEQ_TCG_CNTL__MOP__SHIFT 0x00000008
+#define MC_SEQ_TCG_CNTL__NFIFO_MASK 0x00000070L
+#define MC_SEQ_TCG_CNTL__NFIFO__SHIFT 0x00000004
+#define MC_SEQ_TCG_CNTL__RESET_MASK 0x00000001L
+#define MC_SEQ_TCG_CNTL__RESET__SHIFT 0x00000000
+#define MC_SEQ_TCG_CNTL__SHORT_LDFF_MASK 0x00020000L
+#define MC_SEQ_TCG_CNTL__SHORT_LDFF__SHIFT 0x00000011
+#define MC_SEQ_TCG_CNTL__START_MASK 0x00000008L
+#define MC_SEQ_TCG_CNTL__START__SHIFT 0x00000003
+#define MC_SEQ_TCG_CNTL__TXDBI_CNTL_MASK 0x00800000L
+#define MC_SEQ_TCG_CNTL__TXDBI_CNTL__SHIFT 0x00000017
+#define MC_SEQ_TCG_CNTL__VPTR_MASK_MASK 0x01000000L
+#define MC_SEQ_TCG_CNTL__VPTR_MASK__SHIFT 0x00000018
+#define MC_SEQ_TIMER_RD__COUNTER_MASK 0xffffffffL
+#define MC_SEQ_TIMER_RD__COUNTER__SHIFT 0x00000000
+#define MC_SEQ_TIMER_WR__COUNTER_MASK 0xffffffffL
+#define MC_SEQ_TIMER_WR__COUNTER__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_CAPTURE__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_CAPTURE__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_CAPTURE__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_CAPTURE__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_CAPTURE__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_CAPTURE__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_CAPTURE__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_CAPTURE__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_CAPTURE__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_CAPTURE__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_CAPTURE__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_CAPTURE__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_CAPTURE__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_CAPTURE__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_CAPTURE__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_CAPTURE__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_CAPTURE__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_CAPTURE__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_CAPTURE__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_CAPTURE__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_CAPTURE__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_CAPTURE__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_CAPTURE__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_CAPTURE__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_CAPTURE__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_CAPTURE__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_CAPTURE__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_CAPTURE__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_CAPTURE__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_CAPTURE__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_CAPTURE__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_CAPTURE__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_CAPTURE__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_CAPTURE__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_CAPTURE__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_CAPTURE__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_CAPTURE__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_CAPTURE__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_CAPTURE__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_CAPTURE__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_CAPTURE__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_CAPTURE__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_CAPTURE__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_CAPTURE__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_CAPTURE__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_EDC_THRESHOLD2__THRESHOLD_PERIOD_MASK 0xffffffffL
+#define MC_SEQ_TRAIN_EDC_THRESHOLD2__THRESHOLD_PERIOD__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_IN_PROGRESS_MASK 0x00000100L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_IN_PROGRESS__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_STATUS_MASK 0x00000001L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH0_LINK_RETRAIN_STATUS__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_IN_PROGRESS_MASK 0x00000200L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_IN_PROGRESS__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_STATUS_MASK 0x00000002L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CH1_LINK_RETRAIN_STATUS__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CLEAR_RETRAIN_STATUS_MASK 0x00000004L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__CLEAR_RETRAIN_STATUS__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_MONITOR_MASK 0x00000030L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_MONITOR__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_VBI_MASK 0x00000008L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD3__RETRAIN_VBI__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__READ_EDC_THRESHOLD_MASK 0xffff0000L
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__READ_EDC_THRESHOLD__SHIFT 0x00000010
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__WRITE_EDC_THRESHOLD_MASK 0x0000ffffL
+#define MC_SEQ_TRAIN_EDC_THRESHOLD__WRITE_EDC_THRESHOLD__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_TIMING__TARF2T_MASK 0x000003e0L
+#define MC_SEQ_TRAIN_TIMING__TARF2T__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_TIMING__TLD2LD_MASK 0x000f8000L
+#define MC_SEQ_TRAIN_TIMING__TLD2LD__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_TIMING__TT2ROW_MASK 0x00007c00L
+#define MC_SEQ_TRAIN_TIMING__TT2ROW__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_TIMING__TWT2RT_MASK 0x0000001fL
+#define MC_SEQ_TRAIN_TIMING__TWT2RT__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__CLEARALL_MASK 0x00010000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__CLEARALL__SHIFT 0x00000010
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_CLEAR__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_ADDR_TRAIN_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_ADDR_TRAIN__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_READ_TRAIN_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_READ_TRAIN__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WAKEUP_EARLY_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WAKEUP_EARLY__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WCK_TRAIN_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WCK_TRAIN__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WRITE_TRAIN_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__AUTO_REFRESH_WRITE_TRAIN__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D0_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D0__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D1_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_RD_D1__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D0_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D0__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D1_MASK 0x08000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BLOCK_ARB_WR_D1__SHIFT 0x0000001b
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_ADDR_TRAIN_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_ADDR_TRAIN__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_READ_TRAIN_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_READ_TRAIN__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WCK_TRAIN_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WCK_TRAIN__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WRITE_TRAIN_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__BOOT_UP_WRITE_TRAIN__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__DISP_ASTOP_WAKEUP_MASK 0x20000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__DISP_ASTOP_WAKEUP__SHIFT 0x0000001d
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_ADDR_TRAIN_MASK 0x00010000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_ADDR_TRAIN__SHIFT 0x00000010
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_READ_TRAIN_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_READ_TRAIN__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WCK_TRAIN_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WCK_TRAIN__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WRITE_TRAIN_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__READ_ECC_WRITE_TRAIN__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_ADDR_TRAIN_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_ADDR_TRAIN__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_READ_TRAIN_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_READ_TRAIN__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WCK_TRAIN_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WCK_TRAIN__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WRITE_TRAIN_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SELF_REFRESH_WRITE_TRAIN__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D0_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D0__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D1_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__STOP_WCK_D1__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SW_WAKEUP_MASK 0x10000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__SW_WAKEUP__SHIFT 0x0000001c
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D0_MASK 0x40000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D0__SHIFT 0x0000001e
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D1_MASK 0x80000000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__TRAIN_DONE_D1__SHIFT 0x0000001f
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_ADDR_TRAIN_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_ADDR_TRAIN__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_READ_TRAIN_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_READ_TRAIN__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WCK_TRAIN_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WCK_TRAIN__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WRITE_TRAIN_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_CNTL__WRITE_ECC_WRITE_TRAIN__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_EDGE__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP0_WAKEUP_MASK 0x00040000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP0_WAKEUP__SHIFT 0x00000012
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP1_WAKEUP_MASK 0x00080000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOP1_WAKEUP__SHIFT 0x00000013
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB0_WAKEUP_MASK 0x00200000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB0_WAKEUP__SHIFT 0x00000015
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB1_WAKEUP_MASK 0x00400000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__ALLOWSTOPB1_WAKEUP__SHIFT 0x00000016
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_ARF_WAKEUP_MASK 0x00000001L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_ARF_WAKEUP__SHIFT 0x00000000
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_CMD_FIFO_READY_WAKEUP_MASK 0x00000100L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000008
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_DATA_FIFO_READY_WAKEUP_MASK 0x00000400L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000a
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_IDLEH_WAKEUP_MASK 0x01000000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_IDLEH_WAKEUP__SHIFT 0x00000018
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_REDC_WAKEUP_MASK 0x00000004L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_REDC_WAKEUP__SHIFT 0x00000002
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_WEDC_WAKEUP_MASK 0x00000010L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D0_WEDC_WAKEUP__SHIFT 0x00000004
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_ARF_WAKEUP_MASK 0x00000002L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_ARF_WAKEUP__SHIFT 0x00000001
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_CMD_FIFO_READY_WAKEUP_MASK 0x00000200L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_CMD_FIFO_READY_WAKEUP__SHIFT 0x00000009
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_DATA_FIFO_READY_WAKEUP_MASK 0x00000800L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_DATA_FIFO_READY_WAKEUP__SHIFT 0x0000000b
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_IDLEH_WAKEUP_MASK 0x02000000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_IDLEH_WAKEUP__SHIFT 0x00000019
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_REDC_WAKEUP_MASK 0x00000008L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_REDC_WAKEUP__SHIFT 0x00000003
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_WEDC_WAKEUP_MASK 0x00000020L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__D1_WEDC_WAKEUP__SHIFT 0x00000005
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_LPT_WAKEUP_MASK 0x00800000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_LPT_WAKEUP__SHIFT 0x00000017
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_WAKEUP_MASK 0x00100000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__DPM_WAKEUP__SHIFT 0x00000014
+#define MC_SEQ_TRAIN_WAKEUP_MASK__MCLK_FREQ_CHANGE_WAKEUP_MASK 0x00000040L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__MCLK_FREQ_CHANGE_WAKEUP__SHIFT 0x00000006
+#define MC_SEQ_TRAIN_WAKEUP_MASK__PHY_PG_WAKEUP_MASK 0x04000000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__PHY_PG_WAKEUP__SHIFT 0x0000001a
+#define MC_SEQ_TRAIN_WAKEUP_MASK__RESERVE0_WAKEUP_MASK 0x00002000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__RESERVE0_WAKEUP__SHIFT 0x0000000d
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SCLK_SRBM_READY_WAKEUP_MASK 0x00000080L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SCLK_SRBM_READY_WAKEUP__SHIFT 0x00000007
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SOFTWARE_WAKEUP_WAKEUP_MASK 0x00001000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__SOFTWARE_WAKEUP_WAKEUP__SHIFT 0x0000000c
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TCG_DONE_WAKEUP_MASK 0x00020000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TCG_DONE_WAKEUP__SHIFT 0x00000011
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TIMER_DONE_WAKEUP_MASK 0x00008000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TIMER_DONE_WAKEUP__SHIFT 0x0000000f
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TSM_DONE_WAKEUP_MASK 0x00004000L
+#define MC_SEQ_TRAIN_WAKEUP_MASK__TSM_DONE_WAKEUP__SHIFT 0x0000000e
+#define MC_SEQ_TSM_BCNT__BCNT_TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_BCNT__BCNT_TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_BCNT__COMP_VALUE_MASK 0x00ff0000L
+#define MC_SEQ_TSM_BCNT__COMP_VALUE__SHIFT 0x00000010
+#define MC_SEQ_TSM_BCNT__DONE_TESTS_MASK 0xff000000L
+#define MC_SEQ_TSM_BCNT__DONE_TESTS__SHIFT 0x00000018
+#define MC_SEQ_TSM_BCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_BCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_BCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_BCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_CTRL__CAPTURE_START_MASK 0x00000002L
+#define MC_SEQ_TSM_CTRL__CAPTURE_START__SHIFT 0x00000001
+#define MC_SEQ_TSM_CTRL__DIRECTION_MASK 0x00000020L
+#define MC_SEQ_TSM_CTRL__DIRECTION__SHIFT 0x00000005
+#define MC_SEQ_TSM_CTRL__DONE_MASK 0x00000004L
+#define MC_SEQ_TSM_CTRL__DONE__SHIFT 0x00000002
+#define MC_SEQ_TSM_CTRL__ERR_MASK 0x00000008L
+#define MC_SEQ_TSM_CTRL__ERR__SHIFT 0x00000003
+#define MC_SEQ_TSM_CTRL__INVERT_MASK 0x00000040L
+#define MC_SEQ_TSM_CTRL__INVERT__SHIFT 0x00000006
+#define MC_SEQ_TSM_CTRL__MASK_BITS_MASK 0x00000080L
+#define MC_SEQ_TSM_CTRL__MASK_BITS__SHIFT 0x00000007
+#define MC_SEQ_TSM_CTRL__POINTER_MASK 0xffff0000L
+#define MC_SEQ_TSM_CTRL__POINTER__SHIFT 0x00000010
+#define MC_SEQ_TSM_CTRL__ROT_INV_MASK 0x00000400L
+#define MC_SEQ_TSM_CTRL__ROT_INV__SHIFT 0x0000000a
+#define MC_SEQ_TSM_CTRL__START_MASK 0x00000001L
+#define MC_SEQ_TSM_CTRL__START__SHIFT 0x00000000
+#define MC_SEQ_TSM_CTRL__STEP_MASK 0x00000010L
+#define MC_SEQ_TSM_CTRL__STEP__SHIFT 0x00000004
+#define MC_SEQ_TSM_CTRL__UPDATE_LOOP_MASK 0x00000300L
+#define MC_SEQ_TSM_CTRL__UPDATE_LOOP__SHIFT 0x00000008
+#define MC_SEQ_TSM_DBI__DBI_MASK 0xffffffffL
+#define MC_SEQ_TSM_DBI__DBI__SHIFT 0x00000000
+#define MC_SEQ_TSM_DEBUG_DATA__TSM_DEBUG_DATA_MASK 0xffffffffL
+#define MC_SEQ_TSM_DEBUG_DATA__TSM_DEBUG_DATA__SHIFT 0x00000000
+#define MC_SEQ_TSM_DEBUG_INDEX__TSM_DEBUG_INDEX_MASK 0x0000001fL
+#define MC_SEQ_TSM_DEBUG_INDEX__TSM_DEBUG_INDEX__SHIFT 0x00000000
+#define MC_SEQ_TSM_EDC__EDC_MASK 0xffffffffL
+#define MC_SEQ_TSM_EDC__EDC__SHIFT 0x00000000
+#define MC_SEQ_TSM_FLAG__ERROR_TESTS_MASK 0xff000000L
+#define MC_SEQ_TSM_FLAG__ERROR_TESTS__SHIFT 0x00000018
+#define MC_SEQ_TSM_FLAG__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_FLAG__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_FLAG__FLAG_TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_FLAG__FLAG_TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_FLAG__NBBL_MASK_MASK 0x000f0000L
+#define MC_SEQ_TSM_FLAG__NBBL_MASK__SHIFT 0x00000010
+#define MC_SEQ_TSM_FLAG__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_FLAG__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_GCNT__COMP_VALUE_MASK 0xffff0000L
+#define MC_SEQ_TSM_GCNT__COMP_VALUE__SHIFT 0x00000010
+#define MC_SEQ_TSM_GCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_GCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_GCNT__TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_GCNT__TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_GCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_GCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_MISC__WCDR_MASK_MASK 0x000f0000L
+#define MC_SEQ_TSM_MISC__WCDR_MASK__SHIFT 0x00000010
+#define MC_SEQ_TSM_MISC__WCDR_PTR_MASK 0x0000ffffL
+#define MC_SEQ_TSM_MISC__WCDR_PTR__SHIFT 0x00000000
+#define MC_SEQ_TSM_NCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_NCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_NCNT__NIBBLE_SKIP_MASK 0x0f000000L
+#define MC_SEQ_TSM_NCNT__NIBBLE_SKIP__SHIFT 0x00000018
+#define MC_SEQ_TSM_NCNT__RANGE_HIGH_MASK 0x00f00000L
+#define MC_SEQ_TSM_NCNT__RANGE_HIGH__SHIFT 0x00000014
+#define MC_SEQ_TSM_NCNT__RANGE_LOW_MASK 0x000f0000L
+#define MC_SEQ_TSM_NCNT__RANGE_LOW__SHIFT 0x00000010
+#define MC_SEQ_TSM_NCNT__TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_NCNT__TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_NCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_NCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_OCNT__CMP_VALUE_MASK 0xffff0000L
+#define MC_SEQ_TSM_OCNT__CMP_VALUE__SHIFT 0x00000010
+#define MC_SEQ_TSM_OCNT__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_OCNT__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_OCNT__TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_OCNT__TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_OCNT__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_OCNT__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_UPDATE__AREF_COUNT_MASK 0x00ff0000L
+#define MC_SEQ_TSM_UPDATE__AREF_COUNT__SHIFT 0x00000010
+#define MC_SEQ_TSM_UPDATE__CAPTR_TESTS_MASK 0xff000000L
+#define MC_SEQ_TSM_UPDATE__CAPTR_TESTS__SHIFT 0x00000018
+#define MC_SEQ_TSM_UPDATE__FALSE_ACT_MASK 0x000000f0L
+#define MC_SEQ_TSM_UPDATE__FALSE_ACT__SHIFT 0x00000004
+#define MC_SEQ_TSM_UPDATE__TRUE_ACT_MASK 0x0000000fL
+#define MC_SEQ_TSM_UPDATE__TRUE_ACT__SHIFT 0x00000000
+#define MC_SEQ_TSM_UPDATE__UPDT_TESTS_MASK 0x0000ff00L
+#define MC_SEQ_TSM_UPDATE__UPDT_TESTS__SHIFT 0x00000008
+#define MC_SEQ_TSM_WCDR__WCDR_MASK 0xffffffffL
+#define MC_SEQ_TSM_WCDR__WCDR__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE0_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE1_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE2_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D0__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ4_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ4__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ5_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ5__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ6_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ6__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ7_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_BYTE3_D1__DQ7__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_DBI_D0__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_DBI_D1__DBI3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_EDC_D0__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_EDC_D0__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_EDC_D1__EDC3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR0_MASK 0x000f0000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR0__SHIFT 0x00000010
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR1_MASK 0x00f00000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR1__SHIFT 0x00000014
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR2_MASK 0x0f000000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR2__SHIFT 0x00000018
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR3_MASK 0xf0000000L
+#define MC_SEQ_TXFRAMING_EDC_D1__WCDR3__SHIFT 0x0000001c
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_FCK_D0__FCK3__SHIFT 0x0000000c
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK0_MASK 0x0000000fL
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK0__SHIFT 0x00000000
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK1_MASK 0x000000f0L
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK1__SHIFT 0x00000004
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK2_MASK 0x00000f00L
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK2__SHIFT 0x00000008
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK3_MASK 0x0000f000L
+#define MC_SEQ_TXFRAMING_FCK_D1__FCK3__SHIFT 0x0000000c
+#define MC_SEQ_VENDOR_ID_I0__VALUE_MASK 0xffffffffL
+#define MC_SEQ_VENDOR_ID_I0__VALUE__SHIFT 0x00000000
+#define MC_SEQ_VENDOR_ID_I1__VALUE_MASK 0xffffffffL
+#define MC_SEQ_VENDOR_ID_I1__VALUE__SHIFT 0x00000000
+#define MC_SEQ_WCDR_CTRL__AREF_EN_MASK 0x00004000L
+#define MC_SEQ_WCDR_CTRL__AREF_EN__SHIFT 0x0000000e
+#define MC_SEQ_WCDR_CTRL__PRBS_EN_MASK 0x00100000L
+#define MC_SEQ_WCDR_CTRL__PRBS_EN__SHIFT 0x00000014
+#define MC_SEQ_WCDR_CTRL__PRBS_RST_MASK 0x00200000L
+#define MC_SEQ_WCDR_CTRL__PRBS_RST__SHIFT 0x00000015
+#define MC_SEQ_WCDR_CTRL__PREAMBLE_MASK 0x0f000000L
+#define MC_SEQ_WCDR_CTRL__PREAMBLE__SHIFT 0x00000018
+#define MC_SEQ_WCDR_CTRL__PRE_MASK_MASK 0xf0000000L
+#define MC_SEQ_WCDR_CTRL__PRE_MASK__SHIFT 0x0000001c
+#define MC_SEQ_WCDR_CTRL__RD_EN_MASK 0x00002000L
+#define MC_SEQ_WCDR_CTRL__RD_EN__SHIFT 0x0000000d
+#define MC_SEQ_WCDR_CTRL__TRAIN_EN_MASK 0x00008000L
+#define MC_SEQ_WCDR_CTRL__TRAIN_EN__SHIFT 0x0000000f
+#define MC_SEQ_WCDR_CTRL__TWCDRL_MASK 0x000f0000L
+#define MC_SEQ_WCDR_CTRL__TWCDRL__SHIFT 0x00000010
+#define MC_SEQ_WCDR_CTRL__WCDR_PRE_MASK 0x000000ffL
+#define MC_SEQ_WCDR_CTRL__WCDR_PRE__SHIFT 0x00000000
+#define MC_SEQ_WCDR_CTRL__WCDR_TIM_MASK 0x00000f00L
+#define MC_SEQ_WCDR_CTRL__WCDR_TIM__SHIFT 0x00000008
+#define MC_SEQ_WCDR_CTRL__WR_EN_MASK 0x00001000L
+#define MC_SEQ_WCDR_CTRL__WR_EN__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D0_MASK 0x00000001L
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D0__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D1_MASK 0x00000008L
+#define MC_SEQ_WR_CTL_2__DAT_DLY_H_D1__SHIFT 0x00000003
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D0_MASK 0x00000002L
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D0__SHIFT 0x00000001
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D1_MASK 0x00000010L
+#define MC_SEQ_WR_CTL_2__DQS_DLY_H_D1__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D0_MASK 0x00000001L
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D0__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D1_MASK 0x00000008L
+#define MC_SEQ_WR_CTL_2_LP__DAT_DLY_H_D1__SHIFT 0x00000003
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D0_MASK 0x00000002L
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D0__SHIFT 0x00000001
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D1_MASK 0x00000010L
+#define MC_SEQ_WR_CTL_2_LP__DQS_DLY_H_D1__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D0_MASK 0x00000004L
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D0__SHIFT 0x00000002
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D1_MASK 0x00000020L
+#define MC_SEQ_WR_CTL_2_LP__OEN_DLY_H_D1__SHIFT 0x00000005
+#define MC_SEQ_WR_CTL_2_LP__WCDR_EN_MASK 0x00000040L
+#define MC_SEQ_WR_CTL_2_LP__WCDR_EN__SHIFT 0x00000006
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D0_MASK 0x00000004L
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D0__SHIFT 0x00000002
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D1_MASK 0x00000020L
+#define MC_SEQ_WR_CTL_2__OEN_DLY_H_D1__SHIFT 0x00000005
+#define MC_SEQ_WR_CTL_2__WCDR_EN_MASK 0x00000040L
+#define MC_SEQ_WR_CTL_2__WCDR_EN__SHIFT 0x00000006
+#define MC_SEQ_WR_CTL_D0__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D0__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D0__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D0__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D0__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D0__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D0__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D0__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D0__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D0__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D0__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D0__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D0__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D0__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D0__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D0__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D0_LP__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D0_LP__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D0_LP__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D0_LP__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D0_LP__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D0_LP__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D0_LP__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D0_LP__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D0_LP__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D0_LP__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D0_LP__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D0_LP__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D0_LP__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D0_LP__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D0_LP__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D0_LP__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D0_LP__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D0_LP__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D0_LP__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D0_LP__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D0_LP__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D0_LP__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D0_LP__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D0_LP__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D0_LP__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D0_LP__OEN_SEL__SHIFT 0x00000014
+#define MC_SEQ_WR_CTL_D0__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D0__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D0__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D0__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D0__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D0__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D0__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D0__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D0__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D0__OEN_SEL__SHIFT 0x00000014
+#define MC_SEQ_WR_CTL_D1__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D1__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D1__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D1__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D1__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D1__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D1__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D1__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D1__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D1__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D1__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D1__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D1__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D1__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D1__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D1__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D1_LP__ADR_2Y_DLY_MASK 0x00000400L
+#define MC_SEQ_WR_CTL_D1_LP__ADR_2Y_DLY__SHIFT 0x0000000a
+#define MC_SEQ_WR_CTL_D1_LP__ADR_DLY_MASK 0x20000000L
+#define MC_SEQ_WR_CTL_D1_LP__ADR_DLY__SHIFT 0x0000001d
+#define MC_SEQ_WR_CTL_D1_LP__CMD_2Y_DLY_MASK 0x00000800L
+#define MC_SEQ_WR_CTL_D1_LP__CMD_2Y_DLY__SHIFT 0x0000000b
+#define MC_SEQ_WR_CTL_D1_LP__CMD_DLY_MASK 0x40000000L
+#define MC_SEQ_WR_CTL_D1_LP__CMD_DLY__SHIFT 0x0000001e
+#define MC_SEQ_WR_CTL_D1_LP__DAT_2Y_DLY_MASK 0x00000200L
+#define MC_SEQ_WR_CTL_D1_LP__DAT_2Y_DLY__SHIFT 0x00000009
+#define MC_SEQ_WR_CTL_D1_LP__DAT_DLY_MASK 0x0000000fL
+#define MC_SEQ_WR_CTL_D1_LP__DAT_DLY__SHIFT 0x00000000
+#define MC_SEQ_WR_CTL_D1_LP__DQS_DLY_MASK 0x000000f0L
+#define MC_SEQ_WR_CTL_D1_LP__DQS_DLY__SHIFT 0x00000004
+#define MC_SEQ_WR_CTL_D1_LP__DQS_XTR_MASK 0x00000100L
+#define MC_SEQ_WR_CTL_D1_LP__DQS_XTR__SHIFT 0x00000008
+#define MC_SEQ_WR_CTL_D1_LP__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D1_LP__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D1_LP__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D1_LP__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D1_LP__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D1_LP__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D1_LP__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D1_LP__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D1_LP__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D1_LP__OEN_SEL__SHIFT 0x00000014
+#define MC_SEQ_WR_CTL_D1__ODT_DLY_MASK 0x0f000000L
+#define MC_SEQ_WR_CTL_D1__ODT_DLY__SHIFT 0x00000018
+#define MC_SEQ_WR_CTL_D1__ODT_EXT_MASK 0x10000000L
+#define MC_SEQ_WR_CTL_D1__ODT_EXT__SHIFT 0x0000001c
+#define MC_SEQ_WR_CTL_D1__OEN_DLY_MASK 0x0000f000L
+#define MC_SEQ_WR_CTL_D1__OEN_DLY__SHIFT 0x0000000c
+#define MC_SEQ_WR_CTL_D1__OEN_EXT_MASK 0x000f0000L
+#define MC_SEQ_WR_CTL_D1__OEN_EXT__SHIFT 0x00000010
+#define MC_SEQ_WR_CTL_D1__OEN_SEL_MASK 0x00300000L
+#define MC_SEQ_WR_CTL_D1__OEN_SEL__SHIFT 0x00000014
+#define MC_SHARED_BLACKOUT_CNTL__BLACKOUT_MODE_MASK 0x00000007L
+#define MC_SHARED_BLACKOUT_CNTL__BLACKOUT_MODE__SHIFT 0x00000000
+#define MC_SHARED_CHMAP__CHAN0_MASK 0x0000000fL
+#define MC_SHARED_CHMAP__CHAN0__SHIFT 0x00000000
+#define MC_SHARED_CHMAP__CHAN1_MASK 0x000000f0L
+#define MC_SHARED_CHMAP__CHAN1__SHIFT 0x00000004
+#define MC_SHARED_CHMAP__CHAN2_MASK 0x00000f00L
+#define MC_SHARED_CHMAP__CHAN2__SHIFT 0x00000008
+#define MC_SHARED_CHMAP__NOOFCHAN_MASK 0x0000f000L
+#define MC_SHARED_CHMAP__NOOFCHAN__SHIFT 0x0000000c
+#define MC_SHARED_CHREMAP__CHAN0_MASK 0x00000007L
+#define MC_SHARED_CHREMAP__CHAN0__SHIFT 0x00000000
+#define MC_SHARED_CHREMAP__CHAN1_MASK 0x00000038L
+#define MC_SHARED_CHREMAP__CHAN1__SHIFT 0x00000003
+#define MC_SHARED_CHREMAP__CHAN2_MASK 0x000001c0L
+#define MC_SHARED_CHREMAP__CHAN2__SHIFT 0x00000006
+#define MC_SHARED_CHREMAP__CHAN3_MASK 0x00000e00L
+#define MC_SHARED_CHREMAP__CHAN3__SHIFT 0x00000009
+#define MC_SHARED_CHREMAP__CHAN4_MASK 0x00007000L
+#define MC_SHARED_CHREMAP__CHAN4__SHIFT 0x0000000c
+#define MC_SHARED_CHREMAP__CHAN5_MASK 0x00038000L
+#define MC_SHARED_CHREMAP__CHAN5__SHIFT 0x0000000f
+#define MC_SHARED_CHREMAP__CHAN6_MASK 0x001c0000L
+#define MC_SHARED_CHREMAP__CHAN6__SHIFT 0x00000012
+#define MC_SHARED_CHREMAP__CHAN7_MASK 0x00e00000L
+#define MC_SHARED_CHREMAP__CHAN7__SHIFT 0x00000015
+#define MC_TRAIN_EDCCDR_R_D0__EDC0_MASK 0x000000ffL
+#define MC_TRAIN_EDCCDR_R_D0__EDC0__SHIFT 0x00000000
+#define MC_TRAIN_EDCCDR_R_D0__EDC1_MASK 0x0000ff00L
+#define MC_TRAIN_EDCCDR_R_D0__EDC1__SHIFT 0x00000008
+#define MC_TRAIN_EDCCDR_R_D0__EDC2_MASK 0x00ff0000L
+#define MC_TRAIN_EDCCDR_R_D0__EDC2__SHIFT 0x00000010
+#define MC_TRAIN_EDCCDR_R_D0__EDC3_MASK 0xff000000L
+#define MC_TRAIN_EDCCDR_R_D0__EDC3__SHIFT 0x00000018
+#define MC_TRAIN_EDCCDR_R_D1__EDC0_MASK 0x000000ffL
+#define MC_TRAIN_EDCCDR_R_D1__EDC0__SHIFT 0x00000000
+#define MC_TRAIN_EDCCDR_R_D1__EDC1_MASK 0x0000ff00L
+#define MC_TRAIN_EDCCDR_R_D1__EDC1__SHIFT 0x00000008
+#define MC_TRAIN_EDCCDR_R_D1__EDC2_MASK 0x00ff0000L
+#define MC_TRAIN_EDCCDR_R_D1__EDC2__SHIFT 0x00000010
+#define MC_TRAIN_EDCCDR_R_D1__EDC3_MASK 0xff000000L
+#define MC_TRAIN_EDCCDR_R_D1__EDC3__SHIFT 0x00000018
+#define MC_TRAIN_EDC_STATUS_D0__REDC_CNT_MASK 0xffff0000L
+#define MC_TRAIN_EDC_STATUS_D0__REDC_CNT__SHIFT 0x00000010
+#define MC_TRAIN_EDC_STATUS_D0__WEDC_CNT_MASK 0x0000ffffL
+#define MC_TRAIN_EDC_STATUS_D0__WEDC_CNT__SHIFT 0x00000000
+#define MC_TRAIN_EDC_STATUS_D1__REDC_CNT_MASK 0xffff0000L
+#define MC_TRAIN_EDC_STATUS_D1__REDC_CNT__SHIFT 0x00000010
+#define MC_TRAIN_EDC_STATUS_D1__WEDC_CNT_MASK 0x0000ffffL
+#define MC_TRAIN_EDC_STATUS_D1__WEDC_CNT__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_0_D0__DQ_STATUS_MASK 0xffffffffL
+#define MC_TRAIN_PRBSERR_0_D0__DQ_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_0_D1__DQ_STATUS_MASK 0xffffffffL
+#define MC_TRAIN_PRBSERR_0_D1__DQ_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_1_D0__DBI_STATUS_MASK 0x0000000fL
+#define MC_TRAIN_PRBSERR_1_D0__DBI_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_1_D0__EDC_STATUS_MASK 0x000000f0L
+#define MC_TRAIN_PRBSERR_1_D0__EDC_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_1_D0__PMA_PRBSCLR_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_1_D0__PMA_PRBSCLR__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_1_D0__PMD0_PRBSCLR_MASK 0x20000000L
+#define MC_TRAIN_PRBSERR_1_D0__PMD0_PRBSCLR__SHIFT 0x0000001d
+#define MC_TRAIN_PRBSERR_1_D0__PMD1_PRBSCLR_MASK 0x40000000L
+#define MC_TRAIN_PRBSERR_1_D0__PMD1_PRBSCLR__SHIFT 0x0000001e
+#define MC_TRAIN_PRBSERR_1_D0__WCDR_STATUS_MASK 0x0000f000L
+#define MC_TRAIN_PRBSERR_1_D0__WCDR_STATUS__SHIFT 0x0000000c
+#define MC_TRAIN_PRBSERR_1_D0__WCK_STATUS_MASK 0x00000f00L
+#define MC_TRAIN_PRBSERR_1_D0__WCK_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_1_D1__DBI_STATUS_MASK 0x0000000fL
+#define MC_TRAIN_PRBSERR_1_D1__DBI_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_1_D1__EDC_STATUS_MASK 0x000000f0L
+#define MC_TRAIN_PRBSERR_1_D1__EDC_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_1_D1__PMA_PRBSCLR_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_1_D1__PMA_PRBSCLR__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_1_D1__PMD0_PRBSCLR_MASK 0x20000000L
+#define MC_TRAIN_PRBSERR_1_D1__PMD0_PRBSCLR__SHIFT 0x0000001d
+#define MC_TRAIN_PRBSERR_1_D1__PMD1_PRBSCLR_MASK 0x40000000L
+#define MC_TRAIN_PRBSERR_1_D1__PMD1_PRBSCLR__SHIFT 0x0000001e
+#define MC_TRAIN_PRBSERR_1_D1__WCDR_STATUS_MASK 0x0000f000L
+#define MC_TRAIN_PRBSERR_1_D1__WCDR_STATUS__SHIFT 0x0000000c
+#define MC_TRAIN_PRBSERR_1_D1__WCK_STATUS_MASK 0x00000f00L
+#define MC_TRAIN_PRBSERR_1_D1__WCK_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_2_D0__ABI_STATUS_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_2_D0__ABI_STATUS__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_2_D0__ADDR_STATUS_MASK 0x03ff0000L
+#define MC_TRAIN_PRBSERR_2_D0__ADDR_STATUS__SHIFT 0x00000010
+#define MC_TRAIN_PRBSERR_2_D0__CAS_STATUS_MASK 0x00000400L
+#define MC_TRAIN_PRBSERR_2_D0__CAS_STATUS__SHIFT 0x0000000a
+#define MC_TRAIN_PRBSERR_2_D0__CKB_STATUS_MASK 0x00000002L
+#define MC_TRAIN_PRBSERR_2_D0__CKB_STATUS__SHIFT 0x00000001
+#define MC_TRAIN_PRBSERR_2_D0__CKE_STATUS_MASK 0x00000100L
+#define MC_TRAIN_PRBSERR_2_D0__CKE_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_2_D0__CK_STATUS_MASK 0x00000001L
+#define MC_TRAIN_PRBSERR_2_D0__CK_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_2_D0__CS_STATUS_MASK 0x00000030L
+#define MC_TRAIN_PRBSERR_2_D0__CS_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_2_D0__RAS_STATUS_MASK 0x00000200L
+#define MC_TRAIN_PRBSERR_2_D0__RAS_STATUS__SHIFT 0x00000009
+#define MC_TRAIN_PRBSERR_2_D0__WE_STATUS_MASK 0x00000800L
+#define MC_TRAIN_PRBSERR_2_D0__WE_STATUS__SHIFT 0x0000000b
+#define MC_TRAIN_PRBSERR_2_D1__ABI_STATUS_MASK 0x10000000L
+#define MC_TRAIN_PRBSERR_2_D1__ABI_STATUS__SHIFT 0x0000001c
+#define MC_TRAIN_PRBSERR_2_D1__ADDR_STATUS_MASK 0x03ff0000L
+#define MC_TRAIN_PRBSERR_2_D1__ADDR_STATUS__SHIFT 0x00000010
+#define MC_TRAIN_PRBSERR_2_D1__CAS_STATUS_MASK 0x00000400L
+#define MC_TRAIN_PRBSERR_2_D1__CAS_STATUS__SHIFT 0x0000000a
+#define MC_TRAIN_PRBSERR_2_D1__CKB_STATUS_MASK 0x00000002L
+#define MC_TRAIN_PRBSERR_2_D1__CKB_STATUS__SHIFT 0x00000001
+#define MC_TRAIN_PRBSERR_2_D1__CKE_STATUS_MASK 0x00000100L
+#define MC_TRAIN_PRBSERR_2_D1__CKE_STATUS__SHIFT 0x00000008
+#define MC_TRAIN_PRBSERR_2_D1__CK_STATUS_MASK 0x00000001L
+#define MC_TRAIN_PRBSERR_2_D1__CK_STATUS__SHIFT 0x00000000
+#define MC_TRAIN_PRBSERR_2_D1__CS_STATUS_MASK 0x00000030L
+#define MC_TRAIN_PRBSERR_2_D1__CS_STATUS__SHIFT 0x00000004
+#define MC_TRAIN_PRBSERR_2_D1__RAS_STATUS_MASK 0x00000200L
+#define MC_TRAIN_PRBSERR_2_D1__RAS_STATUS__SHIFT 0x00000009
+#define MC_TRAIN_PRBSERR_2_D1__WE_STATUS_MASK 0x00000800L
+#define MC_TRAIN_PRBSERR_2_D1__WE_STATUS__SHIFT 0x0000000b
+#define MC_TSM_DEBUG_BCNT0__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT0__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT0__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT0__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT0__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT0__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT0__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT0__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT10__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT10__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT10__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT10__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT10__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT10__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT10__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT10__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT1__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT1__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT1__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT1__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT1__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT1__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT1__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT1__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT2__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT2__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT2__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT2__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT2__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT2__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT2__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT2__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT3__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT3__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT3__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT3__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT3__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT3__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT3__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT3__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT4__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT4__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT4__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT4__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT4__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT4__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT4__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT4__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT5__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT5__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT5__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT5__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT5__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT5__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT5__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT5__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT6__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT6__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT6__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT6__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT6__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT6__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT6__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT6__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT7__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT7__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT7__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT7__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT7__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT7__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT7__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT7__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT8__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT8__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT8__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT8__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT8__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT8__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT8__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT8__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BCNT9__BYTE0_MASK 0x000000ffL
+#define MC_TSM_DEBUG_BCNT9__BYTE0__SHIFT 0x00000000
+#define MC_TSM_DEBUG_BCNT9__BYTE1_MASK 0x0000ff00L
+#define MC_TSM_DEBUG_BCNT9__BYTE1__SHIFT 0x00000008
+#define MC_TSM_DEBUG_BCNT9__BYTE2_MASK 0x00ff0000L
+#define MC_TSM_DEBUG_BCNT9__BYTE2__SHIFT 0x00000010
+#define MC_TSM_DEBUG_BCNT9__BYTE3_MASK 0xff000000L
+#define MC_TSM_DEBUG_BCNT9__BYTE3__SHIFT 0x00000018
+#define MC_TSM_DEBUG_BKPT__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_BKPT__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_FLAG__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_FLAG__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_GCNT__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_GCNT__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_MISC__FLAG_MASK 0x000000ffL
+#define MC_TSM_DEBUG_MISC__FLAG__SHIFT 0x00000000
+#define MC_TSM_DEBUG_MISC__NCNT_RD_MASK 0x00000f00L
+#define MC_TSM_DEBUG_MISC__NCNT_RD__SHIFT 0x00000008
+#define MC_TSM_DEBUG_MISC__NCNT_WR_MASK 0x0000f000L
+#define MC_TSM_DEBUG_MISC__NCNT_WR__SHIFT 0x0000000c
+#define MC_TSM_DEBUG_ST01__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_ST01__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_ST23__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_ST23__DATA__SHIFT 0x00000000
+#define MC_TSM_DEBUG_ST45__DATA_MASK 0xffffffffL
+#define MC_TSM_DEBUG_ST45__DATA__SHIFT 0x00000000
+#define MC_VM_AGP_BASE__AGP_BASE_MASK 0x0003ffffL
+#define MC_VM_AGP_BASE__AGP_BASE__SHIFT 0x00000000
+#define MC_VM_AGP_BOT__AGP_BOT_MASK 0x0003ffffL
+#define MC_VM_AGP_BOT__AGP_BOT__SHIFT 0x00000000
+#define MC_VM_AGP_TOP__AGP_TOP_MASK 0x0003ffffL
+#define MC_VM_AGP_TOP__AGP_TOP__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_LOCAL_MASK 0x00000100L
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_LOCAL__SHIFT 0x00000008
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_SYSTEM_MASK 0x00000200L
+#define MC_VM_DC_WRITE_CNTL__DC_MEMORY_WRITE_SYSTEM__SHIFT 0x00000009
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_0_MODE_MASK 0x00000003L
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_0_MODE__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_1_MODE_MASK 0x0000000cL
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_1_MODE__SHIFT 0x00000002
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_2_MODE_MASK 0x00000030L
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_2_MODE__SHIFT 0x00000004
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_3_MODE_MASK 0x000000c0L
+#define MC_VM_DC_WRITE_CNTL__DC_WRITE_HIT_REGION_3_MODE__SHIFT 0x00000006
+#define MC_VM_DC_WRITE_HIT_REGION_0_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_0_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_0_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_0_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_1_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_1_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_1_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_1_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_2_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_2_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_2_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_2_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_3_HIGH_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_3_HIGH_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_DC_WRITE_HIT_REGION_3_LOW_ADDR__PHYSICAL_ADDRESS_MASK 0x0fffffffL
+#define MC_VM_DC_WRITE_HIT_REGION_3_LOW_ADDR__PHYSICAL_ADDRESS__SHIFT 0x00000000
+#define MC_VM_FB_LOCATION__FB_BASE_MASK 0x0000ffffL
+#define MC_VM_FB_LOCATION__FB_BASE__SHIFT 0x00000000
+#define MC_VM_FB_LOCATION__FB_TOP_MASK 0xffff0000L
+#define MC_VM_FB_LOCATION__FB_TOP__SHIFT 0x00000010
+#define MC_VM_FB_OFFSET__FB_OFFSET_MASK 0x0003ffffL
+#define MC_VM_FB_OFFSET__FB_OFFSET__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MB_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MB_L1_TLB0_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB0_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB0_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MB_L1_TLB0_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MB_L1_TLB0_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MB_L1_TLB0_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MB_L1_TLB0_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB0_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB1_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB1_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MB_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MB_L1_TLB2_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB2_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB2_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MB_L1_TLB2_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MB_L1_TLB2_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MB_L1_TLB2_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MB_L1_TLB2_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB2_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MB_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MB_L1_TLB3_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB3_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MB_L1_TLB3_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MB_L1_TLB3_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MB_L1_TLB3_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MB_L1_TLB3_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MB_L1_TLB3_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MB_L1_TLB3_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MB_L2ARBITER_L2_CREDITS__L2_IF_CREDITS_MASK 0x0000003fL
+#define MC_VM_MB_L2ARBITER_L2_CREDITS__L2_IF_CREDITS__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB0_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB0_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB0_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB0_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB0_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB0_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB0_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB0_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB0_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB1_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB1_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB1_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB1_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB1_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB1_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB1_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB1_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB1_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB2_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB2_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB2_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB2_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB2_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB2_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB2_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB2_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB2_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE_MASK 0x00007000L
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_QUEUE_SIZE__SHIFT 0x0000000c
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE_MASK 0x00000e00L
+#define MC_VM_MD_L1_TLB3_DEBUG__EFFECTIVE_L1_TLB_SIZE__SHIFT 0x00000009
+#define MC_VM_MD_L1_TLB3_DEBUG__INVALIDATE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB3_DEBUG__INVALIDATE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MD_L1_TLB3_DEBUG__L1_TLB_DEBUG_MASK 0x00078000L
+#define MC_VM_MD_L1_TLB3_DEBUG__L1_TLB_DEBUG__SHIFT 0x0000000f
+#define MC_VM_MD_L1_TLB3_DEBUG__SEND_FREE_AT_RTN_MASK 0x00000100L
+#define MC_VM_MD_L1_TLB3_DEBUG__SEND_FREE_AT_RTN__SHIFT 0x00000008
+#define MC_VM_MD_L1_TLB3_STATUS__BUSY_MASK 0x00000001L
+#define MC_VM_MD_L1_TLB3_STATUS__BUSY__SHIFT 0x00000000
+#define MC_VM_MD_L2ARBITER_L2_CREDITS__L2_IF_CREDITS_MASK 0x0000003fL
+#define MC_VM_MD_L2ARBITER_L2_CREDITS__L2_IF_CREDITS__SHIFT 0x00000000
+#define MC_VM_MX_L1_TLB_CNTL__ECO_BITS_MASK 0x00000780L
+#define MC_VM_MX_L1_TLB_CNTL__ECO_BITS__SHIFT 0x00000007
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_ADVANCED_DRIVER_MODEL_MASK 0x00000040L
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_ADVANCED_DRIVER_MODEL__SHIFT 0x00000006
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_FRAGMENT_PROCESSING_MASK 0x00000002L
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_FRAGMENT_PROCESSING__SHIFT 0x00000001
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_TLB_MASK 0x00000001L
+#define MC_VM_MX_L1_TLB_CNTL__ENABLE_L1_TLB__SHIFT 0x00000000
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE_MASK 0x00000018L
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_ACCESS_MODE__SHIFT 0x00000003
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS_MASK 0x00000020L
+#define MC_VM_MX_L1_TLB_CNTL__SYSTEM_APERTURE_UNMAPPED_ACCESS__SHIFT 0x00000005
+#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define MC_VM_SYSTEM_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define MC_VM_SYSTEM_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define MC_WR_CB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_CB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_CB__ENABLE_MASK 0x00000001L
+#define MC_WR_CB__ENABLE__SHIFT 0x00000000
+#define MC_WR_CB__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_CB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_CB__MAX_BURST_MASK 0x00000780L
+#define MC_WR_CB__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_CB__PRESCALE_MASK 0x00000006L
+#define MC_WR_CB__PRESCALE__SHIFT 0x00000001
+#define MC_WR_CB__STALL_MODE_MASK 0x00000030L
+#define MC_WR_CB__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_CB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_CB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_CB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_CB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_DB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_DB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_DB__ENABLE_MASK 0x00000001L
+#define MC_WR_DB__ENABLE__SHIFT 0x00000000
+#define MC_WR_DB__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_DB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_DB__MAX_BURST_MASK 0x00000780L
+#define MC_WR_DB__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_DB__PRESCALE_MASK 0x00000006L
+#define MC_WR_DB__PRESCALE__SHIFT 0x00000001
+#define MC_WR_DB__STALL_MODE_MASK 0x00000030L
+#define MC_WR_DB__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_DB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_DB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_DB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_DB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_GRP_EXT__DBSTEN0_MASK 0x0000000fL
+#define MC_WR_GRP_EXT__DBSTEN0__SHIFT 0x00000000
+#define MC_WR_GRP_EXT__TC0_MASK 0x000000f0L
+#define MC_WR_GRP_EXT__TC0__SHIFT 0x00000004
+#define MC_WR_GRP_GFX__CP_MASK 0x0000000fL
+#define MC_WR_GRP_GFX__CP__SHIFT 0x00000000
+#define MC_WR_GRP_GFX__XDMA_MASK 0x0000f000L
+#define MC_WR_GRP_GFX__XDMAM_MASK 0x000f0000L
+#define MC_WR_GRP_GFX__XDMAM__SHIFT 0x00000010
+#define MC_WR_GRP_GFX__XDMA__SHIFT 0x0000000c
+#define MC_WR_GRP_LCL__CB0_MASK 0x0000000fL
+#define MC_WR_GRP_LCL__CB0__SHIFT 0x00000000
+#define MC_WR_GRP_LCL__CBCMASK0_MASK 0x000000f0L
+#define MC_WR_GRP_LCL__CBCMASK0__SHIFT 0x00000004
+#define MC_WR_GRP_LCL__CBFMASK0_MASK 0x00000f00L
+#define MC_WR_GRP_LCL__CBFMASK0__SHIFT 0x00000008
+#define MC_WR_GRP_LCL__CBIMMED0_MASK 0xf0000000L
+#define MC_WR_GRP_LCL__CBIMMED0__SHIFT 0x0000001c
+#define MC_WR_GRP_LCL__DB0_MASK 0x0000f000L
+#define MC_WR_GRP_LCL__DB0__SHIFT 0x0000000c
+#define MC_WR_GRP_LCL__DBHTILE0_MASK 0x000f0000L
+#define MC_WR_GRP_LCL__DBHTILE0__SHIFT 0x00000010
+#define MC_WR_GRP_LCL__SX0_MASK 0x00f00000L
+#define MC_WR_GRP_LCL__SX0__SHIFT 0x00000014
+#define MC_WR_GRP_OTH__HDP_MASK 0x00000f00L
+#define MC_WR_GRP_OTH__HDP__SHIFT 0x00000008
+#define MC_WR_GRP_OTH__SEM_MASK 0x0000f000L
+#define MC_WR_GRP_OTH__SEM__SHIFT 0x0000000c
+#define MC_WR_GRP_OTH__UMC_MASK 0x000f0000L
+#define MC_WR_GRP_OTH__UMC__SHIFT 0x00000010
+#define MC_WR_GRP_OTH__UVD_EXT0_MASK 0x0000000fL
+#define MC_WR_GRP_OTH__UVD_EXT0__SHIFT 0x00000000
+#define MC_WR_GRP_OTH__UVD_EXT1_MASK 0xf0000000L
+#define MC_WR_GRP_OTH__UVD_EXT1__SHIFT 0x0000001c
+#define MC_WR_GRP_OTH__UVD_MASK 0x00f00000L
+#define MC_WR_GRP_OTH__UVD__SHIFT 0x00000014
+#define MC_WR_GRP_OTH__XDP_MASK 0x0f000000L
+#define MC_WR_GRP_OTH__XDP__SHIFT 0x00000018
+#define MC_WR_GRP_SYS__IH_MASK 0x0000000fL
+#define MC_WR_GRP_SYS__IH__SHIFT 0x00000000
+#define MC_WR_GRP_SYS__MCIF_MASK 0x000000f0L
+#define MC_WR_GRP_SYS__MCIF__SHIFT 0x00000004
+#define MC_WR_GRP_SYS__RLC_MASK 0x00000f00L
+#define MC_WR_GRP_SYS__RLC__SHIFT 0x00000008
+#define MC_WR_GRP_SYS__SMU_MASK 0x00f00000L
+#define MC_WR_GRP_SYS__SMU__SHIFT 0x00000014
+#define MC_WR_GRP_SYS__VCE_MASK 0x0f000000L
+#define MC_WR_GRP_SYS__VCE__SHIFT 0x00000018
+#define MC_WR_GRP_SYS__VCEU_MASK 0xf0000000L
+#define MC_WR_GRP_SYS__VCEU__SHIFT 0x0000001c
+#define MC_WR_HUB__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_HUB__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_HUB__ENABLE_MASK 0x00000001L
+#define MC_WR_HUB__ENABLE__SHIFT 0x00000000
+#define MC_WR_HUB__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_HUB__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_HUB__MAX_BURST_MASK 0x00000780L
+#define MC_WR_HUB__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_HUB__PRESCALE_MASK 0x00000006L
+#define MC_WR_HUB__PRESCALE__SHIFT 0x00000001
+#define MC_WR_HUB__STALL_MODE_MASK 0x00000030L
+#define MC_WR_HUB__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_HUB__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_HUB__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_HUB__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_HUB__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_TC0__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_TC0__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_TC0__ENABLE_MASK 0x00000001L
+#define MC_WR_TC0__ENABLE__SHIFT 0x00000000
+#define MC_WR_TC0__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_TC0__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_TC0__MAX_BURST_MASK 0x00000780L
+#define MC_WR_TC0__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_TC0__PRESCALE_MASK 0x00000006L
+#define MC_WR_TC0__PRESCALE__SHIFT 0x00000001
+#define MC_WR_TC0__STALL_MODE_MASK 0x00000030L
+#define MC_WR_TC0__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_TC0__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_TC0__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_TC0__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_TC0__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_WR_TC1__BLACKOUT_EXEMPT_MASK 0x00000008L
+#define MC_WR_TC1__BLACKOUT_EXEMPT__SHIFT 0x00000003
+#define MC_WR_TC1__ENABLE_MASK 0x00000001L
+#define MC_WR_TC1__ENABLE__SHIFT 0x00000000
+#define MC_WR_TC1__LAZY_TIMER_MASK 0x00007800L
+#define MC_WR_TC1__LAZY_TIMER__SHIFT 0x0000000b
+#define MC_WR_TC1__MAX_BURST_MASK 0x00000780L
+#define MC_WR_TC1__MAX_BURST__SHIFT 0x00000007
+#define MC_WR_TC1__PRESCALE_MASK 0x00000006L
+#define MC_WR_TC1__PRESCALE__SHIFT 0x00000001
+#define MC_WR_TC1__STALL_MODE_MASK 0x00000030L
+#define MC_WR_TC1__STALL_MODE__SHIFT 0x00000004
+#define MC_WR_TC1__STALL_OVERRIDE_MASK 0x00000040L
+#define MC_WR_TC1__STALL_OVERRIDE__SHIFT 0x00000006
+#define MC_WR_TC1__STALL_OVERRIDE_WTM_MASK 0x00008000L
+#define MC_WR_TC1__STALL_OVERRIDE_WTM__SHIFT 0x0000000f
+#define MC_XBAR_ADDR_DEC__GECC_MASK 0x00000002L
+#define MC_XBAR_ADDR_DEC__GECC__SHIFT 0x00000001
+#define MC_XBAR_ADDR_DEC__NO_DIV_BY_3_MASK 0x00000001L
+#define MC_XBAR_ADDR_DEC__NO_DIV_BY_3__SHIFT 0x00000000
+#define MC_XBAR_ADDR_DEC__RB_SPLIT_COLHI_MASK 0x00000008L
+#define MC_XBAR_ADDR_DEC__RB_SPLIT_COLHI__SHIFT 0x00000003
+#define MC_XBAR_ADDR_DEC__RB_SPLIT_MASK 0x00000004L
+#define MC_XBAR_ADDR_DEC__RB_SPLIT__SHIFT 0x00000002
+#define MC_XBAR_ARB__BREAK_BURST_CID_CHANGE_MASK 0x00000004L
+#define MC_XBAR_ARB__BREAK_BURST_CID_CHANGE__SHIFT 0x00000002
+#define MC_XBAR_ARB__DISABLE_HUB_STALL_HIGHEST_MASK 0x00000002L
+#define MC_XBAR_ARB__DISABLE_HUB_STALL_HIGHEST__SHIFT 0x00000001
+#define MC_XBAR_ARB__HUBRD_HIGHEST_MASK 0x00000001L
+#define MC_XBAR_ARB__HUBRD_HIGHEST__SHIFT 0x00000000
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT0_MASK 0x0000000fL
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT0__SHIFT 0x00000000
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT1_MASK 0x000000f0L
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT1__SHIFT 0x00000004
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT2_MASK 0x00000f00L
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT2__SHIFT 0x00000008
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT3_MASK 0x0000f000L
+#define MC_XBAR_ARB_MAX_BURST__RD_PORT3__SHIFT 0x0000000c
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT0_MASK 0x000f0000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT0__SHIFT 0x00000010
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT1_MASK 0x00f00000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT1__SHIFT 0x00000014
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT2_MASK 0x0f000000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT2__SHIFT 0x00000018
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT3_MASK 0xf0000000L
+#define MC_XBAR_ARB_MAX_BURST__WR_PORT3__SHIFT 0x0000001c
+#define MC_XBAR_CHTRIREMAP__CH0_MASK 0x00000003L
+#define MC_XBAR_CHTRIREMAP__CH0__SHIFT 0x00000000
+#define MC_XBAR_CHTRIREMAP__CH1_MASK 0x0000000cL
+#define MC_XBAR_CHTRIREMAP__CH1__SHIFT 0x00000002
+#define MC_XBAR_CHTRIREMAP__CH2_MASK 0x00000030L
+#define MC_XBAR_CHTRIREMAP__CH2__SHIFT 0x00000004
+#define MC_XBAR_PERF_MON_CNTL0__ALLOW_WRAP_MASK 0x10000000L
+#define MC_XBAR_PERF_MON_CNTL0__ALLOW_WRAP__SHIFT 0x0000001c
+#define MC_XBAR_PERF_MON_CNTL0__START_MODE_MASK 0x03000000L
+#define MC_XBAR_PERF_MON_CNTL0__START_MODE__SHIFT 0x00000018
+#define MC_XBAR_PERF_MON_CNTL0__START_THRESH_MASK 0x00000fffL
+#define MC_XBAR_PERF_MON_CNTL0__START_THRESH__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_CNTL0__STOP_MODE_MASK 0x0c000000L
+#define MC_XBAR_PERF_MON_CNTL0__STOP_MODE__SHIFT 0x0000001a
+#define MC_XBAR_PERF_MON_CNTL0__STOP_THRESH_MASK 0x00fff000L
+#define MC_XBAR_PERF_MON_CNTL0__STOP_THRESH__SHIFT 0x0000000c
+#define MC_XBAR_PERF_MON_CNTL1__START_TRIG_ID_MASK 0x0000ff00L
+#define MC_XBAR_PERF_MON_CNTL1__START_TRIG_ID__SHIFT 0x00000008
+#define MC_XBAR_PERF_MON_CNTL1__STOP_TRIG_ID_MASK 0x00ff0000L
+#define MC_XBAR_PERF_MON_CNTL1__STOP_TRIG_ID__SHIFT 0x00000010
+#define MC_XBAR_PERF_MON_CNTL1__THRESH_CNTR_ID_MASK 0x000000ffL
+#define MC_XBAR_PERF_MON_CNTL1__THRESH_CNTR_ID__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_CNTL2__MON0_ID_MASK 0x000000ffL
+#define MC_XBAR_PERF_MON_CNTL2__MON0_ID__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_CNTL2__MON1_ID_MASK 0x0000ff00L
+#define MC_XBAR_PERF_MON_CNTL2__MON1_ID__SHIFT 0x00000008
+#define MC_XBAR_PERF_MON_CNTL2__MON2_ID_MASK 0x00ff0000L
+#define MC_XBAR_PERF_MON_CNTL2__MON2_ID__SHIFT 0x00000010
+#define MC_XBAR_PERF_MON_CNTL2__MON3_ID_MASK 0xff000000L
+#define MC_XBAR_PERF_MON_CNTL2__MON3_ID__SHIFT 0x00000018
+#define MC_XBAR_PERF_MON_MAX_THSH__MON0_MASK 0x000000ffL
+#define MC_XBAR_PERF_MON_MAX_THSH__MON0__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_MAX_THSH__MON1_MASK 0x0000ff00L
+#define MC_XBAR_PERF_MON_MAX_THSH__MON1__SHIFT 0x00000008
+#define MC_XBAR_PERF_MON_MAX_THSH__MON2_MASK 0x00ff0000L
+#define MC_XBAR_PERF_MON_MAX_THSH__MON2__SHIFT 0x00000010
+#define MC_XBAR_PERF_MON_MAX_THSH__MON3_MASK 0xff000000L
+#define MC_XBAR_PERF_MON_MAX_THSH__MON3__SHIFT 0x00000018
+#define MC_XBAR_PERF_MON_RSLT0__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT0__COUNT__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_RSLT1__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT1__COUNT__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_RSLT2__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT2__COUNT__SHIFT 0x00000000
+#define MC_XBAR_PERF_MON_RSLT3__COUNT_MASK 0xffffffffL
+#define MC_XBAR_PERF_MON_RSLT3__COUNT__SHIFT 0x00000000
+#define MC_XBAR_RDREQ_CREDIT__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDREQ_CREDIT__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDREQ_CREDIT__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDREQ_CREDIT__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDREQ_CREDIT__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDREQ_CREDIT__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDREQ_CREDIT__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDREQ_CREDIT__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDREQ_PRI_CREDIT__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDRET_CREDIT1__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDRET_CREDIT1__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDRET_CREDIT1__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_CREDIT1__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDRET_CREDIT1__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDRET_CREDIT1__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDRET_CREDIT1__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDRET_CREDIT1__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDRET_CREDIT2__HUB_LP_RDRET_SKID_MASK 0x00ff0000L
+#define MC_XBAR_RDRET_CREDIT2__HUB_LP_RDRET_SKID__SHIFT 0x00000010
+#define MC_XBAR_RDRET_CREDIT2__OUT4_MASK 0x000000ffL
+#define MC_XBAR_RDRET_CREDIT2__OUT4__SHIFT 0x00000000
+#define MC_XBAR_RDRET_CREDIT2__OUT5_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_CREDIT2__OUT5__SHIFT 0x00000008
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT0_MASK 0x000000ffL
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT0__SHIFT 0x00000000
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT1__SHIFT 0x00000008
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT2__SHIFT 0x00000010
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT3_MASK 0xff000000L
+#define MC_XBAR_RDRET_PRI_CREDIT1__OUT3__SHIFT 0x00000018
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT4_MASK 0x000000ffL
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT4__SHIFT 0x00000000
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT5_MASK 0x0000ff00L
+#define MC_XBAR_RDRET_PRI_CREDIT2__OUT5__SHIFT 0x00000008
+#define MC_XBAR_REMOTE__RDREQ_EN_GOQ_MASK 0x00000002L
+#define MC_XBAR_REMOTE__RDREQ_EN_GOQ__SHIFT 0x00000001
+#define MC_XBAR_REMOTE__WRREQ_EN_GOQ_MASK 0x00000001L
+#define MC_XBAR_REMOTE__WRREQ_EN_GOQ__SHIFT 0x00000000
+#define MC_XBAR_SPARE0__BIT_MASK 0xffffffffL
+#define MC_XBAR_SPARE0__BIT__SHIFT 0x00000000
+#define MC_XBAR_SPARE1__BIT_MASK 0xffffffffL
+#define MC_XBAR_SPARE1__BIT__SHIFT 0x00000000
+#define MC_XBAR_TWOCHAN__CH0_MASK 0x00000006L
+#define MC_XBAR_TWOCHAN__CH0__SHIFT 0x00000001
+#define MC_XBAR_TWOCHAN__CH1_MASK 0x00000018L
+#define MC_XBAR_TWOCHAN__CH1__SHIFT 0x00000003
+#define MC_XBAR_TWOCHAN__DISABLE_ONEPORT_MASK 0x00000001L
+#define MC_XBAR_TWOCHAN__DISABLE_ONEPORT__SHIFT 0x00000000
+#define MC_XBAR_WRREQ_CREDIT__OUT0_MASK 0x000000ffL
+#define MC_XBAR_WRREQ_CREDIT__OUT0__SHIFT 0x00000000
+#define MC_XBAR_WRREQ_CREDIT__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_WRREQ_CREDIT__OUT1__SHIFT 0x00000008
+#define MC_XBAR_WRREQ_CREDIT__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_WRREQ_CREDIT__OUT2__SHIFT 0x00000010
+#define MC_XBAR_WRREQ_CREDIT__OUT3_MASK 0xff000000L
+#define MC_XBAR_WRREQ_CREDIT__OUT3__SHIFT 0x00000018
+#define MC_XBAR_WRRET_CREDIT1__OUT0_MASK 0x000000ffL
+#define MC_XBAR_WRRET_CREDIT1__OUT0__SHIFT 0x00000000
+#define MC_XBAR_WRRET_CREDIT1__OUT1_MASK 0x0000ff00L
+#define MC_XBAR_WRRET_CREDIT1__OUT1__SHIFT 0x00000008
+#define MC_XBAR_WRRET_CREDIT1__OUT2_MASK 0x00ff0000L
+#define MC_XBAR_WRRET_CREDIT1__OUT2__SHIFT 0x00000010
+#define MC_XBAR_WRRET_CREDIT1__OUT3_MASK 0xff000000L
+#define MC_XBAR_WRRET_CREDIT1__OUT3__SHIFT 0x00000018
+#define MC_XBAR_WRRET_CREDIT2__OUT4_MASK 0x000000ffL
+#define MC_XBAR_WRRET_CREDIT2__OUT4__SHIFT 0x00000000
+#define MC_XBAR_WRRET_CREDIT2__OUT5_MASK 0x0000ff00L
+#define MC_XBAR_WRRET_CREDIT2__OUT5__SHIFT 0x00000008
+#define MC_XPB_CLG_CFG0__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG0__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG0__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG0__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG0__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG0__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG0__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG0__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG0__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG0__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG10__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG10__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG10__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG10__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG10__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG10__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG10__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG10__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG10__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG10__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG11__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG11__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG11__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG11__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG11__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG11__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG11__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG11__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG11__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG11__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG12__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG12__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG12__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG12__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG12__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG12__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG12__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG12__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG12__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG12__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG13__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG13__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG13__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG13__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG13__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG13__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG13__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG13__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG13__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG13__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG14__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG14__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG14__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG14__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG14__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG14__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG14__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG14__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG14__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG14__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG15__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG15__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG15__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG15__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG15__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG15__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG15__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG15__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG15__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG15__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG16__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG16__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG16__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG16__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG16__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG16__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG16__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG16__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG16__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG16__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG17__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG17__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG17__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG17__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG17__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG17__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG17__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG17__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG17__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG17__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG18__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG18__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG18__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG18__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG18__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG18__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG18__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG18__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG18__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG18__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG19__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG19__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG19__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG19__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG19__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG19__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG19__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG19__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG19__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG19__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG1__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG1__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG1__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG1__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG1__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG1__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG1__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG1__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG1__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG1__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG20__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG20__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG20__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG20__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG20__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG20__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG20__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG20__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG20__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG20__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG21__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG21__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG21__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG21__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG21__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG21__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG21__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG21__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG21__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG21__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG22__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG22__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG22__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG22__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG22__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG22__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG22__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG22__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG22__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG22__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG23__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG23__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG23__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG23__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG23__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG23__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG23__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG23__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG23__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG23__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG24__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG24__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG24__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG24__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG24__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG24__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG24__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG24__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG24__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG24__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG25__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG25__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG25__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG25__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG25__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG25__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG25__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG25__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG25__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG25__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG26__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG26__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG26__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG26__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG26__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG26__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG26__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG26__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG26__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG26__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG27__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG27__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG27__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG27__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG27__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG27__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG27__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG27__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG27__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG27__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG28__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG28__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG28__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG28__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG28__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG28__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG28__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG28__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG28__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG28__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG29__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG29__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG29__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG29__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG29__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG29__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG29__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG29__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG29__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG29__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG2__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG2__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG2__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG2__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG2__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG2__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG2__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG2__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG2__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG2__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG30__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG30__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG30__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG30__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG30__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG30__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG30__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG30__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG30__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG30__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG31__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG31__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG31__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG31__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG31__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG31__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG31__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG31__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG31__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG31__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG32__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG32__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG32__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG32__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG32__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG32__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG32__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG32__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG32__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG32__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG33__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG33__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG33__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG33__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG33__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG33__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG33__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG33__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG33__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG33__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG34__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG34__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG34__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG34__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG34__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG34__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG34__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG34__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG34__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG34__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG35__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG35__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG35__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG35__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG35__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG35__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG35__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG35__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG35__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG35__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG36__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG36__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG36__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG36__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG36__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG36__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG36__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG36__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG36__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG36__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG3__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG3__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG3__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG3__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG3__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG3__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG3__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG3__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG3__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG3__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG4__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG4__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG4__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG4__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG4__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG4__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG4__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG4__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG4__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG4__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG5__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG5__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG5__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG5__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG5__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG5__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG5__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG5__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG5__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG5__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG6__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG6__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG6__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG6__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG6__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG6__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG6__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG6__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG6__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG6__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG7__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG7__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG7__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG7__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG7__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG7__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG7__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG7__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG7__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG7__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG8__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG8__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG8__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG8__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG8__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG8__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG8__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG8__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG8__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG8__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_CFG9__HOST_FLUSH_MASK 0x00003c00L
+#define MC_XPB_CLG_CFG9__HOST_FLUSH__SHIFT 0x0000000a
+#define MC_XPB_CLG_CFG9__LB_TYPE_MASK 0x00000070L
+#define MC_XPB_CLG_CFG9__LB_TYPE__SHIFT 0x00000004
+#define MC_XPB_CLG_CFG9__P2P_BAR_MASK 0x00000380L
+#define MC_XPB_CLG_CFG9__P2P_BAR__SHIFT 0x00000007
+#define MC_XPB_CLG_CFG9__SIDE_FLUSH_MASK 0x0003c000L
+#define MC_XPB_CLG_CFG9__SIDE_FLUSH__SHIFT 0x0000000e
+#define MC_XPB_CLG_CFG9__WCB_NUM_MASK 0x0000000fL
+#define MC_XPB_CLG_CFG9__WCB_NUM__SHIFT 0x00000000
+#define MC_XPB_CLG_EXTRA__CMP0_MASK 0x000000ffL
+#define MC_XPB_CLG_EXTRA__CMP0__SHIFT 0x00000000
+#define MC_XPB_CLG_EXTRA__CMP1_MASK 0x01fe0000L
+#define MC_XPB_CLG_EXTRA__CMP1__SHIFT 0x00000011
+#define MC_XPB_CLG_EXTRA__MSK0_MASK 0x0000ff00L
+#define MC_XPB_CLG_EXTRA__MSK0__SHIFT 0x00000008
+#define MC_XPB_CLG_EXTRA_RD__CMP0_MASK 0x000000ffL
+#define MC_XPB_CLG_EXTRA_RD__CMP0__SHIFT 0x00000000
+#define MC_XPB_CLG_EXTRA_RD__CMP1_MASK 0x01fe0000L
+#define MC_XPB_CLG_EXTRA_RD__CMP1__SHIFT 0x00000011
+#define MC_XPB_CLG_EXTRA_RD__MSK0_MASK 0x0000ff00L
+#define MC_XPB_CLG_EXTRA_RD__MSK0__SHIFT 0x00000008
+#define MC_XPB_CLG_EXTRA_RD__VLD0_MASK 0x00010000L
+#define MC_XPB_CLG_EXTRA_RD__VLD0__SHIFT 0x00000010
+#define MC_XPB_CLG_EXTRA_RD__VLD1_MASK 0x02000000L
+#define MC_XPB_CLG_EXTRA_RD__VLD1__SHIFT 0x00000019
+#define MC_XPB_CLG_EXTRA__VLD0_MASK 0x00010000L
+#define MC_XPB_CLG_EXTRA__VLD0__SHIFT 0x00000010
+#define MC_XPB_CLG_EXTRA__VLD1_MASK 0x02000000L
+#define MC_XPB_CLG_EXTRA__VLD1__SHIFT 0x00000019
+#define MC_XPB_CLK_GAT__ENABLE_MASK 0x00040000L
+#define MC_XPB_CLK_GAT__ENABLE__SHIFT 0x00000012
+#define MC_XPB_CLK_GAT__MEM_LS_ENABLE_MASK 0x00080000L
+#define MC_XPB_CLK_GAT__MEM_LS_ENABLE__SHIFT 0x00000013
+#define MC_XPB_CLK_GAT__OFFDLY_MASK 0x00000fc0L
+#define MC_XPB_CLK_GAT__OFFDLY__SHIFT 0x00000006
+#define MC_XPB_CLK_GAT__ONDLY_MASK 0x0000003fL
+#define MC_XPB_CLK_GAT__ONDLY__SHIFT 0x00000000
+#define MC_XPB_CLK_GAT__RDYDLY_MASK 0x0003f000L
+#define MC_XPB_CLK_GAT__RDYDLY__SHIFT 0x0000000c
+#define MC_XPB_INTF_CFG2__RPB_RDREQ_CRD_MASK 0x000000ffL
+#define MC_XPB_INTF_CFG2__RPB_RDREQ_CRD__SHIFT 0x00000000
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_SEL_MASK 0x02000000L
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_SEL__SHIFT 0x00000019
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_VAL_MASK 0x04000000L
+#define MC_XPB_INTF_CFG__BIF_MEM_SNOOP_VAL__SHIFT 0x0000001a
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_SEL_MASK 0x00800000L
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_SEL__SHIFT 0x00000017
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_VAL_MASK 0x01000000L
+#define MC_XPB_INTF_CFG__BIF_REG_SNOOP_VAL__SHIFT 0x00000018
+#define MC_XPB_INTF_CFG__MC_WRRET_ASK_MASK 0x0000ff00L
+#define MC_XPB_INTF_CFG__MC_WRRET_ASK__SHIFT 0x00000008
+#define MC_XPB_INTF_CFG__RPB_WRREQ_CRD_MASK 0x000000ffL
+#define MC_XPB_INTF_CFG__RPB_WRREQ_CRD__SHIFT 0x00000000
+#define MC_XPB_INTF_CFG__XSP_ORDERING_SEL_MASK 0x40000000L
+#define MC_XPB_INTF_CFG__XSP_ORDERING_SEL__SHIFT 0x0000001e
+#define MC_XPB_INTF_CFG__XSP_ORDERING_VAL_MASK 0x80000000L
+#define MC_XPB_INTF_CFG__XSP_ORDERING_VAL__SHIFT 0x0000001f
+#define MC_XPB_INTF_CFG__XSP_REQ_CRD_MASK 0x007f0000L
+#define MC_XPB_INTF_CFG__XSP_REQ_CRD__SHIFT 0x00000010
+#define MC_XPB_INTF_CFG__XSP_SNOOP_SEL_MASK 0x18000000L
+#define MC_XPB_INTF_CFG__XSP_SNOOP_SEL__SHIFT 0x0000001b
+#define MC_XPB_INTF_CFG__XSP_SNOOP_VAL_MASK 0x20000000L
+#define MC_XPB_INTF_CFG__XSP_SNOOP_VAL__SHIFT 0x0000001d
+#define MC_XPB_INTF_STS__CNS_BUF_BUSY_MASK 0x00040000L
+#define MC_XPB_INTF_STS__CNS_BUF_BUSY__SHIFT 0x00000012
+#define MC_XPB_INTF_STS__CNS_BUF_FULL_MASK 0x00020000L
+#define MC_XPB_INTF_STS__CNS_BUF_FULL__SHIFT 0x00000011
+#define MC_XPB_INTF_STS__HOP_ATTR_BUF_FULL_MASK 0x00010000L
+#define MC_XPB_INTF_STS__HOP_ATTR_BUF_FULL__SHIFT 0x00000010
+#define MC_XPB_INTF_STS__HOP_DATA_BUF_FULL_MASK 0x00008000L
+#define MC_XPB_INTF_STS__HOP_DATA_BUF_FULL__SHIFT 0x0000000f
+#define MC_XPB_INTF_STS__RPB_RDREQ_CRD_MASK 0x07f80000L
+#define MC_XPB_INTF_STS__RPB_RDREQ_CRD__SHIFT 0x00000013
+#define MC_XPB_INTF_STS__RPB_WRREQ_CRD_MASK 0x000000ffL
+#define MC_XPB_INTF_STS__RPB_WRREQ_CRD__SHIFT 0x00000000
+#define MC_XPB_INTF_STS__XSP_REQ_CRD_MASK 0x00007f00L
+#define MC_XPB_INTF_STS__XSP_REQ_CRD__SHIFT 0x00000008
+#define MC_XPB_LB_ADDR__CMP0_MASK 0x000003ffL
+#define MC_XPB_LB_ADDR__CMP0__SHIFT 0x00000000
+#define MC_XPB_LB_ADDR__CMP1_MASK 0x03f00000L
+#define MC_XPB_LB_ADDR__CMP1__SHIFT 0x00000014
+#define MC_XPB_LB_ADDR__MASK0_MASK 0x000ffc00L
+#define MC_XPB_LB_ADDR__MASK0__SHIFT 0x0000000a
+#define MC_XPB_LB_ADDR__MASK1_MASK 0xfc000000L
+#define MC_XPB_LB_ADDR__MASK1__SHIFT 0x0000001a
+#define MC_XPB_MAP_INVERT_FLUSH_NUM_LSB__ALTER_FLUSH_NUM_MASK 0x0000ffffL
+#define MC_XPB_MAP_INVERT_FLUSH_NUM_LSB__ALTER_FLUSH_NUM__SHIFT 0x00000000
+#define MC_XPB_MISC_CFG__FIELDNAME0_MASK 0x000000ffL
+#define MC_XPB_MISC_CFG__FIELDNAME0__SHIFT 0x00000000
+#define MC_XPB_MISC_CFG__FIELDNAME1_MASK 0x0000ff00L
+#define MC_XPB_MISC_CFG__FIELDNAME1__SHIFT 0x00000008
+#define MC_XPB_MISC_CFG__FIELDNAME2_MASK 0x00ff0000L
+#define MC_XPB_MISC_CFG__FIELDNAME2__SHIFT 0x00000010
+#define MC_XPB_MISC_CFG__FIELDNAME3_MASK 0x7f000000L
+#define MC_XPB_MISC_CFG__FIELDNAME3__SHIFT 0x00000018
+#define MC_XPB_MISC_CFG__TRIGGERNAME_MASK 0x80000000L
+#define MC_XPB_MISC_CFG__TRIGGERNAME__SHIFT 0x0000001f
+#define MC_XPB_P2P_BAR0__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR0__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR0__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR0__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR0__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR0__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR0__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR0__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR0__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR0__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR0__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR0__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR0__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR0__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR0__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR0__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR1__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR1__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR1__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR1__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR1__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR1__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR1__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR1__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR1__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR1__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR1__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR1__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR1__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR1__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR1__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR1__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR2__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR2__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR2__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR2__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR2__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR2__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR2__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR2__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR2__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR2__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR2__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR2__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR2__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR2__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR2__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR2__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR3__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR3__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR3__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR3__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR3__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR3__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR3__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR3__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR3__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR3__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR3__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR3__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR3__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR3__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR3__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR3__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR4__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR4__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR4__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR4__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR4__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR4__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR4__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR4__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR4__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR4__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR4__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR4__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR4__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR4__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR4__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR4__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR5__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR5__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR5__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR5__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR5__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR5__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR5__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR5__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR5__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR5__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR5__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR5__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR5__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR5__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR5__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR5__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR6__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR6__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR6__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR6__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR6__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR6__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR6__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR6__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR6__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR6__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR6__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR6__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR6__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR6__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR6__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR6__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR7__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR7__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR7__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR7__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR7__HOST_FLUSH_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR7__HOST_FLUSH__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR7__MEM_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR7__MEM_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR7__REG_SYS_BAR_MASK 0x000000f0L
+#define MC_XPB_P2P_BAR7__REG_SYS_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR7__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR7__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR7__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR7__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR7__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR7__VALID__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR_CFG__ADDR_SIZE_MASK 0x0000000fL
+#define MC_XPB_P2P_BAR_CFG__ADDR_SIZE__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_CFG__ATC_TRANSLATED_MASK 0x00001000L
+#define MC_XPB_P2P_BAR_CFG__ATC_TRANSLATED__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR_CFG__COMPRESS_DIS_MASK 0x00000100L
+#define MC_XPB_P2P_BAR_CFG__COMPRESS_DIS__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_CFG__RD_EN_MASK 0x00000800L
+#define MC_XPB_P2P_BAR_CFG__RD_EN__SHIFT 0x0000000b
+#define MC_XPB_P2P_BAR_CFG__REGBAR_FROM_SYSBAR_MASK 0x00000400L
+#define MC_XPB_P2P_BAR_CFG__REGBAR_FROM_SYSBAR__SHIFT 0x0000000a
+#define MC_XPB_P2P_BAR_CFG__SEND_BAR_MASK 0x00000030L
+#define MC_XPB_P2P_BAR_CFG__SEND_BAR__SHIFT 0x00000004
+#define MC_XPB_P2P_BAR_CFG__SEND_DIS_MASK 0x00000080L
+#define MC_XPB_P2P_BAR_CFG__SEND_DIS__SHIFT 0x00000007
+#define MC_XPB_P2P_BAR_CFG__SNOOP_MASK 0x00000040L
+#define MC_XPB_P2P_BAR_CFG__SNOOP__SHIFT 0x00000006
+#define MC_XPB_P2P_BAR_CFG__UPDATE_DIS_MASK 0x00000200L
+#define MC_XPB_P2P_BAR_CFG__UPDATE_DIS__SHIFT 0x00000009
+#define MC_XPB_P2P_BAR_DEBUG__HOST_FLUSH_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR_DEBUG__HOST_FLUSH__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_DEBUG__MEM_SYS_BAR_MASK 0x0000f000L
+#define MC_XPB_P2P_BAR_DEBUG__MEM_SYS_BAR__SHIFT 0x0000000c
+#define MC_XPB_P2P_BAR_DEBUG__SEL_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_DEBUG__SEL__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__DELTA_MASK 0x0fffff00L
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__DELTA__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__EN_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_DELTA_ABOVE__EN__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_DELTA_BELOW__DELTA_MASK 0x0fffff00L
+#define MC_XPB_P2P_BAR_DELTA_BELOW__DELTA__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_DELTA_BELOW__EN_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_DELTA_BELOW__EN__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_SETUP__ADDRESS_MASK 0xffff0000L
+#define MC_XPB_P2P_BAR_SETUP__ADDRESS__SHIFT 0x00000010
+#define MC_XPB_P2P_BAR_SETUP__COMPRESS_DIS_MASK 0x00004000L
+#define MC_XPB_P2P_BAR_SETUP__COMPRESS_DIS__SHIFT 0x0000000e
+#define MC_XPB_P2P_BAR_SETUP__REG_SYS_BAR_MASK 0x00000f00L
+#define MC_XPB_P2P_BAR_SETUP__REG_SYS_BAR__SHIFT 0x00000008
+#define MC_XPB_P2P_BAR_SETUP__RESERVED_MASK 0x00008000L
+#define MC_XPB_P2P_BAR_SETUP__RESERVED__SHIFT 0x0000000f
+#define MC_XPB_P2P_BAR_SETUP__SEL_MASK 0x000000ffL
+#define MC_XPB_P2P_BAR_SETUP__SEL__SHIFT 0x00000000
+#define MC_XPB_P2P_BAR_SETUP__SEND_DIS_MASK 0x00002000L
+#define MC_XPB_P2P_BAR_SETUP__SEND_DIS__SHIFT 0x0000000d
+#define MC_XPB_P2P_BAR_SETUP__VALID_MASK 0x00001000L
+#define MC_XPB_P2P_BAR_SETUP__VALID__SHIFT 0x0000000c
+#define MC_XPB_PEER_SYS_BAR0__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR0__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR0__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR0__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR0__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR0__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR1__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR1__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR1__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR1__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR1__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR1__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR2__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR2__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR2__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR2__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR2__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR2__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR3__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR3__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR3__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR3__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR3__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR3__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR4__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR4__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR4__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR4__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR4__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR4__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR5__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR5__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR5__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR5__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR5__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR5__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR6__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR6__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR6__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR6__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR6__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR6__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR7__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR7__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR7__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR7__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR7__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR7__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR8__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR8__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR8__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR8__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR8__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR8__VALID__SHIFT 0x00000000
+#define MC_XPB_PEER_SYS_BAR9__ADDR_MASK 0x07fffffcL
+#define MC_XPB_PEER_SYS_BAR9__ADDR__SHIFT 0x00000002
+#define MC_XPB_PEER_SYS_BAR9__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_PEER_SYS_BAR9__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_PEER_SYS_BAR9__VALID_MASK 0x00000001L
+#define MC_XPB_PEER_SYS_BAR9__VALID__SHIFT 0x00000000
+#define MC_XPB_PERF_KNOBS__CNS_FIFO_DEPTH_MASK 0x0000003fL
+#define MC_XPB_PERF_KNOBS__CNS_FIFO_DEPTH__SHIFT 0x00000000
+#define MC_XPB_PERF_KNOBS__WCB_HST_FIFO_DEPTH_MASK 0x00000fc0L
+#define MC_XPB_PERF_KNOBS__WCB_HST_FIFO_DEPTH__SHIFT 0x00000006
+#define MC_XPB_PERF_KNOBS__WCB_SID_FIFO_DEPTH_MASK 0x0003f000L
+#define MC_XPB_PERF_KNOBS__WCB_SID_FIFO_DEPTH__SHIFT 0x0000000c
+#define MC_XPB_PIPE_STS__RET_BUF_FULL_MASK 0x00800000L
+#define MC_XPB_PIPE_STS__RET_BUF_FULL__SHIFT 0x00000017
+#define MC_XPB_PIPE_STS__WCB_ANY_PBUF_MASK 0x00000001L
+#define MC_XPB_PIPE_STS__WCB_ANY_PBUF__SHIFT 0x00000000
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_BUF_CNT_MASK 0x000000feL
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_BUF_CNT__SHIFT 0x00000001
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_OBUF_FULL_MASK 0x00200000L
+#define MC_XPB_PIPE_STS__WCB_HST_DATA_OBUF_FULL__SHIFT 0x00000015
+#define MC_XPB_PIPE_STS__WCB_HST_RD_PTR_BUF_FULL_MASK 0x00008000L
+#define MC_XPB_PIPE_STS__WCB_HST_RD_PTR_BUF_FULL__SHIFT 0x0000000f
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_FIFO_FULL_MASK 0x00020000L
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_FIFO_FULL__SHIFT 0x00000011
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_OBUF_FULL_MASK 0x00080000L
+#define MC_XPB_PIPE_STS__WCB_HST_REQ_OBUF_FULL__SHIFT 0x00000013
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_BUF_CNT_MASK 0x00007f00L
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_BUF_CNT__SHIFT 0x00000008
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_OBUF_FULL_MASK 0x00400000L
+#define MC_XPB_PIPE_STS__WCB_SID_DATA_OBUF_FULL__SHIFT 0x00000016
+#define MC_XPB_PIPE_STS__WCB_SID_RD_PTR_BUF_FULL_MASK 0x00010000L
+#define MC_XPB_PIPE_STS__WCB_SID_RD_PTR_BUF_FULL__SHIFT 0x00000010
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_FIFO_FULL_MASK 0x00040000L
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_FIFO_FULL__SHIFT 0x00000012
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_OBUF_FULL_MASK 0x00100000L
+#define MC_XPB_PIPE_STS__WCB_SID_REQ_OBUF_FULL__SHIFT 0x00000014
+#define MC_XPB_PIPE_STS__XPB_CLK_BUSY_BITS_MASK 0xff000000L
+#define MC_XPB_PIPE_STS__XPB_CLK_BUSY_BITS__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP0__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP0__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP0__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP0__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP0__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP0__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP0__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP0__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP0__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP1__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP1__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP1__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP1__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP1__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP1__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP1__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP1__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP1__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP2__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP2__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP2__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP2__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP2__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP2__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP2__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP2__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP2__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP3__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP3__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP3__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP3__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP3__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP3__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP3__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP3__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP3__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP4__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP4__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP4__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP4__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP4__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP4__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP4__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP4__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP4__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP5__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP5__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP5__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP5__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP5__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP5__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP5__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP5__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP5__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP6__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP6__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP6__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP6__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP6__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP6__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP6__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP6__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP6__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP7__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP7__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP7__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP7__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP7__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP7__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP7__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP7__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP7__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP8__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP8__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP8__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP8__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP8__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP8__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP8__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP8__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP8__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_DEST_MAP9__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_RTR_DEST_MAP9__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_RTR_DEST_MAP9__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_RTR_DEST_MAP9__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_RTR_DEST_MAP9__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_RTR_DEST_MAP9__NMR_MASK 0x00000001L
+#define MC_XPB_RTR_DEST_MAP9__NMR__SHIFT 0x00000000
+#define MC_XPB_RTR_DEST_MAP9__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_RTR_DEST_MAP9__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_RTR_SRC_APRTR0__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR0__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR1__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR1__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR2__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR2__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR3__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR3__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR4__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR4__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR5__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR5__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR6__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR6__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR7__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR7__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR8__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR8__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_RTR_SRC_APRTR9__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_RTR_SRC_APRTR9__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_STICKY__BITS_MASK 0xffffffffL
+#define MC_XPB_STICKY__BITS__SHIFT 0x00000000
+#define MC_XPB_STICKY_W1C__BITS_MASK 0xffffffffL
+#define MC_XPB_STICKY_W1C__BITS__SHIFT 0x00000000
+#define MC_XPB_SUB_CTRL__RESET_CGR_MASK 0x00080000L
+#define MC_XPB_SUB_CTRL__RESET_CGR__SHIFT 0x00000013
+#define MC_XPB_SUB_CTRL__RESET_CNS_MASK 0x00000400L
+#define MC_XPB_SUB_CTRL__RESET_CNS__SHIFT 0x0000000a
+#define MC_XPB_SUB_CTRL__RESET_HOP_MASK 0x00010000L
+#define MC_XPB_SUB_CTRL__RESET_HOP__SHIFT 0x00000010
+#define MC_XPB_SUB_CTRL__RESET_HST_MASK 0x00008000L
+#define MC_XPB_SUB_CTRL__RESET_HST__SHIFT 0x0000000f
+#define MC_XPB_SUB_CTRL__RESET_MAP_MASK 0x00002000L
+#define MC_XPB_SUB_CTRL__RESET_MAP__SHIFT 0x0000000d
+#define MC_XPB_SUB_CTRL__RESET_RET_MASK 0x00001000L
+#define MC_XPB_SUB_CTRL__RESET_RET__SHIFT 0x0000000c
+#define MC_XPB_SUB_CTRL__RESET_RTR_MASK 0x00000800L
+#define MC_XPB_SUB_CTRL__RESET_RTR__SHIFT 0x0000000b
+#define MC_XPB_SUB_CTRL__RESET_SID_MASK 0x00020000L
+#define MC_XPB_SUB_CTRL__RESET_SID__SHIFT 0x00000011
+#define MC_XPB_SUB_CTRL__RESET_SRB_MASK 0x00040000L
+#define MC_XPB_SUB_CTRL__RESET_SRB__SHIFT 0x00000012
+#define MC_XPB_SUB_CTRL__RESET_WCB_MASK 0x00004000L
+#define MC_XPB_SUB_CTRL__RESET_WCB__SHIFT 0x0000000e
+#define MC_XPB_SUB_CTRL__STALL_CNS_RTR_REQ_MASK 0x00000002L
+#define MC_XPB_SUB_CTRL__STALL_CNS_RTR_REQ__SHIFT 0x00000001
+#define MC_XPB_SUB_CTRL__STALL_HST_HOP_REQ_MASK 0x00000100L
+#define MC_XPB_SUB_CTRL__STALL_HST_HOP_REQ__SHIFT 0x00000008
+#define MC_XPB_SUB_CTRL__STALL_MAP_WCB_REQ_MASK 0x00000010L
+#define MC_XPB_SUB_CTRL__STALL_MAP_WCB_REQ__SHIFT 0x00000004
+#define MC_XPB_SUB_CTRL__STALL_MC_XSP_REQ_SEND_MASK 0x00000040L
+#define MC_XPB_SUB_CTRL__STALL_MC_XSP_REQ_SEND__SHIFT 0x00000006
+#define MC_XPB_SUB_CTRL__STALL_RTR_MAP_REQ_MASK 0x00000008L
+#define MC_XPB_SUB_CTRL__STALL_RTR_MAP_REQ__SHIFT 0x00000003
+#define MC_XPB_SUB_CTRL__STALL_RTR_RPB_WRREQ_MASK 0x00000004L
+#define MC_XPB_SUB_CTRL__STALL_RTR_RPB_WRREQ__SHIFT 0x00000002
+#define MC_XPB_SUB_CTRL__STALL_WCB_HST_REQ_MASK 0x00000080L
+#define MC_XPB_SUB_CTRL__STALL_WCB_HST_REQ__SHIFT 0x00000007
+#define MC_XPB_SUB_CTRL__STALL_WCB_SID_REQ_MASK 0x00000020L
+#define MC_XPB_SUB_CTRL__STALL_WCB_SID_REQ__SHIFT 0x00000005
+#define MC_XPB_SUB_CTRL__STALL_XPB_RPB_REQ_ATTR_MASK 0x00000200L
+#define MC_XPB_SUB_CTRL__STALL_XPB_RPB_REQ_ATTR__SHIFT 0x00000009
+#define MC_XPB_SUB_CTRL__WRREQ_BYPASS_XPB_MASK 0x00000001L
+#define MC_XPB_SUB_CTRL__WRREQ_BYPASS_XPB__SHIFT 0x00000000
+#define MC_XPB_UNC_THRESH_HST__CHANGE_PREF_MASK 0x0000003fL
+#define MC_XPB_UNC_THRESH_HST__CHANGE_PREF__SHIFT 0x00000000
+#define MC_XPB_UNC_THRESH_HST__STRONG_PREF_MASK 0x00000fc0L
+#define MC_XPB_UNC_THRESH_HST__STRONG_PREF__SHIFT 0x00000006
+#define MC_XPB_UNC_THRESH_HST__USE_UNFULL_MASK 0x0003f000L
+#define MC_XPB_UNC_THRESH_HST__USE_UNFULL__SHIFT 0x0000000c
+#define MC_XPB_UNC_THRESH_SID__CHANGE_PREF_MASK 0x0000003fL
+#define MC_XPB_UNC_THRESH_SID__CHANGE_PREF__SHIFT 0x00000000
+#define MC_XPB_UNC_THRESH_SID__STRONG_PREF_MASK 0x00000fc0L
+#define MC_XPB_UNC_THRESH_SID__STRONG_PREF__SHIFT 0x00000006
+#define MC_XPB_UNC_THRESH_SID__USE_UNFULL_MASK 0x0003f000L
+#define MC_XPB_UNC_THRESH_SID__USE_UNFULL__SHIFT 0x0000000c
+#define MC_XPB_WCB_CFG__HST_MAX_MASK 0x00030000L
+#define MC_XPB_WCB_CFG__HST_MAX__SHIFT 0x00000010
+#define MC_XPB_WCB_CFG__SID_MAX_MASK 0x000c0000L
+#define MC_XPB_WCB_CFG__SID_MAX__SHIFT 0x00000012
+#define MC_XPB_WCB_CFG__TIMEOUT_MASK 0x0000ffffL
+#define MC_XPB_WCB_CFG__TIMEOUT__SHIFT 0x00000000
+#define MC_XPB_WCB_STS__PBUF_VLD_MASK 0x0000ffffL
+#define MC_XPB_WCB_STS__PBUF_VLD__SHIFT 0x00000000
+#define MC_XPB_WCB_STS__WCB_HST_DATA_BUF_CNT_MASK 0x007f0000L
+#define MC_XPB_WCB_STS__WCB_HST_DATA_BUF_CNT__SHIFT 0x00000010
+#define MC_XPB_WCB_STS__WCB_SID_DATA_BUF_CNT_MASK 0x3f800000L
+#define MC_XPB_WCB_STS__WCB_SID_DATA_BUF_CNT__SHIFT 0x00000017
+#define MC_XPB_XDMA_PEER_SYS_BAR0__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR0__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR0__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR0__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR0__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR0__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_PEER_SYS_BAR1__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR1__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR1__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR1__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR1__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR1__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_PEER_SYS_BAR2__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR2__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR2__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR2__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR2__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR2__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_PEER_SYS_BAR3__ADDR_MASK 0x07fffffcL
+#define MC_XPB_XDMA_PEER_SYS_BAR3__ADDR__SHIFT 0x00000002
+#define MC_XPB_XDMA_PEER_SYS_BAR3__SIDE_OK_MASK 0x00000002L
+#define MC_XPB_XDMA_PEER_SYS_BAR3__SIDE_OK__SHIFT 0x00000001
+#define MC_XPB_XDMA_PEER_SYS_BAR3__VALID_MASK 0x00000001L
+#define MC_XPB_XDMA_PEER_SYS_BAR3__VALID__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP0__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP0__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP0__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP0__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP0__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_DEST_MAP1__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP1__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP1__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP1__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP1__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_DEST_MAP2__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP2__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP2__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP2__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP2__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_DEST_MAP3__APRTR_SIZE_MASK 0x7c000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__APRTR_SIZE__SHIFT 0x0000001a
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_OFFSET_MASK 0x000ffffeL
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_OFFSET__SHIFT 0x00000001
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL_MASK 0x00f00000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL_RPB_MASK 0x01000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL_RPB__SHIFT 0x00000018
+#define MC_XPB_XDMA_RTR_DEST_MAP3__DEST_SEL__SHIFT 0x00000014
+#define MC_XPB_XDMA_RTR_DEST_MAP3__NMR_MASK 0x00000001L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__NMR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_DEST_MAP3__SIDE_OK_MASK 0x02000000L
+#define MC_XPB_XDMA_RTR_DEST_MAP3__SIDE_OK__SHIFT 0x00000019
+#define MC_XPB_XDMA_RTR_SRC_APRTR0__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR0__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_SRC_APRTR1__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR1__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_SRC_APRTR2__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR2__BASE_ADDR__SHIFT 0x00000000
+#define MC_XPB_XDMA_RTR_SRC_APRTR3__BASE_ADDR_MASK 0x01ffffffL
+#define MC_XPB_XDMA_RTR_SRC_APRTR3__BASE_ADDR__SHIFT 0x00000000
+#define MPLL_AD_FUNC_CNTL__SPARE_MASK 0xfffffff8L
+#define MPLL_AD_FUNC_CNTL__SPARE__SHIFT 0x00000003
+#define MPLL_AD_FUNC_CNTL__YCLK_POST_DIV_MASK 0x00000007L
+#define MPLL_AD_FUNC_CNTL__YCLK_POST_DIV__SHIFT 0x00000000
+#define MPLL_AD_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_AD_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_AD_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_AD_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_AD_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_AD_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_AD_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_AD_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_AD_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_AD_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_AD_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_AD_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_CNTL_MODE__FAST_LOCK_CNTRL_MASK 0x00600000L
+#define MPLL_CNTL_MODE__FAST_LOCK_CNTRL__SHIFT 0x00000015
+#define MPLL_CNTL_MODE__FAST_LOCK_EN_MASK 0x00100000L
+#define MPLL_CNTL_MODE__FAST_LOCK_EN__SHIFT 0x00000014
+#define MPLL_CNTL_MODE__FORCE_TESTMODE_MASK 0x00020000L
+#define MPLL_CNTL_MODE__FORCE_TESTMODE__SHIFT 0x00000011
+#define MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK 0x80000000L
+#define MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT 0x0000001f
+#define MPLL_CNTL_MODE__INSTR_DELAY_MASK 0x000000ffL
+#define MPLL_CNTL_MODE__INSTR_DELAY__SHIFT 0x00000000
+#define MPLL_CNTL_MODE__MPLL_CHG_STATUS_MASK 0x00010000L
+#define MPLL_CNTL_MODE__MPLL_CHG_STATUS__SHIFT 0x00000010
+#define MPLL_CNTL_MODE__MPLL_CTLREQ_MASK 0x00004000L
+#define MPLL_CNTL_MODE__MPLL_CTLREQ__SHIFT 0x0000000e
+#define MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK 0x00000800L
+#define MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT 0x0000000b
+#define MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK 0x00000100L
+#define MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT 0x00000008
+#define MPLL_CNTL_MODE__QDR_MASK 0x00002000L
+#define MPLL_CNTL_MODE__QDR__SHIFT 0x0000000d
+#define MPLL_CNTL_MODE__SPARE_1_MASK 0x00001000L
+#define MPLL_CNTL_MODE__SPARE_1__SHIFT 0x0000000c
+#define MPLL_CNTL_MODE__SPARE_2_MASK 0x00800000L
+#define MPLL_CNTL_MODE__SPARE_2__SHIFT 0x00000017
+#define MPLL_CNTL_MODE__SPARE_3_MASK 0x70000000L
+#define MPLL_CNTL_MODE__SPARE_3__SHIFT 0x0000001c
+#define MPLL_CNTL_MODE__SS_DSMODE_EN_MASK 0x04000000L
+#define MPLL_CNTL_MODE__SS_DSMODE_EN__SHIFT 0x0000001a
+#define MPLL_CNTL_MODE__SS_SSEN_MASK 0x03000000L
+#define MPLL_CNTL_MODE__SS_SSEN__SHIFT 0x00000018
+#define MPLL_CNTL_MODE__VTOI_BIAS_CNTRL_MASK 0x08000000L
+#define MPLL_CNTL_MODE__VTOI_BIAS_CNTRL__SHIFT 0x0000001b
+#define MPLL_CONTROL__AD_BG_PWRON_MASK 0x00001000L
+#define MPLL_CONTROL__AD_BG_PWRON__SHIFT 0x0000000c
+#define MPLL_CONTROL__AD_PLL_PWRON_MASK 0x00002000L
+#define MPLL_CONTROL__AD_PLL_PWRON__SHIFT 0x0000000d
+#define MPLL_CONTROL__AD_PLL_RESET_MASK 0x00004000L
+#define MPLL_CONTROL__AD_PLL_RESET__SHIFT 0x0000000e
+#define MPLL_CONTROL__DQ_0_0_BG_PWRON_MASK 0x00010000L
+#define MPLL_CONTROL__DQ_0_0_BG_PWRON__SHIFT 0x00000010
+#define MPLL_CONTROL__DQ_0_0_PLL_PWRON_MASK 0x00020000L
+#define MPLL_CONTROL__DQ_0_0_PLL_PWRON__SHIFT 0x00000011
+#define MPLL_CONTROL__DQ_0_0_PLL_RESET_MASK 0x00040000L
+#define MPLL_CONTROL__DQ_0_0_PLL_RESET__SHIFT 0x00000012
+#define MPLL_CONTROL__DQ_0_1_BG_PWRON_MASK 0x00100000L
+#define MPLL_CONTROL__DQ_0_1_BG_PWRON__SHIFT 0x00000014
+#define MPLL_CONTROL__DQ_0_1_PLL_PWRON_MASK 0x00200000L
+#define MPLL_CONTROL__DQ_0_1_PLL_PWRON__SHIFT 0x00000015
+#define MPLL_CONTROL__DQ_0_1_PLL_RESET_MASK 0x00400000L
+#define MPLL_CONTROL__DQ_0_1_PLL_RESET__SHIFT 0x00000016
+#define MPLL_CONTROL__DQ_1_0_BG_PWRON_MASK 0x01000000L
+#define MPLL_CONTROL__DQ_1_0_BG_PWRON__SHIFT 0x00000018
+#define MPLL_CONTROL__DQ_1_0_PLL_PWRON_MASK 0x02000000L
+#define MPLL_CONTROL__DQ_1_0_PLL_PWRON__SHIFT 0x00000019
+#define MPLL_CONTROL__DQ_1_0_PLL_RESET_MASK 0x04000000L
+#define MPLL_CONTROL__DQ_1_0_PLL_RESET__SHIFT 0x0000001a
+#define MPLL_CONTROL__DQ_1_1_BG_PWRON_MASK 0x10000000L
+#define MPLL_CONTROL__DQ_1_1_BG_PWRON__SHIFT 0x0000001c
+#define MPLL_CONTROL__DQ_1_1_PLL_PWRON_MASK 0x20000000L
+#define MPLL_CONTROL__DQ_1_1_PLL_PWRON__SHIFT 0x0000001d
+#define MPLL_CONTROL__DQ_1_1_PLL_RESET_MASK 0x40000000L
+#define MPLL_CONTROL__DQ_1_1_PLL_RESET__SHIFT 0x0000001e
+#define MPLL_CONTROL__GDDR_PWRON_MASK 0x00000001L
+#define MPLL_CONTROL__GDDR_PWRON__SHIFT 0x00000000
+#define MPLL_CONTROL__PLL_BUF_PWRON_TX_MASK 0x00000004L
+#define MPLL_CONTROL__PLL_BUF_PWRON_TX__SHIFT 0x00000002
+#define MPLL_CONTROL__REFCLK_PWRON_MASK 0x00000002L
+#define MPLL_CONTROL__REFCLK_PWRON__SHIFT 0x00000001
+#define MPLL_CONTROL__SPARE_AD_0_MASK 0x00008000L
+#define MPLL_CONTROL__SPARE_AD_0__SHIFT 0x0000000f
+#define MPLL_CONTROL__SPARE_DQ_0_0_MASK 0x00080000L
+#define MPLL_CONTROL__SPARE_DQ_0_0__SHIFT 0x00000013
+#define MPLL_CONTROL__SPARE_DQ_0_1_MASK 0x00800000L
+#define MPLL_CONTROL__SPARE_DQ_0_1__SHIFT 0x00000017
+#define MPLL_CONTROL__SPARE_DQ_1_0_MASK 0x08000000L
+#define MPLL_CONTROL__SPARE_DQ_1_0__SHIFT 0x0000001b
+#define MPLL_CONTROL__SPARE_DQ_1_1_MASK 0x80000000L
+#define MPLL_CONTROL__SPARE_DQ_1_1__SHIFT 0x0000001f
+#define MPLL_DQ_0_0_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_0_0_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_0_0_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_0_0_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_0_0_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_0_0_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_0_0_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_0_0_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_0_0_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_0_1_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_0_1_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_0_1_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_0_1_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_0_1_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_0_1_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_0_1_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_0_1_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_0_1_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_1_0_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_1_0_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_1_0_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_1_0_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_1_0_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_1_0_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_1_0_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_1_0_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_1_0_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_1_1_STATUS__FREQ_LOCK_MASK 0x00040000L
+#define MPLL_DQ_1_1_STATUS__FREQ_LOCK__SHIFT 0x00000012
+#define MPLL_DQ_1_1_STATUS__FREQ_UNLOCK_STICKY_MASK 0x00080000L
+#define MPLL_DQ_1_1_STATUS__FREQ_UNLOCK_STICKY__SHIFT 0x00000013
+#define MPLL_DQ_1_1_STATUS__OINT_RESET_MASK 0x00020000L
+#define MPLL_DQ_1_1_STATUS__OINT_RESET__SHIFT 0x00000011
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_FRAC_MASK 0x00000070L
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_FRAC__SHIFT 0x00000004
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_INT_MASK 0x0001ff80L
+#define MPLL_DQ_1_1_STATUS__TEST_FBDIV_INT__SHIFT 0x00000007
+#define MPLL_DQ_1_1_STATUS__VCTRLADC_MASK 0x00000007L
+#define MPLL_DQ_1_1_STATUS__VCTRLADC__SHIFT 0x00000000
+#define MPLL_DQ_FUNC_CNTL__SPARE_0_MASK 0x00000008L
+#define MPLL_DQ_FUNC_CNTL__SPARE_0__SHIFT 0x00000003
+#define MPLL_DQ_FUNC_CNTL__SPARE_MASK 0xffffffe0L
+#define MPLL_DQ_FUNC_CNTL__SPARE__SHIFT 0x00000005
+#define MPLL_DQ_FUNC_CNTL__YCLK_POST_DIV_MASK 0x00000007L
+#define MPLL_DQ_FUNC_CNTL__YCLK_POST_DIV__SHIFT 0x00000000
+#define MPLL_DQ_FUNC_CNTL__YCLK_SEL_MASK 0x00000010L
+#define MPLL_DQ_FUNC_CNTL__YCLK_SEL__SHIFT 0x00000004
+#define MPLL_FUNC_CNTL_1__CLKF_MASK 0x0fff0000L
+#define MPLL_FUNC_CNTL_1__CLKFRAC_MASK 0x0000fff0L
+#define MPLL_FUNC_CNTL_1__CLKFRAC__SHIFT 0x00000004
+#define MPLL_FUNC_CNTL_1__CLKF__SHIFT 0x00000010
+#define MPLL_FUNC_CNTL_1__SPARE_0_MASK 0x0000000cL
+#define MPLL_FUNC_CNTL_1__SPARE_0__SHIFT 0x00000002
+#define MPLL_FUNC_CNTL_1__SPARE_1_MASK 0xf0000000L
+#define MPLL_FUNC_CNTL_1__SPARE_1__SHIFT 0x0000001c
+#define MPLL_FUNC_CNTL_1__VCO_MODE_MASK 0x00000003L
+#define MPLL_FUNC_CNTL_1__VCO_MODE__SHIFT 0x00000000
+#define MPLL_FUNC_CNTL_2__BACKUP_2_MASK 0x000e0000L
+#define MPLL_FUNC_CNTL_2__BACKUP_2__SHIFT 0x00000011
+#define MPLL_FUNC_CNTL_2__BACKUP_MASK 0xf8000000L
+#define MPLL_FUNC_CNTL_2__BACKUP__SHIFT 0x0000001b
+#define MPLL_FUNC_CNTL_2__LF_CNTRL_MASK 0x07f00000L
+#define MPLL_FUNC_CNTL_2__LF_CNTRL__SHIFT 0x00000014
+#define MPLL_FUNC_CNTL_2__MPLL_UNLOCK_CLEAR_MASK 0x00000080L
+#define MPLL_FUNC_CNTL_2__MPLL_UNLOCK_CLEAR__SHIFT 0x00000007
+#define MPLL_FUNC_CNTL_2__PFD_RESET_CNTRL_MASK 0x00003000L
+#define MPLL_FUNC_CNTL_2__PFD_RESET_CNTRL__SHIFT 0x0000000c
+#define MPLL_FUNC_CNTL_2__RESET_EN_MASK 0x00000004L
+#define MPLL_FUNC_CNTL_2__RESET_EN__SHIFT 0x00000002
+#define MPLL_FUNC_CNTL_2__RESET_TIMER_MASK 0x00000c00L
+#define MPLL_FUNC_CNTL_2__RESET_TIMER__SHIFT 0x0000000a
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_EN_MASK 0x00000008L
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_EN__SHIFT 0x00000003
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_SRC_MASK 0x00000010L
+#define MPLL_FUNC_CNTL_2__TEST_BYPCLK_SRC__SHIFT 0x00000004
+#define MPLL_FUNC_CNTL_2__TEST_BYPMCLK_MASK 0x00000040L
+#define MPLL_FUNC_CNTL_2__TEST_BYPMCLK__SHIFT 0x00000006
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_FRAC_BYPASS_MASK 0x00000020L
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_FRAC_BYPASS__SHIFT 0x00000005
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_SSC_BYPASS_MASK 0x00000200L
+#define MPLL_FUNC_CNTL_2__TEST_FBDIV_SSC_BYPASS__SHIFT 0x00000009
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_CNTRL_MASK 0x00000100L
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_CNTRL__SHIFT 0x00000008
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_EN_MASK 0x00000002L
+#define MPLL_FUNC_CNTL_2__TEST_VCTL_EN__SHIFT 0x00000001
+#define MPLL_FUNC_CNTL_2__VCTRLADC_EN_MASK 0x00000001L
+#define MPLL_FUNC_CNTL_2__VCTRLADC_EN__SHIFT 0x00000000
+#define MPLL_FUNC_CNTL__BG_100ADJ_MASK 0x00000f00L
+#define MPLL_FUNC_CNTL__BG_100ADJ__SHIFT 0x00000008
+#define MPLL_FUNC_CNTL__BG_135ADJ_MASK 0x000f0000L
+#define MPLL_FUNC_CNTL__BG_135ADJ__SHIFT 0x00000010
+#define MPLL_FUNC_CNTL__BWCTRL_MASK 0x0ff00000L
+#define MPLL_FUNC_CNTL__BWCTRL__SHIFT 0x00000014
+#define MPLL_FUNC_CNTL__REG_BIAS_MASK 0xc0000000L
+#define MPLL_FUNC_CNTL__REG_BIAS__SHIFT 0x0000001e
+#define MPLL_FUNC_CNTL__SPARE_0_MASK 0x00000020L
+#define MPLL_FUNC_CNTL__SPARE_0__SHIFT 0x00000005
+#define MPLL_SEQ_UCODE_1__INSTR0_MASK 0x0000000fL
+#define MPLL_SEQ_UCODE_1__INSTR0__SHIFT 0x00000000
+#define MPLL_SEQ_UCODE_1__INSTR1_MASK 0x000000f0L
+#define MPLL_SEQ_UCODE_1__INSTR1__SHIFT 0x00000004
+#define MPLL_SEQ_UCODE_1__INSTR2_MASK 0x00000f00L
+#define MPLL_SEQ_UCODE_1__INSTR2__SHIFT 0x00000008
+#define MPLL_SEQ_UCODE_1__INSTR3_MASK 0x0000f000L
+#define MPLL_SEQ_UCODE_1__INSTR3__SHIFT 0x0000000c
+#define MPLL_SEQ_UCODE_1__INSTR4_MASK 0x000f0000L
+#define MPLL_SEQ_UCODE_1__INSTR4__SHIFT 0x00000010
+#define MPLL_SEQ_UCODE_1__INSTR5_MASK 0x00f00000L
+#define MPLL_SEQ_UCODE_1__INSTR5__SHIFT 0x00000014
+#define MPLL_SEQ_UCODE_1__INSTR6_MASK 0x0f000000L
+#define MPLL_SEQ_UCODE_1__INSTR6__SHIFT 0x00000018
+#define MPLL_SEQ_UCODE_1__INSTR7_MASK 0xf0000000L
+#define MPLL_SEQ_UCODE_1__INSTR7__SHIFT 0x0000001c
+#define MPLL_SEQ_UCODE_2__INSTR10_MASK 0x00000f00L
+#define MPLL_SEQ_UCODE_2__INSTR10__SHIFT 0x00000008
+#define MPLL_SEQ_UCODE_2__INSTR11_MASK 0x0000f000L
+#define MPLL_SEQ_UCODE_2__INSTR11__SHIFT 0x0000000c
+#define MPLL_SEQ_UCODE_2__INSTR12_MASK 0x000f0000L
+#define MPLL_SEQ_UCODE_2__INSTR12__SHIFT 0x00000010
+#define MPLL_SEQ_UCODE_2__INSTR13_MASK 0x00f00000L
+#define MPLL_SEQ_UCODE_2__INSTR13__SHIFT 0x00000014
+#define MPLL_SEQ_UCODE_2__INSTR14_MASK 0x0f000000L
+#define MPLL_SEQ_UCODE_2__INSTR14__SHIFT 0x00000018
+#define MPLL_SEQ_UCODE_2__INSTR15_MASK 0xf0000000L
+#define MPLL_SEQ_UCODE_2__INSTR15__SHIFT 0x0000001c
+#define MPLL_SEQ_UCODE_2__INSTR8_MASK 0x0000000fL
+#define MPLL_SEQ_UCODE_2__INSTR8__SHIFT 0x00000000
+#define MPLL_SEQ_UCODE_2__INSTR9_MASK 0x000000f0L
+#define MPLL_SEQ_UCODE_2__INSTR9__SHIFT 0x00000004
+#define MPLL_SS1__CLKV_MASK 0x03ffffffL
+#define MPLL_SS1__CLKV__SHIFT 0x00000000
+#define MPLL_SS1__SPARE_MASK 0xfc000000L
+#define MPLL_SS1__SPARE__SHIFT 0x0000001a
+#define MPLL_SS2__CLKS_MASK 0x00000fffL
+#define MPLL_SS2__CLKS__SHIFT 0x00000000
+#define MPLL_SS2__SPARE_MASK 0xfffff000L
+#define MPLL_SS2__SPARE__SHIFT 0x0000000c
+#define MPLL_TIME__MPLL_LOCK_TIME_MASK 0x0000ffffL
+#define MPLL_TIME__MPLL_LOCK_TIME__SHIFT 0x00000000
+#define MPLL_TIME__MPLL_RESET_TIME_MASK 0xffff0000L
+#define MPLL_TIME__MPLL_RESET_TIME__SHIFT 0x00000010
+#define VM_CONTEXT0_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES_MASK 0x00000008L
+#define VM_CONTEXT0_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES__SHIFT 0x00000003
+#define VM_CONTEXT0_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR_MASK 0x00000001L
+#define VM_CONTEXT0_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT0_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT_MASK 0x00000002L
+#define VM_CONTEXT0_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT__SHIFT 0x00000001
+#define VM_CONTEXT0_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT_MASK 0x00000004L
+#define VM_CONTEXT0_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT__SHIFT 0x00000002
+#define VM_CONTEXT0_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE_MASK 0x00000010L
+#define VM_CONTEXT0_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE__SHIFT 0x00000004
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000080L
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000007
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000040L
+#define VM_CONTEXT0_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000006
+#define VM_CONTEXT0_CNTL__ENABLE_CONTEXT_MASK 0x00000001L
+#define VM_CONTEXT0_CNTL__ENABLE_CONTEXT__SHIFT 0x00000000
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_BLOCK_SIZE_MASK 0x0f000000L
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT 0x00000018
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_DEPTH_MASK 0x00000006L
+#define VM_CONTEXT0_CNTL__PAGE_TABLE_DEPTH__SHIFT 0x00000001
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000400L
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000a
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000200L
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000009
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00000800L
+#define VM_CONTEXT0_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000b
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00400000L
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000016
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00200000L
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000015
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00800000L
+#define VM_CONTEXT0_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000017
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000010L
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000004
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000008L
+#define VM_CONTEXT0_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000003
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00010000L
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000010
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00008000L
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000f
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00020000L
+#define VM_CONTEXT0_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000011
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00002000L
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000d
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00001000L
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000c
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00004000L
+#define VM_CONTEXT0_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000e
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00080000L
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000013
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00040000L
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000012
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00100000L
+#define VM_CONTEXT0_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000014
+#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT0_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT0_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT0_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT0_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT0_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT0_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID_MASK 0x000ff000L
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID__SHIFT 0x0000000c
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW_MASK 0x01000000L
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW__SHIFT 0x00000018
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__PROTECTIONS_MASK 0x000000ffL
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__PROTECTIONS__SHIFT 0x00000000
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__VMID_MASK 0x1e000000L
+#define VM_CONTEXT0_PROTECTION_FAULT_STATUS__VMID__SHIFT 0x00000019
+#define VM_CONTEXT10_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT10_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT11_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT11_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT12_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT12_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT13_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT13_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT14_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT15_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES_MASK 0x00000008L
+#define VM_CONTEXT1_CNTL2__ALLOW_SUBSEQUENT_PROTECTION_FAULT_STATUS_ADDR_UPDATES__SHIFT 0x00000003
+#define VM_CONTEXT1_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR_MASK 0x00000001L
+#define VM_CONTEXT1_CNTL2__CLEAR_PROTECTION_FAULT_STATUS_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT1_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT_MASK 0x00000002L
+#define VM_CONTEXT1_CNTL2__ENABLE_CLEAR_PROTECTION_FAULT_STATUS_ADDR_WHEN_INVALIDATE_CONTEXT__SHIFT 0x00000001
+#define VM_CONTEXT1_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT_MASK 0x00000004L
+#define VM_CONTEXT1_CNTL2__ENABLE_INTERRUPT_PROCESSING_FOR_SUBSEQUENT_FAULTS_PER_CONTEXT__SHIFT 0x00000002
+#define VM_CONTEXT1_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE_MASK 0x00000010L
+#define VM_CONTEXT1_CNTL2__WAIT_FOR_IDLE_WHEN_INVALIDATE__SHIFT 0x00000004
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000080L
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000007
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000040L
+#define VM_CONTEXT1_CNTL__DUMMY_PAGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000006
+#define VM_CONTEXT1_CNTL__ENABLE_CONTEXT_MASK 0x00000001L
+#define VM_CONTEXT1_CNTL__ENABLE_CONTEXT__SHIFT 0x00000000
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE_MASK 0x0f000000L
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_BLOCK_SIZE__SHIFT 0x00000018
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_DEPTH_MASK 0x00000006L
+#define VM_CONTEXT1_CNTL__PAGE_TABLE_DEPTH__SHIFT 0x00000001
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000400L
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000a
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000200L
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000009
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00000800L
+#define VM_CONTEXT1_CNTL__PDE0_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000b
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00400000L
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000016
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00200000L
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000015
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00800000L
+#define VM_CONTEXT1_CNTL__PRIVILEGED_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000017
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00000010L
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000004
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00000008L
+#define VM_CONTEXT1_CNTL__RANGE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000003
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00010000L
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000010
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00008000L
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000f
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00020000L
+#define VM_CONTEXT1_CNTL__READ_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000011
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00002000L
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x0000000d
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00001000L
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x0000000c
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00004000L
+#define VM_CONTEXT1_CNTL__VALID_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x0000000e
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT_MASK 0x00080000L
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_DEFAULT__SHIFT 0x00000013
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT_MASK 0x00040000L
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_INTERRUPT__SHIFT 0x00000012
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE_MASK 0x00100000L
+#define VM_CONTEXT1_CNTL__WRITE_PROTECTION_FAULT_ENABLE_SAVE__SHIFT 0x00000014
+#define VM_CONTEXT1_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT1_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT1_PAGE_TABLE_END_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT1_PAGE_TABLE_START_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT1_PROTECTION_FAULT_ADDR__LOGICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR__PHYSICAL_PAGE_ADDR__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID_MASK 0x000ff000L
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_ID__SHIFT 0x0000000c
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW_MASK 0x01000000L
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__MEMORY_CLIENT_RW__SHIFT 0x00000018
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__PROTECTIONS_MASK 0x000000ffL
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__PROTECTIONS__SHIFT 0x00000000
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__VMID_MASK 0x1e000000L
+#define VM_CONTEXT1_PROTECTION_FAULT_STATUS__VMID__SHIFT 0x00000019
+#define VM_CONTEXT2_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT2_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT3_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT3_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT4_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT4_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT5_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT5_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT6_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT6_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT7_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT7_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT8_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT8_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXT9_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_CONTEXT9_PAGE_TABLE_BASE_ADDR__PHYSICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_0_MASK 0x00000001L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_0__SHIFT 0x00000000
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_10_MASK 0x00000400L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_10__SHIFT 0x0000000a
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_11_MASK 0x00000800L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_11__SHIFT 0x0000000b
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_12_MASK 0x00001000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_12__SHIFT 0x0000000c
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_13_MASK 0x00002000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_13__SHIFT 0x0000000d
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_14_MASK 0x00004000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_14__SHIFT 0x0000000e
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_15_MASK 0x00008000L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_15__SHIFT 0x0000000f
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_1_MASK 0x00000002L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_1__SHIFT 0x00000001
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_2_MASK 0x00000004L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_2__SHIFT 0x00000002
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_3_MASK 0x00000008L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_3__SHIFT 0x00000003
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_4_MASK 0x00000010L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_4__SHIFT 0x00000004
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_5_MASK 0x00000020L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_5__SHIFT 0x00000005
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_6_MASK 0x00000040L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_6__SHIFT 0x00000006
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_7_MASK 0x00000080L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_7__SHIFT 0x00000007
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_8_MASK 0x00000100L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_8__SHIFT 0x00000008
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_9_MASK 0x00000200L
+#define VM_CONTEXTS_DISABLE__DISABLE_CONTEXT_9__SHIFT 0x00000009
+#define VM_DEBUG__FLAGS_MASK 0xffffffffL
+#define VM_DEBUG__FLAGS__SHIFT 0x00000000
+#define VM_DUMMY_PAGE_FAULT_ADDR__DUMMY_PAGE_ADDR_MASK 0x0fffffffL
+#define VM_DUMMY_PAGE_FAULT_ADDR__DUMMY_PAGE_ADDR__SHIFT 0x00000000
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_ADDRESS_LOGICAL_MASK 0x00000002L
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_ADDRESS_LOGICAL__SHIFT 0x00000001
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_COMPARE_MASK_MASK 0x0000000cL
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_COMPARE_MASK__SHIFT 0x00000002
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_FAULT_ENABLE_MASK 0x00000001L
+#define VM_DUMMY_PAGE_FAULT_CNTL__DUMMY_PAGE_FAULT_ENABLE__SHIFT 0x00000000
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT_MASK 0x000001ffL
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT_MASK_MASK 0x0003fe00L
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT_MASK__SHIFT 0x00000009
+#define VM_FAULT_CLIENT_ID__MEMORY_CLIENT__SHIFT 0x00000000
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_0_MASK 0x00000001L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_0__SHIFT 0x00000000
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_10_MASK 0x00000400L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_10__SHIFT 0x0000000a
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_11_MASK 0x00000800L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_11__SHIFT 0x0000000b
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_12_MASK 0x00001000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_12__SHIFT 0x0000000c
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_13_MASK 0x00002000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_13__SHIFT 0x0000000d
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_14_MASK 0x00004000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_14__SHIFT 0x0000000e
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_15_MASK 0x00008000L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_15__SHIFT 0x0000000f
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_1_MASK 0x00000002L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_1__SHIFT 0x00000001
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_2_MASK 0x00000004L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_2__SHIFT 0x00000002
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_3_MASK 0x00000008L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_3__SHIFT 0x00000003
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_4_MASK 0x00000010L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_4__SHIFT 0x00000004
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_5_MASK 0x00000020L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_5__SHIFT 0x00000005
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_6_MASK 0x00000040L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_6__SHIFT 0x00000006
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_7_MASK 0x00000080L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_7__SHIFT 0x00000007
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_8_MASK 0x00000100L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_8__SHIFT 0x00000008
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_9_MASK 0x00000200L
+#define VM_INVALIDATE_REQUEST__INVALIDATE_DOMAIN_9__SHIFT 0x00000009
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_0_MASK 0x00000001L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_0__SHIFT 0x00000000
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_10_MASK 0x00000400L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_10__SHIFT 0x0000000a
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_11_MASK 0x00000800L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_11__SHIFT 0x0000000b
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_12_MASK 0x00001000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_12__SHIFT 0x0000000c
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_13_MASK 0x00002000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_13__SHIFT 0x0000000d
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_14_MASK 0x00004000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_14__SHIFT 0x0000000e
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_15_MASK 0x00008000L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_15__SHIFT 0x0000000f
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_1_MASK 0x00000002L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_1__SHIFT 0x00000001
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_2_MASK 0x00000004L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_2__SHIFT 0x00000002
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_3_MASK 0x00000008L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_3__SHIFT 0x00000003
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_4_MASK 0x00000010L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_4__SHIFT 0x00000004
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_5_MASK 0x00000020L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_5__SHIFT 0x00000005
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_6_MASK 0x00000040L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_6__SHIFT 0x00000006
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_7_MASK 0x00000080L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_7__SHIFT 0x00000007
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_8_MASK 0x00000100L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_8__SHIFT 0x00000008
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_9_MASK 0x00000200L
+#define VM_INVALIDATE_RESPONSE__DOMAIN_INVALIDATED_9__SHIFT 0x00000009
+#define VM_L2_BANK_SELECT_MASKA__BANK_SELECT_MASK_MASK 0x0fffffffL
+#define VM_L2_BANK_SELECT_MASKA__BANK_SELECT_MASK__SHIFT 0x00000000
+#define VM_L2_BANK_SELECT_MASKB__BANK_SELECT_MASK_MASK 0x000000ffL
+#define VM_L2_BANK_SELECT_MASKB__BANK_SELECT_MASK__SHIFT 0x00000000
+#define VM_L2_CG__ENABLE_MASK 0x00040000L
+#define VM_L2_CG__ENABLE__SHIFT 0x00000012
+#define VM_L2_CG__MEM_LS_ENABLE_MASK 0x00080000L
+#define VM_L2_CG__MEM_LS_ENABLE__SHIFT 0x00000013
+#define VM_L2_CG__OFFDLY_MASK 0x00000fc0L
+#define VM_L2_CG__OFFDLY__SHIFT 0x00000006
+#define VM_L2_CNTL2__DISABLE_BIGK_CACHE_OPTIMIZATION_MASK 0x00400000L
+#define VM_L2_CNTL2__DISABLE_BIGK_CACHE_OPTIMIZATION__SHIFT 0x00000016
+#define VM_L2_CNTL2__DISABLE_INVALIDATE_PER_DOMAIN_MASK 0x00200000L
+#define VM_L2_CNTL2__DISABLE_INVALIDATE_PER_DOMAIN__SHIFT 0x00000015
+#define VM_L2_CNTL2__INVALIDATE_ALL_L1_TLBS_MASK 0x00000001L
+#define VM_L2_CNTL2__INVALIDATE_ALL_L1_TLBS__SHIFT 0x00000000
+#define VM_L2_CNTL2__INVALIDATE_CACHE_MODE_MASK 0x0c000000L
+#define VM_L2_CNTL2__INVALIDATE_CACHE_MODE__SHIFT 0x0000001a
+#define VM_L2_CNTL2__INVALIDATE_L2_CACHE_MASK 0x00000002L
+#define VM_L2_CNTL2__INVALIDATE_L2_CACHE__SHIFT 0x00000001
+#define VM_L2_CNTL2__L2_CACHE_BIGK_VMID_MODE_MASK 0x03800000L
+#define VM_L2_CNTL2__L2_CACHE_BIGK_VMID_MODE__SHIFT 0x00000017
+#define VM_L2_CNTL3__BANK_SELECT_MASK 0x0000003fL
+#define VM_L2_CNTL3__BANK_SELECT__SHIFT 0x00000000
+#define VM_L2_CNTL3__L2_CACHE_4K_EFFECTIVE_SIZE_MASK 0x00e00000L
+#define VM_L2_CNTL3__L2_CACHE_4K_EFFECTIVE_SIZE__SHIFT 0x00000015
+#define VM_L2_CNTL3__L2_CACHE_4K_FORCE_MISS_MASK 0x10000000L
+#define VM_L2_CNTL3__L2_CACHE_4K_FORCE_MISS__SHIFT 0x0000001c
+#define VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY_MASK 0x00100000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_ASSOCIATIVITY__SHIFT 0x00000014
+#define VM_L2_CNTL3__L2_CACHE_BIGK_EFFECTIVE_SIZE_MASK 0x0f000000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_EFFECTIVE_SIZE__SHIFT 0x00000018
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FORCE_MISS_MASK 0x20000000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FORCE_MISS__SHIFT 0x0000001d
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE_MASK 0x000f8000L
+#define VM_L2_CNTL3__L2_CACHE_BIGK_FRAGMENT_SIZE__SHIFT 0x0000000f
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_MODE_MASK 0x000000c0L
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_MODE__SHIFT 0x00000006
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_WILDCARD_REFERENCE_VALUE_MASK 0x00001f00L
+#define VM_L2_CNTL3__L2_CACHE_UPDATE_WILDCARD_REFERENCE_VALUE__SHIFT 0x00000008
+#define VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE_MASK 0x00180000L
+#define VM_L2_CNTL__CONTEXT1_IDENTITY_ACCESS_MODE__SHIFT 0x00000013
+#define VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE_MASK 0x00038000L
+#define VM_L2_CNTL__EFFECTIVE_L2_QUEUE_SIZE__SHIFT 0x0000000f
+#define VM_L2_CNTL__ENABLE_L2_CACHE_MASK 0x00000001L
+#define VM_L2_CNTL__ENABLE_L2_CACHE__SHIFT 0x00000000
+#define VM_L2_CNTL__ENABLE_L2_FRAGMENT_PROCESSING_MASK 0x00000002L
+#define VM_L2_CNTL__ENABLE_L2_FRAGMENT_PROCESSING__SHIFT 0x00000001
+#define VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE_MASK 0x00000400L
+#define VM_L2_CNTL__ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE__SHIFT 0x0000000a
+#define VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE_MASK 0x00000200L
+#define VM_L2_CNTL__ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE__SHIFT 0x00000009
+#define VM_L2_CNTL__IDENTITY_MODE_FRAGMENT_SIZE_MASK 0x03e00000L
+#define VM_L2_CNTL__IDENTITY_MODE_FRAGMENT_SIZE__SHIFT 0x00000015
+#define VM_L2_CNTL__L2_CACHE_4K_SWAP_TAG_INDEX_LSBS_MASK 0x0c000000L
+#define VM_L2_CNTL__L2_CACHE_4K_SWAP_TAG_INDEX_LSBS__SHIFT 0x0000001a
+#define VM_L2_CNTL__L2_CACHE_BIGK_SWAP_TAG_INDEX_LSBS_MASK 0x70000000L
+#define VM_L2_CNTL__L2_CACHE_BIGK_SWAP_TAG_INDEX_LSBS__SHIFT 0x0000001c
+#define VM_L2_CNTL__L2_CACHE_PDE_ENDIAN_SWAP_MODE_MASK 0x00000030L
+#define VM_L2_CNTL__L2_CACHE_PDE_ENDIAN_SWAP_MODE__SHIFT 0x00000004
+#define VM_L2_CNTL__L2_CACHE_PTE_ENDIAN_SWAP_MODE_MASK 0x0000000cL
+#define VM_L2_CNTL__L2_CACHE_PTE_ENDIAN_SWAP_MODE__SHIFT 0x00000002
+#define VM_L2_CNTL__L2_PDE0_CACHE_SPLIT_MODE_MASK 0x00007000L
+#define VM_L2_CNTL__L2_PDE0_CACHE_SPLIT_MODE__SHIFT 0x0000000c
+#define VM_L2_CNTL__L2_PDE0_CACHE_TAG_GENERATION_MODE_MASK 0x00000100L
+#define VM_L2_CNTL__L2_PDE0_CACHE_TAG_GENERATION_MODE__SHIFT 0x00000008
+#define VM_L2_CNTL__PDE_FAULT_CLASSIFICATION_MASK 0x00040000L
+#define VM_L2_CNTL__PDE_FAULT_CLASSIFICATION__SHIFT 0x00000012
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET__PHYSICAL_PAGE_OFFSET_MASK 0x0fffffffL
+#define VM_L2_CONTEXT_IDENTITY_PHYSICAL_OFFSET__PHYSICAL_PAGE_OFFSET__SHIFT 0x00000000
+#define VM_L2_STATUS__CONTEXT_DOMAIN_BUSY_MASK 0x0001fffeL
+#define VM_L2_STATUS__CONTEXT_DOMAIN_BUSY__SHIFT 0x00000001
+#define VM_L2_STATUS__L2_BUSY_MASK 0x00000001L
+#define VM_L2_STATUS__L2_BUSY__SHIFT 0x00000000
+#define VM_PRT_APERTURE0_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE0_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE0_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE0_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE1_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE1_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE1_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE1_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE2_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE2_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE2_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE2_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE3_HIGH_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE3_HIGH_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_APERTURE3_LOW_ADDR__LOGICAL_PAGE_NUMBER_MASK 0x0fffffffL
+#define VM_PRT_APERTURE3_LOW_ADDR__LOGICAL_PAGE_NUMBER__SHIFT 0x00000000
+#define VM_PRT_CNTL__L1_TLB_STORE_INVALID_ENTRIES_MASK 0x00000008L
+#define VM_PRT_CNTL__L1_TLB_STORE_INVALID_ENTRIES__SHIFT 0x00000003
+#define VM_PRT_CNTL__L2_CACHE_STORE_INVALID_ENTRIES_MASK 0x00000004L
+#define VM_PRT_CNTL__L2_CACHE_STORE_INVALID_ENTRIES__SHIFT 0x00000002
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,275 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 OSS_1_0_D_H
+#define OSS_1_0_D_H
+
+#define ixCLIENT0_BM 0x0220
+#define ixCLIENT0_CD0 0x0210
+#define ixCLIENT0_CD1 0x0214
+#define ixCLIENT0_CD2 0x0218
+#define ixCLIENT0_CD3 0x021C
+#define ixCLIENT0_CK0 0x0200
+#define ixCLIENT0_CK1 0x0204
+#define ixCLIENT0_CK2 0x0208
+#define ixCLIENT0_CK3 0x020C
+#define ixCLIENT0_K0 0x01F0
+#define ixCLIENT0_K1 0x01F4
+#define ixCLIENT0_K2 0x01F8
+#define ixCLIENT0_K3 0x01FC
+#define ixCLIENT0_OFFSET 0x0224
+#define ixCLIENT0_OFFSET_HI 0x0290
+#define ixCLIENT0_STATUS 0x0228
+#define ixCLIENT1_BM 0x025C
+#define ixCLIENT1_CD0 0x024C
+#define ixCLIENT1_CD1 0x0250
+#define ixCLIENT1_CD2 0x0254
+#define ixCLIENT1_CD3 0x0258
+#define ixCLIENT1_CK0 0x023C
+#define ixCLIENT1_CK1 0x0240
+#define ixCLIENT1_CK2 0x0244
+#define ixCLIENT1_CK3 0x0248
+#define ixCLIENT1_K0 0x022C
+#define ixCLIENT1_K1 0x0230
+#define ixCLIENT1_K2 0x0234
+#define ixCLIENT1_K3 0x0238
+#define ixCLIENT1_OFFSET 0x0260
+#define ixCLIENT1_OFFSET_HI 0x0294
+#define ixCLIENT1_PORT_STATUS 0x0264
+#define ixCLIENT2_BM 0x01E4
+#define ixCLIENT2_CD0 0x01D4
+#define ixCLIENT2_CD1 0x01D8
+#define ixCLIENT2_CD2 0x01DC
+#define ixCLIENT2_CD3 0x01E0
+#define ixCLIENT2_CK0 0x01C4
+#define ixCLIENT2_CK1 0x01C8
+#define ixCLIENT2_CK2 0x01CC
+#define ixCLIENT2_CK3 0x01D0
+#define ixCLIENT2_K0 0x01B4
+#define ixCLIENT2_K1 0x01B8
+#define ixCLIENT2_K2 0x01BC
+#define ixCLIENT2_K3 0x01C0
+#define ixCLIENT2_OFFSET 0x01E8
+#define ixCLIENT2_OFFSET_HI 0x0298
+#define ixCLIENT2_STATUS 0x01EC
+#define ixCLIENT3_BM 0x02D4
+#define ixCLIENT3_CD0 0x02C4
+#define ixCLIENT3_CD1 0x02C8
+#define ixCLIENT3_CD2 0x02CC
+#define ixCLIENT3_CD3 0x02D0
+#define ixCLIENT3_CK0 0x02B4
+#define ixCLIENT3_CK1 0x02B8
+#define ixCLIENT3_CK2 0x02BC
+#define ixCLIENT3_CK3 0x02C0
+#define ixCLIENT3_K0 0x02A4
+#define ixCLIENT3_K1 0x02A8
+#define ixCLIENT3_K2 0x02AC
+#define ixCLIENT3_K3 0x02B0
+#define ixCLIENT3_OFFSET 0x02D8
+#define ixCLIENT3_OFFSET_HI 0x02A0
+#define ixCLIENT3_STATUS 0x02DC
+#define ixDH_TEST 0x0000
+#define ixEXP0 0x0034
+#define ixEXP1 0x0038
+#define ixEXP2 0x003C
+#define ixEXP3 0x0040
+#define ixEXP4 0x0044
+#define ixEXP5 0x0048
+#define ixEXP6 0x004C
+#define ixEXP7 0x0050
+#define ixHFS_SEED0 0x0278
+#define ixHFS_SEED1 0x027C
+#define ixHFS_SEED2 0x0280
+#define ixHFS_SEED3 0x0284
+#define ixKEFUSE0 0x0268
+#define ixKEFUSE1 0x026C
+#define ixKEFUSE2 0x0270
+#define ixKEFUSE3 0x0274
+#define ixKHFS0 0x0004
+#define ixKHFS1 0x0008
+#define ixKHFS2 0x000C
+#define ixKHFS3 0x0010
+#define ixKSESSION0 0x0014
+#define ixKSESSION1 0x0018
+#define ixKSESSION2 0x001C
+#define ixKSESSION3 0x0020
+#define ixKSIG0 0x0024
+#define ixKSIG1 0x0028
+#define ixKSIG2 0x002C
+#define ixKSIG3 0x0030
+#define ixLX0 0x0054
+#define ixLX1 0x0058
+#define ixLX2 0x005C
+#define ixLX3 0x0060
+#define ixRINGOSC_MASK 0x0288
+#define ixSPU_PORT_STATUS 0x029C
+#define mmCC_DRM_ID_STRAPS 0x1559
+#define mmCC_SYS_RB_BACKEND_DISABLE 0x03A0
+#define mmCC_SYS_RB_REDUNDANCY 0x039F
+#define mmCGTT_DRM_CLK_CTRL0 0x1579
+#define mmCP_CONFIG 0x0F92
+#define mmDC_TEST_DEBUG_DATA 0x157D
+#define mmDC_TEST_DEBUG_INDEX 0x157C
+#define mmGC_USER_SYS_RB_BACKEND_DISABLE 0x03A1
+#define mmHDP_ADDR_CONFIG 0x0BD2
+#define mmHDP_DEBUG0 0x0BCC
+#define mmHDP_DEBUG1 0x0BCD
+#define mmHDP_HOST_PATH_CNTL 0x0B00
+#define mmHDP_LAST_SURFACE_HIT 0x0BCE
+#define mmHDP_MEMIO_ADDR 0x0BF7
+#define mmHDP_MEMIO_CNTL 0x0BF6
+#define mmHDP_MEMIO_RD_DATA 0x0BFA
+#define mmHDP_MEMIO_STATUS 0x0BF8
+#define mmHDP_MEMIO_WR_DATA 0x0BF9
+#define mmHDP_MEM_POWER_LS 0x0BD4
+#define mmHDP_MISC_CNTL 0x0BD3
+#define mmHDP_NONSURFACE_BASE 0x0B01
+#define mmHDP_NONSURFACE_INFO 0x0B02
+#define mmHDP_NONSURFACE_PREFETCH 0x0BD5
+#define mmHDP_NONSURFACE_SIZE 0x0B03
+#define mmHDP_NONSURF_FLAGS 0x0BC9
+#define mmHDP_NONSURF_FLAGS_CLR 0x0BCA
+#define mmHDP_OUTSTANDING_REQ 0x0BD1
+#define mmHDP_SC_MULTI_CHIP_CNTL 0x0BD0
+#define mmHDP_SW_SEMAPHORE 0x0BCB
+#define mmHDP_TILING_CONFIG 0x0BCF
+#define mmHDP_XDP_BARS_ADDR_39_36 0x0C44
+#define mmHDP_XDP_BUSY_STS 0x0C3E
+#define mmHDP_XDP_CGTT_BLK_CTRL 0x0C33
+#define mmHDP_XDP_CHKN 0x0C40
+#define mmHDP_XDP_D2H_BAR_UPDATE 0x0C02
+#define mmHDP_XDP_D2H_FLUSH 0x0C01
+#define mmHDP_XDP_D2H_RSVD_10 0x0C0A
+#define mmHDP_XDP_D2H_RSVD_11 0x0C0B
+#define mmHDP_XDP_D2H_RSVD_12 0x0C0C
+#define mmHDP_XDP_D2H_RSVD_13 0x0C0D
+#define mmHDP_XDP_D2H_RSVD_14 0x0C0E
+#define mmHDP_XDP_D2H_RSVD_15 0x0C0F
+#define mmHDP_XDP_D2H_RSVD_16 0x0C10
+#define mmHDP_XDP_D2H_RSVD_17 0x0C11
+#define mmHDP_XDP_D2H_RSVD_18 0x0C12
+#define mmHDP_XDP_D2H_RSVD_19 0x0C13
+#define mmHDP_XDP_D2H_RSVD_20 0x0C14
+#define mmHDP_XDP_D2H_RSVD_21 0x0C15
+#define mmHDP_XDP_D2H_RSVD_22 0x0C16
+#define mmHDP_XDP_D2H_RSVD_23 0x0C17
+#define mmHDP_XDP_D2H_RSVD_24 0x0C18
+#define mmHDP_XDP_D2H_RSVD_25 0x0C19
+#define mmHDP_XDP_D2H_RSVD_26 0x0C1A
+#define mmHDP_XDP_D2H_RSVD_27 0x0C1B
+#define mmHDP_XDP_D2H_RSVD_28 0x0C1C
+#define mmHDP_XDP_D2H_RSVD_29 0x0C1D
+#define mmHDP_XDP_D2H_RSVD_30 0x0C1E
+#define mmHDP_XDP_D2H_RSVD_3 0x0C03
+#define mmHDP_XDP_D2H_RSVD_31 0x0C1F
+#define mmHDP_XDP_D2H_RSVD_32 0x0C20
+#define mmHDP_XDP_D2H_RSVD_33 0x0C21
+#define mmHDP_XDP_D2H_RSVD_34 0x0C22
+#define mmHDP_XDP_D2H_RSVD_4 0x0C04
+#define mmHDP_XDP_D2H_RSVD_5 0x0C05
+#define mmHDP_XDP_D2H_RSVD_6 0x0C06
+#define mmHDP_XDP_D2H_RSVD_7 0x0C07
+#define mmHDP_XDP_D2H_RSVD_8 0x0C08
+#define mmHDP_XDP_D2H_RSVD_9 0x0C09
+#define mmHDP_XDP_DBG_ADDR 0x0C41
+#define mmHDP_XDP_DBG_DATA 0x0C42
+#define mmHDP_XDP_DBG_MASK 0x0C43
+#define mmHDP_XDP_DIRECT2HDP_FIRST 0x0C00
+#define mmHDP_XDP_DIRECT2HDP_LAST 0x0C23
+#define mmHDP_XDP_FLUSH_ARMED_STS 0x0C3C
+#define mmHDP_XDP_FLUSH_CNTR0_STS 0x0C3D
+#define mmHDP_XDP_HDP_IPH_CFG 0x0C31
+#define mmHDP_XDP_HDP_MBX_MC_CFG 0x0C2D
+#define mmHDP_XDP_HDP_MC_CFG 0x0C2E
+#define mmHDP_XDP_HST_CFG 0x0C2F
+#define mmHDP_XDP_P2P_BAR0 0x0C34
+#define mmHDP_XDP_P2P_BAR1 0x0C35
+#define mmHDP_XDP_P2P_BAR2 0x0C36
+#define mmHDP_XDP_P2P_BAR3 0x0C37
+#define mmHDP_XDP_P2P_BAR4 0x0C38
+#define mmHDP_XDP_P2P_BAR5 0x0C39
+#define mmHDP_XDP_P2P_BAR6 0x0C3A
+#define mmHDP_XDP_P2P_BAR7 0x0C3B
+#define mmHDP_XDP_P2P_BAR_CFG 0x0C24
+#define mmHDP_XDP_P2P_MBX_ADDR0 0x0C26
+#define mmHDP_XDP_P2P_MBX_ADDR1 0x0C27
+#define mmHDP_XDP_P2P_MBX_ADDR2 0x0C28
+#define mmHDP_XDP_P2P_MBX_ADDR3 0x0C29
+#define mmHDP_XDP_P2P_MBX_ADDR4 0x0C2A
+#define mmHDP_XDP_P2P_MBX_ADDR5 0x0C2B
+#define mmHDP_XDP_P2P_MBX_ADDR6 0x0C2C
+#define mmHDP_XDP_P2P_MBX_OFFSET 0x0C25
+#define mmHDP_XDP_SID_CFG 0x0C30
+#define mmHDP_XDP_SRBM_CFG 0x0C32
+#define mmHDP_XDP_STICKY 0x0C3F
+#define mmIH_ADVFAULT_CNTL 0x0F8C
+#define mmIH_CNTL 0x0F86
+#define mmIH_LEVEL_STATUS 0x0F87
+#define mmIH_PERFCOUNTER0_RESULT 0x0F8A
+#define mmIH_PERFCOUNTER1_RESULT 0x0F8B
+#define mmIH_PERFMON_CNTL 0x0F89
+#define mmIH_RB_BASE 0x0F81
+#define mmIH_RB_CNTL 0x0F80
+#define mmIH_RB_RPTR 0x0F82
+#define mmIH_RB_WPTR 0x0F83
+#define mmIH_RB_WPTR_ADDR_HI 0x0F84
+#define mmIH_RB_WPTR_ADDR_LO 0x0F85
+#define mmIH_STATUS 0x0F88
+#define mmSEM_MAILBOX 0x0F9B
+#define mmSEM_MAILBOX_CLIENTCONFIG 0x0F9A
+#define mmSEM_MAILBOX_CONTROL 0x0F9C
+#define mmSEM_MCIF_CONFIG 0x0F90
+#define mmSRBM_CAM_DATA 0x0397
+#define mmSRBM_CAM_INDEX 0x0396
+#define mmSRBM_CHIP_REVISION 0x039B
+#define mmSRBM_CNTL 0x0390
+#define mmSRBM_DEBUG 0x03A4
+#define mmSRBM_DEBUG_CNTL 0x0399
+#define mmSRBM_DEBUG_DATA 0x039A
+#define mmSRBM_DEBUG_SNAPSHOT 0x03A5
+#define mmSRBM_GFX_CNTL 0x0391
+#define mmSRBM_INT_ACK 0x03AA
+#define mmSRBM_INT_CNTL 0x03A8
+#define mmSRBM_INT_STATUS 0x03A9
+#define mmSRBM_MC_CLKEN_CNTL 0x03B3
+#define mmSRBM_PERFCOUNTER0_HI 0x0704
+#define mmSRBM_PERFCOUNTER0_LO 0x0703
+#define mmSRBM_PERFCOUNTER0_SELECT 0x0701
+#define mmSRBM_PERFCOUNTER1_HI 0x0706
+#define mmSRBM_PERFCOUNTER1_LO 0x0705
+#define mmSRBM_PERFCOUNTER1_SELECT 0x0702
+#define mmSRBM_PERFMON_CNTL 0x0700
+#define mmSRBM_READ_ERROR 0x03A6
+#define mmSRBM_SOFT_RESET 0x0398
+#define mmSRBM_STATUS 0x0394
+#define mmSRBM_STATUS2 0x0393
+#define mmSRBM_SYS_CLKEN_CNTL 0x03B4
+#define mmSRBM_UVD_CLKEN_CNTL 0x03B6
+#define mmSRBM_VCE_CLKEN_CNTL 0x03B5
+#define mmUVD_CONFIG 0x0F98
+#define mmVCE_CONFIG 0x0F94
+#define mmXDMA_MSTR_MEM_OVERFLOW_CNTL 0x03F8
+
+/* from the old sid.h */
+#define mmDMA_TILING_CONFIG 0x342E
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/oss/oss_1_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1079 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 OSS_1_0_SH_MASK_H
+#define OSS_1_0_SH_MASK_H
+
+#define CC_DRM_ID_STRAPS__ATI_REV_ID_MASK 0xf0000000L
+#define CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT 0x0000001c
+#define CC_DRM_ID_STRAPS__DEVICE_ID_MASK 0x000ffff0L
+#define CC_DRM_ID_STRAPS__DEVICE_ID__SHIFT 0x00000004
+#define CC_DRM_ID_STRAPS__MAJOR_REV_ID_MASK 0x00f00000L
+#define CC_DRM_ID_STRAPS__MAJOR_REV_ID__SHIFT 0x00000014
+#define CC_DRM_ID_STRAPS__MINOR_REV_ID_MASK 0x0f000000L
+#define CC_DRM_ID_STRAPS__MINOR_REV_ID__SHIFT 0x00000018
+#define CC_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define CC_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define CLIENT0_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT0_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT0_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT0_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT0_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT0_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT0_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT0_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT0_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT0_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT0_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT0_STATUS__RESERVED__SHIFT 0x00000000
+#define CLIENT1_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT1_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT1_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT1_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT1_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT1_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT1_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT1_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT1_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT1_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT1_PORT_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT1_PORT_STATUS__RESERVED__SHIFT 0x00000000
+#define CLIENT2_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT2_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT2_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT2_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT2_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT2_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT2_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT2_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT2_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT2_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT2_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT2_STATUS__RESERVED__SHIFT 0x00000000
+#define CLIENT3_BM__RESERVED_MASK 0xffffffffL
+#define CLIENT3_BM__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD0__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD0__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD1__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD1__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD2__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD2__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CD3__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CD3__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK0__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK0__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK1__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK1__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK2__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK2__RESERVED__SHIFT 0x00000000
+#define CLIENT3_CK3__RESERVED_MASK 0xffffffffL
+#define CLIENT3_CK3__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K0__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K0__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K1__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K1__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K2__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K2__RESERVED__SHIFT 0x00000000
+#define CLIENT3_K3__RESERVED_MASK 0xffffffffL
+#define CLIENT3_K3__RESERVED__SHIFT 0x00000000
+#define CLIENT3_OFFSET_HI__RESERVED_MASK 0xffffffffL
+#define CLIENT3_OFFSET_HI__RESERVED__SHIFT 0x00000000
+#define CLIENT3_OFFSET__RESERVED_MASK 0xffffffffL
+#define CLIENT3_OFFSET__RESERVED__SHIFT 0x00000000
+#define CLIENT3_STATUS__RESERVED_MASK 0xffffffffL
+#define CLIENT3_STATUS__RESERVED__SHIFT 0x00000000
+#define CP_CONFIG__CP_RDREQ_URG_MASK 0x00000f00L
+#define CP_CONFIG__CP_RDREQ_URG__SHIFT 0x00000008
+#define CP_CONFIG__CP_REQ_TRAN_MASK 0x00010000L
+#define CP_CONFIG__CP_REQ_TRAN__SHIFT 0x00000010
+#define DC_TEST_DEBUG_DATA__DC_TEST_DEBUG_DATA_MASK 0xffffffffL
+#define DC_TEST_DEBUG_DATA__DC_TEST_DEBUG_DATA__SHIFT 0x00000000
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_INDEX_MASK 0x000000ffL
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_INDEX__SHIFT 0x00000000
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_WRITE_EN_MASK 0x00000100L
+#define DC_TEST_DEBUG_INDEX__DC_TEST_DEBUG_WRITE_EN__SHIFT 0x00000008
+#define DH_TEST__DH_TEST_MASK 0x00000001L
+#define DH_TEST__DH_TEST__SHIFT 0x00000000
+#define EXP0__RESERVED_MASK 0xffffffffL
+#define EXP0__RESERVED__SHIFT 0x00000000
+#define EXP1__RESERVED_MASK 0xffffffffL
+#define EXP1__RESERVED__SHIFT 0x00000000
+#define EXP2__RESERVED_MASK 0xffffffffL
+#define EXP2__RESERVED__SHIFT 0x00000000
+#define EXP3__RESERVED_MASK 0xffffffffL
+#define EXP3__RESERVED__SHIFT 0x00000000
+#define EXP4__RESERVED_MASK 0xffffffffL
+#define EXP4__RESERVED__SHIFT 0x00000000
+#define EXP5__RESERVED_MASK 0xffffffffL
+#define EXP5__RESERVED__SHIFT 0x00000000
+#define EXP6__RESERVED_MASK 0xffffffffL
+#define EXP6__RESERVED__SHIFT 0x00000000
+#define EXP7__RESERVED_MASK 0xffffffffL
+#define EXP7__RESERVED__SHIFT 0x00000000
+#define GC_USER_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK 0x00ff0000L
+#define GC_USER_SYS_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT 0x00000010
+#define HDP_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define HDP_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define HDP_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define HDP_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define HDP_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define HDP_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define HDP_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define HDP_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define HDP_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define HDP_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define HDP_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define HDP_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define HDP_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define HDP_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define HDP_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define HDP_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define HDP_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define HDP_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define HDP_DEBUG0__HDP_DEBUG__SHIFT 0x00000000
+#define HDP_DEBUG1__HDP_DEBUG__SHIFT 0x00000000
+#define HDP_HOST_PATH_CNTL__ALL_SURFACES_DIS_MASK 0x20000000L
+#define HDP_HOST_PATH_CNTL__ALL_SURFACES_DIS__SHIFT 0x0000001d
+#define HDP_HOST_PATH_CNTL__BIF_RDRET_CREDIT_MASK 0x00000007L
+#define HDP_HOST_PATH_CNTL__BIF_RDRET_CREDIT__SHIFT 0x00000000
+#define HDP_HOST_PATH_CNTL__CACHE_INVALIDATE_MASK 0x00400000L
+#define HDP_HOST_PATH_CNTL__CACHE_INVALIDATE__SHIFT 0x00000016
+#define HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK 0x00800000L
+#define HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS__SHIFT 0x00000017
+#define HDP_HOST_PATH_CNTL__LIN_RD_CACHE_DIS_MASK 0x80000000L
+#define HDP_HOST_PATH_CNTL__LIN_RD_CACHE_DIS__SHIFT 0x0000001f
+#define HDP_HOST_PATH_CNTL__MC_WRREQ_CREDIT_MASK 0x000001f8L
+#define HDP_HOST_PATH_CNTL__MC_WRREQ_CREDIT__SHIFT 0x00000003
+#define HDP_HOST_PATH_CNTL__RD_STALL_TIMER_MASK 0x00001800L
+#define HDP_HOST_PATH_CNTL__RD_STALL_TIMER__SHIFT 0x0000000b
+#define HDP_HOST_PATH_CNTL__REG_CLK_ENABLE_COUNT_MASK 0x0f000000L
+#define HDP_HOST_PATH_CNTL__REG_CLK_ENABLE_COUNT__SHIFT 0x00000018
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_EN_MASK 0x00200000L
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_EN__SHIFT 0x00000015
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_TIMER_MASK 0x00180000L
+#define HDP_HOST_PATH_CNTL__WRITE_COMBINE_TIMER__SHIFT 0x00000013
+#define HDP_HOST_PATH_CNTL__WRITE_THROUGH_CACHE_DIS_MASK 0x40000000L
+#define HDP_HOST_PATH_CNTL__WRITE_THROUGH_CACHE_DIS__SHIFT 0x0000001e
+#define HDP_HOST_PATH_CNTL__WR_STALL_TIMER_MASK 0x00000600L
+#define HDP_HOST_PATH_CNTL__WR_STALL_TIMER__SHIFT 0x00000009
+#define HDP_LAST_SURFACE_HIT__LAST_SURFACE_HIT_MASK 0x0000003fL
+#define HDP_LAST_SURFACE_HIT__LAST_SURFACE_HIT__SHIFT 0x00000000
+#define HDP_MEMIO_ADDR__MEMIO_ADDR_LOWER_MASK 0xffffffffL
+#define HDP_MEMIO_ADDR__MEMIO_ADDR_LOWER__SHIFT 0x00000000
+#define HDP_MEMIO_CNTL__MEMIO_ADDR_UPPER_MASK 0x00003f00L
+#define HDP_MEMIO_CNTL__MEMIO_ADDR_UPPER__SHIFT 0x00000008
+#define HDP_MEMIO_CNTL__MEMIO_BE_MASK 0x0000003cL
+#define HDP_MEMIO_CNTL__MEMIO_BE__SHIFT 0x00000002
+#define HDP_MEMIO_CNTL__MEMIO_CLR_RD_ERROR_MASK 0x00008000L
+#define HDP_MEMIO_CNTL__MEMIO_CLR_RD_ERROR__SHIFT 0x0000000f
+#define HDP_MEMIO_CNTL__MEMIO_CLR_WR_ERROR_MASK 0x00004000L
+#define HDP_MEMIO_CNTL__MEMIO_CLR_WR_ERROR__SHIFT 0x0000000e
+#define HDP_MEMIO_CNTL__MEMIO_OP_MASK 0x00000002L
+#define HDP_MEMIO_CNTL__MEMIO_OP__SHIFT 0x00000001
+#define HDP_MEMIO_CNTL__MEMIO_RD_STROBE_MASK 0x00000080L
+#define HDP_MEMIO_CNTL__MEMIO_RD_STROBE__SHIFT 0x00000007
+#define HDP_MEMIO_CNTL__MEMIO_SEND_MASK 0x00000001L
+#define HDP_MEMIO_CNTL__MEMIO_SEND__SHIFT 0x00000000
+#define HDP_MEMIO_CNTL__MEMIO_WR_STROBE_MASK 0x00000040L
+#define HDP_MEMIO_CNTL__MEMIO_WR_STROBE__SHIFT 0x00000006
+#define HDP_MEMIO_RD_DATA__MEMIO_RD_DATA_MASK 0xffffffffL
+#define HDP_MEMIO_RD_DATA__MEMIO_RD_DATA__SHIFT 0x00000000
+#define HDP_MEMIO_STATUS__MEMIO_RD_ERROR_MASK 0x00000008L
+#define HDP_MEMIO_STATUS__MEMIO_RD_ERROR__SHIFT 0x00000003
+#define HDP_MEMIO_STATUS__MEMIO_RD_STATUS_MASK 0x00000002L
+#define HDP_MEMIO_STATUS__MEMIO_RD_STATUS__SHIFT 0x00000001
+#define HDP_MEMIO_STATUS__MEMIO_WR_ERROR_MASK 0x00000004L
+#define HDP_MEMIO_STATUS__MEMIO_WR_ERROR__SHIFT 0x00000002
+#define HDP_MEMIO_STATUS__MEMIO_WR_STATUS_MASK 0x00000001L
+#define HDP_MEMIO_STATUS__MEMIO_WR_STATUS__SHIFT 0x00000000
+#define HDP_MEMIO_WR_DATA__MEMIO_WR_DATA_MASK 0xffffffffL
+#define HDP_MEMIO_WR_DATA__MEMIO_WR_DATA__SHIFT 0x00000000
+#define HDP_MEM_POWER_LS__LS_ENABLE_MASK 0x00000001L
+#define HDP_MEM_POWER_LS__LS_ENABLE__SHIFT 0x00000000
+#define HDP_MEM_POWER_LS__LS_HOLD_MASK 0x00001f80L
+#define HDP_MEM_POWER_LS__LS_HOLD__SHIFT 0x00000007
+#define HDP_MEM_POWER_LS__LS_SETUP_MASK 0x0000007eL
+#define HDP_MEM_POWER_LS__LS_SETUP__SHIFT 0x00000001
+#define HDP_MISC_CNTL__ADDRLIB_LINEAR_BYPASS_MASK 0x00100000L
+#define HDP_MISC_CNTL__ADDRLIB_LINEAR_BYPASS__SHIFT 0x00000014
+#define HDP_MISC_CNTL__FED_ENABLE_MASK 0x00200000L
+#define HDP_MISC_CNTL__FED_ENABLE__SHIFT 0x00000015
+#define HDP_MISC_CNTL__FLUSH_INVALIDATE_CACHE_MASK 0x00000001L
+#define HDP_MISC_CNTL__FLUSH_INVALIDATE_CACHE__SHIFT 0x00000000
+#define HDP_MISC_CNTL__HDP_BIF_RDRET_CREDIT_MASK 0x00000780L
+#define HDP_MISC_CNTL__HDP_BIF_RDRET_CREDIT__SHIFT 0x00000007
+#define HDP_MISC_CNTL__MC_RDREQ_CREDIT_MASK 0x0007e000L
+#define HDP_MISC_CNTL__MC_RDREQ_CREDIT__SHIFT 0x0000000d
+#define HDP_MISC_CNTL__MULTIPLE_READS_MASK 0x00000040L
+#define HDP_MISC_CNTL__MULTIPLE_READS__SHIFT 0x00000006
+#define HDP_MISC_CNTL__NO_SPLIT_ARRAY_LINEAR_MASK 0x00001000L
+#define HDP_MISC_CNTL__NO_SPLIT_ARRAY_LINEAR__SHIFT 0x0000000c
+#define HDP_MISC_CNTL__OUTSTANDING_WRITE_COUNT_1024_MASK 0x00000020L
+#define HDP_MISC_CNTL__OUTSTANDING_WRITE_COUNT_1024__SHIFT 0x00000005
+#define HDP_MISC_CNTL__READ_CACHE_INVALIDATE_MASK 0x00080000L
+#define HDP_MISC_CNTL__READ_CACHE_INVALIDATE__SHIFT 0x00000013
+#define HDP_MISC_CNTL__SIMULTANEOUS_READS_WRITES_MASK 0x00000800L
+#define HDP_MISC_CNTL__SIMULTANEOUS_READS_WRITES__SHIFT 0x0000000b
+#define HDP_MISC_CNTL__VM_ID_MASK 0x0000001eL
+#define HDP_MISC_CNTL__VM_ID__SHIFT 0x00000001
+#define HDP_NONSURFACE_BASE__NONSURF_BASE_MASK 0xffffffffL
+#define HDP_NONSURFACE_BASE__NONSURF_BASE__SHIFT 0x00000000
+#define HDP_NONSURFACE_INFO__NONSURF_ADDR_TYPE_MASK 0x00000001L
+#define HDP_NONSURFACE_INFO__NONSURF_ADDR_TYPE__SHIFT 0x00000000
+#define HDP_NONSURFACE_INFO__NONSURF_ARRAY_MODE_MASK 0x0000001eL
+#define HDP_NONSURFACE_INFO__NONSURF_ARRAY_MODE__SHIFT 0x00000001
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_HEIGHT_MASK 0x03000000L
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_HEIGHT__SHIFT 0x00000018
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_WIDTH_MASK 0x00c00000L
+#define HDP_NONSURFACE_INFO__NONSURF_BANK_WIDTH__SHIFT 0x00000016
+#define HDP_NONSURFACE_INFO__NONSURF_ENDIAN_MASK 0x00000060L
+#define HDP_NONSURFACE_INFO__NONSURF_ENDIAN__SHIFT 0x00000005
+#define HDP_NONSURFACE_INFO__NONSURF_MACRO_TILE_ASPECT_MASK 0x0c000000L
+#define HDP_NONSURFACE_INFO__NONSURF_MACRO_TILE_ASPECT__SHIFT 0x0000001a
+#define HDP_NONSURFACE_INFO__NONSURF_MICRO_TILE_MODE_MASK 0x30000000L
+#define HDP_NONSURFACE_INFO__NONSURF_MICRO_TILE_MODE__SHIFT 0x0000001c
+#define HDP_NONSURFACE_INFO__NONSURF_NUM_BANKS_MASK 0x00300000L
+#define HDP_NONSURFACE_INFO__NONSURF_NUM_BANKS__SHIFT 0x00000014
+#define HDP_NONSURFACE_INFO__NONSURF_PIXEL_SIZE_MASK 0x00000380L
+#define HDP_NONSURFACE_INFO__NONSURF_PIXEL_SIZE__SHIFT 0x00000007
+#define HDP_NONSURFACE_INFO__NONSURF_PRIV_MASK 0x00008000L
+#define HDP_NONSURFACE_INFO__NONSURF_PRIV__SHIFT 0x0000000f
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_NUM_MASK 0x00001c00L
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_NUM__SHIFT 0x0000000a
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_SIZE_MASK 0x00006000L
+#define HDP_NONSURFACE_INFO__NONSURF_SAMPLE_SIZE__SHIFT 0x0000000d
+#define HDP_NONSURFACE_INFO__NONSURF_SLICE_TILE_MAX_MSB_MASK 0x40000000L
+#define HDP_NONSURFACE_INFO__NONSURF_SLICE_TILE_MAX_MSB__SHIFT 0x0000001e
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_COMPACT_MASK 0x00010000L
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_COMPACT__SHIFT 0x00000010
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_SPLIT_MASK 0x000e0000L
+#define HDP_NONSURFACE_INFO__NONSURF_TILE_SPLIT__SHIFT 0x00000011
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PIPE_CONFIG_MASK 0xf8000000L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PIPE_CONFIG__SHIFT 0x0000001b
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_DIR_MASK 0x00000038L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_DIR__SHIFT 0x00000003
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_MAX_Z_MASK 0x000ffe00L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_MAX_Z__SHIFT 0x00000009
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_NUM_MASK 0x000001c0L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_NUM__SHIFT 0x00000006
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_PRI_MASK 0x00000007L
+#define HDP_NONSURFACE_PREFETCH__NONSURF_PREFETCH_PRI__SHIFT 0x00000000
+#define HDP_NONSURFACE_SIZE__NONSURF_PITCH_TILE_MAX_MASK 0x000007ffL
+#define HDP_NONSURFACE_SIZE__NONSURF_PITCH_TILE_MAX__SHIFT 0x00000000
+#define HDP_NONSURFACE_SIZE__NONSURF_SLICE_TILE_MAX_MASK 0xfffff800L
+#define HDP_NONSURFACE_SIZE__NONSURF_SLICE_TILE_MAX__SHIFT 0x0000000b
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_READ_FLAG_CLR_MASK 0x00000002L
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_READ_FLAG_CLR__SHIFT 0x00000001
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_WRITE_FLAG_CLR_MASK 0x00000001L
+#define HDP_NONSURF_FLAGS_CLR__NONSURF_WRITE_FLAG_CLR__SHIFT 0x00000000
+#define HDP_NONSURF_FLAGS__NONSURF_READ_FLAG_MASK 0x00000002L
+#define HDP_NONSURF_FLAGS__NONSURF_READ_FLAG__SHIFT 0x00000001
+#define HDP_NONSURF_FLAGS__NONSURF_WRITE_FLAG_MASK 0x00000001L
+#define HDP_NONSURF_FLAGS__NONSURF_WRITE_FLAG__SHIFT 0x00000000
+#define HDP_OUTSTANDING_REQ__READ_REQ_MASK 0x0000ff00L
+#define HDP_OUTSTANDING_REQ__READ_REQ__SHIFT 0x00000008
+#define HDP_OUTSTANDING_REQ__WRITE_REQ_MASK 0x000000ffL
+#define HDP_OUTSTANDING_REQ__WRITE_REQ__SHIFT 0x00000000
+#define HDP_SC_MULTI_CHIP_CNTL__LOG2_NUM_CHIPS_MASK 0x00000007L
+#define HDP_SC_MULTI_CHIP_CNTL__LOG2_NUM_CHIPS__SHIFT 0x00000000
+#define HDP_SC_MULTI_CHIP_CNTL__MULTI_CHIP_TILE_SIZE_MASK 0x00000018L
+#define HDP_SC_MULTI_CHIP_CNTL__MULTI_CHIP_TILE_SIZE__SHIFT 0x00000003
+#define HDP_SW_SEMAPHORE__SW_SEMAPHORE_MASK 0xffffffffL
+#define HDP_SW_SEMAPHORE__SW_SEMAPHORE__SHIFT 0x00000000
+#define HDP_TILING_CONFIG__BANK_SWAPS_MASK 0x00003800L
+#define HDP_TILING_CONFIG__BANK_SWAPS__SHIFT 0x0000000b
+#define HDP_TILING_CONFIG__BANK_TILING_MASK 0x00000030L
+#define HDP_TILING_CONFIG__BANK_TILING__SHIFT 0x00000004
+#define HDP_TILING_CONFIG__GROUP_SIZE_MASK 0x000000c0L
+#define HDP_TILING_CONFIG__GROUP_SIZE__SHIFT 0x00000006
+#define HDP_TILING_CONFIG__PIPE_TILING_MASK 0x0000000eL
+#define HDP_TILING_CONFIG__PIPE_TILING__SHIFT 0x00000001
+#define HDP_TILING_CONFIG__ROW_TILING_MASK 0x00000700L
+#define HDP_TILING_CONFIG__ROW_TILING__SHIFT 0x00000008
+#define HDP_TILING_CONFIG__SAMPLE_SPLIT_MASK 0x0000c000L
+#define HDP_TILING_CONFIG__SAMPLE_SPLIT__SHIFT 0x0000000e
+#define HDP_XDP_BARS_ADDR_39_36__BAR0_ADDR_39_36_MASK 0x0000000fL
+#define HDP_XDP_BARS_ADDR_39_36__BAR0_ADDR_39_36__SHIFT 0x00000000
+#define HDP_XDP_BARS_ADDR_39_36__BAR1_ADDR_39_36_MASK 0x000000f0L
+#define HDP_XDP_BARS_ADDR_39_36__BAR1_ADDR_39_36__SHIFT 0x00000004
+#define HDP_XDP_BARS_ADDR_39_36__BAR2_ADDR_39_36_MASK 0x00000f00L
+#define HDP_XDP_BARS_ADDR_39_36__BAR2_ADDR_39_36__SHIFT 0x00000008
+#define HDP_XDP_BARS_ADDR_39_36__BAR3_ADDR_39_36_MASK 0x0000f000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR3_ADDR_39_36__SHIFT 0x0000000c
+#define HDP_XDP_BARS_ADDR_39_36__BAR4_ADDR_39_36_MASK 0x000f0000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR4_ADDR_39_36__SHIFT 0x00000010
+#define HDP_XDP_BARS_ADDR_39_36__BAR5_ADDR_39_36_MASK 0x00f00000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR5_ADDR_39_36__SHIFT 0x00000014
+#define HDP_XDP_BARS_ADDR_39_36__BAR6_ADDR_39_36_MASK 0x0f000000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR6_ADDR_39_36__SHIFT 0x00000018
+#define HDP_XDP_BARS_ADDR_39_36__BAR7_ADDR_39_36_MASK 0xf0000000L
+#define HDP_XDP_BARS_ADDR_39_36__BAR7_ADDR_39_36__SHIFT 0x0000001c
+#define HDP_XDP_BUSY_STS__BUSY_BITS_MASK 0x0003ffffL
+#define HDP_XDP_BUSY_STS__BUSY_BITS__SHIFT 0x00000000
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_0_ON_DELAY_MASK 0x0000000fL
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_0_ON_DELAY__SHIFT 0x00000000
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_1_OFF_DELAY_MASK 0x00000ff0L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_1_OFF_DELAY__SHIFT 0x00000004
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_2_RSVD_MASK 0x3ffff000L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_2_RSVD__SHIFT 0x0000000c
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_3_SOFT_CORE_OVERRIDE_MASK 0x40000000L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_3_SOFT_CORE_OVERRIDE__SHIFT 0x0000001e
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_4_SOFT_REG_OVERRIDE_MASK 0x80000000L
+#define HDP_XDP_CGTT_BLK_CTRL__CGTT_BLK_CTRL_4_SOFT_REG_OVERRIDE__SHIFT 0x0000001f
+#define HDP_XDP_CHKN__CHKN_0_RSVD_MASK 0x000000ffL
+#define HDP_XDP_CHKN__CHKN_0_RSVD__SHIFT 0x00000000
+#define HDP_XDP_CHKN__CHKN_1_RSVD_MASK 0x0000ff00L
+#define HDP_XDP_CHKN__CHKN_1_RSVD__SHIFT 0x00000008
+#define HDP_XDP_CHKN__CHKN_2_RSVD_MASK 0x00ff0000L
+#define HDP_XDP_CHKN__CHKN_2_RSVD__SHIFT 0x00000010
+#define HDP_XDP_CHKN__CHKN_3_RSVD_MASK 0xff000000L
+#define HDP_XDP_CHKN__CHKN_3_RSVD__SHIFT 0x00000018
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_ADDR_MASK 0x0000ffffL
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_ADDR__SHIFT 0x00000000
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_BAR_NUM_MASK 0x00700000L
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_BAR_NUM__SHIFT 0x00000014
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_FLUSH_NUM_MASK 0x000f0000L
+#define HDP_XDP_D2H_BAR_UPDATE__D2H_BAR_UPDATE_FLUSH_NUM__SHIFT 0x00000010
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_ALTER_FLUSH_NUM_MASK 0x00040000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_ALTER_FLUSH_NUM__SHIFT 0x00000012
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_FLUSH_NUM_MASK 0x0000000fL
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_FLUSH_NUM__SHIFT 0x00000000
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ADDR_SEL_MASK 0x00000700L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ADDR_SEL__SHIFT 0x00000008
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ENC_DATA_MASK 0x000000f0L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_MBX_ENC_DATA__SHIFT 0x00000004
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_0_MASK 0x00080000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_0__SHIFT 0x00000013
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_1_MASK 0x00100000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_RSVD_1__SHIFT 0x00000014
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_HOST_MASK 0x00010000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_HOST__SHIFT 0x00000010
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_SIDE_MASK 0x00020000L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_SEND_SIDE__SHIFT 0x00000011
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_XPB_CLG_MASK 0x0000f800L
+#define HDP_XDP_D2H_FLUSH__D2H_FLUSH_XPB_CLG__SHIFT 0x0000000b
+#define HDP_XDP_D2H_RSVD_10__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_10__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_11__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_11__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_12__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_12__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_13__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_13__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_14__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_14__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_15__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_15__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_16__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_16__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_17__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_17__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_18__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_18__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_19__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_19__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_20__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_20__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_21__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_21__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_22__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_22__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_23__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_23__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_24__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_24__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_25__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_25__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_26__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_26__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_27__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_27__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_28__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_28__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_29__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_29__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_30__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_30__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_31__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_31__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_32__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_32__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_33__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_33__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_34__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_34__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_3__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_3__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_4__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_4__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_5__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_5__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_6__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_6__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_7__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_7__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_8__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_8__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_D2H_RSVD_9__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_D2H_RSVD_9__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_DBG_ADDR__CTRL_MASK 0xffff0000L
+#define HDP_XDP_DBG_ADDR__CTRL__SHIFT 0x00000010
+#define HDP_XDP_DBG_ADDR__STS_MASK 0x0000ffffL
+#define HDP_XDP_DBG_ADDR__STS__SHIFT 0x00000000
+#define HDP_XDP_DBG_DATA__CTRL_MASK 0xffff0000L
+#define HDP_XDP_DBG_DATA__CTRL__SHIFT 0x00000010
+#define HDP_XDP_DBG_DATA__STS_MASK 0x0000ffffL
+#define HDP_XDP_DBG_DATA__STS__SHIFT 0x00000000
+#define HDP_XDP_DBG_MASK__CTRL_MASK 0xffff0000L
+#define HDP_XDP_DBG_MASK__CTRL__SHIFT 0x00000010
+#define HDP_XDP_DBG_MASK__STS_MASK 0x0000ffffL
+#define HDP_XDP_DBG_MASK__STS__SHIFT 0x00000000
+#define HDP_XDP_DIRECT2HDP_FIRST__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_DIRECT2HDP_FIRST__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_DIRECT2HDP_LAST__RESERVED_MASK 0xffffffffL
+#define HDP_XDP_DIRECT2HDP_LAST__RESERVED__SHIFT 0x00000000
+#define HDP_XDP_FLUSH_ARMED_STS__FLUSH_ARMED_STS_MASK 0xffffffffL
+#define HDP_XDP_FLUSH_ARMED_STS__FLUSH_ARMED_STS__SHIFT 0x00000000
+#define HDP_XDP_FLUSH_CNTR0_STS__FLUSH_CNTR0_STS_MASK 0x03ffffffL
+#define HDP_XDP_FLUSH_CNTR0_STS__FLUSH_CNTR0_STS__SHIFT 0x00000000
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_INVERSE_PEER_TAG_MATCHING_MASK 0x00001000L
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_INVERSE_PEER_TAG_MATCHING__SHIFT 0x0000000c
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_P2P_RD_EN_MASK 0x00002000L
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_P2P_RD_EN__SHIFT 0x0000000d
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_SYS_FIFO_DEPTH_OVERRIDE_MASK 0x0000003fL
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_SYS_FIFO_DEPTH_OVERRIDE__SHIFT 0x00000000
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_XDP_FIFO_DEPTH_OVERRIDE_MASK 0x00000fc0L
+#define HDP_XDP_HDP_IPH_CFG__HDP_IPH_CFG_XDP_FIFO_DEPTH_OVERRIDE__SHIFT 0x00000006
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_PRIV_MASK 0x00000001L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_PRIV__SHIFT 0x00000000
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_SWAP_MASK 0x00000006L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_SWAP__SHIFT 0x00000001
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_TRAN_MASK 0x00000008L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_TRAN__SHIFT 0x00000003
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_VMID_MASK 0x000000f0L
+#define HDP_XDP_HDP_MBX_MC_CFG__HDP_MBX_MC_CFG_TAP_WRREQ_VMID__SHIFT 0x00000004
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_PRIV_MASK 0x00000001L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_PRIV__SHIFT 0x00000000
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_SWAP_MASK 0x00000006L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_SWAP__SHIFT 0x00000001
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_TRAN_MASK 0x00000008L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_TRAN__SHIFT 0x00000003
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_VMID_MASK 0x07800000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_HST_TAP_WRREQ_VMID__SHIFT 0x00000017
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_MC_STALL_ON_BUF_FULL_MASK_MASK 0x00700000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_MC_STALL_ON_BUF_FULL_MASK__SHIFT 0x00000014
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_PRIV_MASK 0x00000010L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_PRIV__SHIFT 0x00000004
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_SWAP_MASK 0x00000060L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_SWAP__SHIFT 0x00000005
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_TRAN_MASK 0x00000080L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_TRAN__SHIFT 0x00000007
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_VMID_MASK 0x78000000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_SID_TAP_WRREQ_VMID__SHIFT 0x0000001b
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XDP_HIGHER_PRI_THRESH_MASK 0x000fc000L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XDP_HIGHER_PRI_THRESH__SHIFT 0x0000000e
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XL8R_WRREQ_CRD_OVERRIDE_MASK 0x00003f00L
+#define HDP_XDP_HDP_MC_CFG__HDP_MC_CFG_XL8R_WRREQ_CRD_OVERRIDE__SHIFT 0x00000008
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_EN_MASK 0x00000001L
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_EN__SHIFT 0x00000000
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_TIMER_MASK 0x00000006L
+#define HDP_XDP_HST_CFG__HST_CFG_WR_COMBINE_TIMER__SHIFT 0x00000001
+#define HDP_XDP_P2P_BAR0__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR0__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR0__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR0__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR0__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR0__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR1__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR1__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR1__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR1__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR1__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR1__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR2__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR2__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR2__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR2__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR2__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR2__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR3__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR3__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR3__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR3__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR3__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR3__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR4__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR4__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR4__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR4__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR4__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR4__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR5__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR5__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR5__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR5__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR5__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR5__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR6__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR6__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR6__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR6__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR6__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR6__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR7__ADDR_MASK 0x0000ffffL
+#define HDP_XDP_P2P_BAR7__ADDR__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR7__FLUSH_MASK 0x000f0000L
+#define HDP_XDP_P2P_BAR7__FLUSH__SHIFT 0x00000010
+#define HDP_XDP_P2P_BAR7__VALID_MASK 0x00100000L
+#define HDP_XDP_P2P_BAR7__VALID__SHIFT 0x00000014
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_ADDR_SIZE_MASK 0x0000000fL
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_ADDR_SIZE__SHIFT 0x00000000
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_BAR_FROM_MASK 0x00000030L
+#define HDP_XDP_P2P_BAR_CFG__P2P_BAR_CFG_BAR_FROM__SHIFT 0x00000004
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR0__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR0__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR0__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR1__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR1__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR1__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR2__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR2__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR2__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR3__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR3__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR3__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR4__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR4__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR4__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR5__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR5__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR5__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR_39_36_MASK 0x01e00000L
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR_39_36__SHIFT 0x00000015
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR_MASK 0x001ffffeL
+#define HDP_XDP_P2P_MBX_ADDR6__ADDR__SHIFT 0x00000001
+#define HDP_XDP_P2P_MBX_ADDR6__VALID_MASK 0x00000001L
+#define HDP_XDP_P2P_MBX_ADDR6__VALID__SHIFT 0x00000000
+#define HDP_XDP_P2P_MBX_OFFSET__P2P_MBX_OFFSET_MASK 0x00003fffL
+#define HDP_XDP_P2P_MBX_OFFSET__P2P_MBX_OFFSET__SHIFT 0x00000000
+#define HDP_XDP_SID_CFG__SID_CFG_FLNUM_MSB_SEL_MASK 0x00000018L
+#define HDP_XDP_SID_CFG__SID_CFG_FLNUM_MSB_SEL__SHIFT 0x00000003
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_EN_MASK 0x00000001L
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_EN__SHIFT 0x00000000
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_TIMER_MASK 0x00000006L
+#define HDP_XDP_SID_CFG__SID_CFG_WR_COMBINE_TIMER__SHIFT 0x00000001
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_ENABLE_COUNT_MASK 0x0000003fL
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_ENABLE_COUNT__SHIFT 0x00000000
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_GATING_DIS_MASK 0x00000040L
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_REG_CLK_GATING_DIS__SHIFT 0x00000006
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_WAKE_DYN_CLK_MASK 0x00000080L
+#define HDP_XDP_SRBM_CFG__SRBM_CFG_WAKE_DYN_CLK__SHIFT 0x00000007
+#define HDP_XDP_STICKY__STICKY_STS_MASK 0x0000ffffL
+#define HDP_XDP_STICKY__STICKY_STS__SHIFT 0x00000000
+#define HDP_XDP_STICKY__STICKY_W1C_MASK 0xffff0000L
+#define HDP_XDP_STICKY__STICKY_W1C__SHIFT 0x00000010
+#define HFS_SEED0__RESERVED_MASK 0xffffffffL
+#define HFS_SEED0__RESERVED__SHIFT 0x00000000
+#define HFS_SEED1__RESERVED_MASK 0xffffffffL
+#define HFS_SEED1__RESERVED__SHIFT 0x00000000
+#define HFS_SEED2__RESERVED_MASK 0xffffffffL
+#define HFS_SEED2__RESERVED__SHIFT 0x00000000
+#define HFS_SEED3__RESERVED_MASK 0xffffffffL
+#define HFS_SEED3__RESERVED__SHIFT 0x00000000
+#define IH_ADVFAULT_CNTL__NUM_FAULTS_DROPPED_MASK 0x0000ff00L
+#define IH_ADVFAULT_CNTL__NUM_FAULTS_DROPPED__SHIFT 0x00000008
+#define IH_ADVFAULT_CNTL__WAIT_TIMER_MASK 0x3fff0000L
+#define IH_ADVFAULT_CNTL__WAIT_TIMER__SHIFT 0x00000010
+#define IH_ADVFAULT_CNTL__WATERMARK_ENABLE_MASK 0x00000008L
+#define IH_ADVFAULT_CNTL__WATERMARK_ENABLE__SHIFT 0x00000003
+#define IH_ADVFAULT_CNTL__WATERMARK_MASK 0x00000007L
+#define IH_ADVFAULT_CNTL__WATERMARK_REACHED_MASK 0x00000010L
+#define IH_ADVFAULT_CNTL__WATERMARK_REACHED__SHIFT 0x00000004
+#define IH_ADVFAULT_CNTL__WATERMARK__SHIFT 0x00000000
+#define IH_CNTL__CLIENT_FIFO_HIGHWATER_MASK 0x00000300L
+#define IH_CNTL__CLIENT_FIFO_HIGHWATER__SHIFT 0x00000008
+#define IH_CNTL__ENABLE_INTR_MASK 0x00000001L
+#define IH_CNTL__ENABLE_INTR__SHIFT 0x00000000
+#define IH_CNTL__MC_FIFO_HIGHWATER_MASK 0x00007c00L
+#define IH_CNTL__MC_FIFO_HIGHWATER__SHIFT 0x0000000a
+#define IH_CNTL__MC_SWAP_MASK 0x00000006L
+#define IH_CNTL__MC_SWAP__SHIFT 0x00000001
+#define IH_CNTL__MC_TRAN_MASK 0x00000008L
+#define IH_CNTL__MC_TRAN__SHIFT 0x00000003
+#define IH_CNTL__MC_VMID_MASK 0x1e000000L
+#define IH_CNTL__MC_VMID__SHIFT 0x00000019
+#define IH_CNTL__MC_WR_CLEAN_CNT_MASK 0x01f00000L
+#define IH_CNTL__MC_WR_CLEAN_CNT__SHIFT 0x00000014
+#define IH_CNTL__MC_WRREQ_CREDIT_MASK 0x000f8000L
+#define IH_CNTL__MC_WRREQ_CREDIT__SHIFT 0x0000000f
+#define IH_CNTL__RPTR_REARM_MASK 0x00000010L
+#define IH_CNTL__RPTR_REARM__SHIFT 0x00000004
+#define IH_LEVEL_STATUS__BIF_STATUS_MASK 0x00000010L
+#define IH_LEVEL_STATUS__BIF_STATUS__SHIFT 0x00000004
+#define IH_LEVEL_STATUS__DC_STATUS_MASK 0x00000001L
+#define IH_LEVEL_STATUS__DC_STATUS__SHIFT 0x00000000
+#define IH_LEVEL_STATUS__ROM_STATUS_MASK 0x00000004L
+#define IH_LEVEL_STATUS__ROM_STATUS__SHIFT 0x00000002
+#define IH_LEVEL_STATUS__SRBM_STATUS_MASK 0x00000008L
+#define IH_LEVEL_STATUS__SRBM_STATUS__SHIFT 0x00000003
+#define IH_LEVEL_STATUS__XDMA_STATUS_MASK 0x00000020L
+#define IH_LEVEL_STATUS__XDMA_STATUS__SHIFT 0x00000005
+#define IH_PERFCOUNTER0_RESULT__PERF_COUNT_MASK 0xffffffffL
+#define IH_PERFCOUNTER0_RESULT__PERF_COUNT__SHIFT 0x00000000
+#define IH_PERFCOUNTER1_RESULT__PERF_COUNT_MASK 0xffffffffL
+#define IH_PERFCOUNTER1_RESULT__PERF_COUNT__SHIFT 0x00000000
+#define IH_PERFMON_CNTL__CLEAR0_MASK 0x00000002L
+#define IH_PERFMON_CNTL__CLEAR0__SHIFT 0x00000001
+#define IH_PERFMON_CNTL__CLEAR1_MASK 0x00000200L
+#define IH_PERFMON_CNTL__CLEAR1__SHIFT 0x00000009
+#define IH_PERFMON_CNTL__ENABLE0_MASK 0x00000001L
+#define IH_PERFMON_CNTL__ENABLE0__SHIFT 0x00000000
+#define IH_PERFMON_CNTL__ENABLE1_MASK 0x00000100L
+#define IH_PERFMON_CNTL__ENABLE1__SHIFT 0x00000008
+#define IH_PERFMON_CNTL__PERF_SEL0_MASK 0x000000fcL
+#define IH_PERFMON_CNTL__PERF_SEL0__SHIFT 0x00000002
+#define IH_PERFMON_CNTL__PERF_SEL1_MASK 0x0000fc00L
+#define IH_PERFMON_CNTL__PERF_SEL1__SHIFT 0x0000000a
+#define IH_RB_BASE__ADDR_MASK 0xffffffffL
+#define IH_RB_BASE__ADDR__SHIFT 0x00000000
+#define IH_RB_CNTL__RB_ENABLE_MASK 0x00000001L
+#define IH_RB_CNTL__RB_ENABLE__SHIFT 0x00000000
+#define IH_RB_CNTL__RB_FULL_DRAIN_ENABLE_MASK 0x00000040L
+#define IH_RB_CNTL__RB_FULL_DRAIN_ENABLE__SHIFT 0x00000006
+#define IH_RB_CNTL__RB_GPU_TS_ENABLE_MASK 0x00000080L
+#define IH_RB_CNTL__RB_GPU_TS_ENABLE__SHIFT 0x00000007
+#define IH_RB_CNTL__RB_SIZE_MASK 0x0000003eL
+#define IH_RB_CNTL__RB_SIZE__SHIFT 0x00000001
+#define IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK 0x80000000L
+#define IH_RB_CNTL__WPTR_OVERFLOW_CLEAR__SHIFT 0x0000001f
+#define IH_RB_CNTL__WPTR_OVERFLOW_ENABLE_MASK 0x00010000L
+#define IH_RB_CNTL__WPTR_OVERFLOW_ENABLE__SHIFT 0x00000010
+#define IH_RB_CNTL__WPTR_WRITEBACK_ENABLE_MASK 0x00000100L
+#define IH_RB_CNTL__WPTR_WRITEBACK_ENABLE__SHIFT 0x00000008
+#define IH_RB_CNTL__WPTR_WRITEBACK_TIMER_MASK 0x00003e00L
+#define IH_RB_CNTL__WPTR_WRITEBACK_TIMER__SHIFT 0x00000009
+#define IH_RB_RPTR__OFFSET_MASK 0x0003fffcL
+#define IH_RB_RPTR__OFFSET__SHIFT 0x00000002
+#define IH_RB_WPTR_ADDR_HI__ADDR_MASK 0x000000ffL
+#define IH_RB_WPTR_ADDR_HI__ADDR__SHIFT 0x00000000
+#define IH_RB_WPTR_ADDR_LO__ADDR_MASK 0xfffffffcL
+#define IH_RB_WPTR_ADDR_LO__ADDR__SHIFT 0x00000002
+#define IH_RB_WPTR__OFFSET_MASK 0x0003fffcL
+#define IH_RB_WPTR__OFFSET__SHIFT 0x00000002
+#define IH_RB_WPTR__RB_OVERFLOW_MASK 0x00000001L
+#define IH_RB_WPTR__RB_OVERFLOW__SHIFT 0x00000000
+#define IH_STATUS__BIF_INTERRUPT_LINE_MASK 0x00000400L
+#define IH_STATUS__BIF_INTERRUPT_LINE__SHIFT 0x0000000a
+#define IH_STATUS__IDLE_MASK 0x00000001L
+#define IH_STATUS__IDLE__SHIFT 0x00000000
+#define IH_STATUS__INPUT_IDLE_MASK 0x00000002L
+#define IH_STATUS__INPUT_IDLE__SHIFT 0x00000001
+#define IH_STATUS__MC_WR_CLEAN_PENDING_MASK 0x00000100L
+#define IH_STATUS__MC_WR_CLEAN_PENDING__SHIFT 0x00000008
+#define IH_STATUS__MC_WR_CLEAN_STALL_MASK 0x00000200L
+#define IH_STATUS__MC_WR_CLEAN_STALL__SHIFT 0x00000009
+#define IH_STATUS__MC_WR_IDLE_MASK 0x00000040L
+#define IH_STATUS__MC_WR_IDLE__SHIFT 0x00000006
+#define IH_STATUS__MC_WR_STALL_MASK 0x00000080L
+#define IH_STATUS__MC_WR_STALL__SHIFT 0x00000007
+#define IH_STATUS__RB_FULL_DRAIN_MASK 0x00000010L
+#define IH_STATUS__RB_FULL_DRAIN__SHIFT 0x00000004
+#define IH_STATUS__RB_FULL_MASK 0x00000008L
+#define IH_STATUS__RB_FULL__SHIFT 0x00000003
+#define IH_STATUS__RB_IDLE_MASK 0x00000004L
+#define IH_STATUS__RB_IDLE__SHIFT 0x00000002
+#define IH_STATUS__RB_OVERFLOW_MASK 0x00000020L
+#define IH_STATUS__RB_OVERFLOW__SHIFT 0x00000005
+#define KEFUSE0__RESERVED_MASK 0xffffffffL
+#define KEFUSE0__RESERVED__SHIFT 0x00000000
+#define KEFUSE1__RESERVED_MASK 0xffffffffL
+#define KEFUSE1__RESERVED__SHIFT 0x00000000
+#define KEFUSE2__RESERVED_MASK 0xffffffffL
+#define KEFUSE2__RESERVED__SHIFT 0x00000000
+#define KEFUSE3__RESERVED_MASK 0xffffffffL
+#define KEFUSE3__RESERVED__SHIFT 0x00000000
+#define KHFS0__RESERVED_MASK 0xffffffffL
+#define KHFS0__RESERVED__SHIFT 0x00000000
+#define KHFS1__RESERVED_MASK 0xffffffffL
+#define KHFS1__RESERVED__SHIFT 0x00000000
+#define KHFS2__RESERVED_MASK 0xffffffffL
+#define KHFS2__RESERVED__SHIFT 0x00000000
+#define KHFS3__RESERVED_MASK 0xffffffffL
+#define KHFS3__RESERVED__SHIFT 0x00000000
+#define KSESSION0__RESERVED_MASK 0xffffffffL
+#define KSESSION0__RESERVED__SHIFT 0x00000000
+#define KSESSION1__RESERVED_MASK 0xffffffffL
+#define KSESSION1__RESERVED__SHIFT 0x00000000
+#define KSESSION2__RESERVED_MASK 0xffffffffL
+#define KSESSION2__RESERVED__SHIFT 0x00000000
+#define KSESSION3__RESERVED_MASK 0xffffffffL
+#define KSESSION3__RESERVED__SHIFT 0x00000000
+#define KSIG0__RESERVED_MASK 0xffffffffL
+#define KSIG0__RESERVED__SHIFT 0x00000000
+#define KSIG1__RESERVED_MASK 0xffffffffL
+#define KSIG1__RESERVED__SHIFT 0x00000000
+#define KSIG2__RESERVED_MASK 0xffffffffL
+#define KSIG2__RESERVED__SHIFT 0x00000000
+#define KSIG3__RESERVED_MASK 0xffffffffL
+#define KSIG3__RESERVED__SHIFT 0x00000000
+#define LX0__RESERVED_MASK 0xffffffffL
+#define LX0__RESERVED__SHIFT 0x00000000
+#define LX1__RESERVED_MASK 0xffffffffL
+#define LX1__RESERVED__SHIFT 0x00000000
+#define LX2__RESERVED_MASK 0xffffffffL
+#define LX2__RESERVED__SHIFT 0x00000000
+#define LX3__RESERVED_MASK 0xffffffffL
+#define LX3__RESERVED__SHIFT 0x00000000
+#define RINGOSC_MASK__MASK_MASK 0x0000ffffL
+#define RINGOSC_MASK__MASK__SHIFT 0x00000000
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT0_MASK 0x00000007L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT0__SHIFT 0x00000000
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT1_MASK 0x00000038L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT1__SHIFT 0x00000003
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT2_MASK 0x000001c0L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT2__SHIFT 0x00000006
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT3_MASK 0x00000e00L
+#define SEM_MAILBOX_CLIENTCONFIG__CP_CLIENT3__SHIFT 0x00000009
+#define SEM_MAILBOX_CLIENTCONFIG__UVD_CLIENT0_MASK 0x00038000L
+#define SEM_MAILBOX_CLIENTCONFIG__UVD_CLIENT0__SHIFT 0x0000000f
+#define SEM_MAILBOX_CLIENTCONFIG__VCE_CLIENT0_MASK 0x00e00000L
+#define SEM_MAILBOX_CLIENTCONFIG__VCE_CLIENT0__SHIFT 0x00000015
+#define SEM_MAILBOX_CONTROL__HOSTPORT_ENABLE_MASK 0x0000ff00L
+#define SEM_MAILBOX_CONTROL__HOSTPORT_ENABLE__SHIFT 0x00000008
+#define SEM_MAILBOX_CONTROL__SIDEPORT_ENABLE_MASK 0x000000ffL
+#define SEM_MAILBOX_CONTROL__SIDEPORT_ENABLE__SHIFT 0x00000000
+#define SEM_MAILBOX__HOSTPORT_MASK 0x0000ff00L
+#define SEM_MAILBOX__HOSTPORT__SHIFT 0x00000008
+#define SEM_MAILBOX__SIDEPORT_MASK 0x000000ffL
+#define SEM_MAILBOX__SIDEPORT__SHIFT 0x00000000
+#define SEM_MCIF_CONFIG__MC_REQ_SWAP_MASK 0x00000003L
+#define SEM_MCIF_CONFIG__MC_REQ_SWAP__SHIFT 0x00000000
+#define SPU_PORT_STATUS__RESERVED_MASK 0xffffffffL
+#define SPU_PORT_STATUS__RESERVED__SHIFT 0x00000000
+#define SRBM_CAM_DATA__CAM_ADDR_MASK 0x0000ffffL
+#define SRBM_CAM_DATA__CAM_ADDR__SHIFT 0x00000000
+#define SRBM_CAM_DATA__CAM_REMAPADDR_MASK 0xffff0000L
+#define SRBM_CAM_DATA__CAM_REMAPADDR__SHIFT 0x00000010
+#define SRBM_CAM_INDEX__CAM_INDEX_MASK 0x00000007L
+#define SRBM_CAM_INDEX__CAM_INDEX__SHIFT 0x00000000
+#define SRBM_CHIP_REVISION__CHIP_REVISION_MASK 0x000000ffL
+#define SRBM_CHIP_REVISION__CHIP_REVISION__SHIFT 0x00000000
+#define SRBM_CNTL__COMBINE_SYSTEM_MC_MASK 0x00020000L
+#define SRBM_CNTL__COMBINE_SYSTEM_MC__SHIFT 0x00000011
+#define SRBM_CNTL__PWR_REQUEST_HALT_MASK 0x00010000L
+#define SRBM_CNTL__PWR_REQUEST_HALT__SHIFT 0x00000010
+#define SRBM_CNTL__READ_TIMEOUT_MASK 0x000003ffL
+#define SRBM_CNTL__READ_TIMEOUT__SHIFT 0x00000000
+#define SRBM_DEBUG_CNTL__SRBM_DEBUG_INDEX_MASK 0x0000003fL
+#define SRBM_DEBUG_CNTL__SRBM_DEBUG_INDEX__SHIFT 0x00000000
+#define SRBM_DEBUG_DATA__DATA_MASK 0xffffffffL
+#define SRBM_DEBUG_DATA__DATA__SHIFT 0x00000000
+#define SRBM_DEBUG__DISABLE_READ_TIMEOUT_MASK 0x00000002L
+#define SRBM_DEBUG__DISABLE_READ_TIMEOUT__SHIFT 0x00000001
+#define SRBM_DEBUG__IGNORE_RDY_MASK 0x00000001L
+#define SRBM_DEBUG__IGNORE_RDY__SHIFT 0x00000000
+#define SRBM_DEBUG__MC_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000100L
+#define SRBM_DEBUG__MC_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000008
+#define SRBM_DEBUG_SNAPSHOT__BIF_RDY_MASK 0x00000080L
+#define SRBM_DEBUG_SNAPSHOT__BIF_RDY__SHIFT 0x00000007
+#define SRBM_DEBUG_SNAPSHOT__DC_RDY_MASK 0x00000040L
+#define SRBM_DEBUG_SNAPSHOT__DC_RDY__SHIFT 0x00000006
+#define SRBM_DEBUG__SNAPSHOT_FREE_CNTRS_MASK 0x00000004L
+#define SRBM_DEBUG__SNAPSHOT_FREE_CNTRS__SHIFT 0x00000002
+#define SRBM_DEBUG_SNAPSHOT__GRBM_RDY_MASK 0x00000020L
+#define SRBM_DEBUG_SNAPSHOT__GRBM_RDY__SHIFT 0x00000005
+#define SRBM_DEBUG_SNAPSHOT__MCB_RDY_MASK 0x00000001L
+#define SRBM_DEBUG_SNAPSHOT__MCB_RDY__SHIFT 0x00000000
+#define SRBM_DEBUG_SNAPSHOT__MCC0_RDY_MASK 0x10000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC0_RDY__SHIFT 0x0000001c
+#define SRBM_DEBUG_SNAPSHOT__MCC1_RDY_MASK 0x08000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC1_RDY__SHIFT 0x0000001b
+#define SRBM_DEBUG_SNAPSHOT__MCC2_RDY_MASK 0x04000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC2_RDY__SHIFT 0x0000001a
+#define SRBM_DEBUG_SNAPSHOT__MCC3_RDY_MASK 0x02000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC3_RDY__SHIFT 0x00000019
+#define SRBM_DEBUG_SNAPSHOT__MCC4_RDY_MASK 0x01000000L
+#define SRBM_DEBUG_SNAPSHOT__MCC4_RDY__SHIFT 0x00000018
+#define SRBM_DEBUG_SNAPSHOT__MCC5_RDY_MASK 0x00800000L
+#define SRBM_DEBUG_SNAPSHOT__MCC5_RDY__SHIFT 0x00000017
+#define SRBM_DEBUG_SNAPSHOT__MCC6_RDY_MASK 0x00400000L
+#define SRBM_DEBUG_SNAPSHOT__MCC6_RDY__SHIFT 0x00000016
+#define SRBM_DEBUG_SNAPSHOT__MCC7_RDY_MASK 0x00200000L
+#define SRBM_DEBUG_SNAPSHOT__MCC7_RDY__SHIFT 0x00000015
+#define SRBM_DEBUG_SNAPSHOT__MCD0_RDY_MASK 0x00100000L
+#define SRBM_DEBUG_SNAPSHOT__MCD0_RDY__SHIFT 0x00000014
+#define SRBM_DEBUG_SNAPSHOT__MCD1_RDY_MASK 0x00080000L
+#define SRBM_DEBUG_SNAPSHOT__MCD1_RDY__SHIFT 0x00000013
+#define SRBM_DEBUG_SNAPSHOT__MCD2_RDY_MASK 0x00040000L
+#define SRBM_DEBUG_SNAPSHOT__MCD2_RDY__SHIFT 0x00000012
+#define SRBM_DEBUG_SNAPSHOT__MCD3_RDY_MASK 0x00020000L
+#define SRBM_DEBUG_SNAPSHOT__MCD3_RDY__SHIFT 0x00000011
+#define SRBM_DEBUG_SNAPSHOT__MCD4_RDY_MASK 0x00010000L
+#define SRBM_DEBUG_SNAPSHOT__MCD4_RDY__SHIFT 0x00000010
+#define SRBM_DEBUG_SNAPSHOT__MCD5_RDY_MASK 0x00008000L
+#define SRBM_DEBUG_SNAPSHOT__MCD5_RDY__SHIFT 0x0000000f
+#define SRBM_DEBUG_SNAPSHOT__MCD6_RDY_MASK 0x00004000L
+#define SRBM_DEBUG_SNAPSHOT__MCD6_RDY__SHIFT 0x0000000e
+#define SRBM_DEBUG_SNAPSHOT__MCD7_RDY_MASK 0x00002000L
+#define SRBM_DEBUG_SNAPSHOT__MCD7_RDY__SHIFT 0x0000000d
+#define SRBM_DEBUG_SNAPSHOT__ORB_RDY_MASK 0x00001000L
+#define SRBM_DEBUG_SNAPSHOT__ORB_RDY__SHIFT 0x0000000c
+#define SRBM_DEBUG_SNAPSHOT__REGBB_RDY_MASK 0x00000800L
+#define SRBM_DEBUG_SNAPSHOT__REGBB_RDY__SHIFT 0x0000000b
+#define SRBM_DEBUG_SNAPSHOT__UVD_RDY_MASK 0x00000200L
+#define SRBM_DEBUG_SNAPSHOT__UVD_RDY__SHIFT 0x00000009
+#define SRBM_DEBUG_SNAPSHOT__VCE_RDY_MASK 0x20000000L
+#define SRBM_DEBUG_SNAPSHOT__VCE_RDY__SHIFT 0x0000001d
+#define SRBM_DEBUG_SNAPSHOT__XDMA_RDY_MASK 0x00000100L
+#define SRBM_DEBUG_SNAPSHOT__XDMA_RDY__SHIFT 0x00000008
+#define SRBM_DEBUG_SNAPSHOT__XSP_RDY_MASK 0x00000400L
+#define SRBM_DEBUG_SNAPSHOT__XSP_RDY__SHIFT 0x0000000a
+#define SRBM_DEBUG__SYS_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000010L
+#define SRBM_DEBUG__SYS_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000004
+#define SRBM_DEBUG__UVD_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000040L
+#define SRBM_DEBUG__UVD_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000006
+#define SRBM_DEBUG__VCE_CLOCK_DOMAIN_OVERRIDE_MASK 0x00000020L
+#define SRBM_DEBUG__VCE_CLOCK_DOMAIN_OVERRIDE__SHIFT 0x00000005
+#define SRBM_GFX_CNTL__VMID_MASK 0x000000f0L
+#define SRBM_GFX_CNTL__VMID__SHIFT 0x00000004
+#define SRBM_INT_ACK__RDERR_INT_ACK_MASK 0x00000001L
+#define SRBM_INT_ACK__RDERR_INT_ACK__SHIFT 0x00000000
+#define SRBM_INT_CNTL__RDERR_INT_MASK_MASK 0x00000001L
+#define SRBM_INT_CNTL__RDERR_INT_MASK__SHIFT 0x00000000
+#define SRBM_INT_STATUS__RDERR_INT_STAT_MASK 0x00000001L
+#define SRBM_INT_STATUS__RDERR_INT_STAT__SHIFT 0x00000000
+#define SRBM_MC_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_MC_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_MC_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_MC_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER0_HI__PERF_COUNT0_HI_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER0_HI__PERF_COUNT0_HI__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER0_LO__PERF_COUNT0_LO_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER0_LO__PERF_COUNT0_LO__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER0_SELECT__PERF_SEL_MASK 0x0000003fL
+#define SRBM_PERFCOUNTER0_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER1_HI__PERF_COUNT1_HI_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER1_HI__PERF_COUNT1_HI__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER1_LO__PERF_COUNT1_LO_MASK 0xffffffffL
+#define SRBM_PERFCOUNTER1_LO__PERF_COUNT1_LO__SHIFT 0x00000000
+#define SRBM_PERFCOUNTER1_SELECT__PERF_SEL_MASK 0x0000003fL
+#define SRBM_PERFCOUNTER1_SELECT__PERF_SEL__SHIFT 0x00000000
+#define SRBM_PERFMON_CNTL__PERFMON_ENABLE_MODE_MASK 0x00000300L
+#define SRBM_PERFMON_CNTL__PERFMON_ENABLE_MODE__SHIFT 0x00000008
+#define SRBM_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE_MASK 0x00000400L
+#define SRBM_PERFMON_CNTL__PERFMON_SAMPLE_ENABLE__SHIFT 0x0000000a
+#define SRBM_PERFMON_CNTL__PERFMON_STATE_MASK 0x0000000fL
+#define SRBM_PERFMON_CNTL__PERFMON_STATE__SHIFT 0x00000000
+#define SRBM_READ_ERROR__READ_ADDRESS_MASK 0x0003fffcL
+#define SRBM_READ_ERROR__READ_ADDRESS__SHIFT 0x00000002
+#define SRBM_READ_ERROR__READ_ERROR_MASK 0x80000000L
+#define SRBM_READ_ERROR__READ_ERROR__SHIFT 0x0000001f
+#define SRBM_READ_ERROR__READ_REQUESTER_GRBM_MASK 0x02000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_GRBM__SHIFT 0x00000019
+#define SRBM_READ_ERROR__READ_REQUESTER_HI_MASK 0x01000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_HI__SHIFT 0x00000018
+#define SRBM_READ_ERROR__READ_REQUESTER_SMU_MASK 0x04000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_SMU__SHIFT 0x0000001a
+#define SRBM_READ_ERROR__READ_REQUESTER_TST_MASK 0x00400000L
+#define SRBM_READ_ERROR__READ_REQUESTER_TST__SHIFT 0x00000016
+#define SRBM_READ_ERROR__READ_REQUESTER_UVD_MASK 0x20000000L
+#define SRBM_READ_ERROR__READ_REQUESTER_UVD__SHIFT 0x0000001d
+#define SRBM_READ_ERROR__READ_REQUESTER_VCE_MASK 0x00100000L
+#define SRBM_READ_ERROR__READ_REQUESTER_VCE__SHIFT 0x00000014
+#define SRBM_SOFT_RESET__SOFT_RESET_BIF_MASK 0x00000002L
+#define SRBM_SOFT_RESET__SOFT_RESET_BIF__SHIFT 0x00000001
+#define SRBM_SOFT_RESET__SOFT_RESET_DC_MASK 0x00000020L
+#define SRBM_SOFT_RESET__SOFT_RESET_DC__SHIFT 0x00000005
+#define SRBM_SOFT_RESET__SOFT_RESET_GRBM_MASK 0x00000100L
+#define SRBM_SOFT_RESET__SOFT_RESET_GRBM__SHIFT 0x00000008
+#define SRBM_SOFT_RESET__SOFT_RESET_HDP_MASK 0x00000200L
+#define SRBM_SOFT_RESET__SOFT_RESET_HDP__SHIFT 0x00000009
+#define SRBM_SOFT_RESET__SOFT_RESET_IH_MASK 0x00000400L
+#define SRBM_SOFT_RESET__SOFT_RESET_IH__SHIFT 0x0000000a
+#define SRBM_SOFT_RESET__SOFT_RESET_MC_MASK 0x00000800L
+#define SRBM_SOFT_RESET__SOFT_RESET_MC__SHIFT 0x0000000b
+#define SRBM_SOFT_RESET__SOFT_RESET_ORB_MASK 0x00800000L
+#define SRBM_SOFT_RESET__SOFT_RESET_ORB__SHIFT 0x00000017
+#define SRBM_SOFT_RESET__SOFT_RESET_REGBB_MASK 0x00400000L
+#define SRBM_SOFT_RESET__SOFT_RESET_REGBB__SHIFT 0x00000016
+#define SRBM_SOFT_RESET__SOFT_RESET_ROM_MASK 0x00004000L
+#define SRBM_SOFT_RESET__SOFT_RESET_ROM__SHIFT 0x0000000e
+#define SRBM_SOFT_RESET__SOFT_RESET_SEM_MASK 0x00008000L
+#define SRBM_SOFT_RESET__SOFT_RESET_SEM__SHIFT 0x0000000f
+#define SRBM_SOFT_RESET__SOFT_RESET_TST_MASK 0x00200000L
+#define SRBM_SOFT_RESET__SOFT_RESET_TST__SHIFT 0x00000015
+#define SRBM_SOFT_RESET__SOFT_RESET_UVD_MASK 0x00040000L
+#define SRBM_SOFT_RESET__SOFT_RESET_UVD__SHIFT 0x00000012
+#define SRBM_SOFT_RESET__SOFT_RESET_VCE_MASK 0x01000000L
+#define SRBM_SOFT_RESET__SOFT_RESET_VCE__SHIFT 0x00000018
+#define SRBM_SOFT_RESET__SOFT_RESET_VMC_MASK 0x00020000L
+#define SRBM_SOFT_RESET__SOFT_RESET_VMC__SHIFT 0x00000011
+#define SRBM_SOFT_RESET__SOFT_RESET_XDMA_MASK 0x02000000L
+#define SRBM_SOFT_RESET__SOFT_RESET_XDMA__SHIFT 0x00000019
+#define SRBM_SOFT_RESET__SOFT_RESET_XSP_MASK 0x00080000L
+#define SRBM_SOFT_RESET__SOFT_RESET_XSP__SHIFT 0x00000013
+#define SRBM_STATUS2__TST_RQ_PENDING_MASK 0x00000002L
+#define SRBM_STATUS2__TST_RQ_PENDING__SHIFT 0x00000001
+#define SRBM_STATUS2__VCE_BUSY_MASK 0x00000080L
+#define SRBM_STATUS2__VCE_BUSY__SHIFT 0x00000007
+#define SRBM_STATUS2__VCE_RQ_PENDING_MASK 0x00000008L
+#define SRBM_STATUS2__VCE_RQ_PENDING__SHIFT 0x00000003
+#define SRBM_STATUS2__XDMA_BUSY_MASK 0x00000100L
+#define SRBM_STATUS2__XDMA_BUSY__SHIFT 0x00000008
+#define SRBM_STATUS2__XSP_BUSY_MASK 0x00000010L
+#define SRBM_STATUS2__XSP_BUSY__SHIFT 0x00000004
+#define SRBM_STATUS__BIF_BUSY_MASK 0x20000000L
+#define SRBM_STATUS__BIF_BUSY__SHIFT 0x0000001d
+#define SRBM_STATUS__GRBM_RQ_PENDING_MASK 0x00000020L
+#define SRBM_STATUS__GRBM_RQ_PENDING__SHIFT 0x00000005
+#define SRBM_STATUS__HI_RQ_PENDING_MASK 0x00000040L
+#define SRBM_STATUS__HI_RQ_PENDING__SHIFT 0x00000006
+#define SRBM_STATUS__IH_BUSY_MASK 0x00020000L
+#define SRBM_STATUS__IH_BUSY__SHIFT 0x00000011
+#define SRBM_STATUS__IO_EXTERN_SIGNAL_MASK 0x00000080L
+#define SRBM_STATUS__IO_EXTERN_SIGNAL__SHIFT 0x00000007
+#define SRBM_STATUS__MCB_BUSY_MASK 0x00000200L
+#define SRBM_STATUS__MCB_BUSY__SHIFT 0x00000009
+#define SRBM_STATUS__MCB_NON_DISPLAY_BUSY_MASK 0x00000400L
+#define SRBM_STATUS__MCB_NON_DISPLAY_BUSY__SHIFT 0x0000000a
+#define SRBM_STATUS__MCC_BUSY_MASK 0x00000800L
+#define SRBM_STATUS__MCC_BUSY__SHIFT 0x0000000b
+#define SRBM_STATUS__MCD_BUSY_MASK 0x00001000L
+#define SRBM_STATUS__MCD_BUSY__SHIFT 0x0000000c
+#define SRBM_STATUS__SEM_BUSY_MASK 0x00004000L
+#define SRBM_STATUS__SEM_BUSY__SHIFT 0x0000000e
+#define SRBM_STATUS__SMU_RQ_PENDING_MASK 0x00000010L
+#define SRBM_STATUS__SMU_RQ_PENDING__SHIFT 0x00000004
+#define SRBM_STATUS__UVD_BUSY_MASK 0x00080000L
+#define SRBM_STATUS__UVD_BUSY__SHIFT 0x00000013
+#define SRBM_STATUS__UVD_RQ_PENDING_MASK 0x00000002L
+#define SRBM_STATUS__UVD_RQ_PENDING__SHIFT 0x00000001
+#define SRBM_STATUS__VMC_BUSY_MASK 0x00000100L
+#define SRBM_STATUS__VMC_BUSY__SHIFT 0x00000008
+#define SRBM_SYS_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_SYS_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_SYS_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_SYS_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define SRBM_UVD_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_UVD_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_UVD_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_UVD_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define SRBM_VCE_CLKEN_CNTL__POST_DELAY_CNT_MASK 0x00001f00L
+#define SRBM_VCE_CLKEN_CNTL__POST_DELAY_CNT__SHIFT 0x00000008
+#define SRBM_VCE_CLKEN_CNTL__PREFIX_DELAY_CNT_MASK 0x0000000fL
+#define SRBM_VCE_CLKEN_CNTL__PREFIX_DELAY_CNT__SHIFT 0x00000000
+#define UVD_CONFIG__UVD_RDREQ_URG_MASK 0x00000f00L
+#define UVD_CONFIG__UVD_RDREQ_URG__SHIFT 0x00000008
+#define UVD_CONFIG__UVD_REQ_TRAN_MASK 0x00010000L
+#define UVD_CONFIG__UVD_REQ_TRAN__SHIFT 0x00000010
+#define VCE_CONFIG__VCE_RDREQ_URG_MASK 0x00000f00L
+#define VCE_CONFIG__VCE_RDREQ_URG__SHIFT 0x00000008
+#define VCE_CONFIG__VCE_REQ_TRAN_MASK 0x00010000L
+#define VCE_CONFIG__VCE_REQ_TRAN__SHIFT 0x00000010
+#define XDMA_MSTR_CNTL__XDMA_MSTR_LAT_TEST_EN_MASK 0x00080000L
+#define XDMA_MSTR_CNTL__XDMA_MSTR_LAT_TEST_EN__SHIFT 0x00000013
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT_ENABLE_MASK 0x80000000L
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT_ENABLE__SHIFT 0x0000001f
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT_MASK 0x0000ffffL
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_COUNT__SHIFT 0x00000000
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_THRESHOLD_MASK 0x3fff0000L
+#define XDMA_MSTR_MEM_OVERFLOW_CNTL__XDMA_MSTR_OVERFLOW_THRESHOLD__SHIFT 0x00000010
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,148 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 SMU_6_0_D_H
+#define SMU_6_0_D_H
+
+#define ixLCAC_MC0_CNTL 0x011C
+#define ixLCAC_MC0_OVR_SEL 0x011D
+#define ixLCAC_MC0_OVR_VAL 0x011E
+#define ixLCAC_MC1_CNTL 0x011F
+#define ixLCAC_MC1_OVR_SEL 0x0120
+#define ixLCAC_MC1_OVR_VAL 0x0121
+#define ixLCAC_MC2_CNTL 0x0122
+#define ixLCAC_MC2_OVR_SEL 0x0123
+#define ixLCAC_MC2_OVR_VAL 0x0124
+#define ixLCAC_MC3_CNTL 0x0125
+#define ixLCAC_MC3_OVR_SEL 0x0126
+#define ixLCAC_MC3_OVR_VAL 0x0127
+#define ixLCAC_MC4_CNTL 0x0128
+#define ixLCAC_MC4_OVR_SEL 0x0129
+#define ixLCAC_MC4_OVR_VAL 0x012A
+#define ixLCAC_MC5_CNTL 0x012B
+#define ixLCAC_MC5_OVR_SEL 0x012C
+#define ixLCAC_MC5_OVR_VAL 0x012D
+#define ixSMC_PC_C 0x80000370
+#define ixTHM_TMON0_DEBUG 0x03F0
+#define ixTHM_TMON0_INT_DATA 0x0380
+#define ixTHM_TMON0_RDIL0_DATA 0x0300
+#define ixTHM_TMON0_RDIL10_DATA 0x030A
+#define ixTHM_TMON0_RDIL11_DATA 0x030B
+#define ixTHM_TMON0_RDIL12_DATA 0x030C
+#define ixTHM_TMON0_RDIL13_DATA 0x030D
+#define ixTHM_TMON0_RDIL14_DATA 0x030E
+#define ixTHM_TMON0_RDIL15_DATA 0x030F
+#define ixTHM_TMON0_RDIL1_DATA 0x0301
+#define ixTHM_TMON0_RDIL2_DATA 0x0302
+#define ixTHM_TMON0_RDIL3_DATA 0x0303
+#define ixTHM_TMON0_RDIL4_DATA 0x0304
+#define ixTHM_TMON0_RDIL5_DATA 0x0305
+#define ixTHM_TMON0_RDIL6_DATA 0x0306
+#define ixTHM_TMON0_RDIL7_DATA 0x0307
+#define ixTHM_TMON0_RDIL8_DATA 0x0308
+#define ixTHM_TMON0_RDIL9_DATA 0x0309
+#define ixTHM_TMON0_RDIR0_DATA 0x0310
+#define ixTHM_TMON0_RDIR10_DATA 0x031A
+#define ixTHM_TMON0_RDIR11_DATA 0x031B
+#define ixTHM_TMON0_RDIR12_DATA 0x031C
+#define ixTHM_TMON0_RDIR13_DATA 0x031D
+#define ixTHM_TMON0_RDIR14_DATA 0x031E
+#define ixTHM_TMON0_RDIR15_DATA 0x031F
+#define ixTHM_TMON0_RDIR1_DATA 0x0311
+#define ixTHM_TMON0_RDIR2_DATA 0x0312
+#define ixTHM_TMON0_RDIR3_DATA 0x0313
+#define ixTHM_TMON0_RDIR4_DATA 0x0314
+#define ixTHM_TMON0_RDIR5_DATA 0x0315
+#define ixTHM_TMON0_RDIR6_DATA 0x0316
+#define ixTHM_TMON0_RDIR7_DATA 0x0317
+#define ixTHM_TMON0_RDIR8_DATA 0x0318
+#define ixTHM_TMON0_RDIR9_DATA 0x0319
+#define ixTHM_TMON1_DEBUG 0x03F1
+#define ixTHM_TMON1_INT_DATA 0x0381
+#define ixTHM_TMON1_RDIL0_DATA 0x0320
+#define ixTHM_TMON1_RDIL10_DATA 0x032A
+#define ixTHM_TMON1_RDIL11_DATA 0x032B
+#define ixTHM_TMON1_RDIL12_DATA 0x032C
+#define ixTHM_TMON1_RDIL13_DATA 0x032D
+#define ixTHM_TMON1_RDIL14_DATA 0x032E
+#define ixTHM_TMON1_RDIL15_DATA 0x032F
+#define ixTHM_TMON1_RDIL1_DATA 0x0321
+#define ixTHM_TMON1_RDIL2_DATA 0x0322
+#define ixTHM_TMON1_RDIL3_DATA 0x0323
+#define ixTHM_TMON1_RDIL4_DATA 0x0324
+#define ixTHM_TMON1_RDIL5_DATA 0x0325
+#define ixTHM_TMON1_RDIL6_DATA 0x0326
+#define ixTHM_TMON1_RDIL7_DATA 0x0327
+#define ixTHM_TMON1_RDIL8_DATA 0x0328
+#define ixTHM_TMON1_RDIL9_DATA 0x0329
+#define ixTHM_TMON1_RDIR0_DATA 0x0330
+#define ixTHM_TMON1_RDIR10_DATA 0x033A
+#define ixTHM_TMON1_RDIR11_DATA 0x033B
+#define ixTHM_TMON1_RDIR12_DATA 0x033C
+#define ixTHM_TMON1_RDIR13_DATA 0x033D
+#define ixTHM_TMON1_RDIR14_DATA 0x033E
+#define ixTHM_TMON1_RDIR15_DATA 0x033F
+#define ixTHM_TMON1_RDIR1_DATA 0x0331
+#define ixTHM_TMON1_RDIR2_DATA 0x0332
+#define ixTHM_TMON1_RDIR3_DATA 0x0333
+#define ixTHM_TMON1_RDIR4_DATA 0x0334
+#define ixTHM_TMON1_RDIR5_DATA 0x0335
+#define ixTHM_TMON1_RDIR6_DATA 0x0336
+#define ixTHM_TMON1_RDIR7_DATA 0x0337
+#define ixTHM_TMON1_RDIR8_DATA 0x0338
+#define ixTHM_TMON1_RDIR9_DATA 0x0339
+#define mmGPIOPAD_A 0x05E7
+#define mmGPIOPAD_EN 0x05E8
+#define mmGPIOPAD_EXTERN_TRIG_CNTL 0x05F1
+#define mmGPIOPAD_INT_EN 0x05EE
+#define mmGPIOPAD_INT_POLARITY 0x05F0
+#define mmGPIOPAD_INT_STAT 0x05EC
+#define mmGPIOPAD_INT_STAT_AK 0x05ED
+#define mmGPIOPAD_INT_STAT_EN 0x05EB
+#define mmGPIOPAD_INT_TYPE 0x05EF
+#define mmGPIOPAD_MASK 0x05E6
+#define mmGPIOPAD_PD_EN 0x05F4
+#define mmGPIOPAD_PINSTRAPS 0x05EA
+#define mmGPIOPAD_PU_EN 0x05F3
+#define mmGPIOPAD_RCVR_SEL 0x05F2
+#define mmGPIOPAD_STRENGTH 0x05E5
+#define mmGPIOPAD_SW_INT_STAT 0x05E4
+#define mmGPIOPAD_Y 0x05E9
+#define mmSMC_IND_ACCESS_CNTL 0x008A
+#define mmSMC_IND_DATA_0 0x0081
+#define mmSMC_IND_DATA 0x0081
+#define mmSMC_IND_DATA_1 0x0083
+#define mmSMC_IND_DATA_2 0x0085
+#define mmSMC_IND_DATA_3 0x0087
+#define mmSMC_IND_INDEX_0 0x0080
+#define mmSMC_IND_INDEX 0x0080
+#define mmSMC_IND_INDEX_1 0x0082
+#define mmSMC_IND_INDEX_2 0x0084
+#define mmSMC_IND_INDEX_3 0x0086
+#define mmSMC_MESSAGE_0 0x008B
+#define mmSMC_MESSAGE_1 0x008D
+#define mmSMC_MESSAGE_2 0x008F
+#define mmSMC_RESP_0 0x008C
+#define mmSMC_RESP_1 0x008E
+#define mmSMC_RESP_2 0x0090
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_6_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,715 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 SMU_6_0_SH_MASK_H
+#define SMU_6_0_SH_MASK_H
+
+#define CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV_MASK 0x03ffffffL
+#define CG_SPLL_FUNC_CNTL_3__SPLL_FB_DIV__SHIFT 0x00000000
+#define CG_SPLL_FUNC_CNTL__SPLL_REF_DIV_MASK 0x000003f0L
+#define CG_SPLL_FUNC_CNTL__SPLL_REF_DIV__SHIFT 0x00000004
+#define GPIOPAD_A__GPIO_A_MASK 0x7fffffffL
+#define GPIOPAD_A__GPIO_A__SHIFT 0x00000000
+#define GPIOPAD_EN__GPIO_EN_MASK 0x7fffffffL
+#define GPIOPAD_EN__GPIO_EN__SHIFT 0x00000000
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_CLR_MASK 0x00000020L
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_CLR__SHIFT 0x00000005
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_READ_MASK 0x00000040L
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_READ__SHIFT 0x00000006
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_SEL_MASK 0x0000001fL
+#define GPIOPAD_EXTERN_TRIG_CNTL__EXTERN_TRIG_SEL__SHIFT 0x00000000
+#define GPIOPAD_INT_EN__GPIO_INT_EN_MASK 0x1fffffffL
+#define GPIOPAD_INT_EN__GPIO_INT_EN__SHIFT 0x00000000
+#define GPIOPAD_INT_EN__SW_INITIATED_INT_EN_MASK 0x80000000L
+#define GPIOPAD_INT_EN__SW_INITIATED_INT_EN__SHIFT 0x0000001f
+#define GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY_MASK 0x1fffffffL
+#define GPIOPAD_INT_POLARITY__GPIO_INT_POLARITY__SHIFT 0x00000000
+#define GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY_MASK 0x80000000L
+#define GPIOPAD_INT_POLARITY__SW_INITIATED_INT_POLARITY__SHIFT 0x0000001f
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0_MASK 0x00000001L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_0__SHIFT 0x00000000
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10_MASK 0x00000400L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_10__SHIFT 0x0000000a
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11_MASK 0x00000800L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_11__SHIFT 0x0000000b
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12_MASK 0x00001000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_12__SHIFT 0x0000000c
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13_MASK 0x00002000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_13__SHIFT 0x0000000d
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14_MASK 0x00004000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_14__SHIFT 0x0000000e
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15_MASK 0x00008000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_15__SHIFT 0x0000000f
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16_MASK 0x00010000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_16__SHIFT 0x00000010
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17_MASK 0x00020000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_17__SHIFT 0x00000011
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18_MASK 0x00040000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_18__SHIFT 0x00000012
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19_MASK 0x00080000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_19__SHIFT 0x00000013
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1_MASK 0x00000002L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_1__SHIFT 0x00000001
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20_MASK 0x00100000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_20__SHIFT 0x00000014
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21_MASK 0x00200000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_21__SHIFT 0x00000015
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22_MASK 0x00400000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_22__SHIFT 0x00000016
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23_MASK 0x00800000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_23__SHIFT 0x00000017
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24_MASK 0x01000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_24__SHIFT 0x00000018
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25_MASK 0x02000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_25__SHIFT 0x00000019
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26_MASK 0x04000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_26__SHIFT 0x0000001a
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27_MASK 0x08000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_27__SHIFT 0x0000001b
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28_MASK 0x10000000L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_28__SHIFT 0x0000001c
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2_MASK 0x00000004L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_2__SHIFT 0x00000002
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3_MASK 0x00000008L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_3__SHIFT 0x00000003
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4_MASK 0x00000010L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_4__SHIFT 0x00000004
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5_MASK 0x00000020L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_5__SHIFT 0x00000005
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6_MASK 0x00000040L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_6__SHIFT 0x00000006
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7_MASK 0x00000080L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_7__SHIFT 0x00000007
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8_MASK 0x00000100L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_8__SHIFT 0x00000008
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9_MASK 0x00000200L
+#define GPIOPAD_INT_STAT_AK__GPIO_INT_STAT_AK_9__SHIFT 0x00000009
+#define GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK_MASK 0x80000000L
+#define GPIOPAD_INT_STAT_AK__SW_INITIATED_INT_STAT_AK__SHIFT 0x0000001f
+#define GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN_MASK 0x1fffffffL
+#define GPIOPAD_INT_STAT_EN__GPIO_INT_STAT_EN__SHIFT 0x00000000
+#define GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN_MASK 0x80000000L
+#define GPIOPAD_INT_STAT_EN__SW_INITIATED_INT_STAT_EN__SHIFT 0x0000001f
+#define GPIOPAD_INT_STAT__GPIO_INT_STAT_MASK 0x1fffffffL
+#define GPIOPAD_INT_STAT__GPIO_INT_STAT__SHIFT 0x00000000
+#define GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT_MASK 0x80000000L
+#define GPIOPAD_INT_STAT__SW_INITIATED_INT_STAT__SHIFT 0x0000001f
+#define GPIOPAD_INT_TYPE__GPIO_INT_TYPE_MASK 0x1fffffffL
+#define GPIOPAD_INT_TYPE__GPIO_INT_TYPE__SHIFT 0x00000000
+#define GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE_MASK 0x80000000L
+#define GPIOPAD_INT_TYPE__SW_INITIATED_INT_TYPE__SHIFT 0x0000001f
+#define GPIOPAD_MASK__GPIO_MASK_MASK 0x7fffffffL
+#define GPIOPAD_MASK__GPIO_MASK__SHIFT 0x00000000
+#define GPIOPAD_PD_EN__GPIO_PD_EN_MASK 0x7fffffffL
+#define GPIOPAD_PD_EN__GPIO_PD_EN__SHIFT 0x00000000
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0_MASK 0x00000001L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_0__SHIFT 0x00000000
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10_MASK 0x00000400L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_10__SHIFT 0x0000000a
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11_MASK 0x00000800L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_11__SHIFT 0x0000000b
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12_MASK 0x00001000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_12__SHIFT 0x0000000c
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13_MASK 0x00002000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_13__SHIFT 0x0000000d
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14_MASK 0x00004000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_14__SHIFT 0x0000000e
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15_MASK 0x00008000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_15__SHIFT 0x0000000f
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16_MASK 0x00010000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_16__SHIFT 0x00000010
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17_MASK 0x00020000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_17__SHIFT 0x00000011
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18_MASK 0x00040000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_18__SHIFT 0x00000012
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19_MASK 0x00080000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_19__SHIFT 0x00000013
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1_MASK 0x00000002L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_1__SHIFT 0x00000001
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20_MASK 0x00100000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_20__SHIFT 0x00000014
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21_MASK 0x00200000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_21__SHIFT 0x00000015
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22_MASK 0x00400000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_22__SHIFT 0x00000016
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23_MASK 0x00800000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_23__SHIFT 0x00000017
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24_MASK 0x01000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_24__SHIFT 0x00000018
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25_MASK 0x02000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_25__SHIFT 0x00000019
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26_MASK 0x04000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_26__SHIFT 0x0000001a
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27_MASK 0x08000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_27__SHIFT 0x0000001b
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28_MASK 0x10000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_28__SHIFT 0x0000001c
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29_MASK 0x20000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_29__SHIFT 0x0000001d
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2_MASK 0x00000004L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_2__SHIFT 0x00000002
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30_MASK 0x40000000L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_30__SHIFT 0x0000001e
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3_MASK 0x00000008L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_3__SHIFT 0x00000003
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4_MASK 0x00000010L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_4__SHIFT 0x00000004
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5_MASK 0x00000020L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_5__SHIFT 0x00000005
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6_MASK 0x00000040L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_6__SHIFT 0x00000006
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7_MASK 0x00000080L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_7__SHIFT 0x00000007
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8_MASK 0x00000100L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_8__SHIFT 0x00000008
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9_MASK 0x00000200L
+#define GPIOPAD_PINSTRAPS__GPIO_PINSTRAP_9__SHIFT 0x00000009
+#define GPIOPAD_PU_EN__GPIO_PU_EN_MASK 0x7fffffffL
+#define GPIOPAD_PU_EN__GPIO_PU_EN__SHIFT 0x00000000
+#define GPIOPAD_RCVR_SEL__GPIO_RCVR_SEL_MASK 0x7fffffffL
+#define GPIOPAD_RCVR_SEL__GPIO_RCVR_SEL__SHIFT 0x00000000
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SN_MASK 0x0000000fL
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SN__SHIFT 0x00000000
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SP_MASK 0x000000f0L
+#define GPIOPAD_STRENGTH__GPIO_STRENGTH_SP__SHIFT 0x00000004
+#define GPIOPAD_SW_INT_STAT__SW_INT_STAT_MASK 0x00000001L
+#define GPIOPAD_SW_INT_STAT__SW_INT_STAT__SHIFT 0x00000000
+#define GPIOPAD_Y__GPIO_Y_MASK 0x7fffffffL
+#define GPIOPAD_Y__GPIO_Y__SHIFT 0x00000000
+#define LCAC_MC0_CNTL__MC0_ENABLE_MASK 0x00000001L
+#define LCAC_MC0_CNTL__MC0_ENABLE__SHIFT 0x00000000
+#define LCAC_MC0_CNTL__MC0_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC0_CNTL__MC0_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC0_OVR_SEL__MC0_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC0_OVR_SEL__MC0_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC0_OVR_VAL__MC0_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC0_OVR_VAL__MC0_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC1_CNTL__MC1_ENABLE_MASK 0x00000001L
+#define LCAC_MC1_CNTL__MC1_ENABLE__SHIFT 0x00000000
+#define LCAC_MC1_CNTL__MC1_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC1_CNTL__MC1_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC1_OVR_SEL__MC1_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC1_OVR_SEL__MC1_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC1_OVR_VAL__MC1_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC1_OVR_VAL__MC1_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC2_CNTL__MC2_ENABLE_MASK 0x00000001L
+#define LCAC_MC2_CNTL__MC2_ENABLE__SHIFT 0x00000000
+#define LCAC_MC2_CNTL__MC2_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC2_CNTL__MC2_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC2_OVR_SEL__MC2_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC2_OVR_SEL__MC2_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC2_OVR_VAL__MC2_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC2_OVR_VAL__MC2_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC3_CNTL__MC3_ENABLE_MASK 0x00000001L
+#define LCAC_MC3_CNTL__MC3_ENABLE__SHIFT 0x00000000
+#define LCAC_MC3_CNTL__MC3_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC3_CNTL__MC3_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC3_OVR_SEL__MC3_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC3_OVR_SEL__MC3_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC3_OVR_VAL__MC3_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC3_OVR_VAL__MC3_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC4_CNTL__MC4_ENABLE_MASK 0x00000001L
+#define LCAC_MC4_CNTL__MC4_ENABLE__SHIFT 0x00000000
+#define LCAC_MC4_CNTL__MC4_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC4_CNTL__MC4_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC4_OVR_SEL__MC4_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC4_OVR_SEL__MC4_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC4_OVR_VAL__MC4_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC4_OVR_VAL__MC4_OVR_VAL__SHIFT 0x00000000
+#define LCAC_MC5_CNTL__MC5_ENABLE_MASK 0x00000001L
+#define LCAC_MC5_CNTL__MC5_ENABLE__SHIFT 0x00000000
+#define LCAC_MC5_CNTL__MC5_THRESHOLD_MASK 0x0001fffeL
+#define LCAC_MC5_CNTL__MC5_THRESHOLD__SHIFT 0x00000001
+#define LCAC_MC5_OVR_SEL__MC5_OVR_SEL_MASK 0xffffffffL
+#define LCAC_MC5_OVR_SEL__MC5_OVR_SEL__SHIFT 0x00000000
+#define LCAC_MC5_OVR_VAL__MC5_OVR_VAL_MASK 0xffffffffL
+#define LCAC_MC5_OVR_VAL__MC5_OVR_VAL__SHIFT 0x00000000
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK 0x00000001L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0__SHIFT 0x00000000
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_1_MASK 0x00000100L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_1__SHIFT 0x00000008
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_2_MASK 0x00010000L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_2__SHIFT 0x00000010
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_3_MASK 0x01000000L
+#define SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_3__SHIFT 0x00000018
+#define SMC_IND_DATA_0__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_0__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA_1__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_1__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA_2__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_2__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA_3__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA_3__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_DATA__SMC_IND_DATA_MASK 0xffffffffL
+#define SMC_IND_DATA__SMC_IND_DATA__SHIFT 0x00000000
+#define SMC_IND_INDEX_0__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_0__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX_1__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_1__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX_2__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_2__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX_3__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX_3__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_IND_INDEX__SMC_IND_ADDR_MASK 0xffffffffL
+#define SMC_IND_INDEX__SMC_IND_ADDR__SHIFT 0x00000000
+#define SMC_MESSAGE_0__SMC_MSG_MASK 0xffffffffL
+#define SMC_MESSAGE_0__SMC_MSG__SHIFT 0x00000000
+#define SMC_MESSAGE_1__SMC_MSG_MASK 0xffffffffL
+#define SMC_MESSAGE_1__SMC_MSG__SHIFT 0x00000000
+#define SMC_MESSAGE_2__SMC_MSG_MASK 0xffffffffL
+#define SMC_MESSAGE_2__SMC_MSG__SHIFT 0x00000000
+#define SMC_PC_C__smc_pc_c_MASK 0xffffffffL
+#define SMC_PC_C__smc_pc_c__SHIFT 0x00000000
+#define SMC_RESP_0__SMC_RESP_MASK 0xffffffffL
+#define SMC_RESP_0__SMC_RESP__SHIFT 0x00000000
+#define SMC_RESP_1__SMC_RESP_MASK 0xffffffffL
+#define SMC_RESP_1__SMC_RESP__SHIFT 0x00000000
+#define SMC_RESP_2__SMC_RESP_MASK 0xffffffffL
+#define SMC_RESP_2__SMC_RESP__SHIFT 0x00000000
+#define SPLL_CNTL_MODE__SPLL_CTLREQ_DLY_CNT_MASK 0x000ff000L
+#define SPLL_CNTL_MODE__SPLL_CTLREQ_DLY_CNT__SHIFT 0x0000000c
+#define SPLL_CNTL_MODE__SPLL_ENSAT_MASK 0x00000010L
+#define SPLL_CNTL_MODE__SPLL_ENSAT__SHIFT 0x00000004
+#define SPLL_CNTL_MODE__SPLL_FASTEN_MASK 0x00000008L
+#define SPLL_CNTL_MODE__SPLL_FASTEN__SHIFT 0x00000003
+#define SPLL_CNTL_MODE__SPLL_LEGACY_PDIV_MASK 0x00000002L
+#define SPLL_CNTL_MODE__SPLL_LEGACY_PDIV__SHIFT 0x00000001
+#define SPLL_CNTL_MODE__SPLL_RESET_EN_MASK 0x10000000L
+#define SPLL_CNTL_MODE__SPLL_RESET_EN__SHIFT 0x0000001c
+#define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL_MASK 0x00000001L
+#define SPLL_CNTL_MODE__SPLL_SW_DIR_CONTROL__SHIFT 0x00000000
+#define SPLL_CNTL_MODE__SPLL_TEST_CLK_EXT_DIV_MASK 0x00000c00L
+#define SPLL_CNTL_MODE__SPLL_TEST_CLK_EXT_DIV__SHIFT 0x0000000a
+#define SPLL_CNTL_MODE__SPLL_TEST_MASK 0x00000004L
+#define SPLL_CNTL_MODE__SPLL_TEST__SHIFT 0x00000002
+#define SPLL_CNTL_MODE__SPLL_VCO_MODE_MASK 0x60000000L
+#define SPLL_CNTL_MODE__SPLL_VCO_MODE__SHIFT 0x0000001d
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX_MASK 0x0f000000L
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__CURR_PCIE_INDEX__SHIFT 0x00000018
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__TARG_PCIE_INDEX_MASK 0xf0000000L
+#define TARGET_AND_CURRENT_PROFILE_INDEX_1__TARG_PCIE_INDEX__SHIFT 0x0000001c
+#define THM_TMON0_DEBUG__DEBUG_RDI_MASK 0x0000001fL
+#define THM_TMON0_DEBUG__DEBUG_RDI__SHIFT 0x00000000
+#define THM_TMON0_DEBUG__DEBUG_Z_MASK 0x0000ffe0L
+#define THM_TMON0_DEBUG__DEBUG_Z__SHIFT 0x00000005
+#define THM_TMON0_INT_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_INT_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_INT_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_INT_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_INT_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_INT_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIL9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIL9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIL9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIL9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIL9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIL9_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON0_RDIR9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON0_RDIR9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON0_RDIR9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON0_RDIR9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON0_RDIR9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON0_RDIR9_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_DEBUG__DEBUG_RDI_MASK 0x0000001fL
+#define THM_TMON1_DEBUG__DEBUG_RDI__SHIFT 0x00000000
+#define THM_TMON1_DEBUG__DEBUG_Z_MASK 0x0000ffe0L
+#define THM_TMON1_DEBUG__DEBUG_Z__SHIFT 0x00000005
+#define THM_TMON1_INT_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_INT_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_INT_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_INT_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_INT_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_INT_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIL9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIL9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIL9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIL9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIL9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIL9_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR0_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR0_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR0_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR0_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR0_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR0_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR10_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR10_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR10_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR10_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR10_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR10_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR11_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR11_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR11_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR11_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR11_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR11_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR12_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR12_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR12_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR12_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR12_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR12_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR13_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR13_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR13_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR13_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR13_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR13_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR14_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR14_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR14_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR14_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR14_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR14_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR15_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR15_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR15_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR15_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR15_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR15_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR1_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR1_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR1_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR1_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR1_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR1_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR2_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR2_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR2_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR2_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR2_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR2_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR3_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR3_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR3_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR3_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR3_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR3_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR4_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR4_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR4_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR4_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR4_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR4_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR5_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR5_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR5_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR5_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR5_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR5_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR6_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR6_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR6_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR6_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR6_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR6_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR7_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR7_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR7_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR7_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR7_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR7_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR8_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR8_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR8_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR8_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR8_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR8_DATA__Z__SHIFT 0x00000000
+#define THM_TMON1_RDIR9_DATA__TEMP_MASK 0x00fff000L
+#define THM_TMON1_RDIR9_DATA__TEMP__SHIFT 0x0000000c
+#define THM_TMON1_RDIR9_DATA__VALID_MASK 0x00000800L
+#define THM_TMON1_RDIR9_DATA__VALID__SHIFT 0x0000000b
+#define THM_TMON1_RDIR9_DATA__Z_MASK 0x000007ffL
+#define THM_TMON1_RDIR9_DATA__Z__SHIFT 0x00000000
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_1_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -176,6 +176,8 @@
 #define mmSMU1_SMU_SMC_IND_DATA                                                 0x83
 #define mmSMU2_SMU_SMC_IND_DATA                                                 0x85
 #define mmSMU3_SMU_SMC_IND_DATA                                                 0x87
+#define mmSMC_IND_INDEX_11														0x1AC
+#define mmSMC_IND_DATA_11														0x1AD
 #define ixRCU_UC_EVENTS                                                         0xc0000004
 #define ixRCU_MISC_CTRL                                                         0xc0000010
 #define ixCC_RCU_FUSES                                                          0xc00c0000
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_2_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -87,6 +87,8 @@
 #define mmSMC_IND_DATA_6                                                        0x8d
 #define mmSMC_IND_INDEX_7                                                       0x8e
 #define mmSMC_IND_DATA_7                                                        0x8f
+#define mmSMC_IND_INDEX_11														0x1AC
+#define mmSMC_IND_DATA_11														0x1AD
 #define mmSMC_IND_ACCESS_CNTL                                                   0x92
 #define mmSMC_MESSAGE_0                                                         0x94
 #define mmSMC_RESP_0                                                            0x95
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/smu/smu_7_1_3_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,6 +90,8 @@
 #define mmSMC_IND_DATA_6                                                        0x8d
 #define mmSMC_IND_INDEX_7                                                       0x8e
 #define mmSMC_IND_DATA_7                                                        0x8f
+#define mmSMC_IND_INDEX_11														0x1AC
+#define mmSMC_IND_DATA_11														0x1AD
 #define mmSMC_IND_ACCESS_CNTL                                                   0x92
 #define mmSMC_MESSAGE_0                                                         0x94
 #define mmSMC_RESP_0                                                            0x95
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,96 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 UVD_4_0_D_H
+#define UVD_4_0_D_H
+
+#define ixUVD_CGC_CTRL2 0x00C1
+#define ixUVD_CGC_MEM_CTRL 0x00C0
+#define ixUVD_LMI_ADDR_EXT2 0x00AB
+#define ixUVD_LMI_CACHE_CTRL 0x009B
+#define ixUVD_LMI_SWAP_CNTL2 0x00AA
+#define ixUVD_MIF_CURR_ADDR_CONFIG 0x0048
+#define ixUVD_MIF_RECON1_ADDR_CONFIG 0x0114
+#define ixUVD_MIF_REF_ADDR_CONFIG 0x004C
+#define mmUVD_CGC_CTRL 0x3D2C
+#define mmUVD_CGC_GATE 0x3D2A
+#define mmUVD_CGC_STATUS 0x3D2B
+#define mmUVD_CGC_UDEC_STATUS 0x3D2D
+#define mmUVD_CONTEXT_ID 0x3DBD
+#define mmUVD_CTX_DATA 0x3D29
+#define mmUVD_CTX_INDEX 0x3D28
+#define mmUVD_ENGINE_CNTL 0x3BC6
+#define mmUVD_GPCOM_VCPU_CMD 0x3BC3
+#define mmUVD_GPCOM_VCPU_DATA0 0x3BC4
+#define mmUVD_GPCOM_VCPU_DATA1 0x3BC5
+#define mmUVD_GP_SCRATCH4 0x3D38
+#define mmUVD_LMI_ADDR_EXT 0x3D65
+#define mmUVD_LMI_CTRL 0x3D66
+#define mmUVD_LMI_CTRL2 0x3D3D
+#define mmUVD_LMI_EXT40_ADDR 0x3D26
+#define mmUVD_LMI_STATUS 0x3D67
+#define mmUVD_LMI_SWAP_CNTL 0x3D6D
+#define mmUVD_MASTINT_EN 0x3D40
+#define mmUVD_MPC_CNTL 0x3D77
+#define mmUVD_MPC_SET_ALU 0x3D7E
+#define mmUVD_MPC_SET_MUX 0x3D7D
+#define mmUVD_MPC_SET_MUXA0 0x3D79
+#define mmUVD_MPC_SET_MUXA1 0x3D7A
+#define mmUVD_MPC_SET_MUXB0 0x3D7B
+#define mmUVD_MPC_SET_MUXB1 0x3D7C
+#define mmUVD_MP_SWAP_CNTL 0x3D6F
+#define mmUVD_NO_OP 0x3BFF
+#define mmUVD_PGFSM_CONFIG 0x38F8
+#define mmUVD_PGFSM_READ_TILE1 0x38FA
+#define mmUVD_PGFSM_READ_TILE2 0x38FB
+#define mmUVD_POWER_STATUS 0x38FC
+#define mmUVD_RBC_IB_BASE 0x3DA1
+#define mmUVD_RBC_IB_SIZE 0x3DA2
+#define mmUVD_RBC_IB_SIZE_UPDATE 0x3DF1
+#define mmUVD_RBC_RB_BASE 0x3DA3
+#define mmUVD_RBC_RB_CNTL 0x3DA9
+#define mmUVD_RBC_RB_RPTR 0x3DA4
+#define mmUVD_RBC_RB_RPTR_ADDR 0x3DAA
+#define mmUVD_RBC_RB_WPTR 0x3DA5
+#define mmUVD_RBC_RB_WPTR_CNTL 0x3DA6
+#define mmUVD_SEMA_ADDR_HIGH 0x3BC1
+#define mmUVD_SEMA_ADDR_LOW 0x3BC0
+#define mmUVD_SEMA_CMD 0x3BC2
+#define mmUVD_SEMA_CNTL 0x3D00
+#define mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL 0x3DB3
+#define mmUVD_SEMA_TIMEOUT_STATUS 0x3DB0
+#define mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL 0x3DB2
+#define mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL 0x3DB1
+#define mmUVD_SOFT_RESET 0x3DA0
+#define mmUVD_STATUS 0x3DAF
+#define mmUVD_UDEC_ADDR_CONFIG 0x3BD3
+#define mmUVD_UDEC_DB_ADDR_CONFIG 0x3BD4
+#define mmUVD_UDEC_DBW_ADDR_CONFIG 0x3BD5
+#define mmUVD_VCPU_CACHE_OFFSET0 0x3D36
+#define mmUVD_VCPU_CACHE_OFFSET1 0x3D38
+#define mmUVD_VCPU_CACHE_OFFSET2 0x3D3A
+#define mmUVD_VCPU_CACHE_SIZE0 0x3D37
+#define mmUVD_VCPU_CACHE_SIZE1 0x3D39
+#define mmUVD_VCPU_CACHE_SIZE2 0x3D3B
+#define mmUVD_VCPU_CNTL 0x3D98
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_4_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,795 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 UVD_4_0_SH_MASK_H
+#define UVD_4_0_SH_MASK_H
+
+#define UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN_MASK 0x00000001L
+#define UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN__SHIFT 0x00000000
+#define UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN_MASK 0x00000002L
+#define UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN__SHIFT 0x00000001
+#define UVD_CGC_CTRL2__GATER_DIV_ID_MASK 0x0000001cL
+#define UVD_CGC_CTRL2__GATER_DIV_ID__SHIFT 0x00000002
+#define UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK 0x0000003cL
+#define UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT 0x00000002
+#define UVD_CGC_CTRL__CLK_OFF_DELAY_MASK 0x000007c0L
+#define UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT 0x00000006
+#define UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK 0x00000001L
+#define UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT 0x00000000
+#define UVD_CGC_CTRL__IDCT_MODE_MASK 0x00800000L
+#define UVD_CGC_CTRL__IDCT_MODE__SHIFT 0x00000017
+#define UVD_CGC_CTRL__LBSI_MODE_MASK 0x04000000L
+#define UVD_CGC_CTRL__LBSI_MODE__SHIFT 0x0000001a
+#define UVD_CGC_CTRL__LMI_MC_MODE_MASK 0x00200000L
+#define UVD_CGC_CTRL__LMI_MC_MODE__SHIFT 0x00000015
+#define UVD_CGC_CTRL__LMI_UMC_MODE_MASK 0x00400000L
+#define UVD_CGC_CTRL__LMI_UMC_MODE__SHIFT 0x00000016
+#define UVD_CGC_CTRL__LRBBM_MODE_MASK 0x08000000L
+#define UVD_CGC_CTRL__LRBBM_MODE__SHIFT 0x0000001b
+#define UVD_CGC_CTRL__MPC_MODE_MASK 0x02000000L
+#define UVD_CGC_CTRL__MPC_MODE__SHIFT 0x00000019
+#define UVD_CGC_CTRL__MPEG2_MODE_MASK 0x00040000L
+#define UVD_CGC_CTRL__MPEG2_MODE__SHIFT 0x00000012
+#define UVD_CGC_CTRL__MPRD_MODE_MASK 0x01000000L
+#define UVD_CGC_CTRL__MPRD_MODE__SHIFT 0x00000018
+#define UVD_CGC_CTRL__RBC_MODE_MASK 0x00100000L
+#define UVD_CGC_CTRL__RBC_MODE__SHIFT 0x00000014
+#define UVD_CGC_CTRL__REGS_MODE_MASK 0x00080000L
+#define UVD_CGC_CTRL__REGS_MODE__SHIFT 0x00000013
+#define UVD_CGC_CTRL__SCPU_MODE_MASK 0x40000000L
+#define UVD_CGC_CTRL__SCPU_MODE__SHIFT 0x0000001e
+#define UVD_CGC_CTRL__SYS_MODE_MASK 0x00010000L
+#define UVD_CGC_CTRL__SYS_MODE__SHIFT 0x00000010
+#define UVD_CGC_CTRL__UDEC_CM_MODE_MASK 0x00001000L
+#define UVD_CGC_CTRL__UDEC_CM_MODE__SHIFT 0x0000000c
+#define UVD_CGC_CTRL__UDEC_DB_MODE_MASK 0x00004000L
+#define UVD_CGC_CTRL__UDEC_DB_MODE__SHIFT 0x0000000e
+#define UVD_CGC_CTRL__UDEC_IT_MODE_MASK 0x00002000L
+#define UVD_CGC_CTRL__UDEC_IT_MODE__SHIFT 0x0000000d
+#define UVD_CGC_CTRL__UDEC_MODE_MASK 0x00020000L
+#define UVD_CGC_CTRL__UDEC_MODE__SHIFT 0x00000011
+#define UVD_CGC_CTRL__UDEC_MP_MODE_MASK 0x00008000L
+#define UVD_CGC_CTRL__UDEC_MP_MODE__SHIFT 0x0000000f
+#define UVD_CGC_CTRL__UDEC_RE_MODE_MASK 0x00000800L
+#define UVD_CGC_CTRL__UDEC_RE_MODE__SHIFT 0x0000000b
+#define UVD_CGC_CTRL__VCPU_MODE_MASK 0x20000000L
+#define UVD_CGC_CTRL__VCPU_MODE__SHIFT 0x0000001d
+#define UVD_CGC_CTRL__WCB_MODE_MASK 0x10000000L
+#define UVD_CGC_CTRL__WCB_MODE__SHIFT 0x0000001c
+#define UVD_CGC_GATE__IDCT_MASK 0x00000080L
+#define UVD_CGC_GATE__IDCT__SHIFT 0x00000007
+#define UVD_CGC_GATE__LBSI_MASK 0x00000400L
+#define UVD_CGC_GATE__LBSI__SHIFT 0x0000000a
+#define UVD_CGC_GATE__LMI_MC_MASK 0x00000020L
+#define UVD_CGC_GATE__LMI_MC__SHIFT 0x00000005
+#define UVD_CGC_GATE__LMI_UMC_MASK 0x00000040L
+#define UVD_CGC_GATE__LMI_UMC__SHIFT 0x00000006
+#define UVD_CGC_GATE__LRBBM_MASK 0x00000800L
+#define UVD_CGC_GATE__LRBBM__SHIFT 0x0000000b
+#define UVD_CGC_GATE__MPC_MASK 0x00000200L
+#define UVD_CGC_GATE__MPC__SHIFT 0x00000009
+#define UVD_CGC_GATE__MPEG2_MASK 0x00000004L
+#define UVD_CGC_GATE__MPEG2__SHIFT 0x00000002
+#define UVD_CGC_GATE__MPRD_MASK 0x00000100L
+#define UVD_CGC_GATE__MPRD__SHIFT 0x00000008
+#define UVD_CGC_GATE__RBC_MASK 0x00000010L
+#define UVD_CGC_GATE__RBC__SHIFT 0x00000004
+#define UVD_CGC_GATE__REGS_MASK 0x00000008L
+#define UVD_CGC_GATE__REGS__SHIFT 0x00000003
+#define UVD_CGC_GATE__SCPU_MASK 0x00080000L
+#define UVD_CGC_GATE__SCPU__SHIFT 0x00000013
+#define UVD_CGC_GATE__SYS_MASK 0x00000001L
+#define UVD_CGC_GATE__SYS__SHIFT 0x00000000
+#define UVD_CGC_GATE__UDEC_CM_MASK 0x00002000L
+#define UVD_CGC_GATE__UDEC_CM__SHIFT 0x0000000d
+#define UVD_CGC_GATE__UDEC_DB_MASK 0x00008000L
+#define UVD_CGC_GATE__UDEC_DB__SHIFT 0x0000000f
+#define UVD_CGC_GATE__UDEC_IT_MASK 0x00004000L
+#define UVD_CGC_GATE__UDEC_IT__SHIFT 0x0000000e
+#define UVD_CGC_GATE__UDEC_MASK 0x00000002L
+#define UVD_CGC_GATE__UDEC_MP_MASK 0x00010000L
+#define UVD_CGC_GATE__UDEC_MP__SHIFT 0x00000010
+#define UVD_CGC_GATE__UDEC_RE_MASK 0x00001000L
+#define UVD_CGC_GATE__UDEC_RE__SHIFT 0x0000000c
+#define UVD_CGC_GATE__UDEC__SHIFT 0x00000001
+#define UVD_CGC_GATE__VCPU_MASK 0x00040000L
+#define UVD_CGC_GATE__VCPU__SHIFT 0x00000012
+#define UVD_CGC_GATE__WCB_MASK 0x00020000L
+#define UVD_CGC_GATE__WCB__SHIFT 0x00000011
+#define UVD_CGC_MEM_CTRL__LCM_LS_EN_MASK 0x00002000L
+#define UVD_CGC_MEM_CTRL__LCM_LS_EN__SHIFT 0x0000000d
+#define UVD_CGC_MEM_CTRL__LMI_MC_LS_EN_MASK 0x00000001L
+#define UVD_CGC_MEM_CTRL__LMI_MC_LS_EN__SHIFT 0x00000000
+#define UVD_CGC_MEM_CTRL__LS_CLEAR_DELAY_MASK 0x00f00000L
+#define UVD_CGC_MEM_CTRL__LS_CLEAR_DELAY__SHIFT 0x00000014
+#define UVD_CGC_MEM_CTRL__LS_SET_DELAY_MASK 0x000f0000L
+#define UVD_CGC_MEM_CTRL__LS_SET_DELAY__SHIFT 0x00000010
+#define UVD_CGC_MEM_CTRL__MIF_LS_EN_MASK 0x00001000L
+#define UVD_CGC_MEM_CTRL__MIF_LS_EN__SHIFT 0x0000000c
+#define UVD_CGC_MEM_CTRL__MPC_LS_EN_MASK 0x00000002L
+#define UVD_CGC_MEM_CTRL__MPC_LS_EN__SHIFT 0x00000001
+#define UVD_CGC_MEM_CTRL__MPRD_LS_EN_MASK 0x00000004L
+#define UVD_CGC_MEM_CTRL__MPRD_LS_EN__SHIFT 0x00000002
+#define UVD_CGC_MEM_CTRL__SCPU_LS_EN_MASK 0x00000800L
+#define UVD_CGC_MEM_CTRL__SCPU_LS_EN__SHIFT 0x0000000b
+#define UVD_CGC_MEM_CTRL__SYS_LS_EN_MASK 0x00000200L
+#define UVD_CGC_MEM_CTRL__SYS_LS_EN__SHIFT 0x00000009
+#define UVD_CGC_MEM_CTRL__UDEC_CM_LS_EN_MASK 0x00000020L
+#define UVD_CGC_MEM_CTRL__UDEC_CM_LS_EN__SHIFT 0x00000005
+#define UVD_CGC_MEM_CTRL__UDEC_DB_LS_EN_MASK 0x00000080L
+#define UVD_CGC_MEM_CTRL__UDEC_DB_LS_EN__SHIFT 0x00000007
+#define UVD_CGC_MEM_CTRL__UDEC_IT_LS_EN_MASK 0x00000040L
+#define UVD_CGC_MEM_CTRL__UDEC_IT_LS_EN__SHIFT 0x00000006
+#define UVD_CGC_MEM_CTRL__UDEC_MP_LS_EN_MASK 0x00000100L
+#define UVD_CGC_MEM_CTRL__UDEC_MP_LS_EN__SHIFT 0x00000008
+#define UVD_CGC_MEM_CTRL__UDEC_RE_LS_EN_MASK 0x00000010L
+#define UVD_CGC_MEM_CTRL__UDEC_RE_LS_EN__SHIFT 0x00000004
+#define UVD_CGC_MEM_CTRL__VCPU_LS_EN_MASK 0x00000400L
+#define UVD_CGC_MEM_CTRL__VCPU_LS_EN__SHIFT 0x0000000a
+#define UVD_CGC_MEM_CTRL__WCB_LS_EN_MASK 0x00000008L
+#define UVD_CGC_MEM_CTRL__WCB_LS_EN__SHIFT 0x00000003
+#define UVD_CGC_STATUS__IDCT_SCLK_MASK 0x00004000L
+#define UVD_CGC_STATUS__IDCT_SCLK__SHIFT 0x0000000e
+#define UVD_CGC_STATUS__IDCT_VCLK_MASK 0x00008000L
+#define UVD_CGC_STATUS__IDCT_VCLK__SHIFT 0x0000000f
+#define UVD_CGC_STATUS__LBSI_SCLK_MASK 0x00200000L
+#define UVD_CGC_STATUS__LBSI_SCLK__SHIFT 0x00000015
+#define UVD_CGC_STATUS__LBSI_VCLK_MASK 0x00400000L
+#define UVD_CGC_STATUS__LBSI_VCLK__SHIFT 0x00000016
+#define UVD_CGC_STATUS__LMI_MC_SCLK_MASK 0x00001000L
+#define UVD_CGC_STATUS__LMI_MC_SCLK__SHIFT 0x0000000c
+#define UVD_CGC_STATUS__LMI_UMC_SCLK_MASK 0x00002000L
+#define UVD_CGC_STATUS__LMI_UMC_SCLK__SHIFT 0x0000000d
+#define UVD_CGC_STATUS__LRBBM_SCLK_MASK 0x00800000L
+#define UVD_CGC_STATUS__LRBBM_SCLK__SHIFT 0x00000017
+#define UVD_CGC_STATUS__MPC_DCLK_MASK 0x00100000L
+#define UVD_CGC_STATUS__MPC_DCLK__SHIFT 0x00000014
+#define UVD_CGC_STATUS__MPC_SCLK_MASK 0x00080000L
+#define UVD_CGC_STATUS__MPC_SCLK__SHIFT 0x00000013
+#define UVD_CGC_STATUS__MPEG2_DCLK_MASK 0x00000080L
+#define UVD_CGC_STATUS__MPEG2_DCLK__SHIFT 0x00000007
+#define UVD_CGC_STATUS__MPEG2_SCLK_MASK 0x00000040L
+#define UVD_CGC_STATUS__MPEG2_SCLK__SHIFT 0x00000006
+#define UVD_CGC_STATUS__MPEG2_VCLK_MASK 0x00000100L
+#define UVD_CGC_STATUS__MPEG2_VCLK__SHIFT 0x00000008
+#define UVD_CGC_STATUS__MPRD_DCLK_MASK 0x00020000L
+#define UVD_CGC_STATUS__MPRD_DCLK__SHIFT 0x00000011
+#define UVD_CGC_STATUS__MPRD_SCLK_MASK 0x00010000L
+#define UVD_CGC_STATUS__MPRD_SCLK__SHIFT 0x00000010
+#define UVD_CGC_STATUS__MPRD_VCLK_MASK 0x00040000L
+#define UVD_CGC_STATUS__MPRD_VCLK__SHIFT 0x00000012
+#define UVD_CGC_STATUS__RBC_SCLK_MASK 0x00000800L
+#define UVD_CGC_STATUS__RBC_SCLK__SHIFT 0x0000000b
+#define UVD_CGC_STATUS__REGS_SCLK_MASK 0x00000200L
+#define UVD_CGC_STATUS__REGS_SCLK__SHIFT 0x00000009
+#define UVD_CGC_STATUS__REGS_VCLK_MASK 0x00000400L
+#define UVD_CGC_STATUS__REGS_VCLK__SHIFT 0x0000000a
+#define UVD_CGC_STATUS__SCPU_SCLK_MASK 0x08000000L
+#define UVD_CGC_STATUS__SCPU_SCLK__SHIFT 0x0000001b
+#define UVD_CGC_STATUS__SCPU_VCLK_MASK 0x10000000L
+#define UVD_CGC_STATUS__SCPU_VCLK__SHIFT 0x0000001c
+#define UVD_CGC_STATUS__SYS_DCLK_MASK 0x00000002L
+#define UVD_CGC_STATUS__SYS_DCLK__SHIFT 0x00000001
+#define UVD_CGC_STATUS__SYS_SCLK_MASK 0x00000001L
+#define UVD_CGC_STATUS__SYS_SCLK__SHIFT 0x00000000
+#define UVD_CGC_STATUS__SYS_VCLK_MASK 0x00000004L
+#define UVD_CGC_STATUS__SYS_VCLK__SHIFT 0x00000002
+#define UVD_CGC_STATUS__UDEC_DCLK_MASK 0x00000010L
+#define UVD_CGC_STATUS__UDEC_DCLK__SHIFT 0x00000004
+#define UVD_CGC_STATUS__UDEC_SCLK_MASK 0x00000008L
+#define UVD_CGC_STATUS__UDEC_SCLK__SHIFT 0x00000003
+#define UVD_CGC_STATUS__UDEC_VCLK_MASK 0x00000020L
+#define UVD_CGC_STATUS__UDEC_VCLK__SHIFT 0x00000005
+#define UVD_CGC_STATUS__VCPU_SCLK_MASK 0x02000000L
+#define UVD_CGC_STATUS__VCPU_SCLK__SHIFT 0x00000019
+#define UVD_CGC_STATUS__VCPU_VCLK_MASK 0x04000000L
+#define UVD_CGC_STATUS__VCPU_VCLK__SHIFT 0x0000001a
+#define UVD_CGC_STATUS__WCB_SCLK_MASK 0x01000000L
+#define UVD_CGC_STATUS__WCB_SCLK__SHIFT 0x00000018
+#define UVD_CGC_UDEC_STATUS__CM_DCLK_MASK 0x00000010L
+#define UVD_CGC_UDEC_STATUS__CM_DCLK__SHIFT 0x00000004
+#define UVD_CGC_UDEC_STATUS__CM_SCLK_MASK 0x00000008L
+#define UVD_CGC_UDEC_STATUS__CM_SCLK__SHIFT 0x00000003
+#define UVD_CGC_UDEC_STATUS__CM_VCLK_MASK 0x00000020L
+#define UVD_CGC_UDEC_STATUS__CM_VCLK__SHIFT 0x00000005
+#define UVD_CGC_UDEC_STATUS__DB_DCLK_MASK 0x00000400L
+#define UVD_CGC_UDEC_STATUS__DB_DCLK__SHIFT 0x0000000a
+#define UVD_CGC_UDEC_STATUS__DB_SCLK_MASK 0x00000200L
+#define UVD_CGC_UDEC_STATUS__DB_SCLK__SHIFT 0x00000009
+#define UVD_CGC_UDEC_STATUS__DB_VCLK_MASK 0x00000800L
+#define UVD_CGC_UDEC_STATUS__DB_VCLK__SHIFT 0x0000000b
+#define UVD_CGC_UDEC_STATUS__IT_DCLK_MASK 0x00000080L
+#define UVD_CGC_UDEC_STATUS__IT_DCLK__SHIFT 0x00000007
+#define UVD_CGC_UDEC_STATUS__IT_SCLK_MASK 0x00000040L
+#define UVD_CGC_UDEC_STATUS__IT_SCLK__SHIFT 0x00000006
+#define UVD_CGC_UDEC_STATUS__IT_VCLK_MASK 0x00000100L
+#define UVD_CGC_UDEC_STATUS__IT_VCLK__SHIFT 0x00000008
+#define UVD_CGC_UDEC_STATUS__MP_DCLK_MASK 0x00002000L
+#define UVD_CGC_UDEC_STATUS__MP_DCLK__SHIFT 0x0000000d
+#define UVD_CGC_UDEC_STATUS__MP_SCLK_MASK 0x00001000L
+#define UVD_CGC_UDEC_STATUS__MP_SCLK__SHIFT 0x0000000c
+#define UVD_CGC_UDEC_STATUS__MP_VCLK_MASK 0x00004000L
+#define UVD_CGC_UDEC_STATUS__MP_VCLK__SHIFT 0x0000000e
+#define UVD_CGC_UDEC_STATUS__RE_DCLK_MASK 0x00000002L
+#define UVD_CGC_UDEC_STATUS__RE_DCLK__SHIFT 0x00000001
+#define UVD_CGC_UDEC_STATUS__RE_SCLK_MASK 0x00000001L
+#define UVD_CGC_UDEC_STATUS__RE_SCLK__SHIFT 0x00000000
+#define UVD_CGC_UDEC_STATUS__RE_VCLK_MASK 0x00000004L
+#define UVD_CGC_UDEC_STATUS__RE_VCLK__SHIFT 0x00000002
+#define UVD_CONTEXT_ID__CONTEXT_ID_MASK 0xffffffffL
+#define UVD_CONTEXT_ID__CONTEXT_ID__SHIFT 0x00000000
+#define UVD_CTX_DATA__DATA_MASK 0xffffffffL
+#define UVD_CTX_DATA__DATA__SHIFT 0x00000000
+#define UVD_CTX_INDEX__INDEX_MASK 0x000001ffL
+#define UVD_CTX_INDEX__INDEX__SHIFT 0x00000000
+#define UVD_ENGINE_CNTL__ENGINE_START_MASK 0x00000001L
+#define UVD_ENGINE_CNTL__ENGINE_START_MODE_MASK 0x00000002L
+#define UVD_ENGINE_CNTL__ENGINE_START_MODE__SHIFT 0x00000001
+#define UVD_ENGINE_CNTL__ENGINE_START__SHIFT 0x00000000
+#define UVD_GPCOM_VCPU_CMD__CMD_MASK 0x7ffffffeL
+#define UVD_GPCOM_VCPU_CMD__CMD_SEND_MASK 0x00000001L
+#define UVD_GPCOM_VCPU_CMD__CMD_SEND__SHIFT 0x00000000
+#define UVD_GPCOM_VCPU_CMD__CMD__SHIFT 0x00000001
+#define UVD_GPCOM_VCPU_CMD__CMD_SOURCE_MASK 0x80000000L
+#define UVD_GPCOM_VCPU_CMD__CMD_SOURCE__SHIFT 0x0000001f
+#define UVD_GPCOM_VCPU_DATA0__DATA0_MASK 0xffffffffL
+#define UVD_GPCOM_VCPU_DATA0__DATA0__SHIFT 0x00000000
+#define UVD_GPCOM_VCPU_DATA1__DATA1_MASK 0xffffffffL
+#define UVD_GPCOM_VCPU_DATA1__DATA1__SHIFT 0x00000000
+#define UVD_LMI_ADDR_EXT2__SCPU_ADDR_EXT_MASK 0x0000000fL
+#define UVD_LMI_ADDR_EXT2__SCPU_ADDR_EXT__SHIFT 0x00000000
+#define UVD_LMI_ADDR_EXT2__SCPU_NC0_ADDR_EXT_MASK 0x00000f00L
+#define UVD_LMI_ADDR_EXT2__SCPU_NC0_ADDR_EXT__SHIFT 0x00000008
+#define UVD_LMI_ADDR_EXT2__SCPU_NC1_ADDR_EXT_MASK 0x0000f000L
+#define UVD_LMI_ADDR_EXT2__SCPU_NC1_ADDR_EXT__SHIFT 0x0000000c
+#define UVD_LMI_ADDR_EXT2__SCPU_VM_ADDR_EXT_MASK 0x000000f0L
+#define UVD_LMI_ADDR_EXT2__SCPU_VM_ADDR_EXT__SHIFT 0x00000004
+#define UVD_LMI_ADDR_EXT__CM_ADDR_EXT_MASK 0x000000f0L
+#define UVD_LMI_ADDR_EXT__CM_ADDR_EXT__SHIFT 0x00000004
+#define UVD_LMI_ADDR_EXT__IT_ADDR_EXT_MASK 0x00000f00L
+#define UVD_LMI_ADDR_EXT__IT_ADDR_EXT__SHIFT 0x00000008
+#define UVD_LMI_ADDR_EXT__MP_ADDR_EXT_MASK 0x00f00000L
+#define UVD_LMI_ADDR_EXT__MP_ADDR_EXT__SHIFT 0x00000014
+#define UVD_LMI_ADDR_EXT__RE_ADDR_EXT_MASK 0x000f0000L
+#define UVD_LMI_ADDR_EXT__RE_ADDR_EXT__SHIFT 0x00000010
+#define UVD_LMI_ADDR_EXT__VCPU_ADDR_EXT_MASK 0x0000000fL
+#define UVD_LMI_ADDR_EXT__VCPU_ADDR_EXT__SHIFT 0x00000000
+#define UVD_LMI_ADDR_EXT__VCPU_NC0_ADDR_EXT_MASK 0x0f000000L
+#define UVD_LMI_ADDR_EXT__VCPU_NC0_ADDR_EXT__SHIFT 0x00000018
+#define UVD_LMI_ADDR_EXT__VCPU_NC1_ADDR_EXT_MASK 0xf0000000L
+#define UVD_LMI_ADDR_EXT__VCPU_NC1_ADDR_EXT__SHIFT 0x0000001c
+#define UVD_LMI_ADDR_EXT__VCPU_VM_ADDR_EXT_MASK 0x0000f000L
+#define UVD_LMI_ADDR_EXT__VCPU_VM_ADDR_EXT__SHIFT 0x0000000c
+#define UVD_LMI_CACHE_CTRL__CM_EN_MASK 0x00000004L
+#define UVD_LMI_CACHE_CTRL__CM_EN__SHIFT 0x00000002
+#define UVD_LMI_CACHE_CTRL__CM_FLUSH_MASK 0x00000008L
+#define UVD_LMI_CACHE_CTRL__CM_FLUSH__SHIFT 0x00000003
+#define UVD_LMI_CACHE_CTRL__IT_EN_MASK 0x00000001L
+#define UVD_LMI_CACHE_CTRL__IT_EN__SHIFT 0x00000000
+#define UVD_LMI_CACHE_CTRL__IT_FLUSH_MASK 0x00000002L
+#define UVD_LMI_CACHE_CTRL__IT_FLUSH__SHIFT 0x00000001
+#define UVD_LMI_CACHE_CTRL__VCPU_EN_MASK 0x00000010L
+#define UVD_LMI_CACHE_CTRL__VCPU_EN__SHIFT 0x00000004
+#define UVD_LMI_CACHE_CTRL__VCPU_FLUSH_MASK 0x00000020L
+#define UVD_LMI_CACHE_CTRL__VCPU_FLUSH__SHIFT 0x00000005
+#define UVD_LMI_CTRL2__ASSERT_UMC_URGENT_MASK 0x00000004L
+#define UVD_LMI_CTRL2__ASSERT_UMC_URGENT__SHIFT 0x00000002
+#define UVD_LMI_CTRL2__DRCITF_BUBBLE_FIX_DIS_MASK 0x00000080L
+#define UVD_LMI_CTRL2__DRCITF_BUBBLE_FIX_DIS__SHIFT 0x00000007
+#define UVD_LMI_CTRL2__MASK_UMC_URGENT_MASK 0x00000008L
+#define UVD_LMI_CTRL2__MASK_UMC_URGENT__SHIFT 0x00000003
+#define UVD_LMI_CTRL2__MCIF_WR_WATERMARK_MASK 0x00000070L
+#define UVD_LMI_CTRL2__MCIF_WR_WATERMARK__SHIFT 0x00000004
+#define UVD_LMI_CTRL2__MC_READ_ID_SEL_MASK 0x00000600L
+#define UVD_LMI_CTRL2__MC_READ_ID_SEL__SHIFT 0x00000009
+#define UVD_LMI_CTRL2__MC_WRITE_ID_SEL_MASK 0x00001800L
+#define UVD_LMI_CTRL2__MC_WRITE_ID_SEL__SHIFT 0x0000000b
+#define UVD_LMI_CTRL2__SPH_DIS_MASK 0x00000001L
+#define UVD_LMI_CTRL2__SPH_DIS__SHIFT 0x00000000
+#define UVD_LMI_CTRL2__SPU_EXTRA_CID_EN_MASK 0x00008000L
+#define UVD_LMI_CTRL2__SPU_EXTRA_CID_EN__SHIFT 0x0000000f
+#define UVD_LMI_CTRL2__STALL_ARB_MASK 0x00000002L
+#define UVD_LMI_CTRL2__STALL_ARB__SHIFT 0x00000001
+#define UVD_LMI_CTRL2__STALL_ARB_UMC_MASK 0x00000100L
+#define UVD_LMI_CTRL2__STALL_ARB_UMC__SHIFT 0x00000008
+#define UVD_LMI_CTRL2__VCPU_NC0_EXT_EN_MASK 0x00002000L
+#define UVD_LMI_CTRL2__VCPU_NC0_EXT_EN__SHIFT 0x0000000d
+#define UVD_LMI_CTRL2__VCPU_NC1_EXT_EN_MASK 0x00004000L
+#define UVD_LMI_CTRL2__VCPU_NC1_EXT_EN__SHIFT 0x0000000e
+#define UVD_LMI_CTRL__ASSERT_MC_URGENT_MASK 0x00000800L
+#define UVD_LMI_CTRL__ASSERT_MC_URGENT__SHIFT 0x0000000b
+#define UVD_LMI_CTRL__CM_DATA_COHERENCY_EN_MASK 0x00400000L
+#define UVD_LMI_CTRL__CM_DATA_COHERENCY_EN__SHIFT 0x00000016
+#define UVD_LMI_CTRL__CRC_RESET_MASK 0x00004000L
+#define UVD_LMI_CTRL__CRC_RESET__SHIFT 0x0000000e
+#define UVD_LMI_CTRL__CRC_SEL_MASK 0x000f8000L
+#define UVD_LMI_CTRL__CRC_SEL__SHIFT 0x0000000f
+#define UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK 0x00002000L
+#define UVD_LMI_CTRL__DATA_COHERENCY_EN__SHIFT 0x0000000d
+#define UVD_LMI_CTRL__DB_DB_DATA_COHERENCY_EN_MASK 0x00800000L
+#define UVD_LMI_CTRL__DB_DB_DATA_COHERENCY_EN__SHIFT 0x00000017
+#define UVD_LMI_CTRL__DB_IT_DATA_COHERENCY_EN_MASK 0x01000000L
+#define UVD_LMI_CTRL__DB_IT_DATA_COHERENCY_EN__SHIFT 0x00000018
+#define UVD_LMI_CTRL__DISABLE_ON_FWV_FAIL_MASK 0x00100000L
+#define UVD_LMI_CTRL__DISABLE_ON_FWV_FAIL__SHIFT 0x00000014
+#define UVD_LMI_CTRL__IT_IT_DATA_COHERENCY_EN_MASK 0x02000000L
+#define UVD_LMI_CTRL__IT_IT_DATA_COHERENCY_EN__SHIFT 0x00000019
+#define UVD_LMI_CTRL__MASK_MC_URGENT_MASK 0x00001000L
+#define UVD_LMI_CTRL__MASK_MC_URGENT__SHIFT 0x0000000c
+#define UVD_LMI_CTRL__MIF_MIF_DATA_COHERENCY_EN_MASK 0x04000000L
+#define UVD_LMI_CTRL__MIF_MIF_DATA_COHERENCY_EN__SHIFT 0x0000001a
+#define UVD_LMI_CTRL__REQ_MODE_MASK 0x00000200L
+#define UVD_LMI_CTRL__REQ_MODE__SHIFT 0x00000009
+#define UVD_LMI_CTRL__RFU_MASK 0xf8000000L
+#define UVD_LMI_CTRL__RFU_MASK 0xfc000000L
+#define UVD_LMI_CTRL__RFU__SHIFT 0x0000001a
+#define UVD_LMI_CTRL__RFU__SHIFT 0x0000001b
+#define UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK 0x00200000L
+#define UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN__SHIFT 0x00000015
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK 0x00000100L
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN__SHIFT 0x00000008
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER_MASK 0x000000ffL
+#define UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT 0x00000000
+#define UVD_LMI_EXT40_ADDR__ADDR_MASK 0x000000ffL
+#define UVD_LMI_EXT40_ADDR__ADDR__SHIFT 0x00000000
+#define UVD_LMI_EXT40_ADDR__INDEX_MASK 0x001f0000L
+#define UVD_LMI_EXT40_ADDR__INDEX__SHIFT 0x00000010
+#define UVD_LMI_EXT40_ADDR__WRITE_ADDR_MASK 0x80000000L
+#define UVD_LMI_EXT40_ADDR__WRITE_ADDR__SHIFT 0x0000001f
+#define UVD_LMI_STATUS__ADP_MC_READ_CLEAN_MASK 0x00001000L
+#define UVD_LMI_STATUS__ADP_MC_READ_CLEAN__SHIFT 0x0000000c
+#define UVD_LMI_STATUS__ADP_UMC_READ_CLEAN_MASK 0x00002000L
+#define UVD_LMI_STATUS__ADP_UMC_READ_CLEAN__SHIFT 0x0000000d
+#define UVD_LMI_STATUS__PENDING_UVD_MC_WRITE_MASK 0x00000080L
+#define UVD_LMI_STATUS__PENDING_UVD_MC_WRITE__SHIFT 0x00000007
+#define UVD_LMI_STATUS__READ_CLEAN_MASK 0x00000001L
+#define UVD_LMI_STATUS__READ_CLEAN_RAW_MASK 0x00000100L
+#define UVD_LMI_STATUS__READ_CLEAN_RAW__SHIFT 0x00000008
+#define UVD_LMI_STATUS__READ_CLEAN__SHIFT 0x00000000
+#define UVD_LMI_STATUS__UMC_AVP_IDLE_MASK 0x00000800L
+#define UVD_LMI_STATUS__UMC_AVP_IDLE__SHIFT 0x0000000b
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_MASK 0x00000010L
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK 0x00000200L
+#define UVD_LMI_STATUS__UMC_READ_CLEAN_RAW__SHIFT 0x00000009
+#define UVD_LMI_STATUS__UMC_READ_CLEAN__SHIFT 0x00000004
+#define UVD_LMI_STATUS__UMC_UVD_IDLE_MASK 0x00000400L
+#define UVD_LMI_STATUS__UMC_UVD_IDLE__SHIFT 0x0000000a
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_MASK 0x00000020L
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK 0x00000040L
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW__SHIFT 0x00000006
+#define UVD_LMI_STATUS__UMC_WRITE_CLEAN__SHIFT 0x00000005
+#define UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK 0x00000008L
+#define UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN__SHIFT 0x00000003
+#define UVD_LMI_STATUS__WRITE_CLEAN_MASK 0x00000002L
+#define UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK 0x00000004L
+#define UVD_LMI_STATUS__WRITE_CLEAN_RAW__SHIFT 0x00000002
+#define UVD_LMI_STATUS__WRITE_CLEAN__SHIFT 0x00000001
+#define UVD_LMI_SWAP_CNTL2__SCPU_R_MC_SWAP_MASK 0x00000003L
+#define UVD_LMI_SWAP_CNTL2__SCPU_R_MC_SWAP__SHIFT 0x00000000
+#define UVD_LMI_SWAP_CNTL2__SCPU_W_MC_SWAP_MASK 0x0000000cL
+#define UVD_LMI_SWAP_CNTL2__SCPU_W_MC_SWAP__SHIFT 0x00000002
+#define UVD_LMI_SWAP_CNTL__CM_MC_SWAP_MASK 0x00000c00L
+#define UVD_LMI_SWAP_CNTL__CM_MC_SWAP__SHIFT 0x0000000a
+#define UVD_LMI_SWAP_CNTL__CSM_MC_SWAP_MASK 0x000c0000L
+#define UVD_LMI_SWAP_CNTL__CSM_MC_SWAP__SHIFT 0x00000012
+#define UVD_LMI_SWAP_CNTL__DB_R_MC_SWAP_MASK 0x0000c000L
+#define UVD_LMI_SWAP_CNTL__DB_R_MC_SWAP__SHIFT 0x0000000e
+#define UVD_LMI_SWAP_CNTL__DB_W_MC_SWAP_MASK 0x00030000L
+#define UVD_LMI_SWAP_CNTL__DBW_MC_SWAP_MASK 0x03000000L
+#define UVD_LMI_SWAP_CNTL__DB_W_MC_SWAP__SHIFT 0x00000010
+#define UVD_LMI_SWAP_CNTL__DBW_MC_SWAP__SHIFT 0x00000018
+#define UVD_LMI_SWAP_CNTL__IB_MC_SWAP_MASK 0x0000000cL
+#define UVD_LMI_SWAP_CNTL__IB_MC_SWAP__SHIFT 0x00000002
+#define UVD_LMI_SWAP_CNTL__IT_MC_SWAP_MASK 0x00003000L
+#define UVD_LMI_SWAP_CNTL__IT_MC_SWAP__SHIFT 0x0000000c
+#define UVD_LMI_SWAP_CNTL__MP_MC_SWAP_MASK 0xc0000000L
+#define UVD_LMI_SWAP_CNTL__MP_MC_SWAP__SHIFT 0x0000001e
+#define UVD_LMI_SWAP_CNTL__MP_REF16_MC_SWAP_MASK 0x00c00000L
+#define UVD_LMI_SWAP_CNTL__MP_REF16_MC_SWAP__SHIFT 0x00000016
+#define UVD_LMI_SWAP_CNTL__RB_MC_SWAP_MASK 0x00000003L
+#define UVD_LMI_SWAP_CNTL__RB_MC_SWAP__SHIFT 0x00000000
+#define UVD_LMI_SWAP_CNTL__RB_RPTR_MC_SWAP_MASK 0x00000030L
+#define UVD_LMI_SWAP_CNTL__RB_RPTR_MC_SWAP__SHIFT 0x00000004
+#define UVD_LMI_SWAP_CNTL__RB_WR_MC_SWAP_MASK 0x0c000000L
+#define UVD_LMI_SWAP_CNTL__RB_WR_MC_SWAP__SHIFT 0x0000001a
+#define UVD_LMI_SWAP_CNTL__RE_MC_SWAP_MASK 0x30000000L
+#define UVD_LMI_SWAP_CNTL__RE_MC_SWAP__SHIFT 0x0000001c
+#define UVD_LMI_SWAP_CNTL__VCPU_R_MC_SWAP_MASK 0x000000c0L
+#define UVD_LMI_SWAP_CNTL__VCPU_R_MC_SWAP__SHIFT 0x00000006
+#define UVD_LMI_SWAP_CNTL__VCPU_W_MC_SWAP_MASK 0x00000300L
+#define UVD_LMI_SWAP_CNTL__VCPU_W_MC_SWAP__SHIFT 0x00000008
+#define UVD_MASTINT_EN__INT_OVERRUN_MASK 0x007ffff0L
+#define UVD_MASTINT_EN__INT_OVERRUN__SHIFT 0x00000004
+#define UVD_MASTINT_EN__OVERRUN_RST_MASK 0x00000001L
+#define UVD_MASTINT_EN__OVERRUN_RST__SHIFT 0x00000000
+#define UVD_MASTINT_EN__SYS_EN_MASK 0x00000004L
+#define UVD_MASTINT_EN__SYS_EN__SHIFT 0x00000002
+#define UVD_MASTINT_EN__VCPU_EN_MASK 0x00000002L
+#define UVD_MASTINT_EN__VCPU_EN__SHIFT 0x00000001
+#define UVD_MIF_CURR_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_MIF_CURR_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_MIF_CURR_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_MIF_CURR_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_MIF_CURR_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_MIF_CURR_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_MIF_CURR_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_MIF_CURR_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_MIF_CURR_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_MIF_CURR_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_MIF_CURR_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_MIF_RECON1_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_MIF_RECON1_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_MIF_RECON1_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_MIF_RECON1_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_MIF_RECON1_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_MIF_RECON1_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_MIF_RECON1_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_MIF_RECON1_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_MIF_REF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_MIF_REF_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_MIF_REF_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_MIF_REF_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_MIF_REF_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_MIF_REF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_MIF_REF_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_MIF_REF_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_MIF_REF_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_MIF_REF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_MIF_REF_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_MPC_CNTL__AVE_WEIGHT_MASK 0x00030000L
+#define UVD_MPC_CNTL__AVE_WEIGHT__SHIFT 0x00000010
+#define UVD_MPC_CNTL__DBG_MUX_MASK 0x00000700L
+#define UVD_MPC_CNTL__DBG_MUX__SHIFT 0x00000008
+#define UVD_MPC_CNTL__PERF_RST_MASK 0x00000040L
+#define UVD_MPC_CNTL__PERF_RST__SHIFT 0x00000006
+#define UVD_MPC_CNTL__REPLACEMENT_MODE_MASK 0x00000038L
+#define UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT 0x00000003
+#define UVD_MPC_CNTL__URGENT_EN_MASK 0x00040000L
+#define UVD_MPC_CNTL__URGENT_EN__SHIFT 0x00000012
+#define UVD_MPC_SET_ALU__FUNCT_MASK 0x00000007L
+#define UVD_MPC_SET_ALU__FUNCT__SHIFT 0x00000000
+#define UVD_MPC_SET_ALU__OPERAND_MASK 0x00000ff0L
+#define UVD_MPC_SET_ALU__OPERAND__SHIFT 0x00000004
+#define UVD_MPC_SET_MUXA0__VARA_0_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXA0__VARA_0__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXA0__VARA_1_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXA0__VARA_1__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXA0__VARA_2_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXA0__VARA_2__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUXA0__VARA_3_MASK 0x00fc0000L
+#define UVD_MPC_SET_MUXA0__VARA_3__SHIFT 0x00000012
+#define UVD_MPC_SET_MUXA0__VARA_4_MASK 0x3f000000L
+#define UVD_MPC_SET_MUXA0__VARA_4__SHIFT 0x00000018
+#define UVD_MPC_SET_MUXA1__VARA_5_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXA1__VARA_5__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXA1__VARA_6_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXA1__VARA_6__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXA1__VARA_7_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXA1__VARA_7__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUXB0__VARB_0_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXB0__VARB_0__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXB0__VARB_1_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXB0__VARB_1__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXB0__VARB_2_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXB0__VARB_2__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUXB0__VARB_3_MASK 0x00fc0000L
+#define UVD_MPC_SET_MUXB0__VARB_3__SHIFT 0x00000012
+#define UVD_MPC_SET_MUXB0__VARB_4_MASK 0x3f000000L
+#define UVD_MPC_SET_MUXB0__VARB_4__SHIFT 0x00000018
+#define UVD_MPC_SET_MUXB1__VARB_5_MASK 0x0000003fL
+#define UVD_MPC_SET_MUXB1__VARB_5__SHIFT 0x00000000
+#define UVD_MPC_SET_MUXB1__VARB_6_MASK 0x00000fc0L
+#define UVD_MPC_SET_MUXB1__VARB_6__SHIFT 0x00000006
+#define UVD_MPC_SET_MUXB1__VARB_7_MASK 0x0003f000L
+#define UVD_MPC_SET_MUXB1__VARB_7__SHIFT 0x0000000c
+#define UVD_MPC_SET_MUX__SET_0_MASK 0x00000007L
+#define UVD_MPC_SET_MUX__SET_0__SHIFT 0x00000000
+#define UVD_MPC_SET_MUX__SET_1_MASK 0x00000038L
+#define UVD_MPC_SET_MUX__SET_1__SHIFT 0x00000003
+#define UVD_MPC_SET_MUX__SET_2_MASK 0x000001c0L
+#define UVD_MPC_SET_MUX__SET_2__SHIFT 0x00000006
+#define UVD_MP_SWAP_CNTL__MP_REF0_MC_SWAP_MASK 0x00000003L
+#define UVD_MP_SWAP_CNTL__MP_REF0_MC_SWAP__SHIFT 0x00000000
+#define UVD_MP_SWAP_CNTL__MP_REF10_MC_SWAP_MASK 0x00300000L
+#define UVD_MP_SWAP_CNTL__MP_REF10_MC_SWAP__SHIFT 0x00000014
+#define UVD_MP_SWAP_CNTL__MP_REF11_MC_SWAP_MASK 0x00c00000L
+#define UVD_MP_SWAP_CNTL__MP_REF11_MC_SWAP__SHIFT 0x00000016
+#define UVD_MP_SWAP_CNTL__MP_REF12_MC_SWAP_MASK 0x03000000L
+#define UVD_MP_SWAP_CNTL__MP_REF12_MC_SWAP__SHIFT 0x00000018
+#define UVD_MP_SWAP_CNTL__MP_REF13_MC_SWAP_MASK 0x0c000000L
+#define UVD_MP_SWAP_CNTL__MP_REF13_MC_SWAP__SHIFT 0x0000001a
+#define UVD_MP_SWAP_CNTL__MP_REF14_MC_SWAP_MASK 0x30000000L
+#define UVD_MP_SWAP_CNTL__MP_REF14_MC_SWAP__SHIFT 0x0000001c
+#define UVD_MP_SWAP_CNTL__MP_REF15_MC_SWAP_MASK 0xc0000000L
+#define UVD_MP_SWAP_CNTL__MP_REF15_MC_SWAP__SHIFT 0x0000001e
+#define UVD_MP_SWAP_CNTL__MP_REF1_MC_SWAP_MASK 0x0000000cL
+#define UVD_MP_SWAP_CNTL__MP_REF1_MC_SWAP__SHIFT 0x00000002
+#define UVD_MP_SWAP_CNTL__MP_REF2_MC_SWAP_MASK 0x00000030L
+#define UVD_MP_SWAP_CNTL__MP_REF2_MC_SWAP__SHIFT 0x00000004
+#define UVD_MP_SWAP_CNTL__MP_REF3_MC_SWAP_MASK 0x000000c0L
+#define UVD_MP_SWAP_CNTL__MP_REF3_MC_SWAP__SHIFT 0x00000006
+#define UVD_MP_SWAP_CNTL__MP_REF4_MC_SWAP_MASK 0x00000300L
+#define UVD_MP_SWAP_CNTL__MP_REF4_MC_SWAP__SHIFT 0x00000008
+#define UVD_MP_SWAP_CNTL__MP_REF5_MC_SWAP_MASK 0x00000c00L
+#define UVD_MP_SWAP_CNTL__MP_REF5_MC_SWAP__SHIFT 0x0000000a
+#define UVD_MP_SWAP_CNTL__MP_REF6_MC_SWAP_MASK 0x00003000L
+#define UVD_MP_SWAP_CNTL__MP_REF6_MC_SWAP__SHIFT 0x0000000c
+#define UVD_MP_SWAP_CNTL__MP_REF7_MC_SWAP_MASK 0x0000c000L
+#define UVD_MP_SWAP_CNTL__MP_REF7_MC_SWAP__SHIFT 0x0000000e
+#define UVD_MP_SWAP_CNTL__MP_REF8_MC_SWAP_MASK 0x00030000L
+#define UVD_MP_SWAP_CNTL__MP_REF8_MC_SWAP__SHIFT 0x00000010
+#define UVD_MP_SWAP_CNTL__MP_REF9_MC_SWAP_MASK 0x000c0000L
+#define UVD_MP_SWAP_CNTL__MP_REF9_MC_SWAP__SHIFT 0x00000012
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_FSM_ADDR_MASK 0x000000ffL
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_FSM_ADDR__SHIFT 0x00000000
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P1_SELECT_MASK 0x00000400L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P1_SELECT__SHIFT 0x0000000a
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P2_SELECT_MASK 0x00000800L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_P2_SELECT__SHIFT 0x0000000b
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_DOWN_MASK 0x00000100L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_DOWN__SHIFT 0x00000008
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_UP_MASK 0x00000200L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_UP__SHIFT 0x00000009
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_READ_MASK 0x00002000L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_READ__SHIFT 0x0000000d
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_REG_ADDR_MASK 0xf0000000L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_REG_ADDR__SHIFT 0x0000001c
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_WRITE_MASK 0x00001000L
+#define UVD_PGFSM_CONFIG__UVD_PGFSM_WRITE__SHIFT 0x0000000c
+#define UVD_PGFSM_READ_TILE1__UVD_PGFSM_READ_TILE1_VALUE_MASK 0x00ffffffL
+#define UVD_PGFSM_READ_TILE1__UVD_PGFSM_READ_TILE1_VALUE__SHIFT 0x00000000
+#define UVD_PGFSM_READ_TILE2__UVD_PGFSM_READ_TILE2_VALUE_MASK 0x00ffffffL
+#define UVD_PGFSM_READ_TILE2__UVD_PGFSM_READ_TILE2_VALUE__SHIFT 0x00000000
+#define UVD_POWER_STATUS__UVD_POWER_STATUS_MASK 0x00000001L
+#define UVD_POWER_STATUS__UVD_POWER_STATUS__SHIFT 0x00000000
+#define UVD_RBC_IB_BASE__IB_BASE_MASK 0xffffffc0L
+#define UVD_RBC_IB_BASE__IB_BASE__SHIFT 0x00000006
+#define UVD_RBC_IB_SIZE__IB_SIZE_MASK 0x007ffff0L
+#define UVD_RBC_IB_SIZE__IB_SIZE__SHIFT 0x00000004
+#define UVD_RBC_RB_BASE__RB_BASE_MASK 0xffffffc0L
+#define UVD_RBC_RB_BASE__RB_BASE__SHIFT 0x00000006
+#define UVD_RBC_RB_CNTL__RB_BLKSZ_MASK 0x00001f00L
+#define UVD_RBC_RB_CNTL__RB_BLKSZ__SHIFT 0x00000008
+#define UVD_RBC_RB_CNTL__RB_BUFSZ_MASK 0x0000001fL
+#define UVD_RBC_RB_CNTL__RB_BUFSZ__SHIFT 0x00000000
+#define UVD_RBC_RB_CNTL__RB_NO_FETCH_MASK 0x00010000L
+#define UVD_RBC_RB_CNTL__RB_NO_FETCH__SHIFT 0x00000010
+#define UVD_RBC_RB_CNTL__RB_NO_UPDATE_MASK 0x01000000L
+#define UVD_RBC_RB_CNTL__RB_NO_UPDATE__SHIFT 0x00000018
+#define UVD_RBC_RB_CNTL__RB_RPTR_WR_EN_MASK 0x10000000L
+#define UVD_RBC_RB_CNTL__RB_RPTR_WR_EN__SHIFT 0x0000001c
+#define UVD_RBC_RB_CNTL__RB_WPTR_POLL_EN_MASK 0x00100000L
+#define UVD_RBC_RB_CNTL__RB_WPTR_POLL_EN__SHIFT 0x00000014
+#define UVD_RBC_RB_RPTR_ADDR__RB_RPTR_ADDR_MASK 0xffffffffL
+#define UVD_RBC_RB_RPTR_ADDR__RB_RPTR_ADDR__SHIFT 0x00000000
+#define UVD_RBC_RB_RPTR__RB_RPTR_MASK 0x007ffff0L
+#define UVD_RBC_RB_RPTR__RB_RPTR__SHIFT 0x00000004
+#define UVD_RBC_RB_WPTR__RB_WPTR_MASK 0x007ffff0L
+#define UVD_RBC_RB_WPTR__RB_WPTR__SHIFT 0x00000004
+#define UVD_SEMA_ADDR_HIGH__ADDR_42_23_MASK 0x000fffffL
+#define UVD_SEMA_ADDR_HIGH__ADDR_42_23__SHIFT 0x00000000
+#define UVD_SEMA_ADDR_LOW__ADDR_22_3_MASK 0x000fffffL
+#define UVD_SEMA_ADDR_LOW__ADDR_22_3__SHIFT 0x00000000
+#define UVD_SEMA_CMD__MODE_MASK 0x00000040L
+#define UVD_SEMA_CMD__MODE__SHIFT 0x00000006
+#define UVD_SEMA_CMD__REQ_CMD_MASK 0x0000000fL
+#define UVD_SEMA_CMD__REQ_CMD__SHIFT 0x00000000
+#define UVD_SEMA_CMD__VMID_EN_MASK 0x00000080L
+#define UVD_SEMA_CMD__VMID_EN__SHIFT 0x00000007
+#define UVD_SEMA_CMD__VMID_MASK 0x00000f00L
+#define UVD_SEMA_CMD__VMID__SHIFT 0x00000008
+#define UVD_SEMA_CMD__WR_PHASE_MASK 0x00000030L
+#define UVD_SEMA_CMD__WR_PHASE__SHIFT 0x00000004
+#define UVD_SEMA_CNTL__ADVANCED_MODE_DIS_MASK 0x00000002L
+#define UVD_SEMA_CNTL__ADVANCED_MODE_DIS__SHIFT 0x00000001
+#define UVD_SEMA_CNTL__SEMAPHORE_EN_MASK 0x00000001L
+#define UVD_SEMA_CNTL__SEMAPHORE_EN__SHIFT 0x00000000
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x00000018
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_COUNT_MASK 0x001ffffeL
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_COUNT__SHIFT 0x00000001
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_EN_MASK 0x00000001L
+#define UVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL__SIGNAL_INCOMPLETE_EN__SHIFT 0x00000000
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_SIGNAL_INCOMPLETE_TIMEOUT_STAT_MASK 0x00000004L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_SIGNAL_INCOMPLETE_TIMEOUT_STAT__SHIFT 0x00000002
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_TIMEOUT_CLEAR_MASK 0x00000008L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_TIMEOUT_CLEAR__SHIFT 0x00000003
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_FAULT_TIMEOUT_STAT_MASK 0x00000002L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_FAULT_TIMEOUT_STAT__SHIFT 0x00000001
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_INCOMPLETE_TIMEOUT_STAT_MASK 0x00000001L
+#define UVD_SEMA_TIMEOUT_STATUS__SEMAPHORE_WAIT_INCOMPLETE_TIMEOUT_STAT__SHIFT 0x00000000
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x00000018
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_COUNT_MASK 0x001ffffeL
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_COUNT__SHIFT 0x00000001
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_EN_MASK 0x00000001L
+#define UVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL__WAIT_FAULT_EN__SHIFT 0x00000000
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER_MASK 0x07000000L
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__RESEND_TIMER__SHIFT 0x00000018
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_COUNT_MASK 0x001ffffeL
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_COUNT__SHIFT 0x00000001
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_EN_MASK 0x00000001L
+#define UVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL__WAIT_INCOMPLETE_EN__SHIFT 0x00000000
+#define UVD_SOFT_RESET__CSM_SOFT_RESET_MASK 0x00000020L
+#define UVD_SOFT_RESET__CSM_SOFT_RESET__SHIFT 0x00000005
+#define UVD_SOFT_RESET__CXW_SOFT_RESET_MASK 0x00000040L
+#define UVD_SOFT_RESET__CXW_SOFT_RESET__SHIFT 0x00000006
+#define UVD_SOFT_RESET__FWV_SOFT_RESET_MASK 0x00000200L
+#define UVD_SOFT_RESET__FWV_SOFT_RESET__SHIFT 0x00000009
+#define UVD_SOFT_RESET__IDCT_SOFT_RESET_MASK 0x00001000L
+#define UVD_SOFT_RESET__IDCT_SOFT_RESET__SHIFT 0x0000000c
+#define UVD_SOFT_RESET__IH_SOFT_RESET_MASK 0x00000400L
+#define UVD_SOFT_RESET__IH_SOFT_RESET__SHIFT 0x0000000a
+#define UVD_SOFT_RESET__LBSI_SOFT_RESET_MASK 0x00000002L
+#define UVD_SOFT_RESET__LBSI_SOFT_RESET__SHIFT 0x00000001
+#define UVD_SOFT_RESET__LCM_SOFT_RESET_MASK 0x00010000L
+#define UVD_SOFT_RESET__LCM_SOFT_RESET__SHIFT 0x00000010
+#define UVD_SOFT_RESET__LMI_SOFT_RESET_MASK 0x00000004L
+#define UVD_SOFT_RESET__LMI_SOFT_RESET__SHIFT 0x00000002
+#define UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK 0x00002000L
+#define UVD_SOFT_RESET__LMI_UMC_SOFT_RESET__SHIFT 0x0000000d
+#define UVD_SOFT_RESET__MIF_SOFT_RESET_MASK 0x00008000L
+#define UVD_SOFT_RESET__MIF_SOFT_RESET__SHIFT 0x0000000f
+#define UVD_SOFT_RESET__MPC_SOFT_RESET_MASK 0x00000100L
+#define UVD_SOFT_RESET__MPC_SOFT_RESET__SHIFT 0x00000008
+#define UVD_SOFT_RESET__MPRD_SOFT_RESET_MASK 0x00000800L
+#define UVD_SOFT_RESET__MPRD_SOFT_RESET__SHIFT 0x0000000b
+#define UVD_SOFT_RESET__RBC_SOFT_RESET_MASK 0x00000001L
+#define UVD_SOFT_RESET__RBC_SOFT_RESET__SHIFT 0x00000000
+#define UVD_SOFT_RESET__SPH_SOFT_RESET_MASK 0x00004000L
+#define UVD_SOFT_RESET__SPH_SOFT_RESET__SHIFT 0x0000000e
+#define UVD_SOFT_RESET__TAP_SOFT_RESET_MASK 0x00000080L
+#define UVD_SOFT_RESET__TAP_SOFT_RESET__SHIFT 0x00000007
+#define UVD_SOFT_RESET__UDEC_SOFT_RESET_MASK 0x00000010L
+#define UVD_SOFT_RESET__UDEC_SOFT_RESET__SHIFT 0x00000004
+#define UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK 0x00000008L
+#define UVD_SOFT_RESET__VCPU_SOFT_RESET__SHIFT 0x00000003
+#define UVD_STATUS__RBC_BUSY_MASK 0x00000001L
+#define UVD_STATUS__RBC_BUSY__SHIFT 0x00000000
+#define UVD_STATUS__VCPU_REPORT_MASK 0x000000feL
+#define UVD_STATUS__VCPU_REPORT__SHIFT 0x00000001
+#define UVD_UDEC_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_UDEC_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_UDEC_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_UDEC_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_UDEC_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_UDEC_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_UDEC_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_UDEC_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_UDEC_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_UDEC_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_UDEC_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_UDEC_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_UDEC_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_UDEC_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_UDEC_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_UDEC_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_UDEC_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_UDEC_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_UDEC_DB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_UDEC_DB_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_UDEC_DB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_UDEC_DB_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_UDEC_DB_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_UDEC_DB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_UDEC_DB_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_UDEC_DB_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_UDEC_DB_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_UDEC_DB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_UDEC_DB_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_UDEC_DBW_ADDR_CONFIG__BANK_INTERLEAVE_SIZE_MASK 0x00000700L
+#define UVD_UDEC_DBW_ADDR_CONFIG__BANK_INTERLEAVE_SIZE__SHIFT 0x00000008
+#define UVD_UDEC_DBW_ADDR_CONFIG__MULTI_GPU_TILE_SIZE_MASK 0x03000000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__MULTI_GPU_TILE_SIZE__SHIFT 0x00000018
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_GPUS_MASK 0x00700000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_GPUS__SHIFT 0x00000014
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_LOWER_PIPES_MASK 0x40000000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_LOWER_PIPES__SHIFT 0x0000001e
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_PIPES_MASK 0x00000007L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_PIPES__SHIFT 0x00000000
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK 0x00003000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT 0x0000000c
+#define UVD_UDEC_DBW_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE_MASK 0x00000070L
+#define UVD_UDEC_DBW_ADDR_CONFIG__PIPE_INTERLEAVE_SIZE__SHIFT 0x00000004
+#define UVD_UDEC_DBW_ADDR_CONFIG__ROW_SIZE_MASK 0x30000000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__ROW_SIZE__SHIFT 0x0000001c
+#define UVD_UDEC_DBW_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE_MASK 0x00070000L
+#define UVD_UDEC_DBW_ADDR_CONFIG__SHADER_ENGINE_TILE_SIZE__SHIFT 0x00000010
+#define UVD_VCPU_CACHE_OFFSET0__CACHE_OFFSET0_MASK 0x01ffffffL
+#define UVD_VCPU_CACHE_OFFSET0__CACHE_OFFSET0__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_OFFSET1__CACHE_OFFSET1_MASK 0x01ffffffL
+#define UVD_VCPU_CACHE_OFFSET1__CACHE_OFFSET1__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_OFFSET2__CACHE_OFFSET2_MASK 0x01ffffffL
+#define UVD_VCPU_CACHE_OFFSET2__CACHE_OFFSET2__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_SIZE0__CACHE_SIZE0_MASK 0x001fffffL
+#define UVD_VCPU_CACHE_SIZE0__CACHE_SIZE0__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_SIZE1__CACHE_SIZE1_MASK 0x001fffffL
+#define UVD_VCPU_CACHE_SIZE1__CACHE_SIZE1__SHIFT 0x00000000
+#define UVD_VCPU_CACHE_SIZE2__CACHE_SIZE2_MASK 0x001fffffL
+#define UVD_VCPU_CACHE_SIZE2__CACHE_SIZE2__SHIFT 0x00000000
+#define UVD_VCPU_CNTL__ABORT_REQ_MASK 0x00000100L
+#define UVD_VCPU_CNTL__ABORT_REQ__SHIFT 0x00000008
+#define UVD_VCPU_CNTL__AXI_MAX_BRST_SIZE_IS_4_MASK 0x00000010L
+#define UVD_VCPU_CNTL__AXI_MAX_BRST_SIZE_IS_4__SHIFT 0x00000004
+#define UVD_VCPU_CNTL__CABAC_MB_ACC_MASK 0x10000000L
+#define UVD_VCPU_CNTL__CABAC_MB_ACC__SHIFT 0x0000001c
+#define UVD_VCPU_CNTL__CLK_ACTIVE_MASK 0x00020000L
+#define UVD_VCPU_CNTL__CLK_ACTIVE__SHIFT 0x00000011
+#define UVD_VCPU_CNTL__CLK_EN_MASK 0x00000200L
+#define UVD_VCPU_CNTL__CLK_EN__SHIFT 0x00000009
+#define UVD_VCPU_CNTL__DBG_MUX_MASK 0x0000e000L
+#define UVD_VCPU_CNTL__DBG_MUX__SHIFT 0x0000000d
+#define UVD_VCPU_CNTL__ECPU_AM32_EN_MASK 0x20000000L
+#define UVD_VCPU_CNTL__ECPU_AM32_EN__SHIFT 0x0000001d
+#define UVD_VCPU_CNTL__IRQ_ERR_MASK 0x0000000fL
+#define UVD_VCPU_CNTL__IRQ_ERR__SHIFT 0x00000000
+#define UVD_VCPU_CNTL__JTAG_EN_MASK 0x00010000L
+#define UVD_VCPU_CNTL__JTAG_EN__SHIFT 0x00000010
+#define UVD_VCPU_CNTL__PMB_ED_ENABLE_MASK 0x00000020L
+#define UVD_VCPU_CNTL__PMB_ED_ENABLE__SHIFT 0x00000005
+#define UVD_VCPU_CNTL__PMB_SOFT_RESET_MASK 0x00000040L
+#define UVD_VCPU_CNTL__PMB_SOFT_RESET__SHIFT 0x00000006
+#define UVD_VCPU_CNTL__PRB_TIMEOUT_VAL_MASK 0x0ff00000L
+#define UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT 0x00000014
+#define UVD_VCPU_CNTL__RBBM_SOFT_RESET_MASK 0x00000080L
+#define UVD_VCPU_CNTL__RBBM_SOFT_RESET__SHIFT 0x00000007
+#define UVD_VCPU_CNTL__TIMEOUT_DIS_MASK 0x00040000L
+#define UVD_VCPU_CNTL__TIMEOUT_DIS__SHIFT 0x00000012
+#define UVD_VCPU_CNTL__TRCE_EN_MASK 0x00000400L
+#define UVD_VCPU_CNTL__TRCE_EN__SHIFT 0x0000000a
+#define UVD_VCPU_CNTL__TRCE_MUX_MASK 0x00001800L
+#define UVD_VCPU_CNTL__TRCE_MUX__SHIFT 0x0000000b
+#define UVD_VCPU_CNTL__WMV9_EN_MASK 0x40000000L
+#define UVD_VCPU_CNTL__WMV9_EN__SHIFT 0x0000001e
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 VCE_1_0_D_H
+#define VCE_1_0_D_H
+
+#define mmVCE_CLOCK_GATING_A 0x80BE
+#define mmVCE_CLOCK_GATING_B 0x80BF
+#define mmVCE_LMI_CACHE_CTRL 0x83BD
+#define mmVCE_LMI_CTRL 0x83A6
+#define mmVCE_LMI_CTRL2 0x839D
+#define mmVCE_LMI_MISC_CTRL 0x83B5
+#define mmVCE_LMI_STATUS 0x83A7
+#define mmVCE_LMI_SWAP_CNTL 0x83AD
+#define mmVCE_LMI_SWAP_CNTL1 0x83AE
+#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR 0x8397
+#define mmVCE_LMI_VM_CTRL 0x83A8
+#define mmVCE_RB_ARB_CTRL 0x809F
+#define mmVCE_RB_BASE_HI 0x8061
+#define mmVCE_RB_BASE_HI2 0x805C
+#define mmVCE_RB_BASE_LO 0x8060
+#define mmVCE_RB_BASE_LO2 0x805B
+#define mmVCE_RB_RPTR 0x8063
+#define mmVCE_RB_RPTR2 0x805E
+#define mmVCE_RB_SIZE 0x8062
+#define mmVCE_RB_SIZE2 0x805D
+#define mmVCE_RB_WPTR 0x8064
+#define mmVCE_RB_WPTR2 0x805F
+#define mmVCE_SOFT_RESET 0x8048
+#define mmVCE_STATUS 0x8001
+#define mmVCE_SYS_INT_ACK 0x8341
+#define mmVCE_SYS_INT_EN 0x8340
+#define mmVCE_SYS_INT_STATUS 0x8341
+#define mmVCE_UENC_CLOCK_GATING 0x816F
+#define mmVCE_UENC_DMA_DCLK_CTRL 0x8250
+#define mmVCE_UENC_REG_CLOCK_GATING 0x8170
+#define mmVCE_VCPU_CACHE_OFFSET0 0x8009
+#define mmVCE_VCPU_CACHE_OFFSET1 0x800B
+#define mmVCE_VCPU_CACHE_OFFSET2 0x800D
+#define mmVCE_VCPU_CACHE_SIZE0 0x800A
+#define mmVCE_VCPU_CACHE_SIZE1 0x800C
+#define mmVCE_VCPU_CACHE_SIZE2 0x800E
+#define mmVCE_VCPU_CNTL 0x8005
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/asic_reg/vce/vce_1_0_sh_mask.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,99 @@
+/*
+ *
+ * Copyright (C) 2016 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) 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 VCE_1_0_SH_MASK_H
+#define VCE_1_0_SH_MASK_H
+
+#define VCE_LMI_CACHE_CTRL__VCPU_EN_MASK 0x00000001L
+#define VCE_LMI_CACHE_CTRL__VCPU_EN__SHIFT 0x00000000
+#define VCE_LMI_CTRL2__STALL_ARB_UMC_MASK 0x00000100L
+#define VCE_LMI_CTRL2__STALL_ARB_UMC__SHIFT 0x00000008
+#define VCE_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK 0x00200000L
+#define VCE_LMI_CTRL__VCPU_DATA_COHERENCY_EN__SHIFT 0x00000015
+#define VCE_LMI_SWAP_CNTL1__RD_MC_CID_SWAP_MASK 0x00003ffcL
+#define VCE_LMI_SWAP_CNTL1__RD_MC_CID_SWAP__SHIFT 0x00000002
+#define VCE_LMI_SWAP_CNTL1__VCPU_R_MC_SWAP_MASK 0x00000003L
+#define VCE_LMI_SWAP_CNTL1__VCPU_R_MC_SWAP__SHIFT 0x00000000
+#define VCE_LMI_SWAP_CNTL__VCPU_W_MC_SWAP_MASK 0x00000003L
+#define VCE_LMI_SWAP_CNTL__VCPU_W_MC_SWAP__SHIFT 0x00000000
+#define VCE_LMI_SWAP_CNTL__WR_MC_CID_SWAP_MASK 0x00003ffcL
+#define VCE_LMI_SWAP_CNTL__WR_MC_CID_SWAP__SHIFT 0x00000002
+#define VCE_LMI_VCPU_CACHE_40BIT_BAR__BAR_MASK 0xffffffffL
+#define VCE_LMI_VCPU_CACHE_40BIT_BAR__BAR__SHIFT 0x00000000
+#define VCE_RB_BASE_HI2__RB_BASE_HI_MASK 0xffffffffL
+#define VCE_RB_BASE_HI2__RB_BASE_HI__SHIFT 0x00000000
+#define VCE_RB_BASE_HI__RB_BASE_HI_MASK 0xffffffffL
+#define VCE_RB_BASE_HI__RB_BASE_HI__SHIFT 0x00000000
+#define VCE_RB_BASE_LO2__RB_BASE_LO_MASK 0xffffffc0L
+#define VCE_RB_BASE_LO2__RB_BASE_LO__SHIFT 0x00000006
+#define VCE_RB_BASE_LO__RB_BASE_LO_MASK 0xffffffc0L
+#define VCE_RB_BASE_LO__RB_BASE_LO__SHIFT 0x00000006
+#define VCE_RB_RPTR2__RB_RPTR_MASK 0x007ffff0L
+#define VCE_RB_RPTR2__RB_RPTR__SHIFT 0x00000004
+#define VCE_RB_RPTR__RB_RPTR_MASK 0x007ffff0L
+#define VCE_RB_RPTR__RB_RPTR__SHIFT 0x00000004
+#define VCE_RB_SIZE2__RB_SIZE_MASK 0x007ffff0L
+#define VCE_RB_SIZE2__RB_SIZE__SHIFT 0x00000004
+#define VCE_RB_SIZE__RB_SIZE_MASK 0x007ffff0L
+#define VCE_RB_SIZE__RB_SIZE__SHIFT 0x00000004
+#define VCE_RB_WPTR2__RB_WPTR_MASK 0x007ffff0L
+#define VCE_RB_WPTR2__RB_WPTR__SHIFT 0x00000004
+#define VCE_RB_WPTR__RB_WPTR_MASK 0x007ffff0L
+#define VCE_RB_WPTR__RB_WPTR__SHIFT 0x00000004
+#define VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK 0x00000001L
+#define VCE_SOFT_RESET__ECPU_SOFT_RESET__SHIFT 0x00000000
+#define VCE_STATUS__JOB_BUSY_MASK 0x00000001L
+#define VCE_STATUS__JOB_BUSY__SHIFT 0x00000000
+#define VCE_STATUS__UENC_BUSY_MASK 0x00000100L
+#define VCE_STATUS__UENC_BUSY__SHIFT 0x00000008
+#define VCE_STATUS__VCPU_REPORT_MASK 0x000000feL
+#define VCE_STATUS__VCPU_REPORT__SHIFT 0x00000001
+#define VCE_SYS_INT_ACK__VCE_SYS_INT_TRAP_INTERRUPT_ACK_MASK 0x00000008L
+#define VCE_SYS_INT_ACK__VCE_SYS_INT_TRAP_INTERRUPT_ACK__SHIFT 0x00000003
+#define VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK 0x00000008L
+#define VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN__SHIFT 0x00000003
+#define VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT_MASK 0x00000008L
+#define VCE_SYS_INT_STATUS__VCE_SYS_INT_TRAP_INTERRUPT_INT__SHIFT 0x00000003
+#define VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK 0x00000002L
+#define VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON__SHIFT 0x00000001
+#define VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK 0x00000004L
+#define VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON__SHIFT 0x00000002
+#define VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK 0x00000001L
+#define VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_OFFSET0__OFFSET_MASK 0x0fffffffL
+#define VCE_VCPU_CACHE_OFFSET0__OFFSET__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_OFFSET1__OFFSET_MASK 0x0fffffffL
+#define VCE_VCPU_CACHE_OFFSET1__OFFSET__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_OFFSET2__OFFSET_MASK 0x0fffffffL
+#define VCE_VCPU_CACHE_OFFSET2__OFFSET__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_SIZE0__SIZE_MASK 0x00ffffffL
+#define VCE_VCPU_CACHE_SIZE0__SIZE__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_SIZE1__SIZE_MASK 0x00ffffffL
+#define VCE_VCPU_CACHE_SIZE1__SIZE__SHIFT 0x00000000
+#define VCE_VCPU_CACHE_SIZE2__SIZE_MASK 0x00ffffffL
+#define VCE_VCPU_CACHE_SIZE2__SIZE__SHIFT 0x00000000
+#define VCE_VCPU_CNTL__CLK_EN_MASK 0x00000001L
+#define VCE_VCPU_CNTL__CLK_EN__SHIFT 0x00000000
+#define VCE_VCPU_CNTL__RBBM_SOFT_RESET_MASK 0x00040000L
+#define VCE_VCPU_CNTL__RBBM_SOFT_RESET__SHIFT 0x00000012
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/cgs_common.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/cgs_common.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/include/cgs_common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/include/cgs_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -106,6 +106,7 @@ enum cgs_ucode_id {
 	CGS_UCODE_ID_CP_MEC_JT2,
 	CGS_UCODE_ID_GMCON_RENG,
 	CGS_UCODE_ID_RLC_G,
+	CGS_UCODE_ID_STORAGE,
 	CGS_UCODE_ID_MAXIMUM,
 };
 
@@ -619,6 +620,8 @@ typedef int (*cgs_call_acpi_method)(stru
 typedef int (*cgs_query_system_info)(struct cgs_device *cgs_device,
 				struct cgs_system_info *sys_info);
 
+typedef int (*cgs_is_virtualization_enabled_t)(void *cgs_device);
+
 struct cgs_ops {
 	/* memory management calls (similar to KFD interface) */
 	cgs_gpu_mem_info_t gpu_mem_info;
@@ -670,6 +673,7 @@ struct cgs_ops {
 	cgs_call_acpi_method call_acpi_method;
 	/* get system info */
 	cgs_query_system_info query_system_info;
+	cgs_is_virtualization_enabled_t is_virtualization_enabled;
 };
 
 struct cgs_os_ops; /* To be define in OS-specific CGS header */
@@ -773,4 +777,6 @@ struct cgs_device
 	CGS_CALL(get_pci_resource, cgs_device, resource_type, size, offset, \
 	resource_base)
 
+#define cgs_is_virtualization_enabled(cgs_device) \
+		CGS_CALL(is_virtualization_enabled, cgs_device)
 #endif /* _CGS_COMMON_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/amd_powerplay.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@
 #define PP_CHECK_HW(hwmgr)						\
 	do {								\
 		if ((hwmgr) == NULL || (hwmgr)->hwmgr_func == NULL)	\
-			return -EINVAL;					\
+			return 0;					\
 	} while (0)
 
 static int pp_early_init(void *handle)
@@ -115,6 +115,7 @@ static int pp_hw_init(void *handle)
 	struct pp_instance *pp_handle;
 	struct pp_smumgr *smumgr;
 	struct pp_eventmgr *eventmgr;
+	struct pp_hwmgr  *hwmgr;
 	int ret = 0;
 
 	if (handle == NULL)
@@ -122,6 +123,7 @@ static int pp_hw_init(void *handle)
 
 	pp_handle = (struct pp_instance *)handle;
 	smumgr = pp_handle->smu_mgr;
+	hwmgr = pp_handle->hwmgr;
 
 	if (smumgr == NULL || smumgr->smumgr_funcs == NULL ||
 		smumgr->smumgr_funcs->smu_init == NULL ||
@@ -141,9 +143,11 @@ static int pp_hw_init(void *handle)
 		return ret;
 	}
 
-	hw_init_power_state_table(pp_handle->hwmgr);
-	eventmgr = pp_handle->eventmgr;
+	PP_CHECK_HW(hwmgr);
+
+	hw_init_power_state_table(hwmgr);
 
+	eventmgr = pp_handle->eventmgr;
 	if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
 		return -EINVAL;
 
@@ -243,7 +247,9 @@ static int pp_suspend(void *handle)
 
 	pp_handle = (struct pp_instance *)handle;
 	eventmgr = pp_handle->eventmgr;
-	pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
+
+	if (eventmgr != NULL)
+		pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data);
 	return 0;
 }
 
@@ -273,7 +279,8 @@ static int pp_resume(void *handle)
 	}
 
 	eventmgr = pp_handle->eventmgr;
-	pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
+	if (eventmgr != NULL)
+		pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data);
 
 	return 0;
 }
@@ -340,8 +347,7 @@ static enum amd_dpm_forced_level pp_dpm_
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
-	if (hwmgr == NULL)
-		return -EINVAL;
+	PP_CHECK_HW(hwmgr);
 
 	return (((struct pp_instance *)handle)->hwmgr->dpm_level);
 }
@@ -436,7 +442,8 @@ static enum PP_StateUILabel power_state_
 	}
 }
 
-int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output)
+static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id,
+		void *input, void *output)
 {
 	int ret = 0;
 	struct pp_instance *pp_handle;
@@ -447,6 +454,9 @@ int pp_dpm_dispatch_tasks(void *handle,
 	if (pp_handle == NULL)
 		return -EINVAL;
 
+	if (pp_handle->eventmgr == NULL)
+		return 0;
+
 	switch (event_id) {
 	case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE:
 		ret = pem_handle_event(pp_handle->eventmgr, event_id, &data);
@@ -475,7 +485,7 @@ int pp_dpm_dispatch_tasks(void *handle,
 	return ret;
 }
 
-enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
+static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle)
 {
 	struct pp_hwmgr *hwmgr;
 	struct pp_power_state *state;
@@ -581,6 +591,23 @@ static int pp_dpm_get_fan_speed_percent(
 	return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed);
 }
 
+static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
+{
+	struct pp_hwmgr *hwmgr;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+	PP_CHECK_HW(hwmgr);
+
+	if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL)
+		return -EINVAL;
+
+	return hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm);
+}
+
 static int pp_dpm_get_temperature(void *handle)
 {
 	struct pp_hwmgr  *hwmgr;
@@ -820,6 +847,21 @@ static int pp_dpm_read_sensor(void *hand
 	return hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value);
 }
 
+static struct amd_vce_state*
+pp_dpm_get_vce_clock_state(void *handle, unsigned idx)
+{
+	struct pp_hwmgr *hwmgr;
+
+	if (handle) {
+		hwmgr = ((struct pp_instance *)handle)->hwmgr;
+
+		if (hwmgr && idx < hwmgr->num_vce_state_tables)
+			return &hwmgr->vce_states[idx];
+	}
+
+	return NULL;
+}
+
 const struct amd_powerplay_funcs pp_dpm_funcs = {
 	.get_temperature = pp_dpm_get_temperature,
 	.load_firmware = pp_dpm_load_fw,
@@ -836,6 +878,7 @@ const struct amd_powerplay_funcs pp_dpm_
 	.get_fan_control_mode = pp_dpm_get_fan_control_mode,
 	.set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
 	.get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
+	.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
 	.get_pp_num_states = pp_dpm_get_pp_num_states,
 	.get_pp_table = pp_dpm_get_pp_table,
 	.set_pp_table = pp_dpm_set_pp_table,
@@ -846,6 +889,7 @@ const struct amd_powerplay_funcs pp_dpm_
 	.get_mclk_od = pp_dpm_get_mclk_od,
 	.set_mclk_od = pp_dpm_set_mclk_od,
 	.read_sensor = pp_dpm_read_sensor,
+	.get_vce_clock_state = pp_dpm_get_vce_clock_state,
 };
 
 static int amd_pp_instance_init(struct amd_pp_init *pp_init,
@@ -864,6 +908,13 @@ static int amd_pp_instance_init(struct a
 	if (ret)
 		goto fail_smum;
 
+
+	amd_pp->pp_handle = handle;
+
+	if ((amdgpu_dpm == 0)
+		|| cgs_is_virtualization_enabled(pp_init->device))
+		return 0;
+
 	ret = hwmgr_init(pp_init, handle);
 	if (ret)
 		goto fail_hwmgr;
@@ -872,7 +923,6 @@ static int amd_pp_instance_init(struct a
 	if (ret)
 		goto fail_eventmgr;
 
-	amd_pp->pp_handle = handle;
 	return 0;
 
 fail_eventmgr:
@@ -891,12 +941,13 @@ static int amd_pp_instance_fini(void *ha
 	if (instance == NULL)
 		return -EINVAL;
 
-	eventmgr_fini(instance->eventmgr);
-
-	hwmgr_fini(instance->hwmgr);
+	if ((amdgpu_dpm != 0)
+		&& !cgs_is_virtualization_enabled(instance->smu_mgr->device)) {
+		eventmgr_fini(instance->eventmgr);
+		hwmgr_fini(instance->hwmgr);
+	}
 
 	smum_fini(instance->smu_mgr);
-
 	kfree(handle);
 	return 0;
 }
@@ -953,6 +1004,10 @@ int amd_powerplay_reset(void *handle)
 	if (ret)
 		return ret;
 
+	if ((amdgpu_dpm == 0)
+		|| cgs_is_virtualization_enabled(instance->smu_mgr->device))
+		return 0;
+
 	hw_init_power_state_table(instance->hwmgr);
 
 	if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL)
@@ -976,6 +1031,8 @@ int amd_powerplay_display_configuration_
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
+	PP_CHECK_HW(hwmgr);
+
 	phm_store_dal_configuration_data(hwmgr, display_config);
 
 	return 0;
@@ -993,6 +1050,8 @@ int amd_powerplay_get_display_power_leve
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
+	PP_CHECK_HW(hwmgr);
+
 	return phm_get_dal_power_level(hwmgr, output);
 }
 
@@ -1010,6 +1069,8 @@ int amd_powerplay_get_current_clocks(voi
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
+	PP_CHECK_HW(hwmgr);
+
 	phm_get_dal_power_level(hwmgr, &simple_clocks);
 
 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerContainment)) {
@@ -1054,6 +1115,8 @@ int amd_powerplay_get_clock_by_type(void
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
+	PP_CHECK_HW(hwmgr);
+
 	result = phm_get_clock_by_type(hwmgr, type, clocks);
 
 	return result;
@@ -1072,6 +1135,8 @@ int amd_powerplay_get_display_mode_valid
 
 	hwmgr = ((struct pp_instance *)handle)->hwmgr;
 
+	PP_CHECK_HW(hwmgr);
+
 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState))
 		result = phm_get_max_high_clocks(hwmgr, clocks);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c	2017-02-12 16:03:20.000000000 -0500
@@ -154,7 +154,7 @@ int pem_task_powerdown_vce_tasks(struct
 
 int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
 {
-	/* TODO */
+	phm_disable_clock_power_gatings(eventmgr->hwmgr);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c	2017-02-12 16:03:20.000000000 -0500
@@ -169,7 +169,7 @@ int cz_dpm_powergate_uvd(struct pp_hwmgr
 	if (bgate) {
 		cgs_set_clockgating_state(hwmgr->device,
 						AMD_IP_BLOCK_TYPE_UVD,
-						AMD_CG_STATE_UNGATE);
+						AMD_CG_STATE_GATE);
 		cgs_set_powergating_state(hwmgr->device,
 						AMD_IP_BLOCK_TYPE_UVD,
 						AMD_PG_STATE_GATE);
@@ -182,7 +182,7 @@ int cz_dpm_powergate_uvd(struct pp_hwmgr
 						AMD_CG_STATE_UNGATE);
 		cgs_set_clockgating_state(hwmgr->device,
 						AMD_IP_BLOCK_TYPE_UVD,
-						AMD_PG_STATE_GATE);
+						AMD_PG_STATE_UNGATE);
 		cz_dpm_update_uvd_dpm(hwmgr, false);
 	}
 
@@ -200,7 +200,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr
 				cgs_set_clockgating_state(
 							hwmgr->device,
 							AMD_IP_BLOCK_TYPE_VCE,
-							AMD_CG_STATE_UNGATE);
+							AMD_CG_STATE_GATE);
 				cgs_set_powergating_state(
 							hwmgr->device,
 							AMD_IP_BLOCK_TYPE_VCE,
@@ -218,7 +218,7 @@ int cz_dpm_powergate_vce(struct pp_hwmgr
 				cgs_set_clockgating_state(
 							hwmgr->device,
 							AMD_IP_BLOCK_TYPE_VCE,
-							AMD_PG_STATE_GATE);
+							AMD_PG_STATE_UNGATE);
 				cz_dpm_update_vce_dpm(hwmgr);
 				cz_enable_disable_vce_dpm(hwmgr, true);
 				return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,7 +66,7 @@ static const struct cz_power_state *cast
 	return (struct cz_power_state *)hw_ps;
 }
 
-uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr,
+static uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr,
 					uint32_t clock, uint32_t msg)
 {
 	int i = 0;
@@ -1017,7 +1017,7 @@ static int cz_tf_program_bootup_state(st
 	return 0;
 }
 
-int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input,
+static int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input,
 				void *output, void *storage, int result)
 {
 	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
@@ -1225,7 +1225,7 @@ static int cz_hwmgr_backend_fini(struct
 	return 0;
 }
 
-int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr)
+static int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr)
 {
 	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
 
@@ -1239,7 +1239,7 @@ int cz_phm_force_dpm_highest(struct pp_h
 	return 0;
 }
 
-int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
+static int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
 {
 	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
 	struct phm_clock_voltage_dependency_table *table =
@@ -1277,7 +1277,7 @@ int cz_phm_unforce_dpm_levels(struct pp_
 	return 0;
 }
 
-int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr)
+static int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr)
 {
 	struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
 
@@ -1402,14 +1402,22 @@ int  cz_dpm_update_vce_dpm(struct pp_hwm
 					     cz_hwmgr->vce_dpm.hard_min_clk,
 						PPSMC_MSG_SetEclkHardMin));
 	} else {
-		/*EPR# 419220 -HW limitation to to */
-		cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
-		smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
-					    PPSMC_MSG_SetEclkHardMin,
-					    cz_get_eclk_level(hwmgr,
-				     cz_hwmgr->vce_dpm.hard_min_clk,
-					  PPSMC_MSG_SetEclkHardMin));
-
+		/*Program HardMin based on the vce_arbiter.ecclk */
+		if (hwmgr->vce_arbiter.ecclk == 0) {
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					    PPSMC_MSG_SetEclkHardMin, 0);
+		/* disable ECLK DPM 0. Otherwise VCE could hang if
+		 * switching SCLK from DPM 0 to 6/7 */
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+					PPSMC_MSG_SetEclkSoftMin, 1);
+		} else {
+			cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
+			smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+						PPSMC_MSG_SetEclkHardMin,
+						cz_get_eclk_level(hwmgr,
+						cz_hwmgr->vce_dpm.hard_min_clk,
+						PPSMC_MSG_SetEclkHardMin));
+		}
 	}
 	return 0;
 }
@@ -1533,7 +1541,7 @@ static int cz_dpm_get_pp_table_entry(str
 	return result;
 }
 
-int cz_get_power_state_size(struct pp_hwmgr *hwmgr)
+static int cz_get_power_state_size(struct pp_hwmgr *hwmgr)
 {
 	return sizeof(struct cz_power_state);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@ static int phm_run_table(struct pp_hwmgr
 	phm_table_function *function;
 
 	if (rt_table->function_list == NULL) {
-		printk(KERN_INFO "[ powerplay ] this function not implement!\n");
+		pr_debug("[ powerplay ] this function not implement!\n");
 		return 0;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c	2017-02-12 16:03:20.000000000 -0500
@@ -209,6 +209,19 @@ int phm_enable_clock_power_gatings(struc
 	return 0;
 }
 
+int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr)
+{
+	PHM_FUNC_CHECK(hwmgr);
+
+	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+		PHM_PlatformCaps_TablelessHardwareInterface)) {
+		if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating)
+			return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr);
+	}
+	return 0;
+}
+
+
 int phm_display_configuration_changed(struct pp_hwmgr *hwmgr)
 {
 	PHM_FUNC_CHECK(hwmgr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,24 +80,22 @@ int hwmgr_init(struct amd_pp_init *pp_in
 		switch (hwmgr->chip_id) {
 		case CHIP_TOPAZ:
 			topaz_set_asic_special_caps(hwmgr);
-			hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
-						PP_VBI_TIME_SUPPORT_MASK |
+			hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
 						PP_ENABLE_GFX_CG_THRU_SMU);
 			hwmgr->pp_table_version = PP_TABLE_V0;
 			break;
 		case CHIP_TONGA:
 			tonga_set_asic_special_caps(hwmgr);
-			hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
-						PP_VBI_TIME_SUPPORT_MASK);
+			hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK;
 			break;
 		case CHIP_FIJI:
 			fiji_set_asic_special_caps(hwmgr);
-			hwmgr->feature_mask &= ~(PP_SMC_VOLTAGE_CONTROL_MASK |
-						PP_VBI_TIME_SUPPORT_MASK |
+			hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK |
 						PP_ENABLE_GFX_CG_THRU_SMU);
 			break;
 		case CHIP_POLARIS11:
 		case CHIP_POLARIS10:
+		case CHIP_POLARIS12:
 			polaris_set_asic_special_caps(hwmgr);
 			hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK);
 			break;
@@ -685,20 +683,24 @@ void hwmgr_init_default_caps(struct pp_h
 
 int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr)
 {
-	if (amdgpu_sclk_deep_sleep_en)
+	if (amdgpu_pp_feature_mask & PP_SCLK_DEEP_SLEEP_MASK)
 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 			PHM_PlatformCaps_SclkDeepSleep);
 	else
 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 			PHM_PlatformCaps_SclkDeepSleep);
 
-	if (amdgpu_powercontainment)
+	if (amdgpu_pp_feature_mask & PP_POWER_CONTAINMENT_MASK) {
 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 			    PHM_PlatformCaps_PowerContainment);
-	else
+		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_CAC);
+	} else {
 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 			    PHM_PlatformCaps_PowerContainment);
-
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_CAC);
+	}
 	hwmgr->feature_mask = amdgpu_pp_feature_mask;
 
 	return 0;
@@ -736,9 +738,6 @@ int polaris_set_asic_special_caps(struct
 						PHM_PlatformCaps_TCPRamping);
 
 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
-							PHM_PlatformCaps_CAC);
-
-	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 						PHM_PlatformCaps_RegulatorHot);
 
 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
@@ -747,7 +746,7 @@ int polaris_set_asic_special_caps(struct
 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 				PHM_PlatformCaps_TablelessHardwareInterface);
 
-	if (hwmgr->chip_id == CHIP_POLARIS11)
+	if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12))
 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 					PHM_PlatformCaps_SPLLShutdownSupport);
 	return 0;
@@ -767,8 +766,6 @@ int fiji_set_asic_special_caps(struct pp
 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 			PHM_PlatformCaps_TablelessHardwareInterface);
 
-	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
-			PHM_PlatformCaps_CAC);
 	return 0;
 }
 
@@ -791,9 +788,6 @@ int tonga_set_asic_special_caps(struct p
 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 			 PHM_PlatformCaps_TablelessHardwareInterface);
 
-	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
-			PHM_PlatformCaps_CAC);
-
 	return 0;
 }
 
@@ -810,8 +804,6 @@ int topaz_set_asic_special_caps(struct p
 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 			 PHM_PlatformCaps_TablelessHardwareInterface);
 	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
-			PHM_PlatformCaps_CAC);
-	phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 		    PHM_PlatformCaps_EVV);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,6 +25,7 @@
 #include "linux/delay.h"
 #include "hwmgr.h"
 #include "amd_acpi.h"
+#include "pp_acpi.h"
 
 bool acpi_atcs_functions_supported(void *device, uint32_t index)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c	2017-02-12 16:03:20.000000000 -0500
@@ -1507,7 +1507,7 @@ static int init_phase_shedding_table(str
 	return 0;
 }
 
-int get_number_of_vce_state_table_entries(
+static int get_number_of_vce_state_table_entries(
 						  struct pp_hwmgr *hwmgr)
 {
 	const ATOM_PPLIB_POWERPLAYTABLE *table =
@@ -1521,9 +1521,9 @@ int get_number_of_vce_state_table_entrie
 	return 0;
 }
 
-int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
+static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,
 							unsigned long i,
-							struct pp_vce_state *vce_state,
+							struct amd_vce_state *vce_state,
 							void **clock_info,
 							unsigned long *flag)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c	2017-02-12 16:03:20.000000000 -0500
@@ -131,7 +131,7 @@ static int set_platform_caps(struct pp_h
 /**
  * Private Function to get the PowerPlay Table Address.
  */
-const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
+static const void *get_powerplay_table(struct pp_hwmgr *hwmgr)
 {
 	int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo);
 
@@ -1049,7 +1049,7 @@ static int check_powerplay_tables(
 	return 0;
 }
 
-int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
+static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr)
 {
 	int result = 0;
 	const ATOM_Tonga_POWERPLAYTABLE *powerplay_table;
@@ -1100,7 +1100,7 @@ int pp_tables_v1_0_initialize(struct pp_
 	return result;
 }
 
-int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr)
+static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr)
 {
 	struct phm_ppt_v1_information *pp_table_information =
 		(struct phm_ppt_v1_information *)(hwmgr->pptable);
@@ -1214,7 +1214,7 @@ static int ppt_get_num_of_vce_state_tabl
 }
 
 static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i,
-		struct pp_vce_state *vce_state, void **clock_info, uint32_t *flag)
+		struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag)
 {
 	const ATOM_Tonga_VCE_State_Record *vce_state_record;
 	ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record;
@@ -1318,7 +1318,7 @@ int get_powerplay_table_entry_v1_0(struc
 
 	hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr);
 
-	if ((i != 0) && (i <= PP_MAX_VCE_LEVELS)) {
+	if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) {
 		for (j = 0; j < i; j++)
 			ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,7 @@ int smu7_powerdown_uvd(struct pp_hwmgr *
 	return 0;
 }
 
-int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
+static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr)
 {
 	if (phm_cf_want_uvd_power_gating(hwmgr)) {
 		if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
@@ -91,7 +91,7 @@ int smu7_powerup_uvd(struct pp_hwmgr *hw
 	return 0;
 }
 
-int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
+static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr)
 {
 	if (phm_cf_want_vce_power_gating(hwmgr))
 		return smum_send_msg_to_smc(hwmgr->smumgr,
@@ -99,7 +99,7 @@ int smu7_powerdown_vce(struct pp_hwmgr *
 	return 0;
 }
 
-int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
+static int smu7_powerup_vce(struct pp_hwmgr *hwmgr)
 {
 	if (phm_cf_want_vce_power_gating(hwmgr))
 		return smum_send_msg_to_smc(hwmgr->smumgr,
@@ -107,7 +107,7 @@ int smu7_powerup_vce(struct pp_hwmgr *hw
 	return 0;
 }
 
-int smu7_powerdown_samu(struct pp_hwmgr *hwmgr)
+static int smu7_powerdown_samu(struct pp_hwmgr *hwmgr)
 {
 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 			PHM_PlatformCaps_SamuPowerGating))
@@ -116,7 +116,7 @@ int smu7_powerdown_samu(struct pp_hwmgr
 	return 0;
 }
 
-int smu7_powerup_samu(struct pp_hwmgr *hwmgr)
+static int smu7_powerup_samu(struct pp_hwmgr *hwmgr)
 {
 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 			PHM_PlatformCaps_SamuPowerGating))
@@ -150,14 +150,20 @@ int smu7_powergate_uvd(struct pp_hwmgr *
 		cgs_set_clockgating_state(hwmgr->device,
 				AMD_IP_BLOCK_TYPE_UVD,
 				AMD_CG_STATE_GATE);
+		cgs_set_powergating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_PG_STATE_GATE);
 		smu7_update_uvd_dpm(hwmgr, true);
 		smu7_powerdown_uvd(hwmgr);
 	} else {
 		smu7_powerup_uvd(hwmgr);
-		smu7_update_uvd_dpm(hwmgr, false);
+		cgs_set_powergating_state(hwmgr->device,
+						AMD_IP_BLOCK_TYPE_UVD,
+						AMD_CG_STATE_UNGATE);
 		cgs_set_clockgating_state(hwmgr->device,
 				AMD_IP_BLOCK_TYPE_UVD,
 				AMD_CG_STATE_UNGATE);
+		smu7_update_uvd_dpm(hwmgr, false);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,7 @@ enum DPM_EVENT_SRC {
 
 static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic);
 
-struct smu7_power_state *cast_phw_smu7_power_state(
+static struct smu7_power_state *cast_phw_smu7_power_state(
 				  struct pp_hw_power_state *hw_ps)
 {
 	PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
@@ -99,7 +99,7 @@ struct smu7_power_state *cast_phw_smu7_p
 	return (struct smu7_power_state *)hw_ps;
 }
 
-const struct smu7_power_state *cast_const_phw_smu7_power_state(
+static const struct smu7_power_state *cast_const_phw_smu7_power_state(
 				 const struct pp_hw_power_state *hw_ps)
 {
 	PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic),
@@ -115,7 +115,7 @@ const struct smu7_power_state *cast_cons
  * @param    hwmgr  the address of the powerplay hardware manager.
  * @return   always 0
  */
-int smu7_get_mc_microcode_version (struct pp_hwmgr *hwmgr)
+static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr)
 {
 	cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
 
@@ -124,7 +124,7 @@ int smu7_get_mc_microcode_version (struc
 	return 0;
 }
 
-uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
+static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr)
 {
 	uint32_t speedCntl = 0;
 
@@ -135,7 +135,7 @@ uint16_t smu7_get_current_pcie_speed(str
 			PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE));
 }
 
-int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
+static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr)
 {
 	uint32_t link_width;
 
@@ -155,7 +155,7 @@ int smu7_get_current_pcie_lane_number(st
 * @param    pHwMgr  the address of the powerplay hardware manager.
 * @return   always PP_Result_OK
 */
-int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
+static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr)
 {
 	if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK)
 		smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Enable);
@@ -802,7 +802,7 @@ static int smu7_setup_dpm_tables_v1(stru
 	return 0;
 }
 
-int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
+static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
 {
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
@@ -993,13 +993,6 @@ static int smu7_start_dpm(struct pp_hwmg
 	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE,
 			SWRST_COMMAND_1, RESETLC, 0x0);
 
-	PP_ASSERT_WITH_CODE(
-			(0 == smum_send_msg_to_smc(hwmgr->smumgr,
-					PPSMC_MSG_Voltage_Cntl_Enable)),
-			"Failed to enable voltage DPM during DPM Start Function!",
-			return -EINVAL);
-
-
 	if (smu7_enable_sclk_mclk_dpm(hwmgr)) {
 		printk(KERN_ERR "Failed to enable Sclk DPM and Mclk DPM!");
 		return -EINVAL;
@@ -1153,7 +1146,7 @@ static int smu7_disable_thermal_auto_thr
 	return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal);
 }
 
-int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
+static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr)
 {
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 	data->pcie_performance_request = true;
@@ -1161,7 +1154,7 @@ int smu7_pcie_performance_request(struct
 	return 0;
 }
 
-int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
 {
 	int tmp_result = 0;
 	int result = 0;
@@ -1352,6 +1345,8 @@ static void smu7_init_dpm_defaults(struc
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 	struct phm_ppt_v1_information *table_info =
 			(struct phm_ppt_v1_information *)(hwmgr->pptable);
+	struct cgs_system_info sys_info = {0};
+	int result;
 
 	data->dll_default_on = false;
 	data->mclk_dpm0_activity_target = 0xa;
@@ -1426,7 +1421,7 @@ static void smu7_init_dpm_defaults(struc
 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 				PHM_PlatformCaps_ControlVDDCI);
 
-	if ((hwmgr->pp_table_version != PP_TABLE_V0)
+	if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK)
 		&& (table_info->cac_dtp_table->usClockStretchAmount != 0))
 		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
 					PHM_PlatformCaps_ClockStretcher);
@@ -1439,6 +1434,18 @@ static void smu7_init_dpm_defaults(struc
 	data->pcie_lane_performance.min = 16;
 	data->pcie_lane_power_saving.max = 0;
 	data->pcie_lane_power_saving.min = 16;
+
+	sys_info.size = sizeof(struct cgs_system_info);
+	sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
+	result = cgs_query_system_info(hwmgr->device, &sys_info);
+	if (!result) {
+		if (sys_info.value & AMD_PG_SUPPORT_UVD)
+			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				      PHM_PlatformCaps_UVDPowerGating);
+		if (sys_info.value & AMD_PG_SUPPORT_VCE)
+			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+				      PHM_PlatformCaps_VCEPowerGating);
+	}
 }
 
 /**
@@ -1865,7 +1872,7 @@ static int smu7_set_private_data_based_o
 	return 0;
 }
 
-int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
+static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr)
 {
 	struct phm_ppt_v1_information *table_info =
 		       (struct phm_ppt_v1_information *)(hwmgr->pptable);
@@ -1994,8 +2001,9 @@ static int smu7_thermal_parameter_init(s
 
 		hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp =
 			       table_info->cac_dtp_table->usTargetOperatingTemp;
-		phm_cap_set(hwmgr->platform_descriptor.platformCaps,
-						PHM_PlatformCaps_ODFuzzyFanControlSupport);
+		if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK)
+			phm_cap_set(hwmgr->platform_descriptor.platformCaps,
+					PHM_PlatformCaps_ODFuzzyFanControlSupport);
 	}
 
 	return 0;
@@ -2259,7 +2267,7 @@ static int smu7_set_private_data_based_o
 	return 0;
 }
 
-int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
+static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 {
 	struct smu7_hwmgr *data;
 	int result;
@@ -3678,14 +3686,16 @@ static int smu7_set_max_fan_pwm_output(s
 			PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm);
 }
 
-int smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
+static int
+smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display)
 {
 	PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay;
 
 	return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ?  0 : -1;
 }
 
-int smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
+static int
+smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr)
 {
 	uint32_t num_active_displays = 0;
 	struct cgs_display_info info = {0};
@@ -3707,7 +3717,7 @@ int smu7_notify_smc_display_config_after
 * @param    hwmgr  the address of the powerplay hardware manager.
 * @return   always OK
 */
-int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
+static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
 {
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 	uint32_t num_active_displays = 0;
@@ -3757,7 +3767,7 @@ int smu7_program_display_gap(struct pp_h
 	return 0;
 }
 
-int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
+static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr)
 {
 	return smu7_program_display_gap(hwmgr);
 }
@@ -3781,13 +3791,14 @@ static int smu7_set_max_fan_rpm_output(s
 			PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm);
 }
 
-int smu7_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
+static int smu7_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr,
 					const void *thermal_interrupt_info)
 {
 	return 0;
 }
 
-bool smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
+static bool
+smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr)
 {
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 	bool is_update_required = false;
@@ -3816,7 +3827,9 @@ static inline bool smu7_are_power_levels
 		  (pl1->pcie_lane == pl2->pcie_lane));
 }
 
-int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal)
+static int smu7_check_states_equal(struct pp_hwmgr *hwmgr,
+		const struct pp_hw_power_state *pstate1,
+		const struct pp_hw_power_state *pstate2, bool *equal)
 {
 	const struct smu7_power_state *psa;
 	const struct smu7_power_state *psb;
@@ -3849,7 +3862,7 @@ int smu7_check_states_equal(struct pp_hw
 	return 0;
 }
 
-int smu7_upload_mc_firmware(struct pp_hwmgr *hwmgr)
+static int smu7_upload_mc_firmware(struct pp_hwmgr *hwmgr)
 {
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
@@ -3978,7 +3991,7 @@ static int smu7_init_sclk_threshold(stru
 	return 0;
 }
 
-int smu7_setup_asic_task(struct pp_hwmgr *hwmgr)
+static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr)
 {
 	int tmp_result, result = 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c	2017-02-12 16:03:20.000000000 -0500
@@ -521,7 +521,7 @@ int smu7_enable_didt_config(struct pp_hw
 				PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
 				result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris10);
 				PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
-			} else if (hwmgr->chip_id == CHIP_POLARIS11) {
+			} else if ((hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12)) {
 				result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11);
 				PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", return result);
 				result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11);
@@ -603,9 +603,10 @@ int smu7_set_power_limit(struct pp_hwmgr
 	return 0;
 }
 
-static int smu7_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp)
+static int smu7_set_overdriver_target_tdp(struct pp_hwmgr *hwmgr,
+						uint32_t target_tdp)
 {
-	return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr,
+	return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
 			PPSMC_MSG_OverDriveSetTargetTdp, target_tdp);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,8 @@
 #include "amd_shared.h"
 #include "cgs_common.h"
 
+extern int amdgpu_dpm;
+
 enum amd_pp_sensors {
 	AMDGPU_PP_SENSOR_GFX_SCLK = 0,
 	AMDGPU_PP_SENSOR_VDDNB,
@@ -349,6 +351,7 @@ struct amd_powerplay_funcs {
 	int (*get_fan_control_mode)(void *handle);
 	int (*set_fan_speed_percent)(void *handle, uint32_t percent);
 	int (*get_fan_speed_percent)(void *handle, uint32_t *speed);
+	int (*get_fan_speed_rpm)(void *handle, uint32_t *rpm);
 	int (*get_pp_num_states)(void *handle, struct pp_states_info *data);
 	int (*get_pp_table)(void *handle, char **table);
 	int (*set_pp_table)(void *handle, const char *buf, size_t size);
@@ -359,6 +362,7 @@ struct amd_powerplay_funcs {
 	int (*get_mclk_od)(void *handle);
 	int (*set_mclk_od)(void *handle, uint32_t value);
 	int (*read_sensor)(void *handle, int idx, int32_t *value);
+	struct amd_vce_state* (*get_vce_clock_state)(void *handle, unsigned idx);
 };
 
 struct amd_powerplay {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h	2017-02-12 16:03:20.000000000 -0500
@@ -334,6 +334,7 @@ struct phm_clocks {
 	uint32_t clock[MAX_NUM_CLOCKS];
 };
 
+extern int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr);
 extern int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr);
 extern int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate);
 extern int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h	2017-02-12 16:03:20.000000000 -0500
@@ -38,8 +38,6 @@ struct pp_hwmgr;
 struct phm_fan_speed_info;
 struct pp_atomctrl_voltage_table;
 
-extern int amdgpu_powercontainment;
-extern int amdgpu_sclk_deep_sleep_en;
 extern unsigned amdgpu_pp_feature_mask;
 
 #define VOLTAGE_SCALE 4
@@ -85,7 +83,9 @@ enum PP_FEATURE_MASK {
 	PP_SMC_VOLTAGE_CONTROL_MASK = 0x40,
 	PP_VBI_TIME_SUPPORT_MASK = 0x80,
 	PP_ULV_MASK = 0x100,
-	PP_ENABLE_GFX_CG_THRU_SMU = 0x200
+	PP_ENABLE_GFX_CG_THRU_SMU = 0x200,
+	PP_CLOCK_STRETCH_MASK = 0x400,
+	PP_OD_FUZZY_FAN_CONTROL_MASK = 0x800
 };
 
 enum PHM_BackEnd_Magic {
@@ -367,7 +367,7 @@ struct pp_table_func {
 	int (*pptable_get_vce_state_table_entry)(
 						struct pp_hwmgr *hwmgr,
 						unsigned long i,
-						struct pp_vce_state *vce_state,
+						struct amd_vce_state *vce_state,
 						void **clock_info,
 						unsigned long *flag);
 };
@@ -586,18 +586,6 @@ struct phm_microcode_version_info {
 	uint32_t NB;
 };
 
-#define PP_MAX_VCE_LEVELS 6
-
-enum PP_VCE_LEVEL {
-	PP_VCE_LEVEL_AC_ALL = 0,     /* AC, All cases */
-	PP_VCE_LEVEL_DC_EE = 1,      /* DC, entropy encoding */
-	PP_VCE_LEVEL_DC_LL_LOW = 2,  /* DC, low latency queue, res <= 720 */
-	PP_VCE_LEVEL_DC_LL_HIGH = 3, /* DC, low latency queue, 1080 >= res > 720 */
-	PP_VCE_LEVEL_DC_GP_LOW = 4,  /* DC, general purpose queue, res <= 720 */
-	PP_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
-};
-
-
 enum PP_TABLE_VERSION {
 	PP_TABLE_V0 = 0,
 	PP_TABLE_V1,
@@ -620,7 +608,7 @@ struct pp_hwmgr {
 	void *hardcode_pp_table;
 	bool need_pp_table_upload;
 
-	struct pp_vce_state vce_states[PP_MAX_VCE_LEVELS];
+	struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS];
 	uint32_t num_vce_state_tables;
 
 	enum amd_dpm_forced_level dpm_level;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/power_state.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/power_state.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/power_state.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/power_state.h	2017-02-12 16:03:20.000000000 -0500
@@ -156,15 +156,6 @@ struct pp_power_state {
 	struct pp_hw_power_state  hardware;
 };
 
-
-/*Structure to hold a VCE state entry*/
-struct pp_vce_state {
-	uint32_t evclk;
-	uint32_t ecclk;
-	uint32_t sclk;
-	uint32_t mclk;
-};
-
 enum PP_MMProfilingState {
 	PP_MMProfilingState_NA = 0,
 	PP_MMProfilingState_Started,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,9 +21,6 @@
  *
  */
 
-extern bool acpi_atcs_functions_supported(void *device,
-							uint32_t index);
-extern int acpi_pcie_perf_request(void *device,
-						uint8_t perf_req,
-						bool advertise);
-extern bool acpi_atcs_notify_pcie_device_ready(void *device);
+bool acpi_atcs_functions_supported(void *device, uint32_t index);
+int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise);
+bool acpi_atcs_notify_pcie_device_ready(void *device);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1958,6 +1958,12 @@ int fiji_thermal_setup_fan_table(struct
 	int res;
 	uint64_t tmp64;
 
+	if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
 	if (smu_data->smu7_data.fan_table_start == 0) {
 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 				PHM_PlatformCaps_MicrocodeFanControl);
@@ -2049,7 +2055,7 @@ int fiji_thermal_setup_fan_table(struct
 	return 0;
 }
 
-int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
+static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr)
 {
 	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
@@ -2125,7 +2131,7 @@ uint32_t fiji_get_offsetof(uint32_t type
 			return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold);
 		}
 	}
-	printk("cant't get the offset of type %x member %x \n", type, member);
+	printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
 	return 0;
 }
 
@@ -2150,7 +2156,7 @@ uint32_t fiji_get_mac_definition(uint32_
 		return SMU73_MAX_LEVELS_MVDD;
 	}
 
-	printk("cant't get the mac of %x \n", value);
+	printk(KERN_WARNING "can't get the mac of %x\n", value);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -159,7 +159,7 @@ static int fiji_start_smu_in_non_protect
 	return result;
 }
 
-int fiji_setup_pwr_virus(struct pp_smumgr *smumgr)
+static int fiji_setup_pwr_virus(struct pp_smumgr *smumgr)
 {
 	int i, result = -1;
 	uint32_t reg, data;
@@ -224,7 +224,7 @@ static int fiji_start_avfs_btc(struct pp
 	return result;
 }
 
-int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
+static int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr)
 {
 	int result = 0;
 	uint32_t table_start;
@@ -260,7 +260,7 @@ int fiji_setup_pm_fuse_for_avfs(struct p
 	return result;
 }
 
-int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr)
+static int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr)
 {
 	int32_t vr_config;
 	uint32_t table_start;
@@ -299,7 +299,7 @@ int fiji_setup_graphics_level_structure(
 }
 
 /* Work in Progress */
-int fiji_restore_vft_table(struct pp_smumgr *smumgr)
+static int fiji_restore_vft_table(struct pp_smumgr *smumgr)
 {
 	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
@@ -311,7 +311,7 @@ int fiji_restore_vft_table(struct pp_smu
 }
 
 /* Work in Progress */
-int fiji_save_vft_table(struct pp_smumgr *smumgr)
+static int fiji_save_vft_table(struct pp_smumgr *smumgr)
 {
 	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
@@ -322,7 +322,7 @@ int fiji_save_vft_table(struct pp_smumgr
 		return -EINVAL;
 }
 
-int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started)
+static int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started)
 {
 	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
@@ -396,7 +396,8 @@ static int fiji_start_smu(struct pp_smum
 	struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend);
 
 	/* Only start SMC if SMC RAM is not running */
-	if (!smu7_is_smc_ram_running(smumgr)) {
+	if (!(smu7_is_smc_ram_running(smumgr)
+		|| cgs_is_virtualization_enabled(smumgr->device))) {
 		fiji_avfs_event_mgr(smumgr, false);
 
 		/* Check if SMU is running in protected mode */
@@ -443,6 +444,9 @@ static bool fiji_is_hw_avfs_present(stru
 	uint32_t efuse = 0;
 	uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1;
 
+	if (cgs_is_virtualization_enabled(smumgr->device))
+		return 0;
+
 	if (!atomctrl_read_efuse(smumgr->device, AVFS_EN_LSB, AVFS_EN_MSB,
 			mask, &efuse)) {
 		if (efuse)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c	2017-02-12 16:03:20.000000000 -0500
@@ -2006,6 +2006,12 @@ int iceland_thermal_setup_fan_table(stru
 	if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl))
 		return 0;
 
+	if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
 	if (0 == smu7_data->fan_table_start) {
 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
 		return 0;
@@ -2140,7 +2146,7 @@ uint32_t iceland_get_offsetof(uint32_t t
 			return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold);
 		}
 	}
-	printk("cant't get the offset of type %x member %x \n", type, member);
+	printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
 	return 0;
 }
 
@@ -2163,7 +2169,7 @@ uint32_t iceland_get_mac_definition(uint
 		return SMU71_MAX_LEVELS_MVDD;
 	}
 
-	printk("cant't get the mac of %x \n", value);
+	printk(KERN_WARNING "can't get the mac of %x\n", value);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1885,6 +1885,12 @@ int polaris10_thermal_setup_fan_table(st
 	int res;
 	uint64_t tmp64;
 
+	if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
 	if (smu_data->smu7_data.fan_table_start == 0) {
 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 				PHM_PlatformCaps_MicrocodeFanControl);
@@ -2174,7 +2180,7 @@ uint32_t polaris10_get_offsetof(uint32_t
 			return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold);
 		}
 	}
-	printk("cant't get the offset of type %x member %x \n", type, member);
+	printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
 	return 0;
 }
 
@@ -2201,7 +2207,7 @@ uint32_t polaris10_get_mac_definition(ui
 		return SMU7_UVD_MCLK_HANDSHAKE_DISABLE;
 	}
 
-	printk("cant't get the mac of %x \n", value);
+	printk(KERN_WARNING "can't get the mac of %x\n", value);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,7 +118,7 @@ static int polaris10_perform_btc(struct
 }
 
 
-int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr)
+static int polaris10_setup_graphics_level_structure(struct pp_smumgr *smumgr)
 {
 	uint32_t vr_config;
 	uint32_t dpm_table_start;
@@ -172,7 +172,8 @@ int polaris10_setup_graphics_level_struc
 	return 0;
 }
 
-int polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT)
+static int
+polaris10_avfs_event_mgr(struct pp_smumgr *smumgr, bool SMU_VFT_INTACT)
 {
 	struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(smumgr->backend);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -278,6 +278,9 @@ enum cgs_ucode_id smu7_convert_fw_type_t
 	case UCODE_ID_RLC_G:
 		result = CGS_UCODE_ID_RLC_G;
 		break;
+	case UCODE_ID_MEC_STORAGE:
+		result = CGS_UCODE_ID_STORAGE;
+		break;
 	default:
 		break;
 	}
@@ -363,12 +366,16 @@ static int smu7_populate_single_firmware
 				&info);
 
 	if (!result) {
-		entry->version = info.version;
+		entry->version = info.fw_version;
 		entry->id = (uint16_t)fw_type;
 		entry->image_addr_high = smu_upper_32_bits(info.mc_addr);
 		entry->image_addr_low = smu_lower_32_bits(info.mc_addr);
 		entry->meta_data_addr_high = 0;
 		entry->meta_data_addr_low = 0;
+
+		/* digest need be excluded out */
+		if (cgs_is_virtualization_enabled(smumgr->device))
+			info.image_size -= 20;
 		entry->data_size_byte = info.image_size;
 		entry->num_register_entries = 0;
 	}
@@ -400,8 +407,14 @@ int smu7_request_smu_load_fw(struct pp_s
 					0x0);
 
 	if (smumgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */
-		smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SMU_DRAM_ADDR_HI, smu_data->smu_buffer.mc_addr_high);
-		smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_SMU_DRAM_ADDR_LO, smu_data->smu_buffer.mc_addr_low);
+		if (!cgs_is_virtualization_enabled(smumgr->device)) {
+			smu7_send_msg_to_smc_with_parameter(smumgr,
+						PPSMC_MSG_SMU_DRAM_ADDR_HI,
+						smu_data->smu_buffer.mc_addr_high);
+			smu7_send_msg_to_smc_with_parameter(smumgr,
+						PPSMC_MSG_SMU_DRAM_ADDR_LO,
+						smu_data->smu_buffer.mc_addr_low);
+		}
 		fw_to_load = UCODE_ID_RLC_G_MASK
 			   + UCODE_ID_SDMA0_MASK
 			   + UCODE_ID_SDMA1_MASK
@@ -452,6 +465,10 @@ int smu7_request_smu_load_fw(struct pp_s
 	PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr,
 				UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
 				"Failed to Get Firmware Entry.", return -EINVAL);
+	if (cgs_is_virtualization_enabled(smumgr->device))
+		PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(smumgr,
+				UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]),
+				"Failed to Get Firmware Entry.", return -EINVAL);
 
 	smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, smu_data->header_buffer.mc_addr_high);
 	smu7_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, smu_data->header_buffer.mc_addr_low);
@@ -532,7 +549,6 @@ int smu7_init(struct pp_smumgr *smumgr)
 	smu_data = (struct smu7_smumgr *)(smumgr->backend);
 	smu_data->header_buffer.data_size =
 			((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
-	smu_data->smu_buffer.data_size = 200*4096;
 
 /* Allocate FW image data structure and header buffer and
  * send the header buffer address to SMU */
@@ -555,6 +571,10 @@ int smu7_init(struct pp_smumgr *smumgr)
 		(cgs_handle_t)smu_data->header_buffer.handle);
 		return -EINVAL);
 
+	if (cgs_is_virtualization_enabled(smumgr->device))
+		return 0;
+
+	smu_data->smu_buffer.data_size = 200*4096;
 	smu_allocate_memory(smumgr->device,
 		smu_data->smu_buffer.data_size,
 		CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h	2017-02-12 16:03:20.000000000 -0500
@@ -28,8 +28,6 @@
 #include <pp_endian.h>
 
 #define SMC_RAM_END 0x40000
-#define mmSMC_IND_INDEX_11                              0x01AC
-#define mmSMC_IND_DATA_11                               0x01AD
 
 struct smu7_buffer_entry {
 	uint32_t data_size;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,7 @@ int smum_init(struct amd_pp_init *pp_ini
 			break;
 		case CHIP_POLARIS11:
 		case CHIP_POLARIS10:
+		case CHIP_POLARIS12:
 			polaris10_smum_init(smumgr);
 			break;
 		default:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c	2017-02-12 16:03:20.000000000 -0500
@@ -2496,6 +2496,12 @@ int tonga_thermal_setup_fan_table(struct
 					PHM_PlatformCaps_MicrocodeFanControl))
 		return 0;
 
+	if (hwmgr->thermal_controller.fanInfo.bNoFan) {
+		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
+			PHM_PlatformCaps_MicrocodeFanControl);
+		return 0;
+	}
+
 	if (0 == smu_data->smu7_data.fan_table_start) {
 		phm_cap_unset(hwmgr->platform_descriptor.platformCaps,
 					PHM_PlatformCaps_MicrocodeFanControl);
@@ -2651,7 +2657,7 @@ uint32_t tonga_get_offsetof(uint32_t typ
 			return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold);
 		}
 	}
-	printk("cant't get the offset of type %x member %x\n", type, member);
+	printk(KERN_WARNING "can't get the offset of type %x member %x\n", type, member);
 	return 0;
 }
 
@@ -2675,7 +2681,7 @@ uint32_t tonga_get_mac_definition(uint32
 	case SMU_MAX_LEVELS_MVDD:
 		return SMU72_MAX_LEVELS_MVDD;
 	}
-	printk("cant't get the mac value %x\n", value);
+	printk(KERN_WARNING "can't get the mac value %x\n", value);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -140,7 +140,8 @@ static int tonga_start_smu(struct pp_smu
 	int result;
 
 	/* Only start SMC if SMC RAM is not running */
-	if (!smu7_is_smc_ram_running(smumgr)) {
+	if (!(smu7_is_smc_ram_running(smumgr) ||
+		cgs_is_virtualization_enabled(smumgr->device))) {
 		/*Check if SMU is running in protected mode*/
 		if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC,
 					SMU_FIRMWARE, SMU_MODE)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/gpu_sched_trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@ TRACE_EVENT(amd_sched_job,
 	    TP_STRUCT__entry(
 			     __field(struct amd_sched_entity *, entity)
 			     __field(struct amd_sched_job *, sched_job)
-			     __field(struct fence *, fence)
+			     __field(struct dma_fence *, fence)
 			     __field(const char *, name)
 			     __field(u32, job_count)
 			     __field(int, hw_job_count)
@@ -42,7 +42,7 @@ TRACE_EVENT(amd_sched_process_job,
 	    TP_PROTO(struct amd_sched_fence *fence),
 	    TP_ARGS(fence),
 	    TP_STRUCT__entry(
-		    __field(struct fence *, fence)
+		    __field(struct dma_fence *, fence)
 		    ),
 
 	    TP_fast_assign(
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 
 static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity);
 static void amd_sched_wakeup(struct amd_gpu_scheduler *sched);
-static void amd_sched_process_job(struct fence *f, struct fence_cb *cb);
+static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb);
 
 /* Initialize a given run queue struct */
 static void amd_sched_rq_init(struct amd_sched_rq *rq)
@@ -138,7 +138,7 @@ int amd_sched_entity_init(struct amd_gpu
 		return r;
 
 	atomic_set(&entity->fence_seq, 0);
-	entity->fence_context = fence_context_alloc(2);
+	entity->fence_context = dma_fence_context_alloc(2);
 
 	return 0;
 }
@@ -218,32 +218,32 @@ void amd_sched_entity_fini(struct amd_gp
 	kfifo_free(&entity->job_queue);
 }
 
-static void amd_sched_entity_wakeup(struct fence *f, struct fence_cb *cb)
+static void amd_sched_entity_wakeup(struct dma_fence *f, struct dma_fence_cb *cb)
 {
 	struct amd_sched_entity *entity =
 		container_of(cb, struct amd_sched_entity, cb);
 	entity->dependency = NULL;
-	fence_put(f);
+	dma_fence_put(f);
 	amd_sched_wakeup(entity->sched);
 }
 
-static void amd_sched_entity_clear_dep(struct fence *f, struct fence_cb *cb)
+static void amd_sched_entity_clear_dep(struct dma_fence *f, struct dma_fence_cb *cb)
 {
 	struct amd_sched_entity *entity =
 		container_of(cb, struct amd_sched_entity, cb);
 	entity->dependency = NULL;
-	fence_put(f);
+	dma_fence_put(f);
 }
 
 static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity)
 {
 	struct amd_gpu_scheduler *sched = entity->sched;
-	struct fence * fence = entity->dependency;
+	struct dma_fence * fence = entity->dependency;
 	struct amd_sched_fence *s_fence;
 
 	if (fence->context == entity->fence_context) {
 		/* We can ignore fences from ourself */
-		fence_put(entity->dependency);
+		dma_fence_put(entity->dependency);
 		return false;
 	}
 
@@ -254,23 +254,23 @@ static bool amd_sched_entity_add_depende
 		 * Fence is from the same scheduler, only need to wait for
 		 * it to be scheduled
 		 */
-		fence = fence_get(&s_fence->scheduled);
-		fence_put(entity->dependency);
+		fence = dma_fence_get(&s_fence->scheduled);
+		dma_fence_put(entity->dependency);
 		entity->dependency = fence;
-		if (!fence_add_callback(fence, &entity->cb,
-					amd_sched_entity_clear_dep))
+		if (!dma_fence_add_callback(fence, &entity->cb,
+					    amd_sched_entity_clear_dep))
 			return true;
 
 		/* Ignore it when it is already scheduled */
-		fence_put(fence);
+		dma_fence_put(fence);
 		return false;
 	}
 
-	if (!fence_add_callback(entity->dependency, &entity->cb,
-				amd_sched_entity_wakeup))
+	if (!dma_fence_add_callback(entity->dependency, &entity->cb,
+				    amd_sched_entity_wakeup))
 		return true;
 
-	fence_put(entity->dependency);
+	dma_fence_put(entity->dependency);
 	return false;
 }
 
@@ -351,7 +351,8 @@ static void amd_sched_job_finish(struct
 	sched->ops->free_job(s_job);
 }
 
-static void amd_sched_job_finish_cb(struct fence *f, struct fence_cb *cb)
+static void amd_sched_job_finish_cb(struct dma_fence *f,
+				    struct dma_fence_cb *cb)
 {
 	struct amd_sched_job *job = container_of(cb, struct amd_sched_job,
 						 finish_cb);
@@ -385,8 +386,8 @@ void amd_sched_hw_job_reset(struct amd_g
 
 	spin_lock(&sched->job_list_lock);
 	list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) {
-		if (fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) {
-			fence_put(s_job->s_fence->parent);
+		if (dma_fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) {
+			dma_fence_put(s_job->s_fence->parent);
 			s_job->s_fence->parent = NULL;
 		}
 	}
@@ -407,21 +408,21 @@ void amd_sched_job_recovery(struct amd_g
 
 	list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
 		struct amd_sched_fence *s_fence = s_job->s_fence;
-		struct fence *fence;
+		struct dma_fence *fence;
 
 		spin_unlock(&sched->job_list_lock);
 		fence = sched->ops->run_job(s_job);
 		atomic_inc(&sched->hw_rq_count);
 		if (fence) {
-			s_fence->parent = fence_get(fence);
-			r = fence_add_callback(fence, &s_fence->cb,
-					       amd_sched_process_job);
+			s_fence->parent = dma_fence_get(fence);
+			r = dma_fence_add_callback(fence, &s_fence->cb,
+						   amd_sched_process_job);
 			if (r == -ENOENT)
 				amd_sched_process_job(fence, &s_fence->cb);
 			else if (r)
 				DRM_ERROR("fence add callback failed (%d)\n",
 					  r);
-			fence_put(fence);
+			dma_fence_put(fence);
 		} else {
 			DRM_ERROR("Failed to run job!\n");
 			amd_sched_process_job(NULL, &s_fence->cb);
@@ -443,8 +444,8 @@ void amd_sched_entity_push_job(struct am
 	struct amd_sched_entity *entity = sched_job->s_entity;
 
 	trace_amd_sched_job(sched_job);
-	fence_add_callback(&sched_job->s_fence->finished, &sched_job->finish_cb,
-			   amd_sched_job_finish_cb);
+	dma_fence_add_callback(&sched_job->s_fence->finished, &sched_job->finish_cb,
+			       amd_sched_job_finish_cb);
 	wait_event(entity->sched->job_scheduled,
 		   amd_sched_entity_in(sched_job));
 }
@@ -508,7 +509,7 @@ amd_sched_select_entity(struct amd_gpu_s
 	return entity;
 }
 
-static void amd_sched_process_job(struct fence *f, struct fence_cb *cb)
+static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb)
 {
 	struct amd_sched_fence *s_fence =
 		container_of(cb, struct amd_sched_fence, cb);
@@ -518,7 +519,7 @@ static void amd_sched_process_job(struct
 	amd_sched_fence_finished(s_fence);
 
 	trace_amd_sched_process_job(s_fence);
-	fence_put(&s_fence->finished);
+	dma_fence_put(&s_fence->finished);
 	wake_up_interruptible(&sched->wake_up_worker);
 }
 
@@ -544,7 +545,7 @@ static int amd_sched_main(void *param)
 		struct amd_sched_entity *entity = NULL;
 		struct amd_sched_fence *s_fence;
 		struct amd_sched_job *sched_job;
-		struct fence *fence;
+		struct dma_fence *fence;
 
 		wait_event_interruptible(sched->wake_up_worker,
 					 (!amd_sched_blocked(sched) &&
@@ -566,15 +567,15 @@ static int amd_sched_main(void *param)
 		fence = sched->ops->run_job(sched_job);
 		amd_sched_fence_scheduled(s_fence);
 		if (fence) {
-			s_fence->parent = fence_get(fence);
-			r = fence_add_callback(fence, &s_fence->cb,
-					       amd_sched_process_job);
+			s_fence->parent = dma_fence_get(fence);
+			r = dma_fence_add_callback(fence, &s_fence->cb,
+						   amd_sched_process_job);
 			if (r == -ENOENT)
 				amd_sched_process_job(fence, &s_fence->cb);
 			else if (r)
 				DRM_ERROR("fence add callback failed (%d)\n",
 					  r);
-			fence_put(fence);
+			dma_fence_put(fence);
 		} else {
 			DRM_ERROR("Failed to run job!\n");
 			amd_sched_process_job(NULL, &s_fence->cb);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #define _GPU_SCHEDULER_H_
 
 #include <linux/kfifo.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 struct amd_gpu_scheduler;
 struct amd_sched_rq;
@@ -47,8 +47,8 @@ struct amd_sched_entity {
 	atomic_t			fence_seq;
 	uint64_t                        fence_context;
 
-	struct fence			*dependency;
-	struct fence_cb			cb;
+	struct dma_fence		*dependency;
+	struct dma_fence_cb		cb;
 };
 
 /**
@@ -63,10 +63,10 @@ struct amd_sched_rq {
 };
 
 struct amd_sched_fence {
-	struct fence                    scheduled;
-	struct fence                    finished;
-	struct fence_cb                 cb;
-	struct fence                    *parent;
+	struct dma_fence                scheduled;
+	struct dma_fence                finished;
+	struct dma_fence_cb             cb;
+	struct dma_fence                *parent;
 	struct amd_gpu_scheduler	*sched;
 	spinlock_t			lock;
 	void                            *owner;
@@ -76,15 +76,15 @@ struct amd_sched_job {
 	struct amd_gpu_scheduler        *sched;
 	struct amd_sched_entity         *s_entity;
 	struct amd_sched_fence          *s_fence;
-	struct fence_cb			finish_cb;
+	struct dma_fence_cb		finish_cb;
 	struct work_struct		finish_work;
 	struct list_head		node;
 	struct delayed_work		work_tdr;
 };
 
-extern const struct fence_ops amd_sched_fence_ops_scheduled;
-extern const struct fence_ops amd_sched_fence_ops_finished;
-static inline struct amd_sched_fence *to_amd_sched_fence(struct fence *f)
+extern const struct dma_fence_ops amd_sched_fence_ops_scheduled;
+extern const struct dma_fence_ops amd_sched_fence_ops_finished;
+static inline struct amd_sched_fence *to_amd_sched_fence(struct dma_fence *f)
 {
 	if (f->ops == &amd_sched_fence_ops_scheduled)
 		return container_of(f, struct amd_sched_fence, scheduled);
@@ -100,8 +100,8 @@ static inline struct amd_sched_fence *to
  * these functions should be implemented in driver side
 */
 struct amd_sched_backend_ops {
-	struct fence *(*dependency)(struct amd_sched_job *sched_job);
-	struct fence *(*run_job)(struct amd_sched_job *sched_job);
+	struct dma_fence *(*dependency)(struct amd_sched_job *sched_job);
+	struct dma_fence *(*run_job)(struct amd_sched_job *sched_job);
 	void (*timedout_job)(struct amd_sched_job *sched_job);
 	void (*free_job)(struct amd_sched_job *sched_job);
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/amd/scheduler/sched_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,46 +61,50 @@ struct amd_sched_fence *amd_sched_fence_
 	spin_lock_init(&fence->lock);
 
 	seq = atomic_inc_return(&entity->fence_seq);
-	fence_init(&fence->scheduled, &amd_sched_fence_ops_scheduled,
-		   &fence->lock, entity->fence_context, seq);
-	fence_init(&fence->finished, &amd_sched_fence_ops_finished,
-		   &fence->lock, entity->fence_context + 1, seq);
+	dma_fence_init(&fence->scheduled, &amd_sched_fence_ops_scheduled,
+		       &fence->lock, entity->fence_context, seq);
+	dma_fence_init(&fence->finished, &amd_sched_fence_ops_finished,
+		       &fence->lock, entity->fence_context + 1, seq);
 
 	return fence;
 }
 
 void amd_sched_fence_scheduled(struct amd_sched_fence *fence)
 {
-	int ret = fence_signal(&fence->scheduled);
+	int ret = dma_fence_signal(&fence->scheduled);
 
 	if (!ret)
-		FENCE_TRACE(&fence->scheduled, "signaled from irq context\n");
+		DMA_FENCE_TRACE(&fence->scheduled,
+				"signaled from irq context\n");
 	else
-		FENCE_TRACE(&fence->scheduled, "was already signaled\n");
+		DMA_FENCE_TRACE(&fence->scheduled,
+				"was already signaled\n");
 }
 
 void amd_sched_fence_finished(struct amd_sched_fence *fence)
 {
-	int ret = fence_signal(&fence->finished);
+	int ret = dma_fence_signal(&fence->finished);
 
 	if (!ret)
-		FENCE_TRACE(&fence->finished, "signaled from irq context\n");
+		DMA_FENCE_TRACE(&fence->finished,
+				"signaled from irq context\n");
 	else
-		FENCE_TRACE(&fence->finished, "was already signaled\n");
+		DMA_FENCE_TRACE(&fence->finished,
+				"was already signaled\n");
 }
 
-static const char *amd_sched_fence_get_driver_name(struct fence *fence)
+static const char *amd_sched_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "amd_sched";
 }
 
-static const char *amd_sched_fence_get_timeline_name(struct fence *f)
+static const char *amd_sched_fence_get_timeline_name(struct dma_fence *f)
 {
 	struct amd_sched_fence *fence = to_amd_sched_fence(f);
 	return (const char *)fence->sched->name;
 }
 
-static bool amd_sched_fence_enable_signaling(struct fence *f)
+static bool amd_sched_fence_enable_signaling(struct dma_fence *f)
 {
 	return true;
 }
@@ -114,10 +118,10 @@ static bool amd_sched_fence_enable_signa
  */
 static void amd_sched_fence_free(struct rcu_head *rcu)
 {
-	struct fence *f = container_of(rcu, struct fence, rcu);
+	struct dma_fence *f = container_of(rcu, struct dma_fence, rcu);
 	struct amd_sched_fence *fence = to_amd_sched_fence(f);
 
-	fence_put(fence->parent);
+	dma_fence_put(fence->parent);
 	kmem_cache_free(sched_fence_slab, fence);
 }
 
@@ -129,7 +133,7 @@ static void amd_sched_fence_free(struct
  * This function is called when the reference count becomes zero.
  * It just RCU schedules freeing up the fence.
  */
-static void amd_sched_fence_release_scheduled(struct fence *f)
+static void amd_sched_fence_release_scheduled(struct dma_fence *f)
 {
 	struct amd_sched_fence *fence = to_amd_sched_fence(f);
 
@@ -143,27 +147,27 @@ static void amd_sched_fence_release_sche
  *
  * Drop the extra reference from the scheduled fence to the base fence.
  */
-static void amd_sched_fence_release_finished(struct fence *f)
+static void amd_sched_fence_release_finished(struct dma_fence *f)
 {
 	struct amd_sched_fence *fence = to_amd_sched_fence(f);
 
-	fence_put(&fence->scheduled);
+	dma_fence_put(&fence->scheduled);
 }
 
-const struct fence_ops amd_sched_fence_ops_scheduled = {
+const struct dma_fence_ops amd_sched_fence_ops_scheduled = {
 	.get_driver_name = amd_sched_fence_get_driver_name,
 	.get_timeline_name = amd_sched_fence_get_timeline_name,
 	.enable_signaling = amd_sched_fence_enable_signaling,
 	.signaled = NULL,
-	.wait = fence_default_wait,
+	.wait = dma_fence_default_wait,
 	.release = amd_sched_fence_release_scheduled,
 };
 
-const struct fence_ops amd_sched_fence_ops_finished = {
+const struct dma_fence_ops amd_sched_fence_ops_finished = {
 	.get_driver_name = amd_sched_fence_get_driver_name,
 	.get_timeline_name = amd_sched_fence_get_timeline_name,
 	.enable_signaling = amd_sched_fence_enable_signaling,
 	.signaled = NULL,
-	.wait = fence_default_wait,
+	.wait = dma_fence_default_wait,
 	.release = amd_sched_fence_release_finished,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arc/arcpgu_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arc/arcpgu_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/arc/arcpgu_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arc/arcpgu_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,9 +65,7 @@ static const struct file_operations arcp
 	.open = drm_open,
 	.release = drm_release,
 	.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.poll = drm_poll,
 	.read = drm_read,
 	.llseek = no_llseek,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arc/arcpgu_sim.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arc/arcpgu_sim.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/arc/arcpgu_sim.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arc/arcpgu_sim.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,12 +41,6 @@ static int arcpgu_drm_connector_get_mode
 	return count;
 }
 
-static enum drm_connector_status
-arcpgu_drm_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void arcpgu_drm_connector_destroy(struct drm_connector *connector)
 {
 	drm_connector_unregister(connector);
@@ -61,7 +55,6 @@ arcpgu_drm_connector_helper_funcs = {
 static const struct drm_connector_funcs arcpgu_drm_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
 	.reset = drm_atomic_helper_connector_reset,
-	.detect = arcpgu_drm_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = arcpgu_drm_connector_destroy,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/hdlcd_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -222,14 +222,12 @@ static void hdlcd_plane_atomic_update(st
 {
 	struct hdlcd_drm_private *hdlcd;
 	struct drm_gem_cma_object *gem;
-	unsigned int depth, bpp;
 	u32 src_w, src_h, dest_w, dest_h;
 	dma_addr_t scanout_start;
 
 	if (!plane->state->fb)
 		return;
 
-	drm_fb_get_bpp_depth(plane->state->fb->pixel_format, &depth, &bpp);
 	src_w = plane->state->src_w >> 16;
 	src_h = plane->state->src_h >> 16;
 	dest_w = plane->state->crtc_w;
@@ -237,7 +235,8 @@ static void hdlcd_plane_atomic_update(st
 	gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0);
 	scanout_start = gem->paddr + plane->state->fb->offsets[0] +
 		plane->state->crtc_y * plane->state->fb->pitches[0] +
-		plane->state->crtc_x * bpp / 8;
+		plane->state->crtc_x *
+		drm_format_plane_cpp(plane->state->fb->pixel_format, 0);
 
 	hdlcd = plane->dev->dev_private;
 	hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, plane->state->fb->pitches[0]);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arm/hdlcd_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/hdlcd_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/arm/hdlcd_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/hdlcd_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -268,9 +268,7 @@ static const struct file_operations fops
 	.open		= drm_open,
 	.release	= drm_release,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl	= drm_compat_ioctl,
-#endif
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.llseek		= noop_llseek,
@@ -337,14 +335,10 @@ static int hdlcd_drm_bind(struct device
 	if (ret)
 		goto err_free;
 
-	ret = drm_dev_register(drm, 0);
-	if (ret)
-		goto err_unload;
-
 	ret = component_bind_all(dev, drm);
 	if (ret) {
 		DRM_ERROR("Failed to bind all components\n");
-		goto err_unregister;
+		goto err_unload;
 	}
 
 	ret = pm_runtime_set_active(dev);
@@ -371,8 +365,17 @@ static int hdlcd_drm_bind(struct device
 		goto err_fbdev;
 	}
 
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto err_register;
+
 	return 0;
 
+err_register:
+	if (hdlcd->fbdev) {
+		drm_fbdev_cma_fini(hdlcd->fbdev);
+		hdlcd->fbdev = NULL;
+	}
 err_fbdev:
 	drm_kms_helper_poll_fini(drm);
 	drm_vblank_cleanup(drm);
@@ -380,8 +383,6 @@ err_vblank:
 	pm_runtime_disable(drm->dev);
 err_pm_active:
 	component_unbind_all(dev, drm);
-err_unregister:
-	drm_dev_unregister(drm);
 err_unload:
 	drm_irq_uninstall(drm);
 	of_reserved_mem_device_release(drm->dev);
@@ -398,6 +399,7 @@ static void hdlcd_drm_unbind(struct devi
 	struct drm_device *drm = dev_get_drvdata(dev);
 	struct hdlcd_drm_private *hdlcd = drm->dev_private;
 
+	drm_dev_unregister(drm);
 	if (hdlcd->fbdev) {
 		drm_fbdev_cma_fini(hdlcd->fbdev);
 		hdlcd->fbdev = NULL;
@@ -411,7 +413,6 @@ static void hdlcd_drm_unbind(struct devi
 	pm_runtime_disable(drm->dev);
 	of_reserved_mem_device_release(drm->dev);
 	drm_mode_config_cleanup(drm);
-	drm_dev_unregister(drm);
 	drm_dev_unref(drm);
 	drm->dev_private = NULL;
 	dev_set_drvdata(dev, NULL);
@@ -453,7 +454,8 @@ static int hdlcd_probe(struct platform_d
 		return -EAGAIN;
 	}
 
-	component_match_add(&pdev->dev, &match, compare_dev, port);
+	drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
+	of_node_put(port);
 
 	return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops,
 					       match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,7 @@ static int malidp_set_and_wait_config_va
 	struct malidp_hw_device *hwdev = malidp->dev;
 	int ret;
 
+	atomic_set(&malidp->config_valid, 0);
 	hwdev->set_config_valid(hwdev);
 	/* don't wait for config_valid flag if we are in config mode */
 	if (hwdev->in_config_mode(hwdev))
@@ -91,8 +92,7 @@ static void malidp_atomic_commit_tail(st
 
 	drm_atomic_helper_commit_modeset_disables(drm, state);
 	drm_atomic_helper_commit_modeset_enables(drm, state);
-	drm_atomic_helper_commit_planes(drm, state,
-					DRM_PLANE_COMMIT_ACTIVE_ONLY);
+	drm_atomic_helper_commit_planes(drm, state, 0);
 
 	malidp_atomic_commit_hw_done(state);
 
@@ -155,6 +155,12 @@ static int malidp_init(struct drm_device
 	return 0;
 }
 
+static void malidp_fini(struct drm_device *drm)
+{
+	malidp_de_planes_destroy(drm);
+	drm_mode_config_cleanup(drm);
+}
+
 static int malidp_irq_init(struct platform_device *pdev)
 {
 	int irq_de, irq_se, ret = 0;
@@ -197,9 +203,7 @@ static const struct file_operations fops
 	.open = drm_open,
 	.release = drm_release,
 	.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.poll = drm_poll,
 	.read = drm_read,
 	.llseek = noop_llseek,
@@ -355,10 +359,6 @@ static int malidp_bind(struct device *de
 	if (ret < 0)
 		goto init_fail;
 
-	ret = drm_dev_register(drm, 0);
-	if (ret)
-		goto register_fail;
-
 	/* Set the CRTC's port so that the encoder component can find it */
 	ep = of_graph_get_next_endpoint(dev->of_node, NULL);
 	if (!ep) {
@@ -377,6 +377,8 @@ static int malidp_bind(struct device *de
 	if (ret < 0)
 		goto irq_init_fail;
 
+	drm->irq_enabled = true;
+
 	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
 	if (ret < 0) {
 		DRM_ERROR("failed to initialise vblank\n");
@@ -395,23 +397,31 @@ static int malidp_bind(struct device *de
 	}
 
 	drm_kms_helper_poll_init(drm);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto register_fail;
+
 	return 0;
 
+register_fail:
+	if (malidp->fbdev) {
+		drm_fbdev_cma_fini(malidp->fbdev);
+		malidp->fbdev = NULL;
+	}
 fbdev_fail:
 	drm_vblank_cleanup(drm);
 vblank_fail:
 	malidp_se_irq_fini(drm);
 	malidp_de_irq_fini(drm);
+	drm->irq_enabled = false;
 irq_init_fail:
 	component_unbind_all(dev, drm);
 bind_fail:
 	of_node_put(malidp->crtc.port);
 	malidp->crtc.port = NULL;
 port_fail:
-	drm_dev_unregister(drm);
-register_fail:
-	malidp_de_planes_destroy(drm);
-	drm_mode_config_cleanup(drm);
+	malidp_fini(drm);
 init_fail:
 	drm->dev_private = NULL;
 	dev_set_drvdata(dev, NULL);
@@ -432,6 +442,7 @@ static void malidp_unbind(struct device
 	struct malidp_drm *malidp = drm->dev_private;
 	struct malidp_hw_device *hwdev = malidp->dev;
 
+	drm_dev_unregister(drm);
 	if (malidp->fbdev) {
 		drm_fbdev_cma_fini(malidp->fbdev);
 		malidp->fbdev = NULL;
@@ -443,9 +454,7 @@ static void malidp_unbind(struct device
 	component_unbind_all(dev, drm);
 	of_node_put(malidp->crtc.port);
 	malidp->crtc.port = NULL;
-	drm_dev_unregister(drm);
-	malidp_de_planes_destroy(drm);
-	drm_mode_config_cleanup(drm);
+	malidp_fini(drm);
 	drm->dev_private = NULL;
 	dev_set_drvdata(dev, NULL);
 	clk_disable_unprepare(hwdev->mclk);
@@ -493,7 +502,9 @@ static int malidp_platform_probe(struct
 		return -EAGAIN;
 	}
 
-	component_match_add(&pdev->dev, &match, malidp_compare_dev, port);
+	drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
+				   port);
+	of_node_put(port);
 	return component_master_add_with_match(&pdev->dev, &malidp_master_ops,
 					       match);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,9 @@ struct malidp_plane_state {
 
 	/* size of the required rotation memory if plane is rotated */
 	u32 rotmem_size;
+	/* internal format ID */
+	u8 format;
+	u8 n_planes;
 };
 
 #define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_hw.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_hw.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -125,6 +125,7 @@ static void malidp500_leave_config_mode(
 {
 	u32 status, count = 100;
 
+	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
 	malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
 	while (count) {
 		status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
@@ -198,9 +199,6 @@ static void malidp500_modeset(struct mal
 
 static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
 {
-	unsigned int depth;
-	int bpp;
-
 	/* RGB888 or BGR888 can't be rotated */
 	if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
 		return -EINVAL;
@@ -210,9 +208,7 @@ static int malidp500_rotmem_required(str
 	 * worth of pixel data. Required size is then:
 	 *    size = rotated_width * (bpp / 8) * 8;
 	 */
-	drm_fb_get_bpp_depth(fmt, &depth, &bpp);
-
-	return w * bpp;
+	return w * drm_format_plane_cpp(fmt, 0) * 8;
 }
 
 static int malidp550_query_hw(struct malidp_hw_device *hwdev)
@@ -271,6 +267,7 @@ static void malidp550_leave_config_mode(
 {
 	u32 status, count = 100;
 
+	malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
 	malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
 	while (count) {
 		status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
@@ -441,6 +438,7 @@ const struct malidp_hw_device malidp_dev
 			},
 			.input_formats = malidp500_de_formats,
 			.n_input_formats = ARRAY_SIZE(malidp500_de_formats),
+			.bus_align_bytes = 8,
 		},
 		.query_hw = malidp500_query_hw,
 		.enter_config_mode = malidp500_enter_config_mode,
@@ -473,6 +471,7 @@ const struct malidp_hw_device malidp_dev
 			},
 			.input_formats = malidp550_de_formats,
 			.n_input_formats = ARRAY_SIZE(malidp550_de_formats),
+			.bus_align_bytes = 8,
 		},
 		.query_hw = malidp550_query_hw,
 		.enter_config_mode = malidp550_enter_config_mode,
@@ -506,6 +505,7 @@ const struct malidp_hw_device malidp_dev
 			},
 			.input_formats = malidp550_de_formats,
 			.n_input_formats = ARRAY_SIZE(malidp550_de_formats),
+			.bus_align_bytes = 16,
 		},
 		.query_hw = malidp650_query_hw,
 		.enter_config_mode = malidp550_enter_config_mode,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_hw.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_hw.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_hw.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_hw.h	2017-02-12 16:03:20.000000000 -0500
@@ -88,6 +88,9 @@ struct malidp_hw_regmap {
 	/* list of supported input formats for each layer */
 	const struct malidp_input_format *input_formats;
 	const u8 n_input_formats;
+
+	/* pitch alignment requirement in bytes */
+	const u8 bus_align_bytes;
 };
 
 struct malidp_hw_device {
@@ -229,6 +232,12 @@ void malidp_se_irq_fini(struct drm_devic
 u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
 			   u8 layer_id, u32 format);
 
+static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev,
+					 unsigned int pitch)
+{
+	return !(pitch & (hwdev->map.bus_align_bytes - 1));
+}
+
 /*
  * background color components are defined as 12bits values,
  * they will be shifted right when stored on hardware that
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_planes.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_planes.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/arm/malidp_planes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/arm/malidp_planes.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,10 @@
 #define   LAYER_H_FLIP			(1 << 10)
 #define   LAYER_V_FLIP			(1 << 11)
 #define   LAYER_ROT_MASK		(0xf << 8)
+#define   LAYER_COMP_MASK		(0x3 << 12)
+#define   LAYER_COMP_PIXEL		(0x3 << 12)
+#define   LAYER_COMP_PLANE		(0x2 << 12)
+#define MALIDP_LAYER_COMPOSE		0x008
 #define MALIDP_LAYER_SIZE		0x00c
 #define   LAYER_H_VAL(x)		(((x) & 0x1fff) << 0)
 #define   LAYER_V_VAL(x)		(((x) & 0x1fff) << 16)
@@ -34,6 +38,14 @@
 #define MALIDP_LAYER_OFFSET		0x014
 #define MALIDP_LAYER_STRIDE		0x018
 
+/*
+ * This 4-entry look-up-table is used to determine the full 8-bit alpha value
+ * for formats with 1- or 2-bit alpha channels.
+ * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
+ * opacity for 2-bit formats.
+ */
+#define MALIDP_ALPHA_LUT 0xffaa5500
+
 static void malidp_de_plane_destroy(struct drm_plane *plane)
 {
 	struct malidp_plane *mp = to_malidp_plane(plane);
@@ -46,7 +58,8 @@ static void malidp_de_plane_destroy(stru
 	devm_kfree(plane->dev->dev, mp);
 }
 
-struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
+static struct
+drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
 {
 	struct malidp_plane_state *state, *m_state;
 
@@ -58,13 +71,15 @@ struct drm_plane_state *malidp_duplicate
 		m_state = to_malidp_plane_state(plane->state);
 		__drm_atomic_helper_plane_duplicate_state(plane, &state->base);
 		state->rotmem_size = m_state->rotmem_size;
+		state->format = m_state->format;
+		state->n_planes = m_state->n_planes;
 	}
 
 	return &state->base;
 }
 
-void malidp_destroy_plane_state(struct drm_plane *plane,
-				struct drm_plane_state *state)
+static void malidp_destroy_plane_state(struct drm_plane *plane,
+				       struct drm_plane_state *state)
 {
 	struct malidp_plane_state *m_state = to_malidp_plane_state(state);
 
@@ -75,6 +90,7 @@ void malidp_destroy_plane_state(struct d
 static const struct drm_plane_funcs malidp_de_plane_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
 	.disable_plane = drm_atomic_helper_disable_plane,
+	.set_property = drm_atomic_helper_plane_set_property,
 	.destroy = malidp_de_plane_destroy,
 	.reset = drm_atomic_helper_plane_reset,
 	.atomic_duplicate_state = malidp_duplicate_plane_state,
@@ -86,17 +102,29 @@ static int malidp_de_plane_check(struct
 {
 	struct malidp_plane *mp = to_malidp_plane(plane);
 	struct malidp_plane_state *ms = to_malidp_plane_state(state);
-	u8 format_id;
+	struct drm_framebuffer *fb;
+	int i;
 	u32 src_w, src_h;
 
 	if (!state->crtc || !state->fb)
 		return 0;
 
-	format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
-					    state->fb->pixel_format);
-	if (format_id == MALIDP_INVALID_FORMAT_ID)
+	fb = state->fb;
+
+	ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
+					    fb->pixel_format);
+	if (ms->format == MALIDP_INVALID_FORMAT_ID)
 		return -EINVAL;
 
+	ms->n_planes = drm_format_num_planes(fb->pixel_format);
+	for (i = 0; i < ms->n_planes; i++) {
+		if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) {
+			DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
+				      fb->pitches[i], i);
+			return -EINVAL;
+		}
+	}
+
 	src_w = state->src_w >> 16;
 	src_h = state->src_h >> 16;
 
@@ -135,17 +163,13 @@ static void malidp_de_plane_update(struc
 	struct drm_gem_cma_object *obj;
 	struct malidp_plane *mp;
 	const struct malidp_hw_regmap *map;
-	u8 format_id;
+	struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
 	u16 ptr;
-	u32 format, src_w, src_h, dest_w, dest_h, val = 0;
-	int num_planes, i;
+	u32 src_w, src_h, dest_w, dest_h, val;
+	int i;
 
 	mp = to_malidp_plane(plane);
-
 	map = &mp->hwdev->map;
-	format = plane->state->fb->pixel_format;
-	format_id = malidp_hw_get_format_id(map, mp->layer->id, format);
-	num_planes = drm_format_num_planes(format);
 
 	/* convert src values from Q16 fixed point to integer */
 	src_w = plane->state->src_w >> 16;
@@ -158,9 +182,9 @@ static void malidp_de_plane_update(struc
 		dest_h = plane->state->crtc_h;
 	}
 
-	malidp_hw_write(mp->hwdev, format_id, mp->layer->base);
+	malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
 
-	for (i = 0; i < num_planes; i++) {
+	for (i = 0; i < ms->n_planes; i++) {
 		/* calculate the offset for the layer's plane registers */
 		ptr = mp->layer->ptr + (i << 4);
 
@@ -181,9 +205,9 @@ static void malidp_de_plane_update(struc
 			LAYER_V_VAL(plane->state->crtc_y),
 			mp->layer->base + MALIDP_LAYER_OFFSET);
 
-	/* first clear the rotation bits in the register */
-	malidp_hw_clearbits(mp->hwdev, LAYER_ROT_MASK,
-			    mp->layer->base + MALIDP_LAYER_CONTROL);
+	/* first clear the rotation bits */
+	val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
+	val &= ~LAYER_ROT_MASK;
 
 	/* setup the rotation and axis flip bits */
 	if (plane->state->rotation & DRM_ROTATE_MASK)
@@ -193,11 +217,18 @@ static void malidp_de_plane_update(struc
 	if (plane->state->rotation & DRM_REFLECT_Y)
 		val |= LAYER_H_FLIP;
 
+	/*
+	 * always enable pixel alpha blending until we have a way to change
+	 * blend modes
+	 */
+	val &= ~LAYER_COMP_MASK;
+	val |= LAYER_COMP_PIXEL;
+
 	/* set the 'enable layer' bit */
 	val |= LAYER_ENABLE;
 
-	malidp_hw_setbits(mp->hwdev, val,
-			  mp->layer->base + MALIDP_LAYER_CONTROL);
+	malidp_hw_write(mp->hwdev, val,
+			mp->layer->base + MALIDP_LAYER_CONTROL);
 }
 
 static void malidp_de_plane_disable(struct drm_plane *plane,
@@ -222,6 +253,8 @@ int malidp_de_planes_init(struct drm_dev
 	struct malidp_plane *plane = NULL;
 	enum drm_plane_type plane_type;
 	unsigned long crtcs = 1 << drm->mode_config.num_crtc;
+	unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 |
+			      DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y;
 	u32 *formats;
 	int ret, i, j, n;
 
@@ -254,26 +287,18 @@ int malidp_de_planes_init(struct drm_dev
 		if (ret < 0)
 			goto cleanup;
 
-		if (!drm->mode_config.rotation_property) {
-			unsigned long flags = DRM_ROTATE_0 |
-					      DRM_ROTATE_90 |
-					      DRM_ROTATE_180 |
-					      DRM_ROTATE_270 |
-					      DRM_REFLECT_X |
-					      DRM_REFLECT_Y;
-			drm->mode_config.rotation_property =
-				drm_mode_create_rotation_property(drm, flags);
-		}
-		/* SMART layer can't be rotated */
-		if (drm->mode_config.rotation_property && (id != DE_SMART))
-			drm_object_attach_property(&plane->base.base,
-						   drm->mode_config.rotation_property,
-						   DRM_ROTATE_0);
-
 		drm_plane_helper_add(&plane->base,
 				     &malidp_de_plane_helper_funcs);
 		plane->hwdev = malidp->dev;
 		plane->layer = &map->layers[i];
+
+		/* Skip the features which the SMART layer doesn't have */
+		if (id == DE_SMART)
+			continue;
+
+		drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);
+		malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
+				plane->layer->base + MALIDP_LAYER_COMPOSE);
 	}
 
 	kfree(formats);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 #include "armada_fb.h"
 #include "armada_gem.h"
 #include "armada_hw.h"
+#include "armada_trace.h"
 
 struct armada_frame_work {
 	struct armada_plane_work work;
@@ -164,19 +165,37 @@ static void armada_drm_crtc_update(struc
 	}
 }
 
+void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
+	int x, int y)
+{
+	u32 addr = drm_fb_obj(fb)->dev_addr;
+	u32 pixel_format = fb->pixel_format;
+	int num_planes = drm_format_num_planes(pixel_format);
+	int i;
+
+	if (num_planes > 3)
+		num_planes = 3;
+
+	for (i = 0; i < num_planes; i++)
+		addrs[i] = addr + fb->offsets[i] + y * fb->pitches[i] +
+			     x * drm_format_plane_cpp(pixel_format, i);
+	for (; i < 3; i++)
+		addrs[i] = 0;
+}
+
 static unsigned armada_drm_crtc_calc_fb(struct drm_framebuffer *fb,
 	int x, int y, struct armada_regs *regs, bool interlaced)
 {
-	struct armada_gem_object *obj = drm_fb_obj(fb);
 	unsigned pitch = fb->pitches[0];
-	unsigned offset = y * pitch + x * fb->bits_per_pixel / 8;
-	uint32_t addr_odd, addr_even;
+	u32 addrs[3], addr_odd, addr_even;
 	unsigned i = 0;
 
 	DRM_DEBUG_DRIVER("pitch %u x %d y %d bpp %d\n",
 		pitch, x, y, fb->bits_per_pixel);
 
-	addr_odd = addr_even = obj->dev_addr + offset;
+	armada_drm_plane_calc_addrs(addrs, fb, x, y);
+
+	addr_odd = addr_even = addrs[0];
 
 	if (interlaced) {
 		addr_even += pitch;
@@ -192,17 +211,18 @@ static unsigned armada_drm_crtc_calc_fb(
 }
 
 static void armada_drm_plane_work_run(struct armada_crtc *dcrtc,
-	struct armada_plane *plane)
+	struct drm_plane *plane)
 {
-	struct armada_plane_work *work = xchg(&plane->work, NULL);
+	struct armada_plane *dplane = drm_to_armada_plane(plane);
+	struct armada_plane_work *work = xchg(&dplane->work, NULL);
 
 	/* Handle any pending frame work. */
 	if (work) {
-		work->fn(dcrtc, plane, work);
+		work->fn(dcrtc, dplane, work);
 		drm_crtc_vblank_put(&dcrtc->crtc);
 	}
 
-	wake_up(&plane->frame_wait);
+	wake_up(&dplane->frame_wait);
 }
 
 int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
@@ -307,14 +327,12 @@ static void armada_drm_crtc_finish_fb(st
 
 static void armada_drm_vblank_off(struct armada_crtc *dcrtc)
 {
-	struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary);
-
 	/*
 	 * Tell the DRM core that vblank IRQs aren't going to happen for
 	 * a while.  This cleans up any pending vblank events for us.
 	 */
 	drm_crtc_vblank_off(&dcrtc->crtc);
-	armada_drm_plane_work_run(dcrtc, plane);
+	armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
 }
 
 void armada_drm_crtc_gamma_set(struct drm_crtc *crtc, u16 r, u16 g, u16 b,
@@ -416,10 +434,8 @@ static void armada_drm_crtc_irq(struct a
 
 	spin_lock(&dcrtc->irq_lock);
 	ovl_plane = dcrtc->plane;
-	if (ovl_plane) {
-		struct armada_plane *plane = drm_to_armada_plane(ovl_plane);
-		armada_drm_plane_work_run(dcrtc, plane);
-	}
+	if (ovl_plane)
+		armada_drm_plane_work_run(dcrtc, ovl_plane);
 
 	if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
 		int i = stat & GRA_FRAME_IRQ0 ? 0 : 1;
@@ -449,10 +465,8 @@ static void armada_drm_crtc_irq(struct a
 
 	spin_unlock(&dcrtc->irq_lock);
 
-	if (stat & GRA_FRAME_IRQ) {
-		struct armada_plane *plane = drm_to_armada_plane(dcrtc->crtc.primary);
-		armada_drm_plane_work_run(dcrtc, plane);
-	}
+	if (stat & GRA_FRAME_IRQ)
+		armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
 }
 
 static irqreturn_t armada_drm_irq(int irq, void *arg)
@@ -466,6 +480,8 @@ static irqreturn_t armada_drm_irq(int ir
 	 */
 	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
 
+	trace_armada_drm_irq(&dcrtc->crtc, stat);
+
 	/* Mask out those interrupts we haven't enabled */
 	v = stat & dcrtc->irq_ena;
 
@@ -531,6 +547,35 @@ static uint32_t armada_drm_crtc_calculat
 	return val;
 }
 
+static void armada_drm_primary_set(struct drm_crtc *crtc,
+	struct drm_plane *plane, int x, int y)
+{
+	struct armada_plane_state *state = &drm_to_armada_plane(plane)->state;
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_regs regs[8];
+	bool interlaced = dcrtc->interlaced;
+	unsigned i;
+	u32 ctrl0;
+
+	i = armada_drm_crtc_calc_fb(plane->fb, x, y, regs, interlaced);
+
+	armada_reg_queue_set(regs, i, state->dst_yx, LCD_SPU_GRA_OVSA_HPXL_VLN);
+	armada_reg_queue_set(regs, i, state->src_hw, LCD_SPU_GRA_HPXL_VLN);
+	armada_reg_queue_set(regs, i, state->dst_hw, LCD_SPU_GZM_HPXL_VLN);
+
+	ctrl0 = state->ctrl0;
+	if (interlaced)
+		ctrl0 |= CFG_GRA_FTOGGLE;
+
+	armada_reg_queue_mod(regs, i, ctrl0, CFG_GRAFORMAT |
+			     CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
+					 CFG_SWAPYU | CFG_YUV2RGB) |
+			     CFG_PALETTE_ENA | CFG_GRA_FTOGGLE,
+			     LCD_SPU_DMA_CTRL0);
+	armada_reg_queue_end(regs, i);
+	armada_drm_crtc_update_regs(dcrtc, regs);
+}
+
 /* The mode_config.mutex will be held for this call */
 static int armada_drm_crtc_mode_set(struct drm_crtc *crtc,
 	struct drm_display_mode *mode, struct drm_display_mode *adj,
@@ -547,9 +592,20 @@ static int armada_drm_crtc_mode_set(stru
 
 	interlaced = !!(adj->flags & DRM_MODE_FLAG_INTERLACE);
 
-	i = armada_drm_crtc_calc_fb(dcrtc->crtc.primary->fb,
-				    x, y, regs, interlaced);
+	val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
+	val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt);
+	val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod);
+
+	if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420)
+		val |= CFG_PALETTE_ENA;
 
+	drm_to_armada_plane(crtc->primary)->state.ctrl0 = val;
+	drm_to_armada_plane(crtc->primary)->state.src_hw =
+	drm_to_armada_plane(crtc->primary)->state.dst_hw =
+		adj->crtc_vdisplay << 16 | adj->crtc_hdisplay;
+	drm_to_armada_plane(crtc->primary)->state.dst_yx = 0;
+
+	i = 0;
 	rm = adj->crtc_hsync_start - adj->crtc_hdisplay;
 	lm = adj->crtc_htotal - adj->crtc_hsync_end;
 	bm = adj->crtc_vsync_start - adj->crtc_vdisplay;
@@ -625,8 +681,6 @@ static int armada_drm_crtc_mode_set(stru
 	val = adj->crtc_vdisplay << 16 | adj->crtc_hdisplay;
 
 	armada_reg_queue_set(regs, i, val, LCD_SPU_V_H_ACTIVE);
-	armada_reg_queue_set(regs, i, val, LCD_SPU_GRA_HPXL_VLN);
-	armada_reg_queue_set(regs, i, val, LCD_SPU_GZM_HPXL_VLN);
 	armada_reg_queue_set(regs, i, (lm << 16) | rm, LCD_SPU_H_PORCH);
 	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_porch, LCD_SPU_V_PORCH);
 	armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
@@ -638,22 +692,6 @@ static int armada_drm_crtc_mode_set(stru
 				     ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
 	}
 
-	val = CFG_GRA_ENA | CFG_GRA_HSMOOTH;
-	val |= CFG_GRA_FMT(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt);
-	val |= CFG_GRA_MOD(drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->mod);
-
-	if (drm_fb_to_armada_fb(dcrtc->crtc.primary->fb)->fmt > CFG_420)
-		val |= CFG_PALETTE_ENA;
-
-	if (interlaced)
-		val |= CFG_GRA_FTOGGLE;
-
-	armada_reg_queue_mod(regs, i, val, CFG_GRAFORMAT |
-			     CFG_GRA_MOD(CFG_SWAPRB | CFG_SWAPUV |
-					 CFG_SWAPYU | CFG_YUV2RGB) |
-			     CFG_PALETTE_ENA | CFG_GRA_FTOGGLE,
-			     LCD_SPU_DMA_CTRL0);
-
 	val = adj->flags & DRM_MODE_FLAG_NVSYNC ? CFG_VSYNC_INV : 0;
 	armada_reg_queue_mod(regs, i, val, CFG_VSYNC_INV, LCD_SPU_DMA_CTRL1);
 
@@ -662,6 +700,8 @@ static int armada_drm_crtc_mode_set(stru
 	armada_reg_queue_end(regs, i);
 
 	armada_drm_crtc_update_regs(dcrtc, regs);
+
+	armada_drm_primary_set(crtc, crtc->primary, x, y);
 	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
 
 	armada_drm_crtc_update(dcrtc);
@@ -1038,7 +1078,7 @@ static int armada_drm_crtc_page_flip(str
 	 * interrupt, so complete it now.
 	 */
 	if (dpms_blanked(dcrtc->dpms))
-		armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary));
+		armada_drm_plane_work_run(dcrtc, dcrtc->crtc.primary);
 
 	return 0;
 }
@@ -1172,7 +1212,6 @@ static int armada_drm_crtc_create(struct
 		       CFG_PDWN32x32 | CFG_PDWN16x66 | CFG_PDWN32x66 |
 		       CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
 	writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
-	writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
 	writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
 	writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_crtc.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_crtc.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_crtc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_crtc.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,10 +41,18 @@ struct armada_plane_work {
 				      struct armada_plane_work *);
 };
 
+struct armada_plane_state {
+	u32 src_hw;
+	u32 dst_hw;
+	u32 dst_yx;
+	u32 ctrl0;
+};
+
 struct armada_plane {
 	struct drm_plane	base;
 	wait_queue_head_t	frame_wait;
 	struct armada_plane_work *work;
+	struct armada_plane_state state;
 };
 #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
 
@@ -54,6 +62,8 @@ int armada_drm_plane_work_queue(struct a
 int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout);
 struct armada_plane_work *armada_drm_plane_work_cancel(
 	struct armada_crtc *dcrtc, struct armada_plane *plane);
+void armada_drm_plane_calc_addrs(u32 *addrs, struct drm_framebuffer *fb,
+	int x, int y);
 
 struct armada_crtc {
 	struct drm_crtc		crtc;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_debugfs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_debugfs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,7 +113,7 @@ static int drm_add_fake_info_node(struct
 	struct drm_info_node *node;
 
 	node = kmalloc(sizeof(struct drm_info_node), GFP_KERNEL);
-	if (node == NULL) {
+	if (!node) {
 		debugfs_remove(ent);
 		return -ENOMEM;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_drm.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_drm.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_drm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_drm.h	2017-02-12 16:03:20.000000000 -0500
@@ -53,6 +53,7 @@ struct armada_variant {
 extern const struct armada_variant armada510_ops;
 
 struct armada_private {
+	struct drm_device	drm;
 	struct work_struct	fb_unref_work;
 	DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
 	struct drm_fb_helper	*fbdev;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,106 +49,6 @@ void armada_drm_queue_unref_work(struct
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
 
-static int armada_drm_load(struct drm_device *dev, unsigned long flags)
-{
-	struct armada_private *priv;
-	struct resource *mem = NULL;
-	int ret, n;
-
-	for (n = 0; ; n++) {
-		struct resource *r = platform_get_resource(dev->platformdev,
-							   IORESOURCE_MEM, n);
-		if (!r)
-			break;
-
-		/* Resources above 64K are graphics memory */
-		if (resource_size(r) > SZ_64K)
-			mem = r;
-		else
-			return -EINVAL;
-	}
-
-	if (!mem)
-		return -ENXIO;
-
-	if (!devm_request_mem_region(dev->dev, mem->start,
-			resource_size(mem), "armada-drm"))
-		return -EBUSY;
-
-	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		DRM_ERROR("failed to allocate private\n");
-		return -ENOMEM;
-	}
-
-	platform_set_drvdata(dev->platformdev, dev);
-	dev->dev_private = priv;
-
-	INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
-	INIT_KFIFO(priv->fb_unref);
-
-	/* Mode setting support */
-	drm_mode_config_init(dev);
-	dev->mode_config.min_width = 320;
-	dev->mode_config.min_height = 200;
-
-	/*
-	 * With vscale enabled, the maximum width is 1920 due to the
-	 * 1920 by 3 lines RAM
-	 */
-	dev->mode_config.max_width = 1920;
-	dev->mode_config.max_height = 2048;
-
-	dev->mode_config.preferred_depth = 24;
-	dev->mode_config.funcs = &armada_drm_mode_config_funcs;
-	drm_mm_init(&priv->linear, mem->start, resource_size(mem));
-	mutex_init(&priv->linear_lock);
-
-	ret = component_bind_all(dev->dev, dev);
-	if (ret)
-		goto err_kms;
-
-	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
-	if (ret)
-		goto err_comp;
-
-	dev->irq_enabled = true;
-
-	ret = armada_fbdev_init(dev);
-	if (ret)
-		goto err_comp;
-
-	drm_kms_helper_poll_init(dev);
-
-	return 0;
-
- err_comp:
-	component_unbind_all(dev->dev, dev);
- err_kms:
-	drm_mode_config_cleanup(dev);
-	drm_mm_takedown(&priv->linear);
-	flush_work(&priv->fb_unref_work);
-
-	return ret;
-}
-
-static int armada_drm_unload(struct drm_device *dev)
-{
-	struct armada_private *priv = dev->dev_private;
-
-	drm_kms_helper_poll_fini(dev);
-	armada_fbdev_fini(dev);
-
-	component_unbind_all(dev->dev, dev);
-
-	drm_mode_config_cleanup(dev);
-	drm_mm_takedown(&priv->linear);
-	flush_work(&priv->fb_unref_work);
-	dev->dev_private = NULL;
-
-	return 0;
-}
-
 /* These are called under the vbl_lock. */
 static int armada_drm_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
@@ -186,16 +86,10 @@ static const struct file_operations arma
 };
 
 static struct drm_driver armada_drm_driver = {
-	.load			= armada_drm_load,
 	.lastclose		= armada_drm_lastclose,
-	.unload			= armada_drm_unload,
 	.get_vblank_counter	= drm_vblank_no_hw_counter,
 	.enable_vblank		= armada_drm_enable_vblank,
 	.disable_vblank		= armada_drm_disable_vblank,
-#ifdef CONFIG_DEBUG_FS
-	.debugfs_init		= armada_drm_debugfs_init,
-	.debugfs_cleanup	= armada_drm_debugfs_cleanup,
-#endif
 	.gem_free_object_unlocked = armada_gem_free_object,
 	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
 	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
@@ -218,12 +112,138 @@ static struct drm_driver armada_drm_driv
 
 static int armada_drm_bind(struct device *dev)
 {
-	return drm_platform_init(&armada_drm_driver, to_platform_device(dev));
+	struct armada_private *priv;
+	struct resource *mem = NULL;
+	int ret, n;
+
+	for (n = 0; ; n++) {
+		struct resource *r = platform_get_resource(to_platform_device(dev),
+							   IORESOURCE_MEM, n);
+		if (!r)
+			break;
+
+		/* Resources above 64K are graphics memory */
+		if (resource_size(r) > SZ_64K)
+			mem = r;
+		else
+			return -EINVAL;
+	}
+
+	if (!mem)
+		return -ENXIO;
+
+	if (!devm_request_mem_region(dev, mem->start, resource_size(mem),
+				     "armada-drm"))
+		return -EBUSY;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	/*
+	 * The drm_device structure must be at the start of
+	 * armada_private for drm_dev_unref() to work correctly.
+	 */
+	BUILD_BUG_ON(offsetof(struct armada_private, drm) != 0);
+
+	ret = drm_dev_init(&priv->drm, &armada_drm_driver, dev);
+	if (ret) {
+		dev_err(dev, "[" DRM_NAME ":%s] drm_dev_init failed: %d\n",
+			__func__, ret);
+		kfree(priv);
+		return ret;
+	}
+
+	priv->drm.platformdev = to_platform_device(dev);
+	priv->drm.dev_private = priv;
+
+	platform_set_drvdata(priv->drm.platformdev, &priv->drm);
+
+	INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
+	INIT_KFIFO(priv->fb_unref);
+
+	/* Mode setting support */
+	drm_mode_config_init(&priv->drm);
+	priv->drm.mode_config.min_width = 320;
+	priv->drm.mode_config.min_height = 200;
+
+	/*
+	 * With vscale enabled, the maximum width is 1920 due to the
+	 * 1920 by 3 lines RAM
+	 */
+	priv->drm.mode_config.max_width = 1920;
+	priv->drm.mode_config.max_height = 2048;
+
+	priv->drm.mode_config.preferred_depth = 24;
+	priv->drm.mode_config.funcs = &armada_drm_mode_config_funcs;
+	drm_mm_init(&priv->linear, mem->start, resource_size(mem));
+	mutex_init(&priv->linear_lock);
+
+	ret = component_bind_all(dev, &priv->drm);
+	if (ret)
+		goto err_kms;
+
+	ret = drm_vblank_init(&priv->drm, priv->drm.mode_config.num_crtc);
+	if (ret)
+		goto err_comp;
+
+	priv->drm.irq_enabled = true;
+
+	ret = armada_fbdev_init(&priv->drm);
+	if (ret)
+		goto err_comp;
+
+	drm_kms_helper_poll_init(&priv->drm);
+
+	ret = drm_dev_register(&priv->drm, 0);
+	if (ret)
+		goto err_poll;
+
+#ifdef CONFIG_DEBUG_FS
+	armada_drm_debugfs_init(priv->drm.primary);
+#endif
+
+	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
+		 armada_drm_driver.name, armada_drm_driver.major,
+		 armada_drm_driver.minor, armada_drm_driver.patchlevel,
+		 armada_drm_driver.date, dev_name(dev),
+		 priv->drm.primary->index);
+
+	return 0;
+
+ err_poll:
+	drm_kms_helper_poll_fini(&priv->drm);
+	armada_fbdev_fini(&priv->drm);
+ err_comp:
+	component_unbind_all(dev, &priv->drm);
+ err_kms:
+	drm_mode_config_cleanup(&priv->drm);
+	drm_mm_takedown(&priv->linear);
+	flush_work(&priv->fb_unref_work);
+	drm_dev_unref(&priv->drm);
+	return ret;
 }
 
 static void armada_drm_unbind(struct device *dev)
 {
-	drm_put_dev(dev_get_drvdata(dev));
+	struct drm_device *drm = dev_get_drvdata(dev);
+	struct armada_private *priv = drm->dev_private;
+
+	drm_kms_helper_poll_fini(&priv->drm);
+	armada_fbdev_fini(&priv->drm);
+
+#ifdef CONFIG_DEBUG_FS
+	armada_drm_debugfs_cleanup(priv->drm.primary);
+#endif
+	drm_dev_unregister(&priv->drm);
+
+	component_unbind_all(dev, &priv->drm);
+
+	drm_mode_config_cleanup(&priv->drm);
+	drm_mm_takedown(&priv->linear);
+	flush_work(&priv->fb_unref_work);
+
+	drm_dev_unref(&priv->drm);
 }
 
 static int compare_of(struct device *dev, void *data)
@@ -254,7 +274,7 @@ static void armada_add_endpoints(struct
 			continue;
 		}
 
-		component_match_add(dev, match, compare_of, remote);
+		drm_of_component_match_add(dev, match, compare_of, remote);
 		of_node_put(remote);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,16 +19,10 @@
 
 static /*const*/ struct fb_ops armada_fb_ops = {
 	.owner		= THIS_MODULE,
-	.fb_check_var	= drm_fb_helper_check_var,
-	.fb_set_par	= drm_fb_helper_set_par,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_fillrect	= drm_fb_helper_cfb_fillrect,
 	.fb_copyarea	= drm_fb_helper_cfb_copyarea,
 	.fb_imageblit	= drm_fb_helper_cfb_imageblit,
-	.fb_pan_display	= drm_fb_helper_pan_display,
-	.fb_blank	= drm_fb_helper_blank,
-	.fb_setcmap	= drm_fb_helper_setcmap,
-	.fb_debug_enter	= drm_fb_helper_debug_enter,
-	.fb_debug_leave	= drm_fb_helper_debug_leave,
 };
 
 static int armada_fb_create(struct drm_fb_helper *fbh,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,12 +17,11 @@
 static int armada_gem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct armada_gem_object *obj = drm_to_armada_gem(vma->vm_private_data);
-	unsigned long addr = (unsigned long)vmf->virtual_address;
 	unsigned long pfn = obj->phys_addr >> PAGE_SHIFT;
 	int ret;
 
-	pfn += (addr - vma->vm_start) >> PAGE_SHIFT;
-	ret = vm_insert_pfn(vma, addr, pfn);
+	pfn += (vmf->address - vma->vm_start) >> PAGE_SHIFT;
+	ret = vm_insert_pfn(vma, vmf->address, pfn);
 
 	switch (ret) {
 	case 0:
@@ -212,7 +211,7 @@ armada_gem_alloc_private_object(struct d
 	return obj;
 }
 
-struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev,
+static struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev,
 	size_t size)
 {
 	struct armada_gem_object *obj;
@@ -419,7 +418,7 @@ int armada_gem_pwrite_ioctl(struct drm_d
 }
 
 /* Prime support */
-struct sg_table *
+static struct sg_table *
 armada_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
 	enum dma_data_direction dir)
 {
@@ -594,11 +593,7 @@ int armada_gem_map_import(struct armada_
 	int ret;
 
 	dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
-					  DMA_TO_DEVICE);
-	if (!dobj->sgt) {
-		DRM_ERROR("dma_buf_map_attachment() returned NULL\n");
-		return -EINVAL;
-	}
+					   DMA_TO_DEVICE);
 	if (IS_ERR(dobj->sgt)) {
 		ret = PTR_ERR(dobj->sgt);
 		dobj->sgt = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_overlay.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_overlay.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_overlay.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_overlay.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include "armada_hw.h"
 #include <drm/armada_drm.h>
 #include "armada_ioctlP.h"
+#include "armada_trace.h"
 
 struct armada_ovl_plane_properties {
 	uint32_t colorkey_yr;
@@ -32,10 +33,6 @@ struct armada_ovl_plane_properties {
 struct armada_ovl_plane {
 	struct armada_plane base;
 	struct drm_framebuffer *old_fb;
-	uint32_t src_hw;
-	uint32_t dst_hw;
-	uint32_t dst_yx;
-	uint32_t ctrl0;
 	struct {
 		struct armada_plane_work work;
 		struct armada_regs regs[13];
@@ -87,6 +84,8 @@ static void armada_ovl_plane_work(struct
 {
 	struct armada_ovl_plane *dplane = container_of(plane, struct armada_ovl_plane, base);
 
+	trace_armada_ovl_plane_work(&dcrtc->crtc, &plane->base);
+
 	armada_drm_crtc_update_regs(dcrtc, dplane->vbl.regs);
 	armada_ovl_retire_fb(dplane, NULL);
 }
@@ -120,6 +119,10 @@ armada_ovl_plane_update(struct drm_plane
 	bool visible;
 	int ret;
 
+	trace_armada_ovl_plane_update(plane, crtc, fb,
+				 crtc_x, crtc_y, crtc_w, crtc_h,
+				 src_x, src_y, src_w, src_h);
+
 	ret = drm_plane_helper_check_update(plane, crtc, fb, &src, &dest, &clip,
 					    DRM_ROTATE_0,
 					    0, INT_MAX, true, false, &visible);
@@ -141,22 +144,22 @@ armada_ovl_plane_update(struct drm_plane
 
 	/* FIXME: overlay on an interlaced display */
 	/* Just updating the position/size? */
-	if (plane->fb == fb && dplane->ctrl0 == ctrl0) {
+	if (plane->fb == fb && dplane->base.state.ctrl0 == ctrl0) {
 		val = (drm_rect_height(&src) & 0xffff0000) |
 		      drm_rect_width(&src) >> 16;
-		dplane->src_hw = val;
+		dplane->base.state.src_hw = val;
 		writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_HPXL_VLN);
 
 		val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
-		dplane->dst_hw = val;
+		dplane->base.state.dst_hw = val;
 		writel_relaxed(val, dcrtc->base + LCD_SPU_DZM_HPXL_VLN);
 
 		val = dest.y1 << 16 | dest.x1;
-		dplane->dst_yx = val;
+		dplane->base.state.dst_yx = val;
 		writel_relaxed(val, dcrtc->base + LCD_SPU_DMA_OVSA_HPXL_VLN);
 
 		return 0;
-	} else if (~dplane->ctrl0 & ctrl0 & CFG_DMA_ENA) {
+	} else if (~dplane->base.state.ctrl0 & ctrl0 & CFG_DMA_ENA) {
 		/* Power up the Y/U/V FIFOs on ENA 0->1 transitions */
 		armada_updatel(0, CFG_PDWN16x66 | CFG_PDWN32x66,
 			       dcrtc->base + LCD_SPU_SRAM_PARA1);
@@ -166,9 +169,8 @@ armada_ovl_plane_update(struct drm_plane
 		armada_drm_plane_work_cancel(dcrtc, &dplane->base);
 
 	if (plane->fb != fb) {
-		struct armada_gem_object *obj = drm_fb_obj(fb);
-		uint32_t addr[3], pixel_format;
-		int i, num_planes, hsub;
+		u32 addrs[3], pixel_format;
+		int num_planes, hsub;
 
 		/*
 		 * Take a reference on the new framebuffer - we want to
@@ -182,6 +184,8 @@ armada_ovl_plane_update(struct drm_plane
 		src_y = src.y1 >> 16;
 		src_x = src.x1 >> 16;
 
+		armada_drm_plane_calc_addrs(addrs, fb, src_x, src_y);
+
 		pixel_format = fb->pixel_format;
 		hsub = drm_format_horz_chroma_subsampling(pixel_format);
 		num_planes = drm_format_num_planes(pixel_format);
@@ -194,24 +198,17 @@ armada_ovl_plane_update(struct drm_plane
 		if (src_x & (hsub - 1) && num_planes == 1)
 			ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV);
 
-		for (i = 0; i < num_planes; i++)
-			addr[i] = obj->dev_addr + fb->offsets[i] +
-				  src_y * fb->pitches[i] +
-				  src_x * drm_format_plane_cpp(pixel_format, i);
-		for (; i < ARRAY_SIZE(addr); i++)
-			addr[i] = 0;
-
-		armada_reg_queue_set(dplane->vbl.regs, idx, addr[0],
+		armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0],
 				     LCD_SPU_DMA_START_ADDR_Y0);
-		armada_reg_queue_set(dplane->vbl.regs, idx, addr[1],
+		armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1],
 				     LCD_SPU_DMA_START_ADDR_U0);
-		armada_reg_queue_set(dplane->vbl.regs, idx, addr[2],
+		armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2],
 				     LCD_SPU_DMA_START_ADDR_V0);
-		armada_reg_queue_set(dplane->vbl.regs, idx, addr[0],
+		armada_reg_queue_set(dplane->vbl.regs, idx, addrs[0],
 				     LCD_SPU_DMA_START_ADDR_Y1);
-		armada_reg_queue_set(dplane->vbl.regs, idx, addr[1],
+		armada_reg_queue_set(dplane->vbl.regs, idx, addrs[1],
 				     LCD_SPU_DMA_START_ADDR_U1);
-		armada_reg_queue_set(dplane->vbl.regs, idx, addr[2],
+		armada_reg_queue_set(dplane->vbl.regs, idx, addrs[2],
 				     LCD_SPU_DMA_START_ADDR_V1);
 
 		val = fb->pitches[0] << 16 | fb->pitches[0];
@@ -223,28 +220,28 @@ armada_ovl_plane_update(struct drm_plane
 	}
 
 	val = (drm_rect_height(&src) & 0xffff0000) | drm_rect_width(&src) >> 16;
-	if (dplane->src_hw != val) {
-		dplane->src_hw = val;
+	if (dplane->base.state.src_hw != val) {
+		dplane->base.state.src_hw = val;
 		armada_reg_queue_set(dplane->vbl.regs, idx, val,
 				     LCD_SPU_DMA_HPXL_VLN);
 	}
 
 	val = drm_rect_height(&dest) << 16 | drm_rect_width(&dest);
-	if (dplane->dst_hw != val) {
-		dplane->dst_hw = val;
+	if (dplane->base.state.dst_hw != val) {
+		dplane->base.state.dst_hw = val;
 		armada_reg_queue_set(dplane->vbl.regs, idx, val,
 				     LCD_SPU_DZM_HPXL_VLN);
 	}
 
 	val = dest.y1 << 16 | dest.x1;
-	if (dplane->dst_yx != val) {
-		dplane->dst_yx = val;
+	if (dplane->base.state.dst_yx != val) {
+		dplane->base.state.dst_yx = val;
 		armada_reg_queue_set(dplane->vbl.regs, idx, val,
 				     LCD_SPU_DMA_OVSA_HPXL_VLN);
 	}
 
-	if (dplane->ctrl0 != ctrl0) {
-		dplane->ctrl0 = ctrl0;
+	if (dplane->base.state.ctrl0 != ctrl0) {
+		dplane->base.state.ctrl0 = ctrl0;
 		armada_reg_queue_mod(dplane->vbl.regs, idx, ctrl0,
 			CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE |
 			CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE |
@@ -275,7 +272,7 @@ static int armada_ovl_plane_disable(stru
 	armada_drm_crtc_plane_disable(dcrtc, plane);
 
 	dcrtc->plane = NULL;
-	dplane->ctrl0 = 0;
+	dplane->base.state.ctrl0 = 0;
 
 	fb = xchg(&dplane->old_fb, NULL);
 	if (fb)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_trace.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_trace.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_trace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_trace.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,4 @@
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "armada_trace.h"
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_trace.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_trace.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/armada_trace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/armada_trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,66 @@
+#if !defined(ARMADA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define ARMADA_TRACE_H
+
+#include <linux/tracepoint.h>
+#include <drm/drmP.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM armada
+#define TRACE_INCLUDE_FILE armada_trace
+
+TRACE_EVENT(armada_drm_irq,
+	TP_PROTO(struct drm_crtc *crtc, u32 stat),
+	TP_ARGS(crtc, stat),
+	TP_STRUCT__entry(
+		__field(struct drm_crtc *, crtc)
+		__field(u32, stat)
+	),
+	TP_fast_assign(
+		__entry->crtc = crtc;
+		__entry->stat = stat;
+	),
+	TP_printk("crtc %p stat 0x%08x",
+		__entry->crtc, __entry->stat)
+);
+
+TRACE_EVENT(armada_ovl_plane_update,
+	TP_PROTO(struct drm_plane *plane, struct drm_crtc *crtc,
+		     struct drm_framebuffer *fb,
+		     int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
+		     uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h),
+	TP_ARGS(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h),
+	TP_STRUCT__entry(
+		__field(struct drm_plane *, plane)
+		__field(struct drm_crtc *, crtc)
+		__field(struct drm_framebuffer *, fb)
+	),
+	TP_fast_assign(
+		__entry->plane = plane;
+		__entry->crtc = crtc;
+		__entry->fb = fb;
+	),
+	TP_printk("plane %p crtc %p fb %p",
+		__entry->plane, __entry->crtc, __entry->fb)
+);
+
+TRACE_EVENT(armada_ovl_plane_work,
+	TP_PROTO(struct drm_crtc *crtc, struct drm_plane *plane),
+	TP_ARGS(crtc, plane),
+	TP_STRUCT__entry(
+		__field(struct drm_plane *, plane)
+		__field(struct drm_crtc *, crtc)
+	),
+	TP_fast_assign(
+		__entry->plane = plane;
+		__entry->crtc = crtc;
+	),
+	TP_printk("plane %p crtc %p",
+		__entry->plane, __entry->crtc)
+);
+
+#endif
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/armada/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/armada/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/armada/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 armada-y	:= armada_crtc.o armada_drv.o armada_fb.o armada_fbdev.o \
-		   armada_gem.o armada_overlay.o
+		   armada_gem.o armada_overlay.o armada_trace.o
 armada-y	+= armada_510.o
 armada-$(CONFIG_DEBUG_FS) += armada_debugfs.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -188,9 +188,7 @@ static const struct file_operations ast_
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = ast_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.read = drm_read,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -113,6 +113,7 @@ struct ast_private {
 	struct ttm_bo_kmap_obj cache_kmap;
 	int next_cursor;
 	bool support_wide_screen;
+	bool DisableP2A;
 
 	enum ast_tx_chip tx_chip_type;
 	u8 dp501_maxclk;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -253,7 +253,7 @@ static int astfb_create(struct drm_fb_he
 err_release_fbi:
 	drm_fb_helper_release_fbi(helper);
 err_free_vram:
-	vfree(afbdev->sysram);
+	vfree(sysram);
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_main.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_main.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -124,6 +124,12 @@ static int ast_detect_chip(struct drm_de
 	} else
 		*need_post = false;
 
+	/* Check P2A Access */
+	ast->DisableP2A = true;
+	data = ast_read32(ast, 0xf004);
+	if (data != 0xFFFFFFFF)
+		ast->DisableP2A = false;
+
 	/* Check if we support wide screen */
 	switch (ast->chip) {
 	case AST1180:
@@ -140,15 +146,17 @@ static int ast_detect_chip(struct drm_de
 			ast->support_wide_screen = true;
 		else {
 			ast->support_wide_screen = false;
-			/* Read SCU7c (silicon revision register) */
-			ast_write32(ast, 0xf004, 0x1e6e0000);
-			ast_write32(ast, 0xf000, 0x1);
-			data = ast_read32(ast, 0x1207c);
-			data &= 0x300;
-			if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
-				ast->support_wide_screen = true;
-			if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
-				ast->support_wide_screen = true;
+			if (ast->DisableP2A == false) {
+				/* Read SCU7c (silicon revision register) */
+				ast_write32(ast, 0xf004, 0x1e6e0000);
+				ast_write32(ast, 0xf000, 0x1);
+				data = ast_read32(ast, 0x1207c);
+				data &= 0x300;
+				if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
+					ast->support_wide_screen = true;
+				if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
+					ast->support_wide_screen = true;
+			}
 		}
 		break;
 	}
@@ -216,79 +224,81 @@ static int ast_get_dram_info(struct drm_
 	uint32_t data, data2;
 	uint32_t denum, num, div, ref_pll;
 
-	ast_write32(ast, 0xf004, 0x1e6e0000);
-	ast_write32(ast, 0xf000, 0x1);
-
+	if (ast->DisableP2A)
+	{
+		ast->dram_bus_width = 16;
+		ast->dram_type = AST_DRAM_1Gx16;
+		ast->mclk = 396;
+	}
+	else
+	{
+		ast_write32(ast, 0xf004, 0x1e6e0000);
+		ast_write32(ast, 0xf000, 0x1);
+		data = ast_read32(ast, 0x10004);
 
-	ast_write32(ast, 0x10000, 0xfc600309);
+		if (data & 0x40)
+			ast->dram_bus_width = 16;
+		else
+			ast->dram_bus_width = 32;
 
-	do {
-		;
-	} while (ast_read32(ast, 0x10000) != 0x01);
-	data = ast_read32(ast, 0x10004);
+		if (ast->chip == AST2300 || ast->chip == AST2400) {
+			switch (data & 0x03) {
+			case 0:
+				ast->dram_type = AST_DRAM_512Mx16;
+				break;
+			default:
+			case 1:
+				ast->dram_type = AST_DRAM_1Gx16;
+				break;
+			case 2:
+				ast->dram_type = AST_DRAM_2Gx16;
+				break;
+			case 3:
+				ast->dram_type = AST_DRAM_4Gx16;
+				break;
+			}
+		} else {
+			switch (data & 0x0c) {
+			case 0:
+			case 4:
+				ast->dram_type = AST_DRAM_512Mx16;
+				break;
+			case 8:
+				if (data & 0x40)
+					ast->dram_type = AST_DRAM_1Gx16;
+				else
+					ast->dram_type = AST_DRAM_512Mx32;
+				break;
+			case 0xc:
+				ast->dram_type = AST_DRAM_1Gx32;
+				break;
+			}
+		}
 
-	if (data & 0x40)
-		ast->dram_bus_width = 16;
-	else
-		ast->dram_bus_width = 32;
+		data = ast_read32(ast, 0x10120);
+		data2 = ast_read32(ast, 0x10170);
+		if (data2 & 0x2000)
+			ref_pll = 14318;
+		else
+			ref_pll = 12000;
 
-	if (ast->chip == AST2300 || ast->chip == AST2400) {
-		switch (data & 0x03) {
-		case 0:
-			ast->dram_type = AST_DRAM_512Mx16;
-			break;
-		default:
-		case 1:
-			ast->dram_type = AST_DRAM_1Gx16;
-			break;
-		case 2:
-			ast->dram_type = AST_DRAM_2Gx16;
-			break;
+		denum = data & 0x1f;
+		num = (data & 0x3fe0) >> 5;
+		data = (data & 0xc000) >> 14;
+		switch (data) {
 		case 3:
-			ast->dram_type = AST_DRAM_4Gx16;
-			break;
-		}
-	} else {
-		switch (data & 0x0c) {
-		case 0:
-		case 4:
-			ast->dram_type = AST_DRAM_512Mx16;
+			div = 0x4;
 			break;
-		case 8:
-			if (data & 0x40)
-				ast->dram_type = AST_DRAM_1Gx16;
-			else
-				ast->dram_type = AST_DRAM_512Mx32;
+		case 2:
+		case 1:
+			div = 0x2;
 			break;
-		case 0xc:
-			ast->dram_type = AST_DRAM_1Gx32;
+		default:
+			div = 0x1;
 			break;
 		}
+		ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
 	}
-
-	data = ast_read32(ast, 0x10120);
-	data2 = ast_read32(ast, 0x10170);
-	if (data2 & 0x2000)
-		ref_pll = 14318;
-	else
-		ref_pll = 12000;
-
-	denum = data & 0x1f;
-	num = (data & 0x3fe0) >> 5;
-	data = (data & 0xc000) >> 14;
-	switch (data) {
-	case 3:
-		div = 0x4;
-		break;
-	case 2:
-	case 1:
-		div = 0x2;
-		break;
-	default:
-		div = 0x1;
-		break;
-	}
-	ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
 	return 0;
 }
 
@@ -428,7 +438,9 @@ int ast_driver_load(struct drm_device *d
 	ast_detect_chip(dev, &need_post);
 
 	if (ast->chip != AST1180) {
-		ast_get_dram_info(dev);
+		ret = ast_get_dram_info(dev);
+		if (ret)
+			goto out_free;
 		ast->vram_size = ast_get_vram_info(dev);
 		DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_mode.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_mode.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_mode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_mode.c	2017-02-12 16:03:20.000000000 -0500
@@ -839,12 +839,6 @@ static void ast_connector_destroy(struct
 	kfree(connector);
 }
 
-static enum drm_connector_status
-ast_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static const struct drm_connector_helper_funcs ast_connector_helper_funcs = {
 	.mode_valid = ast_mode_valid,
 	.get_modes = ast_get_modes,
@@ -853,7 +847,6 @@ static const struct drm_connector_helper
 
 static const struct drm_connector_funcs ast_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
-	.detect = ast_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = ast_connector_destroy,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_post.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_post.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_post.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_post.c	2017-02-12 16:03:20.000000000 -0500
@@ -379,12 +379,20 @@ void ast_post_gpu(struct drm_device *dev
 	ast_open_key(ast);
 	ast_set_def_ext_reg(dev);
 
-	if (ast->chip == AST2300 || ast->chip == AST2400)
-		ast_init_dram_2300(dev);
-	else
-		ast_init_dram_reg(dev);
+	if (ast->DisableP2A == false)
+	{
+		if (ast->chip == AST2300 || ast->chip == AST2400)
+			ast_init_dram_2300(dev);
+		else
+			ast_init_dram_reg(dev);
 
-	ast_init_3rdtx(dev);
+		ast_init_3rdtx(dev);
+	}
+	else
+	{
+		if (ast->tx_chip_type != AST_TX_NONE)
+			ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);	/* Enable DVO */
+	}
 }
 
 /* AST 2300 DRAM settings */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ast/ast_ttm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ast/ast_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -230,6 +230,7 @@ struct ttm_bo_driver ast_bo_driver = {
 	.ttm_tt_populate = ast_ttm_tt_populate,
 	.ttm_tt_unpopulate = ast_ttm_tt_unpopulate,
 	.init_mem_type = ast_bo_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = ast_bo_evict_flags,
 	.move = NULL,
 	.verify_access = ast_bo_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c	2017-02-12 16:03:20.000000000 -0500
@@ -464,7 +464,7 @@ atmel_hlcdc_dc_atomic_complete(struct at
 
 	drm_atomic_helper_cleanup_planes(dev, old_state);
 
-	drm_atomic_state_free(old_state);
+	drm_atomic_state_put(old_state);
 
 	/* Complete the commit, wake up any waiter. */
 	spin_lock(&dc->commit.wait.lock);
@@ -521,6 +521,7 @@ static int atmel_hlcdc_dc_atomic_commit(
 	/* Swap the state, this is the point of no return. */
 	drm_atomic_helper_swap_state(state, true);
 
+	drm_atomic_state_get(state);
 	if (async)
 		queue_work(dc->wq, &commit->work);
 	else
@@ -748,9 +749,7 @@ static const struct file_operations fops
 	.open               = drm_open,
 	.release            = drm_release,
 	.unlocked_ioctl     = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl       = drm_compat_ioctl,
-#endif
 	.poll               = drm_poll,
 	.read               = drm_read,
 	.llseek             = no_llseek,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -393,7 +393,7 @@ static void atmel_hlcdc_plane_update_for
 
 	if ((state->base.fb->pixel_format == DRM_FORMAT_YUV422 ||
 	     state->base.fb->pixel_format == DRM_FORMAT_NV61) &&
-	    (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)))
+	    drm_rotation_90_or_270(state->base.rotation))
 		cfg |= ATMEL_HLCDC_YUV422ROT;
 
 	atmel_hlcdc_layer_update_cfg(&plane->layer,
@@ -628,7 +628,7 @@ static int atmel_hlcdc_plane_atomic_chec
 	/*
 	 * Swap width and size in case of 90 or 270 degrees rotation
 	 */
-	if (state->base.rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) {
+	if (drm_rotation_90_or_270(state->base.rotation)) {
 		tmp = state->crtc_w;
 		state->crtc_w = state->crtc_h;
 		state->crtc_h = tmp;
@@ -883,9 +883,9 @@ static int atmel_hlcdc_plane_atomic_get_
 	return 0;
 }
 
-static void atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
-				const struct atmel_hlcdc_layer_desc *desc,
-				struct atmel_hlcdc_plane_properties *props)
+static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane,
+					     const struct atmel_hlcdc_layer_desc *desc,
+					     struct atmel_hlcdc_plane_properties *props)
 {
 	struct regmap *regmap = plane->layer.hlcdc->regmap;
 
@@ -902,10 +902,18 @@ static void atmel_hlcdc_plane_init_prope
 				ATMEL_HLCDC_LAYER_GA_MASK);
 	}
 
-	if (desc->layout.xstride && desc->layout.pstride)
-		drm_object_attach_property(&plane->base.base,
-				plane->base.dev->mode_config.rotation_property,
-				DRM_ROTATE_0);
+	if (desc->layout.xstride && desc->layout.pstride) {
+		int ret;
+
+		ret = drm_plane_create_rotation_property(&plane->base,
+							 DRM_ROTATE_0,
+							 DRM_ROTATE_0 |
+							 DRM_ROTATE_90 |
+							 DRM_ROTATE_180 |
+							 DRM_ROTATE_270);
+		if (ret)
+			return ret;
+	}
 
 	if (desc->layout.csc) {
 		/*
@@ -925,6 +933,8 @@ static void atmel_hlcdc_plane_init_prope
 			     ATMEL_HLCDC_LAYER_CSC_CFG(&plane->layer, 2),
 			     0x40040890);
 	}
+
+	return 0;
 }
 
 static struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
@@ -1036,7 +1046,9 @@ atmel_hlcdc_plane_create(struct drm_devi
 			     &atmel_hlcdc_layer_plane_helper_funcs);
 
 	/* Set default property values*/
-	atmel_hlcdc_plane_init_properties(plane, desc, props);
+	ret = atmel_hlcdc_plane_init_properties(plane, desc, props);
+	if (ret)
+		return ERR_PTR(ret);
 
 	return plane;
 }
@@ -1054,15 +1066,6 @@ atmel_hlcdc_plane_create_properties(stru
 	if (!props->alpha)
 		return ERR_PTR(-ENOMEM);
 
-	dev->mode_config.rotation_property =
-			drm_mode_create_rotation_property(dev,
-							  DRM_ROTATE_0 |
-							  DRM_ROTATE_90 |
-							  DRM_ROTATE_180 |
-							  DRM_ROTATE_270);
-	if (!dev->mode_config.rotation_property)
-		return ERR_PTR(-ENOMEM);
-
 	return props;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,9 +70,7 @@ static const struct file_operations boch
 	.open		= drm_open,
 	.release	= drm_release,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl	= drm_compat_ioctl,
-#endif
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.llseek		= no_llseek,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,14 +22,10 @@ static int bochsfb_mmap(struct fb_info *
 
 static struct fb_ops bochsfb_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_fillrect = drm_fb_helper_sys_fillrect,
 	.fb_copyarea = drm_fb_helper_sys_copyarea,
 	.fb_imageblit = drm_fb_helper_sys_imageblit,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
 	.fb_mmap = bochsfb_mmap,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -216,12 +216,6 @@ bochs_connector_best_encoder(struct drm_
 	return NULL;
 }
 
-static enum drm_connector_status bochs_connector_detect(struct drm_connector
-							*connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static const struct drm_connector_helper_funcs bochs_connector_connector_helper_funcs = {
 	.get_modes = bochs_connector_get_modes,
 	.mode_valid = bochs_connector_mode_valid,
@@ -230,7 +224,6 @@ static const struct drm_connector_helper
 
 static const struct drm_connector_funcs bochs_connector_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
-	.detect = bochs_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = drm_connector_cleanup,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_mm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_mm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bochs/bochs_mm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bochs/bochs_mm.c	2017-02-12 16:03:20.000000000 -0500
@@ -199,6 +199,7 @@ struct ttm_bo_driver bochs_bo_driver = {
 	.ttm_tt_populate = ttm_pool_populate,
 	.ttm_tt_unpopulate = ttm_pool_unpopulate,
 	.init_mem_type = bochs_bo_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = bochs_bo_evict_flags,
 	.move = NULL,
 	.verify_access = bochs_bo_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,213 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ * Copyright (c) 2016, Linaro Limited
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <sound/core.h>
+#include <sound/hdmi-codec.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include "adv7511.h"
+
+static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
+			       unsigned int *cts, unsigned int *n)
+{
+	switch (fs) {
+	case 32000:
+		*n = 4096;
+		break;
+	case 44100:
+		*n = 6272;
+		break;
+	case 48000:
+		*n = 6144;
+		break;
+	}
+
+	*cts = ((f_tmds * *n) / (128 * fs)) * 1000;
+}
+
+static int adv7511_update_cts_n(struct adv7511 *adv7511)
+{
+	unsigned int cts = 0;
+	unsigned int n = 0;
+
+	adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n);
+
+	regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf);
+	regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff);
+	regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff);
+
+	regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0,
+		     (cts >> 16) & 0xf);
+	regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1,
+		     (cts >> 8) & 0xff);
+	regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2,
+		     cts & 0xff);
+
+	return 0;
+}
+
+int adv7511_hdmi_hw_params(struct device *dev, void *data,
+			   struct hdmi_codec_daifmt *fmt,
+			   struct hdmi_codec_params *hparms)
+{
+	struct adv7511 *adv7511 = dev_get_drvdata(dev);
+	unsigned int audio_source, i2s_format = 0;
+	unsigned int invert_clock;
+	unsigned int rate;
+	unsigned int len;
+
+	switch (hparms->sample_rate) {
+	case 32000:
+		rate = ADV7511_SAMPLE_FREQ_32000;
+		break;
+	case 44100:
+		rate = ADV7511_SAMPLE_FREQ_44100;
+		break;
+	case 48000:
+		rate = ADV7511_SAMPLE_FREQ_48000;
+		break;
+	case 88200:
+		rate = ADV7511_SAMPLE_FREQ_88200;
+		break;
+	case 96000:
+		rate = ADV7511_SAMPLE_FREQ_96000;
+		break;
+	case 176400:
+		rate = ADV7511_SAMPLE_FREQ_176400;
+		break;
+	case 192000:
+		rate = ADV7511_SAMPLE_FREQ_192000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (hparms->sample_width) {
+	case 16:
+		len = ADV7511_I2S_SAMPLE_LEN_16;
+		break;
+	case 18:
+		len = ADV7511_I2S_SAMPLE_LEN_18;
+		break;
+	case 20:
+		len = ADV7511_I2S_SAMPLE_LEN_20;
+		break;
+	case 24:
+		len = ADV7511_I2S_SAMPLE_LEN_24;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (fmt->fmt) {
+	case HDMI_I2S:
+		audio_source = ADV7511_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7511_I2S_FORMAT_I2S;
+		break;
+	case HDMI_RIGHT_J:
+		audio_source = ADV7511_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7511_I2S_FORMAT_RIGHT_J;
+		break;
+	case HDMI_LEFT_J:
+		audio_source = ADV7511_AUDIO_SOURCE_I2S;
+		i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	invert_clock = fmt->bit_clk_inv;
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70,
+			   audio_source << 4);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6),
+			   invert_clock << 6);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03,
+			   i2s_format);
+
+	adv7511->audio_source = audio_source;
+
+	adv7511->f_audio = hparms->sample_rate;
+
+	adv7511_update_cts_n(adv7511);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3,
+			   ADV7511_AUDIO_CFG3_LEN_MASK, len);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
+			   ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
+	regmap_write(adv7511->regmap, 0x73, 0x1);
+
+	return 0;
+}
+
+static int audio_startup(struct device *dev, void *data)
+{
+	struct adv7511 *adv7511 = dev_get_drvdata(dev);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
+				BIT(7), 0);
+
+	/* hide Audio infoframe updates */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
+				BIT(5), BIT(5));
+	/* enable N/CTS, enable Audio sample packets */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+				BIT(5), BIT(5));
+	/* enable N/CTS */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+				BIT(6), BIT(6));
+	/* not copyrighted */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG1,
+				BIT(5), BIT(5));
+	/* enable audio infoframes */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+				BIT(3), BIT(3));
+	/* AV mute disable */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
+				BIT(7) | BIT(6), BIT(7));
+	/* use Audio infoframe updated info */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
+				BIT(5), 0);
+	return 0;
+}
+
+static void audio_shutdown(struct device *dev, void *data)
+{
+}
+
+static const struct hdmi_codec_ops adv7511_codec_ops = {
+	.hw_params	= adv7511_hdmi_hw_params,
+	.audio_shutdown = audio_shutdown,
+	.audio_startup	= audio_startup,
+};
+
+static struct hdmi_codec_pdata codec_data = {
+	.ops = &adv7511_codec_ops,
+	.max_i2s_channels = 2,
+	.i2s = 1,
+};
+
+int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
+{
+	adv7511->audio_pdev = platform_device_register_data(dev,
+					HDMI_CODEC_DRV_NAME,
+					PLATFORM_DEVID_AUTO,
+					&codec_data,
+					sizeof(codec_data));
+	return PTR_ERR_OR_ZERO(adv7511->audio_pdev);
+}
+
+void adv7511_audio_exit(struct adv7511 *adv7511)
+{
+	if (adv7511->audio_pdev) {
+		platform_device_unregister(adv7511->audio_pdev);
+		adv7511->audio_pdev = NULL;
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -1037,6 +1037,8 @@ static int adv7511_probe(struct i2c_clie
 		goto err_unregister_cec;
 	}
 
+	adv7511_audio_init(dev, adv7511);
+
 	return 0;
 
 err_unregister_cec:
@@ -1058,6 +1060,8 @@ static int adv7511_remove(struct i2c_cli
 
 	drm_bridge_remove(&adv7511->bridge);
 
+	adv7511_audio_exit(adv7511);
+
 	i2c_unregister_device(adv7511->i2c_edid);
 
 	kfree(adv7511->edid);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7511.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7511.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7511.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7511.h	2017-02-12 16:03:20.000000000 -0500
@@ -309,6 +309,8 @@ struct adv7511 {
 	struct drm_display_mode curr_mode;
 
 	unsigned int f_tmds;
+	unsigned int f_audio;
+	unsigned int audio_source;
 
 	unsigned int current_edid_segment;
 	uint8_t edid_buf[256];
@@ -334,6 +336,7 @@ struct adv7511 {
 	bool use_timing_gen;
 
 	enum adv7511_type type;
+	struct platform_device *audio_pdev;
 };
 
 #ifdef CONFIG_DRM_I2C_ADV7533
@@ -389,4 +392,17 @@ static inline int adv7533_parse_dt(struc
 }
 #endif
 
+#ifdef CONFIG_DRM_I2C_ADV7511_AUDIO
+int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511);
+void adv7511_audio_exit(struct adv7511 *adv7511);
+#else /*CONFIG_DRM_I2C_ADV7511_AUDIO */
+static inline int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
+{
+	return 0;
+}
+static inline void adv7511_audio_exit(struct adv7511 *adv7511)
+{
+}
+#endif /* CONFIG_DRM_I2C_ADV7511_AUDIO */
+
 #endif /* __DRM_I2C_ADV7511_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7533.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7533.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/adv7533.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/adv7533.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,7 @@ static const struct reg_sequence adv7533
 	{ 0x17, 0xd0 },
 	{ 0x24, 0x20 },
 	{ 0x57, 0x11 },
+	{ 0x05, 0xc8 },
 };
 
 static const struct regmap_config adv7533_cec_regmap_config = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,14 @@ config DRM_I2C_ADV7511
 	help
 	  Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
 
+config DRM_I2C_ADV7511_AUDIO
+	bool "ADV7511 HDMI Audio driver"
+	depends on DRM_I2C_ADV7511 && SND_SOC
+	select SND_SOC_HDMI_CODEC
+	help
+	  Support the ADV7511 HDMI Audio interface. This is used in
+	  conjunction with the AV7511  HDMI driver.
+
 config DRM_I2C_ADV7533
 	bool "ADV7533 encoder"
 	depends on DRM_I2C_ADV7511
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/adv7511/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/adv7511/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,4 @@
 adv7511-y := adv7511_drv.o
+adv7511-$(CONFIG_DRM_I2C_ADV7511_AUDIO) += adv7511_audio.o
 adv7511-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -112,7 +112,7 @@ int analogix_dp_enable_psr(struct device
 	struct edp_vsc_psr psr_vsc;
 
 	if (!dp->psr_support)
-		return -EINVAL;
+		return 0;
 
 	/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
 	memset(&psr_vsc, 0, sizeof(psr_vsc));
@@ -135,7 +135,7 @@ int analogix_dp_disable_psr(struct devic
 	struct edp_vsc_psr psr_vsc;
 
 	if (!dp->psr_support)
-		return -EINVAL;
+		return 0;
 
 	/* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */
 	memset(&psr_vsc, 0, sizeof(psr_vsc));
@@ -1382,6 +1382,7 @@ int analogix_dp_bind(struct device *dev,
 
 	pm_runtime_enable(dev);
 
+	pm_runtime_get_sync(dev);
 	phy_power_on(dp->phy);
 
 	analogix_dp_init_dp(dp);
@@ -1414,9 +1415,15 @@ int analogix_dp_bind(struct device *dev,
 		goto err_disable_pm_runtime;
 	}
 
+	phy_power_off(dp->phy);
+	pm_runtime_put(dev);
+
 	return 0;
 
 err_disable_pm_runtime:
+
+	phy_power_off(dp->phy);
+	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c	2017-02-12 16:03:20.000000000 -0500
@@ -1162,5 +1162,5 @@ ssize_t analogix_dp_transfer(struct anal
 		 (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
 		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
 
-	return num_transferred;
+	return num_transferred > 0 ? num_transferred : -EBUSY;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dumb-vga-dac.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dumb-vga-dac.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dumb-vga-dac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dumb-vga-dac.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
@@ -23,6 +24,7 @@ struct dumb_vga {
 	struct drm_connector	connector;
 
 	struct i2c_adapter	*ddc;
+	struct regulator	*vdd;
 };
 
 static inline struct dumb_vga *
@@ -124,8 +126,30 @@ static int dumb_vga_attach(struct drm_br
 	return 0;
 }
 
+static void dumb_vga_enable(struct drm_bridge *bridge)
+{
+	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+	int ret = 0;
+
+	if (vga->vdd)
+		ret = regulator_enable(vga->vdd);
+
+	if (ret)
+		DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+}
+
+static void dumb_vga_disable(struct drm_bridge *bridge)
+{
+	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+
+	if (vga->vdd)
+		regulator_disable(vga->vdd);
+}
+
 static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
 	.attach		= dumb_vga_attach,
+	.enable		= dumb_vga_enable,
+	.disable	= dumb_vga_disable,
 };
 
 static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
@@ -169,6 +193,15 @@ static int dumb_vga_probe(struct platfor
 		return -ENOMEM;
 	platform_set_drvdata(pdev, vga);
 
+	vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
+	if (IS_ERR(vga->vdd)) {
+		ret = PTR_ERR(vga->vdd);
+		if (ret == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		vga->vdd = NULL;
+		dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
+	}
+
 	vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
 	if (IS_ERR(vga->ddc)) {
 		if (PTR_ERR(vga->ddc) == -ENODEV) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi-audio.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi-audio.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi-audio.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi-audio.h	2017-02-12 16:03:20.000000000 -0500
@@ -11,4 +11,11 @@ struct dw_hdmi_audio_data {
 	u8 *eld;
 };
 
+struct dw_hdmi_i2s_audio_data {
+	struct dw_hdmi *hdmi;
+
+	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
+	u8 (*read)(struct dw_hdmi *hdmi, int offset);
+};
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,14 +1,15 @@
 /*
+ * DesignWare High-Definition Multimedia Interface (HDMI) driver
+ *
+ * Copyright (C) 2013-2015 Mentor Graphics Inc.
  * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * Designware High-Definition Multimedia Interface (HDMI) driver
- *
- * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
  */
 #include <linux/module.h>
 #include <linux/irq.h>
@@ -101,6 +102,17 @@ struct hdmi_data_info {
 	struct hdmi_vmode video_mode;
 };
 
+struct dw_hdmi_i2c {
+	struct i2c_adapter	adap;
+
+	struct mutex		lock;	/* used to serialize data transfers */
+	struct completion	cmp;
+	u8			stat;
+
+	u8			slave_reg;
+	bool			is_regaddr;
+};
+
 struct dw_hdmi {
 	struct drm_connector connector;
 	struct drm_encoder *encoder;
@@ -111,6 +123,7 @@ struct dw_hdmi {
 	struct device *dev;
 	struct clk *isfr_clk;
 	struct clk *iahb_clk;
+	struct dw_hdmi_i2c *i2c;
 
 	struct hdmi_data_info hdmi_data;
 	const struct dw_hdmi_plat_data *plat_data;
@@ -198,6 +211,201 @@ static void hdmi_mask_writeb(struct dw_h
 	hdmi_modb(hdmi, data << shift, mask, reg);
 }
 
+static void dw_hdmi_i2c_init(struct dw_hdmi *hdmi)
+{
+	/* Software reset */
+	hdmi_writeb(hdmi, 0x00, HDMI_I2CM_SOFTRSTZ);
+
+	/* Set Standard Mode speed (determined to be 100KHz on iMX6) */
+	hdmi_writeb(hdmi, 0x00, HDMI_I2CM_DIV);
+
+	/* Set done, not acknowledged and arbitration interrupt polarities */
+	hdmi_writeb(hdmi, HDMI_I2CM_INT_DONE_POL, HDMI_I2CM_INT);
+	hdmi_writeb(hdmi, HDMI_I2CM_CTLINT_NAC_POL | HDMI_I2CM_CTLINT_ARB_POL,
+		    HDMI_I2CM_CTLINT);
+
+	/* Clear DONE and ERROR interrupts */
+	hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+		    HDMI_IH_I2CM_STAT0);
+
+	/* Mute DONE and ERROR interrupts */
+	hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+		    HDMI_IH_MUTE_I2CM_STAT0);
+}
+
+static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi,
+			    unsigned char *buf, unsigned int length)
+{
+	struct dw_hdmi_i2c *i2c = hdmi->i2c;
+	int stat;
+
+	if (!i2c->is_regaddr) {
+		dev_dbg(hdmi->dev, "set read register address to 0\n");
+		i2c->slave_reg = 0x00;
+		i2c->is_regaddr = true;
+	}
+
+	while (length--) {
+		reinit_completion(&i2c->cmp);
+
+		hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
+		hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_READ,
+			    HDMI_I2CM_OPERATION);
+
+		stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
+		if (!stat)
+			return -EAGAIN;
+
+		/* Check for error condition on the bus */
+		if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
+			return -EIO;
+
+		*buf++ = hdmi_readb(hdmi, HDMI_I2CM_DATAI);
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi,
+			     unsigned char *buf, unsigned int length)
+{
+	struct dw_hdmi_i2c *i2c = hdmi->i2c;
+	int stat;
+
+	if (!i2c->is_regaddr) {
+		/* Use the first write byte as register address */
+		i2c->slave_reg = buf[0];
+		length--;
+		buf++;
+		i2c->is_regaddr = true;
+	}
+
+	while (length--) {
+		reinit_completion(&i2c->cmp);
+
+		hdmi_writeb(hdmi, *buf++, HDMI_I2CM_DATAO);
+		hdmi_writeb(hdmi, i2c->slave_reg++, HDMI_I2CM_ADDRESS);
+		hdmi_writeb(hdmi, HDMI_I2CM_OPERATION_WRITE,
+			    HDMI_I2CM_OPERATION);
+
+		stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
+		if (!stat)
+			return -EAGAIN;
+
+		/* Check for error condition on the bus */
+		if (i2c->stat & HDMI_IH_I2CM_STAT0_ERROR)
+			return -EIO;
+	}
+
+	return 0;
+}
+
+static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap,
+			    struct i2c_msg *msgs, int num)
+{
+	struct dw_hdmi *hdmi = i2c_get_adapdata(adap);
+	struct dw_hdmi_i2c *i2c = hdmi->i2c;
+	u8 addr = msgs[0].addr;
+	int i, ret = 0;
+
+	dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
+
+	for (i = 0; i < num; i++) {
+		if (msgs[i].addr != addr) {
+			dev_warn(hdmi->dev,
+				 "unsupported transfer, changed slave address\n");
+			return -EOPNOTSUPP;
+		}
+
+		if (msgs[i].len == 0) {
+			dev_dbg(hdmi->dev,
+				"unsupported transfer %d/%d, no data\n",
+				i + 1, num);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	mutex_lock(&i2c->lock);
+
+	/* Unmute DONE and ERROR interrupts */
+	hdmi_writeb(hdmi, 0x00, HDMI_IH_MUTE_I2CM_STAT0);
+
+	/* Set slave device address taken from the first I2C message */
+	hdmi_writeb(hdmi, addr, HDMI_I2CM_SLAVE);
+
+	/* Set slave device register address on transfer */
+	i2c->is_regaddr = false;
+
+	for (i = 0; i < num; i++) {
+		dev_dbg(hdmi->dev, "xfer: num: %d/%d, len: %d, flags: %#x\n",
+			i + 1, num, msgs[i].len, msgs[i].flags);
+
+		if (msgs[i].flags & I2C_M_RD)
+			ret = dw_hdmi_i2c_read(hdmi, msgs[i].buf, msgs[i].len);
+		else
+			ret = dw_hdmi_i2c_write(hdmi, msgs[i].buf, msgs[i].len);
+
+		if (ret < 0)
+			break;
+	}
+
+	if (!ret)
+		ret = num;
+
+	/* Mute DONE and ERROR interrupts */
+	hdmi_writeb(hdmi, HDMI_IH_I2CM_STAT0_ERROR | HDMI_IH_I2CM_STAT0_DONE,
+		    HDMI_IH_MUTE_I2CM_STAT0);
+
+	mutex_unlock(&i2c->lock);
+
+	return ret;
+}
+
+static u32 dw_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm dw_hdmi_algorithm = {
+	.master_xfer	= dw_hdmi_i2c_xfer,
+	.functionality	= dw_hdmi_i2c_func,
+};
+
+static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
+{
+	struct i2c_adapter *adap;
+	struct dw_hdmi_i2c *i2c;
+	int ret;
+
+	i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
+	if (!i2c)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&i2c->lock);
+	init_completion(&i2c->cmp);
+
+	adap = &i2c->adap;
+	adap->class = I2C_CLASS_DDC;
+	adap->owner = THIS_MODULE;
+	adap->dev.parent = hdmi->dev;
+	adap->algo = &dw_hdmi_algorithm;
+	strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
+	i2c_set_adapdata(adap, hdmi);
+
+	ret = i2c_add_adapter(adap);
+	if (ret) {
+		dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
+		devm_kfree(hdmi->dev, i2c);
+		return ERR_PTR(ret);
+	}
+
+	hdmi->i2c = i2c;
+
+	dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
+
+	return adap;
+}
+
 static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts,
 			   unsigned int n)
 {
@@ -1512,16 +1720,40 @@ static const struct drm_bridge_funcs dw_
 	.mode_set = dw_hdmi_bridge_mode_set,
 };
 
+static irqreturn_t dw_hdmi_i2c_irq(struct dw_hdmi *hdmi)
+{
+	struct dw_hdmi_i2c *i2c = hdmi->i2c;
+	unsigned int stat;
+
+	stat = hdmi_readb(hdmi, HDMI_IH_I2CM_STAT0);
+	if (!stat)
+		return IRQ_NONE;
+
+	hdmi_writeb(hdmi, stat, HDMI_IH_I2CM_STAT0);
+
+	i2c->stat = stat;
+
+	complete(&i2c->cmp);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t dw_hdmi_hardirq(int irq, void *dev_id)
 {
 	struct dw_hdmi *hdmi = dev_id;
 	u8 intr_stat;
+	irqreturn_t ret = IRQ_NONE;
+
+	if (hdmi->i2c)
+		ret = dw_hdmi_i2c_irq(hdmi);
 
 	intr_stat = hdmi_readb(hdmi, HDMI_IH_PHY_STAT0);
-	if (intr_stat)
+	if (intr_stat) {
 		hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
+		return IRQ_WAKE_THREAD;
+	}
 
-	return intr_stat ? IRQ_WAKE_THREAD : IRQ_NONE;
+	return ret;
 }
 
 static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
@@ -1639,10 +1871,11 @@ int dw_hdmi_bind(struct device *dev, str
 	struct device_node *np = dev->of_node;
 	struct platform_device_info pdevinfo;
 	struct device_node *ddc_node;
-	struct dw_hdmi_audio_data audio;
 	struct dw_hdmi *hdmi;
 	int ret;
 	u32 val = 1;
+	u8 config0;
+	u8 config1;
 
 	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
 	if (!hdmi)
@@ -1681,7 +1914,7 @@ int dw_hdmi_bind(struct device *dev, str
 
 	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
 	if (ddc_node) {
-		hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+		hdmi->ddc = of_get_i2c_adapter_by_node(ddc_node);
 		of_node_put(ddc_node);
 		if (!hdmi->ddc) {
 			dev_dbg(hdmi->dev, "failed to read ddc node\n");
@@ -1693,20 +1926,22 @@ int dw_hdmi_bind(struct device *dev, str
 	}
 
 	hdmi->regs = devm_ioremap_resource(dev, iores);
-	if (IS_ERR(hdmi->regs))
-		return PTR_ERR(hdmi->regs);
+	if (IS_ERR(hdmi->regs)) {
+		ret = PTR_ERR(hdmi->regs);
+		goto err_res;
+	}
 
 	hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
 	if (IS_ERR(hdmi->isfr_clk)) {
 		ret = PTR_ERR(hdmi->isfr_clk);
 		dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
-		return ret;
+		goto err_res;
 	}
 
 	ret = clk_prepare_enable(hdmi->isfr_clk);
 	if (ret) {
 		dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
-		return ret;
+		goto err_res;
 	}
 
 	hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
@@ -1744,6 +1979,13 @@ int dw_hdmi_bind(struct device *dev, str
 	 */
 	hdmi_init_clk_regenerator(hdmi);
 
+	/* If DDC bus is not specified, try to register HDMI I2C bus */
+	if (!hdmi->ddc) {
+		hdmi->ddc = dw_hdmi_i2c_adapter(hdmi);
+		if (IS_ERR(hdmi->ddc))
+			hdmi->ddc = NULL;
+	}
+
 	/*
 	 * Configure registers related to HDMI interrupt
 	 * generation before registering IRQ.
@@ -1770,7 +2012,12 @@ int dw_hdmi_bind(struct device *dev, str
 	pdevinfo.parent = dev;
 	pdevinfo.id = PLATFORM_DEVID_AUTO;
 
-	if (hdmi_readb(hdmi, HDMI_CONFIG1_ID) & HDMI_CONFIG1_AHB) {
+	config0 = hdmi_readb(hdmi, HDMI_CONFIG0_ID);
+	config1 = hdmi_readb(hdmi, HDMI_CONFIG1_ID);
+
+	if (config1 & HDMI_CONFIG1_AHB) {
+		struct dw_hdmi_audio_data audio;
+
 		audio.phys = iores->start;
 		audio.base = hdmi->regs;
 		audio.irq = irq;
@@ -1782,16 +2029,39 @@ int dw_hdmi_bind(struct device *dev, str
 		pdevinfo.size_data = sizeof(audio);
 		pdevinfo.dma_mask = DMA_BIT_MASK(32);
 		hdmi->audio = platform_device_register_full(&pdevinfo);
+	} else if (config0 & HDMI_CONFIG0_I2S) {
+		struct dw_hdmi_i2s_audio_data audio;
+
+		audio.hdmi	= hdmi;
+		audio.write	= hdmi_writeb;
+		audio.read	= hdmi_readb;
+
+		pdevinfo.name = "dw-hdmi-i2s-audio";
+		pdevinfo.data = &audio;
+		pdevinfo.size_data = sizeof(audio);
+		pdevinfo.dma_mask = DMA_BIT_MASK(32);
+		hdmi->audio = platform_device_register_full(&pdevinfo);
 	}
 
+	/* Reset HDMI DDC I2C master controller and mute I2CM interrupts */
+	if (hdmi->i2c)
+		dw_hdmi_i2c_init(hdmi);
+
 	dev_set_drvdata(dev, hdmi);
 
 	return 0;
 
 err_iahb:
+	if (hdmi->i2c) {
+		i2c_del_adapter(&hdmi->i2c->adap);
+		hdmi->ddc = NULL;
+	}
+
 	clk_disable_unprepare(hdmi->iahb_clk);
 err_isfr:
 	clk_disable_unprepare(hdmi->isfr_clk);
+err_res:
+	i2c_put_adapter(hdmi->ddc);
 
 	return ret;
 }
@@ -1809,13 +2079,18 @@ void dw_hdmi_unbind(struct device *dev,
 
 	clk_disable_unprepare(hdmi->iahb_clk);
 	clk_disable_unprepare(hdmi->isfr_clk);
-	i2c_put_adapter(hdmi->ddc);
+
+	if (hdmi->i2c)
+		i2c_del_adapter(&hdmi->i2c->adap);
+	else
+		i2c_put_adapter(hdmi->ddc);
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
+MODULE_AUTHOR("Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com>");
 MODULE_DESCRIPTION("DW HDMI transmitter driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:dw-hdmi");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi.h	2017-02-12 16:03:20.000000000 -0500
@@ -545,6 +545,9 @@
 #define HDMI_I2CM_FS_SCL_LCNT_0_ADDR            0x7E12
 
 enum {
+/* CONFIG0_ID field values */
+	HDMI_CONFIG0_I2S = 0x10,
+
 /* CONFIG1_ID field values */
 	HDMI_CONFIG1_AHB = 0x01,
 
@@ -566,6 +569,10 @@ enum {
 	HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
 	HDMI_IH_PHY_STAT0_HPD = 0x1,
 
+/* IH_I2CM_STAT0 and IH_MUTE_I2CM_STAT0 field values */
+	HDMI_IH_I2CM_STAT0_DONE = 0x2,
+	HDMI_IH_I2CM_STAT0_ERROR = 0x1,
+
 /* IH_MUTE_I2CMPHY_STAT0 field values */
 	HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
 	HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
@@ -887,6 +894,17 @@ enum {
 	HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
 	HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
 
+/* AUD_CONF0 field values */
+	HDMI_AUD_CONF0_SW_RESET = 0x80,
+	HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F,
+
+/* AUD_CONF1 field values */
+	HDMI_AUD_CONF1_MODE_I2S = 0x00,
+	HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02,
+	HDMI_AUD_CONF1_MODE_LEFT_J = 0x04,
+	HDMI_AUD_CONF1_WIDTH_16 = 0x10,
+	HDMI_AUD_CONF1_WIDTH_24 = 0x18,
+
 /* AUD_CTS3 field values */
 	HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
 	HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
@@ -901,6 +919,12 @@ enum {
 	HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
 	HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
 
+/* HDMI_AUD_INPUTCLKFS field values */
+	HDMI_AUD_INPUTCLKFS_128FS = 0,
+	HDMI_AUD_INPUTCLKFS_256FS = 1,
+	HDMI_AUD_INPUTCLKFS_512FS = 2,
+	HDMI_AUD_INPUTCLKFS_64FS = 4,
+
 /* AHB_DMA_CONF0 field values */
 	HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
 	HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
@@ -1032,6 +1056,21 @@ enum {
 	HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
 	HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
 	HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
+
+/* I2CM_OPERATION field values */
+	HDMI_I2CM_OPERATION_WRITE = 0x10,
+	HDMI_I2CM_OPERATION_READ_EXT = 0x2,
+	HDMI_I2CM_OPERATION_READ = 0x1,
+
+/* I2CM_INT field values */
+	HDMI_I2CM_INT_DONE_POL = 0x8,
+	HDMI_I2CM_INT_DONE_MASK = 0x4,
+
+/* I2CM_CTLINT field values */
+	HDMI_I2CM_CTLINT_NAC_POL = 0x80,
+	HDMI_I2CM_CTLINT_NAC_MASK = 0x40,
+	HDMI_I2CM_CTLINT_ARB_POL = 0x8,
+	HDMI_I2CM_CTLINT_ARB_MASK = 0x4,
 };
 
 #endif /* __DW_HDMI_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/dw-hdmi-i2s-audio.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,141 @@
+/*
+ * dw-hdmi-i2s-audio.c
+ *
+ * Copyright (c) 2016 Kuninori Morimoto <kuninori.morimoto.gx@renesas.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 <drm/bridge/dw_hdmi.h>
+
+#include <sound/hdmi-codec.h>
+
+#include "dw-hdmi.h"
+#include "dw-hdmi-audio.h"
+
+#define DRIVER_NAME "dw-hdmi-i2s-audio"
+
+static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio,
+			      u8 val, int offset)
+{
+	struct dw_hdmi *hdmi = audio->hdmi;
+
+	audio->write(hdmi, val, offset);
+}
+
+static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset)
+{
+	struct dw_hdmi *hdmi = audio->hdmi;
+
+	return audio->read(hdmi, offset);
+}
+
+static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
+				 struct hdmi_codec_daifmt *fmt,
+				 struct hdmi_codec_params *hparms)
+{
+	struct dw_hdmi_i2s_audio_data *audio = data;
+	struct dw_hdmi *hdmi = audio->hdmi;
+	u8 conf0 = 0;
+	u8 conf1 = 0;
+	u8 inputclkfs = 0;
+
+	/* it cares I2S only */
+	if ((fmt->fmt != HDMI_I2S) ||
+	    (fmt->bit_clk_master | fmt->frame_clk_master)) {
+		dev_err(dev, "unsupported format/settings\n");
+		return -EINVAL;
+	}
+
+	inputclkfs	= HDMI_AUD_INPUTCLKFS_64FS;
+	conf0		= HDMI_AUD_CONF0_I2S_ALL_ENABLE;
+
+	switch (hparms->sample_width) {
+	case 16:
+		conf1 = HDMI_AUD_CONF1_WIDTH_16;
+		break;
+	case 24:
+	case 32:
+		conf1 = HDMI_AUD_CONF1_WIDTH_24;
+		break;
+	}
+
+	dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate);
+
+	hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS);
+	hdmi_write(audio, conf0, HDMI_AUD_CONF0);
+	hdmi_write(audio, conf1, HDMI_AUD_CONF1);
+
+	dw_hdmi_audio_enable(hdmi);
+
+	return 0;
+}
+
+static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data)
+{
+	struct dw_hdmi_i2s_audio_data *audio = data;
+	struct dw_hdmi *hdmi = audio->hdmi;
+
+	dw_hdmi_audio_disable(hdmi);
+
+	hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0);
+}
+
+static struct hdmi_codec_ops dw_hdmi_i2s_ops = {
+	.hw_params	= dw_hdmi_i2s_hw_params,
+	.audio_shutdown	= dw_hdmi_i2s_audio_shutdown,
+};
+
+static int snd_dw_hdmi_probe(struct platform_device *pdev)
+{
+	struct dw_hdmi_i2s_audio_data *audio = pdev->dev.platform_data;
+	struct platform_device_info pdevinfo;
+	struct hdmi_codec_pdata pdata;
+	struct platform_device *platform;
+
+	pdata.ops		= &dw_hdmi_i2s_ops;
+	pdata.i2s		= 1;
+	pdata.max_i2s_channels	= 6;
+	pdata.data		= audio;
+
+	memset(&pdevinfo, 0, sizeof(pdevinfo));
+	pdevinfo.parent		= pdev->dev.parent;
+	pdevinfo.id		= PLATFORM_DEVID_AUTO;
+	pdevinfo.name		= HDMI_CODEC_DRV_NAME;
+	pdevinfo.data		= &pdata;
+	pdevinfo.size_data	= sizeof(pdata);
+	pdevinfo.dma_mask	= DMA_BIT_MASK(32);
+
+	platform = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(platform))
+		return PTR_ERR(platform);
+
+	dev_set_drvdata(&pdev->dev, platform);
+
+	return 0;
+}
+
+static int snd_dw_hdmi_remove(struct platform_device *pdev)
+{
+	struct platform_device *platform = dev_get_drvdata(&pdev->dev);
+
+	platform_device_unregister(platform);
+
+	return 0;
+}
+
+static struct platform_driver snd_dw_hdmi_driver = {
+	.probe	= snd_dw_hdmi_probe,
+	.remove	= snd_dw_hdmi_remove,
+	.driver	= {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+module_platform_driver(snd_dw_hdmi_driver);
+
+MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
+MODULE_DESCRIPTION("Synopsis Designware HDMI I2S ALSA SoC interface");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,15 @@ config DRM_DW_HDMI_AHB_AUDIO
 	  Designware HDMI block.  This is used in conjunction with
 	  the i.MX6 HDMI driver.
 
+config DRM_DW_HDMI_I2S_AUDIO
+	tristate "Synopsis Designware I2S Audio interface"
+	depends on SND_SOC
+	depends on DRM_DW_HDMI
+	select SND_SOC_HDMI_CODEC
+	help
+	  Support the I2S Audio interface which is part of the Synopsis
+	  Designware HDMI block.
+
 config DRM_NXP_PTN3460
 	tristate "NXP PTN3460 DP/LVDS bridge"
 	depends on OF
@@ -57,6 +66,13 @@ config DRM_PARADE_PS8622
 	---help---
 	  Parade eDP-LVDS bridge chip driver.
 
+config DRM_SIL_SII8620
+	tristate "Silicon Image SII8620 HDMI/MHL bridge"
+	depends on OF
+	select DRM_KMS_HELPER
+	help
+	  Silicon Image SII8620 HDMI/MHL bridge chip driver.
+
 config DRM_SII902X
 	tristate "Silicon Image sii902x RGB/HDMI bridge"
 	depends on OF
@@ -74,6 +90,13 @@ config DRM_TOSHIBA_TC358767
 	---help---
 	  Toshiba TC358767 eDP bridge chip driver.
 
+config DRM_TI_TFP410
+	tristate "TI TFP410 DVI/HDMI bridge"
+	depends on OF
+	select DRM_KMS_HELPER
+	---help---
+	  Texas Instruments TFP410 DVI/HDMI Transmitter driver
+
 source "drivers/gpu/drm/bridge/analogix/Kconfig"
 
 source "drivers/gpu/drm/bridge/adv7511/Kconfig"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -4,9 +4,12 @@ obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += an
 obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o
 obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
 obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
+obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
 obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
 obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
+obj-$(CONFIG_DRM_SIL_SII8620) += sil-sii8620.o
 obj-$(CONFIG_DRM_SII902X) += sii902x.o
 obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
 obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
 obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
+obj-$(CONFIG_DRM_TI_TFP410) += ti-tfp410.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/nxp-ptn3460.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/nxp-ptn3460.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/nxp-ptn3460.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/nxp-ptn3460.c	2017-02-12 16:03:20.000000000 -0500
@@ -239,16 +239,9 @@ static const struct drm_connector_helper
 	.get_modes = ptn3460_get_modes,
 };
 
-static enum drm_connector_status ptn3460_detect(struct drm_connector *connector,
-		bool force)
-{
-	return connector_status_connected;
-}
-
 static const struct drm_connector_funcs ptn3460_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = ptn3460_detect,
 	.destroy = drm_connector_cleanup,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/parade-ps8622.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/parade-ps8622.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/parade-ps8622.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/parade-ps8622.c	2017-02-12 16:03:20.000000000 -0500
@@ -477,16 +477,9 @@ static const struct drm_connector_helper
 	.get_modes = ps8622_get_modes,
 };
 
-static enum drm_connector_status ps8622_detect(struct drm_connector *connector,
-								bool force)
-{
-	return connector_status_connected;
-}
-
 static const struct drm_connector_funcs ps8622_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = ps8622_detect,
 	.destroy = drm_connector_cleanup,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/sil-sii8620.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/sil-sii8620.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/sil-sii8620.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/sil-sii8620.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1564 @@
+/*
+ * Silicon Image SiI8620 HDMI/MHL bridge driver
+ *
+ * Copyright (C) 2015, Samsung Electronics Co., Ltd.
+ * Andrzej Hajda <a.hajda@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 <drm/bridge/mhl.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_edid.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include "sil-sii8620.h"
+
+#define VAL_RX_HDMI_CTRL2_DEFVAL	VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
+
+enum sii8620_mode {
+	CM_DISCONNECTED,
+	CM_DISCOVERY,
+	CM_MHL1,
+	CM_MHL3,
+	CM_ECBUS_S
+};
+
+enum sii8620_sink_type {
+	SINK_NONE,
+	SINK_HDMI,
+	SINK_DVI
+};
+
+enum sii8620_mt_state {
+	MT_STATE_READY,
+	MT_STATE_BUSY,
+	MT_STATE_DONE
+};
+
+struct sii8620 {
+	struct drm_bridge bridge;
+	struct device *dev;
+	struct clk *clk_xtal;
+	struct gpio_desc *gpio_reset;
+	struct gpio_desc *gpio_int;
+	struct regulator_bulk_data supplies[2];
+	struct mutex lock; /* context lock, protects fields below */
+	int error;
+	enum sii8620_mode mode;
+	enum sii8620_sink_type sink_type;
+	u8 cbus_status;
+	u8 stat[MHL_DST_SIZE];
+	u8 xstat[MHL_XDS_SIZE];
+	u8 devcap[MHL_DCAP_SIZE];
+	u8 xdevcap[MHL_XDC_SIZE];
+	u8 avif[19];
+	struct edid *edid;
+	unsigned int gen2_write_burst:1;
+	enum sii8620_mt_state mt_state;
+	struct list_head mt_queue;
+};
+
+struct sii8620_mt_msg;
+
+typedef void (*sii8620_mt_msg_cb)(struct sii8620 *ctx,
+				  struct sii8620_mt_msg *msg);
+
+struct sii8620_mt_msg {
+	struct list_head node;
+	u8 reg[4];
+	u8 ret;
+	sii8620_mt_msg_cb send;
+	sii8620_mt_msg_cb recv;
+};
+
+static const u8 sii8620_i2c_page[] = {
+	0x39, /* Main System */
+	0x3d, /* TDM and HSIC */
+	0x49, /* TMDS Receiver, MHL EDID */
+	0x4d, /* eMSC, HDCP, HSIC */
+	0x5d, /* MHL Spec */
+	0x64, /* MHL CBUS */
+	0x59, /* Hardware TPI (Transmitter Programming Interface) */
+	0x61, /* eCBUS-S, eCBUS-D */
+};
+
+static void sii8620_fetch_edid(struct sii8620 *ctx);
+static void sii8620_set_upstream_edid(struct sii8620 *ctx);
+static void sii8620_enable_hpd(struct sii8620 *ctx);
+static void sii8620_mhl_disconnected(struct sii8620 *ctx);
+
+static int sii8620_clear_error(struct sii8620 *ctx)
+{
+	int ret = ctx->error;
+
+	ctx->error = 0;
+	return ret;
+}
+
+static void sii8620_read_buf(struct sii8620 *ctx, u16 addr, u8 *buf, int len)
+{
+	struct device *dev = ctx->dev;
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 data = addr;
+	struct i2c_msg msg[] = {
+		{
+			.addr = sii8620_i2c_page[addr >> 8],
+			.flags = client->flags,
+			.len = 1,
+			.buf = &data
+		},
+		{
+			.addr = sii8620_i2c_page[addr >> 8],
+			.flags = client->flags | I2C_M_RD,
+			.len = len,
+			.buf = buf
+		},
+	};
+	int ret;
+
+	if (ctx->error)
+		return;
+
+	ret = i2c_transfer(client->adapter, msg, 2);
+	dev_dbg(dev, "read at %04x: %*ph, %d\n", addr, len, buf, ret);
+
+	if (ret != 2) {
+		dev_err(dev, "Read at %#06x of %d bytes failed with code %d.\n",
+			addr, len, ret);
+		ctx->error = ret < 0 ? ret : -EIO;
+	}
+}
+
+static u8 sii8620_readb(struct sii8620 *ctx, u16 addr)
+{
+	u8 ret;
+
+	sii8620_read_buf(ctx, addr, &ret, 1);
+	return ret;
+}
+
+static void sii8620_write_buf(struct sii8620 *ctx, u16 addr, const u8 *buf,
+			      int len)
+{
+	struct device *dev = ctx->dev;
+	struct i2c_client *client = to_i2c_client(dev);
+	u8 data[2];
+	struct i2c_msg msg = {
+		.addr = sii8620_i2c_page[addr >> 8],
+		.flags = client->flags,
+		.len = len + 1,
+	};
+	int ret;
+
+	if (ctx->error)
+		return;
+
+	if (len > 1) {
+		msg.buf = kmalloc(len + 1, GFP_KERNEL);
+		if (!msg.buf) {
+			ctx->error = -ENOMEM;
+			return;
+		}
+		memcpy(msg.buf + 1, buf, len);
+	} else {
+		msg.buf = data;
+		msg.buf[1] = *buf;
+	}
+
+	msg.buf[0] = addr;
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	dev_dbg(dev, "write at %04x: %*ph, %d\n", addr, len, buf, ret);
+
+	if (ret != 1) {
+		dev_err(dev, "Write at %#06x of %*ph failed with code %d.\n",
+			addr, len, buf, ret);
+		ctx->error = ret ?: -EIO;
+	}
+
+	if (len > 1)
+		kfree(msg.buf);
+}
+
+#define sii8620_write(ctx, addr, arr...) \
+({\
+	u8 d[] = { arr }; \
+	sii8620_write_buf(ctx, addr, d, ARRAY_SIZE(d)); \
+})
+
+static void __sii8620_write_seq(struct sii8620 *ctx, const u16 *seq, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i += 2)
+		sii8620_write(ctx, seq[i], seq[i + 1]);
+}
+
+#define sii8620_write_seq(ctx, seq...) \
+({\
+	const u16 d[] = { seq }; \
+	__sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
+})
+
+#define sii8620_write_seq_static(ctx, seq...) \
+({\
+	static const u16 d[] = { seq }; \
+	__sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
+})
+
+static void sii8620_setbits(struct sii8620 *ctx, u16 addr, u8 mask, u8 val)
+{
+	val = (val & mask) | (sii8620_readb(ctx, addr) & ~mask);
+	sii8620_write(ctx, addr, val);
+}
+
+static void sii8620_mt_cleanup(struct sii8620 *ctx)
+{
+	struct sii8620_mt_msg *msg, *n;
+
+	list_for_each_entry_safe(msg, n, &ctx->mt_queue, node) {
+		list_del(&msg->node);
+		kfree(msg);
+	}
+	ctx->mt_state = MT_STATE_READY;
+}
+
+static void sii8620_mt_work(struct sii8620 *ctx)
+{
+	struct sii8620_mt_msg *msg;
+
+	if (ctx->error)
+		return;
+	if (ctx->mt_state == MT_STATE_BUSY || list_empty(&ctx->mt_queue))
+		return;
+
+	if (ctx->mt_state == MT_STATE_DONE) {
+		ctx->mt_state = MT_STATE_READY;
+		msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg,
+				       node);
+		if (msg->recv)
+			msg->recv(ctx, msg);
+		list_del(&msg->node);
+		kfree(msg);
+	}
+
+	if (ctx->mt_state != MT_STATE_READY || list_empty(&ctx->mt_queue))
+		return;
+
+	ctx->mt_state = MT_STATE_BUSY;
+	msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
+	if (msg->send)
+		msg->send(ctx, msg);
+}
+
+static void sii8620_mt_msc_cmd_send(struct sii8620 *ctx,
+				    struct sii8620_mt_msg *msg)
+{
+	switch (msg->reg[0]) {
+	case MHL_WRITE_STAT:
+	case MHL_SET_INT:
+		sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg + 1, 2);
+		sii8620_write(ctx, REG_MSC_COMMAND_START,
+			      BIT_MSC_COMMAND_START_WRITE_STAT);
+		break;
+	case MHL_MSC_MSG:
+		sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg, 3);
+		sii8620_write(ctx, REG_MSC_COMMAND_START,
+			      BIT_MSC_COMMAND_START_MSC_MSG);
+		break;
+	default:
+		dev_err(ctx->dev, "%s: command %#x not supported\n", __func__,
+			msg->reg[0]);
+	}
+}
+
+static struct sii8620_mt_msg *sii8620_mt_msg_new(struct sii8620 *ctx)
+{
+	struct sii8620_mt_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
+
+	if (!msg)
+		ctx->error = -ENOMEM;
+	else
+		list_add_tail(&msg->node, &ctx->mt_queue);
+
+	return msg;
+}
+
+static void sii8620_mt_msc_cmd(struct sii8620 *ctx, u8 cmd, u8 arg1, u8 arg2)
+{
+	struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
+
+	if (!msg)
+		return;
+
+	msg->reg[0] = cmd;
+	msg->reg[1] = arg1;
+	msg->reg[2] = arg2;
+	msg->send = sii8620_mt_msc_cmd_send;
+}
+
+static void sii8620_mt_write_stat(struct sii8620 *ctx, u8 reg, u8 val)
+{
+	sii8620_mt_msc_cmd(ctx, MHL_WRITE_STAT, reg, val);
+}
+
+static inline void sii8620_mt_set_int(struct sii8620 *ctx, u8 irq, u8 mask)
+{
+	sii8620_mt_msc_cmd(ctx, MHL_SET_INT, irq, mask);
+}
+
+static void sii8620_mt_msc_msg(struct sii8620 *ctx, u8 cmd, u8 data)
+{
+	sii8620_mt_msc_cmd(ctx, MHL_MSC_MSG, cmd, data);
+}
+
+static void sii8620_mt_rap(struct sii8620 *ctx, u8 code)
+{
+	sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RAP, code);
+}
+
+static void sii8620_mt_read_devcap_send(struct sii8620 *ctx,
+					struct sii8620_mt_msg *msg)
+{
+	u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP
+			| BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+			| BIT_EDID_CTRL_EDID_MODE_EN;
+
+	if (msg->reg[0] == MHL_READ_XDEVCAP)
+		ctrl |= BIT_EDID_CTRL_XDEVCAP_EN;
+
+	sii8620_write_seq(ctx,
+		REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE,
+		REG_EDID_CTRL, ctrl,
+		REG_TPI_CBUS_START, BIT_TPI_CBUS_START_GET_DEVCAP_START
+	);
+}
+
+/* copy src to dst and set changed bits in src */
+static void sii8620_update_array(u8 *dst, u8 *src, int count)
+{
+	while (--count >= 0) {
+		*src ^= *dst;
+		*dst++ ^= *src++;
+	}
+}
+
+static void sii8620_mr_devcap(struct sii8620 *ctx)
+{
+	static const char * const sink_str[] = {
+		[SINK_NONE] = "NONE",
+		[SINK_HDMI] = "HDMI",
+		[SINK_DVI] = "DVI"
+	};
+
+	u8 dcap[MHL_DCAP_SIZE];
+	char sink_name[20];
+	struct device *dev = ctx->dev;
+
+	sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, dcap, MHL_DCAP_SIZE);
+	if (ctx->error < 0)
+		return;
+
+	dev_info(dev, "dcap: %*ph\n", MHL_DCAP_SIZE, dcap);
+	dev_info(dev, "detected dongle MHL %d.%d, ChipID %02x%02x:%02x%02x\n",
+		 dcap[MHL_DCAP_MHL_VERSION] / 16,
+		 dcap[MHL_DCAP_MHL_VERSION] % 16, dcap[MHL_DCAP_ADOPTER_ID_H],
+		 dcap[MHL_DCAP_ADOPTER_ID_L], dcap[MHL_DCAP_DEVICE_ID_H],
+		 dcap[MHL_DCAP_DEVICE_ID_L]);
+	sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE);
+
+	if (!(dcap[MHL_DCAP_CAT] & MHL_DCAP_CAT_SINK))
+		return;
+
+	sii8620_fetch_edid(ctx);
+	if (!ctx->edid) {
+		dev_err(ctx->dev, "Cannot fetch EDID\n");
+		sii8620_mhl_disconnected(ctx);
+		return;
+	}
+
+	if (drm_detect_hdmi_monitor(ctx->edid))
+		ctx->sink_type = SINK_HDMI;
+	else
+		ctx->sink_type = SINK_DVI;
+
+	drm_edid_get_monitor_name(ctx->edid, sink_name, ARRAY_SIZE(sink_name));
+
+	dev_info(dev, "detected sink(type: %s): %s\n",
+		 sink_str[ctx->sink_type], sink_name);
+	sii8620_set_upstream_edid(ctx);
+	sii8620_enable_hpd(ctx);
+}
+
+static void sii8620_mr_xdevcap(struct sii8620 *ctx)
+{
+	sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, ctx->xdevcap,
+			 MHL_XDC_SIZE);
+
+	sii8620_mt_write_stat(ctx, MHL_XDS_REG(CURR_ECBUS_MODE),
+			      MHL_XDS_ECBUS_S | MHL_XDS_SLOT_MODE_8BIT);
+	sii8620_mt_rap(ctx, MHL_RAP_CBUS_MODE_UP);
+}
+
+static void sii8620_mt_read_devcap_recv(struct sii8620 *ctx,
+					struct sii8620_mt_msg *msg)
+{
+	u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP
+		| BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+		| BIT_EDID_CTRL_EDID_MODE_EN;
+
+	if (msg->reg[0] == MHL_READ_XDEVCAP)
+		ctrl |= BIT_EDID_CTRL_XDEVCAP_EN;
+
+	sii8620_write_seq(ctx,
+		REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE | BIT_INTR9_EDID_DONE
+			| BIT_INTR9_EDID_ERROR,
+		REG_EDID_CTRL, ctrl,
+		REG_EDID_FIFO_ADDR, 0
+	);
+
+	if (msg->reg[0] == MHL_READ_XDEVCAP)
+		sii8620_mr_xdevcap(ctx);
+	else
+		sii8620_mr_devcap(ctx);
+}
+
+static void sii8620_mt_read_devcap(struct sii8620 *ctx, bool xdevcap)
+{
+	struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
+
+	if (!msg)
+		return;
+
+	msg->reg[0] = xdevcap ? MHL_READ_XDEVCAP : MHL_READ_DEVCAP;
+	msg->send = sii8620_mt_read_devcap_send;
+	msg->recv = sii8620_mt_read_devcap_recv;
+}
+
+static void sii8620_fetch_edid(struct sii8620 *ctx)
+{
+	u8 lm_ddc, ddc_cmd, int3, cbus;
+	int fetched, i;
+	int edid_len = EDID_LENGTH;
+	u8 *edid;
+
+	sii8620_readb(ctx, REG_CBUS_STATUS);
+	lm_ddc = sii8620_readb(ctx, REG_LM_DDC);
+	ddc_cmd = sii8620_readb(ctx, REG_DDC_CMD);
+
+	sii8620_write_seq(ctx,
+		REG_INTR9_MASK, 0,
+		REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO,
+		REG_HDCP2X_POLL_CS, 0x71,
+		REG_HDCP2X_CTRL_0, BIT_HDCP2X_CTRL_0_HDCP2X_HDCPTX,
+		REG_LM_DDC, lm_ddc | BIT_LM_DDC_SW_TPI_EN_DISABLED,
+	);
+
+	for (i = 0; i < 256; ++i) {
+		u8 ddc_stat = sii8620_readb(ctx, REG_DDC_STATUS);
+
+		if (!(ddc_stat & BIT_DDC_STATUS_DDC_I2C_IN_PROG))
+			break;
+		sii8620_write(ctx, REG_DDC_STATUS,
+			      BIT_DDC_STATUS_DDC_FIFO_EMPTY);
+	}
+
+	sii8620_write(ctx, REG_DDC_ADDR, 0x50 << 1);
+
+	edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!edid) {
+		ctx->error = -ENOMEM;
+		return;
+	}
+
+#define FETCH_SIZE 16
+	for (fetched = 0; fetched < edid_len; fetched += FETCH_SIZE) {
+		sii8620_readb(ctx, REG_DDC_STATUS);
+		sii8620_write_seq(ctx,
+			REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_ABORT,
+			REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_CLEAR_FIFO,
+			REG_DDC_STATUS, BIT_DDC_STATUS_DDC_FIFO_EMPTY
+		);
+		sii8620_write_seq(ctx,
+			REG_DDC_SEGM, fetched >> 8,
+			REG_DDC_OFFSET, fetched & 0xff,
+			REG_DDC_DIN_CNT1, FETCH_SIZE,
+			REG_DDC_DIN_CNT2, 0,
+			REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK
+		);
+
+		do {
+			int3 = sii8620_readb(ctx, REG_INTR3);
+			cbus = sii8620_readb(ctx, REG_CBUS_STATUS);
+
+			if (int3 & BIT_DDC_CMD_DONE)
+				break;
+
+			if (!(cbus & BIT_CBUS_STATUS_CBUS_CONNECTED)) {
+				kfree(edid);
+				edid = NULL;
+				goto end;
+			}
+		} while (1);
+
+		sii8620_readb(ctx, REG_DDC_STATUS);
+		while (sii8620_readb(ctx, REG_DDC_DOUT_CNT) < FETCH_SIZE)
+			usleep_range(10, 20);
+
+		sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE);
+		if (fetched + FETCH_SIZE == EDID_LENGTH) {
+			u8 ext = ((struct edid *)edid)->extensions;
+
+			if (ext) {
+				u8 *new_edid;
+
+				edid_len += ext * EDID_LENGTH;
+				new_edid = krealloc(edid, edid_len, GFP_KERNEL);
+				if (!new_edid) {
+					kfree(edid);
+					ctx->error = -ENOMEM;
+					return;
+				}
+				edid = new_edid;
+			}
+		}
+
+		if (fetched + FETCH_SIZE == edid_len)
+			sii8620_write(ctx, REG_INTR3, int3);
+	}
+
+	sii8620_write(ctx, REG_LM_DDC, lm_ddc);
+
+end:
+	kfree(ctx->edid);
+	ctx->edid = (struct edid *)edid;
+}
+
+static void sii8620_set_upstream_edid(struct sii8620 *ctx)
+{
+	sii8620_setbits(ctx, REG_DPD, BIT_DPD_PDNRX12 | BIT_DPD_PDIDCK_N
+			| BIT_DPD_PD_MHL_CLK_N, 0xff);
+
+	sii8620_write_seq_static(ctx,
+		REG_RX_HDMI_CTRL3, 0x00,
+		REG_PKT_FILTER_0, 0xFF,
+		REG_PKT_FILTER_1, 0xFF,
+		REG_ALICE0_BW_I2C, 0x06
+	);
+
+	sii8620_setbits(ctx, REG_RX_HDMI_CLR_BUFFER,
+			BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_EN, 0xff);
+
+	sii8620_write_seq_static(ctx,
+		REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+			| BIT_EDID_CTRL_EDID_MODE_EN,
+		REG_EDID_FIFO_ADDR, 0,
+	);
+
+	sii8620_write_buf(ctx, REG_EDID_FIFO_WR_DATA, (u8 *)ctx->edid,
+			  (ctx->edid->extensions + 1) * EDID_LENGTH);
+
+	sii8620_write_seq_static(ctx,
+		REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID
+			| BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
+			| BIT_EDID_CTRL_EDID_MODE_EN,
+		REG_INTR5_MASK, BIT_INTR_SCDT_CHANGE,
+		REG_INTR9_MASK, 0
+	);
+}
+
+static void sii8620_xtal_set_rate(struct sii8620 *ctx)
+{
+	static const struct {
+		unsigned int rate;
+		u8 div;
+		u8 tp1;
+	} rates[] = {
+		{ 19200, 0x04, 0x53 },
+		{ 20000, 0x04, 0x62 },
+		{ 24000, 0x05, 0x75 },
+		{ 30000, 0x06, 0x92 },
+		{ 38400, 0x0c, 0xbc },
+	};
+	unsigned long rate = clk_get_rate(ctx->clk_xtal) / 1000;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rates) - 1; ++i)
+		if (rate <= rates[i].rate)
+			break;
+
+	if (rate != rates[i].rate)
+		dev_err(ctx->dev, "xtal clock rate(%lukHz) not supported, setting MHL for %ukHz.\n",
+			rate, rates[i].rate);
+
+	sii8620_write(ctx, REG_DIV_CTL_MAIN, rates[i].div);
+	sii8620_write(ctx, REG_HDCP2X_TP1, rates[i].tp1);
+}
+
+static int sii8620_hw_on(struct sii8620 *ctx)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+	if (ret)
+		return ret;
+	usleep_range(10000, 20000);
+	return clk_prepare_enable(ctx->clk_xtal);
+}
+
+static int sii8620_hw_off(struct sii8620 *ctx)
+{
+	clk_disable_unprepare(ctx->clk_xtal);
+	gpiod_set_value(ctx->gpio_reset, 1);
+	return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
+}
+
+static void sii8620_hw_reset(struct sii8620 *ctx)
+{
+	usleep_range(10000, 20000);
+	gpiod_set_value(ctx->gpio_reset, 0);
+	usleep_range(5000, 20000);
+	gpiod_set_value(ctx->gpio_reset, 1);
+	usleep_range(10000, 20000);
+	gpiod_set_value(ctx->gpio_reset, 0);
+	msleep(300);
+}
+
+static void sii8620_cbus_reset(struct sii8620 *ctx)
+{
+	sii8620_write_seq_static(ctx,
+		REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST
+			| BIT_PWD_SRST_CBUS_RST_SW_EN,
+		REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST_SW_EN
+	);
+}
+
+static void sii8620_set_auto_zone(struct sii8620 *ctx)
+{
+	if (ctx->mode != CM_MHL1) {
+		sii8620_write_seq_static(ctx,
+			REG_TX_ZONE_CTL1, 0x0,
+			REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+				| BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
+				| BIT_MHL_PLL_CTL0_ZONE_MASK_OE
+		);
+	} else {
+		sii8620_write_seq_static(ctx,
+			REG_TX_ZONE_CTL1, VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE,
+			REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+				| BIT_MHL_PLL_CTL0_ZONE_MASK_OE
+		);
+	}
+}
+
+static void sii8620_stop_video(struct sii8620 *ctx)
+{
+	u8 uninitialized_var(val);
+
+	sii8620_write_seq_static(ctx,
+		REG_TPI_INTR_EN, 0,
+		REG_HDCP2X_INTR0_MASK, 0,
+		REG_TPI_COPP_DATA2, 0,
+		REG_TPI_INTR_ST0, ~0,
+	);
+
+	switch (ctx->sink_type) {
+	case SINK_DVI:
+		val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN
+			| BIT_TPI_SC_TPI_AV_MUTE;
+		break;
+	case SINK_HDMI:
+		val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN
+			| BIT_TPI_SC_TPI_AV_MUTE
+			| BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI;
+		break;
+	default:
+		return;
+	}
+
+	sii8620_write(ctx, REG_TPI_SC, val);
+}
+
+static void sii8620_start_hdmi(struct sii8620 *ctx)
+{
+	sii8620_write_seq_static(ctx,
+		REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL
+			| BIT_RX_HDMI_CTRL2_USE_AV_MUTE,
+		REG_VID_OVRRD, BIT_VID_OVRRD_PP_AUTO_DISABLE
+			| BIT_VID_OVRRD_M1080P_OVRRD,
+		REG_VID_MODE, 0,
+		REG_MHL_TOP_CTL, 0x1,
+		REG_MHLTX_CTL6, 0xa0,
+		REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
+		REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL),
+	);
+
+	sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
+			      MHL_DST_LM_CLK_MODE_NORMAL |
+			      MHL_DST_LM_PATH_ENABLED);
+
+	sii8620_set_auto_zone(ctx);
+
+	sii8620_write(ctx, REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
+
+	sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif,
+			  ARRAY_SIZE(ctx->avif));
+
+	sii8620_write(ctx, REG_PKT_FILTER_0, 0xa1, 0x2);
+}
+
+static void sii8620_start_video(struct sii8620 *ctx)
+{
+	if (ctx->mode < CM_MHL3)
+		sii8620_stop_video(ctx);
+
+	switch (ctx->sink_type) {
+	case SINK_HDMI:
+		sii8620_start_hdmi(ctx);
+		break;
+	case SINK_DVI:
+	default:
+		break;
+	}
+}
+
+static void sii8620_disable_hpd(struct sii8620 *ctx)
+{
+	sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0);
+	sii8620_write_seq_static(ctx,
+		REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN,
+		REG_INTR8_MASK, 0
+	);
+}
+
+static void sii8620_enable_hpd(struct sii8620 *ctx)
+{
+	sii8620_setbits(ctx, REG_TMDS_CSTAT_P3,
+			BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS
+			| BIT_TMDS_CSTAT_P3_CLR_AVI, ~0);
+	sii8620_write_seq_static(ctx,
+		REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN
+			| BIT_HPD_CTRL_HPD_HIGH,
+	);
+}
+
+static void sii8620_enable_gen2_write_burst(struct sii8620 *ctx)
+{
+	if (ctx->gen2_write_burst)
+		return;
+
+	sii8620_write_seq_static(ctx,
+		REG_MDT_RCV_TIMEOUT, 100,
+		REG_MDT_RCV_CTRL, BIT_MDT_RCV_CTRL_MDT_RCV_EN
+	);
+	ctx->gen2_write_burst = 1;
+}
+
+static void sii8620_disable_gen2_write_burst(struct sii8620 *ctx)
+{
+	if (!ctx->gen2_write_burst)
+		return;
+
+	sii8620_write_seq_static(ctx,
+		REG_MDT_XMIT_CTRL, 0,
+		REG_MDT_RCV_CTRL, 0
+	);
+	ctx->gen2_write_burst = 0;
+}
+
+static void sii8620_start_gen2_write_burst(struct sii8620 *ctx)
+{
+	sii8620_write_seq_static(ctx,
+		REG_MDT_INT_1_MASK, BIT_MDT_RCV_TIMEOUT
+			| BIT_MDT_RCV_SM_ABORT_PKT_RCVD | BIT_MDT_RCV_SM_ERROR
+			| BIT_MDT_XMIT_TIMEOUT | BIT_MDT_XMIT_SM_ABORT_PKT_RCVD
+			| BIT_MDT_XMIT_SM_ERROR,
+		REG_MDT_INT_0_MASK, BIT_MDT_XFIFO_EMPTY
+			| BIT_MDT_IDLE_AFTER_HAWB_DISABLE
+			| BIT_MDT_RFIFO_DATA_RDY
+	);
+	sii8620_enable_gen2_write_burst(ctx);
+}
+
+static void sii8620_mhl_discover(struct sii8620 *ctx)
+{
+	sii8620_write_seq_static(ctx,
+		REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+			| BIT_DISC_CTRL9_DISC_PULSE_PROCEED,
+		REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_5K, VAL_PUP_20K),
+		REG_CBUS_DISC_INTR0_MASK, BIT_MHL3_EST_INT
+			| BIT_MHL_EST_INT
+			| BIT_NOT_MHL_EST_INT
+			| BIT_CBUS_MHL3_DISCON_INT
+			| BIT_CBUS_MHL12_DISCON_INT
+			| BIT_RGND_READY_INT,
+		REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+			| BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
+			| BIT_MHL_PLL_CTL0_ZONE_MASK_OE,
+		REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE
+			| BIT_MHL_DP_CTL0_TX_OE_OVR,
+		REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
+		REG_MHL_DP_CTL1, 0xA2,
+		REG_MHL_DP_CTL2, 0x03,
+		REG_MHL_DP_CTL3, 0x35,
+		REG_MHL_DP_CTL5, 0x02,
+		REG_MHL_DP_CTL6, 0x02,
+		REG_MHL_DP_CTL7, 0x03,
+		REG_COC_CTLC, 0xFF,
+		REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12
+			| BIT_DPD_OSC_EN | BIT_DPD_PWRON_HSIC,
+		REG_COC_INTR_MASK, BIT_COC_PLL_LOCK_STATUS_CHANGE
+			| BIT_COC_CALIBRATION_DONE,
+		REG_CBUS_INT_1_MASK, BIT_CBUS_MSC_ABORT_RCVD
+			| BIT_CBUS_CMD_ABORT,
+		REG_CBUS_INT_0_MASK, BIT_CBUS_MSC_MT_DONE
+			| BIT_CBUS_HPD_CHG
+			| BIT_CBUS_MSC_MR_WRITE_STAT
+			| BIT_CBUS_MSC_MR_MSC_MSG
+			| BIT_CBUS_MSC_MR_WRITE_BURST
+			| BIT_CBUS_MSC_MR_SET_INT
+			| BIT_CBUS_MSC_MT_DONE_NACK
+	);
+}
+
+static void sii8620_peer_specific_init(struct sii8620 *ctx)
+{
+	if (ctx->mode == CM_MHL3)
+		sii8620_write_seq_static(ctx,
+			REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD,
+			REG_EMSCINTRMASK1,
+				BIT_EMSCINTR1_EMSC_TRAINING_COMMA_ERR
+		);
+	else
+		sii8620_write_seq_static(ctx,
+			REG_HDCP2X_INTR0_MASK, 0x00,
+			REG_EMSCINTRMASK1, 0x00,
+			REG_HDCP2X_INTR0, 0xFF,
+			REG_INTR1, 0xFF,
+			REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD
+				| BIT_SYS_CTRL1_TX_CTRL_HDMI
+		);
+}
+
+#define SII8620_MHL_VERSION			0x32
+#define SII8620_SCRATCHPAD_SIZE			16
+#define SII8620_INT_STAT_SIZE			0x33
+
+static void sii8620_set_dev_cap(struct sii8620 *ctx)
+{
+	static const u8 devcap[MHL_DCAP_SIZE] = {
+		[MHL_DCAP_MHL_VERSION] = SII8620_MHL_VERSION,
+		[MHL_DCAP_CAT] = MHL_DCAP_CAT_SOURCE | MHL_DCAP_CAT_POWER,
+		[MHL_DCAP_ADOPTER_ID_H] = 0x01,
+		[MHL_DCAP_ADOPTER_ID_L] = 0x41,
+		[MHL_DCAP_VID_LINK_MODE] = MHL_DCAP_VID_LINK_RGB444
+			| MHL_DCAP_VID_LINK_PPIXEL
+			| MHL_DCAP_VID_LINK_16BPP,
+		[MHL_DCAP_AUD_LINK_MODE] = MHL_DCAP_AUD_LINK_2CH,
+		[MHL_DCAP_VIDEO_TYPE] = MHL_DCAP_VT_GRAPHICS,
+		[MHL_DCAP_LOG_DEV_MAP] = MHL_DCAP_LD_GUI,
+		[MHL_DCAP_BANDWIDTH] = 0x0f,
+		[MHL_DCAP_FEATURE_FLAG] = MHL_DCAP_FEATURE_RCP_SUPPORT
+			| MHL_DCAP_FEATURE_RAP_SUPPORT
+			| MHL_DCAP_FEATURE_SP_SUPPORT,
+		[MHL_DCAP_SCRATCHPAD_SIZE] = SII8620_SCRATCHPAD_SIZE,
+		[MHL_DCAP_INT_STAT_SIZE] = SII8620_INT_STAT_SIZE,
+	};
+	static const u8 xdcap[MHL_XDC_SIZE] = {
+		[MHL_XDC_ECBUS_SPEEDS] = MHL_XDC_ECBUS_S_075
+			| MHL_XDC_ECBUS_S_8BIT,
+		[MHL_XDC_TMDS_SPEEDS] = MHL_XDC_TMDS_150
+			| MHL_XDC_TMDS_300 | MHL_XDC_TMDS_600,
+		[MHL_XDC_ECBUS_ROLES] = MHL_XDC_DEV_HOST,
+		[MHL_XDC_LOG_DEV_MAPX] = MHL_XDC_LD_PHONE,
+	};
+
+	sii8620_write_buf(ctx, REG_MHL_DEVCAP_0, devcap, ARRAY_SIZE(devcap));
+	sii8620_write_buf(ctx, REG_MHL_EXTDEVCAP_0, xdcap, ARRAY_SIZE(xdcap));
+}
+
+static void sii8620_mhl_init(struct sii8620 *ctx)
+{
+	sii8620_write_seq_static(ctx,
+		REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
+		REG_CBUS_MSC_COMPAT_CTRL,
+			BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN,
+	);
+
+	sii8620_peer_specific_init(ctx);
+
+	sii8620_disable_hpd(ctx);
+
+	sii8620_write_seq_static(ctx,
+		REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO,
+		REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+			| BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
+		REG_TMDS0_CCTRL1, 0x90,
+		REG_TMDS_CLK_EN, 0x01,
+		REG_TMDS_CH_EN, 0x11,
+		REG_BGR_BIAS, 0x87,
+		REG_ALICE0_ZONE_CTRL, 0xE8,
+		REG_ALICE0_MODE_CTRL, 0x04,
+	);
+	sii8620_setbits(ctx, REG_LM_DDC, BIT_LM_DDC_SW_TPI_EN_DISABLED, 0);
+	sii8620_write_seq_static(ctx,
+		REG_TPI_HW_OPT3, 0x76,
+		REG_TMDS_CCTRL, BIT_TMDS_CCTRL_TMDS_OE,
+		REG_TPI_DTD_B2, 79,
+	);
+	sii8620_set_dev_cap(ctx);
+	sii8620_write_seq_static(ctx,
+		REG_MDT_XMIT_TIMEOUT, 100,
+		REG_MDT_XMIT_CTRL, 0x03,
+		REG_MDT_XFIFO_STAT, 0x00,
+		REG_MDT_RCV_TIMEOUT, 100,
+		REG_CBUS_LINK_CTRL_8, 0x1D,
+	);
+
+	sii8620_start_gen2_write_burst(ctx);
+	sii8620_write_seq_static(ctx,
+		REG_BIST_CTRL, 0x00,
+		REG_COC_CTL1, 0x10,
+		REG_COC_CTL2, 0x18,
+		REG_COC_CTLF, 0x07,
+		REG_COC_CTL11, 0xF8,
+		REG_COC_CTL17, 0x61,
+		REG_COC_CTL18, 0x46,
+		REG_COC_CTL19, 0x15,
+		REG_COC_CTL1A, 0x01,
+		REG_MHL_COC_CTL3, BIT_MHL_COC_CTL3_COC_AECHO_EN,
+		REG_MHL_COC_CTL4, 0x2D,
+		REG_MHL_COC_CTL5, 0xF9,
+		REG_MSC_HEARTBEAT_CTRL, 0x27,
+	);
+	sii8620_disable_gen2_write_burst(ctx);
+
+	/* currently MHL3 is not supported, so we force version to 0 */
+	sii8620_mt_write_stat(ctx, MHL_DST_REG(VERSION), 0);
+	sii8620_mt_write_stat(ctx, MHL_DST_REG(CONNECTED_RDY),
+			      MHL_DST_CONN_DCAP_RDY | MHL_DST_CONN_XDEVCAPP_SUPP
+			      | MHL_DST_CONN_POW_STAT);
+	sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE), MHL_INT_RC_DCAP_CHG);
+}
+
+static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode)
+{
+	if (ctx->mode == mode)
+		return;
+
+	ctx->mode = mode;
+
+	switch (mode) {
+	case CM_MHL1:
+		sii8620_write_seq_static(ctx,
+			REG_CBUS_MSC_COMPAT_CTRL, 0x02,
+			REG_M3_CTRL, VAL_M3_CTRL_MHL1_2_VALUE,
+			REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12
+				| BIT_DPD_OSC_EN,
+			REG_COC_INTR_MASK, 0
+		);
+		break;
+	case CM_MHL3:
+		sii8620_write_seq_static(ctx,
+			REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
+			REG_COC_CTL0, 0x40,
+			REG_MHL_COC_CTL1, 0x07
+		);
+		break;
+	case CM_DISCONNECTED:
+		break;
+	default:
+		dev_err(ctx->dev, "%s mode %d not supported\n", __func__, mode);
+		break;
+	}
+
+	sii8620_set_auto_zone(ctx);
+
+	if (mode != CM_MHL1)
+		return;
+
+	sii8620_write_seq_static(ctx,
+		REG_MHL_DP_CTL0, 0xBC,
+		REG_MHL_DP_CTL1, 0xBB,
+		REG_MHL_DP_CTL3, 0x48,
+		REG_MHL_DP_CTL5, 0x39,
+		REG_MHL_DP_CTL2, 0x2A,
+		REG_MHL_DP_CTL6, 0x2A,
+		REG_MHL_DP_CTL7, 0x08
+	);
+}
+
+static void sii8620_disconnect(struct sii8620 *ctx)
+{
+	sii8620_disable_gen2_write_burst(ctx);
+	sii8620_stop_video(ctx);
+	msleep(50);
+	sii8620_cbus_reset(ctx);
+	sii8620_set_mode(ctx, CM_DISCONNECTED);
+	sii8620_write_seq_static(ctx,
+		REG_COC_CTL0, 0x40,
+		REG_CBUS3_CNVT, 0x84,
+		REG_COC_CTL14, 0x00,
+		REG_COC_CTL0, 0x40,
+		REG_HRXCTRL3, 0x07,
+		REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
+			| BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
+			| BIT_MHL_PLL_CTL0_ZONE_MASK_OE,
+		REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE
+			| BIT_MHL_DP_CTL0_TX_OE_OVR,
+		REG_MHL_DP_CTL1, 0xBB,
+		REG_MHL_DP_CTL3, 0x48,
+		REG_MHL_DP_CTL5, 0x3F,
+		REG_MHL_DP_CTL2, 0x2F,
+		REG_MHL_DP_CTL6, 0x2A,
+		REG_MHL_DP_CTL7, 0x03
+	);
+	sii8620_disable_hpd(ctx);
+	sii8620_write_seq_static(ctx,
+		REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
+		REG_MHL_COC_CTL1, 0x07,
+		REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
+		REG_DISC_CTRL8, 0x00,
+		REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+			| BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
+		REG_INT_CTRL, 0x00,
+		REG_MSC_HEARTBEAT_CTRL, 0x27,
+		REG_DISC_CTRL1, 0x25,
+		REG_CBUS_DISC_INTR0, (u8)~BIT_RGND_READY_INT,
+		REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT,
+		REG_MDT_INT_1, 0xff,
+		REG_MDT_INT_1_MASK, 0x00,
+		REG_MDT_INT_0, 0xff,
+		REG_MDT_INT_0_MASK, 0x00,
+		REG_COC_INTR, 0xff,
+		REG_COC_INTR_MASK, 0x00,
+		REG_TRXINTH, 0xff,
+		REG_TRXINTMH, 0x00,
+		REG_CBUS_INT_0, 0xff,
+		REG_CBUS_INT_0_MASK, 0x00,
+		REG_CBUS_INT_1, 0xff,
+		REG_CBUS_INT_1_MASK, 0x00,
+		REG_EMSCINTR, 0xff,
+		REG_EMSCINTRMASK, 0x00,
+		REG_EMSCINTR1, 0xff,
+		REG_EMSCINTRMASK1, 0x00,
+		REG_INTR8, 0xff,
+		REG_INTR8_MASK, 0x00,
+		REG_TPI_INTR_ST0, 0xff,
+		REG_TPI_INTR_EN, 0x00,
+		REG_HDCP2X_INTR0, 0xff,
+		REG_HDCP2X_INTR0_MASK, 0x00,
+		REG_INTR9, 0xff,
+		REG_INTR9_MASK, 0x00,
+		REG_INTR3, 0xff,
+		REG_INTR3_MASK, 0x00,
+		REG_INTR5, 0xff,
+		REG_INTR5_MASK, 0x00,
+		REG_INTR2, 0xff,
+		REG_INTR2_MASK, 0x00,
+	);
+	memset(ctx->stat, 0, sizeof(ctx->stat));
+	memset(ctx->xstat, 0, sizeof(ctx->xstat));
+	memset(ctx->devcap, 0, sizeof(ctx->devcap));
+	memset(ctx->xdevcap, 0, sizeof(ctx->xdevcap));
+	ctx->cbus_status = 0;
+	ctx->sink_type = SINK_NONE;
+	kfree(ctx->edid);
+	ctx->edid = NULL;
+	sii8620_mt_cleanup(ctx);
+}
+
+static void sii8620_mhl_disconnected(struct sii8620 *ctx)
+{
+	sii8620_write_seq_static(ctx,
+		REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
+		REG_CBUS_MSC_COMPAT_CTRL,
+			BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN
+	);
+	sii8620_disconnect(ctx);
+}
+
+static void sii8620_irq_disc(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_CBUS_DISC_INTR0);
+
+	if (stat & VAL_CBUS_MHL_DISCON)
+		sii8620_mhl_disconnected(ctx);
+
+	if (stat & BIT_RGND_READY_INT) {
+		u8 stat2 = sii8620_readb(ctx, REG_DISC_STAT2);
+
+		if ((stat2 & MSK_DISC_STAT2_RGND) == VAL_RGND_1K) {
+			sii8620_mhl_discover(ctx);
+		} else {
+			sii8620_write_seq_static(ctx,
+				REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
+					| BIT_DISC_CTRL9_NOMHL_EST
+					| BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
+				REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT
+					| BIT_CBUS_MHL3_DISCON_INT
+					| BIT_CBUS_MHL12_DISCON_INT
+					| BIT_NOT_MHL_EST_INT
+			);
+		}
+	}
+	if (stat & BIT_MHL_EST_INT)
+		sii8620_mhl_init(ctx);
+
+	sii8620_write(ctx, REG_CBUS_DISC_INTR0, stat);
+}
+
+static void sii8620_irq_g2wb(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_MDT_INT_0);
+
+	if (stat & BIT_MDT_IDLE_AFTER_HAWB_DISABLE)
+		dev_dbg(ctx->dev, "HAWB idle\n");
+
+	sii8620_write(ctx, REG_MDT_INT_0, stat);
+}
+
+static void sii8620_status_changed_dcap(struct sii8620 *ctx)
+{
+	if (ctx->stat[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY) {
+		sii8620_set_mode(ctx, CM_MHL1);
+		sii8620_peer_specific_init(ctx);
+		sii8620_write(ctx, REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE
+			       | BIT_INTR9_EDID_DONE | BIT_INTR9_EDID_ERROR);
+	}
+}
+
+static void sii8620_status_changed_path(struct sii8620 *ctx)
+{
+	if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED) {
+		sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
+				      MHL_DST_LM_CLK_MODE_NORMAL
+				      | MHL_DST_LM_PATH_ENABLED);
+		sii8620_mt_read_devcap(ctx, false);
+	} else {
+		sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
+				      MHL_DST_LM_CLK_MODE_NORMAL);
+	}
+}
+
+static void sii8620_msc_mr_write_stat(struct sii8620 *ctx)
+{
+	u8 st[MHL_DST_SIZE], xst[MHL_XDS_SIZE];
+
+	sii8620_read_buf(ctx, REG_MHL_STAT_0, st, MHL_DST_SIZE);
+	sii8620_read_buf(ctx, REG_MHL_EXTSTAT_0, xst, MHL_XDS_SIZE);
+
+	sii8620_update_array(ctx->stat, st, MHL_DST_SIZE);
+	sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE);
+
+	if (st[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY)
+		sii8620_status_changed_dcap(ctx);
+
+	if (st[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
+		sii8620_status_changed_path(ctx);
+}
+
+static void sii8620_msc_mr_set_int(struct sii8620 *ctx)
+{
+	u8 ints[MHL_INT_SIZE];
+
+	sii8620_read_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE);
+	sii8620_write_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE);
+}
+
+static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx)
+{
+	struct device *dev = ctx->dev;
+
+	if (list_empty(&ctx->mt_queue)) {
+		dev_err(dev, "unexpected MSC MT response\n");
+		return NULL;
+	}
+
+	return list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
+}
+
+static void sii8620_msc_mt_done(struct sii8620 *ctx)
+{
+	struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx);
+
+	if (!msg)
+		return;
+
+	msg->ret = sii8620_readb(ctx, REG_MSC_MT_RCVD_DATA0);
+	ctx->mt_state = MT_STATE_DONE;
+}
+
+static void sii8620_msc_mr_msc_msg(struct sii8620 *ctx)
+{
+	struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx);
+	u8 buf[2];
+
+	if (!msg)
+		return;
+
+	sii8620_read_buf(ctx, REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA, buf, 2);
+
+	switch (buf[0]) {
+	case MHL_MSC_MSG_RAPK:
+		msg->ret = buf[1];
+		ctx->mt_state = MT_STATE_DONE;
+		break;
+	default:
+		dev_err(ctx->dev, "%s message type %d,%d not supported",
+			__func__, buf[0], buf[1]);
+	}
+}
+
+static void sii8620_irq_msc(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_CBUS_INT_0);
+
+	if (stat & ~BIT_CBUS_HPD_CHG)
+		sii8620_write(ctx, REG_CBUS_INT_0, stat & ~BIT_CBUS_HPD_CHG);
+
+	if (stat & BIT_CBUS_HPD_CHG) {
+		u8 cbus_stat = sii8620_readb(ctx, REG_CBUS_STATUS);
+
+		if ((cbus_stat ^ ctx->cbus_status) & BIT_CBUS_STATUS_CBUS_HPD) {
+			sii8620_write(ctx, REG_CBUS_INT_0, BIT_CBUS_HPD_CHG);
+		} else {
+			stat ^= BIT_CBUS_STATUS_CBUS_HPD;
+			cbus_stat ^= BIT_CBUS_STATUS_CBUS_HPD;
+		}
+		ctx->cbus_status = cbus_stat;
+	}
+
+	if (stat & BIT_CBUS_MSC_MR_WRITE_STAT)
+		sii8620_msc_mr_write_stat(ctx);
+
+	if (stat & BIT_CBUS_MSC_MR_SET_INT)
+		sii8620_msc_mr_set_int(ctx);
+
+	if (stat & BIT_CBUS_MSC_MT_DONE)
+		sii8620_msc_mt_done(ctx);
+
+	if (stat & BIT_CBUS_MSC_MR_MSC_MSG)
+		sii8620_msc_mr_msc_msg(ctx);
+}
+
+static void sii8620_irq_coc(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_COC_INTR);
+
+	sii8620_write(ctx, REG_COC_INTR, stat);
+}
+
+static void sii8620_irq_merr(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_CBUS_INT_1);
+
+	sii8620_write(ctx, REG_CBUS_INT_1, stat);
+}
+
+static void sii8620_irq_edid(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_INTR9);
+
+	sii8620_write(ctx, REG_INTR9, stat);
+
+	if (stat & BIT_INTR9_DEVCAP_DONE)
+		ctx->mt_state = MT_STATE_DONE;
+}
+
+static void sii8620_scdt_high(struct sii8620 *ctx)
+{
+	sii8620_write_seq_static(ctx,
+		REG_INTR8_MASK, BIT_CEA_NEW_AVI | BIT_CEA_NEW_VSI,
+		REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI,
+	);
+}
+
+static void sii8620_scdt_low(struct sii8620 *ctx)
+{
+	sii8620_write(ctx, REG_TMDS_CSTAT_P3,
+		      BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS |
+		      BIT_TMDS_CSTAT_P3_CLR_AVI);
+
+	sii8620_stop_video(ctx);
+
+	sii8620_write(ctx, REG_INTR8_MASK, 0);
+}
+
+static void sii8620_irq_scdt(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_INTR5);
+
+	if (stat & BIT_INTR_SCDT_CHANGE) {
+		u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
+
+		if (cstat & BIT_TMDS_CSTAT_P3_SCDT)
+			sii8620_scdt_high(ctx);
+		else
+			sii8620_scdt_low(ctx);
+	}
+
+	sii8620_write(ctx, REG_INTR5, stat);
+}
+
+static void sii8620_new_vsi(struct sii8620 *ctx)
+{
+	u8 vsif[11];
+
+	sii8620_write(ctx, REG_RX_HDMI_CTRL2,
+		      VAL_RX_HDMI_CTRL2_DEFVAL |
+		      BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI);
+	sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, vsif,
+			 ARRAY_SIZE(vsif));
+}
+
+static void sii8620_new_avi(struct sii8620 *ctx)
+{
+	sii8620_write(ctx, REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL);
+	sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, ctx->avif,
+			 ARRAY_SIZE(ctx->avif));
+}
+
+static void sii8620_irq_infr(struct sii8620 *ctx)
+{
+	u8 stat = sii8620_readb(ctx, REG_INTR8)
+		& (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI);
+
+	sii8620_write(ctx, REG_INTR8, stat);
+
+	if (stat & BIT_CEA_NEW_VSI)
+		sii8620_new_vsi(ctx);
+
+	if (stat & BIT_CEA_NEW_AVI)
+		sii8620_new_avi(ctx);
+
+	if (stat & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI))
+		sii8620_start_video(ctx);
+}
+
+/* endian agnostic, non-volatile version of test_bit */
+static bool sii8620_test_bit(unsigned int nr, const u8 *addr)
+{
+	return 1 & (addr[nr / BITS_PER_BYTE] >> (nr % BITS_PER_BYTE));
+}
+
+static irqreturn_t sii8620_irq_thread(int irq, void *data)
+{
+	static const struct {
+		int bit;
+		void (*handler)(struct sii8620 *ctx);
+	} irq_vec[] = {
+		{ BIT_FAST_INTR_STAT_DISC, sii8620_irq_disc },
+		{ BIT_FAST_INTR_STAT_G2WB, sii8620_irq_g2wb },
+		{ BIT_FAST_INTR_STAT_COC, sii8620_irq_coc },
+		{ BIT_FAST_INTR_STAT_MSC, sii8620_irq_msc },
+		{ BIT_FAST_INTR_STAT_MERR, sii8620_irq_merr },
+		{ BIT_FAST_INTR_STAT_EDID, sii8620_irq_edid },
+		{ BIT_FAST_INTR_STAT_SCDT, sii8620_irq_scdt },
+		{ BIT_FAST_INTR_STAT_INFR, sii8620_irq_infr },
+	};
+	struct sii8620 *ctx = data;
+	u8 stats[LEN_FAST_INTR_STAT];
+	int i, ret;
+
+	mutex_lock(&ctx->lock);
+
+	sii8620_read_buf(ctx, REG_FAST_INTR_STAT, stats, ARRAY_SIZE(stats));
+	for (i = 0; i < ARRAY_SIZE(irq_vec); ++i)
+		if (sii8620_test_bit(irq_vec[i].bit, stats))
+			irq_vec[i].handler(ctx);
+
+	sii8620_mt_work(ctx);
+
+	ret = sii8620_clear_error(ctx);
+	if (ret) {
+		dev_err(ctx->dev, "Error during IRQ handling, %d.\n", ret);
+		sii8620_mhl_disconnected(ctx);
+	}
+	mutex_unlock(&ctx->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void sii8620_cable_in(struct sii8620 *ctx)
+{
+	struct device *dev = ctx->dev;
+	u8 ver[5];
+	int ret;
+
+	ret = sii8620_hw_on(ctx);
+	if (ret) {
+		dev_err(dev, "Error powering on, %d.\n", ret);
+		return;
+	}
+	sii8620_hw_reset(ctx);
+
+	sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver));
+	ret = sii8620_clear_error(ctx);
+	if (ret) {
+		dev_err(dev, "Error accessing I2C bus, %d.\n", ret);
+		return;
+	}
+
+	dev_info(dev, "ChipID %02x%02x:%02x%02x rev %02x.\n", ver[1], ver[0],
+		 ver[3], ver[2], ver[4]);
+
+	sii8620_write(ctx, REG_DPD,
+		      BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN);
+
+	sii8620_xtal_set_rate(ctx);
+	sii8620_disconnect(ctx);
+
+	sii8620_write_seq_static(ctx,
+		REG_MHL_CBUS_CTL0, VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONG
+			| VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_734,
+		REG_MHL_CBUS_CTL1, VAL_MHL_CBUS_CTL1_1115_OHM,
+		REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN,
+	);
+
+	ret = sii8620_clear_error(ctx);
+	if (ret) {
+		dev_err(dev, "Error accessing I2C bus, %d.\n", ret);
+		return;
+	}
+
+	enable_irq(to_i2c_client(ctx->dev)->irq);
+}
+
+static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct sii8620, bridge);
+}
+
+static bool sii8620_mode_fixup(struct drm_bridge *bridge,
+			       const struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode)
+{
+	struct sii8620 *ctx = bridge_to_sii8620(bridge);
+	bool ret = false;
+	int max_clock = 74250;
+
+	mutex_lock(&ctx->lock);
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		goto out;
+
+	if (ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL)
+		max_clock = 300000;
+
+	ret = mode->clock <= max_clock;
+
+out:
+	mutex_unlock(&ctx->lock);
+
+	return ret;
+}
+
+static const struct drm_bridge_funcs sii8620_bridge_funcs = {
+	.mode_fixup = sii8620_mode_fixup,
+};
+
+static int sii8620_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct sii8620 *ctx;
+	int ret;
+
+	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->dev = dev;
+	mutex_init(&ctx->lock);
+	INIT_LIST_HEAD(&ctx->mt_queue);
+
+	ctx->clk_xtal = devm_clk_get(dev, "xtal");
+	if (IS_ERR(ctx->clk_xtal)) {
+		dev_err(dev, "failed to get xtal clock from DT\n");
+		return PTR_ERR(ctx->clk_xtal);
+	}
+
+	if (!client->irq) {
+		dev_err(dev, "no irq provided\n");
+		return -EINVAL;
+	}
+	irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
+	ret = devm_request_threaded_irq(dev, client->irq, NULL,
+					sii8620_irq_thread,
+					IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+					"sii8620", ctx);
+
+	ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ctx->gpio_reset)) {
+		dev_err(dev, "failed to get reset gpio from DT\n");
+		return PTR_ERR(ctx->gpio_reset);
+	}
+
+	ctx->supplies[0].supply = "cvcc10";
+	ctx->supplies[1].supply = "iovcc18";
+	ret = devm_regulator_bulk_get(dev, 2, ctx->supplies);
+	if (ret)
+		return ret;
+
+	i2c_set_clientdata(client, ctx);
+
+	ctx->bridge.funcs = &sii8620_bridge_funcs;
+	ctx->bridge.of_node = dev->of_node;
+	drm_bridge_add(&ctx->bridge);
+
+	sii8620_cable_in(ctx);
+
+	return 0;
+}
+
+static int sii8620_remove(struct i2c_client *client)
+{
+	struct sii8620 *ctx = i2c_get_clientdata(client);
+
+	disable_irq(to_i2c_client(ctx->dev)->irq);
+	drm_bridge_remove(&ctx->bridge);
+	sii8620_hw_off(ctx);
+
+	return 0;
+}
+
+static const struct of_device_id sii8620_dt_match[] = {
+	{ .compatible = "sil,sii8620" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sii8620_dt_match);
+
+static const struct i2c_device_id sii8620_id[] = {
+	{ "sii8620", 0 },
+	{ },
+};
+
+MODULE_DEVICE_TABLE(i2c, sii8620_id);
+static struct i2c_driver sii8620_driver = {
+	.driver = {
+		.name	= "sii8620",
+		.of_match_table = of_match_ptr(sii8620_dt_match),
+	},
+	.probe		= sii8620_probe,
+	.remove		= sii8620_remove,
+	.id_table = sii8620_id,
+};
+
+module_i2c_driver(sii8620_driver);
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/sil-sii8620.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/sil-sii8620.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/sil-sii8620.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/sil-sii8620.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1517 @@
+/*
+ * Registers of Silicon Image SiI8620 Mobile HD Transmitter
+ *
+ * Copyright (C) 2015, Samsung Electronics Co., Ltd.
+ * Andrzej Hajda <a.hajda@samsung.com>
+ *
+ * Based on MHL driver for Android devices.
+ * Copyright (C) 2013-2014 Silicon Image, 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 __SIL_SII8620_H__
+#define __SIL_SII8620_H__
+
+/* Vendor ID Low byte, default value: 0x01 */
+#define REG_VND_IDL				0x0000
+
+/* Vendor ID High byte, default value: 0x00 */
+#define REG_VND_IDH				0x0001
+
+/* Device ID Low byte, default value: 0x60 */
+#define REG_DEV_IDL				0x0002
+
+/* Device ID High byte, default value: 0x86 */
+#define REG_DEV_IDH				0x0003
+
+/* Device Revision, default value: 0x10 */
+#define REG_DEV_REV				0x0004
+
+/* OTP DBYTE510, default value: 0x00 */
+#define REG_OTP_DBYTE510			0x0006
+
+/* System Control #1, default value: 0x00 */
+#define REG_SYS_CTRL1				0x0008
+#define BIT_SYS_CTRL1_OTPVMUTEOVR_SET		BIT(7)
+#define BIT_SYS_CTRL1_VSYNCPIN			BIT(6)
+#define BIT_SYS_CTRL1_OTPADROPOVR_SET		BIT(5)
+#define BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD		BIT(4)
+#define BIT_SYS_CTRL1_OTP2XVOVR_EN		BIT(3)
+#define BIT_SYS_CTRL1_OTP2XAOVR_EN		BIT(2)
+#define BIT_SYS_CTRL1_TX_CTRL_HDMI		BIT(1)
+#define BIT_SYS_CTRL1_OTPAMUTEOVR_SET		BIT(0)
+
+/* System Control DPD, default value: 0x90 */
+#define REG_DPD					0x000b
+#define BIT_DPD_PWRON_PLL			BIT(7)
+#define BIT_DPD_PDNTX12				BIT(6)
+#define BIT_DPD_PDNRX12				BIT(5)
+#define BIT_DPD_OSC_EN				BIT(4)
+#define BIT_DPD_PWRON_HSIC			BIT(3)
+#define BIT_DPD_PDIDCK_N			BIT(2)
+#define BIT_DPD_PD_MHL_CLK_N			BIT(1)
+
+/* Dual link Control, default value: 0x00 */
+#define REG_DCTL				0x000d
+#define BIT_DCTL_TDM_LCLK_PHASE			BIT(7)
+#define BIT_DCTL_HSIC_CLK_PHASE			BIT(6)
+#define BIT_DCTL_CTS_TCK_PHASE			BIT(5)
+#define BIT_DCTL_EXT_DDC_SEL			BIT(4)
+#define BIT_DCTL_TRANSCODE			BIT(3)
+#define BIT_DCTL_HSIC_RX_STROBE_PHASE		BIT(2)
+#define BIT_DCTL_HSIC_TX_BIST_START_SEL		BIT(1)
+#define BIT_DCTL_TCLKNX_PHASE			BIT(0)
+
+/* PWD Software Reset, default value: 0x20 */
+#define REG_PWD_SRST				0x000e
+#define BIT_PWD_SRST_COC_DOC_RST		BIT(7)
+#define BIT_PWD_SRST_CBUS_RST_SW		BIT(6)
+#define BIT_PWD_SRST_CBUS_RST_SW_EN		BIT(5)
+#define BIT_PWD_SRST_MHLFIFO_RST		BIT(4)
+#define BIT_PWD_SRST_CBUS_RST			BIT(3)
+#define BIT_PWD_SRST_SW_RST_AUTO		BIT(2)
+#define BIT_PWD_SRST_HDCP2X_SW_RST		BIT(1)
+#define BIT_PWD_SRST_SW_RST			BIT(0)
+
+/* AKSV_1, default value: 0x00 */
+#define REG_AKSV_1				0x001d
+
+/* Video H Resolution #1, default value: 0x00 */
+#define REG_H_RESL				0x003a
+
+/* Video Mode, default value: 0x00 */
+#define REG_VID_MODE				0x004a
+#define BIT_VID_MODE_M1080P			BIT(6)
+
+/* Video Input Mode, default value: 0xc0 */
+#define REG_VID_OVRRD				0x0051
+#define BIT_VID_OVRRD_PP_AUTO_DISABLE		BIT(7)
+#define BIT_VID_OVRRD_M1080P_OVRRD		BIT(6)
+#define BIT_VID_OVRRD_MINIVSYNC_ON		BIT(5)
+#define BIT_VID_OVRRD_3DCONV_EN_FRAME_PACK	BIT(4)
+#define BIT_VID_OVRRD_ENABLE_AUTO_PATH_EN	BIT(3)
+#define BIT_VID_OVRRD_ENRGB2YCBCR_OVRRD		BIT(2)
+#define BIT_VID_OVRRD_ENDOWNSAMPLE_OVRRD	BIT(0)
+
+/* I2C Address reassignment, default value: 0x00 */
+#define REG_PAGE_MHLSPEC_ADDR			0x0057
+#define REG_PAGE7_ADDR				0x0058
+#define REG_PAGE8_ADDR				0x005c
+
+/* Fast Interrupt Status, default value: 0x00 */
+#define REG_FAST_INTR_STAT			0x005f
+#define LEN_FAST_INTR_STAT			7
+#define BIT_FAST_INTR_STAT_TIMR			8
+#define BIT_FAST_INTR_STAT_INT2			9
+#define BIT_FAST_INTR_STAT_DDC			10
+#define BIT_FAST_INTR_STAT_SCDT			11
+#define BIT_FAST_INTR_STAT_INFR			13
+#define BIT_FAST_INTR_STAT_EDID			14
+#define BIT_FAST_INTR_STAT_HDCP			15
+#define BIT_FAST_INTR_STAT_MSC			16
+#define BIT_FAST_INTR_STAT_MERR			17
+#define BIT_FAST_INTR_STAT_G2WB			18
+#define BIT_FAST_INTR_STAT_G2WB_ERR		19
+#define BIT_FAST_INTR_STAT_DISC			28
+#define BIT_FAST_INTR_STAT_BLOCK		30
+#define BIT_FAST_INTR_STAT_LTRN			31
+#define BIT_FAST_INTR_STAT_HDCP2		32
+#define BIT_FAST_INTR_STAT_TDM			42
+#define BIT_FAST_INTR_STAT_COC			51
+
+/* GPIO Control, default value: 0x15 */
+#define REG_GPIO_CTRL1				0x006e
+#define BIT_CTRL1_GPIO_I_8			BIT(5)
+#define BIT_CTRL1_GPIO_OEN_8			BIT(4)
+#define BIT_CTRL1_GPIO_I_7			BIT(3)
+#define BIT_CTRL1_GPIO_OEN_7			BIT(2)
+#define BIT_CTRL1_GPIO_I_6			BIT(1)
+#define BIT_CTRL1_GPIO_OEN_6			BIT(0)
+
+/* Interrupt Control, default value: 0x06 */
+#define REG_INT_CTRL				0x006f
+#define BIT_INT_CTRL_SOFTWARE_WP		BIT(7)
+#define BIT_INT_CTRL_INTR_OD			BIT(2)
+#define BIT_INT_CTRL_INTR_POLARITY		BIT(1)
+
+/* Interrupt State, default value: 0x00 */
+#define REG_INTR_STATE				0x0070
+#define BIT_INTR_STATE_INTR_STATE		BIT(0)
+
+/* Interrupt Source #1, default value: 0x00 */
+#define REG_INTR1				0x0071
+
+/* Interrupt Source #2, default value: 0x00 */
+#define REG_INTR2				0x0072
+
+/* Interrupt Source #3, default value: 0x01 */
+#define REG_INTR3				0x0073
+#define BIT_DDC_CMD_DONE			BIT(3)
+
+/* Interrupt Source #5, default value: 0x00 */
+#define REG_INTR5				0x0074
+
+/* Interrupt #1 Mask, default value: 0x00 */
+#define REG_INTR1_MASK				0x0075
+
+/* Interrupt #2 Mask, default value: 0x00 */
+#define REG_INTR2_MASK				0x0076
+
+/* Interrupt #3 Mask, default value: 0x00 */
+#define REG_INTR3_MASK				0x0077
+
+/* Interrupt #5 Mask, default value: 0x00 */
+#define REG_INTR5_MASK				0x0078
+#define BIT_INTR_SCDT_CHANGE			BIT(0)
+
+/* Hot Plug Connection Control, default value: 0x45 */
+#define REG_HPD_CTRL				0x0079
+#define BIT_HPD_CTRL_HPD_DS_SIGNAL		BIT(7)
+#define BIT_HPD_CTRL_HPD_OUT_OD_EN		BIT(6)
+#define BIT_HPD_CTRL_HPD_HIGH			BIT(5)
+#define BIT_HPD_CTRL_HPD_OUT_OVR_EN		BIT(4)
+#define BIT_HPD_CTRL_GPIO_I_1			BIT(3)
+#define BIT_HPD_CTRL_GPIO_OEN_1			BIT(2)
+#define BIT_HPD_CTRL_GPIO_I_0			BIT(1)
+#define BIT_HPD_CTRL_GPIO_OEN_0			BIT(0)
+
+/* GPIO Control, default value: 0x55 */
+#define REG_GPIO_CTRL				0x007a
+#define BIT_CTRL_GPIO_I_5			BIT(7)
+#define BIT_CTRL_GPIO_OEN_5			BIT(6)
+#define BIT_CTRL_GPIO_I_4			BIT(5)
+#define BIT_CTRL_GPIO_OEN_4			BIT(4)
+#define BIT_CTRL_GPIO_I_3			BIT(3)
+#define BIT_CTRL_GPIO_OEN_3			BIT(2)
+#define BIT_CTRL_GPIO_I_2			BIT(1)
+#define BIT_CTRL_GPIO_OEN_2			BIT(0)
+
+/* Interrupt Source 7, default value: 0x00 */
+#define REG_INTR7				0x007b
+
+/* Interrupt Source 8, default value: 0x00 */
+#define REG_INTR8				0x007c
+
+/* Interrupt #7 Mask, default value: 0x00 */
+#define REG_INTR7_MASK				0x007d
+
+/* Interrupt #8 Mask, default value: 0x00 */
+#define REG_INTR8_MASK				0x007e
+#define BIT_CEA_NEW_VSI				BIT(2)
+#define BIT_CEA_NEW_AVI				BIT(1)
+
+/* IEEE, default value: 0x10 */
+#define REG_TMDS_CCTRL				0x0080
+#define BIT_TMDS_CCTRL_TMDS_OE			BIT(4)
+
+/* TMDS Control #4, default value: 0x02 */
+#define REG_TMDS_CTRL4				0x0085
+#define BIT_TMDS_CTRL4_SCDT_CKDT_SEL		BIT(1)
+#define BIT_TMDS_CTRL4_TX_EN_BY_SCDT		BIT(0)
+
+/* BIST CNTL, default value: 0x00 */
+#define REG_BIST_CTRL				0x00bb
+#define BIT_RXBIST_VGB_EN			BIT(7)
+#define BIT_TXBIST_VGB_EN			BIT(6)
+#define BIT_BIST_START_SEL			BIT(5)
+#define BIT_BIST_START_BIT			BIT(4)
+#define BIT_BIST_ALWAYS_ON			BIT(3)
+#define BIT_BIST_TRANS				BIT(2)
+#define BIT_BIST_RESET				BIT(1)
+#define BIT_BIST_EN				BIT(0)
+
+/* BIST DURATION0, default value: 0x00 */
+#define REG_BIST_TEST_SEL			0x00bd
+#define MSK_BIST_TEST_SEL_BIST_PATT_SEL		0x0f
+
+/* BIST VIDEO_MODE, default value: 0x00 */
+#define REG_BIST_VIDEO_MODE			0x00be
+#define MSK_BIST_VIDEO_MODE_BIST_VIDEO_MODE_3_0	0x0f
+
+/* BIST DURATION0, default value: 0x00 */
+#define REG_BIST_DURATION_0			0x00bf
+
+/* BIST DURATION1, default value: 0x00 */
+#define REG_BIST_DURATION_1			0x00c0
+
+/* BIST DURATION2, default value: 0x00 */
+#define REG_BIST_DURATION_2			0x00c1
+
+/* BIST 8BIT_PATTERN, default value: 0x00 */
+#define REG_BIST_8BIT_PATTERN			0x00c2
+
+/* LM DDC, default value: 0x80 */
+#define REG_LM_DDC				0x00c7
+#define BIT_LM_DDC_SW_TPI_EN_DISABLED		BIT(7)
+
+#define BIT_LM_DDC_VIDEO_MUTE_EN		BIT(5)
+#define BIT_LM_DDC_DDC_TPI_SW			BIT(2)
+#define BIT_LM_DDC_DDC_GRANT			BIT(1)
+#define BIT_LM_DDC_DDC_GPU_REQUEST		BIT(0)
+
+/* DDC I2C Manual, default value: 0x03 */
+#define REG_DDC_MANUAL				0x00ec
+#define BIT_DDC_MANUAL_MAN_DDC			BIT(7)
+#define BIT_DDC_MANUAL_VP_SEL			BIT(6)
+#define BIT_DDC_MANUAL_DSDA			BIT(5)
+#define BIT_DDC_MANUAL_DSCL			BIT(4)
+#define BIT_DDC_MANUAL_GCP_HW_CTL_EN		BIT(3)
+#define BIT_DDC_MANUAL_DDCM_ABORT_WP		BIT(2)
+#define BIT_DDC_MANUAL_IO_DSDA			BIT(1)
+#define BIT_DDC_MANUAL_IO_DSCL			BIT(0)
+
+/* DDC I2C Target Slave Address, default value: 0x00 */
+#define REG_DDC_ADDR				0x00ed
+#define MSK_DDC_ADDR_DDC_ADDR			0xfe
+
+/* DDC I2C Target Segment Address, default value: 0x00 */
+#define REG_DDC_SEGM				0x00ee
+
+/* DDC I2C Target Offset Address, default value: 0x00 */
+#define REG_DDC_OFFSET				0x00ef
+
+/* DDC I2C Data In count #1, default value: 0x00 */
+#define REG_DDC_DIN_CNT1			0x00f0
+
+/* DDC I2C Data In count #2, default value: 0x00 */
+#define REG_DDC_DIN_CNT2			0x00f1
+#define MSK_DDC_DIN_CNT2_DDC_DIN_CNT_9_8	0x03
+
+/* DDC I2C Status, default value: 0x04 */
+#define REG_DDC_STATUS				0x00f2
+#define BIT_DDC_STATUS_DDC_BUS_LOW		BIT(6)
+#define BIT_DDC_STATUS_DDC_NO_ACK		BIT(5)
+#define BIT_DDC_STATUS_DDC_I2C_IN_PROG		BIT(4)
+#define BIT_DDC_STATUS_DDC_FIFO_FULL		BIT(3)
+#define BIT_DDC_STATUS_DDC_FIFO_EMPTY		BIT(2)
+#define BIT_DDC_STATUS_DDC_FIFO_READ_IN_SUE	BIT(1)
+#define BIT_DDC_STATUS_DDC_FIFO_WRITE_IN_USE	BIT(0)
+
+/* DDC I2C Command, default value: 0x70 */
+#define REG_DDC_CMD				0x00f3
+#define BIT_DDC_CMD_HDCP_DDC_EN			BIT(6)
+#define BIT_DDC_CMD_SDA_DEL_EN			BIT(5)
+#define BIT_DDC_CMD_DDC_FLT_EN			BIT(4)
+
+#define MSK_DDC_CMD_DDC_CMD			0x0f
+#define VAL_DDC_CMD_ENH_DDC_READ_NO_ACK		0x04
+#define VAL_DDC_CMD_DDC_CMD_CLEAR_FIFO		0x09
+#define VAL_DDC_CMD_DDC_CMD_ABORT		0x0f
+
+/* DDC I2C FIFO Data In/Out, default value: 0x00 */
+#define REG_DDC_DATA				0x00f4
+
+/* DDC I2C Data Out Counter, default value: 0x00 */
+#define REG_DDC_DOUT_CNT			0x00f5
+#define BIT_DDC_DOUT_CNT_DDC_DELAY_CNT_8	BIT(7)
+#define MSK_DDC_DOUT_CNT_DDC_DATA_OUT_CNT	0x1f
+
+/* DDC I2C Delay Count, default value: 0x14 */
+#define REG_DDC_DELAY_CNT			0x00f6
+
+/* Test Control, default value: 0x80 */
+#define REG_TEST_TXCTRL				0x00f7
+#define BIT_TEST_TXCTRL_RCLK_REF_SEL		BIT(7)
+#define BIT_TEST_TXCTRL_PCLK_REF_SEL		BIT(6)
+#define MSK_TEST_TXCTRL_BYPASS_PLL_CLK		0x3c
+#define BIT_TEST_TXCTRL_HDMI_MODE		BIT(1)
+#define BIT_TEST_TXCTRL_TST_PLLCK		BIT(0)
+
+/* CBUS Address, default value: 0x00 */
+#define REG_PAGE_CBUS_ADDR			0x00f8
+
+/* I2C Device Address re-assignment */
+#define REG_PAGE1_ADDR				0x00fc
+#define REG_PAGE2_ADDR				0x00fd
+#define REG_PAGE3_ADDR				0x00fe
+#define REG_HW_TPI_ADDR				0x00ff
+
+/* USBT CTRL0, default value: 0x00 */
+#define REG_UTSRST				0x0100
+#define BIT_UTSRST_FC_SRST			BIT(5)
+#define BIT_UTSRST_KEEPER_SRST			BIT(4)
+#define BIT_UTSRST_HTX_SRST			BIT(3)
+#define BIT_UTSRST_TRX_SRST			BIT(2)
+#define BIT_UTSRST_TTX_SRST			BIT(1)
+#define BIT_UTSRST_HRX_SRST			BIT(0)
+
+/* HSIC RX Control3, default value: 0x07 */
+#define REG_HRXCTRL3				0x0104
+#define MSK_HRXCTRL3_HRX_AFFCTRL		0xf0
+#define BIT_HRXCTRL3_HRX_OUT_EN			BIT(2)
+#define BIT_HRXCTRL3_STATUS_EN			BIT(1)
+#define BIT_HRXCTRL3_HRX_STAY_RESET		BIT(0)
+
+/* HSIC RX INT Registers */
+#define REG_HRXINTL				0x0111
+#define REG_HRXINTH				0x0112
+
+/* TDM TX NUMBITS, default value: 0x0c */
+#define REG_TTXNUMB				0x0116
+#define MSK_TTXNUMB_TTX_AFFCTRL_3_0		0xf0
+#define BIT_TTXNUMB_TTX_COM1_AT_SYNC_WAIT	BIT(3)
+#define MSK_TTXNUMB_TTX_NUMBPS_2_0		0x07
+
+/* TDM TX NUMSPISYM, default value: 0x04 */
+#define REG_TTXSPINUMS				0x0117
+
+/* TDM TX NUMHSICSYM, default value: 0x14 */
+#define REG_TTXHSICNUMS				0x0118
+
+/* TDM TX NUMTOTSYM, default value: 0x18 */
+#define REG_TTXTOTNUMS				0x0119
+
+/* TDM TX INT Low, default value: 0x00 */
+#define REG_TTXINTL				0x0136
+#define BIT_TTXINTL_TTX_INTR7			BIT(7)
+#define BIT_TTXINTL_TTX_INTR6			BIT(6)
+#define BIT_TTXINTL_TTX_INTR5			BIT(5)
+#define BIT_TTXINTL_TTX_INTR4			BIT(4)
+#define BIT_TTXINTL_TTX_INTR3			BIT(3)
+#define BIT_TTXINTL_TTX_INTR2			BIT(2)
+#define BIT_TTXINTL_TTX_INTR1			BIT(1)
+#define BIT_TTXINTL_TTX_INTR0			BIT(0)
+
+/* TDM TX INT High, default value: 0x00 */
+#define REG_TTXINTH				0x0137
+#define BIT_TTXINTH_TTX_INTR15			BIT(7)
+#define BIT_TTXINTH_TTX_INTR14			BIT(6)
+#define BIT_TTXINTH_TTX_INTR13			BIT(5)
+#define BIT_TTXINTH_TTX_INTR12			BIT(4)
+#define BIT_TTXINTH_TTX_INTR11			BIT(3)
+#define BIT_TTXINTH_TTX_INTR10			BIT(2)
+#define BIT_TTXINTH_TTX_INTR9			BIT(1)
+#define BIT_TTXINTH_TTX_INTR8			BIT(0)
+
+/* TDM RX Control, default value: 0x1c */
+#define REG_TRXCTRL				0x013b
+#define BIT_TRXCTRL_TRX_CLR_WVALLOW		BIT(4)
+#define BIT_TRXCTRL_TRX_FROM_SE_COC		BIT(3)
+#define MSK_TRXCTRL_TRX_NUMBPS_2_0		0x07
+
+/* TDM RX NUMSPISYM, default value: 0x04 */
+#define REG_TRXSPINUMS				0x013c
+
+/* TDM RX NUMHSICSYM, default value: 0x14 */
+#define REG_TRXHSICNUMS				0x013d
+
+/* TDM RX NUMTOTSYM, default value: 0x18 */
+#define REG_TRXTOTNUMS				0x013e
+
+/* TDM RX Status 2nd, default value: 0x00 */
+#define REG_TRXSTA2				0x015c
+
+/* TDM RX INT Low, default value: 0x00 */
+#define REG_TRXINTL				0x0163
+
+/* TDM RX INT High, default value: 0x00 */
+#define REG_TRXINTH				0x0164
+
+/* TDM RX INTMASK High, default value: 0x00 */
+#define REG_TRXINTMH				0x0166
+
+/* HSIC TX CRTL, default value: 0x00 */
+#define REG_HTXCTRL				0x0169
+#define BIT_HTXCTRL_HTX_ALLSBE_SOP		BIT(4)
+#define BIT_HTXCTRL_HTX_RGDINV_USB		BIT(3)
+#define BIT_HTXCTRL_HTX_RSPTDM_BUSY		BIT(2)
+#define BIT_HTXCTRL_HTX_DRVCONN1		BIT(1)
+#define BIT_HTXCTRL_HTX_DRVRST1			BIT(0)
+
+/* HSIC TX INT Low, default value: 0x00 */
+#define REG_HTXINTL				0x017d
+
+/* HSIC TX INT High, default value: 0x00 */
+#define REG_HTXINTH				0x017e
+
+/* HSIC Keeper, default value: 0x00 */
+#define REG_KEEPER				0x0181
+#define MSK_KEEPER_KEEPER_MODE_1_0		0x03
+
+/* HSIC Flow Control General, default value: 0x02 */
+#define REG_FCGC				0x0183
+#define BIT_FCGC_HSIC_FC_HOSTMODE		BIT(1)
+#define BIT_FCGC_HSIC_FC_ENABLE			BIT(0)
+
+/* HSIC Flow Control CTR13, default value: 0xfc */
+#define REG_FCCTR13				0x0191
+
+/* HSIC Flow Control CTR14, default value: 0xff */
+#define REG_FCCTR14				0x0192
+
+/* HSIC Flow Control CTR15, default value: 0xff */
+#define REG_FCCTR15				0x0193
+
+/* HSIC Flow Control CTR50, default value: 0x03 */
+#define REG_FCCTR50				0x01b6
+
+/* HSIC Flow Control INTR0, default value: 0x00 */
+#define REG_FCINTR0				0x01ec
+#define REG_FCINTR1				0x01ed
+#define REG_FCINTR2				0x01ee
+#define REG_FCINTR3				0x01ef
+#define REG_FCINTR4				0x01f0
+#define REG_FCINTR5				0x01f1
+#define REG_FCINTR6				0x01f2
+#define REG_FCINTR7				0x01f3
+
+/* TDM Low Latency, default value: 0x20 */
+#define REG_TDMLLCTL				0x01fc
+#define MSK_TDMLLCTL_TRX_LL_SEL_MANUAL		0xc0
+#define MSK_TDMLLCTL_TRX_LL_SEL_MODE		0x30
+#define MSK_TDMLLCTL_TTX_LL_SEL_MANUAL		0x0c
+#define BIT_TDMLLCTL_TTX_LL_TIE_LOW		BIT(1)
+#define BIT_TDMLLCTL_TTX_LL_SEL_MODE		BIT(0)
+
+/* TMDS 0 Clock Control, default value: 0x10 */
+#define REG_TMDS0_CCTRL1			0x0210
+#define MSK_TMDS0_CCTRL1_TEST_SEL		0xc0
+#define MSK_TMDS0_CCTRL1_CLK1X_CTL		0x30
+
+/* TMDS Clock Enable, default value: 0x00 */
+#define REG_TMDS_CLK_EN				0x0211
+#define BIT_TMDS_CLK_EN_CLK_EN			BIT(0)
+
+/* TMDS Channel Enable, default value: 0x00 */
+#define REG_TMDS_CH_EN				0x0212
+#define BIT_TMDS_CH_EN_CH0_EN			BIT(4)
+#define BIT_TMDS_CH_EN_CH12_EN			BIT(0)
+
+/* BGR_BIAS, default value: 0x07 */
+#define REG_BGR_BIAS				0x0215
+#define BIT_BGR_BIAS_BGR_EN			BIT(7)
+#define MSK_BGR_BIAS_BIAS_BGR_D			0x0f
+
+/* TMDS 0 Digital I2C BW, default value: 0x0a */
+#define REG_ALICE0_BW_I2C			0x0231
+
+/* TMDS 0 Digital Zone Control, default value: 0xe0 */
+#define REG_ALICE0_ZONE_CTRL			0x024c
+#define BIT_ALICE0_ZONE_CTRL_ICRST_N		BIT(7)
+#define BIT_ALICE0_ZONE_CTRL_USE_INT_DIV20	BIT(6)
+#define MSK_ALICE0_ZONE_CTRL_SZONE_I2C		0x30
+#define MSK_ALICE0_ZONE_CTRL_ZONE_CTRL		0x0f
+
+/* TMDS 0 Digital PLL Mode Control, default value: 0x00 */
+#define REG_ALICE0_MODE_CTRL			0x024d
+#define MSK_ALICE0_MODE_CTRL_PLL_MODE_I2C	0x0c
+#define MSK_ALICE0_MODE_CTRL_DIV20_CTRL		0x03
+
+/* MHL Tx Control 6th, default value: 0xa0 */
+#define REG_MHLTX_CTL6				0x0285
+#define MSK_MHLTX_CTL6_EMI_SEL			0xe0
+#define MSK_MHLTX_CTL6_TX_CLK_SHAPE_9_8		0x03
+
+/* Packet Filter0, default value: 0x00 */
+#define REG_PKT_FILTER_0			0x0290
+#define BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT	BIT(7)
+#define BIT_PKT_FILTER_0_DROP_CEA_CP_PKT	BIT(6)
+#define BIT_PKT_FILTER_0_DROP_MPEG_PKT		BIT(5)
+#define BIT_PKT_FILTER_0_DROP_SPIF_PKT		BIT(4)
+#define BIT_PKT_FILTER_0_DROP_AIF_PKT		BIT(3)
+#define BIT_PKT_FILTER_0_DROP_AVI_PKT		BIT(2)
+#define BIT_PKT_FILTER_0_DROP_CTS_PKT		BIT(1)
+#define BIT_PKT_FILTER_0_DROP_GCP_PKT		BIT(0)
+
+/* Packet Filter1, default value: 0x00 */
+#define REG_PKT_FILTER_1			0x0291
+#define BIT_PKT_FILTER_1_VSI_OVERRIDE_DIS	BIT(7)
+#define BIT_PKT_FILTER_1_AVI_OVERRIDE_DIS	BIT(6)
+#define BIT_PKT_FILTER_1_DROP_AUDIO_PKT		BIT(3)
+#define BIT_PKT_FILTER_1_DROP_GEN2_PKT		BIT(2)
+#define BIT_PKT_FILTER_1_DROP_GEN_PKT		BIT(1)
+#define BIT_PKT_FILTER_1_DROP_VSIF_PKT		BIT(0)
+
+/* TMDS Clock Status, default value: 0x10 */
+#define REG_TMDS_CSTAT_P3			0x02a0
+#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_CLR_MUTE	BIT(7)
+#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_SET_MUTE	BIT(6)
+#define BIT_TMDS_CSTAT_P3_RX_HDMI_CP_NEW_CP	BIT(5)
+#define BIT_TMDS_CSTAT_P3_CLR_AVI		BIT(3)
+#define BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS	BIT(2)
+#define BIT_TMDS_CSTAT_P3_SCDT			BIT(1)
+#define BIT_TMDS_CSTAT_P3_CKDT			BIT(0)
+
+/* RX_HDMI Control, default value: 0x10 */
+#define REG_RX_HDMI_CTRL0			0x02a1
+#define BIT_RX_HDMI_CTRL0_BYP_DVIFILT_SYNC	BIT(5)
+#define BIT_RX_HDMI_CTRL0_HDMI_MODE_EN_ITSELF_CLR BIT(4)
+#define BIT_RX_HDMI_CTRL0_HDMI_MODE_SW_VALUE	BIT(3)
+#define BIT_RX_HDMI_CTRL0_HDMI_MODE_OVERWRITE	BIT(2)
+#define BIT_RX_HDMI_CTRL0_RX_HDMI_HDMI_MODE_EN	BIT(1)
+#define BIT_RX_HDMI_CTRL0_RX_HDMI_HDMI_MODE	BIT(0)
+
+/* RX_HDMI Control, default value: 0x38 */
+#define REG_RX_HDMI_CTRL2			0x02a3
+#define MSK_RX_HDMI_CTRL2_IDLE_CNT		0xf0
+#define VAL_RX_HDMI_CTRL2_IDLE_CNT(n)		((n) << 4)
+#define BIT_RX_HDMI_CTRL2_USE_AV_MUTE		BIT(3)
+#define BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI	BIT(0)
+
+/* RX_HDMI Control, default value: 0x0f */
+#define REG_RX_HDMI_CTRL3			0x02a4
+#define MSK_RX_HDMI_CTRL3_PP_MODE_CLK_EN	0x0f
+
+/* rx_hdmi Clear Buffer, default value: 0x00 */
+#define REG_RX_HDMI_CLR_BUFFER			0x02ac
+#define MSK_RX_HDMI_CLR_BUFFER_AIF4VSI_CMP	0xc0
+#define BIT_RX_HDMI_CLR_BUFFER_USE_AIF4VSI	BIT(5)
+#define BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_W_AVI	BIT(4)
+#define BIT_RX_HDMI_CLR_BUFFER_VSI_IEEE_ID_CHK_EN BIT(3)
+#define BIT_RX_HDMI_CLR_BUFFER_SWAP_VSI_IEEE_ID	BIT(2)
+#define BIT_RX_HDMI_CLR_BUFFER_AIF_CLR_EN	BIT(1)
+#define BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_EN	BIT(0)
+
+/* RX_HDMI VSI Header1, default value: 0x00 */
+#define REG_RX_HDMI_MON_PKT_HEADER1		0x02b8
+
+/* RX_HDMI VSI MHL Monitor, default value: 0x3c */
+#define REG_RX_HDMI_VSIF_MHL_MON		0x02d7
+
+#define MSK_RX_HDMI_VSIF_MHL_MON_RX_HDMI_MHL_3D_FORMAT 0x3c
+#define MSK_RX_HDMI_VSIF_MHL_MON_RX_HDMI_MHL_VID_FORMAT 0x03
+
+/* Interrupt Source 9, default value: 0x00 */
+#define REG_INTR9				0x02e0
+#define BIT_INTR9_EDID_ERROR			BIT(6)
+#define BIT_INTR9_EDID_DONE			BIT(5)
+#define BIT_INTR9_DEVCAP_DONE			BIT(4)
+
+/* Interrupt 9 Mask, default value: 0x00 */
+#define REG_INTR9_MASK				0x02e1
+
+/* TPI CBUS Start, default value: 0x00 */
+#define REG_TPI_CBUS_START			0x02e2
+#define BIT_TPI_CBUS_START_RCP_REQ_START	BIT(7)
+#define BIT_TPI_CBUS_START_RCPK_REPLY_START	BIT(6)
+#define BIT_TPI_CBUS_START_RCPE_REPLY_START	BIT(5)
+#define BIT_TPI_CBUS_START_PUT_LINK_MODE_START	BIT(4)
+#define BIT_TPI_CBUS_START_PUT_DCAPCHG_START	BIT(3)
+#define BIT_TPI_CBUS_START_PUT_DCAPRDY_START	BIT(2)
+#define BIT_TPI_CBUS_START_GET_EDID_START_0	BIT(1)
+#define BIT_TPI_CBUS_START_GET_DEVCAP_START	BIT(0)
+
+/* EDID Control, default value: 0x10 */
+#define REG_EDID_CTRL				0x02e3
+#define BIT_EDID_CTRL_EDID_PRIME_VALID		BIT(7)
+#define BIT_EDID_CTRL_XDEVCAP_EN		BIT(6)
+#define BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP	BIT(5)
+#define BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO	BIT(4)
+#define BIT_EDID_CTRL_EDID_FIFO_ACCESS_ALWAYS_EN BIT(3)
+#define BIT_EDID_CTRL_EDID_FIFO_BLOCK_SEL	BIT(2)
+#define BIT_EDID_CTRL_INVALID_BKSV		BIT(1)
+#define BIT_EDID_CTRL_EDID_MODE_EN		BIT(0)
+
+/* EDID FIFO Addr, default value: 0x00 */
+#define REG_EDID_FIFO_ADDR			0x02e9
+
+/* EDID FIFO Write Data, default value: 0x00 */
+#define REG_EDID_FIFO_WR_DATA			0x02ea
+
+/* EDID/DEVCAP FIFO Internal Addr, default value: 0x00 */
+#define REG_EDID_FIFO_ADDR_MON			0x02eb
+
+/* EDID FIFO Read Data, default value: 0x00 */
+#define REG_EDID_FIFO_RD_DATA			0x02ec
+
+/* EDID DDC Segment Pointer, default value: 0x00 */
+#define REG_EDID_START_EXT			0x02ed
+
+/* TX IP BIST CNTL and Status, default value: 0x00 */
+#define REG_TX_IP_BIST_CNTLSTA			0x02f2
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_QUARTER_CLK_SEL BIT(6)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_DONE	BIT(5)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_ON	BIT(4)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_RUN	BIT(3)
+#define BIT_TX_IP_BIST_CNTLSTA_TXCLK_HALF_SEL	BIT(2)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_EN	BIT(1)
+#define BIT_TX_IP_BIST_CNTLSTA_TXBIST_SEL	BIT(0)
+
+/* TX IP BIST INST LOW, default value: 0x00 */
+#define REG_TX_IP_BIST_INST_LOW			0x02f3
+#define REG_TX_IP_BIST_INST_HIGH		0x02f4
+
+/* TX IP BIST PATTERN LOW, default value: 0x00 */
+#define REG_TX_IP_BIST_PAT_LOW			0x02f5
+#define REG_TX_IP_BIST_PAT_HIGH			0x02f6
+
+/* TX IP BIST CONFIGURE LOW, default value: 0x00 */
+#define REG_TX_IP_BIST_CONF_LOW			0x02f7
+#define REG_TX_IP_BIST_CONF_HIGH		0x02f8
+
+/* E-MSC General Control, default value: 0x80 */
+#define REG_GENCTL				0x0300
+#define BIT_GENCTL_SPEC_TRANS_DIS		BIT(7)
+#define BIT_GENCTL_DIS_XMIT_ERR_STATE		BIT(6)
+#define BIT_GENCTL_SPI_MISO_EDGE		BIT(5)
+#define BIT_GENCTL_SPI_MOSI_EDGE		BIT(4)
+#define BIT_GENCTL_CLR_EMSC_RFIFO		BIT(3)
+#define BIT_GENCTL_CLR_EMSC_XFIFO		BIT(2)
+#define BIT_GENCTL_START_TRAIN_SEQ		BIT(1)
+#define BIT_GENCTL_EMSC_EN			BIT(0)
+
+/* E-MSC Comma ErrorCNT, default value: 0x03 */
+#define REG_COMMECNT				0x0305
+#define BIT_COMMECNT_I2C_TO_EMSC_EN		BIT(7)
+#define MSK_COMMECNT_COMMA_CHAR_ERR_CNT		0x0f
+
+/* E-MSC RFIFO ByteCnt, default value: 0x00 */
+#define REG_EMSCRFIFOBCNTL			0x031a
+#define REG_EMSCRFIFOBCNTH			0x031b
+
+/* SPI Burst Cnt Status, default value: 0x00 */
+#define REG_SPIBURSTCNT				0x031e
+
+/* SPI Burst Status and SWRST, default value: 0x00 */
+#define REG_SPIBURSTSTAT			0x0322
+#define BIT_SPIBURSTSTAT_SPI_HDCPRST		BIT(7)
+#define BIT_SPIBURSTSTAT_SPI_CBUSRST		BIT(6)
+#define BIT_SPIBURSTSTAT_SPI_SRST		BIT(5)
+#define BIT_SPIBURSTSTAT_EMSC_NORMAL_MODE	BIT(0)
+
+/* E-MSC 1st Interrupt, default value: 0x00 */
+#define REG_EMSCINTR				0x0323
+#define BIT_EMSCINTR_EMSC_XFIFO_EMPTY		BIT(7)
+#define BIT_EMSCINTR_EMSC_XMIT_ACK_TOUT		BIT(6)
+#define BIT_EMSCINTR_EMSC_RFIFO_READ_ERR	BIT(5)
+#define BIT_EMSCINTR_EMSC_XFIFO_WRITE_ERR	BIT(4)
+#define BIT_EMSCINTR_EMSC_COMMA_CHAR_ERR	BIT(3)
+#define BIT_EMSCINTR_EMSC_XMIT_DONE		BIT(2)
+#define BIT_EMSCINTR_EMSC_XMIT_GNT_TOUT		BIT(1)
+#define BIT_EMSCINTR_SPI_DVLD		BIT(0)
+
+/* E-MSC Interrupt Mask, default value: 0x00 */
+#define REG_EMSCINTRMASK			0x0324
+
+/* I2C E-MSC XMIT FIFO Write Port, default value: 0x00 */
+#define REG_EMSC_XMIT_WRITE_PORT		0x032a
+
+/* I2C E-MSC RCV FIFO Write Port, default value: 0x00 */
+#define REG_EMSC_RCV_READ_PORT			0x032b
+
+/* E-MSC 2nd Interrupt, default value: 0x00 */
+#define REG_EMSCINTR1				0x032c
+#define BIT_EMSCINTR1_EMSC_TRAINING_COMMA_ERR	BIT(0)
+
+/* E-MSC Interrupt Mask, default value: 0x00 */
+#define REG_EMSCINTRMASK1			0x032d
+#define BIT_EMSCINTRMASK1_EMSC_INTRMASK1_0	BIT(0)
+
+/* MHL Top Ctl, default value: 0x00 */
+#define REG_MHL_TOP_CTL				0x0330
+#define BIT_MHL_TOP_CTL_MHL3_DOC_SEL		BIT(7)
+#define BIT_MHL_TOP_CTL_MHL_PP_SEL		BIT(6)
+#define MSK_MHL_TOP_CTL_IF_TIMING_CTL		0x03
+
+/* MHL DataPath 1st Ctl, default value: 0xbc */
+#define REG_MHL_DP_CTL0				0x0331
+#define BIT_MHL_DP_CTL0_DP_OE			BIT(7)
+#define BIT_MHL_DP_CTL0_TX_OE_OVR		BIT(6)
+#define MSK_MHL_DP_CTL0_TX_OE			0x3f
+
+/* MHL DataPath 2nd Ctl, default value: 0xbb */
+#define REG_MHL_DP_CTL1				0x0332
+#define MSK_MHL_DP_CTL1_CK_SWING_CTL		0xf0
+#define MSK_MHL_DP_CTL1_DT_SWING_CTL		0x0f
+
+/* MHL DataPath 3rd Ctl, default value: 0x2f */
+#define REG_MHL_DP_CTL2				0x0333
+#define BIT_MHL_DP_CTL2_CLK_BYPASS_EN		BIT(7)
+#define MSK_MHL_DP_CTL2_DAMP_TERM_SEL		0x30
+#define MSK_MHL_DP_CTL2_CK_TERM_SEL		0x0c
+#define MSK_MHL_DP_CTL2_DT_TERM_SEL		0x03
+
+/* MHL DataPath 4th Ctl, default value: 0x48 */
+#define REG_MHL_DP_CTL3				0x0334
+#define MSK_MHL_DP_CTL3_DT_DRV_VNBC_CTL		0xf0
+#define MSK_MHL_DP_CTL3_DT_DRV_VNB_CTL		0x0f
+
+/* MHL DataPath 5th Ctl, default value: 0x48 */
+#define REG_MHL_DP_CTL4				0x0335
+#define MSK_MHL_DP_CTL4_CK_DRV_VNBC_CTL		0xf0
+#define MSK_MHL_DP_CTL4_CK_DRV_VNB_CTL		0x0f
+
+/* MHL DataPath 6th Ctl, default value: 0x3f */
+#define REG_MHL_DP_CTL5				0x0336
+#define BIT_MHL_DP_CTL5_RSEN_EN_OVR		BIT(7)
+#define BIT_MHL_DP_CTL5_RSEN_EN			BIT(6)
+#define MSK_MHL_DP_CTL5_DAMP_TERM_VGS_CTL	0x30
+#define MSK_MHL_DP_CTL5_CK_TERM_VGS_CTL		0x0c
+#define MSK_MHL_DP_CTL5_DT_TERM_VGS_CTL		0x03
+
+/* MHL PLL 1st Ctl, default value: 0x05 */
+#define REG_MHL_PLL_CTL0			0x0337
+#define BIT_MHL_PLL_CTL0_AUD_CLK_EN		BIT(7)
+
+#define MSK_MHL_PLL_CTL0_AUD_CLK_RATIO		0x70
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_10	0x70
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_6	0x60
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_4	0x50
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_2	0x40
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_5	0x30
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_3	0x20
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_2_PRIME 0x10
+#define VAL_MHL_PLL_CTL0_AUD_CLK_RATIO_5_1	0x00
+
+#define MSK_MHL_PLL_CTL0_HDMI_CLK_RATIO		0x0c
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_4X	0x0c
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_2X	0x08
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X	0x04
+#define VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_HALF_X	0x00
+
+#define BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL	BIT(1)
+#define BIT_MHL_PLL_CTL0_ZONE_MASK_OE		BIT(0)
+
+/* MHL PLL 3rd Ctl, default value: 0x80 */
+#define REG_MHL_PLL_CTL2			0x0339
+#define BIT_MHL_PLL_CTL2_CLKDETECT_EN		BIT(7)
+#define BIT_MHL_PLL_CTL2_MEAS_FVCO		BIT(3)
+#define BIT_MHL_PLL_CTL2_PLL_FAST_LOCK		BIT(2)
+#define MSK_MHL_PLL_CTL2_PLL_LF_SEL		0x03
+
+/* MHL CBUS 1st Ctl, default value: 0x12 */
+#define REG_MHL_CBUS_CTL0			0x0340
+#define BIT_MHL_CBUS_CTL0_CBUS_RGND_TEST_MODE	BIT(7)
+
+#define MSK_MHL_CBUS_CTL0_CBUS_RGND_VTH_CTL	0x30
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_734	0x00
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_747	0x10
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_740	0x20
+#define VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_754	0x30
+
+#define MSK_MHL_CBUS_CTL0_CBUS_RES_TEST_SEL	0x0c
+
+#define MSK_MHL_CBUS_CTL0_CBUS_DRV_SEL		0x03
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_WEAKEST	0x00
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_WEAK	0x01
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONG	0x02
+#define VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONGEST 0x03
+
+/* MHL CBUS 2nd Ctl, default value: 0x03 */
+#define REG_MHL_CBUS_CTL1			0x0341
+#define MSK_MHL_CBUS_CTL1_CBUS_RGND_RES_CTL	0x07
+#define VAL_MHL_CBUS_CTL1_0888_OHM		0x00
+#define VAL_MHL_CBUS_CTL1_1115_OHM		0x04
+#define VAL_MHL_CBUS_CTL1_1378_OHM		0x07
+
+/* MHL CoC 1st Ctl, default value: 0xc3 */
+#define REG_MHL_COC_CTL0			0x0342
+#define BIT_MHL_COC_CTL0_COC_BIAS_EN		BIT(7)
+#define MSK_MHL_COC_CTL0_COC_BIAS_CTL		0x70
+#define MSK_MHL_COC_CTL0_COC_TERM_CTL		0x07
+
+/* MHL CoC 2nd Ctl, default value: 0x87 */
+#define REG_MHL_COC_CTL1			0x0343
+#define BIT_MHL_COC_CTL1_COC_EN			BIT(7)
+#define MSK_MHL_COC_CTL1_COC_DRV_CTL		0x3f
+
+/* MHL CoC 4th Ctl, default value: 0x00 */
+#define REG_MHL_COC_CTL3			0x0345
+#define BIT_MHL_COC_CTL3_COC_AECHO_EN		BIT(0)
+
+/* MHL CoC 5th Ctl, default value: 0x28 */
+#define REG_MHL_COC_CTL4			0x0346
+#define MSK_MHL_COC_CTL4_COC_IF_CTL		0xf0
+#define MSK_MHL_COC_CTL4_COC_SLEW_CTL		0x0f
+
+/* MHL CoC 6th Ctl, default value: 0x0d */
+#define REG_MHL_COC_CTL5			0x0347
+
+/* MHL DoC 1st Ctl, default value: 0x18 */
+#define REG_MHL_DOC_CTL0			0x0349
+#define BIT_MHL_DOC_CTL0_DOC_RXDATA_EN		BIT(7)
+#define MSK_MHL_DOC_CTL0_DOC_DM_TERM		0x38
+#define MSK_MHL_DOC_CTL0_DOC_OPMODE		0x06
+#define BIT_MHL_DOC_CTL0_DOC_RXBIAS_EN		BIT(0)
+
+/* MHL DataPath 7th Ctl, default value: 0x2a */
+#define REG_MHL_DP_CTL6				0x0350
+#define BIT_MHL_DP_CTL6_DP_TAP2_SGN		BIT(5)
+#define BIT_MHL_DP_CTL6_DP_TAP2_EN		BIT(4)
+#define BIT_MHL_DP_CTL6_DP_TAP1_SGN		BIT(3)
+#define BIT_MHL_DP_CTL6_DP_TAP1_EN		BIT(2)
+#define BIT_MHL_DP_CTL6_DT_PREDRV_FEEDCAP_EN	BIT(1)
+#define BIT_MHL_DP_CTL6_DP_PRE_POST_SEL		BIT(0)
+
+/* MHL DataPath 8th Ctl, default value: 0x06 */
+#define REG_MHL_DP_CTL7				0x0351
+#define MSK_MHL_DP_CTL7_DT_DRV_VBIAS_CASCTL	0xf0
+#define MSK_MHL_DP_CTL7_DT_DRV_IREF_CTL		0x0f
+
+/* Tx Zone Ctl1, default value: 0x00 */
+#define REG_TX_ZONE_CTL1			0x0361
+#define VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE	0x08
+
+/* MHL3 Tx Zone Ctl, default value: 0x00 */
+#define REG_MHL3_TX_ZONE_CTL			0x0364
+#define BIT_MHL3_TX_ZONE_CTL_MHL2_INTPLT_ZONE_MANU_EN BIT(7)
+#define MSK_MHL3_TX_ZONE_CTL_MHL3_TX_ZONE	0x03
+
+#define MSK_TX_ZONE_CTL3_TX_ZONE		0x03
+#define VAL_TX_ZONE_CTL3_TX_ZONE_6GBPS		0x00
+#define VAL_TX_ZONE_CTL3_TX_ZONE_3GBPS		0x01
+#define VAL_TX_ZONE_CTL3_TX_ZONE_1_5GBPS	0x02
+
+/* HDCP Polling Control and Status, default value: 0x70 */
+#define REG_HDCP2X_POLL_CS			0x0391
+
+#define BIT_HDCP2X_POLL_CS_HDCP2X_MSG_SZ_CLR_OPTION BIT(6)
+#define BIT_HDCP2X_POLL_CS_HDCP2X_RPT_READY_CLR_OPTION BIT(5)
+#define BIT_HDCP2X_POLL_CS_HDCP2X_REAUTH_REQ_CLR_OPTION BIT(4)
+#define MSK_HDCP2X_POLL_CS_			0x0c
+#define BIT_HDCP2X_POLL_CS_HDCP2X_DIS_POLL_GNT	BIT(1)
+#define BIT_HDCP2X_POLL_CS_HDCP2X_DIS_POLL_EN	BIT(0)
+
+/* HDCP Interrupt 0, default value: 0x00 */
+#define REG_HDCP2X_INTR0			0x0398
+
+/* HDCP Interrupt 0 Mask, default value: 0x00 */
+#define REG_HDCP2X_INTR0_MASK			0x0399
+
+/* HDCP General Control 0, default value: 0x02 */
+#define REG_HDCP2X_CTRL_0			0x03a0
+#define BIT_HDCP2X_CTRL_0_HDCP2X_ENCRYPT_EN	BIT(7)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_POLINT_SEL	BIT(6)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_POLINT_OVR	BIT(5)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_PRECOMPUTE	BIT(4)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_HDMIMODE	BIT(3)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_REPEATER	BIT(2)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_HDCPTX		BIT(1)
+#define BIT_HDCP2X_CTRL_0_HDCP2X_EN		BIT(0)
+
+/* HDCP General Control 1, default value: 0x08 */
+#define REG_HDCP2X_CTRL_1			0x03a1
+#define MSK_HDCP2X_CTRL_1_HDCP2X_REAUTH_MSK_3_0	0xf0
+#define BIT_HDCP2X_CTRL_1_HDCP2X_HPD_SW		BIT(3)
+#define BIT_HDCP2X_CTRL_1_HDCP2X_HPD_OVR	BIT(2)
+#define BIT_HDCP2X_CTRL_1_HDCP2X_CTL3MSK	BIT(1)
+#define BIT_HDCP2X_CTRL_1_HDCP2X_REAUTH_SW	BIT(0)
+
+/* HDCP Misc Control, default value: 0x00 */
+#define REG_HDCP2X_MISC_CTRL			0x03a5
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_XFER_START BIT(4)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_WR_START BIT(3)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_SMNG_WR	BIT(2)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_RCVID_RD_START BIT(1)
+#define BIT_HDCP2X_MISC_CTRL_HDCP2X_RPT_RCVID_RD	BIT(0)
+
+/* HDCP RPT SMNG K, default value: 0x00 */
+#define REG_HDCP2X_RPT_SMNG_K			0x03a6
+
+/* HDCP RPT SMNG In, default value: 0x00 */
+#define REG_HDCP2X_RPT_SMNG_IN			0x03a7
+
+/* HDCP Auth Status, default value: 0x00 */
+#define REG_HDCP2X_AUTH_STAT			0x03aa
+
+/* HDCP RPT RCVID Out, default value: 0x00 */
+#define REG_HDCP2X_RPT_RCVID_OUT		0x03ac
+
+/* HDCP TP1, default value: 0x62 */
+#define REG_HDCP2X_TP1				0x03b4
+
+/* HDCP GP Out 0, default value: 0x00 */
+#define REG_HDCP2X_GP_OUT0			0x03c7
+
+/* HDCP Repeater RCVR ID 0, default value: 0x00 */
+#define REG_HDCP2X_RPT_RCVR_ID0			0x03d1
+
+/* HDCP DDCM Status, default value: 0x00 */
+#define REG_HDCP2X_DDCM_STS			0x03d8
+#define MSK_HDCP2X_DDCM_STS_HDCP2X_DDCM_ERR_STS_3_0 0xf0
+#define MSK_HDCP2X_DDCM_STS_HDCP2X_DDCM_CTL_CS_3_0 0x0f
+
+/* HDMI2MHL3 Control, default value: 0x0a */
+#define REG_M3_CTRL				0x03e0
+#define BIT_M3_CTRL_H2M_SWRST			BIT(4)
+#define BIT_M3_CTRL_SW_MHL3_SEL			BIT(3)
+#define BIT_M3_CTRL_M3AV_EN			BIT(2)
+#define BIT_M3_CTRL_ENC_TMDS			BIT(1)
+#define BIT_M3_CTRL_MHL3_MASTER_EN		BIT(0)
+
+#define VAL_M3_CTRL_MHL1_2_VALUE (BIT_M3_CTRL_SW_MHL3_SEL \
+				  | BIT_M3_CTRL_ENC_TMDS)
+#define VAL_M3_CTRL_MHL3_VALUE (BIT_M3_CTRL_SW_MHL3_SEL \
+				| BIT_M3_CTRL_M3AV_EN \
+				| BIT_M3_CTRL_ENC_TMDS \
+				| BIT_M3_CTRL_MHL3_MASTER_EN)
+
+/* HDMI2MHL3 Port0 Control, default value: 0x04 */
+#define REG_M3_P0CTRL				0x03e1
+#define BIT_M3_P0CTRL_MHL3_P0_HDCP_ENC_EN	BIT(4)
+#define BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN	BIT(3)
+#define BIT_M3_P0CTRL_MHL3_P0_HDCP_EN		BIT(2)
+#define BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED	BIT(1)
+#define BIT_M3_P0CTRL_MHL3_P0_PORT_EN		BIT(0)
+
+#define REG_M3_POSTM				0x03e2
+#define MSK_M3_POSTM_RRP_DECODE			0xf8
+#define MSK_M3_POSTM_MHL3_P0_STM_ID		0x07
+
+/* HDMI2MHL3 Scramble Control, default value: 0x41 */
+#define REG_M3_SCTRL				0x03e6
+#define MSK_M3_SCTRL_MHL3_SR_LENGTH		0xf0
+#define BIT_M3_SCTRL_MHL3_SCRAMBLER_EN		BIT(0)
+
+/* HSIC Div Ctl, default value: 0x05 */
+#define REG_DIV_CTL_MAIN			0x03f2
+#define MSK_DIV_CTL_MAIN_PRE_DIV_CTL_MAIN	0x1c
+#define MSK_DIV_CTL_MAIN_FB_DIV_CTL_MAIN	0x03
+
+/* MHL Capability 1st Byte, default value: 0x00 */
+#define REG_MHL_DEVCAP_0			0x0400
+
+/* MHL Interrupt 1st Byte, default value: 0x00 */
+#define REG_MHL_INT_0				0x0420
+
+/* Device Status 1st byte, default value: 0x00 */
+#define REG_MHL_STAT_0				0x0430
+
+/* CBUS Scratch Pad 1st Byte, default value: 0x00 */
+#define REG_MHL_SCRPAD_0			0x0440
+
+/* MHL Extended Capability 1st Byte, default value: 0x00 */
+#define REG_MHL_EXTDEVCAP_0			0x0480
+
+/* Device Extended Status 1st byte, default value: 0x00 */
+#define REG_MHL_EXTSTAT_0			0x0490
+
+/* TPI DTD Byte2, default value: 0x00 */
+#define REG_TPI_DTD_B2				0x0602
+
+#define VAL_TPI_QUAN_RANGE_LIMITED		0x01
+#define VAL_TPI_QUAN_RANGE_FULL			0x02
+#define VAL_TPI_FORMAT_RGB			0x00
+#define VAL_TPI_FORMAT_YCBCR444			0x01
+#define VAL_TPI_FORMAT_YCBCR422			0x02
+#define VAL_TPI_FORMAT_INTERNAL_RGB		0x03
+#define VAL_TPI_FORMAT(_fmt, _qr) \
+		(VAL_TPI_FORMAT_##_fmt | (VAL_TPI_QUAN_RANGE_##_qr << 2))
+
+/* Input Format, default value: 0x00 */
+#define REG_TPI_INPUT				0x0609
+#define BIT_TPI_INPUT_EXTENDEDBITMODE		BIT(7)
+#define BIT_TPI_INPUT_ENDITHER			BIT(6)
+#define MSK_TPI_INPUT_INPUT_QUAN_RANGE		0x0c
+#define MSK_TPI_INPUT_INPUT_FORMAT		0x03
+
+/* Output Format, default value: 0x00 */
+#define REG_TPI_OUTPUT				0x060a
+#define BIT_TPI_OUTPUT_CSCMODE709		BIT(4)
+#define MSK_TPI_OUTPUT_OUTPUT_QUAN_RANGE	0x0c
+#define MSK_TPI_OUTPUT_OUTPUT_FORMAT		0x03
+
+/* TPI AVI Check Sum, default value: 0x00 */
+#define REG_TPI_AVI_CHSUM			0x060c
+
+/* TPI System Control, default value: 0x00 */
+#define REG_TPI_SC				0x061a
+#define BIT_TPI_SC_TPI_UPDATE_FLG		BIT(7)
+#define BIT_TPI_SC_TPI_REAUTH_CTL		BIT(6)
+#define BIT_TPI_SC_TPI_OUTPUT_MODE_1		BIT(5)
+#define BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN	BIT(4)
+#define BIT_TPI_SC_TPI_AV_MUTE			BIT(3)
+#define BIT_TPI_SC_DDC_GPU_REQUEST		BIT(2)
+#define BIT_TPI_SC_DDC_TPI_SW			BIT(1)
+#define BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI	BIT(0)
+
+/* TPI COPP Query Data, default value: 0x00 */
+#define REG_TPI_COPP_DATA1			0x0629
+#define BIT_TPI_COPP_DATA1_COPP_GPROT		BIT(7)
+#define BIT_TPI_COPP_DATA1_COPP_LPROT		BIT(6)
+#define MSK_TPI_COPP_DATA1_COPP_LINK_STATUS	0x30
+#define VAL_TPI_COPP_LINK_STATUS_NORMAL		0x00
+#define VAL_TPI_COPP_LINK_STATUS_LINK_LOST	0x10
+#define VAL_TPI_COPP_LINK_STATUS_RENEGOTIATION_REQ 0x20
+#define VAL_TPI_COPP_LINK_STATUS_LINK_SUSPENDED	0x30
+#define BIT_TPI_COPP_DATA1_COPP_HDCP_REP	BIT(3)
+#define BIT_TPI_COPP_DATA1_COPP_CONNTYPE_0	BIT(2)
+#define BIT_TPI_COPP_DATA1_COPP_PROTYPE		BIT(1)
+#define BIT_TPI_COPP_DATA1_COPP_CONNTYPE_1	BIT(0)
+
+/* TPI COPP Control Data, default value: 0x00 */
+#define REG_TPI_COPP_DATA2			0x062a
+#define BIT_TPI_COPP_DATA2_INTR_ENCRYPTION	BIT(5)
+#define BIT_TPI_COPP_DATA2_KSV_FORWARD		BIT(4)
+#define BIT_TPI_COPP_DATA2_INTERM_RI_CHECK_EN	BIT(3)
+#define BIT_TPI_COPP_DATA2_DOUBLE_RI_CHECK	BIT(2)
+#define BIT_TPI_COPP_DATA2_DDC_SHORT_RI_RD	BIT(1)
+#define BIT_TPI_COPP_DATA2_COPP_PROTLEVEL	BIT(0)
+
+/* TPI Interrupt Enable, default value: 0x00 */
+#define REG_TPI_INTR_EN				0x063c
+
+/* TPI Interrupt Status Low Byte, default value: 0x00 */
+#define REG_TPI_INTR_ST0			0x063d
+#define BIT_TPI_INTR_ST0_TPI_AUTH_CHNGE_STAT	BIT(7)
+#define BIT_TPI_INTR_ST0_TPI_V_RDY_STAT		BIT(6)
+#define BIT_TPI_INTR_ST0_TPI_COPP_CHNGE_STAT	BIT(5)
+#define BIT_TPI_INTR_ST0_KSV_FIFO_FIRST_STAT	BIT(3)
+#define BIT_TPI_INTR_ST0_READ_BKSV_BCAPS_DONE_STAT BIT(2)
+#define BIT_TPI_INTR_ST0_READ_BKSV_BCAPS_ERR_STAT BIT(1)
+#define BIT_TPI_INTR_ST0_READ_BKSV_ERR_STAT	BIT(0)
+
+/* TPI DS BCAPS Status, default value: 0x00 */
+#define REG_TPI_DS_BCAPS			0x0644
+
+/* TPI BStatus1, default value: 0x00 */
+#define REG_TPI_BSTATUS1			0x0645
+#define BIT_TPI_BSTATUS1_DS_DEV_EXCEED		BIT(7)
+#define MSK_TPI_BSTATUS1_DS_DEV_CNT		0x7f
+
+/* TPI BStatus2, default value: 0x10 */
+#define REG_TPI_BSTATUS2			0x0646
+#define MSK_TPI_BSTATUS2_DS_BSTATUS		0xe0
+#define BIT_TPI_BSTATUS2_DS_HDMI_MODE		BIT(4)
+#define BIT_TPI_BSTATUS2_DS_CASC_EXCEED		BIT(3)
+#define MSK_TPI_BSTATUS2_DS_DEPTH		0x07
+
+/* TPI HW Optimization Control #3, default value: 0x00 */
+#define REG_TPI_HW_OPT3				0x06bb
+#define BIT_TPI_HW_OPT3_DDC_DEBUG		BIT(7)
+#define BIT_TPI_HW_OPT3_RI_CHECK_SKIP		BIT(3)
+#define BIT_TPI_HW_OPT3_TPI_DDC_BURST_MODE	BIT(2)
+#define MSK_TPI_HW_OPT3_TPI_DDC_REQ_LEVEL	0x03
+
+/* TPI Info Frame Select, default value: 0x00 */
+#define REG_TPI_INFO_FSEL			0x06bf
+#define BIT_TPI_INFO_FSEL_TPI_INFO_EN		BIT(7)
+#define BIT_TPI_INFO_FSEL_TPI_INFO_RPT		BIT(6)
+#define BIT_TPI_INFO_FSEL_TPI_INFO_READ_FLAG	BIT(5)
+#define MSK_TPI_INFO_FSEL_TPI_INFO_SEL		0x07
+
+/* TPI Info Byte #0, default value: 0x00 */
+#define REG_TPI_INFO_B0				0x06c0
+
+/* CoC Status, default value: 0x00 */
+#define REG_COC_STAT_0				0x0700
+#define REG_COC_STAT_1				0x0701
+#define REG_COC_STAT_2				0x0702
+#define REG_COC_STAT_3				0x0703
+#define REG_COC_STAT_4				0x0704
+#define REG_COC_STAT_5				0x0705
+
+/* CoC 1st Ctl, default value: 0x40 */
+#define REG_COC_CTL0				0x0710
+
+/* CoC 2nd Ctl, default value: 0x0a */
+#define REG_COC_CTL1				0x0711
+#define MSK_COC_CTL1_COC_CTRL1_7_6		0xc0
+#define MSK_COC_CTL1_COC_CTRL1_5_0		0x3f
+
+/* CoC 3rd Ctl, default value: 0x14 */
+#define REG_COC_CTL2				0x0712
+#define MSK_COC_CTL2_COC_CTRL2_7_6		0xc0
+#define MSK_COC_CTL2_COC_CTRL2_5_0		0x3f
+
+/* CoC 4th Ctl, default value: 0x40 */
+#define REG_COC_CTL3				0x0713
+#define BIT_COC_CTL3_COC_CTRL3_7		BIT(7)
+#define MSK_COC_CTL3_COC_CTRL3_6_0		0x7f
+
+/* CoC 7th Ctl, default value: 0x00 */
+#define REG_COC_CTL6				0x0716
+#define BIT_COC_CTL6_COC_CTRL6_7		BIT(7)
+#define BIT_COC_CTL6_COC_CTRL6_6		BIT(6)
+#define MSK_COC_CTL6_COC_CTRL6_5_0		0x3f
+
+/* CoC 8th Ctl, default value: 0x06 */
+#define REG_COC_CTL7				0x0717
+#define BIT_COC_CTL7_COC_CTRL7_7		BIT(7)
+#define BIT_COC_CTL7_COC_CTRL7_6		BIT(6)
+#define BIT_COC_CTL7_COC_CTRL7_5		BIT(5)
+#define MSK_COC_CTL7_COC_CTRL7_4_3		0x18
+#define MSK_COC_CTL7_COC_CTRL7_2_0		0x07
+
+/* CoC 10th Ctl, default value: 0x00 */
+#define REG_COC_CTL9				0x0719
+
+/* CoC 11th Ctl, default value: 0x00 */
+#define REG_COC_CTLA				0x071a
+
+/* CoC 12th Ctl, default value: 0x00 */
+#define REG_COC_CTLB				0x071b
+
+/* CoC 13th Ctl, default value: 0x0f */
+#define REG_COC_CTLC				0x071c
+
+/* CoC 14th Ctl, default value: 0x0a */
+#define REG_COC_CTLD				0x071d
+#define BIT_COC_CTLD_COC_CTRLD_7		BIT(7)
+#define MSK_COC_CTLD_COC_CTRLD_6_0		0x7f
+
+/* CoC 15th Ctl, default value: 0x0a */
+#define REG_COC_CTLE				0x071e
+#define BIT_COC_CTLE_COC_CTRLE_7		BIT(7)
+#define MSK_COC_CTLE_COC_CTRLE_6_0		0x7f
+
+/* CoC 16th Ctl, default value: 0x00 */
+#define REG_COC_CTLF				0x071f
+#define MSK_COC_CTLF_COC_CTRLF_7_3		0xf8
+#define MSK_COC_CTLF_COC_CTRLF_2_0		0x07
+
+/* CoC 18th Ctl, default value: 0x32 */
+#define REG_COC_CTL11				0x0721
+#define MSK_COC_CTL11_COC_CTRL11_7_4		0xf0
+#define MSK_COC_CTL11_COC_CTRL11_3_0		0x0f
+
+/* CoC 21st Ctl, default value: 0x00 */
+#define REG_COC_CTL14				0x0724
+#define MSK_COC_CTL14_COC_CTRL14_7_4		0xf0
+#define MSK_COC_CTL14_COC_CTRL14_3_0		0x0f
+
+/* CoC 22nd Ctl, default value: 0x00 */
+#define REG_COC_CTL15				0x0725
+#define BIT_COC_CTL15_COC_CTRL15_7		BIT(7)
+#define MSK_COC_CTL15_COC_CTRL15_6_4		0x70
+#define MSK_COC_CTL15_COC_CTRL15_3_0		0x0f
+
+/* CoC Interrupt, default value: 0x00 */
+#define REG_COC_INTR				0x0726
+
+/* CoC Interrupt Mask, default value: 0x00 */
+#define REG_COC_INTR_MASK			0x0727
+#define BIT_COC_PLL_LOCK_STATUS_CHANGE		BIT(0)
+#define BIT_COC_CALIBRATION_DONE		BIT(1)
+
+/* CoC Misc Ctl, default value: 0x00 */
+#define REG_COC_MISC_CTL0			0x0728
+#define BIT_COC_MISC_CTL0_FSM_MON		BIT(7)
+
+/* CoC 24th Ctl, default value: 0x00 */
+#define REG_COC_CTL17				0x072a
+#define MSK_COC_CTL17_COC_CTRL17_7_4		0xf0
+#define MSK_COC_CTL17_COC_CTRL17_3_0		0x0f
+
+/* CoC 25th Ctl, default value: 0x00 */
+#define REG_COC_CTL18				0x072b
+#define MSK_COC_CTL18_COC_CTRL18_7_4		0xf0
+#define MSK_COC_CTL18_COC_CTRL18_3_0		0x0f
+
+/* CoC 26th Ctl, default value: 0x00 */
+#define REG_COC_CTL19				0x072c
+#define MSK_COC_CTL19_COC_CTRL19_7_4		0xf0
+#define MSK_COC_CTL19_COC_CTRL19_3_0		0x0f
+
+/* CoC 27th Ctl, default value: 0x00 */
+#define REG_COC_CTL1A				0x072d
+#define MSK_COC_CTL1A_COC_CTRL1A_7_2		0xfc
+#define MSK_COC_CTL1A_COC_CTRL1A_1_0		0x03
+
+/* DoC 9th Status, default value: 0x00 */
+#define REG_DOC_STAT_8				0x0740
+
+/* DoC 10th Status, default value: 0x00 */
+#define REG_DOC_STAT_9				0x0741
+
+/* DoC 5th CFG, default value: 0x00 */
+#define REG_DOC_CFG4				0x074e
+#define MSK_DOC_CFG4_DBG_STATE_DOC_FSM		0x0f
+
+/* DoC 1st Ctl, default value: 0x40 */
+#define REG_DOC_CTL0				0x0751
+
+/* DoC 7th Ctl, default value: 0x00 */
+#define REG_DOC_CTL6				0x0757
+#define BIT_DOC_CTL6_DOC_CTRL6_7		BIT(7)
+#define BIT_DOC_CTL6_DOC_CTRL6_6		BIT(6)
+#define MSK_DOC_CTL6_DOC_CTRL6_5_4		0x30
+#define MSK_DOC_CTL6_DOC_CTRL6_3_0		0x0f
+
+/* DoC 8th Ctl, default value: 0x00 */
+#define REG_DOC_CTL7				0x0758
+#define BIT_DOC_CTL7_DOC_CTRL7_7		BIT(7)
+#define BIT_DOC_CTL7_DOC_CTRL7_6		BIT(6)
+#define BIT_DOC_CTL7_DOC_CTRL7_5		BIT(5)
+#define MSK_DOC_CTL7_DOC_CTRL7_4_3		0x18
+#define MSK_DOC_CTL7_DOC_CTRL7_2_0		0x07
+
+/* DoC 9th Ctl, default value: 0x00 */
+#define REG_DOC_CTL8				0x076c
+#define BIT_DOC_CTL8_DOC_CTRL8_7		BIT(7)
+#define MSK_DOC_CTL8_DOC_CTRL8_6_4		0x70
+#define MSK_DOC_CTL8_DOC_CTRL8_3_2		0x0c
+#define MSK_DOC_CTL8_DOC_CTRL8_1_0		0x03
+
+/* DoC 10th Ctl, default value: 0x00 */
+#define REG_DOC_CTL9				0x076d
+
+/* DoC 11th Ctl, default value: 0x00 */
+#define REG_DOC_CTLA				0x076e
+
+/* DoC 15th Ctl, default value: 0x00 */
+#define REG_DOC_CTLE				0x0772
+#define BIT_DOC_CTLE_DOC_CTRLE_7		BIT(7)
+#define BIT_DOC_CTLE_DOC_CTRLE_6		BIT(6)
+#define MSK_DOC_CTLE_DOC_CTRLE_5_4		0x30
+#define MSK_DOC_CTLE_DOC_CTRLE_3_0		0x0f
+
+/* Interrupt Mask 1st, default value: 0x00 */
+#define REG_MHL_INT_0_MASK			0x0580
+
+/* Interrupt Mask 2nd, default value: 0x00 */
+#define REG_MHL_INT_1_MASK			0x0581
+
+/* Interrupt Mask 3rd, default value: 0x00 */
+#define REG_MHL_INT_2_MASK			0x0582
+
+/* Interrupt Mask 4th, default value: 0x00 */
+#define REG_MHL_INT_3_MASK			0x0583
+
+/* MDT Receive Time Out, default value: 0x00 */
+#define REG_MDT_RCV_TIMEOUT			0x0584
+
+/* MDT Transmit Time Out, default value: 0x00 */
+#define REG_MDT_XMIT_TIMEOUT			0x0585
+
+/* MDT Receive Control, default value: 0x00 */
+#define REG_MDT_RCV_CTRL			0x0586
+#define BIT_MDT_RCV_CTRL_MDT_RCV_EN		BIT(7)
+#define BIT_MDT_RCV_CTRL_MDT_DELAY_RCV_EN	BIT(6)
+#define BIT_MDT_RCV_CTRL_MDT_RFIFO_OVER_WR_EN	BIT(4)
+#define BIT_MDT_RCV_CTRL_MDT_XFIFO_OVER_WR_EN	BIT(3)
+#define BIT_MDT_RCV_CTRL_MDT_DISABLE		BIT(2)
+#define BIT_MDT_RCV_CTRL_MDT_RFIFO_CLR_ALL	BIT(1)
+#define BIT_MDT_RCV_CTRL_MDT_RFIFO_CLR_CUR	BIT(0)
+
+/* MDT Receive Read Port, default value: 0x00 */
+#define REG_MDT_RCV_READ_PORT			0x0587
+
+/* MDT Transmit Control, default value: 0x70 */
+#define REG_MDT_XMIT_CTRL			0x0588
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_EN		BIT(7)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_CMD_MERGE_EN	BIT(6)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_BURST_LEN BIT(5)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_AID	BIT(4)
+#define BIT_MDT_XMIT_CTRL_MDT_XMIT_SINGLE_RUN_EN BIT(3)
+#define BIT_MDT_XMIT_CTRL_MDT_CLR_ABORT_WAIT	BIT(2)
+#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_ALL	BIT(1)
+#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_CUR	BIT(0)
+
+/* MDT Receive WRITE Port, default value: 0x00 */
+#define REG_MDT_XMIT_WRITE_PORT			0x0589
+
+/* MDT RFIFO Status, default value: 0x00 */
+#define REG_MDT_RFIFO_STAT			0x058a
+#define MSK_MDT_RFIFO_STAT_MDT_RFIFO_CNT	0xe0
+#define MSK_MDT_RFIFO_STAT_MDT_RFIFO_CUR_BYTE_CNT 0x1f
+
+/* MDT XFIFO Status, default value: 0x80 */
+#define REG_MDT_XFIFO_STAT			0x058b
+#define MSK_MDT_XFIFO_STAT_MDT_XFIFO_LEVEL_AVAIL 0xe0
+#define BIT_MDT_XFIFO_STAT_MDT_XMIT_PRE_HS_EN	BIT(4)
+#define MSK_MDT_XFIFO_STAT_MDT_WRITE_BURST_LEN	0x0f
+
+/* MDT Interrupt 0, default value: 0x0c */
+#define REG_MDT_INT_0				0x058c
+#define BIT_MDT_RFIFO_DATA_RDY			BIT(0)
+#define BIT_MDT_IDLE_AFTER_HAWB_DISABLE		BIT(2)
+#define BIT_MDT_XFIFO_EMPTY			BIT(3)
+
+/* MDT Interrupt 0 Mask, default value: 0x00 */
+#define REG_MDT_INT_0_MASK			0x058d
+
+/* MDT Interrupt 1, default value: 0x00 */
+#define REG_MDT_INT_1				0x058e
+#define BIT_MDT_RCV_TIMEOUT			BIT(0)
+#define BIT_MDT_RCV_SM_ABORT_PKT_RCVD		BIT(1)
+#define BIT_MDT_RCV_SM_ERROR			BIT(2)
+#define BIT_MDT_XMIT_TIMEOUT			BIT(5)
+#define BIT_MDT_XMIT_SM_ABORT_PKT_RCVD		BIT(6)
+#define BIT_MDT_XMIT_SM_ERROR			BIT(7)
+
+/* MDT Interrupt 1 Mask, default value: 0x00 */
+#define REG_MDT_INT_1_MASK			0x058f
+
+/* CBUS Vendor ID, default value: 0x01 */
+#define REG_CBUS_VENDOR_ID			0x0590
+
+/* CBUS Connection Status, default value: 0x00 */
+#define REG_CBUS_STATUS				0x0591
+#define BIT_CBUS_STATUS_MHL_CABLE_PRESENT	BIT(4)
+#define BIT_CBUS_STATUS_MSC_HB_SUCCESS		BIT(3)
+#define BIT_CBUS_STATUS_CBUS_HPD		BIT(2)
+#define BIT_CBUS_STATUS_MHL_MODE		BIT(1)
+#define BIT_CBUS_STATUS_CBUS_CONNECTED		BIT(0)
+
+/* CBUS Interrupt 1st, default value: 0x00 */
+#define REG_CBUS_INT_0				0x0592
+#define BIT_CBUS_MSC_MT_DONE_NACK		BIT(7)
+#define BIT_CBUS_MSC_MR_SET_INT			BIT(6)
+#define BIT_CBUS_MSC_MR_WRITE_BURST		BIT(5)
+#define BIT_CBUS_MSC_MR_MSC_MSG			BIT(4)
+#define BIT_CBUS_MSC_MR_WRITE_STAT		BIT(3)
+#define BIT_CBUS_HPD_CHG			BIT(2)
+#define BIT_CBUS_MSC_MT_DONE			BIT(1)
+#define BIT_CBUS_CNX_CHG			BIT(0)
+
+/* CBUS Interrupt Mask 1st, default value: 0x00 */
+#define REG_CBUS_INT_0_MASK			0x0593
+
+/* CBUS Interrupt 2nd, default value: 0x00 */
+#define REG_CBUS_INT_1				0x0594
+#define BIT_CBUS_CMD_ABORT			BIT(6)
+#define BIT_CBUS_MSC_ABORT_RCVD			BIT(3)
+#define BIT_CBUS_DDC_ABORT			BIT(2)
+#define BIT_CBUS_CEC_ABORT			BIT(1)
+
+/* CBUS Interrupt Mask 2nd, default value: 0x00 */
+#define REG_CBUS_INT_1_MASK			0x0595
+
+/* CBUS DDC Abort Interrupt, default value: 0x00 */
+#define REG_DDC_ABORT_INT			0x0598
+
+/* CBUS DDC Abort Interrupt Mask, default value: 0x00 */
+#define REG_DDC_ABORT_INT_MASK			0x0599
+
+/* CBUS MSC Requester Abort Interrupt, default value: 0x00 */
+#define REG_MSC_MT_ABORT_INT			0x059a
+
+/* CBUS MSC Requester Abort Interrupt Mask, default value: 0x00 */
+#define REG_MSC_MT_ABORT_INT_MASK		0x059b
+
+/* CBUS MSC Responder Abort Interrupt, default value: 0x00 */
+#define REG_MSC_MR_ABORT_INT			0x059c
+
+/* CBUS MSC Responder Abort Interrupt Mask, default value: 0x00 */
+#define REG_MSC_MR_ABORT_INT_MASK		0x059d
+
+/* CBUS RX DISCOVERY interrupt, default value: 0x00 */
+#define REG_CBUS_RX_DISC_INT0			0x059e
+
+/* CBUS RX DISCOVERY Interrupt Mask, default value: 0x00 */
+#define REG_CBUS_RX_DISC_INT0_MASK		0x059f
+
+/* CBUS_Link_Layer Control #8, default value: 0x00 */
+#define REG_CBUS_LINK_CTRL_8			0x05a7
+
+/* MDT State Machine Status, default value: 0x00 */
+#define REG_MDT_SM_STAT				0x05b5
+#define MSK_MDT_SM_STAT_MDT_RCV_STATE		0xf0
+#define MSK_MDT_SM_STAT_MDT_XMIT_STATE		0x0f
+
+/* CBUS MSC command trigger, default value: 0x00 */
+#define REG_MSC_COMMAND_START			0x05b8
+#define BIT_MSC_COMMAND_START_DEBUG		BIT(5)
+#define BIT_MSC_COMMAND_START_WRITE_BURST	BIT(4)
+#define BIT_MSC_COMMAND_START_WRITE_STAT	BIT(3)
+#define BIT_MSC_COMMAND_START_READ_DEVCAP	BIT(2)
+#define BIT_MSC_COMMAND_START_MSC_MSG		BIT(1)
+#define BIT_MSC_COMMAND_START_PEER		BIT(0)
+
+/* CBUS MSC Command/Offset, default value: 0x00 */
+#define REG_MSC_CMD_OR_OFFSET			0x05b9
+
+/* CBUS MSC Transmit Data */
+#define REG_MSC_1ST_TRANSMIT_DATA		0x05ba
+#define REG_MSC_2ND_TRANSMIT_DATA		0x05bb
+
+/* CBUS MSC Requester Received Data */
+#define REG_MSC_MT_RCVD_DATA0			0x05bc
+#define REG_MSC_MT_RCVD_DATA1			0x05bd
+
+/* CBUS MSC Responder MSC_MSG Received Data */
+#define REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA	0x05bf
+#define REG_MSC_MR_MSC_MSG_RCVD_2ND_DATA	0x05c0
+
+/* CBUS MSC Heartbeat Control, default value: 0x27 */
+#define REG_MSC_HEARTBEAT_CTRL			0x05c4
+#define BIT_MSC_HEARTBEAT_CTRL_MSC_HB_EN	BIT(7)
+#define MSK_MSC_HEARTBEAT_CTRL_MSC_HB_FAIL_LIMIT 0x70
+#define MSK_MSC_HEARTBEAT_CTRL_MSC_HB_PERIOD_MSB 0x0f
+
+/* CBUS MSC Compatibility Control, default value: 0x02 */
+#define REG_CBUS_MSC_COMPAT_CTRL		0x05c7
+#define BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN	BIT(7)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_MSC_ON_CBUS BIT(6)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_DDC_ON_CBUS BIT(5)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_GET_DDC_ERRORCODE BIT(3)
+#define BIT_CBUS_MSC_COMPAT_CTRL_DISABLE_GET_VS1_ERRORCODE BIT(2)
+
+/* CBUS3 Converter Control, default value: 0x24 */
+#define REG_CBUS3_CNVT				0x05dc
+#define MSK_CBUS3_CNVT_CBUS3_RETRYLMT		0xf0
+#define MSK_CBUS3_CNVT_CBUS3_PEERTOUT_SEL	0x0c
+#define BIT_CBUS3_CNVT_TEARCBUS_EN		BIT(1)
+#define BIT_CBUS3_CNVT_CBUS3CNVT_EN		BIT(0)
+
+/* Discovery Control1, default value: 0x24 */
+#define REG_DISC_CTRL1				0x05e0
+#define BIT_DISC_CTRL1_CBUS_INTR_EN		BIT(7)
+#define BIT_DISC_CTRL1_HB_ONLY			BIT(6)
+#define MSK_DISC_CTRL1_DISC_ATT			0x30
+#define MSK_DISC_CTRL1_DISC_CYC			0x0c
+#define BIT_DISC_CTRL1_DISC_EN			BIT(0)
+
+#define VAL_PUP_OFF				0
+#define VAL_PUP_20K				1
+#define VAL_PUP_5K				2
+
+/* Discovery Control4, default value: 0x80 */
+#define REG_DISC_CTRL4				0x05e3
+#define MSK_DISC_CTRL4_CBUSDISC_PUP_SEL		0xc0
+#define MSK_DISC_CTRL4_CBUSIDLE_PUP_SEL		0x30
+#define VAL_DISC_CTRL4(pup_disc, pup_idle) (((pup_disc) << 6) | (pup_idle << 4))
+
+/* Discovery Control5, default value: 0x03 */
+#define REG_DISC_CTRL5				0x05e4
+#define BIT_DISC_CTRL5_DSM_OVRIDE		BIT(3)
+#define MSK_DISC_CTRL5_CBUSMHL_PUP_SEL		0x03
+
+/* Discovery Control8, default value: 0x81 */
+#define REG_DISC_CTRL8				0x05e7
+#define BIT_DISC_CTRL8_NOMHLINT_CLR_BYPASS	BIT(7)
+#define BIT_DISC_CTRL8_DELAY_CBUS_INTR_EN	BIT(0)
+
+/* Discovery Control9, default value: 0x54 */
+#define REG_DISC_CTRL9			0x05e8
+#define BIT_DISC_CTRL9_MHL3_RSEN_BYP		BIT(7)
+#define BIT_DISC_CTRL9_MHL3DISC_EN		BIT(6)
+#define BIT_DISC_CTRL9_WAKE_DRVFLT		BIT(4)
+#define BIT_DISC_CTRL9_NOMHL_EST		BIT(3)
+#define BIT_DISC_CTRL9_DISC_PULSE_PROCEED	BIT(2)
+#define BIT_DISC_CTRL9_WAKE_PULSE_BYPASS	BIT(1)
+#define BIT_DISC_CTRL9_VBUS_OUTPUT_CAPABILITY_SRC BIT(0)
+
+/* Discovery Status1, default value: 0x00 */
+#define REG_DISC_STAT1				0x05eb
+#define BIT_DISC_STAT1_PSM_OVRIDE		BIT(5)
+#define MSK_DISC_STAT1_DISC_SM			0x0f
+
+/* Discovery Status2, default value: 0x00 */
+#define REG_DISC_STAT2				0x05ec
+#define BIT_DISC_STAT2_CBUS_OE_POL		BIT(6)
+#define BIT_DISC_STAT2_CBUS_SATUS		BIT(5)
+#define BIT_DISC_STAT2_RSEN			BIT(4)
+
+#define MSK_DISC_STAT2_MHL_VRSN			0x0c
+#define VAL_DISC_STAT2_DEFAULT			0x00
+#define VAL_DISC_STAT2_MHL1_2			0x04
+#define VAL_DISC_STAT2_MHL3			0x08
+#define VAL_DISC_STAT2_RESERVED			0x0c
+
+#define MSK_DISC_STAT2_RGND			0x03
+#define VAL_RGND_OPEN				0x00
+#define VAL_RGND_2K				0x01
+#define VAL_RGND_1K				0x02
+#define VAL_RGND_SHORT				0x03
+
+/* Interrupt CBUS_reg1 INTR0, default value: 0x00 */
+#define REG_CBUS_DISC_INTR0			0x05ed
+#define BIT_RGND_READY_INT			BIT(6)
+#define BIT_CBUS_MHL12_DISCON_INT		BIT(5)
+#define BIT_CBUS_MHL3_DISCON_INT		BIT(4)
+#define BIT_NOT_MHL_EST_INT			BIT(3)
+#define BIT_MHL_EST_INT				BIT(2)
+#define BIT_MHL3_EST_INT			BIT(1)
+#define VAL_CBUS_MHL_DISCON (BIT_CBUS_MHL12_DISCON_INT \
+			    | BIT_CBUS_MHL3_DISCON_INT \
+			    | BIT_NOT_MHL_EST_INT)
+
+/* Interrupt CBUS_reg1 INTR0 Mask, default value: 0x00 */
+#define REG_CBUS_DISC_INTR0_MASK		0x05ee
+
+#endif /* __SIL_SII8620_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/tc358767.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/tc358767.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/tc358767.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/tc358767.c	2017-02-12 16:03:20.000000000 -0500
@@ -908,7 +908,7 @@ static int tc_main_link_setup(struct tc_
 			goto err_dpcd_read;
 
 		if (tmp[0] != tc->assr) {
-			dev_warn(dev, "Failed to switch display ASSR to %d, falling back to unscrambled mode\n",
+			dev_dbg(dev, "Failed to switch display ASSR to %d, falling back to unscrambled mode\n",
 				 tc->assr);
 			/* trying with disabled scrambler */
 			tc->link.scrambler_dis = 1;
@@ -1038,12 +1038,6 @@ err:
 	return ret;
 }
 
-static enum drm_connector_status
-tc_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void tc_bridge_pre_enable(struct drm_bridge *bridge)
 {
 	struct tc_data *tc = bridge_to_tc(bridge);
@@ -1168,7 +1162,6 @@ static const struct drm_connector_helper
 static const struct drm_connector_funcs tc_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = tc_connector_detect,
 	.destroy = drm_connector_cleanup,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/bridge/ti-tfp410.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/ti-tfp410.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/bridge/ti-tfp410.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/bridge/ti-tfp410.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2016 Texas Instruments
+ * Author: Jyri Sarha <jsarha@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+struct tfp410 {
+	struct drm_bridge	bridge;
+	struct drm_connector	connector;
+
+	struct i2c_adapter	*ddc;
+
+	struct device *dev;
+};
+
+static inline struct tfp410 *
+drm_bridge_to_tfp410(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct tfp410, bridge);
+}
+
+static inline struct tfp410 *
+drm_connector_to_tfp410(struct drm_connector *connector)
+{
+	return container_of(connector, struct tfp410, connector);
+}
+
+static int tfp410_get_modes(struct drm_connector *connector)
+{
+	struct tfp410 *dvi = drm_connector_to_tfp410(connector);
+	struct edid *edid;
+	int ret;
+
+	if (!dvi->ddc)
+		goto fallback;
+
+	edid = drm_get_edid(connector, dvi->ddc);
+	if (!edid) {
+		DRM_INFO("EDID read failed. Fallback to standard modes\n");
+		goto fallback;
+	}
+
+	drm_mode_connector_update_edid_property(connector, edid);
+
+	return drm_add_edid_modes(connector, edid);
+fallback:
+	/* No EDID, fallback on the XGA standard modes */
+	ret = drm_add_modes_noedid(connector, 1920, 1200);
+
+	/* And prefer a mode pretty much anything can handle */
+	drm_set_preferred_mode(connector, 1024, 768);
+
+	return ret;
+}
+
+static const struct drm_connector_helper_funcs tfp410_con_helper_funcs = {
+	.get_modes	= tfp410_get_modes,
+};
+
+static enum drm_connector_status
+tfp410_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct tfp410 *dvi = drm_connector_to_tfp410(connector);
+
+	if (dvi->ddc) {
+		if (drm_probe_ddc(dvi->ddc))
+			return connector_status_connected;
+		else
+			return connector_status_disconnected;
+	}
+
+	return connector_status_unknown;
+}
+
+static const struct drm_connector_funcs tfp410_con_funcs = {
+	.dpms			= drm_atomic_helper_connector_dpms,
+	.detect			= tfp410_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= drm_connector_cleanup,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static int tfp410_attach(struct drm_bridge *bridge)
+{
+	struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
+	int ret;
+
+	if (!bridge->encoder) {
+		dev_err(dvi->dev, "Missing encoder\n");
+		return -ENODEV;
+	}
+
+	drm_connector_helper_add(&dvi->connector,
+				 &tfp410_con_helper_funcs);
+	ret = drm_connector_init(bridge->dev, &dvi->connector,
+				 &tfp410_con_funcs, DRM_MODE_CONNECTOR_HDMIA);
+	if (ret) {
+		dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	drm_mode_connector_attach_encoder(&dvi->connector,
+					  bridge->encoder);
+
+	return 0;
+}
+
+static const struct drm_bridge_funcs tfp410_bridge_funcs = {
+	.attach		= tfp410_attach,
+};
+
+static int tfp410_get_connector_ddc(struct tfp410 *dvi)
+{
+	struct device_node *ep = NULL, *connector_node = NULL;
+	struct device_node *ddc_phandle = NULL;
+	int ret = 0;
+
+	/* port@1 is the connector node */
+	ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 1, -1);
+	if (!ep)
+		goto fail;
+
+	connector_node = of_graph_get_remote_port_parent(ep);
+	if (!connector_node)
+		goto fail;
+
+	ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0);
+	if (!ddc_phandle)
+		goto fail;
+
+	dvi->ddc = of_get_i2c_adapter_by_node(ddc_phandle);
+	if (dvi->ddc)
+		dev_info(dvi->dev, "Connector's ddc i2c bus found\n");
+	else
+		ret = -EPROBE_DEFER;
+
+fail:
+	of_node_put(ep);
+	of_node_put(connector_node);
+	of_node_put(ddc_phandle);
+	return ret;
+}
+
+static int tfp410_init(struct device *dev)
+{
+	struct tfp410 *dvi;
+	int ret;
+
+	if (!dev->of_node) {
+		dev_err(dev, "device-tree data is missing\n");
+		return -ENXIO;
+	}
+
+	dvi = devm_kzalloc(dev, sizeof(*dvi), GFP_KERNEL);
+	if (!dvi)
+		return -ENOMEM;
+	dev_set_drvdata(dev, dvi);
+
+	dvi->bridge.funcs = &tfp410_bridge_funcs;
+	dvi->bridge.of_node = dev->of_node;
+	dvi->dev = dev;
+
+	ret = tfp410_get_connector_ddc(dvi);
+	if (ret)
+		goto fail;
+
+	ret = drm_bridge_add(&dvi->bridge);
+	if (ret) {
+		dev_err(dev, "drm_bridge_add() failed: %d\n", ret);
+		goto fail;
+	}
+
+	return 0;
+fail:
+	i2c_put_adapter(dvi->ddc);
+	return ret;
+}
+
+static int tfp410_fini(struct device *dev)
+{
+	struct tfp410 *dvi = dev_get_drvdata(dev);
+
+	drm_bridge_remove(&dvi->bridge);
+
+	if (dvi->ddc)
+		i2c_put_adapter(dvi->ddc);
+
+	return 0;
+}
+
+static int tfp410_probe(struct platform_device *pdev)
+{
+	return tfp410_init(&pdev->dev);
+}
+
+static int tfp410_remove(struct platform_device *pdev)
+{
+	return tfp410_fini(&pdev->dev);
+}
+
+static const struct of_device_id tfp410_match[] = {
+	{ .compatible = "ti,tfp410" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tfp410_match);
+
+struct platform_driver tfp410_platform_driver = {
+	.probe	= tfp410_probe,
+	.remove	= tfp410_remove,
+	.driver	= {
+		.name		= "tfp410-bridge",
+		.of_match_table	= tfp410_match,
+	},
+};
+
+#if IS_ENABLED(CONFIG_I2C)
+/* There is currently no i2c functionality. */
+static int tfp410_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	int reg;
+
+	if (!client->dev.of_node ||
+	    of_property_read_u32(client->dev.of_node, "reg", &reg)) {
+		dev_err(&client->dev,
+			"Can't get i2c reg property from device-tree\n");
+		return -ENXIO;
+	}
+
+	return tfp410_init(&client->dev);
+}
+
+static int tfp410_i2c_remove(struct i2c_client *client)
+{
+	return tfp410_fini(&client->dev);
+}
+
+static const struct i2c_device_id tfp410_i2c_ids[] = {
+	{ "tfp410", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tfp410_i2c_ids);
+
+static struct i2c_driver tfp410_i2c_driver = {
+	.driver = {
+		.name	= "tfp410",
+		.of_match_table = of_match_ptr(tfp410_match),
+	},
+	.id_table	= tfp410_i2c_ids,
+	.probe		= tfp410_i2c_probe,
+	.remove		= tfp410_i2c_remove,
+};
+#endif /* IS_ENABLED(CONFIG_I2C) */
+
+static struct {
+	uint i2c:1;
+	uint platform:1;
+}  tfp410_registered_driver;
+
+static int __init tfp410_module_init(void)
+{
+	int ret;
+
+#if IS_ENABLED(CONFIG_I2C)
+	ret = i2c_add_driver(&tfp410_i2c_driver);
+	if (ret)
+		pr_err("%s: registering i2c driver failed: %d",
+		       __func__, ret);
+	else
+		tfp410_registered_driver.i2c = 1;
+#endif
+
+	ret = platform_driver_register(&tfp410_platform_driver);
+	if (ret)
+		pr_err("%s: registering platform driver failed: %d",
+		       __func__, ret);
+	else
+		tfp410_registered_driver.platform = 1;
+
+	if (tfp410_registered_driver.i2c ||
+	    tfp410_registered_driver.platform)
+		return 0;
+
+	return ret;
+}
+module_init(tfp410_module_init);
+
+static void __exit tfp410_module_exit(void)
+{
+#if IS_ENABLED(CONFIG_I2C)
+	if (tfp410_registered_driver.i2c)
+		i2c_del_driver(&tfp410_i2c_driver);
+#endif
+	if (tfp410_registered_driver.platform)
+		platform_driver_unregister(&tfp410_platform_driver);
+}
+module_exit(tfp410_module_exit);
+
+MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
+MODULE_DESCRIPTION("TI TFP410 DVI bridge driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -126,9 +126,7 @@ static const struct file_operations cirr
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = cirrus_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 };
 static struct drm_driver driver = {
 	.driver_features = DRIVER_MODESET | DRIVER_GEM,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -138,12 +138,12 @@ static int cirrusfb_create_object(struct
 {
 	struct drm_device *dev = afbdev->helper.dev;
 	struct cirrus_device *cdev = dev->dev_private;
-	u32 bpp, depth;
+	u32 bpp;
 	u32 size;
 	struct drm_gem_object *gobj;
-
 	int ret = 0;
-	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+
+	bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
 
 	if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
 				      bpp, mode_cmd->pitches[0]))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_main.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_main.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,10 +52,10 @@ cirrus_user_framebuffer_create(struct dr
 	struct cirrus_device *cdev = dev->dev_private;
 	struct drm_gem_object *obj;
 	struct cirrus_framebuffer *cirrus_fb;
+	u32 bpp;
 	int ret;
-	u32 bpp, depth;
 
-	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+	bpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0) * 8;
 
 	if (!cirrus_check_framebuffer(cdev, mode_cmd->width, mode_cmd->height,
 				      bpp, mode_cmd->pitches[0]))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_mode.c	2017-02-12 16:03:20.000000000 -0500
@@ -498,12 +498,6 @@ static struct drm_encoder *cirrus_connec
 	return NULL;
 }
 
-static enum drm_connector_status cirrus_vga_detect(struct drm_connector
-						   *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void cirrus_connector_destroy(struct drm_connector *connector)
 {
 	drm_connector_cleanup(connector);
@@ -517,7 +511,6 @@ static const struct drm_connector_helper
 
 static const struct drm_connector_funcs cirrus_vga_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
-	.detect = cirrus_vga_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = cirrus_connector_destroy,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/cirrus_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -230,6 +230,7 @@ struct ttm_bo_driver cirrus_bo_driver =
 	.ttm_tt_populate = cirrus_ttm_tt_populate,
 	.ttm_tt_unpopulate = cirrus_ttm_tt_unpopulate,
 	.init_mem_type = cirrus_bo_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = cirrus_bo_evict_flags,
 	.move = NULL,
 	.verify_access = cirrus_bo_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/cirrus/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/cirrus/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -7,3 +7,12 @@ config DRM_CIRRUS_QEMU
 	 This is a KMS driver for emulated cirrus device in qemu.
 	 It is *NOT* intended for real cirrus devices. This requires
 	 the modesetting userspace X.org driver.
+
+	 Cirrus is obsolete, the hardware was designed in the 90ies
+	 and can't keep up with todays needs.  More background:
+	 https://www.kraxel.org/blog/2014/10/qemu-using-cirrus-considered-harmful/
+
+	 Better alternatives are:
+	   - stdvga (DRM_BOCHS, qemu -vga std, default in qemu 2.2+)
+	   - qxl (DRM_QXL, qemu -vga qxl, works best with spice)
+	   - virtio (DRM_VIRTIO_GPU), qemu -vga virtio)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_atomic.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_atomic.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_atomic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_atomic.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,8 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_mode.h>
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_print.h>
+#include <linux/sync_file.h>
 
 #include "drm_crtc_internal.h"
 
@@ -74,6 +76,8 @@ EXPORT_SYMBOL(drm_atomic_state_default_r
 int
 drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
 {
+	kref_init(&state->ref);
+
 	/* TODO legacy paths should maybe do a better job about
 	 * setting this appropriately?
 	 */
@@ -215,22 +219,16 @@ void drm_atomic_state_clear(struct drm_a
 EXPORT_SYMBOL(drm_atomic_state_clear);
 
 /**
- * drm_atomic_state_free - free all memory for an atomic state
- * @state: atomic state to deallocate
+ * __drm_atomic_state_free - free all memory for an atomic state
+ * @ref: This atomic state to deallocate
  *
  * This frees all memory associated with an atomic state, including all the
  * per-object state for planes, crtcs and connectors.
  */
-void drm_atomic_state_free(struct drm_atomic_state *state)
+void __drm_atomic_state_free(struct kref *ref)
 {
-	struct drm_device *dev;
-	struct drm_mode_config *config;
-
-	if (!state)
-		return;
-
-	dev = state->dev;
-	config = &dev->mode_config;
+	struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
+	struct drm_mode_config *config = &state->dev->mode_config;
 
 	drm_atomic_state_clear(state);
 
@@ -243,7 +241,7 @@ void drm_atomic_state_free(struct drm_at
 		kfree(state);
 	}
 }
-EXPORT_SYMBOL(drm_atomic_state_free);
+EXPORT_SYMBOL(__drm_atomic_state_free);
 
 /**
  * drm_atomic_get_crtc_state - get crtc state
@@ -292,6 +290,23 @@ drm_atomic_get_crtc_state(struct drm_ato
 }
 EXPORT_SYMBOL(drm_atomic_get_crtc_state);
 
+static void set_out_fence_for_crtc(struct drm_atomic_state *state,
+				   struct drm_crtc *crtc, s32 __user *fence_ptr)
+{
+	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = fence_ptr;
+}
+
+static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
+					  struct drm_crtc *crtc)
+{
+	s32 __user *fence_ptr;
+
+	fence_ptr = state->crtcs[drm_crtc_index(crtc)].out_fence_ptr;
+	state->crtcs[drm_crtc_index(crtc)].out_fence_ptr = NULL;
+
+	return fence_ptr;
+}
+
 /**
  * drm_atomic_set_mode_for_crtc - set mode for CRTC
  * @state: the CRTC whose incoming state to update
@@ -496,6 +511,16 @@ int drm_atomic_crtc_set_property(struct
 					&replaced);
 		state->color_mgmt_changed |= replaced;
 		return ret;
+	} else if (property == config->prop_out_fence_ptr) {
+		s32 __user *fence_ptr = u64_to_user_ptr(val);
+
+		if (!fence_ptr)
+			return 0;
+
+		if (put_user(-1, fence_ptr))
+			return -EFAULT;
+
+		set_out_fence_for_crtc(state->state, crtc, fence_ptr);
 	} else if (crtc->funcs->atomic_set_property)
 		return crtc->funcs->atomic_set_property(crtc, state, property, val);
 	else
@@ -538,6 +563,8 @@ drm_atomic_crtc_get_property(struct drm_
 		*val = (state->ctm) ? state->ctm->base.id : 0;
 	else if (property == config->gamma_lut_property)
 		*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
+	else if (property == config->prop_out_fence_ptr)
+		*val = 0;
 	else if (crtc->funcs->atomic_get_property)
 		return crtc->funcs->atomic_get_property(crtc, state, property, val);
 	else
@@ -609,6 +636,28 @@ static int drm_atomic_crtc_check(struct
 	return 0;
 }
 
+static void drm_atomic_crtc_print_state(struct drm_printer *p,
+		const struct drm_crtc_state *state)
+{
+	struct drm_crtc *crtc = state->crtc;
+
+	drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name);
+	drm_printf(p, "\tenable=%d\n", state->enable);
+	drm_printf(p, "\tactive=%d\n", state->active);
+	drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed);
+	drm_printf(p, "\tmode_changed=%d\n", state->mode_changed);
+	drm_printf(p, "\tactive_changed=%d\n", state->active_changed);
+	drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed);
+	drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
+	drm_printf(p, "\tplane_mask=%x\n", state->plane_mask);
+	drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
+	drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
+	drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
+
+	if (crtc->funcs->atomic_print_state)
+		crtc->funcs->atomic_print_state(p, state);
+}
+
 /**
  * drm_atomic_get_plane_state - get plane state
  * @state: global atomic state object
@@ -693,6 +742,17 @@ int drm_atomic_plane_set_property(struct
 		drm_atomic_set_fb_for_plane(state, fb);
 		if (fb)
 			drm_framebuffer_unreference(fb);
+	} else if (property == config->prop_in_fence_fd) {
+		if (state->fence)
+			return -EINVAL;
+
+		if (U642I64(val) == -1)
+			return 0;
+
+		state->fence = sync_file_get_fence(val);
+		if (!state->fence)
+			return -EINVAL;
+
 	} else if (property == config->prop_crtc_id) {
 		struct drm_crtc *crtc = drm_crtc_find(dev, val);
 		return drm_atomic_set_crtc_for_plane(state, crtc);
@@ -712,7 +772,9 @@ int drm_atomic_plane_set_property(struct
 		state->src_w = val;
 	} else if (property == config->prop_src_h) {
 		state->src_h = val;
-	} else if (property == config->rotation_property) {
+	} else if (property == plane->rotation_property) {
+		if (!is_power_of_2(val & DRM_ROTATE_MASK))
+			return -EINVAL;
 		state->rotation = val;
 	} else if (property == plane->zpos_property) {
 		state->zpos = val;
@@ -752,6 +814,8 @@ drm_atomic_plane_get_property(struct drm
 
 	if (property == config->prop_fb_id) {
 		*val = (state->fb) ? state->fb->base.id : 0;
+	} else if (property == config->prop_in_fence_fd) {
+		*val = -1;
 	} else if (property == config->prop_crtc_id) {
 		*val = (state->crtc) ? state->crtc->base.id : 0;
 	} else if (property == config->prop_crtc_x) {
@@ -770,7 +834,7 @@ drm_atomic_plane_get_property(struct drm
 		*val = state->src_w;
 	} else if (property == config->prop_src_h) {
 		*val = state->src_h;
-	} else if (property == config->rotation_property) {
+	} else if (property == plane->rotation_property) {
 		*val = state->rotation;
 	} else if (property == plane->zpos_property) {
 		*val = state->zpos;
@@ -840,9 +904,10 @@ static int drm_atomic_plane_check(struct
 	/* Check whether this plane supports the fb pixel format. */
 	ret = drm_plane_check_pixel_format(plane, state->fb->pixel_format);
 	if (ret) {
-		char *format_name = drm_get_format_name(state->fb->pixel_format);
-		DRM_DEBUG_ATOMIC("Invalid pixel format %s\n", format_name);
-		kfree(format_name);
+		struct drm_format_name_buf format_name;
+		DRM_DEBUG_ATOMIC("Invalid pixel format %s\n",
+		                 drm_get_format_name(state->fb->pixel_format,
+		                                     &format_name));
 		return ret;
 	}
 
@@ -883,6 +948,39 @@ static int drm_atomic_plane_check(struct
 	return 0;
 }
 
+static void drm_atomic_plane_print_state(struct drm_printer *p,
+		const struct drm_plane_state *state)
+{
+	struct drm_plane *plane = state->plane;
+	struct drm_rect src  = drm_plane_state_src(state);
+	struct drm_rect dest = drm_plane_state_dest(state);
+
+	drm_printf(p, "plane[%u]: %s\n", plane->base.id, plane->name);
+	drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
+	drm_printf(p, "\tfb=%u\n", state->fb ? state->fb->base.id : 0);
+	if (state->fb) {
+		struct drm_framebuffer *fb = state->fb;
+		int i, n = drm_format_num_planes(fb->pixel_format);
+		struct drm_format_name_buf format_name;
+
+		drm_printf(p, "\t\tformat=%s\n",
+		              drm_get_format_name(fb->pixel_format, &format_name));
+		drm_printf(p, "\t\t\tmodifier=0x%llx\n", fb->modifier);
+		drm_printf(p, "\t\tsize=%dx%d\n", fb->width, fb->height);
+		drm_printf(p, "\t\tlayers:\n");
+		for (i = 0; i < n; i++) {
+			drm_printf(p, "\t\t\tpitch[%d]=%u\n", i, fb->pitches[i]);
+			drm_printf(p, "\t\t\toffset[%d]=%u\n", i, fb->offsets[i]);
+		}
+	}
+	drm_printf(p, "\tcrtc-pos=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&dest));
+	drm_printf(p, "\tsrc-pos=" DRM_RECT_FP_FMT "\n", DRM_RECT_FP_ARG(&src));
+	drm_printf(p, "\trotation=%x\n", state->rotation);
+
+	if (plane->funcs->atomic_print_state)
+		plane->funcs->atomic_print_state(p, state);
+}
+
 /**
  * drm_atomic_get_connector_state - get connector state
  * @state: global atomic state object
@@ -989,15 +1087,53 @@ int drm_atomic_connector_set_property(st
 		 * now?) atomic writes to DPMS property:
 		 */
 		return -EINVAL;
+	} else if (property == config->tv_select_subconnector_property) {
+		state->tv.subconnector = val;
+	} else if (property == config->tv_left_margin_property) {
+		state->tv.margins.left = val;
+	} else if (property == config->tv_right_margin_property) {
+		state->tv.margins.right = val;
+	} else if (property == config->tv_top_margin_property) {
+		state->tv.margins.top = val;
+	} else if (property == config->tv_bottom_margin_property) {
+		state->tv.margins.bottom = val;
+	} else if (property == config->tv_mode_property) {
+		state->tv.mode = val;
+	} else if (property == config->tv_brightness_property) {
+		state->tv.brightness = val;
+	} else if (property == config->tv_contrast_property) {
+		state->tv.contrast = val;
+	} else if (property == config->tv_flicker_reduction_property) {
+		state->tv.flicker_reduction = val;
+	} else if (property == config->tv_overscan_property) {
+		state->tv.overscan = val;
+	} else if (property == config->tv_saturation_property) {
+		state->tv.saturation = val;
+	} else if (property == config->tv_hue_property) {
+		state->tv.hue = val;
 	} else if (connector->funcs->atomic_set_property) {
 		return connector->funcs->atomic_set_property(connector,
 				state, property, val);
 	} else {
 		return -EINVAL;
 	}
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_atomic_connector_set_property);
 
+static void drm_atomic_connector_print_state(struct drm_printer *p,
+		const struct drm_connector_state *state)
+{
+	struct drm_connector *connector = state->connector;
+
+	drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);
+	drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
+
+	if (connector->funcs->atomic_print_state)
+		connector->funcs->atomic_print_state(p, state);
+}
+
 /**
  * drm_atomic_connector_get_property - get property value from connector state
  * @connector: the drm connector to set a property on
@@ -1025,6 +1161,30 @@ drm_atomic_connector_get_property(struct
 		*val = (state->crtc) ? state->crtc->base.id : 0;
 	} else if (property == config->dpms_property) {
 		*val = connector->dpms;
+	} else if (property == config->tv_select_subconnector_property) {
+		*val = state->tv.subconnector;
+	} else if (property == config->tv_left_margin_property) {
+		*val = state->tv.margins.left;
+	} else if (property == config->tv_right_margin_property) {
+		*val = state->tv.margins.right;
+	} else if (property == config->tv_top_margin_property) {
+		*val = state->tv.margins.top;
+	} else if (property == config->tv_bottom_margin_property) {
+		*val = state->tv.margins.bottom;
+	} else if (property == config->tv_mode_property) {
+		*val = state->tv.mode;
+	} else if (property == config->tv_brightness_property) {
+		*val = state->tv.brightness;
+	} else if (property == config->tv_contrast_property) {
+		*val = state->tv.contrast;
+	} else if (property == config->tv_flicker_reduction_property) {
+		*val = state->tv.flicker_reduction;
+	} else if (property == config->tv_overscan_property) {
+		*val = state->tv.overscan;
+	} else if (property == config->tv_saturation_property) {
+		*val = state->tv.saturation;
+	} else if (property == config->tv_hue_property) {
+		*val = state->tv.hue;
 	} else if (connector->funcs->atomic_get_property) {
 		return connector->funcs->atomic_get_property(connector,
 				state, property, val);
@@ -1136,22 +1296,48 @@ void
 drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
 			    struct drm_framebuffer *fb)
 {
-	if (plane_state->fb)
-		drm_framebuffer_unreference(plane_state->fb);
-	if (fb)
-		drm_framebuffer_reference(fb);
-	plane_state->fb = fb;
-
 	if (fb)
 		DRM_DEBUG_ATOMIC("Set [FB:%d] for plane state %p\n",
 				 fb->base.id, plane_state);
 	else
 		DRM_DEBUG_ATOMIC("Set [NOFB] for plane state %p\n",
 				 plane_state);
+
+	drm_framebuffer_assign(&plane_state->fb, fb);
 }
 EXPORT_SYMBOL(drm_atomic_set_fb_for_plane);
 
 /**
+ * drm_atomic_set_fence_for_plane - set fence for plane
+ * @plane_state: atomic state object for the plane
+ * @fence: dma_fence to use for the plane
+ *
+ * Helper to setup the plane_state fence in case it is not set yet.
+ * By using this drivers doesn't need to worry if the user choose
+ * implicit or explicit fencing.
+ *
+ * This function will not set the fence to the state if it was set
+ * via explicit fencing interfaces on the atomic ioctl. It will
+ * all drope the reference to the fence as we not storing it
+ * anywhere.
+ *
+ * Otherwise, if plane_state->fence is not set this function we
+ * just set it with the received implict fence.
+ */
+void
+drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
+			       struct dma_fence *fence)
+{
+	if (plane_state->fence) {
+		dma_fence_put(fence);
+		return;
+	}
+
+	plane_state->fence = fence;
+}
+EXPORT_SYMBOL(drm_atomic_set_fence_for_plane);
+
+/**
  * drm_atomic_set_crtc_for_connector - set crtc for connector
  * @conn_state: atomic state object for the connector
  * @crtc: crtc to use for the connector
@@ -1462,16 +1648,107 @@ int drm_atomic_nonblocking_commit(struct
 }
 EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
 
+static void drm_atomic_print_state(const struct drm_atomic_state *state)
+{
+	struct drm_printer p = drm_info_printer(state->dev->dev);
+	struct drm_plane *plane;
+	struct drm_plane_state *plane_state;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_connector *connector;
+	struct drm_connector_state *connector_state;
+	int i;
+
+	DRM_DEBUG_ATOMIC("checking %p\n", state);
+
+	for_each_plane_in_state(state, plane, plane_state, i)
+		drm_atomic_plane_print_state(&p, plane_state);
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i)
+		drm_atomic_crtc_print_state(&p, crtc_state);
+
+	for_each_connector_in_state(state, connector, connector_state, i)
+		drm_atomic_connector_print_state(&p, connector_state);
+}
+
+/**
+ * drm_state_dump - dump entire device atomic state
+ * @dev: the drm device
+ * @p: where to print the state to
+ *
+ * Just for debugging.  Drivers might want an option to dump state
+ * to dmesg in case of error irq's.  (Hint, you probably want to
+ * ratelimit this!)
+ *
+ * The caller must drm_modeset_lock_all(), or if this is called
+ * from error irq handler, it should not be enabled by default.
+ * (Ie. if you are debugging errors you might not care that this
+ * is racey.  But calling this without all modeset locks held is
+ * not inherently safe.)
+ */
+void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+
+	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
+		return;
+
+	list_for_each_entry(plane, &config->plane_list, head)
+		drm_atomic_plane_print_state(p, plane->state);
+
+	list_for_each_entry(crtc, &config->crtc_list, head)
+		drm_atomic_crtc_print_state(p, crtc->state);
+
+	list_for_each_entry(connector, &config->connector_list, head)
+		drm_atomic_connector_print_state(p, connector->state);
+}
+EXPORT_SYMBOL(drm_state_dump);
+
+#ifdef CONFIG_DEBUG_FS
+static int drm_state_info(struct seq_file *m, void *data)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_printer p = drm_seq_file_printer(m);
+
+	drm_modeset_lock_all(dev);
+	drm_state_dump(dev, &p);
+	drm_modeset_unlock_all(dev);
+
+	return 0;
+}
+
+/* any use in debugfs files to dump individual planes/crtc/etc? */
+static const struct drm_info_list drm_atomic_debugfs_list[] = {
+	{"state", drm_state_info, 0},
+};
+
+int drm_atomic_debugfs_init(struct drm_minor *minor)
+{
+	return drm_debugfs_create_files(drm_atomic_debugfs_list,
+			ARRAY_SIZE(drm_atomic_debugfs_list),
+			minor->debugfs_root, minor);
+}
+
+int drm_atomic_debugfs_cleanup(struct drm_minor *minor)
+{
+	return drm_debugfs_remove_files(drm_atomic_debugfs_list,
+					ARRAY_SIZE(drm_atomic_debugfs_list),
+					minor);
+}
+#endif
+
 /*
  * The big monstor ioctl
  */
 
 static struct drm_pending_vblank_event *create_vblank_event(
-		struct drm_device *dev, struct drm_file *file_priv,
-		struct fence *fence, uint64_t user_data)
+		struct drm_device *dev, uint64_t user_data)
 {
 	struct drm_pending_vblank_event *e = NULL;
-	int ret;
 
 	e = kzalloc(sizeof *e, GFP_KERNEL);
 	if (!e)
@@ -1481,17 +1758,6 @@ static struct drm_pending_vblank_event *
 	e->event.base.length = sizeof(e->event);
 	e->event.user_data = user_data;
 
-	if (file_priv) {
-		ret = drm_event_reserve_init(dev, file_priv, &e->base,
-					     &e->event.base);
-		if (ret) {
-			kfree(e);
-			return NULL;
-		}
-	}
-
-	e->base.fence = fence;
-
 	return e;
 }
 
@@ -1596,6 +1862,206 @@ void drm_atomic_clean_old_fb(struct drm_
 }
 EXPORT_SYMBOL(drm_atomic_clean_old_fb);
 
+/**
+ * DOC: explicit fencing properties
+ *
+ * Explicit fencing allows userspace to control the buffer synchronization
+ * between devices. A Fence or a group of fences are transfered to/from
+ * userspace using Sync File fds and there are two DRM properties for that.
+ * IN_FENCE_FD on each DRM Plane to send fences to the kernel and
+ * OUT_FENCE_PTR on each DRM CRTC to receive fences from the kernel.
+ *
+ * As a contrast, with implicit fencing the kernel keeps track of any
+ * ongoing rendering, and automatically ensures that the atomic update waits
+ * for any pending rendering to complete. For shared buffers represented with
+ * a struct &dma_buf this is tracked in &reservation_object structures.
+ * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org),
+ * whereas explicit fencing is what Android wants.
+ *
+ * "IN_FENCE_FD”:
+ *	Use this property to pass a fence that DRM should wait on before
+ *	proceeding with the Atomic Commit request and show the framebuffer for
+ *	the plane on the screen. The fence can be either a normal fence or a
+ *	merged one, the sync_file framework will handle both cases and use a
+ *	fence_array if a merged fence is received. Passing -1 here means no
+ *	fences to wait on.
+ *
+ *	If the Atomic Commit request has the DRM_MODE_ATOMIC_TEST_ONLY flag
+ *	it will only check if the Sync File is a valid one.
+ *
+ *	On the driver side the fence is stored on the @fence parameter of
+ *	struct &drm_plane_state. Drivers which also support implicit fencing
+ *	should set the implicit fence using drm_atomic_set_fence_for_plane(),
+ *	to make sure there's consistent behaviour between drivers in precedence
+ *	of implicit vs. explicit fencing.
+ *
+ * "OUT_FENCE_PTR”:
+ *	Use this property to pass a file descriptor pointer to DRM. Once the
+ *	Atomic Commit request call returns OUT_FENCE_PTR will be filled with
+ *	the file descriptor number of a Sync File. This Sync File contains the
+ *	CRTC fence that will be signaled when all framebuffers present on the
+ *	Atomic Commit * request for that given CRTC are scanned out on the
+ *	screen.
+ *
+ *	The Atomic Commit request fails if a invalid pointer is passed. If the
+ *	Atomic Commit request fails for any other reason the out fence fd
+ *	returned will be -1. On a Atomic Commit with the
+ *	DRM_MODE_ATOMIC_TEST_ONLY flag the out fence will also be set to -1.
+ *
+ *	Note that out-fences don't have a special interface to drivers and are
+ *	internally represented by a struct &drm_pending_vblank_event in struct
+ *	&drm_crtc_state, which is also used by the nonblocking atomic commit
+ *	helpers and for the DRM event handling for existing userspace.
+ */
+
+struct drm_out_fence_state {
+	s32 __user *out_fence_ptr;
+	struct sync_file *sync_file;
+	int fd;
+};
+
+static int setup_out_fence(struct drm_out_fence_state *fence_state,
+			   struct dma_fence *fence)
+{
+	fence_state->fd = get_unused_fd_flags(O_CLOEXEC);
+	if (fence_state->fd < 0)
+		return fence_state->fd;
+
+	if (put_user(fence_state->fd, fence_state->out_fence_ptr))
+		return -EFAULT;
+
+	fence_state->sync_file = sync_file_create(fence);
+	if (!fence_state->sync_file)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int prepare_crtc_signaling(struct drm_device *dev,
+				  struct drm_atomic_state *state,
+				  struct drm_mode_atomic *arg,
+				  struct drm_file *file_priv,
+				  struct drm_out_fence_state **fence_state,
+				  unsigned int *num_fences)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	int i, ret;
+
+	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
+		return 0;
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		s32 __user *fence_ptr;
+
+		fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
+
+		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) {
+			struct drm_pending_vblank_event *e;
+
+			e = create_vblank_event(dev, arg->user_data);
+			if (!e)
+				return -ENOMEM;
+
+			crtc_state->event = e;
+		}
+
+		if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+			struct drm_pending_vblank_event *e = crtc_state->event;
+
+			if (!file_priv)
+				continue;
+
+			ret = drm_event_reserve_init(dev, file_priv, &e->base,
+						     &e->event.base);
+			if (ret) {
+				kfree(e);
+				crtc_state->event = NULL;
+				return ret;
+			}
+		}
+
+		if (fence_ptr) {
+			struct dma_fence *fence;
+			struct drm_out_fence_state *f;
+
+			f = krealloc(*fence_state, sizeof(**fence_state) *
+				     (*num_fences + 1), GFP_KERNEL);
+			if (!f)
+				return -ENOMEM;
+
+			memset(&f[*num_fences], 0, sizeof(*f));
+
+			f[*num_fences].out_fence_ptr = fence_ptr;
+			*fence_state = f;
+
+			fence = drm_crtc_create_fence(crtc);
+			if (!fence)
+				return -ENOMEM;
+
+			ret = setup_out_fence(&f[(*num_fences)++], fence);
+			if (ret) {
+				dma_fence_put(fence);
+				return ret;
+			}
+
+			crtc_state->event->base.fence = fence;
+		}
+	}
+
+	return 0;
+}
+
+static void complete_crtc_signaling(struct drm_device *dev,
+				    struct drm_atomic_state *state,
+				    struct drm_out_fence_state *fence_state,
+				    unsigned int num_fences,
+				    bool install_fds)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	int i;
+
+	if (install_fds) {
+		for (i = 0; i < num_fences; i++)
+			fd_install(fence_state[i].fd,
+				   fence_state[i].sync_file->file);
+
+		kfree(fence_state);
+		return;
+	}
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		struct drm_pending_vblank_event *event = crtc_state->event;
+		/*
+		 * Free the allocated event. drm_atomic_helper_setup_commit
+		 * can allocate an event too, so only free it if it's ours
+		 * to prevent a double free in drm_atomic_state_clear.
+		 */
+		if (event && (event->base.fence || event->base.file_priv)) {
+			drm_event_cancel_free(dev, &event->base);
+			crtc_state->event = NULL;
+		}
+	}
+
+	if (!fence_state)
+		return;
+
+	for (i = 0; i < num_fences; i++) {
+		if (fence_state[i].sync_file)
+			fput(fence_state[i].sync_file->file);
+		if (fence_state[i].fd >= 0)
+			put_unused_fd(fence_state[i].fd);
+
+		/* If this fails log error to the user */
+		if (fence_state[i].out_fence_ptr &&
+		    put_user(-1, fence_state[i].out_fence_ptr))
+			DRM_DEBUG_ATOMIC("Couldn't clear out_fence_ptr\n");
+	}
+
+	kfree(fence_state);
+}
+
 int drm_mode_atomic_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv)
 {
@@ -1608,11 +2074,10 @@ int drm_mode_atomic_ioctl(struct drm_dev
 	struct drm_atomic_state *state;
 	struct drm_modeset_acquire_ctx ctx;
 	struct drm_plane *plane;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
+	struct drm_out_fence_state *fence_state = NULL;
 	unsigned plane_mask;
 	int ret = 0;
-	unsigned int i, j;
+	unsigned int i, j, num_fences = 0;
 
 	/* disallow for drivers not supporting atomic: */
 	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
@@ -1727,50 +2192,30 @@ retry:
 		drm_mode_object_unreference(obj);
 	}
 
-	if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-		for_each_crtc_in_state(state, crtc, crtc_state, i) {
-			struct drm_pending_vblank_event *e;
-
-			e = create_vblank_event(dev, file_priv, NULL,
-						arg->user_data);
-			if (!e) {
-				ret = -ENOMEM;
-				goto out;
-			}
-
-			crtc_state->event = e;
-		}
-	}
+	ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state,
+				     &num_fences);
+	if (ret)
+		goto out;
 
 	if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
 		/*
 		 * Unlike commit, check_only does not clean up state.
-		 * Below we call drm_atomic_state_free for it.
+		 * Below we call drm_atomic_state_put for it.
 		 */
 		ret = drm_atomic_check_only(state);
 	} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
 		ret = drm_atomic_nonblocking_commit(state);
 	} else {
+		if (unlikely(drm_debug & DRM_UT_STATE))
+			drm_atomic_print_state(state);
+
 		ret = drm_atomic_commit(state);
 	}
 
 out:
 	drm_atomic_clean_old_fb(dev, plane_mask, ret);
 
-	if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-		/*
-		 * TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
-		 * if they weren't, this code should be called on success
-		 * for TEST_ONLY too.
-		 */
-
-		for_each_crtc_in_state(state, crtc, crtc_state, i) {
-			if (!crtc_state->event)
-				continue;
-
-			drm_event_cancel_free(dev, &crtc_state->event->base);
-		}
-	}
+	complete_crtc_signaling(dev, state, fence_state, num_fences, !ret);
 
 	if (ret == -EDEADLK) {
 		drm_atomic_state_clear(state);
@@ -1778,8 +2223,7 @@ out:
 		goto retry;
 	}
 
-	if (ret || arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
-		drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_atomic_helper.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_atomic_helper.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_atomic_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_atomic_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_atomic_helper.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 #include "drm_crtc_internal.h"
 
@@ -458,10 +458,11 @@ mode_fixup(struct drm_atomic_state *stat
  * removed from the crtc.
  * crtc_state->active_changed is set when crtc_state->active changes,
  * which is used for dpms.
+ * See also: drm_atomic_crtc_needs_modeset()
  *
  * IMPORTANT:
  *
- * Drivers which update ->mode_changed (e.g. in their ->atomic_check hooks if a
+ * Drivers which set ->mode_changed (e.g. in their ->atomic_check hooks if a
  * plane update can't be done without a full modeset) _must_ call this function
  * afterwards after that change. It is permitted to call this function multiple
  * times for the same update, e.g. when the ->atomic_check functions depend upon
@@ -510,9 +511,9 @@ drm_atomic_helper_check_modeset(struct d
 
 	for_each_connector_in_state(state, connector, connector_state, i) {
 		/*
-		 * This only sets crtc->mode_changed for routing changes,
-		 * drivers must set crtc->mode_changed themselves when connector
-		 * properties need to be updated.
+		 * This only sets crtc->connectors_changed for routing changes,
+		 * drivers must set crtc->connectors_changed themselves when
+		 * connector properties need to be updated.
 		 */
 		ret = update_connector_routing(state, connector,
 					       connector_state);
@@ -1005,14 +1006,22 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_m
  * drm_atomic_helper_wait_for_fences - wait for fences stashed in plane state
  * @dev: DRM device
  * @state: atomic state object with old state structures
- * @pre_swap: if true, do an interruptible wait
+ * @pre_swap: If true, do an interruptible wait, and @state is the new state.
+ * 	Otherwise @state is the old state.
  *
  * For implicit sync, driver should fish the exclusive fence out from the
  * incoming fb's and stash it in the drm_plane_state.  This is called after
  * drm_atomic_helper_swap_state() so it uses the current plane state (and
  * just uses the atomic state to find the changed planes)
  *
- * Returns zero if success or < 0 if fence_wait() fails.
+ * Note that @pre_swap is needed since the point where we block for fences moves
+ * around depending upon whether an atomic commit is blocking or
+ * non-blocking. For async commit all waiting needs to happen after
+ * drm_atomic_helper_swap_state() is called, but for synchronous commits we want
+ * to wait **before** we do anything that can't be easily rolled back. That is
+ * before we call drm_atomic_helper_swap_state().
+ *
+ * Returns zero if success or < 0 if dma_fence_wait() fails.
  */
 int drm_atomic_helper_wait_for_fences(struct drm_device *dev,
 				      struct drm_atomic_state *state,
@@ -1036,11 +1045,11 @@ int drm_atomic_helper_wait_for_fences(st
 		 * still interrupt the operation. Instead of blocking until the
 		 * timer expires, make the wait interruptible.
 		 */
-		ret = fence_wait(plane_state->fence, pre_swap);
+		ret = dma_fence_wait(plane_state->fence, pre_swap);
 		if (ret)
 			return ret;
 
-		fence_put(plane_state->fence);
+		dma_fence_put(plane_state->fence);
 		plane_state->fence = NULL;
 	}
 
@@ -1146,7 +1155,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for
 
 /**
  * drm_atomic_helper_commit_tail - commit atomic update to hardware
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
  *
  * This is the default implemenation for the ->atomic_commit_tail() hook of the
  * &drm_mode_config_helper_funcs vtable.
@@ -1157,53 +1166,53 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for
  *
  * For drivers supporting runtime PM the recommended sequence is instead ::
  *
- *     drm_atomic_helper_commit_modeset_disables(dev, state);
+ *     drm_atomic_helper_commit_modeset_disables(dev, old_state);
  *
- *     drm_atomic_helper_commit_modeset_enables(dev, state);
+ *     drm_atomic_helper_commit_modeset_enables(dev, old_state);
  *
- *     drm_atomic_helper_commit_planes(dev, state,
+ *     drm_atomic_helper_commit_planes(dev, old_state,
  *                                     DRM_PLANE_COMMIT_ACTIVE_ONLY);
  *
  * for committing the atomic update to hardware.  See the kerneldoc entries for
  * these three functions for more details.
  */
-void drm_atomic_helper_commit_tail(struct drm_atomic_state *state)
+void drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
 {
-	struct drm_device *dev = state->dev;
+	struct drm_device *dev = old_state->dev;
 
-	drm_atomic_helper_commit_modeset_disables(dev, state);
+	drm_atomic_helper_commit_modeset_disables(dev, old_state);
 
-	drm_atomic_helper_commit_planes(dev, state, 0);
+	drm_atomic_helper_commit_planes(dev, old_state, 0);
 
-	drm_atomic_helper_commit_modeset_enables(dev, state);
+	drm_atomic_helper_commit_modeset_enables(dev, old_state);
 
-	drm_atomic_helper_commit_hw_done(state);
+	drm_atomic_helper_commit_hw_done(old_state);
 
-	drm_atomic_helper_wait_for_vblanks(dev, state);
+	drm_atomic_helper_wait_for_vblanks(dev, old_state);
 
-	drm_atomic_helper_cleanup_planes(dev, state);
+	drm_atomic_helper_cleanup_planes(dev, old_state);
 }
 EXPORT_SYMBOL(drm_atomic_helper_commit_tail);
 
-static void commit_tail(struct drm_atomic_state *state)
+static void commit_tail(struct drm_atomic_state *old_state)
 {
-	struct drm_device *dev = state->dev;
+	struct drm_device *dev = old_state->dev;
 	struct drm_mode_config_helper_funcs *funcs;
 
 	funcs = dev->mode_config.helper_private;
 
-	drm_atomic_helper_wait_for_fences(dev, state, false);
+	drm_atomic_helper_wait_for_fences(dev, old_state, false);
 
-	drm_atomic_helper_wait_for_dependencies(state);
+	drm_atomic_helper_wait_for_dependencies(old_state);
 
 	if (funcs && funcs->atomic_commit_tail)
-		funcs->atomic_commit_tail(state);
+		funcs->atomic_commit_tail(old_state);
 	else
-		drm_atomic_helper_commit_tail(state);
+		drm_atomic_helper_commit_tail(old_state);
 
-	drm_atomic_helper_commit_cleanup_done(state);
+	drm_atomic_helper_commit_cleanup_done(old_state);
 
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(old_state);
 }
 
 static void commit_work(struct work_struct *work)
@@ -1225,9 +1234,6 @@ static void commit_work(struct work_stru
  * function implements nonblocking commits, using
  * drm_atomic_helper_setup_commit() and related functions.
  *
- * Note that right now this function does not support nonblocking commits, hence
- * driver writers must implement their own version for now.
- *
  * Committing the actual hardware state is done through the
  * ->atomic_commit_tail() callback of the &drm_mode_config_helper_funcs vtable,
  * or it's default implementation drm_atomic_helper_commit_tail().
@@ -1253,8 +1259,10 @@ int drm_atomic_helper_commit(struct drm_
 
 	if (!nonblock) {
 		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
-		if (ret)
+		if (ret) {
+			drm_atomic_helper_cleanup_planes(dev, state);
 			return ret;
+		}
 	}
 
 	/*
@@ -1285,6 +1293,7 @@ int drm_atomic_helper_commit(struct drm_
 	 * make sure work items don't artifically stall on each another.
 	 */
 
+	drm_atomic_state_get(state);
 	if (nonblock)
 		queue_work(system_unbound_wq, &state->commit_work);
 	else
@@ -1496,10 +1505,10 @@ static struct drm_crtc_commit *preceedin
 
 /**
  * drm_atomic_helper_wait_for_dependencies - wait for required preceeding commits
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
  *
  * This function waits for all preceeding commits that touch the same CRTC as
- * @state to both be committed to the hardware (as signalled by
+ * @old_state to both be committed to the hardware (as signalled by
  * drm_atomic_helper_commit_hw_done) and executed by the hardware (as signalled
  * by calling drm_crtc_vblank_send_event on the event member of
  * &drm_crtc_state).
@@ -1507,7 +1516,7 @@ static struct drm_crtc_commit *preceedin
  * This is part of the atomic helper support for nonblocking commits, see
  * drm_atomic_helper_setup_commit() for an overview.
  */
-void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state)
+void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *crtc_state;
@@ -1515,7 +1524,7 @@ void drm_atomic_helper_wait_for_dependen
 	int i;
 	long ret;
 
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+	for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
 		spin_lock(&crtc->commit_lock);
 		commit = preceeding_commit(crtc);
 		if (commit)
@@ -1546,7 +1555,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for
 
 /**
  * drm_atomic_helper_commit_hw_done - setup possible nonblocking commit
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
  *
  * This function is used to signal completion of the hardware commit step. After
  * this step the driver is not allowed to read or change any permanent software
@@ -1559,15 +1568,15 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for
  * This is part of the atomic helper support for nonblocking commits, see
  * drm_atomic_helper_setup_commit() for an overview.
  */
-void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state)
+void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *crtc_state;
 	struct drm_crtc_commit *commit;
 	int i;
 
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		commit = state->crtcs[i].commit;
+	for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
+		commit = old_state->crtcs[i].commit;
 		if (!commit)
 			continue;
 
@@ -1582,16 +1591,16 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_h
 
 /**
  * drm_atomic_helper_commit_cleanup_done - signal completion of commit
- * @state: new modeset state to be committed
+ * @old_state: atomic state object with old state structures
  *
- * This signals completion of the atomic update @state, including any cleanup
- * work. If used, it must be called right before calling
- * drm_atomic_state_free().
+ * This signals completion of the atomic update @old_state, including any
+ * cleanup work. If used, it must be called right before calling
+ * drm_atomic_state_put().
  *
  * This is part of the atomic helper support for nonblocking commits, see
  * drm_atomic_helper_setup_commit() for an overview.
  */
-void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state)
+void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *crtc_state;
@@ -1599,8 +1608,8 @@ void drm_atomic_helper_commit_cleanup_do
 	int i;
 	long ret;
 
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		commit = state->crtcs[i].commit;
+	for_each_crtc_in_state(old_state, crtc, crtc_state, i) {
+		commit = old_state->crtcs[i].commit;
 		if (WARN_ON(!commit))
 			continue;
 
@@ -1657,9 +1666,6 @@ int drm_atomic_helper_prepare_planes(str
 
 		funcs = plane->helper_private;
 
-		if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
-			continue;
-
 		if (funcs->prepare_fb) {
 			ret = funcs->prepare_fb(plane, plane_state);
 			if (ret)
@@ -1676,9 +1682,6 @@ fail:
 		if (j >= i)
 			continue;
 
-		if (!drm_atomic_helper_framebuffer_changed(dev, state, plane_state->crtc))
-			continue;
-
 		funcs = plane->helper_private;
 
 		if (funcs->cleanup_fb)
@@ -1945,9 +1948,6 @@ void drm_atomic_helper_cleanup_planes(st
 	for_each_plane_in_state(old_state, plane, plane_state, i) {
 		const struct drm_plane_helper_funcs *funcs;
 
-		if (!drm_atomic_helper_framebuffer_changed(dev, old_state, plane_state->crtc))
-			continue;
-
 		funcs = plane->helper_private;
 
 		if (funcs->cleanup_fb)
@@ -2109,18 +2109,13 @@ retry:
 		state->legacy_cursor_update = true;
 
 	ret = drm_atomic_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -2182,18 +2177,13 @@ retry:
 		goto fail;
 
 	ret = drm_atomic_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -2322,18 +2312,13 @@ retry:
 		goto fail;
 
 	ret = drm_atomic_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -2408,7 +2393,7 @@ int __drm_atomic_helper_set_config(struc
 	primary_state->crtc_h = vdisplay;
 	primary_state->src_x = set->x << 16;
 	primary_state->src_y = set->y << 16;
-	if (primary_state->rotation & (DRM_ROTATE_90 | DRM_ROTATE_270)) {
+	if (drm_rotation_90_or_270(primary_state->rotation)) {
 		primary_state->src_w = vdisplay << 16;
 		primary_state->src_h = hdisplay << 16;
 	} else {
@@ -2475,11 +2460,8 @@ int drm_atomic_helper_disable_all(struct
 	}
 
 	err = drm_atomic_commit(state);
-
 free:
-	if (err < 0)
-		drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return err;
 }
 EXPORT_SYMBOL(drm_atomic_helper_disable_all);
@@ -2530,7 +2512,7 @@ retry:
 
 	err = drm_atomic_helper_disable_all(dev, &ctx);
 	if (err < 0) {
-		drm_atomic_state_free(state);
+		drm_atomic_state_put(state);
 		state = ERR_PTR(err);
 		goto unlock;
 	}
@@ -2619,18 +2601,13 @@ retry:
 		goto fail;
 
 	ret = drm_atomic_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -2679,18 +2656,13 @@ retry:
 		goto fail;
 
 	ret = drm_atomic_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -2739,18 +2711,13 @@ retry:
 		goto fail;
 
 	ret = drm_atomic_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -2823,18 +2790,13 @@ retry:
 	}
 
 	ret = drm_atomic_nonblocking_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -2910,19 +2872,14 @@ retry:
 	crtc_state->active = active;
 
 	ret = drm_atomic_commit(state);
-	if (ret != 0)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
-
-	connector->dpms = old_mode;
-	drm_atomic_state_free(state);
-
+	if (ret != 0)
+		connector->dpms = old_mode;
+	drm_atomic_state_put(state);
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
@@ -3113,6 +3070,8 @@ void __drm_atomic_helper_plane_duplicate
 
 	if (state->fb)
 		drm_framebuffer_reference(state->fb);
+
+	state->fence = NULL;
 }
 EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
 
@@ -3151,6 +3110,9 @@ void __drm_atomic_helper_plane_destroy_s
 {
 	if (state->fb)
 		drm_framebuffer_unreference(state->fb);
+
+	if (state->fence)
+		dma_fence_put(state->fence);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
 
@@ -3329,7 +3291,7 @@ drm_atomic_helper_duplicate_state(struct
 
 free:
 	if (err < 0) {
-		drm_atomic_state_free(state);
+		drm_atomic_state_put(state);
 		state = ERR_PTR(err);
 	}
 
@@ -3444,22 +3406,14 @@ retry:
 		goto fail;
 
 	ret = drm_atomic_commit(state);
-	if (ret)
-		goto fail;
-
-	/* Driver takes ownership of state on successful commit. */
-
-	drm_property_unreference_blob(blob);
-
-	return 0;
 fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 	drm_property_unreference_blob(blob);
-
 	return ret;
+
 backoff:
 	drm_atomic_state_clear(state);
 	drm_atomic_legacy_backoff(state);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_blend.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_blend.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_blend.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_blend.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,7 @@
  * On top of this basic transformation additional properties can be exposed by
  * the driver:
  *
- * - Rotation is set up with drm_mode_create_rotation_property(). It adds a
+ * - Rotation is set up with drm_plane_create_rotation_property(). It adds a
  *   rotation and reflection step between the source and destination rectangles.
  *   Without this property the rectangle is only scaled, but not rotated or
  *   reflected.
@@ -105,18 +105,12 @@
  */
 
 /**
- * drm_mode_create_rotation_property - create a new rotation property
- * @dev: DRM device
+ * drm_plane_create_rotation_property - create a new rotation property
+ * @plane: drm plane
+ * @rotation: initial value of the rotation property
  * @supported_rotations: bitmask of supported rotations and reflections
  *
  * This creates a new property with the selected support for transformations.
- * The resulting property should be stored in @rotation_property in
- * &drm_mode_config. It then must be attached to each plane which supports
- * rotations using drm_object_attach_property().
- *
- * FIXME: Probably better if the rotation property is created on each plane,
- * like the zpos property. Otherwise it's not possible to allow different
- * rotation modes on different planes.
  *
  * Since a rotation by 180° degress is the same as reflecting both along the x
  * and the y axis the rotation property is somewhat redundant. Drivers can use
@@ -144,8 +138,9 @@
  * rotation. After reflection, the rotation is applied to the image sampled from
  * the source rectangle, before scaling it to fit the destination rectangle.
  */
-struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
-						       unsigned int supported_rotations)
+int drm_plane_create_rotation_property(struct drm_plane *plane,
+				       unsigned int rotation,
+				       unsigned int supported_rotations)
 {
 	static const struct drm_prop_enum_list props[] = {
 		{ __builtin_ffs(DRM_ROTATE_0) - 1,   "rotate-0" },
@@ -155,12 +150,28 @@ struct drm_property *drm_mode_create_rot
 		{ __builtin_ffs(DRM_REFLECT_X) - 1,  "reflect-x" },
 		{ __builtin_ffs(DRM_REFLECT_Y) - 1,  "reflect-y" },
 	};
+	struct drm_property *prop;
 
-	return drm_property_create_bitmask(dev, 0, "rotation",
+	WARN_ON((supported_rotations & DRM_ROTATE_MASK) == 0);
+	WARN_ON(!is_power_of_2(rotation & DRM_ROTATE_MASK));
+	WARN_ON(rotation & ~supported_rotations);
+
+	prop = drm_property_create_bitmask(plane->dev, 0, "rotation",
 					   props, ARRAY_SIZE(props),
 					   supported_rotations);
+	if (!prop)
+		return -ENOMEM;
+
+	drm_object_attach_property(&plane->base, prop, rotation);
+
+	if (plane->state)
+		plane->state->rotation = rotation;
+
+	plane->rotation_property = prop;
+
+	return 0;
 }
-EXPORT_SYMBOL(drm_mode_create_rotation_property);
+EXPORT_SYMBOL(drm_plane_create_rotation_property);
 
 /**
  * drm_rotation_simplify() - Try to simplify the rotation
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_color_mgmt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_color_mgmt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_color_mgmt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_color_mgmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,10 @@
  *	nor use all the elements of the LUT (for example the hardware might
  *	choose to interpolate between LUT[0] and LUT[4]).
  *
+ *	Setting this to NULL (blob property value set to 0) means a
+ *	linear/pass-thru gamma table should be used. This is generally the
+ *	driver boot-up state too.
+ *
  * “DEGAMMA_LUT_SIZE”:
  *	Unsinged range property to give the size of the lookup table to be set
  *	on the DEGAMMA_LUT property (the size depends on the underlying
@@ -54,6 +58,10 @@
  *	lookup through the gamma LUT. The data is interpreted as a struct
  *	&drm_color_ctm.
  *
+ *	Setting this to NULL (blob property value set to 0) means a
+ *	unit/pass-thru matrix should be used. This is generally the driver
+ *	boot-up state too.
+ *
  * “GAMMA_LUT”:
  *	Blob property to set the gamma lookup table (LUT) mapping pixel data
  *	after the transformation matrix to data sent to the connector. The
@@ -62,6 +70,10 @@
  *	nor use all the elements of the LUT (for example the hardware might
  *	choose to interpolate between LUT[0] and LUT[4]).
  *
+ *	Setting this to NULL (blob property value set to 0) means a
+ *	linear/pass-thru gamma table should be used. This is generally the
+ *	driver boot-up state too.
+ *
  * “GAMMA_LUT_SIZE”:
  *	Unsigned range property to give the size of the lookup table to be set
  *	on the GAMMA_LUT property (the size depends on the underlying hardware).
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_connector.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_connector.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_connector.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_connector.c	2017-02-12 16:03:20.000000000 -0500
@@ -225,6 +225,7 @@ int drm_connector_init(struct drm_device
 
 	INIT_LIST_HEAD(&connector->probed_modes);
 	INIT_LIST_HEAD(&connector->modes);
+	mutex_init(&connector->mutex);
 	connector->edid_blob_ptr = NULL;
 	connector->status = connector_status_unknown;
 
@@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_co
 		connector->funcs->atomic_destroy_state(connector,
 						       connector->state);
 
+	mutex_destroy(&connector->mutex);
+
 	memset(connector, 0, sizeof(*connector));
 }
 EXPORT_SYMBOL(drm_connector_cleanup);
@@ -374,14 +377,18 @@ EXPORT_SYMBOL(drm_connector_cleanup);
  */
 int drm_connector_register(struct drm_connector *connector)
 {
-	int ret;
+	int ret = 0;
 
-	if (connector->registered)
+	if (!connector->dev->registered)
 		return 0;
 
+	mutex_lock(&connector->mutex);
+	if (connector->registered)
+		goto unlock;
+
 	ret = drm_sysfs_connector_add(connector);
 	if (ret)
-		return ret;
+		goto unlock;
 
 	ret = drm_debugfs_connector_add(connector);
 	if (ret) {
@@ -397,12 +404,14 @@ int drm_connector_register(struct drm_co
 	drm_mode_object_register(connector->dev, &connector->base);
 
 	connector->registered = true;
-	return 0;
+	goto unlock;
 
 err_debugfs:
 	drm_debugfs_connector_remove(connector);
 err_sysfs:
 	drm_sysfs_connector_remove(connector);
+unlock:
+	mutex_unlock(&connector->mutex);
 	return ret;
 }
 EXPORT_SYMBOL(drm_connector_register);
@@ -415,8 +424,11 @@ EXPORT_SYMBOL(drm_connector_register);
  */
 void drm_connector_unregister(struct drm_connector *connector)
 {
-	if (!connector->registered)
+	mutex_lock(&connector->mutex);
+	if (!connector->registered) {
+		mutex_unlock(&connector->mutex);
 		return;
+	}
 
 	if (connector->funcs->early_unregister)
 		connector->funcs->early_unregister(connector);
@@ -425,6 +437,7 @@ void drm_connector_unregister(struct drm
 	drm_debugfs_connector_remove(connector);
 
 	connector->registered = false;
+	mutex_unlock(&connector->mutex);
 }
 EXPORT_SYMBOL(drm_connector_unregister);
 
@@ -588,6 +601,50 @@ static const struct drm_prop_enum_list d
 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
 		 drm_tv_subconnector_enum_list)
 
+/**
+ * DOC: standard connector properties
+ *
+ * DRM connectors have a few standardized properties:
+ *
+ * EDID:
+ * 	Blob property which contains the current EDID read from the sink. This
+ * 	is useful to parse sink identification information like vendor, model
+ * 	and serial. Drivers should update this property by calling
+ * 	drm_mode_connector_update_edid_property(), usually after having parsed
+ * 	the EDID using drm_add_edid_modes(). Userspace cannot change this
+ * 	property.
+ * DPMS:
+ * 	Legacy property for setting the power state of the connector. For atomic
+ * 	drivers this is only provided for backwards compatibility with existing
+ * 	drivers, it remaps to controlling the "ACTIVE" property on the CRTC the
+ * 	connector is linked to. Drivers should never set this property directly,
+ * 	it is handled by the DRM core by calling the ->dpms() callback in
+ * 	&drm_connector_funcs. Atomic drivers should implement this hook using
+ * 	drm_atomic_helper_connector_dpms(). This is the only property standard
+ * 	connector property that userspace can change.
+ * PATH:
+ * 	Connector path property to identify how this sink is physically
+ * 	connected. Used by DP MST. This should be set by calling
+ * 	drm_mode_connector_set_path_property(), in the case of DP MST with the
+ * 	path property the MST manager created. Userspace cannot change this
+ * 	property.
+ * TILE:
+ * 	Connector tile group property to indicate how a set of DRM connector
+ * 	compose together into one logical screen. This is used by both high-res
+ * 	external screens (often only using a single cable, but exposing multiple
+ * 	DP MST sinks), or high-res integrated panels (like dual-link DSI) which
+ * 	are not gen-locked. Note that for tiled panels which are genlocked, like
+ * 	dual-link LVDS or dual-link DSI, the driver should try to not expose the
+ * 	tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers
+ * 	should update this value using drm_mode_connector_set_tile_property().
+ * 	Userspace cannot change this property.
+ *
+ * Connectors also have one standardized atomic property:
+ *
+ * CRTC_ID:
+ * 	Mode object ID of the &drm_crtc this connector should be connected to.
+ */
+
 int drm_connector_create_standard_properties(struct drm_device *dev)
 {
 	struct drm_property *prop;
@@ -1121,3 +1178,107 @@ out_unlock:
 	return ret;
 }
 
+
+/**
+ * DOC: Tile group
+ *
+ * Tile groups are used to represent tiled monitors with a unique integer
+ * identifier. Tiled monitors using DisplayID v1.3 have a unique 8-byte handle,
+ * we store this in a tile group, so we have a common identifier for all tiles
+ * in a monitor group. The property is called "TILE". Drivers can manage tile
+ * groups using drm_mode_create_tile_group(), drm_mode_put_tile_group() and
+ * drm_mode_get_tile_group(). But this is only needed for internal panels where
+ * the tile group information is exposed through a non-standard way.
+ */
+
+static void drm_tile_group_free(struct kref *kref)
+{
+	struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
+	struct drm_device *dev = tg->dev;
+	mutex_lock(&dev->mode_config.idr_mutex);
+	idr_remove(&dev->mode_config.tile_idr, tg->id);
+	mutex_unlock(&dev->mode_config.idr_mutex);
+	kfree(tg);
+}
+
+/**
+ * drm_mode_put_tile_group - drop a reference to a tile group.
+ * @dev: DRM device
+ * @tg: tile group to drop reference to.
+ *
+ * drop reference to tile group and free if 0.
+ */
+void drm_mode_put_tile_group(struct drm_device *dev,
+			     struct drm_tile_group *tg)
+{
+	kref_put(&tg->refcount, drm_tile_group_free);
+}
+EXPORT_SYMBOL(drm_mode_put_tile_group);
+
+/**
+ * drm_mode_get_tile_group - get a reference to an existing tile group
+ * @dev: DRM device
+ * @topology: 8-bytes unique per monitor.
+ *
+ * Use the unique bytes to get a reference to an existing tile group.
+ *
+ * RETURNS:
+ * tile group or NULL if not found.
+ */
+struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
+					       char topology[8])
+{
+	struct drm_tile_group *tg;
+	int id;
+	mutex_lock(&dev->mode_config.idr_mutex);
+	idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
+		if (!memcmp(tg->group_data, topology, 8)) {
+			if (!kref_get_unless_zero(&tg->refcount))
+				tg = NULL;
+			mutex_unlock(&dev->mode_config.idr_mutex);
+			return tg;
+		}
+	}
+	mutex_unlock(&dev->mode_config.idr_mutex);
+	return NULL;
+}
+EXPORT_SYMBOL(drm_mode_get_tile_group);
+
+/**
+ * drm_mode_create_tile_group - create a tile group from a displayid description
+ * @dev: DRM device
+ * @topology: 8-bytes unique per monitor.
+ *
+ * Create a tile group for the unique monitor, and get a unique
+ * identifier for the tile group.
+ *
+ * RETURNS:
+ * new tile group or error.
+ */
+struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
+						  char topology[8])
+{
+	struct drm_tile_group *tg;
+	int ret;
+
+	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
+	if (!tg)
+		return ERR_PTR(-ENOMEM);
+
+	kref_init(&tg->refcount);
+	memcpy(tg->group_data, topology, 8);
+	tg->dev = dev;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
+	if (ret >= 0) {
+		tg->id = ret;
+	} else {
+		kfree(tg);
+		tg = ERR_PTR(ret);
+	}
+
+	mutex_unlock(&dev->mode_config.idr_mutex);
+	return tg;
+}
+EXPORT_SYMBOL(drm_mode_create_tile_group);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/dma-fence.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
@@ -40,23 +41,11 @@
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_auth.h>
-#include <drm/drm_framebuffer.h>
+#include <drm/drm_debugfs_crc.h>
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
 
-/*
- * Global properties
- */
-static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
-	{ DRM_PLANE_TYPE_OVERLAY, "Overlay" },
-	{ DRM_PLANE_TYPE_PRIMARY, "Primary" },
-	{ DRM_PLANE_TYPE_CURSOR, "Cursor" },
-};
-
-/*
- * Optional properties
- */
 /**
  * drm_crtc_force_disable - Forcibly turn off a CRTC
  * @crtc: CRTC to turn off
@@ -102,8 +91,6 @@ out:
 }
 EXPORT_SYMBOL(drm_crtc_force_disable_all);
 
-DEFINE_WW_CLASS(crtc_ww_class);
-
 static unsigned int drm_num_crtcs(struct drm_device *dev)
 {
 	unsigned int num = 0;
@@ -116,12 +103,16 @@ static unsigned int drm_num_crtcs(struct
 	return num;
 }
 
-static int drm_crtc_register_all(struct drm_device *dev)
+int drm_crtc_register_all(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
 	int ret = 0;
 
 	drm_for_each_crtc(crtc, dev) {
+		if (drm_debugfs_crtc_add(crtc))
+			DRM_ERROR("Failed to initialize debugfs entry for CRTC '%s'.\n",
+				  crtc->name);
+
 		if (crtc->funcs->late_register)
 			ret = crtc->funcs->late_register(crtc);
 		if (ret)
@@ -131,16 +122,84 @@ static int drm_crtc_register_all(struct
 	return 0;
 }
 
-static void drm_crtc_unregister_all(struct drm_device *dev)
+void drm_crtc_unregister_all(struct drm_device *dev)
 {
 	struct drm_crtc *crtc;
 
 	drm_for_each_crtc(crtc, dev) {
 		if (crtc->funcs->early_unregister)
 			crtc->funcs->early_unregister(crtc);
+		drm_debugfs_crtc_remove(crtc);
 	}
 }
 
+static int drm_crtc_crc_init(struct drm_crtc *crtc)
+{
+#ifdef CONFIG_DEBUG_FS
+	spin_lock_init(&crtc->crc.lock);
+	init_waitqueue_head(&crtc->crc.wq);
+	crtc->crc.source = kstrdup("auto", GFP_KERNEL);
+	if (!crtc->crc.source)
+		return -ENOMEM;
+#endif
+	return 0;
+}
+
+static void drm_crtc_crc_fini(struct drm_crtc *crtc)
+{
+#ifdef CONFIG_DEBUG_FS
+	kfree(crtc->crc.source);
+#endif
+}
+
+static const struct dma_fence_ops drm_crtc_fence_ops;
+
+static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
+{
+	BUG_ON(fence->ops != &drm_crtc_fence_ops);
+	return container_of(fence->lock, struct drm_crtc, fence_lock);
+}
+
+static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
+{
+	struct drm_crtc *crtc = fence_to_crtc(fence);
+
+	return crtc->dev->driver->name;
+}
+
+static const char *drm_crtc_fence_get_timeline_name(struct dma_fence *fence)
+{
+	struct drm_crtc *crtc = fence_to_crtc(fence);
+
+	return crtc->timeline_name;
+}
+
+static bool drm_crtc_fence_enable_signaling(struct dma_fence *fence)
+{
+	return true;
+}
+
+static const struct dma_fence_ops drm_crtc_fence_ops = {
+	.get_driver_name = drm_crtc_fence_get_driver_name,
+	.get_timeline_name = drm_crtc_fence_get_timeline_name,
+	.enable_signaling = drm_crtc_fence_enable_signaling,
+	.wait = dma_fence_default_wait,
+};
+
+struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
+{
+	struct dma_fence *fence;
+
+	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
+	if (!fence)
+		return NULL;
+
+	dma_fence_init(fence, &drm_crtc_fence_ops, &crtc->fence_lock,
+		       crtc->fence_context, ++crtc->fence_seqno);
+
+	return fence;
+}
+
 /**
  * drm_crtc_init_with_planes - Initialise a new CRTC object with
  *    specified primary and cursor planes.
@@ -198,6 +257,11 @@ int drm_crtc_init_with_planes(struct drm
 		return -ENOMEM;
 	}
 
+	crtc->fence_context = dma_fence_context_alloc(1);
+	spin_lock_init(&crtc->fence_lock);
+	snprintf(crtc->timeline_name, sizeof(crtc->timeline_name),
+		 "CRTC:%d-%s", crtc->base.id, crtc->name);
+
 	crtc->base.properties = &crtc->properties;
 
 	list_add_tail(&crtc->head, &config->crtc_list);
@@ -205,14 +269,22 @@ int drm_crtc_init_with_planes(struct drm
 
 	crtc->primary = primary;
 	crtc->cursor = cursor;
-	if (primary)
+	if (primary && !primary->possible_crtcs)
 		primary->possible_crtcs = 1 << drm_crtc_index(crtc);
-	if (cursor)
+	if (cursor && !cursor->possible_crtcs)
 		cursor->possible_crtcs = 1 << drm_crtc_index(crtc);
 
+	ret = drm_crtc_crc_init(crtc);
+	if (ret) {
+		drm_mode_object_unregister(dev, &crtc->base);
+		return ret;
+	}
+
 	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
 		drm_object_attach_property(&crtc->base, config->prop_active, 0);
 		drm_object_attach_property(&crtc->base, config->prop_mode_id, 0);
+		drm_object_attach_property(&crtc->base,
+					   config->prop_out_fence_ptr, 0);
 	}
 
 	return 0;
@@ -236,6 +308,8 @@ void drm_crtc_cleanup(struct drm_crtc *c
 	 * the indices on the drm_crtc after us in the crtc_list.
 	 */
 
+	drm_crtc_crc_fini(crtc);
+
 	kfree(crtc->gamma_store);
 	crtc->gamma_store = NULL;
 
@@ -255,301 +329,6 @@ void drm_crtc_cleanup(struct drm_crtc *c
 }
 EXPORT_SYMBOL(drm_crtc_cleanup);
 
-int drm_modeset_register_all(struct drm_device *dev)
-{
-	int ret;
-
-	ret = drm_plane_register_all(dev);
-	if (ret)
-		goto err_plane;
-
-	ret = drm_crtc_register_all(dev);
-	if  (ret)
-		goto err_crtc;
-
-	ret = drm_encoder_register_all(dev);
-	if (ret)
-		goto err_encoder;
-
-	ret = drm_connector_register_all(dev);
-	if (ret)
-		goto err_connector;
-
-	return 0;
-
-err_connector:
-	drm_encoder_unregister_all(dev);
-err_encoder:
-	drm_crtc_unregister_all(dev);
-err_crtc:
-	drm_plane_unregister_all(dev);
-err_plane:
-	return ret;
-}
-
-void drm_modeset_unregister_all(struct drm_device *dev)
-{
-	drm_connector_unregister_all(dev);
-	drm_encoder_unregister_all(dev);
-	drm_crtc_unregister_all(dev);
-	drm_plane_unregister_all(dev);
-}
-
-static int drm_mode_create_standard_properties(struct drm_device *dev)
-{
-	struct drm_property *prop;
-	int ret;
-
-	ret = drm_connector_create_standard_properties(dev);
-	if (ret)
-		return ret;
-
-	prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
-					"type", drm_plane_type_enum_list,
-					ARRAY_SIZE(drm_plane_type_enum_list));
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.plane_type_property = prop;
-
-	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
-			"SRC_X", 0, UINT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_src_x = prop;
-
-	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
-			"SRC_Y", 0, UINT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_src_y = prop;
-
-	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
-			"SRC_W", 0, UINT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_src_w = prop;
-
-	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
-			"SRC_H", 0, UINT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_src_h = prop;
-
-	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
-			"CRTC_X", INT_MIN, INT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_crtc_x = prop;
-
-	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
-			"CRTC_Y", INT_MIN, INT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_crtc_y = prop;
-
-	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
-			"CRTC_W", 0, INT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_crtc_w = prop;
-
-	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
-			"CRTC_H", 0, INT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_crtc_h = prop;
-
-	prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
-			"FB_ID", DRM_MODE_OBJECT_FB);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_fb_id = prop;
-
-	prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
-			"CRTC_ID", DRM_MODE_OBJECT_CRTC);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_crtc_id = prop;
-
-	prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
-			"ACTIVE");
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_active = prop;
-
-	prop = drm_property_create(dev,
-			DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
-			"MODE_ID", 0);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.prop_mode_id = prop;
-
-	prop = drm_property_create(dev,
-			DRM_MODE_PROP_BLOB,
-			"DEGAMMA_LUT", 0);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.degamma_lut_property = prop;
-
-	prop = drm_property_create_range(dev,
-			DRM_MODE_PROP_IMMUTABLE,
-			"DEGAMMA_LUT_SIZE", 0, UINT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.degamma_lut_size_property = prop;
-
-	prop = drm_property_create(dev,
-			DRM_MODE_PROP_BLOB,
-			"CTM", 0);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.ctm_property = prop;
-
-	prop = drm_property_create(dev,
-			DRM_MODE_PROP_BLOB,
-			"GAMMA_LUT", 0);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.gamma_lut_property = prop;
-
-	prop = drm_property_create_range(dev,
-			DRM_MODE_PROP_IMMUTABLE,
-			"GAMMA_LUT_SIZE", 0, UINT_MAX);
-	if (!prop)
-		return -ENOMEM;
-	dev->mode_config.gamma_lut_size_property = prop;
-
-	return 0;
-}
-
-/**
- * drm_mode_getresources - get graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Construct a set of configuration description structures and return
- * them to the user, including CRTC, connector and framebuffer configuration.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getresources(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
-{
-	struct drm_mode_card_res *card_res = data;
-	struct list_head *lh;
-	struct drm_framebuffer *fb;
-	struct drm_connector *connector;
-	struct drm_crtc *crtc;
-	struct drm_encoder *encoder;
-	int ret = 0;
-	int connector_count = 0;
-	int crtc_count = 0;
-	int fb_count = 0;
-	int encoder_count = 0;
-	int copied = 0;
-	uint32_t __user *fb_id;
-	uint32_t __user *crtc_id;
-	uint32_t __user *connector_id;
-	uint32_t __user *encoder_id;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-
-	mutex_lock(&file_priv->fbs_lock);
-	/*
-	 * For the non-control nodes we need to limit the list of resources
-	 * by IDs in the group list for this node
-	 */
-	list_for_each(lh, &file_priv->fbs)
-		fb_count++;
-
-	/* handle this in 4 parts */
-	/* FBs */
-	if (card_res->count_fbs >= fb_count) {
-		copied = 0;
-		fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
-		list_for_each_entry(fb, &file_priv->fbs, filp_head) {
-			if (put_user(fb->base.id, fb_id + copied)) {
-				mutex_unlock(&file_priv->fbs_lock);
-				return -EFAULT;
-			}
-			copied++;
-		}
-	}
-	card_res->count_fbs = fb_count;
-	mutex_unlock(&file_priv->fbs_lock);
-
-	/* mode_config.mutex protects the connector list against e.g. DP MST
-	 * connector hot-adding. CRTC/Plane lists are invariant. */
-	mutex_lock(&dev->mode_config.mutex);
-	drm_for_each_crtc(crtc, dev)
-		crtc_count++;
-
-	drm_for_each_connector(connector, dev)
-		connector_count++;
-
-	drm_for_each_encoder(encoder, dev)
-		encoder_count++;
-
-	card_res->max_height = dev->mode_config.max_height;
-	card_res->min_height = dev->mode_config.min_height;
-	card_res->max_width = dev->mode_config.max_width;
-	card_res->min_width = dev->mode_config.min_width;
-
-	/* CRTCs */
-	if (card_res->count_crtcs >= crtc_count) {
-		copied = 0;
-		crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
-		drm_for_each_crtc(crtc, dev) {
-			if (put_user(crtc->base.id, crtc_id + copied)) {
-				ret = -EFAULT;
-				goto out;
-			}
-			copied++;
-		}
-	}
-	card_res->count_crtcs = crtc_count;
-
-	/* Encoders */
-	if (card_res->count_encoders >= encoder_count) {
-		copied = 0;
-		encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
-		drm_for_each_encoder(encoder, dev) {
-			if (put_user(encoder->base.id, encoder_id +
-				     copied)) {
-				ret = -EFAULT;
-				goto out;
-			}
-			copied++;
-		}
-	}
-	card_res->count_encoders = encoder_count;
-
-	/* Connectors */
-	if (card_res->count_connectors >= connector_count) {
-		copied = 0;
-		connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
-		drm_for_each_connector(connector, dev) {
-			if (put_user(connector->base.id,
-				     connector_id + copied)) {
-				ret = -EFAULT;
-				goto out;
-			}
-			copied++;
-		}
-	}
-	card_res->count_connectors = connector_count;
-
-out:
-	mutex_unlock(&dev->mode_config.mutex);
-	return ret;
-}
-
 /**
  * drm_mode_getcrtc - get CRTC configuration
  * @dev: drm device for the ioctl
@@ -695,8 +474,7 @@ int drm_crtc_check_viewport(const struct
 	drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
 
 	if (crtc->state &&
-	    crtc->primary->state->rotation & (DRM_ROTATE_90 |
-					      DRM_ROTATE_270))
+	    drm_rotation_90_or_270(crtc->primary->state->rotation))
 		swap(hdisplay, vdisplay);
 
 	return drm_framebuffer_check_src_coords(x << 16, y << 16,
@@ -796,9 +574,10 @@ int drm_mode_setcrtc(struct drm_device *
 			ret = drm_plane_check_pixel_format(crtc->primary,
 							   fb->pixel_format);
 			if (ret) {
-				char *format_name = drm_get_format_name(fb->pixel_format);
-				DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
-				kfree(format_name);
+				struct drm_format_name_buf format_name;
+				DRM_DEBUG_KMS("Invalid pixel format %s\n",
+				              drm_get_format_name(fb->pixel_format,
+				                                  &format_name));
 				goto out;
 			}
 		}
@@ -902,362 +681,3 @@ int drm_mode_crtc_set_obj_prop(struct dr
 
 	return ret;
 }
-
-/**
- * drm_mode_config_reset - call ->reset callbacks
- * @dev: drm device
- *
- * This functions calls all the crtc's, encoder's and connector's ->reset
- * callback. Drivers can use this in e.g. their driver load or resume code to
- * reset hardware and software state.
- */
-void drm_mode_config_reset(struct drm_device *dev)
-{
-	struct drm_crtc *crtc;
-	struct drm_plane *plane;
-	struct drm_encoder *encoder;
-	struct drm_connector *connector;
-
-	drm_for_each_plane(plane, dev)
-		if (plane->funcs->reset)
-			plane->funcs->reset(plane);
-
-	drm_for_each_crtc(crtc, dev)
-		if (crtc->funcs->reset)
-			crtc->funcs->reset(crtc);
-
-	drm_for_each_encoder(encoder, dev)
-		if (encoder->funcs->reset)
-			encoder->funcs->reset(encoder);
-
-	mutex_lock(&dev->mode_config.mutex);
-	drm_for_each_connector(connector, dev)
-		if (connector->funcs->reset)
-			connector->funcs->reset(connector);
-	mutex_unlock(&dev->mode_config.mutex);
-}
-EXPORT_SYMBOL(drm_mode_config_reset);
-
-/**
- * drm_mode_create_dumb_ioctl - create a dumb backing storage buffer
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This creates a new dumb buffer in the driver's backing storage manager (GEM,
- * TTM or something else entirely) and returns the resulting buffer handle. This
- * handle can then be wrapped up into a framebuffer modeset object.
- *
- * Note that userspace is not allowed to use such objects for render
- * acceleration - drivers must create their own private ioctls for such a use
- * case.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_create_dumb_ioctl(struct drm_device *dev,
-			       void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_create_dumb *args = data;
-	u32 cpp, stride, size;
-
-	if (!dev->driver->dumb_create)
-		return -ENOSYS;
-	if (!args->width || !args->height || !args->bpp)
-		return -EINVAL;
-
-	/* overflow checks for 32bit size calculations */
-	/* NOTE: DIV_ROUND_UP() can overflow */
-	cpp = DIV_ROUND_UP(args->bpp, 8);
-	if (!cpp || cpp > 0xffffffffU / args->width)
-		return -EINVAL;
-	stride = cpp * args->width;
-	if (args->height > 0xffffffffU / stride)
-		return -EINVAL;
-
-	/* test for wrap-around */
-	size = args->height * stride;
-	if (PAGE_ALIGN(size) == 0)
-		return -EINVAL;
-
-	/*
-	 * handle, pitch and size are output parameters. Zero them out to
-	 * prevent drivers from accidentally using uninitialized data. Since
-	 * not all existing userspace is clearing these fields properly we
-	 * cannot reject IOCTL with garbage in them.
-	 */
-	args->handle = 0;
-	args->pitch = 0;
-	args->size = 0;
-
-	return dev->driver->dumb_create(file_priv, dev, args);
-}
-
-/**
- * drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Allocate an offset in the drm device node's address space to be able to
- * memory map a dumb buffer.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
-			     void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_map_dumb *args = data;
-
-	/* call driver ioctl to get mmap offset */
-	if (!dev->driver->dumb_map_offset)
-		return -ENOSYS;
-
-	return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
-}
-
-/**
- * drm_mode_destroy_dumb_ioctl - destroy a dumb backing strage buffer
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * This destroys the userspace handle for the given dumb backing storage buffer.
- * Since buffer objects must be reference counted in the kernel a buffer object
- * won't be immediately freed if a framebuffer modeset object still uses it.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
-				void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_destroy_dumb *args = data;
-
-	if (!dev->driver->dumb_destroy)
-		return -ENOSYS;
-
-	return dev->driver->dumb_destroy(file_priv, dev, args->handle);
-}
-
-/**
- * drm_mode_config_init - initialize DRM mode_configuration structure
- * @dev: DRM device
- *
- * Initialize @dev's mode_config structure, used for tracking the graphics
- * configuration of @dev.
- *
- * Since this initializes the modeset locks, no locking is possible. Which is no
- * problem, since this should happen single threaded at init time. It is the
- * driver's problem to ensure this guarantee.
- *
- */
-void drm_mode_config_init(struct drm_device *dev)
-{
-	mutex_init(&dev->mode_config.mutex);
-	drm_modeset_lock_init(&dev->mode_config.connection_mutex);
-	mutex_init(&dev->mode_config.idr_mutex);
-	mutex_init(&dev->mode_config.fb_lock);
-	mutex_init(&dev->mode_config.blob_lock);
-	INIT_LIST_HEAD(&dev->mode_config.fb_list);
-	INIT_LIST_HEAD(&dev->mode_config.crtc_list);
-	INIT_LIST_HEAD(&dev->mode_config.connector_list);
-	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
-	INIT_LIST_HEAD(&dev->mode_config.property_list);
-	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
-	INIT_LIST_HEAD(&dev->mode_config.plane_list);
-	idr_init(&dev->mode_config.crtc_idr);
-	idr_init(&dev->mode_config.tile_idr);
-	ida_init(&dev->mode_config.connector_ida);
-
-	drm_modeset_lock_all(dev);
-	drm_mode_create_standard_properties(dev);
-	drm_modeset_unlock_all(dev);
-
-	/* Just to be sure */
-	dev->mode_config.num_fb = 0;
-	dev->mode_config.num_connector = 0;
-	dev->mode_config.num_crtc = 0;
-	dev->mode_config.num_encoder = 0;
-	dev->mode_config.num_overlay_plane = 0;
-	dev->mode_config.num_total_plane = 0;
-}
-EXPORT_SYMBOL(drm_mode_config_init);
-
-/**
- * drm_mode_config_cleanup - free up DRM mode_config info
- * @dev: DRM device
- *
- * Free up all the connectors and CRTCs associated with this DRM device, then
- * free up the framebuffers and associated buffer objects.
- *
- * Note that since this /should/ happen single-threaded at driver/device
- * teardown time, no locking is required. It's the driver's job to ensure that
- * this guarantee actually holds true.
- *
- * FIXME: cleanup any dangling user buffer objects too
- */
-void drm_mode_config_cleanup(struct drm_device *dev)
-{
-	struct drm_connector *connector, *ot;
-	struct drm_crtc *crtc, *ct;
-	struct drm_encoder *encoder, *enct;
-	struct drm_framebuffer *fb, *fbt;
-	struct drm_property *property, *pt;
-	struct drm_property_blob *blob, *bt;
-	struct drm_plane *plane, *plt;
-
-	list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
-				 head) {
-		encoder->funcs->destroy(encoder);
-	}
-
-	list_for_each_entry_safe(connector, ot,
-				 &dev->mode_config.connector_list, head) {
-		connector->funcs->destroy(connector);
-	}
-
-	list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
-				 head) {
-		drm_property_destroy(dev, property);
-	}
-
-	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
-				 head) {
-		plane->funcs->destroy(plane);
-	}
-
-	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
-		crtc->funcs->destroy(crtc);
-	}
-
-	list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
-				 head_global) {
-		drm_property_unreference_blob(blob);
-	}
-
-	/*
-	 * Single-threaded teardown context, so it's not required to grab the
-	 * fb_lock to protect against concurrent fb_list access. Contrary, it
-	 * would actually deadlock with the drm_framebuffer_cleanup function.
-	 *
-	 * Also, if there are any framebuffers left, that's a driver leak now,
-	 * so politely WARN about this.
-	 */
-	WARN_ON(!list_empty(&dev->mode_config.fb_list));
-	list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
-		drm_framebuffer_free(&fb->base.refcount);
-	}
-
-	ida_destroy(&dev->mode_config.connector_ida);
-	idr_destroy(&dev->mode_config.tile_idr);
-	idr_destroy(&dev->mode_config.crtc_idr);
-	drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
-}
-EXPORT_SYMBOL(drm_mode_config_cleanup);
-
-/**
- * DOC: Tile group
- *
- * Tile groups are used to represent tiled monitors with a unique
- * integer identifier. Tiled monitors using DisplayID v1.3 have
- * a unique 8-byte handle, we store this in a tile group, so we
- * have a common identifier for all tiles in a monitor group.
- */
-static void drm_tile_group_free(struct kref *kref)
-{
-	struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
-	struct drm_device *dev = tg->dev;
-	mutex_lock(&dev->mode_config.idr_mutex);
-	idr_remove(&dev->mode_config.tile_idr, tg->id);
-	mutex_unlock(&dev->mode_config.idr_mutex);
-	kfree(tg);
-}
-
-/**
- * drm_mode_put_tile_group - drop a reference to a tile group.
- * @dev: DRM device
- * @tg: tile group to drop reference to.
- *
- * drop reference to tile group and free if 0.
- */
-void drm_mode_put_tile_group(struct drm_device *dev,
-			     struct drm_tile_group *tg)
-{
-	kref_put(&tg->refcount, drm_tile_group_free);
-}
-
-/**
- * drm_mode_get_tile_group - get a reference to an existing tile group
- * @dev: DRM device
- * @topology: 8-bytes unique per monitor.
- *
- * Use the unique bytes to get a reference to an existing tile group.
- *
- * RETURNS:
- * tile group or NULL if not found.
- */
-struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
-					       char topology[8])
-{
-	struct drm_tile_group *tg;
-	int id;
-	mutex_lock(&dev->mode_config.idr_mutex);
-	idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
-		if (!memcmp(tg->group_data, topology, 8)) {
-			if (!kref_get_unless_zero(&tg->refcount))
-				tg = NULL;
-			mutex_unlock(&dev->mode_config.idr_mutex);
-			return tg;
-		}
-	}
-	mutex_unlock(&dev->mode_config.idr_mutex);
-	return NULL;
-}
-EXPORT_SYMBOL(drm_mode_get_tile_group);
-
-/**
- * drm_mode_create_tile_group - create a tile group from a displayid description
- * @dev: DRM device
- * @topology: 8-bytes unique per monitor.
- *
- * Create a tile group for the unique monitor, and get a unique
- * identifier for the tile group.
- *
- * RETURNS:
- * new tile group or error.
- */
-struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
-						  char topology[8])
-{
-	struct drm_tile_group *tg;
-	int ret;
-
-	tg = kzalloc(sizeof(*tg), GFP_KERNEL);
-	if (!tg)
-		return ERR_PTR(-ENOMEM);
-
-	kref_init(&tg->refcount);
-	memcpy(tg->group_data, topology, 8);
-	tg->dev = dev;
-
-	mutex_lock(&dev->mode_config.idr_mutex);
-	ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL);
-	if (ret >= 0) {
-		tg->id = ret;
-	} else {
-		kfree(tg);
-		tg = ERR_PTR(ret);
-	}
-
-	mutex_unlock(&dev->mode_config.idr_mutex);
-	return tg;
-}
-EXPORT_SYMBOL(drm_mode_create_tile_group);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_crtc_internal.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_crtc_internal.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_crtc_internal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_crtc_internal.h	2017-02-12 16:03:20.000000000 -0500
@@ -40,10 +40,29 @@ int drm_crtc_check_viewport(const struct
 			    int x, int y,
 			    const struct drm_display_mode *mode,
 			    const struct drm_framebuffer *fb);
+int drm_crtc_register_all(struct drm_device *dev);
+void drm_crtc_unregister_all(struct drm_device *dev);
 
-void drm_fb_release(struct drm_file *file_priv);
+struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc);
 
-/* dumb buffer support IOCTLs */
+/* IOCTLs */
+int drm_mode_getcrtc(struct drm_device *dev,
+		     void *data, struct drm_file *file_priv);
+int drm_mode_setcrtc(struct drm_device *dev,
+		     void *data, struct drm_file *file_priv);
+
+
+/* drm_mode_config.c */
+int drm_modeset_register_all(struct drm_device *dev);
+void drm_modeset_unregister_all(struct drm_device *dev);
+
+/* IOCTLs */
+int drm_mode_getresources(struct drm_device *dev,
+			  void *data, struct drm_file *file_priv);
+
+
+/* drm_dumb_buffers.c */
+/* IOCTLs */
 int drm_mode_create_dumb_ioctl(struct drm_device *dev,
 			       void *data, struct drm_file *file_priv);
 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
@@ -51,14 +70,6 @@ int drm_mode_mmap_dumb_ioctl(struct drm_
 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 
-/* IOCTLs */
-int drm_mode_getresources(struct drm_device *dev,
-			  void *data, struct drm_file *file_priv);
-int drm_mode_getcrtc(struct drm_device *dev,
-		     void *data, struct drm_file *file_priv);
-int drm_mode_setcrtc(struct drm_device *dev,
-		     void *data, struct drm_file *file_priv);
-
 /* drm_color_mgmt.c */
 
 /* IOCTLs */
@@ -147,6 +158,8 @@ void drm_framebuffer_free(struct kref *k
 int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
 				     uint32_t src_w, uint32_t src_h,
 				     const struct drm_framebuffer *fb);
+void drm_fb_release(struct drm_file *file_priv);
+
 
 /* IOCTL */
 int drm_mode_addfb(struct drm_device *dev,
@@ -166,9 +179,6 @@ int drm_atomic_get_property(struct drm_m
 int drm_mode_atomic_ioctl(struct drm_device *dev,
 			  void *data, struct drm_file *file_priv);
 
-int drm_modeset_register_all(struct drm_device *dev);
-void drm_modeset_unregister_all(struct drm_device *dev);
-
 
 /* drm_plane.c */
 int drm_plane_register_all(struct drm_device *dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_debugfs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_debugfs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,7 @@
 #include <linux/export.h>
 #include <drm/drmP.h>
 #include <drm/drm_edid.h>
+#include <drm/drm_atomic.h>
 #include "drm_internal.h"
 
 #if defined(CONFIG_DEBUG_FS)
@@ -163,6 +164,14 @@ int drm_debugfs_init(struct drm_minor *m
 		return ret;
 	}
 
+	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
+		ret = drm_atomic_debugfs_init(minor);
+		if (ret) {
+			DRM_ERROR("Failed to create atomic debugfs files\n");
+			return ret;
+		}
+	}
+
 	if (dev->driver->debugfs_init) {
 		ret = dev->driver->debugfs_init(minor);
 		if (ret) {
@@ -219,6 +228,7 @@ EXPORT_SYMBOL(drm_debugfs_remove_files);
 int drm_debugfs_cleanup(struct drm_minor *minor)
 {
 	struct drm_device *dev = minor->dev;
+	int ret;
 
 	if (!minor->debugfs_root)
 		return 0;
@@ -226,6 +236,14 @@ int drm_debugfs_cleanup(struct drm_minor
 	if (dev->driver->debugfs_cleanup)
 		dev->driver->debugfs_cleanup(minor);
 
+	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
+		ret = drm_atomic_debugfs_cleanup(minor);
+		if (ret) {
+			DRM_ERROR("DRM: Failed to remove atomic debugfs entries\n");
+			return ret;
+		}
+	}
+
 	drm_debugfs_remove_files(drm_debugfs_list, DRM_DEBUGFS_ENTRIES, minor);
 
 	debugfs_remove(minor->debugfs_root);
@@ -415,5 +433,37 @@ void drm_debugfs_connector_remove(struct
 	connector->debugfs_entry = NULL;
 }
 
-#endif /* CONFIG_DEBUG_FS */
+int drm_debugfs_crtc_add(struct drm_crtc *crtc)
+{
+	struct drm_minor *minor = crtc->dev->primary;
+	struct dentry *root;
+	char *name;
+
+	name = kasprintf(GFP_KERNEL, "crtc-%d", crtc->index);
+	if (!name)
+		return -ENOMEM;
+
+	root = debugfs_create_dir(name, minor->debugfs_root);
+	kfree(name);
+	if (!root)
+		return -ENOMEM;
+
+	crtc->debugfs_entry = root;
+
+	if (drm_debugfs_crtc_crc_add(crtc))
+		goto error;
+
+	return 0;
 
+error:
+	drm_debugfs_crtc_remove(crtc);
+	return -ENOMEM;
+}
+
+void drm_debugfs_crtc_remove(struct drm_crtc *crtc)
+{
+	debugfs_remove_recursive(crtc->debugfs_entry);
+	crtc->debugfs_entry = NULL;
+}
+
+#endif /* CONFIG_DEBUG_FS */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_debugfs_crc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_debugfs_crc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_debugfs_crc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_debugfs_crc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,352 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ * Copyright © 2016 Collabora Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Based on code from the i915 driver.
+ * Original author: Damien Lespiau <damien.lespiau@intel.com>
+ *
+ */
+
+#include <linux/circ_buf.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <drm/drmP.h>
+#include "drm_internal.h"
+
+/**
+ * DOC: CRC ABI
+ *
+ * DRM device drivers can provide to userspace CRC information of each frame as
+ * it reached a given hardware component (a "source").
+ *
+ * Userspace can control generation of CRCs in a given CRTC by writing to the
+ * file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
+ * Accepted values are source names (which are driver-specific) and the "auto"
+ * keyword, which will let the driver select a default source of frame CRCs
+ * for this CRTC.
+ *
+ * Once frame CRC generation is enabled, userspace can capture them by reading
+ * the dri/0/crtc-N/crc/data file. Each line in that file contains the frame
+ * number in the first field and then a number of unsigned integer fields
+ * containing the CRC data. Fields are separated by a single space and the number
+ * of CRC fields is source-specific.
+ *
+ * Note that though in some cases the CRC is computed in a specified way and on
+ * the frame contents as supplied by userspace (eDP 1.3), in general the CRC
+ * computation is performed in an unspecified way and on frame contents that have
+ * been already processed in also an unspecified way and thus userspace cannot
+ * rely on being able to generate matching CRC values for the frame contents that
+ * it submits. In this general case, the maximum userspace can do is to compare
+ * the reported CRCs of frames that should have the same contents.
+ */
+
+static int crc_control_show(struct seq_file *m, void *data)
+{
+	struct drm_crtc *crtc = m->private;
+
+	seq_printf(m, "%s\n", crtc->crc.source);
+
+	return 0;
+}
+
+static int crc_control_open(struct inode *inode, struct file *file)
+{
+	struct drm_crtc *crtc = inode->i_private;
+
+	return single_open(file, crc_control_show, crtc);
+}
+
+static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
+				 size_t len, loff_t *offp)
+{
+	struct seq_file *m = file->private_data;
+	struct drm_crtc *crtc = m->private;
+	struct drm_crtc_crc *crc = &crtc->crc;
+	char *source;
+
+	if (len == 0)
+		return 0;
+
+	if (len > PAGE_SIZE - 1) {
+		DRM_DEBUG_KMS("Expected < %lu bytes into crtc crc control\n",
+			      PAGE_SIZE);
+		return -E2BIG;
+	}
+
+	source = memdup_user_nul(ubuf, len);
+	if (IS_ERR(source))
+		return PTR_ERR(source);
+
+	if (source[len] == '\n')
+		source[len] = '\0';
+
+	spin_lock_irq(&crc->lock);
+
+	if (crc->opened) {
+		spin_unlock_irq(&crc->lock);
+		kfree(source);
+		return -EBUSY;
+	}
+
+	kfree(crc->source);
+	crc->source = source;
+
+	spin_unlock_irq(&crc->lock);
+
+	*offp += len;
+	return len;
+}
+
+static const struct file_operations drm_crtc_crc_control_fops = {
+	.owner = THIS_MODULE,
+	.open = crc_control_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.write = crc_control_write
+};
+
+static int crtc_crc_open(struct inode *inode, struct file *filep)
+{
+	struct drm_crtc *crtc = inode->i_private;
+	struct drm_crtc_crc *crc = &crtc->crc;
+	struct drm_crtc_crc_entry *entries = NULL;
+	size_t values_cnt;
+	int ret;
+
+	if (crc->opened)
+		return -EBUSY;
+
+	ret = crtc->funcs->set_crc_source(crtc, crc->source, &values_cnt);
+	if (ret)
+		return ret;
+
+	if (WARN_ON(values_cnt > DRM_MAX_CRC_NR)) {
+		ret = -EINVAL;
+		goto err_disable;
+	}
+
+	if (WARN_ON(values_cnt == 0)) {
+		ret = -EINVAL;
+		goto err_disable;
+	}
+
+	entries = kcalloc(DRM_CRC_ENTRIES_NR, sizeof(*entries), GFP_KERNEL);
+	if (!entries) {
+		ret = -ENOMEM;
+		goto err_disable;
+	}
+
+	spin_lock_irq(&crc->lock);
+	crc->entries = entries;
+	crc->values_cnt = values_cnt;
+	crc->opened = true;
+	spin_unlock_irq(&crc->lock);
+
+	return 0;
+
+err_disable:
+	crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
+	return ret;
+}
+
+static int crtc_crc_release(struct inode *inode, struct file *filep)
+{
+	struct drm_crtc *crtc = filep->f_inode->i_private;
+	struct drm_crtc_crc *crc = &crtc->crc;
+	size_t values_cnt;
+
+	spin_lock_irq(&crc->lock);
+	kfree(crc->entries);
+	crc->entries = NULL;
+	crc->head = 0;
+	crc->tail = 0;
+	crc->values_cnt = 0;
+	crc->opened = false;
+	spin_unlock_irq(&crc->lock);
+
+	crtc->funcs->set_crc_source(crtc, NULL, &values_cnt);
+
+	return 0;
+}
+
+static int crtc_crc_data_count(struct drm_crtc_crc *crc)
+{
+	assert_spin_locked(&crc->lock);
+	return CIRC_CNT(crc->head, crc->tail, DRM_CRC_ENTRIES_NR);
+}
+
+/*
+ * 1 frame field of 10 chars plus a number of CRC fields of 10 chars each, space
+ * separated, with a newline at the end and null-terminated.
+ */
+#define LINE_LEN(values_cnt)	(10 + 11 * values_cnt + 1 + 1)
+#define MAX_LINE_LEN		(LINE_LEN(DRM_MAX_CRC_NR))
+
+static ssize_t crtc_crc_read(struct file *filep, char __user *user_buf,
+			     size_t count, loff_t *pos)
+{
+	struct drm_crtc *crtc = filep->f_inode->i_private;
+	struct drm_crtc_crc *crc = &crtc->crc;
+	struct drm_crtc_crc_entry *entry;
+	char buf[MAX_LINE_LEN];
+	int ret, i;
+
+	spin_lock_irq(&crc->lock);
+
+	if (!crc->source) {
+		spin_unlock_irq(&crc->lock);
+		return 0;
+	}
+
+	/* Nothing to read? */
+	while (crtc_crc_data_count(crc) == 0) {
+		if (filep->f_flags & O_NONBLOCK) {
+			spin_unlock_irq(&crc->lock);
+			return -EAGAIN;
+		}
+
+		ret = wait_event_interruptible_lock_irq(crc->wq,
+							crtc_crc_data_count(crc),
+							crc->lock);
+		if (ret) {
+			spin_unlock_irq(&crc->lock);
+			return ret;
+		}
+	}
+
+	/* We know we have an entry to be read */
+	entry = &crc->entries[crc->tail];
+
+	if (count < LINE_LEN(crc->values_cnt)) {
+		spin_unlock_irq(&crc->lock);
+		return -EINVAL;
+	}
+
+	BUILD_BUG_ON_NOT_POWER_OF_2(DRM_CRC_ENTRIES_NR);
+	crc->tail = (crc->tail + 1) & (DRM_CRC_ENTRIES_NR - 1);
+
+	spin_unlock_irq(&crc->lock);
+
+	if (entry->has_frame_counter)
+		sprintf(buf, "0x%08x", entry->frame);
+	else
+		sprintf(buf, "XXXXXXXXXX");
+
+	for (i = 0; i < crc->values_cnt; i++)
+		sprintf(buf + 10 + i * 11, " 0x%08x", entry->crcs[i]);
+	sprintf(buf + 10 + crc->values_cnt * 11, "\n");
+
+	if (copy_to_user(user_buf, buf, LINE_LEN(crc->values_cnt)))
+		return -EFAULT;
+
+	return LINE_LEN(crc->values_cnt);
+}
+
+static const struct file_operations drm_crtc_crc_data_fops = {
+	.owner = THIS_MODULE,
+	.open = crtc_crc_open,
+	.read = crtc_crc_read,
+	.release = crtc_crc_release,
+};
+
+/**
+ * drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs
+ * @crtc: CRTC to whom the frames will belong
+ *
+ * Adds files to debugfs directory that allows userspace to control the
+ * generation of frame CRCs and to read them.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
+{
+	struct dentry *crc_ent, *ent;
+
+	if (!crtc->funcs->set_crc_source)
+		return 0;
+
+	crc_ent = debugfs_create_dir("crc", crtc->debugfs_entry);
+	if (!crc_ent)
+		return -ENOMEM;
+
+	ent = debugfs_create_file("control", S_IRUGO, crc_ent, crtc,
+				  &drm_crtc_crc_control_fops);
+	if (!ent)
+		goto error;
+
+	ent = debugfs_create_file("data", S_IRUGO, crc_ent, crtc,
+				  &drm_crtc_crc_data_fops);
+	if (!ent)
+		goto error;
+
+	return 0;
+
+error:
+	debugfs_remove_recursive(crc_ent);
+
+	return -ENOMEM;
+}
+
+/**
+ * drm_crtc_add_crc_entry - Add entry with CRC information for a frame
+ * @crtc: CRTC to which the frame belongs
+ * @has_frame: whether this entry has a frame number to go with
+ * @frame: number of the frame these CRCs are about
+ * @crcs: array of CRC values, with length matching #drm_crtc_crc.values_cnt
+ *
+ * For each frame, the driver polls the source of CRCs for new data and calls
+ * this function to add them to the buffer from where userspace reads.
+ */
+int drm_crtc_add_crc_entry(struct drm_crtc *crtc, bool has_frame,
+			   uint32_t frame, uint32_t *crcs)
+{
+	struct drm_crtc_crc *crc = &crtc->crc;
+	struct drm_crtc_crc_entry *entry;
+	int head, tail;
+
+	assert_spin_locked(&crc->lock);
+
+	/* Caller may not have noticed yet that userspace has stopped reading */
+	if (!crc->opened)
+		return -EINVAL;
+
+	head = crc->head;
+	tail = crc->tail;
+
+	if (CIRC_SPACE(head, tail, DRM_CRC_ENTRIES_NR) < 1) {
+		DRM_ERROR("Overflow of CRC buffer, userspace reads too slow.\n");
+		return -ENOBUFS;
+	}
+
+	entry = &crc->entries[head];
+	entry->frame = frame;
+	entry->has_frame_counter = has_frame;
+	memcpy(&entry->crcs, crcs, sizeof(*crcs) * crc->values_cnt);
+
+	head = (head + 1) & (DRM_CRC_ENTRIES_NR - 1);
+	crc->head = head;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_crtc_add_crc_entry);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_dp_dual_mode_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -142,12 +142,25 @@ static bool is_hdmi_adaptor(const char h
 		      sizeof(dp_dual_mode_hdmi_id)) == 0;
 }
 
+static bool is_type1_adaptor(uint8_t adaptor_id)
+{
+	return adaptor_id == 0 || adaptor_id == 0xff;
+}
+
 static bool is_type2_adaptor(uint8_t adaptor_id)
 {
 	return adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 |
 			      DP_DUAL_MODE_REV_TYPE2);
 }
 
+static bool is_lspcon_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN],
+			      const uint8_t adaptor_id)
+{
+	return is_hdmi_adaptor(hdmi_id) &&
+		(adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 |
+		 DP_DUAL_MODE_TYPE_HAS_DPCD));
+}
+
 /**
  * drm_dp_dual_mode_detect - Identify the DP dual mode adaptor
  * @adapter: I2C adapter for the DDC bus
@@ -185,6 +198,8 @@ enum drm_dp_dual_mode_type drm_dp_dual_m
 	 */
 	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_HDMI_ID,
 				    hdmi_id, sizeof(hdmi_id));
+	DRM_DEBUG_KMS("DP dual mode HDMI ID: %*pE (err %zd)\n",
+		      ret ? 0 : (int)sizeof(hdmi_id), hdmi_id, ret);
 	if (ret)
 		return DRM_DP_DUAL_MODE_UNKNOWN;
 
@@ -202,13 +217,26 @@ enum drm_dp_dual_mode_type drm_dp_dual_m
 	 */
 	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID,
 				    &adaptor_id, sizeof(adaptor_id));
+	DRM_DEBUG_KMS("DP dual mode adaptor ID: %02x (err %zd)\n",
+		      adaptor_id, ret);
 	if (ret == 0) {
+		if (is_lspcon_adaptor(hdmi_id, adaptor_id))
+			return DRM_DP_DUAL_MODE_LSPCON;
 		if (is_type2_adaptor(adaptor_id)) {
 			if (is_hdmi_adaptor(hdmi_id))
 				return DRM_DP_DUAL_MODE_TYPE2_HDMI;
 			else
 				return DRM_DP_DUAL_MODE_TYPE2_DVI;
 		}
+		/*
+		 * If neither a proper type 1 ID nor a broken type 1 adaptor
+		 * as described above, assume type 1, but let the user know
+		 * that we may have misdetected the type.
+		 */
+		if (!is_type1_adaptor(adaptor_id) && adaptor_id != hdmi_id[0])
+			DRM_ERROR("Unexpected DP dual mode adaptor ID %02x\n",
+				  adaptor_id);
+
 	}
 
 	if (is_hdmi_adaptor(hdmi_id))
@@ -364,3 +392,96 @@ const char *drm_dp_get_dual_mode_type_na
 	}
 }
 EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name);
+
+/**
+ * drm_lspcon_get_mode: Get LSPCON's current mode of operation by
+ * reading offset (0x80, 0x41)
+ * @adapter: I2C-over-aux adapter
+ * @mode: current lspcon mode of operation output variable
+ *
+ * Returns:
+ * 0 on success, sets the current_mode value to appropriate mode
+ * -error on failure
+ */
+int drm_lspcon_get_mode(struct i2c_adapter *adapter,
+			enum drm_lspcon_mode *mode)
+{
+	u8 data;
+	int ret = 0;
+
+	if (!mode) {
+		DRM_ERROR("NULL input\n");
+		return -EINVAL;
+	}
+
+	/* Read Status: i2c over aux */
+	ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_CURRENT_MODE,
+				    &data, sizeof(data));
+	if (ret < 0) {
+		DRM_ERROR("LSPCON read(0x80, 0x41) failed\n");
+		return -EFAULT;
+	}
+
+	if (data & DP_DUAL_MODE_LSPCON_MODE_PCON)
+		*mode = DRM_LSPCON_MODE_PCON;
+	else
+		*mode = DRM_LSPCON_MODE_LS;
+	return 0;
+}
+EXPORT_SYMBOL(drm_lspcon_get_mode);
+
+/**
+ * drm_lspcon_set_mode: Change LSPCON's mode of operation by
+ * writing offset (0x80, 0x40)
+ * @adapter: I2C-over-aux adapter
+ * @mode: required mode of operation
+ *
+ * Returns:
+ * 0 on success, -error on failure/timeout
+ */
+int drm_lspcon_set_mode(struct i2c_adapter *adapter,
+			enum drm_lspcon_mode mode)
+{
+	u8 data = 0;
+	int ret;
+	int time_out = 200;
+	enum drm_lspcon_mode current_mode;
+
+	if (mode == DRM_LSPCON_MODE_PCON)
+		data = DP_DUAL_MODE_LSPCON_MODE_PCON;
+
+	/* Change mode */
+	ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_LSPCON_MODE_CHANGE,
+				     &data, sizeof(data));
+	if (ret < 0) {
+		DRM_ERROR("LSPCON mode change failed\n");
+		return ret;
+	}
+
+	/*
+	 * Confirm mode change by reading the status bit.
+	 * Sometimes, it takes a while to change the mode,
+	 * so wait and retry until time out or done.
+	 */
+	do {
+		ret = drm_lspcon_get_mode(adapter, &current_mode);
+		if (ret) {
+			DRM_ERROR("can't confirm LSPCON mode change\n");
+			return ret;
+		} else {
+			if (current_mode != mode) {
+				msleep(10);
+				time_out -= 10;
+			} else {
+				DRM_DEBUG_KMS("LSPCON mode changed to %s\n",
+						mode == DRM_LSPCON_MODE_LS ?
+						"LS" : "PCON");
+				return 0;
+			}
+		}
+	} while (time_out);
+
+	DRM_ERROR("LSPCON mode change timed out\n");
+	return -ETIMEDOUT;
+}
+EXPORT_SYMBOL(drm_lspcon_set_mode);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,10 @@
 #include <linux/moduleparam.h>
 #include <linux/mount.h>
 #include <linux/slab.h>
+
+#include <drm/drm_drv.h>
 #include <drm/drmP.h>
+
 #include "drm_crtc_internal.h"
 #include "drm_legacy.h"
 #include "drm_internal.h"
@@ -257,10 +260,7 @@ static void drm_minor_unregister(struct
 	drm_debugfs_cleanup(minor);
 }
 
-/**
- * drm_minor_acquire - Acquire a DRM minor
- * @minor_id: Minor ID of the DRM-minor
- *
+/*
  * Looks up the given minor-ID and returns the respective DRM-minor object. The
  * refence-count of the underlying device is increased so you must release this
  * object with drm_minor_release().
@@ -268,10 +268,6 @@ static void drm_minor_unregister(struct
  * As long as you hold this minor, it is guaranteed that the object and the
  * minor->dev pointer will stay valid! However, the device may get unplugged and
  * unregistered while you hold the minor.
- *
- * Returns:
- * Pointer to minor-object with increased device-refcount, or PTR_ERR on
- * failure.
  */
 struct drm_minor *drm_minor_acquire(unsigned int minor_id)
 {
@@ -294,12 +290,6 @@ struct drm_minor *drm_minor_acquire(unsi
 	return minor;
 }
 
-/**
- * drm_minor_release - Release DRM minor
- * @minor: Pointer to DRM minor object
- *
- * Release a minor that was previously acquired via drm_minor_acquire().
- */
 void drm_minor_release(struct drm_minor *minor)
 {
 	drm_dev_unref(minor->dev);
@@ -313,9 +303,10 @@ void drm_minor_release(struct drm_minor
  * callbacks implemented by the driver. The driver then needs to initialize all
  * the various subsystems for the drm device like memory management, vblank
  * handling, modesetting support and intial output configuration plus obviously
- * initialize all the corresponding hardware bits. Finally when everything is up
- * and running and ready for userspace the device instance can be published
- * using drm_dev_register().
+ * initialize all the corresponding hardware bits. An important part of this is
+ * also calling drm_dev_set_unique() to set the userspace-visible unique name of
+ * this device instance. Finally when everything is up and running and ready for
+ * userspace the device instance can be published using drm_dev_register().
  *
  * There is also deprecated support for initalizing device instances using
  * bus-specific helpers and the ->load() callback. But due to
@@ -337,17 +328,6 @@ void drm_minor_release(struct drm_minor
  * dev_priv field of &drm_device.
  */
 
-static int drm_dev_set_unique(struct drm_device *dev, const char *name)
-{
-	if (!name)
-		return -EINVAL;
-
-	kfree(dev->unique);
-	dev->unique = kstrdup(name, GFP_KERNEL);
-
-	return dev->unique ? 0 : -ENOMEM;
-}
-
 /**
  * drm_put_dev - Unregister and release a DRM device
  * @dev: DRM device
@@ -517,12 +497,6 @@ int drm_dev_init(struct drm_device *dev,
 		goto err_free;
 	}
 
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = drm_minor_alloc(dev, DRM_MINOR_CONTROL);
-		if (ret)
-			goto err_minors;
-	}
-
 	if (drm_core_check_feature(dev, DRIVER_RENDER)) {
 		ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
 		if (ret)
@@ -568,6 +542,9 @@ err_minors:
 	drm_fs_inode_free(dev->anon_inode);
 err_free:
 	mutex_destroy(&dev->master_mutex);
+	mutex_destroy(&dev->ctxlist_mutex);
+	mutex_destroy(&dev->filelist_mutex);
+	mutex_destroy(&dev->struct_mutex);
 	return ret;
 }
 EXPORT_SYMBOL(drm_dev_init);
@@ -630,6 +607,9 @@ static void drm_dev_release(struct kref
 	drm_minor_free(dev, DRM_MINOR_CONTROL);
 
 	mutex_destroy(&dev->master_mutex);
+	mutex_destroy(&dev->ctxlist_mutex);
+	mutex_destroy(&dev->filelist_mutex);
+	mutex_destroy(&dev->struct_mutex);
 	kfree(dev->unique);
 	kfree(dev);
 }
@@ -667,6 +647,62 @@ void drm_dev_unref(struct drm_device *de
 }
 EXPORT_SYMBOL(drm_dev_unref);
 
+static int create_compat_control_link(struct drm_device *dev)
+{
+	struct drm_minor *minor;
+	char *name;
+	int ret;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return 0;
+
+	minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY);
+	if (!minor)
+		return 0;
+
+	/*
+	 * Some existing userspace out there uses the existing of the controlD*
+	 * sysfs files to figure out whether it's a modeset driver. It only does
+	 * readdir, hence a symlink is sufficient (and the least confusing
+	 * option). Otherwise controlD* is entirely unused.
+	 *
+	 * Old controlD chardev have been allocated in the range
+	 * 64-127.
+	 */
+	name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64);
+	if (!name)
+		return -ENOMEM;
+
+	ret = sysfs_create_link(minor->kdev->kobj.parent,
+				&minor->kdev->kobj,
+				name);
+
+	kfree(name);
+
+	return ret;
+}
+
+static void remove_compat_control_link(struct drm_device *dev)
+{
+	struct drm_minor *minor;
+	char *name;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return;
+
+	minor = *drm_minor_get_slot(dev, DRM_MINOR_PRIMARY);
+	if (!minor)
+		return;
+
+	name = kasprintf(GFP_KERNEL, "controlD%d", minor->index);
+	if (!name)
+		return;
+
+	sysfs_remove_link(minor->kdev->kobj.parent, name);
+
+	kfree(name);
+}
+
 /**
  * drm_dev_register - Register DRM device
  * @dev: Device to register
@@ -705,6 +741,12 @@ int drm_dev_register(struct drm_device *
 	if (ret)
 		goto err_minors;
 
+	ret = create_compat_control_link(dev);
+	if (ret)
+		goto err_minors;
+
+	dev->registered = true;
+
 	if (dev->driver->load) {
 		ret = dev->driver->load(dev, flags);
 		if (ret)
@@ -718,6 +760,7 @@ int drm_dev_register(struct drm_device *
 	goto out_unlock;
 
 err_minors:
+	remove_compat_control_link(dev);
 	drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
 	drm_minor_unregister(dev, DRM_MINOR_RENDER);
 	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
@@ -744,6 +787,8 @@ void drm_dev_unregister(struct drm_devic
 
 	drm_lastclose(dev);
 
+	dev->registered = false;
+
 	if (drm_core_check_feature(dev, DRIVER_MODESET))
 		drm_modeset_unregister_all(dev);
 
@@ -758,12 +803,33 @@ void drm_dev_unregister(struct drm_devic
 	list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
 		drm_legacy_rmmap(dev, r_list->map);
 
+	remove_compat_control_link(dev);
 	drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
 	drm_minor_unregister(dev, DRM_MINOR_RENDER);
 	drm_minor_unregister(dev, DRM_MINOR_CONTROL);
 }
 EXPORT_SYMBOL(drm_dev_unregister);
 
+/**
+ * drm_dev_set_unique - Set the unique name of a DRM device
+ * @dev: device of which to set the unique name
+ * @name: unique name
+ *
+ * Sets the unique name of a DRM device using the specified string. Drivers
+ * can use this at driver probe time if the unique name of the devices they
+ * drive is static.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int drm_dev_set_unique(struct drm_device *dev, const char *name)
+{
+	kfree(dev->unique);
+	dev->unique = kstrdup(name, GFP_KERNEL);
+
+	return dev->unique ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(drm_dev_set_unique);
+
 /*
  * DRM Core
  * The DRM core module initializes all global DRM objects and makes them
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_dumb_buffers.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_dumb_buffers.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_dumb_buffers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_dumb_buffers.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2006-2008 Intel Corporation
+ * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
+ * Copyright (c) 2008 Red Hat Inc.
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <drm/drmP.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * The KMS API doesn't standardize backing storage object creation and leaves it
+ * to driver-specific ioctls. Furthermore actually creating a buffer object even
+ * for GEM-based drivers is done through a driver-specific ioctl - GEM only has
+ * a common userspace interface for sharing and destroying objects. While not an
+ * issue for full-fledged graphics stacks that include device-specific userspace
+ * components (in libdrm for instance), this limit makes DRM-based early boot
+ * graphics unnecessarily complex.
+ *
+ * Dumb objects partly alleviate the problem by providing a standard API to
+ * create dumb buffers suitable for scanout, which can then be used to create
+ * KMS frame buffers.
+ *
+ * To support dumb objects drivers must implement the dumb_create,
+ * dumb_destroy and dumb_map_offset operations from struct &drm_driver. See
+ * there for further details.
+ *
+ * Note that dumb objects may not be used for gpu acceleration, as has been
+ * attempted on some ARM embedded platforms. Such drivers really must have
+ * a hardware-specific ioctl to allocate suitable buffer objects.
+ */
+
+int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_create_dumb *args = data;
+	u32 cpp, stride, size;
+
+	if (!dev->driver->dumb_create)
+		return -ENOSYS;
+	if (!args->width || !args->height || !args->bpp)
+		return -EINVAL;
+
+	/* overflow checks for 32bit size calculations */
+	/* NOTE: DIV_ROUND_UP() can overflow */
+	cpp = DIV_ROUND_UP(args->bpp, 8);
+	if (!cpp || cpp > 0xffffffffU / args->width)
+		return -EINVAL;
+	stride = cpp * args->width;
+	if (args->height > 0xffffffffU / stride)
+		return -EINVAL;
+
+	/* test for wrap-around */
+	size = args->height * stride;
+	if (PAGE_ALIGN(size) == 0)
+		return -EINVAL;
+
+	/*
+	 * handle, pitch and size are output parameters. Zero them out to
+	 * prevent drivers from accidentally using uninitialized data. Since
+	 * not all existing userspace is clearing these fields properly we
+	 * cannot reject IOCTL with garbage in them.
+	 */
+	args->handle = 0;
+	args->pitch = 0;
+	args->size = 0;
+
+	return dev->driver->dumb_create(file_priv, dev, args);
+}
+
+/**
+ * drm_mode_mmap_dumb_ioctl - create an mmap offset for a dumb backing storage buffer
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Allocate an offset in the drm device node's address space to be able to
+ * memory map a dumb buffer.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+			     void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_map_dumb *args = data;
+
+	/* call driver ioctl to get mmap offset */
+	if (!dev->driver->dumb_map_offset)
+		return -ENOSYS;
+
+	return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
+}
+
+int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
+				void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_destroy_dumb *args = data;
+
+	if (!dev->driver->dumb_destroy)
+		return -ENOSYS;
+
+	return dev->driver->dumb_destroy(file_priv, dev, args->handle);
+}
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_edid.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_edid.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_edid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_edid.c	2017-02-12 16:03:20.000000000 -0500
@@ -957,13 +957,13 @@ static const struct drm_display_mode edi
 		   798, 858, 0, 480, 489, 495, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
 	  .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
-	/* 58 - 720(1440)x480i@240 */
+	/* 58 - 720(1440)x480i@240Hz */
 	{ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
 		   801, 858, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
 			DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
 	  .vrefresh = 240, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
-	/* 59 - 720(1440)x480i@240 */
+	/* 59 - 720(1440)x480i@240Hz */
 	{ DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 54000, 720, 739,
 		   801, 858, 0, 480, 488, 494, 525, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC |
@@ -1260,6 +1260,34 @@ drm_do_probe_ddc_edid(void *data, u8 *bu
 	return ret == xfers ? 0 : -1;
 }
 
+static void connector_bad_edid(struct drm_connector *connector,
+			       u8 *edid, int num_blocks)
+{
+	int i;
+
+	if (connector->bad_edid_counter++ && !(drm_debug & DRM_UT_KMS))
+		return;
+
+	dev_warn(connector->dev->dev,
+		 "%s: EDID is invalid:\n",
+		 connector->name);
+	for (i = 0; i < num_blocks; i++) {
+		u8 *block = edid + i * EDID_LENGTH;
+		char prefix[20];
+
+		if (drm_edid_is_zero(block, EDID_LENGTH))
+			sprintf(prefix, "\t[%02x] ZERO ", i);
+		else if (!drm_edid_block_valid(block, i, false, NULL))
+			sprintf(prefix, "\t[%02x] BAD  ", i);
+		else
+			sprintf(prefix, "\t[%02x] GOOD ", i);
+
+		print_hex_dump(KERN_WARNING,
+			       prefix, DUMP_PREFIX_NONE, 16, 1,
+			       block, EDID_LENGTH, false);
+	}
+}
+
 /**
  * drm_do_get_edid - get EDID data using a custom EDID block read function
  * @connector: connector we're probing
@@ -1282,20 +1310,19 @@ struct edid *drm_do_get_edid(struct drm_
 	void *data)
 {
 	int i, j = 0, valid_extensions = 0;
-	u8 *block, *new;
-	bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);
+	u8 *edid, *new;
 
-	if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
+	if ((edid = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
 		return NULL;
 
 	/* base block fetch */
 	for (i = 0; i < 4; i++) {
-		if (get_edid_block(data, block, 0, EDID_LENGTH))
+		if (get_edid_block(data, edid, 0, EDID_LENGTH))
 			goto out;
-		if (drm_edid_block_valid(block, 0, print_bad_edid,
+		if (drm_edid_block_valid(edid, 0, false,
 					 &connector->edid_corrupt))
 			break;
-		if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
+		if (i == 0 && drm_edid_is_zero(edid, EDID_LENGTH)) {
 			connector->null_edid_counter++;
 			goto carp;
 		}
@@ -1304,58 +1331,62 @@ struct edid *drm_do_get_edid(struct drm_
 		goto carp;
 
 	/* if there's no extensions, we're done */
-	if (block[0x7e] == 0)
-		return (struct edid *)block;
+	valid_extensions = edid[0x7e];
+	if (valid_extensions == 0)
+		return (struct edid *)edid;
 
-	new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
+	new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
 	if (!new)
 		goto out;
-	block = new;
+	edid = new;
+
+	for (j = 1; j <= edid[0x7e]; j++) {
+		u8 *block = edid + j * EDID_LENGTH;
 
-	for (j = 1; j <= block[0x7e]; j++) {
 		for (i = 0; i < 4; i++) {
-			if (get_edid_block(data,
-				  block + (valid_extensions + 1) * EDID_LENGTH,
-				  j, EDID_LENGTH))
+			if (get_edid_block(data, block, j, EDID_LENGTH))
 				goto out;
-			if (drm_edid_block_valid(block + (valid_extensions + 1)
-						 * EDID_LENGTH, j,
-						 print_bad_edid,
-						 NULL)) {
-				valid_extensions++;
+			if (drm_edid_block_valid(block, j, false, NULL))
 				break;
-			}
 		}
 
-		if (i == 4 && print_bad_edid) {
-			dev_warn(connector->dev->dev,
-			 "%s: Ignoring invalid EDID block %d.\n",
-			 connector->name, j);
-
-			connector->bad_edid_counter++;
-		}
+		if (i == 4)
+			valid_extensions--;
 	}
 
-	if (valid_extensions != block[0x7e]) {
-		block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
-		block[0x7e] = valid_extensions;
-		new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
+	if (valid_extensions != edid[0x7e]) {
+		u8 *base;
+
+		connector_bad_edid(connector, edid, edid[0x7e] + 1);
+
+		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
+		edid[0x7e] = valid_extensions;
+
+		new = kmalloc((valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
 		if (!new)
 			goto out;
-		block = new;
-	}
 
-	return (struct edid *)block;
+		base = new;
+		for (i = 0; i <= edid[0x7e]; i++) {
+			u8 *block = edid + i * EDID_LENGTH;
 
-carp:
-	if (print_bad_edid) {
-		dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
-			 connector->name, j);
+			if (!drm_edid_block_valid(block, i, false, NULL))
+				continue;
+
+			memcpy(base, block, EDID_LENGTH);
+			base += EDID_LENGTH;
+		}
+
+		kfree(edid);
+		edid = new;
 	}
-	connector->bad_edid_counter++;
 
+	return (struct edid *)edid;
+
+carp:
+	connector_bad_edid(connector, edid, 1);
 out:
-	kfree(block);
+	kfree(edid);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(drm_do_get_edid);
@@ -2582,6 +2613,41 @@ cea_mode_alternate_clock(const struct dr
 	return clock;
 }
 
+static bool
+cea_mode_alternate_timings(u8 vic, struct drm_display_mode *mode)
+{
+	/*
+	 * For certain VICs the spec allows the vertical
+	 * front porch to vary by one or two lines.
+	 *
+	 * cea_modes[] stores the variant with the shortest
+	 * vertical front porch. We can adjust the mode to
+	 * get the other variants by simply increasing the
+	 * vertical front porch length.
+	 */
+	BUILD_BUG_ON(edid_cea_modes[8].vtotal != 262 ||
+		     edid_cea_modes[9].vtotal != 262 ||
+		     edid_cea_modes[12].vtotal != 262 ||
+		     edid_cea_modes[13].vtotal != 262 ||
+		     edid_cea_modes[23].vtotal != 312 ||
+		     edid_cea_modes[24].vtotal != 312 ||
+		     edid_cea_modes[27].vtotal != 312 ||
+		     edid_cea_modes[28].vtotal != 312);
+
+	if (((vic == 8 || vic == 9 ||
+	      vic == 12 || vic == 13) && mode->vtotal < 263) ||
+	    ((vic == 23 || vic == 24 ||
+	      vic == 27 || vic == 28) && mode->vtotal < 314)) {
+		mode->vsync_start++;
+		mode->vsync_end++;
+		mode->vtotal++;
+
+		return true;
+	}
+
+	return false;
+}
+
 static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
 					     unsigned int clock_tolerance)
 {
@@ -2591,19 +2657,21 @@ static u8 drm_match_cea_mode_clock_toler
 		return 0;
 
 	for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
-		const struct drm_display_mode *cea_mode = &edid_cea_modes[vic];
+		struct drm_display_mode cea_mode = edid_cea_modes[vic];
 		unsigned int clock1, clock2;
 
 		/* Check both 60Hz and 59.94Hz */
-		clock1 = cea_mode->clock;
-		clock2 = cea_mode_alternate_clock(cea_mode);
+		clock1 = cea_mode.clock;
+		clock2 = cea_mode_alternate_clock(&cea_mode);
 
 		if (abs(to_match->clock - clock1) > clock_tolerance &&
 		    abs(to_match->clock - clock2) > clock_tolerance)
 			continue;
 
-		if (drm_mode_equal_no_clocks(to_match, cea_mode))
-			return vic;
+		do {
+			if (drm_mode_equal_no_clocks_no_stereo(to_match, &cea_mode))
+				return vic;
+		} while (cea_mode_alternate_timings(vic, &cea_mode));
 	}
 
 	return 0;
@@ -2624,18 +2692,23 @@ u8 drm_match_cea_mode(const struct drm_d
 		return 0;
 
 	for (vic = 1; vic < ARRAY_SIZE(edid_cea_modes); vic++) {
-		const struct drm_display_mode *cea_mode = &edid_cea_modes[vic];
+		struct drm_display_mode cea_mode = edid_cea_modes[vic];
 		unsigned int clock1, clock2;
 
 		/* Check both 60Hz and 59.94Hz */
-		clock1 = cea_mode->clock;
-		clock2 = cea_mode_alternate_clock(cea_mode);
+		clock1 = cea_mode.clock;
+		clock2 = cea_mode_alternate_clock(&cea_mode);
 
-		if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
-		     KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
-		    drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
-			return vic;
+		if (KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock1) &&
+		    KHZ2PICOS(to_match->clock) != KHZ2PICOS(clock2))
+			continue;
+
+		do {
+			if (drm_mode_equal_no_clocks_no_stereo(to_match, &cea_mode))
+				return vic;
+		} while (cea_mode_alternate_timings(vic, &cea_mode));
 	}
+
 	return 0;
 }
 EXPORT_SYMBOL(drm_match_cea_mode);
@@ -3580,32 +3653,6 @@ int drm_av_sync_delay(struct drm_connect
 EXPORT_SYMBOL(drm_av_sync_delay);
 
 /**
- * drm_select_eld - select one ELD from multiple HDMI/DP sinks
- * @encoder: the encoder just changed 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.
- *
- * Return: The connector associated with the first HDMI/DP sink that has ELD
- * attached to it.
- */
-struct drm_connector *drm_select_eld(struct drm_encoder *encoder)
-{
-	struct drm_connector *connector;
-	struct drm_device *dev = encoder->dev;
-
-	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
-	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
-
-	drm_for_each_connector(connector, dev)
-		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 -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_encoder.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_encoder.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_encoder.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_encoder.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,11 +110,9 @@ int drm_encoder_init(struct drm_device *
 {
 	int ret;
 
-	drm_modeset_lock_all(dev);
-
 	ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
 	if (ret)
-		goto out_unlock;
+		return ret;
 
 	encoder->dev = dev;
 	encoder->encoder_type = encoder_type;
@@ -142,9 +140,6 @@ out_put:
 	if (ret)
 		drm_mode_object_unregister(dev, &encoder->base);
 
-out_unlock:
-	drm_modeset_unlock_all(dev);
-
 	return ret;
 }
 EXPORT_SYMBOL(drm_encoder_init);
@@ -164,12 +159,10 @@ void drm_encoder_cleanup(struct drm_enco
 	 * the indices on the drm_encoder after us in the encoder_list.
 	 */
 
-	drm_modeset_lock_all(dev);
 	drm_mode_object_unregister(dev, &encoder->base);
 	kfree(encoder->name);
 	list_del(&encoder->head);
 	dev->mode_config.num_encoder--;
-	drm_modeset_unlock_all(dev);
 
 	memset(encoder, 0, sizeof(*encoder));
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_fb_cma_helper.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fb_cma_helper.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_fb_cma_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fb_cma_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,13 +18,16 @@
  */
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <linux/dma-buf.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
+#include <linux/reservation.h>
 
 #define DEFAULT_FBDEFIO_DELAY_MS 50
 
@@ -176,20 +179,20 @@ struct drm_framebuffer *drm_fb_cma_creat
 	struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd,
 	const struct drm_framebuffer_funcs *funcs)
 {
+	const struct drm_format_info *info;
 	struct drm_fb_cma *fb_cma;
 	struct drm_gem_cma_object *objs[4];
 	struct drm_gem_object *obj;
-	unsigned int hsub;
-	unsigned int vsub;
 	int ret;
 	int i;
 
-	hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format);
-	vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format);
+	info = drm_format_info(mode_cmd->pixel_format);
+	if (!info)
+		return ERR_PTR(-EINVAL);
 
-	for (i = 0; i < drm_format_num_planes(mode_cmd->pixel_format); i++) {
-		unsigned int width = mode_cmd->width / (i ? hsub : 1);
-		unsigned int height = mode_cmd->height / (i ? vsub : 1);
+	for (i = 0; i < info->num_planes; i++) {
+		unsigned int width = mode_cmd->width / (i ? info->hsub : 1);
+		unsigned int height = mode_cmd->height / (i ? info->vsub : 1);
 		unsigned int min_size;
 
 		obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]);
@@ -200,7 +203,7 @@ struct drm_framebuffer *drm_fb_cma_creat
 		}
 
 		min_size = (height - 1) * mode_cmd->pitches[i]
-			 + width * drm_format_plane_cpp(mode_cmd->pixel_format, i)
+			 + width * info->cpp[i]
 			 + mode_cmd->offsets[i];
 
 		if (obj->size < min_size) {
@@ -265,16 +268,51 @@ struct drm_gem_cma_object *drm_fb_cma_ge
 }
 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
 
+/**
+ * drm_fb_cma_prepare_fb() - Prepare CMA framebuffer
+ * @plane: Which plane
+ * @state: Plane state attach fence to
+ *
+ * This should be put into prepare_fb hook of struct &drm_plane_helper_funcs .
+ *
+ * This function checks if the plane FB has an dma-buf attached, extracts
+ * the exclusive fence and attaches it to plane state for the atomic helper
+ * to wait on.
+ *
+ * There is no need for cleanup_fb for CMA based framebuffer drivers.
+ */
+int drm_fb_cma_prepare_fb(struct drm_plane *plane,
+			  struct drm_plane_state *state)
+{
+	struct dma_buf *dma_buf;
+	struct dma_fence *fence;
+
+	if ((plane->state->fb == state->fb) || !state->fb)
+		return 0;
+
+	dma_buf = drm_fb_cma_get_gem_obj(state->fb, 0)->base.dma_buf;
+	if (dma_buf) {
+		fence = reservation_object_get_excl_rcu(dma_buf->resv);
+		drm_atomic_set_fence_for_plane(state, fence);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_fb_cma_prepare_fb);
+
 #ifdef CONFIG_DEBUG_FS
 static void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m)
 {
 	struct drm_fb_cma *fb_cma = to_fb_cma(fb);
-	int i, n = drm_format_num_planes(fb->pixel_format);
+	const struct drm_format_info *info;
+	int i;
 
 	seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height,
 			(char *)&fb->pixel_format);
 
-	for (i = 0; i < n; i++) {
+	info = drm_format_info(fb->pixel_format);
+
+	for (i = 0; i < info->num_planes; i++) {
 		seq_printf(m, "   %d: offset=%d pitch=%d, obj: ",
 				i, fb->offsets[i], fb->pitches[i]);
 		drm_gem_cma_describe(fb_cma->obj[i], m);
@@ -311,14 +349,10 @@ static int drm_fb_cma_mmap(struct fb_inf
 
 static struct fb_ops drm_fbdev_cma_ops = {
 	.owner		= THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_fillrect	= drm_fb_helper_sys_fillrect,
 	.fb_copyarea	= drm_fb_helper_sys_copyarea,
 	.fb_imageblit	= drm_fb_helper_sys_imageblit,
-	.fb_check_var	= drm_fb_helper_check_var,
-	.fb_set_par	= drm_fb_helper_set_par,
-	.fb_blank	= drm_fb_helper_blank,
-	.fb_pan_display	= drm_fb_helper_pan_display,
-	.fb_setcmap	= drm_fb_helper_setcmap,
 	.fb_mmap	= drm_fb_cma_mmap,
 };
 
@@ -557,7 +591,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
 void drm_fbdev_cma_fini(struct drm_fbdev_cma *fbdev_cma)
 {
 	drm_fb_helper_unregister_fbi(&fbdev_cma->fb_helper);
-	drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
+	if (fbdev_cma->fb_helper.fbdev)
+		drm_fbdev_cma_defio_fini(fbdev_cma->fb_helper.fbdev);
 	drm_fb_helper_release_fbi(&fbdev_cma->fb_helper);
 
 	if (fbdev_cma->fb) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_fb_helper.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_fb_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fb_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,7 @@ MODULE_PARM_DESC(fbdev_emulation,
 		 "Enable legacy fbdev emulation [default=true]");
 
 static LIST_HEAD(kernel_fb_helper_list);
+static DEFINE_MUTEX(kernel_fb_helper_lock);
 
 /**
  * DOC: fbdev helpers
@@ -97,6 +98,10 @@ static LIST_HEAD(kernel_fb_helper_list);
  * mmap page writes.
  */
 
+#define drm_fb_helper_for_each_connector(fbh, i__) \
+	for (({ lockdep_assert_held(&(fbh)->dev->mode_config.mutex); }), \
+	     i__ = 0; i__ < (fbh)->connector_count; i__++)
+
 /**
  * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev
  * 					       emulation helper
@@ -130,7 +135,7 @@ int drm_fb_helper_single_add_all_connect
 	mutex_unlock(&dev->mode_config.mutex);
 	return 0;
 fail:
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		struct drm_fb_helper_connector *fb_helper_connector =
 			fb_helper->connector_info[i];
 
@@ -256,6 +261,9 @@ int drm_fb_helper_debug_enter(struct fb_
 				continue;
 
 			funcs =	mode_set->crtc->helper_private;
+			if (funcs->mode_set_base_atomic == NULL)
+				continue;
+
 			drm_fb_helper_save_lut_atomic(mode_set->crtc, helper);
 			funcs->mode_set_base_atomic(mode_set->crtc,
 						    mode_set->fb,
@@ -309,6 +317,9 @@ int drm_fb_helper_debug_leave(struct fb_
 			continue;
 		}
 
+		if (funcs->mode_set_base_atomic == NULL)
+			continue;
+
 		drm_fb_helper_restore_lut_atomic(mode_set->crtc);
 		funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
 					    crtc->y, LEAVE_ATOMIC_MODE_SET);
@@ -372,9 +383,7 @@ fail:
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	if (ret != 0)
-		drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
 
 backoff:
@@ -399,11 +408,10 @@ static int restore_fbdev_mode(struct drm
 		if (plane->type != DRM_PLANE_TYPE_PRIMARY)
 			drm_plane_force_disable(plane);
 
-		if (dev->mode_config.rotation_property) {
+		if (plane->rotation_property)
 			drm_mode_plane_set_obj_prop(plane,
-						    dev->mode_config.rotation_property,
+						    plane->rotation_property,
 						    DRM_ROTATE_0);
-		}
 	}
 
 	for (i = 0; i < fb_helper->crtc_count; i++) {
@@ -562,7 +570,7 @@ static void drm_fb_helper_dpms(struct fb
 			continue;
 
 		/* Walk the connectors & encoders on this fb turning them on/off */
-		for (j = 0; j < fb_helper->connector_count; j++) {
+		drm_fb_helper_for_each_connector(fb_helper, j) {
 			connector = fb_helper->connector_info[j]->connector;
 			connector->funcs->dpms(connector, dpms_mode);
 			drm_object_property_set_value(&connector->base,
@@ -848,12 +856,14 @@ void drm_fb_helper_fini(struct drm_fb_he
 	if (!drm_fbdev_emulation)
 		return;
 
+	mutex_lock(&kernel_fb_helper_lock);
 	if (!list_empty(&fb_helper->kernel_fb_list)) {
 		list_del(&fb_helper->kernel_fb_list);
 		if (list_empty(&kernel_fb_helper_list)) {
 			unregister_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
 		}
 	}
+	mutex_unlock(&kernel_fb_helper_lock);
 
 	drm_fb_helper_crtc_free(fb_helper);
 
@@ -1238,11 +1248,14 @@ int drm_fb_helper_check_var(struct fb_va
 	if (var->pixclock != 0 || in_dbg_master())
 		return -EINVAL;
 
-	/* Need to resize the fb object !!! */
-	if (var->bits_per_pixel > fb->bits_per_pixel ||
-	    var->xres > fb->width || var->yres > fb->height ||
-	    var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
-		DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
+	/*
+	 * Changes struct fb_var_screeninfo are currently not pushed back
+	 * to KMS, hence fail if different settings are requested.
+	 */
+	if (var->bits_per_pixel != fb->bits_per_pixel ||
+	    var->xres != fb->width || var->yres != fb->height ||
+	    var->xres_virtual != fb->width || var->yres_virtual != fb->height) {
+		DRM_DEBUG("fb userspace requested width/height/bpp different than current fb "
 			  "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
 			  var->xres, var->yres, var->bits_per_pixel,
 			  var->xres_virtual, var->yres_virtual,
@@ -1388,16 +1401,13 @@ retry:
 	info->var.xoffset = var->xoffset;
 	info->var.yoffset = var->yoffset;
 
-
 fail:
 	drm_atomic_clean_old_fb(dev, plane_mask, ret);
 
 	if (ret == -EDEADLK)
 		goto backoff;
 
-	if (ret != 0)
-		drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 	return ret;
 
 backoff:
@@ -1466,7 +1476,6 @@ static int drm_fb_helper_single_fb_probe
 	int ret = 0;
 	int crtc_count = 0;
 	int i;
-	struct fb_info *info;
 	struct drm_fb_helper_surface_size sizes;
 	int gamma_size = 0;
 
@@ -1482,7 +1491,7 @@ static int drm_fb_helper_single_fb_probe
 		sizes.surface_depth = sizes.surface_bpp = preferred_bpp;
 
 	/* first up get a count of crtcs now in use and new min/maxes width/heights */
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
 		struct drm_cmdline_mode *cmdline_mode;
 
@@ -1569,8 +1578,6 @@ static int drm_fb_helper_single_fb_probe
 	if (ret < 0)
 		return ret;
 
-	info = fb_helper->fbdev;
-
 	/*
 	 * Set the fb pointer - usually drm_setup_crtcs does this for hotplug
 	 * events, but at init time drm_setup_crtcs needs to be called before
@@ -1582,20 +1589,6 @@ static int drm_fb_helper_single_fb_probe
 		if (fb_helper->crtc_info[i].mode_set.num_connectors)
 			fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
 
-
-	info->var.pixclock = 0;
-	if (register_framebuffer(info) < 0)
-		return -EINVAL;
-
-	dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
-			info->node, info->fix.id);
-
-	if (list_empty(&kernel_fb_helper_list)) {
-		register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
-	}
-
-	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
-
 	return 0;
 }
 
@@ -1727,7 +1720,7 @@ static int drm_fb_helper_probe_connector
 	int count = 0;
 	int i;
 
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		connector = fb_helper->connector_info[i]->connector;
 		count += connector->funcs->fill_modes(connector, maxX, maxY);
 	}
@@ -1827,7 +1820,7 @@ static void drm_enable_connectors(struct
 	struct drm_connector *connector;
 	int i = 0;
 
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		connector = fb_helper->connector_info[i]->connector;
 		enabled[i] = drm_connector_enabled(connector, true);
 		DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id,
@@ -1838,7 +1831,7 @@ static void drm_enable_connectors(struct
 	if (any_enabled)
 		return;
 
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		connector = fb_helper->connector_info[i]->connector;
 		enabled[i] = drm_connector_enabled(connector, false);
 	}
@@ -1859,7 +1852,7 @@ static bool drm_target_cloned(struct drm
 		return false;
 
 	count = 0;
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		if (enabled[i])
 			count++;
 	}
@@ -1870,7 +1863,7 @@ static bool drm_target_cloned(struct drm
 
 	/* check the command line or if nothing common pick 1024x768 */
 	can_clone = true;
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		if (!enabled[i])
 			continue;
 		fb_helper_conn = fb_helper->connector_info[i];
@@ -1896,8 +1889,7 @@ static bool drm_target_cloned(struct drm
 	can_clone = true;
 	dmt_mode = drm_mode_find_dmt(fb_helper->dev, 1024, 768, 60, false);
 
-	for (i = 0; i < fb_helper->connector_count; i++) {
-
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		if (!enabled[i])
 			continue;
 
@@ -1928,7 +1920,7 @@ static int drm_get_tile_offsets(struct d
 	int i;
 	int hoffset = 0, voffset = 0;
 
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		fb_helper_conn = fb_helper->connector_info[i];
 		if (!fb_helper_conn->connector->has_tile)
 			continue;
@@ -1956,19 +1948,20 @@ static bool drm_target_preferred(struct
 				 bool *enabled, int width, int height)
 {
 	struct drm_fb_helper_connector *fb_helper_conn;
-	int i;
-	uint64_t conn_configured = 0, mask;
+	const u64 mask = BIT_ULL(fb_helper->connector_count) - 1;
+	u64 conn_configured = 0;
 	int tile_pass = 0;
-	mask = (1 << fb_helper->connector_count) - 1;
+	int i;
+
 retry:
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		fb_helper_conn = fb_helper->connector_info[i];
 
-		if (conn_configured & (1 << i))
+		if (conn_configured & BIT_ULL(i))
 			continue;
 
 		if (enabled[i] == false) {
-			conn_configured |= (1 << i);
+			conn_configured |= BIT_ULL(i);
 			continue;
 		}
 
@@ -2009,7 +2002,7 @@ retry:
 		}
 		DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name :
 			  "none");
-		conn_configured |= (1 << i);
+		conn_configured |= BIT_ULL(i);
 	}
 
 	if ((conn_configured & mask) != mask) {
@@ -2109,20 +2102,22 @@ out:
 	return best_score;
 }
 
-static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
+static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
+			    u32 width, u32 height)
 {
 	struct drm_device *dev = fb_helper->dev;
 	struct drm_fb_helper_crtc **crtcs;
 	struct drm_display_mode **modes;
 	struct drm_fb_offset *offsets;
 	bool *enabled;
-	int width, height;
 	int i;
 
 	DRM_DEBUG_KMS("\n");
+	if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0)
+		DRM_DEBUG_KMS("No connectors reported connected with modes\n");
 
-	width = dev->mode_config.max_width;
-	height = dev->mode_config.max_height;
+	/* prevent concurrent modification of connector_count by hotplug */
+	lockdep_assert_held(&fb_helper->dev->mode_config.mutex);
 
 	crtcs = kcalloc(fb_helper->connector_count,
 			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
@@ -2137,7 +2132,6 @@ static void drm_setup_crtcs(struct drm_f
 		goto out;
 	}
 
-
 	drm_enable_connectors(fb_helper, enabled);
 
 	if (!(fb_helper->funcs->initial_config &&
@@ -2166,7 +2160,7 @@ static void drm_setup_crtcs(struct drm_f
 		drm_fb_helper_modeset_release(fb_helper,
 					      &fb_helper->crtc_info[i].mode_set);
 
-	for (i = 0; i < fb_helper->connector_count; i++) {
+	drm_fb_helper_for_each_connector(fb_helper, i) {
 		struct drm_display_mode *mode = modes[i];
 		struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
 		struct drm_fb_offset *offset = &offsets[i];
@@ -2243,25 +2237,38 @@ out:
 int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
 {
 	struct drm_device *dev = fb_helper->dev;
-	int count = 0;
+	struct fb_info *info;
+	int ret;
 
 	if (!drm_fbdev_emulation)
 		return 0;
 
 	mutex_lock(&dev->mode_config.mutex);
-	count = drm_fb_helper_probe_connector_modes(fb_helper,
-						    dev->mode_config.max_width,
-						    dev->mode_config.max_height);
+	drm_setup_crtcs(fb_helper,
+			dev->mode_config.max_width,
+			dev->mode_config.max_height);
+	ret = drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
 	mutex_unlock(&dev->mode_config.mutex);
-	/*
-	 * we shouldn't end up with no modes here.
-	 */
-	if (count == 0)
-		dev_info(fb_helper->dev->dev, "No connectors reported connected with modes\n");
+	if (ret)
+		return ret;
 
-	drm_setup_crtcs(fb_helper);
+	info = fb_helper->fbdev;
+	info->var.pixclock = 0;
+	ret = register_framebuffer(info);
+	if (ret < 0)
+		return ret;
 
-	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
+	dev_info(dev->dev, "fb%d: %s frame buffer device\n",
+		 info->node, info->fix.id);
+
+	mutex_lock(&kernel_fb_helper_lock);
+	if (list_empty(&kernel_fb_helper_list))
+		register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
+
+	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
+	mutex_unlock(&kernel_fb_helper_lock);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_fb_helper_initial_config);
 
@@ -2289,28 +2296,22 @@ EXPORT_SYMBOL(drm_fb_helper_initial_conf
 int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 {
 	struct drm_device *dev = fb_helper->dev;
-	u32 max_width, max_height;
 
 	if (!drm_fbdev_emulation)
 		return 0;
 
-	mutex_lock(&fb_helper->dev->mode_config.mutex);
+	mutex_lock(&dev->mode_config.mutex);
 	if (!fb_helper->fb || !drm_fb_helper_is_bound(fb_helper)) {
 		fb_helper->delayed_hotplug = true;
-		mutex_unlock(&fb_helper->dev->mode_config.mutex);
+		mutex_unlock(&dev->mode_config.mutex);
 		return 0;
 	}
 	DRM_DEBUG_KMS("\n");
 
-	max_width = fb_helper->fb->width;
-	max_height = fb_helper->fb->height;
+	drm_setup_crtcs(fb_helper, fb_helper->fb->width, fb_helper->fb->height);
 
-	drm_fb_helper_probe_connector_modes(fb_helper, max_width, max_height);
-	mutex_unlock(&fb_helper->dev->mode_config.mutex);
+	mutex_unlock(&dev->mode_config.mutex);
 
-	drm_modeset_lock_all(dev);
-	drm_setup_crtcs(fb_helper);
-	drm_modeset_unlock_all(dev);
 	drm_fb_helper_set_par(fb_helper->fbdev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_fops.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fops.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_fops.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fops.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,10 +51,11 @@ DEFINE_MUTEX(drm_global_mutex);
  * Drivers must define the file operations structure that forms the DRM
  * userspace API entry point, even though most of those operations are
  * implemented in the DRM core. The mandatory functions are drm_open(),
- * drm_read(), drm_ioctl() and drm_compat_ioctl if CONFIG_COMPAT is enabled.
- * Drivers which implement private ioctls that require 32/64 bit compatibility
- * support must provided their onw .compat_ioctl() handler that processes
- * private ioctls and calls drm_compat_ioctl() for core ioctls.
+ * drm_read(), drm_ioctl() and drm_compat_ioctl() if CONFIG_COMPAT is enabled
+ * (note that drm_compat_ioctl will be NULL if CONFIG_COMPAT=n). Drivers which
+ * implement private ioctls that require 32/64 bit compatibility support must
+ * provide their own .compat_ioctl() handler that processes private ioctls and
+ * calls drm_compat_ioctl() for core ioctls.
  *
  * In addition drm_read() and drm_poll() provide support for DRM events. DRM
  * events are a generic and extensible means to send asynchronous events to
@@ -75,9 +76,7 @@ DEFINE_MUTEX(drm_global_mutex);
  *             .open = drm_open,
  *             .release = drm_release,
  *             .unlocked_ioctl = drm_ioctl,
- *     #ifdef CONFIG_COMPAT
- *             .compat_ioctl = drm_compat_ioctl,
- *     #endif
+ *             .compat_ioctl = drm_compat_ioctl, // NULL if CONFIG_COMPAT=n
  *             .poll = drm_poll,
  *             .read = drm_read,
  *             .llseek = no_llseek,
@@ -663,6 +662,10 @@ void drm_event_cancel_free(struct drm_de
 		list_del(&p->pending_link);
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	if (p->fence)
+		dma_fence_put(p->fence);
+
 	kfree(p);
 }
 EXPORT_SYMBOL(drm_event_cancel_free);
@@ -692,8 +695,8 @@ void drm_send_event_locked(struct drm_de
 	}
 
 	if (e->fence) {
-		fence_signal(e->fence);
-		fence_put(e->fence);
+		dma_fence_signal(e->fence);
+		dma_fence_put(e->fence);
 	}
 
 	if (!e->file_priv) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_fourcc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fourcc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_fourcc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_fourcc.c	2017-02-12 16:03:20.000000000 -0500
@@ -79,17 +79,13 @@ uint32_t drm_mode_legacy_fb_format(uint3
 EXPORT_SYMBOL(drm_mode_legacy_fb_format);
 
 /**
- * drm_get_format_name - return a string for drm fourcc format
+ * drm_get_format_name - fill a string with a drm fourcc format's name
  * @format: format to compute name of
- *
- * Note that the buffer returned by this function is owned by the caller
- * and will need to be freed using kfree().
+ * @buf: caller-supplied buffer
  */
-char *drm_get_format_name(uint32_t format)
+const char *drm_get_format_name(uint32_t format, struct drm_format_name_buf *buf)
 {
-	char *buf = kmalloc(32, GFP_KERNEL);
-
-	snprintf(buf, 32,
+	snprintf(buf->str, sizeof(buf->str),
 		 "%c%c%c%c %s-endian (0x%08x)",
 		 printable_char(format & 0xff),
 		 printable_char((format >> 8) & 0xff),
@@ -98,87 +94,109 @@ char *drm_get_format_name(uint32_t forma
 		 format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
 		 format);
 
-	return buf;
+	return buf->str;
 }
 EXPORT_SYMBOL(drm_get_format_name);
 
+/*
+ * Internal function to query information for a given format. See
+ * drm_format_info() for the public API.
+ */
+const struct drm_format_info *__drm_format_info(u32 format)
+{
+	static const struct drm_format_info formats[] = {
+		{ .format = DRM_FORMAT_C8,		.depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGB332,		.depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGR233,		.depth = 8,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XRGB4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XBGR4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBX4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRX4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ARGB4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ABGR4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBA4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRA4444,	.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XRGB1555,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XBGR1555,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBX5551,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRX5551,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ARGB1555,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ABGR1555,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBA5551,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRA5551,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGB565,		.depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGR565,		.depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGB888,		.depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGR888,		.depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XRGB8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XBGR8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBX8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRX8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XRGB2101010,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XBGR2101010,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBX1010102,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRX1010102,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ARGB2101010,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ABGR2101010,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBA1010102,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRA1010102,	.depth = 30, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ARGB8888,	.depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_ABGR8888,	.depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGBA8888,	.depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_BGRA8888,	.depth = 32, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_YUV410,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
+		{ .format = DRM_FORMAT_YVU410,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 4 },
+		{ .format = DRM_FORMAT_YUV411,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
+		{ .format = DRM_FORMAT_YVU411,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 4, .vsub = 1 },
+		{ .format = DRM_FORMAT_YUV420,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
+		{ .format = DRM_FORMAT_YVU420,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 2 },
+		{ .format = DRM_FORMAT_YUV422,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_YVU422,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_YUV444,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_YVU444,		.depth = 0,  .num_planes = 3, .cpp = { 1, 1, 1 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_NV12,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
+		{ .format = DRM_FORMAT_NV21,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 2 },
+		{ .format = DRM_FORMAT_NV16,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_NV61,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_NV24,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_NV42,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_YUYV,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_YVYU,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_UYVY,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_VYUY,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1 },
+		{ .format = DRM_FORMAT_AYUV,		.depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+	};
+
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+		if (formats[i].format == format)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
 /**
- * drm_fb_get_bpp_depth - get the bpp/depth values for format
+ * drm_format_info - query information for a given format
  * @format: pixel format (DRM_FORMAT_*)
- * @depth: storage for the depth value
- * @bpp: storage for the bpp value
  *
- * This only supports RGB formats here for compat with code that doesn't use
- * pixel formats directly yet.
+ * The caller should only pass a supported pixel format to this function.
+ * Unsupported pixel formats will generate a warning in the kernel log.
+ *
+ * Returns:
+ * The instance of struct drm_format_info that describes the pixel format, or
+ * NULL if the format is unsupported.
  */
-void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
-			  int *bpp)
+const struct drm_format_info *drm_format_info(u32 format)
 {
-	char *format_name;
+	const struct drm_format_info *info;
 
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB332:
-	case DRM_FORMAT_BGR233:
-		*depth = 8;
-		*bpp = 8;
-		break;
-	case DRM_FORMAT_XRGB1555:
-	case DRM_FORMAT_XBGR1555:
-	case DRM_FORMAT_RGBX5551:
-	case DRM_FORMAT_BGRX5551:
-	case DRM_FORMAT_ARGB1555:
-	case DRM_FORMAT_ABGR1555:
-	case DRM_FORMAT_RGBA5551:
-	case DRM_FORMAT_BGRA5551:
-		*depth = 15;
-		*bpp = 16;
-		break;
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_BGR565:
-		*depth = 16;
-		*bpp = 16;
-		break;
-	case DRM_FORMAT_RGB888:
-	case DRM_FORMAT_BGR888:
-		*depth = 24;
-		*bpp = 24;
-		break;
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_RGBX8888:
-	case DRM_FORMAT_BGRX8888:
-		*depth = 24;
-		*bpp = 32;
-		break;
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_RGBX1010102:
-	case DRM_FORMAT_BGRX1010102:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_RGBA1010102:
-	case DRM_FORMAT_BGRA1010102:
-		*depth = 30;
-		*bpp = 32;
-		break;
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_RGBA8888:
-	case DRM_FORMAT_BGRA8888:
-		*depth = 32;
-		*bpp = 32;
-		break;
-	default:
-		format_name = drm_get_format_name(format);
-		DRM_DEBUG_KMS("unsupported pixel format %s\n", format_name);
-		kfree(format_name);
-		*depth = 0;
-		*bpp = 0;
-		break;
-	}
+	info = __drm_format_info(format);
+	WARN_ON(!info);
+	return info;
 }
-EXPORT_SYMBOL(drm_fb_get_bpp_depth);
+EXPORT_SYMBOL(drm_format_info);
 
 /**
  * drm_format_num_planes - get the number of planes for format
@@ -189,28 +207,10 @@ EXPORT_SYMBOL(drm_fb_get_bpp_depth);
  */
 int drm_format_num_planes(uint32_t format)
 {
-	switch (format) {
-	case DRM_FORMAT_YUV410:
-	case DRM_FORMAT_YVU410:
-	case DRM_FORMAT_YUV411:
-	case DRM_FORMAT_YVU411:
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YUV422:
-	case DRM_FORMAT_YVU422:
-	case DRM_FORMAT_YUV444:
-	case DRM_FORMAT_YVU444:
-		return 3;
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-	case DRM_FORMAT_NV24:
-	case DRM_FORMAT_NV42:
-		return 2;
-	default:
-		return 1;
-	}
+	const struct drm_format_info *info;
+
+	info = drm_format_info(format);
+	return info ? info->num_planes : 1;
 }
 EXPORT_SYMBOL(drm_format_num_planes);
 
@@ -224,40 +224,13 @@ EXPORT_SYMBOL(drm_format_num_planes);
  */
 int drm_format_plane_cpp(uint32_t format, int plane)
 {
-	unsigned int depth;
-	int bpp;
+	const struct drm_format_info *info;
 
-	if (plane >= drm_format_num_planes(format))
+	info = drm_format_info(format);
+	if (!info || plane >= info->num_planes)
 		return 0;
 
-	switch (format) {
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-		return 2;
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-	case DRM_FORMAT_NV24:
-	case DRM_FORMAT_NV42:
-		return plane ? 2 : 1;
-	case DRM_FORMAT_YUV410:
-	case DRM_FORMAT_YVU410:
-	case DRM_FORMAT_YUV411:
-	case DRM_FORMAT_YVU411:
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YUV422:
-	case DRM_FORMAT_YVU422:
-	case DRM_FORMAT_YUV444:
-	case DRM_FORMAT_YVU444:
-		return 1;
-	default:
-		drm_fb_get_bpp_depth(format, &depth, &bpp);
-		return bpp >> 3;
-	}
+	return info->cpp[plane];
 }
 EXPORT_SYMBOL(drm_format_plane_cpp);
 
@@ -271,28 +244,10 @@ EXPORT_SYMBOL(drm_format_plane_cpp);
  */
 int drm_format_horz_chroma_subsampling(uint32_t format)
 {
-	switch (format) {
-	case DRM_FORMAT_YUV411:
-	case DRM_FORMAT_YVU411:
-	case DRM_FORMAT_YUV410:
-	case DRM_FORMAT_YVU410:
-		return 4;
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-	case DRM_FORMAT_YUV422:
-	case DRM_FORMAT_YVU422:
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-		return 2;
-	default:
-		return 1;
-	}
+	const struct drm_format_info *info;
+
+	info = drm_format_info(format);
+	return info ? info->hsub : 1;
 }
 EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
 
@@ -306,18 +261,10 @@ EXPORT_SYMBOL(drm_format_horz_chroma_sub
  */
 int drm_format_vert_chroma_subsampling(uint32_t format)
 {
-	switch (format) {
-	case DRM_FORMAT_YUV410:
-	case DRM_FORMAT_YVU410:
-		return 4;
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-		return 2;
-	default:
-		return 1;
-	}
+	const struct drm_format_info *info;
+
+	info = drm_format_info(format);
+	return info ? info->vsub : 1;
 }
 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
 
@@ -332,13 +279,16 @@ EXPORT_SYMBOL(drm_format_vert_chroma_sub
  */
 int drm_format_plane_width(int width, uint32_t format, int plane)
 {
-	if (plane >= drm_format_num_planes(format))
+	const struct drm_format_info *info;
+
+	info = drm_format_info(format);
+	if (!info || plane >= info->num_planes)
 		return 0;
 
 	if (plane == 0)
 		return width;
 
-	return width / drm_format_horz_chroma_subsampling(format);
+	return width / info->hsub;
 }
 EXPORT_SYMBOL(drm_format_plane_width);
 
@@ -353,12 +303,15 @@ EXPORT_SYMBOL(drm_format_plane_width);
  */
 int drm_format_plane_height(int height, uint32_t format, int plane)
 {
-	if (plane >= drm_format_num_planes(format))
+	const struct drm_format_info *info;
+
+	info = drm_format_info(format);
+	if (!info || plane >= info->num_planes)
 		return 0;
 
 	if (plane == 0)
 		return height;
 
-	return height / drm_format_vert_chroma_subsampling(format);
+	return height / info->vsub;
 }
 EXPORT_SYMBOL(drm_format_plane_height);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_framebuffer.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_framebuffer.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_framebuffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_framebuffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -126,111 +126,34 @@ int drm_mode_addfb(struct drm_device *de
 	return 0;
 }
 
-static int format_check(const struct drm_mode_fb_cmd2 *r)
-{
-	uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
-	char *format_name;
-
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB332:
-	case DRM_FORMAT_BGR233:
-	case DRM_FORMAT_XRGB4444:
-	case DRM_FORMAT_XBGR4444:
-	case DRM_FORMAT_RGBX4444:
-	case DRM_FORMAT_BGRX4444:
-	case DRM_FORMAT_ARGB4444:
-	case DRM_FORMAT_ABGR4444:
-	case DRM_FORMAT_RGBA4444:
-	case DRM_FORMAT_BGRA4444:
-	case DRM_FORMAT_XRGB1555:
-	case DRM_FORMAT_XBGR1555:
-	case DRM_FORMAT_RGBX5551:
-	case DRM_FORMAT_BGRX5551:
-	case DRM_FORMAT_ARGB1555:
-	case DRM_FORMAT_ABGR1555:
-	case DRM_FORMAT_RGBA5551:
-	case DRM_FORMAT_BGRA5551:
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_BGR565:
-	case DRM_FORMAT_RGB888:
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_RGBX8888:
-	case DRM_FORMAT_BGRX8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_RGBA8888:
-	case DRM_FORMAT_BGRA8888:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_RGBX1010102:
-	case DRM_FORMAT_BGRX1010102:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_RGBA1010102:
-	case DRM_FORMAT_BGRA1010102:
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_AYUV:
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-	case DRM_FORMAT_NV24:
-	case DRM_FORMAT_NV42:
-	case DRM_FORMAT_YUV410:
-	case DRM_FORMAT_YVU410:
-	case DRM_FORMAT_YUV411:
-	case DRM_FORMAT_YVU411:
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YUV422:
-	case DRM_FORMAT_YVU422:
-	case DRM_FORMAT_YUV444:
-	case DRM_FORMAT_YVU444:
-		return 0;
-	default:
-		format_name = drm_get_format_name(r->pixel_format);
-		DRM_DEBUG_KMS("invalid pixel format %s\n", format_name);
-		kfree(format_name);
-		return -EINVAL;
-	}
-}
-
 static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
 {
-	int ret, hsub, vsub, num_planes, i;
+	const struct drm_format_info *info;
+	int i;
 
-	ret = format_check(r);
-	if (ret) {
-		char *format_name = drm_get_format_name(r->pixel_format);
-		DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name);
-		kfree(format_name);
-		return ret;
+	info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN);
+	if (!info) {
+		struct drm_format_name_buf format_name;
+		DRM_DEBUG_KMS("bad framebuffer format %s\n",
+		              drm_get_format_name(r->pixel_format,
+		                                  &format_name));
+		return -EINVAL;
 	}
 
-	hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
-	vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
-	num_planes = drm_format_num_planes(r->pixel_format);
-
-	if (r->width == 0 || r->width % hsub) {
+	if (r->width == 0 || r->width % info->hsub) {
 		DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
 		return -EINVAL;
 	}
 
-	if (r->height == 0 || r->height % vsub) {
+	if (r->height == 0 || r->height % info->vsub) {
 		DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
 		return -EINVAL;
 	}
 
-	for (i = 0; i < num_planes; i++) {
-		unsigned int width = r->width / (i != 0 ? hsub : 1);
-		unsigned int height = r->height / (i != 0 ? vsub : 1);
-		unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
+	for (i = 0; i < info->num_planes; i++) {
+		unsigned int width = r->width / (i != 0 ? info->hsub : 1);
+		unsigned int height = r->height / (i != 0 ? info->vsub : 1);
+		unsigned int cpp = info->cpp[i];
 
 		if (!r->handles[i]) {
 			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
@@ -254,6 +177,13 @@ static int framebuffer_check(const struc
 			return -EINVAL;
 		}
 
+		if (r->flags & DRM_MODE_FB_MODIFIERS &&
+		    r->modifier[i] != r->modifier[0]) {
+			DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
+				      r->modifier[i], i);
+			return -EINVAL;
+		}
+
 		/* modifier specific checks: */
 		switch (r->modifier[i]) {
 		case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
@@ -273,7 +203,7 @@ static int framebuffer_check(const struc
 		}
 	}
 
-	for (i = num_planes; i < 4; i++) {
+	for (i = info->num_planes; i < 4; i++) {
 		if (r->modifier[i]) {
 			DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
 			return -EINVAL;
@@ -751,6 +681,11 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
  * those used for fbdev. Note that the caller must hold a reference of it's own,
  * i.e. the object may not be destroyed through this call (since it'll lead to a
  * locking inversion).
+ *
+ * NOTE: This function is deprecated. For driver-private framebuffers it is not
+ * recommended to embed a framebuffer struct info fbdev struct, instead, a
+ * framebuffer pointer is preferred and drm_framebuffer_unreference() should be
+ * called when the framebuffer is to be cleaned up.
  */
 void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_internal.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_internal.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_internal.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_internal.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,9 +24,6 @@
 #define DRM_IF_MAJOR 1
 #define DRM_IF_MINOR 4
 
-/* drm_irq.c */
-extern unsigned int drm_timestamp_monotonic;
-
 /* drm_fops.c */
 extern struct mutex drm_global_mutex;
 void drm_lastclose(struct drm_device *dev);
@@ -46,12 +43,21 @@ void drm_prime_destroy_file_private(stru
 void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
 					struct dma_buf *dma_buf);
 
+/* drm_drv.c */
+struct drm_minor *drm_minor_acquire(unsigned int minor_id);
+void drm_minor_release(struct drm_minor *minor);
+
 /* drm_info.c */
 int drm_name_info(struct seq_file *m, void *data);
 int drm_clients_info(struct seq_file *m, void* data);
 int drm_gem_name_info(struct seq_file *m, void *data);
 
 /* drm_irq.c */
+extern unsigned int drm_timestamp_monotonic;
+
+/* IOCTLS */
+int drm_wait_vblank(struct drm_device *dev, void *data,
+		    struct drm_file *filp);
 int drm_control(struct drm_device *dev, void *data,
 		struct drm_file *file_priv);
 int drm_modeset_ctl(struct drm_device *dev, void *data,
@@ -100,6 +106,9 @@ int drm_debugfs_init(struct drm_minor *m
 int drm_debugfs_cleanup(struct drm_minor *minor);
 int drm_debugfs_connector_add(struct drm_connector *connector);
 void drm_debugfs_connector_remove(struct drm_connector *connector);
+int drm_debugfs_crtc_add(struct drm_crtc *crtc);
+void drm_debugfs_crtc_remove(struct drm_crtc *crtc);
+int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc);
 #else
 static inline int drm_debugfs_init(struct drm_minor *minor, int minor_id,
 				   struct dentry *root)
@@ -119,4 +128,17 @@ static inline int drm_debugfs_connector_
 static inline void drm_debugfs_connector_remove(struct drm_connector *connector)
 {
 }
+
+static inline int drm_debugfs_crtc_add(struct drm_crtc *crtc)
+{
+	return 0;
+}
+static inline void drm_debugfs_crtc_remove(struct drm_crtc *crtc)
+{
+}
+
+static inline int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
+{
+	return 0;
+}
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_ioctl.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_ioctl.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -229,6 +229,22 @@ static int drm_getcap(struct drm_device
 	struct drm_crtc *crtc;
 
 	req->value = 0;
+
+	/* Only some caps make sense with UMS/render-only drivers. */
+	switch (req->capability) {
+	case DRM_CAP_TIMESTAMP_MONOTONIC:
+		req->value = drm_timestamp_monotonic;
+		return 0;
+	case DRM_CAP_PRIME:
+		req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
+		req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
+		return 0;
+	}
+
+	/* Other caps only work with KMS drivers */
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -ENOTSUPP;
+
 	switch (req->capability) {
 	case DRM_CAP_DUMB_BUFFER:
 		if (dev->driver->dumb_create)
@@ -243,23 +259,14 @@ static int drm_getcap(struct drm_device
 	case DRM_CAP_DUMB_PREFER_SHADOW:
 		req->value = dev->mode_config.prefer_shadow;
 		break;
-	case DRM_CAP_PRIME:
-		req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0;
-		req->value |= dev->driver->prime_handle_to_fd ? DRM_PRIME_CAP_EXPORT : 0;
-		break;
-	case DRM_CAP_TIMESTAMP_MONOTONIC:
-		req->value = drm_timestamp_monotonic;
-		break;
 	case DRM_CAP_ASYNC_PAGE_FLIP:
 		req->value = dev->mode_config.async_page_flip;
 		break;
 	case DRM_CAP_PAGE_FLIP_TARGET:
-		if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-			req->value = 1;
-			drm_for_each_crtc(crtc, dev) {
-				if (!crtc->funcs->page_flip_target)
-					req->value = 0;
-			}
+		req->value = 1;
+		drm_for_each_crtc(crtc, dev) {
+			if (!crtc->funcs->page_flip_target)
+				req->value = 0;
 		}
 		break;
 	case DRM_CAP_CURSOR_WIDTH:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_irq.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_irq.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -93,7 +93,7 @@ static void store_vblank(struct drm_devi
  * Reset the stored timestamp for the current vblank count to correspond
  * to the last vblank occurred.
  *
- * Only to be called from drm_vblank_on().
+ * Only to be called from drm_crtc_vblank_on().
  *
  * Note: caller must hold dev->vbl_lock since this reads & writes
  * device vblank fields.
@@ -234,6 +234,16 @@ static void drm_update_vblank_count(stru
 	store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
 }
 
+static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
+{
+	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+
+	if (WARN_ON(pipe >= dev->num_crtcs))
+		return 0;
+
+	return vblank->count;
+}
+
 /**
  * drm_accurate_vblank_count - retrieve the master vblank counter
  * @crtc: which counter to retrieve
@@ -296,7 +306,7 @@ static void vblank_disable_and_save(stru
 	 * Always update the count and timestamp to maintain the
 	 * appearance that the counter has been ticking all along until
 	 * this time. This makes the count account for the entire time
-	 * between drm_vblank_on() and drm_vblank_off().
+	 * between drm_crtc_vblank_on() and drm_crtc_vblank_off().
 	 */
 	drm_update_vblank_count(dev, pipe, 0);
 
@@ -888,31 +898,6 @@ drm_get_last_vbltimestamp(struct drm_dev
 }
 
 /**
- * drm_vblank_count - retrieve "cooked" vblank counter value
- * @dev: DRM device
- * @pipe: index of CRTC for which to retrieve the counter
- *
- * Fetches the "cooked" vblank count value that represents the number of
- * vblank events since the system was booted, including lost events due to
- * modesetting activity.
- *
- * This is the legacy version of drm_crtc_vblank_count().
- *
- * Returns:
- * The software vblank counter.
- */
-u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
-{
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
-
-	if (WARN_ON(pipe >= dev->num_crtcs))
-		return 0;
-
-	return vblank->count;
-}
-EXPORT_SYMBOL(drm_vblank_count);
-
-/**
  * drm_crtc_vblank_count - retrieve "cooked" vblank counter value
  * @crtc: which counter to retrieve
  *
@@ -920,8 +905,6 @@ EXPORT_SYMBOL(drm_vblank_count);
  * vblank events since the system was booted, including lost events due to
  * modesetting activity.
  *
- * This is the native KMS version of drm_vblank_count().
- *
  * Returns:
  * The software vblank counter.
  */
@@ -952,8 +935,10 @@ static u32 drm_vblank_count_and_time(str
 	u32 vblank_count;
 	unsigned int seq;
 
-	if (WARN_ON(pipe >= dev->num_crtcs))
+	if (WARN_ON(pipe >= dev->num_crtcs)) {
+		*vblanktime = (struct timeval) { 0 };
 		return 0;
+	}
 
 	do {
 		seq = read_seqbegin(&vblank->seqlock);
@@ -1270,21 +1255,20 @@ void drm_crtc_wait_one_vblank(struct drm
 EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
 
 /**
- * drm_vblank_off - disable vblank events on a CRTC
- * @dev: DRM device
- * @pipe: CRTC index
+ * drm_crtc_vblank_off - disable vblank events on a CRTC
+ * @crtc: CRTC in question
  *
  * Drivers can use this function to shut down the vblank interrupt handling when
  * disabling a crtc. This function ensures that the latest vblank frame count is
- * stored so that drm_vblank_on() can restore it again.
+ * stored so that drm_vblank_on can restore it again.
  *
  * Drivers must use this function when the hardware vblank counter can get
  * reset, e.g. when suspending.
- *
- * This is the legacy version of drm_crtc_vblank_off().
  */
-void drm_vblank_off(struct drm_device *dev, unsigned int pipe)
+void drm_crtc_vblank_off(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = drm_crtc_index(crtc);
 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 	struct drm_pending_vblank_event *e, *t;
 	struct timeval now;
@@ -1300,7 +1284,8 @@ void drm_vblank_off(struct drm_device *d
 	DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
 		      pipe, vblank->enabled, vblank->inmodeset);
 
-	/* Avoid redundant vblank disables without previous drm_vblank_on(). */
+	/* Avoid redundant vblank disables without previous
+	 * drm_crtc_vblank_on(). */
 	if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
 		vblank_disable_and_save(dev, pipe);
 
@@ -1331,25 +1316,6 @@ void drm_vblank_off(struct drm_device *d
 	}
 	spin_unlock_irqrestore(&dev->event_lock, irqflags);
 }
-EXPORT_SYMBOL(drm_vblank_off);
-
-/**
- * drm_crtc_vblank_off - disable vblank events on a CRTC
- * @crtc: CRTC in question
- *
- * Drivers can use this function to shut down the vblank interrupt handling when
- * disabling a crtc. This function ensures that the latest vblank frame count is
- * stored so that drm_vblank_on can restore it again.
- *
- * Drivers must use this function when the hardware vblank counter can get
- * reset, e.g. when suspending.
- *
- * This is the native kms version of drm_vblank_off().
- */
-void drm_crtc_vblank_off(struct drm_crtc *crtc)
-{
-	drm_vblank_off(crtc->dev, drm_crtc_index(crtc));
-}
 EXPORT_SYMBOL(drm_crtc_vblank_off);
 
 /**
@@ -1385,19 +1351,18 @@ void drm_crtc_vblank_reset(struct drm_cr
 EXPORT_SYMBOL(drm_crtc_vblank_reset);
 
 /**
- * drm_vblank_on - enable vblank events on a CRTC
- * @dev: DRM device
- * @pipe: CRTC index
+ * drm_crtc_vblank_on - enable vblank events on a CRTC
+ * @crtc: CRTC in question
  *
  * This functions restores the vblank interrupt state captured with
- * drm_vblank_off() again. Note that calls to drm_vblank_on() and
- * drm_vblank_off() can be unbalanced and so can also be unconditionally called
+ * drm_crtc_vblank_off() again. Note that calls to drm_crtc_vblank_on() and
+ * drm_crtc_vblank_off() can be unbalanced and so can also be unconditionally called
  * in driver load code to reflect the current hardware state of the crtc.
- *
- * This is the legacy version of drm_crtc_vblank_on().
  */
-void drm_vblank_on(struct drm_device *dev, unsigned int pipe)
+void drm_crtc_vblank_on(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
+	unsigned int pipe = drm_crtc_index(crtc);
 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 	unsigned long irqflags;
 
@@ -1424,49 +1389,10 @@ void drm_vblank_on(struct drm_device *de
 		WARN_ON(drm_vblank_enable(dev, pipe));
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
-EXPORT_SYMBOL(drm_vblank_on);
-
-/**
- * drm_crtc_vblank_on - enable vblank events on a CRTC
- * @crtc: CRTC in question
- *
- * This functions restores the vblank interrupt state captured with
- * drm_vblank_off() again. Note that calls to drm_vblank_on() and
- * drm_vblank_off() can be unbalanced and so can also be unconditionally called
- * in driver load code to reflect the current hardware state of the crtc.
- *
- * This is the native kms version of drm_vblank_on().
- */
-void drm_crtc_vblank_on(struct drm_crtc *crtc)
-{
-	drm_vblank_on(crtc->dev, drm_crtc_index(crtc));
-}
 EXPORT_SYMBOL(drm_crtc_vblank_on);
 
-/**
- * drm_vblank_pre_modeset - account for vblanks across mode sets
- * @dev: DRM device
- * @pipe: CRTC index
- *
- * Account for vblank events across mode setting events, which will likely
- * reset the hardware frame counter.
- *
- * This is done by grabbing a temporary vblank reference to ensure that the
- * vblank interrupt keeps running across the modeset sequence. With this the
- * software-side vblank frame counting will ensure that there are no jumps or
- * discontinuities.
- *
- * Unfortunately this approach is racy and also doesn't work when the vblank
- * interrupt stops running, e.g. across system suspend resume. It is therefore
- * highly recommended that drivers use the newer drm_vblank_off() and
- * drm_vblank_on() instead. drm_vblank_pre_modeset() only works correctly when
- * using "cooked" software vblank frame counters and not relying on any hardware
- * counters.
- *
- * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc
- * again.
- */
-void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe)
+static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
+					  unsigned int pipe)
 {
 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 
@@ -1490,17 +1416,9 @@ void drm_vblank_pre_modeset(struct drm_d
 			vblank->inmodeset |= 0x2;
 	}
 }
-EXPORT_SYMBOL(drm_vblank_pre_modeset);
 
-/**
- * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes
- * @dev: DRM device
- * @pipe: CRTC index
- *
- * This function again drops the temporary vblank reference acquired in
- * drm_vblank_pre_modeset.
- */
-void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)
+static void drm_legacy_vblank_post_modeset(struct drm_device *dev,
+					   unsigned int pipe)
 {
 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
 	unsigned long irqflags;
@@ -1523,7 +1441,6 @@ void drm_vblank_post_modeset(struct drm_
 		vblank->inmodeset = 0;
 	}
 }
-EXPORT_SYMBOL(drm_vblank_post_modeset);
 
 /*
  * drm_modeset_ctl - handle vblank event counter changes across mode switch
@@ -1556,10 +1473,10 @@ int drm_modeset_ctl(struct drm_device *d
 
 	switch (modeset->cmd) {
 	case _DRM_PRE_MODESET:
-		drm_vblank_pre_modeset(dev, pipe);
+		drm_legacy_vblank_pre_modeset(dev, pipe);
 		break;
 	case _DRM_POST_MODESET:
-		drm_vblank_post_modeset(dev, pipe);
+		drm_legacy_vblank_post_modeset(dev, pipe);
 		break;
 	default:
 		return -EINVAL;
@@ -1594,11 +1511,10 @@ static int drm_queue_vblank_event(struct
 	spin_lock_irqsave(&dev->event_lock, flags);
 
 	/*
-	 * drm_vblank_off() might have been called after we called
-	 * drm_vblank_get(). drm_vblank_off() holds event_lock
-	 * around the vblank disable, so no need for further locking.
-	 * The reference from drm_vblank_get() protects against
-	 * vblank disable from another source.
+	 * drm_crtc_vblank_off() might have been called after we called
+	 * drm_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
+	 * vblank disable, so no need for further locking.  The reference from
+	 * drm_vblank_get() protects against vblank disable from another source.
 	 */
 	if (!vblank->enabled) {
 		ret = -EINVAL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_lock.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_lock.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_lock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_lock.c	2017-02-12 16:03:20.000000000 -0500
@@ -176,7 +176,8 @@ int drm_legacy_lock(struct drm_device *d
 
 	DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n",
 		  lock->context, task_pid_nr(current),
-		  master->lock.hw_lock->lock, lock->flags);
+		  master->lock.hw_lock ? master->lock.hw_lock->lock : -1,
+		  lock->flags);
 
 	add_wait_queue(&master->lock.lock_queue, &entry);
 	spin_lock_bh(&master->lock.spinlock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_mm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_mm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_mm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_mm.c	2017-02-12 16:03:20.000000000 -0500
@@ -104,6 +104,68 @@ static struct drm_mm_node *drm_mm_search
 						u64 end,
 						enum drm_mm_search_flags flags);
 
+#ifdef CONFIG_DRM_DEBUG_MM
+#include <linux/stackdepot.h>
+
+#define STACKDEPTH 32
+#define BUFSZ 4096
+
+static noinline void save_stack(struct drm_mm_node *node)
+{
+	unsigned long entries[STACKDEPTH];
+	struct stack_trace trace = {
+		.entries = entries,
+		.max_entries = STACKDEPTH,
+		.skip = 1
+	};
+
+	save_stack_trace(&trace);
+	if (trace.nr_entries != 0 &&
+	    trace.entries[trace.nr_entries-1] == ULONG_MAX)
+		trace.nr_entries--;
+
+	/* May be called under spinlock, so avoid sleeping */
+	node->stack = depot_save_stack(&trace, GFP_NOWAIT);
+}
+
+static void show_leaks(struct drm_mm *mm)
+{
+	struct drm_mm_node *node;
+	unsigned long entries[STACKDEPTH];
+	char *buf;
+
+	buf = kmalloc(BUFSZ, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	list_for_each_entry(node, &mm->head_node.node_list, node_list) {
+		struct stack_trace trace = {
+			.entries = entries,
+			.max_entries = STACKDEPTH
+		};
+
+		if (!node->stack) {
+			DRM_ERROR("node [%08llx + %08llx]: unknown owner\n",
+				  node->start, node->size);
+			continue;
+		}
+
+		depot_fetch_stack(node->stack, &trace);
+		snprint_stack_trace(buf, BUFSZ, &trace, 0);
+		DRM_ERROR("node [%08llx + %08llx]: inserted at\n%s",
+			  node->start, node->size, buf);
+	}
+
+	kfree(buf);
+}
+
+#undef STACKDEPTH
+#undef BUFSZ
+#else
+static void save_stack(struct drm_mm_node *node) { }
+static void show_leaks(struct drm_mm *mm) { }
+#endif
+
 #define START(node) ((node)->start)
 #define LAST(node)  ((node)->start + (node)->size - 1)
 
@@ -112,19 +174,12 @@ INTERVAL_TREE_DEFINE(struct drm_mm_node,
 		     START, LAST, static inline, drm_mm_interval_tree)
 
 struct drm_mm_node *
-drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last)
+__drm_mm_interval_first(struct drm_mm *mm, u64 start, u64 last)
 {
 	return drm_mm_interval_tree_iter_first(&mm->interval_tree,
 					       start, last);
 }
-EXPORT_SYMBOL(drm_mm_interval_first);
-
-struct drm_mm_node *
-drm_mm_interval_next(struct drm_mm_node *node, u64 start, u64 last)
-{
-	return drm_mm_interval_tree_iter_next(node, start, last);
-}
-EXPORT_SYMBOL(drm_mm_interval_next);
+EXPORT_SYMBOL(__drm_mm_interval_first);
 
 static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
 					  struct drm_mm_node *node)
@@ -228,6 +283,8 @@ static void drm_mm_insert_helper(struct
 		list_add(&node->hole_stack, &mm->hole_stack);
 		node->hole_follows = 1;
 	}
+
+	save_stack(node);
 }
 
 /**
@@ -249,6 +306,7 @@ int drm_mm_reserve_node(struct drm_mm *m
 	u64 end = node->start + node->size;
 	struct drm_mm_node *hole;
 	u64 hole_start, hole_end;
+	u64 adj_start, adj_end;
 
 	if (WARN_ON(node->size == 0))
 		return -EINVAL;
@@ -270,9 +328,13 @@ int drm_mm_reserve_node(struct drm_mm *m
 	if (!hole->hole_follows)
 		return -ENOSPC;
 
-	hole_start = __drm_mm_hole_node_start(hole);
-	hole_end = __drm_mm_hole_node_end(hole);
-	if (hole_start > node->start || hole_end < end)
+	adj_start = hole_start = __drm_mm_hole_node_start(hole);
+	adj_end = hole_end = __drm_mm_hole_node_end(hole);
+
+	if (mm->color_adjust)
+		mm->color_adjust(hole, node->color, &adj_start, &adj_end);
+
+	if (adj_start > node->start || adj_end < end)
 		return -ENOSPC;
 
 	node->mm = mm;
@@ -293,6 +355,8 @@ int drm_mm_reserve_node(struct drm_mm *m
 		node->hole_follows = 1;
 	}
 
+	save_stack(node);
+
 	return 0;
 }
 EXPORT_SYMBOL(drm_mm_reserve_node);
@@ -397,6 +461,8 @@ static void drm_mm_insert_helper_range(s
 		list_add(&node->hole_stack, &mm->hole_stack);
 		node->hole_follows = 1;
 	}
+
+	save_stack(node);
 }
 
 /**
@@ -839,6 +905,7 @@ void drm_mm_init(struct drm_mm * mm, u64
 
 	/* Clever trick to avoid a special case in the free hole tracking. */
 	INIT_LIST_HEAD(&mm->head_node.node_list);
+	mm->head_node.allocated = 0;
 	mm->head_node.hole_follows = 1;
 	mm->head_node.scanned_block = 0;
 	mm->head_node.scanned_prev_free = 0;
@@ -861,10 +928,12 @@ EXPORT_SYMBOL(drm_mm_init);
  * Note that it is a bug to call this function on an allocator which is not
  * clean.
  */
-void drm_mm_takedown(struct drm_mm * mm)
+void drm_mm_takedown(struct drm_mm *mm)
 {
-	WARN(!list_empty(&mm->head_node.node_list),
-	     "Memory manager not clean during takedown.\n");
+	if (WARN(!list_empty(&mm->head_node.node_list),
+		 "Memory manager not clean during takedown.\n"))
+		show_leaks(mm);
+
 }
 EXPORT_SYMBOL(drm_mm_takedown);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_mode_config.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_mode_config.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_mode_config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_mode_config.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <drm/drm_mode_config.h>
+#include <drm/drmP.h>
+
+#include "drm_crtc_internal.h"
+#include "drm_internal.h"
+
+int drm_modeset_register_all(struct drm_device *dev)
+{
+	int ret;
+
+	ret = drm_plane_register_all(dev);
+	if (ret)
+		goto err_plane;
+
+	ret = drm_crtc_register_all(dev);
+	if  (ret)
+		goto err_crtc;
+
+	ret = drm_encoder_register_all(dev);
+	if (ret)
+		goto err_encoder;
+
+	ret = drm_connector_register_all(dev);
+	if (ret)
+		goto err_connector;
+
+	return 0;
+
+err_connector:
+	drm_encoder_unregister_all(dev);
+err_encoder:
+	drm_crtc_unregister_all(dev);
+err_crtc:
+	drm_plane_unregister_all(dev);
+err_plane:
+	return ret;
+}
+
+void drm_modeset_unregister_all(struct drm_device *dev)
+{
+	drm_connector_unregister_all(dev);
+	drm_encoder_unregister_all(dev);
+	drm_crtc_unregister_all(dev);
+	drm_plane_unregister_all(dev);
+}
+
+/**
+ * drm_mode_getresources - get graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Construct a set of configuration description structures and return
+ * them to the user, including CRTC, connector and framebuffer configuration.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getresources(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	struct drm_mode_card_res *card_res = data;
+	struct list_head *lh;
+	struct drm_framebuffer *fb;
+	struct drm_connector *connector;
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	int ret = 0;
+	int connector_count = 0;
+	int crtc_count = 0;
+	int fb_count = 0;
+	int encoder_count = 0;
+	int copied = 0;
+	uint32_t __user *fb_id;
+	uint32_t __user *crtc_id;
+	uint32_t __user *connector_id;
+	uint32_t __user *encoder_id;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+
+	mutex_lock(&file_priv->fbs_lock);
+	/*
+	 * For the non-control nodes we need to limit the list of resources
+	 * by IDs in the group list for this node
+	 */
+	list_for_each(lh, &file_priv->fbs)
+		fb_count++;
+
+	/* handle this in 4 parts */
+	/* FBs */
+	if (card_res->count_fbs >= fb_count) {
+		copied = 0;
+		fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
+		list_for_each_entry(fb, &file_priv->fbs, filp_head) {
+			if (put_user(fb->base.id, fb_id + copied)) {
+				mutex_unlock(&file_priv->fbs_lock);
+				return -EFAULT;
+			}
+			copied++;
+		}
+	}
+	card_res->count_fbs = fb_count;
+	mutex_unlock(&file_priv->fbs_lock);
+
+	/* mode_config.mutex protects the connector list against e.g. DP MST
+	 * connector hot-adding. CRTC/Plane lists are invariant. */
+	mutex_lock(&dev->mode_config.mutex);
+	drm_for_each_crtc(crtc, dev)
+		crtc_count++;
+
+	drm_for_each_connector(connector, dev)
+		connector_count++;
+
+	drm_for_each_encoder(encoder, dev)
+		encoder_count++;
+
+	card_res->max_height = dev->mode_config.max_height;
+	card_res->min_height = dev->mode_config.min_height;
+	card_res->max_width = dev->mode_config.max_width;
+	card_res->min_width = dev->mode_config.min_width;
+
+	/* CRTCs */
+	if (card_res->count_crtcs >= crtc_count) {
+		copied = 0;
+		crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
+		drm_for_each_crtc(crtc, dev) {
+			if (put_user(crtc->base.id, crtc_id + copied)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			copied++;
+		}
+	}
+	card_res->count_crtcs = crtc_count;
+
+	/* Encoders */
+	if (card_res->count_encoders >= encoder_count) {
+		copied = 0;
+		encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
+		drm_for_each_encoder(encoder, dev) {
+			if (put_user(encoder->base.id, encoder_id +
+				     copied)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			copied++;
+		}
+	}
+	card_res->count_encoders = encoder_count;
+
+	/* Connectors */
+	if (card_res->count_connectors >= connector_count) {
+		copied = 0;
+		connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
+		drm_for_each_connector(connector, dev) {
+			if (put_user(connector->base.id,
+				     connector_id + copied)) {
+				ret = -EFAULT;
+				goto out;
+			}
+			copied++;
+		}
+	}
+	card_res->count_connectors = connector_count;
+
+out:
+	mutex_unlock(&dev->mode_config.mutex);
+	return ret;
+}
+
+/**
+ * drm_mode_config_reset - call ->reset callbacks
+ * @dev: drm device
+ *
+ * This functions calls all the crtc's, encoder's and connector's ->reset
+ * callback. Drivers can use this in e.g. their driver load or resume code to
+ * reset hardware and software state.
+ */
+void drm_mode_config_reset(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	drm_for_each_plane(plane, dev)
+		if (plane->funcs->reset)
+			plane->funcs->reset(plane);
+
+	drm_for_each_crtc(crtc, dev)
+		if (crtc->funcs->reset)
+			crtc->funcs->reset(crtc);
+
+	drm_for_each_encoder(encoder, dev)
+		if (encoder->funcs->reset)
+			encoder->funcs->reset(encoder);
+
+	mutex_lock(&dev->mode_config.mutex);
+	drm_for_each_connector(connector, dev)
+		if (connector->funcs->reset)
+			connector->funcs->reset(connector);
+	mutex_unlock(&dev->mode_config.mutex);
+}
+EXPORT_SYMBOL(drm_mode_config_reset);
+
+/*
+ * Global properties
+ */
+static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
+	{ DRM_PLANE_TYPE_OVERLAY, "Overlay" },
+	{ DRM_PLANE_TYPE_PRIMARY, "Primary" },
+	{ DRM_PLANE_TYPE_CURSOR, "Cursor" },
+};
+
+static int drm_mode_create_standard_properties(struct drm_device *dev)
+{
+	struct drm_property *prop;
+	int ret;
+
+	ret = drm_connector_create_standard_properties(dev);
+	if (ret)
+		return ret;
+
+	prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
+					"type", drm_plane_type_enum_list,
+					ARRAY_SIZE(drm_plane_type_enum_list));
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.plane_type_property = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"SRC_X", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_src_x = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"SRC_Y", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_src_y = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"SRC_W", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_src_w = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"SRC_H", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_src_h = prop;
+
+	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
+			"CRTC_X", INT_MIN, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_crtc_x = prop;
+
+	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
+			"CRTC_Y", INT_MIN, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_crtc_y = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"CRTC_W", 0, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_crtc_w = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"CRTC_H", 0, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_crtc_h = prop;
+
+	prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+			"FB_ID", DRM_MODE_OBJECT_FB);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_fb_id = prop;
+
+	prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC,
+			"IN_FENCE_FD", -1, INT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_in_fence_fd = prop;
+
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
+			"OUT_FENCE_PTR", 0, U64_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_out_fence_ptr = prop;
+
+	prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+			"CRTC_ID", DRM_MODE_OBJECT_CRTC);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_crtc_id = prop;
+
+	prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC,
+			"ACTIVE");
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_active = prop;
+
+	prop = drm_property_create(dev,
+			DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB,
+			"MODE_ID", 0);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.prop_mode_id = prop;
+
+	prop = drm_property_create(dev,
+			DRM_MODE_PROP_BLOB,
+			"DEGAMMA_LUT", 0);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.degamma_lut_property = prop;
+
+	prop = drm_property_create_range(dev,
+			DRM_MODE_PROP_IMMUTABLE,
+			"DEGAMMA_LUT_SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.degamma_lut_size_property = prop;
+
+	prop = drm_property_create(dev,
+			DRM_MODE_PROP_BLOB,
+			"CTM", 0);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.ctm_property = prop;
+
+	prop = drm_property_create(dev,
+			DRM_MODE_PROP_BLOB,
+			"GAMMA_LUT", 0);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.gamma_lut_property = prop;
+
+	prop = drm_property_create_range(dev,
+			DRM_MODE_PROP_IMMUTABLE,
+			"GAMMA_LUT_SIZE", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.gamma_lut_size_property = prop;
+
+	return 0;
+}
+
+/**
+ * drm_mode_config_init - initialize DRM mode_configuration structure
+ * @dev: DRM device
+ *
+ * Initialize @dev's mode_config structure, used for tracking the graphics
+ * configuration of @dev.
+ *
+ * Since this initializes the modeset locks, no locking is possible. Which is no
+ * problem, since this should happen single threaded at init time. It is the
+ * driver's problem to ensure this guarantee.
+ *
+ */
+void drm_mode_config_init(struct drm_device *dev)
+{
+	mutex_init(&dev->mode_config.mutex);
+	drm_modeset_lock_init(&dev->mode_config.connection_mutex);
+	mutex_init(&dev->mode_config.idr_mutex);
+	mutex_init(&dev->mode_config.fb_lock);
+	mutex_init(&dev->mode_config.blob_lock);
+	INIT_LIST_HEAD(&dev->mode_config.fb_list);
+	INIT_LIST_HEAD(&dev->mode_config.crtc_list);
+	INIT_LIST_HEAD(&dev->mode_config.connector_list);
+	INIT_LIST_HEAD(&dev->mode_config.encoder_list);
+	INIT_LIST_HEAD(&dev->mode_config.property_list);
+	INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
+	INIT_LIST_HEAD(&dev->mode_config.plane_list);
+	idr_init(&dev->mode_config.crtc_idr);
+	idr_init(&dev->mode_config.tile_idr);
+	ida_init(&dev->mode_config.connector_ida);
+
+	drm_modeset_lock_all(dev);
+	drm_mode_create_standard_properties(dev);
+	drm_modeset_unlock_all(dev);
+
+	/* Just to be sure */
+	dev->mode_config.num_fb = 0;
+	dev->mode_config.num_connector = 0;
+	dev->mode_config.num_crtc = 0;
+	dev->mode_config.num_encoder = 0;
+	dev->mode_config.num_overlay_plane = 0;
+	dev->mode_config.num_total_plane = 0;
+}
+EXPORT_SYMBOL(drm_mode_config_init);
+
+/**
+ * drm_mode_config_cleanup - free up DRM mode_config info
+ * @dev: DRM device
+ *
+ * Free up all the connectors and CRTCs associated with this DRM device, then
+ * free up the framebuffers and associated buffer objects.
+ *
+ * Note that since this /should/ happen single-threaded at driver/device
+ * teardown time, no locking is required. It's the driver's job to ensure that
+ * this guarantee actually holds true.
+ *
+ * FIXME: cleanup any dangling user buffer objects too
+ */
+void drm_mode_config_cleanup(struct drm_device *dev)
+{
+	struct drm_connector *connector, *ot;
+	struct drm_crtc *crtc, *ct;
+	struct drm_encoder *encoder, *enct;
+	struct drm_framebuffer *fb, *fbt;
+	struct drm_property *property, *pt;
+	struct drm_property_blob *blob, *bt;
+	struct drm_plane *plane, *plt;
+
+	list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
+				 head) {
+		encoder->funcs->destroy(encoder);
+	}
+
+	list_for_each_entry_safe(connector, ot,
+				 &dev->mode_config.connector_list, head) {
+		connector->funcs->destroy(connector);
+	}
+
+	list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
+				 head) {
+		drm_property_destroy(dev, property);
+	}
+
+	list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
+				 head) {
+		plane->funcs->destroy(plane);
+	}
+
+	list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
+		crtc->funcs->destroy(crtc);
+	}
+
+	list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
+				 head_global) {
+		drm_property_unreference_blob(blob);
+	}
+
+	/*
+	 * Single-threaded teardown context, so it's not required to grab the
+	 * fb_lock to protect against concurrent fb_list access. Contrary, it
+	 * would actually deadlock with the drm_framebuffer_cleanup function.
+	 *
+	 * Also, if there are any framebuffers left, that's a driver leak now,
+	 * so politely WARN about this.
+	 */
+	WARN_ON(!list_empty(&dev->mode_config.fb_list));
+	list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
+		drm_framebuffer_free(&fb->base.refcount);
+	}
+
+	ida_destroy(&dev->mode_config.connector_ida);
+	idr_destroy(&dev->mode_config.tile_idr);
+	idr_destroy(&dev->mode_config.crtc_idr);
+	drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
+}
+EXPORT_SYMBOL(drm_mode_config_cleanup);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_modes.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_modes.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_modes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_modes.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,13 +49,7 @@
  */
 void drm_mode_debug_printmodeline(const struct drm_display_mode *mode)
 {
-	DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d "
-			"0x%x 0x%x\n",
-		mode->base.id, mode->name, mode->vrefresh, mode->clock,
-		mode->hdisplay, mode->hsync_start,
-		mode->hsync_end, mode->htotal,
-		mode->vdisplay, mode->vsync_start,
-		mode->vsync_end, mode->vtotal, mode->type, mode->flags);
+	DRM_DEBUG_KMS("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
 }
 EXPORT_SYMBOL(drm_mode_debug_printmodeline);
 
@@ -165,6 +159,7 @@ struct drm_display_mode *drm_cvt_mode(st
 	unsigned int vfieldrate, hperiod;
 	int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync;
 	int interlace;
+	u64 tmp;
 
 	/* allocate the drm_display_mode structure. If failure, we will
 	 * return directly
@@ -322,8 +317,11 @@ struct drm_display_mode *drm_cvt_mode(st
 		drm_mode->vsync_end = drm_mode->vsync_start + vsync;
 	}
 	/* 15/13. Find pixel clock frequency (kHz for xf86) */
-	drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod;
-	drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP;
+	tmp = drm_mode->htotal; /* perform intermediate calcs in u64 */
+	tmp *= HV_FACTOR * 1000;
+	do_div(tmp, hperiod);
+	tmp -= drm_mode->clock % CVT_CLOCK_STEP;
+	drm_mode->clock = tmp;
 	/* 18/16. Find actual vertical frame frequency */
 	/* ignore - just set the mode flag for interlaced */
 	if (interlaced) {
@@ -1462,6 +1460,13 @@ drm_mode_create_from_cmdline_mode(struct
 		return NULL;
 
 	mode->type |= DRM_MODE_TYPE_USERDEF;
+	/* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
+	if (cmd->xres == 1366 && mode->hdisplay == 1368) {
+		mode->hdisplay = 1366;
+		mode->hsync_start--;
+		mode->hsync_end--;
+		drm_mode_set_name(mode);
+	}
 	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
 	return mode;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_modeset_helper.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_modeset_helper.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_modeset_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_modeset_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
  * Some userspace presumes that the first connected connector is the main
  * display, where it's supposed to display e.g. the login screen. For
  * laptops, this should be the main panel. Use this function to sort all
- * (eDP/LVDS) panels to the front of the connector list, instead of
+ * (eDP/LVDS/DSI) panels to the front of the connector list, instead of
  * painstakingly trying to initialize them in the right order.
  */
 void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
@@ -51,7 +51,8 @@ void drm_helper_move_panel_connectors_to
 	list_for_each_entry_safe(connector, tmp,
 				 &dev->mode_config.connector_list, head) {
 		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
-		    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		    connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
+		    connector->connector_type == DRM_MODE_CONNECTOR_DSI)
 			list_move_tail(&connector->head, &panel_list);
 	}
 
@@ -70,17 +71,31 @@ EXPORT_SYMBOL(drm_helper_move_panel_conn
 void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
 				    const struct drm_mode_fb_cmd2 *mode_cmd)
 {
+	const struct drm_format_info *info;
 	int i;
 
+	info = drm_format_info(mode_cmd->pixel_format);
+	if (!info || !info->depth) {
+		struct drm_format_name_buf format_name;
+
+		DRM_DEBUG_KMS("non-RGB pixel format %s\n",
+		              drm_get_format_name(mode_cmd->pixel_format,
+		                                  &format_name));
+
+		fb->depth = 0;
+		fb->bits_per_pixel = 0;
+	} else {
+		fb->depth = info->depth;
+		fb->bits_per_pixel = info->cpp[0] * 8;
+	}
+
 	fb->width = mode_cmd->width;
 	fb->height = mode_cmd->height;
 	for (i = 0; i < 4; i++) {
 		fb->pitches[i] = mode_cmd->pitches[i];
 		fb->offsets[i] = mode_cmd->offsets[i];
-		fb->modifier[i] = mode_cmd->modifier[i];
 	}
-	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
-				    &fb->bits_per_pixel);
+	fb->modifier = mode_cmd->modifier[0];
 	fb->pixel_format = mode_cmd->pixel_format;
 	fb->flags = mode_cmd->flags;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_modeset_lock.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_modeset_lock.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_modeset_lock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_modeset_lock.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,14 +52,16 @@
  *     drm_modeset_drop_locks(&ctx);
  *     drm_modeset_acquire_fini(&ctx);
  *
- *  On top of of these per-object locks using &ww_mutex there's also an overall
- *  dev->mode_config.lock, for protecting everything else. Mostly this means
- *  probe state of connectors, and preventing hotplug add/removal of connectors.
+ * On top of of these per-object locks using &ww_mutex there's also an overall
+ * dev->mode_config.lock, for protecting everything else. Mostly this means
+ * probe state of connectors, and preventing hotplug add/removal of connectors.
  *
- *  Finally there's a bunch of dedicated locks to protect drm core internal
- *  lists and lookup data structures.
+ * Finally there's a bunch of dedicated locks to protect drm core internal
+ * lists and lookup data structures.
  */
 
+static DEFINE_WW_CLASS(crtc_ww_class);
+
 /**
  * drm_modeset_lock_all - take all modeset locks
  * @dev: DRM device
@@ -398,6 +400,17 @@ int drm_modeset_backoff_interruptible(st
 EXPORT_SYMBOL(drm_modeset_backoff_interruptible);
 
 /**
+ * drm_modeset_lock_init - initialize lock
+ * @lock: lock to init
+ */
+void drm_modeset_lock_init(struct drm_modeset_lock *lock)
+{
+	ww_mutex_init(&lock->mutex, &crtc_ww_class);
+	INIT_LIST_HEAD(&lock->head);
+}
+EXPORT_SYMBOL(drm_modeset_lock_init);
+
+/**
  * drm_modeset_lock - take modeset lock
  * @lock: lock to take
  * @ctx: acquire ctx
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_of.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_of.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_of.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_of.c	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,11 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_of.h>
 
+static void drm_release_of(struct device *dev, void *data)
+{
+	of_node_put(data);
+}
+
 /**
  * drm_crtc_port_mask - find the mask of a registered CRTC by port OF node
  * @dev: DRM device
@@ -64,6 +69,24 @@ uint32_t drm_of_find_possible_crtcs(stru
 EXPORT_SYMBOL(drm_of_find_possible_crtcs);
 
 /**
+ * drm_of_component_match_add - Add a component helper OF node match rule
+ * @master: master device
+ * @matchptr: component match pointer
+ * @compare: compare function used for matching component
+ * @node: of_node
+ */
+void drm_of_component_match_add(struct device *master,
+				struct component_match **matchptr,
+				int (*compare)(struct device *, void *),
+				struct device_node *node)
+{
+	of_node_get(node);
+	component_match_add_release(master, matchptr, drm_release_of,
+				    compare, node);
+}
+EXPORT_SYMBOL_GPL(drm_of_component_match_add);
+
+/**
  * drm_of_component_probe - Generic probe function for a component based master
  * @dev: master device containing the OF node
  * @compare_of: compare function used for matching components
@@ -101,7 +124,7 @@ int drm_of_component_probe(struct device
 			continue;
 		}
 
-		component_match_add(dev, &match, compare_of, port);
+		drm_of_component_match_add(dev, &match, compare_of, port);
 		of_node_put(port);
 	}
 
@@ -140,7 +163,8 @@ int drm_of_component_probe(struct device
 				continue;
 			}
 
-			component_match_add(dev, &match, compare_of, remote);
+			drm_of_component_match_add(dev, &match, compare_of,
+						   remote);
 			of_node_put(remote);
 		}
 		of_node_put(port);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -79,7 +79,7 @@ static unsigned int drm_num_planes(struc
  * Zero on success, error code on failure.
  */
 int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
-			     unsigned long possible_crtcs,
+			     uint32_t possible_crtcs,
 			     const struct drm_plane_funcs *funcs,
 			     const uint32_t *formats, unsigned int format_count,
 			     enum drm_plane_type type,
@@ -137,6 +137,7 @@ int drm_universal_plane_init(struct drm_
 
 	if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
 		drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
+		drm_object_attach_property(&plane->base, config->prop_in_fence_fd, -1);
 		drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
 		drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
 		drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
@@ -195,7 +196,7 @@ void drm_plane_unregister_all(struct drm
  * Zero on success, error code on failure.
  */
 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
-		   unsigned long possible_crtcs,
+		   uint32_t possible_crtcs,
 		   const struct drm_plane_funcs *funcs,
 		   const uint32_t *formats, unsigned int format_count,
 		   bool is_primary)
@@ -220,7 +221,8 @@ void drm_plane_cleanup(struct drm_plane
 {
 	struct drm_device *dev = plane->dev;
 
-	drm_modeset_lock_all(dev);
+	drm_modeset_lock_fini(&plane->mutex);
+
 	kfree(plane->format_types);
 	drm_mode_object_unregister(dev, &plane->base);
 
@@ -235,7 +237,6 @@ void drm_plane_cleanup(struct drm_plane
 	dev->mode_config.num_total_plane--;
 	if (plane->type == DRM_PLANE_TYPE_OVERLAY)
 		dev->mode_config.num_overlay_plane--;
-	drm_modeset_unlock_all(dev);
 
 	WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
 	if (plane->state && plane->funcs->atomic_destroy_state)
@@ -479,9 +480,10 @@ static int __setplane_internal(struct dr
 	/* Check whether this plane supports the fb pixel format. */
 	ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
 	if (ret) {
-		char *format_name = drm_get_format_name(fb->pixel_format);
-		DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
-		kfree(format_name);
+		struct drm_format_name_buf format_name;
+		DRM_DEBUG_KMS("Invalid pixel format %s\n",
+		              drm_get_format_name(fb->pixel_format,
+		                                  &format_name));
 		goto out;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_plane_helper.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_plane_helper.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_plane_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_plane_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -130,15 +130,8 @@ int drm_plane_helper_check_state(struct
 	unsigned int rotation = state->rotation;
 	int hscale, vscale;
 
-	src->x1 = state->src_x;
-	src->y1 = state->src_y;
-	src->x2 = state->src_x + state->src_w;
-	src->y2 = state->src_y + state->src_h;
-
-	dst->x1 = state->crtc_x;
-	dst->y1 = state->crtc_y;
-	dst->x2 = state->crtc_x + state->crtc_w;
-	dst->y2 = state->crtc_y + state->crtc_h;
+	*src = drm_plane_state_src(state);
+	*dst = drm_plane_state_dest(state);
 
 	if (!fb) {
 		state->visible = false;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_prime.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_prime.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_prime.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_prime.c	2017-02-12 16:03:20.000000000 -0500
@@ -290,7 +290,8 @@ static void drm_gem_unmap_dma_buf(struct
  *
  * This wraps dma_buf_export() for use by generic GEM drivers that are using
  * drm_gem_dmabuf_release(). In addition to calling dma_buf_export(), we take
- * a reference to the drm_device which is released by drm_gem_dmabuf_release().
+ * a reference to the &drm_device and the exported &drm_gem_object (stored in
+ * exp_info->priv) which is released by drm_gem_dmabuf_release().
  *
  * Returns the new dmabuf.
  */
@@ -300,8 +301,11 @@ struct dma_buf *drm_gem_dmabuf_export(st
 	struct dma_buf *dma_buf;
 
 	dma_buf = dma_buf_export(exp_info);
-	if (!IS_ERR(dma_buf))
-		drm_dev_ref(dev);
+	if (IS_ERR(dma_buf))
+		return dma_buf;
+
+	drm_dev_ref(dev);
+	drm_gem_object_reference(exp_info->priv);
 
 	return dma_buf;
 }
@@ -472,8 +476,6 @@ static struct dma_buf *export_and_regist
 	 */
 	obj->dma_buf = dmabuf;
 	get_dma_buf(obj->dma_buf);
-	/* Grab a new ref since the callers is now used by the dma-buf */
-	drm_gem_object_reference(obj);
 
 	return dmabuf;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_print.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_print.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_print.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_print.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ *
+ * 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:
+ * Rob Clark <robdclark@gmail.com>
+ */
+
+#include <stdarg.h>
+#include <linux/seq_file.h>
+#include <drm/drmP.h>
+#include <drm/drm_print.h>
+
+void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
+{
+	seq_printf(p->arg, "%pV", vaf);
+}
+EXPORT_SYMBOL(__drm_printfn_seq_file);
+
+void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf)
+{
+	dev_printk(KERN_INFO, p->arg, "[" DRM_NAME "] %pV", vaf);
+}
+EXPORT_SYMBOL(__drm_printfn_info);
+
+/**
+ * drm_printf - print to a &drm_printer stream
+ * @p: the &drm_printer
+ * @f: format string
+ */
+void drm_printf(struct drm_printer *p, const char *f, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, f);
+	vaf.fmt = f;
+	vaf.va = &args;
+	p->printfn(p, &vaf);
+	va_end(args);
+}
+EXPORT_SYMBOL(drm_printf);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_probe_helper.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_probe_helper.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_probe_helper.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_probe_helper.c	2017-02-12 16:03:20.000000000 -0500
@@ -143,8 +143,18 @@ void drm_kms_helper_poll_enable_locked(s
 	}
 
 	if (dev->mode_config.delayed_event) {
+		/*
+		 * FIXME:
+		 *
+		 * Use short (1s) delay to handle the initial delayed event.
+		 * This delay should not be needed, but Optimus/nouveau will
+		 * fail in a mysterious way if the delayed event is handled as
+		 * soon as possible like it is done in
+		 * drm_helper_probe_single_connector_modes() in case the poll
+		 * was enabled before.
+		 */
 		poll = true;
-		delay = 0;
+		delay = HZ;
 	}
 
 	if (poll)
@@ -152,6 +162,14 @@ void drm_kms_helper_poll_enable_locked(s
 }
 EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked);
 
+static enum drm_connector_status
+drm_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector->funcs->detect ?
+		connector->funcs->detect(connector, force) :
+		connector_status_connected;
+}
+
 /**
  * drm_helper_probe_single_connector_modes - get complete set of display modes
  * @connector: connector to probe
@@ -239,7 +257,7 @@ int drm_helper_probe_single_connector_mo
 		if (connector->funcs->force)
 			connector->funcs->force(connector);
 	} else {
-		connector->status = connector->funcs->detect(connector, true);
+		connector->status = drm_connector_detect(connector, true);
 	}
 
 	/*
@@ -384,7 +402,11 @@ static void output_poll_execute(struct w
 	if (!drm_kms_helper_poll)
 		goto out;
 
-	mutex_lock(&dev->mode_config.mutex);
+	if (!mutex_trylock(&dev->mode_config.mutex)) {
+		repoll = true;
+		goto out;
+	}
+
 	drm_for_each_connector(connector, dev) {
 
 		/* Ignore forced connectors. */
@@ -405,7 +427,7 @@ static void output_poll_execute(struct w
 
 		repoll = true;
 
-		connector->status = connector->funcs->detect(connector, false);
+		connector->status = drm_connector_detect(connector, false);
 		if (old_status != connector->status) {
 			const char *old, *new;
 
@@ -565,7 +587,7 @@ bool drm_helper_hpd_irq_event(struct drm
 
 		old_status = connector->status;
 
-		connector->status = connector->funcs->detect(connector, false);
+		connector->status = drm_connector_detect(connector, false);
 		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
 			      connector->base.id,
 			      connector->name,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_property.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_property.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_property.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_property.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,9 +65,9 @@ static bool drm_property_type_valid(stru
  * @num_values: number of pre-defined values
  *
  * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
  *
  * Returns:
  * A pointer to the newly created property on success, NULL on failure.
@@ -125,9 +125,9 @@ EXPORT_SYMBOL(drm_property_create);
  * @num_values: number of pre-defined values
  *
  * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
  *
  * Userspace is only allowed to set one of the predefined values for enumeration
  * properties.
@@ -173,9 +173,9 @@ EXPORT_SYMBOL(drm_property_create_enum);
  * @supported_bits: bitmask of all supported enumeration values
  *
  * This creates a new bitmask drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
  *
  * Compared to plain enumeration properties userspace is allowed to set any
  * or'ed together combination of the predefined property bitflag values
@@ -245,9 +245,9 @@ static struct drm_property *property_cre
  * @max: maximum value of the property
  *
  * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
  *
  * Userspace is allowed to set any unsigned integer value in the (min, max)
  * range inclusive.
@@ -273,9 +273,9 @@ EXPORT_SYMBOL(drm_property_create_range)
  * @max: maximum value of the property
  *
  * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
  *
  * Userspace is allowed to set any signed integer value in the (min, max)
  * range inclusive.
@@ -300,9 +300,9 @@ EXPORT_SYMBOL(drm_property_create_signed
  * @type: object type from DRM_MODE_OBJECT_* defines
  *
  * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
  *
  * Userspace is only allowed to set this to any property value of the given
  * @type. Only useful for atomic properties, which is enforced.
@@ -338,9 +338,9 @@ EXPORT_SYMBOL(drm_property_create_object
  * @name: name of the property
  *
  * This creates a new generic drm property which can then be attached to a drm
- * object with drm_object_attach_property. The returned property object must be
- * freed with drm_property_destroy(), which is done automatically when calling
- * drm_mode_config_cleanup().
+ * object with drm_object_attach_property(). The returned property object must
+ * be freed with drm_property_destroy(), which is done automatically when
+ * calling drm_mode_config_cleanup().
  *
  * This is implemented as a ranged property with only {0, 1} as valid values.
  *
@@ -729,7 +729,6 @@ int drm_mode_getblob_ioctl(struct drm_de
 	struct drm_mode_get_blob *out_resp = data;
 	struct drm_property_blob *blob;
 	int ret = 0;
-	void __user *blob_ptr;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EINVAL;
@@ -739,8 +738,9 @@ int drm_mode_getblob_ioctl(struct drm_de
 		return -ENOENT;
 
 	if (out_resp->length == blob->length) {
-		blob_ptr = (void __user *)(unsigned long)out_resp->data;
-		if (copy_to_user(blob_ptr, blob->data, blob->length)) {
+		if (copy_to_user(u64_to_user_ptr(out_resp->data),
+				 blob->data,
+				 blob->length)) {
 			ret = -EFAULT;
 			goto unref;
 		}
@@ -757,7 +757,6 @@ int drm_mode_createblob_ioctl(struct drm
 {
 	struct drm_mode_create_blob *out_resp = data;
 	struct drm_property_blob *blob;
-	void __user *blob_ptr;
 	int ret = 0;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -767,8 +766,9 @@ int drm_mode_createblob_ioctl(struct drm
 	if (IS_ERR(blob))
 		return PTR_ERR(blob);
 
-	blob_ptr = (void __user *)(unsigned long)out_resp->data;
-	if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
+	if (copy_from_user(blob->data,
+			   u64_to_user_ptr(out_resp->data),
+			   out_resp->length)) {
 		ret = -EFAULT;
 		goto out_blob;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_rect.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_rect.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_rect.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_rect.c	2017-02-12 16:03:20.000000000 -0500
@@ -281,17 +281,10 @@ EXPORT_SYMBOL(drm_rect_calc_vscale_relax
  */
 void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
 {
-	int w = drm_rect_width(r);
-	int h = drm_rect_height(r);
-
 	if (fixed_point)
-		DRM_DEBUG_KMS("%s%d.%06ux%d.%06u%+d.%06u%+d.%06u\n", prefix,
-			      w >> 16, ((w & 0xffff) * 15625) >> 10,
-			      h >> 16, ((h & 0xffff) * 15625) >> 10,
-			      r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10,
-			      r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10);
+		DRM_DEBUG_KMS("%s" DRM_RECT_FP_FMT "\n", prefix, DRM_RECT_FP_ARG(r));
 	else
-		DRM_DEBUG_KMS("%s%dx%d%+d%+d\n", prefix, w, h, r->x1, r->y1);
+		DRM_DEBUG_KMS("%s" DRM_RECT_FMT "\n", prefix, DRM_RECT_ARG(r));
 }
 EXPORT_SYMBOL(drm_rect_debug_print);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/drm_vm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_vm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/drm_vm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/drm_vm.c	2017-02-12 16:03:20.000000000 -0500
@@ -124,8 +124,7 @@ static int drm_do_vm_fault(struct vm_are
 		 * Using vm_pgoff as a selector forces us to use this unusual
 		 * addressing scheme.
 		 */
-		resource_size_t offset = (unsigned long)vmf->virtual_address -
-			vma->vm_start;
+		resource_size_t offset = vmf->address - vma->vm_start;
 		resource_size_t baddr = map->offset + offset;
 		struct drm_agp_mem *agpmem;
 		struct page *page;
@@ -195,7 +194,7 @@ static int drm_do_vm_shm_fault(struct vm
 	if (!map)
 		return VM_FAULT_SIGBUS;	/* Nothing allocated */
 
-	offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+	offset = vmf->address - vma->vm_start;
 	i = (unsigned long)map->handle + offset;
 	page = vmalloc_to_page((void *)i);
 	if (!page)
@@ -301,7 +300,8 @@ static int drm_do_vm_dma_fault(struct vm
 	if (!dma->pagelist)
 		return VM_FAULT_SIGBUS;	/* Nothing allocated */
 
-	offset = (unsigned long)vmf->virtual_address - vma->vm_start;	/* vm_[pg]off[set] should be 0 */
+	offset = vmf->address - vma->vm_start;
+					/* vm_[pg]off[set] should be 0 */
 	page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */
 	page = virt_to_page((void *)dma->pagelist[page_nr]);
 
@@ -337,7 +337,7 @@ static int drm_do_vm_sg_fault(struct vm_
 	if (!entry->pagelist)
 		return VM_FAULT_SIGBUS;	/* Nothing allocated */
 
-	offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+	offset = vmf->address - vma->vm_start;
 	map_offset = map->offset - (unsigned long)dev->sg->virtual;
 	page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT);
 	page = entry->pagelist[page_offset];
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/cmdstream.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/cmdstream.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/cmdstream.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/cmdstream.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,10 +8,34 @@ http://0x04.net/cgit/index.cgi/rules-ng-
 git clone git://0x04.net/rules-ng-ng
 
 The rules-ng-ng source files this header was generated from are:
-- cmdstream.xml (  12589 bytes, from 2014-02-17 14:57:56)
-- common.xml    (  18437 bytes, from 2015-03-25 11:27:41)
+- cmdstream.xml (  14094 bytes, from 2016-11-11 06:55:14)
+- copyright.xml (   1597 bytes, from 2016-10-29 07:29:22)
+- common.xml    (  23344 bytes, from 2016-11-10 15:14:07)
 
-Copyright (C) 2014
+Copyright (C) 2012-2016 by the following authors:
+- Wladimir J. van der Laan <laanwj@gmail.com>
+- Christian Gmeiner <christian.gmeiner@gmail.com>
+- Lucas Stach <l.stach@pengutronix.de>
+- Russell King <rmk@arm.linux.org.uk>
+
+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 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.
 */
 
 
@@ -26,6 +50,7 @@ Copyright (C) 2014
 #define FE_OPCODE_STALL						0x00000009
 #define FE_OPCODE_CALL						0x0000000a
 #define FE_OPCODE_RETURN					0x0000000b
+#define FE_OPCODE_DRAW_INSTANCED				0x0000000c
 #define FE_OPCODE_CHIP_SELECT					0x0000000d
 #define PRIMITIVE_TYPE_POINTS					0x00000001
 #define PRIMITIVE_TYPE_LINES					0x00000002
@@ -214,5 +239,32 @@ Copyright (C) 2014
 #define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP1			0x00000002
 #define VIV_FE_CHIP_SELECT_HEADER_ENABLE_CHIP0			0x00000001
 
+#define VIV_FE_DRAW_INSTANCED					0x00000000
+
+#define VIV_FE_DRAW_INSTANCED_HEADER				0x00000000
+#define VIV_FE_DRAW_INSTANCED_HEADER_OP__MASK			0xf8000000
+#define VIV_FE_DRAW_INSTANCED_HEADER_OP__SHIFT			27
+#define VIV_FE_DRAW_INSTANCED_HEADER_OP_DRAW_INSTANCED		0x60000000
+#define VIV_FE_DRAW_INSTANCED_HEADER_INDEXED			0x00100000
+#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE__MASK			0x000f0000
+#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE__SHIFT		16
+#define VIV_FE_DRAW_INSTANCED_HEADER_TYPE(x)			(((x) << VIV_FE_DRAW_INSTANCED_HEADER_TYPE__SHIFT) & VIV_FE_DRAW_INSTANCED_HEADER_TYPE__MASK)
+#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__MASK	0x0000ffff
+#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__SHIFT	0
+#define VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO(x)	(((x) << VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__SHIFT) & VIV_FE_DRAW_INSTANCED_HEADER_INSTANCE_COUNT_LO__MASK)
+
+#define VIV_FE_DRAW_INSTANCED_COUNT				0x00000004
+#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__MASK	0xff000000
+#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__SHIFT	24
+#define VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI(x)	(((x) << VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__SHIFT) & VIV_FE_DRAW_INSTANCED_COUNT_INSTANCE_COUNT_HI__MASK)
+#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__MASK		0x00ffffff
+#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__SHIFT		0
+#define VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT(x)		(((x) << VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__SHIFT) & VIV_FE_DRAW_INSTANCED_COUNT_VERTEX_COUNT__MASK)
+
+#define VIV_FE_DRAW_INSTANCED_START				0x00000008
+#define VIV_FE_DRAW_INSTANCED_START_INDEX__MASK			0xffffffff
+#define VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT		0
+#define VIV_FE_DRAW_INSTANCED_START_INDEX(x)			(((x) << VIV_FE_DRAW_INSTANCED_START_INDEX__SHIFT) & VIV_FE_DRAW_INSTANCED_START_INDEX__MASK)
+
 
 #endif /* CMDSTREAM_XML */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_cmd_parser.c	2017-02-12 16:03:20.000000000 -0500
@@ -143,6 +143,7 @@ static bool etnaviv_validate_load_state(
 static uint8_t cmd_length[32] = {
 	[FE_OPCODE_DRAW_PRIMITIVES] = 4,
 	[FE_OPCODE_DRAW_INDEXED_PRIMITIVES] = 6,
+	[FE_OPCODE_DRAW_INSTANCED] = 4,
 	[FE_OPCODE_NOP] = 2,
 	[FE_OPCODE_STALL] = 2,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 
 #include <linux/component.h>
 #include <linux/of_platform.h>
+#include <drm/drm_of.h>
 
 #include "etnaviv_drv.h"
 #include "etnaviv_gpu.h"
@@ -478,9 +479,7 @@ static const struct file_operations fops
 	.open               = drm_open,
 	.release            = drm_release,
 	.unlocked_ioctl     = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl       = drm_compat_ioctl,
-#endif
 	.poll               = drm_poll,
 	.read               = drm_read,
 	.llseek             = no_llseek,
@@ -505,6 +504,7 @@ static struct drm_driver etnaviv_drm_dri
 	.gem_prime_import_sg_table = etnaviv_gem_prime_import_sg_table,
 	.gem_prime_vmap     = etnaviv_gem_prime_vmap,
 	.gem_prime_vunmap   = etnaviv_gem_prime_vunmap,
+	.gem_prime_mmap     = etnaviv_gem_prime_mmap,
 #ifdef CONFIG_DEBUG_FS
 	.debugfs_init       = etnaviv_debugfs_init,
 	.debugfs_cleanup    = etnaviv_debugfs_cleanup,
@@ -629,8 +629,8 @@ static int etnaviv_pdev_probe(struct pla
 			if (!core_node)
 				break;
 
-			component_match_add(&pdev->dev, &match, compare_of,
-					    core_node);
+			drm_of_component_match_add(&pdev->dev, &match,
+						   compare_of, core_node);
 			of_node_put(core_node);
 		}
 	} else if (dev->platform_data) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -78,6 +78,8 @@ int etnaviv_gem_mmap_offset(struct drm_g
 struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
 void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj);
 void etnaviv_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
+int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
+			   struct vm_area_struct *vma);
 struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
 	struct dma_buf_attachment *attach, struct sg_table *sg);
 int etnaviv_gem_prime_pin(struct drm_gem_object *obj);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_dump.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_dump.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_dump.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_dump.c	2017-02-12 16:03:20.000000000 -0500
@@ -160,7 +160,8 @@ void etnaviv_core_dump(struct etnaviv_gp
 	file_size += sizeof(*iter.hdr) * n_obj;
 
 	/* Allocate the file in vmalloc memory, it's likely to be big */
-	iter.start = vmalloc(file_size);
+	iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_HIGHMEM |
+			       __GFP_NOWARN | __GFP_NORETRY, PAGE_KERNEL);
 	if (!iter.start) {
 		dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
 		return;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -202,15 +202,14 @@ int etnaviv_gem_fault(struct vm_area_str
 	}
 
 	/* We don't use vmf->pgoff since that has the fake offset: */
-	pgoff = ((unsigned long)vmf->virtual_address -
-			vma->vm_start) >> PAGE_SHIFT;
+	pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
 	page = pages[pgoff];
 
-	VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+	VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
 	     page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
 
-	ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);
+	ret = vm_insert_page(vma, vmf->address, page);
 
 out:
 	switch (ret) {
@@ -409,20 +408,16 @@ int etnaviv_gem_cpu_prep(struct drm_gem_
 	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 	struct drm_device *dev = obj->dev;
 	bool write = !!(op & ETNA_PREP_WRITE);
-	int ret;
-
-	if (op & ETNA_PREP_NOSYNC) {
-		if (!reservation_object_test_signaled_rcu(etnaviv_obj->resv,
-							  write))
-			return -EBUSY;
-	} else {
-		unsigned long remain = etnaviv_timeout_to_jiffies(timeout);
+	unsigned long remain =
+		op & ETNA_PREP_NOSYNC ? 0 : etnaviv_timeout_to_jiffies(timeout);
+	long lret;
 
-		ret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv,
-							  write, true, remain);
-		if (ret <= 0)
-			return ret == 0 ? -ETIMEDOUT : ret;
-	}
+	lret = reservation_object_wait_timeout_rcu(etnaviv_obj->resv,
+						   write, true, remain);
+	if (lret < 0)
+		return lret;
+	else if (lret == 0)
+		return remain == 0 ? -EBUSY : -ETIMEDOUT;
 
 	if (etnaviv_obj->flags & ETNA_BO_CACHED) {
 		if (!etnaviv_obj->sgt) {
@@ -470,10 +465,10 @@ int etnaviv_gem_wait_bo(struct etnaviv_g
 }
 
 #ifdef CONFIG_DEBUG_FS
-static void etnaviv_gem_describe_fence(struct fence *fence,
+static void etnaviv_gem_describe_fence(struct dma_fence *fence,
 	const char *type, struct seq_file *m)
 {
-	if (!test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+	if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
 		seq_printf(m, "\t%9s: %s %s seq %u\n",
 			   type,
 			   fence->ops->get_driver_name(fence),
@@ -486,7 +481,7 @@ static void etnaviv_gem_describe(struct
 	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
 	struct reservation_object *robj = etnaviv_obj->resv;
 	struct reservation_object_list *fobj;
-	struct fence *fence;
+	struct dma_fence *fence;
 	unsigned long off = drm_vma_node_start(&obj->vma_node);
 
 	seq_printf(m, "%08x: %c %2d (%2d) %08lx %p %zd\n",
@@ -763,7 +758,7 @@ static struct page **etnaviv_gem_userptr
 	down_read(&mm->mmap_sem);
 	while (pinned < npages) {
 		ret = get_user_pages_remote(task, mm, ptr, npages - pinned,
-					    flags, pvec + pinned, NULL);
+					    flags, pvec + pinned, NULL, NULL);
 		if (ret < 0)
 			break;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,10 +23,12 @@
 struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj)
 {
 	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	int npages = obj->size >> PAGE_SHIFT;
 
-	BUG_ON(!etnaviv_obj->sgt);  /* should have already pinned! */
+	if (WARN_ON(!etnaviv_obj->pages))  /* should have already pinned! */
+		return NULL;
 
-	return etnaviv_obj->sgt;
+	return drm_prime_pages_to_sg(etnaviv_obj->pages, npages);
 }
 
 void *etnaviv_gem_prime_vmap(struct drm_gem_object *obj)
@@ -39,6 +41,19 @@ void etnaviv_gem_prime_vunmap(struct drm
 	/* TODO msm_gem_vunmap() */
 }
 
+int etnaviv_gem_prime_mmap(struct drm_gem_object *obj,
+			   struct vm_area_struct *vma)
+{
+	struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
+	int ret;
+
+	ret = drm_gem_mmap_obj(obj, obj->size, vma);
+	if (ret < 0)
+		return ret;
+
+	return etnaviv_obj->ops->mmap(etnaviv_obj, vma);
+}
+
 int etnaviv_gem_prime_pin(struct drm_gem_object *obj)
 {
 	if (!obj->import_attach) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
  */
 
 #include <linux/component.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 #include <linux/moduleparam.h>
 #include <linux/of_device.h>
 #include "etnaviv_dump.h"
@@ -639,6 +639,10 @@ int etnaviv_gpu_init(struct etnaviv_gpu
 			gpu->memory_base = PHYS_OFFSET;
 		else
 			gpu->memory_base = dma_mask - SZ_2G + 1;
+	} else if (PHYS_OFFSET >= SZ_2G) {
+		dev_info(gpu->dev, "Need to move linear window on MC1.0, disabling TS\n");
+		gpu->memory_base = PHYS_OFFSET;
+		gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
 	}
 
 	ret = etnaviv_hw_reset(gpu);
@@ -882,7 +886,7 @@ static void recover_worker(struct work_s
 	for (i = 0; i < ARRAY_SIZE(gpu->event); i++) {
 		if (!gpu->event[i].used)
 			continue;
-		fence_signal(gpu->event[i].fence);
+		dma_fence_signal(gpu->event[i].fence);
 		gpu->event[i].fence = NULL;
 		gpu->event[i].used = false;
 		complete(&gpu->event_free);
@@ -952,55 +956,55 @@ static void hangcheck_disable(struct etn
 /* fence object management */
 struct etnaviv_fence {
 	struct etnaviv_gpu *gpu;
-	struct fence base;
+	struct dma_fence base;
 };
 
-static inline struct etnaviv_fence *to_etnaviv_fence(struct fence *fence)
+static inline struct etnaviv_fence *to_etnaviv_fence(struct dma_fence *fence)
 {
 	return container_of(fence, struct etnaviv_fence, base);
 }
 
-static const char *etnaviv_fence_get_driver_name(struct fence *fence)
+static const char *etnaviv_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "etnaviv";
 }
 
-static const char *etnaviv_fence_get_timeline_name(struct fence *fence)
+static const char *etnaviv_fence_get_timeline_name(struct dma_fence *fence)
 {
 	struct etnaviv_fence *f = to_etnaviv_fence(fence);
 
 	return dev_name(f->gpu->dev);
 }
 
-static bool etnaviv_fence_enable_signaling(struct fence *fence)
+static bool etnaviv_fence_enable_signaling(struct dma_fence *fence)
 {
 	return true;
 }
 
-static bool etnaviv_fence_signaled(struct fence *fence)
+static bool etnaviv_fence_signaled(struct dma_fence *fence)
 {
 	struct etnaviv_fence *f = to_etnaviv_fence(fence);
 
 	return fence_completed(f->gpu, f->base.seqno);
 }
 
-static void etnaviv_fence_release(struct fence *fence)
+static void etnaviv_fence_release(struct dma_fence *fence)
 {
 	struct etnaviv_fence *f = to_etnaviv_fence(fence);
 
 	kfree_rcu(f, base.rcu);
 }
 
-static const struct fence_ops etnaviv_fence_ops = {
+static const struct dma_fence_ops etnaviv_fence_ops = {
 	.get_driver_name = etnaviv_fence_get_driver_name,
 	.get_timeline_name = etnaviv_fence_get_timeline_name,
 	.enable_signaling = etnaviv_fence_enable_signaling,
 	.signaled = etnaviv_fence_signaled,
-	.wait = fence_default_wait,
+	.wait = dma_fence_default_wait,
 	.release = etnaviv_fence_release,
 };
 
-static struct fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
+static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu)
 {
 	struct etnaviv_fence *f;
 
@@ -1010,8 +1014,8 @@ static struct fence *etnaviv_gpu_fence_a
 
 	f->gpu = gpu;
 
-	fence_init(&f->base, &etnaviv_fence_ops, &gpu->fence_spinlock,
-		   gpu->fence_context, ++gpu->next_fence);
+	dma_fence_init(&f->base, &etnaviv_fence_ops, &gpu->fence_spinlock,
+		       gpu->fence_context, ++gpu->next_fence);
 
 	return &f->base;
 }
@@ -1021,7 +1025,7 @@ int etnaviv_gpu_fence_sync_obj(struct et
 {
 	struct reservation_object *robj = etnaviv_obj->resv;
 	struct reservation_object_list *fobj;
-	struct fence *fence;
+	struct dma_fence *fence;
 	int i, ret;
 
 	if (!exclusive) {
@@ -1039,7 +1043,7 @@ int etnaviv_gpu_fence_sync_obj(struct et
 		/* Wait on any existing exclusive fence which isn't our own */
 		fence = reservation_object_get_excl(robj);
 		if (fence && fence->context != context) {
-			ret = fence_wait(fence, true);
+			ret = dma_fence_wait(fence, true);
 			if (ret)
 				return ret;
 		}
@@ -1052,7 +1056,7 @@ int etnaviv_gpu_fence_sync_obj(struct et
 		fence = rcu_dereference_protected(fobj->shared[i],
 						reservation_object_held(robj));
 		if (fence->context != context) {
-			ret = fence_wait(fence, true);
+			ret = dma_fence_wait(fence, true);
 			if (ret)
 				return ret;
 		}
@@ -1158,11 +1162,11 @@ static void retire_worker(struct work_st
 
 	mutex_lock(&gpu->lock);
 	list_for_each_entry_safe(cmdbuf, tmp, &gpu->active_cmd_list, node) {
-		if (!fence_is_signaled(cmdbuf->fence))
+		if (!dma_fence_is_signaled(cmdbuf->fence))
 			break;
 
 		list_del(&cmdbuf->node);
-		fence_put(cmdbuf->fence);
+		dma_fence_put(cmdbuf->fence);
 
 		for (i = 0; i < cmdbuf->nr_bos; i++) {
 			struct etnaviv_vram_mapping *mapping = cmdbuf->bo_map[i];
@@ -1275,7 +1279,7 @@ void etnaviv_gpu_pm_put(struct etnaviv_g
 int etnaviv_gpu_submit(struct etnaviv_gpu *gpu,
 	struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf)
 {
-	struct fence *fence;
+	struct dma_fence *fence;
 	unsigned int event, i;
 	int ret;
 
@@ -1391,7 +1395,7 @@ static irqreturn_t irq_handler(int irq,
 		}
 
 		while ((event = ffs(intr)) != 0) {
-			struct fence *fence;
+			struct dma_fence *fence;
 
 			event -= 1;
 
@@ -1401,7 +1405,7 @@ static irqreturn_t irq_handler(int irq,
 
 			fence = gpu->event[event].fence;
 			gpu->event[event].fence = NULL;
-			fence_signal(fence);
+			dma_fence_signal(fence);
 
 			/*
 			 * Events can be processed out of order.  Eg,
@@ -1553,7 +1557,7 @@ static int etnaviv_gpu_bind(struct devic
 		return ret;
 
 	gpu->drm = drm;
-	gpu->fence_context = fence_context_alloc(1);
+	gpu->fence_context = dma_fence_context_alloc(1);
 	spin_lock_init(&gpu->fence_spinlock);
 
 	INIT_LIST_HEAD(&gpu->active_cmd_list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_gpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -89,7 +89,7 @@ struct etnaviv_chip_identity {
 
 struct etnaviv_event {
 	bool used;
-	struct fence *fence;
+	struct dma_fence *fence;
 };
 
 struct etnaviv_cmdbuf;
@@ -163,7 +163,7 @@ struct etnaviv_cmdbuf {
 	/* vram node used if the cmdbuf is mapped through the MMUv2 */
 	struct drm_mm_node vram_node;
 	/* fence after which this buffer is to be disposed */
-	struct fence *fence;
+	struct dma_fence *fence;
 	/* target exec state */
 	u32 exec_state;
 	/* per GPU in-flight list */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/etnaviv/etnaviv_mmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -116,9 +116,14 @@ static int etnaviv_iommu_find_iova(struc
 		struct list_head list;
 		bool found;
 
+		/*
+		 * XXX: The DRM_MM_SEARCH_BELOW is really a hack to trick
+		 * drm_mm into giving out a low IOVA after address space
+		 * rollover. This needs a proper fix.
+		 */
 		ret = drm_mm_insert_node_in_range(&mmu->mm, node,
 			size, 0, mmu->last_iova, ~0UL,
-			DRM_MM_SEARCH_DEFAULT);
+			mmu->last_iova ? DRM_MM_SEARCH_DEFAULT : DRM_MM_SEARCH_BELOW);
 
 		if (ret != -ENOSPC)
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos5433_drm_decon.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,8 @@ enum decon_flag_bits {
 	BIT_CLKS_ENABLED,
 	BIT_IRQS_ENABLED,
 	BIT_WIN_UPDATED,
-	BIT_SUSPENDED
+	BIT_SUSPENDED,
+	BIT_REQUEST_UPDATE
 };
 
 struct decon_context {
@@ -141,12 +142,6 @@ static void decon_commit(struct exynos_d
 		m->crtc_vsync_end = m->crtc_vsync_start + 1;
 	}
 
-	decon_set_bits(ctx, DECON_VIDCON0, VIDCON0_ENVID, 0);
-
-	/* enable clock gate */
-	val = CMU_CLKGAGE_MODE_SFR_F | CMU_CLKGAGE_MODE_MEM_F;
-	writel(val, ctx->addr + DECON_CMU);
-
 	if (ctx->out_type & (IFTYPE_I80 | I80_HW_TRG))
 		decon_setup_trigger(ctx);
 
@@ -315,6 +310,7 @@ static void decon_update_plane(struct ex
 
 	/* window enable */
 	decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, ~0);
+	set_bit(BIT_REQUEST_UPDATE, &ctx->flags);
 }
 
 static void decon_disable_plane(struct exynos_drm_crtc *crtc,
@@ -327,6 +323,7 @@ static void decon_disable_plane(struct e
 		return;
 
 	decon_set_bits(ctx, DECON_WINCONx(win), WINCONx_ENWIN_F, 0);
+	set_bit(BIT_REQUEST_UPDATE, &ctx->flags);
 }
 
 static void decon_atomic_flush(struct exynos_drm_crtc *crtc)
@@ -340,8 +337,8 @@ static void decon_atomic_flush(struct ex
 	for (i = ctx->first_win; i < WINDOWS_NR; i++)
 		decon_shadow_protect_win(ctx, i, false);
 
-	/* standalone update */
-	decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
+	if (test_and_clear_bit(BIT_REQUEST_UPDATE, &ctx->flags))
+		decon_set_bits(ctx, DECON_UPDATE, STANDALONE_UPDATE_F, ~0);
 
 	if (ctx->out_type & IFTYPE_I80)
 		set_bit(BIT_WIN_UPDATED, &ctx->flags);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -69,7 +69,7 @@ static void exynos_atomic_commit_complet
 
 	drm_atomic_helper_cleanup_planes(dev, state);
 
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 
 	spin_lock(&priv->lock);
 	priv->pending &= ~commit->crtcs;
@@ -254,6 +254,7 @@ int exynos_atomic_commit(struct drm_devi
 
 	drm_atomic_helper_swap_state(state, true);
 
+	drm_atomic_state_get(state);
 	if (nonblock)
 		schedule_work(&commit->work);
 	else
@@ -365,9 +366,7 @@ static const struct file_operations exyn
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.release	= drm_release,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,15 +63,11 @@ static int exynos_drm_fb_mmap(struct fb_
 
 static struct fb_ops exynos_drm_fb_ops = {
 	.owner		= THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_mmap        = exynos_drm_fb_mmap,
 	.fb_fillrect	= drm_fb_helper_cfb_fillrect,
 	.fb_copyarea	= drm_fb_helper_cfb_copyarea,
 	.fb_imageblit	= drm_fb_helper_cfb_imageblit,
-	.fb_check_var	= drm_fb_helper_check_var,
-	.fb_set_par	= drm_fb_helper_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,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_fimc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1433,7 +1433,7 @@ static int fimc_ippdrv_start(struct devi
 		&img_pos[EXYNOS_DRM_OPS_SRC],
 		&img_pos[EXYNOS_DRM_OPS_DST]);
 	if (ret) {
-		dev_err(dev, "failed to set precalser.\n");
+		dev_err(dev, "failed to set prescaler.\n");
 		return ret;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -231,12 +231,12 @@ struct exynos_drm_gem *exynos_drm_gem_cr
 	int ret;
 
 	if (flags & ~(EXYNOS_BO_MASK)) {
-		DRM_ERROR("invalid flags.\n");
+		DRM_ERROR("invalid GEM buffer flags: %u\n", flags);
 		return ERR_PTR(-EINVAL);
 	}
 
 	if (!size) {
-		DRM_ERROR("invalid size.\n");
+		DRM_ERROR("invalid GEM buffer size: %lu\n", size);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -455,8 +455,7 @@ int exynos_drm_gem_fault(struct vm_area_
 	pgoff_t page_offset;
 	int ret;
 
-	page_offset = ((unsigned long)vmf->virtual_address -
-			vma->vm_start) >> PAGE_SHIFT;
+	page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
 	if (page_offset >= (exynos_gem->size >> PAGE_SHIFT)) {
 		DRM_ERROR("invalid page offset\n");
@@ -465,8 +464,7 @@ int exynos_drm_gem_fault(struct vm_area_
 	}
 
 	pfn = page_to_pfn(exynos_gem->pages[page_offset]);
-	ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
-			__pfn_to_pfn_t(pfn, PFN_DEV));
+	ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
 
 out:
 	switch (ret) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_gsc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_gsc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_drm_gsc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_drm_gsc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1610,7 +1610,7 @@ static int gsc_ippdrv_start(struct devic
 		&img_pos[EXYNOS_DRM_OPS_SRC],
 		&img_pos[EXYNOS_DRM_OPS_DST]);
 	if (ret) {
-		dev_err(dev, "failed to set precalser.\n");
+		dev_err(dev, "failed to set prescaler.\n");
 		return ret;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/exynos_hdmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,19 +47,6 @@
 
 #define HOTPLUG_DEBOUNCE_MS		1100
 
-/* AVI header and aspect ratio */
-#define HDMI_AVI_VERSION		0x02
-#define HDMI_AVI_LENGTH			0x0d
-
-/* AUI header info */
-#define HDMI_AUI_VERSION		0x01
-#define HDMI_AUI_LENGTH			0x0a
-
-/* AVI active format aspect ratio */
-#define AVI_SAME_AS_PIC_ASPECT_RATIO	0x08
-#define AVI_4_3_CENTER_RATIO		0x09
-#define AVI_16_9_CENTER_RATIO		0x0a
-
 enum hdmi_type {
 	HDMI_TYPE13,
 	HDMI_TYPE14,
@@ -131,7 +118,6 @@ struct hdmi_context {
 	bool				dvi_mode;
 	struct delayed_work		hotplug_work;
 	struct drm_display_mode		current_mode;
-	u8				cea_video_id;
 	const struct hdmi_driver_data	*drv_data;
 
 	void __iomem			*regs;
@@ -681,6 +667,13 @@ static inline void hdmi_reg_writev(struc
 	}
 }
 
+static inline void hdmi_reg_write_buf(struct hdmi_context *hdata, u32 reg_id,
+				      u8 *buf, int size)
+{
+	for (reg_id = hdmi_map_reg(hdata, reg_id); size; --size, reg_id += 4)
+		writel(*buf++, hdata->regs + reg_id);
+}
+
 static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
 				 u32 reg_id, u32 value, u32 mask)
 {
@@ -762,93 +755,50 @@ static int hdmi_clk_set_parents(struct h
 	return ret;
 }
 
-static u8 hdmi_chksum(struct hdmi_context *hdata,
-			u32 start, u8 len, u32 hdr_sum)
-{
-	int i;
-
-	/* hdr_sum : header0 + header1 + header2
-	* start : start address of packet byte1
-	* len : packet bytes - 1 */
-	for (i = 0; i < len; ++i)
-		hdr_sum += 0xff & hdmi_reg_read(hdata, start + i * 4);
-
-	/* return 2's complement of 8 bit hdr_sum */
-	return (u8)(~(hdr_sum & 0xff) + 1);
-}
-
-static void hdmi_reg_infoframe(struct hdmi_context *hdata,
-			union hdmi_infoframe *infoframe)
+static void hdmi_reg_infoframes(struct hdmi_context *hdata)
 {
-	u32 hdr_sum;
-	u8 chksum;
-	u8 ar;
+	union hdmi_infoframe frm;
+	u8 buf[25];
+	int ret;
 
 	if (hdata->dvi_mode) {
-		hdmi_reg_writeb(hdata, HDMI_VSI_CON,
-				HDMI_VSI_CON_DO_NOT_TRANSMIT);
 		hdmi_reg_writeb(hdata, HDMI_AVI_CON,
 				HDMI_AVI_CON_DO_NOT_TRANSMIT);
+		hdmi_reg_writeb(hdata, HDMI_VSI_CON,
+				HDMI_VSI_CON_DO_NOT_TRANSMIT);
 		hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_NO_TRAN);
 		return;
 	}
 
-	switch (infoframe->any.type) {
-	case HDMI_INFOFRAME_TYPE_AVI:
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
+			&hdata->current_mode);
+	if (!ret)
+		ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf));
+	if (ret > 0) {
 		hdmi_reg_writeb(hdata, HDMI_AVI_CON, HDMI_AVI_CON_EVERY_VSYNC);
-		hdmi_reg_writeb(hdata, HDMI_AVI_HEADER0, infoframe->any.type);
-		hdmi_reg_writeb(hdata, HDMI_AVI_HEADER1,
-				infoframe->any.version);
-		hdmi_reg_writeb(hdata, HDMI_AVI_HEADER2, infoframe->any.length);
-		hdr_sum = infoframe->any.type + infoframe->any.version +
-			  infoframe->any.length;
-
-		/* Output format zero hardcoded ,RGB YBCR selection */
-		hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 0 << 5 |
-			AVI_ACTIVE_FORMAT_VALID |
-			AVI_UNDERSCANNED_DISPLAY_VALID);
-
-		/*
-		 * Set the aspect ratio as per the mode, mentioned in
-		 * Table 9 AVI InfoFrame Data Byte 2 of CEA-861-D Standard
-		 */
-		ar = hdata->current_mode.picture_aspect_ratio;
-		switch (ar) {
-		case HDMI_PICTURE_ASPECT_4_3:
-			ar |= AVI_4_3_CENTER_RATIO;
-			break;
-		case HDMI_PICTURE_ASPECT_16_9:
-			ar |= AVI_16_9_CENTER_RATIO;
-			break;
-		case HDMI_PICTURE_ASPECT_NONE:
-		default:
-			ar |= AVI_SAME_AS_PIC_ASPECT_RATIO;
-			break;
-		}
-		hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(2), ar);
+		hdmi_reg_write_buf(hdata, HDMI_AVI_HEADER0, buf, ret);
+	} else {
+		DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret);
+	}
 
-		hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), hdata->cea_video_id);
+	ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi,
+			&hdata->current_mode);
+	if (!ret)
+		ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf,
+				sizeof(buf));
+	if (ret > 0) {
+		hdmi_reg_writeb(hdata, HDMI_VSI_CON, HDMI_VSI_CON_EVERY_VSYNC);
+		hdmi_reg_write_buf(hdata, HDMI_VSI_HEADER0, buf, ret);
+	}
 
-		chksum = hdmi_chksum(hdata, HDMI_AVI_BYTE(1),
-					infoframe->any.length, hdr_sum);
-		DRM_DEBUG_KMS("AVI checksum = 0x%x\n", chksum);
-		hdmi_reg_writeb(hdata, HDMI_AVI_CHECK_SUM, chksum);
-		break;
-	case HDMI_INFOFRAME_TYPE_AUDIO:
-		hdmi_reg_writeb(hdata, HDMI_AUI_CON, 0x02);
-		hdmi_reg_writeb(hdata, HDMI_AUI_HEADER0, infoframe->any.type);
-		hdmi_reg_writeb(hdata, HDMI_AUI_HEADER1,
-				infoframe->any.version);
-		hdmi_reg_writeb(hdata, HDMI_AUI_HEADER2, infoframe->any.length);
-		hdr_sum = infoframe->any.type + infoframe->any.version +
-			  infoframe->any.length;
-		chksum = hdmi_chksum(hdata, HDMI_AUI_BYTE(1),
-					infoframe->any.length, hdr_sum);
-		DRM_DEBUG_KMS("AUI checksum = 0x%x\n", chksum);
-		hdmi_reg_writeb(hdata, HDMI_AUI_CHECK_SUM, chksum);
-		break;
-	default:
-		break;
+	ret = hdmi_audio_infoframe_init(&frm.audio);
+	if (!ret) {
+		frm.audio.channels = 2;
+		ret = hdmi_audio_infoframe_pack(&frm.audio, buf, sizeof(buf));
+	}
+	if (ret > 0) {
+		hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC);
+		hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, ret);
 	}
 }
 
@@ -1127,8 +1077,6 @@ static void hdmi_start(struct hdmi_conte
 
 static void hdmi_conf_init(struct hdmi_context *hdata)
 {
-	union hdmi_infoframe infoframe;
-
 	/* disable HPD interrupts from HDMI IP block, use GPIO instead */
 	hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
 		HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
@@ -1164,15 +1112,7 @@ static void hdmi_conf_init(struct hdmi_c
 		hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
 		hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
 	} else {
-		infoframe.any.type = HDMI_INFOFRAME_TYPE_AVI;
-		infoframe.any.version = HDMI_AVI_VERSION;
-		infoframe.any.length = HDMI_AVI_LENGTH;
-		hdmi_reg_infoframe(hdata, &infoframe);
-
-		infoframe.any.type = HDMI_INFOFRAME_TYPE_AUDIO;
-		infoframe.any.version = HDMI_AUI_VERSION;
-		infoframe.any.length = HDMI_AUI_LENGTH;
-		hdmi_reg_infoframe(hdata, &infoframe);
+		hdmi_reg_infoframes(hdata);
 
 		/* enable AVI packet every vsync, fixes purple line problem */
 		hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
@@ -1458,7 +1398,6 @@ static void hdmi_mode_set(struct drm_enc
 		"INTERLACED" : "PROGRESSIVE");
 
 	drm_mode_copy(&hdata->current_mode, m);
-	hdata->cea_video_id = drm_match_cea_mode(mode);
 }
 
 static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -114,7 +114,7 @@ config DRM_EXYNOS_ROTATOR
 
 config DRM_EXYNOS_GSC
 	bool "GScaler"
-	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && !VIDEO_SAMSUNG_EXYNOS_GSC
+	depends on DRM_EXYNOS_IPP && ARCH_EXYNOS5 && VIDEO_SAMSUNG_EXYNOS_GSC=n
 	help
 	  Choose this option if you want to use Exynos GSC for DRM.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/exynos/regs-hdmi.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/regs-hdmi.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/exynos/regs-hdmi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/exynos/regs-hdmi.h	2017-02-12 16:03:20.000000000 -0500
@@ -361,9 +361,11 @@
 
 /* AUI bit definition */
 #define HDMI_AUI_CON_NO_TRAN		(0 << 0)
+#define HDMI_AUI_CON_EVERY_VSYNC	(1 << 1)
 
 /* VSI bit definition */
 #define HDMI_VSI_CON_DO_NOT_TRANSMIT	(0 << 0)
+#define HDMI_VSI_CON_EVERY_VSYNC	(1 << 1)
 
 /* HDCP related registers */
 #define HDMI_HDCP_SHA1(n)		HDMI_CORE_BASE(0x7000 + 4 * (n))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,9 @@
 #include "fsl_dcu_drm_drv.h"
 #include "fsl_tcon.h"
 
+static int legacyfb_depth = 24;
+module_param(legacyfb_depth, int, 0444);
+
 static bool fsl_dcu_drm_is_volatile_reg(struct device *dev, unsigned int reg)
 {
 	if (reg == DCU_INT_STATUS || reg == DCU_UPDATE_MODE)
@@ -85,7 +88,18 @@ static int fsl_dcu_load(struct drm_devic
 		goto done;
 	dev->irq_enabled = true;
 
-	fsl_dcu_fbdev_init(dev);
+	if (legacyfb_depth != 16 && legacyfb_depth != 24 &&
+	    legacyfb_depth != 32) {
+		dev_warn(dev->dev,
+			"Invalid legacyfb_depth.  Defaulting to 24bpp\n");
+		legacyfb_depth = 24;
+	}
+	fsl_dev->fbdev = drm_fbdev_cma_init(dev, legacyfb_depth, 1, 1);
+	if (IS_ERR(fsl_dev->fbdev)) {
+		ret = PTR_ERR(fsl_dev->fbdev);
+		fsl_dev->fbdev = NULL;
+		goto done;
+	}
 
 	return 0;
 done:
@@ -106,6 +120,7 @@ static int fsl_dcu_unload(struct drm_dev
 {
 	struct fsl_dcu_drm_device *fsl_dev = dev->dev_private;
 
+	drm_crtc_force_disable_all(dev);
 	drm_kms_helper_poll_fini(dev);
 
 	if (fsl_dev->fbdev)
@@ -176,9 +191,7 @@ static const struct file_operations fsl_
 	.open		= drm_open,
 	.release	= drm_release,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl	= drm_compat_ioctl,
-#endif
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.llseek		= no_llseek,
@@ -334,11 +347,6 @@ static int fsl_dcu_drm_probe(struct plat
 	fsl_dev->soc = id->data;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(dev, "could not get memory IO resource\n");
-		return -ENODEV;
-	}
-
 	base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(base)) {
 		ret = PTR_ERR(base);
@@ -348,7 +356,7 @@ static int fsl_dcu_drm_probe(struct plat
 	fsl_dev->irq = platform_get_irq(pdev, 0);
 	if (fsl_dev->irq < 0) {
 		dev_err(dev, "failed to get irq\n");
-		return -ENXIO;
+		return fsl_dev->irq;
 	}
 
 	fsl_dev->regmap = devm_regmap_init_mmio(dev, base,
@@ -426,9 +434,9 @@ static int fsl_dcu_drm_remove(struct pla
 {
 	struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev);
 
+	drm_put_dev(fsl_dev->drm);
 	clk_disable_unprepare(fsl_dev->clk);
 	clk_unregister(fsl_dev->pix_clk);
-	drm_put_dev(fsl_dev->drm);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -197,7 +197,6 @@ struct fsl_dcu_drm_device {
 	struct drm_atomic_state *state;
 };
 
-void fsl_dcu_fbdev_init(struct drm_device *dev);
 int fsl_dcu_drm_modeset_init(struct fsl_dcu_drm_device *fsl_dev);
 
 #endif /* __FSL_DCU_DRM_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_fbdev.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * Copyright 2015 Freescale Semiconductor, Inc.
- *
- * Freescale DCU drm device 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.
- */
-
-#include <drm/drmP.h>
-#include <drm/drm_fb_cma_helper.h>
-
-#include "fsl_dcu_drm_drv.h"
-
-/* initialize fbdev helper */
-void fsl_dcu_fbdev_init(struct drm_device *dev)
-{
-	struct fsl_dcu_drm_device *fsl_dev = dev_get_drvdata(dev->dev);
-
-	fsl_dev->fbdev = drm_fbdev_cma_init(dev, 24, 1, 1);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,17 +58,10 @@ static void fsl_dcu_drm_connector_destro
 	drm_connector_cleanup(connector);
 }
 
-static enum drm_connector_status
-fsl_dcu_drm_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = {
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 	.destroy = fsl_dcu_drm_connector_destroy,
-	.detect = fsl_dcu_drm_connector_detect,
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.reset = drm_atomic_helper_connector_reset,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/fsl-dcu/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/fsl-dcu/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -3,6 +3,5 @@ fsl-dcu-drm-y := fsl_dcu_drm_drv.o \
 		 fsl_dcu_drm_rgb.o \
 		 fsl_dcu_drm_plane.o \
 		 fsl_dcu_drm_crtc.o \
-		 fsl_dcu_drm_fbdev.o \
 		 fsl_tcon.o
 obj-$(CONFIG_DRM_FSL_DCU)	+= fsl-dcu-drm.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/cdv_intel_lvds.c	2017-02-12 16:03:20.000000000 -0500
@@ -387,19 +387,6 @@ static void cdv_intel_lvds_mode_set(stru
 }
 
 /**
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status cdv_intel_lvds_detect(
-				struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-/**
  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
  */
 static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
@@ -521,7 +508,6 @@ static const struct drm_connector_helper
 
 static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
-	.detect = cdv_intel_lvds_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = cdv_intel_lvds_set_property,
 	.destroy = cdv_intel_lvds_destroy,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/gma500/framebuffer.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/framebuffer.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/gma500/framebuffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/framebuffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -124,8 +124,8 @@ static int psbfb_vm_fault(struct vm_area
 	unsigned long phys_addr = (unsigned long)dev_priv->stolen_base +
 				  psbfb->gtt->offset;
 
-	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
-	address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT);
+	page_num = vma_pages(vma);
+	address = vmf->address - (vmf->pgoff << PAGE_SHIFT);
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
@@ -185,9 +185,7 @@ static int psbfb_mmap(struct fb_info *in
 
 static struct fb_ops psbfb_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_blank = drm_fb_helper_blank,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_setcolreg = psbfb_setcolreg,
 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
 	.fb_copyarea = psbfb_copyarea,
@@ -198,9 +196,7 @@ static struct fb_ops psbfb_ops = {
 
 static struct fb_ops psbfb_roll_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_blank = drm_fb_helper_blank,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_setcolreg = psbfb_setcolreg,
 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
@@ -211,9 +207,7 @@ static struct fb_ops psbfb_roll_ops = {
 
 static struct fb_ops psbfb_unaccel_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_blank = drm_fb_helper_blank,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_setcolreg = psbfb_setcolreg,
 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
@@ -236,22 +230,20 @@ static int psb_framebuffer_init(struct d
 					const struct drm_mode_fb_cmd2 *mode_cmd,
 					struct gtt_range *gt)
 {
-	u32 bpp, depth;
+	const struct drm_format_info *info;
 	int ret;
 
-	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+	/*
+	 * Reject unknown formats, YUV formats, and formats with more than
+	 * 4 bytes per pixel.
+	 */
+	info = drm_format_info(mode_cmd->pixel_format);
+	if (!info || !info->depth || info->cpp[0] > 4)
+		return -EINVAL;
 
 	if (mode_cmd->pitches[0] & 63)
 		return -EINVAL;
-	switch (bpp) {
-	case 8:
-	case 16:
-	case 24:
-	case 32:
-		break;
-	default:
-		return -EINVAL;
-	}
+
 	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
 	fb->gtt = gt;
 	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
@@ -298,7 +290,6 @@ static struct drm_framebuffer *psb_frame
  *	psbfb_alloc		-	allocate frame buffer memory
  *	@dev: the DRM device
  *	@aligned_size: space needed
- *	@force: fall back to GEM buffers if need be
  *
  *	Allocate the frame buffer. In the usual case we get a GTT range that
  *	is stolen memory backed and life is simple. If there isn't sufficient
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/gma500/gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/gma500/gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -197,15 +197,14 @@ int psb_gem_fault(struct vm_area_struct
 
 	/* Page relative to the VMA start - we must calculate this ourselves
 	   because vmf->pgoff is the fake GEM offset */
-	page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
-				>> PAGE_SHIFT;
+	page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
 	/* CPU view of the page, don't go via the GART for CPU writes */
 	if (r->stolen)
 		pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
 	else
 		pfn = page_to_pfn(r->pages[page_offset]);
-	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
+	ret = vm_insert_pfn(vma, vmf->address, pfn);
 
 fail:
 	mutex_unlock(&dev_priv->mmap_mutex);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/gma500/gtt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/gtt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/gma500/gtt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/gtt.c	2017-02-12 16:03:20.000000000 -0500
@@ -76,6 +76,7 @@ static u32 __iomem *psb_gtt_entry(struct
  *	psb_gtt_insert	-	put an object into the GTT
  *	@dev: our DRM device
  *	@r: our GTT range
+ *	@resume: on resume
  *
  *	Take our preallocated GTT range and insert the GEM object into
  *	the GTT. This is protected via the gtt mutex which the caller
@@ -130,7 +131,7 @@ static int psb_gtt_insert(struct drm_dev
  *	page table entries with the dummy page. This is protected via the gtt
  *	mutex which the caller must hold.
  */
-void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
+static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	u32 __iomem *gtt_slot;
@@ -321,6 +322,7 @@ out:
  *	@len: length (bytes) of address space required
  *	@name: resource name
  *	@backed: resource should be backed by stolen pages
+ *	@align: requested alignment
  *
  *	Ask the kernel core to find us a suitable range of addresses
  *	to use for a GTT mapping.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/gma500/psb_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/psb_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/gma500/psb_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/psb_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -473,6 +473,7 @@ static const struct file_operations psb_
 	.open = drm_open,
 	.release = drm_release,
 	.unlocked_ioctl = psb_unlocked_ioctl,
+	.compat_ioctl = drm_compat_ioctl,
 	.mmap = drm_gem_mmap,
 	.poll = drm_poll,
 	.read = drm_read,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/gma500/psb_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/psb_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/gma500/psb_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/psb_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -753,10 +753,6 @@ extern int psb_gem_dumb_create(struct dr
 extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
 			uint32_t handle, uint64_t *offset);
 extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file);
-extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
-					struct drm_file *file);
 
 /* psb_device.c */
 extern const struct psb_ops psb_chip_ops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/gma500/psb_intel_lvds.c	2017-02-12 16:03:20.000000000 -0500
@@ -500,19 +500,6 @@ static void psb_intel_lvds_mode_set(stru
 }
 
 /*
- * Detect the LVDS connection.
- *
- * This always returns CONNECTOR_STATUS_CONNECTED.
- * This connector should only have
- * been set up if the LVDS was actually connected anyway.
- */
-static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
-						   *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-/*
  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
  */
 static int psb_intel_lvds_get_modes(struct drm_connector *connector)
@@ -643,7 +630,6 @@ const struct drm_connector_helper_funcs
 
 const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
-	.detect = psb_intel_lvds_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = psb_intel_lvds_set_property,
 	.destroy = psb_intel_lvds_destroy,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,477 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei.com>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.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 <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+struct hibmc_display_panel_pll {
+	unsigned long M;
+	unsigned long N;
+	unsigned long OD;
+	unsigned long POD;
+};
+
+struct hibmc_dislay_pll_config {
+	unsigned long hdisplay;
+	unsigned long vdisplay;
+	u32 pll1_config_value;
+	u32 pll2_config_value;
+};
+
+static const struct hibmc_dislay_pll_config hibmc_pll_table[] = {
+	{800, 600, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
+	{1024, 768, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
+	{1152, 864, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
+	{1280, 768, CRT_PLL1_HS_80MHZ, CRT_PLL2_HS_80MHZ},
+	{1280, 720, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
+	{1280, 960, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
+	{1280, 1024, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
+	{1600, 1200, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
+	{1920, 1080, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
+	{1920, 1200, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
+};
+
+#define PADDING(align, data) (((data) + (align) - 1) & (~((align) - 1)))
+
+static int hibmc_plane_atomic_check(struct drm_plane *plane,
+				    struct drm_plane_state *state)
+{
+	struct drm_framebuffer *fb = state->fb;
+	struct drm_crtc *crtc = state->crtc;
+	struct drm_crtc_state *crtc_state;
+	u32 src_w = state->src_w >> 16;
+	u32 src_h = state->src_h >> 16;
+
+	if (!crtc || !fb)
+		return 0;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	if (src_w != state->crtc_w || src_h != state->crtc_h) {
+		DRM_DEBUG_ATOMIC("scale not support\n");
+		return -EINVAL;
+	}
+
+	if (state->crtc_x < 0 || state->crtc_y < 0) {
+		DRM_DEBUG_ATOMIC("crtc_x/y of drm_plane state is invalid\n");
+		return -EINVAL;
+	}
+
+	if (state->crtc_x + state->crtc_w >
+	    crtc_state->adjusted_mode.hdisplay ||
+	    state->crtc_y + state->crtc_h >
+	    crtc_state->adjusted_mode.vdisplay) {
+		DRM_DEBUG_ATOMIC("visible portion of plane is invalid\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void hibmc_plane_atomic_update(struct drm_plane *plane,
+				      struct drm_plane_state *old_state)
+{
+	struct drm_plane_state	*state	= plane->state;
+	u32 reg;
+	int ret;
+	u64 gpu_addr = 0;
+	unsigned int line_l;
+	struct hibmc_drm_private *priv = plane->dev->dev_private;
+	struct hibmc_framebuffer *hibmc_fb;
+	struct hibmc_bo *bo;
+
+	if (!state->fb)
+		return;
+
+	hibmc_fb = to_hibmc_framebuffer(state->fb);
+	bo = gem_to_hibmc_bo(hibmc_fb->obj);
+	ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+	if (ret) {
+		DRM_ERROR("failed to reserve ttm_bo: %d", ret);
+		return;
+	}
+
+	ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
+	ttm_bo_unreserve(&bo->bo);
+	if (ret) {
+		DRM_ERROR("failed to pin hibmc_bo: %d", ret);
+		return;
+	}
+
+	writel(gpu_addr, priv->mmio + HIBMC_CRT_FB_ADDRESS);
+
+	reg = state->fb->width * (state->fb->bits_per_pixel / 8);
+	/* now line_pad is 16 */
+	reg = PADDING(16, reg);
+
+	line_l = state->fb->width * state->fb->bits_per_pixel / 8;
+	line_l = PADDING(16, line_l);
+	writel(HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_WIDTH, reg) |
+	       HIBMC_FIELD(HIBMC_CRT_FB_WIDTH_OFFS, line_l),
+	       priv->mmio + HIBMC_CRT_FB_WIDTH);
+
+	/* SET PIXEL FORMAT */
+	reg = readl(priv->mmio + HIBMC_CRT_DISP_CTL);
+	reg &= ~HIBMC_CRT_DISP_CTL_FORMAT_MASK;
+	reg |= HIBMC_FIELD(HIBMC_CRT_DISP_CTL_FORMAT,
+			   state->fb->bits_per_pixel / 16);
+	writel(reg, priv->mmio + HIBMC_CRT_DISP_CTL);
+}
+
+static const u32 channel_formats1[] = {
+	DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888,
+	DRM_FORMAT_BGR888, DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ABGR8888
+};
+
+static struct drm_plane_funcs hibmc_plane_funcs = {
+	.update_plane	= drm_atomic_helper_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = {
+	.atomic_check = hibmc_plane_atomic_check,
+	.atomic_update = hibmc_plane_atomic_update,
+};
+
+static struct drm_plane *hibmc_plane_init(struct hibmc_drm_private *priv)
+{
+	struct drm_device *dev = priv->dev;
+	struct drm_plane *plane;
+	int ret = 0;
+
+	plane = devm_kzalloc(dev->dev, sizeof(*plane), GFP_KERNEL);
+	if (!plane) {
+		DRM_ERROR("failed to alloc memory when init plane\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	/*
+	 * plane init
+	 * TODO: Now only support primary plane, overlay planes
+	 * need to do.
+	 */
+	ret = drm_universal_plane_init(dev, plane, 1, &hibmc_plane_funcs,
+				       channel_formats1,
+				       ARRAY_SIZE(channel_formats1),
+				       DRM_PLANE_TYPE_PRIMARY,
+				       NULL);
+	if (ret) {
+		DRM_ERROR("failed to init plane: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(plane, &hibmc_plane_helper_funcs);
+	return plane;
+}
+
+static void hibmc_crtc_enable(struct drm_crtc *crtc)
+{
+	unsigned int reg;
+	struct hibmc_drm_private *priv = crtc->dev->dev_private;
+
+	hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg |= HIBMC_CURR_GATE_LOCALMEM(1);
+	reg |= HIBMC_CURR_GATE_DISPLAY(1);
+	hibmc_set_current_gate(priv, reg);
+	drm_crtc_vblank_on(crtc);
+}
+
+static void hibmc_crtc_disable(struct drm_crtc *crtc)
+{
+	unsigned int reg;
+	struct hibmc_drm_private *priv = crtc->dev->dev_private;
+
+	drm_crtc_vblank_off(crtc);
+
+	hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_SLEEP);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg |= HIBMC_CURR_GATE_LOCALMEM(0);
+	reg |= HIBMC_CURR_GATE_DISPLAY(0);
+	hibmc_set_current_gate(priv, reg);
+}
+
+static unsigned int format_pll_reg(void)
+{
+	unsigned int pllreg = 0;
+	struct hibmc_display_panel_pll pll = {0};
+
+	/*
+	 * Note that all PLL's have the same format. Here,
+	 * we just use Panel PLL parameter to work out the bit
+	 * fields in the register.On returning a 32 bit number, the value can
+	 * be applied to any PLL in the calling function.
+	 */
+	pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_BYPASS, 0);
+	pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_POWER, 1);
+	pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_INPUT, 0);
+	pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_POD, pll.POD);
+	pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_OD, pll.OD);
+	pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_N, pll.N);
+	pllreg |= HIBMC_FIELD(HIBMC_PLL_CTRL_M, pll.M);
+
+	return pllreg;
+}
+
+static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll)
+{
+	u32 val;
+	struct hibmc_drm_private *priv = dev->dev_private;
+
+	val = readl(priv->mmio + CRT_PLL1_HS);
+	val &= ~(CRT_PLL1_HS_OUTER_BYPASS(1));
+	writel(val, priv->mmio + CRT_PLL1_HS);
+
+	val = CRT_PLL1_HS_INTER_BYPASS(1) | CRT_PLL1_HS_POWERON(1);
+	writel(val, priv->mmio + CRT_PLL1_HS);
+
+	writel(pll, priv->mmio + CRT_PLL1_HS);
+
+	usleep_range(1000, 2000);
+
+	val = pll & ~(CRT_PLL1_HS_POWERON(1));
+	writel(val, priv->mmio + CRT_PLL1_HS);
+
+	usleep_range(1000, 2000);
+
+	val &= ~(CRT_PLL1_HS_INTER_BYPASS(1));
+	writel(val, priv->mmio + CRT_PLL1_HS);
+
+	usleep_range(1000, 2000);
+
+	val |= CRT_PLL1_HS_OUTER_BYPASS(1);
+	writel(val, priv->mmio + CRT_PLL1_HS);
+}
+
+static void get_pll_config(unsigned long x, unsigned long y,
+			   u32 *pll1, u32 *pll2)
+{
+	int i;
+	int count = ARRAY_SIZE(hibmc_pll_table);
+
+	for (i = 0; i < count; i++) {
+		if (hibmc_pll_table[i].hdisplay == x &&
+		    hibmc_pll_table[i].vdisplay == y) {
+			*pll1 = hibmc_pll_table[i].pll1_config_value;
+			*pll2 = hibmc_pll_table[i].pll2_config_value;
+			return;
+		}
+	}
+
+	/* if found none, we use default value */
+	*pll1 = CRT_PLL1_HS_25MHZ;
+	*pll2 = CRT_PLL2_HS_25MHZ;
+}
+
+/*
+ * This function takes care the extra registers and bit fields required to
+ * setup a mode in board.
+ * Explanation about Display Control register:
+ * FPGA only supports 7 predefined pixel clocks, and clock select is
+ * in bit 4:0 of new register 0x802a8.
+ */
+static unsigned int display_ctrl_adjust(struct drm_device *dev,
+					struct drm_display_mode *mode,
+					unsigned int ctrl)
+{
+	unsigned long x, y;
+	u32 pll1; /* bit[31:0] of PLL */
+	u32 pll2; /* bit[63:32] of PLL */
+	struct hibmc_drm_private *priv = dev->dev_private;
+
+	x = mode->hdisplay;
+	y = mode->vdisplay;
+
+	get_pll_config(x, y, &pll1, &pll2);
+	writel(pll2, priv->mmio + CRT_PLL2_HS);
+	set_vclock_hisilicon(dev, pll1);
+
+	/*
+	 * Hisilicon has to set up the top-left and bottom-right
+	 * registers as well.
+	 * Note that normal chip only use those two register for
+	 * auto-centering mode.
+	 */
+	writel(HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_TL_TOP, 0) |
+	       HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_TL_LEFT, 0),
+	       priv->mmio + HIBMC_CRT_AUTO_CENTERING_TL);
+
+	writel(HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM, y - 1) |
+	       HIBMC_FIELD(HIBMC_CRT_AUTO_CENTERING_BR_RIGHT, x - 1),
+	       priv->mmio + HIBMC_CRT_AUTO_CENTERING_BR);
+
+	/*
+	 * Assume common fields in ctrl have been properly set before
+	 * calling this function.
+	 * This function only sets the extra fields in ctrl.
+	 */
+
+	/* Set bit 25 of display controller: Select CRT or VGA clock */
+	ctrl &= ~HIBMC_CRT_DISP_CTL_CRTSELECT_MASK;
+	ctrl &= ~HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK;
+
+	ctrl |= HIBMC_CRT_DISP_CTL_CRTSELECT(HIBMC_CRTSELECT_CRT);
+
+	/* clock_phase_polarity is 0 */
+	ctrl |= HIBMC_CRT_DISP_CTL_CLOCK_PHASE(0);
+
+	writel(ctrl, priv->mmio + HIBMC_CRT_DISP_CTL);
+
+	return ctrl;
+}
+
+static void hibmc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	unsigned int val;
+	struct drm_display_mode *mode = &crtc->state->mode;
+	struct drm_device *dev = crtc->dev;
+	struct hibmc_drm_private *priv = dev->dev_private;
+	int width = mode->hsync_end - mode->hsync_start;
+	int height = mode->vsync_end - mode->vsync_start;
+
+	writel(format_pll_reg(), priv->mmio + HIBMC_CRT_PLL_CTRL);
+	writel(HIBMC_FIELD(HIBMC_CRT_HORZ_TOTAL_TOTAL, mode->htotal - 1) |
+	       HIBMC_FIELD(HIBMC_CRT_HORZ_TOTAL_DISP_END, mode->hdisplay - 1),
+	       priv->mmio + HIBMC_CRT_HORZ_TOTAL);
+
+	writel(HIBMC_FIELD(HIBMC_CRT_HORZ_SYNC_WIDTH, width) |
+	       HIBMC_FIELD(HIBMC_CRT_HORZ_SYNC_START, mode->hsync_start - 1),
+	       priv->mmio + HIBMC_CRT_HORZ_SYNC);
+
+	writel(HIBMC_FIELD(HIBMC_CRT_VERT_TOTAL_TOTAL, mode->vtotal - 1) |
+	       HIBMC_FIELD(HIBMC_CRT_VERT_TOTAL_DISP_END, mode->vdisplay - 1),
+	       priv->mmio + HIBMC_CRT_VERT_TOTAL);
+
+	writel(HIBMC_FIELD(HIBMC_CRT_VERT_SYNC_HEIGHT, height) |
+	       HIBMC_FIELD(HIBMC_CRT_VERT_SYNC_START, mode->vsync_start - 1),
+	       priv->mmio + HIBMC_CRT_VERT_SYNC);
+
+	val = HIBMC_FIELD(HIBMC_CRT_DISP_CTL_VSYNC_PHASE, 0);
+	val |= HIBMC_FIELD(HIBMC_CRT_DISP_CTL_HSYNC_PHASE, 0);
+	val |= HIBMC_CRT_DISP_CTL_TIMING(1);
+	val |= HIBMC_CRT_DISP_CTL_PLANE(1);
+
+	display_ctrl_adjust(dev, mode, val);
+}
+
+static void hibmc_crtc_atomic_begin(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+{
+	unsigned int reg;
+	struct drm_device *dev = crtc->dev;
+	struct hibmc_drm_private *priv = dev->dev_private;
+
+	hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg |= HIBMC_CURR_GATE_DISPLAY(1);
+	reg |= HIBMC_CURR_GATE_LOCALMEM(1);
+	hibmc_set_current_gate(priv, reg);
+
+	/* We can add more initialization as needed. */
+}
+
+static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_state)
+
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&crtc->dev->event_lock, flags);
+	if (crtc->state->event)
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+	crtc->state->event = NULL;
+	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+}
+
+static const struct drm_crtc_funcs hibmc_crtc_funcs = {
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_config = drm_atomic_helper_set_config,
+	.destroy = drm_crtc_cleanup,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state =  drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
+	.enable		= hibmc_crtc_enable,
+	.disable	= hibmc_crtc_disable,
+	.mode_set_nofb	= hibmc_crtc_mode_set_nofb,
+	.atomic_begin	= hibmc_crtc_atomic_begin,
+	.atomic_flush	= hibmc_crtc_atomic_flush,
+};
+
+int hibmc_de_init(struct hibmc_drm_private *priv)
+{
+	struct drm_device *dev = priv->dev;
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+	int ret;
+
+	plane = hibmc_plane_init(priv);
+	if (IS_ERR(plane)) {
+		DRM_ERROR("failed to create plane: %ld\n", PTR_ERR(plane));
+		return PTR_ERR(plane);
+	}
+
+	crtc = devm_kzalloc(dev->dev, sizeof(*crtc), GFP_KERNEL);
+	if (!crtc) {
+		DRM_ERROR("failed to alloc memory when init crtc\n");
+		return -ENOMEM;
+	}
+
+	ret = drm_crtc_init_with_planes(dev, crtc, plane,
+					NULL, &hibmc_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init crtc: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_mode_crtc_set_gamma_size(crtc, 256);
+	if (ret) {
+		DRM_ERROR("failed to set gamma size: %d\n", ret);
+		return ret;
+	}
+	drm_crtc_helper_add(crtc, &hibmc_crtc_helper_funcs);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,456 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei.com>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.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/console.h>
+#include <linux/module.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+static const struct file_operations hibmc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+	.compat_ioctl	= drm_compat_ioctl,
+	.mmap		= hibmc_mmap,
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+};
+
+static int hibmc_enable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	struct hibmc_drm_private *priv =
+		(struct hibmc_drm_private *)dev->dev_private;
+
+	writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(1),
+	       priv->mmio + HIBMC_RAW_INTERRUPT_EN);
+
+	return 0;
+}
+
+static void hibmc_disable_vblank(struct drm_device *dev, unsigned int pipe)
+{
+	struct hibmc_drm_private *priv =
+		(struct hibmc_drm_private *)dev->dev_private;
+
+	writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(0),
+	       priv->mmio + HIBMC_RAW_INTERRUPT_EN);
+}
+
+irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
+{
+	struct drm_device *dev = (struct drm_device *)arg;
+	struct hibmc_drm_private *priv =
+		(struct hibmc_drm_private *)dev->dev_private;
+	u32 status;
+
+	status = readl(priv->mmio + HIBMC_RAW_INTERRUPT);
+
+	if (status & HIBMC_RAW_INTERRUPT_VBLANK(1)) {
+		writel(HIBMC_RAW_INTERRUPT_VBLANK(1),
+		       priv->mmio + HIBMC_RAW_INTERRUPT);
+		drm_handle_vblank(dev, 0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct drm_driver hibmc_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
+				  DRIVER_ATOMIC | DRIVER_HAVE_IRQ,
+	.fops			= &hibmc_fops,
+	.name			= "hibmc",
+	.date			= "20160828",
+	.desc			= "hibmc drm driver",
+	.major			= 1,
+	.minor			= 0,
+	.get_vblank_counter	= drm_vblank_no_hw_counter,
+	.enable_vblank		= hibmc_enable_vblank,
+	.disable_vblank		= hibmc_disable_vblank,
+	.gem_free_object_unlocked = hibmc_gem_free_object,
+	.dumb_create            = hibmc_dumb_create,
+	.dumb_map_offset        = hibmc_dumb_mmap_offset,
+	.dumb_destroy           = drm_gem_dumb_destroy,
+	.irq_handler		= hibmc_drm_interrupt,
+};
+
+static int __maybe_unused hibmc_pm_suspend(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct hibmc_drm_private *priv = drm_dev->dev_private;
+
+	drm_kms_helper_poll_disable(drm_dev);
+	priv->suspend_state = drm_atomic_helper_suspend(drm_dev);
+	if (IS_ERR(priv->suspend_state)) {
+		DRM_ERROR("drm_atomic_helper_suspend failed: %ld\n",
+			  PTR_ERR(priv->suspend_state));
+		drm_kms_helper_poll_enable(drm_dev);
+		return PTR_ERR(priv->suspend_state);
+	}
+
+	return 0;
+}
+
+static int  __maybe_unused hibmc_pm_resume(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct drm_device *drm_dev = pci_get_drvdata(pdev);
+	struct hibmc_drm_private *priv = drm_dev->dev_private;
+
+	drm_atomic_helper_resume(drm_dev, priv->suspend_state);
+	drm_kms_helper_poll_enable(drm_dev);
+
+	return 0;
+}
+
+static const struct dev_pm_ops hibmc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(hibmc_pm_suspend,
+				hibmc_pm_resume)
+};
+
+static int hibmc_kms_init(struct hibmc_drm_private *priv)
+{
+	int ret;
+
+	drm_mode_config_init(priv->dev);
+	priv->mode_config_initialized = true;
+
+	priv->dev->mode_config.min_width = 0;
+	priv->dev->mode_config.min_height = 0;
+	priv->dev->mode_config.max_width = 1920;
+	priv->dev->mode_config.max_height = 1440;
+
+	priv->dev->mode_config.fb_base = priv->fb_base;
+	priv->dev->mode_config.preferred_depth = 24;
+	priv->dev->mode_config.prefer_shadow = 0;
+
+	priv->dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
+
+	ret = hibmc_de_init(priv);
+	if (ret) {
+		DRM_ERROR("failed to init de: %d\n", ret);
+		return ret;
+	}
+
+	ret = hibmc_vdac_init(priv);
+	if (ret) {
+		DRM_ERROR("failed to init vdac: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void hibmc_kms_fini(struct hibmc_drm_private *priv)
+{
+	if (priv->mode_config_initialized) {
+		drm_mode_config_cleanup(priv->dev);
+		priv->mode_config_initialized = false;
+	}
+}
+
+/*
+ * It can operate in one of three modes: 0, 1 or Sleep.
+ */
+void hibmc_set_power_mode(struct hibmc_drm_private *priv,
+			  unsigned int power_mode)
+{
+	unsigned int control_value = 0;
+	void __iomem   *mmio = priv->mmio;
+	unsigned int input = 1;
+
+	if (power_mode > HIBMC_PW_MODE_CTL_MODE_SLEEP)
+		return;
+
+	if (power_mode == HIBMC_PW_MODE_CTL_MODE_SLEEP)
+		input = 0;
+
+	control_value = readl(mmio + HIBMC_POWER_MODE_CTRL);
+	control_value &= ~(HIBMC_PW_MODE_CTL_MODE_MASK |
+			   HIBMC_PW_MODE_CTL_OSC_INPUT_MASK);
+	control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_MODE, power_mode);
+	control_value |= HIBMC_FIELD(HIBMC_PW_MODE_CTL_OSC_INPUT, input);
+	writel(control_value, mmio + HIBMC_POWER_MODE_CTRL);
+}
+
+void hibmc_set_current_gate(struct hibmc_drm_private *priv, unsigned int gate)
+{
+	unsigned int gate_reg;
+	unsigned int mode;
+	void __iomem   *mmio = priv->mmio;
+
+	/* Get current power mode. */
+	mode = (readl(mmio + HIBMC_POWER_MODE_CTRL) &
+		HIBMC_PW_MODE_CTL_MODE_MASK) >> HIBMC_PW_MODE_CTL_MODE_SHIFT;
+
+	switch (mode) {
+	case HIBMC_PW_MODE_CTL_MODE_MODE0:
+		gate_reg = HIBMC_MODE0_GATE;
+		break;
+
+	case HIBMC_PW_MODE_CTL_MODE_MODE1:
+		gate_reg = HIBMC_MODE1_GATE;
+		break;
+
+	default:
+		gate_reg = HIBMC_MODE0_GATE;
+		break;
+	}
+	writel(gate, mmio + gate_reg);
+}
+
+static void hibmc_hw_config(struct hibmc_drm_private *priv)
+{
+	unsigned int reg;
+
+	/* On hardware reset, power mode 0 is default. */
+	hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0);
+
+	/* Enable display power gate & LOCALMEM power gate*/
+	reg = readl(priv->mmio + HIBMC_CURRENT_GATE);
+	reg &= ~HIBMC_CURR_GATE_DISPLAY_MASK;
+	reg &= ~HIBMC_CURR_GATE_LOCALMEM_MASK;
+	reg |= HIBMC_CURR_GATE_DISPLAY(1);
+	reg |= HIBMC_CURR_GATE_LOCALMEM(1);
+
+	hibmc_set_current_gate(priv, reg);
+
+	/*
+	 * Reset the memory controller. If the memory controller
+	 * is not reset in chip,the system might hang when sw accesses
+	 * the memory.The memory should be resetted after
+	 * changing the MXCLK.
+	 */
+	reg = readl(priv->mmio + HIBMC_MISC_CTRL);
+	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(0);
+	writel(reg, priv->mmio + HIBMC_MISC_CTRL);
+
+	reg &= ~HIBMC_MSCCTL_LOCALMEM_RESET_MASK;
+	reg |= HIBMC_MSCCTL_LOCALMEM_RESET(1);
+
+	writel(reg, priv->mmio + HIBMC_MISC_CTRL);
+}
+
+static int hibmc_hw_map(struct hibmc_drm_private *priv)
+{
+	struct drm_device *dev = priv->dev;
+	struct pci_dev *pdev = dev->pdev;
+	resource_size_t addr, size, ioaddr, iosize;
+
+	ioaddr = pci_resource_start(pdev, 1);
+	iosize = pci_resource_len(pdev, 1);
+	priv->mmio = devm_ioremap_nocache(dev->dev, ioaddr, iosize);
+	if (!priv->mmio) {
+		DRM_ERROR("Cannot map mmio region\n");
+		return -ENOMEM;
+	}
+
+	addr = pci_resource_start(pdev, 0);
+	size = pci_resource_len(pdev, 0);
+	priv->fb_map = devm_ioremap(dev->dev, addr, size);
+	if (!priv->fb_map) {
+		DRM_ERROR("Cannot map framebuffer\n");
+		return -ENOMEM;
+	}
+	priv->fb_base = addr;
+	priv->fb_size = size;
+
+	return 0;
+}
+
+static int hibmc_hw_init(struct hibmc_drm_private *priv)
+{
+	int ret;
+
+	ret = hibmc_hw_map(priv);
+	if (ret)
+		return ret;
+
+	hibmc_hw_config(priv);
+
+	return 0;
+}
+
+static int hibmc_unload(struct drm_device *dev)
+{
+	struct hibmc_drm_private *priv = dev->dev_private;
+
+	hibmc_fbdev_fini(priv);
+
+	if (dev->irq_enabled)
+		drm_irq_uninstall(dev);
+	if (priv->msi_enabled)
+		pci_disable_msi(dev->pdev);
+	drm_vblank_cleanup(dev);
+
+	hibmc_kms_fini(priv);
+	hibmc_mm_fini(priv);
+	dev->dev_private = NULL;
+	return 0;
+}
+
+static int hibmc_load(struct drm_device *dev)
+{
+	struct hibmc_drm_private *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		DRM_ERROR("no memory to allocate for hibmc_drm_private\n");
+		return -ENOMEM;
+	}
+	dev->dev_private = priv;
+	priv->dev = dev;
+
+	ret = hibmc_hw_init(priv);
+	if (ret)
+		goto err;
+
+	ret = hibmc_mm_init(priv);
+	if (ret)
+		goto err;
+
+	ret = hibmc_kms_init(priv);
+	if (ret)
+		goto err;
+
+	ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+	if (ret) {
+		DRM_ERROR("failed to initialize vblank: %d\n", ret);
+		goto err;
+	}
+
+	priv->msi_enabled = 0;
+	ret = pci_enable_msi(dev->pdev);
+	if (ret) {
+		DRM_WARN("enabling MSI failed: %d\n", ret);
+	} else {
+		priv->msi_enabled = 1;
+		ret = drm_irq_install(dev, dev->pdev->irq);
+		if (ret)
+			DRM_WARN("install irq failed: %d\n", ret);
+	}
+
+	/* reset all the states of crtc/plane/encoder/connector */
+	drm_mode_config_reset(dev);
+
+	ret = hibmc_fbdev_init(priv);
+	if (ret) {
+		DRM_ERROR("failed to initialize fbdev: %d\n", ret);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	hibmc_unload(dev);
+	DRM_ERROR("failed to initialize drm driver: %d\n", ret);
+	return ret;
+}
+
+static int hibmc_pci_probe(struct pci_dev *pdev,
+			   const struct pci_device_id *ent)
+{
+	struct drm_device *dev;
+	int ret;
+
+	dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
+	if (IS_ERR(dev)) {
+		DRM_ERROR("failed to allocate drm_device\n");
+		return PTR_ERR(dev);
+	}
+
+	dev->pdev = pdev;
+	pci_set_drvdata(pdev, dev);
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		DRM_ERROR("failed to enable pci device: %d\n", ret);
+		goto err_free;
+	}
+
+	ret = hibmc_load(dev);
+	if (ret) {
+		DRM_ERROR("failed to load hibmc: %d\n", ret);
+		goto err_disable;
+	}
+
+	ret = drm_dev_register(dev, 0);
+	if (ret) {
+		DRM_ERROR("failed to register drv for userspace access: %d\n",
+			  ret);
+		goto err_unload;
+	}
+	return 0;
+
+err_unload:
+	hibmc_unload(dev);
+err_disable:
+	pci_disable_device(pdev);
+err_free:
+	drm_dev_unref(dev);
+
+	return ret;
+}
+
+static void hibmc_pci_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+
+	drm_dev_unregister(dev);
+	hibmc_unload(dev);
+	drm_dev_unref(dev);
+}
+
+static struct pci_device_id hibmc_pci_table[] = {
+	{0x19e5, 0x1711, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}
+};
+
+static struct pci_driver hibmc_pci_driver = {
+	.name =		"hibmc-drm",
+	.id_table =	hibmc_pci_table,
+	.probe =	hibmc_pci_probe,
+	.remove =	hibmc_pci_remove,
+	.driver.pm =    &hibmc_pm_ops,
+};
+
+static int __init hibmc_init(void)
+{
+	return pci_register_driver(&hibmc_pci_driver);
+}
+
+static void __exit hibmc_exit(void)
+{
+	return pci_unregister_driver(&hibmc_pci_driver);
+}
+
+module_init(hibmc_init);
+module_exit(hibmc_exit);
+
+MODULE_DEVICE_TABLE(pci, hibmc_pci_table);
+MODULE_AUTHOR("RongrongZou <zourongrong@huawei.com>");
+MODULE_DESCRIPTION("DRM Driver for Hisilicon Hibmc");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,114 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei.com>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.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 HIBMC_DRM_DRV_H
+#define HIBMC_DRM_DRV_H
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem.h>
+#include <drm/ttm/ttm_bo_driver.h>
+
+struct hibmc_framebuffer {
+	struct drm_framebuffer fb;
+	struct drm_gem_object *obj;
+};
+
+struct hibmc_fbdev {
+	struct drm_fb_helper helper;
+	struct hibmc_framebuffer *fb;
+	int size;
+};
+
+struct hibmc_drm_private {
+	/* hw */
+	void __iomem   *mmio;
+	void __iomem   *fb_map;
+	unsigned long  fb_base;
+	unsigned long  fb_size;
+	bool msi_enabled;
+
+	/* drm */
+	struct drm_device  *dev;
+	bool mode_config_initialized;
+	struct drm_atomic_state *suspend_state;
+
+	/* ttm */
+	struct drm_global_reference mem_global_ref;
+	struct ttm_bo_global_ref bo_global_ref;
+	struct ttm_bo_device bdev;
+	bool initialized;
+
+	/* fbdev */
+	struct hibmc_fbdev *fbdev;
+	bool mm_inited;
+};
+
+#define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb)
+
+struct hibmc_bo {
+	struct ttm_buffer_object bo;
+	struct ttm_placement placement;
+	struct ttm_bo_kmap_obj kmap;
+	struct drm_gem_object gem;
+	struct ttm_place placements[3];
+	int pin_count;
+};
+
+static inline struct hibmc_bo *hibmc_bo(struct ttm_buffer_object *bo)
+{
+	return container_of(bo, struct hibmc_bo, bo);
+}
+
+static inline struct hibmc_bo *gem_to_hibmc_bo(struct drm_gem_object *gem)
+{
+	return container_of(gem, struct hibmc_bo, gem);
+}
+
+void hibmc_set_power_mode(struct hibmc_drm_private *priv,
+			  unsigned int power_mode);
+void hibmc_set_current_gate(struct hibmc_drm_private *priv,
+			    unsigned int gate);
+
+int hibmc_de_init(struct hibmc_drm_private *priv);
+int hibmc_vdac_init(struct hibmc_drm_private *priv);
+int hibmc_fbdev_init(struct hibmc_drm_private *priv);
+void hibmc_fbdev_fini(struct hibmc_drm_private *priv);
+
+int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+		     struct drm_gem_object **obj);
+struct hibmc_framebuffer *
+hibmc_framebuffer_init(struct drm_device *dev,
+		       const struct drm_mode_fb_cmd2 *mode_cmd,
+		       struct drm_gem_object *obj);
+
+int hibmc_mm_init(struct hibmc_drm_private *hibmc);
+void hibmc_mm_fini(struct hibmc_drm_private *hibmc);
+int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr);
+int hibmc_bo_unpin(struct hibmc_bo *bo);
+void hibmc_gem_free_object(struct drm_gem_object *obj);
+int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
+		      struct drm_mode_create_dumb *args);
+int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+			   u32 handle, u64 *offset);
+int hibmc_mmap(struct file *filp, struct vm_area_struct *vma);
+
+extern const struct drm_mode_config_funcs hibmc_mode_funcs;
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,267 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei.com>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.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 <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+
+#include "hibmc_drm_drv.h"
+
+static int hibmcfb_create_object(
+				struct hibmc_drm_private *priv,
+				const struct drm_mode_fb_cmd2 *mode_cmd,
+				struct drm_gem_object **gobj_p)
+{
+	struct drm_gem_object *gobj;
+	struct drm_device *dev = priv->dev;
+	u32 size;
+	int ret = 0;
+
+	size = mode_cmd->pitches[0] * mode_cmd->height;
+	ret = hibmc_gem_create(dev, size, true, &gobj);
+	if (ret)
+		return ret;
+
+	*gobj_p = gobj;
+	return ret;
+}
+
+static struct fb_ops hibmc_drm_fb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_fillrect = drm_fb_helper_sys_fillrect,
+	.fb_copyarea = drm_fb_helper_sys_copyarea,
+	.fb_imageblit = drm_fb_helper_sys_imageblit,
+	.fb_pan_display = drm_fb_helper_pan_display,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static int hibmc_drm_fb_create(struct drm_fb_helper *helper,
+			       struct drm_fb_helper_surface_size *sizes)
+{
+	struct hibmc_fbdev *hi_fbdev =
+		container_of(helper, struct hibmc_fbdev, helper);
+	struct hibmc_drm_private *priv = helper->dev->dev_private;
+	struct fb_info *info;
+	struct drm_mode_fb_cmd2 mode_cmd;
+	struct drm_gem_object *gobj = NULL;
+	int ret = 0;
+	int ret1;
+	size_t size;
+	unsigned int bytes_per_pixel;
+	struct hibmc_bo *bo = NULL;
+
+	DRM_DEBUG_DRIVER("surface width(%d), height(%d) and bpp(%d)\n",
+			 sizes->surface_width, sizes->surface_height,
+			 sizes->surface_bpp);
+	sizes->surface_depth = 32;
+
+	bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8);
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+	mode_cmd.pitches[0] = mode_cmd.width * bytes_per_pixel;
+	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+							  sizes->surface_depth);
+
+	size = PAGE_ALIGN(mode_cmd.pitches[0] * mode_cmd.height);
+
+	ret = hibmcfb_create_object(priv, &mode_cmd, &gobj);
+	if (ret) {
+		DRM_ERROR("failed to create fbcon backing object: %d\n", ret);
+		return -ENOMEM;
+	}
+
+	bo = gem_to_hibmc_bo(gobj);
+
+	ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
+	if (ret) {
+		DRM_ERROR("failed to reserve ttm_bo: %d\n", ret);
+		goto out_unref_gem;
+	}
+
+	ret = hibmc_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
+	if (ret) {
+		DRM_ERROR("failed to pin fbcon: %d\n", ret);
+		goto out_unreserve_ttm_bo;
+	}
+
+	ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
+	if (ret) {
+		DRM_ERROR("failed to kmap fbcon: %d\n", ret);
+		goto out_unpin_bo;
+	}
+	ttm_bo_unreserve(&bo->bo);
+
+	info = drm_fb_helper_alloc_fbi(helper);
+	if (IS_ERR(info)) {
+		ret = PTR_ERR(info);
+		DRM_ERROR("failed to allocate fbi: %d\n", ret);
+		goto out_release_fbi;
+	}
+
+	info->par = hi_fbdev;
+
+	hi_fbdev->fb = hibmc_framebuffer_init(priv->dev, &mode_cmd, gobj);
+	if (IS_ERR(hi_fbdev->fb)) {
+		ret = PTR_ERR(info);
+		DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
+		goto out_release_fbi;
+	}
+
+	priv->fbdev->size = size;
+	hi_fbdev->helper.fb = &hi_fbdev->fb->fb;
+
+	strcpy(info->fix.id, "hibmcdrmfb");
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &hibmc_drm_fb_ops;
+
+	drm_fb_helper_fill_fix(info, hi_fbdev->fb->fb.pitches[0],
+			       hi_fbdev->fb->fb.depth);
+	drm_fb_helper_fill_var(info, &priv->fbdev->helper, sizes->fb_width,
+			       sizes->fb_height);
+
+	info->screen_base = bo->kmap.virtual;
+	info->screen_size = size;
+
+	info->fix.smem_start = bo->bo.mem.bus.offset + bo->bo.mem.bus.base;
+	info->fix.smem_len = size;
+	return 0;
+
+out_release_fbi:
+	drm_fb_helper_release_fbi(helper);
+	ret1 = ttm_bo_reserve(&bo->bo, true, false, NULL);
+	if (ret1) {
+		DRM_ERROR("failed to rsv ttm_bo when release fbi: %d\n", ret1);
+		goto out_unref_gem;
+	}
+	ttm_bo_kunmap(&bo->kmap);
+out_unpin_bo:
+	hibmc_bo_unpin(bo);
+out_unreserve_ttm_bo:
+	ttm_bo_unreserve(&bo->bo);
+out_unref_gem:
+	drm_gem_object_unreference_unlocked(gobj);
+
+	return ret;
+}
+
+static void hibmc_fbdev_destroy(struct hibmc_fbdev *fbdev)
+{
+	struct hibmc_framebuffer *gfb = fbdev->fb;
+	struct drm_fb_helper *fbh = &fbdev->helper;
+
+	drm_fb_helper_unregister_fbi(fbh);
+	drm_fb_helper_release_fbi(fbh);
+
+	drm_fb_helper_fini(fbh);
+
+	if (gfb)
+		drm_framebuffer_unreference(&gfb->fb);
+}
+
+static const struct drm_fb_helper_funcs hibmc_fbdev_helper_funcs = {
+	.fb_probe = hibmc_drm_fb_create,
+};
+
+int hibmc_fbdev_init(struct hibmc_drm_private *priv)
+{
+	int ret;
+	struct fb_var_screeninfo *var;
+	struct fb_fix_screeninfo *fix;
+	struct hibmc_fbdev *hifbdev;
+
+	hifbdev = devm_kzalloc(priv->dev->dev, sizeof(*hifbdev), GFP_KERNEL);
+	if (!hifbdev) {
+		DRM_ERROR("failed to allocate hibmc_fbdev\n");
+		return -ENOMEM;
+	}
+
+	priv->fbdev = hifbdev;
+	drm_fb_helper_prepare(priv->dev, &hifbdev->helper,
+			      &hibmc_fbdev_helper_funcs);
+
+	/* Now just one crtc and one channel */
+	ret = drm_fb_helper_init(priv->dev,
+				 &hifbdev->helper, 1, 1);
+	if (ret) {
+		DRM_ERROR("failed to initialize fb helper: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(&hifbdev->helper);
+	if (ret) {
+		DRM_ERROR("failed to add all connectors: %d\n", ret);
+		goto fini;
+	}
+
+	ret = drm_fb_helper_initial_config(&hifbdev->helper, 16);
+	if (ret) {
+		DRM_ERROR("failed to setup initial conn config: %d\n", ret);
+		goto fini;
+	}
+
+	var = &hifbdev->helper.fbdev->var;
+	fix = &hifbdev->helper.fbdev->fix;
+
+	DRM_DEBUG_DRIVER("Member of info->var is :\n"
+			 "xres=%d\n"
+			 "yres=%d\n"
+			 "xres_virtual=%d\n"
+			 "yres_virtual=%d\n"
+			 "xoffset=%d\n"
+			 "yoffset=%d\n"
+			 "bits_per_pixel=%d\n"
+			 "...\n", var->xres, var->yres, var->xres_virtual,
+			 var->yres_virtual, var->xoffset, var->yoffset,
+			 var->bits_per_pixel);
+	DRM_DEBUG_DRIVER("Member of info->fix is :\n"
+			 "smem_start=%lx\n"
+			 "smem_len=%d\n"
+			 "type=%d\n"
+			 "type_aux=%d\n"
+			 "visual=%d\n"
+			 "xpanstep=%d\n"
+			 "ypanstep=%d\n"
+			 "ywrapstep=%d\n"
+			 "line_length=%d\n"
+			 "accel=%d\n"
+			 "capabilities=%d\n"
+			 "...\n", fix->smem_start, fix->smem_len, fix->type,
+			 fix->type_aux, fix->visual, fix->xpanstep,
+			 fix->ypanstep, fix->ywrapstep, fix->line_length,
+			 fix->accel, fix->capabilities);
+
+	return 0;
+
+fini:
+	drm_fb_helper_fini(&hifbdev->helper);
+	return ret;
+}
+
+void hibmc_fbdev_fini(struct hibmc_drm_private *priv)
+{
+	if (!priv->fbdev)
+		return;
+
+	hibmc_fbdev_destroy(priv->fbdev);
+	priv->fbdev = NULL;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,196 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei.com>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.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 HIBMC_DRM_HW_H
+#define HIBMC_DRM_HW_H
+
+/* register definition */
+#define HIBMC_MISC_CTRL				0x4
+
+#define HIBMC_MSCCTL_LOCALMEM_RESET(x)		((x) << 6)
+#define HIBMC_MSCCTL_LOCALMEM_RESET_MASK	0x40
+
+#define HIBMC_CURRENT_GATE			0x000040
+#define HIBMC_CURR_GATE_DISPLAY(x)		((x) << 2)
+#define HIBMC_CURR_GATE_DISPLAY_MASK		0x4
+
+#define HIBMC_CURR_GATE_LOCALMEM(x)		((x) << 1)
+#define HIBMC_CURR_GATE_LOCALMEM_MASK		0x2
+
+#define HIBMC_MODE0_GATE			0x000044
+#define HIBMC_MODE1_GATE			0x000048
+#define HIBMC_POWER_MODE_CTRL			0x00004C
+
+#define HIBMC_PW_MODE_CTL_OSC_INPUT(x)		((x) << 3)
+#define HIBMC_PW_MODE_CTL_OSC_INPUT_MASK	0x8
+
+#define HIBMC_PW_MODE_CTL_MODE(x)		((x) << 0)
+#define HIBMC_PW_MODE_CTL_MODE_MASK		0x03
+#define HIBMC_PW_MODE_CTL_MODE_SHIFT		0
+
+#define HIBMC_PW_MODE_CTL_MODE_MODE0		0
+#define HIBMC_PW_MODE_CTL_MODE_MODE1		1
+#define HIBMC_PW_MODE_CTL_MODE_SLEEP		2
+
+#define HIBMC_PANEL_PLL_CTRL			0x00005C
+#define HIBMC_CRT_PLL_CTRL			0x000060
+
+#define HIBMC_PLL_CTRL_BYPASS(x)		((x) << 18)
+#define HIBMC_PLL_CTRL_BYPASS_MASK		0x40000
+
+#define HIBMC_PLL_CTRL_POWER(x)			((x) << 17)
+#define HIBMC_PLL_CTRL_POWER_MASK		0x20000
+
+#define HIBMC_PLL_CTRL_INPUT(x)			((x) << 16)
+#define HIBMC_PLL_CTRL_INPUT_MASK		0x10000
+
+#define HIBMC_PLL_CTRL_POD(x)			((x) << 14)
+#define HIBMC_PLL_CTRL_POD_MASK			0xC000
+
+#define HIBMC_PLL_CTRL_OD(x)			((x) << 12)
+#define HIBMC_PLL_CTRL_OD_MASK			0x3000
+
+#define HIBMC_PLL_CTRL_N(x)			((x) << 8)
+#define HIBMC_PLL_CTRL_N_MASK			0xF00
+
+#define HIBMC_PLL_CTRL_M(x)			((x) << 0)
+#define HIBMC_PLL_CTRL_M_MASK			0xFF
+
+#define HIBMC_CRT_DISP_CTL			0x80200
+
+#define HIBMC_CRT_DISP_CTL_CRTSELECT(x)		((x) << 25)
+#define HIBMC_CRT_DISP_CTL_CRTSELECT_MASK	0x2000000
+
+#define HIBMC_CRTSELECT_CRT			1
+
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE(x)	((x) << 14)
+#define HIBMC_CRT_DISP_CTL_CLOCK_PHASE_MASK	0x4000
+
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE(x)	((x) << 13)
+#define HIBMC_CRT_DISP_CTL_VSYNC_PHASE_MASK	0x2000
+
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE(x)	((x) << 12)
+#define HIBMC_CRT_DISP_CTL_HSYNC_PHASE_MASK	0x1000
+
+#define HIBMC_CRT_DISP_CTL_TIMING(x)		((x) << 8)
+#define HIBMC_CRT_DISP_CTL_TIMING_MASK		0x100
+
+#define HIBMC_CRT_DISP_CTL_PLANE(x)		((x) << 2)
+#define HIBMC_CRT_DISP_CTL_PLANE_MASK		4
+
+#define HIBMC_CRT_DISP_CTL_FORMAT(x)		((x) << 0)
+#define HIBMC_CRT_DISP_CTL_FORMAT_MASK		0x03
+
+#define HIBMC_CRT_FB_ADDRESS			0x080204
+
+#define HIBMC_CRT_FB_WIDTH			0x080208
+#define HIBMC_CRT_FB_WIDTH_WIDTH(x)		((x) << 16)
+#define HIBMC_CRT_FB_WIDTH_WIDTH_MASK		0x3FFF0000
+#define HIBMC_CRT_FB_WIDTH_OFFS(x)		((x) << 0)
+#define HIBMC_CRT_FB_WIDTH_OFFS_MASK		0x3FFF
+
+#define HIBMC_CRT_HORZ_TOTAL			0x08020C
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL(x)		((x) << 16)
+#define HIBMC_CRT_HORZ_TOTAL_TOTAL_MASK		0xFFF0000
+
+#define HIBMC_CRT_HORZ_TOTAL_DISP_END(x)	((x) << 0)
+#define HIBMC_CRT_HORZ_TOTAL_DISP_END_MASK	0xFFF
+
+#define HIBMC_CRT_HORZ_SYNC			0x080210
+#define HIBMC_CRT_HORZ_SYNC_WIDTH(x)		((x) << 16)
+#define HIBMC_CRT_HORZ_SYNC_WIDTH_MASK		0xFF0000
+
+#define HIBMC_CRT_HORZ_SYNC_START(x)		((x) << 0)
+#define HIBMC_CRT_HORZ_SYNC_START_MASK		0xFFF
+
+#define HIBMC_CRT_VERT_TOTAL			0x080214
+#define HIBMC_CRT_VERT_TOTAL_TOTAL(x)		((x) << 16)
+#define HIBMC_CRT_VERT_TOTAL_TOTAL_MASK		0x7FFF0000
+
+#define HIBMC_CRT_VERT_TOTAL_DISP_END(x)	((x) << 0)
+#define HIBMC_CRT_VERT_TOTAL_DISP_END_MASK	0x7FF
+
+#define HIBMC_CRT_VERT_SYNC			0x080218
+#define HIBMC_CRT_VERT_SYNC_HEIGHT(x)		((x) << 16)
+#define HIBMC_CRT_VERT_SYNC_HEIGHT_MASK		0x3F0000
+
+#define HIBMC_CRT_VERT_SYNC_START(x)		((x) << 0)
+#define HIBMC_CRT_VERT_SYNC_START_MASK		0x7FF
+
+/* Auto Centering */
+#define HIBMC_CRT_AUTO_CENTERING_TL		0x080280
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP(x)	((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_TL_TOP_MASK	0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT(x)	((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_TL_LEFT_MASK	0x7FF
+
+#define HIBMC_CRT_AUTO_CENTERING_BR		0x080284
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM(x)	((x) << 16)
+#define HIBMC_CRT_AUTO_CENTERING_BR_BOTTOM_MASK	0x7FF0000
+
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT(x)	((x) << 0)
+#define HIBMC_CRT_AUTO_CENTERING_BR_RIGHT_MASK	0x7FF
+
+/* register to control panel output */
+#define HIBMC_DISPLAY_CONTROL_HISILE		0x80288
+#define HIBMC_DISPLAY_CONTROL_FPVDDEN(x)	((x) << 0)
+#define HIBMC_DISPLAY_CONTROL_PANELDATE(x)	((x) << 1)
+#define HIBMC_DISPLAY_CONTROL_FPEN(x)		((x) << 2)
+#define HIBMC_DISPLAY_CONTROL_VBIASEN(x)	((x) << 3)
+
+#define HIBMC_RAW_INTERRUPT			0x80290
+#define HIBMC_RAW_INTERRUPT_VBLANK(x)		((x) << 2)
+#define HIBMC_RAW_INTERRUPT_VBLANK_MASK		0x4
+
+#define HIBMC_RAW_INTERRUPT_EN			0x80298
+#define HIBMC_RAW_INTERRUPT_EN_VBLANK(x)	((x) << 2)
+#define HIBMC_RAW_INTERRUPT_EN_VBLANK_MASK	0x4
+
+/* register and values for PLL control */
+#define CRT_PLL1_HS				0x802a8
+#define CRT_PLL1_HS_OUTER_BYPASS(x)		((x) << 30)
+#define CRT_PLL1_HS_INTER_BYPASS(x)		((x) << 29)
+#define CRT_PLL1_HS_POWERON(x)			((x) << 24)
+
+#define CRT_PLL1_HS_25MHZ			0x23d40f02
+#define CRT_PLL1_HS_40MHZ			0x23940801
+#define CRT_PLL1_HS_65MHZ			0x23940d01
+#define CRT_PLL1_HS_78MHZ			0x23540F82
+#define CRT_PLL1_HS_74MHZ			0x23941dc2
+#define CRT_PLL1_HS_80MHZ			0x23941001
+#define CRT_PLL1_HS_80MHZ_1152			0x23540fc2
+#define CRT_PLL1_HS_108MHZ			0x23b41b01
+#define CRT_PLL1_HS_162MHZ			0x23480681
+#define CRT_PLL1_HS_148MHZ			0x23541dc2
+#define CRT_PLL1_HS_193MHZ			0x234807c1
+
+#define CRT_PLL2_HS				0x802ac
+#define CRT_PLL2_HS_25MHZ			0x206B851E
+#define CRT_PLL2_HS_40MHZ			0x30000000
+#define CRT_PLL2_HS_65MHZ			0x40000000
+#define CRT_PLL2_HS_78MHZ			0x50E147AE
+#define CRT_PLL2_HS_74MHZ			0x602B6AE7
+#define CRT_PLL2_HS_80MHZ			0x70000000
+#define CRT_PLL2_HS_108MHZ			0x80000000
+#define CRT_PLL2_HS_162MHZ			0xA0000000
+#define CRT_PLL2_HS_148MHZ			0xB0CCCCCD
+#define CRT_PLL2_HS_193MHZ			0xC0872B02
+
+#define HIBMC_FIELD(field, value) (field(value) & field##_MASK)
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,140 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei.com>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.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 <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "hibmc_drm_drv.h"
+#include "hibmc_drm_regs.h"
+
+static int hibmc_connector_get_modes(struct drm_connector *connector)
+{
+	return drm_add_modes_noedid(connector, 800, 600);
+}
+
+static int hibmc_connector_mode_valid(struct drm_connector *connector,
+				      struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+hibmc_connector_best_encoder(struct drm_connector *connector)
+{
+	return drm_encoder_find(connector->dev, connector->encoder_ids[0]);
+}
+
+static const struct drm_connector_helper_funcs
+	hibmc_connector_helper_funcs = {
+	.get_modes = hibmc_connector_get_modes,
+	.mode_valid = hibmc_connector_mode_valid,
+	.best_encoder = hibmc_connector_best_encoder,
+};
+
+static const struct drm_connector_funcs hibmc_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static struct drm_connector *
+hibmc_connector_init(struct hibmc_drm_private *priv)
+{
+	struct drm_device *dev = priv->dev;
+	struct drm_connector *connector;
+	int ret;
+
+	connector = devm_kzalloc(dev->dev, sizeof(*connector), GFP_KERNEL);
+	if (!connector) {
+		DRM_ERROR("failed to alloc memory when init connector\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = drm_connector_init(dev, connector,
+				 &hibmc_connector_funcs,
+				 DRM_MODE_CONNECTOR_VGA);
+	if (ret) {
+		DRM_ERROR("failed to init connector: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+	drm_connector_helper_add(connector,
+				 &hibmc_connector_helper_funcs);
+
+	return connector;
+}
+
+static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adj_mode)
+{
+	u32 reg;
+	struct drm_device *dev = encoder->dev;
+	struct hibmc_drm_private *priv = dev->dev_private;
+
+	reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
+	reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1);
+	reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
+	reg |= HIBMC_DISPLAY_CONTROL_FPEN(1);
+	reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1);
+	writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
+}
+
+static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = {
+	.mode_set = hibmc_encoder_mode_set,
+};
+
+static const struct drm_encoder_funcs hibmc_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+int hibmc_vdac_init(struct hibmc_drm_private *priv)
+{
+	struct drm_device *dev = priv->dev;
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+	int ret;
+
+	connector = hibmc_connector_init(priv);
+	if (IS_ERR(connector)) {
+		DRM_ERROR("failed to create connector: %ld\n",
+			  PTR_ERR(connector));
+		return PTR_ERR(connector);
+	}
+
+	encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
+	if (!encoder) {
+		DRM_ERROR("failed to alloc memory when init encoder\n");
+		return -ENOMEM;
+	}
+
+	encoder->possible_crtcs = 0x1;
+	ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs,
+			       DRM_MODE_ENCODER_DAC, NULL);
+	if (ret) {
+		DRM_ERROR("failed to init encoder: %d\n", ret);
+		return ret;
+	}
+
+	drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,558 @@
+/* Hisilicon Hibmc SoC drm driver
+ *
+ * Based on the bochs drm driver.
+ *
+ * Copyright (c) 2016 Huawei Limited.
+ *
+ * Author:
+ *	Rongrong Zou <zourongrong@huawei.com>
+ *	Rongrong Zou <zourongrong@gmail.com>
+ *	Jianhua Li <lijianhua@huawei.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 <drm/drm_atomic_helper.h>
+#include <ttm/ttm_page_alloc.h>
+
+#include "hibmc_drm_drv.h"
+
+#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+static inline struct hibmc_drm_private *
+hibmc_bdev(struct ttm_bo_device *bd)
+{
+	return container_of(bd, struct hibmc_drm_private, bdev);
+}
+
+static int
+hibmc_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+	return ttm_mem_global_init(ref->object);
+}
+
+static void
+hibmc_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+	ttm_mem_global_release(ref->object);
+}
+
+static int hibmc_ttm_global_init(struct hibmc_drm_private *hibmc)
+{
+	int ret;
+
+	hibmc->mem_global_ref.global_type = DRM_GLOBAL_TTM_MEM;
+	hibmc->mem_global_ref.size = sizeof(struct ttm_mem_global);
+	hibmc->mem_global_ref.init = &hibmc_ttm_mem_global_init;
+	hibmc->mem_global_ref.release = &hibmc_ttm_mem_global_release;
+	ret = drm_global_item_ref(&hibmc->mem_global_ref);
+	if (ret) {
+		DRM_ERROR("could not get ref on ttm global: %d\n", ret);
+		return ret;
+	}
+
+	hibmc->bo_global_ref.mem_glob =
+		hibmc->mem_global_ref.object;
+	hibmc->bo_global_ref.ref.global_type = DRM_GLOBAL_TTM_BO;
+	hibmc->bo_global_ref.ref.size = sizeof(struct ttm_bo_global);
+	hibmc->bo_global_ref.ref.init = &ttm_bo_global_init;
+	hibmc->bo_global_ref.ref.release = &ttm_bo_global_release;
+	ret = drm_global_item_ref(&hibmc->bo_global_ref.ref);
+	if (ret) {
+		DRM_ERROR("failed setting up TTM BO subsystem: %d\n", ret);
+		drm_global_item_unref(&hibmc->mem_global_ref);
+		return ret;
+	}
+	return 0;
+}
+
+static void
+hibmc_ttm_global_release(struct hibmc_drm_private *hibmc)
+{
+	drm_global_item_unref(&hibmc->bo_global_ref.ref);
+	drm_global_item_unref(&hibmc->mem_global_ref);
+	hibmc->mem_global_ref.release = NULL;
+}
+
+static void hibmc_bo_ttm_destroy(struct ttm_buffer_object *tbo)
+{
+	struct hibmc_bo *bo = container_of(tbo, struct hibmc_bo, bo);
+
+	drm_gem_object_release(&bo->gem);
+	kfree(bo);
+}
+
+static bool hibmc_ttm_bo_is_hibmc_bo(struct ttm_buffer_object *bo)
+{
+	return bo->destroy == &hibmc_bo_ttm_destroy;
+}
+
+static int
+hibmc_bo_init_mem_type(struct ttm_bo_device *bdev, u32 type,
+		       struct ttm_mem_type_manager *man)
+{
+	switch (type) {
+	case TTM_PL_SYSTEM:
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_MASK_CACHING;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		break;
+	case TTM_PL_VRAM:
+		man->func = &ttm_bo_manager_func;
+		man->flags = TTM_MEMTYPE_FLAG_FIXED |
+			TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_FLAG_UNCACHED |
+			TTM_PL_FLAG_WC;
+		man->default_caching = TTM_PL_FLAG_WC;
+		break;
+	default:
+		DRM_ERROR("unsupported memory type %u\n", type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+void hibmc_ttm_placement(struct hibmc_bo *bo, int domain)
+{
+	u32 count = 0;
+	u32 i;
+
+	bo->placement.placement = bo->placements;
+	bo->placement.busy_placement = bo->placements;
+	if (domain & TTM_PL_FLAG_VRAM)
+		bo->placements[count++].flags = TTM_PL_FLAG_WC |
+			TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
+	if (domain & TTM_PL_FLAG_SYSTEM)
+		bo->placements[count++].flags = TTM_PL_MASK_CACHING |
+			TTM_PL_FLAG_SYSTEM;
+	if (!count)
+		bo->placements[count++].flags = TTM_PL_MASK_CACHING |
+			TTM_PL_FLAG_SYSTEM;
+
+	bo->placement.num_placement = count;
+	bo->placement.num_busy_placement = count;
+	for (i = 0; i < count; i++) {
+		bo->placements[i].fpfn = 0;
+		bo->placements[i].lpfn = 0;
+	}
+}
+
+static void
+hibmc_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
+{
+	struct hibmc_bo *hibmcbo = hibmc_bo(bo);
+
+	if (!hibmc_ttm_bo_is_hibmc_bo(bo))
+		return;
+
+	hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_SYSTEM);
+	*pl = hibmcbo->placement;
+}
+
+static int hibmc_bo_verify_access(struct ttm_buffer_object *bo,
+				  struct file *filp)
+{
+	struct hibmc_bo *hibmcbo = hibmc_bo(bo);
+
+	return drm_vma_node_verify_access(&hibmcbo->gem.vma_node,
+					  filp->private_data);
+}
+
+static int hibmc_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
+				    struct ttm_mem_reg *mem)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+	struct hibmc_drm_private *hibmc = hibmc_bdev(bdev);
+
+	mem->bus.addr = NULL;
+	mem->bus.offset = 0;
+	mem->bus.size = mem->num_pages << PAGE_SHIFT;
+	mem->bus.base = 0;
+	mem->bus.is_iomem = false;
+	if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+		return -EINVAL;
+	switch (mem->mem_type) {
+	case TTM_PL_SYSTEM:
+		/* system memory */
+		return 0;
+	case TTM_PL_VRAM:
+		mem->bus.offset = mem->start << PAGE_SHIFT;
+		mem->bus.base = pci_resource_start(hibmc->dev->pdev, 0);
+		mem->bus.is_iomem = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void hibmc_ttm_backend_destroy(struct ttm_tt *tt)
+{
+	ttm_tt_fini(tt);
+	kfree(tt);
+}
+
+static struct ttm_backend_func hibmc_tt_backend_func = {
+	.destroy = &hibmc_ttm_backend_destroy,
+};
+
+static struct ttm_tt *hibmc_ttm_tt_create(struct ttm_bo_device *bdev,
+					  unsigned long size,
+					  u32 page_flags,
+					  struct page *dummy_read_page)
+{
+	struct ttm_tt *tt;
+	int ret;
+
+	tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+	if (!tt) {
+		DRM_ERROR("failed to allocate ttm_tt\n");
+		return NULL;
+	}
+	tt->func = &hibmc_tt_backend_func;
+	ret = ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page);
+	if (ret) {
+		DRM_ERROR("failed to initialize ttm_tt: %d\n", ret);
+		kfree(tt);
+		return NULL;
+	}
+	return tt;
+}
+
+static int hibmc_ttm_tt_populate(struct ttm_tt *ttm)
+{
+	return ttm_pool_populate(ttm);
+}
+
+static void hibmc_ttm_tt_unpopulate(struct ttm_tt *ttm)
+{
+	ttm_pool_unpopulate(ttm);
+}
+
+struct ttm_bo_driver hibmc_bo_driver = {
+	.ttm_tt_create		= hibmc_ttm_tt_create,
+	.ttm_tt_populate	= hibmc_ttm_tt_populate,
+	.ttm_tt_unpopulate	= hibmc_ttm_tt_unpopulate,
+	.init_mem_type		= hibmc_bo_init_mem_type,
+	.evict_flags		= hibmc_bo_evict_flags,
+	.move			= NULL,
+	.verify_access		= hibmc_bo_verify_access,
+	.io_mem_reserve		= &hibmc_ttm_io_mem_reserve,
+	.io_mem_free		= NULL,
+	.lru_tail		= &ttm_bo_default_lru_tail,
+	.swap_lru_tail		= &ttm_bo_default_swap_lru_tail,
+};
+
+int hibmc_mm_init(struct hibmc_drm_private *hibmc)
+{
+	int ret;
+	struct drm_device *dev = hibmc->dev;
+	struct ttm_bo_device *bdev = &hibmc->bdev;
+
+	ret = hibmc_ttm_global_init(hibmc);
+	if (ret)
+		return ret;
+
+	ret = ttm_bo_device_init(&hibmc->bdev,
+				 hibmc->bo_global_ref.ref.object,
+				 &hibmc_bo_driver,
+				 dev->anon_inode->i_mapping,
+				 DRM_FILE_PAGE_OFFSET,
+				 true);
+	if (ret) {
+		hibmc_ttm_global_release(hibmc);
+		DRM_ERROR("error initializing bo driver: %d\n", ret);
+		return ret;
+	}
+
+	ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
+			     hibmc->fb_size >> PAGE_SHIFT);
+	if (ret) {
+		hibmc_ttm_global_release(hibmc);
+		DRM_ERROR("failed ttm VRAM init: %d\n", ret);
+		return ret;
+	}
+
+	hibmc->mm_inited = true;
+	return 0;
+}
+
+void hibmc_mm_fini(struct hibmc_drm_private *hibmc)
+{
+	if (!hibmc->mm_inited)
+		return;
+
+	ttm_bo_device_release(&hibmc->bdev);
+	hibmc_ttm_global_release(hibmc);
+	hibmc->mm_inited = false;
+}
+
+static void hibmc_bo_unref(struct hibmc_bo **bo)
+{
+	struct ttm_buffer_object *tbo;
+
+	if ((*bo) == NULL)
+		return;
+
+	tbo = &((*bo)->bo);
+	ttm_bo_unref(&tbo);
+	*bo = NULL;
+}
+
+int hibmc_bo_create(struct drm_device *dev, int size, int align,
+		    u32 flags, struct hibmc_bo **phibmcbo)
+{
+	struct hibmc_drm_private *hibmc = dev->dev_private;
+	struct hibmc_bo *hibmcbo;
+	size_t acc_size;
+	int ret;
+
+	hibmcbo = kzalloc(sizeof(*hibmcbo), GFP_KERNEL);
+	if (!hibmcbo) {
+		DRM_ERROR("failed to allocate hibmcbo\n");
+		return -ENOMEM;
+	}
+	ret = drm_gem_object_init(dev, &hibmcbo->gem, size);
+	if (ret) {
+		DRM_ERROR("failed to initialize drm gem object: %d\n", ret);
+		kfree(hibmcbo);
+		return ret;
+	}
+
+	hibmcbo->bo.bdev = &hibmc->bdev;
+
+	hibmc_ttm_placement(hibmcbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
+
+	acc_size = ttm_bo_dma_acc_size(&hibmc->bdev, size,
+				       sizeof(struct hibmc_bo));
+
+	ret = ttm_bo_init(&hibmc->bdev, &hibmcbo->bo, size,
+			  ttm_bo_type_device, &hibmcbo->placement,
+			  align >> PAGE_SHIFT, false, NULL, acc_size,
+			  NULL, NULL, hibmc_bo_ttm_destroy);
+	if (ret) {
+		hibmc_bo_unref(&hibmcbo);
+		DRM_ERROR("failed to initialize ttm_bo: %d\n", ret);
+		return ret;
+	}
+
+	*phibmcbo = hibmcbo;
+	return 0;
+}
+
+int hibmc_bo_pin(struct hibmc_bo *bo, u32 pl_flag, u64 *gpu_addr)
+{
+	int i, ret;
+
+	if (bo->pin_count) {
+		bo->pin_count++;
+		if (gpu_addr)
+			*gpu_addr = bo->bo.offset;
+		return 0;
+	}
+
+	hibmc_ttm_placement(bo, pl_flag);
+	for (i = 0; i < bo->placement.num_placement; i++)
+		bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
+	ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+	if (ret)
+		return ret;
+
+	bo->pin_count = 1;
+	if (gpu_addr)
+		*gpu_addr = bo->bo.offset;
+	return 0;
+}
+
+int hibmc_bo_unpin(struct hibmc_bo *bo)
+{
+	int i, ret;
+
+	if (!bo->pin_count) {
+		DRM_ERROR("unpin bad %p\n", bo);
+		return 0;
+	}
+	bo->pin_count--;
+	if (bo->pin_count)
+		return 0;
+
+	for (i = 0; i < bo->placement.num_placement ; i++)
+		bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
+	ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false);
+	if (ret) {
+		DRM_ERROR("validate failed for unpin: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int hibmc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	struct hibmc_drm_private *hibmc;
+
+	if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
+		return -EINVAL;
+
+	file_priv = filp->private_data;
+	hibmc = file_priv->minor->dev->dev_private;
+	return ttm_bo_mmap(filp, vma, &hibmc->bdev);
+}
+
+int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel,
+		     struct drm_gem_object **obj)
+{
+	struct hibmc_bo *hibmcbo;
+	int ret;
+
+	*obj = NULL;
+
+	size = PAGE_ALIGN(size);
+	if (size == 0) {
+		DRM_ERROR("error: zero size\n");
+		return -EINVAL;
+	}
+
+	ret = hibmc_bo_create(dev, size, 0, 0, &hibmcbo);
+	if (ret) {
+		if (ret != -ERESTARTSYS)
+			DRM_ERROR("failed to allocate GEM object: %d\n", ret);
+		return ret;
+	}
+	*obj = &hibmcbo->gem;
+	return 0;
+}
+
+int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
+		      struct drm_mode_create_dumb *args)
+{
+	struct drm_gem_object *gobj;
+	u32 handle;
+	int ret;
+
+	args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 16);
+	args->size = args->pitch * args->height;
+
+	ret = hibmc_gem_create(dev, args->size, false,
+			       &gobj);
+	if (ret) {
+		DRM_ERROR("failed to create GEM object: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_gem_handle_create(file, gobj, &handle);
+	drm_gem_object_unreference_unlocked(gobj);
+	if (ret) {
+		DRM_ERROR("failed to unreference GEM object: %d\n", ret);
+		return ret;
+	}
+
+	args->handle = handle;
+	return 0;
+}
+
+void hibmc_gem_free_object(struct drm_gem_object *obj)
+{
+	struct hibmc_bo *hibmcbo = gem_to_hibmc_bo(obj);
+
+	hibmc_bo_unref(&hibmcbo);
+}
+
+static u64 hibmc_bo_mmap_offset(struct hibmc_bo *bo)
+{
+	return drm_vma_node_offset_addr(&bo->bo.vma_node);
+}
+
+int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
+			   u32 handle, u64 *offset)
+{
+	struct drm_gem_object *obj;
+	struct hibmc_bo *bo;
+
+	obj = drm_gem_object_lookup(file, handle);
+	if (!obj)
+		return -ENOENT;
+
+	bo = gem_to_hibmc_bo(obj);
+	*offset = hibmc_bo_mmap_offset(bo);
+
+	drm_gem_object_unreference_unlocked(obj);
+	return 0;
+}
+
+static void hibmc_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+	struct hibmc_framebuffer *hibmc_fb = to_hibmc_framebuffer(fb);
+
+	drm_gem_object_unreference_unlocked(hibmc_fb->obj);
+	drm_framebuffer_cleanup(fb);
+	kfree(hibmc_fb);
+}
+
+static const struct drm_framebuffer_funcs hibmc_fb_funcs = {
+	.destroy = hibmc_user_framebuffer_destroy,
+};
+
+struct hibmc_framebuffer *
+hibmc_framebuffer_init(struct drm_device *dev,
+		       const struct drm_mode_fb_cmd2 *mode_cmd,
+		       struct drm_gem_object *obj)
+{
+	struct hibmc_framebuffer *hibmc_fb;
+	int ret;
+
+	hibmc_fb = kzalloc(sizeof(*hibmc_fb), GFP_KERNEL);
+	if (!hibmc_fb) {
+		DRM_ERROR("failed to allocate hibmc_fb\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	drm_helper_mode_fill_fb_struct(&hibmc_fb->fb, mode_cmd);
+	hibmc_fb->obj = obj;
+	ret = drm_framebuffer_init(dev, &hibmc_fb->fb, &hibmc_fb_funcs);
+	if (ret) {
+		DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
+		kfree(hibmc_fb);
+		return ERR_PTR(ret);
+	}
+
+	return hibmc_fb;
+}
+
+static struct drm_framebuffer *
+hibmc_user_framebuffer_create(struct drm_device *dev,
+			      struct drm_file *filp,
+			      const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	struct drm_gem_object *obj;
+	struct hibmc_framebuffer *hibmc_fb;
+
+	DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n",
+			 mode_cmd->width, mode_cmd->height,
+			 (mode_cmd->pixel_format) & 0xff,
+			 (mode_cmd->pixel_format >> 8)  & 0xff,
+			 (mode_cmd->pixel_format >> 16) & 0xff,
+			 (mode_cmd->pixel_format >> 24) & 0xff);
+
+	obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
+	if (!obj)
+		return ERR_PTR(-ENOENT);
+
+	hibmc_fb = hibmc_framebuffer_init(dev, mode_cmd, obj);
+	if (IS_ERR(hibmc_fb)) {
+		drm_gem_object_unreference_unlocked(obj);
+		return ERR_PTR((long)hibmc_fb);
+	}
+	return &hibmc_fb->fb;
+}
+
+const struct drm_mode_config_funcs hibmc_mode_funcs = {
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+	.fb_create = hibmc_user_framebuffer_create,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,9 @@
+config DRM_HISI_HIBMC
+	tristate "DRM Support for Hisilicon Hibmc"
+	depends on DRM && PCI
+	select DRM_KMS_HELPER
+	select DRM_TTM
+
+	help
+	  Choose this option if you have a Hisilicon Hibmc soc chipset.
+	  If M is selected the module will be called hibmc-drm.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/hibmc/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/hibmc/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,4 @@
+ccflags-y := -Iinclude/drm
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_fbdev.o hibmc_ttm.o
+
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc-drm.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -2,4 +2,5 @@
 # hisilicon drm device configuration.
 # Please keep this list sorted alphabetically
 
+source "drivers/gpu/drm/hisilicon/hibmc/Kconfig"
 source "drivers/gpu/drm/hisilicon/kirin/Kconfig"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c	2017-02-12 16:03:20.000000000 -0500
@@ -608,17 +608,16 @@ static void ade_rdma_set(void __iomem *b
 			 u32 ch, u32 y, u32 in_h, u32 fmt)
 {
 	struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
-	char *format_name;
+	struct drm_format_name_buf format_name;
 	u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
 	u32 stride = fb->pitches[0];
 	u32 addr = (u32)obj->paddr + y * stride;
 
 	DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n",
 			 ch + 1, y, in_h, stride, (u32)obj->paddr);
-	format_name = drm_get_format_name(fb->pixel_format);
 	DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%s)\n",
-			 addr, fb->width, fb->height, fmt, format_name);
-	kfree(format_name);
+			 addr, fb->width, fb->height, fmt,
+			 drm_get_format_name(fb->pixel_format, &format_name));
 
 	/* get reg offset */
 	reg_ctrl = RD_CH_CTRL(ch);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
 
 #include "kirin_drm_drv.h"
 
@@ -151,9 +152,7 @@ static const struct file_operations kiri
 	.open		= drm_open,
 	.release	= drm_release,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl	= drm_compat_ioctl,
-#endif
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.llseek		= no_llseek,
@@ -260,14 +259,13 @@ static struct device_node *kirin_get_rem
 		DRM_ERROR("no valid endpoint node\n");
 		return ERR_PTR(-ENODEV);
 	}
-	of_node_put(endpoint);
 
 	remote = of_graph_get_remote_port_parent(endpoint);
+	of_node_put(endpoint);
 	if (!remote) {
 		DRM_ERROR("no valid remote node\n");
 		return ERR_PTR(-ENODEV);
 	}
-	of_node_put(remote);
 
 	if (!of_device_is_available(remote)) {
 		DRM_ERROR("not available for remote node\n");
@@ -294,7 +292,8 @@ static int kirin_drm_platform_probe(stru
 	if (IS_ERR(remote))
 		return PTR_ERR(remote);
 
-	component_match_add(dev, &match, compare_of, remote);
+	drm_of_component_match_add(dev, &match, compare_of, remote);
+	of_node_put(remote);
 
 	return component_master_add_with_match(dev, &kirin_drm_ops, match);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/hisilicon/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/hisilicon/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,4 +2,5 @@
 # Makefile for hisilicon drm drivers.
 # Please keep this list sorted alphabetically
 
+obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/
 obj-$(CONFIG_DRM_HISI_KIRIN) += kirin/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i2c/tda998x_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i2c/tda998x_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i2c/tda998x_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i2c/tda998x_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,12 +41,15 @@ struct tda998x_priv {
 	struct i2c_client *hdmi;
 	struct mutex mutex;
 	u16 rev;
+	u8 cec_addr;
 	u8 current_page;
-	int dpms;
-	bool is_hdmi_sink;
+	bool is_on;
+	bool supports_infoframes;
+	bool sink_has_audio;
 	u8 vip_cntrl_0;
 	u8 vip_cntrl_1;
 	u8 vip_cntrl_2;
+	unsigned long tmds_clock;
 	struct tda998x_audio_params audio_params;
 
 	struct platform_device *audio_pdev;
@@ -105,6 +108,8 @@ struct tda998x_priv {
 # define I2C_MASTER_DIS_FILT      (1 << 1)
 # define I2C_MASTER_APP_STRT_LAT  (1 << 2)
 #define REG_FEAT_POWERDOWN        REG(0x00, 0x0e)     /* read/write */
+# define FEAT_POWERDOWN_PREFILT   BIT(0)
+# define FEAT_POWERDOWN_CSC       BIT(1)
 # define FEAT_POWERDOWN_SPDIF     (1 << 3)
 #define REG_INT_FLAGS_0           REG(0x00, 0x0f)     /* read/write */
 #define REG_INT_FLAGS_1           REG(0x00, 0x10)     /* read/write */
@@ -370,35 +375,46 @@ struct tda998x_priv {
 static void
 cec_write(struct tda998x_priv *priv, u16 addr, u8 val)
 {
-	struct i2c_client *client = priv->cec;
 	u8 buf[] = {addr, val};
+	struct i2c_msg msg = {
+		.addr = priv->cec_addr,
+		.len = 2,
+		.buf = buf,
+	};
 	int ret;
 
-	ret = i2c_master_send(client, buf, sizeof(buf));
+	ret = i2c_transfer(priv->hdmi->adapter, &msg, 1);
 	if (ret < 0)
-		dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
+		dev_err(&priv->hdmi->dev, "Error %d writing to cec:0x%x\n",
+			ret, addr);
 }
 
 static u8
 cec_read(struct tda998x_priv *priv, u8 addr)
 {
-	struct i2c_client *client = priv->cec;
 	u8 val;
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cec_addr,
+			.len = 1,
+			.buf = &addr,
+		}, {
+			.addr = priv->cec_addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = &val,
+		},
+	};
 	int ret;
 
-	ret = i2c_master_send(client, &addr, sizeof(addr));
-	if (ret < 0)
-		goto fail;
-
-	ret = i2c_master_recv(client, &val, sizeof(val));
-	if (ret < 0)
-		goto fail;
+	ret = i2c_transfer(priv->hdmi->adapter, msg, ARRAY_SIZE(msg));
+	if (ret < 0) {
+		dev_err(&priv->hdmi->dev, "Error %d reading from cec:0x%x\n",
+			ret, addr);
+		val = 0;
+	}
 
 	return val;
-
-fail:
-	dev_err(&client->dev, "Error %d reading from cec:0x%x\n", ret, addr);
-	return 0;
 }
 
 static int
@@ -579,9 +595,9 @@ tda998x_reset(struct tda998x_priv *priv)
  * HPD assertion: it needs a delay of 100ms to avoid timing out while
  * trying to read EDID data.
  *
- * However, tda998x_encoder_get_modes() may be called at any moment
+ * However, tda998x_connector_get_modes() may be called at any moment
  * after tda998x_connector_detect() indicates that we are connected, so
- * we need to delay probing modes in tda998x_encoder_get_modes() after
+ * we need to delay probing modes in tda998x_connector_get_modes() after
  * we have seen a HPD inactive->active transition.  This code implements
  * that delay.
  */
@@ -630,28 +646,30 @@ static irqreturn_t tda998x_irq_thread(in
 	bool handled = false;
 
 	sta = cec_read(priv, REG_CEC_INTSTATUS);
-	cec = cec_read(priv, REG_CEC_RXSHPDINT);
-	lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
-	flag0 = reg_read(priv, REG_INT_FLAGS_0);
-	flag1 = reg_read(priv, REG_INT_FLAGS_1);
-	flag2 = reg_read(priv, REG_INT_FLAGS_2);
-	DRM_DEBUG_DRIVER(
-		"tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n",
-		sta, cec, lvl, flag0, flag1, flag2);
+	if (sta & CEC_INTSTATUS_HDMI) {
+		cec = cec_read(priv, REG_CEC_RXSHPDINT);
+		lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
+		flag0 = reg_read(priv, REG_INT_FLAGS_0);
+		flag1 = reg_read(priv, REG_INT_FLAGS_1);
+		flag2 = reg_read(priv, REG_INT_FLAGS_2);
+		DRM_DEBUG_DRIVER(
+			"tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n",
+			sta, cec, lvl, flag0, flag1, flag2);
 
-	if (cec & CEC_RXSHPDINT_HPD) {
-		if (lvl & CEC_RXSHPDLEV_HPD)
-			tda998x_edid_delay_start(priv);
-		else
-			schedule_work(&priv->detect_work);
+		if (cec & CEC_RXSHPDINT_HPD) {
+			if (lvl & CEC_RXSHPDLEV_HPD)
+				tda998x_edid_delay_start(priv);
+			else
+				schedule_work(&priv->detect_work);
 
-		handled = true;
-	}
+			handled = true;
+		}
 
-	if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
-		priv->wq_edid_wait = 0;
-		wake_up(&priv->wq_edid);
-		handled = true;
+		if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
+			priv->wq_edid_wait = 0;
+			wake_up(&priv->wq_edid);
+			handled = true;
+		}
 	}
 
 	return IRQ_RETVAL(handled);
@@ -700,6 +718,8 @@ tda998x_write_avi(struct tda998x_priv *p
 	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
 }
 
+/* Audio support */
+
 static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
 {
 	if (on) {
@@ -713,8 +733,7 @@ static void tda998x_audio_mute(struct td
 
 static int
 tda998x_configure_audio(struct tda998x_priv *priv,
-			struct tda998x_audio_params *params,
-			unsigned mode_clock)
+			struct tda998x_audio_params *params)
 {
 	u8 buf[6], clksel_aip, clksel_fs, cts_n, adiv;
 	u32 n;
@@ -771,7 +790,7 @@ tda998x_configure_audio(struct tda998x_p
 	 * assume 100MHz requires larger divider.
 	 */
 	adiv = AUDIO_DIV_SERCLK_8;
-	if (mode_clock > 100000)
+	if (priv->tmds_clock > 100000)
 		adiv++;			/* AUDIO_DIV_SERCLK_16 */
 
 	/* S/PDIF asks for a larger divider */
@@ -819,58 +838,281 @@ tda998x_configure_audio(struct tda998x_p
 	return tda998x_write_aif(priv, &params->cea);
 }
 
-/* DRM encoder functions */
+static int tda998x_audio_hw_params(struct device *dev, void *data,
+				   struct hdmi_codec_daifmt *daifmt,
+				   struct hdmi_codec_params *params)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+	int i, ret;
+	struct tda998x_audio_params audio = {
+		.sample_width = params->sample_width,
+		.sample_rate = params->sample_rate,
+		.cea = params->cea,
+	};
 
-static void tda998x_encoder_set_config(struct tda998x_priv *priv,
-				       const struct tda998x_encoder_params *p)
+	memcpy(audio.status, params->iec.status,
+	       min(sizeof(audio.status), sizeof(params->iec.status)));
+
+	switch (daifmt->fmt) {
+	case HDMI_I2S:
+		if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
+		    daifmt->bit_clk_master || daifmt->frame_clk_master) {
+			dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
+				daifmt->bit_clk_inv, daifmt->frame_clk_inv,
+				daifmt->bit_clk_master,
+				daifmt->frame_clk_master);
+			return -EINVAL;
+		}
+		for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
+			if (priv->audio_port[i].format == AFMT_I2S)
+				audio.config = priv->audio_port[i].config;
+		audio.format = AFMT_I2S;
+		break;
+	case HDMI_SPDIF:
+		for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
+			if (priv->audio_port[i].format == AFMT_SPDIF)
+				audio.config = priv->audio_port[i].config;
+		audio.format = AFMT_SPDIF;
+		break;
+	default:
+		dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
+		return -EINVAL;
+	}
+
+	if (audio.config == 0) {
+		dev_err(dev, "%s: No audio configuration found\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&priv->audio_mutex);
+	if (priv->supports_infoframes && priv->sink_has_audio)
+		ret = tda998x_configure_audio(priv, &audio);
+	else
+		ret = 0;
+
+	if (ret == 0)
+		priv->audio_params = audio;
+	mutex_unlock(&priv->audio_mutex);
+
+	return ret;
+}
+
+static void tda998x_audio_shutdown(struct device *dev, void *data)
 {
-	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
-			    (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
-			    VIP_CNTRL_0_SWAP_B(p->swap_b) |
-			    (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
-	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
-			    (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
-			    VIP_CNTRL_1_SWAP_D(p->swap_d) |
-			    (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
-	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
-			    (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
-			    VIP_CNTRL_2_SWAP_F(p->swap_f) |
-			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
 
-	priv->audio_params = p->audio_params;
+	mutex_lock(&priv->audio_mutex);
+
+	reg_write(priv, REG_ENA_AP, 0);
+
+	priv->audio_params.format = AFMT_UNUSED;
+
+	mutex_unlock(&priv->audio_mutex);
 }
 
-static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable)
 {
-	struct tda998x_priv *priv = enc_to_tda998x_priv(encoder);
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
 
-	/* we only care about on or off: */
-	if (mode != DRM_MODE_DPMS_ON)
-		mode = DRM_MODE_DPMS_OFF;
+	mutex_lock(&priv->audio_mutex);
 
-	if (mode == priv->dpms)
-		return;
+	tda998x_audio_mute(priv, enable);
 
-	switch (mode) {
-	case DRM_MODE_DPMS_ON:
-		/* enable video ports, audio will be enabled later */
-		reg_write(priv, REG_ENA_VP_0, 0xff);
-		reg_write(priv, REG_ENA_VP_1, 0xff);
-		reg_write(priv, REG_ENA_VP_2, 0xff);
-		/* set muxing after enabling ports: */
-		reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
-		reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
-		reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
-		break;
-	case DRM_MODE_DPMS_OFF:
-		/* disable video ports */
-		reg_write(priv, REG_ENA_VP_0, 0x00);
-		reg_write(priv, REG_ENA_VP_1, 0x00);
-		reg_write(priv, REG_ENA_VP_2, 0x00);
-		break;
+	mutex_unlock(&priv->audio_mutex);
+	return 0;
+}
+
+static int tda998x_audio_get_eld(struct device *dev, void *data,
+				 uint8_t *buf, size_t len)
+{
+	struct tda998x_priv *priv = dev_get_drvdata(dev);
+
+	mutex_lock(&priv->audio_mutex);
+	memcpy(buf, priv->connector.eld,
+	       min(sizeof(priv->connector.eld), len));
+	mutex_unlock(&priv->audio_mutex);
+
+	return 0;
+}
+
+static const struct hdmi_codec_ops audio_codec_ops = {
+	.hw_params = tda998x_audio_hw_params,
+	.audio_shutdown = tda998x_audio_shutdown,
+	.digital_mute = tda998x_audio_digital_mute,
+	.get_eld = tda998x_audio_get_eld,
+};
+
+static int tda998x_audio_codec_init(struct tda998x_priv *priv,
+				    struct device *dev)
+{
+	struct hdmi_codec_pdata codec_data = {
+		.ops = &audio_codec_ops,
+		.max_i2s_channels = 2,
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++) {
+		if (priv->audio_port[i].format == AFMT_I2S &&
+		    priv->audio_port[i].config != 0)
+			codec_data.i2s = 1;
+		if (priv->audio_port[i].format == AFMT_SPDIF &&
+		    priv->audio_port[i].config != 0)
+			codec_data.spdif = 1;
 	}
 
-	priv->dpms = mode;
+	priv->audio_pdev = platform_device_register_data(
+		dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
+		&codec_data, sizeof(codec_data));
+
+	return PTR_ERR_OR_ZERO(priv->audio_pdev);
+}
+
+/* DRM connector functions */
+
+static int tda998x_connector_dpms(struct drm_connector *connector, int mode)
+{
+	if (drm_core_check_feature(connector->dev, DRIVER_ATOMIC))
+		return drm_atomic_helper_connector_dpms(connector, mode);
+	else
+		return drm_helper_connector_dpms(connector, mode);
+}
+
+static int tda998x_connector_fill_modes(struct drm_connector *connector,
+					uint32_t maxX, uint32_t maxY)
+{
+	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+	int ret;
+
+	mutex_lock(&priv->audio_mutex);
+	ret = drm_helper_probe_single_connector_modes(connector, maxX, maxY);
+
+	if (connector->edid_blob_ptr) {
+		struct edid *edid = (void *)connector->edid_blob_ptr->data;
+
+		priv->sink_has_audio = drm_detect_monitor_audio(edid);
+	} else {
+		priv->sink_has_audio = false;
+	}
+	mutex_unlock(&priv->audio_mutex);
+
+	return ret;
+}
+
+static enum drm_connector_status
+tda998x_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+	u8 val = cec_read(priv, REG_CEC_RXSHPDLEV);
+
+	return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
+			connector_status_disconnected;
+}
+
+static void tda998x_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs tda998x_connector_funcs = {
+	.dpms = tda998x_connector_dpms,
+	.reset = drm_atomic_helper_connector_reset,
+	.fill_modes = tda998x_connector_fill_modes,
+	.detect = tda998x_connector_detect,
+	.destroy = tda998x_connector_destroy,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
+{
+	struct tda998x_priv *priv = data;
+	u8 offset, segptr;
+	int ret, i;
+
+	offset = (blk & 1) ? 128 : 0;
+	segptr = blk / 2;
+
+	reg_write(priv, REG_DDC_ADDR, 0xa0);
+	reg_write(priv, REG_DDC_OFFS, offset);
+	reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
+	reg_write(priv, REG_DDC_SEGM, segptr);
+
+	/* enable reading EDID: */
+	priv->wq_edid_wait = 1;
+	reg_write(priv, REG_EDID_CTRL, 0x1);
+
+	/* flag must be cleared by sw: */
+	reg_write(priv, REG_EDID_CTRL, 0x0);
+
+	/* wait for block read to complete: */
+	if (priv->hdmi->irq) {
+		i = wait_event_timeout(priv->wq_edid,
+					!priv->wq_edid_wait,
+					msecs_to_jiffies(100));
+		if (i < 0) {
+			dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i);
+			return i;
+		}
+	} else {
+		for (i = 100; i > 0; i--) {
+			msleep(1);
+			ret = reg_read(priv, REG_INT_FLAGS_2);
+			if (ret < 0)
+				return ret;
+			if (ret & INT_FLAGS_2_EDID_BLK_RD)
+				break;
+		}
+	}
+
+	if (i == 0) {
+		dev_err(&priv->hdmi->dev, "read edid timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	ret = reg_read_range(priv, REG_EDID_DATA_0, buf, length);
+	if (ret != length) {
+		dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n",
+			blk, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int tda998x_connector_get_modes(struct drm_connector *connector)
+{
+	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+	struct edid *edid;
+	int n;
+
+	/*
+	 * If we get killed while waiting for the HPD timeout, return
+	 * no modes found: we are not in a restartable path, so we
+	 * can't handle signals gracefully.
+	 */
+	if (tda998x_edid_delay_wait(priv))
+		return 0;
+
+	if (priv->rev == TDA19988)
+		reg_clear(priv, REG_TX4, TX4_PD_RAM);
+
+	edid = drm_do_get_edid(connector, read_edid_block, priv);
+
+	if (priv->rev == TDA19988)
+		reg_set(priv, REG_TX4, TX4_PD_RAM);
+
+	if (!edid) {
+		dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
+		return 0;
+	}
+
+	drm_mode_connector_update_edid_property(connector, edid);
+	n = drm_add_edid_modes(connector, edid);
+	drm_edid_to_eld(connector, edid);
+
+	kfree(edid);
+
+	return n;
 }
 
 static int tda998x_connector_mode_valid(struct drm_connector *connector,
@@ -888,6 +1130,80 @@ static int tda998x_connector_mode_valid(
 	return MODE_OK;
 }
 
+static struct drm_encoder *
+tda998x_connector_best_encoder(struct drm_connector *connector)
+{
+	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
+
+	return &priv->encoder;
+}
+
+static
+const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
+	.get_modes = tda998x_connector_get_modes,
+	.mode_valid = tda998x_connector_mode_valid,
+	.best_encoder = tda998x_connector_best_encoder,
+};
+
+static int tda998x_connector_init(struct tda998x_priv *priv,
+				  struct drm_device *drm)
+{
+	struct drm_connector *connector = &priv->connector;
+	int ret;
+
+	connector->interlace_allowed = 1;
+
+	if (priv->hdmi->irq)
+		connector->polled = DRM_CONNECTOR_POLL_HPD;
+	else
+		connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+			DRM_CONNECTOR_POLL_DISCONNECT;
+
+	drm_connector_helper_add(connector, &tda998x_connector_helper_funcs);
+	ret = drm_connector_init(drm, connector, &tda998x_connector_funcs,
+				 DRM_MODE_CONNECTOR_HDMIA);
+	if (ret)
+		return ret;
+
+	drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
+
+	return 0;
+}
+
+/* DRM encoder functions */
+
+static void tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct tda998x_priv *priv = enc_to_tda998x_priv(encoder);
+	bool on;
+
+	/* we only care about on or off: */
+	on = mode == DRM_MODE_DPMS_ON;
+
+	if (on == priv->is_on)
+		return;
+
+	if (on) {
+		/* enable video ports, audio will be enabled later */
+		reg_write(priv, REG_ENA_VP_0, 0xff);
+		reg_write(priv, REG_ENA_VP_1, 0xff);
+		reg_write(priv, REG_ENA_VP_2, 0xff);
+		/* set muxing after enabling ports: */
+		reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
+		reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
+		reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
+
+		priv->is_on = true;
+	} else {
+		/* disable video ports */
+		reg_write(priv, REG_ENA_VP_0, 0x00);
+		reg_write(priv, REG_ENA_VP_1, 0x00);
+		reg_write(priv, REG_ENA_VP_2, 0x00);
+
+		priv->is_on = false;
+	}
+}
+
 static void
 tda998x_encoder_mode_set(struct drm_encoder *encoder,
 			 struct drm_display_mode *mode,
@@ -971,6 +1287,8 @@ tda998x_encoder_mode_set(struct drm_enco
 			div = 3;
 	}
 
+	mutex_lock(&priv->audio_mutex);
+
 	/* mute the audio FIFO: */
 	reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
 
@@ -982,6 +1300,7 @@ tda998x_encoder_mode_set(struct drm_enco
 	/* no pre-filter or interpolator: */
 	reg_write(priv, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
 			HVF_CNTRL_0_INTPOL(0));
+	reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_PREFILT);
 	reg_write(priv, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
 	reg_write(priv, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
 			VIP_CNTRL_4_BLC(0));
@@ -1004,6 +1323,7 @@ tda998x_encoder_mode_set(struct drm_enco
 	/* set color matrix bypass flag: */
 	reg_write(priv, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP |
 				MAT_CONTRL_MAT_SC(1));
+	reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_CSC);
 
 	/* set BIAS tmds value: */
 	reg_write(priv, REG_ANA_GENERAL, 0x09);
@@ -1064,8 +1384,22 @@ tda998x_encoder_mode_set(struct drm_enco
 	/* must be last register set: */
 	reg_write(priv, REG_TBG_CNTRL_0, 0);
 
-	/* Only setup the info frames if the sink is HDMI */
-	if (priv->is_hdmi_sink) {
+	priv->tmds_clock = adjusted_mode->clock;
+
+	/* CEA-861B section 6 says that:
+	 * CEA version 1 (CEA-861) has no support for infoframes.
+	 * CEA version 2 (CEA-861A) supports version 1 AVI infoframes,
+	 * and optional basic audio.
+	 * CEA version 3 (CEA-861B) supports version 1 and 2 AVI infoframes,
+	 * and optional digital audio, with audio infoframes.
+	 *
+	 * Since we only support generation of version 2 AVI infoframes,
+	 * ignore CEA version 2 and below (iow, behave as if we're a
+	 * CEA-861 source.)
+	 */
+	priv->supports_infoframes = priv->connector.display_info.cea_rev >= 3;
+
+	if (priv->supports_infoframes) {
 		/* We need to turn HDMI HDCP stuff on to get audio through */
 		reg &= ~TBG_CNTRL_1_DWIN_DIS;
 		reg_write(priv, REG_TBG_CNTRL_1, reg);
@@ -1074,127 +1408,12 @@ tda998x_encoder_mode_set(struct drm_enco
 
 		tda998x_write_avi(priv, adjusted_mode);
 
-		if (priv->audio_params.format != AFMT_UNUSED) {
-			mutex_lock(&priv->audio_mutex);
-			tda998x_configure_audio(priv,
-						&priv->audio_params,
-						adjusted_mode->clock);
-			mutex_unlock(&priv->audio_mutex);
-		}
-	}
-}
-
-static enum drm_connector_status
-tda998x_connector_detect(struct drm_connector *connector, bool force)
-{
-	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
-	u8 val = cec_read(priv, REG_CEC_RXSHPDLEV);
-
-	return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
-			connector_status_disconnected;
-}
-
-static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
-{
-	struct tda998x_priv *priv = data;
-	u8 offset, segptr;
-	int ret, i;
-
-	offset = (blk & 1) ? 128 : 0;
-	segptr = blk / 2;
-
-	reg_write(priv, REG_DDC_ADDR, 0xa0);
-	reg_write(priv, REG_DDC_OFFS, offset);
-	reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
-	reg_write(priv, REG_DDC_SEGM, segptr);
-
-	/* enable reading EDID: */
-	priv->wq_edid_wait = 1;
-	reg_write(priv, REG_EDID_CTRL, 0x1);
-
-	/* flag must be cleared by sw: */
-	reg_write(priv, REG_EDID_CTRL, 0x0);
-
-	/* wait for block read to complete: */
-	if (priv->hdmi->irq) {
-		i = wait_event_timeout(priv->wq_edid,
-					!priv->wq_edid_wait,
-					msecs_to_jiffies(100));
-		if (i < 0) {
-			dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i);
-			return i;
-		}
-	} else {
-		for (i = 100; i > 0; i--) {
-			msleep(1);
-			ret = reg_read(priv, REG_INT_FLAGS_2);
-			if (ret < 0)
-				return ret;
-			if (ret & INT_FLAGS_2_EDID_BLK_RD)
-				break;
-		}
-	}
-
-	if (i == 0) {
-		dev_err(&priv->hdmi->dev, "read edid timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	ret = reg_read_range(priv, REG_EDID_DATA_0, buf, length);
-	if (ret != length) {
-		dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n",
-			blk, ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int tda998x_connector_get_modes(struct drm_connector *connector)
-{
-	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
-	struct edid *edid;
-	int n;
-
-	/*
-	 * If we get killed while waiting for the HPD timeout, return
-	 * no modes found: we are not in a restartable path, so we
-	 * can't handle signals gracefully.
-	 */
-	if (tda998x_edid_delay_wait(priv))
-		return 0;
-
-	if (priv->rev == TDA19988)
-		reg_clear(priv, REG_TX4, TX4_PD_RAM);
-
-	edid = drm_do_get_edid(connector, read_edid_block, priv);
-
-	if (priv->rev == TDA19988)
-		reg_set(priv, REG_TX4, TX4_PD_RAM);
-
-	if (!edid) {
-		dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
-		return 0;
+		if (priv->audio_params.format != AFMT_UNUSED &&
+		    priv->sink_has_audio)
+			tda998x_configure_audio(priv, &priv->audio_params);
 	}
 
-	drm_mode_connector_update_edid_property(connector, edid);
-	n = drm_add_edid_modes(connector, edid);
-	priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
-	drm_edid_to_eld(connector, edid);
-
-	kfree(edid);
-
-	return n;
-}
-
-static void tda998x_encoder_set_polling(struct tda998x_priv *priv,
-					struct drm_connector *connector)
-{
-	if (priv->hdmi->irq)
-		connector->polled = DRM_CONNECTOR_POLL_HPD;
-	else
-		connector->polled = DRM_CONNECTOR_POLL_CONNECT |
-			DRM_CONNECTOR_POLL_DISCONNECT;
+	mutex_unlock(&priv->audio_mutex);
 }
 
 static void tda998x_destroy(struct tda998x_priv *priv)
@@ -1215,145 +1434,6 @@ static void tda998x_destroy(struct tda99
 	i2c_unregister_device(priv->cec);
 }
 
-static int tda998x_audio_hw_params(struct device *dev, void *data,
-				   struct hdmi_codec_daifmt *daifmt,
-				   struct hdmi_codec_params *params)
-{
-	struct tda998x_priv *priv = dev_get_drvdata(dev);
-	int i, ret;
-	struct tda998x_audio_params audio = {
-		.sample_width = params->sample_width,
-		.sample_rate = params->sample_rate,
-		.cea = params->cea,
-	};
-
-	if (!priv->encoder.crtc)
-		return -ENODEV;
-
-	memcpy(audio.status, params->iec.status,
-	       min(sizeof(audio.status), sizeof(params->iec.status)));
-
-	switch (daifmt->fmt) {
-	case HDMI_I2S:
-		if (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
-		    daifmt->bit_clk_master || daifmt->frame_clk_master) {
-			dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
-				daifmt->bit_clk_inv, daifmt->frame_clk_inv,
-				daifmt->bit_clk_master,
-				daifmt->frame_clk_master);
-			return -EINVAL;
-		}
-		for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
-			if (priv->audio_port[i].format == AFMT_I2S)
-				audio.config = priv->audio_port[i].config;
-		audio.format = AFMT_I2S;
-		break;
-	case HDMI_SPDIF:
-		for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++)
-			if (priv->audio_port[i].format == AFMT_SPDIF)
-				audio.config = priv->audio_port[i].config;
-		audio.format = AFMT_SPDIF;
-		break;
-	default:
-		dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
-		return -EINVAL;
-	}
-
-	if (audio.config == 0) {
-		dev_err(dev, "%s: No audio configutation found\n", __func__);
-		return -EINVAL;
-	}
-
-	mutex_lock(&priv->audio_mutex);
-	ret = tda998x_configure_audio(priv,
-				      &audio,
-				      priv->encoder.crtc->hwmode.clock);
-
-	if (ret == 0)
-		priv->audio_params = audio;
-	mutex_unlock(&priv->audio_mutex);
-
-	return ret;
-}
-
-static void tda998x_audio_shutdown(struct device *dev, void *data)
-{
-	struct tda998x_priv *priv = dev_get_drvdata(dev);
-
-	mutex_lock(&priv->audio_mutex);
-
-	reg_write(priv, REG_ENA_AP, 0);
-
-	priv->audio_params.format = AFMT_UNUSED;
-
-	mutex_unlock(&priv->audio_mutex);
-}
-
-int tda998x_audio_digital_mute(struct device *dev, void *data, bool enable)
-{
-	struct tda998x_priv *priv = dev_get_drvdata(dev);
-
-	mutex_lock(&priv->audio_mutex);
-
-	tda998x_audio_mute(priv, enable);
-
-	mutex_unlock(&priv->audio_mutex);
-	return 0;
-}
-
-static int tda998x_audio_get_eld(struct device *dev, void *data,
-				 uint8_t *buf, size_t len)
-{
-	struct tda998x_priv *priv = dev_get_drvdata(dev);
-	struct drm_mode_config *config = &priv->encoder.dev->mode_config;
-	struct drm_connector *connector;
-	int ret = -ENODEV;
-
-	mutex_lock(&config->mutex);
-	list_for_each_entry(connector, &config->connector_list, head) {
-		if (&priv->encoder == connector->encoder) {
-			memcpy(buf, connector->eld,
-			       min(sizeof(connector->eld), len));
-			ret = 0;
-		}
-	}
-	mutex_unlock(&config->mutex);
-
-	return ret;
-}
-
-static const struct hdmi_codec_ops audio_codec_ops = {
-	.hw_params = tda998x_audio_hw_params,
-	.audio_shutdown = tda998x_audio_shutdown,
-	.digital_mute = tda998x_audio_digital_mute,
-	.get_eld = tda998x_audio_get_eld,
-};
-
-static int tda998x_audio_codec_init(struct tda998x_priv *priv,
-				    struct device *dev)
-{
-	struct hdmi_codec_pdata codec_data = {
-		.ops = &audio_codec_ops,
-		.max_i2s_channels = 2,
-	};
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(priv->audio_port); i++) {
-		if (priv->audio_port[i].format == AFMT_I2S &&
-		    priv->audio_port[i].config != 0)
-			codec_data.i2s = 1;
-		if (priv->audio_port[i].format == AFMT_SPDIF &&
-		    priv->audio_port[i].config != 0)
-			codec_data.spdif = 1;
-	}
-
-	priv->audio_pdev = platform_device_register_data(
-		dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
-		&codec_data, sizeof(codec_data));
-
-	return PTR_ERR_OR_ZERO(priv->audio_pdev);
-}
-
 /* I2C driver functions */
 
 static int tda998x_get_audio_ports(struct tda998x_priv *priv,
@@ -1403,22 +1483,21 @@ static int tda998x_create(struct i2c_cli
 	struct device_node *np = client->dev.of_node;
 	u32 video;
 	int rev_lo, rev_hi, ret;
-	unsigned short cec_addr;
+
+	mutex_init(&priv->audio_mutex); /* Protect access from audio thread */
 
 	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
 	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
 	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
 
+	/* CEC I2C address bound to TDA998x I2C addr by configuration pins */
+	priv->cec_addr = 0x34 + (client->addr & 0x03);
 	priv->current_page = 0xff;
 	priv->hdmi = client;
-	/* CEC I2C address bound to TDA998x I2C addr by configuration pins */
-	cec_addr = 0x34 + (client->addr & 0x03);
-	priv->cec = i2c_new_dummy(client->adapter, cec_addr);
+	priv->cec = i2c_new_dummy(client->adapter, priv->cec_addr);
 	if (!priv->cec)
 		return -ENODEV;
 
-	priv->dpms = DRM_MODE_DPMS_OFF;
-
 	mutex_init(&priv->mutex);	/* protect the page access */
 	init_waitqueue_head(&priv->edid_delay_waitq);
 	setup_timer(&priv->edid_delay_timer, tda998x_edid_delay_done,
@@ -1478,7 +1557,7 @@ static int tda998x_create(struct i2c_cli
 
 	/* initialize the optional IRQ */
 	if (client->irq) {
-		int irqf_trigger;
+		unsigned long irq_flags;
 
 		/* init read EDID waitqueue and HDP work */
 		init_waitqueue_head(&priv->wq_edid);
@@ -1488,11 +1567,11 @@ static int tda998x_create(struct i2c_cli
 		reg_read(priv, REG_INT_FLAGS_1);
 		reg_read(priv, REG_INT_FLAGS_2);
 
-		irqf_trigger =
+		irq_flags =
 			irqd_get_trigger_type(irq_get_irq_data(client->irq));
+		irq_flags |= IRQF_SHARED | IRQF_ONESHOT;
 		ret = request_threaded_irq(client->irq, NULL,
-					   tda998x_irq_thread,
-					   irqf_trigger | IRQF_ONESHOT,
+					   tda998x_irq_thread, irq_flags,
 					   "tda998x", priv);
 		if (ret) {
 			dev_err(&client->dev,
@@ -1519,8 +1598,6 @@ static int tda998x_create(struct i2c_cli
 		priv->vip_cntrl_2 = video;
 	}
 
-	mutex_init(&priv->audio_mutex); /* Protect access from audio thread */
-
 	ret = tda998x_get_audio_ports(priv, np);
 	if (ret)
 		goto fail;
@@ -1567,45 +1644,25 @@ static const struct drm_encoder_funcs td
 	.destroy = tda998x_encoder_destroy,
 };
 
-static struct drm_encoder *
-tda998x_connector_best_encoder(struct drm_connector *connector)
-{
-	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
-
-	return &priv->encoder;
-}
-
-static
-const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
-	.get_modes = tda998x_connector_get_modes,
-	.mode_valid = tda998x_connector_mode_valid,
-	.best_encoder = tda998x_connector_best_encoder,
-};
-
-static void tda998x_connector_destroy(struct drm_connector *connector)
+static void tda998x_set_config(struct tda998x_priv *priv,
+			       const struct tda998x_encoder_params *p)
 {
-	drm_connector_unregister(connector);
-	drm_connector_cleanup(connector);
-}
+	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
+			    (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
+			    VIP_CNTRL_0_SWAP_B(p->swap_b) |
+			    (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
+	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
+			    (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
+			    VIP_CNTRL_1_SWAP_D(p->swap_d) |
+			    (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
+	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
+			    (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
+			    VIP_CNTRL_2_SWAP_F(p->swap_f) |
+			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
 
-static int tda998x_connector_dpms(struct drm_connector *connector, int mode)
-{
-	if (drm_core_check_feature(connector->dev, DRIVER_ATOMIC))
-		return drm_atomic_helper_connector_dpms(connector, mode);
-	else
-		return drm_helper_connector_dpms(connector, mode);
+	priv->audio_params = p->audio_params;
 }
 
-static const struct drm_connector_funcs tda998x_connector_funcs = {
-	.dpms = tda998x_connector_dpms,
-	.reset = drm_atomic_helper_connector_reset,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = tda998x_connector_detect,
-	.destroy = tda998x_connector_destroy,
-	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
 static int tda998x_bind(struct device *dev, struct device *master, void *data)
 {
 	struct tda998x_encoder_params *params = dev->platform_data;
@@ -1630,7 +1687,6 @@ static int tda998x_bind(struct device *d
 		crtcs = 1 << 0;
 	}
 
-	priv->connector.interlace_allowed = 1;
 	priv->encoder.possible_crtcs = crtcs;
 
 	ret = tda998x_create(client, priv);
@@ -1638,9 +1694,7 @@ static int tda998x_bind(struct device *d
 		return ret;
 
 	if (!dev->of_node && params)
-		tda998x_encoder_set_config(priv, params);
-
-	tda998x_encoder_set_polling(priv, &priv->connector);
+		tda998x_set_config(priv, params);
 
 	drm_encoder_helper_add(&priv->encoder, &tda998x_encoder_helper_funcs);
 	ret = drm_encoder_init(drm, &priv->encoder, &tda998x_encoder_funcs,
@@ -1648,24 +1702,12 @@ static int tda998x_bind(struct device *d
 	if (ret)
 		goto err_encoder;
 
-	drm_connector_helper_add(&priv->connector,
-				 &tda998x_connector_helper_funcs);
-	ret = drm_connector_init(drm, &priv->connector,
-				 &tda998x_connector_funcs,
-				 DRM_MODE_CONNECTOR_HDMIA);
+	ret = tda998x_connector_init(priv, drm);
 	if (ret)
 		goto err_connector;
 
-	ret = drm_connector_register(&priv->connector);
-	if (ret)
-		goto err_sysfs;
-
-	drm_mode_connector_attach_encoder(&priv->connector, &priv->encoder);
-
 	return 0;
 
-err_sysfs:
-	drm_connector_cleanup(&priv->connector);
 err_connector:
 	drm_encoder_cleanup(&priv->encoder);
 err_encoder:
@@ -1678,7 +1720,6 @@ static void tda998x_unbind(struct device
 {
 	struct tda998x_priv *priv = dev_get_drvdata(dev);
 
-	drm_connector_unregister(&priv->connector);
 	drm_connector_cleanup(&priv->connector);
 	drm_encoder_cleanup(&priv->encoder);
 	tda998x_destroy(priv);
@@ -1692,6 +1733,10 @@ static const struct component_ops tda998
 static int
 tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_warn(&client->dev, "adapter does not support I2C\n");
+		return -EIO;
+	}
 	return component_add(&client->dev, &tda998x_ops);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i810/i810_dma.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i810/i810_dma.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i810/i810_dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i810/i810_dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,9 +113,7 @@ static const struct file_operations i810
 	.release = drm_release,
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = i810_mmap_buffers,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i810/i810_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i810/i810_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i810/i810_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i810/i810_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,9 +49,7 @@ static const struct file_operations i810
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = drm_legacy_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/aperture_gm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/aperture_gm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/aperture_gm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/aperture_gm.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,370 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Dexuan Cui
+ *
+ * Contributors:
+ *    Pei Zhang <pei.zhang@intel.com>
+ *    Min He <min.he@intel.com>
+ *    Niu Bing <bing.niu@intel.com>
+ *    Yulei Zhang <yulei.zhang@intel.com>
+ *    Zhenyu Wang <zhenyuw@linux.intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	u32 alloc_flag, search_flag;
+	u64 start, end, size;
+	struct drm_mm_node *node;
+	int retried = 0;
+	int ret;
+
+	if (high_gm) {
+		search_flag = DRM_MM_SEARCH_BELOW;
+		alloc_flag = DRM_MM_CREATE_TOP;
+		node = &vgpu->gm.high_gm_node;
+		size = vgpu_hidden_sz(vgpu);
+		start = gvt_hidden_gmadr_base(gvt);
+		end = gvt_hidden_gmadr_end(gvt);
+	} else {
+		search_flag = DRM_MM_SEARCH_DEFAULT;
+		alloc_flag = DRM_MM_CREATE_DEFAULT;
+		node = &vgpu->gm.low_gm_node;
+		size = vgpu_aperture_sz(vgpu);
+		start = gvt_aperture_gmadr_base(gvt);
+		end = gvt_aperture_gmadr_end(gvt);
+	}
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+search_again:
+	ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm,
+						  node, size, 4096, 0,
+						  start, end, search_flag,
+						  alloc_flag);
+	if (ret) {
+		ret = i915_gem_evict_something(&dev_priv->ggtt.base,
+					       size, 4096, 0, start, end, 0);
+		if (ret == 0 && ++retried < 3)
+			goto search_again;
+
+		gvt_err("fail to alloc %s gm space from host, retried %d\n",
+				high_gm ? "high" : "low", retried);
+	}
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+	return ret;
+}
+
+static int alloc_vgpu_gm(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	int ret;
+
+	ret = alloc_gm(vgpu, false);
+	if (ret)
+		return ret;
+
+	ret = alloc_gm(vgpu, true);
+	if (ret)
+		goto out_free_aperture;
+
+	gvt_dbg_core("vgpu%d: alloc low GM start %llx size %llx\n", vgpu->id,
+		     vgpu_aperture_offset(vgpu), vgpu_aperture_sz(vgpu));
+
+	gvt_dbg_core("vgpu%d: alloc high GM start %llx size %llx\n", vgpu->id,
+		     vgpu_hidden_offset(vgpu), vgpu_hidden_sz(vgpu));
+
+	return 0;
+out_free_aperture:
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	drm_mm_remove_node(&vgpu->gm.low_gm_node);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+	return ret;
+}
+
+static void free_vgpu_gm(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	drm_mm_remove_node(&vgpu->gm.low_gm_node);
+	drm_mm_remove_node(&vgpu->gm.high_gm_node);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+/**
+ * intel_vgpu_write_fence - write fence registers owned by a vGPU
+ * @vgpu: vGPU instance
+ * @fence: vGPU fence register number
+ * @value: Fence register value to be written
+ *
+ * This function is used to write fence registers owned by a vGPU. The vGPU
+ * fence register number will be translated into HW fence register number.
+ *
+ */
+void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
+		u32 fence, u64 value)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct drm_i915_fence_reg *reg;
+	i915_reg_t fence_reg_lo, fence_reg_hi;
+
+	assert_rpm_wakelock_held(dev_priv);
+
+	if (WARN_ON(fence > vgpu_fence_sz(vgpu)))
+		return;
+
+	reg = vgpu->fence.regs[fence];
+	if (WARN_ON(!reg))
+		return;
+
+	fence_reg_lo = FENCE_REG_GEN6_LO(reg->id);
+	fence_reg_hi = FENCE_REG_GEN6_HI(reg->id);
+
+	I915_WRITE(fence_reg_lo, 0);
+	POSTING_READ(fence_reg_lo);
+
+	I915_WRITE(fence_reg_hi, upper_32_bits(value));
+	I915_WRITE(fence_reg_lo, lower_32_bits(value));
+	POSTING_READ(fence_reg_lo);
+}
+
+static void _clear_vgpu_fence(struct intel_vgpu *vgpu)
+{
+	int i;
+
+	for (i = 0; i < vgpu_fence_sz(vgpu); i++)
+		intel_vgpu_write_fence(vgpu, i, 0);
+}
+
+static void free_vgpu_fence(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct drm_i915_fence_reg *reg;
+	u32 i;
+
+	if (WARN_ON(!vgpu_fence_sz(vgpu)))
+		return;
+
+	intel_runtime_pm_get(dev_priv);
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	_clear_vgpu_fence(vgpu);
+	for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
+		reg = vgpu->fence.regs[i];
+		list_add_tail(&reg->link,
+			      &dev_priv->mm.fence_list);
+	}
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+
+	intel_runtime_pm_put(dev_priv);
+}
+
+static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct drm_i915_fence_reg *reg;
+	int i;
+	struct list_head *pos, *q;
+
+	intel_runtime_pm_get(dev_priv);
+
+	/* Request fences from host */
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	i = 0;
+	list_for_each_safe(pos, q, &dev_priv->mm.fence_list) {
+		reg = list_entry(pos, struct drm_i915_fence_reg, link);
+		if (reg->pin_count || reg->vma)
+			continue;
+		list_del(pos);
+		vgpu->fence.regs[i] = reg;
+		if (++i == vgpu_fence_sz(vgpu))
+			break;
+	}
+	if (i != vgpu_fence_sz(vgpu))
+		goto out_free_fence;
+
+	_clear_vgpu_fence(vgpu);
+
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+	intel_runtime_pm_put(dev_priv);
+	return 0;
+out_free_fence:
+	/* Return fences to host, if fail */
+	for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
+		reg = vgpu->fence.regs[i];
+		if (!reg)
+			continue;
+		list_add_tail(&reg->link,
+			      &dev_priv->mm.fence_list);
+	}
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+	intel_runtime_pm_put(dev_priv);
+	return -ENOSPC;
+}
+
+static void free_resource(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+
+	gvt->gm.vgpu_allocated_low_gm_size -= vgpu_aperture_sz(vgpu);
+	gvt->gm.vgpu_allocated_high_gm_size -= vgpu_hidden_sz(vgpu);
+	gvt->fence.vgpu_allocated_fence_num -= vgpu_fence_sz(vgpu);
+}
+
+static int alloc_resource(struct intel_vgpu *vgpu,
+		struct intel_vgpu_creation_params *param)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	unsigned long request, avail, max, taken;
+	const char *item;
+
+	if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) {
+		gvt_err("Invalid vGPU creation params\n");
+		return -EINVAL;
+	}
+
+	item = "low GM space";
+	max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;
+	taken = gvt->gm.vgpu_allocated_low_gm_size;
+	avail = max - taken;
+	request = MB_TO_BYTES(param->low_gm_sz);
+
+	if (request > avail)
+		goto no_enough_resource;
+
+	vgpu_aperture_sz(vgpu) = request;
+
+	item = "high GM space";
+	max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
+	taken = gvt->gm.vgpu_allocated_high_gm_size;
+	avail = max - taken;
+	request = MB_TO_BYTES(param->high_gm_sz);
+
+	if (request > avail)
+		goto no_enough_resource;
+
+	vgpu_hidden_sz(vgpu) = request;
+
+	item = "fence";
+	max = gvt_fence_sz(gvt) - HOST_FENCE;
+	taken = gvt->fence.vgpu_allocated_fence_num;
+	avail = max - taken;
+	request = param->fence_sz;
+
+	if (request > avail)
+		goto no_enough_resource;
+
+	vgpu_fence_sz(vgpu) = request;
+
+	gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz);
+	gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz);
+	gvt->fence.vgpu_allocated_fence_num += param->fence_sz;
+	return 0;
+
+no_enough_resource:
+	gvt_err("vgpu%d: fail to allocate resource %s\n", vgpu->id, item);
+	gvt_err("vgpu%d: request %luMB avail %luMB max %luMB taken %luMB\n",
+		vgpu->id, BYTES_TO_MB(request), BYTES_TO_MB(avail),
+		BYTES_TO_MB(max), BYTES_TO_MB(taken));
+	return -ENOSPC;
+}
+
+/**
+ * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU
+ * @vgpu: a vGPU
+ *
+ * This function is used to free the HW resource owned by a vGPU.
+ *
+ */
+void intel_vgpu_free_resource(struct intel_vgpu *vgpu)
+{
+	free_vgpu_gm(vgpu);
+	free_vgpu_fence(vgpu);
+	free_resource(vgpu);
+}
+
+/**
+ * intel_vgpu_reset_resource - reset resource state owned by a vGPU
+ * @vgpu: a vGPU
+ *
+ * This function is used to reset resource state owned by a vGPU.
+ *
+ */
+void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	intel_runtime_pm_get(dev_priv);
+	_clear_vgpu_fence(vgpu);
+	intel_runtime_pm_put(dev_priv);
+}
+
+/**
+ * intel_alloc_vgpu_resource - allocate HW resource for a vGPU
+ * @vgpu: vGPU
+ * @param: vGPU creation params
+ *
+ * This function is used to allocate HW resource for a vGPU. User specifies
+ * the resource configuration through the creation params.
+ *
+ * Returns:
+ * zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
+		struct intel_vgpu_creation_params *param)
+{
+	int ret;
+
+	ret = alloc_resource(vgpu, param);
+	if (ret)
+		return ret;
+
+	ret = alloc_vgpu_gm(vgpu);
+	if (ret)
+		goto out_free_resource;
+
+	ret = alloc_vgpu_fence(vgpu);
+	if (ret)
+		goto out_free_vgpu_gm;
+
+	return 0;
+
+out_free_vgpu_gm:
+	free_vgpu_gm(vgpu);
+out_free_resource:
+	free_resource(vgpu);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/cfg_space.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/cfg_space.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/cfg_space.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/cfg_space.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,358 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eddie Dong <eddie.dong@intel.com>
+ *    Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+enum {
+	INTEL_GVT_PCI_BAR_GTTMMIO = 0,
+	INTEL_GVT_PCI_BAR_APERTURE,
+	INTEL_GVT_PCI_BAR_PIO,
+	INTEL_GVT_PCI_BAR_MAX,
+};
+
+/**
+ * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
+	void *p_data, unsigned int bytes)
+{
+	if (WARN_ON(bytes > 4))
+		return -EINVAL;
+
+	if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ))
+		return -EINVAL;
+
+	memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes);
+	return 0;
+}
+
+static int map_aperture(struct intel_vgpu *vgpu, bool map)
+{
+	u64 first_gfn, first_mfn;
+	u64 val;
+	int ret;
+
+	if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked)
+		return 0;
+
+	val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2];
+	if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+		val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
+	else
+		val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2);
+
+	first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT;
+	first_mfn = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+
+	ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn,
+						  first_mfn,
+						  vgpu_aperture_sz(vgpu) >>
+						  PAGE_SHIFT, map);
+	if (ret)
+		return ret;
+
+	vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map;
+	return 0;
+}
+
+static int trap_gttmmio(struct intel_vgpu *vgpu, bool trap)
+{
+	u64 start, end;
+	u64 val;
+	int ret;
+
+	if (trap == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked)
+		return 0;
+
+	val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_0];
+	if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+		start = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0);
+	else
+		start = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0);
+
+	start &= ~GENMASK(3, 0);
+	end = start + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size - 1;
+
+	ret = intel_gvt_hypervisor_set_trap_area(vgpu, start, end, trap);
+	if (ret)
+		return ret;
+
+	vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap;
+	return 0;
+}
+
+static int emulate_pci_command_write(struct intel_vgpu *vgpu,
+	unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u8 old = vgpu_cfg_space(vgpu)[offset];
+	u8 new = *(u8 *)p_data;
+	u8 changed = old ^ new;
+	int ret;
+
+	memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
+	if (!(changed & PCI_COMMAND_MEMORY))
+		return 0;
+
+	if (old & PCI_COMMAND_MEMORY) {
+		ret = trap_gttmmio(vgpu, false);
+		if (ret)
+			return ret;
+		ret = map_aperture(vgpu, false);
+		if (ret)
+			return ret;
+	} else {
+		ret = trap_gttmmio(vgpu, true);
+		if (ret)
+			return ret;
+		ret = map_aperture(vgpu, true);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset,
+	void *p_data, unsigned int bytes)
+{
+	unsigned int bar_index =
+		(rounddown(offset, 8) % PCI_BASE_ADDRESS_0) / 8;
+	u32 new = *(u32 *)(p_data);
+	bool lo = IS_ALIGNED(offset, 8);
+	u64 size;
+	int ret = 0;
+	bool mmio_enabled =
+		vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY;
+
+	if (WARN_ON(bar_index >= INTEL_GVT_PCI_BAR_MAX))
+		return -EINVAL;
+
+	if (new == 0xffffffff) {
+		/*
+		 * Power-up software can determine how much address
+		 * space the device requires by writing a value of
+		 * all 1's to the register and then reading the value
+		 * back. The device will return 0's in all don't-care
+		 * address bits.
+		 */
+		size = vgpu->cfg_space.bar[bar_index].size;
+		if (lo) {
+			new = rounddown(new, size);
+		} else {
+			u32 val = vgpu_cfg_space(vgpu)[rounddown(offset, 8)];
+			/* for 32bit mode bar it returns all-0 in upper 32
+			 * bit, for 64bit mode bar it will calculate the
+			 * size with lower 32bit and return the corresponding
+			 * value
+			 */
+			if (val & PCI_BASE_ADDRESS_MEM_TYPE_64)
+				new &= (~(size-1)) >> 32;
+			else
+				new = 0;
+		}
+		/*
+		 * Unmapp & untrap the BAR, since guest hasn't configured a
+		 * valid GPA
+		 */
+		switch (bar_index) {
+		case INTEL_GVT_PCI_BAR_GTTMMIO:
+			ret = trap_gttmmio(vgpu, false);
+			break;
+		case INTEL_GVT_PCI_BAR_APERTURE:
+			ret = map_aperture(vgpu, false);
+			break;
+		}
+		intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
+	} else {
+		/*
+		 * Unmapp & untrap the old BAR first, since guest has
+		 * re-configured the BAR
+		 */
+		switch (bar_index) {
+		case INTEL_GVT_PCI_BAR_GTTMMIO:
+			ret = trap_gttmmio(vgpu, false);
+			break;
+		case INTEL_GVT_PCI_BAR_APERTURE:
+			ret = map_aperture(vgpu, false);
+			break;
+		}
+		intel_vgpu_write_pci_bar(vgpu, offset, new, lo);
+		/* Track the new BAR */
+		if (mmio_enabled) {
+			switch (bar_index) {
+			case INTEL_GVT_PCI_BAR_GTTMMIO:
+				ret = trap_gttmmio(vgpu, true);
+				break;
+			case INTEL_GVT_PCI_BAR_APERTURE:
+				ret = map_aperture(vgpu, true);
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+/**
+ * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space write
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
+	void *p_data, unsigned int bytes)
+{
+	int ret;
+
+	if (WARN_ON(bytes > 4))
+		return -EINVAL;
+
+	if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ))
+		return -EINVAL;
+
+	/* First check if it's PCI_COMMAND */
+	if (IS_ALIGNED(offset, 2) && offset == PCI_COMMAND) {
+		if (WARN_ON(bytes > 2))
+			return -EINVAL;
+		return emulate_pci_command_write(vgpu, offset, p_data, bytes);
+	}
+
+	switch (rounddown(offset, 4)) {
+	case PCI_BASE_ADDRESS_0:
+	case PCI_BASE_ADDRESS_1:
+	case PCI_BASE_ADDRESS_2:
+	case PCI_BASE_ADDRESS_3:
+		if (WARN_ON(!IS_ALIGNED(offset, 4)))
+			return -EINVAL;
+		return emulate_pci_bar_write(vgpu, offset, p_data, bytes);
+
+	case INTEL_GVT_PCI_SWSCI:
+		if (WARN_ON(!IS_ALIGNED(offset, 4)))
+			return -EINVAL;
+		ret = intel_vgpu_emulate_opregion_request(vgpu, *(u32 *)p_data);
+		if (ret)
+			return ret;
+		break;
+
+	case INTEL_GVT_PCI_OPREGION:
+		if (WARN_ON(!IS_ALIGNED(offset, 4)))
+			return -EINVAL;
+		ret = intel_vgpu_init_opregion(vgpu, *(u32 *)p_data);
+		if (ret)
+			return ret;
+
+		memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
+		break;
+	default:
+		memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
+		break;
+	}
+	return 0;
+}
+
+/**
+ * intel_vgpu_init_cfg_space - init vGPU configuration space when create vGPU
+ *
+ * @vgpu: a vGPU
+ * @primary: is the vGPU presented as primary
+ *
+ */
+void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
+			       bool primary)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	const struct intel_gvt_device_info *info = &gvt->device_info;
+	u16 *gmch_ctl;
+	int i;
+
+	memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
+	       info->cfg_space_size);
+
+	if (!primary) {
+		vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
+			INTEL_GVT_PCI_CLASS_VGA_OTHER;
+		vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
+			INTEL_GVT_PCI_CLASS_VGA_OTHER;
+	}
+
+	/* Show guest that there isn't any stolen memory.*/
+	gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
+	*gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);
+
+	intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
+				 gvt_aperture_pa_base(gvt), true);
+
+	vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
+					     | PCI_COMMAND_MEMORY
+					     | PCI_COMMAND_MASTER);
+	/*
+	 * Clear the bar upper 32bit and let guest to assign the new value
+	 */
+	memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
+	memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
+	memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
+
+	for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {
+		vgpu->cfg_space.bar[i].size = pci_resource_len(
+					      gvt->dev_priv->drm.pdev, i * 2);
+		vgpu->cfg_space.bar[i].tracked = false;
+	}
+}
+
+/**
+ * intel_vgpu_reset_cfg_space - reset vGPU configuration space
+ *
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu)
+{
+	u8 cmd = vgpu_cfg_space(vgpu)[PCI_COMMAND];
+	bool primary = vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] !=
+				INTEL_GVT_PCI_CLASS_VGA_OTHER;
+
+	if (cmd & PCI_COMMAND_MEMORY) {
+		trap_gttmmio(vgpu, false);
+		map_aperture(vgpu, false);
+	}
+
+	/**
+	 * Currently we only do such reset when vGPU is not
+	 * owned by any VM, so we simply restore entire cfg
+	 * space to default value.
+	 */
+	intel_vgpu_init_cfg_space(vgpu, primary);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2827 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Yulei Zhang <yulei.zhang@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include <linux/slab.h>
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+#include "trace.h"
+
+#define INVALID_OP    (~0U)
+
+#define OP_LEN_MI           9
+#define OP_LEN_2D           10
+#define OP_LEN_3D_MEDIA     16
+#define OP_LEN_MFX_VC       16
+#define OP_LEN_VEBOX	    16
+
+#define CMD_TYPE(cmd)	(((cmd) >> 29) & 7)
+
+struct sub_op_bits {
+	int hi;
+	int low;
+};
+struct decode_info {
+	char *name;
+	int op_len;
+	int nr_sub_op;
+	struct sub_op_bits *sub_op;
+};
+
+#define   MAX_CMD_BUDGET			0x7fffffff
+#define   MI_WAIT_FOR_PLANE_C_FLIP_PENDING      (1<<15)
+#define   MI_WAIT_FOR_PLANE_B_FLIP_PENDING      (1<<9)
+#define   MI_WAIT_FOR_PLANE_A_FLIP_PENDING      (1<<1)
+
+#define   MI_WAIT_FOR_SPRITE_C_FLIP_PENDING      (1<<20)
+#define   MI_WAIT_FOR_SPRITE_B_FLIP_PENDING      (1<<10)
+#define   MI_WAIT_FOR_SPRITE_A_FLIP_PENDING      (1<<2)
+
+/* Render Command Map */
+
+/* MI_* command Opcode (28:23) */
+#define OP_MI_NOOP                          0x0
+#define OP_MI_SET_PREDICATE                 0x1  /* HSW+ */
+#define OP_MI_USER_INTERRUPT                0x2
+#define OP_MI_WAIT_FOR_EVENT                0x3
+#define OP_MI_FLUSH                         0x4
+#define OP_MI_ARB_CHECK                     0x5
+#define OP_MI_RS_CONTROL                    0x6  /* HSW+ */
+#define OP_MI_REPORT_HEAD                   0x7
+#define OP_MI_ARB_ON_OFF                    0x8
+#define OP_MI_URB_ATOMIC_ALLOC              0x9  /* HSW+ */
+#define OP_MI_BATCH_BUFFER_END              0xA
+#define OP_MI_SUSPEND_FLUSH                 0xB
+#define OP_MI_PREDICATE                     0xC  /* IVB+ */
+#define OP_MI_TOPOLOGY_FILTER               0xD  /* IVB+ */
+#define OP_MI_SET_APPID                     0xE  /* IVB+ */
+#define OP_MI_RS_CONTEXT                    0xF  /* HSW+ */
+#define OP_MI_LOAD_SCAN_LINES_INCL          0x12 /* HSW+ */
+#define OP_MI_DISPLAY_FLIP                  0x14
+#define OP_MI_SEMAPHORE_MBOX                0x16
+#define OP_MI_SET_CONTEXT                   0x18
+#define OP_MI_MATH                          0x1A
+#define OP_MI_URB_CLEAR                     0x19
+#define OP_MI_SEMAPHORE_SIGNAL		    0x1B  /* BDW+ */
+#define OP_MI_SEMAPHORE_WAIT		    0x1C  /* BDW+ */
+
+#define OP_MI_STORE_DATA_IMM                0x20
+#define OP_MI_STORE_DATA_INDEX              0x21
+#define OP_MI_LOAD_REGISTER_IMM             0x22
+#define OP_MI_UPDATE_GTT                    0x23
+#define OP_MI_STORE_REGISTER_MEM            0x24
+#define OP_MI_FLUSH_DW                      0x26
+#define OP_MI_CLFLUSH                       0x27
+#define OP_MI_REPORT_PERF_COUNT             0x28
+#define OP_MI_LOAD_REGISTER_MEM             0x29  /* HSW+ */
+#define OP_MI_LOAD_REGISTER_REG             0x2A  /* HSW+ */
+#define OP_MI_RS_STORE_DATA_IMM             0x2B  /* HSW+ */
+#define OP_MI_LOAD_URB_MEM                  0x2C  /* HSW+ */
+#define OP_MI_STORE_URM_MEM                 0x2D  /* HSW+ */
+#define OP_MI_2E			    0x2E  /* BDW+ */
+#define OP_MI_2F			    0x2F  /* BDW+ */
+#define OP_MI_BATCH_BUFFER_START            0x31
+
+/* Bit definition for dword 0 */
+#define _CMDBIT_BB_START_IN_PPGTT	(1UL << 8)
+
+#define OP_MI_CONDITIONAL_BATCH_BUFFER_END  0x36
+
+#define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2))
+#define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U))
+#define BATCH_BUFFER_ADR_SPACE_BIT(x)	(((x) >> 8) & 1U)
+#define BATCH_BUFFER_2ND_LEVEL_BIT(x)   ((x) >> 22 & 1U)
+
+/* 2D command: Opcode (28:22) */
+#define OP_2D(x)    ((2<<7) | x)
+
+#define OP_XY_SETUP_BLT                             OP_2D(0x1)
+#define OP_XY_SETUP_CLIP_BLT                        OP_2D(0x3)
+#define OP_XY_SETUP_MONO_PATTERN_SL_BLT             OP_2D(0x11)
+#define OP_XY_PIXEL_BLT                             OP_2D(0x24)
+#define OP_XY_SCANLINES_BLT                         OP_2D(0x25)
+#define OP_XY_TEXT_BLT                              OP_2D(0x26)
+#define OP_XY_TEXT_IMMEDIATE_BLT                    OP_2D(0x31)
+#define OP_XY_COLOR_BLT                             OP_2D(0x50)
+#define OP_XY_PAT_BLT                               OP_2D(0x51)
+#define OP_XY_MONO_PAT_BLT                          OP_2D(0x52)
+#define OP_XY_SRC_COPY_BLT                          OP_2D(0x53)
+#define OP_XY_MONO_SRC_COPY_BLT                     OP_2D(0x54)
+#define OP_XY_FULL_BLT                              OP_2D(0x55)
+#define OP_XY_FULL_MONO_SRC_BLT                     OP_2D(0x56)
+#define OP_XY_FULL_MONO_PATTERN_BLT                 OP_2D(0x57)
+#define OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT        OP_2D(0x58)
+#define OP_XY_MONO_PAT_FIXED_BLT                    OP_2D(0x59)
+#define OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT           OP_2D(0x71)
+#define OP_XY_PAT_BLT_IMMEDIATE                     OP_2D(0x72)
+#define OP_XY_SRC_COPY_CHROMA_BLT                   OP_2D(0x73)
+#define OP_XY_FULL_IMMEDIATE_PATTERN_BLT            OP_2D(0x74)
+#define OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT   OP_2D(0x75)
+#define OP_XY_PAT_CHROMA_BLT                        OP_2D(0x76)
+#define OP_XY_PAT_CHROMA_BLT_IMMEDIATE              OP_2D(0x77)
+
+/* 3D/Media Command: Pipeline Type(28:27) Opcode(26:24) Sub Opcode(23:16) */
+#define OP_3D_MEDIA(sub_type, opcode, sub_opcode) \
+	((3 << 13) | ((sub_type) << 11) | ((opcode) << 8) | (sub_opcode))
+
+#define OP_STATE_PREFETCH                       OP_3D_MEDIA(0x0, 0x0, 0x03)
+
+#define OP_STATE_BASE_ADDRESS                   OP_3D_MEDIA(0x0, 0x1, 0x01)
+#define OP_STATE_SIP                            OP_3D_MEDIA(0x0, 0x1, 0x02)
+#define OP_3D_MEDIA_0_1_4			OP_3D_MEDIA(0x0, 0x1, 0x04)
+
+#define OP_3DSTATE_VF_STATISTICS_GM45           OP_3D_MEDIA(0x1, 0x0, 0x0B)
+
+#define OP_PIPELINE_SELECT                      OP_3D_MEDIA(0x1, 0x1, 0x04)
+
+#define OP_MEDIA_VFE_STATE                      OP_3D_MEDIA(0x2, 0x0, 0x0)
+#define OP_MEDIA_CURBE_LOAD                     OP_3D_MEDIA(0x2, 0x0, 0x1)
+#define OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD      OP_3D_MEDIA(0x2, 0x0, 0x2)
+#define OP_MEDIA_GATEWAY_STATE                  OP_3D_MEDIA(0x2, 0x0, 0x3)
+#define OP_MEDIA_STATE_FLUSH                    OP_3D_MEDIA(0x2, 0x0, 0x4)
+
+#define OP_MEDIA_OBJECT                         OP_3D_MEDIA(0x2, 0x1, 0x0)
+#define OP_MEDIA_OBJECT_PRT                     OP_3D_MEDIA(0x2, 0x1, 0x2)
+#define OP_MEDIA_OBJECT_WALKER                  OP_3D_MEDIA(0x2, 0x1, 0x3)
+#define OP_GPGPU_WALKER                         OP_3D_MEDIA(0x2, 0x1, 0x5)
+
+#define OP_3DSTATE_CLEAR_PARAMS                 OP_3D_MEDIA(0x3, 0x0, 0x04) /* IVB+ */
+#define OP_3DSTATE_DEPTH_BUFFER                 OP_3D_MEDIA(0x3, 0x0, 0x05) /* IVB+ */
+#define OP_3DSTATE_STENCIL_BUFFER               OP_3D_MEDIA(0x3, 0x0, 0x06) /* IVB+ */
+#define OP_3DSTATE_HIER_DEPTH_BUFFER            OP_3D_MEDIA(0x3, 0x0, 0x07) /* IVB+ */
+#define OP_3DSTATE_VERTEX_BUFFERS               OP_3D_MEDIA(0x3, 0x0, 0x08)
+#define OP_3DSTATE_VERTEX_ELEMENTS              OP_3D_MEDIA(0x3, 0x0, 0x09)
+#define OP_3DSTATE_INDEX_BUFFER                 OP_3D_MEDIA(0x3, 0x0, 0x0A)
+#define OP_3DSTATE_VF_STATISTICS                OP_3D_MEDIA(0x3, 0x0, 0x0B)
+#define OP_3DSTATE_VF                           OP_3D_MEDIA(0x3, 0x0, 0x0C)  /* HSW+ */
+#define OP_3DSTATE_CC_STATE_POINTERS            OP_3D_MEDIA(0x3, 0x0, 0x0E)
+#define OP_3DSTATE_SCISSOR_STATE_POINTERS       OP_3D_MEDIA(0x3, 0x0, 0x0F)
+#define OP_3DSTATE_VS                           OP_3D_MEDIA(0x3, 0x0, 0x10)
+#define OP_3DSTATE_GS                           OP_3D_MEDIA(0x3, 0x0, 0x11)
+#define OP_3DSTATE_CLIP                         OP_3D_MEDIA(0x3, 0x0, 0x12)
+#define OP_3DSTATE_SF                           OP_3D_MEDIA(0x3, 0x0, 0x13)
+#define OP_3DSTATE_WM                           OP_3D_MEDIA(0x3, 0x0, 0x14)
+#define OP_3DSTATE_CONSTANT_VS                  OP_3D_MEDIA(0x3, 0x0, 0x15)
+#define OP_3DSTATE_CONSTANT_GS                  OP_3D_MEDIA(0x3, 0x0, 0x16)
+#define OP_3DSTATE_CONSTANT_PS                  OP_3D_MEDIA(0x3, 0x0, 0x17)
+#define OP_3DSTATE_SAMPLE_MASK                  OP_3D_MEDIA(0x3, 0x0, 0x18)
+#define OP_3DSTATE_CONSTANT_HS                  OP_3D_MEDIA(0x3, 0x0, 0x19) /* IVB+ */
+#define OP_3DSTATE_CONSTANT_DS                  OP_3D_MEDIA(0x3, 0x0, 0x1A) /* IVB+ */
+#define OP_3DSTATE_HS                           OP_3D_MEDIA(0x3, 0x0, 0x1B) /* IVB+ */
+#define OP_3DSTATE_TE                           OP_3D_MEDIA(0x3, 0x0, 0x1C) /* IVB+ */
+#define OP_3DSTATE_DS                           OP_3D_MEDIA(0x3, 0x0, 0x1D) /* IVB+ */
+#define OP_3DSTATE_STREAMOUT                    OP_3D_MEDIA(0x3, 0x0, 0x1E) /* IVB+ */
+#define OP_3DSTATE_SBE                          OP_3D_MEDIA(0x3, 0x0, 0x1F) /* IVB+ */
+#define OP_3DSTATE_PS                           OP_3D_MEDIA(0x3, 0x0, 0x20) /* IVB+ */
+#define OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP OP_3D_MEDIA(0x3, 0x0, 0x21) /* IVB+ */
+#define OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC   OP_3D_MEDIA(0x3, 0x0, 0x23) /* IVB+ */
+#define OP_3DSTATE_BLEND_STATE_POINTERS         OP_3D_MEDIA(0x3, 0x0, 0x24) /* IVB+ */
+#define OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x25) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_VS    OP_3D_MEDIA(0x3, 0x0, 0x26) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_HS    OP_3D_MEDIA(0x3, 0x0, 0x27) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_DS    OP_3D_MEDIA(0x3, 0x0, 0x28) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_GS    OP_3D_MEDIA(0x3, 0x0, 0x29) /* IVB+ */
+#define OP_3DSTATE_BINDING_TABLE_POINTERS_PS    OP_3D_MEDIA(0x3, 0x0, 0x2A) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_VS    OP_3D_MEDIA(0x3, 0x0, 0x2B) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_HS    OP_3D_MEDIA(0x3, 0x0, 0x2C) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_DS    OP_3D_MEDIA(0x3, 0x0, 0x2D) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_GS    OP_3D_MEDIA(0x3, 0x0, 0x2E) /* IVB+ */
+#define OP_3DSTATE_SAMPLER_STATE_POINTERS_PS    OP_3D_MEDIA(0x3, 0x0, 0x2F) /* IVB+ */
+#define OP_3DSTATE_URB_VS                       OP_3D_MEDIA(0x3, 0x0, 0x30) /* IVB+ */
+#define OP_3DSTATE_URB_HS                       OP_3D_MEDIA(0x3, 0x0, 0x31) /* IVB+ */
+#define OP_3DSTATE_URB_DS                       OP_3D_MEDIA(0x3, 0x0, 0x32) /* IVB+ */
+#define OP_3DSTATE_URB_GS                       OP_3D_MEDIA(0x3, 0x0, 0x33) /* IVB+ */
+#define OP_3DSTATE_GATHER_CONSTANT_VS           OP_3D_MEDIA(0x3, 0x0, 0x34) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_GS           OP_3D_MEDIA(0x3, 0x0, 0x35) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_HS           OP_3D_MEDIA(0x3, 0x0, 0x36) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_DS           OP_3D_MEDIA(0x3, 0x0, 0x37) /* HSW+ */
+#define OP_3DSTATE_GATHER_CONSTANT_PS           OP_3D_MEDIA(0x3, 0x0, 0x38) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTF_VS             OP_3D_MEDIA(0x3, 0x0, 0x39) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTF_PS             OP_3D_MEDIA(0x3, 0x0, 0x3A) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTI_VS             OP_3D_MEDIA(0x3, 0x0, 0x3B) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTI_PS             OP_3D_MEDIA(0x3, 0x0, 0x3C) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTB_VS             OP_3D_MEDIA(0x3, 0x0, 0x3D) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANTB_PS             OP_3D_MEDIA(0x3, 0x0, 0x3E) /* HSW+ */
+#define OP_3DSTATE_DX9_LOCAL_VALID_VS           OP_3D_MEDIA(0x3, 0x0, 0x3F) /* HSW+ */
+#define OP_3DSTATE_DX9_LOCAL_VALID_PS           OP_3D_MEDIA(0x3, 0x0, 0x40) /* HSW+ */
+#define OP_3DSTATE_DX9_GENERATE_ACTIVE_VS       OP_3D_MEDIA(0x3, 0x0, 0x41) /* HSW+ */
+#define OP_3DSTATE_DX9_GENERATE_ACTIVE_PS       OP_3D_MEDIA(0x3, 0x0, 0x42) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_VS        OP_3D_MEDIA(0x3, 0x0, 0x43) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_GS        OP_3D_MEDIA(0x3, 0x0, 0x44) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_HS        OP_3D_MEDIA(0x3, 0x0, 0x45) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_DS        OP_3D_MEDIA(0x3, 0x0, 0x46) /* HSW+ */
+#define OP_3DSTATE_BINDING_TABLE_EDIT_PS        OP_3D_MEDIA(0x3, 0x0, 0x47) /* HSW+ */
+
+#define OP_3DSTATE_VF_INSTANCING 		OP_3D_MEDIA(0x3, 0x0, 0x49) /* BDW+ */
+#define OP_3DSTATE_VF_SGVS  			OP_3D_MEDIA(0x3, 0x0, 0x4A) /* BDW+ */
+#define OP_3DSTATE_VF_TOPOLOGY   		OP_3D_MEDIA(0x3, 0x0, 0x4B) /* BDW+ */
+#define OP_3DSTATE_WM_CHROMAKEY   		OP_3D_MEDIA(0x3, 0x0, 0x4C) /* BDW+ */
+#define OP_3DSTATE_PS_BLEND   			OP_3D_MEDIA(0x3, 0x0, 0x4D) /* BDW+ */
+#define OP_3DSTATE_WM_DEPTH_STENCIL   		OP_3D_MEDIA(0x3, 0x0, 0x4E) /* BDW+ */
+#define OP_3DSTATE_PS_EXTRA   			OP_3D_MEDIA(0x3, 0x0, 0x4F) /* BDW+ */
+#define OP_3DSTATE_RASTER   			OP_3D_MEDIA(0x3, 0x0, 0x50) /* BDW+ */
+#define OP_3DSTATE_SBE_SWIZ   			OP_3D_MEDIA(0x3, 0x0, 0x51) /* BDW+ */
+#define OP_3DSTATE_WM_HZ_OP   			OP_3D_MEDIA(0x3, 0x0, 0x52) /* BDW+ */
+#define OP_3DSTATE_COMPONENT_PACKING		OP_3D_MEDIA(0x3, 0x0, 0x55) /* SKL+ */
+
+#define OP_3DSTATE_DRAWING_RECTANGLE            OP_3D_MEDIA(0x3, 0x1, 0x00)
+#define OP_3DSTATE_SAMPLER_PALETTE_LOAD0        OP_3D_MEDIA(0x3, 0x1, 0x02)
+#define OP_3DSTATE_CHROMA_KEY                   OP_3D_MEDIA(0x3, 0x1, 0x04)
+#define OP_SNB_3DSTATE_DEPTH_BUFFER             OP_3D_MEDIA(0x3, 0x1, 0x05)
+#define OP_3DSTATE_POLY_STIPPLE_OFFSET          OP_3D_MEDIA(0x3, 0x1, 0x06)
+#define OP_3DSTATE_POLY_STIPPLE_PATTERN         OP_3D_MEDIA(0x3, 0x1, 0x07)
+#define OP_3DSTATE_LINE_STIPPLE                 OP_3D_MEDIA(0x3, 0x1, 0x08)
+#define OP_3DSTATE_AA_LINE_PARAMS               OP_3D_MEDIA(0x3, 0x1, 0x0A)
+#define OP_3DSTATE_GS_SVB_INDEX                 OP_3D_MEDIA(0x3, 0x1, 0x0B)
+#define OP_3DSTATE_SAMPLER_PALETTE_LOAD1        OP_3D_MEDIA(0x3, 0x1, 0x0C)
+#define OP_3DSTATE_MULTISAMPLE_BDW		OP_3D_MEDIA(0x3, 0x0, 0x0D)
+#define OP_SNB_3DSTATE_STENCIL_BUFFER           OP_3D_MEDIA(0x3, 0x1, 0x0E)
+#define OP_SNB_3DSTATE_HIER_DEPTH_BUFFER        OP_3D_MEDIA(0x3, 0x1, 0x0F)
+#define OP_SNB_3DSTATE_CLEAR_PARAMS             OP_3D_MEDIA(0x3, 0x1, 0x10)
+#define OP_3DSTATE_MONOFILTER_SIZE              OP_3D_MEDIA(0x3, 0x1, 0x11)
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS       OP_3D_MEDIA(0x3, 0x1, 0x12) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS       OP_3D_MEDIA(0x3, 0x1, 0x13) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS       OP_3D_MEDIA(0x3, 0x1, 0x14) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS       OP_3D_MEDIA(0x3, 0x1, 0x15) /* IVB+ */
+#define OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS       OP_3D_MEDIA(0x3, 0x1, 0x16) /* IVB+ */
+#define OP_3DSTATE_SO_DECL_LIST                 OP_3D_MEDIA(0x3, 0x1, 0x17)
+#define OP_3DSTATE_SO_BUFFER                    OP_3D_MEDIA(0x3, 0x1, 0x18)
+#define OP_3DSTATE_BINDING_TABLE_POOL_ALLOC     OP_3D_MEDIA(0x3, 0x1, 0x19) /* HSW+ */
+#define OP_3DSTATE_GATHER_POOL_ALLOC            OP_3D_MEDIA(0x3, 0x1, 0x1A) /* HSW+ */
+#define OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x1B) /* HSW+ */
+#define OP_3DSTATE_SAMPLE_PATTERN               OP_3D_MEDIA(0x3, 0x1, 0x1C)
+#define OP_PIPE_CONTROL                         OP_3D_MEDIA(0x3, 0x2, 0x00)
+#define OP_3DPRIMITIVE                          OP_3D_MEDIA(0x3, 0x3, 0x00)
+
+/* VCCP Command Parser */
+
+/*
+ * Below MFX and VBE cmd definition is from vaapi intel driver project (BSD License)
+ * git://anongit.freedesktop.org/vaapi/intel-driver
+ * src/i965_defines.h
+ *
+ */
+
+#define OP_MFX(pipeline, op, sub_opa, sub_opb)     \
+	(3 << 13 | \
+	 (pipeline) << 11 | \
+	 (op) << 8 | \
+	 (sub_opa) << 5 | \
+	 (sub_opb))
+
+#define OP_MFX_PIPE_MODE_SELECT                    OP_MFX(2, 0, 0, 0)  /* ALL */
+#define OP_MFX_SURFACE_STATE                       OP_MFX(2, 0, 0, 1)  /* ALL */
+#define OP_MFX_PIPE_BUF_ADDR_STATE                 OP_MFX(2, 0, 0, 2)  /* ALL */
+#define OP_MFX_IND_OBJ_BASE_ADDR_STATE             OP_MFX(2, 0, 0, 3)  /* ALL */
+#define OP_MFX_BSP_BUF_BASE_ADDR_STATE             OP_MFX(2, 0, 0, 4)  /* ALL */
+#define OP_2_0_0_5                                 OP_MFX(2, 0, 0, 5)  /* ALL */
+#define OP_MFX_STATE_POINTER                       OP_MFX(2, 0, 0, 6)  /* ALL */
+#define OP_MFX_QM_STATE                            OP_MFX(2, 0, 0, 7)  /* IVB+ */
+#define OP_MFX_FQM_STATE                           OP_MFX(2, 0, 0, 8)  /* IVB+ */
+#define OP_MFX_PAK_INSERT_OBJECT                   OP_MFX(2, 0, 2, 8)  /* IVB+ */
+#define OP_MFX_STITCH_OBJECT                       OP_MFX(2, 0, 2, 0xA)  /* IVB+ */
+
+#define OP_MFD_IT_OBJECT                           OP_MFX(2, 0, 1, 9) /* ALL */
+
+#define OP_MFX_WAIT                                OP_MFX(1, 0, 0, 0) /* IVB+ */
+#define OP_MFX_AVC_IMG_STATE                       OP_MFX(2, 1, 0, 0) /* ALL */
+#define OP_MFX_AVC_QM_STATE                        OP_MFX(2, 1, 0, 1) /* ALL */
+#define OP_MFX_AVC_DIRECTMODE_STATE                OP_MFX(2, 1, 0, 2) /* ALL */
+#define OP_MFX_AVC_SLICE_STATE                     OP_MFX(2, 1, 0, 3) /* ALL */
+#define OP_MFX_AVC_REF_IDX_STATE                   OP_MFX(2, 1, 0, 4) /* ALL */
+#define OP_MFX_AVC_WEIGHTOFFSET_STATE              OP_MFX(2, 1, 0, 5) /* ALL */
+#define OP_MFD_AVC_PICID_STATE                     OP_MFX(2, 1, 1, 5) /* HSW+ */
+#define OP_MFD_AVC_DPB_STATE			   OP_MFX(2, 1, 1, 6) /* IVB+ */
+#define OP_MFD_AVC_SLICEADDR                       OP_MFX(2, 1, 1, 7) /* IVB+ */
+#define OP_MFD_AVC_BSD_OBJECT                      OP_MFX(2, 1, 1, 8) /* ALL */
+#define OP_MFC_AVC_PAK_OBJECT                      OP_MFX(2, 1, 2, 9) /* ALL */
+
+#define OP_MFX_VC1_PRED_PIPE_STATE                 OP_MFX(2, 2, 0, 1) /* ALL */
+#define OP_MFX_VC1_DIRECTMODE_STATE                OP_MFX(2, 2, 0, 2) /* ALL */
+#define OP_MFD_VC1_SHORT_PIC_STATE                 OP_MFX(2, 2, 1, 0) /* IVB+ */
+#define OP_MFD_VC1_LONG_PIC_STATE                  OP_MFX(2, 2, 1, 1) /* IVB+ */
+#define OP_MFD_VC1_BSD_OBJECT                      OP_MFX(2, 2, 1, 8) /* ALL */
+
+#define OP_MFX_MPEG2_PIC_STATE                     OP_MFX(2, 3, 0, 0) /* ALL */
+#define OP_MFX_MPEG2_QM_STATE                      OP_MFX(2, 3, 0, 1) /* ALL */
+#define OP_MFD_MPEG2_BSD_OBJECT                    OP_MFX(2, 3, 1, 8) /* ALL */
+#define OP_MFC_MPEG2_SLICEGROUP_STATE              OP_MFX(2, 3, 2, 3) /* ALL */
+#define OP_MFC_MPEG2_PAK_OBJECT                    OP_MFX(2, 3, 2, 9) /* ALL */
+
+#define OP_MFX_2_6_0_0                             OP_MFX(2, 6, 0, 0) /* IVB+ */
+#define OP_MFX_2_6_0_8                             OP_MFX(2, 6, 0, 8) /* IVB+ */
+#define OP_MFX_2_6_0_9                             OP_MFX(2, 6, 0, 9) /* IVB+ */
+
+#define OP_MFX_JPEG_PIC_STATE                      OP_MFX(2, 7, 0, 0)
+#define OP_MFX_JPEG_HUFF_TABLE_STATE               OP_MFX(2, 7, 0, 2)
+#define OP_MFD_JPEG_BSD_OBJECT                     OP_MFX(2, 7, 1, 8)
+
+#define OP_VEB(pipeline, op, sub_opa, sub_opb) \
+	(3 << 13 | \
+	 (pipeline) << 11 | \
+	 (op) << 8 | \
+	 (sub_opa) << 5 | \
+	 (sub_opb))
+
+#define OP_VEB_SURFACE_STATE                       OP_VEB(2, 4, 0, 0)
+#define OP_VEB_STATE                               OP_VEB(2, 4, 0, 2)
+#define OP_VEB_DNDI_IECP_STATE                     OP_VEB(2, 4, 0, 3)
+
+struct parser_exec_state;
+
+typedef int (*parser_cmd_handler)(struct parser_exec_state *s);
+
+#define GVT_CMD_HASH_BITS   7
+
+/* which DWords need address fix */
+#define ADDR_FIX_1(x1)			(1 << (x1))
+#define ADDR_FIX_2(x1, x2)		(ADDR_FIX_1(x1) | ADDR_FIX_1(x2))
+#define ADDR_FIX_3(x1, x2, x3)		(ADDR_FIX_1(x1) | ADDR_FIX_2(x2, x3))
+#define ADDR_FIX_4(x1, x2, x3, x4)	(ADDR_FIX_1(x1) | ADDR_FIX_3(x2, x3, x4))
+#define ADDR_FIX_5(x1, x2, x3, x4, x5)  (ADDR_FIX_1(x1) | ADDR_FIX_4(x2, x3, x4, x5))
+
+struct cmd_info {
+	char *name;
+	u32 opcode;
+
+#define F_LEN_MASK	(1U<<0)
+#define F_LEN_CONST  1U
+#define F_LEN_VAR    0U
+
+/*
+ * command has its own ip advance logic
+ * e.g. MI_BATCH_START, MI_BATCH_END
+ */
+#define F_IP_ADVANCE_CUSTOM (1<<1)
+
+#define F_POST_HANDLE	(1<<2)
+	u32 flag;
+
+#define R_RCS	(1 << RCS)
+#define R_VCS1  (1 << VCS)
+#define R_VCS2  (1 << VCS2)
+#define R_VCS	(R_VCS1 | R_VCS2)
+#define R_BCS	(1 << BCS)
+#define R_VECS	(1 << VECS)
+#define R_ALL (R_RCS | R_VCS | R_BCS | R_VECS)
+	/* rings that support this cmd: BLT/RCS/VCS/VECS */
+	uint16_t rings;
+
+	/* devices that support this cmd: SNB/IVB/HSW/... */
+	uint16_t devices;
+
+	/* which DWords are address that need fix up.
+	 * bit 0 means a 32-bit non address operand in command
+	 * bit 1 means address operand, which could be 32-bit
+	 * or 64-bit depending on different architectures.(
+	 * defined by "gmadr_bytes_in_cmd" in intel_gvt.
+	 * No matter the address length, each address only takes
+	 * one bit in the bitmap.
+	 */
+	uint16_t addr_bitmap;
+
+	/* flag == F_LEN_CONST : command length
+	 * flag == F_LEN_VAR : length bias bits
+	 * Note: length is in DWord
+	 */
+	uint8_t	len;
+
+	parser_cmd_handler handler;
+};
+
+struct cmd_entry {
+	struct hlist_node hlist;
+	struct cmd_info *info;
+};
+
+enum {
+	RING_BUFFER_INSTRUCTION,
+	BATCH_BUFFER_INSTRUCTION,
+	BATCH_BUFFER_2ND_LEVEL,
+};
+
+enum {
+	GTT_BUFFER,
+	PPGTT_BUFFER
+};
+
+struct parser_exec_state {
+	struct intel_vgpu *vgpu;
+	int ring_id;
+
+	int buf_type;
+
+	/* batch buffer address type */
+	int buf_addr_type;
+
+	/* graphics memory address of ring buffer start */
+	unsigned long ring_start;
+	unsigned long ring_size;
+	unsigned long ring_head;
+	unsigned long ring_tail;
+
+	/* instruction graphics memory address */
+	unsigned long ip_gma;
+
+	/* mapped va of the instr_gma */
+	void *ip_va;
+	void *rb_va;
+
+	void *ret_bb_va;
+	/* next instruction when return from  batch buffer to ring buffer */
+	unsigned long ret_ip_gma_ring;
+
+	/* next instruction when return from 2nd batch buffer to batch buffer */
+	unsigned long ret_ip_gma_bb;
+
+	/* batch buffer address type (GTT or PPGTT)
+	 * used when ret from 2nd level batch buffer
+	 */
+	int saved_buf_addr_type;
+
+	struct cmd_info *info;
+
+	struct intel_vgpu_workload *workload;
+};
+
+#define gmadr_dw_number(s)	\
+	(s->vgpu->gvt->device_info.gmadr_bytes_in_cmd >> 2)
+
+static unsigned long bypass_scan_mask = 0;
+
+/* ring ALL, type = 0 */
+static struct sub_op_bits sub_op_mi[] = {
+	{31, 29},
+	{28, 23},
+};
+
+static struct decode_info decode_info_mi = {
+	"MI",
+	OP_LEN_MI,
+	ARRAY_SIZE(sub_op_mi),
+	sub_op_mi,
+};
+
+/* ring RCS, command type 2 */
+static struct sub_op_bits sub_op_2d[] = {
+	{31, 29},
+	{28, 22},
+};
+
+static struct decode_info decode_info_2d = {
+	"2D",
+	OP_LEN_2D,
+	ARRAY_SIZE(sub_op_2d),
+	sub_op_2d,
+};
+
+/* ring RCS, command type 3 */
+static struct sub_op_bits sub_op_3d_media[] = {
+	{31, 29},
+	{28, 27},
+	{26, 24},
+	{23, 16},
+};
+
+static struct decode_info decode_info_3d_media = {
+	"3D_Media",
+	OP_LEN_3D_MEDIA,
+	ARRAY_SIZE(sub_op_3d_media),
+	sub_op_3d_media,
+};
+
+/* ring VCS, command type 3 */
+static struct sub_op_bits sub_op_mfx_vc[] = {
+	{31, 29},
+	{28, 27},
+	{26, 24},
+	{23, 21},
+	{20, 16},
+};
+
+static struct decode_info decode_info_mfx_vc = {
+	"MFX_VC",
+	OP_LEN_MFX_VC,
+	ARRAY_SIZE(sub_op_mfx_vc),
+	sub_op_mfx_vc,
+};
+
+/* ring VECS, command type 3 */
+static struct sub_op_bits sub_op_vebox[] = {
+	{31, 29},
+	{28, 27},
+	{26, 24},
+	{23, 21},
+	{20, 16},
+};
+
+static struct decode_info decode_info_vebox = {
+	"VEBOX",
+	OP_LEN_VEBOX,
+	ARRAY_SIZE(sub_op_vebox),
+	sub_op_vebox,
+};
+
+static struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = {
+	[RCS] = {
+		&decode_info_mi,
+		NULL,
+		NULL,
+		&decode_info_3d_media,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+	},
+
+	[VCS] = {
+		&decode_info_mi,
+		NULL,
+		NULL,
+		&decode_info_mfx_vc,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+	},
+
+	[BCS] = {
+		&decode_info_mi,
+		NULL,
+		&decode_info_2d,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+	},
+
+	[VECS] = {
+		&decode_info_mi,
+		NULL,
+		NULL,
+		&decode_info_vebox,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+	},
+
+	[VCS2] = {
+		&decode_info_mi,
+		NULL,
+		NULL,
+		&decode_info_mfx_vc,
+		NULL,
+		NULL,
+		NULL,
+		NULL,
+	},
+};
+
+static inline u32 get_opcode(u32 cmd, int ring_id)
+{
+	struct decode_info *d_info;
+
+	if (ring_id >= I915_NUM_ENGINES)
+		return INVALID_OP;
+
+	d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)];
+	if (d_info == NULL)
+		return INVALID_OP;
+
+	return cmd >> (32 - d_info->op_len);
+}
+
+static inline struct cmd_info *find_cmd_entry(struct intel_gvt *gvt,
+		unsigned int opcode, int ring_id)
+{
+	struct cmd_entry *e;
+
+	hash_for_each_possible(gvt->cmd_table, e, hlist, opcode) {
+		if ((opcode == e->info->opcode) &&
+				(e->info->rings & (1 << ring_id)))
+			return e->info;
+	}
+	return NULL;
+}
+
+static inline struct cmd_info *get_cmd_info(struct intel_gvt *gvt,
+		u32 cmd, int ring_id)
+{
+	u32 opcode;
+
+	opcode = get_opcode(cmd, ring_id);
+	if (opcode == INVALID_OP)
+		return NULL;
+
+	return find_cmd_entry(gvt, opcode, ring_id);
+}
+
+static inline u32 sub_op_val(u32 cmd, u32 hi, u32 low)
+{
+	return (cmd >> low) & ((1U << (hi - low + 1)) - 1);
+}
+
+static inline void print_opcode(u32 cmd, int ring_id)
+{
+	struct decode_info *d_info;
+	int i;
+
+	if (ring_id >= I915_NUM_ENGINES)
+		return;
+
+	d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)];
+	if (d_info == NULL)
+		return;
+
+	gvt_err("opcode=0x%x %s sub_ops:",
+			cmd >> (32 - d_info->op_len), d_info->name);
+
+	for (i = 0; i < d_info->nr_sub_op; i++)
+		pr_err("0x%x ", sub_op_val(cmd, d_info->sub_op[i].hi,
+					d_info->sub_op[i].low));
+
+	pr_err("\n");
+}
+
+static inline u32 *cmd_ptr(struct parser_exec_state *s, int index)
+{
+	return s->ip_va + (index << 2);
+}
+
+static inline u32 cmd_val(struct parser_exec_state *s, int index)
+{
+	return *cmd_ptr(s, index);
+}
+
+static void parser_exec_state_dump(struct parser_exec_state *s)
+{
+	int cnt = 0;
+	int i;
+
+	gvt_err("  vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)"
+			" ring_head(%08lx) ring_tail(%08lx)\n", s->vgpu->id,
+			s->ring_id, s->ring_start, s->ring_start + s->ring_size,
+			s->ring_head, s->ring_tail);
+
+	gvt_err("  %s %s ip_gma(%08lx) ",
+			s->buf_type == RING_BUFFER_INSTRUCTION ?
+			"RING_BUFFER" : "BATCH_BUFFER",
+			s->buf_addr_type == GTT_BUFFER ?
+			"GTT" : "PPGTT", s->ip_gma);
+
+	if (s->ip_va == NULL) {
+		gvt_err(" ip_va(NULL)");
+		return;
+	}
+
+	gvt_err("  ip_va=%p: %08x %08x %08x %08x\n",
+			s->ip_va, cmd_val(s, 0), cmd_val(s, 1),
+			cmd_val(s, 2), cmd_val(s, 3));
+
+	print_opcode(cmd_val(s, 0), s->ring_id);
+
+	/* print the whole page to trace */
+	pr_err("    ip_va=%p: %08x %08x %08x %08x\n",
+			s->ip_va, cmd_val(s, 0), cmd_val(s, 1),
+			cmd_val(s, 2), cmd_val(s, 3));
+
+	s->ip_va = (u32 *)((((u64)s->ip_va) >> 12) << 12);
+
+	while (cnt < 1024) {
+		pr_err("ip_va=%p: ", s->ip_va);
+		for (i = 0; i < 8; i++)
+			pr_err("%08x ", cmd_val(s, i));
+		pr_err("\n");
+
+		s->ip_va += 8 * sizeof(u32);
+		cnt += 8;
+	}
+}
+
+static inline void update_ip_va(struct parser_exec_state *s)
+{
+	unsigned long len = 0;
+
+	if (WARN_ON(s->ring_head == s->ring_tail))
+		return;
+
+	if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+		unsigned long ring_top = s->ring_start + s->ring_size;
+
+		if (s->ring_head > s->ring_tail) {
+			if (s->ip_gma >= s->ring_head && s->ip_gma < ring_top)
+				len = (s->ip_gma - s->ring_head);
+			else if (s->ip_gma >= s->ring_start &&
+					s->ip_gma <= s->ring_tail)
+				len = (ring_top - s->ring_head) +
+					(s->ip_gma - s->ring_start);
+		} else
+			len = (s->ip_gma - s->ring_head);
+
+		s->ip_va = s->rb_va + len;
+	} else {/* shadow batch buffer */
+		s->ip_va = s->ret_bb_va;
+	}
+}
+
+static inline int ip_gma_set(struct parser_exec_state *s,
+		unsigned long ip_gma)
+{
+	WARN_ON(!IS_ALIGNED(ip_gma, 4));
+
+	s->ip_gma = ip_gma;
+	update_ip_va(s);
+	return 0;
+}
+
+static inline int ip_gma_advance(struct parser_exec_state *s,
+		unsigned int dw_len)
+{
+	s->ip_gma += (dw_len << 2);
+
+	if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+		if (s->ip_gma >= s->ring_start + s->ring_size)
+			s->ip_gma -= s->ring_size;
+		update_ip_va(s);
+	} else {
+		s->ip_va += (dw_len << 2);
+	}
+
+	return 0;
+}
+
+static inline int get_cmd_length(struct cmd_info *info, u32 cmd)
+{
+	if ((info->flag & F_LEN_MASK) == F_LEN_CONST)
+		return info->len;
+	else
+		return (cmd & ((1U << info->len) - 1)) + 2;
+	return 0;
+}
+
+static inline int cmd_length(struct parser_exec_state *s)
+{
+	return get_cmd_length(s->info, cmd_val(s, 0));
+}
+
+/* do not remove this, some platform may need clflush here */
+#define patch_value(s, addr, val) do { \
+	*addr = val; \
+} while (0)
+
+static bool is_shadowed_mmio(unsigned int offset)
+{
+	bool ret = false;
+
+	if ((offset == 0x2168) || /*BB current head register UDW */
+	    (offset == 0x2140) || /*BB current header register */
+	    (offset == 0x211c) || /*second BB header register UDW */
+	    (offset == 0x2114)) { /*second BB header register UDW */
+		ret = true;
+	}
+	return ret;
+}
+
+static int cmd_reg_handler(struct parser_exec_state *s,
+	unsigned int offset, unsigned int index, char *cmd)
+{
+	struct intel_vgpu *vgpu = s->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+
+	if (offset + 4 > gvt->device_info.mmio_size) {
+		gvt_err("%s access to (%x) outside of MMIO range\n",
+				cmd, offset);
+		return -EINVAL;
+	}
+
+	if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) {
+		gvt_err("vgpu%d: %s access to non-render register (%x)\n",
+				s->vgpu->id, cmd, offset);
+		return 0;
+	}
+
+	if (is_shadowed_mmio(offset)) {
+		gvt_err("vgpu%d: found access of shadowed MMIO %x\n",
+				s->vgpu->id, offset);
+		return 0;
+	}
+
+	if (offset == i915_mmio_reg_offset(DERRMR) ||
+		offset == i915_mmio_reg_offset(FORCEWAKE_MT)) {
+		/* Writing to HW VGT_PVINFO_PAGE offset will be discarded */
+		patch_value(s, cmd_ptr(s, index), VGT_PVINFO_PAGE);
+	}
+
+	/* TODO: Update the global mask if this MMIO is a masked-MMIO */
+	intel_gvt_mmio_set_cmd_accessed(gvt, offset);
+	return 0;
+}
+
+#define cmd_reg(s, i) \
+	(cmd_val(s, i) & GENMASK(22, 2))
+
+#define cmd_reg_inhibit(s, i) \
+	(cmd_val(s, i) & GENMASK(22, 18))
+
+#define cmd_gma(s, i) \
+	(cmd_val(s, i) & GENMASK(31, 2))
+
+#define cmd_gma_hi(s, i) \
+	(cmd_val(s, i) & GENMASK(15, 0))
+
+static int cmd_handler_lri(struct parser_exec_state *s)
+{
+	int i, ret = 0;
+	int cmd_len = cmd_length(s);
+	struct intel_gvt *gvt = s->vgpu->gvt;
+
+	for (i = 1; i < cmd_len; i += 2) {
+		if (IS_BROADWELL(gvt->dev_priv) &&
+				(s->ring_id != RCS)) {
+			if (s->ring_id == BCS &&
+					cmd_reg(s, i) ==
+					i915_mmio_reg_offset(DERRMR))
+				ret |= 0;
+			else
+				ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0;
+		}
+		if (ret)
+			break;
+		ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lri");
+	}
+	return ret;
+}
+
+static int cmd_handler_lrr(struct parser_exec_state *s)
+{
+	int i, ret = 0;
+	int cmd_len = cmd_length(s);
+
+	for (i = 1; i < cmd_len; i += 2) {
+		if (IS_BROADWELL(s->vgpu->gvt->dev_priv))
+			ret |= ((cmd_reg_inhibit(s, i) ||
+					(cmd_reg_inhibit(s, i + 1)))) ?
+				-EINVAL : 0;
+		if (ret)
+			break;
+		ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrr-src");
+		ret |= cmd_reg_handler(s, cmd_reg(s, i + 1), i, "lrr-dst");
+	}
+	return ret;
+}
+
+static inline int cmd_address_audit(struct parser_exec_state *s,
+		unsigned long guest_gma, int op_size, bool index_mode);
+
+static int cmd_handler_lrm(struct parser_exec_state *s)
+{
+	struct intel_gvt *gvt = s->vgpu->gvt;
+	int gmadr_bytes = gvt->device_info.gmadr_bytes_in_cmd;
+	unsigned long gma;
+	int i, ret = 0;
+	int cmd_len = cmd_length(s);
+
+	for (i = 1; i < cmd_len;) {
+		if (IS_BROADWELL(gvt->dev_priv))
+			ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0;
+		if (ret)
+			break;
+		ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrm");
+		if (cmd_val(s, 0) & (1 << 22)) {
+			gma = cmd_gma(s, i + 1);
+			if (gmadr_bytes == 8)
+				gma |= (cmd_gma_hi(s, i + 2)) << 32;
+			ret |= cmd_address_audit(s, gma, sizeof(u32), false);
+		}
+		i += gmadr_dw_number(s) + 1;
+	}
+	return ret;
+}
+
+static int cmd_handler_srm(struct parser_exec_state *s)
+{
+	int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+	unsigned long gma;
+	int i, ret = 0;
+	int cmd_len = cmd_length(s);
+
+	for (i = 1; i < cmd_len;) {
+		ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "srm");
+		if (cmd_val(s, 0) & (1 << 22)) {
+			gma = cmd_gma(s, i + 1);
+			if (gmadr_bytes == 8)
+				gma |= (cmd_gma_hi(s, i + 2)) << 32;
+			ret |= cmd_address_audit(s, gma, sizeof(u32), false);
+		}
+		i += gmadr_dw_number(s) + 1;
+	}
+	return ret;
+}
+
+struct cmd_interrupt_event {
+	int pipe_control_notify;
+	int mi_flush_dw;
+	int mi_user_interrupt;
+};
+
+static struct cmd_interrupt_event cmd_interrupt_events[] = {
+	[RCS] = {
+		.pipe_control_notify = RCS_PIPE_CONTROL,
+		.mi_flush_dw = INTEL_GVT_EVENT_RESERVED,
+		.mi_user_interrupt = RCS_MI_USER_INTERRUPT,
+	},
+	[BCS] = {
+		.pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+		.mi_flush_dw = BCS_MI_FLUSH_DW,
+		.mi_user_interrupt = BCS_MI_USER_INTERRUPT,
+	},
+	[VCS] = {
+		.pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+		.mi_flush_dw = VCS_MI_FLUSH_DW,
+		.mi_user_interrupt = VCS_MI_USER_INTERRUPT,
+	},
+	[VCS2] = {
+		.pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+		.mi_flush_dw = VCS2_MI_FLUSH_DW,
+		.mi_user_interrupt = VCS2_MI_USER_INTERRUPT,
+	},
+	[VECS] = {
+		.pipe_control_notify = INTEL_GVT_EVENT_RESERVED,
+		.mi_flush_dw = VECS_MI_FLUSH_DW,
+		.mi_user_interrupt = VECS_MI_USER_INTERRUPT,
+	},
+};
+
+static int cmd_handler_pipe_control(struct parser_exec_state *s)
+{
+	int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+	unsigned long gma;
+	bool index_mode = false;
+	unsigned int post_sync;
+	int ret = 0;
+
+	post_sync = (cmd_val(s, 1) & PIPE_CONTROL_POST_SYNC_OP_MASK) >> 14;
+
+	/* LRI post sync */
+	if (cmd_val(s, 1) & PIPE_CONTROL_MMIO_WRITE)
+		ret = cmd_reg_handler(s, cmd_reg(s, 2), 1, "pipe_ctrl");
+	/* post sync */
+	else if (post_sync) {
+		if (post_sync == 2)
+			ret = cmd_reg_handler(s, 0x2350, 1, "pipe_ctrl");
+		else if (post_sync == 3)
+			ret = cmd_reg_handler(s, 0x2358, 1, "pipe_ctrl");
+		else if (post_sync == 1) {
+			/* check ggtt*/
+			if ((cmd_val(s, 2) & (1 << 2))) {
+				gma = cmd_val(s, 2) & GENMASK(31, 3);
+				if (gmadr_bytes == 8)
+					gma |= (cmd_gma_hi(s, 3)) << 32;
+				/* Store Data Index */
+				if (cmd_val(s, 1) & (1 << 21))
+					index_mode = true;
+				ret |= cmd_address_audit(s, gma, sizeof(u64),
+						index_mode);
+			}
+		}
+	}
+
+	if (ret)
+		return ret;
+
+	if (cmd_val(s, 1) & PIPE_CONTROL_NOTIFY)
+		set_bit(cmd_interrupt_events[s->ring_id].pipe_control_notify,
+				s->workload->pending_events);
+	return 0;
+}
+
+static int cmd_handler_mi_user_interrupt(struct parser_exec_state *s)
+{
+	set_bit(cmd_interrupt_events[s->ring_id].mi_user_interrupt,
+			s->workload->pending_events);
+	return 0;
+}
+
+static int cmd_advance_default(struct parser_exec_state *s)
+{
+	return ip_gma_advance(s, cmd_length(s));
+}
+
+static int cmd_handler_mi_batch_buffer_end(struct parser_exec_state *s)
+{
+	int ret;
+
+	if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) {
+		s->buf_type = BATCH_BUFFER_INSTRUCTION;
+		ret = ip_gma_set(s, s->ret_ip_gma_bb);
+		s->buf_addr_type = s->saved_buf_addr_type;
+	} else {
+		s->buf_type = RING_BUFFER_INSTRUCTION;
+		s->buf_addr_type = GTT_BUFFER;
+		if (s->ret_ip_gma_ring >= s->ring_start + s->ring_size)
+			s->ret_ip_gma_ring -= s->ring_size;
+		ret = ip_gma_set(s, s->ret_ip_gma_ring);
+	}
+	return ret;
+}
+
+struct mi_display_flip_command_info {
+	int pipe;
+	int plane;
+	int event;
+	i915_reg_t stride_reg;
+	i915_reg_t ctrl_reg;
+	i915_reg_t surf_reg;
+	u64 stride_val;
+	u64 tile_val;
+	u64 surf_val;
+	bool async_flip;
+};
+
+struct plane_code_mapping {
+	int pipe;
+	int plane;
+	int event;
+};
+
+static int gen8_decode_mi_display_flip(struct parser_exec_state *s,
+		struct mi_display_flip_command_info *info)
+{
+	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+	struct plane_code_mapping gen8_plane_code[] = {
+		[0] = {PIPE_A, PLANE_A, PRIMARY_A_FLIP_DONE},
+		[1] = {PIPE_B, PLANE_A, PRIMARY_B_FLIP_DONE},
+		[2] = {PIPE_A, PLANE_B, SPRITE_A_FLIP_DONE},
+		[3] = {PIPE_B, PLANE_B, SPRITE_B_FLIP_DONE},
+		[4] = {PIPE_C, PLANE_A, PRIMARY_C_FLIP_DONE},
+		[5] = {PIPE_C, PLANE_B, SPRITE_C_FLIP_DONE},
+	};
+	u32 dword0, dword1, dword2;
+	u32 v;
+
+	dword0 = cmd_val(s, 0);
+	dword1 = cmd_val(s, 1);
+	dword2 = cmd_val(s, 2);
+
+	v = (dword0 & GENMASK(21, 19)) >> 19;
+	if (WARN_ON(v >= ARRAY_SIZE(gen8_plane_code)))
+		return -EINVAL;
+
+	info->pipe = gen8_plane_code[v].pipe;
+	info->plane = gen8_plane_code[v].plane;
+	info->event = gen8_plane_code[v].event;
+	info->stride_val = (dword1 & GENMASK(15, 6)) >> 6;
+	info->tile_val = (dword1 & 0x1);
+	info->surf_val = (dword2 & GENMASK(31, 12)) >> 12;
+	info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1);
+
+	if (info->plane == PLANE_A) {
+		info->ctrl_reg = DSPCNTR(info->pipe);
+		info->stride_reg = DSPSTRIDE(info->pipe);
+		info->surf_reg = DSPSURF(info->pipe);
+	} else if (info->plane == PLANE_B) {
+		info->ctrl_reg = SPRCTL(info->pipe);
+		info->stride_reg = SPRSTRIDE(info->pipe);
+		info->surf_reg = SPRSURF(info->pipe);
+	} else {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int skl_decode_mi_display_flip(struct parser_exec_state *s,
+		struct mi_display_flip_command_info *info)
+{
+	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+	u32 dword0 = cmd_val(s, 0);
+	u32 dword1 = cmd_val(s, 1);
+	u32 dword2 = cmd_val(s, 2);
+	u32 plane = (dword0 & GENMASK(12, 8)) >> 8;
+
+	switch (plane) {
+	case MI_DISPLAY_FLIP_SKL_PLANE_1_A:
+		info->pipe = PIPE_A;
+		info->event = PRIMARY_A_FLIP_DONE;
+		break;
+	case MI_DISPLAY_FLIP_SKL_PLANE_1_B:
+		info->pipe = PIPE_B;
+		info->event = PRIMARY_B_FLIP_DONE;
+		break;
+	case MI_DISPLAY_FLIP_SKL_PLANE_1_C:
+		info->pipe = PIPE_C;
+		info->event = PRIMARY_C_FLIP_DONE;
+		break;
+	default:
+		gvt_err("unknown plane code %d\n", plane);
+		return -EINVAL;
+	}
+
+	info->pipe = PRIMARY_PLANE;
+	info->stride_val = (dword1 & GENMASK(15, 6)) >> 6;
+	info->tile_val = (dword1 & GENMASK(2, 0));
+	info->surf_val = (dword2 & GENMASK(31, 12)) >> 12;
+	info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1);
+
+	info->ctrl_reg = DSPCNTR(info->pipe);
+	info->stride_reg = DSPSTRIDE(info->pipe);
+	info->surf_reg = DSPSURF(info->pipe);
+
+	return 0;
+}
+
+static int gen8_check_mi_display_flip(struct parser_exec_state *s,
+		struct mi_display_flip_command_info *info)
+{
+	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+	u32 stride, tile;
+
+	if (!info->async_flip)
+		return 0;
+
+	if (IS_SKYLAKE(dev_priv)) {
+		stride = vgpu_vreg(s->vgpu, info->stride_reg) & GENMASK(9, 0);
+		tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) &
+				GENMASK(12, 10)) >> 10;
+	} else {
+		stride = (vgpu_vreg(s->vgpu, info->stride_reg) &
+				GENMASK(15, 6)) >> 6;
+		tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & (1 << 10)) >> 10;
+	}
+
+	if (stride != info->stride_val)
+		gvt_dbg_cmd("cannot change stride during async flip\n");
+
+	if (tile != info->tile_val)
+		gvt_dbg_cmd("cannot change tile during async flip\n");
+
+	return 0;
+}
+
+static int gen8_update_plane_mmio_from_mi_display_flip(
+		struct parser_exec_state *s,
+		struct mi_display_flip_command_info *info)
+{
+	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+	struct intel_vgpu *vgpu = s->vgpu;
+
+	set_mask_bits(&vgpu_vreg(vgpu, info->surf_reg), GENMASK(31, 12),
+		      info->surf_val << 12);
+	if (IS_SKYLAKE(dev_priv)) {
+		set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(9, 0),
+			      info->stride_val);
+		set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(12, 10),
+			      info->tile_val << 10);
+	} else {
+		set_mask_bits(&vgpu_vreg(vgpu, info->stride_reg), GENMASK(15, 6),
+			      info->stride_val << 6);
+		set_mask_bits(&vgpu_vreg(vgpu, info->ctrl_reg), GENMASK(10, 10),
+			      info->tile_val << 10);
+	}
+
+	vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(info->pipe))++;
+	intel_vgpu_trigger_virtual_event(vgpu, info->event);
+	return 0;
+}
+
+static int decode_mi_display_flip(struct parser_exec_state *s,
+		struct mi_display_flip_command_info *info)
+{
+	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+
+	if (IS_BROADWELL(dev_priv))
+		return gen8_decode_mi_display_flip(s, info);
+	if (IS_SKYLAKE(dev_priv))
+		return skl_decode_mi_display_flip(s, info);
+
+	return -ENODEV;
+}
+
+static int check_mi_display_flip(struct parser_exec_state *s,
+		struct mi_display_flip_command_info *info)
+{
+	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+
+	if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+		return gen8_check_mi_display_flip(s, info);
+	return -ENODEV;
+}
+
+static int update_plane_mmio_from_mi_display_flip(
+		struct parser_exec_state *s,
+		struct mi_display_flip_command_info *info)
+{
+	struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv;
+
+	if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
+		return gen8_update_plane_mmio_from_mi_display_flip(s, info);
+	return -ENODEV;
+}
+
+static int cmd_handler_mi_display_flip(struct parser_exec_state *s)
+{
+	struct mi_display_flip_command_info info;
+	int ret;
+	int i;
+	int len = cmd_length(s);
+
+	ret = decode_mi_display_flip(s, &info);
+	if (ret) {
+		gvt_err("fail to decode MI display flip command\n");
+		return ret;
+	}
+
+	ret = check_mi_display_flip(s, &info);
+	if (ret) {
+		gvt_err("invalid MI display flip command\n");
+		return ret;
+	}
+
+	ret = update_plane_mmio_from_mi_display_flip(s, &info);
+	if (ret) {
+		gvt_err("fail to update plane mmio\n");
+		return ret;
+	}
+
+	for (i = 0; i < len; i++)
+		patch_value(s, cmd_ptr(s, i), MI_NOOP);
+	return 0;
+}
+
+static bool is_wait_for_flip_pending(u32 cmd)
+{
+	return cmd & (MI_WAIT_FOR_PLANE_A_FLIP_PENDING |
+			MI_WAIT_FOR_PLANE_B_FLIP_PENDING |
+			MI_WAIT_FOR_PLANE_C_FLIP_PENDING |
+			MI_WAIT_FOR_SPRITE_A_FLIP_PENDING |
+			MI_WAIT_FOR_SPRITE_B_FLIP_PENDING |
+			MI_WAIT_FOR_SPRITE_C_FLIP_PENDING);
+}
+
+static int cmd_handler_mi_wait_for_event(struct parser_exec_state *s)
+{
+	u32 cmd = cmd_val(s, 0);
+
+	if (!is_wait_for_flip_pending(cmd))
+		return 0;
+
+	patch_value(s, cmd_ptr(s, 0), MI_NOOP);
+	return 0;
+}
+
+static unsigned long get_gma_bb_from_cmd(struct parser_exec_state *s, int index)
+{
+	unsigned long addr;
+	unsigned long gma_high, gma_low;
+	int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+
+	if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8))
+		return INTEL_GVT_INVALID_ADDR;
+
+	gma_low = cmd_val(s, index) & BATCH_BUFFER_ADDR_MASK;
+	if (gmadr_bytes == 4) {
+		addr = gma_low;
+	} else {
+		gma_high = cmd_val(s, index + 1) & BATCH_BUFFER_ADDR_HIGH_MASK;
+		addr = (((unsigned long)gma_high) << 32) | gma_low;
+	}
+	return addr;
+}
+
+static inline int cmd_address_audit(struct parser_exec_state *s,
+		unsigned long guest_gma, int op_size, bool index_mode)
+{
+	struct intel_vgpu *vgpu = s->vgpu;
+	u32 max_surface_size = vgpu->gvt->device_info.max_surface_size;
+	int i;
+	int ret;
+
+	if (op_size > max_surface_size) {
+		gvt_err("command address audit fail name %s\n", s->info->name);
+		return -EINVAL;
+	}
+
+	if (index_mode)	{
+		if (guest_gma >= GTT_PAGE_SIZE / sizeof(u64)) {
+			ret = -EINVAL;
+			goto err;
+		}
+	} else if ((!vgpu_gmadr_is_valid(s->vgpu, guest_gma)) ||
+			(!vgpu_gmadr_is_valid(s->vgpu,
+					      guest_gma + op_size - 1))) {
+		ret = -EINVAL;
+		goto err;
+	}
+	return 0;
+err:
+	gvt_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n",
+			s->info->name, guest_gma, op_size);
+
+	pr_err("cmd dump: ");
+	for (i = 0; i < cmd_length(s); i++) {
+		if (!(i % 4))
+			pr_err("\n%08x ", cmd_val(s, i));
+		else
+			pr_err("%08x ", cmd_val(s, i));
+	}
+	pr_err("\nvgpu%d: aperture 0x%llx - 0x%llx, hidden 0x%llx - 0x%llx\n",
+			vgpu->id,
+			vgpu_aperture_gmadr_base(vgpu),
+			vgpu_aperture_gmadr_end(vgpu),
+			vgpu_hidden_gmadr_base(vgpu),
+			vgpu_hidden_gmadr_end(vgpu));
+	return ret;
+}
+
+static int cmd_handler_mi_store_data_imm(struct parser_exec_state *s)
+{
+	int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+	int op_size = (cmd_length(s) - 3) * sizeof(u32);
+	int core_id = (cmd_val(s, 2) & (1 << 0)) ? 1 : 0;
+	unsigned long gma, gma_low, gma_high;
+	int ret = 0;
+
+	/* check ppggt */
+	if (!(cmd_val(s, 0) & (1 << 22)))
+		return 0;
+
+	gma = cmd_val(s, 2) & GENMASK(31, 2);
+
+	if (gmadr_bytes == 8) {
+		gma_low = cmd_val(s, 1) & GENMASK(31, 2);
+		gma_high = cmd_val(s, 2) & GENMASK(15, 0);
+		gma = (gma_high << 32) | gma_low;
+		core_id = (cmd_val(s, 1) & (1 << 0)) ? 1 : 0;
+	}
+	ret = cmd_address_audit(s, gma + op_size * core_id, op_size, false);
+	return ret;
+}
+
+static inline int unexpected_cmd(struct parser_exec_state *s)
+{
+	gvt_err("vgpu%d: Unexpected %s in command buffer!\n",
+			s->vgpu->id, s->info->name);
+	return -EINVAL;
+}
+
+static int cmd_handler_mi_semaphore_wait(struct parser_exec_state *s)
+{
+	return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_report_perf_count(struct parser_exec_state *s)
+{
+	return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_op_2e(struct parser_exec_state *s)
+{
+	return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_op_2f(struct parser_exec_state *s)
+{
+	int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+	int op_size = (1 << ((cmd_val(s, 0) & GENMASK(20, 19)) >> 19)) *
+			sizeof(u32);
+	unsigned long gma, gma_high;
+	int ret = 0;
+
+	if (!(cmd_val(s, 0) & (1 << 22)))
+		return ret;
+
+	gma = cmd_val(s, 1) & GENMASK(31, 2);
+	if (gmadr_bytes == 8) {
+		gma_high = cmd_val(s, 2) & GENMASK(15, 0);
+		gma = (gma_high << 32) | gma;
+	}
+	ret = cmd_address_audit(s, gma, op_size, false);
+	return ret;
+}
+
+static int cmd_handler_mi_store_data_index(struct parser_exec_state *s)
+{
+	return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_clflush(struct parser_exec_state *s)
+{
+	return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_conditional_batch_buffer_end(
+		struct parser_exec_state *s)
+{
+	return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_update_gtt(struct parser_exec_state *s)
+{
+	return unexpected_cmd(s);
+}
+
+static int cmd_handler_mi_flush_dw(struct parser_exec_state *s)
+{
+	int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+	unsigned long gma;
+	bool index_mode = false;
+	int ret = 0;
+
+	/* Check post-sync and ppgtt bit */
+	if (((cmd_val(s, 0) >> 14) & 0x3) && (cmd_val(s, 1) & (1 << 2))) {
+		gma = cmd_val(s, 1) & GENMASK(31, 3);
+		if (gmadr_bytes == 8)
+			gma |= (cmd_val(s, 2) & GENMASK(15, 0)) << 32;
+		/* Store Data Index */
+		if (cmd_val(s, 0) & (1 << 21))
+			index_mode = true;
+		ret = cmd_address_audit(s, gma, sizeof(u64), index_mode);
+	}
+	/* Check notify bit */
+	if ((cmd_val(s, 0) & (1 << 8)))
+		set_bit(cmd_interrupt_events[s->ring_id].mi_flush_dw,
+				s->workload->pending_events);
+	return ret;
+}
+
+static void addr_type_update_snb(struct parser_exec_state *s)
+{
+	if ((s->buf_type == RING_BUFFER_INSTRUCTION) &&
+			(BATCH_BUFFER_ADR_SPACE_BIT(cmd_val(s, 0)) == 1)) {
+		s->buf_addr_type = PPGTT_BUFFER;
+	}
+}
+
+
+static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm,
+		unsigned long gma, unsigned long end_gma, void *va)
+{
+	unsigned long copy_len, offset;
+	unsigned long len = 0;
+	unsigned long gpa;
+
+	while (gma != end_gma) {
+		gpa = intel_vgpu_gma_to_gpa(mm, gma);
+		if (gpa == INTEL_GVT_INVALID_ADDR) {
+			gvt_err("invalid gma address: %lx\n", gma);
+			return -EFAULT;
+		}
+
+		offset = gma & (GTT_PAGE_SIZE - 1);
+
+		copy_len = (end_gma - gma) >= (GTT_PAGE_SIZE - offset) ?
+			GTT_PAGE_SIZE - offset : end_gma - gma;
+
+		intel_gvt_hypervisor_read_gpa(vgpu, gpa, va + len, copy_len);
+
+		len += copy_len;
+		gma += copy_len;
+	}
+	return 0;
+}
+
+
+/*
+ * Check whether a batch buffer needs to be scanned. Currently
+ * the only criteria is based on privilege.
+ */
+static int batch_buffer_needs_scan(struct parser_exec_state *s)
+{
+	struct intel_gvt *gvt = s->vgpu->gvt;
+
+	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+		/* BDW decides privilege based on address space */
+		if (cmd_val(s, 0) & (1 << 8))
+			return 0;
+	}
+	return 1;
+}
+
+static uint32_t find_bb_size(struct parser_exec_state *s)
+{
+	unsigned long gma = 0;
+	struct cmd_info *info;
+	uint32_t bb_size = 0;
+	uint32_t cmd_len = 0;
+	bool met_bb_end = false;
+	u32 cmd;
+
+	/* get the start gm address of the batch buffer */
+	gma = get_gma_bb_from_cmd(s, 1);
+	cmd = cmd_val(s, 0);
+
+	info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
+	if (info == NULL) {
+		gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+				cmd, get_opcode(cmd, s->ring_id));
+		return -EINVAL;
+	}
+	do {
+		copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm,
+				gma, gma + 4, &cmd);
+		info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
+		if (info == NULL) {
+			gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+				cmd, get_opcode(cmd, s->ring_id));
+			return -EINVAL;
+		}
+
+		if (info->opcode == OP_MI_BATCH_BUFFER_END) {
+			met_bb_end = true;
+		} else if (info->opcode == OP_MI_BATCH_BUFFER_START) {
+			if (BATCH_BUFFER_2ND_LEVEL_BIT(cmd) == 0) {
+				/* chained batch buffer */
+				met_bb_end = true;
+			}
+		}
+		cmd_len = get_cmd_length(info, cmd) << 2;
+		bb_size += cmd_len;
+		gma += cmd_len;
+
+	} while (!met_bb_end);
+
+	return bb_size;
+}
+
+static int perform_bb_shadow(struct parser_exec_state *s)
+{
+	struct intel_shadow_bb_entry *entry_obj;
+	unsigned long gma = 0;
+	uint32_t bb_size;
+	void *dst = NULL;
+	int ret = 0;
+
+	/* get the start gm address of the batch buffer */
+	gma = get_gma_bb_from_cmd(s, 1);
+
+	/* get the size of the batch buffer */
+	bb_size = find_bb_size(s);
+
+	/* allocate shadow batch buffer */
+	entry_obj = kmalloc(sizeof(*entry_obj), GFP_KERNEL);
+	if (entry_obj == NULL)
+		return -ENOMEM;
+
+	entry_obj->obj =
+		i915_gem_object_create(&(s->vgpu->gvt->dev_priv->drm),
+				       roundup(bb_size, PAGE_SIZE));
+	if (IS_ERR(entry_obj->obj)) {
+		ret = PTR_ERR(entry_obj->obj);
+		goto free_entry;
+	}
+	entry_obj->len = bb_size;
+	INIT_LIST_HEAD(&entry_obj->list);
+
+	dst = i915_gem_object_pin_map(entry_obj->obj, I915_MAP_WB);
+	if (IS_ERR(dst)) {
+		ret = PTR_ERR(dst);
+		goto put_obj;
+	}
+
+	ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false);
+	if (ret) {
+		gvt_err("failed to set shadow batch to CPU\n");
+		goto unmap_src;
+	}
+
+	entry_obj->va = dst;
+	entry_obj->bb_start_cmd_va = s->ip_va;
+
+	/* copy batch buffer to shadow batch buffer*/
+	ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm,
+			      gma, gma + bb_size,
+			      dst);
+	if (ret) {
+		gvt_err("fail to copy guest ring buffer\n");
+		goto unmap_src;
+	}
+
+	list_add(&entry_obj->list, &s->workload->shadow_bb);
+	/*
+	 * ip_va saves the virtual address of the shadow batch buffer, while
+	 * ip_gma saves the graphics address of the original batch buffer.
+	 * As the shadow batch buffer is just a copy from the originial one,
+	 * it should be right to use shadow batch buffer'va and original batch
+	 * buffer's gma in pair. After all, we don't want to pin the shadow
+	 * buffer here (too early).
+	 */
+	s->ip_va = dst;
+	s->ip_gma = gma;
+
+	return 0;
+
+unmap_src:
+	i915_gem_object_unpin_map(entry_obj->obj);
+put_obj:
+	i915_gem_object_put(entry_obj->obj);
+free_entry:
+	kfree(entry_obj);
+	return ret;
+}
+
+static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s)
+{
+	bool second_level;
+	int ret = 0;
+
+	if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) {
+		gvt_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n");
+		return -EINVAL;
+	}
+
+	second_level = BATCH_BUFFER_2ND_LEVEL_BIT(cmd_val(s, 0)) == 1;
+	if (second_level && (s->buf_type != BATCH_BUFFER_INSTRUCTION)) {
+		gvt_err("Jumping to 2nd level BB from RB is not allowed\n");
+		return -EINVAL;
+	}
+
+	s->saved_buf_addr_type = s->buf_addr_type;
+	addr_type_update_snb(s);
+	if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+		s->ret_ip_gma_ring = s->ip_gma + cmd_length(s) * sizeof(u32);
+		s->buf_type = BATCH_BUFFER_INSTRUCTION;
+	} else if (second_level) {
+		s->buf_type = BATCH_BUFFER_2ND_LEVEL;
+		s->ret_ip_gma_bb = s->ip_gma + cmd_length(s) * sizeof(u32);
+		s->ret_bb_va = s->ip_va + cmd_length(s) * sizeof(u32);
+	}
+
+	if (batch_buffer_needs_scan(s)) {
+		ret = perform_bb_shadow(s);
+		if (ret < 0)
+			gvt_err("invalid shadow batch buffer\n");
+	} else {
+		/* emulate a batch buffer end to do return right */
+		ret = cmd_handler_mi_batch_buffer_end(s);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
+}
+
+static struct cmd_info cmd_info[] = {
+	{"MI_NOOP", OP_MI_NOOP, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL},
+
+	{"MI_SET_PREDICATE", OP_MI_SET_PREDICATE, F_LEN_CONST, R_ALL, D_ALL,
+		0, 1, NULL},
+
+	{"MI_USER_INTERRUPT", OP_MI_USER_INTERRUPT, F_LEN_CONST, R_ALL, D_ALL,
+		0, 1, cmd_handler_mi_user_interrupt},
+
+	{"MI_WAIT_FOR_EVENT", OP_MI_WAIT_FOR_EVENT, F_LEN_CONST, R_RCS | R_BCS,
+		D_ALL, 0, 1, cmd_handler_mi_wait_for_event},
+
+	{"MI_FLUSH", OP_MI_FLUSH, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL},
+
+	{"MI_ARB_CHECK", OP_MI_ARB_CHECK, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+		NULL},
+
+	{"MI_RS_CONTROL", OP_MI_RS_CONTROL, F_LEN_CONST, R_RCS, D_ALL, 0, 1,
+		NULL},
+
+	{"MI_REPORT_HEAD", OP_MI_REPORT_HEAD, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+		NULL},
+
+	{"MI_ARB_ON_OFF", OP_MI_ARB_ON_OFF, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+		NULL},
+
+	{"MI_URB_ATOMIC_ALLOC", OP_MI_URB_ATOMIC_ALLOC, F_LEN_CONST, R_RCS,
+		D_ALL, 0, 1, NULL},
+
+	{"MI_BATCH_BUFFER_END", OP_MI_BATCH_BUFFER_END,
+		F_IP_ADVANCE_CUSTOM | F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+		cmd_handler_mi_batch_buffer_end},
+
+	{"MI_SUSPEND_FLUSH", OP_MI_SUSPEND_FLUSH, F_LEN_CONST, R_ALL, D_ALL,
+		0, 1, NULL},
+
+	{"MI_PREDICATE", OP_MI_PREDICATE, F_LEN_CONST, R_RCS, D_ALL, 0, 1,
+		NULL},
+
+	{"MI_TOPOLOGY_FILTER", OP_MI_TOPOLOGY_FILTER, F_LEN_CONST, R_ALL,
+		D_ALL, 0, 1, NULL},
+
+	{"MI_SET_APPID", OP_MI_SET_APPID, F_LEN_CONST, R_ALL, D_ALL, 0, 1,
+		NULL},
+
+	{"MI_RS_CONTEXT", OP_MI_RS_CONTEXT, F_LEN_CONST, R_RCS, D_ALL, 0, 1,
+		NULL},
+
+	{"MI_DISPLAY_FLIP", OP_MI_DISPLAY_FLIP, F_LEN_VAR | F_POST_HANDLE,
+		R_RCS | R_BCS, D_ALL, 0, 8, cmd_handler_mi_display_flip},
+
+	{"MI_SEMAPHORE_MBOX", OP_MI_SEMAPHORE_MBOX, F_LEN_VAR, R_ALL, D_ALL,
+		0, 8, NULL},
+
+	{"MI_MATH", OP_MI_MATH, F_LEN_VAR, R_ALL, D_ALL, 0, 8, NULL},
+
+	{"MI_URB_CLEAR", OP_MI_URB_CLEAR, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"ME_SEMAPHORE_SIGNAL", OP_MI_SEMAPHORE_SIGNAL, F_LEN_VAR, R_ALL,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"ME_SEMAPHORE_WAIT", OP_MI_SEMAPHORE_WAIT, F_LEN_VAR, R_ALL, D_BDW_PLUS,
+		ADDR_FIX_1(2), 8, cmd_handler_mi_semaphore_wait},
+
+	{"MI_STORE_DATA_IMM", OP_MI_STORE_DATA_IMM, F_LEN_VAR, R_ALL, D_BDW_PLUS,
+		ADDR_FIX_1(1), 10, cmd_handler_mi_store_data_imm},
+
+	{"MI_STORE_DATA_INDEX", OP_MI_STORE_DATA_INDEX, F_LEN_VAR, R_ALL, D_ALL,
+		0, 8, cmd_handler_mi_store_data_index},
+
+	{"MI_LOAD_REGISTER_IMM", OP_MI_LOAD_REGISTER_IMM, F_LEN_VAR, R_ALL,
+		D_ALL, 0, 8, cmd_handler_lri},
+
+	{"MI_UPDATE_GTT", OP_MI_UPDATE_GTT, F_LEN_VAR, R_ALL, D_BDW_PLUS, 0, 10,
+		cmd_handler_mi_update_gtt},
+
+	{"MI_STORE_REGISTER_MEM", OP_MI_STORE_REGISTER_MEM, F_LEN_VAR, R_ALL,
+		D_ALL, ADDR_FIX_1(2), 8, cmd_handler_srm},
+
+	{"MI_FLUSH_DW", OP_MI_FLUSH_DW, F_LEN_VAR, R_ALL, D_ALL, 0, 6,
+		cmd_handler_mi_flush_dw},
+
+	{"MI_CLFLUSH", OP_MI_CLFLUSH, F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(1),
+		10, cmd_handler_mi_clflush},
+
+	{"MI_REPORT_PERF_COUNT", OP_MI_REPORT_PERF_COUNT, F_LEN_VAR, R_ALL,
+		D_ALL, ADDR_FIX_1(1), 6, cmd_handler_mi_report_perf_count},
+
+	{"MI_LOAD_REGISTER_MEM", OP_MI_LOAD_REGISTER_MEM, F_LEN_VAR, R_ALL,
+		D_ALL, ADDR_FIX_1(2), 8, cmd_handler_lrm},
+
+	{"MI_LOAD_REGISTER_REG", OP_MI_LOAD_REGISTER_REG, F_LEN_VAR, R_ALL,
+		D_ALL, 0, 8, cmd_handler_lrr},
+
+	{"MI_RS_STORE_DATA_IMM", OP_MI_RS_STORE_DATA_IMM, F_LEN_VAR, R_RCS,
+		D_ALL, 0, 8, NULL},
+
+	{"MI_LOAD_URB_MEM", OP_MI_LOAD_URB_MEM, F_LEN_VAR, R_RCS, D_ALL,
+		ADDR_FIX_1(2), 8, NULL},
+
+	{"MI_STORE_URM_MEM", OP_MI_STORE_URM_MEM, F_LEN_VAR, R_RCS, D_ALL,
+		ADDR_FIX_1(2), 8, NULL},
+
+	{"MI_OP_2E", OP_MI_2E, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_2(1, 2),
+		8, cmd_handler_mi_op_2e},
+
+	{"MI_OP_2F", OP_MI_2F, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_1(1),
+		8, cmd_handler_mi_op_2f},
+
+	{"MI_BATCH_BUFFER_START", OP_MI_BATCH_BUFFER_START,
+		F_IP_ADVANCE_CUSTOM, R_ALL, D_ALL, 0, 8,
+		cmd_handler_mi_batch_buffer_start},
+
+	{"MI_CONDITIONAL_BATCH_BUFFER_END", OP_MI_CONDITIONAL_BATCH_BUFFER_END,
+		F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(2), 8,
+		cmd_handler_mi_conditional_batch_buffer_end},
+
+	{"MI_LOAD_SCAN_LINES_INCL", OP_MI_LOAD_SCAN_LINES_INCL, F_LEN_CONST,
+		R_RCS | R_BCS, D_ALL, 0, 2, NULL},
+
+	{"XY_SETUP_BLT", OP_XY_SETUP_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		ADDR_FIX_2(4, 7), 8, NULL},
+
+	{"XY_SETUP_CLIP_BLT", OP_XY_SETUP_CLIP_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		0, 8, NULL},
+
+	{"XY_SETUP_MONO_PATTERN_SL_BLT", OP_XY_SETUP_MONO_PATTERN_SL_BLT,
+		F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+	{"XY_PIXEL_BLT", OP_XY_PIXEL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL},
+
+	{"XY_SCANLINES_BLT", OP_XY_SCANLINES_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		0, 8, NULL},
+
+	{"XY_TEXT_BLT", OP_XY_TEXT_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		ADDR_FIX_1(3), 8, NULL},
+
+	{"XY_TEXT_IMMEDIATE_BLT", OP_XY_TEXT_IMMEDIATE_BLT, F_LEN_VAR, R_BCS,
+		D_ALL, 0, 8, NULL},
+
+	{"XY_COLOR_BLT", OP_XY_COLOR_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		ADDR_FIX_1(4), 8, NULL},
+
+	{"XY_PAT_BLT", OP_XY_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		ADDR_FIX_2(4, 5), 8, NULL},
+
+	{"XY_MONO_PAT_BLT", OP_XY_MONO_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		ADDR_FIX_1(4), 8, NULL},
+
+	{"XY_SRC_COPY_BLT", OP_XY_SRC_COPY_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		ADDR_FIX_2(4, 7), 8, NULL},
+
+	{"XY_MONO_SRC_COPY_BLT", OP_XY_MONO_SRC_COPY_BLT, F_LEN_VAR, R_BCS,
+		D_ALL, ADDR_FIX_2(4, 5), 8, NULL},
+
+	{"XY_FULL_BLT", OP_XY_FULL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL},
+
+	{"XY_FULL_MONO_SRC_BLT", OP_XY_FULL_MONO_SRC_BLT, F_LEN_VAR, R_BCS,
+		D_ALL, ADDR_FIX_3(4, 5, 8), 8, NULL},
+
+	{"XY_FULL_MONO_PATTERN_BLT", OP_XY_FULL_MONO_PATTERN_BLT, F_LEN_VAR,
+		R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL},
+
+	{"XY_FULL_MONO_PATTERN_MONO_SRC_BLT",
+		OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT,
+		F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL},
+
+	{"XY_MONO_PAT_FIXED_BLT", OP_XY_MONO_PAT_FIXED_BLT, F_LEN_VAR, R_BCS,
+		D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+	{"XY_MONO_SRC_COPY_IMMEDIATE_BLT", OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT,
+		F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+	{"XY_PAT_BLT_IMMEDIATE", OP_XY_PAT_BLT_IMMEDIATE, F_LEN_VAR, R_BCS,
+		D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+	{"XY_SRC_COPY_CHROMA_BLT", OP_XY_SRC_COPY_CHROMA_BLT, F_LEN_VAR, R_BCS,
+		D_ALL, ADDR_FIX_2(4, 7), 8, NULL},
+
+	{"XY_FULL_IMMEDIATE_PATTERN_BLT", OP_XY_FULL_IMMEDIATE_PATTERN_BLT,
+		F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL},
+
+	{"XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT",
+		OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT,
+		F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL},
+
+	{"XY_PAT_CHROMA_BLT", OP_XY_PAT_CHROMA_BLT, F_LEN_VAR, R_BCS, D_ALL,
+		ADDR_FIX_2(4, 5), 8, NULL},
+
+	{"XY_PAT_CHROMA_BLT_IMMEDIATE", OP_XY_PAT_CHROMA_BLT_IMMEDIATE,
+		F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL},
+
+	{"3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP",
+		OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_VIEWPORT_STATE_POINTERS_CC",
+		OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_BLEND_STATE_POINTERS",
+		OP_3DSTATE_BLEND_STATE_POINTERS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DEPTH_STENCIL_STATE_POINTERS",
+		OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_BINDING_TABLE_POINTERS_VS",
+		OP_3DSTATE_BINDING_TABLE_POINTERS_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_BINDING_TABLE_POINTERS_HS",
+		OP_3DSTATE_BINDING_TABLE_POINTERS_HS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_BINDING_TABLE_POINTERS_DS",
+		OP_3DSTATE_BINDING_TABLE_POINTERS_DS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_BINDING_TABLE_POINTERS_GS",
+		OP_3DSTATE_BINDING_TABLE_POINTERS_GS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_BINDING_TABLE_POINTERS_PS",
+		OP_3DSTATE_BINDING_TABLE_POINTERS_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLER_STATE_POINTERS_VS",
+		OP_3DSTATE_SAMPLER_STATE_POINTERS_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLER_STATE_POINTERS_HS",
+		OP_3DSTATE_SAMPLER_STATE_POINTERS_HS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLER_STATE_POINTERS_DS",
+		OP_3DSTATE_SAMPLER_STATE_POINTERS_DS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLER_STATE_POINTERS_GS",
+		OP_3DSTATE_SAMPLER_STATE_POINTERS_GS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLER_STATE_POINTERS_PS",
+		OP_3DSTATE_SAMPLER_STATE_POINTERS_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_URB_VS", OP_3DSTATE_URB_VS, F_LEN_VAR, R_RCS, D_ALL,
+		0, 8, NULL},
+
+	{"3DSTATE_URB_HS", OP_3DSTATE_URB_HS, F_LEN_VAR, R_RCS, D_ALL,
+		0, 8, NULL},
+
+	{"3DSTATE_URB_DS", OP_3DSTATE_URB_DS, F_LEN_VAR, R_RCS, D_ALL,
+		0, 8, NULL},
+
+	{"3DSTATE_URB_GS", OP_3DSTATE_URB_GS, F_LEN_VAR, R_RCS, D_ALL,
+		0, 8, NULL},
+
+	{"3DSTATE_GATHER_CONSTANT_VS", OP_3DSTATE_GATHER_CONSTANT_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_GATHER_CONSTANT_GS", OP_3DSTATE_GATHER_CONSTANT_GS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_GATHER_CONSTANT_HS", OP_3DSTATE_GATHER_CONSTANT_HS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_GATHER_CONSTANT_DS", OP_3DSTATE_GATHER_CONSTANT_DS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_GATHER_CONSTANT_PS", OP_3DSTATE_GATHER_CONSTANT_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_CONSTANTF_VS", OP_3DSTATE_DX9_CONSTANTF_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL},
+
+	{"3DSTATE_DX9_CONSTANTF_PS", OP_3DSTATE_DX9_CONSTANTF_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL},
+
+	{"3DSTATE_DX9_CONSTANTI_VS", OP_3DSTATE_DX9_CONSTANTI_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_CONSTANTI_PS", OP_3DSTATE_DX9_CONSTANTI_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_CONSTANTB_VS", OP_3DSTATE_DX9_CONSTANTB_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_CONSTANTB_PS", OP_3DSTATE_DX9_CONSTANTB_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_LOCAL_VALID_VS", OP_3DSTATE_DX9_LOCAL_VALID_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_LOCAL_VALID_PS", OP_3DSTATE_DX9_LOCAL_VALID_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_GENERATE_ACTIVE_VS", OP_3DSTATE_DX9_GENERATE_ACTIVE_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DX9_GENERATE_ACTIVE_PS", OP_3DSTATE_DX9_GENERATE_ACTIVE_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_BINDING_TABLE_EDIT_VS", OP_3DSTATE_BINDING_TABLE_EDIT_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+	{"3DSTATE_BINDING_TABLE_EDIT_GS", OP_3DSTATE_BINDING_TABLE_EDIT_GS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+	{"3DSTATE_BINDING_TABLE_EDIT_HS", OP_3DSTATE_BINDING_TABLE_EDIT_HS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+	{"3DSTATE_BINDING_TABLE_EDIT_DS", OP_3DSTATE_BINDING_TABLE_EDIT_DS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+	{"3DSTATE_BINDING_TABLE_EDIT_PS", OP_3DSTATE_BINDING_TABLE_EDIT_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL},
+
+	{"3DSTATE_VF_INSTANCING", OP_3DSTATE_VF_INSTANCING, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_VF_SGVS", OP_3DSTATE_VF_SGVS, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+		NULL},
+
+	{"3DSTATE_VF_TOPOLOGY", OP_3DSTATE_VF_TOPOLOGY, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_WM_CHROMAKEY", OP_3DSTATE_WM_CHROMAKEY, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_PS_BLEND", OP_3DSTATE_PS_BLEND, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0,
+		8, NULL},
+
+	{"3DSTATE_WM_DEPTH_STENCIL", OP_3DSTATE_WM_DEPTH_STENCIL, F_LEN_VAR,
+		R_RCS, D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_PS_EXTRA", OP_3DSTATE_PS_EXTRA, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0,
+		8, NULL},
+
+	{"3DSTATE_RASTER", OP_3DSTATE_RASTER, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+		NULL},
+
+	{"3DSTATE_SBE_SWIZ", OP_3DSTATE_SBE_SWIZ, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+		NULL},
+
+	{"3DSTATE_WM_HZ_OP", OP_3DSTATE_WM_HZ_OP, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8,
+		NULL},
+
+	{"3DSTATE_VERTEX_BUFFERS", OP_3DSTATE_VERTEX_BUFFERS, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_VERTEX_ELEMENTS", OP_3DSTATE_VERTEX_ELEMENTS, F_LEN_VAR,
+		R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_INDEX_BUFFER", OP_3DSTATE_INDEX_BUFFER, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, ADDR_FIX_1(2), 8, NULL},
+
+	{"3DSTATE_VF_STATISTICS", OP_3DSTATE_VF_STATISTICS, F_LEN_CONST,
+		R_RCS, D_ALL, 0, 1, NULL},
+
+	{"3DSTATE_VF", OP_3DSTATE_VF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_CC_STATE_POINTERS", OP_3DSTATE_CC_STATE_POINTERS, F_LEN_VAR,
+		R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SCISSOR_STATE_POINTERS", OP_3DSTATE_SCISSOR_STATE_POINTERS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_GS", OP_3DSTATE_GS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_CLIP", OP_3DSTATE_CLIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_WM", OP_3DSTATE_WM, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_CONSTANT_GS", OP_3DSTATE_CONSTANT_GS, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_CONSTANT_PS", OP_3DSTATE_CONSTANT_PS, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLE_MASK", OP_3DSTATE_SAMPLE_MASK, F_LEN_VAR, R_RCS,
+		D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_CONSTANT_HS", OP_3DSTATE_CONSTANT_HS, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_CONSTANT_DS", OP_3DSTATE_CONSTANT_DS, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_HS", OP_3DSTATE_HS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_TE", OP_3DSTATE_TE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DS", OP_3DSTATE_DS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_STREAMOUT", OP_3DSTATE_STREAMOUT, F_LEN_VAR, R_RCS,
+		D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SBE", OP_3DSTATE_SBE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_PS", OP_3DSTATE_PS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_DRAWING_RECTANGLE", OP_3DSTATE_DRAWING_RECTANGLE, F_LEN_VAR,
+		R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLER_PALETTE_LOAD0", OP_3DSTATE_SAMPLER_PALETTE_LOAD0,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_CHROMA_KEY", OP_3DSTATE_CHROMA_KEY, F_LEN_VAR, R_RCS, D_ALL,
+		0, 8, NULL},
+
+	{"3DSTATE_DEPTH_BUFFER", OP_3DSTATE_DEPTH_BUFFER, F_LEN_VAR, R_RCS,
+		D_ALL, ADDR_FIX_1(2), 8, NULL},
+
+	{"3DSTATE_POLY_STIPPLE_OFFSET", OP_3DSTATE_POLY_STIPPLE_OFFSET,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_POLY_STIPPLE_PATTERN", OP_3DSTATE_POLY_STIPPLE_PATTERN,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_LINE_STIPPLE", OP_3DSTATE_LINE_STIPPLE, F_LEN_VAR, R_RCS,
+		D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_AA_LINE_PARAMS", OP_3DSTATE_AA_LINE_PARAMS, F_LEN_VAR, R_RCS,
+		D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_GS_SVB_INDEX", OP_3DSTATE_GS_SVB_INDEX, F_LEN_VAR, R_RCS,
+		D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SAMPLER_PALETTE_LOAD1", OP_3DSTATE_SAMPLER_PALETTE_LOAD1,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_MULTISAMPLE", OP_3DSTATE_MULTISAMPLE_BDW, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"3DSTATE_STENCIL_BUFFER", OP_3DSTATE_STENCIL_BUFFER, F_LEN_VAR, R_RCS,
+		D_ALL, ADDR_FIX_1(2), 8, NULL},
+
+	{"3DSTATE_HIER_DEPTH_BUFFER", OP_3DSTATE_HIER_DEPTH_BUFFER, F_LEN_VAR,
+		R_RCS, D_ALL, ADDR_FIX_1(2), 8, NULL},
+
+	{"3DSTATE_CLEAR_PARAMS", OP_3DSTATE_CLEAR_PARAMS, F_LEN_VAR,
+		R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_PUSH_CONSTANT_ALLOC_VS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_PUSH_CONSTANT_ALLOC_HS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_PUSH_CONSTANT_ALLOC_DS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_PUSH_CONSTANT_ALLOC_GS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_PUSH_CONSTANT_ALLOC_PS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_MONOFILTER_SIZE", OP_3DSTATE_MONOFILTER_SIZE, F_LEN_VAR,
+		R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SO_DECL_LIST", OP_3DSTATE_SO_DECL_LIST, F_LEN_VAR, R_RCS,
+		D_ALL, 0, 9, NULL},
+
+	{"3DSTATE_SO_BUFFER", OP_3DSTATE_SO_BUFFER, F_LEN_VAR, R_RCS, D_BDW_PLUS,
+		ADDR_FIX_2(2, 4), 8, NULL},
+
+	{"3DSTATE_BINDING_TABLE_POOL_ALLOC",
+		OP_3DSTATE_BINDING_TABLE_POOL_ALLOC,
+		F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL},
+
+	{"3DSTATE_GATHER_POOL_ALLOC", OP_3DSTATE_GATHER_POOL_ALLOC,
+		F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL},
+
+	{"3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC",
+		OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC,
+		F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL},
+
+	{"3DSTATE_SAMPLE_PATTERN", OP_3DSTATE_SAMPLE_PATTERN, F_LEN_VAR, R_RCS,
+		D_BDW_PLUS, 0, 8, NULL},
+
+	{"PIPE_CONTROL", OP_PIPE_CONTROL, F_LEN_VAR, R_RCS, D_ALL,
+		ADDR_FIX_1(2), 8, cmd_handler_pipe_control},
+
+	{"3DPRIMITIVE", OP_3DPRIMITIVE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"PIPELINE_SELECT", OP_PIPELINE_SELECT, F_LEN_CONST, R_RCS, D_ALL, 0,
+		1, NULL},
+
+	{"STATE_PREFETCH", OP_STATE_PREFETCH, F_LEN_VAR, R_RCS, D_ALL,
+		ADDR_FIX_1(1), 8, NULL},
+
+	{"STATE_SIP", OP_STATE_SIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"STATE_BASE_ADDRESS", OP_STATE_BASE_ADDRESS, F_LEN_VAR, R_RCS, D_BDW_PLUS,
+		ADDR_FIX_5(1, 3, 4, 5, 6), 8, NULL},
+
+	{"OP_3D_MEDIA_0_1_4", OP_3D_MEDIA_0_1_4, F_LEN_VAR, R_RCS, D_ALL,
+		ADDR_FIX_1(1), 8, NULL},
+
+	{"3DSTATE_VS", OP_3DSTATE_VS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_SF", OP_3DSTATE_SF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL},
+
+	{"3DSTATE_CONSTANT_VS", OP_3DSTATE_CONSTANT_VS, F_LEN_VAR, R_RCS, D_BDW_PLUS,
+		0, 8, NULL},
+
+	{"3DSTATE_COMPONENT_PACKING", OP_3DSTATE_COMPONENT_PACKING, F_LEN_VAR, R_RCS,
+		D_SKL_PLUS, 0, 8, NULL},
+
+	{"MEDIA_INTERFACE_DESCRIPTOR_LOAD", OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD,
+		F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL},
+
+	{"MEDIA_GATEWAY_STATE", OP_MEDIA_GATEWAY_STATE, F_LEN_VAR, R_RCS, D_ALL,
+		0, 16, NULL},
+
+	{"MEDIA_STATE_FLUSH", OP_MEDIA_STATE_FLUSH, F_LEN_VAR, R_RCS, D_ALL,
+		0, 16, NULL},
+
+	{"MEDIA_OBJECT", OP_MEDIA_OBJECT, F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL},
+
+	{"MEDIA_CURBE_LOAD", OP_MEDIA_CURBE_LOAD, F_LEN_VAR, R_RCS, D_ALL,
+		0, 16, NULL},
+
+	{"MEDIA_OBJECT_PRT", OP_MEDIA_OBJECT_PRT, F_LEN_VAR, R_RCS, D_ALL,
+		0, 16, NULL},
+
+	{"MEDIA_OBJECT_WALKER", OP_MEDIA_OBJECT_WALKER, F_LEN_VAR, R_RCS, D_ALL,
+		0, 16, NULL},
+
+	{"GPGPU_WALKER", OP_GPGPU_WALKER, F_LEN_VAR, R_RCS, D_ALL,
+		0, 8, NULL},
+
+	{"MEDIA_VFE_STATE", OP_MEDIA_VFE_STATE, F_LEN_VAR, R_RCS, D_ALL, 0, 16,
+		NULL},
+
+	{"3DSTATE_VF_STATISTICS_GM45", OP_3DSTATE_VF_STATISTICS_GM45,
+		F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL},
+
+	{"MFX_PIPE_MODE_SELECT", OP_MFX_PIPE_MODE_SELECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_SURFACE_STATE", OP_MFX_SURFACE_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_PIPE_BUF_ADDR_STATE", OP_MFX_PIPE_BUF_ADDR_STATE, F_LEN_VAR,
+		R_VCS, D_BDW_PLUS, 0, 12, NULL},
+
+	{"MFX_IND_OBJ_BASE_ADDR_STATE", OP_MFX_IND_OBJ_BASE_ADDR_STATE,
+		F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL},
+
+	{"MFX_BSP_BUF_BASE_ADDR_STATE", OP_MFX_BSP_BUF_BASE_ADDR_STATE,
+		F_LEN_VAR, R_VCS, D_BDW_PLUS, ADDR_FIX_3(1, 3, 5), 12, NULL},
+
+	{"OP_2_0_0_5", OP_2_0_0_5, F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL},
+
+	{"MFX_STATE_POINTER", OP_MFX_STATE_POINTER, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_QM_STATE", OP_MFX_QM_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_FQM_STATE", OP_MFX_FQM_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_PAK_INSERT_OBJECT", OP_MFX_PAK_INSERT_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_STITCH_OBJECT", OP_MFX_STITCH_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_IT_OBJECT", OP_MFD_IT_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_WAIT", OP_MFX_WAIT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 6, NULL},
+
+	{"MFX_AVC_IMG_STATE", OP_MFX_AVC_IMG_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_AVC_QM_STATE", OP_MFX_AVC_QM_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_AVC_DIRECTMODE_STATE", OP_MFX_AVC_DIRECTMODE_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_AVC_SLICE_STATE", OP_MFX_AVC_SLICE_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_AVC_REF_IDX_STATE", OP_MFX_AVC_REF_IDX_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_AVC_WEIGHTOFFSET_STATE", OP_MFX_AVC_WEIGHTOFFSET_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_AVC_PICID_STATE", OP_MFD_AVC_PICID_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+	{"MFD_AVC_DPB_STATE", OP_MFD_AVC_DPB_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_AVC_BSD_OBJECT", OP_MFD_AVC_BSD_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_AVC_SLICEADDR", OP_MFD_AVC_SLICEADDR, F_LEN_VAR,
+		R_VCS, D_ALL, ADDR_FIX_1(2), 12, NULL},
+
+	{"MFC_AVC_PAK_OBJECT", OP_MFC_AVC_PAK_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_VC1_PRED_PIPE_STATE", OP_MFX_VC1_PRED_PIPE_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_VC1_DIRECTMODE_STATE", OP_MFX_VC1_DIRECTMODE_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_VC1_SHORT_PIC_STATE", OP_MFD_VC1_SHORT_PIC_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_VC1_LONG_PIC_STATE", OP_MFD_VC1_LONG_PIC_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_VC1_BSD_OBJECT", OP_MFD_VC1_BSD_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFC_MPEG2_SLICEGROUP_STATE", OP_MFC_MPEG2_SLICEGROUP_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFC_MPEG2_PAK_OBJECT", OP_MFC_MPEG2_PAK_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_MPEG2_PIC_STATE", OP_MFX_MPEG2_PIC_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_MPEG2_QM_STATE", OP_MFX_MPEG2_QM_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_MPEG2_BSD_OBJECT", OP_MFD_MPEG2_BSD_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_2_6_0_0", OP_MFX_2_6_0_0, F_LEN_VAR, R_VCS, D_ALL,
+		0, 16, NULL},
+
+	{"MFX_2_6_0_9", OP_MFX_2_6_0_9, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL},
+
+	{"MFX_2_6_0_8", OP_MFX_2_6_0_8, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL},
+
+	{"MFX_JPEG_PIC_STATE", OP_MFX_JPEG_PIC_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFX_JPEG_HUFF_TABLE_STATE", OP_MFX_JPEG_HUFF_TABLE_STATE, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"MFD_JPEG_BSD_OBJECT", OP_MFD_JPEG_BSD_OBJECT, F_LEN_VAR,
+		R_VCS, D_ALL, 0, 12, NULL},
+
+	{"VEBOX_STATE", OP_VEB_STATE, F_LEN_VAR, R_VECS, D_ALL, 0, 12, NULL},
+
+	{"VEBOX_SURFACE_STATE", OP_VEB_SURFACE_STATE, F_LEN_VAR, R_VECS, D_ALL,
+		0, 12, NULL},
+
+	{"VEB_DI_IECP", OP_VEB_DNDI_IECP_STATE, F_LEN_VAR, R_VECS, D_BDW_PLUS,
+		0, 20, NULL},
+};
+
+static void add_cmd_entry(struct intel_gvt *gvt, struct cmd_entry *e)
+{
+	hash_add(gvt->cmd_table, &e->hlist, e->info->opcode);
+}
+
+#define GVT_MAX_CMD_LENGTH     20  /* In Dword */
+
+static void trace_cs_command(struct parser_exec_state *s,
+		cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler)
+{
+	/* This buffer is used by ftrace to store all commands copied from
+	 * guest gma space. Sometimes commands can cross pages, this should
+	 * not be handled in ftrace logic. So this is just used as a
+	 * 'bounce buffer'
+	 */
+	u32 cmd_trace_buf[GVT_MAX_CMD_LENGTH];
+	int i;
+	u32 cmd_len = cmd_length(s);
+	/* The chosen value of GVT_MAX_CMD_LENGTH are just based on
+	 * following two considerations:
+	 * 1) From observation, most common ring commands is not that long.
+	 *    But there are execeptions. So it indeed makes sence to observe
+	 *    longer commands.
+	 * 2) From the performance and debugging point of view, dumping all
+	 *    contents of very commands is not necessary.
+	 * We mgith shrink GVT_MAX_CMD_LENGTH or remove this trace event in
+	 * future for performance considerations.
+	 */
+	if (unlikely(cmd_len > GVT_MAX_CMD_LENGTH)) {
+		gvt_dbg_cmd("cmd length exceed tracing limitation!\n");
+		cmd_len = GVT_MAX_CMD_LENGTH;
+	}
+
+	for (i = 0; i < cmd_len; i++)
+		cmd_trace_buf[i] = cmd_val(s, i);
+
+	trace_gvt_command(s->vgpu->id, s->ring_id, s->ip_gma, cmd_trace_buf,
+			cmd_len, s->buf_type == RING_BUFFER_INSTRUCTION,
+			cost_pre_cmd_handler, cost_cmd_handler);
+}
+
+/* call the cmd handler, and advance ip */
+static int cmd_parser_exec(struct parser_exec_state *s)
+{
+	struct cmd_info *info;
+	u32 cmd;
+	int ret = 0;
+	cycles_t t0, t1, t2;
+	struct parser_exec_state s_before_advance_custom;
+
+	t0 = get_cycles();
+
+	cmd = cmd_val(s, 0);
+
+	info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id);
+	if (info == NULL) {
+		gvt_err("unknown cmd 0x%x, opcode=0x%x\n",
+				cmd, get_opcode(cmd, s->ring_id));
+		return -EINVAL;
+	}
+
+	gvt_dbg_cmd("%s\n", info->name);
+
+	s->info = info;
+
+	t1 = get_cycles();
+
+	memcpy(&s_before_advance_custom, s, sizeof(struct parser_exec_state));
+
+	if (info->handler) {
+		ret = info->handler(s);
+		if (ret < 0) {
+			gvt_err("%s handler error\n", info->name);
+			return ret;
+		}
+	}
+	t2 = get_cycles();
+
+	trace_cs_command(&s_before_advance_custom, t1 - t0, t2 - t1);
+
+	if (!(info->flag & F_IP_ADVANCE_CUSTOM)) {
+		ret = cmd_advance_default(s);
+		if (ret) {
+			gvt_err("%s IP advance error\n", info->name);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static inline bool gma_out_of_range(unsigned long gma,
+		unsigned long gma_head, unsigned int gma_tail)
+{
+	if (gma_tail >= gma_head)
+		return (gma < gma_head) || (gma > gma_tail);
+	else
+		return (gma > gma_tail) && (gma < gma_head);
+}
+
+static int command_scan(struct parser_exec_state *s,
+		unsigned long rb_head, unsigned long rb_tail,
+		unsigned long rb_start, unsigned long rb_len)
+{
+
+	unsigned long gma_head, gma_tail, gma_bottom;
+	int ret = 0;
+
+	gma_head = rb_start + rb_head;
+	gma_tail = rb_start + rb_tail;
+	gma_bottom = rb_start +  rb_len;
+
+	gvt_dbg_cmd("scan_start: start=%lx end=%lx\n", gma_head, gma_tail);
+
+	while (s->ip_gma != gma_tail) {
+		if (s->buf_type == RING_BUFFER_INSTRUCTION) {
+			if (!(s->ip_gma >= rb_start) ||
+				!(s->ip_gma < gma_bottom)) {
+				gvt_err("ip_gma %lx out of ring scope."
+					"(base:0x%lx, bottom: 0x%lx)\n",
+					s->ip_gma, rb_start,
+					gma_bottom);
+				parser_exec_state_dump(s);
+				return -EINVAL;
+			}
+			if (gma_out_of_range(s->ip_gma, gma_head, gma_tail)) {
+				gvt_err("ip_gma %lx out of range."
+					"base 0x%lx head 0x%lx tail 0x%lx\n",
+					s->ip_gma, rb_start,
+					rb_head, rb_tail);
+				parser_exec_state_dump(s);
+				break;
+			}
+		}
+		ret = cmd_parser_exec(s);
+		if (ret) {
+			gvt_err("cmd parser error\n");
+			parser_exec_state_dump(s);
+			break;
+		}
+	}
+
+	gvt_dbg_cmd("scan_end\n");
+
+	return ret;
+}
+
+static int scan_workload(struct intel_vgpu_workload *workload)
+{
+	unsigned long gma_head, gma_tail, gma_bottom;
+	struct parser_exec_state s;
+	int ret = 0;
+
+	/* ring base is page aligned */
+	if (WARN_ON(!IS_ALIGNED(workload->rb_start, GTT_PAGE_SIZE)))
+		return -EINVAL;
+
+	gma_head = workload->rb_start + workload->rb_head;
+	gma_tail = workload->rb_start + workload->rb_tail;
+	gma_bottom = workload->rb_start +  _RING_CTL_BUF_SIZE(workload->rb_ctl);
+
+	s.buf_type = RING_BUFFER_INSTRUCTION;
+	s.buf_addr_type = GTT_BUFFER;
+	s.vgpu = workload->vgpu;
+	s.ring_id = workload->ring_id;
+	s.ring_start = workload->rb_start;
+	s.ring_size = _RING_CTL_BUF_SIZE(workload->rb_ctl);
+	s.ring_head = gma_head;
+	s.ring_tail = gma_tail;
+	s.rb_va = workload->shadow_ring_buffer_va;
+	s.workload = workload;
+
+	if ((bypass_scan_mask & (1 << workload->ring_id)) ||
+		gma_head == gma_tail)
+		return 0;
+
+	ret = ip_gma_set(&s, gma_head);
+	if (ret)
+		goto out;
+
+	ret = command_scan(&s, workload->rb_head, workload->rb_tail,
+		workload->rb_start, _RING_CTL_BUF_SIZE(workload->rb_ctl));
+
+out:
+	return ret;
+}
+
+static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+
+	unsigned long gma_head, gma_tail, gma_bottom, ring_size, ring_tail;
+	struct parser_exec_state s;
+	int ret = 0;
+
+	/* ring base is page aligned */
+	if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, GTT_PAGE_SIZE)))
+		return -EINVAL;
+
+	ring_tail = wa_ctx->indirect_ctx.size + 3 * sizeof(uint32_t);
+	ring_size = round_up(wa_ctx->indirect_ctx.size + CACHELINE_BYTES,
+			PAGE_SIZE);
+	gma_head = wa_ctx->indirect_ctx.guest_gma;
+	gma_tail = wa_ctx->indirect_ctx.guest_gma + ring_tail;
+	gma_bottom = wa_ctx->indirect_ctx.guest_gma + ring_size;
+
+	s.buf_type = RING_BUFFER_INSTRUCTION;
+	s.buf_addr_type = GTT_BUFFER;
+	s.vgpu = wa_ctx->workload->vgpu;
+	s.ring_id = wa_ctx->workload->ring_id;
+	s.ring_start = wa_ctx->indirect_ctx.guest_gma;
+	s.ring_size = ring_size;
+	s.ring_head = gma_head;
+	s.ring_tail = gma_tail;
+	s.rb_va = wa_ctx->indirect_ctx.shadow_va;
+	s.workload = wa_ctx->workload;
+
+	ret = ip_gma_set(&s, gma_head);
+	if (ret)
+		goto out;
+
+	ret = command_scan(&s, 0, ring_tail,
+		wa_ctx->indirect_ctx.guest_gma, ring_size);
+out:
+	return ret;
+}
+
+static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
+{
+	struct intel_vgpu *vgpu = workload->vgpu;
+	int ring_id = workload->ring_id;
+	struct i915_gem_context *shadow_ctx = vgpu->shadow_ctx;
+	struct intel_ring *ring = shadow_ctx->engine[ring_id].ring;
+	unsigned long gma_head, gma_tail, gma_top, guest_rb_size;
+	unsigned int copy_len = 0;
+	int ret;
+
+	guest_rb_size = _RING_CTL_BUF_SIZE(workload->rb_ctl);
+
+	/* calculate workload ring buffer size */
+	workload->rb_len = (workload->rb_tail + guest_rb_size -
+			workload->rb_head) % guest_rb_size;
+
+	gma_head = workload->rb_start + workload->rb_head;
+	gma_tail = workload->rb_start + workload->rb_tail;
+	gma_top = workload->rb_start + guest_rb_size;
+
+	/* allocate shadow ring buffer */
+	ret = intel_ring_begin(workload->req, workload->rb_len / 4);
+	if (ret)
+		return ret;
+
+	/* get shadow ring buffer va */
+	workload->shadow_ring_buffer_va = ring->vaddr + ring->tail;
+
+	/* head > tail --> copy head <-> top */
+	if (gma_head > gma_tail) {
+		ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm,
+				gma_head, gma_top,
+				workload->shadow_ring_buffer_va);
+		if (ret) {
+			gvt_err("fail to copy guest ring buffer\n");
+			return ret;
+		}
+		copy_len = gma_top - gma_head;
+		gma_head = workload->rb_start;
+	}
+
+	/* copy head or start <-> tail */
+	ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm,
+			gma_head, gma_tail,
+			workload->shadow_ring_buffer_va + copy_len);
+	if (ret) {
+		gvt_err("fail to copy guest ring buffer\n");
+		return ret;
+	}
+	ring->tail += workload->rb_len;
+	intel_ring_advance(ring);
+	return 0;
+}
+
+int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
+{
+	int ret;
+
+	ret = shadow_workload_ring_buffer(workload);
+	if (ret) {
+		gvt_err("fail to shadow workload ring_buffer\n");
+		return ret;
+	}
+
+	ret = scan_workload(workload);
+	if (ret) {
+		gvt_err("scan workload error\n");
+		return ret;
+	}
+	return 0;
+}
+
+static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+	struct drm_device *dev = &wa_ctx->workload->vgpu->gvt->dev_priv->drm;
+	int ctx_size = wa_ctx->indirect_ctx.size;
+	unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma;
+	struct drm_i915_gem_object *obj;
+	int ret = 0;
+	void *map;
+
+	obj = i915_gem_object_create(dev,
+				     roundup(ctx_size + CACHELINE_BYTES,
+					     PAGE_SIZE));
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	/* get the va of the shadow batch buffer */
+	map = i915_gem_object_pin_map(obj, I915_MAP_WB);
+	if (IS_ERR(map)) {
+		gvt_err("failed to vmap shadow indirect ctx\n");
+		ret = PTR_ERR(map);
+		goto put_obj;
+	}
+
+	ret = i915_gem_object_set_to_cpu_domain(obj, false);
+	if (ret) {
+		gvt_err("failed to set shadow indirect ctx to CPU\n");
+		goto unmap_src;
+	}
+
+	ret = copy_gma_to_hva(wa_ctx->workload->vgpu,
+				wa_ctx->workload->vgpu->gtt.ggtt_mm,
+				guest_gma, guest_gma + ctx_size,
+				map);
+	if (ret) {
+		gvt_err("fail to copy guest indirect ctx\n");
+		goto unmap_src;
+	}
+
+	wa_ctx->indirect_ctx.obj = obj;
+	wa_ctx->indirect_ctx.shadow_va = map;
+	return 0;
+
+unmap_src:
+	i915_gem_object_unpin_map(obj);
+put_obj:
+	i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+	return ret;
+}
+
+static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+	uint32_t per_ctx_start[CACHELINE_DWORDS] = {0};
+	unsigned char *bb_start_sva;
+
+	per_ctx_start[0] = 0x18800001;
+	per_ctx_start[1] = wa_ctx->per_ctx.guest_gma;
+
+	bb_start_sva = (unsigned char *)wa_ctx->indirect_ctx.shadow_va +
+				wa_ctx->indirect_ctx.size;
+
+	memcpy(bb_start_sva, per_ctx_start, CACHELINE_BYTES);
+
+	return 0;
+}
+
+int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+	int ret;
+
+	if (wa_ctx->indirect_ctx.size == 0)
+		return 0;
+
+	ret = shadow_indirect_ctx(wa_ctx);
+	if (ret) {
+		gvt_err("fail to shadow indirect ctx\n");
+		return ret;
+	}
+
+	combine_wa_ctx(wa_ctx);
+
+	ret = scan_wa_ctx(wa_ctx);
+	if (ret) {
+		gvt_err("scan wa ctx error\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct cmd_info *find_cmd_entry_any_ring(struct intel_gvt *gvt,
+		unsigned int opcode, int rings)
+{
+	struct cmd_info *info = NULL;
+	unsigned int ring;
+
+	for_each_set_bit(ring, (unsigned long *)&rings, I915_NUM_ENGINES) {
+		info = find_cmd_entry(gvt, opcode, ring);
+		if (info)
+			break;
+	}
+	return info;
+}
+
+static int init_cmd_table(struct intel_gvt *gvt)
+{
+	int i;
+	struct cmd_entry *e;
+	struct cmd_info	*info;
+	unsigned int gen_type;
+
+	gen_type = intel_gvt_get_device_type(gvt);
+
+	for (i = 0; i < ARRAY_SIZE(cmd_info); i++) {
+		if (!(cmd_info[i].devices & gen_type))
+			continue;
+
+		e = kzalloc(sizeof(*e), GFP_KERNEL);
+		if (!e)
+			return -ENOMEM;
+
+		e->info = &cmd_info[i];
+		info = find_cmd_entry_any_ring(gvt,
+				e->info->opcode, e->info->rings);
+		if (info) {
+			gvt_err("%s %s duplicated\n", e->info->name,
+					info->name);
+			return -EEXIST;
+		}
+
+		INIT_HLIST_NODE(&e->hlist);
+		add_cmd_entry(gvt, e);
+		gvt_dbg_cmd("add %-30s op %04x flag %x devs %02x rings %02x\n",
+				e->info->name, e->info->opcode, e->info->flag,
+				e->info->devices, e->info->rings);
+	}
+	return 0;
+}
+
+static void clean_cmd_table(struct intel_gvt *gvt)
+{
+	struct hlist_node *tmp;
+	struct cmd_entry *e;
+	int i;
+
+	hash_for_each_safe(gvt->cmd_table, i, tmp, e, hlist)
+		kfree(e);
+
+	hash_init(gvt->cmd_table);
+}
+
+void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt)
+{
+	clean_cmd_table(gvt);
+}
+
+int intel_gvt_init_cmd_parser(struct intel_gvt *gvt)
+{
+	int ret;
+
+	ret = init_cmd_table(gvt);
+	if (ret) {
+		intel_gvt_clean_cmd_parser(gvt);
+		return ret;
+	}
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/cmd_parser.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,49 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Yulei Zhang <yulei.zhang@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+#ifndef _GVT_CMD_PARSER_H_
+#define _GVT_CMD_PARSER_H_
+
+#define GVT_CMD_HASH_BITS 7
+
+void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt);
+
+int intel_gvt_init_cmd_parser(struct intel_gvt *gvt);
+
+int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload);
+
+int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/debug.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/debug.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/debug.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/debug.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,11 +24,34 @@
 #ifndef __GVT_DEBUG_H__
 #define __GVT_DEBUG_H__
 
+#define gvt_err(fmt, args...) \
+	DRM_ERROR("gvt: "fmt, ##args)
+
 #define gvt_dbg_core(fmt, args...) \
 	DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args)
 
-/*
- * Other GVT debug stuff will be introduced in the GVT device model patches.
- */
+#define gvt_dbg_irq(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: irq: "fmt, ##args)
+
+#define gvt_dbg_mm(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: mm: "fmt, ##args)
+
+#define gvt_dbg_mmio(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: mmio: "fmt, ##args)
+
+#define gvt_dbg_dpy(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: dpy: "fmt, ##args)
+
+#define gvt_dbg_el(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: el: "fmt, ##args)
+
+#define gvt_dbg_sched(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: sched: "fmt, ##args)
+
+#define gvt_dbg_render(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: render: "fmt, ##args)
+
+#define gvt_dbg_cmd(fmt, args...) \
+	DRM_DEBUG_DRIVER("gvt: cmd: "fmt, ##args)
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/display.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/display.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,330 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Terrence Xu <terrence.xu@intel.com>
+ *    Changbin Du <changbin.du@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+static int get_edp_pipe(struct intel_vgpu *vgpu)
+{
+	u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP);
+	int pipe = -1;
+
+	switch (data & TRANS_DDI_EDP_INPUT_MASK) {
+	case TRANS_DDI_EDP_INPUT_A_ON:
+	case TRANS_DDI_EDP_INPUT_A_ONOFF:
+		pipe = PIPE_A;
+		break;
+	case TRANS_DDI_EDP_INPUT_B_ONOFF:
+		pipe = PIPE_B;
+		break;
+	case TRANS_DDI_EDP_INPUT_C_ONOFF:
+		pipe = PIPE_C;
+		break;
+	}
+	return pipe;
+}
+
+static int edp_pipe_is_enabled(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	if (!(vgpu_vreg(vgpu, PIPECONF(_PIPE_EDP)) & PIPECONF_ENABLE))
+		return 0;
+
+	if (!(vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP) & TRANS_DDI_FUNC_ENABLE))
+		return 0;
+	return 1;
+}
+
+static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	if (WARN_ON(pipe < PIPE_A || pipe >= I915_MAX_PIPES))
+		return -EINVAL;
+
+	if (vgpu_vreg(vgpu, PIPECONF(pipe)) & PIPECONF_ENABLE)
+		return 1;
+
+	if (edp_pipe_is_enabled(vgpu) &&
+			get_edp_pipe(vgpu) == pipe)
+		return 1;
+	return 0;
+}
+
+/* EDID with 1024x768 as its resolution */
+static unsigned char virtual_dp_monitor_edid[] = {
+	/*Header*/
+	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+	/* Vendor & Product Identification */
+	0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17,
+	/* Version & Revision */
+	0x01, 0x04,
+	/* Basic Display Parameters & Features */
+	0xa5, 0x34, 0x20, 0x78, 0x23,
+	/* Color Characteristics */
+	0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54,
+	/* Established Timings: maximum resolution is 1024x768 */
+	0x21, 0x08, 0x00,
+	/* Standard Timings. All invalid */
+	0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00,
+	0x00, 0x40, 0x00, 0x00, 0x00, 0x01,
+	/* 18 Byte Data Blocks 1: invalid */
+	0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0,
+	0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a,
+	/* 18 Byte Data Blocks 2: invalid */
+	0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+	/* 18 Byte Data Blocks 3: invalid */
+	0x00, 0x00, 0x00, 0xfc, 0x00, 0x48,
+	0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20,
+	/* 18 Byte Data Blocks 4: invalid */
+	0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30,
+	0x44, 0x58, 0x51, 0x0a, 0x20, 0x20,
+	/* Extension Block Count */
+	0x00,
+	/* Checksum */
+	0xef,
+};
+
+#define DPCD_HEADER_SIZE        0xb
+
+static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = {
+	0x11, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTB_HOTPLUG_CPT |
+			SDE_PORTC_HOTPLUG_CPT |
+			SDE_PORTD_HOTPLUG_CPT);
+
+	if (IS_SKYLAKE(dev_priv))
+		vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT |
+				SDE_PORTE_HOTPLUG_SPT);
+
+	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B))
+		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT;
+
+	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C))
+		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT;
+
+	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D))
+		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT;
+
+	if (IS_SKYLAKE(dev_priv) &&
+			intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) {
+		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT;
+	}
+
+	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+		if (IS_BROADWELL(dev_priv))
+			vgpu_vreg(vgpu, GEN8_DE_PORT_ISR) |=
+				GEN8_PORT_DP_A_HOTPLUG;
+		else
+			vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT;
+	}
+}
+
+static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num)
+{
+	struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);
+
+	kfree(port->edid);
+	port->edid = NULL;
+
+	kfree(port->dpcd);
+	port->dpcd = NULL;
+}
+
+static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
+		int type)
+{
+	struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);
+
+	port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL);
+	if (!port->edid)
+		return -ENOMEM;
+
+	port->dpcd = kzalloc(sizeof(*(port->dpcd)), GFP_KERNEL);
+	if (!port->dpcd) {
+		kfree(port->edid);
+		return -ENOMEM;
+	}
+
+	memcpy(port->edid->edid_block, virtual_dp_monitor_edid,
+			EDID_SIZE);
+	port->edid->data_valid = true;
+
+	memcpy(port->dpcd->data, dpcd_fix_data, DPCD_HEADER_SIZE);
+	port->dpcd->data_valid = true;
+	port->dpcd->data[DPCD_SINK_COUNT] = 0x1;
+	port->type = type;
+
+	emulate_monitor_status_change(vgpu);
+	return 0;
+}
+
+/**
+ * intel_gvt_check_vblank_emulation - check if vblank emulation timer should
+ * be turned on/off when a virtual pipe is enabled/disabled.
+ * @gvt: a GVT device
+ *
+ * This function is used to turn on/off vblank timer according to currently
+ * enabled/disabled virtual pipes.
+ *
+ */
+void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt)
+{
+	struct intel_gvt_irq *irq = &gvt->irq;
+	struct intel_vgpu *vgpu;
+	bool have_enabled_pipe = false;
+	int pipe, id;
+
+	if (WARN_ON(!mutex_is_locked(&gvt->lock)))
+		return;
+
+	hrtimer_cancel(&irq->vblank_timer.timer);
+
+	for_each_active_vgpu(gvt, vgpu, id) {
+		for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) {
+			have_enabled_pipe =
+				pipe_is_enabled(vgpu, pipe);
+			if (have_enabled_pipe)
+				break;
+		}
+	}
+
+	if (have_enabled_pipe)
+		hrtimer_start(&irq->vblank_timer.timer,
+			ktime_add_ns(ktime_get(), irq->vblank_timer.period),
+			HRTIMER_MODE_ABS);
+}
+
+static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct intel_vgpu_irq *irq = &vgpu->irq;
+	int vblank_event[] = {
+		[PIPE_A] = PIPE_A_VBLANK,
+		[PIPE_B] = PIPE_B_VBLANK,
+		[PIPE_C] = PIPE_C_VBLANK,
+	};
+	int event;
+
+	if (pipe < PIPE_A || pipe > PIPE_C)
+		return;
+
+	for_each_set_bit(event, irq->flip_done_event[pipe],
+			INTEL_GVT_EVENT_MAX) {
+		clear_bit(event, irq->flip_done_event[pipe]);
+		if (!pipe_is_enabled(vgpu, pipe))
+			continue;
+
+		vgpu_vreg(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++;
+		intel_vgpu_trigger_virtual_event(vgpu, event);
+	}
+
+	if (pipe_is_enabled(vgpu, pipe)) {
+		vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(pipe))++;
+		intel_vgpu_trigger_virtual_event(vgpu, vblank_event[pipe]);
+	}
+}
+
+static void emulate_vblank(struct intel_vgpu *vgpu)
+{
+	int pipe;
+
+	for_each_pipe(vgpu->gvt->dev_priv, pipe)
+		emulate_vblank_on_pipe(vgpu, pipe);
+}
+
+/**
+ * intel_gvt_emulate_vblank - trigger vblank events for vGPUs on GVT device
+ * @gvt: a GVT device
+ *
+ * This function is used to trigger vblank interrupts for vGPUs on GVT device
+ *
+ */
+void intel_gvt_emulate_vblank(struct intel_gvt *gvt)
+{
+	struct intel_vgpu *vgpu;
+	int id;
+
+	if (WARN_ON(!mutex_is_locked(&gvt->lock)))
+		return;
+
+	for_each_active_vgpu(gvt, vgpu, id)
+		emulate_vblank(vgpu);
+}
+
+/**
+ * intel_vgpu_clean_display - clean vGPU virtual display emulation
+ * @vgpu: a vGPU
+ *
+ * This function is used to clean vGPU virtual display emulation stuffs
+ *
+ */
+void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	if (IS_SKYLAKE(dev_priv))
+		clean_virtual_dp_monitor(vgpu, PORT_D);
+	else
+		clean_virtual_dp_monitor(vgpu, PORT_B);
+}
+
+/**
+ * intel_vgpu_init_display- initialize vGPU virtual display emulation
+ * @vgpu: a vGPU
+ *
+ * This function is used to initialize vGPU virtual display emulation stuffs
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_init_display(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	intel_vgpu_init_i2c_edid(vgpu);
+
+	if (IS_SKYLAKE(dev_priv))
+		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D);
+	else
+		return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/display.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/display.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/display.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/display.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,163 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Terrence Xu <terrence.xu@intel.com>
+ *    Changbin Du <changbin.du@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef _GVT_DISPLAY_H_
+#define _GVT_DISPLAY_H_
+
+#define SBI_REG_MAX	20
+#define DPCD_SIZE	0x700
+
+#define intel_vgpu_port(vgpu, port) \
+	(&(vgpu->display.ports[port]))
+
+#define intel_vgpu_has_monitor_on_port(vgpu, port) \
+	(intel_vgpu_port(vgpu, port)->edid && \
+		intel_vgpu_port(vgpu, port)->edid->data_valid)
+
+#define intel_vgpu_port_is_dp(vgpu, port) \
+	((intel_vgpu_port(vgpu, port)->type == GVT_DP_A) || \
+	(intel_vgpu_port(vgpu, port)->type == GVT_DP_B) || \
+	(intel_vgpu_port(vgpu, port)->type == GVT_DP_C) || \
+	(intel_vgpu_port(vgpu, port)->type == GVT_DP_D))
+
+#define INTEL_GVT_MAX_UEVENT_VARS	3
+
+/* DPCD start */
+#define DPCD_SIZE	0x700
+
+/* DPCD */
+#define DP_SET_POWER            0x600
+#define DP_SET_POWER_D0         0x1
+#define AUX_NATIVE_WRITE        0x8
+#define AUX_NATIVE_READ         0x9
+
+#define AUX_NATIVE_REPLY_MASK   (0x3 << 4)
+#define AUX_NATIVE_REPLY_ACK    (0x0 << 4)
+#define AUX_NATIVE_REPLY_NAK    (0x1 << 4)
+#define AUX_NATIVE_REPLY_DEFER  (0x2 << 4)
+
+#define AUX_BURST_SIZE          16
+
+/* DPCD addresses */
+#define DPCD_REV			0x000
+#define DPCD_MAX_LINK_RATE		0x001
+#define DPCD_MAX_LANE_COUNT		0x002
+
+#define DPCD_TRAINING_PATTERN_SET	0x102
+#define	DPCD_SINK_COUNT			0x200
+#define DPCD_LANE0_1_STATUS		0x202
+#define DPCD_LANE2_3_STATUS		0x203
+#define DPCD_LANE_ALIGN_STATUS_UPDATED	0x204
+#define DPCD_SINK_STATUS		0x205
+
+/* link training */
+#define DPCD_TRAINING_PATTERN_SET_MASK	0x03
+#define DPCD_LINK_TRAINING_DISABLED	0x00
+#define DPCD_TRAINING_PATTERN_1		0x01
+#define DPCD_TRAINING_PATTERN_2		0x02
+
+#define DPCD_CP_READY_MASK		(1 << 6)
+
+/* lane status */
+#define DPCD_LANES_CR_DONE		0x11
+#define DPCD_LANES_EQ_DONE		0x22
+#define DPCD_SYMBOL_LOCKED		0x44
+
+#define DPCD_INTERLANE_ALIGN_DONE	0x01
+
+#define DPCD_SINK_IN_SYNC		0x03
+/* DPCD end */
+
+#define SBI_RESPONSE_MASK               0x3
+#define SBI_RESPONSE_SHIFT              0x1
+#define SBI_STAT_MASK                   0x1
+#define SBI_STAT_SHIFT                  0x0
+#define SBI_OPCODE_SHIFT                8
+#define SBI_OPCODE_MASK			(0xff << SBI_OPCODE_SHIFT)
+#define SBI_CMD_IORD                    2
+#define SBI_CMD_IOWR                    3
+#define SBI_CMD_CRRD                    6
+#define SBI_CMD_CRWR                    7
+#define SBI_ADDR_OFFSET_SHIFT           16
+#define SBI_ADDR_OFFSET_MASK            (0xffff << SBI_ADDR_OFFSET_SHIFT)
+
+struct intel_vgpu_sbi_register {
+	unsigned int offset;
+	u32 value;
+};
+
+struct intel_vgpu_sbi {
+	int number;
+	struct intel_vgpu_sbi_register registers[SBI_REG_MAX];
+};
+
+enum intel_gvt_plane_type {
+	PRIMARY_PLANE = 0,
+	CURSOR_PLANE,
+	SPRITE_PLANE,
+	MAX_PLANE
+};
+
+struct intel_vgpu_dpcd_data {
+	bool data_valid;
+	u8 data[DPCD_SIZE];
+};
+
+enum intel_vgpu_port_type {
+	GVT_CRT = 0,
+	GVT_DP_A,
+	GVT_DP_B,
+	GVT_DP_C,
+	GVT_DP_D,
+	GVT_HDMI_B,
+	GVT_HDMI_C,
+	GVT_HDMI_D,
+	GVT_PORT_MAX
+};
+
+struct intel_vgpu_port {
+	/* per display EDID information */
+	struct intel_vgpu_edid_data *edid;
+	/* per display DPCD information */
+	struct intel_vgpu_dpcd_data *dpcd;
+	int type;
+};
+
+void intel_gvt_emulate_vblank(struct intel_gvt *gvt);
+void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt);
+
+int intel_vgpu_init_display(struct intel_vgpu *vgpu);
+void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/edid.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/edid.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/edid.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/edid.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,531 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Terrence Xu <terrence.xu@intel.com>
+ *    Changbin Du <changbin.du@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define GMBUS1_TOTAL_BYTES_SHIFT 16
+#define GMBUS1_TOTAL_BYTES_MASK 0x1ff
+#define gmbus1_total_byte_count(v) (((v) >> \
+	GMBUS1_TOTAL_BYTES_SHIFT) & GMBUS1_TOTAL_BYTES_MASK)
+#define gmbus1_slave_addr(v) (((v) & 0xff) >> 1)
+#define gmbus1_slave_index(v) (((v) >> 8) & 0xff)
+#define gmbus1_bus_cycle(v) (((v) >> 25) & 0x7)
+
+/* GMBUS0 bits definitions */
+#define _GMBUS_PIN_SEL_MASK     (0x7)
+
+static unsigned char edid_get_byte(struct intel_vgpu *vgpu)
+{
+	struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid;
+	unsigned char chr = 0;
+
+	if (edid->state == I2C_NOT_SPECIFIED || !edid->slave_selected) {
+		gvt_err("Driver tries to read EDID without proper sequence!\n");
+		return 0;
+	}
+	if (edid->current_edid_read >= EDID_SIZE) {
+		gvt_err("edid_get_byte() exceeds the size of EDID!\n");
+		return 0;
+	}
+
+	if (!edid->edid_available) {
+		gvt_err("Reading EDID but EDID is not available!\n");
+		return 0;
+	}
+
+	if (intel_vgpu_has_monitor_on_port(vgpu, edid->port)) {
+		struct intel_vgpu_edid_data *edid_data =
+			intel_vgpu_port(vgpu, edid->port)->edid;
+
+		chr = edid_data->edid_block[edid->current_edid_read];
+		edid->current_edid_read++;
+	} else {
+		gvt_err("No EDID available during the reading?\n");
+	}
+	return chr;
+}
+
+static inline int get_port_from_gmbus0(u32 gmbus0)
+{
+	int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK;
+	int port = -EINVAL;
+
+	if (port_select == 2)
+		port = PORT_E;
+	else if (port_select == 4)
+		port = PORT_C;
+	else if (port_select == 5)
+		port = PORT_B;
+	else if (port_select == 6)
+		port = PORT_D;
+	return port;
+}
+
+static void reset_gmbus_controller(struct intel_vgpu *vgpu)
+{
+	vgpu_vreg(vgpu, PCH_GMBUS2) = GMBUS_HW_RDY;
+	if (!vgpu->display.i2c_edid.edid_available)
+		vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER;
+	vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE;
+}
+
+/* GMBUS0 */
+static int gmbus0_mmio_write(struct intel_vgpu *vgpu,
+			unsigned int offset, void *p_data, unsigned int bytes)
+{
+	int port, pin_select;
+
+	memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes);
+
+	pin_select = vgpu_vreg(vgpu, offset) & _GMBUS_PIN_SEL_MASK;
+
+	intel_vgpu_init_i2c_edid(vgpu);
+
+	if (pin_select == 0)
+		return 0;
+
+	port = get_port_from_gmbus0(pin_select);
+	if (WARN_ON(port < 0))
+		return 0;
+
+	vgpu->display.i2c_edid.state = I2C_GMBUS;
+	vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE;
+
+	vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE;
+	vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY | GMBUS_HW_WAIT_PHASE;
+
+	if (intel_vgpu_has_monitor_on_port(vgpu, port) &&
+			!intel_vgpu_port_is_dp(vgpu, port)) {
+		vgpu->display.i2c_edid.port = port;
+		vgpu->display.i2c_edid.edid_available = true;
+		vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_SATOER;
+	} else
+		vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER;
+	return 0;
+}
+
+static int gmbus1_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid;
+	u32 slave_addr;
+	u32 wvalue = *(u32 *)p_data;
+
+	if (vgpu_vreg(vgpu, offset) & GMBUS_SW_CLR_INT) {
+		if (!(wvalue & GMBUS_SW_CLR_INT)) {
+			vgpu_vreg(vgpu, offset) &= ~GMBUS_SW_CLR_INT;
+			reset_gmbus_controller(vgpu);
+		}
+		/*
+		 * TODO: "This bit is cleared to zero when an event
+		 * causes the HW_RDY bit transition to occur "
+		 */
+	} else {
+		/*
+		 * per bspec setting this bit can cause:
+		 * 1) INT status bit cleared
+		 * 2) HW_RDY bit asserted
+		 */
+		if (wvalue & GMBUS_SW_CLR_INT) {
+			vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_INT;
+			vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY;
+		}
+
+		/* For virtualization, we suppose that HW is always ready,
+		 * so GMBUS_SW_RDY should always be cleared
+		 */
+		if (wvalue & GMBUS_SW_RDY)
+			wvalue &= ~GMBUS_SW_RDY;
+
+		i2c_edid->gmbus.total_byte_count =
+			gmbus1_total_byte_count(wvalue);
+		slave_addr = gmbus1_slave_addr(wvalue);
+
+		/* vgpu gmbus only support EDID */
+		if (slave_addr == EDID_ADDR) {
+			i2c_edid->slave_selected = true;
+		} else if (slave_addr != 0) {
+			gvt_dbg_dpy(
+				"vgpu%d: unsupported gmbus slave addr(0x%x)\n"
+				"	gmbus operations will be ignored.\n",
+					vgpu->id, slave_addr);
+		}
+
+		if (wvalue & GMBUS_CYCLE_INDEX)
+			i2c_edid->current_edid_read =
+				gmbus1_slave_index(wvalue);
+
+		i2c_edid->gmbus.cycle_type = gmbus1_bus_cycle(wvalue);
+		switch (gmbus1_bus_cycle(wvalue)) {
+		case GMBUS_NOCYCLE:
+			break;
+		case GMBUS_STOP:
+			/* From spec:
+			 * This can only cause a STOP to be generated
+			 * if a GMBUS cycle is generated, the GMBUS is
+			 * currently in a data/wait/idle phase, or it is in a
+			 * WAIT phase
+			 */
+			if (gmbus1_bus_cycle(vgpu_vreg(vgpu, offset))
+				!= GMBUS_NOCYCLE) {
+				intel_vgpu_init_i2c_edid(vgpu);
+				/* After the 'stop' cycle, hw state would become
+				 * 'stop phase' and then 'idle phase' after a
+				 * few milliseconds. In emulation, we just set
+				 * it as 'idle phase' ('stop phase' is not
+				 * visible in gmbus interface)
+				 */
+				i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE;
+				vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE;
+			}
+			break;
+		case NIDX_NS_W:
+		case IDX_NS_W:
+		case NIDX_STOP:
+		case IDX_STOP:
+			/* From hw spec the GMBUS phase
+			 * transition like this:
+			 * START (-->INDEX) -->DATA
+			 */
+			i2c_edid->gmbus.phase = GMBUS_DATA_PHASE;
+			vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_ACTIVE;
+			break;
+		default:
+			gvt_err("Unknown/reserved GMBUS cycle detected!\n");
+			break;
+		}
+		/*
+		 * From hw spec the WAIT state will be
+		 * cleared:
+		 * (1) in a new GMBUS cycle
+		 * (2) by generating a stop
+		 */
+		vgpu_vreg(vgpu, offset) = wvalue;
+	}
+	return 0;
+}
+
+static int gmbus3_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+	void *p_data, unsigned int bytes)
+{
+	WARN_ON(1);
+	return 0;
+}
+
+static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	int i;
+	unsigned char byte_data;
+	struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid;
+	int byte_left = i2c_edid->gmbus.total_byte_count -
+				i2c_edid->current_edid_read;
+	int byte_count = byte_left;
+	u32 reg_data = 0;
+
+	/* Data can only be recevied if previous settings correct */
+	if (vgpu_vreg(vgpu, PCH_GMBUS1) & GMBUS_SLAVE_READ) {
+		if (byte_left <= 0) {
+			memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+			return 0;
+		}
+
+		if (byte_count > 4)
+			byte_count = 4;
+		for (i = 0; i < byte_count; i++) {
+			byte_data = edid_get_byte(vgpu);
+			reg_data |= (byte_data << (i << 3));
+		}
+
+		memcpy(&vgpu_vreg(vgpu, offset), &reg_data, byte_count);
+		memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+
+		if (byte_left <= 4) {
+			switch (i2c_edid->gmbus.cycle_type) {
+			case NIDX_STOP:
+			case IDX_STOP:
+				i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE;
+				break;
+			case NIDX_NS_W:
+			case IDX_NS_W:
+			default:
+				i2c_edid->gmbus.phase = GMBUS_WAIT_PHASE;
+				break;
+			}
+			intel_vgpu_init_i2c_edid(vgpu);
+		}
+		/*
+		 * Read GMBUS3 during send operation,
+		 * return the latest written value
+		 */
+	} else {
+		memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+		gvt_err("vgpu%d: warning: gmbus3 read with nothing returned\n",
+				vgpu->id);
+	}
+	return 0;
+}
+
+static int gmbus2_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 value = vgpu_vreg(vgpu, offset);
+
+	if (!(vgpu_vreg(vgpu, offset) & GMBUS_INUSE))
+		vgpu_vreg(vgpu, offset) |= GMBUS_INUSE;
+	memcpy(p_data, (void *)&value, bytes);
+	return 0;
+}
+
+static int gmbus2_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 wvalue = *(u32 *)p_data;
+
+	if (wvalue & GMBUS_INUSE)
+		vgpu_vreg(vgpu, offset) &= ~GMBUS_INUSE;
+	/* All other bits are read-only */
+	return 0;
+}
+
+/**
+ * intel_gvt_i2c_handle_gmbus_read - emulate gmbus register mmio read
+ * @vgpu: a vGPU
+ *
+ * This function is used to emulate gmbus register mmio read
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu,
+	unsigned int offset, void *p_data, unsigned int bytes)
+{
+	if (WARN_ON(bytes > 8 && (offset & (bytes - 1))))
+		return -EINVAL;
+
+	if (offset == i915_mmio_reg_offset(PCH_GMBUS2))
+		return gmbus2_mmio_read(vgpu, offset, p_data, bytes);
+	else if (offset == i915_mmio_reg_offset(PCH_GMBUS3))
+		return gmbus3_mmio_read(vgpu, offset, p_data, bytes);
+
+	memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+	return 0;
+}
+
+/**
+ * intel_gvt_i2c_handle_gmbus_write - emulate gmbus register mmio write
+ * @vgpu: a vGPU
+ *
+ * This function is used to emulate gmbus register mmio write
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	if (WARN_ON(bytes > 8 && (offset & (bytes - 1))))
+		return -EINVAL;
+
+	if (offset == i915_mmio_reg_offset(PCH_GMBUS0))
+		return gmbus0_mmio_write(vgpu, offset, p_data, bytes);
+	else if (offset == i915_mmio_reg_offset(PCH_GMBUS1))
+		return gmbus1_mmio_write(vgpu, offset, p_data, bytes);
+	else if (offset == i915_mmio_reg_offset(PCH_GMBUS2))
+		return gmbus2_mmio_write(vgpu, offset, p_data, bytes);
+	else if (offset == i915_mmio_reg_offset(PCH_GMBUS3))
+		return gmbus3_mmio_write(vgpu, offset, p_data, bytes);
+
+	memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes);
+	return 0;
+}
+
+enum {
+	AUX_CH_CTL = 0,
+	AUX_CH_DATA1,
+	AUX_CH_DATA2,
+	AUX_CH_DATA3,
+	AUX_CH_DATA4,
+	AUX_CH_DATA5
+};
+
+static inline int get_aux_ch_reg(unsigned int offset)
+{
+	int reg;
+
+	switch (offset & 0xff) {
+	case 0x10:
+		reg = AUX_CH_CTL;
+		break;
+	case 0x14:
+		reg = AUX_CH_DATA1;
+		break;
+	case 0x18:
+		reg = AUX_CH_DATA2;
+		break;
+	case 0x1c:
+		reg = AUX_CH_DATA3;
+		break;
+	case 0x20:
+		reg = AUX_CH_DATA4;
+		break;
+	case 0x24:
+		reg = AUX_CH_DATA5;
+		break;
+	default:
+		reg = -1;
+		break;
+	}
+	return reg;
+}
+
+#define AUX_CTL_MSG_LENGTH(reg) \
+	((reg & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> \
+		DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT)
+
+/**
+ * intel_gvt_i2c_handle_aux_ch_write - emulate AUX channel register write
+ * @vgpu: a vGPU
+ *
+ * This function is used to emulate AUX channel register write
+ *
+ */
+void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
+				int port_idx,
+				unsigned int offset,
+				void *p_data)
+{
+	struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid;
+	int msg_length, ret_msg_size;
+	int msg, addr, ctrl, op;
+	u32 value = *(u32 *)p_data;
+	int aux_data_for_write = 0;
+	int reg = get_aux_ch_reg(offset);
+
+	if (reg != AUX_CH_CTL) {
+		vgpu_vreg(vgpu, offset) = value;
+		return;
+	}
+
+	msg_length = AUX_CTL_MSG_LENGTH(value);
+	// check the msg in DATA register.
+	msg = vgpu_vreg(vgpu, offset + 4);
+	addr = (msg >> 8) & 0xffff;
+	ctrl = (msg >> 24) & 0xff;
+	op = ctrl >> 4;
+	if (!(value & DP_AUX_CH_CTL_SEND_BUSY)) {
+		/* The ctl write to clear some states */
+		return;
+	}
+
+	/* Always set the wanted value for vms. */
+	ret_msg_size = (((op & 0x1) == GVT_AUX_I2C_READ) ? 2 : 1);
+	vgpu_vreg(vgpu, offset) =
+		DP_AUX_CH_CTL_DONE |
+		((ret_msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) &
+		DP_AUX_CH_CTL_MESSAGE_SIZE_MASK);
+
+	if (msg_length == 3) {
+		if (!(op & GVT_AUX_I2C_MOT)) {
+			/* stop */
+			intel_vgpu_init_i2c_edid(vgpu);
+		} else {
+			/* start or restart */
+			i2c_edid->aux_ch.i2c_over_aux_ch = true;
+			i2c_edid->aux_ch.aux_ch_mot = true;
+			if (addr == 0) {
+				/* reset the address */
+				intel_vgpu_init_i2c_edid(vgpu);
+			} else if (addr == EDID_ADDR) {
+				i2c_edid->state = I2C_AUX_CH;
+				i2c_edid->port = port_idx;
+				i2c_edid->slave_selected = true;
+				if (intel_vgpu_has_monitor_on_port(vgpu,
+					port_idx) &&
+					intel_vgpu_port_is_dp(vgpu, port_idx))
+					i2c_edid->edid_available = true;
+			}
+		}
+	} else if ((op & 0x1) == GVT_AUX_I2C_WRITE) {
+		/* TODO
+		 * We only support EDID reading from I2C_over_AUX. And
+		 * we do not expect the index mode to be used. Right now
+		 * the WRITE operation is ignored. It is good enough to
+		 * support the gfx driver to do EDID access.
+		 */
+	} else {
+		if (WARN_ON((op & 0x1) != GVT_AUX_I2C_READ))
+			return;
+		if (WARN_ON(msg_length != 4))
+			return;
+		if (i2c_edid->edid_available && i2c_edid->slave_selected) {
+			unsigned char val = edid_get_byte(vgpu);
+
+			aux_data_for_write = (val << 16);
+		}
+	}
+	/* write the return value in AUX_CH_DATA reg which includes:
+	 * ACK of I2C_WRITE
+	 * returned byte if it is READ
+	 */
+	aux_data_for_write |= GVT_AUX_I2C_REPLY_ACK << 24;
+	vgpu_vreg(vgpu, offset + 4) = aux_data_for_write;
+}
+
+/**
+ * intel_vgpu_init_i2c_edid - initialize vGPU i2c edid emulation
+ * @vgpu: a vGPU
+ *
+ * This function is used to initialize vGPU i2c edid emulation stuffs
+ *
+ */
+void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu)
+{
+	struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid;
+
+	edid->state = I2C_NOT_SPECIFIED;
+
+	edid->port = -1;
+	edid->slave_selected = false;
+	edid->edid_available = false;
+	edid->current_edid_read = 0;
+
+	memset(&edid->gmbus, 0, sizeof(struct intel_vgpu_i2c_gmbus));
+
+	edid->aux_ch.i2c_over_aux_ch = false;
+	edid->aux_ch.aux_ch_mot = false;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/edid.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/edid.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/edid.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/edid.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,150 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Terrence Xu <terrence.xu@intel.com>
+ *    Changbin Du <changbin.du@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef _GVT_EDID_H_
+#define _GVT_EDID_H_
+
+#define EDID_SIZE		128
+#define EDID_ADDR		0x50 /* Linux hvm EDID addr */
+
+#define GVT_AUX_NATIVE_WRITE			0x8
+#define GVT_AUX_NATIVE_READ			0x9
+#define GVT_AUX_I2C_WRITE			0x0
+#define GVT_AUX_I2C_READ			0x1
+#define GVT_AUX_I2C_STATUS			0x2
+#define GVT_AUX_I2C_MOT				0x4
+#define GVT_AUX_I2C_REPLY_ACK			0x0
+
+struct intel_vgpu_edid_data {
+	bool data_valid;
+	unsigned char edid_block[EDID_SIZE];
+};
+
+enum gmbus_cycle_type {
+	GMBUS_NOCYCLE	= 0x0,
+	NIDX_NS_W	= 0x1,
+	IDX_NS_W	= 0x3,
+	GMBUS_STOP	= 0x4,
+	NIDX_STOP	= 0x5,
+	IDX_STOP	= 0x7
+};
+
+/*
+ * States of GMBUS
+ *
+ * GMBUS0-3 could be related to the EDID virtualization. Another two GMBUS
+ * registers, GMBUS4 (interrupt mask) and GMBUS5 (2 byte indes register), are
+ * not considered here. Below describes the usage of GMBUS registers that are
+ * cared by the EDID virtualization
+ *
+ * GMBUS0:
+ *      R/W
+ *      port selection. value of bit0 - bit2 corresponds to the GPIO registers.
+ *
+ * GMBUS1:
+ *      R/W Protect
+ *      Command and Status.
+ *      bit0 is the direction bit: 1 is read; 0 is write.
+ *      bit1 - bit7 is slave 7-bit address.
+ *      bit16 - bit24 total byte count (ignore?)
+ *
+ * GMBUS2:
+ *      Most of bits are read only except bit 15 (IN_USE)
+ *      Status register
+ *      bit0 - bit8 current byte count
+ *      bit 11: hardware ready;
+ *
+ * GMBUS3:
+ *      Read/Write
+ *      Data for transfer
+ */
+
+/* From hw specs, Other phases like START, ADDRESS, INDEX
+ * are invisible to GMBUS MMIO interface. So no definitions
+ * in below enum types
+ */
+enum gvt_gmbus_phase {
+	GMBUS_IDLE_PHASE = 0,
+	GMBUS_DATA_PHASE,
+	GMBUS_WAIT_PHASE,
+	//GMBUS_STOP_PHASE,
+	GMBUS_MAX_PHASE
+};
+
+struct intel_vgpu_i2c_gmbus {
+	unsigned int total_byte_count; /* from GMBUS1 */
+	enum gmbus_cycle_type cycle_type;
+	enum gvt_gmbus_phase phase;
+};
+
+struct intel_vgpu_i2c_aux_ch {
+	bool i2c_over_aux_ch;
+	bool aux_ch_mot;
+};
+
+enum i2c_state {
+	I2C_NOT_SPECIFIED = 0,
+	I2C_GMBUS = 1,
+	I2C_AUX_CH = 2
+};
+
+/* I2C sequences cannot interleave.
+ * GMBUS and AUX_CH sequences cannot interleave.
+ */
+struct intel_vgpu_i2c_edid {
+	enum i2c_state state;
+
+	unsigned int port;
+	bool slave_selected;
+	bool edid_available;
+	unsigned int current_edid_read;
+
+	struct intel_vgpu_i2c_gmbus gmbus;
+	struct intel_vgpu_i2c_aux_ch aux_ch;
+};
+
+void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu);
+
+int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes);
+
+int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes);
+
+void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu,
+		int port_idx,
+		unsigned int offset,
+		void *p_data);
+
+#endif /*_GVT_EDID_H_*/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/execlist.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/execlist.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/execlist.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/execlist.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,830 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define _EL_OFFSET_STATUS       0x234
+#define _EL_OFFSET_STATUS_BUF   0x370
+#define _EL_OFFSET_STATUS_PTR   0x3A0
+
+#define execlist_ring_mmio(gvt, ring_id, offset) \
+	(gvt->dev_priv->engine[ring_id]->mmio_base + (offset))
+
+#define valid_context(ctx) ((ctx)->valid)
+#define same_context(a, b) (((a)->context_id == (b)->context_id) && \
+		((a)->lrca == (b)->lrca))
+
+static int context_switch_events[] = {
+	[RCS] = RCS_AS_CONTEXT_SWITCH,
+	[BCS] = BCS_AS_CONTEXT_SWITCH,
+	[VCS] = VCS_AS_CONTEXT_SWITCH,
+	[VCS2] = VCS2_AS_CONTEXT_SWITCH,
+	[VECS] = VECS_AS_CONTEXT_SWITCH,
+};
+
+static int ring_id_to_context_switch_event(int ring_id)
+{
+	if (WARN_ON(ring_id < RCS && ring_id >
+				ARRAY_SIZE(context_switch_events)))
+		return -EINVAL;
+
+	return context_switch_events[ring_id];
+}
+
+static void switch_virtual_execlist_slot(struct intel_vgpu_execlist *execlist)
+{
+	gvt_dbg_el("[before] running slot %d/context %x pending slot %d\n",
+			execlist->running_slot ?
+			execlist->running_slot->index : -1,
+			execlist->running_context ?
+			execlist->running_context->context_id : 0,
+			execlist->pending_slot ?
+			execlist->pending_slot->index : -1);
+
+	execlist->running_slot = execlist->pending_slot;
+	execlist->pending_slot = NULL;
+	execlist->running_context = execlist->running_context ?
+		&execlist->running_slot->ctx[0] : NULL;
+
+	gvt_dbg_el("[after] running slot %d/context %x pending slot %d\n",
+			execlist->running_slot ?
+			execlist->running_slot->index : -1,
+			execlist->running_context ?
+			execlist->running_context->context_id : 0,
+			execlist->pending_slot ?
+			execlist->pending_slot->index : -1);
+}
+
+static void emulate_execlist_status(struct intel_vgpu_execlist *execlist)
+{
+	struct intel_vgpu_execlist_slot *running = execlist->running_slot;
+	struct intel_vgpu_execlist_slot *pending = execlist->pending_slot;
+	struct execlist_ctx_descriptor_format *desc = execlist->running_context;
+	struct intel_vgpu *vgpu = execlist->vgpu;
+	struct execlist_status_format status;
+	int ring_id = execlist->ring_id;
+	u32 status_reg = execlist_ring_mmio(vgpu->gvt,
+			ring_id, _EL_OFFSET_STATUS);
+
+	status.ldw = vgpu_vreg(vgpu, status_reg);
+	status.udw = vgpu_vreg(vgpu, status_reg + 4);
+
+	if (running) {
+		status.current_execlist_pointer = !!running->index;
+		status.execlist_write_pointer = !!!running->index;
+		status.execlist_0_active = status.execlist_0_valid =
+			!!!(running->index);
+		status.execlist_1_active = status.execlist_1_valid =
+			!!(running->index);
+	} else {
+		status.context_id = 0;
+		status.execlist_0_active = status.execlist_0_valid = 0;
+		status.execlist_1_active = status.execlist_1_valid = 0;
+	}
+
+	status.context_id = desc ? desc->context_id : 0;
+	status.execlist_queue_full = !!(pending);
+
+	vgpu_vreg(vgpu, status_reg) = status.ldw;
+	vgpu_vreg(vgpu, status_reg + 4) = status.udw;
+
+	gvt_dbg_el("vgpu%d: status reg offset %x ldw %x udw %x\n",
+		vgpu->id, status_reg, status.ldw, status.udw);
+}
+
+static void emulate_csb_update(struct intel_vgpu_execlist *execlist,
+		struct execlist_context_status_format *status,
+		bool trigger_interrupt_later)
+{
+	struct intel_vgpu *vgpu = execlist->vgpu;
+	int ring_id = execlist->ring_id;
+	struct execlist_context_status_pointer_format ctx_status_ptr;
+	u32 write_pointer;
+	u32 ctx_status_ptr_reg, ctx_status_buf_reg, offset;
+
+	ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+			_EL_OFFSET_STATUS_PTR);
+	ctx_status_buf_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+			_EL_OFFSET_STATUS_BUF);
+
+	ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg);
+
+	write_pointer = ctx_status_ptr.write_ptr;
+
+	if (write_pointer == 0x7)
+		write_pointer = 0;
+	else {
+		++write_pointer;
+		write_pointer %= 0x6;
+	}
+
+	offset = ctx_status_buf_reg + write_pointer * 8;
+
+	vgpu_vreg(vgpu, offset) = status->ldw;
+	vgpu_vreg(vgpu, offset + 4) = status->udw;
+
+	ctx_status_ptr.write_ptr = write_pointer;
+	vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
+
+	gvt_dbg_el("vgpu%d: w pointer %u reg %x csb l %x csb h %x\n",
+		vgpu->id, write_pointer, offset, status->ldw, status->udw);
+
+	if (trigger_interrupt_later)
+		return;
+
+	intel_vgpu_trigger_virtual_event(vgpu,
+			ring_id_to_context_switch_event(execlist->ring_id));
+}
+
+static int emulate_execlist_ctx_schedule_out(
+		struct intel_vgpu_execlist *execlist,
+		struct execlist_ctx_descriptor_format *ctx)
+{
+	struct intel_vgpu_execlist_slot *running = execlist->running_slot;
+	struct intel_vgpu_execlist_slot *pending = execlist->pending_slot;
+	struct execlist_ctx_descriptor_format *ctx0 = &running->ctx[0];
+	struct execlist_ctx_descriptor_format *ctx1 = &running->ctx[1];
+	struct execlist_context_status_format status;
+
+	memset(&status, 0, sizeof(status));
+
+	gvt_dbg_el("schedule out context id %x\n", ctx->context_id);
+
+	if (WARN_ON(!same_context(ctx, execlist->running_context))) {
+		gvt_err("schedule out context is not running context,"
+				"ctx id %x running ctx id %x\n",
+				ctx->context_id,
+				execlist->running_context->context_id);
+		return -EINVAL;
+	}
+
+	/* ctx1 is valid, ctx0/ctx is scheduled-out -> element switch */
+	if (valid_context(ctx1) && same_context(ctx0, ctx)) {
+		gvt_dbg_el("ctx 1 valid, ctx/ctx 0 is scheduled-out\n");
+
+		execlist->running_context = ctx1;
+
+		emulate_execlist_status(execlist);
+
+		status.context_complete = status.element_switch = 1;
+		status.context_id = ctx->context_id;
+
+		emulate_csb_update(execlist, &status, false);
+		/*
+		 * ctx1 is not valid, ctx == ctx0
+		 * ctx1 is valid, ctx1 == ctx
+		 *	--> last element is finished
+		 * emulate:
+		 *	active-to-idle if there is *no* pending execlist
+		 *	context-complete if there *is* pending execlist
+		 */
+	} else if ((!valid_context(ctx1) && same_context(ctx0, ctx))
+			|| (valid_context(ctx1) && same_context(ctx1, ctx))) {
+		gvt_dbg_el("need to switch virtual execlist slot\n");
+
+		switch_virtual_execlist_slot(execlist);
+
+		emulate_execlist_status(execlist);
+
+		status.context_complete = status.active_to_idle = 1;
+		status.context_id = ctx->context_id;
+
+		if (!pending) {
+			emulate_csb_update(execlist, &status, false);
+		} else {
+			emulate_csb_update(execlist, &status, true);
+
+			memset(&status, 0, sizeof(status));
+
+			status.idle_to_active = 1;
+			status.context_id = 0;
+
+			emulate_csb_update(execlist, &status, false);
+		}
+	} else {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct intel_vgpu_execlist_slot *get_next_execlist_slot(
+		struct intel_vgpu_execlist *execlist)
+{
+	struct intel_vgpu *vgpu = execlist->vgpu;
+	int ring_id = execlist->ring_id;
+	u32 status_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+			_EL_OFFSET_STATUS);
+	struct execlist_status_format status;
+
+	status.ldw = vgpu_vreg(vgpu, status_reg);
+	status.udw = vgpu_vreg(vgpu, status_reg + 4);
+
+	if (status.execlist_queue_full) {
+		gvt_err("virtual execlist slots are full\n");
+		return NULL;
+	}
+
+	return &execlist->slot[status.execlist_write_pointer];
+}
+
+static int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist,
+		struct execlist_ctx_descriptor_format ctx[2])
+{
+	struct intel_vgpu_execlist_slot *running = execlist->running_slot;
+	struct intel_vgpu_execlist_slot *slot =
+		get_next_execlist_slot(execlist);
+
+	struct execlist_ctx_descriptor_format *ctx0, *ctx1;
+	struct execlist_context_status_format status;
+
+	gvt_dbg_el("emulate schedule-in\n");
+
+	if (!slot) {
+		gvt_err("no available execlist slot\n");
+		return -EINVAL;
+	}
+
+	memset(&status, 0, sizeof(status));
+	memset(slot->ctx, 0, sizeof(slot->ctx));
+
+	slot->ctx[0] = ctx[0];
+	slot->ctx[1] = ctx[1];
+
+	gvt_dbg_el("alloc slot index %d ctx 0 %x ctx 1 %x\n",
+			slot->index, ctx[0].context_id,
+			ctx[1].context_id);
+
+	/*
+	 * no running execlist, make this write bundle as running execlist
+	 * -> idle-to-active
+	 */
+	if (!running) {
+		gvt_dbg_el("no current running execlist\n");
+
+		execlist->running_slot = slot;
+		execlist->pending_slot = NULL;
+		execlist->running_context = &slot->ctx[0];
+
+		gvt_dbg_el("running slot index %d running context %x\n",
+				execlist->running_slot->index,
+				execlist->running_context->context_id);
+
+		emulate_execlist_status(execlist);
+
+		status.idle_to_active = 1;
+		status.context_id = 0;
+
+		emulate_csb_update(execlist, &status, false);
+		return 0;
+	}
+
+	ctx0 = &running->ctx[0];
+	ctx1 = &running->ctx[1];
+
+	gvt_dbg_el("current running slot index %d ctx 0 %x ctx 1 %x\n",
+		running->index, ctx0->context_id, ctx1->context_id);
+
+	/*
+	 * already has an running execlist
+	 *	a. running ctx1 is valid,
+	 *	   ctx0 is finished, and running ctx1 == new execlist ctx[0]
+	 *	b. running ctx1 is not valid,
+	 *	   ctx0 == new execlist ctx[0]
+	 * ----> lite-restore + preempted
+	 */
+	if ((valid_context(ctx1) && same_context(ctx1, &slot->ctx[0]) &&
+		/* condition a */
+		(!same_context(ctx0, execlist->running_context))) ||
+			(!valid_context(ctx1) &&
+			 same_context(ctx0, &slot->ctx[0]))) { /* condition b */
+		gvt_dbg_el("need to switch virtual execlist slot\n");
+
+		execlist->pending_slot = slot;
+		switch_virtual_execlist_slot(execlist);
+
+		emulate_execlist_status(execlist);
+
+		status.lite_restore = status.preempted = 1;
+		status.context_id = ctx[0].context_id;
+
+		emulate_csb_update(execlist, &status, false);
+	} else {
+		gvt_dbg_el("emulate as pending slot\n");
+		/*
+		 * otherwise
+		 * --> emulate pending execlist exist + but no preemption case
+		 */
+		execlist->pending_slot = slot;
+		emulate_execlist_status(execlist);
+	}
+	return 0;
+}
+
+static void free_workload(struct intel_vgpu_workload *workload)
+{
+	intel_vgpu_unpin_mm(workload->shadow_mm);
+	intel_gvt_mm_unreference(workload->shadow_mm);
+	kmem_cache_free(workload->vgpu->workloads, workload);
+}
+
+#define get_desc_from_elsp_dwords(ed, i) \
+	((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2]))
+
+static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload)
+{
+	const int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd;
+	struct intel_shadow_bb_entry *entry_obj;
+
+	/* pin the gem object to ggtt */
+	list_for_each_entry(entry_obj, &workload->shadow_bb, list) {
+		struct i915_vma *vma;
+
+		vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, 4, 0);
+		if (IS_ERR(vma)) {
+			gvt_err("Cannot pin\n");
+			return;
+		}
+
+		/* FIXME: we are not tracking our pinned VMA leaving it
+		 * up to the core to fix up the stray pin_count upon
+		 * free.
+		 */
+
+		/* update the relocate gma with shadow batch buffer*/
+		entry_obj->bb_start_cmd_va[1] = i915_ggtt_offset(vma);
+		if (gmadr_bytes == 8)
+			entry_obj->bb_start_cmd_va[2] = 0;
+	}
+}
+
+static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+	int ring_id = wa_ctx->workload->ring_id;
+	struct i915_gem_context *shadow_ctx =
+		wa_ctx->workload->vgpu->shadow_ctx;
+	struct drm_i915_gem_object *ctx_obj =
+		shadow_ctx->engine[ring_id].state->obj;
+	struct execlist_ring_context *shadow_ring_context;
+	struct page *page;
+
+	page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+	shadow_ring_context = kmap_atomic(page);
+
+	shadow_ring_context->bb_per_ctx_ptr.val =
+		(shadow_ring_context->bb_per_ctx_ptr.val &
+		(~PER_CTX_ADDR_MASK)) | wa_ctx->per_ctx.shadow_gma;
+	shadow_ring_context->rcs_indirect_ctx.val =
+		(shadow_ring_context->rcs_indirect_ctx.val &
+		(~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma;
+
+	kunmap_atomic(shadow_ring_context);
+	return 0;
+}
+
+static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+	struct i915_vma *vma;
+	unsigned char *per_ctx_va =
+		(unsigned char *)wa_ctx->indirect_ctx.shadow_va +
+		wa_ctx->indirect_ctx.size;
+
+	if (wa_ctx->indirect_ctx.size == 0)
+		return;
+
+	vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL,
+				       0, CACHELINE_BYTES, 0);
+	if (IS_ERR(vma)) {
+		gvt_err("Cannot pin indirect ctx obj\n");
+		return;
+	}
+
+	/* FIXME: we are not tracking our pinned VMA leaving it
+	 * up to the core to fix up the stray pin_count upon
+	 * free.
+	 */
+
+	wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma);
+
+	wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1);
+	memset(per_ctx_va, 0, CACHELINE_BYTES);
+
+	update_wa_ctx_2_shadow_ctx(wa_ctx);
+}
+
+static int prepare_execlist_workload(struct intel_vgpu_workload *workload)
+{
+	struct intel_vgpu *vgpu = workload->vgpu;
+	struct execlist_ctx_descriptor_format ctx[2];
+	int ring_id = workload->ring_id;
+
+	intel_vgpu_pin_mm(workload->shadow_mm);
+	intel_vgpu_sync_oos_pages(workload->vgpu);
+	intel_vgpu_flush_post_shadow(workload->vgpu);
+	prepare_shadow_batch_buffer(workload);
+	prepare_shadow_wa_ctx(&workload->wa_ctx);
+	if (!workload->emulate_schedule_in)
+		return 0;
+
+	ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1);
+	ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0);
+
+	return emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx);
+}
+
+static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload)
+{
+	/* release all the shadow batch buffer */
+	if (!list_empty(&workload->shadow_bb)) {
+		struct intel_shadow_bb_entry *entry_obj =
+			list_first_entry(&workload->shadow_bb,
+					 struct intel_shadow_bb_entry,
+					 list);
+		struct intel_shadow_bb_entry *temp;
+
+		list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb,
+					 list) {
+			i915_gem_object_unpin_map(entry_obj->obj);
+			i915_gem_object_put(entry_obj->obj);
+			list_del(&entry_obj->list);
+			kfree(entry_obj);
+		}
+	}
+}
+
+static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
+{
+	if (wa_ctx->indirect_ctx.size == 0)
+		return;
+
+	i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);
+	i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+}
+
+static int complete_execlist_workload(struct intel_vgpu_workload *workload)
+{
+	struct intel_vgpu *vgpu = workload->vgpu;
+	struct intel_vgpu_execlist *execlist =
+		&vgpu->execlist[workload->ring_id];
+	struct intel_vgpu_workload *next_workload;
+	struct list_head *next = workload_q_head(vgpu, workload->ring_id)->next;
+	bool lite_restore = false;
+	int ret;
+
+	gvt_dbg_el("complete workload %p status %d\n", workload,
+			workload->status);
+
+	release_shadow_batch_buffer(workload);
+	release_shadow_wa_ctx(&workload->wa_ctx);
+
+	if (workload->status || vgpu->resetting)
+		goto out;
+
+	if (!list_empty(workload_q_head(vgpu, workload->ring_id))) {
+		struct execlist_ctx_descriptor_format *this_desc, *next_desc;
+
+		next_workload = container_of(next,
+				struct intel_vgpu_workload, list);
+		this_desc = &workload->ctx_desc;
+		next_desc = &next_workload->ctx_desc;
+
+		lite_restore = same_context(this_desc, next_desc);
+	}
+
+	if (lite_restore) {
+		gvt_dbg_el("next context == current - no schedule-out\n");
+		free_workload(workload);
+		return 0;
+	}
+
+	ret = emulate_execlist_ctx_schedule_out(execlist, &workload->ctx_desc);
+	if (ret)
+		goto err;
+out:
+	free_workload(workload);
+	return 0;
+err:
+	free_workload(workload);
+	return ret;
+}
+
+#define RING_CTX_OFF(x) \
+	offsetof(struct execlist_ring_context, x)
+
+static void read_guest_pdps(struct intel_vgpu *vgpu,
+		u64 ring_context_gpa, u32 pdp[8])
+{
+	u64 gpa;
+	int i;
+
+	gpa = ring_context_gpa + RING_CTX_OFF(pdp3_UDW.val);
+
+	for (i = 0; i < 8; i++)
+		intel_gvt_hypervisor_read_gpa(vgpu,
+				gpa + i * 8, &pdp[7 - i], 4);
+}
+
+static int prepare_mm(struct intel_vgpu_workload *workload)
+{
+	struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc;
+	struct intel_vgpu_mm *mm;
+	int page_table_level;
+	u32 pdp[8];
+
+	if (desc->addressing_mode == 1) { /* legacy 32-bit */
+		page_table_level = 3;
+	} else if (desc->addressing_mode == 3) { /* legacy 64 bit */
+		page_table_level = 4;
+	} else {
+		gvt_err("Advanced Context mode(SVM) is not supported!\n");
+		return -EINVAL;
+	}
+
+	read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp);
+
+	mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp);
+	if (mm) {
+		intel_gvt_mm_reference(mm);
+	} else {
+
+		mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT,
+				pdp, page_table_level, 0);
+		if (IS_ERR(mm)) {
+			gvt_err("fail to create mm object.\n");
+			return PTR_ERR(mm);
+		}
+	}
+	workload->shadow_mm = mm;
+	return 0;
+}
+
+#define get_last_workload(q) \
+	(list_empty(q) ? NULL : container_of(q->prev, \
+	struct intel_vgpu_workload, list))
+
+static int submit_context(struct intel_vgpu *vgpu, int ring_id,
+		struct execlist_ctx_descriptor_format *desc,
+		bool emulate_schedule_in)
+{
+	struct list_head *q = workload_q_head(vgpu, ring_id);
+	struct intel_vgpu_workload *last_workload = get_last_workload(q);
+	struct intel_vgpu_workload *workload = NULL;
+	u64 ring_context_gpa;
+	u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx;
+	int ret;
+
+	ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
+			(u32)((desc->lrca + 1) << GTT_PAGE_SHIFT));
+	if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) {
+		gvt_err("invalid guest context LRCA: %x\n", desc->lrca);
+		return -EINVAL;
+	}
+
+	intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+			RING_CTX_OFF(ring_header.val), &head, 4);
+
+	intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+			RING_CTX_OFF(ring_tail.val), &tail, 4);
+
+	head &= RB_HEAD_OFF_MASK;
+	tail &= RB_TAIL_OFF_MASK;
+
+	if (last_workload && same_context(&last_workload->ctx_desc, desc)) {
+		gvt_dbg_el("ring id %d cur workload == last\n", ring_id);
+		gvt_dbg_el("ctx head %x real head %lx\n", head,
+				last_workload->rb_tail);
+		/*
+		 * cannot use guest context head pointer here,
+		 * as it might not be updated at this time
+		 */
+		head = last_workload->rb_tail;
+	}
+
+	gvt_dbg_el("ring id %d begin a new workload\n", ring_id);
+
+	workload = kmem_cache_zalloc(vgpu->workloads, GFP_KERNEL);
+	if (!workload)
+		return -ENOMEM;
+
+	/* record some ring buffer register values for scan and shadow */
+	intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+			RING_CTX_OFF(rb_start.val), &start, 4);
+	intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+			RING_CTX_OFF(rb_ctrl.val), &ctl, 4);
+	intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+			RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4);
+
+	INIT_LIST_HEAD(&workload->list);
+	INIT_LIST_HEAD(&workload->shadow_bb);
+
+	init_waitqueue_head(&workload->shadow_ctx_status_wq);
+	atomic_set(&workload->shadow_ctx_active, 0);
+
+	workload->vgpu = vgpu;
+	workload->ring_id = ring_id;
+	workload->ctx_desc = *desc;
+	workload->ring_context_gpa = ring_context_gpa;
+	workload->rb_head = head;
+	workload->rb_tail = tail;
+	workload->rb_start = start;
+	workload->rb_ctl = ctl;
+	workload->prepare = prepare_execlist_workload;
+	workload->complete = complete_execlist_workload;
+	workload->status = -EINPROGRESS;
+	workload->emulate_schedule_in = emulate_schedule_in;
+
+	if (ring_id == RCS) {
+		intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+			RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4);
+		intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
+			RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4);
+
+		workload->wa_ctx.indirect_ctx.guest_gma =
+			indirect_ctx & INDIRECT_CTX_ADDR_MASK;
+		workload->wa_ctx.indirect_ctx.size =
+			(indirect_ctx & INDIRECT_CTX_SIZE_MASK) *
+			CACHELINE_BYTES;
+		workload->wa_ctx.per_ctx.guest_gma =
+			per_ctx & PER_CTX_ADDR_MASK;
+		workload->wa_ctx.workload = workload;
+
+		WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1));
+	}
+
+	if (emulate_schedule_in)
+		memcpy(&workload->elsp_dwords,
+				&vgpu->execlist[ring_id].elsp_dwords,
+				sizeof(workload->elsp_dwords));
+
+	gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n",
+			workload, ring_id, head, tail, start, ctl);
+
+	gvt_dbg_el("workload %p emulate schedule_in %d\n", workload,
+			emulate_schedule_in);
+
+	ret = prepare_mm(workload);
+	if (ret) {
+		kmem_cache_free(vgpu->workloads, workload);
+		return ret;
+	}
+
+	queue_workload(workload);
+	return 0;
+}
+
+int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id)
+{
+	struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id];
+	struct execlist_ctx_descriptor_format *desc[2], valid_desc[2];
+	unsigned long valid_desc_bitmap = 0;
+	bool emulate_schedule_in = true;
+	int ret;
+	int i;
+
+	memset(valid_desc, 0, sizeof(valid_desc));
+
+	desc[0] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 1);
+	desc[1] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 0);
+
+	for (i = 0; i < 2; i++) {
+		if (!desc[i]->valid)
+			continue;
+
+		if (!desc[i]->privilege_access) {
+			gvt_err("vgpu%d: unexpected GGTT elsp submission\n",
+					vgpu->id);
+			return -EINVAL;
+		}
+
+		/* TODO: add another guest context checks here. */
+		set_bit(i, &valid_desc_bitmap);
+		valid_desc[i] = *desc[i];
+	}
+
+	if (!valid_desc_bitmap) {
+		gvt_err("vgpu%d: no valid desc in a elsp submission\n",
+				vgpu->id);
+		return -EINVAL;
+	}
+
+	if (!test_bit(0, (void *)&valid_desc_bitmap) &&
+			test_bit(1, (void *)&valid_desc_bitmap)) {
+		gvt_err("vgpu%d: weird elsp submission, desc 0 is not valid\n",
+				vgpu->id);
+		return -EINVAL;
+	}
+
+	/* submit workload */
+	for_each_set_bit(i, (void *)&valid_desc_bitmap, 2) {
+		ret = submit_context(vgpu, ring_id, &valid_desc[i],
+				emulate_schedule_in);
+		if (ret) {
+			gvt_err("vgpu%d: fail to schedule workload\n",
+					vgpu->id);
+			return ret;
+		}
+		emulate_schedule_in = false;
+	}
+	return 0;
+}
+
+static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id)
+{
+	struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id];
+	struct execlist_context_status_pointer_format ctx_status_ptr;
+	u32 ctx_status_ptr_reg;
+
+	memset(execlist, 0, sizeof(*execlist));
+
+	execlist->vgpu = vgpu;
+	execlist->ring_id = ring_id;
+	execlist->slot[0].index = 0;
+	execlist->slot[1].index = 1;
+
+	ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id,
+			_EL_OFFSET_STATUS_PTR);
+
+	ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg);
+	ctx_status_ptr.read_ptr = ctx_status_ptr.write_ptr = 0x7;
+	vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw;
+}
+
+void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu)
+{
+	kmem_cache_destroy(vgpu->workloads);
+}
+
+int intel_vgpu_init_execlist(struct intel_vgpu *vgpu)
+{
+	enum intel_engine_id i;
+	struct intel_engine_cs *engine;
+
+	/* each ring has a virtual execlist engine */
+	for_each_engine(engine, vgpu->gvt->dev_priv, i) {
+		init_vgpu_execlist(vgpu, i);
+		INIT_LIST_HEAD(&vgpu->workload_q_head[i]);
+	}
+
+	vgpu->workloads = kmem_cache_create("gvt-g_vgpu_workload",
+			sizeof(struct intel_vgpu_workload), 0,
+			SLAB_HWCACHE_ALIGN,
+			NULL);
+
+	if (!vgpu->workloads)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,
+		unsigned long engine_mask)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct intel_engine_cs *engine;
+	struct intel_vgpu_workload *pos, *n;
+	unsigned int tmp;
+
+	for_each_engine_masked(engine, dev_priv, engine_mask, tmp) {
+		/* free the unsubmited workload in the queue */
+		list_for_each_entry_safe(pos, n,
+			&vgpu->workload_q_head[engine->id], list) {
+			list_del_init(&pos->list);
+			free_workload(pos);
+		}
+
+		init_vgpu_execlist(vgpu, engine->id);
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/execlist.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/execlist.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/execlist.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/execlist.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,188 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *
+ */
+
+#ifndef _GVT_EXECLIST_H_
+#define _GVT_EXECLIST_H_
+
+struct execlist_ctx_descriptor_format {
+	union {
+		u32 udw;
+		u32 context_id;
+	};
+	union {
+		u32 ldw;
+		struct {
+			u32 valid                  : 1;
+			u32 force_pd_restore       : 1;
+			u32 force_restore          : 1;
+			u32 addressing_mode        : 2;
+			u32 llc_coherency          : 1;
+			u32 fault_handling         : 2;
+			u32 privilege_access       : 1;
+			u32 reserved               : 3;
+			u32 lrca                   : 20;
+		};
+	};
+};
+
+struct execlist_status_format {
+	union {
+		u32 ldw;
+		struct {
+			u32 current_execlist_pointer       :1;
+			u32 execlist_write_pointer         :1;
+			u32 execlist_queue_full            :1;
+			u32 execlist_1_valid               :1;
+			u32 execlist_0_valid               :1;
+			u32 last_ctx_switch_reason         :9;
+			u32 current_active_elm_status      :2;
+			u32 arbitration_enable             :1;
+			u32 execlist_1_active              :1;
+			u32 execlist_0_active              :1;
+			u32 reserved                       :13;
+		};
+	};
+	union {
+		u32 udw;
+		u32 context_id;
+	};
+};
+
+struct execlist_context_status_pointer_format {
+	union {
+		u32 dw;
+		struct {
+			u32 write_ptr              :3;
+			u32 reserved               :5;
+			u32 read_ptr               :3;
+			u32 reserved2              :5;
+			u32 mask                   :16;
+		};
+	};
+};
+
+struct execlist_context_status_format {
+	union {
+		u32 ldw;
+		struct {
+			u32 idle_to_active         :1;
+			u32 preempted              :1;
+			u32 element_switch         :1;
+			u32 active_to_idle         :1;
+			u32 context_complete       :1;
+			u32 wait_on_sync_flip      :1;
+			u32 wait_on_vblank         :1;
+			u32 wait_on_semaphore      :1;
+			u32 wait_on_scanline       :1;
+			u32 reserved               :2;
+			u32 semaphore_wait_mode    :1;
+			u32 display_plane          :3;
+			u32 lite_restore           :1;
+			u32 reserved_2             :16;
+		};
+	};
+	union {
+		u32 udw;
+		u32 context_id;
+	};
+};
+
+struct execlist_mmio_pair {
+	u32 addr;
+	u32 val;
+};
+
+/* The first 52 dwords in register state context */
+struct execlist_ring_context {
+	u32 nop1;
+	u32 lri_cmd_1;
+	struct execlist_mmio_pair ctx_ctrl;
+	struct execlist_mmio_pair ring_header;
+	struct execlist_mmio_pair ring_tail;
+	struct execlist_mmio_pair rb_start;
+	struct execlist_mmio_pair rb_ctrl;
+	struct execlist_mmio_pair bb_cur_head_UDW;
+	struct execlist_mmio_pair bb_cur_head_LDW;
+	struct execlist_mmio_pair bb_state;
+	struct execlist_mmio_pair second_bb_addr_UDW;
+	struct execlist_mmio_pair second_bb_addr_LDW;
+	struct execlist_mmio_pair second_bb_state;
+	struct execlist_mmio_pair bb_per_ctx_ptr;
+	struct execlist_mmio_pair rcs_indirect_ctx;
+	struct execlist_mmio_pair rcs_indirect_ctx_offset;
+	u32 nop2;
+	u32 nop3;
+	u32 nop4;
+	u32 lri_cmd_2;
+	struct execlist_mmio_pair ctx_timestamp;
+	struct execlist_mmio_pair pdp3_UDW;
+	struct execlist_mmio_pair pdp3_LDW;
+	struct execlist_mmio_pair pdp2_UDW;
+	struct execlist_mmio_pair pdp2_LDW;
+	struct execlist_mmio_pair pdp1_UDW;
+	struct execlist_mmio_pair pdp1_LDW;
+	struct execlist_mmio_pair pdp0_UDW;
+	struct execlist_mmio_pair pdp0_LDW;
+};
+
+struct intel_vgpu_elsp_dwords {
+	u32 data[4];
+	u32 index;
+};
+
+struct intel_vgpu_execlist_slot {
+	struct execlist_ctx_descriptor_format ctx[2];
+	u32 index;
+};
+
+struct intel_vgpu_execlist {
+	struct intel_vgpu_execlist_slot slot[2];
+	struct intel_vgpu_execlist_slot *running_slot;
+	struct intel_vgpu_execlist_slot *pending_slot;
+	struct execlist_ctx_descriptor_format *running_context;
+	int ring_id;
+	struct intel_vgpu *vgpu;
+	struct intel_vgpu_elsp_dwords elsp_dwords;
+};
+
+void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu);
+
+int intel_vgpu_init_execlist(struct intel_vgpu *vgpu);
+
+int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id);
+
+void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu,
+		unsigned long engine_mask);
+
+#endif /*_GVT_EXECLIST_H_*/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/firmware.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/firmware.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/firmware.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/firmware.c	2017-02-12 17:25:20.000000000 -0500
@@ -0,0 +1,312 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ *    Changbin Du <changbin.du@intel.com>
+ *
+ */
+
+#include <linux/firmware.h>
+#include <linux/crc32.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+
+#define FIRMWARE_VERSION (0x0)
+
+struct gvt_firmware_header {
+	u64 magic;
+	u32 crc32;		/* protect the data after this field */
+	u32 version;
+	u64 cfg_space_size;
+	u64 cfg_space_offset;	/* offset in the file */
+	u64 mmio_size;
+	u64 mmio_offset;	/* offset in the file */
+	unsigned char data[1];
+};
+
+#define RD(offset) (readl(mmio + offset.reg))
+#define WR(v, offset) (writel(v, mmio + offset.reg))
+
+static void bdw_forcewake_get(void __iomem *mmio)
+{
+	WR(_MASKED_BIT_DISABLE(0xffff), FORCEWAKE_MT);
+
+	RD(ECOBUS);
+
+	if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL) == 0, 50))
+		gvt_err("fail to wait forcewake idle\n");
+
+	WR(_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL), FORCEWAKE_MT);
+
+	if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL), 50))
+		gvt_err("fail to wait forcewake ack\n");
+
+	if (wait_for((RD(GEN6_GT_THREAD_STATUS_REG) &
+		      GEN6_GT_THREAD_STATUS_CORE_MASK) == 0, 50))
+		gvt_err("fail to wait c0 wake up\n");
+}
+
+#undef RD
+#undef WR
+
+#define dev_to_drm_minor(d) dev_get_drvdata((d))
+
+static ssize_t
+gvt_firmware_read(struct file *filp, struct kobject *kobj,
+	     struct bin_attribute *attr, char *buf,
+	     loff_t offset, size_t count)
+{
+	memcpy(buf, attr->private + offset, count);
+	return count;
+}
+
+static struct bin_attribute firmware_attr = {
+	.attr = {.name = "gvt_firmware", .mode = (S_IRUSR)},
+	.read = gvt_firmware_read,
+	.write = NULL,
+	.mmap = NULL,
+};
+
+static int expose_firmware_sysfs(struct intel_gvt *gvt,
+					void __iomem *mmio)
+{
+	struct intel_gvt_device_info *info = &gvt->device_info;
+	struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
+	struct intel_gvt_mmio_info *e;
+	struct gvt_firmware_header *h;
+	void *firmware;
+	void *p;
+	unsigned long size;
+	int i;
+	int ret;
+
+	size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1;
+	firmware = vmalloc(size);
+	if (!firmware)
+		return -ENOMEM;
+
+	h = firmware;
+
+	h->magic = VGT_MAGIC;
+	h->version = FIRMWARE_VERSION;
+	h->cfg_space_size = info->cfg_space_size;
+	h->cfg_space_offset = offsetof(struct gvt_firmware_header, data);
+	h->mmio_size = info->mmio_size;
+	h->mmio_offset = h->cfg_space_offset + h->cfg_space_size;
+
+	p = firmware + h->cfg_space_offset;
+
+	for (i = 0; i < h->cfg_space_size; i += 4)
+		pci_read_config_dword(pdev, i, p + i);
+
+	memcpy(gvt->firmware.cfg_space, p, info->cfg_space_size);
+
+	p = firmware + h->mmio_offset;
+
+	hash_for_each(gvt->mmio.mmio_info_table, i, e, node) {
+		int j;
+
+		for (j = 0; j < e->length; j += 4)
+			*(u32 *)(p + e->offset + j) =
+				readl(mmio + e->offset + j);
+	}
+
+	memcpy(gvt->firmware.mmio, p, info->mmio_size);
+
+	firmware_attr.size = size;
+	firmware_attr.private = firmware;
+
+	ret = device_create_bin_file(&pdev->dev, &firmware_attr);
+	if (ret) {
+		vfree(firmware);
+		return ret;
+	}
+	return 0;
+}
+
+static void clean_firmware_sysfs(struct intel_gvt *gvt)
+{
+	struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
+
+	device_remove_bin_file(&pdev->dev, &firmware_attr);
+	vfree(firmware_attr.private);
+}
+
+/**
+ * intel_gvt_free_firmware - free GVT firmware
+ * @gvt: intel gvt device
+ *
+ */
+void intel_gvt_free_firmware(struct intel_gvt *gvt)
+{
+	if (!gvt->firmware.firmware_loaded)
+		clean_firmware_sysfs(gvt);
+
+	kfree(gvt->firmware.cfg_space);
+	kfree(gvt->firmware.mmio);
+}
+
+static int verify_firmware(struct intel_gvt *gvt,
+			   const struct firmware *fw)
+{
+	struct intel_gvt_device_info *info = &gvt->device_info;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct gvt_firmware_header *h;
+	unsigned long id, crc32_start;
+	const void *mem;
+	const char *item;
+	u64 file, request;
+
+	h = (struct gvt_firmware_header *)fw->data;
+
+	crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4;
+	mem = fw->data + crc32_start;
+
+#define VERIFY(s, a, b) do { \
+	item = (s); file = (u64)(a); request = (u64)(b); \
+	if ((a) != (b)) \
+		goto invalid_firmware; \
+} while (0)
+
+	VERIFY("magic number", h->magic, VGT_MAGIC);
+	VERIFY("version", h->version, FIRMWARE_VERSION);
+	VERIFY("crc32", h->crc32, crc32_le(0, mem, fw->size - crc32_start));
+	VERIFY("cfg space size", h->cfg_space_size, info->cfg_space_size);
+	VERIFY("mmio size", h->mmio_size, info->mmio_size);
+
+	mem = (fw->data + h->cfg_space_offset);
+
+	id = *(u16 *)(mem + PCI_VENDOR_ID);
+	VERIFY("vender id", id, pdev->vendor);
+
+	id = *(u16 *)(mem + PCI_DEVICE_ID);
+	VERIFY("device id", id, pdev->device);
+
+	id = *(u8 *)(mem + PCI_REVISION_ID);
+	VERIFY("revision id", id, pdev->revision);
+
+#undef VERIFY
+	return 0;
+
+invalid_firmware:
+	gvt_dbg_core("Invalid firmware: %s [file] 0x%llx [request] 0x%llx\n",
+		     item, file, request);
+	return -EINVAL;
+}
+
+#define GVT_FIRMWARE_PATH "i915/gvt"
+
+/**
+ * intel_gvt_load_firmware - load GVT firmware
+ * @gvt: intel gvt device
+ *
+ */
+int intel_gvt_load_firmware(struct intel_gvt *gvt)
+{
+	struct intel_gvt_device_info *info = &gvt->device_info;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	struct intel_gvt_firmware *firmware = &gvt->firmware;
+	struct gvt_firmware_header *h;
+	const struct firmware *fw;
+	char *path;
+	void __iomem *mmio;
+	void *mem;
+	int ret;
+
+	path = kmalloc(PATH_MAX, GFP_KERNEL);
+	if (!path)
+		return -ENOMEM;
+
+	mem = kmalloc(info->cfg_space_size, GFP_KERNEL);
+	if (!mem) {
+		kfree(path);
+		return -ENOMEM;
+	}
+
+	firmware->cfg_space = mem;
+
+	mem = kmalloc(info->mmio_size, GFP_KERNEL);
+	if (!mem) {
+		kfree(path);
+		kfree(firmware->cfg_space);
+		return -ENOMEM;
+	}
+
+	firmware->mmio = mem;
+
+	mmio = pci_iomap(pdev, info->mmio_bar, info->mmio_size);
+	if (!mmio) {
+		kfree(path);
+		kfree(firmware->cfg_space);
+		kfree(firmware->mmio);
+		return -EINVAL;
+	}
+
+	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv))
+		bdw_forcewake_get(mmio);
+
+	sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%04x.golden_hw_state",
+		 GVT_FIRMWARE_PATH, pdev->vendor, pdev->device,
+		 pdev->revision);
+
+	gvt_dbg_core("request hw state firmware %s...\n", path);
+
+	ret = reject_firmware(&fw, path, &dev_priv->drm.pdev->dev);
+	kfree(path);
+
+	if (ret)
+		goto expose_firmware;
+
+	gvt_dbg_core("success.\n");
+
+	ret = verify_firmware(gvt, fw);
+	if (ret)
+		goto out_free_fw;
+
+	gvt_dbg_core("verified.\n");
+
+	h = (struct gvt_firmware_header *)fw->data;
+
+	memcpy(firmware->cfg_space, fw->data + h->cfg_space_offset,
+	       h->cfg_space_size);
+	memcpy(firmware->mmio, fw->data + h->mmio_offset,
+	       h->mmio_size);
+
+	release_firmware(fw);
+	firmware->firmware_loaded = true;
+	pci_iounmap(pdev, mmio);
+	return 0;
+
+out_free_fw:
+	release_firmware(fw);
+expose_firmware:
+	expose_firmware_sysfs(gvt, mmio);
+	pci_iounmap(pdev, mmio);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gtt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gtt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gtt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gtt.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2306 @@
+/*
+ * GTT virtualization
+ *
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *    Zhenyu Wang <zhenyuw@linux.intel.com>
+ *    Xiao Zheng <xiao.zheng@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+#include "trace.h"
+
+static bool enable_out_of_sync = false;
+static int preallocated_oos_pages = 8192;
+
+/*
+ * validate a gm address and related range size,
+ * translate it to host gm address
+ */
+bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size)
+{
+	if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size
+			&& !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) {
+		gvt_err("vgpu%d: invalid range gmadr 0x%llx size 0x%x\n",
+				vgpu->id, addr, size);
+		return false;
+	}
+	return true;
+}
+
+/* translate a guest gmadr to host gmadr */
+int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr)
+{
+	if (WARN(!vgpu_gmadr_is_valid(vgpu, g_addr),
+		 "invalid guest gmadr %llx\n", g_addr))
+		return -EACCES;
+
+	if (vgpu_gmadr_is_aperture(vgpu, g_addr))
+		*h_addr = vgpu_aperture_gmadr_base(vgpu)
+			  + (g_addr - vgpu_aperture_offset(vgpu));
+	else
+		*h_addr = vgpu_hidden_gmadr_base(vgpu)
+			  + (g_addr - vgpu_hidden_offset(vgpu));
+	return 0;
+}
+
+/* translate a host gmadr to guest gmadr */
+int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr)
+{
+	if (WARN(!gvt_gmadr_is_valid(vgpu->gvt, h_addr),
+		 "invalid host gmadr %llx\n", h_addr))
+		return -EACCES;
+
+	if (gvt_gmadr_is_aperture(vgpu->gvt, h_addr))
+		*g_addr = vgpu_aperture_gmadr_base(vgpu)
+			+ (h_addr - gvt_aperture_gmadr_base(vgpu->gvt));
+	else
+		*g_addr = vgpu_hidden_gmadr_base(vgpu)
+			+ (h_addr - gvt_hidden_gmadr_base(vgpu->gvt));
+	return 0;
+}
+
+int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index,
+			     unsigned long *h_index)
+{
+	u64 h_addr;
+	int ret;
+
+	ret = intel_gvt_ggtt_gmadr_g2h(vgpu, g_index << GTT_PAGE_SHIFT,
+				       &h_addr);
+	if (ret)
+		return ret;
+
+	*h_index = h_addr >> GTT_PAGE_SHIFT;
+	return 0;
+}
+
+int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index,
+			     unsigned long *g_index)
+{
+	u64 g_addr;
+	int ret;
+
+	ret = intel_gvt_ggtt_gmadr_h2g(vgpu, h_index << GTT_PAGE_SHIFT,
+				       &g_addr);
+	if (ret)
+		return ret;
+
+	*g_index = g_addr >> GTT_PAGE_SHIFT;
+	return 0;
+}
+
+#define gtt_type_is_entry(type) \
+	(type > GTT_TYPE_INVALID && type < GTT_TYPE_PPGTT_ENTRY \
+	 && type != GTT_TYPE_PPGTT_PTE_ENTRY \
+	 && type != GTT_TYPE_PPGTT_ROOT_ENTRY)
+
+#define gtt_type_is_pt(type) \
+	(type >= GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX)
+
+#define gtt_type_is_pte_pt(type) \
+	(type == GTT_TYPE_PPGTT_PTE_PT)
+
+#define gtt_type_is_root_pointer(type) \
+	(gtt_type_is_entry(type) && type > GTT_TYPE_PPGTT_ROOT_ENTRY)
+
+#define gtt_init_entry(e, t, p, v) do { \
+	(e)->type = t; \
+	(e)->pdev = p; \
+	memcpy(&(e)->val64, &v, sizeof(v)); \
+} while (0)
+
+/*
+ * Mappings between GTT_TYPE* enumerations.
+ * Following information can be found according to the given type:
+ * - type of next level page table
+ * - type of entry inside this level page table
+ * - type of entry with PSE set
+ *
+ * If the given type doesn't have such a kind of information,
+ * e.g. give a l4 root entry type, then request to get its PSE type,
+ * give a PTE page table type, then request to get its next level page
+ * table type, as we know l4 root entry doesn't have a PSE bit,
+ * and a PTE page table doesn't have a next level page table type,
+ * GTT_TYPE_INVALID will be returned. This is useful when traversing a
+ * page table.
+ */
+
+struct gtt_type_table_entry {
+	int entry_type;
+	int next_pt_type;
+	int pse_entry_type;
+};
+
+#define GTT_TYPE_TABLE_ENTRY(type, e_type, npt_type, pse_type) \
+	[type] = { \
+		.entry_type = e_type, \
+		.next_pt_type = npt_type, \
+		.pse_entry_type = pse_type, \
+	}
+
+static struct gtt_type_table_entry gtt_type_table[] = {
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
+			GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
+			GTT_TYPE_PPGTT_PML4_PT,
+			GTT_TYPE_INVALID),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_PT,
+			GTT_TYPE_PPGTT_PML4_ENTRY,
+			GTT_TYPE_PPGTT_PDP_PT,
+			GTT_TYPE_INVALID),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_ENTRY,
+			GTT_TYPE_PPGTT_PML4_ENTRY,
+			GTT_TYPE_PPGTT_PDP_PT,
+			GTT_TYPE_INVALID),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_PT,
+			GTT_TYPE_PPGTT_PDP_ENTRY,
+			GTT_TYPE_PPGTT_PDE_PT,
+			GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
+			GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
+			GTT_TYPE_PPGTT_PDE_PT,
+			GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_ENTRY,
+			GTT_TYPE_PPGTT_PDP_ENTRY,
+			GTT_TYPE_PPGTT_PDE_PT,
+			GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_PT,
+			GTT_TYPE_PPGTT_PDE_ENTRY,
+			GTT_TYPE_PPGTT_PTE_PT,
+			GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_ENTRY,
+			GTT_TYPE_PPGTT_PDE_ENTRY,
+			GTT_TYPE_PPGTT_PTE_PT,
+			GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT,
+			GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+			GTT_TYPE_INVALID,
+			GTT_TYPE_INVALID),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+			GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+			GTT_TYPE_INVALID,
+			GTT_TYPE_INVALID),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_2M_ENTRY,
+			GTT_TYPE_PPGTT_PDE_ENTRY,
+			GTT_TYPE_INVALID,
+			GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_1G_ENTRY,
+			GTT_TYPE_PPGTT_PDP_ENTRY,
+			GTT_TYPE_INVALID,
+			GTT_TYPE_PPGTT_PTE_1G_ENTRY),
+	GTT_TYPE_TABLE_ENTRY(GTT_TYPE_GGTT_PTE,
+			GTT_TYPE_GGTT_PTE,
+			GTT_TYPE_INVALID,
+			GTT_TYPE_INVALID),
+};
+
+static inline int get_next_pt_type(int type)
+{
+	return gtt_type_table[type].next_pt_type;
+}
+
+static inline int get_entry_type(int type)
+{
+	return gtt_type_table[type].entry_type;
+}
+
+static inline int get_pse_type(int type)
+{
+	return gtt_type_table[type].pse_entry_type;
+}
+
+static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index)
+{
+	void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;
+
+	return readq(addr);
+}
+
+static void write_pte64(struct drm_i915_private *dev_priv,
+		unsigned long index, u64 pte)
+{
+	void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;
+
+	writeq(pte, addr);
+
+	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
+	POSTING_READ(GFX_FLSH_CNTL_GEN6);
+}
+
+static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt,
+		struct intel_gvt_gtt_entry *e,
+		unsigned long index, bool hypervisor_access, unsigned long gpa,
+		struct intel_vgpu *vgpu)
+{
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+	int ret;
+
+	if (WARN_ON(info->gtt_entry_size != 8))
+		return e;
+
+	if (hypervisor_access) {
+		ret = intel_gvt_hypervisor_read_gpa(vgpu, gpa +
+				(index << info->gtt_entry_size_shift),
+				&e->val64, 8);
+		WARN_ON(ret);
+	} else if (!pt) {
+		e->val64 = read_pte64(vgpu->gvt->dev_priv, index);
+	} else {
+		e->val64 = *((u64 *)pt + index);
+	}
+	return e;
+}
+
+static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt,
+		struct intel_gvt_gtt_entry *e,
+		unsigned long index, bool hypervisor_access, unsigned long gpa,
+		struct intel_vgpu *vgpu)
+{
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+	int ret;
+
+	if (WARN_ON(info->gtt_entry_size != 8))
+		return e;
+
+	if (hypervisor_access) {
+		ret = intel_gvt_hypervisor_write_gpa(vgpu, gpa +
+				(index << info->gtt_entry_size_shift),
+				&e->val64, 8);
+		WARN_ON(ret);
+	} else if (!pt) {
+		write_pte64(vgpu->gvt->dev_priv, index, e->val64);
+	} else {
+		*((u64 *)pt + index) = e->val64;
+	}
+	return e;
+}
+
+#define GTT_HAW 46
+
+#define ADDR_1G_MASK (((1UL << (GTT_HAW - 30 + 1)) - 1) << 30)
+#define ADDR_2M_MASK (((1UL << (GTT_HAW - 21 + 1)) - 1) << 21)
+#define ADDR_4K_MASK (((1UL << (GTT_HAW - 12 + 1)) - 1) << 12)
+
+static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
+{
+	unsigned long pfn;
+
+	if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY)
+		pfn = (e->val64 & ADDR_1G_MASK) >> 12;
+	else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY)
+		pfn = (e->val64 & ADDR_2M_MASK) >> 12;
+	else
+		pfn = (e->val64 & ADDR_4K_MASK) >> 12;
+	return pfn;
+}
+
+static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry *e, unsigned long pfn)
+{
+	if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY) {
+		e->val64 &= ~ADDR_1G_MASK;
+		pfn &= (ADDR_1G_MASK >> 12);
+	} else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) {
+		e->val64 &= ~ADDR_2M_MASK;
+		pfn &= (ADDR_2M_MASK >> 12);
+	} else {
+		e->val64 &= ~ADDR_4K_MASK;
+		pfn &= (ADDR_4K_MASK >> 12);
+	}
+
+	e->val64 |= (pfn << 12);
+}
+
+static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry *e)
+{
+	/* Entry doesn't have PSE bit. */
+	if (get_pse_type(e->type) == GTT_TYPE_INVALID)
+		return false;
+
+	e->type = get_entry_type(e->type);
+	if (!(e->val64 & (1 << 7)))
+		return false;
+
+	e->type = get_pse_type(e->type);
+	return true;
+}
+
+static bool gen8_gtt_test_present(struct intel_gvt_gtt_entry *e)
+{
+	/*
+	 * i915 writes PDP root pointer registers without present bit,
+	 * it also works, so we need to treat root pointer entry
+	 * specifically.
+	 */
+	if (e->type == GTT_TYPE_PPGTT_ROOT_L3_ENTRY
+			|| e->type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY)
+		return (e->val64 != 0);
+	else
+		return (e->val64 & (1 << 0));
+}
+
+static void gtt_entry_clear_present(struct intel_gvt_gtt_entry *e)
+{
+	e->val64 &= ~(1 << 0);
+}
+
+/*
+ * Per-platform GMA routines.
+ */
+static unsigned long gma_to_ggtt_pte_index(unsigned long gma)
+{
+	unsigned long x = (gma >> GTT_PAGE_SHIFT);
+
+	trace_gma_index(__func__, gma, x);
+	return x;
+}
+
+#define DEFINE_PPGTT_GMA_TO_INDEX(prefix, ename, exp) \
+static unsigned long prefix##_gma_to_##ename##_index(unsigned long gma) \
+{ \
+	unsigned long x = (exp); \
+	trace_gma_index(__func__, gma, x); \
+	return x; \
+}
+
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, pte, (gma >> 12 & 0x1ff));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, pde, (gma >> 21 & 0x1ff));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, l3_pdp, (gma >> 30 & 0x3));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, l4_pdp, (gma >> 30 & 0x1ff));
+DEFINE_PPGTT_GMA_TO_INDEX(gen8, pml4, (gma >> 39 & 0x1ff));
+
+static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
+	.get_entry = gtt_get_entry64,
+	.set_entry = gtt_set_entry64,
+	.clear_present = gtt_entry_clear_present,
+	.test_present = gen8_gtt_test_present,
+	.test_pse = gen8_gtt_test_pse,
+	.get_pfn = gen8_gtt_get_pfn,
+	.set_pfn = gen8_gtt_set_pfn,
+};
+
+static struct intel_gvt_gtt_gma_ops gen8_gtt_gma_ops = {
+	.gma_to_ggtt_pte_index = gma_to_ggtt_pte_index,
+	.gma_to_pte_index = gen8_gma_to_pte_index,
+	.gma_to_pde_index = gen8_gma_to_pde_index,
+	.gma_to_l3_pdp_index = gen8_gma_to_l3_pdp_index,
+	.gma_to_l4_pdp_index = gen8_gma_to_l4_pdp_index,
+	.gma_to_pml4_index = gen8_gma_to_pml4_index,
+};
+
+static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,
+		struct intel_gvt_gtt_entry *m)
+{
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	unsigned long gfn, mfn;
+
+	*m = *p;
+
+	if (!ops->test_present(p))
+		return 0;
+
+	gfn = ops->get_pfn(p);
+
+	mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn);
+	if (mfn == INTEL_GVT_INVALID_ADDR) {
+		gvt_err("fail to translate gfn: 0x%lx\n", gfn);
+		return -ENXIO;
+	}
+
+	ops->set_pfn(m, mfn);
+	return 0;
+}
+
+/*
+ * MM helpers.
+ */
+struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm,
+		void *page_table, struct intel_gvt_gtt_entry *e,
+		unsigned long index)
+{
+	struct intel_gvt *gvt = mm->vgpu->gvt;
+	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+	e->type = mm->page_table_entry_type;
+
+	ops->get_entry(page_table, e, index, false, 0, mm->vgpu);
+	ops->test_pse(e);
+	return e;
+}
+
+struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
+		void *page_table, struct intel_gvt_gtt_entry *e,
+		unsigned long index)
+{
+	struct intel_gvt *gvt = mm->vgpu->gvt;
+	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+	return ops->set_entry(page_table, e, index, false, 0, mm->vgpu);
+}
+
+/*
+ * PPGTT shadow page table helpers.
+ */
+static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry(
+		struct intel_vgpu_ppgtt_spt *spt,
+		void *page_table, int type,
+		struct intel_gvt_gtt_entry *e, unsigned long index,
+		bool guest)
+{
+	struct intel_gvt *gvt = spt->vgpu->gvt;
+	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+	e->type = get_entry_type(type);
+
+	if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
+		return e;
+
+	ops->get_entry(page_table, e, index, guest,
+			spt->guest_page.gfn << GTT_PAGE_SHIFT,
+			spt->vgpu);
+	ops->test_pse(e);
+	return e;
+}
+
+static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry(
+		struct intel_vgpu_ppgtt_spt *spt,
+		void *page_table, int type,
+		struct intel_gvt_gtt_entry *e, unsigned long index,
+		bool guest)
+{
+	struct intel_gvt *gvt = spt->vgpu->gvt;
+	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+
+	if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
+		return e;
+
+	return ops->set_entry(page_table, e, index, guest,
+			spt->guest_page.gfn << GTT_PAGE_SHIFT,
+			spt->vgpu);
+}
+
+#define ppgtt_get_guest_entry(spt, e, index) \
+	ppgtt_spt_get_entry(spt, NULL, \
+		spt->guest_page_type, e, index, true)
+
+#define ppgtt_set_guest_entry(spt, e, index) \
+	ppgtt_spt_set_entry(spt, NULL, \
+		spt->guest_page_type, e, index, true)
+
+#define ppgtt_get_shadow_entry(spt, e, index) \
+	ppgtt_spt_get_entry(spt, spt->shadow_page.vaddr, \
+		spt->shadow_page.type, e, index, false)
+
+#define ppgtt_set_shadow_entry(spt, e, index) \
+	ppgtt_spt_set_entry(spt, spt->shadow_page.vaddr, \
+		spt->shadow_page.type, e, index, false)
+
+/**
+ * intel_vgpu_init_guest_page - init a guest page data structure
+ * @vgpu: a vGPU
+ * @p: a guest page data structure
+ * @gfn: guest memory page frame number
+ * @handler: function will be called when target guest memory page has
+ * been modified.
+ *
+ * This function is called when user wants to track a guest memory page.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *p,
+		unsigned long gfn,
+		int (*handler)(void *, u64, void *, int),
+		void *data)
+{
+	INIT_HLIST_NODE(&p->node);
+
+	p->writeprotection = false;
+	p->gfn = gfn;
+	p->handler = handler;
+	p->data = data;
+	p->oos_page = NULL;
+	p->write_cnt = 0;
+
+	hash_add(vgpu->gtt.guest_page_hash_table, &p->node, p->gfn);
+	return 0;
+}
+
+static int detach_oos_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_oos_page *oos_page);
+
+/**
+ * intel_vgpu_clean_guest_page - release the resource owned by guest page data
+ * structure
+ * @vgpu: a vGPU
+ * @p: a tracked guest page
+ *
+ * This function is called when user tries to stop tracking a guest memory
+ * page.
+ */
+void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *p)
+{
+	if (!hlist_unhashed(&p->node))
+		hash_del(&p->node);
+
+	if (p->oos_page)
+		detach_oos_page(vgpu, p->oos_page);
+
+	if (p->writeprotection)
+		intel_gvt_hypervisor_unset_wp_page(vgpu, p);
+}
+
+/**
+ * intel_vgpu_find_guest_page - find a guest page data structure by GFN.
+ * @vgpu: a vGPU
+ * @gfn: guest memory page frame number
+ *
+ * This function is called when emulation logic wants to know if a trapped GFN
+ * is a tracked guest page.
+ *
+ * Returns:
+ * Pointer to guest page data structure, NULL if failed.
+ */
+struct intel_vgpu_guest_page *intel_vgpu_find_guest_page(
+		struct intel_vgpu *vgpu, unsigned long gfn)
+{
+	struct intel_vgpu_guest_page *p;
+
+	hash_for_each_possible(vgpu->gtt.guest_page_hash_table,
+		p, node, gfn) {
+		if (p->gfn == gfn)
+			return p;
+	}
+	return NULL;
+}
+
+static inline int init_shadow_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_shadow_page *p, int type)
+{
+	p->vaddr = page_address(p->page);
+	p->type = type;
+
+	INIT_HLIST_NODE(&p->node);
+
+	p->mfn = intel_gvt_hypervisor_virt_to_mfn(p->vaddr);
+	if (p->mfn == INTEL_GVT_INVALID_ADDR)
+		return -EFAULT;
+
+	hash_add(vgpu->gtt.shadow_page_hash_table, &p->node, p->mfn);
+	return 0;
+}
+
+static inline void clean_shadow_page(struct intel_vgpu_shadow_page *p)
+{
+	if (!hlist_unhashed(&p->node))
+		hash_del(&p->node);
+}
+
+static inline struct intel_vgpu_shadow_page *find_shadow_page(
+		struct intel_vgpu *vgpu, unsigned long mfn)
+{
+	struct intel_vgpu_shadow_page *p;
+
+	hash_for_each_possible(vgpu->gtt.shadow_page_hash_table,
+		p, node, mfn) {
+		if (p->mfn == mfn)
+			return p;
+	}
+	return NULL;
+}
+
+#define guest_page_to_ppgtt_spt(ptr) \
+	container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page)
+
+#define shadow_page_to_ppgtt_spt(ptr) \
+	container_of(ptr, struct intel_vgpu_ppgtt_spt, shadow_page)
+
+static void *alloc_spt(gfp_t gfp_mask)
+{
+	struct intel_vgpu_ppgtt_spt *spt;
+
+	spt = kzalloc(sizeof(*spt), gfp_mask);
+	if (!spt)
+		return NULL;
+
+	spt->shadow_page.page = alloc_page(gfp_mask);
+	if (!spt->shadow_page.page) {
+		kfree(spt);
+		return NULL;
+	}
+	return spt;
+}
+
+static void free_spt(struct intel_vgpu_ppgtt_spt *spt)
+{
+	__free_page(spt->shadow_page.page);
+	kfree(spt);
+}
+
+static void ppgtt_free_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+	trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type);
+
+	clean_shadow_page(&spt->shadow_page);
+	intel_vgpu_clean_guest_page(spt->vgpu, &spt->guest_page);
+	list_del_init(&spt->post_shadow_list);
+
+	free_spt(spt);
+}
+
+static void ppgtt_free_all_shadow_page(struct intel_vgpu *vgpu)
+{
+	struct hlist_node *n;
+	struct intel_vgpu_shadow_page *sp;
+	int i;
+
+	hash_for_each_safe(vgpu->gtt.shadow_page_hash_table, i, n, sp, node)
+		ppgtt_free_shadow_page(shadow_page_to_ppgtt_spt(sp));
+}
+
+static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
+		u64 pa, void *p_data, int bytes);
+
+static int ppgtt_write_protection_handler(void *gp, u64 pa,
+		void *p_data, int bytes)
+{
+	struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp;
+	int ret;
+
+	if (bytes != 4 && bytes != 8)
+		return -EINVAL;
+
+	if (!gpt->writeprotection)
+		return -EINVAL;
+
+	ret = ppgtt_handle_guest_write_page_table_bytes(gp,
+		pa, p_data, bytes);
+	if (ret)
+		return ret;
+	return ret;
+}
+
+static int reclaim_one_mm(struct intel_gvt *gvt);
+
+static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page(
+		struct intel_vgpu *vgpu, int type, unsigned long gfn)
+{
+	struct intel_vgpu_ppgtt_spt *spt = NULL;
+	int ret;
+
+retry:
+	spt = alloc_spt(GFP_KERNEL | __GFP_ZERO);
+	if (!spt) {
+		if (reclaim_one_mm(vgpu->gvt))
+			goto retry;
+
+		gvt_err("fail to allocate ppgtt shadow page\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	spt->vgpu = vgpu;
+	spt->guest_page_type = type;
+	atomic_set(&spt->refcount, 1);
+	INIT_LIST_HEAD(&spt->post_shadow_list);
+
+	/*
+	 * TODO: guest page type may be different with shadow page type,
+	 *	 when we support PSE page in future.
+	 */
+	ret = init_shadow_page(vgpu, &spt->shadow_page, type);
+	if (ret) {
+		gvt_err("fail to initialize shadow page for spt\n");
+		goto err;
+	}
+
+	ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page,
+			gfn, ppgtt_write_protection_handler, NULL);
+	if (ret) {
+		gvt_err("fail to initialize guest page for spt\n");
+		goto err;
+	}
+
+	trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
+	return spt;
+err:
+	ppgtt_free_shadow_page(spt);
+	return ERR_PTR(ret);
+}
+
+static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page(
+		struct intel_vgpu *vgpu, unsigned long mfn)
+{
+	struct intel_vgpu_shadow_page *p = find_shadow_page(vgpu, mfn);
+
+	if (p)
+		return shadow_page_to_ppgtt_spt(p);
+
+	gvt_err("vgpu%d: fail to find ppgtt shadow page: 0x%lx\n",
+			vgpu->id, mfn);
+	return NULL;
+}
+
+#define pt_entry_size_shift(spt) \
+	((spt)->vgpu->gvt->device_info.gtt_entry_size_shift)
+
+#define pt_entries(spt) \
+	(GTT_PAGE_SIZE >> pt_entry_size_shift(spt))
+
+#define for_each_present_guest_entry(spt, e, i) \
+	for (i = 0; i < pt_entries(spt); i++) \
+	if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
+		ppgtt_get_guest_entry(spt, e, i)))
+
+#define for_each_present_shadow_entry(spt, e, i) \
+	for (i = 0; i < pt_entries(spt); i++) \
+	if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
+		ppgtt_get_shadow_entry(spt, e, i)))
+
+static void ppgtt_get_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+	int v = atomic_read(&spt->refcount);
+
+	trace_spt_refcount(spt->vgpu->id, "inc", spt, v, (v + 1));
+
+	atomic_inc(&spt->refcount);
+}
+
+static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt);
+
+static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu,
+		struct intel_gvt_gtt_entry *e)
+{
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	struct intel_vgpu_ppgtt_spt *s;
+	intel_gvt_gtt_type_t cur_pt_type;
+
+	if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(e->type))))
+		return -EINVAL;
+
+	if (e->type != GTT_TYPE_PPGTT_ROOT_L3_ENTRY
+		&& e->type != GTT_TYPE_PPGTT_ROOT_L4_ENTRY) {
+		cur_pt_type = get_next_pt_type(e->type) + 1;
+		if (ops->get_pfn(e) ==
+			vgpu->gtt.scratch_pt[cur_pt_type].page_mfn)
+			return 0;
+	}
+	s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e));
+	if (!s) {
+		gvt_err("vgpu%d: fail to find shadow page: mfn: 0x%lx\n",
+				vgpu->id, ops->get_pfn(e));
+		return -ENXIO;
+	}
+	return ppgtt_invalidate_shadow_page(s);
+}
+
+static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+	struct intel_gvt_gtt_entry e;
+	unsigned long index;
+	int ret;
+	int v = atomic_read(&spt->refcount);
+
+	trace_spt_change(spt->vgpu->id, "die", spt,
+			spt->guest_page.gfn, spt->shadow_page.type);
+
+	trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1));
+
+	if (atomic_dec_return(&spt->refcount) > 0)
+		return 0;
+
+	if (gtt_type_is_pte_pt(spt->shadow_page.type))
+		goto release;
+
+	for_each_present_shadow_entry(spt, &e, index) {
+		if (!gtt_type_is_pt(get_next_pt_type(e.type))) {
+			gvt_err("GVT doesn't support pse bit for now\n");
+			return -EINVAL;
+		}
+		ret = ppgtt_invalidate_shadow_page_by_shadow_entry(
+				spt->vgpu, &e);
+		if (ret)
+			goto fail;
+	}
+release:
+	trace_spt_change(spt->vgpu->id, "release", spt,
+			spt->guest_page.gfn, spt->shadow_page.type);
+	ppgtt_free_shadow_page(spt);
+	return 0;
+fail:
+	gvt_err("vgpu%d: fail: shadow page %p shadow entry 0x%llx type %d\n",
+			spt->vgpu->id, spt, e.val64, e.type);
+	return ret;
+}
+
+static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt);
+
+static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry(
+		struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *we)
+{
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	struct intel_vgpu_ppgtt_spt *s = NULL;
+	struct intel_vgpu_guest_page *g;
+	int ret;
+
+	if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) {
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	g = intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we));
+	if (g) {
+		s = guest_page_to_ppgtt_spt(g);
+		ppgtt_get_shadow_page(s);
+	} else {
+		int type = get_next_pt_type(we->type);
+
+		s = ppgtt_alloc_shadow_page(vgpu, type, ops->get_pfn(we));
+		if (IS_ERR(s)) {
+			ret = PTR_ERR(s);
+			goto fail;
+		}
+
+		ret = intel_gvt_hypervisor_set_wp_page(vgpu, &s->guest_page);
+		if (ret)
+			goto fail;
+
+		ret = ppgtt_populate_shadow_page(s);
+		if (ret)
+			goto fail;
+
+		trace_spt_change(vgpu->id, "new", s, s->guest_page.gfn,
+			s->shadow_page.type);
+	}
+	return s;
+fail:
+	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
+			vgpu->id, s, we->val64, we->type);
+	return ERR_PTR(ret);
+}
+
+static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se,
+		struct intel_vgpu_ppgtt_spt *s, struct intel_gvt_gtt_entry *ge)
+{
+	struct intel_gvt_gtt_pte_ops *ops = s->vgpu->gvt->gtt.pte_ops;
+
+	se->type = ge->type;
+	se->val64 = ge->val64;
+
+	ops->set_pfn(se, s->shadow_page.mfn);
+}
+
+static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
+{
+	struct intel_vgpu *vgpu = spt->vgpu;
+	struct intel_vgpu_ppgtt_spt *s;
+	struct intel_gvt_gtt_entry se, ge;
+	unsigned long i;
+	int ret;
+
+	trace_spt_change(spt->vgpu->id, "born", spt,
+			spt->guest_page.gfn, spt->shadow_page.type);
+
+	if (gtt_type_is_pte_pt(spt->shadow_page.type)) {
+		for_each_present_guest_entry(spt, &ge, i) {
+			ret = gtt_entry_p2m(vgpu, &ge, &se);
+			if (ret)
+				goto fail;
+			ppgtt_set_shadow_entry(spt, &se, i);
+		}
+		return 0;
+	}
+
+	for_each_present_guest_entry(spt, &ge, i) {
+		if (!gtt_type_is_pt(get_next_pt_type(ge.type))) {
+			gvt_err("GVT doesn't support pse bit now\n");
+			ret = -EINVAL;
+			goto fail;
+		}
+
+		s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);
+		if (IS_ERR(s)) {
+			ret = PTR_ERR(s);
+			goto fail;
+		}
+		ppgtt_get_shadow_entry(spt, &se, i);
+		ppgtt_generate_shadow_entry(&se, s, &ge);
+		ppgtt_set_shadow_entry(spt, &se, i);
+	}
+	return 0;
+fail:
+	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
+			vgpu->id, spt, ge.val64, ge.type);
+	return ret;
+}
+
+static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
+		unsigned long index)
+{
+	struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+	struct intel_vgpu_shadow_page *sp = &spt->shadow_page;
+	struct intel_vgpu *vgpu = spt->vgpu;
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	struct intel_gvt_gtt_entry e;
+	int ret;
+
+	ppgtt_get_shadow_entry(spt, &e, index);
+
+	trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, e.val64,
+			 index);
+
+	if (!ops->test_present(&e))
+		return 0;
+
+	if (ops->get_pfn(&e) == vgpu->gtt.scratch_pt[sp->type].page_mfn)
+		return 0;
+
+	if (gtt_type_is_pt(get_next_pt_type(e.type))) {
+		struct intel_vgpu_ppgtt_spt *s =
+			ppgtt_find_shadow_page(vgpu, ops->get_pfn(&e));
+		if (!s) {
+			gvt_err("fail to find guest page\n");
+			ret = -ENXIO;
+			goto fail;
+		}
+		ret = ppgtt_invalidate_shadow_page(s);
+		if (ret)
+			goto fail;
+	}
+	ops->set_pfn(&e, vgpu->gtt.scratch_pt[sp->type].page_mfn);
+	ppgtt_set_shadow_entry(spt, &e, index);
+	return 0;
+fail:
+	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n",
+			vgpu->id, spt, e.val64, e.type);
+	return ret;
+}
+
+static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt,
+		struct intel_gvt_gtt_entry *we, unsigned long index)
+{
+	struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+	struct intel_vgpu_shadow_page *sp = &spt->shadow_page;
+	struct intel_vgpu *vgpu = spt->vgpu;
+	struct intel_gvt_gtt_entry m;
+	struct intel_vgpu_ppgtt_spt *s;
+	int ret;
+
+	trace_gpt_change(spt->vgpu->id, "add", spt, sp->type,
+		we->val64, index);
+
+	if (gtt_type_is_pt(get_next_pt_type(we->type))) {
+		s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, we);
+		if (IS_ERR(s)) {
+			ret = PTR_ERR(s);
+			goto fail;
+		}
+		ppgtt_get_shadow_entry(spt, &m, index);
+		ppgtt_generate_shadow_entry(&m, s, we);
+		ppgtt_set_shadow_entry(spt, &m, index);
+	} else {
+		ret = gtt_entry_p2m(vgpu, we, &m);
+		if (ret)
+			goto fail;
+		ppgtt_set_shadow_entry(spt, &m, index);
+	}
+	return 0;
+fail:
+	gvt_err("vgpu%d: fail: spt %p guest entry 0x%llx type %d\n", vgpu->id,
+			spt, we->val64, we->type);
+	return ret;
+}
+
+static int sync_oos_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_oos_page *oos_page)
+{
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+	struct intel_vgpu_ppgtt_spt *spt =
+		guest_page_to_ppgtt_spt(oos_page->guest_page);
+	struct intel_gvt_gtt_entry old, new, m;
+	int index;
+	int ret;
+
+	trace_oos_change(vgpu->id, "sync", oos_page->id,
+			oos_page->guest_page, spt->guest_page_type);
+
+	old.type = new.type = get_entry_type(spt->guest_page_type);
+	old.val64 = new.val64 = 0;
+
+	for (index = 0; index < (GTT_PAGE_SIZE >> info->gtt_entry_size_shift);
+		index++) {
+		ops->get_entry(oos_page->mem, &old, index, false, 0, vgpu);
+		ops->get_entry(NULL, &new, index, true,
+			oos_page->guest_page->gfn << PAGE_SHIFT, vgpu);
+
+		if (old.val64 == new.val64
+			&& !test_and_clear_bit(index, spt->post_shadow_bitmap))
+			continue;
+
+		trace_oos_sync(vgpu->id, oos_page->id,
+				oos_page->guest_page, spt->guest_page_type,
+				new.val64, index);
+
+		ret = gtt_entry_p2m(vgpu, &new, &m);
+		if (ret)
+			return ret;
+
+		ops->set_entry(oos_page->mem, &new, index, false, 0, vgpu);
+		ppgtt_set_shadow_entry(spt, &m, index);
+	}
+
+	oos_page->guest_page->write_cnt = 0;
+	list_del_init(&spt->post_shadow_list);
+	return 0;
+}
+
+static int detach_oos_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_oos_page *oos_page)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_vgpu_ppgtt_spt *spt =
+		guest_page_to_ppgtt_spt(oos_page->guest_page);
+
+	trace_oos_change(vgpu->id, "detach", oos_page->id,
+			oos_page->guest_page, spt->guest_page_type);
+
+	oos_page->guest_page->write_cnt = 0;
+	oos_page->guest_page->oos_page = NULL;
+	oos_page->guest_page = NULL;
+
+	list_del_init(&oos_page->vm_list);
+	list_move_tail(&oos_page->list, &gvt->gtt.oos_page_free_list_head);
+
+	return 0;
+}
+
+static int attach_oos_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_oos_page *oos_page,
+		struct intel_vgpu_guest_page *gpt)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	int ret;
+
+	ret = intel_gvt_hypervisor_read_gpa(vgpu, gpt->gfn << GTT_PAGE_SHIFT,
+		oos_page->mem, GTT_PAGE_SIZE);
+	if (ret)
+		return ret;
+
+	oos_page->guest_page = gpt;
+	gpt->oos_page = oos_page;
+
+	list_move_tail(&oos_page->list, &gvt->gtt.oos_page_use_list_head);
+
+	trace_oos_change(vgpu->id, "attach", gpt->oos_page->id,
+			gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type);
+	return 0;
+}
+
+static int ppgtt_set_guest_page_sync(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *gpt)
+{
+	int ret;
+
+	ret = intel_gvt_hypervisor_set_wp_page(vgpu, gpt);
+	if (ret)
+		return ret;
+
+	trace_oos_change(vgpu->id, "set page sync", gpt->oos_page->id,
+			gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type);
+
+	list_del_init(&gpt->oos_page->vm_list);
+	return sync_oos_page(vgpu, gpt->oos_page);
+}
+
+static int ppgtt_allocate_oos_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *gpt)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct intel_vgpu_oos_page *oos_page = gpt->oos_page;
+	int ret;
+
+	WARN(oos_page, "shadow PPGTT page has already has a oos page\n");
+
+	if (list_empty(&gtt->oos_page_free_list_head)) {
+		oos_page = container_of(gtt->oos_page_use_list_head.next,
+			struct intel_vgpu_oos_page, list);
+		ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page);
+		if (ret)
+			return ret;
+		ret = detach_oos_page(vgpu, oos_page);
+		if (ret)
+			return ret;
+	} else
+		oos_page = container_of(gtt->oos_page_free_list_head.next,
+			struct intel_vgpu_oos_page, list);
+	return attach_oos_page(vgpu, oos_page, gpt);
+}
+
+static int ppgtt_set_guest_page_oos(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *gpt)
+{
+	struct intel_vgpu_oos_page *oos_page = gpt->oos_page;
+
+	if (WARN(!oos_page, "shadow PPGTT page should have a oos page\n"))
+		return -EINVAL;
+
+	trace_oos_change(vgpu->id, "set page out of sync", gpt->oos_page->id,
+			gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type);
+
+	list_add_tail(&oos_page->vm_list, &vgpu->gtt.oos_page_list_head);
+	return intel_gvt_hypervisor_unset_wp_page(vgpu, gpt);
+}
+
+/**
+ * intel_vgpu_sync_oos_pages - sync all the out-of-synced shadow for vGPU
+ * @vgpu: a vGPU
+ *
+ * This function is called before submitting a guest workload to host,
+ * to sync all the out-of-synced shadow for vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu)
+{
+	struct list_head *pos, *n;
+	struct intel_vgpu_oos_page *oos_page;
+	int ret;
+
+	if (!enable_out_of_sync)
+		return 0;
+
+	list_for_each_safe(pos, n, &vgpu->gtt.oos_page_list_head) {
+		oos_page = container_of(pos,
+				struct intel_vgpu_oos_page, vm_list);
+		ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+/*
+ * The heart of PPGTT shadow page table.
+ */
+static int ppgtt_handle_guest_write_page_table(
+		struct intel_vgpu_guest_page *gpt,
+		struct intel_gvt_gtt_entry *we, unsigned long index)
+{
+	struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+	struct intel_vgpu *vgpu = spt->vgpu;
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+
+	int ret;
+	int new_present;
+
+	new_present = ops->test_present(we);
+
+	ret = ppgtt_handle_guest_entry_removal(gpt, index);
+	if (ret)
+		goto fail;
+
+	if (new_present) {
+		ret = ppgtt_handle_guest_entry_add(gpt, we, index);
+		if (ret)
+			goto fail;
+	}
+	return 0;
+fail:
+	gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d.\n",
+			vgpu->id, spt, we->val64, we->type);
+	return ret;
+}
+
+static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt)
+{
+	return enable_out_of_sync
+		&& gtt_type_is_pte_pt(
+			guest_page_to_ppgtt_spt(gpt)->guest_page_type)
+		&& gpt->write_cnt >= 2;
+}
+
+static void ppgtt_set_post_shadow(struct intel_vgpu_ppgtt_spt *spt,
+		unsigned long index)
+{
+	set_bit(index, spt->post_shadow_bitmap);
+	if (!list_empty(&spt->post_shadow_list))
+		return;
+
+	list_add_tail(&spt->post_shadow_list,
+			&spt->vgpu->gtt.post_shadow_list_head);
+}
+
+/**
+ * intel_vgpu_flush_post_shadow - flush the post shadow transactions
+ * @vgpu: a vGPU
+ *
+ * This function is called before submitting a guest workload to host,
+ * to flush all the post shadows for a vGPU.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu)
+{
+	struct list_head *pos, *n;
+	struct intel_vgpu_ppgtt_spt *spt;
+	struct intel_gvt_gtt_entry ge;
+	unsigned long index;
+	int ret;
+
+	list_for_each_safe(pos, n, &vgpu->gtt.post_shadow_list_head) {
+		spt = container_of(pos, struct intel_vgpu_ppgtt_spt,
+				post_shadow_list);
+
+		for_each_set_bit(index, spt->post_shadow_bitmap,
+				GTT_ENTRY_NUM_IN_ONE_PAGE) {
+			ppgtt_get_guest_entry(spt, &ge, index);
+
+			ret = ppgtt_handle_guest_write_page_table(
+					&spt->guest_page, &ge, index);
+			if (ret)
+				return ret;
+			clear_bit(index, spt->post_shadow_bitmap);
+		}
+		list_del_init(&spt->post_shadow_list);
+	}
+	return 0;
+}
+
+static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
+		u64 pa, void *p_data, int bytes)
+{
+	struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp;
+	struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
+	struct intel_vgpu *vgpu = spt->vgpu;
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+	struct intel_gvt_gtt_entry we;
+	unsigned long index;
+	int ret;
+
+	index = (pa & (PAGE_SIZE - 1)) >> info->gtt_entry_size_shift;
+
+	ppgtt_get_guest_entry(spt, &we, index);
+
+	ops->test_pse(&we);
+
+	if (bytes == info->gtt_entry_size) {
+		ret = ppgtt_handle_guest_write_page_table(gpt, &we, index);
+		if (ret)
+			return ret;
+	} else {
+		if (!test_bit(index, spt->post_shadow_bitmap)) {
+			ret = ppgtt_handle_guest_entry_removal(gpt, index);
+			if (ret)
+				return ret;
+		}
+
+		ppgtt_set_post_shadow(spt, index);
+	}
+
+	if (!enable_out_of_sync)
+		return 0;
+
+	gpt->write_cnt++;
+
+	if (gpt->oos_page)
+		ops->set_entry(gpt->oos_page->mem, &we, index,
+				false, 0, vgpu);
+
+	if (can_do_out_of_sync(gpt)) {
+		if (!gpt->oos_page)
+			ppgtt_allocate_oos_page(vgpu, gpt);
+
+		ret = ppgtt_set_guest_page_oos(vgpu, gpt);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+/*
+ * mm page table allocation policy for bdw+
+ *  - for ggtt, only virtual page table will be allocated.
+ *  - for ppgtt, dedicated virtual/shadow page table will be allocated.
+ */
+static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm)
+{
+	struct intel_vgpu *vgpu = mm->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+	const struct intel_gvt_device_info *info = &gvt->device_info;
+	void *mem;
+
+	if (mm->type == INTEL_GVT_MM_PPGTT) {
+		mm->page_table_entry_cnt = 4;
+		mm->page_table_entry_size = mm->page_table_entry_cnt *
+			info->gtt_entry_size;
+		mem = kzalloc(mm->has_shadow_page_table ?
+			mm->page_table_entry_size * 2
+				: mm->page_table_entry_size, GFP_KERNEL);
+		if (!mem)
+			return -ENOMEM;
+		mm->virtual_page_table = mem;
+		if (!mm->has_shadow_page_table)
+			return 0;
+		mm->shadow_page_table = mem + mm->page_table_entry_size;
+	} else if (mm->type == INTEL_GVT_MM_GGTT) {
+		mm->page_table_entry_cnt =
+			(gvt_ggtt_gm_sz(gvt) >> GTT_PAGE_SHIFT);
+		mm->page_table_entry_size = mm->page_table_entry_cnt *
+			info->gtt_entry_size;
+		mem = vzalloc(mm->page_table_entry_size);
+		if (!mem)
+			return -ENOMEM;
+		mm->virtual_page_table = mem;
+	}
+	return 0;
+}
+
+static void gen8_mm_free_page_table(struct intel_vgpu_mm *mm)
+{
+	if (mm->type == INTEL_GVT_MM_PPGTT) {
+		kfree(mm->virtual_page_table);
+	} else if (mm->type == INTEL_GVT_MM_GGTT) {
+		if (mm->virtual_page_table)
+			vfree(mm->virtual_page_table);
+	}
+	mm->virtual_page_table = mm->shadow_page_table = NULL;
+}
+
+static void invalidate_mm(struct intel_vgpu_mm *mm)
+{
+	struct intel_vgpu *vgpu = mm->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops;
+	struct intel_gvt_gtt_entry se;
+	int i;
+
+	if (WARN_ON(!mm->has_shadow_page_table || !mm->shadowed))
+		return;
+
+	for (i = 0; i < mm->page_table_entry_cnt; i++) {
+		ppgtt_get_shadow_root_entry(mm, &se, i);
+		if (!ops->test_present(&se))
+			continue;
+		ppgtt_invalidate_shadow_page_by_shadow_entry(
+				vgpu, &se);
+		se.val64 = 0;
+		ppgtt_set_shadow_root_entry(mm, &se, i);
+
+		trace_gpt_change(vgpu->id, "destroy root pointer",
+				NULL, se.type, se.val64, i);
+	}
+	mm->shadowed = false;
+}
+
+/**
+ * intel_vgpu_destroy_mm - destroy a mm object
+ * @mm: a kref object
+ *
+ * This function is used to destroy a mm object for vGPU
+ *
+ */
+void intel_vgpu_destroy_mm(struct kref *mm_ref)
+{
+	struct intel_vgpu_mm *mm = container_of(mm_ref, typeof(*mm), ref);
+	struct intel_vgpu *vgpu = mm->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+
+	if (!mm->initialized)
+		goto out;
+
+	list_del(&mm->list);
+	list_del(&mm->lru_list);
+
+	if (mm->has_shadow_page_table)
+		invalidate_mm(mm);
+
+	gtt->mm_free_page_table(mm);
+out:
+	kfree(mm);
+}
+
+static int shadow_mm(struct intel_vgpu_mm *mm)
+{
+	struct intel_vgpu *vgpu = mm->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops;
+	struct intel_vgpu_ppgtt_spt *spt;
+	struct intel_gvt_gtt_entry ge, se;
+	int i;
+	int ret;
+
+	if (WARN_ON(!mm->has_shadow_page_table || mm->shadowed))
+		return 0;
+
+	mm->shadowed = true;
+
+	for (i = 0; i < mm->page_table_entry_cnt; i++) {
+		ppgtt_get_guest_root_entry(mm, &ge, i);
+		if (!ops->test_present(&ge))
+			continue;
+
+		trace_gpt_change(vgpu->id, __func__, NULL,
+				ge.type, ge.val64, i);
+
+		spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge);
+		if (IS_ERR(spt)) {
+			gvt_err("fail to populate guest root pointer\n");
+			ret = PTR_ERR(spt);
+			goto fail;
+		}
+		ppgtt_generate_shadow_entry(&se, spt, &ge);
+		ppgtt_set_shadow_root_entry(mm, &se, i);
+
+		trace_gpt_change(vgpu->id, "populate root pointer",
+				NULL, se.type, se.val64, i);
+	}
+	return 0;
+fail:
+	invalidate_mm(mm);
+	return ret;
+}
+
+/**
+ * intel_vgpu_create_mm - create a mm object for a vGPU
+ * @vgpu: a vGPU
+ * @mm_type: mm object type, should be PPGTT or GGTT
+ * @virtual_page_table: page table root pointers. Could be NULL if user wants
+ *	to populate shadow later.
+ * @page_table_level: describe the page table level of the mm object
+ * @pde_base_index: pde root pointer base in GGTT MMIO.
+ *
+ * This function is used to create a mm object for a vGPU.
+ *
+ * Returns:
+ * Zero on success, negative error code in pointer if failed.
+ */
+struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
+		int mm_type, void *virtual_page_table, int page_table_level,
+		u32 pde_base_index)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct intel_vgpu_mm *mm;
+	int ret;
+
+	mm = kzalloc(sizeof(*mm), GFP_KERNEL);
+	if (!mm) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	mm->type = mm_type;
+
+	if (page_table_level == 1)
+		mm->page_table_entry_type = GTT_TYPE_GGTT_PTE;
+	else if (page_table_level == 3)
+		mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY;
+	else if (page_table_level == 4)
+		mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY;
+	else {
+		WARN_ON(1);
+		ret = -EINVAL;
+		goto fail;
+	}
+
+	mm->page_table_level = page_table_level;
+	mm->pde_base_index = pde_base_index;
+
+	mm->vgpu = vgpu;
+	mm->has_shadow_page_table = !!(mm_type == INTEL_GVT_MM_PPGTT);
+
+	kref_init(&mm->ref);
+	atomic_set(&mm->pincount, 0);
+	INIT_LIST_HEAD(&mm->list);
+	INIT_LIST_HEAD(&mm->lru_list);
+	list_add_tail(&mm->list, &vgpu->gtt.mm_list_head);
+
+	ret = gtt->mm_alloc_page_table(mm);
+	if (ret) {
+		gvt_err("fail to allocate page table for mm\n");
+		goto fail;
+	}
+
+	mm->initialized = true;
+
+	if (virtual_page_table)
+		memcpy(mm->virtual_page_table, virtual_page_table,
+				mm->page_table_entry_size);
+
+	if (mm->has_shadow_page_table) {
+		ret = shadow_mm(mm);
+		if (ret)
+			goto fail;
+		list_add_tail(&mm->lru_list, &gvt->gtt.mm_lru_list_head);
+	}
+	return mm;
+fail:
+	gvt_err("fail to create mm\n");
+	if (mm)
+		intel_gvt_mm_unreference(mm);
+	return ERR_PTR(ret);
+}
+
+/**
+ * intel_vgpu_unpin_mm - decrease the pin count of a vGPU mm object
+ * @mm: a vGPU mm object
+ *
+ * This function is called when user doesn't want to use a vGPU mm object
+ */
+void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm)
+{
+	if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT))
+		return;
+
+	atomic_dec(&mm->pincount);
+}
+
+/**
+ * intel_vgpu_pin_mm - increase the pin count of a vGPU mm object
+ * @vgpu: a vGPU
+ *
+ * This function is called when user wants to use a vGPU mm object. If this
+ * mm object hasn't been shadowed yet, the shadow will be populated at this
+ * time.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm)
+{
+	int ret;
+
+	if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT))
+		return 0;
+
+	atomic_inc(&mm->pincount);
+
+	if (!mm->shadowed) {
+		ret = shadow_mm(mm);
+		if (ret)
+			return ret;
+	}
+
+	list_del_init(&mm->lru_list);
+	list_add_tail(&mm->lru_list, &mm->vgpu->gvt->gtt.mm_lru_list_head);
+	return 0;
+}
+
+static int reclaim_one_mm(struct intel_gvt *gvt)
+{
+	struct intel_vgpu_mm *mm;
+	struct list_head *pos, *n;
+
+	list_for_each_safe(pos, n, &gvt->gtt.mm_lru_list_head) {
+		mm = container_of(pos, struct intel_vgpu_mm, lru_list);
+
+		if (mm->type != INTEL_GVT_MM_PPGTT)
+			continue;
+		if (atomic_read(&mm->pincount))
+			continue;
+
+		list_del_init(&mm->lru_list);
+		invalidate_mm(mm);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * GMA translation APIs.
+ */
+static inline int ppgtt_get_next_level_entry(struct intel_vgpu_mm *mm,
+		struct intel_gvt_gtt_entry *e, unsigned long index, bool guest)
+{
+	struct intel_vgpu *vgpu = mm->vgpu;
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	struct intel_vgpu_ppgtt_spt *s;
+
+	if (WARN_ON(!mm->has_shadow_page_table))
+		return -EINVAL;
+
+	s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e));
+	if (!s)
+		return -ENXIO;
+
+	if (!guest)
+		ppgtt_get_shadow_entry(s, e, index);
+	else
+		ppgtt_get_guest_entry(s, e, index);
+	return 0;
+}
+
+/**
+ * intel_vgpu_gma_to_gpa - translate a gma to GPA
+ * @mm: mm object. could be a PPGTT or GGTT mm object
+ * @gma: graphics memory address in this mm object
+ *
+ * This function is used to translate a graphics memory address in specific
+ * graphics memory space to guest physical address.
+ *
+ * Returns:
+ * Guest physical address on success, INTEL_GVT_INVALID_ADDR if failed.
+ */
+unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
+{
+	struct intel_vgpu *vgpu = mm->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt_pte_ops *pte_ops = gvt->gtt.pte_ops;
+	struct intel_gvt_gtt_gma_ops *gma_ops = gvt->gtt.gma_ops;
+	unsigned long gpa = INTEL_GVT_INVALID_ADDR;
+	unsigned long gma_index[4];
+	struct intel_gvt_gtt_entry e;
+	int i, index;
+	int ret;
+
+	if (mm->type != INTEL_GVT_MM_GGTT && mm->type != INTEL_GVT_MM_PPGTT)
+		return INTEL_GVT_INVALID_ADDR;
+
+	if (mm->type == INTEL_GVT_MM_GGTT) {
+		if (!vgpu_gmadr_is_valid(vgpu, gma))
+			goto err;
+
+		ggtt_get_guest_entry(mm, &e,
+			gma_ops->gma_to_ggtt_pte_index(gma));
+		gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
+			+ (gma & ~GTT_PAGE_MASK);
+
+		trace_gma_translate(vgpu->id, "ggtt", 0, 0, gma, gpa);
+		return gpa;
+	}
+
+	switch (mm->page_table_level) {
+	case 4:
+		ppgtt_get_shadow_root_entry(mm, &e, 0);
+		gma_index[0] = gma_ops->gma_to_pml4_index(gma);
+		gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma);
+		gma_index[2] = gma_ops->gma_to_pde_index(gma);
+		gma_index[3] = gma_ops->gma_to_pte_index(gma);
+		index = 4;
+		break;
+	case 3:
+		ppgtt_get_shadow_root_entry(mm, &e,
+				gma_ops->gma_to_l3_pdp_index(gma));
+		gma_index[0] = gma_ops->gma_to_pde_index(gma);
+		gma_index[1] = gma_ops->gma_to_pte_index(gma);
+		index = 2;
+		break;
+	case 2:
+		ppgtt_get_shadow_root_entry(mm, &e,
+				gma_ops->gma_to_pde_index(gma));
+		gma_index[0] = gma_ops->gma_to_pte_index(gma);
+		index = 1;
+		break;
+	default:
+		WARN_ON(1);
+		goto err;
+	}
+
+	/* walk into the shadow page table and get gpa from guest entry */
+	for (i = 0; i < index; i++) {
+		ret = ppgtt_get_next_level_entry(mm, &e, gma_index[i],
+			(i == index - 1));
+		if (ret)
+			goto err;
+	}
+
+	gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
+		+ (gma & ~GTT_PAGE_MASK);
+
+	trace_gma_translate(vgpu->id, "ppgtt", 0,
+			mm->page_table_level, gma, gpa);
+	return gpa;
+err:
+	gvt_err("invalid mm type: %d gma %lx\n", mm->type, gma);
+	return INTEL_GVT_INVALID_ADDR;
+}
+
+static int emulate_gtt_mmio_read(struct intel_vgpu *vgpu,
+	unsigned int off, void *p_data, unsigned int bytes)
+{
+	struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+	unsigned long index = off >> info->gtt_entry_size_shift;
+	struct intel_gvt_gtt_entry e;
+
+	if (bytes != 4 && bytes != 8)
+		return -EINVAL;
+
+	ggtt_get_guest_entry(ggtt_mm, &e, index);
+	memcpy(p_data, (void *)&e.val64 + (off & (info->gtt_entry_size - 1)),
+			bytes);
+	return 0;
+}
+
+/**
+ * intel_vgpu_emulate_gtt_mmio_read - emulate GTT MMIO register read
+ * @vgpu: a vGPU
+ * @off: register offset
+ * @p_data: data will be returned to guest
+ * @bytes: data length
+ *
+ * This function is used to emulate the GTT MMIO register read
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
+	void *p_data, unsigned int bytes)
+{
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+	int ret;
+
+	if (bytes != 4 && bytes != 8)
+		return -EINVAL;
+
+	off -= info->gtt_start_offset;
+	ret = emulate_gtt_mmio_read(vgpu, off, p_data, bytes);
+	return ret;
+}
+
+static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
+	void *p_data, unsigned int bytes)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	const struct intel_gvt_device_info *info = &gvt->device_info;
+	struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm;
+	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
+	unsigned long g_gtt_index = off >> info->gtt_entry_size_shift;
+	unsigned long gma;
+	struct intel_gvt_gtt_entry e, m;
+	int ret;
+
+	if (bytes != 4 && bytes != 8)
+		return -EINVAL;
+
+	gma = g_gtt_index << GTT_PAGE_SHIFT;
+
+	/* the VM may configure the whole GM space when ballooning is used */
+	if (WARN_ONCE(!vgpu_gmadr_is_valid(vgpu, gma),
+				"vgpu%d: found oob ggtt write, offset %x\n",
+				vgpu->id, off)) {
+		return 0;
+	}
+
+	ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index);
+
+	memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,
+			bytes);
+
+	if (ops->test_present(&e)) {
+		ret = gtt_entry_p2m(vgpu, &e, &m);
+		if (ret) {
+			gvt_err("vgpu%d: fail to translate guest gtt entry\n",
+					vgpu->id);
+			return ret;
+		}
+	} else {
+		m = e;
+		m.val64 = 0;
+	}
+
+	ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index);
+	ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);
+	return 0;
+}
+
+/*
+ * intel_vgpu_emulate_gtt_mmio_write - emulate GTT MMIO register write
+ * @vgpu: a vGPU
+ * @off: register offset
+ * @p_data: data from guest write
+ * @bytes: data length
+ *
+ * This function is used to emulate the GTT MMIO register write
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
+	void *p_data, unsigned int bytes)
+{
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+	int ret;
+
+	if (bytes != 4 && bytes != 8)
+		return -EINVAL;
+
+	off -= info->gtt_start_offset;
+	ret = emulate_gtt_mmio_write(vgpu, off, p_data, bytes);
+	return ret;
+}
+
+static int alloc_scratch_pages(struct intel_vgpu *vgpu,
+		intel_gvt_gtt_type_t type)
+{
+	struct intel_vgpu_gtt *gtt = &vgpu->gtt;
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	int page_entry_num = GTT_PAGE_SIZE >>
+				vgpu->gvt->device_info.gtt_entry_size_shift;
+	void *scratch_pt;
+	unsigned long mfn;
+	int i;
+
+	if (WARN_ON(type < GTT_TYPE_PPGTT_PTE_PT || type >= GTT_TYPE_MAX))
+		return -EINVAL;
+
+	scratch_pt = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!scratch_pt) {
+		gvt_err("fail to allocate scratch page\n");
+		return -ENOMEM;
+	}
+
+	mfn = intel_gvt_hypervisor_virt_to_mfn(scratch_pt);
+	if (mfn == INTEL_GVT_INVALID_ADDR) {
+		gvt_err("fail to translate vaddr:0x%lx\n", (unsigned long)scratch_pt);
+		free_page((unsigned long)scratch_pt);
+		return -EFAULT;
+	}
+	gtt->scratch_pt[type].page_mfn = mfn;
+	gtt->scratch_pt[type].page = virt_to_page(scratch_pt);
+	gvt_dbg_mm("vgpu%d create scratch_pt: type %d mfn=0x%lx\n",
+			vgpu->id, type, mfn);
+
+	/* Build the tree by full filled the scratch pt with the entries which
+	 * point to the next level scratch pt or scratch page. The
+	 * scratch_pt[type] indicate the scratch pt/scratch page used by the
+	 * 'type' pt.
+	 * e.g. scratch_pt[GTT_TYPE_PPGTT_PDE_PT] is used by
+	 * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scratch_pt it self
+	 * is GTT_TYPE_PPGTT_PTE_PT, and full filled by scratch page mfn.
+	 */
+	if (type > GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX) {
+		struct intel_gvt_gtt_entry se;
+
+		memset(&se, 0, sizeof(struct intel_gvt_gtt_entry));
+		se.type = get_entry_type(type - 1);
+		ops->set_pfn(&se, gtt->scratch_pt[type - 1].page_mfn);
+
+		/* The entry parameters like present/writeable/cache type
+		 * set to the same as i915's scratch page tree.
+		 */
+		se.val64 |= _PAGE_PRESENT | _PAGE_RW;
+		if (type == GTT_TYPE_PPGTT_PDE_PT)
+			se.val64 |= PPAT_CACHED_INDEX;
+
+		for (i = 0; i < page_entry_num; i++)
+			ops->set_entry(scratch_pt, &se, i, false, 0, vgpu);
+	}
+
+	return 0;
+}
+
+static int release_scratch_page_tree(struct intel_vgpu *vgpu)
+{
+	int i;
+
+	for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {
+		if (vgpu->gtt.scratch_pt[i].page != NULL) {
+			__free_page(vgpu->gtt.scratch_pt[i].page);
+			vgpu->gtt.scratch_pt[i].page = NULL;
+			vgpu->gtt.scratch_pt[i].page_mfn = 0;
+		}
+	}
+
+	return 0;
+}
+
+static int create_scratch_page_tree(struct intel_vgpu *vgpu)
+{
+	int i, ret;
+
+	for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {
+		ret = alloc_scratch_pages(vgpu, i);
+		if (ret)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	release_scratch_page_tree(vgpu);
+	return ret;
+}
+
+/**
+ * intel_vgpu_init_gtt - initialize per-vGPU graphics memory virulization
+ * @vgpu: a vGPU
+ *
+ * This function is used to initialize per-vGPU graphics memory virtualization
+ * components.
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)
+{
+	struct intel_vgpu_gtt *gtt = &vgpu->gtt;
+	struct intel_vgpu_mm *ggtt_mm;
+
+	hash_init(gtt->guest_page_hash_table);
+	hash_init(gtt->shadow_page_hash_table);
+
+	INIT_LIST_HEAD(&gtt->mm_list_head);
+	INIT_LIST_HEAD(&gtt->oos_page_list_head);
+	INIT_LIST_HEAD(&gtt->post_shadow_list_head);
+
+	intel_vgpu_reset_ggtt(vgpu);
+
+	ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT,
+			NULL, 1, 0);
+	if (IS_ERR(ggtt_mm)) {
+		gvt_err("fail to create mm for ggtt.\n");
+		return PTR_ERR(ggtt_mm);
+	}
+
+	gtt->ggtt_mm = ggtt_mm;
+
+	return create_scratch_page_tree(vgpu);
+}
+
+/**
+ * intel_vgpu_clean_gtt - clean up per-vGPU graphics memory virulization
+ * @vgpu: a vGPU
+ *
+ * This function is used to clean up per-vGPU graphics memory virtualization
+ * components.
+ *
+ * Returns:
+ * Zero on success, error code if failed.
+ */
+void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu)
+{
+	struct list_head *pos, *n;
+	struct intel_vgpu_mm *mm;
+
+	ppgtt_free_all_shadow_page(vgpu);
+	release_scratch_page_tree(vgpu);
+
+	list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) {
+		mm = container_of(pos, struct intel_vgpu_mm, list);
+		vgpu->gvt->gtt.mm_free_page_table(mm);
+		list_del(&mm->list);
+		list_del(&mm->lru_list);
+		kfree(mm);
+	}
+}
+
+static void clean_spt_oos(struct intel_gvt *gvt)
+{
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct list_head *pos, *n;
+	struct intel_vgpu_oos_page *oos_page;
+
+	WARN(!list_empty(&gtt->oos_page_use_list_head),
+		"someone is still using oos page\n");
+
+	list_for_each_safe(pos, n, &gtt->oos_page_free_list_head) {
+		oos_page = container_of(pos, struct intel_vgpu_oos_page, list);
+		list_del(&oos_page->list);
+		kfree(oos_page);
+	}
+}
+
+static int setup_spt_oos(struct intel_gvt *gvt)
+{
+	struct intel_gvt_gtt *gtt = &gvt->gtt;
+	struct intel_vgpu_oos_page *oos_page;
+	int i;
+	int ret;
+
+	INIT_LIST_HEAD(&gtt->oos_page_free_list_head);
+	INIT_LIST_HEAD(&gtt->oos_page_use_list_head);
+
+	for (i = 0; i < preallocated_oos_pages; i++) {
+		oos_page = kzalloc(sizeof(*oos_page), GFP_KERNEL);
+		if (!oos_page) {
+			gvt_err("fail to pre-allocate oos page\n");
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		INIT_LIST_HEAD(&oos_page->list);
+		INIT_LIST_HEAD(&oos_page->vm_list);
+		oos_page->id = i;
+		list_add_tail(&oos_page->list, &gtt->oos_page_free_list_head);
+	}
+
+	gvt_dbg_mm("%d oos pages preallocated\n", i);
+
+	return 0;
+fail:
+	clean_spt_oos(gvt);
+	return ret;
+}
+
+/**
+ * intel_vgpu_find_ppgtt_mm - find a PPGTT mm object
+ * @vgpu: a vGPU
+ * @page_table_level: PPGTT page table level
+ * @root_entry: PPGTT page table root pointers
+ *
+ * This function is used to find a PPGTT mm object from mm object pool
+ *
+ * Returns:
+ * pointer to mm object on success, NULL if failed.
+ */
+struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
+		int page_table_level, void *root_entry)
+{
+	struct list_head *pos;
+	struct intel_vgpu_mm *mm;
+	u64 *src, *dst;
+
+	list_for_each(pos, &vgpu->gtt.mm_list_head) {
+		mm = container_of(pos, struct intel_vgpu_mm, list);
+		if (mm->type != INTEL_GVT_MM_PPGTT)
+			continue;
+
+		if (mm->page_table_level != page_table_level)
+			continue;
+
+		src = root_entry;
+		dst = mm->virtual_page_table;
+
+		if (page_table_level == 3) {
+			if (src[0] == dst[0]
+					&& src[1] == dst[1]
+					&& src[2] == dst[2]
+					&& src[3] == dst[3])
+				return mm;
+		} else {
+			if (src[0] == dst[0])
+				return mm;
+		}
+	}
+	return NULL;
+}
+
+/**
+ * intel_vgpu_g2v_create_ppgtt_mm - create a PPGTT mm object from
+ * g2v notification
+ * @vgpu: a vGPU
+ * @page_table_level: PPGTT page table level
+ *
+ * This function is used to create a PPGTT mm object from a guest to GVT-g
+ * notification.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
+		int page_table_level)
+{
+	u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0]));
+	struct intel_vgpu_mm *mm;
+
+	if (WARN_ON((page_table_level != 4) && (page_table_level != 3)))
+		return -EINVAL;
+
+	mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);
+	if (mm) {
+		intel_gvt_mm_reference(mm);
+	} else {
+		mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT,
+				pdp, page_table_level, 0);
+		if (IS_ERR(mm)) {
+			gvt_err("fail to create mm\n");
+			return PTR_ERR(mm);
+		}
+	}
+	return 0;
+}
+
+/**
+ * intel_vgpu_g2v_destroy_ppgtt_mm - destroy a PPGTT mm object from
+ * g2v notification
+ * @vgpu: a vGPU
+ * @page_table_level: PPGTT page table level
+ *
+ * This function is used to create a PPGTT mm object from a guest to GVT-g
+ * notification.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
+		int page_table_level)
+{
+	u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0]));
+	struct intel_vgpu_mm *mm;
+
+	if (WARN_ON((page_table_level != 4) && (page_table_level != 3)))
+		return -EINVAL;
+
+	mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp);
+	if (!mm) {
+		gvt_err("fail to find ppgtt instance.\n");
+		return -EINVAL;
+	}
+	intel_gvt_mm_unreference(mm);
+	return 0;
+}
+
+/**
+ * intel_gvt_init_gtt - initialize mm components of a GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the initialization stage, to initialize
+ * the mm components of a GVT device.
+ *
+ * Returns:
+ * zero on success, negative error code if failed.
+ */
+int intel_gvt_init_gtt(struct intel_gvt *gvt)
+{
+	int ret;
+	void *page;
+
+	gvt_dbg_core("init gtt\n");
+
+	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+		gvt->gtt.pte_ops = &gen8_gtt_pte_ops;
+		gvt->gtt.gma_ops = &gen8_gtt_gma_ops;
+		gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table;
+		gvt->gtt.mm_free_page_table = gen8_mm_free_page_table;
+	} else {
+		return -ENODEV;
+	}
+
+	page = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!page) {
+		gvt_err("fail to allocate scratch ggtt page\n");
+		return -ENOMEM;
+	}
+	gvt->gtt.scratch_ggtt_page = virt_to_page(page);
+
+	gvt->gtt.scratch_ggtt_mfn = intel_gvt_hypervisor_virt_to_mfn(page);
+	if (gvt->gtt.scratch_ggtt_mfn == INTEL_GVT_INVALID_ADDR) {
+		gvt_err("fail to translate scratch ggtt page\n");
+		__free_page(gvt->gtt.scratch_ggtt_page);
+		return -EFAULT;
+	}
+
+	if (enable_out_of_sync) {
+		ret = setup_spt_oos(gvt);
+		if (ret) {
+			gvt_err("fail to initialize SPT oos\n");
+			return ret;
+		}
+	}
+	INIT_LIST_HEAD(&gvt->gtt.mm_lru_list_head);
+	return 0;
+}
+
+/**
+ * intel_gvt_clean_gtt - clean up mm components of a GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the driver unloading stage, to clean up the
+ * the mm components of a GVT device.
+ *
+ */
+void intel_gvt_clean_gtt(struct intel_gvt *gvt)
+{
+	__free_page(gvt->gtt.scratch_ggtt_page);
+
+	if (enable_out_of_sync)
+		clean_spt_oos(gvt);
+}
+
+/**
+ * intel_vgpu_reset_ggtt - reset the GGTT entry
+ * @vgpu: a vGPU
+ *
+ * This function is called at the vGPU create stage
+ * to reset all the GGTT entries.
+ *
+ */
+void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+	u32 index;
+	u32 offset;
+	u32 num_entries;
+	struct intel_gvt_gtt_entry e;
+
+	memset(&e, 0, sizeof(struct intel_gvt_gtt_entry));
+	e.type = GTT_TYPE_GGTT_PTE;
+	ops->set_pfn(&e, gvt->gtt.scratch_ggtt_mfn);
+	e.val64 |= _PAGE_PRESENT;
+
+	index = vgpu_aperture_gmadr_base(vgpu) >> PAGE_SHIFT;
+	num_entries = vgpu_aperture_sz(vgpu) >> PAGE_SHIFT;
+	for (offset = 0; offset < num_entries; offset++)
+		ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
+
+	index = vgpu_hidden_gmadr_base(vgpu) >> PAGE_SHIFT;
+	num_entries = vgpu_hidden_sz(vgpu) >> PAGE_SHIFT;
+	for (offset = 0; offset < num_entries; offset++)
+		ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
+}
+
+/**
+ * intel_vgpu_reset_gtt - reset the all GTT related status
+ * @vgpu: a vGPU
+ * @dmlr: true for vGPU Device Model Level Reset, false for GT Reset
+ *
+ * This function is called from vfio core to reset reset all
+ * GTT related status, including GGTT, PPGTT, scratch page.
+ *
+ */
+void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)
+{
+	int i;
+
+	ppgtt_free_all_shadow_page(vgpu);
+	if (!dmlr)
+		return;
+
+	intel_vgpu_reset_ggtt(vgpu);
+
+	/* clear scratch page for security */
+	for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {
+		if (vgpu->gtt.scratch_pt[i].page != NULL)
+			memset(page_address(vgpu->gtt.scratch_pt[i].page),
+				0, PAGE_SIZE);
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gtt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gtt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gtt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gtt.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,311 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *    Zhenyu Wang <zhenyuw@linux.intel.com>
+ *    Xiao Zheng <xiao.zheng@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#ifndef _GVT_GTT_H_
+#define _GVT_GTT_H_
+
+#define GTT_PAGE_SHIFT		12
+#define GTT_PAGE_SIZE		(1UL << GTT_PAGE_SHIFT)
+#define GTT_PAGE_MASK		(~(GTT_PAGE_SIZE-1))
+
+struct intel_vgpu_mm;
+
+#define INTEL_GVT_GTT_HASH_BITS 8
+#define INTEL_GVT_INVALID_ADDR (~0UL)
+
+struct intel_gvt_gtt_entry {
+	u64 val64;
+	int type;
+};
+
+struct intel_gvt_gtt_pte_ops {
+	struct intel_gvt_gtt_entry *(*get_entry)(void *pt,
+		struct intel_gvt_gtt_entry *e,
+		unsigned long index, bool hypervisor_access, unsigned long gpa,
+		struct intel_vgpu *vgpu);
+	struct intel_gvt_gtt_entry *(*set_entry)(void *pt,
+		struct intel_gvt_gtt_entry *e,
+		unsigned long index, bool hypervisor_access, unsigned long gpa,
+		struct intel_vgpu *vgpu);
+	bool (*test_present)(struct intel_gvt_gtt_entry *e);
+	void (*clear_present)(struct intel_gvt_gtt_entry *e);
+	bool (*test_pse)(struct intel_gvt_gtt_entry *e);
+	void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
+	unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
+};
+
+struct intel_gvt_gtt_gma_ops {
+	unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma);
+	unsigned long (*gma_to_pte_index)(unsigned long gma);
+	unsigned long (*gma_to_pde_index)(unsigned long gma);
+	unsigned long (*gma_to_l3_pdp_index)(unsigned long gma);
+	unsigned long (*gma_to_l4_pdp_index)(unsigned long gma);
+	unsigned long (*gma_to_pml4_index)(unsigned long gma);
+};
+
+struct intel_gvt_gtt {
+	struct intel_gvt_gtt_pte_ops *pte_ops;
+	struct intel_gvt_gtt_gma_ops *gma_ops;
+	int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm);
+	void (*mm_free_page_table)(struct intel_vgpu_mm *mm);
+	struct list_head oos_page_use_list_head;
+	struct list_head oos_page_free_list_head;
+	struct list_head mm_lru_list_head;
+
+	struct page *scratch_ggtt_page;
+	unsigned long scratch_ggtt_mfn;
+};
+
+enum {
+	INTEL_GVT_MM_GGTT = 0,
+	INTEL_GVT_MM_PPGTT,
+};
+
+typedef enum {
+	GTT_TYPE_INVALID = -1,
+
+	GTT_TYPE_GGTT_PTE,
+
+	GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+	GTT_TYPE_PPGTT_PTE_2M_ENTRY,
+	GTT_TYPE_PPGTT_PTE_1G_ENTRY,
+
+	GTT_TYPE_PPGTT_PTE_ENTRY,
+
+	GTT_TYPE_PPGTT_PDE_ENTRY,
+	GTT_TYPE_PPGTT_PDP_ENTRY,
+	GTT_TYPE_PPGTT_PML4_ENTRY,
+
+	GTT_TYPE_PPGTT_ROOT_ENTRY,
+
+	GTT_TYPE_PPGTT_ROOT_L3_ENTRY,
+	GTT_TYPE_PPGTT_ROOT_L4_ENTRY,
+
+	GTT_TYPE_PPGTT_ENTRY,
+
+	GTT_TYPE_PPGTT_PTE_PT,
+	GTT_TYPE_PPGTT_PDE_PT,
+	GTT_TYPE_PPGTT_PDP_PT,
+	GTT_TYPE_PPGTT_PML4_PT,
+
+	GTT_TYPE_MAX,
+} intel_gvt_gtt_type_t;
+
+struct intel_vgpu_mm {
+	int type;
+	bool initialized;
+	bool shadowed;
+
+	int page_table_entry_type;
+	u32 page_table_entry_size;
+	u32 page_table_entry_cnt;
+	void *virtual_page_table;
+	void *shadow_page_table;
+
+	int page_table_level;
+	bool has_shadow_page_table;
+	u32 pde_base_index;
+
+	struct list_head list;
+	struct kref ref;
+	atomic_t pincount;
+	struct list_head lru_list;
+	struct intel_vgpu *vgpu;
+};
+
+extern struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(
+		struct intel_vgpu_mm *mm,
+		void *page_table, struct intel_gvt_gtt_entry *e,
+		unsigned long index);
+
+extern struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(
+		struct intel_vgpu_mm *mm,
+		void *page_table, struct intel_gvt_gtt_entry *e,
+		unsigned long index);
+
+#define ggtt_get_guest_entry(mm, e, index) \
+	intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index)
+
+#define ggtt_set_guest_entry(mm, e, index) \
+	intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index)
+
+#define ggtt_get_shadow_entry(mm, e, index) \
+	intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index)
+
+#define ggtt_set_shadow_entry(mm, e, index) \
+	intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index)
+
+#define ppgtt_get_guest_root_entry(mm, e, index) \
+	intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index)
+
+#define ppgtt_set_guest_root_entry(mm, e, index) \
+	intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index)
+
+#define ppgtt_get_shadow_root_entry(mm, e, index) \
+	intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index)
+
+#define ppgtt_set_shadow_root_entry(mm, e, index) \
+	intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index)
+
+extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
+		int mm_type, void *virtual_page_table, int page_table_level,
+		u32 pde_base_index);
+extern void intel_vgpu_destroy_mm(struct kref *mm_ref);
+
+struct intel_vgpu_guest_page;
+
+struct intel_vgpu_scratch_pt {
+	struct page *page;
+	unsigned long page_mfn;
+};
+
+
+struct intel_vgpu_gtt {
+	struct intel_vgpu_mm *ggtt_mm;
+	unsigned long active_ppgtt_mm_bitmap;
+	struct list_head mm_list_head;
+	DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
+	DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
+	atomic_t n_write_protected_guest_page;
+	struct list_head oos_page_list_head;
+	struct list_head post_shadow_list_head;
+	struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX];
+
+};
+
+extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
+extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
+void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);
+
+extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
+extern void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr);
+extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);
+
+extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
+		int page_table_level, void *root_entry);
+
+struct intel_vgpu_oos_page;
+
+struct intel_vgpu_shadow_page {
+	void *vaddr;
+	struct page *page;
+	int type;
+	struct hlist_node node;
+	unsigned long mfn;
+};
+
+struct intel_vgpu_guest_page {
+	struct hlist_node node;
+	bool writeprotection;
+	unsigned long gfn;
+	int (*handler)(void *, u64, void *, int);
+	void *data;
+	unsigned long write_cnt;
+	struct intel_vgpu_oos_page *oos_page;
+};
+
+struct intel_vgpu_oos_page {
+	struct intel_vgpu_guest_page *guest_page;
+	struct list_head list;
+	struct list_head vm_list;
+	int id;
+	unsigned char mem[GTT_PAGE_SIZE];
+};
+
+#define GTT_ENTRY_NUM_IN_ONE_PAGE 512
+
+struct intel_vgpu_ppgtt_spt {
+	struct intel_vgpu_shadow_page shadow_page;
+	struct intel_vgpu_guest_page guest_page;
+	int guest_page_type;
+	atomic_t refcount;
+	struct intel_vgpu *vgpu;
+	DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE);
+	struct list_head post_shadow_list;
+};
+
+int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *guest_page,
+		unsigned long gfn,
+		int (*handler)(void *gp, u64, void *, int),
+		void *data);
+
+void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *guest_page);
+
+int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *guest_page);
+
+void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *guest_page);
+
+struct intel_vgpu_guest_page *intel_vgpu_find_guest_page(
+		struct intel_vgpu *vgpu, unsigned long gfn);
+
+int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu);
+
+int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu);
+
+static inline void intel_gvt_mm_reference(struct intel_vgpu_mm *mm)
+{
+	kref_get(&mm->ref);
+}
+
+static inline void intel_gvt_mm_unreference(struct intel_vgpu_mm *mm)
+{
+	kref_put(&mm->ref, intel_vgpu_destroy_mm);
+}
+
+int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm);
+
+void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm);
+
+unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm,
+		unsigned long gma);
+
+struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu,
+		int page_table_level, void *root_entry);
+
+int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu,
+		int page_table_level);
+
+int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
+		int page_table_level);
+
+int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu,
+	unsigned int off, void *p_data, unsigned int bytes);
+
+int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu,
+	unsigned int off, void *p_data, unsigned int bytes);
+
+#endif /* _GVT_GTT_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gvt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gvt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gvt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gvt.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,12 +19,23 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Eddie Dong <eddie.dong@intel.com>
+ *
+ * Contributors:
+ *    Niu Bing <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
  */
 
 #include <linux/types.h>
 #include <xen/xen.h>
+#include <linux/kthread.h>
 
 #include "i915_drv.h"
+#include "gvt.h"
 
 struct intel_gvt_host intel_gvt_host;
 
@@ -33,6 +44,16 @@ static const char * const supported_hype
 	[INTEL_GVT_HYPERVISOR_KVM] = "KVM",
 };
 
+static const struct intel_gvt_ops intel_gvt_ops = {
+	.emulate_cfg_read = intel_vgpu_emulate_cfg_read,
+	.emulate_cfg_write = intel_vgpu_emulate_cfg_write,
+	.emulate_mmio_read = intel_vgpu_emulate_mmio_read,
+	.emulate_mmio_write = intel_vgpu_emulate_mmio_write,
+	.vgpu_create = intel_gvt_create_vgpu,
+	.vgpu_destroy = intel_gvt_destroy_vgpu,
+	.vgpu_reset = intel_gvt_reset_vgpu,
+};
+
 /**
  * intel_gvt_init_host - Load MPT modules and detect if we're running in host
  * @gvt: intel gvt device
@@ -47,6 +68,8 @@ static const char * const supported_hype
  */
 int intel_gvt_init_host(void)
 {
+	int ret;
+
 	if (intel_gvt_host.initialized)
 		return 0;
 
@@ -61,10 +84,12 @@ int intel_gvt_init_host(void)
 				symbol_get(xengt_mpt), "xengt");
 		intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_XEN;
 	} else {
+#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
 		/* not in Xen. Try KVMGT */
 		intel_gvt_host.mpt = try_then_request_module(
-				symbol_get(kvmgt_mpt), "kvm");
+				symbol_get(kvmgt_mpt), "kvmgt");
 		intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_KVM;
+#endif
 	}
 
 	/* Fail to load MPT modules - bail out */
@@ -72,7 +97,8 @@ int intel_gvt_init_host(void)
 		return -EINVAL;
 
 	/* Try to detect if we're running in host instead of VM. */
-	if (!intel_gvt_hypervisor_detect_host())
+	ret = intel_gvt_hypervisor_detect_host();
+	if (ret)
 		return -ENODEV;
 
 	gvt_dbg_core("Running with hypervisor %s in host mode\n",
@@ -84,9 +110,67 @@ int intel_gvt_init_host(void)
 
 static void init_device_info(struct intel_gvt *gvt)
 {
-	if (IS_BROADWELL(gvt->dev_priv))
-		gvt->device_info.max_support_vgpus = 8;
-	/* This function will grow large in GVT device model patches. */
+	struct intel_gvt_device_info *info = &gvt->device_info;
+	struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
+
+	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+		info->max_support_vgpus = 8;
+		info->cfg_space_size = 256;
+		info->mmio_size = 2 * 1024 * 1024;
+		info->mmio_bar = 0;
+		info->gtt_start_offset = 8 * 1024 * 1024;
+		info->gtt_entry_size = 8;
+		info->gtt_entry_size_shift = 3;
+		info->gmadr_bytes_in_cmd = 8;
+		info->max_surface_size = 36 * 1024 * 1024;
+	}
+	info->msi_cap_offset = pdev->msi_cap;
+}
+
+static int gvt_service_thread(void *data)
+{
+	struct intel_gvt *gvt = (struct intel_gvt *)data;
+	int ret;
+
+	gvt_dbg_core("service thread start\n");
+
+	while (!kthread_should_stop()) {
+		ret = wait_event_interruptible(gvt->service_thread_wq,
+				kthread_should_stop() || gvt->service_request);
+
+		if (kthread_should_stop())
+			break;
+
+		if (WARN_ONCE(ret, "service thread is waken up by signal.\n"))
+			continue;
+
+		if (test_and_clear_bit(INTEL_GVT_REQUEST_EMULATE_VBLANK,
+					(void *)&gvt->service_request)) {
+			mutex_lock(&gvt->lock);
+			intel_gvt_emulate_vblank(gvt);
+			mutex_unlock(&gvt->lock);
+		}
+	}
+
+	return 0;
+}
+
+static void clean_service_thread(struct intel_gvt *gvt)
+{
+	kthread_stop(gvt->service_thread);
+}
+
+static int init_service_thread(struct intel_gvt *gvt)
+{
+	init_waitqueue_head(&gvt->service_thread_wq);
+
+	gvt->service_thread = kthread_run(gvt_service_thread,
+			gvt, "gvt_service_thread");
+	if (IS_ERR(gvt->service_thread)) {
+		gvt_err("fail to start service thread.\n");
+		return PTR_ERR(gvt->service_thread);
+	}
+	return 0;
 }
 
 /**
@@ -99,14 +183,28 @@ static void init_device_info(struct inte
  */
 void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
 {
-	struct intel_gvt *gvt = &dev_priv->gvt;
+	struct intel_gvt *gvt = to_gvt(dev_priv);
 
-	if (WARN_ON(!gvt->initialized))
+	if (WARN_ON(!gvt))
 		return;
 
-	/* Other de-initialization of GVT components will be introduced. */
+	clean_service_thread(gvt);
+	intel_gvt_clean_cmd_parser(gvt);
+	intel_gvt_clean_sched_policy(gvt);
+	intel_gvt_clean_workload_scheduler(gvt);
+	intel_gvt_clean_opregion(gvt);
+	intel_gvt_clean_gtt(gvt);
+	intel_gvt_clean_irq(gvt);
+	intel_gvt_clean_mmio_info(gvt);
+	intel_gvt_free_firmware(gvt);
 
-	gvt->initialized = false;
+	intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt);
+	intel_gvt_clean_vgpu_types(gvt);
+
+	idr_destroy(&gvt->vgpu_idr);
+
+	kfree(dev_priv->gvt);
+	dev_priv->gvt = NULL;
 }
 
 /**
@@ -122,7 +220,9 @@ void intel_gvt_clean_device(struct drm_i
  */
 int intel_gvt_init_device(struct drm_i915_private *dev_priv)
 {
-	struct intel_gvt *gvt = &dev_priv->gvt;
+	struct intel_gvt *gvt;
+	int ret;
+
 	/*
 	 * Cannot initialize GVT device without intel_gvt_host gets
 	 * initialized first.
@@ -130,16 +230,95 @@ int intel_gvt_init_device(struct drm_i91
 	if (WARN_ON(!intel_gvt_host.initialized))
 		return -EINVAL;
 
-	if (WARN_ON(gvt->initialized))
+	if (WARN_ON(dev_priv->gvt))
 		return -EEXIST;
 
+	gvt = kzalloc(sizeof(struct intel_gvt), GFP_KERNEL);
+	if (!gvt)
+		return -ENOMEM;
+
 	gvt_dbg_core("init gvt device\n");
 
+	idr_init(&gvt->vgpu_idr);
+
+	mutex_init(&gvt->lock);
+	gvt->dev_priv = dev_priv;
+
 	init_device_info(gvt);
-	/*
-	 * Other initialization of GVT components will be introduce here.
-	 */
-	gvt_dbg_core("gvt device creation is done\n");
-	gvt->initialized = true;
+
+	ret = intel_gvt_setup_mmio_info(gvt);
+	if (ret)
+		goto out_clean_idr;
+
+	ret = intel_gvt_load_firmware(gvt);
+	if (ret)
+		goto out_clean_mmio_info;
+
+	ret = intel_gvt_init_irq(gvt);
+	if (ret)
+		goto out_free_firmware;
+
+	ret = intel_gvt_init_gtt(gvt);
+	if (ret)
+		goto out_clean_irq;
+
+	ret = intel_gvt_init_opregion(gvt);
+	if (ret)
+		goto out_clean_gtt;
+
+	ret = intel_gvt_init_workload_scheduler(gvt);
+	if (ret)
+		goto out_clean_opregion;
+
+	ret = intel_gvt_init_sched_policy(gvt);
+	if (ret)
+		goto out_clean_workload_scheduler;
+
+	ret = intel_gvt_init_cmd_parser(gvt);
+	if (ret)
+		goto out_clean_sched_policy;
+
+	ret = init_service_thread(gvt);
+	if (ret)
+		goto out_clean_cmd_parser;
+
+	ret = intel_gvt_init_vgpu_types(gvt);
+	if (ret)
+		goto out_clean_thread;
+
+	ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt,
+				&intel_gvt_ops);
+	if (ret) {
+		gvt_err("failed to register gvt-g host device: %d\n", ret);
+		goto out_clean_types;
+	}
+
+	gvt_dbg_core("gvt device initialization is done\n");
+	dev_priv->gvt = gvt;
 	return 0;
+
+out_clean_types:
+	intel_gvt_clean_vgpu_types(gvt);
+out_clean_thread:
+	clean_service_thread(gvt);
+out_clean_cmd_parser:
+	intel_gvt_clean_cmd_parser(gvt);
+out_clean_sched_policy:
+	intel_gvt_clean_sched_policy(gvt);
+out_clean_workload_scheduler:
+	intel_gvt_clean_workload_scheduler(gvt);
+out_clean_opregion:
+	intel_gvt_clean_opregion(gvt);
+out_clean_gtt:
+	intel_gvt_clean_gtt(gvt);
+out_clean_irq:
+	intel_gvt_clean_irq(gvt);
+out_free_firmware:
+	intel_gvt_free_firmware(gvt);
+out_clean_mmio_info:
+	intel_gvt_clean_mmio_info(gvt);
+out_clean_idr:
+	idr_destroy(&gvt->vgpu_idr);
+	kfree(gvt);
+	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gvt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gvt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/gvt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/gvt.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,15 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Eddie Dong <eddie.dong@intel.com>
+ *
+ * Contributors:
+ *    Niu Bing <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
  */
 
 #ifndef _GVT_H_
@@ -26,6 +35,17 @@
 
 #include "debug.h"
 #include "hypercall.h"
+#include "mmio.h"
+#include "reg.h"
+#include "interrupt.h"
+#include "gtt.h"
+#include "display.h"
+#include "edid.h"
+#include "execlist.h"
+#include "scheduler.h"
+#include "sched_policy.h"
+#include "render.h"
+#include "cmd_parser.h"
 
 #define GVT_MAX_VGPU 8
 
@@ -45,25 +65,390 @@ extern struct intel_gvt_host intel_gvt_h
 /* Describe per-platform limitations. */
 struct intel_gvt_device_info {
 	u32 max_support_vgpus;
-	/* This data structure will grow bigger in GVT device model patches */
+	u32 cfg_space_size;
+	u32 mmio_size;
+	u32 mmio_bar;
+	unsigned long msi_cap_offset;
+	u32 gtt_start_offset;
+	u32 gtt_entry_size;
+	u32 gtt_entry_size_shift;
+	int gmadr_bytes_in_cmd;
+	u32 max_surface_size;
+};
+
+/* GM resources owned by a vGPU */
+struct intel_vgpu_gm {
+	u64 aperture_sz;
+	u64 hidden_sz;
+	struct drm_mm_node low_gm_node;
+	struct drm_mm_node high_gm_node;
+};
+
+#define INTEL_GVT_MAX_NUM_FENCES 32
+
+/* Fences owned by a vGPU */
+struct intel_vgpu_fence {
+	struct drm_i915_fence_reg *regs[INTEL_GVT_MAX_NUM_FENCES];
+	u32 base;
+	u32 size;
+};
+
+struct intel_vgpu_mmio {
+	void *vreg;
+	void *sreg;
+	bool disable_warn_untrack;
+};
+
+#define INTEL_GVT_MAX_CFG_SPACE_SZ 256
+#define INTEL_GVT_MAX_BAR_NUM 4
+
+struct intel_vgpu_pci_bar {
+	u64 size;
+	bool tracked;
+};
+
+struct intel_vgpu_cfg_space {
+	unsigned char virtual_cfg_space[INTEL_GVT_MAX_CFG_SPACE_SZ];
+	struct intel_vgpu_pci_bar bar[INTEL_GVT_MAX_BAR_NUM];
+};
+
+#define vgpu_cfg_space(vgpu) ((vgpu)->cfg_space.virtual_cfg_space)
+
+#define INTEL_GVT_MAX_PIPE 4
+
+struct intel_vgpu_irq {
+	bool irq_warn_once[INTEL_GVT_EVENT_MAX];
+	DECLARE_BITMAP(flip_done_event[INTEL_GVT_MAX_PIPE],
+		       INTEL_GVT_EVENT_MAX);
+};
+
+struct intel_vgpu_opregion {
+	void *va;
+	u32 gfn[INTEL_GVT_OPREGION_PAGES];
+	struct page *pages[INTEL_GVT_OPREGION_PAGES];
+};
+
+#define vgpu_opregion(vgpu) (&(vgpu->opregion))
+
+#define INTEL_GVT_MAX_PORT 5
+
+struct intel_vgpu_display {
+	struct intel_vgpu_i2c_edid i2c_edid;
+	struct intel_vgpu_port ports[INTEL_GVT_MAX_PORT];
+	struct intel_vgpu_sbi sbi;
 };
 
 struct intel_vgpu {
 	struct intel_gvt *gvt;
 	int id;
 	unsigned long handle; /* vGPU handle used by hypervisor MPT modules */
+	bool active;
+	bool resetting;
+	void *sched_data;
+
+	struct intel_vgpu_fence fence;
+	struct intel_vgpu_gm gm;
+	struct intel_vgpu_cfg_space cfg_space;
+	struct intel_vgpu_mmio mmio;
+	struct intel_vgpu_irq irq;
+	struct intel_vgpu_gtt gtt;
+	struct intel_vgpu_opregion opregion;
+	struct intel_vgpu_display display;
+	struct intel_vgpu_execlist execlist[I915_NUM_ENGINES];
+	struct list_head workload_q_head[I915_NUM_ENGINES];
+	struct kmem_cache *workloads;
+	atomic_t running_workload_num;
+	DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
+	struct i915_gem_context *shadow_ctx;
+	struct notifier_block shadow_ctx_notifier_block;
+
+#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
+	struct {
+		struct mdev_device *mdev;
+		struct vfio_region *region;
+		int num_regions;
+		struct eventfd_ctx *intx_trigger;
+		struct eventfd_ctx *msi_trigger;
+		struct rb_root cache;
+		struct mutex cache_lock;
+		struct notifier_block iommu_notifier;
+		struct notifier_block group_notifier;
+		struct kvm *kvm;
+		struct work_struct release_work;
+		atomic_t released;
+	} vdev;
+#endif
+};
+
+struct intel_gvt_gm {
+	unsigned long vgpu_allocated_low_gm_size;
+	unsigned long vgpu_allocated_high_gm_size;
+};
+
+struct intel_gvt_fence {
+	unsigned long vgpu_allocated_fence_num;
+};
+
+#define INTEL_GVT_MMIO_HASH_BITS 9
+
+struct intel_gvt_mmio {
+	u32 *mmio_attribute;
+	DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS);
+};
+
+struct intel_gvt_firmware {
+	void *cfg_space;
+	void *mmio;
+	bool firmware_loaded;
+};
+
+struct intel_gvt_opregion {
+	void __iomem *opregion_va;
+	u32 opregion_pa;
+};
+
+#define NR_MAX_INTEL_VGPU_TYPES 20
+struct intel_vgpu_type {
+	char name[16];
+	unsigned int max_instance;
+	unsigned int avail_instance;
+	unsigned int low_gm_size;
+	unsigned int high_gm_size;
+	unsigned int fence;
 };
 
 struct intel_gvt {
 	struct mutex lock;
-	bool initialized;
-
 	struct drm_i915_private *dev_priv;
 	struct idr vgpu_idr;	/* vGPU IDR pool */
 
 	struct intel_gvt_device_info device_info;
+	struct intel_gvt_gm gm;
+	struct intel_gvt_fence fence;
+	struct intel_gvt_mmio mmio;
+	struct intel_gvt_firmware firmware;
+	struct intel_gvt_irq irq;
+	struct intel_gvt_gtt gtt;
+	struct intel_gvt_opregion opregion;
+	struct intel_gvt_workload_scheduler scheduler;
+	DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
+	struct intel_vgpu_type *types;
+	unsigned int num_types;
+
+	struct task_struct *service_thread;
+	wait_queue_head_t service_thread_wq;
+	unsigned long service_request;
+};
+
+static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915)
+{
+	return i915->gvt;
+}
+
+enum {
+	INTEL_GVT_REQUEST_EMULATE_VBLANK = 0,
 };
 
+static inline void intel_gvt_request_service(struct intel_gvt *gvt,
+		int service)
+{
+	set_bit(service, (void *)&gvt->service_request);
+	wake_up(&gvt->service_thread_wq);
+}
+
+void intel_gvt_free_firmware(struct intel_gvt *gvt);
+int intel_gvt_load_firmware(struct intel_gvt *gvt);
+
+/* Aperture/GM space definitions for GVT device */
+#define MB_TO_BYTES(mb) ((mb) << 20ULL)
+#define BYTES_TO_MB(b) ((b) >> 20ULL)
+
+#define HOST_LOW_GM_SIZE MB_TO_BYTES(128)
+#define HOST_HIGH_GM_SIZE MB_TO_BYTES(384)
+#define HOST_FENCE 4
+
+/* Aperture/GM space definitions for GVT device */
+#define gvt_aperture_sz(gvt)	  (gvt->dev_priv->ggtt.mappable_end)
+#define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.mappable_base)
+
+#define gvt_ggtt_gm_sz(gvt)	  (gvt->dev_priv->ggtt.base.total)
+#define gvt_ggtt_sz(gvt) \
+	((gvt->dev_priv->ggtt.base.total >> PAGE_SHIFT) << 3)
+#define gvt_hidden_sz(gvt)	  (gvt_ggtt_gm_sz(gvt) - gvt_aperture_sz(gvt))
+
+#define gvt_aperture_gmadr_base(gvt) (0)
+#define gvt_aperture_gmadr_end(gvt) (gvt_aperture_gmadr_base(gvt) \
+				     + gvt_aperture_sz(gvt) - 1)
+
+#define gvt_hidden_gmadr_base(gvt) (gvt_aperture_gmadr_base(gvt) \
+				    + gvt_aperture_sz(gvt))
+#define gvt_hidden_gmadr_end(gvt) (gvt_hidden_gmadr_base(gvt) \
+				   + gvt_hidden_sz(gvt) - 1)
+
+#define gvt_fence_sz(gvt) (gvt->dev_priv->num_fence_regs)
+
+/* Aperture/GM space definitions for vGPU */
+#define vgpu_aperture_offset(vgpu)	((vgpu)->gm.low_gm_node.start)
+#define vgpu_hidden_offset(vgpu)	((vgpu)->gm.high_gm_node.start)
+#define vgpu_aperture_sz(vgpu)		((vgpu)->gm.aperture_sz)
+#define vgpu_hidden_sz(vgpu)		((vgpu)->gm.hidden_sz)
+
+#define vgpu_aperture_pa_base(vgpu) \
+	(gvt_aperture_pa_base(vgpu->gvt) + vgpu_aperture_offset(vgpu))
+
+#define vgpu_ggtt_gm_sz(vgpu) ((vgpu)->gm.aperture_sz + (vgpu)->gm.hidden_sz)
+
+#define vgpu_aperture_pa_end(vgpu) \
+	(vgpu_aperture_pa_base(vgpu) + vgpu_aperture_sz(vgpu) - 1)
+
+#define vgpu_aperture_gmadr_base(vgpu) (vgpu_aperture_offset(vgpu))
+#define vgpu_aperture_gmadr_end(vgpu) \
+	(vgpu_aperture_gmadr_base(vgpu) + vgpu_aperture_sz(vgpu) - 1)
+
+#define vgpu_hidden_gmadr_base(vgpu) (vgpu_hidden_offset(vgpu))
+#define vgpu_hidden_gmadr_end(vgpu) \
+	(vgpu_hidden_gmadr_base(vgpu) + vgpu_hidden_sz(vgpu) - 1)
+
+#define vgpu_fence_base(vgpu) (vgpu->fence.base)
+#define vgpu_fence_sz(vgpu) (vgpu->fence.size)
+
+struct intel_vgpu_creation_params {
+	__u64 handle;
+	__u64 low_gm_sz;  /* in MB */
+	__u64 high_gm_sz; /* in MB */
+	__u64 fence_sz;
+	__s32 primary;
+	__u64 vgpu_id;
+};
+
+int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
+			      struct intel_vgpu_creation_params *param);
+void intel_vgpu_reset_resource(struct intel_vgpu *vgpu);
+void intel_vgpu_free_resource(struct intel_vgpu *vgpu);
+void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
+	u32 fence, u64 value);
+
+/* Macros for easily accessing vGPU virtual/shadow register */
+#define vgpu_vreg(vgpu, reg) \
+	(*(u32 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_vreg8(vgpu, reg) \
+	(*(u8 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_vreg16(vgpu, reg) \
+	(*(u16 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_vreg64(vgpu, reg) \
+	(*(u64 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg(vgpu, reg) \
+	(*(u32 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg8(vgpu, reg) \
+	(*(u8 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg16(vgpu, reg) \
+	(*(u16 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+#define vgpu_sreg64(vgpu, reg) \
+	(*(u64 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg)))
+
+#define for_each_active_vgpu(gvt, vgpu, id) \
+	idr_for_each_entry((&(gvt)->vgpu_idr), (vgpu), (id)) \
+		for_each_if(vgpu->active)
+
+static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu,
+					    u32 offset, u32 val, bool low)
+{
+	u32 *pval;
+
+	/* BAR offset should be 32 bits algiend */
+	offset = rounddown(offset, 4);
+	pval = (u32 *)(vgpu_cfg_space(vgpu) + offset);
+
+	if (low) {
+		/*
+		 * only update bit 31 - bit 4,
+		 * leave the bit 3 - bit 0 unchanged.
+		 */
+		*pval = (val & GENMASK(31, 4)) | (*pval & GENMASK(3, 0));
+	} else {
+		*pval = val;
+	}
+}
+
+int intel_gvt_init_vgpu_types(struct intel_gvt *gvt);
+void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt);
+
+struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
+					 struct intel_vgpu_type *type);
+void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);
+void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
+				 unsigned int engine_mask);
+void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu);
+
+
+/* validating GM functions */
+#define vgpu_gmadr_is_aperture(vgpu, gmadr) \
+	((gmadr >= vgpu_aperture_gmadr_base(vgpu)) && \
+	 (gmadr <= vgpu_aperture_gmadr_end(vgpu)))
+
+#define vgpu_gmadr_is_hidden(vgpu, gmadr) \
+	((gmadr >= vgpu_hidden_gmadr_base(vgpu)) && \
+	 (gmadr <= vgpu_hidden_gmadr_end(vgpu)))
+
+#define vgpu_gmadr_is_valid(vgpu, gmadr) \
+	 ((vgpu_gmadr_is_aperture(vgpu, gmadr) || \
+	  (vgpu_gmadr_is_hidden(vgpu, gmadr))))
+
+#define gvt_gmadr_is_aperture(gvt, gmadr) \
+	 ((gmadr >= gvt_aperture_gmadr_base(gvt)) && \
+	  (gmadr <= gvt_aperture_gmadr_end(gvt)))
+
+#define gvt_gmadr_is_hidden(gvt, gmadr) \
+	  ((gmadr >= gvt_hidden_gmadr_base(gvt)) && \
+	   (gmadr <= gvt_hidden_gmadr_end(gvt)))
+
+#define gvt_gmadr_is_valid(gvt, gmadr) \
+	  (gvt_gmadr_is_aperture(gvt, gmadr) || \
+	    gvt_gmadr_is_hidden(gvt, gmadr))
+
+bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size);
+int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr);
+int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr);
+int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index,
+			     unsigned long *h_index);
+int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index,
+			     unsigned long *g_index);
+
+void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
+		bool primary);
+void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu);
+
+int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes);
+
+int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes);
+
+void intel_gvt_clean_opregion(struct intel_gvt *gvt);
+int intel_gvt_init_opregion(struct intel_gvt *gvt);
+
+void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
+int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);
+
+int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci);
+void populate_pvinfo_page(struct intel_vgpu *vgpu);
+
+struct intel_gvt_ops {
+	int (*emulate_cfg_read)(struct intel_vgpu *, unsigned int, void *,
+				unsigned int);
+	int (*emulate_cfg_write)(struct intel_vgpu *, unsigned int, void *,
+				unsigned int);
+	int (*emulate_mmio_read)(struct intel_vgpu *, u64, void *,
+				unsigned int);
+	int (*emulate_mmio_write)(struct intel_vgpu *, u64, void *,
+				unsigned int);
+	struct intel_vgpu *(*vgpu_create)(struct intel_gvt *,
+				struct intel_vgpu_type *);
+	void (*vgpu_destroy)(struct intel_vgpu *);
+	void (*vgpu_reset)(struct intel_vgpu *);
+};
+
+
 #include "mpt.h"
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/handlers.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/handlers.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/handlers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/handlers.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2815 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Eddie Dong <eddie.dong@intel.com>
+ *    Zhiyuan Lv <zhiyuan.lv@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Pei Zhang <pei.zhang@intel.com>
+ *    Niu Bing <bing.niu@intel.com>
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+
+/* XXX FIXME i915 has changed PP_XXX definition */
+#define PCH_PP_STATUS  _MMIO(0xc7200)
+#define PCH_PP_CONTROL _MMIO(0xc7204)
+#define PCH_PP_ON_DELAYS _MMIO(0xc7208)
+#define PCH_PP_OFF_DELAYS _MMIO(0xc720c)
+#define PCH_PP_DIVISOR _MMIO(0xc7210)
+
+/* Register contains RO bits */
+#define F_RO		(1 << 0)
+/* Register contains graphics address */
+#define F_GMADR		(1 << 1)
+/* Mode mask registers with high 16 bits as the mask bits */
+#define F_MODE_MASK	(1 << 2)
+/* This reg can be accessed by GPU commands */
+#define F_CMD_ACCESS	(1 << 3)
+/* This reg has been accessed by a VM */
+#define F_ACCESSED	(1 << 4)
+/* This reg has been accessed through GPU commands */
+#define F_CMD_ACCESSED	(1 << 5)
+/* This reg could be accessed by unaligned address */
+#define F_UNALIGN	(1 << 6)
+
+unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt)
+{
+	if (IS_BROADWELL(gvt->dev_priv))
+		return D_BDW;
+	else if (IS_SKYLAKE(gvt->dev_priv))
+		return D_SKL;
+
+	return 0;
+}
+
+bool intel_gvt_match_device(struct intel_gvt *gvt,
+		unsigned long device)
+{
+	return intel_gvt_get_device_type(gvt) & device;
+}
+
+static void read_vreg(struct intel_vgpu *vgpu, unsigned int offset,
+	void *p_data, unsigned int bytes)
+{
+	memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes);
+}
+
+static void write_vreg(struct intel_vgpu *vgpu, unsigned int offset,
+	void *p_data, unsigned int bytes)
+{
+	memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes);
+}
+
+static int new_mmio_info(struct intel_gvt *gvt,
+		u32 offset, u32 flags, u32 size,
+		u32 addr_mask, u32 ro_mask, u32 device,
+		int (*read)(struct intel_vgpu *, unsigned int, void *, unsigned int),
+		int (*write)(struct intel_vgpu *, unsigned int, void *, unsigned int))
+{
+	struct intel_gvt_mmio_info *info, *p;
+	u32 start, end, i;
+
+	if (!intel_gvt_match_device(gvt, device))
+		return 0;
+
+	if (WARN_ON(!IS_ALIGNED(offset, 4)))
+		return -EINVAL;
+
+	start = offset;
+	end = offset + size;
+
+	for (i = start; i < end; i += 4) {
+		info = kzalloc(sizeof(*info), GFP_KERNEL);
+		if (!info)
+			return -ENOMEM;
+
+		info->offset = i;
+		p = intel_gvt_find_mmio_info(gvt, info->offset);
+		if (p)
+			gvt_err("dup mmio definition offset %x\n",
+				info->offset);
+		info->size = size;
+		info->length = (i + 4) < end ? 4 : (end - i);
+		info->addr_mask = addr_mask;
+		info->device = device;
+		info->read = read ? read : intel_vgpu_default_mmio_read;
+		info->write = write ? write : intel_vgpu_default_mmio_write;
+		gvt->mmio.mmio_attribute[info->offset / 4] = flags;
+		INIT_HLIST_NODE(&info->node);
+		hash_add(gvt->mmio.mmio_info_table, &info->node, info->offset);
+	}
+	return 0;
+}
+
+static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg)
+{
+	enum intel_engine_id id;
+	struct intel_engine_cs *engine;
+
+	reg &= ~GENMASK(11, 0);
+	for_each_engine(engine, gvt->dev_priv, id) {
+		if (engine->mmio_base == reg)
+			return id;
+	}
+	return -1;
+}
+
+#define offset_to_fence_num(offset) \
+	((offset - i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) >> 3)
+
+#define fence_num_to_offset(num) \
+	(num * 8 + i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0)))
+
+static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu,
+		unsigned int fence_num, void *p_data, unsigned int bytes)
+{
+	if (fence_num >= vgpu_fence_sz(vgpu)) {
+		gvt_err("vgpu%d: found oob fence register access\n",
+				vgpu->id);
+		gvt_err("vgpu%d: total fence num %d access fence num %d\n",
+				vgpu->id, vgpu_fence_sz(vgpu), fence_num);
+		memset(p_data, 0, bytes);
+	}
+	return 0;
+}
+
+static int fence_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
+		void *p_data, unsigned int bytes)
+{
+	int ret;
+
+	ret = sanitize_fence_mmio_access(vgpu, offset_to_fence_num(off),
+			p_data, bytes);
+	if (ret)
+		return ret;
+	read_vreg(vgpu, off, p_data, bytes);
+	return 0;
+}
+
+static int fence_mmio_write(struct intel_vgpu *vgpu, unsigned int off,
+		void *p_data, unsigned int bytes)
+{
+	unsigned int fence_num = offset_to_fence_num(off);
+	int ret;
+
+	ret = sanitize_fence_mmio_access(vgpu, fence_num, p_data, bytes);
+	if (ret)
+		return ret;
+	write_vreg(vgpu, off, p_data, bytes);
+
+	intel_vgpu_write_fence(vgpu, fence_num,
+			vgpu_vreg64(vgpu, fence_num_to_offset(fence_num)));
+	return 0;
+}
+
+#define CALC_MODE_MASK_REG(old, new) \
+	(((new) & GENMASK(31, 16)) \
+	 | ((((old) & GENMASK(15, 0)) & ~((new) >> 16)) \
+	 | ((new) & ((new) >> 16))))
+
+static int mul_force_wake_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u32 old, new;
+	uint32_t ack_reg_offset;
+
+	old = vgpu_vreg(vgpu, offset);
+	new = CALC_MODE_MASK_REG(old, *(u32 *)p_data);
+
+	if (IS_SKYLAKE(vgpu->gvt->dev_priv)) {
+		switch (offset) {
+		case FORCEWAKE_RENDER_GEN9_REG:
+			ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG;
+			break;
+		case FORCEWAKE_BLITTER_GEN9_REG:
+			ack_reg_offset = FORCEWAKE_ACK_BLITTER_GEN9_REG;
+			break;
+		case FORCEWAKE_MEDIA_GEN9_REG:
+			ack_reg_offset = FORCEWAKE_ACK_MEDIA_GEN9_REG;
+			break;
+		default:
+			/*should not hit here*/
+			gvt_err("invalid forcewake offset 0x%x\n", offset);
+			return -EINVAL;
+		}
+	} else {
+		ack_reg_offset = FORCEWAKE_ACK_HSW_REG;
+	}
+
+	vgpu_vreg(vgpu, offset) = new;
+	vgpu_vreg(vgpu, ack_reg_offset) = (new & GENMASK(15, 0));
+	return 0;
+}
+
+static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+			    void *p_data, unsigned int bytes)
+{
+	unsigned int engine_mask = 0;
+	u32 data;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	if (data & GEN6_GRDOM_FULL) {
+		gvt_dbg_mmio("vgpu%d: request full GPU reset\n", vgpu->id);
+		engine_mask = ALL_ENGINES;
+	} else {
+		if (data & GEN6_GRDOM_RENDER) {
+			gvt_dbg_mmio("vgpu%d: request RCS reset\n", vgpu->id);
+			engine_mask |= (1 << RCS);
+		}
+		if (data & GEN6_GRDOM_MEDIA) {
+			gvt_dbg_mmio("vgpu%d: request VCS reset\n", vgpu->id);
+			engine_mask |= (1 << VCS);
+		}
+		if (data & GEN6_GRDOM_BLT) {
+			gvt_dbg_mmio("vgpu%d: request BCS Reset\n", vgpu->id);
+			engine_mask |= (1 << BCS);
+		}
+		if (data & GEN6_GRDOM_VECS) {
+			gvt_dbg_mmio("vgpu%d: request VECS Reset\n", vgpu->id);
+			engine_mask |= (1 << VECS);
+		}
+		if (data & GEN8_GRDOM_MEDIA2) {
+			gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id);
+			if (HAS_BSD2(vgpu->gvt->dev_priv))
+				engine_mask |= (1 << VCS2);
+		}
+	}
+
+	intel_gvt_reset_vgpu_locked(vgpu, false, engine_mask);
+
+	return 0;
+}
+
+static int gmbus_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	return intel_gvt_i2c_handle_gmbus_read(vgpu, offset, p_data, bytes);
+}
+
+static int gmbus_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	return intel_gvt_i2c_handle_gmbus_write(vgpu, offset, p_data, bytes);
+}
+
+static int pch_pp_control_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	if (vgpu_vreg(vgpu, offset) & PANEL_POWER_ON) {
+		vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_ON;
+		vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_SEQUENCE_STATE_ON_IDLE;
+		vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_SEQUENCE_POWER_DOWN;
+		vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_CYCLE_DELAY_ACTIVE;
+
+	} else
+		vgpu_vreg(vgpu, PCH_PP_STATUS) &=
+			~(PP_ON | PP_SEQUENCE_POWER_DOWN
+					| PP_CYCLE_DELAY_ACTIVE);
+	return 0;
+}
+
+static int transconf_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	if (vgpu_vreg(vgpu, offset) & TRANS_ENABLE)
+		vgpu_vreg(vgpu, offset) |= TRANS_STATE_ENABLE;
+	else
+		vgpu_vreg(vgpu, offset) &= ~TRANS_STATE_ENABLE;
+	return 0;
+}
+
+static int lcpll_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	if (vgpu_vreg(vgpu, offset) & LCPLL_PLL_DISABLE)
+		vgpu_vreg(vgpu, offset) &= ~LCPLL_PLL_LOCK;
+	else
+		vgpu_vreg(vgpu, offset) |= LCPLL_PLL_LOCK;
+
+	if (vgpu_vreg(vgpu, offset) & LCPLL_CD_SOURCE_FCLK)
+		vgpu_vreg(vgpu, offset) |= LCPLL_CD_SOURCE_FCLK_DONE;
+	else
+		vgpu_vreg(vgpu, offset) &= ~LCPLL_CD_SOURCE_FCLK_DONE;
+
+	return 0;
+}
+
+static int dpy_reg_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	*(u32 *)p_data = (1 << 17);
+	return 0;
+}
+
+static int dpy_reg_mmio_read_2(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	*(u32 *)p_data = 3;
+	return 0;
+}
+
+static int dpy_reg_mmio_read_3(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	*(u32 *)p_data = (0x2f << 16);
+	return 0;
+}
+
+static int pipeconf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 data;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	if (data & PIPECONF_ENABLE)
+		vgpu_vreg(vgpu, offset) |= I965_PIPECONF_ACTIVE;
+	else
+		vgpu_vreg(vgpu, offset) &= ~I965_PIPECONF_ACTIVE;
+	intel_gvt_check_vblank_emulation(vgpu->gvt);
+	return 0;
+}
+
+static int ddi_buf_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	if (vgpu_vreg(vgpu, offset) & DDI_BUF_CTL_ENABLE) {
+		vgpu_vreg(vgpu, offset) &= ~DDI_BUF_IS_IDLE;
+	} else {
+		vgpu_vreg(vgpu, offset) |= DDI_BUF_IS_IDLE;
+		if (offset == i915_mmio_reg_offset(DDI_BUF_CTL(PORT_E)))
+			vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E))
+				&= ~DP_TP_STATUS_AUTOTRAIN_DONE;
+	}
+	return 0;
+}
+
+static int fdi_rx_iir_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	vgpu_vreg(vgpu, offset) &= ~*(u32 *)p_data;
+	return 0;
+}
+
+#define FDI_LINK_TRAIN_PATTERN1         0
+#define FDI_LINK_TRAIN_PATTERN2         1
+
+static int fdi_auto_training_started(struct intel_vgpu *vgpu)
+{
+	u32 ddi_buf_ctl = vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_E));
+	u32 rx_ctl = vgpu_vreg(vgpu, _FDI_RXA_CTL);
+	u32 tx_ctl = vgpu_vreg(vgpu, DP_TP_CTL(PORT_E));
+
+	if ((ddi_buf_ctl & DDI_BUF_CTL_ENABLE) &&
+			(rx_ctl & FDI_RX_ENABLE) &&
+			(rx_ctl & FDI_AUTO_TRAINING) &&
+			(tx_ctl & DP_TP_CTL_ENABLE) &&
+			(tx_ctl & DP_TP_CTL_FDI_AUTOTRAIN))
+		return 1;
+	else
+		return 0;
+}
+
+static int check_fdi_rx_train_status(struct intel_vgpu *vgpu,
+		enum pipe pipe, unsigned int train_pattern)
+{
+	i915_reg_t fdi_rx_imr, fdi_tx_ctl, fdi_rx_ctl;
+	unsigned int fdi_rx_check_bits, fdi_tx_check_bits;
+	unsigned int fdi_rx_train_bits, fdi_tx_train_bits;
+	unsigned int fdi_iir_check_bits;
+
+	fdi_rx_imr = FDI_RX_IMR(pipe);
+	fdi_tx_ctl = FDI_TX_CTL(pipe);
+	fdi_rx_ctl = FDI_RX_CTL(pipe);
+
+	if (train_pattern == FDI_LINK_TRAIN_PATTERN1) {
+		fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_1_CPT;
+		fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_1;
+		fdi_iir_check_bits = FDI_RX_BIT_LOCK;
+	} else if (train_pattern == FDI_LINK_TRAIN_PATTERN2) {
+		fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_2_CPT;
+		fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_2;
+		fdi_iir_check_bits = FDI_RX_SYMBOL_LOCK;
+	} else {
+		gvt_err("Invalid train pattern %d\n", train_pattern);
+		return -EINVAL;
+	}
+
+	fdi_rx_check_bits = FDI_RX_ENABLE | fdi_rx_train_bits;
+	fdi_tx_check_bits = FDI_TX_ENABLE | fdi_tx_train_bits;
+
+	/* If imr bit has been masked */
+	if (vgpu_vreg(vgpu, fdi_rx_imr) & fdi_iir_check_bits)
+		return 0;
+
+	if (((vgpu_vreg(vgpu, fdi_tx_ctl) & fdi_tx_check_bits)
+			== fdi_tx_check_bits)
+		&& ((vgpu_vreg(vgpu, fdi_rx_ctl) & fdi_rx_check_bits)
+			== fdi_rx_check_bits))
+		return 1;
+	else
+		return 0;
+}
+
+#define INVALID_INDEX (~0U)
+
+static unsigned int calc_index(unsigned int offset, unsigned int start,
+	unsigned int next, unsigned int end, i915_reg_t i915_end)
+{
+	unsigned int range = next - start;
+
+	if (!end)
+		end = i915_mmio_reg_offset(i915_end);
+	if (offset < start || offset > end)
+		return INVALID_INDEX;
+	offset -= start;
+	return offset / range;
+}
+
+#define FDI_RX_CTL_TO_PIPE(offset) \
+	calc_index(offset, _FDI_RXA_CTL, _FDI_RXB_CTL, 0, FDI_RX_CTL(PIPE_C))
+
+#define FDI_TX_CTL_TO_PIPE(offset) \
+	calc_index(offset, _FDI_TXA_CTL, _FDI_TXB_CTL, 0, FDI_TX_CTL(PIPE_C))
+
+#define FDI_RX_IMR_TO_PIPE(offset) \
+	calc_index(offset, _FDI_RXA_IMR, _FDI_RXB_IMR, 0, FDI_RX_IMR(PIPE_C))
+
+static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	i915_reg_t fdi_rx_iir;
+	unsigned int index;
+	int ret;
+
+	if (FDI_RX_CTL_TO_PIPE(offset) != INVALID_INDEX)
+		index = FDI_RX_CTL_TO_PIPE(offset);
+	else if (FDI_TX_CTL_TO_PIPE(offset) != INVALID_INDEX)
+		index = FDI_TX_CTL_TO_PIPE(offset);
+	else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX)
+		index = FDI_RX_IMR_TO_PIPE(offset);
+	else {
+		gvt_err("Unsupport registers %x\n", offset);
+		return -EINVAL;
+	}
+
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	fdi_rx_iir = FDI_RX_IIR(index);
+
+	ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN1);
+	if (ret < 0)
+		return ret;
+	if (ret)
+		vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_BIT_LOCK;
+
+	ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN2);
+	if (ret < 0)
+		return ret;
+	if (ret)
+		vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_SYMBOL_LOCK;
+
+	if (offset == _FDI_RXA_CTL)
+		if (fdi_auto_training_started(vgpu))
+			vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E)) |=
+				DP_TP_STATUS_AUTOTRAIN_DONE;
+	return 0;
+}
+
+#define DP_TP_CTL_TO_PORT(offset) \
+	calc_index(offset, _DP_TP_CTL_A, _DP_TP_CTL_B, 0, DP_TP_CTL(PORT_E))
+
+static int dp_tp_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	i915_reg_t status_reg;
+	unsigned int index;
+	u32 data;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	index = DP_TP_CTL_TO_PORT(offset);
+	data = (vgpu_vreg(vgpu, offset) & GENMASK(10, 8)) >> 8;
+	if (data == 0x2) {
+		status_reg = DP_TP_STATUS(index);
+		vgpu_vreg(vgpu, status_reg) |= (1 << 25);
+	}
+	return 0;
+}
+
+static int dp_tp_status_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u32 reg_val;
+	u32 sticky_mask;
+
+	reg_val = *((u32 *)p_data);
+	sticky_mask = GENMASK(27, 26) | (1 << 24);
+
+	vgpu_vreg(vgpu, offset) = (reg_val & ~sticky_mask) |
+		(vgpu_vreg(vgpu, offset) & sticky_mask);
+	vgpu_vreg(vgpu, offset) &= ~(reg_val & sticky_mask);
+	return 0;
+}
+
+static int pch_adpa_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u32 data;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	if (data & ADPA_CRT_HOTPLUG_FORCE_TRIGGER)
+		vgpu_vreg(vgpu, offset) &= ~ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
+	return 0;
+}
+
+static int south_chicken2_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u32 data;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	if (data & FDI_MPHY_IOSFSB_RESET_CTL)
+		vgpu_vreg(vgpu, offset) |= FDI_MPHY_IOSFSB_RESET_STATUS;
+	else
+		vgpu_vreg(vgpu, offset) &= ~FDI_MPHY_IOSFSB_RESET_STATUS;
+	return 0;
+}
+
+#define DSPSURF_TO_PIPE(offset) \
+	calc_index(offset, _DSPASURF, _DSPBSURF, 0, DSPSURF(PIPE_C))
+
+static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	unsigned int index = DSPSURF_TO_PIPE(offset);
+	i915_reg_t surflive_reg = DSPSURFLIVE(index);
+	int flip_event[] = {
+		[PIPE_A] = PRIMARY_A_FLIP_DONE,
+		[PIPE_B] = PRIMARY_B_FLIP_DONE,
+		[PIPE_C] = PRIMARY_C_FLIP_DONE,
+	};
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
+
+	set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
+	return 0;
+}
+
+#define SPRSURF_TO_PIPE(offset) \
+	calc_index(offset, _SPRA_SURF, _SPRB_SURF, 0, SPRSURF(PIPE_C))
+
+static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	unsigned int index = SPRSURF_TO_PIPE(offset);
+	i915_reg_t surflive_reg = SPRSURFLIVE(index);
+	int flip_event[] = {
+		[PIPE_A] = SPRITE_A_FLIP_DONE,
+		[PIPE_B] = SPRITE_B_FLIP_DONE,
+		[PIPE_C] = SPRITE_C_FLIP_DONE,
+	};
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
+
+	set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
+	return 0;
+}
+
+static int trigger_aux_channel_interrupt(struct intel_vgpu *vgpu,
+		unsigned int reg)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	enum intel_gvt_event_type event;
+
+	if (reg == _DPA_AUX_CH_CTL)
+		event = AUX_CHANNEL_A;
+	else if (reg == _PCH_DPB_AUX_CH_CTL || reg == _DPB_AUX_CH_CTL)
+		event = AUX_CHANNEL_B;
+	else if (reg == _PCH_DPC_AUX_CH_CTL || reg == _DPC_AUX_CH_CTL)
+		event = AUX_CHANNEL_C;
+	else if (reg == _PCH_DPD_AUX_CH_CTL || reg == _DPD_AUX_CH_CTL)
+		event = AUX_CHANNEL_D;
+	else {
+		WARN_ON(true);
+		return -EINVAL;
+	}
+
+	intel_vgpu_trigger_virtual_event(vgpu, event);
+	return 0;
+}
+
+static int dp_aux_ch_ctl_trans_done(struct intel_vgpu *vgpu, u32 value,
+		unsigned int reg, int len, bool data_valid)
+{
+	/* mark transaction done */
+	value |= DP_AUX_CH_CTL_DONE;
+	value &= ~DP_AUX_CH_CTL_SEND_BUSY;
+	value &= ~DP_AUX_CH_CTL_RECEIVE_ERROR;
+
+	if (data_valid)
+		value &= ~DP_AUX_CH_CTL_TIME_OUT_ERROR;
+	else
+		value |= DP_AUX_CH_CTL_TIME_OUT_ERROR;
+
+	/* message size */
+	value &= ~(0xf << 20);
+	value |= (len << 20);
+	vgpu_vreg(vgpu, reg) = value;
+
+	if (value & DP_AUX_CH_CTL_INTERRUPT)
+		return trigger_aux_channel_interrupt(vgpu, reg);
+	return 0;
+}
+
+static void dp_aux_ch_ctl_link_training(struct intel_vgpu_dpcd_data *dpcd,
+		uint8_t t)
+{
+	if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == DPCD_TRAINING_PATTERN_1) {
+		/* training pattern 1 for CR */
+		/* set LANE0_CR_DONE, LANE1_CR_DONE */
+		dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_CR_DONE;
+		/* set LANE2_CR_DONE, LANE3_CR_DONE */
+		dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_CR_DONE;
+	} else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) ==
+			DPCD_TRAINING_PATTERN_2) {
+		/* training pattern 2 for EQ */
+		/* Set CHANNEL_EQ_DONE and  SYMBOL_LOCKED for Lane0_1 */
+		dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_EQ_DONE;
+		dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_SYMBOL_LOCKED;
+		/* Set CHANNEL_EQ_DONE and  SYMBOL_LOCKED for Lane2_3 */
+		dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_EQ_DONE;
+		dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_SYMBOL_LOCKED;
+		/* set INTERLANE_ALIGN_DONE */
+		dpcd->data[DPCD_LANE_ALIGN_STATUS_UPDATED] |=
+			DPCD_INTERLANE_ALIGN_DONE;
+	} else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) ==
+			DPCD_LINK_TRAINING_DISABLED) {
+		/* finish link training */
+		/* set sink status as synchronized */
+		dpcd->data[DPCD_SINK_STATUS] = DPCD_SINK_IN_SYNC;
+	}
+}
+
+#define _REG_HSW_DP_AUX_CH_CTL(dp) \
+	((dp) ? (_PCH_DPB_AUX_CH_CTL + ((dp)-1)*0x100) : 0x64010)
+
+#define _REG_SKL_DP_AUX_CH_CTL(dp) (0x64010 + (dp) * 0x100)
+
+#define OFFSET_TO_DP_AUX_PORT(offset) (((offset) & 0xF00) >> 8)
+
+#define dpy_is_valid_port(port)	\
+		(((port) >= PORT_A) && ((port) < I915_MAX_PORTS))
+
+static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	struct intel_vgpu_display *display = &vgpu->display;
+	int msg, addr, ctrl, op, len;
+	int port_index = OFFSET_TO_DP_AUX_PORT(offset);
+	struct intel_vgpu_dpcd_data *dpcd = NULL;
+	struct intel_vgpu_port *port = NULL;
+	u32 data;
+
+	if (!dpy_is_valid_port(port_index)) {
+		gvt_err("GVT(%d): Unsupported DP port access!\n", vgpu->id);
+		return 0;
+	}
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	if (IS_SKYLAKE(vgpu->gvt->dev_priv) &&
+	    offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) {
+		/* SKL DPB/C/D aux ctl register changed */
+		return 0;
+	} else if (IS_BROADWELL(vgpu->gvt->dev_priv) &&
+		   offset != _REG_HSW_DP_AUX_CH_CTL(port_index)) {
+		/* write to the data registers */
+		return 0;
+	}
+
+	if (!(data & DP_AUX_CH_CTL_SEND_BUSY)) {
+		/* just want to clear the sticky bits */
+		vgpu_vreg(vgpu, offset) = 0;
+		return 0;
+	}
+
+	port = &display->ports[port_index];
+	dpcd = port->dpcd;
+
+	/* read out message from DATA1 register */
+	msg = vgpu_vreg(vgpu, offset + 4);
+	addr = (msg >> 8) & 0xffff;
+	ctrl = (msg >> 24) & 0xff;
+	len = msg & 0xff;
+	op = ctrl >> 4;
+
+	if (op == GVT_AUX_NATIVE_WRITE) {
+		int t;
+		uint8_t buf[16];
+
+		if ((addr + len + 1) >= DPCD_SIZE) {
+			/*
+			 * Write request exceeds what we supported,
+			 * DCPD spec: When a Source Device is writing a DPCD
+			 * address not supported by the Sink Device, the Sink
+			 * Device shall reply with AUX NACK and “M” equal to
+			 * zero.
+			 */
+
+			/* NAK the write */
+			vgpu_vreg(vgpu, offset + 4) = AUX_NATIVE_REPLY_NAK;
+			dp_aux_ch_ctl_trans_done(vgpu, data, offset, 2, true);
+			return 0;
+		}
+
+		/*
+		 * Write request format: (command + address) occupies
+		 * 3 bytes, followed by (len + 1) bytes of data.
+		 */
+		if (WARN_ON((len + 4) > AUX_BURST_SIZE))
+			return -EINVAL;
+
+		/* unpack data from vreg to buf */
+		for (t = 0; t < 4; t++) {
+			u32 r = vgpu_vreg(vgpu, offset + 8 + t * 4);
+
+			buf[t * 4] = (r >> 24) & 0xff;
+			buf[t * 4 + 1] = (r >> 16) & 0xff;
+			buf[t * 4 + 2] = (r >> 8) & 0xff;
+			buf[t * 4 + 3] = r & 0xff;
+		}
+
+		/* write to virtual DPCD */
+		if (dpcd && dpcd->data_valid) {
+			for (t = 0; t <= len; t++) {
+				int p = addr + t;
+
+				dpcd->data[p] = buf[t];
+				/* check for link training */
+				if (p == DPCD_TRAINING_PATTERN_SET)
+					dp_aux_ch_ctl_link_training(dpcd,
+							buf[t]);
+			}
+		}
+
+		/* ACK the write */
+		vgpu_vreg(vgpu, offset + 4) = 0;
+		dp_aux_ch_ctl_trans_done(vgpu, data, offset, 1,
+				dpcd && dpcd->data_valid);
+		return 0;
+	}
+
+	if (op == GVT_AUX_NATIVE_READ) {
+		int idx, i, ret = 0;
+
+		if ((addr + len + 1) >= DPCD_SIZE) {
+			/*
+			 * read request exceeds what we supported
+			 * DPCD spec: A Sink Device receiving a Native AUX CH
+			 * read request for an unsupported DPCD address must
+			 * reply with an AUX ACK and read data set equal to
+			 * zero instead of replying with AUX NACK.
+			 */
+
+			/* ACK the READ*/
+			vgpu_vreg(vgpu, offset + 4) = 0;
+			vgpu_vreg(vgpu, offset + 8) = 0;
+			vgpu_vreg(vgpu, offset + 12) = 0;
+			vgpu_vreg(vgpu, offset + 16) = 0;
+			vgpu_vreg(vgpu, offset + 20) = 0;
+
+			dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2,
+					true);
+			return 0;
+		}
+
+		for (idx = 1; idx <= 5; idx++) {
+			/* clear the data registers */
+			vgpu_vreg(vgpu, offset + 4 * idx) = 0;
+		}
+
+		/*
+		 * Read reply format: ACK (1 byte) plus (len + 1) bytes of data.
+		 */
+		if (WARN_ON((len + 2) > AUX_BURST_SIZE))
+			return -EINVAL;
+
+		/* read from virtual DPCD to vreg */
+		/* first 4 bytes: [ACK][addr][addr+1][addr+2] */
+		if (dpcd && dpcd->data_valid) {
+			for (i = 1; i <= (len + 1); i++) {
+				int t;
+
+				t = dpcd->data[addr + i - 1];
+				t <<= (24 - 8 * (i % 4));
+				ret |= t;
+
+				if ((i % 4 == 3) || (i == (len + 1))) {
+					vgpu_vreg(vgpu, offset +
+							(i / 4 + 1) * 4) = ret;
+					ret = 0;
+				}
+			}
+		}
+		dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2,
+				dpcd && dpcd->data_valid);
+		return 0;
+	}
+
+	/* i2c transaction starts */
+	intel_gvt_i2c_handle_aux_ch_write(vgpu, port_index, offset, p_data);
+
+	if (data & DP_AUX_CH_CTL_INTERRUPT)
+		trigger_aux_channel_interrupt(vgpu, offset);
+	return 0;
+}
+
+static int vga_control_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	bool vga_disable;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	vga_disable = vgpu_vreg(vgpu, offset) & VGA_DISP_DISABLE;
+
+	gvt_dbg_core("vgpu%d: %s VGA mode\n", vgpu->id,
+			vga_disable ? "Disable" : "Enable");
+	return 0;
+}
+
+static u32 read_virtual_sbi_register(struct intel_vgpu *vgpu,
+		unsigned int sbi_offset)
+{
+	struct intel_vgpu_display *display = &vgpu->display;
+	int num = display->sbi.number;
+	int i;
+
+	for (i = 0; i < num; ++i)
+		if (display->sbi.registers[i].offset == sbi_offset)
+			break;
+
+	if (i == num)
+		return 0;
+
+	return display->sbi.registers[i].value;
+}
+
+static void write_virtual_sbi_register(struct intel_vgpu *vgpu,
+		unsigned int offset, u32 value)
+{
+	struct intel_vgpu_display *display = &vgpu->display;
+	int num = display->sbi.number;
+	int i;
+
+	for (i = 0; i < num; ++i) {
+		if (display->sbi.registers[i].offset == offset)
+			break;
+	}
+
+	if (i == num) {
+		if (num == SBI_REG_MAX) {
+			gvt_err("vgpu%d: SBI caching meets maximum limits\n",
+					vgpu->id);
+			return;
+		}
+		display->sbi.number++;
+	}
+
+	display->sbi.registers[i].offset = offset;
+	display->sbi.registers[i].value = value;
+}
+
+static int sbi_data_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >>
+				SBI_OPCODE_SHIFT) == SBI_CMD_CRRD) {
+		unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) &
+				SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT;
+		vgpu_vreg(vgpu, offset) = read_virtual_sbi_register(vgpu,
+				sbi_offset);
+	}
+	read_vreg(vgpu, offset, p_data, bytes);
+	return 0;
+}
+
+static int sbi_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 data;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	data &= ~(SBI_STAT_MASK << SBI_STAT_SHIFT);
+	data |= SBI_READY;
+
+	data &= ~(SBI_RESPONSE_MASK << SBI_RESPONSE_SHIFT);
+	data |= SBI_RESPONSE_SUCCESS;
+
+	vgpu_vreg(vgpu, offset) = data;
+
+	if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >>
+				SBI_OPCODE_SHIFT) == SBI_CMD_CRWR) {
+		unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) &
+				SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT;
+
+		write_virtual_sbi_register(vgpu, sbi_offset,
+				vgpu_vreg(vgpu, SBI_DATA));
+	}
+	return 0;
+}
+
+#define _vgtif_reg(x) \
+	(VGT_PVINFO_PAGE + offsetof(struct vgt_if, x))
+
+static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	bool invalid_read = false;
+
+	read_vreg(vgpu, offset, p_data, bytes);
+
+	switch (offset) {
+	case _vgtif_reg(magic) ... _vgtif_reg(vgt_id):
+		if (offset + bytes > _vgtif_reg(vgt_id) + 4)
+			invalid_read = true;
+		break;
+	case _vgtif_reg(avail_rs.mappable_gmadr.base) ...
+		_vgtif_reg(avail_rs.fence_num):
+		if (offset + bytes >
+			_vgtif_reg(avail_rs.fence_num) + 4)
+			invalid_read = true;
+		break;
+	case 0x78010:	/* vgt_caps */
+	case 0x7881c:
+		break;
+	default:
+		invalid_read = true;
+		break;
+	}
+	if (invalid_read)
+		gvt_err("invalid pvinfo read: [%x:%x] = %x\n",
+				offset, bytes, *(u32 *)p_data);
+	return 0;
+}
+
+static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification)
+{
+	int ret = 0;
+
+	switch (notification) {
+	case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE:
+		ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 3);
+		break;
+	case VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY:
+		ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 3);
+		break;
+	case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE:
+		ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 4);
+		break;
+	case VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY:
+		ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 4);
+		break;
+	case VGT_G2V_EXECLIST_CONTEXT_CREATE:
+	case VGT_G2V_EXECLIST_CONTEXT_DESTROY:
+	case 1:	/* Remove this in guest driver. */
+		break;
+	default:
+		gvt_err("Invalid PV notification %d\n", notification);
+	}
+	return ret;
+}
+
+static int send_display_ready_uevent(struct intel_vgpu *vgpu, int ready)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj;
+	char *env[3] = {NULL, NULL, NULL};
+	char vmid_str[20];
+	char display_ready_str[20];
+
+	snprintf(display_ready_str, 20, "GVT_DISPLAY_READY=%d\n", ready);
+	env[0] = display_ready_str;
+
+	snprintf(vmid_str, 20, "VMID=%d", vgpu->id);
+	env[1] = vmid_str;
+
+	return kobject_uevent_env(kobj, KOBJ_ADD, env);
+}
+
+static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 data;
+	int ret;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	switch (offset) {
+	case _vgtif_reg(display_ready):
+		send_display_ready_uevent(vgpu, data ? 1 : 0);
+		break;
+	case _vgtif_reg(g2v_notify):
+		ret = handle_g2v_notification(vgpu, data);
+		break;
+	/* add xhot and yhot to handled list to avoid error log */
+	case 0x78830:
+	case 0x78834:
+	case _vgtif_reg(pdp[0].lo):
+	case _vgtif_reg(pdp[0].hi):
+	case _vgtif_reg(pdp[1].lo):
+	case _vgtif_reg(pdp[1].hi):
+	case _vgtif_reg(pdp[2].lo):
+	case _vgtif_reg(pdp[2].hi):
+	case _vgtif_reg(pdp[3].lo):
+	case _vgtif_reg(pdp[3].hi):
+	case _vgtif_reg(execlist_context_descriptor_lo):
+	case _vgtif_reg(execlist_context_descriptor_hi):
+		break;
+	default:
+		gvt_err("invalid pvinfo write offset %x bytes %x data %x\n",
+				offset, bytes, data);
+		break;
+	}
+	return 0;
+}
+
+static int pf_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u32 val = *(u32 *)p_data;
+
+	if ((offset == _PS_1A_CTRL || offset == _PS_2A_CTRL ||
+	   offset == _PS_1B_CTRL || offset == _PS_2B_CTRL ||
+	   offset == _PS_1C_CTRL) && (val & PS_PLANE_SEL_MASK) != 0) {
+		WARN_ONCE(true, "VM(%d): guest is trying to scaling a plane\n",
+			  vgpu->id);
+		return 0;
+	}
+
+	return intel_vgpu_default_mmio_write(vgpu, offset, p_data, bytes);
+}
+
+static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_ENABLE_REQUEST)
+		vgpu_vreg(vgpu, offset) |= HSW_PWR_WELL_STATE_ENABLED;
+	else
+		vgpu_vreg(vgpu, offset) &= ~HSW_PWR_WELL_STATE_ENABLED;
+	return 0;
+}
+
+static int fpga_dbg_mmio_write(struct intel_vgpu *vgpu,
+	unsigned int offset, void *p_data, unsigned int bytes)
+{
+	write_vreg(vgpu, offset, p_data, bytes);
+
+	if (vgpu_vreg(vgpu, offset) & FPGA_DBG_RM_NOCLAIM)
+		vgpu_vreg(vgpu, offset) &= ~FPGA_DBG_RM_NOCLAIM;
+	return 0;
+}
+
+static int dma_ctrl_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 mode;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	mode = vgpu_vreg(vgpu, offset);
+
+	if (GFX_MODE_BIT_SET_IN_MASK(mode, START_DMA)) {
+		WARN_ONCE(1, "VM(%d): iGVT-g doesn't supporte GuC\n",
+				vgpu->id);
+		return 0;
+	}
+
+	return 0;
+}
+
+static int gen9_trtte_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	u32 trtte = *(u32 *)p_data;
+
+	if ((trtte & 1) && (trtte & (1 << 1)) == 0) {
+		WARN(1, "VM(%d): Use physical address for TRTT!\n",
+				vgpu->id);
+		return -EINVAL;
+	}
+	write_vreg(vgpu, offset, p_data, bytes);
+	/* TRTTE is not per-context */
+	I915_WRITE(_MMIO(offset), vgpu_vreg(vgpu, offset));
+
+	return 0;
+}
+
+static int gen9_trtt_chicken_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	u32 val = *(u32 *)p_data;
+
+	if (val & 1) {
+		/* unblock hw logic */
+		I915_WRITE(_MMIO(offset), val);
+	}
+	write_vreg(vgpu, offset, p_data, bytes);
+	return 0;
+}
+
+static int dpll_status_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 v = 0;
+
+	if (vgpu_vreg(vgpu, 0x46010) & (1 << 31))
+		v |= (1 << 0);
+
+	if (vgpu_vreg(vgpu, 0x46014) & (1 << 31))
+		v |= (1 << 8);
+
+	if (vgpu_vreg(vgpu, 0x46040) & (1 << 31))
+		v |= (1 << 16);
+
+	if (vgpu_vreg(vgpu, 0x46060) & (1 << 31))
+		v |= (1 << 24);
+
+	vgpu_vreg(vgpu, offset) = v;
+
+	return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
+}
+
+static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 value = *(u32 *)p_data;
+	u32 cmd = value & 0xff;
+	u32 *data0 = &vgpu_vreg(vgpu, GEN6_PCODE_DATA);
+
+	switch (cmd) {
+	case 0x6:
+		/**
+		 * "Read memory latency" command on gen9.
+		 * Below memory latency values are read
+		 * from skylake platform.
+		 */
+		if (!*data0)
+			*data0 = 0x1e1a1100;
+		else
+			*data0 = 0x61514b3d;
+		break;
+	case 0x5:
+		*data0 |= 0x1;
+		break;
+	}
+
+	gvt_dbg_core("VM(%d) write %x to mailbox, return data0 %x\n",
+		     vgpu->id, value, *data0);
+
+	value &= ~(1 << 31);
+	return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes);
+}
+
+static int skl_power_well_ctl_write(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u32 v = *(u32 *)p_data;
+
+	v &= (1 << 31) | (1 << 29) | (1 << 9) |
+	     (1 << 7) | (1 << 5) | (1 << 3) | (1 << 1);
+	v |= (v >> 1);
+
+	return intel_vgpu_default_mmio_write(vgpu, offset, &v, bytes);
+}
+
+static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	i915_reg_t reg = {.reg = offset};
+
+	switch (offset) {
+	case 0x4ddc:
+		vgpu_vreg(vgpu, offset) = 0x8000003c;
+		/* WaCompressedResourceSamplerPbeMediaNewHashMode:skl */
+		I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+		break;
+	case 0x42080:
+		vgpu_vreg(vgpu, offset) = 0x8000;
+		/* WaCompressedResourceDisplayNewHashMode:skl */
+		I915_WRITE(reg, vgpu_vreg(vgpu, offset));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 v = *(u32 *)p_data;
+
+	/* other bits are MBZ. */
+	v &= (1 << 31) | (1 << 30);
+	v & (1 << 31) ? (v |= (1 << 30)) : (v &= ~(1 << 30));
+
+	vgpu_vreg(vgpu, offset) = v;
+
+	return 0;
+}
+
+static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset));
+	return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
+}
+
+static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
+	struct intel_vgpu_execlist *execlist;
+	u32 data = *(u32 *)p_data;
+	int ret = 0;
+
+	if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1))
+		return -EINVAL;
+
+	execlist = &vgpu->execlist[ring_id];
+
+	execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data;
+	if (execlist->elsp_dwords.index == 3) {
+		ret = intel_vgpu_submit_execlist(vgpu, ring_id);
+		if(ret)
+			gvt_err("fail submit workload on ring %d\n", ring_id);
+	}
+
+	++execlist->elsp_dwords.index;
+	execlist->elsp_dwords.index &= 0x3;
+	return ret;
+}
+
+static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	u32 data = *(u32 *)p_data;
+	int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
+	bool enable_execlist;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	if ((data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE))
+			|| (data & _MASKED_BIT_DISABLE(GFX_RUN_LIST_ENABLE))) {
+		enable_execlist = !!(data & GFX_RUN_LIST_ENABLE);
+
+		gvt_dbg_core("EXECLIST %s on ring %d\n",
+				(enable_execlist ? "enabling" : "disabling"),
+				ring_id);
+
+		if (enable_execlist)
+			intel_vgpu_start_schedule(vgpu);
+	}
+	return 0;
+}
+
+static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu,
+		unsigned int offset, void *p_data, unsigned int bytes)
+{
+	unsigned int id = 0;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	vgpu_vreg(vgpu, offset) = 0;
+
+	switch (offset) {
+	case 0x4260:
+		id = RCS;
+		break;
+	case 0x4264:
+		id = VCS;
+		break;
+	case 0x4268:
+		id = VCS2;
+		break;
+	case 0x426c:
+		id = BCS;
+		break;
+	case 0x4270:
+		id = VECS;
+		break;
+	default:
+		return -EINVAL;
+	}
+	set_bit(id, (void *)vgpu->tlb_handle_pending);
+
+	return 0;
+}
+
+static int ring_reset_ctl_write(struct intel_vgpu *vgpu,
+	unsigned int offset, void *p_data, unsigned int bytes)
+{
+	u32 data;
+
+	write_vreg(vgpu, offset, p_data, bytes);
+	data = vgpu_vreg(vgpu, offset);
+
+	if (data & _MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET))
+		data |= RESET_CTL_READY_TO_RESET;
+	else if (data & _MASKED_BIT_DISABLE(RESET_CTL_REQUEST_RESET))
+		data &= ~RESET_CTL_READY_TO_RESET;
+
+	vgpu_vreg(vgpu, offset) = data;
+	return 0;
+}
+
+#define MMIO_F(reg, s, f, am, rm, d, r, w) do { \
+	ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \
+		f, s, am, rm, d, r, w); \
+	if (ret) \
+		return ret; \
+} while (0)
+
+#define MMIO_D(reg, d) \
+	MMIO_F(reg, 4, 0, 0, 0, d, NULL, NULL)
+
+#define MMIO_DH(reg, d, r, w) \
+	MMIO_F(reg, 4, 0, 0, 0, d, r, w)
+
+#define MMIO_DFH(reg, d, f, r, w) \
+	MMIO_F(reg, 4, f, 0, 0, d, r, w)
+
+#define MMIO_GM(reg, d, r, w) \
+	MMIO_F(reg, 4, F_GMADR, 0xFFFFF000, 0, d, r, w)
+
+#define MMIO_RO(reg, d, f, rm, r, w) \
+	MMIO_F(reg, 4, F_RO | f, 0, rm, d, r, w)
+
+#define MMIO_RING_F(prefix, s, f, am, rm, d, r, w) do { \
+	MMIO_F(prefix(RENDER_RING_BASE), s, f, am, rm, d, r, w); \
+	MMIO_F(prefix(BLT_RING_BASE), s, f, am, rm, d, r, w); \
+	MMIO_F(prefix(GEN6_BSD_RING_BASE), s, f, am, rm, d, r, w); \
+	MMIO_F(prefix(VEBOX_RING_BASE), s, f, am, rm, d, r, w); \
+} while (0)
+
+#define MMIO_RING_D(prefix, d) \
+	MMIO_RING_F(prefix, 4, 0, 0, 0, d, NULL, NULL)
+
+#define MMIO_RING_DFH(prefix, d, f, r, w) \
+	MMIO_RING_F(prefix, 4, f, 0, 0, d, r, w)
+
+#define MMIO_RING_GM(prefix, d, r, w) \
+	MMIO_RING_F(prefix, 4, F_GMADR, 0xFFFF0000, 0, d, r, w)
+
+#define MMIO_RING_RO(prefix, d, f, rm, r, w) \
+	MMIO_RING_F(prefix, 4, F_RO | f, 0, rm, d, r, w)
+
+static int init_generic_mmio_info(struct intel_gvt *gvt)
+{
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	int ret;
+
+	MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler);
+
+	MMIO_DFH(SDEIMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DFH(SDEIER, D_ALL, 0, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DFH(SDEIIR, D_ALL, 0, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(SDEISR, D_ALL);
+
+	MMIO_RING_D(RING_HWSTAM, D_ALL);
+
+	MMIO_GM(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+	MMIO_GM(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+	MMIO_GM(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+	MMIO_GM(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+
+#define RING_REG(base) (base + 0x28)
+	MMIO_RING_D(RING_REG, D_ALL);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x134)
+	MMIO_RING_D(RING_REG, D_ALL);
+#undef RING_REG
+
+	MMIO_GM(0x2148, D_ALL, NULL, NULL);
+	MMIO_GM(CCID, D_ALL, NULL, NULL);
+	MMIO_GM(0x12198, D_ALL, NULL, NULL);
+	MMIO_D(GEN7_CXT_SIZE, D_ALL);
+
+	MMIO_RING_D(RING_TAIL, D_ALL);
+	MMIO_RING_D(RING_HEAD, D_ALL);
+	MMIO_RING_D(RING_CTL, D_ALL);
+	MMIO_RING_D(RING_ACTHD, D_ALL);
+	MMIO_RING_GM(RING_START, D_ALL, NULL, NULL);
+
+	/* RING MODE */
+#define RING_REG(base) (base + 0x29c)
+	MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, ring_mode_mmio_write);
+#undef RING_REG
+
+	MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS,
+			ring_timestamp_mmio_read, NULL);
+	MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS,
+			ring_timestamp_mmio_read, NULL);
+
+	MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(CACHE_MODE_1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+
+	MMIO_DFH(0x20dc, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(_3D_CHICKEN3, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(0x2088, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(0x20e4, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(0x2470, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_D(GAM_ECOCHK, D_ALL);
+	MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+	MMIO_D(0x9030, D_ALL);
+	MMIO_D(0x20a0, D_ALL);
+	MMIO_D(0x2420, D_ALL);
+	MMIO_D(0x2430, D_ALL);
+	MMIO_D(0x2434, D_ALL);
+	MMIO_D(0x2438, D_ALL);
+	MMIO_D(0x243c, D_ALL);
+	MMIO_DFH(0x7018, D_ALL, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(HALF_SLICE_CHICKEN3, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0xe100, D_ALL, F_MODE_MASK, NULL, NULL);
+
+	/* display */
+	MMIO_F(0x60220, 0x20, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_D(0x602a0, D_ALL);
+
+	MMIO_D(0x65050, D_ALL);
+	MMIO_D(0x650b4, D_ALL);
+
+	MMIO_D(0xc4040, D_ALL);
+	MMIO_D(DERRMR, D_ALL);
+
+	MMIO_D(PIPEDSL(PIPE_A), D_ALL);
+	MMIO_D(PIPEDSL(PIPE_B), D_ALL);
+	MMIO_D(PIPEDSL(PIPE_C), D_ALL);
+	MMIO_D(PIPEDSL(_PIPE_EDP), D_ALL);
+
+	MMIO_DH(PIPECONF(PIPE_A), D_ALL, NULL, pipeconf_mmio_write);
+	MMIO_DH(PIPECONF(PIPE_B), D_ALL, NULL, pipeconf_mmio_write);
+	MMIO_DH(PIPECONF(PIPE_C), D_ALL, NULL, pipeconf_mmio_write);
+	MMIO_DH(PIPECONF(_PIPE_EDP), D_ALL, NULL, pipeconf_mmio_write);
+
+	MMIO_D(PIPESTAT(PIPE_A), D_ALL);
+	MMIO_D(PIPESTAT(PIPE_B), D_ALL);
+	MMIO_D(PIPESTAT(PIPE_C), D_ALL);
+	MMIO_D(PIPESTAT(_PIPE_EDP), D_ALL);
+
+	MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_A), D_ALL);
+	MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_B), D_ALL);
+	MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_C), D_ALL);
+	MMIO_D(PIPE_FLIPCOUNT_G4X(_PIPE_EDP), D_ALL);
+
+	MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_A), D_ALL);
+	MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_B), D_ALL);
+	MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_C), D_ALL);
+	MMIO_D(PIPE_FRMCOUNT_G4X(_PIPE_EDP), D_ALL);
+
+	MMIO_D(CURCNTR(PIPE_A), D_ALL);
+	MMIO_D(CURCNTR(PIPE_B), D_ALL);
+	MMIO_D(CURCNTR(PIPE_C), D_ALL);
+
+	MMIO_D(CURPOS(PIPE_A), D_ALL);
+	MMIO_D(CURPOS(PIPE_B), D_ALL);
+	MMIO_D(CURPOS(PIPE_C), D_ALL);
+
+	MMIO_D(CURBASE(PIPE_A), D_ALL);
+	MMIO_D(CURBASE(PIPE_B), D_ALL);
+	MMIO_D(CURBASE(PIPE_C), D_ALL);
+
+	MMIO_D(0x700ac, D_ALL);
+	MMIO_D(0x710ac, D_ALL);
+	MMIO_D(0x720ac, D_ALL);
+
+	MMIO_D(0x70090, D_ALL);
+	MMIO_D(0x70094, D_ALL);
+	MMIO_D(0x70098, D_ALL);
+	MMIO_D(0x7009c, D_ALL);
+
+	MMIO_D(DSPCNTR(PIPE_A), D_ALL);
+	MMIO_D(DSPADDR(PIPE_A), D_ALL);
+	MMIO_D(DSPSTRIDE(PIPE_A), D_ALL);
+	MMIO_D(DSPPOS(PIPE_A), D_ALL);
+	MMIO_D(DSPSIZE(PIPE_A), D_ALL);
+	MMIO_DH(DSPSURF(PIPE_A), D_ALL, NULL, pri_surf_mmio_write);
+	MMIO_D(DSPOFFSET(PIPE_A), D_ALL);
+	MMIO_D(DSPSURFLIVE(PIPE_A), D_ALL);
+
+	MMIO_D(DSPCNTR(PIPE_B), D_ALL);
+	MMIO_D(DSPADDR(PIPE_B), D_ALL);
+	MMIO_D(DSPSTRIDE(PIPE_B), D_ALL);
+	MMIO_D(DSPPOS(PIPE_B), D_ALL);
+	MMIO_D(DSPSIZE(PIPE_B), D_ALL);
+	MMIO_DH(DSPSURF(PIPE_B), D_ALL, NULL, pri_surf_mmio_write);
+	MMIO_D(DSPOFFSET(PIPE_B), D_ALL);
+	MMIO_D(DSPSURFLIVE(PIPE_B), D_ALL);
+
+	MMIO_D(DSPCNTR(PIPE_C), D_ALL);
+	MMIO_D(DSPADDR(PIPE_C), D_ALL);
+	MMIO_D(DSPSTRIDE(PIPE_C), D_ALL);
+	MMIO_D(DSPPOS(PIPE_C), D_ALL);
+	MMIO_D(DSPSIZE(PIPE_C), D_ALL);
+	MMIO_DH(DSPSURF(PIPE_C), D_ALL, NULL, pri_surf_mmio_write);
+	MMIO_D(DSPOFFSET(PIPE_C), D_ALL);
+	MMIO_D(DSPSURFLIVE(PIPE_C), D_ALL);
+
+	MMIO_D(SPRCTL(PIPE_A), D_ALL);
+	MMIO_D(SPRLINOFF(PIPE_A), D_ALL);
+	MMIO_D(SPRSTRIDE(PIPE_A), D_ALL);
+	MMIO_D(SPRPOS(PIPE_A), D_ALL);
+	MMIO_D(SPRSIZE(PIPE_A), D_ALL);
+	MMIO_D(SPRKEYVAL(PIPE_A), D_ALL);
+	MMIO_D(SPRKEYMSK(PIPE_A), D_ALL);
+	MMIO_DH(SPRSURF(PIPE_A), D_ALL, NULL, spr_surf_mmio_write);
+	MMIO_D(SPRKEYMAX(PIPE_A), D_ALL);
+	MMIO_D(SPROFFSET(PIPE_A), D_ALL);
+	MMIO_D(SPRSCALE(PIPE_A), D_ALL);
+	MMIO_D(SPRSURFLIVE(PIPE_A), D_ALL);
+
+	MMIO_D(SPRCTL(PIPE_B), D_ALL);
+	MMIO_D(SPRLINOFF(PIPE_B), D_ALL);
+	MMIO_D(SPRSTRIDE(PIPE_B), D_ALL);
+	MMIO_D(SPRPOS(PIPE_B), D_ALL);
+	MMIO_D(SPRSIZE(PIPE_B), D_ALL);
+	MMIO_D(SPRKEYVAL(PIPE_B), D_ALL);
+	MMIO_D(SPRKEYMSK(PIPE_B), D_ALL);
+	MMIO_DH(SPRSURF(PIPE_B), D_ALL, NULL, spr_surf_mmio_write);
+	MMIO_D(SPRKEYMAX(PIPE_B), D_ALL);
+	MMIO_D(SPROFFSET(PIPE_B), D_ALL);
+	MMIO_D(SPRSCALE(PIPE_B), D_ALL);
+	MMIO_D(SPRSURFLIVE(PIPE_B), D_ALL);
+
+	MMIO_D(SPRCTL(PIPE_C), D_ALL);
+	MMIO_D(SPRLINOFF(PIPE_C), D_ALL);
+	MMIO_D(SPRSTRIDE(PIPE_C), D_ALL);
+	MMIO_D(SPRPOS(PIPE_C), D_ALL);
+	MMIO_D(SPRSIZE(PIPE_C), D_ALL);
+	MMIO_D(SPRKEYVAL(PIPE_C), D_ALL);
+	MMIO_D(SPRKEYMSK(PIPE_C), D_ALL);
+	MMIO_DH(SPRSURF(PIPE_C), D_ALL, NULL, spr_surf_mmio_write);
+	MMIO_D(SPRKEYMAX(PIPE_C), D_ALL);
+	MMIO_D(SPROFFSET(PIPE_C), D_ALL);
+	MMIO_D(SPRSCALE(PIPE_C), D_ALL);
+	MMIO_D(SPRSURFLIVE(PIPE_C), D_ALL);
+
+	MMIO_F(LGC_PALETTE(PIPE_A, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(LGC_PALETTE(PIPE_B, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(LGC_PALETTE(PIPE_C, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(HTOTAL(TRANSCODER_A), D_ALL);
+	MMIO_D(HBLANK(TRANSCODER_A), D_ALL);
+	MMIO_D(HSYNC(TRANSCODER_A), D_ALL);
+	MMIO_D(VTOTAL(TRANSCODER_A), D_ALL);
+	MMIO_D(VBLANK(TRANSCODER_A), D_ALL);
+	MMIO_D(VSYNC(TRANSCODER_A), D_ALL);
+	MMIO_D(BCLRPAT(TRANSCODER_A), D_ALL);
+	MMIO_D(VSYNCSHIFT(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPESRC(TRANSCODER_A), D_ALL);
+
+	MMIO_D(HTOTAL(TRANSCODER_B), D_ALL);
+	MMIO_D(HBLANK(TRANSCODER_B), D_ALL);
+	MMIO_D(HSYNC(TRANSCODER_B), D_ALL);
+	MMIO_D(VTOTAL(TRANSCODER_B), D_ALL);
+	MMIO_D(VBLANK(TRANSCODER_B), D_ALL);
+	MMIO_D(VSYNC(TRANSCODER_B), D_ALL);
+	MMIO_D(BCLRPAT(TRANSCODER_B), D_ALL);
+	MMIO_D(VSYNCSHIFT(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPESRC(TRANSCODER_B), D_ALL);
+
+	MMIO_D(HTOTAL(TRANSCODER_C), D_ALL);
+	MMIO_D(HBLANK(TRANSCODER_C), D_ALL);
+	MMIO_D(HSYNC(TRANSCODER_C), D_ALL);
+	MMIO_D(VTOTAL(TRANSCODER_C), D_ALL);
+	MMIO_D(VBLANK(TRANSCODER_C), D_ALL);
+	MMIO_D(VSYNC(TRANSCODER_C), D_ALL);
+	MMIO_D(BCLRPAT(TRANSCODER_C), D_ALL);
+	MMIO_D(VSYNCSHIFT(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPESRC(TRANSCODER_C), D_ALL);
+
+	MMIO_D(HTOTAL(TRANSCODER_EDP), D_ALL);
+	MMIO_D(HBLANK(TRANSCODER_EDP), D_ALL);
+	MMIO_D(HSYNC(TRANSCODER_EDP), D_ALL);
+	MMIO_D(VTOTAL(TRANSCODER_EDP), D_ALL);
+	MMIO_D(VBLANK(TRANSCODER_EDP), D_ALL);
+	MMIO_D(VSYNC(TRANSCODER_EDP), D_ALL);
+	MMIO_D(BCLRPAT(TRANSCODER_EDP), D_ALL);
+	MMIO_D(VSYNCSHIFT(TRANSCODER_EDP), D_ALL);
+
+	MMIO_D(PIPE_DATA_M1(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPE_DATA_N1(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPE_DATA_M2(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPE_DATA_N2(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPE_LINK_M1(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPE_LINK_N1(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPE_LINK_M2(TRANSCODER_A), D_ALL);
+	MMIO_D(PIPE_LINK_N2(TRANSCODER_A), D_ALL);
+
+	MMIO_D(PIPE_DATA_M1(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPE_DATA_N1(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPE_DATA_M2(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPE_DATA_N2(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPE_LINK_M1(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPE_LINK_N1(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPE_LINK_M2(TRANSCODER_B), D_ALL);
+	MMIO_D(PIPE_LINK_N2(TRANSCODER_B), D_ALL);
+
+	MMIO_D(PIPE_DATA_M1(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPE_DATA_N1(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPE_DATA_M2(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPE_DATA_N2(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPE_LINK_M1(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPE_LINK_N1(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPE_LINK_M2(TRANSCODER_C), D_ALL);
+	MMIO_D(PIPE_LINK_N2(TRANSCODER_C), D_ALL);
+
+	MMIO_D(PIPE_DATA_M1(TRANSCODER_EDP), D_ALL);
+	MMIO_D(PIPE_DATA_N1(TRANSCODER_EDP), D_ALL);
+	MMIO_D(PIPE_DATA_M2(TRANSCODER_EDP), D_ALL);
+	MMIO_D(PIPE_DATA_N2(TRANSCODER_EDP), D_ALL);
+	MMIO_D(PIPE_LINK_M1(TRANSCODER_EDP), D_ALL);
+	MMIO_D(PIPE_LINK_N1(TRANSCODER_EDP), D_ALL);
+	MMIO_D(PIPE_LINK_M2(TRANSCODER_EDP), D_ALL);
+	MMIO_D(PIPE_LINK_N2(TRANSCODER_EDP), D_ALL);
+
+	MMIO_D(PF_CTL(PIPE_A), D_ALL);
+	MMIO_D(PF_WIN_SZ(PIPE_A), D_ALL);
+	MMIO_D(PF_WIN_POS(PIPE_A), D_ALL);
+	MMIO_D(PF_VSCALE(PIPE_A), D_ALL);
+	MMIO_D(PF_HSCALE(PIPE_A), D_ALL);
+
+	MMIO_D(PF_CTL(PIPE_B), D_ALL);
+	MMIO_D(PF_WIN_SZ(PIPE_B), D_ALL);
+	MMIO_D(PF_WIN_POS(PIPE_B), D_ALL);
+	MMIO_D(PF_VSCALE(PIPE_B), D_ALL);
+	MMIO_D(PF_HSCALE(PIPE_B), D_ALL);
+
+	MMIO_D(PF_CTL(PIPE_C), D_ALL);
+	MMIO_D(PF_WIN_SZ(PIPE_C), D_ALL);
+	MMIO_D(PF_WIN_POS(PIPE_C), D_ALL);
+	MMIO_D(PF_VSCALE(PIPE_C), D_ALL);
+	MMIO_D(PF_HSCALE(PIPE_C), D_ALL);
+
+	MMIO_D(WM0_PIPEA_ILK, D_ALL);
+	MMIO_D(WM0_PIPEB_ILK, D_ALL);
+	MMIO_D(WM0_PIPEC_IVB, D_ALL);
+	MMIO_D(WM1_LP_ILK, D_ALL);
+	MMIO_D(WM2_LP_ILK, D_ALL);
+	MMIO_D(WM3_LP_ILK, D_ALL);
+	MMIO_D(WM1S_LP_ILK, D_ALL);
+	MMIO_D(WM2S_LP_IVB, D_ALL);
+	MMIO_D(WM3S_LP_IVB, D_ALL);
+
+	MMIO_D(BLC_PWM_CPU_CTL2, D_ALL);
+	MMIO_D(BLC_PWM_CPU_CTL, D_ALL);
+	MMIO_D(BLC_PWM_PCH_CTL1, D_ALL);
+	MMIO_D(BLC_PWM_PCH_CTL2, D_ALL);
+
+	MMIO_D(0x48268, D_ALL);
+
+	MMIO_F(PCH_GMBUS0, 4 * 4, 0, 0, 0, D_ALL, gmbus_mmio_read,
+		gmbus_mmio_write);
+	MMIO_F(PCH_GPIOA, 6 * 4, F_UNALIGN, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0xe4f00, 0x28, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_F(_PCH_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL,
+		dp_aux_ch_ctl_mmio_write);
+	MMIO_F(_PCH_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL,
+		dp_aux_ch_ctl_mmio_write);
+	MMIO_F(_PCH_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL,
+		dp_aux_ch_ctl_mmio_write);
+
+	MMIO_RO(PCH_ADPA, D_ALL, 0, ADPA_CRT_HOTPLUG_MONITOR_MASK, NULL, pch_adpa_mmio_write);
+
+	MMIO_DH(_PCH_TRANSACONF, D_ALL, NULL, transconf_mmio_write);
+	MMIO_DH(_PCH_TRANSBCONF, D_ALL, NULL, transconf_mmio_write);
+
+	MMIO_DH(FDI_RX_IIR(PIPE_A), D_ALL, NULL, fdi_rx_iir_mmio_write);
+	MMIO_DH(FDI_RX_IIR(PIPE_B), D_ALL, NULL, fdi_rx_iir_mmio_write);
+	MMIO_DH(FDI_RX_IIR(PIPE_C), D_ALL, NULL, fdi_rx_iir_mmio_write);
+	MMIO_DH(FDI_RX_IMR(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status);
+	MMIO_DH(FDI_RX_IMR(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status);
+	MMIO_DH(FDI_RX_IMR(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status);
+	MMIO_DH(FDI_RX_CTL(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status);
+	MMIO_DH(FDI_RX_CTL(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status);
+	MMIO_DH(FDI_RX_CTL(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status);
+
+	MMIO_D(_PCH_TRANS_HTOTAL_A, D_ALL);
+	MMIO_D(_PCH_TRANS_HBLANK_A, D_ALL);
+	MMIO_D(_PCH_TRANS_HSYNC_A, D_ALL);
+	MMIO_D(_PCH_TRANS_VTOTAL_A, D_ALL);
+	MMIO_D(_PCH_TRANS_VBLANK_A, D_ALL);
+	MMIO_D(_PCH_TRANS_VSYNC_A, D_ALL);
+	MMIO_D(_PCH_TRANS_VSYNCSHIFT_A, D_ALL);
+
+	MMIO_D(_PCH_TRANS_HTOTAL_B, D_ALL);
+	MMIO_D(_PCH_TRANS_HBLANK_B, D_ALL);
+	MMIO_D(_PCH_TRANS_HSYNC_B, D_ALL);
+	MMIO_D(_PCH_TRANS_VTOTAL_B, D_ALL);
+	MMIO_D(_PCH_TRANS_VBLANK_B, D_ALL);
+	MMIO_D(_PCH_TRANS_VSYNC_B, D_ALL);
+	MMIO_D(_PCH_TRANS_VSYNCSHIFT_B, D_ALL);
+
+	MMIO_D(_PCH_TRANSA_DATA_M1, D_ALL);
+	MMIO_D(_PCH_TRANSA_DATA_N1, D_ALL);
+	MMIO_D(_PCH_TRANSA_DATA_M2, D_ALL);
+	MMIO_D(_PCH_TRANSA_DATA_N2, D_ALL);
+	MMIO_D(_PCH_TRANSA_LINK_M1, D_ALL);
+	MMIO_D(_PCH_TRANSA_LINK_N1, D_ALL);
+	MMIO_D(_PCH_TRANSA_LINK_M2, D_ALL);
+	MMIO_D(_PCH_TRANSA_LINK_N2, D_ALL);
+
+	MMIO_D(TRANS_DP_CTL(PIPE_A), D_ALL);
+	MMIO_D(TRANS_DP_CTL(PIPE_B), D_ALL);
+	MMIO_D(TRANS_DP_CTL(PIPE_C), D_ALL);
+
+	MMIO_D(TVIDEO_DIP_CTL(PIPE_A), D_ALL);
+	MMIO_D(TVIDEO_DIP_DATA(PIPE_A), D_ALL);
+	MMIO_D(TVIDEO_DIP_GCP(PIPE_A), D_ALL);
+
+	MMIO_D(TVIDEO_DIP_CTL(PIPE_B), D_ALL);
+	MMIO_D(TVIDEO_DIP_DATA(PIPE_B), D_ALL);
+	MMIO_D(TVIDEO_DIP_GCP(PIPE_B), D_ALL);
+
+	MMIO_D(TVIDEO_DIP_CTL(PIPE_C), D_ALL);
+	MMIO_D(TVIDEO_DIP_DATA(PIPE_C), D_ALL);
+	MMIO_D(TVIDEO_DIP_GCP(PIPE_C), D_ALL);
+
+	MMIO_D(_FDI_RXA_MISC, D_ALL);
+	MMIO_D(_FDI_RXB_MISC, D_ALL);
+	MMIO_D(_FDI_RXA_TUSIZE1, D_ALL);
+	MMIO_D(_FDI_RXA_TUSIZE2, D_ALL);
+	MMIO_D(_FDI_RXB_TUSIZE1, D_ALL);
+	MMIO_D(_FDI_RXB_TUSIZE2, D_ALL);
+
+	MMIO_DH(PCH_PP_CONTROL, D_ALL, NULL, pch_pp_control_mmio_write);
+	MMIO_D(PCH_PP_DIVISOR, D_ALL);
+	MMIO_D(PCH_PP_STATUS,  D_ALL);
+	MMIO_D(PCH_LVDS, D_ALL);
+	MMIO_D(_PCH_DPLL_A, D_ALL);
+	MMIO_D(_PCH_DPLL_B, D_ALL);
+	MMIO_D(_PCH_FPA0, D_ALL);
+	MMIO_D(_PCH_FPA1, D_ALL);
+	MMIO_D(_PCH_FPB0, D_ALL);
+	MMIO_D(_PCH_FPB1, D_ALL);
+	MMIO_D(PCH_DREF_CONTROL, D_ALL);
+	MMIO_D(PCH_RAWCLK_FREQ, D_ALL);
+	MMIO_D(PCH_DPLL_SEL, D_ALL);
+
+	MMIO_D(0x61208, D_ALL);
+	MMIO_D(0x6120c, D_ALL);
+	MMIO_D(PCH_PP_ON_DELAYS, D_ALL);
+	MMIO_D(PCH_PP_OFF_DELAYS, D_ALL);
+
+	MMIO_DH(0xe651c, D_ALL, dpy_reg_mmio_read, NULL);
+	MMIO_DH(0xe661c, D_ALL, dpy_reg_mmio_read, NULL);
+	MMIO_DH(0xe671c, D_ALL, dpy_reg_mmio_read, NULL);
+	MMIO_DH(0xe681c, D_ALL, dpy_reg_mmio_read, NULL);
+	MMIO_DH(0xe6c04, D_ALL, dpy_reg_mmio_read_2, NULL);
+	MMIO_DH(0xe6e1c, D_ALL, dpy_reg_mmio_read_3, NULL);
+
+	MMIO_RO(PCH_PORT_HOTPLUG, D_ALL, 0,
+		PORTA_HOTPLUG_STATUS_MASK
+		| PORTB_HOTPLUG_STATUS_MASK
+		| PORTC_HOTPLUG_STATUS_MASK
+		| PORTD_HOTPLUG_STATUS_MASK,
+		NULL, NULL);
+
+	MMIO_DH(LCPLL_CTL, D_ALL, NULL, lcpll_ctl_mmio_write);
+	MMIO_D(FUSE_STRAP, D_ALL);
+	MMIO_D(DIGITAL_PORT_HOTPLUG_CNTRL, D_ALL);
+
+	MMIO_D(DISP_ARB_CTL, D_ALL);
+	MMIO_D(DISP_ARB_CTL2, D_ALL);
+
+	MMIO_D(ILK_DISPLAY_CHICKEN1, D_ALL);
+	MMIO_D(ILK_DISPLAY_CHICKEN2, D_ALL);
+	MMIO_D(ILK_DSPCLK_GATE_D, D_ALL);
+
+	MMIO_D(SOUTH_CHICKEN1, D_ALL);
+	MMIO_DH(SOUTH_CHICKEN2, D_ALL, NULL, south_chicken2_mmio_write);
+	MMIO_D(_TRANSA_CHICKEN1, D_ALL);
+	MMIO_D(_TRANSB_CHICKEN1, D_ALL);
+	MMIO_D(SOUTH_DSPCLK_GATE_D, D_ALL);
+	MMIO_D(_TRANSA_CHICKEN2, D_ALL);
+	MMIO_D(_TRANSB_CHICKEN2, D_ALL);
+
+	MMIO_D(ILK_DPFC_CB_BASE, D_ALL);
+	MMIO_D(ILK_DPFC_CONTROL, D_ALL);
+	MMIO_D(ILK_DPFC_RECOMP_CTL, D_ALL);
+	MMIO_D(ILK_DPFC_STATUS, D_ALL);
+	MMIO_D(ILK_DPFC_FENCE_YOFF, D_ALL);
+	MMIO_D(ILK_DPFC_CHICKEN, D_ALL);
+	MMIO_D(ILK_FBC_RT_BASE, D_ALL);
+
+	MMIO_D(IPS_CTL, D_ALL);
+
+	MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BY(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BU(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BV(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_MODE(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_A), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_A), D_ALL);
+
+	MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BY(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BU(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BV(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_MODE(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_B), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_B), D_ALL);
+
+	MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BY(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BU(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_COEFF_BV(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_MODE(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_C), D_ALL);
+	MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_C), D_ALL);
+
+	MMIO_D(PREC_PAL_INDEX(PIPE_A), D_ALL);
+	MMIO_D(PREC_PAL_DATA(PIPE_A), D_ALL);
+	MMIO_F(PREC_PAL_GC_MAX(PIPE_A, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(PREC_PAL_INDEX(PIPE_B), D_ALL);
+	MMIO_D(PREC_PAL_DATA(PIPE_B), D_ALL);
+	MMIO_F(PREC_PAL_GC_MAX(PIPE_B, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(PREC_PAL_INDEX(PIPE_C), D_ALL);
+	MMIO_D(PREC_PAL_DATA(PIPE_C), D_ALL);
+	MMIO_F(PREC_PAL_GC_MAX(PIPE_C, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(0x60110, D_ALL);
+	MMIO_D(0x61110, D_ALL);
+	MMIO_F(0x70400, 0x40, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x71400, 0x40, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x72400, 0x40, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x70440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+	MMIO_F(0x71440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+	MMIO_F(0x72440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+	MMIO_F(0x7044c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+	MMIO_F(0x7144c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+	MMIO_F(0x7244c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL);
+
+	MMIO_D(PIPE_WM_LINETIME(PIPE_A), D_ALL);
+	MMIO_D(PIPE_WM_LINETIME(PIPE_B), D_ALL);
+	MMIO_D(PIPE_WM_LINETIME(PIPE_C), D_ALL);
+	MMIO_D(SPLL_CTL, D_ALL);
+	MMIO_D(_WRPLL_CTL1, D_ALL);
+	MMIO_D(_WRPLL_CTL2, D_ALL);
+	MMIO_D(PORT_CLK_SEL(PORT_A), D_ALL);
+	MMIO_D(PORT_CLK_SEL(PORT_B), D_ALL);
+	MMIO_D(PORT_CLK_SEL(PORT_C), D_ALL);
+	MMIO_D(PORT_CLK_SEL(PORT_D), D_ALL);
+	MMIO_D(PORT_CLK_SEL(PORT_E), D_ALL);
+	MMIO_D(TRANS_CLK_SEL(TRANSCODER_A), D_ALL);
+	MMIO_D(TRANS_CLK_SEL(TRANSCODER_B), D_ALL);
+	MMIO_D(TRANS_CLK_SEL(TRANSCODER_C), D_ALL);
+
+	MMIO_D(HSW_NDE_RSTWRN_OPT, D_ALL);
+	MMIO_D(0x46508, D_ALL);
+
+	MMIO_D(0x49080, D_ALL);
+	MMIO_D(0x49180, D_ALL);
+	MMIO_D(0x49280, D_ALL);
+
+	MMIO_F(0x49090, 0x14, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x49190, 0x14, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x49290, 0x14, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(GAMMA_MODE(PIPE_A), D_ALL);
+	MMIO_D(GAMMA_MODE(PIPE_B), D_ALL);
+	MMIO_D(GAMMA_MODE(PIPE_C), D_ALL);
+
+	MMIO_D(PIPE_MULT(PIPE_A), D_ALL);
+	MMIO_D(PIPE_MULT(PIPE_B), D_ALL);
+	MMIO_D(PIPE_MULT(PIPE_C), D_ALL);
+
+	MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_A), D_ALL);
+	MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_B), D_ALL);
+	MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_C), D_ALL);
+
+	MMIO_DH(SFUSE_STRAP, D_ALL, NULL, NULL);
+	MMIO_D(SBI_ADDR, D_ALL);
+	MMIO_DH(SBI_DATA, D_ALL, sbi_data_mmio_read, NULL);
+	MMIO_DH(SBI_CTL_STAT, D_ALL, NULL, sbi_ctl_mmio_write);
+	MMIO_D(PIXCLK_GATE, D_ALL);
+
+	MMIO_F(_DPA_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_ALL, NULL,
+		dp_aux_ch_ctl_mmio_write);
+
+	MMIO_DH(DDI_BUF_CTL(PORT_A), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+	MMIO_DH(DDI_BUF_CTL(PORT_B), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+	MMIO_DH(DDI_BUF_CTL(PORT_C), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+	MMIO_DH(DDI_BUF_CTL(PORT_D), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+	MMIO_DH(DDI_BUF_CTL(PORT_E), D_ALL, NULL, ddi_buf_ctl_mmio_write);
+
+	MMIO_DH(DP_TP_CTL(PORT_A), D_ALL, NULL, dp_tp_ctl_mmio_write);
+	MMIO_DH(DP_TP_CTL(PORT_B), D_ALL, NULL, dp_tp_ctl_mmio_write);
+	MMIO_DH(DP_TP_CTL(PORT_C), D_ALL, NULL, dp_tp_ctl_mmio_write);
+	MMIO_DH(DP_TP_CTL(PORT_D), D_ALL, NULL, dp_tp_ctl_mmio_write);
+	MMIO_DH(DP_TP_CTL(PORT_E), D_ALL, NULL, dp_tp_ctl_mmio_write);
+
+	MMIO_DH(DP_TP_STATUS(PORT_A), D_ALL, NULL, dp_tp_status_mmio_write);
+	MMIO_DH(DP_TP_STATUS(PORT_B), D_ALL, NULL, dp_tp_status_mmio_write);
+	MMIO_DH(DP_TP_STATUS(PORT_C), D_ALL, NULL, dp_tp_status_mmio_write);
+	MMIO_DH(DP_TP_STATUS(PORT_D), D_ALL, NULL, dp_tp_status_mmio_write);
+	MMIO_DH(DP_TP_STATUS(PORT_E), D_ALL, NULL, NULL);
+
+	MMIO_F(_DDI_BUF_TRANS_A, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x64e60, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x64eC0, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x64f20, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x64f80, 0x50, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(HSW_AUD_CFG(PIPE_A), D_ALL);
+	MMIO_D(HSW_AUD_PIN_ELD_CP_VLD, D_ALL);
+
+	MMIO_DH(_TRANS_DDI_FUNC_CTL_A, D_ALL, NULL, NULL);
+	MMIO_DH(_TRANS_DDI_FUNC_CTL_B, D_ALL, NULL, NULL);
+	MMIO_DH(_TRANS_DDI_FUNC_CTL_C, D_ALL, NULL, NULL);
+	MMIO_DH(_TRANS_DDI_FUNC_CTL_EDP, D_ALL, NULL, NULL);
+
+	MMIO_D(_TRANSA_MSA_MISC, D_ALL);
+	MMIO_D(_TRANSB_MSA_MISC, D_ALL);
+	MMIO_D(_TRANSC_MSA_MISC, D_ALL);
+	MMIO_D(_TRANS_EDP_MSA_MISC, D_ALL);
+
+	MMIO_DH(FORCEWAKE, D_ALL, NULL, NULL);
+	MMIO_D(FORCEWAKE_ACK, D_ALL);
+	MMIO_D(GEN6_GT_CORE_STATUS, D_ALL);
+	MMIO_D(GEN6_GT_THREAD_STATUS_REG, D_ALL);
+	MMIO_D(GTFIFODBG, D_ALL);
+	MMIO_D(GTFIFOCTL, D_ALL);
+	MMIO_DH(FORCEWAKE_MT, D_PRE_SKL, NULL, mul_force_wake_write);
+	MMIO_DH(FORCEWAKE_ACK_HSW, D_HSW | D_BDW, NULL, NULL);
+	MMIO_D(ECOBUS, D_ALL);
+	MMIO_DH(GEN6_RC_CONTROL, D_ALL, NULL, NULL);
+	MMIO_DH(GEN6_RC_STATE, D_ALL, NULL, NULL);
+	MMIO_D(GEN6_RPNSWREQ, D_ALL);
+	MMIO_D(GEN6_RC_VIDEO_FREQ, D_ALL);
+	MMIO_D(GEN6_RP_DOWN_TIMEOUT, D_ALL);
+	MMIO_D(GEN6_RP_INTERRUPT_LIMITS, D_ALL);
+	MMIO_D(GEN6_RPSTAT1, D_ALL);
+	MMIO_D(GEN6_RP_CONTROL, D_ALL);
+	MMIO_D(GEN6_RP_UP_THRESHOLD, D_ALL);
+	MMIO_D(GEN6_RP_DOWN_THRESHOLD, D_ALL);
+	MMIO_D(GEN6_RP_CUR_UP_EI, D_ALL);
+	MMIO_D(GEN6_RP_CUR_UP, D_ALL);
+	MMIO_D(GEN6_RP_PREV_UP, D_ALL);
+	MMIO_D(GEN6_RP_CUR_DOWN_EI, D_ALL);
+	MMIO_D(GEN6_RP_CUR_DOWN, D_ALL);
+	MMIO_D(GEN6_RP_PREV_DOWN, D_ALL);
+	MMIO_D(GEN6_RP_UP_EI, D_ALL);
+	MMIO_D(GEN6_RP_DOWN_EI, D_ALL);
+	MMIO_D(GEN6_RP_IDLE_HYSTERSIS, D_ALL);
+	MMIO_D(GEN6_RC1_WAKE_RATE_LIMIT, D_ALL);
+	MMIO_D(GEN6_RC6_WAKE_RATE_LIMIT, D_ALL);
+	MMIO_D(GEN6_RC6pp_WAKE_RATE_LIMIT, D_ALL);
+	MMIO_D(GEN6_RC_EVALUATION_INTERVAL, D_ALL);
+	MMIO_D(GEN6_RC_IDLE_HYSTERSIS, D_ALL);
+	MMIO_D(GEN6_RC_SLEEP, D_ALL);
+	MMIO_D(GEN6_RC1e_THRESHOLD, D_ALL);
+	MMIO_D(GEN6_RC6_THRESHOLD, D_ALL);
+	MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL);
+	MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL);
+	MMIO_D(GEN6_PMINTRMSK, D_ALL);
+	MMIO_DH(HSW_PWR_WELL_BIOS, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+	MMIO_DH(HSW_PWR_WELL_DRIVER, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+	MMIO_DH(HSW_PWR_WELL_KVMR, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+	MMIO_DH(HSW_PWR_WELL_DEBUG, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+	MMIO_DH(HSW_PWR_WELL_CTL5, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+	MMIO_DH(HSW_PWR_WELL_CTL6, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write);
+
+	MMIO_D(RSTDBYCTL, D_ALL);
+
+	MMIO_DH(GEN6_GDRST, D_ALL, NULL, gdrst_mmio_write);
+	MMIO_F(FENCE_REG_GEN6_LO(0), 0x80, 0, 0, 0, D_ALL, fence_mmio_read, fence_mmio_write);
+	MMIO_F(VGT_PVINFO_PAGE, VGT_PVINFO_SIZE, F_UNALIGN, 0, 0, D_ALL, pvinfo_mmio_read, pvinfo_mmio_write);
+	MMIO_DH(CPU_VGACNTRL, D_ALL, NULL, vga_control_mmio_write);
+
+	MMIO_F(MCHBAR_MIRROR_BASE_SNB, 0x40000, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(TILECTL, D_ALL);
+
+	MMIO_D(GEN6_UCGCTL1, D_ALL);
+	MMIO_D(GEN6_UCGCTL2, D_ALL);
+
+	MMIO_F(0x4f000, 0x90, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_D(GEN6_PCODE_MAILBOX, D_PRE_SKL);
+	MMIO_D(GEN6_PCODE_DATA, D_ALL);
+	MMIO_D(0x13812c, D_ALL);
+	MMIO_DH(GEN7_ERR_INT, D_ALL, NULL, NULL);
+	MMIO_D(HSW_EDRAM_CAP, D_ALL);
+	MMIO_D(HSW_IDICR, D_ALL);
+	MMIO_DH(GFX_FLSH_CNTL_GEN6, D_ALL, NULL, NULL);
+
+	MMIO_D(0x3c, D_ALL);
+	MMIO_D(0x860, D_ALL);
+	MMIO_D(ECOSKPD, D_ALL);
+	MMIO_D(0x121d0, D_ALL);
+	MMIO_D(GEN6_BLITTER_ECOSKPD, D_ALL);
+	MMIO_D(0x41d0, D_ALL);
+	MMIO_D(GAC_ECO_BITS, D_ALL);
+	MMIO_D(0x6200, D_ALL);
+	MMIO_D(0x6204, D_ALL);
+	MMIO_D(0x6208, D_ALL);
+	MMIO_D(0x7118, D_ALL);
+	MMIO_D(0x7180, D_ALL);
+	MMIO_D(0x7408, D_ALL);
+	MMIO_D(0x7c00, D_ALL);
+	MMIO_D(GEN6_MBCTL, D_ALL);
+	MMIO_D(0x911c, D_ALL);
+	MMIO_D(0x9120, D_ALL);
+	MMIO_DFH(GEN7_UCGCTL4, D_ALL, F_CMD_ACCESS, NULL, NULL);
+
+	MMIO_D(GAB_CTL, D_ALL);
+	MMIO_D(0x48800, D_ALL);
+	MMIO_D(0xce044, D_ALL);
+	MMIO_D(0xe6500, D_ALL);
+	MMIO_D(0xe6504, D_ALL);
+	MMIO_D(0xe6600, D_ALL);
+	MMIO_D(0xe6604, D_ALL);
+	MMIO_D(0xe6700, D_ALL);
+	MMIO_D(0xe6704, D_ALL);
+	MMIO_D(0xe6800, D_ALL);
+	MMIO_D(0xe6804, D_ALL);
+	MMIO_D(PCH_GMBUS4, D_ALL);
+	MMIO_D(PCH_GMBUS5, D_ALL);
+
+	MMIO_D(0x902c, D_ALL);
+	MMIO_D(0xec008, D_ALL);
+	MMIO_D(0xec00c, D_ALL);
+	MMIO_D(0xec008 + 0x18, D_ALL);
+	MMIO_D(0xec00c + 0x18, D_ALL);
+	MMIO_D(0xec008 + 0x18 * 2, D_ALL);
+	MMIO_D(0xec00c + 0x18 * 2, D_ALL);
+	MMIO_D(0xec008 + 0x18 * 3, D_ALL);
+	MMIO_D(0xec00c + 0x18 * 3, D_ALL);
+	MMIO_D(0xec408, D_ALL);
+	MMIO_D(0xec40c, D_ALL);
+	MMIO_D(0xec408 + 0x18, D_ALL);
+	MMIO_D(0xec40c + 0x18, D_ALL);
+	MMIO_D(0xec408 + 0x18 * 2, D_ALL);
+	MMIO_D(0xec40c + 0x18 * 2, D_ALL);
+	MMIO_D(0xec408 + 0x18 * 3, D_ALL);
+	MMIO_D(0xec40c + 0x18 * 3, D_ALL);
+	MMIO_D(0xfc810, D_ALL);
+	MMIO_D(0xfc81c, D_ALL);
+	MMIO_D(0xfc828, D_ALL);
+	MMIO_D(0xfc834, D_ALL);
+	MMIO_D(0xfcc00, D_ALL);
+	MMIO_D(0xfcc0c, D_ALL);
+	MMIO_D(0xfcc18, D_ALL);
+	MMIO_D(0xfcc24, D_ALL);
+	MMIO_D(0xfd000, D_ALL);
+	MMIO_D(0xfd00c, D_ALL);
+	MMIO_D(0xfd018, D_ALL);
+	MMIO_D(0xfd024, D_ALL);
+	MMIO_D(0xfd034, D_ALL);
+
+	MMIO_DH(FPGA_DBG, D_ALL, NULL, fpga_dbg_mmio_write);
+	MMIO_D(0x2054, D_ALL);
+	MMIO_D(0x12054, D_ALL);
+	MMIO_D(0x22054, D_ALL);
+	MMIO_D(0x1a054, D_ALL);
+
+	MMIO_D(0x44070, D_ALL);
+
+	MMIO_D(0x215c, D_HSW_PLUS);
+	MMIO_DFH(0x2178, D_ALL, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x217c, D_ALL, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x12178, D_ALL, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x1217c, D_ALL, F_CMD_ACCESS, NULL, NULL);
+
+	MMIO_F(0x2290, 8, 0, 0, 0, D_HSW_PLUS, NULL, NULL);
+	MMIO_D(OACONTROL, D_HSW);
+	MMIO_D(0x2b00, D_BDW_PLUS);
+	MMIO_D(0x2360, D_BDW_PLUS);
+	MMIO_F(0x5200, 32, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x5240, 32, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(0x5280, 16, 0, 0, 0, D_ALL, NULL, NULL);
+
+	MMIO_DFH(0x1c17c, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x1c178, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_D(BCS_SWCTRL, D_ALL);
+
+	MMIO_F(HS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(DS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(IA_VERTICES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(IA_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(VS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(GS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(GS_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(CL_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(CL_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(PS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_F(PS_DEPTH_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL);
+	MMIO_DH(0x4260, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+	MMIO_DH(0x4264, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+	MMIO_DH(0x4268, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+	MMIO_DH(0x426c, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+	MMIO_DH(0x4270, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler);
+	MMIO_DFH(0x4094, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+
+	return 0;
+}
+
+static int init_broadwell_mmio_info(struct intel_gvt *gvt)
+{
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	int ret;
+
+	MMIO_DH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL,
+			intel_vgpu_reg_imr_handler);
+
+	MMIO_DH(GEN8_GT_IMR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_GT_IER(0), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_GT_IIR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_GT_ISR(0), D_BDW_PLUS);
+
+	MMIO_DH(GEN8_GT_IMR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_GT_IER(1), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_GT_IIR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_GT_ISR(1), D_BDW_PLUS);
+
+	MMIO_DH(GEN8_GT_IMR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_GT_IER(2), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_GT_IIR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_GT_ISR(2), D_BDW_PLUS);
+
+	MMIO_DH(GEN8_GT_IMR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_GT_IER(3), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_GT_IIR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_GT_ISR(3), D_BDW_PLUS);
+
+	MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_A), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_DE_PIPE_IER(PIPE_A), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_A), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_DE_PIPE_ISR(PIPE_A), D_BDW_PLUS);
+
+	MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_B), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_DE_PIPE_IER(PIPE_B), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_B), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_DE_PIPE_ISR(PIPE_B), D_BDW_PLUS);
+
+	MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_C), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_DE_PIPE_IER(PIPE_C), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_C), D_BDW_PLUS, NULL,
+		intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_DE_PIPE_ISR(PIPE_C), D_BDW_PLUS);
+
+	MMIO_DH(GEN8_DE_PORT_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_DE_PORT_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_DE_PORT_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_DE_PORT_ISR, D_BDW_PLUS);
+
+	MMIO_DH(GEN8_DE_MISC_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_DE_MISC_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_DE_MISC_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_DE_MISC_ISR, D_BDW_PLUS);
+
+	MMIO_DH(GEN8_PCU_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
+	MMIO_DH(GEN8_PCU_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
+	MMIO_DH(GEN8_PCU_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
+	MMIO_D(GEN8_PCU_ISR, D_BDW_PLUS);
+
+	MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL,
+		intel_vgpu_reg_master_irq_handler);
+
+	MMIO_D(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+	MMIO_D(0x1c134, D_BDW_PLUS);
+
+	MMIO_D(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+	MMIO_D(RING_HEAD(GEN8_BSD2_RING_BASE),  D_BDW_PLUS);
+	MMIO_GM(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL);
+	MMIO_D(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+	MMIO_D(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+	MMIO_D(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+	MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, ring_mode_mmio_write);
+	MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK,
+			NULL, NULL);
+	MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK,
+			NULL, NULL);
+	MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS,
+			ring_timestamp_mmio_read, NULL);
+
+	MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS);
+
+#define RING_REG(base) (base + 0xd0)
+	MMIO_RING_F(RING_REG, 4, F_RO, 0,
+		~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL,
+		ring_reset_ctl_write);
+	MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0,
+		~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL,
+		ring_reset_ctl_write);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x230)
+	MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, elsp_mmio_write);
+	MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, elsp_mmio_write);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x234)
+	MMIO_RING_F(RING_REG, 8, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL);
+	MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0, ~0LL, D_BDW_PLUS, NULL, NULL);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x244)
+	MMIO_RING_D(RING_REG, D_BDW_PLUS);
+	MMIO_D(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x370)
+	MMIO_RING_F(RING_REG, 48, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL);
+	MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 48, F_RO, 0, ~0, D_BDW_PLUS,
+			NULL, NULL);
+#undef RING_REG
+
+#define RING_REG(base) (base + 0x3a0)
+	MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
+	MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
+#undef RING_REG
+
+	MMIO_D(PIPEMISC(PIPE_A), D_BDW_PLUS);
+	MMIO_D(PIPEMISC(PIPE_B), D_BDW_PLUS);
+	MMIO_D(PIPEMISC(PIPE_C), D_BDW_PLUS);
+	MMIO_D(0x1c1d0, D_BDW_PLUS);
+	MMIO_D(GEN6_MBCUNIT_SNPCR, D_BDW_PLUS);
+	MMIO_D(GEN7_MISCCPCTL, D_BDW_PLUS);
+	MMIO_D(0x1c054, D_BDW_PLUS);
+
+	MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS);
+	MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS);
+
+	MMIO_D(GAMTARBMODE, D_BDW_PLUS);
+
+#define RING_REG(base) (base + 0x270)
+	MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);
+	MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);
+#undef RING_REG
+
+	MMIO_RING_GM(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL);
+	MMIO_GM(0x1c080, D_BDW_PLUS, NULL, NULL);
+
+	MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+
+	MMIO_D(CHICKEN_PIPESL_1(PIPE_A), D_BDW);
+	MMIO_D(CHICKEN_PIPESL_1(PIPE_B), D_BDW);
+	MMIO_D(CHICKEN_PIPESL_1(PIPE_C), D_BDW);
+
+	MMIO_D(WM_MISC, D_BDW);
+	MMIO_D(BDW_EDP_PSR_BASE, D_BDW);
+
+	MMIO_D(0x66c00, D_BDW_PLUS);
+	MMIO_D(0x66c04, D_BDW_PLUS);
+
+	MMIO_D(HSW_GTT_CACHE_EN, D_BDW_PLUS);
+
+	MMIO_D(GEN8_EU_DISABLE0, D_BDW_PLUS);
+	MMIO_D(GEN8_EU_DISABLE1, D_BDW_PLUS);
+	MMIO_D(GEN8_EU_DISABLE2, D_BDW_PLUS);
+
+	MMIO_D(0xfdc, D_BDW);
+	MMIO_DFH(GEN8_ROW_CHICKEN, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_D(GEN7_ROW_CHICKEN2, D_BDW_PLUS);
+	MMIO_D(GEN8_UCGCTL6, D_BDW_PLUS);
+
+	MMIO_D(0xb1f0, D_BDW);
+	MMIO_D(0xb1c0, D_BDW);
+	MMIO_DFH(GEN8_L3SQCREG4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_D(0xb100, D_BDW);
+	MMIO_D(0xb10c, D_BDW);
+	MMIO_D(0xb110, D_BDW);
+
+	MMIO_DFH(0x24d0, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x24d4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x24d8, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x24dc, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+
+	MMIO_D(0x83a4, D_BDW);
+	MMIO_D(GEN8_L3_LRA_1_GPGPU, D_BDW_PLUS);
+
+	MMIO_D(0x8430, D_BDW);
+
+	MMIO_D(0x110000, D_BDW_PLUS);
+
+	MMIO_D(0x48400, D_BDW_PLUS);
+
+	MMIO_D(0x6e570, D_BDW_PLUS);
+	MMIO_D(0x65f10, D_BDW_PLUS);
+
+	MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(HALF_SLICE_CHICKEN2, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
+
+	MMIO_D(0x2248, D_BDW);
+
+	return 0;
+}
+
+static int init_skl_mmio_info(struct intel_gvt *gvt)
+{
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	int ret;
+
+	MMIO_DH(FORCEWAKE_RENDER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write);
+	MMIO_DH(FORCEWAKE_ACK_RENDER_GEN9, D_SKL_PLUS, NULL, NULL);
+	MMIO_DH(FORCEWAKE_BLITTER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write);
+	MMIO_DH(FORCEWAKE_ACK_BLITTER_GEN9, D_SKL_PLUS, NULL, NULL);
+	MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write);
+	MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL);
+
+	MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
+	MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
+	MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write);
+
+	MMIO_D(HSW_PWR_WELL_BIOS, D_SKL);
+	MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, skl_power_well_ctl_write);
+
+	MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL, NULL, mailbox_write);
+	MMIO_D(0xa210, D_SKL_PLUS);
+	MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS);
+	MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS);
+	MMIO_DFH(GEN9_GAMT_ECO_REG_RW_IA, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DH(0x4ddc, D_SKL, NULL, skl_misc_ctl_write);
+	MMIO_DH(0x42080, D_SKL, NULL, skl_misc_ctl_write);
+	MMIO_D(0x45504, D_SKL);
+	MMIO_D(0x45520, D_SKL);
+	MMIO_D(0x46000, D_SKL);
+	MMIO_DH(0x46010, D_SKL, NULL, skl_lcpll_write);
+	MMIO_DH(0x46014, D_SKL, NULL, skl_lcpll_write);
+	MMIO_D(0x6C040, D_SKL);
+	MMIO_D(0x6C048, D_SKL);
+	MMIO_D(0x6C050, D_SKL);
+	MMIO_D(0x6C044, D_SKL);
+	MMIO_D(0x6C04C, D_SKL);
+	MMIO_D(0x6C054, D_SKL);
+	MMIO_D(0x6c058, D_SKL);
+	MMIO_D(0x6c05c, D_SKL);
+	MMIO_DH(0X6c060, D_SKL, dpll_status_read, NULL);
+
+	MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, pf_write);
+
+	MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, pf_write);
+
+	MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, pf_write);
+	MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, pf_write);
+
+	MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL);
+
+	MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL, NULL, NULL);
+	MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL, NULL, NULL);
+	MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL, NULL, NULL);
+
+	MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+	MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+	MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+	MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL, NULL, NULL);
+
+	MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL, NULL, NULL);
+	MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL, NULL, NULL);
+	MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL);
+
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL);
+	MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL);
+
+	MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL, NULL, NULL);
+
+	MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL, NULL, NULL);
+
+	MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL, NULL, NULL);
+
+	MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL, NULL, NULL);
+
+	MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL, NULL, NULL);
+
+	MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL, NULL, NULL);
+	MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL, NULL, NULL);
+
+	MMIO_D(0x70380, D_SKL);
+	MMIO_D(0x71380, D_SKL);
+	MMIO_D(0x72380, D_SKL);
+	MMIO_D(0x7039c, D_SKL);
+
+	MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL, NULL, NULL);
+	MMIO_D(0x8f074, D_SKL);
+	MMIO_D(0x8f004, D_SKL);
+	MMIO_D(0x8f034, D_SKL);
+
+	MMIO_D(0xb11c, D_SKL);
+
+	MMIO_D(0x51000, D_SKL);
+	MMIO_D(0x6c00c, D_SKL);
+
+	MMIO_F(0xc800, 0x7f8, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL);
+	MMIO_F(0xb020, 0x80, F_CMD_ACCESS, 0, 0, D_SKL, NULL, NULL);
+
+	MMIO_D(0xd08, D_SKL);
+	MMIO_D(0x20e0, D_SKL);
+	MMIO_D(0x20ec, D_SKL);
+
+	/* TRTT */
+	MMIO_D(0x4de0, D_SKL);
+	MMIO_D(0x4de4, D_SKL);
+	MMIO_D(0x4de8, D_SKL);
+	MMIO_D(0x4dec, D_SKL);
+	MMIO_D(0x4df0, D_SKL);
+	MMIO_DH(0x4df4, D_SKL, NULL, gen9_trtte_write);
+	MMIO_DH(0x4dfc, D_SKL, NULL, gen9_trtt_chicken_write);
+
+	MMIO_D(0x45008, D_SKL);
+
+	MMIO_D(0x46430, D_SKL);
+
+	MMIO_D(0x46520, D_SKL);
+
+	MMIO_D(0xc403c, D_SKL);
+	MMIO_D(0xb004, D_SKL);
+	MMIO_DH(DMA_CTRL, D_SKL_PLUS, NULL, dma_ctrl_write);
+
+	MMIO_D(0x65900, D_SKL);
+	MMIO_D(0x1082c0, D_SKL);
+	MMIO_D(0x4068, D_SKL);
+	MMIO_D(0x67054, D_SKL);
+	MMIO_D(0x6e560, D_SKL);
+	MMIO_D(0x6e554, D_SKL);
+	MMIO_D(0x2b20, D_SKL);
+	MMIO_D(0x65f00, D_SKL);
+	MMIO_D(0x65f08, D_SKL);
+	MMIO_D(0x320f0, D_SKL);
+
+	MMIO_D(_REG_VCS2_EXCC, D_SKL);
+	MMIO_D(0x70034, D_SKL);
+	MMIO_D(0x71034, D_SKL);
+	MMIO_D(0x72034, D_SKL);
+
+	MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL);
+	MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL);
+	MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL);
+	MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL);
+	MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL);
+	MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL);
+
+	MMIO_D(0x44500, D_SKL);
+	return 0;
+}
+
+/**
+ * intel_gvt_find_mmio_info - find MMIO information entry by aligned offset
+ * @gvt: GVT device
+ * @offset: register offset
+ *
+ * This function is used to find the MMIO information entry from hash table
+ *
+ * Returns:
+ * pointer to MMIO information entry, NULL if not exists
+ */
+struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
+	unsigned int offset)
+{
+	struct intel_gvt_mmio_info *e;
+
+	WARN_ON(!IS_ALIGNED(offset, 4));
+
+	hash_for_each_possible(gvt->mmio.mmio_info_table, e, node, offset) {
+		if (e->offset == offset)
+			return e;
+	}
+	return NULL;
+}
+
+/**
+ * intel_gvt_clean_mmio_info - clean up MMIO information table for GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the driver unloading stage, to clean up the MMIO
+ * information table of GVT device
+ *
+ */
+void intel_gvt_clean_mmio_info(struct intel_gvt *gvt)
+{
+	struct hlist_node *tmp;
+	struct intel_gvt_mmio_info *e;
+	int i;
+
+	hash_for_each_safe(gvt->mmio.mmio_info_table, i, tmp, e, node)
+		kfree(e);
+
+	vfree(gvt->mmio.mmio_attribute);
+	gvt->mmio.mmio_attribute = NULL;
+}
+
+/**
+ * intel_gvt_setup_mmio_info - setup MMIO information table for GVT device
+ * @gvt: GVT device
+ *
+ * This function is called at the initialization stage, to setup the MMIO
+ * information table for GVT device
+ *
+ * Returns:
+ * zero on success, negative if failed.
+ */
+int intel_gvt_setup_mmio_info(struct intel_gvt *gvt)
+{
+	struct intel_gvt_device_info *info = &gvt->device_info;
+	struct drm_i915_private *dev_priv = gvt->dev_priv;
+	int ret;
+
+	gvt->mmio.mmio_attribute = vzalloc(info->mmio_size);
+	if (!gvt->mmio.mmio_attribute)
+		return -ENOMEM;
+
+	ret = init_generic_mmio_info(gvt);
+	if (ret)
+		goto err;
+
+	if (IS_BROADWELL(dev_priv)) {
+		ret = init_broadwell_mmio_info(gvt);
+		if (ret)
+			goto err;
+	} else if (IS_SKYLAKE(dev_priv)) {
+		ret = init_broadwell_mmio_info(gvt);
+		if (ret)
+			goto err;
+		ret = init_skl_mmio_info(gvt);
+		if (ret)
+			goto err;
+	}
+	return 0;
+err:
+	intel_gvt_clean_mmio_info(gvt);
+	return ret;
+}
+
+/**
+ * intel_gvt_mmio_set_accessed - mark a MMIO has been accessed
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset)
+{
+	gvt->mmio.mmio_attribute[offset >> 2] |=
+		F_ACCESSED;
+}
+
+/**
+ * intel_gvt_mmio_is_cmd_accessed - mark a MMIO could be accessed by command
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt,
+		unsigned int offset)
+{
+	return gvt->mmio.mmio_attribute[offset >> 2] &
+		F_CMD_ACCESS;
+}
+
+/**
+ * intel_gvt_mmio_is_unalign - mark a MMIO could be accessed unaligned
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt,
+		unsigned int offset)
+{
+	return gvt->mmio.mmio_attribute[offset >> 2] &
+		F_UNALIGN;
+}
+
+/**
+ * intel_gvt_mmio_set_cmd_accessed - mark a MMIO has been accessed by command
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ */
+void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt,
+		unsigned int offset)
+{
+	gvt->mmio.mmio_attribute[offset >> 2] |=
+		F_CMD_ACCESSED;
+}
+
+/**
+ * intel_gvt_mmio_has_mode_mask - if a MMIO has a mode mask
+ * @gvt: a GVT device
+ * @offset: register offset
+ *
+ * Returns:
+ * True if a MMIO has a mode mask in its higher 16 bits, false if it isn't.
+ *
+ */
+bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset)
+{
+	return gvt->mmio.mmio_attribute[offset >> 2] &
+		F_MODE_MASK;
+}
+
+/**
+ * intel_vgpu_default_mmio_read - default MMIO read handler
+ * @vgpu: a vGPU
+ * @offset: access offset
+ * @p_data: data return buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	read_vreg(vgpu, offset, p_data, bytes);
+	return 0;
+}
+
+/**
+ * intel_t_default_mmio_write - default MMIO write handler
+ * @vgpu: a vGPU
+ * @offset: access offset
+ * @p_data: write data buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+		void *p_data, unsigned int bytes)
+{
+	write_vreg(vgpu, offset, p_data, bytes);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/hypercall.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/hypercall.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/hypercall.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/hypercall.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,15 @@
  * 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:
+ *    Eddie Dong <eddie.dong@intel.com>
+ *    Dexuan Cui
+ *    Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
  */
 
 #ifndef _GVT_HYPERCALL_H_
@@ -30,6 +39,23 @@
  */
 struct intel_gvt_mpt {
 	int (*detect_host)(void);
+	int (*host_init)(struct device *dev, void *gvt, const void *ops);
+	void (*host_exit)(struct device *dev, void *gvt);
+	int (*attach_vgpu)(void *vgpu, unsigned long *handle);
+	void (*detach_vgpu)(unsigned long handle);
+	int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
+	unsigned long (*from_virt_to_mfn)(void *p);
+	int (*set_wp_page)(unsigned long handle, u64 gfn);
+	int (*unset_wp_page)(unsigned long handle, u64 gfn);
+	int (*read_gpa)(unsigned long handle, unsigned long gpa, void *buf,
+			unsigned long len);
+	int (*write_gpa)(unsigned long handle, unsigned long gpa, void *buf,
+			 unsigned long len);
+	unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn);
+	int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,
+			      unsigned long mfn, unsigned int nr, bool map);
+	int (*set_trap_area)(unsigned long handle, u64 start, u64 end,
+			     bool map);
 };
 
 extern struct intel_gvt_mpt xengt_mpt;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/interrupt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/interrupt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/interrupt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/interrupt.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,741 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ *    Min he <min.he@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+/* common offset among interrupt control registers */
+#define regbase_to_isr(base)	(base)
+#define regbase_to_imr(base)	(base + 0x4)
+#define regbase_to_iir(base)	(base + 0x8)
+#define regbase_to_ier(base)	(base + 0xC)
+
+#define iir_to_regbase(iir)    (iir - 0x8)
+#define ier_to_regbase(ier)    (ier - 0xC)
+
+#define get_event_virt_handler(irq, e)	(irq->events[e].v_handler)
+#define get_irq_info(irq, e)		(irq->events[e].info)
+
+#define irq_to_gvt(irq) \
+	container_of(irq, struct intel_gvt, irq)
+
+static void update_upstream_irq(struct intel_vgpu *vgpu,
+		struct intel_gvt_irq_info *info);
+
+static const char * const irq_name[INTEL_GVT_EVENT_MAX] = {
+	[RCS_MI_USER_INTERRUPT] = "Render CS MI USER INTERRUPT",
+	[RCS_DEBUG] = "Render EU debug from SVG",
+	[RCS_MMIO_SYNC_FLUSH] = "Render MMIO sync flush status",
+	[RCS_CMD_STREAMER_ERR] = "Render CS error interrupt",
+	[RCS_PIPE_CONTROL] = "Render PIPE CONTROL notify",
+	[RCS_WATCHDOG_EXCEEDED] = "Render CS Watchdog counter exceeded",
+	[RCS_PAGE_DIRECTORY_FAULT] = "Render page directory faults",
+	[RCS_AS_CONTEXT_SWITCH] = "Render AS Context Switch Interrupt",
+
+	[VCS_MI_USER_INTERRUPT] = "Video CS MI USER INTERRUPT",
+	[VCS_MMIO_SYNC_FLUSH] = "Video MMIO sync flush status",
+	[VCS_CMD_STREAMER_ERR] = "Video CS error interrupt",
+	[VCS_MI_FLUSH_DW] = "Video MI FLUSH DW notify",
+	[VCS_WATCHDOG_EXCEEDED] = "Video CS Watchdog counter exceeded",
+	[VCS_PAGE_DIRECTORY_FAULT] = "Video page directory faults",
+	[VCS_AS_CONTEXT_SWITCH] = "Video AS Context Switch Interrupt",
+	[VCS2_MI_USER_INTERRUPT] = "VCS2 Video CS MI USER INTERRUPT",
+	[VCS2_MI_FLUSH_DW] = "VCS2 Video MI FLUSH DW notify",
+	[VCS2_AS_CONTEXT_SWITCH] = "VCS2 Context Switch Interrupt",
+
+	[BCS_MI_USER_INTERRUPT] = "Blitter CS MI USER INTERRUPT",
+	[BCS_MMIO_SYNC_FLUSH] = "Billter MMIO sync flush status",
+	[BCS_CMD_STREAMER_ERR] = "Blitter CS error interrupt",
+	[BCS_MI_FLUSH_DW] = "Blitter MI FLUSH DW notify",
+	[BCS_PAGE_DIRECTORY_FAULT] = "Blitter page directory faults",
+	[BCS_AS_CONTEXT_SWITCH] = "Blitter AS Context Switch Interrupt",
+
+	[VECS_MI_FLUSH_DW] = "Video Enhanced Streamer MI FLUSH DW notify",
+	[VECS_AS_CONTEXT_SWITCH] = "VECS Context Switch Interrupt",
+
+	[PIPE_A_FIFO_UNDERRUN] = "Pipe A FIFO underrun",
+	[PIPE_A_CRC_ERR] = "Pipe A CRC error",
+	[PIPE_A_CRC_DONE] = "Pipe A CRC done",
+	[PIPE_A_VSYNC] = "Pipe A vsync",
+	[PIPE_A_LINE_COMPARE] = "Pipe A line compare",
+	[PIPE_A_ODD_FIELD] = "Pipe A odd field",
+	[PIPE_A_EVEN_FIELD] = "Pipe A even field",
+	[PIPE_A_VBLANK] = "Pipe A vblank",
+	[PIPE_B_FIFO_UNDERRUN] = "Pipe B FIFO underrun",
+	[PIPE_B_CRC_ERR] = "Pipe B CRC error",
+	[PIPE_B_CRC_DONE] = "Pipe B CRC done",
+	[PIPE_B_VSYNC] = "Pipe B vsync",
+	[PIPE_B_LINE_COMPARE] = "Pipe B line compare",
+	[PIPE_B_ODD_FIELD] = "Pipe B odd field",
+	[PIPE_B_EVEN_FIELD] = "Pipe B even field",
+	[PIPE_B_VBLANK] = "Pipe B vblank",
+	[PIPE_C_VBLANK] = "Pipe C vblank",
+	[DPST_PHASE_IN] = "DPST phase in event",
+	[DPST_HISTOGRAM] = "DPST histogram event",
+	[GSE] = "GSE",
+	[DP_A_HOTPLUG] = "DP A Hotplug",
+	[AUX_CHANNEL_A] = "AUX Channel A",
+	[PERF_COUNTER] = "Performance counter",
+	[POISON] = "Poison",
+	[GTT_FAULT] = "GTT fault",
+	[PRIMARY_A_FLIP_DONE] = "Primary Plane A flip done",
+	[PRIMARY_B_FLIP_DONE] = "Primary Plane B flip done",
+	[PRIMARY_C_FLIP_DONE] = "Primary Plane C flip done",
+	[SPRITE_A_FLIP_DONE] = "Sprite Plane A flip done",
+	[SPRITE_B_FLIP_DONE] = "Sprite Plane B flip done",
+	[SPRITE_C_FLIP_DONE] = "Sprite Plane C flip done",
+
+	[PCU_THERMAL] = "PCU Thermal Event",
+	[PCU_PCODE2DRIVER_MAILBOX] = "PCU pcode2driver mailbox event",
+
+	[FDI_RX_INTERRUPTS_TRANSCODER_A] = "FDI RX Interrupts Combined A",
+	[AUDIO_CP_CHANGE_TRANSCODER_A] = "Audio CP Change Transcoder A",
+	[AUDIO_CP_REQUEST_TRANSCODER_A] = "Audio CP Request Transcoder A",
+	[FDI_RX_INTERRUPTS_TRANSCODER_B] = "FDI RX Interrupts Combined B",
+	[AUDIO_CP_CHANGE_TRANSCODER_B] = "Audio CP Change Transcoder B",
+	[AUDIO_CP_REQUEST_TRANSCODER_B] = "Audio CP Request Transcoder B",
+	[FDI_RX_INTERRUPTS_TRANSCODER_C] = "FDI RX Interrupts Combined C",
+	[AUDIO_CP_CHANGE_TRANSCODER_C] = "Audio CP Change Transcoder C",
+	[AUDIO_CP_REQUEST_TRANSCODER_C] = "Audio CP Request Transcoder C",
+	[ERR_AND_DBG] = "South Error and Debug Interupts Combined",
+	[GMBUS] = "Gmbus",
+	[SDVO_B_HOTPLUG] = "SDVO B hotplug",
+	[CRT_HOTPLUG] = "CRT Hotplug",
+	[DP_B_HOTPLUG] = "DisplayPort/HDMI/DVI B Hotplug",
+	[DP_C_HOTPLUG] = "DisplayPort/HDMI/DVI C Hotplug",
+	[DP_D_HOTPLUG] = "DisplayPort/HDMI/DVI D Hotplug",
+	[AUX_CHANNEL_B] = "AUX Channel B",
+	[AUX_CHANNEL_C] = "AUX Channel C",
+	[AUX_CHANNEL_D] = "AUX Channel D",
+	[AUDIO_POWER_STATE_CHANGE_B] = "Audio Power State change Port B",
+	[AUDIO_POWER_STATE_CHANGE_C] = "Audio Power State change Port C",
+	[AUDIO_POWER_STATE_CHANGE_D] = "Audio Power State change Port D",
+
+	[INTEL_GVT_EVENT_RESERVED] = "RESERVED EVENTS!!!",
+};
+
+static inline struct intel_gvt_irq_info *regbase_to_irq_info(
+		struct intel_gvt *gvt,
+		unsigned int reg)
+{
+	struct intel_gvt_irq *irq = &gvt->irq;
+	int i;
+
+	for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) {
+		if (i915_mmio_reg_offset(irq->info[i]->reg_base) == reg)
+			return irq->info[i];
+	}
+
+	return NULL;
+}
+
+/**
+ * intel_vgpu_reg_imr_handler - Generic IMR register emulation write handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the generic IMR register bit change
+ * behavior.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu,
+	unsigned int reg, void *p_data, unsigned int bytes)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+	u32 changed, masked, unmasked;
+	u32 imr = *(u32 *)p_data;
+
+	gvt_dbg_irq("write IMR %x with val %x\n",
+		reg, imr);
+
+	gvt_dbg_irq("old vIMR %x\n", vgpu_vreg(vgpu, reg));
+
+	/* figure out newly masked/unmasked bits */
+	changed = vgpu_vreg(vgpu, reg) ^ imr;
+	masked = (vgpu_vreg(vgpu, reg) & changed) ^ changed;
+	unmasked = masked ^ changed;
+
+	gvt_dbg_irq("changed %x, masked %x, unmasked %x\n",
+		changed, masked, unmasked);
+
+	vgpu_vreg(vgpu, reg) = imr;
+
+	ops->check_pending_irq(vgpu);
+	gvt_dbg_irq("IRQ: new vIMR %x\n", vgpu_vreg(vgpu, reg));
+	return 0;
+}
+
+/**
+ * intel_vgpu_reg_master_irq_handler - master IRQ write emulation handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the master IRQ register on gen8+.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu,
+	unsigned int reg, void *p_data, unsigned int bytes)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+	u32 changed, enabled, disabled;
+	u32 ier = *(u32 *)p_data;
+	u32 virtual_ier = vgpu_vreg(vgpu, reg);
+
+	gvt_dbg_irq("write master irq reg %x with val %x\n",
+		reg, ier);
+
+	gvt_dbg_irq("old vreg %x\n", vgpu_vreg(vgpu, reg));
+
+	/*
+	 * GEN8_MASTER_IRQ is a special irq register,
+	 * only bit 31 is allowed to be modified
+	 * and treated as an IER bit.
+	 */
+	ier &= GEN8_MASTER_IRQ_CONTROL;
+	virtual_ier &= GEN8_MASTER_IRQ_CONTROL;
+	vgpu_vreg(vgpu, reg) &= ~GEN8_MASTER_IRQ_CONTROL;
+	vgpu_vreg(vgpu, reg) |= ier;
+
+	/* figure out newly enabled/disable bits */
+	changed = virtual_ier ^ ier;
+	enabled = (virtual_ier & changed) ^ changed;
+	disabled = enabled ^ changed;
+
+	gvt_dbg_irq("changed %x, enabled %x, disabled %x\n",
+			changed, enabled, disabled);
+
+	ops->check_pending_irq(vgpu);
+	gvt_dbg_irq("new vreg %x\n", vgpu_vreg(vgpu, reg));
+	return 0;
+}
+
+/**
+ * intel_vgpu_reg_ier_handler - Generic IER write emulation handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the generic IER register behavior.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu,
+	unsigned int reg, void *p_data, unsigned int bytes)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+	struct intel_gvt_irq_info *info;
+	u32 changed, enabled, disabled;
+	u32 ier = *(u32 *)p_data;
+
+	gvt_dbg_irq("write IER %x with val %x\n",
+		reg, ier);
+
+	gvt_dbg_irq("old vIER %x\n", vgpu_vreg(vgpu, reg));
+
+	/* figure out newly enabled/disable bits */
+	changed = vgpu_vreg(vgpu, reg) ^ ier;
+	enabled = (vgpu_vreg(vgpu, reg) & changed) ^ changed;
+	disabled = enabled ^ changed;
+
+	gvt_dbg_irq("changed %x, enabled %x, disabled %x\n",
+			changed, enabled, disabled);
+	vgpu_vreg(vgpu, reg) = ier;
+
+	info = regbase_to_irq_info(gvt, ier_to_regbase(reg));
+	if (WARN_ON(!info))
+		return -EINVAL;
+
+	if (info->has_upstream_irq)
+		update_upstream_irq(vgpu, info);
+
+	ops->check_pending_irq(vgpu);
+	gvt_dbg_irq("new vIER %x\n", vgpu_vreg(vgpu, reg));
+	return 0;
+}
+
+/**
+ * intel_vgpu_reg_iir_handler - Generic IIR write emulation handler
+ * @vgpu: a vGPU
+ * @reg: register offset written by guest
+ * @p_data: register data written by guest
+ * @bytes: register data length
+ *
+ * This function is used to emulate the generic IIR register behavior.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ *
+ */
+int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg,
+	void *p_data, unsigned int bytes)
+{
+	struct intel_gvt_irq_info *info = regbase_to_irq_info(vgpu->gvt,
+		iir_to_regbase(reg));
+	u32 iir = *(u32 *)p_data;
+
+	gvt_dbg_irq("write IIR %x with val %x\n", reg, iir);
+
+	if (WARN_ON(!info))
+		return -EINVAL;
+
+	vgpu_vreg(vgpu, reg) &= ~iir;
+
+	if (info->has_upstream_irq)
+		update_upstream_irq(vgpu, info);
+	return 0;
+}
+
+static struct intel_gvt_irq_map gen8_irq_map[] = {
+	{ INTEL_GVT_IRQ_INFO_MASTER, 0, INTEL_GVT_IRQ_INFO_GT0, 0xffff },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 1, INTEL_GVT_IRQ_INFO_GT0, 0xffff0000 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 2, INTEL_GVT_IRQ_INFO_GT1, 0xffff },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 3, INTEL_GVT_IRQ_INFO_GT1, 0xffff0000 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 4, INTEL_GVT_IRQ_INFO_GT2, 0xffff },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 6, INTEL_GVT_IRQ_INFO_GT3, 0xffff },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 16, INTEL_GVT_IRQ_INFO_DE_PIPE_A, ~0 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 17, INTEL_GVT_IRQ_INFO_DE_PIPE_B, ~0 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 18, INTEL_GVT_IRQ_INFO_DE_PIPE_C, ~0 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 20, INTEL_GVT_IRQ_INFO_DE_PORT, ~0 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 22, INTEL_GVT_IRQ_INFO_DE_MISC, ~0 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 23, INTEL_GVT_IRQ_INFO_PCH, ~0 },
+	{ INTEL_GVT_IRQ_INFO_MASTER, 30, INTEL_GVT_IRQ_INFO_PCU, ~0 },
+	{ -1, -1, ~0 },
+};
+
+static void update_upstream_irq(struct intel_vgpu *vgpu,
+		struct intel_gvt_irq_info *info)
+{
+	struct intel_gvt_irq *irq = &vgpu->gvt->irq;
+	struct intel_gvt_irq_map *map = irq->irq_map;
+	struct intel_gvt_irq_info *up_irq_info = NULL;
+	u32 set_bits = 0;
+	u32 clear_bits = 0;
+	int bit;
+	u32 val = vgpu_vreg(vgpu,
+			regbase_to_iir(i915_mmio_reg_offset(info->reg_base)))
+		& vgpu_vreg(vgpu,
+			regbase_to_ier(i915_mmio_reg_offset(info->reg_base)));
+
+	if (!info->has_upstream_irq)
+		return;
+
+	for (map = irq->irq_map; map->up_irq_bit != -1; map++) {
+		if (info->group != map->down_irq_group)
+			continue;
+
+		if (!up_irq_info)
+			up_irq_info = irq->info[map->up_irq_group];
+		else
+			WARN_ON(up_irq_info != irq->info[map->up_irq_group]);
+
+		bit = map->up_irq_bit;
+
+		if (val & map->down_irq_bitmask)
+			set_bits |= (1 << bit);
+		else
+			clear_bits |= (1 << bit);
+	}
+
+	WARN_ON(!up_irq_info);
+
+	if (up_irq_info->group == INTEL_GVT_IRQ_INFO_MASTER) {
+		u32 isr = i915_mmio_reg_offset(up_irq_info->reg_base);
+
+		vgpu_vreg(vgpu, isr) &= ~clear_bits;
+		vgpu_vreg(vgpu, isr) |= set_bits;
+	} else {
+		u32 iir = regbase_to_iir(
+			i915_mmio_reg_offset(up_irq_info->reg_base));
+		u32 imr = regbase_to_imr(
+			i915_mmio_reg_offset(up_irq_info->reg_base));
+
+		vgpu_vreg(vgpu, iir) |= (set_bits & ~vgpu_vreg(vgpu, imr));
+	}
+
+	if (up_irq_info->has_upstream_irq)
+		update_upstream_irq(vgpu, up_irq_info);
+}
+
+static void init_irq_map(struct intel_gvt_irq *irq)
+{
+	struct intel_gvt_irq_map *map;
+	struct intel_gvt_irq_info *up_info, *down_info;
+	int up_bit;
+
+	for (map = irq->irq_map; map->up_irq_bit != -1; map++) {
+		up_info = irq->info[map->up_irq_group];
+		up_bit = map->up_irq_bit;
+		down_info = irq->info[map->down_irq_group];
+
+		set_bit(up_bit, up_info->downstream_irq_bitmap);
+		down_info->has_upstream_irq = true;
+
+		gvt_dbg_irq("[up] grp %d bit %d -> [down] grp %d bitmask %x\n",
+			up_info->group, up_bit,
+			down_info->group, map->down_irq_bitmask);
+	}
+}
+
+/* =======================vEvent injection===================== */
+static int inject_virtual_interrupt(struct intel_vgpu *vgpu)
+{
+	return intel_gvt_hypervisor_inject_msi(vgpu);
+}
+
+static void propagate_event(struct intel_gvt_irq *irq,
+	enum intel_gvt_event_type event, struct intel_vgpu *vgpu)
+{
+	struct intel_gvt_irq_info *info;
+	unsigned int reg_base;
+	int bit;
+
+	info = get_irq_info(irq, event);
+	if (WARN_ON(!info))
+		return;
+
+	reg_base = i915_mmio_reg_offset(info->reg_base);
+	bit = irq->events[event].bit;
+
+	if (!test_bit(bit, (void *)&vgpu_vreg(vgpu,
+					regbase_to_imr(reg_base)))) {
+		gvt_dbg_irq("set bit (%d) for (%s) for vgpu (%d)\n",
+				bit, irq_name[event], vgpu->id);
+		set_bit(bit, (void *)&vgpu_vreg(vgpu,
+					regbase_to_iir(reg_base)));
+	}
+}
+
+/* =======================vEvent Handlers===================== */
+static void handle_default_event_virt(struct intel_gvt_irq *irq,
+	enum intel_gvt_event_type event, struct intel_vgpu *vgpu)
+{
+	if (!vgpu->irq.irq_warn_once[event]) {
+		gvt_dbg_core("vgpu%d: IRQ receive event %d (%s)\n",
+			vgpu->id, event, irq_name[event]);
+		vgpu->irq.irq_warn_once[event] = true;
+	}
+	propagate_event(irq, event, vgpu);
+}
+
+/* =====================GEN specific logic======================= */
+/* GEN8 interrupt routines. */
+
+#define DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(regname, regbase) \
+static struct intel_gvt_irq_info gen8_##regname##_info = { \
+	.name = #regname"-IRQ", \
+	.reg_base = (regbase), \
+	.bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] = \
+		INTEL_GVT_EVENT_RESERVED}, \
+}
+
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt0, GEN8_GT_ISR(0));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt1, GEN8_GT_ISR(1));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt2, GEN8_GT_ISR(2));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt3, GEN8_GT_ISR(3));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_a, GEN8_DE_PIPE_ISR(PIPE_A));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_b, GEN8_DE_PIPE_ISR(PIPE_B));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_c, GEN8_DE_PIPE_ISR(PIPE_C));
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_port, GEN8_DE_PORT_ISR);
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_misc, GEN8_DE_MISC_ISR);
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(pcu, GEN8_PCU_ISR);
+DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(master, GEN8_MASTER_IRQ);
+
+static struct intel_gvt_irq_info gvt_base_pch_info = {
+	.name = "PCH-IRQ",
+	.reg_base = SDEISR,
+	.bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] =
+		INTEL_GVT_EVENT_RESERVED},
+};
+
+static void gen8_check_pending_irq(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt_irq *irq = &vgpu->gvt->irq;
+	int i;
+
+	if (!(vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ)) &
+				GEN8_MASTER_IRQ_CONTROL))
+		return;
+
+	for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) {
+		struct intel_gvt_irq_info *info = irq->info[i];
+		u32 reg_base;
+
+		if (!info->has_upstream_irq)
+			continue;
+
+		reg_base = i915_mmio_reg_offset(info->reg_base);
+		if ((vgpu_vreg(vgpu, regbase_to_iir(reg_base))
+				& vgpu_vreg(vgpu, regbase_to_ier(reg_base))))
+			update_upstream_irq(vgpu, info);
+	}
+
+	if (vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ))
+			& ~GEN8_MASTER_IRQ_CONTROL)
+		inject_virtual_interrupt(vgpu);
+}
+
+static void gen8_init_irq(
+		struct intel_gvt_irq *irq)
+{
+	struct intel_gvt *gvt = irq_to_gvt(irq);
+
+#define SET_BIT_INFO(s, b, e, i)		\
+	do {					\
+		s->events[e].bit = b;		\
+		s->events[e].info = s->info[i];	\
+		s->info[i]->bit_to_event[b] = e;\
+	} while (0)
+
+#define SET_IRQ_GROUP(s, g, i) \
+	do { \
+		s->info[g] = i; \
+		(i)->group = g; \
+		set_bit(g, s->irq_info_bitmap); \
+	} while (0)
+
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_MASTER, &gen8_master_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT0, &gen8_gt0_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT1, &gen8_gt1_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT2, &gen8_gt2_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT3, &gen8_gt3_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_A, &gen8_de_pipe_a_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_B, &gen8_de_pipe_b_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_C, &gen8_de_pipe_c_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PORT, &gen8_de_port_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_MISC, &gen8_de_misc_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCU, &gen8_pcu_info);
+	SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCH, &gvt_base_pch_info);
+
+	/* GEN8 level 2 interrupts. */
+
+	/* GEN8 interrupt GT0 events */
+	SET_BIT_INFO(irq, 0, RCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0);
+	SET_BIT_INFO(irq, 4, RCS_PIPE_CONTROL, INTEL_GVT_IRQ_INFO_GT0);
+	SET_BIT_INFO(irq, 8, RCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0);
+
+	SET_BIT_INFO(irq, 16, BCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0);
+	SET_BIT_INFO(irq, 20, BCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT0);
+	SET_BIT_INFO(irq, 24, BCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0);
+
+	/* GEN8 interrupt GT1 events */
+	SET_BIT_INFO(irq, 0, VCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT1);
+	SET_BIT_INFO(irq, 4, VCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT1);
+	SET_BIT_INFO(irq, 8, VCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT1);
+
+	if (HAS_BSD2(gvt->dev_priv)) {
+		SET_BIT_INFO(irq, 16, VCS2_MI_USER_INTERRUPT,
+			INTEL_GVT_IRQ_INFO_GT1);
+		SET_BIT_INFO(irq, 20, VCS2_MI_FLUSH_DW,
+			INTEL_GVT_IRQ_INFO_GT1);
+		SET_BIT_INFO(irq, 24, VCS2_AS_CONTEXT_SWITCH,
+			INTEL_GVT_IRQ_INFO_GT1);
+	}
+
+	/* GEN8 interrupt GT3 events */
+	SET_BIT_INFO(irq, 0, VECS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT3);
+	SET_BIT_INFO(irq, 4, VECS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT3);
+	SET_BIT_INFO(irq, 8, VECS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT3);
+
+	SET_BIT_INFO(irq, 0, PIPE_A_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+	SET_BIT_INFO(irq, 0, PIPE_B_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+	SET_BIT_INFO(irq, 0, PIPE_C_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+
+	/* GEN8 interrupt DE PORT events */
+	SET_BIT_INFO(irq, 0, AUX_CHANNEL_A, INTEL_GVT_IRQ_INFO_DE_PORT);
+	SET_BIT_INFO(irq, 3, DP_A_HOTPLUG, INTEL_GVT_IRQ_INFO_DE_PORT);
+
+	/* GEN8 interrupt DE MISC events */
+	SET_BIT_INFO(irq, 0, GSE, INTEL_GVT_IRQ_INFO_DE_MISC);
+
+	/* PCH events */
+	SET_BIT_INFO(irq, 17, GMBUS, INTEL_GVT_IRQ_INFO_PCH);
+	SET_BIT_INFO(irq, 19, CRT_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+	SET_BIT_INFO(irq, 21, DP_B_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+	SET_BIT_INFO(irq, 22, DP_C_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+	SET_BIT_INFO(irq, 23, DP_D_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH);
+
+	if (IS_BROADWELL(gvt->dev_priv)) {
+		SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_PCH);
+		SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_PCH);
+		SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_PCH);
+
+		SET_BIT_INFO(irq, 4, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+		SET_BIT_INFO(irq, 5, SPRITE_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+
+		SET_BIT_INFO(irq, 4, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+		SET_BIT_INFO(irq, 5, SPRITE_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+
+		SET_BIT_INFO(irq, 4, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+		SET_BIT_INFO(irq, 5, SPRITE_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+	} else if (IS_SKYLAKE(gvt->dev_priv)) {
+		SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_DE_PORT);
+		SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_DE_PORT);
+		SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_DE_PORT);
+
+		SET_BIT_INFO(irq, 3, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A);
+		SET_BIT_INFO(irq, 3, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B);
+		SET_BIT_INFO(irq, 3, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C);
+	}
+
+	/* GEN8 interrupt PCU events */
+	SET_BIT_INFO(irq, 24, PCU_THERMAL, INTEL_GVT_IRQ_INFO_PCU);
+	SET_BIT_INFO(irq, 25, PCU_PCODE2DRIVER_MAILBOX, INTEL_GVT_IRQ_INFO_PCU);
+}
+
+static struct intel_gvt_irq_ops gen8_irq_ops = {
+	.init_irq = gen8_init_irq,
+	.check_pending_irq = gen8_check_pending_irq,
+};
+
+/**
+ * intel_vgpu_trigger_virtual_event - Trigger a virtual event for a vGPU
+ * @vgpu: a vGPU
+ * @event: interrupt event
+ *
+ * This function is used to trigger a virtual interrupt event for vGPU.
+ * The caller provides the event to be triggered, the framework itself
+ * will emulate the IRQ register bit change.
+ *
+ */
+void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu,
+	enum intel_gvt_event_type event)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_irq *irq = &gvt->irq;
+	gvt_event_virt_handler_t handler;
+	struct intel_gvt_irq_ops *ops = gvt->irq.ops;
+
+	handler = get_event_virt_handler(irq, event);
+	WARN_ON(!handler);
+
+	handler(irq, event, vgpu);
+
+	ops->check_pending_irq(vgpu);
+}
+
+static void init_events(
+	struct intel_gvt_irq *irq)
+{
+	int i;
+
+	for (i = 0; i < INTEL_GVT_EVENT_MAX; i++) {
+		irq->events[i].info = NULL;
+		irq->events[i].v_handler = handle_default_event_virt;
+	}
+}
+
+static enum hrtimer_restart vblank_timer_fn(struct hrtimer *data)
+{
+	struct intel_gvt_vblank_timer *vblank_timer;
+	struct intel_gvt_irq *irq;
+	struct intel_gvt *gvt;
+
+	vblank_timer = container_of(data, struct intel_gvt_vblank_timer, timer);
+	irq = container_of(vblank_timer, struct intel_gvt_irq, vblank_timer);
+	gvt = container_of(irq, struct intel_gvt, irq);
+
+	intel_gvt_request_service(gvt, INTEL_GVT_REQUEST_EMULATE_VBLANK);
+	hrtimer_add_expires_ns(&vblank_timer->timer, vblank_timer->period);
+	return HRTIMER_RESTART;
+}
+
+/**
+ * intel_gvt_clean_irq - clean up GVT-g IRQ emulation subsystem
+ * @gvt: a GVT device
+ *
+ * This function is called at driver unloading stage, to clean up GVT-g IRQ
+ * emulation subsystem.
+ *
+ */
+void intel_gvt_clean_irq(struct intel_gvt *gvt)
+{
+	struct intel_gvt_irq *irq = &gvt->irq;
+
+	hrtimer_cancel(&irq->vblank_timer.timer);
+}
+
+#define VBLNAK_TIMER_PERIOD 16000000
+
+/**
+ * intel_gvt_init_irq - initialize GVT-g IRQ emulation subsystem
+ * @gvt: a GVT device
+ *
+ * This function is called at driver loading stage, to initialize the GVT-g IRQ
+ * emulation subsystem.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_gvt_init_irq(struct intel_gvt *gvt)
+{
+	struct intel_gvt_irq *irq = &gvt->irq;
+	struct intel_gvt_vblank_timer *vblank_timer = &irq->vblank_timer;
+
+	gvt_dbg_core("init irq framework\n");
+
+	if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) {
+		irq->ops = &gen8_irq_ops;
+		irq->irq_map = gen8_irq_map;
+	} else {
+		WARN_ON(1);
+		return -ENODEV;
+	}
+
+	/* common event initialization */
+	init_events(irq);
+
+	/* gen specific initialization */
+	irq->ops->init_irq(irq);
+
+	init_irq_map(irq);
+
+	hrtimer_init(&vblank_timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+	vblank_timer->timer.function = vblank_timer_fn;
+	vblank_timer->period = VBLNAK_TIMER_PERIOD;
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/interrupt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/interrupt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/interrupt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/interrupt.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,233 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ *    Min he <min.he@intel.com>
+ *
+ */
+
+#ifndef _GVT_INTERRUPT_H_
+#define _GVT_INTERRUPT_H_
+
+enum intel_gvt_event_type {
+	RCS_MI_USER_INTERRUPT = 0,
+	RCS_DEBUG,
+	RCS_MMIO_SYNC_FLUSH,
+	RCS_CMD_STREAMER_ERR,
+	RCS_PIPE_CONTROL,
+	RCS_L3_PARITY_ERR,
+	RCS_WATCHDOG_EXCEEDED,
+	RCS_PAGE_DIRECTORY_FAULT,
+	RCS_AS_CONTEXT_SWITCH,
+	RCS_MONITOR_BUFF_HALF_FULL,
+
+	VCS_MI_USER_INTERRUPT,
+	VCS_MMIO_SYNC_FLUSH,
+	VCS_CMD_STREAMER_ERR,
+	VCS_MI_FLUSH_DW,
+	VCS_WATCHDOG_EXCEEDED,
+	VCS_PAGE_DIRECTORY_FAULT,
+	VCS_AS_CONTEXT_SWITCH,
+
+	VCS2_MI_USER_INTERRUPT,
+	VCS2_MI_FLUSH_DW,
+	VCS2_AS_CONTEXT_SWITCH,
+
+	BCS_MI_USER_INTERRUPT,
+	BCS_MMIO_SYNC_FLUSH,
+	BCS_CMD_STREAMER_ERR,
+	BCS_MI_FLUSH_DW,
+	BCS_PAGE_DIRECTORY_FAULT,
+	BCS_AS_CONTEXT_SWITCH,
+
+	VECS_MI_USER_INTERRUPT,
+	VECS_MI_FLUSH_DW,
+	VECS_AS_CONTEXT_SWITCH,
+
+	PIPE_A_FIFO_UNDERRUN,
+	PIPE_B_FIFO_UNDERRUN,
+	PIPE_A_CRC_ERR,
+	PIPE_B_CRC_ERR,
+	PIPE_A_CRC_DONE,
+	PIPE_B_CRC_DONE,
+	PIPE_A_ODD_FIELD,
+	PIPE_B_ODD_FIELD,
+	PIPE_A_EVEN_FIELD,
+	PIPE_B_EVEN_FIELD,
+	PIPE_A_LINE_COMPARE,
+	PIPE_B_LINE_COMPARE,
+	PIPE_C_LINE_COMPARE,
+	PIPE_A_VBLANK,
+	PIPE_B_VBLANK,
+	PIPE_C_VBLANK,
+	PIPE_A_VSYNC,
+	PIPE_B_VSYNC,
+	PIPE_C_VSYNC,
+	PRIMARY_A_FLIP_DONE,
+	PRIMARY_B_FLIP_DONE,
+	PRIMARY_C_FLIP_DONE,
+	SPRITE_A_FLIP_DONE,
+	SPRITE_B_FLIP_DONE,
+	SPRITE_C_FLIP_DONE,
+
+	PCU_THERMAL,
+	PCU_PCODE2DRIVER_MAILBOX,
+
+	DPST_PHASE_IN,
+	DPST_HISTOGRAM,
+	GSE,
+	DP_A_HOTPLUG,
+	AUX_CHANNEL_A,
+	PERF_COUNTER,
+	POISON,
+	GTT_FAULT,
+	ERROR_INTERRUPT_COMBINED,
+
+	FDI_RX_INTERRUPTS_TRANSCODER_A,
+	AUDIO_CP_CHANGE_TRANSCODER_A,
+	AUDIO_CP_REQUEST_TRANSCODER_A,
+	FDI_RX_INTERRUPTS_TRANSCODER_B,
+	AUDIO_CP_CHANGE_TRANSCODER_B,
+	AUDIO_CP_REQUEST_TRANSCODER_B,
+	FDI_RX_INTERRUPTS_TRANSCODER_C,
+	AUDIO_CP_CHANGE_TRANSCODER_C,
+	AUDIO_CP_REQUEST_TRANSCODER_C,
+	ERR_AND_DBG,
+	GMBUS,
+	SDVO_B_HOTPLUG,
+	CRT_HOTPLUG,
+	DP_B_HOTPLUG,
+	DP_C_HOTPLUG,
+	DP_D_HOTPLUG,
+	AUX_CHANNEL_B,
+	AUX_CHANNEL_C,
+	AUX_CHANNEL_D,
+	AUDIO_POWER_STATE_CHANGE_B,
+	AUDIO_POWER_STATE_CHANGE_C,
+	AUDIO_POWER_STATE_CHANGE_D,
+
+	INTEL_GVT_EVENT_RESERVED,
+	INTEL_GVT_EVENT_MAX,
+};
+
+struct intel_gvt_irq;
+struct intel_gvt;
+
+typedef void (*gvt_event_virt_handler_t)(struct intel_gvt_irq *irq,
+	enum intel_gvt_event_type event, struct intel_vgpu *vgpu);
+
+struct intel_gvt_irq_ops {
+	void (*init_irq)(struct intel_gvt_irq *irq);
+	void (*check_pending_irq)(struct intel_vgpu *vgpu);
+};
+
+/* the list of physical interrupt control register groups */
+enum intel_gvt_irq_type {
+	INTEL_GVT_IRQ_INFO_GT,
+	INTEL_GVT_IRQ_INFO_DPY,
+	INTEL_GVT_IRQ_INFO_PCH,
+	INTEL_GVT_IRQ_INFO_PM,
+
+	INTEL_GVT_IRQ_INFO_MASTER,
+	INTEL_GVT_IRQ_INFO_GT0,
+	INTEL_GVT_IRQ_INFO_GT1,
+	INTEL_GVT_IRQ_INFO_GT2,
+	INTEL_GVT_IRQ_INFO_GT3,
+	INTEL_GVT_IRQ_INFO_DE_PIPE_A,
+	INTEL_GVT_IRQ_INFO_DE_PIPE_B,
+	INTEL_GVT_IRQ_INFO_DE_PIPE_C,
+	INTEL_GVT_IRQ_INFO_DE_PORT,
+	INTEL_GVT_IRQ_INFO_DE_MISC,
+	INTEL_GVT_IRQ_INFO_AUD,
+	INTEL_GVT_IRQ_INFO_PCU,
+
+	INTEL_GVT_IRQ_INFO_MAX,
+};
+
+#define INTEL_GVT_IRQ_BITWIDTH	32
+
+/* device specific interrupt bit definitions */
+struct intel_gvt_irq_info {
+	char *name;
+	i915_reg_t reg_base;
+	enum intel_gvt_event_type bit_to_event[INTEL_GVT_IRQ_BITWIDTH];
+	unsigned long warned;
+	int group;
+	DECLARE_BITMAP(downstream_irq_bitmap, INTEL_GVT_IRQ_BITWIDTH);
+	bool has_upstream_irq;
+};
+
+/* per-event information */
+struct intel_gvt_event_info {
+	int bit;				/* map to register bit */
+	int policy;				/* forwarding policy */
+	struct intel_gvt_irq_info *info;	/* register info */
+	gvt_event_virt_handler_t v_handler;	/* for v_event */
+};
+
+struct intel_gvt_irq_map {
+	int up_irq_group;
+	int up_irq_bit;
+	int down_irq_group;
+	u32 down_irq_bitmask;
+};
+
+struct intel_gvt_vblank_timer {
+	struct hrtimer timer;
+	u64 period;
+};
+
+/* structure containing device specific IRQ state */
+struct intel_gvt_irq {
+	struct intel_gvt_irq_ops *ops;
+	struct intel_gvt_irq_info *info[INTEL_GVT_IRQ_INFO_MAX];
+	DECLARE_BITMAP(irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX);
+	struct intel_gvt_event_info events[INTEL_GVT_EVENT_MAX];
+	DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX);
+	struct intel_gvt_irq_map *irq_map;
+	struct intel_gvt_vblank_timer vblank_timer;
+};
+
+int intel_gvt_init_irq(struct intel_gvt *gvt);
+void intel_gvt_clean_irq(struct intel_gvt *gvt);
+
+void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu,
+	enum intel_gvt_event_type event);
+
+int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg,
+	void *p_data, unsigned int bytes);
+int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu,
+	unsigned int reg, void *p_data, unsigned int bytes);
+int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu,
+	unsigned int reg, void *p_data, unsigned int bytes);
+int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu,
+	unsigned int reg, void *p_data, unsigned int bytes);
+
+int gvt_ring_id_to_pipe_control_notify_event(int ring_id);
+int gvt_ring_id_to_mi_flush_dw_event(int ring_id);
+int gvt_ring_id_to_mi_user_interrupt_event(int ring_id);
+
+#endif /* _GVT_INTERRUPT_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/kvmgt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/kvmgt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/kvmgt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/kvmgt.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1490 @@
+/*
+ * KVMGT - the implementation of Intel mediated pass-through framework for KVM
+ *
+ * Copyright(c) 2014-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Jike Song <jike.song@intel.com>
+ *    Xiaoguang Chen <xiaoguang.chen@intel.com>
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/mmu_context.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/spinlock.h>
+#include <linux/eventfd.h>
+#include <linux/uuid.h>
+#include <linux/kvm_host.h>
+#include <linux/vfio.h>
+#include <linux/mdev.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+static const struct intel_gvt_ops *intel_gvt_ops;
+
+/* helper macros copied from vfio-pci */
+#define VFIO_PCI_OFFSET_SHIFT   40
+#define VFIO_PCI_OFFSET_TO_INDEX(off)   (off >> VFIO_PCI_OFFSET_SHIFT)
+#define VFIO_PCI_INDEX_TO_OFFSET(index) ((u64)(index) << VFIO_PCI_OFFSET_SHIFT)
+#define VFIO_PCI_OFFSET_MASK    (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1)
+
+struct vfio_region {
+	u32				type;
+	u32				subtype;
+	size_t				size;
+	u32				flags;
+};
+
+struct kvmgt_pgfn {
+	gfn_t gfn;
+	struct hlist_node hnode;
+};
+
+struct kvmgt_guest_info {
+	struct kvm *kvm;
+	struct intel_vgpu *vgpu;
+	struct kvm_page_track_notifier_node track_node;
+#define NR_BKT (1 << 18)
+	struct hlist_head ptable[NR_BKT];
+#undef NR_BKT
+};
+
+struct gvt_dma {
+	struct rb_node node;
+	gfn_t gfn;
+	kvm_pfn_t pfn;
+};
+
+static inline bool handle_valid(unsigned long handle)
+{
+	return !!(handle & ~0xff);
+}
+
+static int kvmgt_guest_init(struct mdev_device *mdev);
+static void intel_vgpu_release_work(struct work_struct *work);
+static bool kvmgt_guest_exit(struct kvmgt_guest_info *info);
+
+static struct gvt_dma *__gvt_cache_find(struct intel_vgpu *vgpu, gfn_t gfn)
+{
+	struct rb_node *node = vgpu->vdev.cache.rb_node;
+	struct gvt_dma *ret = NULL;
+
+	while (node) {
+		struct gvt_dma *itr = rb_entry(node, struct gvt_dma, node);
+
+		if (gfn < itr->gfn)
+			node = node->rb_left;
+		else if (gfn > itr->gfn)
+			node = node->rb_right;
+		else {
+			ret = itr;
+			goto out;
+		}
+	}
+
+out:
+	return ret;
+}
+
+static kvm_pfn_t gvt_cache_find(struct intel_vgpu *vgpu, gfn_t gfn)
+{
+	struct gvt_dma *entry;
+	kvm_pfn_t pfn;
+
+	mutex_lock(&vgpu->vdev.cache_lock);
+
+	entry = __gvt_cache_find(vgpu, gfn);
+	pfn = (entry == NULL) ? 0 : entry->pfn;
+
+	mutex_unlock(&vgpu->vdev.cache_lock);
+	return pfn;
+}
+
+static void gvt_cache_add(struct intel_vgpu *vgpu, gfn_t gfn, kvm_pfn_t pfn)
+{
+	struct gvt_dma *new, *itr;
+	struct rb_node **link = &vgpu->vdev.cache.rb_node, *parent = NULL;
+
+	new = kzalloc(sizeof(struct gvt_dma), GFP_KERNEL);
+	if (!new)
+		return;
+
+	new->gfn = gfn;
+	new->pfn = pfn;
+
+	mutex_lock(&vgpu->vdev.cache_lock);
+	while (*link) {
+		parent = *link;
+		itr = rb_entry(parent, struct gvt_dma, node);
+
+		if (gfn == itr->gfn)
+			goto out;
+		else if (gfn < itr->gfn)
+			link = &parent->rb_left;
+		else
+			link = &parent->rb_right;
+	}
+
+	rb_link_node(&new->node, parent, link);
+	rb_insert_color(&new->node, &vgpu->vdev.cache);
+	mutex_unlock(&vgpu->vdev.cache_lock);
+	return;
+
+out:
+	mutex_unlock(&vgpu->vdev.cache_lock);
+	kfree(new);
+}
+
+static void __gvt_cache_remove_entry(struct intel_vgpu *vgpu,
+				struct gvt_dma *entry)
+{
+	rb_erase(&entry->node, &vgpu->vdev.cache);
+	kfree(entry);
+}
+
+static void gvt_cache_remove(struct intel_vgpu *vgpu, gfn_t gfn)
+{
+	struct device *dev = mdev_dev(vgpu->vdev.mdev);
+	struct gvt_dma *this;
+	unsigned long g1;
+	int rc;
+
+	mutex_lock(&vgpu->vdev.cache_lock);
+	this  = __gvt_cache_find(vgpu, gfn);
+	if (!this) {
+		mutex_unlock(&vgpu->vdev.cache_lock);
+		return;
+	}
+
+	g1 = gfn;
+	rc = vfio_unpin_pages(dev, &g1, 1);
+	WARN_ON(rc != 1);
+	__gvt_cache_remove_entry(vgpu, this);
+	mutex_unlock(&vgpu->vdev.cache_lock);
+}
+
+static void gvt_cache_init(struct intel_vgpu *vgpu)
+{
+	vgpu->vdev.cache = RB_ROOT;
+	mutex_init(&vgpu->vdev.cache_lock);
+}
+
+static void gvt_cache_destroy(struct intel_vgpu *vgpu)
+{
+	struct gvt_dma *dma;
+	struct rb_node *node = NULL;
+	struct device *dev = mdev_dev(vgpu->vdev.mdev);
+	unsigned long gfn;
+
+	mutex_lock(&vgpu->vdev.cache_lock);
+	while ((node = rb_first(&vgpu->vdev.cache))) {
+		dma = rb_entry(node, struct gvt_dma, node);
+		gfn = dma->gfn;
+
+		vfio_unpin_pages(dev, &gfn, 1);
+		__gvt_cache_remove_entry(vgpu, dma);
+	}
+	mutex_unlock(&vgpu->vdev.cache_lock);
+}
+
+static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt,
+		const char *name)
+{
+	int i;
+	struct intel_vgpu_type *t;
+	const char *driver_name = dev_driver_string(
+			&gvt->dev_priv->drm.pdev->dev);
+
+	for (i = 0; i < gvt->num_types; i++) {
+		t = &gvt->types[i];
+		if (!strncmp(t->name, name + strlen(driver_name) + 1,
+			sizeof(t->name)))
+			return t;
+	}
+
+	return NULL;
+}
+
+static ssize_t available_instances_show(struct kobject *kobj,
+					struct device *dev, char *buf)
+{
+	struct intel_vgpu_type *type;
+	unsigned int num = 0;
+	void *gvt = kdev_to_i915(dev)->gvt;
+
+	type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
+	if (!type)
+		num = 0;
+	else
+		num = type->avail_instance;
+
+	return sprintf(buf, "%u\n", num);
+}
+
+static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
+		char *buf)
+{
+	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
+}
+
+static ssize_t description_show(struct kobject *kobj, struct device *dev,
+		char *buf)
+{
+	struct intel_vgpu_type *type;
+	void *gvt = kdev_to_i915(dev)->gvt;
+
+	type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
+	if (!type)
+		return 0;
+
+	return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
+				"fence: %d\n",
+				BYTES_TO_MB(type->low_gm_size),
+				BYTES_TO_MB(type->high_gm_size),
+				type->fence);
+}
+
+static MDEV_TYPE_ATTR_RO(available_instances);
+static MDEV_TYPE_ATTR_RO(device_api);
+static MDEV_TYPE_ATTR_RO(description);
+
+static struct attribute *type_attrs[] = {
+	&mdev_type_attr_available_instances.attr,
+	&mdev_type_attr_device_api.attr,
+	&mdev_type_attr_description.attr,
+	NULL,
+};
+
+static struct attribute_group *intel_vgpu_type_groups[] = {
+	[0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
+};
+
+static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
+{
+	int i, j;
+	struct intel_vgpu_type *type;
+	struct attribute_group *group;
+
+	for (i = 0; i < gvt->num_types; i++) {
+		type = &gvt->types[i];
+
+		group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
+		if (WARN_ON(!group))
+			goto unwind;
+
+		group->name = type->name;
+		group->attrs = type_attrs;
+		intel_vgpu_type_groups[i] = group;
+	}
+
+	return true;
+
+unwind:
+	for (j = 0; j < i; j++) {
+		group = intel_vgpu_type_groups[j];
+		kfree(group);
+	}
+
+	return false;
+}
+
+static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
+{
+	int i;
+	struct attribute_group *group;
+
+	for (i = 0; i < gvt->num_types; i++) {
+		group = intel_vgpu_type_groups[i];
+		kfree(group);
+	}
+}
+
+static void kvmgt_protect_table_init(struct kvmgt_guest_info *info)
+{
+	hash_init(info->ptable);
+}
+
+static void kvmgt_protect_table_destroy(struct kvmgt_guest_info *info)
+{
+	struct kvmgt_pgfn *p;
+	struct hlist_node *tmp;
+	int i;
+
+	hash_for_each_safe(info->ptable, i, tmp, p, hnode) {
+		hash_del(&p->hnode);
+		kfree(p);
+	}
+}
+
+static struct kvmgt_pgfn *
+__kvmgt_protect_table_find(struct kvmgt_guest_info *info, gfn_t gfn)
+{
+	struct kvmgt_pgfn *p, *res = NULL;
+
+	hash_for_each_possible(info->ptable, p, hnode, gfn) {
+		if (gfn == p->gfn) {
+			res = p;
+			break;
+		}
+	}
+
+	return res;
+}
+
+static bool kvmgt_gfn_is_write_protected(struct kvmgt_guest_info *info,
+				gfn_t gfn)
+{
+	struct kvmgt_pgfn *p;
+
+	p = __kvmgt_protect_table_find(info, gfn);
+	return !!p;
+}
+
+static void kvmgt_protect_table_add(struct kvmgt_guest_info *info, gfn_t gfn)
+{
+	struct kvmgt_pgfn *p;
+
+	if (kvmgt_gfn_is_write_protected(info, gfn))
+		return;
+
+	p = kzalloc(sizeof(struct kvmgt_pgfn), GFP_ATOMIC);
+	if (WARN(!p, "gfn: 0x%llx\n", gfn))
+		return;
+
+	p->gfn = gfn;
+	hash_add(info->ptable, &p->hnode, gfn);
+}
+
+static void kvmgt_protect_table_del(struct kvmgt_guest_info *info,
+				gfn_t gfn)
+{
+	struct kvmgt_pgfn *p;
+
+	p = __kvmgt_protect_table_find(info, gfn);
+	if (p) {
+		hash_del(&p->hnode);
+		kfree(p);
+	}
+}
+
+static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
+{
+	struct intel_vgpu *vgpu;
+	struct intel_vgpu_type *type;
+	struct device *pdev;
+	void *gvt;
+	int ret;
+
+	pdev = mdev_parent_dev(mdev);
+	gvt = kdev_to_i915(pdev)->gvt;
+
+	type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
+	if (!type) {
+		gvt_err("failed to find type %s to create\n",
+						kobject_name(kobj));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	vgpu = intel_gvt_ops->vgpu_create(gvt, type);
+	if (IS_ERR_OR_NULL(vgpu)) {
+		ret = vgpu == NULL ? -EFAULT : PTR_ERR(vgpu);
+		gvt_err("failed to create intel vgpu: %d\n", ret);
+		goto out;
+	}
+
+	INIT_WORK(&vgpu->vdev.release_work, intel_vgpu_release_work);
+
+	vgpu->vdev.mdev = mdev;
+	mdev_set_drvdata(mdev, vgpu);
+
+	gvt_dbg_core("intel_vgpu_create succeeded for mdev: %s\n",
+		     dev_name(mdev_dev(mdev)));
+	ret = 0;
+
+out:
+	return ret;
+}
+
+static int intel_vgpu_remove(struct mdev_device *mdev)
+{
+	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
+
+	if (handle_valid(vgpu->handle))
+		return -EBUSY;
+
+	intel_gvt_ops->vgpu_destroy(vgpu);
+	return 0;
+}
+
+static int intel_vgpu_iommu_notifier(struct notifier_block *nb,
+				     unsigned long action, void *data)
+{
+	struct intel_vgpu *vgpu = container_of(nb,
+					struct intel_vgpu,
+					vdev.iommu_notifier);
+
+	if (action == VFIO_IOMMU_NOTIFY_DMA_UNMAP) {
+		struct vfio_iommu_type1_dma_unmap *unmap = data;
+		unsigned long gfn, end_gfn;
+
+		gfn = unmap->iova >> PAGE_SHIFT;
+		end_gfn = gfn + unmap->size / PAGE_SIZE;
+
+		while (gfn < end_gfn)
+			gvt_cache_remove(vgpu, gfn++);
+	}
+
+	return NOTIFY_OK;
+}
+
+static int intel_vgpu_group_notifier(struct notifier_block *nb,
+				     unsigned long action, void *data)
+{
+	struct intel_vgpu *vgpu = container_of(nb,
+					struct intel_vgpu,
+					vdev.group_notifier);
+
+	/* the only action we care about */
+	if (action == VFIO_GROUP_NOTIFY_SET_KVM) {
+		vgpu->vdev.kvm = data;
+
+		if (!data)
+			schedule_work(&vgpu->vdev.release_work);
+	}
+
+	return NOTIFY_OK;
+}
+
+static int intel_vgpu_open(struct mdev_device *mdev)
+{
+	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
+	unsigned long events;
+	int ret;
+
+	vgpu->vdev.iommu_notifier.notifier_call = intel_vgpu_iommu_notifier;
+	vgpu->vdev.group_notifier.notifier_call = intel_vgpu_group_notifier;
+
+	events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
+	ret = vfio_register_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY, &events,
+				&vgpu->vdev.iommu_notifier);
+	if (ret != 0) {
+		gvt_err("vfio_register_notifier for iommu failed: %d\n", ret);
+		goto out;
+	}
+
+	events = VFIO_GROUP_NOTIFY_SET_KVM;
+	ret = vfio_register_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY, &events,
+				&vgpu->vdev.group_notifier);
+	if (ret != 0) {
+		gvt_err("vfio_register_notifier for group failed: %d\n", ret);
+		goto undo_iommu;
+	}
+
+	ret = kvmgt_guest_init(mdev);
+	if (ret)
+		goto undo_group;
+
+	atomic_set(&vgpu->vdev.released, 0);
+	return ret;
+
+undo_group:
+	vfio_unregister_notifier(mdev_dev(mdev), VFIO_GROUP_NOTIFY,
+					&vgpu->vdev.group_notifier);
+
+undo_iommu:
+	vfio_unregister_notifier(mdev_dev(mdev), VFIO_IOMMU_NOTIFY,
+					&vgpu->vdev.iommu_notifier);
+out:
+	return ret;
+}
+
+static void __intel_vgpu_release(struct intel_vgpu *vgpu)
+{
+	struct kvmgt_guest_info *info;
+	int ret;
+
+	if (!handle_valid(vgpu->handle))
+		return;
+
+	if (atomic_cmpxchg(&vgpu->vdev.released, 0, 1))
+		return;
+
+	ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_IOMMU_NOTIFY,
+					&vgpu->vdev.iommu_notifier);
+	WARN(ret, "vfio_unregister_notifier for iommu failed: %d\n", ret);
+
+	ret = vfio_unregister_notifier(mdev_dev(vgpu->vdev.mdev), VFIO_GROUP_NOTIFY,
+					&vgpu->vdev.group_notifier);
+	WARN(ret, "vfio_unregister_notifier for group failed: %d\n", ret);
+
+	info = (struct kvmgt_guest_info *)vgpu->handle;
+	kvmgt_guest_exit(info);
+
+	vgpu->vdev.kvm = NULL;
+	vgpu->handle = 0;
+}
+
+static void intel_vgpu_release(struct mdev_device *mdev)
+{
+	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
+
+	__intel_vgpu_release(vgpu);
+}
+
+static void intel_vgpu_release_work(struct work_struct *work)
+{
+	struct intel_vgpu *vgpu = container_of(work, struct intel_vgpu,
+					vdev.release_work);
+
+	__intel_vgpu_release(vgpu);
+}
+
+static uint64_t intel_vgpu_get_bar0_addr(struct intel_vgpu *vgpu)
+{
+	u32 start_lo, start_hi;
+	u32 mem_type;
+	int pos = PCI_BASE_ADDRESS_0;
+
+	start_lo = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + pos)) &
+			PCI_BASE_ADDRESS_MEM_MASK;
+	mem_type = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + pos)) &
+			PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+
+	switch (mem_type) {
+	case PCI_BASE_ADDRESS_MEM_TYPE_64:
+		start_hi = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space
+						+ pos + 4));
+		break;
+	case PCI_BASE_ADDRESS_MEM_TYPE_32:
+	case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+		/* 1M mem BAR treated as 32-bit BAR */
+	default:
+		/* mem unknown type treated as 32-bit BAR */
+		start_hi = 0;
+		break;
+	}
+
+	return ((u64)start_hi << 32) | start_lo;
+}
+
+static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf,
+			size_t count, loff_t *ppos, bool is_write)
+{
+	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
+	unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos);
+	uint64_t pos = *ppos & VFIO_PCI_OFFSET_MASK;
+	int ret = -EINVAL;
+
+
+	if (index >= VFIO_PCI_NUM_REGIONS) {
+		gvt_err("invalid index: %u\n", index);
+		return -EINVAL;
+	}
+
+	switch (index) {
+	case VFIO_PCI_CONFIG_REGION_INDEX:
+		if (is_write)
+			ret = intel_gvt_ops->emulate_cfg_write(vgpu, pos,
+						buf, count);
+		else
+			ret = intel_gvt_ops->emulate_cfg_read(vgpu, pos,
+						buf, count);
+		break;
+	case VFIO_PCI_BAR0_REGION_INDEX:
+	case VFIO_PCI_BAR1_REGION_INDEX:
+		if (is_write) {
+			uint64_t bar0_start = intel_vgpu_get_bar0_addr(vgpu);
+
+			ret = intel_gvt_ops->emulate_mmio_write(vgpu,
+						bar0_start + pos, buf, count);
+		} else {
+			uint64_t bar0_start = intel_vgpu_get_bar0_addr(vgpu);
+
+			ret = intel_gvt_ops->emulate_mmio_read(vgpu,
+						bar0_start + pos, buf, count);
+		}
+		break;
+	case VFIO_PCI_BAR2_REGION_INDEX:
+	case VFIO_PCI_BAR3_REGION_INDEX:
+	case VFIO_PCI_BAR4_REGION_INDEX:
+	case VFIO_PCI_BAR5_REGION_INDEX:
+	case VFIO_PCI_VGA_REGION_INDEX:
+	case VFIO_PCI_ROM_REGION_INDEX:
+	default:
+		gvt_err("unsupported region: %u\n", index);
+	}
+
+	return ret == 0 ? count : ret;
+}
+
+static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf,
+			size_t count, loff_t *ppos)
+{
+	unsigned int done = 0;
+	int ret;
+
+	while (count) {
+		size_t filled;
+
+		if (count >= 4 && !(*ppos % 4)) {
+			u32 val;
+
+			ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val),
+					ppos, false);
+			if (ret <= 0)
+				goto read_err;
+
+			if (copy_to_user(buf, &val, sizeof(val)))
+				goto read_err;
+
+			filled = 4;
+		} else if (count >= 2 && !(*ppos % 2)) {
+			u16 val;
+
+			ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val),
+					ppos, false);
+			if (ret <= 0)
+				goto read_err;
+
+			if (copy_to_user(buf, &val, sizeof(val)))
+				goto read_err;
+
+			filled = 2;
+		} else {
+			u8 val;
+
+			ret = intel_vgpu_rw(mdev, &val, sizeof(val), ppos,
+					false);
+			if (ret <= 0)
+				goto read_err;
+
+			if (copy_to_user(buf, &val, sizeof(val)))
+				goto read_err;
+
+			filled = 1;
+		}
+
+		count -= filled;
+		done += filled;
+		*ppos += filled;
+		buf += filled;
+	}
+
+	return done;
+
+read_err:
+	return -EFAULT;
+}
+
+static ssize_t intel_vgpu_write(struct mdev_device *mdev,
+				const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	unsigned int done = 0;
+	int ret;
+
+	while (count) {
+		size_t filled;
+
+		if (count >= 4 && !(*ppos % 4)) {
+			u32 val;
+
+			if (copy_from_user(&val, buf, sizeof(val)))
+				goto write_err;
+
+			ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val),
+					ppos, true);
+			if (ret <= 0)
+				goto write_err;
+
+			filled = 4;
+		} else if (count >= 2 && !(*ppos % 2)) {
+			u16 val;
+
+			if (copy_from_user(&val, buf, sizeof(val)))
+				goto write_err;
+
+			ret = intel_vgpu_rw(mdev, (char *)&val,
+					sizeof(val), ppos, true);
+			if (ret <= 0)
+				goto write_err;
+
+			filled = 2;
+		} else {
+			u8 val;
+
+			if (copy_from_user(&val, buf, sizeof(val)))
+				goto write_err;
+
+			ret = intel_vgpu_rw(mdev, &val, sizeof(val),
+					ppos, true);
+			if (ret <= 0)
+				goto write_err;
+
+			filled = 1;
+		}
+
+		count -= filled;
+		done += filled;
+		*ppos += filled;
+		buf += filled;
+	}
+
+	return done;
+write_err:
+	return -EFAULT;
+}
+
+static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+{
+	unsigned int index;
+	u64 virtaddr;
+	unsigned long req_size, pgoff = 0;
+	pgprot_t pg_prot;
+	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
+
+	index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
+	if (index >= VFIO_PCI_ROM_REGION_INDEX)
+		return -EINVAL;
+
+	if (vma->vm_end < vma->vm_start)
+		return -EINVAL;
+	if ((vma->vm_flags & VM_SHARED) == 0)
+		return -EINVAL;
+	if (index != VFIO_PCI_BAR2_REGION_INDEX)
+		return -EINVAL;
+
+	pg_prot = vma->vm_page_prot;
+	virtaddr = vma->vm_start;
+	req_size = vma->vm_end - vma->vm_start;
+	pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+
+	return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot);
+}
+
+static int intel_vgpu_get_irq_count(struct intel_vgpu *vgpu, int type)
+{
+	if (type == VFIO_PCI_INTX_IRQ_INDEX || type == VFIO_PCI_MSI_IRQ_INDEX)
+		return 1;
+
+	return 0;
+}
+
+static int intel_vgpu_set_intx_mask(struct intel_vgpu *vgpu,
+			unsigned int index, unsigned int start,
+			unsigned int count, uint32_t flags,
+			void *data)
+{
+	return 0;
+}
+
+static int intel_vgpu_set_intx_unmask(struct intel_vgpu *vgpu,
+			unsigned int index, unsigned int start,
+			unsigned int count, uint32_t flags, void *data)
+{
+	return 0;
+}
+
+static int intel_vgpu_set_intx_trigger(struct intel_vgpu *vgpu,
+		unsigned int index, unsigned int start, unsigned int count,
+		uint32_t flags, void *data)
+{
+	return 0;
+}
+
+static int intel_vgpu_set_msi_trigger(struct intel_vgpu *vgpu,
+		unsigned int index, unsigned int start, unsigned int count,
+		uint32_t flags, void *data)
+{
+	struct eventfd_ctx *trigger;
+
+	if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+		int fd = *(int *)data;
+
+		trigger = eventfd_ctx_fdget(fd);
+		if (IS_ERR(trigger)) {
+			gvt_err("eventfd_ctx_fdget failed\n");
+			return PTR_ERR(trigger);
+		}
+		vgpu->vdev.msi_trigger = trigger;
+	}
+
+	return 0;
+}
+
+static int intel_vgpu_set_irqs(struct intel_vgpu *vgpu, uint32_t flags,
+		unsigned int index, unsigned int start, unsigned int count,
+		void *data)
+{
+	int (*func)(struct intel_vgpu *vgpu, unsigned int index,
+			unsigned int start, unsigned int count, uint32_t flags,
+			void *data) = NULL;
+
+	switch (index) {
+	case VFIO_PCI_INTX_IRQ_INDEX:
+		switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+		case VFIO_IRQ_SET_ACTION_MASK:
+			func = intel_vgpu_set_intx_mask;
+			break;
+		case VFIO_IRQ_SET_ACTION_UNMASK:
+			func = intel_vgpu_set_intx_unmask;
+			break;
+		case VFIO_IRQ_SET_ACTION_TRIGGER:
+			func = intel_vgpu_set_intx_trigger;
+			break;
+		}
+		break;
+	case VFIO_PCI_MSI_IRQ_INDEX:
+		switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+		case VFIO_IRQ_SET_ACTION_MASK:
+		case VFIO_IRQ_SET_ACTION_UNMASK:
+			/* XXX Need masking support exported */
+			break;
+		case VFIO_IRQ_SET_ACTION_TRIGGER:
+			func = intel_vgpu_set_msi_trigger;
+			break;
+		}
+		break;
+	}
+
+	if (!func)
+		return -ENOTTY;
+
+	return func(vgpu, index, start, count, flags, data);
+}
+
+static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
+	unsigned long minsz;
+
+	gvt_dbg_core("vgpu%d ioctl, cmd: %d\n", vgpu->id, cmd);
+
+	if (cmd == VFIO_DEVICE_GET_INFO) {
+		struct vfio_device_info info;
+
+		minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		info.flags = VFIO_DEVICE_FLAGS_PCI;
+		info.flags |= VFIO_DEVICE_FLAGS_RESET;
+		info.num_regions = VFIO_PCI_NUM_REGIONS;
+		info.num_irqs = VFIO_PCI_NUM_IRQS;
+
+		return copy_to_user((void __user *)arg, &info, minsz) ?
+			-EFAULT : 0;
+
+	} else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+		struct vfio_region_info info;
+		struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
+		int i, ret;
+		struct vfio_region_info_cap_sparse_mmap *sparse = NULL;
+		size_t size;
+		int nr_areas = 1;
+		int cap_type_id;
+
+		minsz = offsetofend(struct vfio_region_info, offset);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz)
+			return -EINVAL;
+
+		switch (info.index) {
+		case VFIO_PCI_CONFIG_REGION_INDEX:
+			info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+			info.size = INTEL_GVT_MAX_CFG_SPACE_SZ;
+			info.flags = VFIO_REGION_INFO_FLAG_READ |
+				     VFIO_REGION_INFO_FLAG_WRITE;
+			break;
+		case VFIO_PCI_BAR0_REGION_INDEX:
+			info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+			info.size = vgpu->cfg_space.bar[info.index].size;
+			if (!info.size) {
+				info.flags = 0;
+				break;
+			}
+
+			info.flags = VFIO_REGION_INFO_FLAG_READ |
+				     VFIO_REGION_INFO_FLAG_WRITE;
+			break;
+		case VFIO_PCI_BAR1_REGION_INDEX:
+			info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+			info.size = 0;
+			info.flags = 0;
+			break;
+		case VFIO_PCI_BAR2_REGION_INDEX:
+			info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+			info.flags = VFIO_REGION_INFO_FLAG_CAPS |
+					VFIO_REGION_INFO_FLAG_MMAP |
+					VFIO_REGION_INFO_FLAG_READ |
+					VFIO_REGION_INFO_FLAG_WRITE;
+			info.size = gvt_aperture_sz(vgpu->gvt);
+
+			size = sizeof(*sparse) +
+					(nr_areas * sizeof(*sparse->areas));
+			sparse = kzalloc(size, GFP_KERNEL);
+			if (!sparse)
+				return -ENOMEM;
+
+			sparse->nr_areas = nr_areas;
+			cap_type_id = VFIO_REGION_INFO_CAP_SPARSE_MMAP;
+			sparse->areas[0].offset =
+					PAGE_ALIGN(vgpu_aperture_offset(vgpu));
+			sparse->areas[0].size = vgpu_aperture_sz(vgpu);
+			if (!caps.buf) {
+				kfree(caps.buf);
+				caps.buf = NULL;
+				caps.size = 0;
+			}
+			break;
+
+		case VFIO_PCI_BAR3_REGION_INDEX ... VFIO_PCI_BAR5_REGION_INDEX:
+			info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index);
+			info.size = 0;
+
+			info.flags = 0;
+			gvt_dbg_core("get region info bar:%d\n", info.index);
+			break;
+
+		case VFIO_PCI_ROM_REGION_INDEX:
+		case VFIO_PCI_VGA_REGION_INDEX:
+			gvt_dbg_core("get region info index:%d\n", info.index);
+			break;
+		default:
+			{
+				struct vfio_region_info_cap_type cap_type;
+
+				if (info.index >= VFIO_PCI_NUM_REGIONS +
+						vgpu->vdev.num_regions)
+					return -EINVAL;
+
+				i = info.index - VFIO_PCI_NUM_REGIONS;
+
+				info.offset =
+					VFIO_PCI_INDEX_TO_OFFSET(info.index);
+				info.size = vgpu->vdev.region[i].size;
+				info.flags = vgpu->vdev.region[i].flags;
+
+				cap_type.type = vgpu->vdev.region[i].type;
+				cap_type.subtype = vgpu->vdev.region[i].subtype;
+
+				ret = vfio_info_add_capability(&caps,
+						VFIO_REGION_INFO_CAP_TYPE,
+						&cap_type);
+				if (ret)
+					return ret;
+			}
+		}
+
+		if ((info.flags & VFIO_REGION_INFO_FLAG_CAPS) && sparse) {
+			switch (cap_type_id) {
+			case VFIO_REGION_INFO_CAP_SPARSE_MMAP:
+				ret = vfio_info_add_capability(&caps,
+					VFIO_REGION_INFO_CAP_SPARSE_MMAP,
+					sparse);
+				kfree(sparse);
+				if (ret)
+					return ret;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+
+		if (caps.size) {
+			if (info.argsz < sizeof(info) + caps.size) {
+				info.argsz = sizeof(info) + caps.size;
+				info.cap_offset = 0;
+			} else {
+				vfio_info_cap_shift(&caps, sizeof(info));
+				if (copy_to_user((void __user *)arg +
+						  sizeof(info), caps.buf,
+						  caps.size)) {
+					kfree(caps.buf);
+					return -EFAULT;
+				}
+				info.cap_offset = sizeof(info);
+			}
+
+			kfree(caps.buf);
+		}
+
+		return copy_to_user((void __user *)arg, &info, minsz) ?
+			-EFAULT : 0;
+	} else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+		struct vfio_irq_info info;
+
+		minsz = offsetofend(struct vfio_irq_info, count);
+
+		if (copy_from_user(&info, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (info.argsz < minsz || info.index >= VFIO_PCI_NUM_IRQS)
+			return -EINVAL;
+
+		switch (info.index) {
+		case VFIO_PCI_INTX_IRQ_INDEX:
+		case VFIO_PCI_MSI_IRQ_INDEX:
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		info.flags = VFIO_IRQ_INFO_EVENTFD;
+
+		info.count = intel_vgpu_get_irq_count(vgpu, info.index);
+
+		if (info.index == VFIO_PCI_INTX_IRQ_INDEX)
+			info.flags |= (VFIO_IRQ_INFO_MASKABLE |
+				       VFIO_IRQ_INFO_AUTOMASKED);
+		else
+			info.flags |= VFIO_IRQ_INFO_NORESIZE;
+
+		return copy_to_user((void __user *)arg, &info, minsz) ?
+			-EFAULT : 0;
+	} else if (cmd == VFIO_DEVICE_SET_IRQS) {
+		struct vfio_irq_set hdr;
+		u8 *data = NULL;
+		int ret = 0;
+		size_t data_size = 0;
+
+		minsz = offsetofend(struct vfio_irq_set, count);
+
+		if (copy_from_user(&hdr, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
+			int max = intel_vgpu_get_irq_count(vgpu, hdr.index);
+
+			ret = vfio_set_irqs_validate_and_prepare(&hdr, max,
+						VFIO_PCI_NUM_IRQS, &data_size);
+			if (ret) {
+				gvt_err("intel:vfio_set_irqs_validate_and_prepare failed\n");
+				return -EINVAL;
+			}
+			if (data_size) {
+				data = memdup_user((void __user *)(arg + minsz),
+						   data_size);
+				if (IS_ERR(data))
+					return PTR_ERR(data);
+			}
+		}
+
+		ret = intel_vgpu_set_irqs(vgpu, hdr.flags, hdr.index,
+					hdr.start, hdr.count, data);
+		kfree(data);
+
+		return ret;
+	} else if (cmd == VFIO_DEVICE_RESET) {
+		intel_gvt_ops->vgpu_reset(vgpu);
+		return 0;
+	}
+
+	return 0;
+}
+
+static const struct mdev_parent_ops intel_vgpu_ops = {
+	.supported_type_groups	= intel_vgpu_type_groups,
+	.create			= intel_vgpu_create,
+	.remove			= intel_vgpu_remove,
+
+	.open			= intel_vgpu_open,
+	.release		= intel_vgpu_release,
+
+	.read			= intel_vgpu_read,
+	.write			= intel_vgpu_write,
+	.mmap			= intel_vgpu_mmap,
+	.ioctl			= intel_vgpu_ioctl,
+};
+
+static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
+{
+	if (!intel_gvt_init_vgpu_type_groups(gvt))
+		return -EFAULT;
+
+	intel_gvt_ops = ops;
+
+	return mdev_register_device(dev, &intel_vgpu_ops);
+}
+
+static void kvmgt_host_exit(struct device *dev, void *gvt)
+{
+	intel_gvt_cleanup_vgpu_type_groups(gvt);
+	mdev_unregister_device(dev);
+}
+
+static int kvmgt_write_protect_add(unsigned long handle, u64 gfn)
+{
+	struct kvmgt_guest_info *info;
+	struct kvm *kvm;
+	struct kvm_memory_slot *slot;
+	int idx;
+
+	if (!handle_valid(handle))
+		return -ESRCH;
+
+	info = (struct kvmgt_guest_info *)handle;
+	kvm = info->kvm;
+
+	idx = srcu_read_lock(&kvm->srcu);
+	slot = gfn_to_memslot(kvm, gfn);
+	if (!slot) {
+		srcu_read_unlock(&kvm->srcu, idx);
+		return -EINVAL;
+	}
+
+	spin_lock(&kvm->mmu_lock);
+
+	if (kvmgt_gfn_is_write_protected(info, gfn))
+		goto out;
+
+	kvm_slot_page_track_add_page(kvm, slot, gfn, KVM_PAGE_TRACK_WRITE);
+	kvmgt_protect_table_add(info, gfn);
+
+out:
+	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
+	return 0;
+}
+
+static int kvmgt_write_protect_remove(unsigned long handle, u64 gfn)
+{
+	struct kvmgt_guest_info *info;
+	struct kvm *kvm;
+	struct kvm_memory_slot *slot;
+	int idx;
+
+	if (!handle_valid(handle))
+		return 0;
+
+	info = (struct kvmgt_guest_info *)handle;
+	kvm = info->kvm;
+
+	idx = srcu_read_lock(&kvm->srcu);
+	slot = gfn_to_memslot(kvm, gfn);
+	if (!slot) {
+		srcu_read_unlock(&kvm->srcu, idx);
+		return -EINVAL;
+	}
+
+	spin_lock(&kvm->mmu_lock);
+
+	if (!kvmgt_gfn_is_write_protected(info, gfn))
+		goto out;
+
+	kvm_slot_page_track_remove_page(kvm, slot, gfn, KVM_PAGE_TRACK_WRITE);
+	kvmgt_protect_table_del(info, gfn);
+
+out:
+	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
+	return 0;
+}
+
+static void kvmgt_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa,
+		const u8 *val, int len,
+		struct kvm_page_track_notifier_node *node)
+{
+	struct kvmgt_guest_info *info = container_of(node,
+					struct kvmgt_guest_info, track_node);
+
+	if (kvmgt_gfn_is_write_protected(info, gpa_to_gfn(gpa)))
+		intel_gvt_ops->emulate_mmio_write(info->vgpu, gpa,
+					(void *)val, len);
+}
+
+static void kvmgt_page_track_flush_slot(struct kvm *kvm,
+		struct kvm_memory_slot *slot,
+		struct kvm_page_track_notifier_node *node)
+{
+	int i;
+	gfn_t gfn;
+	struct kvmgt_guest_info *info = container_of(node,
+					struct kvmgt_guest_info, track_node);
+
+	spin_lock(&kvm->mmu_lock);
+	for (i = 0; i < slot->npages; i++) {
+		gfn = slot->base_gfn + i;
+		if (kvmgt_gfn_is_write_protected(info, gfn)) {
+			kvm_slot_page_track_remove_page(kvm, slot, gfn,
+						KVM_PAGE_TRACK_WRITE);
+			kvmgt_protect_table_del(info, gfn);
+		}
+	}
+	spin_unlock(&kvm->mmu_lock);
+}
+
+static bool kvmgt_check_guest(void)
+{
+	unsigned int eax, ebx, ecx, edx;
+	char s[12];
+	unsigned int *i;
+
+	eax = KVM_CPUID_SIGNATURE;
+	ebx = ecx = edx = 0;
+
+	asm volatile ("cpuid"
+		      : "+a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
+		      :
+		      : "cc", "memory");
+	i = (unsigned int *)s;
+	i[0] = ebx;
+	i[1] = ecx;
+	i[2] = edx;
+
+	return !strncmp(s, "KVMKVMKVM", strlen("KVMKVMKVM"));
+}
+
+/**
+ * NOTE:
+ * It's actually impossible to check if we are running in KVM host,
+ * since the "KVM host" is simply native. So we only dectect guest here.
+ */
+static int kvmgt_detect_host(void)
+{
+#ifdef CONFIG_INTEL_IOMMU
+	if (intel_iommu_gfx_mapped) {
+		gvt_err("Hardware IOMMU compatibility not yet supported, try to boot with intel_iommu=igfx_off\n");
+		return -ENODEV;
+	}
+#endif
+	return kvmgt_check_guest() ? -ENODEV : 0;
+}
+
+static bool __kvmgt_vgpu_exist(struct intel_vgpu *vgpu, struct kvm *kvm)
+{
+	struct intel_vgpu *itr;
+	struct kvmgt_guest_info *info;
+	int id;
+	bool ret = false;
+
+	mutex_lock(&vgpu->gvt->lock);
+	for_each_active_vgpu(vgpu->gvt, itr, id) {
+		if (!handle_valid(itr->handle))
+			continue;
+
+		info = (struct kvmgt_guest_info *)itr->handle;
+		if (kvm && kvm == info->kvm) {
+			ret = true;
+			goto out;
+		}
+	}
+out:
+	mutex_unlock(&vgpu->gvt->lock);
+	return ret;
+}
+
+static int kvmgt_guest_init(struct mdev_device *mdev)
+{
+	struct kvmgt_guest_info *info;
+	struct intel_vgpu *vgpu;
+	struct kvm *kvm;
+
+	vgpu = mdev_get_drvdata(mdev);
+	if (handle_valid(vgpu->handle))
+		return -EEXIST;
+
+	kvm = vgpu->vdev.kvm;
+	if (!kvm || kvm->mm != current->mm) {
+		gvt_err("KVM is required to use Intel vGPU\n");
+		return -ESRCH;
+	}
+
+	if (__kvmgt_vgpu_exist(vgpu, kvm))
+		return -EEXIST;
+
+	info = vzalloc(sizeof(struct kvmgt_guest_info));
+	if (!info)
+		return -ENOMEM;
+
+	vgpu->handle = (unsigned long)info;
+	info->vgpu = vgpu;
+	info->kvm = kvm;
+
+	kvmgt_protect_table_init(info);
+	gvt_cache_init(vgpu);
+
+	info->track_node.track_write = kvmgt_page_track_write;
+	info->track_node.track_flush_slot = kvmgt_page_track_flush_slot;
+	kvm_page_track_register_notifier(kvm, &info->track_node);
+
+	return 0;
+}
+
+static bool kvmgt_guest_exit(struct kvmgt_guest_info *info)
+{
+	if (!info) {
+		gvt_err("kvmgt_guest_info invalid\n");
+		return false;
+	}
+
+	kvm_page_track_unregister_notifier(info->kvm, &info->track_node);
+	kvmgt_protect_table_destroy(info);
+	gvt_cache_destroy(info->vgpu);
+	vfree(info);
+
+	return true;
+}
+
+static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle)
+{
+	/* nothing to do here */
+	return 0;
+}
+
+static void kvmgt_detach_vgpu(unsigned long handle)
+{
+	/* nothing to do here */
+}
+
+static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
+{
+	struct kvmgt_guest_info *info;
+	struct intel_vgpu *vgpu;
+
+	if (!handle_valid(handle))
+		return -ESRCH;
+
+	info = (struct kvmgt_guest_info *)handle;
+	vgpu = info->vgpu;
+
+	if (eventfd_signal(vgpu->vdev.msi_trigger, 1) == 1)
+		return 0;
+
+	return -EFAULT;
+}
+
+static unsigned long kvmgt_gfn_to_pfn(unsigned long handle, unsigned long gfn)
+{
+	unsigned long pfn;
+	struct kvmgt_guest_info *info;
+	struct device *dev;
+	int rc;
+
+	if (!handle_valid(handle))
+		return INTEL_GVT_INVALID_ADDR;
+
+	info = (struct kvmgt_guest_info *)handle;
+	pfn = gvt_cache_find(info->vgpu, gfn);
+	if (pfn != 0)
+		return pfn;
+
+	pfn = INTEL_GVT_INVALID_ADDR;
+	dev = mdev_dev(info->vgpu->vdev.mdev);
+	rc = vfio_pin_pages(dev, &gfn, 1, IOMMU_READ | IOMMU_WRITE, &pfn);
+	if (rc != 1) {
+		gvt_err("vfio_pin_pages failed for gfn 0x%lx: %d\n", gfn, rc);
+		return INTEL_GVT_INVALID_ADDR;
+	}
+
+	gvt_cache_add(info->vgpu, gfn, pfn);
+	return pfn;
+}
+
+static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa,
+			void *buf, unsigned long len, bool write)
+{
+	struct kvmgt_guest_info *info;
+	struct kvm *kvm;
+	int ret;
+	bool kthread = current->mm == NULL;
+
+	if (!handle_valid(handle))
+		return -ESRCH;
+
+	info = (struct kvmgt_guest_info *)handle;
+	kvm = info->kvm;
+
+	if (kthread)
+		use_mm(kvm->mm);
+
+	ret = write ? kvm_write_guest(kvm, gpa, buf, len) :
+		      kvm_read_guest(kvm, gpa, buf, len);
+
+	if (kthread)
+		unuse_mm(kvm->mm);
+
+	return ret;
+}
+
+static int kvmgt_read_gpa(unsigned long handle, unsigned long gpa,
+			void *buf, unsigned long len)
+{
+	return kvmgt_rw_gpa(handle, gpa, buf, len, false);
+}
+
+static int kvmgt_write_gpa(unsigned long handle, unsigned long gpa,
+			void *buf, unsigned long len)
+{
+	return kvmgt_rw_gpa(handle, gpa, buf, len, true);
+}
+
+static unsigned long kvmgt_virt_to_pfn(void *addr)
+{
+	return PFN_DOWN(__pa(addr));
+}
+
+struct intel_gvt_mpt kvmgt_mpt = {
+	.detect_host = kvmgt_detect_host,
+	.host_init = kvmgt_host_init,
+	.host_exit = kvmgt_host_exit,
+	.attach_vgpu = kvmgt_attach_vgpu,
+	.detach_vgpu = kvmgt_detach_vgpu,
+	.inject_msi = kvmgt_inject_msi,
+	.from_virt_to_mfn = kvmgt_virt_to_pfn,
+	.set_wp_page = kvmgt_write_protect_add,
+	.unset_wp_page = kvmgt_write_protect_remove,
+	.read_gpa = kvmgt_read_gpa,
+	.write_gpa = kvmgt_write_gpa,
+	.gfn_to_mfn = kvmgt_gfn_to_pfn,
+};
+EXPORT_SYMBOL_GPL(kvmgt_mpt);
+
+static int __init kvmgt_init(void)
+{
+	return 0;
+}
+
+static void __exit kvmgt_exit(void)
+{
+}
+
+module_init(kvmgt_init);
+module_exit(kvmgt_exit);
+
+MODULE_LICENSE("GPL and additional rights");
+MODULE_AUTHOR("Intel Corporation");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,8 @@
 GVT_DIR := gvt
-GVT_SOURCE := gvt.o
+GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
+	interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
+	execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
 
-ccflags-y                      += -I$(src) -I$(src)/$(GVT_DIR) -Wall
-i915-y			       += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
+ccflags-y				+= -I$(src) -I$(src)/$(GVT_DIR) -Wall
+i915-y					+= $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
+obj-$(CONFIG_DRM_I915_GVT_KVMGT)	+= $(GVT_DIR)/kvmgt.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/mmio.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/mmio.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/mmio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/mmio.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,358 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Dexuan Cui
+ *
+ * Contributors:
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Min He <min.he@intel.com>
+ *    Niu Bing <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+/**
+ * intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset
+ * @vgpu: a vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa)
+{
+	u64 gttmmio_gpa = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0) &
+			  ~GENMASK(3, 0);
+	return gpa - gttmmio_gpa;
+}
+
+#define reg_is_mmio(gvt, reg)  \
+	(reg >= 0 && reg < gvt->device_info.mmio_size)
+
+#define reg_is_gtt(gvt, reg)   \
+	(reg >= gvt->device_info.gtt_start_offset \
+	 && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt))
+
+/**
+ * intel_vgpu_emulate_mmio_read - emulate MMIO read
+ * @vgpu: a vGPU
+ * @pa: guest physical address
+ * @p_data: data return buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
+		void *p_data, unsigned int bytes)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_mmio_info *mmio;
+	unsigned int offset = 0;
+	int ret = -EINVAL;
+
+	mutex_lock(&gvt->lock);
+
+	if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) {
+		struct intel_vgpu_guest_page *gp;
+
+		gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT);
+		if (gp) {
+			ret = intel_gvt_hypervisor_read_gpa(vgpu, pa,
+					p_data, bytes);
+			if (ret) {
+				gvt_err("vgpu%d: guest page read error %d, "
+					"gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
+					vgpu->id, ret,
+					gp->gfn, pa, *(u32 *)p_data, bytes);
+			}
+			mutex_unlock(&gvt->lock);
+			return ret;
+		}
+	}
+
+	offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);
+
+	if (WARN_ON(bytes > 8))
+		goto err;
+
+	if (reg_is_gtt(gvt, offset)) {
+		if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8)))
+			goto err;
+		if (WARN_ON(bytes != 4 && bytes != 8))
+			goto err;
+		if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1)))
+			goto err;
+
+		ret = intel_vgpu_emulate_gtt_mmio_read(vgpu, offset,
+				p_data, bytes);
+		if (ret)
+			goto err;
+		mutex_unlock(&gvt->lock);
+		return ret;
+	}
+
+	if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) {
+		ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, p_data, bytes);
+		mutex_unlock(&gvt->lock);
+		return ret;
+	}
+
+	if (WARN_ON(!reg_is_mmio(gvt, offset + bytes - 1)))
+		goto err;
+
+	if (!intel_gvt_mmio_is_unalign(gvt, offset)) {
+		if (WARN_ON(!IS_ALIGNED(offset, bytes)))
+			goto err;
+	}
+
+	mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4));
+	if (mmio) {
+		if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) {
+			if (WARN_ON(offset + bytes > mmio->offset + mmio->size))
+				goto err;
+			if (WARN_ON(mmio->offset != offset))
+				goto err;
+		}
+		ret = mmio->read(vgpu, offset, p_data, bytes);
+	} else {
+		ret = intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
+
+		if (!vgpu->mmio.disable_warn_untrack) {
+			gvt_err("vgpu%d: read untracked MMIO %x(%dB) val %x\n",
+				vgpu->id, offset, bytes, *(u32 *)p_data);
+
+			if (offset == 0x206c) {
+				gvt_err("------------------------------------------\n");
+				gvt_err("vgpu%d: likely triggers a gfx reset\n",
+					vgpu->id);
+				gvt_err("------------------------------------------\n");
+				vgpu->mmio.disable_warn_untrack = true;
+			}
+		}
+	}
+
+	if (ret)
+		goto err;
+
+	intel_gvt_mmio_set_accessed(gvt, offset);
+	mutex_unlock(&gvt->lock);
+	return 0;
+err:
+	gvt_err("vgpu%d: fail to emulate MMIO read %08x len %d\n",
+			vgpu->id, offset, bytes);
+	mutex_unlock(&gvt->lock);
+	return ret;
+}
+
+/**
+ * intel_vgpu_emulate_mmio_write - emulate MMIO write
+ * @vgpu: a vGPU
+ * @pa: guest physical address
+ * @p_data: write data buffer
+ * @bytes: access data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
+		void *p_data, unsigned int bytes)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_mmio_info *mmio;
+	unsigned int offset = 0;
+	u32 old_vreg = 0, old_sreg = 0;
+	int ret = -EINVAL;
+
+	mutex_lock(&gvt->lock);
+
+	if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) {
+		struct intel_vgpu_guest_page *gp;
+
+		gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT);
+		if (gp) {
+			ret = gp->handler(gp, pa, p_data, bytes);
+			if (ret) {
+				gvt_err("vgpu%d: guest page write error %d, "
+					"gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
+					vgpu->id, ret,
+					gp->gfn, pa, *(u32 *)p_data, bytes);
+			}
+			mutex_unlock(&gvt->lock);
+			return ret;
+		}
+	}
+
+	offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa);
+
+	if (WARN_ON(bytes > 8))
+		goto err;
+
+	if (reg_is_gtt(gvt, offset)) {
+		if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8)))
+			goto err;
+		if (WARN_ON(bytes != 4 && bytes != 8))
+			goto err;
+		if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1)))
+			goto err;
+
+		ret = intel_vgpu_emulate_gtt_mmio_write(vgpu, offset,
+				p_data, bytes);
+		if (ret)
+			goto err;
+		mutex_unlock(&gvt->lock);
+		return ret;
+	}
+
+	if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) {
+		ret = intel_gvt_hypervisor_write_gpa(vgpu, pa, p_data, bytes);
+		mutex_unlock(&gvt->lock);
+		return ret;
+	}
+
+	mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4));
+	if (!mmio && !vgpu->mmio.disable_warn_untrack)
+		gvt_err("vgpu%d: write untracked MMIO %x len %d val %x\n",
+				vgpu->id, offset, bytes, *(u32 *)p_data);
+
+	if (!intel_gvt_mmio_is_unalign(gvt, offset)) {
+		if (WARN_ON(!IS_ALIGNED(offset, bytes)))
+			goto err;
+	}
+
+	if (mmio) {
+		u64 ro_mask = mmio->ro_mask;
+
+		if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) {
+			if (WARN_ON(offset + bytes > mmio->offset + mmio->size))
+				goto err;
+			if (WARN_ON(mmio->offset != offset))
+				goto err;
+		}
+
+		if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) {
+			old_vreg = vgpu_vreg(vgpu, offset);
+			old_sreg = vgpu_sreg(vgpu, offset);
+		}
+
+		if (!ro_mask) {
+			ret = mmio->write(vgpu, offset, p_data, bytes);
+		} else {
+			/* Protect RO bits like HW */
+			u64 data = 0;
+
+			/* all register bits are RO. */
+			if (ro_mask == ~(u64)0) {
+				gvt_err("vgpu%d: try to write RO reg %x\n",
+						vgpu->id, offset);
+				ret = 0;
+				goto out;
+			}
+			/* keep the RO bits in the virtual register */
+			memcpy(&data, p_data, bytes);
+			data &= ~mmio->ro_mask;
+			data |= vgpu_vreg(vgpu, offset) & mmio->ro_mask;
+			ret = mmio->write(vgpu, offset, &data, bytes);
+		}
+
+		/* higher 16bits of mode ctl regs are mask bits for change */
+		if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) {
+			u32 mask = vgpu_vreg(vgpu, offset) >> 16;
+
+			vgpu_vreg(vgpu, offset) = (old_vreg & ~mask)
+				| (vgpu_vreg(vgpu, offset) & mask);
+			vgpu_sreg(vgpu, offset) = (old_sreg & ~mask)
+				| (vgpu_sreg(vgpu, offset) & mask);
+		}
+	} else
+		ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data,
+				bytes);
+	if (ret)
+		goto err;
+out:
+	intel_gvt_mmio_set_accessed(gvt, offset);
+	mutex_unlock(&gvt->lock);
+	return 0;
+err:
+	gvt_err("vgpu%d: fail to emulate MMIO write %08x len %d\n",
+			vgpu->id, offset, bytes);
+	mutex_unlock(&gvt->lock);
+	return ret;
+}
+
+
+/**
+ * intel_vgpu_reset_mmio - reset virtual MMIO space
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	const struct intel_gvt_device_info *info = &gvt->device_info;
+
+	memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size);
+	memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size);
+
+	vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0;
+
+	/* set the bit 0:2(Core C-State ) to C0 */
+	vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0;
+}
+
+/**
+ * intel_vgpu_init_mmio - init MMIO  space
+ * @vgpu: a vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_init_mmio(struct intel_vgpu *vgpu)
+{
+	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
+
+	vgpu->mmio.vreg = vzalloc(info->mmio_size * 2);
+	if (!vgpu->mmio.vreg)
+		return -ENOMEM;
+
+	vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size;
+
+	intel_vgpu_reset_mmio(vgpu);
+
+	return 0;
+}
+
+/**
+ * intel_vgpu_clean_mmio - clean MMIO space
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_clean_mmio(struct intel_vgpu *vgpu)
+{
+	vfree(vgpu->mmio.vreg);
+	vgpu->mmio.vreg = vgpu->mmio.sreg = NULL;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/mmio.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/mmio.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/mmio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/mmio.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,110 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Ke Yu
+ *    Kevin Tian <kevin.tian@intel.com>
+ *    Dexuan Cui
+ *
+ * Contributors:
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Min He <min.he@intel.com>
+ *    Niu Bing <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef _GVT_MMIO_H_
+#define _GVT_MMIO_H_
+
+struct intel_gvt;
+struct intel_vgpu;
+
+#define D_SNB   (1 << 0)
+#define D_IVB   (1 << 1)
+#define D_HSW   (1 << 2)
+#define D_BDW   (1 << 3)
+#define D_SKL	(1 << 4)
+
+#define D_GEN9PLUS	(D_SKL)
+#define D_GEN8PLUS	(D_BDW | D_SKL)
+#define D_GEN75PLUS	(D_HSW | D_BDW | D_SKL)
+#define D_GEN7PLUS	(D_IVB | D_HSW | D_BDW | D_SKL)
+
+#define D_SKL_PLUS	(D_SKL)
+#define D_BDW_PLUS	(D_BDW | D_SKL)
+#define D_HSW_PLUS	(D_HSW | D_BDW | D_SKL)
+#define D_IVB_PLUS	(D_IVB | D_HSW | D_BDW | D_SKL)
+
+#define D_PRE_BDW	(D_SNB | D_IVB | D_HSW)
+#define D_PRE_SKL	(D_SNB | D_IVB | D_HSW | D_BDW)
+#define D_ALL		(D_SNB | D_IVB | D_HSW | D_BDW | D_SKL)
+
+struct intel_gvt_mmio_info {
+	u32 offset;
+	u32 size;
+	u32 length;
+	u32 addr_mask;
+	u64 ro_mask;
+	u32 device;
+	int (*read)(struct intel_vgpu *, unsigned int, void *, unsigned int);
+	int (*write)(struct intel_vgpu *, unsigned int, void *, unsigned int);
+	u32 addr_range;
+	struct hlist_node node;
+};
+
+unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt);
+bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device);
+
+int intel_gvt_setup_mmio_info(struct intel_gvt *gvt);
+void intel_gvt_clean_mmio_info(struct intel_gvt *gvt);
+
+struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt,
+						     unsigned int offset);
+#define INTEL_GVT_MMIO_OFFSET(reg) ({ \
+	typeof(reg) __reg = reg; \
+	u32 *offset = (u32 *)&__reg; \
+	*offset; \
+})
+
+int intel_vgpu_init_mmio(struct intel_vgpu *vgpu);
+void intel_vgpu_reset_mmio(struct intel_vgpu *vgpu);
+void intel_vgpu_clean_mmio(struct intel_vgpu *vgpu);
+
+int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa);
+
+int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, u64 pa,
+				void *p_data, unsigned int bytes);
+int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, u64 pa,
+				void *p_data, unsigned int bytes);
+bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt,
+				  unsigned int offset);
+bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt, unsigned int offset);
+void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset);
+void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt,
+				     unsigned int offset);
+bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset);
+int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset,
+				 void *p_data, unsigned int bytes);
+int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
+				  void *p_data, unsigned int bytes);
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/mpt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/mpt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/mpt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/mpt.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,15 @@
  * 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:
+ *    Eddie Dong <eddie.dong@intel.com>
+ *    Dexuan Cui
+ *    Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
  */
 
 #ifndef _GVT_MPT_H_
@@ -46,4 +55,254 @@ static inline int intel_gvt_hypervisor_d
 	return intel_gvt_host.mpt->detect_host();
 }
 
+/**
+ * intel_gvt_hypervisor_host_init - init GVT-g host side
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+static inline int intel_gvt_hypervisor_host_init(struct device *dev,
+			void *gvt, const void *ops)
+{
+	/* optional to provide */
+	if (!intel_gvt_host.mpt->host_init)
+		return 0;
+
+	return intel_gvt_host.mpt->host_init(dev, gvt, ops);
+}
+
+/**
+ * intel_gvt_hypervisor_host_exit - exit GVT-g host side
+ */
+static inline void intel_gvt_hypervisor_host_exit(struct device *dev,
+			void *gvt)
+{
+	/* optional to provide */
+	if (!intel_gvt_host.mpt->host_exit)
+		return;
+
+	intel_gvt_host.mpt->host_exit(dev, gvt);
+}
+
+/**
+ * intel_gvt_hypervisor_attach_vgpu - call hypervisor to initialize vGPU
+ * related stuffs inside hypervisor.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_attach_vgpu(struct intel_vgpu *vgpu)
+{
+	/* optional to provide */
+	if (!intel_gvt_host.mpt->attach_vgpu)
+		return 0;
+
+	return intel_gvt_host.mpt->attach_vgpu(vgpu, &vgpu->handle);
+}
+
+/**
+ * intel_gvt_hypervisor_detach_vgpu - call hypervisor to release vGPU
+ * related stuffs inside hypervisor.
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu)
+{
+	/* optional to provide */
+	if (!intel_gvt_host.mpt->detach_vgpu)
+		return;
+
+	intel_gvt_host.mpt->detach_vgpu(vgpu->handle);
+}
+
+#define MSI_CAP_CONTROL(offset) (offset + 2)
+#define MSI_CAP_ADDRESS(offset) (offset + 4)
+#define MSI_CAP_DATA(offset) (offset + 8)
+#define MSI_CAP_EN 0x1
+
+/**
+ * intel_gvt_hypervisor_inject_msi - inject a MSI interrupt into vGPU
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu)
+{
+	unsigned long offset = vgpu->gvt->device_info.msi_cap_offset;
+	u16 control, data;
+	u32 addr;
+	int ret;
+
+	control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset));
+	addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset));
+	data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset));
+
+	/* Do not generate MSI if MSIEN is disable */
+	if (!(control & MSI_CAP_EN))
+		return 0;
+
+	if (WARN(control & GENMASK(15, 1), "only support one MSI format\n"))
+		return -EINVAL;
+
+	gvt_dbg_irq("vgpu%d: inject msi address %x data%x\n", vgpu->id, addr,
+		    data);
+
+	ret = intel_gvt_host.mpt->inject_msi(vgpu->handle, addr, data);
+	if (ret)
+		return ret;
+	return 0;
+}
+
+/**
+ * intel_gvt_hypervisor_set_wp_page - translate a host VA into MFN
+ * @p: host kernel virtual address
+ *
+ * Returns:
+ * MFN on success, INTEL_GVT_INVALID_ADDR if failed.
+ */
+static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p)
+{
+	return intel_gvt_host.mpt->from_virt_to_mfn(p);
+}
+
+/**
+ * intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected
+ * @vgpu: a vGPU
+ * @p: intel_vgpu_guest_page
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *p)
+{
+	int ret;
+
+	if (p->writeprotection)
+		return 0;
+
+	ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn);
+	if (ret)
+		return ret;
+	p->writeprotection = true;
+	atomic_inc(&vgpu->gtt.n_write_protected_guest_page);
+	return 0;
+}
+
+/**
+ * intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a
+ * guest page
+ * @vgpu: a vGPU
+ * @p: intel_vgpu_guest_page
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu,
+		struct intel_vgpu_guest_page *p)
+{
+	int ret;
+
+	if (!p->writeprotection)
+		return 0;
+
+	ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn);
+	if (ret)
+		return ret;
+	p->writeprotection = false;
+	atomic_dec(&vgpu->gtt.n_write_protected_guest_page);
+	return 0;
+}
+
+/**
+ * intel_gvt_hypervisor_read_gpa - copy data from GPA to host data buffer
+ * @vgpu: a vGPU
+ * @gpa: guest physical address
+ * @buf: host data buffer
+ * @len: data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_read_gpa(struct intel_vgpu *vgpu,
+		unsigned long gpa, void *buf, unsigned long len)
+{
+	return intel_gvt_host.mpt->read_gpa(vgpu->handle, gpa, buf, len);
+}
+
+/**
+ * intel_gvt_hypervisor_write_gpa - copy data from host data buffer to GPA
+ * @vgpu: a vGPU
+ * @gpa: guest physical address
+ * @buf: host data buffer
+ * @len: data length
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_write_gpa(struct intel_vgpu *vgpu,
+		unsigned long gpa, void *buf, unsigned long len)
+{
+	return intel_gvt_host.mpt->write_gpa(vgpu->handle, gpa, buf, len);
+}
+
+/**
+ * intel_gvt_hypervisor_gfn_to_mfn - translate a GFN to MFN
+ * @vgpu: a vGPU
+ * @gpfn: guest pfn
+ *
+ * Returns:
+ * MFN on success, INTEL_GVT_INVALID_ADDR if failed.
+ */
+static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn(
+		struct intel_vgpu *vgpu, unsigned long gfn)
+{
+	return intel_gvt_host.mpt->gfn_to_mfn(vgpu->handle, gfn);
+}
+
+/**
+ * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN
+ * @vgpu: a vGPU
+ * @gfn: guest PFN
+ * @mfn: host PFN
+ * @nr: amount of PFNs
+ * @map: map or unmap
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_map_gfn_to_mfn(
+		struct intel_vgpu *vgpu, unsigned long gfn,
+		unsigned long mfn, unsigned int nr,
+		bool map)
+{
+	/* a MPT implementation could have MMIO mapped elsewhere */
+	if (!intel_gvt_host.mpt->map_gfn_to_mfn)
+		return 0;
+
+	return intel_gvt_host.mpt->map_gfn_to_mfn(vgpu->handle, gfn, mfn, nr,
+						  map);
+}
+
+/**
+ * intel_gvt_hypervisor_set_trap_area - Trap a guest PA region
+ * @vgpu: a vGPU
+ * @start: the beginning of the guest physical address region
+ * @end: the end of the guest physical address region
+ * @map: map or unmap
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+static inline int intel_gvt_hypervisor_set_trap_area(
+		struct intel_vgpu *vgpu, u64 start, u64 end, bool map)
+{
+	/* a MPT implementation could have MMIO trapped elsewhere */
+	if (!intel_gvt_host.mpt->set_trap_area)
+		return 0;
+
+	return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map);
+}
+
 #endif /* _GVT_MPT_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/opregion.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/opregion.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/opregion.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/opregion.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,320 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * 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/acpi.h>
+#include "i915_drv.h"
+#include "gvt.h"
+
+static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)
+{
+	void __iomem *host_va = vgpu->gvt->opregion.opregion_va;
+	u8 *buf;
+	int i;
+
+	if (WARN((vgpu_opregion(vgpu)->va),
+			"vgpu%d: opregion has been initialized already.\n",
+			vgpu->id))
+		return -EINVAL;
+
+	vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL |
+			__GFP_ZERO,
+			get_order(INTEL_GVT_OPREGION_SIZE));
+
+	if (!vgpu_opregion(vgpu)->va)
+		return -ENOMEM;
+
+	memcpy_fromio(vgpu_opregion(vgpu)->va, host_va,
+			INTEL_GVT_OPREGION_SIZE);
+
+	for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
+		vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
+
+	/* for unknown reason, the value in LID field is incorrect
+	 * which block the windows guest, so workaround it by force
+	 * setting it to "OPEN"
+	 */
+	buf = (u8 *)vgpu_opregion(vgpu)->va;
+	buf[INTEL_GVT_OPREGION_CLID] = 0x3;
+
+	return 0;
+}
+
+static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map)
+{
+	u64 mfn;
+	int i, ret;
+
+	for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) {
+		mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu)->va
+			+ i * PAGE_SIZE);
+		if (mfn == INTEL_GVT_INVALID_ADDR) {
+			gvt_err("fail to get MFN from VA\n");
+			return -EINVAL;
+		}
+		ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu,
+				vgpu_opregion(vgpu)->gfn[i],
+				mfn, 1, map);
+		if (ret) {
+			gvt_err("fail to map GFN to MFN, errno: %d\n", ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+/**
+ * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion
+ * @vgpu: a vGPU
+ *
+ */
+void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu)
+{
+	gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu->id);
+
+	if (!vgpu_opregion(vgpu)->va)
+		return;
+
+	if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
+		map_vgpu_opregion(vgpu, false);
+		free_pages((unsigned long)vgpu_opregion(vgpu)->va,
+				get_order(INTEL_GVT_OPREGION_SIZE));
+
+		vgpu_opregion(vgpu)->va = NULL;
+	}
+}
+
+/**
+ * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion
+ * @vgpu: a vGPU
+ * @gpa: guest physical address of opregion
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
+{
+	int ret;
+
+	gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id);
+
+	if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) {
+		gvt_dbg_core("emulate opregion from kernel\n");
+
+		ret = init_vgpu_opregion(vgpu, gpa);
+		if (ret)
+			return ret;
+
+		ret = map_vgpu_opregion(vgpu, true);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * intel_gvt_clean_opregion - clean host opergion related stuffs
+ * @gvt: a GVT device
+ *
+ */
+void intel_gvt_clean_opregion(struct intel_gvt *gvt)
+{
+	memunmap(gvt->opregion.opregion_va);
+	gvt->opregion.opregion_va = NULL;
+}
+
+/**
+ * intel_gvt_init_opregion - initialize host opergion related stuffs
+ * @gvt: a GVT device
+ *
+ * Returns:
+ * Zero on success, negative error code if failed.
+ */
+int intel_gvt_init_opregion(struct intel_gvt *gvt)
+{
+	gvt_dbg_core("init host opregion\n");
+
+	pci_read_config_dword(gvt->dev_priv->drm.pdev, INTEL_GVT_PCI_OPREGION,
+			&gvt->opregion.opregion_pa);
+
+	gvt->opregion.opregion_va = memremap(gvt->opregion.opregion_pa,
+					     INTEL_GVT_OPREGION_SIZE, MEMREMAP_WB);
+	if (!gvt->opregion.opregion_va) {
+		gvt_err("fail to map host opregion\n");
+		return -EFAULT;
+	}
+	return 0;
+}
+
+#define GVT_OPREGION_FUNC(scic)					\
+	({							\
+	 u32 __ret;						\
+	 __ret = (scic & OPREGION_SCIC_FUNC_MASK) >>		\
+	 OPREGION_SCIC_FUNC_SHIFT;				\
+	 __ret;							\
+	 })
+
+#define GVT_OPREGION_SUBFUNC(scic)				\
+	({							\
+	 u32 __ret;						\
+	 __ret = (scic & OPREGION_SCIC_SUBFUNC_MASK) >>		\
+	 OPREGION_SCIC_SUBFUNC_SHIFT;				\
+	 __ret;							\
+	 })
+
+static const char *opregion_func_name(u32 func)
+{
+	const char *name = NULL;
+
+	switch (func) {
+	case 0 ... 3:
+	case 5:
+	case 7 ... 15:
+		name = "Reserved";
+		break;
+
+	case 4:
+		name = "Get BIOS Data";
+		break;
+
+	case 6:
+		name = "System BIOS Callbacks";
+		break;
+
+	default:
+		name = "Unknown";
+		break;
+	}
+	return name;
+}
+
+static const char *opregion_subfunc_name(u32 subfunc)
+{
+	const char *name = NULL;
+
+	switch (subfunc) {
+	case 0:
+		name = "Supported Calls";
+		break;
+
+	case 1:
+		name = "Requested Callbacks";
+		break;
+
+	case 2 ... 3:
+	case 8 ... 9:
+		name = "Reserved";
+		break;
+
+	case 5:
+		name = "Boot Display";
+		break;
+
+	case 6:
+		name = "TV-Standard/Video-Connector";
+		break;
+
+	case 7:
+		name = "Internal Graphics";
+		break;
+
+	case 10:
+		name = "Spread Spectrum Clocks";
+		break;
+
+	case 11:
+		name = "Get AKSV";
+		break;
+
+	default:
+		name = "Unknown";
+		break;
+	}
+	return name;
+};
+
+static bool querying_capabilities(u32 scic)
+{
+	u32 func, subfunc;
+
+	func = GVT_OPREGION_FUNC(scic);
+	subfunc = GVT_OPREGION_SUBFUNC(scic);
+
+	if ((func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA &&
+		subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS)
+		|| (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA &&
+		 subfunc == INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS)
+		|| (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS &&
+		 subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS)) {
+		return true;
+	}
+	return false;
+}
+
+/**
+ * intel_vgpu_emulate_opregion_request - emulating OpRegion request
+ * @vgpu: a vGPU
+ * @swsci: SWSCI request
+ *
+ * Returns:
+ * Zero on success, negative error code if failed
+ */
+int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci)
+{
+	u32 *scic, *parm;
+	u32 func, subfunc;
+
+	scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC;
+	parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM;
+
+	if (!(swsci & SWSCI_SCI_SELECT)) {
+		gvt_err("vgpu%d: requesting SMI service\n", vgpu->id);
+		return 0;
+	}
+	/* ignore non 0->1 trasitions */
+	if ((vgpu_cfg_space(vgpu)[INTEL_GVT_PCI_SWSCI]
+				& SWSCI_SCI_TRIGGER) ||
+			!(swsci & SWSCI_SCI_TRIGGER)) {
+		return 0;
+	}
+
+	func = GVT_OPREGION_FUNC(*scic);
+	subfunc = GVT_OPREGION_SUBFUNC(*scic);
+	if (!querying_capabilities(*scic)) {
+		gvt_err("vgpu%d: requesting runtime service: func \"%s\","
+				" subfunc \"%s\"\n",
+				vgpu->id,
+				opregion_func_name(func),
+				opregion_subfunc_name(subfunc));
+		/*
+		 * emulate exit status of function call, '0' means
+		 * "failure, generic, unsupported or unknown cause"
+		 */
+		*scic &= ~OPREGION_SCIC_EXIT_MASK;
+		return 0;
+	}
+
+	*scic = 0;
+	*parm = 0;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/reg.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/reg.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,79 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * 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 _GVT_REG_H
+#define _GVT_REG_H
+
+#define INTEL_GVT_PCI_CLASS_VGA_OTHER   0x80
+
+#define INTEL_GVT_PCI_GMCH_CONTROL	0x50
+#define   BDW_GMCH_GMS_SHIFT		8
+#define   BDW_GMCH_GMS_MASK		0xff
+
+#define INTEL_GVT_PCI_SWSCI		0xe8
+#define   SWSCI_SCI_SELECT		(1 << 15)
+#define   SWSCI_SCI_TRIGGER		1
+
+#define INTEL_GVT_PCI_OPREGION		0xfc
+
+#define INTEL_GVT_OPREGION_CLID		0x1AC
+#define INTEL_GVT_OPREGION_SCIC		0x200
+#define   OPREGION_SCIC_FUNC_MASK	0x1E
+#define   OPREGION_SCIC_FUNC_SHIFT	1
+#define   OPREGION_SCIC_SUBFUNC_MASK	0xFF00
+#define   OPREGION_SCIC_SUBFUNC_SHIFT	8
+#define   OPREGION_SCIC_EXIT_MASK	0xE0
+#define INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA         4
+#define INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS    6
+#define INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS      0
+#define INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS 1
+#define INTEL_GVT_OPREGION_PARM                   0x204
+
+#define INTEL_GVT_OPREGION_PAGES	2
+#define INTEL_GVT_OPREGION_SIZE		(INTEL_GVT_OPREGION_PAGES * PAGE_SIZE)
+
+#define VGT_SPRSTRIDE(pipe)	_PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B)
+
+#define _REG_VECS_EXCC		0x1A028
+#define _REG_VCS2_EXCC		0x1c028
+
+#define _REG_701C0(pipe, plane) (0x701c0 + pipe * 0x1000 + (plane - 1) * 0x100)
+#define _REG_701C4(pipe, plane) (0x701c4 + pipe * 0x1000 + (plane - 1) * 0x100)
+
+#define GFX_MODE_BIT_SET_IN_MASK(val, bit) \
+		((((bit) & 0xffff0000) == 0) && !!((val) & (((bit) << 16))))
+
+#define FORCEWAKE_RENDER_GEN9_REG 0xa278
+#define FORCEWAKE_ACK_RENDER_GEN9_REG 0x0D84
+#define FORCEWAKE_BLITTER_GEN9_REG 0xa188
+#define FORCEWAKE_ACK_BLITTER_GEN9_REG 0x130044
+#define FORCEWAKE_MEDIA_GEN9_REG 0xa270
+#define FORCEWAKE_ACK_MEDIA_GEN9_REG 0x0D88
+#define FORCEWAKE_ACK_HSW_REG 0x130044
+
+#define RB_HEAD_OFF_MASK	((1U << 21) - (1U << 2))
+#define RB_TAIL_OFF_MASK	((1U << 21) - (1U << 3))
+#define RB_TAIL_SIZE_MASK	((1U << 21) - (1U << 12))
+#define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + GTT_PAGE_SIZE)
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/render.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/render.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/render.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/render.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,310 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eddie Dong <eddie.dong@intel.com>
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *    Changbin Du <changbin.du@intel.com>
+ *    Zhenyu Wang <zhenyuw@linux.intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+struct render_mmio {
+	int ring_id;
+	i915_reg_t reg;
+	u32 mask;
+	bool in_context;
+	u32 value;
+};
+
+static struct render_mmio gen8_render_mmio_list[] = {
+	{RCS, _MMIO(0x229c), 0xffff, false},
+	{RCS, _MMIO(0x2248), 0x0, false},
+	{RCS, _MMIO(0x2098), 0x0, false},
+	{RCS, _MMIO(0x20c0), 0xffff, true},
+	{RCS, _MMIO(0x24d0), 0, false},
+	{RCS, _MMIO(0x24d4), 0, false},
+	{RCS, _MMIO(0x24d8), 0, false},
+	{RCS, _MMIO(0x24dc), 0, false},
+	{RCS, _MMIO(0x7004), 0xffff, true},
+	{RCS, _MMIO(0x7008), 0xffff, true},
+	{RCS, _MMIO(0x7000), 0xffff, true},
+	{RCS, _MMIO(0x7010), 0xffff, true},
+	{RCS, _MMIO(0x7300), 0xffff, true},
+	{RCS, _MMIO(0x83a4), 0xffff, true},
+
+	{BCS, _MMIO(0x2229c), 0xffff, false},
+	{BCS, _MMIO(0x2209c), 0xffff, false},
+	{BCS, _MMIO(0x220c0), 0xffff, false},
+	{BCS, _MMIO(0x22098), 0x0, false},
+	{BCS, _MMIO(0x22028), 0x0, false},
+};
+
+static struct render_mmio gen9_render_mmio_list[] = {
+	{RCS, _MMIO(0x229c), 0xffff, false},
+	{RCS, _MMIO(0x2248), 0x0, false},
+	{RCS, _MMIO(0x2098), 0x0, false},
+	{RCS, _MMIO(0x20c0), 0xffff, true},
+	{RCS, _MMIO(0x24d0), 0, false},
+	{RCS, _MMIO(0x24d4), 0, false},
+	{RCS, _MMIO(0x24d8), 0, false},
+	{RCS, _MMIO(0x24dc), 0, false},
+	{RCS, _MMIO(0x7004), 0xffff, true},
+	{RCS, _MMIO(0x7008), 0xffff, true},
+	{RCS, _MMIO(0x7000), 0xffff, true},
+	{RCS, _MMIO(0x7010), 0xffff, true},
+	{RCS, _MMIO(0x7300), 0xffff, true},
+	{RCS, _MMIO(0x83a4), 0xffff, true},
+
+	{RCS, _MMIO(0x40e0), 0, false},
+	{RCS, _MMIO(0x40e4), 0, false},
+	{RCS, _MMIO(0x2580), 0xffff, true},
+	{RCS, _MMIO(0x7014), 0xffff, true},
+	{RCS, _MMIO(0x20ec), 0xffff, false},
+	{RCS, _MMIO(0xb118), 0, false},
+	{RCS, _MMIO(0xe100), 0xffff, true},
+	{RCS, _MMIO(0xe180), 0xffff, true},
+	{RCS, _MMIO(0xe184), 0xffff, true},
+	{RCS, _MMIO(0xe188), 0xffff, true},
+	{RCS, _MMIO(0xe194), 0xffff, true},
+	{RCS, _MMIO(0x4de0), 0, false},
+	{RCS, _MMIO(0x4de4), 0, false},
+	{RCS, _MMIO(0x4de8), 0, false},
+	{RCS, _MMIO(0x4dec), 0, false},
+	{RCS, _MMIO(0x4df0), 0, false},
+	{RCS, _MMIO(0x4df4), 0, false},
+
+	{BCS, _MMIO(0x2229c), 0xffff, false},
+	{BCS, _MMIO(0x2209c), 0xffff, false},
+	{BCS, _MMIO(0x220c0), 0xffff, false},
+	{BCS, _MMIO(0x22098), 0x0, false},
+	{BCS, _MMIO(0x22028), 0x0, false},
+
+	{VCS2, _MMIO(0x1c028), 0xffff, false},
+
+	{VECS, _MMIO(0x1a028), 0xffff, false},
+};
+
+static u32 gen9_render_mocs[I915_NUM_ENGINES][64];
+static u32 gen9_render_mocs_L3[32];
+
+static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	enum forcewake_domains fw;
+	i915_reg_t reg;
+	u32 regs[] = {
+		[RCS] = 0x4260,
+		[VCS] = 0x4264,
+		[VCS2] = 0x4268,
+		[BCS] = 0x426c,
+		[VECS] = 0x4270,
+	};
+
+	if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
+		return;
+
+	if (!test_and_clear_bit(ring_id, (void *)vgpu->tlb_handle_pending))
+		return;
+
+	reg = _MMIO(regs[ring_id]);
+
+	/* WaForceWakeRenderDuringMmioTLBInvalidate:skl
+	 * we need to put a forcewake when invalidating RCS TLB caches,
+	 * otherwise device can go to RC6 state and interrupt invalidation
+	 * process
+	 */
+	fw = intel_uncore_forcewake_for_reg(dev_priv, reg,
+					    FW_REG_READ | FW_REG_WRITE);
+	if (ring_id == RCS && IS_SKYLAKE(dev_priv))
+		fw |= FORCEWAKE_RENDER;
+
+	intel_uncore_forcewake_get(dev_priv, fw);
+
+	I915_WRITE_FW(reg, 0x1);
+
+	if (wait_for_atomic((I915_READ_FW(reg) == 0), 50))
+		gvt_err("timeout in invalidate ring (%d) tlb\n", ring_id);
+	else
+		vgpu_vreg(vgpu, regs[ring_id]) = 0;
+
+	intel_uncore_forcewake_put(dev_priv, fw);
+
+	gvt_dbg_core("invalidate TLB for ring %d\n", ring_id);
+}
+
+static void load_mocs(struct intel_vgpu *vgpu, int ring_id)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	i915_reg_t offset, l3_offset;
+	u32 regs[] = {
+		[RCS] = 0xc800,
+		[VCS] = 0xc900,
+		[VCS2] = 0xca00,
+		[BCS] = 0xcc00,
+		[VECS] = 0xcb00,
+	};
+	int i;
+
+	if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
+		return;
+
+	if (!IS_SKYLAKE(dev_priv))
+		return;
+
+	offset.reg = regs[ring_id];
+	for (i = 0; i < 64; i++) {
+		gen9_render_mocs[ring_id][i] = I915_READ(offset);
+		I915_WRITE(offset, vgpu_vreg(vgpu, offset));
+		POSTING_READ(offset);
+		offset.reg += 4;
+	}
+
+	if (ring_id == RCS) {
+		l3_offset.reg = 0xb020;
+		for (i = 0; i < 32; i++) {
+			gen9_render_mocs_L3[i] = I915_READ(l3_offset);
+			I915_WRITE(l3_offset, vgpu_vreg(vgpu, offset));
+			POSTING_READ(l3_offset);
+			l3_offset.reg += 4;
+		}
+	}
+}
+
+static void restore_mocs(struct intel_vgpu *vgpu, int ring_id)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	i915_reg_t offset, l3_offset;
+	u32 regs[] = {
+		[RCS] = 0xc800,
+		[VCS] = 0xc900,
+		[VCS2] = 0xca00,
+		[BCS] = 0xcc00,
+		[VECS] = 0xcb00,
+	};
+	int i;
+
+	if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
+		return;
+
+	if (!IS_SKYLAKE(dev_priv))
+		return;
+
+	offset.reg = regs[ring_id];
+	for (i = 0; i < 64; i++) {
+		vgpu_vreg(vgpu, offset) = I915_READ(offset);
+		I915_WRITE(offset, gen9_render_mocs[ring_id][i]);
+		POSTING_READ(offset);
+		offset.reg += 4;
+	}
+
+	if (ring_id == RCS) {
+		l3_offset.reg = 0xb020;
+		for (i = 0; i < 32; i++) {
+			vgpu_vreg(vgpu, l3_offset) = I915_READ(l3_offset);
+			I915_WRITE(l3_offset, gen9_render_mocs_L3[i]);
+			POSTING_READ(l3_offset);
+			l3_offset.reg += 4;
+		}
+	}
+}
+
+void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct render_mmio *mmio;
+	u32 v;
+	int i, array_size;
+
+	if (IS_SKYLAKE(vgpu->gvt->dev_priv)) {
+		mmio = gen9_render_mmio_list;
+		array_size = ARRAY_SIZE(gen9_render_mmio_list);
+		load_mocs(vgpu, ring_id);
+	} else {
+		mmio = gen8_render_mmio_list;
+		array_size = ARRAY_SIZE(gen8_render_mmio_list);
+	}
+
+	for (i = 0; i < array_size; i++, mmio++) {
+		if (mmio->ring_id != ring_id)
+			continue;
+
+		mmio->value = I915_READ(mmio->reg);
+		if (mmio->mask)
+			v = vgpu_vreg(vgpu, mmio->reg) | (mmio->mask << 16);
+		else
+			v = vgpu_vreg(vgpu, mmio->reg);
+
+		I915_WRITE(mmio->reg, v);
+		POSTING_READ(mmio->reg);
+
+		gvt_dbg_render("load reg %x old %x new %x\n",
+				i915_mmio_reg_offset(mmio->reg),
+				mmio->value, v);
+	}
+	handle_tlb_pending_event(vgpu, ring_id);
+}
+
+void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+	struct render_mmio *mmio;
+	u32 v;
+	int i, array_size;
+
+	if (IS_SKYLAKE(dev_priv)) {
+		mmio = gen9_render_mmio_list;
+		array_size = ARRAY_SIZE(gen9_render_mmio_list);
+		restore_mocs(vgpu, ring_id);
+	} else {
+		mmio = gen8_render_mmio_list;
+		array_size = ARRAY_SIZE(gen8_render_mmio_list);
+	}
+
+	for (i = 0; i < array_size; i++, mmio++) {
+		if (mmio->ring_id != ring_id)
+			continue;
+
+		vgpu_vreg(vgpu, mmio->reg) = I915_READ(mmio->reg);
+
+		if (mmio->mask) {
+			vgpu_vreg(vgpu, mmio->reg) &= ~(mmio->mask << 16);
+			v = mmio->value | (mmio->mask << 16);
+		} else
+			v = mmio->value;
+
+		I915_WRITE(mmio->reg, v);
+		POSTING_READ(mmio->reg);
+
+		gvt_dbg_render("restore reg %x old %x new %x\n",
+				i915_mmio_reg_offset(mmio->reg),
+				mmio->value, v);
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/render.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/render.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/render.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/render.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eddie Dong <eddie.dong@intel.com>
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *    Changbin Du <changbin.du@intel.com>
+ *    Zhenyu Wang <zhenyuw@linux.intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#ifndef __GVT_RENDER_H__
+#define __GVT_RENDER_H__
+
+void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id);
+
+void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/sched_policy.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/sched_policy.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/sched_policy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/sched_policy.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,292 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Anhua Xu
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu)
+{
+	enum intel_engine_id i;
+	struct intel_engine_cs *engine;
+
+	for_each_engine(engine, vgpu->gvt->dev_priv, i) {
+		if (!list_empty(workload_q_head(vgpu, i)))
+			return true;
+	}
+
+	return false;
+}
+
+static void try_to_schedule_next_vgpu(struct intel_gvt *gvt)
+{
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+	enum intel_engine_id i;
+	struct intel_engine_cs *engine;
+
+	/* no target to schedule */
+	if (!scheduler->next_vgpu)
+		return;
+
+	gvt_dbg_sched("try to schedule next vgpu %d\n",
+			scheduler->next_vgpu->id);
+
+	/*
+	 * after the flag is set, workload dispatch thread will
+	 * stop dispatching workload for current vgpu
+	 */
+	scheduler->need_reschedule = true;
+
+	/* still have uncompleted workload? */
+	for_each_engine(engine, gvt->dev_priv, i) {
+		if (scheduler->current_workload[i]) {
+			gvt_dbg_sched("still have running workload\n");
+			return;
+		}
+	}
+
+	gvt_dbg_sched("switch to next vgpu %d\n",
+			scheduler->next_vgpu->id);
+
+	/* switch current vgpu */
+	scheduler->current_vgpu = scheduler->next_vgpu;
+	scheduler->next_vgpu = NULL;
+
+	scheduler->need_reschedule = false;
+
+	/* wake up workload dispatch thread */
+	for_each_engine(engine, gvt->dev_priv, i)
+		wake_up(&scheduler->waitq[i]);
+}
+
+struct tbs_vgpu_data {
+	struct list_head list;
+	struct intel_vgpu *vgpu;
+	/* put some per-vgpu sched stats here */
+};
+
+struct tbs_sched_data {
+	struct intel_gvt *gvt;
+	struct delayed_work work;
+	unsigned long period;
+	struct list_head runq_head;
+};
+
+#define GVT_DEFAULT_TIME_SLICE (1 * HZ / 1000)
+
+static void tbs_sched_func(struct work_struct *work)
+{
+	struct tbs_sched_data *sched_data = container_of(work,
+			struct tbs_sched_data, work.work);
+	struct tbs_vgpu_data *vgpu_data;
+
+	struct intel_gvt *gvt = sched_data->gvt;
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+
+	struct intel_vgpu *vgpu = NULL;
+	struct list_head *pos, *head;
+
+	mutex_lock(&gvt->lock);
+
+	/* no vgpu or has already had a target */
+	if (list_empty(&sched_data->runq_head) || scheduler->next_vgpu)
+		goto out;
+
+	if (scheduler->current_vgpu) {
+		vgpu_data = scheduler->current_vgpu->sched_data;
+		head = &vgpu_data->list;
+	} else {
+		gvt_dbg_sched("no current vgpu search from q head\n");
+		head = &sched_data->runq_head;
+	}
+
+	/* search a vgpu with pending workload */
+	list_for_each(pos, head) {
+		if (pos == &sched_data->runq_head)
+			continue;
+
+		vgpu_data = container_of(pos, struct tbs_vgpu_data, list);
+		if (!vgpu_has_pending_workload(vgpu_data->vgpu))
+			continue;
+
+		vgpu = vgpu_data->vgpu;
+		break;
+	}
+
+	if (vgpu) {
+		scheduler->next_vgpu = vgpu;
+		gvt_dbg_sched("pick next vgpu %d\n", vgpu->id);
+	}
+out:
+	if (scheduler->next_vgpu) {
+		gvt_dbg_sched("try to schedule next vgpu %d\n",
+				scheduler->next_vgpu->id);
+		try_to_schedule_next_vgpu(gvt);
+	}
+
+	/*
+	 * still have vgpu on runq
+	 * or last schedule haven't finished due to running workload
+	 */
+	if (!list_empty(&sched_data->runq_head) || scheduler->next_vgpu)
+		schedule_delayed_work(&sched_data->work, sched_data->period);
+
+	mutex_unlock(&gvt->lock);
+}
+
+static int tbs_sched_init(struct intel_gvt *gvt)
+{
+	struct intel_gvt_workload_scheduler *scheduler =
+		&gvt->scheduler;
+
+	struct tbs_sched_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&data->runq_head);
+	INIT_DELAYED_WORK(&data->work, tbs_sched_func);
+	data->period = GVT_DEFAULT_TIME_SLICE;
+	data->gvt = gvt;
+
+	scheduler->sched_data = data;
+	return 0;
+}
+
+static void tbs_sched_clean(struct intel_gvt *gvt)
+{
+	struct intel_gvt_workload_scheduler *scheduler =
+		&gvt->scheduler;
+	struct tbs_sched_data *data = scheduler->sched_data;
+
+	cancel_delayed_work(&data->work);
+	kfree(data);
+	scheduler->sched_data = NULL;
+}
+
+static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu)
+{
+	struct tbs_vgpu_data *data;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->vgpu = vgpu;
+	INIT_LIST_HEAD(&data->list);
+
+	vgpu->sched_data = data;
+	return 0;
+}
+
+static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu)
+{
+	kfree(vgpu->sched_data);
+	vgpu->sched_data = NULL;
+}
+
+static void tbs_sched_start_schedule(struct intel_vgpu *vgpu)
+{
+	struct tbs_sched_data *sched_data = vgpu->gvt->scheduler.sched_data;
+	struct tbs_vgpu_data *vgpu_data = vgpu->sched_data;
+
+	if (!list_empty(&vgpu_data->list))
+		return;
+
+	list_add_tail(&vgpu_data->list, &sched_data->runq_head);
+	schedule_delayed_work(&sched_data->work, sched_data->period);
+}
+
+static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu)
+{
+	struct tbs_vgpu_data *vgpu_data = vgpu->sched_data;
+
+	list_del_init(&vgpu_data->list);
+}
+
+static struct intel_gvt_sched_policy_ops tbs_schedule_ops = {
+	.init = tbs_sched_init,
+	.clean = tbs_sched_clean,
+	.init_vgpu = tbs_sched_init_vgpu,
+	.clean_vgpu = tbs_sched_clean_vgpu,
+	.start_schedule = tbs_sched_start_schedule,
+	.stop_schedule = tbs_sched_stop_schedule,
+};
+
+int intel_gvt_init_sched_policy(struct intel_gvt *gvt)
+{
+	gvt->scheduler.sched_ops = &tbs_schedule_ops;
+
+	return gvt->scheduler.sched_ops->init(gvt);
+}
+
+void intel_gvt_clean_sched_policy(struct intel_gvt *gvt)
+{
+	gvt->scheduler.sched_ops->clean(gvt);
+}
+
+int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu)
+{
+	return vgpu->gvt->scheduler.sched_ops->init_vgpu(vgpu);
+}
+
+void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu)
+{
+	vgpu->gvt->scheduler.sched_ops->clean_vgpu(vgpu);
+}
+
+void intel_vgpu_start_schedule(struct intel_vgpu *vgpu)
+{
+	gvt_dbg_core("vgpu%d: start schedule\n", vgpu->id);
+
+	vgpu->gvt->scheduler.sched_ops->start_schedule(vgpu);
+}
+
+void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt_workload_scheduler *scheduler =
+		&vgpu->gvt->scheduler;
+
+	gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id);
+
+	scheduler->sched_ops->stop_schedule(vgpu);
+
+	if (scheduler->next_vgpu == vgpu)
+		scheduler->next_vgpu = NULL;
+
+	if (scheduler->current_vgpu == vgpu) {
+		/* stop workload dispatching */
+		scheduler->need_reschedule = true;
+		scheduler->current_vgpu = NULL;
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/sched_policy.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/sched_policy.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/sched_policy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/sched_policy.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,58 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Anhua Xu
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#ifndef __GVT_SCHED_POLICY__
+#define __GVT_SCHED_POLICY__
+
+struct intel_gvt_sched_policy_ops {
+	int (*init)(struct intel_gvt *gvt);
+	void (*clean)(struct intel_gvt *gvt);
+	int (*init_vgpu)(struct intel_vgpu *vgpu);
+	void (*clean_vgpu)(struct intel_vgpu *vgpu);
+	void (*start_schedule)(struct intel_vgpu *vgpu);
+	void (*stop_schedule)(struct intel_vgpu *vgpu);
+};
+
+int intel_gvt_init_sched_policy(struct intel_gvt *gvt);
+
+void intel_gvt_clean_sched_policy(struct intel_gvt *gvt);
+
+int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu);
+
+void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu);
+
+void intel_vgpu_start_schedule(struct intel_vgpu *vgpu);
+
+void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/scheduler.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/scheduler.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/scheduler.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/scheduler.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,583 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Chanbin Du <changbin.du@intel.com>
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#include <linux/kthread.h>
+
+#include "i915_drv.h"
+#include "gvt.h"
+
+#define RING_CTX_OFF(x) \
+	offsetof(struct execlist_ring_context, x)
+
+static void set_context_pdp_root_pointer(
+		struct execlist_ring_context *ring_context,
+		u32 pdp[8])
+{
+	struct execlist_mmio_pair *pdp_pair = &ring_context->pdp3_UDW;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		pdp_pair[i].val = pdp[7 - i];
+}
+
+static int populate_shadow_context(struct intel_vgpu_workload *workload)
+{
+	struct intel_vgpu *vgpu = workload->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+	int ring_id = workload->ring_id;
+	struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
+	struct drm_i915_gem_object *ctx_obj =
+		shadow_ctx->engine[ring_id].state->obj;
+	struct execlist_ring_context *shadow_ring_context;
+	struct page *page;
+	void *dst;
+	unsigned long context_gpa, context_page_num;
+	int i;
+
+	gvt_dbg_sched("ring id %d workload lrca %x", ring_id,
+			workload->ctx_desc.lrca);
+
+	context_page_num = intel_lr_context_size(
+			gvt->dev_priv->engine[ring_id]);
+
+	context_page_num = context_page_num >> PAGE_SHIFT;
+
+	if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS)
+		context_page_num = 19;
+
+	i = 2;
+
+	while (i < context_page_num) {
+		context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
+				(u32)((workload->ctx_desc.lrca + i) <<
+				GTT_PAGE_SHIFT));
+		if (context_gpa == INTEL_GVT_INVALID_ADDR) {
+			gvt_err("Invalid guest context descriptor\n");
+			return -EINVAL;
+		}
+
+		page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i);
+		dst = kmap(page);
+		intel_gvt_hypervisor_read_gpa(vgpu, context_gpa, dst,
+				GTT_PAGE_SIZE);
+		kunmap(page);
+		i++;
+	}
+
+	page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+	shadow_ring_context = kmap(page);
+
+#define COPY_REG(name) \
+	intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \
+		+ RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4)
+
+	COPY_REG(ctx_ctrl);
+	COPY_REG(ctx_timestamp);
+
+	if (ring_id == RCS) {
+		COPY_REG(bb_per_ctx_ptr);
+		COPY_REG(rcs_indirect_ctx);
+		COPY_REG(rcs_indirect_ctx_offset);
+	}
+#undef COPY_REG
+
+	set_context_pdp_root_pointer(shadow_ring_context,
+				     workload->shadow_mm->shadow_page_table);
+
+	intel_gvt_hypervisor_read_gpa(vgpu,
+			workload->ring_context_gpa +
+			sizeof(*shadow_ring_context),
+			(void *)shadow_ring_context +
+			sizeof(*shadow_ring_context),
+			GTT_PAGE_SIZE - sizeof(*shadow_ring_context));
+
+	kunmap(page);
+	return 0;
+}
+
+static int shadow_context_status_change(struct notifier_block *nb,
+		unsigned long action, void *data)
+{
+	struct intel_vgpu *vgpu = container_of(nb,
+			struct intel_vgpu, shadow_ctx_notifier_block);
+	struct drm_i915_gem_request *req =
+		(struct drm_i915_gem_request *)data;
+	struct intel_gvt_workload_scheduler *scheduler =
+		&vgpu->gvt->scheduler;
+	struct intel_vgpu_workload *workload =
+		scheduler->current_workload[req->engine->id];
+
+	switch (action) {
+	case INTEL_CONTEXT_SCHEDULE_IN:
+		intel_gvt_load_render_mmio(workload->vgpu,
+					   workload->ring_id);
+		atomic_set(&workload->shadow_ctx_active, 1);
+		break;
+	case INTEL_CONTEXT_SCHEDULE_OUT:
+		intel_gvt_restore_render_mmio(workload->vgpu,
+					      workload->ring_id);
+		atomic_set(&workload->shadow_ctx_active, 0);
+		break;
+	default:
+		WARN_ON(1);
+		return NOTIFY_OK;
+	}
+	wake_up(&workload->shadow_ctx_status_wq);
+	return NOTIFY_OK;
+}
+
+static int dispatch_workload(struct intel_vgpu_workload *workload)
+{
+	int ring_id = workload->ring_id;
+	struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
+	struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv;
+	struct drm_i915_gem_request *rq;
+	int ret;
+
+	gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n",
+		ring_id, workload);
+
+	shadow_ctx->desc_template = workload->ctx_desc.addressing_mode <<
+				    GEN8_CTX_ADDRESSING_MODE_SHIFT;
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+
+	rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx);
+	if (IS_ERR(rq)) {
+		gvt_err("fail to allocate gem request\n");
+		ret = PTR_ERR(rq);
+		goto out;
+	}
+
+	gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq);
+
+	workload->req = i915_gem_request_get(rq);
+
+	ret = intel_gvt_scan_and_shadow_workload(workload);
+	if (ret)
+		goto out;
+
+	ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx);
+	if (ret)
+		goto out;
+
+	ret = populate_shadow_context(workload);
+	if (ret)
+		goto out;
+
+	if (workload->prepare) {
+		ret = workload->prepare(workload);
+		if (ret)
+			goto out;
+	}
+
+	gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
+			ring_id, workload->req);
+
+	ret = 0;
+	workload->dispatched = true;
+out:
+	if (ret)
+		workload->status = ret;
+
+	if (!IS_ERR_OR_NULL(rq))
+		i915_add_request_no_flush(rq);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+	return ret;
+}
+
+static struct intel_vgpu_workload *pick_next_workload(
+		struct intel_gvt *gvt, int ring_id)
+{
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+	struct intel_vgpu_workload *workload = NULL;
+
+	mutex_lock(&gvt->lock);
+
+	/*
+	 * no current vgpu / will be scheduled out / no workload
+	 * bail out
+	 */
+	if (!scheduler->current_vgpu) {
+		gvt_dbg_sched("ring id %d stop - no current vgpu\n", ring_id);
+		goto out;
+	}
+
+	if (scheduler->need_reschedule) {
+		gvt_dbg_sched("ring id %d stop - will reschedule\n", ring_id);
+		goto out;
+	}
+
+	if (list_empty(workload_q_head(scheduler->current_vgpu, ring_id))) {
+		gvt_dbg_sched("ring id %d stop - no available workload\n",
+				ring_id);
+		goto out;
+	}
+
+	/*
+	 * still have current workload, maybe the workload disptacher
+	 * fail to submit it for some reason, resubmit it.
+	 */
+	if (scheduler->current_workload[ring_id]) {
+		workload = scheduler->current_workload[ring_id];
+		gvt_dbg_sched("ring id %d still have current workload %p\n",
+				ring_id, workload);
+		goto out;
+	}
+
+	/*
+	 * pick a workload as current workload
+	 * once current workload is set, schedule policy routines
+	 * will wait the current workload is finished when trying to
+	 * schedule out a vgpu.
+	 */
+	scheduler->current_workload[ring_id] = container_of(
+			workload_q_head(scheduler->current_vgpu, ring_id)->next,
+			struct intel_vgpu_workload, list);
+
+	workload = scheduler->current_workload[ring_id];
+
+	gvt_dbg_sched("ring id %d pick new workload %p\n", ring_id, workload);
+
+	atomic_inc(&workload->vgpu->running_workload_num);
+out:
+	mutex_unlock(&gvt->lock);
+	return workload;
+}
+
+static void update_guest_context(struct intel_vgpu_workload *workload)
+{
+	struct intel_vgpu *vgpu = workload->vgpu;
+	struct intel_gvt *gvt = vgpu->gvt;
+	int ring_id = workload->ring_id;
+	struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx;
+	struct drm_i915_gem_object *ctx_obj =
+		shadow_ctx->engine[ring_id].state->obj;
+	struct execlist_ring_context *shadow_ring_context;
+	struct page *page;
+	void *src;
+	unsigned long context_gpa, context_page_num;
+	int i;
+
+	gvt_dbg_sched("ring id %d workload lrca %x\n", ring_id,
+			workload->ctx_desc.lrca);
+
+	context_page_num = intel_lr_context_size(
+			gvt->dev_priv->engine[ring_id]);
+
+	context_page_num = context_page_num >> PAGE_SHIFT;
+
+	if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS)
+		context_page_num = 19;
+
+	i = 2;
+
+	while (i < context_page_num) {
+		context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm,
+				(u32)((workload->ctx_desc.lrca + i) <<
+					GTT_PAGE_SHIFT));
+		if (context_gpa == INTEL_GVT_INVALID_ADDR) {
+			gvt_err("invalid guest context descriptor\n");
+			return;
+		}
+
+		page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i);
+		src = kmap(page);
+		intel_gvt_hypervisor_write_gpa(vgpu, context_gpa, src,
+				GTT_PAGE_SIZE);
+		kunmap(page);
+		i++;
+	}
+
+	intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa +
+		RING_CTX_OFF(ring_header.val), &workload->rb_tail, 4);
+
+	page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+	shadow_ring_context = kmap(page);
+
+#define COPY_REG(name) \
+	intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa + \
+		RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4)
+
+	COPY_REG(ctx_ctrl);
+	COPY_REG(ctx_timestamp);
+
+#undef COPY_REG
+
+	intel_gvt_hypervisor_write_gpa(vgpu,
+			workload->ring_context_gpa +
+			sizeof(*shadow_ring_context),
+			(void *)shadow_ring_context +
+			sizeof(*shadow_ring_context),
+			GTT_PAGE_SIZE - sizeof(*shadow_ring_context));
+
+	kunmap(page);
+}
+
+static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
+{
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+	struct intel_vgpu_workload *workload;
+	struct intel_vgpu *vgpu;
+	int event;
+
+	mutex_lock(&gvt->lock);
+
+	workload = scheduler->current_workload[ring_id];
+	vgpu = workload->vgpu;
+
+	if (!workload->status && !vgpu->resetting) {
+		wait_event(workload->shadow_ctx_status_wq,
+			   !atomic_read(&workload->shadow_ctx_active));
+
+		update_guest_context(workload);
+
+		for_each_set_bit(event, workload->pending_events,
+				 INTEL_GVT_EVENT_MAX)
+			intel_vgpu_trigger_virtual_event(vgpu, event);
+	}
+
+	gvt_dbg_sched("ring id %d complete workload %p status %d\n",
+			ring_id, workload, workload->status);
+
+	scheduler->current_workload[ring_id] = NULL;
+
+	list_del_init(&workload->list);
+	workload->complete(workload);
+
+	atomic_dec(&vgpu->running_workload_num);
+	wake_up(&scheduler->workload_complete_wq);
+	mutex_unlock(&gvt->lock);
+}
+
+struct workload_thread_param {
+	struct intel_gvt *gvt;
+	int ring_id;
+};
+
+static DEFINE_MUTEX(scheduler_mutex);
+
+static int workload_thread(void *priv)
+{
+	struct workload_thread_param *p = (struct workload_thread_param *)priv;
+	struct intel_gvt *gvt = p->gvt;
+	int ring_id = p->ring_id;
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+	struct intel_vgpu_workload *workload = NULL;
+	long lret;
+	int ret;
+	bool need_force_wake = IS_SKYLAKE(gvt->dev_priv);
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
+
+	kfree(p);
+
+	gvt_dbg_core("workload thread for ring %d started\n", ring_id);
+
+	while (!kthread_should_stop()) {
+		add_wait_queue(&scheduler->waitq[ring_id], &wait);
+		do {
+			workload = pick_next_workload(gvt, ring_id);
+			if (workload)
+				break;
+			wait_woken(&wait, TASK_INTERRUPTIBLE,
+				   MAX_SCHEDULE_TIMEOUT);
+		} while (!kthread_should_stop());
+		remove_wait_queue(&scheduler->waitq[ring_id], &wait);
+
+		if (!workload)
+			break;
+
+		mutex_lock(&scheduler_mutex);
+
+		gvt_dbg_sched("ring id %d next workload %p vgpu %d\n",
+				workload->ring_id, workload,
+				workload->vgpu->id);
+
+		intel_runtime_pm_get(gvt->dev_priv);
+
+		gvt_dbg_sched("ring id %d will dispatch workload %p\n",
+				workload->ring_id, workload);
+
+		if (need_force_wake)
+			intel_uncore_forcewake_get(gvt->dev_priv,
+					FORCEWAKE_ALL);
+
+		mutex_lock(&gvt->lock);
+		ret = dispatch_workload(workload);
+		mutex_unlock(&gvt->lock);
+
+		if (ret) {
+			gvt_err("fail to dispatch workload, skip\n");
+			goto complete;
+		}
+
+		gvt_dbg_sched("ring id %d wait workload %p\n",
+				workload->ring_id, workload);
+
+		lret = i915_wait_request(workload->req,
+					 0, MAX_SCHEDULE_TIMEOUT);
+		if (lret < 0) {
+			workload->status = lret;
+			gvt_err("fail to wait workload, skip\n");
+		} else {
+			workload->status = 0;
+		}
+
+complete:
+		gvt_dbg_sched("will complete workload %p\n, status: %d\n",
+				workload, workload->status);
+
+		if (workload->req)
+			i915_gem_request_put(fetch_and_zero(&workload->req));
+
+		complete_current_workload(gvt, ring_id);
+
+		if (need_force_wake)
+			intel_uncore_forcewake_put(gvt->dev_priv,
+					FORCEWAKE_ALL);
+
+		intel_runtime_pm_put(gvt->dev_priv);
+
+		mutex_unlock(&scheduler_mutex);
+
+	}
+	return 0;
+}
+
+void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+
+	if (atomic_read(&vgpu->running_workload_num)) {
+		gvt_dbg_sched("wait vgpu idle\n");
+
+		wait_event(scheduler->workload_complete_wq,
+				!atomic_read(&vgpu->running_workload_num));
+	}
+}
+
+void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)
+{
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+	int i;
+
+	gvt_dbg_core("clean workload scheduler\n");
+
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
+		if (scheduler->thread[i]) {
+			kthread_stop(scheduler->thread[i]);
+			scheduler->thread[i] = NULL;
+		}
+	}
+}
+
+int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt)
+{
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+	struct workload_thread_param *param = NULL;
+	int ret;
+	int i;
+
+	gvt_dbg_core("init workload scheduler\n");
+
+	init_waitqueue_head(&scheduler->workload_complete_wq);
+
+	for (i = 0; i < I915_NUM_ENGINES; i++) {
+		/* check ring mask at init time */
+		if (!HAS_ENGINE(gvt->dev_priv, i))
+			continue;
+
+		init_waitqueue_head(&scheduler->waitq[i]);
+
+		param = kzalloc(sizeof(*param), GFP_KERNEL);
+		if (!param) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		param->gvt = gvt;
+		param->ring_id = i;
+
+		scheduler->thread[i] = kthread_run(workload_thread, param,
+			"gvt workload %d", i);
+		if (IS_ERR(scheduler->thread[i])) {
+			gvt_err("fail to create workload thread\n");
+			ret = PTR_ERR(scheduler->thread[i]);
+			goto err;
+		}
+	}
+	return 0;
+err:
+	intel_gvt_clean_workload_scheduler(gvt);
+	kfree(param);
+	param = NULL;
+	return ret;
+}
+
+void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu)
+{
+	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+
+	atomic_notifier_chain_unregister(&vgpu->shadow_ctx->status_notifier,
+			&vgpu->shadow_ctx_notifier_block);
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+
+	/* a little hacky to mark as ctx closed */
+	vgpu->shadow_ctx->closed = true;
+	i915_gem_context_put(vgpu->shadow_ctx);
+
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu)
+{
+	atomic_set(&vgpu->running_workload_num, 0);
+
+	vgpu->shadow_ctx = i915_gem_context_create_gvt(
+			&vgpu->gvt->dev_priv->drm);
+	if (IS_ERR(vgpu->shadow_ctx))
+		return PTR_ERR(vgpu->shadow_ctx);
+
+	vgpu->shadow_ctx->engine[RCS].initialised = true;
+
+	vgpu->shadow_ctx_notifier_block.notifier_call =
+		shadow_context_status_change;
+
+	atomic_notifier_chain_register(&vgpu->shadow_ctx->status_notifier,
+				       &vgpu->shadow_ctx_notifier_block);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/scheduler.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/scheduler.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/scheduler.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/scheduler.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ * Contributors:
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Tina Zhang <tina.zhang@intel.com>
+ *    Chanbin Du <changbin.du@intel.com>
+ *    Min He <min.he@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *    Zhenyu Wang <zhenyuw@linux.intel.com>
+ *
+ */
+
+#ifndef _GVT_SCHEDULER_H_
+#define _GVT_SCHEDULER_H_
+
+struct intel_gvt_workload_scheduler {
+	struct intel_vgpu *current_vgpu;
+	struct intel_vgpu *next_vgpu;
+	struct intel_vgpu_workload *current_workload[I915_NUM_ENGINES];
+	bool need_reschedule;
+
+	wait_queue_head_t workload_complete_wq;
+	struct task_struct *thread[I915_NUM_ENGINES];
+	wait_queue_head_t waitq[I915_NUM_ENGINES];
+
+	void *sched_data;
+	struct intel_gvt_sched_policy_ops *sched_ops;
+};
+
+#define INDIRECT_CTX_ADDR_MASK 0xffffffc0
+#define INDIRECT_CTX_SIZE_MASK 0x3f
+struct shadow_indirect_ctx {
+	struct drm_i915_gem_object *obj;
+	unsigned long guest_gma;
+	unsigned long shadow_gma;
+	void *shadow_va;
+	uint32_t size;
+};
+
+#define PER_CTX_ADDR_MASK 0xfffff000
+struct shadow_per_ctx {
+	unsigned long guest_gma;
+	unsigned long shadow_gma;
+};
+
+struct intel_shadow_wa_ctx {
+	struct intel_vgpu_workload *workload;
+	struct shadow_indirect_ctx indirect_ctx;
+	struct shadow_per_ctx per_ctx;
+
+};
+
+struct intel_vgpu_workload {
+	struct intel_vgpu *vgpu;
+	int ring_id;
+	struct drm_i915_gem_request *req;
+	/* if this workload has been dispatched to i915? */
+	bool dispatched;
+	int status;
+
+	struct intel_vgpu_mm *shadow_mm;
+
+	/* different submission model may need different handler */
+	int (*prepare)(struct intel_vgpu_workload *);
+	int (*complete)(struct intel_vgpu_workload *);
+	struct list_head list;
+
+	DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX);
+	void *shadow_ring_buffer_va;
+
+	/* execlist context information */
+	struct execlist_ctx_descriptor_format ctx_desc;
+	struct execlist_ring_context *ring_context;
+	unsigned long rb_head, rb_tail, rb_ctl, rb_start, rb_len;
+	bool restore_inhibit;
+	struct intel_vgpu_elsp_dwords elsp_dwords;
+	bool emulate_schedule_in;
+	atomic_t shadow_ctx_active;
+	wait_queue_head_t shadow_ctx_status_wq;
+	u64 ring_context_gpa;
+
+	/* shadow batch buffer */
+	struct list_head shadow_bb;
+	struct intel_shadow_wa_ctx wa_ctx;
+};
+
+/* Intel shadow batch buffer is a i915 gem object */
+struct intel_shadow_bb_entry {
+	struct list_head list;
+	struct drm_i915_gem_object *obj;
+	void *va;
+	unsigned long len;
+	u32 *bb_start_cmd_va;
+};
+
+#define workload_q_head(vgpu, ring_id) \
+	(&(vgpu->workload_q_head[ring_id]))
+
+#define queue_workload(workload) do { \
+	list_add_tail(&workload->list, \
+	workload_q_head(workload->vgpu, workload->ring_id)); \
+	wake_up(&workload->vgpu->gvt-> \
+	scheduler.waitq[workload->ring_id]); \
+} while (0)
+
+int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt);
+
+void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt);
+
+void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu);
+
+int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu);
+
+void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/trace.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/trace.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/trace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,286 @@
+/*
+ * Copyright © 2011-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#if !defined(_GVT_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _GVT_TRACE_H_
+
+#include <linux/types.h>
+#include <linux/stringify.h>
+#include <linux/tracepoint.h>
+#include <asm/tsc.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM gvt
+
+TRACE_EVENT(spt_alloc,
+	TP_PROTO(int id, void *spt, int type, unsigned long mfn,
+		unsigned long gpt_gfn),
+
+	TP_ARGS(id, spt, type, mfn, gpt_gfn),
+
+	TP_STRUCT__entry(
+		__field(int, id)
+		__field(void *, spt)
+		__field(int, type)
+		__field(unsigned long, mfn)
+		__field(unsigned long, gpt_gfn)
+		),
+
+	TP_fast_assign(
+		__entry->id = id;
+		__entry->spt = spt;
+		__entry->type = type;
+		__entry->mfn = mfn;
+		__entry->gpt_gfn = gpt_gfn;
+	),
+
+	TP_printk("VM%d [alloc] spt %p type %d mfn 0x%lx gfn 0x%lx\n",
+		__entry->id,
+		__entry->spt,
+		__entry->type,
+		__entry->mfn,
+		__entry->gpt_gfn)
+);
+
+TRACE_EVENT(spt_free,
+	TP_PROTO(int id, void *spt, int type),
+
+	TP_ARGS(id, spt, type),
+
+	TP_STRUCT__entry(
+		__field(int, id)
+		__field(void *, spt)
+		__field(int, type)
+		),
+
+	TP_fast_assign(
+		__entry->id = id;
+		__entry->spt = spt;
+		__entry->type = type;
+	),
+
+	TP_printk("VM%u [free] spt %p type %d\n",
+		__entry->id,
+		__entry->spt,
+		__entry->type)
+);
+
+#define MAX_BUF_LEN 256
+
+TRACE_EVENT(gma_index,
+	TP_PROTO(const char *prefix, unsigned long gma,
+		unsigned long index),
+
+	TP_ARGS(prefix, gma, index),
+
+	TP_STRUCT__entry(
+		__array(char, buf, MAX_BUF_LEN)
+	),
+
+	TP_fast_assign(
+		snprintf(__entry->buf, MAX_BUF_LEN,
+			"%s gma 0x%lx index 0x%lx\n", prefix, gma, index);
+	),
+
+	TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(gma_translate,
+	TP_PROTO(int id, char *type, int ring_id, int pt_level,
+		unsigned long gma, unsigned long gpa),
+
+	TP_ARGS(id, type, ring_id, pt_level, gma, gpa),
+
+	TP_STRUCT__entry(
+		__array(char, buf, MAX_BUF_LEN)
+	),
+
+	TP_fast_assign(
+		snprintf(__entry->buf, MAX_BUF_LEN,
+			"VM%d %s ring %d pt_level %d gma 0x%lx -> gpa 0x%lx\n",
+				id, type, ring_id, pt_level, gma, gpa);
+	),
+
+	TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(spt_refcount,
+	TP_PROTO(int id, char *action, void *spt, int before, int after),
+
+	TP_ARGS(id, action, spt, before, after),
+
+	TP_STRUCT__entry(
+		__array(char, buf, MAX_BUF_LEN)
+	),
+
+	TP_fast_assign(
+		snprintf(__entry->buf, MAX_BUF_LEN,
+			"VM%d [%s] spt %p before %d -> after %d\n",
+				id, action, spt, before, after);
+	),
+
+	TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(spt_change,
+	TP_PROTO(int id, char *action, void *spt, unsigned long gfn,
+		int type),
+
+	TP_ARGS(id, action, spt, gfn, type),
+
+	TP_STRUCT__entry(
+		__array(char, buf, MAX_BUF_LEN)
+	),
+
+	TP_fast_assign(
+		snprintf(__entry->buf, MAX_BUF_LEN,
+			"VM%d [%s] spt %p gfn 0x%lx type %d\n",
+				id, action, spt, gfn, type);
+	),
+
+	TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(gpt_change,
+	TP_PROTO(int id, const char *tag, void *spt, int type, u64 v,
+		unsigned long index),
+
+	TP_ARGS(id, tag, spt, type, v, index),
+
+	TP_STRUCT__entry(
+		__array(char, buf, MAX_BUF_LEN)
+	),
+
+	TP_fast_assign(
+		snprintf(__entry->buf, MAX_BUF_LEN,
+		"VM%d [%s] spt %p type %d entry 0x%llx index 0x%lx\n",
+			id, tag, spt, type, v, index);
+	),
+
+	TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(oos_change,
+	TP_PROTO(int id, const char *tag, int page_id, void *gpt, int type),
+
+	TP_ARGS(id, tag, page_id, gpt, type),
+
+	TP_STRUCT__entry(
+		__array(char, buf, MAX_BUF_LEN)
+	),
+
+	TP_fast_assign(
+		snprintf(__entry->buf, MAX_BUF_LEN,
+		"VM%d [oos %s] page id %d gpt %p type %d\n",
+			id, tag, page_id, gpt, type);
+	),
+
+	TP_printk("%s", __entry->buf)
+);
+
+TRACE_EVENT(oos_sync,
+	TP_PROTO(int id, int page_id, void *gpt, int type, u64 v,
+		unsigned long index),
+
+	TP_ARGS(id, page_id, gpt, type, v, index),
+
+	TP_STRUCT__entry(
+		__array(char, buf, MAX_BUF_LEN)
+	),
+
+	TP_fast_assign(
+	snprintf(__entry->buf, MAX_BUF_LEN,
+	"VM%d [oos sync] page id %d gpt %p type %d entry 0x%llx index 0x%lx\n",
+				id, page_id, gpt, type, v, index);
+	),
+
+	TP_printk("%s", __entry->buf)
+);
+
+#define MAX_CMD_STR_LEN	256
+TRACE_EVENT(gvt_command,
+		TP_PROTO(u8 vm_id, u8 ring_id, u32 ip_gma, u32 *cmd_va, u32 cmd_len, bool ring_buffer_cmd, cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler),
+
+		TP_ARGS(vm_id, ring_id, ip_gma, cmd_va, cmd_len, ring_buffer_cmd, cost_pre_cmd_handler, cost_cmd_handler),
+
+		TP_STRUCT__entry(
+			__field(u8, vm_id)
+			__field(u8, ring_id)
+			__field(int, i)
+			__array(char, tmp_buf, MAX_CMD_STR_LEN)
+			__array(char, cmd_str, MAX_CMD_STR_LEN)
+			),
+
+		TP_fast_assign(
+			__entry->vm_id = vm_id;
+			__entry->ring_id = ring_id;
+			__entry->cmd_str[0] = '\0';
+			snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "VM(%d) Ring(%d): %s ip(%08x) pre handler cost (%llu), handler cost (%llu) ", vm_id, ring_id, ring_buffer_cmd ? "RB":"BB", ip_gma, cost_pre_cmd_handler, cost_cmd_handler);
+			strcat(__entry->cmd_str, __entry->tmp_buf);
+			entry->i = 0;
+			while (cmd_len > 0) {
+				if (cmd_len >= 8) {
+					snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x %08x %08x %08x %08x ",
+						cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3],
+						cmd_va[__entry->i+4], cmd_va[__entry->i+5], cmd_va[__entry->i+6], cmd_va[__entry->i+7]);
+					__entry->i += 8;
+					cmd_len -= 8;
+					strcat(__entry->cmd_str, __entry->tmp_buf);
+				} else if (cmd_len >= 4) {
+					snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x ",
+						cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3]);
+					__entry->i += 4;
+					cmd_len -= 4;
+					strcat(__entry->cmd_str, __entry->tmp_buf);
+				} else if (cmd_len >= 2) {
+					snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x ", cmd_va[__entry->i], cmd_va[__entry->i+1]);
+					__entry->i += 2;
+					cmd_len -= 2;
+					strcat(__entry->cmd_str, __entry->tmp_buf);
+				} else if (cmd_len == 1) {
+					snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x ", cmd_va[__entry->i]);
+					__entry->i += 1;
+					cmd_len -= 1;
+					strcat(__entry->cmd_str, __entry->tmp_buf);
+				}
+			}
+			strcat(__entry->cmd_str, "\n");
+		),
+
+		TP_printk("%s", __entry->cmd_str)
+);
+#endif /* _GVT_TRACE_H_ */
+
+/* This part must be out of protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/trace_points.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/trace_points.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/trace_points.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/trace_points.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Jike Song <jike.song@intel.com>
+ *
+ * Contributors:
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *
+ */
+
+#include "trace.h"
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/vgpu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/vgpu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/gvt/vgpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/gvt/vgpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,409 @@
+/*
+ * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eddie Dong <eddie.dong@intel.com>
+ *    Kevin Tian <kevin.tian@intel.com>
+ *
+ * Contributors:
+ *    Ping Gao <ping.a.gao@intel.com>
+ *    Zhi Wang <zhi.a.wang@intel.com>
+ *    Bing Niu <bing.niu@intel.com>
+ *
+ */
+
+#include "i915_drv.h"
+#include "gvt.h"
+#include "i915_pvinfo.h"
+
+void populate_pvinfo_page(struct intel_vgpu *vgpu)
+{
+	/* setup the ballooning information */
+	vgpu_vreg64(vgpu, vgtif_reg(magic)) = VGT_MAGIC;
+	vgpu_vreg(vgpu, vgtif_reg(version_major)) = 1;
+	vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0;
+	vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0;
+	vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id;
+	vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) =
+		vgpu_aperture_gmadr_base(vgpu);
+	vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) =
+		vgpu_aperture_sz(vgpu);
+	vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.base)) =
+		vgpu_hidden_gmadr_base(vgpu);
+	vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.size)) =
+		vgpu_hidden_sz(vgpu);
+
+	vgpu_vreg(vgpu, vgtif_reg(avail_rs.fence_num)) = vgpu_fence_sz(vgpu);
+
+	gvt_dbg_core("Populate PVINFO PAGE for vGPU %d\n", vgpu->id);
+	gvt_dbg_core("aperture base [GMADR] 0x%llx size 0x%llx\n",
+		vgpu_aperture_gmadr_base(vgpu), vgpu_aperture_sz(vgpu));
+	gvt_dbg_core("hidden base [GMADR] 0x%llx size=0x%llx\n",
+		vgpu_hidden_gmadr_base(vgpu), vgpu_hidden_sz(vgpu));
+	gvt_dbg_core("fence size %d\n", vgpu_fence_sz(vgpu));
+
+	WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
+}
+
+/**
+ * intel_gvt_init_vgpu_types - initialize vGPU type list
+ * @gvt : GVT device
+ *
+ * Initialize vGPU type list based on available resource.
+ *
+ */
+int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
+{
+	unsigned int num_types;
+	unsigned int i, low_avail;
+	unsigned int min_low;
+
+	/* vGPU type name is defined as GVTg_Vx_y which contains
+	 * physical GPU generation type and 'y' means maximum vGPU
+	 * instances user can create on one physical GPU for this
+	 * type.
+	 *
+	 * Depend on physical SKU resource, might see vGPU types like
+	 * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create
+	 * different types of vGPU on same physical GPU depending on
+	 * available resource. Each vGPU type will have "avail_instance"
+	 * to indicate how many vGPU instance can be created for this
+	 * type.
+	 *
+	 * Currently use static size here as we init type earlier..
+	 */
+	low_avail = MB_TO_BYTES(256) - HOST_LOW_GM_SIZE;
+	num_types = 4;
+
+	gvt->types = kzalloc(num_types * sizeof(struct intel_vgpu_type),
+			     GFP_KERNEL);
+	if (!gvt->types)
+		return -ENOMEM;
+
+	min_low = MB_TO_BYTES(32);
+	for (i = 0; i < num_types; ++i) {
+		if (low_avail / min_low == 0)
+			break;
+		gvt->types[i].low_gm_size = min_low;
+		gvt->types[i].high_gm_size = max((min_low<<3), MB_TO_BYTES(384U));
+		gvt->types[i].fence = 4;
+		gvt->types[i].max_instance = low_avail / min_low;
+		gvt->types[i].avail_instance = gvt->types[i].max_instance;
+
+		if (IS_GEN8(gvt->dev_priv))
+			sprintf(gvt->types[i].name, "GVTg_V4_%u",
+						gvt->types[i].max_instance);
+		else if (IS_GEN9(gvt->dev_priv))
+			sprintf(gvt->types[i].name, "GVTg_V5_%u",
+						gvt->types[i].max_instance);
+
+		min_low <<= 1;
+		gvt_dbg_core("type[%d]: %s max %u avail %u low %u high %u fence %u\n",
+			     i, gvt->types[i].name, gvt->types[i].max_instance,
+			     gvt->types[i].avail_instance,
+			     gvt->types[i].low_gm_size,
+			     gvt->types[i].high_gm_size, gvt->types[i].fence);
+	}
+
+	gvt->num_types = i;
+	return 0;
+}
+
+void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
+{
+	kfree(gvt->types);
+}
+
+static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
+{
+	int i;
+	unsigned int low_gm_avail, high_gm_avail, fence_avail;
+	unsigned int low_gm_min, high_gm_min, fence_min, total_min;
+
+	/* Need to depend on maxium hw resource size but keep on
+	 * static config for now.
+	 */
+	low_gm_avail = MB_TO_BYTES(256) - HOST_LOW_GM_SIZE -
+		gvt->gm.vgpu_allocated_low_gm_size;
+	high_gm_avail = MB_TO_BYTES(256) * 8UL - HOST_HIGH_GM_SIZE -
+		gvt->gm.vgpu_allocated_high_gm_size;
+	fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
+		gvt->fence.vgpu_allocated_fence_num;
+
+	for (i = 0; i < gvt->num_types; i++) {
+		low_gm_min = low_gm_avail / gvt->types[i].low_gm_size;
+		high_gm_min = high_gm_avail / gvt->types[i].high_gm_size;
+		fence_min = fence_avail / gvt->types[i].fence;
+		total_min = min(min(low_gm_min, high_gm_min), fence_min);
+		gvt->types[i].avail_instance = min(gvt->types[i].max_instance,
+						   total_min);
+
+		gvt_dbg_core("update type[%d]: %s max %u avail %u low %u high %u fence %u\n",
+		       i, gvt->types[i].name, gvt->types[i].max_instance,
+		       gvt->types[i].avail_instance, gvt->types[i].low_gm_size,
+		       gvt->types[i].high_gm_size, gvt->types[i].fence);
+	}
+}
+
+/**
+ * intel_gvt_destroy_vgpu - destroy a virtual GPU
+ * @vgpu: virtual GPU
+ *
+ * This function is called when user wants to destroy a virtual GPU.
+ *
+ */
+void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+
+	mutex_lock(&gvt->lock);
+
+	vgpu->active = false;
+	idr_remove(&gvt->vgpu_idr, vgpu->id);
+
+	if (atomic_read(&vgpu->running_workload_num)) {
+		mutex_unlock(&gvt->lock);
+		intel_gvt_wait_vgpu_idle(vgpu);
+		mutex_lock(&gvt->lock);
+	}
+
+	intel_vgpu_stop_schedule(vgpu);
+	intel_vgpu_clean_sched_policy(vgpu);
+	intel_vgpu_clean_gvt_context(vgpu);
+	intel_vgpu_clean_execlist(vgpu);
+	intel_vgpu_clean_display(vgpu);
+	intel_vgpu_clean_opregion(vgpu);
+	intel_vgpu_clean_gtt(vgpu);
+	intel_gvt_hypervisor_detach_vgpu(vgpu);
+	intel_vgpu_free_resource(vgpu);
+	intel_vgpu_clean_mmio(vgpu);
+	vfree(vgpu);
+
+	intel_gvt_update_vgpu_types(gvt);
+	mutex_unlock(&gvt->lock);
+}
+
+static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
+		struct intel_vgpu_creation_params *param)
+{
+	struct intel_vgpu *vgpu;
+	int ret;
+
+	gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n",
+			param->handle, param->low_gm_sz, param->high_gm_sz,
+			param->fence_sz);
+
+	vgpu = vzalloc(sizeof(*vgpu));
+	if (!vgpu)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_lock(&gvt->lock);
+
+	ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL);
+	if (ret < 0)
+		goto out_free_vgpu;
+
+	vgpu->id = ret;
+	vgpu->handle = param->handle;
+	vgpu->gvt = gvt;
+	bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
+
+	intel_vgpu_init_cfg_space(vgpu, param->primary);
+
+	ret = intel_vgpu_init_mmio(vgpu);
+	if (ret)
+		goto out_clean_idr;
+
+	ret = intel_vgpu_alloc_resource(vgpu, param);
+	if (ret)
+		goto out_clean_vgpu_mmio;
+
+	populate_pvinfo_page(vgpu);
+
+	ret = intel_gvt_hypervisor_attach_vgpu(vgpu);
+	if (ret)
+		goto out_clean_vgpu_resource;
+
+	ret = intel_vgpu_init_gtt(vgpu);
+	if (ret)
+		goto out_detach_hypervisor_vgpu;
+
+	ret = intel_vgpu_init_display(vgpu);
+	if (ret)
+		goto out_clean_gtt;
+
+	ret = intel_vgpu_init_execlist(vgpu);
+	if (ret)
+		goto out_clean_display;
+
+	ret = intel_vgpu_init_gvt_context(vgpu);
+	if (ret)
+		goto out_clean_execlist;
+
+	ret = intel_vgpu_init_sched_policy(vgpu);
+	if (ret)
+		goto out_clean_shadow_ctx;
+
+	vgpu->active = true;
+	mutex_unlock(&gvt->lock);
+
+	return vgpu;
+
+out_clean_shadow_ctx:
+	intel_vgpu_clean_gvt_context(vgpu);
+out_clean_execlist:
+	intel_vgpu_clean_execlist(vgpu);
+out_clean_display:
+	intel_vgpu_clean_display(vgpu);
+out_clean_gtt:
+	intel_vgpu_clean_gtt(vgpu);
+out_detach_hypervisor_vgpu:
+	intel_gvt_hypervisor_detach_vgpu(vgpu);
+out_clean_vgpu_resource:
+	intel_vgpu_free_resource(vgpu);
+out_clean_vgpu_mmio:
+	intel_vgpu_clean_mmio(vgpu);
+out_clean_idr:
+	idr_remove(&gvt->vgpu_idr, vgpu->id);
+out_free_vgpu:
+	vfree(vgpu);
+	mutex_unlock(&gvt->lock);
+	return ERR_PTR(ret);
+}
+
+/**
+ * intel_gvt_create_vgpu - create a virtual GPU
+ * @gvt: GVT device
+ * @type: type of the vGPU to create
+ *
+ * This function is called when user wants to create a virtual GPU.
+ *
+ * Returns:
+ * pointer to intel_vgpu, error pointer if failed.
+ */
+struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
+				struct intel_vgpu_type *type)
+{
+	struct intel_vgpu_creation_params param;
+	struct intel_vgpu *vgpu;
+
+	param.handle = 0;
+	param.primary = 1;
+	param.low_gm_sz = type->low_gm_size;
+	param.high_gm_sz = type->high_gm_size;
+	param.fence_sz = type->fence;
+
+	/* XXX current param based on MB */
+	param.low_gm_sz = BYTES_TO_MB(param.low_gm_sz);
+	param.high_gm_sz = BYTES_TO_MB(param.high_gm_sz);
+
+	vgpu = __intel_gvt_create_vgpu(gvt, &param);
+	if (IS_ERR(vgpu))
+		return vgpu;
+
+	/* calculate left instance change for types */
+	intel_gvt_update_vgpu_types(gvt);
+
+	return vgpu;
+}
+
+/**
+ * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset
+ * @vgpu: virtual GPU
+ * @dmlr: vGPU Device Model Level Reset or GT Reset
+ * @engine_mask: engines to reset for GT reset
+ *
+ * This function is called when user wants to reset a virtual GPU through
+ * device model reset or GT reset. The caller should hold the gvt lock.
+ *
+ * vGPU Device Model Level Reset (DMLR) simulates the PCI level reset to reset
+ * the whole vGPU to default state as when it is created. This vGPU function
+ * is required both for functionary and security concerns.The ultimate goal
+ * of vGPU FLR is that reuse a vGPU instance by virtual machines. When we
+ * assign a vGPU to a virtual machine we must isse such reset first.
+ *
+ * Full GT Reset and Per-Engine GT Reset are soft reset flow for GPU engines
+ * (Render, Blitter, Video, Video Enhancement). It is defined by GPU Spec.
+ * Unlike the FLR, GT reset only reset particular resource of a vGPU per
+ * the reset request. Guest driver can issue a GT reset by programming the
+ * virtual GDRST register to reset specific virtual GPU engine or all
+ * engines.
+ *
+ * The parameter dev_level is to identify if we will do DMLR or GT reset.
+ * The parameter engine_mask is to specific the engines that need to be
+ * resetted. If value ALL_ENGINES is given for engine_mask, it means
+ * the caller requests a full GT reset that we will reset all virtual
+ * GPU engines. For FLR, engine_mask is ignored.
+ */
+void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
+				 unsigned int engine_mask)
+{
+	struct intel_gvt *gvt = vgpu->gvt;
+	struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler;
+
+	gvt_dbg_core("------------------------------------------\n");
+	gvt_dbg_core("resseting vgpu%d, dmlr %d, engine_mask %08x\n",
+		     vgpu->id, dmlr, engine_mask);
+	vgpu->resetting = true;
+
+	intel_vgpu_stop_schedule(vgpu);
+	/*
+	 * The current_vgpu will set to NULL after stopping the
+	 * scheduler when the reset is triggered by current vgpu.
+	 */
+	if (scheduler->current_vgpu == NULL) {
+		mutex_unlock(&gvt->lock);
+		intel_gvt_wait_vgpu_idle(vgpu);
+		mutex_lock(&gvt->lock);
+	}
+
+	intel_vgpu_reset_execlist(vgpu, dmlr ? ALL_ENGINES : engine_mask);
+
+	/* full GPU reset or device model level reset */
+	if (engine_mask == ALL_ENGINES || dmlr) {
+		intel_vgpu_reset_gtt(vgpu, dmlr);
+		intel_vgpu_reset_resource(vgpu);
+		intel_vgpu_reset_mmio(vgpu);
+		populate_pvinfo_page(vgpu);
+
+		if (dmlr)
+			intel_vgpu_reset_cfg_space(vgpu);
+	}
+
+	vgpu->resetting = false;
+	gvt_dbg_core("reset vgpu%d done\n", vgpu->id);
+	gvt_dbg_core("------------------------------------------\n");
+}
+
+/**
+ * intel_gvt_reset_vgpu - reset a virtual GPU (Function Level)
+ * @vgpu: virtual GPU
+ *
+ * This function is called when user wants to reset a virtual GPU.
+ *
+ */
+void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu)
+{
+	mutex_lock(&vgpu->gvt->lock);
+	intel_gvt_reset_vgpu_locked(vgpu, true, 0);
+	mutex_unlock(&vgpu->gvt->lock);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_cmd_parser.c	2017-02-12 16:03:20.000000000 -0500
@@ -1290,7 +1290,7 @@ int intel_engine_cmd_parser(struct intel
 	}
 
 	if (ret == 0 && needs_clflush_after)
-		drm_clflush_virt_range(shadow_batch_obj->mapping, batch_len);
+		drm_clflush_virt_range(shadow_batch_obj->mm.mapping, batch_len);
 	i915_gem_object_unpin_map(shadow_batch_obj);
 
 	return ret;
@@ -1308,10 +1308,11 @@ int intel_engine_cmd_parser(struct intel
 int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	bool active = false;
 
 	/* If the command parser is not enabled, report 0 - unsupported */
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		if (intel_engine_needs_cmd_parser(engine)) {
 			active = true;
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -79,10 +79,8 @@ static int i915_capabilities(struct seq_
 	seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv));
 	seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv));
 #define PRINT_FLAG(x)  seq_printf(m, #x ": %s\n", yesno(info->x))
-#define SEP_SEMICOLON ;
-	DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
+	DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
 #undef PRINT_FLAG
-#undef SEP_SEMICOLON
 
 	return 0;
 }
@@ -109,12 +107,12 @@ static char get_tiling_flag(struct drm_i
 
 static char get_global_flag(struct drm_i915_gem_object *obj)
 {
-	return i915_gem_object_to_ggtt(obj, NULL) ?  'g' : ' ';
+	return !list_empty(&obj->userfault_link) ? 'g' : ' ';
 }
 
 static char get_pin_mapped_flag(struct drm_i915_gem_object *obj)
 {
-	return obj->mapping ? 'M' : ' ';
+	return obj->mm.mapping ? 'M' : ' ';
 }
 
 static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj)
@@ -138,11 +136,10 @@ describe_obj(struct seq_file *m, struct
 	struct i915_vma *vma;
 	unsigned int frontbuffer_bits;
 	int pin_count = 0;
-	enum intel_engine_id id;
 
 	lockdep_assert_held(&obj->base.dev->struct_mutex);
 
-	seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x [ ",
+	seq_printf(m, "%pK: %c%c%c%c%c %8zdKiB %02x %02x %s%s%s",
 		   &obj->base,
 		   get_active_flag(obj),
 		   get_pin_flag(obj),
@@ -151,17 +148,10 @@ describe_obj(struct seq_file *m, struct
 		   get_pin_mapped_flag(obj),
 		   obj->base.size / 1024,
 		   obj->base.read_domains,
-		   obj->base.write_domain);
-	for_each_engine_id(engine, dev_priv, id)
-		seq_printf(m, "%x ",
-			   i915_gem_active_get_seqno(&obj->last_read[id],
-						     &obj->base.dev->struct_mutex));
-	seq_printf(m, "] %x %s%s%s",
-		   i915_gem_active_get_seqno(&obj->last_write,
-					     &obj->base.dev->struct_mutex),
+		   obj->base.write_domain,
 		   i915_cache_level_str(dev_priv, obj->cache_level),
-		   obj->dirty ? " dirty" : "",
-		   obj->madv == I915_MADV_DONTNEED ? " purgeable" : "");
+		   obj->mm.dirty ? " dirty" : "",
+		   obj->mm.madv == I915_MADV_DONTNEED ? " purgeable" : "");
 	if (obj->base.name)
 		seq_printf(m, " (name: %d)", obj->base.name);
 	list_for_each_entry(vma, &obj->vma_list, obj_link) {
@@ -188,18 +178,8 @@ describe_obj(struct seq_file *m, struct
 	}
 	if (obj->stolen)
 		seq_printf(m, " (stolen: %08llx)", obj->stolen->start);
-	if (obj->pin_display || obj->fault_mappable) {
-		char s[3], *t = s;
-		if (obj->pin_display)
-			*t++ = 'p';
-		if (obj->fault_mappable)
-			*t++ = 'f';
-		*t = '\0';
-		seq_printf(m, " (%s mappable)", s);
-	}
 
-	engine = i915_gem_active_get_engine(&obj->last_write,
-					    &dev_priv->drm.struct_mutex);
+	engine = i915_gem_object_last_write_engine(obj);
 	if (engine)
 		seq_printf(m, " (%s)", engine->name);
 
@@ -237,7 +217,7 @@ static int i915_gem_stolen_list_info(str
 		return ret;
 
 	total_obj_size = total_gtt_size = count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
 		if (obj->stolen == NULL)
 			continue;
 
@@ -247,7 +227,7 @@ static int i915_gem_stolen_list_info(str
 		total_gtt_size += i915_gem_obj_total_ggtt_size(obj);
 		count++;
 	}
-	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
 		if (obj->stolen == NULL)
 			continue;
 
@@ -334,11 +314,12 @@ static void print_batch_pool_stats(struc
 	struct drm_i915_gem_object *obj;
 	struct file_stats stats;
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int j;
 
 	memset(&stats, 0, sizeof(stats));
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
 			list_for_each_entry(obj,
 					    &engine->batch_pool.cache_list[j],
@@ -402,23 +383,23 @@ static int i915_gem_object_info(struct s
 	if (ret)
 		return ret;
 
-	seq_printf(m, "%u objects, %zu bytes\n",
+	seq_printf(m, "%u objects, %llu bytes\n",
 		   dev_priv->mm.object_count,
 		   dev_priv->mm.object_memory);
 
 	size = count = 0;
 	mapped_size = mapped_count = 0;
 	purgeable_size = purgeable_count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
 		size += obj->base.size;
 		++count;
 
-		if (obj->madv == I915_MADV_DONTNEED) {
+		if (obj->mm.madv == I915_MADV_DONTNEED) {
 			purgeable_size += obj->base.size;
 			++purgeable_count;
 		}
 
-		if (obj->mapping) {
+		if (obj->mm.mapping) {
 			mapped_count++;
 			mapped_size += obj->base.size;
 		}
@@ -426,7 +407,7 @@ static int i915_gem_object_info(struct s
 	seq_printf(m, "%u unbound objects, %llu bytes\n", count, size);
 
 	size = count = dpy_size = dpy_count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
 		size += obj->base.size;
 		++count;
 
@@ -435,12 +416,12 @@ static int i915_gem_object_info(struct s
 			++dpy_count;
 		}
 
-		if (obj->madv == I915_MADV_DONTNEED) {
+		if (obj->mm.madv == I915_MADV_DONTNEED) {
 			purgeable_size += obj->base.size;
 			++purgeable_count;
 		}
 
-		if (obj->mapping) {
+		if (obj->mm.mapping) {
 			mapped_count++;
 			mapped_size += obj->base.size;
 		}
@@ -512,7 +493,7 @@ static int i915_gem_gtt_info(struct seq_
 		return ret;
 
 	total_obj_size = total_gtt_size = count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
 		if (show_pin_display_only && !obj->pin_display)
 			continue;
 
@@ -566,12 +547,12 @@ static int i915_gem_pageflip_info(struct
 					   pipe, plane);
 			}
 			if (work->flip_queued_req) {
-				struct intel_engine_cs *engine = i915_gem_request_get_engine(work->flip_queued_req);
+				struct intel_engine_cs *engine = work->flip_queued_req->engine;
 
 				seq_printf(m, "Flip queued on %s at seqno %x, next seqno %x [current breadcrumb %x], completed? %d\n",
 					   engine->name,
-					   i915_gem_request_get_seqno(work->flip_queued_req),
-					   dev_priv->next_seqno,
+					   work->flip_queued_req->global_seqno,
+					   atomic_read(&dev_priv->gt.global_timeline.next_seqno),
 					   intel_engine_get_seqno(engine),
 					   i915_gem_request_completed(work->flip_queued_req));
 			} else
@@ -607,6 +588,7 @@ static int i915_gem_batch_pool_info(stru
 	struct drm_device *dev = &dev_priv->drm;
 	struct drm_i915_gem_object *obj;
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int total = 0;
 	int ret, j;
 
@@ -614,7 +596,7 @@ static int i915_gem_batch_pool_info(stru
 	if (ret)
 		return ret;
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) {
 			int count;
 
@@ -645,12 +627,24 @@ static int i915_gem_batch_pool_info(stru
 	return 0;
 }
 
+static void print_request(struct seq_file *m,
+			  struct drm_i915_gem_request *rq,
+			  const char *prefix)
+{
+	seq_printf(m, "%s%x [%x:%x] prio=%d @ %dms: %s\n", prefix,
+		   rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno,
+		   rq->priotree.priority,
+		   jiffies_to_msecs(jiffies - rq->emitted_jiffies),
+		   rq->timeline->common->name);
+}
+
 static int i915_gem_request_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct drm_device *dev = &dev_priv->drm;
-	struct intel_engine_cs *engine;
 	struct drm_i915_gem_request *req;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int ret, any;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -658,29 +652,18 @@ static int i915_gem_request_info(struct
 		return ret;
 
 	any = 0;
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		int count;
 
 		count = 0;
-		list_for_each_entry(req, &engine->request_list, link)
+		list_for_each_entry(req, &engine->timeline->requests, link)
 			count++;
 		if (count == 0)
 			continue;
 
 		seq_printf(m, "%s requests: %d\n", engine->name, count);
-		list_for_each_entry(req, &engine->request_list, link) {
-			struct pid *pid = req->ctx->pid;
-			struct task_struct *task;
-
-			rcu_read_lock();
-			task = pid ? pid_task(pid, PIDTYPE_PID) : NULL;
-			seq_printf(m, "    %x @ %d: %s [%d]\n",
-				   req->fence.seqno,
-				   (int) (jiffies - req->emitted_jiffies),
-				   task ? task->comm : "<unknown>",
-				   task ? task->pid : -1);
-			rcu_read_unlock();
-		}
+		list_for_each_entry(req, &engine->timeline->requests, link)
+			print_request(m, req, "    ");
 
 		any++;
 	}
@@ -701,22 +684,23 @@ static void i915_ring_seqno_info(struct
 	seq_printf(m, "Current sequence (%s): %x\n",
 		   engine->name, intel_engine_get_seqno(engine));
 
-	spin_lock(&b->lock);
+	spin_lock_irq(&b->lock);
 	for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
 		struct intel_wait *w = container_of(rb, typeof(*w), node);
 
 		seq_printf(m, "Waiting (%s): %s [%d] on %x\n",
 			   engine->name, w->tsk->comm, w->tsk->pid, w->seqno);
 	}
-	spin_unlock(&b->lock);
+	spin_unlock_irq(&b->lock);
 }
 
 static int i915_gem_seqno_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		i915_ring_seqno_info(m, engine);
 
 	return 0;
@@ -727,6 +711,7 @@ static int i915_interrupt_info(struct se
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int i, pipe;
 
 	intel_runtime_pm_get(dev_priv);
@@ -743,17 +728,32 @@ static int i915_interrupt_info(struct se
 			   I915_READ(VLV_IIR_RW));
 		seq_printf(m, "Display IMR:\t%08x\n",
 			   I915_READ(VLV_IMR));
-		for_each_pipe(dev_priv, pipe)
+		for_each_pipe(dev_priv, pipe) {
+			enum intel_display_power_domain power_domain;
+
+			power_domain = POWER_DOMAIN_PIPE(pipe);
+			if (!intel_display_power_get_if_enabled(dev_priv,
+								power_domain)) {
+				seq_printf(m, "Pipe %c power disabled\n",
+					   pipe_name(pipe));
+				continue;
+			}
+
 			seq_printf(m, "Pipe %c stat:\t%08x\n",
 				   pipe_name(pipe),
 				   I915_READ(PIPESTAT(pipe)));
 
+			intel_display_power_put(dev_priv, power_domain);
+		}
+
+		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 		seq_printf(m, "Port hotplug:\t%08x\n",
 			   I915_READ(PORT_HOTPLUG_EN));
 		seq_printf(m, "DPFLIPSTAT:\t%08x\n",
 			   I915_READ(VLV_DPFLIPSTAT));
 		seq_printf(m, "DPINVGTT:\t%08x\n",
 			   I915_READ(DPINVGTT));
+		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
 		for (i = 0; i < 4; i++) {
 			seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
@@ -895,7 +895,7 @@ static int i915_interrupt_info(struct se
 		seq_printf(m, "Graphics Interrupt mask:		%08x\n",
 			   I915_READ(GTIMR));
 	}
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		if (INTEL_GEN(dev_priv) >= 6) {
 			seq_printf(m,
 				   "Graphics Interrupt mask (%s):	%08x\n",
@@ -935,26 +935,7 @@ static int i915_gem_fence_regs_info(stru
 	return 0;
 }
 
-static int i915_hws_info(struct seq_file *m, void *data)
-{
-	struct drm_info_node *node = m->private;
-	struct drm_i915_private *dev_priv = node_to_i915(node);
-	struct intel_engine_cs *engine;
-	const u32 *hws;
-	int i;
-
-	engine = &dev_priv->engine[(uintptr_t)node->info_ent->data];
-	hws = engine->status_page.page_addr;
-	if (hws == NULL)
-		return 0;
-
-	for (i = 0; i < 4096 / sizeof(u32) / 4; i += 4) {
-		seq_printf(m, "0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
-			   i * 4,
-			   hws[i], hws[i + 1], hws[i + 2], hws[i + 3]);
-	}
-	return 0;
-}
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
 
 static ssize_t
 i915_error_state_write(struct file *filp,
@@ -1038,19 +1019,14 @@ static const struct file_operations i915
 	.release = i915_error_state_release,
 };
 
+#endif
+
 static int
 i915_next_seqno_get(void *data, u64 *val)
 {
 	struct drm_i915_private *dev_priv = data;
-	int ret;
-
-	ret = mutex_lock_interruptible(&dev_priv->drm.struct_mutex);
-	if (ret)
-		return ret;
-
-	*val = dev_priv->next_seqno;
-	mutex_unlock(&dev_priv->drm.struct_mutex);
 
+	*val = 1 + atomic_read(&dev_priv->gt.global_timeline.next_seqno);
 	return 0;
 }
 
@@ -1065,7 +1041,7 @@ i915_next_seqno_set(void *data, u64 val)
 	if (ret)
 		return ret;
 
-	ret = i915_gem_set_seqno(dev, val);
+	ret = i915_gem_set_global_seqno(dev, val);
 	mutex_unlock(&dev->struct_mutex);
 
 	return ret;
@@ -1277,15 +1253,42 @@ out:
 	return ret;
 }
 
+static void i915_instdone_info(struct drm_i915_private *dev_priv,
+			       struct seq_file *m,
+			       struct intel_instdone *instdone)
+{
+	int slice;
+	int subslice;
+
+	seq_printf(m, "\t\tINSTDONE: 0x%08x\n",
+		   instdone->instdone);
+
+	if (INTEL_GEN(dev_priv) <= 3)
+		return;
+
+	seq_printf(m, "\t\tSC_INSTDONE: 0x%08x\n",
+		   instdone->slice_common);
+
+	if (INTEL_GEN(dev_priv) <= 6)
+		return;
+
+	for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+		seq_printf(m, "\t\tSAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
+			   slice, subslice, instdone->sampler[slice][subslice]);
+
+	for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+		seq_printf(m, "\t\tROW_INSTDONE[%d][%d]: 0x%08x\n",
+			   slice, subslice, instdone->row[slice][subslice]);
+}
+
 static int i915_hangcheck_info(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
 	struct intel_engine_cs *engine;
 	u64 acthd[I915_NUM_ENGINES];
 	u32 seqno[I915_NUM_ENGINES];
-	u32 instdone[I915_NUM_INSTDONE_REG];
+	struct intel_instdone instdone;
 	enum intel_engine_id id;
-	int j;
 
 	if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags))
 		seq_printf(m, "Wedged\n");
@@ -1303,12 +1306,12 @@ static int i915_hangcheck_info(struct se
 
 	intel_runtime_pm_get(dev_priv);
 
-	for_each_engine_id(engine, dev_priv, id) {
+	for_each_engine(engine, dev_priv, id) {
 		acthd[id] = intel_engine_get_active_head(engine);
 		seqno[id] = intel_engine_get_seqno(engine);
 	}
 
-	i915_get_extra_instdone(dev_priv, instdone);
+	intel_engine_get_instdone(dev_priv->engine[RCS], &instdone);
 
 	intel_runtime_pm_put(dev_priv);
 
@@ -1319,16 +1322,27 @@ static int i915_hangcheck_info(struct se
 	} else
 		seq_printf(m, "Hangcheck inactive\n");
 
-	for_each_engine_id(engine, dev_priv, id) {
+	for_each_engine(engine, dev_priv, id) {
+		struct intel_breadcrumbs *b = &engine->breadcrumbs;
+		struct rb_node *rb;
+
 		seq_printf(m, "%s:\n", engine->name);
 		seq_printf(m, "\tseqno = %x [current %x, last %x]\n",
-			   engine->hangcheck.seqno,
-			   seqno[id],
-			   engine->last_submitted_seqno);
+			   engine->hangcheck.seqno, seqno[id],
+			   intel_engine_last_submit(engine));
 		seq_printf(m, "\twaiters? %s, fake irq active? %s\n",
 			   yesno(intel_engine_has_waiter(engine)),
 			   yesno(test_bit(engine->id,
 					  &dev_priv->gpu_error.missed_irq_rings)));
+		spin_lock_irq(&b->lock);
+		for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
+			struct intel_wait *w = container_of(rb, typeof(*w), node);
+
+			seq_printf(m, "\t%s [%d] waiting for %x\n",
+				   w->tsk->comm, w->tsk->pid, w->seqno);
+		}
+		spin_unlock_irq(&b->lock);
+
 		seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n",
 			   (long long)engine->hangcheck.acthd,
 			   (long long)acthd[id]);
@@ -1336,18 +1350,14 @@ static int i915_hangcheck_info(struct se
 		seq_printf(m, "\taction = %d\n", engine->hangcheck.action);
 
 		if (engine->id == RCS) {
-			seq_puts(m, "\tinstdone read =");
-
-			for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
-				seq_printf(m, " 0x%08x", instdone[j]);
+			seq_puts(m, "\tinstdone read =\n");
 
-			seq_puts(m, "\n\tinstdone accu =");
+			i915_instdone_info(dev_priv, m, &instdone);
 
-			for (j = 0; j < I915_NUM_INSTDONE_REG; j++)
-				seq_printf(m, " 0x%08x",
-					   engine->hangcheck.instdone[j]);
+			seq_puts(m, "\tinstdone accu =\n");
 
-			seq_puts(m, "\n");
+			i915_instdone_info(dev_priv, m,
+					   &engine->hangcheck.instdone);
 		}
 	}
 
@@ -1357,14 +1367,9 @@ static int i915_hangcheck_info(struct se
 static int ironlake_drpc_info(struct seq_file *m)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
-	struct drm_device *dev = &dev_priv->drm;
 	u32 rgvmodectl, rstdbyctl;
 	u16 crstandvid;
-	int ret;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
 	intel_runtime_pm_get(dev_priv);
 
 	rgvmodectl = I915_READ(MEMMODECTL);
@@ -1372,7 +1377,6 @@ static int ironlake_drpc_info(struct seq
 	crstandvid = I915_READ16(CRSTANDVID);
 
 	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
 
 	seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
 	seq_printf(m, "Boost freq: %d\n",
@@ -1635,10 +1639,13 @@ static int i915_fbc_status(struct seq_fi
 		seq_printf(m, "FBC disabled: %s\n",
 			   dev_priv->fbc.no_fbc_reason);
 
-	if (INTEL_GEN(dev_priv) >= 7)
+	if (intel_fbc_is_active(dev_priv) && INTEL_GEN(dev_priv) >= 7) {
+		uint32_t mask = INTEL_GEN(dev_priv) >= 8 ?
+				BDW_FBC_COMPRESSION_MASK :
+				IVB_FBC_COMPRESSION_MASK;
 		seq_printf(m, "Compressing: %s\n",
-			   yesno(I915_READ(FBC_STATUS2) &
-				 FBC_COMPRESSION_MASK));
+			   yesno(I915_READ(FBC_STATUS2) & mask));
+	}
 
 	mutex_unlock(&dev_priv->fbc.lock);
 	intel_runtime_pm_put(dev_priv);
@@ -1717,6 +1724,7 @@ static int i915_sr_status(struct seq_fil
 	bool sr_enabled = false;
 
 	intel_runtime_pm_get(dev_priv);
+	intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
 	if (HAS_PCH_SPLIT(dev_priv))
 		sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
@@ -1730,10 +1738,10 @@ static int i915_sr_status(struct seq_fil
 	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 
+	intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 	intel_runtime_pm_put(dev_priv);
 
-	seq_printf(m, "self-refresh: %s\n",
-		   sr_enabled ? "enabled" : "disabled");
+	seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled));
 
 	return 0;
 }
@@ -1867,7 +1875,7 @@ static int i915_gem_framebuffer_info(str
 			   fbdev_fb->base.height,
 			   fbdev_fb->base.depth,
 			   fbdev_fb->base.bits_per_pixel,
-			   fbdev_fb->base.modifier[0],
+			   fbdev_fb->base.modifier,
 			   drm_framebuffer_read_refcount(&fbdev_fb->base));
 		describe_obj(m, fbdev_fb->obj);
 		seq_putc(m, '\n');
@@ -1885,7 +1893,7 @@ static int i915_gem_framebuffer_info(str
 			   fb->base.height,
 			   fb->base.depth,
 			   fb->base.bits_per_pixel,
-			   fb->base.modifier[0],
+			   fb->base.modifier,
 			   drm_framebuffer_read_refcount(&fb->base));
 		describe_obj(m, fb->obj);
 		seq_putc(m, '\n');
@@ -1909,6 +1917,7 @@ static int i915_context_status(struct se
 	struct drm_device *dev = &dev_priv->drm;
 	struct intel_engine_cs *engine;
 	struct i915_gem_context *ctx;
+	enum intel_engine_id id;
 	int ret;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1935,7 +1944,7 @@ static int i915_context_status(struct se
 		seq_putc(m, ctx->remap_slice ? 'R' : 'r');
 		seq_putc(m, '\n');
 
-		for_each_engine(engine, dev_priv) {
+		for_each_engine(engine, dev_priv, id) {
 			struct intel_context *ce = &ctx->engine[engine->id];
 
 			seq_printf(m, "%s: ", engine->name);
@@ -1974,7 +1983,7 @@ static void i915_dump_lrc_obj(struct seq
 		seq_printf(m, "\tBound in GGTT at 0x%08x\n",
 			   i915_ggtt_offset(vma));
 
-	if (i915_gem_object_get_pages(vma->obj)) {
+	if (i915_gem_object_pin_pages(vma->obj)) {
 		seq_puts(m, "\tFailed to get pages for context object\n\n");
 		return;
 	}
@@ -1993,6 +2002,7 @@ static void i915_dump_lrc_obj(struct seq
 		kunmap_atomic(reg_state);
 	}
 
+	i915_gem_object_unpin_pages(vma->obj);
 	seq_putc(m, '\n');
 }
 
@@ -2002,6 +2012,7 @@ static int i915_dump_lrc(struct seq_file
 	struct drm_device *dev = &dev_priv->drm;
 	struct intel_engine_cs *engine;
 	struct i915_gem_context *ctx;
+	enum intel_engine_id id;
 	int ret;
 
 	if (!i915.enable_execlists) {
@@ -2014,7 +2025,7 @@ static int i915_dump_lrc(struct seq_file
 		return ret;
 
 	list_for_each_entry(ctx, &dev_priv->context_list, link)
-		for_each_engine(engine, dev_priv)
+		for_each_engine(engine, dev_priv, id)
 			i915_dump_lrc_obj(m, ctx, engine);
 
 	mutex_unlock(&dev->struct_mutex);
@@ -2022,84 +2033,6 @@ static int i915_dump_lrc(struct seq_file
 	return 0;
 }
 
-static int i915_execlists(struct seq_file *m, void *data)
-{
-	struct drm_i915_private *dev_priv = node_to_i915(m->private);
-	struct drm_device *dev = &dev_priv->drm;
-	struct intel_engine_cs *engine;
-	u32 status_pointer;
-	u8 read_pointer;
-	u8 write_pointer;
-	u32 status;
-	u32 ctx_id;
-	struct list_head *cursor;
-	int i, ret;
-
-	if (!i915.enable_execlists) {
-		seq_puts(m, "Logical Ring Contexts are disabled\n");
-		return 0;
-	}
-
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
-
-	intel_runtime_pm_get(dev_priv);
-
-	for_each_engine(engine, dev_priv) {
-		struct drm_i915_gem_request *head_req = NULL;
-		int count = 0;
-
-		seq_printf(m, "%s\n", engine->name);
-
-		status = I915_READ(RING_EXECLIST_STATUS_LO(engine));
-		ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(engine));
-		seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n",
-			   status, ctx_id);
-
-		status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
-		seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer);
-
-		read_pointer = GEN8_CSB_READ_PTR(status_pointer);
-		write_pointer = GEN8_CSB_WRITE_PTR(status_pointer);
-		if (read_pointer > write_pointer)
-			write_pointer += GEN8_CSB_ENTRIES;
-		seq_printf(m, "\tRead pointer: 0x%08X, write pointer 0x%08X\n",
-			   read_pointer, write_pointer);
-
-		for (i = 0; i < GEN8_CSB_ENTRIES; i++) {
-			status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, i));
-			ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, i));
-
-			seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n",
-				   i, status, ctx_id);
-		}
-
-		spin_lock_bh(&engine->execlist_lock);
-		list_for_each(cursor, &engine->execlist_queue)
-			count++;
-		head_req = list_first_entry_or_null(&engine->execlist_queue,
-						    struct drm_i915_gem_request,
-						    execlist_link);
-		spin_unlock_bh(&engine->execlist_lock);
-
-		seq_printf(m, "\t%d requests in queue\n", count);
-		if (head_req) {
-			seq_printf(m, "\tHead request context: %u\n",
-				   head_req->ctx->hw_id);
-			seq_printf(m, "\tHead request tail: %u\n",
-				   head_req->tail);
-		}
-
-		seq_putc(m, '\n');
-	}
-
-	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
-
-	return 0;
-}
-
 static const char *swizzle_string(unsigned swizzle)
 {
 	switch (swizzle) {
@@ -2127,12 +2060,7 @@ static const char *swizzle_string(unsign
 static int i915_swizzle_info(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
-	struct drm_device *dev = &dev_priv->drm;
-	int ret;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
 	intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
@@ -2172,7 +2100,6 @@ static int i915_swizzle_info(struct seq_
 		seq_puts(m, "L-shaped memory detected\n");
 
 	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
 
 	return 0;
 }
@@ -2201,14 +2128,15 @@ static int per_file_ctx(int id, void *pt
 static void gen8_ppgtt_info(struct seq_file *m,
 			    struct drm_i915_private *dev_priv)
 {
-	struct intel_engine_cs *engine;
 	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int i;
 
 	if (!ppgtt)
 		return;
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		seq_printf(m, "%s\n", engine->name);
 		for (i = 0; i < 4; i++) {
 			u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i));
@@ -2223,11 +2151,12 @@ static void gen6_ppgtt_info(struct seq_f
 			    struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
 	if (IS_GEN6(dev_priv))
 		seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE));
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		seq_printf(m, "%s\n", engine->name);
 		if (IS_GEN7(dev_priv))
 			seq_printf(m, "GFX_MODE: 0x%08x\n",
@@ -2296,9 +2225,10 @@ out_unlock:
 static int count_irq_waiters(struct drm_i915_private *i915)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int count = 0;
 
-	for_each_engine(engine, i915)
+	for_each_engine(engine, i915, id)
 		count += intel_engine_has_waiter(engine);
 
 	return count;
@@ -2325,8 +2255,8 @@ static int i915_rps_boost_info(struct se
 	struct drm_file *file;
 
 	seq_printf(m, "RPS enabled? %d\n", dev_priv->rps.enabled);
-	seq_printf(m, "GPU busy? %s [%x]\n",
-		   yesno(dev_priv->gt.awake), dev_priv->gt.active_engines);
+	seq_printf(m, "GPU busy? %s [%d requests]\n",
+		   yesno(dev_priv->gt.awake), dev_priv->gt.active_requests);
 	seq_printf(m, "CPU waiting? %d\n", count_irq_waiters(dev_priv));
 	seq_printf(m, "Frequency requested %d\n",
 		   intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
@@ -2361,7 +2291,7 @@ static int i915_rps_boost_info(struct se
 
 	if (INTEL_GEN(dev_priv) >= 6 &&
 	    dev_priv->rps.enabled &&
-	    dev_priv->gt.active_engines) {
+	    dev_priv->gt.active_requests) {
 		u32 rpup, rpupei;
 		u32 rpdown, rpdownei;
 
@@ -2442,6 +2372,32 @@ static int i915_guc_load_status_info(str
 	return 0;
 }
 
+static void i915_guc_log_info(struct seq_file *m,
+			      struct drm_i915_private *dev_priv)
+{
+	struct intel_guc *guc = &dev_priv->guc;
+
+	seq_puts(m, "\nGuC logging stats:\n");
+
+	seq_printf(m, "\tISR:   flush count %10u, overflow count %10u\n",
+		   guc->log.flush_count[GUC_ISR_LOG_BUFFER],
+		   guc->log.total_overflow_count[GUC_ISR_LOG_BUFFER]);
+
+	seq_printf(m, "\tDPC:   flush count %10u, overflow count %10u\n",
+		   guc->log.flush_count[GUC_DPC_LOG_BUFFER],
+		   guc->log.total_overflow_count[GUC_DPC_LOG_BUFFER]);
+
+	seq_printf(m, "\tCRASH: flush count %10u, overflow count %10u\n",
+		   guc->log.flush_count[GUC_CRASH_DUMP_LOG_BUFFER],
+		   guc->log.total_overflow_count[GUC_CRASH_DUMP_LOG_BUFFER]);
+
+	seq_printf(m, "\tTotal flush interrupt count: %u\n",
+		   guc->log.flush_interrupt_count);
+
+	seq_printf(m, "\tCapture miss count: %u\n",
+		   guc->log.capture_miss_count);
+}
+
 static void i915_guc_client_info(struct seq_file *m,
 				 struct drm_i915_private *dev_priv,
 				 struct i915_guc_client *client)
@@ -2461,7 +2417,7 @@ static void i915_guc_client_info(struct
 	seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
 	seq_printf(m, "\tLast submission result: %d\n", client->retcode);
 
-	for_each_engine_id(engine, dev_priv, id) {
+	for_each_engine(engine, dev_priv, id) {
 		u64 submissions = client->submissions[id];
 		tot += submissions;
 		seq_printf(m, "\tSubmissions: %llu %s\n",
@@ -2504,7 +2460,7 @@ static int i915_guc_info(struct seq_file
 	seq_printf(m, "GuC last action error code: %d\n", guc.action_err);
 
 	seq_printf(m, "\nGuC submissions:\n");
-	for_each_engine_id(engine, dev_priv, id) {
+	for_each_engine(engine, dev_priv, id) {
 		u64 submissions = guc.submissions[id];
 		total += submissions;
 		seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n",
@@ -2515,6 +2471,8 @@ static int i915_guc_info(struct seq_file
 	seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client);
 	i915_guc_client_info(m, dev_priv, &client);
 
+	i915_guc_log_info(m, dev_priv);
+
 	/* Add more as required ... */
 
 	return 0;
@@ -2526,10 +2484,10 @@ static int i915_guc_log_dump(struct seq_
 	struct drm_i915_gem_object *obj;
 	int i = 0, pg;
 
-	if (!dev_priv->guc.log_vma)
+	if (!dev_priv->guc.log.vma)
 		return 0;
 
-	obj = dev_priv->guc.log_vma->obj;
+	obj = dev_priv->guc.log.vma->obj;
 	for (pg = 0; pg < obj->base.size / PAGE_SIZE; pg++) {
 		u32 *log = kmap_atomic(i915_gem_object_get_page(obj, pg));
 
@@ -2546,6 +2504,44 @@ static int i915_guc_log_dump(struct seq_
 	return 0;
 }
 
+static int i915_guc_log_control_get(void *data, u64 *val)
+{
+	struct drm_device *dev = data;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	if (!dev_priv->guc.log.vma)
+		return -EINVAL;
+
+	*val = i915.guc_log_level;
+
+	return 0;
+}
+
+static int i915_guc_log_control_set(void *data, u64 val)
+{
+	struct drm_device *dev = data;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	int ret;
+
+	if (!dev_priv->guc.log.vma)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	intel_runtime_pm_get(dev_priv);
+	ret = i915_guc_log_control(dev_priv, val);
+	intel_runtime_pm_put(dev_priv);
+
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_guc_log_control_fops,
+			i915_guc_log_control_get, i915_guc_log_control_set,
+			"%lld\n");
+
 static int i915_edp_psr_status(struct seq_file *m, void *data)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -2575,11 +2571,22 @@ static int i915_edp_psr_status(struct se
 		enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
 	else {
 		for_each_pipe(dev_priv, pipe) {
+			enum transcoder cpu_transcoder =
+				intel_pipe_to_cpu_transcoder(dev_priv, pipe);
+			enum intel_display_power_domain power_domain;
+
+			power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+			if (!intel_display_power_get_if_enabled(dev_priv,
+								power_domain))
+				continue;
+
 			stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) &
 				VLV_EDP_PSR_CURR_STATE_MASK;
 			if ((stat[pipe] == VLV_EDP_PSR_ACTIVE_NORFB_UP) ||
 			    (stat[pipe] == VLV_EDP_PSR_ACTIVE_SF_UPDATE))
 				enabled = true;
+
+			intel_display_power_put(dev_priv, power_domain);
 		}
 	}
 
@@ -3004,7 +3011,7 @@ static void intel_plane_info(struct seq_
 	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
 		struct drm_plane_state *state;
 		struct drm_plane *plane = &intel_plane->base;
-		char *format_name;
+		struct drm_format_name_buf format_name;
 
 		if (!plane->state) {
 			seq_puts(m, "plane->state is NULL!\n");
@@ -3014,9 +3021,9 @@ static void intel_plane_info(struct seq_
 		state = plane->state;
 
 		if (state->fb) {
-			format_name = drm_get_format_name(state->fb->pixel_format);
+			drm_get_format_name(state->fb->pixel_format, &format_name);
 		} else {
-			format_name = kstrdup("N/A", GFP_KERNEL);
+			sprintf(format_name.str, "N/A");
 		}
 
 		seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n",
@@ -3032,10 +3039,8 @@ static void intel_plane_info(struct seq_
 			   ((state->src_w & 0xffff) * 15625) >> 10,
 			   (state->src_h >> 16),
 			   ((state->src_h & 0xffff) * 15625) >> 10,
-			   format_name,
+			   format_name.str,
 			   plane_rotation(state->rotation));
-
-		kfree(format_name);
 	}
 }
 
@@ -3121,6 +3126,146 @@ static int i915_display_info(struct seq_
 	return 0;
 }
 
+static int i915_engine_info(struct seq_file *m, void *unused)
+{
+	struct drm_i915_private *dev_priv = node_to_i915(m->private);
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	intel_runtime_pm_get(dev_priv);
+
+	for_each_engine(engine, dev_priv, id) {
+		struct intel_breadcrumbs *b = &engine->breadcrumbs;
+		struct drm_i915_gem_request *rq;
+		struct rb_node *rb;
+		u64 addr;
+
+		seq_printf(m, "%s\n", engine->name);
+		seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [score %d]\n",
+			   intel_engine_get_seqno(engine),
+			   intel_engine_last_submit(engine),
+			   engine->hangcheck.seqno,
+			   engine->hangcheck.score);
+
+		rcu_read_lock();
+
+		seq_printf(m, "\tRequests:\n");
+
+		rq = list_first_entry(&engine->timeline->requests,
+				      struct drm_i915_gem_request, link);
+		if (&rq->link != &engine->timeline->requests)
+			print_request(m, rq, "\t\tfirst  ");
+
+		rq = list_last_entry(&engine->timeline->requests,
+				     struct drm_i915_gem_request, link);
+		if (&rq->link != &engine->timeline->requests)
+			print_request(m, rq, "\t\tlast   ");
+
+		rq = i915_gem_find_active_request(engine);
+		if (rq) {
+			print_request(m, rq, "\t\tactive ");
+			seq_printf(m,
+				   "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n",
+				   rq->head, rq->postfix, rq->tail,
+				   rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u,
+				   rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u);
+		}
+
+		seq_printf(m, "\tRING_START: 0x%08x [0x%08x]\n",
+			   I915_READ(RING_START(engine->mmio_base)),
+			   rq ? i915_ggtt_offset(rq->ring->vma) : 0);
+		seq_printf(m, "\tRING_HEAD:  0x%08x [0x%08x]\n",
+			   I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR,
+			   rq ? rq->ring->head : 0);
+		seq_printf(m, "\tRING_TAIL:  0x%08x [0x%08x]\n",
+			   I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR,
+			   rq ? rq->ring->tail : 0);
+		seq_printf(m, "\tRING_CTL:   0x%08x [%s]\n",
+			   I915_READ(RING_CTL(engine->mmio_base)),
+			   I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : "");
+
+		rcu_read_unlock();
+
+		addr = intel_engine_get_active_head(engine);
+		seq_printf(m, "\tACTHD:  0x%08x_%08x\n",
+			   upper_32_bits(addr), lower_32_bits(addr));
+		addr = intel_engine_get_last_batch_head(engine);
+		seq_printf(m, "\tBBADDR: 0x%08x_%08x\n",
+			   upper_32_bits(addr), lower_32_bits(addr));
+
+		if (i915.enable_execlists) {
+			u32 ptr, read, write;
+			struct rb_node *rb;
+
+			seq_printf(m, "\tExeclist status: 0x%08x %08x\n",
+				   I915_READ(RING_EXECLIST_STATUS_LO(engine)),
+				   I915_READ(RING_EXECLIST_STATUS_HI(engine)));
+
+			ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine));
+			read = GEN8_CSB_READ_PTR(ptr);
+			write = GEN8_CSB_WRITE_PTR(ptr);
+			seq_printf(m, "\tExeclist CSB read %d, write %d\n",
+				   read, write);
+			if (read >= GEN8_CSB_ENTRIES)
+				read = 0;
+			if (write >= GEN8_CSB_ENTRIES)
+				write = 0;
+			if (read > write)
+				write += GEN8_CSB_ENTRIES;
+			while (read < write) {
+				unsigned int idx = ++read % GEN8_CSB_ENTRIES;
+
+				seq_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n",
+					   idx,
+					   I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)),
+					   I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)));
+			}
+
+			rcu_read_lock();
+			rq = READ_ONCE(engine->execlist_port[0].request);
+			if (rq)
+				print_request(m, rq, "\t\tELSP[0] ");
+			else
+				seq_printf(m, "\t\tELSP[0] idle\n");
+			rq = READ_ONCE(engine->execlist_port[1].request);
+			if (rq)
+				print_request(m, rq, "\t\tELSP[1] ");
+			else
+				seq_printf(m, "\t\tELSP[1] idle\n");
+			rcu_read_unlock();
+
+			spin_lock_irq(&engine->timeline->lock);
+			for (rb = engine->execlist_first; rb; rb = rb_next(rb)) {
+				rq = rb_entry(rb, typeof(*rq), priotree.node);
+				print_request(m, rq, "\t\tQ ");
+			}
+			spin_unlock_irq(&engine->timeline->lock);
+		} else if (INTEL_GEN(dev_priv) > 6) {
+			seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n",
+				   I915_READ(RING_PP_DIR_BASE(engine)));
+			seq_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n",
+				   I915_READ(RING_PP_DIR_BASE_READ(engine)));
+			seq_printf(m, "\tPP_DIR_DCLV: 0x%08x\n",
+				   I915_READ(RING_PP_DIR_DCLV(engine)));
+		}
+
+		spin_lock_irq(&b->lock);
+		for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) {
+			struct intel_wait *w = container_of(rb, typeof(*w), node);
+
+			seq_printf(m, "\t%s [%d] waiting for %x\n",
+				   w->tsk->comm, w->tsk->pid, w->seqno);
+		}
+		spin_unlock_irq(&b->lock);
+
+		seq_puts(m, "\n");
+	}
+
+	intel_runtime_pm_put(dev_priv);
+
+	return 0;
+}
+
 static int i915_semaphore_status(struct seq_file *m, void *unused)
 {
 	struct drm_i915_private *dev_priv = node_to_i915(m->private);
@@ -3147,7 +3292,7 @@ static int i915_semaphore_status(struct
 		page = i915_gem_object_get_page(dev_priv->semaphore->obj, 0);
 
 		seqno = (uint64_t *)kmap_atomic(page);
-		for_each_engine_id(engine, dev_priv, id) {
+		for_each_engine(engine, dev_priv, id) {
 			uint64_t offset;
 
 			seq_printf(m, "%s\n", engine->name);
@@ -3172,22 +3317,13 @@ static int i915_semaphore_status(struct
 		kunmap_atomic(seqno);
 	} else {
 		seq_puts(m, "  Last signal:");
-		for_each_engine(engine, dev_priv)
+		for_each_engine(engine, dev_priv, id)
 			for (j = 0; j < num_rings; j++)
 				seq_printf(m, "0x%08x\n",
 					   I915_READ(engine->semaphore.mbox.signal[j]));
 		seq_putc(m, '\n');
 	}
 
-	seq_puts(m, "\nSync seqno:\n");
-	for_each_engine(engine, dev_priv) {
-		for (j = 0; j < num_rings; j++)
-			seq_printf(m, "  0x%08x ",
-				   engine->semaphore.sync_seqno[j]);
-		seq_putc(m, '\n');
-	}
-	seq_putc(m, '\n');
-
 	intel_runtime_pm_put(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 	return 0;
@@ -3236,7 +3372,7 @@ static int i915_wa_registers(struct seq_
 	intel_runtime_pm_get(dev_priv);
 
 	seq_printf(m, "Workarounds applied: %d\n", workarounds->count);
-	for_each_engine_id(engine, dev_priv, id)
+	for_each_engine(engine, dev_priv, id)
 		seq_printf(m, "HW whitelist count for %s: %d\n",
 			   engine->name, workarounds->hw_whitelist_count[id]);
 	for (i = 0; i < workarounds->count; ++i) {
@@ -3280,7 +3416,7 @@ static int i915_ddb_info(struct seq_file
 	for_each_pipe(dev_priv, pipe) {
 		seq_printf(m, "Pipe %c\n", pipe_name(pipe));
 
-		for_each_plane(dev_priv, pipe, plane) {
+		for_each_universal_plane(dev_priv, pipe, plane) {
 			entry = &ddb->plane[pipe][plane];
 			seq_printf(m, "  Plane%-8d%8u%8u%8u\n", plane + 1,
 				   entry->start, entry->end,
@@ -3914,8 +4050,7 @@ static void hsw_trans_edp_pipe_A_crc_wa(
 					bool enable)
 {
 	struct drm_device *dev = &dev_priv->drm;
-	struct intel_crtc *crtc =
-		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[PIPE_A]);
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
 	struct intel_crtc_state *pipe_config;
 	struct drm_atomic_state *state;
 	int ret = 0;
@@ -3941,10 +4076,9 @@ static void hsw_trans_edp_pipe_A_crc_wa(
 
 	ret = drm_atomic_commit(state);
 out:
-	drm_modeset_unlock_all(dev);
 	WARN(ret, "Toggling workaround to %i returns %i\n", enable, ret);
-	if (ret)
-		drm_atomic_state_free(state);
+	drm_modeset_unlock_all(dev);
+	drm_atomic_state_put(state);
 }
 
 static int ivb_pipe_crc_ctl_reg(struct drm_i915_private *dev_priv,
@@ -3982,10 +4116,8 @@ static int pipe_crc_set_source(struct dr
 			       enum pipe pipe,
 			       enum intel_pipe_crc_source source)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
-	struct intel_crtc *crtc =
-			to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 	enum intel_display_power_domain power_domain;
 	u32 val = 0; /* shut up gcc */
 	int ret;
@@ -4056,15 +4188,15 @@ static int pipe_crc_set_source(struct dr
 	/* real source -> none transition */
 	if (source == INTEL_PIPE_CRC_SOURCE_NONE) {
 		struct intel_pipe_crc_entry *entries;
-		struct intel_crtc *crtc =
-			to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+		struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
+								  pipe);
 
 		DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n",
 				 pipe_name(pipe));
 
 		drm_modeset_lock(&crtc->base.mutex, NULL);
 		if (crtc->base.state->active)
-			intel_wait_for_vblank(dev, pipe);
+			intel_wait_for_vblank(dev_priv, pipe);
 		drm_modeset_unlock(&crtc->base.mutex);
 
 		spin_lock_irq(&pipe_crc->lock);
@@ -4463,7 +4595,7 @@ static void wm_latency_show(struct seq_f
 	else if (IS_VALLEYVIEW(dev_priv))
 		num_levels = 1;
 	else
-		num_levels = ilk_wm_max_level(dev) + 1;
+		num_levels = ilk_wm_max_level(dev_priv) + 1;
 
 	drm_modeset_lock_all(dev);
 
@@ -4579,7 +4711,7 @@ static ssize_t wm_latency_write(struct f
 	else if (IS_VALLEYVIEW(dev_priv))
 		num_levels = 1;
 	else
-		num_levels = ilk_wm_max_level(dev) + 1;
+		num_levels = ilk_wm_max_level(dev_priv) + 1;
 
 	if (len >= sizeof(tmp))
 		return -EINVAL;
@@ -4704,13 +4836,9 @@ i915_wedged_set(void *data, u64 val)
 	if (i915_reset_in_progress(&dev_priv->gpu_error))
 		return -EAGAIN;
 
-	intel_runtime_pm_get(dev_priv);
-
 	i915_handle_error(dev_priv, val,
 			  "Manually setting wedged to %llu", val);
 
-	intel_runtime_pm_put(dev_priv);
-
 	return 0;
 }
 
@@ -4778,10 +4906,12 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_test_i
 #define DROP_BOUND 0x2
 #define DROP_RETIRE 0x4
 #define DROP_ACTIVE 0x8
-#define DROP_ALL (DROP_UNBOUND | \
-		  DROP_BOUND | \
-		  DROP_RETIRE | \
-		  DROP_ACTIVE)
+#define DROP_FREED 0x10
+#define DROP_ALL (DROP_UNBOUND	| \
+		  DROP_BOUND	| \
+		  DROP_RETIRE	| \
+		  DROP_ACTIVE	| \
+		  DROP_FREED)
 static int
 i915_drop_caches_get(void *data, u64 *val)
 {
@@ -4825,6 +4955,11 @@ i915_drop_caches_set(void *data, u64 val
 unlock:
 	mutex_unlock(&dev->struct_mutex);
 
+	if (val & DROP_FREED) {
+		synchronize_rcu();
+		flush_work(&dev_priv->mm.free_work);
+	}
+
 	return ret;
 }
 
@@ -4945,22 +5080,16 @@ static int
 i915_cache_sharing_get(void *data, u64 *val)
 {
 	struct drm_i915_private *dev_priv = data;
-	struct drm_device *dev = &dev_priv->drm;
 	u32 snpcr;
-	int ret;
 
 	if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv)))
 		return -ENODEV;
 
-	ret = mutex_lock_interruptible(&dev->struct_mutex);
-	if (ret)
-		return ret;
 	intel_runtime_pm_get(dev_priv);
 
 	snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 
 	intel_runtime_pm_put(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
 
 	*val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
@@ -5253,10 +5382,6 @@ static const struct drm_info_list i915_d
 	{"i915_gem_seqno", i915_gem_seqno_info, 0},
 	{"i915_gem_fence_regs", i915_gem_fence_regs_info, 0},
 	{"i915_gem_interrupt", i915_interrupt_info, 0},
-	{"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
-	{"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
-	{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
-	{"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS},
 	{"i915_gem_batch_pool", i915_gem_batch_pool_info, 0},
 	{"i915_guc_info", i915_guc_info, 0},
 	{"i915_guc_load_status", i915_guc_load_status_info, 0},
@@ -5275,7 +5400,6 @@ static const struct drm_info_list i915_d
 	{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
 	{"i915_context_status", i915_context_status, 0},
 	{"i915_dump_lrc", i915_dump_lrc, 0},
-	{"i915_execlists", i915_execlists, 0},
 	{"i915_forcewake_domains", i915_forcewake_domains, 0},
 	{"i915_swizzle_info", i915_swizzle_info, 0},
 	{"i915_ppgtt_info", i915_ppgtt_info, 0},
@@ -5287,6 +5411,7 @@ static const struct drm_info_list i915_d
 	{"i915_power_domain_info", i915_power_domain_info, 0},
 	{"i915_dmc_info", i915_dmc_info, 0},
 	{"i915_display_info", i915_display_info, 0},
+	{"i915_engine_info", i915_engine_info, 0},
 	{"i915_semaphore_status", i915_semaphore_status, 0},
 	{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
 	{"i915_dp_mst_info", i915_dp_mst_info, 0},
@@ -5309,7 +5434,9 @@ static const struct i915_debugfs_files {
 	{"i915_ring_missed_irq", &i915_ring_missed_irq_fops},
 	{"i915_ring_test_irq", &i915_ring_test_irq_fops},
 	{"i915_gem_drop_caches", &i915_drop_caches_fops},
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
 	{"i915_error_state", &i915_error_state_fops},
+#endif
 	{"i915_next_seqno", &i915_next_seqno_fops},
 	{"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
 	{"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
@@ -5318,7 +5445,8 @@ static const struct i915_debugfs_files {
 	{"i915_fbc_false_color", &i915_fbc_fc_fops},
 	{"i915_dp_test_data", &i915_displayport_test_data_fops},
 	{"i915_dp_test_type", &i915_displayport_test_type_fops},
-	{"i915_dp_test_active", &i915_displayport_test_active_fops}
+	{"i915_dp_test_active", &i915_displayport_test_active_fops},
+	{"i915_guc_log_control", &i915_guc_log_control_fops}
 };
 
 void intel_display_crc_init(struct drm_i915_private *dev_priv)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,7 +114,7 @@ static bool i915_error_injected(struct d
 		      fmt, ##__VA_ARGS__)
 
 
-static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
+static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv)
 {
 	enum intel_pch ret = PCH_NOP;
 
@@ -125,16 +125,16 @@ static enum intel_pch intel_virt_detect_
 	 * make an educated guess as to which PCH is really there.
 	 */
 
-	if (IS_GEN5(dev)) {
+	if (IS_GEN5(dev_priv)) {
 		ret = PCH_IBX;
 		DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n");
-	} else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) {
+	} else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) {
 		ret = PCH_CPT;
 		DRM_DEBUG_KMS("Assuming CouarPoint PCH\n");
-	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		ret = PCH_LPT;
 		DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
-	} else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
 		ret = PCH_SPT;
 		DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
 	}
@@ -150,7 +150,7 @@ static void intel_detect_pch(struct drm_
 	/* In all current cases, num_pipes is equivalent to the PCH_NOP setting
 	 * (which really amounts to a PCH but no South Display).
 	 */
-	if (INTEL_INFO(dev)->num_pipes == 0) {
+	if (INTEL_INFO(dev_priv)->num_pipes == 0) {
 		dev_priv->pch_type = PCH_NOP;
 		return;
 	}
@@ -174,40 +174,47 @@ static void intel_detect_pch(struct drm_
 			if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_IBX;
 				DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
-				WARN_ON(!IS_GEN5(dev));
+				WARN_ON(!IS_GEN5(dev_priv));
 			} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_CPT;
 				DRM_DEBUG_KMS("Found CougarPoint PCH\n");
-				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
+				WARN_ON(!(IS_GEN6(dev_priv) ||
+					IS_IVYBRIDGE(dev_priv)));
 			} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
 				/* PantherPoint is CPT compatible */
 				dev_priv->pch_type = PCH_CPT;
 				DRM_DEBUG_KMS("Found PantherPoint PCH\n");
-				WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
+				WARN_ON(!(IS_GEN6(dev_priv) ||
+					IS_IVYBRIDGE(dev_priv)));
 			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_LPT;
 				DRM_DEBUG_KMS("Found LynxPoint PCH\n");
-				WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
-				WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev));
+				WARN_ON(!IS_HASWELL(dev_priv) &&
+					!IS_BROADWELL(dev_priv));
+				WARN_ON(IS_HSW_ULT(dev_priv) ||
+					IS_BDW_ULT(dev_priv));
 			} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_LPT;
 				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
-				WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev));
-				WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev));
+				WARN_ON(!IS_HASWELL(dev_priv) &&
+					!IS_BROADWELL(dev_priv));
+				WARN_ON(!IS_HSW_ULT(dev_priv) &&
+					!IS_BDW_ULT(dev_priv));
 			} else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_SPT;
 				DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
-				WARN_ON(!IS_SKYLAKE(dev) &&
-					!IS_KABYLAKE(dev));
+				WARN_ON(!IS_SKYLAKE(dev_priv) &&
+					!IS_KABYLAKE(dev_priv));
 			} else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_SPT;
 				DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
-				WARN_ON(!IS_SKYLAKE(dev) &&
-					!IS_KABYLAKE(dev));
+				WARN_ON(!IS_SKYLAKE(dev_priv) &&
+					!IS_KABYLAKE(dev_priv));
 			} else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) {
 				dev_priv->pch_type = PCH_KBP;
 				DRM_DEBUG_KMS("Found KabyPoint PCH\n");
-				WARN_ON(!IS_KABYLAKE(dev));
+				WARN_ON(!IS_SKYLAKE(dev_priv) &&
+					!IS_KABYLAKE(dev_priv));
 			} else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) ||
 				   (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) ||
 				   ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) &&
@@ -215,7 +222,8 @@ static void intel_detect_pch(struct drm_
 					    PCI_SUBVENDOR_ID_REDHAT_QUMRANET &&
 				    pch->subsystem_device ==
 					    PCI_SUBDEVICE_ID_QEMU)) {
-				dev_priv->pch_type = intel_virt_detect_pch(dev);
+				dev_priv->pch_type =
+					intel_virt_detect_pch(dev_priv);
 			} else
 				continue;
 
@@ -255,16 +263,16 @@ static int i915_getparam(struct drm_devi
 		value = dev_priv->overlay ? 1 : 0;
 		break;
 	case I915_PARAM_HAS_BSD:
-		value = intel_engine_initialized(&dev_priv->engine[VCS]);
+		value = !!dev_priv->engine[VCS];
 		break;
 	case I915_PARAM_HAS_BLT:
-		value = intel_engine_initialized(&dev_priv->engine[BCS]);
+		value = !!dev_priv->engine[BCS];
 		break;
 	case I915_PARAM_HAS_VEBOX:
-		value = intel_engine_initialized(&dev_priv->engine[VECS]);
+		value = !!dev_priv->engine[VECS];
 		break;
 	case I915_PARAM_HAS_BSD2:
-		value = intel_engine_initialized(&dev_priv->engine[VCS2]);
+		value = !!dev_priv->engine[VCS2];
 		break;
 	case I915_PARAM_HAS_EXEC_CONSTANTS:
 		value = INTEL_GEN(dev_priv) >= 4;
@@ -316,6 +324,10 @@ static int i915_getparam(struct drm_devi
 		 */
 		value = i915_gem_mmap_gtt_version();
 		break;
+	case I915_PARAM_HAS_SCHEDULER:
+		value = dev_priv->engine[RCS] &&
+			dev_priv->engine[RCS]->schedule;
+		break;
 	case I915_PARAM_MMAP_VERSION:
 		/* Remember to bump this if the version changes! */
 	case I915_PARAM_HAS_GEM:
@@ -367,12 +379,12 @@ static int
 intel_alloc_mchbar_resource(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
+	int reg = INTEL_GEN(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
 	u32 temp_lo, temp_hi = 0;
 	u64 mchbar_addr;
 	int ret;
 
-	if (INTEL_INFO(dev)->gen >= 4)
+	if (INTEL_GEN(dev_priv) >= 4)
 		pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
 	pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
 	mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
@@ -399,7 +411,7 @@ intel_alloc_mchbar_resource(struct drm_d
 		return ret;
 	}
 
-	if (INTEL_INFO(dev)->gen >= 4)
+	if (INTEL_GEN(dev_priv) >= 4)
 		pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
 				       upper_32_bits(dev_priv->mch_res.start));
 
@@ -413,16 +425,16 @@ static void
 intel_setup_mchbar(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
+	int mchbar_reg = INTEL_GEN(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
 	u32 temp;
 	bool enabled;
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		return;
 
 	dev_priv->mchbar_need_disable = false;
 
-	if (IS_I915G(dev) || IS_I915GM(dev)) {
+	if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
 		pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp);
 		enabled = !!(temp & DEVEN_MCHBAR_EN);
 	} else {
@@ -440,7 +452,7 @@ intel_setup_mchbar(struct drm_device *de
 	dev_priv->mchbar_need_disable = true;
 
 	/* Space is allocated or reserved, so enable it. */
-	if (IS_I915G(dev) || IS_I915GM(dev)) {
+	if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
 		pci_write_config_dword(dev_priv->bridge_dev, DEVEN,
 				       temp | DEVEN_MCHBAR_EN);
 	} else {
@@ -453,10 +465,10 @@ static void
 intel_teardown_mchbar(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
+	int mchbar_reg = INTEL_GEN(dev_priv) >= 4 ? MCHBAR_I965 : MCHBAR_I915;
 
 	if (dev_priv->mchbar_need_disable) {
-		if (IS_I915G(dev) || IS_I915GM(dev)) {
+		if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
 			u32 deven_val;
 
 			pci_read_config_dword(dev_priv->bridge_dev, DEVEN,
@@ -484,7 +496,7 @@ static unsigned int i915_vga_set_decode(
 {
 	struct drm_device *dev = cookie;
 
-	intel_modeset_vga_set_state(dev, state);
+	intel_modeset_vga_set_state(to_i915(dev), state);
 	if (state)
 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
 		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
@@ -530,40 +542,17 @@ static const struct vga_switcheroo_clien
 	.can_switch = i915_switcheroo_can_switch,
 };
 
-static void i915_gem_fini(struct drm_device *dev)
+static void i915_gem_fini(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	/*
-	 * Neither the BIOS, ourselves or any other kernel
-	 * expects the system to be in execlists mode on startup,
-	 * so we need to reset the GPU back to legacy mode. And the only
-	 * known way to disable logical contexts is through a GPU reset.
-	 *
-	 * So in order to leave the system in a known default configuration,
-	 * always reset the GPU upon unload. Afterwards we then clean up the
-	 * GEM state tracking, flushing off the requests and leaving the
-	 * system in a known idle state.
-	 *
-	 * Note that is of the upmost importance that the GPU is idle and
-	 * all stray writes are flushed *before* we dismantle the backing
-	 * storage for the pinned objects.
-	 *
-	 * However, since we are uncertain that reseting the GPU on older
-	 * machines is a good idea, we don't - just in case it leaves the
-	 * machine in an unusable condition.
-	 */
-	if (HAS_HW_CONTEXTS(dev)) {
-		int reset = intel_gpu_reset(dev_priv, ALL_ENGINES);
-		WARN_ON(reset && reset != -ENODEV);
-	}
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	i915_gem_cleanup_engines(&dev_priv->drm);
+	i915_gem_context_fini(&dev_priv->drm);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 
-	mutex_lock(&dev->struct_mutex);
-	i915_gem_cleanup_engines(dev);
-	i915_gem_context_fini(dev);
-	mutex_unlock(&dev->struct_mutex);
+	rcu_barrier();
+	flush_work(&dev_priv->mm.free_work);
 
-	WARN_ON(!list_empty(&to_i915(dev)->context_list));
+	WARN_ON(!list_empty(&dev_priv->context_list));
 }
 
 static int i915_load_modeset_init(struct drm_device *dev)
@@ -611,7 +600,9 @@ static int i915_load_modeset_init(struct
 
 	/* Important: The output setup functions called by modeset_init need
 	 * working irqs for e.g. gmbus and dp aux transfers. */
-	intel_modeset_init(dev);
+	ret = intel_modeset_init(dev);
+	if (ret)
+		goto cleanup_irq;
 
 	intel_guc_init(dev);
 
@@ -621,7 +612,7 @@ static int i915_load_modeset_init(struct
 
 	intel_modeset_gem_init(dev);
 
-	if (INTEL_INFO(dev)->num_pipes == 0)
+	if (INTEL_INFO(dev_priv)->num_pipes == 0)
 		return 0;
 
 	ret = intel_fbdev_init(dev);
@@ -636,7 +627,9 @@ static int i915_load_modeset_init(struct
 	return 0;
 
 cleanup_gem:
-	i915_gem_fini(dev);
+	if (i915_gem_suspend(dev))
+		DRM_ERROR("failed to idle hardware; continuing to unload!\n");
+	i915_gem_fini(dev_priv);
 cleanup_irq:
 	intel_guc_fini(dev);
 	drm_irq_uninstall(dev);
@@ -771,6 +764,19 @@ static void i915_workqueues_cleanup(stru
 	destroy_workqueue(dev_priv->wq);
 }
 
+/*
+ * We don't keep the workarounds for pre-production hardware, so we expect our
+ * driver to fail on these machines in one way or another. A little warning on
+ * dmesg may help both the user and the bug triagers.
+ */
+static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv)
+{
+	if (IS_HSW_EARLY_SDV(dev_priv) ||
+	    IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
+		DRM_ERROR("This is a pre-production stepping. "
+			  "It may not be fully functional.\n");
+}
+
 /**
  * i915_driver_init_early - setup state not requiring device access
  * @dev_priv: device private
@@ -829,25 +835,24 @@ static int i915_driver_init_early(struct
 	intel_init_dpio(dev_priv);
 	intel_power_domains_init(dev_priv);
 	intel_irq_init(dev_priv);
+	intel_hangcheck_init(dev_priv);
 	intel_init_display_hooks(dev_priv);
 	intel_init_clock_gating_hooks(dev_priv);
 	intel_init_audio_hooks(dev_priv);
-	i915_gem_load_init(&dev_priv->drm);
+	ret = i915_gem_load_init(&dev_priv->drm);
+	if (ret < 0)
+		goto err_gvt;
 
 	intel_display_crc_init(dev_priv);
 
 	intel_device_info_dump(dev_priv);
 
-	/* Not all pre-production machines fall into this category, only the
-	 * very first ones. Almost everything should work, except for maybe
-	 * suspend/resume. And we don't implement workarounds that affect only
-	 * pre-production machines. */
-	if (IS_HSW_EARLY_SDV(dev_priv))
-		DRM_INFO("This is an early pre-production Haswell machine. "
-			 "It may not be fully functional.\n");
+	intel_detect_preproduction_hw(dev_priv);
 
 	return 0;
 
+err_gvt:
+	intel_gvt_cleanup(dev_priv);
 err_workqueues:
 	i915_workqueues_cleanup(dev_priv);
 	return ret;
@@ -870,7 +875,7 @@ static int i915_mmio_setup(struct drm_de
 	int mmio_bar;
 	int mmio_size;
 
-	mmio_bar = IS_GEN2(dev) ? 1 : 0;
+	mmio_bar = IS_GEN2(dev_priv) ? 1 : 0;
 	/*
 	 * Before gen4, the registers and the GTT are behind different BARs.
 	 * However, from gen4 onwards, the registers and the GTT are shared
@@ -879,7 +884,7 @@ static int i915_mmio_setup(struct drm_de
 	 * the register BAR remains the same size for all the earlier
 	 * generations up to Ironlake.
 	 */
-	if (INTEL_INFO(dev)->gen < 5)
+	if (INTEL_GEN(dev_priv) < 5)
 		mmio_size = 512 * 1024;
 	else
 		mmio_size = 2 * 1024 * 1024;
@@ -982,7 +987,6 @@ static void intel_sanitize_options(struc
 static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
-	struct drm_device *dev = &dev_priv->drm;
 	int ret;
 
 	if (i915_inject_load_failure())
@@ -1023,7 +1027,7 @@ static int i915_driver_init_hw(struct dr
 	pci_set_master(pdev);
 
 	/* overlay on gen2 is broken and can't address above 1G */
-	if (IS_GEN2(dev)) {
+	if (IS_GEN2(dev_priv)) {
 		ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30));
 		if (ret) {
 			DRM_ERROR("failed to set DMA mask\n");
@@ -1040,7 +1044,7 @@ static int i915_driver_init_hw(struct dr
 	 * behaviour if any general state is accessed within a page above 4GB,
 	 * which also needs to be handled carefully.
 	 */
-	if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) {
+	if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv)) {
 		ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 
 		if (ret) {
@@ -1070,7 +1074,7 @@ static int i915_driver_init_hw(struct dr
 	 * be lost or delayed, but we use them anyways to avoid
 	 * stuck interrupts on some machines.
 	 */
-	if (!IS_I945G(dev) && !IS_I945GM(dev)) {
+	if (!IS_I945G(dev_priv) && !IS_I945GM(dev_priv)) {
 		if (pci_enable_msi(pdev) < 0)
 			DRM_DEBUG_DRIVER("can't enable MSI");
 	}
@@ -1121,6 +1125,7 @@ static void i915_driver_register(struct
 	/* Reveal our presence to userspace */
 	if (drm_dev_register(dev, 0) == 0) {
 		i915_debugfs_register(dev_priv);
+		i915_guc_register(dev_priv);
 		i915_setup_sysfs(dev_priv);
 	} else
 		DRM_ERROR("Failed to register driver for userspace access!\n");
@@ -1159,6 +1164,7 @@ static void i915_driver_unregister(struc
 	intel_opregion_unregister(dev_priv);
 
 	i915_teardown_sysfs(dev_priv);
+	i915_guc_unregister(dev_priv);
 	i915_debugfs_unregister(dev_priv);
 	drm_dev_unregister(&dev_priv->drm);
 
@@ -1167,8 +1173,8 @@ static void i915_driver_unregister(struc
 
 /**
  * i915_driver_load - setup chip and create an initial config
- * @dev: DRM device
- * @flags: startup flags
+ * @pdev: PCI device
+ * @ent: matching PCI ID entry
  *
  * The driver load routine has to do several things:
  *   - drive output discovery via intel_modeset_init()
@@ -1242,6 +1248,10 @@ int i915_driver_load(struct pci_dev *pde
 	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
 		 driver.name, driver.major, driver.minor, driver.patchlevel,
 		 driver.date, pci_name(pdev), dev_priv->drm.primary->index);
+	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG))
+		DRM_INFO("DRM_I915_DEBUG enabled\n");
+	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+		DRM_INFO("DRM_I915_DEBUG_GEM enabled\n");
 
 	intel_runtime_pm_put(dev_priv);
 
@@ -1309,7 +1319,7 @@ void i915_driver_unload(struct drm_devic
 	drain_workqueue(dev_priv->wq);
 
 	intel_guc_fini(dev);
-	i915_gem_fini(dev);
+	i915_gem_fini(dev_priv);
 	intel_fbc_cleanup_cfb(dev_priv);
 
 	intel_power_domains_fini(dev_priv);
@@ -1431,9 +1441,9 @@ static int i915_drm_suspend(struct drm_d
 
 	intel_suspend_encoders(dev_priv);
 
-	intel_suspend_hw(dev);
+	intel_suspend_hw(dev_priv);
 
-	i915_gem_suspend_gtt_mappings(dev);
+	i915_gem_suspend_gtt_mappings(dev_priv);
 
 	i915_save_state(dev);
 
@@ -1507,7 +1517,7 @@ static int i915_drm_suspend_late(struct
 	 * Fujitsu FSC S7110
 	 * Acer Aspire 1830T
 	 */
-	if (!(hibernation && INTEL_INFO(dev_priv)->gen < 6))
+	if (!(hibernation && INTEL_GEN(dev_priv) < 6))
 		pci_set_power_state(pdev, PCI_D3hot);
 
 	dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
@@ -1595,6 +1605,8 @@ static int i915_drm_resume(struct drm_de
 
 	intel_display_resume(dev);
 
+	drm_kms_helper_poll_enable(dev);
+
 	/*
 	 * ... but also need to make sure that hotplug processing
 	 * doesn't cause havoc. Like in the driver load code we don't
@@ -1602,8 +1614,6 @@ static int i915_drm_resume(struct drm_de
 	 * notifications.
 	 * */
 	intel_hpd_init(dev_priv);
-	/* Config may have changed between suspend and resume */
-	drm_helper_hpd_irq_event(dev);
 
 	intel_opregion_register(dev_priv);
 
@@ -1616,7 +1626,6 @@ static int i915_drm_resume(struct drm_de
 	intel_opregion_notify_adapter(dev_priv, PCI_D0);
 
 	intel_autoenable_gt_powersave(dev_priv);
-	drm_kms_helper_poll_enable(dev);
 
 	enable_rpm_wakeref_asserts(dev_priv);
 
@@ -1721,6 +1730,22 @@ int i915_resume_switcheroo(struct drm_de
 	return i915_drm_resume(dev);
 }
 
+static void disable_engines_irq(struct drm_i915_private *dev_priv)
+{
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	/* Ensure irq handler finishes, and not run again. */
+	disable_irq(dev_priv->drm.irq);
+	for_each_engine(engine, dev_priv, id)
+		tasklet_kill(&engine->irq_tasklet);
+}
+
+static void enable_engines_irq(struct drm_i915_private *dev_priv)
+{
+	enable_irq(dev_priv->drm.irq);
+}
+
 /**
  * i915_reset - reset chip after a hang
  * @dev: drm device to reset
@@ -1754,7 +1779,11 @@ void i915_reset(struct drm_i915_private
 	error->reset_count++;
 
 	pr_notice("drm/i915: Resetting chip after gpu hang\n");
+
+	disable_engines_irq(dev_priv);
 	ret = intel_gpu_reset(dev_priv, ALL_ENGINES);
+	enable_engines_irq(dev_priv);
+
 	if (ret) {
 		if (ret != -ENODEV)
 			DRM_ERROR("Failed to reset chip: %i\n", ret);
@@ -2240,7 +2269,6 @@ err1:
 static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
 				bool rpm_resume)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	int err;
 	int ret;
 
@@ -2264,10 +2292,8 @@ static int vlv_resume_prepare(struct drm
 
 	vlv_check_no_gt_access(dev_priv);
 
-	if (rpm_resume) {
-		intel_init_clock_gating(dev);
-		i915_gem_restore_fences(dev);
-	}
+	if (rpm_resume)
+		intel_init_clock_gating(dev_priv);
 
 	return ret;
 }
@@ -2282,37 +2308,18 @@ static int intel_runtime_suspend(struct
 	if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6())))
 		return -ENODEV;
 
-	if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
+	if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv)))
 		return -ENODEV;
 
 	DRM_DEBUG_KMS("Suspending device\n");
 
-	/*
-	 * We could deadlock here in case another thread holding struct_mutex
-	 * calls RPM suspend concurrently, since the RPM suspend will wait
-	 * first for this RPM suspend to finish. In this case the concurrent
-	 * RPM resume will be followed by its RPM suspend counterpart. Still
-	 * for consistency return -EAGAIN, which will reschedule this suspend.
-	 */
-	if (!mutex_trylock(&dev->struct_mutex)) {
-		DRM_DEBUG_KMS("device lock contention, deffering suspend\n");
-		/*
-		 * Bump the expiration timestamp, otherwise the suspend won't
-		 * be rescheduled.
-		 */
-		pm_runtime_mark_last_busy(kdev);
-
-		return -EAGAIN;
-	}
-
 	disable_rpm_wakeref_asserts(dev_priv);
 
 	/*
 	 * We are safe here against re-faults, since the fault handler takes
 	 * an RPM reference.
 	 */
-	i915_gem_release_all_mmaps(dev_priv);
-	mutex_unlock(&dev->struct_mutex);
+	i915_gem_runtime_suspend(dev_priv);
 
 	intel_guc_suspend(dev);
 
@@ -2372,7 +2379,7 @@ static int intel_runtime_suspend(struct
 
 	assert_forcewakes_inactive(dev_priv);
 
-	if (!IS_VALLEYVIEW(dev_priv) || !IS_CHERRYVIEW(dev_priv))
+	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
 		intel_hpd_poll_init(dev_priv);
 
 	DRM_DEBUG_KMS("Device suspended\n");
@@ -2386,7 +2393,7 @@ static int intel_runtime_resume(struct d
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	int ret = 0;
 
-	if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev)))
+	if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv)))
 		return -ENODEV;
 
 	DRM_DEBUG_KMS("Resuming device\n");
@@ -2404,7 +2411,7 @@ static int intel_runtime_resume(struct d
 	if (IS_GEN6(dev_priv))
 		intel_init_pch_refclk(dev);
 
-	if (IS_BROXTON(dev)) {
+	if (IS_BROXTON(dev_priv)) {
 		bxt_disable_dc9(dev_priv);
 		bxt_display_core_init(dev_priv, true);
 		if (dev_priv->csr.dmc_payload &&
@@ -2420,7 +2427,8 @@ static int intel_runtime_resume(struct d
 	 * No point of rolling back things in case of an error, as the best
 	 * we can do is to hope that things will still work (and disable RPM).
 	 */
-	i915_gem_init_swizzling(dev);
+	i915_gem_init_swizzling(dev_priv);
+	i915_gem_restore_fences(dev_priv);
 
 	intel_runtime_pm_enable_interrupts(dev_priv);
 
@@ -2495,9 +2503,7 @@ static const struct file_operations i915
 	.mmap = drm_gem_mmap,
 	.poll = drm_poll,
 	.read = drm_read,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = i915_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
@@ -2577,7 +2583,7 @@ static struct drm_driver driver = {
 	.set_busid = drm_pci_set_busid,
 
 	.gem_close_object = i915_gem_close_object,
-	.gem_free_object = i915_gem_free_object,
+	.gem_free_object_unlocked = i915_gem_free_object,
 	.gem_vm_ops = &i915_gem_vm_ops,
 
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,7 @@
 #include <linux/intel-iommu.h>
 #include <linux/kref.h>
 #include <linux/pm_qos.h>
+#include <linux/reservation.h>
 #include <linux/shmem_fs.h>
 
 #include <drm/drmP.h>
@@ -59,9 +60,14 @@
 #include "intel_ringbuffer.h"
 
 #include "i915_gem.h"
+#include "i915_gem_fence_reg.h"
+#include "i915_gem_object.h"
 #include "i915_gem_gtt.h"
 #include "i915_gem_render_state.h"
 #include "i915_gem_request.h"
+#include "i915_gem_timeline.h"
+
+#include "i915_vma.h"
 
 #include "intel_gvt.h"
 
@@ -70,7 +76,8 @@
 
 #define DRIVER_NAME		"i915"
 #define DRIVER_DESC		"Intel Graphics"
-#define DRIVER_DATE		"20160919"
+#define DRIVER_DATE		"20161121"
+#define DRIVER_TIMESTAMP	1479717903
 
 #undef WARN_ON
 /* Many gcc seem to no see through this and fall over :( */
@@ -122,6 +129,11 @@ static inline const char *onoff(bool v)
 	return v ? "on" : "off";
 }
 
+static inline const char *enableddisabled(bool v)
+{
+	return v ? "enabled" : "disabled";
+}
+
 enum pipe {
 	INVALID_PIPE = -1,
 	PIPE_A = 0,
@@ -182,9 +194,10 @@ enum plane {
 };
 #define plane_name(p) ((p) + 'A')
 
-#define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A')
+#define sprite_name(p, s) ((p) * INTEL_INFO(dev_priv)->num_sprites[(p)] + (s) + 'A')
 
 enum port {
+	PORT_NONE = -1,
 	PORT_A = 0,
 	PORT_B,
 	PORT_C,
@@ -310,7 +323,7 @@ struct i915_hotplug {
 #define for_each_pipe_masked(__dev_priv, __p, __mask) \
 	for ((__p) = 0; (__p) < INTEL_INFO(__dev_priv)->num_pipes; (__p)++) \
 		for_each_if ((__mask) & (1 << (__p)))
-#define for_each_plane(__dev_priv, __pipe, __p)				\
+#define for_each_universal_plane(__dev_priv, __pipe, __p)		\
 	for ((__p) = 0;							\
 	     (__p) < INTEL_INFO(__dev_priv)->num_sprites[(__pipe)] + 1;	\
 	     (__p)++)
@@ -455,23 +468,6 @@ struct intel_opregion {
 struct intel_overlay;
 struct intel_overlay_error_state;
 
-struct drm_i915_fence_reg {
-	struct list_head link;
-	struct drm_i915_private *i915;
-	struct i915_vma *vma;
-	int pin_count;
-	int id;
-	/**
-	 * Whether the tiling parameters for the currently
-	 * associated fence register have changed. Note that
-	 * for the purposes of tracking tiling changes we also
-	 * treat the unfenced register, the register slot that
-	 * the object occupies whilst it executes a fenced
-	 * command (such as BLT on gen2/3), as a "fence".
-	 */
-	bool dirty;
-};
-
 struct sdvo_device_mapping {
 	u8 initialized;
 	u8 dvo_port;
@@ -483,6 +479,7 @@ struct sdvo_device_mapping {
 
 struct intel_connector;
 struct intel_encoder;
+struct intel_atomic_state;
 struct intel_crtc_state;
 struct intel_initial_plane_config;
 struct intel_crtc;
@@ -490,16 +487,20 @@ struct intel_limit;
 struct dpll;
 
 struct drm_i915_display_funcs {
-	int (*get_display_clock_speed)(struct drm_device *dev);
-	int (*get_fifo_size)(struct drm_device *dev, int plane);
+	int (*get_display_clock_speed)(struct drm_i915_private *dev_priv);
+	int (*get_fifo_size)(struct drm_i915_private *dev_priv, int plane);
 	int (*compute_pipe_wm)(struct intel_crtc_state *cstate);
 	int (*compute_intermediate_wm)(struct drm_device *dev,
 				       struct intel_crtc *intel_crtc,
 				       struct intel_crtc_state *newstate);
-	void (*initial_watermarks)(struct intel_crtc_state *cstate);
-	void (*optimize_watermarks)(struct intel_crtc_state *cstate);
+	void (*initial_watermarks)(struct intel_atomic_state *state,
+				   struct intel_crtc_state *cstate);
+	void (*atomic_update_watermarks)(struct intel_atomic_state *state,
+					 struct intel_crtc_state *cstate);
+	void (*optimize_watermarks)(struct intel_atomic_state *state,
+				    struct intel_crtc_state *cstate);
 	int (*compute_global_watermarks)(struct drm_atomic_state *state);
-	void (*update_wm)(struct drm_crtc *crtc);
+	void (*update_wm)(struct intel_crtc *crtc);
 	int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
 	void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
 	/* Returns the active state of the crtc, and if the crtc is active,
@@ -521,7 +522,7 @@ struct drm_i915_display_funcs {
 				   const struct drm_display_mode *adjusted_mode);
 	void (*audio_codec_disable)(struct intel_encoder *encoder);
 	void (*fdi_link_train)(struct drm_crtc *crtc);
-	void (*init_clock_gating)(struct drm_device *dev);
+	void (*init_clock_gating)(struct drm_i915_private *dev_priv);
 	int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc,
 			  struct drm_framebuffer *fb,
 			  struct drm_i915_gem_object *obj,
@@ -558,6 +559,18 @@ enum forcewake_domains {
 #define FW_REG_READ  (1)
 #define FW_REG_WRITE (2)
 
+enum decoupled_power_domain {
+	GEN9_DECOUPLED_PD_BLITTER = 0,
+	GEN9_DECOUPLED_PD_RENDER,
+	GEN9_DECOUPLED_PD_MEDIA,
+	GEN9_DECOUPLED_PD_ALL
+};
+
+enum decoupled_ops {
+	GEN9_DECOUPLED_OP_WRITE = 0,
+	GEN9_DECOUPLED_OP_READ
+};
+
 enum forcewake_domains
 intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv,
 			       i915_reg_t reg, unsigned int op);
@@ -581,13 +594,25 @@ struct intel_uncore_funcs {
 				uint32_t val, bool trace);
 };
 
+struct intel_forcewake_range {
+	u32 start;
+	u32 end;
+
+	enum forcewake_domains domains;
+};
+
 struct intel_uncore {
 	spinlock_t lock; /** lock is also taken in irq contexts. */
 
+	const struct intel_forcewake_range *fw_domains_table;
+	unsigned int fw_domains_table_entries;
+
 	struct intel_uncore_funcs funcs;
 
 	unsigned fifo_count;
+
 	enum forcewake_domains fw_domains;
+	enum forcewake_domains fw_domains_active;
 
 	struct intel_uncore_forcewake_domain {
 		struct drm_i915_private *i915;
@@ -633,54 +658,55 @@ struct intel_csr {
 	uint32_t allowed_dc_mask;
 };
 
-#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
-	func(is_mobile) sep \
-	func(is_i85x) sep \
-	func(is_i915g) sep \
-	func(is_i945gm) sep \
-	func(is_g33) sep \
-	func(hws_needs_physical) sep \
-	func(is_g4x) sep \
-	func(is_pineview) sep \
-	func(is_broadwater) sep \
-	func(is_crestline) sep \
-	func(is_ivybridge) sep \
-	func(is_valleyview) sep \
-	func(is_cherryview) sep \
-	func(is_haswell) sep \
-	func(is_broadwell) sep \
-	func(is_skylake) sep \
-	func(is_broxton) sep \
-	func(is_kabylake) sep \
-	func(is_preliminary) sep \
-	func(has_fbc) sep \
-	func(has_psr) sep \
-	func(has_runtime_pm) sep \
-	func(has_csr) sep \
-	func(has_resource_streamer) sep \
-	func(has_rc6) sep \
-	func(has_rc6p) sep \
-	func(has_dp_mst) sep \
-	func(has_gmbus_irq) sep \
-	func(has_hw_contexts) sep \
-	func(has_logical_ring_contexts) sep \
-	func(has_l3_dpf) sep \
-	func(has_gmch_display) sep \
-	func(has_guc) sep \
-	func(has_pipe_cxsr) sep \
-	func(has_hotplug) sep \
-	func(cursor_needs_physical) sep \
-	func(has_overlay) sep \
-	func(overlay_needs_physical) sep \
-	func(supports_tv) sep \
-	func(has_llc) sep \
-	func(has_snoop) sep \
-	func(has_ddi) sep \
-	func(has_fpga_dbg) sep \
-	func(has_pooled_eu)
-
-#define DEFINE_FLAG(name) u8 name:1
-#define SEP_SEMICOLON ;
+#define DEV_INFO_FOR_EACH_FLAG(func) \
+	/* Keep is_* in chronological order */ \
+	func(is_mobile); \
+	func(is_i85x); \
+	func(is_i915g); \
+	func(is_i945gm); \
+	func(is_g33); \
+	func(is_g4x); \
+	func(is_pineview); \
+	func(is_broadwater); \
+	func(is_crestline); \
+	func(is_ivybridge); \
+	func(is_valleyview); \
+	func(is_cherryview); \
+	func(is_haswell); \
+	func(is_broadwell); \
+	func(is_skylake); \
+	func(is_broxton); \
+	func(is_kabylake); \
+	func(is_alpha_support); \
+	/* Keep has_* in alphabetical order */ \
+	func(has_64bit_reloc); \
+	func(has_csr); \
+	func(has_ddi); \
+	func(has_dp_mst); \
+	func(has_fbc); \
+	func(has_fpga_dbg); \
+	func(has_gmbus_irq); \
+	func(has_gmch_display); \
+	func(has_guc); \
+	func(has_hotplug); \
+	func(has_hw_contexts); \
+	func(has_l3_dpf); \
+	func(has_llc); \
+	func(has_logical_ring_contexts); \
+	func(has_overlay); \
+	func(has_pipe_cxsr); \
+	func(has_pooled_eu); \
+	func(has_psr); \
+	func(has_rc6); \
+	func(has_rc6p); \
+	func(has_resource_streamer); \
+	func(has_runtime_pm); \
+	func(has_snoop); \
+	func(cursor_needs_physical); \
+	func(hws_needs_physical); \
+	func(overlay_needs_physical); \
+	func(supports_tv); \
+	func(has_decoupled_mmio)
 
 struct sseu_dev_info {
 	u8 slice_mask;
@@ -709,7 +735,9 @@ struct intel_device_info {
 	u16 gen_mask;
 	u8 ring_mask; /* Rings supported by the HW */
 	u8 num_rings;
-	DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
+#define DEFINE_FLAG(name) u8 name:1
+	DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG);
+#undef DEFINE_FLAG
 	u16 ddb_size; /* in blocks */
 	/* Register offsets for the various display pipes and transcoders */
 	int pipe_offsets[I915_MAX_TRANSCODERS];
@@ -726,14 +754,15 @@ struct intel_device_info {
 	} color;
 };
 
-#undef DEFINE_FLAG
-#undef SEP_SEMICOLON
-
 struct intel_display_error_state;
 
 struct drm_i915_error_state {
 	struct kref ref;
 	struct timeval time;
+	struct timeval boottime;
+	struct timeval uptime;
+
+	struct drm_i915_private *i915;
 
 	char error_msg[128];
 	bool simulated;
@@ -759,11 +788,12 @@ struct drm_i915_error_state {
 	u32 gam_ecochk;
 	u32 gab_ctl;
 	u32 gfx_mode;
-	u32 extra_instdone[I915_NUM_INSTDONE_REG];
+
 	u64 fence[I915_MAX_NUM_FENCES];
 	struct intel_overlay_error_state *overlay;
 	struct intel_display_error_state *display;
 	struct drm_i915_error_object *semaphore;
+	struct drm_i915_error_object *guc_log;
 
 	struct drm_i915_error_engine {
 		int engine_id;
@@ -775,12 +805,14 @@ struct drm_i915_error_state {
 		struct i915_address_space *vm;
 		int num_requests;
 
+		/* position of active request inside the ring */
+		u32 rq_head, rq_post, rq_tail;
+
 		/* our own tracking of ring head and tail */
 		u32 cpu_ring_head;
 		u32 cpu_ring_tail;
 
 		u32 last_seqno;
-		u32 semaphore_seqno[I915_NUM_ENGINES - 1];
 
 		/* Register state */
 		u32 start;
@@ -791,7 +823,6 @@ struct drm_i915_error_state {
 		u32 hws;
 		u32 ipeir;
 		u32 ipehr;
-		u32 instdone;
 		u32 bbstate;
 		u32 instpm;
 		u32 instps;
@@ -802,11 +833,13 @@ struct drm_i915_error_state {
 		u64 faddr;
 		u32 rc_psmi; /* sleep state */
 		u32 semaphore_mboxes[I915_NUM_ENGINES - 1];
+		struct intel_instdone instdone;
 
 		struct drm_i915_error_object {
-			int page_count;
 			u64 gtt_offset;
 			u64 gtt_size;
+			int page_count;
+			int unused;
 			u32 *pages[0];
 		} *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
 
@@ -815,10 +848,11 @@ struct drm_i915_error_state {
 		struct drm_i915_error_request {
 			long jiffies;
 			pid_t pid;
+			u32 context;
 			u32 seqno;
 			u32 head;
 			u32 tail;
-		} *requests;
+		} *requests, execlist[2];
 
 		struct drm_i915_error_waiter {
 			char comm[TASK_COMM_LEN];
@@ -914,6 +948,7 @@ struct i915_gem_context {
 	struct drm_i915_file_private *file_priv;
 	struct i915_hw_ppgtt *ppgtt;
 	struct pid *pid;
+	const char *name;
 
 	struct i915_ctx_hang_stats hang_stats;
 
@@ -924,6 +959,7 @@ struct i915_gem_context {
 	/* Unique identifier for this context, used by the hw for tracking */
 	unsigned int hw_id;
 	u32 user_handle;
+	int priority; /* greater priorities are serviced first */
 
 	u32 ggtt_alignment;
 
@@ -972,7 +1008,12 @@ struct intel_fbc {
 	bool enabled;
 	bool active;
 
+	bool underrun_detected;
+	struct work_struct underrun_work;
+
 	struct intel_fbc_state_cache {
+		struct i915_vma *vma;
+
 		struct {
 			unsigned int mode_flags;
 			uint32_t hsw_bdw_pixel_rate;
@@ -986,15 +1027,14 @@ struct intel_fbc {
 		} plane;
 
 		struct {
-			u64 ilk_ggtt_offset;
 			uint32_t pixel_format;
 			unsigned int stride;
-			int fence_reg;
-			unsigned int tiling_mode;
 		} fb;
 	} state_cache;
 
 	struct intel_fbc_reg_params {
+		struct i915_vma *vma;
+
 		struct {
 			enum pipe pipe;
 			enum plane plane;
@@ -1002,10 +1042,8 @@ struct intel_fbc {
 		} crtc;
 
 		struct {
-			u64 ggtt_offset;
 			uint32_t pixel_format;
 			unsigned int stride;
-			int fence_reg;
 		} fb;
 
 		int cfb_size;
@@ -1297,6 +1335,12 @@ struct i915_power_well {
 	/* cached hw enabled state */
 	bool hw_enabled;
 	unsigned long domains;
+	/* unique identifier for this power well */
+	unsigned long id;
+	/*
+	 * Arbitraty data associated with this power well. Platform and power
+	 * well specific.
+	 */
 	unsigned long data;
 	const struct i915_power_well_ops *ops;
 };
@@ -1334,11 +1378,22 @@ struct i915_gem_mm {
 	struct list_head bound_list;
 	/**
 	 * List of objects which are not bound to the GTT (thus
-	 * are idle and not used by the GPU) but still have
-	 * (presumably uncached) pages still attached.
+	 * are idle and not used by the GPU). These objects may or may
+	 * not actually have any pages attached.
 	 */
 	struct list_head unbound_list;
 
+	/** List of all objects in gtt_space, currently mmaped by userspace.
+	 * All objects within this list must also be on bound_list.
+	 */
+	struct list_head userfault_list;
+
+	/**
+	 * List of objects which are pending destruction.
+	 */
+	struct llist_head free_list;
+	struct work_struct free_work;
+
 	/** Usable portion of the GTT for GEM */
 	unsigned long stolen_base; /* limited to low memory (32-bit) */
 
@@ -1368,7 +1423,7 @@ struct i915_gem_mm {
 
 	/* accounting, useful for userland debugging */
 	spinlock_t object_stat_lock;
-	size_t object_memory;
+	u64 object_memory;
 	u32 object_count;
 };
 
@@ -1387,6 +1442,9 @@ struct i915_error_state_file_priv {
 	struct drm_i915_error_state *error;
 };
 
+#define I915_RESET_TIMEOUT (10 * HZ) /* 10s */
+#define I915_FENCE_TIMEOUT (10 * HZ) /* 10s */
+
 struct i915_gpu_error {
 	/* For hangcheck timer */
 #define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
@@ -1620,7 +1678,6 @@ static inline bool skl_ddb_entry_equal(c
 }
 
 struct skl_ddb_allocation {
-	struct skl_ddb_entry pipe[I915_MAX_PIPES];
 	struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */
 	struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES];
 };
@@ -1628,15 +1685,12 @@ struct skl_ddb_allocation {
 struct skl_wm_values {
 	unsigned dirty_pipes;
 	struct skl_ddb_allocation ddb;
-	uint32_t wm_linetime[I915_MAX_PIPES];
-	uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8];
-	uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES];
 };
 
 struct skl_wm_level {
-	bool plane_en[I915_MAX_PLANES];
-	uint16_t plane_res_b[I915_MAX_PLANES];
-	uint8_t plane_res_l[I915_MAX_PLANES];
+	bool plane_en;
+	uint16_t plane_res_b;
+	uint8_t plane_res_l;
 };
 
 /*
@@ -1664,7 +1718,6 @@ struct skl_wm_level {
  */
 struct i915_runtime_pm {
 	atomic_t wakeref_count;
-	atomic_t atomic_seq;
 	bool suspended;
 	bool irqs_enabled;
 };
@@ -1748,6 +1801,7 @@ struct drm_i915_private {
 	struct kmem_cache *objects;
 	struct kmem_cache *vmas;
 	struct kmem_cache *requests;
+	struct kmem_cache *dependencies;
 
 	const struct intel_device_info info;
 
@@ -1759,7 +1813,7 @@ struct drm_i915_private {
 
 	struct i915_virtual_gpu vgpu;
 
-	struct intel_gvt gvt;
+	struct intel_gvt *gvt;
 
 	struct intel_guc guc;
 
@@ -1787,9 +1841,8 @@ struct drm_i915_private {
 
 	struct pci_dev *bridge_dev;
 	struct i915_gem_context *kernel_context;
-	struct intel_engine_cs engine[I915_NUM_ENGINES];
+	struct intel_engine_cs *engine[I915_NUM_ENGINES];
 	struct i915_vma *semaphore;
-	u32 next_seqno;
 
 	struct drm_dma_handle *status_page_dmah;
 	struct resource mch_res;
@@ -1814,8 +1867,10 @@ struct drm_i915_private {
 		u32 de_irq_mask[I915_MAX_PIPES];
 	};
 	u32 gt_irq_mask;
-	u32 pm_irq_mask;
+	u32 pm_imr;
+	u32 pm_ier;
 	u32 pm_rps_events;
+	u32 pm_guc_events;
 	u32 pipestat_irq_mask[I915_MAX_PIPES];
 
 	struct i915_hotplug hotplug;
@@ -1892,8 +1947,8 @@ struct drm_i915_private {
 
 	/* Kernel Modesetting */
 
-	struct drm_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
-	struct drm_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
+	struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES];
+	struct intel_crtc *pipe_to_crtc_mapping[I915_MAX_PIPES];
 	wait_queue_head_t pending_flip_queue;
 
 #ifdef CONFIG_DEBUG_FS
@@ -1921,6 +1976,11 @@ struct drm_i915_private {
 
 	struct i915_frontbuffer_tracking fb_tracking;
 
+	struct intel_atomic_helper {
+		struct llist_head free_list;
+		struct work_struct free_work;
+	} atomic_helper;
+
 	u16 orig_clock;
 
 	bool mchbar_need_disable;
@@ -2009,13 +2069,6 @@ struct drm_i915_private {
 		 */
 		uint16_t skl_latency[8];
 
-		/*
-		 * The skl_wm_values structure is a bit too big for stack
-		 * allocation, so we keep the staging struct where we store
-		 * intermediate results here instead.
-		 */
-		struct skl_wm_values skl_results;
-
 		/* current hardware state */
 		union {
 			struct ilk_wm_values hw;
@@ -2047,6 +2100,10 @@ struct drm_i915_private {
 		void (*resume)(struct drm_i915_private *);
 		void (*cleanup_engine)(struct intel_engine_cs *engine);
 
+		struct list_head timelines;
+		struct i915_gem_timeline global_timeline;
+		u32 active_requests;
+
 		/**
 		 * Is the GPU currently considered idle, or busy executing
 		 * userspace requests? Whilst idle, we allow runtime power
@@ -2054,7 +2111,6 @@ struct drm_i915_private {
 		 * In order to reduce the effect on performance, there
 		 * is a slight delay before we do so.
 		 */
-		unsigned int active_engines;
 		bool awake;
 
 		/**
@@ -2074,12 +2130,15 @@ struct drm_i915_private {
 		 * off the idle_work.
 		 */
 		struct delayed_work idle_work;
+
+		ktime_t last_init_time;
 	} gt;
 
 	/* perform PHY state sanity checks? */
 	bool chv_phy_assert[2];
 
-	struct intel_encoder *dig_port_map[I915_MAX_PORTS];
+	/* Used to save the pipe-to-encoder mapping for audio */
+	struct intel_encoder *av_enc_map[I915_MAX_PIPES];
 
 	/*
 	 * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
@@ -2103,19 +2162,11 @@ static inline struct drm_i915_private *g
 }
 
 /* Simple iterator over all initialised engines */
-#define for_each_engine(engine__, dev_priv__) \
-	for ((engine__) = &(dev_priv__)->engine[0]; \
-	     (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
-	     (engine__)++) \
-		for_each_if (intel_engine_initialized(engine__))
-
-/* Iterator with engine_id */
-#define for_each_engine_id(engine__, dev_priv__, id__) \
-	for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \
-	     (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \
-	     (engine__)++) \
-		for_each_if (((id__) = (engine__)->id, \
-			      intel_engine_initialized(engine__)))
+#define for_each_engine(engine__, dev_priv__, id__) \
+	for ((id__) = 0; \
+	     (id__) < I915_NUM_ENGINES; \
+	     (id__)++) \
+		for_each_if ((engine__) = (dev_priv__)->engine[(id__)])
 
 #define __mask_next_bit(mask) ({					\
 	int __idx = ffs(mask) - 1;					\
@@ -2126,7 +2177,7 @@ static inline struct drm_i915_private *g
 /* Iterator over subset of engines selected by mask */
 #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \
 	for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask;	\
-	     tmp__ ? (engine__ = &(dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; )
+	     tmp__ ? (engine__ = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; )
 
 enum hdmi_force_audio {
 	HDMI_AUDIO_OFF_DVI = -2,	/* no aux data for HDMI-DVI converter */
@@ -2137,30 +2188,6 @@ enum hdmi_force_audio {
 
 #define I915_GTT_OFFSET_NONE ((u32)-1)
 
-struct drm_i915_gem_object_ops {
-	unsigned int flags;
-#define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
-
-	/* Interface between the GEM object and its backing storage.
-	 * get_pages() is called once prior to the use of the associated set
-	 * of pages before to binding them into the GTT, and put_pages() is
-	 * called after we no longer need them. As we expect there to be
-	 * associated cost with migrating pages between the backing storage
-	 * and making them available for the GPU (e.g. clflush), we may hold
-	 * onto the pages after they are no longer referenced by the GPU
-	 * in case they may be used again shortly (for example migrating the
-	 * pages to a different memory domain within the GTT). put_pages()
-	 * will therefore most likely be called when the object itself is
-	 * being released or under memory pressure (where we attempt to
-	 * reap pages for the shrinker).
-	 */
-	int (*get_pages)(struct drm_i915_gem_object *);
-	void (*put_pages)(struct drm_i915_gem_object *);
-
-	int (*dmabuf_export)(struct drm_i915_gem_object *);
-	void (*release)(struct drm_i915_gem_object *);
-};
-
 /*
  * Frontbuffer tracking bits. Set in obj->frontbuffer_bits while a gem bo is
  * considered to be the frontbuffer for the given plane interface-wise. This
@@ -2182,232 +2209,6 @@ struct drm_i915_gem_object_ops {
 #define INTEL_FRONTBUFFER_ALL_MASK(pipe) \
 	(0xff << (INTEL_FRONTBUFFER_BITS_PER_PIPE * (pipe)))
 
-struct drm_i915_gem_object {
-	struct drm_gem_object base;
-
-	const struct drm_i915_gem_object_ops *ops;
-
-	/** List of VMAs backed by this object */
-	struct list_head vma_list;
-
-	/** Stolen memory for this object, instead of being backed by shmem. */
-	struct drm_mm_node *stolen;
-	struct list_head global_list;
-
-	/** Used in execbuf to temporarily hold a ref */
-	struct list_head obj_exec_link;
-
-	struct list_head batch_pool_link;
-
-	unsigned long flags;
-	/**
-	 * This is set if the object is on the active lists (has pending
-	 * rendering and so a non-zero seqno), and is not set if it i s on
-	 * inactive (ready to be unbound) list.
-	 */
-#define I915_BO_ACTIVE_SHIFT 0
-#define I915_BO_ACTIVE_MASK ((1 << I915_NUM_ENGINES) - 1)
-#define __I915_BO_ACTIVE(bo) \
-	((READ_ONCE((bo)->flags) >> I915_BO_ACTIVE_SHIFT) & I915_BO_ACTIVE_MASK)
-
-	/**
-	 * This is set if the object has been written to since last bound
-	 * to the GTT
-	 */
-	unsigned int dirty:1;
-
-	/**
-	 * Advice: are the backing pages purgeable?
-	 */
-	unsigned int madv:2;
-
-	/**
-	 * 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;
-
-	/*
-	 * Is the object to be mapped as read-only to the GPU
-	 * Only honoured if hardware has relevant pte bit
-	 */
-	unsigned long gt_ro:1;
-	unsigned int cache_level:3;
-	unsigned int cache_dirty:1;
-
-	atomic_t frontbuffer_bits;
-	unsigned int frontbuffer_ggtt_origin; /* write once */
-
-	/** Current tiling stride for the object, if it's tiled. */
-	unsigned int tiling_and_stride;
-#define FENCE_MINIMUM_STRIDE 128 /* See i915_tiling_ok() */
-#define TILING_MASK (FENCE_MINIMUM_STRIDE-1)
-#define STRIDE_MASK (~TILING_MASK)
-
-	/** Count of VMA actually bound by this object */
-	unsigned int bind_count;
-	unsigned int pin_display;
-
-	struct sg_table *pages;
-	int pages_pin_count;
-	struct get_page {
-		struct scatterlist *sg;
-		int last;
-	} get_page;
-	void *mapping;
-
-	/** Breadcrumb of last rendering to the buffer.
-	 * There can only be one writer, but we allow for multiple readers.
-	 * If there is a writer that necessarily implies that all other
-	 * read requests are complete - but we may only be lazily clearing
-	 * the read requests. A read request is naturally the most recent
-	 * request on a ring, so we may have two different write and read
-	 * requests on one ring where the write request is older than the
-	 * read request. This allows for the CPU to read from an active
-	 * buffer by only waiting for the write to complete.
-	 */
-	struct i915_gem_active last_read[I915_NUM_ENGINES];
-	struct i915_gem_active last_write;
-
-	/** References from framebuffers, locks out tiling changes. */
-	unsigned long framebuffer_references;
-
-	/** Record of address bit 17 of each page at last unbind. */
-	unsigned long *bit_17;
-
-	struct i915_gem_userptr {
-		uintptr_t ptr;
-		unsigned read_only :1;
-		unsigned workers :4;
-#define I915_GEM_USERPTR_MAX_WORKERS 15
-
-		struct i915_mm_struct *mm;
-		struct i915_mmu_object *mmu_object;
-		struct work_struct *work;
-	} userptr;
-
-	/** for phys allocated objects */
-	struct drm_dma_handle *phys_handle;
-};
-
-static inline struct drm_i915_gem_object *
-to_intel_bo(struct drm_gem_object *gem)
-{
-	/* Assert that to_intel_bo(NULL) == NULL */
-	BUILD_BUG_ON(offsetof(struct drm_i915_gem_object, base));
-
-	return container_of(gem, struct drm_i915_gem_object, base);
-}
-
-static inline struct drm_i915_gem_object *
-i915_gem_object_lookup(struct drm_file *file, u32 handle)
-{
-	return to_intel_bo(drm_gem_object_lookup(file, handle));
-}
-
-__deprecated
-extern struct drm_gem_object *
-drm_gem_object_lookup(struct drm_file *file, u32 handle);
-
-__attribute__((nonnull))
-static inline struct drm_i915_gem_object *
-i915_gem_object_get(struct drm_i915_gem_object *obj)
-{
-	drm_gem_object_reference(&obj->base);
-	return obj;
-}
-
-__deprecated
-extern void drm_gem_object_reference(struct drm_gem_object *);
-
-__attribute__((nonnull))
-static inline void
-i915_gem_object_put(struct drm_i915_gem_object *obj)
-{
-	drm_gem_object_unreference(&obj->base);
-}
-
-__deprecated
-extern void drm_gem_object_unreference(struct drm_gem_object *);
-
-__attribute__((nonnull))
-static inline void
-i915_gem_object_put_unlocked(struct drm_i915_gem_object *obj)
-{
-	drm_gem_object_unreference_unlocked(&obj->base);
-}
-
-__deprecated
-extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *);
-
-static inline bool
-i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
-{
-	return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE;
-}
-
-static inline unsigned long
-i915_gem_object_get_active(const struct drm_i915_gem_object *obj)
-{
-	return (obj->flags >> I915_BO_ACTIVE_SHIFT) & I915_BO_ACTIVE_MASK;
-}
-
-static inline bool
-i915_gem_object_is_active(const struct drm_i915_gem_object *obj)
-{
-	return i915_gem_object_get_active(obj);
-}
-
-static inline void
-i915_gem_object_set_active(struct drm_i915_gem_object *obj, int engine)
-{
-	obj->flags |= BIT(engine + I915_BO_ACTIVE_SHIFT);
-}
-
-static inline void
-i915_gem_object_clear_active(struct drm_i915_gem_object *obj, int engine)
-{
-	obj->flags &= ~BIT(engine + I915_BO_ACTIVE_SHIFT);
-}
-
-static inline bool
-i915_gem_object_has_active_engine(const struct drm_i915_gem_object *obj,
-				  int engine)
-{
-	return obj->flags & BIT(engine + I915_BO_ACTIVE_SHIFT);
-}
-
-static inline unsigned int
-i915_gem_object_get_tiling(struct drm_i915_gem_object *obj)
-{
-	return obj->tiling_and_stride & TILING_MASK;
-}
-
-static inline bool
-i915_gem_object_is_tiled(struct drm_i915_gem_object *obj)
-{
-	return i915_gem_object_get_tiling(obj) != I915_TILING_NONE;
-}
-
-static inline unsigned int
-i915_gem_object_get_stride(struct drm_i915_gem_object *obj)
-{
-	return obj->tiling_and_stride & STRIDE_MASK;
-}
-
-static inline struct i915_vma *i915_vma_get(struct i915_vma *vma)
-{
-	i915_gem_object_get(vma->obj);
-	return vma;
-}
-
-static inline void i915_vma_put(struct i915_vma *vma)
-{
-	lockdep_assert_held(&vma->vm->dev->struct_mutex);
-	i915_gem_object_put(vma->obj);
-}
-
 /*
  * Optimised SGL iterator for GEM objects
  */
@@ -2434,6 +2235,14 @@ static __always_inline struct sgt_iter {
 	return s;
 }
 
+static inline struct scatterlist *____sg_next(struct scatterlist *sg)
+{
+	++sg;
+	if (unlikely(sg_is_chain(sg)))
+		sg = sg_chain_ptr(sg);
+	return sg;
+}
+
 /**
  * __sg_next - return the next scatterlist entry in a list
  * @sg:		The current sg entry
@@ -2448,9 +2257,7 @@ static inline struct scatterlist *__sg_n
 #ifdef CONFIG_DEBUG_SG
 	BUG_ON(sg->sg_magic != SG_MAGIC);
 #endif
-	return sg_is_last(sg) ? NULL :
-		likely(!sg_is_chain(++sg)) ? sg :
-		sg_chain_ptr(sg);
+	return sg_is_last(sg) ? NULL : ____sg_next(sg);
 }
 
 /**
@@ -2574,23 +2381,19 @@ struct drm_i915_cmd_table {
 	int count;
 };
 
-/* Note that the (struct drm_i915_private *) cast is just to shut up gcc. */
-#define __I915__(p) ({ \
-	struct drm_i915_private *__p; \
-	if (__builtin_types_compatible_p(typeof(*p), struct drm_i915_private)) \
-		__p = (struct drm_i915_private *)p; \
-	else if (__builtin_types_compatible_p(typeof(*p), struct drm_device)) \
-		__p = to_i915((struct drm_device *)p); \
-	else \
-		BUILD_BUG(); \
-	__p; \
-})
-#define INTEL_INFO(p)	(&__I915__(p)->info)
-#define INTEL_GEN(p)	(INTEL_INFO(p)->gen)
-#define INTEL_DEVID(p)	(INTEL_INFO(p)->device_id)
+static inline const struct intel_device_info *
+intel_info(const struct drm_i915_private *dev_priv)
+{
+	return &dev_priv->info;
+}
+
+#define INTEL_INFO(dev_priv)	intel_info((dev_priv))
+
+#define INTEL_GEN(dev_priv)	((dev_priv)->info.gen)
+#define INTEL_DEVID(dev_priv)	((dev_priv)->info.device_id)
 
 #define REVID_FOREVER		0xff
-#define INTEL_REVID(p)	(__I915__(p)->drm.pdev->revision)
+#define INTEL_REVID(dev_priv)	((dev_priv)->drm.pdev->revision)
 
 #define GEN_FOREVER (0)
 /*
@@ -2598,7 +2401,7 @@ struct drm_i915_cmd_table {
  *
  * Use GEN_FOREVER for unbound start and or end.
  */
-#define IS_GEN(p, s, e) ({ \
+#define IS_GEN(dev_priv, s, e) ({ \
 	unsigned int __s = (s), __e = (e); \
 	BUILD_BUG_ON(!__builtin_constant_p(s)); \
 	BUILD_BUG_ON(!__builtin_constant_p(e)); \
@@ -2608,7 +2411,7 @@ struct drm_i915_cmd_table {
 		__e = BITS_PER_LONG - 1; \
 	else \
 		__e = (e) - 1; \
-	!!(INTEL_INFO(p)->gen_mask & GENMASK((__e), (__s))); \
+	!!((dev_priv)->info.gen_mask & GENMASK((__e), (__s))); \
 })
 
 /*
@@ -2619,75 +2422,75 @@ struct drm_i915_cmd_table {
 #define IS_REVID(p, since, until) \
 	(INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until))
 
-#define IS_I830(dev)		(INTEL_DEVID(dev) == 0x3577)
-#define IS_845G(dev)		(INTEL_DEVID(dev) == 0x2562)
-#define IS_I85X(dev)		(INTEL_INFO(dev)->is_i85x)
-#define IS_I865G(dev)		(INTEL_DEVID(dev) == 0x2572)
-#define IS_I915G(dev)		(INTEL_INFO(dev)->is_i915g)
-#define IS_I915GM(dev)		(INTEL_DEVID(dev) == 0x2592)
-#define IS_I945G(dev)		(INTEL_DEVID(dev) == 0x2772)
-#define IS_I945GM(dev)		(INTEL_INFO(dev)->is_i945gm)
-#define IS_BROADWATER(dev)	(INTEL_INFO(dev)->is_broadwater)
-#define IS_CRESTLINE(dev)	(INTEL_INFO(dev)->is_crestline)
-#define IS_GM45(dev)		(INTEL_DEVID(dev) == 0x2A42)
-#define IS_G4X(dev)		(INTEL_INFO(dev)->is_g4x)
-#define IS_PINEVIEW_G(dev)	(INTEL_DEVID(dev) == 0xa001)
-#define IS_PINEVIEW_M(dev)	(INTEL_DEVID(dev) == 0xa011)
-#define IS_PINEVIEW(dev)	(INTEL_INFO(dev)->is_pineview)
-#define IS_G33(dev)		(INTEL_INFO(dev)->is_g33)
-#define IS_IRONLAKE_M(dev)	(INTEL_DEVID(dev) == 0x0046)
-#define IS_IVYBRIDGE(dev)	(INTEL_INFO(dev)->is_ivybridge)
-#define IS_IVB_GT1(dev)		(INTEL_DEVID(dev) == 0x0156 || \
-				 INTEL_DEVID(dev) == 0x0152 || \
-				 INTEL_DEVID(dev) == 0x015a)
-#define IS_VALLEYVIEW(dev)	(INTEL_INFO(dev)->is_valleyview)
-#define IS_CHERRYVIEW(dev)	(INTEL_INFO(dev)->is_cherryview)
-#define IS_HASWELL(dev)	(INTEL_INFO(dev)->is_haswell)
-#define IS_BROADWELL(dev)	(INTEL_INFO(dev)->is_broadwell)
-#define IS_SKYLAKE(dev)	(INTEL_INFO(dev)->is_skylake)
-#define IS_BROXTON(dev)		(INTEL_INFO(dev)->is_broxton)
-#define IS_KABYLAKE(dev)	(INTEL_INFO(dev)->is_kabylake)
-#define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)
-#define IS_HSW_EARLY_SDV(dev)	(IS_HASWELL(dev) && \
-				 (INTEL_DEVID(dev) & 0xFF00) == 0x0C00)
-#define IS_BDW_ULT(dev)		(IS_BROADWELL(dev) && \
-				 ((INTEL_DEVID(dev) & 0xf) == 0x6 ||	\
-				 (INTEL_DEVID(dev) & 0xf) == 0xb ||	\
-				 (INTEL_DEVID(dev) & 0xf) == 0xe))
+#define IS_I830(dev_priv)	(INTEL_DEVID(dev_priv) == 0x3577)
+#define IS_845G(dev_priv)	(INTEL_DEVID(dev_priv) == 0x2562)
+#define IS_I85X(dev_priv)	((dev_priv)->info.is_i85x)
+#define IS_I865G(dev_priv)	(INTEL_DEVID(dev_priv) == 0x2572)
+#define IS_I915G(dev_priv)	((dev_priv)->info.is_i915g)
+#define IS_I915GM(dev_priv)	(INTEL_DEVID(dev_priv) == 0x2592)
+#define IS_I945G(dev_priv)	(INTEL_DEVID(dev_priv) == 0x2772)
+#define IS_I945GM(dev_priv)	((dev_priv)->info.is_i945gm)
+#define IS_BROADWATER(dev_priv)	((dev_priv)->info.is_broadwater)
+#define IS_CRESTLINE(dev_priv)	((dev_priv)->info.is_crestline)
+#define IS_GM45(dev_priv)	(INTEL_DEVID(dev_priv) == 0x2A42)
+#define IS_G4X(dev_priv)	((dev_priv)->info.is_g4x)
+#define IS_PINEVIEW_G(dev_priv)	(INTEL_DEVID(dev_priv) == 0xa001)
+#define IS_PINEVIEW_M(dev_priv)	(INTEL_DEVID(dev_priv) == 0xa011)
+#define IS_PINEVIEW(dev_priv)	((dev_priv)->info.is_pineview)
+#define IS_G33(dev_priv)	((dev_priv)->info.is_g33)
+#define IS_IRONLAKE_M(dev_priv)	(INTEL_DEVID(dev_priv) == 0x0046)
+#define IS_IVYBRIDGE(dev_priv)	((dev_priv)->info.is_ivybridge)
+#define IS_IVB_GT1(dev_priv)	(INTEL_DEVID(dev_priv) == 0x0156 || \
+				 INTEL_DEVID(dev_priv) == 0x0152 || \
+				 INTEL_DEVID(dev_priv) == 0x015a)
+#define IS_VALLEYVIEW(dev_priv)	((dev_priv)->info.is_valleyview)
+#define IS_CHERRYVIEW(dev_priv)	((dev_priv)->info.is_cherryview)
+#define IS_HASWELL(dev_priv)	((dev_priv)->info.is_haswell)
+#define IS_BROADWELL(dev_priv)	((dev_priv)->info.is_broadwell)
+#define IS_SKYLAKE(dev_priv)	((dev_priv)->info.is_skylake)
+#define IS_BROXTON(dev_priv)	((dev_priv)->info.is_broxton)
+#define IS_KABYLAKE(dev_priv)	((dev_priv)->info.is_kabylake)
+#define IS_MOBILE(dev_priv)	((dev_priv)->info.is_mobile)
+#define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \
+				    (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00)
+#define IS_BDW_ULT(dev_priv)	(IS_BROADWELL(dev_priv) && \
+				 ((INTEL_DEVID(dev_priv) & 0xf) == 0x6 ||	\
+				 (INTEL_DEVID(dev_priv) & 0xf) == 0xb ||	\
+				 (INTEL_DEVID(dev_priv) & 0xf) == 0xe))
 /* ULX machines are also considered ULT. */
-#define IS_BDW_ULX(dev)		(IS_BROADWELL(dev) && \
-				 (INTEL_DEVID(dev) & 0xf) == 0xe)
-#define IS_BDW_GT3(dev)		(IS_BROADWELL(dev) && \
-				 (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
-#define IS_HSW_ULT(dev)		(IS_HASWELL(dev) && \
-				 (INTEL_DEVID(dev) & 0xFF00) == 0x0A00)
-#define IS_HSW_GT3(dev)		(IS_HASWELL(dev) && \
-				 (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
+#define IS_BDW_ULX(dev_priv)	(IS_BROADWELL(dev_priv) && \
+				 (INTEL_DEVID(dev_priv) & 0xf) == 0xe)
+#define IS_BDW_GT3(dev_priv)	(IS_BROADWELL(dev_priv) && \
+				 (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020)
+#define IS_HSW_ULT(dev_priv)	(IS_HASWELL(dev_priv) && \
+				 (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0A00)
+#define IS_HSW_GT3(dev_priv)	(IS_HASWELL(dev_priv) && \
+				 (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020)
 /* ULX machines are also considered ULT. */
-#define IS_HSW_ULX(dev)		(INTEL_DEVID(dev) == 0x0A0E || \
-				 INTEL_DEVID(dev) == 0x0A1E)
-#define IS_SKL_ULT(dev)		(INTEL_DEVID(dev) == 0x1906 || \
-				 INTEL_DEVID(dev) == 0x1913 || \
-				 INTEL_DEVID(dev) == 0x1916 || \
-				 INTEL_DEVID(dev) == 0x1921 || \
-				 INTEL_DEVID(dev) == 0x1926)
-#define IS_SKL_ULX(dev)		(INTEL_DEVID(dev) == 0x190E || \
-				 INTEL_DEVID(dev) == 0x1915 || \
-				 INTEL_DEVID(dev) == 0x191E)
-#define IS_KBL_ULT(dev)		(INTEL_DEVID(dev) == 0x5906 || \
-				 INTEL_DEVID(dev) == 0x5913 || \
-				 INTEL_DEVID(dev) == 0x5916 || \
-				 INTEL_DEVID(dev) == 0x5921 || \
-				 INTEL_DEVID(dev) == 0x5926)
-#define IS_KBL_ULX(dev)		(INTEL_DEVID(dev) == 0x590E || \
-				 INTEL_DEVID(dev) == 0x5915 || \
-				 INTEL_DEVID(dev) == 0x591E)
-#define IS_SKL_GT3(dev)		(IS_SKYLAKE(dev) && \
-				 (INTEL_DEVID(dev) & 0x00F0) == 0x0020)
-#define IS_SKL_GT4(dev)		(IS_SKYLAKE(dev) && \
-				 (INTEL_DEVID(dev) & 0x00F0) == 0x0030)
+#define IS_HSW_ULX(dev_priv)	(INTEL_DEVID(dev_priv) == 0x0A0E || \
+				 INTEL_DEVID(dev_priv) == 0x0A1E)
+#define IS_SKL_ULT(dev_priv)	(INTEL_DEVID(dev_priv) == 0x1906 || \
+				 INTEL_DEVID(dev_priv) == 0x1913 || \
+				 INTEL_DEVID(dev_priv) == 0x1916 || \
+				 INTEL_DEVID(dev_priv) == 0x1921 || \
+				 INTEL_DEVID(dev_priv) == 0x1926)
+#define IS_SKL_ULX(dev_priv)	(INTEL_DEVID(dev_priv) == 0x190E || \
+				 INTEL_DEVID(dev_priv) == 0x1915 || \
+				 INTEL_DEVID(dev_priv) == 0x191E)
+#define IS_KBL_ULT(dev_priv)	(INTEL_DEVID(dev_priv) == 0x5906 || \
+				 INTEL_DEVID(dev_priv) == 0x5913 || \
+				 INTEL_DEVID(dev_priv) == 0x5916 || \
+				 INTEL_DEVID(dev_priv) == 0x5921 || \
+				 INTEL_DEVID(dev_priv) == 0x5926)
+#define IS_KBL_ULX(dev_priv)	(INTEL_DEVID(dev_priv) == 0x590E || \
+				 INTEL_DEVID(dev_priv) == 0x5915 || \
+				 INTEL_DEVID(dev_priv) == 0x591E)
+#define IS_SKL_GT3(dev_priv)	(IS_SKYLAKE(dev_priv) && \
+				 (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020)
+#define IS_SKL_GT4(dev_priv)	(IS_SKYLAKE(dev_priv) && \
+				 (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0030)
 
-#define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
+#define IS_ALPHA_SUPPORT(intel_info) ((intel_info)->is_alpha_support)
 
 #define SKL_REVID_A0		0x0
 #define SKL_REVID_B0		0x1
@@ -2705,7 +2508,8 @@ struct drm_i915_cmd_table {
 #define BXT_REVID_B0		0x3
 #define BXT_REVID_C0		0x9
 
-#define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until))
+#define IS_BXT_REVID(dev_priv, since, until) \
+	(IS_BROXTON(dev_priv) && IS_REVID(dev_priv, since, until))
 
 #define KBL_REVID_A0		0x0
 #define KBL_REVID_B0		0x1
@@ -2713,8 +2517,8 @@ struct drm_i915_cmd_table {
 #define KBL_REVID_D0		0x3
 #define KBL_REVID_E0		0x4
 
-#define IS_KBL_REVID(p, since, until) \
-	(IS_KABYLAKE(p) && IS_REVID(p, since, until))
+#define IS_KBL_REVID(dev_priv, since, until) \
+	(IS_KABYLAKE(dev_priv) && IS_REVID(dev_priv, since, until))
 
 /*
  * The genX designation typically refers to the render engine, so render
@@ -2722,14 +2526,14 @@ struct drm_i915_cmd_table {
  * have their own (e.g. HAS_PCH_SPLIT for ILK+ display, IS_foo for particular
  * chips, etc.).
  */
-#define IS_GEN2(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(1)))
-#define IS_GEN3(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(2)))
-#define IS_GEN4(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(3)))
-#define IS_GEN5(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(4)))
-#define IS_GEN6(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(5)))
-#define IS_GEN7(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(6)))
-#define IS_GEN8(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(7)))
-#define IS_GEN9(dev)	(!!(INTEL_INFO(dev)->gen_mask & BIT(8)))
+#define IS_GEN2(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(1)))
+#define IS_GEN3(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(2)))
+#define IS_GEN4(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(3)))
+#define IS_GEN5(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(4)))
+#define IS_GEN6(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(5)))
+#define IS_GEN7(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(6)))
+#define IS_GEN8(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(7)))
+#define IS_GEN9(dev_priv)	(!!((dev_priv)->info.gen_mask & BIT(8)))
 
 #define ENGINE_MASK(id)	BIT(id)
 #define RENDER_RING	ENGINE_MASK(RCS)
@@ -2740,31 +2544,34 @@ struct drm_i915_cmd_table {
 #define ALL_ENGINES	(~0)
 
 #define HAS_ENGINE(dev_priv, id) \
-	(!!(INTEL_INFO(dev_priv)->ring_mask & ENGINE_MASK(id)))
+	(!!((dev_priv)->info.ring_mask & ENGINE_MASK(id)))
 
 #define HAS_BSD(dev_priv)	HAS_ENGINE(dev_priv, VCS)
 #define HAS_BSD2(dev_priv)	HAS_ENGINE(dev_priv, VCS2)
 #define HAS_BLT(dev_priv)	HAS_ENGINE(dev_priv, BCS)
 #define HAS_VEBOX(dev_priv)	HAS_ENGINE(dev_priv, VECS)
 
-#define HAS_LLC(dev)		(INTEL_INFO(dev)->has_llc)
-#define HAS_SNOOP(dev)		(INTEL_INFO(dev)->has_snoop)
-#define HAS_EDRAM(dev)		(!!(__I915__(dev)->edram_cap & EDRAM_ENABLED))
-#define HAS_WT(dev)		((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \
-				 HAS_EDRAM(dev))
-#define HWS_NEEDS_PHYSICAL(dev)	(INTEL_INFO(dev)->hws_needs_physical)
+#define HAS_LLC(dev_priv)	((dev_priv)->info.has_llc)
+#define HAS_SNOOP(dev_priv)	((dev_priv)->info.has_snoop)
+#define HAS_EDRAM(dev_priv)	(!!((dev_priv)->edram_cap & EDRAM_ENABLED))
+#define HAS_WT(dev_priv)	((IS_HASWELL(dev_priv) || \
+				 IS_BROADWELL(dev_priv)) && HAS_EDRAM(dev_priv))
 
-#define HAS_HW_CONTEXTS(dev)	(INTEL_INFO(dev)->has_hw_contexts)
-#define HAS_LOGICAL_RING_CONTEXTS(dev)	(INTEL_INFO(dev)->has_logical_ring_contexts)
-#define USES_PPGTT(dev)		(i915.enable_ppgtt)
-#define USES_FULL_PPGTT(dev)	(i915.enable_ppgtt >= 2)
-#define USES_FULL_48BIT_PPGTT(dev)	(i915.enable_ppgtt == 3)
+#define HWS_NEEDS_PHYSICAL(dev_priv)	((dev_priv)->info.hws_needs_physical)
 
-#define HAS_OVERLAY(dev)		(INTEL_INFO(dev)->has_overlay)
-#define OVERLAY_NEEDS_PHYSICAL(dev)	(INTEL_INFO(dev)->overlay_needs_physical)
+#define HAS_HW_CONTEXTS(dev_priv)	    ((dev_priv)->info.has_hw_contexts)
+#define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \
+		((dev_priv)->info.has_logical_ring_contexts)
+#define USES_PPGTT(dev_priv)		(i915.enable_ppgtt)
+#define USES_FULL_PPGTT(dev_priv)	(i915.enable_ppgtt >= 2)
+#define USES_FULL_48BIT_PPGTT(dev_priv)	(i915.enable_ppgtt == 3)
+
+#define HAS_OVERLAY(dev_priv)		 ((dev_priv)->info.has_overlay)
+#define OVERLAY_NEEDS_PHYSICAL(dev_priv) \
+		((dev_priv)->info.overlay_needs_physical)
 
 /* Early gen2 have a totally busted CS tlb and require pinned batches. */
-#define HAS_BROKEN_CS_TLB(dev)		(IS_I830(dev) || IS_845G(dev))
+#define HAS_BROKEN_CS_TLB(dev_priv)	(IS_I830(dev_priv) || IS_845G(dev_priv))
 
 /* WaRsDisableCoarsePowerGating:skl,bxt */
 #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
@@ -2778,46 +2585,49 @@ struct drm_i915_cmd_table {
  * legacy irq no. is shared with another device. The kernel then disables that
  * interrupt source and so prevents the other device from working properly.
  */
-#define HAS_AUX_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
-#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->has_gmbus_irq)
+#define HAS_AUX_IRQ(dev_priv)   ((dev_priv)->info.gen >= 5)
+#define HAS_GMBUS_IRQ(dev_priv) ((dev_priv)->info.has_gmbus_irq)
 
 /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte
  * rows, which changed the alignment requirements and fence programming.
  */
-#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \
-						      IS_I915GM(dev)))
-#define SUPPORTS_TV(dev)		(INTEL_INFO(dev)->supports_tv)
-#define I915_HAS_HOTPLUG(dev)		 (INTEL_INFO(dev)->has_hotplug)
+#define HAS_128_BYTE_Y_TILING(dev_priv) (!IS_GEN2(dev_priv) && \
+					 !(IS_I915G(dev_priv) || \
+					 IS_I915GM(dev_priv)))
+#define SUPPORTS_TV(dev_priv)		((dev_priv)->info.supports_tv)
+#define I915_HAS_HOTPLUG(dev_priv)	((dev_priv)->info.has_hotplug)
 
-#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2)
-#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
-#define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
+#define HAS_FW_BLC(dev_priv) 	(INTEL_GEN(dev_priv) > 2)
+#define HAS_PIPE_CXSR(dev_priv) ((dev_priv)->info.has_pipe_cxsr)
+#define HAS_FBC(dev_priv)	((dev_priv)->info.has_fbc)
 
-#define HAS_IPS(dev)		(IS_HSW_ULT(dev) || IS_BROADWELL(dev))
+#define HAS_IPS(dev_priv)	(IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv))
 
-#define HAS_DP_MST(dev)	(INTEL_INFO(dev)->has_dp_mst)
+#define HAS_DP_MST(dev_priv)	((dev_priv)->info.has_dp_mst)
 
-#define HAS_DDI(dev)		(INTEL_INFO(dev)->has_ddi)
-#define HAS_FPGA_DBG_UNCLAIMED(dev)	(INTEL_INFO(dev)->has_fpga_dbg)
-#define HAS_PSR(dev)		(INTEL_INFO(dev)->has_psr)
-#define HAS_RUNTIME_PM(dev)	(INTEL_INFO(dev)->has_runtime_pm)
-#define HAS_RC6(dev)		(INTEL_INFO(dev)->has_rc6)
-#define HAS_RC6p(dev)		(INTEL_INFO(dev)->has_rc6p)
+#define HAS_DDI(dev_priv)		 ((dev_priv)->info.has_ddi)
+#define HAS_FPGA_DBG_UNCLAIMED(dev_priv) ((dev_priv)->info.has_fpga_dbg)
+#define HAS_PSR(dev_priv)		 ((dev_priv)->info.has_psr)
+#define HAS_RC6(dev_priv)		 ((dev_priv)->info.has_rc6)
+#define HAS_RC6p(dev_priv)		 ((dev_priv)->info.has_rc6p)
 
-#define HAS_CSR(dev)	(INTEL_INFO(dev)->has_csr)
+#define HAS_CSR(dev_priv)	((dev_priv)->info.has_csr)
+
+#define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm)
+#define HAS_64BIT_RELOC(dev_priv) ((dev_priv)->info.has_64bit_reloc)
 
 /*
  * For now, anything with a GuC requires uCode loading, and then supports
  * command submission once loaded. But these are logically independent
  * properties, so we have separate macros to test them.
  */
-#define HAS_GUC(dev)		(INTEL_INFO(dev)->has_guc)
-#define HAS_GUC_UCODE(dev)	(HAS_GUC(dev))
-#define HAS_GUC_SCHED(dev)	(HAS_GUC(dev))
+#define HAS_GUC(dev_priv)	((dev_priv)->info.has_guc)
+#define HAS_GUC_UCODE(dev_priv)	(HAS_GUC(dev_priv))
+#define HAS_GUC_SCHED(dev_priv)	(HAS_GUC(dev_priv))
 
-#define HAS_RESOURCE_STREAMER(dev) (INTEL_INFO(dev)->has_resource_streamer)
+#define HAS_RESOURCE_STREAMER(dev_priv) ((dev_priv)->info.has_resource_streamer)
 
-#define HAS_POOLED_EU(dev)	(INTEL_INFO(dev)->has_pooled_eu)
+#define HAS_POOLED_EU(dev_priv)	((dev_priv)->info.has_pooled_eu)
 
 #define INTEL_PCH_DEVICE_ID_MASK		0xff00
 #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00
@@ -2832,26 +2642,33 @@ struct drm_i915_cmd_table {
 #define INTEL_PCH_P3X_DEVICE_ID_TYPE		0x7000
 #define INTEL_PCH_QEMU_DEVICE_ID_TYPE		0x2900 /* qemu q35 has 2918 */
 
-#define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type)
-#define HAS_PCH_KBP(dev) (INTEL_PCH_TYPE(dev) == PCH_KBP)
-#define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT)
-#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)
-#define HAS_PCH_LPT_LP(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE)
-#define HAS_PCH_LPT_H(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE)
-#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)
-#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX)
-#define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
-#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
+#define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type)
+#define HAS_PCH_KBP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_KBP)
+#define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT)
+#define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT)
+#define HAS_PCH_LPT_LP(dev_priv) \
+	((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE)
+#define HAS_PCH_LPT_H(dev_priv) \
+	((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE)
+#define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT)
+#define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX)
+#define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP)
+#define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE)
 
-#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->has_gmch_display)
+#define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.has_gmch_display)
+
+#define HAS_LSPCON(dev_priv) (IS_GEN9(dev_priv))
 
 /* DPF == dynamic parity feature */
-#define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf)
-#define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev))
+#define HAS_L3_DPF(dev_priv) ((dev_priv)->info.has_l3_dpf)
+#define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \
+				 2 : HAS_L3_DPF(dev_priv))
 
 #define GT_FREQUENCY_MULTIPLIER 50
 #define GEN9_FREQ_SCALER 3
 
+#define HAS_DECOUPLED_MMIO(dev_priv) (INTEL_INFO(dev_priv)->has_decoupled_mmio)
+
 #include "i915_trace.h"
 
 static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
@@ -2882,6 +2699,8 @@ __i915_printk(struct drm_i915_private *d
 #ifdef CONFIG_COMPAT
 extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
 			      unsigned long arg);
+#else
+#define i915_compat_ioctl NULL
 #endif
 extern const struct dev_pm_ops i915_pm_ops;
 
@@ -2893,6 +2712,7 @@ extern bool intel_has_gpu_reset(struct d
 extern void i915_reset(struct drm_i915_private *dev_priv);
 extern int intel_guc_reset(struct drm_i915_private *dev_priv);
 extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
+extern void intel_hangcheck_init(struct drm_i915_private *dev_priv);
 extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
 extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
@@ -2974,7 +2794,7 @@ int intel_wait_for_register_fw(struct dr
 
 static inline bool intel_gvt_active(struct drm_i915_private *dev_priv)
 {
-	return dev_priv->gvt.initialized;
+	return dev_priv->gvt;
 }
 
 static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv)
@@ -3076,7 +2896,7 @@ int i915_gem_get_aperture_ioctl(struct d
 				struct drm_file *file_priv);
 int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
-void i915_gem_load_init(struct drm_device *dev);
+int i915_gem_load_init(struct drm_device *dev);
 void i915_gem_load_cleanup(struct drm_device *dev);
 void i915_gem_load_init_fences(struct drm_i915_private *dev_priv);
 int i915_gem_freeze(struct drm_i915_private *dev_priv);
@@ -3087,7 +2907,7 @@ void i915_gem_object_free(struct drm_i91
 void i915_gem_object_init(struct drm_i915_gem_object *obj,
 			 const struct drm_i915_gem_object_ops *ops);
 struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev,
-						  size_t size);
+						   u64 size);
 struct drm_i915_gem_object *i915_gem_object_create_from_data(
 		struct drm_device *dev, const void *data, size_t size);
 void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file);
@@ -3100,77 +2920,86 @@ i915_gem_object_ggtt_pin(struct drm_i915
 			 u64 alignment,
 			 u64 flags);
 
-int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
-		  u32 flags);
-void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
-int __must_check i915_vma_unbind(struct i915_vma *vma);
-void i915_vma_close(struct i915_vma *vma);
-void i915_vma_destroy(struct i915_vma *vma);
-
 int i915_gem_object_unbind(struct drm_i915_gem_object *obj);
-int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
-void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 
-int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
+void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv);
 
-static inline int __sg_page_count(struct scatterlist *sg)
+static inline int __sg_page_count(const struct scatterlist *sg)
 {
 	return sg->length >> PAGE_SHIFT;
 }
 
+struct scatterlist *
+i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
+		       unsigned int n, unsigned int *offset);
+
 struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n);
+i915_gem_object_get_page(struct drm_i915_gem_object *obj,
+			 unsigned int n);
 
-static inline dma_addr_t
-i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, int n)
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
+			       unsigned int n);
+
+dma_addr_t
+i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
+				unsigned long n);
+
+void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
+				 struct sg_table *pages);
+int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
+
+static inline int __must_check
+i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
 {
-	if (n < obj->get_page.last) {
-		obj->get_page.sg = obj->pages->sgl;
-		obj->get_page.last = 0;
-	}
+	might_lock(&obj->mm.lock);
 
-	while (obj->get_page.last + __sg_page_count(obj->get_page.sg) <= n) {
-		obj->get_page.last += __sg_page_count(obj->get_page.sg++);
-		if (unlikely(sg_is_chain(obj->get_page.sg)))
-			obj->get_page.sg = sg_chain_ptr(obj->get_page.sg);
-	}
+	if (atomic_inc_not_zero(&obj->mm.pages_pin_count))
+		return 0;
 
-	return sg_dma_address(obj->get_page.sg) + ((n - obj->get_page.last) << PAGE_SHIFT);
+	return __i915_gem_object_get_pages(obj);
 }
 
-static inline struct page *
-i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
+static inline void
+__i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
 {
-	if (WARN_ON(n >= obj->base.size >> PAGE_SHIFT))
-		return NULL;
-
-	if (n < obj->get_page.last) {
-		obj->get_page.sg = obj->pages->sgl;
-		obj->get_page.last = 0;
-	}
+	GEM_BUG_ON(!obj->mm.pages);
 
-	while (obj->get_page.last + __sg_page_count(obj->get_page.sg) <= n) {
-		obj->get_page.last += __sg_page_count(obj->get_page.sg++);
-		if (unlikely(sg_is_chain(obj->get_page.sg)))
-			obj->get_page.sg = sg_chain_ptr(obj->get_page.sg);
-	}
+	atomic_inc(&obj->mm.pages_pin_count);
+}
 
-	return nth_page(sg_page(obj->get_page.sg), n - obj->get_page.last);
+static inline bool
+i915_gem_object_has_pinned_pages(struct drm_i915_gem_object *obj)
+{
+	return atomic_read(&obj->mm.pages_pin_count);
 }
 
-static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
+static inline void
+__i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
 {
-	BUG_ON(obj->pages == NULL);
-	obj->pages_pin_count++;
+	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+	GEM_BUG_ON(!obj->mm.pages);
+
+	atomic_dec(&obj->mm.pages_pin_count);
+	GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count);
 }
 
-static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
+static inline void
+i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
 {
-	BUG_ON(obj->pages_pin_count == 0);
-	obj->pages_pin_count--;
+	__i915_gem_object_unpin_pages(obj);
 }
 
+enum i915_mm_subclass { /* lockdep subclass for obj->mm.lock */
+	I915_MM_NORMAL = 0,
+	I915_MM_SHRINKER
+};
+
+void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
+				 enum i915_mm_subclass subclass);
+void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj);
+
 enum i915_map_type {
 	I915_MAP_WB = 0,
 	I915_MAP_WC,
@@ -3186,8 +3015,8 @@ enum i915_map_type {
  * the kernel address space. Based on the @type of mapping, the PTE will be
  * set to either WriteBack or WriteCombine (via pgprot_t).
  *
- * The caller must hold the struct_mutex, and is responsible for calling
- * i915_gem_object_unpin_map() when the mapping is no longer required.
+ * The caller is responsible for calling i915_gem_object_unpin_map() when the
+ * mapping is no longer required.
  *
  * Returns the pointer through which to access the mapped object, or an
  * ERR_PTR() on error.
@@ -3203,12 +3032,9 @@ void *__must_check i915_gem_object_pin_m
  * with your access, call i915_gem_object_unpin_map() to release the pin
  * upon the mapping. Once the pin count reaches zero, that mapping may be
  * removed.
- *
- * The caller must hold the struct_mutex.
  */
 static inline void i915_gem_object_unpin_map(struct drm_i915_gem_object *obj)
 {
-	lockdep_assert_held(&obj->base.dev->struct_mutex);
 	i915_gem_object_unpin_pages(obj);
 }
 
@@ -3241,7 +3067,7 @@ void i915_gem_track_fb(struct drm_i915_g
 		       struct drm_i915_gem_object *new,
 		       unsigned frontbuffer_bits);
 
-int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);
+int __must_check i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno);
 
 struct drm_i915_gem_request *
 i915_gem_find_active_request(struct intel_engine_cs *engine);
@@ -3270,19 +3096,25 @@ static inline u32 i915_reset_count(struc
 
 void i915_gem_reset(struct drm_i915_private *dev_priv);
 void i915_gem_set_wedged(struct drm_i915_private *dev_priv);
-bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
+void i915_gem_clflush_object(struct drm_i915_gem_object *obj, bool force);
 int __must_check i915_gem_init(struct drm_device *dev);
 int __must_check i915_gem_init_hw(struct drm_device *dev);
-void i915_gem_init_swizzling(struct drm_device *dev);
+void i915_gem_init_swizzling(struct drm_i915_private *dev_priv);
 void i915_gem_cleanup_engines(struct drm_device *dev);
 int __must_check i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
 					unsigned int flags);
 int __must_check i915_gem_suspend(struct drm_device *dev);
 void i915_gem_resume(struct drm_device *dev);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
-int __must_check
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
-			       bool readonly);
+int i915_gem_object_wait(struct drm_i915_gem_object *obj,
+			 unsigned int flags,
+			 long timeout,
+			 struct intel_rps_client *rps);
+int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
+				  unsigned int flags,
+				  int priority);
+#define I915_PRIORITY_DISPLAY I915_PRIORITY_MAX
+
 int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
 				  bool write);
@@ -3335,64 +3167,17 @@ i915_gem_object_to_ggtt(struct drm_i915_
 	return i915_gem_obj_to_vma(obj, &to_i915(obj->base.dev)->ggtt.base, view);
 }
 
-static inline unsigned long
-i915_gem_object_ggtt_offset(struct drm_i915_gem_object *o,
-			    const struct i915_ggtt_view *view)
-{
-	return i915_ggtt_offset(i915_gem_object_to_ggtt(o, view));
-}
-
-/* i915_gem_fence.c */
+/* i915_gem_fence_reg.c */
 int __must_check i915_vma_get_fence(struct i915_vma *vma);
 int __must_check i915_vma_put_fence(struct i915_vma *vma);
 
-/**
- * i915_vma_pin_fence - pin fencing state
- * @vma: vma to pin fencing for
- *
- * This pins the fencing state (whether tiled or untiled) to make sure the
- * vma (and its object) is ready to be used as a scanout target. Fencing
- * status must be synchronize first by calling i915_vma_get_fence():
- *
- * The resulting fence pin reference must be released again with
- * i915_vma_unpin_fence().
- *
- * Returns:
- *
- * True if the vma has a fence, false otherwise.
- */
-static inline bool
-i915_vma_pin_fence(struct i915_vma *vma)
-{
-	if (vma->fence) {
-		vma->fence->pin_count++;
-		return true;
-	} else
-		return false;
-}
-
-/**
- * i915_vma_unpin_fence - unpin fencing state
- * @vma: vma to unpin fencing for
- *
- * This releases the fence pin reference acquired through
- * i915_vma_pin_fence. It will handle both objects with and without an
- * attached fence correctly, callers do not need to distinguish this.
- */
-static inline void
-i915_vma_unpin_fence(struct i915_vma *vma)
-{
-	if (vma->fence) {
-		GEM_BUG_ON(vma->fence->pin_count <= 0);
-		vma->fence->pin_count--;
-	}
-}
-
-void i915_gem_restore_fences(struct drm_device *dev);
+void i915_gem_restore_fences(struct drm_i915_private *dev_priv);
 
-void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);
-void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj);
-void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj);
+void i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv);
+void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
+				       struct sg_table *pages);
+void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
+					 struct sg_table *pages);
 
 /* i915_gem_context.c */
 int __must_check i915_gem_context_init(struct drm_device *dev);
@@ -3402,6 +3187,9 @@ int i915_gem_context_open(struct drm_dev
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
 int i915_switch_context(struct drm_i915_gem_request *req);
 int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv);
+struct i915_vma *
+i915_gem_context_pin_legacy(struct i915_gem_context *ctx,
+			    unsigned int flags);
 void i915_gem_context_free(struct kref *ctx_ref);
 struct drm_i915_gem_object *
 i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
@@ -3435,6 +3223,16 @@ static inline void i915_gem_context_put(
 	kref_put(&ctx->ref, i915_gem_context_free);
 }
 
+static inline struct intel_timeline *
+i915_gem_context_lookup_timeline(struct i915_gem_context *ctx,
+				 struct intel_engine_cs *engine)
+{
+	struct i915_address_space *vm;
+
+	vm = ctx->ppgtt ? &ctx->ppgtt->base : &ctx->i915->ggtt.base;
+	return &vm->timeline.engine[engine->id];
+}
+
 static inline bool i915_gem_context_is_default(const struct i915_gem_context *c)
 {
 	return c->user_handle == DEFAULT_CONTEXT_HANDLE;
@@ -3478,7 +3276,7 @@ int i915_gem_stolen_insert_node_in_range
 					 u64 end);
 void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
 				 struct drm_mm_node *node);
-int i915_gem_init_stolen(struct drm_device *dev);
+int i915_gem_init_stolen(struct drm_i915_private *dev_priv);
 void i915_gem_cleanup_stolen(struct drm_device *dev);
 struct drm_i915_gem_object *
 i915_gem_object_create_stolen(struct drm_device *dev, u32 size);
@@ -3488,6 +3286,11 @@ i915_gem_object_create_stolen_for_preall
 					       u32 gtt_offset,
 					       u32 size);
 
+/* i915_gem_internal.c */
+struct drm_i915_gem_object *
+i915_gem_object_create_internal(struct drm_i915_private *dev_priv,
+				unsigned int size);
+
 /* i915_gem_shrinker.c */
 unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
 			      unsigned long target,
@@ -3526,6 +3329,8 @@ static inline void intel_display_crc_ini
 #endif
 
 /* i915_gpu_error.c */
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
 __printf(2, 3)
 void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
 int i915_error_state_to_str(struct drm_i915_error_state_buf *estr,
@@ -3546,7 +3351,20 @@ void i915_error_state_get(struct drm_dev
 void i915_error_state_put(struct i915_error_state_file_priv *error_priv);
 void i915_destroy_error_state(struct drm_device *dev);
 
-void i915_get_extra_instdone(struct drm_i915_private *dev_priv, uint32_t *instdone);
+#else
+
+static inline void i915_capture_error_state(struct drm_i915_private *dev_priv,
+					    u32 engine_mask,
+					    const char *error_msg)
+{
+}
+
+static inline void i915_destroy_error_state(struct drm_device *dev)
+{
+}
+
+#endif
+
 const char *i915_cache_level_str(struct drm_i915_private *i915, int type);
 
 /* i915_cmd_parser.c */
@@ -3596,6 +3414,9 @@ bool intel_bios_is_port_dp_dual_mode(str
 bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
 bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
 				     enum port port);
+bool intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
+				enum port port);
+
 
 /* intel_opregion.c */
 #ifdef CONFIG_ACPI
@@ -3652,15 +3473,16 @@ void intel_device_info_dump(struct drm_i
 
 /* modesetting */
 extern void intel_modeset_init_hw(struct drm_device *dev);
-extern void intel_modeset_init(struct drm_device *dev);
+extern int intel_modeset_init(struct drm_device *dev);
 extern void intel_modeset_gem_init(struct drm_device *dev);
 extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_connector_register(struct drm_connector *);
 extern void intel_connector_unregister(struct drm_connector *);
-extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
+extern int intel_modeset_vga_set_state(struct drm_i915_private *dev_priv,
+				       bool state);
 extern void intel_display_resume(struct drm_device *dev);
-extern void i915_redisable_vga(struct drm_device *dev);
-extern void i915_redisable_vga_power_on(struct drm_device *dev);
+extern void i915_redisable_vga(struct drm_i915_private *dev_priv);
+extern void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv);
 extern bool ironlake_set_drps(struct drm_i915_private *dev_priv, u8 val);
 extern void intel_init_pch_refclk(struct drm_device *dev);
 extern void intel_set_rps(struct drm_i915_private *dev_priv, u8 val);
@@ -3679,11 +3501,13 @@ extern void intel_overlay_print_error_st
 extern struct intel_display_error_state *
 intel_display_capture_error_state(struct drm_i915_private *dev_priv);
 extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
-					    struct drm_device *dev,
+					    struct drm_i915_private *dev_priv,
 					    struct intel_display_error_state *error);
 
 int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val);
 int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u32 mbox, u32 val);
+int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
+		      u32 reply_mask, u32 reply, int timeout_base_ms);
 
 /* intel_sideband.c */
 u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr);
@@ -3707,6 +3531,23 @@ u32 vlv_flisdsi_read(struct drm_i915_pri
 void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val);
 
 /* intel_dpio_phy.c */
+void bxt_port_to_phy_channel(enum port port,
+			     enum dpio_phy *phy, enum dpio_channel *ch);
+void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
+				  enum port port, u32 margin, u32 scale,
+				  u32 enable, u32 deemphasis);
+void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy);
+void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy);
+bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
+			    enum dpio_phy phy);
+bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
+			      enum dpio_phy phy);
+uint8_t bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder,
+					     uint8_t lane_count);
+void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
+				     uint8_t lane_lat_optim_mask);
+uint8_t bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder);
+
 void chv_set_phy_signal_level(struct intel_encoder *encoder,
 			      u32 deemph_reg_value, u32 margin_reg_value,
 			      bool uniq_trans_scale);
@@ -3796,11 +3637,30 @@ __raw_write(64, q)
 #undef __raw_write
 
 /* These are untraced mmio-accessors that are only valid to be used inside
- * critical sections inside IRQ handlers where forcewake is explicitly
+ * critical sections, such as inside IRQ handlers, where forcewake is explicitly
  * controlled.
+ *
  * Think twice, and think again, before using these.
- * Note: Should only be used between intel_uncore_forcewake_irqlock() and
- * intel_uncore_forcewake_irqunlock().
+ *
+ * As an example, these accessors can possibly be used between:
+ *
+ * spin_lock_irq(&dev_priv->uncore.lock);
+ * intel_uncore_forcewake_get__locked();
+ *
+ * and
+ *
+ * intel_uncore_forcewake_put__locked();
+ * spin_unlock_irq(&dev_priv->uncore.lock);
+ *
+ *
+ * Note: some registers may not need forcewake held, so
+ * intel_uncore_forcewake_{get,put} can be omitted, see
+ * intel_uncore_forcewake_for_reg().
+ *
+ * Certain architectures will die if the same cacheline is concurrently accessed
+ * by different clients (e.g. on Ivybridge). Access to registers should
+ * therefore generally be serialised, by either the dev_priv->uncore.lock or
+ * a more localised lock guarding all access to that bank of registers.
  */
 #define I915_READ_FW(reg__) __raw_i915_read32(dev_priv, (reg__))
 #define I915_WRITE_FW(reg__, val__) __raw_i915_write32(dev_priv, (reg__), (val__))
@@ -3812,11 +3672,11 @@ __raw_write(64, q)
 #define INTEL_BROADCAST_RGB_FULL 1
 #define INTEL_BROADCAST_RGB_LIMITED 2
 
-static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
+static inline i915_reg_t i915_vgacntrl_reg(struct drm_i915_private *dev_priv)
 {
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		return VLV_VGACNTRL;
-	else if (INTEL_INFO(dev)->gen >= 5)
+	else if (INTEL_GEN(dev_priv) >= 5)
 		return CPU_VGACNTRL;
 	else
 		return VGACNTRL;
@@ -3877,7 +3737,7 @@ __i915_request_irq_complete(struct drm_i
 	/* Before we do the heavier coherent read of the seqno,
 	 * check the value (hopefully) in the CPU cacheline.
 	 */
-	if (i915_gem_request_completed(req))
+	if (__i915_gem_request_completed(req))
 		return true;
 
 	/* Ensure our read of the seqno is coherent so that we
@@ -3928,7 +3788,7 @@ __i915_request_irq_complete(struct drm_i
 			wake_up_process(tsk);
 		rcu_read_unlock();
 
-		if (i915_gem_request_completed(req))
+		if (__i915_gem_request_completed(req))
 			return true;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_batch_pool.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_batch_pool.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_batch_pool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_batch_pool.c	2017-02-12 16:03:20.000000000 -0500
@@ -73,7 +73,7 @@ void i915_gem_batch_pool_fini(struct i91
 		list_for_each_entry_safe(obj, next,
 					 &pool->cache_list[n],
 					 batch_pool_link)
-			i915_gem_object_put(obj);
+			__i915_gem_object_release_unless_active(obj);
 
 		INIT_LIST_HEAD(&pool->cache_list[n]);
 	}
@@ -97,9 +97,9 @@ i915_gem_batch_pool_get(struct i915_gem_
 			size_t size)
 {
 	struct drm_i915_gem_object *obj = NULL;
-	struct drm_i915_gem_object *tmp, *next;
+	struct drm_i915_gem_object *tmp;
 	struct list_head *list;
-	int n;
+	int n, ret;
 
 	lockdep_assert_held(&pool->engine->i915->drm.struct_mutex);
 
@@ -112,40 +112,35 @@ i915_gem_batch_pool_get(struct i915_gem_
 		n = ARRAY_SIZE(pool->cache_list) - 1;
 	list = &pool->cache_list[n];
 
-	list_for_each_entry_safe(tmp, next, list, batch_pool_link) {
+	list_for_each_entry(tmp, list, batch_pool_link) {
 		/* The batches are strictly LRU ordered */
-		if (!i915_gem_active_is_idle(&tmp->last_read[pool->engine->id],
-					     &tmp->base.dev->struct_mutex))
+		if (i915_gem_object_is_active(tmp))
 			break;
 
-		/* While we're looping, do some clean up */
-		if (tmp->madv == __I915_MADV_PURGED) {
-			list_del(&tmp->batch_pool_link);
-			i915_gem_object_put(tmp);
-			continue;
-		}
+		GEM_BUG_ON(!reservation_object_test_signaled_rcu(tmp->resv,
+								 true));
 
 		if (tmp->base.size >= size) {
+			/* Clear the set of shared fences early */
+			ww_mutex_lock(&tmp->resv->lock, NULL);
+			reservation_object_add_excl_fence(tmp->resv, NULL);
+			ww_mutex_unlock(&tmp->resv->lock);
+
 			obj = tmp;
 			break;
 		}
 	}
 
 	if (obj == NULL) {
-		int ret;
-
-		obj = i915_gem_object_create(&pool->engine->i915->drm, size);
+		obj = i915_gem_object_create_internal(pool->engine->i915, size);
 		if (IS_ERR(obj))
 			return obj;
-
-		ret = i915_gem_object_get_pages(obj);
-		if (ret)
-			return ERR_PTR(ret);
-
-		obj->madv = I915_MADV_DONTNEED;
 	}
 
+	ret = i915_gem_object_pin_pages(obj);
+	if (ret)
+		return ERR_PTR(ret);
+
 	list_move_tail(&obj->batch_pool_link, list);
-	i915_gem_object_pin_pages(obj);
 	return obj;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,12 +29,12 @@
 #include <drm/drm_vma_manager.h>
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
-#include "i915_gem_dmabuf.h"
 #include "i915_vgpu.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
 #include "intel_frontbuffer.h"
 #include "intel_mocs.h"
+#include <linux/dma-fence-array.h>
 #include <linux/reservation.h>
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
@@ -42,13 +42,14 @@
 #include <linux/pci.h>
 #include <linux/dma-buf.h>
 
+static void i915_gem_flush_free_objects(struct drm_i915_private *i915);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
 
 static bool cpu_cache_is_coherent(struct drm_device *dev,
 				  enum i915_cache_level level)
 {
-	return HAS_LLC(dev) || level != I915_CACHE_NONE;
+	return HAS_LLC(to_i915(dev)) || level != I915_CACHE_NONE;
 }
 
 static bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj)
@@ -63,13 +64,13 @@ static bool cpu_write_needs_clflush(stru
 }
 
 static int
-insert_mappable_node(struct drm_i915_private *i915,
+insert_mappable_node(struct i915_ggtt *ggtt,
                      struct drm_mm_node *node, u32 size)
 {
 	memset(node, 0, sizeof(*node));
-	return drm_mm_insert_node_in_range_generic(&i915->ggtt.base.mm, node,
-						   size, 0, 0, 0,
-						   i915->ggtt.mappable_end,
+	return drm_mm_insert_node_in_range_generic(&ggtt->base.mm, node,
+						   size, 0, -1,
+						   0, ggtt->mappable_end,
 						   DRM_MM_SEARCH_DEFAULT,
 						   DRM_MM_CREATE_DEFAULT);
 }
@@ -82,7 +83,7 @@ remove_mappable_node(struct drm_mm_node
 
 /* some bookkeeping */
 static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
-				  size_t size)
+				  u64 size)
 {
 	spin_lock(&dev_priv->mm.object_stat_lock);
 	dev_priv->mm.object_count++;
@@ -91,7 +92,7 @@ static void i915_gem_info_add_obj(struct
 }
 
 static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv,
-				     size_t size)
+				     u64 size)
 {
 	spin_lock(&dev_priv->mm.object_stat_lock);
 	dev_priv->mm.object_count--;
@@ -104,6 +105,8 @@ i915_gem_wait_for_error(struct i915_gpu_
 {
 	int ret;
 
+	might_sleep();
+
 	if (!i915_reset_in_progress(error))
 		return 0;
 
@@ -114,7 +117,7 @@ i915_gem_wait_for_error(struct i915_gpu_
 	 */
 	ret = wait_event_interruptible_timeout(error->reset_queue,
 					       !i915_reset_in_progress(error),
-					       10*HZ);
+					       I915_RESET_TIMEOUT);
 	if (ret == 0) {
 		DRM_ERROR("Timed out waiting for the gpu reset to complete\n");
 		return -EIO;
@@ -167,25 +170,39 @@ i915_gem_get_aperture_ioctl(struct drm_d
 	return 0;
 }
 
-static int
+static struct sg_table *
 i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 {
 	struct address_space *mapping = obj->base.filp->f_mapping;
-	char *vaddr = obj->phys_handle->vaddr;
+	drm_dma_handle_t *phys;
 	struct sg_table *st;
 	struct scatterlist *sg;
+	char *vaddr;
 	int i;
 
 	if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
+
+	/* Always aligning to the object size, allows a single allocation
+	 * to handle all possible callers, and given typical object sizes,
+	 * the alignment of the buddy allocation will naturally match.
+	 */
+	phys = drm_pci_alloc(obj->base.dev,
+			     obj->base.size,
+			     roundup_pow_of_two(obj->base.size));
+	if (!phys)
+		return ERR_PTR(-ENOMEM);
 
+	vaddr = phys->vaddr;
 	for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
 		struct page *page;
 		char *src;
 
 		page = shmem_read_mapping_page(mapping, i);
-		if (IS_ERR(page))
-			return PTR_ERR(page);
+		if (IS_ERR(page)) {
+			st = ERR_CAST(page);
+			goto err_phys;
+		}
 
 		src = kmap_atomic(page);
 		memcpy(vaddr, src, PAGE_SIZE);
@@ -199,44 +216,58 @@ i915_gem_object_get_pages_phys(struct dr
 	i915_gem_chipset_flush(to_i915(obj->base.dev));
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
-	if (st == NULL)
-		return -ENOMEM;
+	if (!st) {
+		st = ERR_PTR(-ENOMEM);
+		goto err_phys;
+	}
 
 	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
 		kfree(st);
-		return -ENOMEM;
+		st = ERR_PTR(-ENOMEM);
+		goto err_phys;
 	}
 
 	sg = st->sgl;
 	sg->offset = 0;
 	sg->length = obj->base.size;
 
-	sg_dma_address(sg) = obj->phys_handle->busaddr;
+	sg_dma_address(sg) = phys->busaddr;
 	sg_dma_len(sg) = obj->base.size;
 
-	obj->pages = st;
-	return 0;
+	obj->phys_handle = phys;
+	return st;
+
+err_phys:
+	drm_pci_free(obj->base.dev, phys);
+	return st;
 }
 
 static void
-i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj)
+__i915_gem_object_release_shmem(struct drm_i915_gem_object *obj,
+				struct sg_table *pages,
+				bool needs_clflush)
 {
-	int ret;
+	GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED);
 
-	BUG_ON(obj->madv == __I915_MADV_PURGED);
+	if (obj->mm.madv == I915_MADV_DONTNEED)
+		obj->mm.dirty = false;
 
-	ret = i915_gem_object_set_to_cpu_domain(obj, true);
-	if (WARN_ON(ret)) {
-		/* In the event of a disaster, abandon all caches and
-		 * hope for the best.
-		 */
-		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
-	}
+	if (needs_clflush &&
+	    (obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0 &&
+	    !cpu_cache_is_coherent(obj->base.dev, obj->cache_level))
+		drm_clflush_sg(pages);
 
-	if (obj->madv == I915_MADV_DONTNEED)
-		obj->dirty = 0;
+	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+}
 
-	if (obj->dirty) {
+static void
+i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
+			       struct sg_table *pages)
+{
+	__i915_gem_object_release_shmem(obj, pages, false);
+
+	if (obj->mm.dirty) {
 		struct address_space *mapping = obj->base.filp->f_mapping;
 		char *vaddr = obj->phys_handle->vaddr;
 		int i;
@@ -255,22 +286,24 @@ i915_gem_object_put_pages_phys(struct dr
 			kunmap_atomic(dst);
 
 			set_page_dirty(page);
-			if (obj->madv == I915_MADV_WILLNEED)
+			if (obj->mm.madv == I915_MADV_WILLNEED)
 				mark_page_accessed(page);
 			put_page(page);
 			vaddr += PAGE_SIZE;
 		}
-		obj->dirty = 0;
+		obj->mm.dirty = false;
 	}
 
-	sg_free_table(obj->pages);
-	kfree(obj->pages);
+	sg_free_table(pages);
+	kfree(pages);
+
+	drm_pci_free(obj->base.dev, obj->phys_handle);
 }
 
 static void
 i915_gem_object_release_phys(struct drm_i915_gem_object *obj)
 {
-	drm_pci_free(obj->base.dev, obj->phys_handle);
+	i915_gem_object_unpin_pages(obj);
 }
 
 static const struct drm_i915_gem_object_ops i915_gem_phys_ops = {
@@ -292,7 +325,12 @@ int i915_gem_object_unbind(struct drm_i9
 	 * must wait for all rendering to complete to the object (as unbinding
 	 * must anyway), and retire the requests.
 	 */
-	ret = i915_gem_object_wait_rendering(obj, false);
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_LOCKED |
+				   I915_WAIT_ALL,
+				   MAX_SCHEDULE_TIMEOUT,
+				   NULL);
 	if (ret)
 		return ret;
 
@@ -311,90 +349,209 @@ int i915_gem_object_unbind(struct drm_i9
 	return ret;
 }
 
-/**
- * Ensures that all rendering to the object has completed and the object is
- * safe to unbind from the GTT or access from the CPU.
- * @obj: i915 gem object
- * @readonly: waiting for just read access or read-write access
- */
-int
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
-			       bool readonly)
+static long
+i915_gem_object_wait_fence(struct dma_fence *fence,
+			   unsigned int flags,
+			   long timeout,
+			   struct intel_rps_client *rps)
 {
-	struct reservation_object *resv;
-	struct i915_gem_active *active;
-	unsigned long active_mask;
-	int idx;
+	struct drm_i915_gem_request *rq;
 
-	lockdep_assert_held(&obj->base.dev->struct_mutex);
+	BUILD_BUG_ON(I915_WAIT_INTERRUPTIBLE != 0x1);
 
-	if (!readonly) {
-		active = obj->last_read;
-		active_mask = i915_gem_object_get_active(obj);
-	} else {
-		active_mask = 1;
-		active = &obj->last_write;
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		return timeout;
+
+	if (!dma_fence_is_i915(fence))
+		return dma_fence_wait_timeout(fence,
+					      flags & I915_WAIT_INTERRUPTIBLE,
+					      timeout);
+
+	rq = to_request(fence);
+	if (i915_gem_request_completed(rq))
+		goto out;
+
+	/* This client is about to stall waiting for the GPU. In many cases
+	 * this is undesirable and limits the throughput of the system, as
+	 * many clients cannot continue processing user input/output whilst
+	 * blocked. RPS autotuning may take tens of milliseconds to respond
+	 * to the GPU load and thus incurs additional latency for the client.
+	 * We can circumvent that by promoting the GPU frequency to maximum
+	 * before we wait. This makes the GPU throttle up much more quickly
+	 * (good for benchmarks and user experience, e.g. window animations),
+	 * but at a cost of spending more power processing the workload
+	 * (bad for battery). Not all clients even want their results
+	 * immediately and for them we should just let the GPU select its own
+	 * frequency to maximise efficiency. To prevent a single client from
+	 * forcing the clocks too high for the whole system, we only allow
+	 * each client to waitboost once in a busy period.
+	 */
+	if (rps) {
+		if (INTEL_GEN(rq->i915) >= 6)
+			gen6_rps_boost(rq->i915, rps, rq->emitted_jiffies);
+		else
+			rps = NULL;
 	}
 
-	for_each_active(active_mask, idx) {
+	timeout = i915_wait_request(rq, flags, timeout);
+
+out:
+	if (flags & I915_WAIT_LOCKED && i915_gem_request_completed(rq))
+		i915_gem_request_retire_upto(rq);
+
+	if (rps && rq->global_seqno == intel_engine_last_submit(rq->engine)) {
+		/* The GPU is now idle and this client has stalled.
+		 * Since no other client has submitted a request in the
+		 * meantime, assume that this client is the only one
+		 * supplying work to the GPU but is unable to keep that
+		 * work supplied because it is waiting. Since the GPU is
+		 * then never kept fully busy, RPS autoclocking will
+		 * keep the clocks relatively low, causing further delays.
+		 * Compensate by giving the synchronous client credit for
+		 * a waitboost next time.
+		 */
+		spin_lock(&rq->i915->rps.client_lock);
+		list_del_init(&rps->link);
+		spin_unlock(&rq->i915->rps.client_lock);
+	}
+
+	return timeout;
+}
+
+static long
+i915_gem_object_wait_reservation(struct reservation_object *resv,
+				 unsigned int flags,
+				 long timeout,
+				 struct intel_rps_client *rps)
+{
+	struct dma_fence *excl;
+
+	if (flags & I915_WAIT_ALL) {
+		struct dma_fence **shared;
+		unsigned int count, i;
 		int ret;
 
-		ret = i915_gem_active_wait(&active[idx],
-					   &obj->base.dev->struct_mutex);
+		ret = reservation_object_get_fences_rcu(resv,
+							&excl, &count, &shared);
 		if (ret)
 			return ret;
-	}
 
-	resv = i915_gem_object_get_dmabuf_resv(obj);
-	if (resv) {
-		long err;
+		for (i = 0; i < count; i++) {
+			timeout = i915_gem_object_wait_fence(shared[i],
+							     flags, timeout,
+							     rps);
+			if (timeout <= 0)
+				break;
 
-		err = reservation_object_wait_timeout_rcu(resv, !readonly, true,
-							  MAX_SCHEDULE_TIMEOUT);
-		if (err < 0)
-			return err;
+			dma_fence_put(shared[i]);
+		}
+
+		for (; i < count; i++)
+			dma_fence_put(shared[i]);
+		kfree(shared);
+	} else {
+		excl = reservation_object_get_excl_rcu(resv);
 	}
 
-	return 0;
+	if (excl && timeout > 0)
+		timeout = i915_gem_object_wait_fence(excl, flags, timeout, rps);
+
+	dma_fence_put(excl);
+
+	return timeout;
 }
 
-/* A nonblocking variant of the above wait. Must be called prior to
- * acquiring the mutex for the object, as the object state may change
- * during this call. A reference must be held by the caller for the object.
- */
-static __must_check int
-__unsafe_wait_rendering(struct drm_i915_gem_object *obj,
-			struct intel_rps_client *rps,
-			bool readonly)
+static void __fence_set_priority(struct dma_fence *fence, int prio)
 {
-	struct i915_gem_active *active;
-	unsigned long active_mask;
-	int idx;
+	struct drm_i915_gem_request *rq;
+	struct intel_engine_cs *engine;
 
-	active_mask = __I915_BO_ACTIVE(obj);
-	if (!active_mask)
-		return 0;
+	if (!dma_fence_is_i915(fence))
+		return;
 
-	if (!readonly) {
-		active = obj->last_read;
+	rq = to_request(fence);
+	engine = rq->engine;
+	if (!engine->schedule)
+		return;
+
+	engine->schedule(rq, prio);
+}
+
+static void fence_set_priority(struct dma_fence *fence, int prio)
+{
+	/* Recurse once into a fence-array */
+	if (dma_fence_is_array(fence)) {
+		struct dma_fence_array *array = to_dma_fence_array(fence);
+		int i;
+
+		for (i = 0; i < array->num_fences; i++)
+			__fence_set_priority(array->fences[i], prio);
 	} else {
-		active_mask = 1;
-		active = &obj->last_write;
+		__fence_set_priority(fence, prio);
 	}
+}
 
-	for_each_active(active_mask, idx) {
+int
+i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
+			      unsigned int flags,
+			      int prio)
+{
+	struct dma_fence *excl;
+
+	if (flags & I915_WAIT_ALL) {
+		struct dma_fence **shared;
+		unsigned int count, i;
 		int ret;
 
-		ret = i915_gem_active_wait_unlocked(&active[idx],
-						    I915_WAIT_INTERRUPTIBLE,
-						    NULL, rps);
+		ret = reservation_object_get_fences_rcu(obj->resv,
+							&excl, &count, &shared);
 		if (ret)
 			return ret;
+
+		for (i = 0; i < count; i++) {
+			fence_set_priority(shared[i], prio);
+			dma_fence_put(shared[i]);
+		}
+
+		kfree(shared);
+	} else {
+		excl = reservation_object_get_excl_rcu(obj->resv);
 	}
 
+	if (excl) {
+		fence_set_priority(excl, prio);
+		dma_fence_put(excl);
+	}
 	return 0;
 }
 
+/**
+ * Waits for rendering to the object to be completed
+ * @obj: i915 gem object
+ * @flags: how to wait (under a lock, for all rendering or just for writes etc)
+ * @timeout: how long to wait
+ * @rps: client (user process) to charge for any waitboosting
+ */
+int
+i915_gem_object_wait(struct drm_i915_gem_object *obj,
+		     unsigned int flags,
+		     long timeout,
+		     struct intel_rps_client *rps)
+{
+	might_sleep();
+#if IS_ENABLED(CONFIG_LOCKDEP)
+	GEM_BUG_ON(debug_locks &&
+		   !!lockdep_is_held(&obj->base.dev->struct_mutex) !=
+		   !!(flags & I915_WAIT_LOCKED));
+#endif
+	GEM_BUG_ON(timeout < 0);
+
+	timeout = i915_gem_object_wait_reservation(obj->resv,
+						   flags, timeout,
+						   rps);
+	return timeout < 0 ? timeout : 0;
+}
+
 static struct intel_rps_client *to_rps_client(struct drm_file *file)
 {
 	struct drm_i915_file_private *fpriv = file->driver_priv;
@@ -406,17 +563,15 @@ int
 i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
 			    int align)
 {
-	drm_dma_handle_t *phys;
 	int ret;
 
-	if (obj->phys_handle) {
-		if ((unsigned long)obj->phys_handle->vaddr & (align -1))
-			return -EBUSY;
+	if (align > obj->base.size)
+		return -EINVAL;
 
+	if (obj->ops == &i915_gem_phys_ops)
 		return 0;
-	}
 
-	if (obj->madv != I915_MADV_WILLNEED)
+	if (obj->mm.madv != I915_MADV_WILLNEED)
 		return -EFAULT;
 
 	if (obj->base.filp == NULL)
@@ -426,61 +581,35 @@ i915_gem_object_attach_phys(struct drm_i
 	if (ret)
 		return ret;
 
-	ret = i915_gem_object_put_pages(obj);
-	if (ret)
-		return ret;
-
-	/* create a new object */
-	phys = drm_pci_alloc(obj->base.dev, obj->base.size, align);
-	if (!phys)
-		return -ENOMEM;
+	__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
+	if (obj->mm.pages)
+		return -EBUSY;
 
-	obj->phys_handle = phys;
 	obj->ops = &i915_gem_phys_ops;
 
-	return i915_gem_object_get_pages(obj);
+	return i915_gem_object_pin_pages(obj);
 }
 
 static int
 i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
 		     struct drm_i915_gem_pwrite *args,
-		     struct drm_file *file_priv)
+		     struct drm_file *file)
 {
-	struct drm_device *dev = obj->base.dev;
 	void *vaddr = obj->phys_handle->vaddr + args->offset;
 	char __user *user_data = u64_to_user_ptr(args->data_ptr);
-	int ret = 0;
 
 	/* We manually control the domain here and pretend that it
 	 * remains coherent i.e. in the GTT domain, like shmem_pwrite.
 	 */
-	ret = i915_gem_object_wait_rendering(obj, false);
-	if (ret)
-		return ret;
-
 	intel_fb_obj_invalidate(obj, ORIGIN_CPU);
-	if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
-		unsigned long unwritten;
-
-		/* The physical object once assigned is fixed for the lifetime
-		 * of the obj, so we can safely drop the lock and continue
-		 * to access vaddr.
-		 */
-		mutex_unlock(&dev->struct_mutex);
-		unwritten = copy_from_user(vaddr, user_data, args->size);
-		mutex_lock(&dev->struct_mutex);
-		if (unwritten) {
-			ret = -EFAULT;
-			goto out;
-		}
-	}
+	if (copy_from_user(vaddr, user_data, args->size))
+		return -EFAULT;
 
 	drm_clflush_virt_range(vaddr, args->size);
-	i915_gem_chipset_flush(to_i915(dev));
+	i915_gem_chipset_flush(to_i915(obj->base.dev));
 
-out:
 	intel_fb_obj_flush(obj, false, ORIGIN_CPU);
-	return ret;
+	return 0;
 }
 
 void *i915_gem_object_alloc(struct drm_device *dev)
@@ -516,7 +645,7 @@ i915_gem_create(struct drm_file *file,
 
 	ret = drm_gem_handle_create(file, &obj->base, &handle);
 	/* drop reference from allocate - handle holds it now */
-	i915_gem_object_put_unlocked(obj);
+	i915_gem_object_put(obj);
 	if (ret)
 		return ret;
 
@@ -548,6 +677,8 @@ i915_gem_create_ioctl(struct drm_device
 {
 	struct drm_i915_gem_create *args = data;
 
+	i915_gem_flush_free_objects(to_i915(dev));
+
 	return i915_gem_create(file, dev,
 			       args->size, &args->handle);
 }
@@ -614,21 +745,24 @@ int i915_gem_obj_prepare_shmem_read(stru
 {
 	int ret;
 
-	*needs_clflush = 0;
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
 
+	*needs_clflush = 0;
 	if (!i915_gem_object_has_struct_page(obj))
 		return -ENODEV;
 
-	ret = i915_gem_object_wait_rendering(obj, true);
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_LOCKED,
+				   MAX_SCHEDULE_TIMEOUT,
+				   NULL);
 	if (ret)
 		return ret;
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		return ret;
 
-	i915_gem_object_pin_pages(obj);
-
 	i915_gem_object_flush_gtt_write_domain(obj);
 
 	/* If we're not in the cpu read domain, set ourself into the gtt
@@ -661,20 +795,25 @@ int i915_gem_obj_prepare_shmem_write(str
 {
 	int ret;
 
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
 	*needs_clflush = 0;
 	if (!i915_gem_object_has_struct_page(obj))
 		return -ENODEV;
 
-	ret = i915_gem_object_wait_rendering(obj, false);
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_LOCKED |
+				   I915_WAIT_ALL,
+				   MAX_SCHEDULE_TIMEOUT,
+				   NULL);
 	if (ret)
 		return ret;
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		return ret;
 
-	i915_gem_object_pin_pages(obj);
-
 	i915_gem_object_flush_gtt_write_domain(obj);
 
 	/* If we're not in the cpu write domain, set ourself into the
@@ -704,7 +843,7 @@ int i915_gem_obj_prepare_shmem_write(str
 		obj->cache_dirty = true;
 
 	intel_fb_obj_invalidate(obj, ORIGIN_CPU);
-	obj->dirty = 1;
+	obj->mm.dirty = true;
 	/* return with the pages pinned */
 	return 0;
 
@@ -713,32 +852,6 @@ err_unpin:
 	return ret;
 }
 
-/* Per-page copy function for the shmem pread fastpath.
- * Flushes invalid cachelines before reading the target if
- * needs_clflush is set. */
-static int
-shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length,
-		 char __user *user_data,
-		 bool page_do_bit17_swizzling, bool needs_clflush)
-{
-	char *vaddr;
-	int ret;
-
-	if (unlikely(page_do_bit17_swizzling))
-		return -EINVAL;
-
-	vaddr = kmap_atomic(page);
-	if (needs_clflush)
-		drm_clflush_virt_range(vaddr + shmem_page_offset,
-				       page_length);
-	ret = __copy_to_user_inatomic(user_data,
-				      vaddr + shmem_page_offset,
-				      page_length);
-	kunmap_atomic(vaddr);
-
-	return ret ? -EFAULT : 0;
-}
-
 static void
 shmem_clflush_swizzled_range(char *addr, unsigned long length,
 			     bool swizzled)
@@ -764,7 +877,7 @@ shmem_clflush_swizzled_range(char *addr,
 /* Only difference to the fast-path function is that this can handle bit17
  * and uses non-atomic copy and kmap functions. */
 static int
-shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length,
+shmem_pread_slow(struct page *page, int offset, int length,
 		 char __user *user_data,
 		 bool page_do_bit17_swizzling, bool needs_clflush)
 {
@@ -773,60 +886,130 @@ shmem_pread_slow(struct page *page, int
 
 	vaddr = kmap(page);
 	if (needs_clflush)
-		shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
-					     page_length,
+		shmem_clflush_swizzled_range(vaddr + offset, length,
 					     page_do_bit17_swizzling);
 
 	if (page_do_bit17_swizzling)
-		ret = __copy_to_user_swizzled(user_data,
-					      vaddr, shmem_page_offset,
-					      page_length);
+		ret = __copy_to_user_swizzled(user_data, vaddr, offset, length);
 	else
-		ret = __copy_to_user(user_data,
-				     vaddr + shmem_page_offset,
-				     page_length);
+		ret = __copy_to_user(user_data, vaddr + offset, length);
 	kunmap(page);
 
 	return ret ? - EFAULT : 0;
 }
 
-static inline unsigned long
-slow_user_access(struct io_mapping *mapping,
-		 uint64_t page_base, int page_offset,
-		 char __user *user_data,
-		 unsigned long length, bool pwrite)
+static int
+shmem_pread(struct page *page, int offset, int length, char __user *user_data,
+	    bool page_do_bit17_swizzling, bool needs_clflush)
+{
+	int ret;
+
+	ret = -ENODEV;
+	if (!page_do_bit17_swizzling) {
+		char *vaddr = kmap_atomic(page);
+
+		if (needs_clflush)
+			drm_clflush_virt_range(vaddr + offset, length);
+		ret = __copy_to_user_inatomic(user_data, vaddr + offset, length);
+		kunmap_atomic(vaddr);
+	}
+	if (ret == 0)
+		return 0;
+
+	return shmem_pread_slow(page, offset, length, user_data,
+				page_do_bit17_swizzling, needs_clflush);
+}
+
+static int
+i915_gem_shmem_pread(struct drm_i915_gem_object *obj,
+		     struct drm_i915_gem_pread *args)
+{
+	char __user *user_data;
+	u64 remain;
+	unsigned int obj_do_bit17_swizzling;
+	unsigned int needs_clflush;
+	unsigned int idx, offset;
+	int ret;
+
+	obj_do_bit17_swizzling = 0;
+	if (i915_gem_object_needs_bit17_swizzle(obj))
+		obj_do_bit17_swizzling = BIT(17);
+
+	ret = mutex_lock_interruptible(&obj->base.dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush);
+	mutex_unlock(&obj->base.dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	remain = args->size;
+	user_data = u64_to_user_ptr(args->data_ptr);
+	offset = offset_in_page(args->offset);
+	for (idx = args->offset >> PAGE_SHIFT; remain; idx++) {
+		struct page *page = i915_gem_object_get_page(obj, idx);
+		int length;
+
+		length = remain;
+		if (offset + length > PAGE_SIZE)
+			length = PAGE_SIZE - offset;
+
+		ret = shmem_pread(page, offset, length, user_data,
+				  page_to_phys(page) & obj_do_bit17_swizzling,
+				  needs_clflush);
+		if (ret)
+			break;
+
+		remain -= length;
+		user_data += length;
+		offset = 0;
+	}
+
+	i915_gem_obj_finish_shmem_access(obj);
+	return ret;
+}
+
+static inline bool
+gtt_user_read(struct io_mapping *mapping,
+	      loff_t base, int offset,
+	      char __user *user_data, int length)
 {
-	void __iomem *ioaddr;
 	void *vaddr;
-	uint64_t unwritten;
+	unsigned long unwritten;
 
-	ioaddr = io_mapping_map_wc(mapping, page_base, PAGE_SIZE);
 	/* We can use the cpu mem copy function because this is X86. */
-	vaddr = (void __force *)ioaddr + page_offset;
-	if (pwrite)
-		unwritten = __copy_from_user(vaddr, user_data, length);
-	else
-		unwritten = __copy_to_user(user_data, vaddr, length);
-
-	io_mapping_unmap(ioaddr);
+	vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base);
+	unwritten = __copy_to_user_inatomic(user_data, vaddr + offset, length);
+	io_mapping_unmap_atomic(vaddr);
+	if (unwritten) {
+		vaddr = (void __force *)
+			io_mapping_map_wc(mapping, base, PAGE_SIZE);
+		unwritten = copy_to_user(user_data, vaddr + offset, length);
+		io_mapping_unmap(vaddr);
+	}
 	return unwritten;
 }
 
 static int
-i915_gem_gtt_pread(struct drm_device *dev,
-		   struct drm_i915_gem_object *obj, uint64_t size,
-		   uint64_t data_offset, uint64_t data_ptr)
+i915_gem_gtt_pread(struct drm_i915_gem_object *obj,
+		   const struct drm_i915_gem_pread *args)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct i915_ggtt *ggtt = &dev_priv->ggtt;
-	struct i915_vma *vma;
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	struct i915_ggtt *ggtt = &i915->ggtt;
 	struct drm_mm_node node;
-	char __user *user_data;
-	uint64_t remain;
-	uint64_t offset;
+	struct i915_vma *vma;
+	void __user *user_data;
+	u64 remain, offset;
 	int ret;
 
-	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
+	ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
+	if (ret)
+		return ret;
+
+	intel_runtime_pm_get(i915);
+	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
+				       PIN_MAPPABLE | PIN_NONBLOCK);
 	if (!IS_ERR(vma)) {
 		node.start = i915_ggtt_offset(vma);
 		node.allocated = false;
@@ -837,35 +1020,21 @@ i915_gem_gtt_pread(struct drm_device *de
 		}
 	}
 	if (IS_ERR(vma)) {
-		ret = insert_mappable_node(dev_priv, &node, PAGE_SIZE);
+		ret = insert_mappable_node(ggtt, &node, PAGE_SIZE);
 		if (ret)
-			goto out;
-
-		ret = i915_gem_object_get_pages(obj);
-		if (ret) {
-			remove_mappable_node(&node);
-			goto out;
-		}
-
-		i915_gem_object_pin_pages(obj);
+			goto out_unlock;
+		GEM_BUG_ON(!node.allocated);
 	}
 
 	ret = i915_gem_object_set_to_gtt_domain(obj, false);
 	if (ret)
 		goto out_unpin;
 
-	user_data = u64_to_user_ptr(data_ptr);
-	remain = size;
-	offset = data_offset;
+	mutex_unlock(&i915->drm.struct_mutex);
 
-	mutex_unlock(&dev->struct_mutex);
-	if (likely(!i915.prefault_disable)) {
-		ret = fault_in_pages_writeable(user_data, remain);
-		if (ret) {
-			mutex_lock(&dev->struct_mutex);
-			goto out_unpin;
-		}
-	}
+	user_data = u64_to_user_ptr(args->data_ptr);
+	remain = args->size;
+	offset = args->offset;
 
 	while (remain > 0) {
 		/* Operation in this page
@@ -882,19 +1051,14 @@ i915_gem_gtt_pread(struct drm_device *de
 			wmb();
 			ggtt->base.insert_page(&ggtt->base,
 					       i915_gem_object_get_dma_address(obj, offset >> PAGE_SHIFT),
-					       node.start,
-					       I915_CACHE_NONE, 0);
+					       node.start, I915_CACHE_NONE, 0);
 			wmb();
 		} else {
 			page_base += offset & PAGE_MASK;
 		}
-		/* This is a slow read/write as it tries to read from
-		 * and write to user memory which may result into page
-		 * faults, and so we cannot perform this under struct_mutex.
-		 */
-		if (slow_user_access(&ggtt->mappable, page_base,
-				     page_offset, user_data,
-				     page_length, false)) {
+
+		if (gtt_user_read(&ggtt->mappable, page_base, page_offset,
+				  user_data, page_length)) {
 			ret = -EFAULT;
 			break;
 		}
@@ -904,111 +1068,19 @@ i915_gem_gtt_pread(struct drm_device *de
 		offset += page_length;
 	}
 
-	mutex_lock(&dev->struct_mutex);
-	if (ret == 0 && (obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) {
-		/* The user has modified the object whilst we tried
-		 * reading from it, and we now have no idea what domain
-		 * the pages should be in. As we have just been touching
-		 * them directly, flush everything back to the GTT
-		 * domain.
-		 */
-		ret = i915_gem_object_set_to_gtt_domain(obj, false);
-	}
-
+	mutex_lock(&i915->drm.struct_mutex);
 out_unpin:
 	if (node.allocated) {
 		wmb();
 		ggtt->base.clear_range(&ggtt->base,
-				       node.start, node.size,
-				       true);
-		i915_gem_object_unpin_pages(obj);
+				       node.start, node.size);
 		remove_mappable_node(&node);
 	} else {
 		i915_vma_unpin(vma);
 	}
-out:
-	return ret;
-}
-
-static int
-i915_gem_shmem_pread(struct drm_device *dev,
-		     struct drm_i915_gem_object *obj,
-		     struct drm_i915_gem_pread *args,
-		     struct drm_file *file)
-{
-	char __user *user_data;
-	ssize_t remain;
-	loff_t offset;
-	int shmem_page_offset, page_length, ret = 0;
-	int obj_do_bit17_swizzling, page_do_bit17_swizzling;
-	int prefaulted = 0;
-	int needs_clflush = 0;
-	struct sg_page_iter sg_iter;
-
-	ret = i915_gem_obj_prepare_shmem_read(obj, &needs_clflush);
-	if (ret)
-		return ret;
-
-	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
-	user_data = u64_to_user_ptr(args->data_ptr);
-	offset = args->offset;
-	remain = args->size;
-
-	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
-			 offset >> PAGE_SHIFT) {
-		struct page *page = sg_page_iter_page(&sg_iter);
-
-		if (remain <= 0)
-			break;
-
-		/* Operation in this page
-		 *
-		 * shmem_page_offset = offset within page in shmem file
-		 * page_length = bytes to copy for this page
-		 */
-		shmem_page_offset = offset_in_page(offset);
-		page_length = remain;
-		if ((shmem_page_offset + page_length) > PAGE_SIZE)
-			page_length = PAGE_SIZE - shmem_page_offset;
-
-		page_do_bit17_swizzling = obj_do_bit17_swizzling &&
-			(page_to_phys(page) & (1 << 17)) != 0;
-
-		ret = shmem_pread_fast(page, shmem_page_offset, page_length,
-				       user_data, page_do_bit17_swizzling,
-				       needs_clflush);
-		if (ret == 0)
-			goto next_page;
-
-		mutex_unlock(&dev->struct_mutex);
-
-		if (likely(!i915.prefault_disable) && !prefaulted) {
-			ret = fault_in_pages_writeable(user_data, remain);
-			/* Userspace is tricking us, but we've already clobbered
-			 * its pages with the prefault and promised to write the
-			 * data up to the first fault. Hence ignore any errors
-			 * and just continue. */
-			(void)ret;
-			prefaulted = 1;
-		}
-
-		ret = shmem_pread_slow(page, shmem_page_offset, page_length,
-				       user_data, page_do_bit17_swizzling,
-				       needs_clflush);
-
-		mutex_lock(&dev->struct_mutex);
-
-		if (ret)
-			goto out;
-
-next_page:
-		remain -= page_length;
-		user_data += page_length;
-		offset += page_length;
-	}
-
-out:
-	i915_gem_obj_finish_shmem_access(obj);
+out_unlock:
+	intel_runtime_pm_put(i915);
+	mutex_unlock(&i915->drm.struct_mutex);
 
 	return ret;
 }
@@ -1027,7 +1099,7 @@ i915_gem_pread_ioctl(struct drm_device *
 {
 	struct drm_i915_gem_pread *args = data;
 	struct drm_i915_gem_object *obj;
-	int ret = 0;
+	int ret;
 
 	if (args->size == 0)
 		return 0;
@@ -1045,36 +1117,29 @@ i915_gem_pread_ioctl(struct drm_device *
 	if (args->offset > obj->base.size ||
 	    args->size > obj->base.size - args->offset) {
 		ret = -EINVAL;
-		goto err;
+		goto out;
 	}
 
 	trace_i915_gem_object_pread(obj, args->offset, args->size);
 
-	ret = __unsafe_wait_rendering(obj, to_rps_client(file), true);
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE,
+				   MAX_SCHEDULE_TIMEOUT,
+				   to_rps_client(file));
 	if (ret)
-		goto err;
+		goto out;
 
-	ret = i915_mutex_lock_interruptible(dev);
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
-		goto err;
-
-	ret = i915_gem_shmem_pread(dev, obj, args, file);
+		goto out;
 
-	/* pread for non shmem backed objects */
-	if (ret == -EFAULT || ret == -ENODEV) {
-		intel_runtime_pm_get(to_i915(dev));
-		ret = i915_gem_gtt_pread(dev, obj, args->size,
-					args->offset, args->data_ptr);
-		intel_runtime_pm_put(to_i915(dev));
-	}
+	ret = i915_gem_shmem_pread(obj, args);
+	if (ret == -EFAULT || ret == -ENODEV)
+		ret = i915_gem_gtt_pread(obj, args);
 
+	i915_gem_object_unpin_pages(obj);
+out:
 	i915_gem_object_put(obj);
-	mutex_unlock(&dev->struct_mutex);
-
-	return ret;
-
-err:
-	i915_gem_object_put_unlocked(obj);
 	return ret;
 }
 
@@ -1082,51 +1147,52 @@ err:
  * page faults in the source data
  */
 
-static inline int
-fast_user_write(struct io_mapping *mapping,
-		loff_t page_base, int page_offset,
-		char __user *user_data,
-		int length)
+static inline bool
+ggtt_write(struct io_mapping *mapping,
+	   loff_t base, int offset,
+	   char __user *user_data, int length)
 {
-	void __iomem *vaddr_atomic;
 	void *vaddr;
 	unsigned long unwritten;
 
-	vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
 	/* We can use the cpu mem copy function because this is X86. */
-	vaddr = (void __force*)vaddr_atomic + page_offset;
-	unwritten = __copy_from_user_inatomic_nocache(vaddr,
+	vaddr = (void __force *)io_mapping_map_atomic_wc(mapping, base);
+	unwritten = __copy_from_user_inatomic_nocache(vaddr + offset,
 						      user_data, length);
-	io_mapping_unmap_atomic(vaddr_atomic);
+	io_mapping_unmap_atomic(vaddr);
+	if (unwritten) {
+		vaddr = (void __force *)
+			io_mapping_map_wc(mapping, base, PAGE_SIZE);
+		unwritten = copy_from_user(vaddr + offset, user_data, length);
+		io_mapping_unmap(vaddr);
+	}
+
 	return unwritten;
 }
 
 /**
  * This is the fast pwrite path, where we copy the data directly from the
  * user into the GTT, uncached.
- * @i915: i915 device private data
- * @obj: i915 gem object
+ * @obj: i915 GEM object
  * @args: pwrite arguments structure
- * @file: drm file pointer
  */
 static int
-i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
-			 struct drm_i915_gem_object *obj,
-			 struct drm_i915_gem_pwrite *args,
-			 struct drm_file *file)
+i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
+			 const struct drm_i915_gem_pwrite *args)
 {
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct i915_ggtt *ggtt = &i915->ggtt;
-	struct drm_device *dev = obj->base.dev;
-	struct i915_vma *vma;
 	struct drm_mm_node node;
-	uint64_t remain, offset;
-	char __user *user_data;
+	struct i915_vma *vma;
+	u64 remain, offset;
+	void __user *user_data;
 	int ret;
-	bool hit_slow_path = false;
 
-	if (i915_gem_object_is_tiled(obj))
-		return -EFAULT;
+	ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
+	if (ret)
+		return ret;
 
+	intel_runtime_pm_get(i915);
 	vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
 				       PIN_MAPPABLE | PIN_NONBLOCK);
 	if (!IS_ERR(vma)) {
@@ -1139,25 +1205,19 @@ i915_gem_gtt_pwrite_fast(struct drm_i915
 		}
 	}
 	if (IS_ERR(vma)) {
-		ret = insert_mappable_node(i915, &node, PAGE_SIZE);
+		ret = insert_mappable_node(ggtt, &node, PAGE_SIZE);
 		if (ret)
-			goto out;
-
-		ret = i915_gem_object_get_pages(obj);
-		if (ret) {
-			remove_mappable_node(&node);
-			goto out;
-		}
-
-		i915_gem_object_pin_pages(obj);
+			goto out_unlock;
+		GEM_BUG_ON(!node.allocated);
 	}
 
 	ret = i915_gem_object_set_to_gtt_domain(obj, true);
 	if (ret)
 		goto out_unpin;
 
+	mutex_unlock(&i915->drm.struct_mutex);
+
 	intel_fb_obj_invalidate(obj, ORIGIN_CPU);
-	obj->dirty = true;
 
 	user_data = u64_to_user_ptr(args->data_ptr);
 	offset = args->offset;
@@ -1170,8 +1230,8 @@ i915_gem_gtt_pwrite_fast(struct drm_i915
 		 * page_length = bytes to copy for this page
 		 */
 		u32 page_base = node.start;
-		unsigned page_offset = offset_in_page(offset);
-		unsigned page_length = PAGE_SIZE - page_offset;
+		unsigned int page_offset = offset_in_page(offset);
+		unsigned int page_length = PAGE_SIZE - page_offset;
 		page_length = remain < page_length ? remain : page_length;
 		if (node.allocated) {
 			wmb(); /* flush the write before we modify the GGTT */
@@ -1188,92 +1248,36 @@ i915_gem_gtt_pwrite_fast(struct drm_i915
 		 * If the object is non-shmem backed, we retry again with the
 		 * path that handles page fault.
 		 */
-		if (fast_user_write(&ggtt->mappable, page_base,
-				    page_offset, user_data, page_length)) {
-			hit_slow_path = true;
-			mutex_unlock(&dev->struct_mutex);
-			if (slow_user_access(&ggtt->mappable,
-					     page_base,
-					     page_offset, user_data,
-					     page_length, true)) {
-				ret = -EFAULT;
-				mutex_lock(&dev->struct_mutex);
-				goto out_flush;
-			}
-
-			mutex_lock(&dev->struct_mutex);
+		if (ggtt_write(&ggtt->mappable, page_base, page_offset,
+			       user_data, page_length)) {
+			ret = -EFAULT;
+			break;
 		}
 
 		remain -= page_length;
 		user_data += page_length;
 		offset += page_length;
 	}
-
-out_flush:
-	if (hit_slow_path) {
-		if (ret == 0 &&
-		    (obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0) {
-			/* The user has modified the object whilst we tried
-			 * reading from it, and we now have no idea what domain
-			 * the pages should be in. As we have just been touching
-			 * them directly, flush everything back to the GTT
-			 * domain.
-			 */
-			ret = i915_gem_object_set_to_gtt_domain(obj, false);
-		}
-	}
-
 	intel_fb_obj_flush(obj, false, ORIGIN_CPU);
+
+	mutex_lock(&i915->drm.struct_mutex);
 out_unpin:
 	if (node.allocated) {
 		wmb();
 		ggtt->base.clear_range(&ggtt->base,
-				       node.start, node.size,
-				       true);
-		i915_gem_object_unpin_pages(obj);
+				       node.start, node.size);
 		remove_mappable_node(&node);
 	} else {
 		i915_vma_unpin(vma);
 	}
-out:
+out_unlock:
+	intel_runtime_pm_put(i915);
+	mutex_unlock(&i915->drm.struct_mutex);
 	return ret;
 }
 
-/* Per-page copy function for the shmem pwrite fastpath.
- * Flushes invalid cachelines before writing to the target if
- * needs_clflush_before is set and flushes out any written cachelines after
- * writing if needs_clflush is set. */
 static int
-shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length,
-		  char __user *user_data,
-		  bool page_do_bit17_swizzling,
-		  bool needs_clflush_before,
-		  bool needs_clflush_after)
-{
-	char *vaddr;
-	int ret;
-
-	if (unlikely(page_do_bit17_swizzling))
-		return -EINVAL;
-
-	vaddr = kmap_atomic(page);
-	if (needs_clflush_before)
-		drm_clflush_virt_range(vaddr + shmem_page_offset,
-				       page_length);
-	ret = __copy_from_user_inatomic(vaddr + shmem_page_offset,
-					user_data, page_length);
-	if (needs_clflush_after)
-		drm_clflush_virt_range(vaddr + shmem_page_offset,
-				       page_length);
-	kunmap_atomic(vaddr);
-
-	return ret ? -EFAULT : 0;
-}
-
-/* Only difference to the fast-path function is that this can handle bit17
- * and uses non-atomic copy and kmap functions. */
-static int
-shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length,
+shmem_pwrite_slow(struct page *page, int offset, int length,
 		  char __user *user_data,
 		  bool page_do_bit17_swizzling,
 		  bool needs_clflush_before,
@@ -1284,124 +1288,114 @@ shmem_pwrite_slow(struct page *page, int
 
 	vaddr = kmap(page);
 	if (unlikely(needs_clflush_before || page_do_bit17_swizzling))
-		shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
-					     page_length,
+		shmem_clflush_swizzled_range(vaddr + offset, length,
 					     page_do_bit17_swizzling);
 	if (page_do_bit17_swizzling)
-		ret = __copy_from_user_swizzled(vaddr, shmem_page_offset,
-						user_data,
-						page_length);
+		ret = __copy_from_user_swizzled(vaddr, offset, user_data,
+						length);
 	else
-		ret = __copy_from_user(vaddr + shmem_page_offset,
-				       user_data,
-				       page_length);
+		ret = __copy_from_user(vaddr + offset, user_data, length);
 	if (needs_clflush_after)
-		shmem_clflush_swizzled_range(vaddr + shmem_page_offset,
-					     page_length,
+		shmem_clflush_swizzled_range(vaddr + offset, length,
 					     page_do_bit17_swizzling);
 	kunmap(page);
 
 	return ret ? -EFAULT : 0;
 }
 
+/* Per-page copy function for the shmem pwrite fastpath.
+ * Flushes invalid cachelines before writing to the target if
+ * needs_clflush_before is set and flushes out any written cachelines after
+ * writing if needs_clflush is set.
+ */
 static int
-i915_gem_shmem_pwrite(struct drm_device *dev,
-		      struct drm_i915_gem_object *obj,
-		      struct drm_i915_gem_pwrite *args,
-		      struct drm_file *file)
+shmem_pwrite(struct page *page, int offset, int len, char __user *user_data,
+	     bool page_do_bit17_swizzling,
+	     bool needs_clflush_before,
+	     bool needs_clflush_after)
 {
-	ssize_t remain;
-	loff_t offset;
-	char __user *user_data;
-	int shmem_page_offset, page_length, ret = 0;
-	int obj_do_bit17_swizzling, page_do_bit17_swizzling;
-	int hit_slowpath = 0;
-	unsigned int needs_clflush;
-	struct sg_page_iter sg_iter;
+	int ret;
 
-	ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush);
-	if (ret)
-		return ret;
+	ret = -ENODEV;
+	if (!page_do_bit17_swizzling) {
+		char *vaddr = kmap_atomic(page);
 
-	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
-	user_data = u64_to_user_ptr(args->data_ptr);
-	offset = args->offset;
-	remain = args->size;
+		if (needs_clflush_before)
+			drm_clflush_virt_range(vaddr + offset, len);
+		ret = __copy_from_user_inatomic(vaddr + offset, user_data, len);
+		if (needs_clflush_after)
+			drm_clflush_virt_range(vaddr + offset, len);
 
-	for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents,
-			 offset >> PAGE_SHIFT) {
-		struct page *page = sg_page_iter_page(&sg_iter);
-		int partial_cacheline_write;
+		kunmap_atomic(vaddr);
+	}
+	if (ret == 0)
+		return ret;
 
-		if (remain <= 0)
-			break;
+	return shmem_pwrite_slow(page, offset, len, user_data,
+				 page_do_bit17_swizzling,
+				 needs_clflush_before,
+				 needs_clflush_after);
+}
 
-		/* Operation in this page
-		 *
-		 * shmem_page_offset = offset within page in shmem file
-		 * page_length = bytes to copy for this page
-		 */
-		shmem_page_offset = offset_in_page(offset);
+static int
+i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
+		      const struct drm_i915_gem_pwrite *args)
+{
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	void __user *user_data;
+	u64 remain;
+	unsigned int obj_do_bit17_swizzling;
+	unsigned int partial_cacheline_write;
+	unsigned int needs_clflush;
+	unsigned int offset, idx;
+	int ret;
 
-		page_length = remain;
-		if ((shmem_page_offset + page_length) > PAGE_SIZE)
-			page_length = PAGE_SIZE - shmem_page_offset;
+	ret = mutex_lock_interruptible(&i915->drm.struct_mutex);
+	if (ret)
+		return ret;
 
-		/* If we don't overwrite a cacheline completely we need to be
-		 * careful to have up-to-date data by first clflushing. Don't
-		 * overcomplicate things and flush the entire patch. */
-		partial_cacheline_write = needs_clflush & CLFLUSH_BEFORE &&
-			((shmem_page_offset | page_length)
-				& (boot_cpu_data.x86_clflush_size - 1));
+	ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush);
+	mutex_unlock(&i915->drm.struct_mutex);
+	if (ret)
+		return ret;
 
-		page_do_bit17_swizzling = obj_do_bit17_swizzling &&
-			(page_to_phys(page) & (1 << 17)) != 0;
+	obj_do_bit17_swizzling = 0;
+	if (i915_gem_object_needs_bit17_swizzle(obj))
+		obj_do_bit17_swizzling = BIT(17);
 
-		ret = shmem_pwrite_fast(page, shmem_page_offset, page_length,
-					user_data, page_do_bit17_swizzling,
-					partial_cacheline_write,
-					needs_clflush & CLFLUSH_AFTER);
-		if (ret == 0)
-			goto next_page;
+	/* If we don't overwrite a cacheline completely we need to be
+	 * careful to have up-to-date data by first clflushing. Don't
+	 * overcomplicate things and flush the entire patch.
+	 */
+	partial_cacheline_write = 0;
+	if (needs_clflush & CLFLUSH_BEFORE)
+		partial_cacheline_write = boot_cpu_data.x86_clflush_size - 1;
 
-		hit_slowpath = 1;
-		mutex_unlock(&dev->struct_mutex);
-		ret = shmem_pwrite_slow(page, shmem_page_offset, page_length,
-					user_data, page_do_bit17_swizzling,
-					partial_cacheline_write,
-					needs_clflush & CLFLUSH_AFTER);
+	user_data = u64_to_user_ptr(args->data_ptr);
+	remain = args->size;
+	offset = offset_in_page(args->offset);
+	for (idx = args->offset >> PAGE_SHIFT; remain; idx++) {
+		struct page *page = i915_gem_object_get_page(obj, idx);
+		int length;
 
-		mutex_lock(&dev->struct_mutex);
+		length = remain;
+		if (offset + length > PAGE_SIZE)
+			length = PAGE_SIZE - offset;
 
+		ret = shmem_pwrite(page, offset, length, user_data,
+				   page_to_phys(page) & obj_do_bit17_swizzling,
+				   (offset | length) & partial_cacheline_write,
+				   needs_clflush & CLFLUSH_AFTER);
 		if (ret)
-			goto out;
-
-next_page:
-		remain -= page_length;
-		user_data += page_length;
-		offset += page_length;
-	}
-
-out:
-	i915_gem_obj_finish_shmem_access(obj);
+			break;
 
-	if (hit_slowpath) {
-		/*
-		 * Fixup: Flush cpu caches in case we didn't flush the dirty
-		 * cachelines in-line while writing and the object moved
-		 * out of the cpu write domain while we've dropped the lock.
-		 */
-		if (!(needs_clflush & CLFLUSH_AFTER) &&
-		    obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
-			if (i915_gem_clflush_object(obj, obj->pin_display))
-				needs_clflush |= CLFLUSH_AFTER;
-		}
+		remain -= length;
+		user_data += length;
+		offset = 0;
 	}
 
-	if (needs_clflush & CLFLUSH_AFTER)
-		i915_gem_chipset_flush(to_i915(dev));
-
 	intel_fb_obj_flush(obj, false, ORIGIN_CPU);
+	i915_gem_obj_finish_shmem_access(obj);
 	return ret;
 }
 
@@ -1417,7 +1411,6 @@ int
 i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		      struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_pwrite *args = data;
 	struct drm_i915_gem_object *obj;
 	int ret;
@@ -1430,13 +1423,6 @@ i915_gem_pwrite_ioctl(struct drm_device
 		       args->size))
 		return -EFAULT;
 
-	if (likely(!i915.prefault_disable)) {
-		ret = fault_in_pages_readable(u64_to_user_ptr(args->data_ptr),
-						   args->size);
-		if (ret)
-			return -EFAULT;
-	}
-
 	obj = i915_gem_object_lookup(file, args->handle);
 	if (!obj)
 		return -ENOENT;
@@ -1450,15 +1436,17 @@ i915_gem_pwrite_ioctl(struct drm_device
 
 	trace_i915_gem_object_pwrite(obj, args->offset, args->size);
 
-	ret = __unsafe_wait_rendering(obj, to_rps_client(file), false);
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_ALL,
+				   MAX_SCHEDULE_TIMEOUT,
+				   to_rps_client(file));
 	if (ret)
 		goto err;
 
-	intel_runtime_pm_get(dev_priv);
-
-	ret = i915_mutex_lock_interruptible(dev);
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
-		goto err_rpm;
+		goto err;
 
 	ret = -EFAULT;
 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
@@ -1468,30 +1456,23 @@ i915_gem_pwrite_ioctl(struct drm_device
 	 * perspective, requiring manual detiling by the client.
 	 */
 	if (!i915_gem_object_has_struct_page(obj) ||
-	    cpu_write_needs_clflush(obj)) {
-		ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file);
+	    cpu_write_needs_clflush(obj))
 		/* Note that the gtt paths might fail with non-page-backed user
 		 * pointers (e.g. gtt mappings when moving data between
-		 * textures). Fallback to the shmem path in that case. */
-	}
+		 * textures). Fallback to the shmem path in that case.
+		 */
+		ret = i915_gem_gtt_pwrite_fast(obj, args);
 
 	if (ret == -EFAULT || ret == -ENOSPC) {
 		if (obj->phys_handle)
 			ret = i915_gem_phys_pwrite(obj, args, file);
 		else
-			ret = i915_gem_shmem_pwrite(dev, obj, args, file);
+			ret = i915_gem_shmem_pwrite(obj, args);
 	}
 
-	i915_gem_object_put(obj);
-	mutex_unlock(&dev->struct_mutex);
-	intel_runtime_pm_put(dev_priv);
-
-	return ret;
-
-err_rpm:
-	intel_runtime_pm_put(dev_priv);
+	i915_gem_object_unpin_pages(obj);
 err:
-	i915_gem_object_put_unlocked(obj);
+	i915_gem_object_put(obj);
 	return ret;
 }
 
@@ -1502,6 +1483,30 @@ write_origin(struct drm_i915_gem_object
 		obj->frontbuffer_ggtt_origin : ORIGIN_CPU);
 }
 
+static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *i915;
+	struct list_head *list;
+	struct i915_vma *vma;
+
+	list_for_each_entry(vma, &obj->vma_list, obj_link) {
+		if (!i915_vma_is_ggtt(vma))
+			continue;
+
+		if (i915_vma_is_active(vma))
+			continue;
+
+		if (!drm_mm_node_allocated(&vma->node))
+			continue;
+
+		list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
+	}
+
+	i915 = to_i915(obj->base.dev);
+	list = obj->bind_count ? &i915->mm.bound_list : &i915->mm.unbound_list;
+	list_move_tail(&obj->global_link, list);
+}
+
 /**
  * Called when user space prepares to use an object with the CPU, either
  * through the mmap ioctl's mapping or a GTT mapping.
@@ -1517,7 +1522,7 @@ i915_gem_set_domain_ioctl(struct drm_dev
 	struct drm_i915_gem_object *obj;
 	uint32_t read_domains = args->read_domains;
 	uint32_t write_domain = args->write_domain;
-	int ret;
+	int err;
 
 	/* Only handle setting domains to types used by the CPU. */
 	if ((write_domain | read_domains) & I915_GEM_GPU_DOMAINS)
@@ -1537,29 +1542,48 @@ i915_gem_set_domain_ioctl(struct drm_dev
 	 * We will repeat the flush holding the lock in the normal manner
 	 * to catch cases where we are gazumped.
 	 */
-	ret = __unsafe_wait_rendering(obj, to_rps_client(file), !write_domain);
-	if (ret)
-		goto err;
+	err = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   (write_domain ? I915_WAIT_ALL : 0),
+				   MAX_SCHEDULE_TIMEOUT,
+				   to_rps_client(file));
+	if (err)
+		goto out;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		goto err;
+	/* Flush and acquire obj->pages so that we are coherent through
+	 * direct access in memory with previous cached writes through
+	 * shmemfs and that our cache domain tracking remains valid.
+	 * For example, if the obj->filp was moved to swap without us
+	 * being notified and releasing the pages, we would mistakenly
+	 * continue to assume that the obj remained out of the CPU cached
+	 * domain.
+	 */
+	err = i915_gem_object_pin_pages(obj);
+	if (err)
+		goto out;
+
+	err = i915_mutex_lock_interruptible(dev);
+	if (err)
+		goto out_unpin;
 
 	if (read_domains & I915_GEM_DOMAIN_GTT)
-		ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
+		err = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
 	else
-		ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
+		err = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
+
+	/* And bump the LRU for this access */
+	i915_gem_object_bump_inactive_ggtt(obj);
+
+	mutex_unlock(&dev->struct_mutex);
 
 	if (write_domain != 0)
 		intel_fb_obj_invalidate(obj, write_origin(obj, write_domain));
 
+out_unpin:
+	i915_gem_object_unpin_pages(obj);
+out:
 	i915_gem_object_put(obj);
-	mutex_unlock(&dev->struct_mutex);
-	return ret;
-
-err:
-	i915_gem_object_put_unlocked(obj);
-	return ret;
+	return err;
 }
 
 /**
@@ -1589,7 +1613,7 @@ i915_gem_sw_finish_ioctl(struct drm_devi
 		}
 	}
 
-	i915_gem_object_put_unlocked(obj);
+	i915_gem_object_put(obj);
 	return err;
 }
 
@@ -1635,7 +1659,7 @@ i915_gem_mmap_ioctl(struct drm_device *d
 	 * pages from.
 	 */
 	if (!obj->base.filp) {
-		i915_gem_object_put_unlocked(obj);
+		i915_gem_object_put(obj);
 		return -EINVAL;
 	}
 
@@ -1647,7 +1671,7 @@ i915_gem_mmap_ioctl(struct drm_device *d
 		struct vm_area_struct *vma;
 
 		if (down_write_killable(&mm->mmap_sem)) {
-			i915_gem_object_put_unlocked(obj);
+			i915_gem_object_put(obj);
 			return -EINTR;
 		}
 		vma = find_vma(mm, addr);
@@ -1661,7 +1685,7 @@ i915_gem_mmap_ioctl(struct drm_device *d
 		/* This may race, but that's ok, it only gets set */
 		WRITE_ONCE(obj->frontbuffer_ggtt_origin, ORIGIN_CPU);
 	}
-	i915_gem_object_put_unlocked(obj);
+	i915_gem_object_put(obj);
 	if (IS_ERR((void *)addr))
 		return addr;
 
@@ -1763,8 +1787,7 @@ int i915_gem_fault(struct vm_area_struct
 	int ret;
 
 	/* We don't use vmf->pgoff since that has the fake offset */
-	page_offset = ((unsigned long)vmf->virtual_address - area->vm_start) >>
-		PAGE_SHIFT;
+	page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT;
 
 	trace_i915_gem_object_fault(obj, page_offset, true, write);
 
@@ -1773,7 +1796,14 @@ int i915_gem_fault(struct vm_area_struct
 	 * repeat the flush holding the lock in the normal manner to catch cases
 	 * where we are gazumped.
 	 */
-	ret = __unsafe_wait_rendering(obj, NULL, !write);
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE,
+				   MAX_SCHEDULE_TIMEOUT,
+				   NULL);
+	if (ret)
+		goto err;
+
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		goto err;
 
@@ -1784,7 +1814,7 @@ int i915_gem_fault(struct vm_area_struct
 		goto err_rpm;
 
 	/* Access to snoopable pages through the GTT is incoherent. */
-	if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) {
+	if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev_priv)) {
 		ret = -EFAULT;
 		goto err_unlock;
 	}
@@ -1813,8 +1843,7 @@ int i915_gem_fault(struct vm_area_struct
 		view.params.partial.offset = rounddown(page_offset, chunk_size);
 		view.params.partial.size =
 			min_t(unsigned int, chunk_size,
-			      (area->vm_end - area->vm_start) / PAGE_SIZE -
-			      view.params.partial.offset);
+			      vma_pages(area) - view.params.partial.offset);
 
 		/* If the partial covers the entire object, just create a
 		 * normal VMA.
@@ -1842,22 +1871,25 @@ int i915_gem_fault(struct vm_area_struct
 	if (ret)
 		goto err_unpin;
 
+	/* Mark as being mmapped into userspace for later revocation */
+	assert_rpm_wakelock_held(dev_priv);
+	if (list_empty(&obj->userfault_link))
+		list_add(&obj->userfault_link, &dev_priv->mm.userfault_list);
+
 	/* Finally, remap it using the new GTT offset */
 	ret = remap_io_mapping(area,
 			       area->vm_start + (vma->ggtt_view.params.partial.offset << PAGE_SHIFT),
 			       (ggtt->mappable_base + vma->node.start) >> PAGE_SHIFT,
 			       min_t(u64, vma->size, area->vm_end - area->vm_start),
 			       &ggtt->mappable);
-	if (ret)
-		goto err_unpin;
 
-	obj->fault_mappable = true;
 err_unpin:
 	__i915_vma_unpin(vma);
 err_unlock:
 	mutex_unlock(&dev->struct_mutex);
 err_rpm:
 	intel_runtime_pm_put(dev_priv);
+	i915_gem_object_unpin_pages(obj);
 err:
 	switch (ret) {
 	case -EIO:
@@ -1919,15 +1951,23 @@ err:
 void
 i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 {
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+
 	/* Serialisation between user GTT access and our code depends upon
 	 * revoking the CPU's PTE whilst the mutex is held. The next user
 	 * pagefault then has to wait until we release the mutex.
+	 *
+	 * Note that RPM complicates somewhat by adding an additional
+	 * requirement that operations to the GGTT be made holding the RPM
+	 * wakeref.
 	 */
-	lockdep_assert_held(&obj->base.dev->struct_mutex);
+	lockdep_assert_held(&i915->drm.struct_mutex);
+	intel_runtime_pm_get(i915);
 
-	if (!obj->fault_mappable)
-		return;
+	if (list_empty(&obj->userfault_link))
+		goto out;
 
+	list_del_init(&obj->userfault_link);
 	drm_vma_node_unmap(&obj->base.vma_node,
 			   obj->base.dev->anon_inode->i_mapping);
 
@@ -1940,16 +1980,53 @@ i915_gem_release_mmap(struct drm_i915_ge
 	 */
 	wmb();
 
-	obj->fault_mappable = false;
+out:
+	intel_runtime_pm_put(i915);
 }
 
-void
-i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
+void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_object *obj, *on;
+	int i;
 
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
-		i915_gem_release_mmap(obj);
+	/*
+	 * Only called during RPM suspend. All users of the userfault_list
+	 * must be holding an RPM wakeref to ensure that this can not
+	 * run concurrently with themselves (and use the struct_mutex for
+	 * protection between themselves).
+	 */
+
+	list_for_each_entry_safe(obj, on,
+				 &dev_priv->mm.userfault_list, userfault_link) {
+		list_del_init(&obj->userfault_link);
+		drm_vma_node_unmap(&obj->base.vma_node,
+				   obj->base.dev->anon_inode->i_mapping);
+	}
+
+	/* The fence will be lost when the device powers down. If any were
+	 * in use by hardware (i.e. they are pinned), we should not be powering
+	 * down! All other fences will be reacquired by the user upon waking.
+	 */
+	for (i = 0; i < dev_priv->num_fence_regs; i++) {
+		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
+
+		/* Ideally we want to assert that the fence register is not
+		 * live at this point (i.e. that no piece of code will be
+		 * trying to write through fence + GTT, as that both violates
+		 * our tracking of activity and associated locking/barriers,
+		 * but also is illegal given that the hw is powered down).
+		 *
+		 * Previously we used reg->pin_count as a "liveness" indicator.
+		 * That is not sufficient, and we need a more fine-grained
+		 * tool if we want to have a sanity check here.
+		 */
+
+		if (!reg->vma)
+			continue;
+
+		GEM_BUG_ON(!list_empty(&reg->vma->obj->userfault_link));
+		reg->dirty = true;
+	}
 }
 
 /**
@@ -2063,7 +2140,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
 	if (ret == 0)
 		*offset = drm_vma_node_offset_addr(&obj->base.vma_node);
 
-	i915_gem_object_put_unlocked(obj);
+	i915_gem_object_put(obj);
 	return ret;
 }
 
@@ -2106,16 +2183,18 @@ i915_gem_object_truncate(struct drm_i915
 	 * backing pages, *now*.
 	 */
 	shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);
-	obj->madv = __I915_MADV_PURGED;
+	obj->mm.madv = __I915_MADV_PURGED;
 }
 
 /* Try to discard unwanted pages */
-static void
-i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
+void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj)
 {
 	struct address_space *mapping;
 
-	switch (obj->madv) {
+	lockdep_assert_held(&obj->mm.lock);
+	GEM_BUG_ON(obj->mm.pages);
+
+	switch (obj->mm.madv) {
 	case I915_MADV_DONTNEED:
 		i915_gem_object_truncate(obj);
 	case __I915_MADV_PURGED:
@@ -2130,95 +2209,122 @@ i915_gem_object_invalidate(struct drm_i9
 }
 
 static void
-i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
+i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj,
+			      struct sg_table *pages)
 {
 	struct sgt_iter sgt_iter;
 	struct page *page;
-	int ret;
-
-	BUG_ON(obj->madv == __I915_MADV_PURGED);
 
-	ret = i915_gem_object_set_to_cpu_domain(obj, true);
-	if (WARN_ON(ret)) {
-		/* In the event of a disaster, abandon all caches and
-		 * hope for the best.
-		 */
-		i915_gem_clflush_object(obj, true);
-		obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU;
-	}
+	__i915_gem_object_release_shmem(obj, pages, true);
 
-	i915_gem_gtt_finish_object(obj);
+	i915_gem_gtt_finish_pages(obj, pages);
 
 	if (i915_gem_object_needs_bit17_swizzle(obj))
-		i915_gem_object_save_bit_17_swizzle(obj);
-
-	if (obj->madv == I915_MADV_DONTNEED)
-		obj->dirty = 0;
+		i915_gem_object_save_bit_17_swizzle(obj, pages);
 
-	for_each_sgt_page(page, sgt_iter, obj->pages) {
-		if (obj->dirty)
+	for_each_sgt_page(page, sgt_iter, pages) {
+		if (obj->mm.dirty)
 			set_page_dirty(page);
 
-		if (obj->madv == I915_MADV_WILLNEED)
+		if (obj->mm.madv == I915_MADV_WILLNEED)
 			mark_page_accessed(page);
 
 		put_page(page);
 	}
-	obj->dirty = 0;
+	obj->mm.dirty = false;
 
-	sg_free_table(obj->pages);
-	kfree(obj->pages);
+	sg_free_table(pages);
+	kfree(pages);
 }
 
-int
-i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
+static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj)
 {
-	const struct drm_i915_gem_object_ops *ops = obj->ops;
+	struct radix_tree_iter iter;
+	void **slot;
 
-	if (obj->pages == NULL)
-		return 0;
+	radix_tree_for_each_slot(slot, &obj->mm.get_page.radix, &iter, 0)
+		radix_tree_delete(&obj->mm.get_page.radix, iter.index);
+}
 
-	if (obj->pages_pin_count)
-		return -EBUSY;
+void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj,
+				 enum i915_mm_subclass subclass)
+{
+	struct sg_table *pages;
+
+	if (i915_gem_object_has_pinned_pages(obj))
+		return;
 
 	GEM_BUG_ON(obj->bind_count);
+	if (!READ_ONCE(obj->mm.pages))
+		return;
+
+	/* May be called by shrinker from within get_pages() (on another bo) */
+	mutex_lock_nested(&obj->mm.lock, subclass);
+	if (unlikely(atomic_read(&obj->mm.pages_pin_count)))
+		goto unlock;
 
 	/* ->put_pages might need to allocate memory for the bit17 swizzle
 	 * array, hence protect them from being reaped by removing them from gtt
 	 * lists early. */
-	list_del(&obj->global_list);
+	pages = fetch_and_zero(&obj->mm.pages);
+	GEM_BUG_ON(!pages);
 
-	if (obj->mapping) {
+	if (obj->mm.mapping) {
 		void *ptr;
 
-		ptr = ptr_mask_bits(obj->mapping);
+		ptr = ptr_mask_bits(obj->mm.mapping);
 		if (is_vmalloc_addr(ptr))
 			vunmap(ptr);
 		else
 			kunmap(kmap_to_page(ptr));
 
-		obj->mapping = NULL;
+		obj->mm.mapping = NULL;
 	}
 
-	ops->put_pages(obj);
-	obj->pages = NULL;
+	__i915_gem_object_reset_page_iter(obj);
 
-	i915_gem_object_invalidate(obj);
+	obj->ops->put_pages(obj, pages);
+unlock:
+	mutex_unlock(&obj->mm.lock);
+}
 
-	return 0;
+static void i915_sg_trim(struct sg_table *orig_st)
+{
+	struct sg_table new_st;
+	struct scatterlist *sg, *new_sg;
+	unsigned int i;
+
+	if (orig_st->nents == orig_st->orig_nents)
+		return;
+
+	if (sg_alloc_table(&new_st, orig_st->nents, GFP_KERNEL | __GFP_NOWARN))
+		return;
+
+	new_sg = new_st.sgl;
+	for_each_sg(orig_st->sgl, sg, orig_st->nents, i) {
+		sg_set_page(new_sg, sg_page(sg), sg->length, 0);
+		/* called before being DMA mapped, no need to copy sg->dma_* */
+		new_sg = sg_next(new_sg);
+	}
+
+	sg_free_table(orig_st);
+
+	*orig_st = new_st;
 }
 
-static int
+static struct sg_table *
 i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
-	int page_count, i;
+	const unsigned long page_count = obj->base.size / PAGE_SIZE;
+	unsigned long i;
 	struct address_space *mapping;
 	struct sg_table *st;
 	struct scatterlist *sg;
 	struct sgt_iter sgt_iter;
 	struct page *page;
 	unsigned long last_pfn = 0;	/* suppress gcc warning */
+	unsigned int max_segment;
 	int ret;
 	gfp_t gfp;
 
@@ -2226,17 +2332,21 @@ i915_gem_object_get_pages_gtt(struct drm
 	 * wasn't in the GTT, there shouldn't be any way it could have been in
 	 * a GPU cache
 	 */
-	BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
-	BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
+	GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS);
+	GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS);
+
+	max_segment = swiotlb_max_segment();
+	if (!max_segment)
+		max_segment = rounddown(UINT_MAX, PAGE_SIZE);
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (st == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	page_count = obj->base.size / PAGE_SIZE;
+rebuild_st:
 	if (sg_alloc_table(st, page_count, GFP_KERNEL)) {
 		kfree(st);
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	/* Get the list of pages out of our struct file.  They'll be pinned
@@ -2264,22 +2374,15 @@ i915_gem_object_get_pages_gtt(struct drm
 			 * our own buffer, now let the real VM do its job and
 			 * go down in flames if truly OOM.
 			 */
-			i915_gem_shrink_all(dev_priv);
 			page = shmem_read_mapping_page(mapping, i);
 			if (IS_ERR(page)) {
 				ret = PTR_ERR(page);
 				goto err_sg;
 			}
 		}
-#ifdef CONFIG_SWIOTLB
-		if (swiotlb_nr_tbl()) {
-			st->nents++;
-			sg_set_page(sg, page, PAGE_SIZE, 0);
-			sg = sg_next(sg);
-			continue;
-		}
-#endif
-		if (!i || page_to_pfn(page) != last_pfn + 1) {
+		if (!i ||
+		    sg->length >= max_segment ||
+		    page_to_pfn(page) != last_pfn + 1) {
 			if (i)
 				sg = sg_next(sg);
 			st->nents++;
@@ -2292,24 +2395,37 @@ i915_gem_object_get_pages_gtt(struct drm
 		/* Check that the i965g/gm workaround works. */
 		WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL));
 	}
-#ifdef CONFIG_SWIOTLB
-	if (!swiotlb_nr_tbl())
-#endif
+	if (sg) /* loop terminated early; short sg table */
 		sg_mark_end(sg);
-	obj->pages = st;
 
-	ret = i915_gem_gtt_prepare_object(obj);
-	if (ret)
-		goto err_pages;
+	/* Trim unused sg entries to avoid wasting memory. */
+	i915_sg_trim(st);
 
-	if (i915_gem_object_needs_bit17_swizzle(obj))
-		i915_gem_object_do_bit_17_swizzle(obj);
+	ret = i915_gem_gtt_prepare_pages(obj, st);
+	if (ret) {
+		/* DMA remapping failed? One possible cause is that
+		 * it could not reserve enough large entries, asking
+		 * for PAGE_SIZE chunks instead may be helpful.
+		 */
+		if (max_segment > PAGE_SIZE) {
+			for_each_sgt_page(page, sgt_iter, st)
+				put_page(page);
+			sg_free_table(st);
 
-	if (i915_gem_object_is_tiled(obj) &&
-	    dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
-		i915_gem_object_pin_pages(obj);
+			max_segment = PAGE_SIZE;
+			goto rebuild_st;
+		} else {
+			dev_warn(&dev_priv->drm.pdev->dev,
+				 "Failed to DMA remap %lu pages\n",
+				 page_count);
+			goto err_pages;
+		}
+	}
 
-	return 0;
+	if (i915_gem_object_needs_bit17_swizzle(obj))
+		i915_gem_object_do_bit_17_swizzle(obj, st);
+
+	return st;
 
 err_sg:
 	sg_mark_end(sg);
@@ -2330,43 +2446,73 @@ err_pages:
 	if (ret == -ENOSPC)
 		ret = -ENOMEM;
 
-	return ret;
+	return ERR_PTR(ret);
 }
 
-/* Ensure that the associated pages are gathered from the backing storage
- * and pinned into our object. i915_gem_object_get_pages() may be called
- * multiple times before they are released by a single call to
- * i915_gem_object_put_pages() - once the pages are no longer referenced
- * either as a result of memory pressure (reaping pages under the shrinker)
- * or as the object is itself released.
- */
-int
-i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
+				 struct sg_table *pages)
 {
-	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
-	const struct drm_i915_gem_object_ops *ops = obj->ops;
-	int ret;
+	lockdep_assert_held(&obj->mm.lock);
 
-	if (obj->pages)
-		return 0;
+	obj->mm.get_page.sg_pos = pages->sgl;
+	obj->mm.get_page.sg_idx = 0;
 
-	if (obj->madv != I915_MADV_WILLNEED) {
+	obj->mm.pages = pages;
+
+	if (i915_gem_object_is_tiled(obj) &&
+	    to_i915(obj->base.dev)->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
+		GEM_BUG_ON(obj->mm.quirked);
+		__i915_gem_object_pin_pages(obj);
+		obj->mm.quirked = true;
+	}
+}
+
+static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+{
+	struct sg_table *pages;
+
+	GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj));
+
+	if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) {
 		DRM_DEBUG("Attempting to obtain a purgeable object\n");
 		return -EFAULT;
 	}
 
-	BUG_ON(obj->pages_pin_count);
+	pages = obj->ops->get_pages(obj);
+	if (unlikely(IS_ERR(pages)))
+		return PTR_ERR(pages);
 
-	ret = ops->get_pages(obj);
-	if (ret)
-		return ret;
+	__i915_gem_object_set_pages(obj, pages);
+	return 0;
+}
 
-	list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list);
+/* Ensure that the associated pages are gathered from the backing storage
+ * and pinned into our object. i915_gem_object_pin_pages() may be called
+ * multiple times before they are released by a single call to
+ * i915_gem_object_unpin_pages() - once the pages are no longer referenced
+ * either as a result of memory pressure (reaping pages under the shrinker)
+ * or as the object is itself released.
+ */
+int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
+{
+	int err;
 
-	obj->get_page.sg = obj->pages->sgl;
-	obj->get_page.last = 0;
+	err = mutex_lock_interruptible(&obj->mm.lock);
+	if (err)
+		return err;
 
-	return 0;
+	if (unlikely(!obj->mm.pages)) {
+		err = ____i915_gem_object_get_pages(obj);
+		if (err)
+			goto unlock;
+
+		smp_mb__before_atomic();
+	}
+	atomic_inc(&obj->mm.pages_pin_count);
+
+unlock:
+	mutex_unlock(&obj->mm.lock);
+	return err;
 }
 
 /* The 'mapping' part of i915_gem_object_pin_map() below */
@@ -2374,7 +2520,7 @@ static void *i915_gem_object_map(const s
 				 enum i915_map_type type)
 {
 	unsigned long n_pages = obj->base.size >> PAGE_SHIFT;
-	struct sg_table *sgt = obj->pages;
+	struct sg_table *sgt = obj->mm.pages;
 	struct sgt_iter sgt_iter;
 	struct page *page;
 	struct page *stack_pages[32];
@@ -2425,21 +2571,31 @@ void *i915_gem_object_pin_map(struct drm
 	void *ptr;
 	int ret;
 
-	lockdep_assert_held(&obj->base.dev->struct_mutex);
 	GEM_BUG_ON(!i915_gem_object_has_struct_page(obj));
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = mutex_lock_interruptible(&obj->mm.lock);
 	if (ret)
 		return ERR_PTR(ret);
 
-	i915_gem_object_pin_pages(obj);
-	pinned = obj->pages_pin_count > 1;
+	pinned = true;
+	if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) {
+		if (unlikely(!obj->mm.pages)) {
+			ret = ____i915_gem_object_get_pages(obj);
+			if (ret)
+				goto err_unlock;
 
-	ptr = ptr_unpack_bits(obj->mapping, has_type);
+			smp_mb__before_atomic();
+		}
+		atomic_inc(&obj->mm.pages_pin_count);
+		pinned = false;
+	}
+	GEM_BUG_ON(!obj->mm.pages);
+
+	ptr = ptr_unpack_bits(obj->mm.mapping, has_type);
 	if (ptr && has_type != type) {
 		if (pinned) {
 			ret = -EBUSY;
-			goto err;
+			goto err_unpin;
 		}
 
 		if (is_vmalloc_addr(ptr))
@@ -2447,59 +2603,28 @@ void *i915_gem_object_pin_map(struct drm
 		else
 			kunmap(kmap_to_page(ptr));
 
-		ptr = obj->mapping = NULL;
+		ptr = obj->mm.mapping = NULL;
 	}
 
 	if (!ptr) {
 		ptr = i915_gem_object_map(obj, type);
 		if (!ptr) {
 			ret = -ENOMEM;
-			goto err;
+			goto err_unpin;
 		}
 
-		obj->mapping = ptr_pack_bits(ptr, type);
+		obj->mm.mapping = ptr_pack_bits(ptr, type);
 	}
 
+out_unlock:
+	mutex_unlock(&obj->mm.lock);
 	return ptr;
 
-err:
-	i915_gem_object_unpin_pages(obj);
-	return ERR_PTR(ret);
-}
-
-static void
-i915_gem_object_retire__write(struct i915_gem_active *active,
-			      struct drm_i915_gem_request *request)
-{
-	struct drm_i915_gem_object *obj =
-		container_of(active, struct drm_i915_gem_object, last_write);
-
-	intel_fb_obj_flush(obj, true, ORIGIN_CS);
-}
-
-static void
-i915_gem_object_retire__read(struct i915_gem_active *active,
-			     struct drm_i915_gem_request *request)
-{
-	int idx = request->engine->id;
-	struct drm_i915_gem_object *obj =
-		container_of(active, struct drm_i915_gem_object, last_read[idx]);
-
-	GEM_BUG_ON(!i915_gem_object_has_active_engine(obj, idx));
-
-	i915_gem_object_clear_active(obj, idx);
-	if (i915_gem_object_is_active(obj))
-		return;
-
-	/* Bump our place on the bound list to keep it roughly in LRU order
-	 * so that we don't steal from recently used but inactive objects
-	 * (unless we are forced to ofc!)
-	 */
-	if (obj->bind_count)
-		list_move_tail(&obj->global_list,
-			       &request->i915->mm.bound_list);
-
-	i915_gem_object_put(obj);
+err_unpin:
+	atomic_dec(&obj->mm.pages_pin_count);
+err_unlock:
+	ptr = ERR_PTR(ret);
+	goto out_unlock;
 }
 
 static bool i915_context_is_banned(const struct i915_gem_context *ctx)
@@ -2546,13 +2671,10 @@ i915_gem_find_active_request(struct inte
 	 * extra delay for a recent interrupt is pointless. Hence, we do
 	 * not need an engine->irq_seqno_barrier() before the seqno reads.
 	 */
-	list_for_each_entry(request, &engine->request_list, link) {
-		if (i915_gem_request_completed(request))
+	list_for_each_entry(request, &engine->timeline->requests, link) {
+		if (__i915_gem_request_completed(request))
 			continue;
 
-		if (!i915_sw_fence_done(&request->submit))
-			break;
-
 		return request;
 	}
 
@@ -2580,10 +2702,10 @@ static void i915_gem_reset_engine(struct
 {
 	struct drm_i915_gem_request *request;
 	struct i915_gem_context *incomplete_ctx;
+	struct intel_timeline *timeline;
+	unsigned long flags;
 	bool ring_hung;
 
-	/* Ensure irq handler finishes, and not run again. */
-	tasklet_kill(&engine->irq_tasklet);
 	if (engine->irq_seqno_barrier)
 		engine->irq_seqno_barrier(engine);
 
@@ -2592,12 +2714,15 @@ static void i915_gem_reset_engine(struct
 		return;
 
 	ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG;
+	if (engine->hangcheck.seqno != intel_engine_get_seqno(engine))
+		ring_hung = false;
+
 	i915_set_reset_status(request->ctx, ring_hung);
 	if (!ring_hung)
 		return;
 
 	DRM_DEBUG_DRIVER("resetting %s to restart from tail of request 0x%x\n",
-			 engine->name, request->fence.seqno);
+			 engine->name, request->global_seqno);
 
 	/* Setup the CS to resume from the breadcrumb of the hung request */
 	engine->reset_hw(engine, request);
@@ -2614,21 +2739,35 @@ static void i915_gem_reset_engine(struct
 	if (i915_gem_context_is_default(incomplete_ctx))
 		return;
 
-	list_for_each_entry_continue(request, &engine->request_list, link)
+	timeline = i915_gem_context_lookup_timeline(incomplete_ctx, engine);
+
+	spin_lock_irqsave(&engine->timeline->lock, flags);
+	spin_lock(&timeline->lock);
+
+	list_for_each_entry_continue(request, &engine->timeline->requests, link)
 		if (request->ctx == incomplete_ctx)
 			reset_request(request);
+
+	list_for_each_entry(request, &timeline->requests, link)
+		reset_request(request);
+
+	spin_unlock(&timeline->lock);
+	spin_unlock_irqrestore(&engine->timeline->lock, flags);
 }
 
 void i915_gem_reset(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
 	i915_gem_retire_requests(dev_priv);
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		i915_gem_reset_engine(engine);
 
-	i915_gem_restore_fences(&dev_priv->drm);
+	i915_gem_restore_fences(dev_priv);
 
 	if (dev_priv->gt.awake) {
 		intel_sanitize_gt_powersave(dev_priv);
@@ -2640,6 +2779,8 @@ void i915_gem_reset(struct drm_i915_priv
 
 static void nop_submit_request(struct drm_i915_gem_request *request)
 {
+	i915_gem_request_submit(request);
+	intel_engine_init_global_seqno(request->engine, request->global_seqno);
 }
 
 static void i915_gem_cleanup_engine(struct intel_engine_cs *engine)
@@ -2650,7 +2791,8 @@ static void i915_gem_cleanup_engine(stru
 	 * (lockless) lookup doesn't try and wait upon the request as we
 	 * reset it.
 	 */
-	intel_engine_init_seqno(engine, engine->last_submitted_seqno);
+	intel_engine_init_global_seqno(engine,
+				       intel_engine_last_submit(engine));
 
 	/*
 	 * Clear the execlists queue up before freeing the requests, as those
@@ -2659,26 +2801,30 @@ static void i915_gem_cleanup_engine(stru
 	 */
 
 	if (i915.enable_execlists) {
-		spin_lock(&engine->execlist_lock);
-		INIT_LIST_HEAD(&engine->execlist_queue);
+		unsigned long flags;
+
+		spin_lock_irqsave(&engine->timeline->lock, flags);
+
 		i915_gem_request_put(engine->execlist_port[0].request);
 		i915_gem_request_put(engine->execlist_port[1].request);
 		memset(engine->execlist_port, 0, sizeof(engine->execlist_port));
-		spin_unlock(&engine->execlist_lock);
-	}
+		engine->execlist_queue = RB_ROOT;
+		engine->execlist_first = NULL;
 
-	engine->i915->gt.active_engines &= ~intel_engine_flag(engine);
+		spin_unlock_irqrestore(&engine->timeline->lock, flags);
+	}
 }
 
 void i915_gem_set_wedged(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
 	lockdep_assert_held(&dev_priv->drm.struct_mutex);
 	set_bit(I915_WEDGED, &dev_priv->gpu_error.flags);
 
 	i915_gem_context_lost(dev_priv);
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		i915_gem_cleanup_engine(engine);
 	mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0);
 
@@ -2717,12 +2863,20 @@ i915_gem_idle_work_handler(struct work_s
 		container_of(work, typeof(*dev_priv), gt.idle_work.work);
 	struct drm_device *dev = &dev_priv->drm;
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	bool rearm_hangcheck;
 
 	if (!READ_ONCE(dev_priv->gt.awake))
 		return;
 
-	if (READ_ONCE(dev_priv->gt.active_engines))
+	/*
+	 * Wait for last execlists context complete, but bail out in case a
+	 * new request is submitted.
+	 */
+	wait_for(READ_ONCE(dev_priv->gt.active_requests) ||
+		 intel_execlists_idle(dev_priv), 10);
+
+	if (READ_ONCE(dev_priv->gt.active_requests))
 		return;
 
 	rearm_hangcheck =
@@ -2736,10 +2890,20 @@ i915_gem_idle_work_handler(struct work_s
 		goto out_rearm;
 	}
 
-	if (dev_priv->gt.active_engines)
+	/*
+	 * New request retired after this work handler started, extend active
+	 * period until next instance of the work.
+	 */
+	if (work_pending(work))
 		goto out_unlock;
 
-	for_each_engine(engine, dev_priv)
+	if (dev_priv->gt.active_requests)
+		goto out_unlock;
+
+	if (wait_for(intel_execlists_idle(dev_priv), 10))
+		DRM_ERROR("Timeout waiting for engines to idle\n");
+
+	for_each_engine(engine, dev_priv, id)
 		i915_gem_batch_pool_fini(&engine->batch_pool);
 
 	GEM_BUG_ON(!dev_priv->gt.awake);
@@ -2769,9 +2933,26 @@ void i915_gem_close_object(struct drm_ge
 	list_for_each_entry_safe(vma, vn, &obj->vma_list, obj_link)
 		if (vma->vm->file == fpriv)
 			i915_vma_close(vma);
+
+	if (i915_gem_object_is_active(obj) &&
+	    !i915_gem_object_has_active_reference(obj)) {
+		i915_gem_object_set_active_reference(obj);
+		i915_gem_object_get(obj);
+	}
 	mutex_unlock(&obj->base.dev->struct_mutex);
 }
 
+static unsigned long to_wait_timeout(s64 timeout_ns)
+{
+	if (timeout_ns < 0)
+		return MAX_SCHEDULE_TIMEOUT;
+
+	if (timeout_ns == 0)
+		return 0;
+
+	return nsecs_to_jiffies_timeout(timeout_ns);
+}
+
 /**
  * i915_gem_wait_ioctl - implements DRM_IOCTL_I915_GEM_WAIT
  * @dev: drm device pointer
@@ -2800,10 +2981,9 @@ int
 i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 {
 	struct drm_i915_gem_wait *args = data;
-	struct intel_rps_client *rps = to_rps_client(file);
 	struct drm_i915_gem_object *obj;
-	unsigned long active;
-	int idx, ret = 0;
+	ktime_t start;
+	long ret;
 
 	if (args->flags != 0)
 		return -EINVAL;
@@ -2812,133 +2992,29 @@ i915_gem_wait_ioctl(struct drm_device *d
 	if (!obj)
 		return -ENOENT;
 
-	active = __I915_BO_ACTIVE(obj);
-	for_each_active(active, idx) {
-		s64 *timeout = args->timeout_ns >= 0 ? &args->timeout_ns : NULL;
-		ret = i915_gem_active_wait_unlocked(&obj->last_read[idx],
-						    I915_WAIT_INTERRUPTIBLE,
-						    timeout, rps);
-		if (ret)
-			break;
-	}
-
-	i915_gem_object_put_unlocked(obj);
-	return ret;
-}
-
-static void __i915_vma_iounmap(struct i915_vma *vma)
-{
-	GEM_BUG_ON(i915_vma_is_pinned(vma));
-
-	if (vma->iomap == NULL)
-		return;
-
-	io_mapping_unmap(vma->iomap);
-	vma->iomap = NULL;
-}
-
-int i915_vma_unbind(struct i915_vma *vma)
-{
-	struct drm_i915_gem_object *obj = vma->obj;
-	unsigned long active;
-	int ret;
-
-	/* First wait upon any activity as retiring the request may
-	 * have side-effects such as unpinning or even unbinding this vma.
-	 */
-	active = i915_vma_get_active(vma);
-	if (active) {
-		int idx;
-
-		/* When a closed VMA is retired, it is unbound - eek.
-		 * In order to prevent it from being recursively closed,
-		 * take a pin on the vma so that the second unbind is
-		 * aborted.
-		 */
-		__i915_vma_pin(vma);
-
-		for_each_active(active, idx) {
-			ret = i915_gem_active_retire(&vma->last_read[idx],
-						   &vma->vm->dev->struct_mutex);
-			if (ret)
-				break;
-		}
-
-		__i915_vma_unpin(vma);
-		if (ret)
-			return ret;
-
-		GEM_BUG_ON(i915_vma_is_active(vma));
-	}
-
-	if (i915_vma_is_pinned(vma))
-		return -EBUSY;
-
-	if (!drm_mm_node_allocated(&vma->node))
-		goto destroy;
-
-	GEM_BUG_ON(obj->bind_count == 0);
-	GEM_BUG_ON(!obj->pages);
-
-	if (i915_vma_is_map_and_fenceable(vma)) {
-		/* release the fence reg _after_ flushing */
-		ret = i915_vma_put_fence(vma);
-		if (ret)
-			return ret;
-
-		/* Force a pagefault for domain tracking on next user access */
-		i915_gem_release_mmap(obj);
-
-		__i915_vma_iounmap(vma);
-		vma->flags &= ~I915_VMA_CAN_FENCE;
-	}
-
-	if (likely(!vma->vm->closed)) {
-		trace_i915_vma_unbind(vma);
-		vma->vm->unbind_vma(vma);
-	}
-	vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
+	start = ktime_get();
 
-	drm_mm_remove_node(&vma->node);
-	list_move_tail(&vma->vm_link, &vma->vm->unbound_list);
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE | I915_WAIT_ALL,
+				   to_wait_timeout(args->timeout_ns),
+				   to_rps_client(file));
 
-	if (vma->pages != obj->pages) {
-		GEM_BUG_ON(!vma->pages);
-		sg_free_table(vma->pages);
-		kfree(vma->pages);
+	if (args->timeout_ns > 0) {
+		args->timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start));
+		if (args->timeout_ns < 0)
+			args->timeout_ns = 0;
 	}
-	vma->pages = NULL;
-
-	/* Since the unbound list is global, only move to that list if
-	 * no more VMAs exist. */
-	if (--obj->bind_count == 0)
-		list_move_tail(&obj->global_list,
-			       &to_i915(obj->base.dev)->mm.unbound_list);
-
-	/* And finally now the object is completely decoupled from this vma,
-	 * we can drop its hold on the backing storage and allow it to be
-	 * reaped by the shrinker.
-	 */
-	i915_gem_object_unpin_pages(obj);
 
-destroy:
-	if (unlikely(i915_vma_is_closed(vma)))
-		i915_vma_destroy(vma);
-
-	return 0;
+	i915_gem_object_put(obj);
+	return ret;
 }
 
-int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv,
-			   unsigned int flags)
+static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags)
 {
-	struct intel_engine_cs *engine;
-	int ret;
-
-	for_each_engine(engine, dev_priv) {
-		if (engine->last_context == NULL)
-			continue;
+	int ret, i;
 
-		ret = intel_engine_idle(engine, flags);
+	for (i = 0; i < ARRAY_SIZE(tl->engine); i++) {
+		ret = i915_gem_active_wait(&tl->engine[i].last_request, flags);
 		if (ret)
 			return ret;
 	}
@@ -2946,187 +3022,45 @@ int i915_gem_wait_for_idle(struct drm_i9
 	return 0;
 }
 
-static bool i915_gem_valid_gtt_space(struct i915_vma *vma,
-				     unsigned long cache_level)
-{
-	struct drm_mm_node *gtt_space = &vma->node;
-	struct drm_mm_node *other;
-
-	/*
-	 * On some machines we have to be careful when putting differing types
-	 * of snoopable memory together to avoid the prefetcher crossing memory
-	 * domains and dying. During vm initialisation, we decide whether or not
-	 * these constraints apply and set the drm_mm.color_adjust
-	 * appropriately.
-	 */
-	if (vma->vm->mm.color_adjust == NULL)
-		return true;
-
-	if (!drm_mm_node_allocated(gtt_space))
-		return true;
-
-	if (list_empty(&gtt_space->node_list))
-		return true;
-
-	other = list_entry(gtt_space->node_list.prev, struct drm_mm_node, node_list);
-	if (other->allocated && !other->hole_follows && other->color != cache_level)
-		return false;
-
-	other = list_entry(gtt_space->node_list.next, struct drm_mm_node, node_list);
-	if (other->allocated && !gtt_space->hole_follows && other->color != cache_level)
-		return false;
-
-	return true;
-}
-
-/**
- * i915_vma_insert - finds a slot for the vma in its address space
- * @vma: the vma
- * @size: requested size in bytes (can be larger than the VMA)
- * @alignment: required alignment
- * @flags: mask of PIN_* flags to use
- *
- * First we try to allocate some free space that meets the requirements for
- * the VMA. Failiing that, if the flags permit, it will evict an old VMA,
- * preferrably the oldest idle entry to make room for the new VMA.
- *
- * Returns:
- * 0 on success, negative error code otherwise.
- */
-static int
-i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+int i915_gem_wait_for_idle(struct drm_i915_private *i915, unsigned int flags)
 {
-	struct drm_i915_private *dev_priv = to_i915(vma->vm->dev);
-	struct drm_i915_gem_object *obj = vma->obj;
-	u64 start, end;
 	int ret;
 
-	GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND));
-	GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
-
-	size = max(size, vma->size);
-	if (flags & PIN_MAPPABLE)
-		size = i915_gem_get_ggtt_size(dev_priv, size,
-					      i915_gem_object_get_tiling(obj));
-
-	alignment = max(max(alignment, vma->display_alignment),
-			i915_gem_get_ggtt_alignment(dev_priv, size,
-						    i915_gem_object_get_tiling(obj),
-						    flags & PIN_MAPPABLE));
-
-	start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
-
-	end = vma->vm->total;
-	if (flags & PIN_MAPPABLE)
-		end = min_t(u64, end, dev_priv->ggtt.mappable_end);
-	if (flags & PIN_ZONE_4G)
-		end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE);
-
-	/* If binding the object/GGTT view requires more space than the entire
-	 * aperture has, reject it early before evicting everything in a vain
-	 * attempt to find space.
-	 */
-	if (size > end) {
-		DRM_DEBUG("Attempting to bind an object larger than the aperture: request=%llu [object=%zd] > %s aperture=%llu\n",
-			  size, obj->base.size,
-			  flags & PIN_MAPPABLE ? "mappable" : "total",
-			  end);
-		return -E2BIG;
-	}
-
-	ret = i915_gem_object_get_pages(obj);
-	if (ret)
-		return ret;
-
-	i915_gem_object_pin_pages(obj);
+	if (flags & I915_WAIT_LOCKED) {
+		struct i915_gem_timeline *tl;
 
-	if (flags & PIN_OFFSET_FIXED) {
-		u64 offset = flags & PIN_OFFSET_MASK;
-		if (offset & (alignment - 1) || offset > end - size) {
-			ret = -EINVAL;
-			goto err_unpin;
-		}
+		lockdep_assert_held(&i915->drm.struct_mutex);
 
-		vma->node.start = offset;
-		vma->node.size = size;
-		vma->node.color = obj->cache_level;
-		ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
-		if (ret) {
-			ret = i915_gem_evict_for_vma(vma);
-			if (ret == 0)
-				ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
+		list_for_each_entry(tl, &i915->gt.timelines, link) {
+			ret = wait_for_timeline(tl, flags);
 			if (ret)
-				goto err_unpin;
+				return ret;
 		}
 	} else {
-		u32 search_flag, alloc_flag;
-
-		if (flags & PIN_HIGH) {
-			search_flag = DRM_MM_SEARCH_BELOW;
-			alloc_flag = DRM_MM_CREATE_TOP;
-		} else {
-			search_flag = DRM_MM_SEARCH_DEFAULT;
-			alloc_flag = DRM_MM_CREATE_DEFAULT;
-		}
-
-		/* We only allocate in PAGE_SIZE/GTT_PAGE_SIZE (4096) chunks,
-		 * so we know that we always have a minimum alignment of 4096.
-		 * The drm_mm range manager is optimised to return results
-		 * with zero alignment, so where possible use the optimal
-		 * path.
-		 */
-		if (alignment <= 4096)
-			alignment = 0;
-
-search_free:
-		ret = drm_mm_insert_node_in_range_generic(&vma->vm->mm,
-							  &vma->node,
-							  size, alignment,
-							  obj->cache_level,
-							  start, end,
-							  search_flag,
-							  alloc_flag);
-		if (ret) {
-			ret = i915_gem_evict_something(vma->vm, size, alignment,
-						       obj->cache_level,
-						       start, end,
-						       flags);
-			if (ret == 0)
-				goto search_free;
-
-			goto err_unpin;
-		}
+		ret = wait_for_timeline(&i915->gt.global_timeline, flags);
+		if (ret)
+			return ret;
 	}
-	GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
-
-	list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
-	list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
-	obj->bind_count++;
 
 	return 0;
-
-err_unpin:
-	i915_gem_object_unpin_pages(obj);
-	return ret;
 }
 
-bool
-i915_gem_clflush_object(struct drm_i915_gem_object *obj,
-			bool force)
+void i915_gem_clflush_object(struct drm_i915_gem_object *obj,
+			     bool force)
 {
 	/* If we don't have a page list set up, then we're not pinned
 	 * to GPU, and we can ignore the cache flush because it'll happen
 	 * again at bind time.
 	 */
-	if (obj->pages == NULL)
-		return false;
+	if (!obj->mm.pages)
+		return;
 
 	/*
 	 * Stolen memory is always coherent with the GPU as it is explicitly
 	 * marked as wc by the system, or the system is cache-coherent.
 	 */
 	if (obj->stolen || obj->phys_handle)
-		return false;
+		return;
 
 	/* If the GPU is snooping the contents of the CPU cache,
 	 * we do not need to manually clear the CPU cache lines.  However,
@@ -3138,14 +3072,12 @@ i915_gem_clflush_object(struct drm_i915_
 	 */
 	if (!force && cpu_cache_is_coherent(obj->base.dev, obj->cache_level)) {
 		obj->cache_dirty = true;
-		return false;
+		return;
 	}
 
 	trace_i915_gem_object_clflush(obj);
-	drm_clflush_sg(obj->pages);
+	drm_clflush_sg(obj->mm.pages);
 	obj->cache_dirty = false;
-
-	return true;
 }
 
 /** Flushes the GTT write domain for the object if it's dirty. */
@@ -3174,7 +3106,7 @@ i915_gem_object_flush_gtt_write_domain(s
 	 */
 	wmb();
 	if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv))
-		POSTING_READ(RING_ACTHD(dev_priv->engine[RCS].mmio_base));
+		POSTING_READ(RING_ACTHD(dev_priv->engine[RCS]->mmio_base));
 
 	intel_fb_obj_flush(obj, false, write_origin(obj, I915_GEM_DOMAIN_GTT));
 
@@ -3191,9 +3123,7 @@ i915_gem_object_flush_cpu_write_domain(s
 	if (obj->base.write_domain != I915_GEM_DOMAIN_CPU)
 		return;
 
-	if (i915_gem_clflush_object(obj, obj->pin_display))
-		i915_gem_chipset_flush(to_i915(obj->base.dev));
-
+	i915_gem_clflush_object(obj, obj->pin_display);
 	intel_fb_obj_flush(obj, false, ORIGIN_CPU);
 
 	obj->base.write_domain = 0;
@@ -3202,24 +3132,6 @@ i915_gem_object_flush_cpu_write_domain(s
 					    I915_GEM_DOMAIN_CPU);
 }
 
-static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
-{
-	struct i915_vma *vma;
-
-	list_for_each_entry(vma, &obj->vma_list, obj_link) {
-		if (!i915_vma_is_ggtt(vma))
-			continue;
-
-		if (i915_vma_is_active(vma))
-			continue;
-
-		if (!drm_mm_node_allocated(&vma->node))
-			continue;
-
-		list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
-	}
-}
-
 /**
  * Moves a single object to the GTT read, and possibly write domain.
  * @obj: object to act on
@@ -3234,7 +3146,14 @@ i915_gem_object_set_to_gtt_domain(struct
 	uint32_t old_write_domain, old_read_domains;
 	int ret;
 
-	ret = i915_gem_object_wait_rendering(obj, !write);
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_LOCKED |
+				   (write ? I915_WAIT_ALL : 0),
+				   MAX_SCHEDULE_TIMEOUT,
+				   NULL);
 	if (ret)
 		return ret;
 
@@ -3249,7 +3168,7 @@ i915_gem_object_set_to_gtt_domain(struct
 	 * continue to assume that the obj remained out of the CPU cached
 	 * domain.
 	 */
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		return ret;
 
@@ -3268,21 +3187,19 @@ i915_gem_object_set_to_gtt_domain(struct
 	/* It should now be out of any other write domains, and we can update
 	 * the domain values for our changes.
 	 */
-	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
+	GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0);
 	obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
 	if (write) {
 		obj->base.read_domains = I915_GEM_DOMAIN_GTT;
 		obj->base.write_domain = I915_GEM_DOMAIN_GTT;
-		obj->dirty = 1;
+		obj->mm.dirty = true;
 	}
 
 	trace_i915_gem_object_change_domain(obj,
 					    old_read_domains,
 					    old_write_domain);
 
-	/* And bump the LRU for this access */
-	i915_gem_object_bump_inactive_ggtt(obj);
-
+	i915_gem_object_unpin_pages(obj);
 	return 0;
 }
 
@@ -3305,10 +3222,12 @@ int i915_gem_object_set_cache_level(stru
 				    enum i915_cache_level cache_level)
 {
 	struct i915_vma *vma;
-	int ret = 0;
+	int ret;
+
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
 
 	if (obj->cache_level == cache_level)
-		goto out;
+		return 0;
 
 	/* Inspect the list of currently bound VMA and unbind any that would
 	 * be invalid given the new cache-level. This is principally to
@@ -3351,11 +3270,17 @@ restart:
 		 * If we wait upon the object, we know that all the bound
 		 * VMA are no longer active.
 		 */
-		ret = i915_gem_object_wait_rendering(obj, false);
+		ret = i915_gem_object_wait(obj,
+					   I915_WAIT_INTERRUPTIBLE |
+					   I915_WAIT_LOCKED |
+					   I915_WAIT_ALL,
+					   MAX_SCHEDULE_TIMEOUT,
+					   NULL);
 		if (ret)
 			return ret;
 
-		if (!HAS_LLC(obj->base.dev) && cache_level != I915_CACHE_NONE) {
+		if (!HAS_LLC(to_i915(obj->base.dev)) &&
+		    cache_level != I915_CACHE_NONE) {
 			/* Access to snoopable pages through the GTT is
 			 * incoherent and on some machines causes a hard
 			 * lockup. Relinquish the CPU mmaping to force
@@ -3397,20 +3322,14 @@ restart:
 		}
 	}
 
+	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU &&
+	    cpu_cache_is_coherent(obj->base.dev, obj->cache_level))
+		obj->cache_dirty = true;
+
 	list_for_each_entry(vma, &obj->vma_list, obj_link)
 		vma->node.color = cache_level;
 	obj->cache_level = cache_level;
 
-out:
-	/* Flush the dirty CPU caches to the backing storage so that the
-	 * object is now coherent at its new cache level (with respect
-	 * to the access domain).
-	 */
-	if (obj->cache_dirty && cpu_write_needs_clflush(obj)) {
-		if (i915_gem_clflush_object(obj, true))
-			i915_gem_chipset_flush(to_i915(obj->base.dev));
-	}
-
 	return 0;
 }
 
@@ -3419,10 +3338,14 @@ int i915_gem_get_caching_ioctl(struct dr
 {
 	struct drm_i915_gem_caching *args = data;
 	struct drm_i915_gem_object *obj;
+	int err = 0;
 
-	obj = i915_gem_object_lookup(file, args->handle);
-	if (!obj)
-		return -ENOENT;
+	rcu_read_lock();
+	obj = i915_gem_object_lookup_rcu(file, args->handle);
+	if (!obj) {
+		err = -ENOENT;
+		goto out;
+	}
 
 	switch (obj->cache_level) {
 	case I915_CACHE_LLC:
@@ -3438,15 +3361,15 @@ int i915_gem_get_caching_ioctl(struct dr
 		args->caching = I915_CACHING_NONE;
 		break;
 	}
-
-	i915_gem_object_put_unlocked(obj);
-	return 0;
+out:
+	rcu_read_unlock();
+	return err;
 }
 
 int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
 			       struct drm_file *file)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *i915 = to_i915(dev);
 	struct drm_i915_gem_caching *args = data;
 	struct drm_i915_gem_object *obj;
 	enum i915_cache_level level;
@@ -3463,23 +3386,21 @@ int i915_gem_set_caching_ioctl(struct dr
 		 * cacheline, whereas normally such cachelines would get
 		 * invalidated.
 		 */
-		if (!HAS_LLC(dev) && !HAS_SNOOP(dev))
+		if (!HAS_LLC(i915) && !HAS_SNOOP(i915))
 			return -ENODEV;
 
 		level = I915_CACHE_LLC;
 		break;
 	case I915_CACHING_DISPLAY:
-		level = HAS_WT(dev) ? I915_CACHE_WT : I915_CACHE_NONE;
+		level = HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	intel_runtime_pm_get(dev_priv);
-
 	ret = i915_mutex_lock_interruptible(dev);
 	if (ret)
-		goto rpm_put;
+		return ret;
 
 	obj = i915_gem_object_lookup(file, args->handle);
 	if (!obj) {
@@ -3488,13 +3409,9 @@ int i915_gem_set_caching_ioctl(struct dr
 	}
 
 	ret = i915_gem_object_set_cache_level(obj, level);
-
 	i915_gem_object_put(obj);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
-rpm_put:
-	intel_runtime_pm_put(dev_priv);
-
 	return ret;
 }
 
@@ -3512,6 +3429,8 @@ i915_gem_object_pin_to_display_plane(str
 	u32 old_read_domains, old_write_domain;
 	int ret;
 
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
 	/* Mark the pin_display early so that we account for the
 	 * display coherency whilst setting up the cache domains.
 	 */
@@ -3527,7 +3446,8 @@ i915_gem_object_pin_to_display_plane(str
 	 * with that bit in the PTE to main memory with just one PIPE_CONTROL.
 	 */
 	ret = i915_gem_object_set_cache_level(obj,
-					      HAS_WT(obj->base.dev) ? I915_CACHE_WT : I915_CACHE_NONE);
+					      HAS_WT(to_i915(obj->base.dev)) ?
+					      I915_CACHE_WT : I915_CACHE_NONE);
 	if (ret) {
 		vma = ERR_PTR(ret);
 		goto err_unpin_display;
@@ -3565,7 +3485,11 @@ i915_gem_object_pin_to_display_plane(str
 
 	vma->display_alignment = max_t(u64, vma->display_alignment, alignment);
 
-	i915_gem_object_flush_cpu_write_domain(obj);
+	/* Treat this as an end-of-frame, like intel_user_framebuffer_dirty() */
+	if (obj->cache_dirty || obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
+		i915_gem_clflush_object(obj, true);
+		intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
+	}
 
 	old_write_domain = obj->base.write_domain;
 	old_read_domains = obj->base.read_domains;
@@ -3590,6 +3514,8 @@ err_unpin_display:
 void
 i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)
 {
+	lockdep_assert_held(&vma->vm->dev->struct_mutex);
+
 	if (WARN_ON(vma->obj->pin_display == 0))
 		return;
 
@@ -3617,7 +3543,14 @@ i915_gem_object_set_to_cpu_domain(struct
 	uint32_t old_write_domain, old_read_domains;
 	int ret;
 
-	ret = i915_gem_object_wait_rendering(obj, !write);
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+	ret = i915_gem_object_wait(obj,
+				   I915_WAIT_INTERRUPTIBLE |
+				   I915_WAIT_LOCKED |
+				   (write ? I915_WAIT_ALL : 0),
+				   MAX_SCHEDULE_TIMEOUT,
+				   NULL);
 	if (ret)
 		return ret;
 
@@ -3639,7 +3572,7 @@ i915_gem_object_set_to_cpu_domain(struct
 	/* It should now be out of any other write domains, and we can update
 	 * the domain values for our changes.
 	 */
-	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
+	GEM_BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0);
 
 	/* If we're writing through the CPU, then the GPU read domains will
 	 * need to be invalidated at next use.
@@ -3673,11 +3606,7 @@ i915_gem_ring_throttle(struct drm_device
 	struct drm_i915_file_private *file_priv = file->driver_priv;
 	unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES;
 	struct drm_i915_gem_request *request, *target = NULL;
-	int ret;
-
-	ret = i915_gem_wait_for_error(&dev_priv->gpu_error);
-	if (ret)
-		return ret;
+	long ret;
 
 	/* ABI: return -EIO if already wedged */
 	if (i915_terminally_wedged(&dev_priv->gpu_error))
@@ -3704,103 +3633,12 @@ i915_gem_ring_throttle(struct drm_device
 	if (target == NULL)
 		return 0;
 
-	ret = i915_wait_request(target, I915_WAIT_INTERRUPTIBLE, NULL, NULL);
+	ret = i915_wait_request(target,
+				I915_WAIT_INTERRUPTIBLE,
+				MAX_SCHEDULE_TIMEOUT);
 	i915_gem_request_put(target);
 
-	return ret;
-}
-
-static bool
-i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
-{
-	if (!drm_mm_node_allocated(&vma->node))
-		return false;
-
-	if (vma->node.size < size)
-		return true;
-
-	if (alignment && vma->node.start & (alignment - 1))
-		return true;
-
-	if (flags & PIN_MAPPABLE && !i915_vma_is_map_and_fenceable(vma))
-		return true;
-
-	if (flags & PIN_OFFSET_BIAS &&
-	    vma->node.start < (flags & PIN_OFFSET_MASK))
-		return true;
-
-	if (flags & PIN_OFFSET_FIXED &&
-	    vma->node.start != (flags & PIN_OFFSET_MASK))
-		return true;
-
-	return false;
-}
-
-void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
-{
-	struct drm_i915_gem_object *obj = vma->obj;
-	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
-	bool mappable, fenceable;
-	u32 fence_size, fence_alignment;
-
-	fence_size = i915_gem_get_ggtt_size(dev_priv,
-					    vma->size,
-					    i915_gem_object_get_tiling(obj));
-	fence_alignment = i915_gem_get_ggtt_alignment(dev_priv,
-						      vma->size,
-						      i915_gem_object_get_tiling(obj),
-						      true);
-
-	fenceable = (vma->node.size == fence_size &&
-		     (vma->node.start & (fence_alignment - 1)) == 0);
-
-	mappable = (vma->node.start + fence_size <=
-		    dev_priv->ggtt.mappable_end);
-
-	/*
-	 * Explicitly disable for rotated VMA since the display does not
-	 * need the fence and the VMA is not accessible to other users.
-	 */
-	if (mappable && fenceable &&
-	    vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED)
-		vma->flags |= I915_VMA_CAN_FENCE;
-	else
-		vma->flags &= ~I915_VMA_CAN_FENCE;
-}
-
-int __i915_vma_do_pin(struct i915_vma *vma,
-		      u64 size, u64 alignment, u64 flags)
-{
-	unsigned int bound = vma->flags;
-	int ret;
-
-	GEM_BUG_ON((flags & (PIN_GLOBAL | PIN_USER)) == 0);
-	GEM_BUG_ON((flags & PIN_GLOBAL) && !i915_vma_is_ggtt(vma));
-
-	if (WARN_ON(bound & I915_VMA_PIN_OVERFLOW)) {
-		ret = -EBUSY;
-		goto err;
-	}
-
-	if ((bound & I915_VMA_BIND_MASK) == 0) {
-		ret = i915_vma_insert(vma, size, alignment, flags);
-		if (ret)
-			goto err;
-	}
-
-	ret = i915_vma_bind(vma, vma->obj->cache_level, flags);
-	if (ret)
-		goto err;
-
-	if ((bound ^ vma->flags) & I915_VMA_GLOBAL_BIND)
-		__i915_vma_set_map_and_fenceable(vma);
-
-	GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
-	return 0;
-
-err:
-	__i915_vma_unpin(vma);
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 struct i915_vma *
@@ -3810,10 +3648,13 @@ i915_gem_object_ggtt_pin(struct drm_i915
 			 u64 alignment,
 			 u64 flags)
 {
-	struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base;
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct i915_address_space *vm = &dev_priv->ggtt.base;
 	struct i915_vma *vma;
 	int ret;
 
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
 	vma = i915_gem_obj_lookup_or_create_vma(obj, vm, view);
 	if (IS_ERR(vma))
 		return vma;
@@ -3823,6 +3664,41 @@ i915_gem_object_ggtt_pin(struct drm_i915
 		    (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)))
 			return ERR_PTR(-ENOSPC);
 
+		if (flags & PIN_MAPPABLE) {
+			u32 fence_size;
+
+			fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size,
+							    i915_gem_object_get_tiling(obj));
+			/* If the required space is larger than the available
+			 * aperture, we will not able to find a slot for the
+			 * object and unbinding the object now will be in
+			 * vain. Worse, doing so may cause us to ping-pong
+			 * the object in and out of the Global GTT and
+			 * waste a lot of cycles under the mutex.
+			 */
+			if (fence_size > dev_priv->ggtt.mappable_end)
+				return ERR_PTR(-E2BIG);
+
+			/* If NONBLOCK is set the caller is optimistically
+			 * trying to cache the full object within the mappable
+			 * aperture, and *must* have a fallback in place for
+			 * situations where we cannot bind the object. We
+			 * can be a little more lax here and use the fallback
+			 * more often to avoid costly migrations of ourselves
+			 * and other objects within the aperture.
+			 *
+			 * Half-the-aperture is used as a simple heuristic.
+			 * More interesting would to do search for a free
+			 * block prior to making the commitment to unbind.
+			 * That caters for the self-harm case, and with a
+			 * little more heuristics (e.g. NOFAULT, NOEVICT)
+			 * we could try to minimise harm to others.
+			 */
+			if (flags & PIN_NONBLOCK &&
+			    fence_size > dev_priv->ggtt.mappable_end / 2)
+				return ERR_PTR(-ENOSPC);
+		}
+
 		WARN(i915_vma_is_pinned(vma),
 		     "bo is already pinned in ggtt with incorrect alignment:"
 		     " offset=%08x, req.alignment=%llx,"
@@ -3869,83 +3745,42 @@ static __always_inline unsigned int __bu
 }
 
 static __always_inline unsigned int
-__busy_set_if_active(const struct i915_gem_active *active,
+__busy_set_if_active(const struct dma_fence *fence,
 		     unsigned int (*flag)(unsigned int id))
 {
-	struct drm_i915_gem_request *request;
-
-	request = rcu_dereference(active->request);
-	if (!request || i915_gem_request_completed(request))
-		return 0;
+	struct drm_i915_gem_request *rq;
 
-	/* This is racy. See __i915_gem_active_get_rcu() for an in detail
-	 * discussion of how to handle the race correctly, but for reporting
-	 * the busy state we err on the side of potentially reporting the
-	 * wrong engine as being busy (but we guarantee that the result
-	 * is at least self-consistent).
-	 *
-	 * As we use SLAB_DESTROY_BY_RCU, the request may be reallocated
-	 * whilst we are inspecting it, even under the RCU read lock as we are.
-	 * This means that there is a small window for the engine and/or the
-	 * seqno to have been overwritten. The seqno will always be in the
-	 * future compared to the intended, and so we know that if that
-	 * seqno is idle (on whatever engine) our request is idle and the
-	 * return 0 above is correct.
-	 *
-	 * The issue is that if the engine is switched, it is just as likely
-	 * to report that it is busy (but since the switch happened, we know
-	 * the request should be idle). So there is a small chance that a busy
-	 * result is actually the wrong engine.
-	 *
-	 * So why don't we care?
-	 *
-	 * For starters, the busy ioctl is a heuristic that is by definition
-	 * racy. Even with perfect serialisation in the driver, the hardware
-	 * state is constantly advancing - the state we report to the user
-	 * is stale.
-	 *
-	 * The critical information for the busy-ioctl is whether the object
-	 * is idle as userspace relies on that to detect whether its next
-	 * access will stall, or if it has missed submitting commands to
-	 * the hardware allowing the GPU to stall. We never generate a
-	 * false-positive for idleness, thus busy-ioctl is reliable at the
-	 * most fundamental level, and we maintain the guarantee that a
-	 * busy object left to itself will eventually become idle (and stay
-	 * idle!).
-	 *
-	 * We allow ourselves the leeway of potentially misreporting the busy
-	 * state because that is an optimisation heuristic that is constantly
-	 * in flux. Being quickly able to detect the busy/idle state is much
-	 * more important than accurate logging of exactly which engines were
-	 * busy.
-	 *
-	 * For accuracy in reporting the engine, we could use
-	 *
-	 *	result = 0;
-	 *	request = __i915_gem_active_get_rcu(active);
-	 *	if (request) {
-	 *		if (!i915_gem_request_completed(request))
-	 *			result = flag(request->engine->exec_id);
-	 *		i915_gem_request_put(request);
-	 *	}
+	/* We have to check the current hw status of the fence as the uABI
+	 * guarantees forward progress. We could rely on the idle worker
+	 * to eventually flush us, but to minimise latency just ask the
+	 * hardware.
 	 *
-	 * but that still remains susceptible to both hardware and userspace
-	 * races. So we accept making the result of that race slightly worse,
-	 * given the rarity of the race and its low impact on the result.
+	 * Note we only report on the status of native fences.
 	 */
-	return flag(READ_ONCE(request->engine->exec_id));
+	if (!dma_fence_is_i915(fence))
+		return 0;
+
+	/* opencode to_request() in order to avoid const warnings */
+	rq = container_of(fence, struct drm_i915_gem_request, fence);
+	if (i915_gem_request_completed(rq))
+		return 0;
+
+	return flag(rq->engine->exec_id);
 }
 
 static __always_inline unsigned int
-busy_check_reader(const struct i915_gem_active *active)
+busy_check_reader(const struct dma_fence *fence)
 {
-	return __busy_set_if_active(active, __busy_read_flag);
+	return __busy_set_if_active(fence, __busy_read_flag);
 }
 
 static __always_inline unsigned int
-busy_check_writer(const struct i915_gem_active *active)
+busy_check_writer(const struct dma_fence *fence)
 {
-	return __busy_set_if_active(active, __busy_write_id);
+	if (!fence)
+		return 0;
+
+	return __busy_set_if_active(fence, __busy_write_id);
 }
 
 int
@@ -3954,64 +3789,58 @@ i915_gem_busy_ioctl(struct drm_device *d
 {
 	struct drm_i915_gem_busy *args = data;
 	struct drm_i915_gem_object *obj;
-	unsigned long active;
+	struct reservation_object_list *list;
+	unsigned int seq;
+	int err;
 
-	obj = i915_gem_object_lookup(file, args->handle);
+	err = -ENOENT;
+	rcu_read_lock();
+	obj = i915_gem_object_lookup_rcu(file, args->handle);
 	if (!obj)
-		return -ENOENT;
+		goto out;
 
-	args->busy = 0;
-	active = __I915_BO_ACTIVE(obj);
-	if (active) {
-		int idx;
+	/* A discrepancy here is that we do not report the status of
+	 * non-i915 fences, i.e. even though we may report the object as idle,
+	 * a call to set-domain may still stall waiting for foreign rendering.
+	 * This also means that wait-ioctl may report an object as busy,
+	 * where busy-ioctl considers it idle.
+	 *
+	 * We trade the ability to warn of foreign fences to report on which
+	 * i915 engines are active for the object.
+	 *
+	 * Alternatively, we can trade that extra information on read/write
+	 * activity with
+	 *	args->busy =
+	 *		!reservation_object_test_signaled_rcu(obj->resv, true);
+	 * to report the overall busyness. This is what the wait-ioctl does.
+	 *
+	 */
+retry:
+	seq = raw_read_seqcount(&obj->resv->seq);
 
-		/* Yes, the lookups are intentionally racy.
-		 *
-		 * First, we cannot simply rely on __I915_BO_ACTIVE. We have
-		 * to regard the value as stale and as our ABI guarantees
-		 * forward progress, we confirm the status of each active
-		 * request with the hardware.
-		 *
-		 * Even though we guard the pointer lookup by RCU, that only
-		 * guarantees that the pointer and its contents remain
-		 * dereferencable and does *not* mean that the request we
-		 * have is the same as the one being tracked by the object.
-		 *
-		 * Consider that we lookup the request just as it is being
-		 * retired and freed. We take a local copy of the pointer,
-		 * but before we add its engine into the busy set, the other
-		 * thread reallocates it and assigns it to a task on another
-		 * engine with a fresh and incomplete seqno. Guarding against
-		 * that requires careful serialisation and reference counting,
-		 * i.e. using __i915_gem_active_get_request_rcu(). We don't,
-		 * instead we expect that if the result is busy, which engines
-		 * are busy is not completely reliable - we only guarantee
-		 * that the object was busy.
-		 */
-		rcu_read_lock();
+	/* Translate the exclusive fence to the READ *and* WRITE engine */
+	args->busy = busy_check_writer(rcu_dereference(obj->resv->fence_excl));
 
-		for_each_active(active, idx)
-			args->busy |= busy_check_reader(&obj->last_read[idx]);
+	/* Translate shared fences to READ set of engines */
+	list = rcu_dereference(obj->resv->fence);
+	if (list) {
+		unsigned int shared_count = list->shared_count, i;
 
-		/* For ABI sanity, we only care that the write engine is in
-		 * the set of read engines. This should be ensured by the
-		 * ordering of setting last_read/last_write in
-		 * i915_vma_move_to_active(), and then in reverse in retire.
-		 * However, for good measure, we always report the last_write
-		 * request as a busy read as well as being a busy write.
-		 *
-		 * We don't care that the set of active read/write engines
-		 * may change during construction of the result, as it is
-		 * equally liable to change before userspace can inspect
-		 * the result.
-		 */
-		args->busy |= busy_check_writer(&obj->last_write);
+		for (i = 0; i < shared_count; ++i) {
+			struct dma_fence *fence =
+				rcu_dereference(list->shared[i]);
 
-		rcu_read_unlock();
+			args->busy |= busy_check_reader(fence);
+		}
 	}
 
-	i915_gem_object_put_unlocked(obj);
-	return 0;
+	if (args->busy && read_seqcount_retry(&obj->resv->seq, seq))
+		goto retry;
+
+	err = 0;
+out:
+	rcu_read_unlock();
+	return err;
 }
 
 int
@@ -4028,7 +3857,7 @@ i915_gem_madvise_ioctl(struct drm_device
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_madvise *args = data;
 	struct drm_i915_gem_object *obj;
-	int ret;
+	int err;
 
 	switch (args->madv) {
 	case I915_MADV_DONTNEED:
@@ -4038,77 +3867,111 @@ i915_gem_madvise_ioctl(struct drm_device
 	    return -EINVAL;
 	}
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ret;
-
 	obj = i915_gem_object_lookup(file_priv, args->handle);
-	if (!obj) {
-		ret = -ENOENT;
-		goto unlock;
-	}
+	if (!obj)
+		return -ENOENT;
 
-	if (obj->pages &&
+	err = mutex_lock_interruptible(&obj->mm.lock);
+	if (err)
+		goto out;
+
+	if (obj->mm.pages &&
 	    i915_gem_object_is_tiled(obj) &&
 	    dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
-		if (obj->madv == I915_MADV_WILLNEED)
-			i915_gem_object_unpin_pages(obj);
-		if (args->madv == I915_MADV_WILLNEED)
-			i915_gem_object_pin_pages(obj);
+		if (obj->mm.madv == I915_MADV_WILLNEED) {
+			GEM_BUG_ON(!obj->mm.quirked);
+			__i915_gem_object_unpin_pages(obj);
+			obj->mm.quirked = false;
+		}
+		if (args->madv == I915_MADV_WILLNEED) {
+			GEM_BUG_ON(obj->mm.quirked);
+			__i915_gem_object_pin_pages(obj);
+			obj->mm.quirked = true;
+		}
 	}
 
-	if (obj->madv != __I915_MADV_PURGED)
-		obj->madv = args->madv;
+	if (obj->mm.madv != __I915_MADV_PURGED)
+		obj->mm.madv = args->madv;
 
 	/* if the object is no longer attached, discard its backing storage */
-	if (obj->madv == I915_MADV_DONTNEED && obj->pages == NULL)
+	if (obj->mm.madv == I915_MADV_DONTNEED && !obj->mm.pages)
 		i915_gem_object_truncate(obj);
 
-	args->retained = obj->madv != __I915_MADV_PURGED;
+	args->retained = obj->mm.madv != __I915_MADV_PURGED;
+	mutex_unlock(&obj->mm.lock);
 
+out:
 	i915_gem_object_put(obj);
-unlock:
-	mutex_unlock(&dev->struct_mutex);
-	return ret;
+	return err;
+}
+
+static void
+frontbuffer_retire(struct i915_gem_active *active,
+		   struct drm_i915_gem_request *request)
+{
+	struct drm_i915_gem_object *obj =
+		container_of(active, typeof(*obj), frontbuffer_write);
+
+	intel_fb_obj_flush(obj, true, ORIGIN_CS);
 }
 
 void i915_gem_object_init(struct drm_i915_gem_object *obj,
 			  const struct drm_i915_gem_object_ops *ops)
 {
-	int i;
+	mutex_init(&obj->mm.lock);
 
-	INIT_LIST_HEAD(&obj->global_list);
-	for (i = 0; i < I915_NUM_ENGINES; i++)
-		init_request_active(&obj->last_read[i],
-				    i915_gem_object_retire__read);
-	init_request_active(&obj->last_write,
-			    i915_gem_object_retire__write);
+	INIT_LIST_HEAD(&obj->global_link);
+	INIT_LIST_HEAD(&obj->userfault_link);
 	INIT_LIST_HEAD(&obj->obj_exec_link);
 	INIT_LIST_HEAD(&obj->vma_list);
 	INIT_LIST_HEAD(&obj->batch_pool_link);
 
 	obj->ops = ops;
 
+	reservation_object_init(&obj->__builtin_resv);
+	obj->resv = &obj->__builtin_resv;
+
 	obj->frontbuffer_ggtt_origin = ORIGIN_GTT;
-	obj->madv = I915_MADV_WILLNEED;
+	init_request_active(&obj->frontbuffer_write, frontbuffer_retire);
+
+	obj->mm.madv = I915_MADV_WILLNEED;
+	INIT_RADIX_TREE(&obj->mm.get_page.radix, GFP_KERNEL | __GFP_NOWARN);
+	mutex_init(&obj->mm.get_page.lock);
 
 	i915_gem_info_add_obj(to_i915(obj->base.dev), obj->base.size);
 }
 
 static const struct drm_i915_gem_object_ops i915_gem_object_ops = {
-	.flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE,
+	.flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
+		 I915_GEM_OBJECT_IS_SHRINKABLE,
 	.get_pages = i915_gem_object_get_pages_gtt,
 	.put_pages = i915_gem_object_put_pages_gtt,
 };
 
-struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev,
-						  size_t size)
+/* Note we don't consider signbits :| */
+#define overflows_type(x, T) \
+	(sizeof(x) > sizeof(T) && (x) >> (sizeof(T) * BITS_PER_BYTE))
+
+struct drm_i915_gem_object *
+i915_gem_object_create(struct drm_device *dev, u64 size)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_object *obj;
 	struct address_space *mapping;
 	gfp_t mask;
 	int ret;
 
+	/* There is a prevalence of the assumption that we fit the object's
+	 * page count inside a 32bit _signed_ variable. Let's document this and
+	 * catch if we ever need to fix it. In the meantime, if you do spot
+	 * such a local variable, please consider fixing!
+	 */
+	if (WARN_ON(size >> PAGE_SHIFT > INT_MAX))
+		return ERR_PTR(-E2BIG);
+
+	if (overflows_type(size, obj->base.size))
+		return ERR_PTR(-E2BIG);
+
 	obj = i915_gem_object_alloc(dev);
 	if (obj == NULL)
 		return ERR_PTR(-ENOMEM);
@@ -4118,7 +3981,7 @@ struct drm_i915_gem_object *i915_gem_obj
 		goto fail;
 
 	mask = GFP_HIGHUSER | __GFP_RECLAIMABLE;
-	if (IS_CRESTLINE(dev) || IS_BROADWATER(dev)) {
+	if (IS_CRESTLINE(dev_priv) || IS_BROADWATER(dev_priv)) {
 		/* 965gm cannot relocate objects above 4GiB. */
 		mask &= ~__GFP_HIGHMEM;
 		mask |= __GFP_DMA32;
@@ -4132,7 +3995,7 @@ struct drm_i915_gem_object *i915_gem_obj
 	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 
-	if (HAS_LLC(dev)) {
+	if (HAS_LLC(dev_priv)) {
 		/* On some devices, we can have the GPU use the LLC (the CPU
 		 * cache) for about a 10% performance improvement
 		 * compared to uncached.  Graphics requests other than
@@ -4155,7 +4018,6 @@ struct drm_i915_gem_object *i915_gem_obj
 
 fail:
 	i915_gem_object_free(obj);
-
 	return ERR_PTR(ret);
 }
 
@@ -4167,7 +4029,7 @@ static bool discard_backing_storage(stru
 	 * back the contents from the GPU.
 	 */
 
-	if (obj->madv != I915_MADV_WILLNEED)
+	if (obj->mm.madv != I915_MADV_WILLNEED)
 		return false;
 
 	if (obj->base.filp == NULL)
@@ -4183,16 +4045,72 @@ static bool discard_backing_storage(stru
 	return atomic_long_read(&obj->base.filp->f_count) == 1;
 }
 
-void i915_gem_free_object(struct drm_gem_object *gem_obj)
+static void __i915_gem_free_objects(struct drm_i915_private *i915,
+				    struct llist_node *freed)
 {
-	struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
-	struct drm_device *dev = obj->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct i915_vma *vma, *next;
+	struct drm_i915_gem_object *obj, *on;
 
-	intel_runtime_pm_get(dev_priv);
+	mutex_lock(&i915->drm.struct_mutex);
+	intel_runtime_pm_get(i915);
+	llist_for_each_entry(obj, freed, freed) {
+		struct i915_vma *vma, *vn;
 
-	trace_i915_gem_object_destroy(obj);
+		trace_i915_gem_object_destroy(obj);
+
+		GEM_BUG_ON(i915_gem_object_is_active(obj));
+		list_for_each_entry_safe(vma, vn,
+					 &obj->vma_list, obj_link) {
+			GEM_BUG_ON(!i915_vma_is_ggtt(vma));
+			GEM_BUG_ON(i915_vma_is_active(vma));
+			vma->flags &= ~I915_VMA_PIN_MASK;
+			i915_vma_close(vma);
+		}
+		GEM_BUG_ON(!list_empty(&obj->vma_list));
+		GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree));
+
+		list_del(&obj->global_link);
+	}
+	intel_runtime_pm_put(i915);
+	mutex_unlock(&i915->drm.struct_mutex);
+
+	llist_for_each_entry_safe(obj, on, freed, freed) {
+		GEM_BUG_ON(obj->bind_count);
+		GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits));
+
+		if (obj->ops->release)
+			obj->ops->release(obj);
+
+		if (WARN_ON(i915_gem_object_has_pinned_pages(obj)))
+			atomic_set(&obj->mm.pages_pin_count, 0);
+		__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
+		GEM_BUG_ON(obj->mm.pages);
+
+		if (obj->base.import_attach)
+			drm_prime_gem_destroy(&obj->base, NULL);
+
+		reservation_object_fini(&obj->__builtin_resv);
+		drm_gem_object_release(&obj->base);
+		i915_gem_info_remove_obj(i915, obj->base.size);
+
+		kfree(obj->bit_17);
+		i915_gem_object_free(obj);
+	}
+}
+
+static void i915_gem_flush_free_objects(struct drm_i915_private *i915)
+{
+	struct llist_node *freed;
+
+	freed = llist_del_all(&i915->mm.free_list);
+	if (unlikely(freed))
+		__i915_gem_free_objects(i915, freed);
+}
+
+static void __i915_gem_free_work(struct work_struct *work)
+{
+	struct drm_i915_private *i915 =
+		container_of(work, struct drm_i915_private, mm.free_work);
+	struct llist_node *freed;
 
 	/* All file-owned VMA should have been released by this point through
 	 * i915_gem_close_object(), or earlier by i915_gem_context_close().
@@ -4201,47 +4119,62 @@ void i915_gem_free_object(struct drm_gem
 	 * the GTT either for the user or for scanout). Those VMA still need to
 	 * unbound now.
 	 */
-	list_for_each_entry_safe(vma, next, &obj->vma_list, obj_link) {
-		GEM_BUG_ON(!i915_vma_is_ggtt(vma));
-		GEM_BUG_ON(i915_vma_is_active(vma));
-		vma->flags &= ~I915_VMA_PIN_MASK;
-		i915_vma_close(vma);
-	}
-	GEM_BUG_ON(obj->bind_count);
 
-	/* Stolen objects don't hold a ref, but do hold pin count. Fix that up
-	 * before progressing. */
-	if (obj->stolen)
-		i915_gem_object_unpin_pages(obj);
+	while ((freed = llist_del_all(&i915->mm.free_list)))
+		__i915_gem_free_objects(i915, freed);
+}
 
-	WARN_ON(atomic_read(&obj->frontbuffer_bits));
+static void __i915_gem_free_object_rcu(struct rcu_head *head)
+{
+	struct drm_i915_gem_object *obj =
+		container_of(head, typeof(*obj), rcu);
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 
-	if (obj->pages && obj->madv == I915_MADV_WILLNEED &&
-	    dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES &&
-	    i915_gem_object_is_tiled(obj))
-		i915_gem_object_unpin_pages(obj);
+	/* We can't simply use call_rcu() from i915_gem_free_object()
+	 * as we need to block whilst unbinding, and the call_rcu
+	 * task may be called from softirq context. So we take a
+	 * detour through a worker.
+	 */
+	if (llist_add(&obj->freed, &i915->mm.free_list))
+		schedule_work(&i915->mm.free_work);
+}
 
-	if (WARN_ON(obj->pages_pin_count))
-		obj->pages_pin_count = 0;
-	if (discard_backing_storage(obj))
-		obj->madv = I915_MADV_DONTNEED;
-	i915_gem_object_put_pages(obj);
+void i915_gem_free_object(struct drm_gem_object *gem_obj)
+{
+	struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
 
-	BUG_ON(obj->pages);
+	if (obj->mm.quirked)
+		__i915_gem_object_unpin_pages(obj);
 
-	if (obj->base.import_attach)
-		drm_prime_gem_destroy(&obj->base, NULL);
+	if (discard_backing_storage(obj))
+		obj->mm.madv = I915_MADV_DONTNEED;
 
-	if (obj->ops->release)
-		obj->ops->release(obj);
+	/* Before we free the object, make sure any pure RCU-only
+	 * read-side critical sections are complete, e.g.
+	 * i915_gem_busy_ioctl(). For the corresponding synchronized
+	 * lookup see i915_gem_object_lookup_rcu().
+	 */
+	call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+}
 
-	drm_gem_object_release(&obj->base);
-	i915_gem_info_remove_obj(dev_priv, obj->base.size);
+void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj)
+{
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
 
-	kfree(obj->bit_17);
-	i915_gem_object_free(obj);
+	GEM_BUG_ON(i915_gem_object_has_active_reference(obj));
+	if (i915_gem_object_is_active(obj))
+		i915_gem_object_set_active_reference(obj);
+	else
+		i915_gem_object_put(obj);
+}
 
-	intel_runtime_pm_put(dev_priv);
+static void assert_kernel_context_is_current(struct drm_i915_private *dev_priv)
+{
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	for_each_engine(engine, dev_priv, id)
+		GEM_BUG_ON(engine->last_context != dev_priv->kernel_context);
 }
 
 int i915_gem_suspend(struct drm_device *dev)
@@ -4272,18 +4205,46 @@ int i915_gem_suspend(struct drm_device *
 		goto err;
 
 	i915_gem_retire_requests(dev_priv);
+	GEM_BUG_ON(dev_priv->gt.active_requests);
 
+	assert_kernel_context_is_current(dev_priv);
 	i915_gem_context_lost(dev_priv);
 	mutex_unlock(&dev->struct_mutex);
 
 	cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
 	cancel_delayed_work_sync(&dev_priv->gt.retire_work);
 	flush_delayed_work(&dev_priv->gt.idle_work);
+	flush_work(&dev_priv->mm.free_work);
 
 	/* Assert that we sucessfully flushed all the work and
 	 * reset the GPU back to its idle, low power state.
 	 */
 	WARN_ON(dev_priv->gt.awake);
+	WARN_ON(!intel_execlists_idle(dev_priv));
+
+	/*
+	 * Neither the BIOS, ourselves or any other kernel
+	 * expects the system to be in execlists mode on startup,
+	 * so we need to reset the GPU back to legacy mode. And the only
+	 * known way to disable logical contexts is through a GPU reset.
+	 *
+	 * So in order to leave the system in a known default configuration,
+	 * always reset the GPU upon unload and suspend. Afterwards we then
+	 * clean up the GEM state tracking, flushing off the requests and
+	 * leaving the system in a known idle state.
+	 *
+	 * Note that is of the upmost importance that the GPU is idle and
+	 * all stray writes are flushed *before* we dismantle the backing
+	 * storage for the pinned objects.
+	 *
+	 * However, since we are uncertain that resetting the GPU on older
+	 * machines is a good idea, we don't - just in case it leaves the
+	 * machine in an unusable condition.
+	 */
+	if (HAS_HW_CONTEXTS(dev_priv)) {
+		int reset = intel_gpu_reset(dev_priv, ALL_ENGINES);
+		WARN_ON(reset && reset != -ENODEV);
+	}
 
 	return 0;
 
@@ -4296,8 +4257,10 @@ void i915_gem_resume(struct drm_device *
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
+	WARN_ON(dev_priv->gt.awake);
+
 	mutex_lock(&dev->struct_mutex);
-	i915_gem_restore_gtt_mappings(dev);
+	i915_gem_restore_gtt_mappings(dev_priv);
 
 	/* As we didn't flush the kernel context before suspend, we cannot
 	 * guarantee that the context image is complete. So let's just reset
@@ -4308,55 +4271,51 @@ void i915_gem_resume(struct drm_device *
 	mutex_unlock(&dev->struct_mutex);
 }
 
-void i915_gem_init_swizzling(struct drm_device *dev)
+void i915_gem_init_swizzling(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (INTEL_INFO(dev)->gen < 5 ||
+	if (INTEL_GEN(dev_priv) < 5 ||
 	    dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE)
 		return;
 
 	I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) |
 				 DISP_TILE_SURFACE_SWIZZLING);
 
-	if (IS_GEN5(dev))
+	if (IS_GEN5(dev_priv))
 		return;
 
 	I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);
-	if (IS_GEN6(dev))
+	if (IS_GEN6(dev_priv))
 		I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
-	else if (IS_GEN7(dev))
+	else if (IS_GEN7(dev_priv))
 		I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
-	else if (IS_GEN8(dev))
+	else if (IS_GEN8(dev_priv))
 		I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW));
 	else
 		BUG();
 }
 
-static void init_unused_ring(struct drm_device *dev, u32 base)
+static void init_unused_ring(struct drm_i915_private *dev_priv, u32 base)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	I915_WRITE(RING_CTL(base), 0);
 	I915_WRITE(RING_HEAD(base), 0);
 	I915_WRITE(RING_TAIL(base), 0);
 	I915_WRITE(RING_START(base), 0);
 }
 
-static void init_unused_rings(struct drm_device *dev)
+static void init_unused_rings(struct drm_i915_private *dev_priv)
 {
-	if (IS_I830(dev)) {
-		init_unused_ring(dev, PRB1_BASE);
-		init_unused_ring(dev, SRB0_BASE);
-		init_unused_ring(dev, SRB1_BASE);
-		init_unused_ring(dev, SRB2_BASE);
-		init_unused_ring(dev, SRB3_BASE);
-	} else if (IS_GEN2(dev)) {
-		init_unused_ring(dev, SRB0_BASE);
-		init_unused_ring(dev, SRB1_BASE);
-	} else if (IS_GEN3(dev)) {
-		init_unused_ring(dev, PRB1_BASE);
-		init_unused_ring(dev, PRB2_BASE);
+	if (IS_I830(dev_priv)) {
+		init_unused_ring(dev_priv, PRB1_BASE);
+		init_unused_ring(dev_priv, SRB0_BASE);
+		init_unused_ring(dev_priv, SRB1_BASE);
+		init_unused_ring(dev_priv, SRB2_BASE);
+		init_unused_ring(dev_priv, SRB3_BASE);
+	} else if (IS_GEN2(dev_priv)) {
+		init_unused_ring(dev_priv, SRB0_BASE);
+		init_unused_ring(dev_priv, SRB1_BASE);
+	} else if (IS_GEN3(dev_priv)) {
+		init_unused_ring(dev_priv, PRB1_BASE);
+		init_unused_ring(dev_priv, PRB2_BASE);
 	}
 }
 
@@ -4365,31 +4324,34 @@ i915_gem_init_hw(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int ret;
 
+	dev_priv->gt.last_init_time = ktime_get();
+
 	/* Double layer security blanket, see i915_gem_init() */
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
-	if (HAS_EDRAM(dev) && INTEL_GEN(dev_priv) < 9)
+	if (HAS_EDRAM(dev_priv) && INTEL_GEN(dev_priv) < 9)
 		I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf));
 
-	if (IS_HASWELL(dev))
-		I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ?
+	if (IS_HASWELL(dev_priv))
+		I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ?
 			   LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED);
 
-	if (HAS_PCH_NOP(dev)) {
-		if (IS_IVYBRIDGE(dev)) {
+	if (HAS_PCH_NOP(dev_priv)) {
+		if (IS_IVYBRIDGE(dev_priv)) {
 			u32 temp = I915_READ(GEN7_MSG_CTL);
 			temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK);
 			I915_WRITE(GEN7_MSG_CTL, temp);
-		} else if (INTEL_INFO(dev)->gen >= 7) {
+		} else if (INTEL_GEN(dev_priv) >= 7) {
 			u32 temp = I915_READ(HSW_NDE_RSTWRN_OPT);
 			temp &= ~RESET_PCH_HANDSHAKE_ENABLE;
 			I915_WRITE(HSW_NDE_RSTWRN_OPT, temp);
 		}
 	}
 
-	i915_gem_init_swizzling(dev);
+	i915_gem_init_swizzling(dev_priv);
 
 	/*
 	 * At least 830 can leave some of the unused rings
@@ -4397,18 +4359,18 @@ i915_gem_init_hw(struct drm_device *dev)
 	 * will prevent c3 entry. Makes sure all unused rings
 	 * are totally idle.
 	 */
-	init_unused_rings(dev);
+	init_unused_rings(dev_priv);
 
 	BUG_ON(!dev_priv->kernel_context);
 
-	ret = i915_ppgtt_init_hw(dev);
+	ret = i915_ppgtt_init_hw(dev_priv);
 	if (ret) {
 		DRM_ERROR("PPGTT enable HW failed %d\n", ret);
 		goto out;
 	}
 
 	/* Need to do basic initialisation of all rings first: */
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		ret = engine->init_hw(engine);
 		if (ret)
 			goto out;
@@ -4507,21 +4469,15 @@ i915_gem_cleanup_engines(struct drm_devi
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		dev_priv->gt.cleanup_engine(engine);
 }
 
-static void
-init_engine_lists(struct intel_engine_cs *engine)
-{
-	INIT_LIST_HEAD(&engine->request_list);
-}
-
 void
 i915_gem_load_init_fences(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	int i;
 
 	if (INTEL_INFO(dev_priv)->gen >= 7 && !IS_VALLEYVIEW(dev_priv) &&
@@ -4545,41 +4501,52 @@ i915_gem_load_init_fences(struct drm_i91
 		fence->id = i;
 		list_add_tail(&fence->link, &dev_priv->mm.fence_list);
 	}
-	i915_gem_restore_fences(dev);
+	i915_gem_restore_fences(dev_priv);
 
-	i915_gem_detect_bit_6_swizzle(dev);
+	i915_gem_detect_bit_6_swizzle(dev_priv);
 }
 
-void
+int
 i915_gem_load_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int i;
+	int err = -ENOMEM;
 
-	dev_priv->objects =
-		kmem_cache_create("i915_gem_object",
-				  sizeof(struct drm_i915_gem_object), 0,
-				  SLAB_HWCACHE_ALIGN,
-				  NULL);
-	dev_priv->vmas =
-		kmem_cache_create("i915_gem_vma",
-				  sizeof(struct i915_vma), 0,
-				  SLAB_HWCACHE_ALIGN,
-				  NULL);
-	dev_priv->requests =
-		kmem_cache_create("i915_gem_request",
-				  sizeof(struct drm_i915_gem_request), 0,
-				  SLAB_HWCACHE_ALIGN |
-				  SLAB_RECLAIM_ACCOUNT |
-				  SLAB_DESTROY_BY_RCU,
-				  NULL);
+	dev_priv->objects = KMEM_CACHE(drm_i915_gem_object, SLAB_HWCACHE_ALIGN);
+	if (!dev_priv->objects)
+		goto err_out;
+
+	dev_priv->vmas = KMEM_CACHE(i915_vma, SLAB_HWCACHE_ALIGN);
+	if (!dev_priv->vmas)
+		goto err_objects;
+
+	dev_priv->requests = KMEM_CACHE(drm_i915_gem_request,
+					SLAB_HWCACHE_ALIGN |
+					SLAB_RECLAIM_ACCOUNT |
+					SLAB_DESTROY_BY_RCU);
+	if (!dev_priv->requests)
+		goto err_vmas;
+
+	dev_priv->dependencies = KMEM_CACHE(i915_dependency,
+					    SLAB_HWCACHE_ALIGN |
+					    SLAB_RECLAIM_ACCOUNT);
+	if (!dev_priv->dependencies)
+		goto err_requests;
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	INIT_LIST_HEAD(&dev_priv->gt.timelines);
+	err = i915_gem_timeline_init__global(dev_priv);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+	if (err)
+		goto err_dependencies;
 
 	INIT_LIST_HEAD(&dev_priv->context_list);
+	INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work);
+	init_llist_head(&dev_priv->mm.free_list);
 	INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
 	INIT_LIST_HEAD(&dev_priv->mm.bound_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
-	for (i = 0; i < I915_NUM_ENGINES; i++)
-		init_engine_lists(&dev_priv->engine[i]);
+	INIT_LIST_HEAD(&dev_priv->mm.userfault_list);
 	INIT_DELAYED_WORK(&dev_priv->gt.retire_work,
 			  i915_gem_retire_work_handler);
 	INIT_DELAYED_WORK(&dev_priv->gt.idle_work,
@@ -4596,12 +4563,33 @@ i915_gem_load_init(struct drm_device *de
 	atomic_set(&dev_priv->mm.bsd_engine_dispatch_index, 0);
 
 	spin_lock_init(&dev_priv->fb_tracking.lock);
+
+	return 0;
+
+err_dependencies:
+	kmem_cache_destroy(dev_priv->dependencies);
+err_requests:
+	kmem_cache_destroy(dev_priv->requests);
+err_vmas:
+	kmem_cache_destroy(dev_priv->vmas);
+err_objects:
+	kmem_cache_destroy(dev_priv->objects);
+err_out:
+	return err;
 }
 
 void i915_gem_load_cleanup(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
+	WARN_ON(!llist_empty(&dev_priv->mm.free_list));
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	i915_gem_timeline_fini(&dev_priv->gt.global_timeline);
+	WARN_ON(!list_empty(&dev_priv->gt.timelines));
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+
+	kmem_cache_destroy(dev_priv->dependencies);
 	kmem_cache_destroy(dev_priv->requests);
 	kmem_cache_destroy(dev_priv->vmas);
 	kmem_cache_destroy(dev_priv->objects);
@@ -4650,7 +4638,7 @@ int i915_gem_freeze_late(struct drm_i915
 	i915_gem_shrink(dev_priv, -1UL, I915_SHRINK_UNBOUND);
 
 	for (p = phases; *p; p++) {
-		list_for_each_entry(obj, *p, global_list) {
+		list_for_each_entry(obj, *p, global_link) {
 			obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 			obj->base.write_domain = I915_GEM_DOMAIN_CPU;
 		}
@@ -4686,7 +4674,7 @@ int i915_gem_open(struct drm_device *dev
 	struct drm_i915_file_private *file_priv;
 	int ret;
 
-	DRM_DEBUG_DRIVER("\n");
+	DRM_DEBUG("\n");
 
 	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
 	if (!file_priv)
@@ -4742,21 +4730,6 @@ void i915_gem_track_fb(struct drm_i915_g
 	}
 }
 
-/* Like i915_gem_object_get_page(), but mark the returned page dirty */
-struct page *
-i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
-{
-	struct page *page;
-
-	/* Only default objects have per-page dirty tracking */
-	if (WARN_ON(!i915_gem_object_has_struct_page(obj)))
-		return NULL;
-
-	page = i915_gem_object_get_page(obj, n);
-	set_page_dirty(page);
-	return page;
-}
-
 /* Allocate a new GEM object and fill it with the supplied data */
 struct drm_i915_gem_object *
 i915_gem_object_create_from_data(struct drm_device *dev,
@@ -4775,14 +4748,13 @@ i915_gem_object_create_from_data(struct
 	if (ret)
 		goto fail;
 
-	ret = i915_gem_object_get_pages(obj);
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		goto fail;
 
-	i915_gem_object_pin_pages(obj);
-	sg = obj->pages;
+	sg = obj->mm.pages;
 	bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size);
-	obj->dirty = 1;		/* Backing store is now out of date */
+	obj->mm.dirty = true; /* Backing store is now out of date */
 	i915_gem_object_unpin_pages(obj);
 
 	if (WARN_ON(bytes != size)) {
@@ -4797,3 +4769,156 @@ fail:
 	i915_gem_object_put(obj);
 	return ERR_PTR(ret);
 }
+
+struct scatterlist *
+i915_gem_object_get_sg(struct drm_i915_gem_object *obj,
+		       unsigned int n,
+		       unsigned int *offset)
+{
+	struct i915_gem_object_page_iter *iter = &obj->mm.get_page;
+	struct scatterlist *sg;
+	unsigned int idx, count;
+
+	might_sleep();
+	GEM_BUG_ON(n >= obj->base.size >> PAGE_SHIFT);
+	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+
+	/* As we iterate forward through the sg, we record each entry in a
+	 * radixtree for quick repeated (backwards) lookups. If we have seen
+	 * this index previously, we will have an entry for it.
+	 *
+	 * Initial lookup is O(N), but this is amortized to O(1) for
+	 * sequential page access (where each new request is consecutive
+	 * to the previous one). Repeated lookups are O(lg(obj->base.size)),
+	 * i.e. O(1) with a large constant!
+	 */
+	if (n < READ_ONCE(iter->sg_idx))
+		goto lookup;
+
+	mutex_lock(&iter->lock);
+
+	/* We prefer to reuse the last sg so that repeated lookup of this
+	 * (or the subsequent) sg are fast - comparing against the last
+	 * sg is faster than going through the radixtree.
+	 */
+
+	sg = iter->sg_pos;
+	idx = iter->sg_idx;
+	count = __sg_page_count(sg);
+
+	while (idx + count <= n) {
+		unsigned long exception, i;
+		int ret;
+
+		/* If we cannot allocate and insert this entry, or the
+		 * individual pages from this range, cancel updating the
+		 * sg_idx so that on this lookup we are forced to linearly
+		 * scan onwards, but on future lookups we will try the
+		 * insertion again (in which case we need to be careful of
+		 * the error return reporting that we have already inserted
+		 * this index).
+		 */
+		ret = radix_tree_insert(&iter->radix, idx, sg);
+		if (ret && ret != -EEXIST)
+			goto scan;
+
+		exception =
+			RADIX_TREE_EXCEPTIONAL_ENTRY |
+			idx << RADIX_TREE_EXCEPTIONAL_SHIFT;
+		for (i = 1; i < count; i++) {
+			ret = radix_tree_insert(&iter->radix, idx + i,
+						(void *)exception);
+			if (ret && ret != -EEXIST)
+				goto scan;
+		}
+
+		idx += count;
+		sg = ____sg_next(sg);
+		count = __sg_page_count(sg);
+	}
+
+scan:
+	iter->sg_pos = sg;
+	iter->sg_idx = idx;
+
+	mutex_unlock(&iter->lock);
+
+	if (unlikely(n < idx)) /* insertion completed by another thread */
+		goto lookup;
+
+	/* In case we failed to insert the entry into the radixtree, we need
+	 * to look beyond the current sg.
+	 */
+	while (idx + count <= n) {
+		idx += count;
+		sg = ____sg_next(sg);
+		count = __sg_page_count(sg);
+	}
+
+	*offset = n - idx;
+	return sg;
+
+lookup:
+	rcu_read_lock();
+
+	sg = radix_tree_lookup(&iter->radix, n);
+	GEM_BUG_ON(!sg);
+
+	/* If this index is in the middle of multi-page sg entry,
+	 * the radixtree will contain an exceptional entry that points
+	 * to the start of that range. We will return the pointer to
+	 * the base page and the offset of this page within the
+	 * sg entry's range.
+	 */
+	*offset = 0;
+	if (unlikely(radix_tree_exception(sg))) {
+		unsigned long base =
+			(unsigned long)sg >> RADIX_TREE_EXCEPTIONAL_SHIFT;
+
+		sg = radix_tree_lookup(&iter->radix, base);
+		GEM_BUG_ON(!sg);
+
+		*offset = n - base;
+	}
+
+	rcu_read_unlock();
+
+	return sg;
+}
+
+struct page *
+i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n)
+{
+	struct scatterlist *sg;
+	unsigned int offset;
+
+	GEM_BUG_ON(!i915_gem_object_has_struct_page(obj));
+
+	sg = i915_gem_object_get_sg(obj, n, &offset);
+	return nth_page(sg_page(sg), offset);
+}
+
+/* Like i915_gem_object_get_page(), but mark the returned page dirty */
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj,
+			       unsigned int n)
+{
+	struct page *page;
+
+	page = i915_gem_object_get_page(obj, n);
+	if (!obj->mm.dirty)
+		set_page_dirty(page);
+
+	return page;
+}
+
+dma_addr_t
+i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
+				unsigned long n)
+{
+	struct scatterlist *sg;
+	unsigned int offset;
+
+	sg = i915_gem_object_get_sg(obj, n, &offset);
+	return sg_dma_address(sg) + (offset << PAGE_SHIFT);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_context.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_context.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_context.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_context.c	2017-02-12 16:03:20.000000000 -0500
@@ -155,9 +155,10 @@ void i915_gem_context_free(struct kref *
 		if (ce->ring)
 			intel_ring_free(ce->ring);
 
-		i915_vma_put(ce->state);
+		__i915_gem_object_release_unless_active(ce->state->obj);
 	}
 
+	kfree(ctx->name);
 	put_pid(ctx->pid);
 	list_del(&ctx->link);
 
@@ -192,7 +193,7 @@ i915_gem_alloc_context_obj(struct drm_de
 	 * This is only applicable for Ivy Bridge devices since
 	 * later platforms don't have L3 control bits in the PTE.
 	 */
-	if (IS_IVYBRIDGE(dev)) {
+	if (IS_IVYBRIDGE(to_i915(dev))) {
 		ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC);
 		/* Failure shouldn't ever happen this early */
 		if (WARN_ON(ret)) {
@@ -303,19 +304,28 @@ __create_hw_context(struct drm_device *d
 	}
 
 	/* Default context will never have a file_priv */
-	if (file_priv != NULL) {
+	ret = DEFAULT_CONTEXT_HANDLE;
+	if (file_priv) {
 		ret = idr_alloc(&file_priv->context_idr, ctx,
 				DEFAULT_CONTEXT_HANDLE, 0, GFP_KERNEL);
 		if (ret < 0)
 			goto err_out;
-	} else
-		ret = DEFAULT_CONTEXT_HANDLE;
+	}
+	ctx->user_handle = ret;
 
 	ctx->file_priv = file_priv;
-	if (file_priv)
+	if (file_priv) {
 		ctx->pid = get_task_pid(current, PIDTYPE_PID);
+		ctx->name = kasprintf(GFP_KERNEL, "%s[%d]/%x",
+				      current->comm,
+				      pid_nr(ctx->pid),
+				      ctx->user_handle);
+		if (!ctx->name) {
+			ret = -ENOMEM;
+			goto err_pid;
+		}
+	}
 
-	ctx->user_handle = ret;
 	/* NB: Mark all slices as needing a remap so that when the context first
 	 * loads it will restore whatever remap state already exists. If there
 	 * is no remap info, it will be a NOP. */
@@ -329,6 +339,9 @@ __create_hw_context(struct drm_device *d
 
 	return ctx;
 
+err_pid:
+	put_pid(ctx->pid);
+	idr_remove(&file_priv->context_idr, ctx->user_handle);
 err_out:
 	context_close(ctx);
 	return ERR_PTR(ret);
@@ -352,9 +365,9 @@ i915_gem_create_context(struct drm_devic
 		return ctx;
 
 	if (USES_FULL_PPGTT(dev)) {
-		struct i915_hw_ppgtt *ppgtt =
-			i915_ppgtt_create(to_i915(dev), file_priv);
+		struct i915_hw_ppgtt *ppgtt;
 
+		ppgtt = i915_ppgtt_create(to_i915(dev), file_priv, ctx->name);
 		if (IS_ERR(ppgtt)) {
 			DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
 					 PTR_ERR(ppgtt));
@@ -463,6 +476,7 @@ int i915_gem_context_init(struct drm_dev
 		return PTR_ERR(ctx);
 	}
 
+	ctx->priority = I915_PRIORITY_MIN; /* lowest priority; idle task */
 	dev_priv->kernel_context = ctx;
 
 	DRM_DEBUG_DRIVER("%s context support initialized\n",
@@ -474,10 +488,11 @@ int i915_gem_context_init(struct drm_dev
 void i915_gem_context_lost(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
 	lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		if (engine->last_context) {
 			i915_gem_context_unpin(engine->last_context, engine);
 			engine->last_context = NULL;
@@ -492,13 +507,13 @@ void i915_gem_context_lost(struct drm_i9
 			if (!i915_gem_context_is_default(ctx))
 				continue;
 
-			for_each_engine(engine, dev_priv)
+			for_each_engine(engine, dev_priv, id)
 				ctx->engine[engine->id].initialised = false;
 
 			ctx->remap_slice = ALL_L3_SLICES(dev_priv);
 		}
 
-		for_each_engine(engine, dev_priv) {
+		for_each_engine(engine, dev_priv, id) {
 			struct intel_context *kce =
 				&dev_priv->kernel_context->engine[engine->id];
 
@@ -563,6 +578,7 @@ mi_set_context(struct drm_i915_gem_reque
 	struct drm_i915_private *dev_priv = req->i915;
 	struct intel_ring *ring = req->ring;
 	struct intel_engine_cs *engine = req->engine;
+	enum intel_engine_id id;
 	u32 flags = hw_flags | MI_MM_SPACE_GTT;
 	const int num_rings =
 		/* Use an extended w/a on ivb+ if signalling from other rings */
@@ -605,7 +621,7 @@ mi_set_context(struct drm_i915_gem_reque
 
 			intel_ring_emit(ring,
 					MI_LOAD_REGISTER_IMM(num_rings));
-			for_each_engine(signaller, dev_priv) {
+			for_each_engine(signaller, dev_priv, id) {
 				if (signaller == engine)
 					continue;
 
@@ -634,7 +650,7 @@ mi_set_context(struct drm_i915_gem_reque
 
 			intel_ring_emit(ring,
 					MI_LOAD_REGISTER_IMM(num_rings));
-			for_each_engine(signaller, dev_priv) {
+			for_each_engine(signaller, dev_priv, id) {
 				if (signaller == engine)
 					continue;
 
@@ -749,12 +765,36 @@ needs_pd_load_post(struct i915_hw_ppgtt
 	return false;
 }
 
+struct i915_vma *
+i915_gem_context_pin_legacy(struct i915_gem_context *ctx,
+			    unsigned int flags)
+{
+	struct i915_vma *vma = ctx->engine[RCS].state;
+	int ret;
+
+	/* Clear this page out of any CPU caches for coherent swap-in/out.
+	 * We only want to do this on the first bind so that we do not stall
+	 * on an active context (which by nature is already on the GPU).
+	 */
+	if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
+		ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
+	ret = i915_vma_pin(vma, 0, ctx->ggtt_alignment, PIN_GLOBAL | flags);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return vma;
+}
+
 static int do_rcs_switch(struct drm_i915_gem_request *req)
 {
 	struct i915_gem_context *to = req->ctx;
 	struct intel_engine_cs *engine = req->engine;
 	struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
-	struct i915_vma *vma = to->engine[RCS].state;
+	struct i915_vma *vma;
 	struct i915_gem_context *from;
 	u32 hw_flags;
 	int ret, i;
@@ -762,17 +802,10 @@ static int do_rcs_switch(struct drm_i915
 	if (skip_rcs_switch(ppgtt, engine, to))
 		return 0;
 
-	/* Clear this page out of any CPU caches for coherent swap-in/out. */
-	if (!(vma->flags & I915_VMA_GLOBAL_BIND)) {
-		ret = i915_gem_object_set_to_gtt_domain(vma->obj, false);
-		if (ret)
-			return ret;
-	}
-
 	/* Trying to pin first makes error handling easier. */
-	ret = i915_vma_pin(vma, 0, to->ggtt_alignment, PIN_GLOBAL);
-	if (ret)
-		return ret;
+	vma = i915_gem_context_pin_legacy(to, 0);
+	if (IS_ERR(vma))
+		return PTR_ERR(vma);
 
 	/*
 	 * Pin can switch back to the default context if we end up calling into
@@ -929,21 +962,33 @@ int i915_switch_context(struct drm_i915_
 int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	struct i915_gem_timeline *timeline;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv) {
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+	for_each_engine(engine, dev_priv, id) {
 		struct drm_i915_gem_request *req;
 		int ret;
 
-		if (engine->last_context == NULL)
-			continue;
-
-		if (engine->last_context == dev_priv->kernel_context)
-			continue;
-
 		req = i915_gem_request_alloc(engine, dev_priv->kernel_context);
 		if (IS_ERR(req))
 			return PTR_ERR(req);
 
+		/* Queue this switch after all other activity */
+		list_for_each_entry(timeline, &dev_priv->gt.timelines, link) {
+			struct drm_i915_gem_request *prev;
+			struct intel_timeline *tl;
+
+			tl = &timeline->engine[engine->id];
+			prev = i915_gem_active_raw(&tl->last_request,
+						   &dev_priv->drm.struct_mutex);
+			if (prev)
+				i915_sw_fence_await_sw_fence_gfp(&req->submit,
+								 &prev->submit,
+								 GFP_KERNEL);
+		}
+
 		ret = i915_switch_context(req);
 		i915_add_request_no_flush(req);
 		if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,51 +44,42 @@ static struct sg_table *i915_gem_map_dma
 	struct scatterlist *src, *dst;
 	int ret, i;
 
-	ret = i915_mutex_lock_interruptible(obj->base.dev);
+	ret = i915_gem_object_pin_pages(obj);
 	if (ret)
 		goto err;
 
-	ret = i915_gem_object_get_pages(obj);
-	if (ret)
-		goto err_unlock;
-
-	i915_gem_object_pin_pages(obj);
-
 	/* Copy sg so that we make an independent mapping */
 	st = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
 	if (st == NULL) {
 		ret = -ENOMEM;
-		goto err_unpin;
+		goto err_unpin_pages;
 	}
 
-	ret = sg_alloc_table(st, obj->pages->nents, GFP_KERNEL);
+	ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL);
 	if (ret)
 		goto err_free;
 
-	src = obj->pages->sgl;
+	src = obj->mm.pages->sgl;
 	dst = st->sgl;
-	for (i = 0; i < obj->pages->nents; i++) {
+	for (i = 0; i < obj->mm.pages->nents; i++) {
 		sg_set_page(dst, sg_page(src), src->length, 0);
 		dst = sg_next(dst);
 		src = sg_next(src);
 	}
 
 	if (!dma_map_sg(attachment->dev, st->sgl, st->nents, dir)) {
-		ret =-ENOMEM;
+		ret = -ENOMEM;
 		goto err_free_sg;
 	}
 
-	mutex_unlock(&obj->base.dev->struct_mutex);
 	return st;
 
 err_free_sg:
 	sg_free_table(st);
 err_free:
 	kfree(st);
-err_unpin:
+err_unpin_pages:
 	i915_gem_object_unpin_pages(obj);
-err_unlock:
-	mutex_unlock(&obj->base.dev->struct_mutex);
 err:
 	return ERR_PTR(ret);
 }
@@ -103,36 +94,21 @@ static void i915_gem_unmap_dma_buf(struc
 	sg_free_table(sg);
 	kfree(sg);
 
-	mutex_lock(&obj->base.dev->struct_mutex);
 	i915_gem_object_unpin_pages(obj);
-	mutex_unlock(&obj->base.dev->struct_mutex);
 }
 
 static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
-	struct drm_device *dev = obj->base.dev;
-	void *addr;
-	int ret;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ERR_PTR(ret);
-
-	addr = i915_gem_object_pin_map(obj, I915_MAP_WB);
-	mutex_unlock(&dev->struct_mutex);
-
-	return addr;
+	return i915_gem_object_pin_map(obj, I915_MAP_WB);
 }
 
 static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
-	struct drm_device *dev = obj->base.dev;
 
-	mutex_lock(&dev->struct_mutex);
 	i915_gem_object_unpin_map(obj);
-	mutex_unlock(&dev->struct_mutex);
 }
 
 static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
@@ -179,32 +155,45 @@ static int i915_gem_begin_cpu_access(str
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
 	struct drm_device *dev = obj->base.dev;
-	int ret;
 	bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE);
+	int err;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ret;
+	err = i915_gem_object_pin_pages(obj);
+	if (err)
+		return err;
 
-	ret = i915_gem_object_set_to_cpu_domain(obj, write);
+	err = i915_mutex_lock_interruptible(dev);
+	if (err)
+		goto out;
+
+	err = i915_gem_object_set_to_cpu_domain(obj, write);
 	mutex_unlock(&dev->struct_mutex);
-	return ret;
+
+out:
+	i915_gem_object_unpin_pages(obj);
+	return err;
 }
 
 static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direction direction)
 {
 	struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
 	struct drm_device *dev = obj->base.dev;
-	int ret;
+	int err;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ret;
+	err = i915_gem_object_pin_pages(obj);
+	if (err)
+		return err;
 
-	ret = i915_gem_object_set_to_gtt_domain(obj, false);
+	err = i915_mutex_lock_interruptible(dev);
+	if (err)
+		goto out;
+
+	err = i915_gem_object_set_to_gtt_domain(obj, false);
 	mutex_unlock(&dev->struct_mutex);
 
-	return ret;
+out:
+	i915_gem_object_unpin_pages(obj);
+	return err;
 }
 
 static const struct dma_buf_ops i915_dmabuf_ops =  {
@@ -222,60 +211,17 @@ static const struct dma_buf_ops i915_dma
 	.end_cpu_access = i915_gem_end_cpu_access,
 };
 
-static void export_fences(struct drm_i915_gem_object *obj,
-			  struct dma_buf *dma_buf)
-{
-	struct reservation_object *resv = dma_buf->resv;
-	struct drm_i915_gem_request *req;
-	unsigned long active;
-	int idx;
-
-	active = __I915_BO_ACTIVE(obj);
-	if (!active)
-		return;
-
-	/* Serialise with execbuf to prevent concurrent fence-loops */
-	mutex_lock(&obj->base.dev->struct_mutex);
-
-	/* Mark the object for future fences before racily adding old fences */
-	obj->base.dma_buf = dma_buf;
-
-	ww_mutex_lock(&resv->lock, NULL);
-
-	for_each_active(active, idx) {
-		req = i915_gem_active_get(&obj->last_read[idx],
-					  &obj->base.dev->struct_mutex);
-		if (!req)
-			continue;
-
-		if (reservation_object_reserve_shared(resv) == 0)
-			reservation_object_add_shared_fence(resv, &req->fence);
-
-		i915_gem_request_put(req);
-	}
-
-	req = i915_gem_active_get(&obj->last_write,
-				  &obj->base.dev->struct_mutex);
-	if (req) {
-		reservation_object_add_excl_fence(resv, &req->fence);
-		i915_gem_request_put(req);
-	}
-
-	ww_mutex_unlock(&resv->lock);
-	mutex_unlock(&obj->base.dev->struct_mutex);
-}
-
 struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
 				      struct drm_gem_object *gem_obj, int flags)
 {
 	struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
-	struct dma_buf *dma_buf;
 
 	exp_info.ops = &i915_dmabuf_ops;
 	exp_info.size = gem_obj->size;
 	exp_info.flags = flags;
 	exp_info.priv = gem_obj;
+	exp_info.resv = obj->resv;
 
 	if (obj->ops->dmabuf_export) {
 		int ret = obj->ops->dmabuf_export(obj);
@@ -283,30 +229,21 @@ struct dma_buf *i915_gem_prime_export(st
 			return ERR_PTR(ret);
 	}
 
-	dma_buf = drm_gem_dmabuf_export(dev, &exp_info);
-	if (IS_ERR(dma_buf))
-		return dma_buf;
-
-	export_fences(obj, dma_buf);
-	return dma_buf;
+	return drm_gem_dmabuf_export(dev, &exp_info);
 }
 
-static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
+static struct sg_table *
+i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
 {
-	struct sg_table *sg;
-
-	sg = dma_buf_map_attachment(obj->base.import_attach, DMA_BIDIRECTIONAL);
-	if (IS_ERR(sg))
-		return PTR_ERR(sg);
-
-	obj->pages = sg;
-	return 0;
+	return dma_buf_map_attachment(obj->base.import_attach,
+				      DMA_BIDIRECTIONAL);
 }
 
-static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj)
+static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
+					     struct sg_table *pages)
 {
-	dma_buf_unmap_attachment(obj->base.import_attach,
-				 obj->pages, DMA_BIDIRECTIONAL);
+	dma_buf_unmap_attachment(obj->base.import_attach, pages,
+				 DMA_BIDIRECTIONAL);
 }
 
 static const struct drm_i915_gem_object_ops i915_gem_object_dmabuf_ops = {
@@ -350,6 +287,7 @@ struct drm_gem_object *i915_gem_prime_im
 	drm_gem_private_object_init(dev, &obj->base, dma_buf->size);
 	i915_gem_object_init(obj, &i915_gem_object_dmabuf_ops);
 	obj->base.import_attach = attach;
+	obj->resv = dma_buf->resv;
 
 	/* We use GTT as shorthand for a coherent domain, one that is
 	 * neither in the GPU cache nor in the CPU cache, where all
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_dmabuf.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef _I915_GEM_DMABUF_H_
-#define _I915_GEM_DMABUF_H_
-
-#include <linux/dma-buf.h>
-
-static inline struct reservation_object *
-i915_gem_object_get_dmabuf_resv(struct drm_i915_gem_object *obj)
-{
-	struct dma_buf *dma_buf;
-
-	if (obj->base.dma_buf)
-		dma_buf = obj->base.dma_buf;
-	else if (obj->base.import_attach)
-		dma_buf = obj->base.import_attach->dmabuf;
-	else
-		return NULL;
-
-	return dma_buf->resv;
-}
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_evict.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_evict.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_evict.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_evict.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,13 +33,17 @@
 #include "intel_drv.h"
 #include "i915_trace.h"
 
-static bool
-gpu_is_idle(struct drm_i915_private *dev_priv)
+static bool ggtt_is_idle(struct drm_i915_private *dev_priv)
 {
+	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv) {
-		if (intel_engine_is_active(engine))
+	for_each_engine(engine, dev_priv, id) {
+		struct intel_timeline *tl;
+
+		tl = &ggtt->base.timeline.engine[engine->id];
+		if (i915_gem_active_isset(&tl->last_request))
 			return false;
 	}
 
@@ -55,7 +59,7 @@ mark_free(struct i915_vma *vma, unsigned
 	if (WARN_ON(!list_empty(&vma->exec_list)))
 		return false;
 
-	if (flags & PIN_NONFAULT && vma->obj->fault_mappable)
+	if (flags & PIN_NONFAULT && !list_empty(&vma->obj->userfault_link))
 		return false;
 
 	list_add(&vma->exec_list, unwind);
@@ -102,6 +106,7 @@ i915_gem_evict_something(struct i915_add
 	struct i915_vma *vma, *next;
 	int ret;
 
+	lockdep_assert_held(&vm->dev->struct_mutex);
 	trace_i915_gem_evict(vm, min_size, alignment, flags);
 
 	/*
@@ -152,7 +157,7 @@ search_again:
 	if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK)
 		return -ENOSPC;
 
-	if (gpu_is_idle(dev_priv)) {
+	if (ggtt_is_idle(dev_priv)) {
 		/* If we still have pending pageflip completions, drop
 		 * back to userspace to give our workqueues time to
 		 * acquire our locks and unpin the old scanouts.
@@ -194,6 +199,7 @@ found:
 	}
 
 	/* Unbinding will emit any required flushes */
+	ret = 0;
 	while (!list_empty(&eviction_list)) {
 		vma = list_first_entry(&eviction_list,
 				       struct i915_vma,
@@ -212,6 +218,8 @@ i915_gem_evict_for_vma(struct i915_vma *
 {
 	struct drm_mm_node *node, *next;
 
+	lockdep_assert_held(&target->vm->dev->struct_mutex);
+
 	list_for_each_entry_safe(node, next,
 			&target->vm->mm.head_node.node_list,
 			node_list) {
@@ -265,7 +273,7 @@ int i915_gem_evict_vm(struct i915_addres
 	struct i915_vma *vma, *next;
 	int ret;
 
-	WARN_ON(!mutex_is_locked(&vm->dev->struct_mutex));
+	lockdep_assert_held(&vm->dev->struct_mutex);
 	trace_i915_gem_evict_vm(vm);
 
 	if (do_idle) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,6 @@
 #include <drm/i915_drm.h>
 
 #include "i915_drv.h"
-#include "i915_gem_dmabuf.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
 #include "intel_frontbuffer.h"
@@ -288,7 +287,7 @@ static inline int use_cpu_reloc(struct d
 	if (DBG_USE_CPU_RELOC)
 		return DBG_USE_CPU_RELOC > 0;
 
-	return (HAS_LLC(obj->base.dev) ||
+	return (HAS_LLC(to_i915(obj->base.dev)) ||
 		obj->base.write_domain == I915_GEM_DOMAIN_CPU ||
 		obj->cache_level != I915_CACHE_NONE);
 }
@@ -332,7 +331,8 @@ static void reloc_cache_init(struct relo
 	cache->page = -1;
 	cache->vaddr = 0;
 	cache->i915 = i915;
-	cache->use_64bit_reloc = INTEL_GEN(cache->i915) >= 8;
+	/* Must be a variable in the struct to allow GCC to unroll. */
+	cache->use_64bit_reloc = HAS_64BIT_RELOC(i915);
 	cache->node.allocated = false;
 }
 
@@ -370,8 +370,7 @@ static void reloc_cache_fini(struct relo
 
 			ggtt->base.clear_range(&ggtt->base,
 					       cache->node.start,
-					       cache->node.size,
-					       true);
+					       cache->node.size);
 			drm_mm_remove_node(&cache->node);
 		} else {
 			i915_vma_unpin((struct i915_vma *)cache->node.mm);
@@ -419,17 +418,8 @@ static void *reloc_iomap(struct drm_i915
 	unsigned long offset;
 	void *vaddr;
 
-	if (cache->node.allocated) {
-		wmb();
-		ggtt->base.insert_page(&ggtt->base,
-				       i915_gem_object_get_dma_address(obj, page),
-				       cache->node.start, I915_CACHE_NONE, 0);
-		cache->page = page;
-		return unmask_page(cache->vaddr);
-	}
-
 	if (cache->vaddr) {
-		io_mapping_unmap_atomic(unmask_page(cache->vaddr));
+		io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr));
 	} else {
 		struct i915_vma *vma;
 		int ret;
@@ -467,6 +457,7 @@ static void *reloc_iomap(struct drm_i915
 
 	offset = cache->node.start;
 	if (cache->node.allocated) {
+		wmb();
 		ggtt->base.insert_page(&ggtt->base,
 				       i915_gem_object_get_dma_address(obj, page),
 				       offset, I915_CACHE_NONE, 0);
@@ -474,7 +465,7 @@ static void *reloc_iomap(struct drm_i915
 		offset += page << PAGE_SHIFT;
 	}
 
-	vaddr = io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset);
+	vaddr = (void __force *) io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset);
 	cache->page = page;
 	cache->vaddr = (unsigned long)vaddr;
 
@@ -552,27 +543,13 @@ repeat:
 	return 0;
 }
 
-static bool object_is_idle(struct drm_i915_gem_object *obj)
-{
-	unsigned long active = i915_gem_object_get_active(obj);
-	int idx;
-
-	for_each_active(active, idx) {
-		if (!i915_gem_active_is_idle(&obj->last_read[idx],
-					     &obj->base.dev->struct_mutex))
-			return false;
-	}
-
-	return true;
-}
-
 static int
 i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 				   struct eb_vmas *eb,
 				   struct drm_i915_gem_relocation_entry *reloc,
 				   struct reloc_cache *cache)
 {
-	struct drm_device *dev = obj->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 	struct drm_gem_object *target_obj;
 	struct drm_i915_gem_object *target_i915_obj;
 	struct i915_vma *target_vma;
@@ -591,7 +568,7 @@ i915_gem_execbuffer_relocate_entry(struc
 	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
 	 * pipe_control writes because the gpu doesn't properly redirect them
 	 * through the ppgtt for non_secure batchbuffers. */
-	if (unlikely(IS_GEN6(dev) &&
+	if (unlikely(IS_GEN6(dev_priv) &&
 	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION)) {
 		ret = i915_vma_bind(target_vma, target_i915_obj->cache_level,
 				    PIN_GLOBAL);
@@ -649,10 +626,6 @@ i915_gem_execbuffer_relocate_entry(struc
 		return -EINVAL;
 	}
 
-	/* We can't wait for rendering with pagefaults disabled */
-	if (pagefault_disabled() && !object_is_idle(obj))
-		return -EFAULT;
-
 	ret = relocate_entry(obj, reloc, cache, target_offset);
 	if (ret)
 		return ret;
@@ -679,12 +652,23 @@ i915_gem_execbuffer_relocate_vma(struct
 	remain = entry->relocation_count;
 	while (remain) {
 		struct drm_i915_gem_relocation_entry *r = stack_reloc;
-		int count = remain;
-		if (count > ARRAY_SIZE(stack_reloc))
-			count = ARRAY_SIZE(stack_reloc);
+		unsigned long unwritten;
+		unsigned int count;
+
+		count = min_t(unsigned int, remain, ARRAY_SIZE(stack_reloc));
 		remain -= count;
 
-		if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0]))) {
+		/* This is the fast path and we cannot handle a pagefault
+		 * whilst holding the struct mutex lest the user pass in the
+		 * relocations contained within a mmaped bo. For in such a case
+		 * we, the page fault handler would call i915_gem_fault() and
+		 * we would try to acquire the struct mutex again. Obviously
+		 * this is bad and so lockdep complains vehemently.
+		 */
+		pagefault_disable();
+		unwritten = __copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0]));
+		pagefault_enable();
+		if (unlikely(unwritten)) {
 			ret = -EFAULT;
 			goto out;
 		}
@@ -696,11 +680,26 @@ i915_gem_execbuffer_relocate_vma(struct
 			if (ret)
 				goto out;
 
-			if (r->presumed_offset != offset &&
-			    __put_user(r->presumed_offset,
-				       &user_relocs->presumed_offset)) {
-				ret = -EFAULT;
-				goto out;
+			if (r->presumed_offset != offset) {
+				pagefault_disable();
+				unwritten = __put_user(r->presumed_offset,
+						       &user_relocs->presumed_offset);
+				pagefault_enable();
+				if (unlikely(unwritten)) {
+					/* Note that reporting an error now
+					 * leaves everything in an inconsistent
+					 * state as we have *already* changed
+					 * the relocation value inside the
+					 * object. As we have not changed the
+					 * reloc.presumed_offset or will not
+					 * change the execobject.offset, on the
+					 * call we may not rewrite the value
+					 * inside the object, leaving it
+					 * dangling and causing a GPU hang.
+					 */
+					ret = -EFAULT;
+					goto out;
+				}
 			}
 
 			user_relocs++;
@@ -740,20 +739,11 @@ i915_gem_execbuffer_relocate(struct eb_v
 	struct i915_vma *vma;
 	int ret = 0;
 
-	/* This is the fast path and we cannot handle a pagefault whilst
-	 * holding the struct mutex lest the user pass in the relocations
-	 * contained within a mmaped bo. For in such a case we, the page
-	 * fault handler would call i915_gem_fault() and we would try to
-	 * acquire the struct mutex again. Obviously this is bad and so
-	 * lockdep complains vehemently.
-	 */
-	pagefault_disable();
 	list_for_each_entry(vma, &eb->vmas, exec_list) {
 		ret = i915_gem_execbuffer_relocate_vma(vma, eb);
 		if (ret)
 			break;
 	}
-	pagefault_enable();
 
 	return ret;
 }
@@ -843,7 +833,7 @@ need_reloc_mappable(struct i915_vma *vma
 		return false;
 
 	/* See also use_cpu_reloc() */
-	if (HAS_LLC(vma->obj->base.dev))
+	if (HAS_LLC(to_i915(vma->obj->base.dev)))
 		return false;
 
 	if (vma->obj->base.write_domain == I915_GEM_DOMAIN_CPU)
@@ -1111,44 +1101,20 @@ err:
 	return ret;
 }
 
-static unsigned int eb_other_engines(struct drm_i915_gem_request *req)
-{
-	unsigned int mask;
-
-	mask = ~intel_engine_flag(req->engine) & I915_BO_ACTIVE_MASK;
-	mask <<= I915_BO_ACTIVE_SHIFT;
-
-	return mask;
-}
-
 static int
 i915_gem_execbuffer_move_to_gpu(struct drm_i915_gem_request *req,
 				struct list_head *vmas)
 {
-	const unsigned int other_rings = eb_other_engines(req);
 	struct i915_vma *vma;
 	int ret;
 
 	list_for_each_entry(vma, vmas, exec_list) {
 		struct drm_i915_gem_object *obj = vma->obj;
-		struct reservation_object *resv;
 
-		if (obj->flags & other_rings) {
-			ret = i915_gem_request_await_object
-				(req, obj, obj->base.pending_write_domain);
-			if (ret)
-				return ret;
-		}
-
-		resv = i915_gem_object_get_dmabuf_resv(obj);
-		if (resv) {
-			ret = i915_sw_fence_await_reservation
-				(&req->submit, resv, &i915_fence_ops,
-				 obj->base.pending_write_domain, 10*HZ,
-				 GFP_KERNEL | __GFP_NOWARN);
-			if (ret < 0)
-				return ret;
-		}
+		ret = i915_gem_request_await_object
+			(req, obj, obj->base.pending_write_domain);
+		if (ret)
+			return ret;
 
 		if (obj->base.write_domain & I915_GEM_DOMAIN_CPU)
 			i915_gem_clflush_object(obj, false);
@@ -1215,14 +1181,14 @@ validate_exec_list(struct drm_device *de
 			if (exec[i].offset !=
 			    gen8_canonical_addr(exec[i].offset & PAGE_MASK))
 				return -EINVAL;
-
-			/* From drm_mm perspective address space is continuous,
-			 * so from this point we're always using non-canonical
-			 * form internally.
-			 */
-			exec[i].offset = gen8_noncanonical_addr(exec[i].offset);
 		}
 
+		/* From drm_mm perspective address space is continuous,
+		 * so from this point we're always using non-canonical
+		 * form internally.
+		 */
+		exec[i].offset = gen8_noncanonical_addr(exec[i].offset);
+
 		if (exec[i].alignment && !is_power_of_2(exec[i].alignment))
 			return -EINVAL;
 
@@ -1296,8 +1262,6 @@ void i915_vma_move_to_active(struct i915
 
 	GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
 
-	obj->dirty = 1; /* be paranoid  */
-
 	/* Add a reference if we're newly entering the active list.
 	 * The order in which we add operations to the retirement queue is
 	 * vital here: mark_active adds to the start of the callback list,
@@ -1305,15 +1269,15 @@ void i915_vma_move_to_active(struct i915
 	 * add the active reference first and queue for it to be dropped
 	 * *last*.
 	 */
-	if (!i915_gem_object_is_active(obj))
-		i915_gem_object_get(obj);
-	i915_gem_object_set_active(obj, idx);
-	i915_gem_active_set(&obj->last_read[idx], req);
+	if (!i915_vma_is_active(vma))
+		obj->active_count++;
+	i915_vma_set_active(vma, idx);
+	i915_gem_active_set(&vma->last_read[idx], req);
+	list_move_tail(&vma->vm_link, &vma->vm->active_list);
 
 	if (flags & EXEC_OBJECT_WRITE) {
-		i915_gem_active_set(&obj->last_write, req);
-
-		intel_fb_obj_invalidate(obj, ORIGIN_CS);
+		if (intel_fb_obj_invalidate(obj, ORIGIN_CS))
+			i915_gem_active_set(&obj->frontbuffer_write, req);
 
 		/* update for the implicit flush after a batch */
 		obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
@@ -1323,21 +1287,13 @@ void i915_vma_move_to_active(struct i915
 
 	if (flags & EXEC_OBJECT_NEEDS_FENCE)
 		i915_gem_active_set(&vma->last_fence, req);
-
-	i915_vma_set_active(vma, idx);
-	i915_gem_active_set(&vma->last_read[idx], req);
-	list_move_tail(&vma->vm_link, &vma->vm->active_list);
 }
 
 static void eb_export_fence(struct drm_i915_gem_object *obj,
 			    struct drm_i915_gem_request *req,
 			    unsigned int flags)
 {
-	struct reservation_object *resv;
-
-	resv = i915_gem_object_get_dmabuf_resv(obj);
-	if (!resv)
-		return;
+	struct reservation_object *resv = obj->resv;
 
 	/* Ignore errors from failing to allocate the new fence, we can't
 	 * handle an error right now. Worst case should be missed
@@ -1607,12 +1563,12 @@ eb_select_engine(struct drm_i915_private
 			return NULL;
 		}
 
-		engine = &dev_priv->engine[_VCS(bsd_idx)];
+		engine = dev_priv->engine[_VCS(bsd_idx)];
 	} else {
-		engine = &dev_priv->engine[user_ring_map[user_ring_id]];
+		engine = dev_priv->engine[user_ring_map[user_ring_id]];
 	}
 
-	if (!intel_engine_initialized(engine)) {
+	if (!engine) {
 		DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id);
 		return NULL;
 	}
@@ -1667,7 +1623,7 @@ i915_gem_do_execbuffer(struct drm_device
 	}
 
 	if (args->flags & I915_EXEC_RESOURCE_STREAMER) {
-		if (!HAS_RESOURCE_STREAMER(dev)) {
+		if (!HAS_RESOURCE_STREAMER(dev_priv)) {
 			DRM_DEBUG("RS is only allowed for Haswell, Gen8 and above\n");
 			return -EINVAL;
 		}
@@ -1921,7 +1877,7 @@ i915_gem_execbuffer(struct drm_device *d
 		exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr;
 		exec2_list[i].alignment = exec_list[i].alignment;
 		exec2_list[i].offset = exec_list[i].offset;
-		if (INTEL_INFO(dev)->gen < 4)
+		if (INTEL_GEN(to_i915(dev)) < 4)
 			exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE;
 		else
 			exec2_list[i].flags = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_fence.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,714 +0,0 @@
-/*
- * Copyright © 2008-2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <drm/drmP.h>
-#include <drm/i915_drm.h>
-#include "i915_drv.h"
-
-/**
- * DOC: fence register handling
- *
- * Important to avoid confusions: "fences" in the i915 driver are not execution
- * fences used to track command completion but hardware detiler objects which
- * wrap a given range of the global GTT. Each platform has only a fairly limited
- * set of these objects.
- *
- * Fences are used to detile GTT memory mappings. They're also connected to the
- * hardware frontbuffer render tracking and hence interact with frontbuffer
- * compression. Furthermore on older platforms fences are required for tiled
- * objects used by the display engine. They can also be used by the render
- * engine - they're required for blitter commands and are optional for render
- * commands. But on gen4+ both display (with the exception of fbc) and rendering
- * have their own tiling state bits and don't need fences.
- *
- * Also note that fences only support X and Y tiling and hence can't be used for
- * the fancier new tiling formats like W, Ys and Yf.
- *
- * Finally note that because fences are such a restricted resource they're
- * dynamically associated with objects. Furthermore fence state is committed to
- * the hardware lazily to avoid unnecessary stalls on gen2/3. Therefore code must
- * explicitly call i915_gem_object_get_fence() to synchronize fencing status
- * for cpu access. Also note that some code wants an unfenced view, for those
- * cases the fence can be removed forcefully with i915_gem_object_put_fence().
- *
- * Internally these functions will synchronize with userspace access by removing
- * CPU ptes into GTT mmaps (not the GTT ptes themselves) as needed.
- */
-
-#define pipelined 0
-
-static void i965_write_fence_reg(struct drm_i915_fence_reg *fence,
-				 struct i915_vma *vma)
-{
-	i915_reg_t fence_reg_lo, fence_reg_hi;
-	int fence_pitch_shift;
-	u64 val;
-
-	if (INTEL_INFO(fence->i915)->gen >= 6) {
-		fence_reg_lo = FENCE_REG_GEN6_LO(fence->id);
-		fence_reg_hi = FENCE_REG_GEN6_HI(fence->id);
-		fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT;
-
-	} else {
-		fence_reg_lo = FENCE_REG_965_LO(fence->id);
-		fence_reg_hi = FENCE_REG_965_HI(fence->id);
-		fence_pitch_shift = I965_FENCE_PITCH_SHIFT;
-	}
-
-	val = 0;
-	if (vma) {
-		unsigned int tiling = i915_gem_object_get_tiling(vma->obj);
-		bool is_y_tiled = tiling == I915_TILING_Y;
-		unsigned int stride = i915_gem_object_get_stride(vma->obj);
-		u32 row_size = stride * (is_y_tiled ? 32 : 8);
-		u32 size = rounddown((u32)vma->node.size, row_size);
-
-		val = ((vma->node.start + size - 4096) & 0xfffff000) << 32;
-		val |= vma->node.start & 0xfffff000;
-		val |= (u64)((stride / 128) - 1) << fence_pitch_shift;
-		if (is_y_tiled)
-			val |= BIT(I965_FENCE_TILING_Y_SHIFT);
-		val |= I965_FENCE_REG_VALID;
-	}
-
-	if (!pipelined) {
-		struct drm_i915_private *dev_priv = fence->i915;
-
-		/* To w/a incoherency with non-atomic 64-bit register updates,
-		 * we split the 64-bit update into two 32-bit writes. In order
-		 * for a partial fence not to be evaluated between writes, we
-		 * precede the update with write to turn off the fence register,
-		 * and only enable the fence as the last step.
-		 *
-		 * For extra levels of paranoia, we make sure each step lands
-		 * before applying the next step.
-		 */
-		I915_WRITE(fence_reg_lo, 0);
-		POSTING_READ(fence_reg_lo);
-
-		I915_WRITE(fence_reg_hi, upper_32_bits(val));
-		I915_WRITE(fence_reg_lo, lower_32_bits(val));
-		POSTING_READ(fence_reg_lo);
-	}
-}
-
-static void i915_write_fence_reg(struct drm_i915_fence_reg *fence,
-				 struct i915_vma *vma)
-{
-	u32 val;
-
-	val = 0;
-	if (vma) {
-		unsigned int tiling = i915_gem_object_get_tiling(vma->obj);
-		bool is_y_tiled = tiling == I915_TILING_Y;
-		unsigned int stride = i915_gem_object_get_stride(vma->obj);
-		int pitch_val;
-		int tile_width;
-
-		WARN((vma->node.start & ~I915_FENCE_START_MASK) ||
-		     !is_power_of_2(vma->node.size) ||
-		     (vma->node.start & (vma->node.size - 1)),
-		     "object 0x%08llx [fenceable? %d] not 1M or pot-size (0x%08llx) aligned\n",
-		     vma->node.start,
-		     i915_vma_is_map_and_fenceable(vma),
-		     vma->node.size);
-
-		if (is_y_tiled && HAS_128_BYTE_Y_TILING(fence->i915))
-			tile_width = 128;
-		else
-			tile_width = 512;
-
-		/* Note: pitch better be a power of two tile widths */
-		pitch_val = stride / tile_width;
-		pitch_val = ffs(pitch_val) - 1;
-
-		val = vma->node.start;
-		if (is_y_tiled)
-			val |= BIT(I830_FENCE_TILING_Y_SHIFT);
-		val |= I915_FENCE_SIZE_BITS(vma->node.size);
-		val |= pitch_val << I830_FENCE_PITCH_SHIFT;
-		val |= I830_FENCE_REG_VALID;
-	}
-
-	if (!pipelined) {
-		struct drm_i915_private *dev_priv = fence->i915;
-		i915_reg_t reg = FENCE_REG(fence->id);
-
-		I915_WRITE(reg, val);
-		POSTING_READ(reg);
-	}
-}
-
-static void i830_write_fence_reg(struct drm_i915_fence_reg *fence,
-				 struct i915_vma *vma)
-{
-	u32 val;
-
-	val = 0;
-	if (vma) {
-		unsigned int tiling = i915_gem_object_get_tiling(vma->obj);
-		bool is_y_tiled = tiling == I915_TILING_Y;
-		unsigned int stride = i915_gem_object_get_stride(vma->obj);
-		u32 pitch_val;
-
-		WARN((vma->node.start & ~I830_FENCE_START_MASK) ||
-		     !is_power_of_2(vma->node.size) ||
-		     (vma->node.start & (vma->node.size - 1)),
-		     "object 0x%08llx not 512K or pot-size 0x%08llx aligned\n",
-		     vma->node.start, vma->node.size);
-
-		pitch_val = stride / 128;
-		pitch_val = ffs(pitch_val) - 1;
-
-		val = vma->node.start;
-		if (is_y_tiled)
-			val |= BIT(I830_FENCE_TILING_Y_SHIFT);
-		val |= I830_FENCE_SIZE_BITS(vma->node.size);
-		val |= pitch_val << I830_FENCE_PITCH_SHIFT;
-		val |= I830_FENCE_REG_VALID;
-	}
-
-	if (!pipelined) {
-		struct drm_i915_private *dev_priv = fence->i915;
-		i915_reg_t reg = FENCE_REG(fence->id);
-
-		I915_WRITE(reg, val);
-		POSTING_READ(reg);
-	}
-}
-
-static void fence_write(struct drm_i915_fence_reg *fence,
-			struct i915_vma *vma)
-{
-	/* Previous access through the fence register is marshalled by
-	 * the mb() inside the fault handlers (i915_gem_release_mmaps)
-	 * and explicitly managed for internal users.
-	 */
-
-	if (IS_GEN2(fence->i915))
-		i830_write_fence_reg(fence, vma);
-	else if (IS_GEN3(fence->i915))
-		i915_write_fence_reg(fence, vma);
-	else
-		i965_write_fence_reg(fence, vma);
-
-	/* Access through the fenced region afterwards is
-	 * ordered by the posting reads whilst writing the registers.
-	 */
-
-	fence->dirty = false;
-}
-
-static int fence_update(struct drm_i915_fence_reg *fence,
-			struct i915_vma *vma)
-{
-	int ret;
-
-	if (vma) {
-		if (!i915_vma_is_map_and_fenceable(vma))
-			return -EINVAL;
-
-		if (WARN(!i915_gem_object_get_stride(vma->obj) ||
-			 !i915_gem_object_get_tiling(vma->obj),
-			 "bogus fence setup with stride: 0x%x, tiling mode: %i\n",
-			 i915_gem_object_get_stride(vma->obj),
-			 i915_gem_object_get_tiling(vma->obj)))
-			return -EINVAL;
-
-		ret = i915_gem_active_retire(&vma->last_fence,
-					     &vma->obj->base.dev->struct_mutex);
-		if (ret)
-			return ret;
-	}
-
-	if (fence->vma) {
-		ret = i915_gem_active_retire(&fence->vma->last_fence,
-				      &fence->vma->obj->base.dev->struct_mutex);
-		if (ret)
-			return ret;
-	}
-
-	if (fence->vma && fence->vma != vma) {
-		/* Ensure that all userspace CPU access is completed before
-		 * stealing the fence.
-		 */
-		i915_gem_release_mmap(fence->vma->obj);
-
-		fence->vma->fence = NULL;
-		fence->vma = NULL;
-
-		list_move(&fence->link, &fence->i915->mm.fence_list);
-	}
-
-	fence_write(fence, vma);
-
-	if (vma) {
-		if (fence->vma != vma) {
-			vma->fence = fence;
-			fence->vma = vma;
-		}
-
-		list_move_tail(&fence->link, &fence->i915->mm.fence_list);
-	}
-
-	return 0;
-}
-
-/**
- * i915_vma_put_fence - force-remove fence for a VMA
- * @vma: vma to map linearly (not through a fence reg)
- *
- * This function force-removes any fence from the given object, which is useful
- * if the kernel wants to do untiled GTT access.
- *
- * Returns:
- *
- * 0 on success, negative error code on failure.
- */
-int
-i915_vma_put_fence(struct i915_vma *vma)
-{
-	struct drm_i915_fence_reg *fence = vma->fence;
-
-	assert_rpm_wakelock_held(to_i915(vma->vm->dev));
-
-	if (!fence)
-		return 0;
-
-	if (fence->pin_count)
-		return -EBUSY;
-
-	return fence_update(fence, NULL);
-}
-
-static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *dev_priv)
-{
-	struct drm_i915_fence_reg *fence;
-
-	list_for_each_entry(fence, &dev_priv->mm.fence_list, link) {
-		if (fence->pin_count)
-			continue;
-
-		return fence;
-	}
-
-	/* Wait for completion of pending flips which consume fences */
-	if (intel_has_pending_fb_unpin(&dev_priv->drm))
-		return ERR_PTR(-EAGAIN);
-
-	return ERR_PTR(-EDEADLK);
-}
-
-/**
- * i915_vma_get_fence - set up fencing for a vma
- * @vma: vma to map through a fence reg
- *
- * When mapping objects through the GTT, userspace wants to be able to write
- * to them without having to worry about swizzling if the object is tiled.
- * This function walks the fence regs looking for a free one for @obj,
- * stealing one if it can't find any.
- *
- * It then sets up the reg based on the object's properties: address, pitch
- * and tiling format.
- *
- * For an untiled surface, this removes any existing fence.
- *
- * Returns:
- *
- * 0 on success, negative error code on failure.
- */
-int
-i915_vma_get_fence(struct i915_vma *vma)
-{
-	struct drm_i915_fence_reg *fence;
-	struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL;
-
-	assert_rpm_wakelock_held(to_i915(vma->vm->dev));
-
-	/* Just update our place in the LRU if our fence is getting reused. */
-	if (vma->fence) {
-		fence = vma->fence;
-		if (!fence->dirty) {
-			list_move_tail(&fence->link,
-				       &fence->i915->mm.fence_list);
-			return 0;
-		}
-	} else if (set) {
-		fence = fence_find(to_i915(vma->vm->dev));
-		if (IS_ERR(fence))
-			return PTR_ERR(fence);
-	} else
-		return 0;
-
-	return fence_update(fence, set);
-}
-
-/**
- * i915_gem_restore_fences - restore fence state
- * @dev: DRM device
- *
- * Restore the hw fence state to match the software tracking again, to be called
- * after a gpu reset and on resume.
- */
-void i915_gem_restore_fences(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	int i;
-
-	/* Note that this may be called outside of struct_mutex, by
-	 * runtime suspend/resume. The barrier we require is enforced by
-	 * rpm itself - all access to fences/GTT are only within an rpm
-	 * wakeref, and to acquire that wakeref you must pass through here.
-	 */
-
-	for (i = 0; i < dev_priv->num_fence_regs; i++) {
-		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
-		struct i915_vma *vma = reg->vma;
-
-		/*
-		 * Commit delayed tiling changes if we have an object still
-		 * attached to the fence, otherwise just clear the fence.
-		 */
-		if (vma && !i915_gem_object_is_tiled(vma->obj)) {
-			GEM_BUG_ON(!reg->dirty);
-			GEM_BUG_ON(vma->obj->fault_mappable);
-
-			list_move(&reg->link, &dev_priv->mm.fence_list);
-			vma->fence = NULL;
-			vma = NULL;
-		}
-
-		fence_write(reg, vma);
-		reg->vma = vma;
-	}
-}
-
-/**
- * DOC: tiling swizzling details
- *
- * The idea behind tiling is to increase cache hit rates by rearranging
- * pixel data so that a group of pixel accesses are in the same cacheline.
- * Performance improvement from doing this on the back/depth buffer are on
- * the order of 30%.
- *
- * Intel architectures make this somewhat more complicated, though, by
- * adjustments made to addressing of data when the memory is in interleaved
- * mode (matched pairs of DIMMS) to improve memory bandwidth.
- * For interleaved memory, the CPU sends every sequential 64 bytes
- * to an alternate memory channel so it can get the bandwidth from both.
- *
- * The GPU also rearranges its accesses for increased bandwidth to interleaved
- * memory, and it matches what the CPU does for non-tiled.  However, when tiled
- * it does it a little differently, since one walks addresses not just in the
- * X direction but also Y.  So, along with alternating channels when bit
- * 6 of the address flips, it also alternates when other bits flip --  Bits 9
- * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
- * are common to both the 915 and 965-class hardware.
- *
- * The CPU also sometimes XORs in higher bits as well, to improve
- * bandwidth doing strided access like we do so frequently in graphics.  This
- * is called "Channel XOR Randomization" in the MCH documentation.  The result
- * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
- * decode.
- *
- * All of this bit 6 XORing has an effect on our memory management,
- * as we need to make sure that the 3d driver can correctly address object
- * contents.
- *
- * If we don't have interleaved memory, all tiling is safe and no swizzling is
- * required.
- *
- * When bit 17 is XORed in, we simply refuse to tile at all.  Bit
- * 17 is not just a page offset, so as we page an object out and back in,
- * individual pages in it will have different bit 17 addresses, resulting in
- * each 64 bytes being swapped with its neighbor!
- *
- * Otherwise, if interleaved, we have to tell the 3d driver what the address
- * swizzling it needs to do is, since it's writing with the CPU to the pages
- * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
- * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
- * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
- * to match what the GPU expects.
- */
-
-/**
- * i915_gem_detect_bit_6_swizzle - detect bit 6 swizzling pattern
- * @dev: DRM device
- *
- * Detects bit 6 swizzling of address lookup between IGD access and CPU
- * access through main memory.
- */
-void
-i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-
-	if (INTEL_INFO(dev)->gen >= 8 || IS_VALLEYVIEW(dev)) {
-		/*
-		 * On BDW+, swizzling is not used. We leave the CPU memory
-		 * controller in charge of optimizing memory accesses without
-		 * the extra address manipulation GPU side.
-		 *
-		 * VLV and CHV don't have GPU swizzling.
-		 */
-		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-	} else if (INTEL_INFO(dev)->gen >= 6) {
-		if (dev_priv->preserve_bios_swizzle) {
-			if (I915_READ(DISP_ARB_CTL) &
-			    DISP_TILE_SURFACE_SWIZZLING) {
-				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-				swizzle_y = I915_BIT_6_SWIZZLE_9;
-			} else {
-				swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-				swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-			}
-		} else {
-			uint32_t dimm_c0, dimm_c1;
-			dimm_c0 = I915_READ(MAD_DIMM_C0);
-			dimm_c1 = I915_READ(MAD_DIMM_C1);
-			dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
-			dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
-			/* Enable swizzling when the channels are populated
-			 * with identically sized dimms. We don't need to check
-			 * the 3rd channel because no cpu with gpu attached
-			 * ships in that configuration. Also, swizzling only
-			 * makes sense for 2 channels anyway. */
-			if (dimm_c0 == dimm_c1) {
-				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-				swizzle_y = I915_BIT_6_SWIZZLE_9;
-			} else {
-				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.
-		 */
-		swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-		swizzle_y = I915_BIT_6_SWIZZLE_9;
-	} else if (IS_GEN2(dev)) {
-		/* As far as we know, the 865 doesn't have these bit 6
-		 * swizzling issues.
-		 */
-		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-	} else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) {
-		uint32_t dcc;
-
-		/* On 9xx chipsets, channel interleave by the CPU is
-		 * determined by DCC.  For single-channel, neither the CPU
-		 * nor the GPU do swizzling.  For dual channel interleaved,
-		 * the GPU's interleave is bit 9 and 10 for X tiled, and bit
-		 * 9 for Y tiled.  The CPU's interleave is independent, and
-		 * can be based on either bit 11 (haven't seen this yet) or
-		 * bit 17 (common).
-		 */
-		dcc = I915_READ(DCC);
-		switch (dcc & DCC_ADDRESSING_MODE_MASK) {
-		case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
-		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
-			swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-			swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-			break;
-		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
-			if (dcc & DCC_CHANNEL_XOR_DISABLE) {
-				/* This is the base swizzling by the GPU for
-				 * tiled buffers.
-				 */
-				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-				swizzle_y = I915_BIT_6_SWIZZLE_9;
-			} else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
-				/* Bit 11 swizzling by the CPU in addition. */
-				swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
-				swizzle_y = I915_BIT_6_SWIZZLE_9_11;
-			} else {
-				/* Bit 17 swizzling by the CPU in addition. */
-				swizzle_x = I915_BIT_6_SWIZZLE_9_10_17;
-				swizzle_y = I915_BIT_6_SWIZZLE_9_17;
-			}
-			break;
-		}
-
-		/* check for L-shaped memory aka modified enhanced addressing */
-		if (IS_GEN4(dev) &&
-		    !(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) {
-			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-		}
-
-		if (dcc == 0xffffffff) {
-			DRM_ERROR("Couldn't read from MCHBAR.  "
-				  "Disabling tiling.\n");
-			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
-			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
-		}
-	} else {
-		/* The 965, G33, and newer, have a very flexible memory
-		 * configuration.  It will enable dual-channel mode
-		 * (interleaving) on as much memory as it can, and the GPU
-		 * will additionally sometimes enable different bit 6
-		 * swizzling for tiled objects from the CPU.
-		 *
-		 * Here's what I found on the G965:
-		 *    slot fill         memory size  swizzling
-		 * 0A   0B   1A   1B    1-ch   2-ch
-		 * 512  0    0    0     512    0     O
-		 * 512  0    512  0     16     1008  X
-		 * 512  0    0    512   16     1008  X
-		 * 0    512  0    512   16     1008  X
-		 * 1024 1024 1024 0     2048   1024  O
-		 *
-		 * We could probably detect this based on either the DRB
-		 * matching, which was the case for the swizzling required in
-		 * the table above, or from the 1-ch value being less than
-		 * the minimum size of a rank.
-		 *
-		 * Reports indicate that the swizzling actually
-		 * varies depending upon page placement inside the
-		 * channels, i.e. we see swizzled pages where the
-		 * banks of memory are paired and unswizzled on the
-		 * uneven portion, so leave that as unknown.
-		 */
-		if (I915_READ16(C0DRB3) == I915_READ16(C1DRB3)) {
-			swizzle_x = I915_BIT_6_SWIZZLE_9_10;
-			swizzle_y = I915_BIT_6_SWIZZLE_9;
-		}
-	}
-
-	if (swizzle_x == I915_BIT_6_SWIZZLE_UNKNOWN ||
-	    swizzle_y == I915_BIT_6_SWIZZLE_UNKNOWN) {
-		/* Userspace likes to explode if it sees unknown swizzling,
-		 * so lie. We will finish the lie when reporting through
-		 * the get-tiling-ioctl by reporting the physical swizzle
-		 * mode as unknown instead.
-		 *
-		 * As we don't strictly know what the swizzling is, it may be
-		 * bit17 dependent, and so we need to also prevent the pages
-		 * from being moved.
-		 */
-		dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
-		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
-		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-	}
-
-	dev_priv->mm.bit_6_swizzle_x = swizzle_x;
-	dev_priv->mm.bit_6_swizzle_y = swizzle_y;
-}
-
-/*
- * Swap every 64 bytes of this page around, to account for it having a new
- * bit 17 of its physical address and therefore being interpreted differently
- * by the GPU.
- */
-static void
-i915_gem_swizzle_page(struct page *page)
-{
-	char temp[64];
-	char *vaddr;
-	int i;
-
-	vaddr = kmap(page);
-
-	for (i = 0; i < PAGE_SIZE; i += 128) {
-		memcpy(temp, &vaddr[i], 64);
-		memcpy(&vaddr[i], &vaddr[i + 64], 64);
-		memcpy(&vaddr[i + 64], temp, 64);
-	}
-
-	kunmap(page);
-}
-
-/**
- * i915_gem_object_do_bit_17_swizzle - fixup bit 17 swizzling
- * @obj: i915 GEM buffer object
- *
- * This function fixes up the swizzling in case any page frame number for this
- * object has changed in bit 17 since that state has been saved with
- * i915_gem_object_save_bit_17_swizzle().
- *
- * This is called when pinning backing storage again, since the kernel is free
- * to move unpinned backing storage around (either by directly moving pages or
- * by swapping them out and back in again).
- */
-void
-i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj)
-{
-	struct sgt_iter sgt_iter;
-	struct page *page;
-	int i;
-
-	if (obj->bit_17 == NULL)
-		return;
-
-	i = 0;
-	for_each_sgt_page(page, sgt_iter, obj->pages) {
-		char new_bit_17 = page_to_phys(page) >> 17;
-		if ((new_bit_17 & 0x1) !=
-		    (test_bit(i, obj->bit_17) != 0)) {
-			i915_gem_swizzle_page(page);
-			set_page_dirty(page);
-		}
-		i++;
-	}
-}
-
-/**
- * i915_gem_object_save_bit_17_swizzle - save bit 17 swizzling
- * @obj: i915 GEM buffer object
- *
- * This function saves the bit 17 of each page frame number so that swizzling
- * can be fixed up later on with i915_gem_object_do_bit_17_swizzle(). This must
- * be called before the backing storage can be unpinned.
- */
-void
-i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj)
-{
-	struct sgt_iter sgt_iter;
-	struct page *page;
-	int page_count = obj->base.size >> PAGE_SHIFT;
-	int i;
-
-	if (obj->bit_17 == NULL) {
-		obj->bit_17 = kcalloc(BITS_TO_LONGS(page_count),
-				      sizeof(long), GFP_KERNEL);
-		if (obj->bit_17 == NULL) {
-			DRM_ERROR("Failed to allocate memory for bit 17 "
-				  "record\n");
-			return;
-		}
-	}
-
-	i = 0;
-
-	for_each_sgt_page(page, sgt_iter, obj->pages) {
-		if (page_to_phys(page) & (1 << 17))
-			__set_bit(i, obj->bit_17);
-		else
-			__clear_bit(i, obj->bit_17);
-		i++;
-	}
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,714 @@
+/*
+ * Copyright © 2008-2015 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <drm/drmP.h>
+#include <drm/i915_drm.h>
+#include "i915_drv.h"
+
+/**
+ * DOC: fence register handling
+ *
+ * Important to avoid confusions: "fences" in the i915 driver are not execution
+ * fences used to track command completion but hardware detiler objects which
+ * wrap a given range of the global GTT. Each platform has only a fairly limited
+ * set of these objects.
+ *
+ * Fences are used to detile GTT memory mappings. They're also connected to the
+ * hardware frontbuffer render tracking and hence interact with frontbuffer
+ * compression. Furthermore on older platforms fences are required for tiled
+ * objects used by the display engine. They can also be used by the render
+ * engine - they're required for blitter commands and are optional for render
+ * commands. But on gen4+ both display (with the exception of fbc) and rendering
+ * have their own tiling state bits and don't need fences.
+ *
+ * Also note that fences only support X and Y tiling and hence can't be used for
+ * the fancier new tiling formats like W, Ys and Yf.
+ *
+ * Finally note that because fences are such a restricted resource they're
+ * dynamically associated with objects. Furthermore fence state is committed to
+ * the hardware lazily to avoid unnecessary stalls on gen2/3. Therefore code must
+ * explicitly call i915_gem_object_get_fence() to synchronize fencing status
+ * for cpu access. Also note that some code wants an unfenced view, for those
+ * cases the fence can be removed forcefully with i915_gem_object_put_fence().
+ *
+ * Internally these functions will synchronize with userspace access by removing
+ * CPU ptes into GTT mmaps (not the GTT ptes themselves) as needed.
+ */
+
+#define pipelined 0
+
+static void i965_write_fence_reg(struct drm_i915_fence_reg *fence,
+				 struct i915_vma *vma)
+{
+	i915_reg_t fence_reg_lo, fence_reg_hi;
+	int fence_pitch_shift;
+	u64 val;
+
+	if (INTEL_INFO(fence->i915)->gen >= 6) {
+		fence_reg_lo = FENCE_REG_GEN6_LO(fence->id);
+		fence_reg_hi = FENCE_REG_GEN6_HI(fence->id);
+		fence_pitch_shift = GEN6_FENCE_PITCH_SHIFT;
+
+	} else {
+		fence_reg_lo = FENCE_REG_965_LO(fence->id);
+		fence_reg_hi = FENCE_REG_965_HI(fence->id);
+		fence_pitch_shift = I965_FENCE_PITCH_SHIFT;
+	}
+
+	val = 0;
+	if (vma) {
+		unsigned int tiling = i915_gem_object_get_tiling(vma->obj);
+		bool is_y_tiled = tiling == I915_TILING_Y;
+		unsigned int stride = i915_gem_object_get_stride(vma->obj);
+		u32 row_size = stride * (is_y_tiled ? 32 : 8);
+		u32 size = rounddown((u32)vma->node.size, row_size);
+
+		val = ((vma->node.start + size - 4096) & 0xfffff000) << 32;
+		val |= vma->node.start & 0xfffff000;
+		val |= (u64)((stride / 128) - 1) << fence_pitch_shift;
+		if (is_y_tiled)
+			val |= BIT(I965_FENCE_TILING_Y_SHIFT);
+		val |= I965_FENCE_REG_VALID;
+	}
+
+	if (!pipelined) {
+		struct drm_i915_private *dev_priv = fence->i915;
+
+		/* To w/a incoherency with non-atomic 64-bit register updates,
+		 * we split the 64-bit update into two 32-bit writes. In order
+		 * for a partial fence not to be evaluated between writes, we
+		 * precede the update with write to turn off the fence register,
+		 * and only enable the fence as the last step.
+		 *
+		 * For extra levels of paranoia, we make sure each step lands
+		 * before applying the next step.
+		 */
+		I915_WRITE(fence_reg_lo, 0);
+		POSTING_READ(fence_reg_lo);
+
+		I915_WRITE(fence_reg_hi, upper_32_bits(val));
+		I915_WRITE(fence_reg_lo, lower_32_bits(val));
+		POSTING_READ(fence_reg_lo);
+	}
+}
+
+static void i915_write_fence_reg(struct drm_i915_fence_reg *fence,
+				 struct i915_vma *vma)
+{
+	u32 val;
+
+	val = 0;
+	if (vma) {
+		unsigned int tiling = i915_gem_object_get_tiling(vma->obj);
+		bool is_y_tiled = tiling == I915_TILING_Y;
+		unsigned int stride = i915_gem_object_get_stride(vma->obj);
+		int pitch_val;
+		int tile_width;
+
+		WARN((vma->node.start & ~I915_FENCE_START_MASK) ||
+		     !is_power_of_2(vma->node.size) ||
+		     (vma->node.start & (vma->node.size - 1)),
+		     "object 0x%08llx [fenceable? %d] not 1M or pot-size (0x%08llx) aligned\n",
+		     vma->node.start,
+		     i915_vma_is_map_and_fenceable(vma),
+		     vma->node.size);
+
+		if (is_y_tiled && HAS_128_BYTE_Y_TILING(fence->i915))
+			tile_width = 128;
+		else
+			tile_width = 512;
+
+		/* Note: pitch better be a power of two tile widths */
+		pitch_val = stride / tile_width;
+		pitch_val = ffs(pitch_val) - 1;
+
+		val = vma->node.start;
+		if (is_y_tiled)
+			val |= BIT(I830_FENCE_TILING_Y_SHIFT);
+		val |= I915_FENCE_SIZE_BITS(vma->node.size);
+		val |= pitch_val << I830_FENCE_PITCH_SHIFT;
+		val |= I830_FENCE_REG_VALID;
+	}
+
+	if (!pipelined) {
+		struct drm_i915_private *dev_priv = fence->i915;
+		i915_reg_t reg = FENCE_REG(fence->id);
+
+		I915_WRITE(reg, val);
+		POSTING_READ(reg);
+	}
+}
+
+static void i830_write_fence_reg(struct drm_i915_fence_reg *fence,
+				 struct i915_vma *vma)
+{
+	u32 val;
+
+	val = 0;
+	if (vma) {
+		unsigned int tiling = i915_gem_object_get_tiling(vma->obj);
+		bool is_y_tiled = tiling == I915_TILING_Y;
+		unsigned int stride = i915_gem_object_get_stride(vma->obj);
+		u32 pitch_val;
+
+		WARN((vma->node.start & ~I830_FENCE_START_MASK) ||
+		     !is_power_of_2(vma->node.size) ||
+		     (vma->node.start & (vma->node.size - 1)),
+		     "object 0x%08llx not 512K or pot-size 0x%08llx aligned\n",
+		     vma->node.start, vma->node.size);
+
+		pitch_val = stride / 128;
+		pitch_val = ffs(pitch_val) - 1;
+
+		val = vma->node.start;
+		if (is_y_tiled)
+			val |= BIT(I830_FENCE_TILING_Y_SHIFT);
+		val |= I830_FENCE_SIZE_BITS(vma->node.size);
+		val |= pitch_val << I830_FENCE_PITCH_SHIFT;
+		val |= I830_FENCE_REG_VALID;
+	}
+
+	if (!pipelined) {
+		struct drm_i915_private *dev_priv = fence->i915;
+		i915_reg_t reg = FENCE_REG(fence->id);
+
+		I915_WRITE(reg, val);
+		POSTING_READ(reg);
+	}
+}
+
+static void fence_write(struct drm_i915_fence_reg *fence,
+			struct i915_vma *vma)
+{
+	/* Previous access through the fence register is marshalled by
+	 * the mb() inside the fault handlers (i915_gem_release_mmaps)
+	 * and explicitly managed for internal users.
+	 */
+
+	if (IS_GEN2(fence->i915))
+		i830_write_fence_reg(fence, vma);
+	else if (IS_GEN3(fence->i915))
+		i915_write_fence_reg(fence, vma);
+	else
+		i965_write_fence_reg(fence, vma);
+
+	/* Access through the fenced region afterwards is
+	 * ordered by the posting reads whilst writing the registers.
+	 */
+
+	fence->dirty = false;
+}
+
+static int fence_update(struct drm_i915_fence_reg *fence,
+			struct i915_vma *vma)
+{
+	int ret;
+
+	if (vma) {
+		if (!i915_vma_is_map_and_fenceable(vma))
+			return -EINVAL;
+
+		if (WARN(!i915_gem_object_get_stride(vma->obj) ||
+			 !i915_gem_object_get_tiling(vma->obj),
+			 "bogus fence setup with stride: 0x%x, tiling mode: %i\n",
+			 i915_gem_object_get_stride(vma->obj),
+			 i915_gem_object_get_tiling(vma->obj)))
+			return -EINVAL;
+
+		ret = i915_gem_active_retire(&vma->last_fence,
+					     &vma->obj->base.dev->struct_mutex);
+		if (ret)
+			return ret;
+	}
+
+	if (fence->vma) {
+		ret = i915_gem_active_retire(&fence->vma->last_fence,
+				      &fence->vma->obj->base.dev->struct_mutex);
+		if (ret)
+			return ret;
+	}
+
+	if (fence->vma && fence->vma != vma) {
+		/* Ensure that all userspace CPU access is completed before
+		 * stealing the fence.
+		 */
+		i915_gem_release_mmap(fence->vma->obj);
+
+		fence->vma->fence = NULL;
+		fence->vma = NULL;
+
+		list_move(&fence->link, &fence->i915->mm.fence_list);
+	}
+
+	fence_write(fence, vma);
+
+	if (vma) {
+		if (fence->vma != vma) {
+			vma->fence = fence;
+			fence->vma = vma;
+		}
+
+		list_move_tail(&fence->link, &fence->i915->mm.fence_list);
+	}
+
+	return 0;
+}
+
+/**
+ * i915_vma_put_fence - force-remove fence for a VMA
+ * @vma: vma to map linearly (not through a fence reg)
+ *
+ * This function force-removes any fence from the given object, which is useful
+ * if the kernel wants to do untiled GTT access.
+ *
+ * Returns:
+ *
+ * 0 on success, negative error code on failure.
+ */
+int
+i915_vma_put_fence(struct i915_vma *vma)
+{
+	struct drm_i915_fence_reg *fence = vma->fence;
+
+	assert_rpm_wakelock_held(to_i915(vma->vm->dev));
+
+	if (!fence)
+		return 0;
+
+	if (fence->pin_count)
+		return -EBUSY;
+
+	return fence_update(fence, NULL);
+}
+
+static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *dev_priv)
+{
+	struct drm_i915_fence_reg *fence;
+
+	list_for_each_entry(fence, &dev_priv->mm.fence_list, link) {
+		if (fence->pin_count)
+			continue;
+
+		return fence;
+	}
+
+	/* Wait for completion of pending flips which consume fences */
+	if (intel_has_pending_fb_unpin(&dev_priv->drm))
+		return ERR_PTR(-EAGAIN);
+
+	return ERR_PTR(-EDEADLK);
+}
+
+/**
+ * i915_vma_get_fence - set up fencing for a vma
+ * @vma: vma to map through a fence reg
+ *
+ * When mapping objects through the GTT, userspace wants to be able to write
+ * to them without having to worry about swizzling if the object is tiled.
+ * This function walks the fence regs looking for a free one for @obj,
+ * stealing one if it can't find any.
+ *
+ * It then sets up the reg based on the object's properties: address, pitch
+ * and tiling format.
+ *
+ * For an untiled surface, this removes any existing fence.
+ *
+ * Returns:
+ *
+ * 0 on success, negative error code on failure.
+ */
+int
+i915_vma_get_fence(struct i915_vma *vma)
+{
+	struct drm_i915_fence_reg *fence;
+	struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL;
+
+	/* Note that we revoke fences on runtime suspend. Therefore the user
+	 * must keep the device awake whilst using the fence.
+	 */
+	assert_rpm_wakelock_held(to_i915(vma->vm->dev));
+
+	/* Just update our place in the LRU if our fence is getting reused. */
+	if (vma->fence) {
+		fence = vma->fence;
+		if (!fence->dirty) {
+			list_move_tail(&fence->link,
+				       &fence->i915->mm.fence_list);
+			return 0;
+		}
+	} else if (set) {
+		fence = fence_find(to_i915(vma->vm->dev));
+		if (IS_ERR(fence))
+			return PTR_ERR(fence);
+	} else
+		return 0;
+
+	return fence_update(fence, set);
+}
+
+/**
+ * i915_gem_restore_fences - restore fence state
+ * @dev_priv: i915 device private
+ *
+ * Restore the hw fence state to match the software tracking again, to be called
+ * after a gpu reset and on resume. Note that on runtime suspend we only cancel
+ * the fences, to be reacquired by the user later.
+ */
+void i915_gem_restore_fences(struct drm_i915_private *dev_priv)
+{
+	int i;
+
+	for (i = 0; i < dev_priv->num_fence_regs; i++) {
+		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
+		struct i915_vma *vma = reg->vma;
+
+		/*
+		 * Commit delayed tiling changes if we have an object still
+		 * attached to the fence, otherwise just clear the fence.
+		 */
+		if (vma && !i915_gem_object_is_tiled(vma->obj)) {
+			GEM_BUG_ON(!reg->dirty);
+			GEM_BUG_ON(!list_empty(&vma->obj->userfault_link));
+
+			list_move(&reg->link, &dev_priv->mm.fence_list);
+			vma->fence = NULL;
+			vma = NULL;
+		}
+
+		fence_write(reg, vma);
+		reg->vma = vma;
+	}
+}
+
+/**
+ * DOC: tiling swizzling details
+ *
+ * The idea behind tiling is to increase cache hit rates by rearranging
+ * pixel data so that a group of pixel accesses are in the same cacheline.
+ * Performance improvement from doing this on the back/depth buffer are on
+ * the order of 30%.
+ *
+ * Intel architectures make this somewhat more complicated, though, by
+ * adjustments made to addressing of data when the memory is in interleaved
+ * mode (matched pairs of DIMMS) to improve memory bandwidth.
+ * For interleaved memory, the CPU sends every sequential 64 bytes
+ * to an alternate memory channel so it can get the bandwidth from both.
+ *
+ * The GPU also rearranges its accesses for increased bandwidth to interleaved
+ * memory, and it matches what the CPU does for non-tiled.  However, when tiled
+ * it does it a little differently, since one walks addresses not just in the
+ * X direction but also Y.  So, along with alternating channels when bit
+ * 6 of the address flips, it also alternates when other bits flip --  Bits 9
+ * (every 512 bytes, an X tile scanline) and 10 (every two X tile scanlines)
+ * are common to both the 915 and 965-class hardware.
+ *
+ * The CPU also sometimes XORs in higher bits as well, to improve
+ * bandwidth doing strided access like we do so frequently in graphics.  This
+ * is called "Channel XOR Randomization" in the MCH documentation.  The result
+ * is that the CPU is XORing in either bit 11 or bit 17 to bit 6 of its address
+ * decode.
+ *
+ * All of this bit 6 XORing has an effect on our memory management,
+ * as we need to make sure that the 3d driver can correctly address object
+ * contents.
+ *
+ * If we don't have interleaved memory, all tiling is safe and no swizzling is
+ * required.
+ *
+ * When bit 17 is XORed in, we simply refuse to tile at all.  Bit
+ * 17 is not just a page offset, so as we page an object out and back in,
+ * individual pages in it will have different bit 17 addresses, resulting in
+ * each 64 bytes being swapped with its neighbor!
+ *
+ * Otherwise, if interleaved, we have to tell the 3d driver what the address
+ * swizzling it needs to do is, since it's writing with the CPU to the pages
+ * (bit 6 and potentially bit 11 XORed in), and the GPU is reading from the
+ * pages (bit 6, 9, and 10 XORed in), resulting in a cumulative bit swizzling
+ * required by the CPU of XORing in bit 6, 9, 10, and potentially 11, in order
+ * to match what the GPU expects.
+ */
+
+/**
+ * i915_gem_detect_bit_6_swizzle - detect bit 6 swizzling pattern
+ * @dev_priv: i915 device private
+ *
+ * Detects bit 6 swizzling of address lookup between IGD access and CPU
+ * access through main memory.
+ */
+void
+i915_gem_detect_bit_6_swizzle(struct drm_i915_private *dev_priv)
+{
+	uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+	uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+
+	if (INTEL_GEN(dev_priv) >= 8 || IS_VALLEYVIEW(dev_priv)) {
+		/*
+		 * On BDW+, swizzling is not used. We leave the CPU memory
+		 * controller in charge of optimizing memory accesses without
+		 * the extra address manipulation GPU side.
+		 *
+		 * VLV and CHV don't have GPU swizzling.
+		 */
+		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+	} else if (INTEL_GEN(dev_priv) >= 6) {
+		if (dev_priv->preserve_bios_swizzle) {
+			if (I915_READ(DISP_ARB_CTL) &
+			    DISP_TILE_SURFACE_SWIZZLING) {
+				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+				swizzle_y = I915_BIT_6_SWIZZLE_9;
+			} else {
+				swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+				swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+			}
+		} else {
+			uint32_t dimm_c0, dimm_c1;
+			dimm_c0 = I915_READ(MAD_DIMM_C0);
+			dimm_c1 = I915_READ(MAD_DIMM_C1);
+			dimm_c0 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
+			dimm_c1 &= MAD_DIMM_A_SIZE_MASK | MAD_DIMM_B_SIZE_MASK;
+			/* Enable swizzling when the channels are populated
+			 * with identically sized dimms. We don't need to check
+			 * the 3rd channel because no cpu with gpu attached
+			 * ships in that configuration. Also, swizzling only
+			 * makes sense for 2 channels anyway. */
+			if (dimm_c0 == dimm_c1) {
+				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+				swizzle_y = I915_BIT_6_SWIZZLE_9;
+			} else {
+				swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+				swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+			}
+		}
+	} else if (IS_GEN5(dev_priv)) {
+		/* On Ironlake whatever DRAM config, GPU always do
+		 * same swizzling setup.
+		 */
+		swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+		swizzle_y = I915_BIT_6_SWIZZLE_9;
+	} else if (IS_GEN2(dev_priv)) {
+		/* As far as we know, the 865 doesn't have these bit 6
+		 * swizzling issues.
+		 */
+		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+	} else if (IS_MOBILE(dev_priv) || (IS_GEN3(dev_priv) &&
+		   !IS_G33(dev_priv))) {
+		uint32_t dcc;
+
+		/* On 9xx chipsets, channel interleave by the CPU is
+		 * determined by DCC.  For single-channel, neither the CPU
+		 * nor the GPU do swizzling.  For dual channel interleaved,
+		 * the GPU's interleave is bit 9 and 10 for X tiled, and bit
+		 * 9 for Y tiled.  The CPU's interleave is independent, and
+		 * can be based on either bit 11 (haven't seen this yet) or
+		 * bit 17 (common).
+		 */
+		dcc = I915_READ(DCC);
+		switch (dcc & DCC_ADDRESSING_MODE_MASK) {
+		case DCC_ADDRESSING_MODE_SINGLE_CHANNEL:
+		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_ASYMMETRIC:
+			swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+			swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+			break;
+		case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
+			if (dcc & DCC_CHANNEL_XOR_DISABLE) {
+				/* This is the base swizzling by the GPU for
+				 * tiled buffers.
+				 */
+				swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+				swizzle_y = I915_BIT_6_SWIZZLE_9;
+			} else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
+				/* Bit 11 swizzling by the CPU in addition. */
+				swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
+				swizzle_y = I915_BIT_6_SWIZZLE_9_11;
+			} else {
+				/* Bit 17 swizzling by the CPU in addition. */
+				swizzle_x = I915_BIT_6_SWIZZLE_9_10_17;
+				swizzle_y = I915_BIT_6_SWIZZLE_9_17;
+			}
+			break;
+		}
+
+		/* check for L-shaped memory aka modified enhanced addressing */
+		if (IS_GEN4(dev_priv) &&
+		    !(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) {
+			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+		}
+
+		if (dcc == 0xffffffff) {
+			DRM_ERROR("Couldn't read from MCHBAR.  "
+				  "Disabling tiling.\n");
+			swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
+			swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
+		}
+	} else {
+		/* The 965, G33, and newer, have a very flexible memory
+		 * configuration.  It will enable dual-channel mode
+		 * (interleaving) on as much memory as it can, and the GPU
+		 * will additionally sometimes enable different bit 6
+		 * swizzling for tiled objects from the CPU.
+		 *
+		 * Here's what I found on the G965:
+		 *    slot fill         memory size  swizzling
+		 * 0A   0B   1A   1B    1-ch   2-ch
+		 * 512  0    0    0     512    0     O
+		 * 512  0    512  0     16     1008  X
+		 * 512  0    0    512   16     1008  X
+		 * 0    512  0    512   16     1008  X
+		 * 1024 1024 1024 0     2048   1024  O
+		 *
+		 * We could probably detect this based on either the DRB
+		 * matching, which was the case for the swizzling required in
+		 * the table above, or from the 1-ch value being less than
+		 * the minimum size of a rank.
+		 *
+		 * Reports indicate that the swizzling actually
+		 * varies depending upon page placement inside the
+		 * channels, i.e. we see swizzled pages where the
+		 * banks of memory are paired and unswizzled on the
+		 * uneven portion, so leave that as unknown.
+		 */
+		if (I915_READ16(C0DRB3) == I915_READ16(C1DRB3)) {
+			swizzle_x = I915_BIT_6_SWIZZLE_9_10;
+			swizzle_y = I915_BIT_6_SWIZZLE_9;
+		}
+	}
+
+	if (swizzle_x == I915_BIT_6_SWIZZLE_UNKNOWN ||
+	    swizzle_y == I915_BIT_6_SWIZZLE_UNKNOWN) {
+		/* Userspace likes to explode if it sees unknown swizzling,
+		 * so lie. We will finish the lie when reporting through
+		 * the get-tiling-ioctl by reporting the physical swizzle
+		 * mode as unknown instead.
+		 *
+		 * As we don't strictly know what the swizzling is, it may be
+		 * bit17 dependent, and so we need to also prevent the pages
+		 * from being moved.
+		 */
+		dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES;
+		swizzle_x = I915_BIT_6_SWIZZLE_NONE;
+		swizzle_y = I915_BIT_6_SWIZZLE_NONE;
+	}
+
+	dev_priv->mm.bit_6_swizzle_x = swizzle_x;
+	dev_priv->mm.bit_6_swizzle_y = swizzle_y;
+}
+
+/*
+ * Swap every 64 bytes of this page around, to account for it having a new
+ * bit 17 of its physical address and therefore being interpreted differently
+ * by the GPU.
+ */
+static void
+i915_gem_swizzle_page(struct page *page)
+{
+	char temp[64];
+	char *vaddr;
+	int i;
+
+	vaddr = kmap(page);
+
+	for (i = 0; i < PAGE_SIZE; i += 128) {
+		memcpy(temp, &vaddr[i], 64);
+		memcpy(&vaddr[i], &vaddr[i + 64], 64);
+		memcpy(&vaddr[i + 64], temp, 64);
+	}
+
+	kunmap(page);
+}
+
+/**
+ * i915_gem_object_do_bit_17_swizzle - fixup bit 17 swizzling
+ * @obj: i915 GEM buffer object
+ * @pages: the scattergather list of physical pages
+ *
+ * This function fixes up the swizzling in case any page frame number for this
+ * object has changed in bit 17 since that state has been saved with
+ * i915_gem_object_save_bit_17_swizzle().
+ *
+ * This is called when pinning backing storage again, since the kernel is free
+ * to move unpinned backing storage around (either by directly moving pages or
+ * by swapping them out and back in again).
+ */
+void
+i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
+				  struct sg_table *pages)
+{
+	struct sgt_iter sgt_iter;
+	struct page *page;
+	int i;
+
+	if (obj->bit_17 == NULL)
+		return;
+
+	i = 0;
+	for_each_sgt_page(page, sgt_iter, pages) {
+		char new_bit_17 = page_to_phys(page) >> 17;
+		if ((new_bit_17 & 0x1) != (test_bit(i, obj->bit_17) != 0)) {
+			i915_gem_swizzle_page(page);
+			set_page_dirty(page);
+		}
+		i++;
+	}
+}
+
+/**
+ * i915_gem_object_save_bit_17_swizzle - save bit 17 swizzling
+ * @obj: i915 GEM buffer object
+ * @pages: the scattergather list of physical pages
+ *
+ * This function saves the bit 17 of each page frame number so that swizzling
+ * can be fixed up later on with i915_gem_object_do_bit_17_swizzle(). This must
+ * be called before the backing storage can be unpinned.
+ */
+void
+i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
+				    struct sg_table *pages)
+{
+	const unsigned int page_count = obj->base.size >> PAGE_SHIFT;
+	struct sgt_iter sgt_iter;
+	struct page *page;
+	int i;
+
+	if (obj->bit_17 == NULL) {
+		obj->bit_17 = kcalloc(BITS_TO_LONGS(page_count),
+				      sizeof(long), GFP_KERNEL);
+		if (obj->bit_17 == NULL) {
+			DRM_ERROR("Failed to allocate memory for bit 17 "
+				  "record\n");
+			return;
+		}
+	}
+
+	i = 0;
+
+	for_each_sgt_page(page, sgt_iter, pages) {
+		if (page_to_phys(page) & (1 << 17))
+			__set_bit(i, obj->bit_17);
+		else
+			__clear_bit(i, obj->bit_17);
+		i++;
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_fence_reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,51 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __I915_FENCE_REG_H__
+#define __I915_FENCE_REG_H__
+
+#include <linux/list.h>
+
+struct drm_i915_private;
+struct i915_vma;
+
+struct drm_i915_fence_reg {
+	struct list_head link;
+	struct drm_i915_private *i915;
+	struct i915_vma *vma;
+	int pin_count;
+	int id;
+	/**
+	 * Whether the tiling parameters for the currently
+	 * associated fence register have changed. Note that
+	 * for the purposes of tracking tiling changes we also
+	 * treat the unfenced register, the register slot that
+	 * the object occupies whilst it executes a fenced
+	 * command (such as BLT on gen2/3), as a "fence".
+	 */
+	bool dirty;
+};
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_gtt.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@
 #include "i915_vgpu.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include "intel_frontbuffer.h"
 
 #define I915_GFP_DMA (GFP_KERNEL | __GFP_HIGHMEM)
 
@@ -95,13 +96,6 @@
  *
  */
 
-static inline struct i915_ggtt *
-i915_vm_to_ggtt(struct i915_address_space *vm)
-{
-	GEM_BUG_ON(!i915_is_ggtt(vm));
-	return container_of(vm, struct i915_ggtt, base);
-}
-
 static int
 i915_get_ggtt_vma_pages(struct i915_vma *vma);
 
@@ -175,7 +169,7 @@ static int ppgtt_bind_vma(struct i915_vm
 {
 	u32 pte_flags = 0;
 
-	vma->pages = vma->obj->pages;
+	vma->pages = vma->obj->mm.pages;
 
 	/* Currently applicable only to VLV */
 	if (vma->obj->gt_ro)
@@ -191,15 +185,13 @@ static void ppgtt_unbind_vma(struct i915
 {
 	vma->vm->clear_range(vma->vm,
 			     vma->node.start,
-			     vma->size,
-			     true);
+			     vma->size);
 }
 
 static gen8_pte_t gen8_pte_encode(dma_addr_t addr,
-				  enum i915_cache_level level,
-				  bool valid)
+				  enum i915_cache_level level)
 {
-	gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0;
+	gen8_pte_t pte = _PAGE_PRESENT | _PAGE_RW;
 	pte |= addr;
 
 	switch (level) {
@@ -234,9 +226,9 @@ static gen8_pde_t gen8_pde_encode(const
 
 static gen6_pte_t snb_pte_encode(dma_addr_t addr,
 				 enum i915_cache_level level,
-				 bool valid, u32 unused)
+				 u32 unused)
 {
-	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+	gen6_pte_t pte = GEN6_PTE_VALID;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
@@ -256,9 +248,9 @@ static gen6_pte_t snb_pte_encode(dma_add
 
 static gen6_pte_t ivb_pte_encode(dma_addr_t addr,
 				 enum i915_cache_level level,
-				 bool valid, u32 unused)
+				 u32 unused)
 {
-	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+	gen6_pte_t pte = GEN6_PTE_VALID;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
@@ -280,9 +272,9 @@ static gen6_pte_t ivb_pte_encode(dma_add
 
 static gen6_pte_t byt_pte_encode(dma_addr_t addr,
 				 enum i915_cache_level level,
-				 bool valid, u32 flags)
+				 u32 flags)
 {
-	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+	gen6_pte_t pte = GEN6_PTE_VALID;
 	pte |= GEN6_PTE_ADDR_ENCODE(addr);
 
 	if (!(flags & PTE_READ_ONLY))
@@ -296,9 +288,9 @@ static gen6_pte_t byt_pte_encode(dma_add
 
 static gen6_pte_t hsw_pte_encode(dma_addr_t addr,
 				 enum i915_cache_level level,
-				 bool valid, u32 unused)
+				 u32 unused)
 {
-	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+	gen6_pte_t pte = GEN6_PTE_VALID;
 	pte |= HSW_PTE_ADDR_ENCODE(addr);
 
 	if (level != I915_CACHE_NONE)
@@ -309,9 +301,9 @@ static gen6_pte_t hsw_pte_encode(dma_add
 
 static gen6_pte_t iris_pte_encode(dma_addr_t addr,
 				  enum i915_cache_level level,
-				  bool valid, u32 unused)
+				  u32 unused)
 {
-	gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0;
+	gen6_pte_t pte = GEN6_PTE_VALID;
 	pte |= HSW_PTE_ADDR_ENCODE(addr);
 
 	switch (level) {
@@ -328,10 +320,10 @@ static gen6_pte_t iris_pte_encode(dma_ad
 	return pte;
 }
 
-static int __setup_page_dma(struct drm_device *dev,
+static int __setup_page_dma(struct drm_i915_private *dev_priv,
 			    struct i915_page_dma *p, gfp_t flags)
 {
-	struct device *kdev = &dev->pdev->dev;
+	struct device *kdev = &dev_priv->drm.pdev->dev;
 
 	p->page = alloc_page(flags);
 	if (!p->page)
@@ -348,14 +340,16 @@ static int __setup_page_dma(struct drm_d
 	return 0;
 }
 
-static int setup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
+static int setup_page_dma(struct drm_i915_private *dev_priv,
+			  struct i915_page_dma *p)
 {
-	return __setup_page_dma(dev, p, I915_GFP_DMA);
+	return __setup_page_dma(dev_priv, p, I915_GFP_DMA);
 }
 
-static void cleanup_page_dma(struct drm_device *dev, struct i915_page_dma *p)
+static void cleanup_page_dma(struct drm_i915_private *dev_priv,
+			     struct i915_page_dma *p)
 {
-	struct pci_dev *pdev = dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 
 	if (WARN_ON(!p->page))
 		return;
@@ -373,27 +367,29 @@ static void *kmap_page_dma(struct i915_p
 /* We use the flushing unmap only with ppgtt structures:
  * page directories, page tables and scratch pages.
  */
-static void kunmap_page_dma(struct drm_device *dev, void *vaddr)
+static void kunmap_page_dma(struct drm_i915_private *dev_priv, void *vaddr)
 {
 	/* There are only few exceptions for gen >=6. chv and bxt.
 	 * And we are not sure about the latter so play safe for now.
 	 */
-	if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
+	if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
 		drm_clflush_virt_range(vaddr, PAGE_SIZE);
 
 	kunmap_atomic(vaddr);
 }
 
 #define kmap_px(px) kmap_page_dma(px_base(px))
-#define kunmap_px(ppgtt, vaddr) kunmap_page_dma((ppgtt)->base.dev, (vaddr))
+#define kunmap_px(ppgtt, vaddr) \
+		kunmap_page_dma(to_i915((ppgtt)->base.dev), (vaddr))
 
-#define setup_px(dev, px) setup_page_dma((dev), px_base(px))
-#define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px))
-#define fill_px(dev, px, v) fill_page_dma((dev), px_base(px), (v))
-#define fill32_px(dev, px, v) fill_page_dma_32((dev), px_base(px), (v))
+#define setup_px(dev_priv, px) setup_page_dma((dev_priv), px_base(px))
+#define cleanup_px(dev_priv, px) cleanup_page_dma((dev_priv), px_base(px))
+#define fill_px(dev_priv, px, v) fill_page_dma((dev_priv), px_base(px), (v))
+#define fill32_px(dev_priv, px, v) \
+		fill_page_dma_32((dev_priv), px_base(px), (v))
 
-static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p,
-			  const uint64_t val)
+static void fill_page_dma(struct drm_i915_private *dev_priv,
+			  struct i915_page_dma *p, const uint64_t val)
 {
 	int i;
 	uint64_t * const vaddr = kmap_page_dma(p);
@@ -401,38 +397,37 @@ static void fill_page_dma(struct drm_dev
 	for (i = 0; i < 512; i++)
 		vaddr[i] = val;
 
-	kunmap_page_dma(dev, vaddr);
+	kunmap_page_dma(dev_priv, vaddr);
 }
 
-static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p,
-			     const uint32_t val32)
+static void fill_page_dma_32(struct drm_i915_private *dev_priv,
+			     struct i915_page_dma *p, const uint32_t val32)
 {
 	uint64_t v = val32;
 
 	v = v << 32 | val32;
 
-	fill_page_dma(dev, p, v);
+	fill_page_dma(dev_priv, p, v);
 }
 
 static int
-setup_scratch_page(struct drm_device *dev,
+setup_scratch_page(struct drm_i915_private *dev_priv,
 		   struct i915_page_dma *scratch,
 		   gfp_t gfp)
 {
-	return __setup_page_dma(dev, scratch, gfp | __GFP_ZERO);
+	return __setup_page_dma(dev_priv, scratch, gfp | __GFP_ZERO);
 }
 
-static void cleanup_scratch_page(struct drm_device *dev,
+static void cleanup_scratch_page(struct drm_i915_private *dev_priv,
 				 struct i915_page_dma *scratch)
 {
-	cleanup_page_dma(dev, scratch);
+	cleanup_page_dma(dev_priv, scratch);
 }
 
-static struct i915_page_table *alloc_pt(struct drm_device *dev)
+static struct i915_page_table *alloc_pt(struct drm_i915_private *dev_priv)
 {
 	struct i915_page_table *pt;
-	const size_t count = INTEL_INFO(dev)->gen >= 8 ?
-		GEN8_PTES : GEN6_PTES;
+	const size_t count = INTEL_GEN(dev_priv) >= 8 ? GEN8_PTES : GEN6_PTES;
 	int ret = -ENOMEM;
 
 	pt = kzalloc(sizeof(*pt), GFP_KERNEL);
@@ -445,7 +440,7 @@ static struct i915_page_table *alloc_pt(
 	if (!pt->used_ptes)
 		goto fail_bitmap;
 
-	ret = setup_px(dev, pt);
+	ret = setup_px(dev_priv, pt);
 	if (ret)
 		goto fail_page_m;
 
@@ -459,9 +454,10 @@ fail_bitmap:
 	return ERR_PTR(ret);
 }
 
-static void free_pt(struct drm_device *dev, struct i915_page_table *pt)
+static void free_pt(struct drm_i915_private *dev_priv,
+		    struct i915_page_table *pt)
 {
-	cleanup_px(dev, pt);
+	cleanup_px(dev_priv, pt);
 	kfree(pt->used_ptes);
 	kfree(pt);
 }
@@ -472,9 +468,9 @@ static void gen8_initialize_pt(struct i9
 	gen8_pte_t scratch_pte;
 
 	scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
-				      I915_CACHE_LLC, true);
+				      I915_CACHE_LLC);
 
-	fill_px(vm->dev, pt, scratch_pte);
+	fill_px(to_i915(vm->dev), pt, scratch_pte);
 }
 
 static void gen6_initialize_pt(struct i915_address_space *vm,
@@ -485,12 +481,12 @@ static void gen6_initialize_pt(struct i9
 	WARN_ON(vm->scratch_page.daddr == 0);
 
 	scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
-				     I915_CACHE_LLC, true, 0);
+				     I915_CACHE_LLC, 0);
 
-	fill32_px(vm->dev, pt, scratch_pte);
+	fill32_px(to_i915(vm->dev), pt, scratch_pte);
 }
 
-static struct i915_page_directory *alloc_pd(struct drm_device *dev)
+static struct i915_page_directory *alloc_pd(struct drm_i915_private *dev_priv)
 {
 	struct i915_page_directory *pd;
 	int ret = -ENOMEM;
@@ -504,7 +500,7 @@ static struct i915_page_directory *alloc
 	if (!pd->used_pdes)
 		goto fail_bitmap;
 
-	ret = setup_px(dev, pd);
+	ret = setup_px(dev_priv, pd);
 	if (ret)
 		goto fail_page_m;
 
@@ -518,10 +514,11 @@ fail_bitmap:
 	return ERR_PTR(ret);
 }
 
-static void free_pd(struct drm_device *dev, struct i915_page_directory *pd)
+static void free_pd(struct drm_i915_private *dev_priv,
+		    struct i915_page_directory *pd)
 {
 	if (px_page(pd)) {
-		cleanup_px(dev, pd);
+		cleanup_px(dev_priv, pd);
 		kfree(pd->used_pdes);
 		kfree(pd);
 	}
@@ -534,13 +531,13 @@ static void gen8_initialize_pd(struct i9
 
 	scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC);
 
-	fill_px(vm->dev, pd, scratch_pde);
+	fill_px(to_i915(vm->dev), pd, scratch_pde);
 }
 
-static int __pdp_init(struct drm_device *dev,
+static int __pdp_init(struct drm_i915_private *dev_priv,
 		      struct i915_page_directory_pointer *pdp)
 {
-	size_t pdpes = I915_PDPES_PER_PDP(dev);
+	size_t pdpes = I915_PDPES_PER_PDP(dev_priv);
 
 	pdp->used_pdpes = kcalloc(BITS_TO_LONGS(pdpes),
 				  sizeof(unsigned long),
@@ -569,22 +566,22 @@ static void __pdp_fini(struct i915_page_
 }
 
 static struct
-i915_page_directory_pointer *alloc_pdp(struct drm_device *dev)
+i915_page_directory_pointer *alloc_pdp(struct drm_i915_private *dev_priv)
 {
 	struct i915_page_directory_pointer *pdp;
 	int ret = -ENOMEM;
 
-	WARN_ON(!USES_FULL_48BIT_PPGTT(dev));
+	WARN_ON(!USES_FULL_48BIT_PPGTT(dev_priv));
 
 	pdp = kzalloc(sizeof(*pdp), GFP_KERNEL);
 	if (!pdp)
 		return ERR_PTR(-ENOMEM);
 
-	ret = __pdp_init(dev, pdp);
+	ret = __pdp_init(dev_priv, pdp);
 	if (ret)
 		goto fail_bitmap;
 
-	ret = setup_px(dev, pdp);
+	ret = setup_px(dev_priv, pdp);
 	if (ret)
 		goto fail_page_m;
 
@@ -598,12 +595,12 @@ fail_bitmap:
 	return ERR_PTR(ret);
 }
 
-static void free_pdp(struct drm_device *dev,
+static void free_pdp(struct drm_i915_private *dev_priv,
 		     struct i915_page_directory_pointer *pdp)
 {
 	__pdp_fini(pdp);
-	if (USES_FULL_48BIT_PPGTT(dev)) {
-		cleanup_px(dev, pdp);
+	if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+		cleanup_px(dev_priv, pdp);
 		kfree(pdp);
 	}
 }
@@ -615,7 +612,7 @@ static void gen8_initialize_pdp(struct i
 
 	scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
 
-	fill_px(vm->dev, pdp, scratch_pdpe);
+	fill_px(to_i915(vm->dev), pdp, scratch_pdpe);
 }
 
 static void gen8_initialize_pml4(struct i915_address_space *vm,
@@ -626,7 +623,7 @@ static void gen8_initialize_pml4(struct
 	scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp),
 					  I915_CACHE_LLC);
 
-	fill_px(vm->dev, pml4, scratch_pml4e);
+	fill_px(to_i915(vm->dev), pml4, scratch_pml4e);
 }
 
 static void
@@ -637,7 +634,7 @@ gen8_setup_page_directory(struct i915_hw
 {
 	gen8_ppgtt_pdpe_t *page_directorypo;
 
-	if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
+	if (!USES_FULL_48BIT_PPGTT(to_i915(ppgtt->base.dev)))
 		return;
 
 	page_directorypo = kmap_px(pdp);
@@ -653,7 +650,7 @@ gen8_setup_page_directory_pointer(struct
 {
 	gen8_ppgtt_pml4e_t *pagemap = kmap_px(pml4);
 
-	WARN_ON(!USES_FULL_48BIT_PPGTT(ppgtt->base.dev));
+	WARN_ON(!USES_FULL_48BIT_PPGTT(to_i915(ppgtt->base.dev)));
 	pagemap[index] = gen8_pml4e_encode(px_dma(pdp), I915_CACHE_LLC);
 	kunmap_px(ppgtt, pagemap);
 }
@@ -706,85 +703,172 @@ static int gen8_48b_mm_switch(struct i91
 	return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4));
 }
 
-static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm,
-				       struct i915_page_directory_pointer *pdp,
-				       uint64_t start,
-				       uint64_t length,
-				       gen8_pte_t scratch_pte)
+/* PDE TLBs are a pain to invalidate on GEN8+. When we modify
+ * the page table structures, we mark them dirty so that
+ * context switching/execlist queuing code takes extra steps
+ * to ensure that tlbs are flushed.
+ */
+static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
+{
+	ppgtt->pd_dirty_rings = INTEL_INFO(to_i915(ppgtt->base.dev))->ring_mask;
+}
+
+/* Removes entries from a single page table, releasing it if it's empty.
+ * Caller can use the return value to update higher-level entries.
+ */
+static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm,
+				struct i915_page_table *pt,
+				uint64_t start,
+				uint64_t length)
 {
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+	unsigned int num_entries = gen8_pte_count(start, length);
+	unsigned int pte = gen8_pte_index(start);
+	unsigned int pte_end = pte + num_entries;
 	gen8_pte_t *pt_vaddr;
-	unsigned pdpe = gen8_pdpe_index(start);
-	unsigned pde = gen8_pde_index(start);
-	unsigned pte = gen8_pte_index(start);
-	unsigned num_entries = length >> PAGE_SHIFT;
-	unsigned last_pte, i;
+	gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
+						 I915_CACHE_LLC);
 
-	if (WARN_ON(!pdp))
-		return;
+	if (WARN_ON(!px_page(pt)))
+		return false;
 
-	while (num_entries) {
-		struct i915_page_directory *pd;
-		struct i915_page_table *pt;
+	GEM_BUG_ON(pte_end > GEN8_PTES);
 
-		if (WARN_ON(!pdp->page_directory[pdpe]))
-			break;
+	bitmap_clear(pt->used_ptes, pte, num_entries);
 
-		pd = pdp->page_directory[pdpe];
+	if (bitmap_empty(pt->used_ptes, GEN8_PTES)) {
+		free_pt(to_i915(vm->dev), pt);
+		return true;
+	}
+
+	pt_vaddr = kmap_px(pt);
+
+	while (pte < pte_end)
+		pt_vaddr[pte++] = scratch_pte;
+
+	kunmap_px(ppgtt, pt_vaddr);
+
+	return false;
+}
+
+/* Removes entries from a single page dir, releasing it if it's empty.
+ * Caller can use the return value to update higher-level entries
+ */
+static bool gen8_ppgtt_clear_pd(struct i915_address_space *vm,
+				struct i915_page_directory *pd,
+				uint64_t start,
+				uint64_t length)
+{
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+	struct i915_page_table *pt;
+	uint64_t pde;
+	gen8_pde_t *pde_vaddr;
+	gen8_pde_t scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt),
+						 I915_CACHE_LLC);
 
+	gen8_for_each_pde(pt, pd, start, length, pde) {
 		if (WARN_ON(!pd->page_table[pde]))
 			break;
 
-		pt = pd->page_table[pde];
+		if (gen8_ppgtt_clear_pt(vm, pt, start, length)) {
+			__clear_bit(pde, pd->used_pdes);
+			pde_vaddr = kmap_px(pd);
+			pde_vaddr[pde] = scratch_pde;
+			kunmap_px(ppgtt, pde_vaddr);
+		}
+	}
 
-		if (WARN_ON(!px_page(pt)))
-			break;
+	if (bitmap_empty(pd->used_pdes, I915_PDES)) {
+		free_pd(to_i915(vm->dev), pd);
+		return true;
+	}
 
-		last_pte = pte + num_entries;
-		if (last_pte > GEN8_PTES)
-			last_pte = GEN8_PTES;
+	return false;
+}
 
-		pt_vaddr = kmap_px(pt);
+/* Removes entries from a single page dir pointer, releasing it if it's empty.
+ * Caller can use the return value to update higher-level entries
+ */
+static bool gen8_ppgtt_clear_pdp(struct i915_address_space *vm,
+				 struct i915_page_directory_pointer *pdp,
+				 uint64_t start,
+				 uint64_t length)
+{
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
+	struct i915_page_directory *pd;
+	uint64_t pdpe;
+	gen8_ppgtt_pdpe_t *pdpe_vaddr;
+	gen8_ppgtt_pdpe_t scratch_pdpe =
+		gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC);
 
-		for (i = pte; i < last_pte; i++) {
-			pt_vaddr[i] = scratch_pte;
-			num_entries--;
+	gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
+		if (WARN_ON(!pdp->page_directory[pdpe]))
+			break;
+
+		if (gen8_ppgtt_clear_pd(vm, pd, start, length)) {
+			__clear_bit(pdpe, pdp->used_pdpes);
+			if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+				pdpe_vaddr = kmap_px(pdp);
+				pdpe_vaddr[pdpe] = scratch_pdpe;
+				kunmap_px(ppgtt, pdpe_vaddr);
+			}
 		}
+	}
 
-		kunmap_px(ppgtt, pt_vaddr);
+	mark_tlbs_dirty(ppgtt);
 
-		pte = 0;
-		if (++pde == I915_PDES) {
-			if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
-				break;
-			pde = 0;
-		}
+	if (USES_FULL_48BIT_PPGTT(dev_priv) &&
+	    bitmap_empty(pdp->used_pdpes, I915_PDPES_PER_PDP(dev_priv))) {
+		free_pdp(dev_priv, pdp);
+		return true;
 	}
+
+	return false;
 }
 
-static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
-				   uint64_t start,
-				   uint64_t length,
-				   bool use_scratch)
+/* Removes entries from a single pml4.
+ * This is the top-level structure in 4-level page tables used on gen8+.
+ * Empty entries are always scratch pml4e.
+ */
+static void gen8_ppgtt_clear_pml4(struct i915_address_space *vm,
+				  struct i915_pml4 *pml4,
+				  uint64_t start,
+				  uint64_t length)
 {
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
-	gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
-						 I915_CACHE_LLC, use_scratch);
+	struct i915_page_directory_pointer *pdp;
+	uint64_t pml4e;
+	gen8_ppgtt_pml4e_t *pml4e_vaddr;
+	gen8_ppgtt_pml4e_t scratch_pml4e =
+		gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC);
 
-	if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
-		gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
-					   scratch_pte);
-	} else {
-		uint64_t pml4e;
-		struct i915_page_directory_pointer *pdp;
+	GEM_BUG_ON(!USES_FULL_48BIT_PPGTT(to_i915(vm->dev)));
 
-		gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
-			gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
-						   scratch_pte);
+	gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
+		if (WARN_ON(!pml4->pdps[pml4e]))
+			break;
+
+		if (gen8_ppgtt_clear_pdp(vm, pdp, start, length)) {
+			__clear_bit(pml4e, pml4->used_pml4es);
+			pml4e_vaddr = kmap_px(pml4);
+			pml4e_vaddr[pml4e] = scratch_pml4e;
+			kunmap_px(ppgtt, pml4e_vaddr);
 		}
 	}
 }
 
+static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
+				   uint64_t start, uint64_t length)
+{
+	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
+
+	if (USES_FULL_48BIT_PPGTT(to_i915(vm->dev)))
+		gen8_ppgtt_clear_pml4(vm, &ppgtt->pml4, start, length);
+	else
+		gen8_ppgtt_clear_pdp(vm, &ppgtt->pdp, start, length);
+}
+
 static void
 gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
 			      struct i915_page_directory_pointer *pdp,
@@ -809,12 +893,12 @@ gen8_ppgtt_insert_pte_entries(struct i91
 
 		pt_vaddr[pte] =
 			gen8_pte_encode(sg_page_iter_dma_address(sg_iter),
-					cache_level, true);
+					cache_level);
 		if (++pte == GEN8_PTES) {
 			kunmap_px(ppgtt, pt_vaddr);
 			pt_vaddr = NULL;
 			if (++pde == I915_PDES) {
-				if (++pdpe == I915_PDPES_PER_PDP(vm->dev))
+				if (++pdpe == I915_PDPES_PER_PDP(to_i915(vm->dev)))
 					break;
 				pde = 0;
 			}
@@ -837,7 +921,7 @@ static void gen8_ppgtt_insert_entries(st
 
 	__sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0);
 
-	if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
+	if (!USES_FULL_48BIT_PPGTT(to_i915(vm->dev))) {
 		gen8_ppgtt_insert_pte_entries(vm, &ppgtt->pdp, &sg_iter, start,
 					      cache_level);
 	} else {
@@ -852,7 +936,7 @@ static void gen8_ppgtt_insert_entries(st
 	}
 }
 
-static void gen8_free_page_tables(struct drm_device *dev,
+static void gen8_free_page_tables(struct drm_i915_private *dev_priv,
 				  struct i915_page_directory *pd)
 {
 	int i;
@@ -864,34 +948,34 @@ static void gen8_free_page_tables(struct
 		if (WARN_ON(!pd->page_table[i]))
 			continue;
 
-		free_pt(dev, pd->page_table[i]);
+		free_pt(dev_priv, pd->page_table[i]);
 		pd->page_table[i] = NULL;
 	}
 }
 
 static int gen8_init_scratch(struct i915_address_space *vm)
 {
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	int ret;
 
-	ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA);
+	ret = setup_scratch_page(dev_priv, &vm->scratch_page, I915_GFP_DMA);
 	if (ret)
 		return ret;
 
-	vm->scratch_pt = alloc_pt(dev);
+	vm->scratch_pt = alloc_pt(dev_priv);
 	if (IS_ERR(vm->scratch_pt)) {
 		ret = PTR_ERR(vm->scratch_pt);
 		goto free_scratch_page;
 	}
 
-	vm->scratch_pd = alloc_pd(dev);
+	vm->scratch_pd = alloc_pd(dev_priv);
 	if (IS_ERR(vm->scratch_pd)) {
 		ret = PTR_ERR(vm->scratch_pd);
 		goto free_pt;
 	}
 
-	if (USES_FULL_48BIT_PPGTT(dev)) {
-		vm->scratch_pdp = alloc_pdp(dev);
+	if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+		vm->scratch_pdp = alloc_pdp(dev_priv);
 		if (IS_ERR(vm->scratch_pdp)) {
 			ret = PTR_ERR(vm->scratch_pdp);
 			goto free_pd;
@@ -900,17 +984,17 @@ static int gen8_init_scratch(struct i915
 
 	gen8_initialize_pt(vm, vm->scratch_pt);
 	gen8_initialize_pd(vm, vm->scratch_pd);
-	if (USES_FULL_48BIT_PPGTT(dev))
+	if (USES_FULL_48BIT_PPGTT(dev_priv))
 		gen8_initialize_pdp(vm, vm->scratch_pdp);
 
 	return 0;
 
 free_pd:
-	free_pd(dev, vm->scratch_pd);
+	free_pd(dev_priv, vm->scratch_pd);
 free_pt:
-	free_pt(dev, vm->scratch_pt);
+	free_pt(dev_priv, vm->scratch_pt);
 free_scratch_page:
-	cleanup_scratch_page(dev, &vm->scratch_page);
+	cleanup_scratch_page(dev_priv, &vm->scratch_page);
 
 	return ret;
 }
@@ -948,54 +1032,56 @@ static int gen8_ppgtt_notify_vgt(struct
 
 static void gen8_free_scratch(struct i915_address_space *vm)
 {
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 
-	if (USES_FULL_48BIT_PPGTT(dev))
-		free_pdp(dev, vm->scratch_pdp);
-	free_pd(dev, vm->scratch_pd);
-	free_pt(dev, vm->scratch_pt);
-	cleanup_scratch_page(dev, &vm->scratch_page);
+	if (USES_FULL_48BIT_PPGTT(dev_priv))
+		free_pdp(dev_priv, vm->scratch_pdp);
+	free_pd(dev_priv, vm->scratch_pd);
+	free_pt(dev_priv, vm->scratch_pt);
+	cleanup_scratch_page(dev_priv, &vm->scratch_page);
 }
 
-static void gen8_ppgtt_cleanup_3lvl(struct drm_device *dev,
+static void gen8_ppgtt_cleanup_3lvl(struct drm_i915_private *dev_priv,
 				    struct i915_page_directory_pointer *pdp)
 {
 	int i;
 
-	for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev)) {
+	for_each_set_bit(i, pdp->used_pdpes, I915_PDPES_PER_PDP(dev_priv)) {
 		if (WARN_ON(!pdp->page_directory[i]))
 			continue;
 
-		gen8_free_page_tables(dev, pdp->page_directory[i]);
-		free_pd(dev, pdp->page_directory[i]);
+		gen8_free_page_tables(dev_priv, pdp->page_directory[i]);
+		free_pd(dev_priv, pdp->page_directory[i]);
 	}
 
-	free_pdp(dev, pdp);
+	free_pdp(dev_priv, pdp);
 }
 
 static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt)
 {
+	struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
 	int i;
 
 	for_each_set_bit(i, ppgtt->pml4.used_pml4es, GEN8_PML4ES_PER_PML4) {
 		if (WARN_ON(!ppgtt->pml4.pdps[i]))
 			continue;
 
-		gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, ppgtt->pml4.pdps[i]);
+		gen8_ppgtt_cleanup_3lvl(dev_priv, ppgtt->pml4.pdps[i]);
 	}
 
-	cleanup_px(ppgtt->base.dev, &ppgtt->pml4);
+	cleanup_px(dev_priv, &ppgtt->pml4);
 }
 
 static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
 {
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 
-	if (intel_vgpu_active(to_i915(vm->dev)))
+	if (intel_vgpu_active(dev_priv))
 		gen8_ppgtt_notify_vgt(ppgtt, false);
 
-	if (!USES_FULL_48BIT_PPGTT(ppgtt->base.dev))
-		gen8_ppgtt_cleanup_3lvl(ppgtt->base.dev, &ppgtt->pdp);
+	if (!USES_FULL_48BIT_PPGTT(dev_priv))
+		gen8_ppgtt_cleanup_3lvl(dev_priv, &ppgtt->pdp);
 	else
 		gen8_ppgtt_cleanup_4lvl(ppgtt);
 
@@ -1026,7 +1112,7 @@ static int gen8_ppgtt_alloc_pagetabs(str
 				     uint64_t length,
 				     unsigned long *new_pts)
 {
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_page_table *pt;
 	uint32_t pde;
 
@@ -1038,7 +1124,7 @@ static int gen8_ppgtt_alloc_pagetabs(str
 			continue;
 		}
 
-		pt = alloc_pt(dev);
+		pt = alloc_pt(dev_priv);
 		if (IS_ERR(pt))
 			goto unwind_out;
 
@@ -1052,7 +1138,7 @@ static int gen8_ppgtt_alloc_pagetabs(str
 
 unwind_out:
 	for_each_set_bit(pde, new_pts, I915_PDES)
-		free_pt(dev, pd->page_table[pde]);
+		free_pt(dev_priv, pd->page_table[pde]);
 
 	return -ENOMEM;
 }
@@ -1087,10 +1173,10 @@ gen8_ppgtt_alloc_page_directories(struct
 				  uint64_t length,
 				  unsigned long *new_pds)
 {
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_page_directory *pd;
 	uint32_t pdpe;
-	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
+	uint32_t pdpes = I915_PDPES_PER_PDP(dev_priv);
 
 	WARN_ON(!bitmap_empty(new_pds, pdpes));
 
@@ -1098,7 +1184,7 @@ gen8_ppgtt_alloc_page_directories(struct
 		if (test_bit(pdpe, pdp->used_pdpes))
 			continue;
 
-		pd = alloc_pd(dev);
+		pd = alloc_pd(dev_priv);
 		if (IS_ERR(pd))
 			goto unwind_out;
 
@@ -1112,7 +1198,7 @@ gen8_ppgtt_alloc_page_directories(struct
 
 unwind_out:
 	for_each_set_bit(pdpe, new_pds, pdpes)
-		free_pd(dev, pdp->page_directory[pdpe]);
+		free_pd(dev_priv, pdp->page_directory[pdpe]);
 
 	return -ENOMEM;
 }
@@ -1140,7 +1226,7 @@ gen8_ppgtt_alloc_page_dirpointers(struct
 				  uint64_t length,
 				  unsigned long *new_pdps)
 {
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_page_directory_pointer *pdp;
 	uint32_t pml4e;
 
@@ -1148,7 +1234,7 @@ gen8_ppgtt_alloc_page_dirpointers(struct
 
 	gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
 		if (!test_bit(pml4e, pml4->used_pml4es)) {
-			pdp = alloc_pdp(dev);
+			pdp = alloc_pdp(dev_priv);
 			if (IS_ERR(pdp))
 				goto unwind_out;
 
@@ -1166,7 +1252,7 @@ gen8_ppgtt_alloc_page_dirpointers(struct
 
 unwind_out:
 	for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
-		free_pdp(dev, pml4->pdps[pml4e]);
+		free_pdp(dev_priv, pml4->pdps[pml4e]);
 
 	return -ENOMEM;
 }
@@ -1208,16 +1294,6 @@ err_out:
 	return -ENOMEM;
 }
 
-/* PDE TLBs are a pain to invalidate on GEN8+. When we modify
- * the page table structures, we mark them dirty so that
- * context switching/execlist queuing code takes extra steps
- * to ensure that tlbs are flushed.
- */
-static void mark_tlbs_dirty(struct i915_hw_ppgtt *ppgtt)
-{
-	ppgtt->pd_dirty_rings = INTEL_INFO(ppgtt->base.dev)->ring_mask;
-}
-
 static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
 				    struct i915_page_directory_pointer *pdp,
 				    uint64_t start,
@@ -1225,12 +1301,12 @@ static int gen8_alloc_va_range_3lvl(stru
 {
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	unsigned long *new_page_dirs, *new_page_tables;
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_page_directory *pd;
 	const uint64_t orig_start = start;
 	const uint64_t orig_length = length;
 	uint32_t pdpe;
-	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
+	uint32_t pdpes = I915_PDPES_PER_PDP(dev_priv);
 	int ret;
 
 	/* Wrap is never okay since we can only represent 48b, and we don't
@@ -1318,11 +1394,12 @@ err_out:
 
 		for_each_set_bit(temp, new_page_tables + pdpe *
 				BITS_TO_LONGS(I915_PDES), I915_PDES)
-			free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]);
+			free_pt(dev_priv,
+				pdp->page_directory[pdpe]->page_table[temp]);
 	}
 
 	for_each_set_bit(pdpe, new_page_dirs, pdpes)
-		free_pd(dev, pdp->page_directory[pdpe]);
+		free_pd(dev_priv, pdp->page_directory[pdpe]);
 
 	free_gen8_temp_bitmaps(new_page_dirs, new_page_tables);
 	mark_tlbs_dirty(ppgtt);
@@ -1373,7 +1450,7 @@ static int gen8_alloc_va_range_4lvl(stru
 
 err_out:
 	for_each_set_bit(pml4e, new_pdps, GEN8_PML4ES_PER_PML4)
-		gen8_ppgtt_cleanup_3lvl(vm->dev, pml4->pdps[pml4e]);
+		gen8_ppgtt_cleanup_3lvl(to_i915(vm->dev), pml4->pdps[pml4e]);
 
 	return ret;
 }
@@ -1383,7 +1460,7 @@ static int gen8_alloc_va_range(struct i9
 {
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 
-	if (USES_FULL_48BIT_PPGTT(vm->dev))
+	if (USES_FULL_48BIT_PPGTT(to_i915(vm->dev)))
 		return gen8_alloc_va_range_4lvl(vm, &ppgtt->pml4, start, length);
 	else
 		return gen8_alloc_va_range_3lvl(vm, &ppgtt->pdp, start, length);
@@ -1452,9 +1529,9 @@ static void gen8_dump_ppgtt(struct i915_
 	uint64_t start = ppgtt->base.start;
 	uint64_t length = ppgtt->base.total;
 	gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
-						 I915_CACHE_LLC, true);
+						 I915_CACHE_LLC);
 
-	if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
+	if (!USES_FULL_48BIT_PPGTT(to_i915(vm->dev))) {
 		gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
 	} else {
 		uint64_t pml4e;
@@ -1474,7 +1551,7 @@ static void gen8_dump_ppgtt(struct i915_
 static int gen8_preallocate_top_level_pdps(struct i915_hw_ppgtt *ppgtt)
 {
 	unsigned long *new_page_dirs, *new_page_tables;
-	uint32_t pdpes = I915_PDPES_PER_PDP(dev);
+	uint32_t pdpes = I915_PDPES_PER_PDP(to_i915(ppgtt->base.dev));
 	int ret;
 
 	/* We allocate temp bitmap for page tables for no gain
@@ -1507,6 +1584,7 @@ static int gen8_preallocate_top_level_pd
  */
 static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 {
+	struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
 	int ret;
 
 	ret = gen8_init_scratch(&ppgtt->base);
@@ -1522,8 +1600,8 @@ static int gen8_ppgtt_init(struct i915_h
 	ppgtt->base.bind_vma = ppgtt_bind_vma;
 	ppgtt->debug_dump = gen8_dump_ppgtt;
 
-	if (USES_FULL_48BIT_PPGTT(ppgtt->base.dev)) {
-		ret = setup_px(ppgtt->base.dev, &ppgtt->pml4);
+	if (USES_FULL_48BIT_PPGTT(dev_priv)) {
+		ret = setup_px(dev_priv, &ppgtt->pml4);
 		if (ret)
 			goto free_scratch;
 
@@ -1532,7 +1610,7 @@ static int gen8_ppgtt_init(struct i915_h
 		ppgtt->base.total = 1ULL << 48;
 		ppgtt->switch_mm = gen8_48b_mm_switch;
 	} else {
-		ret = __pdp_init(ppgtt->base.dev, &ppgtt->pdp);
+		ret = __pdp_init(dev_priv, &ppgtt->pdp);
 		if (ret)
 			goto free_scratch;
 
@@ -1542,14 +1620,14 @@ static int gen8_ppgtt_init(struct i915_h
 							      0, 0,
 							      GEN8_PML4E_SHIFT);
 
-		if (intel_vgpu_active(to_i915(ppgtt->base.dev))) {
+		if (intel_vgpu_active(dev_priv)) {
 			ret = gen8_preallocate_top_level_pdps(ppgtt);
 			if (ret)
 				goto free_scratch;
 		}
 	}
 
-	if (intel_vgpu_active(to_i915(ppgtt->base.dev)))
+	if (intel_vgpu_active(dev_priv))
 		gen8_ppgtt_notify_vgt(ppgtt, true);
 
 	return 0;
@@ -1569,7 +1647,7 @@ static void gen6_dump_ppgtt(struct i915_
 	uint32_t start = ppgtt->base.start, length = ppgtt->base.total;
 
 	scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
-				     I915_CACHE_LLC, true, 0);
+				     I915_CACHE_LLC, 0);
 
 	gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) {
 		u32 expected;
@@ -1724,29 +1802,30 @@ static int gen6_mm_switch(struct i915_hw
 	return 0;
 }
 
-static void gen8_ppgtt_enable(struct drm_device *dev)
+static void gen8_ppgtt_enable(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv) {
-		u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0;
+	for_each_engine(engine, dev_priv, id) {
+		u32 four_level = USES_FULL_48BIT_PPGTT(dev_priv) ?
+				 GEN8_GFX_PPGTT_48B : 0;
 		I915_WRITE(RING_MODE_GEN7(engine),
 			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level));
 	}
 }
 
-static void gen7_ppgtt_enable(struct drm_device *dev)
+static void gen7_ppgtt_enable(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_engine_cs *engine;
 	uint32_t ecochk, ecobits;
+	enum intel_engine_id id;
 
 	ecobits = I915_READ(GAC_ECO_BITS);
 	I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
 
 	ecochk = I915_READ(GAM_ECOCHK);
-	if (IS_HASWELL(dev)) {
+	if (IS_HASWELL(dev_priv)) {
 		ecochk |= ECOCHK_PPGTT_WB_HSW;
 	} else {
 		ecochk |= ECOCHK_PPGTT_LLC_IVB;
@@ -1754,16 +1833,15 @@ static void gen7_ppgtt_enable(struct drm
 	}
 	I915_WRITE(GAM_ECOCHK, ecochk);
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		/* GFX_MODE is per-ring on gen7+ */
 		I915_WRITE(RING_MODE_GEN7(engine),
 			   _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
 	}
 }
 
-static void gen6_ppgtt_enable(struct drm_device *dev)
+static void gen6_ppgtt_enable(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t ecochk, gab_ctl, ecobits;
 
 	ecobits = I915_READ(GAC_ECO_BITS);
@@ -1782,8 +1860,7 @@ static void gen6_ppgtt_enable(struct drm
 /* PPGTT support for Sandybdrige/Gen6 and later */
 static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
 				   uint64_t start,
-				   uint64_t length,
-				   bool use_scratch)
+				   uint64_t length)
 {
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	gen6_pte_t *pt_vaddr, scratch_pte;
@@ -1794,7 +1871,7 @@ static void gen6_ppgtt_clear_range(struc
 	unsigned last_pte, i;
 
 	scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
-				     I915_CACHE_LLC, true, 0);
+				     I915_CACHE_LLC, 0);
 
 	while (num_entries) {
 		last_pte = first_pte + num_entries;
@@ -1832,7 +1909,7 @@ static void gen6_ppgtt_insert_entries(st
 			pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]);
 
 		pt_vaddr[act_pte] =
-			vm->pte_encode(addr, cache_level, true, flags);
+			vm->pte_encode(addr, cache_level, flags);
 
 		if (++act_pte == GEN6_PTES) {
 			kunmap_px(ppgtt, pt_vaddr);
@@ -1850,8 +1927,7 @@ static int gen6_alloc_va_range(struct i9
 			       uint64_t start_in, uint64_t length_in)
 {
 	DECLARE_BITMAP(new_page_tables, I915_PDES);
-	struct drm_device *dev = vm->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	struct i915_page_table *pt;
@@ -1881,7 +1957,7 @@ static int gen6_alloc_va_range(struct i9
 		/* We've already allocated a page table */
 		WARN_ON(!bitmap_empty(pt->used_ptes, GEN6_PTES));
 
-		pt = alloc_pt(dev);
+		pt = alloc_pt(dev_priv);
 		if (IS_ERR(pt)) {
 			ret = PTR_ERR(pt);
 			goto unwind_out;
@@ -1929,7 +2005,7 @@ unwind_out:
 		struct i915_page_table *pt = ppgtt->pd.page_table[pde];
 
 		ppgtt->pd.page_table[pde] = vm->scratch_pt;
-		free_pt(vm->dev, pt);
+		free_pt(dev_priv, pt);
 	}
 
 	mark_tlbs_dirty(ppgtt);
@@ -1938,16 +2014,16 @@ unwind_out:
 
 static int gen6_init_scratch(struct i915_address_space *vm)
 {
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	int ret;
 
-	ret = setup_scratch_page(dev, &vm->scratch_page, I915_GFP_DMA);
+	ret = setup_scratch_page(dev_priv, &vm->scratch_page, I915_GFP_DMA);
 	if (ret)
 		return ret;
 
-	vm->scratch_pt = alloc_pt(dev);
+	vm->scratch_pt = alloc_pt(dev_priv);
 	if (IS_ERR(vm->scratch_pt)) {
-		cleanup_scratch_page(dev, &vm->scratch_page);
+		cleanup_scratch_page(dev_priv, &vm->scratch_page);
 		return PTR_ERR(vm->scratch_pt);
 	}
 
@@ -1958,17 +2034,17 @@ static int gen6_init_scratch(struct i915
 
 static void gen6_free_scratch(struct i915_address_space *vm)
 {
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 
-	free_pt(dev, vm->scratch_pt);
-	cleanup_scratch_page(dev, &vm->scratch_page);
+	free_pt(dev_priv, vm->scratch_pt);
+	cleanup_scratch_page(dev_priv, &vm->scratch_page);
 }
 
 static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
 {
 	struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
 	struct i915_page_directory *pd = &ppgtt->pd;
-	struct drm_device *dev = vm->dev;
+	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_page_table *pt;
 	uint32_t pde;
 
@@ -1976,7 +2052,7 @@ static void gen6_ppgtt_cleanup(struct i9
 
 	gen6_for_all_pdes(pt, pd, pde)
 		if (pt != vm->scratch_pt)
-			free_pt(dev, pt);
+			free_pt(dev_priv, pt);
 
 	gen6_free_scratch(vm);
 }
@@ -1984,8 +2060,7 @@ static void gen6_ppgtt_cleanup(struct i9
 static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
 {
 	struct i915_address_space *vm = &ppgtt->base;
-	struct drm_device *dev = ppgtt->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	bool retried = false;
 	int ret;
@@ -2050,17 +2125,16 @@ static void gen6_scratch_va_range(struct
 
 static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
 {
-	struct drm_device *dev = ppgtt->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(ppgtt->base.dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	int ret;
 
 	ppgtt->base.pte_encode = ggtt->base.pte_encode;
-	if (intel_vgpu_active(dev_priv) || IS_GEN6(dev))
+	if (intel_vgpu_active(dev_priv) || IS_GEN6(dev_priv))
 		ppgtt->switch_mm = gen6_mm_switch;
-	else if (IS_HASWELL(dev))
+	else if (IS_HASWELL(dev_priv))
 		ppgtt->switch_mm = hsw_mm_switch;
-	else if (IS_GEN7(dev))
+	else if (IS_GEN7(dev_priv))
 		ppgtt->switch_mm = gen7_mm_switch;
 	else
 		BUG();
@@ -2111,8 +2185,10 @@ static int __hw_ppgtt_init(struct i915_h
 }
 
 static void i915_address_space_init(struct i915_address_space *vm,
-				    struct drm_i915_private *dev_priv)
+				    struct drm_i915_private *dev_priv,
+				    const char *name)
 {
+	i915_gem_timeline_init(dev_priv, &vm->timeline, name);
 	drm_mm_init(&vm->mm, vm->start, vm->total);
 	INIT_LIST_HEAD(&vm->active_list);
 	INIT_LIST_HEAD(&vm->inactive_list);
@@ -2120,44 +2196,50 @@ static void i915_address_space_init(stru
 	list_add_tail(&vm->global_link, &dev_priv->vm_list);
 }
 
-static void gtt_write_workarounds(struct drm_device *dev)
+static void i915_address_space_fini(struct i915_address_space *vm)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	i915_gem_timeline_fini(&vm->timeline);
+	drm_mm_takedown(&vm->mm);
+	list_del(&vm->global_link);
+}
 
+static void gtt_write_workarounds(struct drm_i915_private *dev_priv)
+{
 	/* This function is for gtt related workarounds. This function is
 	 * called on driver load and after a GPU reset, so you can place
 	 * workarounds here even if they get overwritten by GPU reset.
 	 */
 	/* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */
-	if (IS_BROADWELL(dev))
+	if (IS_BROADWELL(dev_priv))
 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW);
-	else if (IS_CHERRYVIEW(dev))
+	else if (IS_CHERRYVIEW(dev_priv))
 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV);
-	else if (IS_SKYLAKE(dev))
+	else if (IS_SKYLAKE(dev_priv))
 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT);
 }
 
 static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt,
 			   struct drm_i915_private *dev_priv,
-			   struct drm_i915_file_private *file_priv)
+			   struct drm_i915_file_private *file_priv,
+			   const char *name)
 {
 	int ret;
 
 	ret = __hw_ppgtt_init(ppgtt, dev_priv);
 	if (ret == 0) {
 		kref_init(&ppgtt->ref);
-		i915_address_space_init(&ppgtt->base, dev_priv);
+		i915_address_space_init(&ppgtt->base, dev_priv, name);
 		ppgtt->base.file = file_priv;
 	}
 
 	return ret;
 }
 
-int i915_ppgtt_init_hw(struct drm_device *dev)
+int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv)
 {
-	gtt_write_workarounds(dev);
+	gtt_write_workarounds(dev_priv);
 
 	/* In the case of execlists, PPGTT is enabled by the context descriptor
 	 * and the PDPs are contained within the context itself.  We don't
@@ -2165,24 +2247,25 @@ int i915_ppgtt_init_hw(struct drm_device
 	if (i915.enable_execlists)
 		return 0;
 
-	if (!USES_PPGTT(dev))
+	if (!USES_PPGTT(dev_priv))
 		return 0;
 
-	if (IS_GEN6(dev))
-		gen6_ppgtt_enable(dev);
-	else if (IS_GEN7(dev))
-		gen7_ppgtt_enable(dev);
-	else if (INTEL_INFO(dev)->gen >= 8)
-		gen8_ppgtt_enable(dev);
+	if (IS_GEN6(dev_priv))
+		gen6_ppgtt_enable(dev_priv);
+	else if (IS_GEN7(dev_priv))
+		gen7_ppgtt_enable(dev_priv);
+	else if (INTEL_GEN(dev_priv) >= 8)
+		gen8_ppgtt_enable(dev_priv);
 	else
-		MISSING_CASE(INTEL_INFO(dev)->gen);
+		MISSING_CASE(INTEL_GEN(dev_priv));
 
 	return 0;
 }
 
 struct i915_hw_ppgtt *
 i915_ppgtt_create(struct drm_i915_private *dev_priv,
-		  struct drm_i915_file_private *fpriv)
+		  struct drm_i915_file_private *fpriv,
+		  const char *name)
 {
 	struct i915_hw_ppgtt *ppgtt;
 	int ret;
@@ -2191,7 +2274,7 @@ i915_ppgtt_create(struct drm_i915_privat
 	if (!ppgtt)
 		return ERR_PTR(-ENOMEM);
 
-	ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv);
+	ret = i915_ppgtt_init(ppgtt, dev_priv, fpriv, name);
 	if (ret) {
 		kfree(ppgtt);
 		return ERR_PTR(ret);
@@ -2202,7 +2285,7 @@ i915_ppgtt_create(struct drm_i915_privat
 	return ppgtt;
 }
 
-void  i915_ppgtt_release(struct kref *kref)
+void i915_ppgtt_release(struct kref *kref)
 {
 	struct i915_hw_ppgtt *ppgtt =
 		container_of(kref, struct i915_hw_ppgtt, ref);
@@ -2214,8 +2297,7 @@ void  i915_ppgtt_release(struct kref *kr
 	WARN_ON(!list_empty(&ppgtt->base.inactive_list));
 	WARN_ON(!list_empty(&ppgtt->base.unbound_list));
 
-	list_del(&ppgtt->base.global_link);
-	drm_mm_takedown(&ppgtt->base.mm);
+	i915_address_space_fini(&ppgtt->base);
 
 	ppgtt->base.cleanup(&ppgtt->base);
 	kfree(ppgtt);
@@ -2239,11 +2321,12 @@ static bool needs_idle_maps(struct drm_i
 void i915_check_and_clear_faults(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
 	if (INTEL_INFO(dev_priv)->gen < 6)
 		return;
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		u32 fault_reg;
 		fault_reg = I915_READ(RING_FAULT_REG(engine));
 		if (fault_reg & RING_FAULT_VALID) {
@@ -2260,7 +2343,10 @@ void i915_check_and_clear_faults(struct
 				   fault_reg & ~RING_FAULT_VALID);
 		}
 	}
-	POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS]));
+
+	/* Engine specific init may not have been done till this point. */
+	if (dev_priv->engine[RCS])
+		POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS]));
 }
 
 static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
@@ -2273,33 +2359,32 @@ static void i915_ggtt_flush(struct drm_i
 	}
 }
 
-void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
+void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 
 	/* Don't bother messing with faults pre GEN6 as we have little
 	 * documentation supporting that it's a good idea.
 	 */
-	if (INTEL_INFO(dev)->gen < 6)
+	if (INTEL_GEN(dev_priv) < 6)
 		return;
 
 	i915_check_and_clear_faults(dev_priv);
 
-	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
-			     true);
+	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total);
 
 	i915_ggtt_flush(dev_priv);
 }
 
-int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)
+int i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
+			       struct sg_table *pages)
 {
-	if (!dma_map_sg(&obj->base.dev->pdev->dev,
-			obj->pages->sgl, obj->pages->nents,
-			PCI_DMA_BIDIRECTIONAL))
-		return -ENOSPC;
+	if (dma_map_sg(&obj->base.dev->pdev->dev,
+		       pages->sgl, pages->nents,
+		       PCI_DMA_BIDIRECTIONAL))
+		return 0;
 
-	return 0;
+	return -ENOSPC;
 }
 
 static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
@@ -2317,16 +2402,11 @@ static void gen8_ggtt_insert_page(struct
 	gen8_pte_t __iomem *pte =
 		(gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
 		(offset >> PAGE_SHIFT);
-	int rpm_atomic_seq;
-
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
-	gen8_set_pte(pte, gen8_pte_encode(addr, level, true));
+	gen8_set_pte(pte, gen8_pte_encode(addr, level));
 
 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
@@ -2340,15 +2420,12 @@ static void gen8_ggtt_insert_entries(str
 	gen8_pte_t __iomem *gtt_entries;
 	gen8_pte_t gtt_entry;
 	dma_addr_t addr;
-	int rpm_atomic_seq;
 	int i = 0;
 
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
 	gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
 
 	for_each_sgt_dma(addr, sgt_iter, st) {
-		gtt_entry = gen8_pte_encode(addr, level, true);
+		gtt_entry = gen8_pte_encode(addr, level);
 		gen8_set_pte(&gtt_entries[i++], gtt_entry);
 	}
 
@@ -2368,8 +2445,6 @@ static void gen8_ggtt_insert_entries(str
 	 */
 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 struct insert_entries {
@@ -2408,16 +2483,11 @@ static void gen6_ggtt_insert_page(struct
 	gen6_pte_t __iomem *pte =
 		(gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
 		(offset >> PAGE_SHIFT);
-	int rpm_atomic_seq;
 
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
-	iowrite32(vm->pte_encode(addr, level, true, flags), pte);
+	iowrite32(vm->pte_encode(addr, level, flags), pte);
 
 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 /*
@@ -2437,15 +2507,12 @@ static void gen6_ggtt_insert_entries(str
 	gen6_pte_t __iomem *gtt_entries;
 	gen6_pte_t gtt_entry;
 	dma_addr_t addr;
-	int rpm_atomic_seq;
 	int i = 0;
 
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
 	gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
 
 	for_each_sgt_dma(addr, sgt_iter, st) {
-		gtt_entry = vm->pte_encode(addr, level, true, flags);
+		gtt_entry = vm->pte_encode(addr, level, flags);
 		iowrite32(gtt_entry, &gtt_entries[i++]);
 	}
 
@@ -2464,23 +2531,16 @@ static void gen6_ggtt_insert_entries(str
 	 */
 	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
 	POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void nop_clear_range(struct i915_address_space *vm,
-			    uint64_t start,
-			    uint64_t length,
-			    bool use_scratch)
+			    uint64_t start, uint64_t length)
 {
 }
 
 static void gen8_ggtt_clear_range(struct i915_address_space *vm,
-				  uint64_t start,
-				  uint64_t length,
-				  bool use_scratch)
+				  uint64_t start, uint64_t length)
 {
-	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
 	unsigned first_entry = start >> PAGE_SHIFT;
 	unsigned num_entries = length >> PAGE_SHIFT;
@@ -2488,9 +2548,6 @@ static void gen8_ggtt_clear_range(struct
 		(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
 	const int max_entries = ggtt_total_entries(ggtt) - first_entry;
 	int i;
-	int rpm_atomic_seq;
-
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	if (WARN(num_entries > max_entries,
 		 "First entry = %d; Num entries = %d (max=%d)\n",
@@ -2498,21 +2555,16 @@ static void gen8_ggtt_clear_range(struct
 		num_entries = max_entries;
 
 	scratch_pte = gen8_pte_encode(vm->scratch_page.daddr,
-				      I915_CACHE_LLC,
-				      use_scratch);
+				      I915_CACHE_LLC);
 	for (i = 0; i < num_entries; i++)
 		gen8_set_pte(&gtt_base[i], scratch_pte);
 	readl(gtt_base);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void gen6_ggtt_clear_range(struct i915_address_space *vm,
 				  uint64_t start,
-				  uint64_t length,
-				  bool use_scratch)
+				  uint64_t length)
 {
-	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
 	unsigned first_entry = start >> PAGE_SHIFT;
 	unsigned num_entries = length >> PAGE_SHIFT;
@@ -2520,9 +2572,6 @@ static void gen6_ggtt_clear_range(struct
 		(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
 	const int max_entries = ggtt_total_entries(ggtt) - first_entry;
 	int i;
-	int rpm_atomic_seq;
-
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	if (WARN(num_entries > max_entries,
 		 "First entry = %d; Num entries = %d (max=%d)\n",
@@ -2530,13 +2579,11 @@ static void gen6_ggtt_clear_range(struct
 		num_entries = max_entries;
 
 	scratch_pte = vm->pte_encode(vm->scratch_page.daddr,
-				     I915_CACHE_LLC, use_scratch, 0);
+				     I915_CACHE_LLC, 0);
 
 	for (i = 0; i < num_entries; i++)
 		iowrite32(scratch_pte, &gtt_base[i]);
 	readl(gtt_base);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void i915_ggtt_insert_page(struct i915_address_space *vm,
@@ -2545,16 +2592,10 @@ static void i915_ggtt_insert_page(struct
 				  enum i915_cache_level cache_level,
 				  u32 unused)
 {
-	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	unsigned int flags = (cache_level == I915_CACHE_NONE) ?
 		AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
-	int rpm_atomic_seq;
-
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	intel_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void i915_ggtt_insert_entries(struct i915_address_space *vm,
@@ -2562,40 +2603,25 @@ static void i915_ggtt_insert_entries(str
 				     uint64_t start,
 				     enum i915_cache_level cache_level, u32 unused)
 {
-	struct drm_i915_private *dev_priv = to_i915(vm->dev);
 	unsigned int flags = (cache_level == I915_CACHE_NONE) ?
 		AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
-	int rpm_atomic_seq;
-
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
 	intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
 
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
-
 }
 
 static void i915_ggtt_clear_range(struct i915_address_space *vm,
 				  uint64_t start,
-				  uint64_t length,
-				  bool unused)
+				  uint64_t length)
 {
-	struct drm_i915_private *dev_priv = to_i915(vm->dev);
-	unsigned first_entry = start >> PAGE_SHIFT;
-	unsigned num_entries = length >> PAGE_SHIFT;
-	int rpm_atomic_seq;
-
-	rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
-	intel_gtt_clear_range(first_entry, num_entries);
-
-	assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
+	intel_gtt_clear_range(start >> PAGE_SHIFT, length >> PAGE_SHIFT);
 }
 
 static int ggtt_bind_vma(struct i915_vma *vma,
 			 enum i915_cache_level cache_level,
 			 u32 flags)
 {
+	struct drm_i915_private *i915 = to_i915(vma->vm->dev);
 	struct drm_i915_gem_object *obj = vma->obj;
 	u32 pte_flags = 0;
 	int ret;
@@ -2608,8 +2634,10 @@ static int ggtt_bind_vma(struct i915_vma
 	if (obj->gt_ro)
 		pte_flags |= PTE_READ_ONLY;
 
+	intel_runtime_pm_get(i915);
 	vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start,
 				cache_level, pte_flags);
+	intel_runtime_pm_put(i915);
 
 	/*
 	 * Without aliasing PPGTT there's no difference between
@@ -2625,6 +2653,7 @@ static int aliasing_gtt_bind_vma(struct
 				 enum i915_cache_level cache_level,
 				 u32 flags)
 {
+	struct drm_i915_private *i915 = to_i915(vma->vm->dev);
 	u32 pte_flags;
 	int ret;
 
@@ -2639,14 +2668,15 @@ static int aliasing_gtt_bind_vma(struct
 
 
 	if (flags & I915_VMA_GLOBAL_BIND) {
+		intel_runtime_pm_get(i915);
 		vma->vm->insert_entries(vma->vm,
 					vma->pages, vma->node.start,
 					cache_level, pte_flags);
+		intel_runtime_pm_put(i915);
 	}
 
 	if (flags & I915_VMA_LOCAL_BIND) {
-		struct i915_hw_ppgtt *appgtt =
-			to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+		struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt;
 		appgtt->base.insert_entries(&appgtt->base,
 					    vma->pages, vma->node.start,
 					    cache_level, pte_flags);
@@ -2657,21 +2687,24 @@ static int aliasing_gtt_bind_vma(struct
 
 static void ggtt_unbind_vma(struct i915_vma *vma)
 {
-	struct i915_hw_ppgtt *appgtt = to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+	struct drm_i915_private *i915 = to_i915(vma->vm->dev);
+	struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt;
 	const u64 size = min(vma->size, vma->node.size);
 
-	if (vma->flags & I915_VMA_GLOBAL_BIND)
+	if (vma->flags & I915_VMA_GLOBAL_BIND) {
+		intel_runtime_pm_get(i915);
 		vma->vm->clear_range(vma->vm,
-				     vma->node.start, size,
-				     true);
+				     vma->node.start, size);
+		intel_runtime_pm_put(i915);
+	}
 
 	if (vma->flags & I915_VMA_LOCAL_BIND && appgtt)
 		appgtt->base.clear_range(&appgtt->base,
-					 vma->node.start, size,
-					 true);
+					 vma->node.start, size);
 }
 
-void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj)
+void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
+			       struct sg_table *pages)
 {
 	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
 	struct device *kdev = &dev_priv->drm.pdev->dev;
@@ -2685,8 +2718,7 @@ void i915_gem_gtt_finish_object(struct d
 		}
 	}
 
-	dma_unmap_sg(kdev, obj->pages->sgl, obj->pages->nents,
-		     PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL);
 }
 
 static void i915_gtt_color_adjust(struct drm_mm_node *node,
@@ -2717,6 +2749,7 @@ int i915_gem_init_ggtt(struct drm_i915_p
 	 */
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned long hole_start, hole_end;
+	struct i915_hw_ppgtt *ppgtt;
 	struct drm_mm_node *entry;
 	int ret;
 
@@ -2724,45 +2757,48 @@ int i915_gem_init_ggtt(struct drm_i915_p
 	if (ret)
 		return ret;
 
+	/* Reserve a mappable slot for our lockless error capture */
+	ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
+						  &ggtt->error_capture,
+						  4096, 0, -1,
+						  0, ggtt->mappable_end,
+						  0, 0);
+	if (ret)
+		return ret;
+
 	/* Clear any non-preallocated blocks */
 	drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
 		DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
 			      hole_start, hole_end);
 		ggtt->base.clear_range(&ggtt->base, hole_start,
-				     hole_end - hole_start, true);
+				       hole_end - hole_start);
 	}
 
 	/* And finally clear the reserved guard page */
 	ggtt->base.clear_range(&ggtt->base,
-			       ggtt->base.total - PAGE_SIZE, PAGE_SIZE,
-			       true);
+			       ggtt->base.total - PAGE_SIZE, PAGE_SIZE);
 
 	if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) {
-		struct i915_hw_ppgtt *ppgtt;
-
 		ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
-		if (!ppgtt)
-			return -ENOMEM;
+		if (!ppgtt) {
+			ret = -ENOMEM;
+			goto err;
+		}
 
 		ret = __hw_ppgtt_init(ppgtt, dev_priv);
-		if (ret) {
-			kfree(ppgtt);
-			return ret;
-		}
+		if (ret)
+			goto err_ppgtt;
 
-		if (ppgtt->base.allocate_va_range)
+		if (ppgtt->base.allocate_va_range) {
 			ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0,
 							    ppgtt->base.total);
-		if (ret) {
-			ppgtt->base.cleanup(&ppgtt->base);
-			kfree(ppgtt);
-			return ret;
+			if (ret)
+				goto err_ppgtt_cleanup;
 		}
 
 		ppgtt->base.clear_range(&ppgtt->base,
 					ppgtt->base.start,
-					ppgtt->base.total,
-					true);
+					ppgtt->base.total);
 
 		dev_priv->mm.aliasing_ppgtt = ppgtt;
 		WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma);
@@ -2770,6 +2806,14 @@ int i915_gem_init_ggtt(struct drm_i915_p
 	}
 
 	return 0;
+
+err_ppgtt_cleanup:
+	ppgtt->base.cleanup(&ppgtt->base);
+err_ppgtt:
+	kfree(ppgtt);
+err:
+	drm_mm_remove_node(&ggtt->error_capture);
+	return ret;
 }
 
 /**
@@ -2788,11 +2832,15 @@ void i915_ggtt_cleanup_hw(struct drm_i91
 
 	i915_gem_cleanup_stolen(&dev_priv->drm);
 
+	if (drm_mm_node_allocated(&ggtt->error_capture))
+		drm_mm_remove_node(&ggtt->error_capture);
+
 	if (drm_mm_initialized(&ggtt->base.mm)) {
 		intel_vgt_deballoon(dev_priv);
 
-		drm_mm_takedown(&ggtt->base.mm);
-		list_del(&ggtt->base.global_link);
+		mutex_lock(&dev_priv->drm.struct_mutex);
+		i915_address_space_fini(&ggtt->base);
+		mutex_unlock(&dev_priv->drm.struct_mutex);
 	}
 
 	ggtt->base.cleanup(&ggtt->base);
@@ -2881,6 +2929,7 @@ static size_t gen9_get_stolen_size(u16 g
 
 static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
 {
+	struct drm_i915_private *dev_priv = to_i915(ggtt->base.dev);
 	struct pci_dev *pdev = ggtt->base.dev->pdev;
 	phys_addr_t phys_addr;
 	int ret;
@@ -2895,7 +2944,7 @@ static int ggtt_probe_common(struct i915
 	 * resort to an uncached mapping. The WC issue is easily caught by the
 	 * readback check when writing GTT PTE entries.
 	 */
-	if (IS_BROXTON(ggtt->base.dev))
+	if (IS_BROXTON(dev_priv))
 		ggtt->gsm = ioremap_nocache(phys_addr, size);
 	else
 		ggtt->gsm = ioremap_wc(phys_addr, size);
@@ -2904,9 +2953,7 @@ static int ggtt_probe_common(struct i915
 		return -ENOMEM;
 	}
 
-	ret = setup_scratch_page(ggtt->base.dev,
-				 &ggtt->base.scratch_page,
-				 GFP_DMA32);
+	ret = setup_scratch_page(dev_priv, &ggtt->base.scratch_page, GFP_DMA32);
 	if (ret) {
 		DRM_ERROR("Scratch setup failed\n");
 		/* iounmap will also get called at remove, but meh */
@@ -2995,7 +3042,7 @@ static void gen6_gmch_remove(struct i915
 	struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
 
 	iounmap(ggtt->gsm);
-	cleanup_scratch_page(vm->dev, &vm->scratch_page);
+	cleanup_scratch_page(to_i915(vm->dev), &vm->scratch_page);
 }
 
 static int gen8_gmch_probe(struct i915_ggtt *ggtt)
@@ -3190,11 +3237,13 @@ int i915_ggtt_init_hw(struct drm_i915_pr
 	/* Subtract the guard page before address space initialization to
 	 * shrink the range used by drm_mm.
 	 */
+	mutex_lock(&dev_priv->drm.struct_mutex);
 	ggtt->base.total -= PAGE_SIZE;
-	i915_address_space_init(&ggtt->base, dev_priv);
+	i915_address_space_init(&ggtt->base, dev_priv, "[global]");
 	ggtt->base.total += PAGE_SIZE;
 	if (!HAS_LLC(dev_priv))
 		ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
+	mutex_unlock(&dev_priv->drm.struct_mutex);
 
 	if (!io_mapping_init_wc(&dev_priv->ggtt.mappable,
 				dev_priv->ggtt.mappable_base,
@@ -3209,7 +3258,7 @@ int i915_ggtt_init_hw(struct drm_i915_pr
 	 * Initialise stolen early so that we may reserve preallocated
 	 * objects for the BIOS to KMS transition.
 	 */
-	ret = i915_gem_init_stolen(&dev_priv->drm);
+	ret = i915_gem_init_stolen(dev_priv);
 	if (ret)
 		goto out_gtt_cleanup;
 
@@ -3228,23 +3277,21 @@ int i915_ggtt_enable_hw(struct drm_i915_
 	return 0;
 }
 
-void i915_gem_restore_gtt_mappings(struct drm_device *dev)
+void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct drm_i915_gem_object *obj, *on;
 
 	i915_check_and_clear_faults(dev_priv);
 
 	/* First fill our portion of the GTT with scratch pages */
-	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
-			       true);
+	ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total);
 
 	ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */
 
 	/* clflush objects bound into the GGTT and rebind them. */
 	list_for_each_entry_safe(obj, on,
-				 &dev_priv->mm.bound_list, global_list) {
+				 &dev_priv->mm.bound_list, global_link) {
 		bool ggtt_bound = false;
 		struct i915_vma *vma;
 
@@ -3266,8 +3313,8 @@ void i915_gem_restore_gtt_mappings(struc
 
 	ggtt->base.closed = false;
 
-	if (INTEL_INFO(dev)->gen >= 8) {
-		if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev))
+	if (INTEL_GEN(dev_priv) >= 8) {
+		if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv))
 			chv_setup_private_ppat(dev_priv);
 		else
 			bdw_setup_private_ppat(dev_priv);
@@ -3275,7 +3322,7 @@ void i915_gem_restore_gtt_mappings(struc
 		return;
 	}
 
-	if (USES_PPGTT(dev)) {
+	if (USES_PPGTT(dev_priv)) {
 		struct i915_address_space *vm;
 
 		list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
@@ -3296,137 +3343,28 @@ void i915_gem_restore_gtt_mappings(struc
 	i915_ggtt_flush(dev_priv);
 }
 
-static void
-i915_vma_retire(struct i915_gem_active *active,
-		struct drm_i915_gem_request *rq)
-{
-	const unsigned int idx = rq->engine->id;
-	struct i915_vma *vma =
-		container_of(active, struct i915_vma, last_read[idx]);
-
-	GEM_BUG_ON(!i915_vma_has_active_engine(vma, idx));
-
-	i915_vma_clear_active(vma, idx);
-	if (i915_vma_is_active(vma))
-		return;
-
-	list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
-	if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma)))
-		WARN_ON(i915_vma_unbind(vma));
-}
-
-void i915_vma_destroy(struct i915_vma *vma)
-{
-	GEM_BUG_ON(vma->node.allocated);
-	GEM_BUG_ON(i915_vma_is_active(vma));
-	GEM_BUG_ON(!i915_vma_is_closed(vma));
-	GEM_BUG_ON(vma->fence);
-
-	list_del(&vma->vm_link);
-	if (!i915_vma_is_ggtt(vma))
-		i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm));
-
-	kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
-}
-
-void i915_vma_close(struct i915_vma *vma)
-{
-	GEM_BUG_ON(i915_vma_is_closed(vma));
-	vma->flags |= I915_VMA_CLOSED;
-
-	list_del_init(&vma->obj_link);
-	if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma))
-		WARN_ON(i915_vma_unbind(vma));
-}
-
-static struct i915_vma *
-__i915_vma_create(struct drm_i915_gem_object *obj,
-		  struct i915_address_space *vm,
-		  const struct i915_ggtt_view *view)
-{
-	struct i915_vma *vma;
-	int i;
-
-	GEM_BUG_ON(vm->closed);
-
-	vma = kmem_cache_zalloc(to_i915(obj->base.dev)->vmas, GFP_KERNEL);
-	if (vma == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	INIT_LIST_HEAD(&vma->exec_list);
-	for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
-		init_request_active(&vma->last_read[i], i915_vma_retire);
-	init_request_active(&vma->last_fence, NULL);
-	list_add(&vma->vm_link, &vm->unbound_list);
-	vma->vm = vm;
-	vma->obj = obj;
-	vma->size = obj->base.size;
-
-	if (view) {
-		vma->ggtt_view = *view;
-		if (view->type == I915_GGTT_VIEW_PARTIAL) {
-			vma->size = view->params.partial.size;
-			vma->size <<= PAGE_SHIFT;
-		} else if (view->type == I915_GGTT_VIEW_ROTATED) {
-			vma->size =
-				intel_rotation_info_size(&view->params.rotated);
-			vma->size <<= PAGE_SHIFT;
-		}
-	}
-
-	if (i915_is_ggtt(vm)) {
-		vma->flags |= I915_VMA_GGTT;
-	} else {
-		i915_ppgtt_get(i915_vm_to_ppgtt(vm));
-	}
-
-	list_add_tail(&vma->obj_link, &obj->vma_list);
-	return vma;
-}
-
-static inline bool vma_matches(struct i915_vma *vma,
-			       struct i915_address_space *vm,
-			       const struct i915_ggtt_view *view)
-{
-	if (vma->vm != vm)
-		return false;
-
-	if (!i915_vma_is_ggtt(vma))
-		return true;
-
-	if (!view)
-		return vma->ggtt_view.type == 0;
-
-	if (vma->ggtt_view.type != view->type)
-		return false;
-
-	return memcmp(&vma->ggtt_view.params,
-		      &view->params,
-		      sizeof(view->params)) == 0;
-}
-
-struct i915_vma *
-i915_vma_create(struct drm_i915_gem_object *obj,
-		struct i915_address_space *vm,
-		const struct i915_ggtt_view *view)
-{
-	GEM_BUG_ON(view && !i915_is_ggtt(vm));
-	GEM_BUG_ON(i915_gem_obj_to_vma(obj, vm, view));
-
-	return __i915_vma_create(obj, vm, view);
-}
-
 struct i915_vma *
 i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
 		    struct i915_address_space *vm,
 		    const struct i915_ggtt_view *view)
 {
-	struct i915_vma *vma;
+	struct rb_node *rb;
 
-	list_for_each_entry_reverse(vma, &obj->vma_list, obj_link)
-		if (vma_matches(vma, vm, view))
+	rb = obj->vma_tree.rb_node;
+	while (rb) {
+		struct i915_vma *vma = rb_entry(rb, struct i915_vma, obj_node);
+		long cmp;
+
+		cmp = i915_vma_compare(vma, vm, view);
+		if (cmp == 0)
 			return vma;
 
+		if (cmp < 0)
+			rb = rb->rb_right;
+		else
+			rb = rb->rb_left;
+	}
+
 	return NULL;
 }
 
@@ -3437,11 +3375,14 @@ i915_gem_obj_lookup_or_create_vma(struct
 {
 	struct i915_vma *vma;
 
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
 	GEM_BUG_ON(view && !i915_is_ggtt(vm));
 
 	vma = i915_gem_obj_to_vma(obj, vm, view);
-	if (!vma)
-		vma = __i915_vma_create(obj, vm, view);
+	if (!vma) {
+		vma = i915_vma_create(obj, vm, view);
+		GEM_BUG_ON(vma != i915_gem_obj_to_vma(obj, vm, view));
+	}
 
 	GEM_BUG_ON(i915_vma_is_closed(vma));
 	return vma;
@@ -3507,7 +3448,7 @@ intel_rotate_fb_obj_pages(const struct i
 
 	/* Populate source page list from the object. */
 	i = 0;
-	for_each_sgt_dma(dma_addr, sgt_iter, obj->pages)
+	for_each_sgt_dma(dma_addr, sgt_iter, obj->mm.pages)
 		page_addr_list[i++] = dma_addr;
 
 	GEM_BUG_ON(i != n_pages);
@@ -3543,35 +3484,47 @@ intel_partial_pages(const struct i915_gg
 		    struct drm_i915_gem_object *obj)
 {
 	struct sg_table *st;
-	struct scatterlist *sg;
-	struct sg_page_iter obj_sg_iter;
+	struct scatterlist *sg, *iter;
+	unsigned int count = view->params.partial.size;
+	unsigned int offset;
 	int ret = -ENOMEM;
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st)
 		goto err_st_alloc;
 
-	ret = sg_alloc_table(st, view->params.partial.size, GFP_KERNEL);
+	ret = sg_alloc_table(st, count, GFP_KERNEL);
 	if (ret)
 		goto err_sg_alloc;
 
+	iter = i915_gem_object_get_sg(obj,
+				      view->params.partial.offset,
+				      &offset);
+	GEM_BUG_ON(!iter);
+
 	sg = st->sgl;
 	st->nents = 0;
-	for_each_sg_page(obj->pages->sgl, &obj_sg_iter, obj->pages->nents,
-		view->params.partial.offset)
-	{
-		if (st->nents >= view->params.partial.size)
-			break;
+	do {
+		unsigned int len;
 
-		sg_set_page(sg, NULL, PAGE_SIZE, 0);
-		sg_dma_address(sg) = sg_page_iter_dma_address(&obj_sg_iter);
-		sg_dma_len(sg) = PAGE_SIZE;
+		len = min(iter->length - (offset << PAGE_SHIFT),
+			  count << PAGE_SHIFT);
+		sg_set_page(sg, NULL, len, 0);
+		sg_dma_address(sg) =
+			sg_dma_address(iter) + (offset << PAGE_SHIFT);
+		sg_dma_len(sg) = len;
 
-		sg = sg_next(sg);
 		st->nents++;
-	}
+		count -= len >> PAGE_SHIFT;
+		if (count == 0) {
+			sg_mark_end(sg);
+			return st;
+		}
 
-	return st;
+		sg = __sg_next(sg);
+		iter = __sg_next(iter);
+		offset = 0;
+	} while (1);
 
 err_sg_alloc:
 	kfree(st);
@@ -3584,11 +3537,18 @@ i915_get_ggtt_vma_pages(struct i915_vma
 {
 	int ret = 0;
 
+	/* The vma->pages are only valid within the lifespan of the borrowed
+	 * obj->mm.pages. When the obj->mm.pages sg_table is regenerated, so
+	 * must be the vma->pages. A simple rule is that vma->pages must only
+	 * be accessed when the obj->mm.pages are pinned.
+	 */
+	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj));
+
 	if (vma->pages)
 		return 0;
 
 	if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
-		vma->pages = vma->obj->pages;
+		vma->pages = vma->obj->mm.pages;
 	else if (vma->ggtt_view.type == I915_GGTT_VIEW_ROTATED)
 		vma->pages =
 			intel_rotate_fb_obj_pages(&vma->ggtt_view.params.rotated, vma->obj);
@@ -3612,94 +3572,3 @@ i915_get_ggtt_vma_pages(struct i915_vma
 	return ret;
 }
 
-/**
- * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
- * @vma: VMA to map
- * @cache_level: mapping cache level
- * @flags: flags like global or local mapping
- *
- * DMA addresses are taken from the scatter-gather table of this object (or of
- * this VMA in case of non-default GGTT views) and PTE entries set up.
- * Note that DMA addresses are also the only part of the SG table we care about.
- */
-int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
-		  u32 flags)
-{
-	u32 bind_flags;
-	u32 vma_flags;
-	int ret;
-
-	if (WARN_ON(flags == 0))
-		return -EINVAL;
-
-	bind_flags = 0;
-	if (flags & PIN_GLOBAL)
-		bind_flags |= I915_VMA_GLOBAL_BIND;
-	if (flags & PIN_USER)
-		bind_flags |= I915_VMA_LOCAL_BIND;
-
-	vma_flags = vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
-	if (flags & PIN_UPDATE)
-		bind_flags |= vma_flags;
-	else
-		bind_flags &= ~vma_flags;
-	if (bind_flags == 0)
-		return 0;
-
-	if (vma_flags == 0 && vma->vm->allocate_va_range) {
-		trace_i915_va_alloc(vma);
-		ret = vma->vm->allocate_va_range(vma->vm,
-						 vma->node.start,
-						 vma->node.size);
-		if (ret)
-			return ret;
-	}
-
-	ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
-	if (ret)
-		return ret;
-
-	vma->flags |= bind_flags;
-	return 0;
-}
-
-void __iomem *i915_vma_pin_iomap(struct i915_vma *vma)
-{
-	void __iomem *ptr;
-
-	/* Access through the GTT requires the device to be awake. */
-	assert_rpm_wakelock_held(to_i915(vma->vm->dev));
-
-	lockdep_assert_held(&vma->vm->dev->struct_mutex);
-	if (WARN_ON(!i915_vma_is_map_and_fenceable(vma)))
-		return IO_ERR_PTR(-ENODEV);
-
-	GEM_BUG_ON(!i915_vma_is_ggtt(vma));
-	GEM_BUG_ON((vma->flags & I915_VMA_GLOBAL_BIND) == 0);
-
-	ptr = vma->iomap;
-	if (ptr == NULL) {
-		ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->mappable,
-					vma->node.start,
-					vma->node.size);
-		if (ptr == NULL)
-			return IO_ERR_PTR(-ENOMEM);
-
-		vma->iomap = ptr;
-	}
-
-	__i915_vma_pin(vma);
-	return ptr;
-}
-
-void i915_vma_unpin_and_release(struct i915_vma **p_vma)
-{
-	struct i915_vma *vma;
-
-	vma = fetch_and_zero(p_vma);
-	if (!vma)
-		return;
-
-	i915_vma_unpin(vma);
-	i915_vma_put(vma);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_gtt.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,9 @@
 #define __I915_GEM_GTT_H__
 
 #include <linux/io-mapping.h>
+#include <linux/mm.h>
 
+#include "i915_gem_timeline.h"
 #include "i915_gem_request.h"
 
 #define I915_FENCE_REG_NONE -1
@@ -118,8 +120,8 @@ typedef uint64_t gen8_ppgtt_pml4e_t;
 #define GEN8_LEGACY_PDPES		4
 #define GEN8_PTES			I915_PTES(sizeof(gen8_pte_t))
 
-#define I915_PDPES_PER_PDP(dev) (USES_FULL_48BIT_PPGTT(dev) ?\
-				 GEN8_PML4ES_PER_PML4 : GEN8_LEGACY_PDPES)
+#define I915_PDPES_PER_PDP(dev_priv)	(USES_FULL_48BIT_PPGTT(dev_priv) ?\
+					GEN8_PML4ES_PER_PML4 : GEN8_LEGACY_PDPES)
 
 #define PPAT_UNCACHED_INDEX		(_PAGE_PWT | _PAGE_PCD)
 #define PPAT_CACHED_PDE_INDEX		0 /* WB LLC */
@@ -138,6 +140,8 @@ typedef uint64_t gen8_ppgtt_pml4e_t;
 #define GEN8_PPAT_ELLC_OVERRIDE		(0<<2)
 #define GEN8_PPAT(i, x)			((uint64_t) (x) << ((i) * 8))
 
+struct sg_table;
+
 enum i915_ggtt_view_type {
 	I915_GGTT_VIEW_NORMAL = 0,
 	I915_GGTT_VIEW_ROTATED,
@@ -168,133 +172,7 @@ extern const struct i915_ggtt_view i915_
 
 enum i915_cache_level;
 
-/**
- * A VMA represents a GEM BO that is bound into an address space. Therefore, a
- * VMA's presence cannot be guaranteed before binding, or after unbinding the
- * object into/from the address space.
- *
- * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
- * will always be <= an objects lifetime. So object refcounting should cover us.
- */
-struct i915_vma {
-	struct drm_mm_node node;
-	struct drm_i915_gem_object *obj;
-	struct i915_address_space *vm;
-	struct drm_i915_fence_reg *fence;
-	struct sg_table *pages;
-	void __iomem *iomap;
-	u64 size;
-	u64 display_alignment;
-
-	unsigned int flags;
-	/**
-	 * How many users have pinned this object in GTT space. The following
-	 * users can each hold at most one reference: pwrite/pread, execbuffer
-	 * (objects are not allowed multiple times for the same batchbuffer),
-	 * and the framebuffer code. When switching/pageflipping, the
-	 * framebuffer code has at most two buffers pinned per crtc.
-	 *
-	 * 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.
-	 */
-#define I915_VMA_PIN_MASK 0xf
-#define I915_VMA_PIN_OVERFLOW	BIT(5)
-
-	/** Flags and address space this VMA is bound to */
-#define I915_VMA_GLOBAL_BIND	BIT(6)
-#define I915_VMA_LOCAL_BIND	BIT(7)
-#define I915_VMA_BIND_MASK (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND | I915_VMA_PIN_OVERFLOW)
-
-#define I915_VMA_GGTT		BIT(8)
-#define I915_VMA_CAN_FENCE	BIT(9)
-#define I915_VMA_CLOSED		BIT(10)
-
-	unsigned int active;
-	struct i915_gem_active last_read[I915_NUM_ENGINES];
-	struct i915_gem_active last_fence;
-
-	/**
-	 * Support different GGTT views into the same object.
-	 * This means there can be multiple VMA mappings per object and per VM.
-	 * i915_ggtt_view_type is used to distinguish between those entries.
-	 * The default one of zero (I915_GGTT_VIEW_NORMAL) is default and also
-	 * assumed in GEM functions which take no ggtt view parameter.
-	 */
-	struct i915_ggtt_view ggtt_view;
-
-	/** This object's place on the active/inactive lists */
-	struct list_head vm_link;
-
-	struct list_head obj_link; /* Link in the object's VMA list */
-
-	/** This vma's place in the batchbuffer or on the eviction list */
-	struct list_head exec_list;
-
-	/**
-	 * Used for performing relocations during execbuffer insertion.
-	 */
-	struct hlist_node exec_node;
-	unsigned long exec_handle;
-	struct drm_i915_gem_exec_object2 *exec_entry;
-};
-
-struct i915_vma *
-i915_vma_create(struct drm_i915_gem_object *obj,
-		struct i915_address_space *vm,
-		const struct i915_ggtt_view *view);
-void i915_vma_unpin_and_release(struct i915_vma **p_vma);
-
-static inline bool i915_vma_is_ggtt(const struct i915_vma *vma)
-{
-	return vma->flags & I915_VMA_GGTT;
-}
-
-static inline bool i915_vma_is_map_and_fenceable(const struct i915_vma *vma)
-{
-	return vma->flags & I915_VMA_CAN_FENCE;
-}
-
-static inline bool i915_vma_is_closed(const struct i915_vma *vma)
-{
-	return vma->flags & I915_VMA_CLOSED;
-}
-
-static inline unsigned int i915_vma_get_active(const struct i915_vma *vma)
-{
-	return vma->active;
-}
-
-static inline bool i915_vma_is_active(const struct i915_vma *vma)
-{
-	return i915_vma_get_active(vma);
-}
-
-static inline void i915_vma_set_active(struct i915_vma *vma,
-				       unsigned int engine)
-{
-	vma->active |= BIT(engine);
-}
-
-static inline void i915_vma_clear_active(struct i915_vma *vma,
-					 unsigned int engine)
-{
-	vma->active &= ~BIT(engine);
-}
-
-static inline bool i915_vma_has_active_engine(const struct i915_vma *vma,
-					      unsigned int engine)
-{
-	return vma->active & BIT(engine);
-}
-
-static inline u32 i915_ggtt_offset(const struct i915_vma *vma)
-{
-	GEM_BUG_ON(!i915_vma_is_ggtt(vma));
-	GEM_BUG_ON(!vma->node.allocated);
-	GEM_BUG_ON(upper_32_bits(vma->node.start));
-	GEM_BUG_ON(upper_32_bits(vma->node.start + vma->node.size - 1));
-	return lower_32_bits(vma->node.start);
-}
+struct i915_vma;
 
 struct i915_page_dma {
 	struct page *page;
@@ -341,6 +219,7 @@ struct i915_pml4 {
 
 struct i915_address_space {
 	struct drm_mm mm;
+	struct i915_gem_timeline timeline;
 	struct drm_device *dev;
 	/* Every address space belongs to a struct file - except for the global
 	 * GTT that is owned by the driver (and so @file is set to NULL). In
@@ -395,7 +274,7 @@ struct i915_address_space {
 	/* FIXME: Need a more generic return type */
 	gen6_pte_t (*pte_encode)(dma_addr_t addr,
 				 enum i915_cache_level level,
-				 bool valid, u32 flags); /* Create a valid PTE */
+				 u32 flags); /* Create a valid PTE */
 	/* flags for pte_encode */
 #define PTE_READ_ONLY	(1<<0)
 	int (*allocate_va_range)(struct i915_address_space *vm,
@@ -403,8 +282,7 @@ struct i915_address_space {
 				 uint64_t length);
 	void (*clear_range)(struct i915_address_space *vm,
 			    uint64_t start,
-			    uint64_t length,
-			    bool use_scratch);
+			    uint64_t length);
 	void (*insert_page)(struct i915_address_space *vm,
 			    dma_addr_t addr,
 			    uint64_t offset,
@@ -450,6 +328,8 @@ struct i915_ggtt {
 	bool do_idle_maps;
 
 	int mtrr;
+
+	struct drm_mm_node error_capture;
 };
 
 struct i915_hw_ppgtt {
@@ -602,16 +482,24 @@ i915_page_dir_dma_addr(const struct i915
 		px_dma(ppgtt->base.scratch_pd);
 }
 
+static inline struct i915_ggtt *
+i915_vm_to_ggtt(struct i915_address_space *vm)
+{
+	GEM_BUG_ON(!i915_is_ggtt(vm));
+	return container_of(vm, struct i915_ggtt, base);
+}
+
 int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv);
 int i915_ggtt_init_hw(struct drm_i915_private *dev_priv);
 int i915_ggtt_enable_hw(struct drm_i915_private *dev_priv);
 int i915_gem_init_ggtt(struct drm_i915_private *dev_priv);
 void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv);
 
-int i915_ppgtt_init_hw(struct drm_device *dev);
+int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv);
 void i915_ppgtt_release(struct kref *kref);
 struct i915_hw_ppgtt *i915_ppgtt_create(struct drm_i915_private *dev_priv,
-					struct drm_i915_file_private *fpriv);
+					struct drm_i915_file_private *fpriv,
+					const char *name);
 static inline void i915_ppgtt_get(struct i915_hw_ppgtt *ppgtt)
 {
 	if (ppgtt)
@@ -624,11 +512,13 @@ static inline void i915_ppgtt_put(struct
 }
 
 void i915_check_and_clear_faults(struct drm_i915_private *dev_priv);
-void i915_gem_suspend_gtt_mappings(struct drm_device *dev);
-void i915_gem_restore_gtt_mappings(struct drm_device *dev);
+void i915_gem_suspend_gtt_mappings(struct drm_i915_private *dev_priv);
+void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv);
 
-int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj);
-void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj);
+int __must_check i915_gem_gtt_prepare_pages(struct drm_i915_gem_object *obj,
+					    struct sg_table *pages);
+void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj,
+			       struct sg_table *pages);
 
 /* Flags used by pin/bind&friends. */
 #define PIN_NONBLOCK		BIT(0)
@@ -646,88 +536,4 @@ void i915_gem_gtt_finish_object(struct d
 #define PIN_OFFSET_FIXED	BIT(11)
 #define PIN_OFFSET_MASK		(~4095)
 
-int __i915_vma_do_pin(struct i915_vma *vma,
-		      u64 size, u64 alignment, u64 flags);
-static inline int __must_check
-i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
-{
-	BUILD_BUG_ON(PIN_MBZ != I915_VMA_PIN_OVERFLOW);
-	BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND);
-	BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND);
-
-	/* Pin early to prevent the shrinker/eviction logic from destroying
-	 * our vma as we insert and bind.
-	 */
-	if (likely(((++vma->flags ^ flags) & I915_VMA_BIND_MASK) == 0))
-		return 0;
-
-	return __i915_vma_do_pin(vma, size, alignment, flags);
-}
-
-static inline int i915_vma_pin_count(const struct i915_vma *vma)
-{
-	return vma->flags & I915_VMA_PIN_MASK;
-}
-
-static inline bool i915_vma_is_pinned(const struct i915_vma *vma)
-{
-	return i915_vma_pin_count(vma);
-}
-
-static inline void __i915_vma_pin(struct i915_vma *vma)
-{
-	vma->flags++;
-	GEM_BUG_ON(vma->flags & I915_VMA_PIN_OVERFLOW);
-}
-
-static inline void __i915_vma_unpin(struct i915_vma *vma)
-{
-	GEM_BUG_ON(!i915_vma_is_pinned(vma));
-	vma->flags--;
-}
-
-static inline void i915_vma_unpin(struct i915_vma *vma)
-{
-	GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
-	__i915_vma_unpin(vma);
-}
-
-/**
- * i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture
- * @vma: VMA to iomap
- *
- * The passed in VMA has to be pinned in the global GTT mappable region.
- * An extra pinning of the VMA is acquired for the return iomapping,
- * the caller must call i915_vma_unpin_iomap to relinquish the pinning
- * after the iomapping is no longer required.
- *
- * Callers must hold the struct_mutex.
- *
- * Returns a valid iomapped pointer or ERR_PTR.
- */
-void __iomem *i915_vma_pin_iomap(struct i915_vma *vma);
-#define IO_ERR_PTR(x) ((void __iomem *)ERR_PTR(x))
-
-/**
- * i915_vma_unpin_iomap - unpins the mapping returned from i915_vma_iomap
- * @vma: VMA to unpin
- *
- * Unpins the previously iomapped VMA from i915_vma_pin_iomap().
- *
- * Callers must hold the struct_mutex. This function is only valid to be
- * called on a VMA previously iomapped by the caller with i915_vma_pin_iomap().
- */
-static inline void i915_vma_unpin_iomap(struct i915_vma *vma)
-{
-	lockdep_assert_held(&vma->vm->dev->struct_mutex);
-	GEM_BUG_ON(vma->iomap == NULL);
-	i915_vma_unpin(vma);
-}
-
-static inline struct page *i915_vma_first_page(struct i915_vma *vma)
-{
-	GEM_BUG_ON(!vma->pages);
-	return sg_page(vma->pages->sgl);
-}
-
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem.h	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,9 @@
 #ifdef CONFIG_DRM_I915_DEBUG_GEM
 #define GEM_BUG_ON(expr) BUG_ON(expr)
 #else
-#define GEM_BUG_ON(expr)
+#define GEM_BUG_ON(expr) do { } while (0)
 #endif
 
+#define I915_NUM_ENGINES 5
+
 #endif /* __I915_GEM_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_internal.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_internal.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_internal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_internal.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,178 @@
+/*
+ * Copyright © 2014-2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/i915_drm.h>
+#include "i915_drv.h"
+
+#define QUIET (__GFP_NORETRY | __GFP_NOWARN)
+
+/* convert swiotlb segment size into sensible units (pages)! */
+#define IO_TLB_SEGPAGES (IO_TLB_SEGSIZE << IO_TLB_SHIFT >> PAGE_SHIFT)
+
+static void internal_free_pages(struct sg_table *st)
+{
+	struct scatterlist *sg;
+
+	for (sg = st->sgl; sg; sg = __sg_next(sg))
+		__free_pages(sg_page(sg), get_order(sg->length));
+
+	sg_free_table(st);
+	kfree(st);
+}
+
+static struct sg_table *
+i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	unsigned int npages = obj->base.size / PAGE_SIZE;
+	struct sg_table *st;
+	struct scatterlist *sg;
+	int max_order;
+	gfp_t gfp;
+
+	st = kmalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return ERR_PTR(-ENOMEM);
+
+	if (sg_alloc_table(st, npages, GFP_KERNEL)) {
+		kfree(st);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	sg = st->sgl;
+	st->nents = 0;
+
+	max_order = MAX_ORDER;
+#ifdef CONFIG_SWIOTLB
+	if (swiotlb_nr_tbl()) {
+		unsigned int max_segment;
+
+		max_segment = swiotlb_max_segment();
+		if (max_segment) {
+			max_segment = max_t(unsigned int, max_segment,
+					    PAGE_SIZE) >> PAGE_SHIFT;
+			max_order = min(max_order, ilog2(max_segment));
+		}
+	}
+#endif
+
+	gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE;
+	if (IS_CRESTLINE(i915) || IS_BROADWATER(i915)) {
+		/* 965gm cannot relocate objects above 4GiB. */
+		gfp &= ~__GFP_HIGHMEM;
+		gfp |= __GFP_DMA32;
+	}
+
+	do {
+		int order = min(fls(npages) - 1, max_order);
+		struct page *page;
+
+		do {
+			page = alloc_pages(gfp | (order ? QUIET : 0), order);
+			if (page)
+				break;
+			if (!order--)
+				goto err;
+
+			/* Limit subsequent allocations as well */
+			max_order = order;
+		} while (1);
+
+		sg_set_page(sg, page, PAGE_SIZE << order, 0);
+		st->nents++;
+
+		npages -= 1 << order;
+		if (!npages) {
+			sg_mark_end(sg);
+			break;
+		}
+
+		sg = __sg_next(sg);
+	} while (1);
+
+	if (i915_gem_gtt_prepare_pages(obj, st))
+		goto err;
+
+	/* Mark the pages as dontneed whilst they are still pinned. As soon
+	 * as they are unpinned they are allowed to be reaped by the shrinker,
+	 * and the caller is expected to repopulate - the contents of this
+	 * object are only valid whilst active and pinned.
+	 */
+	obj->mm.madv = I915_MADV_DONTNEED;
+	return st;
+
+err:
+	sg_mark_end(sg);
+	internal_free_pages(st);
+	return ERR_PTR(-ENOMEM);
+}
+
+static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj,
+					       struct sg_table *pages)
+{
+	i915_gem_gtt_finish_pages(obj, pages);
+	internal_free_pages(pages);
+
+	obj->mm.dirty = false;
+	obj->mm.madv = I915_MADV_WILLNEED;
+}
+
+static const struct drm_i915_gem_object_ops i915_gem_object_internal_ops = {
+	.flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
+		 I915_GEM_OBJECT_IS_SHRINKABLE,
+	.get_pages = i915_gem_object_get_pages_internal,
+	.put_pages = i915_gem_object_put_pages_internal,
+};
+
+/**
+ * Creates a new object that wraps some internal memory for private use.
+ * This object is not backed by swappable storage, and as such its contents
+ * are volatile and only valid whilst pinned. If the object is reaped by the
+ * shrinker, its pages and data will be discarded. Equally, it is not a full
+ * GEM object and so not valid for access from userspace. This makes it useful
+ * for hardware interfaces like ringbuffers (which are pinned from the time
+ * the request is written to the time the hardware stops accessing it), but
+ * not for contexts (which need to be preserved when not active for later
+ * reuse). Note that it is not cleared upon allocation.
+ */
+struct drm_i915_gem_object *
+i915_gem_object_create_internal(struct drm_i915_private *i915,
+				unsigned int size)
+{
+	struct drm_i915_gem_object *obj;
+
+	obj = i915_gem_object_alloc(&i915->drm);
+	if (!obj)
+		return ERR_PTR(-ENOMEM);
+
+	drm_gem_private_object_init(&i915->drm, &obj->base, size);
+	i915_gem_object_init(obj, &i915_gem_object_internal_ops);
+
+	obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+	obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+	obj->cache_level = HAS_LLC(i915) ? I915_CACHE_LLC : I915_CACHE_NONE;
+
+	return obj;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_object.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_object.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_object.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_object.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,338 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __I915_GEM_OBJECT_H__
+#define __I915_GEM_OBJECT_H__
+
+#include <linux/reservation.h>
+
+#include <drm/drm_vma_manager.h>
+#include <drm/drm_gem.h>
+#include <drm/drmP.h>
+
+#include <drm/i915_drm.h>
+
+struct drm_i915_gem_object_ops {
+	unsigned int flags;
+#define I915_GEM_OBJECT_HAS_STRUCT_PAGE 0x1
+#define I915_GEM_OBJECT_IS_SHRINKABLE   0x2
+
+	/* Interface between the GEM object and its backing storage.
+	 * get_pages() is called once prior to the use of the associated set
+	 * of pages before to binding them into the GTT, and put_pages() is
+	 * called after we no longer need them. As we expect there to be
+	 * associated cost with migrating pages between the backing storage
+	 * and making them available for the GPU (e.g. clflush), we may hold
+	 * onto the pages after they are no longer referenced by the GPU
+	 * in case they may be used again shortly (for example migrating the
+	 * pages to a different memory domain within the GTT). put_pages()
+	 * will therefore most likely be called when the object itself is
+	 * being released or under memory pressure (where we attempt to
+	 * reap pages for the shrinker).
+	 */
+	struct sg_table *(*get_pages)(struct drm_i915_gem_object *);
+	void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *);
+
+	int (*dmabuf_export)(struct drm_i915_gem_object *);
+	void (*release)(struct drm_i915_gem_object *);
+};
+
+struct drm_i915_gem_object {
+	struct drm_gem_object base;
+
+	const struct drm_i915_gem_object_ops *ops;
+
+	/** List of VMAs backed by this object */
+	struct list_head vma_list;
+	struct rb_root vma_tree;
+
+	/** Stolen memory for this object, instead of being backed by shmem. */
+	struct drm_mm_node *stolen;
+	struct list_head global_link;
+	union {
+		struct rcu_head rcu;
+		struct llist_node freed;
+	};
+
+	/**
+	 * Whether the object is currently in the GGTT mmap.
+	 */
+	struct list_head userfault_link;
+
+	/** Used in execbuf to temporarily hold a ref */
+	struct list_head obj_exec_link;
+
+	struct list_head batch_pool_link;
+
+	unsigned long flags;
+
+	/**
+	 * Have we taken a reference for the object for incomplete GPU
+	 * activity?
+	 */
+#define I915_BO_ACTIVE_REF 0
+
+	/*
+	 * Is the object to be mapped as read-only to the GPU
+	 * Only honoured if hardware has relevant pte bit
+	 */
+	unsigned long gt_ro:1;
+	unsigned int cache_level:3;
+	unsigned int cache_dirty:1;
+
+	atomic_t frontbuffer_bits;
+	unsigned int frontbuffer_ggtt_origin; /* write once */
+	struct i915_gem_active frontbuffer_write;
+
+	/** Current tiling stride for the object, if it's tiled. */
+	unsigned int tiling_and_stride;
+#define FENCE_MINIMUM_STRIDE 128 /* See i915_tiling_ok() */
+#define TILING_MASK (FENCE_MINIMUM_STRIDE-1)
+#define STRIDE_MASK (~TILING_MASK)
+
+	/** Count of VMA actually bound by this object */
+	unsigned int bind_count;
+	unsigned int active_count;
+	unsigned int pin_display;
+
+	struct {
+		struct mutex lock; /* protects the pages and their use */
+		atomic_t pages_pin_count;
+
+		struct sg_table *pages;
+		void *mapping;
+
+		struct i915_gem_object_page_iter {
+			struct scatterlist *sg_pos;
+			unsigned int sg_idx; /* in pages, but 32bit eek! */
+
+			struct radix_tree_root radix;
+			struct mutex lock; /* protects this cache */
+		} get_page;
+
+		/**
+		 * Advice: are the backing pages purgeable?
+		 */
+		unsigned int madv:2;
+
+		/**
+		 * This is set if the object has been written to since the
+		 * pages were last acquired.
+		 */
+		bool dirty:1;
+
+		/**
+		 * This is set if the object has been pinned due to unknown
+		 * swizzling.
+		 */
+		bool quirked:1;
+	} mm;
+
+	/** Breadcrumb of last rendering to the buffer.
+	 * There can only be one writer, but we allow for multiple readers.
+	 * If there is a writer that necessarily implies that all other
+	 * read requests are complete - but we may only be lazily clearing
+	 * the read requests. A read request is naturally the most recent
+	 * request on a ring, so we may have two different write and read
+	 * requests on one ring where the write request is older than the
+	 * read request. This allows for the CPU to read from an active
+	 * buffer by only waiting for the write to complete.
+	 */
+	struct reservation_object *resv;
+
+	/** References from framebuffers, locks out tiling changes. */
+	unsigned long framebuffer_references;
+
+	/** Record of address bit 17 of each page at last unbind. */
+	unsigned long *bit_17;
+
+	struct i915_gem_userptr {
+		uintptr_t ptr;
+		unsigned read_only :1;
+
+		struct i915_mm_struct *mm;
+		struct i915_mmu_object *mmu_object;
+		struct work_struct *work;
+	} userptr;
+
+	/** for phys allocated objects */
+	struct drm_dma_handle *phys_handle;
+
+	struct reservation_object __builtin_resv;
+};
+
+static inline struct drm_i915_gem_object *
+to_intel_bo(struct drm_gem_object *gem)
+{
+	/* Assert that to_intel_bo(NULL) == NULL */
+	BUILD_BUG_ON(offsetof(struct drm_i915_gem_object, base));
+
+	return container_of(gem, struct drm_i915_gem_object, base);
+}
+
+/**
+ * i915_gem_object_lookup_rcu - look up a temporary GEM object from its handle
+ * @filp: DRM file private date
+ * @handle: userspace handle
+ *
+ * Returns:
+ *
+ * A pointer to the object named by the handle if such exists on @filp, NULL
+ * otherwise. This object is only valid whilst under the RCU read lock, and
+ * note carefully the object may be in the process of being destroyed.
+ */
+static inline struct drm_i915_gem_object *
+i915_gem_object_lookup_rcu(struct drm_file *file, u32 handle)
+{
+#ifdef CONFIG_LOCKDEP
+	WARN_ON(debug_locks && !lock_is_held(&rcu_lock_map));
+#endif
+	return idr_find(&file->object_idr, handle);
+}
+
+static inline struct drm_i915_gem_object *
+i915_gem_object_lookup(struct drm_file *file, u32 handle)
+{
+	struct drm_i915_gem_object *obj;
+
+	rcu_read_lock();
+	obj = i915_gem_object_lookup_rcu(file, handle);
+	if (obj && !kref_get_unless_zero(&obj->base.refcount))
+		obj = NULL;
+	rcu_read_unlock();
+
+	return obj;
+}
+
+__deprecated
+extern struct drm_gem_object *
+drm_gem_object_lookup(struct drm_file *file, u32 handle);
+
+__attribute__((nonnull))
+static inline struct drm_i915_gem_object *
+i915_gem_object_get(struct drm_i915_gem_object *obj)
+{
+	drm_gem_object_reference(&obj->base);
+	return obj;
+}
+
+__deprecated
+extern void drm_gem_object_reference(struct drm_gem_object *);
+
+__attribute__((nonnull))
+static inline void
+i915_gem_object_put(struct drm_i915_gem_object *obj)
+{
+	__drm_gem_object_unreference(&obj->base);
+}
+
+__deprecated
+extern void drm_gem_object_unreference(struct drm_gem_object *);
+
+__deprecated
+extern void drm_gem_object_unreference_unlocked(struct drm_gem_object *);
+
+static inline bool
+i915_gem_object_is_dead(const struct drm_i915_gem_object *obj)
+{
+	return atomic_read(&obj->base.refcount.refcount) == 0;
+}
+
+static inline bool
+i915_gem_object_has_struct_page(const struct drm_i915_gem_object *obj)
+{
+	return obj->ops->flags & I915_GEM_OBJECT_HAS_STRUCT_PAGE;
+}
+
+static inline bool
+i915_gem_object_is_shrinkable(const struct drm_i915_gem_object *obj)
+{
+	return obj->ops->flags & I915_GEM_OBJECT_IS_SHRINKABLE;
+}
+
+static inline bool
+i915_gem_object_is_active(const struct drm_i915_gem_object *obj)
+{
+	return obj->active_count;
+}
+
+static inline bool
+i915_gem_object_has_active_reference(const struct drm_i915_gem_object *obj)
+{
+	return test_bit(I915_BO_ACTIVE_REF, &obj->flags);
+}
+
+static inline void
+i915_gem_object_set_active_reference(struct drm_i915_gem_object *obj)
+{
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+	__set_bit(I915_BO_ACTIVE_REF, &obj->flags);
+}
+
+static inline void
+i915_gem_object_clear_active_reference(struct drm_i915_gem_object *obj)
+{
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+	__clear_bit(I915_BO_ACTIVE_REF, &obj->flags);
+}
+
+void __i915_gem_object_release_unless_active(struct drm_i915_gem_object *obj);
+
+static inline unsigned int
+i915_gem_object_get_tiling(struct drm_i915_gem_object *obj)
+{
+	return obj->tiling_and_stride & TILING_MASK;
+}
+
+static inline bool
+i915_gem_object_is_tiled(struct drm_i915_gem_object *obj)
+{
+	return i915_gem_object_get_tiling(obj) != I915_TILING_NONE;
+}
+
+static inline unsigned int
+i915_gem_object_get_stride(struct drm_i915_gem_object *obj)
+{
+	return obj->tiling_and_stride & STRIDE_MASK;
+}
+
+static inline struct intel_engine_cs *
+i915_gem_object_last_write_engine(struct drm_i915_gem_object *obj)
+{
+	struct intel_engine_cs *engine = NULL;
+	struct dma_fence *fence;
+
+	rcu_read_lock();
+	fence = reservation_object_get_excl_rcu(obj->resv);
+	rcu_read_unlock();
+
+	if (fence && dma_fence_is_i915(fence) && !dma_fence_is_signaled(fence))
+		engine = to_request(fence)->engine;
+	dma_fence_put(fence);
+
+	return engine;
+}
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_render_state.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,17 +28,19 @@
 #include "i915_drv.h"
 #include "intel_renderstate.h"
 
-struct render_state {
+struct intel_render_state {
 	const struct intel_renderstate_rodata *rodata;
 	struct i915_vma *vma;
-	u32 aux_batch_size;
-	u32 aux_batch_offset;
+	u32 batch_offset;
+	u32 batch_size;
+	u32 aux_offset;
+	u32 aux_size;
 };
 
 static const struct intel_renderstate_rodata *
-render_state_get_rodata(const struct drm_i915_gem_request *req)
+render_state_get_rodata(const struct intel_engine_cs *engine)
 {
-	switch (INTEL_GEN(req->i915)) {
+	switch (INTEL_GEN(engine->i915)) {
 	case 6:
 		return &gen6_null_state;
 	case 7:
@@ -63,29 +65,26 @@ render_state_get_rodata(const struct drm
  */
 #define OUT_BATCH(batch, i, val)				\
 	do {							\
-		if (WARN_ON((i) >= PAGE_SIZE / sizeof(u32))) {	\
-			ret = -ENOSPC;				\
-			goto err_out;				\
-		}						\
+		if ((i) >= PAGE_SIZE / sizeof(u32))		\
+			goto err;				\
 		(batch)[(i)++] = (val);				\
 	} while(0)
 
-static int render_state_setup(struct render_state *so)
+static int render_state_setup(struct intel_render_state *so,
+			      struct drm_i915_private *i915)
 {
-	struct drm_device *dev = so->vma->vm->dev;
 	const struct intel_renderstate_rodata *rodata = so->rodata;
-	const bool has_64bit_reloc = INTEL_GEN(dev) >= 8;
+	struct drm_i915_gem_object *obj = so->vma->obj;
 	unsigned int i = 0, reloc_index = 0;
-	struct page *page;
+	unsigned int needs_clflush;
 	u32 *d;
 	int ret;
 
-	ret = i915_gem_object_set_to_cpu_domain(so->vma->obj, true);
+	ret = i915_gem_obj_prepare_shmem_write(obj, &needs_clflush);
 	if (ret)
 		return ret;
 
-	page = i915_gem_object_get_dirty_page(so->vma->obj, 0);
-	d = kmap(page);
+	d = kmap_atomic(i915_gem_object_get_dirty_page(obj, 0));
 
 	while (i < rodata->batch_items) {
 		u32 s = rodata->batch[i];
@@ -93,12 +92,10 @@ static int render_state_setup(struct ren
 		if (i * 4  == rodata->reloc[reloc_index]) {
 			u64 r = s + so->vma->node.start;
 			s = lower_32_bits(r);
-			if (has_64bit_reloc) {
+			if (HAS_64BIT_RELOC(i915)) {
 				if (i + 1 >= rodata->batch_items ||
-				    rodata->batch[i + 1] != 0) {
-					ret = -EINVAL;
-					goto err_out;
-				}
+				    rodata->batch[i + 1] != 0)
+					goto err;
 
 				d[i++] = s;
 				s = upper_32_bits(r);
@@ -110,12 +107,20 @@ static int render_state_setup(struct ren
 		d[i++] = s;
 	}
 
+	if (rodata->reloc[reloc_index] != -1) {
+		DRM_ERROR("only %d relocs resolved\n", reloc_index);
+		goto err;
+	}
+
+	so->batch_offset = so->vma->node.start;
+	so->batch_size = rodata->batch_items * sizeof(u32);
+
 	while (i % CACHELINE_DWORDS)
 		OUT_BATCH(d, i, MI_NOOP);
 
-	so->aux_batch_offset = i * sizeof(u32);
+	so->aux_offset = i * sizeof(u32);
 
-	if (HAS_POOLED_EU(dev)) {
+	if (HAS_POOLED_EU(i915)) {
 		/*
 		 * We always program 3x6 pool config but depending upon which
 		 * subslice is disabled HW drops down to appropriate config
@@ -143,88 +148,133 @@ static int render_state_setup(struct ren
 	}
 
 	OUT_BATCH(d, i, MI_BATCH_BUFFER_END);
-	so->aux_batch_size = (i * sizeof(u32)) - so->aux_batch_offset;
-
+	so->aux_size = i * sizeof(u32) - so->aux_offset;
+	so->aux_offset += so->batch_offset;
 	/*
 	 * Since we are sending length, we need to strictly conform to
 	 * all requirements. For Gen2 this must be a multiple of 8.
 	 */
-	so->aux_batch_size = ALIGN(so->aux_batch_size, 8);
-
-	kunmap(page);
-
-	ret = i915_gem_object_set_to_gtt_domain(so->vma->obj, false);
-	if (ret)
-		return ret;
-
-	if (rodata->reloc[reloc_index] != -1) {
-		DRM_ERROR("only %d relocs resolved\n", reloc_index);
-		return -EINVAL;
-	}
+	so->aux_size = ALIGN(so->aux_size, 8);
 
-	return 0;
+	if (needs_clflush)
+		drm_clflush_virt_range(d, i * sizeof(u32));
+	kunmap_atomic(d);
 
-err_out:
-	kunmap(page);
+	ret = i915_gem_object_set_to_gtt_domain(obj, false);
+out:
+	i915_gem_obj_finish_shmem_access(obj);
 	return ret;
+
+err:
+	kunmap_atomic(d);
+	ret = -EINVAL;
+	goto out;
 }
 
 #undef OUT_BATCH
 
-int i915_gem_render_state_init(struct drm_i915_gem_request *req)
+int i915_gem_render_state_init(struct intel_engine_cs *engine)
 {
-	struct render_state so;
+	struct intel_render_state *so;
+	const struct intel_renderstate_rodata *rodata;
 	struct drm_i915_gem_object *obj;
 	int ret;
 
-	if (WARN_ON(req->engine->id != RCS))
-		return -ENOENT;
+	if (engine->id != RCS)
+		return 0;
 
-	so.rodata = render_state_get_rodata(req);
-	if (!so.rodata)
+	rodata = render_state_get_rodata(engine);
+	if (!rodata)
 		return 0;
 
-	if (so.rodata->batch_items * 4 > 4096)
+	if (rodata->batch_items * 4 > 4096)
 		return -EINVAL;
 
-	obj = i915_gem_object_create(&req->i915->drm, 4096);
-	if (IS_ERR(obj))
-		return PTR_ERR(obj);
+	so = kmalloc(sizeof(*so), GFP_KERNEL);
+	if (!so)
+		return -ENOMEM;
 
-	so.vma = i915_vma_create(obj, &req->i915->ggtt.base, NULL);
-	if (IS_ERR(so.vma)) {
-		ret = PTR_ERR(so.vma);
-		goto err_obj;
+	obj = i915_gem_object_create_internal(engine->i915, 4096);
+	if (IS_ERR(obj)) {
+		ret = PTR_ERR(obj);
+		goto err_free;
 	}
 
-	ret = i915_vma_pin(so.vma, 0, 0, PIN_GLOBAL);
-	if (ret)
+	so->vma = i915_vma_create(obj, &engine->i915->ggtt.base, NULL);
+	if (IS_ERR(so->vma)) {
+		ret = PTR_ERR(so->vma);
 		goto err_obj;
+	}
 
-	ret = render_state_setup(&so);
+	so->rodata = rodata;
+	engine->render_state = so;
+	return 0;
+
+err_obj:
+	i915_gem_object_put(obj);
+err_free:
+	kfree(so);
+	return ret;
+}
+
+int i915_gem_render_state_emit(struct drm_i915_gem_request *req)
+{
+	struct intel_render_state *so;
+	int ret;
+
+	lockdep_assert_held(&req->i915->drm.struct_mutex);
+
+	so = req->engine->render_state;
+	if (!so)
+		return 0;
+
+	/* Recreate the page after shrinking */
+	if (!so->vma->obj->mm.pages)
+		so->batch_offset = -1;
+
+	ret = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH);
 	if (ret)
-		goto err_unpin;
+		return ret;
 
-	ret = req->engine->emit_bb_start(req, so.vma->node.start,
-					 so.rodata->batch_items * 4,
+	if (so->vma->node.start != so->batch_offset) {
+		ret = render_state_setup(so, req->i915);
+		if (ret)
+			goto err_unpin;
+	}
+
+	ret = req->engine->emit_bb_start(req,
+					 so->batch_offset, so->batch_size,
 					 I915_DISPATCH_SECURE);
 	if (ret)
 		goto err_unpin;
 
-	if (so.aux_batch_size > 8) {
+	if (so->aux_size > 8) {
 		ret = req->engine->emit_bb_start(req,
-						 (so.vma->node.start +
-						  so.aux_batch_offset),
-						 so.aux_batch_size,
+						 so->aux_offset, so->aux_size,
 						 I915_DISPATCH_SECURE);
 		if (ret)
 			goto err_unpin;
 	}
 
-	i915_vma_move_to_active(so.vma, req, 0);
+	i915_vma_move_to_active(so->vma, req, 0);
 err_unpin:
-	i915_vma_unpin(so.vma);
-err_obj:
-	i915_gem_object_put(obj);
+	i915_vma_unpin(so->vma);
 	return ret;
 }
+
+void i915_gem_render_state_fini(struct intel_engine_cs *engine)
+{
+	struct intel_render_state *so;
+	struct drm_i915_gem_object *obj;
+
+	so = fetch_and_zero(&engine->render_state);
+	if (!so)
+		return;
+
+	obj = so->vma->obj;
+
+	i915_vma_close(so->vma);
+	__i915_gem_object_release_unless_active(obj);
+
+	kfree(so);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_render_state.h	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,8 @@
 
 struct drm_i915_gem_request;
 
-int i915_gem_render_state_init(struct drm_i915_gem_request *req);
+int i915_gem_render_state_init(struct intel_engine_cs *engine);
+int i915_gem_render_state_emit(struct drm_i915_gem_request *req);
+void i915_gem_render_state_fini(struct intel_engine_cs *engine);
 
 #endif /* _I915_GEM_RENDER_STATE_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_request.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_request.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_request.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_request.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,31 +23,26 @@
  */
 
 #include <linux/prefetch.h>
+#include <linux/dma-fence-array.h>
 
 #include "i915_drv.h"
 
-static const char *i915_fence_get_driver_name(struct fence *fence)
+static const char *i915_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "i915";
 }
 
-static const char *i915_fence_get_timeline_name(struct fence *fence)
+static const char *i915_fence_get_timeline_name(struct dma_fence *fence)
 {
-	/* Timelines are bound by eviction to a VM. However, since
-	 * we only have a global seqno at the moment, we only have
-	 * a single timeline. Note that each timeline will have
-	 * multiple execution contexts (fence contexts) as we allow
-	 * engines within a single timeline to execute in parallel.
-	 */
-	return "global";
+	return to_request(fence)->timeline->common->name;
 }
 
-static bool i915_fence_signaled(struct fence *fence)
+static bool i915_fence_signaled(struct dma_fence *fence)
 {
 	return i915_gem_request_completed(to_request(fence));
 }
 
-static bool i915_fence_enable_signaling(struct fence *fence)
+static bool i915_fence_enable_signaling(struct dma_fence *fence)
 {
 	if (i915_fence_signaled(fence))
 		return false;
@@ -56,63 +51,27 @@ static bool i915_fence_enable_signaling(
 	return true;
 }
 
-static signed long i915_fence_wait(struct fence *fence,
+static signed long i915_fence_wait(struct dma_fence *fence,
 				   bool interruptible,
-				   signed long timeout_jiffies)
-{
-	s64 timeout_ns, *timeout;
-	int ret;
-
-	if (timeout_jiffies != MAX_SCHEDULE_TIMEOUT) {
-		timeout_ns = jiffies_to_nsecs(timeout_jiffies);
-		timeout = &timeout_ns;
-	} else {
-		timeout = NULL;
-	}
-
-	ret = i915_wait_request(to_request(fence),
-				interruptible, timeout,
-				NO_WAITBOOST);
-	if (ret == -ETIME)
-		return 0;
-
-	if (ret < 0)
-		return ret;
-
-	if (timeout_jiffies != MAX_SCHEDULE_TIMEOUT)
-		timeout_jiffies = nsecs_to_jiffies(timeout_ns);
-
-	return timeout_jiffies;
-}
-
-static void i915_fence_value_str(struct fence *fence, char *str, int size)
-{
-	snprintf(str, size, "%u", fence->seqno);
-}
-
-static void i915_fence_timeline_value_str(struct fence *fence, char *str,
-					  int size)
+				   signed long timeout)
 {
-	snprintf(str, size, "%u",
-		 intel_engine_get_seqno(to_request(fence)->engine));
+	return i915_wait_request(to_request(fence), interruptible, timeout);
 }
 
-static void i915_fence_release(struct fence *fence)
+static void i915_fence_release(struct dma_fence *fence)
 {
 	struct drm_i915_gem_request *req = to_request(fence);
 
 	kmem_cache_free(req->i915->requests, req);
 }
 
-const struct fence_ops i915_fence_ops = {
+const struct dma_fence_ops i915_fence_ops = {
 	.get_driver_name = i915_fence_get_driver_name,
 	.get_timeline_name = i915_fence_get_timeline_name,
 	.enable_signaling = i915_fence_enable_signaling,
 	.signaled = i915_fence_signaled,
 	.wait = i915_fence_wait,
 	.release = i915_fence_release,
-	.fence_value_str = i915_fence_value_str,
-	.timeline_value_str = i915_fence_timeline_value_str,
 };
 
 int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
@@ -154,6 +113,82 @@ i915_gem_request_remove_from_client(stru
 	spin_unlock(&file_priv->mm.lock);
 }
 
+static struct i915_dependency *
+i915_dependency_alloc(struct drm_i915_private *i915)
+{
+	return kmem_cache_alloc(i915->dependencies, GFP_KERNEL);
+}
+
+static void
+i915_dependency_free(struct drm_i915_private *i915,
+		     struct i915_dependency *dep)
+{
+	kmem_cache_free(i915->dependencies, dep);
+}
+
+static void
+__i915_priotree_add_dependency(struct i915_priotree *pt,
+			       struct i915_priotree *signal,
+			       struct i915_dependency *dep,
+			       unsigned long flags)
+{
+	INIT_LIST_HEAD(&dep->dfs_link);
+	list_add(&dep->wait_link, &signal->waiters_list);
+	list_add(&dep->signal_link, &pt->signalers_list);
+	dep->signaler = signal;
+	dep->flags = flags;
+}
+
+static int
+i915_priotree_add_dependency(struct drm_i915_private *i915,
+			     struct i915_priotree *pt,
+			     struct i915_priotree *signal)
+{
+	struct i915_dependency *dep;
+
+	dep = i915_dependency_alloc(i915);
+	if (!dep)
+		return -ENOMEM;
+
+	__i915_priotree_add_dependency(pt, signal, dep, I915_DEPENDENCY_ALLOC);
+	return 0;
+}
+
+static void
+i915_priotree_fini(struct drm_i915_private *i915, struct i915_priotree *pt)
+{
+	struct i915_dependency *dep, *next;
+
+	GEM_BUG_ON(!RB_EMPTY_NODE(&pt->node));
+
+	/* Everyone we depended upon (the fences we wait to be signaled)
+	 * should retire before us and remove themselves from our list.
+	 * However, retirement is run independently on each timeline and
+	 * so we may be called out-of-order.
+	 */
+	list_for_each_entry_safe(dep, next, &pt->signalers_list, signal_link) {
+		list_del(&dep->wait_link);
+		if (dep->flags & I915_DEPENDENCY_ALLOC)
+			i915_dependency_free(i915, dep);
+	}
+
+	/* Remove ourselves from everyone who depends upon us */
+	list_for_each_entry_safe(dep, next, &pt->waiters_list, wait_link) {
+		list_del(&dep->signal_link);
+		if (dep->flags & I915_DEPENDENCY_ALLOC)
+			i915_dependency_free(i915, dep);
+	}
+}
+
+static void
+i915_priotree_init(struct i915_priotree *pt)
+{
+	INIT_LIST_HEAD(&pt->signalers_list);
+	INIT_LIST_HEAD(&pt->waiters_list);
+	RB_CLEAR_NODE(&pt->node);
+	pt->priority = INT_MIN;
+}
+
 void i915_gem_retire_noop(struct i915_gem_active *active,
 			  struct drm_i915_gem_request *request)
 {
@@ -164,8 +199,17 @@ static void i915_gem_request_retire(stru
 {
 	struct i915_gem_active *active, *next;
 
+	lockdep_assert_held(&request->i915->drm.struct_mutex);
+	GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit));
+	GEM_BUG_ON(!i915_sw_fence_signaled(&request->execute));
+	GEM_BUG_ON(!i915_gem_request_completed(request));
+	GEM_BUG_ON(!request->i915->gt.active_requests);
+
 	trace_i915_gem_request_retire(request);
-	list_del(&request->link);
+
+	spin_lock_irq(&request->engine->timeline->lock);
+	list_del_init(&request->link);
+	spin_unlock_irq(&request->engine->timeline->lock);
 
 	/* We know the GPU must have read the request to have
 	 * sent us the seqno + interrupt, so use the position
@@ -177,6 +221,12 @@ static void i915_gem_request_retire(stru
 	 */
 	list_del(&request->ring_link);
 	request->ring->last_retired_head = request->postfix;
+	if (!--request->i915->gt.active_requests) {
+		GEM_BUG_ON(!request->i915->gt.awake);
+		mod_delayed_work(request->i915->wq,
+				 &request->i915->gt.idle_work,
+				 msecs_to_jiffies(100));
+	}
 
 	/* Walk through the active list, calling retire on each. This allows
 	 * objects to track their GPU activity and mark themselves as idle
@@ -214,6 +264,10 @@ static void i915_gem_request_retire(stru
 	}
 
 	i915_gem_context_put(request->ctx);
+
+	dma_fence_signal(&request->fence);
+
+	i915_priotree_fini(request->i915, &request->priotree);
 	i915_gem_request_put(request);
 }
 
@@ -223,10 +277,11 @@ void i915_gem_request_retire_upto(struct
 	struct drm_i915_gem_request *tmp;
 
 	lockdep_assert_held(&req->i915->drm.struct_mutex);
-	GEM_BUG_ON(list_empty(&req->link));
+	if (list_empty(&req->link))
+		return;
 
 	do {
-		tmp = list_first_entry(&engine->request_list,
+		tmp = list_first_entry(&engine->timeline->requests,
 				       typeof(*tmp), link);
 
 		i915_gem_request_retire(tmp);
@@ -253,39 +308,50 @@ static int i915_gem_check_wedge(struct d
 	return 0;
 }
 
-static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno)
+static int i915_gem_init_global_seqno(struct drm_i915_private *i915, u32 seqno)
 {
+	struct i915_gem_timeline *timeline = &i915->gt.global_timeline;
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int ret;
 
 	/* Carefully retire all requests without writing to the rings */
-	for_each_engine(engine, dev_priv) {
-		ret = intel_engine_idle(engine,
-					I915_WAIT_INTERRUPTIBLE |
-					I915_WAIT_LOCKED);
-		if (ret)
-			return ret;
-	}
-	i915_gem_retire_requests(dev_priv);
+	ret = i915_gem_wait_for_idle(i915,
+				     I915_WAIT_INTERRUPTIBLE |
+				     I915_WAIT_LOCKED);
+	if (ret)
+		return ret;
+
+	i915_gem_retire_requests(i915);
+	GEM_BUG_ON(i915->gt.active_requests > 1);
 
 	/* If the seqno wraps around, we need to clear the breadcrumb rbtree */
-	if (!i915_seqno_passed(seqno, dev_priv->next_seqno)) {
-		while (intel_kick_waiters(dev_priv) ||
-		       intel_kick_signalers(dev_priv))
-			yield();
+	if (!i915_seqno_passed(seqno, atomic_read(&timeline->next_seqno))) {
+		while (intel_breadcrumbs_busy(i915))
+			cond_resched(); /* spin until threads are complete */
 	}
+	atomic_set(&timeline->next_seqno, seqno);
 
 	/* Finally reset hw state */
-	for_each_engine(engine, dev_priv)
-		intel_engine_init_seqno(engine, seqno);
+	for_each_engine(engine, i915, id)
+		intel_engine_init_global_seqno(engine, seqno);
+
+	list_for_each_entry(timeline, &i915->gt.timelines, link) {
+		for_each_engine(engine, i915, id) {
+			struct intel_timeline *tl = &timeline->engine[id];
+
+			memset(tl->sync_seqno, 0, sizeof(tl->sync_seqno));
+		}
+	}
 
 	return 0;
 }
 
-int i915_gem_set_seqno(struct drm_device *dev, u32 seqno)
+int i915_gem_set_global_seqno(struct drm_device *dev, u32 seqno)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int ret;
+
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
 	if (seqno == 0)
 		return -EINVAL;
@@ -293,29 +359,87 @@ int i915_gem_set_seqno(struct drm_device
 	/* HWS page needs to be set less than what we
 	 * will inject to ring
 	 */
-	ret = i915_gem_init_seqno(dev_priv, seqno - 1);
-	if (ret)
+	return i915_gem_init_global_seqno(dev_priv, seqno - 1);
+}
+
+static int reserve_global_seqno(struct drm_i915_private *i915)
+{
+	u32 active_requests = ++i915->gt.active_requests;
+	u32 next_seqno = atomic_read(&i915->gt.global_timeline.next_seqno);
+	int ret;
+
+	/* Reservation is fine until we need to wrap around */
+	if (likely(next_seqno + active_requests > next_seqno))
+		return 0;
+
+	ret = i915_gem_init_global_seqno(i915, 0);
+	if (ret) {
+		i915->gt.active_requests--;
 		return ret;
+	}
 
-	dev_priv->next_seqno = seqno;
 	return 0;
 }
 
-static int i915_gem_get_seqno(struct drm_i915_private *dev_priv, u32 *seqno)
+static u32 __timeline_get_seqno(struct i915_gem_timeline *tl)
 {
-	/* reserve 0 for non-seqno */
-	if (unlikely(dev_priv->next_seqno == 0)) {
-		int ret;
+	/* next_seqno only incremented under a mutex */
+	return ++tl->next_seqno.counter;
+}
 
-		ret = i915_gem_init_seqno(dev_priv, 0);
-		if (ret)
-			return ret;
+static u32 timeline_get_seqno(struct i915_gem_timeline *tl)
+{
+	return atomic_inc_return(&tl->next_seqno);
+}
 
-		dev_priv->next_seqno = 1;
-	}
+void __i915_gem_request_submit(struct drm_i915_gem_request *request)
+{
+	struct intel_engine_cs *engine = request->engine;
+	struct intel_timeline *timeline;
+	u32 seqno;
 
-	*seqno = dev_priv->next_seqno++;
-	return 0;
+	/* Transfer from per-context onto the global per-engine timeline */
+	timeline = engine->timeline;
+	GEM_BUG_ON(timeline == request->timeline);
+	assert_spin_locked(&timeline->lock);
+
+	seqno = timeline_get_seqno(timeline->common);
+	GEM_BUG_ON(!seqno);
+	GEM_BUG_ON(i915_seqno_passed(intel_engine_get_seqno(engine), seqno));
+
+	GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno, seqno));
+	request->previous_seqno = timeline->last_submitted_seqno;
+	timeline->last_submitted_seqno = seqno;
+
+	/* We may be recursing from the signal callback of another i915 fence */
+	spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING);
+	request->global_seqno = seqno;
+	if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags))
+		intel_engine_enable_signaling(request);
+	spin_unlock(&request->lock);
+
+	GEM_BUG_ON(!request->global_seqno);
+	engine->emit_breadcrumb(request,
+				request->ring->vaddr + request->postfix);
+
+	spin_lock(&request->timeline->lock);
+	list_move_tail(&request->link, &timeline->requests);
+	spin_unlock(&request->timeline->lock);
+
+	i915_sw_fence_commit(&request->execute);
+}
+
+void i915_gem_request_submit(struct drm_i915_gem_request *request)
+{
+	struct intel_engine_cs *engine = request->engine;
+	unsigned long flags;
+
+	/* Will be called from irq-context when using foreign fences. */
+	spin_lock_irqsave(&engine->timeline->lock, flags);
+
+	__i915_gem_request_submit(request);
+
+	spin_unlock_irqrestore(&engine->timeline->lock, flags);
 }
 
 static int __i915_sw_fence_call
@@ -324,15 +448,31 @@ submit_notify(struct i915_sw_fence *fenc
 	struct drm_i915_gem_request *request =
 		container_of(fence, typeof(*request), submit);
 
-	/* Will be called from irq-context when using foreign DMA fences */
-
 	switch (state) {
 	case FENCE_COMPLETE:
-		request->engine->last_submitted_seqno = request->fence.seqno;
 		request->engine->submit_request(request);
 		break;
 
 	case FENCE_FREE:
+		i915_gem_request_put(request);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int __i915_sw_fence_call
+execute_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
+{
+	struct drm_i915_gem_request *request =
+		container_of(fence, typeof(*request), execute);
+
+	switch (state) {
+	case FENCE_COMPLETE:
+		break;
+
+	case FENCE_FREE:
+		i915_gem_request_put(request);
 		break;
 	}
 
@@ -357,9 +497,10 @@ i915_gem_request_alloc(struct intel_engi
 {
 	struct drm_i915_private *dev_priv = engine->i915;
 	struct drm_i915_gem_request *req;
-	u32 seqno;
 	int ret;
 
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
 	/* ABI: Before userspace accesses the GPU (e.g. execbuffer), report
 	 * EIO if the GPU is already wedged, or EAGAIN to drop the struct_mutex
 	 * and restart.
@@ -368,10 +509,14 @@ i915_gem_request_alloc(struct intel_engi
 	if (ret)
 		return ERR_PTR(ret);
 
+	ret = reserve_global_seqno(dev_priv);
+	if (ret)
+		return ERR_PTR(ret);
+
 	/* Move the oldest request to the slab-cache (if not in use!) */
-	req = list_first_entry_or_null(&engine->request_list,
+	req = list_first_entry_or_null(&engine->timeline->requests,
 				       typeof(*req), link);
-	if (req && i915_gem_request_completed(req))
+	if (req && __i915_gem_request_completed(req))
 		i915_gem_request_retire(req);
 
 	/* Beware: Dragons be flying overhead.
@@ -382,13 +527,13 @@ i915_gem_request_alloc(struct intel_engi
 	 * of being read by __i915_gem_active_get_rcu(). As such,
 	 * we have to be very careful when overwriting the contents. During
 	 * the RCU lookup, we change chase the request->engine pointer,
-	 * read the request->fence.seqno and increment the reference count.
+	 * read the request->global_seqno and increment the reference count.
 	 *
 	 * The reference count is incremented atomically. If it is zero,
 	 * the lookup knows the request is unallocated and complete. Otherwise,
 	 * it is either still in use, or has been reallocated and reset
-	 * with fence_init(). This increment is safe for release as we check
-	 * that the request we have a reference to and matches the active
+	 * with dma_fence_init(). This increment is safe for release as we
+	 * check that the request we have a reference to and matches the active
 	 * request.
 	 *
 	 * Before we increment the refcount, we chase the request->engine
@@ -403,21 +548,32 @@ i915_gem_request_alloc(struct intel_engi
 	 * Do not use kmem_cache_zalloc() here!
 	 */
 	req = kmem_cache_alloc(dev_priv->requests, GFP_KERNEL);
-	if (!req)
-		return ERR_PTR(-ENOMEM);
+	if (!req) {
+		ret = -ENOMEM;
+		goto err_unreserve;
+	}
 
-	ret = i915_gem_get_seqno(dev_priv, &seqno);
-	if (ret)
-		goto err;
+	req->timeline = i915_gem_context_lookup_timeline(ctx, engine);
+	GEM_BUG_ON(req->timeline == engine->timeline);
 
 	spin_lock_init(&req->lock);
-	fence_init(&req->fence,
-		   &i915_fence_ops,
-		   &req->lock,
-		   engine->fence_context,
-		   seqno);
+	dma_fence_init(&req->fence,
+		       &i915_fence_ops,
+		       &req->lock,
+		       req->timeline->fence_context,
+		       __timeline_get_seqno(req->timeline->common));
 
-	i915_sw_fence_init(&req->submit, submit_notify);
+	/* We bump the ref for the fence chain */
+	i915_sw_fence_init(&i915_gem_request_get(req)->submit, submit_notify);
+	i915_sw_fence_init(&i915_gem_request_get(req)->execute, execute_notify);
+
+	/* Ensure that the execute fence completes after the submit fence -
+	 * as we complete the execute fence from within the submit fence
+	 * callback, its completion would otherwise be visible first.
+	 */
+	i915_sw_fence_await_sw_fence(&req->execute, &req->submit, &req->execq);
+
+	i915_priotree_init(&req->priotree);
 
 	INIT_LIST_HEAD(&req->active_list);
 	req->i915 = dev_priv;
@@ -425,6 +581,7 @@ i915_gem_request_alloc(struct intel_engi
 	req->ctx = i915_gem_context_get(ctx);
 
 	/* No zalloc, must clear what we need by hand */
+	req->global_seqno = 0;
 	req->previous_context = NULL;
 	req->file_priv = NULL;
 	req->batch = NULL;
@@ -437,6 +594,7 @@ i915_gem_request_alloc(struct intel_engi
 	 * away, e.g. because a GPU scheduler has deferred it.
 	 */
 	req->reserved_space = MIN_SPACE_FOR_ADD_REQUEST;
+	GEM_BUG_ON(req->reserved_space < engine->emit_breadcrumb_sz);
 
 	if (i915.enable_execlists)
 		ret = intel_logical_ring_alloc_request_extras(req);
@@ -456,8 +614,9 @@ i915_gem_request_alloc(struct intel_engi
 
 err_ctx:
 	i915_gem_context_put(ctx);
-err:
 	kmem_cache_free(dev_priv->requests, req);
+err_unreserve:
+	dev_priv->gt.active_requests--;
 	return ERR_PTR(ret);
 }
 
@@ -465,15 +624,36 @@ static int
 i915_gem_request_await_request(struct drm_i915_gem_request *to,
 			       struct drm_i915_gem_request *from)
 {
-	int idx, ret;
+	int ret;
 
 	GEM_BUG_ON(to == from);
 
-	if (to->engine == from->engine)
+	if (to->engine->schedule) {
+		ret = i915_priotree_add_dependency(to->i915,
+						   &to->priotree,
+						   &from->priotree);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (to->timeline == from->timeline)
 		return 0;
 
-	idx = intel_engine_sync_index(from->engine, to->engine);
-	if (from->fence.seqno <= from->engine->semaphore.sync_seqno[idx])
+	if (to->engine == from->engine) {
+		ret = i915_sw_fence_await_sw_fence_gfp(&to->submit,
+						       &from->submit,
+						       GFP_KERNEL);
+		return ret < 0 ? ret : 0;
+	}
+
+	if (!from->global_seqno) {
+		ret = i915_sw_fence_await_dma_fence(&to->submit,
+						    &from->fence, 0,
+						    GFP_KERNEL);
+		return ret < 0 ? ret : 0;
+	}
+
+	if (from->global_seqno <= to->timeline->sync_seqno[from->engine->id])
 		return 0;
 
 	trace_i915_gem_ring_sync_to(to, from);
@@ -491,7 +671,54 @@ i915_gem_request_await_request(struct dr
 			return ret;
 	}
 
-	from->engine->semaphore.sync_seqno[idx] = from->fence.seqno;
+	to->timeline->sync_seqno[from->engine->id] = from->global_seqno;
+	return 0;
+}
+
+int
+i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req,
+				 struct dma_fence *fence)
+{
+	struct dma_fence_array *array;
+	int ret;
+	int i;
+
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		return 0;
+
+	if (dma_fence_is_i915(fence))
+		return i915_gem_request_await_request(req, to_request(fence));
+
+	if (!dma_fence_is_array(fence)) {
+		ret = i915_sw_fence_await_dma_fence(&req->submit,
+						    fence, I915_FENCE_TIMEOUT,
+						    GFP_KERNEL);
+		return ret < 0 ? ret : 0;
+	}
+
+	/* Note that if the fence-array was created in signal-on-any mode,
+	 * we should *not* decompose it into its individual fences. However,
+	 * we don't currently store which mode the fence-array is operating
+	 * in. Fortunately, the only user of signal-on-any is private to
+	 * amdgpu and we should not see any incoming fence-array from
+	 * sync-file being in signal-on-any mode.
+	 */
+
+	array = to_dma_fence_array(fence);
+	for (i = 0; i < array->num_fences; i++) {
+		struct dma_fence *child = array->fences[i];
+
+		if (dma_fence_is_i915(child))
+			ret = i915_gem_request_await_request(req,
+							     to_request(child));
+		else
+			ret = i915_sw_fence_await_dma_fence(&req->submit,
+							    child, I915_FENCE_TIMEOUT,
+							    GFP_KERNEL);
+		if (ret < 0)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -520,43 +747,52 @@ i915_gem_request_await_object(struct drm
 			      struct drm_i915_gem_object *obj,
 			      bool write)
 {
-	struct i915_gem_active *active;
-	unsigned long active_mask;
-	int idx;
+	struct dma_fence *excl;
+	int ret = 0;
 
 	if (write) {
-		active_mask = i915_gem_object_get_active(obj);
-		active = obj->last_read;
+		struct dma_fence **shared;
+		unsigned int count, i;
+
+		ret = reservation_object_get_fences_rcu(obj->resv,
+							&excl, &count, &shared);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < count; i++) {
+			ret = i915_gem_request_await_dma_fence(to, shared[i]);
+			if (ret)
+				break;
+
+			dma_fence_put(shared[i]);
+		}
+
+		for (; i < count; i++)
+			dma_fence_put(shared[i]);
+		kfree(shared);
 	} else {
-		active_mask = 1;
-		active = &obj->last_write;
+		excl = reservation_object_get_excl_rcu(obj->resv);
 	}
 
-	for_each_active(active_mask, idx) {
-		struct drm_i915_gem_request *request;
-		int ret;
-
-		request = i915_gem_active_peek(&active[idx],
-					       &obj->base.dev->struct_mutex);
-		if (!request)
-			continue;
+	if (excl) {
+		if (ret == 0)
+			ret = i915_gem_request_await_dma_fence(to, excl);
 
-		ret = i915_gem_request_await_request(to, request);
-		if (ret)
-			return ret;
+		dma_fence_put(excl);
 	}
 
-	return 0;
+	return ret;
 }
 
 static void i915_gem_mark_busy(const struct intel_engine_cs *engine)
 {
 	struct drm_i915_private *dev_priv = engine->i915;
 
-	dev_priv->gt.active_engines |= intel_engine_flag(engine);
 	if (dev_priv->gt.awake)
 		return;
 
+	GEM_BUG_ON(!dev_priv->gt.active_requests);
+
 	intel_runtime_pm_get_noresume(dev_priv);
 	dev_priv->gt.awake = true;
 
@@ -579,11 +815,11 @@ void __i915_add_request(struct drm_i915_
 {
 	struct intel_engine_cs *engine = request->engine;
 	struct intel_ring *ring = request->ring;
+	struct intel_timeline *timeline = request->timeline;
 	struct drm_i915_gem_request *prev;
-	u32 request_start;
-	u32 reserved_tail;
-	int ret;
+	int err;
 
+	lockdep_assert_held(&request->i915->drm.struct_mutex);
 	trace_i915_gem_request_add(request);
 
 	/*
@@ -591,8 +827,6 @@ void __i915_add_request(struct drm_i915_
 	 * should already have been reserved in the ring buffer. Let the ring
 	 * know that it is time to use that space up.
 	 */
-	request_start = ring->tail;
-	reserved_tail = request->reserved_space;
 	request->reserved_space = 0;
 
 	/*
@@ -603,10 +837,10 @@ void __i915_add_request(struct drm_i915_
 	 * what.
 	 */
 	if (flush_caches) {
-		ret = engine->emit_flush(request, EMIT_FLUSH);
+		err = engine->emit_flush(request, EMIT_FLUSH);
 
 		/* Not allowed to fail! */
-		WARN(ret, "engine->emit_flush() failed: %d!\n", ret);
+		WARN(err, "engine->emit_flush() failed: %d!\n", err);
 	}
 
 	/* Record the position of the start of the breadcrumb so that
@@ -614,20 +848,10 @@ void __i915_add_request(struct drm_i915_
 	 * GPU processing the request, we never over-estimate the
 	 * position of the ring's HEAD.
 	 */
+	err = intel_ring_begin(request, engine->emit_breadcrumb_sz);
+	GEM_BUG_ON(err);
 	request->postfix = ring->tail;
-
-	/* Not allowed to fail! */
-	ret = engine->emit_request(request);
-	WARN(ret, "(%s)->emit_request failed: %d!\n", engine->name, ret);
-
-	/* Sanity check that the reserved size was large enough. */
-	ret = ring->tail - request_start;
-	if (ret < 0)
-		ret += ring->size;
-	WARN_ONCE(ret > reserved_tail,
-		  "Not enough space reserved (%d bytes) "
-		  "for adding the request (%d bytes)\n",
-		  reserved_tail, ret);
+	ring->tail += engine->emit_breadcrumb_sz * sizeof(u32);
 
 	/* Seal the request and mark it as pending execution. Note that
 	 * we may inspect this state, without holding any locks, during
@@ -635,21 +859,46 @@ void __i915_add_request(struct drm_i915_
 	 * see a more recent value in the hws than we are tracking.
 	 */
 
-	prev = i915_gem_active_raw(&engine->last_request,
+	prev = i915_gem_active_raw(&timeline->last_request,
 				   &request->i915->drm.struct_mutex);
-	if (prev)
+	if (prev) {
 		i915_sw_fence_await_sw_fence(&request->submit, &prev->submit,
 					     &request->submitq);
+		if (engine->schedule)
+			__i915_priotree_add_dependency(&request->priotree,
+						       &prev->priotree,
+						       &request->dep,
+						       0);
+	}
+
+	spin_lock_irq(&timeline->lock);
+	list_add_tail(&request->link, &timeline->requests);
+	spin_unlock_irq(&timeline->lock);
+
+	GEM_BUG_ON(i915_seqno_passed(timeline->last_submitted_seqno,
+				     request->fence.seqno));
+
+	timeline->last_submitted_seqno = request->fence.seqno;
+	i915_gem_active_set(&timeline->last_request, request);
 
-	request->emitted_jiffies = jiffies;
-	request->previous_seqno = engine->last_pending_seqno;
-	engine->last_pending_seqno = request->fence.seqno;
-	i915_gem_active_set(&engine->last_request, request);
-	list_add_tail(&request->link, &engine->request_list);
 	list_add_tail(&request->ring_link, &ring->request_list);
+	request->emitted_jiffies = jiffies;
 
 	i915_gem_mark_busy(engine);
 
+	/* Let the backend know a new request has arrived that may need
+	 * to adjust the existing execution schedule due to a high priority
+	 * request - i.e. we may want to preempt the current request in order
+	 * to run a high priority dependency chain *before* we can execute this
+	 * request.
+	 *
+	 * This is called before the request is ready to run so that we can
+	 * decide whether to preempt the entire chain so that it is ready to
+	 * run at the earliest possible convenience.
+	 */
+	if (engine->schedule)
+		engine->schedule(request, request->ctx->priority);
+
 	local_bh_disable();
 	i915_sw_fence_commit(&request->submit);
 	local_bh_enable(); /* Kick the execlists tasklet if just scheduled */
@@ -714,7 +963,7 @@ bool __i915_spin_request(const struct dr
 
 	timeout_us += local_clock_us(&cpu);
 	do {
-		if (i915_gem_request_completed(req))
+		if (__i915_gem_request_completed(req))
 			return true;
 
 		if (signal_pending_state(state, current))
@@ -723,82 +972,108 @@ bool __i915_spin_request(const struct dr
 		if (busywait_stop(timeout_us, cpu))
 			break;
 
-		cpu_relax_lowlatency();
+		cpu_relax();
 	} while (!need_resched());
 
 	return false;
 }
 
+static long
+__i915_request_wait_for_execute(struct drm_i915_gem_request *request,
+				unsigned int flags,
+				long timeout)
+{
+	const int state = flags & I915_WAIT_INTERRUPTIBLE ?
+		TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
+	wait_queue_head_t *q = &request->i915->gpu_error.wait_queue;
+	DEFINE_WAIT(reset);
+	DEFINE_WAIT(wait);
+
+	if (flags & I915_WAIT_LOCKED)
+		add_wait_queue(q, &reset);
+
+	do {
+		prepare_to_wait(&request->execute.wait, &wait, state);
+
+		if (i915_sw_fence_done(&request->execute))
+			break;
+
+		if (flags & I915_WAIT_LOCKED &&
+		    i915_reset_in_progress(&request->i915->gpu_error)) {
+			__set_current_state(TASK_RUNNING);
+			i915_reset(request->i915);
+			reset_wait_queue(q, &reset);
+			continue;
+		}
+
+		if (signal_pending_state(state, current)) {
+			timeout = -ERESTARTSYS;
+			break;
+		}
+
+		timeout = io_schedule_timeout(timeout);
+	} while (timeout);
+	finish_wait(&request->execute.wait, &wait);
+
+	if (flags & I915_WAIT_LOCKED)
+		remove_wait_queue(q, &reset);
+
+	return timeout;
+}
+
 /**
  * i915_wait_request - wait until execution of request has finished
- * @req: duh!
+ * @req: the request to wait upon
  * @flags: how to wait
- * @timeout: in - how long to wait (NULL forever); out - how much time remaining
- * @rps: client to charge for RPS boosting
+ * @timeout: how long to wait in jiffies
  *
- * Note: It is of utmost importance that the passed in seqno and reset_counter
- * values have been read by the caller in an smp safe manner. Where read-side
- * locks are involved, it is sufficient to read the reset_counter before
- * unlocking the lock that protects the seqno. For lockless tricks, the
- * reset_counter _must_ be read before, and an appropriate smp_rmb must be
- * inserted.
+ * i915_wait_request() waits for the request to be completed, for a
+ * maximum of @timeout jiffies (with MAX_SCHEDULE_TIMEOUT implying an
+ * unbounded wait).
  *
- * Returns 0 if the request was found within the alloted time. Else returns the
- * errno with remaining time filled in timeout argument.
+ * If the caller holds the struct_mutex, the caller must pass I915_WAIT_LOCKED
+ * in via the flags, and vice versa if the struct_mutex is not held, the caller
+ * must not specify that the wait is locked.
+ *
+ * Returns the remaining time (in jiffies) if the request completed, which may
+ * be zero or -ETIME if the request is unfinished after the timeout expires.
+ * May return -EINTR is called with I915_WAIT_INTERRUPTIBLE and a signal is
+ * pending before the request completes.
  */
-int i915_wait_request(struct drm_i915_gem_request *req,
-		      unsigned int flags,
-		      s64 *timeout,
-		      struct intel_rps_client *rps)
+long i915_wait_request(struct drm_i915_gem_request *req,
+		       unsigned int flags,
+		       long timeout)
 {
 	const int state = flags & I915_WAIT_INTERRUPTIBLE ?
 		TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
 	DEFINE_WAIT(reset);
 	struct intel_wait wait;
-	unsigned long timeout_remain;
-	int ret = 0;
 
 	might_sleep();
 #if IS_ENABLED(CONFIG_LOCKDEP)
-	GEM_BUG_ON(!!lockdep_is_held(&req->i915->drm.struct_mutex) !=
+	GEM_BUG_ON(debug_locks &&
+		   !!lockdep_is_held(&req->i915->drm.struct_mutex) !=
 		   !!(flags & I915_WAIT_LOCKED));
 #endif
+	GEM_BUG_ON(timeout < 0);
 
 	if (i915_gem_request_completed(req))
-		return 0;
-
-	timeout_remain = MAX_SCHEDULE_TIMEOUT;
-	if (timeout) {
-		if (WARN_ON(*timeout < 0))
-			return -EINVAL;
-
-		if (*timeout == 0)
-			return -ETIME;
+		return timeout;
 
-		/* Record current time in case interrupted, or wedged */
-		timeout_remain = nsecs_to_jiffies_timeout(*timeout);
-		*timeout += ktime_get_raw_ns();
-	}
+	if (!timeout)
+		return -ETIME;
 
 	trace_i915_gem_request_wait_begin(req);
 
-	/* This client is about to stall waiting for the GPU. In many cases
-	 * this is undesirable and limits the throughput of the system, as
-	 * many clients cannot continue processing user input/output whilst
-	 * blocked. RPS autotuning may take tens of milliseconds to respond
-	 * to the GPU load and thus incurs additional latency for the client.
-	 * We can circumvent that by promoting the GPU frequency to maximum
-	 * before we wait. This makes the GPU throttle up much more quickly
-	 * (good for benchmarks and user experience, e.g. window animations),
-	 * but at a cost of spending more power processing the workload
-	 * (bad for battery). Not all clients even want their results
-	 * immediately and for them we should just let the GPU select its own
-	 * frequency to maximise efficiency. To prevent a single client from
-	 * forcing the clocks too high for the whole system, we only allow
-	 * each client to waitboost once in a busy period.
-	 */
-	if (IS_RPS_CLIENT(rps) && INTEL_GEN(req->i915) >= 6)
-		gen6_rps_boost(req->i915, rps, req->emitted_jiffies);
+	if (!i915_sw_fence_done(&req->execute)) {
+		timeout = __i915_request_wait_for_execute(req, flags, timeout);
+		if (timeout < 0)
+			goto complete;
+
+		GEM_BUG_ON(!i915_sw_fence_done(&req->execute));
+	}
+	GEM_BUG_ON(!i915_sw_fence_done(&req->submit));
+	GEM_BUG_ON(!req->global_seqno);
 
 	/* Optimistic short spin before touching IRQs */
 	if (i915_spin_request(req, state, 5))
@@ -808,7 +1083,7 @@ int i915_wait_request(struct drm_i915_ge
 	if (flags & I915_WAIT_LOCKED)
 		add_wait_queue(&req->i915->gpu_error.wait_queue, &reset);
 
-	intel_wait_init(&wait, req->fence.seqno);
+	intel_wait_init(&wait, req->global_seqno);
 	if (intel_engine_add_wait(req->engine, &wait))
 		/* In order to check that we haven't missed the interrupt
 		 * as we enabled it, we need to kick ourselves to do a
@@ -818,16 +1093,17 @@ int i915_wait_request(struct drm_i915_ge
 
 	for (;;) {
 		if (signal_pending_state(state, current)) {
-			ret = -ERESTARTSYS;
+			timeout = -ERESTARTSYS;
 			break;
 		}
 
-		timeout_remain = io_schedule_timeout(timeout_remain);
-		if (timeout_remain == 0) {
-			ret = -ETIME;
+		if (!timeout) {
+			timeout = -ETIME;
 			break;
 		}
 
+		timeout = io_schedule_timeout(timeout);
+
 		if (intel_wait_complete(&wait))
 			break;
 
@@ -874,74 +1150,32 @@ wakeup:
 complete:
 	trace_i915_gem_request_wait_end(req);
 
-	if (timeout) {
-		*timeout -= ktime_get_raw_ns();
-		if (*timeout < 0)
-			*timeout = 0;
-
-		/*
-		 * Apparently ktime isn't accurate enough and occasionally has a
-		 * bit of mismatch in the jiffies<->nsecs<->ktime loop. So patch
-		 * things up to make the test happy. We allow up to 1 jiffy.
-		 *
-		 * This is a regrssion from the timespec->ktime conversion.
-		 */
-		if (ret == -ETIME && *timeout < jiffies_to_usecs(1)*1000)
-			*timeout = 0;
-	}
-
-	if (IS_RPS_USER(rps) &&
-	    req->fence.seqno == req->engine->last_submitted_seqno) {
-		/* The GPU is now idle and this client has stalled.
-		 * Since no other client has submitted a request in the
-		 * meantime, assume that this client is the only one
-		 * supplying work to the GPU but is unable to keep that
-		 * work supplied because it is waiting. Since the GPU is
-		 * then never kept fully busy, RPS autoclocking will
-		 * keep the clocks relatively low, causing further delays.
-		 * Compensate by giving the synchronous client credit for
-		 * a waitboost next time.
-		 */
-		spin_lock(&req->i915->rps.client_lock);
-		list_del_init(&rps->link);
-		spin_unlock(&req->i915->rps.client_lock);
-	}
-
-	return ret;
+	return timeout;
 }
 
-static bool engine_retire_requests(struct intel_engine_cs *engine)
+static void engine_retire_requests(struct intel_engine_cs *engine)
 {
 	struct drm_i915_gem_request *request, *next;
 
-	list_for_each_entry_safe(request, next, &engine->request_list, link) {
-		if (!i915_gem_request_completed(request))
-			return false;
+	list_for_each_entry_safe(request, next,
+				 &engine->timeline->requests, link) {
+		if (!__i915_gem_request_completed(request))
+			return;
 
 		i915_gem_request_retire(request);
 	}
-
-	return true;
 }
 
 void i915_gem_retire_requests(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
-	unsigned int tmp;
+	enum intel_engine_id id;
 
 	lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
-	if (dev_priv->gt.active_engines == 0)
+	if (!dev_priv->gt.active_requests)
 		return;
 
-	GEM_BUG_ON(!dev_priv->gt.awake);
-
-	for_each_engine_masked(engine, dev_priv, dev_priv->gt.active_engines, tmp)
-		if (engine_retire_requests(engine))
-			dev_priv->gt.active_engines &= ~intel_engine_flag(engine);
-
-	if (dev_priv->gt.active_engines == 0)
-		queue_delayed_work(dev_priv->wq,
-				   &dev_priv->gt.idle_work,
-				   msecs_to_jiffies(100));
+	for_each_engine(engine, dev_priv, id)
+		engine_retire_requests(engine);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_request.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_request.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_request.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_request.h	2017-02-12 16:03:20.000000000 -0500
@@ -25,11 +25,14 @@
 #ifndef I915_GEM_REQUEST_H
 #define I915_GEM_REQUEST_H
 
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 #include "i915_gem.h"
 #include "i915_sw_fence.h"
 
+struct drm_file;
+struct drm_i915_gem_object;
+
 struct intel_wait {
 	struct rb_node node;
 	struct task_struct *tsk;
@@ -41,6 +44,33 @@ struct intel_signal_node {
 	struct intel_wait wait;
 };
 
+struct i915_dependency {
+	struct i915_priotree *signaler;
+	struct list_head signal_link;
+	struct list_head wait_link;
+	struct list_head dfs_link;
+	unsigned long flags;
+#define I915_DEPENDENCY_ALLOC BIT(0)
+};
+
+/* Requests exist in a complex web of interdependencies. Each request
+ * has to wait for some other request to complete before it is ready to be run
+ * (e.g. we have to wait until the pixels have been rendering into a texture
+ * before we can copy from it). We track the readiness of a request in terms
+ * of fences, but we also need to keep the dependency tree for the lifetime
+ * of the request (beyond the life of an individual fence). We use the tree
+ * at various points to reorder the requests whilst keeping the requests
+ * in order with respect to their various dependencies.
+ */
+struct i915_priotree {
+	struct list_head signalers_list; /* those before us, we depend upon */
+	struct list_head waiters_list; /* those after us, they depend upon us */
+	struct rb_node node;
+	int priority;
+#define I915_PRIORITY_MAX 1024
+#define I915_PRIORITY_MIN (-I915_PRIORITY_MAX)
+};
+
 /**
  * Request queue structure.
  *
@@ -62,7 +92,7 @@ struct intel_signal_node {
  * The requests are reference counted.
  */
 struct drm_i915_gem_request {
-	struct fence fence;
+	struct dma_fence fence;
 	spinlock_t lock;
 
 	/** On Which ring this request was generated */
@@ -81,10 +111,39 @@ struct drm_i915_gem_request {
 	struct i915_gem_context *ctx;
 	struct intel_engine_cs *engine;
 	struct intel_ring *ring;
+	struct intel_timeline *timeline;
 	struct intel_signal_node signaling;
 
+	/* Fences for the various phases in the request's lifetime.
+	 *
+	 * The submit fence is used to await upon all of the request's
+	 * dependencies. When it is signaled, the request is ready to run.
+	 * It is used by the driver to then queue the request for execution.
+	 *
+	 * The execute fence is used to signal when the request has been
+	 * sent to hardware.
+	 *
+	 * It is illegal for the submit fence of one request to wait upon the
+	 * execute fence of an earlier request. It should be sufficient to
+	 * wait upon the submit fence of the earlier request.
+	 */
 	struct i915_sw_fence submit;
+	struct i915_sw_fence execute;
 	wait_queue_t submitq;
+	wait_queue_t execq;
+
+	/* A list of everyone we wait upon, and everyone who waits upon us.
+	 * Even though we will not be submitted to the hardware before the
+	 * submit fence is signaled (it waits for all external events as well
+	 * as our own requests), the scheduler still needs to know the
+	 * dependency tree for the lifetime of the request (from execbuf
+	 * to retirement), i.e. bidirectional dependency information for the
+	 * request not tied to individual fences.
+	 */
+	struct i915_priotree priotree;
+	struct i915_dependency dep;
+
+	u32 global_seqno;
 
 	/** GEM sequence number associated with the previous request,
 	 * when the HWS breadcrumb is equal to this the GPU is processing
@@ -140,14 +199,11 @@ struct drm_i915_gem_request {
 	struct drm_i915_file_private *file_priv;
 	/** file_priv list entry for this request */
 	struct list_head client_list;
-
-	/** Link in the execlist submission queue, guarded by execlist_lock. */
-	struct list_head execlist_link;
 };
 
-extern const struct fence_ops i915_fence_ops;
+extern const struct dma_fence_ops i915_fence_ops;
 
-static inline bool fence_is_i915(struct fence *fence)
+static inline bool dma_fence_is_i915(const struct dma_fence *fence)
 {
 	return fence->ops == &i915_fence_ops;
 }
@@ -159,43 +215,31 @@ int i915_gem_request_add_to_client(struc
 				   struct drm_file *file);
 void i915_gem_request_retire_upto(struct drm_i915_gem_request *req);
 
-static inline u32
-i915_gem_request_get_seqno(struct drm_i915_gem_request *req)
-{
-	return req ? req->fence.seqno : 0;
-}
-
-static inline struct intel_engine_cs *
-i915_gem_request_get_engine(struct drm_i915_gem_request *req)
-{
-	return req ? req->engine : NULL;
-}
-
 static inline struct drm_i915_gem_request *
-to_request(struct fence *fence)
+to_request(struct dma_fence *fence)
 {
 	/* We assume that NULL fence/request are interoperable */
 	BUILD_BUG_ON(offsetof(struct drm_i915_gem_request, fence) != 0);
-	GEM_BUG_ON(fence && !fence_is_i915(fence));
+	GEM_BUG_ON(fence && !dma_fence_is_i915(fence));
 	return container_of(fence, struct drm_i915_gem_request, fence);
 }
 
 static inline struct drm_i915_gem_request *
 i915_gem_request_get(struct drm_i915_gem_request *req)
 {
-	return to_request(fence_get(&req->fence));
+	return to_request(dma_fence_get(&req->fence));
 }
 
 static inline struct drm_i915_gem_request *
 i915_gem_request_get_rcu(struct drm_i915_gem_request *req)
 {
-	return to_request(fence_get_rcu(&req->fence));
+	return to_request(dma_fence_get_rcu(&req->fence));
 }
 
 static inline void
 i915_gem_request_put(struct drm_i915_gem_request *req)
 {
-	fence_put(&req->fence);
+	dma_fence_put(&req->fence);
 }
 
 static inline void i915_gem_request_assign(struct drm_i915_gem_request **pdst,
@@ -214,6 +258,8 @@ int
 i915_gem_request_await_object(struct drm_i915_gem_request *to,
 			      struct drm_i915_gem_object *obj,
 			      bool write);
+int i915_gem_request_await_dma_fence(struct drm_i915_gem_request *req,
+				     struct dma_fence *fence);
 
 void __i915_add_request(struct drm_i915_gem_request *req, bool flush_caches);
 #define i915_add_request(req) \
@@ -221,18 +267,21 @@ void __i915_add_request(struct drm_i915_
 #define i915_add_request_no_flush(req) \
 	__i915_add_request(req, false)
 
+void __i915_gem_request_submit(struct drm_i915_gem_request *request);
+void i915_gem_request_submit(struct drm_i915_gem_request *request);
+
 struct intel_rps_client;
 #define NO_WAITBOOST ERR_PTR(-1)
 #define IS_RPS_CLIENT(p) (!IS_ERR(p))
 #define IS_RPS_USER(p) (!IS_ERR_OR_NULL(p))
 
-int i915_wait_request(struct drm_i915_gem_request *req,
-		      unsigned int flags,
-		      s64 *timeout,
-		      struct intel_rps_client *rps)
+long i915_wait_request(struct drm_i915_gem_request *req,
+		       unsigned int flags,
+		       long timeout)
 	__attribute__((nonnull(1)));
 #define I915_WAIT_INTERRUPTIBLE	BIT(0)
 #define I915_WAIT_LOCKED	BIT(1) /* struct_mutex held, handle GPU reset */
+#define I915_WAIT_ALL		BIT(2) /* used by i915_gem_object_wait() */
 
 static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine);
 
@@ -245,17 +294,37 @@ static inline bool i915_seqno_passed(u32
 }
 
 static inline bool
-i915_gem_request_started(const struct drm_i915_gem_request *req)
+__i915_gem_request_started(const struct drm_i915_gem_request *req)
 {
+	GEM_BUG_ON(!req->global_seqno);
 	return i915_seqno_passed(intel_engine_get_seqno(req->engine),
 				 req->previous_seqno);
 }
 
 static inline bool
-i915_gem_request_completed(const struct drm_i915_gem_request *req)
+i915_gem_request_started(const struct drm_i915_gem_request *req)
 {
+	if (!req->global_seqno)
+		return false;
+
+	return __i915_gem_request_started(req);
+}
+
+static inline bool
+__i915_gem_request_completed(const struct drm_i915_gem_request *req)
+{
+	GEM_BUG_ON(!req->global_seqno);
 	return i915_seqno_passed(intel_engine_get_seqno(req->engine),
-				 req->fence.seqno);
+				 req->global_seqno);
+}
+
+static inline bool
+i915_gem_request_completed(const struct drm_i915_gem_request *req)
+{
+	if (!req->global_seqno)
+		return false;
+
+	return __i915_gem_request_completed(req);
 }
 
 bool __i915_spin_request(const struct drm_i915_gem_request *request,
@@ -263,7 +332,7 @@ bool __i915_spin_request(const struct dr
 static inline bool i915_spin_request(const struct drm_i915_gem_request *request,
 				     int state, unsigned long timeout_us)
 {
-	return (i915_gem_request_started(request) &&
+	return (__i915_gem_request_started(request) &&
 		__i915_spin_request(request, state, timeout_us));
 }
 
@@ -344,6 +413,25 @@ i915_gem_active_set(struct i915_gem_acti
 	rcu_assign_pointer(active->request, request);
 }
 
+/**
+ * i915_gem_active_set_retire_fn - updates the retirement callback
+ * @active - the active tracker
+ * @fn - the routine called when the request is retired
+ * @mutex - struct_mutex used to guard retirements
+ *
+ * i915_gem_active_set_retire_fn() updates the function pointer that
+ * is called when the final request associated with the @active tracker
+ * is retired.
+ */
+static inline void
+i915_gem_active_set_retire_fn(struct i915_gem_active *active,
+			      i915_gem_retire_fn fn,
+			      struct mutex *mutex)
+{
+	lockdep_assert_held(mutex);
+	active->retire = fn ?: i915_gem_retire_noop;
+}
+
 static inline struct drm_i915_gem_request *
 __i915_gem_active_peek(const struct i915_gem_active *active)
 {
@@ -497,7 +585,7 @@ __i915_gem_active_get_rcu(const struct i
 		 * compiler.
 		 *
 		 * The atomic operation at the heart of
-		 * i915_gem_request_get_rcu(), see fence_get_rcu(), is
+		 * i915_gem_request_get_rcu(), see dma_fence_get_rcu(), is
 		 * atomic_inc_not_zero() which is only a full memory barrier
 		 * when successful. That is, if i915_gem_request_get_rcu()
 		 * returns the request (and so with the reference counted
@@ -552,53 +640,13 @@ i915_gem_active_isset(const struct i915_
 }
 
 /**
- * i915_gem_active_is_idle - report whether the active tracker is idle
- * @active - the active tracker
- *
- * i915_gem_active_is_idle() returns true if the active tracker is currently
- * unassigned or if the request is complete (but not yet retired). Requires
- * the caller to hold struct_mutex (but that can be relaxed if desired).
- */
-static inline bool
-i915_gem_active_is_idle(const struct i915_gem_active *active,
-			struct mutex *mutex)
-{
-	return !i915_gem_active_peek(active, mutex);
-}
-
-/**
  * i915_gem_active_wait - waits until the request is completed
  * @active - the active request on which to wait
- *
- * i915_gem_active_wait() waits until the request is completed before
- * returning. Note that it does not guarantee that the request is
- * retired first, see i915_gem_active_retire().
- *
- * i915_gem_active_wait() returns immediately if the active
- * request is already complete.
- */
-static inline int __must_check
-i915_gem_active_wait(const struct i915_gem_active *active, struct mutex *mutex)
-{
-	struct drm_i915_gem_request *request;
-
-	request = i915_gem_active_peek(active, mutex);
-	if (!request)
-		return 0;
-
-	return i915_wait_request(request,
-				 I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
-				 NULL, NULL);
-}
-
-/**
- * i915_gem_active_wait_unlocked - waits until the request is completed
- * @active - the active request on which to wait
  * @flags - how to wait
  * @timeout - how long to wait at most
  * @rps - userspace client to charge for a waitboost
  *
- * i915_gem_active_wait_unlocked() waits until the request is completed before
+ * i915_gem_active_wait() waits until the request is completed before
  * returning, without requiring any locks to be held. Note that it does not
  * retire any requests before returning.
  *
@@ -614,21 +662,18 @@ i915_gem_active_wait(const struct i915_g
  * Returns 0 if successful, or a negative error code.
  */
 static inline int
-i915_gem_active_wait_unlocked(const struct i915_gem_active *active,
-			      unsigned int flags,
-			      s64 *timeout,
-			      struct intel_rps_client *rps)
+i915_gem_active_wait(const struct i915_gem_active *active, unsigned int flags)
 {
 	struct drm_i915_gem_request *request;
-	int ret = 0;
+	long ret = 0;
 
 	request = i915_gem_active_get_unlocked(active);
 	if (request) {
-		ret = i915_wait_request(request, flags, timeout, rps);
+		ret = i915_wait_request(request, flags, MAX_SCHEDULE_TIMEOUT);
 		i915_gem_request_put(request);
 	}
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 /**
@@ -645,7 +690,7 @@ i915_gem_active_retire(struct i915_gem_a
 		       struct mutex *mutex)
 {
 	struct drm_i915_gem_request *request;
-	int ret;
+	long ret;
 
 	request = i915_gem_active_raw(active, mutex);
 	if (!request)
@@ -653,8 +698,8 @@ i915_gem_active_retire(struct i915_gem_a
 
 	ret = i915_wait_request(request,
 				I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
-				NULL, NULL);
-	if (ret)
+				MAX_SCHEDULE_TIMEOUT);
+	if (ret < 0)
 		return ret;
 
 	list_del_init(&active->link);
@@ -665,24 +710,6 @@ i915_gem_active_retire(struct i915_gem_a
 	return 0;
 }
 
-/* Convenience functions for peeking at state inside active's request whilst
- * guarded by the struct_mutex.
- */
-
-static inline uint32_t
-i915_gem_active_get_seqno(const struct i915_gem_active *active,
-			  struct mutex *mutex)
-{
-	return i915_gem_request_get_seqno(i915_gem_active_peek(active, mutex));
-}
-
-static inline struct intel_engine_cs *
-i915_gem_active_get_engine(const struct i915_gem_active *active,
-			   struct mutex *mutex)
-{
-	return i915_gem_request_get_engine(i915_gem_active_peek(active, mutex));
-}
-
 #define for_each_active(mask, idx) \
 	for (; mask ? idx = ffs(mask) - 1, 1 : 0; mask &= ~BIT(idx))
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_shrinker.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,17 +35,22 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 
-static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
+static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
 {
-	if (!mutex_is_locked(mutex))
+	switch (mutex_trylock_recursive(&dev->struct_mutex)) {
+	case MUTEX_TRYLOCK_FAILED:
 		return false;
 
-#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
-	return mutex->owner == task;
-#else
-	/* Since UP may be pre-empted, we cannot assume that we own the lock */
-	return false;
-#endif
+	case MUTEX_TRYLOCK_SUCCESS:
+		*unlock = true;
+		return true;
+
+	case MUTEX_TRYLOCK_RECURSIVE:
+		*unlock = false;
+		return true;
+	}
+
+	BUG();
 }
 
 static bool any_vma_pinned(struct drm_i915_gem_object *obj)
@@ -66,8 +71,11 @@ static bool swap_available(void)
 
 static bool can_release_pages(struct drm_i915_gem_object *obj)
 {
-	/* Only shmemfs objects are backed by swap */
-	if (!obj->base.filp)
+	if (!obj->mm.pages)
+		return false;
+
+	/* Consider only shrinkable ojects. */
+	if (!i915_gem_object_is_shrinkable(obj))
 		return false;
 
 	/* Only report true if by unbinding the object and putting its pages
@@ -78,7 +86,7 @@ static bool can_release_pages(struct drm
 	 * to the GPU, simply unbinding from the GPU is not going to succeed
 	 * in releasing our pin count on the pages themselves.
 	 */
-	if (obj->pages_pin_count > obj->bind_count)
+	if (atomic_read(&obj->mm.pages_pin_count) > obj->bind_count)
 		return false;
 
 	if (any_vma_pinned(obj))
@@ -88,7 +96,14 @@ static bool can_release_pages(struct drm
 	 * discard the contents (because the user has marked them as being
 	 * purgeable) or if we can move their contents out to swap.
 	 */
-	return swap_available() || obj->madv == I915_MADV_DONTNEED;
+	return swap_available() || obj->mm.madv == I915_MADV_DONTNEED;
+}
+
+static bool unsafe_drop_pages(struct drm_i915_gem_object *obj)
+{
+	if (i915_gem_object_unbind(obj) == 0)
+		__i915_gem_object_put_pages(obj, I915_MM_SHRINKER);
+	return !READ_ONCE(obj->mm.pages);
 }
 
 /**
@@ -128,6 +143,10 @@ i915_gem_shrink(struct drm_i915_private
 		{ NULL, 0 },
 	}, *phase;
 	unsigned long count = 0;
+	bool unlock;
+
+	if (!i915_gem_shrinker_lock(&dev_priv->drm, &unlock))
+		return 0;
 
 	trace_i915_gem_shrink(dev_priv, target, flags);
 	i915_gem_retire_requests(dev_priv);
@@ -171,40 +190,51 @@ i915_gem_shrink(struct drm_i915_private
 		while (count < target &&
 		       (obj = list_first_entry_or_null(phase->list,
 						       typeof(*obj),
-						       global_list))) {
-			list_move_tail(&obj->global_list, &still_in_list);
+						       global_link))) {
+			list_move_tail(&obj->global_link, &still_in_list);
+			if (!obj->mm.pages) {
+				list_del_init(&obj->global_link);
+				continue;
+			}
 
 			if (flags & I915_SHRINK_PURGEABLE &&
-			    obj->madv != I915_MADV_DONTNEED)
+			    obj->mm.madv != I915_MADV_DONTNEED)
 				continue;
 
 			if (flags & I915_SHRINK_VMAPS &&
-			    !is_vmalloc_addr(obj->mapping))
+			    !is_vmalloc_addr(obj->mm.mapping))
 				continue;
 
-			if ((flags & I915_SHRINK_ACTIVE) == 0 &&
-			    i915_gem_object_is_active(obj))
+			if (!(flags & I915_SHRINK_ACTIVE) &&
+			    (i915_gem_object_is_active(obj) ||
+			     obj->framebuffer_references))
 				continue;
 
 			if (!can_release_pages(obj))
 				continue;
 
-			i915_gem_object_get(obj);
-
-			/* For the unbound phase, this should be a no-op! */
-			i915_gem_object_unbind(obj);
-			if (i915_gem_object_put_pages(obj) == 0)
-				count += obj->base.size >> PAGE_SHIFT;
-
-			i915_gem_object_put(obj);
+			if (unsafe_drop_pages(obj)) {
+				/* May arrive from get_pages on another bo */
+				mutex_lock_nested(&obj->mm.lock,
+						  I915_MM_SHRINKER);
+				if (!obj->mm.pages) {
+					__i915_gem_object_invalidate(obj);
+					list_del_init(&obj->global_link);
+					count += obj->base.size >> PAGE_SHIFT;
+				}
+				mutex_unlock(&obj->mm.lock);
+			}
 		}
-		list_splice(&still_in_list, phase->list);
+		list_splice_tail(&still_in_list, phase->list);
 	}
 
 	if (flags & I915_SHRINK_BOUND)
 		intel_runtime_pm_put(dev_priv);
 
 	i915_gem_retire_requests(dev_priv);
+	if (unlock)
+		mutex_unlock(&dev_priv->drm.struct_mutex);
+
 	/* expedite the RCU grace period to free some request slabs */
 	synchronize_rcu_expedited();
 
@@ -238,19 +268,6 @@ unsigned long i915_gem_shrink_all(struct
 	return freed;
 }
 
-static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
-{
-	if (!mutex_trylock(&dev->struct_mutex)) {
-		if (!mutex_is_locked_by(&dev->struct_mutex, current))
-			return false;
-
-		*unlock = false;
-	} else
-		*unlock = true;
-
-	return true;
-}
-
 static unsigned long
 i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
 {
@@ -267,11 +284,11 @@ i915_gem_shrinker_count(struct shrinker
 	i915_gem_retire_requests(dev_priv);
 
 	count = 0;
-	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link)
 		if (can_release_pages(obj))
 			count += obj->base.size >> PAGE_SHIFT;
 
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
 		if (!i915_gem_object_is_active(obj) && can_release_pages(obj))
 			count += obj->base.size >> PAGE_SHIFT;
 	}
@@ -372,13 +389,19 @@ i915_gem_shrinker_oom(struct notifier_bl
 	 * being pointed to by hardware.
 	 */
 	unbound = bound = unevictable = 0;
-	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) {
+		if (!obj->mm.pages)
+			continue;
+
 		if (!can_release_pages(obj))
 			unevictable += obj->base.size >> PAGE_SHIFT;
 		else
 			unbound += obj->base.size >> PAGE_SHIFT;
 	}
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
+	list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) {
+		if (!obj->mm.pages)
+			continue;
+
 		if (!can_release_pages(obj))
 			unevictable += obj->base.size >> PAGE_SHIFT;
 		else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_stolen.c	2017-02-12 16:03:20.000000000 -0500
@@ -55,10 +55,9 @@ int i915_gem_stolen_insert_node_in_range
 		return -ENODEV;
 
 	/* See the comment at the drm_mm_init() call for more about this check.
-	 * WaSkipStolenMemoryFirstPage:bdw,chv,kbl (incomplete)
+	 * WaSkipStolenMemoryFirstPage:bdw+ (incomplete)
 	 */
-	if (start < 4096 && (IS_GEN8(dev_priv) ||
-			     IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0)))
+	if (start < 4096 && INTEL_GEN(dev_priv) >= 8)
 		start = 4096;
 
 	mutex_lock(&dev_priv->mm.stolen_lock);
@@ -89,9 +88,8 @@ void i915_gem_stolen_remove_node(struct
 	mutex_unlock(&dev_priv->mm.stolen_lock);
 }
 
-static unsigned long i915_stolen_to_physical(struct drm_device *dev)
+static unsigned long i915_stolen_to_physical(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct resource *r;
@@ -109,13 +107,13 @@ static unsigned long i915_stolen_to_phys
 	 *
 	 */
 	base = 0;
-	if (INTEL_INFO(dev)->gen >= 3) {
+	if (INTEL_GEN(dev_priv) >= 3) {
 		u32 bsm;
 
 		pci_read_config_dword(pdev, INTEL_BSM, &bsm);
 
 		base = bsm & INTEL_BSM_MASK;
-	} else if (IS_I865G(dev)) {
+	} else if (IS_I865G(dev_priv)) {
 		u32 tseg_size = 0;
 		u16 toud = 0;
 		u8 tmp;
@@ -138,7 +136,7 @@ static unsigned long i915_stolen_to_phys
 					 I865_TOUD, &toud);
 
 		base = (toud << 16) + tseg_size;
-	} else if (IS_I85X(dev)) {
+	} else if (IS_I85X(dev_priv)) {
 		u32 tseg_size = 0;
 		u32 tom;
 		u8 tmp;
@@ -154,7 +152,7 @@ static unsigned long i915_stolen_to_phys
 		tom = tmp * MB(32);
 
 		base = tom - tseg_size - ggtt->stolen_size;
-	} else if (IS_845G(dev)) {
+	} else if (IS_845G(dev_priv)) {
 		u32 tseg_size = 0;
 		u32 tom;
 		u8 tmp;
@@ -178,7 +176,7 @@ static unsigned long i915_stolen_to_phys
 		tom = tmp * MB(32);
 
 		base = tom - tseg_size - ggtt->stolen_size;
-	} else if (IS_I830(dev)) {
+	} else if (IS_I830(dev_priv)) {
 		u32 tseg_size = 0;
 		u32 tom;
 		u8 tmp;
@@ -204,7 +202,8 @@ static unsigned long i915_stolen_to_phys
 		return 0;
 
 	/* make sure we don't clobber the GTT if it's within stolen memory */
-	if (INTEL_INFO(dev)->gen <= 4 && !IS_G33(dev) && !IS_G4X(dev)) {
+	if (INTEL_GEN(dev_priv) <= 4 && !IS_G33(dev_priv) &&
+	    !IS_G4X(dev_priv)) {
 		struct {
 			u32 start, end;
 		} stolen[2] = {
@@ -214,7 +213,7 @@ static unsigned long i915_stolen_to_phys
 		u64 ggtt_start, ggtt_end;
 
 		ggtt_start = I915_READ(PGTBL_CTL);
-		if (IS_GEN4(dev))
+		if (IS_GEN4(dev_priv))
 			ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) |
 				     (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
 		else
@@ -252,7 +251,7 @@ static unsigned long i915_stolen_to_phys
 	 * kernel. So if the region is already marked as busy, something
 	 * is seriously wrong.
 	 */
-	r = devm_request_mem_region(dev->dev, base, ggtt->stolen_size,
+	r = devm_request_mem_region(dev_priv->drm.dev, base, ggtt->stolen_size,
 				    "Graphics Stolen Memory");
 	if (r == NULL) {
 		/*
@@ -263,14 +262,14 @@ static unsigned long i915_stolen_to_phys
 		 * PCI bus, but have an off-by-one error. Hence retry the
 		 * reservation starting from 1 instead of 0.
 		 */
-		r = devm_request_mem_region(dev->dev, base + 1,
+		r = devm_request_mem_region(dev_priv->drm.dev, base + 1,
 					    ggtt->stolen_size - 1,
 					    "Graphics Stolen Memory");
 		/*
 		 * GEN3 firmware likes to smash pci bridges into the stolen
 		 * range. Apparently this works.
 		 */
-		if (r == NULL && !IS_GEN3(dev)) {
+		if (r == NULL && !IS_GEN3(dev_priv)) {
 			DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
 				  base, base + (uint32_t)ggtt->stolen_size);
 			base = 0;
@@ -407,9 +406,8 @@ static void bdw_get_stolen_reserved(stru
 		*size = stolen_top - *base;
 }
 
-int i915_gem_init_stolen(struct drm_device *dev)
+int i915_gem_init_stolen(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	unsigned long reserved_total, reserved_base = 0, reserved_size;
 	unsigned long stolen_top;
@@ -417,7 +415,7 @@ int i915_gem_init_stolen(struct drm_devi
 	mutex_init(&dev_priv->mm.stolen_lock);
 
 #ifdef CONFIG_INTEL_IOMMU
-	if (intel_iommu_gfx_mapped && INTEL_INFO(dev)->gen < 8) {
+	if (intel_iommu_gfx_mapped && INTEL_GEN(dev_priv) < 8) {
 		DRM_INFO("DMAR active, disabling use of stolen memory\n");
 		return 0;
 	}
@@ -426,7 +424,7 @@ int i915_gem_init_stolen(struct drm_devi
 	if (ggtt->stolen_size == 0)
 		return 0;
 
-	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
+	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev_priv);
 	if (dev_priv->mm.stolen_base == 0)
 		return 0;
 
@@ -437,7 +435,7 @@ int i915_gem_init_stolen(struct drm_devi
 	case 3:
 		break;
 	case 4:
-		if (IS_G4X(dev))
+		if (IS_G4X(dev_priv))
 			g4x_get_stolen_reserved(dev_priv, &reserved_base,
 						&reserved_size);
 		break;
@@ -456,7 +454,7 @@ int i915_gem_init_stolen(struct drm_devi
 		break;
 	default:
 		if (IS_BROADWELL(dev_priv) ||
-		    IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev))
+		    IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 			bdw_get_stolen_reserved(dev_priv, &reserved_base,
 						&reserved_size);
 		else
@@ -514,12 +512,10 @@ i915_pages_create_for_stolen(struct drm_
 			     u32 offset, u32 size)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct i915_ggtt *ggtt = &dev_priv->ggtt;
 	struct sg_table *st;
 	struct scatterlist *sg;
 
-	DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
-	BUG_ON(offset > ggtt->stolen_size - size);
+	GEM_BUG_ON(offset > dev_priv->ggtt.stolen_size - size);
 
 	/* We hide that we have no struct page backing our stolen object
 	 * by wrapping the contiguous physical allocation with a fake
@@ -528,11 +524,11 @@ i915_pages_create_for_stolen(struct drm_
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (st == NULL)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
 		kfree(st);
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	}
 
 	sg = st->sgl;
@@ -545,31 +541,36 @@ i915_pages_create_for_stolen(struct drm_
 	return st;
 }
 
-static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
+static struct sg_table *
+i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
 {
-	BUG();
-	return -EINVAL;
+	return i915_pages_create_for_stolen(obj->base.dev,
+					    obj->stolen->start,
+					    obj->stolen->size);
 }
 
-static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj)
+static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj,
+					     struct sg_table *pages)
 {
-	/* Should only be called during free */
-	sg_free_table(obj->pages);
-	kfree(obj->pages);
+	/* Should only be called from i915_gem_object_release_stolen() */
+	sg_free_table(pages);
+	kfree(pages);
 }
 
-
 static void
 i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
 {
 	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	struct drm_mm_node *stolen = fetch_and_zero(&obj->stolen);
 
-	if (obj->stolen) {
-		i915_gem_stolen_remove_node(dev_priv, obj->stolen);
-		kfree(obj->stolen);
-		obj->stolen = NULL;
-	}
+	GEM_BUG_ON(!stolen);
+
+	__i915_gem_object_unpin_pages(obj);
+
+	i915_gem_stolen_remove_node(dev_priv, stolen);
+	kfree(stolen);
 }
+
 static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = {
 	.get_pages = i915_gem_object_get_pages_stolen,
 	.put_pages = i915_gem_object_put_pages_stolen,
@@ -589,19 +590,13 @@ _i915_gem_object_create_stolen(struct dr
 	drm_gem_private_object_init(dev, &obj->base, stolen->size);
 	i915_gem_object_init(obj, &i915_gem_object_stolen_ops);
 
-	obj->pages = i915_pages_create_for_stolen(dev,
-						  stolen->start, stolen->size);
-	if (obj->pages == NULL)
-		goto cleanup;
-
-	obj->get_page.sg = obj->pages->sgl;
-	obj->get_page.last = 0;
-
-	i915_gem_object_pin_pages(obj);
 	obj->stolen = stolen;
-
 	obj->base.read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT;
-	obj->cache_level = HAS_LLC(dev) ? I915_CACHE_LLC : I915_CACHE_NONE;
+	obj->cache_level = HAS_LLC(to_i915(dev)) ?
+			   I915_CACHE_LLC : I915_CACHE_NONE;
+
+	if (i915_gem_object_pin_pages(obj))
+		goto cleanup;
 
 	return obj;
 
@@ -621,7 +616,6 @@ i915_gem_object_create_stolen(struct drm
 	if (!drm_mm_initialized(&dev_priv->mm.stolen))
 		return NULL;
 
-	DRM_DEBUG_KMS("creating stolen object: size=%x\n", size);
 	if (size == 0)
 		return NULL;
 
@@ -697,10 +691,14 @@ i915_gem_object_create_stolen_for_preall
 	if (gtt_offset == I915_GTT_OFFSET_NONE)
 		return obj;
 
+	ret = i915_gem_object_pin_pages(obj);
+	if (ret)
+		goto err;
+
 	vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base, NULL);
 	if (IS_ERR(vma)) {
 		ret = PTR_ERR(vma);
-		goto err;
+		goto err_pages;
 	}
 
 	/* To simplify the initialisation sequence between KMS and GTT,
@@ -714,20 +712,20 @@ i915_gem_object_create_stolen_for_preall
 	ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node);
 	if (ret) {
 		DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
-		goto err;
+		goto err_pages;
 	}
 
-	vma->pages = obj->pages;
+	vma->pages = obj->mm.pages;
 	vma->flags |= I915_VMA_GLOBAL_BIND;
 	__i915_vma_set_map_and_fenceable(vma);
 	list_move_tail(&vma->vm_link, &ggtt->base.inactive_list);
+	list_move_tail(&obj->global_link, &dev_priv->mm.bound_list);
 	obj->bind_count++;
 
-	list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
-	i915_gem_object_pin_pages(obj);
-
 	return obj;
 
+err_pages:
+	i915_gem_object_unpin_pages(obj);
 err:
 	i915_gem_object_put(obj);
 	return NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2017-02-12 16:03:20.000000000 -0500
@@ -60,7 +60,8 @@
 
 /* Check pitch constriants for all chips & tiling formats */
 static bool
-i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
+i915_tiling_ok(struct drm_i915_private *dev_priv,
+	       int stride, int size, int tiling_mode)
 {
 	int tile_width;
 
@@ -71,8 +72,8 @@ i915_tiling_ok(struct drm_device *dev, i
 	if (tiling_mode > I915_TILING_LAST)
 		return false;
 
-	if (IS_GEN2(dev) ||
-	    (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
+	if (IS_GEN2(dev_priv) ||
+	    (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev_priv)))
 		tile_width = 128;
 	else
 		tile_width = 512;
@@ -80,17 +81,17 @@ i915_tiling_ok(struct drm_device *dev, i
 	/* check maximum stride & object size */
 	/* i965+ stores the end address of the gtt mapping in the fence
 	 * reg, so dont bother to check the size */
-	if (INTEL_INFO(dev)->gen >= 7) {
+	if (INTEL_GEN(dev_priv) >= 7) {
 		if (stride / 128 > GEN7_FENCE_MAX_PITCH_VAL)
 			return false;
-	} else if (INTEL_INFO(dev)->gen >= 4) {
+	} else if (INTEL_GEN(dev_priv) >= 4) {
 		if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
 			return false;
 	} else {
 		if (stride > 8192)
 			return false;
 
-		if (IS_GEN3(dev)) {
+		if (IS_GEN3(dev_priv)) {
 			if (size > I830_FENCE_MAX_SIZE_VAL << 20)
 				return false;
 		} else {
@@ -103,7 +104,7 @@ i915_tiling_ok(struct drm_device *dev, i
 		return false;
 
 	/* 965+ just needs multiples of tile width */
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		if (stride & (tile_width - 1))
 			return false;
 		return true;
@@ -198,14 +199,12 @@ i915_gem_set_tiling(struct drm_device *d
 	if (!obj)
 		return -ENOENT;
 
-	if (!i915_tiling_ok(dev,
+	if (!i915_tiling_ok(dev_priv,
 			    args->stride, obj->base.size, args->tiling_mode)) {
-		i915_gem_object_put_unlocked(obj);
+		i915_gem_object_put(obj);
 		return -EINVAL;
 	}
 
-	intel_runtime_pm_get(dev_priv);
-
 	mutex_lock(&dev->struct_mutex);
 	if (obj->pin_display || obj->framebuffer_references) {
 		err = -EBUSY;
@@ -260,14 +259,22 @@ i915_gem_set_tiling(struct drm_device *d
 		if (!err) {
 			struct i915_vma *vma;
 
-			if (obj->pages &&
-			    obj->madv == I915_MADV_WILLNEED &&
+			mutex_lock(&obj->mm.lock);
+			if (obj->mm.pages &&
+			    obj->mm.madv == I915_MADV_WILLNEED &&
 			    dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
-				if (args->tiling_mode == I915_TILING_NONE)
-					i915_gem_object_unpin_pages(obj);
-				if (!i915_gem_object_is_tiled(obj))
-					i915_gem_object_pin_pages(obj);
+				if (args->tiling_mode == I915_TILING_NONE) {
+					GEM_BUG_ON(!obj->mm.quirked);
+					__i915_gem_object_unpin_pages(obj);
+					obj->mm.quirked = false;
+				}
+				if (!i915_gem_object_is_tiled(obj)) {
+					GEM_BUG_ON(!obj->mm.quirked);
+					__i915_gem_object_pin_pages(obj);
+					obj->mm.quirked = true;
+				}
 			}
+			mutex_unlock(&obj->mm.lock);
 
 			list_for_each_entry(vma, &obj->vma_list, obj_link) {
 				if (!vma->fence)
@@ -301,8 +308,6 @@ err:
 	i915_gem_object_put(obj);
 	mutex_unlock(&dev->struct_mutex);
 
-	intel_runtime_pm_put(dev_priv);
-
 	return err;
 }
 
@@ -326,12 +331,19 @@ i915_gem_get_tiling(struct drm_device *d
 	struct drm_i915_gem_get_tiling *args = data;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_object *obj;
+	int err = -ENOENT;
 
-	obj = i915_gem_object_lookup(file, args->handle);
-	if (!obj)
-		return -ENOENT;
+	rcu_read_lock();
+	obj = i915_gem_object_lookup_rcu(file, args->handle);
+	if (obj) {
+		args->tiling_mode =
+			READ_ONCE(obj->tiling_and_stride) & TILING_MASK;
+		err = 0;
+	}
+	rcu_read_unlock();
+	if (unlikely(err))
+		return err;
 
-	args->tiling_mode = READ_ONCE(obj->tiling_and_stride) & TILING_MASK;
 	switch (args->tiling_mode) {
 	case I915_TILING_X:
 		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
@@ -339,11 +351,10 @@ i915_gem_get_tiling(struct drm_device *d
 	case I915_TILING_Y:
 		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
 		break;
+	default:
 	case I915_TILING_NONE:
 		args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
 		break;
-	default:
-		DRM_ERROR("unknown tiling mode\n");
 	}
 
 	/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
@@ -356,6 +367,5 @@ i915_gem_get_tiling(struct drm_device *d
 	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
 		args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
 
-	i915_gem_object_put_unlocked(obj);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_timeline.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_timeline.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_timeline.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_timeline.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_drv.h"
+
+static int __i915_gem_timeline_init(struct drm_i915_private *i915,
+				    struct i915_gem_timeline *timeline,
+				    const char *name,
+				    struct lock_class_key *lockclass,
+				    const char *lockname)
+{
+	unsigned int i;
+	u64 fences;
+
+	lockdep_assert_held(&i915->drm.struct_mutex);
+
+	timeline->i915 = i915;
+	timeline->name = kstrdup(name ?: "[kernel]", GFP_KERNEL);
+	if (!timeline->name)
+		return -ENOMEM;
+
+	list_add(&timeline->link, &i915->gt.timelines);
+
+	/* Called during early_init before we know how many engines there are */
+	fences = dma_fence_context_alloc(ARRAY_SIZE(timeline->engine));
+	for (i = 0; i < ARRAY_SIZE(timeline->engine); i++) {
+		struct intel_timeline *tl = &timeline->engine[i];
+
+		tl->fence_context = fences++;
+		tl->common = timeline;
+#ifdef CONFIG_DEBUG_SPINLOCK
+		__raw_spin_lock_init(&tl->lock.rlock, lockname, lockclass);
+#else
+		spin_lock_init(&tl->lock);
+#endif
+		init_request_active(&tl->last_request, NULL);
+		INIT_LIST_HEAD(&tl->requests);
+	}
+
+	return 0;
+}
+
+int i915_gem_timeline_init(struct drm_i915_private *i915,
+			   struct i915_gem_timeline *timeline,
+			   const char *name)
+{
+	static struct lock_class_key class;
+
+	return __i915_gem_timeline_init(i915, timeline, name,
+					&class, "&timeline->lock");
+}
+
+int i915_gem_timeline_init__global(struct drm_i915_private *i915)
+{
+	static struct lock_class_key class;
+
+	return __i915_gem_timeline_init(i915,
+					&i915->gt.global_timeline,
+					"[execution]",
+					&class, "&global_timeline->lock");
+}
+
+void i915_gem_timeline_fini(struct i915_gem_timeline *tl)
+{
+	lockdep_assert_held(&tl->i915->drm.struct_mutex);
+
+	list_del(&tl->link);
+	kfree(tl->name);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_timeline.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_timeline.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_timeline.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_timeline.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef I915_GEM_TIMELINE_H
+#define I915_GEM_TIMELINE_H
+
+#include <linux/list.h>
+
+#include "i915_gem_request.h"
+
+struct i915_gem_timeline;
+
+struct intel_timeline {
+	u64 fence_context;
+	u32 last_submitted_seqno;
+
+	spinlock_t lock;
+
+	/**
+	 * List of breadcrumbs associated with GPU requests currently
+	 * outstanding.
+	 */
+	struct list_head requests;
+
+	/* Contains an RCU guarded pointer to the last request. No reference is
+	 * held to the request, users must carefully acquire a reference to
+	 * the request using i915_gem_active_get_request_rcu(), or hold the
+	 * struct_mutex.
+	 */
+	struct i915_gem_active last_request;
+	u32 sync_seqno[I915_NUM_ENGINES];
+
+	struct i915_gem_timeline *common;
+};
+
+struct i915_gem_timeline {
+	struct list_head link;
+	atomic_t next_seqno;
+
+	struct drm_i915_private *i915;
+	const char *name;
+
+	struct intel_timeline engine[I915_NUM_ENGINES];
+};
+
+int i915_gem_timeline_init(struct drm_i915_private *i915,
+			   struct i915_gem_timeline *tl,
+			   const char *name);
+int i915_gem_timeline_init__global(struct drm_i915_private *i915);
+void i915_gem_timeline_fini(struct i915_gem_timeline *tl);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gem_userptr.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,33 +61,26 @@ struct i915_mmu_object {
 	bool attached;
 };
 
-static void wait_rendering(struct drm_i915_gem_object *obj)
-{
-	unsigned long active = __I915_BO_ACTIVE(obj);
-	int idx;
-
-	for_each_active(active, idx)
-		i915_gem_active_wait_unlocked(&obj->last_read[idx],
-					      0, NULL, NULL);
-}
-
 static void cancel_userptr(struct work_struct *work)
 {
 	struct i915_mmu_object *mo = container_of(work, typeof(*mo), work);
 	struct drm_i915_gem_object *obj = mo->obj;
 	struct drm_device *dev = obj->base.dev;
 
-	wait_rendering(obj);
+	i915_gem_object_wait(obj, I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT, NULL);
 
 	mutex_lock(&dev->struct_mutex);
 	/* Cancel any active worker and force us to re-evaluate gup */
 	obj->userptr.work = NULL;
 
-	if (obj->pages != NULL) {
-		/* We are inside a kthread context and can't be interrupted */
-		WARN_ON(i915_gem_object_unbind(obj));
-		WARN_ON(i915_gem_object_put_pages(obj));
-	}
+	/* We are inside a kthread context and can't be interrupted */
+	if (i915_gem_object_unbind(obj) == 0)
+		__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
+	WARN_ONCE(obj->mm.pages,
+		  "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_display=%d\n",
+		  obj->bind_count,
+		  atomic_read(&obj->mm.pages_pin_count),
+		  obj->pin_display);
 
 	i915_gem_object_put(obj);
 	mutex_unlock(&dev->struct_mutex);
@@ -436,24 +429,25 @@ err:
 	return ret;
 }
 
-static int
+static struct sg_table *
 __i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj,
 			     struct page **pvec, int num_pages)
 {
+	struct sg_table *pages;
 	int ret;
 
-	ret = st_set_pages(&obj->pages, pvec, num_pages);
+	ret = st_set_pages(&pages, pvec, num_pages);
 	if (ret)
-		return ret;
+		return ERR_PTR(ret);
 
-	ret = i915_gem_gtt_prepare_object(obj);
+	ret = i915_gem_gtt_prepare_pages(obj, pages);
 	if (ret) {
-		sg_free_table(obj->pages);
-		kfree(obj->pages);
-		obj->pages = NULL;
+		sg_free_table(pages);
+		kfree(pages);
+		return ERR_PTR(ret);
 	}
 
-	return ret;
+	return pages;
 }
 
 static int
@@ -497,7 +491,6 @@ __i915_gem_userptr_get_pages_worker(stru
 {
 	struct get_pages_work *work = container_of(_work, typeof(*work), work);
 	struct drm_i915_gem_object *obj = work->obj;
-	struct drm_device *dev = obj->base.dev;
 	const int npages = obj->base.size >> PAGE_SHIFT;
 	struct page **pvec;
 	int pinned, ret;
@@ -522,7 +515,7 @@ __i915_gem_userptr_get_pages_worker(stru
 					 obj->userptr.ptr + pinned * PAGE_SIZE,
 					 npages - pinned,
 					 flags,
-					 pvec + pinned, NULL);
+					 pvec + pinned, NULL, NULL);
 				if (ret < 0)
 					break;
 
@@ -533,33 +526,32 @@ __i915_gem_userptr_get_pages_worker(stru
 		}
 	}
 
-	mutex_lock(&dev->struct_mutex);
+	mutex_lock(&obj->mm.lock);
 	if (obj->userptr.work == &work->work) {
+		struct sg_table *pages = ERR_PTR(ret);
+
 		if (pinned == npages) {
-			ret = __i915_gem_userptr_set_pages(obj, pvec, npages);
-			if (ret == 0) {
-				list_add_tail(&obj->global_list,
-					      &to_i915(dev)->mm.unbound_list);
-				obj->get_page.sg = obj->pages->sgl;
-				obj->get_page.last = 0;
+			pages = __i915_gem_userptr_set_pages(obj, pvec, npages);
+			if (!IS_ERR(pages)) {
+				__i915_gem_object_set_pages(obj, pages);
 				pinned = 0;
+				pages = NULL;
 			}
 		}
-		obj->userptr.work = ERR_PTR(ret);
-	}
 
-	obj->userptr.workers--;
-	i915_gem_object_put(obj);
-	mutex_unlock(&dev->struct_mutex);
+		obj->userptr.work = ERR_CAST(pages);
+	}
+	mutex_unlock(&obj->mm.lock);
 
 	release_pages(pvec, pinned, 0);
 	drm_free_large(pvec);
 
+	i915_gem_object_put(obj);
 	put_task_struct(work->task);
 	kfree(work);
 }
 
-static int
+static struct sg_table *
 __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj,
 				      bool *active)
 {
@@ -584,15 +576,11 @@ __i915_gem_userptr_get_pages_schedule(st
 	 * that error back to this function through
 	 * obj->userptr.work = ERR_PTR.
 	 */
-	if (obj->userptr.workers >= I915_GEM_USERPTR_MAX_WORKERS)
-		return -EAGAIN;
-
 	work = kmalloc(sizeof(*work), GFP_KERNEL);
 	if (work == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	obj->userptr.work = &work->work;
-	obj->userptr.workers++;
 
 	work->obj = i915_gem_object_get(obj);
 
@@ -603,14 +591,15 @@ __i915_gem_userptr_get_pages_schedule(st
 	schedule_work(&work->work);
 
 	*active = true;
-	return -EAGAIN;
+	return ERR_PTR(-EAGAIN);
 }
 
-static int
+static struct sg_table *
 i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 {
 	const int num_pages = obj->base.size >> PAGE_SHIFT;
 	struct page **pvec;
+	struct sg_table *pages;
 	int pinned, ret;
 	bool active;
 
@@ -634,15 +623,15 @@ i915_gem_userptr_get_pages(struct drm_i9
 	if (obj->userptr.work) {
 		/* active flag should still be held for the pending work */
 		if (IS_ERR(obj->userptr.work))
-			return PTR_ERR(obj->userptr.work);
+			return ERR_CAST(obj->userptr.work);
 		else
-			return -EAGAIN;
+			return ERR_PTR(-EAGAIN);
 	}
 
 	/* Let the mmu-notifier know that we have begun and need cancellation */
 	ret = __i915_gem_userptr_set_active(obj, true);
 	if (ret)
-		return ret;
+		return ERR_PTR(ret);
 
 	pvec = NULL;
 	pinned = 0;
@@ -651,7 +640,7 @@ i915_gem_userptr_get_pages(struct drm_i9
 				      GFP_TEMPORARY);
 		if (pvec == NULL) {
 			__i915_gem_userptr_set_active(obj, false);
-			return -ENOMEM;
+			return ERR_PTR(-ENOMEM);
 		}
 
 		pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages,
@@ -660,21 +649,22 @@ i915_gem_userptr_get_pages(struct drm_i9
 
 	active = false;
 	if (pinned < 0)
-		ret = pinned, pinned = 0;
+		pages = ERR_PTR(pinned), pinned = 0;
 	else if (pinned < num_pages)
-		ret = __i915_gem_userptr_get_pages_schedule(obj, &active);
+		pages = __i915_gem_userptr_get_pages_schedule(obj, &active);
 	else
-		ret = __i915_gem_userptr_set_pages(obj, pvec, num_pages);
-	if (ret) {
+		pages = __i915_gem_userptr_set_pages(obj, pvec, num_pages);
+	if (IS_ERR(pages)) {
 		__i915_gem_userptr_set_active(obj, active);
 		release_pages(pvec, pinned, 0);
 	}
 	drm_free_large(pvec);
-	return ret;
+	return pages;
 }
 
 static void
-i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj)
+i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
+			   struct sg_table *pages)
 {
 	struct sgt_iter sgt_iter;
 	struct page *page;
@@ -682,22 +672,22 @@ i915_gem_userptr_put_pages(struct drm_i9
 	BUG_ON(obj->userptr.work != NULL);
 	__i915_gem_userptr_set_active(obj, false);
 
-	if (obj->madv != I915_MADV_WILLNEED)
-		obj->dirty = 0;
+	if (obj->mm.madv != I915_MADV_WILLNEED)
+		obj->mm.dirty = false;
 
-	i915_gem_gtt_finish_object(obj);
+	i915_gem_gtt_finish_pages(obj, pages);
 
-	for_each_sgt_page(page, sgt_iter, obj->pages) {
-		if (obj->dirty)
+	for_each_sgt_page(page, sgt_iter, pages) {
+		if (obj->mm.dirty)
 			set_page_dirty(page);
 
 		mark_page_accessed(page);
 		put_page(page);
 	}
-	obj->dirty = 0;
+	obj->mm.dirty = false;
 
-	sg_free_table(obj->pages);
-	kfree(obj->pages);
+	sg_free_table(pages);
+	kfree(pages);
 }
 
 static void
@@ -717,7 +707,8 @@ i915_gem_userptr_dmabuf_export(struct dr
 }
 
 static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
-	.flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE,
+	.flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE |
+		 I915_GEM_OBJECT_IS_SHRINKABLE,
 	.get_pages = i915_gem_userptr_get_pages,
 	.put_pages = i915_gem_userptr_put_pages,
 	.dmabuf_export = i915_gem_userptr_dmabuf_export,
@@ -762,12 +753,13 @@ static const struct drm_i915_gem_object_
 int
 i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_userptr *args = data;
 	struct drm_i915_gem_object *obj;
 	int ret;
 	u32 handle;
 
-	if (!HAS_LLC(dev) && !HAS_SNOOP(dev)) {
+	if (!HAS_LLC(dev_priv) && !HAS_SNOOP(dev_priv)) {
 		/* We cannot support coherent userptr objects on hw without
 		 * LLC and broken snooping.
 		 */
@@ -816,7 +808,7 @@ i915_gem_userptr_ioctl(struct drm_device
 		ret = drm_gem_handle_create(file, &obj->base, &handle);
 
 	/* drop reference from allocate - handle holds it now */
-	i915_gem_object_put_unlocked(obj);
+	i915_gem_object_put(obj);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gpu_error.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gpu_error.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_gpu_error.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_gpu_error.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,8 @@
  */
 
 #include <generated/utsrelease.h>
+#include <linux/stop_machine.h>
+#include <linux/zlib.h>
 #include "i915_drv.h"
 
 static const char *engine_str(int engine)
@@ -172,6 +174,110 @@ static void i915_error_puts(struct drm_i
 #define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
 #define err_puts(e, s) i915_error_puts(e, s)
 
+#ifdef CONFIG_DRM_I915_COMPRESS_ERROR
+
+static bool compress_init(struct z_stream_s *zstream)
+{
+	memset(zstream, 0, sizeof(*zstream));
+
+	zstream->workspace =
+		kmalloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
+			GFP_ATOMIC | __GFP_NOWARN);
+	if (!zstream->workspace)
+		return false;
+
+	if (zlib_deflateInit(zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
+		kfree(zstream->workspace);
+		return false;
+	}
+
+	return true;
+}
+
+static int compress_page(struct z_stream_s *zstream,
+			 void *src,
+			 struct drm_i915_error_object *dst)
+{
+	zstream->next_in = src;
+	zstream->avail_in = PAGE_SIZE;
+
+	do {
+		if (zstream->avail_out == 0) {
+			unsigned long page;
+
+			page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN);
+			if (!page)
+				return -ENOMEM;
+
+			dst->pages[dst->page_count++] = (void *)page;
+
+			zstream->next_out = (void *)page;
+			zstream->avail_out = PAGE_SIZE;
+		}
+
+		if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK)
+			return -EIO;
+	} while (zstream->avail_in);
+
+	/* Fallback to uncompressed if we increase size? */
+	if (0 && zstream->total_out > zstream->total_in)
+		return -E2BIG;
+
+	return 0;
+}
+
+static void compress_fini(struct z_stream_s *zstream,
+			  struct drm_i915_error_object *dst)
+{
+	if (dst) {
+		zlib_deflate(zstream, Z_FINISH);
+		dst->unused = zstream->avail_out;
+	}
+
+	zlib_deflateEnd(zstream);
+	kfree(zstream->workspace);
+}
+
+static void err_compression_marker(struct drm_i915_error_state_buf *m)
+{
+	err_puts(m, ":");
+}
+
+#else
+
+static bool compress_init(struct z_stream_s *zstream)
+{
+	return true;
+}
+
+static int compress_page(struct z_stream_s *zstream,
+			 void *src,
+			 struct drm_i915_error_object *dst)
+{
+	unsigned long page;
+
+	page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN);
+	if (!page)
+		return -ENOMEM;
+
+	dst->pages[dst->page_count++] =
+		memcpy((void *)page, src, PAGE_SIZE);
+
+	return 0;
+}
+
+static void compress_fini(struct z_stream_s *zstream,
+			  struct drm_i915_error_object *dst)
+{
+}
+
+static void err_compression_marker(struct drm_i915_error_state_buf *m)
+{
+	err_puts(m, "~");
+}
+
+#endif
+
 static void print_error_buffers(struct drm_i915_error_state_buf *m,
 				const char *name,
 				struct drm_i915_error_buffer *err,
@@ -228,13 +334,57 @@ static const char *hangcheck_action_to_s
 	return "unknown";
 }
 
+static void error_print_instdone(struct drm_i915_error_state_buf *m,
+				 struct drm_i915_error_engine *ee)
+{
+	int slice;
+	int subslice;
+
+	err_printf(m, "  INSTDONE: 0x%08x\n",
+		   ee->instdone.instdone);
+
+	if (ee->engine_id != RCS || INTEL_GEN(m->i915) <= 3)
+		return;
+
+	err_printf(m, "  SC_INSTDONE: 0x%08x\n",
+		   ee->instdone.slice_common);
+
+	if (INTEL_GEN(m->i915) <= 6)
+		return;
+
+	for_each_instdone_slice_subslice(m->i915, slice, subslice)
+		err_printf(m, "  SAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
+			   slice, subslice,
+			   ee->instdone.sampler[slice][subslice]);
+
+	for_each_instdone_slice_subslice(m->i915, slice, subslice)
+		err_printf(m, "  ROW_INSTDONE[%d][%d]: 0x%08x\n",
+			   slice, subslice,
+			   ee->instdone.row[slice][subslice]);
+}
+
+static void error_print_request(struct drm_i915_error_state_buf *m,
+				const char *prefix,
+				struct drm_i915_error_request *erq)
+{
+	if (!erq->seqno)
+		return;
+
+	err_printf(m, "%s pid %d, seqno %8x:%08x, emitted %dms ago, head %08x, tail %08x\n",
+		   prefix, erq->pid,
+		   erq->context, erq->seqno,
+		   jiffies_to_msecs(jiffies - erq->jiffies),
+		   erq->head, erq->tail);
+}
+
 static void error_print_engine(struct drm_i915_error_state_buf *m,
 			       struct drm_i915_error_engine *ee)
 {
 	err_printf(m, "%s command stream:\n", engine_str(ee->engine_id));
 	err_printf(m, "  START: 0x%08x\n", ee->start);
-	err_printf(m, "  HEAD:  0x%08x\n", ee->head);
-	err_printf(m, "  TAIL:  0x%08x\n", ee->tail);
+	err_printf(m, "  HEAD:  0x%08x [0x%08x]\n", ee->head, ee->rq_head);
+	err_printf(m, "  TAIL:  0x%08x [0x%08x, 0x%08x]\n",
+		   ee->tail, ee->rq_post, ee->rq_tail);
 	err_printf(m, "  CTL:   0x%08x\n", ee->ctl);
 	err_printf(m, "  MODE:  0x%08x\n", ee->mode);
 	err_printf(m, "  HWS:   0x%08x\n", ee->hws);
@@ -242,7 +392,9 @@ static void error_print_engine(struct dr
 		   (u32)(ee->acthd>>32), (u32)ee->acthd);
 	err_printf(m, "  IPEIR: 0x%08x\n", ee->ipeir);
 	err_printf(m, "  IPEHR: 0x%08x\n", ee->ipehr);
-	err_printf(m, "  INSTDONE: 0x%08x\n", ee->instdone);
+
+	error_print_instdone(m, ee);
+
 	if (ee->batchbuffer) {
 		u64 start = ee->batchbuffer->gtt_offset;
 		u64 end = start + ee->batchbuffer->gtt_size;
@@ -263,17 +415,13 @@ static void error_print_engine(struct dr
 	if (INTEL_GEN(m->i915) >= 6) {
 		err_printf(m, "  RC PSMI: 0x%08x\n", ee->rc_psmi);
 		err_printf(m, "  FAULT_REG: 0x%08x\n", ee->fault_reg);
-		err_printf(m, "  SYNC_0: 0x%08x [last synced 0x%08x]\n",
-			   ee->semaphore_mboxes[0],
-			   ee->semaphore_seqno[0]);
-		err_printf(m, "  SYNC_1: 0x%08x [last synced 0x%08x]\n",
-			   ee->semaphore_mboxes[1],
-			   ee->semaphore_seqno[1]);
-		if (HAS_VEBOX(m->i915)) {
-			err_printf(m, "  SYNC_2: 0x%08x [last synced 0x%08x]\n",
-				   ee->semaphore_mboxes[2],
-				   ee->semaphore_seqno[2]);
-		}
+		err_printf(m, "  SYNC_0: 0x%08x\n",
+			   ee->semaphore_mboxes[0]);
+		err_printf(m, "  SYNC_1: 0x%08x\n",
+			   ee->semaphore_mboxes[1]);
+		if (HAS_VEBOX(m->i915))
+			err_printf(m, "  SYNC_2: 0x%08x\n",
+				   ee->semaphore_mboxes[2]);
 	}
 	if (USES_PPGTT(m->i915)) {
 		err_printf(m, "  GFX_MODE: 0x%08x\n", ee->vm_info.gfx_mode);
@@ -296,6 +444,8 @@ static void error_print_engine(struct dr
 	err_printf(m, "  hangcheck: %s [%d]\n",
 		   hangcheck_action_to_str(ee->hangcheck_action),
 		   ee->hangcheck_score);
+	error_print_request(m, "  ELSP[0]: ", &ee->execlist[0]);
+	error_print_request(m, "  ELSP[1]: ", &ee->execlist[1]);
 }
 
 void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
@@ -307,40 +457,83 @@ void i915_error_printf(struct drm_i915_e
 	va_end(args);
 }
 
+static int
+ascii85_encode_len(int len)
+{
+	return DIV_ROUND_UP(len, 4);
+}
+
+static bool
+ascii85_encode(u32 in, char *out)
+{
+	int i;
+
+	if (in == 0)
+		return false;
+
+	out[5] = '\0';
+	for (i = 5; i--; ) {
+		out[i] = '!' + in % 85;
+		in /= 85;
+	}
+
+	return true;
+}
+
 static void print_error_obj(struct drm_i915_error_state_buf *m,
+			    struct intel_engine_cs *engine,
+			    const char *name,
 			    struct drm_i915_error_object *obj)
 {
-	int page, offset, elt;
+	char out[6];
+	int page;
 
-	for (page = offset = 0; page < obj->page_count; page++) {
-		for (elt = 0; elt < PAGE_SIZE/4; elt++) {
-			err_printf(m, "%08x :  %08x\n", offset,
-				   obj->pages[page][elt]);
-			offset += 4;
+	if (!obj)
+		return;
+
+	if (name) {
+		err_printf(m, "%s --- %s = 0x%08x %08x\n",
+			   engine ? engine->name : "global", name,
+			   upper_32_bits(obj->gtt_offset),
+			   lower_32_bits(obj->gtt_offset));
+	}
+
+	err_compression_marker(m);
+	for (page = 0; page < obj->page_count; page++) {
+		int i, len;
+
+		len = PAGE_SIZE;
+		if (page == obj->page_count - 1)
+			len -= obj->unused;
+		len = ascii85_encode_len(len);
+
+		for (i = 0; i < len; i++) {
+			if (ascii85_encode(obj->pages[page][i], out))
+				err_puts(m, out);
+			else
+				err_puts(m, "z");
 		}
 	}
+	err_puts(m, "\n");
 }
 
 static void err_print_capabilities(struct drm_i915_error_state_buf *m,
 				   const struct intel_device_info *info)
 {
 #define PRINT_FLAG(x)  err_printf(m, #x ": %s\n", yesno(info->x))
-#define SEP_SEMICOLON ;
-	DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
+	DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
 #undef PRINT_FLAG
-#undef SEP_SEMICOLON
 }
 
 int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
 			    const struct i915_error_state_file_priv *error_priv)
 {
-	struct drm_device *dev = error_priv->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(error_priv->dev);
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	struct drm_i915_error_state *error = error_priv->error;
 	struct drm_i915_error_object *obj;
-	int i, j, offset, elt;
 	int max_hangcheck_score;
+	int i, j;
 
 	if (!error) {
 		err_printf(m, "no error state collected\n");
@@ -348,9 +541,13 @@ int i915_error_state_to_str(struct drm_i
 	}
 
 	err_printf(m, "%s\n", error->error_msg);
-	err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
-		   error->time.tv_usec);
 	err_printf(m, "Kernel: " UTS_RELEASE "\n");
+	err_printf(m, "Time: %ld s %ld us\n",
+		   error->time.tv_sec, error->time.tv_usec);
+	err_printf(m, "Boottime: %ld s %ld us\n",
+		   error->boottime.tv_sec, error->boottime.tv_usec);
+	err_printf(m, "Uptime: %ld s %ld us\n",
+		   error->uptime.tv_sec, error->uptime.tv_usec);
 	err_print_capabilities(m, &error->device_info);
 	max_hangcheck_score = 0;
 	for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
@@ -375,7 +572,7 @@ int i915_error_state_to_str(struct drm_i
 		   pdev->subsystem_device);
 	err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
 
-	if (HAS_CSR(dev)) {
+	if (HAS_CSR(dev_priv)) {
 		struct intel_csr *csr = &dev_priv->csr;
 
 		err_printf(m, "DMC loaded: %s\n",
@@ -387,11 +584,11 @@ int i915_error_state_to_str(struct drm_i
 
 	err_printf(m, "EIR: 0x%08x\n", error->eir);
 	err_printf(m, "IER: 0x%08x\n", error->ier);
-	if (INTEL_INFO(dev)->gen >= 8) {
+	if (INTEL_GEN(dev_priv) >= 8) {
 		for (i = 0; i < 4; i++)
 			err_printf(m, "GTIER gt %d: 0x%08x\n", i,
 				   error->gtier[i]);
-	} else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev))
+	} else if (HAS_PCH_SPLIT(dev_priv) || IS_VALLEYVIEW(dev_priv))
 		err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]);
 	err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
 	err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
@@ -402,21 +599,17 @@ int i915_error_state_to_str(struct drm_i
 	for (i = 0; i < dev_priv->num_fence_regs; i++)
 		err_printf(m, "  fence[%d] = %08llx\n", i, error->fence[i]);
 
-	for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++)
-		err_printf(m, "  INSTDONE_%d: 0x%08x\n", i,
-			   error->extra_instdone[i]);
-
-	if (INTEL_INFO(dev)->gen >= 6) {
+	if (INTEL_GEN(dev_priv) >= 6) {
 		err_printf(m, "ERROR: 0x%08x\n", error->error);
 
-		if (INTEL_INFO(dev)->gen >= 8)
+		if (INTEL_GEN(dev_priv) >= 8)
 			err_printf(m, "FAULT_TLB_DATA: 0x%08x 0x%08x\n",
 				   error->fault_data1, error->fault_data0);
 
 		err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
 	}
 
-	if (IS_GEN7(dev))
+	if (IS_GEN7(dev_priv))
 		err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
 
 	for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
@@ -438,7 +631,7 @@ int i915_error_state_to_str(struct drm_i
 
 			len += scnprintf(buf + len, sizeof(buf), "%s%s",
 					 first ? "" : ", ",
-					 dev_priv->engine[j].name);
+					 dev_priv->engine[j]->name);
 			first = 0;
 		}
 		scnprintf(buf + len, sizeof(buf), ")");
@@ -456,7 +649,7 @@ int i915_error_state_to_str(struct drm_i
 
 		obj = ee->batchbuffer;
 		if (obj) {
-			err_puts(m, dev_priv->engine[i].name);
+			err_puts(m, dev_priv->engine[i]->name);
 			if (ee->pid != -1)
 				err_printf(m, " (submitted by %s [%d])",
 					   ee->comm,
@@ -464,37 +657,23 @@ int i915_error_state_to_str(struct drm_i
 			err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
 				   upper_32_bits(obj->gtt_offset),
 				   lower_32_bits(obj->gtt_offset));
-			print_error_obj(m, obj);
-		}
-
-		obj = ee->wa_batchbuffer;
-		if (obj) {
-			err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
-				   dev_priv->engine[i].name,
-				   lower_32_bits(obj->gtt_offset));
-			print_error_obj(m, obj);
+			print_error_obj(m, dev_priv->engine[i], NULL, obj);
 		}
 
 		if (ee->num_requests) {
 			err_printf(m, "%s --- %d requests\n",
-				   dev_priv->engine[i].name,
+				   dev_priv->engine[i]->name,
 				   ee->num_requests);
-			for (j = 0; j < ee->num_requests; j++) {
-				err_printf(m, "  pid %d, seqno 0x%08x, emitted %ld, head 0x%08x, tail 0x%08x\n",
-					   ee->requests[j].pid,
-					   ee->requests[j].seqno,
-					   ee->requests[j].jiffies,
-					   ee->requests[j].head,
-					   ee->requests[j].tail);
-			}
+			for (j = 0; j < ee->num_requests; j++)
+				error_print_request(m, " ", &ee->requests[j]);
 		}
 
 		if (IS_ERR(ee->waiters)) {
 			err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n",
-				   dev_priv->engine[i].name);
+				   dev_priv->engine[i]->name);
 		} else if (ee->num_waiters) {
 			err_printf(m, "%s --- %d waiters\n",
-				   dev_priv->engine[i].name,
+				   dev_priv->engine[i]->name,
 				   ee->num_waiters);
 			for (j = 0; j < ee->num_waiters; j++) {
 				err_printf(m, " seqno 0x%08x for %s [%d]\n",
@@ -504,83 +683,31 @@ int i915_error_state_to_str(struct drm_i
 			}
 		}
 
-		if ((obj = ee->ringbuffer)) {
-			err_printf(m, "%s --- ringbuffer = 0x%08x\n",
-				   dev_priv->engine[i].name,
-				   lower_32_bits(obj->gtt_offset));
-			print_error_obj(m, obj);
-		}
-
-		if ((obj = ee->hws_page)) {
-			u64 hws_offset = obj->gtt_offset;
-			u32 *hws_page = &obj->pages[0][0];
+		print_error_obj(m, dev_priv->engine[i],
+				"ringbuffer", ee->ringbuffer);
 
-			if (i915.enable_execlists) {
-				hws_offset += LRC_PPHWSP_PN * PAGE_SIZE;
-				hws_page = &obj->pages[LRC_PPHWSP_PN][0];
-			}
-			err_printf(m, "%s --- HW Status = 0x%08llx\n",
-				   dev_priv->engine[i].name, hws_offset);
-			offset = 0;
-			for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
-				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
-					   offset,
-					   hws_page[elt],
-					   hws_page[elt+1],
-					   hws_page[elt+2],
-					   hws_page[elt+3]);
-				offset += 16;
-			}
-		}
+		print_error_obj(m, dev_priv->engine[i],
+				"HW Status", ee->hws_page);
 
-		obj = ee->wa_ctx;
-		if (obj) {
-			u64 wa_ctx_offset = obj->gtt_offset;
-			u32 *wa_ctx_page = &obj->pages[0][0];
-			struct intel_engine_cs *engine = &dev_priv->engine[RCS];
-			u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size +
-					   engine->wa_ctx.per_ctx.size);
+		print_error_obj(m, dev_priv->engine[i],
+				"HW context", ee->ctx);
 
-			err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n",
-				   dev_priv->engine[i].name, wa_ctx_offset);
-			offset = 0;
-			for (elt = 0; elt < wa_ctx_size; elt += 4) {
-				err_printf(m, "[%04x] %08x %08x %08x %08x\n",
-					   offset,
-					   wa_ctx_page[elt + 0],
-					   wa_ctx_page[elt + 1],
-					   wa_ctx_page[elt + 2],
-					   wa_ctx_page[elt + 3]);
-				offset += 16;
-			}
-		}
+		print_error_obj(m, dev_priv->engine[i],
+				"WA context", ee->wa_ctx);
 
-		if ((obj = ee->ctx)) {
-			err_printf(m, "%s --- HW Context = 0x%08x\n",
-				   dev_priv->engine[i].name,
-				   lower_32_bits(obj->gtt_offset));
-			print_error_obj(m, obj);
-		}
+		print_error_obj(m, dev_priv->engine[i],
+				"WA batchbuffer", ee->wa_batchbuffer);
 	}
 
-	if ((obj = error->semaphore)) {
-		err_printf(m, "Semaphore page = 0x%08x\n",
-			   lower_32_bits(obj->gtt_offset));
-		for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
-			err_printf(m, "[%04x] %08x %08x %08x %08x\n",
-				   elt * 4,
-				   obj->pages[0][elt],
-				   obj->pages[0][elt+1],
-				   obj->pages[0][elt+2],
-				   obj->pages[0][elt+3]);
-		}
-	}
+	print_error_obj(m, NULL, "Semaphores", error->semaphore);
+
+	print_error_obj(m, NULL, "GuC log buffer", error->guc_log);
 
 	if (error->overlay)
 		intel_overlay_print_error_state(m, error->overlay);
 
 	if (error->display)
-		intel_display_print_error_state(m, dev, error->display);
+		intel_display_print_error_state(m, dev_priv, error->display);
 
 out:
 	if (m->bytes == 0 && m->err)
@@ -629,7 +756,7 @@ static void i915_error_object_free(struc
 		return;
 
 	for (page = 0; page < obj->page_count; page++)
-		kfree(obj->pages[page]);
+		free_page((unsigned long)obj->pages[page]);
 
 	kfree(obj);
 }
@@ -656,6 +783,7 @@ static void i915_error_state_free(struct
 	}
 
 	i915_error_object_free(error->semaphore);
+	i915_error_object_free(error->guc_log);
 
 	for (i = 0; i < ARRAY_SIZE(error->active_bo); i++)
 		kfree(error->active_bo[i]);
@@ -667,104 +795,63 @@ static void i915_error_state_free(struct
 }
 
 static struct drm_i915_error_object *
-i915_error_object_create(struct drm_i915_private *dev_priv,
+i915_error_object_create(struct drm_i915_private *i915,
 			 struct i915_vma *vma)
 {
-	struct i915_ggtt *ggtt = &dev_priv->ggtt;
-	struct drm_i915_gem_object *src;
+	struct i915_ggtt *ggtt = &i915->ggtt;
+	const u64 slot = ggtt->error_capture.start;
 	struct drm_i915_error_object *dst;
-	int num_pages;
-	bool use_ggtt;
-	int i = 0;
-	u64 reloc_offset;
+	struct z_stream_s zstream;
+	unsigned long num_pages;
+	struct sgt_iter iter;
+	dma_addr_t dma;
 
 	if (!vma)
 		return NULL;
 
-	src = vma->obj;
-	if (!src->pages)
-		return NULL;
-
-	num_pages = src->base.size >> PAGE_SHIFT;
-
-	dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC);
+	num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT;
+	num_pages = DIV_ROUND_UP(10 * num_pages, 8); /* worstcase zlib growth */
+	dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *),
+		      GFP_ATOMIC | __GFP_NOWARN);
 	if (!dst)
 		return NULL;
 
 	dst->gtt_offset = vma->node.start;
 	dst->gtt_size = vma->node.size;
+	dst->page_count = 0;
+	dst->unused = 0;
 
-	reloc_offset = dst->gtt_offset;
-	use_ggtt = (src->cache_level == I915_CACHE_NONE &&
-		   (vma->flags & I915_VMA_GLOBAL_BIND) &&
-		   reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
-
-	/* Cannot access stolen address directly, try to use the aperture */
-	if (src->stolen) {
-		use_ggtt = true;
-
-		if (!(vma->flags & I915_VMA_GLOBAL_BIND))
-			goto unwind;
-
-		reloc_offset = vma->node.start;
-		if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
-			goto unwind;
+	if (!compress_init(&zstream)) {
+		kfree(dst);
+		return NULL;
 	}
 
-	/* Cannot access snooped pages through the aperture */
-	if (use_ggtt && src->cache_level != I915_CACHE_NONE &&
-	    !HAS_LLC(dev_priv))
-		goto unwind;
-
-	dst->page_count = num_pages;
-	while (num_pages--) {
-		unsigned long flags;
-		void *d;
-
-		d = kmalloc(PAGE_SIZE, GFP_ATOMIC);
-		if (d == NULL)
-			goto unwind;
-
-		local_irq_save(flags);
-		if (use_ggtt) {
-			void __iomem *s;
-
-			/* Simply ignore tiling or any overlapping fence.
-			 * It's part of the error state, and this hopefully
-			 * captures what the GPU read.
-			 */
-
-			s = io_mapping_map_atomic_wc(&ggtt->mappable,
-						     reloc_offset);
-			memcpy_fromio(d, s, PAGE_SIZE);
-			io_mapping_unmap_atomic(s);
-		} else {
-			struct page *page;
-			void *s;
-
-			page = i915_gem_object_get_page(src, i);
-
-			drm_clflush_pages(&page, 1);
+	for_each_sgt_dma(dma, iter, vma->pages) {
+		void __iomem *s;
+		int ret;
 
-			s = kmap_atomic(page);
-			memcpy(d, s, PAGE_SIZE);
-			kunmap_atomic(s);
+		ggtt->base.insert_page(&ggtt->base, dma, slot,
+				       I915_CACHE_NONE, 0);
 
-			drm_clflush_pages(&page, 1);
-		}
-		local_irq_restore(flags);
+		s = io_mapping_map_atomic_wc(&ggtt->mappable, slot);
+		ret = compress_page(&zstream, (void  __force *)s, dst);
+		io_mapping_unmap_atomic(s);
 
-		dst->pages[i++] = d;
-		reloc_offset += PAGE_SIZE;
+		if (ret)
+			goto unwind;
 	}
-
-	return dst;
+	goto out;
 
 unwind:
-	while (i--)
-		kfree(dst->pages[i]);
+	while (dst->page_count--)
+		free_page((unsigned long)dst->pages[dst->page_count]);
 	kfree(dst);
-	return NULL;
+	dst = NULL;
+
+out:
+	compress_fini(&zstream, dst);
+	ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE);
+	return dst;
 }
 
 /* The error capture is special as tries to run underneath the normal
@@ -773,16 +860,19 @@ unwind:
 static inline uint32_t
 __active_get_seqno(struct i915_gem_active *active)
 {
-	return i915_gem_request_get_seqno(__i915_gem_active_peek(active));
+	struct drm_i915_gem_request *request;
+
+	request = __i915_gem_active_peek(active);
+	return request ? request->global_seqno : 0;
 }
 
 static inline int
 __active_get_engine_id(struct i915_gem_active *active)
 {
-	struct intel_engine_cs *engine;
+	struct drm_i915_gem_request *request;
 
-	engine = i915_gem_request_get_engine(__i915_gem_active_peek(active));
-	return engine ? engine->id : -1;
+	request = __i915_gem_active_peek(active);
+	return request ? request->engine->id : -1;
 }
 
 static void capture_bo(struct drm_i915_error_buffer *err,
@@ -795,17 +885,17 @@ static void capture_bo(struct drm_i915_e
 	err->name = obj->base.name;
 
 	for (i = 0; i < I915_NUM_ENGINES; i++)
-		err->rseqno[i] = __active_get_seqno(&obj->last_read[i]);
-	err->wseqno = __active_get_seqno(&obj->last_write);
-	err->engine = __active_get_engine_id(&obj->last_write);
+		err->rseqno[i] = __active_get_seqno(&vma->last_read[i]);
+	err->wseqno = __active_get_seqno(&obj->frontbuffer_write);
+	err->engine = __active_get_engine_id(&obj->frontbuffer_write);
 
 	err->gtt_offset = vma->node.start;
 	err->read_domains = obj->base.read_domains;
 	err->write_domain = obj->base.write_domain;
 	err->fence_reg = vma->fence ? vma->fence->id : -1;
 	err->tiling = i915_gem_object_get_tiling(obj);
-	err->dirty = obj->dirty;
-	err->purgeable = obj->madv != I915_MADV_WILLNEED;
+	err->dirty = obj->mm.dirty;
+	err->purgeable = obj->mm.madv != I915_MADV_WILLNEED;
 	err->userptr = obj->userptr.mm != NULL;
 	err->cache_level = obj->cache_level;
 }
@@ -855,7 +945,8 @@ static uint32_t i915_error_generate_code
 			if (engine_id)
 				*engine_id = i;
 
-			return error->engine[i].ipehr ^ error->engine[i].instdone;
+			return error->engine[i].ipehr ^
+			       error->engine[i].instdone.instdone;
 		}
 	}
 
@@ -879,6 +970,26 @@ static void i915_gem_record_fences(struc
 	}
 }
 
+static inline u32
+gen8_engine_sync_index(struct intel_engine_cs *engine,
+		       struct intel_engine_cs *other)
+{
+	int idx;
+
+	/*
+	 * rcs -> 0 = vcs, 1 = bcs, 2 = vecs, 3 = vcs2;
+	 * vcs -> 0 = bcs, 1 = vecs, 2 = vcs2, 3 = rcs;
+	 * bcs -> 0 = vecs, 1 = vcs2. 2 = rcs, 3 = vcs;
+	 * vecs -> 0 = vcs2, 1 = rcs, 2 = vcs, 3 = bcs;
+	 * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs;
+	 */
+
+	idx = (other - engine) - 1;
+	if (idx < 0)
+		idx += I915_NUM_ENGINES;
+
+	return idx;
+}
 
 static void gen8_record_semaphore_state(struct drm_i915_error_state *error,
 					struct intel_engine_cs *engine,
@@ -891,7 +1002,7 @@ static void gen8_record_semaphore_state(
 	if (!error->semaphore)
 		return;
 
-	for_each_engine_id(to, dev_priv, id) {
+	for_each_engine(to, dev_priv, id) {
 		int idx;
 		u16 signal_offset;
 		u32 *tmp;
@@ -902,10 +1013,9 @@ static void gen8_record_semaphore_state(
 		signal_offset =
 			(GEN8_SIGNAL_OFFSET(engine, id) & (PAGE_SIZE - 1)) / 4;
 		tmp = error->semaphore->pages[0];
-		idx = intel_engine_sync_index(engine, to);
+		idx = gen8_engine_sync_index(engine, to);
 
 		ee->semaphore_mboxes[idx] = tmp[signal_offset];
-		ee->semaphore_seqno[idx] = engine->semaphore.sync_seqno[idx];
 	}
 }
 
@@ -916,14 +1026,9 @@ static void gen6_record_semaphore_state(
 
 	ee->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(engine->mmio_base));
 	ee->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(engine->mmio_base));
-	ee->semaphore_seqno[0] = engine->semaphore.sync_seqno[0];
-	ee->semaphore_seqno[1] = engine->semaphore.sync_seqno[1];
-
-	if (HAS_VEBOX(dev_priv)) {
+	if (HAS_VEBOX(dev_priv))
 		ee->semaphore_mboxes[2] =
 			I915_READ(RING_SYNC_2(engine->mmio_base));
-		ee->semaphore_seqno[2] = engine->semaphore.sync_seqno[2];
-	}
 }
 
 static void error_record_engine_waiters(struct intel_engine_cs *engine,
@@ -940,7 +1045,7 @@ static void error_record_engine_waiters(
 	if (RB_EMPTY_ROOT(&b->waiters))
 		return;
 
-	if (!spin_trylock(&b->lock)) {
+	if (!spin_trylock_irq(&b->lock)) {
 		ee->waiters = ERR_PTR(-EDEADLK);
 		return;
 	}
@@ -948,7 +1053,7 @@ static void error_record_engine_waiters(
 	count = 0;
 	for (rb = rb_first(&b->waiters); rb != NULL; rb = rb_next(rb))
 		count++;
-	spin_unlock(&b->lock);
+	spin_unlock_irq(&b->lock);
 
 	waiter = NULL;
 	if (count)
@@ -958,7 +1063,7 @@ static void error_record_engine_waiters(
 	if (!waiter)
 		return;
 
-	if (!spin_trylock(&b->lock)) {
+	if (!spin_trylock_irq(&b->lock)) {
 		kfree(waiter);
 		ee->waiters = ERR_PTR(-EDEADLK);
 		return;
@@ -976,7 +1081,7 @@ static void error_record_engine_waiters(
 		if (++ee->num_waiters == count)
 			break;
 	}
-	spin_unlock(&b->lock);
+	spin_unlock_irq(&b->lock);
 }
 
 static void error_record_engine_registers(struct drm_i915_error_state *error,
@@ -998,7 +1103,6 @@ static void error_record_engine_register
 		ee->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base));
 		ee->ipeir = I915_READ(RING_IPEIR(engine->mmio_base));
 		ee->ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
-		ee->instdone = I915_READ(RING_INSTDONE(engine->mmio_base));
 		ee->instps = I915_READ(RING_INSTPS(engine->mmio_base));
 		ee->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
 		if (INTEL_GEN(dev_priv) >= 8) {
@@ -1010,14 +1114,15 @@ static void error_record_engine_register
 		ee->faddr = I915_READ(DMA_FADD_I8XX);
 		ee->ipeir = I915_READ(IPEIR);
 		ee->ipehr = I915_READ(IPEHR);
-		ee->instdone = I915_READ(GEN2_INSTDONE);
 	}
 
+	intel_engine_get_instdone(engine, &ee->instdone);
+
 	ee->waiting = intel_engine_has_waiter(engine);
 	ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base));
 	ee->acthd = intel_engine_get_active_head(engine);
 	ee->seqno = intel_engine_get_seqno(engine);
-	ee->last_seqno = engine->last_submitted_seqno;
+	ee->last_seqno = intel_engine_last_submit(engine);
 	ee->start = I915_READ_START(engine);
 	ee->head = I915_READ_HEAD(engine);
 	ee->tail = I915_READ_TAIL(engine);
@@ -1079,6 +1184,20 @@ static void error_record_engine_register
 	}
 }
 
+static void record_request(struct drm_i915_gem_request *request,
+			   struct drm_i915_error_request *erq)
+{
+	erq->context = request->ctx->hw_id;
+	erq->seqno = request->global_seqno;
+	erq->jiffies = request->emitted_jiffies;
+	erq->head = request->head;
+	erq->tail = request->tail;
+
+	rcu_read_lock();
+	erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0;
+	rcu_read_unlock();
+}
+
 static void engine_record_requests(struct intel_engine_cs *engine,
 				   struct drm_i915_gem_request *first,
 				   struct drm_i915_error_engine *ee)
@@ -1088,7 +1207,7 @@ static void engine_record_requests(struc
 
 	count = 0;
 	request = first;
-	list_for_each_entry_from(request, &engine->request_list, link)
+	list_for_each_entry_from(request, &engine->timeline->requests, link)
 		count++;
 	if (!count)
 		return;
@@ -1101,9 +1220,7 @@ static void engine_record_requests(struc
 
 	count = 0;
 	request = first;
-	list_for_each_entry_from(request, &engine->request_list, link) {
-		struct drm_i915_error_request *erq;
-
+	list_for_each_entry_from(request, &engine->timeline->requests, link) {
 		if (count >= ee->num_requests) {
 			/*
 			 * If the ring request list was changed in
@@ -1123,19 +1240,22 @@ static void engine_record_requests(struc
 			break;
 		}
 
-		erq = &ee->requests[count++];
-		erq->seqno = request->fence.seqno;
-		erq->jiffies = request->emitted_jiffies;
-		erq->head = request->head;
-		erq->tail = request->tail;
-
-		rcu_read_lock();
-		erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0;
-		rcu_read_unlock();
+		record_request(request, &ee->requests[count++]);
 	}
 	ee->num_requests = count;
 }
 
+static void error_record_engine_execlists(struct intel_engine_cs *engine,
+					  struct drm_i915_error_engine *ee)
+{
+	unsigned int n;
+
+	for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++)
+		if (engine->execlist_port[n].request)
+			record_request(engine->execlist_port[n].request,
+				       &ee->execlist[n]);
+}
+
 static void i915_gem_record_rings(struct drm_i915_private *dev_priv,
 				  struct drm_i915_error_state *error)
 {
@@ -1146,20 +1266,21 @@ static void i915_gem_record_rings(struct
 		i915_error_object_create(dev_priv, dev_priv->semaphore);
 
 	for (i = 0; i < I915_NUM_ENGINES; i++) {
-		struct intel_engine_cs *engine = &dev_priv->engine[i];
+		struct intel_engine_cs *engine = dev_priv->engine[i];
 		struct drm_i915_error_engine *ee = &error->engine[i];
 		struct drm_i915_gem_request *request;
 
 		ee->pid = -1;
 		ee->engine_id = -1;
 
-		if (!intel_engine_initialized(engine))
+		if (!engine)
 			continue;
 
 		ee->engine_id = i;
 
 		error_record_engine_registers(error, engine, ee);
 		error_record_engine_waiters(engine, ee);
+		error_record_engine_execlists(engine, ee);
 
 		request = i915_gem_find_active_request(engine);
 		if (request) {
@@ -1202,6 +1323,10 @@ static void i915_gem_record_rings(struct
 			error->simulated |=
 				request->ctx->flags & CONTEXT_NO_ERROR_CAPTURE;
 
+			ee->rq_head = request->head;
+			ee->rq_post = request->postfix;
+			ee->rq_tail = request->tail;
+
 			ring = request->ring;
 			ee->cpu_ring_head = ring->head;
 			ee->cpu_ring_tail = ring->tail;
@@ -1302,11 +1427,21 @@ static void i915_capture_pinned_buffers(
 	error->pinned_bo = bo;
 }
 
+static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv,
+					    struct drm_i915_error_state *error)
+{
+	/* Capturing log buf contents won't be useful if logging was disabled */
+	if (!dev_priv->guc.log.vma || (i915.guc_log_level < 0))
+		return;
+
+	error->guc_log = i915_error_object_create(dev_priv,
+						  dev_priv->guc.log.vma);
+}
+
 /* Capture all registers which don't fit into another category. */
 static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
 				   struct drm_i915_error_state *error)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	int i;
 
 	/* General organization
@@ -1318,62 +1453,60 @@ static void i915_capture_reg_state(struc
 	 */
 
 	/* 1: Registers specific to a single generation */
-	if (IS_VALLEYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv)) {
 		error->gtier[0] = I915_READ(GTIER);
 		error->ier = I915_READ(VLV_IER);
 		error->forcewake = I915_READ_FW(FORCEWAKE_VLV);
 	}
 
-	if (IS_GEN7(dev))
+	if (IS_GEN7(dev_priv))
 		error->err_int = I915_READ(GEN7_ERR_INT);
 
-	if (INTEL_INFO(dev)->gen >= 8) {
+	if (INTEL_GEN(dev_priv) >= 8) {
 		error->fault_data0 = I915_READ(GEN8_FAULT_TLB_DATA0);
 		error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1);
 	}
 
-	if (IS_GEN6(dev)) {
+	if (IS_GEN6(dev_priv)) {
 		error->forcewake = I915_READ_FW(FORCEWAKE);
 		error->gab_ctl = I915_READ(GAB_CTL);
 		error->gfx_mode = I915_READ(GFX_MODE);
 	}
 
 	/* 2: Registers which belong to multiple generations */
-	if (INTEL_INFO(dev)->gen >= 7)
+	if (INTEL_GEN(dev_priv) >= 7)
 		error->forcewake = I915_READ_FW(FORCEWAKE_MT);
 
-	if (INTEL_INFO(dev)->gen >= 6) {
+	if (INTEL_GEN(dev_priv) >= 6) {
 		error->derrmr = I915_READ(DERRMR);
 		error->error = I915_READ(ERROR_GEN6);
 		error->done_reg = I915_READ(DONE_REG);
 	}
 
 	/* 3: Feature specific registers */
-	if (IS_GEN6(dev) || IS_GEN7(dev)) {
+	if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
 		error->gam_ecochk = I915_READ(GAM_ECOCHK);
 		error->gac_eco = I915_READ(GAC_ECO_BITS);
 	}
 
 	/* 4: Everything else */
-	if (HAS_HW_CONTEXTS(dev))
+	if (HAS_HW_CONTEXTS(dev_priv))
 		error->ccid = I915_READ(CCID);
 
-	if (INTEL_INFO(dev)->gen >= 8) {
+	if (INTEL_GEN(dev_priv) >= 8) {
 		error->ier = I915_READ(GEN8_DE_MISC_IER);
 		for (i = 0; i < 4; i++)
 			error->gtier[i] = I915_READ(GEN8_GT_IER(i));
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		error->ier = I915_READ(DEIER);
 		error->gtier[0] = I915_READ(GTIER);
-	} else if (IS_GEN2(dev)) {
+	} else if (IS_GEN2(dev_priv)) {
 		error->ier = I915_READ16(IER);
-	} else if (!IS_VALLEYVIEW(dev)) {
+	} else if (!IS_VALLEYVIEW(dev_priv)) {
 		error->ier = I915_READ(IER);
 	}
 	error->eir = I915_READ(EIR);
 	error->pgtbl_er = I915_READ(PGTBL_ER);
-
-	i915_get_extra_instdone(dev_priv, error->extra_instdone);
 }
 
 static void i915_error_capture_msg(struct drm_i915_private *dev_priv,
@@ -1418,6 +1551,32 @@ static void i915_capture_gen_state(struc
 	       sizeof(error->device_info));
 }
 
+static int capture(void *data)
+{
+	struct drm_i915_error_state *error = data;
+
+	i915_capture_gen_state(error->i915, error);
+	i915_capture_reg_state(error->i915, error);
+	i915_gem_record_fences(error->i915, error);
+	i915_gem_record_rings(error->i915, error);
+	i915_capture_active_buffers(error->i915, error);
+	i915_capture_pinned_buffers(error->i915, error);
+	i915_gem_capture_guc_log_buffer(error->i915, error);
+
+	do_gettimeofday(&error->time);
+	error->boottime = ktime_to_timeval(ktime_get_boottime());
+	error->uptime =
+		ktime_to_timeval(ktime_sub(ktime_get(),
+					   error->i915->gt.last_init_time));
+
+	error->overlay = intel_overlay_capture_error_state(error->i915);
+	error->display = intel_display_capture_error_state(error->i915);
+
+	return 0;
+}
+
+#define DAY_AS_SECONDS(x) (24 * 60 * 60 * (x))
+
 /**
  * i915_capture_error_state - capture an error record for later analysis
  * @dev: drm device
@@ -1435,6 +1594,9 @@ void i915_capture_error_state(struct drm
 	struct drm_i915_error_state *error;
 	unsigned long flags;
 
+	if (!i915.error_capture)
+		return;
+
 	if (READ_ONCE(dev_priv->gpu_error.first_error))
 		return;
 
@@ -1446,18 +1608,9 @@ void i915_capture_error_state(struct drm
 	}
 
 	kref_init(&error->ref);
+	error->i915 = dev_priv;
 
-	i915_capture_gen_state(dev_priv, error);
-	i915_capture_reg_state(dev_priv, error);
-	i915_gem_record_fences(dev_priv, error);
-	i915_gem_record_rings(dev_priv, error);
-	i915_capture_active_buffers(dev_priv, error);
-	i915_capture_pinned_buffers(dev_priv, error);
-
-	do_gettimeofday(&error->time);
-
-	error->overlay = intel_overlay_capture_error_state(dev_priv);
-	error->display = intel_display_capture_error_state(dev_priv);
+	stop_machine(capture, error, NULL);
 
 	i915_error_capture_msg(dev_priv, error, engine_mask, error_msg);
 	DRM_INFO("%s\n", error->error_msg);
@@ -1476,7 +1629,8 @@ void i915_capture_error_state(struct drm
 		return;
 	}
 
-	if (!warned) {
+	if (!warned &&
+	    ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) {
 		DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
 		DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
 		DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
@@ -1497,7 +1651,6 @@ void i915_error_state_get(struct drm_dev
 	if (error_priv->error)
 		kref_get(&error_priv->error->ref);
 	spin_unlock_irq(&dev_priv->gpu_error.lock);
-
 }
 
 void i915_error_state_put(struct i915_error_state_file_priv *error_priv)
@@ -1519,33 +1672,3 @@ void i915_destroy_error_state(struct drm
 	if (error)
 		kref_put(&error->ref, i915_error_state_free);
 }
-
-const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
-{
-	switch (type) {
-	case I915_CACHE_NONE: return " uncached";
-	case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
-	case I915_CACHE_L3_LLC: return " L3+LLC";
-	case I915_CACHE_WT: return " WT";
-	default: return "";
-	}
-}
-
-/* NB: please notice the memset */
-void i915_get_extra_instdone(struct drm_i915_private *dev_priv,
-			     uint32_t *instdone)
-{
-	memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG);
-
-	if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv))
-		instdone[0] = I915_READ(GEN2_INSTDONE);
-	else if (IS_GEN4(dev_priv) || IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) {
-		instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE));
-		instdone[1] = I915_READ(GEN4_INSTDONE1);
-	} else if (INTEL_GEN(dev_priv) >= 7) {
-		instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE));
-		instdone[1] = I915_READ(GEN7_SC_INSTDONE);
-		instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE);
-		instdone[3] = I915_READ(GEN7_ROW_INSTDONE);
-	}
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_guc_submission.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_guc_submission.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_guc_submission.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_guc_submission.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,8 @@
  */
 #include <linux/firmware.h>
 #include <linux/circ_buf.h>
+#include <linux/debugfs.h>
+#include <linux/relay.h>
 #include "i915_drv.h"
 #include "intel_guc.h"
 
@@ -85,6 +87,7 @@ static int host2guc_action(struct intel_
 	if (WARN_ON(len < 1 || len > 15))
 		return -EINVAL;
 
+	mutex_lock(&guc->action_lock);
 	intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
 
 	dev_priv->guc.action_count += 1;
@@ -123,6 +126,7 @@ static int host2guc_action(struct intel_
 	dev_priv->guc.action_status = status;
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
+	mutex_unlock(&guc->action_lock);
 
 	return ret;
 }
@@ -170,6 +174,35 @@ static int host2guc_sample_forcewake(str
 	return host2guc_action(guc, data, ARRAY_SIZE(data));
 }
 
+static int host2guc_logbuffer_flush_complete(struct intel_guc *guc)
+{
+	u32 data[1];
+
+	data[0] = HOST2GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE;
+
+	return host2guc_action(guc, data, 1);
+}
+
+static int host2guc_force_logbuffer_flush(struct intel_guc *guc)
+{
+	u32 data[2];
+
+	data[0] = HOST2GUC_ACTION_FORCE_LOG_BUFFER_FLUSH;
+	data[1] = 0;
+
+	return host2guc_action(guc, data, 2);
+}
+
+static int host2guc_logging_control(struct intel_guc *guc, u32 control_val)
+{
+	u32 data[2];
+
+	data[0] = HOST2GUC_ACTION_UK_LOG_ENABLE_LOGGING;
+	data[1] = control_val;
+
+	return host2guc_action(guc, data, 2);
+}
+
 /*
  * Initialise, update, or clear doorbell data shared with the GuC
  *
@@ -187,7 +220,7 @@ static int guc_update_doorbell_id(struct
 	struct guc_context_desc desc;
 	size_t len;
 
-	doorbell = client->client_base + client->doorbell_offset;
+	doorbell = client->vaddr + client->doorbell_offset;
 
 	if (client->doorbell_id != GUC_INVALID_DOORBELL_ID &&
 	    test_bit(client->doorbell_id, doorbell_bitmap)) {
@@ -293,7 +326,7 @@ static void guc_proc_desc_init(struct in
 {
 	struct guc_process_desc *desc;
 
-	desc = client->client_base + client->proc_desc_offset;
+	desc = client->vaddr + client->proc_desc_offset;
 
 	memset(desc, 0, sizeof(*desc));
 
@@ -380,8 +413,8 @@ static void guc_ctx_desc_init(struct int
 	gfx_addr = i915_ggtt_offset(client->vma);
 	desc.db_trigger_phy = sg_dma_address(client->vma->pages->sgl) +
 				client->doorbell_offset;
-	desc.db_trigger_cpu = (uintptr_t)client->client_base +
-				client->doorbell_offset;
+	desc.db_trigger_cpu =
+		(uintptr_t)client->vaddr + client->doorbell_offset;
 	desc.db_trigger_uk = gfx_addr + client->doorbell_offset;
 	desc.process_desc = gfx_addr + client->proc_desc_offset;
 	desc.wq_addr = gfx_addr + client->wq_offset;
@@ -432,7 +465,7 @@ int i915_guc_wq_reserve(struct drm_i915_
 {
 	const size_t wqi_size = sizeof(struct guc_wq_item);
 	struct i915_guc_client *gc = request->i915->guc.execbuf_client;
-	struct guc_process_desc *desc = gc->client_base + gc->proc_desc_offset;
+	struct guc_process_desc *desc = gc->vaddr + gc->proc_desc_offset;
 	u32 freespace;
 	int ret;
 
@@ -473,10 +506,9 @@ static void guc_wq_item_append(struct i9
 	struct intel_engine_cs *engine = rq->engine;
 	struct guc_process_desc *desc;
 	struct guc_wq_item *wqi;
-	void *base;
-	u32 freespace, tail, wq_off, wq_page;
+	u32 freespace, tail, wq_off;
 
-	desc = gc->client_base + gc->proc_desc_offset;
+	desc = gc->vaddr + gc->proc_desc_offset;
 
 	/* Free space is guaranteed, see i915_guc_wq_reserve() above */
 	freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
@@ -506,10 +538,7 @@ static void guc_wq_item_append(struct i9
 	gc->wq_rsvd -= wqi_size;
 
 	/* WQ starts from the page after doorbell / process_desc */
-	wq_page = (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT;
-	wq_off &= PAGE_SIZE - 1;
-	base = kmap_atomic(i915_gem_object_get_page(gc->vma->obj, wq_page));
-	wqi = (struct guc_wq_item *)((char *)base + wq_off);
+	wqi = gc->vaddr + wq_off + GUC_DB_SIZE;
 
 	/* Now fill in the 4-word work queue item */
 	wqi->header = WQ_TYPE_INORDER |
@@ -521,9 +550,7 @@ static void guc_wq_item_append(struct i9
 	wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, engine);
 
 	wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT;
-	wqi->fence_id = rq->fence.seqno;
-
-	kunmap_atomic(base);
+	wqi->fence_id = rq->global_seqno;
 }
 
 static int guc_ring_doorbell(struct i915_guc_client *gc)
@@ -533,7 +560,7 @@ static int guc_ring_doorbell(struct i915
 	union guc_doorbell_qw *db;
 	int attempt = 2, ret = -EAGAIN;
 
-	desc = gc->client_base + gc->proc_desc_offset;
+	desc = gc->vaddr + gc->proc_desc_offset;
 
 	/* Update the tail so it is visible to GuC */
 	desc->tail = gc->wq_tail;
@@ -549,7 +576,7 @@ static int guc_ring_doorbell(struct i915
 		db_exc.cookie = 1;
 
 	/* pointer of current doorbell cacheline */
-	db = gc->client_base + gc->doorbell_offset;
+	db = gc->vaddr + gc->doorbell_offset;
 
 	while (attempt--) {
 		/* lets ring the doorbell */
@@ -601,13 +628,31 @@ static int guc_ring_doorbell(struct i915
  */
 static void i915_guc_submit(struct drm_i915_gem_request *rq)
 {
-	unsigned int engine_id = rq->engine->id;
+	struct drm_i915_private *dev_priv = rq->i915;
+	struct intel_engine_cs *engine = rq->engine;
+	unsigned int engine_id = engine->id;
 	struct intel_guc *guc = &rq->i915->guc;
 	struct i915_guc_client *client = guc->execbuf_client;
 	int b_ret;
 
+	/* We keep the previous context alive until we retire the following
+	 * request. This ensures that any the context object is still pinned
+	 * for any residual writes the HW makes into it on the context switch
+	 * into the next object following the breadcrumb. Otherwise, we may
+	 * retire the context too early.
+	 */
+	rq->previous_context = engine->last_context;
+	engine->last_context = rq->ctx;
+
+	i915_gem_request_submit(rq);
+
 	spin_lock(&client->wq_lock);
 	guc_wq_item_append(client, rq);
+
+	/* WA to flush out the pending GMADR writes to ring buffer. */
+	if (i915_vma_is_map_and_fenceable(rq->ring->vma))
+		POSTING_READ_FW(GUC_STATUS);
+
 	b_ret = guc_ring_doorbell(client);
 
 	client->submissions[engine_id] += 1;
@@ -616,7 +661,7 @@ static void i915_guc_submit(struct drm_i
 		client->b_fail += 1;
 
 	guc->submissions[engine_id] += 1;
-	guc->last_seqno[engine_id] = rq->fence.seqno;
+	guc->last_seqno[engine_id] = rq->global_seqno;
 	spin_unlock(&client->wq_lock);
 }
 
@@ -685,14 +730,14 @@ guc_client_free(struct drm_i915_private
 	 * Be sure to drop any locks
 	 */
 
-	if (client->client_base) {
+	if (client->vaddr) {
 		/*
 		 * If we got as far as setting up a doorbell, make sure we
 		 * shut it down before unmapping & deallocating the memory.
 		 */
 		guc_disable_doorbell(guc, client);
 
-		kunmap(kmap_to_page(client->client_base));
+		i915_gem_object_unpin_map(client->vma->obj);
 	}
 
 	i915_vma_unpin_and_release(&client->vma);
@@ -781,6 +826,7 @@ guc_client_alloc(struct drm_i915_private
 	struct i915_guc_client *client;
 	struct intel_guc *guc = &dev_priv->guc;
 	struct i915_vma *vma;
+	void *vaddr;
 	uint16_t db_id;
 
 	client = kzalloc(sizeof(*client), GFP_KERNEL);
@@ -807,7 +853,12 @@ guc_client_alloc(struct drm_i915_private
 
 	/* We'll keep just the first (doorbell/proc) page permanently kmap'd. */
 	client->vma = vma;
-	client->client_base = kmap(i915_vma_first_page(vma));
+
+	vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
+	if (IS_ERR(vaddr))
+		goto err;
+
+	client->vaddr = vaddr;
 
 	spin_lock_init(&client->wq_lock);
 	client->wq_offset = GUC_DB_SIZE;
@@ -847,15 +898,411 @@ err:
 	return NULL;
 }
 
+/*
+ * Sub buffer switch callback. Called whenever relay has to switch to a new
+ * sub buffer, relay stays on the same sub buffer if 0 is returned.
+ */
+static int subbuf_start_callback(struct rchan_buf *buf,
+				 void *subbuf,
+				 void *prev_subbuf,
+				 size_t prev_padding)
+{
+	/* Use no-overwrite mode by default, where relay will stop accepting
+	 * new data if there are no empty sub buffers left.
+	 * There is no strict synchronization enforced by relay between Consumer
+	 * and Producer. In overwrite mode, there is a possibility of getting
+	 * inconsistent/garbled data, the producer could be writing on to the
+	 * same sub buffer from which Consumer is reading. This can't be avoided
+	 * unless Consumer is fast enough and can always run in tandem with
+	 * Producer.
+	 */
+	if (relay_buf_full(buf))
+		return 0;
+
+	return 1;
+}
+
+/*
+ * file_create() callback. Creates relay file in debugfs.
+ */
+static struct dentry *create_buf_file_callback(const char *filename,
+					       struct dentry *parent,
+					       umode_t mode,
+					       struct rchan_buf *buf,
+					       int *is_global)
+{
+	struct dentry *buf_file;
+
+	/* This to enable the use of a single buffer for the relay channel and
+	 * correspondingly have a single file exposed to User, through which
+	 * it can collect the logs in order without any post-processing.
+	 * Need to set 'is_global' even if parent is NULL for early logging.
+	 */
+	*is_global = 1;
+
+	if (!parent)
+		return NULL;
+
+	/* Not using the channel filename passed as an argument, since for each
+	 * channel relay appends the corresponding CPU number to the filename
+	 * passed in relay_open(). This should be fine as relay just needs a
+	 * dentry of the file associated with the channel buffer and that file's
+	 * name need not be same as the filename passed as an argument.
+	 */
+	buf_file = debugfs_create_file("guc_log", mode,
+				       parent, buf, &relay_file_operations);
+	return buf_file;
+}
+
+/*
+ * file_remove() default callback. Removes relay file in debugfs.
+ */
+static int remove_buf_file_callback(struct dentry *dentry)
+{
+	debugfs_remove(dentry);
+	return 0;
+}
+
+/* relay channel callbacks */
+static struct rchan_callbacks relay_callbacks = {
+	.subbuf_start = subbuf_start_callback,
+	.create_buf_file = create_buf_file_callback,
+	.remove_buf_file = remove_buf_file_callback,
+};
+
+static void guc_log_remove_relay_file(struct intel_guc *guc)
+{
+	relay_close(guc->log.relay_chan);
+}
+
+static int guc_log_create_relay_channel(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	struct rchan *guc_log_relay_chan;
+	size_t n_subbufs, subbuf_size;
+
+	/* Keep the size of sub buffers same as shared log buffer */
+	subbuf_size = guc->log.vma->obj->base.size;
+
+	/* Store up to 8 snapshots, which is large enough to buffer sufficient
+	 * boot time logs and provides enough leeway to User, in terms of
+	 * latency, for consuming the logs from relay. Also doesn't take
+	 * up too much memory.
+	 */
+	n_subbufs = 8;
+
+	guc_log_relay_chan = relay_open(NULL, NULL, subbuf_size,
+					n_subbufs, &relay_callbacks, dev_priv);
+	if (!guc_log_relay_chan) {
+		DRM_ERROR("Couldn't create relay chan for GuC logging\n");
+		return -ENOMEM;
+	}
+
+	GEM_BUG_ON(guc_log_relay_chan->subbuf_size < subbuf_size);
+	guc->log.relay_chan = guc_log_relay_chan;
+	return 0;
+}
+
+static int guc_log_create_relay_file(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	struct dentry *log_dir;
+	int ret;
+
+	/* For now create the log file in /sys/kernel/debug/dri/0 dir */
+	log_dir = dev_priv->drm.primary->debugfs_root;
+
+	/* If /sys/kernel/debug/dri/0 location do not exist, then debugfs is
+	 * not mounted and so can't create the relay file.
+	 * The relay API seems to fit well with debugfs only, for availing relay
+	 * there are 3 requirements which can be met for debugfs file only in a
+	 * straightforward/clean manner :-
+	 * i)   Need the associated dentry pointer of the file, while opening the
+	 *      relay channel.
+	 * ii)  Should be able to use 'relay_file_operations' fops for the file.
+	 * iii) Set the 'i_private' field of file's inode to the pointer of
+	 *	relay channel buffer.
+	 */
+	if (!log_dir) {
+		DRM_ERROR("Debugfs dir not available yet for GuC log file\n");
+		return -ENODEV;
+	}
+
+	ret = relay_late_setup_files(guc->log.relay_chan, "guc_log", log_dir);
+	if (ret) {
+		DRM_ERROR("Couldn't associate relay chan with file %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void guc_move_to_next_buf(struct intel_guc *guc)
+{
+	/* Make sure the updates made in the sub buffer are visible when
+	 * Consumer sees the following update to offset inside the sub buffer.
+	 */
+	smp_wmb();
+
+	/* All data has been written, so now move the offset of sub buffer. */
+	relay_reserve(guc->log.relay_chan, guc->log.vma->obj->base.size);
+
+	/* Switch to the next sub buffer */
+	relay_flush(guc->log.relay_chan);
+}
+
+static void *guc_get_write_buffer(struct intel_guc *guc)
+{
+	if (!guc->log.relay_chan)
+		return NULL;
+
+	/* Just get the base address of a new sub buffer and copy data into it
+	 * ourselves. NULL will be returned in no-overwrite mode, if all sub
+	 * buffers are full. Could have used the relay_write() to indirectly
+	 * copy the data, but that would have been bit convoluted, as we need to
+	 * write to only certain locations inside a sub buffer which cannot be
+	 * done without using relay_reserve() along with relay_write(). So its
+	 * better to use relay_reserve() alone.
+	 */
+	return relay_reserve(guc->log.relay_chan, 0);
+}
+
+static bool
+guc_check_log_buf_overflow(struct intel_guc *guc,
+			   enum guc_log_buffer_type type, unsigned int full_cnt)
+{
+	unsigned int prev_full_cnt = guc->log.prev_overflow_count[type];
+	bool overflow = false;
+
+	if (full_cnt != prev_full_cnt) {
+		overflow = true;
+
+		guc->log.prev_overflow_count[type] = full_cnt;
+		guc->log.total_overflow_count[type] += full_cnt - prev_full_cnt;
+
+		if (full_cnt < prev_full_cnt) {
+			/* buffer_full_cnt is a 4 bit counter */
+			guc->log.total_overflow_count[type] += 16;
+		}
+		DRM_ERROR_RATELIMITED("GuC log buffer overflow\n");
+	}
+
+	return overflow;
+}
+
+static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type)
+{
+	switch (type) {
+	case GUC_ISR_LOG_BUFFER:
+		return (GUC_LOG_ISR_PAGES + 1) * PAGE_SIZE;
+	case GUC_DPC_LOG_BUFFER:
+		return (GUC_LOG_DPC_PAGES + 1) * PAGE_SIZE;
+	case GUC_CRASH_DUMP_LOG_BUFFER:
+		return (GUC_LOG_CRASH_PAGES + 1) * PAGE_SIZE;
+	default:
+		MISSING_CASE(type);
+	}
+
+	return 0;
+}
+
+static void guc_read_update_log_buffer(struct intel_guc *guc)
+{
+	unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt;
+	struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state;
+	struct guc_log_buffer_state log_buf_state_local;
+	enum guc_log_buffer_type type;
+	void *src_data, *dst_data;
+	bool new_overflow;
+
+	if (WARN_ON(!guc->log.buf_addr))
+		return;
+
+	/* Get the pointer to shared GuC log buffer */
+	log_buf_state = src_data = guc->log.buf_addr;
+
+	/* Get the pointer to local buffer to store the logs */
+	log_buf_snapshot_state = dst_data = guc_get_write_buffer(guc);
+
+	/* Actual logs are present from the 2nd page */
+	src_data += PAGE_SIZE;
+	dst_data += PAGE_SIZE;
+
+	for (type = GUC_ISR_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) {
+		/* Make a copy of the state structure, inside GuC log buffer
+		 * (which is uncached mapped), on the stack to avoid reading
+		 * from it multiple times.
+		 */
+		memcpy(&log_buf_state_local, log_buf_state,
+		       sizeof(struct guc_log_buffer_state));
+		buffer_size = guc_get_log_buffer_size(type);
+		read_offset = log_buf_state_local.read_ptr;
+		write_offset = log_buf_state_local.sampled_write_ptr;
+		full_cnt = log_buf_state_local.buffer_full_cnt;
+
+		/* Bookkeeping stuff */
+		guc->log.flush_count[type] += log_buf_state_local.flush_to_file;
+		new_overflow = guc_check_log_buf_overflow(guc, type, full_cnt);
+
+		/* Update the state of shared log buffer */
+		log_buf_state->read_ptr = write_offset;
+		log_buf_state->flush_to_file = 0;
+		log_buf_state++;
+
+		if (unlikely(!log_buf_snapshot_state))
+			continue;
+
+		/* First copy the state structure in snapshot buffer */
+		memcpy(log_buf_snapshot_state, &log_buf_state_local,
+		       sizeof(struct guc_log_buffer_state));
+
+		/* The write pointer could have been updated by GuC firmware,
+		 * after sending the flush interrupt to Host, for consistency
+		 * set write pointer value to same value of sampled_write_ptr
+		 * in the snapshot buffer.
+		 */
+		log_buf_snapshot_state->write_ptr = write_offset;
+		log_buf_snapshot_state++;
+
+		/* Now copy the actual logs. */
+		if (unlikely(new_overflow)) {
+			/* copy the whole buffer in case of overflow */
+			read_offset = 0;
+			write_offset = buffer_size;
+		} else if (unlikely((read_offset > buffer_size) ||
+				    (write_offset > buffer_size))) {
+			DRM_ERROR("invalid log buffer state\n");
+			/* copy whole buffer as offsets are unreliable */
+			read_offset = 0;
+			write_offset = buffer_size;
+		}
+
+		/* Just copy the newly written data */
+		if (read_offset > write_offset) {
+			i915_memcpy_from_wc(dst_data, src_data, write_offset);
+			bytes_to_copy = buffer_size - read_offset;
+		} else {
+			bytes_to_copy = write_offset - read_offset;
+		}
+		i915_memcpy_from_wc(dst_data + read_offset,
+				    src_data + read_offset, bytes_to_copy);
+
+		src_data += buffer_size;
+		dst_data += buffer_size;
+	}
+
+	if (log_buf_snapshot_state)
+		guc_move_to_next_buf(guc);
+	else {
+		/* Used rate limited to avoid deluge of messages, logs might be
+		 * getting consumed by User at a slow rate.
+		 */
+		DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n");
+		guc->log.capture_miss_count++;
+	}
+}
+
+static void guc_capture_logs_work(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, struct drm_i915_private, guc.log.flush_work);
+
+	i915_guc_capture_logs(dev_priv);
+}
+
+static void guc_log_cleanup(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+	/* First disable the flush interrupt */
+	gen9_disable_guc_interrupts(dev_priv);
+
+	if (guc->log.flush_wq)
+		destroy_workqueue(guc->log.flush_wq);
+
+	guc->log.flush_wq = NULL;
+
+	if (guc->log.relay_chan)
+		guc_log_remove_relay_file(guc);
+
+	guc->log.relay_chan = NULL;
+
+	if (guc->log.buf_addr)
+		i915_gem_object_unpin_map(guc->log.vma->obj);
+
+	guc->log.buf_addr = NULL;
+}
+
+static int guc_log_create_extras(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	void *vaddr;
+	int ret;
+
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+	/* Nothing to do */
+	if (i915.guc_log_level < 0)
+		return 0;
+
+	if (!guc->log.buf_addr) {
+		/* Create a WC (Uncached for read) vmalloc mapping of log
+		 * buffer pages, so that we can directly get the data
+		 * (up-to-date) from memory.
+		 */
+		vaddr = i915_gem_object_pin_map(guc->log.vma->obj, I915_MAP_WC);
+		if (IS_ERR(vaddr)) {
+			ret = PTR_ERR(vaddr);
+			DRM_ERROR("Couldn't map log buffer pages %d\n", ret);
+			return ret;
+		}
+
+		guc->log.buf_addr = vaddr;
+	}
+
+	if (!guc->log.relay_chan) {
+		/* Create a relay channel, so that we have buffers for storing
+		 * the GuC firmware logs, the channel will be linked with a file
+		 * later on when debugfs is registered.
+		 */
+		ret = guc_log_create_relay_channel(guc);
+		if (ret)
+			return ret;
+	}
+
+	if (!guc->log.flush_wq) {
+		INIT_WORK(&guc->log.flush_work, guc_capture_logs_work);
+
+		 /*
+		 * GuC log buffer flush work item has to do register access to
+		 * send the ack to GuC and this work item, if not synced before
+		 * suspend, can potentially get executed after the GFX device is
+		 * suspended.
+		 * By marking the WQ as freezable, we don't have to bother about
+		 * flushing of this work item from the suspend hooks, the pending
+		 * work item if any will be either executed before the suspend
+		 * or scheduled later on resume. This way the handling of work
+		 * item can be kept same between system suspend & rpm suspend.
+		 */
+		guc->log.flush_wq = alloc_ordered_workqueue("i915-guc_log",
+							    WQ_HIGHPRI | WQ_FREEZABLE);
+		if (guc->log.flush_wq == NULL) {
+			DRM_ERROR("Couldn't allocate the wq for GuC logging\n");
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
 static void guc_log_create(struct intel_guc *guc)
 {
 	struct i915_vma *vma;
 	unsigned long offset;
 	uint32_t size, flags;
 
-	if (i915.guc_log_level < GUC_LOG_VERBOSITY_MIN)
-		return;
-
 	if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX)
 		i915.guc_log_level = GUC_LOG_VERBOSITY_MAX;
 
@@ -865,8 +1312,18 @@ static void guc_log_create(struct intel_
 		GUC_LOG_ISR_PAGES + 1 +
 		GUC_LOG_CRASH_PAGES + 1) << PAGE_SHIFT;
 
-	vma = guc->log_vma;
+	vma = guc->log.vma;
 	if (!vma) {
+		/* We require SSE 4.1 for fast reads from the GuC log buffer and
+		 * it should be present on the chipsets supporting GuC based
+		 * submisssions.
+		 */
+		if (WARN_ON(!i915_memcpy_from_wc(NULL, NULL, 0))) {
+			/* logging will not be enabled */
+			i915.guc_log_level = -1;
+			return;
+		}
+
 		vma = guc_allocate_vma(guc, size);
 		if (IS_ERR(vma)) {
 			/* logging will be off */
@@ -874,7 +1331,14 @@ static void guc_log_create(struct intel_
 			return;
 		}
 
-		guc->log_vma = vma;
+		guc->log.vma = vma;
+
+		if (guc_log_create_extras(guc)) {
+			guc_log_cleanup(guc);
+			i915_vma_unpin_and_release(&guc->log.vma);
+			i915.guc_log_level = -1;
+			return;
+		}
 	}
 
 	/* each allocated unit is a page */
@@ -884,7 +1348,37 @@ static void guc_log_create(struct intel_
 		(GUC_LOG_CRASH_PAGES << GUC_LOG_CRASH_SHIFT);
 
 	offset = i915_ggtt_offset(vma) >> PAGE_SHIFT; /* in pages */
-	guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
+	guc->log.flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
+}
+
+static int guc_log_late_setup(struct intel_guc *guc)
+{
+	struct drm_i915_private *dev_priv = guc_to_i915(guc);
+	int ret;
+
+	lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+	if (i915.guc_log_level < 0)
+		return -EINVAL;
+
+	/* If log_level was set as -1 at boot time, then setup needed to
+	 * handle log buffer flush interrupts would not have been done yet,
+	 * so do that now.
+	 */
+	ret = guc_log_create_extras(guc);
+	if (ret)
+		goto err;
+
+	ret = guc_log_create_relay_file(guc);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	guc_log_cleanup(guc);
+	/* logging will remain off */
+	i915.guc_log_level = -1;
+	return ret;
 }
 
 static void guc_policies_init(struct guc_policies *policies)
@@ -917,6 +1411,7 @@ static void guc_addon_create(struct inte
 	struct guc_policies *policies;
 	struct guc_mmio_reg_state *reg_state;
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	struct page *page;
 	u32 size;
 
@@ -944,10 +1439,10 @@ static void guc_addon_create(struct inte
 	 * so its address won't change after we've told the GuC where
 	 * to find it.
 	 */
-	engine = &dev_priv->engine[RCS];
+	engine = dev_priv->engine[RCS];
 	ads->golden_context_lrca = engine->status_page.ggtt_offset;
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine);
 
 	/* GuC scheduling policies */
@@ -960,7 +1455,7 @@ static void guc_addon_create(struct inte
 	/* MMIO reg state */
 	reg_state = (void *)policies + sizeof(struct guc_policies);
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		reg_state->mmio_white_list[engine->guc_id].mmio_start =
 			engine->mmio_base + GUC_MMIO_WHITE_LIST_START;
 
@@ -1005,6 +1500,7 @@ int i915_guc_submission_init(struct drm_
 
 	guc->ctx_pool_vma = vma;
 	ida_init(&guc->ctx_ids);
+	mutex_init(&guc->action_lock);
 	guc_log_create(guc);
 	guc_addon_create(guc);
 
@@ -1014,9 +1510,10 @@ int i915_guc_submission_init(struct drm_
 int i915_guc_submission_enable(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc *guc = &dev_priv->guc;
+	struct drm_i915_gem_request *request;
 	struct i915_guc_client *client;
 	struct intel_engine_cs *engine;
-	struct drm_i915_gem_request *request;
+	enum intel_engine_id id;
 
 	/* client for execbuf submission */
 	client = guc_client_alloc(dev_priv,
@@ -1033,11 +1530,13 @@ int i915_guc_submission_enable(struct dr
 	guc_init_doorbell_hw(guc);
 
 	/* Take over from manual control of ELSP (execlists) */
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		engine->submit_request = i915_guc_submit;
+		engine->schedule = NULL;
 
 		/* Replay the current set of previously submitted requests */
-		list_for_each_entry(request, &engine->request_list, link) {
+		list_for_each_entry(request,
+				    &engine->timeline->requests, link) {
 			client->wq_rsvd += sizeof(struct guc_wq_item);
 			if (i915_sw_fence_done(&request->submit))
 				i915_guc_submit(request);
@@ -1066,7 +1565,7 @@ void i915_guc_submission_fini(struct drm
 	struct intel_guc *guc = &dev_priv->guc;
 
 	i915_vma_unpin_and_release(&guc->ads_vma);
-	i915_vma_unpin_and_release(&guc->log_vma);
+	i915_vma_unpin_and_release(&guc->log.vma);
 
 	if (guc->ctx_pool_vma)
 		ida_destroy(&guc->ctx_ids);
@@ -1087,6 +1586,8 @@ int intel_guc_suspend(struct drm_device
 	if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
 		return 0;
 
+	gen9_disable_guc_interrupts(dev_priv);
+
 	ctx = dev_priv->kernel_context;
 
 	data[0] = HOST2GUC_ACTION_ENTER_S_STATE;
@@ -1113,6 +1614,9 @@ int intel_guc_resume(struct drm_device *
 	if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
 		return 0;
 
+	if (i915.guc_log_level >= 0)
+		gen9_enable_guc_interrupts(dev_priv);
+
 	ctx = dev_priv->kernel_context;
 
 	data[0] = HOST2GUC_ACTION_EXIT_S_STATE;
@@ -1122,3 +1626,104 @@ int intel_guc_resume(struct drm_device *
 
 	return host2guc_action(guc, data, ARRAY_SIZE(data));
 }
+
+void i915_guc_capture_logs(struct drm_i915_private *dev_priv)
+{
+	guc_read_update_log_buffer(&dev_priv->guc);
+
+	/* Generally device is expected to be active only at this
+	 * time, so get/put should be really quick.
+	 */
+	intel_runtime_pm_get(dev_priv);
+	host2guc_logbuffer_flush_complete(&dev_priv->guc);
+	intel_runtime_pm_put(dev_priv);
+}
+
+void i915_guc_flush_logs(struct drm_i915_private *dev_priv)
+{
+	if (!i915.enable_guc_submission || (i915.guc_log_level < 0))
+		return;
+
+	/* First disable the interrupts, will be renabled afterwards */
+	gen9_disable_guc_interrupts(dev_priv);
+
+	/* Before initiating the forceful flush, wait for any pending/ongoing
+	 * flush to complete otherwise forceful flush may not actually happen.
+	 */
+	flush_work(&dev_priv->guc.log.flush_work);
+
+	/* Ask GuC to update the log buffer state */
+	host2guc_force_logbuffer_flush(&dev_priv->guc);
+
+	/* GuC would have updated log buffer by now, so capture it */
+	i915_guc_capture_logs(dev_priv);
+}
+
+void i915_guc_unregister(struct drm_i915_private *dev_priv)
+{
+	if (!i915.enable_guc_submission)
+		return;
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	guc_log_cleanup(&dev_priv->guc);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+void i915_guc_register(struct drm_i915_private *dev_priv)
+{
+	if (!i915.enable_guc_submission)
+		return;
+
+	mutex_lock(&dev_priv->drm.struct_mutex);
+	guc_log_late_setup(&dev_priv->guc);
+	mutex_unlock(&dev_priv->drm.struct_mutex);
+}
+
+int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val)
+{
+	union guc_log_control log_param;
+	int ret;
+
+	log_param.value = control_val;
+
+	if (log_param.verbosity < GUC_LOG_VERBOSITY_MIN ||
+	    log_param.verbosity > GUC_LOG_VERBOSITY_MAX)
+		return -EINVAL;
+
+	/* This combination doesn't make sense & won't have any effect */
+	if (!log_param.logging_enabled && (i915.guc_log_level < 0))
+		return 0;
+
+	ret = host2guc_logging_control(&dev_priv->guc, log_param.value);
+	if (ret < 0) {
+		DRM_DEBUG_DRIVER("host2guc action failed %d\n", ret);
+		return ret;
+	}
+
+	i915.guc_log_level = log_param.verbosity;
+
+	/* If log_level was set as -1 at boot time, then the relay channel file
+	 * wouldn't have been created by now and interrupts also would not have
+	 * been enabled.
+	 */
+	if (!dev_priv->guc.log.relay_chan) {
+		ret = guc_log_late_setup(&dev_priv->guc);
+		if (!ret)
+			gen9_enable_guc_interrupts(dev_priv);
+	} else if (!log_param.logging_enabled) {
+		/* Once logging is disabled, GuC won't generate logs & send an
+		 * interrupt. But there could be some data in the log buffer
+		 * which is yet to be captured. So request GuC to update the log
+		 * buffer state and then collect the left over logs.
+		 */
+		i915_guc_flush_logs(dev_priv);
+
+		/* As logging is disabled, update log level to reflect that */
+		i915.guc_log_level = -1;
+	} else {
+		/* In case interrupts were disabled, enable them now */
+		gen9_enable_guc_interrupts(dev_priv);
+	}
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -170,6 +170,7 @@ static void gen5_assert_iir_is_zero(stru
 } while (0)
 
 static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
+static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir);
 
 /* For display hotplug interrupt */
 static inline void
@@ -303,18 +304,18 @@ static void snb_update_pm_irq(struct drm
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	new_val = dev_priv->pm_irq_mask;
+	new_val = dev_priv->pm_imr;
 	new_val &= ~interrupt_mask;
 	new_val |= (~enabled_irq_mask & interrupt_mask);
 
-	if (new_val != dev_priv->pm_irq_mask) {
-		dev_priv->pm_irq_mask = new_val;
-		I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_irq_mask);
+	if (new_val != dev_priv->pm_imr) {
+		dev_priv->pm_imr = new_val;
+		I915_WRITE(gen6_pm_imr(dev_priv), dev_priv->pm_imr);
 		POSTING_READ(gen6_pm_imr(dev_priv));
 	}
 }
 
-void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
 	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
 		return;
@@ -322,28 +323,54 @@ void gen6_enable_pm_irq(struct drm_i915_
 	snb_update_pm_irq(dev_priv, mask, mask);
 }
 
-static void __gen6_disable_pm_irq(struct drm_i915_private *dev_priv,
-				  uint32_t mask)
+static void __gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
 	snb_update_pm_irq(dev_priv, mask, 0);
 }
 
-void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
+void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask)
 {
 	if (WARN_ON(!intel_irqs_enabled(dev_priv)))
 		return;
 
-	__gen6_disable_pm_irq(dev_priv, mask);
+	__gen6_mask_pm_irq(dev_priv, mask);
 }
 
-void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv)
+void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 reset_mask)
 {
 	i915_reg_t reg = gen6_pm_iir(dev_priv);
 
-	spin_lock_irq(&dev_priv->irq_lock);
-	I915_WRITE(reg, dev_priv->pm_rps_events);
-	I915_WRITE(reg, dev_priv->pm_rps_events);
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	I915_WRITE(reg, reset_mask);
+	I915_WRITE(reg, reset_mask);
 	POSTING_READ(reg);
+}
+
+void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, u32 enable_mask)
+{
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	dev_priv->pm_ier |= enable_mask;
+	I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier);
+	gen6_unmask_pm_irq(dev_priv, enable_mask);
+	/* unmask_pm_irq provides an implicit barrier (POSTING_READ) */
+}
+
+void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, u32 disable_mask)
+{
+	assert_spin_locked(&dev_priv->irq_lock);
+
+	dev_priv->pm_ier &= ~disable_mask;
+	__gen6_mask_pm_irq(dev_priv, disable_mask);
+	I915_WRITE(gen6_pm_ier(dev_priv), dev_priv->pm_ier);
+	/* though a barrier is missing here, but don't really need a one */
+}
+
+void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv)
+{
+	spin_lock_irq(&dev_priv->irq_lock);
+	gen6_reset_pm_iir(dev_priv, dev_priv->pm_rps_events);
 	dev_priv->rps.pm_iir = 0;
 	spin_unlock_irq(&dev_priv->irq_lock);
 }
@@ -357,8 +384,6 @@ void gen6_enable_rps_interrupts(struct d
 	WARN_ON_ONCE(dev_priv->rps.pm_iir);
 	WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events);
 	dev_priv->rps.interrupts_enabled = true;
-	I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) |
-				dev_priv->pm_rps_events);
 	gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
 
 	spin_unlock_irq(&dev_priv->irq_lock);
@@ -379,9 +404,7 @@ void gen6_disable_rps_interrupts(struct
 
 	I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0u));
 
-	__gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events);
-	I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) &
-				~dev_priv->pm_rps_events);
+	gen6_disable_pm_irq(dev_priv, dev_priv->pm_rps_events);
 
 	spin_unlock_irq(&dev_priv->irq_lock);
 	synchronize_irq(dev_priv->drm.irq);
@@ -395,6 +418,38 @@ void gen6_disable_rps_interrupts(struct
 	gen6_reset_rps_interrupts(dev_priv);
 }
 
+void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv)
+{
+	spin_lock_irq(&dev_priv->irq_lock);
+	gen6_reset_pm_iir(dev_priv, dev_priv->pm_guc_events);
+	spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv)
+{
+	spin_lock_irq(&dev_priv->irq_lock);
+	if (!dev_priv->guc.interrupts_enabled) {
+		WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) &
+				       dev_priv->pm_guc_events);
+		dev_priv->guc.interrupts_enabled = true;
+		gen6_enable_pm_irq(dev_priv, dev_priv->pm_guc_events);
+	}
+	spin_unlock_irq(&dev_priv->irq_lock);
+}
+
+void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv)
+{
+	spin_lock_irq(&dev_priv->irq_lock);
+	dev_priv->guc.interrupts_enabled = false;
+
+	gen6_disable_pm_irq(dev_priv, dev_priv->pm_guc_events);
+
+	spin_unlock_irq(&dev_priv->irq_lock);
+	synchronize_irq(dev_priv->drm.irq);
+
+	gen9_reset_guc_interrupts(dev_priv);
+}
+
 /**
  * bdw_update_port_irq - update DE port interrupt
  * @dev_priv: driver private
@@ -670,8 +725,8 @@ static u32 i915_get_vblank_counter(struc
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	i915_reg_t high_frame, low_frame;
 	u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal;
-	struct intel_crtc *intel_crtc =
-		to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+	struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
+								pipe);
 	const struct drm_display_mode *mode = &intel_crtc->base.hwmode;
 
 	htotal = mode->crtc_htotal;
@@ -776,8 +831,8 @@ static int i915_get_crtc_scanoutpos(stru
 				    const struct drm_display_mode *mode)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
+								pipe);
 	int position;
 	int vbl_start, vbl_end, hsync_start, htotal, vtotal;
 	bool in_vbl = true;
@@ -912,21 +967,22 @@ static int i915_get_vblank_timestamp(str
 			      struct timeval *vblank_time,
 			      unsigned flags)
 {
-	struct drm_crtc *crtc;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_crtc *crtc;
 
-	if (pipe >= INTEL_INFO(dev)->num_pipes) {
+	if (pipe >= INTEL_INFO(dev_priv)->num_pipes) {
 		DRM_ERROR("Invalid crtc %u\n", pipe);
 		return -EINVAL;
 	}
 
 	/* Get drm_crtc to timestamp: */
-	crtc = intel_get_crtc_for_pipe(dev, pipe);
+	crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 	if (crtc == NULL) {
 		DRM_ERROR("Invalid crtc %u\n", pipe);
 		return -EINVAL;
 	}
 
-	if (!crtc->hwmode.crtc_clock) {
+	if (!crtc->base.hwmode.crtc_clock) {
 		DRM_DEBUG_KMS("crtc %u is disabled\n", pipe);
 		return -EBUSY;
 	}
@@ -934,7 +990,7 @@ static int i915_get_vblank_timestamp(str
 	/* Helper routine in DRM core does all the work: */
 	return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
 						     vblank_time, flags,
-						     &crtc->hwmode);
+						     &crtc->base.hwmode);
 }
 
 static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
@@ -1058,8 +1114,9 @@ static u32 vlv_wa_c0_ei(struct drm_i915_
 static bool any_waiters(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		if (intel_engine_has_waiter(engine))
 			return true;
 
@@ -1084,7 +1141,7 @@ static void gen6_pm_rps_work(struct work
 	pm_iir = dev_priv->rps.pm_iir;
 	dev_priv->rps.pm_iir = 0;
 	/* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */
-	gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events);
+	gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events);
 	client_boost = dev_priv->rps.client_boost;
 	dev_priv->rps.client_boost = false;
 	spin_unlock_irq(&dev_priv->irq_lock);
@@ -1257,20 +1314,20 @@ static void ilk_gt_irq_handler(struct dr
 			       u32 gt_iir)
 {
 	if (gt_iir & GT_RENDER_USER_INTERRUPT)
-		notify_ring(&dev_priv->engine[RCS]);
+		notify_ring(dev_priv->engine[RCS]);
 	if (gt_iir & ILK_BSD_USER_INTERRUPT)
-		notify_ring(&dev_priv->engine[VCS]);
+		notify_ring(dev_priv->engine[VCS]);
 }
 
 static void snb_gt_irq_handler(struct drm_i915_private *dev_priv,
 			       u32 gt_iir)
 {
 	if (gt_iir & GT_RENDER_USER_INTERRUPT)
-		notify_ring(&dev_priv->engine[RCS]);
+		notify_ring(dev_priv->engine[RCS]);
 	if (gt_iir & GT_BSD_USER_INTERRUPT)
-		notify_ring(&dev_priv->engine[VCS]);
+		notify_ring(dev_priv->engine[VCS]);
 	if (gt_iir & GT_BLT_USER_INTERRUPT)
-		notify_ring(&dev_priv->engine[BCS]);
+		notify_ring(dev_priv->engine[BCS]);
 
 	if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
 		      GT_BSD_CS_ERROR_INTERRUPT |
@@ -1323,11 +1380,13 @@ static irqreturn_t gen8_gt_irq_ack(struc
 			DRM_ERROR("The master control interrupt lied (GT3)!\n");
 	}
 
-	if (master_ctl & GEN8_GT_PM_IRQ) {
+	if (master_ctl & (GEN8_GT_PM_IRQ | GEN8_GT_GUC_IRQ)) {
 		gt_iir[2] = I915_READ_FW(GEN8_GT_IIR(2));
-		if (gt_iir[2] & dev_priv->pm_rps_events) {
+		if (gt_iir[2] & (dev_priv->pm_rps_events |
+				 dev_priv->pm_guc_events)) {
 			I915_WRITE_FW(GEN8_GT_IIR(2),
-				      gt_iir[2] & dev_priv->pm_rps_events);
+				      gt_iir[2] & (dev_priv->pm_rps_events |
+						   dev_priv->pm_guc_events));
 			ret = IRQ_HANDLED;
 		} else
 			DRM_ERROR("The master control interrupt lied (PM)!\n");
@@ -1340,25 +1399,28 @@ static void gen8_gt_irq_handler(struct d
 				u32 gt_iir[4])
 {
 	if (gt_iir[0]) {
-		gen8_cs_irq_handler(&dev_priv->engine[RCS],
+		gen8_cs_irq_handler(dev_priv->engine[RCS],
 				    gt_iir[0], GEN8_RCS_IRQ_SHIFT);
-		gen8_cs_irq_handler(&dev_priv->engine[BCS],
+		gen8_cs_irq_handler(dev_priv->engine[BCS],
 				    gt_iir[0], GEN8_BCS_IRQ_SHIFT);
 	}
 
 	if (gt_iir[1]) {
-		gen8_cs_irq_handler(&dev_priv->engine[VCS],
+		gen8_cs_irq_handler(dev_priv->engine[VCS],
 				    gt_iir[1], GEN8_VCS1_IRQ_SHIFT);
-		gen8_cs_irq_handler(&dev_priv->engine[VCS2],
+		gen8_cs_irq_handler(dev_priv->engine[VCS2],
 				    gt_iir[1], GEN8_VCS2_IRQ_SHIFT);
 	}
 
 	if (gt_iir[3])
-		gen8_cs_irq_handler(&dev_priv->engine[VECS],
+		gen8_cs_irq_handler(dev_priv->engine[VECS],
 				    gt_iir[3], GEN8_VECS_IRQ_SHIFT);
 
 	if (gt_iir[2] & dev_priv->pm_rps_events)
 		gen6_rps_irq_handler(dev_priv, gt_iir[2]);
+
+	if (gt_iir[2] & dev_priv->pm_guc_events)
+		gen9_guc_irq_handler(dev_priv, gt_iir[2]);
 }
 
 static bool bxt_port_hotplug_long_detect(enum port port, u32 val)
@@ -1585,7 +1647,7 @@ static void gen6_rps_irq_handler(struct
 {
 	if (pm_iir & dev_priv->pm_rps_events) {
 		spin_lock(&dev_priv->irq_lock);
-		gen6_disable_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
+		gen6_mask_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events);
 		if (dev_priv->rps.interrupts_enabled) {
 			dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events;
 			schedule_work(&dev_priv->rps.work);
@@ -1598,13 +1660,48 @@ static void gen6_rps_irq_handler(struct
 
 	if (HAS_VEBOX(dev_priv)) {
 		if (pm_iir & PM_VEBOX_USER_INTERRUPT)
-			notify_ring(&dev_priv->engine[VECS]);
+			notify_ring(dev_priv->engine[VECS]);
 
 		if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
 			DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
 	}
 }
 
+static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir)
+{
+	if (gt_iir & GEN9_GUC_TO_HOST_INT_EVENT) {
+		/* Sample the log buffer flush related bits & clear them out now
+		 * itself from the message identity register to minimize the
+		 * probability of losing a flush interrupt, when there are back
+		 * to back flush interrupts.
+		 * There can be a new flush interrupt, for different log buffer
+		 * type (like for ISR), whilst Host is handling one (for DPC).
+		 * Since same bit is used in message register for ISR & DPC, it
+		 * could happen that GuC sets the bit for 2nd interrupt but Host
+		 * clears out the bit on handling the 1st interrupt.
+		 */
+		u32 msg, flush;
+
+		msg = I915_READ(SOFT_SCRATCH(15));
+		flush = msg & (GUC2HOST_MSG_CRASH_DUMP_POSTED |
+			       GUC2HOST_MSG_FLUSH_LOG_BUFFER);
+		if (flush) {
+			/* Clear the message bits that are handled */
+			I915_WRITE(SOFT_SCRATCH(15), msg & ~flush);
+
+			/* Handle flush interrupt in bottom half */
+			queue_work(dev_priv->guc.log.flush_wq,
+				   &dev_priv->guc.log.flush_work);
+
+			dev_priv->guc.log.flush_interrupt_count++;
+		} else {
+			/* Not clearing of unhandled event bits won't result in
+			 * re-triggering of the interrupt.
+			 */
+		}
+	}
+}
+
 static bool intel_pipe_handle_vblank(struct drm_i915_private *dev_priv,
 				     enum pipe pipe)
 {
@@ -2407,7 +2504,7 @@ gen8_de_irq_handler(struct drm_i915_priv
 			fault_errors &= GEN8_DE_PIPE_IRQ_FAULT_ERRORS;
 
 		if (fault_errors)
-			DRM_ERROR("Fault errors on pipe %c\n: 0x%08x",
+			DRM_ERROR("Fault errors on pipe %c: 0x%08x\n",
 				  pipe_name(pipe),
 				  fault_errors);
 	}
@@ -2551,92 +2648,52 @@ static void i915_reset_and_wakeup(struct
 	wake_up_all(&dev_priv->gpu_error.reset_queue);
 }
 
-static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv)
+static inline void
+i915_err_print_instdone(struct drm_i915_private *dev_priv,
+			struct intel_instdone *instdone)
 {
-	uint32_t instdone[I915_NUM_INSTDONE_REG];
-	u32 eir = I915_READ(EIR);
-	int pipe, i;
+	int slice;
+	int subslice;
 
-	if (!eir)
-		return;
+	pr_err("  INSTDONE: 0x%08x\n", instdone->instdone);
 
-	pr_err("render error detected, EIR: 0x%08x\n", eir);
+	if (INTEL_GEN(dev_priv) <= 3)
+		return;
 
-	i915_get_extra_instdone(dev_priv, instdone);
+	pr_err("  SC_INSTDONE: 0x%08x\n", instdone->slice_common);
 
-	if (IS_G4X(dev_priv)) {
-		if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
-			u32 ipeir = I915_READ(IPEIR_I965);
+	if (INTEL_GEN(dev_priv) <= 6)
+		return;
 
-			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
-			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
-			for (i = 0; i < ARRAY_SIZE(instdone); i++)
-				pr_err("  INSTDONE_%d: 0x%08x\n", i, instdone[i]);
-			pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS));
-			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
-			I915_WRITE(IPEIR_I965, ipeir);
-			POSTING_READ(IPEIR_I965);
-		}
-		if (eir & GM45_ERROR_PAGE_TABLE) {
-			u32 pgtbl_err = I915_READ(PGTBL_ER);
-			pr_err("page table error\n");
-			pr_err("  PGTBL_ER: 0x%08x\n", pgtbl_err);
-			I915_WRITE(PGTBL_ER, pgtbl_err);
-			POSTING_READ(PGTBL_ER);
-		}
-	}
+	for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+		pr_err("  SAMPLER_INSTDONE[%d][%d]: 0x%08x\n",
+		       slice, subslice, instdone->sampler[slice][subslice]);
 
-	if (!IS_GEN2(dev_priv)) {
-		if (eir & I915_ERROR_PAGE_TABLE) {
-			u32 pgtbl_err = I915_READ(PGTBL_ER);
-			pr_err("page table error\n");
-			pr_err("  PGTBL_ER: 0x%08x\n", pgtbl_err);
-			I915_WRITE(PGTBL_ER, pgtbl_err);
-			POSTING_READ(PGTBL_ER);
-		}
-	}
+	for_each_instdone_slice_subslice(dev_priv, slice, subslice)
+		pr_err("  ROW_INSTDONE[%d][%d]: 0x%08x\n",
+		       slice, subslice, instdone->row[slice][subslice]);
+}
 
-	if (eir & I915_ERROR_MEMORY_REFRESH) {
-		pr_err("memory refresh error:\n");
-		for_each_pipe(dev_priv, pipe)
-			pr_err("pipe %c stat: 0x%08x\n",
-			       pipe_name(pipe), I915_READ(PIPESTAT(pipe)));
-		/* pipestat has already been acked */
-	}
-	if (eir & I915_ERROR_INSTRUCTION) {
-		pr_err("instruction error\n");
-		pr_err("  INSTPM: 0x%08x\n", I915_READ(INSTPM));
-		for (i = 0; i < ARRAY_SIZE(instdone); i++)
-			pr_err("  INSTDONE_%d: 0x%08x\n", i, instdone[i]);
-		if (INTEL_GEN(dev_priv) < 4) {
-			u32 ipeir = I915_READ(IPEIR);
+static void i915_clear_error_registers(struct drm_i915_private *dev_priv)
+{
+	u32 eir;
 
-			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR));
-			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR));
-			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD));
-			I915_WRITE(IPEIR, ipeir);
-			POSTING_READ(IPEIR);
-		} else {
-			u32 ipeir = I915_READ(IPEIR_I965);
+	if (!IS_GEN2(dev_priv))
+		I915_WRITE(PGTBL_ER, I915_READ(PGTBL_ER));
 
-			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
-			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
-			pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS));
-			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
-			I915_WRITE(IPEIR_I965, ipeir);
-			POSTING_READ(IPEIR_I965);
-		}
-	}
+	if (INTEL_GEN(dev_priv) < 4)
+		I915_WRITE(IPEIR, I915_READ(IPEIR));
+	else
+		I915_WRITE(IPEIR_I965, I915_READ(IPEIR_I965));
 
-	I915_WRITE(EIR, eir);
-	POSTING_READ(EIR);
+	I915_WRITE(EIR, I915_READ(EIR));
 	eir = I915_READ(EIR);
 	if (eir) {
 		/*
 		 * some errors might have become stuck,
 		 * mask them.
 		 */
-		DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir);
+		DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir);
 		I915_WRITE(EMR, I915_READ(EMR) | eir);
 		I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT);
 	}
@@ -2665,7 +2722,7 @@ void i915_handle_error(struct drm_i915_p
 	va_end(args);
 
 	i915_capture_error_state(dev_priv, engine_mask, error_msg);
-	i915_report_and_clear_eir(dev_priv);
+	i915_clear_error_registers(dev_priv);
 
 	if (!engine_mask)
 		return;
@@ -2694,45 +2751,40 @@ void i915_handle_error(struct drm_i915_p
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
-static int i915_enable_vblank(struct drm_device *dev, unsigned int pipe)
+static int i8xx_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	if (INTEL_INFO(dev)->gen >= 4)
-		i915_enable_pipestat(dev_priv, pipe,
-				     PIPE_START_VBLANK_INTERRUPT_STATUS);
-	else
-		i915_enable_pipestat(dev_priv, pipe,
-				     PIPE_VBLANK_INTERRUPT_STATUS);
+	i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
 }
 
-static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
+static int i965_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
-	uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) :
-						     DE_PIPE_VBLANK(pipe);
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	ilk_enable_display_irq(dev_priv, bit);
+	i915_enable_pipestat(dev_priv, pipe,
+			     PIPE_START_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
 }
 
-static int valleyview_enable_vblank(struct drm_device *dev, unsigned int pipe)
+static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
+	uint32_t bit = INTEL_GEN(dev_priv) >= 7 ?
+		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	i915_enable_pipestat(dev_priv, pipe,
-			     PIPE_START_VBLANK_INTERRUPT_STATUS);
+	ilk_enable_display_irq(dev_priv, bit);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
 	return 0;
@@ -2753,38 +2805,36 @@ static int gen8_enable_vblank(struct drm
 /* Called from drm generic code, passed 'crtc' which
  * we use as a pipe index
  */
-static void i915_disable_vblank(struct drm_device *dev, unsigned int pipe)
+static void i8xx_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	i915_disable_pipestat(dev_priv, pipe,
-			      PIPE_VBLANK_INTERRUPT_STATUS |
-			      PIPE_START_VBLANK_INTERRUPT_STATUS);
+	i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe)
+static void i965_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
-	uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) :
-						     DE_PIPE_VBLANK(pipe);
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	ilk_disable_display_irq(dev_priv, bit);
+	i915_disable_pipestat(dev_priv, pipe,
+			      PIPE_START_VBLANK_INTERRUPT_STATUS);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-static void valleyview_disable_vblank(struct drm_device *dev, unsigned int pipe)
+static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	unsigned long irqflags;
+	uint32_t bit = INTEL_GEN(dev_priv) >= 7 ?
+		DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe);
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	i915_disable_pipestat(dev_priv, pipe,
-			      PIPE_START_VBLANK_INTERRUPT_STATUS);
+	ilk_disable_display_irq(dev_priv, bit);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -2798,411 +2848,14 @@ static void gen8_disable_vblank(struct d
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-static bool
-ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr)
-{
-	if (INTEL_GEN(engine->i915) >= 8) {
-		return (ipehr >> 23) == 0x1c;
-	} else {
-		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
-		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
-				 MI_SEMAPHORE_REGISTER);
-	}
-}
-
-static struct intel_engine_cs *
-semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
-				 u64 offset)
-{
-	struct drm_i915_private *dev_priv = engine->i915;
-	struct intel_engine_cs *signaller;
-
-	if (INTEL_GEN(dev_priv) >= 8) {
-		for_each_engine(signaller, dev_priv) {
-			if (engine == signaller)
-				continue;
-
-			if (offset == signaller->semaphore.signal_ggtt[engine->hw_id])
-				return signaller;
-		}
-	} else {
-		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
-
-		for_each_engine(signaller, dev_priv) {
-			if(engine == signaller)
-				continue;
-
-			if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id])
-				return signaller;
-		}
-	}
-
-	DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n",
-			 engine->name, ipehr, offset);
-
-	return ERR_PTR(-ENODEV);
-}
-
-static struct intel_engine_cs *
-semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno)
-{
-	struct drm_i915_private *dev_priv = engine->i915;
-	void __iomem *vaddr;
-	u32 cmd, ipehr, head;
-	u64 offset = 0;
-	int i, backwards;
-
-	/*
-	 * This function does not support execlist mode - any attempt to
-	 * proceed further into this function will result in a kernel panic
-	 * when dereferencing ring->buffer, which is not set up in execlist
-	 * mode.
-	 *
-	 * The correct way of doing it would be to derive the currently
-	 * executing ring buffer from the current context, which is derived
-	 * from the currently running request. Unfortunately, to get the
-	 * current request we would have to grab the struct_mutex before doing
-	 * anything else, which would be ill-advised since some other thread
-	 * might have grabbed it already and managed to hang itself, causing
-	 * the hang checker to deadlock.
-	 *
-	 * Therefore, this function does not support execlist mode in its
-	 * current form. Just return NULL and move on.
-	 */
-	if (engine->buffer == NULL)
-		return NULL;
-
-	ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
-	if (!ipehr_is_semaphore_wait(engine, ipehr))
-		return NULL;
-
-	/*
-	 * HEAD is likely pointing to the dword after the actual command,
-	 * so scan backwards until we find the MBOX. But limit it to just 3
-	 * or 4 dwords depending on the semaphore wait command size.
-	 * Note that we don't care about ACTHD here since that might
-	 * point at at batch, and semaphores are always emitted into the
-	 * ringbuffer itself.
-	 */
-	head = I915_READ_HEAD(engine) & HEAD_ADDR;
-	backwards = (INTEL_GEN(dev_priv) >= 8) ? 5 : 4;
-	vaddr = (void __iomem *)engine->buffer->vaddr;
-
-	for (i = backwards; i; --i) {
-		/*
-		 * Be paranoid and presume the hw has gone off into the wild -
-		 * our ring is smaller than what the hardware (and hence
-		 * HEAD_ADDR) allows. Also handles wrap-around.
-		 */
-		head &= engine->buffer->size - 1;
-
-		/* This here seems to blow up */
-		cmd = ioread32(vaddr + head);
-		if (cmd == ipehr)
-			break;
-
-		head -= 4;
-	}
-
-	if (!i)
-		return NULL;
-
-	*seqno = ioread32(vaddr + head + 4) + 1;
-	if (INTEL_GEN(dev_priv) >= 8) {
-		offset = ioread32(vaddr + head + 12);
-		offset <<= 32;
-		offset |= ioread32(vaddr + head + 8);
-	}
-	return semaphore_wait_to_signaller_ring(engine, ipehr, offset);
-}
-
-static int semaphore_passed(struct intel_engine_cs *engine)
-{
-	struct drm_i915_private *dev_priv = engine->i915;
-	struct intel_engine_cs *signaller;
-	u32 seqno;
-
-	engine->hangcheck.deadlock++;
-
-	signaller = semaphore_waits_for(engine, &seqno);
-	if (signaller == NULL)
-		return -1;
-
-	if (IS_ERR(signaller))
-		return 0;
-
-	/* Prevent pathological recursion due to driver bugs */
-	if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
-		return -1;
-
-	if (i915_seqno_passed(intel_engine_get_seqno(signaller), seqno))
-		return 1;
-
-	/* cursory check for an unkickable deadlock */
-	if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE &&
-	    semaphore_passed(signaller) < 0)
-		return -1;
-
-	return 0;
-}
-
-static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
-{
-	struct intel_engine_cs *engine;
-
-	for_each_engine(engine, dev_priv)
-		engine->hangcheck.deadlock = 0;
-}
-
-static bool subunits_stuck(struct intel_engine_cs *engine)
-{
-	u32 instdone[I915_NUM_INSTDONE_REG];
-	bool stuck;
-	int i;
-
-	if (engine->id != RCS)
-		return true;
-
-	i915_get_extra_instdone(engine->i915, instdone);
-
-	/* There might be unstable subunit states even when
-	 * actual head is not moving. Filter out the unstable ones by
-	 * accumulating the undone -> done transitions and only
-	 * consider those as progress.
-	 */
-	stuck = true;
-	for (i = 0; i < I915_NUM_INSTDONE_REG; i++) {
-		const u32 tmp = instdone[i] | engine->hangcheck.instdone[i];
-
-		if (tmp != engine->hangcheck.instdone[i])
-			stuck = false;
-
-		engine->hangcheck.instdone[i] |= tmp;
-	}
-
-	return stuck;
-}
-
-static enum intel_engine_hangcheck_action
-head_stuck(struct intel_engine_cs *engine, u64 acthd)
-{
-	if (acthd != engine->hangcheck.acthd) {
-
-		/* Clear subunit states on head movement */
-		memset(engine->hangcheck.instdone, 0,
-		       sizeof(engine->hangcheck.instdone));
-
-		return HANGCHECK_ACTIVE;
-	}
-
-	if (!subunits_stuck(engine))
-		return HANGCHECK_ACTIVE;
-
-	return HANGCHECK_HUNG;
-}
-
-static enum intel_engine_hangcheck_action
-engine_stuck(struct intel_engine_cs *engine, u64 acthd)
-{
-	struct drm_i915_private *dev_priv = engine->i915;
-	enum intel_engine_hangcheck_action ha;
-	u32 tmp;
-
-	ha = head_stuck(engine, acthd);
-	if (ha != HANGCHECK_HUNG)
-		return ha;
-
-	if (IS_GEN2(dev_priv))
-		return HANGCHECK_HUNG;
-
-	/* Is the chip hanging on a WAIT_FOR_EVENT?
-	 * If so we can simply poke the RB_WAIT bit
-	 * and break the hang. This should work on
-	 * all but the second generation chipsets.
-	 */
-	tmp = I915_READ_CTL(engine);
-	if (tmp & RING_WAIT) {
-		i915_handle_error(dev_priv, 0,
-				  "Kicking stuck wait on %s",
-				  engine->name);
-		I915_WRITE_CTL(engine, tmp);
-		return HANGCHECK_KICK;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 6 && tmp & RING_WAIT_SEMAPHORE) {
-		switch (semaphore_passed(engine)) {
-		default:
-			return HANGCHECK_HUNG;
-		case 1:
-			i915_handle_error(dev_priv, 0,
-					  "Kicking stuck semaphore on %s",
-					  engine->name);
-			I915_WRITE_CTL(engine, tmp);
-			return HANGCHECK_KICK;
-		case 0:
-			return HANGCHECK_WAIT;
-		}
-	}
-
-	return HANGCHECK_HUNG;
-}
-
-/*
- * This is called when the chip hasn't reported back with completed
- * batchbuffers in a long time. We keep track per ring seqno progress and
- * if there are no progress, hangcheck score for that ring is increased.
- * Further, acthd is inspected to see if the ring is stuck. On stuck case
- * we kick the ring. If we see no progress on three subsequent calls
- * we assume chip is wedged and try to fix it by resetting the chip.
- */
-static void i915_hangcheck_elapsed(struct work_struct *work)
-{
-	struct drm_i915_private *dev_priv =
-		container_of(work, typeof(*dev_priv),
-			     gpu_error.hangcheck_work.work);
-	struct intel_engine_cs *engine;
-	unsigned int hung = 0, stuck = 0;
-	int busy_count = 0;
-#define BUSY 1
-#define KICK 5
-#define HUNG 20
-#define ACTIVE_DECAY 15
-
-	if (!i915.enable_hangcheck)
-		return;
-
-	if (!READ_ONCE(dev_priv->gt.awake))
-		return;
-
-	/* As enabling the GPU requires fairly extensive mmio access,
-	 * periodically arm the mmio checker to see if we are triggering
-	 * any invalid access.
-	 */
-	intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
-
-	for_each_engine(engine, dev_priv) {
-		bool busy = intel_engine_has_waiter(engine);
-		u64 acthd;
-		u32 seqno;
-		u32 submit;
-
-		semaphore_clear_deadlocks(dev_priv);
-
-		/* We don't strictly need an irq-barrier here, as we are not
-		 * serving an interrupt request, be paranoid in case the
-		 * barrier has side-effects (such as preventing a broken
-		 * cacheline snoop) and so be sure that we can see the seqno
-		 * advance. If the seqno should stick, due to a stale
-		 * cacheline, we would erroneously declare the GPU hung.
-		 */
-		if (engine->irq_seqno_barrier)
-			engine->irq_seqno_barrier(engine);
-
-		acthd = intel_engine_get_active_head(engine);
-		seqno = intel_engine_get_seqno(engine);
-		submit = READ_ONCE(engine->last_submitted_seqno);
-
-		if (engine->hangcheck.seqno == seqno) {
-			if (i915_seqno_passed(seqno, submit)) {
-				engine->hangcheck.action = HANGCHECK_IDLE;
-			} else {
-				/* We always increment the hangcheck score
-				 * if the engine is busy and still processing
-				 * the same request, so that no single request
-				 * can run indefinitely (such as a chain of
-				 * batches). The only time we do not increment
-				 * the hangcheck score on this ring, if this
-				 * engine is in a legitimate wait for another
-				 * engine. In that case the waiting engine is a
-				 * victim and we want to be sure we catch the
-				 * right culprit. Then every time we do kick
-				 * the ring, add a small increment to the
-				 * score so that we can catch a batch that is
-				 * being repeatedly kicked and so responsible
-				 * for stalling the machine.
-				 */
-				engine->hangcheck.action =
-					engine_stuck(engine, acthd);
-
-				switch (engine->hangcheck.action) {
-				case HANGCHECK_IDLE:
-				case HANGCHECK_WAIT:
-					break;
-				case HANGCHECK_ACTIVE:
-					engine->hangcheck.score += BUSY;
-					break;
-				case HANGCHECK_KICK:
-					engine->hangcheck.score += KICK;
-					break;
-				case HANGCHECK_HUNG:
-					engine->hangcheck.score += HUNG;
-					break;
-				}
-			}
-
-			if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
-				hung |= intel_engine_flag(engine);
-				if (engine->hangcheck.action != HANGCHECK_HUNG)
-					stuck |= intel_engine_flag(engine);
-			}
-		} else {
-			engine->hangcheck.action = HANGCHECK_ACTIVE;
-
-			/* Gradually reduce the count so that we catch DoS
-			 * attempts across multiple batches.
-			 */
-			if (engine->hangcheck.score > 0)
-				engine->hangcheck.score -= ACTIVE_DECAY;
-			if (engine->hangcheck.score < 0)
-				engine->hangcheck.score = 0;
-
-			/* Clear head and subunit states on seqno movement */
-			acthd = 0;
-
-			memset(engine->hangcheck.instdone, 0,
-			       sizeof(engine->hangcheck.instdone));
-		}
-
-		engine->hangcheck.seqno = seqno;
-		engine->hangcheck.acthd = acthd;
-		busy_count += busy;
-	}
-
-	if (hung) {
-		char msg[80];
-		unsigned int tmp;
-		int len;
-
-		/* If some rings hung but others were still busy, only
-		 * blame the hanging rings in the synopsis.
-		 */
-		if (stuck != hung)
-			hung &= ~stuck;
-		len = scnprintf(msg, sizeof(msg),
-				"%s on ", stuck == hung ? "No progress" : "Hang");
-		for_each_engine_masked(engine, dev_priv, hung, tmp)
-			len += scnprintf(msg + len, sizeof(msg) - len,
-					 "%s, ", engine->name);
-		msg[len-2] = '\0';
-
-		return i915_handle_error(dev_priv, hung, msg);
-	}
-
-	/* Reset timer in case GPU hangs without another request being added */
-	if (busy_count)
-		i915_queue_hangcheck(dev_priv);
-}
-
-static void ibx_irq_reset(struct drm_device *dev)
+static void ibx_irq_reset(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (HAS_PCH_NOP(dev))
+	if (HAS_PCH_NOP(dev_priv))
 		return;
 
 	GEN5_IRQ_RESET(SDE);
 
-	if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev))
+	if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv))
 		I915_WRITE(SERR_INT, 0xffffffff);
 }
 
@@ -3218,7 +2871,7 @@ static void ibx_irq_pre_postinstall(stru
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
-	if (HAS_PCH_NOP(dev))
+	if (HAS_PCH_NOP(dev_priv))
 		return;
 
 	WARN_ON(I915_READ(SDEIER) != 0);
@@ -3226,12 +2879,10 @@ static void ibx_irq_pre_postinstall(stru
 	POSTING_READ(SDEIER);
 }
 
-static void gen5_gt_irq_reset(struct drm_device *dev)
+static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	GEN5_IRQ_RESET(GT);
-	if (INTEL_INFO(dev)->gen >= 6)
+	if (INTEL_GEN(dev_priv) >= 6)
 		GEN5_IRQ_RESET(GEN6_PM);
 }
 
@@ -3293,12 +2944,12 @@ static void ironlake_irq_reset(struct dr
 	I915_WRITE(HWSTAM, 0xffffffff);
 
 	GEN5_IRQ_RESET(DE);
-	if (IS_GEN7(dev))
+	if (IS_GEN7(dev_priv))
 		I915_WRITE(GEN7_ERR_INT, 0xffffffff);
 
-	gen5_gt_irq_reset(dev);
+	gen5_gt_irq_reset(dev_priv);
 
-	ibx_irq_reset(dev);
+	ibx_irq_reset(dev_priv);
 }
 
 static void valleyview_irq_preinstall(struct drm_device *dev)
@@ -3308,7 +2959,7 @@ static void valleyview_irq_preinstall(st
 	I915_WRITE(VLV_MASTER_IER, 0);
 	POSTING_READ(VLV_MASTER_IER);
 
-	gen5_gt_irq_reset(dev);
+	gen5_gt_irq_reset(dev_priv);
 
 	spin_lock_irq(&dev_priv->irq_lock);
 	if (dev_priv->display_irqs_enabled)
@@ -3343,8 +2994,8 @@ static void gen8_irq_reset(struct drm_de
 	GEN5_IRQ_RESET(GEN8_DE_MISC_);
 	GEN5_IRQ_RESET(GEN8_PCU_);
 
-	if (HAS_PCH_SPLIT(dev))
-		ibx_irq_reset(dev);
+	if (HAS_PCH_SPLIT(dev_priv))
+		ibx_irq_reset(dev_priv);
 }
 
 void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv,
@@ -3532,10 +3183,10 @@ static void ibx_irq_postinstall(struct d
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 mask;
 
-	if (HAS_PCH_NOP(dev))
+	if (HAS_PCH_NOP(dev_priv))
 		return;
 
-	if (HAS_PCH_IBX(dev))
+	if (HAS_PCH_IBX(dev_priv))
 		mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON;
 	else
 		mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT;
@@ -3552,14 +3203,14 @@ static void gen5_gt_irq_postinstall(stru
 	pm_irqs = gt_irqs = 0;
 
 	dev_priv->gt_irq_mask = ~0;
-	if (HAS_L3_DPF(dev)) {
+	if (HAS_L3_DPF(dev_priv)) {
 		/* L3 parity interrupt is always unmasked. */
-		dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev);
-		gt_irqs |= GT_PARITY_ERROR(dev);
+		dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev_priv);
+		gt_irqs |= GT_PARITY_ERROR(dev_priv);
 	}
 
 	gt_irqs |= GT_RENDER_USER_INTERRUPT;
-	if (IS_GEN5(dev)) {
+	if (IS_GEN5(dev_priv)) {
 		gt_irqs |= ILK_BSD_USER_INTERRUPT;
 	} else {
 		gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
@@ -3567,16 +3218,18 @@ static void gen5_gt_irq_postinstall(stru
 
 	GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs);
 
-	if (INTEL_INFO(dev)->gen >= 6) {
+	if (INTEL_GEN(dev_priv) >= 6) {
 		/*
 		 * RPS interrupts will get enabled/disabled on demand when RPS
 		 * itself is enabled/disabled.
 		 */
-		if (HAS_VEBOX(dev))
+		if (HAS_VEBOX(dev_priv)) {
 			pm_irqs |= PM_VEBOX_USER_INTERRUPT;
+			dev_priv->pm_ier |= PM_VEBOX_USER_INTERRUPT;
+		}
 
-		dev_priv->pm_irq_mask = 0xffffffff;
-		GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_irq_mask, pm_irqs);
+		dev_priv->pm_imr = 0xffffffff;
+		GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs);
 	}
 }
 
@@ -3585,7 +3238,7 @@ static int ironlake_irq_postinstall(stru
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 display_mask, extra_mask;
 
-	if (INTEL_INFO(dev)->gen >= 7) {
+	if (INTEL_GEN(dev_priv) >= 7) {
 		display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB |
 				DE_PCH_EVENT_IVB | DE_PLANEC_FLIP_DONE_IVB |
 				DE_PLANEB_FLIP_DONE_IVB |
@@ -3616,7 +3269,7 @@ static int ironlake_irq_postinstall(stru
 
 	ibx_irq_postinstall(dev);
 
-	if (IS_IRONLAKE_M(dev)) {
+	if (IS_IRONLAKE_M(dev_priv)) {
 		/* Enable PCU event interrupts
 		 *
 		 * spinlocking not required here for correctness since interrupt
@@ -3696,14 +3349,15 @@ static void gen8_gt_irq_postinstall(stru
 	if (HAS_L3_DPF(dev_priv))
 		gt_interrupts[0] |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
 
-	dev_priv->pm_irq_mask = 0xffffffff;
+	dev_priv->pm_ier = 0x0;
+	dev_priv->pm_imr = ~dev_priv->pm_ier;
 	GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]);
 	GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]);
 	/*
 	 * RPS interrupts will get enabled/disabled on demand when RPS itself
-	 * is enabled/disabled.
+	 * is enabled/disabled. Same wil be the case for GuC interrupts.
 	 */
-	GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, 0);
+	GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_imr, dev_priv->pm_ier);
 	GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]);
 }
 
@@ -3756,13 +3410,13 @@ static int gen8_irq_postinstall(struct d
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		ibx_irq_pre_postinstall(dev);
 
 	gen8_gt_irq_postinstall(dev_priv);
 	gen8_de_irq_postinstall(dev_priv);
 
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		ibx_irq_postinstall(dev);
 
 	I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
@@ -3808,7 +3462,7 @@ static void valleyview_irq_uninstall(str
 	I915_WRITE(VLV_MASTER_IER, 0);
 	POSTING_READ(VLV_MASTER_IER);
 
-	gen5_gt_irq_reset(dev);
+	gen5_gt_irq_reset(dev_priv);
 
 	I915_WRITE(HWSTAM, 0xffffffff);
 
@@ -3971,7 +3625,7 @@ static irqreturn_t i8xx_irq_handler(int
 		new_iir = I915_READ16(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
-			notify_ring(&dev_priv->engine[RCS]);
+			notify_ring(dev_priv->engine[RCS]);
 
 		for_each_pipe(dev_priv, pipe) {
 			int plane = pipe;
@@ -4020,7 +3674,7 @@ static void i915_irq_preinstall(struct d
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	int pipe;
 
-	if (I915_HAS_HOTPLUG(dev)) {
+	if (I915_HAS_HOTPLUG(dev_priv)) {
 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 	}
@@ -4054,7 +3708,7 @@ static int i915_irq_postinstall(struct d
 		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
 		I915_USER_INTERRUPT;
 
-	if (I915_HAS_HOTPLUG(dev)) {
+	if (I915_HAS_HOTPLUG(dev_priv)) {
 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
 		POSTING_READ(PORT_HOTPLUG_EN);
 
@@ -4168,7 +3822,7 @@ static irqreturn_t i915_irq_handler(int
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
-			notify_ring(&dev_priv->engine[RCS]);
+			notify_ring(dev_priv->engine[RCS]);
 
 		for_each_pipe(dev_priv, pipe) {
 			int plane = pipe;
@@ -4222,7 +3876,7 @@ static void i915_irq_uninstall(struct dr
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	int pipe;
 
-	if (I915_HAS_HOTPLUG(dev)) {
+	if (I915_HAS_HOTPLUG(dev_priv)) {
 		i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
 		I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
 	}
@@ -4400,9 +4054,9 @@ static irqreturn_t i965_irq_handler(int
 		new_iir = I915_READ(IIR); /* Flush posted writes */
 
 		if (iir & I915_USER_INTERRUPT)
-			notify_ring(&dev_priv->engine[RCS]);
+			notify_ring(dev_priv->engine[RCS]);
 		if (iir & I915_BSD_USER_INTERRUPT)
-			notify_ring(&dev_priv->engine[VCS]);
+			notify_ring(dev_priv->engine[VCS]);
 
 		for_each_pipe(dev_priv, pipe) {
 			if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
@@ -4487,6 +4141,9 @@ void intel_irq_init(struct drm_i915_priv
 	INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);
 	INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
 
+	if (HAS_GUC_SCHED(dev_priv))
+		dev_priv->pm_guc_events = GEN9_GUC_TO_HOST_INT_EVENT;
+
 	/* Let's track the enabled rps events */
 	if (IS_VALLEYVIEW(dev_priv))
 		/* WaGsvRC0ResidencyMethod:vlv */
@@ -4508,9 +4165,6 @@ void intel_irq_init(struct drm_i915_priv
 	if (INTEL_INFO(dev_priv)->gen >= 8)
 		dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_GUC;
 
-	INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work,
-			  i915_hangcheck_elapsed);
-
 	if (IS_GEN2(dev_priv)) {
 		/* Gen2 doesn't have a hardware frame counter */
 		dev->max_vblank_count = 0;
@@ -4539,16 +4193,16 @@ void intel_irq_init(struct drm_i915_priv
 		dev->driver->irq_preinstall = cherryview_irq_preinstall;
 		dev->driver->irq_postinstall = cherryview_irq_postinstall;
 		dev->driver->irq_uninstall = cherryview_irq_uninstall;
-		dev->driver->enable_vblank = valleyview_enable_vblank;
-		dev->driver->disable_vblank = valleyview_disable_vblank;
+		dev->driver->enable_vblank = i965_enable_vblank;
+		dev->driver->disable_vblank = i965_disable_vblank;
 		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
 	} else if (IS_VALLEYVIEW(dev_priv)) {
 		dev->driver->irq_handler = valleyview_irq_handler;
 		dev->driver->irq_preinstall = valleyview_irq_preinstall;
 		dev->driver->irq_postinstall = valleyview_irq_postinstall;
 		dev->driver->irq_uninstall = valleyview_irq_uninstall;
-		dev->driver->enable_vblank = valleyview_enable_vblank;
-		dev->driver->disable_vblank = valleyview_disable_vblank;
+		dev->driver->enable_vblank = i965_enable_vblank;
+		dev->driver->disable_vblank = i965_disable_vblank;
 		dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
 	} else if (INTEL_INFO(dev_priv)->gen >= 8) {
 		dev->driver->irq_handler = gen8_irq_handler;
@@ -4557,13 +4211,13 @@ void intel_irq_init(struct drm_i915_priv
 		dev->driver->irq_uninstall = gen8_irq_uninstall;
 		dev->driver->enable_vblank = gen8_enable_vblank;
 		dev->driver->disable_vblank = gen8_disable_vblank;
-		if (IS_BROXTON(dev))
+		if (IS_BROXTON(dev_priv))
 			dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup;
-		else if (HAS_PCH_SPT(dev) || HAS_PCH_KBP(dev))
+		else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_KBP(dev_priv))
 			dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup;
 		else
 			dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup;
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		dev->driver->irq_handler = ironlake_irq_handler;
 		dev->driver->irq_preinstall = ironlake_irq_reset;
 		dev->driver->irq_postinstall = ironlake_irq_postinstall;
@@ -4577,21 +4231,25 @@ void intel_irq_init(struct drm_i915_priv
 			dev->driver->irq_postinstall = i8xx_irq_postinstall;
 			dev->driver->irq_handler = i8xx_irq_handler;
 			dev->driver->irq_uninstall = i8xx_irq_uninstall;
+			dev->driver->enable_vblank = i8xx_enable_vblank;
+			dev->driver->disable_vblank = i8xx_disable_vblank;
 		} else if (IS_GEN3(dev_priv)) {
 			dev->driver->irq_preinstall = i915_irq_preinstall;
 			dev->driver->irq_postinstall = i915_irq_postinstall;
 			dev->driver->irq_uninstall = i915_irq_uninstall;
 			dev->driver->irq_handler = i915_irq_handler;
+			dev->driver->enable_vblank = i8xx_enable_vblank;
+			dev->driver->disable_vblank = i8xx_disable_vblank;
 		} else {
 			dev->driver->irq_preinstall = i965_irq_preinstall;
 			dev->driver->irq_postinstall = i965_irq_postinstall;
 			dev->driver->irq_uninstall = i965_irq_uninstall;
 			dev->driver->irq_handler = i965_irq_handler;
+			dev->driver->enable_vblank = i965_enable_vblank;
+			dev->driver->disable_vblank = i965_disable_vblank;
 		}
 		if (I915_HAS_HOTPLUG(dev_priv))
 			dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;
-		dev->driver->enable_vblank = i915_enable_vblank;
-		dev->driver->disable_vblank = i915_disable_vblank;
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_params.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_params.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_params.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_params.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@ struct i915_params i915 __read_mostly =
 	.enable_hangcheck = true,
 	.enable_ppgtt = -1,
 	.enable_psr = -1,
-	.preliminary_hw_support = IS_ENABLED(CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT),
+	.alpha_support = IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT),
 	.disable_power_well = -1,
 	.enable_ips = 1,
 	.fastboot = 0,
@@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly =
 	.load_detect_test = 0,
 	.force_reset_modeset_test = 0,
 	.reset = true,
+	.error_capture = true,
 	.invert_brightness = 0,
 	.disable_display = 0,
 	.enable_cmd_parser = 1,
@@ -115,6 +116,14 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type,
 module_param_named_unsafe(reset, i915.reset, bool, 0600);
 MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)");
 
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+module_param_named(error_capture, i915.error_capture, bool, 0600);
+MODULE_PARM_DESC(error_capture,
+	"Record the GPU state following a hang. "
+	"This information in /sys/class/drm/card<N>/error is vital for "
+	"triaging and debugging hangs.");
+#endif
+
 module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644);
 MODULE_PARM_DESC(enable_hangcheck,
 	"Periodically check GPU activity for detecting hangs. "
@@ -136,9 +145,10 @@ MODULE_PARM_DESC(enable_psr, "Enable PSR
 		 "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) "
 		 "Default: -1 (use per-chip default)");
 
-module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, int, 0400);
-MODULE_PARM_DESC(preliminary_hw_support,
-	"Enable preliminary hardware support.");
+module_param_named_unsafe(alpha_support, i915.alpha_support, int, 0400);
+MODULE_PARM_DESC(alpha_support,
+	"Enable alpha quality driver support for latest hardware. "
+	"See also CONFIG_DRM_I915_ALPHA_SUPPORT.");
 
 module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0400);
 MODULE_PARM_DESC(disable_power_well,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_params.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_params.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_params.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_params.h	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@ struct i915_params {
 	int enable_ppgtt;
 	int enable_execlists;
 	int enable_psr;
-	unsigned int preliminary_hw_support;
+	unsigned int alpha_support;
 	int disable_power_well;
 	int enable_ips;
 	int invert_brightness;
@@ -59,6 +59,7 @@ struct i915_params {
 	bool load_detect_test;
 	bool force_reset_modeset_test;
 	bool reset;
+	bool error_capture;
 	bool disable_display;
 	bool verbose_state_checks;
 	bool nuclear_pageflip;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_pci.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_pci.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -288,7 +288,8 @@ static const struct intel_device_info in
 #define BDW_FEATURES \
 	HSW_FEATURES, \
 	BDW_COLORS, \
-	.has_logical_ring_contexts = 1
+	.has_logical_ring_contexts = 1, \
+	.has_64bit_reloc = 1
 
 static const struct intel_device_info intel_broadwell_info = {
 	BDW_FEATURES,
@@ -308,6 +309,7 @@ static const struct intel_device_info in
 	.has_hotplug = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 	.is_cherryview = 1,
+	.has_64bit_reloc = 1,
 	.has_psr = 1,
 	.has_runtime_pm = 1,
 	.has_resource_streamer = 1,
@@ -347,6 +349,7 @@ static const struct intel_device_info in
 	.has_hotplug = 1,
 	.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
 	.num_pipes = 3,
+	.has_64bit_reloc = 1,
 	.has_ddi = 1,
 	.has_fpga_dbg = 1,
 	.has_fbc = 1,
@@ -360,6 +363,7 @@ static const struct intel_device_info in
 	.has_hw_contexts = 1,
 	.has_logical_ring_contexts = 1,
 	.has_guc = 1,
+	.has_decoupled_mmio = 1,
 	.ddb_size = 512,
 	GEN_DEFAULT_PIPEOFFSETS,
 	IVB_CURSOR_OFFSETS,
@@ -436,9 +440,10 @@ static int i915_pci_probe(struct pci_dev
 	struct intel_device_info *intel_info =
 		(struct intel_device_info *) ent->driver_data;
 
-	if (IS_PRELIMINARY_HW(intel_info) && !i915.preliminary_hw_support) {
-		DRM_INFO("This hardware requires preliminary hardware support.\n"
-			 "See CONFIG_DRM_I915_PRELIMINARY_HW_SUPPORT, and/or modparam preliminary_hw_support\n");
+	if (IS_ALPHA_SUPPORT(intel_info) && !i915.alpha_support) {
+		DRM_INFO("The driver support for your hardware in this kernel version is alpha quality\n"
+			 "See CONFIG_DRM_I915_ALPHA_SUPPORT or i915.alpha_support module parameter\n"
+			 "to enable support in this kernel version, or check for kernel updates.\n");
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -86,8 +86,7 @@ static inline bool i915_mmio_reg_valid(i
 #define DEVEN 0x54
 #define   DEVEN_MCHBAR_EN (1 << 28)
 
-#define BSM 0x5c
-#define   BSM_MASK (0xFFFF << 20)
+/* BSM in include/drm/i915_drm.h */
 
 #define HPLLCC	0xc0 /* 85x only */
 #define   GC_CLOCK_CONTROL_MASK		(0x7 << 0)
@@ -831,96 +830,7 @@ enum skl_disp_power_wells {
 #define  CCK_FREQUENCY_STATUS_SHIFT		8
 #define  CCK_FREQUENCY_VALUES			(0x1f << 0)
 
-/**
- * DOC: DPIO
- *
- * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI
- * ports. DPIO is the name given to such a display PHY. These PHYs
- * don't follow the standard programming model using direct MMIO
- * registers, and instead their registers must be accessed trough IOSF
- * sideband. VLV has one such PHY for driving ports B and C, and CHV
- * adds another PHY for driving port D. Each PHY responds to specific
- * IOSF-SB port.
- *
- * Each display PHY is made up of one or two channels. Each channel
- * houses a common lane part which contains the PLL and other common
- * logic. CH0 common lane also contains the IOSF-SB logic for the
- * Common Register Interface (CRI) ie. the DPIO registers. CRI clock
- * must be running when any DPIO registers are accessed.
- *
- * In addition to having their own registers, the PHYs are also
- * controlled through some dedicated signals from the display
- * controller. These include PLL reference clock enable, PLL enable,
- * and CRI clock selection, for example.
- *
- * Eeach channel also has two splines (also called data lanes), and
- * each spline is made up of one Physical Access Coding Sub-Layer
- * (PCS) block and two TX lanes. So each channel has two PCS blocks
- * and four TX lanes. The TX lanes are used as DP lanes or TMDS
- * data/clock pairs depending on the output type.
- *
- * Additionally the PHY also contains an AUX lane with AUX blocks
- * for each channel. This is used for DP AUX communication, but
- * this fact isn't really relevant for the driver since AUX is
- * controlled from the display controller side. No DPIO registers
- * need to be accessed during AUX communication,
- *
- * Generally on VLV/CHV the common lane corresponds to the pipe and
- * the spline (PCS/TX) corresponds to the port.
- *
- * For dual channel PHY (VLV/CHV):
- *
- *  pipe A == CMN/PLL/REF CH0
- *
- *  pipe B == CMN/PLL/REF CH1
- *
- *  port B == PCS/TX CH0
- *
- *  port C == PCS/TX CH1
- *
- * This is especially important when we cross the streams
- * ie. drive port B with pipe B, or port C with pipe A.
- *
- * For single channel PHY (CHV):
- *
- *  pipe C == CMN/PLL/REF CH0
- *
- *  port D == PCS/TX CH0
- *
- * On BXT the entire PHY channel corresponds to the port. That means
- * the PLL is also now associated with the port rather than the pipe,
- * and so the clock needs to be routed to the appropriate transcoder.
- * Port A PLL is directly connected to transcoder EDP and port B/C
- * PLLs can be routed to any transcoder A/B/C.
- *
- * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is
- * digital port D (CHV) or port A (BXT). ::
- *
- *
- *     Dual channel PHY (VLV/CHV/BXT)
- *     ---------------------------------
- *     |      CH0      |      CH1      |
- *     |  CMN/PLL/REF  |  CMN/PLL/REF  |
- *     |---------------|---------------| Display PHY
- *     | PCS01 | PCS23 | PCS01 | PCS23 |
- *     |-------|-------|-------|-------|
- *     |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3|
- *     ---------------------------------
- *     |     DDI0      |     DDI1      | DP/HDMI ports
- *     ---------------------------------
- *
- *     Single channel PHY (CHV/BXT)
- *     -----------------
- *     |      CH0      |
- *     |  CMN/PLL/REF  |
- *     |---------------| Display PHY
- *     | PCS01 | PCS23 |
- *     |-------|-------|
- *     |TX0|TX1|TX2|TX3|
- *     -----------------
- *     |     DDI2      | DP/HDMI port
- *     -----------------
- */
+/* DPIO registers */
 #define DPIO_DEVFN			0
 
 #define DPIO_CTL			_MMIO(VLV_DISPLAY_BASE + 0x2110)
@@ -1276,7 +1186,19 @@ enum skl_disp_power_wells {
 #define   DPIO_UPAR_SHIFT		30
 
 /* BXT PHY registers */
-#define _BXT_PHY(phy, a, b)		_MMIO_PIPE((phy), (a), (b))
+#define _BXT_PHY0_BASE			0x6C000
+#define _BXT_PHY1_BASE			0x162000
+#define BXT_PHY_BASE(phy)		_PIPE((phy), _BXT_PHY0_BASE, \
+						     _BXT_PHY1_BASE)
+
+#define _BXT_PHY(phy, reg)						\
+	_MMIO(BXT_PHY_BASE(phy) - _BXT_PHY0_BASE + (reg))
+
+#define _BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1)		\
+	(BXT_PHY_BASE(phy) + _PIPE((ch), (reg_ch0) - _BXT_PHY0_BASE,	\
+					 (reg_ch1) - _BXT_PHY0_BASE))
+#define _MMIO_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1)		\
+	_MMIO(_BXT_PHY_CH(phy, ch, reg_ch0, reg_ch1))
 
 #define BXT_P_CR_GT_DISP_PWRON		_MMIO(0x138090)
 #define   GT_DISPLAY_POWER_ON(phy)	(1 << (phy))
@@ -1293,8 +1215,8 @@ enum skl_disp_power_wells {
 #define _PHY_CTL_FAMILY_EDP		0x64C80
 #define _PHY_CTL_FAMILY_DDI		0x64C90
 #define   COMMON_RESET_DIS		(1 << 31)
-#define BXT_PHY_CTL_FAMILY(phy)		_BXT_PHY((phy), _PHY_CTL_FAMILY_DDI, \
-							_PHY_CTL_FAMILY_EDP)
+#define BXT_PHY_CTL_FAMILY(phy)		_MMIO_PIPE((phy), _PHY_CTL_FAMILY_DDI, \
+							  _PHY_CTL_FAMILY_EDP)
 
 /* BXT PHY PLL registers */
 #define _PORT_PLL_A			0x46074
@@ -1314,18 +1236,18 @@ enum skl_disp_power_wells {
 #define   PORT_PLL_P2_SHIFT		8
 #define   PORT_PLL_P2_MASK		(0x1f << PORT_PLL_P2_SHIFT)
 #define   PORT_PLL_P2(x)		((x)  << PORT_PLL_P2_SHIFT)
-#define BXT_PORT_PLL_EBB_0(port)	_MMIO_PORT3(port, _PORT_PLL_EBB_0_A, \
-						_PORT_PLL_EBB_0_B,	\
-						_PORT_PLL_EBB_0_C)
+#define BXT_PORT_PLL_EBB_0(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_PLL_EBB_0_B, \
+							 _PORT_PLL_EBB_0_C)
 
 #define _PORT_PLL_EBB_4_A		0x162038
 #define _PORT_PLL_EBB_4_B		0x6C038
 #define _PORT_PLL_EBB_4_C		0x6C344
 #define   PORT_PLL_10BIT_CLK_ENABLE	(1 << 13)
 #define   PORT_PLL_RECALIBRATE		(1 << 14)
-#define BXT_PORT_PLL_EBB_4(port)	_MMIO_PORT3(port, _PORT_PLL_EBB_4_A, \
-						_PORT_PLL_EBB_4_B,	\
-						_PORT_PLL_EBB_4_C)
+#define BXT_PORT_PLL_EBB_4(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_PLL_EBB_4_B, \
+							 _PORT_PLL_EBB_4_C)
 
 #define _PORT_PLL_0_A			0x162100
 #define _PORT_PLL_0_B			0x6C100
@@ -1356,57 +1278,56 @@ enum skl_disp_power_wells {
 #define  PORT_PLL_DCO_AMP_DEFAULT	15
 #define  PORT_PLL_DCO_AMP_MASK		0x3c00
 #define  PORT_PLL_DCO_AMP(x)		((x)<<10)
-#define _PORT_PLL_BASE(port)		_PORT3(port, _PORT_PLL_0_A,	\
-						_PORT_PLL_0_B,		\
-						_PORT_PLL_0_C)
-#define BXT_PORT_PLL(port, idx)		_MMIO(_PORT_PLL_BASE(port) + (idx) * 4)
+#define _PORT_PLL_BASE(phy, ch)		_BXT_PHY_CH(phy, ch, \
+						    _PORT_PLL_0_B, \
+						    _PORT_PLL_0_C)
+#define BXT_PORT_PLL(phy, ch, idx)	_MMIO(_PORT_PLL_BASE(phy, ch) + \
+					      (idx) * 4)
 
 /* BXT PHY common lane registers */
 #define _PORT_CL1CM_DW0_A		0x162000
 #define _PORT_CL1CM_DW0_BC		0x6C000
 #define   PHY_POWER_GOOD		(1 << 16)
 #define   PHY_RESERVED			(1 << 7)
-#define BXT_PORT_CL1CM_DW0(phy)		_BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \
-							_PORT_CL1CM_DW0_A)
+#define BXT_PORT_CL1CM_DW0(phy)		_BXT_PHY((phy), _PORT_CL1CM_DW0_BC)
 
 #define _PORT_CL1CM_DW9_A		0x162024
 #define _PORT_CL1CM_DW9_BC		0x6C024
 #define   IREF0RC_OFFSET_SHIFT		8
 #define   IREF0RC_OFFSET_MASK		(0xFF << IREF0RC_OFFSET_SHIFT)
-#define BXT_PORT_CL1CM_DW9(phy)		_BXT_PHY((phy), _PORT_CL1CM_DW9_BC, \
-							_PORT_CL1CM_DW9_A)
+#define BXT_PORT_CL1CM_DW9(phy)		_BXT_PHY((phy), _PORT_CL1CM_DW9_BC)
 
 #define _PORT_CL1CM_DW10_A		0x162028
 #define _PORT_CL1CM_DW10_BC		0x6C028
 #define   IREF1RC_OFFSET_SHIFT		8
 #define   IREF1RC_OFFSET_MASK		(0xFF << IREF1RC_OFFSET_SHIFT)
-#define BXT_PORT_CL1CM_DW10(phy)	_BXT_PHY((phy), _PORT_CL1CM_DW10_BC, \
-							_PORT_CL1CM_DW10_A)
+#define BXT_PORT_CL1CM_DW10(phy)	_BXT_PHY((phy), _PORT_CL1CM_DW10_BC)
 
 #define _PORT_CL1CM_DW28_A		0x162070
 #define _PORT_CL1CM_DW28_BC		0x6C070
 #define   OCL1_POWER_DOWN_EN		(1 << 23)
 #define   DW28_OLDO_DYN_PWR_DOWN_EN	(1 << 22)
 #define   SUS_CLK_CONFIG		0x3
-#define BXT_PORT_CL1CM_DW28(phy)	_BXT_PHY((phy), _PORT_CL1CM_DW28_BC, \
-							_PORT_CL1CM_DW28_A)
+#define BXT_PORT_CL1CM_DW28(phy)	_BXT_PHY((phy), _PORT_CL1CM_DW28_BC)
 
 #define _PORT_CL1CM_DW30_A		0x162078
 #define _PORT_CL1CM_DW30_BC		0x6C078
 #define   OCL2_LDOFUSE_PWR_DIS		(1 << 6)
-#define BXT_PORT_CL1CM_DW30(phy)	_BXT_PHY((phy), _PORT_CL1CM_DW30_BC, \
-							_PORT_CL1CM_DW30_A)
+#define BXT_PORT_CL1CM_DW30(phy)	_BXT_PHY((phy), _PORT_CL1CM_DW30_BC)
 
-/* Defined for PHY0 only */
-#define BXT_PORT_CL2CM_DW6_BC		_MMIO(0x6C358)
+/* The spec defines this only for BXT PHY0, but lets assume that this
+ * would exist for PHY1 too if it had a second channel.
+ */
+#define _PORT_CL2CM_DW6_A		0x162358
+#define _PORT_CL2CM_DW6_BC		0x6C358
+#define BXT_PORT_CL2CM_DW6(phy)		_BXT_PHY((phy), _PORT_CL2CM_DW6_BC)
 #define   DW6_OLDO_DYN_PWR_DOWN_EN	(1 << 28)
 
 /* BXT PHY Ref registers */
 #define _PORT_REF_DW3_A			0x16218C
 #define _PORT_REF_DW3_BC		0x6C18C
 #define   GRC_DONE			(1 << 22)
-#define BXT_PORT_REF_DW3(phy)		_BXT_PHY((phy), _PORT_REF_DW3_BC, \
-							_PORT_REF_DW3_A)
+#define BXT_PORT_REF_DW3(phy)		_BXT_PHY((phy), _PORT_REF_DW3_BC)
 
 #define _PORT_REF_DW6_A			0x162198
 #define _PORT_REF_DW6_BC		0x6C198
@@ -1417,15 +1338,13 @@ enum skl_disp_power_wells {
 #define   GRC_CODE_SLOW_SHIFT		8
 #define   GRC_CODE_SLOW_MASK		(0xFF << GRC_CODE_SLOW_SHIFT)
 #define   GRC_CODE_NOM_MASK		0xFF
-#define BXT_PORT_REF_DW6(phy)		_BXT_PHY((phy), _PORT_REF_DW6_BC,	\
-						      _PORT_REF_DW6_A)
+#define BXT_PORT_REF_DW6(phy)		_BXT_PHY((phy), _PORT_REF_DW6_BC)
 
 #define _PORT_REF_DW8_A			0x1621A0
 #define _PORT_REF_DW8_BC		0x6C1A0
 #define   GRC_DIS			(1 << 15)
 #define   GRC_RDY_OVRD			(1 << 1)
-#define BXT_PORT_REF_DW8(phy)		_BXT_PHY((phy), _PORT_REF_DW8_BC,	\
-						      _PORT_REF_DW8_A)
+#define BXT_PORT_REF_DW8(phy)		_BXT_PHY((phy), _PORT_REF_DW8_BC)
 
 /* BXT PHY PCS registers */
 #define _PORT_PCS_DW10_LN01_A		0x162428
@@ -1434,12 +1353,13 @@ enum skl_disp_power_wells {
 #define _PORT_PCS_DW10_GRP_A		0x162C28
 #define _PORT_PCS_DW10_GRP_B		0x6CC28
 #define _PORT_PCS_DW10_GRP_C		0x6CE28
-#define BXT_PORT_PCS_DW10_LN01(port)	_MMIO_PORT3(port, _PORT_PCS_DW10_LN01_A, \
-						     _PORT_PCS_DW10_LN01_B, \
-						     _PORT_PCS_DW10_LN01_C)
-#define BXT_PORT_PCS_DW10_GRP(port)	_MMIO_PORT3(port, _PORT_PCS_DW10_GRP_A,  \
-						     _PORT_PCS_DW10_GRP_B,  \
-						     _PORT_PCS_DW10_GRP_C)
+#define BXT_PORT_PCS_DW10_LN01(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_PCS_DW10_LN01_B, \
+							 _PORT_PCS_DW10_LN01_C)
+#define BXT_PORT_PCS_DW10_GRP(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_PCS_DW10_GRP_B, \
+							 _PORT_PCS_DW10_GRP_C)
+
 #define   TX2_SWING_CALC_INIT		(1 << 31)
 #define   TX1_SWING_CALC_INIT		(1 << 30)
 
@@ -1454,15 +1374,15 @@ enum skl_disp_power_wells {
 #define _PORT_PCS_DW12_GRP_C		0x6CE30
 #define   LANESTAGGER_STRAP_OVRD	(1 << 6)
 #define   LANE_STAGGER_MASK		0x1F
-#define BXT_PORT_PCS_DW12_LN01(port)	_MMIO_PORT3(port, _PORT_PCS_DW12_LN01_A, \
-						     _PORT_PCS_DW12_LN01_B, \
-						     _PORT_PCS_DW12_LN01_C)
-#define BXT_PORT_PCS_DW12_LN23(port)	_MMIO_PORT3(port, _PORT_PCS_DW12_LN23_A, \
-						     _PORT_PCS_DW12_LN23_B, \
-						     _PORT_PCS_DW12_LN23_C)
-#define BXT_PORT_PCS_DW12_GRP(port)	_MMIO_PORT3(port, _PORT_PCS_DW12_GRP_A, \
-						     _PORT_PCS_DW12_GRP_B, \
-						     _PORT_PCS_DW12_GRP_C)
+#define BXT_PORT_PCS_DW12_LN01(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_PCS_DW12_LN01_B, \
+							 _PORT_PCS_DW12_LN01_C)
+#define BXT_PORT_PCS_DW12_LN23(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_PCS_DW12_LN23_B, \
+							 _PORT_PCS_DW12_LN23_C)
+#define BXT_PORT_PCS_DW12_GRP(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_PCS_DW12_GRP_B, \
+							 _PORT_PCS_DW12_GRP_C)
 
 /* BXT PHY TX registers */
 #define _BXT_LANE_OFFSET(lane)           (((lane) >> 1) * 0x200 +	\
@@ -1474,12 +1394,12 @@ enum skl_disp_power_wells {
 #define _PORT_TX_DW2_GRP_A		0x162D08
 #define _PORT_TX_DW2_GRP_B		0x6CD08
 #define _PORT_TX_DW2_GRP_C		0x6CF08
-#define BXT_PORT_TX_DW2_GRP(port)	_MMIO_PORT3(port, _PORT_TX_DW2_GRP_A,  \
-						     _PORT_TX_DW2_GRP_B,  \
-						     _PORT_TX_DW2_GRP_C)
-#define BXT_PORT_TX_DW2_LN0(port)	_MMIO_PORT3(port, _PORT_TX_DW2_LN0_A,  \
-						     _PORT_TX_DW2_LN0_B,  \
-						     _PORT_TX_DW2_LN0_C)
+#define BXT_PORT_TX_DW2_LN0(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_TX_DW2_LN0_B, \
+							 _PORT_TX_DW2_LN0_C)
+#define BXT_PORT_TX_DW2_GRP(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_TX_DW2_GRP_B, \
+							 _PORT_TX_DW2_GRP_C)
 #define   MARGIN_000_SHIFT		16
 #define   MARGIN_000			(0xFF << MARGIN_000_SHIFT)
 #define   UNIQ_TRANS_SCALE_SHIFT	8
@@ -1491,12 +1411,12 @@ enum skl_disp_power_wells {
 #define _PORT_TX_DW3_GRP_A		0x162D0C
 #define _PORT_TX_DW3_GRP_B		0x6CD0C
 #define _PORT_TX_DW3_GRP_C		0x6CF0C
-#define BXT_PORT_TX_DW3_GRP(port)	_MMIO_PORT3(port, _PORT_TX_DW3_GRP_A,  \
-						     _PORT_TX_DW3_GRP_B,  \
-						     _PORT_TX_DW3_GRP_C)
-#define BXT_PORT_TX_DW3_LN0(port)	_MMIO_PORT3(port, _PORT_TX_DW3_LN0_A,  \
-						     _PORT_TX_DW3_LN0_B,  \
-						     _PORT_TX_DW3_LN0_C)
+#define BXT_PORT_TX_DW3_LN0(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_TX_DW3_LN0_B, \
+							 _PORT_TX_DW3_LN0_C)
+#define BXT_PORT_TX_DW3_GRP(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_TX_DW3_GRP_B, \
+							 _PORT_TX_DW3_GRP_C)
 #define   SCALE_DCOMP_METHOD		(1 << 26)
 #define   UNIQUE_TRANGE_EN_METHOD	(1 << 27)
 
@@ -1506,12 +1426,12 @@ enum skl_disp_power_wells {
 #define _PORT_TX_DW4_GRP_A		0x162D10
 #define _PORT_TX_DW4_GRP_B		0x6CD10
 #define _PORT_TX_DW4_GRP_C		0x6CF10
-#define BXT_PORT_TX_DW4_LN0(port)	_MMIO_PORT3(port, _PORT_TX_DW4_LN0_A,  \
-						     _PORT_TX_DW4_LN0_B,  \
-						     _PORT_TX_DW4_LN0_C)
-#define BXT_PORT_TX_DW4_GRP(port)	_MMIO_PORT3(port, _PORT_TX_DW4_GRP_A,  \
-						     _PORT_TX_DW4_GRP_B,  \
-						     _PORT_TX_DW4_GRP_C)
+#define BXT_PORT_TX_DW4_LN0(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_TX_DW4_LN0_B, \
+							 _PORT_TX_DW4_LN0_C)
+#define BXT_PORT_TX_DW4_GRP(phy, ch)	_MMIO_BXT_PHY_CH(phy, ch, \
+							 _PORT_TX_DW4_GRP_B, \
+							 _PORT_TX_DW4_GRP_C)
 #define   DEEMPH_SHIFT			24
 #define   DE_EMPHASIS			(0xFF << DEEMPH_SHIFT)
 
@@ -1520,10 +1440,10 @@ enum skl_disp_power_wells {
 #define _PORT_TX_DW14_LN0_C		0x6C938
 #define   LATENCY_OPTIM_SHIFT		30
 #define   LATENCY_OPTIM			(1 << LATENCY_OPTIM_SHIFT)
-#define BXT_PORT_TX_DW14_LN(port, lane)	_MMIO(_PORT3((port), _PORT_TX_DW14_LN0_A,   \
-							_PORT_TX_DW14_LN0_B,   \
-							_PORT_TX_DW14_LN0_C) + \
-					 _BXT_LANE_OFFSET(lane))
+#define BXT_PORT_TX_DW14_LN(phy, ch, lane)				\
+	_MMIO(_BXT_PHY_CH(phy, ch, _PORT_TX_DW14_LN0_B,			\
+				   _PORT_TX_DW14_LN0_C) +		\
+	      _BXT_LANE_OFFSET(lane))
 
 /* UAIMI scratch pad register 1 */
 #define UAIMI_SPR1			_MMIO(0x4F074)
@@ -1605,6 +1525,7 @@ enum skl_disp_power_wells {
 #define RING_HEAD(base)		_MMIO((base)+0x34)
 #define RING_START(base)	_MMIO((base)+0x38)
 #define RING_CTL(base)		_MMIO((base)+0x3c)
+#define   RING_CTL_SIZE(size)	((size) - PAGE_SIZE) /* in bytes -> pages */
 #define RING_SYNC_0(base)	_MMIO((base)+0x40)
 #define RING_SYNC_1(base)	_MMIO((base)+0x44)
 #define RING_SYNC_2(base)	_MMIO((base)+0x48)
@@ -1708,7 +1629,11 @@ enum skl_disp_power_wells {
 #define GEN7_SC_INSTDONE	_MMIO(0x7100)
 #define GEN7_SAMPLER_INSTDONE	_MMIO(0xe160)
 #define GEN7_ROW_INSTDONE	_MMIO(0xe164)
-#define I915_NUM_INSTDONE_REG	4
+#define GEN8_MCR_SELECTOR		_MMIO(0xfdc)
+#define   GEN8_MCR_SLICE(slice)		(((slice) & 3) << 26)
+#define   GEN8_MCR_SLICE_MASK		GEN8_MCR_SLICE(3)
+#define   GEN8_MCR_SUBSLICE(subslice)	(((subslice) & 3) << 24)
+#define   GEN8_MCR_SUBSLICE_MASK	GEN8_MCR_SUBSLICE(3)
 #define RING_IPEIR(base)	_MMIO((base)+0x64)
 #define RING_IPEHR(base)	_MMIO((base)+0x68)
 /*
@@ -2089,9 +2014,9 @@ enum skl_disp_power_wells {
 #define PM_VEBOX_CS_ERROR_INTERRUPT		(1 << 12) /* hsw+ */
 #define PM_VEBOX_USER_INTERRUPT			(1 << 10) /* hsw+ */
 
-#define GT_PARITY_ERROR(dev) \
+#define GT_PARITY_ERROR(dev_priv) \
 	(GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \
-	 (IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0))
+	 (IS_HASWELL(dev_priv) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0))
 
 /* These are all the "old" interrupts */
 #define ILK_BSD_USER_INTERRUPT				(1<<5)
@@ -2184,8 +2109,9 @@ enum skl_disp_power_wells {
 #define FBC_FENCE_OFF		_MMIO(0x3218) /* BSpec typo has 321Bh */
 #define FBC_TAG(i)		_MMIO(0x3300 + (i) * 4)
 
-#define FBC_STATUS2		_MMIO(0x43214)
-#define  FBC_COMPRESSION_MASK	0x7ff
+#define FBC_STATUS2			_MMIO(0x43214)
+#define  IVB_FBC_COMPRESSION_MASK	0x7ff
+#define  BDW_FBC_COMPRESSION_MASK	0xfff
 
 #define FBC_LL_SIZE		(1536)
 
@@ -6011,6 +5937,7 @@ enum {
 #define  GEN8_DE_PIPE_A_IRQ		(1<<16)
 #define  GEN8_DE_PIPE_IRQ(pipe)		(1<<(16+(pipe)))
 #define  GEN8_GT_VECS_IRQ		(1<<6)
+#define  GEN8_GT_GUC_IRQ		(1<<5)
 #define  GEN8_GT_PM_IRQ			(1<<4)
 #define  GEN8_GT_VCS2_IRQ		(1<<3)
 #define  GEN8_GT_VCS1_IRQ		(1<<2)
@@ -6022,6 +5949,16 @@ enum {
 #define GEN8_GT_IIR(which) _MMIO(0x44308 + (0x10 * (which)))
 #define GEN8_GT_IER(which) _MMIO(0x4430c + (0x10 * (which)))
 
+#define GEN9_GUC_TO_HOST_INT_EVENT	(1<<31)
+#define GEN9_GUC_EXEC_ERROR_EVENT	(1<<30)
+#define GEN9_GUC_DISPLAY_EVENT		(1<<29)
+#define GEN9_GUC_SEMA_SIGNAL_EVENT	(1<<28)
+#define GEN9_GUC_IOMMU_MSG_EVENT	(1<<27)
+#define GEN9_GUC_DB_RING_EVENT		(1<<26)
+#define GEN9_GUC_DMA_DONE_EVENT		(1<<25)
+#define GEN9_GUC_FATAL_ERROR_EVENT	(1<<24)
+#define GEN9_GUC_NOTIFICATION_EVENT	(1<<23)
+
 #define GEN8_RCS_IRQ_SHIFT 0
 #define GEN8_BCS_IRQ_SHIFT 16
 #define GEN8_VCS1_IRQ_SHIFT 0
@@ -7327,6 +7264,10 @@ enum {
 #define   AUD_CONFIG_UPPER_N_MASK		(0xff << 20)
 #define   AUD_CONFIG_LOWER_N_SHIFT		4
 #define   AUD_CONFIG_LOWER_N_MASK		(0xfff << 4)
+#define   AUD_CONFIG_N_MASK			(AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK)
+#define   AUD_CONFIG_N(n) \
+	(((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) |	\
+	 (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT))
 #define   AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT	16
 #define   AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK	(0xf << 16)
 #define   AUD_CONFIG_PIXEL_CLOCK_HDMI_25175	(0 << 16)
@@ -7350,6 +7291,13 @@ enum {
 #define _HSW_AUD_MISC_CTRL_B		0x65110
 #define HSW_AUD_MISC_CTRL(pipe)		_MMIO_PIPE(pipe, _HSW_AUD_MISC_CTRL_A, _HSW_AUD_MISC_CTRL_B)
 
+#define _HSW_AUD_M_CTS_ENABLE_A		0x65028
+#define _HSW_AUD_M_CTS_ENABLE_B		0x65128
+#define HSW_AUD_M_CTS_ENABLE(pipe)	_MMIO_PIPE(pipe, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
+#define   AUD_M_CTS_M_VALUE_INDEX	(1 << 21)
+#define   AUD_M_CTS_M_PROG_ENABLE	(1 << 20)
+#define   AUD_CONFIG_M_MASK		0xfffff
+
 #define _HSW_AUD_DIP_ELD_CTRL_ST_A	0x650b4
 #define _HSW_AUD_DIP_ELD_CTRL_ST_B	0x651b4
 #define HSW_AUD_DIP_ELD_CTRL(pipe)	_MMIO_PIPE(pipe, _HSW_AUD_DIP_ELD_CTRL_ST_A, _HSW_AUD_DIP_ELD_CTRL_ST_B)
@@ -7394,6 +7342,13 @@ enum {
 #define  SKL_FUSE_PG1_DIST_STATUS              (1<<26)
 #define  SKL_FUSE_PG2_DIST_STATUS              (1<<25)
 
+/* Decoupled MMIO register pair for kernel driver */
+#define GEN9_DECOUPLED_REG0_DW0			_MMIO(0xF00)
+#define GEN9_DECOUPLED_REG0_DW1			_MMIO(0xF04)
+#define GEN9_DECOUPLED_DW1_GO			(1<<31)
+#define GEN9_DECOUPLED_PD_SHIFT			28
+#define GEN9_DECOUPLED_OP_SHIFT			24
+
 /* Per-pipe DDI Function Control */
 #define _TRANS_DDI_FUNC_CTL_A		0x60400
 #define _TRANS_DDI_FUNC_CTL_B		0x61400
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_suspend.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_suspend.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_suspend.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_suspend.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,35 +29,31 @@
 #include "intel_drv.h"
 #include "i915_reg.h"
 
-static void i915_save_display(struct drm_device *dev)
+static void i915_save_display(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/* Display arbitration control */
-	if (INTEL_INFO(dev)->gen <= 4)
+	if (INTEL_GEN(dev_priv) <= 4)
 		dev_priv->regfile.saveDSPARB = I915_READ(DSPARB);
 
 	/* save FBC interval */
-	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
+	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv))
 		dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL);
 }
 
-static void i915_restore_display(struct drm_device *dev)
+static void i915_restore_display(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/* Display arbitration */
-	if (INTEL_INFO(dev)->gen <= 4)
+	if (INTEL_GEN(dev_priv) <= 4)
 		I915_WRITE(DSPARB, dev_priv->regfile.saveDSPARB);
 
 	/* only restore FBC info on the platform that supports FBC*/
 	intel_fbc_global_disable(dev_priv);
 
 	/* restore FBC interval */
-	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev))
+	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv))
 		I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL);
 
-	i915_redisable_vga(dev);
+	i915_redisable_vga(dev_priv);
 }
 
 int i915_save_state(struct drm_device *dev)
@@ -68,14 +64,14 @@ int i915_save_state(struct drm_device *d
 
 	mutex_lock(&dev->struct_mutex);
 
-	i915_save_display(dev);
+	i915_save_display(dev_priv);
 
-	if (IS_GEN4(dev))
+	if (IS_GEN4(dev_priv))
 		pci_read_config_word(pdev, GCDGMBUS,
 				     &dev_priv->regfile.saveGCDGMBUS);
 
 	/* Cache mode state */
-	if (INTEL_INFO(dev)->gen < 7)
+	if (INTEL_GEN(dev_priv) < 7)
 		dev_priv->regfile.saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0);
 
 	/* Memory Arbitration state */
@@ -114,15 +110,15 @@ int i915_restore_state(struct drm_device
 
 	mutex_lock(&dev->struct_mutex);
 
-	i915_gem_restore_fences(dev);
+	i915_gem_restore_fences(dev_priv);
 
-	if (IS_GEN4(dev))
+	if (IS_GEN4(dev_priv))
 		pci_write_config_word(pdev, GCDGMBUS,
 				      dev_priv->regfile.saveGCDGMBUS);
-	i915_restore_display(dev);
+	i915_restore_display(dev_priv);
 
 	/* Cache mode state */
-	if (INTEL_INFO(dev)->gen < 7)
+	if (INTEL_GEN(dev_priv) < 7)
 		I915_WRITE(CACHE_MODE_0, dev_priv->regfile.saveCACHE_MODE_0 |
 			   0xffff0000);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_sw_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_sw_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_sw_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_sw_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,11 +8,13 @@
  */
 
 #include <linux/slab.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 #include <linux/reservation.h>
 
 #include "i915_sw_fence.h"
 
+#define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */
+
 static DEFINE_SPINLOCK(i915_sw_fence_lock);
 
 static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
@@ -114,11 +116,14 @@ static void i915_sw_fence_await(struct i
 	WARN_ON(atomic_inc_return(&fence->pending) <= 1);
 }
 
-void i915_sw_fence_init(struct i915_sw_fence *fence, i915_sw_fence_notify_t fn)
+void __i915_sw_fence_init(struct i915_sw_fence *fence,
+			  i915_sw_fence_notify_t fn,
+			  const char *name,
+			  struct lock_class_key *key)
 {
 	BUG_ON((unsigned long)fn & ~I915_SW_FENCE_MASK);
 
-	init_waitqueue_head(&fence->wait);
+	__init_waitqueue_head(&fence->wait, name, key);
 	kref_init(&fence->kref);
 	atomic_set(&fence->pending, 1);
 	fence->flags = (unsigned long)fn;
@@ -135,6 +140,8 @@ static int i915_sw_fence_wake(wait_queue
 	list_del(&wq->task_list);
 	__i915_sw_fence_complete(wq->private, key);
 	i915_sw_fence_put(wq->private);
+	if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
+		kfree(wq);
 	return 0;
 }
 
@@ -192,9 +199,9 @@ static bool i915_sw_fence_check_if_after
 	return err;
 }
 
-int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
-				 struct i915_sw_fence *signaler,
-				 wait_queue_t *wq)
+static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
+					  struct i915_sw_fence *signaler,
+					  wait_queue_t *wq, gfp_t gfp)
 {
 	unsigned long flags;
 	int pending;
@@ -206,8 +213,22 @@ int i915_sw_fence_await_sw_fence(struct
 	if (unlikely(i915_sw_fence_check_if_after(fence, signaler)))
 		return -EINVAL;
 
+	pending = 0;
+	if (!wq) {
+		wq = kmalloc(sizeof(*wq), gfp);
+		if (!wq) {
+			if (!gfpflags_allow_blocking(gfp))
+				return -ENOMEM;
+
+			i915_sw_fence_wait(signaler);
+			return 0;
+		}
+
+		pending |= I915_SW_FENCE_FLAG_ALLOC;
+	}
+
 	INIT_LIST_HEAD(&wq->task_list);
-	wq->flags = 0;
+	wq->flags = pending;
 	wq->func = i915_sw_fence_wake;
 	wq->private = i915_sw_fence_get(fence);
 
@@ -226,49 +247,64 @@ int i915_sw_fence_await_sw_fence(struct
 	return pending;
 }
 
-struct dma_fence_cb {
-	struct fence_cb base;
+int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
+				 struct i915_sw_fence *signaler,
+				 wait_queue_t *wq)
+{
+	return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0);
+}
+
+int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
+				     struct i915_sw_fence *signaler,
+				     gfp_t gfp)
+{
+	return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp);
+}
+
+struct i915_sw_dma_fence_cb {
+	struct dma_fence_cb base;
 	struct i915_sw_fence *fence;
-	struct fence *dma;
+	struct dma_fence *dma;
 	struct timer_list timer;
 };
 
 static void timer_i915_sw_fence_wake(unsigned long data)
 {
-	struct dma_fence_cb *cb = (struct dma_fence_cb *)data;
+	struct i915_sw_dma_fence_cb *cb = (struct i915_sw_dma_fence_cb *)data;
 
 	printk(KERN_WARNING "asynchronous wait on fence %s:%s:%x timed out\n",
 	       cb->dma->ops->get_driver_name(cb->dma),
 	       cb->dma->ops->get_timeline_name(cb->dma),
 	       cb->dma->seqno);
-	fence_put(cb->dma);
+	dma_fence_put(cb->dma);
 	cb->dma = NULL;
 
 	i915_sw_fence_commit(cb->fence);
 	cb->timer.function = NULL;
 }
 
-static void dma_i915_sw_fence_wake(struct fence *dma, struct fence_cb *data)
+static void dma_i915_sw_fence_wake(struct dma_fence *dma,
+				   struct dma_fence_cb *data)
 {
-	struct dma_fence_cb *cb = container_of(data, typeof(*cb), base);
+	struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
 
 	del_timer_sync(&cb->timer);
 	if (cb->timer.function)
 		i915_sw_fence_commit(cb->fence);
-	fence_put(cb->dma);
+	dma_fence_put(cb->dma);
 
 	kfree(cb);
 }
 
 int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
-				  struct fence *dma,
+				  struct dma_fence *dma,
 				  unsigned long timeout,
 				  gfp_t gfp)
 {
-	struct dma_fence_cb *cb;
+	struct i915_sw_dma_fence_cb *cb;
 	int ret;
 
-	if (fence_is_signaled(dma))
+	if (dma_fence_is_signaled(dma))
 		return 0;
 
 	cb = kmalloc(sizeof(*cb), gfp);
@@ -276,7 +312,7 @@ int i915_sw_fence_await_dma_fence(struct
 		if (!gfpflags_allow_blocking(gfp))
 			return -ENOMEM;
 
-		return fence_wait(dma, false);
+		return dma_fence_wait(dma, false);
 	}
 
 	cb->fence = i915_sw_fence_get(fence);
@@ -287,11 +323,11 @@ int i915_sw_fence_await_dma_fence(struct
 		      timer_i915_sw_fence_wake, (unsigned long)cb,
 		      TIMER_IRQSAFE);
 	if (timeout) {
-		cb->dma = fence_get(dma);
+		cb->dma = dma_fence_get(dma);
 		mod_timer(&cb->timer, round_jiffies_up(jiffies + timeout));
 	}
 
-	ret = fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake);
+	ret = dma_fence_add_callback(dma, &cb->base, dma_i915_sw_fence_wake);
 	if (ret == 0) {
 		ret = 1;
 	} else {
@@ -305,16 +341,16 @@ int i915_sw_fence_await_dma_fence(struct
 
 int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
 				    struct reservation_object *resv,
-				    const struct fence_ops *exclude,
+				    const struct dma_fence_ops *exclude,
 				    bool write,
 				    unsigned long timeout,
 				    gfp_t gfp)
 {
-	struct fence *excl;
+	struct dma_fence *excl;
 	int ret = 0, pending;
 
 	if (write) {
-		struct fence **shared;
+		struct dma_fence **shared;
 		unsigned int count, i;
 
 		ret = reservation_object_get_fences_rcu(resv,
@@ -339,7 +375,7 @@ int i915_sw_fence_await_reservation(stru
 		}
 
 		for (i = 0; i < count; i++)
-			fence_put(shared[i]);
+			dma_fence_put(shared[i]);
 		kfree(shared);
 	} else {
 		excl = reservation_object_get_excl_rcu(resv);
@@ -356,7 +392,7 @@ int i915_sw_fence_await_reservation(stru
 			ret |= pending;
 	}
 
-	fence_put(excl);
+	dma_fence_put(excl);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_sw_fence.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_sw_fence.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_sw_fence.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_sw_fence.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,8 +16,8 @@
 #include <linux/wait.h>
 
 struct completion;
-struct fence;
-struct fence_ops;
+struct dma_fence;
+struct dma_fence_ops;
 struct reservation_object;
 
 struct i915_sw_fence {
@@ -40,26 +40,54 @@ typedef int (*i915_sw_fence_notify_t)(st
 				      enum i915_sw_fence_notify state);
 #define __i915_sw_fence_call __aligned(4)
 
-void i915_sw_fence_init(struct i915_sw_fence *fence, i915_sw_fence_notify_t fn);
+void __i915_sw_fence_init(struct i915_sw_fence *fence,
+			  i915_sw_fence_notify_t fn,
+			  const char *name,
+			  struct lock_class_key *key);
+#ifdef CONFIG_LOCKDEP
+#define i915_sw_fence_init(fence, fn)				\
+do {								\
+	static struct lock_class_key __key;			\
+								\
+	__i915_sw_fence_init((fence), (fn), #fence, &__key);	\
+} while (0)
+#else
+#define i915_sw_fence_init(fence, fn)				\
+	__i915_sw_fence_init((fence), (fn), NULL, NULL)
+#endif
+
 void i915_sw_fence_commit(struct i915_sw_fence *fence);
 
 int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
 				 struct i915_sw_fence *after,
 				 wait_queue_t *wq);
+int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
+				     struct i915_sw_fence *after,
+				     gfp_t gfp);
 int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
-				  struct fence *dma,
+				  struct dma_fence *dma,
 				  unsigned long timeout,
 				  gfp_t gfp);
 int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
 				    struct reservation_object *resv,
-				    const struct fence_ops *exclude,
+				    const struct dma_fence_ops *exclude,
 				    bool write,
 				    unsigned long timeout,
 				    gfp_t gfp);
 
+static inline bool i915_sw_fence_signaled(const struct i915_sw_fence *fence)
+{
+	return atomic_read(&fence->pending) <= 0;
+}
+
 static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence)
 {
 	return atomic_read(&fence->pending) < 0;
 }
 
+static inline void i915_sw_fence_wait(struct i915_sw_fence *fence)
+{
+	wait_event(fence->wait, i915_sw_fence_done(fence));
+}
+
 #endif /* _I915_SW_FENCE_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_sysfs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_sysfs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -460,7 +460,7 @@ static ssize_t gt_min_freq_mhz_store(str
 
 static DEVICE_ATTR(gt_act_freq_mhz, S_IRUGO, gt_act_freq_mhz_show, NULL);
 static DEVICE_ATTR(gt_cur_freq_mhz, S_IRUGO, gt_cur_freq_mhz_show, NULL);
-static DEVICE_ATTR(gt_boost_freq_mhz, S_IRUGO, gt_boost_freq_mhz_show, gt_boost_freq_mhz_store);
+static DEVICE_ATTR(gt_boost_freq_mhz, S_IRUGO | S_IWUSR, gt_boost_freq_mhz_show, gt_boost_freq_mhz_store);
 static DEVICE_ATTR(gt_max_freq_mhz, S_IRUGO | S_IWUSR, gt_max_freq_mhz_show, gt_max_freq_mhz_store);
 static DEVICE_ATTR(gt_min_freq_mhz, S_IRUGO | S_IWUSR, gt_min_freq_mhz_show, gt_min_freq_mhz_store);
 
@@ -514,6 +514,8 @@ static const struct attribute *vlv_attrs
 	NULL,
 };
 
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
 static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
 				struct bin_attribute *attr, char *buf,
 				loff_t off, size_t count)
@@ -571,6 +573,21 @@ static struct bin_attribute error_state_
 	.write = error_state_write,
 };
 
+static void i915_setup_error_capture(struct device *kdev)
+{
+	if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr))
+		DRM_ERROR("error_state sysfs setup failed\n");
+}
+
+static void i915_teardown_error_capture(struct device *kdev)
+{
+	sysfs_remove_bin_file(&kdev->kobj, &error_state_attr);
+}
+#else
+static void i915_setup_error_capture(struct device *kdev) {}
+static void i915_teardown_error_capture(struct device *kdev) {}
+#endif
+
 void i915_setup_sysfs(struct drm_i915_private *dev_priv)
 {
 	struct device *kdev = dev_priv->drm.primary->kdev;
@@ -617,17 +634,15 @@ void i915_setup_sysfs(struct drm_i915_pr
 	if (ret)
 		DRM_ERROR("RPS sysfs setup failed\n");
 
-	ret = sysfs_create_bin_file(&kdev->kobj,
-				    &error_state_attr);
-	if (ret)
-		DRM_ERROR("error_state sysfs setup failed\n");
+	i915_setup_error_capture(kdev);
 }
 
 void i915_teardown_sysfs(struct drm_i915_private *dev_priv)
 {
 	struct device *kdev = dev_priv->drm.primary->kdev;
 
-	sysfs_remove_bin_file(&kdev->kobj, &error_state_attr);
+	i915_teardown_error_capture(kdev);
+
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		sysfs_remove_files(&kdev->kobj, vlv_attrs);
 	else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_trace.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_trace.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_trace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -466,7 +466,7 @@ TRACE_EVENT(i915_gem_ring_sync_to,
 			   __entry->dev = from->i915->drm.primary->index;
 			   __entry->sync_from = from->engine->id;
 			   __entry->sync_to = to->engine->id;
-			   __entry->seqno = from->fence.seqno;
+			   __entry->seqno = from->global_seqno;
 			   ),
 
 	    TP_printk("dev=%u, sync-from=%u, sync-to=%u, seqno=%u",
@@ -489,9 +489,9 @@ TRACE_EVENT(i915_gem_ring_dispatch,
 	    TP_fast_assign(
 			   __entry->dev = req->i915->drm.primary->index;
 			   __entry->ring = req->engine->id;
-			   __entry->seqno = req->fence.seqno;
+			   __entry->seqno = req->global_seqno;
 			   __entry->flags = flags;
-			   fence_enable_sw_signaling(&req->fence);
+			   dma_fence_enable_sw_signaling(&req->fence);
 			   ),
 
 	    TP_printk("dev=%u, ring=%u, seqno=%u, flags=%x",
@@ -534,7 +534,7 @@ DECLARE_EVENT_CLASS(i915_gem_request,
 	    TP_fast_assign(
 			   __entry->dev = req->i915->drm.primary->index;
 			   __entry->ring = req->engine->id;
-			   __entry->seqno = req->fence.seqno;
+			   __entry->seqno = req->global_seqno;
 			   ),
 
 	    TP_printk("dev=%u, ring=%u, seqno=%u",
@@ -596,7 +596,7 @@ TRACE_EVENT(i915_gem_request_wait_begin,
 	    TP_fast_assign(
 			   __entry->dev = req->i915->drm.primary->index;
 			   __entry->ring = req->engine->id;
-			   __entry->seqno = req->fence.seqno;
+			   __entry->seqno = req->global_seqno;
 			   __entry->blocking =
 				     mutex_is_locked(&req->i915->drm.struct_mutex);
 			   ),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_vma.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_vma.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_vma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_vma.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,639 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+ 
+#include "i915_vma.h"
+
+#include "i915_drv.h"
+#include "intel_ringbuffer.h"
+#include "intel_frontbuffer.h"
+
+#include <drm/drm_gem.h>
+
+static void
+i915_vma_retire(struct i915_gem_active *active,
+		struct drm_i915_gem_request *rq)
+{
+	const unsigned int idx = rq->engine->id;
+	struct i915_vma *vma =
+		container_of(active, struct i915_vma, last_read[idx]);
+	struct drm_i915_gem_object *obj = vma->obj;
+
+	GEM_BUG_ON(!i915_vma_has_active_engine(vma, idx));
+
+	i915_vma_clear_active(vma, idx);
+	if (i915_vma_is_active(vma))
+		return;
+
+	list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
+	if (unlikely(i915_vma_is_closed(vma) && !i915_vma_is_pinned(vma)))
+		WARN_ON(i915_vma_unbind(vma));
+
+	GEM_BUG_ON(!i915_gem_object_is_active(obj));
+	if (--obj->active_count)
+		return;
+
+	/* Bump our place on the bound list to keep it roughly in LRU order
+	 * so that we don't steal from recently used but inactive objects
+	 * (unless we are forced to ofc!)
+	 */
+	if (obj->bind_count)
+		list_move_tail(&obj->global_link, &rq->i915->mm.bound_list);
+
+	obj->mm.dirty = true; /* be paranoid  */
+
+	if (i915_gem_object_has_active_reference(obj)) {
+		i915_gem_object_clear_active_reference(obj);
+		i915_gem_object_put(obj);
+	}
+}
+
+static struct i915_vma *
+__i915_vma_create(struct drm_i915_gem_object *obj,
+		  struct i915_address_space *vm,
+		  const struct i915_ggtt_view *view)
+{
+	struct i915_vma *vma;
+	struct rb_node *rb, **p;
+	int i;
+
+	GEM_BUG_ON(vm->closed);
+
+	vma = kmem_cache_zalloc(to_i915(obj->base.dev)->vmas, GFP_KERNEL);
+	if (vma == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&vma->exec_list);
+	for (i = 0; i < ARRAY_SIZE(vma->last_read); i++)
+		init_request_active(&vma->last_read[i], i915_vma_retire);
+	init_request_active(&vma->last_fence, NULL);
+	list_add(&vma->vm_link, &vm->unbound_list);
+	vma->vm = vm;
+	vma->obj = obj;
+	vma->size = obj->base.size;
+
+	if (view) {
+		vma->ggtt_view = *view;
+		if (view->type == I915_GGTT_VIEW_PARTIAL) {
+			vma->size = view->params.partial.size;
+			vma->size <<= PAGE_SHIFT;
+		} else if (view->type == I915_GGTT_VIEW_ROTATED) {
+			vma->size =
+				intel_rotation_info_size(&view->params.rotated);
+			vma->size <<= PAGE_SHIFT;
+		}
+	}
+
+	if (i915_is_ggtt(vm)) {
+		vma->flags |= I915_VMA_GGTT;
+		list_add(&vma->obj_link, &obj->vma_list);
+	} else {
+		i915_ppgtt_get(i915_vm_to_ppgtt(vm));
+		list_add_tail(&vma->obj_link, &obj->vma_list);
+	}
+
+	rb = NULL;
+	p = &obj->vma_tree.rb_node;
+	while (*p) {
+		struct i915_vma *pos;
+
+		rb = *p;
+		pos = rb_entry(rb, struct i915_vma, obj_node);
+		if (i915_vma_compare(pos, vm, view) < 0)
+			p = &rb->rb_right;
+		else
+			p = &rb->rb_left;
+	}
+	rb_link_node(&vma->obj_node, rb, p);
+	rb_insert_color(&vma->obj_node, &obj->vma_tree);
+
+	return vma;
+}
+
+struct i915_vma *
+i915_vma_create(struct drm_i915_gem_object *obj,
+		struct i915_address_space *vm,
+		const struct i915_ggtt_view *view)
+{
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+	GEM_BUG_ON(view && !i915_is_ggtt(vm));
+	GEM_BUG_ON(i915_gem_obj_to_vma(obj, vm, view));
+
+	return __i915_vma_create(obj, vm, view);
+}
+
+/**
+ * i915_vma_bind - Sets up PTEs for an VMA in it's corresponding address space.
+ * @vma: VMA to map
+ * @cache_level: mapping cache level
+ * @flags: flags like global or local mapping
+ *
+ * DMA addresses are taken from the scatter-gather table of this object (or of
+ * this VMA in case of non-default GGTT views) and PTE entries set up.
+ * Note that DMA addresses are also the only part of the SG table we care about.
+ */
+int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
+		  u32 flags)
+{
+	u32 bind_flags;
+	u32 vma_flags;
+	int ret;
+
+	if (WARN_ON(flags == 0))
+		return -EINVAL;
+
+	bind_flags = 0;
+	if (flags & PIN_GLOBAL)
+		bind_flags |= I915_VMA_GLOBAL_BIND;
+	if (flags & PIN_USER)
+		bind_flags |= I915_VMA_LOCAL_BIND;
+
+	vma_flags = vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
+	if (flags & PIN_UPDATE)
+		bind_flags |= vma_flags;
+	else
+		bind_flags &= ~vma_flags;
+	if (bind_flags == 0)
+		return 0;
+
+	if (vma_flags == 0 && vma->vm->allocate_va_range) {
+		trace_i915_va_alloc(vma);
+		ret = vma->vm->allocate_va_range(vma->vm,
+						 vma->node.start,
+						 vma->node.size);
+		if (ret)
+			return ret;
+	}
+
+	trace_i915_vma_bind(vma, bind_flags);
+	ret = vma->vm->bind_vma(vma, cache_level, bind_flags);
+	if (ret)
+		return ret;
+
+	vma->flags |= bind_flags;
+	return 0;
+}
+
+void __iomem *i915_vma_pin_iomap(struct i915_vma *vma)
+{
+	void __iomem *ptr;
+
+	/* Access through the GTT requires the device to be awake. */
+	assert_rpm_wakelock_held(to_i915(vma->vm->dev));
+
+	lockdep_assert_held(&vma->vm->dev->struct_mutex);
+	if (WARN_ON(!i915_vma_is_map_and_fenceable(vma)))
+		return IO_ERR_PTR(-ENODEV);
+
+	GEM_BUG_ON(!i915_vma_is_ggtt(vma));
+	GEM_BUG_ON((vma->flags & I915_VMA_GLOBAL_BIND) == 0);
+
+	ptr = vma->iomap;
+	if (ptr == NULL) {
+		ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->mappable,
+					vma->node.start,
+					vma->node.size);
+		if (ptr == NULL)
+			return IO_ERR_PTR(-ENOMEM);
+
+		vma->iomap = ptr;
+	}
+
+	__i915_vma_pin(vma);
+	return ptr;
+}
+
+void i915_vma_unpin_and_release(struct i915_vma **p_vma)
+{
+	struct i915_vma *vma;
+	struct drm_i915_gem_object *obj;
+
+	vma = fetch_and_zero(p_vma);
+	if (!vma)
+		return;
+
+	obj = vma->obj;
+
+	i915_vma_unpin(vma);
+	i915_vma_close(vma);
+
+	__i915_gem_object_release_unless_active(obj);
+}
+
+bool
+i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+{
+	if (!drm_mm_node_allocated(&vma->node))
+		return false;
+
+	if (vma->node.size < size)
+		return true;
+
+	if (alignment && vma->node.start & (alignment - 1))
+		return true;
+
+	if (flags & PIN_MAPPABLE && !i915_vma_is_map_and_fenceable(vma))
+		return true;
+
+	if (flags & PIN_OFFSET_BIAS &&
+	    vma->node.start < (flags & PIN_OFFSET_MASK))
+		return true;
+
+	if (flags & PIN_OFFSET_FIXED &&
+	    vma->node.start != (flags & PIN_OFFSET_MASK))
+		return true;
+
+	return false;
+}
+
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
+{
+	struct drm_i915_gem_object *obj = vma->obj;
+	struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+	bool mappable, fenceable;
+	u32 fence_size, fence_alignment;
+
+	fence_size = i915_gem_get_ggtt_size(dev_priv,
+					    vma->size,
+					    i915_gem_object_get_tiling(obj));
+	fence_alignment = i915_gem_get_ggtt_alignment(dev_priv,
+						      vma->size,
+						      i915_gem_object_get_tiling(obj),
+						      true);
+
+	fenceable = (vma->node.size == fence_size &&
+		     (vma->node.start & (fence_alignment - 1)) == 0);
+
+	mappable = (vma->node.start + fence_size <=
+		    dev_priv->ggtt.mappable_end);
+
+	/*
+	 * Explicitly disable for rotated VMA since the display does not
+	 * need the fence and the VMA is not accessible to other users.
+	 */
+	if (mappable && fenceable &&
+	    vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED)
+		vma->flags |= I915_VMA_CAN_FENCE;
+	else
+		vma->flags &= ~I915_VMA_CAN_FENCE;
+}
+
+bool i915_gem_valid_gtt_space(struct i915_vma *vma,
+			      unsigned long cache_level)
+{
+	struct drm_mm_node *gtt_space = &vma->node;
+	struct drm_mm_node *other;
+
+	/*
+	 * On some machines we have to be careful when putting differing types
+	 * of snoopable memory together to avoid the prefetcher crossing memory
+	 * domains and dying. During vm initialisation, we decide whether or not
+	 * these constraints apply and set the drm_mm.color_adjust
+	 * appropriately.
+	 */
+	if (vma->vm->mm.color_adjust == NULL)
+		return true;
+
+	if (!drm_mm_node_allocated(gtt_space))
+		return true;
+
+	if (list_empty(&gtt_space->node_list))
+		return true;
+
+	other = list_entry(gtt_space->node_list.prev, struct drm_mm_node, node_list);
+	if (other->allocated && !other->hole_follows && other->color != cache_level)
+		return false;
+
+	other = list_entry(gtt_space->node_list.next, struct drm_mm_node, node_list);
+	if (other->allocated && !gtt_space->hole_follows && other->color != cache_level)
+		return false;
+
+	return true;
+}
+
+/**
+ * i915_vma_insert - finds a slot for the vma in its address space
+ * @vma: the vma
+ * @size: requested size in bytes (can be larger than the VMA)
+ * @alignment: required alignment
+ * @flags: mask of PIN_* flags to use
+ *
+ * First we try to allocate some free space that meets the requirements for
+ * the VMA. Failiing that, if the flags permit, it will evict an old VMA,
+ * preferrably the oldest idle entry to make room for the new VMA.
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise.
+ */
+static int
+i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+{
+	struct drm_i915_private *dev_priv = to_i915(vma->vm->dev);
+	struct drm_i915_gem_object *obj = vma->obj;
+	u64 start, end;
+	int ret;
+
+	GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND));
+	GEM_BUG_ON(drm_mm_node_allocated(&vma->node));
+
+	size = max(size, vma->size);
+	if (flags & PIN_MAPPABLE)
+		size = i915_gem_get_ggtt_size(dev_priv, size,
+					      i915_gem_object_get_tiling(obj));
+
+	alignment = max(max(alignment, vma->display_alignment),
+			i915_gem_get_ggtt_alignment(dev_priv, size,
+						    i915_gem_object_get_tiling(obj),
+						    flags & PIN_MAPPABLE));
+
+	start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
+
+	end = vma->vm->total;
+	if (flags & PIN_MAPPABLE)
+		end = min_t(u64, end, dev_priv->ggtt.mappable_end);
+	if (flags & PIN_ZONE_4G)
+		end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE);
+
+	/* If binding the object/GGTT view requires more space than the entire
+	 * aperture has, reject it early before evicting everything in a vain
+	 * attempt to find space.
+	 */
+	if (size > end) {
+		DRM_DEBUG("Attempting to bind an object larger than the aperture: request=%llu [object=%zd] > %s aperture=%llu\n",
+			  size, obj->base.size,
+			  flags & PIN_MAPPABLE ? "mappable" : "total",
+			  end);
+		return -E2BIG;
+	}
+
+	ret = i915_gem_object_pin_pages(obj);
+	if (ret)
+		return ret;
+
+	if (flags & PIN_OFFSET_FIXED) {
+		u64 offset = flags & PIN_OFFSET_MASK;
+		if (offset & (alignment - 1) || offset > end - size) {
+			ret = -EINVAL;
+			goto err_unpin;
+		}
+
+		vma->node.start = offset;
+		vma->node.size = size;
+		vma->node.color = obj->cache_level;
+		ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
+		if (ret) {
+			ret = i915_gem_evict_for_vma(vma);
+			if (ret == 0)
+				ret = drm_mm_reserve_node(&vma->vm->mm, &vma->node);
+			if (ret)
+				goto err_unpin;
+		}
+	} else {
+		u32 search_flag, alloc_flag;
+
+		if (flags & PIN_HIGH) {
+			search_flag = DRM_MM_SEARCH_BELOW;
+			alloc_flag = DRM_MM_CREATE_TOP;
+		} else {
+			search_flag = DRM_MM_SEARCH_DEFAULT;
+			alloc_flag = DRM_MM_CREATE_DEFAULT;
+		}
+
+		/* We only allocate in PAGE_SIZE/GTT_PAGE_SIZE (4096) chunks,
+		 * so we know that we always have a minimum alignment of 4096.
+		 * The drm_mm range manager is optimised to return results
+		 * with zero alignment, so where possible use the optimal
+		 * path.
+		 */
+		if (alignment <= 4096)
+			alignment = 0;
+
+search_free:
+		ret = drm_mm_insert_node_in_range_generic(&vma->vm->mm,
+							  &vma->node,
+							  size, alignment,
+							  obj->cache_level,
+							  start, end,
+							  search_flag,
+							  alloc_flag);
+		if (ret) {
+			ret = i915_gem_evict_something(vma->vm, size, alignment,
+						       obj->cache_level,
+						       start, end,
+						       flags);
+			if (ret == 0)
+				goto search_free;
+
+			goto err_unpin;
+		}
+
+		GEM_BUG_ON(vma->node.start < start);
+		GEM_BUG_ON(vma->node.start + vma->node.size > end);
+	}
+	GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level));
+
+	list_move_tail(&obj->global_link, &dev_priv->mm.bound_list);
+	list_move_tail(&vma->vm_link, &vma->vm->inactive_list);
+	obj->bind_count++;
+	GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count);
+
+	return 0;
+
+err_unpin:
+	i915_gem_object_unpin_pages(obj);
+	return ret;
+}
+
+int __i915_vma_do_pin(struct i915_vma *vma,
+		      u64 size, u64 alignment, u64 flags)
+{
+	unsigned int bound = vma->flags;
+	int ret;
+
+	lockdep_assert_held(&vma->vm->dev->struct_mutex);
+	GEM_BUG_ON((flags & (PIN_GLOBAL | PIN_USER)) == 0);
+	GEM_BUG_ON((flags & PIN_GLOBAL) && !i915_vma_is_ggtt(vma));
+
+	if (WARN_ON(bound & I915_VMA_PIN_OVERFLOW)) {
+		ret = -EBUSY;
+		goto err;
+	}
+
+	if ((bound & I915_VMA_BIND_MASK) == 0) {
+		ret = i915_vma_insert(vma, size, alignment, flags);
+		if (ret)
+			goto err;
+	}
+
+	ret = i915_vma_bind(vma, vma->obj->cache_level, flags);
+	if (ret)
+		goto err;
+
+	if ((bound ^ vma->flags) & I915_VMA_GLOBAL_BIND)
+		__i915_vma_set_map_and_fenceable(vma);
+
+	GEM_BUG_ON(i915_vma_misplaced(vma, size, alignment, flags));
+	return 0;
+
+err:
+	__i915_vma_unpin(vma);
+	return ret;
+}
+
+void i915_vma_destroy(struct i915_vma *vma)
+{
+	GEM_BUG_ON(vma->node.allocated);
+	GEM_BUG_ON(i915_vma_is_active(vma));
+	GEM_BUG_ON(!i915_vma_is_closed(vma));
+	GEM_BUG_ON(vma->fence);
+
+	list_del(&vma->vm_link);
+	if (!i915_vma_is_ggtt(vma))
+		i915_ppgtt_put(i915_vm_to_ppgtt(vma->vm));
+
+	kmem_cache_free(to_i915(vma->obj->base.dev)->vmas, vma);
+}
+
+void i915_vma_close(struct i915_vma *vma)
+{
+	GEM_BUG_ON(i915_vma_is_closed(vma));
+	vma->flags |= I915_VMA_CLOSED;
+
+	list_del(&vma->obj_link);
+	rb_erase(&vma->obj_node, &vma->obj->vma_tree);
+
+	if (!i915_vma_is_active(vma) && !i915_vma_is_pinned(vma))
+		WARN_ON(i915_vma_unbind(vma));
+}
+
+static void __i915_vma_iounmap(struct i915_vma *vma)
+{
+	GEM_BUG_ON(i915_vma_is_pinned(vma));
+
+	if (vma->iomap == NULL)
+		return;
+
+	io_mapping_unmap(vma->iomap);
+	vma->iomap = NULL;
+}
+
+int i915_vma_unbind(struct i915_vma *vma)
+{
+	struct drm_i915_gem_object *obj = vma->obj;
+	unsigned long active;
+	int ret;
+
+	lockdep_assert_held(&obj->base.dev->struct_mutex);
+
+	/* First wait upon any activity as retiring the request may
+	 * have side-effects such as unpinning or even unbinding this vma.
+	 */
+	active = i915_vma_get_active(vma);
+	if (active) {
+		int idx;
+
+		/* When a closed VMA is retired, it is unbound - eek.
+		 * In order to prevent it from being recursively closed,
+		 * take a pin on the vma so that the second unbind is
+		 * aborted.
+		 *
+		 * Even more scary is that the retire callback may free
+		 * the object (last active vma). To prevent the explosion
+		 * we defer the actual object free to a worker that can
+		 * only proceed once it acquires the struct_mutex (which
+		 * we currently hold, therefore it cannot free this object
+		 * before we are finished).
+		 */
+		__i915_vma_pin(vma);
+
+		for_each_active(active, idx) {
+			ret = i915_gem_active_retire(&vma->last_read[idx],
+						   &vma->vm->dev->struct_mutex);
+			if (ret)
+				break;
+		}
+
+		__i915_vma_unpin(vma);
+		if (ret)
+			return ret;
+
+		GEM_BUG_ON(i915_vma_is_active(vma));
+	}
+
+	if (i915_vma_is_pinned(vma))
+		return -EBUSY;
+
+	if (!drm_mm_node_allocated(&vma->node))
+		goto destroy;
+
+	GEM_BUG_ON(obj->bind_count == 0);
+	GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
+
+	if (i915_vma_is_map_and_fenceable(vma)) {
+		/* release the fence reg _after_ flushing */
+		ret = i915_vma_put_fence(vma);
+		if (ret)
+			return ret;
+
+		/* Force a pagefault for domain tracking on next user access */
+		i915_gem_release_mmap(obj);
+
+		__i915_vma_iounmap(vma);
+		vma->flags &= ~I915_VMA_CAN_FENCE;
+	}
+
+	if (likely(!vma->vm->closed)) {
+		trace_i915_vma_unbind(vma);
+		vma->vm->unbind_vma(vma);
+	}
+	vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND);
+
+	drm_mm_remove_node(&vma->node);
+	list_move_tail(&vma->vm_link, &vma->vm->unbound_list);
+
+	if (vma->pages != obj->mm.pages) {
+		GEM_BUG_ON(!vma->pages);
+		sg_free_table(vma->pages);
+		kfree(vma->pages);
+	}
+	vma->pages = NULL;
+
+	/* Since the unbound list is global, only move to that list if
+	 * no more VMAs exist. */
+	if (--obj->bind_count == 0)
+		list_move_tail(&obj->global_link,
+			       &to_i915(obj->base.dev)->mm.unbound_list);
+
+	/* And finally now the object is completely decoupled from this vma,
+	 * we can drop its hold on the backing storage and allow it to be
+	 * reaped by the shrinker.
+	 */
+	i915_gem_object_unpin_pages(obj);
+
+destroy:
+	if (unlikely(i915_vma_is_closed(vma)))
+		i915_vma_destroy(vma);
+
+	return 0;
+}
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_vma.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_vma.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/i915_vma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/i915_vma.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,341 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __I915_VMA_H__
+#define __I915_VMA_H__
+
+#include <linux/io-mapping.h>
+
+#include <drm/drm_mm.h>
+
+#include "i915_gem_gtt.h"
+#include "i915_gem_fence_reg.h"
+#include "i915_gem_object.h"
+#include "i915_gem_request.h"
+
+
+enum i915_cache_level;
+
+/**
+ * A VMA represents a GEM BO that is bound into an address space. Therefore, a
+ * VMA's presence cannot be guaranteed before binding, or after unbinding the
+ * object into/from the address space.
+ *
+ * To make things as simple as possible (ie. no refcounting), a VMA's lifetime
+ * will always be <= an objects lifetime. So object refcounting should cover us.
+ */
+struct i915_vma {
+	struct drm_mm_node node;
+	struct drm_i915_gem_object *obj;
+	struct i915_address_space *vm;
+	struct drm_i915_fence_reg *fence;
+	struct sg_table *pages;
+	void __iomem *iomap;
+	u64 size;
+	u64 display_alignment;
+
+	unsigned int flags;
+	/**
+	 * How many users have pinned this object in GTT space. The following
+	 * users can each hold at most one reference: pwrite/pread, execbuffer
+	 * (objects are not allowed multiple times for the same batchbuffer),
+	 * and the framebuffer code. When switching/pageflipping, the
+	 * framebuffer code has at most two buffers pinned per crtc.
+	 *
+	 * 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.
+	 */
+#define I915_VMA_PIN_MASK 0xf
+#define I915_VMA_PIN_OVERFLOW	BIT(5)
+
+	/** Flags and address space this VMA is bound to */
+#define I915_VMA_GLOBAL_BIND	BIT(6)
+#define I915_VMA_LOCAL_BIND	BIT(7)
+#define I915_VMA_BIND_MASK (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND | I915_VMA_PIN_OVERFLOW)
+
+#define I915_VMA_GGTT		BIT(8)
+#define I915_VMA_CAN_FENCE	BIT(9)
+#define I915_VMA_CLOSED		BIT(10)
+
+	unsigned int active;
+	struct i915_gem_active last_read[I915_NUM_ENGINES];
+	struct i915_gem_active last_fence;
+
+	/**
+	 * Support different GGTT views into the same object.
+	 * This means there can be multiple VMA mappings per object and per VM.
+	 * i915_ggtt_view_type is used to distinguish between those entries.
+	 * The default one of zero (I915_GGTT_VIEW_NORMAL) is default and also
+	 * assumed in GEM functions which take no ggtt view parameter.
+	 */
+	struct i915_ggtt_view ggtt_view;
+
+	/** This object's place on the active/inactive lists */
+	struct list_head vm_link;
+
+	struct list_head obj_link; /* Link in the object's VMA list */
+	struct rb_node obj_node;
+
+	/** This vma's place in the batchbuffer or on the eviction list */
+	struct list_head exec_list;
+
+	/**
+	 * Used for performing relocations during execbuffer insertion.
+	 */
+	struct hlist_node exec_node;
+	unsigned long exec_handle;
+	struct drm_i915_gem_exec_object2 *exec_entry;
+};
+
+struct i915_vma *
+i915_vma_create(struct drm_i915_gem_object *obj,
+		struct i915_address_space *vm,
+		const struct i915_ggtt_view *view);
+
+void i915_vma_unpin_and_release(struct i915_vma **p_vma);
+
+static inline bool i915_vma_is_ggtt(const struct i915_vma *vma)
+{
+	return vma->flags & I915_VMA_GGTT;
+}
+
+static inline bool i915_vma_is_map_and_fenceable(const struct i915_vma *vma)
+{
+	return vma->flags & I915_VMA_CAN_FENCE;
+}
+
+static inline bool i915_vma_is_closed(const struct i915_vma *vma)
+{
+	return vma->flags & I915_VMA_CLOSED;
+}
+
+static inline unsigned int i915_vma_get_active(const struct i915_vma *vma)
+{
+	return vma->active;
+}
+
+static inline bool i915_vma_is_active(const struct i915_vma *vma)
+{
+	return i915_vma_get_active(vma);
+}
+
+static inline void i915_vma_set_active(struct i915_vma *vma,
+				       unsigned int engine)
+{
+	vma->active |= BIT(engine);
+}
+
+static inline void i915_vma_clear_active(struct i915_vma *vma,
+					 unsigned int engine)
+{
+	vma->active &= ~BIT(engine);
+}
+
+static inline bool i915_vma_has_active_engine(const struct i915_vma *vma,
+					      unsigned int engine)
+{
+	return vma->active & BIT(engine);
+}
+
+static inline u32 i915_ggtt_offset(const struct i915_vma *vma)
+{
+	GEM_BUG_ON(!i915_vma_is_ggtt(vma));
+	GEM_BUG_ON(!vma->node.allocated);
+	GEM_BUG_ON(upper_32_bits(vma->node.start));
+	GEM_BUG_ON(upper_32_bits(vma->node.start + vma->node.size - 1));
+	return lower_32_bits(vma->node.start);
+}
+
+static inline struct i915_vma *i915_vma_get(struct i915_vma *vma)
+{
+	i915_gem_object_get(vma->obj);
+	return vma;
+}
+
+static inline void i915_vma_put(struct i915_vma *vma)
+{
+	i915_gem_object_put(vma->obj);
+}
+
+static inline long
+i915_vma_compare(struct i915_vma *vma,
+		 struct i915_address_space *vm,
+		 const struct i915_ggtt_view *view)
+{
+	GEM_BUG_ON(view && !i915_is_ggtt(vm));
+
+	if (vma->vm != vm)
+		return vma->vm - vm;
+
+	if (!view)
+		return vma->ggtt_view.type;
+
+	if (vma->ggtt_view.type != view->type)
+		return vma->ggtt_view.type - view->type;
+
+	return memcmp(&vma->ggtt_view.params,
+		      &view->params,
+		      sizeof(view->params));
+}
+
+int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
+		  u32 flags);
+bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level);
+bool
+i915_vma_misplaced(struct i915_vma *vma, u64 size, u64 alignment, u64 flags);
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
+int __must_check i915_vma_unbind(struct i915_vma *vma);
+void i915_vma_close(struct i915_vma *vma);
+void i915_vma_destroy(struct i915_vma *vma);
+
+int __i915_vma_do_pin(struct i915_vma *vma,
+		      u64 size, u64 alignment, u64 flags);
+static inline int __must_check
+i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags)
+{
+	BUILD_BUG_ON(PIN_MBZ != I915_VMA_PIN_OVERFLOW);
+	BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND);
+	BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND);
+
+	/* Pin early to prevent the shrinker/eviction logic from destroying
+	 * our vma as we insert and bind.
+	 */
+	if (likely(((++vma->flags ^ flags) & I915_VMA_BIND_MASK) == 0))
+		return 0;
+
+	return __i915_vma_do_pin(vma, size, alignment, flags);
+}
+
+static inline int i915_vma_pin_count(const struct i915_vma *vma)
+{
+	return vma->flags & I915_VMA_PIN_MASK;
+}
+
+static inline bool i915_vma_is_pinned(const struct i915_vma *vma)
+{
+	return i915_vma_pin_count(vma);
+}
+
+static inline void __i915_vma_pin(struct i915_vma *vma)
+{
+	vma->flags++;
+	GEM_BUG_ON(vma->flags & I915_VMA_PIN_OVERFLOW);
+}
+
+static inline void __i915_vma_unpin(struct i915_vma *vma)
+{
+	GEM_BUG_ON(!i915_vma_is_pinned(vma));
+	vma->flags--;
+}
+
+static inline void i915_vma_unpin(struct i915_vma *vma)
+{
+	GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
+	__i915_vma_unpin(vma);
+}
+
+/**
+ * i915_vma_pin_iomap - calls ioremap_wc to map the GGTT VMA via the aperture
+ * @vma: VMA to iomap
+ *
+ * The passed in VMA has to be pinned in the global GTT mappable region.
+ * An extra pinning of the VMA is acquired for the return iomapping,
+ * the caller must call i915_vma_unpin_iomap to relinquish the pinning
+ * after the iomapping is no longer required.
+ *
+ * Callers must hold the struct_mutex.
+ *
+ * Returns a valid iomapped pointer or ERR_PTR.
+ */
+void __iomem *i915_vma_pin_iomap(struct i915_vma *vma);
+#define IO_ERR_PTR(x) ((void __iomem *)ERR_PTR(x))
+
+/**
+ * i915_vma_unpin_iomap - unpins the mapping returned from i915_vma_iomap
+ * @vma: VMA to unpin
+ *
+ * Unpins the previously iomapped VMA from i915_vma_pin_iomap().
+ *
+ * Callers must hold the struct_mutex. This function is only valid to be
+ * called on a VMA previously iomapped by the caller with i915_vma_pin_iomap().
+ */
+static inline void i915_vma_unpin_iomap(struct i915_vma *vma)
+{
+	lockdep_assert_held(&vma->vm->dev->struct_mutex);
+	GEM_BUG_ON(vma->iomap == NULL);
+	i915_vma_unpin(vma);
+}
+
+static inline struct page *i915_vma_first_page(struct i915_vma *vma)
+{
+	GEM_BUG_ON(!vma->pages);
+	return sg_page(vma->pages->sgl);
+}
+
+/**
+ * i915_vma_pin_fence - pin fencing state
+ * @vma: vma to pin fencing for
+ *
+ * This pins the fencing state (whether tiled or untiled) to make sure the
+ * vma (and its object) is ready to be used as a scanout target. Fencing
+ * status must be synchronize first by calling i915_vma_get_fence():
+ *
+ * The resulting fence pin reference must be released again with
+ * i915_vma_unpin_fence().
+ *
+ * Returns:
+ *
+ * True if the vma has a fence, false otherwise.
+ */
+static inline bool
+i915_vma_pin_fence(struct i915_vma *vma)
+{
+	lockdep_assert_held(&vma->vm->dev->struct_mutex);
+	if (vma->fence) {
+		vma->fence->pin_count++;
+		return true;
+	} else
+		return false;
+}
+
+/**
+ * i915_vma_unpin_fence - unpin fencing state
+ * @vma: vma to unpin fencing for
+ *
+ * This releases the fence pin reference acquired through
+ * i915_vma_pin_fence. It will handle both objects with and without an
+ * attached fence correctly, callers do not need to distinguish this.
+ */
+static inline void
+i915_vma_unpin_fence(struct i915_vma *vma)
+{
+	lockdep_assert_held(&vma->vm->dev->struct_mutex);
+	if (vma->fence) {
+		GEM_BUG_ON(vma->fence->pin_count <= 0);
+		vma->fence->pin_count--;
+	}
+}
+
+#endif
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_atomic_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,8 @@ intel_plane_duplicate_state(struct drm_p
 	state = &intel_state->base;
 
 	__drm_atomic_helper_plane_duplicate_state(plane, state);
-	intel_state->wait_req = NULL;
+
+	intel_state->vma = NULL;
 
 	return state;
 }
@@ -101,13 +102,31 @@ void
 intel_plane_destroy_state(struct drm_plane *plane,
 			  struct drm_plane_state *state)
 {
-	WARN_ON(state && to_intel_plane_state(state)->wait_req);
+	struct i915_vma *vma;
+
+	vma = fetch_and_zero(&to_intel_plane_state(state)->vma);
+
+	/*
+	 * FIXME: Normally intel_cleanup_plane_fb handles destruction of vma.
+	 * We currently don't clear all planes during driver unload, so we have
+	 * to be able to unpin vma here for now.
+	 *
+	 * Normally this can only happen during unload when kmscon is disabled
+	 * and userspace doesn't attempt to set a framebuffer at all.
+	 */
+	if (vma) {
+		mutex_lock(&plane->dev->struct_mutex);
+		intel_unpin_fb_vma(vma);
+		mutex_unlock(&plane->dev->struct_mutex);
+	}
+
 	drm_atomic_helper_plane_destroy_state(plane, state);
 }
 
 static int intel_plane_atomic_check(struct drm_plane *plane,
 				    struct drm_plane_state *state)
 {
+	struct drm_i915_private *dev_priv = to_i915(plane->dev);
 	struct drm_crtc *crtc = state->crtc;
 	struct intel_crtc *intel_crtc;
 	struct intel_crtc_state *crtc_state;
@@ -142,10 +161,11 @@ static int intel_plane_atomic_check(stru
 	intel_state->clip.y2 =
 		crtc_state->base.enable ? crtc_state->pipe_src_h : 0;
 
-	if (state->fb && intel_rotation_90_or_270(state->rotation)) {
-		char *format_name;
-		if (!(state->fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
-			state->fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED)) {
+	if (state->fb && drm_rotation_90_or_270(state->rotation)) {
+		struct drm_format_name_buf format_name;
+
+		if (state->fb->modifier != I915_FORMAT_MOD_Y_TILED &&
+		    state->fb->modifier != I915_FORMAT_MOD_Yf_TILED) {
 			DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n");
 			return -EINVAL;
 		}
@@ -158,9 +178,9 @@ static int intel_plane_atomic_check(stru
 		switch (state->fb->pixel_format) {
 		case DRM_FORMAT_C8:
 		case DRM_FORMAT_RGB565:
-			format_name = drm_get_format_name(state->fb->pixel_format);
-			DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", format_name);
-			kfree(format_name);
+			DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n",
+			              drm_get_format_name(state->fb->pixel_format,
+			                                  &format_name));
 			return -EINVAL;
 
 		default:
@@ -168,6 +188,14 @@ static int intel_plane_atomic_check(stru
 		}
 	}
 
+	/* CHV ignores the mirror bit when the rotate bit is set :( */
+	if (IS_CHERRYVIEW(dev_priv) &&
+	    state->rotation & DRM_ROTATE_180 &&
+	    state->rotation & DRM_REFLECT_X) {
+		DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n");
+		return -EINVAL;
+	}
+
 	intel_state->base.visible = false;
 	ret = intel_plane->check_plane(plane, crtc_state, intel_state);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_audio.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_audio.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_audio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_audio.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,6 +57,63 @@
  * struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver.
  */
 
+/* DP N/M table */
+#define LC_540M	540000
+#define LC_270M	270000
+#define LC_162M	162000
+
+struct dp_aud_n_m {
+	int sample_rate;
+	int clock;
+	u16 m;
+	u16 n;
+};
+
+/* Values according to DP 1.4 Table 2-104 */
+static const struct dp_aud_n_m dp_aud_n_m[] = {
+	{ 32000, LC_162M, 1024, 10125 },
+	{ 44100, LC_162M, 784, 5625 },
+	{ 48000, LC_162M, 512, 3375 },
+	{ 64000, LC_162M, 2048, 10125 },
+	{ 88200, LC_162M, 1568, 5625 },
+	{ 96000, LC_162M, 1024, 3375 },
+	{ 128000, LC_162M, 4096, 10125 },
+	{ 176400, LC_162M, 3136, 5625 },
+	{ 192000, LC_162M, 2048, 3375 },
+	{ 32000, LC_270M, 1024, 16875 },
+	{ 44100, LC_270M, 784, 9375 },
+	{ 48000, LC_270M, 512, 5625 },
+	{ 64000, LC_270M, 2048, 16875 },
+	{ 88200, LC_270M, 1568, 9375 },
+	{ 96000, LC_270M, 1024, 5625 },
+	{ 128000, LC_270M, 4096, 16875 },
+	{ 176400, LC_270M, 3136, 9375 },
+	{ 192000, LC_270M, 2048, 5625 },
+	{ 32000, LC_540M, 1024, 33750 },
+	{ 44100, LC_540M, 784, 18750 },
+	{ 48000, LC_540M, 512, 11250 },
+	{ 64000, LC_540M, 2048, 33750 },
+	{ 88200, LC_540M, 1568, 18750 },
+	{ 96000, LC_540M, 1024, 11250 },
+	{ 128000, LC_540M, 4096, 33750 },
+	{ 176400, LC_540M, 3136, 18750 },
+	{ 192000, LC_540M, 2048, 11250 },
+};
+
+static const struct dp_aud_n_m *
+audio_config_dp_get_n_m(struct intel_crtc *intel_crtc, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dp_aud_n_m); i++) {
+		if (rate == dp_aud_n_m[i].sample_rate &&
+		    intel_crtc->config->port_clock == dp_aud_n_m[i].clock)
+			return &dp_aud_n_m[i];
+	}
+
+	return NULL;
+}
+
 static const struct {
 	int clock;
 	u32 config;
@@ -81,7 +138,7 @@ static const struct {
 	int clock;
 	int n;
 	int cts;
-} aud_ncts[] = {
+} hdmi_aud_ncts[] = {
 	{ 44100, TMDS_296M, 4459, 234375 },
 	{ 44100, TMDS_297M, 4704, 247500 },
 	{ 48000, TMDS_296M, 5824, 281250 },
@@ -121,45 +178,20 @@ static u32 audio_config_hdmi_pixel_clock
 	return hdmi_audio_clock[i].config;
 }
 
-static int audio_config_get_n(const struct drm_display_mode *mode, int rate)
+static int audio_config_hdmi_get_n(const struct drm_display_mode *adjusted_mode,
+				   int rate)
 {
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) {
-		if ((rate == aud_ncts[i].sample_rate) &&
-			(mode->clock == aud_ncts[i].clock)) {
-			return aud_ncts[i].n;
+	for (i = 0; i < ARRAY_SIZE(hdmi_aud_ncts); i++) {
+		if (rate == hdmi_aud_ncts[i].sample_rate &&
+		    adjusted_mode->crtc_clock == hdmi_aud_ncts[i].clock) {
+			return hdmi_aud_ncts[i].n;
 		}
 	}
 	return 0;
 }
 
-static uint32_t audio_config_setup_n_reg(int n, uint32_t val)
-{
-	int n_low, n_up;
-	uint32_t tmp = val;
-
-	n_low = n & 0xfff;
-	n_up = (n >> 12) & 0xff;
-	tmp &= ~(AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK);
-	tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) |
-			(n_low << AUD_CONFIG_LOWER_N_SHIFT) |
-			AUD_CONFIG_N_PROG_ENABLE);
-	return tmp;
-}
-
-/* check whether N/CTS/M need be set manually */
-static bool audio_rate_need_prog(struct intel_crtc *crtc,
-				 const struct drm_display_mode *mode)
-{
-	if (((mode->clock == TMDS_297M) ||
-		 (mode->clock == TMDS_296M)) &&
-		intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI))
-		return true;
-	else
-		return false;
-}
-
 static bool intel_eld_uptodate(struct drm_connector *connector,
 			       i915_reg_t reg_eldv, uint32_t bits_eldv,
 			       i915_reg_t reg_elda, uint32_t bits_elda,
@@ -245,6 +277,100 @@ static void g4x_audio_codec_enable(struc
 	I915_WRITE(G4X_AUD_CNTL_ST, tmp);
 }
 
+static void
+hsw_dp_audio_config_update(struct intel_crtc *intel_crtc, enum port port,
+			   const struct drm_display_mode *adjusted_mode)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	struct i915_audio_component *acomp = dev_priv->audio_component;
+	int rate = acomp ? acomp->aud_sample_rate[port] : 0;
+	const struct dp_aud_n_m *nm = audio_config_dp_get_n_m(intel_crtc, rate);
+	enum pipe pipe = intel_crtc->pipe;
+	u32 tmp;
+
+	if (nm)
+		DRM_DEBUG_KMS("using Maud %u, Naud %u\n", nm->m, nm->n);
+	else
+		DRM_DEBUG_KMS("using automatic Maud, Naud\n");
+
+	tmp = I915_READ(HSW_AUD_CFG(pipe));
+	tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
+	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
+	tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+	tmp |= AUD_CONFIG_N_VALUE_INDEX;
+
+	if (nm) {
+		tmp &= ~AUD_CONFIG_N_MASK;
+		tmp |= AUD_CONFIG_N(nm->n);
+		tmp |= AUD_CONFIG_N_PROG_ENABLE;
+	}
+
+	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+
+	tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+	tmp &= ~AUD_CONFIG_M_MASK;
+	tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
+	tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
+
+	if (nm) {
+		tmp |= nm->m;
+		tmp |= AUD_M_CTS_M_VALUE_INDEX;
+		tmp |= AUD_M_CTS_M_PROG_ENABLE;
+	}
+
+	I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+}
+
+static void
+hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port,
+			     const struct drm_display_mode *adjusted_mode)
+{
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
+	struct i915_audio_component *acomp = dev_priv->audio_component;
+	int rate = acomp ? acomp->aud_sample_rate[port] : 0;
+	enum pipe pipe = intel_crtc->pipe;
+	int n;
+	u32 tmp;
+
+	tmp = I915_READ(HSW_AUD_CFG(pipe));
+	tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
+	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
+	tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+	tmp |= audio_config_hdmi_pixel_clock(adjusted_mode);
+
+	n = audio_config_hdmi_get_n(adjusted_mode, rate);
+	if (n != 0) {
+		DRM_DEBUG_KMS("using N %d\n", n);
+
+		tmp &= ~AUD_CONFIG_N_MASK;
+		tmp |= AUD_CONFIG_N(n);
+		tmp |= AUD_CONFIG_N_PROG_ENABLE;
+	} else {
+		DRM_DEBUG_KMS("using automatic N\n");
+	}
+
+	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+
+	/*
+	 * Let's disable "Enable CTS or M Prog bit"
+	 * and let HW calculate the value
+	 */
+	tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
+	tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
+	tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
+	I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
+}
+
+static void
+hsw_audio_config_update(struct intel_crtc *intel_crtc, enum port port,
+			const struct drm_display_mode *adjusted_mode)
+{
+	if (intel_crtc_has_dp_encoder(intel_crtc->config))
+		hsw_dp_audio_config_update(intel_crtc, port, adjusted_mode);
+	else
+		hsw_hdmi_audio_config_update(intel_crtc, port, adjusted_mode);
+}
+
 static void hsw_audio_codec_disable(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -276,20 +402,16 @@ static void hsw_audio_codec_disable(stru
 }
 
 static void hsw_audio_codec_enable(struct drm_connector *connector,
-				   struct intel_encoder *encoder,
+				   struct intel_encoder *intel_encoder,
 				   const struct drm_display_mode *adjusted_mode)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
 	enum pipe pipe = intel_crtc->pipe;
-	struct i915_audio_component *acomp = dev_priv->audio_component;
+	enum port port = intel_encoder->port;
 	const uint8_t *eld = connector->eld;
-	struct intel_digital_port *intel_dig_port =
-		enc_to_dig_port(&encoder->base);
-	enum port port = intel_dig_port->port;
 	uint32_t tmp;
 	int len, i;
-	int n, rate;
 
 	DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n",
 		      pipe_name(pipe), drm_eld_size(eld));
@@ -325,42 +447,17 @@ static void hsw_audio_codec_enable(struc
 	I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
 
 	/* Enable timestamps */
-	tmp = I915_READ(HSW_AUD_CFG(pipe));
-	tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
-	tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
-	if (intel_crtc_has_dp_encoder(intel_crtc->config))
-		tmp |= AUD_CONFIG_N_VALUE_INDEX;
-	else
-		tmp |= audio_config_hdmi_pixel_clock(adjusted_mode);
-
-	tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
-	if (audio_rate_need_prog(intel_crtc, adjusted_mode)) {
-		if (!acomp)
-			rate = 0;
-		else if (port >= PORT_A && port <= PORT_E)
-			rate = acomp->aud_sample_rate[port];
-		else {
-			DRM_ERROR("invalid port: %d\n", port);
-			rate = 0;
-		}
-		n = audio_config_get_n(adjusted_mode, rate);
-		if (n != 0)
-			tmp = audio_config_setup_n_reg(n, tmp);
-		else
-			DRM_DEBUG_KMS("no suitable N value is found\n");
-	}
-
-	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+	hsw_audio_config_update(intel_crtc, port, adjusted_mode);
 
 	mutex_unlock(&dev_priv->av_mutex);
 }
 
-static void ilk_audio_codec_disable(struct intel_encoder *encoder)
+static void ilk_audio_codec_disable(struct intel_encoder *intel_encoder)
 {
-	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
-	enum port port = enc_to_dig_port(&encoder->base)->port;
+	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
 	enum pipe pipe = intel_crtc->pipe;
+	enum port port = intel_encoder->port;
 	uint32_t tmp, eldv;
 	i915_reg_t aud_config, aud_cntrl_st2;
 
@@ -400,13 +497,13 @@ static void ilk_audio_codec_disable(stru
 }
 
 static void ilk_audio_codec_enable(struct drm_connector *connector,
-				   struct intel_encoder *encoder,
+				   struct intel_encoder *intel_encoder,
 				   const struct drm_display_mode *adjusted_mode)
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->dev);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
-	enum port port = enc_to_dig_port(&encoder->base)->port;
+	struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc);
 	enum pipe pipe = intel_crtc->pipe;
+	enum port port = intel_encoder->port;
 	uint8_t *eld = connector->eld;
 	uint32_t tmp, eldv;
 	int len, i;
@@ -425,13 +522,13 @@ static void ilk_audio_codec_enable(struc
 	 * infrastructure is not there yet.
 	 */
 
-	if (HAS_PCH_IBX(connector->dev)) {
+	if (HAS_PCH_IBX(dev_priv)) {
 		hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
 		aud_config = IBX_AUD_CFG(pipe);
 		aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
 		aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
-	} else if (IS_VALLEYVIEW(connector->dev) ||
-		   IS_CHERRYVIEW(connector->dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) ||
+		   IS_CHERRYVIEW(dev_priv)) {
 		hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
 		aud_config = VLV_AUD_CFG(pipe);
 		aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
@@ -480,24 +577,26 @@ static void ilk_audio_codec_enable(struc
 /**
  * intel_audio_codec_enable - Enable the audio codec for HD audio
  * @intel_encoder: encoder on which to enable audio
+ * @crtc_state: pointer to the current crtc state.
+ * @conn_state: pointer to the current connector state.
  *
  * The enable sequences may only be performed after enabling the transcoder and
  * port, and after completed link training.
  */
-void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
+void intel_audio_codec_enable(struct intel_encoder *intel_encoder,
+			      const struct intel_crtc_state *crtc_state,
+			      const struct drm_connector_state *conn_state)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
-	struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
-	const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
+	const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
 	struct drm_connector *connector;
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct i915_audio_component *acomp = dev_priv->audio_component;
-	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
-	enum port port = intel_dig_port->port;
+	enum port port = intel_encoder->port;
+	enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
 
-	connector = drm_select_eld(encoder);
-	if (!connector)
+	connector = conn_state->connector;
+	if (!connector || !connector->eld[0])
 		return;
 
 	DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
@@ -508,7 +607,7 @@ void intel_audio_codec_enable(struct int
 
 	/* ELD Conn_Type */
 	connector->eld[5] &= ~(3 << 2);
-	if (intel_crtc_has_dp_encoder(crtc->config))
+	if (intel_crtc_has_dp_encoder(crtc_state))
 		connector->eld[5] |= (1 << 2);
 
 	connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
@@ -518,13 +617,19 @@ void intel_audio_codec_enable(struct int
 						     adjusted_mode);
 
 	mutex_lock(&dev_priv->av_mutex);
-	intel_dig_port->audio_connector = connector;
+	intel_encoder->audio_connector = connector;
+
 	/* referred in audio callbacks */
-	dev_priv->dig_port_map[port] = intel_encoder;
+	dev_priv->av_enc_map[pipe] = intel_encoder;
 	mutex_unlock(&dev_priv->av_mutex);
 
+	/* audio drivers expect pipe = -1 to indicate Non-MST cases */
+	if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
+		pipe = -1;
+
 	if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
-		acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
+		acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
+						 (int) port, (int) pipe);
 }
 
 /**
@@ -537,22 +642,27 @@ void intel_audio_codec_enable(struct int
 void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct i915_audio_component *acomp = dev_priv->audio_component;
-	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
-	enum port port = intel_dig_port->port;
+	enum port port = intel_encoder->port;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
+	enum pipe pipe = crtc->pipe;
 
 	if (dev_priv->display.audio_codec_disable)
 		dev_priv->display.audio_codec_disable(intel_encoder);
 
 	mutex_lock(&dev_priv->av_mutex);
-	intel_dig_port->audio_connector = NULL;
-	dev_priv->dig_port_map[port] = NULL;
+	intel_encoder->audio_connector = NULL;
+	dev_priv->av_enc_map[pipe] = NULL;
 	mutex_unlock(&dev_priv->av_mutex);
 
+	/* audio drivers expect pipe = -1 to indicate Non-MST cases */
+	if (intel_encoder->type != INTEL_OUTPUT_DP_MST)
+		pipe = -1;
+
 	if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
-		acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
+		acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
+						 (int) port, (int) pipe);
 }
 
 /**
@@ -627,74 +737,68 @@ static int i915_audio_component_get_cdcl
 	return dev_priv->cdclk_freq;
 }
 
-static int i915_audio_component_sync_audio_rate(struct device *kdev,
-						int port, int rate)
+static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
+					       int port, int pipe)
+{
+
+	if (WARN_ON(pipe >= I915_MAX_PIPES))
+		return NULL;
+
+	/* MST */
+	if (pipe >= 0)
+		return dev_priv->av_enc_map[pipe];
+
+	/* Non-MST */
+	for_each_pipe(dev_priv, pipe) {
+		struct intel_encoder *encoder;
+
+		encoder = dev_priv->av_enc_map[pipe];
+		if (encoder == NULL)
+			continue;
+
+		if (port == encoder->port)
+			return encoder;
+	}
+
+	return NULL;
+}
+
+static int i915_audio_component_sync_audio_rate(struct device *kdev, int port,
+						int pipe, int rate)
 {
 	struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
 	struct intel_encoder *intel_encoder;
 	struct intel_crtc *crtc;
-	struct drm_display_mode *mode;
+	struct drm_display_mode *adjusted_mode;
 	struct i915_audio_component *acomp = dev_priv->audio_component;
-	enum pipe pipe = INVALID_PIPE;
-	u32 tmp;
-	int n;
 	int err = 0;
 
-	/* HSW, BDW, SKL, KBL need this fix */
-	if (!IS_SKYLAKE(dev_priv) &&
-	    !IS_KABYLAKE(dev_priv) &&
-	    !IS_BROADWELL(dev_priv) &&
-	    !IS_HASWELL(dev_priv))
+	if (!HAS_DDI(dev_priv))
 		return 0;
 
 	i915_audio_component_get_power(kdev);
 	mutex_lock(&dev_priv->av_mutex);
+
 	/* 1. get the pipe */
-	intel_encoder = dev_priv->dig_port_map[port];
-	/* intel_encoder might be NULL for DP MST */
+	intel_encoder = get_saved_enc(dev_priv, port, pipe);
 	if (!intel_encoder || !intel_encoder->base.crtc ||
-	    intel_encoder->type != INTEL_OUTPUT_HDMI) {
-		DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
+	    (intel_encoder->type != INTEL_OUTPUT_HDMI &&
+	     intel_encoder->type != INTEL_OUTPUT_DP)) {
+		DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port));
 		err = -ENODEV;
 		goto unlock;
 	}
+
+	/* pipe passed from the audio driver will be -1 for Non-MST case */
 	crtc = to_intel_crtc(intel_encoder->base.crtc);
 	pipe = crtc->pipe;
-	if (pipe == INVALID_PIPE) {
-		DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
-		err = -ENODEV;
-		goto unlock;
-	}
 
-	DRM_DEBUG_KMS("pipe %c connects port %c\n",
-				  pipe_name(pipe), port_name(port));
-	mode = &crtc->config->base.adjusted_mode;
+	adjusted_mode = &crtc->config->base.adjusted_mode;
 
 	/* port must be valid now, otherwise the pipe will be invalid */
 	acomp->aud_sample_rate[port] = rate;
 
-	/* 2. check whether to set the N/CTS/M manually or not */
-	if (!audio_rate_need_prog(crtc, mode)) {
-		tmp = I915_READ(HSW_AUD_CFG(pipe));
-		tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
-		I915_WRITE(HSW_AUD_CFG(pipe), tmp);
-		goto unlock;
-	}
-
-	n = audio_config_get_n(mode, rate);
-	if (n == 0) {
-		DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n",
-					  port_name(port));
-		tmp = I915_READ(HSW_AUD_CFG(pipe));
-		tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
-		I915_WRITE(HSW_AUD_CFG(pipe), tmp);
-		goto unlock;
-	}
-
-	/* 3. set the N/CTS/M */
-	tmp = I915_READ(HSW_AUD_CFG(pipe));
-	tmp = audio_config_setup_n_reg(n, tmp);
-	I915_WRITE(HSW_AUD_CFG(pipe), tmp);
+	hsw_audio_config_update(crtc, port, adjusted_mode);
 
  unlock:
 	mutex_unlock(&dev_priv->av_mutex);
@@ -703,27 +807,29 @@ static int i915_audio_component_sync_aud
 }
 
 static int i915_audio_component_get_eld(struct device *kdev, int port,
-					bool *enabled,
+					int pipe, bool *enabled,
 					unsigned char *buf, int max_bytes)
 {
 	struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
 	struct intel_encoder *intel_encoder;
-	struct intel_digital_port *intel_dig_port;
 	const u8 *eld;
 	int ret = -EINVAL;
 
 	mutex_lock(&dev_priv->av_mutex);
-	intel_encoder = dev_priv->dig_port_map[port];
-	/* intel_encoder might be NULL for DP MST */
-	if (intel_encoder) {
-		ret = 0;
-		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
-		*enabled = intel_dig_port->audio_connector != NULL;
-		if (*enabled) {
-			eld = intel_dig_port->audio_connector->eld;
-			ret = drm_eld_size(eld);
-			memcpy(buf, eld, min(max_bytes, ret));
-		}
+
+	intel_encoder = get_saved_enc(dev_priv, port, pipe);
+	if (!intel_encoder) {
+		DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port));
+		mutex_unlock(&dev_priv->av_mutex);
+		return ret;
+	}
+
+	ret = 0;
+	*enabled = intel_encoder->audio_connector != NULL;
+	if (*enabled) {
+		eld = intel_encoder->audio_connector->eld;
+		ret = drm_eld_size(eld);
+		memcpy(buf, eld, min(max_bytes, ret));
 	}
 
 	mutex_unlock(&dev_priv->av_mutex);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_bios.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_bios.c	2017-02-12 16:03:20.000000000 -0500
@@ -996,6 +996,10 @@ parse_mipi_sequence(struct drm_i915_priv
 			goto err;
 		}
 
+		/* Log about presence of sequences we won't run. */
+		if (seq_id == MIPI_SEQ_TEAR_ON || seq_id == MIPI_SEQ_TEAR_OFF)
+			DRM_DEBUG_KMS("Unsupported sequence %u\n", seq_id);
+
 		dev_priv->vbt.dsi.sequence[seq_id] = data + index;
 
 		if (sequence->version >= 3)
@@ -1799,6 +1803,55 @@ intel_bios_is_port_hpd_inverted(struct d
 				return true;
 			break;
 		default:
+			break;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * intel_bios_is_lspcon_present - if LSPCON is attached on %port
+ * @dev_priv:	i915 device instance
+ * @port:	port to check
+ *
+ * Return true if LSPCON is present on this port
+ */
+bool
+intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
+				enum port port)
+{
+	int i;
+
+	if (!HAS_LSPCON(dev_priv))
+		return false;
+
+	for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
+		if (!dev_priv->vbt.child_dev[i].common.lspcon)
+			continue;
+
+		switch (dev_priv->vbt.child_dev[i].common.dvo_port) {
+		case DVO_PORT_DPA:
+		case DVO_PORT_HDMIA:
+			if (port == PORT_A)
+				return true;
+			break;
+		case DVO_PORT_DPB:
+		case DVO_PORT_HDMIB:
+			if (port == PORT_B)
+				return true;
+			break;
+		case DVO_PORT_DPC:
+		case DVO_PORT_HDMIC:
+			if (port == PORT_C)
+				return true;
+			break;
+		case DVO_PORT_DPD:
+		case DVO_PORT_HDMID:
+			if (port == PORT_D)
+				return true;
+			break;
+		default:
 			break;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_bios.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_bios.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_bios.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_bios.h	2017-02-12 16:03:20.000000000 -0500
@@ -46,14 +46,20 @@ struct edp_power_seq {
 	u16 t11_t12;
 } __packed;
 
-/* MIPI Sequence Block definitions */
+/*
+ * MIPI Sequence Block definitions
+ *
+ * Note the VBT spec has AssertReset / DeassertReset swapped from their
+ * usual naming, we use the proper names here to avoid confusion when
+ * reading the code.
+ */
 enum mipi_seq {
 	MIPI_SEQ_END = 0,
-	MIPI_SEQ_ASSERT_RESET,
+	MIPI_SEQ_DEASSERT_RESET,	/* Spec says MipiAssertResetPin */
 	MIPI_SEQ_INIT_OTP,
 	MIPI_SEQ_DISPLAY_ON,
 	MIPI_SEQ_DISPLAY_OFF,
-	MIPI_SEQ_DEASSERT_RESET,
+	MIPI_SEQ_ASSERT_RESET,		/* Spec says MipiDeassertResetPin */
 	MIPI_SEQ_BACKLIGHT_ON,		/* sequence block v2+ */
 	MIPI_SEQ_BACKLIGHT_OFF,		/* sequence block v2+ */
 	MIPI_SEQ_TEAR_ON,		/* sequence block v2+ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_breadcrumbs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_breadcrumbs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_breadcrumbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_breadcrumbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -83,16 +83,18 @@ static void irq_enable(struct intel_engi
 	 */
 	engine->breadcrumbs.irq_posted = true;
 
-	spin_lock_irq(&engine->i915->irq_lock);
+	/* Caller disables interrupts */
+	spin_lock(&engine->i915->irq_lock);
 	engine->irq_enable(engine);
-	spin_unlock_irq(&engine->i915->irq_lock);
+	spin_unlock(&engine->i915->irq_lock);
 }
 
 static void irq_disable(struct intel_engine_cs *engine)
 {
-	spin_lock_irq(&engine->i915->irq_lock);
+	/* Caller disables interrupts */
+	spin_lock(&engine->i915->irq_lock);
 	engine->irq_disable(engine);
-	spin_unlock_irq(&engine->i915->irq_lock);
+	spin_unlock(&engine->i915->irq_lock);
 
 	engine->breadcrumbs.irq_posted = false;
 }
@@ -293,9 +295,9 @@ bool intel_engine_add_wait(struct intel_
 	struct intel_breadcrumbs *b = &engine->breadcrumbs;
 	bool first;
 
-	spin_lock(&b->lock);
+	spin_lock_irq(&b->lock);
 	first = __intel_engine_add_wait(engine, wait);
-	spin_unlock(&b->lock);
+	spin_unlock_irq(&b->lock);
 
 	return first;
 }
@@ -326,7 +328,7 @@ void intel_engine_remove_wait(struct int
 	if (RB_EMPTY_NODE(&wait->node))
 		return;
 
-	spin_lock(&b->lock);
+	spin_lock_irq(&b->lock);
 
 	if (RB_EMPTY_NODE(&wait->node))
 		goto out_unlock;
@@ -400,7 +402,7 @@ out_unlock:
 	GEM_BUG_ON(rb_first(&b->waiters) !=
 		   (b->first_wait ? &b->first_wait->node : NULL));
 	GEM_BUG_ON(!rcu_access_pointer(b->irq_seqno_bh) ^ RB_EMPTY_ROOT(&b->waiters));
-	spin_unlock(&b->lock);
+	spin_unlock_irq(&b->lock);
 }
 
 static bool signal_complete(struct drm_i915_gem_request *request)
@@ -464,7 +466,7 @@ static int intel_breadcrumbs_signaler(vo
 						 &request->signaling.wait);
 
 			local_bh_disable();
-			fence_signal(&request->fence);
+			dma_fence_signal(&request->fence);
 			local_bh_enable(); /* kick start the tasklets */
 
 			/* Find the next oldest signal. Note that as we have
@@ -473,14 +475,14 @@ static int intel_breadcrumbs_signaler(vo
 			 * we just completed - so double check we are still
 			 * the oldest before picking the next one.
 			 */
-			spin_lock(&b->lock);
+			spin_lock_irq(&b->lock);
 			if (request == b->first_signal) {
 				struct rb_node *rb =
 					rb_next(&request->signaling.node);
 				b->first_signal = rb ? to_signaler(rb) : NULL;
 			}
 			rb_erase(&request->signaling.node, &b->signals);
-			spin_unlock(&b->lock);
+			spin_unlock_irq(&b->lock);
 
 			i915_gem_request_put(request);
 		} else {
@@ -502,11 +504,20 @@ void intel_engine_enable_signaling(struc
 	struct rb_node *parent, **p;
 	bool first, wakeup;
 
-	/* locked by fence_enable_sw_signaling() */
+	/* Note that we may be called from an interrupt handler on another
+	 * device (e.g. nouveau signaling a fence completion causing us
+	 * to submit a request, and so enable signaling). As such,
+	 * we need to make sure that all other users of b->lock protect
+	 * against interrupts, i.e. use spin_lock_irqsave.
+	 */
+
+	/* locked by dma_fence_enable_sw_signaling() (irqsafe fence->lock) */
 	assert_spin_locked(&request->lock);
+	if (!request->global_seqno)
+		return;
 
 	request->signaling.wait.tsk = b->signaler;
-	request->signaling.wait.seqno = request->fence.seqno;
+	request->signaling.wait.seqno = request->global_seqno;
 	i915_gem_request_get(request);
 
 	spin_lock(&b->lock);
@@ -530,8 +541,8 @@ void intel_engine_enable_signaling(struc
 	p = &b->signals.rb_node;
 	while (*p) {
 		parent = *p;
-		if (i915_seqno_passed(request->fence.seqno,
-				      to_signaler(parent)->fence.seqno)) {
+		if (i915_seqno_passed(request->global_seqno,
+				      to_signaler(parent)->global_seqno)) {
 			p = &parent->rb_right;
 			first = false;
 		} else {
@@ -592,7 +603,7 @@ void intel_engine_reset_breadcrumbs(stru
 	struct intel_breadcrumbs *b = &engine->breadcrumbs;
 
 	cancel_fake_irq(engine);
-	spin_lock(&b->lock);
+	spin_lock_irq(&b->lock);
 
 	__intel_breadcrumbs_disable_irq(b);
 	if (intel_engine_has_waiter(engine)) {
@@ -605,7 +616,7 @@ void intel_engine_reset_breadcrumbs(stru
 		irq_disable(engine);
 	}
 
-	spin_unlock(&b->lock);
+	spin_unlock_irq(&b->lock);
 }
 
 void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine)
@@ -618,33 +629,28 @@ void intel_engine_fini_breadcrumbs(struc
 	cancel_fake_irq(engine);
 }
 
-unsigned int intel_kick_waiters(struct drm_i915_private *i915)
+unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	unsigned int mask = 0;
 
-	/* To avoid the task_struct disappearing beneath us as we wake up
-	 * the process, we must first inspect the task_struct->state under the
-	 * RCU lock, i.e. as we call wake_up_process() we must be holding the
-	 * rcu_read_lock().
-	 */
-	for_each_engine(engine, i915)
-		if (unlikely(intel_engine_wakeup(engine)))
-			mask |= intel_engine_flag(engine);
+	for_each_engine(engine, i915, id) {
+		struct intel_breadcrumbs *b = &engine->breadcrumbs;
 
-	return mask;
-}
+		spin_lock_irq(&b->lock);
 
-unsigned int intel_kick_signalers(struct drm_i915_private *i915)
-{
-	struct intel_engine_cs *engine;
-	unsigned int mask = 0;
+		if (b->first_wait) {
+			wake_up_process(b->first_wait->tsk);
+			mask |= intel_engine_flag(engine);
+		}
 
-	for_each_engine(engine, i915) {
-		if (unlikely(READ_ONCE(engine->breadcrumbs.first_signal))) {
-			wake_up_process(engine->breadcrumbs.signaler);
+		if (b->first_signal) {
+			wake_up_process(b->signaler);
 			mask |= intel_engine_flag(engine);
 		}
+
+		spin_unlock_irq(&b->lock);
 	}
 
 	return mask;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_color.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_color.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_color.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_color.c	2017-02-12 16:03:20.000000000 -0500
@@ -95,8 +95,7 @@ static void ctm_mult_by_limited(uint64_t
 static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
 {
 	struct drm_crtc *crtc = crtc_state->crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int i, pipe = intel_crtc->pipe;
 	uint16_t coeffs[9] = { 0, };
@@ -180,7 +179,7 @@ static void i9xx_load_csc_matrix(struct
 	I915_WRITE(PIPE_CSC_PREOFF_ME(pipe), 0);
 	I915_WRITE(PIPE_CSC_PREOFF_LO(pipe), 0);
 
-	if (INTEL_INFO(dev)->gen > 6) {
+	if (INTEL_GEN(dev_priv) > 6) {
 		uint16_t postoff = 0;
 
 		if (intel_crtc_state->limited_color_range)
@@ -273,7 +272,7 @@ static void i9xx_load_luts_internal(stru
 	enum pipe pipe = intel_crtc->pipe;
 	int i;
 
-	if (HAS_GMCH_DISPLAY(dev)) {
+	if (HAS_GMCH_DISPLAY(dev_priv)) {
 		if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
 			assert_dsi_pll_enabled(dev_priv);
 		else
@@ -288,7 +287,7 @@ static void i9xx_load_luts_internal(stru
 				(drm_color_lut_extract(lut[i].green, 8) << 8) |
 				drm_color_lut_extract(lut[i].blue, 8);
 
-			if (HAS_GMCH_DISPLAY(dev))
+			if (HAS_GMCH_DISPLAY(dev_priv))
 				I915_WRITE(PALETTE(pipe, i), word);
 			else
 				I915_WRITE(LGC_PALETTE(pipe, i), word);
@@ -297,7 +296,7 @@ static void i9xx_load_luts_internal(stru
 		for (i = 0; i < 256; i++) {
 			uint32_t word = (i << 16) | (i << 8) | i;
 
-			if (HAS_GMCH_DISPLAY(dev))
+			if (HAS_GMCH_DISPLAY(dev_priv))
 				I915_WRITE(PALETTE(pipe, i), word);
 			else
 				I915_WRITE(LGC_PALETTE(pipe, i), word);
@@ -326,7 +325,7 @@ static void haswell_load_luts(struct drm
 	 * Workaround : Do not read or write the pipe palette/gamma data while
 	 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled.
 	 */
-	if (IS_HASWELL(dev) && intel_crtc_state->ips_enabled &&
+	if (IS_HASWELL(dev_priv) && intel_crtc_state->ips_enabled &&
 	    (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) {
 		hsw_disable_ips(intel_crtc);
 		reenable_ips = true;
@@ -345,11 +344,10 @@ static void haswell_load_luts(struct drm
 static void broadwell_load_luts(struct drm_crtc_state *state)
 {
 	struct drm_crtc *crtc = state->crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
-	uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+	uint32_t i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
 
 	if (crtc_state_is_legacy(state)) {
 		haswell_load_luts(state);
@@ -428,8 +426,7 @@ static void broadwell_load_luts(struct d
 static void cherryview_load_luts(struct drm_crtc_state *state)
 {
 	struct drm_crtc *crtc = state->crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	enum pipe pipe = to_intel_crtc(crtc)->pipe;
 	struct drm_color_lut *lut;
 	uint32_t i, lut_size;
@@ -446,7 +443,7 @@ static void cherryview_load_luts(struct
 
 	if (state->degamma_lut) {
 		lut = (struct drm_color_lut *) state->degamma_lut->data;
-		lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
+		lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
 		for (i = 0; i < lut_size; i++) {
 			/* Write LUT in U0.14 format. */
 			word0 =
@@ -461,7 +458,7 @@ static void cherryview_load_luts(struct
 
 	if (state->gamma_lut) {
 		lut = (struct drm_color_lut *) state->gamma_lut->data;
-		lut_size = INTEL_INFO(dev)->color.gamma_lut_size;
+		lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
 		for (i = 0; i < lut_size; i++) {
 			/* Write LUT in U0.10 format. */
 			word0 =
@@ -497,12 +494,12 @@ void intel_color_load_luts(struct drm_cr
 int intel_color_check(struct drm_crtc *crtc,
 		      struct drm_crtc_state *crtc_state)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	size_t gamma_length, degamma_length;
 
-	degamma_length = INTEL_INFO(dev)->color.degamma_lut_size *
+	degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size *
 		sizeof(struct drm_color_lut);
-	gamma_length = INTEL_INFO(dev)->color.gamma_lut_size *
+	gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size *
 		sizeof(struct drm_color_lut);
 
 	/*
@@ -529,19 +526,18 @@ int intel_color_check(struct drm_crtc *c
 
 void intel_color_init(struct drm_crtc *crtc)
 {
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
-	if (IS_CHERRYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev_priv)) {
 		dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix;
 		dev_priv->display.load_luts = cherryview_load_luts;
-	} else if (IS_HASWELL(dev)) {
+	} else if (IS_HASWELL(dev_priv)) {
 		dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
 		dev_priv->display.load_luts = haswell_load_luts;
-	} else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) ||
-		   IS_BROXTON(dev) || IS_KABYLAKE(dev)) {
+	} else if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv) ||
+		   IS_BROXTON(dev_priv) || IS_KABYLAKE(dev_priv)) {
 		dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix;
 		dev_priv->display.load_luts = broadwell_load_luts;
 	} else {
@@ -549,10 +545,10 @@ void intel_color_init(struct drm_crtc *c
 	}
 
 	/* Enable color management support when we have degamma & gamma LUTs. */
-	if (INTEL_INFO(dev)->color.degamma_lut_size != 0 &&
-	    INTEL_INFO(dev)->color.gamma_lut_size != 0)
+	if (INTEL_INFO(dev_priv)->color.degamma_lut_size != 0 &&
+	    INTEL_INFO(dev_priv)->color.gamma_lut_size != 0)
 		drm_crtc_enable_color_mgmt(crtc,
-					INTEL_INFO(dev)->color.degamma_lut_size,
-					true,
-					INTEL_INFO(dev)->color.gamma_lut_size);
+					   INTEL_INFO(dev_priv)->color.degamma_lut_size,
+					   true,
+					   INTEL_INFO(dev_priv)->color.gamma_lut_size);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_crt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_crt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_crt.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,7 @@ static bool intel_crt_get_hw_state(struc
 	if (!(tmp & ADPA_DAC_ENABLE))
 		goto out;
 
-	if (HAS_PCH_CPT(dev))
+	if (HAS_PCH_CPT(dev_priv))
 		*pipe = PORT_TO_PIPE_CPT(tmp);
 	else
 		*pipe = PORT_TO_PIPE(tmp);
@@ -147,14 +147,13 @@ static void intel_crt_set_dpms(struct in
 			       struct intel_crtc_state *crtc_state,
 			       int mode)
 {
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_crt *crt = intel_encoder_to_crt(encoder);
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
 	u32 adpa;
 
-	if (INTEL_INFO(dev)->gen >= 5)
+	if (INTEL_GEN(dev_priv) >= 5)
 		adpa = ADPA_HOTPLUG_BITS;
 	else
 		adpa = 0;
@@ -165,16 +164,16 @@ static void intel_crt_set_dpms(struct in
 		adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
 	/* For CPT allow 3 pipe config, for others just use A or B */
-	if (HAS_PCH_LPT(dev))
+	if (HAS_PCH_LPT(dev_priv))
 		; /* Those bits don't exist here */
-	else if (HAS_PCH_CPT(dev))
+	else if (HAS_PCH_CPT(dev_priv))
 		adpa |= PORT_TRANS_SEL_CPT(crtc->pipe);
 	else if (crtc->pipe == 0)
 		adpa |= ADPA_PIPE_A_SELECT;
 	else
 		adpa |= ADPA_PIPE_B_SELECT;
 
-	if (!HAS_PCH_SPLIT(dev))
+	if (!HAS_PCH_SPLIT(dev_priv))
 		I915_WRITE(BCLRPAT(crtc->pipe), 0);
 
 	switch (mode) {
@@ -241,7 +240,8 @@ intel_crt_mode_valid(struct drm_connecto
 		     struct drm_display_mode *mode)
 {
 	struct drm_device *dev = connector->dev;
-	int max_dotclk = to_i915(dev)->max_dotclk_freq;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	int max_dotclk = dev_priv->max_dotclk_freq;
 	int max_clock;
 
 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -250,15 +250,15 @@ intel_crt_mode_valid(struct drm_connecto
 	if (mode->clock < 25000)
 		return MODE_CLOCK_LOW;
 
-	if (HAS_PCH_LPT(dev))
+	if (HAS_PCH_LPT(dev_priv))
 		max_clock = 180000;
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev_priv))
 		/*
 		 * 270 MHz due to current DPLL limits,
 		 * DAC limit supposedly 355 MHz.
 		 */
 		max_clock = 270000;
-	else if (IS_GEN3(dev) || IS_GEN4(dev))
+	else if (IS_GEN3(dev_priv) || IS_GEN4(dev_priv))
 		max_clock = 400000;
 	else
 		max_clock = 350000;
@@ -269,7 +269,7 @@ intel_crt_mode_valid(struct drm_connecto
 		return MODE_CLOCK_HIGH;
 
 	/* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */
-	if (HAS_PCH_LPT(dev) &&
+	if (HAS_PCH_LPT(dev_priv) &&
 	    (ironlake_get_lanes_required(mode->clock, 270000, 24) > 2))
 		return MODE_CLOCK_HIGH;
 
@@ -280,13 +280,13 @@ static bool intel_crt_compute_config(str
 				     struct intel_crtc_state *pipe_config,
 				     struct drm_connector_state *conn_state)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
 	/* LPT FDI RX only supports 8bpc. */
-	if (HAS_PCH_LPT(dev)) {
+	if (HAS_PCH_LPT(dev_priv)) {
 		if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
 			DRM_DEBUG_KMS("LPT only supports 24bpp\n");
 			return false;
@@ -296,7 +296,7 @@ static bool intel_crt_compute_config(str
 	}
 
 	/* FDI must always be 2.7 GHz */
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev_priv))
 		pipe_config->port_clock = 135000 * 2;
 
 	return true;
@@ -312,7 +312,7 @@ static bool intel_ironlake_crt_detect_ho
 
 	/* The first time through, trigger an explicit detection cycle */
 	if (crt->force_hotplug_required) {
-		bool turn_off_dac = HAS_PCH_SPLIT(dev);
+		bool turn_off_dac = HAS_PCH_SPLIT(dev_priv);
 		u32 save_adpa;
 
 		crt->force_hotplug_required = 0;
@@ -419,10 +419,10 @@ static bool intel_crt_detect_hotplug(str
 	bool ret = false;
 	int i, tries = 0;
 
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		return intel_ironlake_crt_detect_hotplug(connector);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv))
 		return valleyview_crt_detect_hotplug(connector);
 
 	/*
@@ -430,7 +430,7 @@ static bool intel_crt_detect_hotplug(str
 	 * to get a reliable result.
 	 */
 
-	if (IS_G4X(dev) && !IS_GM45(dev))
+	if (IS_G4X(dev_priv) && !IS_GM45(dev_priv))
 		tries = 2;
 	else
 		tries = 1;
@@ -499,6 +499,7 @@ static bool intel_crt_detect_ddc(struct
 	struct drm_i915_private *dev_priv = to_i915(crt->base.base.dev);
 	struct edid *edid;
 	struct i2c_adapter *i2c;
+	bool ret = false;
 
 	BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
 
@@ -515,17 +516,17 @@ static bool intel_crt_detect_ddc(struct
 		 */
 		if (!is_digital) {
 			DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
-			return true;
+			ret = true;
+		} else {
+			DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
 		}
-
-		DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
 	} else {
 		DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n");
 	}
 
 	kfree(edid);
 
-	return false;
+	return ret;
 }
 
 static enum drm_connector_status
@@ -566,13 +567,13 @@ intel_crt_load_detect(struct intel_crt *
 	/* Set the border color to purple. */
 	I915_WRITE(bclrpat_reg, 0x500050);
 
-	if (!IS_GEN2(dev)) {
+	if (!IS_GEN2(dev_priv)) {
 		uint32_t pipeconf = I915_READ(pipeconf_reg);
 		I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
 		POSTING_READ(pipeconf_reg);
 		/* Wait for next Vblank to substitue
 		 * border color for Color info */
-		intel_wait_for_vblank(dev, pipe);
+		intel_wait_for_vblank(dev_priv, pipe);
 		st00 = I915_READ8(_VGA_MSR_WRITE);
 		status = ((st00 & (1 << 4)) != 0) ?
 			connector_status_connected :
@@ -643,11 +644,36 @@ intel_crt_load_detect(struct intel_crt *
 	return status;
 }
 
+static int intel_spurious_crt_detect_dmi_callback(const struct dmi_system_id *id)
+{
+	DRM_DEBUG_DRIVER("Skipping CRT detection for %s\n", id->ident);
+	return 1;
+}
+
+static const struct dmi_system_id intel_spurious_crt_detect[] = {
+	{
+		.callback = intel_spurious_crt_detect_dmi_callback,
+		.ident = "ACER ZGB",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
+		},
+	},
+	{
+		.callback = intel_spurious_crt_detect_dmi_callback,
+		.ident = "Intel DZ77BH-55K",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "DZ77BH-55K"),
+		},
+	},
+	{ }
+};
+
 static enum drm_connector_status
 intel_crt_detect(struct drm_connector *connector, bool force)
 {
-	struct drm_device *dev = connector->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(connector->dev);
 	struct intel_crt *crt = intel_attached_crt(connector);
 	struct intel_encoder *intel_encoder = &crt->base;
 	enum intel_display_power_domain power_domain;
@@ -659,10 +685,14 @@ intel_crt_detect(struct drm_connector *c
 		      connector->base.id, connector->name,
 		      force);
 
+	/* Skip machines without VGA that falsely report hotplug events */
+	if (dmi_check_system(intel_spurious_crt_detect))
+		return connector_status_disconnected;
+
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_get(dev_priv, power_domain);
 
-	if (I915_HAS_HOTPLUG(dev)) {
+	if (I915_HAS_HOTPLUG(dev_priv)) {
 		/* We can not rely on the HPD pin always being correctly wired
 		 * up, for example many KVM do not pass it through, and so
 		 * only trust an assertion that the monitor is connected.
@@ -684,7 +714,7 @@ intel_crt_detect(struct drm_connector *c
 	 * broken monitor (without edid) to work behind a broken kvm (that fails
 	 * to have the right resistors for HP detection) needs to fix this up.
 	 * For now just bail out. */
-	if (I915_HAS_HOTPLUG(dev) && !i915.load_detect_test) {
+	if (I915_HAS_HOTPLUG(dev_priv) && !i915.load_detect_test) {
 		status = connector_status_disconnected;
 		goto out;
 	}
@@ -700,7 +730,7 @@ intel_crt_detect(struct drm_connector *c
 	if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
 		if (intel_crt_detect_ddc(connector))
 			status = connector_status_connected;
-		else if (INTEL_INFO(dev)->gen < 4)
+		else if (INTEL_GEN(dev_priv) < 4)
 			status = intel_crt_load_detect(crt,
 				to_intel_crtc(connector->state->crtc)->pipe);
 		else if (i915.load_detect_test)
@@ -740,7 +770,7 @@ static int intel_crt_get_modes(struct dr
 
 	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
 	ret = intel_crt_ddc_get_modes(connector, i2c);
-	if (ret || !IS_G4X(dev))
+	if (ret || !IS_G4X(dev_priv))
 		goto out;
 
 	/* Try to probe digital port for output in DVI-I -> VGA mode. */
@@ -762,11 +792,10 @@ static int intel_crt_set_property(struct
 
 void intel_crt_reset(struct drm_encoder *encoder)
 {
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct intel_crt *crt = intel_encoder_to_crt(to_intel_encoder(encoder));
 
-	if (INTEL_INFO(dev)->gen >= 5) {
+	if (INTEL_GEN(dev_priv) >= 5) {
 		u32 adpa;
 
 		adpa = I915_READ(crt->adpa_reg);
@@ -808,32 +837,6 @@ static const struct drm_encoder_funcs in
 	.destroy = intel_encoder_destroy,
 };
 
-static int intel_no_crt_dmi_callback(const struct dmi_system_id *id)
-{
-	DRM_INFO("Skipping CRT initialization for %s\n", id->ident);
-	return 1;
-}
-
-static const struct dmi_system_id intel_no_crt[] = {
-	{
-		.callback = intel_no_crt_dmi_callback,
-		.ident = "ACER ZGB",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
-		},
-	},
-	{
-		.callback = intel_no_crt_dmi_callback,
-		.ident = "DELL XPS 8700",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"),
-		},
-	},
-	{ }
-};
-
 void intel_crt_init(struct drm_device *dev)
 {
 	struct drm_connector *connector;
@@ -843,13 +846,9 @@ void intel_crt_init(struct drm_device *d
 	i915_reg_t adpa_reg;
 	u32 adpa;
 
-	/* Skip machines without VGA that falsely report hotplug events */
-	if (dmi_check_system(intel_no_crt))
-		return;
-
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		adpa_reg = PCH_ADPA;
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev_priv))
 		adpa_reg = VLV_ADPA;
 	else
 		adpa_reg = ADPA;
@@ -893,12 +892,12 @@ void intel_crt_init(struct drm_device *d
 
 	crt->base.type = INTEL_OUTPUT_ANALOG;
 	crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI);
-	if (IS_I830(dev))
+	if (IS_I830(dev_priv))
 		crt->base.crtc_mask = (1 << 0);
 	else
 		crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		connector->interlace_allowed = 0;
 	else
 		connector->interlace_allowed = 1;
@@ -907,20 +906,23 @@ void intel_crt_init(struct drm_device *d
 	crt->adpa_reg = adpa_reg;
 
 	crt->base.compute_config = intel_crt_compute_config;
-	if (HAS_PCH_SPLIT(dev)) {
+	if (HAS_PCH_SPLIT(dev_priv)) {
 		crt->base.disable = pch_disable_crt;
 		crt->base.post_disable = pch_post_disable_crt;
 	} else {
 		crt->base.disable = intel_disable_crt;
 	}
 	crt->base.enable = intel_enable_crt;
-	if (I915_HAS_HOTPLUG(dev))
+	if (I915_HAS_HOTPLUG(dev_priv) &&
+	    !dmi_check_system(intel_spurious_crt_detect))
 		crt->base.hpd_pin = HPD_CRT;
-	if (HAS_DDI(dev)) {
+	if (HAS_DDI(dev_priv)) {
+		crt->base.port = PORT_E;
 		crt->base.get_config = hsw_crt_get_config;
 		crt->base.get_hw_state = intel_ddi_get_hw_state;
 		crt->base.post_disable = hsw_post_disable_crt;
 	} else {
+		crt->base.port = PORT_NONE;
 		crt->base.get_config = intel_crt_get_config;
 		crt->base.get_hw_state = intel_crt_get_hw_state;
 	}
@@ -928,7 +930,7 @@ void intel_crt_init(struct drm_device *d
 
 	drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
 
-	if (!I915_HAS_HOTPLUG(dev))
+	if (!I915_HAS_HOTPLUG(dev_priv))
 		intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
 	/*
@@ -941,7 +943,7 @@ void intel_crt_init(struct drm_device *d
 	 * polarity and link reversal bits or not, instead of relying on the
 	 * BIOS.
 	 */
-	if (HAS_PCH_LPT(dev)) {
+	if (HAS_PCH_LPT(dev_priv)) {
 		u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
 				 FDI_RX_LINK_REVERSAL_OVERRIDE;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_csr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_csr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_csr.c	2016-12-11 17:42:01.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_csr.c	2017-02-12 17:25:14.000000000 -0500
@@ -168,12 +168,6 @@ struct stepping_info {
 	char substepping;
 };
 
-static const struct stepping_info kbl_stepping_info[] = {
-	{'A', '0'}, {'B', '0'}, {'C', '0'},
-	{'D', '0'}, {'E', '0'}, {'F', '0'},
-	{'G', '0'}, {'H', '0'}, {'I', '0'},
-};
-
 static const struct stepping_info skl_stepping_info[] = {
 	{'A', '0'}, {'B', '0'}, {'C', '0'},
 	{'D', '0'}, {'E', '0'}, {'F', '0'},
@@ -194,10 +188,7 @@ intel_get_stepping_info(struct drm_i915_
 	const struct stepping_info *si;
 	unsigned int size;
 
-	if (IS_KABYLAKE(dev_priv)) {
-		size = ARRAY_SIZE(kbl_stepping_info);
-		si = kbl_stepping_info;
-	} else if (IS_SKYLAKE(dev_priv)) {
+	if (IS_SKYLAKE(dev_priv)) {
 		size = ARRAY_SIZE(skl_stepping_info);
 		si = skl_stepping_info;
 	} else if (IS_BROXTON(dev_priv)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_ddi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_ddi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_ddi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_ddi.c	2017-02-12 16:03:20.000000000 -0500
@@ -167,8 +167,47 @@ static const struct ddi_buf_trans skl_y_
 	{ 0x80005012, 0x000000C0, 0x3 },
 };
 
+/* Kabylake H and S */
+static const struct ddi_buf_trans kbl_ddi_translations_dp[] = {
+	{ 0x00002016, 0x000000A0, 0x0 },
+	{ 0x00005012, 0x0000009B, 0x0 },
+	{ 0x00007011, 0x00000088, 0x0 },
+	{ 0x80009010, 0x000000C0, 0x1 },
+	{ 0x00002016, 0x0000009B, 0x0 },
+	{ 0x00005012, 0x00000088, 0x0 },
+	{ 0x80007011, 0x000000C0, 0x1 },
+	{ 0x00002016, 0x00000097, 0x0 },
+	{ 0x80005012, 0x000000C0, 0x1 },
+};
+
+/* Kabylake U */
+static const struct ddi_buf_trans kbl_u_ddi_translations_dp[] = {
+	{ 0x0000201B, 0x000000A1, 0x0 },
+	{ 0x00005012, 0x00000088, 0x0 },
+	{ 0x80007011, 0x000000CD, 0x3 },
+	{ 0x80009010, 0x000000C0, 0x3 },
+	{ 0x0000201B, 0x0000009D, 0x0 },
+	{ 0x80005012, 0x000000C0, 0x3 },
+	{ 0x80007011, 0x000000C0, 0x3 },
+	{ 0x00002016, 0x0000004F, 0x0 },
+	{ 0x80005012, 0x000000C0, 0x3 },
+};
+
+/* Kabylake Y */
+static const struct ddi_buf_trans kbl_y_ddi_translations_dp[] = {
+	{ 0x00001017, 0x000000A1, 0x0 },
+	{ 0x00005012, 0x00000088, 0x0 },
+	{ 0x80007011, 0x000000CD, 0x3 },
+	{ 0x8000800F, 0x000000C0, 0x3 },
+	{ 0x00001017, 0x0000009D, 0x0 },
+	{ 0x80005012, 0x000000C0, 0x3 },
+	{ 0x80007011, 0x000000C0, 0x3 },
+	{ 0x00001017, 0x0000004C, 0x0 },
+	{ 0x80005012, 0x000000C0, 0x3 },
+};
+
 /*
- * Skylake H and S
+ * Skylake/Kabylake H and S
  * eDP 1.4 low vswing translation parameters
  */
 static const struct ddi_buf_trans skl_ddi_translations_edp[] = {
@@ -185,7 +224,7 @@ static const struct ddi_buf_trans skl_dd
 };
 
 /*
- * Skylake U
+ * Skylake/Kabylake U
  * eDP 1.4 low vswing translation parameters
  */
 static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = {
@@ -202,7 +241,7 @@ static const struct ddi_buf_trans skl_u_
 };
 
 /*
- * Skylake Y
+ * Skylake/Kabylake Y
  * eDP 1.4 low vswing translation parameters
  */
 static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = {
@@ -218,7 +257,7 @@ static const struct ddi_buf_trans skl_y_
 	{ 0x00000018, 0x0000008A, 0x0 },
 };
 
-/* Skylake U, H and S */
+/* Skylake/Kabylake U, H and S */
 static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
 	{ 0x00000018, 0x000000AC, 0x0 },
 	{ 0x00005012, 0x0000009D, 0x0 },
@@ -233,7 +272,7 @@ static const struct ddi_buf_trans skl_dd
 	{ 0x80000018, 0x000000C0, 0x1 },
 };
 
-/* Skylake Y */
+/* Skylake/Kabylake Y */
 static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = {
 	{ 0x00000018, 0x000000A1, 0x0 },
 	{ 0x00005012, 0x000000DF, 0x0 },
@@ -334,10 +373,10 @@ bdw_get_buf_trans_edp(struct drm_i915_pr
 static const struct ddi_buf_trans *
 skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
 {
-	if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) {
+	if (IS_SKL_ULX(dev_priv)) {
 		*n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp);
 		return skl_y_ddi_translations_dp;
-	} else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) {
+	} else if (IS_SKL_ULT(dev_priv)) {
 		*n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp);
 		return skl_u_ddi_translations_dp;
 	} else {
@@ -347,6 +386,21 @@ skl_get_buf_trans_dp(struct drm_i915_pri
 }
 
 static const struct ddi_buf_trans *
+kbl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
+{
+	if (IS_KBL_ULX(dev_priv)) {
+		*n_entries = ARRAY_SIZE(kbl_y_ddi_translations_dp);
+		return kbl_y_ddi_translations_dp;
+	} else if (IS_KBL_ULT(dev_priv)) {
+		*n_entries = ARRAY_SIZE(kbl_u_ddi_translations_dp);
+		return kbl_u_ddi_translations_dp;
+	} else {
+		*n_entries = ARRAY_SIZE(kbl_ddi_translations_dp);
+		return kbl_ddi_translations_dp;
+	}
+}
+
+static const struct ddi_buf_trans *
 skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
 {
 	if (dev_priv->vbt.edp.low_vswing) {
@@ -362,7 +416,10 @@ skl_get_buf_trans_edp(struct drm_i915_pr
 		}
 	}
 
-	return skl_get_buf_trans_dp(dev_priv, n_entries);
+	if (IS_KABYLAKE(dev_priv))
+		return kbl_get_buf_trans_dp(dev_priv, n_entries);
+	else
+		return skl_get_buf_trans_dp(dev_priv, n_entries);
 }
 
 static const struct ddi_buf_trans *
@@ -430,21 +487,18 @@ void intel_prepare_dp_ddi_buffers(struct
 	if (IS_BROXTON(dev_priv))
 		return;
 
-	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+	if (IS_KABYLAKE(dev_priv)) {
+		ddi_translations_fdi = NULL;
+		ddi_translations_dp =
+				kbl_get_buf_trans_dp(dev_priv, &n_dp_entries);
+		ddi_translations_edp =
+				skl_get_buf_trans_edp(dev_priv, &n_edp_entries);
+	} else if (IS_SKYLAKE(dev_priv)) {
 		ddi_translations_fdi = NULL;
 		ddi_translations_dp =
 				skl_get_buf_trans_dp(dev_priv, &n_dp_entries);
 		ddi_translations_edp =
 				skl_get_buf_trans_edp(dev_priv, &n_edp_entries);
-
-		/* If we're boosting the current, set bit 31 of trans1 */
-		if (dev_priv->vbt.ddi_port_info[port].dp_boost_level)
-			iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
-
-		if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP &&
-			    port != PORT_A && port != PORT_E &&
-			    n_edp_entries > 9))
-			n_edp_entries = 9;
 	} else if (IS_BROADWELL(dev_priv)) {
 		ddi_translations_fdi = bdw_ddi_translations_fdi;
 		ddi_translations_dp = bdw_ddi_translations_dp;
@@ -464,6 +518,17 @@ void intel_prepare_dp_ddi_buffers(struct
 		n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
 	}
 
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+		/* If we're boosting the current, set bit 31 of trans1 */
+		if (dev_priv->vbt.ddi_port_info[port].dp_boost_level)
+			iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
+
+		if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP &&
+			    port != PORT_A && port != PORT_E &&
+			    n_edp_entries > 9))
+			n_edp_entries = 9;
+	}
+
 	switch (encoder->type) {
 	case INTEL_OUTPUT_EDP:
 		ddi_translations = ddi_translations_edp;
@@ -1020,13 +1085,13 @@ static void bxt_ddi_clock_get(struct int
 void intel_ddi_clock_get(struct intel_encoder *encoder,
 			 struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
-	if (INTEL_INFO(dev)->gen <= 8)
+	if (INTEL_GEN(dev_priv) <= 8)
 		hsw_ddi_clock_get(encoder, pipe_config);
-	else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+	else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		skl_ddi_clock_get(encoder, pipe_config);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		bxt_ddi_clock_get(encoder, pipe_config);
 }
 
@@ -1081,14 +1146,14 @@ bxt_ddi_pll_select(struct intel_crtc *in
 bool intel_ddi_pll_select(struct intel_crtc *intel_crtc,
 			  struct intel_crtc_state *crtc_state)
 {
-	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
 	struct intel_encoder *intel_encoder =
 		intel_ddi_get_crtc_new_encoder(crtc_state);
 
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		return skl_ddi_pll_select(intel_crtc, crtc_state,
 					  intel_encoder);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		return bxt_ddi_pll_select(intel_crtc, crtc_state,
 					  intel_encoder);
 	else
@@ -1189,7 +1254,7 @@ void intel_ddi_enable_transcoder_func(st
 			 * eDP when not using the panel fitter, and when not
 			 * using motion blur mitigation (which we don't
 			 * support). */
-			if (IS_HASWELL(dev) &&
+			if (IS_HASWELL(dev_priv) &&
 			    (intel_crtc->config->pch_pfit.enabled ||
 			     intel_crtc->config->pch_pfit.force_thru))
 				temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
@@ -1434,7 +1499,12 @@ static void skl_ddi_set_iboost(struct in
 		if (dp_iboost) {
 			iboost = dp_iboost;
 		} else {
-			ddi_translations = skl_get_buf_trans_dp(dev_priv, &n_entries);
+			if (IS_KABYLAKE(dev_priv))
+				ddi_translations = kbl_get_buf_trans_dp(dev_priv,
+									&n_entries);
+			else
+				ddi_translations = skl_get_buf_trans_dp(dev_priv,
+									&n_entries);
 			iboost = ddi_translations[level].i_boost;
 		}
 	} else if (type == INTEL_OUTPUT_EDP) {
@@ -1477,7 +1547,6 @@ static void bxt_ddi_vswing_sequence(stru
 {
 	const struct bxt_ddi_buf_trans *ddi_translations;
 	u32 n_entries, i;
-	uint32_t val;
 
 	if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
 		n_entries = ARRAY_SIZE(bxt_ddi_translations_edp);
@@ -1506,38 +1575,11 @@ static void bxt_ddi_vswing_sequence(stru
 		}
 	}
 
-	/*
-	 * While we write to the group register to program all lanes at once we
-	 * can read only lane registers and we pick lanes 0/1 for that.
-	 */
-	val = I915_READ(BXT_PORT_PCS_DW10_LN01(port));
-	val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT);
-	I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val);
-
-	val = I915_READ(BXT_PORT_TX_DW2_LN0(port));
-	val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE);
-	val |= ddi_translations[level].margin << MARGIN_000_SHIFT |
-	       ddi_translations[level].scale << UNIQ_TRANS_SCALE_SHIFT;
-	I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val);
-
-	val = I915_READ(BXT_PORT_TX_DW3_LN0(port));
-	val &= ~SCALE_DCOMP_METHOD;
-	if (ddi_translations[level].enable)
-		val |= SCALE_DCOMP_METHOD;
-
-	if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD))
-		DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set");
-
-	I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val);
-
-	val = I915_READ(BXT_PORT_TX_DW4_LN0(port));
-	val &= ~DE_EMPHASIS;
-	val |= ddi_translations[level].deemphasis << DEEMPH_SHIFT;
-	I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val);
-
-	val = I915_READ(BXT_PORT_PCS_DW10_LN01(port));
-	val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT;
-	I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val);
+	bxt_ddi_phy_set_signal_level(dev_priv, port,
+				     ddi_translations[level].margin,
+				     ddi_translations[level].scale,
+				     ddi_translations[level].enable,
+				     ddi_translations[level].deemphasis);
 }
 
 static uint32_t translate_signal_level(int signal_levels)
@@ -1711,8 +1753,7 @@ static void intel_ddi_post_disable(struc
 				   struct drm_connector_state *old_conn_state)
 {
 	struct drm_encoder *encoder = &intel_encoder->base;
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
 	int type = intel_encoder->type;
 	uint32_t val;
@@ -1742,10 +1783,10 @@ static void intel_ddi_post_disable(struc
 		intel_edp_panel_off(intel_dp);
 	}
 
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) |
 					DPLL_CTRL2_DDI_CLK_OFF(port)));
-	else if (INTEL_INFO(dev)->gen < 9)
+	else if (INTEL_GEN(dev_priv) < 9)
 		I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
 
 	if (type == INTEL_OUTPUT_HDMI) {
@@ -1795,8 +1836,7 @@ static void intel_enable_ddi(struct inte
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = encoder->crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_device *dev = encoder->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	enum port port = intel_ddi_get_encoder_port(intel_encoder);
 	int type = intel_encoder->type;
 
@@ -1814,7 +1854,7 @@ static void intel_enable_ddi(struct inte
 	} else if (type == INTEL_OUTPUT_EDP) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-		if (port == PORT_A && INTEL_INFO(dev)->gen < 9)
+		if (port == PORT_A && INTEL_GEN(dev_priv) < 9)
 			intel_dp_stop_link_train(intel_dp);
 
 		intel_edp_backlight_on(intel_dp);
@@ -1824,7 +1864,7 @@ static void intel_enable_ddi(struct inte
 
 	if (intel_crtc->config->has_audio) {
 		intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
-		intel_audio_codec_enable(intel_encoder);
+		intel_audio_codec_enable(intel_encoder, pipe_config, conn_state);
 	}
 }
 
@@ -1853,332 +1893,14 @@ static void intel_disable_ddi(struct int
 	}
 }
 
-bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
-			    enum dpio_phy phy)
-{
-	enum port port;
-
-	if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy)))
-		return false;
-
-	if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
-	     (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) {
-		DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n",
-				 phy);
-
-		return false;
-	}
-
-	if (phy == DPIO_PHY1 &&
-	    !(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE)) {
-		DRM_DEBUG_DRIVER("DDI PHY 1 powered, but GRC isn't done\n");
-
-		return false;
-	}
-
-	if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) {
-		DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n",
-				 phy);
-
-		return false;
-	}
-
-	for_each_port_masked(port,
-			     phy == DPIO_PHY0 ? BIT(PORT_B) | BIT(PORT_C) :
-						BIT(PORT_A)) {
-		u32 tmp = I915_READ(BXT_PHY_CTL(port));
-
-		if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) {
-			DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane "
-					 "for port %c powered down "
-					 "(PHY_CTL %08x)\n",
-					 phy, port_name(port), tmp);
-
-			return false;
-		}
-	}
-
-	return true;
-}
-
-static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy)
-{
-	u32 val = I915_READ(BXT_PORT_REF_DW6(phy));
-
-	return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT;
-}
-
-static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv,
-				  enum dpio_phy phy)
-{
-	if (intel_wait_for_register(dev_priv,
-				    BXT_PORT_REF_DW3(phy),
-				    GRC_DONE, GRC_DONE,
-				    10))
-		DRM_ERROR("timeout waiting for PHY%d GRC\n", phy);
-}
-
-void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
-{
-	u32 val;
-
-	if (bxt_ddi_phy_is_enabled(dev_priv, phy)) {
-		/* Still read out the GRC value for state verification */
-		if (phy == DPIO_PHY0)
-			dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy);
-
-		if (bxt_ddi_phy_verify_state(dev_priv, phy)) {
-			DRM_DEBUG_DRIVER("DDI PHY %d already enabled, "
-					 "won't reprogram it\n", phy);
-
-			return;
-		}
-
-		DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, "
-				 "force reprogramming it\n", phy);
-	}
-
-	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
-	val |= GT_DISPLAY_POWER_ON(phy);
-	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
-
-	/*
-	 * The PHY registers start out inaccessible and respond to reads with
-	 * all 1s.  Eventually they become accessible as they power up, then
-	 * the reserved bit will give the default 0.  Poll on the reserved bit
-	 * becoming 0 to find when the PHY is accessible.
-	 * HW team confirmed that the time to reach phypowergood status is
-	 * anywhere between 50 us and 100us.
-	 */
-	if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
-		(PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) {
-		DRM_ERROR("timeout during PHY%d power on\n", phy);
-	}
-
-	/* Program PLL Rcomp code offset */
-	val = I915_READ(BXT_PORT_CL1CM_DW9(phy));
-	val &= ~IREF0RC_OFFSET_MASK;
-	val |= 0xE4 << IREF0RC_OFFSET_SHIFT;
-	I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val);
-
-	val = I915_READ(BXT_PORT_CL1CM_DW10(phy));
-	val &= ~IREF1RC_OFFSET_MASK;
-	val |= 0xE4 << IREF1RC_OFFSET_SHIFT;
-	I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val);
-
-	/* Program power gating */
-	val = I915_READ(BXT_PORT_CL1CM_DW28(phy));
-	val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN |
-		SUS_CLK_CONFIG;
-	I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val);
-
-	if (phy == DPIO_PHY0) {
-		val = I915_READ(BXT_PORT_CL2CM_DW6_BC);
-		val |= DW6_OLDO_DYN_PWR_DOWN_EN;
-		I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val);
-	}
-
-	val = I915_READ(BXT_PORT_CL1CM_DW30(phy));
-	val &= ~OCL2_LDOFUSE_PWR_DIS;
-	/*
-	 * On PHY1 disable power on the second channel, since no port is
-	 * connected there. On PHY0 both channels have a port, so leave it
-	 * enabled.
-	 * TODO: port C is only connected on BXT-P, so on BXT0/1 we should
-	 * power down the second channel on PHY0 as well.
-	 *
-	 * FIXME: Clarify programming of the following, the register is
-	 * read-only with bit 6 fixed at 0 at least in stepping A.
-	 */
-	if (phy == DPIO_PHY1)
-		val |= OCL2_LDOFUSE_PWR_DIS;
-	I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val);
-
-	if (phy == DPIO_PHY0) {
-		uint32_t grc_code;
-		/*
-		 * PHY0 isn't connected to an RCOMP resistor so copy over
-		 * the corresponding calibrated value from PHY1, and disable
-		 * the automatic calibration on PHY0.
-		 */
-		val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, DPIO_PHY1);
-		grc_code = val << GRC_CODE_FAST_SHIFT |
-			   val << GRC_CODE_SLOW_SHIFT |
-			   val;
-		I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code);
-
-		val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0));
-		val |= GRC_DIS | GRC_RDY_OVRD;
-		I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val);
-	}
-
-	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
-	val |= COMMON_RESET_DIS;
-	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
-
-	if (phy == DPIO_PHY1)
-		bxt_phy_wait_grc_done(dev_priv, DPIO_PHY1);
-}
-
-void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
-{
-	uint32_t val;
-
-	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
-	val &= ~COMMON_RESET_DIS;
-	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
-
-	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
-	val &= ~GT_DISPLAY_POWER_ON(phy);
-	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
-}
-
-static bool __printf(6, 7)
-__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
-		       i915_reg_t reg, u32 mask, u32 expected,
-		       const char *reg_fmt, ...)
-{
-	struct va_format vaf;
-	va_list args;
-	u32 val;
-
-	val = I915_READ(reg);
-	if ((val & mask) == expected)
-		return true;
-
-	va_start(args, reg_fmt);
-	vaf.fmt = reg_fmt;
-	vaf.va = &args;
-
-	DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: "
-			 "current %08x, expected %08x (mask %08x)\n",
-			 phy, &vaf, reg.reg, val, (val & ~mask) | expected,
-			 mask);
-
-	va_end(args);
-
-	return false;
-}
-
-bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
-			      enum dpio_phy phy)
-{
-	uint32_t mask;
-	bool ok;
-
-#define _CHK(reg, mask, exp, fmt, ...)					\
-	__phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt,	\
-			       ## __VA_ARGS__)
-
-	if (!bxt_ddi_phy_is_enabled(dev_priv, phy))
-		return false;
-
-	ok = true;
-
-	/* PLL Rcomp code offset */
-	ok &= _CHK(BXT_PORT_CL1CM_DW9(phy),
-		    IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT,
-		    "BXT_PORT_CL1CM_DW9(%d)", phy);
-	ok &= _CHK(BXT_PORT_CL1CM_DW10(phy),
-		    IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT,
-		    "BXT_PORT_CL1CM_DW10(%d)", phy);
-
-	/* Power gating */
-	mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG;
-	ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask,
-		    "BXT_PORT_CL1CM_DW28(%d)", phy);
-
-	if (phy == DPIO_PHY0)
-		ok &= _CHK(BXT_PORT_CL2CM_DW6_BC,
-			   DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN,
-			   "BXT_PORT_CL2CM_DW6_BC");
-
-	/*
-	 * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS,
-	 * at least on stepping A this bit is read-only and fixed at 0.
-	 */
-
-	if (phy == DPIO_PHY0) {
-		u32 grc_code = dev_priv->bxt_phy_grc;
-
-		grc_code = grc_code << GRC_CODE_FAST_SHIFT |
-			   grc_code << GRC_CODE_SLOW_SHIFT |
-			   grc_code;
-		mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK |
-		       GRC_CODE_NOM_MASK;
-		ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code,
-			    "BXT_PORT_REF_DW6(%d)", DPIO_PHY0);
-
-		mask = GRC_DIS | GRC_RDY_OVRD;
-		ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask,
-			    "BXT_PORT_REF_DW8(%d)", DPIO_PHY0);
-	}
-
-	return ok;
-#undef _CHK
-}
-
-static uint8_t
-bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder,
-				     struct intel_crtc_state *pipe_config)
-{
-	switch (pipe_config->lane_count) {
-	case 1:
-		return 0;
-	case 2:
-		return BIT(2) | BIT(0);
-	case 4:
-		return BIT(3) | BIT(2) | BIT(0);
-	default:
-		MISSING_CASE(pipe_config->lane_count);
-
-		return 0;
-	}
-}
-
 static void bxt_ddi_pre_pll_enable(struct intel_encoder *encoder,
 				   struct intel_crtc_state *pipe_config,
 				   struct drm_connector_state *conn_state)
 {
-	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
-	struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
-	enum port port = dport->port;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
-	int lane;
-
-	for (lane = 0; lane < 4; lane++) {
-		u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane));
-
-		/*
-		 * Note that on CHV this flag is called UPAR, but has
-		 * the same function.
-		 */
-		val &= ~LATENCY_OPTIM;
-		if (intel_crtc->config->lane_lat_optim_mask & BIT(lane))
-			val |= LATENCY_OPTIM;
-
-		I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val);
-	}
-}
-
-static uint8_t
-bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
-{
-	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
-	struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
-	enum port port = dport->port;
-	int lane;
-	uint8_t mask;
-
-	mask = 0;
-	for (lane = 0; lane < 4; lane++) {
-		u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane));
-
-		if (val & LATENCY_OPTIM)
-			mask |= BIT(lane);
-	}
+	uint8_t mask = intel_crtc->config->lane_lat_optim_mask;
 
-	return mask;
+	bxt_ddi_phy_set_lane_optim_mask(encoder, mask);
 }
 
 void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
@@ -2347,7 +2069,7 @@ static bool intel_ddi_compute_config(str
 	if (IS_BROXTON(dev_priv) && ret)
 		pipe_config->lane_lat_optim_mask =
 			bxt_ddi_phy_calc_lane_lat_optim_mask(encoder,
-							     pipe_config);
+							     pipe_config->lane_count);
 
 	return ret;
 
@@ -2438,7 +2160,7 @@ void intel_ddi_init(struct drm_device *d
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
 	struct drm_encoder *encoder;
-	bool init_hdmi, init_dp;
+	bool init_hdmi, init_dp, init_lspcon = false;
 	int max_lanes;
 
 	if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) {
@@ -2470,6 +2192,19 @@ void intel_ddi_init(struct drm_device *d
 	init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi ||
 		     dev_priv->vbt.ddi_port_info[port].supports_hdmi);
 	init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp;
+
+	if (intel_bios_is_lspcon_present(dev_priv, port)) {
+		/*
+		 * Lspcon device needs to be driven with DP connector
+		 * with special detection sequence. So make sure DP
+		 * is initialized before lspcon.
+		 */
+		init_dp = true;
+		init_lspcon = true;
+		init_hdmi = false;
+		DRM_DEBUG_KMS("VBT says port %c has lspcon\n", port_name(port));
+	}
+
 	if (!init_dp && !init_hdmi) {
 		DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, respect it\n",
 			      port_name(port));
@@ -2509,7 +2244,7 @@ void intel_ddi_init(struct drm_device *d
 	 * configuration so that we use the proper lane count for our
 	 * calculations.
 	 */
-	if (IS_BROXTON(dev) && port == PORT_A) {
+	if (IS_BROXTON(dev_priv) && port == PORT_A) {
 		if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) {
 			DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n");
 			intel_dig_port->saved_port_bits |= DDI_A_4_LANES;
@@ -2520,6 +2255,7 @@ void intel_ddi_init(struct drm_device *d
 	intel_dig_port->max_lanes = max_lanes;
 
 	intel_encoder->type = INTEL_OUTPUT_UNKNOWN;
+	intel_encoder->port = port;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	intel_encoder->cloneable = 0;
 
@@ -2532,7 +2268,7 @@ void intel_ddi_init(struct drm_device *d
 		 * On BXT A0/A1, sw needs to activate DDIA HPD logic and
 		 * interrupts to check the external panel connection.
 		 */
-		if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) && port == PORT_B)
+		if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) && port == PORT_B)
 			dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port;
 		else
 			dev_priv->hotplug.irq_port[port] = intel_dig_port;
@@ -2545,6 +2281,20 @@ void intel_ddi_init(struct drm_device *d
 			goto err;
 	}
 
+	if (init_lspcon) {
+		if (lspcon_init(intel_dig_port))
+			/* TODO: handle hdmi info frame part */
+			DRM_DEBUG_KMS("LSPCON init success on port %c\n",
+				port_name(port));
+		else
+			/*
+			 * LSPCON init faied, but DP init was success, so
+			 * lets try to drive as DP++ port.
+			 */
+			DRM_ERROR("LSPCON init failed on port %c\n",
+				port_name(port));
+	}
+
 	return;
 
 err:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_device_info.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_device_info.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_device_info.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_device_info.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,20 +28,14 @@ void intel_device_info_dump(struct drm_i
 {
 	const struct intel_device_info *info = &dev_priv->info;
 
-#define PRINT_S(name) "%s"
-#define SEP_EMPTY
-#define PRINT_FLAG(name) info->name ? #name "," : ""
-#define SEP_COMMA ,
-	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags="
-			 DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
+	DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x",
 			 info->gen,
 			 dev_priv->drm.pdev->device,
-			 dev_priv->drm.pdev->revision,
-			 DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
-#undef PRINT_S
-#undef SEP_EMPTY
+			 dev_priv->drm.pdev->revision);
+#define PRINT_FLAG(name) \
+	DRM_DEBUG_DRIVER("i915 device info: " #name ": %s", yesno(info->name))
+	DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG);
 #undef PRINT_FLAG
-#undef SEP_COMMA
 }
 
 static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv)
@@ -288,12 +282,13 @@ void intel_device_info_runtime_init(stru
 		info->num_sprites[PIPE_A] = 2;
 		info->num_sprites[PIPE_B] = 2;
 		info->num_sprites[PIPE_C] = 1;
-	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		for_each_pipe(dev_priv, pipe)
 			info->num_sprites[pipe] = 2;
-	else
+	} else if (INTEL_GEN(dev_priv) >= 5) {
 		for_each_pipe(dev_priv, pipe)
 			info->num_sprites[pipe] = 1;
+	}
 
 	if (i915.disable_display) {
 		DRM_INFO("Display disabled (module parameter)\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_display.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,6 @@
 #include "intel_frontbuffer.h"
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
-#include "i915_gem_dmabuf.h"
 #include "intel_dsi.h"
 #include "i915_trace.h"
 #include <drm/drm_atomic.h>
@@ -116,8 +115,9 @@ static void chv_prepare_pll(struct intel
 			    const struct intel_crtc_state *pipe_config);
 static void intel_begin_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
 static void intel_finish_crtc_commit(struct drm_crtc *, struct drm_crtc_state *);
-static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
-	struct intel_crtc_state *crtc_state);
+static void skl_init_scalers(struct drm_i915_private *dev_priv,
+			     struct intel_crtc *crtc,
+			     struct intel_crtc_state *crtc_state);
 static void skylake_pfit_enable(struct intel_crtc *crtc);
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
@@ -600,7 +600,7 @@ int chv_calc_dpll_params(int refclk, str
  * the given connectors.
  */
 
-static bool intel_PLL_is_valid(struct drm_device *dev,
+static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv,
 			       const struct intel_limit *limit,
 			       const struct dpll *clock)
 {
@@ -613,12 +613,13 @@ static bool intel_PLL_is_valid(struct dr
 	if (clock->m1  < limit->m1.min  || limit->m1.max  < clock->m1)
 		INTELPllInvalid("m1 out of range\n");
 
-	if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) &&
-	    !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev))
+	if (!IS_PINEVIEW(dev_priv) && !IS_VALLEYVIEW(dev_priv) &&
+	    !IS_CHERRYVIEW(dev_priv) && !IS_BROXTON(dev_priv))
 		if (clock->m1 <= clock->m2)
 			INTELPllInvalid("m1 <= m2\n");
 
-	if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) {
+	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
+	    !IS_BROXTON(dev_priv)) {
 		if (clock->p < limit->p.min || limit->p.max < clock->p)
 			INTELPllInvalid("p out of range\n");
 		if (clock->m < limit->m.min || limit->m.max < clock->m)
@@ -698,7 +699,8 @@ i9xx_find_best_dpll(const struct intel_l
 					int this_err;
 
 					i9xx_calc_dpll_params(refclk, &clock);
-					if (!intel_PLL_is_valid(dev, limit,
+					if (!intel_PLL_is_valid(to_i915(dev),
+								limit,
 								&clock))
 						continue;
 					if (match_clock &&
@@ -753,7 +755,8 @@ pnv_find_best_dpll(const struct intel_li
 					int this_err;
 
 					pnv_calc_dpll_params(refclk, &clock);
-					if (!intel_PLL_is_valid(dev, limit,
+					if (!intel_PLL_is_valid(to_i915(dev),
+								limit,
 								&clock))
 						continue;
 					if (match_clock &&
@@ -813,7 +816,8 @@ g4x_find_best_dpll(const struct intel_li
 					int this_err;
 
 					i9xx_calc_dpll_params(refclk, &clock);
-					if (!intel_PLL_is_valid(dev, limit,
+					if (!intel_PLL_is_valid(to_i915(dev),
+								limit,
 								&clock))
 						continue;
 
@@ -845,7 +849,7 @@ static bool vlv_PLL_is_optimal(struct dr
 	 * For CHV ignore the error and consider only the P value.
 	 * Prefer a bigger P value based on HW requirements.
 	 */
-	if (IS_CHERRYVIEW(dev)) {
+	if (IS_CHERRYVIEW(to_i915(dev))) {
 		*error_ppm = 0;
 
 		return calculated_clock->p > best_clock->p;
@@ -909,7 +913,8 @@ vlv_find_best_dpll(const struct intel_li
 
 					vlv_calc_dpll_params(refclk, &clock);
 
-					if (!intel_PLL_is_valid(dev, limit,
+					if (!intel_PLL_is_valid(to_i915(dev),
+								limit,
 								&clock))
 						continue;
 
@@ -977,7 +982,7 @@ chv_find_best_dpll(const struct intel_li
 
 			chv_calc_dpll_params(refclk, &clock);
 
-			if (!intel_PLL_is_valid(dev, limit, &clock))
+			if (!intel_PLL_is_valid(to_i915(dev), limit, &clock))
 				continue;
 
 			if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock,
@@ -1003,10 +1008,8 @@ bool bxt_find_best_dpll(struct intel_crt
 				  target_clock, refclk, NULL, best_clock);
 }
 
-bool intel_crtc_active(struct drm_crtc *crtc)
+bool intel_crtc_active(struct intel_crtc *crtc)
 {
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
 	/* Be paranoid as we can arrive here with only partial
 	 * state retrieved from the hardware during setup.
 	 *
@@ -1020,27 +1023,25 @@ bool intel_crtc_active(struct drm_crtc *
 	 * crtc->state->active once we have proper CRTC states wired up
 	 * for atomic.
 	 */
-	return intel_crtc->active && crtc->primary->state->fb &&
-		intel_crtc->config->base.adjusted_mode.crtc_clock;
+	return crtc->active && crtc->base.primary->state->fb &&
+		crtc->config->base.adjusted_mode.crtc_clock;
 }
 
 enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
 					     enum pipe pipe)
 {
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 
-	return intel_crtc->config->cpu_transcoder;
+	return crtc->config->cpu_transcoder;
 }
 
-static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe)
+static bool pipe_dsl_stopped(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	i915_reg_t reg = PIPEDSL(pipe);
 	u32 line1, line2;
 	u32 line_mask;
 
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		line_mask = DSL_LINEMASK_GEN2;
 	else
 		line_mask = DSL_LINEMASK_GEN3;
@@ -1070,12 +1071,11 @@ static bool pipe_dsl_stopped(struct drm_
  */
 static void intel_wait_for_pipe_off(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
 	enum pipe pipe = crtc->pipe;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		i915_reg_t reg = PIPECONF(cpu_transcoder);
 
 		/* Wait for the Pipe State to go off */
@@ -1085,7 +1085,7 @@ static void intel_wait_for_pipe_off(stru
 			WARN(1, "pipe_off wait timed out\n");
 	} else {
 		/* Wait for the display line to settle */
-		if (wait_for(pipe_dsl_stopped(dev, pipe), 100))
+		if (wait_for(pipe_dsl_stopped(dev_priv, pipe), 100))
 			WARN(1, "pipe_off wait timed out\n");
 	}
 }
@@ -1187,19 +1187,17 @@ void assert_fdi_rx_pll(struct drm_i915_p
 			onoff(state), onoff(cur_state));
 }
 
-void assert_panel_unlocked(struct drm_i915_private *dev_priv,
-			   enum pipe pipe)
+void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	i915_reg_t pp_reg;
 	u32 val;
 	enum pipe panel_pipe = PIPE_A;
 	bool locked = true;
 
-	if (WARN_ON(HAS_DDI(dev)))
+	if (WARN_ON(HAS_DDI(dev_priv)))
 		return;
 
-	if (HAS_PCH_SPLIT(dev)) {
+	if (HAS_PCH_SPLIT(dev_priv)) {
 		u32 port_sel;
 
 		pp_reg = PP_CONTROL(0);
@@ -1209,7 +1207,7 @@ void assert_panel_unlocked(struct drm_i9
 		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
 			panel_pipe = PIPE_B;
 		/* XXX: else fix for eDP */
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		/* presumably write lock depends on pipe, not port select */
 		pp_reg = PP_CONTROL(pipe);
 		panel_pipe = pipe;
@@ -1232,10 +1230,9 @@ void assert_panel_unlocked(struct drm_i9
 static void assert_cursor(struct drm_i915_private *dev_priv,
 			  enum pipe pipe, bool state)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	bool cur_state;
 
-	if (IS_845G(dev) || IS_I865G(dev))
+	if (IS_845G(dev_priv) || IS_I865G(dev_priv))
 		cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE;
 	else
 		cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE;
@@ -1294,11 +1291,10 @@ static void assert_plane(struct drm_i915
 static void assert_planes_disabled(struct drm_i915_private *dev_priv,
 				   enum pipe pipe)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	int i;
 
 	/* Primary planes are fixed to pipes on gen4+ */
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		u32 val = I915_READ(DSPCNTR(pipe));
 		I915_STATE_WARN(val & DISPLAY_PLANE_ENABLE,
 		     "plane %c assertion failure, should be disabled but not\n",
@@ -1320,29 +1316,28 @@ static void assert_planes_disabled(struc
 static void assert_sprites_disabled(struct drm_i915_private *dev_priv,
 				    enum pipe pipe)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	int sprite;
 
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		for_each_sprite(dev_priv, pipe, sprite) {
 			u32 val = I915_READ(PLANE_CTL(pipe, sprite));
 			I915_STATE_WARN(val & PLANE_CTL_ENABLE,
 			     "plane %d assertion failure, should be off on pipe %c but is still active\n",
 			     sprite, pipe_name(pipe));
 		}
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		for_each_sprite(dev_priv, pipe, sprite) {
 			u32 val = I915_READ(SPCNTR(pipe, sprite));
 			I915_STATE_WARN(val & SP_ENABLE,
 			     "sprite %c assertion failure, should be off on pipe %c but is still active\n",
 			     sprite_name(pipe, sprite), pipe_name(pipe));
 		}
-	} else if (INTEL_INFO(dev)->gen >= 7) {
+	} else if (INTEL_GEN(dev_priv) >= 7) {
 		u32 val = I915_READ(SPRCTL(pipe));
 		I915_STATE_WARN(val & SPRITE_ENABLE,
 		     "sprite %c assertion failure, should be off on pipe %c but is still active\n",
 		     plane_name(pipe), pipe_name(pipe));
-	} else if (INTEL_INFO(dev)->gen >= 5) {
+	} else if (INTEL_GEN(dev_priv) >= 5) {
 		u32 val = I915_READ(DVSCNTR(pipe));
 		I915_STATE_WARN(val & DVS_ENABLE,
 		     "sprite %c assertion failure, should be off on pipe %c but is still active\n",
@@ -1596,12 +1591,12 @@ static void chv_enable_pll(struct intel_
 	}
 }
 
-static int intel_num_dvo_pipes(struct drm_device *dev)
+static int intel_num_dvo_pipes(struct drm_i915_private *dev_priv)
 {
 	struct intel_crtc *crtc;
 	int count = 0;
 
-	for_each_intel_crtc(dev, crtc) {
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
 		count += crtc->base.state->active &&
 			intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO);
 	}
@@ -1611,19 +1606,18 @@ static int intel_num_dvo_pipes(struct dr
 
 static void i9xx_enable_pll(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	i915_reg_t reg = DPLL(crtc->pipe);
 	u32 dpll = crtc->config->dpll_hw_state.dpll;
 
 	assert_pipe_disabled(dev_priv, crtc->pipe);
 
 	/* PLL is protected by panel, make sure we can write it */
-	if (IS_MOBILE(dev) && !IS_I830(dev))
+	if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
 		assert_panel_unlocked(dev_priv, crtc->pipe);
 
 	/* Enable DVO 2x clock on both PLLs if necessary */
-	if (IS_I830(dev) && intel_num_dvo_pipes(dev) > 0) {
+	if (IS_I830(dev_priv) && intel_num_dvo_pipes(dev_priv) > 0) {
 		/*
 		 * It appears to be important that we don't enable this
 		 * for the current pipe before otherwise configuring the
@@ -1648,7 +1642,7 @@ static void i9xx_enable_pll(struct intel
 	POSTING_READ(reg);
 	udelay(150);
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		I915_WRITE(DPLL_MD(crtc->pipe),
 			   crtc->config->dpll_hw_state.dpll_md);
 	} else {
@@ -1683,14 +1677,13 @@ static void i9xx_enable_pll(struct intel
  */
 static void i9xx_disable_pll(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum pipe pipe = crtc->pipe;
 
 	/* Disable DVO 2x clock on both PLLs if necessary */
-	if (IS_I830(dev) &&
+	if (IS_I830(dev_priv) &&
 	    intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO) &&
-	    !intel_num_dvo_pipes(dev)) {
+	    !intel_num_dvo_pipes(dev_priv)) {
 		I915_WRITE(DPLL(PIPE_B),
 			   I915_READ(DPLL(PIPE_B)) & ~DPLL_DVO_2X_MODE);
 		I915_WRITE(DPLL(PIPE_A),
@@ -1786,9 +1779,8 @@ void vlv_wait_port_ready(struct drm_i915
 static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
 					   enum pipe pipe)
 {
-	struct drm_device *dev = &dev_priv->drm;
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
+								pipe);
 	i915_reg_t reg;
 	uint32_t val, pipeconf_val;
 
@@ -1799,7 +1791,7 @@ static void ironlake_enable_pch_transcod
 	assert_fdi_tx_enabled(dev_priv, pipe);
 	assert_fdi_rx_enabled(dev_priv, pipe);
 
-	if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		/* Workaround: Set the timing override bit before enabling the
 		 * pch transcoder. */
 		reg = TRANS_CHICKEN2(pipe);
@@ -1877,7 +1869,6 @@ static void lpt_enable_pch_transcoder(st
 static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
 					    enum pipe pipe)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	i915_reg_t reg;
 	uint32_t val;
 
@@ -1898,7 +1889,7 @@ static void ironlake_disable_pch_transco
 				    50))
 		DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe));
 
-	if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		/* Workaround: Clear the timing override chicken bit again. */
 		reg = TRANS_CHICKEN2(pipe);
 		val = I915_READ(reg);
@@ -1926,6 +1917,18 @@ void lpt_disable_pch_transcoder(struct d
 	I915_WRITE(TRANS_CHICKEN2(PIPE_A), val);
 }
 
+enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc)
+{
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+
+	WARN_ON(!crtc->config->has_pch_encoder);
+
+	if (HAS_PCH_LPT(dev_priv))
+		return TRANSCODER_A;
+	else
+		return (enum transcoder) crtc->pipe;
+}
+
 /**
  * intel_enable_pipe - enable a pipe, asserting requirements
  * @crtc: crtc responsible for the pipe
@@ -1939,7 +1942,6 @@ static void intel_enable_pipe(struct int
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum pipe pipe = crtc->pipe;
 	enum transcoder cpu_transcoder = crtc->config->cpu_transcoder;
-	enum pipe pch_transcoder;
 	i915_reg_t reg;
 	u32 val;
 
@@ -1949,11 +1951,6 @@ static void intel_enable_pipe(struct int
 	assert_cursor_disabled(dev_priv, pipe);
 	assert_sprites_disabled(dev_priv, pipe);
 
-	if (HAS_PCH_LPT(dev_priv))
-		pch_transcoder = TRANSCODER_A;
-	else
-		pch_transcoder = pipe;
-
 	/*
 	 * A pipe without a PLL won't actually be able to drive bits from
 	 * a plane.  On ILK+ the pipe PLLs are integrated, so we don't
@@ -1967,7 +1964,8 @@ static void intel_enable_pipe(struct int
 	} else {
 		if (crtc->config->has_pch_encoder) {
 			/* if driving the PCH, we need FDI enabled */
-			assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder);
+			assert_fdi_rx_pll_enabled(dev_priv,
+						  (enum pipe) intel_crtc_pch_transcoder(crtc));
 			assert_fdi_tx_pll_enabled(dev_priv,
 						  (enum pipe) cpu_transcoder);
 		}
@@ -2139,7 +2137,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt
 			const struct drm_framebuffer *fb,
 			unsigned int rotation)
 {
-	if (intel_rotation_90_or_270(rotation)) {
+	if (drm_rotation_90_or_270(rotation)) {
 		*view = i915_ggtt_view_rotated;
 		view->params.rotated = to_intel_framebuffer(fb)->rot_info;
 	} else {
@@ -2191,7 +2189,7 @@ intel_pin_and_fence_fb_obj(struct drm_fr
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
-	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
+	alignment = intel_surf_alignment(dev_priv, fb->modifier);
 
 	intel_fill_fb_ggtt_view(&view, fb, rotation);
 
@@ -2237,30 +2235,28 @@ intel_pin_and_fence_fb_obj(struct drm_fr
 			i915_vma_pin_fence(vma);
 	}
 
+	i915_vma_get(vma);
 err:
 	intel_runtime_pm_put(dev_priv);
 	return vma;
 }
 
-void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation)
+void intel_unpin_fb_vma(struct i915_vma *vma)
 {
-	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-	struct i915_ggtt_view view;
-	struct i915_vma *vma;
-
-	WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
+	lockdep_assert_held(&vma->vm->dev->struct_mutex);
 
-	intel_fill_fb_ggtt_view(&view, fb, rotation);
-	vma = i915_gem_object_to_ggtt(obj, &view);
+	if (WARN_ON_ONCE(!vma))
+		return;
 
 	i915_vma_unpin_fence(vma);
 	i915_gem_object_unpin_from_display_plane(vma);
+	i915_vma_put(vma);
 }
 
 static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
 			  unsigned int rotation)
 {
-	if (intel_rotation_90_or_270(rotation))
+	if (drm_rotation_90_or_270(rotation))
 		return to_intel_framebuffer(fb)->rotated[plane].pitch;
 	else
 		return fb->pitches[plane];
@@ -2296,7 +2292,7 @@ void intel_add_fb_offsets(int *x, int *y
 	const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb);
 	unsigned int rotation = state->base.rotation;
 
-	if (intel_rotation_90_or_270(rotation)) {
+	if (drm_rotation_90_or_270(rotation)) {
 		*x += intel_fb->rotated[plane].x;
 		*y += intel_fb->rotated[plane].y;
 	} else {
@@ -2352,15 +2348,15 @@ static u32 intel_adjust_tile_offset(int
 
 	WARN_ON(new_offset > old_offset);
 
-	if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
+	if (fb->modifier != DRM_FORMAT_MOD_NONE) {
 		unsigned int tile_size, tile_width, tile_height;
 		unsigned int pitch_tiles;
 
 		tile_size = intel_tile_size(dev_priv);
 		intel_tile_dims(dev_priv, &tile_width, &tile_height,
-				fb->modifier[plane], cpp);
+				fb->modifier, cpp);
 
-		if (intel_rotation_90_or_270(rotation)) {
+		if (drm_rotation_90_or_270(rotation)) {
 			pitch_tiles = pitch / tile_height;
 			swap(tile_width, tile_height);
 		} else {
@@ -2401,7 +2397,7 @@ static u32 _intel_compute_tile_offset(co
 				      unsigned int rotation,
 				      u32 alignment)
 {
-	uint64_t fb_modifier = fb->modifier[plane];
+	uint64_t fb_modifier = fb->modifier;
 	unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
 	u32 offset, offset_aligned;
 
@@ -2416,7 +2412,7 @@ static u32 _intel_compute_tile_offset(co
 		intel_tile_dims(dev_priv, &tile_width, &tile_height,
 				fb_modifier, cpp);
 
-		if (intel_rotation_90_or_270(rotation)) {
+		if (drm_rotation_90_or_270(rotation)) {
 			pitch_tiles = pitch / tile_height;
 			swap(tile_width, tile_height);
 		} else {
@@ -2460,7 +2456,7 @@ u32 intel_compute_tile_offset(int *x, in
 	if (fb->pixel_format == DRM_FORMAT_NV12 && plane == 1)
 		alignment = 4096;
 	else
-		alignment = intel_surf_alignment(dev_priv, fb->modifier[plane]);
+		alignment = intel_surf_alignment(dev_priv, fb->modifier);
 
 	return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
 					  rotation, alignment);
@@ -2542,13 +2538,13 @@ intel_fill_fb_info(struct drm_i915_priva
 						    DRM_ROTATE_0, tile_size);
 		offset /= tile_size;
 
-		if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
+		if (fb->modifier != DRM_FORMAT_MOD_NONE) {
 			unsigned int tile_width, tile_height;
 			unsigned int pitch_tiles;
 			struct drm_rect r;
 
 			intel_tile_dims(dev_priv, &tile_width, &tile_height,
-					fb->modifier[i], cpp);
+					fb->modifier, cpp);
 
 			rot_info->plane[i].offset = offset;
 			rot_info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], tile_width * cpp);
@@ -2587,8 +2583,9 @@ intel_fill_fb_info(struct drm_i915_priva
 			 * We only keep the x/y offsets, so push all of the
 			 * gtt offset into the x/y offsets.
 			 */
-			_intel_adjust_tile_offset(&x, &y, tile_size,
-						  tile_width, tile_height, pitch_tiles,
+			_intel_adjust_tile_offset(&x, &y,
+						  tile_width, tile_height,
+						  tile_size, pitch_tiles,
 						  gtt_offset_rotated * tile_size, 0);
 
 			gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height;
@@ -2707,7 +2704,7 @@ intel_alloc_initial_plane_obj(struct int
 	mode_cmd.width = fb->width;
 	mode_cmd.height = fb->height;
 	mode_cmd.pitches[0] = fb->pitches[0];
-	mode_cmd.modifier[0] = fb->modifier[0];
+	mode_cmd.modifier[0] = fb->modifier;
 	mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
 
 	if (intel_framebuffer_init(dev, to_intel_framebuffer(fb),
@@ -2748,7 +2745,6 @@ intel_find_initial_plane_obj(struct inte
 	struct drm_device *dev = intel_crtc->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_crtc *c;
-	struct intel_crtc *i;
 	struct drm_i915_gem_object *obj;
 	struct drm_plane *primary = intel_crtc->base.primary;
 	struct drm_plane_state *plane_state = primary->state;
@@ -2773,20 +2769,20 @@ intel_find_initial_plane_obj(struct inte
 	 * an fb with another CRTC instead
 	 */
 	for_each_crtc(dev, c) {
-		i = to_intel_crtc(c);
+		struct intel_plane_state *state;
 
 		if (c == &intel_crtc->base)
 			continue;
 
-		if (!i->active)
+		if (!to_intel_crtc(c)->active)
 			continue;
 
-		fb = c->primary->fb;
-		if (!fb)
+		state = to_intel_plane_state(c->primary->state);
+		if (!state->vma)
 			continue;
 
-		obj = intel_fb_obj(fb);
-		if (i915_gem_object_ggtt_offset(obj, NULL) == plane_config->base) {
+		if (intel_plane_ggtt_offset(state) == plane_config->base) {
+			fb = c->primary->fb;
 			drm_framebuffer_reference(fb);
 			goto valid_fb;
 		}
@@ -2807,6 +2803,19 @@ intel_find_initial_plane_obj(struct inte
 	return;
 
 valid_fb:
+	mutex_lock(&dev->struct_mutex);
+	intel_state->vma =
+		intel_pin_and_fence_fb_obj(fb, primary->state->rotation);
+	mutex_unlock(&dev->struct_mutex);
+	if (IS_ERR(intel_state->vma)) {
+		DRM_ERROR("failed to pin boot fb on pipe %d: %li\n",
+			  intel_crtc->pipe, PTR_ERR(intel_state->vma));
+
+		intel_state->vma = NULL;
+		drm_framebuffer_unreference(fb);
+		return;
+	}
+
 	plane_state->src_x = 0;
 	plane_state->src_y = 0;
 	plane_state->src_w = fb->width << 16;
@@ -2817,14 +2826,8 @@ valid_fb:
 	plane_state->crtc_w = fb->width;
 	plane_state->crtc_h = fb->height;
 
-	intel_state->base.src.x1 = plane_state->src_x;
-	intel_state->base.src.y1 = plane_state->src_y;
-	intel_state->base.src.x2 = plane_state->src_x + plane_state->src_w;
-	intel_state->base.src.y2 = plane_state->src_y + plane_state->src_h;
-	intel_state->base.dst.x1 = plane_state->crtc_x;
-	intel_state->base.dst.y1 = plane_state->crtc_y;
-	intel_state->base.dst.x2 = plane_state->crtc_x + plane_state->crtc_w;
-	intel_state->base.dst.y2 = plane_state->crtc_y + plane_state->crtc_h;
+	intel_state->base.src = drm_plane_state_src(plane_state);
+	intel_state->base.dst = drm_plane_state_dest(plane_state);
 
 	obj = intel_fb_obj(fb);
 	if (i915_gem_object_is_tiled(obj))
@@ -2843,7 +2846,7 @@ static int skl_max_plane_width(const str
 {
 	int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
 
-	switch (fb->modifier[plane]) {
+	switch (fb->modifier) {
 	case DRM_FORMAT_MOD_NONE:
 	case I915_FORMAT_MOD_X_TILED:
 		switch (cpp) {
@@ -2874,7 +2877,7 @@ static int skl_max_plane_width(const str
 		}
 		break;
 	default:
-		MISSING_CASE(fb->modifier[plane]);
+		MISSING_CASE(fb->modifier);
 	}
 
 	return 2048;
@@ -2902,7 +2905,7 @@ static int skl_check_main_surface(struct
 	intel_add_fb_offsets(&x, &y, plane_state, 0);
 	offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
 
-	alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
+	alignment = intel_surf_alignment(dev_priv, fb->modifier);
 
 	/*
 	 * AUX surface offset is specified as the distance from the
@@ -2919,7 +2922,7 @@ static int skl_check_main_surface(struct
 	 *
 	 * TODO: linear and Y-tiled seem fine, Yf untested,
 	 */
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) {
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
 		int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 		while ((x + w) * cpp > fb->pitches[0]) {
@@ -2975,8 +2978,11 @@ int skl_check_plane_surface(struct intel
 	unsigned int rotation = plane_state->base.rotation;
 	int ret;
 
+	if (!plane_state->base.visible)
+		return 0;
+
 	/* Rotate src coordinates to match rotated GTT view */
-	if (intel_rotation_90_or_270(rotation))
+	if (drm_rotation_90_or_270(rotation))
 		drm_rect_rotate(&plane_state->base.src,
 				fb->width << 16, fb->height << 16,
 				DRM_ROTATE_270);
@@ -3006,11 +3012,9 @@ static void i9xx_update_primary_plane(st
 				      const struct intel_crtc_state *crtc_state,
 				      const struct intel_plane_state *plane_state)
 {
-	struct drm_device *dev = primary->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(primary->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_framebuffer *fb = plane_state->base.fb;
-	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	int plane = intel_crtc->plane;
 	u32 linear_offset;
 	u32 dspcntr;
@@ -3023,7 +3027,7 @@ static void i9xx_update_primary_plane(st
 
 	dspcntr |= DISPLAY_PLANE_ENABLE;
 
-	if (INTEL_INFO(dev)->gen < 4) {
+	if (INTEL_GEN(dev_priv) < 4) {
 		if (intel_crtc->pipe == PIPE_B)
 			dspcntr |= DISPPLANE_SEL_PIPE_B;
 
@@ -3034,7 +3038,7 @@ static void i9xx_update_primary_plane(st
 			   ((crtc_state->pipe_src_h - 1) << 16) |
 			   (crtc_state->pipe_src_w - 1));
 		I915_WRITE(DSPPOS(plane), 0);
-	} else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) {
+	} else if (IS_CHERRYVIEW(dev_priv) && plane == PLANE_B) {
 		I915_WRITE(PRIMSIZE(plane),
 			   ((crtc_state->pipe_src_h - 1) << 16) |
 			   (crtc_state->pipe_src_w - 1));
@@ -3069,28 +3073,34 @@ static void i9xx_update_primary_plane(st
 	}
 
 	if (INTEL_GEN(dev_priv) >= 4 &&
-	    fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	    fb->modifier == I915_FORMAT_MOD_X_TILED)
 		dspcntr |= DISPPLANE_TILED;
 
-	if (IS_G4X(dev))
+	if (rotation & DRM_ROTATE_180)
+		dspcntr |= DISPPLANE_ROTATE_180;
+
+	if (rotation & DRM_REFLECT_X)
+		dspcntr |= DISPPLANE_MIRROR;
+
+	if (IS_G4X(dev_priv))
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
 	intel_add_fb_offsets(&x, &y, plane_state, 0);
 
-	if (INTEL_INFO(dev)->gen >= 4)
+	if (INTEL_GEN(dev_priv) >= 4)
 		intel_crtc->dspaddr_offset =
 			intel_compute_tile_offset(&x, &y, plane_state, 0);
 
-	if (rotation == DRM_ROTATE_180) {
-		dspcntr |= DISPPLANE_ROTATE_180;
-
-		x += (crtc_state->pipe_src_w - 1);
-		y += (crtc_state->pipe_src_h - 1);
+	if (rotation & DRM_ROTATE_180) {
+		x += crtc_state->pipe_src_w - 1;
+		y += crtc_state->pipe_src_h - 1;
+	} else if (rotation & DRM_REFLECT_X) {
+		x += crtc_state->pipe_src_w - 1;
 	}
 
 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 
-	if (INTEL_INFO(dev)->gen < 4)
+	if (INTEL_GEN(dev_priv) < 4)
 		intel_crtc->dspaddr_offset = linear_offset;
 
 	intel_crtc->adjusted_x = x;
@@ -3099,14 +3109,17 @@ static void i9xx_update_primary_plane(st
 	I915_WRITE(reg, dspcntr);
 
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		I915_WRITE(DSPSURF(plane),
-			   intel_fb_gtt_offset(fb, rotation) +
+			   intel_plane_ggtt_offset(plane_state) +
 			   intel_crtc->dspaddr_offset);
 		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
 		I915_WRITE(DSPLINOFF(plane), linear_offset);
-	} else
-		I915_WRITE(DSPADDR(plane), i915_gem_object_ggtt_offset(obj, NULL) + linear_offset);
+	} else {
+		I915_WRITE(DSPADDR(plane),
+			   intel_plane_ggtt_offset(plane_state) +
+			   intel_crtc->dspaddr_offset);
+	}
 	POSTING_READ(reg);
 }
 
@@ -3145,7 +3158,7 @@ static void ironlake_update_primary_plan
 	dspcntr = DISPPLANE_GAMMA_ENABLE;
 	dspcntr |= DISPLAY_PLANE_ENABLE;
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		dspcntr |= DISPPLANE_PIPE_CSC_ENABLE;
 
 	switch (fb->pixel_format) {
@@ -3171,10 +3184,13 @@ static void ironlake_update_primary_plan
 		BUG();
 	}
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		dspcntr |= DISPPLANE_TILED;
 
-	if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
+	if (rotation & DRM_ROTATE_180)
+		dspcntr |= DISPPLANE_ROTATE_180;
+
+	if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv))
 		dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
 
 	intel_add_fb_offsets(&x, &y, plane_state, 0);
@@ -3182,13 +3198,11 @@ static void ironlake_update_primary_plan
 	intel_crtc->dspaddr_offset =
 		intel_compute_tile_offset(&x, &y, plane_state, 0);
 
-	if (rotation == DRM_ROTATE_180) {
-		dspcntr |= DISPPLANE_ROTATE_180;
-
-		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
-			x += (crtc_state->pipe_src_w - 1);
-			y += (crtc_state->pipe_src_h - 1);
-		}
+	/* HSW+ does this automagically in hardware */
+	if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv) &&
+	    rotation & DRM_ROTATE_180) {
+		x += crtc_state->pipe_src_w - 1;
+		y += crtc_state->pipe_src_h - 1;
 	}
 
 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
@@ -3200,9 +3214,9 @@ static void ironlake_update_primary_plan
 
 	I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
 	I915_WRITE(DSPSURF(plane),
-		   intel_fb_gtt_offset(fb, rotation) +
+		   intel_plane_ggtt_offset(plane_state) +
 		   intel_crtc->dspaddr_offset);
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
 	} else {
 		I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
@@ -3223,23 +3237,6 @@ u32 intel_fb_stride_alignment(const stru
 	}
 }
 
-u32 intel_fb_gtt_offset(struct drm_framebuffer *fb,
-			unsigned int rotation)
-{
-	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-	struct i915_ggtt_view view;
-	struct i915_vma *vma;
-
-	intel_fill_fb_ggtt_view(&view, fb, rotation);
-
-	vma = i915_gem_object_to_ggtt(obj, &view);
-	if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
-		 view.type))
-		return -1;
-
-	return i915_ggtt_offset(vma);
-}
-
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
 {
 	struct drm_device *dev = intel_crtc->base.dev;
@@ -3277,12 +3274,12 @@ u32 skl_plane_stride(const struct drm_fr
 	 * The stride is either expressed as a multiple of 64 bytes chunks for
 	 * linear buffers or in number of tiles for tiled buffers.
 	 */
-	if (intel_rotation_90_or_270(rotation)) {
+	if (drm_rotation_90_or_270(rotation)) {
 		int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
 
-		stride /= intel_tile_height(dev_priv, fb->modifier[0], cpp);
+		stride /= intel_tile_height(dev_priv, fb->modifier, cpp);
 	} else {
-		stride /= intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+		stride /= intel_fb_stride_alignment(dev_priv, fb->modifier,
 						    fb->pixel_format);
 	}
 
@@ -3378,7 +3375,6 @@ static void skylake_update_primary_plane
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct drm_framebuffer *fb = plane_state->base.fb;
-	const struct skl_wm_values *wm = &dev_priv->wm.skl_results;
 	int pipe = intel_crtc->pipe;
 	u32 plane_ctl;
 	unsigned int rotation = plane_state->base.rotation;
@@ -3399,7 +3395,7 @@ static void skylake_update_primary_plane
 		    PLANE_CTL_PIPE_CSC_ENABLE;
 
 	plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
-	plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
+	plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
 	plane_ctl |= PLANE_CTL_PLANE_GAMMA_DISABLE;
 	plane_ctl |= skl_plane_ctl_rotation(rotation);
 
@@ -3414,9 +3410,6 @@ static void skylake_update_primary_plane
 	intel_crtc->adjusted_x = src_x;
 	intel_crtc->adjusted_y = src_y;
 
-	if (wm->dirty_pipes & drm_crtc_mask(&intel_crtc->base))
-		skl_write_plane_wm(intel_crtc, wm, 0);
-
 	I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
 	I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_x);
 	I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
@@ -3438,7 +3431,7 @@ static void skylake_update_primary_plane
 	}
 
 	I915_WRITE(PLANE_SURF(pipe, 0),
-		   intel_fb_gtt_offset(fb, rotation) + surf_addr);
+		   intel_plane_ggtt_offset(plane_state) + surf_addr);
 
 	POSTING_READ(PLANE_SURF(pipe, 0));
 }
@@ -3451,13 +3444,6 @@ static void skylake_disable_primary_plan
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 
-	/*
-	 * We only populate skl_results on watermark updates, and if the
-	 * plane's visiblity isn't actually changing neither is its watermarks.
-	 */
-	if (!crtc->primary->state->visible)
-		skl_write_plane_wm(intel_crtc, &dev_priv->wm.skl_results, 0);
-
 	I915_WRITE(PLANE_CTL(pipe, 0), 0);
 	I915_WRITE(PLANE_SURF(pipe, 0), 0);
 	POSTING_READ(PLANE_SURF(pipe, 0));
@@ -3507,7 +3493,7 @@ __intel_display_resume(struct drm_device
 	int i, ret;
 
 	intel_modeset_setup_hw_state(dev);
-	i915_redisable_vga(dev);
+	i915_redisable_vga(to_i915(dev));
 
 	if (!state)
 		return 0;
@@ -3585,7 +3571,7 @@ void intel_prepare_reset(struct drm_i915
 	return;
 
 err:
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 }
 
 void intel_finish_reset(struct drm_i915_private *dev_priv)
@@ -3604,8 +3590,6 @@ void intel_finish_reset(struct drm_i915_
 
 	dev_priv->modeset_restore_state = NULL;
 
-	dev_priv->modeset_restore_state = NULL;
-
 	/* reset doesn't touch the display */
 	if (!gpu_reset_clobbers_display(dev_priv)) {
 		if (!state) {
@@ -3647,6 +3631,8 @@ void intel_finish_reset(struct drm_i915_
 		intel_hpd_init(dev_priv);
 	}
 
+	if (state)
+		drm_atomic_state_put(state);
 	drm_modeset_drop_locks(ctx);
 	drm_modeset_acquire_fini(ctx);
 	mutex_unlock(&dev->mode_config.mutex);
@@ -3684,8 +3670,7 @@ static bool intel_crtc_has_pending_flip(
 static void intel_update_pipe_config(struct intel_crtc *crtc,
 				     struct intel_crtc_state *old_crtc_state)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct intel_crtc_state *pipe_config =
 		to_intel_crtc_state(crtc->base.state);
 
@@ -3710,12 +3695,12 @@ static void intel_update_pipe_config(str
 		   (pipe_config->pipe_src_h - 1));
 
 	/* on skylake this is done by detaching scalers */
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		skl_detach_scalers(crtc);
 
 		if (pipe_config->pch_pfit.enabled)
 			skylake_pfit_enable(crtc);
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		if (pipe_config->pch_pfit.enabled)
 			ironlake_pfit_enable(crtc);
 		else if (old_crtc_state->pch_pfit.enabled)
@@ -3735,7 +3720,7 @@ static void intel_fdi_normal_train(struc
 	/* enable normal train */
 	reg = FDI_TX_CTL(pipe);
 	temp = I915_READ(reg);
-	if (IS_IVYBRIDGE(dev)) {
+	if (IS_IVYBRIDGE(dev_priv)) {
 		temp &= ~FDI_LINK_TRAIN_NONE_IVB;
 		temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
 	} else {
@@ -3746,7 +3731,7 @@ static void intel_fdi_normal_train(struc
 
 	reg = FDI_RX_CTL(pipe);
 	temp = I915_READ(reg);
-	if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
 		temp |= FDI_LINK_TRAIN_NORMAL_CPT;
 	} else {
@@ -3760,7 +3745,7 @@ static void intel_fdi_normal_train(struc
 	udelay(1000);
 
 	/* IVB wants error correction enabled */
-	if (IS_IVYBRIDGE(dev))
+	if (IS_IVYBRIDGE(dev_priv))
 		I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE |
 			   FDI_FE_ERRC_ENABLE);
 }
@@ -3904,7 +3889,7 @@ static void gen6_fdi_link_train(struct d
 
 	reg = FDI_RX_CTL(pipe);
 	temp = I915_READ(reg);
-	if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
 		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
 	} else {
@@ -3948,7 +3933,7 @@ static void gen6_fdi_link_train(struct d
 	temp = I915_READ(reg);
 	temp &= ~FDI_LINK_TRAIN_NONE;
 	temp |= FDI_LINK_TRAIN_PATTERN_2;
-	if (IS_GEN6(dev)) {
+	if (IS_GEN6(dev_priv)) {
 		temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
 		/* SNB-B */
 		temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
@@ -3957,7 +3942,7 @@ static void gen6_fdi_link_train(struct d
 
 	reg = FDI_RX_CTL(pipe);
 	temp = I915_READ(reg);
-	if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
 		temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
 	} else {
@@ -4211,7 +4196,7 @@ static void ironlake_fdi_disable(struct
 	udelay(100);
 
 	/* Ironlake workaround, disable clock pointer after downing FDI */
-	if (HAS_PCH_IBX(dev))
+	if (HAS_PCH_IBX(dev_priv))
 		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
 
 	/* still set train pattern 1 */
@@ -4223,7 +4208,7 @@ static void ironlake_fdi_disable(struct
 
 	reg = FDI_RX_CTL(pipe);
 	temp = I915_READ(reg);
-	if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
 		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
 	} else {
@@ -4241,6 +4226,7 @@ static void ironlake_fdi_disable(struct
 
 bool intel_has_pending_fb_unpin(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *crtc;
 
 	/* Note that we don't need to be called with mode_config.lock here
@@ -4255,7 +4241,7 @@ bool intel_has_pending_fb_unpin(struct d
 			continue;
 
 		if (crtc->flip_work)
-			intel_wait_for_vblank(dev, crtc->pipe);
+			intel_wait_for_vblank(dev_priv, crtc->pipe);
 
 		return true;
 	}
@@ -4276,10 +4262,10 @@ static void page_flip_completed(struct i
 	drm_crtc_vblank_put(&intel_crtc->base);
 
 	wake_up_all(&dev_priv->pending_flip_queue);
-	queue_work(dev_priv->wq, &work->unpin_work);
-
 	trace_i915_flip_complete(intel_crtc->plane,
 				 work->pending_flip_obj);
+
+	queue_work(dev_priv->wq, &work->unpin_work);
 }
 
 static int intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
@@ -4546,7 +4532,7 @@ static void ironlake_pch_enable(struct d
 
 	assert_pch_transcoder_disabled(dev_priv, pipe);
 
-	if (IS_IVYBRIDGE(dev))
+	if (IS_IVYBRIDGE(dev_priv))
 		ivybridge_update_fdi_bc_bifurcation(intel_crtc);
 
 	/* Write the TU size bits before fdi link training, so that error
@@ -4559,7 +4545,7 @@ static void ironlake_pch_enable(struct d
 
 	/* We need to program the right clock selection before writing the pixel
 	 * mutliplier into the DPLL. */
-	if (HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_CPT(dev_priv)) {
 		u32 sel;
 
 		temp = I915_READ(PCH_DPLL_SEL);
@@ -4589,7 +4575,8 @@ static void ironlake_pch_enable(struct d
 	intel_fdi_normal_train(crtc);
 
 	/* For PCH DP, enable TRANS_DP_CTL */
-	if (HAS_PCH_CPT(dev) && intel_crtc_has_dp_encoder(intel_crtc->config)) {
+	if (HAS_PCH_CPT(dev_priv) &&
+	    intel_crtc_has_dp_encoder(intel_crtc->config)) {
 		const struct drm_display_mode *adjusted_mode =
 			&intel_crtc->config->base.adjusted_mode;
 		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;
@@ -4668,7 +4655,7 @@ skl_update_scaler(struct intel_crtc_stat
 		to_intel_crtc(crtc_state->base.crtc);
 	int need_scaling;
 
-	need_scaling = intel_rotation_90_or_270(rotation) ?
+	need_scaling = drm_rotation_90_or_270(rotation) ?
 		(src_h != dst_w || src_w != dst_h):
 		(src_w != dst_w || src_h != dst_h);
 
@@ -4729,13 +4716,8 @@ skl_update_scaler(struct intel_crtc_stat
  */
 int skl_update_scaler_crtc(struct intel_crtc_state *state)
 {
-	struct intel_crtc *intel_crtc = to_intel_crtc(state->base.crtc);
 	const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
 
-	DRM_DEBUG_KMS("Updating scaler for [CRTC:%d:%s] scaler_user index %u.%u\n",
-		      intel_crtc->base.base.id, intel_crtc->base.name,
-		      intel_crtc->pipe, SKL_CRTC_INDEX);
-
 	return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
 		&state->scaler_state.scaler_id, DRM_ROTATE_0,
 		state->pipe_src_w, state->pipe_src_h,
@@ -4756,7 +4738,6 @@ static int skl_update_scaler_plane(struc
 				   struct intel_plane_state *plane_state)
 {
 
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc);
 	struct intel_plane *intel_plane =
 		to_intel_plane(plane_state->base.plane);
 	struct drm_framebuffer *fb = plane_state->base.fb;
@@ -4764,10 +4745,6 @@ static int skl_update_scaler_plane(struc
 
 	bool force_detach = !fb || !plane_state->base.visible;
 
-	DRM_DEBUG_KMS("Updating scaler for [PLANE:%d:%s] scaler_user index %u.%u\n",
-		      intel_plane->base.base.id, intel_plane->base.name,
-		      intel_crtc->pipe, drm_plane_index(&intel_plane->base));
-
 	ret = skl_update_scaler(crtc_state, force_detach,
 				drm_plane_index(&intel_plane->base),
 				&plane_state->scaler_id,
@@ -4859,7 +4836,7 @@ static void ironlake_pfit_enable(struct
 		 * as some pre-programmed values are broken,
 		 * e.g. x201.
 		 */
-		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
+		if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv))
 			I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 |
 						 PF_PIPE_SEL_IVB(pipe));
 		else
@@ -4884,7 +4861,7 @@ void hsw_enable_ips(struct intel_crtc *c
 	 */
 
 	assert_plane_enabled(dev_priv, crtc->plane);
-	if (IS_BROADWELL(dev)) {
+	if (IS_BROADWELL(dev_priv)) {
 		mutex_lock(&dev_priv->rps.hw_lock);
 		WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000));
 		mutex_unlock(&dev_priv->rps.hw_lock);
@@ -4916,7 +4893,7 @@ void hsw_disable_ips(struct intel_crtc *
 		return;
 
 	assert_plane_enabled(dev_priv, crtc->plane);
-	if (IS_BROADWELL(dev)) {
+	if (IS_BROADWELL(dev_priv)) {
 		mutex_lock(&dev_priv->rps.hw_lock);
 		WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0));
 		mutex_unlock(&dev_priv->rps.hw_lock);
@@ -4931,7 +4908,7 @@ void hsw_disable_ips(struct intel_crtc *
 	}
 
 	/* We need to wait for a vblank before we can disable the plane. */
-	intel_wait_for_vblank(dev, crtc->pipe);
+	intel_wait_for_vblank(dev_priv, crtc->pipe);
 }
 
 static void intel_crtc_dpms_overlay_disable(struct intel_crtc *intel_crtc)
@@ -4985,7 +4962,7 @@ intel_post_enable_primary(struct drm_crt
 	 * FIXME: Need to fix the logic to work when we turn off all planes
 	 * but leave the pipe running.
 	 */
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
 	/* Underruns don't always raise interrupts, so check manually. */
@@ -5008,7 +4985,7 @@ intel_pre_disable_primary(struct drm_crt
 	 * FIXME: Need to fix the logic to work when we turn off all planes
 	 * but leave the pipe running.
 	 */
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 
 	/*
@@ -5040,10 +5017,10 @@ intel_pre_disable_primary_noatomic(struc
 	 * event which is after the vblank start event, so we need to have a
 	 * wait-for-vblank between disabling the plane and the pipe.
 	 */
-	if (HAS_GMCH_DISPLAY(dev)) {
+	if (HAS_GMCH_DISPLAY(dev_priv)) {
 		intel_set_memory_cxsr(dev_priv, false);
 		dev_priv->wm.vlv.cxsr = false;
-		intel_wait_for_vblank(dev, pipe);
+		intel_wait_for_vblank(dev_priv, pipe);
 	}
 }
 
@@ -5062,7 +5039,7 @@ static void intel_post_plane_update(stru
 	crtc->wm.cxsr_allowed = true;
 
 	if (pipe_config->update_wm_post && pipe_config->base.active)
-		intel_update_watermarks(&crtc->base);
+		intel_update_watermarks(crtc);
 
 	if (old_pri_state) {
 		struct intel_plane_state *primary_state =
@@ -5091,6 +5068,8 @@ static void intel_pre_plane_update(struc
 	struct drm_plane_state *old_pri_state =
 		drm_atomic_get_existing_plane_state(old_state, primary);
 	bool modeset = needs_modeset(&pipe_config->base);
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_state);
 
 	if (old_pri_state) {
 		struct intel_plane_state *primary_state =
@@ -5105,7 +5084,7 @@ static void intel_pre_plane_update(struc
 			intel_pre_disable_primary(&crtc->base);
 	}
 
-	if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev)) {
+	if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev_priv)) {
 		crtc->wm.cxsr_allowed = false;
 
 		/*
@@ -5120,7 +5099,7 @@ static void intel_pre_plane_update(struc
 		if (old_crtc_state->base.active) {
 			intel_set_memory_cxsr(dev_priv, false);
 			dev_priv->wm.vlv.cxsr = false;
-			intel_wait_for_vblank(dev, crtc->pipe);
+			intel_wait_for_vblank(dev_priv, crtc->pipe);
 		}
 	}
 
@@ -5133,7 +5112,7 @@ static void intel_pre_plane_update(struc
 	 */
 	if (pipe_config->disable_lp_wm) {
 		ilk_disable_lp_wm(dev);
-		intel_wait_for_vblank(dev, crtc->pipe);
+		intel_wait_for_vblank(dev_priv, crtc->pipe);
 	}
 
 	/*
@@ -5158,9 +5137,10 @@ static void intel_pre_plane_update(struc
 	 * us to.
 	 */
 	if (dev_priv->display.initial_watermarks != NULL)
-		dev_priv->display.initial_watermarks(pipe_config);
+		dev_priv->display.initial_watermarks(old_intel_state,
+						     pipe_config);
 	else if (pipe_config->update_wm_pre)
-		intel_update_watermarks(&crtc->base);
+		intel_update_watermarks(crtc);
 }
 
 static void intel_crtc_disable_planes(struct drm_crtc *crtc, unsigned plane_mask)
@@ -5314,6 +5294,8 @@ static void ironlake_crtc_enable(struct
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_state);
 
 	if (WARN_ON(intel_crtc->active))
 		return;
@@ -5372,7 +5354,7 @@ static void ironlake_crtc_enable(struct
 	intel_color_load_luts(&pipe_config->base);
 
 	if (dev_priv->display.initial_watermarks != NULL)
-		dev_priv->display.initial_watermarks(intel_crtc->config);
+		dev_priv->display.initial_watermarks(old_intel_state, intel_crtc->config);
 	intel_enable_pipe(intel_crtc);
 
 	if (intel_crtc->config->has_pch_encoder)
@@ -5383,12 +5365,12 @@ static void ironlake_crtc_enable(struct
 
 	intel_encoders_enable(crtc, pipe_config, old_state);
 
-	if (HAS_PCH_CPT(dev))
+	if (HAS_PCH_CPT(dev_priv))
 		cpt_verify_modeset(dev, intel_crtc->pipe);
 
 	/* Must wait for vblank to avoid spurious PCH FIFO underruns */
 	if (intel_crtc->config->has_pch_encoder)
-		intel_wait_for_vblank(dev, pipe);
+		intel_wait_for_vblank(dev_priv, pipe);
 	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 	intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
 }
@@ -5396,18 +5378,19 @@ static void ironlake_crtc_enable(struct
 /* IPS only exists on ULT machines and is tied to pipe A. */
 static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
 {
-	return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
+	return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A;
 }
 
 static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
 				struct drm_atomic_state *old_state)
 {
 	struct drm_crtc *crtc = pipe_config->base.crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe, hsw_workaround_pipe;
 	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_state);
 
 	if (WARN_ON(intel_crtc->active))
 		return;
@@ -5462,7 +5445,7 @@ static void haswell_crtc_enable(struct i
 	if (!transcoder_is_dsi(cpu_transcoder))
 		intel_ddi_enable_pipe_clock(intel_crtc);
 
-	if (INTEL_INFO(dev)->gen >= 9)
+	if (INTEL_GEN(dev_priv) >= 9)
 		skylake_pfit_enable(intel_crtc);
 	else
 		ironlake_pfit_enable(intel_crtc);
@@ -5478,9 +5461,10 @@ static void haswell_crtc_enable(struct i
 		intel_ddi_enable_transcoder_func(crtc);
 
 	if (dev_priv->display.initial_watermarks != NULL)
-		dev_priv->display.initial_watermarks(pipe_config);
+		dev_priv->display.initial_watermarks(old_intel_state,
+						     pipe_config);
 	else
-		intel_update_watermarks(crtc);
+		intel_update_watermarks(intel_crtc);
 
 	/* XXX: Do the pipe assertions at the right place for BXT DSI. */
 	if (!transcoder_is_dsi(cpu_transcoder))
@@ -5489,7 +5473,7 @@ static void haswell_crtc_enable(struct i
 	if (intel_crtc->config->has_pch_encoder)
 		lpt_pch_enable(crtc);
 
-	if (intel_crtc->config->dp_encoder_is_mst)
+	if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))
 		intel_ddi_set_vc_payload_alloc(crtc, true);
 
 	assert_vblank_disabled(crtc);
@@ -5498,8 +5482,8 @@ static void haswell_crtc_enable(struct i
 	intel_encoders_enable(crtc, pipe_config, old_state);
 
 	if (intel_crtc->config->has_pch_encoder) {
-		intel_wait_for_vblank(dev, pipe);
-		intel_wait_for_vblank(dev, pipe);
+		intel_wait_for_vblank(dev_priv, pipe);
+		intel_wait_for_vblank(dev_priv, pipe);
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, TRANSCODER_A,
 						      true);
@@ -5508,9 +5492,9 @@ static void haswell_crtc_enable(struct i
 	/* If we change the relative order between pipe/planes enabling, we need
 	 * to change the workaround. */
 	hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
-	if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) {
-		intel_wait_for_vblank(dev, hsw_workaround_pipe);
-		intel_wait_for_vblank(dev, hsw_workaround_pipe);
+	if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) {
+		intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);
+		intel_wait_for_vblank(dev_priv, hsw_workaround_pipe);
 	}
 }
 
@@ -5565,7 +5549,7 @@ static void ironlake_crtc_disable(struct
 	if (intel_crtc->config->has_pch_encoder) {
 		ironlake_disable_pch_transcoder(dev_priv, pipe);
 
-		if (HAS_PCH_CPT(dev)) {
+		if (HAS_PCH_CPT(dev_priv)) {
 			i915_reg_t reg;
 			u32 temp;
 
@@ -5594,8 +5578,7 @@ static void haswell_crtc_disable(struct
 				 struct drm_atomic_state *old_state)
 {
 	struct drm_crtc *crtc = old_crtc_state->base.crtc;
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
 
@@ -5612,13 +5595,13 @@ static void haswell_crtc_disable(struct
 	if (!transcoder_is_dsi(cpu_transcoder))
 		intel_disable_pipe(intel_crtc);
 
-	if (intel_crtc->config->dp_encoder_is_mst)
+	if (intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DP_MST))
 		intel_ddi_set_vc_payload_alloc(crtc, false);
 
 	if (!transcoder_is_dsi(cpu_transcoder))
 		intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
-	if (INTEL_INFO(dev)->gen >= 9)
+	if (INTEL_GEN(dev_priv) >= 9)
 		skylake_scaler_disable(intel_crtc);
 	else
 		ironlake_pfit_disable(intel_crtc, false);
@@ -5699,13 +5682,13 @@ static enum intel_display_power_domain p
 enum intel_display_power_domain
 intel_display_port_power_domain(struct intel_encoder *intel_encoder)
 {
-	struct drm_device *dev = intel_encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
 	struct intel_digital_port *intel_dig_port;
 
 	switch (intel_encoder->type) {
 	case INTEL_OUTPUT_UNKNOWN:
 		/* Only DDI platforms should ever use this output type */
-		WARN_ON_ONCE(!HAS_DDI(dev));
+		WARN_ON_ONCE(!HAS_DDI(dev_priv));
 	case INTEL_OUTPUT_DP:
 	case INTEL_OUTPUT_HDMI:
 	case INTEL_OUTPUT_EDP:
@@ -5726,7 +5709,7 @@ intel_display_port_power_domain(struct i
 enum intel_display_power_domain
 intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder)
 {
-	struct drm_device *dev = intel_encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
 	struct intel_digital_port *intel_dig_port;
 
 	switch (intel_encoder->type) {
@@ -5739,7 +5722,7 @@ intel_display_port_aux_power_domain(stru
 		 * what's the status of the given connectors, play safe and
 		 * run the DP detection too.
 		 */
-		WARN_ON_ONCE(!HAS_DDI(dev));
+		WARN_ON_ONCE(!HAS_DDI(dev_priv));
 	case INTEL_OUTPUT_DP:
 	case INTEL_OUTPUT_EDP:
 		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
@@ -5831,11 +5814,9 @@ static int intel_compute_max_dotclk(stru
 
 static int skl_calc_cdclk(int max_pixclk, int vco);
 
-static void intel_update_max_cdclk(struct drm_device *dev)
+static void intel_update_max_cdclk(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
 		u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
 		int max_cdclk, vco;
 
@@ -5857,9 +5838,9 @@ static void intel_update_max_cdclk(struc
 			max_cdclk = 308571;
 
 		dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
-	} else if (IS_BROXTON(dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		dev_priv->max_cdclk_freq = 624000;
-	} else if (IS_BROADWELL(dev))  {
+	} else if (IS_BROADWELL(dev_priv))  {
 		/*
 		 * FIXME with extra cooling we can allow
 		 * 540 MHz for ULX and 675 Mhz for ULT.
@@ -5868,15 +5849,15 @@ static void intel_update_max_cdclk(struc
 		 */
 		if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT)
 			dev_priv->max_cdclk_freq = 450000;
-		else if (IS_BDW_ULX(dev))
+		else if (IS_BDW_ULX(dev_priv))
 			dev_priv->max_cdclk_freq = 450000;
-		else if (IS_BDW_ULT(dev))
+		else if (IS_BDW_ULT(dev_priv))
 			dev_priv->max_cdclk_freq = 540000;
 		else
 			dev_priv->max_cdclk_freq = 675000;
-	} else if (IS_CHERRYVIEW(dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		dev_priv->max_cdclk_freq = 320000;
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		dev_priv->max_cdclk_freq = 400000;
 	} else {
 		/* otherwise assume cdclk is fixed */
@@ -5892,11 +5873,9 @@ static void intel_update_max_cdclk(struc
 			 dev_priv->max_dotclk_freq);
 }
 
-static void intel_update_cdclk(struct drm_device *dev)
+static void intel_update_cdclk(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
+	dev_priv->cdclk_freq = dev_priv->display.get_display_clock_speed(dev_priv);
 
 	if (INTEL_GEN(dev_priv) >= 9)
 		DRM_DEBUG_DRIVER("Current CD clock rate: %d kHz, VCO: %d kHz, ref: %d kHz\n",
@@ -6057,14 +6036,14 @@ static void bxt_set_cdclk(struct drm_i91
 		return;
 	}
 
-	intel_update_cdclk(&dev_priv->drm);
+	intel_update_cdclk(dev_priv);
 }
 
 static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
 {
 	u32 cdctl, expected;
 
-	intel_update_cdclk(&dev_priv->drm);
+	intel_update_cdclk(dev_priv);
 
 	if (dev_priv->cdclk_pll.vco == 0 ||
 	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
@@ -6197,7 +6176,7 @@ void skl_set_preferred_cdclk_vco(struct
 	dev_priv->skl_preferred_vco_freq = vco;
 
 	if (changed)
-		intel_update_max_cdclk(&dev_priv->drm);
+		intel_update_max_cdclk(dev_priv);
 }
 
 static void
@@ -6262,36 +6241,24 @@ skl_dpll0_disable(struct drm_i915_privat
 	dev_priv->cdclk_pll.vco = 0;
 }
 
-static bool skl_cdclk_pcu_ready(struct drm_i915_private *dev_priv)
-{
-	int ret;
-	u32 val;
-
-	/* inform PCU we want to change CDCLK */
-	val = SKL_CDCLK_PREPARE_FOR_CHANGE;
-	mutex_lock(&dev_priv->rps.hw_lock);
-	ret = sandybridge_pcode_read(dev_priv, SKL_PCODE_CDCLK_CONTROL, &val);
-	mutex_unlock(&dev_priv->rps.hw_lock);
-
-	return ret == 0 && (val & SKL_CDCLK_READY_FOR_CHANGE);
-}
-
-static bool skl_cdclk_wait_for_pcu_ready(struct drm_i915_private *dev_priv)
-{
-	return _wait_for(skl_cdclk_pcu_ready(dev_priv), 3000, 10) == 0;
-}
-
 static void skl_set_cdclk(struct drm_i915_private *dev_priv, int cdclk, int vco)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	u32 freq_select, pcu_ack;
+	int ret;
 
 	WARN_ON((cdclk == 24000) != (vco == 0));
 
 	DRM_DEBUG_DRIVER("Changing CDCLK to %d kHz (VCO %d kHz)\n", cdclk, vco);
 
-	if (!skl_cdclk_wait_for_pcu_ready(dev_priv)) {
-		DRM_ERROR("failed to inform PCU about cdclk change\n");
+	mutex_lock(&dev_priv->rps.hw_lock);
+	ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
+				SKL_CDCLK_PREPARE_FOR_CHANGE,
+				SKL_CDCLK_READY_FOR_CHANGE,
+				SKL_CDCLK_READY_FOR_CHANGE, 3);
+	mutex_unlock(&dev_priv->rps.hw_lock);
+	if (ret) {
+		DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
+			  ret);
 		return;
 	}
 
@@ -6334,7 +6301,7 @@ static void skl_set_cdclk(struct drm_i91
 	sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	intel_update_cdclk(dev);
+	intel_update_cdclk(dev_priv);
 }
 
 static void skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
@@ -6381,7 +6348,7 @@ static void skl_sanitize_cdclk(struct dr
 	if ((I915_READ(SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
 		goto sanitize;
 
-	intel_update_cdclk(&dev_priv->drm);
+	intel_update_cdclk(dev_priv);
 	/* Is PLL enabled and locked ? */
 	if (dev_priv->cdclk_pll.vco == 0 ||
 	    dev_priv->cdclk_freq == dev_priv->cdclk_pll.ref)
@@ -6415,7 +6382,7 @@ static void valleyview_set_cdclk(struct
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
-	WARN_ON(dev_priv->display.get_display_clock_speed(dev)
+	WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
 					!= dev_priv->cdclk_freq);
 
 	if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
@@ -6472,7 +6439,7 @@ static void valleyview_set_cdclk(struct
 
 	mutex_unlock(&dev_priv->sb_lock);
 
-	intel_update_cdclk(dev);
+	intel_update_cdclk(dev_priv);
 }
 
 static void cherryview_set_cdclk(struct drm_device *dev, int cdclk)
@@ -6480,7 +6447,7 @@ static void cherryview_set_cdclk(struct
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 val, cmd;
 
-	WARN_ON(dev_priv->display.get_display_clock_speed(dev)
+	WARN_ON(dev_priv->display.get_display_clock_speed(dev_priv)
 						!= dev_priv->cdclk_freq);
 
 	switch (cdclk) {
@@ -6513,7 +6480,7 @@ static void cherryview_set_cdclk(struct
 	}
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	intel_update_cdclk(dev);
+	intel_update_cdclk(dev_priv);
 }
 
 static int valleyview_calc_cdclk(struct drm_i915_private *dev_priv,
@@ -6676,7 +6643,7 @@ static void valleyview_modeset_commit_cd
 	 */
 	intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
 
-	if (IS_CHERRYVIEW(dev))
+	if (IS_CHERRYVIEW(dev_priv))
 		cherryview_set_cdclk(dev, req_cdclk);
 	else
 		valleyview_set_cdclk(dev, req_cdclk);
@@ -6704,7 +6671,7 @@ static void valleyview_crtc_enable(struc
 	intel_set_pipe_timings(intel_crtc);
 	intel_set_pipe_src_size(intel_crtc);
 
-	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) {
+	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
 		struct drm_i915_private *dev_priv = to_i915(dev);
 
 		I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY);
@@ -6719,7 +6686,7 @@ static void valleyview_crtc_enable(struc
 
 	intel_encoders_pre_pll_enable(crtc, pipe_config, old_state);
 
-	if (IS_CHERRYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev_priv)) {
 		chv_prepare_pll(intel_crtc, intel_crtc->config);
 		chv_enable_pll(intel_crtc, intel_crtc->config);
 	} else {
@@ -6733,7 +6700,7 @@ static void valleyview_crtc_enable(struc
 
 	intel_color_load_luts(&pipe_config->base);
 
-	intel_update_watermarks(crtc);
+	intel_update_watermarks(intel_crtc);
 	intel_enable_pipe(intel_crtc);
 
 	assert_vblank_disabled(crtc);
@@ -6775,7 +6742,7 @@ static void i9xx_crtc_enable(struct inte
 
 	intel_crtc->active = true;
 
-	if (!IS_GEN2(dev))
+	if (!IS_GEN2(dev_priv))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
 
 	intel_encoders_pre_enable(crtc, pipe_config, old_state);
@@ -6786,7 +6753,7 @@ static void i9xx_crtc_enable(struct inte
 
 	intel_color_load_luts(&pipe_config->base);
 
-	intel_update_watermarks(crtc);
+	intel_update_watermarks(intel_crtc);
 	intel_enable_pipe(intel_crtc);
 
 	assert_vblank_disabled(crtc);
@@ -6823,8 +6790,8 @@ static void i9xx_crtc_disable(struct int
 	 * On gen2 planes are double buffered but the pipe isn't, so we must
 	 * wait for planes to fully turn off before disabling the pipe.
 	 */
-	if (IS_GEN2(dev))
-		intel_wait_for_vblank(dev, pipe);
+	if (IS_GEN2(dev_priv))
+		intel_wait_for_vblank(dev_priv, pipe);
 
 	intel_encoders_disable(crtc, old_crtc_state, old_state);
 
@@ -6838,9 +6805,9 @@ static void i9xx_crtc_disable(struct int
 	intel_encoders_post_disable(crtc, old_crtc_state, old_state);
 
 	if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) {
-		if (IS_CHERRYVIEW(dev))
+		if (IS_CHERRYVIEW(dev_priv))
 			chv_disable_pll(dev_priv, pipe);
-		else if (IS_VALLEYVIEW(dev))
+		else if (IS_VALLEYVIEW(dev_priv))
 			vlv_disable_pll(dev_priv, pipe);
 		else
 			i9xx_disable_pll(intel_crtc);
@@ -6848,7 +6815,7 @@ static void i9xx_crtc_disable(struct int
 
 	intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state);
 
-	if (!IS_GEN2(dev))
+	if (!IS_GEN2(dev_priv))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 }
 
@@ -6876,6 +6843,12 @@ static void intel_crtc_disable_noatomic(
 	}
 
 	state = drm_atomic_state_alloc(crtc->dev);
+	if (!state) {
+		DRM_DEBUG_KMS("failed to disable [CRTC:%d:%s], out of memory",
+			      crtc->base.id, crtc->name);
+		return;
+	}
+
 	state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
 
 	/* Everything's already locked, -EDEADLK can't happen. */
@@ -6886,7 +6859,7 @@ static void intel_crtc_disable_noatomic(
 
 	dev_priv->display.crtc_disable(crtc_state, state);
 
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 
 	DRM_DEBUG_KMS("[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n",
 		      crtc->base.id, crtc->name);
@@ -6902,7 +6875,7 @@ static void intel_crtc_disable_noatomic(
 		encoder->base.crtc = NULL;
 
 	intel_fbc_disable(intel_crtc);
-	intel_update_watermarks(crtc);
+	intel_update_watermarks(intel_crtc);
 	intel_disable_shared_dpll(intel_crtc);
 
 	domains = intel_crtc->enabled_power_domains;
@@ -7028,6 +7001,7 @@ static int pipe_required_fdi_lanes(struc
 static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
 				     struct intel_crtc_state *pipe_config)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_atomic_state *state = pipe_config->base.state;
 	struct intel_crtc *other_crtc;
 	struct intel_crtc_state *other_crtc_state;
@@ -7040,7 +7014,7 @@ static int ironlake_check_fdi_lanes(stru
 		return -EINVAL;
 	}
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		if (pipe_config->fdi_lanes > 2) {
 			DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n",
 				      pipe_config->fdi_lanes);
@@ -7050,7 +7024,7 @@ static int ironlake_check_fdi_lanes(stru
 		}
 	}
 
-	if (INTEL_INFO(dev)->num_pipes == 2)
+	if (INTEL_INFO(dev_priv)->num_pipes == 2)
 		return 0;
 
 	/* Ivybridge 3 pipe is really complicated */
@@ -7061,7 +7035,7 @@ static int ironlake_check_fdi_lanes(stru
 		if (pipe_config->fdi_lanes <= 2)
 			return 0;
 
-		other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_C));
+		other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_C);
 		other_crtc_state =
 			intel_atomic_get_crtc_state(state, other_crtc);
 		if (IS_ERR(other_crtc_state))
@@ -7080,7 +7054,7 @@ static int ironlake_check_fdi_lanes(stru
 			return -EINVAL;
 		}
 
-		other_crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev, PIPE_B));
+		other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_B);
 		other_crtc_state =
 			intel_atomic_get_crtc_state(state, other_crtc);
 		if (IS_ERR(other_crtc_state))
@@ -7191,7 +7165,7 @@ static int intel_crtc_compute_config(str
 	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 	int clock_limit = dev_priv->max_dotclk_freq;
 
-	if (INTEL_INFO(dev)->gen < 4) {
+	if (INTEL_GEN(dev_priv) < 4) {
 		clock_limit = dev_priv->max_cdclk_freq * 9 / 10;
 
 		/*
@@ -7225,11 +7199,11 @@ static int intel_crtc_compute_config(str
 	/* Cantiga+ cannot handle modes with a hsync front porch of 0.
 	 * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw.
 	 */
-	if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) &&
+	if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) &&
 		adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay)
 		return -EINVAL;
 
-	if (HAS_IPS(dev))
+	if (HAS_IPS(dev_priv))
 		hsw_compute_ips_config(crtc, pipe_config);
 
 	if (pipe_config->has_pch_encoder)
@@ -7238,10 +7212,9 @@ static int intel_crtc_compute_config(str
 	return 0;
 }
 
-static int skylake_get_display_clock_speed(struct drm_device *dev)
+static int skylake_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	uint32_t cdctl;
+	u32 cdctl;
 
 	skl_dpll0_update(dev_priv);
 
@@ -7300,9 +7273,8 @@ static void bxt_de_pll_update(struct drm
 		dev_priv->cdclk_pll.ref;
 }
 
-static int broxton_get_display_clock_speed(struct drm_device *dev)
+static int broxton_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 divider;
 	int div, vco;
 
@@ -7335,9 +7307,8 @@ static int broxton_get_display_clock_spe
 	return DIV_ROUND_CLOSEST(vco, div);
 }
 
-static int broadwell_get_display_clock_speed(struct drm_device *dev)
+static int broadwell_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t lcpll = I915_READ(LCPLL_CTL);
 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
 
@@ -7355,9 +7326,8 @@ static int broadwell_get_display_clock_s
 		return 675000;
 }
 
-static int haswell_get_display_clock_speed(struct drm_device *dev)
+static int haswell_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t lcpll = I915_READ(LCPLL_CTL);
 	uint32_t freq = lcpll & LCPLL_CLK_FREQ_MASK;
 
@@ -7367,41 +7337,41 @@ static int haswell_get_display_clock_spe
 		return 450000;
 	else if (freq == LCPLL_CLK_FREQ_450)
 		return 450000;
-	else if (IS_HSW_ULT(dev))
+	else if (IS_HSW_ULT(dev_priv))
 		return 337500;
 	else
 		return 540000;
 }
 
-static int valleyview_get_display_clock_speed(struct drm_device *dev)
+static int valleyview_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	return vlv_get_cck_clock_hpll(to_i915(dev), "cdclk",
+	return vlv_get_cck_clock_hpll(dev_priv, "cdclk",
 				      CCK_DISPLAY_CLOCK_CONTROL);
 }
 
-static int ilk_get_display_clock_speed(struct drm_device *dev)
+static int ilk_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
 	return 450000;
 }
 
-static int i945_get_display_clock_speed(struct drm_device *dev)
+static int i945_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
 	return 400000;
 }
 
-static int i915_get_display_clock_speed(struct drm_device *dev)
+static int i915_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
 	return 333333;
 }
 
-static int i9xx_misc_get_display_clock_speed(struct drm_device *dev)
+static int i9xx_misc_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
 	return 200000;
 }
 
-static int pnv_get_display_clock_speed(struct drm_device *dev)
+static int pnv_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct pci_dev *pdev = dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 gcfgc = 0;
 
 	pci_read_config_word(pdev, GCFGC, &gcfgc);
@@ -7424,9 +7394,9 @@ static int pnv_get_display_clock_speed(s
 	}
 }
 
-static int i915gm_get_display_clock_speed(struct drm_device *dev)
+static int i915gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct pci_dev *pdev = dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 gcfgc = 0;
 
 	pci_read_config_word(pdev, GCFGC, &gcfgc);
@@ -7444,14 +7414,14 @@ static int i915gm_get_display_clock_spee
 	}
 }
 
-static int i865_get_display_clock_speed(struct drm_device *dev)
+static int i865_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
 	return 266667;
 }
 
-static int i85x_get_display_clock_speed(struct drm_device *dev)
+static int i85x_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct pci_dev *pdev = dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u16 hpllcc = 0;
 
 	/*
@@ -7487,14 +7457,13 @@ static int i85x_get_display_clock_speed(
 	return 0;
 }
 
-static int i830_get_display_clock_speed(struct drm_device *dev)
+static int i830_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
 	return 133333;
 }
 
-static unsigned int intel_hpll_vco(struct drm_device *dev)
+static unsigned int intel_hpll_vco(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	static const unsigned int blb_vco[8] = {
 		[0] = 3200000,
 		[1] = 4000000,
@@ -7537,20 +7506,20 @@ static unsigned int intel_hpll_vco(struc
 	uint8_t tmp = 0;
 
 	/* FIXME other chipsets? */
-	if (IS_GM45(dev))
+	if (IS_GM45(dev_priv))
 		vco_table = ctg_vco;
-	else if (IS_G4X(dev))
+	else if (IS_G4X(dev_priv))
 		vco_table = elk_vco;
-	else if (IS_CRESTLINE(dev))
+	else if (IS_CRESTLINE(dev_priv))
 		vco_table = cl_vco;
-	else if (IS_PINEVIEW(dev))
+	else if (IS_PINEVIEW(dev_priv))
 		vco_table = pnv_vco;
-	else if (IS_G33(dev))
+	else if (IS_G33(dev_priv))
 		vco_table = blb_vco;
 	else
 		return 0;
 
-	tmp = I915_READ(IS_MOBILE(dev) ? HPLLVCO_MOBILE : HPLLVCO);
+	tmp = I915_READ(IS_MOBILE(dev_priv) ? HPLLVCO_MOBILE : HPLLVCO);
 
 	vco = vco_table[tmp & 0x7];
 	if (vco == 0)
@@ -7561,10 +7530,10 @@ static unsigned int intel_hpll_vco(struc
 	return vco;
 }
 
-static int gm45_get_display_clock_speed(struct drm_device *dev)
+static int gm45_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct pci_dev *pdev = dev->pdev;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
 	uint16_t tmp = 0;
 
 	pci_read_config_word(pdev, GCFGC, &tmp);
@@ -7584,14 +7553,14 @@ static int gm45_get_display_clock_speed(
 	}
 }
 
-static int i965gm_get_display_clock_speed(struct drm_device *dev)
+static int i965gm_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct pci_dev *pdev = dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	static const uint8_t div_3200[] = { 16, 10,  8 };
 	static const uint8_t div_4000[] = { 20, 12, 10 };
 	static const uint8_t div_5333[] = { 24, 16, 14 };
 	const uint8_t *div_table;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
+	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
 	uint16_t tmp = 0;
 
 	pci_read_config_word(pdev, GCFGC, &tmp);
@@ -7622,15 +7591,15 @@ fail:
 	return 200000;
 }
 
-static int g33_get_display_clock_speed(struct drm_device *dev)
+static int g33_get_display_clock_speed(struct drm_i915_private *dev_priv)
 {
-	struct pci_dev *pdev = dev->pdev;
+	struct pci_dev *pdev = dev_priv->drm.pdev;
 	static const uint8_t div_3200[] = { 12, 10,  8,  7, 5, 16 };
 	static const uint8_t div_4000[] = { 14, 12, 10,  8, 6, 20 };
 	static const uint8_t div_4800[] = { 20, 14, 12, 10, 8, 24 };
 	static const uint8_t div_5333[] = { 20, 16, 12, 12, 8, 28 };
 	const uint8_t *div_table;
-	unsigned int cdclk_sel, vco = intel_hpll_vco(dev);
+	unsigned int cdclk_sel, vco = intel_hpll_vco(dev_priv);
 	uint16_t tmp = 0;
 
 	pci_read_config_word(pdev, GCFGC, &tmp);
@@ -7719,10 +7688,10 @@ static void i9xx_update_pll_dividers(str
 				     struct intel_crtc_state *crtc_state,
 				     struct dpll *reduced_clock)
 {
-	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	u32 fp, fp2 = 0;
 
-	if (IS_PINEVIEW(dev)) {
+	if (IS_PINEVIEW(dev_priv)) {
 		fp = pnv_dpll_compute_fp(&crtc_state->dpll);
 		if (reduced_clock)
 			fp2 = pnv_dpll_compute_fp(reduced_clock);
@@ -7790,12 +7759,11 @@ static void intel_cpu_transcoder_set_m_n
 					 struct intel_link_m_n *m_n,
 					 struct intel_link_m_n *m2_n2)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	int pipe = crtc->pipe;
 	enum transcoder transcoder = crtc->config->cpu_transcoder;
 
-	if (INTEL_INFO(dev)->gen >= 5) {
+	if (INTEL_GEN(dev_priv) >= 5) {
 		I915_WRITE(PIPE_DATA_M1(transcoder), TU_SIZE(m_n->tu) | m_n->gmch_m);
 		I915_WRITE(PIPE_DATA_N1(transcoder), m_n->gmch_n);
 		I915_WRITE(PIPE_LINK_M1(transcoder), m_n->link_m);
@@ -7804,8 +7772,8 @@ static void intel_cpu_transcoder_set_m_n
 		 * for gen < 8) and if DRRS is supported (to make sure the
 		 * registers are not unnecessarily accessed).
 		 */
-		if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) &&
-			crtc->config->has_drrs) {
+		if (m2_n2 && (IS_CHERRYVIEW(dev_priv) ||
+		    INTEL_GEN(dev_priv) < 8) && crtc->config->has_drrs) {
 			I915_WRITE(PIPE_DATA_M2(transcoder),
 					TU_SIZE(m2_n2->tu) | m2_n2->gmch_m);
 			I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n);
@@ -8092,11 +8060,10 @@ static void chv_prepare_pll(struct intel
  * in cases where we need the PLL enabled even when @pipe is not going to
  * be enabled.
  */
-int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
+int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
 		     const struct dpll *dpll)
 {
-	struct intel_crtc *crtc =
-		to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 	struct intel_crtc_state *pipe_config;
 
 	pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL);
@@ -8107,7 +8074,7 @@ int vlv_force_pll_on(struct drm_device *
 	pipe_config->pixel_multiplier = 1;
 	pipe_config->dpll = *dpll;
 
-	if (IS_CHERRYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev_priv)) {
 		chv_compute_dpll(crtc, pipe_config);
 		chv_prepare_pll(crtc, pipe_config);
 		chv_enable_pll(crtc, pipe_config);
@@ -8130,20 +8097,19 @@ int vlv_force_pll_on(struct drm_device *
  * Disable the PLL for @pipe. To be used in cases where we need
  * the PLL enabled even when @pipe is not going to be enabled.
  */
-void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe)
+void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	if (IS_CHERRYVIEW(dev))
-		chv_disable_pll(to_i915(dev), pipe);
+	if (IS_CHERRYVIEW(dev_priv))
+		chv_disable_pll(dev_priv, pipe);
 	else
-		vlv_disable_pll(to_i915(dev), pipe);
+		vlv_disable_pll(dev_priv, pipe);
 }
 
 static void i9xx_compute_dpll(struct intel_crtc *crtc,
 			      struct intel_crtc_state *crtc_state,
 			      struct dpll *reduced_clock)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	u32 dpll;
 	struct dpll *clock = &crtc_state->dpll;
 
@@ -8156,7 +8122,7 @@ static void i9xx_compute_dpll(struct int
 	else
 		dpll |= DPLLB_MODE_DAC_SERIAL;
 
-	if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
+	if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || IS_G33(dev_priv)) {
 		dpll |= (crtc_state->pixel_multiplier - 1)
 			<< SDVO_MULTIPLIER_SHIFT_HIRES;
 	}
@@ -8169,11 +8135,11 @@ static void i9xx_compute_dpll(struct int
 		dpll |= DPLL_SDVO_HIGH_SPEED;
 
 	/* compute bitmask from p1 value */
-	if (IS_PINEVIEW(dev))
+	if (IS_PINEVIEW(dev_priv))
 		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW;
 	else {
 		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT;
-		if (IS_G4X(dev) && reduced_clock)
+		if (IS_G4X(dev_priv) && reduced_clock)
 			dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT;
 	}
 	switch (clock->p2) {
@@ -8190,7 +8156,7 @@ static void i9xx_compute_dpll(struct int
 		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
 		break;
 	}
-	if (INTEL_INFO(dev)->gen >= 4)
+	if (INTEL_GEN(dev_priv) >= 4)
 		dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT);
 
 	if (crtc_state->sdvo_tv_clock)
@@ -8204,7 +8170,7 @@ static void i9xx_compute_dpll(struct int
 	dpll |= DPLL_VCO_ENABLE;
 	crtc_state->dpll_hw_state.dpll = dpll;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		u32 dpll_md = (crtc_state->pixel_multiplier - 1)
 			<< DPLL_MD_UDI_MULTIPLIER_SHIFT;
 		crtc_state->dpll_hw_state.dpll_md = dpll_md;
@@ -8235,7 +8201,8 @@ static void i8xx_compute_dpll(struct int
 			dpll |= PLL_P2_DIVIDE_BY_4;
 	}
 
-	if (!IS_I830(dev) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
+	if (!IS_I830(dev_priv) &&
+	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO))
 		dpll |= DPLL_DVO_2X_MODE;
 
 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) &&
@@ -8250,8 +8217,7 @@ static void i8xx_compute_dpll(struct int
 
 static void intel_set_pipe_timings(struct intel_crtc *intel_crtc)
 {
-	struct drm_device *dev = intel_crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
 	enum pipe pipe = intel_crtc->pipe;
 	enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder;
 	const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
@@ -8277,7 +8243,7 @@ static void intel_set_pipe_timings(struc
 			vsyncshift += adjusted_mode->crtc_htotal;
 	}
 
-	if (INTEL_INFO(dev)->gen > 3)
+	if (INTEL_GEN(dev_priv) > 3)
 		I915_WRITE(VSYNCSHIFT(cpu_transcoder), vsyncshift);
 
 	I915_WRITE(HTOTAL(cpu_transcoder),
@@ -8304,7 +8270,7 @@ static void intel_set_pipe_timings(struc
 	 * programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is
 	 * documented on the DDI_FUNC_CTL register description, EDP Input Select
 	 * bits. */
-	if (IS_HASWELL(dev) && cpu_transcoder == TRANSCODER_EDP &&
+	if (IS_HASWELL(dev_priv) && cpu_transcoder == TRANSCODER_EDP &&
 	    (pipe == PIPE_B || pipe == PIPE_C))
 		I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder)));
 
@@ -8400,8 +8366,7 @@ void intel_mode_from_pipe_config(struct
 
 static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc)
 {
-	struct drm_device *dev = intel_crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
 	uint32_t pipeconf;
 
 	pipeconf = 0;
@@ -8414,7 +8379,8 @@ static void i9xx_set_pipeconf(struct int
 		pipeconf |= PIPECONF_DOUBLE_WIDE;
 
 	/* only g4x and later have fancy bpc/dither controls */
-	if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+	    IS_CHERRYVIEW(dev_priv)) {
 		/* Bspec claims that we can't use dithering for 30bpp pipes. */
 		if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30)
 			pipeconf |= PIPECONF_DITHER_EN |
@@ -8436,7 +8402,7 @@ static void i9xx_set_pipeconf(struct int
 		}
 	}
 
-	if (HAS_PIPE_CXSR(dev)) {
+	if (HAS_PIPE_CXSR(dev_priv)) {
 		if (intel_crtc->lowfreq_avail) {
 			DRM_DEBUG_KMS("enabling CxSR downclocking\n");
 			pipeconf |= PIPECONF_CXSR_DOWNCLOCK;
@@ -8446,7 +8412,7 @@ static void i9xx_set_pipeconf(struct int
 	}
 
 	if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) {
-		if (INTEL_INFO(dev)->gen < 4 ||
+		if (INTEL_GEN(dev_priv) < 4 ||
 		    intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_SDVO))
 			pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;
 		else
@@ -8454,7 +8420,7 @@ static void i9xx_set_pipeconf(struct int
 	} else
 		pipeconf |= PIPECONF_PROGRESSIVE;
 
-	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 	     intel_crtc->config->limited_color_range)
 		pipeconf |= PIPECONF_COLOR_RANGE_SELECT;
 
@@ -8654,11 +8620,11 @@ static int vlv_crtc_compute_clock(struct
 static void i9xx_get_pfit_config(struct intel_crtc *crtc,
 				 struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	uint32_t tmp;
 
-	if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev)))
+	if (INTEL_GEN(dev_priv) <= 3 &&
+	    (IS_I830(dev_priv) || !IS_MOBILE(dev_priv)))
 		return;
 
 	tmp = I915_READ(PFIT_CONTROL);
@@ -8666,7 +8632,7 @@ static void i9xx_get_pfit_config(struct
 		return;
 
 	/* Check whether the pfit is attached to our pipe. */
-	if (INTEL_INFO(dev)->gen < 4) {
+	if (INTEL_GEN(dev_priv) < 4) {
 		if (crtc->pipe != PIPE_B)
 			return;
 	} else {
@@ -8730,10 +8696,10 @@ i9xx_get_initial_plane_config(struct int
 
 	fb = &intel_fb->base;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		if (val & DISPPLANE_TILED) {
 			plane_config->tiling = I915_TILING_X;
-			fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+			fb->modifier = I915_FORMAT_MOD_X_TILED;
 		}
 	}
 
@@ -8742,7 +8708,7 @@ i9xx_get_initial_plane_config(struct int
 	fb->pixel_format = fourcc;
 	fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		if (plane_config->tiling)
 			offset = I915_READ(DSPTILEOFF(plane));
 		else
@@ -8762,7 +8728,7 @@ i9xx_get_initial_plane_config(struct int
 
 	aligned_height = intel_fb_align_height(dev, fb->height,
 					       fb->pixel_format,
-					       fb->modifier[0]);
+					       fb->modifier);
 
 	plane_config->size = fb->pitches[0] * aligned_height;
 
@@ -8811,8 +8777,7 @@ static void chv_crtc_clock_get(struct in
 static bool i9xx_get_pipe_config(struct intel_crtc *crtc,
 				 struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum intel_display_power_domain power_domain;
 	uint32_t tmp;
 	bool ret;
@@ -8830,7 +8795,8 @@ static bool i9xx_get_pipe_config(struct
 	if (!(tmp & PIPECONF_ENABLE))
 		goto out;
 
-	if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+	    IS_CHERRYVIEW(dev_priv)) {
 		switch (tmp & PIPECONF_BPC_MASK) {
 		case PIPECONF_6BPC:
 			pipe_config->pipe_bpp = 18;
@@ -8846,11 +8812,11 @@ static bool i9xx_get_pipe_config(struct
 		}
 	}
 
-	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 	    (tmp & PIPECONF_COLOR_RANGE_SELECT))
 		pipe_config->limited_color_range = true;
 
-	if (INTEL_INFO(dev)->gen < 4)
+	if (INTEL_GEN(dev_priv) < 4)
 		pipe_config->double_wide = tmp & PIPECONF_DOUBLE_WIDE;
 
 	intel_get_pipe_timings(crtc, pipe_config);
@@ -8858,9 +8824,9 @@ static bool i9xx_get_pipe_config(struct
 
 	i9xx_get_pfit_config(crtc, pipe_config);
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		/* No way to read it out on pipes B and C */
-		if (IS_CHERRYVIEW(dev) && crtc->pipe != PIPE_A)
+		if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A)
 			tmp = dev_priv->chv_dpll_md[crtc->pipe];
 		else
 			tmp = I915_READ(DPLL_MD(crtc->pipe));
@@ -8868,7 +8834,8 @@ static bool i9xx_get_pipe_config(struct
 			((tmp & DPLL_MD_UDI_MULTIPLIER_MASK)
 			 >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1;
 		pipe_config->dpll_hw_state.dpll_md = tmp;
-	} else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
+	} else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
+		   IS_G33(dev_priv)) {
 		tmp = I915_READ(DPLL(crtc->pipe));
 		pipe_config->pixel_multiplier =
 			((tmp & SDVO_MULTIPLIER_MASK)
@@ -8880,13 +8847,13 @@ static bool i9xx_get_pipe_config(struct
 		pipe_config->pixel_multiplier = 1;
 	}
 	pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe));
-	if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
 		/*
 		 * DPLL_DVO_2X_MODE must be enabled for both DPLLs
 		 * on 830. Filter it out here so that we don't
 		 * report errors due to that.
 		 */
-		if (IS_I830(dev))
+		if (IS_I830(dev_priv))
 			pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE;
 
 		pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe));
@@ -8898,9 +8865,9 @@ static bool i9xx_get_pipe_config(struct
 						     DPLL_PORTB_READY_MASK);
 	}
 
-	if (IS_CHERRYVIEW(dev))
+	if (IS_CHERRYVIEW(dev_priv))
 		chv_crtc_clock_get(crtc, pipe_config);
-	else if (IS_VALLEYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev_priv))
 		vlv_crtc_clock_get(crtc, pipe_config);
 	else
 		i9xx_crtc_clock_get(crtc, pipe_config);
@@ -8951,7 +8918,7 @@ static void ironlake_init_pch_refclk(str
 		}
 	}
 
-	if (HAS_PCH_IBX(dev)) {
+	if (HAS_PCH_IBX(dev_priv)) {
 		has_ck505 = dev_priv->vbt.display_clock_mode;
 		can_ssc = has_ck505;
 	} else {
@@ -9199,7 +9166,8 @@ static void lpt_enable_clkout_dp(struct
 
 	if (WARN(with_fdi && !with_spread, "FDI requires downspread\n"))
 		with_spread = true;
-	if (WARN(HAS_PCH_LPT_LP(dev) && with_fdi, "LP PCH doesn't have FDI\n"))
+	if (WARN(HAS_PCH_LPT_LP(dev_priv) &&
+	    with_fdi, "LP PCH doesn't have FDI\n"))
 		with_fdi = false;
 
 	mutex_lock(&dev_priv->sb_lock);
@@ -9222,7 +9190,7 @@ static void lpt_enable_clkout_dp(struct
 		}
 	}
 
-	reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
+	reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
 	tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
 	tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE;
 	intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
@@ -9238,7 +9206,7 @@ static void lpt_disable_clkout_dp(struct
 
 	mutex_lock(&dev_priv->sb_lock);
 
-	reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0;
+	reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0;
 	tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK);
 	tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE;
 	intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK);
@@ -9346,9 +9314,11 @@ static void lpt_init_pch_refclk(struct d
  */
 void intel_init_pch_refclk(struct drm_device *dev)
 {
-	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
 		ironlake_init_pch_refclk(dev);
-	else if (HAS_PCH_LPT(dev))
+	else if (HAS_PCH_LPT(dev_priv))
 		lpt_init_pch_refclk(dev);
 }
 
@@ -9477,7 +9447,7 @@ static void ironlake_compute_dpll(struct
 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) {
 		if ((intel_panel_use_ssc(dev_priv) &&
 		     dev_priv->vbt.lvds_ssc_freq == 100000) ||
-		    (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev)))
+		    (HAS_PCH_IBX(dev_priv) && intel_is_dual_link_lvds(dev)))
 			factor = 25;
 	} else if (crtc_state->sdvo_tv_clock)
 		factor = 20;
@@ -9651,11 +9621,10 @@ static void intel_cpu_transcoder_get_m_n
 					 struct intel_link_m_n *m_n,
 					 struct intel_link_m_n *m2_n2)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum pipe pipe = crtc->pipe;
 
-	if (INTEL_INFO(dev)->gen >= 5) {
+	if (INTEL_GEN(dev_priv) >= 5) {
 		m_n->link_m = I915_READ(PIPE_LINK_M1(transcoder));
 		m_n->link_n = I915_READ(PIPE_LINK_N1(transcoder));
 		m_n->gmch_m = I915_READ(PIPE_DATA_M1(transcoder))
@@ -9667,7 +9636,7 @@ static void intel_cpu_transcoder_get_m_n
 		 * gen < 8) and if DRRS is supported (to make sure the
 		 * registers are not unnecessarily read).
 		 */
-		if (m2_n2 && INTEL_INFO(dev)->gen < 8 &&
+		if (m2_n2 && INTEL_GEN(dev_priv) < 8 &&
 			crtc->config->has_drrs) {
 			m2_n2->link_m = I915_READ(PIPE_LINK_M2(transcoder));
 			m2_n2->link_n =	I915_READ(PIPE_LINK_N2(transcoder));
@@ -9771,17 +9740,17 @@ skylake_get_initial_plane_config(struct
 	tiling = val & PLANE_CTL_TILED_MASK;
 	switch (tiling) {
 	case PLANE_CTL_TILED_LINEAR:
-		fb->modifier[0] = DRM_FORMAT_MOD_NONE;
+		fb->modifier = DRM_FORMAT_MOD_NONE;
 		break;
 	case PLANE_CTL_TILED_X:
 		plane_config->tiling = I915_TILING_X;
-		fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+		fb->modifier = I915_FORMAT_MOD_X_TILED;
 		break;
 	case PLANE_CTL_TILED_Y:
-		fb->modifier[0] = I915_FORMAT_MOD_Y_TILED;
+		fb->modifier = I915_FORMAT_MOD_Y_TILED;
 		break;
 	case PLANE_CTL_TILED_YF:
-		fb->modifier[0] = I915_FORMAT_MOD_Yf_TILED;
+		fb->modifier = I915_FORMAT_MOD_Yf_TILED;
 		break;
 	default:
 		MISSING_CASE(tiling);
@@ -9798,13 +9767,13 @@ skylake_get_initial_plane_config(struct
 	fb->width = ((val >> 0) & 0x1fff) + 1;
 
 	val = I915_READ(PLANE_STRIDE(pipe, 0));
-	stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
+	stride_mult = intel_fb_stride_alignment(dev_priv, fb->modifier,
 						fb->pixel_format);
 	fb->pitches[0] = (val & 0x3ff) * stride_mult;
 
 	aligned_height = intel_fb_align_height(dev, fb->height,
 					       fb->pixel_format,
-					       fb->modifier[0]);
+					       fb->modifier);
 
 	plane_config->size = fb->pitches[0] * aligned_height;
 
@@ -9837,7 +9806,7 @@ static void ironlake_get_pfit_config(str
 		/* We currently do not free assignements of panel fitters on
 		 * ivb/hsw (since we don't use the higher upscaling modes which
 		 * differentiates them) so just WARN about this case for now. */
-		if (IS_GEN7(dev)) {
+		if (IS_GEN7(dev_priv)) {
 			WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) !=
 				PF_PIPE_SEL_IVB(crtc->pipe));
 		}
@@ -9869,10 +9838,10 @@ ironlake_get_initial_plane_config(struct
 
 	fb = &intel_fb->base;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		if (val & DISPPLANE_TILED) {
 			plane_config->tiling = I915_TILING_X;
-			fb->modifier[0] = I915_FORMAT_MOD_X_TILED;
+			fb->modifier = I915_FORMAT_MOD_X_TILED;
 		}
 	}
 
@@ -9882,7 +9851,7 @@ ironlake_get_initial_plane_config(struct
 	fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8;
 
 	base = I915_READ(DSPSURF(pipe)) & 0xfffff000;
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		offset = I915_READ(DSPOFFSET(pipe));
 	} else {
 		if (plane_config->tiling)
@@ -9901,7 +9870,7 @@ ironlake_get_initial_plane_config(struct
 
 	aligned_height = intel_fb_align_height(dev, fb->height,
 					       fb->pixel_format,
-					       fb->modifier[0]);
+					       fb->modifier);
 
 	plane_config->size = fb->pitches[0] * aligned_height;
 
@@ -10026,7 +9995,7 @@ static void assert_can_disable_lcpll(str
 	I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
 	I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
 	     "CPU PWM1 enabled\n");
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev_priv))
 		I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE,
 		     "CPU PWM2 enabled\n");
 	I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE,
@@ -10046,9 +10015,7 @@ static void assert_can_disable_lcpll(str
 
 static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv)
 {
-	struct drm_device *dev = &dev_priv->drm;
-
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev_priv))
 		return I915_READ(D_COMP_HSW);
 	else
 		return I915_READ(D_COMP_BDW);
@@ -10056,9 +10023,7 @@ static uint32_t hsw_read_dcomp(struct dr
 
 static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val)
 {
-	struct drm_device *dev = &dev_priv->drm;
-
-	if (IS_HASWELL(dev)) {
+	if (IS_HASWELL(dev_priv)) {
 		mutex_lock(&dev_priv->rps.hw_lock);
 		if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP,
 					    val))
@@ -10173,7 +10138,7 @@ static void hsw_restore_lcpll(struct drm
 	}
 
 	intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
-	intel_update_cdclk(&dev_priv->drm);
+	intel_update_cdclk(dev_priv);
 }
 
 /*
@@ -10206,7 +10171,7 @@ void hsw_enable_pc8(struct drm_i915_priv
 
 	DRM_DEBUG_KMS("Enabling package C8+\n");
 
-	if (HAS_PCH_LPT_LP(dev)) {
+	if (HAS_PCH_LPT_LP(dev_priv)) {
 		val = I915_READ(SOUTH_DSPCLK_GATE_D);
 		val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
 		I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
@@ -10226,7 +10191,7 @@ void hsw_disable_pc8(struct drm_i915_pri
 	hsw_restore_lcpll(dev_priv);
 	lpt_init_pch_refclk(dev);
 
-	if (HAS_PCH_LPT_LP(dev)) {
+	if (HAS_PCH_LPT_LP(dev_priv)) {
 		val = I915_READ(SOUTH_DSPCLK_GATE_D);
 		val |= PCH_LP_PARTITION_LEVEL_DISABLE;
 		I915_WRITE(SOUTH_DSPCLK_GATE_D, val);
@@ -10376,7 +10341,7 @@ static void broadwell_set_cdclk(struct d
 
 	I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
 
-	intel_update_cdclk(dev);
+	intel_update_cdclk(dev_priv);
 
 	WARN(cdclk != dev_priv->cdclk_freq,
 	     "cdclk requested %d kHz but got %d kHz\n",
@@ -10663,8 +10628,7 @@ static bool bxt_get_dsi_transcoder_state
 static void haswell_get_ddi_port_state(struct intel_crtc *crtc,
 				       struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct intel_shared_dpll *pll;
 	enum port port;
 	uint32_t tmp;
@@ -10673,9 +10637,9 @@ static void haswell_get_ddi_port_state(s
 
 	port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT;
 
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		skylake_get_ddi_pll(dev_priv, port, pipe_config);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		bxt_get_ddi_pll(dev_priv, port, pipe_config);
 	else
 		haswell_get_ddi_pll(dev_priv, port, pipe_config);
@@ -10691,7 +10655,7 @@ static void haswell_get_ddi_port_state(s
 	 * DDI E. So just check whether this pipe is wired to DDI E and whether
 	 * the PCH transcoder is on.
 	 */
-	if (INTEL_INFO(dev)->gen < 9 &&
+	if (INTEL_GEN(dev_priv) < 9 &&
 	    (port == PORT_E) && I915_READ(LPT_TRANSCONF) & TRANS_ENABLE) {
 		pipe_config->has_pch_encoder = true;
 
@@ -10706,8 +10670,7 @@ static void haswell_get_ddi_port_state(s
 static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 				    struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum intel_display_power_domain power_domain;
 	unsigned long power_domain_mask;
 	bool active;
@@ -10740,11 +10703,9 @@ static bool haswell_get_pipe_config(stru
 	pipe_config->gamma_mode =
 		I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK;
 
-	if (INTEL_INFO(dev)->gen >= 9) {
-		skl_init_scalers(dev, crtc, pipe_config);
-	}
+	if (INTEL_GEN(dev_priv) >= 9) {
+		skl_init_scalers(dev_priv, crtc, pipe_config);
 
-	if (INTEL_INFO(dev)->gen >= 9) {
 		pipe_config->scaler_state.scaler_id = -1;
 		pipe_config->scaler_state.scaler_users &= ~(1 << SKL_CRTC_INDEX);
 	}
@@ -10752,13 +10713,13 @@ static bool haswell_get_pipe_config(stru
 	power_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
 	if (intel_display_power_get_if_enabled(dev_priv, power_domain)) {
 		power_domain_mask |= BIT(power_domain);
-		if (INTEL_INFO(dev)->gen >= 9)
+		if (INTEL_GEN(dev_priv) >= 9)
 			skylake_get_pfit_config(crtc, pipe_config);
 		else
 			ironlake_get_pfit_config(crtc, pipe_config);
 	}
 
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev_priv))
 		pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) &&
 			(I915_READ(IPS_CTL) & IPS_ENABLE);
 
@@ -10846,13 +10807,9 @@ static void i9xx_update_cursor(struct dr
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	const struct skl_wm_values *wm = &dev_priv->wm.skl_results;
 	int pipe = intel_crtc->pipe;
 	uint32_t cntl = 0;
 
-	if (INTEL_GEN(dev_priv) >= 9 && wm->dirty_pipes & drm_crtc_mask(crtc))
-		skl_write_cursor_wm(intel_crtc, wm);
-
 	if (plane_state && plane_state->base.visible) {
 		cntl = MCURSOR_GAMMA_ENABLE;
 		switch (plane_state->base.crtc_w) {
@@ -10871,10 +10828,10 @@ static void i9xx_update_cursor(struct dr
 		}
 		cntl |= pipe << 28; /* Connect to correct pipe */
 
-		if (HAS_DDI(dev))
+		if (HAS_DDI(dev_priv))
 			cntl |= CURSOR_PIPE_CSC_ENABLE;
 
-		if (plane_state->base.rotation == DRM_ROTATE_180)
+		if (plane_state->base.rotation & DRM_ROTATE_180)
 			cntl |= CURSOR_ROTATE_180;
 	}
 
@@ -10919,8 +10876,8 @@ static void intel_crtc_update_cursor(str
 		pos |= y << CURSOR_Y_SHIFT;
 
 		/* ILK+ do this automagically */
-		if (HAS_GMCH_DISPLAY(dev) &&
-		    plane_state->base.rotation == DRM_ROTATE_180) {
+		if (HAS_GMCH_DISPLAY(dev_priv) &&
+		    plane_state->base.rotation & DRM_ROTATE_180) {
 			base += (plane_state->base.crtc_h *
 				 plane_state->base.crtc_w - 1) * 4;
 		}
@@ -10928,13 +10885,13 @@ static void intel_crtc_update_cursor(str
 
 	I915_WRITE(CURPOS(pipe), pos);
 
-	if (IS_845G(dev) || IS_I865G(dev))
+	if (IS_845G(dev_priv) || IS_I865G(dev_priv))
 		i845_update_cursor(crtc, base, plane_state);
 	else
 		i9xx_update_cursor(crtc, base, plane_state);
 }
 
-static bool cursor_size_ok(struct drm_device *dev,
+static bool cursor_size_ok(struct drm_i915_private *dev_priv,
 			   uint32_t width, uint32_t height)
 {
 	if (width == 0 || height == 0)
@@ -10946,11 +10903,11 @@ static bool cursor_size_ok(struct drm_de
 	 * the precision of the register. Everything else requires
 	 * square cursors, limited to a few power-of-two sizes.
 	 */
-	if (IS_845G(dev) || IS_I865G(dev)) {
+	if (IS_845G(dev_priv) || IS_I865G(dev_priv)) {
 		if ((width & 63) != 0)
 			return false;
 
-		if (width > (IS_845G(dev) ? 64 : 512))
+		if (width > (IS_845G(dev_priv) ? 64 : 512))
 			return false;
 
 		if (height > 1023)
@@ -10959,7 +10916,7 @@ static bool cursor_size_ok(struct drm_de
 		switch (width | height) {
 		case 256:
 		case 128:
-			if (IS_GEN2(dev))
+			if (IS_GEN2(dev_priv))
 				return false;
 		case 64:
 			break;
@@ -11053,7 +11010,7 @@ intel_framebuffer_create_for_mode(struct
 
 	fb = intel_framebuffer_create(dev, &mode_cmd, obj);
 	if (IS_ERR(fb))
-		i915_gem_object_put_unlocked(obj);
+		i915_gem_object_put(obj);
 
 	return fb;
 }
@@ -11138,6 +11095,7 @@ bool intel_get_load_detect_pipe(struct d
 	struct drm_encoder *encoder = &intel_encoder->base;
 	struct drm_crtc *crtc = NULL;
 	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_framebuffer *fb;
 	struct drm_mode_config *config = &dev->mode_config;
 	struct drm_atomic_state *state = NULL, *restore_state = NULL;
@@ -11288,15 +11246,21 @@ found:
 	}
 
 	old->restore_state = restore_state;
+	drm_atomic_state_put(state);
 
 	/* let the connector get through one full cycle before testing */
-	intel_wait_for_vblank(dev, intel_crtc->pipe);
+	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
 	return true;
 
 fail:
-	drm_atomic_state_free(state);
-	drm_atomic_state_free(restore_state);
-	restore_state = state = NULL;
+	if (state) {
+		drm_atomic_state_put(state);
+		state = NULL;
+	}
+	if (restore_state) {
+		drm_atomic_state_put(restore_state);
+		restore_state = NULL;
+	}
 
 	if (ret == -EDEADLK) {
 		drm_modeset_backoff(ctx);
@@ -11324,10 +11288,9 @@ void intel_release_load_detect_pipe(stru
 		return;
 
 	ret = drm_atomic_commit(state);
-	if (ret) {
+	if (ret)
 		DRM_DEBUG_KMS("Couldn't release load detect pipe: %i\n", ret);
-		drm_atomic_state_free(state);
-	}
+	drm_atomic_state_put(state);
 }
 
 static int i9xx_pll_refclk(struct drm_device *dev,
@@ -11338,9 +11301,9 @@ static int i9xx_pll_refclk(struct drm_de
 
 	if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN)
 		return dev_priv->vbt.lvds_ssc_freq;
-	else if (HAS_PCH_SPLIT(dev))
+	else if (HAS_PCH_SPLIT(dev_priv))
 		return 120000;
-	else if (!IS_GEN2(dev))
+	else if (!IS_GEN2(dev_priv))
 		return 96000;
 	else
 		return 48000;
@@ -11365,7 +11328,7 @@ static void i9xx_crtc_clock_get(struct i
 		fp = pipe_config->dpll_hw_state.fp1;
 
 	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
-	if (IS_PINEVIEW(dev)) {
+	if (IS_PINEVIEW(dev_priv)) {
 		clock.n = ffs((fp & FP_N_PINEVIEW_DIV_MASK) >> FP_N_DIV_SHIFT) - 1;
 		clock.m2 = (fp & FP_M2_PINEVIEW_DIV_MASK) >> FP_M2_DIV_SHIFT;
 	} else {
@@ -11373,8 +11336,8 @@ static void i9xx_crtc_clock_get(struct i
 		clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
 	}
 
-	if (!IS_GEN2(dev)) {
-		if (IS_PINEVIEW(dev))
+	if (!IS_GEN2(dev_priv)) {
+		if (IS_PINEVIEW(dev_priv))
 			clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >>
 				DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW);
 		else
@@ -11396,12 +11359,12 @@ static void i9xx_crtc_clock_get(struct i
 			return;
 		}
 
-		if (IS_PINEVIEW(dev))
+		if (IS_PINEVIEW(dev_priv))
 			port_clock = pnv_calc_dpll_params(refclk, &clock);
 		else
 			port_clock = i9xx_calc_dpll_params(refclk, &clock);
 	} else {
-		u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS);
+		u32 lvds = IS_I830(dev_priv) ? 0 : I915_READ(LVDS);
 		bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN);
 
 		if (is_lvds) {
@@ -11563,7 +11526,7 @@ static void intel_unpin_work_fn(struct w
 		flush_work(&work->mmio_work);
 
 	mutex_lock(&dev->struct_mutex);
-	intel_unpin_fb_obj(work->old_fb, primary->state->rotation);
+	intel_unpin_fb_vma(work->old_vma);
 	i915_gem_object_put(work->pending_flip_obj);
 	mutex_unlock(&dev->struct_mutex);
 
@@ -11602,7 +11565,7 @@ static bool __pageflip_finished_cs(struc
 	 * really needed there. But since ctg has the registers,
 	 * include it in the check anyway.
 	 */
-	if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev))
+	if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv))
 		return true;
 
 	/*
@@ -11665,8 +11628,7 @@ static bool pageflip_finished(struct int
 void intel_finish_page_flip_cs(struct drm_i915_private *dev_priv, int pipe)
 {
 	struct drm_device *dev = &dev_priv->drm;
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 	struct intel_flip_work *work;
 	unsigned long flags;
 
@@ -11679,12 +11641,12 @@ void intel_finish_page_flip_cs(struct dr
 	 * lost pageflips) so needs the full irqsave spinlocks.
 	 */
 	spin_lock_irqsave(&dev->event_lock, flags);
-	work = intel_crtc->flip_work;
+	work = crtc->flip_work;
 
 	if (work != NULL &&
 	    !is_mmio_work(work) &&
-	    pageflip_finished(intel_crtc, work))
-		page_flip_completed(intel_crtc);
+	    pageflip_finished(crtc, work))
+		page_flip_completed(crtc);
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
@@ -11692,8 +11654,7 @@ void intel_finish_page_flip_cs(struct dr
 void intel_finish_page_flip_mmio(struct drm_i915_private *dev_priv, int pipe)
 {
 	struct drm_device *dev = &dev_priv->drm;
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 	struct intel_flip_work *work;
 	unsigned long flags;
 
@@ -11706,12 +11667,12 @@ void intel_finish_page_flip_mmio(struct
 	 * lost pageflips) so needs the full irqsave spinlocks.
 	 */
 	spin_lock_irqsave(&dev->event_lock, flags);
-	work = intel_crtc->flip_work;
+	work = crtc->flip_work;
 
 	if (work != NULL &&
 	    is_mmio_work(work) &&
-	    pageflip_finished(intel_crtc, work))
-		page_flip_completed(intel_crtc);
+	    pageflip_finished(crtc, work))
+		page_flip_completed(crtc);
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
@@ -11816,7 +11777,7 @@ static int intel_gen4_queue_flip(struct
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 	intel_ring_emit(ring, fb->pitches[0]);
 	intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset |
-			intel_fb_modifier_to_tiling(fb->modifier[0]));
+			intel_fb_modifier_to_tiling(fb->modifier));
 
 	/* XXX Enabling the panel-fitter across page-flip is so far
 	 * untested on non-native modes, so ignore it for now.
@@ -11849,7 +11810,7 @@ static int intel_gen6_queue_flip(struct
 	intel_ring_emit(ring, MI_DISPLAY_FLIP |
 			MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));
 	intel_ring_emit(ring, fb->pitches[0] |
-			intel_fb_modifier_to_tiling(fb->modifier[0]));
+			intel_fb_modifier_to_tiling(fb->modifier));
 	intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
 
 	/* Contrary to the suggestions in the documentation,
@@ -11872,6 +11833,7 @@ static int intel_gen7_queue_flip(struct
 				 struct drm_i915_gem_request *req,
 				 uint32_t flags)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_ring *ring = req->ring;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	uint32_t plane_bit = 0;
@@ -11900,7 +11862,7 @@ static int intel_gen7_queue_flip(struct
 		 * 48bits addresses, and we need a NOOP for the batch size to
 		 * stay even.
 		 */
-		if (IS_GEN8(dev))
+		if (IS_GEN8(dev_priv))
 			len += 2;
 	}
 
@@ -11937,7 +11899,7 @@ static int intel_gen7_queue_flip(struct
 		intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE |
 					  DERRMR_PIPEB_PRI_FLIP_DONE |
 					  DERRMR_PIPEC_PRI_FLIP_DONE));
-		if (IS_GEN8(dev))
+		if (IS_GEN8(dev_priv))
 			intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 |
 					      MI_SRM_LRM_GLOBAL_GTT);
 		else
@@ -11946,7 +11908,7 @@ static int intel_gen7_queue_flip(struct
 		intel_ring_emit_reg(ring, DERRMR);
 		intel_ring_emit(ring,
 				i915_ggtt_offset(req->engine->scratch) + 256);
-		if (IS_GEN8(dev)) {
+		if (IS_GEN8(dev_priv)) {
 			intel_ring_emit(ring, 0);
 			intel_ring_emit(ring, MI_NOOP);
 		}
@@ -11954,7 +11916,7 @@ static int intel_gen7_queue_flip(struct
 
 	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit);
 	intel_ring_emit(ring, fb->pitches[0] |
-			intel_fb_modifier_to_tiling(fb->modifier[0]));
+			intel_fb_modifier_to_tiling(fb->modifier));
 	intel_ring_emit(ring, intel_crtc->flip_work->gtt_offset);
 	intel_ring_emit(ring, (MI_NOOP));
 
@@ -11964,8 +11926,6 @@ static int intel_gen7_queue_flip(struct
 static bool use_mmio_flip(struct intel_engine_cs *engine,
 			  struct drm_i915_gem_object *obj)
 {
-	struct reservation_object *resv;
-
 	/*
 	 * This is not being used for older platforms, because
 	 * non-availability of flip done interrupt forces us to use
@@ -11987,12 +11947,7 @@ static bool use_mmio_flip(struct intel_e
 	else if (i915.enable_execlists)
 		return true;
 
-	resv = i915_gem_object_get_dmabuf_resv(obj);
-	if (resv && !reservation_object_test_signaled_rcu(resv, false))
-		return true;
-
-	return engine != i915_gem_active_get_engine(&obj->last_write,
-						    &obj->base.dev->struct_mutex);
+	return engine != i915_gem_object_last_write_engine(obj);
 }
 
 static void skl_do_mmio_flip(struct intel_crtc *intel_crtc,
@@ -12007,7 +11962,7 @@ static void skl_do_mmio_flip(struct inte
 
 	ctl = I915_READ(PLANE_CTL(pipe, 0));
 	ctl &= ~PLANE_CTL_TILED_MASK;
-	switch (fb->modifier[0]) {
+	switch (fb->modifier) {
 	case DRM_FORMAT_MOD_NONE:
 		break;
 	case I915_FORMAT_MOD_X_TILED:
@@ -12020,7 +11975,7 @@ static void skl_do_mmio_flip(struct inte
 		ctl |= PLANE_CTL_TILED_YF;
 		break;
 	default:
-		MISSING_CASE(fb->modifier[0]);
+		MISSING_CASE(fb->modifier);
 	}
 
 	/*
@@ -12045,7 +12000,7 @@ static void ilk_do_mmio_flip(struct inte
 
 	dspcntr = I915_READ(reg);
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		dspcntr |= DISPPLANE_TILED;
 	else
 		dspcntr &= ~DISPPLANE_TILED;
@@ -12065,17 +12020,8 @@ static void intel_mmio_flip_work_func(st
 	struct intel_framebuffer *intel_fb =
 		to_intel_framebuffer(crtc->base.primary->fb);
 	struct drm_i915_gem_object *obj = intel_fb->obj;
-	struct reservation_object *resv;
-
-	if (work->flip_queued_req)
-		WARN_ON(i915_wait_request(work->flip_queued_req,
-					  0, NULL, NO_WAITBOOST));
 
-	/* For framebuffer backed by dmabuf, wait for fence */
-	resv = i915_gem_object_get_dmabuf_resv(obj);
-	if (resv)
-		WARN_ON(reservation_object_wait_timeout_rcu(resv, false, false,
-							    MAX_SCHEDULE_TIMEOUT) < 0);
+	WARN_ON(i915_gem_object_wait(obj, 0, MAX_SCHEDULE_TIMEOUT, NULL) < 0);
 
 	intel_pipe_update_start(crtc);
 
@@ -12138,8 +12084,7 @@ static bool __pageflip_stall_check_cs(st
 void intel_check_page_flip(struct drm_i915_private *dev_priv, int pipe)
 {
 	struct drm_device *dev = &dev_priv->drm;
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 	struct intel_flip_work *work;
 
 	WARN_ON(!in_interrupt());
@@ -12148,19 +12093,19 @@ void intel_check_page_flip(struct drm_i9
 		return;
 
 	spin_lock(&dev->event_lock);
-	work = intel_crtc->flip_work;
+	work = crtc->flip_work;
 
 	if (work != NULL && !is_mmio_work(work) &&
-	    __pageflip_stall_check_cs(dev_priv, intel_crtc, work)) {
+	    __pageflip_stall_check_cs(dev_priv, crtc, work)) {
 		WARN_ONCE(1,
 			  "Kicking stuck page flip: queued at %d, now %d\n",
-			work->flip_queued_vblank, intel_crtc_get_vblank_counter(intel_crtc));
-		page_flip_completed(intel_crtc);
+			work->flip_queued_vblank, intel_crtc_get_vblank_counter(crtc));
+		page_flip_completed(crtc);
 		work = NULL;
 	}
 
 	if (work != NULL && !is_mmio_work(work) &&
-	    intel_crtc_get_vblank_counter(intel_crtc) - work->flip_queued_vblank > 1)
+	    intel_crtc_get_vblank_counter(crtc) - work->flip_queued_vblank > 1)
 		intel_queue_rps_boost_for_request(work->flip_queued_req);
 	spin_unlock(&dev->event_lock);
 }
@@ -12200,7 +12145,7 @@ static int intel_crtc_page_flip(struct d
 	 * TILEOFF/LINOFF registers can't be changed via MI display flips.
 	 * Note that pitch changes could also affect these register.
 	 */
-	if (INTEL_INFO(dev)->gen > 3 &&
+	if (INTEL_GEN(dev_priv) > 3 &&
 	    (fb->offsets[0] != crtc->primary->fb->offsets[0] ||
 	     fb->pitches[0] != crtc->primary->fb->pitches[0]))
 		return -EINVAL;
@@ -12265,23 +12210,22 @@ static int intel_crtc_page_flip(struct d
 
 	atomic_inc(&intel_crtc->unpin_work_count);
 
-	if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
+	if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
 		work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1;
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-		engine = &dev_priv->engine[BCS];
-		if (fb->modifier[0] != old_fb->modifier[0])
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		engine = dev_priv->engine[BCS];
+		if (fb->modifier != old_fb->modifier)
 			/* vlv: DISPLAY_FLIP fails to change tiling */
 			engine = NULL;
-	} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {
-		engine = &dev_priv->engine[BCS];
-	} else if (INTEL_INFO(dev)->gen >= 7) {
-		engine = i915_gem_active_get_engine(&obj->last_write,
-						    &obj->base.dev->struct_mutex);
+	} else if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) {
+		engine = dev_priv->engine[BCS];
+	} else if (INTEL_GEN(dev_priv) >= 7) {
+		engine = i915_gem_object_last_write_engine(obj);
 		if (engine == NULL || engine->id != RCS)
-			engine = &dev_priv->engine[BCS];
+			engine = dev_priv->engine[BCS];
 	} else {
-		engine = &dev_priv->engine[RCS];
+		engine = dev_priv->engine[RCS];
 	}
 
 	mmio_flip = use_mmio_flip(engine, obj);
@@ -12292,8 +12236,10 @@ static int intel_crtc_page_flip(struct d
 		goto cleanup_pending;
 	}
 
-	work->gtt_offset = intel_fb_gtt_offset(fb, primary->state->rotation);
-	work->gtt_offset += intel_crtc->dspaddr_offset;
+	work->old_vma = to_intel_plane_state(primary->state)->vma;
+	to_intel_plane_state(primary->state)->vma = vma;
+
+	work->gtt_offset = i915_ggtt_offset(vma) + intel_crtc->dspaddr_offset;
 	work->rotation = crtc->primary->state->rotation;
 
 	/*
@@ -12309,10 +12255,7 @@ static int intel_crtc_page_flip(struct d
 
 	if (mmio_flip) {
 		INIT_WORK(&work->mmio_work, intel_mmio_flip_work_func);
-
-		work->flip_queued_req = i915_gem_active_get(&obj->last_write,
-							    &obj->base.dev->struct_mutex);
-		schedule_work(&work->mmio_work);
+		queue_work(system_unbound_wq, &work->mmio_work);
 	} else {
 		request = i915_gem_request_alloc(engine, engine->last_context);
 		if (IS_ERR(request)) {
@@ -12335,6 +12278,7 @@ static int intel_crtc_page_flip(struct d
 		i915_add_request_no_flush(request);
 	}
 
+	i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
 	i915_gem_track_fb(intel_fb_obj(old_fb), obj,
 			  to_intel_plane(primary)->frontbuffer_bit);
 	mutex_unlock(&dev->struct_mutex);
@@ -12349,7 +12293,8 @@ static int intel_crtc_page_flip(struct d
 cleanup_request:
 	i915_add_request_no_flush(request);
 cleanup_unpin:
-	intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
+	to_intel_plane_state(primary->state)->vma = work->old_vma;
+	intel_unpin_fb_vma(vma);
 cleanup_pending:
 	atomic_dec(&intel_crtc->unpin_work_count);
 unlock:
@@ -12358,7 +12303,7 @@ cleanup:
 	crtc->primary->fb = old_fb;
 	update_state_fb(crtc->primary);
 
-	i915_gem_object_put_unlocked(obj);
+	i915_gem_object_put(obj);
 	drm_framebuffer_unreference(work->old_fb);
 
 	spin_lock_irq(&dev->event_lock);
@@ -12396,8 +12341,7 @@ retry:
 			goto retry;
 		}
 
-		if (ret)
-			drm_atomic_state_free(state);
+		drm_atomic_state_put(state);
 
 		if (ret == 0 && event) {
 			spin_lock_irq(&dev->event_lock);
@@ -12432,7 +12376,7 @@ static bool intel_wm_need_update(struct
 	if (!cur->base.fb || !new->base.fb)
 		return false;
 
-	if (cur->base.fb->modifier[0] != new->base.fb->modifier[0] ||
+	if (cur->base.fb->modifier != new->base.fb->modifier ||
 	    cur->base.rotation != new->base.rotation ||
 	    drm_rect_width(&new->base.src) != drm_rect_width(&cur->base.src) ||
 	    drm_rect_height(&new->base.src) != drm_rect_height(&cur->base.src) ||
@@ -12471,7 +12415,7 @@ int intel_plane_atomic_calc_changes(stru
 	struct drm_framebuffer *fb = plane_state->fb;
 	int ret;
 
-	if (INTEL_GEN(dev) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
+	if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) {
 		ret = skl_update_scaler_plane(
 			to_intel_crtc_state(crtc_state),
 			to_intel_plane_state(plane_state));
@@ -12538,7 +12482,7 @@ int intel_plane_atomic_calc_changes(stru
 
 	/* Pre-gen9 platforms need two-step watermark updates */
 	if ((pipe_config->update_wm_pre || pipe_config->update_wm_post) &&
-	    INTEL_INFO(dev)->gen < 9 && dev_priv->display.optimize_watermarks)
+	    INTEL_GEN(dev_priv) < 9 && dev_priv->display.optimize_watermarks)
 		to_intel_crtc_state(crtc_state)->wm.need_postvbl_update = true;
 
 	if (visible || was_visible)
@@ -12550,7 +12494,7 @@ int intel_plane_atomic_calc_changes(stru
 	 * cstate->update_wm was already set above, so this flag will
 	 * take effect when we commit and program watermarks.
 	 */
-	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev) &&
+	if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) &&
 	    needs_scaling(to_intel_plane_state(plane_state)) &&
 	    !needs_scaling(old_plane_state))
 		pipe_config->disable_lp_wm = true;
@@ -12643,7 +12587,7 @@ static int intel_crtc_atomic_check(struc
 		 * old state and the new state.  We can program these
 		 * immediately.
 		 */
-		ret = dev_priv->display.compute_intermediate_wm(crtc->dev,
+		ret = dev_priv->display.compute_intermediate_wm(dev,
 								intel_crtc,
 								pipe_config);
 		if (ret) {
@@ -12655,7 +12599,7 @@ static int intel_crtc_atomic_check(struc
 			pipe_config->wm.ilk.intermediate = pipe_config->wm.ilk.optimal;
 	}
 
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		if (mode_changed)
 			ret = skl_update_scaler_crtc(pipe_config);
 
@@ -12726,15 +12670,16 @@ static int
 compute_baseline_pipe_bpp(struct intel_crtc *crtc,
 			  struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct drm_atomic_state *state;
 	struct drm_connector *connector;
 	struct drm_connector_state *connector_state;
 	int bpp, i;
 
-	if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)))
+	if ((IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) ||
+	    IS_CHERRYVIEW(dev_priv)))
 		bpp = 10*3;
-	else if (INTEL_INFO(dev)->gen >= 5)
+	else if (INTEL_GEN(dev_priv) >= 5)
 		bpp = 12*3;
 	else
 		bpp = 8*3;
@@ -12767,73 +12712,81 @@ static void intel_dump_crtc_timings(cons
 		mode->crtc_vsync_end, mode->crtc_vtotal, mode->type, mode->flags);
 }
 
+static inline void
+intel_dump_m_n_config(struct intel_crtc_state *pipe_config, char *id,
+		      unsigned int lane_count, struct intel_link_m_n *m_n)
+{
+	DRM_DEBUG_KMS("%s: lanes: %i; gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
+		      id, lane_count,
+		      m_n->gmch_m, m_n->gmch_n,
+		      m_n->link_m, m_n->link_n, m_n->tu);
+}
+
 static void intel_dump_pipe_config(struct intel_crtc *crtc,
 				   struct intel_crtc_state *pipe_config,
 				   const char *context)
 {
 	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_plane *plane;
 	struct intel_plane *intel_plane;
 	struct intel_plane_state *state;
 	struct drm_framebuffer *fb;
 
-	DRM_DEBUG_KMS("[CRTC:%d:%s]%s config %p for pipe %c\n",
-		      crtc->base.base.id, crtc->base.name,
-		      context, pipe_config, pipe_name(crtc->pipe));
+	DRM_DEBUG_KMS("[CRTC:%d:%s]%s\n",
+		      crtc->base.base.id, crtc->base.name, context);
 
-	DRM_DEBUG_KMS("cpu_transcoder: %s\n", transcoder_name(pipe_config->cpu_transcoder));
-	DRM_DEBUG_KMS("pipe bpp: %i, dithering: %i\n",
+	DRM_DEBUG_KMS("cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n",
+		      transcoder_name(pipe_config->cpu_transcoder),
 		      pipe_config->pipe_bpp, pipe_config->dither);
-	DRM_DEBUG_KMS("fdi/pch: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
-		      pipe_config->has_pch_encoder,
-		      pipe_config->fdi_lanes,
-		      pipe_config->fdi_m_n.gmch_m, pipe_config->fdi_m_n.gmch_n,
-		      pipe_config->fdi_m_n.link_m, pipe_config->fdi_m_n.link_n,
-		      pipe_config->fdi_m_n.tu);
-	DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m: %u, gmch_n: %u, link_m: %u, link_n: %u, tu: %u\n",
-		      intel_crtc_has_dp_encoder(pipe_config),
-		      pipe_config->lane_count,
-		      pipe_config->dp_m_n.gmch_m, pipe_config->dp_m_n.gmch_n,
-		      pipe_config->dp_m_n.link_m, pipe_config->dp_m_n.link_n,
-		      pipe_config->dp_m_n.tu);
 
-	DRM_DEBUG_KMS("dp: %i, lanes: %i, gmch_m2: %u, gmch_n2: %u, link_m2: %u, link_n2: %u, tu2: %u\n",
-		      intel_crtc_has_dp_encoder(pipe_config),
-		      pipe_config->lane_count,
-		      pipe_config->dp_m2_n2.gmch_m,
-		      pipe_config->dp_m2_n2.gmch_n,
-		      pipe_config->dp_m2_n2.link_m,
-		      pipe_config->dp_m2_n2.link_n,
-		      pipe_config->dp_m2_n2.tu);
+	if (pipe_config->has_pch_encoder)
+		intel_dump_m_n_config(pipe_config, "fdi",
+				      pipe_config->fdi_lanes,
+				      &pipe_config->fdi_m_n);
+
+	if (intel_crtc_has_dp_encoder(pipe_config)) {
+		intel_dump_m_n_config(pipe_config, "dp m_n",
+				pipe_config->lane_count, &pipe_config->dp_m_n);
+		if (pipe_config->has_drrs)
+			intel_dump_m_n_config(pipe_config, "dp m2_n2",
+					      pipe_config->lane_count,
+					      &pipe_config->dp_m2_n2);
+	}
 
 	DRM_DEBUG_KMS("audio: %i, infoframes: %i\n",
-		      pipe_config->has_audio,
-		      pipe_config->has_infoframe);
+		      pipe_config->has_audio, pipe_config->has_infoframe);
 
 	DRM_DEBUG_KMS("requested mode:\n");
 	drm_mode_debug_printmodeline(&pipe_config->base.mode);
 	DRM_DEBUG_KMS("adjusted mode:\n");
 	drm_mode_debug_printmodeline(&pipe_config->base.adjusted_mode);
 	intel_dump_crtc_timings(&pipe_config->base.adjusted_mode);
-	DRM_DEBUG_KMS("port clock: %d\n", pipe_config->port_clock);
-	DRM_DEBUG_KMS("pipe src size: %dx%d\n",
+	DRM_DEBUG_KMS("port clock: %d, pipe src size: %dx%d\n",
+		      pipe_config->port_clock,
 		      pipe_config->pipe_src_w, pipe_config->pipe_src_h);
-	DRM_DEBUG_KMS("num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n",
-		      crtc->num_scalers,
-		      pipe_config->scaler_state.scaler_users,
-		      pipe_config->scaler_state.scaler_id);
-	DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
-		      pipe_config->gmch_pfit.control,
-		      pipe_config->gmch_pfit.pgm_ratios,
-		      pipe_config->gmch_pfit.lvds_border_bits);
-	DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
-		      pipe_config->pch_pfit.pos,
-		      pipe_config->pch_pfit.size,
-		      pipe_config->pch_pfit.enabled ? "enabled" : "disabled");
-	DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled);
-	DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide);
 
-	if (IS_BROXTON(dev)) {
+	if (INTEL_GEN(dev_priv) >= 9)
+		DRM_DEBUG_KMS("num_scalers: %d, scaler_users: 0x%x, scaler_id: %d\n",
+			      crtc->num_scalers,
+			      pipe_config->scaler_state.scaler_users,
+		              pipe_config->scaler_state.scaler_id);
+
+	if (HAS_GMCH_DISPLAY(dev_priv))
+		DRM_DEBUG_KMS("gmch pfit: control: 0x%08x, ratios: 0x%08x, lvds border: 0x%08x\n",
+			      pipe_config->gmch_pfit.control,
+			      pipe_config->gmch_pfit.pgm_ratios,
+			      pipe_config->gmch_pfit.lvds_border_bits);
+	else
+		DRM_DEBUG_KMS("pch pfit: pos: 0x%08x, size: 0x%08x, %s\n",
+			      pipe_config->pch_pfit.pos,
+			      pipe_config->pch_pfit.size,
+		              enableddisabled(pipe_config->pch_pfit.enabled));
+
+	DRM_DEBUG_KMS("ips: %i, double wide: %i\n",
+		      pipe_config->ips_enabled, pipe_config->double_wide);
+
+	if (IS_BROXTON(dev_priv)) {
 		DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
 			      "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
 			      "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
@@ -12848,13 +12801,13 @@ static void intel_dump_pipe_config(struc
 			      pipe_config->dpll_hw_state.pll9,
 			      pipe_config->dpll_hw_state.pll10,
 			      pipe_config->dpll_hw_state.pcsdw12);
-	} else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
 		DRM_DEBUG_KMS("dpll_hw_state: "
 			      "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
 			      pipe_config->dpll_hw_state.ctrl1,
 			      pipe_config->dpll_hw_state.cfgcr1,
 			      pipe_config->dpll_hw_state.cfgcr2);
-	} else if (HAS_DDI(dev)) {
+	} else if (HAS_DDI(dev_priv)) {
 		DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
 			      pipe_config->dpll_hw_state.wrpll,
 			      pipe_config->dpll_hw_state.spll);
@@ -12869,7 +12822,7 @@ static void intel_dump_pipe_config(struc
 
 	DRM_DEBUG_KMS("planes on this crtc\n");
 	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
-		char *format_name;
+		struct drm_format_name_buf format_name;
 		intel_plane = to_intel_plane(plane);
 		if (intel_plane->pipe != crtc->pipe)
 			continue;
@@ -12882,23 +12835,20 @@ static void intel_dump_pipe_config(struc
 			continue;
 		}
 
-		format_name = drm_get_format_name(fb->pixel_format);
-
-		DRM_DEBUG_KMS("[PLANE:%d:%s] enabled",
-			      plane->base.id, plane->name);
-		DRM_DEBUG_KMS("\tFB:%d, fb = %ux%u format = %s",
-			      fb->base.id, fb->width, fb->height, format_name);
-		DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n",
-			      state->scaler_id,
-			      state->base.src.x1 >> 16,
-			      state->base.src.y1 >> 16,
-			      drm_rect_width(&state->base.src) >> 16,
-			      drm_rect_height(&state->base.src) >> 16,
-			      state->base.dst.x1, state->base.dst.y1,
-			      drm_rect_width(&state->base.dst),
-			      drm_rect_height(&state->base.dst));
-
-		kfree(format_name);
+		DRM_DEBUG_KMS("[PLANE:%d:%s] FB:%d, fb = %ux%u format = %s\n",
+			      plane->base.id, plane->name,
+			      fb->base.id, fb->width, fb->height,
+			      drm_get_format_name(fb->pixel_format, &format_name));
+		if (INTEL_GEN(dev_priv) >= 9)
+			DRM_DEBUG_KMS("\tscaler:%d src %dx%d+%d+%d dst %dx%d+%d+%d\n",
+				      state->scaler_id,
+				      state->base.src.x1 >> 16,
+				      state->base.src.y1 >> 16,
+				      drm_rect_width(&state->base.src) >> 16,
+				      drm_rect_height(&state->base.src) >> 16,
+				      state->base.dst.x1, state->base.dst.y1,
+				      drm_rect_width(&state->base.dst),
+				      drm_rect_height(&state->base.dst));
 	}
 }
 
@@ -12932,7 +12882,7 @@ static bool check_digital_port_conflicts
 		switch (encoder->type) {
 			unsigned int port_mask;
 		case INTEL_OUTPUT_UNKNOWN:
-			if (WARN_ON(!HAS_DDI(dev)))
+			if (WARN_ON(!HAS_DDI(to_i915(dev))))
 				break;
 		case INTEL_OUTPUT_DP:
 		case INTEL_OUTPUT_HDMI:
@@ -13213,7 +13163,7 @@ intel_compare_link_m_n(const struct inte
 }
 
 static bool
-intel_pipe_config_compare(struct drm_device *dev,
+intel_pipe_config_compare(struct drm_i915_private *dev_priv,
 			  struct intel_crtc_state *current_config,
 			  struct intel_crtc_state *pipe_config,
 			  bool adjust)
@@ -13337,7 +13287,7 @@ intel_pipe_config_compare(struct drm_dev
 	PIPE_CONF_CHECK_I(lane_count);
 	PIPE_CONF_CHECK_X(lane_lat_optim_mask);
 
-	if (INTEL_INFO(dev)->gen < 8) {
+	if (INTEL_GEN(dev_priv) < 8) {
 		PIPE_CONF_CHECK_M_N(dp_m_n);
 
 		if (current_config->has_drrs)
@@ -13363,8 +13313,8 @@ intel_pipe_config_compare(struct drm_dev
 
 	PIPE_CONF_CHECK_I(pixel_multiplier);
 	PIPE_CONF_CHECK_I(has_hdmi_sink);
-	if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) ||
-	    IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) ||
+	    IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		PIPE_CONF_CHECK_I(limited_color_range);
 	PIPE_CONF_CHECK_I(has_infoframe);
 
@@ -13386,7 +13336,7 @@ intel_pipe_config_compare(struct drm_dev
 
 	PIPE_CONF_CHECK_X(gmch_pfit.control);
 	/* pfit ratios are autocomputed by the hw on gen4+ */
-	if (INTEL_INFO(dev)->gen < 4)
+	if (INTEL_GEN(dev_priv) < 4)
 		PIPE_CONF_CHECK_X(gmch_pfit.pgm_ratios);
 	PIPE_CONF_CHECK_X(gmch_pfit.lvds_border_bits);
 
@@ -13404,7 +13354,7 @@ intel_pipe_config_compare(struct drm_dev
 	}
 
 	/* BDW+ don't expose a synchronous way to read the state */
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev_priv))
 		PIPE_CONF_CHECK_I(ips_enabled);
 
 	PIPE_CONF_CHECK_I(double_wide);
@@ -13423,7 +13373,7 @@ intel_pipe_config_compare(struct drm_dev
 	PIPE_CONF_CHECK_X(dsi_pll.ctrl);
 	PIPE_CONF_CHECK_X(dsi_pll.div);
 
-	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5)
+	if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5)
 		PIPE_CONF_CHECK_I(pipe_bpp);
 
 	PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock);
@@ -13461,33 +13411,67 @@ static void intel_pipe_config_sanity_che
 static void verify_wm_state(struct drm_crtc *crtc,
 			    struct drm_crtc_state *new_state)
 {
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
 	struct skl_ddb_allocation hw_ddb, *sw_ddb;
-	struct skl_ddb_entry *hw_entry, *sw_entry;
+	struct skl_pipe_wm hw_wm, *sw_wm;
+	struct skl_plane_wm *hw_plane_wm, *sw_plane_wm;
+	struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	const enum pipe pipe = intel_crtc->pipe;
-	int plane;
+	int plane, level, max_level = ilk_wm_max_level(dev_priv);
 
-	if (INTEL_INFO(dev)->gen < 9 || !new_state->active)
+	if (INTEL_GEN(dev_priv) < 9 || !new_state->active)
 		return;
 
+	skl_pipe_wm_get_hw_state(crtc, &hw_wm);
+	sw_wm = &to_intel_crtc_state(new_state)->wm.skl.optimal;
+
 	skl_ddb_get_hw_state(dev_priv, &hw_ddb);
 	sw_ddb = &dev_priv->wm.skl_hw.ddb;
 
 	/* planes */
-	for_each_plane(dev_priv, pipe, plane) {
-		hw_entry = &hw_ddb.plane[pipe][plane];
-		sw_entry = &sw_ddb->plane[pipe][plane];
+	for_each_universal_plane(dev_priv, pipe, plane) {
+		hw_plane_wm = &hw_wm.planes[plane];
+		sw_plane_wm = &sw_wm->planes[plane];
 
-		if (skl_ddb_entry_equal(hw_entry, sw_entry))
-			continue;
+		/* Watermarks */
+		for (level = 0; level <= max_level; level++) {
+			if (skl_wm_level_equals(&hw_plane_wm->wm[level],
+						&sw_plane_wm->wm[level]))
+				continue;
 
-		DRM_ERROR("mismatch in DDB state pipe %c plane %d "
-			  "(expected (%u,%u), found (%u,%u))\n",
-			  pipe_name(pipe), plane + 1,
-			  sw_entry->start, sw_entry->end,
-			  hw_entry->start, hw_entry->end);
+			DRM_ERROR("mismatch in WM pipe %c plane %d level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+				  pipe_name(pipe), plane + 1, level,
+				  sw_plane_wm->wm[level].plane_en,
+				  sw_plane_wm->wm[level].plane_res_b,
+				  sw_plane_wm->wm[level].plane_res_l,
+				  hw_plane_wm->wm[level].plane_en,
+				  hw_plane_wm->wm[level].plane_res_b,
+				  hw_plane_wm->wm[level].plane_res_l);
+		}
+
+		if (!skl_wm_level_equals(&hw_plane_wm->trans_wm,
+					 &sw_plane_wm->trans_wm)) {
+			DRM_ERROR("mismatch in trans WM pipe %c plane %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+				  pipe_name(pipe), plane + 1,
+				  sw_plane_wm->trans_wm.plane_en,
+				  sw_plane_wm->trans_wm.plane_res_b,
+				  sw_plane_wm->trans_wm.plane_res_l,
+				  hw_plane_wm->trans_wm.plane_en,
+				  hw_plane_wm->trans_wm.plane_res_b,
+				  hw_plane_wm->trans_wm.plane_res_l);
+		}
+
+		/* DDB */
+		hw_ddb_entry = &hw_ddb.plane[pipe][plane];
+		sw_ddb_entry = &sw_ddb->plane[pipe][plane];
+
+		if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
+			DRM_ERROR("mismatch in DDB state pipe %c plane %d (expected (%u,%u), found (%u,%u))\n",
+				  pipe_name(pipe), plane + 1,
+				  sw_ddb_entry->start, sw_ddb_entry->end,
+				  hw_ddb_entry->start, hw_ddb_entry->end);
+		}
 	}
 
 	/*
@@ -13497,25 +13481,60 @@ static void verify_wm_state(struct drm_c
 	 * once the plane becomes visible, we can skip this check
 	 */
 	if (intel_crtc->cursor_addr) {
-		hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
-		sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
+		hw_plane_wm = &hw_wm.planes[PLANE_CURSOR];
+		sw_plane_wm = &sw_wm->planes[PLANE_CURSOR];
 
-		if (!skl_ddb_entry_equal(hw_entry, sw_entry)) {
-			DRM_ERROR("mismatch in DDB state pipe %c cursor "
-				  "(expected (%u,%u), found (%u,%u))\n",
+		/* Watermarks */
+		for (level = 0; level <= max_level; level++) {
+			if (skl_wm_level_equals(&hw_plane_wm->wm[level],
+						&sw_plane_wm->wm[level]))
+				continue;
+
+			DRM_ERROR("mismatch in WM pipe %c cursor level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
+				  pipe_name(pipe), level,
+				  sw_plane_wm->wm[level].plane_en,
+				  sw_plane_wm->wm[level].plane_res_b,
+				  sw_plane_wm->wm[level].plane_res_l,
+				  hw_plane_wm->wm[level].plane_en,
+				  hw_plane_wm->wm[level].plane_res_b,
+				  hw_plane_wm->wm[level].plane_res_l);
+		}
+
+		if (!skl_wm_level_equals(&hw_plane_wm->trans_wm,
+					 &sw_plane_wm->trans_wm)) {
+			DRM_ERROR("mismatch in trans WM pipe %c cursor (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n",
 				  pipe_name(pipe),
-				  sw_entry->start, sw_entry->end,
-				  hw_entry->start, hw_entry->end);
+				  sw_plane_wm->trans_wm.plane_en,
+				  sw_plane_wm->trans_wm.plane_res_b,
+				  sw_plane_wm->trans_wm.plane_res_l,
+				  hw_plane_wm->trans_wm.plane_en,
+				  hw_plane_wm->trans_wm.plane_res_b,
+				  hw_plane_wm->trans_wm.plane_res_l);
+		}
+
+		/* DDB */
+		hw_ddb_entry = &hw_ddb.plane[pipe][PLANE_CURSOR];
+		sw_ddb_entry = &sw_ddb->plane[pipe][PLANE_CURSOR];
+
+		if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) {
+			DRM_ERROR("mismatch in DDB state pipe %c cursor (expected (%u,%u), found (%u,%u))\n",
+				  pipe_name(pipe),
+				  sw_ddb_entry->start, sw_ddb_entry->end,
+				  hw_ddb_entry->start, hw_ddb_entry->end);
 		}
 	}
 }
 
 static void
-verify_connector_state(struct drm_device *dev, struct drm_crtc *crtc)
+verify_connector_state(struct drm_device *dev,
+		       struct drm_atomic_state *state,
+		       struct drm_crtc *crtc)
 {
 	struct drm_connector *connector;
+	struct drm_connector_state *old_conn_state;
+	int i;
 
-	drm_for_each_connector(connector, dev) {
+	for_each_connector_in_state(state, connector, old_conn_state, i) {
 		struct drm_encoder *encoder = connector->encoder;
 		struct drm_connector_state *state = connector->state;
 
@@ -13630,7 +13649,7 @@ verify_crtc_state(struct drm_crtc *crtc,
 	intel_pipe_config_sanity_check(dev_priv, pipe_config);
 
 	sw_config = to_intel_crtc_state(crtc->state);
-	if (!intel_pipe_config_compare(dev, sw_config,
+	if (!intel_pipe_config_compare(dev_priv, sw_config,
 				       pipe_config, false)) {
 		I915_STATE_WARN(1, "pipe state doesn't match!\n");
 		intel_dump_pipe_config(intel_crtc, pipe_config,
@@ -13723,15 +13742,16 @@ verify_shared_dpll_state(struct drm_devi
 
 static void
 intel_modeset_verify_crtc(struct drm_crtc *crtc,
-			 struct drm_crtc_state *old_state,
-			 struct drm_crtc_state *new_state)
+			  struct drm_atomic_state *state,
+			  struct drm_crtc_state *old_state,
+			  struct drm_crtc_state *new_state)
 {
 	if (!needs_modeset(new_state) &&
 	    !to_intel_crtc_state(new_state)->update_pipe)
 		return;
 
 	verify_wm_state(crtc, new_state);
-	verify_connector_state(crtc->dev, crtc);
+	verify_connector_state(crtc->dev, state, crtc);
 	verify_crtc_state(crtc, old_state, new_state);
 	verify_shared_dpll_state(crtc->dev, crtc, old_state, new_state);
 }
@@ -13747,16 +13767,17 @@ verify_disabled_dpll_state(struct drm_de
 }
 
 static void
-intel_modeset_verify_disabled(struct drm_device *dev)
+intel_modeset_verify_disabled(struct drm_device *dev,
+			      struct drm_atomic_state *state)
 {
 	verify_encoder_state(dev);
-	verify_connector_state(dev, NULL);
+	verify_connector_state(dev, state, NULL);
 	verify_disabled_dpll_state(dev);
 }
 
 static void update_scanline_offset(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
 	/*
 	 * The scanline counter increments at the leading edge of hsync.
@@ -13776,7 +13797,7 @@ static void update_scanline_offset(struc
 	 * there's an extra 1 line difference. So we need to add two instead of
 	 * one to the value.
 	 */
-	if (IS_GEN2(dev)) {
+	if (IS_GEN2(dev_priv)) {
 		const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
 		int vtotal;
 
@@ -13785,7 +13806,7 @@ static void update_scanline_offset(struc
 			vtotal /= 2;
 
 		crtc->scanline_offset = vtotal - 1;
-	} else if (HAS_DDI(dev) &&
+	} else if (HAS_DDI(dev_priv) &&
 		   intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) {
 		crtc->scanline_offset = 2;
 	} else
@@ -13970,8 +13991,9 @@ static int intel_modeset_checks(struct d
 
 		DRM_DEBUG_KMS("New cdclk calculated to be atomic %u, actual %u\n",
 			      intel_state->cdclk, intel_state->dev_cdclk);
-	} else
+	} else {
 		to_intel_atomic_state(state)->cdclk = dev_priv->atomic_cdclk_freq;
+	}
 
 	intel_modeset_clear_plls(state);
 
@@ -14048,7 +14070,7 @@ static int intel_atomic_check(struct drm
 		}
 
 		if (i915.fastboot &&
-		    intel_pipe_config_compare(dev,
+		    intel_pipe_config_compare(dev_priv,
 					to_intel_crtc_state(crtc->state),
 					pipe_config, true)) {
 			crtc_state->mode_changed = false;
@@ -14072,8 +14094,9 @@ static int intel_atomic_check(struct drm
 
 		if (ret)
 			return ret;
-	} else
-		intel_state->cdclk = dev_priv->cdclk_freq;
+	} else {
+		intel_state->cdclk = dev_priv->atomic_cdclk_freq;
+	}
 
 	ret = drm_atomic_helper_check_planes(dev, state);
 	if (ret)
@@ -14084,13 +14107,10 @@ static int intel_atomic_check(struct drm
 }
 
 static int intel_atomic_prepare_commit(struct drm_device *dev,
-				       struct drm_atomic_state *state,
-				       bool nonblock)
+				       struct drm_atomic_state *state)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_plane_state *plane_state;
 	struct drm_crtc_state *crtc_state;
-	struct drm_plane *plane;
 	struct drm_crtc *crtc;
 	int i, ret;
 
@@ -14113,28 +14133,6 @@ static int intel_atomic_prepare_commit(s
 	ret = drm_atomic_helper_prepare_planes(dev, state);
 	mutex_unlock(&dev->struct_mutex);
 
-	if (!ret && !nonblock) {
-		for_each_plane_in_state(state, plane, plane_state, i) {
-			struct intel_plane_state *intel_plane_state =
-				to_intel_plane_state(plane_state);
-
-			if (!intel_plane_state->wait_req)
-				continue;
-
-			ret = i915_wait_request(intel_plane_state->wait_req,
-						I915_WAIT_INTERRUPTIBLE,
-						NULL, NULL);
-			if (ret) {
-				/* Any hang should be swallowed by the wait */
-				WARN_ON(ret == -EIO);
-				mutex_lock(&dev->struct_mutex);
-				drm_atomic_helper_cleanup_planes(dev, state);
-				mutex_unlock(&dev->struct_mutex);
-				break;
-			}
-		}
-	}
-
 	return ret;
 }
 
@@ -14160,22 +14158,24 @@ static void intel_atomic_wait_for_vblank
 		return;
 
 	for_each_pipe(dev_priv, pipe) {
-		struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+		struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
+								  pipe);
 
 		if (!((1 << pipe) & crtc_mask))
 			continue;
 
-		ret = drm_crtc_vblank_get(crtc);
+		ret = drm_crtc_vblank_get(&crtc->base);
 		if (WARN_ON(ret != 0)) {
 			crtc_mask &= ~(1 << pipe);
 			continue;
 		}
 
-		last_vblank_count[pipe] = drm_crtc_vblank_count(crtc);
+		last_vblank_count[pipe] = drm_crtc_vblank_count(&crtc->base);
 	}
 
 	for_each_pipe(dev_priv, pipe) {
-		struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+		struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv,
+								  pipe);
 		long lret;
 
 		if (!((1 << pipe) & crtc_mask))
@@ -14183,12 +14183,12 @@ static void intel_atomic_wait_for_vblank
 
 		lret = wait_event_timeout(dev->vblank[pipe].queue,
 				last_vblank_count[pipe] !=
-					drm_crtc_vblank_count(crtc),
+					drm_crtc_vblank_count(&crtc->base),
 				msecs_to_jiffies(50));
 
 		WARN(!lret, "pipe %c vblank wait timed out\n", pipe_name(pipe));
 
-		drm_crtc_vblank_put(crtc);
+		drm_crtc_vblank_put(&crtc->base);
 	}
 }
 
@@ -14262,16 +14262,23 @@ static void intel_update_crtcs(struct dr
 static void skl_update_crtcs(struct drm_atomic_state *state,
 			     unsigned int *crtc_vblank_mask)
 {
-	struct drm_device *dev = state->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(state->dev);
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
 	struct drm_crtc *crtc;
+	struct intel_crtc *intel_crtc;
 	struct drm_crtc_state *old_crtc_state;
-	struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb;
-	struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb;
+	struct intel_crtc_state *cstate;
 	unsigned int updated = 0;
 	bool progress;
 	enum pipe pipe;
+	int i;
+
+	const struct skl_ddb_entry *entries[I915_MAX_PIPES] = {};
+
+	for_each_crtc_in_state(state, crtc, old_crtc_state, i)
+		/* ignore allocations for crtc's that have been turned off. */
+		if (crtc->state->active)
+			entries[i] = &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb;
 
 	/*
 	 * Whenever the number of active pipes changes, we need to make sure we
@@ -14280,21 +14287,24 @@ static void skl_update_crtcs(struct drm_
 	 * cause pipe underruns and other bad stuff.
 	 */
 	do {
-		int i;
 		progress = false;
 
 		for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
 			bool vbl_wait = false;
 			unsigned int cmask = drm_crtc_mask(crtc);
-			pipe = to_intel_crtc(crtc)->pipe;
 
-			if (updated & cmask || !crtc->state->active)
+			intel_crtc = to_intel_crtc(crtc);
+			cstate = to_intel_crtc_state(crtc->state);
+			pipe = intel_crtc->pipe;
+
+			if (updated & cmask || !cstate->base.active)
 				continue;
-			if (skl_ddb_allocation_overlaps(state, cur_ddb, new_ddb,
-							pipe))
+
+			if (skl_ddb_allocation_overlaps(entries, &cstate->wm.skl.ddb, i))
 				continue;
 
 			updated |= cmask;
+			entries[i] = &cstate->wm.skl.ddb;
 
 			/*
 			 * If this is an already active pipe, it's DDB changed,
@@ -14302,7 +14312,8 @@ static void skl_update_crtcs(struct drm_
 			 * then we need to wait for a vblank to pass for the
 			 * new ddb allocation to take effect.
 			 */
-			if (!skl_ddb_allocation_equals(cur_ddb, new_ddb, pipe) &&
+			if (!skl_ddb_entry_equal(&cstate->wm.skl.ddb,
+						 &to_intel_crtc_state(old_crtc_state)->wm.skl.ddb) &&
 			    !crtc->state->active_changed &&
 			    intel_state->wm_results.dirty_pipes != updated)
 				vbl_wait = true;
@@ -14311,7 +14322,7 @@ static void skl_update_crtcs(struct drm_
 					  crtc_vblank_mask);
 
 			if (vbl_wait)
-				intel_wait_for_vblank(dev, pipe);
+				intel_wait_for_vblank(dev_priv, pipe);
 
 			progress = true;
 		}
@@ -14326,37 +14337,15 @@ static void intel_atomic_commit_tail(str
 	struct drm_crtc_state *old_crtc_state;
 	struct drm_crtc *crtc;
 	struct intel_crtc_state *intel_cstate;
-	struct drm_plane *plane;
-	struct drm_plane_state *plane_state;
 	bool hw_check = intel_state->modeset;
 	unsigned long put_domains[I915_MAX_PIPES] = {};
 	unsigned crtc_vblank_mask = 0;
-	int i, ret;
-
-	for_each_plane_in_state(state, plane, plane_state, i) {
-		struct intel_plane_state *intel_plane_state =
-			to_intel_plane_state(plane->state);
-
-		if (!intel_plane_state->wait_req)
-			continue;
-
-		ret = i915_wait_request(intel_plane_state->wait_req,
-					0, NULL, NULL);
-		/* EIO should be eaten, and we can't get interrupted in the
-		 * worker, and blocking commits have waited already. */
-		WARN_ON(ret);
-	}
+	int i;
 
 	drm_atomic_helper_wait_for_dependencies(state);
 
-	if (intel_state->modeset) {
-		memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
-		       sizeof(intel_state->min_pixclk));
-		dev_priv->active_crtcs = intel_state->active_crtcs;
-		dev_priv->atomic_cdclk_freq = intel_state->cdclk;
-
+	if (intel_state->modeset)
 		intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
-	}
 
 	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
 		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -14389,8 +14378,17 @@ static void intel_atomic_commit_tail(str
 			intel_check_cpu_fifo_underruns(dev_priv);
 			intel_check_pch_fifo_underruns(dev_priv);
 
-			if (!crtc->state->active)
-				intel_update_watermarks(crtc);
+			if (!crtc->state->active) {
+				/*
+				 * Make sure we don't call initial_watermarks
+				 * for ILK-style watermark updates.
+				 */
+				if (dev_priv->display.atomic_update_watermarks)
+					dev_priv->display.initial_watermarks(intel_state,
+									     to_intel_crtc_state(crtc->state));
+				else
+					intel_update_watermarks(intel_crtc);
+			}
 		}
 	}
 
@@ -14413,7 +14411,7 @@ static void intel_atomic_commit_tail(str
 		if (!intel_can_enable_sagv(state))
 			intel_disable_sagv(dev_priv);
 
-		intel_modeset_verify_disabled(dev);
+		intel_modeset_verify_disabled(dev, state);
 	}
 
 	/* Complete the events for pipes that have now been disabled */
@@ -14456,7 +14454,8 @@ static void intel_atomic_commit_tail(str
 		intel_cstate = to_intel_crtc_state(crtc->state);
 
 		if (dev_priv->display.optimize_watermarks)
-			dev_priv->display.optimize_watermarks(intel_cstate);
+			dev_priv->display.optimize_watermarks(intel_state,
+							      intel_cstate);
 	}
 
 	for_each_crtc_in_state(state, crtc, old_crtc_state, i) {
@@ -14465,7 +14464,7 @@ static void intel_atomic_commit_tail(str
 		if (put_domains[i])
 			modeset_put_power_domains(dev_priv, put_domains[i]);
 
-		intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state);
+		intel_modeset_verify_crtc(crtc, state, old_crtc_state, crtc->state);
 	}
 
 	if (intel_state->modeset && intel_can_enable_sagv(state))
@@ -14482,7 +14481,7 @@ static void intel_atomic_commit_tail(str
 
 	drm_atomic_helper_commit_cleanup_done(state);
 
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 
 	/* As one of the primary mmio accessors, KMS has a high likelihood
 	 * of triggering bugs in unclaimed access. After we finish
@@ -14500,12 +14499,39 @@ static void intel_atomic_commit_tail(str
 
 static void intel_atomic_commit_work(struct work_struct *work)
 {
-	struct drm_atomic_state *state = container_of(work,
-						      struct drm_atomic_state,
-						      commit_work);
+	struct drm_atomic_state *state =
+		container_of(work, struct drm_atomic_state, commit_work);
+
 	intel_atomic_commit_tail(state);
 }
 
+static int __i915_sw_fence_call
+intel_atomic_commit_ready(struct i915_sw_fence *fence,
+			  enum i915_sw_fence_notify notify)
+{
+	struct intel_atomic_state *state =
+		container_of(fence, struct intel_atomic_state, commit_ready);
+
+	switch (notify) {
+	case FENCE_COMPLETE:
+		if (state->base.commit_work.func)
+			queue_work(system_unbound_wq, &state->base.commit_work);
+		break;
+
+	case FENCE_FREE:
+		{
+			struct intel_atomic_helper *helper =
+				&to_i915(state->base.dev)->atomic_helper;
+
+			if (llist_add(&state->freed, &helper->free_list))
+				schedule_work(&helper->free_work);
+			break;
+		}
+	}
+
+	return NOTIFY_DONE;
+}
+
 static void intel_atomic_track_fbs(struct drm_atomic_state *state)
 {
 	struct drm_plane_state *old_plane_state;
@@ -14527,10 +14553,6 @@ static void intel_atomic_track_fbs(struc
  * This function commits a top-level state object that has been validated
  * with drm_atomic_helper_check().
  *
- * FIXME:  Atomic modeset support for i915 is not yet complete.  At the moment
- * nonblocking commits are only safe for pure plane updates. Everything else
- * should work though.
- *
  * RETURNS
  * Zero for success or -errno.
  */
@@ -14542,33 +14564,42 @@ static int intel_atomic_commit(struct dr
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	int ret = 0;
 
-	if (intel_state->modeset && nonblock) {
-		DRM_DEBUG_KMS("nonblocking commit for modeset not yet implemented.\n");
-		return -EINVAL;
-	}
-
 	ret = drm_atomic_helper_setup_commit(state, nonblock);
 	if (ret)
 		return ret;
 
-	INIT_WORK(&state->commit_work, intel_atomic_commit_work);
+	drm_atomic_state_get(state);
+	i915_sw_fence_init(&intel_state->commit_ready,
+			   intel_atomic_commit_ready);
 
-	ret = intel_atomic_prepare_commit(dev, state, nonblock);
+	ret = intel_atomic_prepare_commit(dev, state);
 	if (ret) {
 		DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret);
+		i915_sw_fence_commit(&intel_state->commit_ready);
 		return ret;
 	}
 
 	drm_atomic_helper_swap_state(state, true);
 	dev_priv->wm.distrust_bios_wm = false;
-	dev_priv->wm.skl_results = intel_state->wm_results;
 	intel_shared_dpll_commit(state);
 	intel_atomic_track_fbs(state);
 
-	if (nonblock)
-		queue_work(system_unbound_wq, &state->commit_work);
-	else
+	if (intel_state->modeset) {
+		memcpy(dev_priv->min_pixclk, intel_state->min_pixclk,
+		       sizeof(intel_state->min_pixclk));
+		dev_priv->active_crtcs = intel_state->active_crtcs;
+		dev_priv->atomic_cdclk_freq = intel_state->cdclk;
+	}
+
+	drm_atomic_state_get(state);
+	INIT_WORK(&state->commit_work,
+		  nonblock ? intel_atomic_commit_work : NULL);
+
+	i915_sw_fence_commit(&intel_state->commit_ready);
+	if (!nonblock) {
+		i915_sw_fence_wait(&intel_state->commit_ready);
 		intel_atomic_commit_tail(state);
+	}
 
 	return 0;
 }
@@ -14606,9 +14637,8 @@ retry:
 		goto retry;
 	}
 
-	if (ret)
 out:
-		drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 }
 
 /*
@@ -14681,19 +14711,21 @@ int
 intel_prepare_plane_fb(struct drm_plane *plane,
 		       struct drm_plane_state *new_state)
 {
-	struct drm_device *dev = plane->dev;
+	struct intel_atomic_state *intel_state =
+		to_intel_atomic_state(new_state->state);
+	struct drm_i915_private *dev_priv = to_i915(plane->dev);
 	struct drm_framebuffer *fb = new_state->fb;
 	struct drm_i915_gem_object *obj = intel_fb_obj(fb);
 	struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb);
-	struct reservation_object *resv;
-	int ret = 0;
+	int ret;
 
 	if (!obj && !old_obj)
 		return 0;
 
 	if (old_obj) {
 		struct drm_crtc_state *crtc_state =
-			drm_atomic_get_existing_crtc_state(new_state->state, plane->state->crtc);
+			drm_atomic_get_existing_crtc_state(new_state->state,
+							   plane->state->crtc);
 
 		/* Big Hammer, we also need to ensure that any pending
 		 * MI_WAIT_FOR_EVENT inside a user batch buffer on the
@@ -14706,52 +14738,60 @@ intel_prepare_plane_fb(struct drm_plane
 		 * This should only fail upon a hung GPU, in which case we
 		 * can safely continue.
 		 */
-		if (needs_modeset(crtc_state))
-			ret = i915_gem_object_wait_rendering(old_obj, true);
-		if (ret) {
-			/* GPU hangs should have been swallowed by the wait */
-			WARN_ON(ret == -EIO);
-			return ret;
+		if (needs_modeset(crtc_state)) {
+			ret = i915_sw_fence_await_reservation(&intel_state->commit_ready,
+							      old_obj->resv, NULL,
+							      false, 0,
+							      GFP_KERNEL);
+			if (ret < 0)
+				return ret;
 		}
 	}
 
+	if (new_state->fence) { /* explicit fencing */
+		ret = i915_sw_fence_await_dma_fence(&intel_state->commit_ready,
+						    new_state->fence,
+						    I915_FENCE_TIMEOUT,
+						    GFP_KERNEL);
+		if (ret < 0)
+			return ret;
+	}
+
 	if (!obj)
 		return 0;
 
-	/* For framebuffer backed by dmabuf, wait for fence */
-	resv = i915_gem_object_get_dmabuf_resv(obj);
-	if (resv) {
-		long lret;
-
-		lret = reservation_object_wait_timeout_rcu(resv, false, true,
-							   MAX_SCHEDULE_TIMEOUT);
-		if (lret == -ERESTARTSYS)
-			return lret;
+	if (!new_state->fence) { /* implicit fencing */
+		ret = i915_sw_fence_await_reservation(&intel_state->commit_ready,
+						      obj->resv, NULL,
+						      false, I915_FENCE_TIMEOUT,
+						      GFP_KERNEL);
+		if (ret < 0)
+			return ret;
 
-		WARN(lret < 0, "waiting returns %li\n", lret);
+		i915_gem_object_wait_priority(obj, 0, I915_PRIORITY_DISPLAY);
 	}
 
 	if (plane->type == DRM_PLANE_TYPE_CURSOR &&
-	    INTEL_INFO(dev)->cursor_needs_physical) {
-		int align = IS_I830(dev) ? 16 * 1024 : 256;
+	    INTEL_INFO(dev_priv)->cursor_needs_physical) {
+		int align = IS_I830(dev_priv) ? 16 * 1024 : 256;
 		ret = i915_gem_object_attach_phys(obj, align);
-		if (ret)
+		if (ret) {
 			DRM_DEBUG_KMS("failed to attach phys object\n");
+			return ret;
+		}
 	} else {
 		struct i915_vma *vma;
 
 		vma = intel_pin_and_fence_fb_obj(fb, new_state->rotation);
-		if (IS_ERR(vma))
-			ret = PTR_ERR(vma);
-	}
+		if (IS_ERR(vma)) {
+			DRM_DEBUG_KMS("failed to pin object\n");
+			return PTR_ERR(vma);
+		}
 
-	if (ret == 0) {
-		to_intel_plane_state(new_state)->wait_req =
-			i915_gem_active_get(&obj->last_write,
-					    &obj->base.dev->struct_mutex);
+		to_intel_plane_state(new_state)->vma = vma;
 	}
 
-	return ret;
+	return 0;
 }
 
 /**
@@ -14767,23 +14807,12 @@ void
 intel_cleanup_plane_fb(struct drm_plane *plane,
 		       struct drm_plane_state *old_state)
 {
-	struct drm_device *dev = plane->dev;
-	struct intel_plane_state *old_intel_state;
-	struct intel_plane_state *intel_state = to_intel_plane_state(plane->state);
-	struct drm_i915_gem_object *old_obj = intel_fb_obj(old_state->fb);
-	struct drm_i915_gem_object *obj = intel_fb_obj(plane->state->fb);
-
-	old_intel_state = to_intel_plane_state(old_state);
-
-	if (!obj && !old_obj)
-		return;
-
-	if (old_obj && (plane->type != DRM_PLANE_TYPE_CURSOR ||
-	    !INTEL_INFO(dev)->cursor_needs_physical))
-		intel_unpin_fb_obj(old_state->fb, old_state->rotation);
+	struct i915_vma *vma;
 
-	i915_gem_request_assign(&intel_state->wait_req, NULL);
-	i915_gem_request_assign(&old_intel_state->wait_req, NULL);
+	/* Should only be called after a successful intel_prepare_plane_fb()! */
+	vma = fetch_and_zero(&to_intel_plane_state(old_state)->vma);
+	if (vma)
+		intel_unpin_fb_vma(vma);
 }
 
 int
@@ -14858,30 +14887,34 @@ static void intel_begin_crtc_commit(stru
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_crtc_state *old_intel_state =
+	struct intel_crtc_state *intel_cstate =
+		to_intel_crtc_state(crtc->state);
+	struct intel_crtc_state *old_intel_cstate =
 		to_intel_crtc_state(old_crtc_state);
+	struct intel_atomic_state *old_intel_state =
+		to_intel_atomic_state(old_crtc_state->state);
 	bool modeset = needs_modeset(crtc->state);
-	enum pipe pipe = intel_crtc->pipe;
 
 	/* Perform vblank evasion around commit operation */
 	intel_pipe_update_start(intel_crtc);
 
 	if (modeset)
-		return;
+		goto out;
 
 	if (crtc->state->color_mgmt_changed || to_intel_crtc_state(crtc->state)->update_pipe) {
 		intel_color_set_csc(crtc->state);
 		intel_color_load_luts(crtc->state);
 	}
 
-	if (to_intel_crtc_state(crtc->state)->update_pipe)
-		intel_update_pipe_config(intel_crtc, old_intel_state);
-	else if (INTEL_GEN(dev_priv) >= 9) {
+	if (intel_cstate->update_pipe)
+		intel_update_pipe_config(intel_crtc, old_intel_cstate);
+	else if (INTEL_GEN(dev_priv) >= 9)
 		skl_detach_scalers(intel_crtc);
 
-		I915_WRITE(PIPE_WM_LINETIME(pipe),
-			   dev_priv->wm.skl_hw.wm_linetime[pipe]);
-	}
+out:
+	if (dev_priv->display.atomic_update_watermarks)
+		dev_priv->display.atomic_update_watermarks(old_intel_state,
+							   intel_cstate);
 }
 
 static void intel_finish_crtc_commit(struct drm_crtc *crtc,
@@ -14901,9 +14934,6 @@ static void intel_finish_crtc_commit(str
  */
 void intel_plane_destroy(struct drm_plane *plane)
 {
-	if (!plane)
-		return;
-
 	drm_plane_cleanup(plane);
 	kfree(to_intel_plane(plane));
 }
@@ -14917,53 +14947,63 @@ const struct drm_plane_funcs intel_plane
 	.atomic_set_property = intel_plane_atomic_set_property,
 	.atomic_duplicate_state = intel_plane_duplicate_state,
 	.atomic_destroy_state = intel_plane_destroy_state,
-
 };
 
-static struct drm_plane *intel_primary_plane_create(struct drm_device *dev,
-						    int pipe)
+static struct intel_plane *
+intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
 	struct intel_plane *primary = NULL;
 	struct intel_plane_state *state = NULL;
 	const uint32_t *intel_primary_formats;
+	unsigned int supported_rotations;
 	unsigned int num_formats;
 	int ret;
 
 	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
-	if (!primary)
+	if (!primary) {
+		ret = -ENOMEM;
 		goto fail;
+	}
 
 	state = intel_create_plane_state(&primary->base);
-	if (!state)
+	if (!state) {
+		ret = -ENOMEM;
 		goto fail;
+	}
+
 	primary->base.state = &state->base;
 
 	primary->can_scale = false;
 	primary->max_downscale = 1;
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		primary->can_scale = true;
 		state->scaler_id = -1;
 	}
 	primary->pipe = pipe;
-	primary->plane = pipe;
+	/*
+	 * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
+	 * port is hooked to pipe B. Hence we want plane A feeding pipe B.
+	 */
+	if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) < 4)
+		primary->plane = (enum plane) !pipe;
+	else
+		primary->plane = (enum plane) pipe;
 	primary->frontbuffer_bit = INTEL_FRONTBUFFER_PRIMARY(pipe);
 	primary->check_plane = intel_check_primary_plane;
-	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4)
-		primary->plane = !pipe;
 
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		intel_primary_formats = skl_primary_formats;
 		num_formats = ARRAY_SIZE(skl_primary_formats);
 
 		primary->update_plane = skylake_update_primary_plane;
 		primary->disable_plane = skylake_disable_primary_plane;
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		intel_primary_formats = i965_primary_formats;
 		num_formats = ARRAY_SIZE(i965_primary_formats);
 
 		primary->update_plane = ironlake_update_primary_plane;
 		primary->disable_plane = i9xx_disable_primary_plane;
-	} else if (INTEL_INFO(dev)->gen >= 4) {
+	} else if (INTEL_GEN(dev_priv) >= 4) {
 		intel_primary_formats = i965_primary_formats;
 		num_formats = ARRAY_SIZE(i965_primary_formats);
 
@@ -14977,57 +15017,56 @@ static struct drm_plane *intel_primary_p
 		primary->disable_plane = i9xx_disable_primary_plane;
 	}
 
-	if (INTEL_INFO(dev)->gen >= 9)
-		ret = drm_universal_plane_init(dev, &primary->base, 0,
-					       &intel_plane_funcs,
+	if (INTEL_GEN(dev_priv) >= 9)
+		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane 1%c", pipe_name(pipe));
-	else if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev))
-		ret = drm_universal_plane_init(dev, &primary->base, 0,
-					       &intel_plane_funcs,
+	else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv))
+		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "primary %c", pipe_name(pipe));
 	else
-		ret = drm_universal_plane_init(dev, &primary->base, 0,
-					       &intel_plane_funcs,
+		ret = drm_universal_plane_init(&dev_priv->drm, &primary->base,
+					       0, &intel_plane_funcs,
 					       intel_primary_formats, num_formats,
 					       DRM_PLANE_TYPE_PRIMARY,
 					       "plane %c", plane_name(primary->plane));
 	if (ret)
 		goto fail;
 
-	if (INTEL_INFO(dev)->gen >= 4)
-		intel_create_rotation_property(dev, primary);
+	if (INTEL_GEN(dev_priv) >= 9) {
+		supported_rotations =
+			DRM_ROTATE_0 | DRM_ROTATE_90 |
+			DRM_ROTATE_180 | DRM_ROTATE_270;
+	} else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+		supported_rotations =
+			DRM_ROTATE_0 | DRM_ROTATE_180 |
+			DRM_REFLECT_X;
+	} else if (INTEL_GEN(dev_priv) >= 4) {
+		supported_rotations =
+			DRM_ROTATE_0 | DRM_ROTATE_180;
+	} else {
+		supported_rotations = DRM_ROTATE_0;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 4)
+		drm_plane_create_rotation_property(&primary->base,
+						   DRM_ROTATE_0,
+						   supported_rotations);
 
 	drm_plane_helper_add(&primary->base, &intel_plane_helper_funcs);
 
-	return &primary->base;
+	return primary;
 
 fail:
 	kfree(state);
 	kfree(primary);
 
-	return NULL;
-}
-
-void intel_create_rotation_property(struct drm_device *dev, struct intel_plane *plane)
-{
-	if (!dev->mode_config.rotation_property) {
-		unsigned long flags = DRM_ROTATE_0 |
-			DRM_ROTATE_180;
-
-		if (INTEL_INFO(dev)->gen >= 9)
-			flags |= DRM_ROTATE_90 | DRM_ROTATE_270;
-
-		dev->mode_config.rotation_property =
-			drm_mode_create_rotation_property(dev, flags);
-	}
-	if (dev->mode_config.rotation_property)
-		drm_object_attach_property(&plane->base.base,
-				dev->mode_config.rotation_property,
-				plane->base.state->rotation);
+	return ERR_PTR(ret);
 }
 
 static int
@@ -15054,7 +15093,8 @@ intel_check_cursor_plane(struct drm_plan
 		return 0;
 
 	/* Check for which cursor types we support */
-	if (!cursor_size_ok(plane->dev, state->base.crtc_w, state->base.crtc_h)) {
+	if (!cursor_size_ok(to_i915(plane->dev), state->base.crtc_w,
+			    state->base.crtc_h)) {
 		DRM_DEBUG("Cursor dimension %dx%d not supported\n",
 			  state->base.crtc_w, state->base.crtc_h);
 		return -EINVAL;
@@ -15066,7 +15106,7 @@ intel_check_cursor_plane(struct drm_plan
 		return -ENOMEM;
 	}
 
-	if (fb->modifier[0] != DRM_FORMAT_MOD_NONE) {
+	if (fb->modifier != DRM_FORMAT_MOD_NONE) {
 		DRM_DEBUG_KMS("cursor cannot be tiled\n");
 		return -EINVAL;
 	}
@@ -15081,7 +15121,7 @@ intel_check_cursor_plane(struct drm_plan
 	 * display power well must be turned off and on again.
 	 * Refuse the put the cursor into that compromised position.
 	 */
-	if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C &&
+	if (IS_CHERRYVIEW(to_i915(plane->dev)) && pipe == PIPE_C &&
 	    state->base.visible && state->base.crtc_x < 0) {
 		DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
 		return -EINVAL;
@@ -15107,14 +15147,14 @@ intel_update_cursor_plane(struct drm_pla
 {
 	struct drm_crtc *crtc = crtc_state->base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = to_i915(plane->dev);
 	struct drm_i915_gem_object *obj = intel_fb_obj(state->base.fb);
 	uint32_t addr;
 
 	if (!obj)
 		addr = 0;
-	else if (!INTEL_INFO(dev)->cursor_needs_physical)
-		addr = i915_gem_object_ggtt_offset(obj, NULL);
+	else if (!INTEL_INFO(dev_priv)->cursor_needs_physical)
+		addr = intel_plane_ggtt_offset(state);
 	else
 		addr = obj->phys_handle->busaddr;
 
@@ -15122,20 +15162,25 @@ intel_update_cursor_plane(struct drm_pla
 	intel_crtc_update_cursor(crtc, state);
 }
 
-static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev,
-						   int pipe)
+static struct intel_plane *
+intel_cursor_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
 	struct intel_plane *cursor = NULL;
 	struct intel_plane_state *state = NULL;
 	int ret;
 
 	cursor = kzalloc(sizeof(*cursor), GFP_KERNEL);
-	if (!cursor)
+	if (!cursor) {
+		ret = -ENOMEM;
 		goto fail;
+	}
 
 	state = intel_create_plane_state(&cursor->base);
-	if (!state)
+	if (!state) {
+		ret = -ENOMEM;
 		goto fail;
+	}
+
 	cursor->base.state = &state->base;
 
 	cursor->can_scale = false;
@@ -15147,8 +15192,8 @@ static struct drm_plane *intel_cursor_pl
 	cursor->update_plane = intel_update_cursor_plane;
 	cursor->disable_plane = intel_disable_cursor_plane;
 
-	ret = drm_universal_plane_init(dev, &cursor->base, 0,
-				       &intel_plane_funcs,
+	ret = drm_universal_plane_init(&dev_priv->drm, &cursor->base,
+				       0, &intel_plane_funcs,
 				       intel_cursor_formats,
 				       ARRAY_SIZE(intel_cursor_formats),
 				       DRM_PLANE_TYPE_CURSOR,
@@ -15156,102 +15201,106 @@ static struct drm_plane *intel_cursor_pl
 	if (ret)
 		goto fail;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
-		if (!dev->mode_config.rotation_property)
-			dev->mode_config.rotation_property =
-				drm_mode_create_rotation_property(dev,
-							DRM_ROTATE_0 |
-							DRM_ROTATE_180);
-		if (dev->mode_config.rotation_property)
-			drm_object_attach_property(&cursor->base.base,
-				dev->mode_config.rotation_property,
-				state->base.rotation);
-	}
+	if (INTEL_GEN(dev_priv) >= 4)
+		drm_plane_create_rotation_property(&cursor->base,
+						   DRM_ROTATE_0,
+						   DRM_ROTATE_0 |
+						   DRM_ROTATE_180);
 
-	if (INTEL_INFO(dev)->gen >=9)
+	if (INTEL_GEN(dev_priv) >= 9)
 		state->scaler_id = -1;
 
 	drm_plane_helper_add(&cursor->base, &intel_plane_helper_funcs);
 
-	return &cursor->base;
+	return cursor;
 
 fail:
 	kfree(state);
 	kfree(cursor);
 
-	return NULL;
+	return ERR_PTR(ret);
 }
 
-static void skl_init_scalers(struct drm_device *dev, struct intel_crtc *intel_crtc,
-	struct intel_crtc_state *crtc_state)
+static void skl_init_scalers(struct drm_i915_private *dev_priv,
+			     struct intel_crtc *crtc,
+			     struct intel_crtc_state *crtc_state)
 {
+	struct intel_crtc_scaler_state *scaler_state =
+		&crtc_state->scaler_state;
 	int i;
-	struct intel_scaler *intel_scaler;
-	struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state;
 
-	for (i = 0; i < intel_crtc->num_scalers; i++) {
-		intel_scaler = &scaler_state->scalers[i];
-		intel_scaler->in_use = 0;
-		intel_scaler->mode = PS_SCALER_MODE_DYN;
+	for (i = 0; i < crtc->num_scalers; i++) {
+		struct intel_scaler *scaler = &scaler_state->scalers[i];
+
+		scaler->in_use = 0;
+		scaler->mode = PS_SCALER_MODE_DYN;
 	}
 
 	scaler_state->scaler_id = -1;
 }
 
-static void intel_crtc_init(struct drm_device *dev, int pipe)
+static int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc;
 	struct intel_crtc_state *crtc_state = NULL;
-	struct drm_plane *primary = NULL;
-	struct drm_plane *cursor = NULL;
-	int ret;
+	struct intel_plane *primary = NULL;
+	struct intel_plane *cursor = NULL;
+	int sprite, ret;
 
 	intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL);
-	if (intel_crtc == NULL)
-		return;
+	if (!intel_crtc)
+		return -ENOMEM;
 
 	crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL);
-	if (!crtc_state)
+	if (!crtc_state) {
+		ret = -ENOMEM;
 		goto fail;
+	}
 	intel_crtc->config = crtc_state;
 	intel_crtc->base.state = &crtc_state->base;
 	crtc_state->base.crtc = &intel_crtc->base;
 
 	/* initialize shared scalers */
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		if (pipe == PIPE_C)
 			intel_crtc->num_scalers = 1;
 		else
 			intel_crtc->num_scalers = SKL_NUM_SCALERS;
 
-		skl_init_scalers(dev, intel_crtc, crtc_state);
+		skl_init_scalers(dev_priv, intel_crtc, crtc_state);
 	}
 
-	primary = intel_primary_plane_create(dev, pipe);
-	if (!primary)
+	primary = intel_primary_plane_create(dev_priv, pipe);
+	if (IS_ERR(primary)) {
+		ret = PTR_ERR(primary);
 		goto fail;
+	}
 
-	cursor = intel_cursor_plane_create(dev, pipe);
-	if (!cursor)
+	for_each_sprite(dev_priv, pipe, sprite) {
+		struct intel_plane *plane;
+
+		plane = intel_sprite_plane_create(dev_priv, pipe, sprite);
+		if (IS_ERR(plane)) {
+			ret = PTR_ERR(plane);
+			goto fail;
+		}
+	}
+
+	cursor = intel_cursor_plane_create(dev_priv, pipe);
+	if (IS_ERR(cursor)) {
+		ret = PTR_ERR(cursor);
 		goto fail;
+	}
 
-	ret = drm_crtc_init_with_planes(dev, &intel_crtc->base, primary,
-					cursor, &intel_crtc_funcs,
+	ret = drm_crtc_init_with_planes(&dev_priv->drm, &intel_crtc->base,
+					&primary->base, &cursor->base,
+					&intel_crtc_funcs,
 					"pipe %c", pipe_name(pipe));
 	if (ret)
 		goto fail;
 
-	/*
-	 * On gen2/3 only plane A can do fbc, but the panel fitter and lvds port
-	 * is hooked to pipe B. Hence we want plane A feeding pipe B.
-	 */
 	intel_crtc->pipe = pipe;
-	intel_crtc->plane = pipe;
-	if (HAS_FBC(dev) && INTEL_INFO(dev)->gen < 4) {
-		DRM_DEBUG_KMS("swapping pipes & planes for FBC\n");
-		intel_crtc->plane = !pipe;
-	}
+	intel_crtc->plane = primary->plane;
 
 	intel_crtc->cursor_base = ~0;
 	intel_crtc->cursor_cntl = ~0;
@@ -15261,21 +15310,26 @@ static void intel_crtc_init(struct drm_d
 
 	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
 	       dev_priv->plane_to_crtc_mapping[intel_crtc->plane] != NULL);
-	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = &intel_crtc->base;
-	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = &intel_crtc->base;
+	dev_priv->plane_to_crtc_mapping[intel_crtc->plane] = intel_crtc;
+	dev_priv->pipe_to_crtc_mapping[intel_crtc->pipe] = intel_crtc;
 
 	drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs);
 
 	intel_color_init(&intel_crtc->base);
 
 	WARN_ON(drm_crtc_index(&intel_crtc->base) != intel_crtc->pipe);
-	return;
+
+	return 0;
 
 fail:
-	intel_plane_destroy(primary);
-	intel_plane_destroy(cursor);
+	/*
+	 * drm_mode_config_cleanup() will free up any
+	 * crtcs/planes already initialized.
+	 */
 	kfree(crtc_state);
 	kfree(intel_crtc);
+
+	return ret;
 }
 
 enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
@@ -15325,40 +15379,37 @@ static int intel_encoder_clones(struct i
 	return index_mask;
 }
 
-static bool has_edp_a(struct drm_device *dev)
+static bool has_edp_a(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (!IS_MOBILE(dev))
+	if (!IS_MOBILE(dev_priv))
 		return false;
 
 	if ((I915_READ(DP_A) & DP_DETECTED) == 0)
 		return false;
 
-	if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
+	if (IS_GEN5(dev_priv) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE))
 		return false;
 
 	return true;
 }
 
-static bool intel_crt_present(struct drm_device *dev)
+static bool intel_crt_present(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (INTEL_INFO(dev)->gen >= 9)
+	if (INTEL_GEN(dev_priv) >= 9)
 		return false;
 
-	if (IS_HSW_ULT(dev) || IS_BDW_ULT(dev))
+	if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv))
 		return false;
 
-	if (IS_CHERRYVIEW(dev))
+	if (IS_CHERRYVIEW(dev_priv))
 		return false;
 
-	if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
+	if (HAS_PCH_LPT_H(dev_priv) &&
+	    I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED)
 		return false;
 
 	/* DDI E can't be used if DDI A requires 4 lanes */
-	if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
+	if (HAS_DDI(dev_priv) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
 		return false;
 
 	if (!dev_priv->vbt.int_crt_support)
@@ -15418,10 +15469,10 @@ static void intel_setup_outputs(struct d
 	 */
 	intel_lvds_init(dev);
 
-	if (intel_crt_present(dev))
+	if (intel_crt_present(dev_priv))
 		intel_crt_init(dev);
 
-	if (IS_BROXTON(dev)) {
+	if (IS_BROXTON(dev_priv)) {
 		/*
 		 * FIXME: Broxton doesn't support port detection via the
 		 * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to
@@ -15432,7 +15483,7 @@ static void intel_setup_outputs(struct d
 		intel_ddi_init(dev, PORT_C);
 
 		intel_dsi_init(dev);
-	} else if (HAS_DDI(dev)) {
+	} else if (HAS_DDI(dev_priv)) {
 		int found;
 
 		/*
@@ -15442,7 +15493,7 @@ static void intel_setup_outputs(struct d
 		 */
 		found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
 		/* WaIgnoreDDIAStrap: skl */
-		if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+		if (found || IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 			intel_ddi_init(dev, PORT_A);
 
 		/* DDI B, C and D detection is indicated by the SFUSE_STRAP
@@ -15458,17 +15509,17 @@ static void intel_setup_outputs(struct d
 		/*
 		 * On SKL we don't have a way to detect DDI-E so we rely on VBT.
 		 */
-		if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
+		if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) &&
 		    (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp ||
 		     dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi ||
 		     dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi))
 			intel_ddi_init(dev, PORT_E);
 
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		int found;
-		dpd_is_edp = intel_dp_is_edp(dev, PORT_D);
+		dpd_is_edp = intel_dp_is_edp(dev_priv, PORT_D);
 
-		if (has_edp_a(dev))
+		if (has_edp_a(dev_priv))
 			intel_dp_init(dev, DP_A, PORT_A);
 
 		if (I915_READ(PCH_HDMIB) & SDVO_DETECTED) {
@@ -15491,7 +15542,7 @@ static void intel_setup_outputs(struct d
 
 		if (I915_READ(PCH_DP_D) & DP_DETECTED)
 			intel_dp_init(dev, PCH_DP_D, PORT_D);
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		bool has_edp, has_port;
 
 		/*
@@ -15509,21 +15560,21 @@ static void intel_setup_outputs(struct d
 		 * trust the port type the VBT declares as we've seen at least
 		 * HDMI ports that the VBT claim are DP or eDP.
 		 */
-		has_edp = intel_dp_is_edp(dev, PORT_B);
+		has_edp = intel_dp_is_edp(dev_priv, PORT_B);
 		has_port = intel_bios_is_port_present(dev_priv, PORT_B);
 		if (I915_READ(VLV_DP_B) & DP_DETECTED || has_port)
 			has_edp &= intel_dp_init(dev, VLV_DP_B, PORT_B);
 		if ((I915_READ(VLV_HDMIB) & SDVO_DETECTED || has_port) && !has_edp)
 			intel_hdmi_init(dev, VLV_HDMIB, PORT_B);
 
-		has_edp = intel_dp_is_edp(dev, PORT_C);
+		has_edp = intel_dp_is_edp(dev_priv, PORT_C);
 		has_port = intel_bios_is_port_present(dev_priv, PORT_C);
 		if (I915_READ(VLV_DP_C) & DP_DETECTED || has_port)
 			has_edp &= intel_dp_init(dev, VLV_DP_C, PORT_C);
 		if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp)
 			intel_hdmi_init(dev, VLV_HDMIC, PORT_C);
 
-		if (IS_CHERRYVIEW(dev)) {
+		if (IS_CHERRYVIEW(dev_priv)) {
 			/*
 			 * eDP not supported on port D,
 			 * so no need to worry about it
@@ -15536,18 +15587,18 @@ static void intel_setup_outputs(struct d
 		}
 
 		intel_dsi_init(dev);
-	} else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) {
+	} else if (!IS_GEN2(dev_priv) && !IS_PINEVIEW(dev_priv)) {
 		bool found = false;
 
 		if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) {
 			DRM_DEBUG_KMS("probing SDVOB\n");
 			found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B);
-			if (!found && IS_G4X(dev)) {
+			if (!found && IS_G4X(dev_priv)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOB\n");
 				intel_hdmi_init(dev, GEN4_HDMIB, PORT_B);
 			}
 
-			if (!found && IS_G4X(dev))
+			if (!found && IS_G4X(dev_priv))
 				intel_dp_init(dev, DP_B, PORT_B);
 		}
 
@@ -15560,21 +15611,20 @@ static void intel_setup_outputs(struct d
 
 		if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) {
 
-			if (IS_G4X(dev)) {
+			if (IS_G4X(dev_priv)) {
 				DRM_DEBUG_KMS("probing HDMI on SDVOC\n");
 				intel_hdmi_init(dev, GEN4_HDMIC, PORT_C);
 			}
-			if (IS_G4X(dev))
+			if (IS_G4X(dev_priv))
 				intel_dp_init(dev, DP_C, PORT_C);
 		}
 
-		if (IS_G4X(dev) &&
-		    (I915_READ(DP_D) & DP_DETECTED))
+		if (IS_G4X(dev_priv) && (I915_READ(DP_D) & DP_DETECTED))
 			intel_dp_init(dev, DP_D, PORT_D);
-	} else if (IS_GEN2(dev))
+	} else if (IS_GEN2(dev_priv))
 		intel_dvo_init(dev);
 
-	if (SUPPORTS_TV(dev))
+	if (SUPPORTS_TV(dev_priv))
 		intel_tv_init(dev);
 
 	intel_psr_init(dev);
@@ -15629,6 +15679,8 @@ static int intel_user_framebuffer_dirty(
 	struct drm_i915_gem_object *obj = intel_fb->obj;
 
 	mutex_lock(&dev->struct_mutex);
+	if (obj->pin_display && obj->cache_dirty)
+		i915_gem_clflush_object(obj, true);
 	intel_fb_obj_flush(obj, false, ORIGIN_DIRTYFB);
 	mutex_unlock(&dev->struct_mutex);
 
@@ -15642,10 +15694,10 @@ static const struct drm_framebuffer_func
 };
 
 static
-u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier,
-			 uint32_t pixel_format)
+u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv,
+			 uint64_t fb_modifier, uint32_t pixel_format)
 {
-	u32 gen = INTEL_INFO(dev)->gen;
+	u32 gen = INTEL_INFO(dev_priv)->gen;
 
 	if (gen >= 9) {
 		int cpp = drm_format_plane_cpp(pixel_format, 0);
@@ -15654,7 +15706,8 @@ u32 intel_fb_pitch_limit(struct drm_devi
 		 *  pixels and 32K bytes."
 		 */
 		return min(8192 * cpp, 32768);
-	} else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
+	} else if (gen >= 5 && !IS_VALLEYVIEW(dev_priv) &&
+		   !IS_CHERRYVIEW(dev_priv)) {
 		return 32*1024;
 	} else if (gen >= 4) {
 		if (fb_modifier == I915_FORMAT_MOD_X_TILED)
@@ -15681,7 +15734,7 @@ static int intel_framebuffer_init(struct
 	unsigned int tiling = i915_gem_object_get_tiling(obj);
 	int ret;
 	u32 pitch_limit, stride_alignment;
-	char *format_name;
+	struct drm_format_name_buf format_name;
 
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
@@ -15708,7 +15761,7 @@ static int intel_framebuffer_init(struct
 	switch (mode_cmd->modifier[0]) {
 	case I915_FORMAT_MOD_Y_TILED:
 	case I915_FORMAT_MOD_Yf_TILED:
-		if (INTEL_INFO(dev)->gen < 9) {
+		if (INTEL_GEN(dev_priv) < 9) {
 			DRM_DEBUG("Unsupported tiling 0x%llx!\n",
 				  mode_cmd->modifier[0]);
 			return -EINVAL;
@@ -15741,7 +15794,7 @@ static int intel_framebuffer_init(struct
 		return -EINVAL;
 	}
 
-	pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0],
+	pitch_limit = intel_fb_pitch_limit(dev_priv, mode_cmd->modifier[0],
 					   mode_cmd->pixel_format);
 	if (mode_cmd->pitches[0] > pitch_limit) {
 		DRM_DEBUG("%s pitch (%u) must be at less than %d\n",
@@ -15771,37 +15824,33 @@ static int intel_framebuffer_init(struct
 	case DRM_FORMAT_ARGB8888:
 		break;
 	case DRM_FORMAT_XRGB1555:
-		if (INTEL_INFO(dev)->gen > 3) {
-			format_name = drm_get_format_name(mode_cmd->pixel_format);
-			DRM_DEBUG("unsupported pixel format: %s\n", format_name);
-			kfree(format_name);
+		if (INTEL_GEN(dev_priv) > 3) {
+			DRM_DEBUG("unsupported pixel format: %s\n",
+			          drm_get_format_name(mode_cmd->pixel_format, &format_name));
 			return -EINVAL;
 		}
 		break;
 	case DRM_FORMAT_ABGR8888:
-		if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
-		    INTEL_INFO(dev)->gen < 9) {
-			format_name = drm_get_format_name(mode_cmd->pixel_format);
-			DRM_DEBUG("unsupported pixel format: %s\n", format_name);
-			kfree(format_name);
+		if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
+		    INTEL_GEN(dev_priv) < 9) {
+			DRM_DEBUG("unsupported pixel format: %s\n",
+			          drm_get_format_name(mode_cmd->pixel_format, &format_name));
 			return -EINVAL;
 		}
 		break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_XRGB2101010:
 	case DRM_FORMAT_XBGR2101010:
-		if (INTEL_INFO(dev)->gen < 4) {
-			format_name = drm_get_format_name(mode_cmd->pixel_format);
-			DRM_DEBUG("unsupported pixel format: %s\n", format_name);
-			kfree(format_name);
+		if (INTEL_GEN(dev_priv) < 4) {
+			DRM_DEBUG("unsupported pixel format: %s\n",
+			          drm_get_format_name(mode_cmd->pixel_format, &format_name));
 			return -EINVAL;
 		}
 		break;
 	case DRM_FORMAT_ABGR2101010:
-		if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) {
-			format_name = drm_get_format_name(mode_cmd->pixel_format);
-			DRM_DEBUG("unsupported pixel format: %s\n", format_name);
-			kfree(format_name);
+		if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) {
+			DRM_DEBUG("unsupported pixel format: %s\n",
+			          drm_get_format_name(mode_cmd->pixel_format, &format_name));
 			return -EINVAL;
 		}
 		break;
@@ -15809,17 +15858,15 @@ static int intel_framebuffer_init(struct
 	case DRM_FORMAT_UYVY:
 	case DRM_FORMAT_YVYU:
 	case DRM_FORMAT_VYUY:
-		if (INTEL_INFO(dev)->gen < 5) {
-			format_name = drm_get_format_name(mode_cmd->pixel_format);
-			DRM_DEBUG("unsupported pixel format: %s\n", format_name);
-			kfree(format_name);
+		if (INTEL_GEN(dev_priv) < 5) {
+			DRM_DEBUG("unsupported pixel format: %s\n",
+			          drm_get_format_name(mode_cmd->pixel_format, &format_name));
 			return -EINVAL;
 		}
 		break;
 	default:
-		format_name = drm_get_format_name(mode_cmd->pixel_format);
-		DRM_DEBUG("unsupported pixel format: %s\n", format_name);
-		kfree(format_name);
+		DRM_DEBUG("unsupported pixel format: %s\n",
+		          drm_get_format_name(mode_cmd->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
@@ -15860,17 +15907,11 @@ intel_user_framebuffer_create(struct drm
 
 	fb = intel_framebuffer_create(dev, &mode_cmd, obj);
 	if (IS_ERR(fb))
-		i915_gem_object_put_unlocked(obj);
+		i915_gem_object_put(obj);
 
 	return fb;
 }
 
-#ifndef CONFIG_DRM_FBDEV_EMULATION
-static inline void intel_fbdev_output_poll_changed(struct drm_device *dev)
-{
-}
-#endif
-
 static const struct drm_mode_config_funcs intel_mode_funcs = {
 	.fb_create = intel_user_framebuffer_create,
 	.output_poll_changed = intel_fbdev_output_poll_changed,
@@ -16246,12 +16287,11 @@ static void intel_init_quirks(struct drm
 }
 
 /* Disable the VGA plane that we never use */
-static void i915_disable_vga(struct drm_device *dev)
+static void i915_disable_vga(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct pci_dev *pdev = dev_priv->drm.pdev;
 	u8 sr1;
-	i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
+	i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv);
 
 	/* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */
 	vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
@@ -16269,11 +16309,11 @@ void intel_modeset_init_hw(struct drm_de
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
-	intel_update_cdclk(dev);
+	intel_update_cdclk(dev_priv);
 
 	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
 
-	intel_init_clock_gating(dev);
+	intel_init_clock_gating(dev_priv);
 }
 
 /*
@@ -16290,6 +16330,7 @@ static void sanitize_watermarks(struct d
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_atomic_state *state;
+	struct intel_atomic_state *intel_state;
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *cstate;
 	struct drm_modeset_acquire_ctx ctx;
@@ -16318,12 +16359,14 @@ retry:
 	if (WARN_ON(IS_ERR(state)))
 		goto fail;
 
+	intel_state = to_intel_atomic_state(state);
+
 	/*
 	 * Hardware readout is the only time we don't want to calculate
 	 * intermediate watermarks (since we don't trust the current
 	 * watermarks).
 	 */
-	to_intel_atomic_state(state)->skip_intermediate_wm = true;
+	intel_state->skip_intermediate_wm = true;
 
 	ret = intel_atomic_check(dev, state);
 	if (ret) {
@@ -16339,7 +16382,7 @@ retry:
 		 * BIOS-programmed watermarks untouched and hope for the best.
 		 */
 		WARN(true, "Could not determine valid watermarks for inherited state\n");
-		goto fail;
+		goto put_state;
 	}
 
 	/* Write calculated watermark values back */
@@ -16347,20 +16390,32 @@ retry:
 		struct intel_crtc_state *cs = to_intel_crtc_state(cstate);
 
 		cs->wm.need_postvbl_update = true;
-		dev_priv->display.optimize_watermarks(cs);
+		dev_priv->display.optimize_watermarks(intel_state, cs);
 	}
 
-	drm_atomic_state_free(state);
+put_state:
+	drm_atomic_state_put(state);
 fail:
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
 }
 
-void intel_modeset_init(struct drm_device *dev)
+static void intel_atomic_helper_free_state(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, typeof(*dev_priv), atomic_helper.free_work);
+	struct intel_atomic_state *state, *next;
+	struct llist_node *freed;
+
+	freed = llist_del_all(&dev_priv->atomic_helper.free_list);
+	llist_for_each_entry_safe(state, next, freed, freed)
+		drm_atomic_state_put(&state->base);
+}
+
+int intel_modeset_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct i915_ggtt *ggtt = &dev_priv->ggtt;
-	int sprite, ret;
 	enum pipe pipe;
 	struct intel_crtc *crtc;
 
@@ -16376,12 +16431,15 @@ void intel_modeset_init(struct drm_devic
 
 	dev->mode_config.funcs = &intel_mode_funcs;
 
+	INIT_WORK(&dev_priv->atomic_helper.free_work,
+		  intel_atomic_helper_free_state);
+
 	intel_init_quirks(dev);
 
-	intel_init_pm(dev);
+	intel_init_pm(dev_priv);
 
-	if (INTEL_INFO(dev)->num_pipes == 0)
-		return;
+	if (INTEL_INFO(dev_priv)->num_pipes == 0)
+		return 0;
 
 	/*
 	 * There may be no VBT; and if the BIOS enabled SSC we can
@@ -16389,7 +16447,7 @@ void intel_modeset_init(struct drm_devic
 	 * BIOS isn't using it, don't assume it will work even if the VBT
 	 * indicates as much.
 	 */
-	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+	if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
 		bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) &
 					    DREF_SSC1_ENABLE);
 
@@ -16401,10 +16459,10 @@ void intel_modeset_init(struct drm_devic
 		}
 	}
 
-	if (IS_GEN2(dev)) {
+	if (IS_GEN2(dev_priv)) {
 		dev->mode_config.max_width = 2048;
 		dev->mode_config.max_height = 2048;
-	} else if (IS_GEN3(dev)) {
+	} else if (IS_GEN3(dev_priv)) {
 		dev->mode_config.max_width = 4096;
 		dev->mode_config.max_height = 4096;
 	} else {
@@ -16412,10 +16470,10 @@ void intel_modeset_init(struct drm_devic
 		dev->mode_config.max_height = 8192;
 	}
 
-	if (IS_845G(dev) || IS_I865G(dev)) {
-		dev->mode_config.cursor_width = IS_845G(dev) ? 64 : 512;
+	if (IS_845G(dev_priv) || IS_I865G(dev_priv)) {
+		dev->mode_config.cursor_width = IS_845G(dev_priv) ? 64 : 512;
 		dev->mode_config.cursor_height = 1023;
-	} else if (IS_GEN2(dev)) {
+	} else if (IS_GEN2(dev_priv)) {
 		dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH;
 		dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT;
 	} else {
@@ -16426,29 +16484,30 @@ void intel_modeset_init(struct drm_devic
 	dev->mode_config.fb_base = ggtt->mappable_base;
 
 	DRM_DEBUG_KMS("%d display pipe%s available.\n",
-		      INTEL_INFO(dev)->num_pipes,
-		      INTEL_INFO(dev)->num_pipes > 1 ? "s" : "");
+		      INTEL_INFO(dev_priv)->num_pipes,
+		      INTEL_INFO(dev_priv)->num_pipes > 1 ? "s" : "");
 
 	for_each_pipe(dev_priv, pipe) {
-		intel_crtc_init(dev, pipe);
-		for_each_sprite(dev_priv, pipe, sprite) {
-			ret = intel_plane_init(dev, pipe, sprite);
-			if (ret)
-				DRM_DEBUG_KMS("pipe %c sprite %c init failed: %d\n",
-					      pipe_name(pipe), sprite_name(pipe, sprite), ret);
+		int ret;
+
+		ret = intel_crtc_init(dev_priv, pipe);
+		if (ret) {
+			drm_mode_config_cleanup(dev);
+			return ret;
 		}
 	}
 
 	intel_update_czclk(dev_priv);
-	intel_update_cdclk(dev);
+	intel_update_cdclk(dev_priv);
+	dev_priv->atomic_cdclk_freq = dev_priv->cdclk_freq;
 
 	intel_shared_dpll_init(dev);
 
 	if (dev_priv->max_cdclk_freq == 0)
-		intel_update_max_cdclk(dev);
+		intel_update_max_cdclk(dev_priv);
 
 	/* Just disable it once at startup */
-	i915_disable_vga(dev);
+	i915_disable_vga(dev_priv);
 	intel_setup_outputs(dev);
 
 	drm_modeset_lock_all(dev);
@@ -16484,6 +16543,8 @@ void intel_modeset_init(struct drm_devic
 	 * since the watermark calculation done here will use pstate->fb.
 	 */
 	sanitize_watermarks(dev);
+
+	return 0;
 }
 
 static void intel_enable_pipe_a(struct drm_device *dev)
@@ -16513,11 +16574,10 @@ static void intel_enable_pipe_a(struct d
 static bool
 intel_check_plane_mapping(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	u32 val;
 
-	if (INTEL_INFO(dev)->num_pipes == 1)
+	if (INTEL_INFO(dev_priv)->num_pipes == 1)
 		return true;
 
 	val = I915_READ(DSPCNTR(!crtc->plane));
@@ -16591,7 +16651,7 @@ static void intel_sanitize_crtc(struct i
 	/* We need to sanitize the plane -> pipe mapping first because this will
 	 * disable the crtc (and hence change the state) if it is wrong. Note
 	 * that gen4+ has a fixed plane -> pipe mapping.  */
-	if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
+	if (INTEL_GEN(dev_priv) < 4 && !intel_check_plane_mapping(crtc)) {
 		bool plane;
 
 		DRM_DEBUG_KMS("[CRTC:%d:%s] wrong plane connection detected!\n",
@@ -16621,7 +16681,7 @@ static void intel_sanitize_crtc(struct i
 	if (crtc->active && !intel_crtc_has_encoders(crtc))
 		intel_crtc_disable_noatomic(&crtc->base);
 
-	if (crtc->active || HAS_GMCH_DISPLAY(dev)) {
+	if (crtc->active || HAS_GMCH_DISPLAY(dev_priv)) {
 		/*
 		 * We start out with underrun reporting disabled to avoid races.
 		 * For correct bookkeeping mark this on active crtcs.
@@ -16693,21 +16753,18 @@ static void intel_sanitize_encoder(struc
 	 * the crtc fixup. */
 }
 
-void i915_redisable_vga_power_on(struct drm_device *dev)
+void i915_redisable_vga_power_on(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	i915_reg_t vga_reg = i915_vgacntrl_reg(dev);
+	i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv);
 
 	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
 		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
-		i915_disable_vga(dev);
+		i915_disable_vga(dev_priv);
 	}
 }
 
-void i915_redisable_vga(struct drm_device *dev)
+void i915_redisable_vga(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/* This function can be called both from intel_modeset_setup_hw_state or
 	 * at a very early point in our resume sequence, where the power well
 	 * structures are not yet restored. Since this function is at a very
@@ -16718,7 +16775,7 @@ void i915_redisable_vga(struct drm_devic
 	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_VGA))
 		return;
 
-	i915_redisable_vga_power_on(dev);
+	i915_redisable_vga_power_on(dev_priv);
 
 	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
 }
@@ -16757,7 +16814,6 @@ static void intel_modeset_readout_hw_sta
 
 	for_each_intel_crtc(dev, crtc) {
 		struct intel_crtc_state *crtc_state = crtc->config;
-		int pixclk = 0;
 
 		__drm_atomic_helper_crtc_destroy_state(&crtc_state->base);
 		memset(crtc_state, 0, sizeof(*crtc_state));
@@ -16769,28 +16825,14 @@ static void intel_modeset_readout_hw_sta
 		crtc->base.enabled = crtc_state->base.enable;
 		crtc->active = crtc_state->base.active;
 
-		if (crtc_state->base.active) {
+		if (crtc_state->base.active)
 			dev_priv->active_crtcs |= 1 << crtc->pipe;
 
-			if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
-				pixclk = ilk_pipe_pixel_rate(crtc_state);
-			else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-				pixclk = crtc_state->base.adjusted_mode.crtc_clock;
-			else
-				WARN_ON(dev_priv->display.modeset_calc_cdclk);
-
-			/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
-			if (IS_BROADWELL(dev_priv) && crtc_state->ips_enabled)
-				pixclk = DIV_ROUND_UP(pixclk * 100, 95);
-		}
-
-		dev_priv->min_pixclk[crtc->pipe] = pixclk;
-
 		readout_plane_state(crtc);
 
 		DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",
 			      crtc->base.base.id, crtc->base.name,
-			      crtc->active ? "enabled" : "disabled");
+			      enableddisabled(crtc->active));
 	}
 
 	for (i = 0; i < dev_priv->num_shared_dpll; i++) {
@@ -16813,7 +16855,8 @@ static void intel_modeset_readout_hw_sta
 		pipe = 0;
 
 		if (encoder->get_hw_state(encoder, &pipe)) {
-			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+			crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+
 			encoder->base.crtc = &crtc->base;
 			crtc->config->output_types |= 1 << encoder->type;
 			encoder->get_config(encoder, crtc->config);
@@ -16822,9 +16865,8 @@ static void intel_modeset_readout_hw_sta
 		}
 
 		DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n",
-			      encoder->base.base.id,
-			      encoder->base.name,
-			      encoder->base.crtc ? "enabled" : "disabled",
+			      encoder->base.base.id, encoder->base.name,
+			      enableddisabled(encoder->base.crtc),
 			      pipe_name(pipe));
 	}
 
@@ -16853,12 +16895,13 @@ static void intel_modeset_readout_hw_sta
 			connector->base.encoder = NULL;
 		}
 		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] hw state readout: %s\n",
-			      connector->base.base.id,
-			      connector->base.name,
-			      connector->base.encoder ? "enabled" : "disabled");
+			      connector->base.base.id, connector->base.name,
+			      enableddisabled(connector->base.encoder));
 	}
 
 	for_each_intel_crtc(dev, crtc) {
+		int pixclk = 0;
+
 		crtc->base.hwmode = crtc->config->base.adjusted_mode;
 
 		memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
@@ -16886,10 +16929,23 @@ static void intel_modeset_readout_hw_sta
 			 */
 			crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
 
+			if (INTEL_GEN(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
+				pixclk = ilk_pipe_pixel_rate(crtc->config);
+			else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+				pixclk = crtc->config->base.adjusted_mode.crtc_clock;
+			else
+				WARN_ON(dev_priv->display.modeset_calc_cdclk);
+
+			/* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */
+			if (IS_BROADWELL(dev_priv) && crtc->config->ips_enabled)
+				pixclk = DIV_ROUND_UP(pixclk * 100, 95);
+
 			drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
 			update_scanline_offset(crtc);
 		}
 
+		dev_priv->min_pixclk[crtc->pipe] = pixclk;
+
 		intel_pipe_config_sanity_check(dev_priv, crtc->config);
 	}
 }
@@ -16914,7 +16970,8 @@ intel_modeset_setup_hw_state(struct drm_
 	}
 
 	for_each_pipe(dev_priv, pipe) {
-		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+		crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+
 		intel_sanitize_crtc(crtc);
 		intel_dump_pipe_config(crtc, crtc->config,
 				       "[setup_hw_state]");
@@ -16934,11 +16991,11 @@ intel_modeset_setup_hw_state(struct drm_
 		pll->on = false;
 	}
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		vlv_wm_get_hw_state(dev);
-	else if (IS_GEN9(dev))
+	else if (IS_GEN9(dev_priv))
 		skl_wm_get_hw_state(dev);
-	else if (HAS_PCH_SPLIT(dev))
+	else if (HAS_PCH_SPLIT(dev_priv))
 		ilk_wm_get_hw_state(dev);
 
 	for_each_intel_crtc(dev, crtc) {
@@ -16988,50 +17045,21 @@ void intel_display_resume(struct drm_dev
 	drm_modeset_acquire_fini(&ctx);
 	mutex_unlock(&dev->mode_config.mutex);
 
-	if (ret) {
+	if (ret)
 		DRM_ERROR("Restoring old state failed with %i\n", ret);
-		drm_atomic_state_free(state);
-	}
+	if (state)
+		drm_atomic_state_put(state);
 }
 
 void intel_modeset_gem_init(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *c;
-	struct drm_i915_gem_object *obj;
 
 	intel_init_gt_powersave(dev_priv);
 
 	intel_modeset_init_hw(dev);
 
 	intel_setup_overlay(dev_priv);
-
-	/*
-	 * Make sure any fbs we allocated at startup are properly
-	 * pinned & fenced.  When we do the allocation it's too early
-	 * for this.
-	 */
-	for_each_crtc(dev, c) {
-		struct i915_vma *vma;
-
-		obj = intel_fb_obj(c->primary->fb);
-		if (obj == NULL)
-			continue;
-
-		mutex_lock(&dev->struct_mutex);
-		vma = intel_pin_and_fence_fb_obj(c->primary->fb,
-						 c->primary->state->rotation);
-		mutex_unlock(&dev->struct_mutex);
-		if (IS_ERR(vma)) {
-			DRM_ERROR("failed to pin boot fb on pipe %d\n",
-				  to_intel_crtc(c)->pipe);
-			drm_framebuffer_unreference(c->primary->fb);
-			c->primary->fb = NULL;
-			c->primary->crtc = c->primary->state->crtc = NULL;
-			update_state_fb(c->primary);
-			c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
-		}
-	}
 }
 
 int intel_connector_register(struct drm_connector *connector)
@@ -17061,6 +17089,9 @@ void intel_modeset_cleanup(struct drm_de
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
+	flush_work(&dev_priv->atomic_helper.free_work);
+	WARN_ON(!llist_empty(&dev_priv->atomic_helper.free_list));
+
 	intel_disable_gt_powersave(dev_priv);
 
 	/*
@@ -17103,10 +17134,9 @@ void intel_connector_attach_encoder(stru
 /*
  * set vga decode state - true == enable VGA decode
  */
-int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
+int intel_modeset_vga_set_state(struct drm_i915_private *dev_priv, bool state)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	unsigned reg = INTEL_INFO(dev)->gen >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
+	unsigned reg = INTEL_GEN(dev_priv) >= 6 ? SNB_GMCH_CTRL : INTEL_GMCH_CTRL;
 	u16 gmch_ctrl;
 
 	if (pci_read_config_word(dev_priv->bridge_dev, reg, &gmch_ctrl)) {
@@ -17130,6 +17160,8 @@ int intel_modeset_vga_set_state(struct d
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
 struct intel_display_error_state {
 
 	u32 power_well_driver;
@@ -17258,17 +17290,16 @@ intel_display_capture_error_state(struct
 
 void
 intel_display_print_error_state(struct drm_i915_error_state_buf *m,
-				struct drm_device *dev,
+				struct drm_i915_private *dev_priv,
 				struct intel_display_error_state *error)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	int i;
 
 	if (!error)
 		return;
 
-	err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev_priv)->num_pipes);
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		err_printf(m, "PWR_WELL_CTL2: %08x\n",
 			   error->power_well_driver);
 	for_each_pipe(dev_priv, i) {
@@ -17281,13 +17312,13 @@ intel_display_print_error_state(struct d
 		err_printf(m, "Plane [%d]:\n", i);
 		err_printf(m, "  CNTR: %08x\n", error->plane[i].control);
 		err_printf(m, "  STRIDE: %08x\n", error->plane[i].stride);
-		if (INTEL_INFO(dev)->gen <= 3) {
+		if (INTEL_GEN(dev_priv) <= 3) {
 			err_printf(m, "  SIZE: %08x\n", error->plane[i].size);
 			err_printf(m, "  POS: %08x\n", error->plane[i].pos);
 		}
-		if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev))
+		if (INTEL_GEN(dev_priv) <= 7 && !IS_HASWELL(dev_priv))
 			err_printf(m, "  ADDR: %08x\n", error->plane[i].addr);
-		if (INTEL_INFO(dev)->gen >= 4) {
+		if (INTEL_GEN(dev_priv) >= 4) {
 			err_printf(m, "  SURF: %08x\n", error->plane[i].surface);
 			err_printf(m, "  TILEOFF: %08x\n", error->plane[i].tile_offset);
 		}
@@ -17312,3 +17343,5 @@ intel_display_print_error_state(struct d
 		err_printf(m, "  VSYNC: %08x\n", error->transcoder[i].vsync);
 	}
 }
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dp.c	2017-02-12 16:03:20.000000000 -0500
@@ -213,6 +213,81 @@ intel_dp_downstream_max_dotclock(struct
 	return max_dotclk;
 }
 
+static int
+intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
+{
+	if (intel_dp->num_sink_rates) {
+		*sink_rates = intel_dp->sink_rates;
+		return intel_dp->num_sink_rates;
+	}
+
+	*sink_rates = default_rates;
+
+	return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
+}
+
+static int
+intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	int size;
+
+	if (IS_BROXTON(dev_priv)) {
+		*source_rates = bxt_rates;
+		size = ARRAY_SIZE(bxt_rates);
+	} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+		*source_rates = skl_rates;
+		size = ARRAY_SIZE(skl_rates);
+	} else {
+		*source_rates = default_rates;
+		size = ARRAY_SIZE(default_rates);
+	}
+
+	/* This depends on the fact that 5.4 is last value in the array */
+	if (!intel_dp_source_supports_hbr2(intel_dp))
+		size--;
+
+	return size;
+}
+
+static int intersect_rates(const int *source_rates, int source_len,
+			   const int *sink_rates, int sink_len,
+			   int *common_rates)
+{
+	int i = 0, j = 0, k = 0;
+
+	while (i < source_len && j < sink_len) {
+		if (source_rates[i] == sink_rates[j]) {
+			if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES))
+				return k;
+			common_rates[k] = source_rates[i];
+			++k;
+			++i;
+			++j;
+		} else if (source_rates[i] < sink_rates[j]) {
+			++i;
+		} else {
+			++j;
+		}
+	}
+	return k;
+}
+
+static int intel_dp_common_rates(struct intel_dp *intel_dp,
+				 int *common_rates)
+{
+	const int *source_rates, *sink_rates;
+	int source_len, sink_len;
+
+	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+	source_len = intel_dp_source_rates(intel_dp, &source_rates);
+
+	return intersect_rates(source_rates, source_len,
+			       sink_rates, sink_len,
+			       common_rates);
+}
+
 static enum drm_mode_status
 intel_dp_mode_valid(struct drm_connector *connector,
 		    struct drm_display_mode *mode)
@@ -280,7 +355,8 @@ intel_dp_init_panel_power_sequencer(stru
 				    struct intel_dp *intel_dp);
 static void
 intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
-					      struct intel_dp *intel_dp);
+					      struct intel_dp *intel_dp,
+					      bool force_disable_vdd);
 static void
 intel_dp_pps_init(struct drm_device *dev, struct intel_dp *intel_dp);
 
@@ -320,8 +396,7 @@ static void
 vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = intel_dig_port->base.base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
 	enum pipe pipe = intel_dp->pps_pipe;
 	bool pll_enabled, release_cl_override = false;
 	enum dpio_phy phy = DPIO_PHY(pipe);
@@ -344,7 +419,7 @@ vlv_power_sequencer_kick(struct intel_dp
 	DP |= DP_PORT_WIDTH(1);
 	DP |= DP_LINK_TRAIN_PAT_1;
 
-	if (IS_CHERRYVIEW(dev))
+	if (IS_CHERRYVIEW(dev_priv))
 		DP |= DP_PIPE_SELECT_CHV(pipe);
 	else if (pipe == PIPE_B)
 		DP |= DP_PIPEB_SELECT;
@@ -356,10 +431,10 @@ vlv_power_sequencer_kick(struct intel_dp
 	 * So enable temporarily it if it's not already enabled.
 	 */
 	if (!pll_enabled) {
-		release_cl_override = IS_CHERRYVIEW(dev) &&
+		release_cl_override = IS_CHERRYVIEW(dev_priv) &&
 			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
 
-		if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
+		if (vlv_force_pll_on(dev_priv, pipe, IS_CHERRYVIEW(dev_priv) ?
 				     &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) {
 			DRM_ERROR("Failed to force on pll for pipe %c!\n",
 				  pipe_name(pipe));
@@ -383,7 +458,7 @@ vlv_power_sequencer_kick(struct intel_dp
 	POSTING_READ(intel_dp->output_reg);
 
 	if (!pll_enabled) {
-		vlv_force_pll_off(dev, pipe);
+		vlv_force_pll_off(dev_priv, pipe);
 
 		if (release_cl_override)
 			chv_phy_powergate_ch(dev_priv, phy, ch, false);
@@ -442,7 +517,7 @@ vlv_power_sequencer_pipe(struct intel_dp
 
 	/* init power sequencer on this pipe and port */
 	intel_dp_init_panel_power_sequencer(dev, intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true);
 
 	/*
 	 * Even vdd force doesn't work until we've made
@@ -479,7 +554,7 @@ bxt_power_sequencer_idx(struct intel_dp
 	 * Only the HW needs to be reprogrammed, the SW state is fixed and
 	 * has been setup during connector init.
 	 */
-	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
 
 	return 0;
 }
@@ -562,7 +637,7 @@ vlv_initial_power_sequencer_setup(struct
 		      port_name(port), pipe_name(intel_dp->pps_pipe));
 
 	intel_dp_init_panel_power_sequencer(dev, intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
 }
 
 void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
@@ -570,8 +645,8 @@ void intel_power_sequencer_reset(struct
 	struct drm_device *dev = &dev_priv->drm;
 	struct intel_encoder *encoder;
 
-	if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
-		    !IS_BROXTON(dev)))
+	if (WARN_ON(!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
+		    !IS_BROXTON(dev_priv)))
 		return;
 
 	/*
@@ -591,7 +666,7 @@ void intel_power_sequencer_reset(struct
 			continue;
 
 		intel_dp = enc_to_intel_dp(&encoder->base);
-		if (IS_BROXTON(dev))
+		if (IS_BROXTON(dev_priv))
 			intel_dp->pps_reset = true;
 		else
 			intel_dp->pps_pipe = INVALID_PIPE;
@@ -664,7 +739,7 @@ static int edp_notify_handler(struct not
 
 	pps_lock(intel_dp);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
 		i915_reg_t pp_ctrl_reg, pp_div_reg;
 		u32 pp_div;
@@ -692,7 +767,7 @@ static bool edp_have_panel_power(struct
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 	    intel_dp->pps_pipe == INVALID_PIPE)
 		return false;
 
@@ -706,7 +781,7 @@ static bool edp_have_panel_vdd(struct in
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 	    intel_dp->pps_pipe == INVALID_PIPE)
 		return false;
 
@@ -821,15 +896,16 @@ static uint32_t g4x_get_aux_send_ctl(str
 				     uint32_t aux_clock_divider)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv =
+			to_i915(intel_dig_port->base.base.dev);
 	uint32_t precharge, timeout;
 
-	if (IS_GEN6(dev))
+	if (IS_GEN6(dev_priv))
 		precharge = 3;
 	else
 		precharge = 5;
 
-	if (IS_BROADWELL(dev) && intel_dig_port->port == PORT_A)
+	if (IS_BROADWELL(dev_priv) && intel_dig_port->port == PORT_A)
 		timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
 	else
 		timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
@@ -867,14 +943,14 @@ intel_dp_aux_ch(struct intel_dp *intel_d
 		uint8_t *recv, int recv_size)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = intel_dig_port->base.base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv =
+			to_i915(intel_dig_port->base.base.dev);
 	i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg;
 	uint32_t aux_clock_divider;
 	int i, ret, recv_bytes;
 	uint32_t status;
 	int try, clock = 0;
-	bool has_aux_irq = HAS_AUX_IRQ(dev);
+	bool has_aux_irq = HAS_AUX_IRQ(dev_priv);
 	bool vdd;
 
 	pps_lock(intel_dp);
@@ -1147,7 +1223,7 @@ static enum port intel_aux_port(struct d
 }
 
 static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv,
-				       enum port port)
+				  enum port port)
 {
 	switch (port) {
 	case PORT_B:
@@ -1161,7 +1237,7 @@ static i915_reg_t g4x_aux_ctl_reg(struct
 }
 
 static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv,
-					enum port port, int index)
+				   enum port port, int index)
 {
 	switch (port) {
 	case PORT_B:
@@ -1175,7 +1251,7 @@ static i915_reg_t g4x_aux_data_reg(struc
 }
 
 static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv,
-				       enum port port)
+				  enum port port)
 {
 	switch (port) {
 	case PORT_A:
@@ -1191,7 +1267,7 @@ static i915_reg_t ilk_aux_ctl_reg(struct
 }
 
 static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv,
-					enum port port, int index)
+				   enum port port, int index)
 {
 	switch (port) {
 	case PORT_A:
@@ -1207,7 +1283,7 @@ static i915_reg_t ilk_aux_data_reg(struc
 }
 
 static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,
-				       enum port port)
+				  enum port port)
 {
 	switch (port) {
 	case PORT_A:
@@ -1222,7 +1298,7 @@ static i915_reg_t skl_aux_ctl_reg(struct
 }
 
 static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv,
-					enum port port, int index)
+				   enum port port, int index)
 {
 	switch (port) {
 	case PORT_A:
@@ -1237,7 +1313,7 @@ static i915_reg_t skl_aux_data_reg(struc
 }
 
 static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv,
-					 enum port port)
+				    enum port port)
 {
 	if (INTEL_INFO(dev_priv)->gen >= 9)
 		return skl_aux_ctl_reg(dev_priv, port);
@@ -1248,7 +1324,7 @@ static i915_reg_t intel_aux_ctl_reg(stru
 }
 
 static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv,
-					  enum port port, int index)
+				     enum port port, int index)
 {
 	if (INTEL_INFO(dev_priv)->gen >= 9)
 		return skl_aux_data_reg(dev_priv, port, index);
@@ -1290,78 +1366,37 @@ intel_dp_aux_init(struct intel_dp *intel
 	intel_dp->aux.transfer = intel_dp_aux_transfer;
 }
 
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
-	if (intel_dp->num_sink_rates) {
-		*sink_rates = intel_dp->sink_rates;
-		return intel_dp->num_sink_rates;
-	}
-
-	*sink_rates = default_rates;
-
-	return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
-}
-
 bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = dig_port->base.base.dev;
-
-	/* WaDisableHBR2:skl */
-	if (IS_SKL_REVID(dev, 0, SKL_REVID_B0))
-		return false;
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 
-	if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) ||
-	    (INTEL_INFO(dev)->gen >= 9))
+	if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) ||
+	    IS_BROADWELL(dev_priv) || (INTEL_GEN(dev_priv) >= 9))
 		return true;
 	else
 		return false;
 }
 
-static int
-intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = dig_port->base.base.dev;
-	int size;
-
-	if (IS_BROXTON(dev)) {
-		*source_rates = bxt_rates;
-		size = ARRAY_SIZE(bxt_rates);
-	} else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
-		*source_rates = skl_rates;
-		size = ARRAY_SIZE(skl_rates);
-	} else {
-		*source_rates = default_rates;
-		size = ARRAY_SIZE(default_rates);
-	}
-
-	/* This depends on the fact that 5.4 is last value in the array */
-	if (!intel_dp_source_supports_hbr2(intel_dp))
-		size--;
-
-	return size;
-}
-
 static void
 intel_dp_set_clock(struct intel_encoder *encoder,
 		   struct intel_crtc_state *pipe_config)
 {
 	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	const struct dp_link_dpll *divisor = NULL;
 	int i, count = 0;
 
-	if (IS_G4X(dev)) {
+	if (IS_G4X(dev_priv)) {
 		divisor = gen4_dpll;
 		count = ARRAY_SIZE(gen4_dpll);
-	} else if (HAS_PCH_SPLIT(dev)) {
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
 		divisor = pch_dpll;
 		count = ARRAY_SIZE(pch_dpll);
-	} else if (IS_CHERRYVIEW(dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		divisor = chv_dpll;
 		count = ARRAY_SIZE(chv_dpll);
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		divisor = vlv_dpll;
 		count = ARRAY_SIZE(vlv_dpll);
 	}
@@ -1377,43 +1412,6 @@ intel_dp_set_clock(struct intel_encoder
 	}
 }
 
-static int intersect_rates(const int *source_rates, int source_len,
-			   const int *sink_rates, int sink_len,
-			   int *common_rates)
-{
-	int i = 0, j = 0, k = 0;
-
-	while (i < source_len && j < sink_len) {
-		if (source_rates[i] == sink_rates[j]) {
-			if (WARN_ON(k >= DP_MAX_SUPPORTED_RATES))
-				return k;
-			common_rates[k] = source_rates[i];
-			++k;
-			++i;
-			++j;
-		} else if (source_rates[i] < sink_rates[j]) {
-			++i;
-		} else {
-			++j;
-		}
-	}
-	return k;
-}
-
-static int intel_dp_common_rates(struct intel_dp *intel_dp,
-				 int *common_rates)
-{
-	const int *source_rates, *sink_rates;
-	int source_len, sink_len;
-
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	source_len = intel_dp_source_rates(intel_dp, &source_rates);
-
-	return intersect_rates(source_rates, source_len,
-			       sink_rates, sink_len,
-			       common_rates);
-}
-
 static void snprintf_int_array(char *str, size_t len,
 			       const int *array, int nelem)
 {
@@ -1453,42 +1451,35 @@ static void intel_dp_print_rates(struct
 	DRM_DEBUG_KMS("common rates: %s\n", str);
 }
 
-static void intel_dp_print_hw_revision(struct intel_dp *intel_dp)
+bool
+__intel_dp_read_desc(struct intel_dp *intel_dp, struct intel_dp_desc *desc)
 {
-	uint8_t rev;
-	int len;
-
-	if ((drm_debug & DRM_UT_KMS) == 0)
-		return;
-
-	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-	      DP_DWN_STRM_PORT_PRESENT))
-		return;
-
-	len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_HW_REV, &rev, 1);
-	if (len < 0)
-		return;
+	u32 base = drm_dp_is_branch(intel_dp->dpcd) ? DP_BRANCH_OUI :
+						      DP_SINK_OUI;
 
-	DRM_DEBUG_KMS("sink hw revision: %d.%d\n", (rev & 0xf0) >> 4, rev & 0xf);
+	return drm_dp_dpcd_read(&intel_dp->aux, base, desc, sizeof(*desc)) ==
+	       sizeof(*desc);
 }
 
-static void intel_dp_print_sw_revision(struct intel_dp *intel_dp)
+bool intel_dp_read_desc(struct intel_dp *intel_dp)
 {
-	uint8_t rev[2];
-	int len;
-
-	if ((drm_debug & DRM_UT_KMS) == 0)
-		return;
+	struct intel_dp_desc *desc = &intel_dp->desc;
+	bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] &
+		       DP_OUI_SUPPORT;
+	int dev_id_len;
 
-	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-	      DP_DWN_STRM_PORT_PRESENT))
-		return;
+	if (!__intel_dp_read_desc(intel_dp, desc))
+		return false;
 
-	len = drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_SW_REV, &rev, 2);
-	if (len < 0)
-		return;
+	dev_id_len = strnlen(desc->device_id, sizeof(desc->device_id));
+	DRM_DEBUG_KMS("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n",
+		      drm_dp_is_branch(intel_dp->dpcd) ? "branch" : "sink",
+		      (int)sizeof(desc->oui), desc->oui, oui_sup ? "" : "(NS)",
+		      dev_id_len, desc->device_id,
+		      desc->hw_rev >> 4, desc->hw_rev & 0xf,
+		      desc->sw_major_rev, desc->sw_minor_rev);
 
-	DRM_DEBUG_KMS("sink sw revision: %d.%d\n", rev[0], rev[1]);
+	return true;
 }
 
 static int rate_to_index(int find, const int *rates)
@@ -1552,8 +1543,7 @@ intel_dp_compute_config(struct intel_enc
 			struct intel_crtc_state *pipe_config,
 			struct drm_connector_state *conn_state)
 {
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	enum port port = dp_to_dig_port(intel_dp)->port;
@@ -1578,7 +1568,7 @@ intel_dp_compute_config(struct intel_enc
 
 	max_clock = common_len - 1;
 
-	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A)
+	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)
 		pipe_config->has_pch_encoder = true;
 
 	pipe_config->has_drrs = false;
@@ -1588,14 +1578,14 @@ intel_dp_compute_config(struct intel_enc
 		intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
 				       adjusted_mode);
 
-		if (INTEL_INFO(dev)->gen >= 9) {
+		if (INTEL_GEN(dev_priv) >= 9) {
 			int ret;
 			ret = skl_update_scaler_crtc(pipe_config);
 			if (ret)
 				return ret;
 		}
 
-		if (HAS_GMCH_DISPLAY(dev))
+		if (HAS_GMCH_DISPLAY(dev_priv))
 			intel_gmch_panel_fitting(intel_crtc, pipe_config,
 						 intel_connector->panel.fitting_mode);
 		else
@@ -1720,7 +1710,7 @@ found:
 		to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco;
 	}
 
-	if (!HAS_DDI(dev))
+	if (!HAS_DDI(dev_priv))
 		intel_dp_set_clock(encoder, pipe_config);
 
 	return true;
@@ -1778,7 +1768,7 @@ static void intel_dp_prepare(struct inte
 
 	/* Split out the IBX/CPU vs CPT settings */
 
-	if (IS_GEN7(dev) && port == PORT_A) {
+	if (IS_GEN7(dev_priv) && port == PORT_A) {
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
 			intel_dp->DP |= DP_SYNC_HS_HIGH;
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -1789,7 +1779,7 @@ static void intel_dp_prepare(struct inte
 			intel_dp->DP |= DP_ENHANCED_FRAMING;
 
 		intel_dp->DP |= crtc->pipe << 29;
-	} else if (HAS_PCH_CPT(dev) && port != PORT_A) {
+	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
 		u32 trans_dp;
 
 		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
@@ -1801,8 +1791,7 @@ static void intel_dp_prepare(struct inte
 			trans_dp &= ~TRANS_DP_ENH_FRAMING;
 		I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp);
 	} else {
-		if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
-		    !IS_CHERRYVIEW(dev) && pipe_config->limited_color_range)
+		if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
 			intel_dp->DP |= DP_COLOR_RANGE_16_235;
 
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -1814,7 +1803,7 @@ static void intel_dp_prepare(struct inte
 		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
 			intel_dp->DP |= DP_ENHANCED_FRAMING;
 
-		if (IS_CHERRYVIEW(dev))
+		if (IS_CHERRYVIEW(dev_priv))
 			intel_dp->DP |= DP_PIPE_SELECT_CHV(crtc->pipe);
 		else if (crtc->pipe == PIPE_B)
 			intel_dp->DP |= DP_PIPEB_SELECT;
@@ -2123,7 +2112,7 @@ static void edp_panel_on(struct intel_dp
 
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 	pp = ironlake_get_pp_control(intel_dp);
-	if (IS_GEN5(dev)) {
+	if (IS_GEN5(dev_priv)) {
 		/* ILK workaround: disable reset around power sequence */
 		pp &= ~PANEL_POWER_RESET;
 		I915_WRITE(pp_ctrl_reg, pp);
@@ -2131,7 +2120,7 @@ static void edp_panel_on(struct intel_dp
 	}
 
 	pp |= PANEL_POWER_ON;
-	if (!IS_GEN5(dev))
+	if (!IS_GEN5(dev_priv))
 		pp |= PANEL_POWER_RESET;
 
 	I915_WRITE(pp_ctrl_reg, pp);
@@ -2140,7 +2129,7 @@ static void edp_panel_on(struct intel_dp
 	wait_panel_on(intel_dp);
 	intel_dp->last_power_on = jiffies;
 
-	if (IS_GEN5(dev)) {
+	if (IS_GEN5(dev_priv)) {
 		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
 		I915_WRITE(pp_ctrl_reg, pp);
 		POSTING_READ(pp_ctrl_reg);
@@ -2372,7 +2361,7 @@ static void ironlake_edp_pll_on(struct i
 	 * 2. Program DP PLL enable
 	 */
 	if (IS_GEN5(dev_priv))
-		intel_wait_for_vblank_if_active(&dev_priv->drm, !crtc->pipe);
+		intel_wait_for_vblank_if_active(dev_priv, !crtc->pipe);
 
 	intel_dp->DP |= DP_PLL_ENABLE;
 
@@ -2453,9 +2442,9 @@ static bool intel_dp_get_hw_state(struct
 	if (!(tmp & DP_PORT_EN))
 		goto out;
 
-	if (IS_GEN7(dev) && port == PORT_A) {
+	if (IS_GEN7(dev_priv) && port == PORT_A) {
 		*pipe = PORT_TO_PIPE_CPT(tmp);
-	} else if (HAS_PCH_CPT(dev) && port != PORT_A) {
+	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
 		enum pipe p;
 
 		for_each_pipe(dev_priv, p) {
@@ -2470,7 +2459,7 @@ static bool intel_dp_get_hw_state(struct
 
 		DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n",
 			      i915_mmio_reg_offset(intel_dp->output_reg));
-	} else if (IS_CHERRYVIEW(dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		*pipe = DP_PORT_TO_PIPE_CHV(tmp);
 	} else {
 		*pipe = PORT_TO_PIPE(tmp);
@@ -2498,7 +2487,7 @@ static void intel_dp_get_config(struct i
 
 	pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A;
 
-	if (HAS_PCH_CPT(dev) && port != PORT_A) {
+	if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
 		u32 trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe));
 
 		if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH)
@@ -2524,8 +2513,7 @@ static void intel_dp_get_config(struct i
 
 	pipe_config->base.adjusted_mode.flags |= flags;
 
-	if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) &&
-	    !IS_CHERRYVIEW(dev) && tmp & DP_COLOR_RANGE_16_235)
+	if (IS_G4X(dev_priv) && tmp & DP_COLOR_RANGE_16_235)
 		pipe_config->limited_color_range = true;
 
 	pipe_config->lane_count =
@@ -2645,7 +2633,7 @@ _intel_dp_set_link_train(struct intel_dp
 		DRM_DEBUG_KMS("Using DP training pattern TPS%d\n",
 			      dp_train_pat & DP_TRAINING_PATTERN_MASK);
 
-	if (HAS_DDI(dev)) {
+	if (HAS_DDI(dev_priv)) {
 		uint32_t temp = I915_READ(DP_TP_CTL(port));
 
 		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
@@ -2671,8 +2659,8 @@ _intel_dp_set_link_train(struct intel_dp
 		}
 		I915_WRITE(DP_TP_CTL(port), temp);
 
-	} else if ((IS_GEN7(dev) && port == PORT_A) ||
-		   (HAS_PCH_CPT(dev) && port != PORT_A)) {
+	} else if ((IS_GEN7(dev_priv) && port == PORT_A) ||
+		   (HAS_PCH_CPT(dev_priv) && port != PORT_A)) {
 		*DP &= ~DP_LINK_TRAIN_MASK_CPT;
 
 		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
@@ -2692,7 +2680,7 @@ _intel_dp_set_link_train(struct intel_dp
 		}
 
 	} else {
-		if (IS_CHERRYVIEW(dev))
+		if (IS_CHERRYVIEW(dev_priv))
 			*DP &= ~DP_LINK_TRAIN_MASK_CHV;
 		else
 			*DP &= ~DP_LINK_TRAIN_MASK;
@@ -2708,7 +2696,7 @@ _intel_dp_set_link_train(struct intel_dp
 			*DP |= DP_LINK_TRAIN_PAT_2;
 			break;
 		case DP_TRAINING_PATTERN_3:
-			if (IS_CHERRYVIEW(dev)) {
+			if (IS_CHERRYVIEW(dev_priv)) {
 				*DP |= DP_LINK_TRAIN_PAT_3_CHV;
 			} else {
 				DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n");
@@ -2744,7 +2732,8 @@ static void intel_dp_enable_port(struct
 }
 
 static void intel_enable_dp(struct intel_encoder *encoder,
-			    struct intel_crtc_state *pipe_config)
+			    struct intel_crtc_state *pipe_config,
+			    struct drm_connector_state *conn_state)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	struct drm_device *dev = encoder->base.dev;
@@ -2758,7 +2747,7 @@ static void intel_enable_dp(struct intel
 
 	pps_lock(intel_dp);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		vlv_init_panel_power_sequencer(intel_dp);
 
 	intel_dp_enable_port(intel_dp, pipe_config);
@@ -2769,10 +2758,10 @@ static void intel_enable_dp(struct intel
 
 	pps_unlock(intel_dp);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		unsigned int lane_mask = 0x0;
 
-		if (IS_CHERRYVIEW(dev))
+		if (IS_CHERRYVIEW(dev_priv))
 			lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count);
 
 		vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp),
@@ -2786,7 +2775,7 @@ static void intel_enable_dp(struct intel
 	if (pipe_config->has_audio) {
 		DRM_DEBUG_DRIVER("Enabling DP audio on pipe %c\n",
 				 pipe_name(pipe));
-		intel_audio_codec_enable(encoder);
+		intel_audio_codec_enable(encoder, pipe_config, conn_state);
 	}
 }
 
@@ -2796,7 +2785,7 @@ static void g4x_enable_dp(struct intel_e
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 
-	intel_enable_dp(encoder, pipe_config);
+	intel_enable_dp(encoder, pipe_config, conn_state);
 	intel_edp_backlight_on(intel_dp);
 }
 
@@ -2924,7 +2913,7 @@ static void vlv_init_panel_power_sequenc
 
 	/* init power sequencer on this pipe and port */
 	intel_dp_init_panel_power_sequencer(dev, intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, true);
 }
 
 static void vlv_pre_enable_dp(struct intel_encoder *encoder,
@@ -2933,7 +2922,7 @@ static void vlv_pre_enable_dp(struct int
 {
 	vlv_phy_pre_encoder_enable(encoder);
 
-	intel_enable_dp(encoder, pipe_config);
+	intel_enable_dp(encoder, pipe_config, conn_state);
 }
 
 static void vlv_dp_pre_pll_enable(struct intel_encoder *encoder,
@@ -2951,7 +2940,7 @@ static void chv_pre_enable_dp(struct int
 {
 	chv_phy_pre_encoder_enable(encoder);
 
-	intel_enable_dp(encoder, pipe_config);
+	intel_enable_dp(encoder, pipe_config, conn_state);
 
 	/* Second common lane will stay alive on its own now */
 	chv_phy_release_cl2_override(encoder);
@@ -2988,21 +2977,20 @@ intel_dp_get_link_status(struct intel_dp
 uint8_t
 intel_dp_voltage_max(struct intel_dp *intel_dp)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
-	if (IS_BROXTON(dev))
+	if (IS_BROXTON(dev_priv))
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
-	else if (INTEL_INFO(dev)->gen >= 9) {
+	else if (INTEL_GEN(dev_priv) >= 9) {
 		if (dev_priv->vbt.edp.low_vswing && port == PORT_A)
 			return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
-	else if (IS_GEN7(dev) && port == PORT_A)
+	else if (IS_GEN7(dev_priv) && port == PORT_A)
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
-	else if (HAS_PCH_CPT(dev) && port != PORT_A)
+	else if (HAS_PCH_CPT(dev_priv) && port != PORT_A)
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
 	else
 		return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
@@ -3011,10 +2999,10 @@ intel_dp_voltage_max(struct intel_dp *in
 uint8_t
 intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
 {
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp));
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
 			return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -3027,7 +3015,7 @@ intel_dp_pre_emphasis_max(struct intel_d
 		default:
 			return DP_TRAIN_PRE_EMPH_LEVEL_0;
 		}
-	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
 			return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -3039,7 +3027,7 @@ intel_dp_pre_emphasis_max(struct intel_d
 		default:
 			return DP_TRAIN_PRE_EMPH_LEVEL_0;
 		}
-	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
 			return DP_TRAIN_PRE_EMPH_LEVEL_3;
@@ -3051,7 +3039,7 @@ intel_dp_pre_emphasis_max(struct intel_d
 		default:
 			return DP_TRAIN_PRE_EMPH_LEVEL_0;
 		}
-	} else if (IS_GEN7(dev) && port == PORT_A) {
+	} else if (IS_GEN7(dev_priv) && port == PORT_A) {
 		switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) {
 		case DP_TRAIN_VOLTAGE_SWING_LEVEL_0:
 			return DP_TRAIN_PRE_EMPH_LEVEL_2;
@@ -3352,21 +3340,21 @@ intel_dp_set_signal_levels(struct intel_
 	uint32_t signal_levels, mask = 0;
 	uint8_t train_set = intel_dp->train_set[0];
 
-	if (HAS_DDI(dev)) {
+	if (HAS_DDI(dev_priv)) {
 		signal_levels = ddi_signal_levels(intel_dp);
 
-		if (IS_BROXTON(dev))
+		if (IS_BROXTON(dev_priv))
 			signal_levels = 0;
 		else
 			mask = DDI_BUF_EMP_MASK;
-	} else if (IS_CHERRYVIEW(dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		signal_levels = chv_signal_levels(intel_dp);
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		signal_levels = vlv_signal_levels(intel_dp);
-	} else if (IS_GEN7(dev) && port == PORT_A) {
+	} else if (IS_GEN7(dev_priv) && port == PORT_A) {
 		signal_levels = gen7_edp_signal_levels(train_set);
 		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
-	} else if (IS_GEN6(dev) && port == PORT_A) {
+	} else if (IS_GEN6(dev_priv) && port == PORT_A) {
 		signal_levels = gen6_edp_signal_levels(train_set);
 		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;
 	} else {
@@ -3411,7 +3399,7 @@ void intel_dp_set_idle_link_train(struct
 	enum port port = intel_dig_port->port;
 	uint32_t val;
 
-	if (!HAS_DDI(dev))
+	if (!HAS_DDI(dev_priv))
 		return;
 
 	val = I915_READ(DP_TP_CTL(port));
@@ -3446,7 +3434,7 @@ intel_dp_link_down(struct intel_dp *inte
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t DP = intel_dp->DP;
 
-	if (WARN_ON(HAS_DDI(dev)))
+	if (WARN_ON(HAS_DDI(dev_priv)))
 		return;
 
 	if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0))
@@ -3454,12 +3442,12 @@ intel_dp_link_down(struct intel_dp *inte
 
 	DRM_DEBUG_KMS("\n");
 
-	if ((IS_GEN7(dev) && port == PORT_A) ||
-	    (HAS_PCH_CPT(dev) && port != PORT_A)) {
+	if ((IS_GEN7(dev_priv) && port == PORT_A) ||
+	    (HAS_PCH_CPT(dev_priv) && port != PORT_A)) {
 		DP &= ~DP_LINK_TRAIN_MASK_CPT;
 		DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;
 	} else {
-		if (IS_CHERRYVIEW(dev))
+		if (IS_CHERRYVIEW(dev_priv))
 			DP &= ~DP_LINK_TRAIN_MASK_CHV;
 		else
 			DP &= ~DP_LINK_TRAIN_MASK;
@@ -3477,7 +3465,7 @@ intel_dp_link_down(struct intel_dp *inte
 	 * to transcoder A after disabling it to allow the
 	 * matching HDMI port to be enabled on transcoder A.
 	 */
-	if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) {
+	if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B && port != PORT_A) {
 		/*
 		 * We get CPU/PCH FIFO underruns on the other pipe when
 		 * doing the workaround. Sweep them under the rug.
@@ -3495,7 +3483,7 @@ intel_dp_link_down(struct intel_dp *inte
 		I915_WRITE(intel_dp->output_reg, DP);
 		POSTING_READ(intel_dp->output_reg);
 
-		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
+		intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 	}
@@ -3505,7 +3493,7 @@ intel_dp_link_down(struct intel_dp *inte
 	intel_dp->DP = DP;
 }
 
-static bool
+bool
 intel_dp_read_dpcd(struct intel_dp *intel_dp)
 {
 	if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd,
@@ -3529,6 +3517,8 @@ intel_edp_init_dpcd(struct intel_dp *int
 	if (!intel_dp_read_dpcd(intel_dp))
 		return false;
 
+	intel_dp_read_desc(intel_dp);
+
 	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
 		dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
 			DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
@@ -3616,8 +3606,7 @@ intel_dp_get_dpcd(struct intel_dp *intel
 	if (!is_edp(intel_dp) && !intel_dp->sink_count)
 		return false;
 
-	if (!(intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] &
-	      DP_DWN_STRM_PORT_PRESENT))
+	if (!drm_dp_is_branch(intel_dp->dpcd))
 		return true; /* native DP sink */
 
 	if (intel_dp->dpcd[DP_DPCD_REV] == 0x10)
@@ -3631,23 +3620,6 @@ intel_dp_get_dpcd(struct intel_dp *intel
 	return true;
 }
 
-static void
-intel_dp_probe_oui(struct intel_dp *intel_dp)
-{
-	u8 buf[3];
-
-	if (!(intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
-		return;
-
-	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_OUI, buf, 3) == 3)
-		DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
-			      buf[0], buf[1], buf[2]);
-
-	if (drm_dp_dpcd_read(&intel_dp->aux, DP_BRANCH_OUI, buf, 3) == 3)
-		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
-			      buf[0], buf[1], buf[2]);
-}
-
 static bool
 intel_dp_can_mst(struct intel_dp *intel_dp)
 {
@@ -3691,7 +3663,7 @@ intel_dp_configure_mst(struct intel_dp *
 static int intel_dp_sink_crc_stop(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
 	u8 buf;
 	int ret = 0;
@@ -3712,7 +3684,7 @@ static int intel_dp_sink_crc_stop(struct
 	}
 
 	do {
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
+		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
 
 		if (drm_dp_dpcd_readb(&intel_dp->aux,
 				      DP_TEST_SINK_MISC, &buf) < 0) {
@@ -3735,7 +3707,7 @@ static int intel_dp_sink_crc_stop(struct
 static int intel_dp_sink_crc_start(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
 	u8 buf;
 	int ret;
@@ -3763,14 +3735,14 @@ static int intel_dp_sink_crc_start(struc
 		return -EIO;
 	}
 
-	intel_wait_for_vblank(dev, intel_crtc->pipe);
+	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
 	return 0;
 }
 
 int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(dig_port->base.base.crtc);
 	u8 buf;
 	int count, ret;
@@ -3781,7 +3753,7 @@ int intel_dp_sink_crc(struct intel_dp *i
 		return ret;
 
 	do {
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
+		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
 
 		if (drm_dp_dpcd_readb(&intel_dp->aux,
 				      DP_TEST_SINK_MISC, &buf) < 0) {
@@ -3998,6 +3970,31 @@ go_again:
 }
 
 static void
+intel_dp_retrain_link(struct intel_dp *intel_dp)
+{
+	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+
+	/* Suppress underruns caused by re-training */
+	intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false);
+	if (crtc->config->has_pch_encoder)
+		intel_set_pch_fifo_underrun_reporting(dev_priv,
+						      intel_crtc_pch_transcoder(crtc), false);
+
+	intel_dp_start_link_train(intel_dp);
+	intel_dp_stop_link_train(intel_dp);
+
+	/* Keep underrun reporting disabled until things are stable */
+	intel_wait_for_vblank(dev_priv, crtc->pipe);
+
+	intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true);
+	if (crtc->config->has_pch_encoder)
+		intel_set_pch_fifo_underrun_reporting(dev_priv,
+						      intel_crtc_pch_transcoder(crtc), true);
+}
+
+static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
 	struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
@@ -4017,13 +4014,18 @@ intel_dp_check_link_status(struct intel_
 	if (!to_intel_crtc(intel_encoder->base.crtc)->active)
 		return;
 
+	/* FIXME: we need to synchronize this sort of stuff with hardware
+	 * readout. Currently fast link training doesn't work on boot-up. */
+	if (!intel_dp->lane_count)
+		return;
+
 	/* if link training is requested we should perform it always */
 	if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
 	    (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
 		DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
 			      intel_encoder->base.name);
-		intel_dp_start_link_train(intel_dp);
-		intel_dp_stop_link_train(intel_dp);
+
+		intel_dp_retrain_link(intel_dp);
 	}
 }
 
@@ -4105,7 +4107,7 @@ intel_dp_detect_dpcd(struct intel_dp *in
 		return connector_status_connected;
 
 	/* if there's no downstream port, we're done */
-	if (!(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT))
+	if (!drm_dp_is_branch(dpcd))
 		return connector_status_connected;
 
 	/* If we're HPD-aware, SINK_COUNT changes dynamically */
@@ -4396,10 +4398,7 @@ intel_dp_long_pulse(struct intel_connect
 
 	intel_dp_print_rates(intel_dp);
 
-	intel_dp_probe_oui(intel_dp);
-
-	intel_dp_print_hw_revision(intel_dp);
-	intel_dp_print_sw_revision(intel_dp);
+	intel_dp_read_desc(intel_dp);
 
 	intel_dp_configure_mst(intel_dp);
 
@@ -4755,11 +4754,16 @@ static void intel_edp_panel_vdd_sanitize
 void intel_dp_encoder_reset(struct drm_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+	struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
 
 	if (!HAS_DDI(dev_priv))
 		intel_dp->DP = I915_READ(intel_dp->output_reg);
 
+	if (IS_GEN9(dev_priv) && lspcon->active)
+		lspcon_resume(lspcon);
+
 	if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
 		return;
 
@@ -4866,15 +4870,13 @@ put_power:
 }
 
 /* check the VBT to see whether the eDP is on another port */
-bool intel_dp_is_edp(struct drm_device *dev, enum port port)
+bool intel_dp_is_edp(struct drm_i915_private *dev_priv, enum port port)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/*
 	 * eDP not supported on g4x. so bail out early just
 	 * for a bit extra safety in case the VBT is bonkers.
 	 */
-	if (INTEL_INFO(dev)->gen < 5)
+	if (INTEL_GEN(dev_priv) < 5)
 		return false;
 
 	if (port == PORT_A)
@@ -5054,7 +5056,8 @@ intel_dp_init_panel_power_sequencer(stru
 
 static void
 intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
-					      struct intel_dp *intel_dp)
+					      struct intel_dp *intel_dp,
+					      bool force_disable_vdd)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 pp_on, pp_off, pp_div, port_sel = 0;
@@ -5067,13 +5070,38 @@ intel_dp_init_panel_power_sequencer_regi
 
 	intel_pps_get_registers(dev_priv, intel_dp, &regs);
 
+	/*
+	 * On some VLV machines the BIOS can leave the VDD
+	 * enabled even on power seqeuencers which aren't
+	 * hooked up to any port. This would mess up the
+	 * power domain tracking the first time we pick
+	 * one of these power sequencers for use since
+	 * edp_panel_vdd_on() would notice that the VDD was
+	 * already on and therefore wouldn't grab the power
+	 * domain reference. Disable VDD first to avoid this.
+	 * This also avoids spuriously turning the VDD on as
+	 * soon as the new power seqeuencer gets initialized.
+	 */
+	if (force_disable_vdd) {
+		u32 pp = ironlake_get_pp_control(intel_dp);
+
+		WARN(pp & PANEL_POWER_ON, "Panel power already on\n");
+
+		if (pp & EDP_FORCE_VDD)
+			DRM_DEBUG_KMS("VDD already on, disabling first\n");
+
+		pp &= ~EDP_FORCE_VDD;
+
+		I915_WRITE(regs.pp_ctrl, pp);
+	}
+
 	pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
 		(seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
 	pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
 		 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
 	/* Compute the divisor for the pp clock, simply match the Bspec
 	 * formula. */
-	if (IS_BROXTON(dev)) {
+	if (IS_BROXTON(dev_priv)) {
 		pp_div = I915_READ(regs.pp_ctrl);
 		pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK;
 		pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000)
@@ -5086,9 +5114,9 @@ intel_dp_init_panel_power_sequencer_regi
 
 	/* Haswell doesn't have any port selection bits for the panel
 	 * power sequencer any more. */
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		port_sel = PANEL_PORT_SELECT_VLV(port);
-	} else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
+	} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
 		if (port == PORT_A)
 			port_sel = PANEL_PORT_SELECT_DPA;
 		else
@@ -5099,7 +5127,7 @@ intel_dp_init_panel_power_sequencer_regi
 
 	I915_WRITE(regs.pp_on, pp_on);
 	I915_WRITE(regs.pp_off, pp_off);
-	if (IS_BROXTON(dev))
+	if (IS_BROXTON(dev_priv))
 		I915_WRITE(regs.pp_ctrl, pp_div);
 	else
 		I915_WRITE(regs.pp_div, pp_div);
@@ -5107,7 +5135,7 @@ intel_dp_init_panel_power_sequencer_regi
 	DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
 		      I915_READ(regs.pp_on),
 		      I915_READ(regs.pp_off),
-		      IS_BROXTON(dev) ?
+		      IS_BROXTON(dev_priv) ?
 		      (I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK) :
 		      I915_READ(regs.pp_div));
 }
@@ -5115,11 +5143,13 @@ intel_dp_init_panel_power_sequencer_regi
 static void intel_dp_pps_init(struct drm_device *dev,
 			      struct intel_dp *intel_dp)
 {
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		vlv_initial_power_sequencer_setup(intel_dp);
 	} else {
 		intel_dp_init_panel_power_sequencer(dev, intel_dp);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp);
+		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, false);
 	}
 }
 
@@ -5474,7 +5504,7 @@ intel_dp_drrs_init(struct intel_connecto
 	INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
 	mutex_init(&dev_priv->drrs.mutex);
 
-	if (INTEL_INFO(dev)->gen <= 6) {
+	if (INTEL_GEN(dev_priv) <= 6) {
 		DRM_DEBUG_KMS("DRRS supported for Gen7 and above\n");
 		return NULL;
 	}
@@ -5585,7 +5615,7 @@ static bool intel_edp_init_connector(str
 	}
 	mutex_unlock(&dev->mode_config.mutex);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		intel_dp->edp_notifier.notifier_call = edp_notify_handler;
 		register_reboot_notifier(&intel_dp->edp_notifier);
 
@@ -5594,7 +5624,7 @@ static bool intel_edp_init_connector(str
 		 * If the current pipe isn't valid, try the PPS pipe, and if that
 		 * fails just assume pipe A.
 		 */
-		if (IS_CHERRYVIEW(dev))
+		if (IS_CHERRYVIEW(dev_priv))
 			pipe = DP_PORT_TO_PIPE_CHV(intel_dp->DP);
 		else
 			pipe = PORT_TO_PIPE(intel_dp->DP);
@@ -5648,28 +5678,28 @@ intel_dp_init_connector(struct intel_dig
 	intel_dp->pps_pipe = INVALID_PIPE;
 
 	/* intel_dp vfuncs */
-	if (INTEL_INFO(dev)->gen >= 9)
+	if (INTEL_GEN(dev_priv) >= 9)
 		intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
-	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
-	else if (HAS_PCH_SPLIT(dev))
+	else if (HAS_PCH_SPLIT(dev_priv))
 		intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
 	else
 		intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
 
-	if (INTEL_INFO(dev)->gen >= 9)
+	if (INTEL_GEN(dev_priv) >= 9)
 		intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
 	else
 		intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
 
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev_priv))
 		intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
 
 	/* Preserve the current hw state. */
 	intel_dp->DP = I915_READ(intel_dp->output_reg);
 	intel_dp->attached_connector = intel_connector;
 
-	if (intel_dp_is_edp(dev, port))
+	if (intel_dp_is_edp(dev_priv, port))
 		type = DRM_MODE_CONNECTOR_eDP;
 	else
 		type = DRM_MODE_CONNECTOR_DisplayPort;
@@ -5683,7 +5713,7 @@ intel_dp_init_connector(struct intel_dig
 		intel_encoder->type = INTEL_OUTPUT_EDP;
 
 	/* eDP only on port B and/or C on vlv/chv */
-	if (WARN_ON((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	if (WARN_ON((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 		    is_edp(intel_dp) && port != PORT_B && port != PORT_C))
 		return false;
 
@@ -5704,7 +5734,7 @@ intel_dp_init_connector(struct intel_dig
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
 
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev_priv))
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
@@ -5716,7 +5746,7 @@ intel_dp_init_connector(struct intel_dig
 		break;
 	case PORT_B:
 		intel_encoder->hpd_pin = HPD_PORT_B;
-		if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
+		if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
 			intel_encoder->hpd_pin = HPD_PORT_A;
 		break;
 	case PORT_C:
@@ -5733,7 +5763,7 @@ intel_dp_init_connector(struct intel_dig
 	}
 
 	/* init MST on ports that can support it */
-	if (HAS_DP_MST(dev) && !is_edp(intel_dp) &&
+	if (HAS_DP_MST(dev_priv) && !is_edp(intel_dp) &&
 	    (port == PORT_B || port == PORT_C || port == PORT_D))
 		intel_dp_mst_encoder_init(intel_dig_port,
 					  intel_connector->base.base.id);
@@ -5750,7 +5780,7 @@ intel_dp_init_connector(struct intel_dig
 	 * 0xd.  Failure to do so will result in spurious interrupts being
 	 * generated on the port when a cable is not attached.
 	 */
-	if (IS_G4X(dev) && !IS_GM45(dev)) {
+	if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) {
 		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
@@ -5793,13 +5823,13 @@ bool intel_dp_init(struct drm_device *de
 	intel_encoder->get_hw_state = intel_dp_get_hw_state;
 	intel_encoder->get_config = intel_dp_get_config;
 	intel_encoder->suspend = intel_dp_encoder_suspend;
-	if (IS_CHERRYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev_priv)) {
 		intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable;
 		intel_encoder->pre_enable = chv_pre_enable_dp;
 		intel_encoder->enable = vlv_enable_dp;
 		intel_encoder->post_disable = chv_post_disable_dp;
 		intel_encoder->post_pll_disable = chv_dp_post_pll_disable;
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
 		intel_encoder->pre_enable = vlv_pre_enable_dp;
 		intel_encoder->enable = vlv_enable_dp;
@@ -5807,7 +5837,7 @@ bool intel_dp_init(struct drm_device *de
 	} else {
 		intel_encoder->pre_enable = g4x_pre_enable_dp;
 		intel_encoder->enable = g4x_enable_dp;
-		if (INTEL_INFO(dev)->gen >= 5)
+		if (INTEL_GEN(dev_priv) >= 5)
 			intel_encoder->post_disable = ilk_post_disable_dp;
 	}
 
@@ -5816,7 +5846,7 @@ bool intel_dp_init(struct drm_device *de
 	intel_dig_port->max_lanes = 4;
 
 	intel_encoder->type = INTEL_OUTPUT_DP;
-	if (IS_CHERRYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev_priv)) {
 		if (port == PORT_D)
 			intel_encoder->crtc_mask = 1 << 2;
 		else
@@ -5825,6 +5855,7 @@ bool intel_dp_init(struct drm_device *de
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
 	}
 	intel_encoder->cloneable = 0;
+	intel_encoder->port = port;
 
 	intel_dig_port->hpd_pulse = intel_dp_hpd_pulse;
 	dev_priv->hotplug.irq_port[port] = intel_dig_port;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dpio_phy.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dpio_phy.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dpio_phy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dpio_phy.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,565 @@
 
 #include "intel_drv.h"
 
+/**
+ * DOC: DPIO
+ *
+ * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI
+ * ports. DPIO is the name given to such a display PHY. These PHYs
+ * don't follow the standard programming model using direct MMIO
+ * registers, and instead their registers must be accessed trough IOSF
+ * sideband. VLV has one such PHY for driving ports B and C, and CHV
+ * adds another PHY for driving port D. Each PHY responds to specific
+ * IOSF-SB port.
+ *
+ * Each display PHY is made up of one or two channels. Each channel
+ * houses a common lane part which contains the PLL and other common
+ * logic. CH0 common lane also contains the IOSF-SB logic for the
+ * Common Register Interface (CRI) ie. the DPIO registers. CRI clock
+ * must be running when any DPIO registers are accessed.
+ *
+ * In addition to having their own registers, the PHYs are also
+ * controlled through some dedicated signals from the display
+ * controller. These include PLL reference clock enable, PLL enable,
+ * and CRI clock selection, for example.
+ *
+ * Eeach channel also has two splines (also called data lanes), and
+ * each spline is made up of one Physical Access Coding Sub-Layer
+ * (PCS) block and two TX lanes. So each channel has two PCS blocks
+ * and four TX lanes. The TX lanes are used as DP lanes or TMDS
+ * data/clock pairs depending on the output type.
+ *
+ * Additionally the PHY also contains an AUX lane with AUX blocks
+ * for each channel. This is used for DP AUX communication, but
+ * this fact isn't really relevant for the driver since AUX is
+ * controlled from the display controller side. No DPIO registers
+ * need to be accessed during AUX communication,
+ *
+ * Generally on VLV/CHV the common lane corresponds to the pipe and
+ * the spline (PCS/TX) corresponds to the port.
+ *
+ * For dual channel PHY (VLV/CHV):
+ *
+ *  pipe A == CMN/PLL/REF CH0
+ *
+ *  pipe B == CMN/PLL/REF CH1
+ *
+ *  port B == PCS/TX CH0
+ *
+ *  port C == PCS/TX CH1
+ *
+ * This is especially important when we cross the streams
+ * ie. drive port B with pipe B, or port C with pipe A.
+ *
+ * For single channel PHY (CHV):
+ *
+ *  pipe C == CMN/PLL/REF CH0
+ *
+ *  port D == PCS/TX CH0
+ *
+ * On BXT the entire PHY channel corresponds to the port. That means
+ * the PLL is also now associated with the port rather than the pipe,
+ * and so the clock needs to be routed to the appropriate transcoder.
+ * Port A PLL is directly connected to transcoder EDP and port B/C
+ * PLLs can be routed to any transcoder A/B/C.
+ *
+ * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is
+ * digital port D (CHV) or port A (BXT). ::
+ *
+ *
+ *     Dual channel PHY (VLV/CHV/BXT)
+ *     ---------------------------------
+ *     |      CH0      |      CH1      |
+ *     |  CMN/PLL/REF  |  CMN/PLL/REF  |
+ *     |---------------|---------------| Display PHY
+ *     | PCS01 | PCS23 | PCS01 | PCS23 |
+ *     |-------|-------|-------|-------|
+ *     |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3|
+ *     ---------------------------------
+ *     |     DDI0      |     DDI1      | DP/HDMI ports
+ *     ---------------------------------
+ *
+ *     Single channel PHY (CHV/BXT)
+ *     -----------------
+ *     |      CH0      |
+ *     |  CMN/PLL/REF  |
+ *     |---------------| Display PHY
+ *     | PCS01 | PCS23 |
+ *     |-------|-------|
+ *     |TX0|TX1|TX2|TX3|
+ *     -----------------
+ *     |     DDI2      | DP/HDMI port
+ *     -----------------
+ */
+
+/**
+ * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy
+ */
+struct bxt_ddi_phy_info {
+	/**
+	 * @dual_channel: true if this phy has a second channel.
+	 */
+	bool dual_channel;
+
+	/**
+	 * @rcomp_phy: If -1, indicates this phy has its own rcomp resistor.
+	 * Otherwise the GRC value will be copied from the phy indicated by
+	 * this field.
+	 */
+	enum dpio_phy rcomp_phy;
+
+	/**
+	 * @channel: struct containing per channel information.
+	 */
+	struct {
+		/**
+		 * @port: which port maps to this channel.
+		 */
+		enum port port;
+	} channel[2];
+};
+
+static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = {
+	[DPIO_PHY0] = {
+		.dual_channel = true,
+		.rcomp_phy = DPIO_PHY1,
+
+		.channel = {
+			[DPIO_CH0] = { .port = PORT_B },
+			[DPIO_CH1] = { .port = PORT_C },
+		}
+	},
+	[DPIO_PHY1] = {
+		.dual_channel = false,
+		.rcomp_phy = -1,
+
+		.channel = {
+			[DPIO_CH0] = { .port = PORT_A },
+		}
+	},
+};
+
+static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info)
+{
+	return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) |
+		BIT(phy_info->channel[DPIO_CH0].port);
+}
+
+void bxt_port_to_phy_channel(enum port port,
+			     enum dpio_phy *phy, enum dpio_channel *ch)
+{
+	const struct bxt_ddi_phy_info *phy_info;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bxt_ddi_phy_info); i++) {
+		phy_info = &bxt_ddi_phy_info[i];
+
+		if (port == phy_info->channel[DPIO_CH0].port) {
+			*phy = i;
+			*ch = DPIO_CH0;
+			return;
+		}
+
+		if (phy_info->dual_channel &&
+		    port == phy_info->channel[DPIO_CH1].port) {
+			*phy = i;
+			*ch = DPIO_CH1;
+			return;
+		}
+	}
+
+	WARN(1, "PHY not found for PORT %c", port_name(port));
+	*phy = DPIO_PHY0;
+	*ch = DPIO_CH0;
+}
+
+void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
+				  enum port port, u32 margin, u32 scale,
+				  u32 enable, u32 deemphasis)
+{
+	u32 val;
+	enum dpio_phy phy;
+	enum dpio_channel ch;
+
+	bxt_port_to_phy_channel(port, &phy, &ch);
+
+	/*
+	 * While we write to the group register to program all lanes at once we
+	 * can read only lane registers and we pick lanes 0/1 for that.
+	 */
+	val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch));
+	val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT);
+	I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val);
+
+	val = I915_READ(BXT_PORT_TX_DW2_LN0(phy, ch));
+	val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE);
+	val |= margin << MARGIN_000_SHIFT | scale << UNIQ_TRANS_SCALE_SHIFT;
+	I915_WRITE(BXT_PORT_TX_DW2_GRP(phy, ch), val);
+
+	val = I915_READ(BXT_PORT_TX_DW3_LN0(phy, ch));
+	val &= ~SCALE_DCOMP_METHOD;
+	if (enable)
+		val |= SCALE_DCOMP_METHOD;
+
+	if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD))
+		DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set");
+
+	I915_WRITE(BXT_PORT_TX_DW3_GRP(phy, ch), val);
+
+	val = I915_READ(BXT_PORT_TX_DW4_LN0(phy, ch));
+	val &= ~DE_EMPHASIS;
+	val |= deemphasis << DEEMPH_SHIFT;
+	I915_WRITE(BXT_PORT_TX_DW4_GRP(phy, ch), val);
+
+	val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch));
+	val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT;
+	I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val);
+}
+
+bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
+			    enum dpio_phy phy)
+{
+	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+	enum port port;
+
+	if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy)))
+		return false;
+
+	if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
+	     (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) {
+		DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n",
+				 phy);
+
+		return false;
+	}
+
+	if (phy_info->rcomp_phy == -1 &&
+	    !(I915_READ(BXT_PORT_REF_DW3(phy)) & GRC_DONE)) {
+		DRM_DEBUG_DRIVER("DDI PHY %d powered, but GRC isn't done\n",
+				 phy);
+
+		return false;
+	}
+
+	if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) {
+		DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n",
+				 phy);
+
+		return false;
+	}
+
+	for_each_port_masked(port, bxt_phy_port_mask(phy_info)) {
+		u32 tmp = I915_READ(BXT_PHY_CTL(port));
+
+		if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) {
+			DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane "
+					 "for port %c powered down "
+					 "(PHY_CTL %08x)\n",
+					 phy, port_name(port), tmp);
+
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+	u32 val = I915_READ(BXT_PORT_REF_DW6(phy));
+
+	return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT;
+}
+
+static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv,
+				  enum dpio_phy phy)
+{
+	if (intel_wait_for_register(dev_priv,
+				    BXT_PORT_REF_DW3(phy),
+				    GRC_DONE, GRC_DONE,
+				    10))
+		DRM_ERROR("timeout waiting for PHY%d GRC\n", phy);
+}
+
+static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv,
+			      enum dpio_phy phy)
+{
+	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+	u32 val;
+
+	if (bxt_ddi_phy_is_enabled(dev_priv, phy)) {
+		/* Still read out the GRC value for state verification */
+		if (phy_info->rcomp_phy != -1)
+			dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy);
+
+		if (bxt_ddi_phy_verify_state(dev_priv, phy)) {
+			DRM_DEBUG_DRIVER("DDI PHY %d already enabled, "
+					 "won't reprogram it\n", phy);
+
+			return;
+		}
+
+		DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, "
+				 "force reprogramming it\n", phy);
+	}
+
+	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
+	val |= GT_DISPLAY_POWER_ON(phy);
+	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
+
+	/*
+	 * The PHY registers start out inaccessible and respond to reads with
+	 * all 1s.  Eventually they become accessible as they power up, then
+	 * the reserved bit will give the default 0.  Poll on the reserved bit
+	 * becoming 0 to find when the PHY is accessible.
+	 * HW team confirmed that the time to reach phypowergood status is
+	 * anywhere between 50 us and 100us.
+	 */
+	if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
+		(PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) {
+		DRM_ERROR("timeout during PHY%d power on\n", phy);
+	}
+
+	/* Program PLL Rcomp code offset */
+	val = I915_READ(BXT_PORT_CL1CM_DW9(phy));
+	val &= ~IREF0RC_OFFSET_MASK;
+	val |= 0xE4 << IREF0RC_OFFSET_SHIFT;
+	I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val);
+
+	val = I915_READ(BXT_PORT_CL1CM_DW10(phy));
+	val &= ~IREF1RC_OFFSET_MASK;
+	val |= 0xE4 << IREF1RC_OFFSET_SHIFT;
+	I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val);
+
+	/* Program power gating */
+	val = I915_READ(BXT_PORT_CL1CM_DW28(phy));
+	val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN |
+		SUS_CLK_CONFIG;
+	I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val);
+
+	if (phy_info->dual_channel) {
+		val = I915_READ(BXT_PORT_CL2CM_DW6(phy));
+		val |= DW6_OLDO_DYN_PWR_DOWN_EN;
+		I915_WRITE(BXT_PORT_CL2CM_DW6(phy), val);
+	}
+
+	if (phy_info->rcomp_phy != -1) {
+		uint32_t grc_code;
+		/*
+		 * PHY0 isn't connected to an RCOMP resistor so copy over
+		 * the corresponding calibrated value from PHY1, and disable
+		 * the automatic calibration on PHY0.
+		 */
+		val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv,
+							  phy_info->rcomp_phy);
+		grc_code = val << GRC_CODE_FAST_SHIFT |
+			   val << GRC_CODE_SLOW_SHIFT |
+			   val;
+		I915_WRITE(BXT_PORT_REF_DW6(phy), grc_code);
+
+		val = I915_READ(BXT_PORT_REF_DW8(phy));
+		val |= GRC_DIS | GRC_RDY_OVRD;
+		I915_WRITE(BXT_PORT_REF_DW8(phy), val);
+	}
+
+	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
+	val |= COMMON_RESET_DIS;
+	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
+
+	if (phy_info->rcomp_phy == -1)
+		bxt_phy_wait_grc_done(dev_priv, phy);
+
+}
+
+void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+	uint32_t val;
+
+	val = I915_READ(BXT_PHY_CTL_FAMILY(phy));
+	val &= ~COMMON_RESET_DIS;
+	I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val);
+
+	val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
+	val &= ~GT_DISPLAY_POWER_ON(phy);
+	I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
+}
+
+void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy)
+{
+	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+	enum dpio_phy rcomp_phy = phy_info->rcomp_phy;
+	bool was_enabled;
+
+	lockdep_assert_held(&dev_priv->power_domains.lock);
+
+	if (rcomp_phy != -1) {
+		was_enabled = bxt_ddi_phy_is_enabled(dev_priv, rcomp_phy);
+
+		/*
+		 * We need to copy the GRC calibration value from rcomp_phy,
+		 * so make sure it's powered up.
+		 */
+		if (!was_enabled)
+			_bxt_ddi_phy_init(dev_priv, rcomp_phy);
+	}
+
+	_bxt_ddi_phy_init(dev_priv, phy);
+
+	if (rcomp_phy != -1 && !was_enabled)
+		bxt_ddi_phy_uninit(dev_priv, phy_info->rcomp_phy);
+}
+
+static bool __printf(6, 7)
+__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+		       i915_reg_t reg, u32 mask, u32 expected,
+		       const char *reg_fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	u32 val;
+
+	val = I915_READ(reg);
+	if ((val & mask) == expected)
+		return true;
+
+	va_start(args, reg_fmt);
+	vaf.fmt = reg_fmt;
+	vaf.va = &args;
+
+	DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: "
+			 "current %08x, expected %08x (mask %08x)\n",
+			 phy, &vaf, reg.reg, val, (val & ~mask) | expected,
+			 mask);
+
+	va_end(args);
+
+	return false;
+}
+
+bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
+			      enum dpio_phy phy)
+{
+	const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy];
+	uint32_t mask;
+	bool ok;
+
+#define _CHK(reg, mask, exp, fmt, ...)					\
+	__phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt,	\
+			       ## __VA_ARGS__)
+
+	if (!bxt_ddi_phy_is_enabled(dev_priv, phy))
+		return false;
+
+	ok = true;
+
+	/* PLL Rcomp code offset */
+	ok &= _CHK(BXT_PORT_CL1CM_DW9(phy),
+		    IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT,
+		    "BXT_PORT_CL1CM_DW9(%d)", phy);
+	ok &= _CHK(BXT_PORT_CL1CM_DW10(phy),
+		    IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT,
+		    "BXT_PORT_CL1CM_DW10(%d)", phy);
+
+	/* Power gating */
+	mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG;
+	ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask,
+		    "BXT_PORT_CL1CM_DW28(%d)", phy);
+
+	if (phy_info->dual_channel)
+		ok &= _CHK(BXT_PORT_CL2CM_DW6(phy),
+			   DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN,
+			   "BXT_PORT_CL2CM_DW6(%d)", phy);
+
+	if (phy_info->rcomp_phy != -1) {
+		u32 grc_code = dev_priv->bxt_phy_grc;
+
+		grc_code = grc_code << GRC_CODE_FAST_SHIFT |
+			   grc_code << GRC_CODE_SLOW_SHIFT |
+			   grc_code;
+		mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK |
+		       GRC_CODE_NOM_MASK;
+		ok &= _CHK(BXT_PORT_REF_DW6(phy), mask, grc_code,
+			   "BXT_PORT_REF_DW6(%d)", phy);
+
+		mask = GRC_DIS | GRC_RDY_OVRD;
+		ok &= _CHK(BXT_PORT_REF_DW8(phy), mask, mask,
+			    "BXT_PORT_REF_DW8(%d)", phy);
+	}
+
+	return ok;
+#undef _CHK
+}
+
+uint8_t
+bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder,
+				     uint8_t lane_count)
+{
+	switch (lane_count) {
+	case 1:
+		return 0;
+	case 2:
+		return BIT(2) | BIT(0);
+	case 4:
+		return BIT(3) | BIT(2) | BIT(0);
+	default:
+		MISSING_CASE(lane_count);
+
+		return 0;
+	}
+}
+
+void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
+				     uint8_t lane_lat_optim_mask)
+{
+	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
+	enum port port = dport->port;
+	enum dpio_phy phy;
+	enum dpio_channel ch;
+	int lane;
+
+	bxt_port_to_phy_channel(port, &phy, &ch);
+
+	for (lane = 0; lane < 4; lane++) {
+		u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane));
+
+		/*
+		 * Note that on CHV this flag is called UPAR, but has
+		 * the same function.
+		 */
+		val &= ~LATENCY_OPTIM;
+		if (lane_lat_optim_mask & BIT(lane))
+			val |= LATENCY_OPTIM;
+
+		I915_WRITE(BXT_PORT_TX_DW14_LN(phy, ch, lane), val);
+	}
+}
+
+uint8_t
+bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
+{
+	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
+	struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
+	enum port port = dport->port;
+	enum dpio_phy phy;
+	enum dpio_channel ch;
+	int lane;
+	uint8_t mask;
+
+	bxt_port_to_phy_channel(port, &phy, &ch);
+
+	mask = 0;
+	for (lane = 0; lane < 4; lane++) {
+		u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane));
+
+		if (val & LATENCY_OPTIM)
+			mask |= BIT(lane);
+	}
+
+	return mask;
+}
+
+
 void chv_set_phy_signal_level(struct intel_encoder *encoder,
 			      u32 deemph_reg_value, u32 margin_reg_value,
 			      bool uniq_trans_scale)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dp_link_training.c	2017-02-12 16:03:20.000000000 -0500
@@ -225,9 +225,6 @@ static u32 intel_dp_training_pattern(str
 	 * Intel platforms that support HBR2 also support TPS3. TPS3 support is
 	 * also mandatory for downstream devices that support HBR2. However, not
 	 * all sinks follow the spec.
-	 *
-	 * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is
-	 * supported in source but still not enabled.
 	 */
 	source_tps3 = intel_dp_source_supports_hbr2(intel_dp);
 	sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dpll_mgr.c	2017-02-12 16:03:20.000000000 -0500
@@ -188,13 +188,12 @@ out:
 
 void intel_disable_shared_dpll(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct intel_shared_dpll *pll = crtc->config->shared_dpll;
 	unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
 
 	/* PCH only available on ILK+ */
-	if (INTEL_INFO(dev)->gen < 5)
+	if (INTEL_GEN(dev_priv) < 5)
 		return;
 
 	if (pll == NULL)
@@ -1371,6 +1370,10 @@ static void bxt_ddi_pll_enable(struct dr
 {
 	uint32_t temp;
 	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
+	enum dpio_phy phy;
+	enum dpio_channel ch;
+
+	bxt_port_to_phy_channel(port, &phy, &ch);
 
 	/* Non-SSC reference */
 	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
@@ -1378,72 +1381,72 @@ static void bxt_ddi_pll_enable(struct dr
 	I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
 
 	/* Disable 10 bit clock */
-	temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+	temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
 	temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
-	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+	I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
 
 	/* Write P1 & P2 */
-	temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
+	temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
 	temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
 	temp |= pll->config.hw_state.ebb0;
-	I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
+	I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
 
 	/* Write M2 integer */
-	temp = I915_READ(BXT_PORT_PLL(port, 0));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
 	temp &= ~PORT_PLL_M2_MASK;
 	temp |= pll->config.hw_state.pll0;
-	I915_WRITE(BXT_PORT_PLL(port, 0), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
 
 	/* Write N */
-	temp = I915_READ(BXT_PORT_PLL(port, 1));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
 	temp &= ~PORT_PLL_N_MASK;
 	temp |= pll->config.hw_state.pll1;
-	I915_WRITE(BXT_PORT_PLL(port, 1), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
 
 	/* Write M2 fraction */
-	temp = I915_READ(BXT_PORT_PLL(port, 2));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
 	temp &= ~PORT_PLL_M2_FRAC_MASK;
 	temp |= pll->config.hw_state.pll2;
-	I915_WRITE(BXT_PORT_PLL(port, 2), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
 
 	/* Write M2 fraction enable */
-	temp = I915_READ(BXT_PORT_PLL(port, 3));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
 	temp &= ~PORT_PLL_M2_FRAC_ENABLE;
 	temp |= pll->config.hw_state.pll3;
-	I915_WRITE(BXT_PORT_PLL(port, 3), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
 
 	/* Write coeff */
-	temp = I915_READ(BXT_PORT_PLL(port, 6));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
 	temp &= ~PORT_PLL_PROP_COEFF_MASK;
 	temp &= ~PORT_PLL_INT_COEFF_MASK;
 	temp &= ~PORT_PLL_GAIN_CTL_MASK;
 	temp |= pll->config.hw_state.pll6;
-	I915_WRITE(BXT_PORT_PLL(port, 6), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
 
 	/* Write calibration val */
-	temp = I915_READ(BXT_PORT_PLL(port, 8));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
 	temp &= ~PORT_PLL_TARGET_CNT_MASK;
 	temp |= pll->config.hw_state.pll8;
-	I915_WRITE(BXT_PORT_PLL(port, 8), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
 
-	temp = I915_READ(BXT_PORT_PLL(port, 9));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
 	temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
 	temp |= pll->config.hw_state.pll9;
-	I915_WRITE(BXT_PORT_PLL(port, 9), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
 
-	temp = I915_READ(BXT_PORT_PLL(port, 10));
+	temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
 	temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
 	temp &= ~PORT_PLL_DCO_AMP_MASK;
 	temp |= pll->config.hw_state.pll10;
-	I915_WRITE(BXT_PORT_PLL(port, 10), temp);
+	I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
 
 	/* Recalibrate with new settings */
-	temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
+	temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
 	temp |= PORT_PLL_RECALIBRATE;
-	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+	I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
 	temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
 	temp |= pll->config.hw_state.ebb4;
-	I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
+	I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
 
 	/* Enable PLL */
 	temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
@@ -1459,11 +1462,11 @@ static void bxt_ddi_pll_enable(struct dr
 	 * While we write to the group register to program all lanes at once we
 	 * can read only lane registers and we pick lanes 0/1 for that.
 	 */
-	temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
+	temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
 	temp &= ~LANE_STAGGER_MASK;
 	temp &= ~LANESTAGGER_STRAP_OVRD;
 	temp |= pll->config.hw_state.pcsdw12;
-	I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
+	I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
 }
 
 static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
@@ -1485,6 +1488,10 @@ static bool bxt_ddi_pll_get_hw_state(str
 	enum port port = (enum port)pll->id;	/* 1:1 port->PLL mapping */
 	uint32_t val;
 	bool ret;
+	enum dpio_phy phy;
+	enum dpio_channel ch;
+
+	bxt_port_to_phy_channel(port, &phy, &ch);
 
 	if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
 		return false;
@@ -1495,36 +1502,36 @@ static bool bxt_ddi_pll_get_hw_state(str
 	if (!(val & PORT_PLL_ENABLE))
 		goto out;
 
-	hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
+	hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
 	hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
 
-	hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
+	hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
 	hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
 
-	hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
+	hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
 	hw_state->pll0 &= PORT_PLL_M2_MASK;
 
-	hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
+	hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
 	hw_state->pll1 &= PORT_PLL_N_MASK;
 
-	hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
+	hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
 	hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
 
-	hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
+	hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
 	hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
 
-	hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
+	hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
 	hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
 			  PORT_PLL_INT_COEFF_MASK |
 			  PORT_PLL_GAIN_CTL_MASK;
 
-	hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
+	hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
 	hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
 
-	hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
+	hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
 	hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
 
-	hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
+	hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
 	hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
 			   PORT_PLL_DCO_AMP_MASK;
 
@@ -1533,11 +1540,11 @@ static bool bxt_ddi_pll_get_hw_state(str
 	 * can read only lane registers. We configure all lanes the same way, so
 	 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
 	 */
-	hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
-	if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
+	hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
+	if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
 		DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
 				 hw_state->pcsdw12,
-				 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
+				 I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
 	hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
 
 	ret = true;
@@ -1723,7 +1730,8 @@ bxt_get_dpll(struct intel_crtc *crtc,
 		return NULL;
 
 	if ((encoder->type == INTEL_OUTPUT_DP ||
-	     encoder->type == INTEL_OUTPUT_EDP) &&
+	     encoder->type == INTEL_OUTPUT_EDP ||
+	     encoder->type == INTEL_OUTPUT_DP_MST) &&
 	    !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
 		return NULL;
 
@@ -1851,13 +1859,13 @@ void intel_shared_dpll_init(struct drm_d
 	const struct dpll_info *dpll_info;
 	int i;
 
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
 		dpll_mgr = &skl_pll_mgr;
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		dpll_mgr = &bxt_pll_mgr;
-	else if (HAS_DDI(dev))
+	else if (HAS_DDI(dev_priv))
 		dpll_mgr = &hsw_pll_mgr;
-	else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+	else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
 		dpll_mgr = &pch_pll_mgr;
 
 	if (!dpll_mgr) {
@@ -1883,7 +1891,7 @@ void intel_shared_dpll_init(struct drm_d
 	BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
 
 	/* FIXME: Move this to a more suitable place */
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev_priv))
 		intel_ddi_pll_init(dev);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dp_mst.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dp_mst.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dp_mst.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dp_mst.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,6 @@ static bool intel_dp_mst_compute_config(
 	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 	int mst_pbn;
 
-	pipe_config->dp_encoder_is_mst = true;
 	pipe_config->has_pch_encoder = false;
 	bpp = 24;
 	/*
@@ -523,6 +522,7 @@ intel_dp_create_fake_mst_encoder(struct
 			 DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe));
 
 	intel_encoder->type = INTEL_OUTPUT_DP_MST;
+	intel_encoder->port = intel_dig_port->port;
 	intel_encoder->crtc_mask = 0x7;
 	intel_encoder->cloneable = 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -206,6 +206,7 @@ struct intel_encoder {
 	struct drm_encoder base;
 
 	enum intel_output_type type;
+	enum port port;
 	unsigned int cloneable;
 	void (*hot_plug)(struct intel_encoder *);
 	bool (*compute_config)(struct intel_encoder *,
@@ -247,6 +248,8 @@ struct intel_encoder {
 	void (*suspend)(struct intel_encoder *);
 	int crtc_mask;
 	enum hpd_pin hpd_pin;
+	/* for communication with audio component; protected by av_mutex */
+	const struct drm_connector *audio_connector;
 };
 
 struct intel_panel {
@@ -291,6 +294,9 @@ struct intel_connector {
 	 */
 	struct intel_encoder *encoder;
 
+	/* ACPI device id for ACPI and driver cooperation */
+	u32 acpi_device_id;
+
 	/* Reads out the current hw, returning true if the connector is enabled
 	 * and active (i.e. dpms ON state). */
 	bool (*get_hw_state)(struct intel_connector *);
@@ -362,11 +368,16 @@ struct intel_atomic_state {
 
 	/* Gen9+ only */
 	struct skl_wm_values wm_results;
+
+	struct i915_sw_fence commit_ready;
+
+	struct llist_node freed;
 };
 
 struct intel_plane_state {
 	struct drm_plane_state base;
 	struct drm_rect clip;
+	struct i915_vma *vma;
 
 	struct {
 		u32 offset;
@@ -398,9 +409,6 @@ struct intel_plane_state {
 	int scaler_id;
 
 	struct drm_intel_sprite_colorkey ckey;
-
-	/* async flip related structures */
-	struct drm_i915_gem_request *wait_req;
 };
 
 struct intel_initial_plane_config {
@@ -465,9 +473,13 @@ struct intel_pipe_wm {
 	bool sprites_scaled;
 };
 
-struct skl_pipe_wm {
+struct skl_plane_wm {
 	struct skl_wm_level wm[8];
 	struct skl_wm_level trans_wm;
+};
+
+struct skl_pipe_wm {
+	struct skl_plane_wm planes[I915_MAX_PLANES];
 	uint32_t linetime;
 };
 
@@ -493,14 +505,7 @@ struct intel_crtc_wm_state {
 		struct {
 			/* gen9+ only needs 1-step wm programming */
 			struct skl_pipe_wm optimal;
-
-			/* cached plane data rate */
-			unsigned plane_data_rate[I915_MAX_PLANES];
-			unsigned plane_y_data_rate[I915_MAX_PLANES];
-
-			/* minimum block allocation */
-			uint16_t minimum_blocks[I915_MAX_PLANES];
-			uint16_t minimum_y_blocks[I915_MAX_PLANES];
+			struct skl_ddb_entry ddb;
 		} skl;
 	};
 
@@ -653,7 +658,6 @@ struct intel_crtc_state {
 
 	bool double_wide;
 
-	bool dp_encoder_is_mst;
 	int pbn;
 
 	struct intel_crtc_scaler_state scaler_state;
@@ -723,7 +727,6 @@ struct intel_crtc {
 		/* watermarks currently being used  */
 		union {
 			struct intel_pipe_wm ilk;
-			struct skl_pipe_wm skl;
 		} active;
 
 		/* allow CxSR on this pipe */
@@ -796,22 +799,22 @@ struct intel_plane {
 };
 
 struct intel_watermark_params {
-	unsigned long fifo_size;
-	unsigned long max_wm;
-	unsigned long default_wm;
-	unsigned long guard_size;
-	unsigned long cacheline_size;
+	u16 fifo_size;
+	u16 max_wm;
+	u8 default_wm;
+	u8 guard_size;
+	u8 cacheline_size;
 };
 
 struct cxsr_latency {
-	int is_desktop;
-	int is_ddr3;
-	unsigned long fsb_freq;
-	unsigned long mem_freq;
-	unsigned long display_sr;
-	unsigned long display_hpll_disable;
-	unsigned long cursor_sr;
-	unsigned long cursor_hpll_disable;
+	bool is_desktop : 1;
+	bool is_ddr3 : 1;
+	u16 fsb_freq;
+	u16 mem_freq;
+	u16 display_sr;
+	u16 display_hpll_disable;
+	u16 cursor_sr;
+	u16 cursor_hpll_disable;
 };
 
 #define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base)
@@ -872,6 +875,14 @@ enum link_m_n_set {
 	M2_N2
 };
 
+struct intel_dp_desc {
+	u8 oui[3];
+	u8 device_id[6];
+	u8 hw_rev;
+	u8 sw_major_rev;
+	u8 sw_minor_rev;
+} __packed;
+
 struct intel_dp {
 	i915_reg_t output_reg;
 	i915_reg_t aux_ch_ctl_reg;
@@ -894,6 +905,8 @@ struct intel_dp {
 	/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
 	uint8_t num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
+	/* sink or branch descriptor */
+	struct intel_dp_desc desc;
 	struct drm_dp_aux aux;
 	uint8_t train_set[4];
 	int panel_power_up_delay;
@@ -950,17 +963,22 @@ struct intel_dp {
 	bool compliance_test_active;
 };
 
+struct intel_lspcon {
+	bool active;
+	enum drm_lspcon_mode mode;
+	bool desc_valid;
+};
+
 struct intel_digital_port {
 	struct intel_encoder base;
 	enum port port;
 	u32 saved_port_bits;
 	struct intel_dp dp;
 	struct intel_hdmi hdmi;
+	struct intel_lspcon lspcon;
 	enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
 	bool release_cl2_override;
 	uint8_t max_lanes;
-	/* for communication with audio component; protected by av_mutex */
-	const struct drm_connector *audio_connector;
 };
 
 struct intel_dp_mst_encoder {
@@ -1012,17 +1030,15 @@ vlv_pipe_to_channel(enum pipe pipe)
 	}
 }
 
-static inline struct drm_crtc *
-intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
+static inline struct intel_crtc *
+intel_get_crtc_for_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	return dev_priv->pipe_to_crtc_mapping[pipe];
 }
 
-static inline struct drm_crtc *
-intel_get_crtc_for_plane(struct drm_device *dev, int plane)
+static inline struct intel_crtc *
+intel_get_crtc_for_plane(struct drm_i915_private *dev_priv, enum plane plane)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	return dev_priv->plane_to_crtc_mapping[plane];
 }
 
@@ -1031,6 +1047,7 @@ struct intel_flip_work {
 	struct work_struct mmio_work;
 
 	struct drm_crtc *crtc;
+	struct i915_vma *old_vma;
 	struct drm_framebuffer *old_fb;
 	struct drm_i915_gem_object *pending_flip_obj;
 	struct drm_pending_vblank_event *event;
@@ -1082,15 +1099,6 @@ hdmi_to_dig_port(struct intel_hdmi *inte
 	return container_of(intel_hdmi, struct intel_digital_port, hdmi);
 }
 
-/*
- * Returns the number of planes for this pipe, ie the number of sprites + 1
- * (primary plane). This doesn't count the cursor plane then.
- */
-static inline unsigned int intel_num_planes(struct intel_crtc *crtc)
-{
-	return INTEL_INFO(crtc->base.dev)->num_sprites[crtc->pipe] + 1;
-}
-
 /* intel_fifo_underrun.c */
 bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
 					   enum pipe pipe, bool enable);
@@ -1107,6 +1115,9 @@ void intel_check_pch_fifo_underruns(stru
 /* i915_irq.c */
 void gen5_enable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask);
+void gen6_reset_pm_iir(struct drm_i915_private *dev_priv, u32 mask);
+void gen6_mask_pm_irq(struct drm_i915_private *dev_priv, u32 mask);
+void gen6_unmask_pm_irq(struct drm_i915_private *dev_priv, u32 mask);
 void gen6_enable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask);
 void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv);
@@ -1129,6 +1140,9 @@ void gen8_irq_power_well_post_enable(str
 				     unsigned int pipe_mask);
 void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv,
 				     unsigned int pipe_mask);
+void gen9_reset_guc_interrupts(struct drm_i915_private *dev_priv);
+void gen9_enable_guc_interrupts(struct drm_i915_private *dev_priv);
+void gen9_disable_guc_interrupts(struct drm_i915_private *dev_priv);
 
 /* intel_crt.c */
 void intel_crt_init(struct drm_device *dev);
@@ -1176,12 +1190,15 @@ u32 intel_fb_stride_alignment(const stru
 
 /* intel_audio.c */
 void intel_init_audio_hooks(struct drm_i915_private *dev_priv);
-void intel_audio_codec_enable(struct intel_encoder *encoder);
+void intel_audio_codec_enable(struct intel_encoder *encoder,
+			      const struct intel_crtc_state *crtc_state,
+			      const struct drm_connector_state *conn_state);
 void intel_audio_codec_disable(struct intel_encoder *encoder);
 void i915_audio_component_init(struct drm_i915_private *dev_priv);
 void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
 
 /* intel_display.c */
+enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc);
 void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco);
 void intel_update_rawclk(struct drm_i915_private *dev_priv);
 int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
@@ -1230,18 +1247,17 @@ intel_crtc_has_dp_encoder(const struct i
 		 (1 << INTEL_OUTPUT_EDP));
 }
 static inline void
-intel_wait_for_vblank(struct drm_device *dev, int pipe)
+intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
 {
-	drm_wait_one_vblank(dev, pipe);
+	drm_wait_one_vblank(&dev_priv->drm, pipe);
 }
 static inline void
-intel_wait_for_vblank_if_active(struct drm_device *dev, int pipe)
+intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, int pipe)
 {
-	const struct intel_crtc *crtc =
-		to_intel_crtc(intel_get_crtc_for_pipe(dev, pipe));
+	const struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 
 	if (crtc->active)
-		intel_wait_for_vblank(dev, pipe);
+		intel_wait_for_vblank(dev_priv, pipe);
 }
 
 u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc);
@@ -1259,7 +1275,7 @@ void intel_release_load_detect_pipe(stru
 				    struct drm_modeset_acquire_ctx *ctx);
 struct i915_vma *
 intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
-void intel_unpin_fb_obj(struct drm_framebuffer *fb, unsigned int rotation);
+void intel_unpin_fb_vma(struct i915_vma *vma);
 struct drm_framebuffer *
 __intel_framebuffer_create(struct drm_device *dev,
 			   struct drm_mode_fb_cmd2 *mode_cmd,
@@ -1285,21 +1301,12 @@ int intel_plane_atomic_calc_changes(stru
 unsigned int intel_tile_height(const struct drm_i915_private *dev_priv,
 			       uint64_t fb_modifier, unsigned int cpp);
 
-static inline bool
-intel_rotation_90_or_270(unsigned int rotation)
-{
-	return rotation & (DRM_ROTATE_90 | DRM_ROTATE_270);
-}
-
-void intel_create_rotation_property(struct drm_device *dev,
-					struct intel_plane *plane);
-
 void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv,
 				    enum pipe pipe);
 
-int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe,
+int vlv_force_pll_on(struct drm_i915_private *dev_priv, enum pipe pipe,
 		     const struct dpll *dpll);
-void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe);
+void vlv_force_pll_off(struct drm_i915_private *dev_priv, enum pipe pipe);
 int lpt_get_iclkip(struct drm_i915_private *dev_priv);
 
 /* modesetting asserts */
@@ -1327,12 +1334,6 @@ void hsw_enable_pc8(struct drm_i915_priv
 void hsw_disable_pc8(struct drm_i915_private *dev_priv);
 void bxt_init_cdclk(struct drm_i915_private *dev_priv);
 void bxt_uninit_cdclk(struct drm_i915_private *dev_priv);
-void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy);
-void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy);
-bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
-			    enum dpio_phy phy);
-bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
-			      enum dpio_phy phy);
 void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv);
 void bxt_enable_dc9(struct drm_i915_private *dev_priv);
 void bxt_disable_dc9(struct drm_i915_private *dev_priv);
@@ -1350,7 +1351,7 @@ bool bxt_find_best_dpll(struct intel_crt
 			struct dpll *best_clock);
 int chv_calc_dpll_params(int refclk, struct dpll *pll_clock);
 
-bool intel_crtc_active(struct drm_crtc *crtc);
+bool intel_crtc_active(struct intel_crtc *crtc);
 void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 enum intel_display_power_domain
@@ -1363,7 +1364,10 @@ void intel_mode_from_pipe_config(struct
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state);
 
-u32 intel_fb_gtt_offset(struct drm_framebuffer *fb, unsigned int rotation);
+static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state)
+{
+	return i915_ggtt_offset(state->vma);
+}
 
 u32 skl_plane_ctl_format(uint32_t pixel_format);
 u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
@@ -1396,7 +1400,7 @@ int intel_dp_sink_crc(struct intel_dp *i
 bool intel_dp_compute_config(struct intel_encoder *encoder,
 			     struct intel_crtc_state *pipe_config,
 			     struct drm_connector_state *conn_state);
-bool intel_dp_is_edp(struct drm_device *dev, enum port port);
+bool intel_dp_is_edp(struct drm_i915_private *dev_priv, enum port port);
 enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port,
 				  bool long_hpd);
 void intel_edp_backlight_on(struct intel_dp *intel_dp);
@@ -1443,6 +1447,11 @@ static inline unsigned int intel_dp_unus
 	return ~((1 << lane_count) - 1) & 0xf;
 }
 
+bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
+bool __intel_dp_read_desc(struct intel_dp *intel_dp,
+			  struct intel_dp_desc *desc);
+bool intel_dp_read_desc(struct intel_dp *intel_dp);
+
 /* intel_dp_aux_backlight.c */
 int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
 
@@ -1487,6 +1496,10 @@ static inline void intel_fbdev_set_suspe
 {
 }
 
+static inline void intel_fbdev_output_poll_changed(struct drm_device *dev)
+{
+}
+
 static inline void intel_fbdev_restore_mode(struct drm_device *dev)
 {
 }
@@ -1513,6 +1526,7 @@ void intel_fbc_invalidate(struct drm_i91
 void intel_fbc_flush(struct drm_i915_private *dev_priv,
 		     unsigned int frontbuffer_bits, enum fb_op_origin origin);
 void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv);
+void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv);
 
 /* intel_hdmi.c */
 void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port);
@@ -1642,23 +1656,6 @@ assert_rpm_wakelock_held(struct drm_i915
 		DRM_DEBUG_DRIVER("RPM wakelock ref not held during HW access");
 }
 
-static inline int
-assert_rpm_atomic_begin(struct drm_i915_private *dev_priv)
-{
-	int seq = atomic_read(&dev_priv->pm.atomic_seq);
-
-	assert_rpm_wakelock_held(dev_priv);
-
-	return seq;
-}
-
-static inline void
-assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq)
-{
-	WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq,
-		  "HW access outside of RPM atomic section\n");
-}
-
 /**
  * disable_rpm_wakeref_asserts - disable the RPM assert checks
  * @dev_priv: i915 device instance
@@ -1714,11 +1711,11 @@ bool chv_phy_powergate_ch(struct drm_i91
 
 
 /* intel_pm.c */
-void intel_init_clock_gating(struct drm_device *dev);
-void intel_suspend_hw(struct drm_device *dev);
-int ilk_wm_max_level(const struct drm_device *dev);
-void intel_update_watermarks(struct drm_crtc *crtc);
-void intel_init_pm(struct drm_device *dev);
+void intel_init_clock_gating(struct drm_i915_private *dev_priv);
+void intel_suspend_hw(struct drm_i915_private *dev_priv);
+int ilk_wm_max_level(const struct drm_i915_private *dev_priv);
+void intel_update_watermarks(struct intel_crtc *crtc);
+void intel_init_pm(struct drm_i915_private *dev_priv);
 void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv);
 void intel_pm_setup(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
@@ -1742,21 +1739,16 @@ void ilk_wm_get_hw_state(struct drm_devi
 void skl_wm_get_hw_state(struct drm_device *dev);
 void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
 			  struct skl_ddb_allocation *ddb /* out */);
+void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
+			      struct skl_pipe_wm *out);
 bool intel_can_enable_sagv(struct drm_atomic_state *state);
 int intel_enable_sagv(struct drm_i915_private *dev_priv);
 int intel_disable_sagv(struct drm_i915_private *dev_priv);
-bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old,
-			       const struct skl_ddb_allocation *new,
-			       enum pipe pipe);
-bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state,
-				 const struct skl_ddb_allocation *old,
-				 const struct skl_ddb_allocation *new,
-				 enum pipe pipe);
-void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
-			 const struct skl_wm_values *wm);
-void skl_write_plane_wm(struct intel_crtc *intel_crtc,
-			const struct skl_wm_values *wm,
-			int plane);
+bool skl_wm_level_equals(const struct skl_wm_level *l1,
+			 const struct skl_wm_level *l2);
+bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries,
+				 const struct skl_ddb_entry *ddb,
+				 int ignore);
 uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
 bool ilk_disable_lp_wm(struct drm_device *dev);
 int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6);
@@ -1773,7 +1765,8 @@ bool intel_sdvo_init(struct drm_device *
 /* intel_sprite.c */
 int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode,
 			     int usecs);
-int intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane);
+struct intel_plane *intel_sprite_plane_create(struct drm_i915_private *dev_priv,
+					      enum pipe pipe, int plane);
 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
 void intel_pipe_update_start(struct intel_crtc *crtc);
@@ -1835,4 +1828,7 @@ int intel_color_check(struct drm_crtc *c
 void intel_color_set_csc(struct drm_crtc_state *crtc_state);
 void intel_color_load_luts(struct drm_crtc_state *crtc_state);
 
+/* intel_lspcon.c */
+bool lspcon_init(struct intel_digital_port *intel_dig_port);
+void lspcon_resume(struct intel_lspcon *lspcon);
 #endif /* __INTEL_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dsi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dsi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dsi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dsi.c	2017-02-12 16:03:20.000000000 -0500
@@ -437,11 +437,11 @@ static void vlv_dsi_device_ready(struct
 
 static void intel_dsi_device_ready(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		vlv_dsi_device_ready(encoder);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		bxt_dsi_device_ready(encoder);
 }
 
@@ -464,7 +464,7 @@ static void intel_dsi_port_enable(struct
 	}
 
 	for_each_dsi_port(port, intel_dsi->ports) {
-		i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+		i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ?
 			BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
 		u32 temp;
 
@@ -494,7 +494,7 @@ static void intel_dsi_port_disable(struc
 	enum port port;
 
 	for_each_dsi_port(port, intel_dsi->ports) {
-		i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+		i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ?
 			BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
 		u32 temp;
 
@@ -656,7 +656,6 @@ static void intel_dsi_disable(struct int
 
 static void intel_dsi_clear_device_ready(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 	enum port port;
@@ -664,7 +663,7 @@ static void intel_dsi_clear_device_ready
 	DRM_DEBUG_KMS("\n");
 	for_each_dsi_port(port, intel_dsi->ports) {
 		/* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */
-		i915_reg_t port_ctrl = IS_BROXTON(dev) ?
+		i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ?
 			BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A);
 		u32 val;
 
@@ -741,7 +740,6 @@ static bool intel_dsi_get_hw_state(struc
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
-	struct drm_device *dev = encoder->base.dev;
 	enum intel_display_power_domain power_domain;
 	enum port port;
 	bool active = false;
@@ -762,7 +760,7 @@ static bool intel_dsi_get_hw_state(struc
 
 	/* XXX: this only works for one DSI output */
 	for_each_dsi_port(port, intel_dsi->ports) {
-		i915_reg_t ctrl_reg = IS_BROXTON(dev) ?
+		i915_reg_t ctrl_reg = IS_BROXTON(dev_priv) ?
 			BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port);
 		bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE;
 
@@ -771,7 +769,8 @@ static bool intel_dsi_get_hw_state(struc
 		 * bit in port C control register does not get set. As a
 		 * workaround, check pipe B conf instead.
 		 */
-		if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && port == PORT_C)
+		if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+		    port == PORT_C)
 			enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE;
 
 		/* Try command mode if video mode not enabled */
@@ -970,11 +969,11 @@ static void bxt_dsi_get_pipe_config(stru
 static void intel_dsi_get_config(struct intel_encoder *encoder,
 				 struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	u32 pclk;
 	DRM_DEBUG_KMS("\n");
 
-	if (IS_BROXTON(dev))
+	if (IS_BROXTON(dev_priv))
 		bxt_dsi_get_pipe_config(encoder, pipe_config);
 
 	pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp,
@@ -1066,7 +1065,7 @@ static void set_dsi_timings(struct drm_e
 	hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio);
 
 	for_each_dsi_port(port, intel_dsi->ports) {
-		if (IS_BROXTON(dev)) {
+		if (IS_BROXTON(dev_priv)) {
 			/*
 			 * Program hdisplay and vdisplay on MIPI transcoder.
 			 * This is different from calculated hactive and
@@ -1138,7 +1137,7 @@ static void intel_dsi_prepare(struct int
 	}
 
 	for_each_dsi_port(port, intel_dsi->ports) {
-		if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 			/*
 			 * escape clock divider, 20MHz, shared for A and C.
 			 * device ready must be off when doing this! txclkesc?
@@ -1153,7 +1152,7 @@ static void intel_dsi_prepare(struct int
 			tmp &= ~READ_REQUEST_PRIORITY_MASK;
 			I915_WRITE(MIPI_CTRL(port), tmp |
 					READ_REQUEST_PRIORITY_HIGH);
-		} else if (IS_BROXTON(dev)) {
+		} else if (IS_BROXTON(dev_priv)) {
 			enum pipe pipe = intel_crtc->pipe;
 
 			tmp = I915_READ(MIPI_CTRL(port));
@@ -1242,7 +1241,7 @@ static void intel_dsi_prepare(struct int
 		I915_WRITE(MIPI_INIT_COUNT(port),
 				txclkesc(intel_dsi->escape_clk_div, 100));
 
-		if (IS_BROXTON(dev) && (!intel_dsi->dual_link)) {
+		if (IS_BROXTON(dev_priv) && (!intel_dsi->dual_link)) {
 			/*
 			 * BXT spec says write MIPI_INIT_COUNT for
 			 * both the ports, even if only one is
@@ -1299,12 +1298,6 @@ static void intel_dsi_prepare(struct int
 	}
 }
 
-static enum drm_connector_status
-intel_dsi_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static int intel_dsi_get_modes(struct drm_connector *connector)
 {
 	struct intel_connector *intel_connector = to_intel_connector(connector);
@@ -1346,7 +1339,7 @@ static int intel_dsi_set_property(struct
 			DRM_DEBUG_KMS("no scaling not supported\n");
 			return -EINVAL;
 		}
-		if (HAS_GMCH_DISPLAY(dev) &&
+		if (HAS_GMCH_DISPLAY(to_i915(dev)) &&
 		    val == DRM_MODE_SCALE_CENTER) {
 			DRM_DEBUG_KMS("centering not supported\n");
 			return -EINVAL;
@@ -1408,7 +1401,6 @@ static const struct drm_connector_helper
 
 static const struct drm_connector_funcs intel_dsi_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
-	.detect = intel_dsi_detect,
 	.late_register = intel_connector_register,
 	.early_unregister = intel_connector_unregister,
 	.destroy = intel_dsi_connector_destroy,
@@ -1450,9 +1442,9 @@ void intel_dsi_init(struct drm_device *d
 	if (!intel_bios_is_dsi_present(dev_priv, &port))
 		return;
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		dev_priv->mipi_mmio_base = VLV_MIPI_BASE;
-	} else if (IS_BROXTON(dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		dev_priv->mipi_mmio_base = BXT_MIPI_BASE;
 	} else {
 		DRM_ERROR("Unsupported Mipi device to reg base");
@@ -1488,6 +1480,7 @@ void intel_dsi_init(struct drm_device *d
 
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
+	intel_encoder->port = port;
 	/*
 	 * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI
 	 * port C. BXT isn't limited like this.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c	2017-02-12 16:03:20.000000000 -0500
@@ -126,6 +126,8 @@ static const u8 *mipi_exec_send_packet(s
 	u16 len;
 	enum port port;
 
+	DRM_DEBUG_KMS("\n");
+
 	flags = *data++;
 	type = *data++;
 
@@ -199,6 +201,8 @@ static const u8 *mipi_exec_delay(struct
 {
 	u32 delay = *((const u32 *) data);
 
+	DRM_DEBUG_KMS("\n");
+
 	usleep_range(delay, delay + 10);
 	data += 4;
 
@@ -296,7 +300,8 @@ static void chv_exec_gpio(struct drm_i91
 	mutex_lock(&dev_priv->sb_lock);
 	vlv_iosf_sb_write(dev_priv, port, cfg1, 0);
 	vlv_iosf_sb_write(dev_priv, port, cfg0,
-			  CHV_GPIO_GPIOCFG_GPO | CHV_GPIO_GPIOTXSTATE(value));
+			  CHV_GPIO_GPIOEN | CHV_GPIO_GPIOCFG_GPO |
+			  CHV_GPIO_GPIOTXSTATE(value));
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
@@ -307,6 +312,8 @@ static const u8 *mipi_exec_gpio(struct i
 	u8 gpio_source, gpio_index;
 	bool value;
 
+	DRM_DEBUG_KMS("\n");
+
 	if (dev_priv->vbt.dsi.seq_version >= 3)
 		data++;
 
@@ -331,18 +338,36 @@ static const u8 *mipi_exec_gpio(struct i
 	return data;
 }
 
-static const u8 *mipi_exec_i2c_skip(struct intel_dsi *intel_dsi, const u8 *data)
+static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data)
 {
+	DRM_DEBUG_KMS("Skipping I2C element execution\n");
+
 	return data + *(data + 6) + 7;
 }
 
+static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data)
+{
+	DRM_DEBUG_KMS("Skipping SPI element execution\n");
+
+	return data + *(data + 5) + 6;
+}
+
+static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data)
+{
+	DRM_DEBUG_KMS("Skipping PMIC element execution\n");
+
+	return data + 15;
+}
+
 typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi,
 					const u8 *data);
 static const fn_mipi_elem_exec exec_elem[] = {
 	[MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet,
 	[MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay,
 	[MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio,
-	[MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c_skip,
+	[MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c,
+	[MIPI_SEQ_ELEM_SPI] = mipi_exec_spi,
+	[MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic,
 };
 
 /*
@@ -352,11 +377,11 @@ static const fn_mipi_elem_exec exec_elem
  */
 
 static const char * const seq_name[] = {
-	[MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
+	[MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
 	[MIPI_SEQ_INIT_OTP] = "MIPI_SEQ_INIT_OTP",
 	[MIPI_SEQ_DISPLAY_ON] = "MIPI_SEQ_DISPLAY_ON",
 	[MIPI_SEQ_DISPLAY_OFF]  = "MIPI_SEQ_DISPLAY_OFF",
-	[MIPI_SEQ_DEASSERT_RESET] = "MIPI_SEQ_DEASSERT_RESET",
+	[MIPI_SEQ_ASSERT_RESET] = "MIPI_SEQ_ASSERT_RESET",
 	[MIPI_SEQ_BACKLIGHT_ON] = "MIPI_SEQ_BACKLIGHT_ON",
 	[MIPI_SEQ_BACKLIGHT_OFF] = "MIPI_SEQ_BACKLIGHT_OFF",
 	[MIPI_SEQ_TEAR_ON] = "MIPI_SEQ_TEAR_ON",
@@ -385,11 +410,8 @@ static void generic_exec_sequence(struct
 		return;
 
 	data = dev_priv->vbt.dsi.sequence[seq_id];
-	if (!data) {
-		DRM_DEBUG_KMS("MIPI sequence %d - %s not available\n",
-			      seq_id, sequence_name(seq_id));
+	if (!data)
 		return;
-	}
 
 	WARN_ON(*data != seq_id);
 
@@ -420,7 +442,15 @@ static void generic_exec_sequence(struct
 			operation_size = *data++;
 
 		if (mipi_elem_exec) {
+			const u8 *next = data + operation_size;
+
 			data = mipi_elem_exec(intel_dsi, data);
+
+			/* Consistency check if we have size. */
+			if (operation_size && data != next) {
+				DRM_ERROR("Inconsistent operation size\n");
+				return;
+			}
 		} else if (operation_size) {
 			/* We have size, skip. */
 			DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n",
@@ -438,6 +468,8 @@ static void generic_exec_sequence(struct
 static int vbt_panel_prepare(struct drm_panel *panel)
 {
 	generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET);
+	generic_exec_sequence(panel, MIPI_SEQ_POWER_ON);
+	generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET);
 	generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP);
 
 	return 0;
@@ -445,7 +477,8 @@ static int vbt_panel_prepare(struct drm_
 
 static int vbt_panel_unprepare(struct drm_panel *panel)
 {
-	generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET);
+	generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET);
+	generic_exec_sequence(panel, MIPI_SEQ_POWER_OFF);
 
 	return 0;
 }
@@ -453,12 +486,14 @@ static int vbt_panel_unprepare(struct dr
 static int vbt_panel_enable(struct drm_panel *panel)
 {
 	generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON);
+	generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_ON);
 
 	return 0;
 }
 
 static int vbt_panel_disable(struct drm_panel *panel)
 {
+	generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_OFF);
 	generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF);
 
 	return 0;
@@ -740,9 +775,8 @@ struct drm_panel *vbt_panel_init(struct
 			8);
 	intel_dsi->clk_hs_to_lp_count += extra_byte_count;
 
-	DRM_DEBUG_KMS("Eot %s\n", intel_dsi->eotp_pkt ? "enabled" : "disabled");
-	DRM_DEBUG_KMS("Clockstop %s\n", intel_dsi->clock_stop ?
-						"disabled" : "enabled");
+	DRM_DEBUG_KMS("Eot %s\n", enableddisabled(intel_dsi->eotp_pkt));
+	DRM_DEBUG_KMS("Clockstop %s\n", enableddisabled(!intel_dsi->clock_stop));
 	DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
 	if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
 		DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
@@ -761,8 +795,7 @@ struct drm_panel *vbt_panel_init(struct
 	DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count);
 	DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count);
 	DRM_DEBUG_KMS("BTA %s\n",
-			intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA ?
-			"disabled" : "enabled");
+			enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
 
 	/* delays in VBT are in unit of 100us, so need to convert
 	 * here in ms
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dsi_pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -351,7 +351,7 @@ static u32 bxt_dsi_get_pclk(struct intel
 u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp,
 		       struct intel_crtc_state *config)
 {
-	if (IS_BROXTON(encoder->base.dev))
+	if (IS_BROXTON(to_i915(encoder->base.dev)))
 		return bxt_dsi_get_pclk(encoder, pipe_bpp, config);
 	else
 		return vlv_dsi_get_pclk(encoder, pipe_bpp, config);
@@ -515,11 +515,11 @@ bool intel_dsi_pll_is_enabled(struct drm
 int intel_compute_dsi_pll(struct intel_encoder *encoder,
 			  struct intel_crtc_state *config)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		return vlv_compute_dsi_pll(encoder, config);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		return bxt_compute_dsi_pll(encoder, config);
 
 	return -ENODEV;
@@ -528,21 +528,21 @@ int intel_compute_dsi_pll(struct intel_e
 void intel_enable_dsi_pll(struct intel_encoder *encoder,
 			  const struct intel_crtc_state *config)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		vlv_enable_dsi_pll(encoder, config);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		bxt_enable_dsi_pll(encoder, config);
 }
 
 void intel_disable_dsi_pll(struct intel_encoder *encoder)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		vlv_disable_dsi_pll(encoder);
-	else if (IS_BROXTON(dev))
+	else if (IS_BROXTON(dev_priv))
 		bxt_disable_dsi_pll(encoder);
 }
 
@@ -564,10 +564,10 @@ static void bxt_dsi_reset_clocks(struct
 
 void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port)
 {
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 
-	if (IS_BROXTON(dev))
+	if (IS_BROXTON(dev_priv))
 		bxt_dsi_reset_clocks(encoder, port);
-	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		vlv_dsi_reset_clocks(encoder, port);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dvo.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dvo.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_dvo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_dvo.c	2017-02-12 16:03:20.000000000 -0500
@@ -393,12 +393,12 @@ intel_dvo_get_current_mode(struct drm_co
 	 * its timings to get how the BIOS set up the panel.
 	 */
 	if (dvo_val & DVO_ENABLE) {
-		struct drm_crtc *crtc;
+		struct intel_crtc *crtc;
 		int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0;
 
-		crtc = intel_get_crtc_for_pipe(dev, pipe);
+		crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 		if (crtc) {
-			mode = intel_crtc_mode_get(dev, crtc);
+			mode = intel_crtc_mode_get(dev, &crtc->base);
 			if (mode) {
 				mode->type |= DRM_MODE_TYPE_PREFERRED;
 				if (dvo_val & DVO_HSYNC_ACTIVE_HIGH)
@@ -412,16 +412,14 @@ intel_dvo_get_current_mode(struct drm_co
 	return mode;
 }
 
-static char intel_dvo_port_name(i915_reg_t dvo_reg)
+static enum port intel_dvo_port(i915_reg_t dvo_reg)
 {
 	if (i915_mmio_reg_equal(dvo_reg, DVOA))
-		return 'A';
+		return PORT_A;
 	else if (i915_mmio_reg_equal(dvo_reg, DVOB))
-		return 'B';
-	else if (i915_mmio_reg_equal(dvo_reg, DVOC))
-		return 'C';
+		return PORT_B;
 	else
-		return '?';
+		return PORT_C;
 }
 
 void intel_dvo_init(struct drm_device *dev)
@@ -464,6 +462,7 @@ void intel_dvo_init(struct drm_device *d
 		bool dvoinit;
 		enum pipe pipe;
 		uint32_t dpll[I915_MAX_PIPES];
+		enum port port;
 
 		/* Allow the I2C driver info to specify the GPIO to be used in
 		 * special cases, but otherwise default to what's defined
@@ -511,12 +510,15 @@ void intel_dvo_init(struct drm_device *d
 		if (!dvoinit)
 			continue;
 
+		port = intel_dvo_port(dvo->dvo_reg);
 		drm_encoder_init(dev, &intel_encoder->base,
 				 &intel_dvo_enc_funcs, encoder_type,
-				 "DVO %c", intel_dvo_port_name(dvo->dvo_reg));
+				 "DVO %c", port_name(port));
 
 		intel_encoder->type = INTEL_OUTPUT_DVO;
+		intel_encoder->port = port;
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
+
 		switch (dvo->type) {
 		case INTEL_DVO_CHIP_TMDS:
 			intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) |
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_engine_cs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_engine_cs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_engine_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_engine_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -82,12 +82,17 @@ static const struct engine_info {
 	},
 };
 
-static struct intel_engine_cs *
+static int
 intel_engine_setup(struct drm_i915_private *dev_priv,
 		   enum intel_engine_id id)
 {
 	const struct engine_info *info = &intel_engines[id];
-	struct intel_engine_cs *engine = &dev_priv->engine[id];
+	struct intel_engine_cs *engine;
+
+	GEM_BUG_ON(dev_priv->engine[id]);
+	engine = kzalloc(sizeof(*engine), GFP_KERNEL);
+	if (!engine)
+		return -ENOMEM;
 
 	engine->id = id;
 	engine->i915 = dev_priv;
@@ -97,7 +102,11 @@ intel_engine_setup(struct drm_i915_priva
 	engine->mmio_base = info->mmio_base;
 	engine->irq_shift = info->irq_shift;
 
-	return engine;
+	/* Nothing to do here, execute in order of dependencies */
+	engine->schedule = NULL;
+
+	dev_priv->engine[id] = engine;
+	return 0;
 }
 
 /**
@@ -110,13 +119,16 @@ int intel_engines_init(struct drm_device
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_device_info *device_info = mkwrite_device_info(dev_priv);
+	unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask;
 	unsigned int mask = 0;
 	int (*init)(struct intel_engine_cs *engine);
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	unsigned int i;
 	int ret;
 
-	WARN_ON(INTEL_INFO(dev_priv)->ring_mask == 0);
-	WARN_ON(INTEL_INFO(dev_priv)->ring_mask &
+	WARN_ON(ring_mask == 0);
+	WARN_ON(ring_mask &
 		GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES));
 
 	for (i = 0; i < ARRAY_SIZE(intel_engines); i++) {
@@ -131,7 +143,11 @@ int intel_engines_init(struct drm_device
 		if (!init)
 			continue;
 
-		ret = init(intel_engine_setup(dev_priv, i));
+		ret = intel_engine_setup(dev_priv, i);
+		if (ret)
+			goto cleanup;
+
+		ret = init(dev_priv->engine[i]);
 		if (ret)
 			goto cleanup;
 
@@ -143,7 +159,7 @@ int intel_engines_init(struct drm_device
 	 * are added to the driver by a warning and disabling the forgotten
 	 * engines.
 	 */
-	if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask))
+	if (WARN_ON(mask != ring_mask))
 		device_info->ring_mask = mask;
 
 	device_info->num_rings = hweight32(mask);
@@ -151,17 +167,17 @@ int intel_engines_init(struct drm_device
 	return 0;
 
 cleanup:
-	for (i = 0; i < I915_NUM_ENGINES; i++) {
+	for_each_engine(engine, dev_priv, id) {
 		if (i915.enable_execlists)
-			intel_logical_ring_cleanup(&dev_priv->engine[i]);
+			intel_logical_ring_cleanup(engine);
 		else
-			intel_engine_cleanup(&dev_priv->engine[i]);
+			intel_engine_cleanup(engine);
 	}
 
 	return ret;
 }
 
-void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno)
+void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
 	struct drm_i915_private *dev_priv = engine->i915;
 
@@ -191,13 +207,13 @@ void intel_engine_init_seqno(struct inte
 				       I915_NUM_ENGINES * gen8_semaphore_seqno_size);
 		kunmap(page);
 	}
-	memset(engine->semaphore.sync_seqno, 0,
-	       sizeof(engine->semaphore.sync_seqno));
 
 	intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
 	if (engine->irq_seqno_barrier)
 		engine->irq_seqno_barrier(engine);
-	engine->last_submitted_seqno = seqno;
+
+	GEM_BUG_ON(i915_gem_active_isset(&engine->timeline->last_request));
+	engine->timeline->last_submitted_seqno = seqno;
 
 	engine->hangcheck.seqno = seqno;
 
@@ -207,15 +223,9 @@ void intel_engine_init_seqno(struct inte
 	intel_engine_wakeup(engine);
 }
 
-void intel_engine_init_hangcheck(struct intel_engine_cs *engine)
-{
-	memset(&engine->hangcheck, 0, sizeof(engine->hangcheck));
-}
-
-static void intel_engine_init_requests(struct intel_engine_cs *engine)
+static void intel_engine_init_timeline(struct intel_engine_cs *engine)
 {
-	init_request_active(&engine->last_request, NULL);
-	INIT_LIST_HEAD(&engine->request_list);
+	engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id];
 }
 
 /**
@@ -229,12 +239,10 @@ static void intel_engine_init_requests(s
  */
 void intel_engine_setup_common(struct intel_engine_cs *engine)
 {
-	INIT_LIST_HEAD(&engine->execlist_queue);
-	spin_lock_init(&engine->execlist_lock);
-
-	engine->fence_context = fence_context_alloc(1);
+	engine->execlist_queue = RB_ROOT;
+	engine->execlist_first = NULL;
 
-	intel_engine_init_requests(engine);
+	intel_engine_init_timeline(engine);
 	intel_engine_init_hangcheck(engine);
 	i915_gem_batch_pool_init(engine, &engine->batch_pool);
 
@@ -251,7 +259,7 @@ int intel_engine_create_scratch(struct i
 
 	obj = i915_gem_object_create_stolen(&engine->i915->drm, size);
 	if (!obj)
-		obj = i915_gem_object_create(&engine->i915->drm, size);
+		obj = i915_gem_object_create_internal(engine->i915, size);
 	if (IS_ERR(obj)) {
 		DRM_ERROR("Failed to allocate scratch page\n");
 		return PTR_ERR(obj);
@@ -301,6 +309,10 @@ int intel_engine_init_common(struct inte
 	if (ret)
 		return ret;
 
+	ret = i915_gem_render_state_init(engine);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -315,7 +327,142 @@ void intel_engine_cleanup_common(struct
 {
 	intel_engine_cleanup_scratch(engine);
 
+	i915_gem_render_state_fini(engine);
 	intel_engine_fini_breadcrumbs(engine);
 	intel_engine_cleanup_cmd_parser(engine);
 	i915_gem_batch_pool_fini(&engine->batch_pool);
 }
+
+u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	u64 acthd;
+
+	if (INTEL_GEN(dev_priv) >= 8)
+		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
+					 RING_ACTHD_UDW(engine->mmio_base));
+	else if (INTEL_GEN(dev_priv) >= 4)
+		acthd = I915_READ(RING_ACTHD(engine->mmio_base));
+	else
+		acthd = I915_READ(ACTHD);
+
+	return acthd;
+}
+
+u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	u64 bbaddr;
+
+	if (INTEL_GEN(dev_priv) >= 8)
+		bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base),
+					  RING_BBADDR_UDW(engine->mmio_base));
+	else
+		bbaddr = I915_READ(RING_BBADDR(engine->mmio_base));
+
+	return bbaddr;
+}
+
+const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
+{
+	switch (type) {
+	case I915_CACHE_NONE: return " uncached";
+	case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped";
+	case I915_CACHE_L3_LLC: return " L3+LLC";
+	case I915_CACHE_WT: return " WT";
+	default: return "";
+	}
+}
+
+static inline uint32_t
+read_subslice_reg(struct drm_i915_private *dev_priv, int slice,
+		  int subslice, i915_reg_t reg)
+{
+	uint32_t mcr;
+	uint32_t ret;
+	enum forcewake_domains fw_domains;
+
+	fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg,
+						    FW_REG_READ);
+	fw_domains |= intel_uncore_forcewake_for_reg(dev_priv,
+						     GEN8_MCR_SELECTOR,
+						     FW_REG_READ | FW_REG_WRITE);
+
+	spin_lock_irq(&dev_priv->uncore.lock);
+	intel_uncore_forcewake_get__locked(dev_priv, fw_domains);
+
+	mcr = I915_READ_FW(GEN8_MCR_SELECTOR);
+	/*
+	 * The HW expects the slice and sublice selectors to be reset to 0
+	 * after reading out the registers.
+	 */
+	WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK));
+	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
+	mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice);
+	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
+
+	ret = I915_READ_FW(reg);
+
+	mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK);
+	I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr);
+
+	intel_uncore_forcewake_put__locked(dev_priv, fw_domains);
+	spin_unlock_irq(&dev_priv->uncore.lock);
+
+	return ret;
+}
+
+/* NB: please notice the memset */
+void intel_engine_get_instdone(struct intel_engine_cs *engine,
+			       struct intel_instdone *instdone)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	u32 mmio_base = engine->mmio_base;
+	int slice;
+	int subslice;
+
+	memset(instdone, 0, sizeof(*instdone));
+
+	switch (INTEL_GEN(dev_priv)) {
+	default:
+		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
+
+		if (engine->id != RCS)
+			break;
+
+		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
+		for_each_instdone_slice_subslice(dev_priv, slice, subslice) {
+			instdone->sampler[slice][subslice] =
+				read_subslice_reg(dev_priv, slice, subslice,
+						  GEN7_SAMPLER_INSTDONE);
+			instdone->row[slice][subslice] =
+				read_subslice_reg(dev_priv, slice, subslice,
+						  GEN7_ROW_INSTDONE);
+		}
+		break;
+	case 7:
+		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
+
+		if (engine->id != RCS)
+			break;
+
+		instdone->slice_common = I915_READ(GEN7_SC_INSTDONE);
+		instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE);
+		instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE);
+
+		break;
+	case 6:
+	case 5:
+	case 4:
+		instdone->instdone = I915_READ(RING_INSTDONE(mmio_base));
+
+		if (engine->id == RCS)
+			/* HACK: Using the wrong struct member */
+			instdone->slice_common = I915_READ(GEN4_INSTDONE1);
+		break;
+	case 3:
+	case 2:
+		instdone->instdone = I915_READ(GEN2_INSTDONE);
+		break;
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_fbc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_fbc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_fbc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_fbc.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,17 +48,17 @@ static inline bool fbc_supported(struct
 
 static inline bool fbc_on_pipe_a_only(struct drm_i915_private *dev_priv)
 {
-	return IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8;
+	return IS_HASWELL(dev_priv) || INTEL_GEN(dev_priv) >= 8;
 }
 
 static inline bool fbc_on_plane_a_only(struct drm_i915_private *dev_priv)
 {
-	return INTEL_INFO(dev_priv)->gen < 4;
+	return INTEL_GEN(dev_priv) < 4;
 }
 
 static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv)
 {
-	return INTEL_INFO(dev_priv)->gen <= 3;
+	return INTEL_GEN(dev_priv) <= 3;
 }
 
 /*
@@ -84,7 +84,7 @@ static void intel_fbc_get_plane_source_s
 {
 	int w, h;
 
-	if (intel_rotation_90_or_270(cache->plane.rotation)) {
+	if (drm_rotation_90_or_270(cache->plane.rotation)) {
 		w = cache->plane.src_h;
 		h = cache->plane.src_w;
 	} else {
@@ -173,7 +173,7 @@ static void i8xx_fbc_activate(struct drm
 	if (IS_I945GM(dev_priv))
 		fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */
 	fbc_ctl |= (cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT;
-	fbc_ctl |= params->fb.fence_reg;
+	fbc_ctl |= params->vma->fence->id;
 	I915_WRITE(FBC_CONTROL, fbc_ctl);
 }
 
@@ -193,8 +193,8 @@ static void g4x_fbc_activate(struct drm_
 	else
 		dpfc_ctl |= DPFC_CTL_LIMIT_1X;
 
-	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
-		dpfc_ctl |= DPFC_CTL_FENCE_EN | params->fb.fence_reg;
+	if (params->vma->fence) {
+		dpfc_ctl |= DPFC_CTL_FENCE_EN | params->vma->fence->id;
 		I915_WRITE(DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
 	} else {
 		I915_WRITE(DPFC_FENCE_YOFF, 0);
@@ -251,13 +251,14 @@ static void ilk_fbc_activate(struct drm_
 		break;
 	}
 
-	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
+	if (params->vma->fence) {
 		dpfc_ctl |= DPFC_CTL_FENCE_EN;
 		if (IS_GEN5(dev_priv))
-			dpfc_ctl |= params->fb.fence_reg;
+			dpfc_ctl |= params->vma->fence->id;
 		if (IS_GEN6(dev_priv)) {
 			I915_WRITE(SNB_DPFC_CTL_SA,
-				   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
+				   SNB_CPU_FENCE_ENABLE |
+				   params->vma->fence->id);
 			I915_WRITE(DPFC_CPU_FENCE_OFFSET,
 				   params->crtc.fence_y_offset);
 		}
@@ -269,7 +270,8 @@ static void ilk_fbc_activate(struct drm_
 	}
 
 	I915_WRITE(ILK_DPFC_FENCE_YOFF, params->crtc.fence_y_offset);
-	I915_WRITE(ILK_FBC_RT_BASE, params->fb.ggtt_offset | ILK_FBC_RT_VALID);
+	I915_WRITE(ILK_FBC_RT_BASE,
+		   i915_ggtt_offset(params->vma) | ILK_FBC_RT_VALID);
 	/* enable it... */
 	I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
 
@@ -319,10 +321,11 @@ static void gen7_fbc_activate(struct drm
 		break;
 	}
 
-	if (params->fb.fence_reg != I915_FENCE_REG_NONE) {
+	if (params->vma->fence) {
 		dpfc_ctl |= IVB_DPFC_CTL_FENCE_EN;
 		I915_WRITE(SNB_DPFC_CTL_SA,
-			   SNB_CPU_FENCE_ENABLE | params->fb.fence_reg);
+			   SNB_CPU_FENCE_ENABLE |
+			   params->vma->fence->id);
 		I915_WRITE(DPFC_CPU_FENCE_OFFSET, params->crtc.fence_y_offset);
 	} else {
 		I915_WRITE(SNB_DPFC_CTL_SA,0);
@@ -351,7 +354,7 @@ static void gen7_fbc_activate(struct drm
 
 static bool intel_fbc_hw_is_active(struct drm_i915_private *dev_priv)
 {
-	if (INTEL_INFO(dev_priv)->gen >= 5)
+	if (INTEL_GEN(dev_priv) >= 5)
 		return ilk_fbc_is_active(dev_priv);
 	else if (IS_GM45(dev_priv))
 		return g4x_fbc_is_active(dev_priv);
@@ -365,9 +368,9 @@ static void intel_fbc_hw_activate(struct
 
 	fbc->active = true;
 
-	if (INTEL_INFO(dev_priv)->gen >= 7)
+	if (INTEL_GEN(dev_priv) >= 7)
 		gen7_fbc_activate(dev_priv);
-	else if (INTEL_INFO(dev_priv)->gen >= 5)
+	else if (INTEL_GEN(dev_priv) >= 5)
 		ilk_fbc_activate(dev_priv);
 	else if (IS_GM45(dev_priv))
 		g4x_fbc_activate(dev_priv);
@@ -381,7 +384,7 @@ static void intel_fbc_hw_deactivate(stru
 
 	fbc->active = false;
 
-	if (INTEL_INFO(dev_priv)->gen >= 5)
+	if (INTEL_GEN(dev_priv) >= 5)
 		ilk_fbc_deactivate(dev_priv);
 	else if (IS_GM45(dev_priv))
 		g4x_fbc_deactivate(dev_priv);
@@ -561,7 +564,7 @@ again:
 
 	ret = i915_gem_stolen_insert_node_in_range(dev_priv, node, size >>= 1,
 						   4096, 0, end);
-	if (ret && INTEL_INFO(dev_priv)->gen <= 4) {
+	if (ret && INTEL_GEN(dev_priv) <= 4) {
 		return 0;
 	} else if (ret) {
 		compression_threshold <<= 1;
@@ -594,7 +597,7 @@ static int intel_fbc_alloc_cfb(struct in
 
 	fbc->threshold = ret;
 
-	if (INTEL_INFO(dev_priv)->gen >= 5)
+	if (INTEL_GEN(dev_priv) >= 5)
 		I915_WRITE(ILK_DPFC_CB_BASE, fbc->compressed_fb.start);
 	else if (IS_GM45(dev_priv)) {
 		I915_WRITE(DPFC_CB_BASE, fbc->compressed_fb.start);
@@ -708,10 +711,10 @@ static bool intel_fbc_hw_tracking_covers
 	struct intel_fbc *fbc = &dev_priv->fbc;
 	unsigned int effective_w, effective_h, max_w, max_h;
 
-	if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
+	if (INTEL_GEN(dev_priv) >= 8 || IS_HASWELL(dev_priv)) {
 		max_w = 4096;
 		max_h = 4096;
-	} else if (IS_G4X(dev_priv) || INTEL_INFO(dev_priv)->gen >= 5) {
+	} else if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) {
 		max_w = 4096;
 		max_h = 2048;
 	} else {
@@ -727,14 +730,6 @@ static bool intel_fbc_hw_tracking_covers
 	return effective_w <= max_w && effective_h <= max_h;
 }
 
-/* XXX replace me when we have VMA tracking for intel_plane_state */
-static int get_fence_id(struct drm_framebuffer *fb)
-{
-	struct i915_vma *vma = i915_gem_object_to_ggtt(intel_fb_obj(fb), NULL);
-
-	return vma && vma->fence ? vma->fence->id : I915_FENCE_REG_NONE;
-}
-
 static void intel_fbc_update_state_cache(struct intel_crtc *crtc,
 					 struct intel_crtc_state *crtc_state,
 					 struct intel_plane_state *plane_state)
@@ -743,7 +738,8 @@ static void intel_fbc_update_state_cache
 	struct intel_fbc *fbc = &dev_priv->fbc;
 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
 	struct drm_framebuffer *fb = plane_state->base.fb;
-	struct drm_i915_gem_object *obj;
+
+	cache->vma = NULL;
 
 	cache->crtc.mode_flags = crtc_state->base.adjusted_mode.flags;
 	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
@@ -758,16 +754,10 @@ static void intel_fbc_update_state_cache
 	if (!cache->plane.visible)
 		return;
 
-	obj = intel_fb_obj(fb);
-
-	/* FIXME: We lack the proper locking here, so only run this on the
-	 * platforms that need. */
-	if (IS_GEN(dev_priv, 5, 6))
-		cache->fb.ilk_ggtt_offset = i915_gem_object_ggtt_offset(obj, NULL);
 	cache->fb.pixel_format = fb->pixel_format;
 	cache->fb.stride = fb->pitches[0];
-	cache->fb.fence_reg = get_fence_id(fb);
-	cache->fb.tiling_mode = i915_gem_object_get_tiling(obj);
+
+	cache->vma = plane_state->vma;
 }
 
 static bool intel_fbc_can_activate(struct intel_crtc *crtc)
@@ -776,7 +766,15 @@ static bool intel_fbc_can_activate(struc
 	struct intel_fbc *fbc = &dev_priv->fbc;
 	struct intel_fbc_state_cache *cache = &fbc->state_cache;
 
-	if (!cache->plane.visible) {
+	/* We don't need to use a state cache here since this information is
+	 * global for all CRTC.
+	 */
+	if (fbc->underrun_detected) {
+		fbc->no_fbc_reason = "underrun detected";
+		return false;
+	}
+
+	if (!cache->vma) {
 		fbc->no_fbc_reason = "primary plane not visible";
 		return false;
 	}
@@ -799,12 +797,11 @@ static bool intel_fbc_can_activate(struc
 	 * so have no fence associated with it) due to aperture constaints
 	 * at the time of pinning.
 	 */
-	if (cache->fb.tiling_mode != I915_TILING_X ||
-	    cache->fb.fence_reg == I915_FENCE_REG_NONE) {
+	if (!cache->vma->fence) {
 		fbc->no_fbc_reason = "framebuffer not tiled or fenced";
 		return false;
 	}
-	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_G4X(dev_priv) &&
+	if (INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv) &&
 	    cache->plane.rotation != DRM_ROTATE_0) {
 		fbc->no_fbc_reason = "rotation unsupported";
 		return false;
@@ -846,9 +843,8 @@ static bool intel_fbc_can_activate(struc
 	return true;
 }
 
-static bool intel_fbc_can_choose(struct intel_crtc *crtc)
+static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	struct intel_fbc *fbc = &dev_priv->fbc;
 
 	if (intel_vgpu_active(dev_priv)) {
@@ -861,13 +857,8 @@ static bool intel_fbc_can_choose(struct
 		return false;
 	}
 
-	if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) {
-		fbc->no_fbc_reason = "no enabled pipes can have FBC";
-		return false;
-	}
-
-	if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A) {
-		fbc->no_fbc_reason = "no enabled planes can have FBC";
+	if (fbc->underrun_detected) {
+		fbc->no_fbc_reason = "underrun detected";
 		return false;
 	}
 
@@ -886,17 +877,16 @@ static void intel_fbc_get_reg_params(str
 	 * zero. */
 	memset(params, 0, sizeof(*params));
 
+	params->vma = cache->vma;
+
 	params->crtc.pipe = crtc->pipe;
 	params->crtc.plane = crtc->plane;
 	params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc);
 
 	params->fb.pixel_format = cache->fb.pixel_format;
 	params->fb.stride = cache->fb.stride;
-	params->fb.fence_reg = cache->fb.fence_reg;
 
 	params->cfb_size = intel_fbc_calculate_cfb_size(dev_priv, cache);
-
-	params->fb.ggtt_offset = cache->fb.ilk_ggtt_offset;
 }
 
 static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
@@ -1053,23 +1043,19 @@ void intel_fbc_choose_crtc(struct drm_i9
 			   struct drm_atomic_state *state)
 {
 	struct intel_fbc *fbc = &dev_priv->fbc;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
 	struct drm_plane *plane;
 	struct drm_plane_state *plane_state;
-	bool fbc_crtc_present = false;
-	int i, j;
+	bool crtc_chosen = false;
+	int i;
 
 	mutex_lock(&fbc->lock);
 
-	for_each_crtc_in_state(state, crtc, crtc_state, i) {
-		if (fbc->crtc == to_intel_crtc(crtc)) {
-			fbc_crtc_present = true;
-			break;
-		}
-	}
-	/* This atomic commit doesn't involve the CRTC currently tied to FBC. */
-	if (!fbc_crtc_present && fbc->crtc != NULL)
+	/* Does this atomic commit involve the CRTC currently tied to FBC? */
+	if (fbc->crtc &&
+	    !drm_atomic_get_existing_crtc_state(state, &fbc->crtc->base))
+		goto out;
+
+	if (!intel_fbc_can_enable(dev_priv))
 		goto out;
 
 	/* Simply choose the first CRTC that is compatible and has a visible
@@ -1079,25 +1065,29 @@ void intel_fbc_choose_crtc(struct drm_i9
 	for_each_plane_in_state(state, plane, plane_state, i) {
 		struct intel_plane_state *intel_plane_state =
 			to_intel_plane_state(plane_state);
+		struct intel_crtc_state *intel_crtc_state;
+		struct intel_crtc *crtc = to_intel_crtc(plane_state->crtc);
 
 		if (!intel_plane_state->base.visible)
 			continue;
 
-		for_each_crtc_in_state(state, crtc, crtc_state, j) {
-			struct intel_crtc_state *intel_crtc_state =
-				to_intel_crtc_state(crtc_state);
+		if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A)
+			continue;
 
-			if (plane_state->crtc != crtc)
-				continue;
+		if (fbc_on_plane_a_only(dev_priv) && crtc->plane != PLANE_A)
+			continue;
 
-			if (!intel_fbc_can_choose(to_intel_crtc(crtc)))
-				break;
+		intel_crtc_state = to_intel_crtc_state(
+			drm_atomic_get_existing_crtc_state(state, &crtc->base));
 
-			intel_crtc_state->enable_fbc = true;
-			goto out;
-		}
+		intel_crtc_state->enable_fbc = true;
+		crtc_chosen = true;
+		break;
 	}
 
+	if (!crtc_chosen)
+		fbc->no_fbc_reason = "no suitable CRTC for FBC";
+
 out:
 	mutex_unlock(&fbc->lock);
 }
@@ -1223,6 +1213,59 @@ void intel_fbc_global_disable(struct drm
 	cancel_work_sync(&fbc->work.work);
 }
 
+static void intel_fbc_underrun_work_fn(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, struct drm_i915_private, fbc.underrun_work);
+	struct intel_fbc *fbc = &dev_priv->fbc;
+
+	mutex_lock(&fbc->lock);
+
+	/* Maybe we were scheduled twice. */
+	if (fbc->underrun_detected)
+		goto out;
+
+	DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n");
+	fbc->underrun_detected = true;
+
+	intel_fbc_deactivate(dev_priv);
+out:
+	mutex_unlock(&fbc->lock);
+}
+
+/**
+ * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun
+ * @dev_priv: i915 device instance
+ *
+ * Without FBC, most underruns are harmless and don't really cause too many
+ * problems, except for an annoying message on dmesg. With FBC, underruns can
+ * become black screens or even worse, especially when paired with bad
+ * watermarks. So in order for us to be on the safe side, completely disable FBC
+ * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe
+ * already suggests that watermarks may be bad, so try to be as safe as
+ * possible.
+ *
+ * This function is called from the IRQ handler.
+ */
+void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv)
+{
+	struct intel_fbc *fbc = &dev_priv->fbc;
+
+	if (!fbc_supported(dev_priv))
+		return;
+
+	/* There's no guarantee that underrun_detected won't be set to true
+	 * right after this check and before the work is scheduled, but that's
+	 * not a problem since we'll check it again under the work function
+	 * while FBC is locked. This check here is just to prevent us from
+	 * unnecessarily scheduling the work, and it relies on the fact that we
+	 * never switch underrun_detect back to false after it's true. */
+	if (READ_ONCE(fbc->underrun_detected))
+		return;
+
+	schedule_work(&fbc->underrun_work);
+}
+
 /**
  * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking
  * @dev_priv: i915 device instance
@@ -1240,7 +1283,7 @@ void intel_fbc_init_pipe_state(struct dr
 		return;
 
 	for_each_intel_crtc(&dev_priv->drm, crtc)
-		if (intel_crtc_active(&crtc->base) &&
+		if (intel_crtc_active(crtc) &&
 		    to_intel_plane_state(crtc->base.primary->state)->base.visible)
 			dev_priv->fbc.visible_pipes_mask |= (1 << crtc->pipe);
 }
@@ -1294,6 +1337,7 @@ void intel_fbc_init(struct drm_i915_priv
 	enum pipe pipe;
 
 	INIT_WORK(&fbc->work.work, intel_fbc_work_fn);
+	INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn);
 	mutex_init(&fbc->lock);
 	fbc->enabled = false;
 	fbc->active = false;
@@ -1319,7 +1363,7 @@ void intel_fbc_init(struct drm_i915_priv
 	}
 
 	/* This value was pulled out of someone's hat */
-	if (INTEL_INFO(dev_priv)->gen <= 4 && !IS_GM45(dev_priv))
+	if (INTEL_GEN(dev_priv) <= 4 && !IS_GM45(dev_priv))
 		I915_WRITE(FBC_CONTROL, 500 << FBC_CTL_INTERVAL_SHIFT);
 
 	/* We still don't have any sort of hardware state readout for FBC, so
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,16 +102,13 @@ static int intel_fbdev_pan_display(struc
 
 static struct fb_ops intelfb_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_set_par = intel_fbdev_set_par,
 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
 	.fb_pan_display = intel_fbdev_pan_display,
 	.fb_blank = intel_fbdev_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 static int intelfb_alloc(struct drm_fb_helper *helper,
@@ -287,7 +284,7 @@ static int intelfb_create(struct drm_fb_
 out_destroy_fbi:
 	drm_fb_helper_release_fbi(helper);
 out_unpin:
-	intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0);
+	intel_unpin_fb_vma(vma);
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);
 	return ret;
@@ -359,7 +356,7 @@ static bool intel_fb_initial_config(stru
 				    struct drm_fb_offset *offsets,
 				    bool *enabled, int width, int height)
 {
-	struct drm_device *dev = fb_helper->dev;
+	struct drm_i915_private *dev_priv = to_i915(fb_helper->dev);
 	unsigned long conn_configured, mask;
 	unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
 	int i, j;
@@ -512,7 +509,7 @@ retry:
 	 * fbdev helper library.
 	 */
 	if (num_connectors_enabled != num_connectors_detected &&
-	    num_connectors_enabled < INTEL_INFO(dev)->num_pipes) {
+	    num_connectors_enabled < INTEL_INFO(dev_priv)->num_pipes) {
 		DRM_DEBUG_KMS("fallback: Not all outputs enabled\n");
 		DRM_DEBUG_KMS("Enabled: %i, detected: %i\n", num_connectors_enabled,
 			      num_connectors_detected);
@@ -552,7 +549,7 @@ static void intel_fbdev_destroy(struct i
 
 	if (ifbdev->fb) {
 		mutex_lock(&ifbdev->helper.dev->struct_mutex);
-		intel_unpin_fb_obj(&ifbdev->fb->base, DRM_ROTATE_0);
+		intel_unpin_fb_vma(ifbdev->vma);
 		mutex_unlock(&ifbdev->helper.dev->struct_mutex);
 
 		drm_framebuffer_remove(&ifbdev->fb->base);
@@ -636,7 +633,7 @@ static bool intel_fbdev_init_bios(struct
 		cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay;
 		cur_size = intel_fb_align_height(dev, cur_size,
 						 fb->base.pixel_format,
-						 fb->base.modifier[0]);
+						 fb->base.modifier);
 		cur_size *= fb->base.pitches[0];
 		DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
 			      pipe_name(intel_crtc->pipe),
@@ -700,11 +697,11 @@ static void intel_fbdev_suspend_worker(s
 
 int intel_fbdev_init(struct drm_device *dev)
 {
-	struct intel_fbdev *ifbdev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct intel_fbdev *ifbdev;
 	int ret;
 
-	if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0))
+	if (WARN_ON(INTEL_INFO(dev_priv)->num_pipes == 0))
 		return -ENODEV;
 
 	ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
@@ -717,7 +714,7 @@ int intel_fbdev_init(struct drm_device *
 		ifbdev->preferred_bpp = 32;
 
 	ret = drm_fb_helper_init(dev, &ifbdev->helper,
-				 INTEL_INFO(dev)->num_pipes, 4);
+				 INTEL_INFO(dev_priv)->num_pipes, 4);
 	if (ret) {
 		kfree(ifbdev);
 		return ret;
@@ -745,6 +742,9 @@ void intel_fbdev_initial_config_async(st
 {
 	struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
 
+	if (!ifbdev)
+		return;
+
 	ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_fifo_underrun.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@ static bool ivb_can_enable_err_int(struc
 	assert_spin_locked(&dev_priv->irq_lock);
 
 	for_each_pipe(dev_priv, pipe) {
-		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+		crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 
 		if (crtc->cpu_fifo_underrun_disabled)
 			return false;
@@ -75,7 +75,7 @@ static bool cpt_can_enable_serr_int(stru
 	assert_spin_locked(&dev_priv->irq_lock);
 
 	for_each_pipe(dev_priv, pipe) {
-		crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
+		crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 
 		if (crtc->pch_fifo_underrun_disabled)
 			return false;
@@ -245,22 +245,21 @@ static bool __intel_set_cpu_fifo_underru
 						    enum pipe pipe, bool enable)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 	bool old;
 
 	assert_spin_locked(&dev_priv->irq_lock);
 
-	old = !intel_crtc->cpu_fifo_underrun_disabled;
-	intel_crtc->cpu_fifo_underrun_disabled = !enable;
+	old = !crtc->cpu_fifo_underrun_disabled;
+	crtc->cpu_fifo_underrun_disabled = !enable;
 
-	if (HAS_GMCH_DISPLAY(dev))
+	if (HAS_GMCH_DISPLAY(dev_priv))
 		i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
-	else if (IS_GEN5(dev) || IS_GEN6(dev))
+	else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv))
 		ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
-	else if (IS_GEN7(dev))
+	else if (IS_GEN7(dev_priv))
 		ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
-	else if (IS_GEN8(dev) || IS_GEN9(dev))
+	else if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv))
 		broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
 
 	return old;
@@ -314,8 +313,8 @@ bool intel_set_pch_fifo_underrun_reporti
 					   enum transcoder pch_transcoder,
 					   bool enable)
 {
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	struct intel_crtc *crtc =
+		intel_get_crtc_for_pipe(dev_priv, (enum pipe) pch_transcoder);
 	unsigned long flags;
 	bool old;
 
@@ -330,8 +329,8 @@ bool intel_set_pch_fifo_underrun_reporti
 
 	spin_lock_irqsave(&dev_priv->irq_lock, flags);
 
-	old = !intel_crtc->pch_fifo_underrun_disabled;
-	intel_crtc->pch_fifo_underrun_disabled = !enable;
+	old = !crtc->pch_fifo_underrun_disabled;
+	crtc->pch_fifo_underrun_disabled = !enable;
 
 	if (HAS_PCH_IBX(dev_priv))
 		ibx_set_fifo_underrun_reporting(&dev_priv->drm,
@@ -358,7 +357,7 @@ bool intel_set_pch_fifo_underrun_reporti
 void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
 					 enum pipe pipe)
 {
-	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 
 	/* We may be called too early in init, thanks BIOS! */
 	if (crtc == NULL)
@@ -366,12 +365,14 @@ void intel_cpu_fifo_underrun_irq_handler
 
 	/* GMCH can't disable fifo underruns, filter them. */
 	if (HAS_GMCH_DISPLAY(dev_priv) &&
-	    to_intel_crtc(crtc)->cpu_fifo_underrun_disabled)
+	    crtc->cpu_fifo_underrun_disabled)
 		return;
 
 	if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false))
 		DRM_ERROR("CPU pipe %c FIFO underrun\n",
 			  pipe_name(pipe));
+
+	intel_fbc_handle_fifo_underrun_irq(dev_priv);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_frontbuffer.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_frontbuffer.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_frontbuffer.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_frontbuffer.h	2017-02-12 16:03:20.000000000 -0500
@@ -53,16 +53,17 @@ void __intel_fb_obj_flush(struct drm_i91
  * until the rendering completes or a flip on this frontbuffer plane is
  * scheduled.
  */
-static inline void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
+static inline bool intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
 					   enum fb_op_origin origin)
 {
 	unsigned int frontbuffer_bits;
 
 	frontbuffer_bits = atomic_read(&obj->frontbuffer_bits);
 	if (!frontbuffer_bits)
-		return;
+		return false;
 
 	__intel_fb_obj_invalidate(obj, origin, frontbuffer_bits);
+	return true;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_guc_fwif.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_guc_fwif.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_guc_fwif.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_guc_fwif.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,9 +104,9 @@
 #define   GUC_LOG_ALLOC_IN_MEGABYTE	(1 << 3)
 #define   GUC_LOG_CRASH_PAGES		1
 #define   GUC_LOG_CRASH_SHIFT		4
-#define   GUC_LOG_DPC_PAGES		3
+#define   GUC_LOG_DPC_PAGES		7
 #define   GUC_LOG_DPC_SHIFT		6
-#define   GUC_LOG_ISR_PAGES		3
+#define   GUC_LOG_ISR_PAGES		7
 #define   GUC_LOG_ISR_SHIFT		9
 #define   GUC_LOG_BUF_ADDR_SHIFT	12
 
@@ -419,15 +419,87 @@ struct guc_ads {
 	u32 reserved2[4];
 } __packed;
 
+/* GuC logging structures */
+
+enum guc_log_buffer_type {
+	GUC_ISR_LOG_BUFFER,
+	GUC_DPC_LOG_BUFFER,
+	GUC_CRASH_DUMP_LOG_BUFFER,
+	GUC_MAX_LOG_BUFFER
+};
+
+/**
+ * DOC: GuC Log buffer Layout
+ *
+ * Page0  +-------------------------------+
+ *        |   ISR state header (32 bytes) |
+ *        |      DPC state header         |
+ *        |   Crash dump state header     |
+ * Page1  +-------------------------------+
+ *        |           ISR logs            |
+ * Page9  +-------------------------------+
+ *        |           DPC logs            |
+ * Page17 +-------------------------------+
+ *        |         Crash Dump logs       |
+ *        +-------------------------------+
+ *
+ * Below state structure is used for coordination of retrieval of GuC firmware
+ * logs. Separate state is maintained for each log buffer type.
+ * read_ptr points to the location where i915 read last in log buffer and
+ * is read only for GuC firmware. write_ptr is incremented by GuC with number
+ * of bytes written for each log entry and is read only for i915.
+ * When any type of log buffer becomes half full, GuC sends a flush interrupt.
+ * GuC firmware expects that while it is writing to 2nd half of the buffer,
+ * first half would get consumed by Host and then get a flush completed
+ * acknowledgment from Host, so that it does not end up doing any overwrite
+ * causing loss of logs. So when buffer gets half filled & i915 has requested
+ * for interrupt, GuC will set flush_to_file field, set the sampled_write_ptr
+ * to the value of write_ptr and raise the interrupt.
+ * On receiving the interrupt i915 should read the buffer, clear flush_to_file
+ * field and also update read_ptr with the value of sample_write_ptr, before
+ * sending an acknowledgment to GuC. marker & version fields are for internal
+ * usage of GuC and opaque to i915. buffer_full_cnt field is incremented every
+ * time GuC detects the log buffer overflow.
+ */
+struct guc_log_buffer_state {
+	u32 marker[2];
+	u32 read_ptr;
+	u32 write_ptr;
+	u32 size;
+	u32 sampled_write_ptr;
+	union {
+		struct {
+			u32 flush_to_file:1;
+			u32 buffer_full_cnt:4;
+			u32 reserved:27;
+		};
+		u32 flags;
+	};
+	u32 version;
+} __packed;
+
+union guc_log_control {
+	struct {
+		u32 logging_enabled:1;
+		u32 reserved1:3;
+		u32 verbosity:4;
+		u32 reserved2:24;
+	};
+	u32 value;
+} __packed;
+
 /* This Action will be programmed in C180 - SOFT_SCRATCH_O_REG */
 enum host2guc_action {
 	HOST2GUC_ACTION_DEFAULT = 0x0,
 	HOST2GUC_ACTION_SAMPLE_FORCEWAKE = 0x6,
 	HOST2GUC_ACTION_ALLOCATE_DOORBELL = 0x10,
 	HOST2GUC_ACTION_DEALLOCATE_DOORBELL = 0x20,
+	HOST2GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE = 0x30,
+	HOST2GUC_ACTION_FORCE_LOG_BUFFER_FLUSH = 0x302,
 	HOST2GUC_ACTION_ENTER_S_STATE = 0x501,
 	HOST2GUC_ACTION_EXIT_S_STATE = 0x502,
 	HOST2GUC_ACTION_SLPC_REQUEST = 0x3003,
+	HOST2GUC_ACTION_UK_LOG_ENABLE_LOGGING = 0x0E000,
 	HOST2GUC_ACTION_LIMIT
 };
 
@@ -449,4 +521,10 @@ enum guc2host_status {
 	GUC2HOST_STATUS_GENERIC_FAIL = GUC2HOST_STATUS(0x0000F000)
 };
 
+/* This action will be programmed in C1BC - SOFT_SCRATCH_15_REG */
+enum guc2host_message {
+	GUC2HOST_MSG_CRASH_DUMP_POSTED = (1 << 1),
+	GUC2HOST_MSG_FLUSH_LOG_BUFFER = (1 << 3)
+};
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_guc.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_guc.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_guc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_guc.h	2017-02-12 16:03:20.000000000 -0500
@@ -64,7 +64,7 @@ struct drm_i915_gem_request;
  */
 struct i915_guc_client {
 	struct i915_vma *vma;
-	void *client_base;		/* first page (only) of above	*/
+	void *vaddr;
 	struct i915_gem_context *owner;
 	struct intel_guc *guc;
 
@@ -123,10 +123,28 @@ struct intel_guc_fw {
 	uint32_t ucode_offset;
 };
 
+struct intel_guc_log {
+	uint32_t flags;
+	struct i915_vma *vma;
+	void *buf_addr;
+	struct workqueue_struct *flush_wq;
+	struct work_struct flush_work;
+	struct rchan *relay_chan;
+
+	/* logging related stats */
+	u32 capture_miss_count;
+	u32 flush_interrupt_count;
+	u32 prev_overflow_count[GUC_MAX_LOG_BUFFER];
+	u32 total_overflow_count[GUC_MAX_LOG_BUFFER];
+	u32 flush_count[GUC_MAX_LOG_BUFFER];
+};
+
 struct intel_guc {
 	struct intel_guc_fw guc_fw;
-	uint32_t log_flags;
-	struct i915_vma *log_vma;
+	struct intel_guc_log log;
+
+	/* GuC2Host interrupt related state */
+	bool interrupts_enabled;
 
 	struct i915_vma *ads_vma;
 	struct i915_vma *ctx_pool_vma;
@@ -146,6 +164,9 @@ struct intel_guc {
 
 	uint64_t submissions[I915_NUM_ENGINES];
 	uint32_t last_seqno[I915_NUM_ENGINES];
+
+	/* To serialize the Host2GuC actions */
+	struct mutex action_lock;
 };
 
 /* intel_guc_loader.c */
@@ -163,5 +184,10 @@ int i915_guc_wq_reserve(struct drm_i915_
 void i915_guc_wq_unreserve(struct drm_i915_gem_request *request);
 void i915_guc_submission_disable(struct drm_i915_private *dev_priv);
 void i915_guc_submission_fini(struct drm_i915_private *dev_priv);
+void i915_guc_capture_logs(struct drm_i915_private *dev_priv);
+void i915_guc_flush_logs(struct drm_i915_private *dev_priv);
+void i915_guc_register(struct drm_i915_private *dev_priv);
+void i915_guc_unregister(struct drm_i915_private *dev_priv);
+int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_guc_loader.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_guc_loader.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_guc_loader.c	2016-12-11 17:42:04.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_guc_loader.c	2017-02-12 17:25:19.000000000 -0500
@@ -100,12 +100,13 @@ const char *intel_guc_fw_status_repr(enu
 static void guc_interrupts_release(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int irqs;
 
 	/* tell all command streamers NOT to forward interrupts or vblank to GuC */
 	irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER);
 	irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING);
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		I915_WRITE(RING_MODE_GEN7(engine), irqs);
 
 	/* route all GT interrupts to the host */
@@ -117,12 +118,13 @@ static void guc_interrupts_release(struc
 static void guc_interrupts_capture(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	int irqs;
 	u32 tmp;
 
 	/* tell all command streamers to forward interrupts (but not vblank) to GuC */
 	irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING);
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		I915_WRITE(RING_MODE_GEN7(engine), irqs);
 
 	/* route USER_INTERRUPT to Host, all others are sent to GuC. */
@@ -209,11 +211,13 @@ static void guc_params_init(struct drm_i
 	params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER |
 			GUC_CTL_VCS2_ENABLED;
 
+	params[GUC_CTL_LOG_PARAMS] = guc->log.flags;
+
 	if (i915.guc_log_level >= 0) {
-		params[GUC_CTL_LOG_PARAMS] = guc->log_flags;
 		params[GUC_CTL_DEBUG] =
 			i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT;
-	}
+	} else
+		params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED;
 
 	if (guc->ads_vma) {
 		u32 ads = i915_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT;
@@ -347,7 +351,6 @@ static u32 guc_wopcm_size(struct drm_i91
 static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
 {
 	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
-	struct drm_device *dev = &dev_priv->drm;
 	struct i915_vma *vma;
 	int ret;
 
@@ -375,24 +378,22 @@ static int guc_ucode_xfer(struct drm_i91
 	/* Enable MIA caching. GuC clock gating is disabled. */
 	I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE);
 
-	/* WaDisableMinuteIaClockGating:skl,bxt */
-	if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) ||
-	    IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
+	/* WaDisableMinuteIaClockGating:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
 		I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) &
 					      ~GUC_ENABLE_MIA_CLOCK_GATING));
 	}
 
-	/* WaC6DisallowByGfxPause*/
-	if (IS_SKL_REVID(dev, 0, SKL_REVID_C0) ||
-	    IS_BXT_REVID(dev, 0, BXT_REVID_B0))
+	/* WaC6DisallowByGfxPause:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0))
 		I915_WRITE(GEN6_GFXPAUSE, 0x30FFF);
 
-	if (IS_BROXTON(dev))
+	if (IS_BROXTON(dev_priv))
 		I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE);
 	else
 		I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE);
 
-	if (IS_GEN9(dev)) {
+	if (IS_GEN9(dev_priv)) {
 		/* DOP Clock Gating Enable for GuC clocks */
 		I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE |
 					    I915_READ(GEN7_MISCCPCTL)));
@@ -484,6 +485,7 @@ int intel_guc_setup(struct drm_device *d
 	}
 
 	guc_interrupts_release(dev_priv);
+	gen9_reset_guc_interrupts(dev_priv);
 
 	guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
 
@@ -528,6 +530,9 @@ int intel_guc_setup(struct drm_device *d
 		intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
 
 	if (i915.enable_guc_submission) {
+		if (i915.guc_log_level >= 0)
+			gen9_enable_guc_interrupts(dev_priv);
+
 		err = i915_guc_submission_enable(dev_priv);
 		if (err)
 			goto fail;
@@ -561,7 +566,7 @@ fail:
 		ret = 0;
 	}
 
-	if (err == 0 && !HAS_GUC_UCODE(dev))
+	if (err == 0 && !HAS_GUC_UCODE(dev_priv))
 		;	/* Don't mention the GuC! */
 	else if (err == 0)
 		DRM_INFO("GuC firmware load skipped\n");
@@ -720,23 +725,28 @@ void intel_guc_init(struct drm_device *d
 	struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
 	const char *fw_path;
 
-	/* A negative value means "use platform default" */
-	if (i915.enable_guc_loading < 0)
-		i915.enable_guc_loading = HAS_GUC_UCODE(dev);
-	if (i915.enable_guc_submission < 0)
-		i915.enable_guc_submission = HAS_GUC_SCHED(dev);
+	if (!HAS_GUC(dev_priv)) {
+		i915.enable_guc_loading = 0;
+		i915.enable_guc_submission = 0;
+	} else {
+		/* A negative value means "use platform default" */
+		if (i915.enable_guc_loading < 0)
+			i915.enable_guc_loading = HAS_GUC_UCODE(dev_priv);
+		if (i915.enable_guc_submission < 0)
+			i915.enable_guc_submission = HAS_GUC_SCHED(dev_priv);
+	}
 
-	if (!HAS_GUC_UCODE(dev)) {
+	if (!HAS_GUC_UCODE(dev_priv)) {
 		fw_path = NULL;
-	} else if (IS_SKYLAKE(dev)) {
+	} else if (IS_SKYLAKE(dev_priv)) {
 		fw_path = I915_SKL_GUC_UCODE;
 		guc_fw->guc_fw_major_wanted = SKL_FW_MAJOR;
 		guc_fw->guc_fw_minor_wanted = SKL_FW_MINOR;
-	} else if (IS_BROXTON(dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		fw_path = I915_BXT_GUC_UCODE;
 		guc_fw->guc_fw_major_wanted = BXT_FW_MAJOR;
 		guc_fw->guc_fw_minor_wanted = BXT_FW_MINOR;
-	} else if (IS_KABYLAKE(dev)) {
+	} else if (IS_KABYLAKE(dev_priv)) {
 		fw_path = I915_KBL_GUC_UCODE;
 		guc_fw->guc_fw_major_wanted = KBL_FW_MAJOR;
 		guc_fw->guc_fw_minor_wanted = KBL_FW_MINOR;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_gvt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_gvt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_gvt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_gvt.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,14 +31,20 @@
  * GPU among multiple virtual machines on a time-sharing basis. Each
  * virtual machine is presented a virtual GPU (vGPU), which has equivalent
  * features as the underlying physical GPU (pGPU), so i915 driver can run
- * seamlessly in a virtual machine. This file provides the englightments
- * of GVT and the necessary components used by GVT in i915 driver.
+ * seamlessly in a virtual machine.
+ *
+ * To virtualize GPU resources GVT-g driver depends on hypervisor technology
+ * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability
+ * and be virtualized within GVT-g device module. More architectural design
+ * doc is available on https://01.org/group/2230/documentation-list.
  */
 
 static bool is_supported_device(struct drm_i915_private *dev_priv)
 {
 	if (IS_BROADWELL(dev_priv))
 		return true;
+	if (IS_SKYLAKE(dev_priv))
+		return true;
 	return false;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_gvt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_gvt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_gvt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_gvt.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #ifndef _INTEL_GVT_H_
 #define _INTEL_GVT_H_
 
-#include "gvt/gvt.h"
+struct intel_gvt;
 
 #ifdef CONFIG_DRM_I915_GVT
 int intel_gvt_init(struct drm_i915_private *dev_priv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_hangcheck.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_hangcheck.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_hangcheck.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_hangcheck.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,450 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "i915_drv.h"
+
+static bool
+ipehr_is_semaphore_wait(struct intel_engine_cs *engine, u32 ipehr)
+{
+	if (INTEL_GEN(engine->i915) >= 8) {
+		return (ipehr >> 23) == 0x1c;
+	} else {
+		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
+		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
+				 MI_SEMAPHORE_REGISTER);
+	}
+}
+
+static struct intel_engine_cs *
+semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
+				 u64 offset)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	struct intel_engine_cs *signaller;
+	enum intel_engine_id id;
+
+	if (INTEL_GEN(dev_priv) >= 8) {
+		for_each_engine(signaller, dev_priv, id) {
+			if (engine == signaller)
+				continue;
+
+			if (offset == signaller->semaphore.signal_ggtt[engine->hw_id])
+				return signaller;
+		}
+	} else {
+		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
+
+		for_each_engine(signaller, dev_priv, id) {
+			if(engine == signaller)
+				continue;
+
+			if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id])
+				return signaller;
+		}
+	}
+
+	DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n",
+			 engine->name, ipehr, offset);
+
+	return ERR_PTR(-ENODEV);
+}
+
+static struct intel_engine_cs *
+semaphore_waits_for(struct intel_engine_cs *engine, u32 *seqno)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	void __iomem *vaddr;
+	u32 cmd, ipehr, head;
+	u64 offset = 0;
+	int i, backwards;
+
+	/*
+	 * This function does not support execlist mode - any attempt to
+	 * proceed further into this function will result in a kernel panic
+	 * when dereferencing ring->buffer, which is not set up in execlist
+	 * mode.
+	 *
+	 * The correct way of doing it would be to derive the currently
+	 * executing ring buffer from the current context, which is derived
+	 * from the currently running request. Unfortunately, to get the
+	 * current request we would have to grab the struct_mutex before doing
+	 * anything else, which would be ill-advised since some other thread
+	 * might have grabbed it already and managed to hang itself, causing
+	 * the hang checker to deadlock.
+	 *
+	 * Therefore, this function does not support execlist mode in its
+	 * current form. Just return NULL and move on.
+	 */
+	if (engine->buffer == NULL)
+		return NULL;
+
+	ipehr = I915_READ(RING_IPEHR(engine->mmio_base));
+	if (!ipehr_is_semaphore_wait(engine, ipehr))
+		return NULL;
+
+	/*
+	 * HEAD is likely pointing to the dword after the actual command,
+	 * so scan backwards until we find the MBOX. But limit it to just 3
+	 * or 4 dwords depending on the semaphore wait command size.
+	 * Note that we don't care about ACTHD here since that might
+	 * point at at batch, and semaphores are always emitted into the
+	 * ringbuffer itself.
+	 */
+	head = I915_READ_HEAD(engine) & HEAD_ADDR;
+	backwards = (INTEL_GEN(dev_priv) >= 8) ? 5 : 4;
+	vaddr = (void __iomem *)engine->buffer->vaddr;
+
+	for (i = backwards; i; --i) {
+		/*
+		 * Be paranoid and presume the hw has gone off into the wild -
+		 * our ring is smaller than what the hardware (and hence
+		 * HEAD_ADDR) allows. Also handles wrap-around.
+		 */
+		head &= engine->buffer->size - 1;
+
+		/* This here seems to blow up */
+		cmd = ioread32(vaddr + head);
+		if (cmd == ipehr)
+			break;
+
+		head -= 4;
+	}
+
+	if (!i)
+		return NULL;
+
+	*seqno = ioread32(vaddr + head + 4) + 1;
+	if (INTEL_GEN(dev_priv) >= 8) {
+		offset = ioread32(vaddr + head + 12);
+		offset <<= 32;
+		offset |= ioread32(vaddr + head + 8);
+	}
+	return semaphore_wait_to_signaller_ring(engine, ipehr, offset);
+}
+
+static int semaphore_passed(struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	struct intel_engine_cs *signaller;
+	u32 seqno;
+
+	engine->hangcheck.deadlock++;
+
+	signaller = semaphore_waits_for(engine, &seqno);
+	if (signaller == NULL)
+		return -1;
+
+	if (IS_ERR(signaller))
+		return 0;
+
+	/* Prevent pathological recursion due to driver bugs */
+	if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
+		return -1;
+
+	if (i915_seqno_passed(intel_engine_get_seqno(signaller), seqno))
+		return 1;
+
+	/* cursory check for an unkickable deadlock */
+	if (I915_READ_CTL(signaller) & RING_WAIT_SEMAPHORE &&
+	    semaphore_passed(signaller) < 0)
+		return -1;
+
+	return 0;
+}
+
+static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
+{
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	for_each_engine(engine, dev_priv, id)
+		engine->hangcheck.deadlock = 0;
+}
+
+static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone)
+{
+	u32 tmp = current_instdone | *old_instdone;
+	bool unchanged;
+
+	unchanged = tmp == *old_instdone;
+	*old_instdone |= tmp;
+
+	return unchanged;
+}
+
+static bool subunits_stuck(struct intel_engine_cs *engine)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	struct intel_instdone instdone;
+	struct intel_instdone *accu_instdone = &engine->hangcheck.instdone;
+	bool stuck;
+	int slice;
+	int subslice;
+
+	if (engine->id != RCS)
+		return true;
+
+	intel_engine_get_instdone(engine, &instdone);
+
+	/* There might be unstable subunit states even when
+	 * actual head is not moving. Filter out the unstable ones by
+	 * accumulating the undone -> done transitions and only
+	 * consider those as progress.
+	 */
+	stuck = instdone_unchanged(instdone.instdone,
+				   &accu_instdone->instdone);
+	stuck &= instdone_unchanged(instdone.slice_common,
+				    &accu_instdone->slice_common);
+
+	for_each_instdone_slice_subslice(dev_priv, slice, subslice) {
+		stuck &= instdone_unchanged(instdone.sampler[slice][subslice],
+					    &accu_instdone->sampler[slice][subslice]);
+		stuck &= instdone_unchanged(instdone.row[slice][subslice],
+					    &accu_instdone->row[slice][subslice]);
+	}
+
+	return stuck;
+}
+
+static enum intel_engine_hangcheck_action
+head_stuck(struct intel_engine_cs *engine, u64 acthd)
+{
+	if (acthd != engine->hangcheck.acthd) {
+
+		/* Clear subunit states on head movement */
+		memset(&engine->hangcheck.instdone, 0,
+		       sizeof(engine->hangcheck.instdone));
+
+		return HANGCHECK_ACTIVE;
+	}
+
+	if (!subunits_stuck(engine))
+		return HANGCHECK_ACTIVE;
+
+	return HANGCHECK_HUNG;
+}
+
+static enum intel_engine_hangcheck_action
+engine_stuck(struct intel_engine_cs *engine, u64 acthd)
+{
+	struct drm_i915_private *dev_priv = engine->i915;
+	enum intel_engine_hangcheck_action ha;
+	u32 tmp;
+
+	ha = head_stuck(engine, acthd);
+	if (ha != HANGCHECK_HUNG)
+		return ha;
+
+	if (IS_GEN2(dev_priv))
+		return HANGCHECK_HUNG;
+
+	/* Is the chip hanging on a WAIT_FOR_EVENT?
+	 * If so we can simply poke the RB_WAIT bit
+	 * and break the hang. This should work on
+	 * all but the second generation chipsets.
+	 */
+	tmp = I915_READ_CTL(engine);
+	if (tmp & RING_WAIT) {
+		i915_handle_error(dev_priv, 0,
+				  "Kicking stuck wait on %s",
+				  engine->name);
+		I915_WRITE_CTL(engine, tmp);
+		return HANGCHECK_KICK;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 6 && tmp & RING_WAIT_SEMAPHORE) {
+		switch (semaphore_passed(engine)) {
+		default:
+			return HANGCHECK_HUNG;
+		case 1:
+			i915_handle_error(dev_priv, 0,
+					  "Kicking stuck semaphore on %s",
+					  engine->name);
+			I915_WRITE_CTL(engine, tmp);
+			return HANGCHECK_KICK;
+		case 0:
+			return HANGCHECK_WAIT;
+		}
+	}
+
+	return HANGCHECK_HUNG;
+}
+
+/*
+ * This is called when the chip hasn't reported back with completed
+ * batchbuffers in a long time. We keep track per ring seqno progress and
+ * if there are no progress, hangcheck score for that ring is increased.
+ * Further, acthd is inspected to see if the ring is stuck. On stuck case
+ * we kick the ring. If we see no progress on three subsequent calls
+ * we assume chip is wedged and try to fix it by resetting the chip.
+ */
+static void i915_hangcheck_elapsed(struct work_struct *work)
+{
+	struct drm_i915_private *dev_priv =
+		container_of(work, typeof(*dev_priv),
+			     gpu_error.hangcheck_work.work);
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+	unsigned int hung = 0, stuck = 0;
+	int busy_count = 0;
+#define BUSY 1
+#define KICK 5
+#define HUNG 20
+#define ACTIVE_DECAY 15
+
+	if (!i915.enable_hangcheck)
+		return;
+
+	if (!READ_ONCE(dev_priv->gt.awake))
+		return;
+
+	/* As enabling the GPU requires fairly extensive mmio access,
+	 * periodically arm the mmio checker to see if we are triggering
+	 * any invalid access.
+	 */
+	intel_uncore_arm_unclaimed_mmio_detection(dev_priv);
+
+	for_each_engine(engine, dev_priv, id) {
+		bool busy = intel_engine_has_waiter(engine);
+		u64 acthd;
+		u32 seqno;
+		u32 submit;
+
+		semaphore_clear_deadlocks(dev_priv);
+
+		/* We don't strictly need an irq-barrier here, as we are not
+		 * serving an interrupt request, be paranoid in case the
+		 * barrier has side-effects (such as preventing a broken
+		 * cacheline snoop) and so be sure that we can see the seqno
+		 * advance. If the seqno should stick, due to a stale
+		 * cacheline, we would erroneously declare the GPU hung.
+		 */
+		if (engine->irq_seqno_barrier)
+			engine->irq_seqno_barrier(engine);
+
+		acthd = intel_engine_get_active_head(engine);
+		seqno = intel_engine_get_seqno(engine);
+		submit = intel_engine_last_submit(engine);
+
+		if (engine->hangcheck.seqno == seqno) {
+			if (i915_seqno_passed(seqno, submit)) {
+				engine->hangcheck.action = HANGCHECK_IDLE;
+			} else {
+				/* We always increment the hangcheck score
+				 * if the engine is busy and still processing
+				 * the same request, so that no single request
+				 * can run indefinitely (such as a chain of
+				 * batches). The only time we do not increment
+				 * the hangcheck score on this ring, if this
+				 * engine is in a legitimate wait for another
+				 * engine. In that case the waiting engine is a
+				 * victim and we want to be sure we catch the
+				 * right culprit. Then every time we do kick
+				 * the ring, add a small increment to the
+				 * score so that we can catch a batch that is
+				 * being repeatedly kicked and so responsible
+				 * for stalling the machine.
+				 */
+				engine->hangcheck.action =
+					engine_stuck(engine, acthd);
+
+				switch (engine->hangcheck.action) {
+				case HANGCHECK_IDLE:
+				case HANGCHECK_WAIT:
+					break;
+				case HANGCHECK_ACTIVE:
+					engine->hangcheck.score += BUSY;
+					break;
+				case HANGCHECK_KICK:
+					engine->hangcheck.score += KICK;
+					break;
+				case HANGCHECK_HUNG:
+					engine->hangcheck.score += HUNG;
+					break;
+				}
+			}
+
+			if (engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG) {
+				hung |= intel_engine_flag(engine);
+				if (engine->hangcheck.action != HANGCHECK_HUNG)
+					stuck |= intel_engine_flag(engine);
+			}
+		} else {
+			engine->hangcheck.action = HANGCHECK_ACTIVE;
+
+			/* Gradually reduce the count so that we catch DoS
+			 * attempts across multiple batches.
+			 */
+			if (engine->hangcheck.score > 0)
+				engine->hangcheck.score -= ACTIVE_DECAY;
+			if (engine->hangcheck.score < 0)
+				engine->hangcheck.score = 0;
+
+			/* Clear head and subunit states on seqno movement */
+			acthd = 0;
+
+			memset(&engine->hangcheck.instdone, 0,
+			       sizeof(engine->hangcheck.instdone));
+		}
+
+		engine->hangcheck.seqno = seqno;
+		engine->hangcheck.acthd = acthd;
+		busy_count += busy;
+	}
+
+	if (hung) {
+		char msg[80];
+		unsigned int tmp;
+		int len;
+
+		/* If some rings hung but others were still busy, only
+		 * blame the hanging rings in the synopsis.
+		 */
+		if (stuck != hung)
+			hung &= ~stuck;
+		len = scnprintf(msg, sizeof(msg),
+				"%s on ", stuck == hung ? "No progress" : "Hang");
+		for_each_engine_masked(engine, dev_priv, hung, tmp)
+			len += scnprintf(msg + len, sizeof(msg) - len,
+					 "%s, ", engine->name);
+		msg[len-2] = '\0';
+
+		return i915_handle_error(dev_priv, hung, msg);
+	}
+
+	/* Reset timer in case GPU hangs without another request being added */
+	if (busy_count)
+		i915_queue_hangcheck(dev_priv);
+}
+
+void intel_engine_init_hangcheck(struct intel_engine_cs *engine)
+{
+	memset(&engine->hangcheck, 0, sizeof(engine->hangcheck));
+}
+
+void intel_hangcheck_init(struct drm_i915_private *i915)
+{
+	INIT_DELAYED_WORK(&i915->gpu_error.hangcheck_work,
+			  i915_hangcheck_elapsed);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,7 +50,7 @@ assert_hdmi_port_disabled(struct intel_h
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t enabled_bits;
 
-	enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
+	enabled_bits = HAS_DDI(dev_priv) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;
 
 	WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits,
 	     "HDMI port enabled, expecting disabled\n");
@@ -864,7 +864,7 @@ static void intel_hdmi_prepare(struct in
 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
 
 	hdmi_val = SDVO_ENCODING_HDMI;
-	if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range)
+	if (!HAS_PCH_SPLIT(dev_priv) && crtc->config->limited_color_range)
 		hdmi_val |= HDMI_COLOR_RANGE_16_235;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH;
@@ -879,9 +879,9 @@ static void intel_hdmi_prepare(struct in
 	if (crtc->config->has_hdmi_sink)
 		hdmi_val |= HDMI_MODE_SELECT_HDMI;
 
-	if (HAS_PCH_CPT(dev))
+	if (HAS_PCH_CPT(dev_priv))
 		hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe);
-	else if (IS_CHERRYVIEW(dev))
+	else if (IS_CHERRYVIEW(dev_priv))
 		hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe);
 	else
 		hdmi_val |= SDVO_PIPE_SEL(crtc->pipe);
@@ -911,9 +911,9 @@ static bool intel_hdmi_get_hw_state(stru
 	if (!(tmp & SDVO_ENABLE))
 		goto out;
 
-	if (HAS_PCH_CPT(dev))
+	if (HAS_PCH_CPT(dev_priv))
 		*pipe = PORT_TO_PIPE_CPT(tmp);
-	else if (IS_CHERRYVIEW(dev))
+	else if (IS_CHERRYVIEW(dev_priv))
 		*pipe = SDVO_PORT_TO_PIPE_CHV(tmp);
 	else
 		*pipe = PORT_TO_PIPE(tmp);
@@ -956,7 +956,7 @@ static void intel_hdmi_get_config(struct
 	if (tmp & SDVO_AUDIO_ENABLE)
 		pipe_config->has_audio = true;
 
-	if (!HAS_PCH_SPLIT(dev) &&
+	if (!HAS_PCH_SPLIT(dev_priv) &&
 	    tmp & HDMI_COLOR_RANGE_16_235)
 		pipe_config->limited_color_range = true;
 
@@ -975,14 +975,16 @@ static void intel_hdmi_get_config(struct
 	pipe_config->lane_count = 4;
 }
 
-static void intel_enable_hdmi_audio(struct intel_encoder *encoder)
+static void intel_enable_hdmi_audio(struct intel_encoder *encoder,
+				    struct intel_crtc_state *pipe_config,
+				    struct drm_connector_state *conn_state)
 {
 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 
 	WARN_ON(!crtc->config->has_hdmi_sink);
 	DRM_DEBUG_DRIVER("Enabling HDMI audio on pipe %c\n",
 			 pipe_name(crtc->pipe));
-	intel_audio_codec_enable(encoder);
+	intel_audio_codec_enable(encoder, pipe_config, conn_state);
 }
 
 static void g4x_enable_hdmi(struct intel_encoder *encoder,
@@ -991,21 +993,20 @@ static void g4x_enable_hdmi(struct intel
 {
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
 	u32 temp;
 
 	temp = I915_READ(intel_hdmi->hdmi_reg);
 
 	temp |= SDVO_ENABLE;
-	if (crtc->config->has_audio)
+	if (pipe_config->has_audio)
 		temp |= SDVO_AUDIO_ENABLE;
 
 	I915_WRITE(intel_hdmi->hdmi_reg, temp);
 	POSTING_READ(intel_hdmi->hdmi_reg);
 
-	if (crtc->config->has_audio)
-		intel_enable_hdmi_audio(encoder);
+	if (pipe_config->has_audio)
+		intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
 }
 
 static void ibx_enable_hdmi(struct intel_encoder *encoder,
@@ -1040,8 +1041,8 @@ static void ibx_enable_hdmi(struct intel
 	 * FIXME: BSpec says this should be done at the end of
 	 * of the modeset sequence, so not sure if this isn't too soon.
 	 */
-	if (crtc->config->pipe_bpp > 24 &&
-	    crtc->config->pixel_multiplier > 1) {
+	if (pipe_config->pipe_bpp > 24 &&
+	    pipe_config->pixel_multiplier > 1) {
 		I915_WRITE(intel_hdmi->hdmi_reg, temp & ~SDVO_ENABLE);
 		POSTING_READ(intel_hdmi->hdmi_reg);
 
@@ -1055,8 +1056,8 @@ static void ibx_enable_hdmi(struct intel
 		POSTING_READ(intel_hdmi->hdmi_reg);
 	}
 
-	if (crtc->config->has_audio)
-		intel_enable_hdmi_audio(encoder);
+	if (pipe_config->has_audio)
+		intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
 }
 
 static void cpt_enable_hdmi(struct intel_encoder *encoder,
@@ -1073,7 +1074,7 @@ static void cpt_enable_hdmi(struct intel
 	temp = I915_READ(intel_hdmi->hdmi_reg);
 
 	temp |= SDVO_ENABLE;
-	if (crtc->config->has_audio)
+	if (pipe_config->has_audio)
 		temp |= SDVO_AUDIO_ENABLE;
 
 	/*
@@ -1086,7 +1087,7 @@ static void cpt_enable_hdmi(struct intel
 	 * 4. enable HDMI clock gating
 	 */
 
-	if (crtc->config->pipe_bpp > 24) {
+	if (pipe_config->pipe_bpp > 24) {
 		I915_WRITE(TRANS_CHICKEN1(pipe),
 			   I915_READ(TRANS_CHICKEN1(pipe)) |
 			   TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
@@ -1098,7 +1099,7 @@ static void cpt_enable_hdmi(struct intel
 	I915_WRITE(intel_hdmi->hdmi_reg, temp);
 	POSTING_READ(intel_hdmi->hdmi_reg);
 
-	if (crtc->config->pipe_bpp > 24) {
+	if (pipe_config->pipe_bpp > 24) {
 		temp &= ~SDVO_COLOR_FORMAT_MASK;
 		temp |= HDMI_COLOR_FORMAT_12bpc;
 
@@ -1110,8 +1111,8 @@ static void cpt_enable_hdmi(struct intel
 			   ~TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE);
 	}
 
-	if (crtc->config->has_audio)
-		intel_enable_hdmi_audio(encoder);
+	if (pipe_config->has_audio)
+		intel_enable_hdmi_audio(encoder, pipe_config, conn_state);
 }
 
 static void vlv_enable_hdmi(struct intel_encoder *encoder,
@@ -1141,7 +1142,7 @@ static void intel_disable_hdmi(struct in
 	 * to transcoder A after disabling it to allow the
 	 * matching DP port to be enabled on transcoder A.
 	 */
-	if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) {
+	if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
 		/*
 		 * We get CPU/PCH FIFO underruns on the other pipe when
 		 * doing the workaround. Sweep them under the rug.
@@ -1164,7 +1165,7 @@ static void intel_disable_hdmi(struct in
 		I915_WRITE(intel_hdmi->hdmi_reg, temp);
 		POSTING_READ(intel_hdmi->hdmi_reg);
 
-		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
+		intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 	}
@@ -1178,9 +1179,7 @@ static void g4x_disable_hdmi(struct inte
 			     struct intel_crtc_state *old_crtc_state,
 			     struct drm_connector_state *old_conn_state)
 {
-	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
-
-	if (crtc->config->has_audio)
+	if (old_crtc_state->has_audio)
 		intel_audio_codec_disable(encoder);
 
 	intel_disable_hdmi(encoder, old_crtc_state, old_conn_state);
@@ -1190,9 +1189,7 @@ static void pch_disable_hdmi(struct inte
 			     struct intel_crtc_state *old_crtc_state,
 			     struct drm_connector_state *old_conn_state)
 {
-	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
-
-	if (crtc->config->has_audio)
+	if (old_crtc_state->has_audio)
 		intel_audio_codec_disable(encoder);
 }
 
@@ -1241,7 +1238,7 @@ static enum drm_mode_status
 hdmi_port_clock_valid(struct intel_hdmi *hdmi,
 		      int clock, bool respect_downstream_limits)
 {
-	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
+	struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi));
 
 	if (clock < 25000)
 		return MODE_CLOCK_LOW;
@@ -1249,11 +1246,11 @@ hdmi_port_clock_valid(struct intel_hdmi
 		return MODE_CLOCK_HIGH;
 
 	/* BXT DPLL can't generate 223-240 MHz */
-	if (IS_BROXTON(dev) && clock > 223333 && clock < 240000)
+	if (IS_BROXTON(dev_priv) && clock > 223333 && clock < 240000)
 		return MODE_CLOCK_RANGE;
 
 	/* CHV DPLL can't generate 216-240 MHz */
-	if (IS_CHERRYVIEW(dev) && clock > 216000 && clock < 240000)
+	if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000)
 		return MODE_CLOCK_RANGE;
 
 	return MODE_OK;
@@ -1265,6 +1262,7 @@ intel_hdmi_mode_valid(struct drm_connect
 {
 	struct intel_hdmi *hdmi = intel_attached_hdmi(connector);
 	struct drm_device *dev = intel_hdmi_to_dev(hdmi);
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum drm_mode_status status;
 	int clock;
 	int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
@@ -1287,7 +1285,7 @@ intel_hdmi_mode_valid(struct drm_connect
 	status = hdmi_port_clock_valid(hdmi, clock, true);
 
 	/* if we can't do 8bpc we may still be able to do 12bpc */
-	if (!HAS_GMCH_DISPLAY(dev) && status != MODE_OK)
+	if (!HAS_GMCH_DISPLAY(dev_priv) && status != MODE_OK)
 		status = hdmi_port_clock_valid(hdmi, clock * 3 / 2, true);
 
 	return status;
@@ -1297,7 +1295,7 @@ static bool hdmi_12bpc_possible(struct i
 {
 	struct drm_device *dev = crtc_state->base.crtc->dev;
 
-	if (HAS_GMCH_DISPLAY(dev))
+	if (HAS_GMCH_DISPLAY(to_i915(dev)))
 		return false;
 
 	/*
@@ -1312,7 +1310,7 @@ bool intel_hdmi_compute_config(struct in
 			       struct drm_connector_state *conn_state)
 {
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 	int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock;
 	int clock_12bpc = clock_8bpc * 3 / 2;
@@ -1339,7 +1337,7 @@ bool intel_hdmi_compute_config(struct in
 		clock_12bpc *= 2;
 	}
 
-	if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev))
+	if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
 		pipe_config->has_pch_encoder = true;
 
 	if (pipe_config->has_hdmi_sink && intel_hdmi->has_audio)
@@ -1644,13 +1642,12 @@ static void intel_hdmi_pre_enable(struct
 				  struct drm_connector_state *conn_state)
 {
 	struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base);
-	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
-	const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 
 	intel_hdmi_prepare(encoder);
 
 	intel_hdmi->set_infoframes(&encoder->base,
-				   intel_crtc->config->has_hdmi_sink,
+				   pipe_config->has_hdmi_sink,
 				   adjusted_mode);
 }
 
@@ -1662,9 +1659,7 @@ static void vlv_hdmi_pre_enable(struct i
 	struct intel_hdmi *intel_hdmi = &dport->hdmi;
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_crtc *intel_crtc =
-		to_intel_crtc(encoder->base.crtc);
-	const struct drm_display_mode *adjusted_mode = &intel_crtc->config->base.adjusted_mode;
+	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 
 	vlv_phy_pre_encoder_enable(encoder);
 
@@ -1673,7 +1668,7 @@ static void vlv_hdmi_pre_enable(struct i
 				 0x2b247878);
 
 	intel_hdmi->set_infoframes(&encoder->base,
-				   intel_crtc->config->has_hdmi_sink,
+				   pipe_config->has_hdmi_sink,
 				   adjusted_mode);
 
 	g4x_enable_hdmi(encoder, pipe_config, conn_state);
@@ -1896,19 +1891,19 @@ void intel_hdmi_init_connector(struct in
 		return;
 	}
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		intel_hdmi->write_infoframe = vlv_write_infoframe;
 		intel_hdmi->set_infoframes = vlv_set_infoframes;
 		intel_hdmi->infoframe_enabled = vlv_infoframe_enabled;
-	} else if (IS_G4X(dev)) {
+	} else if (IS_G4X(dev_priv)) {
 		intel_hdmi->write_infoframe = g4x_write_infoframe;
 		intel_hdmi->set_infoframes = g4x_set_infoframes;
 		intel_hdmi->infoframe_enabled = g4x_infoframe_enabled;
-	} else if (HAS_DDI(dev)) {
+	} else if (HAS_DDI(dev_priv)) {
 		intel_hdmi->write_infoframe = hsw_write_infoframe;
 		intel_hdmi->set_infoframes = hsw_set_infoframes;
 		intel_hdmi->infoframe_enabled = hsw_infoframe_enabled;
-	} else if (HAS_PCH_IBX(dev)) {
+	} else if (HAS_PCH_IBX(dev_priv)) {
 		intel_hdmi->write_infoframe = ibx_write_infoframe;
 		intel_hdmi->set_infoframes = ibx_set_infoframes;
 		intel_hdmi->infoframe_enabled = ibx_infoframe_enabled;
@@ -1918,7 +1913,7 @@ void intel_hdmi_init_connector(struct in
 		intel_hdmi->infoframe_enabled = cpt_infoframe_enabled;
 	}
 
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev_priv))
 		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
 	else
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
@@ -1932,7 +1927,7 @@ void intel_hdmi_init_connector(struct in
 	 * 0xd.  Failure to do so will result in spurious interrupts being
 	 * generated on the port when a cable is not attached.
 	 */
-	if (IS_G4X(dev) && !IS_GM45(dev)) {
+	if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) {
 		u32 temp = I915_READ(PEG_BAND_GAP_DATA);
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
@@ -1941,6 +1936,7 @@ void intel_hdmi_init_connector(struct in
 void intel_hdmi_init(struct drm_device *dev,
 		     i915_reg_t hdmi_reg, enum port port)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_digital_port *intel_dig_port;
 	struct intel_encoder *intel_encoder;
 	struct intel_connector *intel_connector;
@@ -1961,7 +1957,7 @@ void intel_hdmi_init(struct drm_device *
 			 DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port));
 
 	intel_encoder->compute_config = intel_hdmi_compute_config;
-	if (HAS_PCH_SPLIT(dev)) {
+	if (HAS_PCH_SPLIT(dev_priv)) {
 		intel_encoder->disable = pch_disable_hdmi;
 		intel_encoder->post_disable = pch_post_disable_hdmi;
 	} else {
@@ -1969,29 +1965,30 @@ void intel_hdmi_init(struct drm_device *
 	}
 	intel_encoder->get_hw_state = intel_hdmi_get_hw_state;
 	intel_encoder->get_config = intel_hdmi_get_config;
-	if (IS_CHERRYVIEW(dev)) {
+	if (IS_CHERRYVIEW(dev_priv)) {
 		intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable;
 		intel_encoder->pre_enable = chv_hdmi_pre_enable;
 		intel_encoder->enable = vlv_enable_hdmi;
 		intel_encoder->post_disable = chv_hdmi_post_disable;
 		intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
 		intel_encoder->pre_enable = vlv_hdmi_pre_enable;
 		intel_encoder->enable = vlv_enable_hdmi;
 		intel_encoder->post_disable = vlv_hdmi_post_disable;
 	} else {
 		intel_encoder->pre_enable = intel_hdmi_pre_enable;
-		if (HAS_PCH_CPT(dev))
+		if (HAS_PCH_CPT(dev_priv))
 			intel_encoder->enable = cpt_enable_hdmi;
-		else if (HAS_PCH_IBX(dev))
+		else if (HAS_PCH_IBX(dev_priv))
 			intel_encoder->enable = ibx_enable_hdmi;
 		else
 			intel_encoder->enable = g4x_enable_hdmi;
 	}
 
 	intel_encoder->type = INTEL_OUTPUT_HDMI;
-	if (IS_CHERRYVIEW(dev)) {
+	intel_encoder->port = port;
+	if (IS_CHERRYVIEW(dev_priv)) {
 		if (port == PORT_D)
 			intel_encoder->crtc_mask = 1 << 2;
 		else
@@ -2005,7 +2002,7 @@ void intel_hdmi_init(struct drm_device *
 	 * to work on real hardware. And since g4x can send infoframes to
 	 * only one port anyway, nothing is lost by allowing it.
 	 */
-	if (IS_G4X(dev))
+	if (IS_G4X(dev_priv))
 		intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
 
 	intel_dig_port->port = port;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_hotplug.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_hotplug.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_hotplug.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_hotplug.c	2017-02-12 16:03:20.000000000 -0500
@@ -501,7 +501,7 @@ static void i915_hpd_poll_init_work(stru
 		if (intel_connector->mst_port)
 			continue;
 
-		if (!connector->polled && I915_HAS_HOTPLUG(dev) &&
+		if (!connector->polled && I915_HAS_HOTPLUG(dev_priv) &&
 		    intel_connector->encoder->hpd_pin > HPD_NONE) {
 			connector->polled = enabled ?
 				DRM_CONNECTOR_POLL_CONNECT |
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_i2c.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -138,11 +138,10 @@ static void intel_i2c_quirk_set(struct d
 static u32 get_reserved(struct intel_gmbus *bus)
 {
 	struct drm_i915_private *dev_priv = bus->dev_priv;
-	struct drm_device *dev = &dev_priv->drm;
 	u32 reserved = 0;
 
 	/* On most chips, these bits must be preserved in software. */
-	if (!IS_I830(dev) && !IS_845G(dev))
+	if (!IS_I830(dev_priv) && !IS_845G(dev_priv))
 		reserved = I915_READ_NOTRACE(bus->gpio_reg) &
 					     (GPIO_DATA_PULLUP_DISABLE |
 					      GPIO_CLOCK_PULLUP_DISABLE);
@@ -468,13 +467,9 @@ do_gmbus_xfer(struct i2c_adapter *adapte
 					       struct intel_gmbus,
 					       adapter);
 	struct drm_i915_private *dev_priv = bus->dev_priv;
-	const unsigned int fw =
-		intel_uncore_forcewake_for_reg(dev_priv, GMBUS0,
-					       FW_REG_READ | FW_REG_WRITE);
 	int i = 0, inc, try = 0;
 	int ret = 0;
 
-	intel_uncore_forcewake_get(dev_priv, fw);
 retry:
 	I915_WRITE_FW(GMBUS0, bus->reg0);
 
@@ -576,7 +571,6 @@ timeout:
 	ret = -EAGAIN;
 
 out:
-	intel_uncore_forcewake_put(dev_priv, fw);
 	return ret;
 }
 
@@ -633,10 +627,10 @@ int intel_setup_gmbus(struct drm_device
 	unsigned int pin;
 	int ret;
 
-	if (HAS_PCH_NOP(dev))
+	if (HAS_PCH_NOP(dev_priv))
 		return 0;
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE;
 	else if (!HAS_GMCH_DISPLAY(dev_priv))
 		dev_priv->gpio_mmio_base =
@@ -674,7 +668,7 @@ int intel_setup_gmbus(struct drm_device
 		bus->reg0 = pin | GMBUS_RATE_100KHZ;
 
 		/* gmbus seems to be broken on i830 */
-		if (IS_I830(dev))
+		if (IS_I830(dev_priv))
 			bus->force_bit = 1;
 
 		intel_gpio_setup(bus, pin);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lrc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lrc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lrc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lrc.c	2017-02-12 16:03:20.000000000 -0500
@@ -275,8 +275,7 @@ logical_ring_init_platform_invariants(st
 	struct drm_i915_private *dev_priv = engine->i915;
 
 	engine->disable_lite_restore_wa =
-		(IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
-		 IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) &&
+		IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) &&
 		(engine->id == VCS || engine->id == VCS2);
 
 	engine->ctx_desc_template = GEN8_CTX_VALID;
@@ -366,7 +365,7 @@ static u64 execlists_update_context(stru
 	struct i915_hw_ppgtt *ppgtt = rq->ctx->ppgtt;
 	u32 *reg_state = ce->lrc_reg_state;
 
-	reg_state[CTX_RING_TAIL+1] = intel_ring_offset(rq->ring, rq->tail);
+	reg_state[CTX_RING_TAIL+1] = rq->tail;
 
 	/* True 32b PPGTT with dynamic page allocation: update PDP
 	 * registers and point the unallocated PDPs to scratch page.
@@ -433,15 +432,17 @@ static bool can_merge_ctx(const struct i
 
 static void execlists_dequeue(struct intel_engine_cs *engine)
 {
-	struct drm_i915_gem_request *cursor, *last;
+	struct drm_i915_gem_request *last;
 	struct execlist_port *port = engine->execlist_port;
+	unsigned long flags;
+	struct rb_node *rb;
 	bool submit = false;
 
 	last = port->request;
 	if (last)
 		/* WaIdleLiteRestore:bdw,skl
 		 * Apply the wa NOOPs to prevent ring:HEAD == req:TAIL
-		 * as we resubmit the request. See gen8_emit_request()
+		 * as we resubmit the request. See gen8_emit_breadcrumb()
 		 * for where we prepare the padding after the end of the
 		 * request.
 		 */
@@ -470,8 +471,12 @@ static void execlists_dequeue(struct int
 	 * and context switches) submission.
 	 */
 
-	spin_lock(&engine->execlist_lock);
-	list_for_each_entry(cursor, &engine->execlist_queue, execlist_link) {
+	spin_lock_irqsave(&engine->timeline->lock, flags);
+	rb = engine->execlist_first;
+	while (rb) {
+		struct drm_i915_gem_request *cursor =
+			rb_entry(rb, typeof(*cursor), priotree.node);
+
 		/* Can we combine this request with the current port? It has to
 		 * be the same context/ringbuffer and not have any exceptions
 		 * (e.g. GVT saying never to combine contexts).
@@ -494,7 +499,8 @@ static void execlists_dequeue(struct int
 			 * context (even though a different request) to
 			 * the second port.
 			 */
-			if (ctx_single_port_submission(cursor->ctx))
+			if (ctx_single_port_submission(last->ctx) ||
+			    ctx_single_port_submission(cursor->ctx))
 				break;
 
 			GEM_BUG_ON(last->ctx == cursor->ctx);
@@ -502,17 +508,30 @@ static void execlists_dequeue(struct int
 			i915_gem_request_assign(&port->request, last);
 			port++;
 		}
+
+		rb = rb_next(rb);
+		rb_erase(&cursor->priotree.node, &engine->execlist_queue);
+		RB_CLEAR_NODE(&cursor->priotree.node);
+		cursor->priotree.priority = INT_MAX;
+
+		/* We keep the previous context alive until we retire the
+		 * following request. This ensures that any the context object
+		 * is still pinned for any residual writes the HW makes into it
+		 * on the context switch into the next object following the
+		 * breadcrumb. Otherwise, we may retire the context too early.
+		 */
+		cursor->previous_context = engine->last_context;
+		engine->last_context = cursor->ctx;
+
+		__i915_gem_request_submit(cursor);
 		last = cursor;
 		submit = true;
 	}
 	if (submit) {
-		/* Decouple all the requests submitted from the queue */
-		engine->execlist_queue.next = &cursor->execlist_link;
-		cursor->execlist_link.prev = &engine->execlist_queue;
-
 		i915_gem_request_assign(&port->request, last);
+		engine->execlist_first = rb;
 	}
-	spin_unlock(&engine->execlist_lock);
+	spin_unlock_irqrestore(&engine->timeline->lock, flags);
 
 	if (submit)
 		execlists_submit_ports(engine);
@@ -523,6 +542,28 @@ static bool execlists_elsp_idle(struct i
 	return !engine->execlist_port[0].request;
 }
 
+/**
+ * intel_execlists_idle() - Determine if all engine submission ports are idle
+ * @dev_priv: i915 device private
+ *
+ * Return true if there are no requests pending on any of the submission ports
+ * of any engines.
+ */
+bool intel_execlists_idle(struct drm_i915_private *dev_priv)
+{
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+
+	if (!i915.enable_execlists)
+		return true;
+
+	for_each_engine(engine, dev_priv, id)
+		if (!execlists_elsp_idle(engine))
+			return false;
+
+	return true;
+}
+
 static bool execlists_elsp_ready(struct intel_engine_cs *engine)
 {
 	int port;
@@ -593,18 +634,147 @@ static void intel_lrc_irq_handler(unsign
 	intel_uncore_forcewake_put(dev_priv, engine->fw_domains);
 }
 
+static bool insert_request(struct i915_priotree *pt, struct rb_root *root)
+{
+	struct rb_node **p, *rb;
+	bool first = true;
+
+	/* most positive priority is scheduled first, equal priorities fifo */
+	rb = NULL;
+	p = &root->rb_node;
+	while (*p) {
+		struct i915_priotree *pos;
+
+		rb = *p;
+		pos = rb_entry(rb, typeof(*pos), node);
+		if (pt->priority > pos->priority) {
+			p = &rb->rb_left;
+		} else {
+			p = &rb->rb_right;
+			first = false;
+		}
+	}
+	rb_link_node(&pt->node, rb, p);
+	rb_insert_color(&pt->node, root);
+
+	return first;
+}
+
 static void execlists_submit_request(struct drm_i915_gem_request *request)
 {
 	struct intel_engine_cs *engine = request->engine;
 	unsigned long flags;
 
-	spin_lock_irqsave(&engine->execlist_lock, flags);
+	/* Will be called from irq-context when using foreign fences. */
+	spin_lock_irqsave(&engine->timeline->lock, flags);
 
-	list_add_tail(&request->execlist_link, &engine->execlist_queue);
+	if (insert_request(&request->priotree, &engine->execlist_queue))
+		engine->execlist_first = &request->priotree.node;
 	if (execlists_elsp_idle(engine))
 		tasklet_hi_schedule(&engine->irq_tasklet);
 
-	spin_unlock_irqrestore(&engine->execlist_lock, flags);
+	spin_unlock_irqrestore(&engine->timeline->lock, flags);
+}
+
+static struct intel_engine_cs *
+pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked)
+{
+	struct intel_engine_cs *engine;
+
+	engine = container_of(pt,
+			      struct drm_i915_gem_request,
+			      priotree)->engine;
+	if (engine != locked) {
+		if (locked)
+			spin_unlock_irq(&locked->timeline->lock);
+		spin_lock_irq(&engine->timeline->lock);
+	}
+
+	return engine;
+}
+
+static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
+{
+	static DEFINE_MUTEX(lock);
+	struct intel_engine_cs *engine = NULL;
+	struct i915_dependency *dep, *p;
+	struct i915_dependency stack;
+	LIST_HEAD(dfs);
+
+	if (prio <= READ_ONCE(request->priotree.priority))
+		return;
+
+	/* Need global lock to use the temporary link inside i915_dependency */
+	mutex_lock(&lock);
+
+	stack.signaler = &request->priotree;
+	list_add(&stack.dfs_link, &dfs);
+
+	/* Recursively bump all dependent priorities to match the new request.
+	 *
+	 * A naive approach would be to use recursion:
+	 * static void update_priorities(struct i915_priotree *pt, prio) {
+	 *	list_for_each_entry(dep, &pt->signalers_list, signal_link)
+	 *		update_priorities(dep->signal, prio)
+	 *	insert_request(pt);
+	 * }
+	 * but that may have unlimited recursion depth and so runs a very
+	 * real risk of overunning the kernel stack. Instead, we build
+	 * a flat list of all dependencies starting with the current request.
+	 * As we walk the list of dependencies, we add all of its dependencies
+	 * to the end of the list (this may include an already visited
+	 * request) and continue to walk onwards onto the new dependencies. The
+	 * end result is a topological list of requests in reverse order, the
+	 * last element in the list is the request we must execute first.
+	 */
+	list_for_each_entry_safe(dep, p, &dfs, dfs_link) {
+		struct i915_priotree *pt = dep->signaler;
+
+		list_for_each_entry(p, &pt->signalers_list, signal_link)
+			if (prio > READ_ONCE(p->signaler->priority))
+				list_move_tail(&p->dfs_link, &dfs);
+
+		p = list_next_entry(dep, dfs_link);
+		if (!RB_EMPTY_NODE(&pt->node))
+			continue;
+
+		engine = pt_lock_engine(pt, engine);
+
+		/* If it is not already in the rbtree, we can update the
+		 * priority inplace and skip over it (and its dependencies)
+		 * if it is referenced *again* as we descend the dfs.
+		 */
+		if (prio > pt->priority && RB_EMPTY_NODE(&pt->node)) {
+			pt->priority = prio;
+			list_del_init(&dep->dfs_link);
+		}
+	}
+
+	/* Fifo and depth-first replacement ensure our deps execute before us */
+	list_for_each_entry_safe_reverse(dep, p, &dfs, dfs_link) {
+		struct i915_priotree *pt = dep->signaler;
+
+		INIT_LIST_HEAD(&dep->dfs_link);
+
+		engine = pt_lock_engine(pt, engine);
+
+		if (prio <= pt->priority)
+			continue;
+
+		GEM_BUG_ON(RB_EMPTY_NODE(&pt->node));
+
+		pt->priority = prio;
+		rb_erase(&pt->node, &engine->execlist_queue);
+		if (insert_request(pt, &engine->execlist_queue))
+			engine->execlist_first = &pt->node;
+	}
+
+	if (engine)
+		spin_unlock_irq(&engine->timeline->lock);
+
+	mutex_unlock(&lock);
+
+	/* XXX Do we need to preempt to make room for us and our deps? */
 }
 
 int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request)
@@ -672,46 +842,6 @@ err_unpin:
 	return ret;
 }
 
-/*
- * intel_logical_ring_advance() - advance the tail and prepare for submission
- * @request: Request to advance the logical ringbuffer of.
- *
- * The tail is updated in our logical ringbuffer struct, not in the actual context. What
- * really happens during submission is that the context and current tail will be placed
- * on a queue waiting for the ELSP to be ready to accept a new context submission. At that
- * point, the tail *inside* the context is updated and the ELSP written to.
- */
-static int
-intel_logical_ring_advance(struct drm_i915_gem_request *request)
-{
-	struct intel_ring *ring = request->ring;
-	struct intel_engine_cs *engine = request->engine;
-
-	intel_ring_advance(ring);
-	request->tail = ring->tail;
-
-	/*
-	 * Here we add two extra NOOPs as padding to avoid
-	 * lite restore of a context with HEAD==TAIL.
-	 *
-	 * Caller must reserve WA_TAIL_DWORDS for us!
-	 */
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
-	request->wa_tail = ring->tail;
-
-	/* We keep the previous context alive until we retire the following
-	 * request. This ensures that any the context object is still pinned
-	 * for any residual writes the HW makes into it on the context switch
-	 * into the next object following the breadcrumb. Otherwise, we may
-	 * retire the context too early.
-	 */
-	request->previous_context = engine->last_context;
-	engine->last_context = request->ctx;
-	return 0;
-}
-
 static int intel_lr_context_pin(struct i915_gem_context *ctx,
 				struct intel_engine_cs *engine)
 {
@@ -745,7 +875,7 @@ static int intel_lr_context_pin(struct i
 	ce->lrc_reg_state[CTX_RING_BUFFER_START+1] =
 		i915_ggtt_offset(ce->ring->vma);
 
-	ce->state->obj->dirty = true;
+	ce->state->obj->mm.dirty = true;
 
 	/* Invalidate GuC TLB. */
 	if (i915.enable_guc_submission) {
@@ -849,19 +979,8 @@ static inline int gen8_emit_flush_cohere
 						uint32_t *batch,
 						uint32_t index)
 {
-	struct drm_i915_private *dev_priv = engine->i915;
 	uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES);
 
-	/*
-	 * WaDisableLSQCROPERFforOCL:skl,kbl
-	 * This WA is implemented in skl_init_clock_gating() but since
-	 * this batch updates GEN8_L3SQCREG4 with default value we need to
-	 * set this bit here to retain the WA during flush.
-	 */
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0) ||
-	    IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
-		l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS;
-
 	wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 |
 				   MI_SRM_LRM_GLOBAL_GTT));
 	wa_ctx_emit_reg(batch, index, GEN8_L3SQCREG4);
@@ -1002,9 +1121,8 @@ static int gen9_init_indirectctx_bb(stru
 	struct drm_i915_private *dev_priv = engine->i915;
 	uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
 
-	/* WaDisableCtxRestoreArbitration:skl,bxt */
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) ||
-	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+	/* WaDisableCtxRestoreArbitration:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
 		wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE);
 
 	/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */
@@ -1075,9 +1193,8 @@ static int gen9_init_perctx_bb(struct in
 {
 	uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS);
 
-	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
-	if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_B0) ||
-	    IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) {
+	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
+	if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) {
 		wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1));
 		wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0);
 		wa_ctx_emit(batch, index,
@@ -1104,9 +1221,8 @@ static int gen9_init_perctx_bb(struct in
 		wa_ctx_emit(batch, index, MI_NOOP);
 	}
 
-	/* WaDisableCtxRestoreArbitration:skl,bxt */
-	if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_D0) ||
-	    IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1))
+	/* WaDisableCtxRestoreArbitration:bxt */
+	if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1))
 		wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE);
 
 	wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END);
@@ -1250,8 +1366,12 @@ static int gen8_init_common_ring(struct
 
 	intel_engine_init_hangcheck(engine);
 
-	if (!execlists_elsp_idle(engine))
+	/* After a GPU reset, we may have requests to replay */
+	if (!execlists_elsp_idle(engine)) {
+		engine->execlist_port[0].count = 0;
+		engine->execlist_port[1].count = 0;
 		execlists_submit_ports(engine);
+	}
 
 	return 0;
 }
@@ -1326,10 +1446,7 @@ static void reset_common_ring(struct int
 		memset(&port[1], 0, sizeof(port[1]));
 	}
 
-	/* CS is stopped, and we will resubmit both ports on resume */
 	GEM_BUG_ON(request->ctx != port[0].request->ctx);
-	port[0].count = 0;
-	port[1].count = 0;
 
 	/* Reset WaIdleLiteRestore:bdw,skl as well */
 	request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32);
@@ -1570,39 +1687,35 @@ static void bxt_a_seqno_barrier(struct i
  * used as a workaround for not being allowed to do lite
  * restore with HEAD==TAIL (WaIdleLiteRestore).
  */
-
-static int gen8_emit_request(struct drm_i915_gem_request *request)
+static void gen8_emit_wa_tail(struct drm_i915_gem_request *request, u32 *out)
 {
-	struct intel_ring *ring = request->ring;
-	int ret;
-
-	ret = intel_ring_begin(request, 6 + WA_TAIL_DWORDS);
-	if (ret)
-		return ret;
+	*out++ = MI_NOOP;
+	*out++ = MI_NOOP;
+	request->wa_tail = intel_ring_offset(request->ring, out);
+}
 
+static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request,
+				 u32 *out)
+{
 	/* w/a: bit 5 needs to be zero for MI_FLUSH_DW address. */
 	BUILD_BUG_ON(I915_GEM_HWS_INDEX_ADDR & (1 << 5));
 
-	intel_ring_emit(ring, (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
-	intel_ring_emit(ring,
-			intel_hws_seqno_address(request->engine) |
-			MI_FLUSH_DW_USE_GTT);
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, request->fence.seqno);
-	intel_ring_emit(ring, MI_USER_INTERRUPT);
-	intel_ring_emit(ring, MI_NOOP);
-	return intel_logical_ring_advance(request);
-}
+	*out++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW;
+	*out++ = intel_hws_seqno_address(request->engine) | MI_FLUSH_DW_USE_GTT;
+	*out++ = 0;
+	*out++ = request->global_seqno;
+	*out++ = MI_USER_INTERRUPT;
+	*out++ = MI_NOOP;
+	request->tail = intel_ring_offset(request->ring, out);
 
-static int gen8_emit_request_render(struct drm_i915_gem_request *request)
-{
-	struct intel_ring *ring = request->ring;
-	int ret;
+	gen8_emit_wa_tail(request, out);
+}
 
-	ret = intel_ring_begin(request, 8 + WA_TAIL_DWORDS);
-	if (ret)
-		return ret;
+static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS;
 
+static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request,
+					u32 *out)
+{
 	/* We're using qword write, seqno should be aligned to 8 bytes. */
 	BUILD_BUG_ON(I915_GEM_HWS_INDEX & 1);
 
@@ -1610,21 +1723,24 @@ static int gen8_emit_request_render(stru
 	 * need a prior CS_STALL, which is emitted by the flush
 	 * following the batch.
 	 */
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
-	intel_ring_emit(ring,
-			(PIPE_CONTROL_GLOBAL_GTT_IVB |
-			 PIPE_CONTROL_CS_STALL |
-			 PIPE_CONTROL_QW_WRITE));
-	intel_ring_emit(ring, intel_hws_seqno_address(request->engine));
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, i915_gem_request_get_seqno(request));
+	*out++ = GFX_OP_PIPE_CONTROL(6);
+	*out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB |
+		  PIPE_CONTROL_CS_STALL |
+		  PIPE_CONTROL_QW_WRITE);
+	*out++ = intel_hws_seqno_address(request->engine);
+	*out++ = 0;
+	*out++ = request->global_seqno;
 	/* We're thrashing one dword of HWS. */
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, MI_USER_INTERRUPT);
-	intel_ring_emit(ring, MI_NOOP);
-	return intel_logical_ring_advance(request);
+	*out++ = 0;
+	*out++ = MI_USER_INTERRUPT;
+	*out++ = MI_NOOP;
+	request->tail = intel_ring_offset(request->ring, out);
+
+	gen8_emit_wa_tail(request, out);
 }
 
+static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS;
+
 static int gen8_init_rcs_context(struct drm_i915_gem_request *req)
 {
 	int ret;
@@ -1641,7 +1757,7 @@ static int gen8_init_rcs_context(struct
 	if (ret)
 		DRM_ERROR("MOCS failed to program: expect performance issues.\n");
 
-	return i915_gem_render_state_init(req);
+	return i915_gem_render_state_emit(req);
 }
 
 /**
@@ -1652,9 +1768,6 @@ void intel_logical_ring_cleanup(struct i
 {
 	struct drm_i915_private *dev_priv;
 
-	if (!intel_engine_initialized(engine))
-		return;
-
 	/*
 	 * Tasklet cannot be active at this point due intel_mark_active/idle
 	 * so this is just for documentation.
@@ -1681,14 +1794,19 @@ void intel_logical_ring_cleanup(struct i
 
 	lrc_destroy_wa_ctx_obj(engine);
 	engine->i915 = NULL;
+	dev_priv->engine[engine->id] = NULL;
+	kfree(engine);
 }
 
 void intel_execlists_enable_submission(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id) {
 		engine->submit_request = execlists_submit_request;
+		engine->schedule = execlists_schedule;
+	}
 }
 
 static void
@@ -1698,8 +1816,10 @@ logical_ring_default_vfuncs(struct intel
 	engine->init_hw = gen8_init_common_ring;
 	engine->reset_hw = reset_common_ring;
 	engine->emit_flush = gen8_emit_flush;
-	engine->emit_request = gen8_emit_request;
+	engine->emit_breadcrumb = gen8_emit_breadcrumb;
+	engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_sz;
 	engine->submit_request = execlists_submit_request;
+	engine->schedule = execlists_schedule;
 
 	engine->irq_enable = gen8_logical_ring_enable_irq;
 	engine->irq_disable = gen8_logical_ring_disable_irq;
@@ -1820,7 +1940,8 @@ int logical_render_ring_init(struct inte
 		engine->init_hw = gen8_init_render_ring;
 	engine->init_context = gen8_init_rcs_context;
 	engine->emit_flush = gen8_emit_flush_render;
-	engine->emit_request = gen8_emit_request_render;
+	engine->emit_breadcrumb = gen8_emit_breadcrumb_render;
+	engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_render_sz;
 
 	ret = intel_engine_create_scratch(engine, 4096);
 	if (ret)
@@ -1837,12 +1958,7 @@ int logical_render_ring_init(struct inte
 			  ret);
 	}
 
-	ret = logical_ring_init(engine);
-	if (ret) {
-		lrc_destroy_wa_ctx_obj(engine);
-	}
-
-	return ret;
+	return logical_ring_init(engine);
 }
 
 int logical_xcs_ring_init(struct intel_engine_cs *engine)
@@ -1945,7 +2061,7 @@ static void execlists_init_reg_state(u32
 		       RING_START(engine->mmio_base), 0);
 	ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL,
 		       RING_CTL(engine->mmio_base),
-		       ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID);
+		       RING_CTL_SIZE(ring->size) | RING_VALID);
 	ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U,
 		       RING_BBADDR_UDW(engine->mmio_base), 0);
 	ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L,
@@ -2046,7 +2162,7 @@ populate_lr_context(struct i915_gem_cont
 		DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret);
 		return ret;
 	}
-	ctx_obj->dirty = true;
+	ctx_obj->mm.dirty = true;
 
 	/* The second page of the context object contains some fields which must
 	 * be set up prior to the first execution. */
@@ -2153,30 +2269,43 @@ error_deref_obj:
 
 void intel_lr_context_resume(struct drm_i915_private *dev_priv)
 {
-	struct i915_gem_context *ctx = dev_priv->kernel_context;
 	struct intel_engine_cs *engine;
+	struct i915_gem_context *ctx;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv) {
-		struct intel_context *ce = &ctx->engine[engine->id];
-		void *vaddr;
-		uint32_t *reg_state;
-
-		if (!ce->state)
-			continue;
+	/* Because we emit WA_TAIL_DWORDS there may be a disparity
+	 * between our bookkeeping in ce->ring->head and ce->ring->tail and
+	 * that stored in context. As we only write new commands from
+	 * ce->ring->tail onwards, everything before that is junk. If the GPU
+	 * starts reading from its RING_HEAD from the context, it may try to
+	 * execute that junk and die.
+	 *
+	 * So to avoid that we reset the context images upon resume. For
+	 * simplicity, we just zero everything out.
+	 */
+	list_for_each_entry(ctx, &dev_priv->context_list, link) {
+		for_each_engine(engine, dev_priv, id) {
+			struct intel_context *ce = &ctx->engine[engine->id];
+			u32 *reg;
 
-		vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB);
-		if (WARN_ON(IS_ERR(vaddr)))
-			continue;
+			if (!ce->state)
+				continue;
 
-		reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
+			reg = i915_gem_object_pin_map(ce->state->obj,
+						      I915_MAP_WB);
+			if (WARN_ON(IS_ERR(reg)))
+				continue;
 
-		reg_state[CTX_RING_HEAD+1] = 0;
-		reg_state[CTX_RING_TAIL+1] = 0;
+			reg += LRC_STATE_PN * PAGE_SIZE / sizeof(*reg);
+			reg[CTX_RING_HEAD+1] = 0;
+			reg[CTX_RING_TAIL+1] = 0;
 
-		ce->state->obj->dirty = true;
-		i915_gem_object_unpin_map(ce->state->obj);
+			ce->state->obj->mm.dirty = true;
+			i915_gem_object_unpin_map(ce->state->obj);
 
-		ce->ring->head = 0;
-		ce->ring->tail = 0;
+			ce->ring->head = ce->ring->tail = 0;
+			ce->ring->last_retired_head = -1;
+			intel_ring_update_space(ce->ring);
+		}
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lrc.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lrc.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lrc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lrc.h	2017-02-12 16:03:20.000000000 -0500
@@ -95,5 +95,6 @@ uint64_t intel_lr_context_descriptor(str
 int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv,
 				    int enable_execlists);
 void intel_execlists_enable_submission(struct drm_i915_private *dev_priv);
+bool intel_execlists_idle(struct drm_i915_private *dev_priv);
 
 #endif /* _INTEL_LRC_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lspcon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lspcon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lspcon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lspcon.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,185 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *
+ */
+#include <drm/drm_edid.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_dp_dual_mode_helper.h>
+#include "intel_drv.h"
+
+static struct intel_dp *lspcon_to_intel_dp(struct intel_lspcon *lspcon)
+{
+	struct intel_digital_port *dig_port =
+		container_of(lspcon, struct intel_digital_port, lspcon);
+
+	return &dig_port->dp;
+}
+
+static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon)
+{
+	enum drm_lspcon_mode current_mode = DRM_LSPCON_MODE_INVALID;
+	struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+
+	if (drm_lspcon_get_mode(adapter, &current_mode))
+		DRM_ERROR("Error reading LSPCON mode\n");
+	else
+		DRM_DEBUG_KMS("Current LSPCON mode %s\n",
+			current_mode == DRM_LSPCON_MODE_PCON ? "PCON" : "LS");
+	return current_mode;
+}
+
+static int lspcon_change_mode(struct intel_lspcon *lspcon,
+	enum drm_lspcon_mode mode, bool force)
+{
+	int err;
+	enum drm_lspcon_mode current_mode;
+	struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+
+	err = drm_lspcon_get_mode(adapter, &current_mode);
+	if (err) {
+		DRM_ERROR("Error reading LSPCON mode\n");
+		return err;
+	}
+
+	if (current_mode == mode) {
+		DRM_DEBUG_KMS("Current mode = desired LSPCON mode\n");
+		return 0;
+	}
+
+	err = drm_lspcon_set_mode(adapter, mode);
+	if (err < 0) {
+		DRM_ERROR("LSPCON mode change failed\n");
+		return err;
+	}
+
+	lspcon->mode = mode;
+	DRM_DEBUG_KMS("LSPCON mode changed done\n");
+	return 0;
+}
+
+static bool lspcon_probe(struct intel_lspcon *lspcon)
+{
+	enum drm_dp_dual_mode_type adaptor_type;
+	struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc;
+
+	/* Lets probe the adaptor and check its type */
+	adaptor_type = drm_dp_dual_mode_detect(adapter);
+	if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) {
+		DRM_DEBUG_KMS("No LSPCON detected, found %s\n",
+			drm_dp_get_dual_mode_type_name(adaptor_type));
+		return false;
+	}
+
+	/* Yay ... got a LSPCON device */
+	DRM_DEBUG_KMS("LSPCON detected\n");
+	lspcon->mode = lspcon_get_current_mode(lspcon);
+	lspcon->active = true;
+	return true;
+}
+
+static void lspcon_resume_in_pcon_wa(struct intel_lspcon *lspcon)
+{
+	struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon);
+	unsigned long start = jiffies;
+
+	if (!lspcon->desc_valid)
+		return;
+
+	while (1) {
+		struct intel_dp_desc desc;
+
+		/*
+		 * The w/a only applies in PCON mode and we don't expect any
+		 * AUX errors.
+		 */
+		if (!__intel_dp_read_desc(intel_dp, &desc))
+			return;
+
+		if (!memcmp(&intel_dp->desc, &desc, sizeof(desc))) {
+			DRM_DEBUG_KMS("LSPCON recovering in PCON mode after %u ms\n",
+				      jiffies_to_msecs(jiffies - start));
+			return;
+		}
+
+		if (time_after(jiffies, start + msecs_to_jiffies(1000)))
+			break;
+
+		usleep_range(10000, 15000);
+	}
+
+	DRM_DEBUG_KMS("LSPCON DP descriptor mismatch after resume\n");
+}
+
+void lspcon_resume(struct intel_lspcon *lspcon)
+{
+	lspcon_resume_in_pcon_wa(lspcon);
+
+	if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, true))
+		DRM_ERROR("LSPCON resume failed\n");
+	else
+		DRM_DEBUG_KMS("LSPCON resume success\n");
+}
+
+bool lspcon_init(struct intel_digital_port *intel_dig_port)
+{
+	struct intel_dp *dp = &intel_dig_port->dp;
+	struct intel_lspcon *lspcon = &intel_dig_port->lspcon;
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+
+	if (!IS_GEN9(dev_priv)) {
+		DRM_ERROR("LSPCON is supported on GEN9 only\n");
+		return false;
+	}
+
+	lspcon->active = false;
+	lspcon->mode = DRM_LSPCON_MODE_INVALID;
+
+	if (!lspcon_probe(lspcon)) {
+		DRM_ERROR("Failed to probe lspcon\n");
+		return false;
+	}
+
+	/*
+	* In the SW state machine, lets Put LSPCON in PCON mode only.
+	* In this way, it will work with both HDMI 1.4 sinks as well as HDMI
+	* 2.0 sinks.
+	*/
+	if (lspcon->active && lspcon->mode != DRM_LSPCON_MODE_PCON) {
+		if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON,
+			true) < 0) {
+			DRM_ERROR("LSPCON mode change to PCON failed\n");
+			return false;
+		}
+	}
+
+	if (!intel_dp_read_dpcd(dp)) {
+		DRM_ERROR("LSPCON DPCD read failed\n");
+		return false;
+	}
+
+	lspcon->desc_valid = intel_dp_read_desc(dp);
+
+	DRM_DEBUG_KMS("Success: LSPCON init\n");
+	return true;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_lvds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_lvds.c	2017-02-12 16:03:20.000000000 -0500
@@ -106,7 +106,7 @@ static bool intel_lvds_get_hw_state(stru
 	if (!(tmp & LVDS_PORT_EN))
 		goto out;
 
-	if (HAS_PCH_CPT(dev))
+	if (HAS_PCH_CPT(dev_priv))
 		*pipe = PORT_TO_PIPE_CPT(tmp);
 	else
 		*pipe = PORT_TO_PIPE(tmp);
@@ -122,8 +122,7 @@ out:
 static void intel_lvds_get_config(struct intel_encoder *encoder,
 				  struct intel_crtc_state *pipe_config)
 {
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
 	u32 tmp, flags = 0;
 
@@ -139,12 +138,12 @@ static void intel_lvds_get_config(struct
 
 	pipe_config->base.adjusted_mode.flags |= flags;
 
-	if (INTEL_INFO(dev)->gen < 5)
+	if (INTEL_GEN(dev_priv) < 5)
 		pipe_config->gmch_pfit.lvds_border_bits =
 			tmp & LVDS_BORDER_ENABLE;
 
 	/* gen2/3 store dither state in pfit control, needs to match */
-	if (INTEL_INFO(dev)->gen < 4) {
+	if (INTEL_GEN(dev_priv) < 4) {
 		tmp = I915_READ(PFIT_CONTROL);
 
 		pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
@@ -396,7 +395,7 @@ static bool intel_lvds_compute_config(st
 				      struct intel_crtc_state *pipe_config,
 				      struct drm_connector_state *conn_state)
 {
-	struct drm_device *dev = intel_encoder->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
 	struct intel_lvds_encoder *lvds_encoder =
 		to_lvds_encoder(&intel_encoder->base);
 	struct intel_connector *intel_connector =
@@ -406,7 +405,7 @@ static bool intel_lvds_compute_config(st
 	unsigned int lvds_bpp;
 
 	/* Should never happen!! */
-	if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
+	if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) {
 		DRM_ERROR("Can't support LVDS on pipe A\n");
 		return false;
 	}
@@ -431,7 +430,7 @@ static bool intel_lvds_compute_config(st
 	intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
 			       adjusted_mode);
 
-	if (HAS_PCH_SPLIT(dev)) {
+	if (HAS_PCH_SPLIT(dev_priv)) {
 		pipe_config->has_pch_encoder = true;
 
 		intel_pch_panel_fitting(intel_crtc, pipe_config,
@@ -566,7 +565,7 @@ static int intel_lid_notify(struct notif
 	 * and as part of the cleanup in the hw state restore we also redisable
 	 * the vga plane.
 	 */
-	if (!HAS_PCH_SPLIT(dev))
+	if (!HAS_PCH_SPLIT(dev_priv))
 		intel_display_resume(dev);
 
 	dev_priv->modeset_restore = MODESET_DONE;
@@ -949,16 +948,17 @@ static bool compute_is_dual_link_lvds(st
 	return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
 }
 
-static bool intel_lvds_supported(struct drm_device *dev)
+static bool intel_lvds_supported(struct drm_i915_private *dev_priv)
 {
 	/* With the introduction of the PCH we gained a dedicated
 	 * LVDS presence pin, use it. */
-	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
+	if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
 		return true;
 
 	/* Otherwise LVDS was only attached to mobile products,
 	 * except for the inglorious 830gm */
-	if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
+	if (INTEL_GEN(dev_priv) <= 4 &&
+	    IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
 		return true;
 
 	return false;
@@ -984,27 +984,27 @@ void intel_lvds_init(struct drm_device *
 	struct drm_display_mode *fixed_mode = NULL;
 	struct drm_display_mode *downclock_mode = NULL;
 	struct edid *edid;
-	struct drm_crtc *crtc;
+	struct intel_crtc *crtc;
 	i915_reg_t lvds_reg;
 	u32 lvds;
 	int pipe;
 	u8 pin;
 
-	if (!intel_lvds_supported(dev))
+	if (!intel_lvds_supported(dev_priv))
 		return;
 
 	/* Skip init on machines we know falsely report LVDS */
 	if (dmi_check_system(intel_no_lvds))
 		return;
 
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		lvds_reg = PCH_LVDS;
 	else
 		lvds_reg = LVDS;
 
 	lvds = I915_READ(lvds_reg);
 
-	if (HAS_PCH_SPLIT(dev)) {
+	if (HAS_PCH_SPLIT(dev_priv)) {
 		if ((lvds & LVDS_DETECTED) == 0)
 			return;
 		if (dev_priv->vbt.edp.support) {
@@ -1064,12 +1064,13 @@ void intel_lvds_init(struct drm_device *
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
-	intel_encoder->type = INTEL_OUTPUT_LVDS;
 
+	intel_encoder->type = INTEL_OUTPUT_LVDS;
+	intel_encoder->port = PORT_NONE;
 	intel_encoder->cloneable = 0;
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
-	else if (IS_GEN4(dev))
+	else if (IS_GEN4(dev_priv))
 		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
 	else
 		intel_encoder->crtc_mask = (1 << 1);
@@ -1157,14 +1158,14 @@ void intel_lvds_init(struct drm_device *
 	 */
 
 	/* Ironlake: FIXME if still fail, not try pipe mode now */
-	if (HAS_PCH_SPLIT(dev))
+	if (HAS_PCH_SPLIT(dev_priv))
 		goto failed;
 
 	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
-	crtc = intel_get_crtc_for_pipe(dev, pipe);
+	crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
 
 	if (crtc && (lvds & LVDS_PORT_EN)) {
-		fixed_mode = intel_crtc_mode_get(dev, crtc);
+		fixed_mode = intel_crtc_mode_get(dev, &crtc->base);
 		if (fixed_mode) {
 			DRM_DEBUG_KMS("using current (BIOS) mode: ");
 			drm_mode_debug_printmodeline(fixed_mode);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_opregion.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_opregion.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_opregion.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_opregion.c	2017-02-12 16:03:20.000000000 -0500
@@ -642,24 +642,6 @@ static struct notifier_block intel_opreg
  * (version 3)
  */
 
-static u32 get_did(struct intel_opregion *opregion, int i)
-{
-	u32 did;
-
-	if (i < ARRAY_SIZE(opregion->acpi->didl)) {
-		did = opregion->acpi->didl[i];
-	} else {
-		i -= ARRAY_SIZE(opregion->acpi->didl);
-
-		if (WARN_ON(i >= ARRAY_SIZE(opregion->acpi->did2)))
-			return 0;
-
-		did = opregion->acpi->did2[i];
-	}
-
-	return did;
-}
-
 static void set_did(struct intel_opregion *opregion, int i, u32 val)
 {
 	if (i < ARRAY_SIZE(opregion->acpi->didl)) {
@@ -674,11 +656,11 @@ static void set_did(struct intel_opregio
 	}
 }
 
-static u32 acpi_display_type(struct drm_connector *connector)
+static u32 acpi_display_type(struct intel_connector *connector)
 {
 	u32 display_type;
 
-	switch (connector->connector_type) {
+	switch (connector->base.connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
 	case DRM_MODE_CONNECTOR_DVIA:
 		display_type = ACPI_DISPLAY_TYPE_VGA;
@@ -707,7 +689,7 @@ static u32 acpi_display_type(struct drm_
 		display_type = ACPI_DISPLAY_TYPE_OTHER;
 		break;
 	default:
-		MISSING_CASE(connector->connector_type);
+		MISSING_CASE(connector->base.connector_type);
 		display_type = ACPI_DISPLAY_TYPE_OTHER;
 		break;
 	}
@@ -718,34 +700,9 @@ static u32 acpi_display_type(struct drm_
 static void intel_didl_outputs(struct drm_i915_private *dev_priv)
 {
 	struct intel_opregion *opregion = &dev_priv->opregion;
-	struct pci_dev *pdev = dev_priv->drm.pdev;
-	struct drm_connector *connector;
-	acpi_handle handle;
-	struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
-	unsigned long long device_id;
-	acpi_status status;
-	u32 temp, max_outputs;
-	int i = 0;
-
-	handle = ACPI_HANDLE(&pdev->dev);
-	if (!handle || acpi_bus_get_device(handle, &acpi_dev))
-		return;
-
-	if (acpi_is_video_device(handle))
-		acpi_video_bus = acpi_dev;
-	else {
-		list_for_each_entry(acpi_cdev, &acpi_dev->children, node) {
-			if (acpi_is_video_device(acpi_cdev->handle)) {
-				acpi_video_bus = acpi_cdev;
-				break;
-			}
-		}
-	}
-
-	if (!acpi_video_bus) {
-		DRM_DEBUG_KMS("No ACPI video bus found\n");
-		return;
-	}
+	struct intel_connector *connector;
+	int i = 0, max_outputs;
+	int display_index[16] = {};
 
 	/*
 	 * In theory, did2, the extended didl, gets added at opregion version
@@ -757,64 +714,58 @@ static void intel_didl_outputs(struct dr
 	max_outputs = ARRAY_SIZE(opregion->acpi->didl) +
 		ARRAY_SIZE(opregion->acpi->did2);
 
-	list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) {
-		if (i >= max_outputs) {
-			DRM_DEBUG_KMS("More than %u outputs detected via ACPI\n",
-				      max_outputs);
-			return;
-		}
-		status = acpi_evaluate_integer(acpi_cdev->handle, "_ADR",
-					       NULL, &device_id);
-		if (ACPI_SUCCESS(status)) {
-			if (!device_id)
-				goto blind_set;
-			set_did(opregion, i++, (u32)(device_id & 0x0f0f));
-		}
+	for_each_intel_connector(&dev_priv->drm, connector) {
+		u32 device_id, type;
+
+		device_id = acpi_display_type(connector);
+
+		/* Use display type specific display index. */
+		type = (device_id & ACPI_DISPLAY_TYPE_MASK)
+			>> ACPI_DISPLAY_TYPE_SHIFT;
+		device_id |= display_index[type]++ << ACPI_DISPLAY_INDEX_SHIFT;
+
+		connector->acpi_device_id = device_id;
+		if (i < max_outputs)
+			set_did(opregion, i, device_id);
+		i++;
 	}
 
-end:
 	DRM_DEBUG_KMS("%d outputs detected\n", i);
 
+	if (i > max_outputs)
+		DRM_ERROR("More than %d outputs in connector list\n",
+			  max_outputs);
+
 	/* If fewer than max outputs, the list must be null terminated */
 	if (i < max_outputs)
 		set_did(opregion, i, 0);
-	return;
-
-blind_set:
-	i = 0;
-	list_for_each_entry(connector,
-			    &dev_priv->drm.mode_config.connector_list, head) {
-		int display_type = acpi_display_type(connector);
-
-		if (i >= max_outputs) {
-			DRM_DEBUG_KMS("More than %u outputs in connector list\n",
-				      max_outputs);
-			return;
-		}
-
-		temp = get_did(opregion, i);
-		set_did(opregion, i, temp | (1 << 31) | display_type | i);
-		i++;
-	}
-	goto end;
 }
 
 static void intel_setup_cadls(struct drm_i915_private *dev_priv)
 {
 	struct intel_opregion *opregion = &dev_priv->opregion;
+	struct intel_connector *connector;
 	int i = 0;
-	u32 disp_id;
 
-	/* Initialize the CADL field by duplicating the DIDL values.
-	 * Technically, this is not always correct as display outputs may exist,
-	 * but not active. This initialization is necessary for some Clevo
-	 * laptops that check this field before processing the brightness and
-	 * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if
-	 * there are less than eight devices. */
-	do {
-		disp_id = get_did(opregion, i);
-		opregion->acpi->cadl[i] = disp_id;
-	} while (++i < 8 && disp_id != 0);
+	/*
+	 * Initialize the CADL field from the connector device ids. This is
+	 * essentially the same as copying from the DIDL. Technically, this is
+	 * not always correct as display outputs may exist, but not active. This
+	 * initialization is necessary for some Clevo laptops that check this
+	 * field before processing the brightness and display switching hotkeys.
+	 *
+	 * Note that internal panels should be at the front of the connector
+	 * list already, ensuring they're not left out.
+	 */
+	for_each_intel_connector(&dev_priv->drm, connector) {
+		if (i >= ARRAY_SIZE(opregion->acpi->cadl))
+			break;
+		opregion->acpi->cadl[i++] = connector->acpi_device_id;
+	}
+
+	/* If fewer than 8 active devices, the list must be null terminated */
+	if (i < ARRAY_SIZE(opregion->acpi->cadl))
+		opregion->acpi->cadl[i] = 0;
 }
 
 void intel_opregion_register(struct drm_i915_private *dev_priv)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_overlay.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_overlay.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_overlay.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_overlay.c	2017-02-12 16:03:20.000000000 -0500
@@ -216,7 +216,8 @@ static void intel_overlay_submit_request
 {
 	GEM_BUG_ON(i915_gem_active_peek(&overlay->last_flip,
 					&overlay->i915->drm.struct_mutex));
-	overlay->last_flip.retire = retire;
+	i915_gem_active_set_retire_fn(&overlay->last_flip, retire,
+				      &overlay->i915->drm.struct_mutex);
 	i915_gem_active_set(&overlay->last_flip, req);
 	i915_add_request(req);
 }
@@ -233,7 +234,7 @@ static int intel_overlay_do_wait_request
 static struct drm_i915_gem_request *alloc_request(struct intel_overlay *overlay)
 {
 	struct drm_i915_private *dev_priv = overlay->i915;
-	struct intel_engine_cs *engine = &dev_priv->engine[RCS];
+	struct intel_engine_cs *engine = dev_priv->engine[RCS];
 
 	return i915_gem_request_alloc(engine, dev_priv->kernel_context);
 }
@@ -839,8 +840,8 @@ static int intel_overlay_do_put_image(st
 	if (ret)
 		goto out_unpin;
 
-	i915_gem_track_fb(overlay->vma->obj, new_bo,
-			  INTEL_FRONTBUFFER_OVERLAY(pipe));
+	i915_gem_track_fb(overlay->vma ? overlay->vma->obj : NULL,
+			  vma->obj, INTEL_FRONTBUFFER_OVERLAY(pipe));
 
 	overlay->old_vma = overlay->vma;
 	overlay->vma = vma;
@@ -1222,7 +1223,7 @@ int intel_overlay_put_image_ioctl(struct
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);
 	drm_modeset_unlock_all(dev);
-	i915_gem_object_put_unlocked(new_bo);
+	i915_gem_object_put(new_bo);
 out_free:
 	kfree(params);
 
@@ -1430,6 +1431,8 @@ void intel_setup_overlay(struct drm_i915
 	overlay->contrast = 75;
 	overlay->saturation = 146;
 
+	init_request_active(&overlay->last_flip, NULL);
+
 	regs = intel_overlay_map_regs(overlay);
 	if (!regs)
 		goto out_unpin_bo;
@@ -1466,10 +1469,12 @@ void intel_cleanup_overlay(struct drm_i9
 	 * hardware should be off already */
 	WARN_ON(dev_priv->overlay->active);
 
-	i915_gem_object_put_unlocked(dev_priv->overlay->reg_bo);
+	i915_gem_object_put(dev_priv->overlay->reg_bo);
 	kfree(dev_priv->overlay);
 }
 
+#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR)
+
 struct intel_overlay_error_state {
 	struct overlay_registers regs;
 	unsigned long base;
@@ -1587,3 +1592,5 @@ intel_overlay_print_error_state(struct d
 	P(UVSCALEV);
 #undef P
 }
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_panel.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_panel.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_panel.c	2017-02-12 16:03:20.000000000 -0500
@@ -304,7 +304,7 @@ void intel_gmch_panel_fitting(struct int
 			      struct intel_crtc_state *pipe_config,
 			      int fitting_mode)
 {
-	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
 	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
 
@@ -325,7 +325,7 @@ void intel_gmch_panel_fitting(struct int
 		break;
 	case DRM_MODE_SCALE_ASPECT:
 		/* Scale but preserve the aspect ratio */
-		if (INTEL_INFO(dev)->gen >= 4)
+		if (INTEL_GEN(dev_priv) >= 4)
 			i965_scale_aspect(pipe_config, &pfit_control);
 		else
 			i9xx_scale_aspect(pipe_config, &pfit_control,
@@ -339,7 +339,7 @@ void intel_gmch_panel_fitting(struct int
 		if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay ||
 		    pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) {
 			pfit_control |= PFIT_ENABLE;
-			if (INTEL_INFO(dev)->gen >= 4)
+			if (INTEL_GEN(dev_priv) >= 4)
 				pfit_control |= PFIT_SCALING_AUTO;
 			else
 				pfit_control |= (VERT_AUTO_SCALE |
@@ -355,7 +355,7 @@ void intel_gmch_panel_fitting(struct int
 
 	/* 965+ wants fuzzy fitting */
 	/* FIXME: handle multiple panels by failing gracefully */
-	if (INTEL_INFO(dev)->gen >= 4)
+	if (INTEL_GEN(dev_priv) >= 4)
 		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
 				 PFIT_FILTER_FUZZY);
 
@@ -366,7 +366,7 @@ out:
 	}
 
 	/* Make sure pre-965 set dither correctly for 18bpp panels. */
-	if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
+	if (INTEL_GEN(dev_priv) < 4 && pipe_config->pipe_bpp == 18)
 		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
 
 	pipe_config->gmch_pfit.control = pfit_control;
@@ -1722,7 +1722,7 @@ int intel_panel_setup_backlight(struct d
 
 	DRM_DEBUG_KMS("Connector %s backlight initialized, %s, brightness %u/%u\n",
 		      connector->name,
-		      panel->backlight.enabled ? "enabled" : "disabled",
+		      enableddisabled(panel->backlight.enabled),
 		      panel->backlight.level, panel->backlight.max);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_pm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_pm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@
 #include "intel_drv.h"
 #include "../../../platform/x86/intel_ips.h"
 #include <linux/module.h>
+#include <drm/drm_atomic_helper.h>
 
 /**
  * DOC: RC6
@@ -55,10 +56,8 @@
 #define INTEL_RC6p_ENABLE			(1<<1)
 #define INTEL_RC6pp_ENABLE			(1<<2)
 
-static void gen9_init_clock_gating(struct drm_device *dev)
+static void gen9_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	/* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl */
 	I915_WRITE(CHICKEN_PAR1_1,
 		   I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP);
@@ -81,11 +80,9 @@ static void gen9_init_clock_gating(struc
 		   ILK_DPFC_DISABLE_DUMMY0);
 }
 
-static void bxt_init_clock_gating(struct drm_device *dev)
+static void bxt_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	gen9_init_clock_gating(dev);
+	gen9_init_clock_gating(dev_priv);
 
 	/* WaDisableSDEUnitClockGating:bxt */
 	I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) |
@@ -107,9 +104,8 @@ static void bxt_init_clock_gating(struct
 			   PWM1_GATING_DIS | PWM2_GATING_DIS);
 }
 
-static void i915_pineview_get_mem_freq(struct drm_device *dev)
+static void i915_pineview_get_mem_freq(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 tmp;
 
 	tmp = I915_READ(CLKCFG);
@@ -146,9 +142,8 @@ static void i915_pineview_get_mem_freq(s
 	dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
 }
 
-static void i915_ironlake_get_mem_freq(struct drm_device *dev)
+static void i915_ironlake_get_mem_freq(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	u16 ddrpll, csipll;
 
 	ddrpll = I915_READ16(DDRMPLL1);
@@ -252,8 +247,8 @@ static const struct cxsr_latency cxsr_la
 	{0, 1, 400, 800, 6042, 36042, 6584, 36584},    /* DDR3-800 SC */
 };
 
-static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop,
-							 int is_ddr3,
+static const struct cxsr_latency *intel_get_cxsr_latency(bool is_desktop,
+							 bool is_ddr3,
 							 int fsb,
 							 int mem)
 {
@@ -319,27 +314,26 @@ static void chv_set_memory_pm5(struct dr
 
 void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	u32 val;
 
-	if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0);
 		POSTING_READ(FW_BLC_SELF_VLV);
 		dev_priv->wm.vlv.cxsr = enable;
-	} else if (IS_G4X(dev) || IS_CRESTLINE(dev)) {
+	} else if (IS_G4X(dev_priv) || IS_CRESTLINE(dev_priv)) {
 		I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0);
 		POSTING_READ(FW_BLC_SELF);
-	} else if (IS_PINEVIEW(dev)) {
+	} else if (IS_PINEVIEW(dev_priv)) {
 		val = I915_READ(DSPFW3) & ~PINEVIEW_SELF_REFRESH_EN;
 		val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0;
 		I915_WRITE(DSPFW3, val);
 		POSTING_READ(DSPFW3);
-	} else if (IS_I945G(dev) || IS_I945GM(dev)) {
+	} else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) {
 		val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) :
 			       _MASKED_BIT_DISABLE(FW_BLC_SELF_EN);
 		I915_WRITE(FW_BLC_SELF, val);
 		POSTING_READ(FW_BLC_SELF);
-	} else if (IS_I915GM(dev)) {
+	} else if (IS_I915GM(dev_priv)) {
 		/*
 		 * FIXME can't find a bit like this for 915G, and
 		 * and yet it does have the related watermark in
@@ -353,8 +347,7 @@ void intel_set_memory_cxsr(struct drm_i9
 		return;
 	}
 
-	DRM_DEBUG_KMS("memory self-refresh is %s\n",
-		      enable ? "enabled" : "disabled");
+	DRM_DEBUG_KMS("memory self-refresh is %s\n", enableddisabled(enable));
 }
 
 
@@ -377,10 +370,9 @@ static const int pessimal_latency_ns = 5
 #define VLV_FIFO_START(dsparb, dsparb2, lo_shift, hi_shift) \
 	((((dsparb) >> (lo_shift)) & 0xff) | ((((dsparb2) >> (hi_shift)) & 0x1) << 8))
 
-static int vlv_get_fifo_size(struct drm_device *dev,
+static int vlv_get_fifo_size(struct drm_i915_private *dev_priv,
 			      enum pipe pipe, int plane)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	int sprite0_start, sprite1_start, size;
 
 	switch (pipe) {
@@ -429,9 +421,8 @@ static int vlv_get_fifo_size(struct drm_
 	return size;
 }
 
-static int i9xx_get_fifo_size(struct drm_device *dev, int plane)
+static int i9xx_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t dsparb = I915_READ(DSPARB);
 	int size;
 
@@ -445,9 +436,8 @@ static int i9xx_get_fifo_size(struct drm
 	return size;
 }
 
-static int i830_get_fifo_size(struct drm_device *dev, int plane)
+static int i830_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t dsparb = I915_READ(DSPARB);
 	int size;
 
@@ -462,9 +452,8 @@ static int i830_get_fifo_size(struct drm
 	return size;
 }
 
-static int i845_get_fifo_size(struct drm_device *dev, int plane)
+static int i845_get_fifo_size(struct drm_i915_private *dev_priv, int plane)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t dsparb = I915_READ(DSPARB);
 	int size;
 
@@ -624,11 +613,11 @@ static unsigned long intel_calculate_wm(
 	return wm_size;
 }
 
-static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
+static struct intel_crtc *single_enabled_crtc(struct drm_i915_private *dev_priv)
 {
-	struct drm_crtc *crtc, *enabled = NULL;
+	struct intel_crtc *crtc, *enabled = NULL;
 
-	for_each_crtc(dev, crtc) {
+	for_each_intel_crtc(&dev_priv->drm, crtc) {
 		if (intel_crtc_active(crtc)) {
 			if (enabled)
 				return NULL;
@@ -639,27 +628,31 @@ static struct drm_crtc *single_enabled_c
 	return enabled;
 }
 
-static void pineview_update_wm(struct drm_crtc *unused_crtc)
+static void pineview_update_wm(struct intel_crtc *unused_crtc)
 {
-	struct drm_device *dev = unused_crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *crtc;
+	struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
+	struct intel_crtc *crtc;
 	const struct cxsr_latency *latency;
 	u32 reg;
 	unsigned long wm;
 
-	latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
-					 dev_priv->fsb_freq, dev_priv->mem_freq);
+	latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
+					 dev_priv->is_ddr3,
+					 dev_priv->fsb_freq,
+					 dev_priv->mem_freq);
 	if (!latency) {
 		DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n");
 		intel_set_memory_cxsr(dev_priv, false);
 		return;
 	}
 
-	crtc = single_enabled_crtc(dev);
+	crtc = single_enabled_crtc(dev_priv);
 	if (crtc) {
-		const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
-		int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+		const struct drm_display_mode *adjusted_mode =
+			&crtc->config->base.adjusted_mode;
+		const struct drm_framebuffer *fb =
+			crtc->base.primary->state->fb;
+		int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 		int clock = adjusted_mode->crtc_clock;
 
 		/* Display SR */
@@ -706,7 +699,7 @@ static void pineview_update_wm(struct dr
 	}
 }
 
-static bool g4x_compute_wm0(struct drm_device *dev,
+static bool g4x_compute_wm0(struct drm_i915_private *dev_priv,
 			    int plane,
 			    const struct intel_watermark_params *display,
 			    int display_latency_ns,
@@ -715,24 +708,26 @@ static bool g4x_compute_wm0(struct drm_d
 			    int *plane_wm,
 			    int *cursor_wm)
 {
-	struct drm_crtc *crtc;
+	struct intel_crtc *crtc;
 	const struct drm_display_mode *adjusted_mode;
+	const struct drm_framebuffer *fb;
 	int htotal, hdisplay, clock, cpp;
 	int line_time_us, line_count;
 	int entries, tlb_miss;
 
-	crtc = intel_get_crtc_for_plane(dev, plane);
+	crtc = intel_get_crtc_for_plane(dev_priv, plane);
 	if (!intel_crtc_active(crtc)) {
 		*cursor_wm = cursor->guard_size;
 		*plane_wm = display->guard_size;
 		return false;
 	}
 
-	adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
+	adjusted_mode = &crtc->config->base.adjusted_mode;
+	fb = crtc->base.primary->state->fb;
 	clock = adjusted_mode->crtc_clock;
 	htotal = adjusted_mode->crtc_htotal;
-	hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
-	cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+	hdisplay = crtc->config->pipe_src_w;
+	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	/* Use the small buffer method to calculate plane watermark */
 	entries = ((clock * cpp / 1000) * display_latency_ns) / 1000;
@@ -747,7 +742,7 @@ static bool g4x_compute_wm0(struct drm_d
 	/* Use the large buffer method to calculate cursor watermark */
 	line_time_us = max(htotal * 1000 / clock, 1);
 	line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
-	entries = line_count * crtc->cursor->state->crtc_w * cpp;
+	entries = line_count * crtc->base.cursor->state->crtc_w * cpp;
 	tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
 	if (tlb_miss > 0)
 		entries += tlb_miss;
@@ -766,7 +761,7 @@ static bool g4x_compute_wm0(struct drm_d
  * can be programmed into the associated watermark register, that watermark
  * must be disabled.
  */
-static bool g4x_check_srwm(struct drm_device *dev,
+static bool g4x_check_srwm(struct drm_i915_private *dev_priv,
 			   int display_wm, int cursor_wm,
 			   const struct intel_watermark_params *display,
 			   const struct intel_watermark_params *cursor)
@@ -775,13 +770,13 @@ static bool g4x_check_srwm(struct drm_de
 		      display_wm, cursor_wm);
 
 	if (display_wm > display->max_wm) {
-		DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n",
+		DRM_DEBUG_KMS("display watermark is too large(%d/%u), disabling\n",
 			      display_wm, display->max_wm);
 		return false;
 	}
 
 	if (cursor_wm > cursor->max_wm) {
-		DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n",
+		DRM_DEBUG_KMS("cursor watermark is too large(%d/%u), disabling\n",
 			      cursor_wm, cursor->max_wm);
 		return false;
 	}
@@ -794,15 +789,16 @@ static bool g4x_check_srwm(struct drm_de
 	return true;
 }
 
-static bool g4x_compute_srwm(struct drm_device *dev,
+static bool g4x_compute_srwm(struct drm_i915_private *dev_priv,
 			     int plane,
 			     int latency_ns,
 			     const struct intel_watermark_params *display,
 			     const struct intel_watermark_params *cursor,
 			     int *display_wm, int *cursor_wm)
 {
-	struct drm_crtc *crtc;
+	struct intel_crtc *crtc;
 	const struct drm_display_mode *adjusted_mode;
+	const struct drm_framebuffer *fb;
 	int hdisplay, htotal, cpp, clock;
 	unsigned long line_time_us;
 	int line_count, line_size;
@@ -814,12 +810,13 @@ static bool g4x_compute_srwm(struct drm_
 		return false;
 	}
 
-	crtc = intel_get_crtc_for_plane(dev, plane);
-	adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
+	crtc = intel_get_crtc_for_plane(dev_priv, plane);
+	adjusted_mode = &crtc->config->base.adjusted_mode;
+	fb = crtc->base.primary->state->fb;
 	clock = adjusted_mode->crtc_clock;
 	htotal = adjusted_mode->crtc_htotal;
-	hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
-	cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+	hdisplay = crtc->config->pipe_src_w;
+	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 	line_time_us = max(htotal * 1000 / clock, 1);
 	line_count = (latency_ns / line_time_us + 1000) / 1000;
@@ -833,11 +830,11 @@ static bool g4x_compute_srwm(struct drm_
 	*display_wm = entries + display->guard_size;
 
 	/* calculate the self-refresh watermark for display cursor */
-	entries = line_count * cpp * crtc->cursor->state->crtc_w;
+	entries = line_count * cpp * crtc->base.cursor->state->crtc_w;
 	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
 	*cursor_wm = entries + cursor->guard_size;
 
-	return g4x_check_srwm(dev,
+	return g4x_check_srwm(dev_priv,
 			      *display_wm, *cursor_wm,
 			      display, cursor);
 }
@@ -937,10 +934,8 @@ static unsigned int vlv_wm_method2(unsig
 	return ret;
 }
 
-static void vlv_setup_wm_latency(struct drm_device *dev)
+static void vlv_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/* all latencies in usec */
 	dev_priv->wm.pri_latency[VLV_WM_LEVEL_PM2] = 3;
 
@@ -1065,7 +1060,8 @@ static void vlv_invert_wms(struct intel_
 
 	for (level = 0; level < wm_state->num_levels; level++) {
 		struct drm_device *dev = crtc->base.dev;
-		const int sr_fifo_size = INTEL_INFO(dev)->num_pipes * 512 - 1;
+		const int sr_fifo_size =
+			INTEL_INFO(to_i915(dev))->num_pipes * 512 - 1;
 		struct intel_plane *plane;
 
 		wm_state->sr[level].plane = sr_fifo_size - wm_state->sr[level].plane;
@@ -1095,15 +1091,16 @@ static void vlv_invert_wms(struct intel_
 static void vlv_compute_wm(struct intel_crtc *crtc)
 {
 	struct drm_device *dev = crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct vlv_wm_state *wm_state = &crtc->wm_state;
 	struct intel_plane *plane;
-	int sr_fifo_size = INTEL_INFO(dev)->num_pipes * 512 - 1;
+	int sr_fifo_size = INTEL_INFO(dev_priv)->num_pipes * 512 - 1;
 	int level;
 
 	memset(wm_state, 0, sizeof(*wm_state));
 
 	wm_state->cxsr = crtc->pipe != PIPE_C && crtc->wm.cxsr_allowed;
-	wm_state->num_levels = to_i915(dev)->wm.max_level + 1;
+	wm_state->num_levels = dev_priv->wm.max_level + 1;
 
 	wm_state->num_active_planes = 0;
 
@@ -1183,7 +1180,7 @@ static void vlv_compute_wm(struct intel_
 	}
 
 	/* clear any (partially) filled invalid levels */
-	for (level = wm_state->num_levels; level < to_i915(dev)->wm.max_level + 1; level++) {
+	for (level = wm_state->num_levels; level < dev_priv->wm.max_level + 1; level++) {
 		memset(&wm_state->wm[level], 0, sizeof(wm_state->wm[level]));
 		memset(&wm_state->sr[level], 0, sizeof(wm_state->sr[level]));
 	}
@@ -1327,20 +1324,19 @@ static void vlv_merge_wm(struct drm_devi
 	}
 }
 
-static void vlv_update_wm(struct drm_crtc *crtc)
+static void vlv_update_wm(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_device *dev = crtc->base.dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	enum pipe pipe = intel_crtc->pipe;
+	enum pipe pipe = crtc->pipe;
 	struct vlv_wm_values wm = {};
 
-	vlv_compute_wm(intel_crtc);
+	vlv_compute_wm(crtc);
 	vlv_merge_wm(dev, &wm);
 
 	if (memcmp(&dev_priv->wm.vlv, &wm, sizeof(wm)) == 0) {
 		/* FIXME should be part of crtc atomic commit */
-		vlv_pipe_set_fifo_size(intel_crtc);
+		vlv_pipe_set_fifo_size(crtc);
 		return;
 	}
 
@@ -1356,9 +1352,9 @@ static void vlv_update_wm(struct drm_crt
 		intel_set_memory_cxsr(dev_priv, false);
 
 	/* FIXME should be part of crtc atomic commit */
-	vlv_pipe_set_fifo_size(intel_crtc);
+	vlv_pipe_set_fifo_size(crtc);
 
-	vlv_write_wm_values(intel_crtc, &wm);
+	vlv_write_wm_values(crtc, &wm);
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - %c: plane=%d, cursor=%d, "
 		      "sprite0=%d, sprite1=%d, SR: plane=%d, cursor=%d level=%d cxsr=%d\n",
@@ -1382,30 +1378,29 @@ static void vlv_update_wm(struct drm_crt
 
 #define single_plane_enabled(mask) is_power_of_2(mask)
 
-static void g4x_update_wm(struct drm_crtc *crtc)
+static void g4x_update_wm(struct intel_crtc *crtc)
 {
-	struct drm_device *dev = crtc->dev;
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	static const int sr_latency_ns = 12000;
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
 	int plane_sr, cursor_sr;
 	unsigned int enabled = 0;
 	bool cxsr_enabled;
 
-	if (g4x_compute_wm0(dev, PIPE_A,
+	if (g4x_compute_wm0(dev_priv, PIPE_A,
 			    &g4x_wm_info, pessimal_latency_ns,
 			    &g4x_cursor_wm_info, pessimal_latency_ns,
 			    &planea_wm, &cursora_wm))
 		enabled |= 1 << PIPE_A;
 
-	if (g4x_compute_wm0(dev, PIPE_B,
+	if (g4x_compute_wm0(dev_priv, PIPE_B,
 			    &g4x_wm_info, pessimal_latency_ns,
 			    &g4x_cursor_wm_info, pessimal_latency_ns,
 			    &planeb_wm, &cursorb_wm))
 		enabled |= 1 << PIPE_B;
 
 	if (single_plane_enabled(enabled) &&
-	    g4x_compute_srwm(dev, ffs(enabled) - 1,
+	    g4x_compute_srwm(dev_priv, ffs(enabled) - 1,
 			     sr_latency_ns,
 			     &g4x_wm_info,
 			     &g4x_cursor_wm_info,
@@ -1440,25 +1435,27 @@ static void g4x_update_wm(struct drm_crt
 		intel_set_memory_cxsr(dev_priv, true);
 }
 
-static void i965_update_wm(struct drm_crtc *unused_crtc)
+static void i965_update_wm(struct intel_crtc *unused_crtc)
 {
-	struct drm_device *dev = unused_crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *crtc;
+	struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
+	struct intel_crtc *crtc;
 	int srwm = 1;
 	int cursor_sr = 16;
 	bool cxsr_enabled;
 
 	/* Calc sr entries for one plane configs */
-	crtc = single_enabled_crtc(dev);
+	crtc = single_enabled_crtc(dev_priv);
 	if (crtc) {
 		/* self-refresh has much higher latency */
 		static const int sr_latency_ns = 12000;
-		const struct drm_display_mode *adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
+		const struct drm_display_mode *adjusted_mode =
+			&crtc->config->base.adjusted_mode;
+		const struct drm_framebuffer *fb =
+			crtc->base.primary->state->fb;
 		int clock = adjusted_mode->crtc_clock;
 		int htotal = adjusted_mode->crtc_htotal;
-		int hdisplay = to_intel_crtc(crtc)->config->pipe_src_w;
-		int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
+		int hdisplay = crtc->config->pipe_src_w;
+		int cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 		unsigned long line_time_us;
 		int entries;
 
@@ -1476,7 +1473,7 @@ static void i965_update_wm(struct drm_cr
 			      entries, srwm);
 
 		entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-			cpp * crtc->cursor->state->crtc_w;
+			cpp * crtc->base.cursor->state->crtc_w;
 		entries = DIV_ROUND_UP(entries,
 					  i965_cursor_wm_info.cacheline_size);
 		cursor_sr = i965_cursor_wm_info.fifo_size -
@@ -1514,34 +1511,38 @@ static void i965_update_wm(struct drm_cr
 
 #undef FW_WM
 
-static void i9xx_update_wm(struct drm_crtc *unused_crtc)
+static void i9xx_update_wm(struct intel_crtc *unused_crtc)
 {
-	struct drm_device *dev = unused_crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
 	const struct intel_watermark_params *wm_info;
 	uint32_t fwater_lo;
 	uint32_t fwater_hi;
 	int cwm, srwm = 1;
 	int fifo_size;
 	int planea_wm, planeb_wm;
-	struct drm_crtc *crtc, *enabled = NULL;
+	struct intel_crtc *crtc, *enabled = NULL;
 
-	if (IS_I945GM(dev))
+	if (IS_I945GM(dev_priv))
 		wm_info = &i945_wm_info;
-	else if (!IS_GEN2(dev))
+	else if (!IS_GEN2(dev_priv))
 		wm_info = &i915_wm_info;
 	else
 		wm_info = &i830_a_wm_info;
 
-	fifo_size = dev_priv->display.get_fifo_size(dev, 0);
-	crtc = intel_get_crtc_for_plane(dev, 0);
+	fifo_size = dev_priv->display.get_fifo_size(dev_priv, 0);
+	crtc = intel_get_crtc_for_plane(dev_priv, 0);
 	if (intel_crtc_active(crtc)) {
-		const struct drm_display_mode *adjusted_mode;
-		int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
-		if (IS_GEN2(dev))
+		const struct drm_display_mode *adjusted_mode =
+			&crtc->config->base.adjusted_mode;
+		const struct drm_framebuffer *fb =
+			crtc->base.primary->state->fb;
+		int cpp;
+
+		if (IS_GEN2(dev_priv))
 			cpp = 4;
+		else
+			cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
-		adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
 		planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
 					       wm_info, fifo_size, cpp,
 					       pessimal_latency_ns);
@@ -1552,18 +1553,23 @@ static void i9xx_update_wm(struct drm_cr
 			planea_wm = wm_info->max_wm;
 	}
 
-	if (IS_GEN2(dev))
+	if (IS_GEN2(dev_priv))
 		wm_info = &i830_bc_wm_info;
 
-	fifo_size = dev_priv->display.get_fifo_size(dev, 1);
-	crtc = intel_get_crtc_for_plane(dev, 1);
+	fifo_size = dev_priv->display.get_fifo_size(dev_priv, 1);
+	crtc = intel_get_crtc_for_plane(dev_priv, 1);
 	if (intel_crtc_active(crtc)) {
-		const struct drm_display_mode *adjusted_mode;
-		int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0);
-		if (IS_GEN2(dev))
+		const struct drm_display_mode *adjusted_mode =
+			&crtc->config->base.adjusted_mode;
+		const struct drm_framebuffer *fb =
+			crtc->base.primary->state->fb;
+		int cpp;
+
+		if (IS_GEN2(dev_priv))
 			cpp = 4;
+		else
+			cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
-		adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
 		planeb_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
 					       wm_info, fifo_size, cpp,
 					       pessimal_latency_ns);
@@ -1579,10 +1585,10 @@ static void i9xx_update_wm(struct drm_cr
 
 	DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
 
-	if (IS_I915GM(dev) && enabled) {
+	if (IS_I915GM(dev_priv) && enabled) {
 		struct drm_i915_gem_object *obj;
 
-		obj = intel_fb_obj(enabled->primary->state->fb);
+		obj = intel_fb_obj(enabled->base.primary->state->fb);
 
 		/* self-refresh seems busted with untiled */
 		if (!i915_gem_object_is_tiled(obj))
@@ -1598,19 +1604,24 @@ static void i9xx_update_wm(struct drm_cr
 	intel_set_memory_cxsr(dev_priv, false);
 
 	/* Calc sr entries for one plane configs */
-	if (HAS_FW_BLC(dev) && enabled) {
+	if (HAS_FW_BLC(dev_priv) && enabled) {
 		/* self-refresh has much higher latency */
 		static const int sr_latency_ns = 6000;
-		const struct drm_display_mode *adjusted_mode = &to_intel_crtc(enabled)->config->base.adjusted_mode;
+		const struct drm_display_mode *adjusted_mode =
+			&enabled->config->base.adjusted_mode;
+		const struct drm_framebuffer *fb =
+			enabled->base.primary->state->fb;
 		int clock = adjusted_mode->crtc_clock;
 		int htotal = adjusted_mode->crtc_htotal;
-		int hdisplay = to_intel_crtc(enabled)->config->pipe_src_w;
-		int cpp = drm_format_plane_cpp(enabled->primary->state->fb->pixel_format, 0);
+		int hdisplay = enabled->config->pipe_src_w;
+		int cpp;
 		unsigned long line_time_us;
 		int entries;
 
-		if (IS_I915GM(dev) || IS_I945GM(dev))
+		if (IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
 			cpp = 4;
+		else
+			cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
 		line_time_us = max(htotal * 1000 / clock, 1);
 
@@ -1623,7 +1634,7 @@ static void i9xx_update_wm(struct drm_cr
 		if (srwm < 0)
 			srwm = 1;
 
-		if (IS_I945G(dev) || IS_I945GM(dev))
+		if (IS_I945G(dev_priv) || IS_I945GM(dev_priv))
 			I915_WRITE(FW_BLC_SELF,
 				   FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
 		else
@@ -1647,23 +1658,22 @@ static void i9xx_update_wm(struct drm_cr
 		intel_set_memory_cxsr(dev_priv, true);
 }
 
-static void i845_update_wm(struct drm_crtc *unused_crtc)
+static void i845_update_wm(struct intel_crtc *unused_crtc)
 {
-	struct drm_device *dev = unused_crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_crtc *crtc;
+	struct drm_i915_private *dev_priv = to_i915(unused_crtc->base.dev);
+	struct intel_crtc *crtc;
 	const struct drm_display_mode *adjusted_mode;
 	uint32_t fwater_lo;
 	int planea_wm;
 
-	crtc = single_enabled_crtc(dev);
+	crtc = single_enabled_crtc(dev_priv);
 	if (crtc == NULL)
 		return;
 
-	adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode;
+	adjusted_mode = &crtc->config->base.adjusted_mode;
 	planea_wm = intel_calculate_wm(adjusted_mode->crtc_clock,
 				       &i845_wm_info,
-				       dev_priv->display.get_fifo_size(dev, 0),
+				       dev_priv->display.get_fifo_size(dev_priv, 0),
 				       4, pessimal_latency_ns);
 	fwater_lo = I915_READ(FW_BLC) & ~0xfff;
 	fwater_lo |= (3<<8) | planea_wm;
@@ -1852,23 +1862,25 @@ static uint32_t ilk_compute_fbc_wm(const
 	return ilk_wm_fbc(pri_val, drm_rect_width(&pstate->base.dst), cpp);
 }
 
-static unsigned int ilk_display_fifo_size(const struct drm_device *dev)
+static unsigned int
+ilk_display_fifo_size(const struct drm_i915_private *dev_priv)
 {
-	if (INTEL_INFO(dev)->gen >= 8)
+	if (INTEL_GEN(dev_priv) >= 8)
 		return 3072;
-	else if (INTEL_INFO(dev)->gen >= 7)
+	else if (INTEL_GEN(dev_priv) >= 7)
 		return 768;
 	else
 		return 512;
 }
 
-static unsigned int ilk_plane_wm_reg_max(const struct drm_device *dev,
-					 int level, bool is_sprite)
+static unsigned int
+ilk_plane_wm_reg_max(const struct drm_i915_private *dev_priv,
+		     int level, bool is_sprite)
 {
-	if (INTEL_INFO(dev)->gen >= 8)
+	if (INTEL_GEN(dev_priv) >= 8)
 		/* BDW primary/sprite plane watermarks */
 		return level == 0 ? 255 : 2047;
-	else if (INTEL_INFO(dev)->gen >= 7)
+	else if (INTEL_GEN(dev_priv) >= 7)
 		/* IVB/HSW primary/sprite plane watermarks */
 		return level == 0 ? 127 : 1023;
 	else if (!is_sprite)
@@ -1879,18 +1891,18 @@ static unsigned int ilk_plane_wm_reg_max
 		return level == 0 ? 63 : 255;
 }
 
-static unsigned int ilk_cursor_wm_reg_max(const struct drm_device *dev,
-					  int level)
+static unsigned int
+ilk_cursor_wm_reg_max(const struct drm_i915_private *dev_priv, int level)
 {
-	if (INTEL_INFO(dev)->gen >= 7)
+	if (INTEL_GEN(dev_priv) >= 7)
 		return level == 0 ? 63 : 255;
 	else
 		return level == 0 ? 31 : 63;
 }
 
-static unsigned int ilk_fbc_wm_reg_max(const struct drm_device *dev)
+static unsigned int ilk_fbc_wm_reg_max(const struct drm_i915_private *dev_priv)
 {
-	if (INTEL_INFO(dev)->gen >= 8)
+	if (INTEL_GEN(dev_priv) >= 8)
 		return 31;
 	else
 		return 15;
@@ -1903,7 +1915,8 @@ static unsigned int ilk_plane_wm_max(con
 				     enum intel_ddb_partitioning ddb_partitioning,
 				     bool is_sprite)
 {
-	unsigned int fifo_size = ilk_display_fifo_size(dev);
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	unsigned int fifo_size = ilk_display_fifo_size(dev_priv);
 
 	/* if sprites aren't enabled, sprites get nothing */
 	if (is_sprite && !config->sprites_enabled)
@@ -1911,14 +1924,14 @@ static unsigned int ilk_plane_wm_max(con
 
 	/* HSW allows LP1+ watermarks even with multiple pipes */
 	if (level == 0 || config->num_pipes_active > 1) {
-		fifo_size /= INTEL_INFO(dev)->num_pipes;
+		fifo_size /= INTEL_INFO(dev_priv)->num_pipes;
 
 		/*
 		 * For some reason the non self refresh
 		 * FIFO size is only half of the self
 		 * refresh FIFO size on ILK/SNB.
 		 */
-		if (INTEL_INFO(dev)->gen <= 6)
+		if (INTEL_GEN(dev_priv) <= 6)
 			fifo_size /= 2;
 	}
 
@@ -1934,7 +1947,7 @@ static unsigned int ilk_plane_wm_max(con
 	}
 
 	/* clamp to max that the registers can hold */
-	return min(fifo_size, ilk_plane_wm_reg_max(dev, level, is_sprite));
+	return min(fifo_size, ilk_plane_wm_reg_max(dev_priv, level, is_sprite));
 }
 
 /* Calculate the maximum cursor plane watermark */
@@ -1947,7 +1960,7 @@ static unsigned int ilk_cursor_wm_max(co
 		return 64;
 
 	/* otherwise just report max that registers can hold */
-	return ilk_cursor_wm_reg_max(dev, level);
+	return ilk_cursor_wm_reg_max(to_i915(dev), level);
 }
 
 static void ilk_compute_wm_maximums(const struct drm_device *dev,
@@ -1959,17 +1972,17 @@ static void ilk_compute_wm_maximums(cons
 	max->pri = ilk_plane_wm_max(dev, level, config, ddb_partitioning, false);
 	max->spr = ilk_plane_wm_max(dev, level, config, ddb_partitioning, true);
 	max->cur = ilk_cursor_wm_max(dev, level, config);
-	max->fbc = ilk_fbc_wm_reg_max(dev);
+	max->fbc = ilk_fbc_wm_reg_max(to_i915(dev));
 }
 
-static void ilk_compute_wm_reg_maximums(struct drm_device *dev,
+static void ilk_compute_wm_reg_maximums(const struct drm_i915_private *dev_priv,
 					int level,
 					struct ilk_wm_maximums *max)
 {
-	max->pri = ilk_plane_wm_reg_max(dev, level, false);
-	max->spr = ilk_plane_wm_reg_max(dev, level, true);
-	max->cur = ilk_cursor_wm_reg_max(dev, level);
-	max->fbc = ilk_fbc_wm_reg_max(dev);
+	max->pri = ilk_plane_wm_reg_max(dev_priv, level, false);
+	max->spr = ilk_plane_wm_reg_max(dev_priv, level, true);
+	max->cur = ilk_cursor_wm_reg_max(dev_priv, level);
+	max->fbc = ilk_fbc_wm_reg_max(dev_priv);
 }
 
 static bool ilk_validate_wm_level(int level,
@@ -2076,14 +2089,13 @@ hsw_compute_linetime_wm(const struct int
 	       PIPE_WM_LINETIME_TIME(linetime);
 }
 
-static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8])
+static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
+				  uint16_t wm[8])
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (IS_GEN9(dev)) {
+	if (IS_GEN9(dev_priv)) {
 		uint32_t val;
 		int ret, i;
-		int level, max_level = ilk_wm_max_level(dev);
+		int level, max_level = ilk_wm_max_level(dev_priv);
 
 		/* read the first set of memory latencies[0:3] */
 		val = 0; /* data0 to be programmed to 0 for first set */
@@ -2155,7 +2167,7 @@ static void intel_read_wm_latency(struct
 			}
 		}
 
-	} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 		uint64_t sskpd = I915_READ64(MCH_SSKPD);
 
 		wm[0] = (sskpd >> 56) & 0xFF;
@@ -2165,14 +2177,14 @@ static void intel_read_wm_latency(struct
 		wm[2] = (sskpd >> 12) & 0xFF;
 		wm[3] = (sskpd >> 20) & 0x1FF;
 		wm[4] = (sskpd >> 32) & 0x1FF;
-	} else if (INTEL_INFO(dev)->gen >= 6) {
+	} else if (INTEL_GEN(dev_priv) >= 6) {
 		uint32_t sskpd = I915_READ(MCH_SSKPD);
 
 		wm[0] = (sskpd >> SSKPD_WM0_SHIFT) & SSKPD_WM_MASK;
 		wm[1] = (sskpd >> SSKPD_WM1_SHIFT) & SSKPD_WM_MASK;
 		wm[2] = (sskpd >> SSKPD_WM2_SHIFT) & SSKPD_WM_MASK;
 		wm[3] = (sskpd >> SSKPD_WM3_SHIFT) & SSKPD_WM_MASK;
-	} else if (INTEL_INFO(dev)->gen >= 5) {
+	} else if (INTEL_GEN(dev_priv) >= 5) {
 		uint32_t mltr = I915_READ(MLTR_ILK);
 
 		/* ILK primary LP0 latency is 700 ns */
@@ -2182,42 +2194,44 @@ static void intel_read_wm_latency(struct
 	}
 }
 
-static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5])
+static void intel_fixup_spr_wm_latency(struct drm_i915_private *dev_priv,
+				       uint16_t wm[5])
 {
 	/* ILK sprite LP0 latency is 1300 ns */
-	if (IS_GEN5(dev))
+	if (IS_GEN5(dev_priv))
 		wm[0] = 13;
 }
 
-static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5])
+static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv,
+				       uint16_t wm[5])
 {
 	/* ILK cursor LP0 latency is 1300 ns */
-	if (IS_GEN5(dev))
+	if (IS_GEN5(dev_priv))
 		wm[0] = 13;
 
 	/* WaDoubleCursorLP3Latency:ivb */
-	if (IS_IVYBRIDGE(dev))
+	if (IS_IVYBRIDGE(dev_priv))
 		wm[3] *= 2;
 }
 
-int ilk_wm_max_level(const struct drm_device *dev)
+int ilk_wm_max_level(const struct drm_i915_private *dev_priv)
 {
 	/* how many WM levels are we expecting */
-	if (INTEL_INFO(dev)->gen >= 9)
+	if (INTEL_GEN(dev_priv) >= 9)
 		return 7;
-	else if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		return 4;
-	else if (INTEL_INFO(dev)->gen >= 6)
+	else if (INTEL_GEN(dev_priv) >= 6)
 		return 3;
 	else
 		return 2;
 }
 
-static void intel_print_wm_latency(struct drm_device *dev,
+static void intel_print_wm_latency(struct drm_i915_private *dev_priv,
 				   const char *name,
 				   const uint16_t wm[8])
 {
-	int level, max_level = ilk_wm_max_level(dev);
+	int level, max_level = ilk_wm_max_level(dev_priv);
 
 	for (level = 0; level <= max_level; level++) {
 		unsigned int latency = wm[level];
@@ -2232,7 +2246,7 @@ static void intel_print_wm_latency(struc
 		 * - latencies are in us on gen9.
 		 * - before then, WM1+ latency values are in 0.5us units
 		 */
-		if (IS_GEN9(dev))
+		if (IS_GEN9(dev_priv))
 			latency *= 10;
 		else if (level > 0)
 			latency *= 5;
@@ -2246,7 +2260,7 @@ static void intel_print_wm_latency(struc
 static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv,
 				    uint16_t wm[5], uint16_t min)
 {
-	int level, max_level = ilk_wm_max_level(&dev_priv->drm);
+	int level, max_level = ilk_wm_max_level(dev_priv);
 
 	if (wm[0] >= min)
 		return false;
@@ -2258,9 +2272,8 @@ static bool ilk_increase_wm_latency(stru
 	return true;
 }
 
-static void snb_wm_latency_quirk(struct drm_device *dev)
+static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	bool changed;
 
 	/*
@@ -2275,39 +2288,35 @@ static void snb_wm_latency_quirk(struct
 		return;
 
 	DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n");
-	intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
-	intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
-	intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
+	intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency);
+	intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
+	intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 }
 
-static void ilk_setup_wm_latency(struct drm_device *dev)
+static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	intel_read_wm_latency(dev, dev_priv->wm.pri_latency);
+	intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency);
 
 	memcpy(dev_priv->wm.spr_latency, dev_priv->wm.pri_latency,
 	       sizeof(dev_priv->wm.pri_latency));
 	memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency,
 	       sizeof(dev_priv->wm.pri_latency));
 
-	intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency);
-	intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency);
+	intel_fixup_spr_wm_latency(dev_priv, dev_priv->wm.spr_latency);
+	intel_fixup_cur_wm_latency(dev_priv, dev_priv->wm.cur_latency);
 
-	intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency);
-	intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency);
-	intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency);
+	intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency);
+	intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
+	intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 
-	if (IS_GEN6(dev))
-		snb_wm_latency_quirk(dev);
+	if (IS_GEN6(dev_priv))
+		snb_wm_latency_quirk(dev_priv);
 }
 
-static void skl_setup_wm_latency(struct drm_device *dev)
+static void skl_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	intel_read_wm_latency(dev, dev_priv->wm.skl_latency);
-	intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency);
+	intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency);
+	intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency);
 }
 
 static bool ilk_validate_pipe_wm(struct drm_device *dev,
@@ -2345,7 +2354,7 @@ static int ilk_compute_pipe_wm(struct in
 	struct intel_plane_state *pristate = NULL;
 	struct intel_plane_state *sprstate = NULL;
 	struct intel_plane_state *curstate = NULL;
-	int level, max_level = ilk_wm_max_level(dev), usable_level;
+	int level, max_level = ilk_wm_max_level(dev_priv), usable_level;
 	struct ilk_wm_maximums max;
 
 	pipe_wm = &cstate->wm.ilk.optimal;
@@ -2377,7 +2386,7 @@ static int ilk_compute_pipe_wm(struct in
 	usable_level = max_level;
 
 	/* ILK/SNB: LP2+ watermarks only w/o sprites */
-	if (INTEL_INFO(dev)->gen <= 6 && pipe_wm->sprites_enabled)
+	if (INTEL_GEN(dev_priv) <= 6 && pipe_wm->sprites_enabled)
 		usable_level = 1;
 
 	/* ILK/SNB/IVB: LP1+ watermarks only w/o scaling */
@@ -2390,13 +2399,13 @@ static int ilk_compute_pipe_wm(struct in
 	memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm));
 	pipe_wm->wm[0] = pipe_wm->raw_wm[0];
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		pipe_wm->linetime = hsw_compute_linetime_wm(cstate);
 
 	if (!ilk_validate_pipe_wm(dev, pipe_wm))
 		return -EINVAL;
 
-	ilk_compute_wm_reg_maximums(dev, 1, &max);
+	ilk_compute_wm_reg_maximums(dev_priv, 1, &max);
 
 	for (level = 1; level <= max_level; level++) {
 		struct intel_wm_level *wm = &pipe_wm->raw_wm[level];
@@ -2432,7 +2441,7 @@ static int ilk_compute_intermediate_wm(s
 {
 	struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate;
 	struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk;
-	int level, max_level = ilk_wm_max_level(dev);
+	int level, max_level = ilk_wm_max_level(to_i915(dev));
 
 	/*
 	 * Start with the final, target watermarks, then combine with the
@@ -2516,16 +2525,16 @@ static void ilk_wm_merge(struct drm_devi
 			 struct intel_pipe_wm *merged)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int level, max_level = ilk_wm_max_level(dev);
+	int level, max_level = ilk_wm_max_level(dev_priv);
 	int last_enabled_level = max_level;
 
 	/* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */
-	if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) &&
+	if ((INTEL_GEN(dev_priv) <= 6 || IS_IVYBRIDGE(dev_priv)) &&
 	    config->num_pipes_active > 1)
 		last_enabled_level = 0;
 
 	/* ILK: FBC WM must be disabled always */
-	merged->fbc_wm_enabled = INTEL_INFO(dev)->gen >= 6;
+	merged->fbc_wm_enabled = INTEL_GEN(dev_priv) >= 6;
 
 	/* merge each WM1+ level */
 	for (level = 1; level <= max_level; level++) {
@@ -2556,7 +2565,7 @@ static void ilk_wm_merge(struct drm_devi
 	 * What we should check here is whether FBC can be
 	 * enabled sometime later.
 	 */
-	if (IS_GEN5(dev) && !merged->fbc_wm_enabled &&
+	if (IS_GEN5(dev_priv) && !merged->fbc_wm_enabled &&
 	    intel_fbc_is_active(dev_priv)) {
 		for (level = 2; level <= max_level; level++) {
 			struct intel_wm_level *wm = &merged->wm[level];
@@ -2577,7 +2586,7 @@ static unsigned int ilk_wm_lp_latency(st
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		return 2 * level;
 	else
 		return dev_priv->wm.pri_latency[level];
@@ -2588,6 +2597,7 @@ static void ilk_compute_wm_results(struc
 				   enum intel_ddb_partitioning partitioning,
 				   struct ilk_wm_values *results)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *intel_crtc;
 	int level, wm_lp;
 
@@ -2614,7 +2624,7 @@ static void ilk_compute_wm_results(struc
 		if (r->enable)
 			results->wm_lp[wm_lp - 1] |= WM1_LP_SR_EN;
 
-		if (INTEL_INFO(dev)->gen >= 8)
+		if (INTEL_GEN(dev_priv) >= 8)
 			results->wm_lp[wm_lp - 1] |=
 				r->fbc_val << WM1_LP_FBC_SHIFT_BDW;
 		else
@@ -2625,7 +2635,7 @@ static void ilk_compute_wm_results(struc
 		 * Always set WM1S_LP_EN when spr_val != 0, even if the
 		 * level is disabled. Doing otherwise could cause underruns.
 		 */
-		if (INTEL_INFO(dev)->gen <= 6 && r->spr_val) {
+		if (INTEL_GEN(dev_priv) <= 6 && r->spr_val) {
 			WARN_ON(wm_lp != 1);
 			results->wm_lp_spr[wm_lp - 1] = WM1S_LP_EN | r->spr_val;
 		} else
@@ -2656,7 +2666,7 @@ static struct intel_pipe_wm *ilk_find_be
 						  struct intel_pipe_wm *r1,
 						  struct intel_pipe_wm *r2)
 {
-	int level, max_level = ilk_wm_max_level(dev);
+	int level, max_level = ilk_wm_max_level(to_i915(dev));
 	int level1 = 0, level2 = 0;
 
 	for (level = 1; level <= max_level; level++) {
@@ -2775,7 +2785,6 @@ static bool _ilk_disable_lp_wm(struct dr
 static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
 				struct ilk_wm_values *results)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	struct ilk_wm_values *previous = &dev_priv->wm.hw;
 	unsigned int dirty;
 	uint32_t val;
@@ -2801,7 +2810,7 @@ static void ilk_write_wm_values(struct d
 		I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]);
 
 	if (dirty & WM_DIRTY_DDB) {
-		if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
+		if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
 			val = I915_READ(WM_MISC);
 			if (results->partitioning == INTEL_DDB_PART_1_2)
 				val &= ~WM_MISC_DATA_PARTITION_5_6;
@@ -2831,7 +2840,7 @@ static void ilk_write_wm_values(struct d
 	    previous->wm_lp_spr[0] != results->wm_lp_spr[0])
 		I915_WRITE(WM1S_LP_ILK, results->wm_lp_spr[0]);
 
-	if (INTEL_INFO(dev)->gen >= 7) {
+	if (INTEL_GEN(dev_priv) >= 7) {
 		if (dirty & WM_DIRTY_LP(2) && previous->wm_lp_spr[1] != results->wm_lp_spr[1])
 			I915_WRITE(WM2S_LP_IVB, results->wm_lp_spr[1]);
 		if (dirty & WM_DIRTY_LP(3) && previous->wm_lp_spr[2] != results->wm_lp_spr[2])
@@ -2879,6 +2888,21 @@ skl_wm_plane_id(const struct intel_plane
 	}
 }
 
+/*
+ * FIXME: We still don't have the proper code detect if we need to apply the WA,
+ * so assume we'll always need it in order to avoid underruns.
+ */
+static bool skl_needs_memory_bw_wa(struct intel_atomic_state *state)
+{
+	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
+
+	if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) ||
+	    IS_KABYLAKE(dev_priv))
+		return true;
+
+	return false;
+}
+
 static bool
 intel_has_sagv(struct drm_i915_private *dev_priv)
 {
@@ -2940,24 +2964,10 @@ intel_enable_sagv(struct drm_i915_privat
 	return 0;
 }
 
-static int
-intel_do_sagv_disable(struct drm_i915_private *dev_priv)
-{
-	int ret;
-	uint32_t temp = GEN9_SAGV_DISABLE;
-
-	ret = sandybridge_pcode_read(dev_priv, GEN9_PCODE_SAGV_CONTROL,
-				     &temp);
-	if (ret)
-		return ret;
-	else
-		return temp & GEN9_SAGV_IS_DISABLED;
-}
-
 int
 intel_disable_sagv(struct drm_i915_private *dev_priv)
 {
-	int ret, result;
+	int ret;
 
 	if (!intel_has_sagv(dev_priv))
 		return 0;
@@ -2969,25 +2979,23 @@ intel_disable_sagv(struct drm_i915_priva
 	mutex_lock(&dev_priv->rps.hw_lock);
 
 	/* bspec says to keep retrying for at least 1 ms */
-	ret = wait_for(result = intel_do_sagv_disable(dev_priv), 1);
+	ret = skl_pcode_request(dev_priv, GEN9_PCODE_SAGV_CONTROL,
+				GEN9_SAGV_DISABLE,
+				GEN9_SAGV_IS_DISABLED, GEN9_SAGV_IS_DISABLED,
+				1);
 	mutex_unlock(&dev_priv->rps.hw_lock);
 
-	if (ret == -ETIMEDOUT) {
-		DRM_ERROR("Request to disable SAGV timed out\n");
-		return -ETIMEDOUT;
-	}
-
 	/*
 	 * Some skl systems, pre-release machines in particular,
 	 * don't actually have an SAGV.
 	 */
-	if (IS_SKYLAKE(dev_priv) && result == -ENXIO) {
+	if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) {
 		DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n");
 		dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED;
 		return 0;
-	} else if (result < 0) {
-		DRM_ERROR("Failed to disable the SAGV\n");
-		return result;
+	} else if (ret < 0) {
+		DRM_ERROR("Failed to disable the SAGV (%d)\n", ret);
+		return ret;
 	}
 
 	dev_priv->sagv_status = I915_SAGV_DISABLED;
@@ -2999,9 +3007,12 @@ bool intel_can_enable_sagv(struct drm_at
 	struct drm_device *dev = state->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
-	struct drm_crtc *crtc;
+	struct intel_crtc *crtc;
+	struct intel_plane *plane;
+	struct intel_crtc_state *cstate;
+	struct skl_plane_wm *wm;
 	enum pipe pipe;
-	int level, plane;
+	int level, latency;
 
 	if (!intel_has_sagv(dev_priv))
 		return false;
@@ -3019,27 +3030,37 @@ bool intel_can_enable_sagv(struct drm_at
 
 	/* Since we're now guaranteed to only have one active CRTC... */
 	pipe = ffs(intel_state->active_crtcs) - 1;
-	crtc = dev_priv->pipe_to_crtc_mapping[pipe];
+	crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+	cstate = to_intel_crtc_state(crtc->base.state);
 
-	if (crtc->state->mode.flags & DRM_MODE_FLAG_INTERLACE)
+	if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
 		return false;
 
-	for_each_plane(dev_priv, pipe, plane) {
+	for_each_intel_plane_on_crtc(dev, crtc, plane) {
+		wm = &cstate->wm.skl.optimal.planes[skl_wm_plane_id(plane)];
+
 		/* Skip this plane if it's not enabled */
-		if (intel_state->wm_results.plane[pipe][plane][0] == 0)
+		if (!wm->wm[0].plane_en)
 			continue;
 
 		/* Find the highest enabled wm level for this plane */
-		for (level = ilk_wm_max_level(dev);
-		     intel_state->wm_results.plane[pipe][plane][level] == 0; --level)
+		for (level = ilk_wm_max_level(dev_priv);
+		     !wm->wm[level].plane_en; --level)
 		     { }
 
+		latency = dev_priv->wm.skl_latency[level];
+
+		if (skl_needs_memory_bw_wa(intel_state) &&
+		    plane->base.state->fb->modifier ==
+		    I915_FORMAT_MOD_X_TILED)
+			latency += 15;
+
 		/*
 		 * If any of the planes on this pipe don't enable wm levels
 		 * that incur memory latencies higher then 30µs we can't enable
 		 * the SAGV
 		 */
-		if (dev_priv->wm.skl_latency[level] < SKL_SAGV_BLOCK_TIME)
+		if (latency < SKL_SAGV_BLOCK_TIME)
 			return false;
 	}
 
@@ -3058,7 +3079,6 @@ skl_ddb_get_pipe_allocation_limits(struc
 	struct drm_crtc *for_crtc = cstate->base.crtc;
 	unsigned int pipe_size, ddb_size;
 	int nth_active_pipe;
-	int pipe = to_intel_crtc(for_crtc)->pipe;
 
 	if (WARN_ON(!state) || !cstate->base.active) {
 		alloc->start = 0;
@@ -3086,7 +3106,11 @@ skl_ddb_get_pipe_allocation_limits(struc
 	 * we currently hold.
 	 */
 	if (!intel_state->active_pipe_changes) {
-		*alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe];
+		/*
+		 * alloc may be cleared by clear_intel_crtc_state,
+		 * copy from old state to be sure
+		 */
+		*alloc = to_intel_crtc_state(for_crtc->state)->wm.skl.ddb;
 		return;
 	}
 
@@ -3129,7 +3153,7 @@ void skl_ddb_get_hw_state(struct drm_i91
 		if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
 			continue;
 
-		for_each_plane(dev_priv, pipe, plane) {
+		for_each_universal_plane(dev_priv, pipe, plane) {
 			val = I915_READ(PLANE_BUF_CFG(pipe, plane));
 			skl_ddb_entry_init_from_hw(&ddb->plane[pipe][plane],
 						   val);
@@ -3173,7 +3197,7 @@ skl_plane_downscale_amount(const struct
 	src_h = drm_rect_height(&pstate->base.src);
 	dst_w = drm_rect_width(&pstate->base.dst);
 	dst_h = drm_rect_height(&pstate->base.dst);
-	if (intel_rotation_90_or_270(pstate->base.rotation))
+	if (drm_rotation_90_or_270(pstate->base.rotation))
 		swap(dst_w, dst_h);
 
 	downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
@@ -3204,7 +3228,7 @@ skl_plane_relative_data_rate(const struc
 	width = drm_rect_width(&intel_pstate->base.src) >> 16;
 	height = drm_rect_height(&intel_pstate->base.src) >> 16;
 
-	if (intel_rotation_90_or_270(pstate->rotation))
+	if (drm_rotation_90_or_270(pstate->rotation))
 		swap(width, height);
 
 	/* for planar format */
@@ -3231,49 +3255,39 @@ skl_plane_relative_data_rate(const struc
  *   3 * 4096 * 8192  * 4 < 2^32
  */
 static unsigned int
-skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
+skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate,
+				 unsigned *plane_data_rate,
+				 unsigned *plane_y_data_rate)
 {
 	struct drm_crtc_state *cstate = &intel_cstate->base;
 	struct drm_atomic_state *state = cstate->state;
-	struct drm_crtc *crtc = cstate->crtc;
-	struct drm_device *dev = crtc->dev;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	const struct drm_plane *plane;
+	struct drm_plane *plane;
 	const struct intel_plane *intel_plane;
-	struct drm_plane_state *pstate;
+	const struct drm_plane_state *pstate;
 	unsigned int rate, total_data_rate = 0;
 	int id;
-	int i;
 
 	if (WARN_ON(!state))
 		return 0;
 
 	/* Calculate and cache data rate for each plane */
-	for_each_plane_in_state(state, plane, pstate, i) {
+	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, cstate) {
 		id = skl_wm_plane_id(to_intel_plane(plane));
 		intel_plane = to_intel_plane(plane);
 
-		if (intel_plane->pipe != intel_crtc->pipe)
-			continue;
-
 		/* packed/uv */
 		rate = skl_plane_relative_data_rate(intel_cstate,
 						    pstate, 0);
-		intel_cstate->wm.skl.plane_data_rate[id] = rate;
+		plane_data_rate[id] = rate;
+
+		total_data_rate += rate;
 
 		/* y-plane */
 		rate = skl_plane_relative_data_rate(intel_cstate,
 						    pstate, 1);
-		intel_cstate->wm.skl.plane_y_data_rate[id] = rate;
-	}
-
-	/* Calculate CRTC's total data rate from cached values */
-	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
-		int id = skl_wm_plane_id(intel_plane);
+		plane_y_data_rate[id] = rate;
 
-		/* packed/uv */
-		total_data_rate += intel_cstate->wm.skl.plane_data_rate[id];
-		total_data_rate += intel_cstate->wm.skl.plane_y_data_rate[id];
+		total_data_rate += rate;
 	}
 
 	return total_data_rate;
@@ -3297,14 +3311,14 @@ skl_ddb_min_alloc(const struct drm_plane
 		return 0;
 
 	/* For Non Y-tile return 8-blocks */
-	if (fb->modifier[0] != I915_FORMAT_MOD_Y_TILED &&
-	    fb->modifier[0] != I915_FORMAT_MOD_Yf_TILED)
+	if (fb->modifier != I915_FORMAT_MOD_Y_TILED &&
+	    fb->modifier != I915_FORMAT_MOD_Yf_TILED)
 		return 8;
 
 	src_w = drm_rect_width(&intel_pstate->base.src) >> 16;
 	src_h = drm_rect_height(&intel_pstate->base.src) >> 16;
 
-	if (intel_rotation_90_or_270(pstate->rotation))
+	if (drm_rotation_90_or_270(pstate->rotation))
 		swap(src_w, src_h);
 
 	/* Halve UV plane width and height for NV12 */
@@ -3318,7 +3332,7 @@ skl_ddb_min_alloc(const struct drm_plane
 	else
 		plane_bpp = drm_format_plane_cpp(fb->pixel_format, 0);
 
-	if (intel_rotation_90_or_270(pstate->rotation)) {
+	if (drm_rotation_90_or_270(pstate->rotation)) {
 		switch (plane_bpp) {
 		case 1:
 			min_scanlines = 32;
@@ -3342,6 +3356,30 @@ skl_ddb_min_alloc(const struct drm_plane
 	return DIV_ROUND_UP((4 * src_w * plane_bpp), 512) * min_scanlines/4 + 3;
 }
 
+static void
+skl_ddb_calc_min(const struct intel_crtc_state *cstate, int num_active,
+		 uint16_t *minimum, uint16_t *y_minimum)
+{
+	const struct drm_plane_state *pstate;
+	struct drm_plane *plane;
+
+	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, &cstate->base) {
+		struct intel_plane *intel_plane = to_intel_plane(plane);
+		int id = skl_wm_plane_id(intel_plane);
+
+		if (id == PLANE_CURSOR)
+			continue;
+
+		if (!pstate->visible)
+			continue;
+
+		minimum[id] = skl_ddb_min_alloc(pstate, 0);
+		y_minimum[id] = skl_ddb_min_alloc(pstate, 1);
+	}
+
+	minimum[PLANE_CURSOR] = skl_cursor_allocation(num_active);
+}
+
 static int
 skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
 		      struct skl_ddb_allocation *ddb /* out */)
@@ -3350,17 +3388,16 @@ skl_allocate_pipe_ddb(struct intel_crtc_
 	struct drm_crtc *crtc = cstate->base.crtc;
 	struct drm_device *dev = crtc->dev;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_plane *intel_plane;
-	struct drm_plane *plane;
-	struct drm_plane_state *pstate;
 	enum pipe pipe = intel_crtc->pipe;
-	struct skl_ddb_entry *alloc = &ddb->pipe[pipe];
-	uint16_t alloc_size, start, cursor_blocks;
-	uint16_t *minimum = cstate->wm.skl.minimum_blocks;
-	uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks;
+	struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb;
+	uint16_t alloc_size, start;
+	uint16_t minimum[I915_MAX_PLANES] = {};
+	uint16_t y_minimum[I915_MAX_PLANES] = {};
 	unsigned int total_data_rate;
 	int num_active;
 	int id, i;
+	unsigned plane_data_rate[I915_MAX_PLANES] = {};
+	unsigned plane_y_data_rate[I915_MAX_PLANES] = {};
 
 	/* Clear the partitioning for disabled planes. */
 	memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
@@ -3370,7 +3407,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_
 		return 0;
 
 	if (!cstate->base.active) {
-		ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0;
+		alloc->start = alloc->end = 0;
 		return 0;
 	}
 
@@ -3381,57 +3418,43 @@ skl_allocate_pipe_ddb(struct intel_crtc_
 		return 0;
 	}
 
-	cursor_blocks = skl_cursor_allocation(num_active);
-	ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - cursor_blocks;
-	ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
-
-	alloc_size -= cursor_blocks;
-
-	/* 1. Allocate the mininum required blocks for each active plane */
-	for_each_plane_in_state(state, plane, pstate, i) {
-		intel_plane = to_intel_plane(plane);
-		id = skl_wm_plane_id(intel_plane);
-
-		if (intel_plane->pipe != pipe)
-			continue;
-
-		if (!to_intel_plane_state(pstate)->base.visible) {
-			minimum[id] = 0;
-			y_minimum[id] = 0;
-			continue;
-		}
-		if (plane->type == DRM_PLANE_TYPE_CURSOR) {
-			minimum[id] = 0;
-			y_minimum[id] = 0;
-			continue;
-		}
+	skl_ddb_calc_min(cstate, num_active, minimum, y_minimum);
 
-		minimum[id] = skl_ddb_min_alloc(pstate, 0);
-		y_minimum[id] = skl_ddb_min_alloc(pstate, 1);
-	}
+	/*
+	 * 1. Allocate the mininum required blocks for each active plane
+	 * and allocate the cursor, it doesn't require extra allocation
+	 * proportional to the data rate.
+	 */
 
-	for (i = 0; i < PLANE_CURSOR; i++) {
+	for (i = 0; i < I915_MAX_PLANES; i++) {
 		alloc_size -= minimum[i];
 		alloc_size -= y_minimum[i];
 	}
 
+	ddb->plane[pipe][PLANE_CURSOR].start = alloc->end - minimum[PLANE_CURSOR];
+	ddb->plane[pipe][PLANE_CURSOR].end = alloc->end;
+
 	/*
 	 * 2. Distribute the remaining space in proportion to the amount of
 	 * data each plane needs to fetch from memory.
 	 *
 	 * FIXME: we may not allocate every single block here.
 	 */
-	total_data_rate = skl_get_total_relative_data_rate(cstate);
+	total_data_rate = skl_get_total_relative_data_rate(cstate,
+							   plane_data_rate,
+							   plane_y_data_rate);
 	if (total_data_rate == 0)
 		return 0;
 
 	start = alloc->start;
-	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+	for (id = 0; id < I915_MAX_PLANES; id++) {
 		unsigned int data_rate, y_data_rate;
 		uint16_t plane_blocks, y_plane_blocks = 0;
-		int id = skl_wm_plane_id(intel_plane);
 
-		data_rate = cstate->wm.skl.plane_data_rate[id];
+		if (id == PLANE_CURSOR)
+			continue;
+
+		data_rate = plane_data_rate[id];
 
 		/*
 		 * allocation for (packed formats) or (uv-plane part of planar format):
@@ -3453,7 +3476,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_
 		/*
 		 * allocation for y_plane part of planar format:
 		 */
-		y_data_rate = cstate->wm.skl.plane_y_data_rate[id];
+		y_data_rate = plane_y_data_rate[id];
 
 		y_plane_blocks = y_minimum[id];
 		y_plane_blocks += div_u64((uint64_t)alloc_size * y_data_rate,
@@ -3549,22 +3572,28 @@ static int skl_compute_plane_wm(const st
 	uint32_t width = 0, height = 0;
 	uint32_t plane_pixel_rate;
 	uint32_t y_tile_minimum, y_min_scanlines;
+	struct intel_atomic_state *state =
+		to_intel_atomic_state(cstate->base.state);
+	bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state);
 
 	if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) {
 		*enabled = false;
 		return 0;
 	}
 
+	if (apply_memory_bw_wa && fb->modifier == I915_FORMAT_MOD_X_TILED)
+		latency += 15;
+
 	width = drm_rect_width(&intel_pstate->base.src) >> 16;
 	height = drm_rect_height(&intel_pstate->base.src) >> 16;
 
-	if (intel_rotation_90_or_270(pstate->rotation))
+	if (drm_rotation_90_or_270(pstate->rotation))
 		swap(width, height);
 
 	cpp = drm_format_plane_cpp(fb->pixel_format, 0);
 	plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate);
 
-	if (intel_rotation_90_or_270(pstate->rotation)) {
+	if (drm_rotation_90_or_270(pstate->rotation)) {
 		int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ?
 			drm_format_plane_cpp(fb->pixel_format, 1) :
 			drm_format_plane_cpp(fb->pixel_format, 0);
@@ -3576,23 +3605,27 @@ static int skl_compute_plane_wm(const st
 		case 2:
 			y_min_scanlines = 8;
 			break;
-		default:
-			WARN(1, "Unsupported pixel depth for rotation");
 		case 4:
 			y_min_scanlines = 4;
 			break;
+		default:
+			MISSING_CASE(cpp);
+			return -EINVAL;
 		}
 	} else {
 		y_min_scanlines = 4;
 	}
 
+	if (apply_memory_bw_wa)
+		y_min_scanlines *= 2;
+
 	plane_bytes_per_line = width * cpp;
-	if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
-	    fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
+	if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
+	    fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
 		plane_blocks_per_line =
 		      DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512);
 		plane_blocks_per_line /= y_min_scanlines;
-	} else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) {
+	} else if (fb->modifier == DRM_FORMAT_MOD_NONE) {
 		plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512)
 					+ 1;
 	} else {
@@ -3607,11 +3640,14 @@ static int skl_compute_plane_wm(const st
 
 	y_tile_minimum = plane_blocks_per_line * y_min_scanlines;
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
-	    fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
+	if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
+	    fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
 		selected_result = max(method2, y_tile_minimum);
 	} else {
-		if ((ddb_allocation / plane_blocks_per_line) >= 1)
+		if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) &&
+		    (plane_bytes_per_line / 512 < 1))
+			selected_result = method2;
+		else if ((ddb_allocation / plane_blocks_per_line) >= 1)
 			selected_result = min(method1, method2);
 		else
 			selected_result = method1;
@@ -3621,8 +3657,8 @@ static int skl_compute_plane_wm(const st
 	res_lines = DIV_ROUND_UP(selected_result, plane_blocks_per_line);
 
 	if (level >= 1 && level <= 7) {
-		if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
-		    fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) {
+		if (fb->modifier == I915_FORMAT_MOD_Y_TILED ||
+		    fb->modifier == I915_FORMAT_MOD_Yf_TILED) {
 			res_blocks += y_tile_minimum;
 			res_lines += y_min_scanlines;
 		} else {
@@ -3661,67 +3697,52 @@ static int
 skl_compute_wm_level(const struct drm_i915_private *dev_priv,
 		     struct skl_ddb_allocation *ddb,
 		     struct intel_crtc_state *cstate,
+		     struct intel_plane *intel_plane,
 		     int level,
 		     struct skl_wm_level *result)
 {
 	struct drm_atomic_state *state = cstate->base.state;
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
-	struct drm_plane *plane;
-	struct intel_plane *intel_plane;
-	struct intel_plane_state *intel_pstate;
+	struct drm_plane *plane = &intel_plane->base;
+	struct intel_plane_state *intel_pstate = NULL;
 	uint16_t ddb_blocks;
 	enum pipe pipe = intel_crtc->pipe;
 	int ret;
+	int i = skl_wm_plane_id(intel_plane);
+
+	if (state)
+		intel_pstate =
+			intel_atomic_get_existing_plane_state(state,
+							      intel_plane);
 
 	/*
-	 * We'll only calculate watermarks for planes that are actually
-	 * enabled, so make sure all other planes are set as disabled.
+	 * Note: If we start supporting multiple pending atomic commits against
+	 * the same planes/CRTC's in the future, plane->state will no longer be
+	 * the correct pre-state to use for the calculations here and we'll
+	 * need to change where we get the 'unchanged' plane data from.
+	 *
+	 * For now this is fine because we only allow one queued commit against
+	 * a CRTC.  Even if the plane isn't modified by this transaction and we
+	 * don't have a plane lock, we still have the CRTC's lock, so we know
+	 * that no other transactions are racing with us to update it.
 	 */
-	memset(result, 0, sizeof(*result));
-
-	for_each_intel_plane_mask(&dev_priv->drm,
-				  intel_plane,
-				  cstate->base.plane_mask) {
-		int i = skl_wm_plane_id(intel_plane);
-
-		plane = &intel_plane->base;
-		intel_pstate = NULL;
-		if (state)
-			intel_pstate =
-				intel_atomic_get_existing_plane_state(state,
-								      intel_plane);
-
-		/*
-		 * Note: If we start supporting multiple pending atomic commits
-		 * against the same planes/CRTC's in the future, plane->state
-		 * will no longer be the correct pre-state to use for the
-		 * calculations here and we'll need to change where we get the
-		 * 'unchanged' plane data from.
-		 *
-		 * For now this is fine because we only allow one queued commit
-		 * against a CRTC.  Even if the plane isn't modified by this
-		 * transaction and we don't have a plane lock, we still have
-		 * the CRTC's lock, so we know that no other transactions are
-		 * racing with us to update it.
-		 */
-		if (!intel_pstate)
-			intel_pstate = to_intel_plane_state(plane->state);
+	if (!intel_pstate)
+		intel_pstate = to_intel_plane_state(plane->state);
 
-		WARN_ON(!intel_pstate->base.fb);
+	WARN_ON(!intel_pstate->base.fb);
 
-		ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
+	ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]);
 
-		ret = skl_compute_plane_wm(dev_priv,
-					   cstate,
-					   intel_pstate,
-					   ddb_blocks,
-					   level,
-					   &result->plane_res_b[i],
-					   &result->plane_res_l[i],
-					   &result->plane_en[i]);
-		if (ret)
-			return ret;
-	}
+	ret = skl_compute_plane_wm(dev_priv,
+				   cstate,
+				   intel_pstate,
+				   ddb_blocks,
+				   level,
+				   &result->plane_res_b,
+				   &result->plane_res_l,
+				   &result->plane_en);
+	if (ret)
+		return ret;
 
 	return 0;
 }
@@ -3729,32 +3750,28 @@ skl_compute_wm_level(const struct drm_i9
 static uint32_t
 skl_compute_linetime_wm(struct intel_crtc_state *cstate)
 {
+	uint32_t pixel_rate;
+
 	if (!cstate->base.active)
 		return 0;
 
-	if (WARN_ON(ilk_pipe_pixel_rate(cstate) == 0))
+	pixel_rate = ilk_pipe_pixel_rate(cstate);
+
+	if (WARN_ON(pixel_rate == 0))
 		return 0;
 
 	return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000,
-			    ilk_pipe_pixel_rate(cstate));
+			    pixel_rate);
 }
 
 static void skl_compute_transition_wm(struct intel_crtc_state *cstate,
 				      struct skl_wm_level *trans_wm /* out */)
 {
-	struct drm_crtc *crtc = cstate->base.crtc;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_plane *intel_plane;
-
 	if (!cstate->base.active)
 		return;
 
 	/* Until we know more, just disable transition WMs */
-	for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) {
-		int i = skl_wm_plane_id(intel_plane);
-
-		trans_wm->plane_en[i] = false;
-	}
+	trans_wm->plane_en = false;
 }
 
 static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
@@ -3763,77 +3780,34 @@ static int skl_build_pipe_wm(struct inte
 {
 	struct drm_device *dev = cstate->base.crtc->dev;
 	const struct drm_i915_private *dev_priv = to_i915(dev);
-	int level, max_level = ilk_wm_max_level(dev);
+	struct intel_plane *intel_plane;
+	struct skl_plane_wm *wm;
+	int level, max_level = ilk_wm_max_level(dev_priv);
 	int ret;
 
-	for (level = 0; level <= max_level; level++) {
-		ret = skl_compute_wm_level(dev_priv, ddb, cstate,
-					   level, &pipe_wm->wm[level]);
-		if (ret)
-			return ret;
-	}
-	pipe_wm->linetime = skl_compute_linetime_wm(cstate);
-
-	skl_compute_transition_wm(cstate, &pipe_wm->trans_wm);
-
-	return 0;
-}
-
-static void skl_compute_wm_results(struct drm_device *dev,
-				   struct skl_pipe_wm *p_wm,
-				   struct skl_wm_values *r,
-				   struct intel_crtc *intel_crtc)
-{
-	int level, max_level = ilk_wm_max_level(dev);
-	enum pipe pipe = intel_crtc->pipe;
-	uint32_t temp;
-	int i;
-
-	for (level = 0; level <= max_level; level++) {
-		for (i = 0; i < intel_num_planes(intel_crtc); i++) {
-			temp = 0;
+	/*
+	 * We'll only calculate watermarks for planes that are actually
+	 * enabled, so make sure all other planes are set as disabled.
+	 */
+	memset(pipe_wm->planes, 0, sizeof(pipe_wm->planes));
 
-			temp |= p_wm->wm[level].plane_res_l[i] <<
-					PLANE_WM_LINES_SHIFT;
-			temp |= p_wm->wm[level].plane_res_b[i];
-			if (p_wm->wm[level].plane_en[i])
-				temp |= PLANE_WM_EN;
+	for_each_intel_plane_mask(&dev_priv->drm,
+				  intel_plane,
+				  cstate->base.plane_mask) {
+		wm = &pipe_wm->planes[skl_wm_plane_id(intel_plane)];
 
-			r->plane[pipe][i][level] = temp;
+		for (level = 0; level <= max_level; level++) {
+			ret = skl_compute_wm_level(dev_priv, ddb, cstate,
+						   intel_plane, level,
+						   &wm->wm[level]);
+			if (ret)
+				return ret;
 		}
-
-		temp = 0;
-
-		temp |= p_wm->wm[level].plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT;
-		temp |= p_wm->wm[level].plane_res_b[PLANE_CURSOR];
-
-		if (p_wm->wm[level].plane_en[PLANE_CURSOR])
-			temp |= PLANE_WM_EN;
-
-		r->plane[pipe][PLANE_CURSOR][level] = temp;
-
-	}
-
-	/* transition WMs */
-	for (i = 0; i < intel_num_planes(intel_crtc); i++) {
-		temp = 0;
-		temp |= p_wm->trans_wm.plane_res_l[i] << PLANE_WM_LINES_SHIFT;
-		temp |= p_wm->trans_wm.plane_res_b[i];
-		if (p_wm->trans_wm.plane_en[i])
-			temp |= PLANE_WM_EN;
-
-		r->plane_trans[pipe][i] = temp;
+		skl_compute_transition_wm(cstate, &wm->trans_wm);
 	}
+	pipe_wm->linetime = skl_compute_linetime_wm(cstate);
 
-	temp = 0;
-	temp |= p_wm->trans_wm.plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT;
-	temp |= p_wm->trans_wm.plane_res_b[PLANE_CURSOR];
-	if (p_wm->trans_wm.plane_en[PLANE_CURSOR])
-		temp |= PLANE_WM_EN;
-
-	r->plane_trans[pipe][PLANE_CURSOR] = temp;
-
-	r->wm_linetime[pipe] = p_wm->linetime;
+	return 0;
 }
 
 static void skl_ddb_entry_write(struct drm_i915_private *dev_priv,
@@ -3846,53 +3820,77 @@ static void skl_ddb_entry_write(struct d
 		I915_WRITE(reg, 0);
 }
 
-void skl_write_plane_wm(struct intel_crtc *intel_crtc,
-			const struct skl_wm_values *wm,
-			int plane)
+static void skl_write_wm_level(struct drm_i915_private *dev_priv,
+			       i915_reg_t reg,
+			       const struct skl_wm_level *level)
+{
+	uint32_t val = 0;
+
+	if (level->plane_en) {
+		val |= PLANE_WM_EN;
+		val |= level->plane_res_b;
+		val |= level->plane_res_l << PLANE_WM_LINES_SHIFT;
+	}
+
+	I915_WRITE(reg, val);
+}
+
+static void skl_write_plane_wm(struct intel_crtc *intel_crtc,
+			       const struct skl_plane_wm *wm,
+			       const struct skl_ddb_allocation *ddb,
+			       int plane)
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int level, max_level = ilk_wm_max_level(dev);
+	int level, max_level = ilk_wm_max_level(dev_priv);
 	enum pipe pipe = intel_crtc->pipe;
 
 	for (level = 0; level <= max_level; level++) {
-		I915_WRITE(PLANE_WM(pipe, plane, level),
-			   wm->plane[pipe][plane][level]);
+		skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane, level),
+				   &wm->wm[level]);
 	}
-	I915_WRITE(PLANE_WM_TRANS(pipe, plane), wm->plane_trans[pipe][plane]);
+	skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane),
+			   &wm->trans_wm);
 
 	skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane),
-			    &wm->ddb.plane[pipe][plane]);
+			    &ddb->plane[pipe][plane]);
 	skl_ddb_entry_write(dev_priv, PLANE_NV12_BUF_CFG(pipe, plane),
-			    &wm->ddb.y_plane[pipe][plane]);
+			    &ddb->y_plane[pipe][plane]);
 }
 
-void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
-			 const struct skl_wm_values *wm)
+static void skl_write_cursor_wm(struct intel_crtc *intel_crtc,
+				const struct skl_plane_wm *wm,
+				const struct skl_ddb_allocation *ddb)
 {
 	struct drm_crtc *crtc = &intel_crtc->base;
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	int level, max_level = ilk_wm_max_level(dev);
+	int level, max_level = ilk_wm_max_level(dev_priv);
 	enum pipe pipe = intel_crtc->pipe;
 
 	for (level = 0; level <= max_level; level++) {
-		I915_WRITE(CUR_WM(pipe, level),
-			   wm->plane[pipe][PLANE_CURSOR][level]);
+		skl_write_wm_level(dev_priv, CUR_WM(pipe, level),
+				   &wm->wm[level]);
 	}
-	I915_WRITE(CUR_WM_TRANS(pipe), wm->plane_trans[pipe][PLANE_CURSOR]);
+	skl_write_wm_level(dev_priv, CUR_WM_TRANS(pipe), &wm->trans_wm);
 
 	skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe),
-			    &wm->ddb.plane[pipe][PLANE_CURSOR]);
+			    &ddb->plane[pipe][PLANE_CURSOR]);
 }
 
-bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old,
-			       const struct skl_ddb_allocation *new,
-			       enum pipe pipe)
+bool skl_wm_level_equals(const struct skl_wm_level *l1,
+			 const struct skl_wm_level *l2)
 {
-	return new->pipe[pipe].start == old->pipe[pipe].start &&
-	       new->pipe[pipe].end == old->pipe[pipe].end;
+	if (l1->plane_en != l2->plane_en)
+		return false;
+
+	/* If both planes aren't enabled, the rest shouldn't matter */
+	if (!l1->plane_en)
+		return true;
+
+	return (l1->plane_res_l == l2->plane_res_l &&
+		l1->plane_res_b == l2->plane_res_b);
 }
 
 static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a,
@@ -3901,35 +3899,26 @@ static inline bool skl_ddb_entries_overl
 	return a->start < b->end && b->start < a->end;
 }
 
-bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state,
-				 const struct skl_ddb_allocation *old,
-				 const struct skl_ddb_allocation *new,
-				 enum pipe pipe)
+bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries,
+				 const struct skl_ddb_entry *ddb,
+				 int ignore)
 {
-	struct drm_device *dev = state->dev;
-	struct intel_crtc *intel_crtc;
-	enum pipe otherp;
-
-	for_each_intel_crtc(dev, intel_crtc) {
-		otherp = intel_crtc->pipe;
-
-		if (otherp == pipe)
-			continue;
+	int i;
 
-		if (skl_ddb_entries_overlap(&new->pipe[pipe],
-					    &old->pipe[otherp]))
+	for (i = 0; i < I915_MAX_PIPES; i++)
+		if (i != ignore && entries[i] &&
+		    skl_ddb_entries_overlap(ddb, entries[i]))
 			return true;
-	}
 
 	return false;
 }
 
 static int skl_update_pipe_wm(struct drm_crtc_state *cstate,
-			      struct skl_ddb_allocation *ddb, /* out */
+			      const struct skl_pipe_wm *old_pipe_wm,
 			      struct skl_pipe_wm *pipe_wm, /* out */
+			      struct skl_ddb_allocation *ddb, /* out */
 			      bool *changed /* out */)
 {
-	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->crtc);
 	struct intel_crtc_state *intel_cstate = to_intel_crtc_state(cstate);
 	int ret;
 
@@ -3937,7 +3926,7 @@ static int skl_update_pipe_wm(struct drm
 	if (ret)
 		return ret;
 
-	if (!memcmp(&intel_crtc->wm.active.skl, pipe_wm, sizeof(*pipe_wm)))
+	if (!memcmp(old_pipe_wm, pipe_wm, sizeof(*pipe_wm)))
 		*changed = false;
 	else
 		*changed = true;
@@ -3958,7 +3947,7 @@ pipes_modified(struct drm_atomic_state *
 	return ret;
 }
 
-int
+static int
 skl_ddb_add_affected_planes(struct intel_crtc_state *cstate)
 {
 	struct drm_atomic_state *state = cstate->base.state;
@@ -3976,7 +3965,7 @@ skl_ddb_add_affected_planes(struct intel
 
 	WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc));
 
-	drm_for_each_plane_mask(plane, dev, crtc->state->plane_mask) {
+	drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) {
 		id = skl_wm_plane_id(to_intel_plane(plane));
 
 		if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][id],
@@ -4076,19 +4065,50 @@ skl_copy_wm_for_pipe(struct skl_wm_value
 		     struct skl_wm_values *src,
 		     enum pipe pipe)
 {
-	dst->wm_linetime[pipe] = src->wm_linetime[pipe];
-	memcpy(dst->plane[pipe], src->plane[pipe],
-	       sizeof(dst->plane[pipe]));
-	memcpy(dst->plane_trans[pipe], src->plane_trans[pipe],
-	       sizeof(dst->plane_trans[pipe]));
-
-	dst->ddb.pipe[pipe] = src->ddb.pipe[pipe];
 	memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe],
 	       sizeof(dst->ddb.y_plane[pipe]));
 	memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe],
 	       sizeof(dst->ddb.plane[pipe]));
 }
 
+static void
+skl_print_wm_changes(const struct drm_atomic_state *state)
+{
+	const struct drm_device *dev = state->dev;
+	const struct drm_i915_private *dev_priv = to_i915(dev);
+	const struct intel_atomic_state *intel_state =
+		to_intel_atomic_state(state);
+	const struct drm_crtc *crtc;
+	const struct drm_crtc_state *cstate;
+	const struct intel_plane *intel_plane;
+	const struct skl_ddb_allocation *old_ddb = &dev_priv->wm.skl_hw.ddb;
+	const struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb;
+	int id;
+	int i;
+
+	for_each_crtc_in_state(state, crtc, cstate, i) {
+		const struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+		enum pipe pipe = intel_crtc->pipe;
+
+		for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+			const struct skl_ddb_entry *old, *new;
+
+			id = skl_wm_plane_id(intel_plane);
+			old = &old_ddb->plane[pipe][id];
+			new = &new_ddb->plane[pipe][id];
+
+			if (skl_ddb_entry_equal(old, new))
+				continue;
+
+			DRM_DEBUG_ATOMIC("[PLANE:%d:%s] ddb (%d - %d) -> (%d - %d)\n",
+					 intel_plane->base.base.id,
+					 intel_plane->base.name,
+					 old->start, old->end,
+					 new->start, new->end);
+		}
+	}
+}
+
 static int
 skl_compute_wm(struct drm_atomic_state *state)
 {
@@ -4131,13 +4151,14 @@ skl_compute_wm(struct drm_atomic_state *
 	 * no suitable watermark values can be found.
 	 */
 	for_each_crtc_in_state(state, crtc, cstate, i) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 		struct intel_crtc_state *intel_cstate =
 			to_intel_crtc_state(cstate);
+		const struct skl_pipe_wm *old_pipe_wm =
+			&to_intel_crtc_state(crtc->state)->wm.skl.optimal;
 
 		pipe_wm = &intel_cstate->wm.skl.optimal;
-		ret = skl_update_pipe_wm(cstate, &results->ddb, pipe_wm,
-					 &changed);
+		ret = skl_update_pipe_wm(cstate, old_pipe_wm, pipe_wm,
+					 &results->ddb, &changed);
 		if (ret)
 			return ret;
 
@@ -4149,44 +4170,51 @@ skl_compute_wm(struct drm_atomic_state *
 			continue;
 
 		intel_cstate->update_wm_pre = true;
-		skl_compute_wm_results(crtc->dev, pipe_wm, results, intel_crtc);
 	}
 
+	skl_print_wm_changes(state);
+
 	return 0;
 }
 
-static void skl_update_wm(struct drm_crtc *crtc)
+static void skl_atomic_update_crtc_wm(struct intel_atomic_state *state,
+				      struct intel_crtc_state *cstate)
 {
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct skl_wm_values *results = &dev_priv->wm.skl_results;
-	struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw;
-	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
+	struct intel_crtc *crtc = to_intel_crtc(cstate->base.crtc);
+	struct drm_i915_private *dev_priv = to_i915(state->base.dev);
 	struct skl_pipe_wm *pipe_wm = &cstate->wm.skl.optimal;
-	enum pipe pipe = intel_crtc->pipe;
+	const struct skl_ddb_allocation *ddb = &state->wm_results.ddb;
+	enum pipe pipe = crtc->pipe;
+	int plane;
 
-	if ((results->dirty_pipes & drm_crtc_mask(crtc)) == 0)
+	if (!(state->wm_results.dirty_pipes & drm_crtc_mask(&crtc->base)))
 		return;
 
-	intel_crtc->wm.active.skl = *pipe_wm;
+	I915_WRITE(PIPE_WM_LINETIME(pipe), pipe_wm->linetime);
 
-	mutex_lock(&dev_priv->wm.wm_mutex);
+	for_each_universal_plane(dev_priv, pipe, plane)
+		skl_write_plane_wm(crtc, &pipe_wm->planes[plane], ddb, plane);
 
-	/*
-	 * If this pipe isn't active already, we're going to be enabling it
-	 * very soon. Since it's safe to update a pipe's ddb allocation while
-	 * the pipe's shut off, just do so here. Already active pipes will have
-	 * their watermarks updated once we update their planes.
-	 */
-	if (crtc->state->active_changed) {
-		int plane;
+	skl_write_cursor_wm(crtc, &pipe_wm->planes[PLANE_CURSOR], ddb);
+}
 
-		for (plane = 0; plane < intel_num_planes(intel_crtc); plane++)
-			skl_write_plane_wm(intel_crtc, results, plane);
+static void skl_initial_wm(struct intel_atomic_state *state,
+			   struct intel_crtc_state *cstate)
+{
+	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
+	struct drm_device *dev = intel_crtc->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct skl_wm_values *results = &state->wm_results;
+	struct skl_wm_values *hw_vals = &dev_priv->wm.skl_hw;
+	enum pipe pipe = intel_crtc->pipe;
 
-		skl_write_cursor_wm(intel_crtc, results);
-	}
+	if ((results->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) == 0)
+		return;
+
+	mutex_lock(&dev_priv->wm.wm_mutex);
+
+	if (cstate->base.active_changed)
+		skl_atomic_update_crtc_wm(state, cstate);
 
 	skl_copy_wm_for_pipe(hw_vals, results, pipe);
 
@@ -4226,7 +4254,7 @@ static void ilk_program_watermarks(struc
 	ilk_wm_merge(dev, &config, &max, &lp_wm_1_2);
 
 	/* 5/6 split only in single pipe config on IVB+ */
-	if (INTEL_INFO(dev)->gen >= 7 &&
+	if (INTEL_GEN(dev_priv) >= 7 &&
 	    config.num_pipes_active == 1 && config.sprites_enabled) {
 		ilk_compute_wm_maximums(dev, 1, &config, INTEL_DDB_PART_5_6, &max);
 		ilk_wm_merge(dev, &config, &max, &lp_wm_5_6);
@@ -4244,7 +4272,8 @@ static void ilk_program_watermarks(struc
 	ilk_write_wm_values(dev_priv, &results);
 }
 
-static void ilk_initial_watermarks(struct intel_crtc_state *cstate)
+static void ilk_initial_watermarks(struct intel_atomic_state *state,
+				   struct intel_crtc_state *cstate)
 {
 	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
@@ -4255,7 +4284,8 @@ static void ilk_initial_watermarks(struc
 	mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
-static void ilk_optimize_watermarks(struct intel_crtc_state *cstate)
+static void ilk_optimize_watermarks(struct intel_atomic_state *state,
+				    struct intel_crtc_state *cstate)
 {
 	struct drm_i915_private *dev_priv = to_i915(cstate->base.crtc->dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
@@ -4268,114 +4298,75 @@ static void ilk_optimize_watermarks(stru
 	mutex_unlock(&dev_priv->wm.wm_mutex);
 }
 
-static void skl_pipe_wm_active_state(uint32_t val,
-				     struct skl_pipe_wm *active,
-				     bool is_transwm,
-				     bool is_cursor,
-				     int i,
-				     int level)
+static inline void skl_wm_level_from_reg_val(uint32_t val,
+					     struct skl_wm_level *level)
 {
-	bool is_enabled = (val & PLANE_WM_EN) != 0;
-
-	if (!is_transwm) {
-		if (!is_cursor) {
-			active->wm[level].plane_en[i] = is_enabled;
-			active->wm[level].plane_res_b[i] =
-					val & PLANE_WM_BLOCKS_MASK;
-			active->wm[level].plane_res_l[i] =
-					(val >> PLANE_WM_LINES_SHIFT) &
-						PLANE_WM_LINES_MASK;
-		} else {
-			active->wm[level].plane_en[PLANE_CURSOR] = is_enabled;
-			active->wm[level].plane_res_b[PLANE_CURSOR] =
-					val & PLANE_WM_BLOCKS_MASK;
-			active->wm[level].plane_res_l[PLANE_CURSOR] =
-					(val >> PLANE_WM_LINES_SHIFT) &
-						PLANE_WM_LINES_MASK;
-		}
-	} else {
-		if (!is_cursor) {
-			active->trans_wm.plane_en[i] = is_enabled;
-			active->trans_wm.plane_res_b[i] =
-					val & PLANE_WM_BLOCKS_MASK;
-			active->trans_wm.plane_res_l[i] =
-					(val >> PLANE_WM_LINES_SHIFT) &
-						PLANE_WM_LINES_MASK;
-		} else {
-			active->trans_wm.plane_en[PLANE_CURSOR] = is_enabled;
-			active->trans_wm.plane_res_b[PLANE_CURSOR] =
-					val & PLANE_WM_BLOCKS_MASK;
-			active->trans_wm.plane_res_l[PLANE_CURSOR] =
-					(val >> PLANE_WM_LINES_SHIFT) &
-						PLANE_WM_LINES_MASK;
-		}
-	}
+	level->plane_en = val & PLANE_WM_EN;
+	level->plane_res_b = val & PLANE_WM_BLOCKS_MASK;
+	level->plane_res_l = (val >> PLANE_WM_LINES_SHIFT) &
+		PLANE_WM_LINES_MASK;
 }
 
-static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc)
+void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc,
+			      struct skl_pipe_wm *out)
 {
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state);
-	struct skl_pipe_wm *active = &cstate->wm.skl.optimal;
+	struct intel_plane *intel_plane;
+	struct skl_plane_wm *wm;
 	enum pipe pipe = intel_crtc->pipe;
-	int level, i, max_level;
-	uint32_t temp;
-
-	max_level = ilk_wm_max_level(dev);
-
-	hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
-
-	for (level = 0; level <= max_level; level++) {
-		for (i = 0; i < intel_num_planes(intel_crtc); i++)
-			hw->plane[pipe][i][level] =
-					I915_READ(PLANE_WM(pipe, i, level));
-		hw->plane[pipe][PLANE_CURSOR][level] = I915_READ(CUR_WM(pipe, level));
-	}
-
-	for (i = 0; i < intel_num_planes(intel_crtc); i++)
-		hw->plane_trans[pipe][i] = I915_READ(PLANE_WM_TRANS(pipe, i));
-	hw->plane_trans[pipe][PLANE_CURSOR] = I915_READ(CUR_WM_TRANS(pipe));
+	int level, id, max_level;
+	uint32_t val;
 
-	if (!intel_crtc->active)
-		return;
+	max_level = ilk_wm_max_level(dev_priv);
 
-	hw->dirty_pipes |= drm_crtc_mask(crtc);
+	for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
+		id = skl_wm_plane_id(intel_plane);
+		wm = &out->planes[id];
 
-	active->linetime = hw->wm_linetime[pipe];
+		for (level = 0; level <= max_level; level++) {
+			if (id != PLANE_CURSOR)
+				val = I915_READ(PLANE_WM(pipe, id, level));
+			else
+				val = I915_READ(CUR_WM(pipe, level));
 
-	for (level = 0; level <= max_level; level++) {
-		for (i = 0; i < intel_num_planes(intel_crtc); i++) {
-			temp = hw->plane[pipe][i][level];
-			skl_pipe_wm_active_state(temp, active, false,
-						false, i, level);
+			skl_wm_level_from_reg_val(val, &wm->wm[level]);
 		}
-		temp = hw->plane[pipe][PLANE_CURSOR][level];
-		skl_pipe_wm_active_state(temp, active, false, true, i, level);
-	}
 
-	for (i = 0; i < intel_num_planes(intel_crtc); i++) {
-		temp = hw->plane_trans[pipe][i];
-		skl_pipe_wm_active_state(temp, active, true, false, i, 0);
+		if (id != PLANE_CURSOR)
+			val = I915_READ(PLANE_WM_TRANS(pipe, id));
+		else
+			val = I915_READ(CUR_WM_TRANS(pipe));
+
+		skl_wm_level_from_reg_val(val, &wm->trans_wm);
 	}
 
-	temp = hw->plane_trans[pipe][PLANE_CURSOR];
-	skl_pipe_wm_active_state(temp, active, true, true, i, 0);
+	if (!intel_crtc->active)
+		return;
 
-	intel_crtc->wm.active.skl = *active;
+	out->linetime = I915_READ(PIPE_WM_LINETIME(pipe));
 }
 
 void skl_wm_get_hw_state(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct skl_wm_values *hw = &dev_priv->wm.skl_hw;
 	struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
 	struct drm_crtc *crtc;
+	struct intel_crtc *intel_crtc;
+	struct intel_crtc_state *cstate;
 
 	skl_ddb_get_hw_state(dev_priv, ddb);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
-		skl_pipe_wm_get_hw_state(crtc);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		intel_crtc = to_intel_crtc(crtc);
+		cstate = to_intel_crtc_state(crtc->state);
+
+		skl_pipe_wm_get_hw_state(crtc, &cstate->wm.skl.optimal);
+
+		if (intel_crtc->active)
+			hw->dirty_pipes |= drm_crtc_mask(crtc);
+	}
 
 	if (dev_priv->active_crtcs) {
 		/* Fully recompute DDB on first atomic commit */
@@ -4402,7 +4393,7 @@ static void ilk_pipe_wm_get_hw_state(str
 	};
 
 	hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]);
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
 
 	memset(active, 0, sizeof(*active));
@@ -4424,7 +4415,7 @@ static void ilk_pipe_wm_get_hw_state(str
 		active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK;
 		active->linetime = hw->wm_linetime[pipe];
 	} else {
-		int level, max_level = ilk_wm_max_level(dev);
+		int level, max_level = ilk_wm_max_level(dev_priv);
 
 		/*
 		 * For inactive pipes, all watermark levels
@@ -4536,11 +4527,11 @@ void vlv_wm_get_hw_state(struct drm_devi
 			plane->wm.fifo_size = 63;
 			break;
 		case DRM_PLANE_TYPE_PRIMARY:
-			plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, 0);
+			plane->wm.fifo_size = vlv_get_fifo_size(dev_priv, plane->pipe, 0);
 			break;
 		case DRM_PLANE_TYPE_OVERLAY:
 			sprite = plane->plane;
-			plane->wm.fifo_size = vlv_get_fifo_size(dev, plane->pipe, sprite + 1);
+			plane->wm.fifo_size = vlv_get_fifo_size(dev_priv, plane->pipe, sprite + 1);
 			break;
 		}
 	}
@@ -4605,15 +4596,15 @@ void ilk_wm_get_hw_state(struct drm_devi
 	hw->wm_lp[2] = I915_READ(WM3_LP_ILK);
 
 	hw->wm_lp_spr[0] = I915_READ(WM1S_LP_ILK);
-	if (INTEL_INFO(dev)->gen >= 7) {
+	if (INTEL_GEN(dev_priv) >= 7) {
 		hw->wm_lp_spr[1] = I915_READ(WM2S_LP_IVB);
 		hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB);
 	}
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ?
 			INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
-	else if (IS_IVYBRIDGE(dev))
+	else if (IS_IVYBRIDGE(dev_priv))
 		hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ?
 			INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2;
 
@@ -4653,9 +4644,9 @@ void ilk_wm_get_hw_state(struct drm_devi
  * We don't use the sprite, so we can ignore that.  And on Crestline we have
  * to set the non-SR watermarks to 8.
  */
-void intel_update_watermarks(struct drm_crtc *crtc)
+void intel_update_watermarks(struct intel_crtc *crtc)
 {
-	struct drm_i915_private *dev_priv = to_i915(crtc->dev);
+	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 
 	if (dev_priv->display.update_wm)
 		dev_priv->display.update_wm(crtc);
@@ -5357,6 +5348,7 @@ static void gen9_enable_rps(struct drm_i
 static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	uint32_t rc6_mask = 0;
 
 	/* 1a: Software RC state - RC0 */
@@ -5378,7 +5370,7 @@ static void gen9_enable_rc6(struct drm_i
 		I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
 	if (HAS_GUC(dev_priv))
@@ -5394,9 +5386,8 @@ static void gen9_enable_rc6(struct drm_i
 	if (intel_enable_rc6() & INTEL_RC6_ENABLE)
 		rc6_mask = GEN6_RC_CTL_RC6_ENABLE;
 	DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE));
-	/* WaRsUseTimeoutMode */
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) ||
-	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
+	/* WaRsUseTimeoutMode:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
 		I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */
 		I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE |
 			   GEN7_RC_CTL_TO_MODE |
@@ -5424,6 +5415,7 @@ static void gen9_enable_rc6(struct drm_i
 static void gen8_enable_rps(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	uint32_t rc6_mask = 0;
 
 	/* 1a: Software RC state - RC0 */
@@ -5440,7 +5432,7 @@ static void gen8_enable_rps(struct drm_i
 	I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16);
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 	I915_WRITE(GEN6_RC_SLEEP, 0);
 	if (IS_BROADWELL(dev_priv))
@@ -5500,6 +5492,7 @@ static void gen8_enable_rps(struct drm_i
 static void gen6_enable_rps(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	u32 rc6vids, rc6_mask = 0;
 	u32 gtfifodbg;
 	int rc6_mode;
@@ -5533,7 +5526,7 @@ static void gen6_enable_rps(struct drm_i
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
 	I915_WRITE(GEN6_RC_SLEEP, 0);
@@ -5570,10 +5563,6 @@ static void gen6_enable_rps(struct drm_i
 	I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000);
 	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
 
-	ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0);
-	if (ret)
-		DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
-
 	reset_rps(dev_priv, gen6_set_rps);
 
 	rc6vids = 0;
@@ -5863,7 +5852,7 @@ static void valleyview_cleanup_pctx(stru
 	if (WARN_ON(!dev_priv->vlv_pctx))
 		return;
 
-	i915_gem_object_put_unlocked(dev_priv->vlv_pctx);
+	i915_gem_object_put(dev_priv->vlv_pctx);
 	dev_priv->vlv_pctx = NULL;
 }
 
@@ -5982,6 +5971,7 @@ static void valleyview_cleanup_gt_powers
 static void cherryview_enable_rps(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	u32 gtfifodbg, val, rc6_mode = 0, pcbr;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -6008,7 +5998,7 @@ static void cherryview_enable_rps(struct
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 	I915_WRITE(GEN6_RC_SLEEP, 0);
 
@@ -6070,6 +6060,7 @@ static void cherryview_enable_rps(struct
 static void valleyview_enable_rps(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 	u32 gtfifodbg, val, rc6_mode = 0;
 
 	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -6109,7 +6100,7 @@ static void valleyview_enable_rps(struct
 	I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000);
 	I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25);
 
-	for_each_engine(engine, dev_priv)
+	for_each_engine(engine, dev_priv, id)
 		I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
 
 	I915_WRITE(GEN6_RC6_THRESHOLD, 0x557);
@@ -6792,7 +6783,7 @@ static void __intel_autoenable_gt_powers
 	if (READ_ONCE(dev_priv->rps.enabled))
 		goto out;
 
-	rcs = &dev_priv->engine[RCS];
+	rcs = dev_priv->engine[RCS];
 	if (rcs->last_context)
 		goto out;
 
@@ -6845,10 +6836,8 @@ void intel_autoenable_gt_powersave(struc
 	}
 }
 
-static void ibx_init_clock_gating(struct drm_device *dev)
+static void ibx_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/*
 	 * On Ibex Peak and Cougar Point, we need to disable clock
 	 * gating for the panel power sequencer or it will fail to
@@ -6857,9 +6846,8 @@ static void ibx_init_clock_gating(struct
 	I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE);
 }
 
-static void g4x_disable_trickle_feed(struct drm_device *dev)
+static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum pipe pipe;
 
 	for_each_pipe(dev_priv, pipe) {
@@ -6872,10 +6860,8 @@ static void g4x_disable_trickle_feed(str
 	}
 }
 
-static void ilk_init_lp_watermarks(struct drm_device *dev)
+static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN);
 	I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN);
 	I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN);
@@ -6886,9 +6872,8 @@ static void ilk_init_lp_watermarks(struc
 	 */
 }
 
-static void ironlake_init_clock_gating(struct drm_device *dev)
+static void ironlake_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
 
 	/*
@@ -6920,7 +6905,7 @@ static void ironlake_init_clock_gating(s
 		   (I915_READ(DISP_ARB_CTL) |
 		    DISP_FBC_WM_DIS));
 
-	ilk_init_lp_watermarks(dev);
+	ilk_init_lp_watermarks(dev_priv);
 
 	/*
 	 * Based on the document from hardware guys the following bits
@@ -6929,7 +6914,7 @@ static void ironlake_init_clock_gating(s
 	 * The bit 22 of 0x42004
 	 * The bit 7,8,9 of 0x42020.
 	 */
-	if (IS_IRONLAKE_M(dev)) {
+	if (IS_IRONLAKE_M(dev_priv)) {
 		/* WaFbcAsynchFlipDisableFbcQueue:ilk */
 		I915_WRITE(ILK_DISPLAY_CHICKEN1,
 			   I915_READ(ILK_DISPLAY_CHICKEN1) |
@@ -6955,14 +6940,13 @@ static void ironlake_init_clock_gating(s
 	/* WaDisable_RenderCache_OperationalFlush:ilk */
 	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 
-	g4x_disable_trickle_feed(dev);
+	g4x_disable_trickle_feed(dev_priv);
 
-	ibx_init_clock_gating(dev);
+	ibx_init_clock_gating(dev_priv);
 }
 
-static void cpt_init_clock_gating(struct drm_device *dev)
+static void cpt_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	int pipe;
 	uint32_t val;
 
@@ -6997,9 +6981,8 @@ static void cpt_init_clock_gating(struct
 	}
 }
 
-static void gen6_check_mch_setup(struct drm_device *dev)
+static void gen6_check_mch_setup(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t tmp;
 
 	tmp = I915_READ(MCH_SSKPD);
@@ -7008,9 +6991,8 @@ static void gen6_check_mch_setup(struct
 			      tmp);
 }
 
-static void gen6_init_clock_gating(struct drm_device *dev)
+static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE;
 
 	I915_WRITE(ILK_DSPCLK_GATE_D, dspclk_gate);
@@ -7037,7 +7019,7 @@ static void gen6_init_clock_gating(struc
 	I915_WRITE(GEN6_GT_MODE,
 		   _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4));
 
-	ilk_init_lp_watermarks(dev);
+	ilk_init_lp_watermarks(dev_priv);
 
 	I915_WRITE(CACHE_MODE_0,
 		   _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB));
@@ -7098,11 +7080,11 @@ static void gen6_init_clock_gating(struc
 		   ILK_DPARBUNIT_CLOCK_GATE_ENABLE  |
 		   ILK_DPFDUNIT_CLOCK_GATE_ENABLE);
 
-	g4x_disable_trickle_feed(dev);
+	g4x_disable_trickle_feed(dev_priv);
 
-	cpt_init_clock_gating(dev);
+	cpt_init_clock_gating(dev_priv);
 
-	gen6_check_mch_setup(dev);
+	gen6_check_mch_setup(dev_priv);
 }
 
 static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
@@ -7123,15 +7105,13 @@ static void gen7_setup_fixed_func_schedu
 	I915_WRITE(GEN7_FF_THREAD_MODE, reg);
 }
 
-static void lpt_init_clock_gating(struct drm_device *dev)
+static void lpt_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/*
 	 * TODO: this bit should only be enabled when really needed, then
 	 * disabled when not needed anymore in order to save power.
 	 */
-	if (HAS_PCH_LPT_LP(dev))
+	if (HAS_PCH_LPT_LP(dev_priv))
 		I915_WRITE(SOUTH_DSPCLK_GATE_D,
 			   I915_READ(SOUTH_DSPCLK_GATE_D) |
 			   PCH_LP_PARTITION_LEVEL_DISABLE);
@@ -7142,11 +7122,9 @@ static void lpt_init_clock_gating(struct
 		   TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
 }
 
-static void lpt_suspend_hw(struct drm_device *dev)
+static void lpt_suspend_hw(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	if (HAS_PCH_LPT_LP(dev)) {
+	if (HAS_PCH_LPT_LP(dev_priv)) {
 		uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D);
 
 		val &= ~PCH_LP_PARTITION_LEVEL_DISABLE;
@@ -7177,11 +7155,9 @@ static void gen8_set_l3sqc_credits(struc
 	I915_WRITE(GEN7_MISCCPCTL, misccpctl);
 }
 
-static void kabylake_init_clock_gating(struct drm_device *dev)
+static void kabylake_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	gen9_init_clock_gating(dev);
+	gen9_init_clock_gating(dev_priv);
 
 	/* WaDisableSDEUnitClockGating:kbl */
 	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0))
@@ -7198,11 +7174,9 @@ static void kabylake_init_clock_gating(s
 		   ILK_DPFC_NUKE_ON_ANY_MODIFICATION);
 }
 
-static void skylake_init_clock_gating(struct drm_device *dev)
+static void skylake_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	gen9_init_clock_gating(dev);
+	gen9_init_clock_gating(dev_priv);
 
 	/* WAC6entrylatency:skl */
 	I915_WRITE(FBC_LLC_READ_CTRL, I915_READ(FBC_LLC_READ_CTRL) |
@@ -7213,12 +7187,11 @@ static void skylake_init_clock_gating(st
 		   ILK_DPFC_NUKE_ON_ANY_MODIFICATION);
 }
 
-static void broadwell_init_clock_gating(struct drm_device *dev)
+static void broadwell_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	enum pipe pipe;
 
-	ilk_init_lp_watermarks(dev);
+	ilk_init_lp_watermarks(dev_priv);
 
 	/* WaSwitchSolVfFArbitrationPriority:bdw */
 	I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
@@ -7261,14 +7234,12 @@ static void broadwell_init_clock_gating(
 	I915_WRITE(CHICKEN_PAR2_1, I915_READ(CHICKEN_PAR2_1)
 		   | KVM_CONFIG_CHANGE_NOTIFICATION_SELECT);
 
-	lpt_init_clock_gating(dev);
+	lpt_init_clock_gating(dev_priv);
 }
 
-static void haswell_init_clock_gating(struct drm_device *dev)
+static void haswell_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	ilk_init_lp_watermarks(dev);
+	ilk_init_lp_watermarks(dev_priv);
 
 	/* L3 caching of data atomics doesn't work -- disable it. */
 	I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE);
@@ -7317,15 +7288,14 @@ static void haswell_init_clock_gating(st
 	I915_WRITE(CHICKEN_PAR1_1,
 		   I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES);
 
-	lpt_init_clock_gating(dev);
+	lpt_init_clock_gating(dev_priv);
 }
 
-static void ivybridge_init_clock_gating(struct drm_device *dev)
+static void ivybridge_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t snpcr;
 
-	ilk_init_lp_watermarks(dev);
+	ilk_init_lp_watermarks(dev_priv);
 
 	I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
 
@@ -7339,7 +7309,7 @@ static void ivybridge_init_clock_gating(
 		   CHICKEN3_DGMG_DONE_FIX_DISABLE);
 
 	/* WaDisablePSDDualDispatchEnable:ivb */
-	if (IS_IVB_GT1(dev))
+	if (IS_IVB_GT1(dev_priv))
 		I915_WRITE(GEN7_HALF_SLICE_CHICKEN1,
 			   _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE));
 
@@ -7355,7 +7325,7 @@ static void ivybridge_init_clock_gating(
 			GEN7_WA_FOR_GEN7_L3_CONTROL);
 	I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
 		   GEN7_WA_L3_CHICKEN_MODE);
-	if (IS_IVB_GT1(dev))
+	if (IS_IVB_GT1(dev_priv))
 		I915_WRITE(GEN7_ROW_CHICKEN2,
 			   _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
 	else {
@@ -7382,7 +7352,7 @@ static void ivybridge_init_clock_gating(
 			I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
 			GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
 
-	g4x_disable_trickle_feed(dev);
+	g4x_disable_trickle_feed(dev_priv);
 
 	gen7_setup_fixed_func_scheduler(dev_priv);
 
@@ -7412,16 +7382,14 @@ static void ivybridge_init_clock_gating(
 	snpcr |= GEN6_MBC_SNPCR_MED;
 	I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
 
-	if (!HAS_PCH_NOP(dev))
-		cpt_init_clock_gating(dev);
+	if (!HAS_PCH_NOP(dev_priv))
+		cpt_init_clock_gating(dev_priv);
 
-	gen6_check_mch_setup(dev);
+	gen6_check_mch_setup(dev_priv);
 }
 
-static void valleyview_init_clock_gating(struct drm_device *dev)
+static void valleyview_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/* WaDisableEarlyCull:vlv */
 	I915_WRITE(_3D_CHICKEN3,
 		   _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_DISABLE_OBJEND_CULL));
@@ -7500,10 +7468,8 @@ static void valleyview_init_clock_gating
 	I915_WRITE(VLV_GUNIT_CLOCK_GATE, GCFG_DIS);
 }
 
-static void cherryview_init_clock_gating(struct drm_device *dev)
+static void cherryview_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	/* WaVSRefCountFullforceMissDisable:chv */
 	/* WaDSRefCountFullforceMissDisable:chv */
 	I915_WRITE(GEN7_FF_THREAD_MODE,
@@ -7536,9 +7502,8 @@ static void cherryview_init_clock_gating
 	I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL);
 }
 
-static void g4x_init_clock_gating(struct drm_device *dev)
+static void g4x_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	uint32_t dspclk_gate;
 
 	I915_WRITE(RENCLK_GATE_D1, 0);
@@ -7549,7 +7514,7 @@ static void g4x_init_clock_gating(struct
 	dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE |
 		OVRUNIT_CLOCK_GATE_DISABLE |
 		OVCUNIT_CLOCK_GATE_DISABLE;
-	if (IS_GM45(dev))
+	if (IS_GM45(dev_priv))
 		dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE;
 	I915_WRITE(DSPCLK_GATE_D, dspclk_gate);
 
@@ -7560,13 +7525,11 @@ static void g4x_init_clock_gating(struct
 	/* WaDisable_RenderCache_OperationalFlush:g4x */
 	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 
-	g4x_disable_trickle_feed(dev);
+	g4x_disable_trickle_feed(dev_priv);
 }
 
-static void crestline_init_clock_gating(struct drm_device *dev)
+static void crestline_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	I915_WRITE(RENCLK_GATE_D1, I965_RCC_CLOCK_GATE_DISABLE);
 	I915_WRITE(RENCLK_GATE_D2, 0);
 	I915_WRITE(DSPCLK_GATE_D, 0);
@@ -7579,10 +7542,8 @@ static void crestline_init_clock_gating(
 	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
-static void broadwater_init_clock_gating(struct drm_device *dev)
+static void broadwater_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	I915_WRITE(RENCLK_GATE_D1, I965_RCZ_CLOCK_GATE_DISABLE |
 		   I965_RCC_CLOCK_GATE_DISABLE |
 		   I965_RCPB_CLOCK_GATE_DISABLE |
@@ -7596,16 +7557,15 @@ static void broadwater_init_clock_gating
 	I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(RC_OP_FLUSH_ENABLE));
 }
 
-static void gen3_init_clock_gating(struct drm_device *dev)
+static void gen3_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
 	u32 dstate = I915_READ(D_STATE);
 
 	dstate |= DSTATE_PLL_D3_OFF | DSTATE_GFX_CLOCK_GATING |
 		DSTATE_DOT_CLOCK_GATING;
 	I915_WRITE(D_STATE, dstate);
 
-	if (IS_PINEVIEW(dev))
+	if (IS_PINEVIEW(dev_priv))
 		I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY));
 
 	/* IIR "flip pending" means done if this bit is set */
@@ -7621,10 +7581,8 @@ static void gen3_init_clock_gating(struc
 		   _MASKED_BIT_ENABLE(MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE));
 }
 
-static void i85x_init_clock_gating(struct drm_device *dev)
+static void i85x_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	I915_WRITE(RENCLK_GATE_D1, SV_CLOCK_GATE_DISABLE);
 
 	/* interrupts should cause a wake up from C3 */
@@ -7635,10 +7593,8 @@ static void i85x_init_clock_gating(struc
 		   _MASKED_BIT_ENABLE(MEM_DISPLAY_TRICKLE_FEED_DISABLE));
 }
 
-static void i830_init_clock_gating(struct drm_device *dev)
+static void i830_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	I915_WRITE(DSPCLK_GATE_D, OVRUNIT_CLOCK_GATE_DISABLE);
 
 	I915_WRITE(MEM_MODE,
@@ -7646,20 +7602,18 @@ static void i830_init_clock_gating(struc
 		   _MASKED_BIT_ENABLE(MEM_DISPLAY_B_TRICKLE_FEED_DISABLE));
 }
 
-void intel_init_clock_gating(struct drm_device *dev)
+void intel_init_clock_gating(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
-	dev_priv->display.init_clock_gating(dev);
+	dev_priv->display.init_clock_gating(dev_priv);
 }
 
-void intel_suspend_hw(struct drm_device *dev)
+void intel_suspend_hw(struct drm_i915_private *dev_priv)
 {
-	if (HAS_PCH_LPT(dev))
-		lpt_suspend_hw(dev);
+	if (HAS_PCH_LPT(dev_priv))
+		lpt_suspend_hw(dev_priv);
 }
 
-static void nop_init_clock_gating(struct drm_device *dev)
+static void nop_init_clock_gating(struct drm_i915_private *dev_priv)
 {
 	DRM_DEBUG_KMS("No clock gating settings or workarounds applied.\n");
 }
@@ -7714,29 +7668,28 @@ void intel_init_clock_gating_hooks(struc
 }
 
 /* Set up chip specific power management-related functions */
-void intel_init_pm(struct drm_device *dev)
+void intel_init_pm(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = to_i915(dev);
-
 	intel_fbc_init(dev_priv);
 
 	/* For cxsr */
-	if (IS_PINEVIEW(dev))
-		i915_pineview_get_mem_freq(dev);
-	else if (IS_GEN5(dev))
-		i915_ironlake_get_mem_freq(dev);
+	if (IS_PINEVIEW(dev_priv))
+		i915_pineview_get_mem_freq(dev_priv);
+	else if (IS_GEN5(dev_priv))
+		i915_ironlake_get_mem_freq(dev_priv);
 
 	/* For FIFO watermark updates */
-	if (INTEL_INFO(dev)->gen >= 9) {
-		skl_setup_wm_latency(dev);
-		dev_priv->display.update_wm = skl_update_wm;
+	if (INTEL_GEN(dev_priv) >= 9) {
+		skl_setup_wm_latency(dev_priv);
+		dev_priv->display.initial_watermarks = skl_initial_wm;
+		dev_priv->display.atomic_update_watermarks = skl_atomic_update_crtc_wm;
 		dev_priv->display.compute_global_watermarks = skl_compute_wm;
-	} else if (HAS_PCH_SPLIT(dev)) {
-		ilk_setup_wm_latency(dev);
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
+		ilk_setup_wm_latency(dev_priv);
 
-		if ((IS_GEN5(dev) && dev_priv->wm.pri_latency[1] &&
+		if ((IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[1] &&
 		     dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) ||
-		    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
+		    (!IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[0] &&
 		     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
 			dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm;
 			dev_priv->display.compute_intermediate_wm =
@@ -7749,14 +7702,14 @@ void intel_init_pm(struct drm_device *de
 			DRM_DEBUG_KMS("Failed to read display plane latency. "
 				      "Disable CxSR\n");
 		}
-	} else if (IS_CHERRYVIEW(dev)) {
-		vlv_setup_wm_latency(dev);
+	} else if (IS_CHERRYVIEW(dev_priv)) {
+		vlv_setup_wm_latency(dev_priv);
 		dev_priv->display.update_wm = vlv_update_wm;
-	} else if (IS_VALLEYVIEW(dev)) {
-		vlv_setup_wm_latency(dev);
+	} else if (IS_VALLEYVIEW(dev_priv)) {
+		vlv_setup_wm_latency(dev_priv);
 		dev_priv->display.update_wm = vlv_update_wm;
-	} else if (IS_PINEVIEW(dev)) {
-		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),
+	} else if (IS_PINEVIEW(dev_priv)) {
+		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv),
 					    dev_priv->is_ddr3,
 					    dev_priv->fsb_freq,
 					    dev_priv->mem_freq)) {
@@ -7770,15 +7723,15 @@ void intel_init_pm(struct drm_device *de
 			dev_priv->display.update_wm = NULL;
 		} else
 			dev_priv->display.update_wm = pineview_update_wm;
-	} else if (IS_G4X(dev)) {
+	} else if (IS_G4X(dev_priv)) {
 		dev_priv->display.update_wm = g4x_update_wm;
-	} else if (IS_GEN4(dev)) {
+	} else if (IS_GEN4(dev_priv)) {
 		dev_priv->display.update_wm = i965_update_wm;
-	} else if (IS_GEN3(dev)) {
+	} else if (IS_GEN3(dev_priv)) {
 		dev_priv->display.update_wm = i9xx_update_wm;
 		dev_priv->display.get_fifo_size = i9xx_get_fifo_size;
-	} else if (IS_GEN2(dev)) {
-		if (INTEL_INFO(dev)->num_pipes == 1) {
+	} else if (IS_GEN2(dev_priv)) {
+		if (INTEL_INFO(dev_priv)->num_pipes == 1) {
 			dev_priv->display.update_wm = i845_update_wm;
 			dev_priv->display.get_fifo_size = i845_get_fifo_size;
 		} else {
@@ -7921,6 +7874,81 @@ int sandybridge_pcode_write(struct drm_i
 	return 0;
 }
 
+static bool skl_pcode_try_request(struct drm_i915_private *dev_priv, u32 mbox,
+				  u32 request, u32 reply_mask, u32 reply,
+				  u32 *status)
+{
+	u32 val = request;
+
+	*status = sandybridge_pcode_read(dev_priv, mbox, &val);
+
+	return *status || ((val & reply_mask) == reply);
+}
+
+/**
+ * skl_pcode_request - send PCODE request until acknowledgment
+ * @dev_priv: device private
+ * @mbox: PCODE mailbox ID the request is targeted for
+ * @request: request ID
+ * @reply_mask: mask used to check for request acknowledgment
+ * @reply: value used to check for request acknowledgment
+ * @timeout_base_ms: timeout for polling with preemption enabled
+ *
+ * Keep resending the @request to @mbox until PCODE acknowledges it, PCODE
+ * reports an error or an overall timeout of @timeout_base_ms+10 ms expires.
+ * The request is acknowledged once the PCODE reply dword equals @reply after
+ * applying @reply_mask. Polling is first attempted with preemption enabled
+ * for @timeout_base_ms and if this times out for another 10 ms with
+ * preemption disabled.
+ *
+ * Returns 0 on success, %-ETIMEDOUT in case of a timeout, <0 in case of some
+ * other error as reported by PCODE.
+ */
+int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request,
+		      u32 reply_mask, u32 reply, int timeout_base_ms)
+{
+	u32 status;
+	int ret;
+
+	WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
+
+#define COND skl_pcode_try_request(dev_priv, mbox, request, reply_mask, reply, \
+				   &status)
+
+	/*
+	 * Prime the PCODE by doing a request first. Normally it guarantees
+	 * that a subsequent request, at most @timeout_base_ms later, succeeds.
+	 * _wait_for() doesn't guarantee when its passed condition is evaluated
+	 * first, so send the first request explicitly.
+	 */
+	if (COND) {
+		ret = 0;
+		goto out;
+	}
+	ret = _wait_for(COND, timeout_base_ms * 1000, 10);
+	if (!ret)
+		goto out;
+
+	/*
+	 * The above can time out if the number of requests was low (2 in the
+	 * worst case) _and_ PCODE was busy for some reason even after a
+	 * (queued) request and @timeout_base_ms delay. As a workaround retry
+	 * the poll with preemption disabled to maximize the number of
+	 * requests. Increase the timeout from @timeout_base_ms to 10ms to
+	 * account for interrupts that could reduce the number of these
+	 * requests.
+	 */
+	DRM_DEBUG_KMS("PCODE timeout, retrying with preemption disabled\n");
+	WARN_ON_ONCE(timeout_base_ms > 3);
+	preempt_disable();
+	ret = wait_for_atomic(COND, 10);
+	preempt_enable();
+
+out:
+	return ret ? ret : status;
+#undef COND
+}
+
 static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
 {
 	/*
@@ -8026,5 +8054,4 @@ void intel_pm_setup(struct drm_device *d
 
 	dev_priv->pm.suspended = false;
 	atomic_set(&dev_priv->pm.wakeref_count, 0);
-	atomic_set(&dev_priv->pm.atomic_seq, 0);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_psr.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_psr.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_psr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_psr.c	2017-02-12 16:03:20.000000000 -0500
@@ -268,7 +268,7 @@ static void hsw_psr_enable_source(struct
 	val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT;
 	val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT;
 
-	if (IS_HASWELL(dev))
+	if (IS_HASWELL(dev_priv))
 		val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES;
 
 	if (dev_priv->psr.link_standby)
@@ -344,7 +344,7 @@ static bool intel_psr_match_conditions(s
 	 * ones. Since by Display design transcoder EDP is tied to port A
 	 * we can safely escape based on the port A.
 	 */
-	if (HAS_DDI(dev) && dig_port->port != PORT_A) {
+	if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) {
 		DRM_DEBUG_KMS("PSR condition failed: Port not supported\n");
 		return false;
 	}
@@ -354,20 +354,20 @@ static bool intel_psr_match_conditions(s
 		return false;
 	}
 
-	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 	    !dev_priv->psr.link_standby) {
 		DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n");
 		return false;
 	}
 
-	if (IS_HASWELL(dev) &&
+	if (IS_HASWELL(dev_priv) &&
 	    I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) &
 		      S3D_ENABLE) {
 		DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n");
 		return false;
 	}
 
-	if (IS_HASWELL(dev) &&
+	if (IS_HASWELL(dev_priv) &&
 	    adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
 		DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n");
 		return false;
@@ -402,7 +402,7 @@ static void intel_psr_activate(struct in
 	lockdep_assert_held(&dev_priv->psr.lock);
 
 	/* Enable/Re-enable PSR on the host */
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev_priv))
 		/* On HSW+ after we enable PSR on source it will activate it
 		 * as soon as it match configure idle_frame count. So
 		 * we just actually enable it here on activation time.
@@ -427,7 +427,7 @@ void intel_psr_enable(struct intel_dp *i
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
 
-	if (!HAS_PSR(dev)) {
+	if (!HAS_PSR(dev_priv)) {
 		DRM_DEBUG_KMS("PSR not supported on this platform\n");
 		return;
 	}
@@ -448,7 +448,7 @@ void intel_psr_enable(struct intel_dp *i
 
 	dev_priv->psr.busy_frontbuffer_bits = 0;
 
-	if (HAS_DDI(dev)) {
+	if (HAS_DDI(dev_priv)) {
 		hsw_psr_setup_vsc(intel_dp);
 
 		if (dev_priv->psr.psr2_support) {
@@ -472,7 +472,7 @@ void intel_psr_enable(struct intel_dp *i
 		/* Enable PSR on the panel */
 		hsw_psr_enable_sink(intel_dp);
 
-		if (INTEL_INFO(dev)->gen >= 9)
+		if (INTEL_GEN(dev_priv) >= 9)
 			intel_psr_activate(intel_dp);
 	} else {
 		vlv_psr_setup_vsc(intel_dp);
@@ -498,7 +498,7 @@ void intel_psr_enable(struct intel_dp *i
 	 *     - On HSW/BDW we get a recoverable frozen screen until next
 	 *       exit-activate sequence.
 	 */
-	if (INTEL_INFO(dev)->gen < 9)
+	if (INTEL_GEN(dev_priv) < 9)
 		schedule_delayed_work(&dev_priv->psr.work,
 				      msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5));
 
@@ -580,7 +580,7 @@ void intel_psr_disable(struct intel_dp *
 	}
 
 	/* Disable PSR on Source */
-	if (HAS_DDI(dev))
+	if (HAS_DDI(dev_priv))
 		hsw_psr_disable(intel_dp);
 	else
 		vlv_psr_disable(intel_dp);
@@ -825,19 +825,15 @@ void intel_psr_init(struct drm_device *d
 	dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ?
 		HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE;
 
-	/* Per platform default */
-	if (i915.enable_psr == -1) {
-		if (IS_HASWELL(dev) || IS_BROADWELL(dev))
-			i915.enable_psr = 1;
-		else
-			i915.enable_psr = 0;
-	}
+	/* Per platform default: all disabled. */
+	if (i915.enable_psr == -1)
+		i915.enable_psr = 0;
 
 	/* Set link_standby x link_off defaults */
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		/* HSW and BDW require workarounds that we don't implement. */
 		dev_priv->psr.link_standby = false;
-	else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 		/* On VLV and CHV only standby mode is supported. */
 		dev_priv->psr.link_standby = true;
 	else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -405,22 +405,6 @@ gen8_render_ring_flush(struct drm_i915_g
 	return gen8_emit_pipe_control(req, flags, scratch_addr);
 }
 
-u64 intel_engine_get_active_head(struct intel_engine_cs *engine)
-{
-	struct drm_i915_private *dev_priv = engine->i915;
-	u64 acthd;
-
-	if (INTEL_GEN(dev_priv) >= 8)
-		acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base),
-					 RING_ACTHD_UDW(engine->mmio_base));
-	else if (INTEL_GEN(dev_priv) >= 4)
-		acthd = I915_READ(RING_ACTHD(engine->mmio_base));
-	else
-		acthd = I915_READ(ACTHD);
-
-	return acthd;
-}
-
 static void ring_setup_phys_status_page(struct intel_engine_cs *engine)
 {
 	struct drm_i915_private *dev_priv = engine->i915;
@@ -585,9 +569,7 @@ static int init_ring_common(struct intel
 	I915_WRITE_TAIL(engine, ring->tail);
 	(void)I915_READ_TAIL(engine);
 
-	I915_WRITE_CTL(engine,
-			((ring->size - PAGE_SIZE) & RING_NR_PAGES)
-			| RING_VALID);
+	I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID);
 
 	/* If the head is still not zero, the ring is dead */
 	if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base),
@@ -666,7 +648,7 @@ static int intel_rcs_ctx_init(struct drm
 	if (ret != 0)
 		return ret;
 
-	ret = i915_gem_render_state_init(req);
+	ret = i915_gem_render_state_emit(req);
 	if (ret)
 		return ret;
 
@@ -851,15 +833,13 @@ static int gen9_init_workarounds(struct
 	WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3,
 			  GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC);
 
-	/* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
-	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+	/* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
 		WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
 				  GEN9_DG_MIRROR_FIX_ENABLE);
 
-	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) ||
-	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
+	/* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) {
 		WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1,
 				  GEN9_RHWO_OPTIMIZATION_DISABLE);
 		/*
@@ -869,10 +849,8 @@ static int gen9_init_workarounds(struct
 		 */
 	}
 
-	/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */
 	/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */
 	WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7,
-			  GEN9_ENABLE_YV12_BUGFIX |
 			  GEN9_ENABLE_GPGPU_PREEMPTION);
 
 	/* Wa4x4STCOptimizationDisable:skl,bxt,kbl */
@@ -884,9 +862,8 @@ static int gen9_init_workarounds(struct
 	WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5,
 			  GEN9_CCS_TLB_PREFETCH_ENABLE);
 
-	/* WaDisableMaskBasedCammingInRCC:skl,bxt */
-	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) ||
-	    IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
+	/* WaDisableMaskBasedCammingInRCC:bxt */
+	if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
 		WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0,
 				  PIXEL_MASK_CAMMING_DISABLE);
 
@@ -1003,47 +980,12 @@ static int skl_init_workarounds(struct i
 	 * until D0 which is the default case so this is equivalent to
 	 * !WaDisablePerCtxtPreemptionGranularityControl:skl
 	 */
-	if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) {
-		I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
-			   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
-	}
-
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) {
-		/* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */
-		I915_WRITE(FF_SLICE_CS_CHICKEN2,
-			   _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE));
-	}
-
-	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
-	 * involving this register should also be added to WA batch as required.
-	 */
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0))
-		/* WaDisableLSQCROPERFforOCL:skl */
-		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
-			   GEN8_LQSC_RO_PERF_DIS);
+	I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1,
+		   _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL));
 
 	/* WaEnableGapsTsvCreditFix:skl */
-	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) {
-		I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
-					   GEN9_GAPS_TSV_CREDIT_DISABLE));
-	}
-
-	/* WaDisablePowerCompilerClockGating:skl */
-	if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0))
-		WA_SET_BIT_MASKED(HIZ_CHICKEN,
-				  BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE);
-
-	/* WaBarrierPerformanceFixDisable:skl */
-	if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0))
-		WA_SET_BIT_MASKED(HDC_CHICKEN0,
-				  HDC_FENCE_DEST_SLM_DISABLE |
-				  HDC_BARRIER_PERFORMANCE_DISABLE);
-
-	/* WaDisableSbeCacheDispatchPortSharing:skl */
-	if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0))
-		WA_SET_BIT_MASKED(
-			GEN7_HALF_SLICE_CHICKEN1,
-			GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
+	I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) |
+				   GEN9_GAPS_TSV_CREDIT_DISABLE));
 
 	/* WaDisableGafsUnitClkGating:skl */
 	WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE);
@@ -1153,14 +1095,6 @@ static int kbl_init_workarounds(struct i
 		WA_SET_BIT_MASKED(HDC_CHICKEN0,
 				  HDC_FENCE_DEST_SLM_DISABLE);
 
-	/* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes
-	 * involving this register should also be added to WA batch as required.
-	 */
-	if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0))
-		/* WaDisableLSQCROPERFforOCL:kbl */
-		I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) |
-			   GEN8_LQSC_RO_PERF_DIS);
-
 	/* WaToEnableHwFixForPushConstHWBug:kbl */
 	if (IS_KBL_REVID(dev_priv, KBL_REVID_C0, REVID_FOREVER))
 		WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2,
@@ -1271,91 +1205,64 @@ static void render_ring_cleanup(struct i
 	i915_vma_unpin_and_release(&dev_priv->semaphore);
 }
 
-static int gen8_rcs_signal(struct drm_i915_gem_request *req)
+static u32 *gen8_rcs_signal(struct drm_i915_gem_request *req, u32 *out)
 {
-	struct intel_ring *ring = req->ring;
 	struct drm_i915_private *dev_priv = req->i915;
 	struct intel_engine_cs *waiter;
 	enum intel_engine_id id;
-	int ret, num_rings;
-
-	num_rings = INTEL_INFO(dev_priv)->num_rings;
-	ret = intel_ring_begin(req, (num_rings-1) * 8);
-	if (ret)
-		return ret;
 
-	for_each_engine_id(waiter, dev_priv, id) {
+	for_each_engine(waiter, dev_priv, id) {
 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
 			continue;
 
-		intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
-		intel_ring_emit(ring,
-				PIPE_CONTROL_GLOBAL_GTT_IVB |
-				PIPE_CONTROL_QW_WRITE |
-				PIPE_CONTROL_CS_STALL);
-		intel_ring_emit(ring, lower_32_bits(gtt_offset));
-		intel_ring_emit(ring, upper_32_bits(gtt_offset));
-		intel_ring_emit(ring, req->fence.seqno);
-		intel_ring_emit(ring, 0);
-		intel_ring_emit(ring,
-				MI_SEMAPHORE_SIGNAL |
-				MI_SEMAPHORE_TARGET(waiter->hw_id));
-		intel_ring_emit(ring, 0);
+		*out++ = GFX_OP_PIPE_CONTROL(6);
+		*out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB |
+			  PIPE_CONTROL_QW_WRITE |
+			  PIPE_CONTROL_CS_STALL);
+		*out++ = lower_32_bits(gtt_offset);
+		*out++ = upper_32_bits(gtt_offset);
+		*out++ = req->global_seqno;
+		*out++ = 0;
+		*out++ = (MI_SEMAPHORE_SIGNAL |
+			  MI_SEMAPHORE_TARGET(waiter->hw_id));
+		*out++ = 0;
 	}
-	intel_ring_advance(ring);
 
-	return 0;
+	return out;
 }
 
-static int gen8_xcs_signal(struct drm_i915_gem_request *req)
+static u32 *gen8_xcs_signal(struct drm_i915_gem_request *req, u32 *out)
 {
-	struct intel_ring *ring = req->ring;
 	struct drm_i915_private *dev_priv = req->i915;
 	struct intel_engine_cs *waiter;
 	enum intel_engine_id id;
-	int ret, num_rings;
-
-	num_rings = INTEL_INFO(dev_priv)->num_rings;
-	ret = intel_ring_begin(req, (num_rings-1) * 6);
-	if (ret)
-		return ret;
 
-	for_each_engine_id(waiter, dev_priv, id) {
+	for_each_engine(waiter, dev_priv, id) {
 		u64 gtt_offset = req->engine->semaphore.signal_ggtt[id];
 		if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID)
 			continue;
 
-		intel_ring_emit(ring,
-				(MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW);
-		intel_ring_emit(ring,
-				lower_32_bits(gtt_offset) |
-				MI_FLUSH_DW_USE_GTT);
-		intel_ring_emit(ring, upper_32_bits(gtt_offset));
-		intel_ring_emit(ring, req->fence.seqno);
-		intel_ring_emit(ring,
-				MI_SEMAPHORE_SIGNAL |
-				MI_SEMAPHORE_TARGET(waiter->hw_id));
-		intel_ring_emit(ring, 0);
+		*out++ = (MI_FLUSH_DW + 1) | MI_FLUSH_DW_OP_STOREDW;
+		*out++ = lower_32_bits(gtt_offset) | MI_FLUSH_DW_USE_GTT;
+		*out++ = upper_32_bits(gtt_offset);
+		*out++ = req->global_seqno;
+		*out++ = (MI_SEMAPHORE_SIGNAL |
+			  MI_SEMAPHORE_TARGET(waiter->hw_id));
+		*out++ = 0;
 	}
-	intel_ring_advance(ring);
 
-	return 0;
+	return out;
 }
 
-static int gen6_signal(struct drm_i915_gem_request *req)
+static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *out)
 {
-	struct intel_ring *ring = req->ring;
 	struct drm_i915_private *dev_priv = req->i915;
 	struct intel_engine_cs *engine;
-	int ret, num_rings;
-
-	num_rings = INTEL_INFO(dev_priv)->num_rings;
-	ret = intel_ring_begin(req, round_up((num_rings-1) * 3, 2));
-	if (ret)
-		return ret;
+	enum intel_engine_id id;
+	int num_rings = 0;
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		i915_reg_t mbox_reg;
 
 		if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK))
@@ -1363,101 +1270,80 @@ static int gen6_signal(struct drm_i915_g
 
 		mbox_reg = req->engine->semaphore.mbox.signal[engine->hw_id];
 		if (i915_mmio_reg_valid(mbox_reg)) {
-			intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-			intel_ring_emit_reg(ring, mbox_reg);
-			intel_ring_emit(ring, req->fence.seqno);
+			*out++ = MI_LOAD_REGISTER_IMM(1);
+			*out++ = i915_mmio_reg_offset(mbox_reg);
+			*out++ = req->global_seqno;
+			num_rings++;
 		}
 	}
+	if (num_rings & 1)
+		*out++ = MI_NOOP;
 
-	/* If num_dwords was rounded, make sure the tail pointer is correct */
-	if (num_rings % 2 == 0)
-		intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
-
-	return 0;
+	return out;
 }
 
 static void i9xx_submit_request(struct drm_i915_gem_request *request)
 {
 	struct drm_i915_private *dev_priv = request->i915;
 
-	I915_WRITE_TAIL(request->engine,
-			intel_ring_offset(request->ring, request->tail));
+	i915_gem_request_submit(request);
+
+	I915_WRITE_TAIL(request->engine, request->tail);
 }
 
-static int i9xx_emit_request(struct drm_i915_gem_request *req)
+static void i9xx_emit_breadcrumb(struct drm_i915_gem_request *req,
+				 u32 *out)
 {
-	struct intel_ring *ring = req->ring;
-	int ret;
-
-	ret = intel_ring_begin(req, 4);
-	if (ret)
-		return ret;
-
-	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, req->fence.seqno);
-	intel_ring_emit(ring, MI_USER_INTERRUPT);
-	intel_ring_advance(ring);
-
-	req->tail = ring->tail;
+	*out++ = MI_STORE_DWORD_INDEX;
+	*out++ = I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT;
+	*out++ = req->global_seqno;
+	*out++ = MI_USER_INTERRUPT;
 
-	return 0;
+	req->tail = intel_ring_offset(req->ring, out);
 }
 
+static const int i9xx_emit_breadcrumb_sz = 4;
+
 /**
- * gen6_sema_emit_request - Update the semaphore mailbox registers
+ * gen6_sema_emit_breadcrumb - Update the semaphore mailbox registers
  *
  * @request - request to write to 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_sema_emit_request(struct drm_i915_gem_request *req)
+static void gen6_sema_emit_breadcrumb(struct drm_i915_gem_request *req,
+				      u32 *out)
 {
-	int ret;
-
-	ret = req->engine->semaphore.signal(req);
-	if (ret)
-		return ret;
-
-	return i9xx_emit_request(req);
+	return i9xx_emit_breadcrumb(req,
+				    req->engine->semaphore.signal(req, out));
 }
 
-static int gen8_render_emit_request(struct drm_i915_gem_request *req)
+static void gen8_render_emit_breadcrumb(struct drm_i915_gem_request *req,
+					u32 *out)
 {
 	struct intel_engine_cs *engine = req->engine;
-	struct intel_ring *ring = req->ring;
-	int ret;
 
-	if (engine->semaphore.signal) {
-		ret = engine->semaphore.signal(req);
-		if (ret)
-			return ret;
-	}
-
-	ret = intel_ring_begin(req, 8);
-	if (ret)
-		return ret;
+	if (engine->semaphore.signal)
+		out = engine->semaphore.signal(req, out);
 
-	intel_ring_emit(ring, GFX_OP_PIPE_CONTROL(6));
-	intel_ring_emit(ring, (PIPE_CONTROL_GLOBAL_GTT_IVB |
+	*out++ = GFX_OP_PIPE_CONTROL(6);
+	*out++ = (PIPE_CONTROL_GLOBAL_GTT_IVB |
 			       PIPE_CONTROL_CS_STALL |
-			       PIPE_CONTROL_QW_WRITE));
-	intel_ring_emit(ring, intel_hws_seqno_address(engine));
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, i915_gem_request_get_seqno(req));
+			       PIPE_CONTROL_QW_WRITE);
+	*out++ = intel_hws_seqno_address(engine);
+	*out++ = 0;
+	*out++ = req->global_seqno;
 	/* We're thrashing one dword of HWS. */
-	intel_ring_emit(ring, 0);
-	intel_ring_emit(ring, MI_USER_INTERRUPT);
-	intel_ring_emit(ring, MI_NOOP);
-	intel_ring_advance(ring);
-
-	req->tail = ring->tail;
+	*out++ = 0;
+	*out++ = MI_USER_INTERRUPT;
+	*out++ = MI_NOOP;
 
-	return 0;
+	req->tail = intel_ring_offset(req->ring, out);
 }
 
+static const int gen8_render_emit_breadcrumb_sz = 8;
+
 /**
  * intel_ring_sync - sync the waiter to the signaller on seqno
  *
@@ -1484,7 +1370,7 @@ gen8_ring_sync_to(struct drm_i915_gem_re
 			MI_SEMAPHORE_WAIT |
 			MI_SEMAPHORE_GLOBAL_GTT |
 			MI_SEMAPHORE_SAD_GTE_SDD);
-	intel_ring_emit(ring, signal->fence.seqno);
+	intel_ring_emit(ring, signal->global_seqno);
 	intel_ring_emit(ring, lower_32_bits(offset));
 	intel_ring_emit(ring, upper_32_bits(offset));
 	intel_ring_advance(ring);
@@ -1522,7 +1408,7 @@ gen6_ring_sync_to(struct drm_i915_gem_re
 	 * seqno is >= the last seqno executed. However for hardware the
 	 * comparison is strictly greater than.
 	 */
-	intel_ring_emit(ring, signal->fence.seqno - 1);
+	intel_ring_emit(ring, signal->global_seqno - 1);
 	intel_ring_emit(ring, 0);
 	intel_ring_emit(ring, MI_NOOP);
 	intel_ring_advance(ring);
@@ -1665,7 +1551,7 @@ hsw_vebox_irq_enable(struct intel_engine
 	struct drm_i915_private *dev_priv = engine->i915;
 
 	I915_WRITE_IMR(engine, ~engine->irq_enable_mask);
-	gen6_enable_pm_irq(dev_priv, engine->irq_enable_mask);
+	gen6_unmask_pm_irq(dev_priv, engine->irq_enable_mask);
 }
 
 static void
@@ -1674,7 +1560,7 @@ hsw_vebox_irq_disable(struct intel_engin
 	struct drm_i915_private *dev_priv = engine->i915;
 
 	I915_WRITE_IMR(engine, ~0);
-	gen6_disable_pm_irq(dev_priv, engine->irq_enable_mask);
+	gen6_mask_pm_irq(dev_priv, engine->irq_enable_mask);
 }
 
 static void
@@ -1819,14 +1705,19 @@ static void cleanup_phys_status_page(str
 static void cleanup_status_page(struct intel_engine_cs *engine)
 {
 	struct i915_vma *vma;
+	struct drm_i915_gem_object *obj;
 
 	vma = fetch_and_zero(&engine->status_page.vma);
 	if (!vma)
 		return;
 
+	obj = vma->obj;
+
 	i915_vma_unpin(vma);
-	i915_gem_object_unpin_map(vma->obj);
-	i915_vma_put(vma);
+	i915_vma_close(vma);
+
+	i915_gem_object_unpin_map(obj);
+	__i915_gem_object_release_unless_active(obj);
 }
 
 static int init_status_page(struct intel_engine_cs *engine)
@@ -1834,9 +1725,10 @@ static int init_status_page(struct intel
 	struct drm_i915_gem_object *obj;
 	struct i915_vma *vma;
 	unsigned int flags;
+	void *vaddr;
 	int ret;
 
-	obj = i915_gem_object_create(&engine->i915->drm, 4096);
+	obj = i915_gem_object_create_internal(engine->i915, 4096);
 	if (IS_ERR(obj)) {
 		DRM_ERROR("Failed to allocate status page\n");
 		return PTR_ERR(obj);
@@ -1869,15 +1761,22 @@ static int init_status_page(struct intel
 	if (ret)
 		goto err;
 
+	vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
+	if (IS_ERR(vaddr)) {
+		ret = PTR_ERR(vaddr);
+		goto err_unpin;
+	}
+
 	engine->status_page.vma = vma;
 	engine->status_page.ggtt_offset = i915_ggtt_offset(vma);
-	engine->status_page.page_addr =
-		i915_gem_object_pin_map(obj, I915_MAP_WB);
+	engine->status_page.page_addr = memset(vaddr, 0, 4096);
 
 	DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n",
 			 engine->name, i915_ggtt_offset(vma));
 	return 0;
 
+err_unpin:
+	i915_vma_unpin(vma);
 err:
 	i915_gem_object_put(obj);
 	return ret;
@@ -1989,6 +1888,7 @@ intel_engine_create_ring(struct intel_en
 	struct i915_vma *vma;
 
 	GEM_BUG_ON(!is_power_of_2(size));
+	GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES);
 
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 	if (!ring)
@@ -2023,7 +1923,11 @@ intel_engine_create_ring(struct intel_en
 void
 intel_ring_free(struct intel_ring *ring)
 {
-	i915_vma_put(ring->vma);
+	struct drm_i915_gem_object *obj = ring->vma->obj;
+
+	i915_vma_close(ring->vma);
+	__i915_gem_object_release_unless_active(obj);
+
 	kfree(ring);
 }
 
@@ -2039,14 +1943,13 @@ static int intel_ring_context_pin(struct
 		return 0;
 
 	if (ce->state) {
-		ret = i915_gem_object_set_to_gtt_domain(ce->state->obj, false);
-		if (ret)
-			goto error;
+		struct i915_vma *vma;
 
-		ret = i915_vma_pin(ce->state, 0, ctx->ggtt_alignment,
-				   PIN_GLOBAL | PIN_HIGH);
-		if (ret)
+		vma = i915_gem_context_pin_legacy(ctx, PIN_HIGH);
+		if (IS_ERR(vma)) {
+			ret = PTR_ERR(vma);
 			goto error;
+		}
 	}
 
 	/* The kernel context is only used as a placeholder for flushing the
@@ -2093,9 +1996,6 @@ static int intel_init_ring_buffer(struct
 
 	intel_engine_setup_common(engine);
 
-	memset(engine->semaphore.sync_seqno, 0,
-	       sizeof(engine->semaphore.sync_seqno));
-
 	ret = intel_engine_init_common(engine);
 	if (ret)
 		goto error;
@@ -2146,9 +2046,6 @@ void intel_engine_cleanup(struct intel_e
 {
 	struct drm_i915_private *dev_priv;
 
-	if (!intel_engine_initialized(engine))
-		return;
-
 	dev_priv = engine->i915;
 
 	if (engine->buffer) {
@@ -2175,13 +2072,16 @@ void intel_engine_cleanup(struct intel_e
 	intel_ring_context_unpin(dev_priv->kernel_context, engine);
 
 	engine->i915 = NULL;
+	dev_priv->engine[engine->id] = NULL;
+	kfree(engine);
 }
 
 void intel_legacy_submission_resume(struct drm_i915_private *dev_priv)
 {
 	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
 
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv, id) {
 		engine->buffer->head = engine->buffer->tail;
 		engine->buffer->last_retired_head = -1;
 	}
@@ -2211,7 +2111,9 @@ static int wait_for_space(struct drm_i91
 {
 	struct intel_ring *ring = req->ring;
 	struct drm_i915_gem_request *target;
-	int ret;
+	long timeout;
+
+	lockdep_assert_held(&req->i915->drm.struct_mutex);
 
 	intel_ring_update_space(ring);
 	if (ring->space >= bytes)
@@ -2241,11 +2143,11 @@ static int wait_for_space(struct drm_i91
 	if (WARN_ON(&target->ring_link == &ring->request_list))
 		return -ENOSPC;
 
-	ret = i915_wait_request(target,
-				I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
-				NULL, NO_WAITBOOST);
-	if (ret)
-		return ret;
+	timeout = i915_wait_request(target,
+				    I915_WAIT_INTERRUPTIBLE | I915_WAIT_LOCKED,
+				    MAX_SCHEDULE_TIMEOUT);
+	if (timeout < 0)
+		return timeout;
 
 	i915_gem_request_retire_upto(target);
 
@@ -2674,9 +2576,22 @@ static void intel_ring_default_vfuncs(st
 	engine->init_hw = init_ring_common;
 	engine->reset_hw = reset_ring_common;
 
-	engine->emit_request = i9xx_emit_request;
-	if (i915.semaphores)
-		engine->emit_request = gen6_sema_emit_request;
+	engine->emit_breadcrumb = i9xx_emit_breadcrumb;
+	engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz;
+	if (i915.semaphores) {
+		int num_rings;
+
+		engine->emit_breadcrumb = gen6_sema_emit_breadcrumb;
+
+		num_rings = hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1;
+		if (INTEL_GEN(dev_priv) >= 8) {
+			engine->emit_breadcrumb_sz += num_rings * 6;
+		} else {
+			engine->emit_breadcrumb_sz += num_rings * 3;
+			if (num_rings & 1)
+				engine->emit_breadcrumb_sz++;
+		}
+	}
 	engine->submit_request = i9xx_submit_request;
 
 	if (INTEL_GEN(dev_priv) >= 8)
@@ -2703,10 +2618,18 @@ int intel_init_render_ring_buffer(struct
 
 	if (INTEL_GEN(dev_priv) >= 8) {
 		engine->init_context = intel_rcs_ctx_init;
-		engine->emit_request = gen8_render_emit_request;
+		engine->emit_breadcrumb = gen8_render_emit_breadcrumb;
+		engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz;
 		engine->emit_flush = gen8_render_ring_flush;
-		if (i915.semaphores)
+		if (i915.semaphores) {
+			int num_rings;
+
 			engine->semaphore.signal = gen8_rcs_signal;
+
+			num_rings =
+				hweight32(INTEL_INFO(dev_priv)->ring_mask) - 1;
+			engine->emit_breadcrumb_sz += num_rings * 6;
+		}
 	} else if (INTEL_GEN(dev_priv) >= 6) {
 		engine->init_context = intel_rcs_ctx_init;
 		engine->emit_flush = gen7_render_ring_flush;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,6 +4,7 @@
 #include <linux/hashtable.h>
 #include "i915_gem_batch_pool.h"
 #include "i915_gem_request.h"
+#include "i915_gem_timeline.h"
 
 #define I915_CMD_HASH_ORDER 9
 
@@ -73,13 +74,40 @@ enum intel_engine_hangcheck_action {
 
 #define HANGCHECK_SCORE_RING_HUNG 31
 
+#define I915_MAX_SLICES	3
+#define I915_MAX_SUBSLICES 3
+
+#define instdone_slice_mask(dev_priv__) \
+	(INTEL_GEN(dev_priv__) == 7 ? \
+	 1 : INTEL_INFO(dev_priv__)->sseu.slice_mask)
+
+#define instdone_subslice_mask(dev_priv__) \
+	(INTEL_GEN(dev_priv__) == 7 ? \
+	 1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask)
+
+#define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \
+	for ((slice__) = 0, (subslice__) = 0; \
+	     (slice__) < I915_MAX_SLICES; \
+	     (subslice__) = ((subslice__) + 1) < I915_MAX_SUBSLICES ? (subslice__) + 1 : 0, \
+	       (slice__) += ((subslice__) == 0)) \
+		for_each_if((BIT(slice__) & instdone_slice_mask(dev_priv__)) && \
+			    (BIT(subslice__) & instdone_subslice_mask(dev_priv__)))
+
+struct intel_instdone {
+	u32 instdone;
+	/* The following exist only in the RCS engine */
+	u32 slice_common;
+	u32 sampler[I915_MAX_SLICES][I915_MAX_SUBSLICES];
+	u32 row[I915_MAX_SLICES][I915_MAX_SUBSLICES];
+};
+
 struct intel_engine_hangcheck {
 	u64 acthd;
 	u32 seqno;
 	int score;
 	enum intel_engine_hangcheck_action action;
 	int deadlock;
-	u32 instdone[I915_NUM_INSTDONE_REG];
+	struct intel_instdone instdone;
 };
 
 struct intel_ring {
@@ -130,6 +158,7 @@ struct i915_ctx_workarounds {
 };
 
 struct drm_i915_gem_request;
+struct intel_render_state;
 
 struct intel_engine_cs {
 	struct drm_i915_private *i915;
@@ -141,7 +170,6 @@ struct intel_engine_cs {
 		VCS2,	/* Keep instances of the same type engine together. */
 		VECS
 	} id;
-#define I915_NUM_ENGINES 5
 #define _VCS(n) (VCS + (n))
 	unsigned int exec_id;
 	enum intel_engine_hw_id {
@@ -152,10 +180,12 @@ struct intel_engine_cs {
 		VCS2_HW
 	} hw_id;
 	enum intel_engine_hw_id guc_id; /* XXX same as hw_id? */
-	u64 fence_context;
 	u32		mmio_base;
 	unsigned int irq_shift;
 	struct intel_ring *buffer;
+	struct intel_timeline *timeline;
+
+	struct intel_render_state *render_state;
 
 	/* Rather than have every client wait upon all user interrupts,
 	 * with the herd waking after every interrupt and each doing the
@@ -177,7 +207,7 @@ struct intel_engine_cs {
 		struct task_struct __rcu *irq_seqno_bh; /* bh for interrupts */
 		bool irq_posted;
 
-		spinlock_t lock; /* protects the lists of requests */
+		spinlock_t lock; /* protects the lists of requests; irqsafe */
 		struct rb_root waiters; /* sorted by retirement, priority */
 		struct rb_root signals; /* sorted by retirement */
 		struct intel_wait *first_wait; /* oldest waiter by retirement */
@@ -225,7 +255,9 @@ struct intel_engine_cs {
 #define I915_DISPATCH_SECURE BIT(0)
 #define I915_DISPATCH_PINNED BIT(1)
 #define I915_DISPATCH_RS     BIT(2)
-	int		(*emit_request)(struct drm_i915_gem_request *req);
+	void		(*emit_breadcrumb)(struct drm_i915_gem_request *req,
+					   u32 *out);
+	int		emit_breadcrumb_sz;
 
 	/* Pass the request to the hardware queue (e.g. directly into
 	 * the legacy ringbuffer or to the end of an execlist).
@@ -235,6 +267,15 @@ struct intel_engine_cs {
 	 */
 	void		(*submit_request)(struct drm_i915_gem_request *req);
 
+	/* Call when the priority on a request has changed and it and its
+	 * dependencies may need rescheduling. Note the request itself may
+	 * not be ready to run!
+	 *
+	 * Called under the struct_mutex.
+	 */
+	void		(*schedule)(struct drm_i915_gem_request *request,
+				    int priority);
+
 	/* Some chipsets are not quite as coherent as advertised and need
 	 * an expensive kick to force a true read of the up-to-date seqno.
 	 * However, the up-to-date seqno is not always required and the last
@@ -282,8 +323,6 @@ struct intel_engine_cs {
 	 *  ie. transpose of f(x, y)
 	 */
 	struct {
-		u32	sync_seqno[I915_NUM_ENGINES-1];
-
 		union {
 #define GEN6_SEMAPHORE_LAST	VECS_HW
 #define GEN6_NUM_SEMAPHORES	(GEN6_SEMAPHORE_LAST + 1)
@@ -300,43 +339,22 @@ struct intel_engine_cs {
 		/* AKA wait() */
 		int	(*sync_to)(struct drm_i915_gem_request *req,
 				   struct drm_i915_gem_request *signal);
-		int	(*signal)(struct drm_i915_gem_request *req);
+		u32	*(*signal)(struct drm_i915_gem_request *req, u32 *out);
 	} semaphore;
 
 	/* Execlists */
 	struct tasklet_struct irq_tasklet;
-	spinlock_t execlist_lock; /* used inside tasklet, use spin_lock_bh */
 	struct execlist_port {
 		struct drm_i915_gem_request *request;
 		unsigned int count;
 	} execlist_port[2];
-	struct list_head execlist_queue;
+	struct rb_root execlist_queue;
+	struct rb_node *execlist_first;
 	unsigned int fw_domains;
 	bool disable_lite_restore_wa;
 	bool preempt_wa;
 	u32 ctx_desc_template;
 
-	/**
-	 * List of breadcrumbs associated with GPU requests currently
-	 * outstanding.
-	 */
-	struct list_head request_list;
-
-	/**
-	 * Seqno of request most recently submitted to request_list.
-	 * Used exclusively by hang checker to avoid grabbing lock while
-	 * inspecting request list.
-	 */
-	u32 last_submitted_seqno;
-	u32 last_pending_seqno;
-
-	/* An RCU guarded pointer to the last request. No reference is
-	 * held to the request, users must carefully acquire a reference to
-	 * the request using i915_gem_active_get_rcu(), or hold the
-	 * struct_mutex.
-	 */
-	struct i915_gem_active last_request;
-
 	struct i915_gem_context *last_context;
 
 	struct intel_engine_hangcheck hangcheck;
@@ -368,39 +386,12 @@ struct intel_engine_cs {
 	u32 (*get_cmd_length_mask)(u32 cmd_header);
 };
 
-static inline bool
-intel_engine_initialized(const struct intel_engine_cs *engine)
-{
-	return engine->i915 != NULL;
-}
-
 static inline unsigned
 intel_engine_flag(const struct intel_engine_cs *engine)
 {
 	return 1 << engine->id;
 }
 
-static inline u32
-intel_engine_sync_index(struct intel_engine_cs *engine,
-			struct intel_engine_cs *other)
-{
-	int idx;
-
-	/*
-	 * rcs -> 0 = vcs, 1 = bcs, 2 = vecs, 3 = vcs2;
-	 * vcs -> 0 = bcs, 1 = vecs, 2 = vcs2, 3 = rcs;
-	 * bcs -> 0 = vecs, 1 = vcs2. 2 = rcs, 3 = vcs;
-	 * vecs -> 0 = vcs2, 1 = rcs, 2 = vcs, 3 = bcs;
-	 * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs;
-	 */
-
-	idx = (other - engine) - 1;
-	if (idx < 0)
-		idx += I915_NUM_ENGINES;
-
-	return idx;
-}
-
 static inline void
 intel_flush_status_page(struct intel_engine_cs *engine, int reg)
 {
@@ -483,30 +474,23 @@ static inline void intel_ring_advance(st
 	 */
 }
 
-static inline u32 intel_ring_offset(struct intel_ring *ring, u32 value)
+static inline u32 intel_ring_offset(struct intel_ring *ring, void *addr)
 {
 	/* Don't write ring->size (equivalent to 0) as that hangs some GPUs. */
-	return value & (ring->size - 1);
+	u32 offset = addr - ring->vaddr;
+	return offset & (ring->size - 1);
 }
 
 int __intel_ring_space(int head, int tail, int size);
 void intel_ring_update_space(struct intel_ring *ring);
 
-void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno);
+void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno);
 
 void intel_engine_setup_common(struct intel_engine_cs *engine);
 int intel_engine_init_common(struct intel_engine_cs *engine);
 int intel_engine_create_scratch(struct intel_engine_cs *engine, int size);
 void intel_engine_cleanup_common(struct intel_engine_cs *engine);
 
-static inline int intel_engine_idle(struct intel_engine_cs *engine,
-				    unsigned int flags)
-{
-	/* Wait upon the last request to be completed */
-	return i915_gem_active_wait_unlocked(&engine->last_request,
-					     flags, NULL, NULL);
-}
-
 int intel_init_render_ring_buffer(struct intel_engine_cs *engine);
 int intel_init_bsd_ring_buffer(struct intel_engine_cs *engine);
 int intel_init_bsd2_ring_buffer(struct intel_engine_cs *engine);
@@ -514,13 +498,30 @@ int intel_init_blt_ring_buffer(struct in
 int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine);
 
 u64 intel_engine_get_active_head(struct intel_engine_cs *engine);
+u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine);
+
 static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine)
 {
 	return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
 }
 
+static inline u32 intel_engine_last_submit(struct intel_engine_cs *engine)
+{
+	/* We are only peeking at the tail of the submit queue (and not the
+	 * queue itself) in order to gain a hint as to the current active
+	 * state of the engine. Callers are not expected to be taking
+	 * engine->timeline->lock, nor are they expected to be concerned
+	 * wtih serialising this hint with anything, so document it as
+	 * a hint and nothing more.
+	 */
+	return READ_ONCE(engine->timeline->last_submitted_seqno);
+}
+
 int init_workarounds_ring(struct intel_engine_cs *engine);
 
+void intel_engine_get_instdone(struct intel_engine_cs *engine,
+			       struct intel_instdone *instdone);
+
 /*
  * Arbitrary size for largest possible 'add request' sequence. The code paths
  * are complex and variable. Empirical measurement shows that the worst case
@@ -586,12 +587,6 @@ static inline bool intel_engine_wakeup(c
 
 void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine);
 void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine);
-unsigned int intel_kick_waiters(struct drm_i915_private *i915);
-unsigned int intel_kick_signalers(struct drm_i915_private *i915);
-
-static inline bool intel_engine_is_active(struct intel_engine_cs *engine)
-{
-	return i915_gem_active_isset(&engine->last_request);
-}
+unsigned int intel_breadcrumbs_busy(struct drm_i915_private *i915);
 
 #endif /* _INTEL_RINGBUFFER_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_runtime_pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -288,7 +288,6 @@ void intel_display_set_init_power(struct
 static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
-	struct drm_device *dev = &dev_priv->drm;
 
 	/*
 	 * After we re-enable the power well, if we touch VGA register 0x3d5
@@ -304,7 +303,7 @@ static void hsw_power_well_post_enable(s
 	outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
 	vga_put(pdev, VGA_RSRC_LEGACY_IO);
 
-	if (IS_BROADWELL(dev))
+	if (IS_BROADWELL(dev_priv))
 		gen8_irq_power_well_post_enable(dev_priv,
 						1 << PIPE_C | 1 << PIPE_B);
 }
@@ -331,7 +330,7 @@ static void skl_power_well_post_enable(s
 	 * sure vgacon can keep working normally without triggering interrupts
 	 * and error messages.
 	 */
-	if (power_well->data == SKL_DISP_PW_2) {
+	if (power_well->id == SKL_DISP_PW_2) {
 		vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO);
 		outb(inb(VGA_MSR_READ), VGA_MSR_WRITE);
 		vga_put(pdev, VGA_RSRC_LEGACY_IO);
@@ -344,7 +343,7 @@ static void skl_power_well_post_enable(s
 static void skl_power_well_pre_disable(struct drm_i915_private *dev_priv,
 				       struct i915_power_well *power_well)
 {
-	if (power_well->data == SKL_DISP_PW_2)
+	if (power_well->id == SKL_DISP_PW_2)
 		gen8_irq_power_well_pre_disable(dev_priv,
 						1 << PIPE_C | 1 << PIPE_B);
 }
@@ -659,7 +658,7 @@ static void
 gen9_sanitize_power_well_requests(struct drm_i915_private *dev_priv,
 				  struct i915_power_well *power_well)
 {
-	enum skl_disp_power_wells power_well_id = power_well->data;
+	enum skl_disp_power_wells power_well_id = power_well->id;
 	u32 val;
 	u32 mask;
 
@@ -704,7 +703,7 @@ static void skl_set_power_well(struct dr
 	tmp = I915_READ(HSW_PWR_WELL_DRIVER);
 	fuse_status = I915_READ(SKL_FUSE_STATUS);
 
-	switch (power_well->data) {
+	switch (power_well->id) {
 	case SKL_DISP_PW_1:
 		if (intel_wait_for_register(dev_priv,
 					    SKL_FUSE_STATUS,
@@ -728,13 +727,13 @@ static void skl_set_power_well(struct dr
 	case SKL_DISP_PW_MISC_IO:
 		break;
 	default:
-		WARN(1, "Unknown power well %lu\n", power_well->data);
+		WARN(1, "Unknown power well %lu\n", power_well->id);
 		return;
 	}
 
-	req_mask = SKL_POWER_WELL_REQ(power_well->data);
+	req_mask = SKL_POWER_WELL_REQ(power_well->id);
 	enable_requested = tmp & req_mask;
-	state_mask = SKL_POWER_WELL_STATE(power_well->data);
+	state_mask = SKL_POWER_WELL_STATE(power_well->id);
 	is_enabled = tmp & state_mask;
 
 	if (!enable && enable_requested)
@@ -770,14 +769,14 @@ static void skl_set_power_well(struct dr
 			  power_well->name, enable ? "enable" : "disable");
 
 	if (check_fuse_status) {
-		if (power_well->data == SKL_DISP_PW_1) {
+		if (power_well->id == SKL_DISP_PW_1) {
 			if (intel_wait_for_register(dev_priv,
 						    SKL_FUSE_STATUS,
 						    SKL_FUSE_PG1_DIST_STATUS,
 						    SKL_FUSE_PG1_DIST_STATUS,
 						    1))
 				DRM_ERROR("PG1 distributing status timeout\n");
-		} else if (power_well->data == SKL_DISP_PW_2) {
+		} else if (power_well->id == SKL_DISP_PW_2) {
 			if (intel_wait_for_register(dev_priv,
 						    SKL_FUSE_STATUS,
 						    SKL_FUSE_PG2_DIST_STATUS,
@@ -819,8 +818,8 @@ static void hsw_power_well_disable(struc
 static bool skl_power_well_enabled(struct drm_i915_private *dev_priv,
 					struct i915_power_well *power_well)
 {
-	uint32_t mask = SKL_POWER_WELL_REQ(power_well->data) |
-		SKL_POWER_WELL_STATE(power_well->data);
+	uint32_t mask = SKL_POWER_WELL_REQ(power_well->id) |
+		SKL_POWER_WELL_STATE(power_well->id);
 
 	return (I915_READ(HSW_PWR_WELL_DRIVER) & mask) == mask;
 }
@@ -846,45 +845,22 @@ static void skl_power_well_disable(struc
 	skl_set_power_well(dev_priv, power_well, false);
 }
 
-static enum dpio_phy bxt_power_well_to_phy(struct i915_power_well *power_well)
-{
-	enum skl_disp_power_wells power_well_id = power_well->data;
-
-	return power_well_id == BXT_DPIO_CMN_A ? DPIO_PHY1 : DPIO_PHY0;
-}
-
 static void bxt_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
-	enum skl_disp_power_wells power_well_id = power_well->data;
-	struct i915_power_well *cmn_a_well = NULL;
-
-	if (power_well_id == BXT_DPIO_CMN_BC) {
-		/*
-		 * We need to copy the GRC calibration value from the eDP PHY,
-		 * so make sure it's powered up.
-		 */
-		cmn_a_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A);
-		intel_power_well_get(dev_priv, cmn_a_well);
-	}
-
-	bxt_ddi_phy_init(dev_priv, bxt_power_well_to_phy(power_well));
-
-	if (cmn_a_well)
-		intel_power_well_put(dev_priv, cmn_a_well);
+	bxt_ddi_phy_init(dev_priv, power_well->data);
 }
 
 static void bxt_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
 					    struct i915_power_well *power_well)
 {
-	bxt_ddi_phy_uninit(dev_priv, bxt_power_well_to_phy(power_well));
+	bxt_ddi_phy_uninit(dev_priv, power_well->data);
 }
 
 static bool bxt_dpio_cmn_power_well_enabled(struct drm_i915_private *dev_priv,
 					    struct i915_power_well *power_well)
 {
-	return bxt_ddi_phy_is_enabled(dev_priv,
-				      bxt_power_well_to_phy(power_well));
+	return bxt_ddi_phy_is_enabled(dev_priv, power_well->data);
 }
 
 static void bxt_dpio_cmn_power_well_sync_hw(struct drm_i915_private *dev_priv,
@@ -903,13 +879,11 @@ static void bxt_verify_ddi_phy_power_wel
 
 	power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_A);
 	if (power_well->count > 0)
-		bxt_ddi_phy_verify_state(dev_priv,
-					 bxt_power_well_to_phy(power_well));
+		bxt_ddi_phy_verify_state(dev_priv, power_well->data);
 
 	power_well = lookup_power_well(dev_priv, BXT_DPIO_CMN_BC);
 	if (power_well->count > 0)
-		bxt_ddi_phy_verify_state(dev_priv,
-					 bxt_power_well_to_phy(power_well));
+		bxt_ddi_phy_verify_state(dev_priv, power_well->data);
 }
 
 static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
@@ -933,7 +907,7 @@ static void gen9_dc_off_power_well_enabl
 	gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
 
 	WARN_ON(dev_priv->cdclk_freq !=
-		dev_priv->display.get_display_clock_speed(&dev_priv->drm));
+		dev_priv->display.get_display_clock_speed(dev_priv));
 
 	gen9_assert_dbuf_enabled(dev_priv);
 
@@ -976,7 +950,7 @@ static bool i9xx_always_on_power_well_en
 static void vlv_set_power_well(struct drm_i915_private *dev_priv,
 			       struct i915_power_well *power_well, bool enable)
 {
-	enum punit_power_well power_well_id = power_well->data;
+	enum punit_power_well power_well_id = power_well->id;
 	u32 mask;
 	u32 state;
 	u32 ctrl;
@@ -1030,7 +1004,7 @@ static void vlv_power_well_disable(struc
 static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
 				   struct i915_power_well *power_well)
 {
-	int power_well_id = power_well->data;
+	int power_well_id = power_well->id;
 	bool enabled = false;
 	u32 mask;
 	u32 state;
@@ -1065,7 +1039,18 @@ static bool vlv_power_well_enabled(struc
 
 static void vlv_init_display_clock_gating(struct drm_i915_private *dev_priv)
 {
-	I915_WRITE(DSPCLK_GATE_D, VRHUNIT_CLOCK_GATE_DISABLE);
+	u32 val;
+
+	/*
+	 * On driver load, a pipe may be active and driving a DSI display.
+	 * Preserve DPOUNIT_CLOCK_GATE_DISABLE to avoid the pipe getting stuck
+	 * (and never recovering) in this case. intel_dsi_post_disable() will
+	 * clear it when we turn off the display.
+	 */
+	val = I915_READ(DSPCLK_GATE_D);
+	val &= DPOUNIT_CLOCK_GATE_DISABLE;
+	val |= VRHUNIT_CLOCK_GATE_DISABLE;
+	I915_WRITE(DSPCLK_GATE_D, val);
 
 	/*
 	 * Disable trickle feed and enable pnd deadline calculation
@@ -1092,7 +1077,7 @@ static void vlv_display_power_well_init(
 	 *
 	 * CHV DPLL B/C have some issues if VGA mode is enabled.
 	 */
-	for_each_pipe(&dev_priv->drm, pipe) {
+	for_each_pipe(dev_priv, pipe) {
 		u32 val = I915_READ(DPLL(pipe));
 
 		val |= DPLL_REF_CLK_ENABLE_VLV | DPLL_VGA_MODE_DIS;
@@ -1123,7 +1108,7 @@ static void vlv_display_power_well_init(
 			intel_crt_reset(&encoder->base);
 	}
 
-	i915_redisable_vga_power_on(&dev_priv->drm);
+	i915_redisable_vga_power_on(dev_priv);
 
 	intel_pps_unlock_regs_wa(dev_priv);
 }
@@ -1147,7 +1132,7 @@ static void vlv_display_power_well_deini
 static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
 					  struct i915_power_well *power_well)
 {
-	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
+	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
 
 	vlv_set_power_well(dev_priv, power_well, true);
 
@@ -1157,7 +1142,7 @@ static void vlv_display_power_well_enabl
 static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
-	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
+	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DISP2D);
 
 	vlv_display_power_well_deinit(dev_priv);
 
@@ -1167,7 +1152,7 @@ static void vlv_display_power_well_disab
 static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
-	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
+	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
 
 	/* since ref/cri clock was enabled */
 	udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
@@ -1193,7 +1178,7 @@ static void vlv_dpio_cmn_power_well_disa
 {
 	enum pipe pipe;
 
-	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC);
+	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC);
 
 	for_each_pipe(dev_priv, pipe)
 		assert_pll_disabled(dev_priv, pipe);
@@ -1216,7 +1201,7 @@ static struct i915_power_well *lookup_po
 		struct i915_power_well *power_well;
 
 		power_well = &power_domains->power_wells[i];
-		if (power_well->data == power_well_id)
+		if (power_well->id == power_well_id)
 			return power_well;
 	}
 
@@ -1340,10 +1325,10 @@ static void chv_dpio_cmn_power_well_enab
 	enum pipe pipe;
 	uint32_t tmp;
 
-	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
-		     power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
+	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
+		     power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
 
-	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+	if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
 		pipe = PIPE_A;
 		phy = DPIO_PHY0;
 	} else {
@@ -1371,7 +1356,7 @@ static void chv_dpio_cmn_power_well_enab
 		DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
 	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
 
-	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+	if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
 		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
 		tmp |= DPIO_DYNPWRDOWNEN_CH1;
 		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
@@ -1402,10 +1387,10 @@ static void chv_dpio_cmn_power_well_disa
 {
 	enum dpio_phy phy;
 
-	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
-		     power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
+	WARN_ON_ONCE(power_well->id != PUNIT_POWER_WELL_DPIO_CMN_BC &&
+		     power_well->id != PUNIT_POWER_WELL_DPIO_CMN_D);
 
-	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+	if (power_well->id == PUNIT_POWER_WELL_DPIO_CMN_BC) {
 		phy = DPIO_PHY0;
 		assert_pll_disabled(dev_priv, PIPE_A);
 		assert_pll_disabled(dev_priv, PIPE_B);
@@ -1554,7 +1539,7 @@ void chv_phy_powergate_lanes(struct inte
 static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
 					struct i915_power_well *power_well)
 {
-	enum pipe pipe = power_well->data;
+	enum pipe pipe = power_well->id;
 	bool enabled;
 	u32 state, ctrl;
 
@@ -1584,7 +1569,7 @@ static void chv_set_pipe_power_well(stru
 				    struct i915_power_well *power_well,
 				    bool enable)
 {
-	enum pipe pipe = power_well->data;
+	enum pipe pipe = power_well->id;
 	u32 state;
 	u32 ctrl;
 
@@ -1617,7 +1602,7 @@ out:
 static void chv_pipe_power_well_sync_hw(struct drm_i915_private *dev_priv,
 					struct i915_power_well *power_well)
 {
-	WARN_ON_ONCE(power_well->data != PIPE_A);
+	WARN_ON_ONCE(power_well->id != PIPE_A);
 
 	chv_set_pipe_power_well(dev_priv, power_well, power_well->count > 0);
 }
@@ -1625,7 +1610,7 @@ static void chv_pipe_power_well_sync_hw(
 static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv,
 				       struct i915_power_well *power_well)
 {
-	WARN_ON_ONCE(power_well->data != PIPE_A);
+	WARN_ON_ONCE(power_well->id != PIPE_A);
 
 	chv_set_pipe_power_well(dev_priv, power_well, true);
 
@@ -1635,7 +1620,7 @@ static void chv_pipe_power_well_enable(s
 static void chv_pipe_power_well_disable(struct drm_i915_private *dev_priv,
 					struct i915_power_well *power_well)
 {
-	WARN_ON_ONCE(power_well->data != PIPE_A);
+	WARN_ON_ONCE(power_well->id != PIPE_A);
 
 	vlv_display_power_well_deinit(dev_priv);
 
@@ -1979,12 +1964,12 @@ static struct i915_power_well vlv_power_
 		.always_on = 1,
 		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
-		.data = PUNIT_POWER_WELL_ALWAYS_ON,
+		.id = PUNIT_POWER_WELL_ALWAYS_ON,
 	},
 	{
 		.name = "display",
 		.domains = VLV_DISPLAY_POWER_DOMAINS,
-		.data = PUNIT_POWER_WELL_DISP2D,
+		.id = PUNIT_POWER_WELL_DISP2D,
 		.ops = &vlv_display_power_well_ops,
 	},
 	{
@@ -1994,7 +1979,7 @@ static struct i915_power_well vlv_power_
 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
 		.ops = &vlv_dpio_power_well_ops,
-		.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
+		.id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
 	},
 	{
 		.name = "dpio-tx-b-23",
@@ -2003,7 +1988,7 @@ static struct i915_power_well vlv_power_
 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
 		.ops = &vlv_dpio_power_well_ops,
-		.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
+		.id = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
 	},
 	{
 		.name = "dpio-tx-c-01",
@@ -2012,7 +1997,7 @@ static struct i915_power_well vlv_power_
 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
 		.ops = &vlv_dpio_power_well_ops,
-		.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
+		.id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
 	},
 	{
 		.name = "dpio-tx-c-23",
@@ -2021,12 +2006,12 @@ static struct i915_power_well vlv_power_
 			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
 			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
 		.ops = &vlv_dpio_power_well_ops,
-		.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
+		.id = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
 	},
 	{
 		.name = "dpio-common",
 		.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
-		.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
+		.id = PUNIT_POWER_WELL_DPIO_CMN_BC,
 		.ops = &vlv_dpio_cmn_power_well_ops,
 	},
 };
@@ -2046,19 +2031,19 @@ static struct i915_power_well chv_power_
 		 * required for any pipe to work.
 		 */
 		.domains = CHV_DISPLAY_POWER_DOMAINS,
-		.data = PIPE_A,
+		.id = PIPE_A,
 		.ops = &chv_pipe_power_well_ops,
 	},
 	{
 		.name = "dpio-common-bc",
 		.domains = CHV_DPIO_CMN_BC_POWER_DOMAINS,
-		.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
+		.id = PUNIT_POWER_WELL_DPIO_CMN_BC,
 		.ops = &chv_dpio_cmn_power_well_ops,
 	},
 	{
 		.name = "dpio-common-d",
 		.domains = CHV_DPIO_CMN_D_POWER_DOMAINS,
-		.data = PUNIT_POWER_WELL_DPIO_CMN_D,
+		.id = PUNIT_POWER_WELL_DPIO_CMN_D,
 		.ops = &chv_dpio_cmn_power_well_ops,
 	},
 };
@@ -2081,57 +2066,57 @@ static struct i915_power_well skl_power_
 		.always_on = 1,
 		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
-		.data = SKL_DISP_PW_ALWAYS_ON,
+		.id = SKL_DISP_PW_ALWAYS_ON,
 	},
 	{
 		.name = "power well 1",
 		/* Handled by the DMC firmware */
 		.domains = 0,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_1,
+		.id = SKL_DISP_PW_1,
 	},
 	{
 		.name = "MISC IO power well",
 		/* Handled by the DMC firmware */
 		.domains = 0,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_MISC_IO,
+		.id = SKL_DISP_PW_MISC_IO,
 	},
 	{
 		.name = "DC off",
 		.domains = SKL_DISPLAY_DC_OFF_POWER_DOMAINS,
 		.ops = &gen9_dc_off_power_well_ops,
-		.data = SKL_DISP_PW_DC_OFF,
+		.id = SKL_DISP_PW_DC_OFF,
 	},
 	{
 		.name = "power well 2",
 		.domains = SKL_DISPLAY_POWERWELL_2_POWER_DOMAINS,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_2,
+		.id = SKL_DISP_PW_2,
 	},
 	{
 		.name = "DDI A/E power well",
 		.domains = SKL_DISPLAY_DDI_A_E_POWER_DOMAINS,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_DDI_A_E,
+		.id = SKL_DISP_PW_DDI_A_E,
 	},
 	{
 		.name = "DDI B power well",
 		.domains = SKL_DISPLAY_DDI_B_POWER_DOMAINS,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_DDI_B,
+		.id = SKL_DISP_PW_DDI_B,
 	},
 	{
 		.name = "DDI C power well",
 		.domains = SKL_DISPLAY_DDI_C_POWER_DOMAINS,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_DDI_C,
+		.id = SKL_DISP_PW_DDI_C,
 	},
 	{
 		.name = "DDI D power well",
 		.domains = SKL_DISPLAY_DDI_D_POWER_DOMAINS,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_DDI_D,
+		.id = SKL_DISP_PW_DDI_D,
 	},
 };
 
@@ -2146,31 +2131,33 @@ static struct i915_power_well bxt_power_
 		.name = "power well 1",
 		.domains = 0,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_1,
+		.id = SKL_DISP_PW_1,
 	},
 	{
 		.name = "DC off",
 		.domains = BXT_DISPLAY_DC_OFF_POWER_DOMAINS,
 		.ops = &gen9_dc_off_power_well_ops,
-		.data = SKL_DISP_PW_DC_OFF,
+		.id = SKL_DISP_PW_DC_OFF,
 	},
 	{
 		.name = "power well 2",
 		.domains = BXT_DISPLAY_POWERWELL_2_POWER_DOMAINS,
 		.ops = &skl_power_well_ops,
-		.data = SKL_DISP_PW_2,
+		.id = SKL_DISP_PW_2,
 	},
 	{
 		.name = "dpio-common-a",
 		.domains = BXT_DPIO_CMN_A_POWER_DOMAINS,
 		.ops = &bxt_dpio_cmn_power_well_ops,
-		.data = BXT_DPIO_CMN_A,
+		.id = BXT_DPIO_CMN_A,
+		.data = DPIO_PHY1,
 	},
 	{
 		.name = "dpio-common-bc",
 		.domains = BXT_DPIO_CMN_BC_POWER_DOMAINS,
 		.ops = &bxt_dpio_cmn_power_well_ops,
-		.data = BXT_DPIO_CMN_BC,
+		.id = BXT_DPIO_CMN_BC,
+		.data = DPIO_PHY0,
 	},
 };
 
@@ -2592,20 +2579,19 @@ static void vlv_cmnlane_wa(struct drm_i9
  */
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume)
 {
-	struct drm_device *dev = &dev_priv->drm;
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
 
 	power_domains->initializing = true;
 
-	if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
 		skl_display_core_init(dev_priv, resume);
-	} else if (IS_BROXTON(dev)) {
+	} else if (IS_BROXTON(dev_priv)) {
 		bxt_display_core_init(dev_priv, resume);
-	} else if (IS_CHERRYVIEW(dev)) {
+	} else if (IS_CHERRYVIEW(dev_priv)) {
 		mutex_lock(&power_domains->lock);
 		chv_phy_control_init(dev_priv);
 		mutex_unlock(&power_domains->lock);
-	} else if (IS_VALLEYVIEW(dev)) {
+	} else if (IS_VALLEYVIEW(dev_priv)) {
 		mutex_lock(&power_domains->lock);
 		vlv_cmnlane_wa(dev_priv);
 		mutex_unlock(&power_domains->lock);
@@ -2740,8 +2726,7 @@ void intel_runtime_pm_put(struct drm_i91
 	struct device *kdev = &pdev->dev;
 
 	assert_rpm_wakelock_held(dev_priv);
-	if (atomic_dec_and_test(&dev_priv->pm.wakeref_count))
-		atomic_inc(&dev_priv->pm.atomic_seq);
+	atomic_dec(&dev_priv->pm.wakeref_count);
 
 	pm_runtime_mark_last_busy(kdev);
 	pm_runtime_put_autosuspend(kdev);
@@ -2760,7 +2745,6 @@ void intel_runtime_pm_put(struct drm_i91
 void intel_runtime_pm_enable(struct drm_i915_private *dev_priv)
 {
 	struct pci_dev *pdev = dev_priv->drm.pdev;
-	struct drm_device *dev = &dev_priv->drm;
 	struct device *kdev = &pdev->dev;
 
 	pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */
@@ -2772,7 +2756,7 @@ void intel_runtime_pm_enable(struct drm_
 	 * so the driver's own RPM reference tracking asserts also work on
 	 * platforms without RPM support.
 	 */
-	if (!HAS_RUNTIME_PM(dev)) {
+	if (!HAS_RUNTIME_PM(dev_priv)) {
 		pm_runtime_dont_use_autosuspend(kdev);
 		pm_runtime_get_sync(kdev);
 	} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2017-02-12 16:03:20.000000000 -0500
@@ -251,7 +251,7 @@ static void intel_sdvo_write_sdvox(struc
 		 * HW workaround, need to write this twice for issue
 		 * that may result in first write getting masked.
 		 */
-		if (HAS_PCH_IBX(dev)) {
+		if (HAS_PCH_IBX(dev_priv)) {
 			I915_WRITE(intel_sdvo->sdvo_reg, val);
 			POSTING_READ(intel_sdvo->sdvo_reg);
 		}
@@ -307,7 +307,7 @@ static bool intel_sdvo_read_byte(struct
 static const struct _sdvo_cmd_name {
 	u8 cmd;
 	const char *name;
-} sdvo_cmd_names[] = {
+} __attribute__ ((packed)) 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),
@@ -1133,7 +1133,7 @@ static bool intel_sdvo_compute_config(st
 	DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n");
 	pipe_config->pipe_bpp = 8*3;
 
-	if (HAS_PCH_SPLIT(encoder->base.dev))
+	if (HAS_PCH_SPLIT(to_i915(encoder->base.dev)))
 		pipe_config->has_pch_encoder = true;
 
 	/* We need to construct preferred input timings based on our
@@ -1195,8 +1195,7 @@ static void intel_sdvo_pre_enable(struct
 				  struct intel_crtc_state *crtc_state,
 				  struct drm_connector_state *conn_state)
 {
-	struct drm_device *dev = intel_encoder->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
 	const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode;
 	struct drm_display_mode *mode = &crtc_state->base.mode;
@@ -1269,13 +1268,13 @@ static void intel_sdvo_pre_enable(struct
 		return;
 
 	/* Set the SDVO control regs. */
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		/* The real mode polarity is set by the SDVO commands, using
 		 * struct intel_sdvo_dtd. */
 		sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
-		if (!HAS_PCH_SPLIT(dev) && crtc_state->limited_color_range)
+		if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range)
 			sdvox |= HDMI_COLOR_RANGE_16_235;
-		if (INTEL_INFO(dev)->gen < 5)
+		if (INTEL_GEN(dev_priv) < 5)
 			sdvox |= SDVO_BORDER_ENABLE;
 	} else {
 		sdvox = I915_READ(intel_sdvo->sdvo_reg);
@@ -1286,7 +1285,7 @@ static void intel_sdvo_pre_enable(struct
 		sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
 	}
 
-	if (INTEL_PCH_TYPE(dev) >= PCH_CPT)
+	if (INTEL_PCH_TYPE(dev_priv) >= PCH_CPT)
 		sdvox |= SDVO_PIPE_SEL_CPT(crtc->pipe);
 	else
 		sdvox |= SDVO_PIPE_SEL(crtc->pipe);
@@ -1294,9 +1293,10 @@ static void intel_sdvo_pre_enable(struct
 	if (intel_sdvo->has_hdmi_audio)
 		sdvox |= SDVO_AUDIO_ENABLE;
 
-	if (INTEL_INFO(dev)->gen >= 4) {
+	if (INTEL_GEN(dev_priv) >= 4) {
 		/* done in crtc_mode_set as the dpll_md reg must be written early */
-	} else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) {
+	} else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) ||
+		   IS_G33(dev_priv)) {
 		/* done in crtc_mode_set as it lives inside the dpll register */
 	} else {
 		sdvox |= (crtc_state->pixel_multiplier - 1)
@@ -1304,7 +1304,7 @@ static void intel_sdvo_pre_enable(struct
 	}
 
 	if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL &&
-	    INTEL_INFO(dev)->gen < 5)
+	    INTEL_GEN(dev_priv) < 5)
 		sdvox |= SDVO_STALL_SELECT;
 	intel_sdvo_write_sdvox(intel_sdvo, sdvox);
 }
@@ -1339,7 +1339,7 @@ static bool intel_sdvo_get_hw_state(stru
 	if (!(tmp & SDVO_ENABLE) && (active_outputs == 0))
 		return false;
 
-	if (HAS_PCH_CPT(dev))
+	if (HAS_PCH_CPT(dev_priv))
 		*pipe = PORT_TO_PIPE_CPT(tmp);
 	else
 		*pipe = PORT_TO_PIPE(tmp);
@@ -1389,7 +1389,7 @@ static void intel_sdvo_get_config(struct
 	 * encoder->get_config we so already have a valid pixel multplier on all
 	 * other platfroms.
 	 */
-	if (IS_I915G(dev) || IS_I915GM(dev)) {
+	if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) {
 		pipe_config->pixel_multiplier =
 			((sdvox & SDVO_PORT_MULTIPLY_MASK)
 			 >> SDVO_PORT_MULTIPLY_SHIFT) + 1;
@@ -1471,7 +1471,7 @@ static void intel_disable_sdvo(struct in
 		temp &= ~SDVO_ENABLE;
 		intel_sdvo_write_sdvox(intel_sdvo, temp);
 
-		intel_wait_for_vblank_if_active(&dev_priv->drm, PIPE_A);
+		intel_wait_for_vblank_if_active(dev_priv, PIPE_A);
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 	}
@@ -1508,7 +1508,7 @@ static void intel_enable_sdvo(struct int
 	intel_sdvo_write_sdvox(intel_sdvo, temp);
 
 	for (i = 0; i < 2; i++)
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
+		intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
 
 	success = intel_sdvo_get_trained_inputs(intel_sdvo, &input1, &input2);
 	/* Warn if the device reported failure to sync.
@@ -1595,15 +1595,15 @@ static bool intel_sdvo_get_capabilities(
 
 static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo)
 {
-	struct drm_device *dev = intel_sdvo->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev);
 	uint16_t hotplug;
 
-	if (!I915_HAS_HOTPLUG(dev))
+	if (!I915_HAS_HOTPLUG(dev_priv))
 		return 0;
 
 	/* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise
 	 * on the line. */
-	if (IS_I945G(dev) || IS_I945GM(dev))
+	if (IS_I945G(dev_priv) || IS_I945GM(dev_priv))
 		return 0;
 
 	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
@@ -2410,10 +2410,10 @@ static void
 intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
 			       struct intel_sdvo_connector *connector)
 {
-	struct drm_device *dev = connector->base.base.dev;
+	struct drm_i915_private *dev_priv = to_i915(connector->base.base.dev);
 
 	intel_attach_force_audio_property(&connector->base.base);
-	if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev)) {
+	if (INTEL_GEN(dev_priv) >= 4 && IS_MOBILE(dev_priv)) {
 		intel_attach_broadcast_rgb_property(&connector->base.base);
 		intel_sdvo->color_range_auto = true;
 	}
@@ -2981,6 +2981,7 @@ bool intel_sdvo_init(struct drm_device *
 	/* encoder type will be decided later */
 	intel_encoder = &intel_sdvo->base;
 	intel_encoder->type = INTEL_OUTPUT_SDVO;
+	intel_encoder->port = port;
 	drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0,
 			 "SDVO %c", port_name(port));
 
@@ -2996,7 +2997,7 @@ bool intel_sdvo_init(struct drm_device *
 	}
 
 	intel_encoder->compute_config = intel_sdvo_compute_config;
-	if (HAS_PCH_SPLIT(dev)) {
+	if (HAS_PCH_SPLIT(dev_priv)) {
 		intel_encoder->disable = pch_disable_sdvo;
 		intel_encoder->post_disable = pch_post_disable_sdvo;
 	} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_sprite.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_sprite.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_sprite.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_sprite.c	2017-02-12 16:03:20.000000000 -0500
@@ -203,9 +203,6 @@ skl_update_plane(struct drm_plane *drm_p
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_plane *intel_plane = to_intel_plane(drm_plane);
 	struct drm_framebuffer *fb = plane_state->base.fb;
-	const struct skl_wm_values *wm = &dev_priv->wm.skl_results;
-	struct drm_crtc *crtc = crtc_state->base.crtc;
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	const int pipe = intel_plane->pipe;
 	const int plane = intel_plane->plane + 1;
 	u32 plane_ctl;
@@ -227,13 +224,10 @@ skl_update_plane(struct drm_plane *drm_p
 		PLANE_CTL_PIPE_CSC_ENABLE;
 
 	plane_ctl |= skl_plane_ctl_format(fb->pixel_format);
-	plane_ctl |= skl_plane_ctl_tiling(fb->modifier[0]);
+	plane_ctl |= skl_plane_ctl_tiling(fb->modifier);
 
 	plane_ctl |= skl_plane_ctl_rotation(rotation);
 
-	if (wm->dirty_pipes & drm_crtc_mask(crtc))
-		skl_write_plane_wm(intel_crtc, wm, plane);
-
 	if (key->flags) {
 		I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
 		I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
@@ -279,7 +273,7 @@ skl_update_plane(struct drm_plane *drm_p
 
 	I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
 	I915_WRITE(PLANE_SURF(pipe, plane),
-		   intel_fb_gtt_offset(fb, rotation) + surf_addr);
+		   intel_plane_ggtt_offset(plane_state) + surf_addr);
 	POSTING_READ(PLANE_SURF(pipe, plane));
 }
 
@@ -292,14 +286,6 @@ skl_disable_plane(struct drm_plane *dpla
 	const int pipe = intel_plane->pipe;
 	const int plane = intel_plane->plane + 1;
 
-	/*
-	 * We only populate skl_results on watermark updates, and if the
-	 * plane's visiblity isn't actually changing neither is its watermarks.
-	 */
-	if (!dplane->state->visible)
-		skl_write_plane_wm(to_intel_crtc(crtc),
-				   &dev_priv->wm.skl_results, plane);
-
 	I915_WRITE(PLANE_CTL(pipe, plane), 0);
 
 	I915_WRITE(PLANE_SURF(pipe, plane), 0);
@@ -420,9 +406,15 @@ vlv_update_plane(struct drm_plane *dplan
 	 */
 	sprctl |= SP_GAMMA_ENABLE;
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		sprctl |= SP_TILED;
 
+	if (rotation & DRM_ROTATE_180)
+		sprctl |= SP_ROTATE_180;
+
+	if (rotation & DRM_REFLECT_X)
+		sprctl |= SP_MIRROR;
+
 	/* Sizes are 0 based */
 	src_w--;
 	src_h--;
@@ -432,11 +424,11 @@ vlv_update_plane(struct drm_plane *dplan
 	intel_add_fb_offsets(&x, &y, plane_state, 0);
 	sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
 
-	if (rotation == DRM_ROTATE_180) {
-		sprctl |= SP_ROTATE_180;
-
+	if (rotation & DRM_ROTATE_180) {
 		x += src_w;
 		y += src_h;
+	} else if (rotation & DRM_REFLECT_X) {
+		x += src_w;
 	}
 
 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
@@ -450,13 +442,13 @@ vlv_update_plane(struct drm_plane *dplan
 	if (key->flags & I915_SET_COLORKEY_SOURCE)
 		sprctl |= SP_SOURCE_KEY;
 
-	if (IS_CHERRYVIEW(dev) && pipe == PIPE_B)
+	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B)
 		chv_update_csc(intel_plane, fb->pixel_format);
 
 	I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
 	I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		I915_WRITE(SPTILEOFF(pipe, plane), (y << 16) | x);
 	else
 		I915_WRITE(SPLINOFF(pipe, plane), linear_offset);
@@ -466,7 +458,7 @@ vlv_update_plane(struct drm_plane *dplan
 	I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
 	I915_WRITE(SPCNTR(pipe, plane), sprctl);
 	I915_WRITE(SPSURF(pipe, plane),
-		   intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
+		   intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 	POSTING_READ(SPSURF(pipe, plane));
 }
 
@@ -539,15 +531,18 @@ ivb_update_plane(struct drm_plane *plane
 	 */
 	sprctl |= SPRITE_GAMMA_ENABLE;
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		sprctl |= SPRITE_TILED;
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (rotation & DRM_ROTATE_180)
+		sprctl |= SPRITE_ROTATE_180;
+
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
 	else
 		sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
 
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
 	/* Sizes are 0 based */
@@ -562,14 +557,11 @@ ivb_update_plane(struct drm_plane *plane
 	intel_add_fb_offsets(&x, &y, plane_state, 0);
 	sprsurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
 
-	if (rotation == DRM_ROTATE_180) {
-		sprctl |= SPRITE_ROTATE_180;
-
-		/* HSW and BDW does this automagically in hardware */
-		if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
-			x += src_w;
-			y += src_h;
-		}
+	/* HSW+ does this automagically in hardware */
+	if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv) &&
+	    rotation & DRM_ROTATE_180) {
+		x += src_w;
+		y += src_h;
 	}
 
 	linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
@@ -590,9 +582,9 @@ ivb_update_plane(struct drm_plane *plane
 
 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
 	 * register */
-	if (IS_HASWELL(dev) || IS_BROADWELL(dev))
+	if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
 		I915_WRITE(SPROFFSET(pipe), (y << 16) | x);
-	else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	else if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x);
 	else
 		I915_WRITE(SPRLINOFF(pipe), linear_offset);
@@ -602,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane
 		I915_WRITE(SPRSCALE(pipe), sprscale);
 	I915_WRITE(SPRCTL(pipe), sprctl);
 	I915_WRITE(SPRSURF(pipe),
-		   intel_fb_gtt_offset(fb, rotation) + sprsurf_offset);
+		   intel_plane_ggtt_offset(plane_state) + sprsurf_offset);
 	POSTING_READ(SPRSURF(pipe));
 }
 
@@ -677,10 +669,13 @@ ilk_update_plane(struct drm_plane *plane
 	 */
 	dvscntr |= DVS_GAMMA_ENABLE;
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		dvscntr |= DVS_TILED;
 
-	if (IS_GEN6(dev))
+	if (rotation & DRM_ROTATE_180)
+		dvscntr |= DVS_ROTATE_180;
+
+	if (IS_GEN6(dev_priv))
 		dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
 
 	/* Sizes are 0 based */
@@ -696,9 +691,7 @@ ilk_update_plane(struct drm_plane *plane
 	intel_add_fb_offsets(&x, &y, plane_state, 0);
 	dvssurf_offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
 
-	if (rotation == DRM_ROTATE_180) {
-		dvscntr |= DVS_ROTATE_180;
-
+	if (rotation & DRM_ROTATE_180) {
 		x += src_w;
 		y += src_h;
 	}
@@ -719,7 +712,7 @@ ilk_update_plane(struct drm_plane *plane
 	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
 	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
 
-	if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
+	if (fb->modifier == I915_FORMAT_MOD_X_TILED)
 		I915_WRITE(DVSTILEOFF(pipe), (y << 16) | x);
 	else
 		I915_WRITE(DVSLINOFF(pipe), linear_offset);
@@ -728,7 +721,7 @@ ilk_update_plane(struct drm_plane *plane
 	I915_WRITE(DVSSCALE(pipe), dvsscale);
 	I915_WRITE(DVSCNTR(pipe), dvscntr);
 	I915_WRITE(DVSSURF(pipe),
-		   intel_fb_gtt_offset(fb, rotation) + dvssurf_offset);
+		   intel_plane_ggtt_offset(plane_state) + dvssurf_offset);
 	POSTING_READ(DVSSURF(pipe));
 }
 
@@ -753,7 +746,7 @@ intel_check_sprite_plane(struct drm_plan
 			 struct intel_crtc_state *crtc_state,
 			 struct intel_plane_state *state)
 {
-	struct drm_device *dev = plane->dev;
+	struct drm_i915_private *dev_priv = to_i915(plane->dev);
 	struct drm_crtc *crtc = state->base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_plane *intel_plane = to_intel_plane(plane);
@@ -769,15 +762,8 @@ intel_check_sprite_plane(struct drm_plan
 	bool can_scale;
 	int ret;
 
-	src->x1 = state->base.src_x;
-	src->y1 = state->base.src_y;
-	src->x2 = state->base.src_x + state->base.src_w;
-	src->y2 = state->base.src_y + state->base.src_h;
-
-	dst->x1 = state->base.crtc_x;
-	dst->y1 = state->base.crtc_y;
-	dst->x2 = state->base.crtc_x + state->base.crtc_w;
-	dst->y2 = state->base.crtc_y + state->base.crtc_h;
+	*src = drm_plane_state_src(&state->base);
+	*dst = drm_plane_state_dest(&state->base);
 
 	if (!fb) {
 		state->base.visible = false;
@@ -797,7 +783,7 @@ intel_check_sprite_plane(struct drm_plan
 	}
 
 	/* setup can_scale, min_scale, max_scale */
-	if (INTEL_INFO(dev)->gen >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		/* use scaler when colorkey is not required */
 		if (state->ckey.flags == I915_SET_COLORKEY_NONE) {
 			can_scale = 1;
@@ -913,7 +899,7 @@ intel_check_sprite_plane(struct drm_plan
 
 		width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
 
-		if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 ||
+		if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
 		    width_bytes > 4096 || fb->pitches[0] > 4096)) {
 			DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
 			return -EINVAL;
@@ -932,7 +918,7 @@ intel_check_sprite_plane(struct drm_plan
 	dst->y1 = crtc_y;
 	dst->y2 = crtc_y + crtc_h;
 
-	if (INTEL_GEN(dev) >= 9) {
+	if (INTEL_GEN(dev_priv) >= 9) {
 		ret = skl_check_plane_surface(state);
 		if (ret)
 			return ret;
@@ -944,6 +930,7 @@ intel_check_sprite_plane(struct drm_plan
 int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_intel_sprite_colorkey *set = data;
 	struct drm_plane *plane;
 	struct drm_plane_state *plane_state;
@@ -955,7 +942,7 @@ int intel_sprite_set_colorkey(struct drm
 	if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE))
 		return -EINVAL;
 
-	if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) &&
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
 	    set->flags & I915_SET_COLORKEY_DESTINATION)
 		return -EINVAL;
 
@@ -987,9 +974,7 @@ int intel_sprite_set_colorkey(struct drm
 		drm_modeset_backoff(&ctx);
 	}
 
-	if (ret)
-		drm_atomic_state_free(state);
-
+	drm_atomic_state_put(state);
 out:
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
@@ -1039,19 +1024,18 @@ static uint32_t skl_plane_formats[] = {
 	DRM_FORMAT_VYUY,
 };
 
-int
-intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
+struct intel_plane *
+intel_sprite_plane_create(struct drm_i915_private *dev_priv,
+			  enum pipe pipe, int plane)
 {
 	struct intel_plane *intel_plane = NULL;
 	struct intel_plane_state *state = NULL;
 	unsigned long possible_crtcs;
 	const uint32_t *plane_formats;
+	unsigned int supported_rotations;
 	int num_plane_formats;
 	int ret;
 
-	if (INTEL_INFO(dev)->gen < 5)
-		return -ENODEV;
-
 	intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
 	if (!intel_plane) {
 		ret = -ENOMEM;
@@ -1065,26 +1049,26 @@ intel_plane_init(struct drm_device *dev,
 	}
 	intel_plane->base.state = &state->base;
 
-	switch (INTEL_INFO(dev)->gen) {
-	case 5:
-	case 6:
+	if (INTEL_GEN(dev_priv) >= 9) {
 		intel_plane->can_scale = true;
-		intel_plane->max_downscale = 16;
-		intel_plane->update_plane = ilk_update_plane;
-		intel_plane->disable_plane = ilk_disable_plane;
+		state->scaler_id = -1;
 
-		if (IS_GEN6(dev)) {
-			plane_formats = snb_plane_formats;
-			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
-		} else {
-			plane_formats = ilk_plane_formats;
-			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
-		}
-		break;
+		intel_plane->update_plane = skl_update_plane;
+		intel_plane->disable_plane = skl_disable_plane;
 
-	case 7:
-	case 8:
-		if (IS_IVYBRIDGE(dev)) {
+		plane_formats = skl_plane_formats;
+		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
+	} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		intel_plane->can_scale = false;
+		intel_plane->max_downscale = 1;
+
+		intel_plane->update_plane = vlv_update_plane;
+		intel_plane->disable_plane = vlv_disable_plane;
+
+		plane_formats = vlv_plane_formats;
+		num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
+	} else if (INTEL_GEN(dev_priv) >= 7) {
+		if (IS_IVYBRIDGE(dev_priv)) {
 			intel_plane->can_scale = true;
 			intel_plane->max_downscale = 2;
 		} else {
@@ -1092,33 +1076,38 @@ intel_plane_init(struct drm_device *dev,
 			intel_plane->max_downscale = 1;
 		}
 
-		if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
-			intel_plane->update_plane = vlv_update_plane;
-			intel_plane->disable_plane = vlv_disable_plane;
+		intel_plane->update_plane = ivb_update_plane;
+		intel_plane->disable_plane = ivb_disable_plane;
 
-			plane_formats = vlv_plane_formats;
-			num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
-		} else {
-			intel_plane->update_plane = ivb_update_plane;
-			intel_plane->disable_plane = ivb_disable_plane;
+		plane_formats = snb_plane_formats;
+		num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+	} else {
+		intel_plane->can_scale = true;
+		intel_plane->max_downscale = 16;
 
+		intel_plane->update_plane = ilk_update_plane;
+		intel_plane->disable_plane = ilk_disable_plane;
+
+		if (IS_GEN6(dev_priv)) {
 			plane_formats = snb_plane_formats;
 			num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+		} else {
+			plane_formats = ilk_plane_formats;
+			num_plane_formats = ARRAY_SIZE(ilk_plane_formats);
 		}
-		break;
-	case 9:
-		intel_plane->can_scale = true;
-		intel_plane->update_plane = skl_update_plane;
-		intel_plane->disable_plane = skl_disable_plane;
-		state->scaler_id = -1;
+	}
 
-		plane_formats = skl_plane_formats;
-		num_plane_formats = ARRAY_SIZE(skl_plane_formats);
-		break;
-	default:
-		MISSING_CASE(INTEL_INFO(dev)->gen);
-		ret = -ENODEV;
-		goto fail;
+	if (INTEL_GEN(dev_priv) >= 9) {
+		supported_rotations =
+			DRM_ROTATE_0 | DRM_ROTATE_90 |
+			DRM_ROTATE_180 | DRM_ROTATE_270;
+	} else if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) {
+		supported_rotations =
+			DRM_ROTATE_0 | DRM_ROTATE_180 |
+			DRM_REFLECT_X;
+	} else {
+		supported_rotations =
+			DRM_ROTATE_0 | DRM_ROTATE_180;
 	}
 
 	intel_plane->pipe = pipe;
@@ -1128,30 +1117,32 @@ intel_plane_init(struct drm_device *dev,
 
 	possible_crtcs = (1 << pipe);
 
-	if (INTEL_INFO(dev)->gen >= 9)
-		ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
-					       &intel_plane_funcs,
+	if (INTEL_GEN(dev_priv) >= 9)
+		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
+					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
 					       DRM_PLANE_TYPE_OVERLAY,
 					       "plane %d%c", plane + 2, pipe_name(pipe));
 	else
-		ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
-					       &intel_plane_funcs,
+		ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
+					       possible_crtcs, &intel_plane_funcs,
 					       plane_formats, num_plane_formats,
 					       DRM_PLANE_TYPE_OVERLAY,
 					       "sprite %c", sprite_name(pipe, plane));
 	if (ret)
 		goto fail;
 
-	intel_create_rotation_property(dev, intel_plane);
+	drm_plane_create_rotation_property(&intel_plane->base,
+					   DRM_ROTATE_0,
+					   supported_rotations);
 
 	drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
 
-	return 0;
+	return intel_plane;
 
 fail:
 	kfree(state);
 	kfree(intel_plane);
 
-	return ret;
+	return ERR_PTR(ret);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_tv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_tv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_tv.c	2017-02-12 16:03:20.000000000 -0500
@@ -86,7 +86,8 @@ struct intel_tv {
 };
 
 struct video_levels {
-	int blank, black, burst;
+	u16 blank, black;
+	u8 burst;
 };
 
 struct color_conversion {
@@ -339,34 +340,43 @@ static const struct video_levels compone
 
 struct tv_mode {
 	const char *name;
-	int clock;
-	int refresh; /* in millihertz (for precision) */
+
+	u32 clock;
+	u16 refresh; /* in millihertz (for precision) */
 	u32 oversample;
-	int hsync_end, hblank_start, hblank_end, htotal;
-	bool progressive, trilevel_sync, component_only;
-	int vsync_start_f1, vsync_start_f2, vsync_len;
-	bool veq_ena;
-	int veq_start_f1, veq_start_f2, veq_len;
-	int vi_end_f1, vi_end_f2, nbr_end;
-	bool burst_ena;
-	int hburst_start, hburst_len;
-	int vburst_start_f1, vburst_end_f1;
-	int vburst_start_f2, vburst_end_f2;
-	int vburst_start_f3, vburst_end_f3;
-	int vburst_start_f4, vburst_end_f4;
+	u8 hsync_end;
+	u16 hblank_start, hblank_end, htotal;
+	bool progressive : 1, trilevel_sync : 1, component_only : 1;
+	u8 vsync_start_f1, vsync_start_f2, vsync_len;
+	bool veq_ena : 1;
+	u8 veq_start_f1, veq_start_f2, veq_len;
+	u8 vi_end_f1, vi_end_f2;
+	u16 nbr_end;
+	bool burst_ena : 1;
+	u8 hburst_start, hburst_len;
+	u8 vburst_start_f1;
+	u16 vburst_end_f1;
+	u8 vburst_start_f2;
+	u16 vburst_end_f2;
+	u8 vburst_start_f3;
+	u16 vburst_end_f3;
+	u8 vburst_start_f4;
+	u16 vburst_end_f4;
 	/*
 	 * subcarrier programming
 	 */
-	int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc;
+	u16 dda2_size, dda3_size;
+	u8 dda1_inc;
+	u16 dda2_inc, dda3_inc;
 	u32 sc_reset;
-	bool pal_burst;
+	bool pal_burst : 1;
 	/*
 	 * blank/black levels
 	 */
 	const struct video_levels *composite_levels, *svideo_levels;
 	const struct color_conversion *composite_color, *svideo_color;
 	const u32 *filter_table;
-	int max_srcw;
+	u16 max_srcw;
 };
 
 
@@ -846,7 +856,7 @@ intel_enable_tv(struct intel_encoder *en
 	struct drm_i915_private *dev_priv = to_i915(dev);
 
 	/* Prevents vblank waits from timing out in intel_tv_detect_type() */
-	intel_wait_for_vblank(encoder->base.dev,
+	intel_wait_for_vblank(dev_priv,
 			      to_intel_crtc(encoder->base.crtc)->pipe);
 
 	I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
@@ -1019,8 +1029,7 @@ static void intel_tv_pre_enable(struct i
 				struct intel_crtc_state *pipe_config,
 				struct drm_connector_state *conn_state)
 {
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	struct intel_tv *intel_tv = enc_to_tv(encoder);
 	const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
@@ -1095,7 +1104,7 @@ static void intel_tv_pre_enable(struct i
 		tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT;
 
 	/* Enable two fixes for the chips that need them. */
-	if (IS_I915GM(dev))
+	if (IS_I915GM(dev_priv))
 		tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX;
 
 	set_tv_mode_timings(dev_priv, tv_mode, burst_ena);
@@ -1106,7 +1115,7 @@ static void intel_tv_pre_enable(struct i
 
 	set_color_conversion(dev_priv, color_conversion);
 
-	if (INTEL_INFO(dev)->gen >= 4)
+	if (INTEL_GEN(dev_priv) >= 4)
 		I915_WRITE(TV_CLR_KNOBS, 0x00404000);
 	else
 		I915_WRITE(TV_CLR_KNOBS, 0x00606000);
@@ -1220,7 +1229,7 @@ intel_tv_detect_type(struct intel_tv *in
 	 * The TV sense state should be cleared to zero on cantiga platform. Otherwise
 	 * the TV is misdetected. This is hardware requirement.
 	 */
-	if (IS_GM45(dev))
+	if (IS_GM45(dev_priv))
 		tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL |
 			    TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL);
 
@@ -1228,7 +1237,7 @@ intel_tv_detect_type(struct intel_tv *in
 	I915_WRITE(TV_DAC, tv_dac);
 	POSTING_READ(TV_DAC);
 
-	intel_wait_for_vblank(dev, intel_crtc->pipe);
+	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
 
 	type = -1;
 	tv_dac = I915_READ(TV_DAC);
@@ -1258,7 +1267,7 @@ intel_tv_detect_type(struct intel_tv *in
 	POSTING_READ(TV_CTL);
 
 	/* For unknown reasons the hw barfs if we don't do this vblank wait. */
-	intel_wait_for_vblank(dev, intel_crtc->pipe);
+	intel_wait_for_vblank(dev_priv, intel_crtc->pipe);
 
 	/* Restore interrupt config */
 	if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
@@ -1610,7 +1619,9 @@ intel_tv_init(struct drm_device *dev)
 	intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	intel_connector_attach_encoder(intel_connector, intel_encoder);
+
 	intel_encoder->type = INTEL_OUTPUT_TVOUT;
+	intel_encoder->port = PORT_NONE;
 	intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
 	intel_encoder->cloneable = 0;
 	intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1));
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_uncore.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_uncore.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/intel_uncore.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/intel_uncore.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,7 @@ fw_domain_arm_timer(struct intel_uncore_
 {
 	d->wake_count++;
 	hrtimer_start_range_ns(&d->timer,
-			       ktime_set(0, NSEC_PER_MSEC),
+			       NSEC_PER_MSEC,
 			       NSEC_PER_MSEC,
 			       HRTIMER_MODE_REL);
 }
@@ -231,19 +231,21 @@ intel_uncore_fw_release_timer(struct hrt
 {
 	struct intel_uncore_forcewake_domain *domain =
 	       container_of(timer, struct intel_uncore_forcewake_domain, timer);
+	struct drm_i915_private *dev_priv = domain->i915;
 	unsigned long irqflags;
 
-	assert_rpm_device_not_suspended(domain->i915);
+	assert_rpm_device_not_suspended(dev_priv);
 
-	spin_lock_irqsave(&domain->i915->uncore.lock, irqflags);
+	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 	if (WARN_ON(domain->wake_count == 0))
 		domain->wake_count++;
 
-	if (--domain->wake_count == 0)
-		domain->i915->uncore.funcs.force_wake_put(domain->i915,
-							  1 << domain->id);
+	if (--domain->wake_count == 0) {
+		dev_priv->uncore.funcs.force_wake_put(dev_priv, domain->mask);
+		dev_priv->uncore.fw_domains_active &= ~domain->mask;
+	}
 
-	spin_unlock_irqrestore(&domain->i915->uncore.lock, irqflags);
+	spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
 	return HRTIMER_NORESTART;
 }
@@ -254,7 +256,7 @@ void intel_uncore_forcewake_reset(struct
 	unsigned long irqflags;
 	struct intel_uncore_forcewake_domain *domain;
 	int retry_count = 100;
-	enum forcewake_domains fw = 0, active_domains;
+	enum forcewake_domains fw, active_domains;
 
 	/* Hold uncore.lock across reset to prevent any register access
 	 * with forcewake not set correctly. Wait until all pending
@@ -291,10 +293,7 @@ void intel_uncore_forcewake_reset(struct
 
 	WARN_ON(active_domains);
 
-	for_each_fw_domain(domain, dev_priv)
-		if (domain->wake_count)
-			fw |= domain->mask;
-
+	fw = dev_priv->uncore.fw_domains_active;
 	if (fw)
 		dev_priv->uncore.funcs.force_wake_put(dev_priv, fw);
 
@@ -403,6 +402,8 @@ check_for_unclaimed_mmio(struct drm_i915
 static void __intel_uncore_early_sanitize(struct drm_i915_private *dev_priv,
 					  bool restore_forcewake)
 {
+	struct intel_device_info *info = mkwrite_device_info(dev_priv);
+
 	/* clear out unclaimed reg detection bit */
 	if (check_for_unclaimed_mmio(dev_priv))
 		DRM_DEBUG("unclaimed mmio detected on uncore init, clearing\n");
@@ -420,6 +421,10 @@ static void __intel_uncore_early_sanitiz
 				   GT_FIFO_CTL_RC6_POLICY_STALL);
 	}
 
+	/* Enable Decoupled MMIO only on BXT C stepping onwards */
+	if (!IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER))
+		info->has_decoupled_mmio = false;
+
 	intel_uncore_forcewake_reset(dev_priv, restore_forcewake);
 }
 
@@ -443,9 +448,6 @@ static void __intel_uncore_forcewake_get
 {
 	struct intel_uncore_forcewake_domain *domain;
 
-	if (!dev_priv->uncore.funcs.force_wake_get)
-		return;
-
 	fw_domains &= dev_priv->uncore.fw_domains;
 
 	for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
@@ -453,8 +455,10 @@ static void __intel_uncore_forcewake_get
 			fw_domains &= ~domain->mask;
 	}
 
-	if (fw_domains)
+	if (fw_domains) {
 		dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
+		dev_priv->uncore.fw_domains_active |= fw_domains;
+	}
 }
 
 /**
@@ -509,9 +513,6 @@ static void __intel_uncore_forcewake_put
 {
 	struct intel_uncore_forcewake_domain *domain;
 
-	if (!dev_priv->uncore.funcs.force_wake_put)
-		return;
-
 	fw_domains &= dev_priv->uncore.fw_domains;
 
 	for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
@@ -567,13 +568,10 @@ void intel_uncore_forcewake_put__locked(
 
 void assert_forcewakes_inactive(struct drm_i915_private *dev_priv)
 {
-	struct intel_uncore_forcewake_domain *domain;
-
 	if (!dev_priv->uncore.funcs.force_wake_get)
 		return;
 
-	for_each_fw_domain(domain, dev_priv)
-		WARN_ON(domain->wake_count);
+	WARN_ON(dev_priv->uncore.fw_domains_active);
 }
 
 /* We give fast paths for the really cool registers */
@@ -589,198 +587,224 @@ void assert_forcewakes_inactive(struct d
 	__fwd; \
 })
 
-#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
+static int fw_range_cmp(u32 offset, const struct intel_forcewake_range *entry)
+{
+	if (offset < entry->start)
+		return -1;
+	else if (offset > entry->end)
+		return 1;
+	else
+		return 0;
+}
 
-#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
-	(REG_RANGE((reg), 0x2000, 0x4000) || \
-	 REG_RANGE((reg), 0x5000, 0x8000) || \
-	 REG_RANGE((reg), 0xB000, 0x12000) || \
-	 REG_RANGE((reg), 0x2E000, 0x30000))
+/* Copied and "macroized" from lib/bsearch.c */
+#define BSEARCH(key, base, num, cmp) ({                                 \
+	unsigned int start__ = 0, end__ = (num);                        \
+	typeof(base) result__ = NULL;                                   \
+	while (start__ < end__) {                                       \
+		unsigned int mid__ = start__ + (end__ - start__) / 2;   \
+		int ret__ = (cmp)((key), (base) + mid__);               \
+		if (ret__ < 0) {                                        \
+			end__ = mid__;                                  \
+		} else if (ret__ > 0) {                                 \
+			start__ = mid__ + 1;                            \
+		} else {                                                \
+			result__ = (base) + mid__;                      \
+			break;                                          \
+		}                                                       \
+	}                                                               \
+	result__;                                                       \
+})
 
-#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \
-	(REG_RANGE((reg), 0x12000, 0x14000) || \
-	 REG_RANGE((reg), 0x22000, 0x24000) || \
-	 REG_RANGE((reg), 0x30000, 0x40000))
+static enum forcewake_domains
+find_fw_domain(struct drm_i915_private *dev_priv, u32 offset)
+{
+	const struct intel_forcewake_range *entry;
 
-#define __vlv_reg_read_fw_domains(offset) \
-({ \
-	enum forcewake_domains __fwd = 0; \
-	if (!NEEDS_FORCE_WAKE(offset)) \
-		__fwd = 0; \
-	else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_MEDIA; \
-	__fwd; \
-})
+	entry = BSEARCH(offset,
+			dev_priv->uncore.fw_domains_table,
+			dev_priv->uncore.fw_domains_table_entries,
+			fw_range_cmp);
 
-static const i915_reg_t gen8_shadowed_regs[] = {
-	GEN6_RPNSWREQ,
-	GEN6_RC_VIDEO_FREQ,
-	RING_TAIL(RENDER_RING_BASE),
-	RING_TAIL(GEN6_BSD_RING_BASE),
-	RING_TAIL(VEBOX_RING_BASE),
-	RING_TAIL(BLT_RING_BASE),
-	/* TODO: Other registers are not yet used */
-};
+	return entry ? entry->domains : 0;
+}
 
-static bool is_gen8_shadowed(u32 offset)
+static void
+intel_fw_table_check(struct drm_i915_private *dev_priv)
 {
-	int i;
-	for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++)
-		if (offset == gen8_shadowed_regs[i].reg)
-			return true;
+	const struct intel_forcewake_range *ranges;
+	unsigned int num_ranges;
+	s32 prev;
+	unsigned int i;
 
-	return false;
-}
+	if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG))
+		return;
 
-#define __gen8_reg_write_fw_domains(offset) \
-({ \
-	enum forcewake_domains __fwd; \
-	if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(offset)) \
-		__fwd = FORCEWAKE_RENDER; \
-	else \
-		__fwd = 0; \
-	__fwd; \
-})
+	ranges = dev_priv->uncore.fw_domains_table;
+	if (!ranges)
+		return;
 
-#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
-	(REG_RANGE((reg), 0x2000, 0x4000) || \
-	 REG_RANGE((reg), 0x5200, 0x8000) || \
-	 REG_RANGE((reg), 0x8300, 0x8500) || \
-	 REG_RANGE((reg), 0xB000, 0xB480) || \
-	 REG_RANGE((reg), 0xE000, 0xE800))
+	num_ranges = dev_priv->uncore.fw_domains_table_entries;
 
-#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \
-	(REG_RANGE((reg), 0x8800, 0x8900) || \
-	 REG_RANGE((reg), 0xD000, 0xD800) || \
-	 REG_RANGE((reg), 0x12000, 0x14000) || \
-	 REG_RANGE((reg), 0x1A000, 0x1C000) || \
-	 REG_RANGE((reg), 0x1E800, 0x1EA00) || \
-	 REG_RANGE((reg), 0x30000, 0x38000))
+	for (i = 0, prev = -1; i < num_ranges; i++, ranges++) {
+		WARN_ON_ONCE(IS_GEN9(dev_priv) &&
+			     (prev + 1) != (s32)ranges->start);
+		WARN_ON_ONCE(prev >= (s32)ranges->start);
+		prev = ranges->start;
+		WARN_ON_ONCE(prev >= (s32)ranges->end);
+		prev = ranges->end;
+	}
+}
 
-#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \
-	(REG_RANGE((reg), 0x4000, 0x5000) || \
-	 REG_RANGE((reg), 0x8000, 0x8300) || \
-	 REG_RANGE((reg), 0x8500, 0x8600) || \
-	 REG_RANGE((reg), 0x9000, 0xB000) || \
-	 REG_RANGE((reg), 0xF000, 0x10000))
+#define GEN_FW_RANGE(s, e, d) \
+	{ .start = (s), .end = (e), .domains = (d) }
 
-#define __chv_reg_read_fw_domains(offset) \
-({ \
-	enum forcewake_domains __fwd = 0; \
-	if (!NEEDS_FORCE_WAKE(offset)) \
-		__fwd = 0; \
-	else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
-	__fwd; \
-})
+#define HAS_FWTABLE(dev_priv) \
+	(IS_GEN9(dev_priv) || \
+	 IS_CHERRYVIEW(dev_priv) || \
+	 IS_VALLEYVIEW(dev_priv))
 
-#define __chv_reg_write_fw_domains(offset) \
+/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */
+static const struct intel_forcewake_range __vlv_fw_ranges[] = {
+	GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x5000, 0x7fff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0xb000, 0x11fff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x2e000, 0x2ffff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA),
+};
+
+#define __fwtable_reg_read_fw_domains(offset) \
 ({ \
 	enum forcewake_domains __fwd = 0; \
-	if (!NEEDS_FORCE_WAKE(offset) || is_gen8_shadowed(offset)) \
-		__fwd = 0; \
-	else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
+	if (NEEDS_FORCE_WAKE((offset))) \
+		__fwd = find_fw_domain(dev_priv, offset); \
 	__fwd; \
 })
 
-#define FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) \
-	REG_RANGE((reg), 0xB00,  0x2000)
+/* *Must* be sorted by offset! See intel_shadow_table_check(). */
+static const i915_reg_t gen8_shadowed_regs[] = {
+	RING_TAIL(RENDER_RING_BASE),	/* 0x2000 (base) */
+	GEN6_RPNSWREQ,			/* 0xA008 */
+	GEN6_RC_VIDEO_FREQ,		/* 0xA00C */
+	RING_TAIL(GEN6_BSD_RING_BASE),	/* 0x12000 (base) */
+	RING_TAIL(VEBOX_RING_BASE),	/* 0x1a000 (base) */
+	RING_TAIL(BLT_RING_BASE),	/* 0x22000 (base) */
+	/* TODO: Other registers are not yet used */
+};
 
-#define FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) \
-	(REG_RANGE((reg), 0x2000, 0x2700) || \
-	 REG_RANGE((reg), 0x3000, 0x4000) || \
-	 REG_RANGE((reg), 0x5200, 0x8000) || \
-	 REG_RANGE((reg), 0x8140, 0x8160) || \
-	 REG_RANGE((reg), 0x8300, 0x8500) || \
-	 REG_RANGE((reg), 0x8C00, 0x8D00) || \
-	 REG_RANGE((reg), 0xB000, 0xB480) || \
-	 REG_RANGE((reg), 0xE000, 0xE900) || \
-	 REG_RANGE((reg), 0x24400, 0x24800))
+static void intel_shadow_table_check(void)
+{
+	const i915_reg_t *reg = gen8_shadowed_regs;
+	s32 prev;
+	u32 offset;
+	unsigned int i;
 
-#define FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) \
-	(REG_RANGE((reg), 0x8130, 0x8140) || \
-	 REG_RANGE((reg), 0x8800, 0x8A00) || \
-	 REG_RANGE((reg), 0xD000, 0xD800) || \
-	 REG_RANGE((reg), 0x12000, 0x14000) || \
-	 REG_RANGE((reg), 0x1A000, 0x1EA00) || \
-	 REG_RANGE((reg), 0x30000, 0x40000))
+	if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG))
+		return;
 
-#define FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg) \
-	REG_RANGE((reg), 0x9400, 0x9800)
+	for (i = 0, prev = -1; i < ARRAY_SIZE(gen8_shadowed_regs); i++, reg++) {
+		offset = i915_mmio_reg_offset(*reg);
+		WARN_ON_ONCE(prev >= (s32)offset);
+		prev = offset;
+	}
+}
 
-#define FORCEWAKE_GEN9_BLITTER_RANGE_OFFSET(reg) \
-	((reg) < 0x40000 && \
-	 !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) && \
-	 !FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) && \
-	 !FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \
-	 !FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg))
+static int mmio_reg_cmp(u32 key, const i915_reg_t *reg)
+{
+	u32 offset = i915_mmio_reg_offset(*reg);
 
-#define SKL_NEEDS_FORCE_WAKE(reg) \
-	((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg))
+	if (key < offset)
+		return -1;
+	else if (key > offset)
+		return 1;
+	else
+		return 0;
+}
 
-#define __gen9_reg_read_fw_domains(offset) \
+static bool is_gen8_shadowed(u32 offset)
+{
+	const i915_reg_t *regs = gen8_shadowed_regs;
+
+	return BSEARCH(offset, regs, ARRAY_SIZE(gen8_shadowed_regs),
+		       mmio_reg_cmp);
+}
+
+#define __gen8_reg_write_fw_domains(offset) \
 ({ \
 	enum forcewake_domains __fwd; \
-	if (!SKL_NEEDS_FORCE_WAKE(offset)) \
-		__fwd = 0; \
-	else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
+	if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(offset)) \
 		__fwd = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
 	else \
-		__fwd = FORCEWAKE_BLITTER; \
+		__fwd = 0; \
 	__fwd; \
 })
 
-static const i915_reg_t gen9_shadowed_regs[] = {
-	RING_TAIL(RENDER_RING_BASE),
-	RING_TAIL(GEN6_BSD_RING_BASE),
-	RING_TAIL(VEBOX_RING_BASE),
-	RING_TAIL(BLT_RING_BASE),
-	GEN6_RPNSWREQ,
-	GEN6_RC_VIDEO_FREQ,
-	/* TODO: Other registers are not yet used */
+/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */
+static const struct intel_forcewake_range __chv_fw_ranges[] = {
+	GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x4000, 0x4fff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x8000, 0x82ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x8500, 0x85ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x8800, 0x88ff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x9000, 0xafff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0xe000, 0xe7ff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0xf000, 0xffff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x1a000, 0x1bfff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x1e800, 0x1e9ff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x30000, 0x37fff, FORCEWAKE_MEDIA),
 };
 
-static bool is_gen9_shadowed(u32 offset)
-{
-	int i;
-	for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++)
-		if (offset == gen9_shadowed_regs[i].reg)
-			return true;
-
-	return false;
-}
-
-#define __gen9_reg_write_fw_domains(offset) \
+#define __fwtable_reg_write_fw_domains(offset) \
 ({ \
-	enum forcewake_domains __fwd; \
-	if (!SKL_NEEDS_FORCE_WAKE(offset) || is_gen9_shadowed(offset)) \
-		__fwd = 0; \
-	else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER; \
-	else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_MEDIA; \
-	else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \
-		__fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
-	else \
-		__fwd = FORCEWAKE_BLITTER; \
+	enum forcewake_domains __fwd = 0; \
+	if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) \
+		__fwd = find_fw_domain(dev_priv, offset); \
 	__fwd; \
 })
 
+/* *Must* be sorted by offset ranges! See intel_fw_table_check(). */
+static const struct intel_forcewake_range __gen9_fw_ranges[] = {
+	GEN_FW_RANGE(0x0, 0xaff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0xb00, 0x1fff, 0), /* uncore range */
+	GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x2700, 0x2fff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x4000, 0x51ff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x8000, 0x812f, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x8130, 0x813f, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x8160, 0x82ff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x8500, 0x87ff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x8800, 0x89ff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x8a00, 0x8bff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x8c00, 0x8cff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x8d00, 0x93ff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x9400, 0x97ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x9800, 0xafff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0xb480, 0xcfff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0xd800, 0xdfff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0xe000, 0xe8ff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0xe900, 0x11fff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x14000, 0x19fff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x1a000, 0x1e9ff, FORCEWAKE_MEDIA),
+	GEN_FW_RANGE(0x1ea00, 0x243ff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x24400, 0x247ff, FORCEWAKE_RENDER),
+	GEN_FW_RANGE(0x24800, 0x2ffff, FORCEWAKE_BLITTER),
+	GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA),
+};
+
 static void
 ilk_dummy_write(struct drm_i915_private *dev_priv)
 {
@@ -815,6 +839,66 @@ unclaimed_reg_debug(struct drm_i915_priv
 	__unclaimed_reg_debug(dev_priv, reg, read, before);
 }
 
+static const enum decoupled_power_domain fw2dpd_domain[] = {
+	GEN9_DECOUPLED_PD_RENDER,
+	GEN9_DECOUPLED_PD_BLITTER,
+	GEN9_DECOUPLED_PD_ALL,
+	GEN9_DECOUPLED_PD_MEDIA,
+	GEN9_DECOUPLED_PD_ALL,
+	GEN9_DECOUPLED_PD_ALL,
+	GEN9_DECOUPLED_PD_ALL
+};
+
+/*
+ * Decoupled MMIO access for only 1 DWORD
+ */
+static void __gen9_decoupled_mmio_access(struct drm_i915_private *dev_priv,
+					 u32 reg,
+					 enum forcewake_domains fw_domain,
+					 enum decoupled_ops operation)
+{
+	enum decoupled_power_domain dp_domain;
+	u32 ctrl_reg_data = 0;
+
+	dp_domain = fw2dpd_domain[fw_domain - 1];
+
+	ctrl_reg_data |= reg;
+	ctrl_reg_data |= (operation << GEN9_DECOUPLED_OP_SHIFT);
+	ctrl_reg_data |= (dp_domain << GEN9_DECOUPLED_PD_SHIFT);
+	ctrl_reg_data |= GEN9_DECOUPLED_DW1_GO;
+	__raw_i915_write32(dev_priv, GEN9_DECOUPLED_REG0_DW1, ctrl_reg_data);
+
+	if (wait_for_atomic((__raw_i915_read32(dev_priv,
+			    GEN9_DECOUPLED_REG0_DW1) &
+			    GEN9_DECOUPLED_DW1_GO) == 0,
+			    FORCEWAKE_ACK_TIMEOUT_MS))
+		DRM_ERROR("Decoupled MMIO wait timed out\n");
+}
+
+static inline u32
+__gen9_decoupled_mmio_read32(struct drm_i915_private *dev_priv,
+			     u32 reg,
+			     enum forcewake_domains fw_domain)
+{
+	__gen9_decoupled_mmio_access(dev_priv, reg, fw_domain,
+				     GEN9_DECOUPLED_OP_READ);
+
+	return __raw_i915_read32(dev_priv, GEN9_DECOUPLED_REG0_DW0);
+}
+
+static inline void
+__gen9_decoupled_mmio_write(struct drm_i915_private *dev_priv,
+			    u32 reg, u32 data,
+			    enum forcewake_domains fw_domain)
+{
+
+	__raw_i915_write32(dev_priv, GEN9_DECOUPLED_REG0_DW0, data);
+
+	__gen9_decoupled_mmio_access(dev_priv, reg, fw_domain,
+				     GEN9_DECOUPLED_OP_WRITE);
+}
+
+
 #define GEN2_READ_HEADER(x) \
 	u##x val = 0; \
 	assert_rpm_wakelock_held(dev_priv);
@@ -869,26 +953,30 @@ __gen2_read(64)
 	trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
 	return val
 
-static inline void __force_wake_auto(struct drm_i915_private *dev_priv,
-				     enum forcewake_domains fw_domains)
+static noinline void ___force_wake_auto(struct drm_i915_private *dev_priv,
+					enum forcewake_domains fw_domains)
 {
 	struct intel_uncore_forcewake_domain *domain;
 
+	for_each_fw_domain_masked(domain, fw_domains, dev_priv)
+		fw_domain_arm_timer(domain);
+
+	dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
+	dev_priv->uncore.fw_domains_active |= fw_domains;
+}
+
+static inline void __force_wake_auto(struct drm_i915_private *dev_priv,
+				     enum forcewake_domains fw_domains)
+{
 	if (WARN_ON(!fw_domains))
 		return;
 
-	/* Ideally GCC would be constant-fold and eliminate this loop */
-	for_each_fw_domain_masked(domain, fw_domains, dev_priv) {
-		if (domain->wake_count) {
-			fw_domains &= ~domain->mask;
-			continue;
-		}
-
-		fw_domain_arm_timer(domain);
-	}
+	/* Turn on all requested but inactive supported forcewake domains. */
+	fw_domains &= dev_priv->uncore.fw_domains;
+	fw_domains &= ~dev_priv->uncore.fw_domains_active;
 
 	if (fw_domains)
-		dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains);
+		___force_wake_auto(dev_priv, fw_domains);
 }
 
 #define __gen6_read(x) \
@@ -903,62 +991,50 @@ gen6_read##x(struct drm_i915_private *de
 	GEN6_READ_FOOTER; \
 }
 
-#define __vlv_read(x) \
-static u##x \
-vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
-	enum forcewake_domains fw_engine; \
-	GEN6_READ_HEADER(x); \
-	fw_engine = __vlv_reg_read_fw_domains(offset); \
-	if (fw_engine) \
-		__force_wake_auto(dev_priv, fw_engine); \
-	val = __raw_i915_read##x(dev_priv, reg); \
-	GEN6_READ_FOOTER; \
-}
-
-#define __chv_read(x) \
+#define __fwtable_read(x) \
 static u##x \
-chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+fwtable_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
 	enum forcewake_domains fw_engine; \
 	GEN6_READ_HEADER(x); \
-	fw_engine = __chv_reg_read_fw_domains(offset); \
+	fw_engine = __fwtable_reg_read_fw_domains(offset); \
 	if (fw_engine) \
 		__force_wake_auto(dev_priv, fw_engine); \
 	val = __raw_i915_read##x(dev_priv, reg); \
 	GEN6_READ_FOOTER; \
 }
 
-#define __gen9_read(x) \
+#define __gen9_decoupled_read(x) \
 static u##x \
-gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
+gen9_decoupled_read##x(struct drm_i915_private *dev_priv, \
+		       i915_reg_t reg, bool trace) { \
 	enum forcewake_domains fw_engine; \
 	GEN6_READ_HEADER(x); \
-	fw_engine = __gen9_reg_read_fw_domains(offset); \
-	if (fw_engine) \
-		__force_wake_auto(dev_priv, fw_engine); \
-	val = __raw_i915_read##x(dev_priv, reg); \
+	fw_engine = __fwtable_reg_read_fw_domains(offset); \
+	if (fw_engine & ~dev_priv->uncore.fw_domains_active) { \
+		unsigned i; \
+		u32 *ptr_data = (u32 *) &val; \
+		for (i = 0; i < x/32; i++, offset += sizeof(u32), ptr_data++) \
+			*ptr_data = __gen9_decoupled_mmio_read32(dev_priv, \
+								 offset, \
+								 fw_engine); \
+	} else { \
+		val = __raw_i915_read##x(dev_priv, reg); \
+	} \
 	GEN6_READ_FOOTER; \
 }
 
-__gen9_read(8)
-__gen9_read(16)
-__gen9_read(32)
-__gen9_read(64)
-__chv_read(8)
-__chv_read(16)
-__chv_read(32)
-__chv_read(64)
-__vlv_read(8)
-__vlv_read(16)
-__vlv_read(32)
-__vlv_read(64)
+__gen9_decoupled_read(32)
+__gen9_decoupled_read(64)
+__fwtable_read(8)
+__fwtable_read(16)
+__fwtable_read(32)
+__fwtable_read(64)
 __gen6_read(8)
 __gen6_read(16)
 __gen6_read(32)
 __gen6_read(64)
 
-#undef __gen9_read
-#undef __chv_read
-#undef __vlv_read
+#undef __fwtable_read
 #undef __gen6_read
 #undef GEN6_READ_FOOTER
 #undef GEN6_READ_HEADER
@@ -1054,21 +1130,6 @@ gen6_write##x(struct drm_i915_private *d
 	GEN6_WRITE_FOOTER; \
 }
 
-#define __hsw_write(x) \
-static void \
-hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
-	u32 __fifo_ret = 0; \
-	GEN6_WRITE_HEADER; \
-	if (NEEDS_FORCE_WAKE(offset)) { \
-		__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
-	} \
-	__raw_i915_write##x(dev_priv, reg, val); \
-	if (unlikely(__fifo_ret)) { \
-		gen6_gt_check_fifodbg(dev_priv); \
-	} \
-	GEN6_WRITE_FOOTER; \
-}
-
 #define __gen8_write(x) \
 static void \
 gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
@@ -1081,51 +1142,49 @@ gen8_write##x(struct drm_i915_private *d
 	GEN6_WRITE_FOOTER; \
 }
 
-#define __chv_write(x) \
+#define __fwtable_write(x) \
 static void \
-chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
+fwtable_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
 	enum forcewake_domains fw_engine; \
 	GEN6_WRITE_HEADER; \
-	fw_engine = __chv_reg_write_fw_domains(offset); \
+	fw_engine = __fwtable_reg_write_fw_domains(offset); \
 	if (fw_engine) \
 		__force_wake_auto(dev_priv, fw_engine); \
 	__raw_i915_write##x(dev_priv, reg, val); \
 	GEN6_WRITE_FOOTER; \
 }
 
-#define __gen9_write(x) \
+#define __gen9_decoupled_write(x) \
 static void \
-gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \
+gen9_decoupled_write##x(struct drm_i915_private *dev_priv, \
+			i915_reg_t reg, u##x val, \
 		bool trace) { \
 	enum forcewake_domains fw_engine; \
 	GEN6_WRITE_HEADER; \
-	fw_engine = __gen9_reg_write_fw_domains(offset); \
-	if (fw_engine) \
-		__force_wake_auto(dev_priv, fw_engine); \
-	__raw_i915_write##x(dev_priv, reg, val); \
+	fw_engine = __fwtable_reg_write_fw_domains(offset); \
+	if (fw_engine & ~dev_priv->uncore.fw_domains_active) \
+		__gen9_decoupled_mmio_write(dev_priv, \
+					    offset, \
+					    val, \
+					    fw_engine); \
+	else \
+		__raw_i915_write##x(dev_priv, reg, val); \
 	GEN6_WRITE_FOOTER; \
 }
 
-__gen9_write(8)
-__gen9_write(16)
-__gen9_write(32)
-__chv_write(8)
-__chv_write(16)
-__chv_write(32)
+__gen9_decoupled_write(32)
+__fwtable_write(8)
+__fwtable_write(16)
+__fwtable_write(32)
 __gen8_write(8)
 __gen8_write(16)
 __gen8_write(32)
-__hsw_write(8)
-__hsw_write(16)
-__hsw_write(32)
 __gen6_write(8)
 __gen6_write(16)
 __gen6_write(32)
 
-#undef __gen9_write
-#undef __chv_write
+#undef __fwtable_write
 #undef __gen8_write
-#undef __hsw_write
 #undef __gen6_write
 #undef GEN6_WRITE_FOOTER
 #undef GEN6_WRITE_HEADER
@@ -1314,6 +1373,13 @@ static void intel_uncore_fw_domains_init
 	WARN_ON(dev_priv->uncore.fw_domains == 0);
 }
 
+#define ASSIGN_FW_DOMAINS_TABLE(d) \
+{ \
+	dev_priv->uncore.fw_domains_table = \
+			(struct intel_forcewake_range *)(d); \
+	dev_priv->uncore.fw_domains_table_entries = ARRAY_SIZE((d)); \
+}
+
 void intel_uncore_init(struct drm_i915_private *dev_priv)
 {
 	i915_check_vgpu(dev_priv);
@@ -1327,13 +1393,23 @@ void intel_uncore_init(struct drm_i915_p
 	switch (INTEL_INFO(dev_priv)->gen) {
 	default:
 	case 9:
-		ASSIGN_WRITE_MMIO_VFUNCS(gen9);
-		ASSIGN_READ_MMIO_VFUNCS(gen9);
+		ASSIGN_FW_DOMAINS_TABLE(__gen9_fw_ranges);
+		ASSIGN_WRITE_MMIO_VFUNCS(fwtable);
+		ASSIGN_READ_MMIO_VFUNCS(fwtable);
+		if (HAS_DECOUPLED_MMIO(dev_priv)) {
+			dev_priv->uncore.funcs.mmio_readl =
+						gen9_decoupled_read32;
+			dev_priv->uncore.funcs.mmio_readq =
+						gen9_decoupled_read64;
+			dev_priv->uncore.funcs.mmio_writel =
+						gen9_decoupled_write32;
+		}
 		break;
 	case 8:
 		if (IS_CHERRYVIEW(dev_priv)) {
-			ASSIGN_WRITE_MMIO_VFUNCS(chv);
-			ASSIGN_READ_MMIO_VFUNCS(chv);
+			ASSIGN_FW_DOMAINS_TABLE(__chv_fw_ranges);
+			ASSIGN_WRITE_MMIO_VFUNCS(fwtable);
+			ASSIGN_READ_MMIO_VFUNCS(fwtable);
 
 		} else {
 			ASSIGN_WRITE_MMIO_VFUNCS(gen8);
@@ -1342,14 +1418,11 @@ void intel_uncore_init(struct drm_i915_p
 		break;
 	case 7:
 	case 6:
-		if (IS_HASWELL(dev_priv)) {
-			ASSIGN_WRITE_MMIO_VFUNCS(hsw);
-		} else {
-			ASSIGN_WRITE_MMIO_VFUNCS(gen6);
-		}
+		ASSIGN_WRITE_MMIO_VFUNCS(gen6);
 
 		if (IS_VALLEYVIEW(dev_priv)) {
-			ASSIGN_READ_MMIO_VFUNCS(vlv);
+			ASSIGN_FW_DOMAINS_TABLE(__vlv_fw_ranges);
+			ASSIGN_READ_MMIO_VFUNCS(fwtable);
 		} else {
 			ASSIGN_READ_MMIO_VFUNCS(gen6);
 		}
@@ -1366,6 +1439,10 @@ void intel_uncore_init(struct drm_i915_p
 		break;
 	}
 
+	intel_fw_table_check(dev_priv);
+	if (INTEL_GEN(dev_priv) >= 8)
+		intel_shadow_table_check();
+
 	if (intel_vgpu_active(dev_priv)) {
 		ASSIGN_WRITE_MMIO_VFUNCS(vgpu);
 		ASSIGN_READ_MMIO_VFUNCS(vgpu);
@@ -1408,7 +1485,7 @@ int i915_reg_read_ioctl(struct drm_devic
 
 	for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
 		if (i915_mmio_reg_offset(entry->offset_ldw) == (reg->offset & -entry->size) &&
-		    (INTEL_INFO(dev)->gen_mask & entry->gen_bitmask))
+		    (INTEL_INFO(dev_priv)->gen_mask & entry->gen_bitmask))
 			break;
 	}
 
@@ -1815,35 +1892,16 @@ static enum forcewake_domains
 intel_uncore_forcewake_for_read(struct drm_i915_private *dev_priv,
 				i915_reg_t reg)
 {
+	u32 offset = i915_mmio_reg_offset(reg);
 	enum forcewake_domains fw_domains;
 
-	if (intel_vgpu_active(dev_priv))
-		return 0;
-
-	switch (INTEL_GEN(dev_priv)) {
-	case 9:
-		fw_domains = __gen9_reg_read_fw_domains(i915_mmio_reg_offset(reg));
-		break;
-	case 8:
-		if (IS_CHERRYVIEW(dev_priv))
-			fw_domains = __chv_reg_read_fw_domains(i915_mmio_reg_offset(reg));
-		else
-			fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg));
-		break;
-	case 7:
-	case 6:
-		if (IS_VALLEYVIEW(dev_priv))
-			fw_domains = __vlv_reg_read_fw_domains(i915_mmio_reg_offset(reg));
-		else
-			fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg));
-		break;
-	default:
-		MISSING_CASE(INTEL_INFO(dev_priv)->gen);
-	case 5: /* forcewake was introduced with gen6 */
-	case 4:
-	case 3:
-	case 2:
-		return 0;
+	if (HAS_FWTABLE(dev_priv)) {
+		fw_domains = __fwtable_reg_read_fw_domains(offset);
+	} else if (INTEL_GEN(dev_priv) >= 6) {
+		fw_domains = __gen6_reg_read_fw_domains(offset);
+	} else {
+		WARN_ON(!IS_GEN(dev_priv, 2, 5));
+		fw_domains = 0;
 	}
 
 	WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains);
@@ -1855,32 +1913,18 @@ static enum forcewake_domains
 intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv,
 				 i915_reg_t reg)
 {
+	u32 offset = i915_mmio_reg_offset(reg);
 	enum forcewake_domains fw_domains;
 
-	if (intel_vgpu_active(dev_priv))
-		return 0;
-
-	switch (INTEL_GEN(dev_priv)) {
-	case 9:
-		fw_domains = __gen9_reg_write_fw_domains(i915_mmio_reg_offset(reg));
-		break;
-	case 8:
-		if (IS_CHERRYVIEW(dev_priv))
-			fw_domains = __chv_reg_write_fw_domains(i915_mmio_reg_offset(reg));
-		else
-			fw_domains = __gen8_reg_write_fw_domains(i915_mmio_reg_offset(reg));
-		break;
-	case 7:
-	case 6:
+	if (HAS_FWTABLE(dev_priv) && !IS_VALLEYVIEW(dev_priv)) {
+		fw_domains = __fwtable_reg_write_fw_domains(offset);
+	} else if (IS_GEN8(dev_priv)) {
+		fw_domains = __gen8_reg_write_fw_domains(offset);
+	} else if (IS_GEN(dev_priv, 6, 7)) {
 		fw_domains = FORCEWAKE_RENDER;
-		break;
-	default:
-		MISSING_CASE(INTEL_INFO(dev_priv)->gen);
-	case 5:
-	case 4:
-	case 3:
-	case 2:
-		return 0;
+	} else {
+		WARN_ON(!IS_GEN(dev_priv, 2, 5));
+		fw_domains = 0;
 	}
 
 	WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains);
@@ -1910,6 +1954,9 @@ intel_uncore_forcewake_for_reg(struct dr
 
 	WARN_ON(!op);
 
+	if (intel_vgpu_active(dev_priv))
+		return 0;
+
 	if (op & FW_REG_READ)
 		fw_domains = intel_uncore_forcewake_for_read(dev_priv, reg);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@ config DRM_I915
 	select DRM_KMS_HELPER
 	select DRM_PANEL
 	select DRM_MIPI_DSI
+	select RELAY
 	# 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
@@ -24,28 +25,59 @@ config DRM_I915
 	  including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G,
 	  G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3,
 	  Core i5, Core i7 as well as Atom CPUs with integrated graphics.
-	  If M is selected, the module will be called i915.  AGP support
-	  is required for this driver to work. This driver is used by
-	  the Intel driver in X.org 6.8 and XFree86 4.4 and above. It
-	  replaces the older i830 module that supported a subset of the
-	  hardware in older X.org releases.
+
+	  This driver is used by the Intel driver in X.org 6.8 and
+	  XFree86 4.4 and above. It replaces the older i830 module that
+	  supported a subset of the hardware in older X.org releases.
 
 	  Note that the older i810/i815 chipsets require the use of the
 	  i810 driver instead, and the Atom z5xx series has an entirely
 	  different implementation.
 
-config DRM_I915_PRELIMINARY_HW_SUPPORT
-	bool "Enable preliminary support for prerelease Intel hardware by default"
+	  If "M" is selected, the module will be called i915.
+
+config DRM_I915_ALPHA_SUPPORT
+	bool "Enable alpha quality support for new Intel hardware by default"
 	depends on DRM_I915
 	default n
 	help
-	  Choose this option if you have prerelease Intel hardware and want the
-	  i915 driver to support it by default.  You can enable such support at
-	  runtime with the module option i915.preliminary_hw_support=1; this
-	  option changes the default for that module option.
+	  Choose this option if you have new Intel hardware and want to enable
+	  the alpha quality i915 driver support for the hardware in this kernel
+	  version. You can also enable the support at runtime using the module
+	  parameter i915.alpha_support=1; this option changes the default for
+	  that module parameter.
+
+	  It is recommended to upgrade to a kernel version with proper support
+	  as soon as it is available. Generally fixes for platforms with alpha
+	  support are not backported to older kernels.
 
 	  If in doubt, say "N".
 
+config DRM_I915_CAPTURE_ERROR
+	bool "Enable capturing GPU state following a hang"
+	depends on DRM_I915
+	default y
+	help
+	  This option enables capturing the GPU state when a hang is detected.
+	  This information is vital for triaging hangs and assists in debugging.
+	  Please report any hang to
+            https://bugs.freedesktop.org/enter_bug.cgi?product=DRI
+	  for triaging.
+
+	  If in doubt, say "Y".
+
+config DRM_I915_COMPRESS_ERROR
+	bool "Compress GPU error state"
+	depends on DRM_I915_CAPTURE_ERROR
+	select ZLIB_DEFLATE
+	default y
+	help
+	  This option selects ZLIB_DEFLATE if it isn't already
+	  selected and causes any error state captured upon a GPU hang
+	  to be compressed using zlib.
+
+	  If in doubt, say "Y".
+
 config DRM_I915_USERPTR
 	bool "Always enable userptr support"
 	depends on DRM_I915
@@ -60,6 +92,7 @@ config DRM_I915_USERPTR
 config DRM_I915_GVT
         bool "Enable Intel GVT-g graphics virtualization host support"
         depends on DRM_I915
+        depends on 64BIT
         default n
         help
 	  Choose this option if you want to enable Intel GVT-g graphics
@@ -79,6 +112,16 @@ config DRM_I915_GVT
 
 	  If in doubt, say "N".
 
+config DRM_I915_GVT_KVMGT
+	tristate "Enable KVM/VFIO support for Intel GVT-g"
+	depends on DRM_I915_GVT
+	depends on KVM
+	depends on VFIO_MDEV && VFIO_MDEV_DEVICE
+	default n
+	help
+	  Choose this option if you want to enable KVMGT support for
+	  Intel GVT-g.
+
 menu "drm/i915 Debugging"
 depends on DRM_I915
 depends on EXPERT
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/Kconfig.debug linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/Kconfig.debug
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/Kconfig.debug	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/Kconfig.debug	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,7 @@ config DRM_I915_DEBUG
         select PREEMPT_COUNT
         select X86_MSR # used by igt/pm_rpm
         select DRM_VGEM # used by igt/prime_vgem (dmabuf interop checks)
+        select DRM_DEBUG_MM if DRM=y
         default n
         help
           Choose this option to turn on extra driver debugging that may affect
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/i915/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/i915/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/i915/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -33,19 +33,22 @@ i915-y += i915_cmd_parser.o \
 	  i915_gem_dmabuf.o \
 	  i915_gem_evict.o \
 	  i915_gem_execbuffer.o \
-	  i915_gem_fence.o \
+	  i915_gem_fence_reg.o \
 	  i915_gem_gtt.o \
+	  i915_gem_internal.o \
 	  i915_gem.o \
 	  i915_gem_render_state.o \
 	  i915_gem_request.o \
 	  i915_gem_shrinker.o \
 	  i915_gem_stolen.o \
 	  i915_gem_tiling.o \
+	  i915_gem_timeline.o \
 	  i915_gem_userptr.o \
-	  i915_gpu_error.o \
 	  i915_trace_points.o \
+	  i915_vma.o \
 	  intel_breadcrumbs.o \
 	  intel_engine_cs.o \
+	  intel_hangcheck.o \
 	  intel_lrc.o \
 	  intel_mocs.o \
 	  intel_ringbuffer.o \
@@ -102,11 +105,15 @@ i915-y += dvo_ch7017.o \
 	  intel_dvo.o \
 	  intel_hdmi.o \
 	  intel_i2c.o \
+	  intel_lspcon.o \
 	  intel_lvds.o \
 	  intel_panel.o \
 	  intel_sdvo.o \
 	  intel_tv.o
 
+# Post-mortem debug and GPU hang state capture
+i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
+
 # virtual gpu code
 i915-y += i915_vgpu.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/imx/imx-drm-core.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/imx-drm-core.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/imx/imx-drm-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/imx-drm-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,6 @@
 #include <linux/dma-buf.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
-#include <linux/reservation.h>
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -151,38 +150,11 @@ static int imx_drm_atomic_check(struct d
 	return ret;
 }
 
-static int imx_drm_atomic_commit(struct drm_device *dev,
-				 struct drm_atomic_state *state,
-				 bool nonblock)
-{
-	struct drm_plane_state *plane_state;
-	struct drm_plane *plane;
-	struct dma_buf *dma_buf;
-	int i;
-
-	/*
-	 * If the plane fb has an dma-buf attached, fish out the exclusive
-	 * fence for the atomic helper to wait on.
-	 */
-	for_each_plane_in_state(state, plane, plane_state, i) {
-		if ((plane->state->fb != plane_state->fb) && plane_state->fb) {
-			dma_buf = drm_fb_cma_get_gem_obj(plane_state->fb,
-							 0)->base.dma_buf;
-			if (!dma_buf)
-				continue;
-			plane_state->fence =
-				reservation_object_get_excl_rcu(dma_buf->resv);
-		}
-	}
-
-	return drm_atomic_helper_commit(dev, state, nonblock);
-}
-
 static const struct drm_mode_config_funcs imx_drm_mode_config_funcs = {
 	.fb_create = drm_fb_cma_create,
 	.output_poll_changed = imx_drm_output_poll_changed,
 	.atomic_check = imx_drm_atomic_check,
-	.atomic_commit = imx_drm_atomic_commit,
+	.atomic_commit = drm_atomic_helper_commit,
 };
 
 static void imx_drm_atomic_commit_tail(struct drm_atomic_state *state)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/imx/imx-ldb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/imx-ldb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/imx/imx-ldb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/imx-ldb.c	2017-02-12 16:03:20.000000000 -0500
@@ -101,12 +101,6 @@ struct imx_ldb {
 	const struct bus_mux *lvds_mux;
 };
 
-static enum drm_connector_status imx_ldb_connector_detect(
-		struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void imx_ldb_ch_set_bus_format(struct imx_ldb_channel *imx_ldb_ch,
 				      u32 bus_format)
 {
@@ -319,18 +313,6 @@ static void imx_ldb_encoder_disable(stru
 	struct imx_ldb *ldb = imx_ldb_ch->ldb;
 	int mux, ret;
 
-	/*
-	 * imx_ldb_encoder_disable is called by
-	 * drm_helper_disable_unused_functions without
-	 * the encoder being enabled before.
-	 */
-	if (imx_ldb_ch == &ldb->channel[0] &&
-	    (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0)
-		return;
-	else if (imx_ldb_ch == &ldb->channel[1] &&
-		 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
-		return;
-
 	drm_panel_disable(imx_ldb_ch->panel);
 
 	if (imx_ldb_ch == &ldb->channel[0])
@@ -409,7 +391,6 @@ static int imx_ldb_encoder_atomic_check(
 static const struct drm_connector_funcs imx_ldb_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = imx_ldb_connector_detect,
 	.destroy = imx_drm_connector_destroy,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/imx/imx-tve.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/imx-tve.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/imx/imx-tve.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/imx-tve.c	2017-02-12 16:03:20.000000000 -0500
@@ -227,12 +227,6 @@ static int tve_setup_vga(struct imx_tve
 				 TVE_TVDAC_TEST_MODE_MASK, 1);
 }
 
-static enum drm_connector_status imx_tve_connector_detect(
-				struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static int imx_tve_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_tve *tve = con_to_tve(connector);
@@ -352,7 +346,6 @@ static int imx_tve_atomic_check(struct d
 static const struct drm_connector_funcs imx_tve_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = imx_tve_connector_detect,
 	.destroy = imx_drm_connector_destroy,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/imx/ipuv3-plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/ipuv3-plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/imx/ipuv3-plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/ipuv3-plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,6 +50,12 @@ static const uint32_t ipu_plane_formats[
 	DRM_FORMAT_YVYU,
 	DRM_FORMAT_YUV420,
 	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YVU422,
+	DRM_FORMAT_YUV444,
+	DRM_FORMAT_YVU444,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
 	DRM_FORMAT_RGB565,
 };
 
@@ -64,13 +70,14 @@ drm_plane_state_to_eba(struct drm_plane_
 {
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *cma_obj;
+	int x = state->src_x >> 16;
+	int y = state->src_y >> 16;
 
 	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
 	BUG_ON(!cma_obj);
 
-	return cma_obj->paddr + fb->offsets[0] +
-	       fb->pitches[0] * (state->src_y >> 16) +
-	       (fb->bits_per_pixel >> 3) * (state->src_x >> 16);
+	return cma_obj->paddr + fb->offsets[0] + fb->pitches[0] * y +
+	       drm_format_plane_cpp(fb->pixel_format, 0) * x;
 }
 
 static inline unsigned long
@@ -79,13 +86,17 @@ drm_plane_state_to_ubo(struct drm_plane_
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *cma_obj;
 	unsigned long eba = drm_plane_state_to_eba(state);
+	int x = state->src_x >> 16;
+	int y = state->src_y >> 16;
 
 	cma_obj = drm_fb_cma_get_gem_obj(fb, 1);
 	BUG_ON(!cma_obj);
 
-	return cma_obj->paddr + fb->offsets[1] +
-	       fb->pitches[1] * (state->src_y >> 16) / 2 +
-	       (state->src_x >> 16) / 2 - eba;
+	x /= drm_format_horz_chroma_subsampling(fb->pixel_format);
+	y /= drm_format_vert_chroma_subsampling(fb->pixel_format);
+
+	return cma_obj->paddr + fb->offsets[1] + fb->pitches[1] * y +
+	       drm_format_plane_cpp(fb->pixel_format, 1) * x - eba;
 }
 
 static inline unsigned long
@@ -94,69 +105,17 @@ drm_plane_state_to_vbo(struct drm_plane_
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *cma_obj;
 	unsigned long eba = drm_plane_state_to_eba(state);
+	int x = state->src_x >> 16;
+	int y = state->src_y >> 16;
 
 	cma_obj = drm_fb_cma_get_gem_obj(fb, 2);
 	BUG_ON(!cma_obj);
 
-	return cma_obj->paddr + fb->offsets[2] +
-	       fb->pitches[2] * (state->src_y >> 16) / 2 +
-	       (state->src_x >> 16) / 2 - eba;
-}
-
-static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane)
-{
-	struct drm_plane *plane = &ipu_plane->base;
-	struct drm_plane_state *state = plane->state;
-	struct drm_crtc_state *crtc_state = state->crtc->state;
-	struct drm_framebuffer *fb = state->fb;
-	unsigned long eba, ubo, vbo;
-	int active;
-
-	eba = drm_plane_state_to_eba(state);
-
-	switch (fb->pixel_format) {
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-		if (!drm_atomic_crtc_needs_modeset(crtc_state))
-			break;
-
-		/*
-		 * Multiplanar formats have to meet the following restrictions:
-		 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
-		 * - EBA, UBO and VBO are a multiple of 8
-		 * - UBO and VBO are unsigned and not larger than 0xfffff8
-		 * - Only EBA may be changed while scanout is active
-		 * - The strides of U and V planes must be identical.
-		 */
-		ubo = drm_plane_state_to_ubo(state);
-		vbo = drm_plane_state_to_vbo(state);
-
-		if (fb->pixel_format == DRM_FORMAT_YUV420)
-			ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
-						      fb->pitches[1], ubo, vbo);
-		else
-			ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
-						      fb->pitches[1], vbo, ubo);
-
-		dev_dbg(ipu_plane->base.dev->dev,
-			"phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
-			state->src_x >> 16, state->src_y >> 16);
-		break;
-	default:
-		dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
-			eba, state->src_x >> 16, state->src_y >> 16);
-
-		break;
-	}
+	x /= drm_format_horz_chroma_subsampling(fb->pixel_format);
+	y /= drm_format_vert_chroma_subsampling(fb->pixel_format);
 
-	if (!drm_atomic_crtc_needs_modeset(crtc_state)) {
-		active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
-		ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
-		ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
-	} else {
-		ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
-		ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
-	}
+	return cma_obj->paddr + fb->offsets[2] + fb->pitches[2] * y +
+	       drm_format_plane_cpp(fb->pixel_format, 2) * x - eba;
 }
 
 void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
@@ -339,6 +298,10 @@ static int ipu_plane_atomic_check(struct
 	switch (fb->pixel_format) {
 	case DRM_FORMAT_YUV420:
 	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
 		/*
 		 * Multiplanar formats have to meet the following restrictions:
 		 * - The (up to) three plane addresses are EBA, EBA+UBO, EBA+VBO
@@ -347,27 +310,34 @@ static int ipu_plane_atomic_check(struct
 		 * - Only EBA may be changed while scanout is active
 		 * - The strides of U and V planes must be identical.
 		 */
-		ubo = drm_plane_state_to_ubo(state);
 		vbo = drm_plane_state_to_vbo(state);
 
-		if ((ubo & 0x7) || (vbo & 0x7))
-			return -EINVAL;
-
-		if ((ubo > 0xfffff8) || (vbo > 0xfffff8))
+		if (vbo & 0x7 || vbo > 0xfffff8)
 			return -EINVAL;
 
-		if (old_fb &&
-		    (old_fb->pixel_format == DRM_FORMAT_YUV420 ||
-		     old_fb->pixel_format == DRM_FORMAT_YVU420)) {
-			old_ubo = drm_plane_state_to_ubo(old_state);
+		if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
 			old_vbo = drm_plane_state_to_vbo(old_state);
-			if (ubo != old_ubo || vbo != old_vbo)
-				return -EINVAL;
+			if (vbo != old_vbo)
+				crtc_state->mode_changed = true;
 		}
 
 		if (fb->pitches[1] != fb->pitches[2])
 			return -EINVAL;
 
+		/* fall-through */
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+		ubo = drm_plane_state_to_ubo(state);
+
+		if (ubo & 0x7 || ubo > 0xfffff8)
+			return -EINVAL;
+
+		if (old_fb && (fb->pixel_format == old_fb->pixel_format)) {
+			old_ubo = drm_plane_state_to_ubo(old_state);
+			if (ubo != old_ubo)
+				crtc_state->mode_changed = true;
+		}
+
 		if (fb->pitches[1] < 1 || fb->pitches[1] > 16384)
 			return -EINVAL;
 
@@ -399,15 +369,19 @@ static void ipu_plane_atomic_update(stru
 {
 	struct ipu_plane *ipu_plane = to_ipu_plane(plane);
 	struct drm_plane_state *state = plane->state;
+	struct drm_crtc_state *crtc_state = state->crtc->state;
+	struct drm_framebuffer *fb = state->fb;
+	unsigned long eba, ubo, vbo;
 	enum ipu_color_space ics;
+	int active;
 
-	if (old_state->fb) {
-		struct drm_crtc_state *crtc_state = state->crtc->state;
+	eba = drm_plane_state_to_eba(state);
 
-		if (!drm_atomic_crtc_needs_modeset(crtc_state)) {
-			ipu_plane_atomic_set_base(ipu_plane);
-			return;
-		}
+	if (old_state->fb && !drm_atomic_crtc_needs_modeset(crtc_state)) {
+		active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);
+		ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);
+		ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active);
+		return;
 	}
 
 	switch (ipu_plane->dp_flow) {
@@ -451,11 +425,50 @@ static void ipu_plane_atomic_update(stru
 	ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
 	ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);
 	ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]);
-	ipu_plane_atomic_set_base(ipu_plane);
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		ubo = drm_plane_state_to_ubo(state);
+		vbo = drm_plane_state_to_vbo(state);
+		if (fb->pixel_format == DRM_FORMAT_YVU420 ||
+		    fb->pixel_format == DRM_FORMAT_YVU422 ||
+		    fb->pixel_format == DRM_FORMAT_YVU444)
+			swap(ubo, vbo);
+
+		ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
+					      fb->pitches[1], ubo, vbo);
+
+		dev_dbg(ipu_plane->base.dev->dev,
+			"phy = %lu %lu %lu, x = %d, y = %d", eba, ubo, vbo,
+			state->src_x >> 16, state->src_y >> 16);
+		break;
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV16:
+		ubo = drm_plane_state_to_ubo(state);
+
+		ipu_cpmem_set_yuv_planar_full(ipu_plane->ipu_ch,
+					      fb->pitches[1], ubo, ubo);
+
+		dev_dbg(ipu_plane->base.dev->dev,
+			"phy = %lu %lu, x = %d, y = %d", eba, ubo,
+			state->src_x >> 16, state->src_y >> 16);
+		break;
+	default:
+		dev_dbg(ipu_plane->base.dev->dev, "phys = %lu, x = %d, y = %d",
+			eba, state->src_x >> 16, state->src_y >> 16);
+		break;
+	}
+	ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 0, eba);
+	ipu_cpmem_set_buffer(ipu_plane->ipu_ch, 1, eba);
 	ipu_plane_enable(ipu_plane);
 }
 
 static const struct drm_plane_helper_funcs ipu_plane_helper_funcs = {
+	.prepare_fb = drm_fb_cma_prepare_fb,
 	.atomic_check = ipu_plane_atomic_check,
 	.atomic_disable = ipu_plane_atomic_disable,
 	.atomic_update = ipu_plane_atomic_update,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/imx/parallel-display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/parallel-display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/imx/parallel-display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/imx/parallel-display.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,12 +49,6 @@ static inline struct imx_parallel_displa
 	return container_of(e, struct imx_parallel_display, encoder);
 }
 
-static enum drm_connector_status imx_pd_connector_detect(
-		struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static int imx_pd_connector_get_modes(struct drm_connector *connector)
 {
 	struct imx_parallel_display *imxpd = con_to_imxpd(connector);
@@ -143,7 +137,6 @@ static int imx_pd_encoder_atomic_check(s
 static const struct drm_connector_funcs imx_pd_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = imx_pd_connector_detect,
 	.destroy = imx_drm_connector_destroy,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@ menuconfig DRM
 	select I2C
 	select I2C_ALGOBIT
 	select DMA_SHARED_BUFFER
+	select SYNC_FILE
 	help
 	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
 	  introduced in XFree86 4.0. If you say Y here, you need to select
@@ -33,6 +34,20 @@ config DRM_DP_AUX_CHARDEV
 	  read and write values to arbitrary DPCD registers on the DP aux
 	  channel.
 
+config DRM_DEBUG_MM
+	bool "Insert extra checks and debug info into the DRM range managers"
+	default n
+	depends on DRM=y
+	depends on STACKTRACE_SUPPORT
+	select STACKDEPOT
+	help
+	  Enable allocation tracking of memory manager and leak detection on
+	  shutdown.
+
+	  Recommended for driver developers only.
+
+	  If in doubt, say "N".
+
 config DRM_KMS_HELPER
 	tristate
 	depends on DRM
@@ -223,6 +238,12 @@ source "drivers/gpu/drm/hisilicon/Kconfi
 
 source "drivers/gpu/drm/mediatek/Kconfig"
 
+source "drivers/gpu/drm/zte/Kconfig"
+
+source "drivers/gpu/drm/mxsfb/Kconfig"
+
+source "drivers/gpu/drm/meson/Kconfig"
+
 # Keep legacy drivers last
 
 menuconfig DRM_LEGACY
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -9,13 +9,14 @@ drm-y       :=	drm_auth.o drm_bufs.o drm
 		drm_scatter.o drm_pci.o \
 		drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
 		drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \
-		drm_info.o drm_debugfs.o drm_encoder_slave.o \
+		drm_info.o drm_encoder_slave.o \
 		drm_trace_points.o drm_global.o drm_prime.o \
 		drm_rect.o drm_vma_manager.o drm_flip_work.o \
 		drm_modeset_lock.o drm_atomic.o drm_bridge.o \
 		drm_framebuffer.o drm_connector.o drm_blend.o \
 		drm_encoder.o drm_mode_object.o drm_property.o \
-		drm_plane.o drm_color_mgmt.o
+		drm_plane.o drm_color_mgmt.o drm_print.o \
+		drm_dumb_buffers.o drm_mode_config.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@ -23,6 +24,7 @@ drm-$(CONFIG_PCI) += ati_pcigart.o
 drm-$(CONFIG_DRM_PANEL) += drm_panel.o
 drm-$(CONFIG_OF) += drm_of.o
 drm-$(CONFIG_AGP) += drm_agpsupport.o
+drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
 
 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
 		drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
@@ -79,6 +81,7 @@ obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-$(CONFIG_DRM_STI) += sti/
 obj-$(CONFIG_DRM_IMX) += imx/
 obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
+obj-$(CONFIG_DRM_MESON)	+= meson/
 obj-y			+= i2c/
 obj-y			+= panel/
 obj-y			+= bridge/
@@ -86,3 +89,5 @@ obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
 obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/
 obj-$(CONFIG_DRM_ARCPGU)+= arc/
 obj-y			+= hisilicon/
+obj-$(CONFIG_DRM_ZTE)	+= zte/
+obj-$(CONFIG_DRM_MXSFB)	+= mxsfb/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mediatek/mtk_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
 #include <linux/component.h>
 #include <linux/iommu.h>
 #include <linux/of_address.h>
@@ -83,7 +84,7 @@ static void mtk_atomic_complete(struct m
 	drm_atomic_helper_wait_for_vblanks(drm, state);
 
 	drm_atomic_helper_cleanup_planes(drm, state);
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 }
 
 static void mtk_atomic_work(struct work_struct *work)
@@ -110,6 +111,7 @@ static int mtk_atomic_commit(struct drm_
 
 	drm_atomic_helper_swap_state(state, true);
 
+	drm_atomic_state_get(state);
 	if (async)
 		mtk_atomic_schedule(private, state);
 	else
@@ -247,16 +249,14 @@ static const struct file_operations mtk_
 	.mmap = mtk_drm_gem_mmap,
 	.poll = drm_poll,
 	.read = drm_read,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 };
 
 static struct drm_driver mtk_drm_driver = {
 	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
 			   DRIVER_ATOMIC,
 
-	.get_vblank_counter = drm_vblank_count,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
 	.enable_vblank = mtk_drm_crtc_enable_vblank,
 	.disable_vblank = mtk_drm_crtc_disable_vblank,
 
@@ -415,7 +415,8 @@ static int mtk_drm_probe(struct platform
 		    comp_type == MTK_DPI) {
 			dev_info(dev, "Adding component match for %s\n",
 				 node->full_name);
-			component_match_add(dev, &match, compare_of, node);
+			drm_of_component_match_add(dev, &match, compare_of,
+						   node);
 		} else {
 			struct mtk_ddp_comp *comp;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mediatek/mtk_dsi.c	2017-02-12 16:03:20.000000000 -0500
@@ -594,12 +594,6 @@ static void mtk_dsi_encoder_enable(struc
 	mtk_output_dsi_enable(dsi);
 }
 
-static enum drm_connector_status mtk_dsi_connector_detect(
-	struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static int mtk_dsi_connector_get_modes(struct drm_connector *connector)
 {
 	struct mtk_dsi *dsi = connector_to_dsi(connector);
@@ -616,7 +610,6 @@ static const struct drm_encoder_helper_f
 
 static const struct drm_connector_funcs mtk_dsi_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
-	.detect = mtk_dsi_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = drm_connector_cleanup,
 	.reset = drm_atomic_helper_connector_reset,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,9 @@
+config DRM_MESON
+	tristate "DRM Support for Amlogic Meson Display Controller"
+	depends on DRM && OF && (ARM || ARM64)
+	depends on ARCH_MESON || COMPILE_TEST
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_GEM_CMA_HELPER
+	select VIDEOMODE_HELPERS
+	select REGMAP_MMIO
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,4 @@
+meson-y := meson_drv.o meson_plane.o meson_crtc.o meson_venc_cvbs.o
+meson-y += meson_viu.o meson_vpp.o meson_venc.o meson_vclk.o meson_canvas.o
+
+obj-$(CONFIG_DRM_MESON) += meson.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_canvas.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_canvas.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_canvas.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_canvas.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/module.h>
+#include "meson_drv.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+/*
+ * CANVAS is a memory zone where physical memory frames information
+ * are stored for the VIU to scanout.
+ */
+
+/* DMC Registers */
+#define DMC_CAV_LUT_DATAL	0x48 /* 0x12 offset in data sheet */
+#define CANVAS_WIDTH_LBIT	29
+#define CANVAS_WIDTH_LWID       3
+#define DMC_CAV_LUT_DATAH	0x4c /* 0x13 offset in data sheet */
+#define CANVAS_WIDTH_HBIT       0
+#define CANVAS_HEIGHT_BIT       9
+#define CANVAS_BLKMODE_BIT      24
+#define DMC_CAV_LUT_ADDR	0x50 /* 0x14 offset in data sheet */
+#define CANVAS_LUT_WR_EN        (0x2 << 8)
+#define CANVAS_LUT_RD_EN        (0x1 << 8)
+
+void meson_canvas_setup(struct meson_drm *priv,
+			uint32_t canvas_index, uint32_t addr,
+			uint32_t stride, uint32_t height,
+			unsigned int wrap,
+			unsigned int blkmode)
+{
+	unsigned int val;
+
+	regmap_write(priv->dmc, DMC_CAV_LUT_DATAL,
+		(((addr + 7) >> 3)) |
+		(((stride + 7) >> 3) << CANVAS_WIDTH_LBIT));
+
+	regmap_write(priv->dmc, DMC_CAV_LUT_DATAH,
+		((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) <<
+						CANVAS_WIDTH_HBIT) |
+		(height << CANVAS_HEIGHT_BIT) |
+		(wrap << 22) |
+		(blkmode << CANVAS_BLKMODE_BIT));
+
+	regmap_write(priv->dmc, DMC_CAV_LUT_ADDR,
+			CANVAS_LUT_WR_EN | canvas_index);
+
+	/* Force a read-back to make sure everything is flushed. */
+	regmap_read(priv->dmc, DMC_CAV_LUT_DATAH, &val);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_canvas.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_canvas.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_canvas.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_canvas.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ */
+
+/* Canvas LUT Memory */
+
+#ifndef __MESON_CANVAS_H
+#define __MESON_CANVAS_H
+
+#define MESON_CANVAS_ID_OSD1	0x4e
+
+/* Canvas configuration. */
+#define MESON_CANVAS_WRAP_NONE	0x00
+#define	MESON_CANVAS_WRAP_X	0x01
+#define	MESON_CANVAS_WRAP_Y	0x02
+
+#define	MESON_CANVAS_BLKMODE_LINEAR	0x00
+#define	MESON_CANVAS_BLKMODE_32x32	0x01
+#define	MESON_CANVAS_BLKMODE_64x64	0x02
+
+void meson_canvas_setup(struct meson_drm *priv,
+			uint32_t canvas_index, uint32_t addr,
+			uint32_t stride, uint32_t height,
+			unsigned int wrap,
+			unsigned int blkmode);
+
+#endif /* __MESON_CANVAS_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "meson_crtc.h"
+#include "meson_plane.h"
+#include "meson_vpp.h"
+#include "meson_viu.h"
+#include "meson_registers.h"
+
+/* CRTC definition */
+
+struct meson_crtc {
+	struct drm_crtc base;
+	struct drm_pending_vblank_event *event;
+	struct meson_drm *priv;
+};
+#define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
+
+/* CRTC */
+
+static const struct drm_crtc_funcs meson_crtc_funcs = {
+	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.destroy		= drm_crtc_cleanup,
+	.page_flip		= drm_atomic_helper_page_flip,
+	.reset			= drm_atomic_helper_crtc_reset,
+	.set_config             = drm_atomic_helper_set_config,
+};
+
+static void meson_crtc_enable(struct drm_crtc *crtc)
+{
+	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+	struct drm_plane *plane = meson_crtc->priv->primary_plane;
+	struct meson_drm *priv = meson_crtc->priv;
+
+	/* Enable VPP Postblend */
+	writel(plane->state->crtc_w,
+	       priv->io_base + _REG(VPP_POSTBLEND_H_SIZE));
+
+	writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
+			    priv->io_base + _REG(VPP_MISC));
+
+	priv->viu.osd1_enabled = true;
+}
+
+static void meson_crtc_disable(struct drm_crtc *crtc)
+{
+	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+	struct meson_drm *priv = meson_crtc->priv;
+
+	priv->viu.osd1_enabled = false;
+
+	/* Disable VPP Postblend */
+	writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+	if (crtc->state->event && !crtc->state->active) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+
+		crtc->state->event = NULL;
+	}
+}
+
+static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
+				    struct drm_crtc_state *state)
+{
+	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+	unsigned long flags;
+
+	if (crtc->state->event) {
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		meson_crtc->event = crtc->state->event;
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+		crtc->state->event = NULL;
+	}
+}
+
+static void meson_crtc_atomic_flush(struct drm_crtc *crtc,
+				    struct drm_crtc_state *old_crtc_state)
+{
+	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+	struct meson_drm *priv = meson_crtc->priv;
+
+	if (priv->viu.osd1_enabled)
+		priv->viu.osd1_commit = true;
+}
+
+static const struct drm_crtc_helper_funcs meson_crtc_helper_funcs = {
+	.enable		= meson_crtc_enable,
+	.disable	= meson_crtc_disable,
+	.atomic_begin	= meson_crtc_atomic_begin,
+	.atomic_flush	= meson_crtc_atomic_flush,
+};
+
+void meson_crtc_irq(struct meson_drm *priv)
+{
+	struct meson_crtc *meson_crtc = to_meson_crtc(priv->crtc);
+	unsigned long flags;
+
+	/* Update the OSD registers */
+	if (priv->viu.osd1_enabled && priv->viu.osd1_commit) {
+		writel_relaxed(priv->viu.osd1_ctrl_stat,
+				priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
+		writel_relaxed(priv->viu.osd1_blk0_cfg[0],
+				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W0));
+		writel_relaxed(priv->viu.osd1_blk0_cfg[1],
+				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W1));
+		writel_relaxed(priv->viu.osd1_blk0_cfg[2],
+				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W2));
+		writel_relaxed(priv->viu.osd1_blk0_cfg[3],
+				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W3));
+		writel_relaxed(priv->viu.osd1_blk0_cfg[4],
+				priv->io_base + _REG(VIU_OSD1_BLK0_CFG_W4));
+
+		/* If output is interlace, make use of the Scaler */
+		if (priv->viu.osd1_interlace) {
+			struct drm_plane *plane = priv->primary_plane;
+			struct drm_plane_state *state = plane->state;
+			struct drm_rect dest = {
+				.x1 = state->crtc_x,
+				.y1 = state->crtc_y,
+				.x2 = state->crtc_x + state->crtc_w,
+				.y2 = state->crtc_y + state->crtc_h,
+			};
+
+			meson_vpp_setup_interlace_vscaler_osd1(priv, &dest);
+		} else
+			meson_vpp_disable_interlace_vscaler_osd1(priv);
+
+		/* Enable OSD1 */
+		writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
+				    priv->io_base + _REG(VPP_MISC));
+
+		priv->viu.osd1_commit = false;
+	}
+
+	drm_crtc_handle_vblank(priv->crtc);
+
+	spin_lock_irqsave(&priv->drm->event_lock, flags);
+	if (meson_crtc->event) {
+		drm_crtc_send_vblank_event(priv->crtc, meson_crtc->event);
+		drm_crtc_vblank_put(priv->crtc);
+		meson_crtc->event = NULL;
+	}
+	spin_unlock_irqrestore(&priv->drm->event_lock, flags);
+}
+
+int meson_crtc_create(struct meson_drm *priv)
+{
+	struct meson_crtc *meson_crtc;
+	struct drm_crtc *crtc;
+	int ret;
+
+	meson_crtc = devm_kzalloc(priv->drm->dev, sizeof(*meson_crtc),
+				  GFP_KERNEL);
+	if (!meson_crtc)
+		return -ENOMEM;
+
+	meson_crtc->priv = priv;
+	crtc = &meson_crtc->base;
+	ret = drm_crtc_init_with_planes(priv->drm, crtc,
+					priv->primary_plane, NULL,
+					&meson_crtc_funcs, "meson_crtc");
+	if (ret) {
+		dev_err(priv->drm->dev, "Failed to init CRTC\n");
+		return ret;
+	}
+
+	drm_crtc_helper_add(crtc, &meson_crtc_helper_funcs);
+
+	priv->crtc = crtc;
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_crtc.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_crtc.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_crtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_crtc.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#ifndef __MESON_CRTC_H
+#define __MESON_CRTC_H
+
+#include "meson_drv.h"
+
+int meson_crtc_create(struct meson_drm *priv);
+
+void meson_crtc_irq(struct meson_drm *priv);
+
+#endif /* __MESON_CRTC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_fb_helper.h>
+
+#include "meson_drv.h"
+#include "meson_plane.h"
+#include "meson_crtc.h"
+#include "meson_venc_cvbs.h"
+
+#include "meson_vpp.h"
+#include "meson_viu.h"
+#include "meson_venc.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+#define DRIVER_NAME "meson"
+#define DRIVER_DESC "Amlogic Meson DRM driver"
+
+/*
+ * Video Processing Unit
+ *
+ * VPU Handles the Global Video Processing, it includes management of the
+ * clocks gates, blocks reset lines and power domains.
+ *
+ * What is missing :
+ * - Full reset of entire video processing HW blocks
+ * - Scaling and setup of the VPU clock
+ * - Bus clock gates
+ * - Powering up video processing HW blocks
+ * - Powering Up HDMI controller and PHY
+ */
+
+static void meson_fb_output_poll_changed(struct drm_device *dev)
+{
+	struct meson_drm *priv = dev->dev_private;
+
+	drm_fbdev_cma_hotplug_event(priv->fbdev);
+}
+
+static const struct drm_mode_config_funcs meson_mode_config_funcs = {
+	.output_poll_changed = meson_fb_output_poll_changed,
+	.atomic_check        = drm_atomic_helper_check,
+	.atomic_commit       = drm_atomic_helper_commit,
+	.fb_create           = drm_fb_cma_create,
+};
+
+static int meson_enable_vblank(struct drm_device *dev, unsigned int crtc)
+{
+	struct meson_drm *priv = dev->dev_private;
+
+	meson_venc_enable_vsync(priv);
+
+	return 0;
+}
+
+static void meson_disable_vblank(struct drm_device *dev, unsigned int crtc)
+{
+	struct meson_drm *priv = dev->dev_private;
+
+	meson_venc_disable_vsync(priv);
+}
+
+static irqreturn_t meson_irq(int irq, void *arg)
+{
+	struct drm_device *dev = arg;
+	struct meson_drm *priv = dev->dev_private;
+
+	(void)readl_relaxed(priv->io_base + _REG(VENC_INTFLAG));
+
+	meson_crtc_irq(priv);
+
+	return IRQ_HANDLED;
+}
+
+static const struct file_operations fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= no_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver meson_driver = {
+	.driver_features	= DRIVER_HAVE_IRQ | DRIVER_GEM |
+				  DRIVER_MODESET | DRIVER_PRIME |
+				  DRIVER_ATOMIC,
+
+	/* Vblank */
+	.enable_vblank		= meson_enable_vblank,
+	.disable_vblank		= meson_disable_vblank,
+	.get_vblank_counter	= drm_vblank_no_hw_counter,
+
+	/* IRQ */
+	.irq_handler		= meson_irq,
+
+	/* PRIME Ops */
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+
+	/* GEM Ops */
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.gem_free_object_unlocked = drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+
+	/* Misc */
+	.fops			= &fops,
+	.name			= DRIVER_NAME,
+	.desc			= DRIVER_DESC,
+	.date			= "20161109",
+	.major			= 1,
+	.minor			= 0,
+};
+
+static bool meson_vpu_has_available_connectors(struct device *dev)
+{
+	struct device_node *ep, *remote;
+
+	/* Parses each endpoint and check if remote exists */
+	for_each_endpoint_of_node(dev->of_node, ep) {
+		/* If the endpoint node exists, consider it enabled */
+		remote = of_graph_get_remote_port(ep);
+		if (remote)
+			return true;
+	}
+
+	return false;
+}
+
+static struct regmap_config meson_regmap_config = {
+	.reg_bits       = 32,
+	.val_bits       = 32,
+	.reg_stride     = 4,
+	.max_register   = 0x1000,
+};
+
+static int meson_drv_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct meson_drm *priv;
+	struct drm_device *drm;
+	struct resource *res;
+	void __iomem *regs;
+	int ret;
+
+	/* Checks if an output connector is available */
+	if (!meson_vpu_has_available_connectors(dev)) {
+		dev_err(dev, "No output connector available\n");
+		return -ENODEV;
+	}
+
+	drm = drm_dev_alloc(&meson_driver, dev);
+	if (IS_ERR(drm))
+		return PTR_ERR(drm);
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto free_drm;
+	}
+	drm->dev_private = priv;
+	priv->drm = drm;
+	priv->dev = dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpu");
+	regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	priv->io_base = regs;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hhi");
+	/* Simply ioremap since it may be a shared register zone */
+	regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (!regs)
+		return -EADDRNOTAVAIL;
+
+	priv->hhi = devm_regmap_init_mmio(dev, regs,
+					  &meson_regmap_config);
+	if (IS_ERR(priv->hhi)) {
+		dev_err(&pdev->dev, "Couldn't create the HHI regmap\n");
+		return PTR_ERR(priv->hhi);
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dmc");
+	/* Simply ioremap since it may be a shared register zone */
+	regs = devm_ioremap(dev, res->start, resource_size(res));
+	if (!regs)
+		return -EADDRNOTAVAIL;
+
+	priv->dmc = devm_regmap_init_mmio(dev, regs,
+					  &meson_regmap_config);
+	if (IS_ERR(priv->dmc)) {
+		dev_err(&pdev->dev, "Couldn't create the DMC regmap\n");
+		return PTR_ERR(priv->dmc);
+	}
+
+	priv->vsync_irq = platform_get_irq(pdev, 0);
+
+	drm_vblank_init(drm, 1);
+	drm_mode_config_init(drm);
+
+	/* Encoder Initialization */
+
+	ret = meson_venc_cvbs_create(priv);
+	if (ret)
+		goto free_drm;
+
+	/* Hardware Initialization */
+
+	meson_venc_init(priv);
+	meson_vpp_init(priv);
+	meson_viu_init(priv);
+
+	ret = meson_plane_create(priv);
+	if (ret)
+		goto free_drm;
+
+	ret = meson_crtc_create(priv);
+	if (ret)
+		goto free_drm;
+
+	ret = drm_irq_install(drm, priv->vsync_irq);
+	if (ret)
+		goto free_drm;
+
+	drm_mode_config_reset(drm);
+	drm->mode_config.max_width = 8192;
+	drm->mode_config.max_height = 8192;
+	drm->mode_config.funcs = &meson_mode_config_funcs;
+
+	priv->fbdev = drm_fbdev_cma_init(drm, 32,
+					 drm->mode_config.num_crtc,
+					 drm->mode_config.num_connector);
+	if (IS_ERR(priv->fbdev)) {
+		ret = PTR_ERR(priv->fbdev);
+		goto free_drm;
+	}
+
+	drm_kms_helper_poll_init(drm);
+
+	platform_set_drvdata(pdev, priv);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto free_drm;
+
+	return 0;
+
+free_drm:
+	drm_dev_unref(drm);
+
+	return ret;
+}
+
+static int meson_drv_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm = dev_get_drvdata(&pdev->dev);
+	struct meson_drm *priv = drm->dev_private;
+
+	drm_dev_unregister(drm);
+	drm_kms_helper_poll_fini(drm);
+	drm_fbdev_cma_fini(priv->fbdev);
+	drm_mode_config_cleanup(drm);
+	drm_vblank_cleanup(drm);
+	drm_dev_unref(drm);
+
+	return 0;
+}
+
+static const struct of_device_id dt_match[] = {
+	{ .compatible = "amlogic,meson-gxbb-vpu" },
+	{ .compatible = "amlogic,meson-gxl-vpu" },
+	{ .compatible = "amlogic,meson-gxm-vpu" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, dt_match);
+
+static struct platform_driver meson_drm_platform_driver = {
+	.probe      = meson_drv_probe,
+	.remove     = meson_drv_remove,
+	.driver     = {
+		.owner  = THIS_MODULE,
+		.name   = DRIVER_NAME,
+		.of_match_table = dt_match,
+	},
+};
+
+module_platform_driver(meson_drm_platform_driver);
+
+MODULE_AUTHOR("Jasper St. Pierre <jstpierre@mecheye.net>");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.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/>.
+ */
+
+#ifndef __MESON_DRV_H
+#define __MESON_DRV_H
+
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/of.h>
+#include <drm/drmP.h>
+
+struct meson_drm {
+	struct device *dev;
+	void __iomem *io_base;
+	struct regmap *hhi;
+	struct regmap *dmc;
+	int vsync_irq;
+
+	struct drm_device *drm;
+	struct drm_crtc *crtc;
+	struct drm_fbdev_cma *fbdev;
+	struct drm_plane *primary_plane;
+
+	/* Components Data */
+	struct {
+		bool osd1_enabled;
+		bool osd1_interlace;
+		bool osd1_commit;
+		uint32_t osd1_ctrl_stat;
+		uint32_t osd1_blk0_cfg[5];
+	} viu;
+
+	struct {
+		unsigned int current_mode;
+	} venc;
+};
+
+static inline int meson_vpu_is_compatible(struct meson_drm *priv,
+					  const char *compat)
+{
+	return of_device_is_compatible(priv->dev->of_node, compat);
+}
+
+#endif /* __MESON_DRV_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_plane.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_rect.h>
+
+#include "meson_plane.h"
+#include "meson_vpp.h"
+#include "meson_viu.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+struct meson_plane {
+	struct drm_plane base;
+	struct meson_drm *priv;
+};
+#define to_meson_plane(x) container_of(x, struct meson_plane, base)
+
+static int meson_plane_atomic_check(struct drm_plane *plane,
+				    struct drm_plane_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_rect clip = { 0, };
+
+	if (!state->crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	clip.x2 = crtc_state->mode.hdisplay;
+	clip.y2 = crtc_state->mode.vdisplay;
+
+	return drm_plane_helper_check_state(state, &clip,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    true, true);
+}
+
+/* Takes a fixed 16.16 number and converts it to integer. */
+static inline int64_t fixed16_to_int(int64_t value)
+{
+	return value >> 16;
+}
+
+static void meson_plane_atomic_update(struct drm_plane *plane,
+				      struct drm_plane_state *old_state)
+{
+	struct meson_plane *meson_plane = to_meson_plane(plane);
+	struct drm_plane_state *state = plane->state;
+	struct drm_framebuffer *fb = state->fb;
+	struct meson_drm *priv = meson_plane->priv;
+	struct drm_gem_cma_object *gem;
+	struct drm_rect src = {
+		.x1 = (state->src_x),
+		.y1 = (state->src_y),
+		.x2 = (state->src_x + state->src_w),
+		.y2 = (state->src_y + state->src_h),
+	};
+	struct drm_rect dest = {
+		.x1 = state->crtc_x,
+		.y1 = state->crtc_y,
+		.x2 = state->crtc_x + state->crtc_w,
+		.y2 = state->crtc_y + state->crtc_h,
+	};
+	unsigned long flags;
+
+	/*
+	 * Update Coordinates
+	 * Update Formats
+	 * Update Buffer
+	 * Enable Plane
+	 */
+	spin_lock_irqsave(&priv->drm->event_lock, flags);
+
+	/* Enable OSD and BLK0, set max global alpha */
+	priv->viu.osd1_ctrl_stat = OSD_ENABLE |
+				   (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
+				   OSD_BLK0_ENABLE;
+
+	/* Set up BLK0 to point to the right canvas */
+	priv->viu.osd1_blk0_cfg[0] = ((MESON_CANVAS_ID_OSD1 << OSD_CANVAS_SEL) |
+				      OSD_ENDIANNESS_LE);
+
+	/* On GXBB, Use the old non-HDR RGB2YUV converter */
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+		priv->viu.osd1_blk0_cfg[0] |= OSD_OUTPUT_COLOR_RGB;
+
+	switch (fb->pixel_format) {
+	case DRM_FORMAT_XRGB8888:
+		/* For XRGB, replace the pixel's alpha by 0xFF */
+		writel_bits_relaxed(OSD_REPLACE_EN, OSD_REPLACE_EN,
+				    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
+		priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
+					      OSD_COLOR_MATRIX_32_ARGB;
+		break;
+	case DRM_FORMAT_ARGB8888:
+		/* For ARGB, use the pixel's alpha */
+		writel_bits_relaxed(OSD_REPLACE_EN, 0,
+				    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
+		priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_32 |
+					      OSD_COLOR_MATRIX_32_ARGB;
+		break;
+	case DRM_FORMAT_RGB888:
+		priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_24 |
+					      OSD_COLOR_MATRIX_24_RGB;
+		break;
+	case DRM_FORMAT_RGB565:
+		priv->viu.osd1_blk0_cfg[0] |= OSD_BLK_MODE_16 |
+					      OSD_COLOR_MATRIX_16_RGB565;
+		break;
+	};
+
+	if (state->crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) {
+		priv->viu.osd1_interlace = true;
+
+		dest.y1 /= 2;
+		dest.y2 /= 2;
+	} else
+		priv->viu.osd1_interlace = false;
+
+	/*
+	 * The format of these registers is (x2 << 16 | x1),
+	 * where x2 is exclusive.
+	 * e.g. +30x1920 would be (1919 << 16) | 30
+	 */
+	priv->viu.osd1_blk0_cfg[1] = ((fixed16_to_int(src.x2) - 1) << 16) |
+					fixed16_to_int(src.x1);
+	priv->viu.osd1_blk0_cfg[2] = ((fixed16_to_int(src.y2) - 1) << 16) |
+					fixed16_to_int(src.y1);
+	priv->viu.osd1_blk0_cfg[3] = ((dest.x2 - 1) << 16) | dest.x1;
+	priv->viu.osd1_blk0_cfg[4] = ((dest.y2 - 1) << 16) | dest.y1;
+
+	/* Update Canvas with buffer address */
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1,
+			   gem->paddr, fb->pitches[0],
+			   fb->height, MESON_CANVAS_WRAP_NONE,
+			   MESON_CANVAS_BLKMODE_LINEAR);
+
+	spin_unlock_irqrestore(&priv->drm->event_lock, flags);
+}
+
+static void meson_plane_atomic_disable(struct drm_plane *plane,
+				       struct drm_plane_state *old_state)
+{
+	struct meson_plane *meson_plane = to_meson_plane(plane);
+	struct meson_drm *priv = meson_plane->priv;
+
+	/* Disable OSD1 */
+	writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+}
+
+static const struct drm_plane_helper_funcs meson_plane_helper_funcs = {
+	.atomic_check	= meson_plane_atomic_check,
+	.atomic_disable	= meson_plane_atomic_disable,
+	.atomic_update	= meson_plane_atomic_update,
+};
+
+static const struct drm_plane_funcs meson_plane_funcs = {
+	.update_plane		= drm_atomic_helper_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.destroy		= drm_plane_cleanup,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static const uint32_t supported_drm_formats[] = {
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGB565,
+};
+
+int meson_plane_create(struct meson_drm *priv)
+{
+	struct meson_plane *meson_plane;
+	struct drm_plane *plane;
+
+	meson_plane = devm_kzalloc(priv->drm->dev, sizeof(*meson_plane),
+				   GFP_KERNEL);
+	if (!meson_plane)
+		return -ENOMEM;
+
+	meson_plane->priv = priv;
+	plane = &meson_plane->base;
+
+	drm_universal_plane_init(priv->drm, plane, 0xFF,
+				 &meson_plane_funcs,
+				 supported_drm_formats,
+				 ARRAY_SIZE(supported_drm_formats),
+				 DRM_PLANE_TYPE_PRIMARY, "meson_primary_plane");
+
+	drm_plane_helper_add(plane, &meson_plane_helper_funcs);
+
+	priv->primary_plane = plane;
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_plane.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_plane.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_plane.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_plane.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#ifndef __MESON_PLANE_H
+#define __MESON_PLANE_H
+
+#include "meson_drv.h"
+
+int meson_plane_create(struct meson_drm *priv);
+
+#endif /* __MESON_PLANE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_registers.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_registers.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_registers.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_registers.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1395 @@
+/*
+ * Copyright (C) 2015 Amlogic, 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.
+ *
+ */
+
+#ifndef __MESON_REGISTERS_H
+#define __MESON_REGISTERS_H
+
+/* Shift all registers by 2 */
+#define _REG(reg)	((reg) << 2)
+
+#define writel_bits_relaxed(mask, val, addr) \
+	writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr)
+
+/* vpp2 */
+#define VPP2_DUMMY_DATA 0x1900
+#define VPP2_LINE_IN_LENGTH 0x1901
+#define VPP2_PIC_IN_HEIGHT 0x1902
+#define VPP2_SCALE_COEF_IDX 0x1903
+#define VPP2_SCALE_COEF 0x1904
+#define VPP2_VSC_REGION12_STARTP 0x1905
+#define VPP2_VSC_REGION34_STARTP 0x1906
+#define VPP2_VSC_REGION4_ENDP 0x1907
+#define VPP2_VSC_START_PHASE_STEP 0x1908
+#define VPP2_VSC_REGION0_PHASE_SLOPE 0x1909
+#define VPP2_VSC_REGION1_PHASE_SLOPE 0x190a
+#define VPP2_VSC_REGION3_PHASE_SLOPE 0x190b
+#define VPP2_VSC_REGION4_PHASE_SLOPE 0x190c
+#define VPP2_VSC_PHASE_CTRL 0x190d
+#define VPP2_VSC_INI_PHASE 0x190e
+#define VPP2_HSC_REGION12_STARTP 0x1910
+#define VPP2_HSC_REGION34_STARTP 0x1911
+#define VPP2_HSC_REGION4_ENDP 0x1912
+#define VPP2_HSC_START_PHASE_STEP 0x1913
+#define VPP2_HSC_REGION0_PHASE_SLOPE 0x1914
+#define VPP2_HSC_REGION1_PHASE_SLOPE 0x1915
+#define VPP2_HSC_REGION3_PHASE_SLOPE 0x1916
+#define VPP2_HSC_REGION4_PHASE_SLOPE 0x1917
+#define VPP2_HSC_PHASE_CTRL 0x1918
+#define VPP2_SC_MISC 0x1919
+#define VPP2_PREBLEND_VD1_H_START_END 0x191a
+#define VPP2_PREBLEND_VD1_V_START_END 0x191b
+#define VPP2_POSTBLEND_VD1_H_START_END 0x191c
+#define VPP2_POSTBLEND_VD1_V_START_END 0x191d
+#define VPP2_PREBLEND_H_SIZE 0x1920
+#define VPP2_POSTBLEND_H_SIZE 0x1921
+#define VPP2_HOLD_LINES 0x1922
+#define VPP2_BLEND_ONECOLOR_CTRL 0x1923
+#define VPP2_PREBLEND_CURRENT_XY 0x1924
+#define VPP2_POSTBLEND_CURRENT_XY 0x1925
+#define VPP2_MISC 0x1926
+#define VPP2_OFIFO_SIZE 0x1927
+#define VPP2_FIFO_STATUS 0x1928
+#define VPP2_SMOKE_CTRL 0x1929
+#define VPP2_SMOKE1_VAL 0x192a
+#define VPP2_SMOKE2_VAL 0x192b
+#define VPP2_SMOKE1_H_START_END 0x192d
+#define VPP2_SMOKE1_V_START_END 0x192e
+#define VPP2_SMOKE2_H_START_END 0x192f
+#define VPP2_SMOKE2_V_START_END 0x1930
+#define VPP2_SCO_FIFO_CTRL 0x1933
+#define VPP2_HSC_PHASE_CTRL1 0x1934
+#define VPP2_HSC_INI_PAT_CTRL 0x1935
+#define VPP2_VADJ_CTRL 0x1940
+#define VPP2_VADJ1_Y 0x1941
+#define VPP2_VADJ1_MA_MB 0x1942
+#define VPP2_VADJ1_MC_MD 0x1943
+#define VPP2_VADJ2_Y 0x1944
+#define VPP2_VADJ2_MA_MB 0x1945
+#define VPP2_VADJ2_MC_MD 0x1946
+#define VPP2_MATRIX_PROBE_COLOR 0x195c
+#define VPP2_MATRIX_HL_COLOR 0x195d
+#define VPP2_MATRIX_PROBE_POS 0x195e
+#define VPP2_MATRIX_CTRL 0x195f
+#define VPP2_MATRIX_COEF00_01 0x1960
+#define VPP2_MATRIX_COEF02_10 0x1961
+#define VPP2_MATRIX_COEF11_12 0x1962
+#define VPP2_MATRIX_COEF20_21 0x1963
+#define VPP2_MATRIX_COEF22 0x1964
+#define VPP2_MATRIX_OFFSET0_1 0x1965
+#define VPP2_MATRIX_OFFSET2 0x1966
+#define VPP2_MATRIX_PRE_OFFSET0_1 0x1967
+#define VPP2_MATRIX_PRE_OFFSET2 0x1968
+#define VPP2_DUMMY_DATA1 0x1969
+#define VPP2_GAINOFF_CTRL0 0x196a
+#define VPP2_GAINOFF_CTRL1 0x196b
+#define VPP2_GAINOFF_CTRL2 0x196c
+#define VPP2_GAINOFF_CTRL3 0x196d
+#define VPP2_GAINOFF_CTRL4 0x196e
+#define VPP2_CHROMA_ADDR_PORT 0x1970
+#define VPP2_CHROMA_DATA_PORT 0x1971
+#define VPP2_GCLK_CTRL0 0x1972
+#define VPP2_GCLK_CTRL1 0x1973
+#define VPP2_SC_GCLK_CTRL 0x1974
+#define VPP2_MISC1 0x1976
+#define VPP2_DNLP_CTRL_00 0x1981
+#define VPP2_DNLP_CTRL_01 0x1982
+#define VPP2_DNLP_CTRL_02 0x1983
+#define VPP2_DNLP_CTRL_03 0x1984
+#define VPP2_DNLP_CTRL_04 0x1985
+#define VPP2_DNLP_CTRL_05 0x1986
+#define VPP2_DNLP_CTRL_06 0x1987
+#define VPP2_DNLP_CTRL_07 0x1988
+#define VPP2_DNLP_CTRL_08 0x1989
+#define VPP2_DNLP_CTRL_09 0x198a
+#define VPP2_DNLP_CTRL_10 0x198b
+#define VPP2_DNLP_CTRL_11 0x198c
+#define VPP2_DNLP_CTRL_12 0x198d
+#define VPP2_DNLP_CTRL_13 0x198e
+#define VPP2_DNLP_CTRL_14 0x198f
+#define VPP2_DNLP_CTRL_15 0x1990
+#define VPP2_VE_ENABLE_CTRL 0x19a1
+#define VPP2_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x19a2
+#define VPP2_VE_DEMO_CENTER_BAR 0x19a3
+#define VPP2_VE_H_V_SIZE 0x19a4
+#define VPP2_VDO_MEAS_CTRL 0x19a8
+#define VPP2_VDO_MEAS_VS_COUNT_HI 0x19a9
+#define VPP2_VDO_MEAS_VS_COUNT_LO 0x19aa
+#define VPP2_OSD_VSC_PHASE_STEP 0x19c0
+#define VPP2_OSD_VSC_INI_PHASE 0x19c1
+#define VPP2_OSD_VSC_CTRL0 0x19c2
+#define VPP2_OSD_HSC_PHASE_STEP 0x19c3
+#define VPP2_OSD_HSC_INI_PHASE 0x19c4
+#define VPP2_OSD_HSC_CTRL0 0x19c5
+#define VPP2_OSD_HSC_INI_PAT_CTRL 0x19c6
+#define VPP2_OSD_SC_DUMMY_DATA 0x19c7
+#define VPP2_OSD_SC_CTRL0 0x19c8
+#define VPP2_OSD_SCI_WH_M1 0x19c9
+#define VPP2_OSD_SCO_H_START_END 0x19ca
+#define VPP2_OSD_SCO_V_START_END 0x19cb
+#define VPP2_OSD_SCALE_COEF_IDX 0x19cc
+#define VPP2_OSD_SCALE_COEF 0x19cd
+#define VPP2_INT_LINE_NUM 0x19ce
+
+/* viu */
+#define VIU_ADDR_START 0x1a00
+#define VIU_ADDR_END 0x1aff
+#define VIU_SW_RESET 0x1a01
+#define VIU_MISC_CTRL0 0x1a06
+#define VIU_MISC_CTRL1 0x1a07
+#define D2D3_INTF_LENGTH 0x1a08
+#define D2D3_INTF_CTRL0 0x1a09
+#define VIU_OSD1_CTRL_STAT 0x1a10
+#define VIU_OSD1_CTRL_STAT2 0x1a2d
+#define VIU_OSD1_COLOR_ADDR 0x1a11
+#define VIU_OSD1_COLOR 0x1a12
+#define VIU_OSD1_TCOLOR_AG0 0x1a17
+#define VIU_OSD1_TCOLOR_AG1 0x1a18
+#define VIU_OSD1_TCOLOR_AG2 0x1a19
+#define VIU_OSD1_TCOLOR_AG3 0x1a1a
+#define VIU_OSD1_BLK0_CFG_W0 0x1a1b
+#define VIU_OSD1_BLK1_CFG_W0 0x1a1f
+#define VIU_OSD1_BLK2_CFG_W0 0x1a23
+#define VIU_OSD1_BLK3_CFG_W0 0x1a27
+#define VIU_OSD1_BLK0_CFG_W1 0x1a1c
+#define VIU_OSD1_BLK1_CFG_W1 0x1a20
+#define VIU_OSD1_BLK2_CFG_W1 0x1a24
+#define VIU_OSD1_BLK3_CFG_W1 0x1a28
+#define VIU_OSD1_BLK0_CFG_W2 0x1a1d
+#define VIU_OSD1_BLK1_CFG_W2 0x1a21
+#define VIU_OSD1_BLK2_CFG_W2 0x1a25
+#define VIU_OSD1_BLK3_CFG_W2 0x1a29
+#define VIU_OSD1_BLK0_CFG_W3 0x1a1e
+#define VIU_OSD1_BLK1_CFG_W3 0x1a22
+#define VIU_OSD1_BLK2_CFG_W3 0x1a26
+#define VIU_OSD1_BLK3_CFG_W3 0x1a2a
+#define VIU_OSD1_BLK0_CFG_W4 0x1a13
+#define VIU_OSD1_BLK1_CFG_W4 0x1a14
+#define VIU_OSD1_BLK2_CFG_W4 0x1a15
+#define VIU_OSD1_BLK3_CFG_W4 0x1a16
+#define VIU_OSD1_FIFO_CTRL_STAT 0x1a2b
+#define VIU_OSD1_TEST_RDDATA 0x1a2c
+#define VIU_OSD1_PROT_CTRL 0x1a2e
+#define VIU_OSD2_CTRL_STAT 0x1a30
+#define VIU_OSD2_CTRL_STAT2 0x1a4d
+#define VIU_OSD2_COLOR_ADDR 0x1a31
+#define VIU_OSD2_COLOR 0x1a32
+#define VIU_OSD2_HL1_H_START_END 0x1a33
+#define VIU_OSD2_HL1_V_START_END 0x1a34
+#define VIU_OSD2_HL2_H_START_END 0x1a35
+#define VIU_OSD2_HL2_V_START_END 0x1a36
+#define VIU_OSD2_TCOLOR_AG0 0x1a37
+#define VIU_OSD2_TCOLOR_AG1 0x1a38
+#define VIU_OSD2_TCOLOR_AG2 0x1a39
+#define VIU_OSD2_TCOLOR_AG3 0x1a3a
+#define VIU_OSD2_BLK0_CFG_W0 0x1a3b
+#define VIU_OSD2_BLK1_CFG_W0 0x1a3f
+#define VIU_OSD2_BLK2_CFG_W0 0x1a43
+#define VIU_OSD2_BLK3_CFG_W0 0x1a47
+#define VIU_OSD2_BLK0_CFG_W1 0x1a3c
+#define VIU_OSD2_BLK1_CFG_W1 0x1a40
+#define VIU_OSD2_BLK2_CFG_W1 0x1a44
+#define VIU_OSD2_BLK3_CFG_W1 0x1a48
+#define VIU_OSD2_BLK0_CFG_W2 0x1a3d
+#define VIU_OSD2_BLK1_CFG_W2 0x1a41
+#define VIU_OSD2_BLK2_CFG_W2 0x1a45
+#define VIU_OSD2_BLK3_CFG_W2 0x1a49
+#define VIU_OSD2_BLK0_CFG_W3 0x1a3e
+#define VIU_OSD2_BLK1_CFG_W3 0x1a42
+#define VIU_OSD2_BLK2_CFG_W3 0x1a46
+#define VIU_OSD2_BLK3_CFG_W3 0x1a4a
+#define VIU_OSD2_BLK0_CFG_W4 0x1a64
+#define VIU_OSD2_BLK1_CFG_W4 0x1a65
+#define VIU_OSD2_BLK2_CFG_W4 0x1a66
+#define VIU_OSD2_BLK3_CFG_W4 0x1a67
+#define VIU_OSD2_FIFO_CTRL_STAT 0x1a4b
+#define VIU_OSD2_TEST_RDDATA 0x1a4c
+#define VIU_OSD2_PROT_CTRL 0x1a4e
+
+#define VD1_IF0_GEN_REG 0x1a50
+#define VD1_IF0_CANVAS0 0x1a51
+#define VD1_IF0_CANVAS1 0x1a52
+#define VD1_IF0_LUMA_X0 0x1a53
+#define VD1_IF0_LUMA_Y0 0x1a54
+#define VD1_IF0_CHROMA_X0 0x1a55
+#define VD1_IF0_CHROMA_Y0 0x1a56
+#define VD1_IF0_LUMA_X1 0x1a57
+#define VD1_IF0_LUMA_Y1 0x1a58
+#define VD1_IF0_CHROMA_X1 0x1a59
+#define VD1_IF0_CHROMA_Y1 0x1a5a
+#define VD1_IF0_RPT_LOOP 0x1a5b
+#define VD1_IF0_LUMA0_RPT_PAT 0x1a5c
+#define VD1_IF0_CHROMA0_RPT_PAT 0x1a5d
+#define VD1_IF0_LUMA1_RPT_PAT 0x1a5e
+#define VD1_IF0_CHROMA1_RPT_PAT 0x1a5f
+#define VD1_IF0_LUMA_PSEL 0x1a60
+#define VD1_IF0_CHROMA_PSEL 0x1a61
+#define VD1_IF0_DUMMY_PIXEL 0x1a62
+#define VD1_IF0_LUMA_FIFO_SIZE 0x1a63
+#define VD1_IF0_RANGE_MAP_Y 0x1a6a
+#define VD1_IF0_RANGE_MAP_CB 0x1a6b
+#define VD1_IF0_RANGE_MAP_CR 0x1a6c
+#define VD1_IF0_GEN_REG2 0x1a6d
+#define VD1_IF0_PROT_CNTL 0x1a6e
+#define VIU_VD1_FMT_CTRL 0x1a68
+#define VIU_VD1_FMT_W 0x1a69
+#define VD2_IF0_GEN_REG 0x1a70
+#define VD2_IF0_CANVAS0 0x1a71
+#define VD2_IF0_CANVAS1 0x1a72
+#define VD2_IF0_LUMA_X0 0x1a73
+#define VD2_IF0_LUMA_Y0 0x1a74
+#define VD2_IF0_CHROMA_X0 0x1a75
+#define VD2_IF0_CHROMA_Y0 0x1a76
+#define VD2_IF0_LUMA_X1 0x1a77
+#define VD2_IF0_LUMA_Y1 0x1a78
+#define VD2_IF0_CHROMA_X1 0x1a79
+#define VD2_IF0_CHROMA_Y1 0x1a7a
+#define VD2_IF0_RPT_LOOP 0x1a7b
+#define VD2_IF0_LUMA0_RPT_PAT 0x1a7c
+#define VD2_IF0_CHROMA0_RPT_PAT 0x1a7d
+#define VD2_IF0_LUMA1_RPT_PAT 0x1a7e
+#define VD2_IF0_CHROMA1_RPT_PAT 0x1a7f
+#define VD2_IF0_LUMA_PSEL 0x1a80
+#define VD2_IF0_CHROMA_PSEL 0x1a81
+#define VD2_IF0_DUMMY_PIXEL 0x1a82
+#define VD2_IF0_LUMA_FIFO_SIZE 0x1a83
+#define VD2_IF0_RANGE_MAP_Y 0x1a8a
+#define VD2_IF0_RANGE_MAP_CB 0x1a8b
+#define VD2_IF0_RANGE_MAP_CR 0x1a8c
+#define VD2_IF0_GEN_REG2 0x1a8d
+#define VD2_IF0_PROT_CNTL 0x1a8e
+#define VIU_VD2_FMT_CTRL 0x1a88
+#define VIU_VD2_FMT_W 0x1a89
+
+/* VIU Matrix Registers */
+#define VIU_OSD1_MATRIX_CTRL 0x1a90
+#define VIU_OSD1_MATRIX_COEF00_01 0x1a91
+#define VIU_OSD1_MATRIX_COEF02_10 0x1a92
+#define VIU_OSD1_MATRIX_COEF11_12 0x1a93
+#define VIU_OSD1_MATRIX_COEF20_21 0x1a94
+#define VIU_OSD1_MATRIX_COLMOD_COEF42 0x1a95
+#define VIU_OSD1_MATRIX_OFFSET0_1 0x1a96
+#define VIU_OSD1_MATRIX_OFFSET2 0x1a97
+#define VIU_OSD1_MATRIX_PRE_OFFSET0_1 0x1a98
+#define VIU_OSD1_MATRIX_PRE_OFFSET2 0x1a99
+#define VIU_OSD1_MATRIX_COEF22_30 0x1a9d
+#define VIU_OSD1_MATRIX_COEF31_32 0x1a9e
+#define VIU_OSD1_MATRIX_COEF40_41 0x1a9f
+#define VIU_OSD1_EOTF_CTL 0x1ad4
+#define VIU_OSD1_EOTF_COEF00_01 0x1ad5
+#define VIU_OSD1_EOTF_COEF02_10 0x1ad6
+#define VIU_OSD1_EOTF_COEF11_12 0x1ad7
+#define VIU_OSD1_EOTF_COEF20_21 0x1ad8
+#define VIU_OSD1_EOTF_COEF22_RS 0x1ad9
+#define VIU_OSD1_EOTF_LUT_ADDR_PORT 0x1ada
+#define VIU_OSD1_EOTF_LUT_DATA_PORT 0x1adb
+#define VIU_OSD1_OETF_CTL 0x1adc
+#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add
+#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade
+
+/* vpp */
+#define VPP_DUMMY_DATA 0x1d00
+#define VPP_LINE_IN_LENGTH 0x1d01
+#define VPP_PIC_IN_HEIGHT 0x1d02
+#define VPP_SCALE_COEF_IDX 0x1d03
+#define VPP_SCALE_COEF 0x1d04
+#define VPP_VSC_REGION12_STARTP 0x1d05
+#define VPP_VSC_REGION34_STARTP 0x1d06
+#define VPP_VSC_REGION4_ENDP 0x1d07
+#define VPP_VSC_START_PHASE_STEP 0x1d08
+#define VPP_VSC_REGION0_PHASE_SLOPE 0x1d09
+#define VPP_VSC_REGION1_PHASE_SLOPE 0x1d0a
+#define VPP_VSC_REGION3_PHASE_SLOPE 0x1d0b
+#define VPP_VSC_REGION4_PHASE_SLOPE 0x1d0c
+#define VPP_VSC_PHASE_CTRL 0x1d0d
+#define VPP_VSC_INI_PHASE 0x1d0e
+#define VPP_HSC_REGION12_STARTP 0x1d10
+#define VPP_HSC_REGION34_STARTP 0x1d11
+#define VPP_HSC_REGION4_ENDP 0x1d12
+#define VPP_HSC_START_PHASE_STEP 0x1d13
+#define VPP_HSC_REGION0_PHASE_SLOPE 0x1d14
+#define VPP_HSC_REGION1_PHASE_SLOPE 0x1d15
+#define VPP_HSC_REGION3_PHASE_SLOPE 0x1d16
+#define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17
+#define VPP_HSC_PHASE_CTRL 0x1d18
+#define VPP_SC_MISC 0x1d19
+#define VPP_PREBLEND_VD1_H_START_END 0x1d1a
+#define VPP_PREBLEND_VD1_V_START_END 0x1d1b
+#define VPP_POSTBLEND_VD1_H_START_END 0x1d1c
+#define VPP_POSTBLEND_VD1_V_START_END 0x1d1d
+#define VPP_BLEND_VD2_H_START_END 0x1d1e
+#define VPP_BLEND_VD2_V_START_END 0x1d1f
+#define VPP_PREBLEND_H_SIZE 0x1d20
+#define VPP_POSTBLEND_H_SIZE 0x1d21
+#define VPP_HOLD_LINES 0x1d22
+#define VPP_BLEND_ONECOLOR_CTRL 0x1d23
+#define VPP_PREBLEND_CURRENT_XY 0x1d24
+#define VPP_POSTBLEND_CURRENT_XY 0x1d25
+#define VPP_MISC 0x1d26
+#define		VPP_PREBLEND_ENABLE	BIT(6)
+#define		VPP_POSTBLEND_ENABLE	BIT(7)
+#define		VPP_OSD2_ALPHA_PREMULT	BIT(8)
+#define		VPP_OSD1_ALPHA_PREMULT	BIT(9)
+#define		VPP_VD1_POSTBLEND	BIT(10)
+#define		VPP_VD2_POSTBLEND	BIT(11)
+#define		VPP_OSD1_POSTBLEND	BIT(12)
+#define		VPP_OSD2_POSTBLEND	BIT(13)
+#define		VPP_VD1_PREBLEND	BIT(14)
+#define		VPP_VD2_PREBLEND	BIT(15)
+#define		VPP_OSD1_PREBLEND	BIT(16)
+#define		VPP_OSD2_PREBLEND	BIT(17)
+#define VPP_OFIFO_SIZE 0x1d27
+#define VPP_FIFO_STATUS 0x1d28
+#define VPP_SMOKE_CTRL 0x1d29
+#define VPP_SMOKE1_VAL 0x1d2a
+#define VPP_SMOKE2_VAL 0x1d2b
+#define VPP_SMOKE3_VAL 0x1d2c
+#define VPP_SMOKE1_H_START_END 0x1d2d
+#define VPP_SMOKE1_V_START_END 0x1d2e
+#define VPP_SMOKE2_H_START_END 0x1d2f
+#define VPP_SMOKE2_V_START_END 0x1d30
+#define VPP_SMOKE3_H_START_END 0x1d31
+#define VPP_SMOKE3_V_START_END 0x1d32
+#define VPP_SCO_FIFO_CTRL 0x1d33
+#define VPP_HSC_PHASE_CTRL1 0x1d34
+#define VPP_HSC_INI_PAT_CTRL 0x1d35
+#define VPP_VADJ_CTRL 0x1d40
+#define VPP_VADJ1_Y 0x1d41
+#define VPP_VADJ1_MA_MB 0x1d42
+#define VPP_VADJ1_MC_MD 0x1d43
+#define VPP_VADJ2_Y 0x1d44
+#define VPP_VADJ2_MA_MB 0x1d45
+#define VPP_VADJ2_MC_MD 0x1d46
+#define VPP_HSHARP_CTRL 0x1d50
+#define VPP_HSHARP_LUMA_THRESH01 0x1d51
+#define VPP_HSHARP_LUMA_THRESH23 0x1d52
+#define VPP_HSHARP_CHROMA_THRESH01 0x1d53
+#define VPP_HSHARP_CHROMA_THRESH23 0x1d54
+#define VPP_HSHARP_LUMA_GAIN 0x1d55
+#define VPP_HSHARP_CHROMA_GAIN 0x1d56
+#define VPP_MATRIX_PROBE_COLOR 0x1d5c
+#define VPP_MATRIX_HL_COLOR 0x1d5d
+#define VPP_MATRIX_PROBE_POS 0x1d5e
+#define VPP_MATRIX_CTRL 0x1d5f
+#define VPP_MATRIX_COEF00_01 0x1d60
+#define VPP_MATRIX_COEF02_10 0x1d61
+#define VPP_MATRIX_COEF11_12 0x1d62
+#define VPP_MATRIX_COEF20_21 0x1d63
+#define VPP_MATRIX_COEF22 0x1d64
+#define VPP_MATRIX_OFFSET0_1 0x1d65
+#define VPP_MATRIX_OFFSET2 0x1d66
+#define VPP_MATRIX_PRE_OFFSET0_1 0x1d67
+#define VPP_MATRIX_PRE_OFFSET2 0x1d68
+#define VPP_DUMMY_DATA1 0x1d69
+#define VPP_GAINOFF_CTRL0 0x1d6a
+#define VPP_GAINOFF_CTRL1 0x1d6b
+#define VPP_GAINOFF_CTRL2 0x1d6c
+#define VPP_GAINOFF_CTRL3 0x1d6d
+#define VPP_GAINOFF_CTRL4 0x1d6e
+#define VPP_CHROMA_ADDR_PORT 0x1d70
+#define VPP_CHROMA_DATA_PORT 0x1d71
+#define VPP_GCLK_CTRL0 0x1d72
+#define VPP_GCLK_CTRL1 0x1d73
+#define VPP_SC_GCLK_CTRL 0x1d74
+#define VPP_MISC1 0x1d76
+#define VPP_BLACKEXT_CTRL 0x1d80
+#define VPP_DNLP_CTRL_00 0x1d81
+#define VPP_DNLP_CTRL_01 0x1d82
+#define VPP_DNLP_CTRL_02 0x1d83
+#define VPP_DNLP_CTRL_03 0x1d84
+#define VPP_DNLP_CTRL_04 0x1d85
+#define VPP_DNLP_CTRL_05 0x1d86
+#define VPP_DNLP_CTRL_06 0x1d87
+#define VPP_DNLP_CTRL_07 0x1d88
+#define VPP_DNLP_CTRL_08 0x1d89
+#define VPP_DNLP_CTRL_09 0x1d8a
+#define VPP_DNLP_CTRL_10 0x1d8b
+#define VPP_DNLP_CTRL_11 0x1d8c
+#define VPP_DNLP_CTRL_12 0x1d8d
+#define VPP_DNLP_CTRL_13 0x1d8e
+#define VPP_DNLP_CTRL_14 0x1d8f
+#define VPP_DNLP_CTRL_15 0x1d90
+#define VPP_PEAKING_HGAIN 0x1d91
+#define VPP_PEAKING_VGAIN 0x1d92
+#define VPP_PEAKING_NLP_1 0x1d93
+#define VPP_DOLBY_CTRL 0x1d93
+#define VPP_PEAKING_NLP_2 0x1d94
+#define VPP_PEAKING_NLP_3 0x1d95
+#define VPP_PEAKING_NLP_4 0x1d96
+#define VPP_PEAKING_NLP_5 0x1d97
+#define VPP_SHARP_LIMIT 0x1d98
+#define VPP_VLTI_CTRL 0x1d99
+#define VPP_HLTI_CTRL 0x1d9a
+#define VPP_CTI_CTRL 0x1d9b
+#define VPP_BLUE_STRETCH_1 0x1d9c
+#define VPP_BLUE_STRETCH_2 0x1d9d
+#define VPP_BLUE_STRETCH_3 0x1d9e
+#define VPP_CCORING_CTRL 0x1da0
+#define VPP_VE_ENABLE_CTRL 0x1da1
+#define VPP_VE_DEMO_LEFT_TOP_SCREEN_WIDTH 0x1da2
+#define VPP_VE_DEMO_CENTER_BAR 0x1da3
+#define VPP_VE_H_V_SIZE 0x1da4
+#define VPP_VDO_MEAS_CTRL 0x1da8
+#define VPP_VDO_MEAS_VS_COUNT_HI 0x1da9
+#define VPP_VDO_MEAS_VS_COUNT_LO 0x1daa
+#define VPP_INPUT_CTRL 0x1dab
+#define VPP_CTI_CTRL2 0x1dac
+#define VPP_PEAKING_SAT_THD1 0x1dad
+#define VPP_PEAKING_SAT_THD2 0x1dae
+#define VPP_PEAKING_SAT_THD3 0x1daf
+#define VPP_PEAKING_SAT_THD4 0x1db0
+#define VPP_PEAKING_SAT_THD5 0x1db1
+#define VPP_PEAKING_SAT_THD6 0x1db2
+#define VPP_PEAKING_SAT_THD7 0x1db3
+#define VPP_PEAKING_SAT_THD8 0x1db4
+#define VPP_PEAKING_SAT_THD9 0x1db5
+#define VPP_PEAKING_GAIN_ADD1 0x1db6
+#define VPP_PEAKING_GAIN_ADD2 0x1db7
+#define VPP_PEAKING_DNLP 0x1db8
+#define VPP_SHARP_DEMO_WIN_CTRL1 0x1db9
+#define VPP_SHARP_DEMO_WIN_CTRL2 0x1dba
+#define VPP_FRONT_HLTI_CTRL 0x1dbb
+#define VPP_FRONT_CTI_CTRL 0x1dbc
+#define VPP_FRONT_CTI_CTRL2 0x1dbd
+#define VPP_OSD_VSC_PHASE_STEP 0x1dc0
+#define VPP_OSD_VSC_INI_PHASE 0x1dc1
+#define VPP_OSD_VSC_CTRL0 0x1dc2
+#define VPP_OSD_HSC_PHASE_STEP 0x1dc3
+#define VPP_OSD_HSC_INI_PHASE 0x1dc4
+#define VPP_OSD_HSC_CTRL0 0x1dc5
+#define VPP_OSD_HSC_INI_PAT_CTRL 0x1dc6
+#define VPP_OSD_SC_DUMMY_DATA 0x1dc7
+#define VPP_OSD_SC_CTRL0 0x1dc8
+#define VPP_OSD_SCI_WH_M1 0x1dc9
+#define VPP_OSD_SCO_H_START_END 0x1dca
+#define VPP_OSD_SCO_V_START_END 0x1dcb
+#define VPP_OSD_SCALE_COEF_IDX 0x1dcc
+#define VPP_OSD_SCALE_COEF 0x1dcd
+#define VPP_INT_LINE_NUM 0x1dce
+
+/* viu2 */
+#define VIU2_ADDR_START 0x1e00
+#define VIU2_ADDR_END 0x1eff
+#define VIU2_SW_RESET 0x1e01
+#define VIU2_OSD1_CTRL_STAT 0x1e10
+#define VIU2_OSD1_CTRL_STAT2 0x1e2d
+#define VIU2_OSD1_COLOR_ADDR 0x1e11
+#define VIU2_OSD1_COLOR 0x1e12
+#define VIU2_OSD1_TCOLOR_AG0 0x1e17
+#define VIU2_OSD1_TCOLOR_AG1 0x1e18
+#define VIU2_OSD1_TCOLOR_AG2 0x1e19
+#define VIU2_OSD1_TCOLOR_AG3 0x1e1a
+#define VIU2_OSD1_BLK0_CFG_W0 0x1e1b
+#define VIU2_OSD1_BLK1_CFG_W0 0x1e1f
+#define VIU2_OSD1_BLK2_CFG_W0 0x1e23
+#define VIU2_OSD1_BLK3_CFG_W0 0x1e27
+#define VIU2_OSD1_BLK0_CFG_W1 0x1e1c
+#define VIU2_OSD1_BLK1_CFG_W1 0x1e20
+#define VIU2_OSD1_BLK2_CFG_W1 0x1e24
+#define VIU2_OSD1_BLK3_CFG_W1 0x1e28
+#define VIU2_OSD1_BLK0_CFG_W2 0x1e1d
+#define VIU2_OSD1_BLK1_CFG_W2 0x1e21
+#define VIU2_OSD1_BLK2_CFG_W2 0x1e25
+#define VIU2_OSD1_BLK3_CFG_W2 0x1e29
+#define VIU2_OSD1_BLK0_CFG_W3 0x1e1e
+#define VIU2_OSD1_BLK1_CFG_W3 0x1e22
+#define VIU2_OSD1_BLK2_CFG_W3 0x1e26
+#define VIU2_OSD1_BLK3_CFG_W3 0x1e2a
+#define VIU2_OSD1_BLK0_CFG_W4 0x1e13
+#define VIU2_OSD1_BLK1_CFG_W4 0x1e14
+#define VIU2_OSD1_BLK2_CFG_W4 0x1e15
+#define VIU2_OSD1_BLK3_CFG_W4 0x1e16
+#define VIU2_OSD1_FIFO_CTRL_STAT 0x1e2b
+#define VIU2_OSD1_TEST_RDDATA 0x1e2c
+#define VIU2_OSD1_PROT_CTRL 0x1e2e
+#define VIU2_OSD2_CTRL_STAT 0x1e30
+#define VIU2_OSD2_CTRL_STAT2 0x1e4d
+#define VIU2_OSD2_COLOR_ADDR 0x1e31
+#define VIU2_OSD2_COLOR 0x1e32
+#define VIU2_OSD2_HL1_H_START_END 0x1e33
+#define VIU2_OSD2_HL1_V_START_END 0x1e34
+#define VIU2_OSD2_HL2_H_START_END 0x1e35
+#define VIU2_OSD2_HL2_V_START_END 0x1e36
+#define VIU2_OSD2_TCOLOR_AG0 0x1e37
+#define VIU2_OSD2_TCOLOR_AG1 0x1e38
+#define VIU2_OSD2_TCOLOR_AG2 0x1e39
+#define VIU2_OSD2_TCOLOR_AG3 0x1e3a
+#define VIU2_OSD2_BLK0_CFG_W0 0x1e3b
+#define VIU2_OSD2_BLK1_CFG_W0 0x1e3f
+#define VIU2_OSD2_BLK2_CFG_W0 0x1e43
+#define VIU2_OSD2_BLK3_CFG_W0 0x1e47
+#define VIU2_OSD2_BLK0_CFG_W1 0x1e3c
+#define VIU2_OSD2_BLK1_CFG_W1 0x1e40
+#define VIU2_OSD2_BLK2_CFG_W1 0x1e44
+#define VIU2_OSD2_BLK3_CFG_W1 0x1e48
+#define VIU2_OSD2_BLK0_CFG_W2 0x1e3d
+#define VIU2_OSD2_BLK1_CFG_W2 0x1e41
+#define VIU2_OSD2_BLK2_CFG_W2 0x1e45
+#define VIU2_OSD2_BLK3_CFG_W2 0x1e49
+#define VIU2_OSD2_BLK0_CFG_W3 0x1e3e
+#define VIU2_OSD2_BLK1_CFG_W3 0x1e42
+#define VIU2_OSD2_BLK2_CFG_W3 0x1e46
+#define VIU2_OSD2_BLK3_CFG_W3 0x1e4a
+#define VIU2_OSD2_BLK0_CFG_W4 0x1e64
+#define VIU2_OSD2_BLK1_CFG_W4 0x1e65
+#define VIU2_OSD2_BLK2_CFG_W4 0x1e66
+#define VIU2_OSD2_BLK3_CFG_W4 0x1e67
+#define VIU2_OSD2_FIFO_CTRL_STAT 0x1e4b
+#define VIU2_OSD2_TEST_RDDATA 0x1e4c
+#define VIU2_OSD2_PROT_CTRL 0x1e4e
+#define VIU2_VD1_IF0_GEN_REG 0x1e50
+#define VIU2_VD1_IF0_CANVAS0 0x1e51
+#define VIU2_VD1_IF0_CANVAS1 0x1e52
+#define VIU2_VD1_IF0_LUMA_X0 0x1e53
+#define VIU2_VD1_IF0_LUMA_Y0 0x1e54
+#define VIU2_VD1_IF0_CHROMA_X0 0x1e55
+#define VIU2_VD1_IF0_CHROMA_Y0 0x1e56
+#define VIU2_VD1_IF0_LUMA_X1 0x1e57
+#define VIU2_VD1_IF0_LUMA_Y1 0x1e58
+#define VIU2_VD1_IF0_CHROMA_X1 0x1e59
+#define VIU2_VD1_IF0_CHROMA_Y1 0x1e5a
+#define VIU2_VD1_IF0_RPT_LOOP 0x1e5b
+#define VIU2_VD1_IF0_LUMA0_RPT_PAT 0x1e5c
+#define VIU2_VD1_IF0_CHROMA0_RPT_PAT 0x1e5d
+#define VIU2_VD1_IF0_LUMA1_RPT_PAT 0x1e5e
+#define VIU2_VD1_IF0_CHROMA1_RPT_PAT 0x1e5f
+#define VIU2_VD1_IF0_LUMA_PSEL 0x1e60
+#define VIU2_VD1_IF0_CHROMA_PSEL 0x1e61
+#define VIU2_VD1_IF0_DUMMY_PIXEL 0x1e62
+#define VIU2_VD1_IF0_LUMA_FIFO_SIZE 0x1e63
+#define VIU2_VD1_IF0_RANGE_MAP_Y 0x1e6a
+#define VIU2_VD1_IF0_RANGE_MAP_CB 0x1e6b
+#define VIU2_VD1_IF0_RANGE_MAP_CR 0x1e6c
+#define VIU2_VD1_IF0_GEN_REG2 0x1e6d
+#define VIU2_VD1_IF0_PROT_CNTL 0x1e6e
+#define VIU2_VD1_FMT_CTRL 0x1e68
+#define VIU2_VD1_FMT_W 0x1e69
+
+/* encode */
+#define ENCP_VFIFO2VD_CTL 0x1b58
+#define ENCP_VFIFO2VD_PIXEL_START 0x1b59
+#define ENCP_VFIFO2VD_PIXEL_END 0x1b5a
+#define ENCP_VFIFO2VD_LINE_TOP_START 0x1b5b
+#define ENCP_VFIFO2VD_LINE_TOP_END 0x1b5c
+#define ENCP_VFIFO2VD_LINE_BOT_START 0x1b5d
+#define ENCP_VFIFO2VD_LINE_BOT_END 0x1b5e
+#define VENC_SYNC_ROUTE 0x1b60
+#define VENC_VIDEO_EXSRC 0x1b61
+#define VENC_DVI_SETTING 0x1b62
+#define VENC_C656_CTRL 0x1b63
+#define VENC_UPSAMPLE_CTRL0 0x1b64
+#define VENC_UPSAMPLE_CTRL1 0x1b65
+#define VENC_UPSAMPLE_CTRL2 0x1b66
+#define TCON_INVERT_CTL 0x1b67
+#define VENC_VIDEO_PROG_MODE 0x1b68
+#define VENC_ENCI_LINE 0x1b69
+#define VENC_ENCI_PIXEL 0x1b6a
+#define VENC_ENCP_LINE 0x1b6b
+#define VENC_ENCP_PIXEL 0x1b6c
+#define VENC_STATA 0x1b6d
+#define VENC_INTCTRL 0x1b6e
+#define VENC_INTFLAG 0x1b6f
+#define VENC_VIDEO_TST_EN 0x1b70
+#define VENC_VIDEO_TST_MDSEL 0x1b71
+#define VENC_VIDEO_TST_Y 0x1b72
+#define VENC_VIDEO_TST_CB 0x1b73
+#define VENC_VIDEO_TST_CR 0x1b74
+#define VENC_VIDEO_TST_CLRBAR_STRT 0x1b75
+#define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76
+#define VENC_VIDEO_TST_VDCNT_STSET 0x1b77
+#define VENC_VDAC_DACSEL0 0x1b78
+#define VENC_VDAC_DACSEL1 0x1b79
+#define VENC_VDAC_DACSEL2 0x1b7a
+#define VENC_VDAC_DACSEL3 0x1b7b
+#define VENC_VDAC_DACSEL4 0x1b7c
+#define VENC_VDAC_DACSEL5 0x1b7d
+#define VENC_VDAC_SETTING 0x1b7e
+#define VENC_VDAC_TST_VAL 0x1b7f
+#define VENC_VDAC_DAC0_GAINCTRL 0x1bf0
+#define VENC_VDAC_DAC0_OFFSET 0x1bf1
+#define VENC_VDAC_DAC1_GAINCTRL 0x1bf2
+#define VENC_VDAC_DAC1_OFFSET 0x1bf3
+#define VENC_VDAC_DAC2_GAINCTRL 0x1bf4
+#define VENC_VDAC_DAC2_OFFSET 0x1bf5
+#define VENC_VDAC_DAC3_GAINCTRL 0x1bf6
+#define VENC_VDAC_DAC3_OFFSET 0x1bf7
+#define VENC_VDAC_DAC4_GAINCTRL 0x1bf8
+#define VENC_VDAC_DAC4_OFFSET 0x1bf9
+#define VENC_VDAC_DAC5_GAINCTRL 0x1bfa
+#define VENC_VDAC_DAC5_OFFSET 0x1bfb
+#define VENC_VDAC_FIFO_CTRL 0x1bfc
+#define ENCL_TCON_INVERT_CTL 0x1bfd
+#define ENCP_VIDEO_EN 0x1b80
+#define ENCP_VIDEO_SYNC_MODE 0x1b81
+#define ENCP_MACV_EN 0x1b82
+#define ENCP_VIDEO_Y_SCL 0x1b83
+#define ENCP_VIDEO_PB_SCL 0x1b84
+#define ENCP_VIDEO_PR_SCL 0x1b85
+#define ENCP_VIDEO_SYNC_SCL 0x1b86
+#define ENCP_VIDEO_MACV_SCL 0x1b87
+#define ENCP_VIDEO_Y_OFFST 0x1b88
+#define ENCP_VIDEO_PB_OFFST 0x1b89
+#define ENCP_VIDEO_PR_OFFST 0x1b8a
+#define ENCP_VIDEO_SYNC_OFFST 0x1b8b
+#define ENCP_VIDEO_MACV_OFFST 0x1b8c
+#define ENCP_VIDEO_MODE 0x1b8d
+#define ENCP_VIDEO_MODE_ADV 0x1b8e
+#define ENCP_DBG_PX_RST 0x1b90
+#define ENCP_DBG_LN_RST 0x1b91
+#define ENCP_DBG_PX_INT 0x1b92
+#define ENCP_DBG_LN_INT 0x1b93
+#define ENCP_VIDEO_YFP1_HTIME 0x1b94
+#define ENCP_VIDEO_YFP2_HTIME 0x1b95
+#define ENCP_VIDEO_YC_DLY 0x1b96
+#define ENCP_VIDEO_MAX_PXCNT 0x1b97
+#define ENCP_VIDEO_HSPULS_BEGIN 0x1b98
+#define ENCP_VIDEO_HSPULS_END 0x1b99
+#define ENCP_VIDEO_HSPULS_SWITCH 0x1b9a
+#define ENCP_VIDEO_VSPULS_BEGIN 0x1b9b
+#define ENCP_VIDEO_VSPULS_END 0x1b9c
+#define ENCP_VIDEO_VSPULS_BLINE 0x1b9d
+#define ENCP_VIDEO_VSPULS_ELINE 0x1b9e
+#define ENCP_VIDEO_EQPULS_BEGIN 0x1b9f
+#define ENCP_VIDEO_EQPULS_END 0x1ba0
+#define ENCP_VIDEO_EQPULS_BLINE 0x1ba1
+#define ENCP_VIDEO_EQPULS_ELINE 0x1ba2
+#define ENCP_VIDEO_HAVON_END 0x1ba3
+#define ENCP_VIDEO_HAVON_BEGIN 0x1ba4
+#define ENCP_VIDEO_VAVON_ELINE 0x1baf
+#define ENCP_VIDEO_VAVON_BLINE 0x1ba6
+#define ENCP_VIDEO_HSO_BEGIN 0x1ba7
+#define ENCP_VIDEO_HSO_END 0x1ba8
+#define ENCP_VIDEO_VSO_BEGIN 0x1ba9
+#define ENCP_VIDEO_VSO_END 0x1baa
+#define ENCP_VIDEO_VSO_BLINE 0x1bab
+#define ENCP_VIDEO_VSO_ELINE 0x1bac
+#define ENCP_VIDEO_SYNC_WAVE_CURVE 0x1bad
+#define ENCP_VIDEO_MAX_LNCNT 0x1bae
+#define ENCP_VIDEO_SY_VAL 0x1bb0
+#define ENCP_VIDEO_SY2_VAL 0x1bb1
+#define ENCP_VIDEO_BLANKY_VAL 0x1bb2
+#define ENCP_VIDEO_BLANKPB_VAL 0x1bb3
+#define ENCP_VIDEO_BLANKPR_VAL 0x1bb4
+#define ENCP_VIDEO_HOFFST 0x1bb5
+#define ENCP_VIDEO_VOFFST 0x1bb6
+#define ENCP_VIDEO_RGB_CTRL 0x1bb7
+#define ENCP_VIDEO_FILT_CTRL 0x1bb8
+#define ENCP_VIDEO_OFLD_VPEQ_OFST 0x1bb9
+#define ENCP_VIDEO_OFLD_VOAV_OFST 0x1bba
+#define ENCP_VIDEO_MATRIX_CB 0x1bbb
+#define ENCP_VIDEO_MATRIX_CR 0x1bbc
+#define ENCP_VIDEO_RGBIN_CTRL 0x1bbd
+#define ENCP_MACV_BLANKY_VAL 0x1bc0
+#define ENCP_MACV_MAXY_VAL 0x1bc1
+#define ENCP_MACV_1ST_PSSYNC_STRT 0x1bc2
+#define ENCP_MACV_PSSYNC_STRT 0x1bc3
+#define ENCP_MACV_AGC_STRT 0x1bc4
+#define ENCP_MACV_AGC_END 0x1bc5
+#define ENCP_MACV_WAVE_END 0x1bc6
+#define ENCP_MACV_STRTLINE 0x1bc7
+#define ENCP_MACV_ENDLINE 0x1bc8
+#define ENCP_MACV_TS_CNT_MAX_L 0x1bc9
+#define ENCP_MACV_TS_CNT_MAX_H 0x1bca
+#define ENCP_MACV_TIME_DOWN 0x1bcb
+#define ENCP_MACV_TIME_LO 0x1bcc
+#define ENCP_MACV_TIME_UP 0x1bcd
+#define ENCP_MACV_TIME_RST 0x1bce
+#define ENCP_VBI_CTRL 0x1bd0
+#define ENCP_VBI_SETTING 0x1bd1
+#define ENCP_VBI_BEGIN 0x1bd2
+#define ENCP_VBI_WIDTH 0x1bd3
+#define ENCP_VBI_HVAL 0x1bd4
+#define ENCP_VBI_DATA0 0x1bd5
+#define ENCP_VBI_DATA1 0x1bd6
+#define C656_HS_ST 0x1be0
+#define C656_HS_ED 0x1be1
+#define C656_VS_LNST_E 0x1be2
+#define C656_VS_LNST_O 0x1be3
+#define C656_VS_LNED_E 0x1be4
+#define C656_VS_LNED_O 0x1be5
+#define C656_FS_LNST 0x1be6
+#define C656_FS_LNED 0x1be7
+#define ENCI_VIDEO_MODE 0x1b00
+#define ENCI_VIDEO_MODE_ADV 0x1b01
+#define ENCI_VIDEO_FSC_ADJ 0x1b02
+#define ENCI_VIDEO_BRIGHT 0x1b03
+#define ENCI_VIDEO_CONT 0x1b04
+#define ENCI_VIDEO_SAT 0x1b05
+#define ENCI_VIDEO_HUE 0x1b06
+#define ENCI_VIDEO_SCH 0x1b07
+#define ENCI_SYNC_MODE 0x1b08
+#define ENCI_SYNC_CTRL 0x1b09
+#define ENCI_SYNC_HSO_BEGIN 0x1b0a
+#define ENCI_SYNC_HSO_END 0x1b0b
+#define ENCI_SYNC_VSO_EVN 0x1b0c
+#define ENCI_SYNC_VSO_ODD 0x1b0d
+#define ENCI_SYNC_VSO_EVNLN 0x1b0e
+#define ENCI_SYNC_VSO_ODDLN 0x1b0f
+#define ENCI_SYNC_HOFFST 0x1b10
+#define ENCI_SYNC_VOFFST 0x1b11
+#define ENCI_SYNC_ADJ 0x1b12
+#define ENCI_RGB_SETTING 0x1b13
+#define ENCI_DE_H_BEGIN 0x1b16
+#define ENCI_DE_H_END 0x1b17
+#define ENCI_DE_V_BEGIN_EVEN 0x1b18
+#define ENCI_DE_V_END_EVEN 0x1b19
+#define ENCI_DE_V_BEGIN_ODD 0x1b1a
+#define ENCI_DE_V_END_ODD 0x1b1b
+#define ENCI_VBI_SETTING 0x1b20
+#define ENCI_VBI_CCDT_EVN 0x1b21
+#define ENCI_VBI_CCDT_ODD 0x1b22
+#define ENCI_VBI_CC525_LN 0x1b23
+#define ENCI_VBI_CC625_LN 0x1b24
+#define ENCI_VBI_WSSDT 0x1b25
+#define ENCI_VBI_WSS_LN 0x1b26
+#define ENCI_VBI_CGMSDT_L 0x1b27
+#define ENCI_VBI_CGMSDT_H 0x1b28
+#define ENCI_VBI_CGMS_LN 0x1b29
+#define ENCI_VBI_TTX_HTIME 0x1b2a
+#define ENCI_VBI_TTX_LN 0x1b2b
+#define ENCI_VBI_TTXDT0 0x1b2c
+#define ENCI_VBI_TTXDT1 0x1b2d
+#define ENCI_VBI_TTXDT2 0x1b2e
+#define ENCI_VBI_TTXDT3 0x1b2f
+#define ENCI_MACV_N0 0x1b30
+#define ENCI_MACV_N1 0x1b31
+#define ENCI_MACV_N2 0x1b32
+#define ENCI_MACV_N3 0x1b33
+#define ENCI_MACV_N4 0x1b34
+#define ENCI_MACV_N5 0x1b35
+#define ENCI_MACV_N6 0x1b36
+#define ENCI_MACV_N7 0x1b37
+#define ENCI_MACV_N8 0x1b38
+#define ENCI_MACV_N9 0x1b39
+#define ENCI_MACV_N10 0x1b3a
+#define ENCI_MACV_N11 0x1b3b
+#define ENCI_MACV_N12 0x1b3c
+#define ENCI_MACV_N13 0x1b3d
+#define ENCI_MACV_N14 0x1b3e
+#define ENCI_MACV_N15 0x1b3f
+#define ENCI_MACV_N16 0x1b40
+#define ENCI_MACV_N17 0x1b41
+#define ENCI_MACV_N18 0x1b42
+#define ENCI_MACV_N19 0x1b43
+#define ENCI_MACV_N20 0x1b44
+#define ENCI_MACV_N21 0x1b45
+#define ENCI_MACV_N22 0x1b46
+#define ENCI_DBG_PX_RST 0x1b48
+#define ENCI_DBG_FLDLN_RST 0x1b49
+#define ENCI_DBG_PX_INT 0x1b4a
+#define ENCI_DBG_FLDLN_INT 0x1b4b
+#define ENCI_DBG_MAXPX 0x1b4c
+#define ENCI_DBG_MAXLN 0x1b4d
+#define ENCI_MACV_MAX_AMP 0x1b50
+#define ENCI_MACV_PULSE_LO 0x1b51
+#define ENCI_MACV_PULSE_HI 0x1b52
+#define ENCI_MACV_BKP_MAX 0x1b53
+#define ENCI_CFILT_CTRL 0x1b54
+#define ENCI_CFILT7 0x1b55
+#define ENCI_YC_DELAY 0x1b56
+#define ENCI_VIDEO_EN 0x1b57
+#define ENCI_DVI_HSO_BEGIN 0x1c00
+#define ENCI_DVI_HSO_END 0x1c01
+#define ENCI_DVI_VSO_BLINE_EVN 0x1c02
+#define ENCI_DVI_VSO_BLINE_ODD 0x1c03
+#define ENCI_DVI_VSO_ELINE_EVN 0x1c04
+#define ENCI_DVI_VSO_ELINE_ODD 0x1c05
+#define ENCI_DVI_VSO_BEGIN_EVN 0x1c06
+#define ENCI_DVI_VSO_BEGIN_ODD 0x1c07
+#define ENCI_DVI_VSO_END_EVN 0x1c08
+#define ENCI_DVI_VSO_END_ODD 0x1c09
+#define ENCI_CFILT_CTRL2 0x1c0a
+#define ENCI_DACSEL_0 0x1c0b
+#define ENCI_DACSEL_1 0x1c0c
+#define ENCP_DACSEL_0 0x1c0d
+#define ENCP_DACSEL_1 0x1c0e
+#define ENCP_MAX_LINE_SWITCH_POINT 0x1c0f
+#define ENCI_TST_EN 0x1c10
+#define ENCI_TST_MDSEL 0x1c11
+#define ENCI_TST_Y 0x1c12
+#define ENCI_TST_CB 0x1c13
+#define ENCI_TST_CR 0x1c14
+#define ENCI_TST_CLRBAR_STRT 0x1c15
+#define ENCI_TST_CLRBAR_WIDTH 0x1c16
+#define ENCI_TST_VDCNT_STSET 0x1c17
+#define ENCI_VFIFO2VD_CTL 0x1c18
+#define ENCI_VFIFO2VD_PIXEL_START 0x1c19
+#define ENCI_VFIFO2VD_PIXEL_END 0x1c1a
+#define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b
+#define ENCI_VFIFO2VD_LINE_TOP_END 0x1c1c
+#define ENCI_VFIFO2VD_LINE_BOT_START 0x1c1d
+#define ENCI_VFIFO2VD_LINE_BOT_END 0x1c1e
+#define ENCI_VFIFO2VD_CTL2 0x1c1f
+#define ENCT_VFIFO2VD_CTL 0x1c20
+#define ENCT_VFIFO2VD_PIXEL_START 0x1c21
+#define ENCT_VFIFO2VD_PIXEL_END 0x1c22
+#define ENCT_VFIFO2VD_LINE_TOP_START 0x1c23
+#define ENCT_VFIFO2VD_LINE_TOP_END 0x1c24
+#define ENCT_VFIFO2VD_LINE_BOT_START 0x1c25
+#define ENCT_VFIFO2VD_LINE_BOT_END 0x1c26
+#define ENCT_VFIFO2VD_CTL2 0x1c27
+#define ENCT_TST_EN 0x1c28
+#define ENCT_TST_MDSEL 0x1c29
+#define ENCT_TST_Y 0x1c2a
+#define ENCT_TST_CB 0x1c2b
+#define ENCT_TST_CR 0x1c2c
+#define ENCT_TST_CLRBAR_STRT 0x1c2d
+#define ENCT_TST_CLRBAR_WIDTH 0x1c2e
+#define ENCT_TST_VDCNT_STSET 0x1c2f
+#define ENCP_DVI_HSO_BEGIN 0x1c30
+#define ENCP_DVI_HSO_END 0x1c31
+#define ENCP_DVI_VSO_BLINE_EVN 0x1c32
+#define ENCP_DVI_VSO_BLINE_ODD 0x1c33
+#define ENCP_DVI_VSO_ELINE_EVN 0x1c34
+#define ENCP_DVI_VSO_ELINE_ODD 0x1c35
+#define ENCP_DVI_VSO_BEGIN_EVN 0x1c36
+#define ENCP_DVI_VSO_BEGIN_ODD 0x1c37
+#define ENCP_DVI_VSO_END_EVN 0x1c38
+#define ENCP_DVI_VSO_END_ODD 0x1c39
+#define ENCP_DE_H_BEGIN 0x1c3a
+#define ENCP_DE_H_END 0x1c3b
+#define ENCP_DE_V_BEGIN_EVEN 0x1c3c
+#define ENCP_DE_V_END_EVEN 0x1c3d
+#define ENCP_DE_V_BEGIN_ODD 0x1c3e
+#define ENCP_DE_V_END_ODD 0x1c3f
+#define ENCI_SYNC_LINE_LENGTH 0x1c40
+#define ENCI_SYNC_PIXEL_EN 0x1c41
+#define ENCI_SYNC_TO_LINE_EN 0x1c42
+#define ENCI_SYNC_TO_PIXEL 0x1c43
+#define ENCP_SYNC_LINE_LENGTH 0x1c44
+#define ENCP_SYNC_PIXEL_EN 0x1c45
+#define ENCP_SYNC_TO_LINE_EN 0x1c46
+#define ENCP_SYNC_TO_PIXEL 0x1c47
+#define ENCT_SYNC_LINE_LENGTH 0x1c48
+#define ENCT_SYNC_PIXEL_EN 0x1c49
+#define ENCT_SYNC_TO_LINE_EN 0x1c4a
+#define ENCT_SYNC_TO_PIXEL 0x1c4b
+#define ENCL_SYNC_LINE_LENGTH 0x1c4c
+#define ENCL_SYNC_PIXEL_EN 0x1c4d
+#define ENCL_SYNC_TO_LINE_EN 0x1c4e
+#define ENCL_SYNC_TO_PIXEL 0x1c4f
+#define ENCP_VFIFO2VD_CTL2 0x1c50
+#define VENC_DVI_SETTING_MORE 0x1c51
+#define VENC_VDAC_DAC4_FILT_CTRL0 0x1c54
+#define VENC_VDAC_DAC4_FILT_CTRL1 0x1c55
+#define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56
+#define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57
+#define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58
+#define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59
+#define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a
+#define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b
+#define VENC_VDAC_DAC2_FILT_CTRL0 0x1c5c
+#define VENC_VDAC_DAC2_FILT_CTRL1 0x1c5d
+#define VENC_VDAC_DAC3_FILT_CTRL0 0x1c5e
+#define VENC_VDAC_DAC3_FILT_CTRL1 0x1c5f
+#define ENCT_VIDEO_EN 0x1c60
+#define ENCT_VIDEO_Y_SCL 0x1c61
+#define ENCT_VIDEO_PB_SCL 0x1c62
+#define ENCT_VIDEO_PR_SCL 0x1c63
+#define ENCT_VIDEO_Y_OFFST 0x1c64
+#define ENCT_VIDEO_PB_OFFST 0x1c65
+#define ENCT_VIDEO_PR_OFFST 0x1c66
+#define ENCT_VIDEO_MODE 0x1c67
+#define ENCT_VIDEO_MODE_ADV 0x1c68
+#define ENCT_DBG_PX_RST 0x1c69
+#define ENCT_DBG_LN_RST 0x1c6a
+#define ENCT_DBG_PX_INT 0x1c6b
+#define ENCT_DBG_LN_INT 0x1c6c
+#define ENCT_VIDEO_YFP1_HTIME 0x1c6d
+#define ENCT_VIDEO_YFP2_HTIME 0x1c6e
+#define ENCT_VIDEO_YC_DLY 0x1c6f
+#define ENCT_VIDEO_MAX_PXCNT 0x1c70
+#define ENCT_VIDEO_HAVON_END 0x1c71
+#define ENCT_VIDEO_HAVON_BEGIN 0x1c72
+#define ENCT_VIDEO_VAVON_ELINE 0x1c73
+#define ENCT_VIDEO_VAVON_BLINE 0x1c74
+#define ENCT_VIDEO_HSO_BEGIN 0x1c75
+#define ENCT_VIDEO_HSO_END 0x1c76
+#define ENCT_VIDEO_VSO_BEGIN 0x1c77
+#define ENCT_VIDEO_VSO_END 0x1c78
+#define ENCT_VIDEO_VSO_BLINE 0x1c79
+#define ENCT_VIDEO_VSO_ELINE 0x1c7a
+#define ENCT_VIDEO_MAX_LNCNT 0x1c7b
+#define ENCT_VIDEO_BLANKY_VAL 0x1c7c
+#define ENCT_VIDEO_BLANKPB_VAL 0x1c7d
+#define ENCT_VIDEO_BLANKPR_VAL 0x1c7e
+#define ENCT_VIDEO_HOFFST 0x1c7f
+#define ENCT_VIDEO_VOFFST 0x1c80
+#define ENCT_VIDEO_RGB_CTRL 0x1c81
+#define ENCT_VIDEO_FILT_CTRL 0x1c82
+#define ENCT_VIDEO_OFLD_VPEQ_OFST 0x1c83
+#define ENCT_VIDEO_OFLD_VOAV_OFST 0x1c84
+#define ENCT_VIDEO_MATRIX_CB 0x1c85
+#define ENCT_VIDEO_MATRIX_CR 0x1c86
+#define ENCT_VIDEO_RGBIN_CTRL 0x1c87
+#define ENCT_MAX_LINE_SWITCH_POINT 0x1c88
+#define ENCT_DACSEL_0 0x1c89
+#define ENCT_DACSEL_1 0x1c8a
+#define ENCL_VFIFO2VD_CTL 0x1c90
+#define ENCL_VFIFO2VD_PIXEL_START 0x1c91
+#define ENCL_VFIFO2VD_PIXEL_END 0x1c92
+#define ENCL_VFIFO2VD_LINE_TOP_START 0x1c93
+#define ENCL_VFIFO2VD_LINE_TOP_END 0x1c94
+#define ENCL_VFIFO2VD_LINE_BOT_START 0x1c95
+#define ENCL_VFIFO2VD_LINE_BOT_END 0x1c96
+#define ENCL_VFIFO2VD_CTL2 0x1c97
+#define ENCL_TST_EN 0x1c98
+#define ENCL_TST_MDSEL 0x1c99
+#define ENCL_TST_Y 0x1c9a
+#define ENCL_TST_CB 0x1c9b
+#define ENCL_TST_CR 0x1c9c
+#define ENCL_TST_CLRBAR_STRT 0x1c9d
+#define ENCL_TST_CLRBAR_WIDTH 0x1c9e
+#define ENCL_TST_VDCNT_STSET 0x1c9f
+#define ENCL_VIDEO_EN 0x1ca0
+#define ENCL_VIDEO_Y_SCL 0x1ca1
+#define ENCL_VIDEO_PB_SCL 0x1ca2
+#define ENCL_VIDEO_PR_SCL 0x1ca3
+#define ENCL_VIDEO_Y_OFFST 0x1ca4
+#define ENCL_VIDEO_PB_OFFST 0x1ca5
+#define ENCL_VIDEO_PR_OFFST 0x1ca6
+#define ENCL_VIDEO_MODE 0x1ca7
+#define ENCL_VIDEO_MODE_ADV 0x1ca8
+#define ENCL_DBG_PX_RST 0x1ca9
+#define ENCL_DBG_LN_RST 0x1caa
+#define ENCL_DBG_PX_INT 0x1cab
+#define ENCL_DBG_LN_INT 0x1cac
+#define ENCL_VIDEO_YFP1_HTIME 0x1cad
+#define ENCL_VIDEO_YFP2_HTIME 0x1cae
+#define ENCL_VIDEO_YC_DLY 0x1caf
+#define ENCL_VIDEO_MAX_PXCNT 0x1cb0
+#define ENCL_VIDEO_HAVON_END 0x1cb1
+#define ENCL_VIDEO_HAVON_BEGIN 0x1cb2
+#define ENCL_VIDEO_VAVON_ELINE 0x1cb3
+#define ENCL_VIDEO_VAVON_BLINE 0x1cb4
+#define ENCL_VIDEO_HSO_BEGIN 0x1cb5
+#define ENCL_VIDEO_HSO_END 0x1cb6
+#define ENCL_VIDEO_VSO_BEGIN 0x1cb7
+#define ENCL_VIDEO_VSO_END 0x1cb8
+#define ENCL_VIDEO_VSO_BLINE 0x1cb9
+#define ENCL_VIDEO_VSO_ELINE 0x1cba
+#define ENCL_VIDEO_MAX_LNCNT 0x1cbb
+#define ENCL_VIDEO_BLANKY_VAL 0x1cbc
+#define ENCL_VIDEO_BLANKPB_VAL 0x1cbd
+#define ENCL_VIDEO_BLANKPR_VAL 0x1cbe
+#define ENCL_VIDEO_HOFFST 0x1cbf
+#define ENCL_VIDEO_VOFFST 0x1cc0
+#define ENCL_VIDEO_RGB_CTRL 0x1cc1
+#define ENCL_VIDEO_FILT_CTRL 0x1cc2
+#define ENCL_VIDEO_OFLD_VPEQ_OFST 0x1cc3
+#define ENCL_VIDEO_OFLD_VOAV_OFST 0x1cc4
+#define ENCL_VIDEO_MATRIX_CB 0x1cc5
+#define ENCL_VIDEO_MATRIX_CR 0x1cc6
+#define ENCL_VIDEO_RGBIN_CTRL 0x1cc7
+#define ENCL_MAX_LINE_SWITCH_POINT 0x1cc8
+#define ENCL_DACSEL_0 0x1cc9
+#define ENCL_DACSEL_1 0x1cca
+#define RDMA_AHB_START_ADDR_MAN 0x1100
+#define RDMA_AHB_END_ADDR_MAN 0x1101
+#define RDMA_AHB_START_ADDR_1 0x1102
+#define RDMA_AHB_END_ADDR_1 0x1103
+#define RDMA_AHB_START_ADDR_2 0x1104
+#define RDMA_AHB_END_ADDR_2 0x1105
+#define RDMA_AHB_START_ADDR_3 0x1106
+#define RDMA_AHB_END_ADDR_3 0x1107
+#define RDMA_AHB_START_ADDR_4 0x1108
+#define RDMA_AHB_END_ADDR_4 0x1109
+#define RDMA_AHB_START_ADDR_5 0x110a
+#define RDMA_AHB_END_ADDR_5 0x110b
+#define RDMA_AHB_START_ADDR_6 0x110c
+#define RDMA_AHB_END_ADDR_6 0x110d
+#define RDMA_AHB_START_ADDR_7 0x110e
+#define RDMA_AHB_END_ADDR_7 0x110f
+#define RDMA_ACCESS_AUTO 0x1110
+#define RDMA_ACCESS_AUTO2 0x1111
+#define RDMA_ACCESS_AUTO3 0x1112
+#define RDMA_ACCESS_MAN 0x1113
+#define RDMA_CTRL 0x1114
+#define RDMA_STATUS 0x1115
+#define RDMA_STATUS2 0x1116
+#define RDMA_STATUS3 0x1117
+#define L_GAMMA_CNTL_PORT 0x1400
+#define L_GAMMA_DATA_PORT 0x1401
+#define L_GAMMA_ADDR_PORT 0x1402
+#define L_GAMMA_VCOM_HSWITCH_ADDR 0x1403
+#define L_RGB_BASE_ADDR 0x1405
+#define L_RGB_COEFF_ADDR 0x1406
+#define L_POL_CNTL_ADDR 0x1407
+#define L_DITH_CNTL_ADDR 0x1408
+#define L_GAMMA_PROBE_CTRL 0x1409
+#define L_GAMMA_PROBE_COLOR_L 0x140a
+#define L_GAMMA_PROBE_COLOR_H 0x140b
+#define L_GAMMA_PROBE_HL_COLOR 0x140c
+#define L_GAMMA_PROBE_POS_X 0x140d
+#define L_GAMMA_PROBE_POS_Y 0x140e
+#define L_STH1_HS_ADDR 0x1410
+#define L_STH1_HE_ADDR 0x1411
+#define L_STH1_VS_ADDR 0x1412
+#define L_STH1_VE_ADDR 0x1413
+#define L_STH2_HS_ADDR 0x1414
+#define L_STH2_HE_ADDR 0x1415
+#define L_STH2_VS_ADDR 0x1416
+#define L_STH2_VE_ADDR 0x1417
+#define L_OEH_HS_ADDR 0x1418
+#define L_OEH_HE_ADDR 0x1419
+#define L_OEH_VS_ADDR 0x141a
+#define L_OEH_VE_ADDR 0x141b
+#define L_VCOM_HSWITCH_ADDR 0x141c
+#define L_VCOM_VS_ADDR 0x141d
+#define L_VCOM_VE_ADDR 0x141e
+#define L_CPV1_HS_ADDR 0x141f
+#define L_CPV1_HE_ADDR 0x1420
+#define L_CPV1_VS_ADDR 0x1421
+#define L_CPV1_VE_ADDR 0x1422
+#define L_CPV2_HS_ADDR 0x1423
+#define L_CPV2_HE_ADDR 0x1424
+#define L_CPV2_VS_ADDR 0x1425
+#define L_CPV2_VE_ADDR 0x1426
+#define L_STV1_HS_ADDR 0x1427
+#define L_STV1_HE_ADDR 0x1428
+#define L_STV1_VS_ADDR 0x1429
+#define L_STV1_VE_ADDR 0x142a
+#define L_STV2_HS_ADDR 0x142b
+#define L_STV2_HE_ADDR 0x142c
+#define L_STV2_VS_ADDR 0x142d
+#define L_STV2_VE_ADDR 0x142e
+#define L_OEV1_HS_ADDR 0x142f
+#define L_OEV1_HE_ADDR 0x1430
+#define L_OEV1_VS_ADDR 0x1431
+#define L_OEV1_VE_ADDR 0x1432
+#define L_OEV2_HS_ADDR 0x1433
+#define L_OEV2_HE_ADDR 0x1434
+#define L_OEV2_VS_ADDR 0x1435
+#define L_OEV2_VE_ADDR 0x1436
+#define L_OEV3_HS_ADDR 0x1437
+#define L_OEV3_HE_ADDR 0x1438
+#define L_OEV3_VS_ADDR 0x1439
+#define L_OEV3_VE_ADDR 0x143a
+#define L_LCD_PWR_ADDR 0x143b
+#define L_LCD_PWM0_LO_ADDR 0x143c
+#define L_LCD_PWM0_HI_ADDR 0x143d
+#define L_LCD_PWM1_LO_ADDR 0x143e
+#define L_LCD_PWM1_HI_ADDR 0x143f
+#define L_INV_CNT_ADDR 0x1440
+#define L_TCON_MISC_SEL_ADDR 0x1441
+#define L_DUAL_PORT_CNTL_ADDR 0x1442
+#define MLVDS_CLK_CTL1_HI 0x1443
+#define MLVDS_CLK_CTL1_LO 0x1444
+#define L_TCON_DOUBLE_CTL 0x1449
+#define L_TCON_PATTERN_HI 0x144a
+#define L_TCON_PATTERN_LO 0x144b
+#define LDIM_BL_ADDR_PORT 0x144e
+#define LDIM_BL_DATA_PORT 0x144f
+#define L_DE_HS_ADDR 0x1451
+#define L_DE_HE_ADDR 0x1452
+#define L_DE_VS_ADDR 0x1453
+#define L_DE_VE_ADDR 0x1454
+#define L_HSYNC_HS_ADDR 0x1455
+#define L_HSYNC_HE_ADDR 0x1456
+#define L_HSYNC_VS_ADDR 0x1457
+#define L_HSYNC_VE_ADDR 0x1458
+#define L_VSYNC_HS_ADDR 0x1459
+#define L_VSYNC_HE_ADDR 0x145a
+#define L_VSYNC_VS_ADDR 0x145b
+#define L_VSYNC_VE_ADDR 0x145c
+#define L_LCD_MCU_CTL 0x145d
+#define DUAL_MLVDS_CTL 0x1460
+#define DUAL_MLVDS_LINE_START 0x1461
+#define DUAL_MLVDS_LINE_END 0x1462
+#define DUAL_MLVDS_PIXEL_W_START_L 0x1463
+#define DUAL_MLVDS_PIXEL_W_END_L 0x1464
+#define DUAL_MLVDS_PIXEL_W_START_R 0x1465
+#define DUAL_MLVDS_PIXEL_W_END_R 0x1466
+#define DUAL_MLVDS_PIXEL_R_START_L 0x1467
+#define DUAL_MLVDS_PIXEL_R_CNT_L 0x1468
+#define DUAL_MLVDS_PIXEL_R_START_R 0x1469
+#define DUAL_MLVDS_PIXEL_R_CNT_R 0x146a
+#define V_INVERSION_PIXEL 0x1470
+#define V_INVERSION_LINE 0x1471
+#define V_INVERSION_CONTROL 0x1472
+#define MLVDS2_CONTROL 0x1474
+#define MLVDS2_CONFIG_HI 0x1475
+#define MLVDS2_CONFIG_LO 0x1476
+#define MLVDS2_DUAL_GATE_WR_START 0x1477
+#define MLVDS2_DUAL_GATE_WR_END 0x1478
+#define MLVDS2_DUAL_GATE_RD_START 0x1479
+#define MLVDS2_DUAL_GATE_RD_END 0x147a
+#define MLVDS2_SECOND_RESET_CTL 0x147b
+#define MLVDS2_DUAL_GATE_CTL_HI 0x147c
+#define MLVDS2_DUAL_GATE_CTL_LO 0x147d
+#define MLVDS2_RESET_CONFIG_HI 0x147e
+#define MLVDS2_RESET_CONFIG_LO 0x147f
+#define GAMMA_CNTL_PORT 0x1480
+#define GAMMA_DATA_PORT 0x1481
+#define GAMMA_ADDR_PORT 0x1482
+#define GAMMA_VCOM_HSWITCH_ADDR 0x1483
+#define RGB_BASE_ADDR 0x1485
+#define RGB_COEFF_ADDR 0x1486
+#define POL_CNTL_ADDR 0x1487
+#define DITH_CNTL_ADDR 0x1488
+#define GAMMA_PROBE_CTRL 0x1489
+#define GAMMA_PROBE_COLOR_L 0x148a
+#define GAMMA_PROBE_COLOR_H 0x148b
+#define GAMMA_PROBE_HL_COLOR 0x148c
+#define GAMMA_PROBE_POS_X 0x148d
+#define GAMMA_PROBE_POS_Y 0x148e
+#define STH1_HS_ADDR 0x1490
+#define STH1_HE_ADDR 0x1491
+#define STH1_VS_ADDR 0x1492
+#define STH1_VE_ADDR 0x1493
+#define STH2_HS_ADDR 0x1494
+#define STH2_HE_ADDR 0x1495
+#define STH2_VS_ADDR 0x1496
+#define STH2_VE_ADDR 0x1497
+#define OEH_HS_ADDR 0x1498
+#define OEH_HE_ADDR 0x1499
+#define OEH_VS_ADDR 0x149a
+#define OEH_VE_ADDR 0x149b
+#define VCOM_HSWITCH_ADDR 0x149c
+#define VCOM_VS_ADDR 0x149d
+#define VCOM_VE_ADDR 0x149e
+#define CPV1_HS_ADDR 0x149f
+#define CPV1_HE_ADDR 0x14a0
+#define CPV1_VS_ADDR 0x14a1
+#define CPV1_VE_ADDR 0x14a2
+#define CPV2_HS_ADDR 0x14a3
+#define CPV2_HE_ADDR 0x14a4
+#define CPV2_VS_ADDR 0x14a5
+#define CPV2_VE_ADDR 0x14a6
+#define STV1_HS_ADDR 0x14a7
+#define STV1_HE_ADDR 0x14a8
+#define STV1_VS_ADDR 0x14a9
+#define STV1_VE_ADDR 0x14aa
+#define STV2_HS_ADDR 0x14ab
+#define STV2_HE_ADDR 0x14ac
+#define STV2_VS_ADDR 0x14ad
+#define STV2_VE_ADDR 0x14ae
+#define OEV1_HS_ADDR 0x14af
+#define OEV1_HE_ADDR 0x14b0
+#define OEV1_VS_ADDR 0x14b1
+#define OEV1_VE_ADDR 0x14b2
+#define OEV2_HS_ADDR 0x14b3
+#define OEV2_HE_ADDR 0x14b4
+#define OEV2_VS_ADDR 0x14b5
+#define OEV2_VE_ADDR 0x14b6
+#define OEV3_HS_ADDR 0x14b7
+#define OEV3_HE_ADDR 0x14b8
+#define OEV3_VS_ADDR 0x14b9
+#define OEV3_VE_ADDR 0x14ba
+#define LCD_PWR_ADDR 0x14bb
+#define LCD_PWM0_LO_ADDR 0x14bc
+#define LCD_PWM0_HI_ADDR 0x14bd
+#define LCD_PWM1_LO_ADDR 0x14be
+#define LCD_PWM1_HI_ADDR 0x14bf
+#define INV_CNT_ADDR 0x14c0
+#define TCON_MISC_SEL_ADDR 0x14c1
+#define DUAL_PORT_CNTL_ADDR 0x14c2
+#define MLVDS_CONTROL 0x14c3
+#define MLVDS_RESET_PATTERN_HI 0x14c4
+#define MLVDS_RESET_PATTERN_LO 0x14c5
+#define MLVDS_RESET_PATTERN_EXT 0x14c6
+#define MLVDS_CONFIG_HI 0x14c7
+#define MLVDS_CONFIG_LO 0x14c8
+#define TCON_DOUBLE_CTL 0x14c9
+#define TCON_PATTERN_HI 0x14ca
+#define TCON_PATTERN_LO 0x14cb
+#define TCON_CONTROL_HI 0x14cc
+#define TCON_CONTROL_LO 0x14cd
+#define LVDS_BLANK_DATA_HI 0x14ce
+#define LVDS_BLANK_DATA_LO 0x14cf
+#define LVDS_PACK_CNTL_ADDR 0x14d0
+#define DE_HS_ADDR 0x14d1
+#define DE_HE_ADDR 0x14d2
+#define DE_VS_ADDR 0x14d3
+#define DE_VE_ADDR 0x14d4
+#define HSYNC_HS_ADDR 0x14d5
+#define HSYNC_HE_ADDR 0x14d6
+#define HSYNC_VS_ADDR 0x14d7
+#define HSYNC_VE_ADDR 0x14d8
+#define VSYNC_HS_ADDR 0x14d9
+#define VSYNC_HE_ADDR 0x14da
+#define VSYNC_VS_ADDR 0x14db
+#define VSYNC_VE_ADDR 0x14dc
+#define LCD_MCU_CTL 0x14dd
+#define LCD_MCU_DATA_0 0x14de
+#define LCD_MCU_DATA_1 0x14df
+#define LVDS_GEN_CNTL 0x14e0
+#define LVDS_PHY_CNTL0 0x14e1
+#define LVDS_PHY_CNTL1 0x14e2
+#define LVDS_PHY_CNTL2 0x14e3
+#define LVDS_PHY_CNTL3 0x14e4
+#define LVDS_PHY_CNTL4 0x14e5
+#define LVDS_PHY_CNTL5 0x14e6
+#define LVDS_SRG_TEST 0x14e8
+#define LVDS_BIST_MUX0 0x14e9
+#define LVDS_BIST_MUX1 0x14ea
+#define LVDS_BIST_FIXED0 0x14eb
+#define LVDS_BIST_FIXED1 0x14ec
+#define LVDS_BIST_CNTL0 0x14ed
+#define LVDS_CLKB_CLKA 0x14ee
+#define LVDS_PHY_CLK_CNTL 0x14ef
+#define LVDS_SER_EN 0x14f0
+#define LVDS_PHY_CNTL6 0x14f1
+#define LVDS_PHY_CNTL7 0x14f2
+#define LVDS_PHY_CNTL8 0x14f3
+#define MLVDS_CLK_CTL0_HI 0x14f4
+#define MLVDS_CLK_CTL0_LO 0x14f5
+#define MLVDS_DUAL_GATE_WR_START 0x14f6
+#define MLVDS_DUAL_GATE_WR_END 0x14f7
+#define MLVDS_DUAL_GATE_RD_START 0x14f8
+#define MLVDS_DUAL_GATE_RD_END 0x14f9
+#define MLVDS_SECOND_RESET_CTL 0x14fa
+#define MLVDS_DUAL_GATE_CTL_HI 0x14fb
+#define MLVDS_DUAL_GATE_CTL_LO 0x14fc
+#define MLVDS_RESET_CONFIG_HI 0x14fd
+#define MLVDS_RESET_CONFIG_LO 0x14fe
+#define VPU_OSD1_MMC_CTRL 0x2701
+#define VPU_OSD2_MMC_CTRL 0x2702
+#define VPU_VD1_MMC_CTRL 0x2703
+#define VPU_VD2_MMC_CTRL 0x2704
+#define VPU_DI_IF1_MMC_CTRL 0x2705
+#define VPU_DI_MEM_MMC_CTRL 0x2706
+#define VPU_DI_INP_MMC_CTRL 0x2707
+#define VPU_DI_MTNRD_MMC_CTRL 0x2708
+#define VPU_DI_CHAN2_MMC_CTRL 0x2709
+#define VPU_DI_MTNWR_MMC_CTRL 0x270a
+#define VPU_DI_NRWR_MMC_CTRL 0x270b
+#define VPU_DI_DIWR_MMC_CTRL 0x270c
+#define VPU_VDIN0_MMC_CTRL 0x270d
+#define VPU_VDIN1_MMC_CTRL 0x270e
+#define VPU_BT656_MMC_CTRL 0x270f
+#define VPU_TVD3D_MMC_CTRL 0x2710
+#define VPU_TVDVBI_MMC_CTRL 0x2711
+#define VPU_TVDVBI_VSLATCH_ADDR 0x2712
+#define VPU_TVDVBI_WRRSP_ADDR 0x2713
+#define VPU_VDIN_PRE_ARB_CTRL 0x2714
+#define VPU_VDISP_PRE_ARB_CTRL 0x2715
+#define VPU_VPUARB2_PRE_ARB_CTRL 0x2716
+#define VPU_OSD3_MMC_CTRL 0x2717
+#define VPU_OSD4_MMC_CTRL 0x2718
+#define VPU_VD3_MMC_CTRL 0x2719
+#define VPU_VIU_VENC_MUX_CTRL 0x271a
+#define		VIU1_SEL_VENC_MASK	0x3
+#define		VIU1_SEL_VENC_ENCL	0
+#define		VIU1_SEL_VENC_ENCI	1
+#define		VIU1_SEL_VENC_ENCP	2
+#define		VIU1_SEL_VENC_ENCT	3
+#define		VIU2_SEL_VENC_MASK	0xc
+#define		VIU2_SEL_VENC_ENCL	0
+#define		VIU2_SEL_VENC_ENCI	(1 << 2)
+#define		VIU2_SEL_VENC_ENCP	(2 << 2)
+#define		VIU2_SEL_VENC_ENCT	(3 << 2)
+#define VPU_HDMI_SETTING 0x271b
+#define ENCI_INFO_READ 0x271c
+#define ENCP_INFO_READ 0x271d
+#define ENCT_INFO_READ 0x271e
+#define ENCL_INFO_READ 0x271f
+#define VPU_SW_RESET 0x2720
+#define VPU_D2D3_MMC_CTRL 0x2721
+#define VPU_CONT_MMC_CTRL 0x2722
+#define VPU_CLK_GATE 0x2723
+#define VPU_RDMA_MMC_CTRL 0x2724
+#define VPU_MEM_PD_REG0 0x2725
+#define VPU_MEM_PD_REG1 0x2726
+#define VPU_HDMI_DATA_OVR 0x2727
+#define VPU_PROT1_MMC_CTRL 0x2728
+#define VPU_PROT2_MMC_CTRL 0x2729
+#define VPU_PROT3_MMC_CTRL 0x272a
+#define VPU_ARB4_V1_MMC_CTRL 0x272b
+#define VPU_ARB4_V2_MMC_CTRL 0x272c
+#define VPU_VPU_PWM_V0 0x2730
+#define VPU_VPU_PWM_V1 0x2731
+#define VPU_VPU_PWM_V2 0x2732
+#define VPU_VPU_PWM_V3 0x2733
+#define VPU_VPU_PWM_H0 0x2734
+#define VPU_VPU_PWM_H1 0x2735
+#define VPU_VPU_PWM_H2 0x2736
+#define VPU_VPU_PWM_H3 0x2737
+#define VPU_MISC_CTRL 0x2740
+#define VPU_ISP_GCLK_CTRL0 0x2741
+#define VPU_ISP_GCLK_CTRL1 0x2742
+#define VPU_VDIN_ASYNC_HOLD_CTRL 0x2743
+#define VPU_VDISP_ASYNC_HOLD_CTRL 0x2744
+#define VPU_VPUARB2_ASYNC_HOLD_CTRL 0x2745
+
+#define VPU_PROT1_CLK_GATE 0x2750
+#define VPU_PROT1_GEN_CNTL 0x2751
+#define VPU_PROT1_X_START_END 0x2752
+#define VPU_PROT1_Y_START_END 0x2753
+#define VPU_PROT1_Y_LEN_STEP 0x2754
+#define VPU_PROT1_RPT_LOOP 0x2755
+#define VPU_PROT1_RPT_PAT 0x2756
+#define VPU_PROT1_DDR 0x2757
+#define VPU_PROT1_RBUF_ROOM 0x2758
+#define VPU_PROT1_STAT_0 0x2759
+#define VPU_PROT1_STAT_1 0x275a
+#define VPU_PROT1_STAT_2 0x275b
+#define VPU_PROT1_REQ_ONOFF 0x275c
+#define VPU_PROT2_CLK_GATE 0x2760
+#define VPU_PROT2_GEN_CNTL 0x2761
+#define VPU_PROT2_X_START_END 0x2762
+#define VPU_PROT2_Y_START_END 0x2763
+#define VPU_PROT2_Y_LEN_STEP 0x2764
+#define VPU_PROT2_RPT_LOOP 0x2765
+#define VPU_PROT2_RPT_PAT 0x2766
+#define VPU_PROT2_DDR 0x2767
+#define VPU_PROT2_RBUF_ROOM 0x2768
+#define VPU_PROT2_STAT_0 0x2769
+#define VPU_PROT2_STAT_1 0x276a
+#define VPU_PROT2_STAT_2 0x276b
+#define VPU_PROT2_REQ_ONOFF 0x276c
+#define VPU_PROT3_CLK_GATE 0x2770
+#define VPU_PROT3_GEN_CNTL 0x2771
+#define VPU_PROT3_X_START_END 0x2772
+#define VPU_PROT3_Y_START_END 0x2773
+#define VPU_PROT3_Y_LEN_STEP 0x2774
+#define VPU_PROT3_RPT_LOOP 0x2775
+#define VPU_PROT3_RPT_PAT 0x2776
+#define VPU_PROT3_DDR 0x2777
+#define VPU_PROT3_RBUF_ROOM 0x2778
+#define VPU_PROT3_STAT_0 0x2779
+#define VPU_PROT3_STAT_1 0x277a
+#define VPU_PROT3_STAT_2 0x277b
+#define VPU_PROT3_REQ_ONOFF 0x277c
+
+/* osd super scale */
+#define OSDSR_HV_SIZEIN 0x3130
+#define OSDSR_CTRL_MODE 0x3131
+#define OSDSR_ABIC_HCOEF 0x3132
+#define OSDSR_YBIC_HCOEF 0x3133
+#define OSDSR_CBIC_HCOEF 0x3134
+#define OSDSR_ABIC_VCOEF 0x3135
+#define OSDSR_YBIC_VCOEF 0x3136
+#define OSDSR_CBIC_VCOEF 0x3137
+#define OSDSR_VAR_PARA 0x3138
+#define OSDSR_CONST_PARA 0x3139
+#define OSDSR_RKE_EXTWIN 0x313a
+#define OSDSR_UK_GRAD2DDIAG_TH_RATE 0x313b
+#define OSDSR_UK_GRAD2DDIAG_LIMIT 0x313c
+#define OSDSR_UK_GRAD2DADJA_TH_RATE 0x313d
+#define OSDSR_UK_GRAD2DADJA_LIMIT 0x313e
+#define OSDSR_UK_BST_GAIN 0x313f
+#define OSDSR_HVBLEND_TH 0x3140
+#define OSDSR_DEMO_WIND_TB 0x3141
+#define OSDSR_DEMO_WIND_LR 0x3142
+#define OSDSR_INT_BLANK_NUM 0x3143
+#define OSDSR_FRM_END_STAT 0x3144
+#define OSDSR_ABIC_HCOEF0 0x3145
+#define OSDSR_YBIC_HCOEF0 0x3146
+#define OSDSR_CBIC_HCOEF0 0x3147
+#define OSDSR_ABIC_VCOEF0 0x3148
+#define OSDSR_YBIC_VCOEF0 0x3149
+#define OSDSR_CBIC_VCOEF0 0x314a
+
+#endif /* __MESON_REGISTERS_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vclk.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vclk.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vclk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vclk.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_vclk.h"
+
+/*
+ * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
+ * We handle the following encodings :
+ * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
+ *
+ * What is missing :
+ * - HDMI Pixel Clocks generation
+ */
+
+/* HHI Registers */
+#define HHI_VID_PLL_CLK_DIV	0x1a0 /* 0x68 offset in data sheet */
+#define VID_PLL_EN		BIT(19)
+#define VID_PLL_BYPASS		BIT(18)
+#define VID_PLL_PRESET		BIT(15)
+#define HHI_VIID_CLK_DIV	0x128 /* 0x4a offset in data sheet */
+#define VCLK2_DIV_MASK		0xff
+#define VCLK2_DIV_EN		BIT(16)
+#define VCLK2_DIV_RESET		BIT(17)
+#define CTS_VDAC_SEL_MASK	(0xf << 28)
+#define CTS_VDAC_SEL_SHIFT	28
+#define HHI_VIID_CLK_CNTL	0x12c /* 0x4b offset in data sheet */
+#define VCLK2_EN		BIT(19)
+#define VCLK2_SEL_MASK		(0x7 << 16)
+#define VCLK2_SEL_SHIFT		16
+#define VCLK2_SOFT_RESET	BIT(15)
+#define VCLK2_DIV1_EN		BIT(0)
+#define HHI_VID_CLK_DIV		0x164 /* 0x59 offset in data sheet */
+#define CTS_ENCI_SEL_MASK	(0xf << 28)
+#define CTS_ENCI_SEL_SHIFT	28
+#define HHI_VID_CLK_CNTL2	0x194 /* 0x65 offset in data sheet */
+#define CTS_ENCI_EN		BIT(0)
+#define CTS_VDAC_EN		BIT(4)
+
+#define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
+
+#define HHI_HDMI_PLL_CNTL	0x320 /* 0xc8 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL2	0x324 /* 0xc9 offset in data sheet */
+#define HHI_HDMI_PLL_CNTL3	0x328 /* 0xca offset in data sheet */
+#define HHI_HDMI_PLL_CNTL4	0x32C /* 0xcb offset in data sheet */
+#define HHI_HDMI_PLL_CNTL5	0x330 /* 0xcc offset in data sheet */
+#define HHI_HDMI_PLL_CNTL6	0x334 /* 0xcd offset in data sheet */
+
+#define HDMI_PLL_RESET		BIT(28)
+#define HDMI_PLL_LOCK		BIT(31)
+
+/*
+ * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
+ *
+ * TOFIX: Refactor into table to also handle HDMI frequency and paths
+ */
+static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
+{
+	unsigned int val;
+
+	/* Setup PLL to output 1.485GHz */
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00404e00);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
+	} else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+		   meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0xa6212844);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
+		regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
+
+		/* Reset PLL */
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET, HDMI_PLL_RESET);
+		regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
+					HDMI_PLL_RESET, 0);
+	}
+
+	/* Poll for lock bit */
+	regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
+				 (val & HDMI_PLL_LOCK), 10, 0);
+
+	/* Disable VCLK2 */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
+
+	/* Disable vid_pll output clock */
+	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
+	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
+	/* Enable vid_pll bypass to HDMI pll */
+	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				VID_PLL_BYPASS, VID_PLL_BYPASS);
+	/* Enable the vid_pll output clock */
+	regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
+				VID_PLL_EN, VID_PLL_EN);
+
+	/* Setup the VCLK2 divider value to achieve 27MHz */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+				VCLK2_DIV_MASK, (55 - 1));
+
+	/* select vid_pll for vclk2 */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+				VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
+	/* enable vclk2 gate */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
+
+	/* select vclk_div1 for enci */
+	regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
+				CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
+	/* select vclk_div1 for vdac */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+				CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
+
+	/* release vclk2_div_reset and enable vclk2_div */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
+				VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
+
+	/* enable vclk2_div1 gate */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+				VCLK2_DIV1_EN, VCLK2_DIV1_EN);
+
+	/* reset vclk2 */
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+				VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
+	regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
+				VCLK2_SOFT_RESET, 0);
+
+	/* enable enci_clk */
+	regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+				CTS_ENCI_EN, CTS_ENCI_EN);
+	/* enable vdac_clk */
+	regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
+				CTS_VDAC_EN, CTS_VDAC_EN);
+}
+
+void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+		      unsigned int freq)
+{
+	if (target == MESON_VCLK_TARGET_CVBS && freq == MESON_VCLK_CVBS)
+		meson_venci_cvbs_clock_config(priv);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vclk.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vclk.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vclk.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vclk.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.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/>.
+ */
+
+/* Video Clock */
+
+#ifndef __MESON_VCLK_H
+#define __MESON_VCLK_H
+
+enum {
+	MESON_VCLK_TARGET_CVBS = 0,
+};
+
+/* 27MHz is the CVBS Pixel Clock */
+#define MESON_VCLK_CVBS	27000
+
+void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+		      unsigned int freq);
+
+#endif /* __MESON_VCLK_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_venc.h"
+#include "meson_vpp.h"
+#include "meson_vclk.h"
+#include "meson_registers.h"
+
+/*
+ * VENC Handle the pixels encoding to the output formats.
+ * We handle the following encodings :
+ * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
+ *
+ * What is missing :
+ * - TMDS/HDMI Encoding via ENCI_DIV and ENCP
+ * - Setup of more clock rates for HDMI modes
+ * - LCD Panel encoding via ENCL
+ * - TV Panel encoding via ENCT
+ */
+
+/* HHI Registers */
+#define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
+#define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */
+
+struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
+	.mode_tag = MESON_VENC_MODE_CVBS_PAL,
+	.hso_begin = 3,
+	.hso_end = 129,
+	.vso_even = 3,
+	.vso_odd = 260,
+	.macv_max_amp = 7,
+	.video_prog_mode = 0xff,
+	.video_mode = 0x13,
+	.sch_adjust = 0x28,
+	.yc_delay = 0x343,
+	.pixel_start = 251,
+	.pixel_end = 1691,
+	.top_field_line_start = 22,
+	.top_field_line_end = 310,
+	.bottom_field_line_start = 23,
+	.bottom_field_line_end = 311,
+	.video_saturation = 9,
+	.video_contrast = 0,
+	.video_brightness = 0,
+	.video_hue = 0,
+	.analog_sync_adj = 0x8080,
+};
+
+struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
+	.mode_tag = MESON_VENC_MODE_CVBS_NTSC,
+	.hso_begin = 5,
+	.hso_end = 129,
+	.vso_even = 3,
+	.vso_odd = 260,
+	.macv_max_amp = 0xb,
+	.video_prog_mode = 0xf0,
+	.video_mode = 0x8,
+	.sch_adjust = 0x20,
+	.yc_delay = 0x333,
+	.pixel_start = 227,
+	.pixel_end = 1667,
+	.top_field_line_start = 18,
+	.top_field_line_end = 258,
+	.bottom_field_line_start = 19,
+	.bottom_field_line_end = 259,
+	.video_saturation = 18,
+	.video_contrast = 3,
+	.video_brightness = 0,
+	.video_hue = 0,
+	.analog_sync_adj = 0x9c00,
+};
+
+void meson_venci_cvbs_mode_set(struct meson_drm *priv,
+			       struct meson_cvbs_enci_mode *mode)
+{
+	if (mode->mode_tag == priv->venc.current_mode)
+		return;
+
+	/* CVBS Filter settings */
+	writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
+	writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
+
+	/* Digital Video Select : Interlace, clk27 clk, external */
+	writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
+
+	/* Reset Video Mode */
+	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
+	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+
+	/* Horizontal sync signal output */
+	writel_relaxed(mode->hso_begin,
+			priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
+	writel_relaxed(mode->hso_end,
+			priv->io_base + _REG(ENCI_SYNC_HSO_END));
+
+	/* Vertical Sync lines */
+	writel_relaxed(mode->vso_even,
+			priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
+	writel_relaxed(mode->vso_odd,
+			priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
+
+	/* Macrovision max amplitude change */
+	writel_relaxed(0x8100 + mode->macv_max_amp,
+			priv->io_base + _REG(ENCI_MACV_MAX_AMP));
+
+	/* Video mode */
+	writel_relaxed(mode->video_prog_mode,
+			priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
+	writel_relaxed(mode->video_mode,
+			priv->io_base + _REG(ENCI_VIDEO_MODE));
+
+	/* Advanced Video Mode :
+	 * Demux shifting 0x2
+	 * Blank line end at line17/22
+	 * High bandwidth Luma Filter
+	 * Low bandwidth Chroma Filter
+	 * Bypass luma low pass filter
+	 * No macrovision on CSYNC
+	 */
+	writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
+
+	writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
+
+	/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
+	writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
+
+	/* 0x3 Y, C, and Component Y delay */
+	writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
+
+	/* Timings */
+	writel_relaxed(mode->pixel_start,
+			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
+	writel_relaxed(mode->pixel_end,
+			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
+
+	writel_relaxed(mode->top_field_line_start,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
+	writel_relaxed(mode->top_field_line_end,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
+
+	writel_relaxed(mode->bottom_field_line_start,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
+	writel_relaxed(mode->bottom_field_line_end,
+			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
+
+	/* Internal Venc, Internal VIU Sync, Internal Vencoder */
+	writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
+
+	/* UNreset Interlaced TV Encoder */
+	writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
+
+	/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
+	writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
+
+	/* Power UP Dacs */
+	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));
+
+	/* Video Upsampling */
+	writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
+	writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
+	writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
+
+	/* Select Interlace Y DACs */
+	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
+	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
+	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
+	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
+	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
+	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));
+
+	/* Select ENCI for VIU */
+	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
+
+	/* Enable ENCI FIFO */
+	writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
+
+	/* Select ENCI DACs 0, 1, 4, and 5 */
+	writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
+	writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
+
+	/* Interlace video enable */
+	writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
+
+	/* Configure Video Saturation / Contrast / Brightness / Hue */
+	writel_relaxed(mode->video_saturation,
+			priv->io_base + _REG(ENCI_VIDEO_SAT));
+	writel_relaxed(mode->video_contrast,
+			priv->io_base + _REG(ENCI_VIDEO_CONT));
+	writel_relaxed(mode->video_brightness,
+			priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
+	writel_relaxed(mode->video_hue,
+			priv->io_base + _REG(ENCI_VIDEO_HUE));
+
+	/* Enable DAC0 Filter */
+	writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
+	writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
+
+	/* 0 in Macrovision register 0 */
+	writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0));
+
+	/* Analog Synchronization and color burst value adjust */
+	writel_relaxed(mode->analog_sync_adj,
+			priv->io_base + _REG(ENCI_SYNC_ADJ));
+
+	/* Setup 27MHz vclk2 for ENCI and VDAC */
+	meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS);
+
+	priv->venc.current_mode = mode->mode_tag;
+}
+
+/* Returns the current ENCI field polarity */
+unsigned int meson_venci_get_field(struct meson_drm *priv)
+{
+	return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29);
+}
+
+void meson_venc_enable_vsync(struct meson_drm *priv)
+{
+	writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
+}
+
+void meson_venc_disable_vsync(struct meson_drm *priv)
+{
+	writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
+}
+
+void meson_venc_init(struct meson_drm *priv)
+{
+	/* Disable CVBS VDAC */
+	regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
+	regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
+
+	/* Power Down Dacs */
+	writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
+
+	/* Disable HDMI PHY */
+	regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
+
+	/* Disable HDMI */
+	writel_bits_relaxed(0x3, 0,
+			    priv->io_base + _REG(VPU_HDMI_SETTING));
+
+	/* Disable all encoders */
+	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
+	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
+	writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
+
+	/* Disable VSync IRQ */
+	meson_venc_disable_vsync(priv);
+
+	priv->venc.current_mode = MESON_VENC_MODE_NONE;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_atomic_helper.h>
+
+#include "meson_venc_cvbs.h"
+#include "meson_venc.h"
+#include "meson_registers.h"
+
+/* HHI VDAC Registers */
+#define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
+#define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
+
+struct meson_venc_cvbs {
+	struct drm_encoder	encoder;
+	struct drm_connector	connector;
+	struct meson_drm	*priv;
+};
+#define encoder_to_meson_venc_cvbs(x) \
+	container_of(x, struct meson_venc_cvbs, encoder)
+
+#define connector_to_meson_venc_cvbs(x) \
+	container_of(x, struct meson_venc_cvbs, connector)
+
+/* Supported Modes */
+
+struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = {
+	{ /* PAL */
+		.enci = &meson_cvbs_enci_pal,
+		.mode = {
+			DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500,
+				 720, 732, 795, 864, 0, 576, 580, 586, 625, 0,
+				 DRM_MODE_FLAG_INTERLACE),
+			.vrefresh = 50,
+			.picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
+		},
+	},
+	{ /* NTSC */
+		.enci = &meson_cvbs_enci_ntsc,
+		.mode = {
+			DRM_MODE("720x480i", DRM_MODE_TYPE_DRIVER, 13500,
+				720, 739, 801, 858, 0, 480, 488, 494, 525, 0,
+				DRM_MODE_FLAG_INTERLACE),
+			.vrefresh = 60,
+			.picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3,
+		},
+	},
+};
+
+/* Connector */
+
+static void meson_cvbs_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+meson_cvbs_connector_detect(struct drm_connector *connector, bool force)
+{
+	/* FIXME: Add load-detect or jack-detect if possible */
+	return connector_status_connected;
+}
+
+static int meson_cvbs_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode;
+	int i;
+
+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+		mode = drm_mode_duplicate(dev, &meson_mode->mode);
+		if (!mode) {
+			DRM_ERROR("Failed to create a new display mode\n");
+			return 0;
+		}
+
+		drm_mode_probed_add(connector, mode);
+	}
+
+	return i;
+}
+
+static int meson_cvbs_connector_mode_valid(struct drm_connector *connector,
+					   struct drm_display_mode *mode)
+{
+	/* Validate the modes added in get_modes */
+	return MODE_OK;
+}
+
+static const struct drm_connector_funcs meson_cvbs_connector_funcs = {
+	.dpms			= drm_atomic_helper_connector_dpms,
+	.detect			= meson_cvbs_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= meson_cvbs_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static const
+struct drm_connector_helper_funcs meson_cvbs_connector_helper_funcs = {
+	.get_modes	= meson_cvbs_connector_get_modes,
+	.mode_valid	= meson_cvbs_connector_mode_valid,
+};
+
+/* Encoder */
+
+static void meson_venc_cvbs_encoder_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs meson_venc_cvbs_encoder_funcs = {
+	.destroy        = meson_venc_cvbs_encoder_destroy,
+};
+
+static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state)
+{
+	int i;
+
+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+		if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode))
+			return 0;
+	}
+
+	return -EINVAL;
+}
+
+static void meson_venc_cvbs_encoder_disable(struct drm_encoder *encoder)
+{
+	struct meson_venc_cvbs *meson_venc_cvbs =
+					encoder_to_meson_venc_cvbs(encoder);
+	struct meson_drm *priv = meson_venc_cvbs->priv;
+
+	/* Disable CVBS VDAC */
+	regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
+	regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
+}
+
+static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder)
+{
+	struct meson_venc_cvbs *meson_venc_cvbs =
+					encoder_to_meson_venc_cvbs(encoder);
+	struct meson_drm *priv = meson_venc_cvbs->priv;
+
+	/* VDAC0 source is not from ATV */
+	writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
+
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
+		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1);
+	else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+		 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0xf0001);
+
+	regmap_write(priv->hhi, HHI_VDAC_CNTL1, 0);
+}
+
+static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
+				   struct drm_display_mode *mode,
+				   struct drm_display_mode *adjusted_mode)
+{
+	struct meson_venc_cvbs *meson_venc_cvbs =
+					encoder_to_meson_venc_cvbs(encoder);
+	int i;
+
+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+		if (drm_mode_equal(mode, &meson_mode->mode)) {
+			meson_venci_cvbs_mode_set(meson_venc_cvbs->priv,
+						  meson_mode->enci);
+			break;
+		}
+	}
+}
+
+static const struct drm_encoder_helper_funcs
+				meson_venc_cvbs_encoder_helper_funcs = {
+	.atomic_check	= meson_venc_cvbs_encoder_atomic_check,
+	.disable	= meson_venc_cvbs_encoder_disable,
+	.enable		= meson_venc_cvbs_encoder_enable,
+	.mode_set	= meson_venc_cvbs_encoder_mode_set,
+};
+
+static bool meson_venc_cvbs_connector_is_available(struct meson_drm *priv)
+{
+	struct device_node *ep, *remote;
+
+	/* CVBS VDAC output is on the first port, first endpoint */
+	ep = of_graph_get_endpoint_by_regs(priv->dev->of_node, 0, 0);
+	if (!ep)
+		return false;
+
+
+	/* If the endpoint node exists, consider it enabled */
+	remote = of_graph_get_remote_port(ep);
+	if (remote) {
+		of_node_put(ep);
+		return true;
+	}
+
+	of_node_put(ep);
+	of_node_put(remote);
+
+	return false;
+}
+
+int meson_venc_cvbs_create(struct meson_drm *priv)
+{
+	struct drm_device *drm = priv->drm;
+	struct meson_venc_cvbs *meson_venc_cvbs;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	int ret;
+
+	if (!meson_venc_cvbs_connector_is_available(priv)) {
+		dev_info(drm->dev, "CVBS Output connector not available\n");
+		return -ENODEV;
+	}
+
+	meson_venc_cvbs = devm_kzalloc(priv->dev, sizeof(*meson_venc_cvbs),
+				       GFP_KERNEL);
+	if (!meson_venc_cvbs)
+		return -ENOMEM;
+
+	meson_venc_cvbs->priv = priv;
+	encoder = &meson_venc_cvbs->encoder;
+	connector = &meson_venc_cvbs->connector;
+
+	/* Connector */
+
+	drm_connector_helper_add(connector,
+				 &meson_cvbs_connector_helper_funcs);
+
+	ret = drm_connector_init(drm, connector, &meson_cvbs_connector_funcs,
+				 DRM_MODE_CONNECTOR_Composite);
+	if (ret) {
+		dev_err(priv->dev, "Failed to init CVBS connector\n");
+		return ret;
+	}
+
+	connector->interlace_allowed = 1;
+
+	/* Encoder */
+
+	drm_encoder_helper_add(encoder, &meson_venc_cvbs_encoder_helper_funcs);
+
+	ret = drm_encoder_init(drm, encoder, &meson_venc_cvbs_encoder_funcs,
+			       DRM_MODE_ENCODER_TVDAC, "meson_venc_cvbs");
+	if (ret) {
+		dev_err(priv->dev, "Failed to init CVBS encoder\n");
+		return ret;
+	}
+
+	encoder->possible_crtcs = BIT(0);
+
+	drm_mode_connector_attach_encoder(connector, encoder);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc_cvbs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre@mecheye.net>
+ */
+
+#ifndef __MESON_VENC_CVBS_H
+#define __MESON_VENC_CVBS_H
+
+#include "meson_drv.h"
+#include "meson_venc.h"
+
+struct meson_cvbs_mode {
+	struct meson_cvbs_enci_mode *enci;
+	struct drm_display_mode mode;
+};
+
+#define MESON_CVBS_MODES_COUNT	2
+
+/* Modes supported by the CVBS output */
+extern struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT];
+
+int meson_venc_cvbs_create(struct meson_drm *priv);
+
+#endif /* __MESON_VENC_CVBS_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_venc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_venc.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.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/>.
+ */
+
+/*
+ * Video Encoders
+ * - ENCI : Interlace Video Encoder
+ * - ENCI_DVI : Interlace Video Encoder for DVI/HDMI
+ * - ENCP : Progressive Video Encoder
+ */
+
+#ifndef __MESON_VENC_H
+#define __MESON_VENC_H
+
+enum {
+	MESON_VENC_MODE_NONE = 0,
+	MESON_VENC_MODE_CVBS_PAL,
+	MESON_VENC_MODE_CVBS_NTSC,
+};
+
+struct meson_cvbs_enci_mode {
+	unsigned int mode_tag;
+	unsigned int hso_begin; /* HSO begin position */
+	unsigned int hso_end; /* HSO end position */
+	unsigned int vso_even; /* VSO even line */
+	unsigned int vso_odd; /* VSO odd line */
+	unsigned int macv_max_amp; /* Macrovision max amplitude */
+	unsigned int video_prog_mode;
+	unsigned int video_mode;
+	unsigned int sch_adjust;
+	unsigned int yc_delay;
+	unsigned int pixel_start;
+	unsigned int pixel_end;
+	unsigned int top_field_line_start;
+	unsigned int top_field_line_end;
+	unsigned int bottom_field_line_start;
+	unsigned int bottom_field_line_end;
+	unsigned int video_saturation;
+	unsigned int video_contrast;
+	unsigned int video_brightness;
+	unsigned int video_hue;
+	unsigned int analog_sync_adj;
+};
+
+/* CVBS Timings and Parameters */
+extern struct meson_cvbs_enci_mode meson_cvbs_enci_pal;
+extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc;
+
+void meson_venci_cvbs_mode_set(struct meson_drm *priv,
+			       struct meson_cvbs_enci_mode *mode);
+unsigned int meson_venci_get_field(struct meson_drm *priv);
+
+void meson_venc_enable_vsync(struct meson_drm *priv);
+void meson_venc_disable_vsync(struct meson_drm *priv);
+
+void meson_venc_init(struct meson_drm *priv);
+
+#endif /* __MESON_VENC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_viu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_viu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_viu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_viu.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_viu.h"
+#include "meson_vpp.h"
+#include "meson_venc.h"
+#include "meson_canvas.h"
+#include "meson_registers.h"
+
+/*
+ * VIU Handles the Pixel scanout and the basic Colorspace conversions
+ * We handle the following features :
+ * - OSD1 RGB565/RGB888/xRGB8888 scanout
+ * - RGB conversion to x/cb/cr
+ * - Progressive or Interlace buffer scanout
+ * - OSD1 Commit on Vsync
+ * - HDR OSD matrix for GXL/GXM
+ *
+ * What is missing :
+ * - BGR888/xBGR8888/BGRx8888/BGRx8888 modes
+ * - YUV4:2:2 Y0CbY1Cr scanout
+ * - Conversion to YUV 4:4:4 from 4:2:2 input
+ * - Colorkey Alpha matching
+ * - Big endian scanout
+ * - X/Y reverse scanout
+ * - Global alpha setup
+ * - OSD2 support, would need interlace switching on vsync
+ * - OSD1 full scaling to support TV overscan
+ */
+
+/* OSD csc defines */
+
+enum viu_matrix_sel_e {
+	VIU_MATRIX_OSD_EOTF = 0,
+	VIU_MATRIX_OSD,
+};
+
+enum viu_lut_sel_e {
+	VIU_LUT_OSD_EOTF = 0,
+	VIU_LUT_OSD_OETF,
+};
+
+#define COEFF_NORM(a) ((int)((((a) * 2048.0) + 1) / 2))
+#define MATRIX_5X3_COEF_SIZE 24
+
+#define EOTF_COEFF_NORM(a) ((int)((((a) * 4096.0) + 1) / 2))
+#define EOTF_COEFF_SIZE 10
+#define EOTF_COEFF_RIGHTSHIFT 1
+
+static int RGB709_to_YUV709l_coeff[MATRIX_5X3_COEF_SIZE] = {
+	0, 0, 0, /* pre offset */
+	COEFF_NORM(0.181873),	COEFF_NORM(0.611831),	COEFF_NORM(0.061765),
+	COEFF_NORM(-0.100251),	COEFF_NORM(-0.337249),	COEFF_NORM(0.437500),
+	COEFF_NORM(0.437500),	COEFF_NORM(-0.397384),	COEFF_NORM(-0.040116),
+	0, 0, 0, /* 10'/11'/12' */
+	0, 0, 0, /* 20'/21'/22' */
+	64, 512, 512, /* offset */
+	0, 0, 0 /* mode, right_shift, clip_en */
+};
+
+/*  eotf matrix: bypass */
+static int eotf_bypass_coeff[EOTF_COEFF_SIZE] = {
+	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),
+	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),	EOTF_COEFF_NORM(0.0),
+	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(0.0),	EOTF_COEFF_NORM(1.0),
+	EOTF_COEFF_RIGHTSHIFT /* right shift */
+};
+
+void meson_viu_set_osd_matrix(struct meson_drm *priv,
+			      enum viu_matrix_sel_e m_select,
+			      int *m, bool csc_on)
+{
+	if (m_select == VIU_MATRIX_OSD) {
+		/* osd matrix, VIU_MATRIX_0 */
+		writel(((m[0] & 0xfff) << 16) | (m[1] & 0xfff),
+			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET0_1));
+		writel(m[2] & 0xfff,
+			priv->io_base + _REG(VIU_OSD1_MATRIX_PRE_OFFSET2));
+		writel(((m[3] & 0x1fff) << 16) | (m[4] & 0x1fff),
+			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF00_01));
+		writel(((m[5] & 0x1fff) << 16) | (m[6] & 0x1fff),
+			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF02_10));
+		writel(((m[7] & 0x1fff) << 16) | (m[8] & 0x1fff),
+			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF11_12));
+		writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
+			priv->io_base + _REG(VIU_OSD1_MATRIX_COEF20_21));
+
+		if (m[21]) {
+			writel(((m[11] & 0x1fff) << 16) | (m[12] & 0x1fff),
+				priv->io_base +
+					_REG(VIU_OSD1_MATRIX_COEF22_30));
+			writel(((m[13] & 0x1fff) << 16) | (m[14] & 0x1fff),
+				priv->io_base +
+					_REG(VIU_OSD1_MATRIX_COEF31_32));
+			writel(((m[15] & 0x1fff) << 16) | (m[16] & 0x1fff),
+				priv->io_base +
+					_REG(VIU_OSD1_MATRIX_COEF40_41));
+			writel(m[17] & 0x1fff, priv->io_base +
+				_REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
+		} else
+			writel((m[11] & 0x1fff) << 16, priv->io_base +
+				_REG(VIU_OSD1_MATRIX_COEF22_30));
+
+		writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
+			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET0_1));
+		writel(m[20] & 0xfff,
+			priv->io_base + _REG(VIU_OSD1_MATRIX_OFFSET2));
+
+		writel_bits_relaxed(3 << 30, m[21] << 30,
+			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
+		writel_bits_relaxed(7 << 16, m[22] << 16,
+			priv->io_base + _REG(VIU_OSD1_MATRIX_COLMOD_COEF42));
+
+		/* 23 reserved for clipping control */
+		writel_bits_relaxed(BIT(0), csc_on ? BIT(0) : 0,
+			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
+		writel_bits_relaxed(BIT(1), 0,
+			priv->io_base + _REG(VIU_OSD1_MATRIX_CTRL));
+	} else if (m_select == VIU_MATRIX_OSD_EOTF) {
+		int i;
+
+		/* osd eotf matrix, VIU_MATRIX_OSD_EOTF */
+		for (i = 0; i < 5; i++)
+			writel(((m[i * 2] & 0x1fff) << 16) |
+				(m[i * 2 + 1] & 0x1fff), priv->io_base +
+				_REG(VIU_OSD1_EOTF_CTL + i + 1));
+
+		writel_bits_relaxed(BIT(30), csc_on ? BIT(30) : 0,
+			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
+		writel_bits_relaxed(BIT(31), csc_on ? BIT(31) : 0,
+			priv->io_base + _REG(VIU_OSD1_EOTF_CTL));
+	}
+}
+
+#define OSD_EOTF_LUT_SIZE 33
+#define OSD_OETF_LUT_SIZE 41
+
+void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
+			   unsigned int *r_map, unsigned int *g_map,
+			   unsigned int *b_map,
+			   bool csc_on)
+{
+	unsigned int addr_port;
+	unsigned int data_port;
+	unsigned int ctrl_port;
+	int i;
+
+	if (lut_sel == VIU_LUT_OSD_EOTF) {
+		addr_port = VIU_OSD1_EOTF_LUT_ADDR_PORT;
+		data_port = VIU_OSD1_EOTF_LUT_DATA_PORT;
+		ctrl_port = VIU_OSD1_EOTF_CTL;
+	} else if (lut_sel == VIU_LUT_OSD_OETF) {
+		addr_port = VIU_OSD1_OETF_LUT_ADDR_PORT;
+		data_port = VIU_OSD1_OETF_LUT_DATA_PORT;
+		ctrl_port = VIU_OSD1_OETF_CTL;
+	} else
+		return;
+
+	if (lut_sel == VIU_LUT_OSD_OETF) {
+		writel(0, priv->io_base + _REG(addr_port));
+
+		for (i = 0; i < 20; i++)
+			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
+				priv->io_base + _REG(data_port));
+
+		writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
+			priv->io_base + _REG(data_port));
+
+		for (i = 0; i < 20; i++)
+			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
+				priv->io_base + _REG(data_port));
+
+		for (i = 0; i < 20; i++)
+			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
+				priv->io_base + _REG(data_port));
+
+		writel(b_map[OSD_OETF_LUT_SIZE - 1],
+			priv->io_base + _REG(data_port));
+
+		if (csc_on)
+			writel_bits_relaxed(0x7 << 29, 7 << 29,
+					    priv->io_base + _REG(ctrl_port));
+		else
+			writel_bits_relaxed(0x7 << 29, 0,
+					    priv->io_base + _REG(ctrl_port));
+	} else if (lut_sel == VIU_LUT_OSD_EOTF) {
+		writel(0, priv->io_base + _REG(addr_port));
+
+		for (i = 0; i < 20; i++)
+			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
+				priv->io_base + _REG(data_port));
+
+		writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
+			priv->io_base + _REG(data_port));
+
+		for (i = 0; i < 20; i++)
+			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
+				priv->io_base + _REG(data_port));
+
+		for (i = 0; i < 20; i++)
+			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
+				priv->io_base + _REG(data_port));
+
+		writel(b_map[OSD_EOTF_LUT_SIZE - 1],
+			priv->io_base + _REG(data_port));
+
+		if (csc_on)
+			writel_bits_relaxed(7 << 27, 7 << 27,
+					    priv->io_base + _REG(ctrl_port));
+		else
+			writel_bits_relaxed(7 << 27, 0,
+					    priv->io_base + _REG(ctrl_port));
+
+		writel_bits_relaxed(BIT(31), BIT(31),
+				    priv->io_base + _REG(ctrl_port));
+	}
+}
+
+/* eotf lut: linear */
+static unsigned int eotf_33_linear_mapping[OSD_EOTF_LUT_SIZE] = {
+	0x0000,	0x0200,	0x0400, 0x0600,
+	0x0800, 0x0a00, 0x0c00, 0x0e00,
+	0x1000, 0x1200, 0x1400, 0x1600,
+	0x1800, 0x1a00, 0x1c00, 0x1e00,
+	0x2000, 0x2200, 0x2400, 0x2600,
+	0x2800, 0x2a00, 0x2c00, 0x2e00,
+	0x3000, 0x3200, 0x3400, 0x3600,
+	0x3800, 0x3a00, 0x3c00, 0x3e00,
+	0x4000
+};
+
+/* osd oetf lut: linear */
+static unsigned int oetf_41_linear_mapping[OSD_OETF_LUT_SIZE] = {
+	0, 0, 0, 0,
+	0, 32, 64, 96,
+	128, 160, 196, 224,
+	256, 288, 320, 352,
+	384, 416, 448, 480,
+	512, 544, 576, 608,
+	640, 672, 704, 736,
+	768, 800, 832, 864,
+	896, 928, 960, 992,
+	1023, 1023, 1023, 1023,
+	1023
+};
+
+static void meson_viu_load_matrix(struct meson_drm *priv)
+{
+	/* eotf lut bypass */
+	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_EOTF,
+			      eotf_33_linear_mapping, /* R */
+			      eotf_33_linear_mapping, /* G */
+			      eotf_33_linear_mapping, /* B */
+			      false);
+
+	/* eotf matrix bypass */
+	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD_EOTF,
+				 eotf_bypass_coeff,
+				 false);
+
+	/* oetf lut bypass */
+	meson_viu_set_osd_lut(priv, VIU_LUT_OSD_OETF,
+			      oetf_41_linear_mapping, /* R */
+			      oetf_41_linear_mapping, /* G */
+			      oetf_41_linear_mapping, /* B */
+			      false);
+
+	/* osd matrix RGB709 to YUV709 limit */
+	meson_viu_set_osd_matrix(priv, VIU_MATRIX_OSD,
+				 RGB709_to_YUV709l_coeff,
+				 true);
+}
+
+void meson_viu_init(struct meson_drm *priv)
+{
+	uint32_t reg;
+
+	/* Disable OSDs */
+	writel_bits_relaxed(BIT(0) | BIT(21), 0,
+			priv->io_base + _REG(VIU_OSD1_CTRL_STAT));
+	writel_bits_relaxed(BIT(0) | BIT(21), 0,
+			priv->io_base + _REG(VIU_OSD2_CTRL_STAT));
+
+	/* On GXL/GXM, Use the 10bit HDR conversion matrix */
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+	    meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+		meson_viu_load_matrix(priv);
+
+	/* Initialize OSD1 fifo control register */
+	reg = BIT(0) |	/* Urgent DDR request priority */
+	      (4 << 5) | /* hold_fifo_lines */
+	      (3 << 10) | /* burst length 64 */
+	      (32 << 12) | /* fifo_depth_val: 32*8=256 */
+	      (2 << 22) | /* 4 words in 1 burst */
+	      (2 << 24);
+	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT));
+	writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT));
+
+	/* Set OSD alpha replace value */
+	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
+			    0xff << OSD_REPLACE_SHIFT,
+			    priv->io_base + _REG(VIU_OSD1_CTRL_STAT2));
+	writel_bits_relaxed(0xff << OSD_REPLACE_SHIFT,
+			    0xff << OSD_REPLACE_SHIFT,
+			    priv->io_base + _REG(VIU_OSD2_CTRL_STAT2));
+
+	priv->viu.osd1_enabled = false;
+	priv->viu.osd1_commit = false;
+	priv->viu.osd1_interlace = false;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_viu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_viu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_viu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_viu.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.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/>.
+ */
+
+/* Video Input Unit */
+
+#ifndef __MESON_VIU_H
+#define __MESON_VIU_H
+
+/* OSDx_BLKx_CFG */
+#define OSD_CANVAS_SEL		16
+
+#define OSD_ENDIANNESS_LE	BIT(15)
+#define OSD_ENDIANNESS_BE	(0)
+
+#define OSD_BLK_MODE_422	(0x03 << 8)
+#define OSD_BLK_MODE_16		(0x04 << 8)
+#define OSD_BLK_MODE_32		(0x05 << 8)
+#define OSD_BLK_MODE_24		(0x07 << 8)
+
+#define OSD_OUTPUT_COLOR_RGB	BIT(7)
+#define OSD_OUTPUT_COLOR_YUV	(0)
+
+#define OSD_COLOR_MATRIX_32_RGBA	(0x00 << 2)
+#define OSD_COLOR_MATRIX_32_ARGB	(0x01 << 2)
+#define OSD_COLOR_MATRIX_32_ABGR	(0x02 << 2)
+#define OSD_COLOR_MATRIX_32_BGRA	(0x03 << 2)
+
+#define OSD_COLOR_MATRIX_24_RGB		(0x00 << 2)
+
+#define OSD_COLOR_MATRIX_16_RGB655	(0x00 << 2)
+#define OSD_COLOR_MATRIX_16_RGB565	(0x04 << 2)
+
+#define OSD_INTERLACE_ENABLED	BIT(1)
+#define OSD_INTERLACE_ODD	BIT(0)
+#define OSD_INTERLACE_EVEN	(0)
+
+/* OSDx_CTRL_STAT */
+#define OSD_ENABLE		BIT(21)
+#define OSD_BLK0_ENABLE		BIT(0)
+
+#define OSD_GLOBAL_ALPHA_SHIFT	12
+
+/* OSDx_CTRL_STAT2 */
+#define OSD_REPLACE_EN		BIT(14)
+#define OSD_REPLACE_SHIFT	6
+
+void meson_viu_init(struct meson_drm *priv);
+
+#endif /* __MESON_VIU_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vpp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vpp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vpp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vpp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ * Copyright (C) 2014 Endless Mobile
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/module.h>
+#include <drm/drmP.h>
+#include "meson_drv.h"
+#include "meson_vpp.h"
+#include "meson_registers.h"
+
+/*
+ * VPP Handles all the Post Processing after the Scanout from the VIU
+ * We handle the following post processings :
+ * - Postblend : Blends the OSD1 only
+ *	We exclude OSD2, VS1, VS1 and Preblend output
+ * - Vertical OSD Scaler for OSD1 only, we disable vertical scaler and
+ *	use it only for interlace scanout
+ * - Intermediate FIFO with default Amlogic values
+ *
+ * What is missing :
+ * - Preblend for video overlay pre-scaling
+ * - OSD2 support for cursor framebuffer
+ * - Video pre-scaling before postblend
+ * - Full Vertical/Horizontal OSD scaling to support TV overscan
+ * - HDR conversion
+ */
+
+void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux)
+{
+	writel(mux, priv->io_base + _REG(VPU_VIU_VENC_MUX_CTRL));
+}
+
+/*
+ * When the output is interlaced, the OSD must switch between
+ * each field using the INTERLACE_SEL_ODD (0) of VIU_OSD1_BLK0_CFG_W0
+ * at each vsync.
+ * But the vertical scaler can provide such funtionnality if
+ * is configured for 2:1 scaling with interlace options enabled.
+ */
+void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
+					    struct drm_rect *input)
+{
+	writel_relaxed(BIT(3) /* Enable scaler */ |
+		       BIT(2), /* Select OSD1 */
+			priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+
+	writel_relaxed(((drm_rect_width(input) - 1) << 16) |
+		       (drm_rect_height(input) - 1),
+			priv->io_base + _REG(VPP_OSD_SCI_WH_M1));
+	/* 2:1 scaling */
+	writel_relaxed(((input->x1) << 16) | (input->x2),
+			priv->io_base + _REG(VPP_OSD_SCO_H_START_END));
+	writel_relaxed(((input->y1 >> 1) << 16) | (input->y2 >> 1),
+			priv->io_base + _REG(VPP_OSD_SCO_V_START_END));
+
+	/* 2:1 scaling values */
+	writel_relaxed(BIT(16), priv->io_base + _REG(VPP_OSD_VSC_INI_PHASE));
+	writel_relaxed(BIT(25), priv->io_base + _REG(VPP_OSD_VSC_PHASE_STEP));
+
+	writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+
+	writel_relaxed((4 << 0) /* osd_vsc_bank_length */ |
+		       (4 << 3) /* osd_vsc_top_ini_rcv_num0 */ |
+		       (1 << 8) /* osd_vsc_top_rpt_p0_num0 */ |
+		       (6 << 11) /* osd_vsc_bot_ini_rcv_num0 */ |
+		       (2 << 16) /* osd_vsc_bot_rpt_p0_num0 */ |
+		       BIT(23)	/* osd_prog_interlace */ |
+		       BIT(24), /* Enable vertical scaler */
+			priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
+}
+
+void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv)
+{
+	writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+	writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
+	writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+}
+
+static unsigned int vpp_filter_coefs_4point_bspline[] = {
+	0x15561500, 0x14561600, 0x13561700, 0x12561800,
+	0x11551a00, 0x11541b00, 0x10541c00, 0x0f541d00,
+	0x0f531e00, 0x0e531f00, 0x0d522100, 0x0c522200,
+	0x0b522300, 0x0b512400, 0x0a502600, 0x0a4f2700,
+	0x094e2900, 0x084e2a00, 0x084d2b00, 0x074c2c01,
+	0x074b2d01, 0x064a2f01, 0x06493001, 0x05483201,
+	0x05473301, 0x05463401, 0x04453601, 0x04433702,
+	0x04423802, 0x03413a02, 0x03403b02, 0x033f3c02,
+	0x033d3d03
+};
+
+static void meson_vpp_write_scaling_filter_coefs(struct meson_drm *priv,
+						 const unsigned int *coefs,
+						 bool is_horizontal)
+{
+	int i;
+
+	writel_relaxed(is_horizontal ? BIT(8) : 0,
+			priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX));
+	for (i = 0; i < 33; i++)
+		writel_relaxed(coefs[i],
+				priv->io_base + _REG(VPP_OSD_SCALE_COEF));
+}
+
+void meson_vpp_init(struct meson_drm *priv)
+{
+	/* set dummy data default YUV black */
+	if (meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
+		writel_relaxed(0x108080, priv->io_base + _REG(VPP_DUMMY_DATA1));
+	else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu")) {
+		writel_bits_relaxed(0xff << 16, 0xff << 16,
+				    priv->io_base + _REG(VIU_MISC_CTRL1));
+		writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL));
+		writel_relaxed(0x1020080,
+				priv->io_base + _REG(VPP_DUMMY_DATA1));
+	}
+
+	/* Initialize vpu fifo control registers */
+	writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) |
+			0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE));
+	writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES));
+
+	/* Turn off preblend */
+	writel_bits_relaxed(VPP_PREBLEND_ENABLE, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+	/* Turn off POSTBLEND */
+	writel_bits_relaxed(VPP_POSTBLEND_ENABLE, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+	/* Force all planes off */
+	writel_bits_relaxed(VPP_OSD1_POSTBLEND | VPP_OSD2_POSTBLEND |
+			    VPP_VD1_POSTBLEND | VPP_VD2_POSTBLEND, 0,
+			    priv->io_base + _REG(VPP_MISC));
+
+	/* Disable Scalers */
+	writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0));
+	writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0));
+	writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0));
+
+	/* Write in the proper filter coefficients. */
+	meson_vpp_write_scaling_filter_coefs(priv,
+				vpp_filter_coefs_4point_bspline, false);
+	meson_vpp_write_scaling_filter_coefs(priv,
+				vpp_filter_coefs_4point_bspline, true);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vpp.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vpp.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/meson/meson_vpp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/meson/meson_vpp.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.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/>.
+ */
+
+/* Video Post Process */
+
+#ifndef __MESON_VPP_H
+#define __MESON_VPP_H
+
+/* Mux VIU/VPP to ENCI */
+#define MESON_VIU_VPP_MUX_ENCI	0x5
+
+void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux);
+
+void meson_vpp_setup_interlace_vscaler_osd1(struct meson_drm *priv,
+					    struct drm_rect *input);
+void meson_vpp_disable_interlace_vscaler_osd1(struct meson_drm *priv);
+
+void meson_vpp_init(struct meson_drm *priv);
+
+#endif /* __MESON_VPP_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mgag200/mgag200_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -82,9 +82,7 @@ static const struct file_operations mgag
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = mgag200_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.read = drm_read,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mgag200/mgag200_mode.c	2017-02-12 16:03:20.000000000 -0500
@@ -1658,12 +1658,6 @@ static struct drm_encoder *mga_connector
 	return NULL;
 }
 
-static enum drm_connector_status mga_vga_detect(struct drm_connector
-						   *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void mga_connector_destroy(struct drm_connector *connector)
 {
 	struct mga_connector *mga_connector = to_mga_connector(connector);
@@ -1680,7 +1674,6 @@ static const struct drm_connector_helper
 
 static const struct drm_connector_funcs mga_vga_connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
-	.detect = mga_vga_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = mga_connector_destroy,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mgag200/mgag200_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -230,6 +230,7 @@ struct ttm_bo_driver mgag200_bo_driver =
 	.ttm_tt_populate = mgag200_ttm_tt_populate,
 	.ttm_tt_unpopulate = mgag200_ttm_tt_unpopulate,
 	.init_mem_type = mgag200_bo_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = mgag200_bo_evict_flags,
 	.move = NULL,
 	.verify_access = mgag200_bo_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a2xx.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,16 +8,17 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    431 bytes, from 2016-04-26 17:56:44)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1572 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml          (  90321 bytes, from 2016-11-28 16:50:05)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml         (   1773 bytes, from 2015-09-24 17:30:00)
 
-Copyright (C) 2013-2015 by the following authors:
+Copyright (C) 2013-2016 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
 - Ilia Mirkin <imirkin@alum.mit.edu> (imirkin)
 
@@ -206,12 +207,12 @@ enum a2xx_rb_copy_sample_select {
 };
 
 enum a2xx_rb_blend_opcode {
-	BLEND_DST_PLUS_SRC = 0,
-	BLEND_SRC_MINUS_DST = 1,
-	BLEND_MIN_DST_SRC = 2,
-	BLEND_MAX_DST_SRC = 3,
-	BLEND_DST_MINUS_SRC = 4,
-	BLEND_DST_PLUS_SRC_BIAS = 5,
+	BLEND2_DST_PLUS_SRC = 0,
+	BLEND2_SRC_MINUS_DST = 1,
+	BLEND2_MIN_DST_SRC = 2,
+	BLEND2_MAX_DST_SRC = 3,
+	BLEND2_DST_MINUS_SRC = 4,
+	BLEND2_DST_PLUS_SRC_BIAS = 5,
 };
 
 enum adreno_mmu_clnt_beh {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a3xx_gpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@ extern bool hang_debug;
 
 static void a3xx_dump(struct msm_gpu *gpu);
 
-static void a3xx_me_init(struct msm_gpu *gpu)
+static bool a3xx_me_init(struct msm_gpu *gpu)
 {
 	struct msm_ringbuffer *ring = gpu->rb;
 
@@ -65,7 +65,7 @@ static void a3xx_me_init(struct msm_gpu
 	OUT_RING(ring, 0x00000000);
 
 	gpu->funcs->flush(gpu);
-	gpu->funcs->idle(gpu);
+	return gpu->funcs->idle(gpu);
 }
 
 static int a3xx_hw_init(struct msm_gpu *gpu)
@@ -294,15 +294,20 @@ static int a3xx_hw_init(struct msm_gpu *
 	/* clear ME_HALT to start micro engine */
 	gpu_write(gpu, REG_AXXX_CP_ME_CNTL, 0);
 
-	a3xx_me_init(gpu);
-
-	return 0;
+	return a3xx_me_init(gpu) ? 0 : -EINVAL;
 }
 
 static void a3xx_recover(struct msm_gpu *gpu)
 {
+	int i;
+
 	adreno_dump_info(gpu);
 
+	for (i = 0; i < 8; i++) {
+		printk("CP_SCRATCH_REG%d: %u\n", i,
+			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
+	}
+
 	/* dump registers before resetting gpu, if enabled: */
 	if (hang_debug)
 		a3xx_dump(gpu);
@@ -330,17 +335,22 @@ static void a3xx_destroy(struct msm_gpu
 	kfree(a3xx_gpu);
 }
 
-static void a3xx_idle(struct msm_gpu *gpu)
+static bool a3xx_idle(struct msm_gpu *gpu)
 {
 	/* wait for ringbuffer to drain: */
-	adreno_idle(gpu);
+	if (!adreno_idle(gpu))
+		return false;
 
 	/* then wait for GPU to finish: */
 	if (spin_until(!(gpu_read(gpu, REG_A3XX_RBBM_STATUS) &
-			A3XX_RBBM_STATUS_GPU_BUSY)))
+			A3XX_RBBM_STATUS_GPU_BUSY))) {
 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
 
-	/* TODO maybe we need to reset GPU here to recover from hang? */
+		/* TODO maybe we need to reset GPU here to recover from hang? */
+		return false;
+	}
+
+	return true;
 }
 
 static irqreturn_t a3xx_irq(struct msm_gpu *gpu)
@@ -419,91 +429,13 @@ static void a3xx_dump(struct msm_gpu *gp
 }
 /* Register offset defines for A3XX */
 static const unsigned int a3xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_DEBUG, REG_AXXX_CP_DEBUG),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_WADDR, REG_AXXX_CP_ME_RAM_WADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_DATA, REG_AXXX_CP_ME_RAM_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_DATA,
-			REG_A3XX_CP_PFP_UCODE_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_ADDR,
-			REG_A3XX_CP_PFP_UCODE_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_WFI_PEND_CTR, REG_A3XX_CP_WFI_PEND_CTR),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_AXXX_CP_RB_BASE),
+	REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_AXXX_CP_RB_RPTR_ADDR),
+	REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_AXXX_CP_RB_RPTR),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_AXXX_CP_RB_WPTR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_CTRL, REG_A3XX_CP_PROTECT_CTRL),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_CNTL, REG_AXXX_CP_ME_CNTL),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_AXXX_CP_RB_CNTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BASE, REG_AXXX_CP_IB1_BASE),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BUFSZ, REG_AXXX_CP_IB1_BUFSZ),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BASE, REG_AXXX_CP_IB2_BASE),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BUFSZ, REG_AXXX_CP_IB2_BUFSZ),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_TIMESTAMP, REG_AXXX_CP_SCRATCH_REG0),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_RADDR, REG_AXXX_CP_ME_RAM_RADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_ADDR, REG_AXXX_SCRATCH_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_UMSK, REG_AXXX_SCRATCH_UMSK),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_ADDR, REG_A3XX_CP_ROQ_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_DATA, REG_A3XX_CP_ROQ_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_ADDR, REG_A3XX_CP_MERCIU_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA, REG_A3XX_CP_MERCIU_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA2, REG_A3XX_CP_MERCIU_DATA2),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_ADDR, REG_A3XX_CP_MEQ_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_DATA, REG_A3XX_CP_MEQ_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_HW_FAULT, REG_A3XX_CP_HW_FAULT),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_STATUS,
-			REG_A3XX_CP_PROTECT_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_STATUS, REG_A3XX_RBBM_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_CTL,
-			REG_A3XX_RBBM_PERFCTR_CTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0,
-			REG_A3XX_RBBM_PERFCTR_LOAD_CMD0),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1,
-			REG_A3XX_RBBM_PERFCTR_LOAD_CMD1),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_PWR_1_LO,
-			REG_A3XX_RBBM_PERFCTR_PWR_1_LO),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_MASK, REG_A3XX_RBBM_INT_0_MASK),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_STATUS,
-			REG_A3XX_RBBM_INT_0_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ERROR_STATUS,
-			REG_A3XX_RBBM_AHB_ERROR_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_CMD, REG_A3XX_RBBM_AHB_CMD),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_CLEAR_CMD,
-			REG_A3XX_RBBM_INT_CLEAR_CMD),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_CLOCK_CTL, REG_A3XX_RBBM_CLOCK_CTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_SEL,
-			REG_A3XX_VPC_VPC_DEBUG_RAM_SEL),
-	REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_READ,
-			REG_A3XX_VPC_VPC_DEBUG_RAM_READ),
-	REG_ADRENO_DEFINE(REG_ADRENO_VSC_SIZE_ADDRESS,
-			REG_A3XX_VSC_SIZE_ADDRESS),
-	REG_ADRENO_DEFINE(REG_ADRENO_VFD_CONTROL_0, REG_A3XX_VFD_CONTROL_0),
-	REG_ADRENO_DEFINE(REG_ADRENO_VFD_INDEX_MAX, REG_A3XX_VFD_INDEX_MAX),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG,
-			REG_A3XX_SP_VS_PVT_MEM_ADDR_REG),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG,
-			REG_A3XX_SP_FS_PVT_MEM_ADDR_REG),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_OBJ_START_REG,
-			REG_A3XX_SP_VS_OBJ_START_REG),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_OBJ_START_REG,
-			REG_A3XX_SP_FS_OBJ_START_REG),
-	REG_ADRENO_DEFINE(REG_ADRENO_PA_SC_AA_CONFIG, REG_A3XX_PA_SC_AA_CONFIG),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PM_OVERRIDE2,
-			REG_A3XX_RBBM_PM_OVERRIDE2),
-	REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_REG2, REG_AXXX_CP_SCRATCH_REG2),
-	REG_ADRENO_DEFINE(REG_ADRENO_SQ_GPR_MANAGEMENT,
-			REG_A3XX_SQ_GPR_MANAGEMENT),
-	REG_ADRENO_DEFINE(REG_ADRENO_SQ_INST_STORE_MANAGMENT,
-			REG_A3XX_SQ_INST_STORE_MANAGMENT),
-	REG_ADRENO_DEFINE(REG_ADRENO_TP0_CHICKEN, REG_A3XX_TP0_CHICKEN),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_RBBM_CTL, REG_A3XX_RBBM_RBBM_CTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_SW_RESET_CMD,
-			REG_A3XX_RBBM_SW_RESET_CMD),
-	REG_ADRENO_DEFINE(REG_ADRENO_UCHE_INVALIDATE0,
-			REG_A3XX_UCHE_CACHE_INVALIDATE0_REG),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO,
-			REG_A3XX_RBBM_PERFCTR_LOAD_VALUE_LO),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI,
-			REG_A3XX_RBBM_PERFCTR_LOAD_VALUE_HI),
 };
 
 static const struct adreno_gpu_funcs funcs = {
@@ -583,7 +515,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm
 #endif
 	}
 
-	if (!gpu->mmu) {
+	if (!gpu->aspace) {
 		/* TODO we think it is possible to configure the GPU to
 		 * restrict access to VRAM carveout.  But the required
 		 * registers are unknown.  For now just bail out and
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a3xx.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    431 bytes, from 2016-04-26 17:56:44)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1572 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml          (  90321 bytes, from 2016-11-28 16:50:05)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml         (   1773 bytes, from 2015-09-24 17:30:00)
 
 Copyright (C) 2013-2016 by the following authors:
@@ -129,10 +130,14 @@ enum a3xx_tex_fmt {
 	TFMT_Z16_UNORM = 9,
 	TFMT_X8Z24_UNORM = 10,
 	TFMT_Z32_FLOAT = 11,
-	TFMT_NV12_UV_TILED = 17,
-	TFMT_NV12_Y_TILED = 19,
-	TFMT_NV12_UV = 21,
-	TFMT_NV12_Y = 23,
+	TFMT_UV_64X32 = 16,
+	TFMT_VU_64X32 = 17,
+	TFMT_Y_64X32 = 18,
+	TFMT_NV12_64X32 = 19,
+	TFMT_UV_LINEAR = 20,
+	TFMT_VU_LINEAR = 21,
+	TFMT_Y_LINEAR = 22,
+	TFMT_NV12_LINEAR = 23,
 	TFMT_I420_Y = 24,
 	TFMT_I420_U = 26,
 	TFMT_I420_V = 27,
@@ -525,14 +530,6 @@ enum a3xx_uche_perfcounter_select {
 	UCHE_UCHEPERF_ACTIVE_CYCLES = 20,
 };
 
-enum a3xx_rb_blend_opcode {
-	BLEND_DST_PLUS_SRC = 0,
-	BLEND_SRC_MINUS_DST = 1,
-	BLEND_DST_MINUS_SRC = 2,
-	BLEND_MIN_DST_SRC = 3,
-	BLEND_MAX_DST_SRC = 4,
-};
-
 enum a3xx_intp_mode {
 	SMOOTH = 0,
 	FLAT = 1,
@@ -1393,13 +1390,14 @@ static inline uint32_t A3XX_RB_COPY_CONT
 {
 	return ((val) << A3XX_RB_COPY_CONTROL_MODE__SHIFT) & A3XX_RB_COPY_CONTROL_MODE__MASK;
 }
+#define A3XX_RB_COPY_CONTROL_MSAA_SRGB_DOWNSAMPLE		0x00000080
 #define A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK			0x00000f00
 #define A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT			8
 static inline uint32_t A3XX_RB_COPY_CONTROL_FASTCLEAR(uint32_t val)
 {
 	return ((val) << A3XX_RB_COPY_CONTROL_FASTCLEAR__SHIFT) & A3XX_RB_COPY_CONTROL_FASTCLEAR__MASK;
 }
-#define A3XX_RB_COPY_CONTROL_UNK12				0x00001000
+#define A3XX_RB_COPY_CONTROL_DEPTH32_RESOLVE			0x00001000
 #define A3XX_RB_COPY_CONTROL_GMEM_BASE__MASK			0xffffc000
 #define A3XX_RB_COPY_CONTROL_GMEM_BASE__SHIFT			14
 static inline uint32_t A3XX_RB_COPY_CONTROL_GMEM_BASE(uint32_t val)
@@ -1472,7 +1470,7 @@ static inline uint32_t A3XX_RB_DEPTH_CON
 {
 	return ((val) << A3XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT) & A3XX_RB_DEPTH_CONTROL_ZFUNC__MASK;
 }
-#define A3XX_RB_DEPTH_CONTROL_BF_ENABLE				0x00000080
+#define A3XX_RB_DEPTH_CONTROL_Z_CLAMP_ENABLE			0x00000080
 #define A3XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE			0x80000000
 
 #define REG_A3XX_RB_DEPTH_CLEAR					0x00002101
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a4xx_gpu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a4xx_gpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a4xx_gpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,7 +113,7 @@ static void a4xx_enable_hwcg(struct msm_
 }
 
 
-static void a4xx_me_init(struct msm_gpu *gpu)
+static bool a4xx_me_init(struct msm_gpu *gpu)
 {
 	struct msm_ringbuffer *ring = gpu->rb;
 
@@ -137,7 +137,7 @@ static void a4xx_me_init(struct msm_gpu
 	OUT_RING(ring, 0x00000000);
 
 	gpu->funcs->flush(gpu);
-	gpu->funcs->idle(gpu);
+	return gpu->funcs->idle(gpu);
 }
 
 static int a4xx_hw_init(struct msm_gpu *gpu)
@@ -292,15 +292,20 @@ static int a4xx_hw_init(struct msm_gpu *
 	/* clear ME_HALT to start micro engine */
 	gpu_write(gpu, REG_A4XX_CP_ME_CNTL, 0);
 
-	a4xx_me_init(gpu);
-
-	return 0;
+	return a4xx_me_init(gpu) ? 0 : -EINVAL;
 }
 
 static void a4xx_recover(struct msm_gpu *gpu)
 {
+	int i;
+
 	adreno_dump_info(gpu);
 
+	for (i = 0; i < 8; i++) {
+		printk("CP_SCRATCH_REG%d: %u\n", i,
+			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
+	}
+
 	/* dump registers before resetting gpu, if enabled: */
 	if (hang_debug)
 		a4xx_dump(gpu);
@@ -328,17 +333,21 @@ static void a4xx_destroy(struct msm_gpu
 	kfree(a4xx_gpu);
 }
 
-static void a4xx_idle(struct msm_gpu *gpu)
+static bool a4xx_idle(struct msm_gpu *gpu)
 {
 	/* wait for ringbuffer to drain: */
-	adreno_idle(gpu);
+	if (!adreno_idle(gpu))
+		return false;
 
 	/* then wait for GPU to finish: */
 	if (spin_until(!(gpu_read(gpu, REG_A4XX_RBBM_STATUS) &
-					A4XX_RBBM_STATUS_GPU_BUSY)))
+					A4XX_RBBM_STATUS_GPU_BUSY))) {
 		DRM_ERROR("%s: timeout waiting for GPU to idle!\n", gpu->name);
+		/* TODO maybe we need to reset GPU here to recover from hang? */
+		return false;
+	}
 
-	/* TODO maybe we need to reset GPU here to recover from hang? */
+	return true;
 }
 
 static irqreturn_t a4xx_irq(struct msm_gpu *gpu)
@@ -460,87 +469,13 @@ static void a4xx_show(struct msm_gpu *gp
 
 /* Register offset defines for A4XX, in order of enum adreno_regs */
 static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_DEBUG, REG_A4XX_CP_DEBUG),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_WADDR, REG_A4XX_CP_ME_RAM_WADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_DATA, REG_A4XX_CP_ME_RAM_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_DATA,
-			REG_A4XX_CP_PFP_UCODE_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PFP_UCODE_ADDR,
-			REG_A4XX_CP_PFP_UCODE_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_WFI_PEND_CTR, REG_A4XX_CP_WFI_PEND_CTR),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A4XX_CP_RB_BASE),
+	REG_ADRENO_SKIP(REG_ADRENO_CP_RB_BASE_HI),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A4XX_CP_RB_RPTR_ADDR),
+	REG_ADRENO_SKIP(REG_ADRENO_CP_RB_RPTR_ADDR_HI),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A4XX_CP_RB_RPTR),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A4XX_CP_RB_WPTR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_CTRL, REG_A4XX_CP_PROTECT_CTRL),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_CNTL, REG_A4XX_CP_ME_CNTL),
 	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A4XX_CP_RB_CNTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BASE, REG_A4XX_CP_IB1_BASE),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB1_BUFSZ, REG_A4XX_CP_IB1_BUFSZ),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BASE, REG_A4XX_CP_IB2_BASE),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_IB2_BUFSZ, REG_A4XX_CP_IB2_BUFSZ),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_TIMESTAMP, REG_AXXX_CP_SCRATCH_REG0),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ME_RAM_RADDR, REG_A4XX_CP_ME_RAM_RADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_ADDR, REG_A4XX_CP_ROQ_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_ROQ_DATA, REG_A4XX_CP_ROQ_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_ADDR, REG_A4XX_CP_MERCIU_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA, REG_A4XX_CP_MERCIU_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MERCIU_DATA2, REG_A4XX_CP_MERCIU_DATA2),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_ADDR, REG_A4XX_CP_MEQ_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_MEQ_DATA, REG_A4XX_CP_MEQ_DATA),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_HW_FAULT, REG_A4XX_CP_HW_FAULT),
-	REG_ADRENO_DEFINE(REG_ADRENO_CP_PROTECT_STATUS,
-			REG_A4XX_CP_PROTECT_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_ADDR, REG_A4XX_CP_SCRATCH_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_SCRATCH_UMSK, REG_A4XX_CP_SCRATCH_UMASK),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_STATUS, REG_A4XX_RBBM_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_CTL,
-			REG_A4XX_RBBM_PERFCTR_CTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0,
-			REG_A4XX_RBBM_PERFCTR_LOAD_CMD0),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1,
-			REG_A4XX_RBBM_PERFCTR_LOAD_CMD1),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_CMD2,
-			REG_A4XX_RBBM_PERFCTR_LOAD_CMD2),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_PWR_1_LO,
-			REG_A4XX_RBBM_PERFCTR_PWR_1_LO),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_MASK, REG_A4XX_RBBM_INT_0_MASK),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_0_STATUS,
-			REG_A4XX_RBBM_INT_0_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ERROR_STATUS,
-			REG_A4XX_RBBM_AHB_ERROR_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_CMD, REG_A4XX_RBBM_AHB_CMD),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_CLOCK_CTL, REG_A4XX_RBBM_CLOCK_CTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_ME_SPLIT_STATUS,
-			REG_A4XX_RBBM_AHB_ME_SPLIT_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_AHB_PFP_SPLIT_STATUS,
-			REG_A4XX_RBBM_AHB_PFP_SPLIT_STATUS),
-	REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_SEL,
-			REG_A4XX_VPC_DEBUG_RAM_SEL),
-	REG_ADRENO_DEFINE(REG_ADRENO_VPC_DEBUG_RAM_READ,
-			REG_A4XX_VPC_DEBUG_RAM_READ),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_INT_CLEAR_CMD,
-			REG_A4XX_RBBM_INT_CLEAR_CMD),
-	REG_ADRENO_DEFINE(REG_ADRENO_VSC_SIZE_ADDRESS,
-			REG_A4XX_VSC_SIZE_ADDRESS),
-	REG_ADRENO_DEFINE(REG_ADRENO_VFD_CONTROL_0, REG_A4XX_VFD_CONTROL_0),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG,
-			REG_A4XX_SP_VS_PVT_MEM_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG,
-			REG_A4XX_SP_FS_PVT_MEM_ADDR),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_VS_OBJ_START_REG,
-			REG_A4XX_SP_VS_OBJ_START),
-	REG_ADRENO_DEFINE(REG_ADRENO_SP_FS_OBJ_START_REG,
-			REG_A4XX_SP_FS_OBJ_START),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_RBBM_CTL, REG_A4XX_RBBM_RBBM_CTL),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_SW_RESET_CMD,
-			REG_A4XX_RBBM_SW_RESET_CMD),
-	REG_ADRENO_DEFINE(REG_ADRENO_UCHE_INVALIDATE0,
-			REG_A4XX_UCHE_INVALIDATE0),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO,
-			REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_LO),
-	REG_ADRENO_DEFINE(REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI,
-			REG_A4XX_RBBM_PERFCTR_LOAD_VALUE_HI),
 };
 
 static void a4xx_dump(struct msm_gpu *gpu)
@@ -587,16 +522,8 @@ static int a4xx_pm_suspend(struct msm_gp
 
 static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
 {
-	uint32_t hi, lo, tmp;
-
-	tmp = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_HI);
-	do {
-		hi = tmp;
-		lo = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO);
-		tmp = gpu_read(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_HI);
-	} while (tmp != hi);
-
-	*value = (((uint64_t)hi) << 32) | lo;
+	*value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO,
+		REG_A4XX_RBBM_PERFCTR_CP_0_HI);
 
 	return 0;
 }
@@ -672,7 +599,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm
 #endif
 	}
 
-	if (!gpu->mmu) {
+	if (!gpu->aspace) {
 		/* TODO we think it is possible to configure the GPU to
 		 * restrict access to VRAM carveout.  But the required
 		 * registers are unknown.  For now just bail out and
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a4xx.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a4xx.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a4xx.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a4xx.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    431 bytes, from 2016-04-26 17:56:44)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1572 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml          (  90321 bytes, from 2016-11-28 16:50:05)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml         (   1773 bytes, from 2015-09-24 17:30:00)
 
 Copyright (C) 2013-2016 by the following authors:
@@ -46,6 +47,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DE
 enum a4xx_color_fmt {
 	RB4_A8_UNORM = 1,
 	RB4_R8_UNORM = 2,
+	RB4_R8_SNORM = 3,
+	RB4_R8_UINT = 4,
+	RB4_R8_SINT = 5,
 	RB4_R4G4B4A4_UNORM = 8,
 	RB4_R5G5B5A1_UNORM = 10,
 	RB4_R5G6B5_UNORM = 14,
@@ -89,17 +93,10 @@ enum a4xx_color_fmt {
 
 enum a4xx_tile_mode {
 	TILE4_LINEAR = 0,
+	TILE4_2 = 2,
 	TILE4_3 = 3,
 };
 
-enum a4xx_rb_blend_opcode {
-	BLEND_DST_PLUS_SRC = 0,
-	BLEND_SRC_MINUS_DST = 1,
-	BLEND_DST_MINUS_SRC = 2,
-	BLEND_MIN_DST_SRC = 3,
-	BLEND_MAX_DST_SRC = 4,
-};
-
 enum a4xx_vtx_fmt {
 	VFMT4_32_FLOAT = 1,
 	VFMT4_32_32_FLOAT = 2,
@@ -940,6 +937,7 @@ static inline uint32_t A4XX_RB_MODE_CONT
 {
 	return ((val >> 5) << A4XX_RB_MODE_CONTROL_HEIGHT__SHIFT) & A4XX_RB_MODE_CONTROL_HEIGHT__MASK;
 }
+#define A4XX_RB_MODE_CONTROL_ENABLE_GMEM			0x00010000
 
 #define REG_A4XX_RB_RENDER_CONTROL				0x000020a1
 #define A4XX_RB_RENDER_CONTROL_BINNING_PASS			0x00000001
@@ -1043,7 +1041,7 @@ static inline uint32_t A4XX_RB_MRT_BLEND
 }
 #define A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK	0x000000e0
 #define A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT	5
-static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a4xx_rb_blend_opcode val)
+static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
 {
 	return ((val) << A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
 }
@@ -1061,7 +1059,7 @@ static inline uint32_t A4XX_RB_MRT_BLEND
 }
 #define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK	0x00e00000
 #define A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT	21
-static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a4xx_rb_blend_opcode val)
+static inline uint32_t A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
 {
 	return ((val) << A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A4XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
 }
@@ -1073,12 +1071,18 @@ static inline uint32_t A4XX_RB_MRT_BLEND
 }
 
 #define REG_A4XX_RB_BLEND_RED					0x000020f0
-#define A4XX_RB_BLEND_RED_UINT__MASK				0x0000ffff
+#define A4XX_RB_BLEND_RED_UINT__MASK				0x000000ff
 #define A4XX_RB_BLEND_RED_UINT__SHIFT				0
 static inline uint32_t A4XX_RB_BLEND_RED_UINT(uint32_t val)
 {
 	return ((val) << A4XX_RB_BLEND_RED_UINT__SHIFT) & A4XX_RB_BLEND_RED_UINT__MASK;
 }
+#define A4XX_RB_BLEND_RED_SINT__MASK				0x0000ff00
+#define A4XX_RB_BLEND_RED_SINT__SHIFT				8
+static inline uint32_t A4XX_RB_BLEND_RED_SINT(uint32_t val)
+{
+	return ((val) << A4XX_RB_BLEND_RED_SINT__SHIFT) & A4XX_RB_BLEND_RED_SINT__MASK;
+}
 #define A4XX_RB_BLEND_RED_FLOAT__MASK				0xffff0000
 #define A4XX_RB_BLEND_RED_FLOAT__SHIFT				16
 static inline uint32_t A4XX_RB_BLEND_RED_FLOAT(float val)
@@ -1095,12 +1099,18 @@ static inline uint32_t A4XX_RB_BLEND_RED
 }
 
 #define REG_A4XX_RB_BLEND_GREEN					0x000020f2
-#define A4XX_RB_BLEND_GREEN_UINT__MASK				0x0000ffff
+#define A4XX_RB_BLEND_GREEN_UINT__MASK				0x000000ff
 #define A4XX_RB_BLEND_GREEN_UINT__SHIFT				0
 static inline uint32_t A4XX_RB_BLEND_GREEN_UINT(uint32_t val)
 {
 	return ((val) << A4XX_RB_BLEND_GREEN_UINT__SHIFT) & A4XX_RB_BLEND_GREEN_UINT__MASK;
 }
+#define A4XX_RB_BLEND_GREEN_SINT__MASK				0x0000ff00
+#define A4XX_RB_BLEND_GREEN_SINT__SHIFT				8
+static inline uint32_t A4XX_RB_BLEND_GREEN_SINT(uint32_t val)
+{
+	return ((val) << A4XX_RB_BLEND_GREEN_SINT__SHIFT) & A4XX_RB_BLEND_GREEN_SINT__MASK;
+}
 #define A4XX_RB_BLEND_GREEN_FLOAT__MASK				0xffff0000
 #define A4XX_RB_BLEND_GREEN_FLOAT__SHIFT			16
 static inline uint32_t A4XX_RB_BLEND_GREEN_FLOAT(float val)
@@ -1117,12 +1127,18 @@ static inline uint32_t A4XX_RB_BLEND_GRE
 }
 
 #define REG_A4XX_RB_BLEND_BLUE					0x000020f4
-#define A4XX_RB_BLEND_BLUE_UINT__MASK				0x0000ffff
+#define A4XX_RB_BLEND_BLUE_UINT__MASK				0x000000ff
 #define A4XX_RB_BLEND_BLUE_UINT__SHIFT				0
 static inline uint32_t A4XX_RB_BLEND_BLUE_UINT(uint32_t val)
 {
 	return ((val) << A4XX_RB_BLEND_BLUE_UINT__SHIFT) & A4XX_RB_BLEND_BLUE_UINT__MASK;
 }
+#define A4XX_RB_BLEND_BLUE_SINT__MASK				0x0000ff00
+#define A4XX_RB_BLEND_BLUE_SINT__SHIFT				8
+static inline uint32_t A4XX_RB_BLEND_BLUE_SINT(uint32_t val)
+{
+	return ((val) << A4XX_RB_BLEND_BLUE_SINT__SHIFT) & A4XX_RB_BLEND_BLUE_SINT__MASK;
+}
 #define A4XX_RB_BLEND_BLUE_FLOAT__MASK				0xffff0000
 #define A4XX_RB_BLEND_BLUE_FLOAT__SHIFT				16
 static inline uint32_t A4XX_RB_BLEND_BLUE_FLOAT(float val)
@@ -1139,12 +1155,18 @@ static inline uint32_t A4XX_RB_BLEND_BLU
 }
 
 #define REG_A4XX_RB_BLEND_ALPHA					0x000020f6
-#define A4XX_RB_BLEND_ALPHA_UINT__MASK				0x0000ffff
+#define A4XX_RB_BLEND_ALPHA_UINT__MASK				0x000000ff
 #define A4XX_RB_BLEND_ALPHA_UINT__SHIFT				0
 static inline uint32_t A4XX_RB_BLEND_ALPHA_UINT(uint32_t val)
 {
 	return ((val) << A4XX_RB_BLEND_ALPHA_UINT__SHIFT) & A4XX_RB_BLEND_ALPHA_UINT__MASK;
 }
+#define A4XX_RB_BLEND_ALPHA_SINT__MASK				0x0000ff00
+#define A4XX_RB_BLEND_ALPHA_SINT__SHIFT				8
+static inline uint32_t A4XX_RB_BLEND_ALPHA_SINT(uint32_t val)
+{
+	return ((val) << A4XX_RB_BLEND_ALPHA_SINT__SHIFT) & A4XX_RB_BLEND_ALPHA_SINT__MASK;
+}
 #define A4XX_RB_BLEND_ALPHA_FLOAT__MASK				0xffff0000
 #define A4XX_RB_BLEND_ALPHA_FLOAT__SHIFT			16
 static inline uint32_t A4XX_RB_BLEND_ALPHA_FLOAT(float val)
@@ -1348,7 +1370,7 @@ static inline uint32_t A4XX_RB_DEPTH_CON
 {
 	return ((val) << A4XX_RB_DEPTH_CONTROL_ZFUNC__SHIFT) & A4XX_RB_DEPTH_CONTROL_ZFUNC__MASK;
 }
-#define A4XX_RB_DEPTH_CONTROL_BF_ENABLE				0x00000080
+#define A4XX_RB_DEPTH_CONTROL_Z_CLAMP_ENABLE			0x00000080
 #define A4XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE			0x00010000
 #define A4XX_RB_DEPTH_CONTROL_FORCE_FRAGZ_TO_FS			0x00020000
 #define A4XX_RB_DEPTH_CONTROL_Z_TEST_ENABLE			0x80000000
@@ -2177,11 +2199,23 @@ static inline uint32_t REG_A4XX_RBBM_CLO
 
 #define REG_A4XX_CP_DRAW_STATE_ADDR				0x00000232
 
-#define REG_A4XX_CP_PROTECT_REG_0				0x00000240
-
 static inline uint32_t REG_A4XX_CP_PROTECT(uint32_t i0) { return 0x00000240 + 0x1*i0; }
 
 static inline uint32_t REG_A4XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000240 + 0x1*i0; }
+#define A4XX_CP_PROTECT_REG_BASE_ADDR__MASK			0x0001ffff
+#define A4XX_CP_PROTECT_REG_BASE_ADDR__SHIFT			0
+static inline uint32_t A4XX_CP_PROTECT_REG_BASE_ADDR(uint32_t val)
+{
+	return ((val) << A4XX_CP_PROTECT_REG_BASE_ADDR__SHIFT) & A4XX_CP_PROTECT_REG_BASE_ADDR__MASK;
+}
+#define A4XX_CP_PROTECT_REG_MASK_LEN__MASK			0x1f000000
+#define A4XX_CP_PROTECT_REG_MASK_LEN__SHIFT			24
+static inline uint32_t A4XX_CP_PROTECT_REG_MASK_LEN(uint32_t val)
+{
+	return ((val) << A4XX_CP_PROTECT_REG_MASK_LEN__SHIFT) & A4XX_CP_PROTECT_REG_MASK_LEN__MASK;
+}
+#define A4XX_CP_PROTECT_REG_TRAP_WRITE				0x20000000
+#define A4XX_CP_PROTECT_REG_TRAP_READ				0x40000000
 
 #define REG_A4XX_CP_PROTECT_CTRL				0x00000250
 
@@ -2272,7 +2306,7 @@ static inline uint32_t A4XX_SP_VS_CTRL_R
 {
 	return ((val) << A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A4XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
 }
-#define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK		0x0003fc00
+#define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK		0x0000fc00
 #define A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT		10
 static inline uint32_t A4XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
 {
@@ -2420,7 +2454,7 @@ static inline uint32_t A4XX_SP_FS_CTRL_R
 {
 	return ((val) << A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A4XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
 }
-#define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK		0x0003fc00
+#define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK		0x0000fc00
 #define A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT		10
 static inline uint32_t A4XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
 {
@@ -3117,6 +3151,8 @@ static inline uint32_t A4XX_TPL1_TP_TEX_
 
 #define REG_A4XX_GRAS_CL_CLIP_CNTL				0x00002000
 #define A4XX_GRAS_CL_CLIP_CNTL_CLIP_DISABLE			0x00008000
+#define A4XX_GRAS_CL_CLIP_CNTL_ZNEAR_CLIP_DISABLE		0x00010000
+#define A4XX_GRAS_CL_CLIP_CNTL_ZFAR_CLIP_DISABLE		0x00020000
 #define A4XX_GRAS_CL_CLIP_CNTL_ZERO_GB_SCALE_Z			0x00400000
 
 #define REG_A4XX_GRAS_CLEAR_CNTL				0x00002003
@@ -3253,6 +3289,7 @@ static inline uint32_t A4XX_GRAS_SU_MODE
 	return ((((int32_t)(val * 4.0))) << A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__SHIFT) & A4XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH__MASK;
 }
 #define A4XX_GRAS_SU_MODE_CONTROL_POLY_OFFSET			0x00000800
+#define A4XX_GRAS_SU_MODE_CONTROL_MSAA_ENABLE			0x00002000
 #define A4XX_GRAS_SU_MODE_CONTROL_RENDERING_PASS		0x00100000
 
 #define REG_A4XX_GRAS_SC_CONTROL				0x0000207b
@@ -3670,6 +3707,8 @@ static inline uint32_t A4XX_HLSQ_GS_CONT
 #define REG_A4XX_PC_BINNING_COMMAND				0x00000d00
 #define A4XX_PC_BINNING_COMMAND_BINNING_ENABLE			0x00000001
 
+#define REG_A4XX_PC_TESSFACTOR_ADDR				0x00000d08
+
 #define REG_A4XX_PC_DRAWCALL_SETUP_OVERRIDE			0x00000d0c
 
 #define REG_A4XX_PC_PERFCTR_PC_SEL_0				0x00000d10
@@ -3690,6 +3729,20 @@ static inline uint32_t A4XX_HLSQ_GS_CONT
 
 #define REG_A4XX_PC_BIN_BASE					0x000021c0
 
+#define REG_A4XX_PC_VSTREAM_CONTROL				0x000021c2
+#define A4XX_PC_VSTREAM_CONTROL_SIZE__MASK			0x003f0000
+#define A4XX_PC_VSTREAM_CONTROL_SIZE__SHIFT			16
+static inline uint32_t A4XX_PC_VSTREAM_CONTROL_SIZE(uint32_t val)
+{
+	return ((val) << A4XX_PC_VSTREAM_CONTROL_SIZE__SHIFT) & A4XX_PC_VSTREAM_CONTROL_SIZE__MASK;
+}
+#define A4XX_PC_VSTREAM_CONTROL_N__MASK				0x07c00000
+#define A4XX_PC_VSTREAM_CONTROL_N__SHIFT			22
+static inline uint32_t A4XX_PC_VSTREAM_CONTROL_N(uint32_t val)
+{
+	return ((val) << A4XX_PC_VSTREAM_CONTROL_N__SHIFT) & A4XX_PC_VSTREAM_CONTROL_N__MASK;
+}
+
 #define REG_A4XX_PC_PRIM_VTX_CNTL				0x000021c4
 #define A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK			0x0000000f
 #define A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT			0
@@ -3752,12 +3805,8 @@ static inline uint32_t A4XX_PC_HS_PARAM_
 {
 	return ((val) << A4XX_PC_HS_PARAM_SPACING__SHIFT) & A4XX_PC_HS_PARAM_SPACING__MASK;
 }
-#define A4XX_PC_HS_PARAM_PRIMTYPE__MASK				0x01800000
-#define A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT			23
-static inline uint32_t A4XX_PC_HS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
-{
-	return ((val) << A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_HS_PARAM_PRIMTYPE__MASK;
-}
+#define A4XX_PC_HS_PARAM_CW					0x00800000
+#define A4XX_PC_HS_PARAM_CONNECTED				0x01000000
 
 #define REG_A4XX_VBIF_VERSION					0x00003000
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,888 @@
+/* Copyright (c) 2016 The Linux Foundation. All 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 "msm_gem.h"
+#include "a5xx_gpu.h"
+
+extern bool hang_debug;
+static void a5xx_dump(struct msm_gpu *gpu);
+
+static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
+	struct msm_file_private *ctx)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct msm_drm_private *priv = gpu->dev->dev_private;
+	struct msm_ringbuffer *ring = gpu->rb;
+	unsigned int i, ibs = 0;
+
+	for (i = 0; i < submit->nr_cmds; i++) {
+		switch (submit->cmd[i].type) {
+		case MSM_SUBMIT_CMD_IB_TARGET_BUF:
+			break;
+		case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
+			if (priv->lastctx == ctx)
+				break;
+		case MSM_SUBMIT_CMD_BUF:
+			OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
+			OUT_RING(ring, lower_32_bits(submit->cmd[i].iova));
+			OUT_RING(ring, upper_32_bits(submit->cmd[i].iova));
+			OUT_RING(ring, submit->cmd[i].size);
+			ibs++;
+			break;
+		}
+	}
+
+	OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1);
+	OUT_RING(ring, submit->fence->seqno);
+
+	OUT_PKT7(ring, CP_EVENT_WRITE, 4);
+	OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31));
+	OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, fence)));
+	OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, fence)));
+	OUT_RING(ring, submit->fence->seqno);
+
+	gpu->funcs->flush(gpu);
+}
+
+struct a5xx_hwcg {
+	u32 offset;
+	u32 value;
+};
+
+static const struct a5xx_hwcg a530_hwcg[] = {
+	{REG_A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220},
+	{REG_A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF},
+	{REG_A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF},
+	{REG_A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF},
+	{REG_A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF},
+	{REG_A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080},
+	{REG_A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080},
+	{REG_A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080},
+	{REG_A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080},
+	{REG_A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222},
+	{REG_A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222},
+	{REG_A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222},
+	{REG_A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222},
+	{REG_A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777},
+	{REG_A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777},
+	{REG_A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777},
+	{REG_A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777},
+	{REG_A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777},
+	{REG_A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111},
+	{REG_A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111},
+	{REG_A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111},
+	{REG_A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111},
+	{REG_A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111},
+	{REG_A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222},
+	{REG_A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444},
+	{REG_A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002},
+	{REG_A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222},
+	{REG_A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220},
+	{REG_A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220},
+	{REG_A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220},
+	{REG_A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220},
+	{REG_A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222},
+	{REG_A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555},
+	{REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404},
+	{REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404},
+	{REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404},
+	{REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404},
+	{REG_A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044},
+	{REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002},
+	{REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002},
+	{REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002},
+	{REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002},
+	{REG_A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011},
+	{REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222},
+	{REG_A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222},
+	{REG_A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222},
+	{REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000},
+	{REG_A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004},
+	{REG_A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000},
+	{REG_A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000},
+	{REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000},
+	{REG_A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200},
+	{REG_A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}
+};
+
+static const struct {
+	int (*test)(struct adreno_gpu *gpu);
+	const struct a5xx_hwcg *regs;
+	unsigned int count;
+} a5xx_hwcg_regs[] = {
+	{ adreno_is_a530, a530_hwcg, ARRAY_SIZE(a530_hwcg), },
+};
+
+static void _a5xx_enable_hwcg(struct msm_gpu *gpu,
+		const struct a5xx_hwcg *regs, unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++)
+		gpu_write(gpu, regs[i].offset, regs[i].value);
+
+	gpu_write(gpu, REG_A5XX_RBBM_CLOCK_CNTL, 0xAAA8AA00);
+	gpu_write(gpu, REG_A5XX_RBBM_ISDB_CNT, 0x182);
+}
+
+static void a5xx_enable_hwcg(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(a5xx_hwcg_regs); i++) {
+		if (a5xx_hwcg_regs[i].test(adreno_gpu)) {
+			_a5xx_enable_hwcg(gpu, a5xx_hwcg_regs[i].regs,
+				a5xx_hwcg_regs[i].count);
+			return;
+		}
+	}
+}
+
+static int a5xx_me_init(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct msm_ringbuffer *ring = gpu->rb;
+
+	OUT_PKT7(ring, CP_ME_INIT, 8);
+
+	OUT_RING(ring, 0x0000002F);
+
+	/* Enable multiple hardware contexts */
+	OUT_RING(ring, 0x00000003);
+
+	/* Enable error detection */
+	OUT_RING(ring, 0x20000000);
+
+	/* Don't enable header dump */
+	OUT_RING(ring, 0x00000000);
+	OUT_RING(ring, 0x00000000);
+
+	/* Specify workarounds for various microcode issues */
+	if (adreno_is_a530(adreno_gpu)) {
+		/* Workaround for token end syncs
+		 * Force a WFI after every direct-render 3D mode draw and every
+		 * 2D mode 3 draw
+		 */
+		OUT_RING(ring, 0x0000000B);
+	} else {
+		/* No workarounds enabled */
+		OUT_RING(ring, 0x00000000);
+	}
+
+	OUT_RING(ring, 0x00000000);
+	OUT_RING(ring, 0x00000000);
+
+	gpu->funcs->flush(gpu);
+
+	return gpu->funcs->idle(gpu) ? 0 : -EINVAL;
+}
+
+static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu,
+		const struct firmware *fw, u64 *iova)
+{
+	struct drm_device *drm = gpu->dev;
+	struct drm_gem_object *bo;
+	void *ptr;
+
+	mutex_lock(&drm->struct_mutex);
+	bo = msm_gem_new(drm, fw->size - 4, MSM_BO_UNCACHED);
+	mutex_unlock(&drm->struct_mutex);
+
+	if (IS_ERR(bo))
+		return bo;
+
+	ptr = msm_gem_get_vaddr(bo);
+	if (!ptr) {
+		drm_gem_object_unreference_unlocked(bo);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	if (iova) {
+		int ret = msm_gem_get_iova(bo, gpu->id, iova);
+
+		if (ret) {
+			drm_gem_object_unreference_unlocked(bo);
+			return ERR_PTR(ret);
+		}
+	}
+
+	memcpy(ptr, &fw->data[4], fw->size - 4);
+
+	msm_gem_put_vaddr(bo);
+	return bo;
+}
+
+static int a5xx_ucode_init(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+	int ret;
+
+	if (!a5xx_gpu->pm4_bo) {
+		a5xx_gpu->pm4_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pm4,
+			&a5xx_gpu->pm4_iova);
+
+		if (IS_ERR(a5xx_gpu->pm4_bo)) {
+			ret = PTR_ERR(a5xx_gpu->pm4_bo);
+			a5xx_gpu->pm4_bo = NULL;
+			dev_err(gpu->dev->dev, "could not allocate PM4: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	if (!a5xx_gpu->pfp_bo) {
+		a5xx_gpu->pfp_bo = a5xx_ucode_load_bo(gpu, adreno_gpu->pfp,
+			&a5xx_gpu->pfp_iova);
+
+		if (IS_ERR(a5xx_gpu->pfp_bo)) {
+			ret = PTR_ERR(a5xx_gpu->pfp_bo);
+			a5xx_gpu->pfp_bo = NULL;
+			dev_err(gpu->dev->dev, "could not allocate PFP: %d\n",
+				ret);
+			return ret;
+		}
+	}
+
+	gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
+		REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
+
+	gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
+		REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
+
+	return 0;
+}
+
+#define A5XX_INT_MASK (A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
+	  A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
+	  A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
+	  A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
+	  A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
+	  A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \
+	  A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
+	  A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \
+	  A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \
+	  A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
+
+static int a5xx_hw_init(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	int ret;
+
+	gpu_write(gpu, REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003);
+
+	/* Make all blocks contribute to the GPU BUSY perf counter */
+	gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
+	/* Enable RBBM error reporting bits */
+	gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL0, 0x00000001);
+
+	if (adreno_gpu->quirks & ADRENO_QUIRK_FAULT_DETECT_MASK) {
+		/*
+		 * Mask out the activity signals from RB1-3 to avoid false
+		 * positives
+		 */
+
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11,
+			0xF0000000);
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12,
+			0xFFFFFFFF);
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13,
+			0xFFFFFFFF);
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14,
+			0xFFFFFFFF);
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15,
+			0xFFFFFFFF);
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16,
+			0xFFFFFFFF);
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17,
+			0xFFFFFFFF);
+		gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18,
+			0xFFFFFFFF);
+	}
+
+	/* Enable fault detection */
+	gpu_write(gpu, REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
+		(1 << 30) | 0xFFFF);
+
+	/* Turn on performance counters */
+	gpu_write(gpu, REG_A5XX_RBBM_PERFCTR_CNTL, 0x01);
+
+	/* Increase VFD cache access so LRZ and other data gets evicted less */
+	gpu_write(gpu, REG_A5XX_UCHE_CACHE_WAYS, 0x02);
+
+	/* Disable L2 bypass in the UCHE */
+	gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_LO, 0xFFFF0000);
+	gpu_write(gpu, REG_A5XX_UCHE_TRAP_BASE_HI, 0x0001FFFF);
+	gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_LO, 0xFFFF0000);
+	gpu_write(gpu, REG_A5XX_UCHE_WRITE_THRU_BASE_HI, 0x0001FFFF);
+
+	/* Set the GMEM VA range (0 to gpu->gmem) */
+	gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
+	gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MIN_HI, 0x00000000);
+	gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_LO,
+		0x00100000 + adreno_gpu->gmem - 1);
+	gpu_write(gpu, REG_A5XX_UCHE_GMEM_RANGE_MAX_HI, 0x00000000);
+
+	gpu_write(gpu, REG_A5XX_CP_MEQ_THRESHOLDS, 0x40);
+	gpu_write(gpu, REG_A5XX_CP_MERCIU_SIZE, 0x40);
+	gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_2, 0x80000060);
+	gpu_write(gpu, REG_A5XX_CP_ROQ_THRESHOLDS_1, 0x40201B16);
+
+	gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, (0x400 << 11 | 0x300 << 22));
+
+	if (adreno_gpu->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
+		gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
+
+	gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
+
+	/* Enable USE_RETENTION_FLOPS */
+	gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
+
+	/* Enable ME/PFP split notification */
+	gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL1, 0xA6FFFFFF);
+
+	/* Enable HWCG */
+	a5xx_enable_hwcg(gpu);
+
+	gpu_write(gpu, REG_A5XX_RBBM_AHB_CNTL2, 0x0000003F);
+
+	/* Set the highest bank bit */
+	gpu_write(gpu, REG_A5XX_TPL1_MODE_CNTL, 2 << 7);
+	gpu_write(gpu, REG_A5XX_RB_MODE_CNTL, 2 << 1);
+
+	/* Protect registers from the CP */
+	gpu_write(gpu, REG_A5XX_CP_PROTECT_CNTL, 0x00000007);
+
+	/* RBBM */
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(0), ADRENO_PROTECT_RW(0x04, 4));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(1), ADRENO_PROTECT_RW(0x08, 8));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(2), ADRENO_PROTECT_RW(0x10, 16));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(3), ADRENO_PROTECT_RW(0x20, 32));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(4), ADRENO_PROTECT_RW(0x40, 64));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(5), ADRENO_PROTECT_RW(0x80, 64));
+
+	/* Content protect */
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(6),
+		ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
+			16));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(7),
+		ADRENO_PROTECT_RW(REG_A5XX_RBBM_SECVID_TRUST_CNTL, 2));
+
+	/* CP */
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(8), ADRENO_PROTECT_RW(0x800, 64));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(9), ADRENO_PROTECT_RW(0x840, 8));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(10), ADRENO_PROTECT_RW(0x880, 32));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(11), ADRENO_PROTECT_RW(0xAA0, 1));
+
+	/* RB */
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(12), ADRENO_PROTECT_RW(0xCC0, 1));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(13), ADRENO_PROTECT_RW(0xCF0, 2));
+
+	/* VPC */
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(14), ADRENO_PROTECT_RW(0xE68, 8));
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(15), ADRENO_PROTECT_RW(0xE70, 4));
+
+	/* UCHE */
+	gpu_write(gpu, REG_A5XX_CP_PROTECT(16), ADRENO_PROTECT_RW(0xE80, 16));
+
+	if (adreno_is_a530(adreno_gpu))
+		gpu_write(gpu, REG_A5XX_CP_PROTECT(17),
+			ADRENO_PROTECT_RW(0x10000, 0x8000));
+
+	gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
+	/*
+	 * Disable the trusted memory range - we don't actually supported secure
+	 * memory rendering at this point in time and we don't want to block off
+	 * part of the virtual memory space.
+	 */
+	gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
+		REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
+	gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
+
+	/* Load the GPMU firmware before starting the HW init */
+	a5xx_gpmu_ucode_init(gpu);
+
+	ret = adreno_hw_init(gpu);
+	if (ret)
+		return ret;
+
+	ret = a5xx_ucode_init(gpu);
+	if (ret)
+		return ret;
+
+	/* Disable the interrupts through the initial bringup stage */
+	gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
+
+	/* Clear ME_HALT to start the micro engine */
+	gpu_write(gpu, REG_A5XX_CP_PFP_ME_CNTL, 0);
+	ret = a5xx_me_init(gpu);
+	if (ret)
+		return ret;
+
+	ret = a5xx_power_init(gpu);
+	if (ret)
+		return ret;
+
+	/*
+	 * Send a pipeline event stat to get misbehaving counters to start
+	 * ticking correctly
+	 */
+	if (adreno_is_a530(adreno_gpu)) {
+		OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1);
+		OUT_RING(gpu->rb, 0x0F);
+
+		gpu->funcs->flush(gpu);
+		if (!gpu->funcs->idle(gpu))
+			return -EINVAL;
+	}
+
+	/* Put the GPU into unsecure mode */
+	gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0);
+
+	return 0;
+}
+
+static void a5xx_recover(struct msm_gpu *gpu)
+{
+	int i;
+
+	adreno_dump_info(gpu);
+
+	for (i = 0; i < 8; i++) {
+		printk("CP_SCRATCH_REG%d: %u\n", i,
+			gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(i)));
+	}
+
+	if (hang_debug)
+		a5xx_dump(gpu);
+
+	gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 1);
+	gpu_read(gpu, REG_A5XX_RBBM_SW_RESET_CMD);
+	gpu_write(gpu, REG_A5XX_RBBM_SW_RESET_CMD, 0);
+	adreno_recover(gpu);
+}
+
+static void a5xx_destroy(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+
+	DBG("%s", gpu->name);
+
+	if (a5xx_gpu->pm4_bo) {
+		if (a5xx_gpu->pm4_iova)
+			msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->id);
+		drm_gem_object_unreference_unlocked(a5xx_gpu->pm4_bo);
+	}
+
+	if (a5xx_gpu->pfp_bo) {
+		if (a5xx_gpu->pfp_iova)
+			msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->id);
+		drm_gem_object_unreference_unlocked(a5xx_gpu->pfp_bo);
+	}
+
+	if (a5xx_gpu->gpmu_bo) {
+		if (a5xx_gpu->gpmu_bo)
+			msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->id);
+		drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
+	}
+
+	adreno_gpu_cleanup(adreno_gpu);
+	kfree(a5xx_gpu);
+}
+
+static inline bool _a5xx_check_idle(struct msm_gpu *gpu)
+{
+	if (gpu_read(gpu, REG_A5XX_RBBM_STATUS) & ~A5XX_RBBM_STATUS_HI_BUSY)
+		return false;
+
+	/*
+	 * Nearly every abnormality ends up pausing the GPU and triggering a
+	 * fault so we can safely just watch for this one interrupt to fire
+	 */
+	return !(gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS) &
+		A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT);
+}
+
+static bool a5xx_idle(struct msm_gpu *gpu)
+{
+	/* wait for CP to drain ringbuffer: */
+	if (!adreno_idle(gpu))
+		return false;
+
+	if (spin_until(_a5xx_check_idle(gpu))) {
+		DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n",
+			gpu->name, __builtin_return_address(0),
+			gpu_read(gpu, REG_A5XX_RBBM_STATUS),
+			gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS));
+
+		return false;
+	}
+
+	return true;
+}
+
+static void a5xx_cp_err_irq(struct msm_gpu *gpu)
+{
+	u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
+
+	if (status & A5XX_CP_INT_CP_OPCODE_ERROR) {
+		u32 val;
+
+		gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, 0);
+
+		/*
+		 * REG_A5XX_CP_PFP_STAT_DATA is indexed, and we want index 1 so
+		 * read it twice
+		 */
+
+		gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
+		val = gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA);
+
+		dev_err_ratelimited(gpu->dev->dev, "CP | opcode error | possible opcode=0x%8.8X\n",
+			val);
+	}
+
+	if (status & A5XX_CP_INT_CP_HW_FAULT_ERROR)
+		dev_err_ratelimited(gpu->dev->dev, "CP | HW fault | status=0x%8.8X\n",
+			gpu_read(gpu, REG_A5XX_CP_HW_FAULT));
+
+	if (status & A5XX_CP_INT_CP_DMA_ERROR)
+		dev_err_ratelimited(gpu->dev->dev, "CP | DMA error\n");
+
+	if (status & A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR) {
+		u32 val = gpu_read(gpu, REG_A5XX_CP_PROTECT_STATUS);
+
+		dev_err_ratelimited(gpu->dev->dev,
+			"CP | protected mode error | %s | addr=0x%8.8X | status=0x%8.8X\n",
+			val & (1 << 24) ? "WRITE" : "READ",
+			(val & 0xFFFFF) >> 2, val);
+	}
+
+	if (status & A5XX_CP_INT_CP_AHB_ERROR) {
+		u32 status = gpu_read(gpu, REG_A5XX_CP_AHB_FAULT);
+		const char *access[16] = { "reserved", "reserved",
+			"timestamp lo", "timestamp hi", "pfp read", "pfp write",
+			"", "", "me read", "me write", "", "", "crashdump read",
+			"crashdump write" };
+
+		dev_err_ratelimited(gpu->dev->dev,
+			"CP | AHB error | addr=%X access=%s error=%d | status=0x%8.8X\n",
+			status & 0xFFFFF, access[(status >> 24) & 0xF],
+			(status & (1 << 31)), status);
+	}
+}
+
+static void a5xx_rbbm_err_irq(struct msm_gpu *gpu)
+{
+	u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
+
+	if (status & A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR) {
+		u32 val = gpu_read(gpu, REG_A5XX_RBBM_AHB_ERROR_STATUS);
+
+		dev_err_ratelimited(gpu->dev->dev,
+			"RBBM | AHB bus error | %s | addr=0x%X | ports=0x%X:0x%X\n",
+			val & (1 << 28) ? "WRITE" : "READ",
+			(val & 0xFFFFF) >> 2, (val >> 20) & 0x3,
+			(val >> 24) & 0xF);
+
+		/* Clear the error */
+		gpu_write(gpu, REG_A5XX_RBBM_AHB_CMD, (1 << 4));
+	}
+
+	if (status & A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT)
+		dev_err_ratelimited(gpu->dev->dev, "RBBM | AHB transfer timeout\n");
+
+	if (status & A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT)
+		dev_err_ratelimited(gpu->dev->dev, "RBBM | ME master split | status=0x%X\n",
+			gpu_read(gpu, REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS));
+
+	if (status & A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT)
+		dev_err_ratelimited(gpu->dev->dev, "RBBM | PFP master split | status=0x%X\n",
+			gpu_read(gpu, REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS));
+
+	if (status & A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT)
+		dev_err_ratelimited(gpu->dev->dev, "RBBM | ETS master split | status=0x%X\n",
+			gpu_read(gpu, REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS));
+
+	if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
+		dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB ASYNC overflow\n");
+
+	if (status & A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW)
+		dev_err_ratelimited(gpu->dev->dev, "RBBM | ATB bus overflow\n");
+}
+
+static void a5xx_uche_err_irq(struct msm_gpu *gpu)
+{
+	uint64_t addr = (uint64_t) gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_HI);
+
+	addr |= gpu_read(gpu, REG_A5XX_UCHE_TRAP_LOG_LO);
+
+	dev_err_ratelimited(gpu->dev->dev, "UCHE | Out of bounds access | addr=0x%llX\n",
+		addr);
+}
+
+static void a5xx_gpmu_err_irq(struct msm_gpu *gpu)
+{
+	dev_err_ratelimited(gpu->dev->dev, "GPMU | voltage droop\n");
+}
+
+#define RBBM_ERROR_MASK \
+	(A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR | \
+	A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT | \
+	A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT | \
+	A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT | \
+	A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT | \
+	A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW)
+
+static irqreturn_t a5xx_irq(struct msm_gpu *gpu)
+{
+	u32 status = gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS);
+
+	gpu_write(gpu, REG_A5XX_RBBM_INT_CLEAR_CMD, status);
+
+	if (status & RBBM_ERROR_MASK)
+		a5xx_rbbm_err_irq(gpu);
+
+	if (status & A5XX_RBBM_INT_0_MASK_CP_HW_ERROR)
+		a5xx_cp_err_irq(gpu);
+
+	if (status & A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS)
+		a5xx_uche_err_irq(gpu);
+
+	if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP)
+		a5xx_gpmu_err_irq(gpu);
+
+	if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS)
+		msm_gpu_retire(gpu);
+
+	return IRQ_HANDLED;
+}
+
+static const u32 a5xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
+	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE, REG_A5XX_CP_RB_BASE),
+	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_BASE_HI, REG_A5XX_CP_RB_BASE_HI),
+	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR, REG_A5XX_CP_RB_RPTR_ADDR),
+	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR_ADDR_HI,
+		REG_A5XX_CP_RB_RPTR_ADDR_HI),
+	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_RPTR, REG_A5XX_CP_RB_RPTR),
+	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_WPTR, REG_A5XX_CP_RB_WPTR),
+	REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A5XX_CP_RB_CNTL),
+};
+
+static const u32 a5xx_registers[] = {
+	0x0000, 0x0002, 0x0004, 0x0020, 0x0022, 0x0026, 0x0029, 0x002B,
+	0x002E, 0x0035, 0x0038, 0x0042, 0x0044, 0x0044, 0x0047, 0x0095,
+	0x0097, 0x00BB, 0x03A0, 0x0464, 0x0469, 0x046F, 0x04D2, 0x04D3,
+	0x04E0, 0x0533, 0x0540, 0x0555, 0xF400, 0xF400, 0xF800, 0xF807,
+	0x0800, 0x081A, 0x081F, 0x0841, 0x0860, 0x0860, 0x0880, 0x08A0,
+	0x0B00, 0x0B12, 0x0B15, 0x0B28, 0x0B78, 0x0B7F, 0x0BB0, 0x0BBD,
+	0x0BC0, 0x0BC6, 0x0BD0, 0x0C53, 0x0C60, 0x0C61, 0x0C80, 0x0C82,
+	0x0C84, 0x0C85, 0x0C90, 0x0C98, 0x0CA0, 0x0CA0, 0x0CB0, 0x0CB2,
+	0x2180, 0x2185, 0x2580, 0x2585, 0x0CC1, 0x0CC1, 0x0CC4, 0x0CC7,
+	0x0CCC, 0x0CCC, 0x0CD0, 0x0CD8, 0x0CE0, 0x0CE5, 0x0CE8, 0x0CE8,
+	0x0CEC, 0x0CF1, 0x0CFB, 0x0D0E, 0x2100, 0x211E, 0x2140, 0x2145,
+	0x2500, 0x251E, 0x2540, 0x2545, 0x0D10, 0x0D17, 0x0D20, 0x0D23,
+	0x0D30, 0x0D30, 0x20C0, 0x20C0, 0x24C0, 0x24C0, 0x0E40, 0x0E43,
+	0x0E4A, 0x0E4A, 0x0E50, 0x0E57, 0x0E60, 0x0E7C, 0x0E80, 0x0E8E,
+	0x0E90, 0x0E96, 0x0EA0, 0x0EA8, 0x0EB0, 0x0EB2, 0xE140, 0xE147,
+	0xE150, 0xE187, 0xE1A0, 0xE1A9, 0xE1B0, 0xE1B6, 0xE1C0, 0xE1C7,
+	0xE1D0, 0xE1D1, 0xE200, 0xE201, 0xE210, 0xE21C, 0xE240, 0xE268,
+	0xE000, 0xE006, 0xE010, 0xE09A, 0xE0A0, 0xE0A4, 0xE0AA, 0xE0EB,
+	0xE100, 0xE105, 0xE380, 0xE38F, 0xE3B0, 0xE3B0, 0xE400, 0xE405,
+	0xE408, 0xE4E9, 0xE4F0, 0xE4F0, 0xE280, 0xE280, 0xE282, 0xE2A3,
+	0xE2A5, 0xE2C2, 0xE940, 0xE947, 0xE950, 0xE987, 0xE9A0, 0xE9A9,
+	0xE9B0, 0xE9B6, 0xE9C0, 0xE9C7, 0xE9D0, 0xE9D1, 0xEA00, 0xEA01,
+	0xEA10, 0xEA1C, 0xEA40, 0xEA68, 0xE800, 0xE806, 0xE810, 0xE89A,
+	0xE8A0, 0xE8A4, 0xE8AA, 0xE8EB, 0xE900, 0xE905, 0xEB80, 0xEB8F,
+	0xEBB0, 0xEBB0, 0xEC00, 0xEC05, 0xEC08, 0xECE9, 0xECF0, 0xECF0,
+	0xEA80, 0xEA80, 0xEA82, 0xEAA3, 0xEAA5, 0xEAC2, 0xA800, 0xA8FF,
+	0xAC60, 0xAC60, 0xB000, 0xB97F, 0xB9A0, 0xB9BF,
+	~0
+};
+
+static void a5xx_dump(struct msm_gpu *gpu)
+{
+	dev_info(gpu->dev->dev, "status:   %08x\n",
+		gpu_read(gpu, REG_A5XX_RBBM_STATUS));
+	adreno_dump(gpu);
+}
+
+static int a5xx_pm_resume(struct msm_gpu *gpu)
+{
+	int ret;
+
+	/* Turn on the core power */
+	ret = msm_gpu_pm_resume(gpu);
+	if (ret)
+		return ret;
+
+	/* Turn the RBCCU domain first to limit the chances of voltage droop */
+	gpu_write(gpu, REG_A5XX_GPMU_RBCCU_POWER_CNTL, 0x778000);
+
+	/* Wait 3 usecs before polling */
+	udelay(3);
+
+	ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS,
+		(1 << 20), (1 << 20));
+	if (ret) {
+		DRM_ERROR("%s: timeout waiting for RBCCU GDSC enable: %X\n",
+			gpu->name,
+			gpu_read(gpu, REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS));
+		return ret;
+	}
+
+	/* Turn on the SP domain */
+	gpu_write(gpu, REG_A5XX_GPMU_SP_POWER_CNTL, 0x778000);
+	ret = spin_usecs(gpu, 20, REG_A5XX_GPMU_SP_PWR_CLK_STATUS,
+		(1 << 20), (1 << 20));
+	if (ret)
+		DRM_ERROR("%s: timeout waiting for SP GDSC enable\n",
+			gpu->name);
+
+	return ret;
+}
+
+static int a5xx_pm_suspend(struct msm_gpu *gpu)
+{
+	/* Clear the VBIF pipe before shutting down */
+	gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0xF);
+	spin_until((gpu_read(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL1) & 0xF) == 0xF);
+
+	gpu_write(gpu, REG_A5XX_VBIF_XIN_HALT_CTRL0, 0);
+
+	/*
+	 * Reset the VBIF before power collapse to avoid issue with FIFO
+	 * entries
+	 */
+	gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x003C0000);
+	gpu_write(gpu, REG_A5XX_RBBM_BLOCK_SW_RESET_CMD, 0x00000000);
+
+	return msm_gpu_pm_suspend(gpu);
+}
+
+static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
+{
+	*value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
+		REG_A5XX_RBBM_PERFCTR_CP_0_HI);
+
+	return 0;
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m)
+{
+	gpu->funcs->pm_resume(gpu);
+
+	seq_printf(m, "status:   %08x\n",
+			gpu_read(gpu, REG_A5XX_RBBM_STATUS));
+	gpu->funcs->pm_suspend(gpu);
+
+	adreno_show(gpu, m);
+}
+#endif
+
+static const struct adreno_gpu_funcs funcs = {
+	.base = {
+		.get_param = adreno_get_param,
+		.hw_init = a5xx_hw_init,
+		.pm_suspend = a5xx_pm_suspend,
+		.pm_resume = a5xx_pm_resume,
+		.recover = a5xx_recover,
+		.last_fence = adreno_last_fence,
+		.submit = a5xx_submit,
+		.flush = adreno_flush,
+		.idle = a5xx_idle,
+		.irq = a5xx_irq,
+		.destroy = a5xx_destroy,
+		.show = a5xx_show,
+	},
+	.get_timestamp = a5xx_get_timestamp,
+};
+
+struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
+{
+	struct msm_drm_private *priv = dev->dev_private;
+	struct platform_device *pdev = priv->gpu_pdev;
+	struct a5xx_gpu *a5xx_gpu = NULL;
+	struct adreno_gpu *adreno_gpu;
+	struct msm_gpu *gpu;
+	int ret;
+
+	if (!pdev) {
+		dev_err(dev->dev, "No A5XX device is defined\n");
+		return ERR_PTR(-ENXIO);
+	}
+
+	a5xx_gpu = kzalloc(sizeof(*a5xx_gpu), GFP_KERNEL);
+	if (!a5xx_gpu)
+		return ERR_PTR(-ENOMEM);
+
+	adreno_gpu = &a5xx_gpu->base;
+	gpu = &adreno_gpu->base;
+
+	a5xx_gpu->pdev = pdev;
+	adreno_gpu->registers = a5xx_registers;
+	adreno_gpu->reg_offsets = a5xx_register_offsets;
+
+	a5xx_gpu->lm_leakage = 0x4E001A;
+
+	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs);
+	if (ret) {
+		a5xx_destroy(&(a5xx_gpu->base.base));
+		return ERR_PTR(ret);
+	}
+
+	return gpu;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx_gpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,60 @@
+/* Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __A5XX_GPU_H__
+#define __A5XX_GPU_H__
+
+#include "adreno_gpu.h"
+
+/* Bringing over the hack from the previous targets */
+#undef ROP_COPY
+#undef ROP_XOR
+
+#include "a5xx.xml.h"
+
+struct a5xx_gpu {
+	struct adreno_gpu base;
+	struct platform_device *pdev;
+
+	struct drm_gem_object *pm4_bo;
+	uint64_t pm4_iova;
+
+	struct drm_gem_object *pfp_bo;
+	uint64_t pfp_iova;
+
+	struct drm_gem_object *gpmu_bo;
+	uint64_t gpmu_iova;
+	uint32_t gpmu_dwords;
+
+	uint32_t lm_leakage;
+};
+
+#define to_a5xx_gpu(x) container_of(x, struct a5xx_gpu, base)
+
+int a5xx_power_init(struct msm_gpu *gpu);
+void a5xx_gpmu_ucode_init(struct msm_gpu *gpu);
+
+static inline int spin_usecs(struct msm_gpu *gpu, uint32_t usecs,
+		uint32_t reg, uint32_t mask, uint32_t value)
+{
+	while (usecs--) {
+		udelay(1);
+		if ((gpu_read(gpu, reg) & mask) == value)
+			return 0;
+		cpu_relax();
+	}
+
+	return -ETIMEDOUT;
+}
+
+
+#endif /* __A5XX_GPU_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx_power.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx_power.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx_power.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx_power.c	2017-02-12 17:25:48.000000000 -0500
@@ -0,0 +1,344 @@
+/* Copyright (c) 2016 The Linux Foundation. All 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/pm_opp.h>
+#include "a5xx_gpu.h"
+
+/*
+ * The GPMU data block is a block of shared registers that can be used to
+ * communicate back and forth. These "registers" are by convention with the GPMU
+ * firwmare and not bound to any specific hardware design
+ */
+
+#define AGC_INIT_BASE REG_A5XX_GPMU_DATA_RAM_BASE
+#define AGC_INIT_MSG_MAGIC (AGC_INIT_BASE + 5)
+#define AGC_MSG_BASE (AGC_INIT_BASE + 7)
+
+#define AGC_MSG_STATE (AGC_MSG_BASE + 0)
+#define AGC_MSG_COMMAND (AGC_MSG_BASE + 1)
+#define AGC_MSG_PAYLOAD_SIZE (AGC_MSG_BASE + 3)
+#define AGC_MSG_PAYLOAD(_o) ((AGC_MSG_BASE + 5) + (_o))
+
+#define AGC_POWER_CONFIG_PRODUCTION_ID 1
+#define AGC_INIT_MSG_VALUE 0xBABEFACE
+
+static struct {
+	uint32_t reg;
+	uint32_t value;
+} a5xx_sequence_regs[] = {
+	{ 0xB9A1, 0x00010303 },
+	{ 0xB9A2, 0x13000000 },
+	{ 0xB9A3, 0x00460020 },
+	{ 0xB9A4, 0x10000000 },
+	{ 0xB9A5, 0x040A1707 },
+	{ 0xB9A6, 0x00010000 },
+	{ 0xB9A7, 0x0E000904 },
+	{ 0xB9A8, 0x10000000 },
+	{ 0xB9A9, 0x01165000 },
+	{ 0xB9AA, 0x000E0002 },
+	{ 0xB9AB, 0x03884141 },
+	{ 0xB9AC, 0x10000840 },
+	{ 0xB9AD, 0x572A5000 },
+	{ 0xB9AE, 0x00000003 },
+	{ 0xB9AF, 0x00000000 },
+	{ 0xB9B0, 0x10000000 },
+	{ 0xB828, 0x6C204010 },
+	{ 0xB829, 0x6C204011 },
+	{ 0xB82A, 0x6C204012 },
+	{ 0xB82B, 0x6C204013 },
+	{ 0xB82C, 0x6C204014 },
+	{ 0xB90F, 0x00000004 },
+	{ 0xB910, 0x00000002 },
+	{ 0xB911, 0x00000002 },
+	{ 0xB912, 0x00000002 },
+	{ 0xB913, 0x00000002 },
+	{ 0xB92F, 0x00000004 },
+	{ 0xB930, 0x00000005 },
+	{ 0xB931, 0x00000005 },
+	{ 0xB932, 0x00000005 },
+	{ 0xB933, 0x00000005 },
+	{ 0xB96F, 0x00000001 },
+	{ 0xB970, 0x00000003 },
+	{ 0xB94F, 0x00000004 },
+	{ 0xB950, 0x0000000B },
+	{ 0xB951, 0x0000000B },
+	{ 0xB952, 0x0000000B },
+	{ 0xB953, 0x0000000B },
+	{ 0xB907, 0x00000019 },
+	{ 0xB927, 0x00000019 },
+	{ 0xB947, 0x00000019 },
+	{ 0xB967, 0x00000019 },
+	{ 0xB987, 0x00000019 },
+	{ 0xB906, 0x00220001 },
+	{ 0xB926, 0x00220001 },
+	{ 0xB946, 0x00220001 },
+	{ 0xB966, 0x00220001 },
+	{ 0xB986, 0x00300000 },
+	{ 0xAC40, 0x0340FF41 },
+	{ 0xAC41, 0x03BEFED0 },
+	{ 0xAC42, 0x00331FED },
+	{ 0xAC43, 0x021FFDD3 },
+	{ 0xAC44, 0x5555AAAA },
+	{ 0xAC45, 0x5555AAAA },
+	{ 0xB9BA, 0x00000008 },
+};
+
+/*
+ * Get the actual voltage value for the operating point at the specified
+ * frequency
+ */
+static inline uint32_t _get_mvolts(struct msm_gpu *gpu, uint32_t freq)
+{
+	struct drm_device *dev = gpu->dev;
+	struct msm_drm_private *priv = dev->dev_private;
+	struct platform_device *pdev = priv->gpu_pdev;
+	struct dev_pm_opp *opp;
+
+	opp = dev_pm_opp_find_freq_exact(&pdev->dev, freq, true);
+
+	return (!IS_ERR(opp)) ? dev_pm_opp_get_voltage(opp) / 1000 : 0;
+}
+
+/* Setup thermal limit management */
+static void a5xx_lm_setup(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+	unsigned int i;
+
+	/* Write the block of sequence registers */
+	for (i = 0; i < ARRAY_SIZE(a5xx_sequence_regs); i++)
+		gpu_write(gpu, a5xx_sequence_regs[i].reg,
+			a5xx_sequence_regs[i].value);
+
+	/* Hard code the A530 GPU thermal sensor ID for the GPMU */
+	gpu_write(gpu, REG_A5XX_GPMU_TEMP_SENSOR_ID, 0x60007);
+	gpu_write(gpu, REG_A5XX_GPMU_DELTA_TEMP_THRESHOLD, 0x01);
+	gpu_write(gpu, REG_A5XX_GPMU_TEMP_SENSOR_CONFIG, 0x01);
+
+	/* Until we get clock scaling 0 is always the active power level */
+	gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE, 0x80000000 | 0);
+
+	gpu_write(gpu, REG_A5XX_GPMU_BASE_LEAKAGE, a5xx_gpu->lm_leakage);
+
+	/* The threshold is fixed at 6000 for A530 */
+	gpu_write(gpu, REG_A5XX_GPMU_GPMU_PWR_THRESHOLD, 0x80000000 | 6000);
+
+	gpu_write(gpu, REG_A5XX_GPMU_BEC_ENABLE, 0x10001FFF);
+	gpu_write(gpu, REG_A5XX_GDPM_CONFIG1, 0x00201FF1);
+
+	/* Write the voltage table */
+	gpu_write(gpu, REG_A5XX_GPMU_BEC_ENABLE, 0x10001FFF);
+	gpu_write(gpu, REG_A5XX_GDPM_CONFIG1, 0x201FF1);
+
+	gpu_write(gpu, AGC_MSG_STATE, 1);
+	gpu_write(gpu, AGC_MSG_COMMAND, AGC_POWER_CONFIG_PRODUCTION_ID);
+
+	/* Write the max power - hard coded to 5448 for A530 */
+	gpu_write(gpu, AGC_MSG_PAYLOAD(0), 5448);
+	gpu_write(gpu, AGC_MSG_PAYLOAD(1), 1);
+
+	/*
+	 * For now just write the one voltage level - we will do more when we
+	 * can do scaling
+	 */
+	gpu_write(gpu, AGC_MSG_PAYLOAD(2), _get_mvolts(gpu, gpu->fast_rate));
+	gpu_write(gpu, AGC_MSG_PAYLOAD(3), gpu->fast_rate / 1000000);
+
+	gpu_write(gpu, AGC_MSG_PAYLOAD_SIZE, 4 * sizeof(uint32_t));
+	gpu_write(gpu, AGC_INIT_MSG_MAGIC, AGC_INIT_MSG_VALUE);
+}
+
+/* Enable SP/TP cpower collapse */
+static void a5xx_pc_init(struct msm_gpu *gpu)
+{
+	gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_INTER_FRAME_CTRL, 0x7F);
+	gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_BINNING_CTRL, 0);
+	gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_INTER_FRAME_HYST, 0xA0080);
+	gpu_write(gpu, REG_A5XX_GPMU_PWR_COL_STAGGER_DELAY, 0x600040);
+}
+
+/* Enable the GPMU microcontroller */
+static int a5xx_gpmu_init(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+	struct msm_ringbuffer *ring = gpu->rb;
+
+	if (!a5xx_gpu->gpmu_dwords)
+		return 0;
+
+	/* Turn off protected mode for this operation */
+	OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
+	OUT_RING(ring, 0);
+
+	/* Kick off the IB to load the GPMU microcode */
+	OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3);
+	OUT_RING(ring, lower_32_bits(a5xx_gpu->gpmu_iova));
+	OUT_RING(ring, upper_32_bits(a5xx_gpu->gpmu_iova));
+	OUT_RING(ring, a5xx_gpu->gpmu_dwords);
+
+	/* Turn back on protected mode */
+	OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
+	OUT_RING(ring, 1);
+
+	gpu->funcs->flush(gpu);
+
+	if (!gpu->funcs->idle(gpu)) {
+		DRM_ERROR("%s: Unable to load GPMU firmware. GPMU will not be active\n",
+			gpu->name);
+		return -EINVAL;
+	}
+
+	gpu_write(gpu, REG_A5XX_GPMU_WFI_CONFIG, 0x4014);
+
+	/* Kick off the GPMU */
+	gpu_write(gpu, REG_A5XX_GPMU_CM3_SYSRESET, 0x0);
+
+	/*
+	 * Wait for the GPMU to respond. It isn't fatal if it doesn't, we just
+	 * won't have advanced power collapse.
+	 */
+	if (spin_usecs(gpu, 25, REG_A5XX_GPMU_GENERAL_0, 0xFFFFFFFF,
+		0xBABEFACE))
+		DRM_ERROR("%s: GPMU firmware initialization timed out\n",
+			gpu->name);
+
+	return 0;
+}
+
+/* Enable limits management */
+static void a5xx_lm_enable(struct msm_gpu *gpu)
+{
+	gpu_write(gpu, REG_A5XX_GDPM_INT_MASK, 0x0);
+	gpu_write(gpu, REG_A5XX_GDPM_INT_EN, 0x0A);
+	gpu_write(gpu, REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_EN_MASK, 0x01);
+	gpu_write(gpu, REG_A5XX_GPMU_TEMP_THRESHOLD_INTR_EN_MASK, 0x50000);
+	gpu_write(gpu, REG_A5XX_GPMU_THROTTLE_UNMASK_FORCE_CTRL, 0x30000);
+
+	gpu_write(gpu, REG_A5XX_GPMU_CLOCK_THROTTLE_CTRL, 0x011);
+}
+
+int a5xx_power_init(struct msm_gpu *gpu)
+{
+	int ret;
+
+	/* Set up the limits management */
+	a5xx_lm_setup(gpu);
+
+	/* Set up SP/TP power collpase */
+	a5xx_pc_init(gpu);
+
+	/* Start the GPMU */
+	ret = a5xx_gpmu_init(gpu);
+	if (ret)
+		return ret;
+
+	/* Start the limits management */
+	a5xx_lm_enable(gpu);
+
+	return 0;
+}
+
+void a5xx_gpmu_ucode_init(struct msm_gpu *gpu)
+{
+	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
+	struct drm_device *drm = gpu->dev;
+	const struct firmware *fw;
+	uint32_t dwords = 0, offset = 0, bosize;
+	unsigned int *data, *ptr, *cmds;
+	unsigned int cmds_size;
+
+	if (a5xx_gpu->gpmu_bo)
+		return;
+
+	/* Get the firmware */
+	if (reject_firmware(&fw, adreno_gpu->info->gpmufw, drm->dev)) {
+		DRM_ERROR("%s: Could not get GPMU firmware. GPMU will not be active\n",
+			gpu->name);
+		return;
+	}
+
+	data = (unsigned int *) fw->data;
+
+	/*
+	 * The first dword is the size of the remaining data in dwords. Use it
+	 * as a checksum of sorts and make sure it matches the actual size of
+	 * the firmware that we read
+	 */
+
+	if (fw->size < 8 || (data[0] < 2) || (data[0] >= (fw->size >> 2)))
+		goto out;
+
+	/* The second dword is an ID - look for 2 (GPMU_FIRMWARE_ID) */
+	if (data[1] != 2)
+		goto out;
+
+	cmds = data + data[2] + 3;
+	cmds_size = data[0] - data[2] - 2;
+
+	/*
+	 * A single type4 opcode can only have so many values attached so
+	 * add enough opcodes to load the all the commands
+	 */
+	bosize = (cmds_size + (cmds_size / TYPE4_MAX_PAYLOAD) + 1) << 2;
+
+	mutex_lock(&drm->struct_mutex);
+	a5xx_gpu->gpmu_bo = msm_gem_new(drm, bosize, MSM_BO_UNCACHED);
+	mutex_unlock(&drm->struct_mutex);
+
+	if (IS_ERR(a5xx_gpu->gpmu_bo))
+		goto err;
+
+	if (msm_gem_get_iova(a5xx_gpu->gpmu_bo, gpu->id, &a5xx_gpu->gpmu_iova))
+		goto err;
+
+	ptr = msm_gem_get_vaddr(a5xx_gpu->gpmu_bo);
+	if (!ptr)
+		goto err;
+
+	while (cmds_size > 0) {
+		int i;
+		uint32_t _size = cmds_size > TYPE4_MAX_PAYLOAD ?
+			TYPE4_MAX_PAYLOAD : cmds_size;
+
+		ptr[dwords++] = PKT4(REG_A5XX_GPMU_INST_RAM_BASE + offset,
+			_size);
+
+		for (i = 0; i < _size; i++)
+			ptr[dwords++] = *cmds++;
+
+		offset += _size;
+		cmds_size -= _size;
+	}
+
+	msm_gem_put_vaddr(a5xx_gpu->gpmu_bo);
+	a5xx_gpu->gpmu_dwords = dwords;
+
+	goto out;
+
+err:
+	if (a5xx_gpu->gpmu_iova)
+		msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->id);
+	if (a5xx_gpu->gpmu_bo)
+		drm_gem_object_unreference_unlocked(a5xx_gpu->gpmu_bo);
+
+	a5xx_gpu->gpmu_bo = NULL;
+	a5xx_gpu->gpmu_iova = 0;
+	a5xx_gpu->gpmu_dwords = 0;
+
+out:
+	/* No need to keep that firmware laying around anymore */
+	release_firmware(fw);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/a5xx.xml.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/a5xx.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3757 @@
+#ifndef A5XX_XML
+#define A5XX_XML
+
+/* Autogenerated file, DO NOT EDIT manually!
+
+This file was generated by the rules-ng-ng headergen tool in this git repository:
+http://github.com/freedreno/envytools/
+git clone https://github.com/freedreno/envytools.git
+
+The rules-ng-ng source files this header was generated from are:
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    431 bytes, from 2016-04-26 17:56:44)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1572 bytes, from 2016-02-10 17:07:21)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml          (  90321 bytes, from 2016-11-28 16:50:05)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml         (   1773 bytes, from 2015-09-24 17:30:00)
+
+Copyright (C) 2013-2016 by the following authors:
+- Rob Clark <robdclark@gmail.com> (robclark)
+- Ilia Mirkin <imirkin@alum.mit.edu> (imirkin)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+enum a5xx_color_fmt {
+	RB5_R8_UNORM = 3,
+	RB5_R4G4B4A4_UNORM = 8,
+	RB5_R5G5B5A1_UNORM = 10,
+	RB5_R5G6B5_UNORM = 14,
+	RB5_R16_FLOAT = 23,
+	RB5_R8G8B8A8_UNORM = 48,
+	RB5_R8G8B8_UNORM = 49,
+	RB5_R8G8B8A8_UINT = 51,
+	RB5_R10G10B10A2_UINT = 58,
+	RB5_R16G16_FLOAT = 69,
+	RB5_R32_FLOAT = 74,
+	RB5_R16G16B16A16_FLOAT = 98,
+	RB5_R32G32_FLOAT = 103,
+	RB5_R32G32B32A32_FLOAT = 130,
+};
+
+enum a5xx_tile_mode {
+	TILE5_LINEAR = 0,
+	TILE5_2 = 2,
+	TILE5_3 = 3,
+};
+
+enum a5xx_vtx_fmt {
+	VFMT5_8_UNORM = 3,
+	VFMT5_8_SNORM = 4,
+	VFMT5_8_UINT = 5,
+	VFMT5_8_SINT = 6,
+	VFMT5_8_8_UNORM = 15,
+	VFMT5_8_8_SNORM = 16,
+	VFMT5_8_8_UINT = 17,
+	VFMT5_8_8_SINT = 18,
+	VFMT5_16_UNORM = 21,
+	VFMT5_16_SNORM = 22,
+	VFMT5_16_FLOAT = 23,
+	VFMT5_16_UINT = 24,
+	VFMT5_16_SINT = 25,
+	VFMT5_8_8_8_UNORM = 33,
+	VFMT5_8_8_8_SNORM = 34,
+	VFMT5_8_8_8_UINT = 35,
+	VFMT5_8_8_8_SINT = 36,
+	VFMT5_8_8_8_8_UNORM = 48,
+	VFMT5_8_8_8_8_SNORM = 50,
+	VFMT5_8_8_8_8_UINT = 51,
+	VFMT5_8_8_8_8_SINT = 52,
+	VFMT5_16_16_UNORM = 67,
+	VFMT5_16_16_SNORM = 68,
+	VFMT5_16_16_FLOAT = 69,
+	VFMT5_16_16_UINT = 70,
+	VFMT5_16_16_SINT = 71,
+	VFMT5_32_UNORM = 72,
+	VFMT5_32_SNORM = 73,
+	VFMT5_32_FLOAT = 74,
+	VFMT5_32_UINT = 75,
+	VFMT5_32_SINT = 76,
+	VFMT5_32_FIXED = 77,
+	VFMT5_16_16_16_UNORM = 88,
+	VFMT5_16_16_16_SNORM = 89,
+	VFMT5_16_16_16_FLOAT = 90,
+	VFMT5_16_16_16_UINT = 91,
+	VFMT5_16_16_16_SINT = 92,
+	VFMT5_16_16_16_16_UNORM = 96,
+	VFMT5_16_16_16_16_SNORM = 97,
+	VFMT5_16_16_16_16_FLOAT = 98,
+	VFMT5_16_16_16_16_UINT = 99,
+	VFMT5_16_16_16_16_SINT = 100,
+	VFMT5_32_32_UNORM = 101,
+	VFMT5_32_32_SNORM = 102,
+	VFMT5_32_32_FLOAT = 103,
+	VFMT5_32_32_UINT = 104,
+	VFMT5_32_32_SINT = 105,
+	VFMT5_32_32_FIXED = 106,
+	VFMT5_32_32_32_UNORM = 112,
+	VFMT5_32_32_32_SNORM = 113,
+	VFMT5_32_32_32_UINT = 114,
+	VFMT5_32_32_32_SINT = 115,
+	VFMT5_32_32_32_FLOAT = 116,
+	VFMT5_32_32_32_FIXED = 117,
+	VFMT5_32_32_32_32_UNORM = 128,
+	VFMT5_32_32_32_32_SNORM = 129,
+	VFMT5_32_32_32_32_FLOAT = 130,
+	VFMT5_32_32_32_32_UINT = 131,
+	VFMT5_32_32_32_32_SINT = 132,
+	VFMT5_32_32_32_32_FIXED = 133,
+};
+
+enum a5xx_tex_fmt {
+	TFMT5_A8_UNORM = 2,
+	TFMT5_8_UNORM = 3,
+	TFMT5_4_4_4_4_UNORM = 8,
+	TFMT5_5_5_5_1_UNORM = 10,
+	TFMT5_5_6_5_UNORM = 14,
+	TFMT5_8_8_UNORM = 15,
+	TFMT5_8_8_SNORM = 16,
+	TFMT5_L8_A8_UNORM = 19,
+	TFMT5_16_FLOAT = 23,
+	TFMT5_8_8_8_8_UNORM = 48,
+	TFMT5_8_8_8_UNORM = 49,
+	TFMT5_8_8_8_SNORM = 50,
+	TFMT5_9_9_9_E5_FLOAT = 53,
+	TFMT5_10_10_10_2_UNORM = 54,
+	TFMT5_11_11_10_FLOAT = 66,
+	TFMT5_16_16_FLOAT = 69,
+	TFMT5_32_FLOAT = 74,
+	TFMT5_16_16_16_16_FLOAT = 98,
+	TFMT5_32_32_FLOAT = 103,
+	TFMT5_32_32_32_32_FLOAT = 130,
+	TFMT5_X8Z24_UNORM = 160,
+};
+
+enum a5xx_tex_fetchsize {
+	TFETCH5_1_BYTE = 0,
+	TFETCH5_2_BYTE = 1,
+	TFETCH5_4_BYTE = 2,
+	TFETCH5_8_BYTE = 3,
+	TFETCH5_16_BYTE = 4,
+};
+
+enum a5xx_depth_format {
+	DEPTH5_NONE = 0,
+	DEPTH5_16 = 1,
+	DEPTH5_24_8 = 2,
+	DEPTH5_32 = 4,
+};
+
+enum a5xx_blit_buf {
+	BLIT_MRT0 = 0,
+	BLIT_MRT1 = 1,
+	BLIT_MRT2 = 2,
+	BLIT_MRT3 = 3,
+	BLIT_MRT4 = 4,
+	BLIT_MRT5 = 5,
+	BLIT_MRT6 = 6,
+	BLIT_MRT7 = 7,
+	BLIT_ZS = 8,
+	BLIT_Z32 = 9,
+};
+
+enum a5xx_tex_filter {
+	A5XX_TEX_NEAREST = 0,
+	A5XX_TEX_LINEAR = 1,
+	A5XX_TEX_ANISO = 2,
+};
+
+enum a5xx_tex_clamp {
+	A5XX_TEX_REPEAT = 0,
+	A5XX_TEX_CLAMP_TO_EDGE = 1,
+	A5XX_TEX_MIRROR_REPEAT = 2,
+	A5XX_TEX_CLAMP_TO_BORDER = 3,
+	A5XX_TEX_MIRROR_CLAMP = 4,
+};
+
+enum a5xx_tex_aniso {
+	A5XX_TEX_ANISO_1 = 0,
+	A5XX_TEX_ANISO_2 = 1,
+	A5XX_TEX_ANISO_4 = 2,
+	A5XX_TEX_ANISO_8 = 3,
+	A5XX_TEX_ANISO_16 = 4,
+};
+
+enum a5xx_tex_swiz {
+	A5XX_TEX_X = 0,
+	A5XX_TEX_Y = 1,
+	A5XX_TEX_Z = 2,
+	A5XX_TEX_W = 3,
+	A5XX_TEX_ZERO = 4,
+	A5XX_TEX_ONE = 5,
+};
+
+enum a5xx_tex_type {
+	A5XX_TEX_1D = 0,
+	A5XX_TEX_2D = 1,
+	A5XX_TEX_CUBE = 2,
+	A5XX_TEX_3D = 3,
+};
+
+#define A5XX_INT0_RBBM_GPU_IDLE					0x00000001
+#define A5XX_INT0_RBBM_AHB_ERROR				0x00000002
+#define A5XX_INT0_RBBM_TRANSFER_TIMEOUT				0x00000004
+#define A5XX_INT0_RBBM_ME_MS_TIMEOUT				0x00000008
+#define A5XX_INT0_RBBM_PFP_MS_TIMEOUT				0x00000010
+#define A5XX_INT0_RBBM_ETS_MS_TIMEOUT				0x00000020
+#define A5XX_INT0_RBBM_ATB_ASYNC_OVERFLOW			0x00000040
+#define A5XX_INT0_RBBM_GPC_ERROR				0x00000080
+#define A5XX_INT0_CP_SW						0x00000100
+#define A5XX_INT0_CP_HW_ERROR					0x00000200
+#define A5XX_INT0_CP_CCU_FLUSH_DEPTH_TS				0x00000400
+#define A5XX_INT0_CP_CCU_FLUSH_COLOR_TS				0x00000800
+#define A5XX_INT0_CP_CCU_RESOLVE_TS				0x00001000
+#define A5XX_INT0_CP_IB2					0x00002000
+#define A5XX_INT0_CP_IB1					0x00004000
+#define A5XX_INT0_CP_RB						0x00008000
+#define A5XX_INT0_CP_UNUSED_1					0x00010000
+#define A5XX_INT0_CP_RB_DONE_TS					0x00020000
+#define A5XX_INT0_CP_WT_DONE_TS					0x00040000
+#define A5XX_INT0_UNKNOWN_1					0x00080000
+#define A5XX_INT0_CP_CACHE_FLUSH_TS				0x00100000
+#define A5XX_INT0_UNUSED_2					0x00200000
+#define A5XX_INT0_RBBM_ATB_BUS_OVERFLOW				0x00400000
+#define A5XX_INT0_MISC_HANG_DETECT				0x00800000
+#define A5XX_INT0_UCHE_OOB_ACCESS				0x01000000
+#define A5XX_INT0_UCHE_TRAP_INTR				0x02000000
+#define A5XX_INT0_DEBBUS_INTR_0					0x04000000
+#define A5XX_INT0_DEBBUS_INTR_1					0x08000000
+#define A5XX_INT0_GPMU_VOLTAGE_DROOP				0x10000000
+#define A5XX_INT0_GPMU_FIRMWARE					0x20000000
+#define A5XX_INT0_ISDB_CPU_IRQ					0x40000000
+#define A5XX_INT0_ISDB_UNDER_DEBUG				0x80000000
+#define A5XX_CP_INT_CP_OPCODE_ERROR				0x00000001
+#define A5XX_CP_INT_CP_RESERVED_BIT_ERROR			0x00000002
+#define A5XX_CP_INT_CP_HW_FAULT_ERROR				0x00000004
+#define A5XX_CP_INT_CP_DMA_ERROR				0x00000008
+#define A5XX_CP_INT_CP_REGISTER_PROTECTION_ERROR		0x00000010
+#define A5XX_CP_INT_CP_AHB_ERROR				0x00000020
+#define REG_A5XX_CP_RB_BASE					0x00000800
+
+#define REG_A5XX_CP_RB_BASE_HI					0x00000801
+
+#define REG_A5XX_CP_RB_CNTL					0x00000802
+
+#define REG_A5XX_CP_RB_RPTR_ADDR				0x00000804
+
+#define REG_A5XX_CP_RB_RPTR_ADDR_HI				0x00000805
+
+#define REG_A5XX_CP_RB_RPTR					0x00000806
+
+#define REG_A5XX_CP_RB_WPTR					0x00000807
+
+#define REG_A5XX_CP_PFP_STAT_ADDR				0x00000808
+
+#define REG_A5XX_CP_PFP_STAT_DATA				0x00000809
+
+#define REG_A5XX_CP_DRAW_STATE_ADDR				0x0000080b
+
+#define REG_A5XX_CP_DRAW_STATE_DATA				0x0000080c
+
+#define REG_A5XX_CP_CRASH_SCRIPT_BASE_LO			0x00000817
+
+#define REG_A5XX_CP_CRASH_SCRIPT_BASE_HI			0x00000818
+
+#define REG_A5XX_CP_CRASH_DUMP_CNTL				0x00000819
+
+#define REG_A5XX_CP_ME_STAT_ADDR				0x0000081a
+
+#define REG_A5XX_CP_ROQ_THRESHOLDS_1				0x0000081f
+
+#define REG_A5XX_CP_ROQ_THRESHOLDS_2				0x00000820
+
+#define REG_A5XX_CP_ROQ_DBG_ADDR				0x00000821
+
+#define REG_A5XX_CP_ROQ_DBG_DATA				0x00000822
+
+#define REG_A5XX_CP_MEQ_DBG_ADDR				0x00000823
+
+#define REG_A5XX_CP_MEQ_DBG_DATA				0x00000824
+
+#define REG_A5XX_CP_MEQ_THRESHOLDS				0x00000825
+
+#define REG_A5XX_CP_MERCIU_SIZE					0x00000826
+
+#define REG_A5XX_CP_MERCIU_DBG_ADDR				0x00000827
+
+#define REG_A5XX_CP_MERCIU_DBG_DATA_1				0x00000828
+
+#define REG_A5XX_CP_MERCIU_DBG_DATA_2				0x00000829
+
+#define REG_A5XX_CP_PFP_UCODE_DBG_ADDR				0x0000082a
+
+#define REG_A5XX_CP_PFP_UCODE_DBG_DATA				0x0000082b
+
+#define REG_A5XX_CP_ME_UCODE_DBG_ADDR				0x0000082f
+
+#define REG_A5XX_CP_ME_UCODE_DBG_DATA				0x00000830
+
+#define REG_A5XX_CP_CNTL					0x00000831
+
+#define REG_A5XX_CP_PFP_ME_CNTL					0x00000832
+
+#define REG_A5XX_CP_CHICKEN_DBG					0x00000833
+
+#define REG_A5XX_CP_PFP_INSTR_BASE_LO				0x00000835
+
+#define REG_A5XX_CP_PFP_INSTR_BASE_HI				0x00000836
+
+#define REG_A5XX_CP_ME_INSTR_BASE_LO				0x00000838
+
+#define REG_A5XX_CP_ME_INSTR_BASE_HI				0x00000839
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_CNTL				0x0000083b
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO		0x0000083c
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_HI		0x0000083d
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_LO			0x0000083e
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_HI			0x0000083f
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_LO			0x00000840
+
+#define REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_HI			0x00000841
+
+#define REG_A5XX_CP_ADDR_MODE_CNTL				0x00000860
+
+#define REG_A5XX_CP_ME_STAT_DATA				0x00000b14
+
+#define REG_A5XX_CP_WFI_PEND_CTR				0x00000b15
+
+#define REG_A5XX_CP_INTERRUPT_STATUS				0x00000b18
+
+#define REG_A5XX_CP_HW_FAULT					0x00000b1a
+
+#define REG_A5XX_CP_PROTECT_STATUS				0x00000b1c
+
+#define REG_A5XX_CP_IB1_BASE					0x00000b1f
+
+#define REG_A5XX_CP_IB1_BASE_HI					0x00000b20
+
+#define REG_A5XX_CP_IB1_BUFSZ					0x00000b21
+
+#define REG_A5XX_CP_IB2_BASE					0x00000b22
+
+#define REG_A5XX_CP_IB2_BASE_HI					0x00000b23
+
+#define REG_A5XX_CP_IB2_BUFSZ					0x00000b24
+
+static inline uint32_t REG_A5XX_CP_SCRATCH(uint32_t i0) { return 0x00000b78 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_CP_SCRATCH_REG(uint32_t i0) { return 0x00000b78 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_CP_PROTECT(uint32_t i0) { return 0x00000880 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_CP_PROTECT_REG(uint32_t i0) { return 0x00000880 + 0x1*i0; }
+#define A5XX_CP_PROTECT_REG_BASE_ADDR__MASK			0x0001ffff
+#define A5XX_CP_PROTECT_REG_BASE_ADDR__SHIFT			0
+static inline uint32_t A5XX_CP_PROTECT_REG_BASE_ADDR(uint32_t val)
+{
+	return ((val) << A5XX_CP_PROTECT_REG_BASE_ADDR__SHIFT) & A5XX_CP_PROTECT_REG_BASE_ADDR__MASK;
+}
+#define A5XX_CP_PROTECT_REG_MASK_LEN__MASK			0x1f000000
+#define A5XX_CP_PROTECT_REG_MASK_LEN__SHIFT			24
+static inline uint32_t A5XX_CP_PROTECT_REG_MASK_LEN(uint32_t val)
+{
+	return ((val) << A5XX_CP_PROTECT_REG_MASK_LEN__SHIFT) & A5XX_CP_PROTECT_REG_MASK_LEN__MASK;
+}
+#define A5XX_CP_PROTECT_REG_TRAP_WRITE				0x20000000
+#define A5XX_CP_PROTECT_REG_TRAP_READ				0x40000000
+
+#define REG_A5XX_CP_PROTECT_CNTL				0x000008a0
+
+#define REG_A5XX_CP_AHB_FAULT					0x00000b1b
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_0				0x00000bb0
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_1				0x00000bb1
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_2				0x00000bb2
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_3				0x00000bb3
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_4				0x00000bb4
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_5				0x00000bb5
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_6				0x00000bb6
+
+#define REG_A5XX_CP_PERFCTR_CP_SEL_7				0x00000bb7
+
+#define REG_A5XX_VSC_ADDR_MODE_CNTL				0x00000bc1
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_0				0x00000bba
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_1				0x00000bbb
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_2				0x00000bbc
+
+#define REG_A5XX_CP_POWERCTR_CP_SEL_3				0x00000bbd
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_A				0x00000004
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_B				0x00000005
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_C				0x00000006
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_SEL_D				0x00000007
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_CNTLT				0x00000008
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_CNTLM				0x00000009
+
+#define REG_A5XX_RBBM_CFG_DEBBUS_CTLTM_ENABLE_SHIFT		0x00000018
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_OPL				0x0000000a
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_OPE				0x0000000b
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_0				0x0000000c
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_1				0x0000000d
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_2				0x0000000e
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTL_3				0x0000000f
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_0			0x00000010
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_1			0x00000011
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_2			0x00000012
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKL_3			0x00000013
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_BYTEL_0			0x00000014
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_BYTEL_1			0x00000015
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_0				0x00000016
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_1				0x00000017
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_2				0x00000018
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IVTE_3				0x00000019
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_0			0x0000001a
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_1			0x0000001b
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_2			0x0000001c
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MASKE_3			0x0000001d
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_NIBBLEE			0x0000001e
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_PTRC0				0x0000001f
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_PTRC1				0x00000020
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_LOADREG			0x00000021
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_IDX				0x00000022
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_CLRC				0x00000023
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_LOADIVT			0x00000024
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_INT_CNTL			0x0000002f
+
+#define REG_A5XX_RBBM_INT_CLEAR_CMD				0x00000037
+
+#define REG_A5XX_RBBM_INT_0_MASK				0x00000038
+#define A5XX_RBBM_INT_0_MASK_RBBM_GPU_IDLE			0x00000001
+#define A5XX_RBBM_INT_0_MASK_RBBM_AHB_ERROR			0x00000002
+#define A5XX_RBBM_INT_0_MASK_RBBM_TRANSFER_TIMEOUT		0x00000004
+#define A5XX_RBBM_INT_0_MASK_RBBM_ME_MS_TIMEOUT			0x00000008
+#define A5XX_RBBM_INT_0_MASK_RBBM_PFP_MS_TIMEOUT		0x00000010
+#define A5XX_RBBM_INT_0_MASK_RBBM_ETS_MS_TIMEOUT		0x00000020
+#define A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW		0x00000040
+#define A5XX_RBBM_INT_0_MASK_RBBM_GPC_ERROR			0x00000080
+#define A5XX_RBBM_INT_0_MASK_CP_SW				0x00000100
+#define A5XX_RBBM_INT_0_MASK_CP_HW_ERROR			0x00000200
+#define A5XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_DEPTH_TS		0x00000400
+#define A5XX_RBBM_INT_0_MASK_CP_CCU_FLUSH_COLOR_TS		0x00000800
+#define A5XX_RBBM_INT_0_MASK_CP_CCU_RESOLVE_TS			0x00001000
+#define A5XX_RBBM_INT_0_MASK_CP_IB2				0x00002000
+#define A5XX_RBBM_INT_0_MASK_CP_IB1				0x00004000
+#define A5XX_RBBM_INT_0_MASK_CP_RB				0x00008000
+#define A5XX_RBBM_INT_0_MASK_CP_RB_DONE_TS			0x00020000
+#define A5XX_RBBM_INT_0_MASK_CP_WT_DONE_TS			0x00040000
+#define A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS			0x00100000
+#define A5XX_RBBM_INT_0_MASK_RBBM_ATB_BUS_OVERFLOW		0x00400000
+#define A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT			0x00800000
+#define A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS			0x01000000
+#define A5XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR			0x02000000
+#define A5XX_RBBM_INT_0_MASK_DEBBUS_INTR_0			0x04000000
+#define A5XX_RBBM_INT_0_MASK_DEBBUS_INTR_1			0x08000000
+#define A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP			0x10000000
+#define A5XX_RBBM_INT_0_MASK_GPMU_FIRMWARE			0x20000000
+#define A5XX_RBBM_INT_0_MASK_ISDB_CPU_IRQ			0x40000000
+#define A5XX_RBBM_INT_0_MASK_ISDB_UNDER_DEBUG			0x80000000
+
+#define REG_A5XX_RBBM_AHB_DBG_CNTL				0x0000003f
+
+#define REG_A5XX_RBBM_EXT_VBIF_DBG_CNTL				0x00000041
+
+#define REG_A5XX_RBBM_SW_RESET_CMD				0x00000043
+
+#define REG_A5XX_RBBM_BLOCK_SW_RESET_CMD			0x00000045
+
+#define REG_A5XX_RBBM_BLOCK_SW_RESET_CMD2			0x00000046
+
+#define REG_A5XX_RBBM_DBG_LO_HI_GPIO				0x00000048
+
+#define REG_A5XX_RBBM_EXT_TRACE_BUS_CNTL			0x00000049
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP0				0x0000004a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP1				0x0000004b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP2				0x0000004c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TP3				0x0000004d
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP0				0x0000004e
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP1				0x0000004f
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP2				0x00000050
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_TP3				0x00000051
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP0				0x00000052
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP1				0x00000053
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP2				0x00000054
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_TP3				0x00000055
+
+#define REG_A5XX_RBBM_READ_AHB_THROUGH_DBG			0x00000059
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_UCHE				0x0000005a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_UCHE				0x0000005b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL3_UCHE				0x0000005c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL4_UCHE				0x0000005d
+
+#define REG_A5XX_RBBM_CLOCK_HYST_UCHE				0x0000005e
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_UCHE				0x0000005f
+
+#define REG_A5XX_RBBM_CLOCK_MODE_GPC				0x00000060
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_GPC				0x00000061
+
+#define REG_A5XX_RBBM_CLOCK_HYST_GPC				0x00000062
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM			0x00000063
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM			0x00000064
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM			0x00000065
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_HLSQ				0x00000066
+
+#define REG_A5XX_RBBM_CLOCK_CNTL				0x00000067
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP0				0x00000068
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP1				0x00000069
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP2				0x0000006a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_SP3				0x0000006b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP0				0x0000006c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP1				0x0000006d
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP2				0x0000006e
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_SP3				0x0000006f
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP0				0x00000070
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP1				0x00000071
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP2				0x00000072
+
+#define REG_A5XX_RBBM_CLOCK_HYST_SP3				0x00000073
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP0				0x00000074
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP1				0x00000075
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP2				0x00000076
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_SP3				0x00000077
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB0				0x00000078
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB1				0x00000079
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB2				0x0000007a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RB3				0x0000007b
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB0				0x0000007c
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB1				0x0000007d
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB2				0x0000007e
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RB3				0x0000007f
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RAC				0x00000080
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RAC				0x00000081
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU0				0x00000082
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU1				0x00000083
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU2				0x00000084
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_CCU3				0x00000085
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU0			0x00000086
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU1			0x00000087
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU2			0x00000088
+
+#define REG_A5XX_RBBM_CLOCK_HYST_RB_CCU3			0x00000089
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_RAC				0x0000008a
+
+#define REG_A5XX_RBBM_CLOCK_CNTL2_RAC				0x0000008b
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0			0x0000008c
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1			0x0000008d
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2			0x0000008e
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3			0x0000008f
+
+#define REG_A5XX_RBBM_CLOCK_HYST_VFD				0x00000090
+
+#define REG_A5XX_RBBM_CLOCK_MODE_VFD				0x00000091
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_VFD				0x00000092
+
+#define REG_A5XX_RBBM_AHB_CNTL0					0x00000093
+
+#define REG_A5XX_RBBM_AHB_CNTL1					0x00000094
+
+#define REG_A5XX_RBBM_AHB_CNTL2					0x00000095
+
+#define REG_A5XX_RBBM_AHB_CMD					0x00000096
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL11		0x0000009c
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL12		0x0000009d
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL13		0x0000009e
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL14		0x0000009f
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL15		0x000000a0
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL16		0x000000a1
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL17		0x000000a2
+
+#define REG_A5XX_RBBM_INTERFACE_HANG_MASK_CNTL18		0x000000a3
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP0				0x000000a4
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP1				0x000000a5
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP2				0x000000a6
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_TP3				0x000000a7
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP0				0x000000a8
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP1				0x000000a9
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP2				0x000000aa
+
+#define REG_A5XX_RBBM_CLOCK_DELAY2_TP3				0x000000ab
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP0				0x000000ac
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP1				0x000000ad
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP2				0x000000ae
+
+#define REG_A5XX_RBBM_CLOCK_DELAY3_TP3				0x000000af
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP0				0x000000b0
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP1				0x000000b1
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP2				0x000000b2
+
+#define REG_A5XX_RBBM_CLOCK_HYST_TP3				0x000000b3
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP0				0x000000b4
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP1				0x000000b5
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP2				0x000000b6
+
+#define REG_A5XX_RBBM_CLOCK_HYST2_TP3				0x000000b7
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP0				0x000000b8
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP1				0x000000b9
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP2				0x000000ba
+
+#define REG_A5XX_RBBM_CLOCK_HYST3_TP3				0x000000bb
+
+#define REG_A5XX_RBBM_CLOCK_CNTL_GPMU				0x000000c8
+
+#define REG_A5XX_RBBM_CLOCK_DELAY_GPMU				0x000000c9
+
+#define REG_A5XX_RBBM_CLOCK_HYST_GPMU				0x000000ca
+
+#define REG_A5XX_RBBM_PERFCTR_CP_0_LO				0x000003a0
+
+#define REG_A5XX_RBBM_PERFCTR_CP_0_HI				0x000003a1
+
+#define REG_A5XX_RBBM_PERFCTR_CP_1_LO				0x000003a2
+
+#define REG_A5XX_RBBM_PERFCTR_CP_1_HI				0x000003a3
+
+#define REG_A5XX_RBBM_PERFCTR_CP_2_LO				0x000003a4
+
+#define REG_A5XX_RBBM_PERFCTR_CP_2_HI				0x000003a5
+
+#define REG_A5XX_RBBM_PERFCTR_CP_3_LO				0x000003a6
+
+#define REG_A5XX_RBBM_PERFCTR_CP_3_HI				0x000003a7
+
+#define REG_A5XX_RBBM_PERFCTR_CP_4_LO				0x000003a8
+
+#define REG_A5XX_RBBM_PERFCTR_CP_4_HI				0x000003a9
+
+#define REG_A5XX_RBBM_PERFCTR_CP_5_LO				0x000003aa
+
+#define REG_A5XX_RBBM_PERFCTR_CP_5_HI				0x000003ab
+
+#define REG_A5XX_RBBM_PERFCTR_CP_6_LO				0x000003ac
+
+#define REG_A5XX_RBBM_PERFCTR_CP_6_HI				0x000003ad
+
+#define REG_A5XX_RBBM_PERFCTR_CP_7_LO				0x000003ae
+
+#define REG_A5XX_RBBM_PERFCTR_CP_7_HI				0x000003af
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_0_LO				0x000003b0
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_0_HI				0x000003b1
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_1_LO				0x000003b2
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_1_HI				0x000003b3
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_2_LO				0x000003b4
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_2_HI				0x000003b5
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_3_LO				0x000003b6
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_3_HI				0x000003b7
+
+#define REG_A5XX_RBBM_PERFCTR_PC_0_LO				0x000003b8
+
+#define REG_A5XX_RBBM_PERFCTR_PC_0_HI				0x000003b9
+
+#define REG_A5XX_RBBM_PERFCTR_PC_1_LO				0x000003ba
+
+#define REG_A5XX_RBBM_PERFCTR_PC_1_HI				0x000003bb
+
+#define REG_A5XX_RBBM_PERFCTR_PC_2_LO				0x000003bc
+
+#define REG_A5XX_RBBM_PERFCTR_PC_2_HI				0x000003bd
+
+#define REG_A5XX_RBBM_PERFCTR_PC_3_LO				0x000003be
+
+#define REG_A5XX_RBBM_PERFCTR_PC_3_HI				0x000003bf
+
+#define REG_A5XX_RBBM_PERFCTR_PC_4_LO				0x000003c0
+
+#define REG_A5XX_RBBM_PERFCTR_PC_4_HI				0x000003c1
+
+#define REG_A5XX_RBBM_PERFCTR_PC_5_LO				0x000003c2
+
+#define REG_A5XX_RBBM_PERFCTR_PC_5_HI				0x000003c3
+
+#define REG_A5XX_RBBM_PERFCTR_PC_6_LO				0x000003c4
+
+#define REG_A5XX_RBBM_PERFCTR_PC_6_HI				0x000003c5
+
+#define REG_A5XX_RBBM_PERFCTR_PC_7_LO				0x000003c6
+
+#define REG_A5XX_RBBM_PERFCTR_PC_7_HI				0x000003c7
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_0_LO				0x000003c8
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_0_HI				0x000003c9
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_1_LO				0x000003ca
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_1_HI				0x000003cb
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_2_LO				0x000003cc
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_2_HI				0x000003cd
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_3_LO				0x000003ce
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_3_HI				0x000003cf
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_4_LO				0x000003d0
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_4_HI				0x000003d1
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_5_LO				0x000003d2
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_5_HI				0x000003d3
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_6_LO				0x000003d4
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_6_HI				0x000003d5
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_7_LO				0x000003d6
+
+#define REG_A5XX_RBBM_PERFCTR_VFD_7_HI				0x000003d7
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_0_LO				0x000003d8
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_0_HI				0x000003d9
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_1_LO				0x000003da
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_1_HI				0x000003db
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_2_LO				0x000003dc
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_2_HI				0x000003dd
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_3_LO				0x000003de
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_3_HI				0x000003df
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_4_LO				0x000003e0
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_4_HI				0x000003e1
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_5_LO				0x000003e2
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_5_HI				0x000003e3
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_6_LO				0x000003e4
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_6_HI				0x000003e5
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_7_LO				0x000003e6
+
+#define REG_A5XX_RBBM_PERFCTR_HLSQ_7_HI				0x000003e7
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_0_LO				0x000003e8
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_0_HI				0x000003e9
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_1_LO				0x000003ea
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_1_HI				0x000003eb
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_2_LO				0x000003ec
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_2_HI				0x000003ed
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_3_LO				0x000003ee
+
+#define REG_A5XX_RBBM_PERFCTR_VPC_3_HI				0x000003ef
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_0_LO				0x000003f0
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_0_HI				0x000003f1
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_1_LO				0x000003f2
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_1_HI				0x000003f3
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_2_LO				0x000003f4
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_2_HI				0x000003f5
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_3_LO				0x000003f6
+
+#define REG_A5XX_RBBM_PERFCTR_CCU_3_HI				0x000003f7
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_0_LO				0x000003f8
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_0_HI				0x000003f9
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_1_LO				0x000003fa
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_1_HI				0x000003fb
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_2_LO				0x000003fc
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_2_HI				0x000003fd
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_3_LO				0x000003fe
+
+#define REG_A5XX_RBBM_PERFCTR_TSE_3_HI				0x000003ff
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_0_LO				0x00000400
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_0_HI				0x00000401
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_1_LO				0x00000402
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_1_HI				0x00000403
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_2_LO				0x00000404
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_2_HI				0x00000405
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_3_LO				0x00000406
+
+#define REG_A5XX_RBBM_PERFCTR_RAS_3_HI				0x00000407
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_0_LO				0x00000408
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_0_HI				0x00000409
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_1_LO				0x0000040a
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_1_HI				0x0000040b
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_2_LO				0x0000040c
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_2_HI				0x0000040d
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_3_LO				0x0000040e
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_3_HI				0x0000040f
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_4_LO				0x00000410
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_4_HI				0x00000411
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_5_LO				0x00000412
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_5_HI				0x00000413
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_6_LO				0x00000414
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_6_HI				0x00000415
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_7_LO				0x00000416
+
+#define REG_A5XX_RBBM_PERFCTR_UCHE_7_HI				0x00000417
+
+#define REG_A5XX_RBBM_PERFCTR_TP_0_LO				0x00000418
+
+#define REG_A5XX_RBBM_PERFCTR_TP_0_HI				0x00000419
+
+#define REG_A5XX_RBBM_PERFCTR_TP_1_LO				0x0000041a
+
+#define REG_A5XX_RBBM_PERFCTR_TP_1_HI				0x0000041b
+
+#define REG_A5XX_RBBM_PERFCTR_TP_2_LO				0x0000041c
+
+#define REG_A5XX_RBBM_PERFCTR_TP_2_HI				0x0000041d
+
+#define REG_A5XX_RBBM_PERFCTR_TP_3_LO				0x0000041e
+
+#define REG_A5XX_RBBM_PERFCTR_TP_3_HI				0x0000041f
+
+#define REG_A5XX_RBBM_PERFCTR_TP_4_LO				0x00000420
+
+#define REG_A5XX_RBBM_PERFCTR_TP_4_HI				0x00000421
+
+#define REG_A5XX_RBBM_PERFCTR_TP_5_LO				0x00000422
+
+#define REG_A5XX_RBBM_PERFCTR_TP_5_HI				0x00000423
+
+#define REG_A5XX_RBBM_PERFCTR_TP_6_LO				0x00000424
+
+#define REG_A5XX_RBBM_PERFCTR_TP_6_HI				0x00000425
+
+#define REG_A5XX_RBBM_PERFCTR_TP_7_LO				0x00000426
+
+#define REG_A5XX_RBBM_PERFCTR_TP_7_HI				0x00000427
+
+#define REG_A5XX_RBBM_PERFCTR_SP_0_LO				0x00000428
+
+#define REG_A5XX_RBBM_PERFCTR_SP_0_HI				0x00000429
+
+#define REG_A5XX_RBBM_PERFCTR_SP_1_LO				0x0000042a
+
+#define REG_A5XX_RBBM_PERFCTR_SP_1_HI				0x0000042b
+
+#define REG_A5XX_RBBM_PERFCTR_SP_2_LO				0x0000042c
+
+#define REG_A5XX_RBBM_PERFCTR_SP_2_HI				0x0000042d
+
+#define REG_A5XX_RBBM_PERFCTR_SP_3_LO				0x0000042e
+
+#define REG_A5XX_RBBM_PERFCTR_SP_3_HI				0x0000042f
+
+#define REG_A5XX_RBBM_PERFCTR_SP_4_LO				0x00000430
+
+#define REG_A5XX_RBBM_PERFCTR_SP_4_HI				0x00000431
+
+#define REG_A5XX_RBBM_PERFCTR_SP_5_LO				0x00000432
+
+#define REG_A5XX_RBBM_PERFCTR_SP_5_HI				0x00000433
+
+#define REG_A5XX_RBBM_PERFCTR_SP_6_LO				0x00000434
+
+#define REG_A5XX_RBBM_PERFCTR_SP_6_HI				0x00000435
+
+#define REG_A5XX_RBBM_PERFCTR_SP_7_LO				0x00000436
+
+#define REG_A5XX_RBBM_PERFCTR_SP_7_HI				0x00000437
+
+#define REG_A5XX_RBBM_PERFCTR_SP_8_LO				0x00000438
+
+#define REG_A5XX_RBBM_PERFCTR_SP_8_HI				0x00000439
+
+#define REG_A5XX_RBBM_PERFCTR_SP_9_LO				0x0000043a
+
+#define REG_A5XX_RBBM_PERFCTR_SP_9_HI				0x0000043b
+
+#define REG_A5XX_RBBM_PERFCTR_SP_10_LO				0x0000043c
+
+#define REG_A5XX_RBBM_PERFCTR_SP_10_HI				0x0000043d
+
+#define REG_A5XX_RBBM_PERFCTR_SP_11_LO				0x0000043e
+
+#define REG_A5XX_RBBM_PERFCTR_SP_11_HI				0x0000043f
+
+#define REG_A5XX_RBBM_PERFCTR_RB_0_LO				0x00000440
+
+#define REG_A5XX_RBBM_PERFCTR_RB_0_HI				0x00000441
+
+#define REG_A5XX_RBBM_PERFCTR_RB_1_LO				0x00000442
+
+#define REG_A5XX_RBBM_PERFCTR_RB_1_HI				0x00000443
+
+#define REG_A5XX_RBBM_PERFCTR_RB_2_LO				0x00000444
+
+#define REG_A5XX_RBBM_PERFCTR_RB_2_HI				0x00000445
+
+#define REG_A5XX_RBBM_PERFCTR_RB_3_LO				0x00000446
+
+#define REG_A5XX_RBBM_PERFCTR_RB_3_HI				0x00000447
+
+#define REG_A5XX_RBBM_PERFCTR_RB_4_LO				0x00000448
+
+#define REG_A5XX_RBBM_PERFCTR_RB_4_HI				0x00000449
+
+#define REG_A5XX_RBBM_PERFCTR_RB_5_LO				0x0000044a
+
+#define REG_A5XX_RBBM_PERFCTR_RB_5_HI				0x0000044b
+
+#define REG_A5XX_RBBM_PERFCTR_RB_6_LO				0x0000044c
+
+#define REG_A5XX_RBBM_PERFCTR_RB_6_HI				0x0000044d
+
+#define REG_A5XX_RBBM_PERFCTR_RB_7_LO				0x0000044e
+
+#define REG_A5XX_RBBM_PERFCTR_RB_7_HI				0x0000044f
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_0_LO				0x00000450
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_0_HI				0x00000451
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_1_LO				0x00000452
+
+#define REG_A5XX_RBBM_PERFCTR_VSC_1_HI				0x00000453
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_0_LO				0x00000454
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_0_HI				0x00000455
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_1_LO				0x00000456
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_1_HI				0x00000457
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_2_LO				0x00000458
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_2_HI				0x00000459
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_3_LO				0x0000045a
+
+#define REG_A5XX_RBBM_PERFCTR_LRZ_3_HI				0x0000045b
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_0_LO				0x0000045c
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_0_HI				0x0000045d
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_1_LO				0x0000045e
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_1_HI				0x0000045f
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_2_LO				0x00000460
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_2_HI				0x00000461
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_3_LO				0x00000462
+
+#define REG_A5XX_RBBM_PERFCTR_CMP_3_HI				0x00000463
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_0			0x0000046b
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_1			0x0000046c
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_2			0x0000046d
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_3			0x0000046e
+
+#define REG_A5XX_RBBM_ALWAYSON_COUNTER_LO			0x000004d2
+
+#define REG_A5XX_RBBM_ALWAYSON_COUNTER_HI			0x000004d3
+
+#define REG_A5XX_RBBM_STATUS					0x000004f5
+#define A5XX_RBBM_STATUS_GPU_BUSY_IGN_AHB			0x80000000
+#define A5XX_RBBM_STATUS_GPU_BUSY_IGN_AHB_CP			0x40000000
+#define A5XX_RBBM_STATUS_HLSQ_BUSY				0x20000000
+#define A5XX_RBBM_STATUS_VSC_BUSY				0x10000000
+#define A5XX_RBBM_STATUS_TPL1_BUSY				0x08000000
+#define A5XX_RBBM_STATUS_SP_BUSY				0x04000000
+#define A5XX_RBBM_STATUS_UCHE_BUSY				0x02000000
+#define A5XX_RBBM_STATUS_VPC_BUSY				0x01000000
+#define A5XX_RBBM_STATUS_VFDP_BUSY				0x00800000
+#define A5XX_RBBM_STATUS_VFD_BUSY				0x00400000
+#define A5XX_RBBM_STATUS_TESS_BUSY				0x00200000
+#define A5XX_RBBM_STATUS_PC_VSD_BUSY				0x00100000
+#define A5XX_RBBM_STATUS_PC_DCALL_BUSY				0x00080000
+#define A5XX_RBBM_STATUS_GPMU_SLAVE_BUSY			0x00040000
+#define A5XX_RBBM_STATUS_DCOM_BUSY				0x00020000
+#define A5XX_RBBM_STATUS_COM_BUSY				0x00010000
+#define A5XX_RBBM_STATUS_LRZ_BUZY				0x00008000
+#define A5XX_RBBM_STATUS_A2D_DSP_BUSY				0x00004000
+#define A5XX_RBBM_STATUS_CCUFCHE_BUSY				0x00002000
+#define A5XX_RBBM_STATUS_RB_BUSY				0x00001000
+#define A5XX_RBBM_STATUS_RAS_BUSY				0x00000800
+#define A5XX_RBBM_STATUS_TSE_BUSY				0x00000400
+#define A5XX_RBBM_STATUS_VBIF_BUSY				0x00000200
+#define A5XX_RBBM_STATUS_GPU_BUSY_IGN_AHB_HYST			0x00000100
+#define A5XX_RBBM_STATUS_CP_BUSY_IGN_HYST			0x00000080
+#define A5XX_RBBM_STATUS_CP_BUSY				0x00000040
+#define A5XX_RBBM_STATUS_GPMU_MASTER_BUSY			0x00000020
+#define A5XX_RBBM_STATUS_CP_CRASH_BUSY				0x00000010
+#define A5XX_RBBM_STATUS_CP_ETS_BUSY				0x00000008
+#define A5XX_RBBM_STATUS_CP_PFP_BUSY				0x00000004
+#define A5XX_RBBM_STATUS_CP_ME_BUSY				0x00000002
+#define A5XX_RBBM_STATUS_HI_BUSY				0x00000001
+
+#define REG_A5XX_RBBM_STATUS3					0x00000530
+
+#define REG_A5XX_RBBM_INT_0_STATUS				0x000004e1
+
+#define REG_A5XX_RBBM_AHB_ME_SPLIT_STATUS			0x000004f0
+
+#define REG_A5XX_RBBM_AHB_PFP_SPLIT_STATUS			0x000004f1
+
+#define REG_A5XX_RBBM_AHB_ETS_SPLIT_STATUS			0x000004f3
+
+#define REG_A5XX_RBBM_AHB_ERROR_STATUS				0x000004f4
+
+#define REG_A5XX_RBBM_PERFCTR_CNTL				0x00000464
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD0				0x00000465
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD1				0x00000466
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD2				0x00000467
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_CMD3				0x00000468
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_VALUE_LO			0x00000469
+
+#define REG_A5XX_RBBM_PERFCTR_LOAD_VALUE_HI			0x0000046a
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_0			0x0000046b
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_1			0x0000046c
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_2			0x0000046d
+
+#define REG_A5XX_RBBM_PERFCTR_RBBM_SEL_3			0x0000046e
+
+#define REG_A5XX_RBBM_PERFCTR_GPU_BUSY_MASKED			0x0000046f
+
+#define REG_A5XX_RBBM_AHB_ERROR					0x000004ed
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_EVENT_LOGIC			0x00000504
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_OVER				0x00000505
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT0				0x00000506
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT1				0x00000507
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT2				0x00000508
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT3				0x00000509
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT4				0x0000050a
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_COUNT5				0x0000050b
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_ADDR			0x0000050c
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF0			0x0000050d
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF1			0x0000050e
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF2			0x0000050f
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF3			0x00000510
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_TRACE_BUF4			0x00000511
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MISR0				0x00000512
+
+#define REG_A5XX_RBBM_CFG_DBGBUS_MISR1				0x00000513
+
+#define REG_A5XX_RBBM_ISDB_CNT					0x00000533
+
+#define REG_A5XX_RBBM_SECVID_TRUST_CONFIG			0x0000f000
+
+#define REG_A5XX_RBBM_SECVID_TRUST_CNTL				0x0000f400
+
+#define REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO		0x0000f800
+
+#define REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI		0x0000f801
+
+#define REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE			0x0000f802
+
+#define REG_A5XX_RBBM_SECVID_TSB_CNTL				0x0000f803
+
+#define REG_A5XX_RBBM_SECVID_TSB_COMP_STATUS_LO			0x0000f804
+
+#define REG_A5XX_RBBM_SECVID_TSB_COMP_STATUS_HI			0x0000f805
+
+#define REG_A5XX_RBBM_SECVID_TSB_UCHE_STATUS_LO			0x0000f806
+
+#define REG_A5XX_RBBM_SECVID_TSB_UCHE_STATUS_HI			0x0000f807
+
+#define REG_A5XX_RBBM_SECVID_TSB_ADDR_MODE_CNTL			0x0000f810
+
+#define REG_A5XX_VSC_PIPE_DATA_LENGTH_0				0x00000c00
+
+#define REG_A5XX_VSC_PERFCTR_VSC_SEL_0				0x00000c60
+
+#define REG_A5XX_VSC_PERFCTR_VSC_SEL_1				0x00000c61
+
+#define REG_A5XX_VSC_BIN_SIZE					0x00000cdd
+#define A5XX_VSC_BIN_SIZE_WINDOW_OFFSET_DISABLE			0x80000000
+#define A5XX_VSC_BIN_SIZE_X__MASK				0x00007fff
+#define A5XX_VSC_BIN_SIZE_X__SHIFT				0
+static inline uint32_t A5XX_VSC_BIN_SIZE_X(uint32_t val)
+{
+	return ((val) << A5XX_VSC_BIN_SIZE_X__SHIFT) & A5XX_VSC_BIN_SIZE_X__MASK;
+}
+#define A5XX_VSC_BIN_SIZE_Y__MASK				0x7fff0000
+#define A5XX_VSC_BIN_SIZE_Y__SHIFT				16
+static inline uint32_t A5XX_VSC_BIN_SIZE_Y(uint32_t val)
+{
+	return ((val) << A5XX_VSC_BIN_SIZE_Y__SHIFT) & A5XX_VSC_BIN_SIZE_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_ADDR_MODE_CNTL				0x00000c81
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_0				0x00000c90
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_1				0x00000c91
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_2				0x00000c92
+
+#define REG_A5XX_GRAS_PERFCTR_TSE_SEL_3				0x00000c93
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_0				0x00000c94
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_1				0x00000c95
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_2				0x00000c96
+
+#define REG_A5XX_GRAS_PERFCTR_RAS_SEL_3				0x00000c97
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_0				0x00000c98
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_1				0x00000c99
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_2				0x00000c9a
+
+#define REG_A5XX_GRAS_PERFCTR_LRZ_SEL_3				0x00000c9b
+
+#define REG_A5XX_RB_DBG_ECO_CNTL				0x00000cc4
+
+#define REG_A5XX_RB_ADDR_MODE_CNTL				0x00000cc5
+
+#define REG_A5XX_RB_MODE_CNTL					0x00000cc6
+
+#define REG_A5XX_RB_CCU_CNTL					0x00000cc7
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_0				0x00000cd0
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_1				0x00000cd1
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_2				0x00000cd2
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_3				0x00000cd3
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_4				0x00000cd4
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_5				0x00000cd5
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_6				0x00000cd6
+
+#define REG_A5XX_RB_PERFCTR_RB_SEL_7				0x00000cd7
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_0				0x00000cd8
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_1				0x00000cd9
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_2				0x00000cda
+
+#define REG_A5XX_RB_PERFCTR_CCU_SEL_3				0x00000cdb
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_0				0x00000ce0
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_1				0x00000ce1
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_2				0x00000ce2
+
+#define REG_A5XX_RB_POWERCTR_RB_SEL_3				0x00000ce3
+
+#define REG_A5XX_RB_POWERCTR_CCU_SEL_0				0x00000ce4
+
+#define REG_A5XX_RB_POWERCTR_CCU_SEL_1				0x00000ce5
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_0				0x00000cec
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_1				0x00000ced
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_2				0x00000cee
+
+#define REG_A5XX_RB_PERFCTR_CMP_SEL_3				0x00000cef
+
+#define REG_A5XX_PC_DBG_ECO_CNTL				0x00000d00
+#define A5XX_PC_DBG_ECO_CNTL_TWOPASSUSEWFI			0x00000100
+
+#define REG_A5XX_PC_ADDR_MODE_CNTL				0x00000d01
+
+#define REG_A5XX_PC_MODE_CNTL					0x00000d02
+
+#define REG_A5XX_UNKNOWN_0D08					0x00000d08
+
+#define REG_A5XX_UNKNOWN_0D09					0x00000d09
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_0				0x00000d10
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_1				0x00000d11
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_2				0x00000d12
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_3				0x00000d13
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_4				0x00000d14
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_5				0x00000d15
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_6				0x00000d16
+
+#define REG_A5XX_PC_PERFCTR_PC_SEL_7				0x00000d17
+
+#define REG_A5XX_HLSQ_TIMEOUT_THRESHOLD_0			0x00000e00
+
+#define REG_A5XX_HLSQ_TIMEOUT_THRESHOLD_1			0x00000e01
+
+#define REG_A5XX_HLSQ_ADDR_MODE_CNTL				0x00000e05
+
+#define REG_A5XX_HLSQ_MODE_CNTL					0x00000e06
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_0			0x00000e10
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_1			0x00000e11
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_2			0x00000e12
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_3			0x00000e13
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_4			0x00000e14
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_5			0x00000e15
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_6			0x00000e16
+
+#define REG_A5XX_HLSQ_PERFCTR_HLSQ_SEL_7			0x00000e17
+
+#define REG_A5XX_HLSQ_SPTP_RDSEL				0x00000f08
+
+#define REG_A5XX_HLSQ_DBG_READ_SEL				0x0000bc00
+
+#define REG_A5XX_HLSQ_DBG_AHB_READ_APERTURE			0x0000a000
+
+#define REG_A5XX_VFD_ADDR_MODE_CNTL				0x00000e41
+
+#define REG_A5XX_VFD_MODE_CNTL					0x00000e42
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_0				0x00000e50
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_1				0x00000e51
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_2				0x00000e52
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_3				0x00000e53
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_4				0x00000e54
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_5				0x00000e55
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_6				0x00000e56
+
+#define REG_A5XX_VFD_PERFCTR_VFD_SEL_7				0x00000e57
+
+#define REG_A5XX_VPC_DBG_ECO_CNTL				0x00000e60
+
+#define REG_A5XX_VPC_ADDR_MODE_CNTL				0x00000e61
+
+#define REG_A5XX_VPC_MODE_CNTL					0x00000e62
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_0				0x00000e64
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_1				0x00000e65
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_2				0x00000e66
+
+#define REG_A5XX_VPC_PERFCTR_VPC_SEL_3				0x00000e67
+
+#define REG_A5XX_UCHE_ADDR_MODE_CNTL				0x00000e80
+
+#define REG_A5XX_UCHE_SVM_CNTL					0x00000e82
+
+#define REG_A5XX_UCHE_WRITE_THRU_BASE_LO			0x00000e87
+
+#define REG_A5XX_UCHE_WRITE_THRU_BASE_HI			0x00000e88
+
+#define REG_A5XX_UCHE_TRAP_BASE_LO				0x00000e89
+
+#define REG_A5XX_UCHE_TRAP_BASE_HI				0x00000e8a
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MIN_LO				0x00000e8b
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MIN_HI				0x00000e8c
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MAX_LO				0x00000e8d
+
+#define REG_A5XX_UCHE_GMEM_RANGE_MAX_HI				0x00000e8e
+
+#define REG_A5XX_UCHE_DBG_ECO_CNTL_2				0x00000e8f
+
+#define REG_A5XX_UCHE_DBG_ECO_CNTL				0x00000e90
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MIN_LO			0x00000e91
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MIN_HI			0x00000e92
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MAX_LO			0x00000e93
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE_MAX_HI			0x00000e94
+
+#define REG_A5XX_UCHE_CACHE_INVALIDATE				0x00000e95
+
+#define REG_A5XX_UCHE_CACHE_WAYS				0x00000e96
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_0			0x00000ea0
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_1			0x00000ea1
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_2			0x00000ea2
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_3			0x00000ea3
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_4			0x00000ea4
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_5			0x00000ea5
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_6			0x00000ea6
+
+#define REG_A5XX_UCHE_PERFCTR_UCHE_SEL_7			0x00000ea7
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_0			0x00000ea8
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_1			0x00000ea9
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_2			0x00000eaa
+
+#define REG_A5XX_UCHE_POWERCTR_UCHE_SEL_3			0x00000eab
+
+#define REG_A5XX_UCHE_TRAP_LOG_LO				0x00000eb1
+
+#define REG_A5XX_UCHE_TRAP_LOG_HI				0x00000eb2
+
+#define REG_A5XX_SP_DBG_ECO_CNTL				0x00000ec0
+
+#define REG_A5XX_SP_ADDR_MODE_CNTL				0x00000ec1
+
+#define REG_A5XX_SP_MODE_CNTL					0x00000ec2
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_0				0x00000ed0
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_1				0x00000ed1
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_2				0x00000ed2
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_3				0x00000ed3
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_4				0x00000ed4
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_5				0x00000ed5
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_6				0x00000ed6
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_7				0x00000ed7
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_8				0x00000ed8
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_9				0x00000ed9
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_10				0x00000eda
+
+#define REG_A5XX_SP_PERFCTR_SP_SEL_11				0x00000edb
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_0				0x00000edc
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_1				0x00000edd
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_2				0x00000ede
+
+#define REG_A5XX_SP_POWERCTR_SP_SEL_3				0x00000edf
+
+#define REG_A5XX_TPL1_ADDR_MODE_CNTL				0x00000f01
+
+#define REG_A5XX_TPL1_MODE_CNTL					0x00000f02
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_0				0x00000f10
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_1				0x00000f11
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_2				0x00000f12
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_3				0x00000f13
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_4				0x00000f14
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_5				0x00000f15
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_6				0x00000f16
+
+#define REG_A5XX_TPL1_PERFCTR_TP_SEL_7				0x00000f17
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_0				0x00000f18
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_1				0x00000f19
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_2				0x00000f1a
+
+#define REG_A5XX_TPL1_POWERCTR_TP_SEL_3				0x00000f1b
+
+#define REG_A5XX_VBIF_VERSION					0x00003000
+
+#define REG_A5XX_VBIF_CLKON					0x00003001
+
+#define REG_A5XX_VBIF_ABIT_SORT					0x00003028
+
+#define REG_A5XX_VBIF_ABIT_SORT_CONF				0x00003029
+
+#define REG_A5XX_VBIF_ROUND_ROBIN_QOS_ARB			0x00003049
+
+#define REG_A5XX_VBIF_GATE_OFF_WRREQ_EN				0x0000302a
+
+#define REG_A5XX_VBIF_IN_RD_LIM_CONF0				0x0000302c
+
+#define REG_A5XX_VBIF_IN_RD_LIM_CONF1				0x0000302d
+
+#define REG_A5XX_VBIF_XIN_HALT_CTRL0				0x00003080
+
+#define REG_A5XX_VBIF_XIN_HALT_CTRL1				0x00003081
+
+#define REG_A5XX_VBIF_TEST_BUS_OUT_CTRL				0x00003084
+
+#define REG_A5XX_VBIF_TEST_BUS1_CTRL0				0x00003085
+
+#define REG_A5XX_VBIF_TEST_BUS1_CTRL1				0x00003086
+
+#define REG_A5XX_VBIF_TEST_BUS2_CTRL0				0x00003087
+
+#define REG_A5XX_VBIF_TEST_BUS2_CTRL1				0x00003088
+
+#define REG_A5XX_VBIF_TEST_BUS_OUT				0x0000308c
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL0				0x000030d0
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL1				0x000030d1
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL2				0x000030d2
+
+#define REG_A5XX_VBIF_PERF_CNT_SEL3				0x000030d3
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW0				0x000030d8
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW1				0x000030d9
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW2				0x000030da
+
+#define REG_A5XX_VBIF_PERF_CNT_LOW3				0x000030db
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH0				0x000030e0
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH1				0x000030e1
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH2				0x000030e2
+
+#define REG_A5XX_VBIF_PERF_CNT_HIGH3				0x000030e3
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_EN0				0x00003100
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_EN1				0x00003101
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_EN2				0x00003102
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_LOW0				0x00003110
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_LOW1				0x00003111
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_LOW2				0x00003112
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_HIGH0			0x00003118
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_HIGH1			0x00003119
+
+#define REG_A5XX_VBIF_PERF_PWR_CNT_HIGH2			0x0000311a
+
+#define REG_A5XX_GPMU_INST_RAM_BASE				0x00008800
+
+#define REG_A5XX_GPMU_DATA_RAM_BASE				0x00009800
+
+#define REG_A5XX_GPMU_SP_POWER_CNTL				0x0000a881
+
+#define REG_A5XX_GPMU_RBCCU_CLOCK_CNTL				0x0000a886
+
+#define REG_A5XX_GPMU_RBCCU_POWER_CNTL				0x0000a887
+
+#define REG_A5XX_GPMU_SP_PWR_CLK_STATUS				0x0000a88b
+#define A5XX_GPMU_SP_PWR_CLK_STATUS_PWR_ON			0x00100000
+
+#define REG_A5XX_GPMU_RBCCU_PWR_CLK_STATUS			0x0000a88d
+#define A5XX_GPMU_RBCCU_PWR_CLK_STATUS_PWR_ON			0x00100000
+
+#define REG_A5XX_GPMU_PWR_COL_STAGGER_DELAY			0x0000a891
+
+#define REG_A5XX_GPMU_PWR_COL_INTER_FRAME_CTRL			0x0000a892
+
+#define REG_A5XX_GPMU_PWR_COL_INTER_FRAME_HYST			0x0000a893
+
+#define REG_A5XX_GPMU_PWR_COL_BINNING_CTRL			0x0000a894
+
+#define REG_A5XX_GPMU_CLOCK_THROTTLE_CTRL			0x0000a8a3
+
+#define REG_A5XX_GPMU_WFI_CONFIG				0x0000a8c1
+
+#define REG_A5XX_GPMU_RBBM_INTR_INFO				0x0000a8d6
+
+#define REG_A5XX_GPMU_CM3_SYSRESET				0x0000a8d8
+
+#define REG_A5XX_GPMU_GENERAL_0					0x0000a8e0
+
+#define REG_A5XX_GPMU_GENERAL_1					0x0000a8e1
+
+#define REG_A5XX_SP_POWER_COUNTER_0_LO				0x0000a840
+
+#define REG_A5XX_SP_POWER_COUNTER_0_HI				0x0000a841
+
+#define REG_A5XX_SP_POWER_COUNTER_1_LO				0x0000a842
+
+#define REG_A5XX_SP_POWER_COUNTER_1_HI				0x0000a843
+
+#define REG_A5XX_SP_POWER_COUNTER_2_LO				0x0000a844
+
+#define REG_A5XX_SP_POWER_COUNTER_2_HI				0x0000a845
+
+#define REG_A5XX_SP_POWER_COUNTER_3_LO				0x0000a846
+
+#define REG_A5XX_SP_POWER_COUNTER_3_HI				0x0000a847
+
+#define REG_A5XX_TP_POWER_COUNTER_0_LO				0x0000a848
+
+#define REG_A5XX_TP_POWER_COUNTER_0_HI				0x0000a849
+
+#define REG_A5XX_TP_POWER_COUNTER_1_LO				0x0000a84a
+
+#define REG_A5XX_TP_POWER_COUNTER_1_HI				0x0000a84b
+
+#define REG_A5XX_TP_POWER_COUNTER_2_LO				0x0000a84c
+
+#define REG_A5XX_TP_POWER_COUNTER_2_HI				0x0000a84d
+
+#define REG_A5XX_TP_POWER_COUNTER_3_LO				0x0000a84e
+
+#define REG_A5XX_TP_POWER_COUNTER_3_HI				0x0000a84f
+
+#define REG_A5XX_RB_POWER_COUNTER_0_LO				0x0000a850
+
+#define REG_A5XX_RB_POWER_COUNTER_0_HI				0x0000a851
+
+#define REG_A5XX_RB_POWER_COUNTER_1_LO				0x0000a852
+
+#define REG_A5XX_RB_POWER_COUNTER_1_HI				0x0000a853
+
+#define REG_A5XX_RB_POWER_COUNTER_2_LO				0x0000a854
+
+#define REG_A5XX_RB_POWER_COUNTER_2_HI				0x0000a855
+
+#define REG_A5XX_RB_POWER_COUNTER_3_LO				0x0000a856
+
+#define REG_A5XX_RB_POWER_COUNTER_3_HI				0x0000a857
+
+#define REG_A5XX_CCU_POWER_COUNTER_0_LO				0x0000a858
+
+#define REG_A5XX_CCU_POWER_COUNTER_0_HI				0x0000a859
+
+#define REG_A5XX_CCU_POWER_COUNTER_1_LO				0x0000a85a
+
+#define REG_A5XX_CCU_POWER_COUNTER_1_HI				0x0000a85b
+
+#define REG_A5XX_UCHE_POWER_COUNTER_0_LO			0x0000a85c
+
+#define REG_A5XX_UCHE_POWER_COUNTER_0_HI			0x0000a85d
+
+#define REG_A5XX_UCHE_POWER_COUNTER_1_LO			0x0000a85e
+
+#define REG_A5XX_UCHE_POWER_COUNTER_1_HI			0x0000a85f
+
+#define REG_A5XX_UCHE_POWER_COUNTER_2_LO			0x0000a860
+
+#define REG_A5XX_UCHE_POWER_COUNTER_2_HI			0x0000a861
+
+#define REG_A5XX_UCHE_POWER_COUNTER_3_LO			0x0000a862
+
+#define REG_A5XX_UCHE_POWER_COUNTER_3_HI			0x0000a863
+
+#define REG_A5XX_CP_POWER_COUNTER_0_LO				0x0000a864
+
+#define REG_A5XX_CP_POWER_COUNTER_0_HI				0x0000a865
+
+#define REG_A5XX_CP_POWER_COUNTER_1_LO				0x0000a866
+
+#define REG_A5XX_CP_POWER_COUNTER_1_HI				0x0000a867
+
+#define REG_A5XX_CP_POWER_COUNTER_2_LO				0x0000a868
+
+#define REG_A5XX_CP_POWER_COUNTER_2_HI				0x0000a869
+
+#define REG_A5XX_CP_POWER_COUNTER_3_LO				0x0000a86a
+
+#define REG_A5XX_CP_POWER_COUNTER_3_HI				0x0000a86b
+
+#define REG_A5XX_GPMU_POWER_COUNTER_0_LO			0x0000a86c
+
+#define REG_A5XX_GPMU_POWER_COUNTER_0_HI			0x0000a86d
+
+#define REG_A5XX_GPMU_POWER_COUNTER_1_LO			0x0000a86e
+
+#define REG_A5XX_GPMU_POWER_COUNTER_1_HI			0x0000a86f
+
+#define REG_A5XX_GPMU_POWER_COUNTER_2_LO			0x0000a870
+
+#define REG_A5XX_GPMU_POWER_COUNTER_2_HI			0x0000a871
+
+#define REG_A5XX_GPMU_POWER_COUNTER_3_LO			0x0000a872
+
+#define REG_A5XX_GPMU_POWER_COUNTER_3_HI			0x0000a873
+
+#define REG_A5XX_GPMU_POWER_COUNTER_4_LO			0x0000a874
+
+#define REG_A5XX_GPMU_POWER_COUNTER_4_HI			0x0000a875
+
+#define REG_A5XX_GPMU_POWER_COUNTER_5_LO			0x0000a876
+
+#define REG_A5XX_GPMU_POWER_COUNTER_5_HI			0x0000a877
+
+#define REG_A5XX_GPMU_POWER_COUNTER_ENABLE			0x0000a878
+
+#define REG_A5XX_GPMU_ALWAYS_ON_COUNTER_LO			0x0000a879
+
+#define REG_A5XX_GPMU_ALWAYS_ON_COUNTER_HI			0x0000a87a
+
+#define REG_A5XX_GPMU_ALWAYS_ON_COUNTER_RESET			0x0000a87b
+
+#define REG_A5XX_GPMU_POWER_COUNTER_SELECT_0			0x0000a87c
+
+#define REG_A5XX_GPMU_POWER_COUNTER_SELECT_1			0x0000a87d
+
+#define REG_A5XX_GPMU_CLOCK_THROTTLE_CTRL			0x0000a8a3
+
+#define REG_A5XX_GPMU_THROTTLE_UNMASK_FORCE_CTRL		0x0000a8a8
+
+#define REG_A5XX_GPMU_TEMP_SENSOR_ID				0x0000ac00
+
+#define REG_A5XX_GPMU_TEMP_SENSOR_CONFIG			0x0000ac01
+
+#define REG_A5XX_GPMU_TEMP_VAL					0x0000ac02
+
+#define REG_A5XX_GPMU_DELTA_TEMP_THRESHOLD			0x0000ac03
+
+#define REG_A5XX_GPMU_TEMP_THRESHOLD_INTR_STATUS		0x0000ac05
+
+#define REG_A5XX_GPMU_TEMP_THRESHOLD_INTR_EN_MASK		0x0000ac06
+
+#define REG_A5XX_GPMU_LEAKAGE_TEMP_COEFF_0_1			0x0000ac40
+
+#define REG_A5XX_GPMU_LEAKAGE_TEMP_COEFF_2_3			0x0000ac41
+
+#define REG_A5XX_GPMU_LEAKAGE_VTG_COEFF_0_1			0x0000ac42
+
+#define REG_A5XX_GPMU_LEAKAGE_VTG_COEFF_2_3			0x0000ac43
+
+#define REG_A5XX_GPMU_BASE_LEAKAGE				0x0000ac46
+
+#define REG_A5XX_GPMU_GPMU_VOLTAGE				0x0000ac60
+
+#define REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_STATUS			0x0000ac61
+
+#define REG_A5XX_GPMU_GPMU_VOLTAGE_INTR_EN_MASK			0x0000ac62
+
+#define REG_A5XX_GPMU_GPMU_PWR_THRESHOLD			0x0000ac80
+
+#define REG_A5XX_GPMU_GPMU_LLM_GLM_SLEEP_CTRL			0x0000acc4
+
+#define REG_A5XX_GPMU_GPMU_LLM_GLM_SLEEP_STATUS			0x0000acc5
+
+#define REG_A5XX_GDPM_CONFIG1					0x0000b80c
+
+#define REG_A5XX_GDPM_CONFIG2					0x0000b80d
+
+#define REG_A5XX_GDPM_INT_EN					0x0000b80f
+
+#define REG_A5XX_GDPM_INT_MASK					0x0000b811
+
+#define REG_A5XX_GPMU_BEC_ENABLE				0x0000b9a0
+
+#define REG_A5XX_GPU_CS_SENSOR_GENERAL_STATUS			0x0000c41a
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_0		0x0000c41d
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_2		0x0000c41f
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_STATUS1_4		0x0000c421
+
+#define REG_A5XX_GPU_CS_ENABLE_REG				0x0000c520
+
+#define REG_A5XX_GPU_CS_AMP_CALIBRATION_CONTROL1		0x0000c557
+
+#define REG_A5XX_GRAS_CL_CNTL					0x0000e000
+
+#define REG_A5XX_UNKNOWN_E001					0x0000e001
+
+#define REG_A5XX_UNKNOWN_E004					0x0000e004
+
+#define REG_A5XX_GRAS_CNTL					0x0000e005
+#define A5XX_GRAS_CNTL_VARYING					0x00000001
+
+#define REG_A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ			0x0000e006
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__MASK		0x000003ff
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__SHIFT		0
+static inline uint32_t A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__SHIFT) & A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ__MASK;
+}
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__MASK		0x000ffc00
+#define A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__SHIFT		10
+static inline uint32_t A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__SHIFT) & A5XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_XOFFSET_0			0x0000e010
+#define A5XX_GRAS_CL_VPORT_XOFFSET_0__MASK			0xffffffff
+#define A5XX_GRAS_CL_VPORT_XOFFSET_0__SHIFT			0
+static inline uint32_t A5XX_GRAS_CL_VPORT_XOFFSET_0(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_CL_VPORT_XOFFSET_0__SHIFT) & A5XX_GRAS_CL_VPORT_XOFFSET_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_XSCALE_0				0x0000e011
+#define A5XX_GRAS_CL_VPORT_XSCALE_0__MASK			0xffffffff
+#define A5XX_GRAS_CL_VPORT_XSCALE_0__SHIFT			0
+static inline uint32_t A5XX_GRAS_CL_VPORT_XSCALE_0(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_CL_VPORT_XSCALE_0__SHIFT) & A5XX_GRAS_CL_VPORT_XSCALE_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_YOFFSET_0			0x0000e012
+#define A5XX_GRAS_CL_VPORT_YOFFSET_0__MASK			0xffffffff
+#define A5XX_GRAS_CL_VPORT_YOFFSET_0__SHIFT			0
+static inline uint32_t A5XX_GRAS_CL_VPORT_YOFFSET_0(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_CL_VPORT_YOFFSET_0__SHIFT) & A5XX_GRAS_CL_VPORT_YOFFSET_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_YSCALE_0				0x0000e013
+#define A5XX_GRAS_CL_VPORT_YSCALE_0__MASK			0xffffffff
+#define A5XX_GRAS_CL_VPORT_YSCALE_0__SHIFT			0
+static inline uint32_t A5XX_GRAS_CL_VPORT_YSCALE_0(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_CL_VPORT_YSCALE_0__SHIFT) & A5XX_GRAS_CL_VPORT_YSCALE_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_ZOFFSET_0			0x0000e014
+#define A5XX_GRAS_CL_VPORT_ZOFFSET_0__MASK			0xffffffff
+#define A5XX_GRAS_CL_VPORT_ZOFFSET_0__SHIFT			0
+static inline uint32_t A5XX_GRAS_CL_VPORT_ZOFFSET_0(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_CL_VPORT_ZOFFSET_0__SHIFT) & A5XX_GRAS_CL_VPORT_ZOFFSET_0__MASK;
+}
+
+#define REG_A5XX_GRAS_CL_VPORT_ZSCALE_0				0x0000e015
+#define A5XX_GRAS_CL_VPORT_ZSCALE_0__MASK			0xffffffff
+#define A5XX_GRAS_CL_VPORT_ZSCALE_0__SHIFT			0
+static inline uint32_t A5XX_GRAS_CL_VPORT_ZSCALE_0(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_CL_VPORT_ZSCALE_0__SHIFT) & A5XX_GRAS_CL_VPORT_ZSCALE_0__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_CNTL					0x0000e090
+#define A5XX_GRAS_SU_CNTL_FRONT_CW				0x00000004
+#define A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__MASK			0x000007f8
+#define A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__SHIFT			3
+static inline uint32_t A5XX_GRAS_SU_CNTL_LINEHALFWIDTH(float val)
+{
+	return ((((int32_t)(val * 4.0))) << A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__SHIFT) & A5XX_GRAS_SU_CNTL_LINEHALFWIDTH__MASK;
+}
+#define A5XX_GRAS_SU_CNTL_POLY_OFFSET				0x00000800
+#define A5XX_GRAS_SU_CNTL_MSAA_ENABLE				0x00002000
+
+#define REG_A5XX_GRAS_SU_POINT_MINMAX				0x0000e091
+#define A5XX_GRAS_SU_POINT_MINMAX_MIN__MASK			0x0000ffff
+#define A5XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT			0
+static inline uint32_t A5XX_GRAS_SU_POINT_MINMAX_MIN(float val)
+{
+	return ((((uint32_t)(val * 16.0))) << A5XX_GRAS_SU_POINT_MINMAX_MIN__SHIFT) & A5XX_GRAS_SU_POINT_MINMAX_MIN__MASK;
+}
+#define A5XX_GRAS_SU_POINT_MINMAX_MAX__MASK			0xffff0000
+#define A5XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT			16
+static inline uint32_t A5XX_GRAS_SU_POINT_MINMAX_MAX(float val)
+{
+	return ((((uint32_t)(val * 16.0))) << A5XX_GRAS_SU_POINT_MINMAX_MAX__SHIFT) & A5XX_GRAS_SU_POINT_MINMAX_MAX__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_POINT_SIZE				0x0000e092
+#define A5XX_GRAS_SU_POINT_SIZE__MASK				0xffffffff
+#define A5XX_GRAS_SU_POINT_SIZE__SHIFT				0
+static inline uint32_t A5XX_GRAS_SU_POINT_SIZE(float val)
+{
+	return ((((int32_t)(val * 16.0))) << A5XX_GRAS_SU_POINT_SIZE__SHIFT) & A5XX_GRAS_SU_POINT_SIZE__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E093					0x0000e093
+
+#define REG_A5XX_GRAS_SU_DEPTH_PLANE_CNTL			0x0000e094
+#define A5XX_GRAS_SU_DEPTH_PLANE_CNTL_ALPHA_TEST_ENABLE		0x00000001
+
+#define REG_A5XX_GRAS_SU_POLY_OFFSET_SCALE			0x0000e095
+#define A5XX_GRAS_SU_POLY_OFFSET_SCALE__MASK			0xffffffff
+#define A5XX_GRAS_SU_POLY_OFFSET_SCALE__SHIFT			0
+static inline uint32_t A5XX_GRAS_SU_POLY_OFFSET_SCALE(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_SU_POLY_OFFSET_SCALE__SHIFT) & A5XX_GRAS_SU_POLY_OFFSET_SCALE__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_POLY_OFFSET_OFFSET			0x0000e096
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK			0xffffffff
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT			0
+static inline uint32_t A5XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A5XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP		0x0000e097
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__MASK		0xffffffff
+#define A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__SHIFT		0
+static inline uint32_t A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP(float val)
+{
+	return ((fui(val)) << A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__SHIFT) & A5XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_DEPTH_BUFFER_INFO			0x0000e098
+#define A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK	0x00000007
+#define A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT	0
+static inline uint32_t A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(enum a5xx_depth_format val)
+{
+	return ((val) << A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT) & A5XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK;
+}
+
+#define REG_A5XX_GRAS_SU_CONSERVATIVE_RAS_CNTL			0x0000e099
+
+#define REG_A5XX_GRAS_SC_CNTL					0x0000e0a0
+#define A5XX_GRAS_SC_CNTL_SAMPLES_PASSED			0x00008000
+
+#define REG_A5XX_GRAS_SC_BIN_CNTL				0x0000e0a1
+
+#define REG_A5XX_GRAS_SC_RAS_MSAA_CNTL				0x0000e0a2
+#define A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__MASK		0x00000003
+#define A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__SHIFT		0
+static inline uint32_t A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+	return ((val) << A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_DEST_MSAA_CNTL				0x0000e0a3
+#define A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__MASK		0x00000003
+#define A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__SHIFT		0
+static inline uint32_t A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+	return ((val) << A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES__MASK;
+}
+#define A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE		0x00000004
+
+#define REG_A5XX_GRAS_SC_SCREEN_SCISSOR_CNTL			0x0000e0a4
+
+#define REG_A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0			0x0000e0aa
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_WINDOW_OFFSET_DISABLE	0x80000000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__MASK		0x00007fff
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__SHIFT		0
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X__MASK;
+}
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__MASK		0x7fff0000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__SHIFT		16
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0			0x0000e0ab
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_WINDOW_OFFSET_DISABLE	0x80000000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__MASK		0x00007fff
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__SHIFT		0
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_X__MASK;
+}
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__MASK		0x7fff0000
+#define A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__SHIFT		16
+static inline uint32_t A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__SHIFT) & A5XX_GRAS_SC_SCREEN_SCISSOR_BR_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0			0x0000e0ca
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_WINDOW_OFFSET_DISABLE	0x80000000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__MASK		0x00007fff
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__SHIFT		0
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X__MASK;
+}
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__MASK		0x7fff0000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__SHIFT		16
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0			0x0000e0cb
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_WINDOW_OFFSET_DISABLE	0x80000000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__MASK		0x00007fff
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__SHIFT		0
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_X__MASK;
+}
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__MASK		0x7fff0000
+#define A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__SHIFT		16
+static inline uint32_t A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__SHIFT) & A5XX_GRAS_SC_VIEWPORT_SCISSOR_BR_0_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL			0x0000e0ea
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_WINDOW_OFFSET_DISABLE	0x80000000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK			0x00007fff
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT			0
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X__MASK;
+}
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK			0x7fff0000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT			16
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_SC_WINDOW_SCISSOR_BR			0x0000e0eb
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_WINDOW_OFFSET_DISABLE	0x80000000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK			0x00007fff
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT			0
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X__MASK;
+}
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK			0x7fff0000
+#define A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT			16
+static inline uint32_t A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(uint32_t val)
+{
+	return ((val) << A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__SHIFT) & A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y__MASK;
+}
+
+#define REG_A5XX_GRAS_LRZ_CNTL					0x0000e100
+
+#define REG_A5XX_GRAS_LRZ_BUFFER_BASE_LO			0x0000e101
+
+#define REG_A5XX_GRAS_LRZ_BUFFER_BASE_HI			0x0000e102
+
+#define REG_A5XX_GRAS_LRZ_BUFFER_PITCH				0x0000e103
+
+#define REG_A5XX_GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_LO		0x0000e104
+
+#define REG_A5XX_GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_HI		0x0000e105
+
+#define REG_A5XX_RB_CNTL					0x0000e140
+#define A5XX_RB_CNTL_WIDTH__MASK				0x000000ff
+#define A5XX_RB_CNTL_WIDTH__SHIFT				0
+static inline uint32_t A5XX_RB_CNTL_WIDTH(uint32_t val)
+{
+	return ((val >> 5) << A5XX_RB_CNTL_WIDTH__SHIFT) & A5XX_RB_CNTL_WIDTH__MASK;
+}
+#define A5XX_RB_CNTL_HEIGHT__MASK				0x0001fe00
+#define A5XX_RB_CNTL_HEIGHT__SHIFT				9
+static inline uint32_t A5XX_RB_CNTL_HEIGHT(uint32_t val)
+{
+	return ((val >> 5) << A5XX_RB_CNTL_HEIGHT__SHIFT) & A5XX_RB_CNTL_HEIGHT__MASK;
+}
+#define A5XX_RB_CNTL_BYPASS					0x00020000
+
+#define REG_A5XX_RB_RENDER_CNTL					0x0000e141
+#define A5XX_RB_RENDER_CNTL_SAMPLES_PASSED			0x00000040
+#define A5XX_RB_RENDER_CNTL_FLAG_DEPTH				0x00004000
+#define A5XX_RB_RENDER_CNTL_FLAG_DEPTH2				0x00008000
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS__MASK			0x00ff0000
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS__SHIFT			16
+static inline uint32_t A5XX_RB_RENDER_CNTL_FLAG_MRTS(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_CNTL_FLAG_MRTS__SHIFT) & A5XX_RB_RENDER_CNTL_FLAG_MRTS__MASK;
+}
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS2__MASK			0xff000000
+#define A5XX_RB_RENDER_CNTL_FLAG_MRTS2__SHIFT			24
+static inline uint32_t A5XX_RB_RENDER_CNTL_FLAG_MRTS2(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_CNTL_FLAG_MRTS2__SHIFT) & A5XX_RB_RENDER_CNTL_FLAG_MRTS2__MASK;
+}
+
+#define REG_A5XX_RB_RAS_MSAA_CNTL				0x0000e142
+#define A5XX_RB_RAS_MSAA_CNTL_SAMPLES__MASK			0x00000003
+#define A5XX_RB_RAS_MSAA_CNTL_SAMPLES__SHIFT			0
+static inline uint32_t A5XX_RB_RAS_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+	return ((val) << A5XX_RB_RAS_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_RB_RAS_MSAA_CNTL_SAMPLES__MASK;
+}
+
+#define REG_A5XX_RB_DEST_MSAA_CNTL				0x0000e143
+#define A5XX_RB_DEST_MSAA_CNTL_SAMPLES__MASK			0x00000003
+#define A5XX_RB_DEST_MSAA_CNTL_SAMPLES__SHIFT			0
+static inline uint32_t A5XX_RB_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+	return ((val) << A5XX_RB_DEST_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_RB_DEST_MSAA_CNTL_SAMPLES__MASK;
+}
+#define A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE			0x00000004
+
+#define REG_A5XX_RB_RENDER_CONTROL0				0x0000e144
+#define A5XX_RB_RENDER_CONTROL0_VARYING				0x00000001
+#define A5XX_RB_RENDER_CONTROL0_XCOORD				0x00000040
+#define A5XX_RB_RENDER_CONTROL0_YCOORD				0x00000080
+#define A5XX_RB_RENDER_CONTROL0_ZCOORD				0x00000100
+#define A5XX_RB_RENDER_CONTROL0_WCOORD				0x00000200
+
+#define REG_A5XX_RB_RENDER_CONTROL1				0x0000e145
+#define A5XX_RB_RENDER_CONTROL1_FACENESS			0x00000002
+
+#define REG_A5XX_RB_FS_OUTPUT_CNTL				0x0000e146
+#define A5XX_RB_FS_OUTPUT_CNTL_MRT__MASK			0x0000000f
+#define A5XX_RB_FS_OUTPUT_CNTL_MRT__SHIFT			0
+static inline uint32_t A5XX_RB_FS_OUTPUT_CNTL_MRT(uint32_t val)
+{
+	return ((val) << A5XX_RB_FS_OUTPUT_CNTL_MRT__SHIFT) & A5XX_RB_FS_OUTPUT_CNTL_MRT__MASK;
+}
+#define A5XX_RB_FS_OUTPUT_CNTL_FRAG_WRITES_Z			0x00000020
+
+#define REG_A5XX_RB_RENDER_COMPONENTS				0x0000e147
+#define A5XX_RB_RENDER_COMPONENTS_RT0__MASK			0x0000000f
+#define A5XX_RB_RENDER_COMPONENTS_RT0__SHIFT			0
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT0(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT0__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT0__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT1__MASK			0x000000f0
+#define A5XX_RB_RENDER_COMPONENTS_RT1__SHIFT			4
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT1(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT1__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT1__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT2__MASK			0x00000f00
+#define A5XX_RB_RENDER_COMPONENTS_RT2__SHIFT			8
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT2(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT2__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT2__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT3__MASK			0x0000f000
+#define A5XX_RB_RENDER_COMPONENTS_RT3__SHIFT			12
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT3(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT3__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT3__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT4__MASK			0x000f0000
+#define A5XX_RB_RENDER_COMPONENTS_RT4__SHIFT			16
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT4(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT4__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT4__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT5__MASK			0x00f00000
+#define A5XX_RB_RENDER_COMPONENTS_RT5__SHIFT			20
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT5(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT5__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT5__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT6__MASK			0x0f000000
+#define A5XX_RB_RENDER_COMPONENTS_RT6__SHIFT			24
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT6(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT6__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT6__MASK;
+}
+#define A5XX_RB_RENDER_COMPONENTS_RT7__MASK			0xf0000000
+#define A5XX_RB_RENDER_COMPONENTS_RT7__SHIFT			28
+static inline uint32_t A5XX_RB_RENDER_COMPONENTS_RT7(uint32_t val)
+{
+	return ((val) << A5XX_RB_RENDER_COMPONENTS_RT7__SHIFT) & A5XX_RB_RENDER_COMPONENTS_RT7__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT(uint32_t i0) { return 0x0000e150 + 0x7*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_CONTROL(uint32_t i0) { return 0x0000e150 + 0x7*i0; }
+#define A5XX_RB_MRT_CONTROL_BLEND				0x00000001
+#define A5XX_RB_MRT_CONTROL_BLEND2				0x00000002
+#define A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK		0x00000780
+#define A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT		7
+static inline uint32_t A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE(uint32_t val)
+{
+	return ((val) << A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__SHIFT) & A5XX_RB_MRT_CONTROL_COMPONENT_ENABLE__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_BLEND_CONTROL(uint32_t i0) { return 0x0000e151 + 0x7*i0; }
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK		0x0000001f
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT		0
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR(enum adreno_rb_blend_factor val)
+{
+	return ((val) << A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_RGB_SRC_FACTOR__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK	0x000000e0
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT	5
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
+{
+	return ((val) << A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_RGB_BLEND_OPCODE__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK		0x00001f00
+#define A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT	8
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR(enum adreno_rb_blend_factor val)
+{
+	return ((val) << A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_RGB_DEST_FACTOR__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK	0x001f0000
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT	16
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR(enum adreno_rb_blend_factor val)
+{
+	return ((val) << A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_ALPHA_SRC_FACTOR__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK	0x00e00000
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT	21
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE(enum a3xx_rb_blend_opcode val)
+{
+	return ((val) << A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_ALPHA_BLEND_OPCODE__MASK;
+}
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK	0x1f000000
+#define A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT	24
+static inline uint32_t A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR(enum adreno_rb_blend_factor val)
+{
+	return ((val) << A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__SHIFT) & A5XX_RB_MRT_BLEND_CONTROL_ALPHA_DEST_FACTOR__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_BUF_INFO(uint32_t i0) { return 0x0000e152 + 0x7*i0; }
+#define A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK			0x000000ff
+#define A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT		0
+static inline uint32_t A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+	return ((val) << A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT) & A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK		0x00000300
+#define A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT		8
+static inline uint32_t A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(enum a5xx_tile_mode val)
+{
+	return ((val) << A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT) & A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK;
+}
+#define A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK			0x00006000
+#define A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT			13
+static inline uint32_t A5XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A5XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
+}
+#define A5XX_RB_MRT_BUF_INFO_COLOR_SRGB				0x00008000
+
+static inline uint32_t REG_A5XX_RB_MRT_PITCH(uint32_t i0) { return 0x0000e153 + 0x7*i0; }
+#define A5XX_RB_MRT_PITCH__MASK					0xffffffff
+#define A5XX_RB_MRT_PITCH__SHIFT				0
+static inline uint32_t A5XX_RB_MRT_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_MRT_PITCH__SHIFT) & A5XX_RB_MRT_PITCH__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_ARRAY_PITCH(uint32_t i0) { return 0x0000e154 + 0x7*i0; }
+#define A5XX_RB_MRT_ARRAY_PITCH__MASK				0xffffffff
+#define A5XX_RB_MRT_ARRAY_PITCH__SHIFT				0
+static inline uint32_t A5XX_RB_MRT_ARRAY_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_MRT_ARRAY_PITCH__SHIFT) & A5XX_RB_MRT_ARRAY_PITCH__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_BASE_LO(uint32_t i0) { return 0x0000e155 + 0x7*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_BASE_HI(uint32_t i0) { return 0x0000e156 + 0x7*i0; }
+
+#define REG_A5XX_RB_BLEND_RED					0x0000e1a0
+#define A5XX_RB_BLEND_RED_UINT__MASK				0x000000ff
+#define A5XX_RB_BLEND_RED_UINT__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_RED_UINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_RED_UINT__SHIFT) & A5XX_RB_BLEND_RED_UINT__MASK;
+}
+#define A5XX_RB_BLEND_RED_SINT__MASK				0x0000ff00
+#define A5XX_RB_BLEND_RED_SINT__SHIFT				8
+static inline uint32_t A5XX_RB_BLEND_RED_SINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_RED_SINT__SHIFT) & A5XX_RB_BLEND_RED_SINT__MASK;
+}
+#define A5XX_RB_BLEND_RED_FLOAT__MASK				0xffff0000
+#define A5XX_RB_BLEND_RED_FLOAT__SHIFT				16
+static inline uint32_t A5XX_RB_BLEND_RED_FLOAT(float val)
+{
+	return ((util_float_to_half(val)) << A5XX_RB_BLEND_RED_FLOAT__SHIFT) & A5XX_RB_BLEND_RED_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_RED_F32				0x0000e1a1
+#define A5XX_RB_BLEND_RED_F32__MASK				0xffffffff
+#define A5XX_RB_BLEND_RED_F32__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_RED_F32(float val)
+{
+	return ((fui(val)) << A5XX_RB_BLEND_RED_F32__SHIFT) & A5XX_RB_BLEND_RED_F32__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_GREEN					0x0000e1a2
+#define A5XX_RB_BLEND_GREEN_UINT__MASK				0x000000ff
+#define A5XX_RB_BLEND_GREEN_UINT__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_GREEN_UINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_GREEN_UINT__SHIFT) & A5XX_RB_BLEND_GREEN_UINT__MASK;
+}
+#define A5XX_RB_BLEND_GREEN_SINT__MASK				0x0000ff00
+#define A5XX_RB_BLEND_GREEN_SINT__SHIFT				8
+static inline uint32_t A5XX_RB_BLEND_GREEN_SINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_GREEN_SINT__SHIFT) & A5XX_RB_BLEND_GREEN_SINT__MASK;
+}
+#define A5XX_RB_BLEND_GREEN_FLOAT__MASK				0xffff0000
+#define A5XX_RB_BLEND_GREEN_FLOAT__SHIFT			16
+static inline uint32_t A5XX_RB_BLEND_GREEN_FLOAT(float val)
+{
+	return ((util_float_to_half(val)) << A5XX_RB_BLEND_GREEN_FLOAT__SHIFT) & A5XX_RB_BLEND_GREEN_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_GREEN_F32				0x0000e1a3
+#define A5XX_RB_BLEND_GREEN_F32__MASK				0xffffffff
+#define A5XX_RB_BLEND_GREEN_F32__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_GREEN_F32(float val)
+{
+	return ((fui(val)) << A5XX_RB_BLEND_GREEN_F32__SHIFT) & A5XX_RB_BLEND_GREEN_F32__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_BLUE					0x0000e1a4
+#define A5XX_RB_BLEND_BLUE_UINT__MASK				0x000000ff
+#define A5XX_RB_BLEND_BLUE_UINT__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_BLUE_UINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_BLUE_UINT__SHIFT) & A5XX_RB_BLEND_BLUE_UINT__MASK;
+}
+#define A5XX_RB_BLEND_BLUE_SINT__MASK				0x0000ff00
+#define A5XX_RB_BLEND_BLUE_SINT__SHIFT				8
+static inline uint32_t A5XX_RB_BLEND_BLUE_SINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_BLUE_SINT__SHIFT) & A5XX_RB_BLEND_BLUE_SINT__MASK;
+}
+#define A5XX_RB_BLEND_BLUE_FLOAT__MASK				0xffff0000
+#define A5XX_RB_BLEND_BLUE_FLOAT__SHIFT				16
+static inline uint32_t A5XX_RB_BLEND_BLUE_FLOAT(float val)
+{
+	return ((util_float_to_half(val)) << A5XX_RB_BLEND_BLUE_FLOAT__SHIFT) & A5XX_RB_BLEND_BLUE_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_BLUE_F32				0x0000e1a5
+#define A5XX_RB_BLEND_BLUE_F32__MASK				0xffffffff
+#define A5XX_RB_BLEND_BLUE_F32__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_BLUE_F32(float val)
+{
+	return ((fui(val)) << A5XX_RB_BLEND_BLUE_F32__SHIFT) & A5XX_RB_BLEND_BLUE_F32__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_ALPHA					0x0000e1a6
+#define A5XX_RB_BLEND_ALPHA_UINT__MASK				0x000000ff
+#define A5XX_RB_BLEND_ALPHA_UINT__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_ALPHA_UINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_ALPHA_UINT__SHIFT) & A5XX_RB_BLEND_ALPHA_UINT__MASK;
+}
+#define A5XX_RB_BLEND_ALPHA_SINT__MASK				0x0000ff00
+#define A5XX_RB_BLEND_ALPHA_SINT__SHIFT				8
+static inline uint32_t A5XX_RB_BLEND_ALPHA_SINT(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_ALPHA_SINT__SHIFT) & A5XX_RB_BLEND_ALPHA_SINT__MASK;
+}
+#define A5XX_RB_BLEND_ALPHA_FLOAT__MASK				0xffff0000
+#define A5XX_RB_BLEND_ALPHA_FLOAT__SHIFT			16
+static inline uint32_t A5XX_RB_BLEND_ALPHA_FLOAT(float val)
+{
+	return ((util_float_to_half(val)) << A5XX_RB_BLEND_ALPHA_FLOAT__SHIFT) & A5XX_RB_BLEND_ALPHA_FLOAT__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_ALPHA_F32				0x0000e1a7
+#define A5XX_RB_BLEND_ALPHA_F32__MASK				0xffffffff
+#define A5XX_RB_BLEND_ALPHA_F32__SHIFT				0
+static inline uint32_t A5XX_RB_BLEND_ALPHA_F32(float val)
+{
+	return ((fui(val)) << A5XX_RB_BLEND_ALPHA_F32__SHIFT) & A5XX_RB_BLEND_ALPHA_F32__MASK;
+}
+
+#define REG_A5XX_RB_ALPHA_CONTROL				0x0000e1a8
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK			0x000000ff
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT			0
+static inline uint32_t A5XX_RB_ALPHA_CONTROL_ALPHA_REF(uint32_t val)
+{
+	return ((val) << A5XX_RB_ALPHA_CONTROL_ALPHA_REF__SHIFT) & A5XX_RB_ALPHA_CONTROL_ALPHA_REF__MASK;
+}
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_TEST			0x00000100
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK		0x00000e00
+#define A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT		9
+static inline uint32_t A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare_func val)
+{
+	return ((val) << A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__SHIFT) & A5XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC__MASK;
+}
+
+#define REG_A5XX_RB_BLEND_CNTL					0x0000e1a9
+#define A5XX_RB_BLEND_CNTL_ENABLE_BLEND__MASK			0x000000ff
+#define A5XX_RB_BLEND_CNTL_ENABLE_BLEND__SHIFT			0
+static inline uint32_t A5XX_RB_BLEND_CNTL_ENABLE_BLEND(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_CNTL_ENABLE_BLEND__SHIFT) & A5XX_RB_BLEND_CNTL_ENABLE_BLEND__MASK;
+}
+#define A5XX_RB_BLEND_CNTL_INDEPENDENT_BLEND			0x00000100
+#define A5XX_RB_BLEND_CNTL_SAMPLE_MASK__MASK			0xffff0000
+#define A5XX_RB_BLEND_CNTL_SAMPLE_MASK__SHIFT			16
+static inline uint32_t A5XX_RB_BLEND_CNTL_SAMPLE_MASK(uint32_t val)
+{
+	return ((val) << A5XX_RB_BLEND_CNTL_SAMPLE_MASK__SHIFT) & A5XX_RB_BLEND_CNTL_SAMPLE_MASK__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_PLANE_CNTL				0x0000e1b0
+#define A5XX_RB_DEPTH_PLANE_CNTL_FRAG_WRITES_Z			0x00000001
+
+#define REG_A5XX_RB_DEPTH_CNTL					0x0000e1b1
+#define A5XX_RB_DEPTH_CNTL_Z_ENABLE				0x00000001
+#define A5XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE			0x00000002
+#define A5XX_RB_DEPTH_CNTL_ZFUNC__MASK				0x0000001c
+#define A5XX_RB_DEPTH_CNTL_ZFUNC__SHIFT				2
+static inline uint32_t A5XX_RB_DEPTH_CNTL_ZFUNC(enum adreno_compare_func val)
+{
+	return ((val) << A5XX_RB_DEPTH_CNTL_ZFUNC__SHIFT) & A5XX_RB_DEPTH_CNTL_ZFUNC__MASK;
+}
+#define A5XX_RB_DEPTH_CNTL_Z_TEST_ENABLE			0x00000040
+
+#define REG_A5XX_RB_DEPTH_BUFFER_INFO				0x0000e1b2
+#define A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK		0x00000007
+#define A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT		0
+static inline uint32_t A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT(enum a5xx_depth_format val)
+{
+	return ((val) << A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__SHIFT) & A5XX_RB_DEPTH_BUFFER_INFO_DEPTH_FORMAT__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_BUFFER_BASE_LO			0x0000e1b3
+
+#define REG_A5XX_RB_DEPTH_BUFFER_BASE_HI			0x0000e1b4
+
+#define REG_A5XX_RB_DEPTH_BUFFER_PITCH				0x0000e1b5
+#define A5XX_RB_DEPTH_BUFFER_PITCH__MASK			0xffffffff
+#define A5XX_RB_DEPTH_BUFFER_PITCH__SHIFT			0
+static inline uint32_t A5XX_RB_DEPTH_BUFFER_PITCH(uint32_t val)
+{
+	return ((val >> 5) << A5XX_RB_DEPTH_BUFFER_PITCH__SHIFT) & A5XX_RB_DEPTH_BUFFER_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH			0x0000e1b6
+#define A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__MASK			0xffffffff
+#define A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__SHIFT			0
+static inline uint32_t A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH(uint32_t val)
+{
+	return ((val >> 5) << A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__SHIFT) & A5XX_RB_DEPTH_BUFFER_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_STENCIL_CONTROL				0x0000e1c0
+#define A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE			0x00000001
+#define A5XX_RB_STENCIL_CONTROL_STENCIL_ENABLE_BF		0x00000002
+#define A5XX_RB_STENCIL_CONTROL_STENCIL_READ			0x00000004
+#define A5XX_RB_STENCIL_CONTROL_FUNC__MASK			0x00000700
+#define A5XX_RB_STENCIL_CONTROL_FUNC__SHIFT			8
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FUNC(enum adreno_compare_func val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_FUNC__SHIFT) & A5XX_RB_STENCIL_CONTROL_FUNC__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_FAIL__MASK			0x00003800
+#define A5XX_RB_STENCIL_CONTROL_FAIL__SHIFT			11
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FAIL(enum adreno_stencil_op val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_FAIL__SHIFT) & A5XX_RB_STENCIL_CONTROL_FAIL__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZPASS__MASK			0x0001c000
+#define A5XX_RB_STENCIL_CONTROL_ZPASS__SHIFT			14
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZPASS(enum adreno_stencil_op val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_ZPASS__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZPASS__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL__MASK			0x000e0000
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT			17
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZFAIL(enum adreno_stencil_op val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_ZFAIL__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZFAIL__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_FUNC_BF__MASK			0x00700000
+#define A5XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT			20
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FUNC_BF(enum adreno_compare_func val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_FUNC_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_FUNC_BF__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_FAIL_BF__MASK			0x03800000
+#define A5XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT			23
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_FAIL_BF(enum adreno_stencil_op val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_FAIL_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_FAIL_BF__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK			0x1c000000
+#define A5XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT			26
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZPASS_BF(enum adreno_stencil_op val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_ZPASS_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZPASS_BF__MASK;
+}
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK			0xe0000000
+#define A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT			29
+static inline uint32_t A5XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op val)
+{
+	return ((val) << A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__SHIFT) & A5XX_RB_STENCIL_CONTROL_ZFAIL_BF__MASK;
+}
+
+#define REG_A5XX_RB_STENCIL_INFO				0x0000e1c1
+#define A5XX_RB_STENCIL_INFO_SEPARATE_STENCIL			0x00000001
+
+#define REG_A5XX_RB_STENCIL_BASE_LO				0x0000e1c2
+
+#define REG_A5XX_RB_STENCIL_BASE_HI				0x0000e1c3
+
+#define REG_A5XX_RB_STENCIL_PITCH				0x0000e1c4
+#define A5XX_RB_STENCIL_PITCH__MASK				0xffffffff
+#define A5XX_RB_STENCIL_PITCH__SHIFT				0
+static inline uint32_t A5XX_RB_STENCIL_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_STENCIL_PITCH__SHIFT) & A5XX_RB_STENCIL_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_STENCIL_ARRAY_PITCH				0x0000e1c5
+#define A5XX_RB_STENCIL_ARRAY_PITCH__MASK			0xffffffff
+#define A5XX_RB_STENCIL_ARRAY_PITCH__SHIFT			0
+static inline uint32_t A5XX_RB_STENCIL_ARRAY_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_STENCIL_ARRAY_PITCH__SHIFT) & A5XX_RB_STENCIL_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_STENCILREFMASK				0x0000e1c6
+#define A5XX_RB_STENCILREFMASK_STENCILREF__MASK			0x000000ff
+#define A5XX_RB_STENCILREFMASK_STENCILREF__SHIFT		0
+static inline uint32_t A5XX_RB_STENCILREFMASK_STENCILREF(uint32_t val)
+{
+	return ((val) << A5XX_RB_STENCILREFMASK_STENCILREF__SHIFT) & A5XX_RB_STENCILREFMASK_STENCILREF__MASK;
+}
+#define A5XX_RB_STENCILREFMASK_STENCILMASK__MASK		0x0000ff00
+#define A5XX_RB_STENCILREFMASK_STENCILMASK__SHIFT		8
+static inline uint32_t A5XX_RB_STENCILREFMASK_STENCILMASK(uint32_t val)
+{
+	return ((val) << A5XX_RB_STENCILREFMASK_STENCILMASK__SHIFT) & A5XX_RB_STENCILREFMASK_STENCILMASK__MASK;
+}
+#define A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK		0x00ff0000
+#define A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT		16
+static inline uint32_t A5XX_RB_STENCILREFMASK_STENCILWRITEMASK(uint32_t val)
+{
+	return ((val) << A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__SHIFT) & A5XX_RB_STENCILREFMASK_STENCILWRITEMASK__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E1C7					0x0000e1c7
+
+#define REG_A5XX_RB_WINDOW_OFFSET				0x0000e1d0
+#define A5XX_RB_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE		0x80000000
+#define A5XX_RB_WINDOW_OFFSET_X__MASK				0x00007fff
+#define A5XX_RB_WINDOW_OFFSET_X__SHIFT				0
+static inline uint32_t A5XX_RB_WINDOW_OFFSET_X(uint32_t val)
+{
+	return ((val) << A5XX_RB_WINDOW_OFFSET_X__SHIFT) & A5XX_RB_WINDOW_OFFSET_X__MASK;
+}
+#define A5XX_RB_WINDOW_OFFSET_Y__MASK				0x7fff0000
+#define A5XX_RB_WINDOW_OFFSET_Y__SHIFT				16
+static inline uint32_t A5XX_RB_WINDOW_OFFSET_Y(uint32_t val)
+{
+	return ((val) << A5XX_RB_WINDOW_OFFSET_Y__SHIFT) & A5XX_RB_WINDOW_OFFSET_Y__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_CNTL					0x0000e210
+#define A5XX_RB_BLIT_CNTL_BUF__MASK				0x0000003f
+#define A5XX_RB_BLIT_CNTL_BUF__SHIFT				0
+static inline uint32_t A5XX_RB_BLIT_CNTL_BUF(enum a5xx_blit_buf val)
+{
+	return ((val) << A5XX_RB_BLIT_CNTL_BUF__SHIFT) & A5XX_RB_BLIT_CNTL_BUF__MASK;
+}
+
+#define REG_A5XX_RB_RESOLVE_CNTL_1				0x0000e211
+#define A5XX_RB_RESOLVE_CNTL_1_WINDOW_OFFSET_DISABLE		0x80000000
+#define A5XX_RB_RESOLVE_CNTL_1_X__MASK				0x00007fff
+#define A5XX_RB_RESOLVE_CNTL_1_X__SHIFT				0
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_1_X(uint32_t val)
+{
+	return ((val) << A5XX_RB_RESOLVE_CNTL_1_X__SHIFT) & A5XX_RB_RESOLVE_CNTL_1_X__MASK;
+}
+#define A5XX_RB_RESOLVE_CNTL_1_Y__MASK				0x7fff0000
+#define A5XX_RB_RESOLVE_CNTL_1_Y__SHIFT				16
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_1_Y(uint32_t val)
+{
+	return ((val) << A5XX_RB_RESOLVE_CNTL_1_Y__SHIFT) & A5XX_RB_RESOLVE_CNTL_1_Y__MASK;
+}
+
+#define REG_A5XX_RB_RESOLVE_CNTL_2				0x0000e212
+#define A5XX_RB_RESOLVE_CNTL_2_WINDOW_OFFSET_DISABLE		0x80000000
+#define A5XX_RB_RESOLVE_CNTL_2_X__MASK				0x00007fff
+#define A5XX_RB_RESOLVE_CNTL_2_X__SHIFT				0
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_2_X(uint32_t val)
+{
+	return ((val) << A5XX_RB_RESOLVE_CNTL_2_X__SHIFT) & A5XX_RB_RESOLVE_CNTL_2_X__MASK;
+}
+#define A5XX_RB_RESOLVE_CNTL_2_Y__MASK				0x7fff0000
+#define A5XX_RB_RESOLVE_CNTL_2_Y__SHIFT				16
+static inline uint32_t A5XX_RB_RESOLVE_CNTL_2_Y(uint32_t val)
+{
+	return ((val) << A5XX_RB_RESOLVE_CNTL_2_Y__SHIFT) & A5XX_RB_RESOLVE_CNTL_2_Y__MASK;
+}
+
+#define REG_A5XX_RB_RESOLVE_CNTL_3				0x0000e213
+
+#define REG_A5XX_RB_BLIT_DST_LO					0x0000e214
+
+#define REG_A5XX_RB_BLIT_DST_HI					0x0000e215
+
+#define REG_A5XX_RB_BLIT_DST_PITCH				0x0000e216
+#define A5XX_RB_BLIT_DST_PITCH__MASK				0xffffffff
+#define A5XX_RB_BLIT_DST_PITCH__SHIFT				0
+static inline uint32_t A5XX_RB_BLIT_DST_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_BLIT_DST_PITCH__SHIFT) & A5XX_RB_BLIT_DST_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_DST_ARRAY_PITCH			0x0000e217
+#define A5XX_RB_BLIT_DST_ARRAY_PITCH__MASK			0xffffffff
+#define A5XX_RB_BLIT_DST_ARRAY_PITCH__SHIFT			0
+static inline uint32_t A5XX_RB_BLIT_DST_ARRAY_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_BLIT_DST_ARRAY_PITCH__SHIFT) & A5XX_RB_BLIT_DST_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW0				0x0000e218
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW1				0x0000e219
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW2				0x0000e21a
+
+#define REG_A5XX_RB_CLEAR_COLOR_DW3				0x0000e21b
+
+#define REG_A5XX_RB_CLEAR_CNTL					0x0000e21c
+#define A5XX_RB_CLEAR_CNTL_FAST_CLEAR				0x00000002
+#define A5XX_RB_CLEAR_CNTL_MASK__MASK				0x000000f0
+#define A5XX_RB_CLEAR_CNTL_MASK__SHIFT				4
+static inline uint32_t A5XX_RB_CLEAR_CNTL_MASK(uint32_t val)
+{
+	return ((val) << A5XX_RB_CLEAR_CNTL_MASK__SHIFT) & A5XX_RB_CLEAR_CNTL_MASK__MASK;
+}
+
+#define REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_LO			0x0000e240
+
+#define REG_A5XX_RB_DEPTH_FLAG_BUFFER_BASE_HI			0x0000e241
+
+#define REG_A5XX_RB_DEPTH_FLAG_BUFFER_PITCH			0x0000e242
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER(uint32_t i0) { return 0x0000e243 + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_ADDR_LO(uint32_t i0) { return 0x0000e243 + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_ADDR_HI(uint32_t i0) { return 0x0000e244 + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_PITCH(uint32_t i0) { return 0x0000e245 + 0x4*i0; }
+#define A5XX_RB_MRT_FLAG_BUFFER_PITCH__MASK			0xffffffff
+#define A5XX_RB_MRT_FLAG_BUFFER_PITCH__SHIFT			0
+static inline uint32_t A5XX_RB_MRT_FLAG_BUFFER_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_MRT_FLAG_BUFFER_PITCH__SHIFT) & A5XX_RB_MRT_FLAG_BUFFER_PITCH__MASK;
+}
+
+static inline uint32_t REG_A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(uint32_t i0) { return 0x0000e246 + 0x4*i0; }
+#define A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__MASK		0xffffffff
+#define A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__SHIFT		0
+static inline uint32_t A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__SHIFT) & A5XX_RB_MRT_FLAG_BUFFER_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_LO				0x0000e263
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_HI				0x0000e264
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_PITCH				0x0000e265
+#define A5XX_RB_BLIT_FLAG_DST_PITCH__MASK			0xffffffff
+#define A5XX_RB_BLIT_FLAG_DST_PITCH__SHIFT			0
+static inline uint32_t A5XX_RB_BLIT_FLAG_DST_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_BLIT_FLAG_DST_PITCH__SHIFT) & A5XX_RB_BLIT_FLAG_DST_PITCH__MASK;
+}
+
+#define REG_A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH			0x0000e266
+#define A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__MASK			0xffffffff
+#define A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__SHIFT		0
+static inline uint32_t A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH(uint32_t val)
+{
+	return ((val >> 6) << A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__SHIFT) & A5XX_RB_BLIT_FLAG_DST_ARRAY_PITCH__MASK;
+}
+
+#define REG_A5XX_VPC_CNTL_0					0x0000e280
+#define A5XX_VPC_CNTL_0_STRIDE_IN_VPC__MASK			0x0000007f
+#define A5XX_VPC_CNTL_0_STRIDE_IN_VPC__SHIFT			0
+static inline uint32_t A5XX_VPC_CNTL_0_STRIDE_IN_VPC(uint32_t val)
+{
+	return ((val) << A5XX_VPC_CNTL_0_STRIDE_IN_VPC__SHIFT) & A5XX_VPC_CNTL_0_STRIDE_IN_VPC__MASK;
+}
+#define A5XX_VPC_CNTL_0_VARYING					0x00000800
+
+static inline uint32_t REG_A5XX_VPC_VARYING_INTERP(uint32_t i0) { return 0x0000e282 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VARYING_INTERP_MODE(uint32_t i0) { return 0x0000e282 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VARYING_PS_REPL(uint32_t i0) { return 0x0000e28a + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0x0000e28a + 0x1*i0; }
+
+#define REG_A5XX_UNKNOWN_E292					0x0000e292
+
+#define REG_A5XX_UNKNOWN_E293					0x0000e293
+
+static inline uint32_t REG_A5XX_VPC_VAR(uint32_t i0) { return 0x0000e294 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VPC_VAR_DISABLE(uint32_t i0) { return 0x0000e294 + 0x1*i0; }
+
+#define REG_A5XX_VPC_GS_SIV_CNTL				0x0000e298
+
+#define REG_A5XX_UNKNOWN_E29A					0x0000e29a
+
+#define REG_A5XX_VPC_PACK					0x0000e29d
+#define A5XX_VPC_PACK_NUMNONPOSVAR__MASK			0x000000ff
+#define A5XX_VPC_PACK_NUMNONPOSVAR__SHIFT			0
+static inline uint32_t A5XX_VPC_PACK_NUMNONPOSVAR(uint32_t val)
+{
+	return ((val) << A5XX_VPC_PACK_NUMNONPOSVAR__SHIFT) & A5XX_VPC_PACK_NUMNONPOSVAR__MASK;
+}
+
+#define REG_A5XX_VPC_FS_PRIMITIVEID_CNTL			0x0000e2a0
+
+#define REG_A5XX_UNKNOWN_E2A1					0x0000e2a1
+
+#define REG_A5XX_VPC_SO_OVERRIDE				0x0000e2a2
+
+#define REG_A5XX_VPC_SO_BUFFER_BASE_LO_0			0x0000e2a7
+
+#define REG_A5XX_VPC_SO_BUFFER_BASE_HI_0			0x0000e2a8
+
+#define REG_A5XX_VPC_SO_BUFFER_SIZE_0				0x0000e2a9
+
+#define REG_A5XX_UNKNOWN_E2AB					0x0000e2ab
+
+#define REG_A5XX_VPC_SO_FLUSH_BASE_LO_0				0x0000e2ac
+
+#define REG_A5XX_VPC_SO_FLUSH_BASE_HI_0				0x0000e2ad
+
+#define REG_A5XX_UNKNOWN_E2AE					0x0000e2ae
+
+#define REG_A5XX_UNKNOWN_E2B2					0x0000e2b2
+
+#define REG_A5XX_UNKNOWN_E2B9					0x0000e2b9
+
+#define REG_A5XX_UNKNOWN_E2C0					0x0000e2c0
+
+#define REG_A5XX_PC_PRIMITIVE_CNTL				0x0000e384
+#define A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK		0x0000007f
+#define A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT		0
+static inline uint32_t A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC(uint32_t val)
+{
+	return ((val) << A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT) & A5XX_PC_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK;
+}
+
+#define REG_A5XX_PC_PRIM_VTX_CNTL				0x0000e385
+#define A5XX_PC_PRIM_VTX_CNTL_PSIZE				0x00000800
+
+#define REG_A5XX_PC_RASTER_CNTL					0x0000e388
+
+#define REG_A5XX_UNKNOWN_E389					0x0000e389
+
+#define REG_A5XX_PC_RESTART_INDEX				0x0000e38c
+
+#define REG_A5XX_UNKNOWN_E38D					0x0000e38d
+
+#define REG_A5XX_PC_GS_PARAM					0x0000e38e
+
+#define REG_A5XX_PC_HS_PARAM					0x0000e38f
+
+#define REG_A5XX_PC_POWER_CNTL					0x0000e3b0
+
+#define REG_A5XX_VFD_CONTROL_0					0x0000e400
+#define A5XX_VFD_CONTROL_0_VTXCNT__MASK				0x0000003f
+#define A5XX_VFD_CONTROL_0_VTXCNT__SHIFT			0
+static inline uint32_t A5XX_VFD_CONTROL_0_VTXCNT(uint32_t val)
+{
+	return ((val) << A5XX_VFD_CONTROL_0_VTXCNT__SHIFT) & A5XX_VFD_CONTROL_0_VTXCNT__MASK;
+}
+
+#define REG_A5XX_VFD_CONTROL_1					0x0000e401
+#define A5XX_VFD_CONTROL_1_REGID4INST__MASK			0x0000ff00
+#define A5XX_VFD_CONTROL_1_REGID4INST__SHIFT			8
+static inline uint32_t A5XX_VFD_CONTROL_1_REGID4INST(uint32_t val)
+{
+	return ((val) << A5XX_VFD_CONTROL_1_REGID4INST__SHIFT) & A5XX_VFD_CONTROL_1_REGID4INST__MASK;
+}
+#define A5XX_VFD_CONTROL_1_REGID4VTX__MASK			0x00ff0000
+#define A5XX_VFD_CONTROL_1_REGID4VTX__SHIFT			16
+static inline uint32_t A5XX_VFD_CONTROL_1_REGID4VTX(uint32_t val)
+{
+	return ((val) << A5XX_VFD_CONTROL_1_REGID4VTX__SHIFT) & A5XX_VFD_CONTROL_1_REGID4VTX__MASK;
+}
+
+#define REG_A5XX_VFD_CONTROL_2					0x0000e402
+
+#define REG_A5XX_VFD_CONTROL_3					0x0000e403
+
+#define REG_A5XX_VFD_CONTROL_4					0x0000e404
+
+#define REG_A5XX_VFD_CONTROL_5					0x0000e405
+
+#define REG_A5XX_VFD_INDEX_OFFSET				0x0000e408
+
+#define REG_A5XX_VFD_INSTANCE_START_OFFSET			0x0000e409
+
+static inline uint32_t REG_A5XX_VFD_FETCH(uint32_t i0) { return 0x0000e40a + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_BASE_LO(uint32_t i0) { return 0x0000e40a + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_BASE_HI(uint32_t i0) { return 0x0000e40b + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_SIZE(uint32_t i0) { return 0x0000e40c + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_FETCH_STRIDE(uint32_t i0) { return 0x0000e40d + 0x4*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DECODE(uint32_t i0) { return 0x0000e48a + 0x2*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DECODE_INSTR(uint32_t i0) { return 0x0000e48a + 0x2*i0; }
+#define A5XX_VFD_DECODE_INSTR_IDX__MASK				0x0000001f
+#define A5XX_VFD_DECODE_INSTR_IDX__SHIFT			0
+static inline uint32_t A5XX_VFD_DECODE_INSTR_IDX(uint32_t val)
+{
+	return ((val) << A5XX_VFD_DECODE_INSTR_IDX__SHIFT) & A5XX_VFD_DECODE_INSTR_IDX__MASK;
+}
+#define A5XX_VFD_DECODE_INSTR_FORMAT__MASK			0x3ff00000
+#define A5XX_VFD_DECODE_INSTR_FORMAT__SHIFT			20
+static inline uint32_t A5XX_VFD_DECODE_INSTR_FORMAT(enum a5xx_vtx_fmt val)
+{
+	return ((val) << A5XX_VFD_DECODE_INSTR_FORMAT__SHIFT) & A5XX_VFD_DECODE_INSTR_FORMAT__MASK;
+}
+#define A5XX_VFD_DECODE_INSTR_SWAP__MASK			0xc0000000
+#define A5XX_VFD_DECODE_INSTR_SWAP__SHIFT			30
+static inline uint32_t A5XX_VFD_DECODE_INSTR_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A5XX_VFD_DECODE_INSTR_SWAP__SHIFT) & A5XX_VFD_DECODE_INSTR_SWAP__MASK;
+}
+
+static inline uint32_t REG_A5XX_VFD_DECODE_STEP_RATE(uint32_t i0) { return 0x0000e48b + 0x2*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DEST_CNTL(uint32_t i0) { return 0x0000e4ca + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_VFD_DEST_CNTL_INSTR(uint32_t i0) { return 0x0000e4ca + 0x1*i0; }
+#define A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__MASK		0x0000000f
+#define A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__SHIFT		0
+static inline uint32_t A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK(uint32_t val)
+{
+	return ((val) << A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__SHIFT) & A5XX_VFD_DEST_CNTL_INSTR_WRITEMASK__MASK;
+}
+#define A5XX_VFD_DEST_CNTL_INSTR_REGID__MASK			0x00000ff0
+#define A5XX_VFD_DEST_CNTL_INSTR_REGID__SHIFT			4
+static inline uint32_t A5XX_VFD_DEST_CNTL_INSTR_REGID(uint32_t val)
+{
+	return ((val) << A5XX_VFD_DEST_CNTL_INSTR_REGID__SHIFT) & A5XX_VFD_DEST_CNTL_INSTR_REGID__MASK;
+}
+
+#define REG_A5XX_VFD_POWER_CNTL					0x0000e4f0
+
+#define REG_A5XX_SP_SP_CNTL					0x0000e580
+
+#define REG_A5XX_SP_VS_CONTROL_REG				0x0000e584
+#define A5XX_SP_VS_CONTROL_REG_ENABLED				0x00000001
+#define A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK		0x000000fe
+#define A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT		1
+static inline uint32_t A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_VS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_FS_CONTROL_REG				0x0000e585
+#define A5XX_SP_FS_CONTROL_REG_ENABLED				0x00000001
+#define A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK		0x000000fe
+#define A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT		1
+static inline uint32_t A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_FS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_HS_CONTROL_REG				0x0000e586
+#define A5XX_SP_HS_CONTROL_REG_ENABLED				0x00000001
+#define A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK		0x000000fe
+#define A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT		1
+static inline uint32_t A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_HS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_DS_CONTROL_REG				0x0000e587
+#define A5XX_SP_DS_CONTROL_REG_ENABLED				0x00000001
+#define A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK		0x000000fe
+#define A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT		1
+static inline uint32_t A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_DS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_GS_CONTROL_REG				0x0000e588
+#define A5XX_SP_GS_CONTROL_REG_ENABLED				0x00000001
+#define A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK		0x000000fe
+#define A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT		1
+static inline uint32_t A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_SP_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_SP_GS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_SP_CS_CONFIG					0x0000e589
+
+#define REG_A5XX_SP_VS_CONFIG_MAX_CONST				0x0000e58a
+
+#define REG_A5XX_SP_FS_CONFIG_MAX_CONST				0x0000e58b
+
+#define REG_A5XX_SP_VS_CTRL_REG0				0x0000e590
+#define A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK		0x000003f0
+#define A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT		4
+static inline uint32_t A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A5XX_SP_VS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK		0x0000fc00
+#define A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT		10
+static inline uint32_t A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A5XX_SP_VS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_VS_CTRL_REG0_VARYING				0x00010000
+#define A5XX_SP_VS_CTRL_REG0_PIXLODENABLE			0x00100000
+
+#define REG_A5XX_SP_PRIMITIVE_CNTL				0x0000e592
+#define A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK		0x0000001f
+#define A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT		0
+static inline uint32_t A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC(uint32_t val)
+{
+	return ((val >> 2) << A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__SHIFT) & A5XX_SP_PRIMITIVE_CNTL_STRIDE_IN_VPC__MASK;
+}
+
+static inline uint32_t REG_A5XX_SP_VS_OUT(uint32_t i0) { return 0x0000e593 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_VS_OUT_REG(uint32_t i0) { return 0x0000e593 + 0x1*i0; }
+#define A5XX_SP_VS_OUT_REG_A_REGID__MASK			0x000000ff
+#define A5XX_SP_VS_OUT_REG_A_REGID__SHIFT			0
+static inline uint32_t A5XX_SP_VS_OUT_REG_A_REGID(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_OUT_REG_A_REGID__SHIFT) & A5XX_SP_VS_OUT_REG_A_REGID__MASK;
+}
+#define A5XX_SP_VS_OUT_REG_A_COMPMASK__MASK			0x00000f00
+#define A5XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT			8
+static inline uint32_t A5XX_SP_VS_OUT_REG_A_COMPMASK(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_OUT_REG_A_COMPMASK__SHIFT) & A5XX_SP_VS_OUT_REG_A_COMPMASK__MASK;
+}
+#define A5XX_SP_VS_OUT_REG_B_REGID__MASK			0x00ff0000
+#define A5XX_SP_VS_OUT_REG_B_REGID__SHIFT			16
+static inline uint32_t A5XX_SP_VS_OUT_REG_B_REGID(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_OUT_REG_B_REGID__SHIFT) & A5XX_SP_VS_OUT_REG_B_REGID__MASK;
+}
+#define A5XX_SP_VS_OUT_REG_B_COMPMASK__MASK			0x0f000000
+#define A5XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT			24
+static inline uint32_t A5XX_SP_VS_OUT_REG_B_COMPMASK(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_OUT_REG_B_COMPMASK__SHIFT) & A5XX_SP_VS_OUT_REG_B_COMPMASK__MASK;
+}
+
+static inline uint32_t REG_A5XX_SP_VS_VPC_DST(uint32_t i0) { return 0x0000e5a3 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_VS_VPC_DST_REG(uint32_t i0) { return 0x0000e5a3 + 0x1*i0; }
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK			0x000000ff
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT			0
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC0(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC0__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC0__MASK;
+}
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK			0x0000ff00
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT			8
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC1(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC1__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC1__MASK;
+}
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK			0x00ff0000
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT			16
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC2(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC2__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC2__MASK;
+}
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK			0xff000000
+#define A5XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT			24
+static inline uint32_t A5XX_SP_VS_VPC_DST_REG_OUTLOC3(uint32_t val)
+{
+	return ((val) << A5XX_SP_VS_VPC_DST_REG_OUTLOC3__SHIFT) & A5XX_SP_VS_VPC_DST_REG_OUTLOC3__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E5AB					0x0000e5ab
+
+#define REG_A5XX_SP_VS_OBJ_START_LO				0x0000e5ac
+
+#define REG_A5XX_SP_VS_OBJ_START_HI				0x0000e5ad
+
+#define REG_A5XX_SP_FS_CTRL_REG0				0x0000e5c0
+#define A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK		0x000003f0
+#define A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT		4
+static inline uint32_t A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__SHIFT) & A5XX_SP_FS_CTRL_REG0_HALFREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK		0x0000fc00
+#define A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT		10
+static inline uint32_t A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__SHIFT) & A5XX_SP_FS_CTRL_REG0_FULLREGFOOTPRINT__MASK;
+}
+#define A5XX_SP_FS_CTRL_REG0_VARYING				0x00010000
+#define A5XX_SP_FS_CTRL_REG0_PIXLODENABLE			0x00100000
+
+#define REG_A5XX_UNKNOWN_E5C2					0x0000e5c2
+
+#define REG_A5XX_SP_FS_OBJ_START_LO				0x0000e5c3
+
+#define REG_A5XX_SP_FS_OBJ_START_HI				0x0000e5c4
+
+#define REG_A5XX_SP_BLEND_CNTL					0x0000e5c9
+
+#define REG_A5XX_SP_FS_OUTPUT_CNTL				0x0000e5ca
+#define A5XX_SP_FS_OUTPUT_CNTL_MRT__MASK			0x0000000f
+#define A5XX_SP_FS_OUTPUT_CNTL_MRT__SHIFT			0
+static inline uint32_t A5XX_SP_FS_OUTPUT_CNTL_MRT(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_OUTPUT_CNTL_MRT__SHIFT) & A5XX_SP_FS_OUTPUT_CNTL_MRT__MASK;
+}
+#define A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__MASK		0x00001fe0
+#define A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__SHIFT		5
+static inline uint32_t A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__SHIFT) & A5XX_SP_FS_OUTPUT_CNTL_DEPTH_REGID__MASK;
+}
+#define A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__MASK		0x001fe000
+#define A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__SHIFT		13
+static inline uint32_t A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__SHIFT) & A5XX_SP_FS_OUTPUT_CNTL_SAMPLEMASK_REGID__MASK;
+}
+
+static inline uint32_t REG_A5XX_SP_FS_OUTPUT(uint32_t i0) { return 0x0000e5cb + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_FS_OUTPUT_REG(uint32_t i0) { return 0x0000e5cb + 0x1*i0; }
+#define A5XX_SP_FS_OUTPUT_REG_REGID__MASK			0x000000ff
+#define A5XX_SP_FS_OUTPUT_REG_REGID__SHIFT			0
+static inline uint32_t A5XX_SP_FS_OUTPUT_REG_REGID(uint32_t val)
+{
+	return ((val) << A5XX_SP_FS_OUTPUT_REG_REGID__SHIFT) & A5XX_SP_FS_OUTPUT_REG_REGID__MASK;
+}
+#define A5XX_SP_FS_OUTPUT_REG_HALF_PRECISION			0x00000100
+
+static inline uint32_t REG_A5XX_SP_FS_MRT(uint32_t i0) { return 0x0000e5d3 + 0x1*i0; }
+
+static inline uint32_t REG_A5XX_SP_FS_MRT_REG(uint32_t i0) { return 0x0000e5d3 + 0x1*i0; }
+#define A5XX_SP_FS_MRT_REG_COLOR_FORMAT__MASK			0x000000ff
+#define A5XX_SP_FS_MRT_REG_COLOR_FORMAT__SHIFT			0
+static inline uint32_t A5XX_SP_FS_MRT_REG_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+	return ((val) << A5XX_SP_FS_MRT_REG_COLOR_FORMAT__SHIFT) & A5XX_SP_FS_MRT_REG_COLOR_FORMAT__MASK;
+}
+
+#define REG_A5XX_UNKNOWN_E5DB					0x0000e5db
+
+#define REG_A5XX_SP_CS_CNTL_0					0x0000e5f0
+
+#define REG_A5XX_UNKNOWN_E600					0x0000e600
+
+#define REG_A5XX_UNKNOWN_E640					0x0000e640
+
+#define REG_A5XX_TPL1_TP_RAS_MSAA_CNTL				0x0000e704
+#define A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__MASK		0x00000003
+#define A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__SHIFT		0
+static inline uint32_t A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+	return ((val) << A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES__MASK;
+}
+
+#define REG_A5XX_TPL1_TP_DEST_MSAA_CNTL				0x0000e705
+#define A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__MASK		0x00000003
+#define A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__SHIFT		0
+static inline uint32_t A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val)
+{
+	return ((val) << A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__SHIFT) & A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES__MASK;
+}
+#define A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE		0x00000004
+
+#define REG_A5XX_TPL1_VS_TEX_COUNT				0x0000e700
+
+#define REG_A5XX_TPL1_VS_TEX_SAMP_LO				0x0000e722
+
+#define REG_A5XX_TPL1_VS_TEX_SAMP_HI				0x0000e723
+
+#define REG_A5XX_TPL1_VS_TEX_CONST_LO				0x0000e72a
+
+#define REG_A5XX_TPL1_VS_TEX_CONST_HI				0x0000e72b
+
+#define REG_A5XX_TPL1_FS_TEX_COUNT				0x0000e750
+
+#define REG_A5XX_TPL1_FS_TEX_SAMP_LO				0x0000e75a
+
+#define REG_A5XX_TPL1_FS_TEX_SAMP_HI				0x0000e75b
+
+#define REG_A5XX_TPL1_FS_TEX_CONST_LO				0x0000e75e
+
+#define REG_A5XX_TPL1_FS_TEX_CONST_HI				0x0000e75f
+
+#define REG_A5XX_TPL1_TP_FS_ROTATION_CNTL			0x0000e764
+
+#define REG_A5XX_HLSQ_CONTROL_0_REG				0x0000e784
+
+#define REG_A5XX_HLSQ_CONTROL_1_REG				0x0000e785
+#define A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__MASK	0x0000003f
+#define A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__SHIFT	0
+static inline uint32_t A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__SHIFT) & A5XX_HLSQ_CONTROL_1_REG_PRIMALLOCTHRESHOLD__MASK;
+}
+
+#define REG_A5XX_HLSQ_CONTROL_2_REG				0x0000e786
+#define A5XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK			0x000000ff
+#define A5XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT		0
+static inline uint32_t A5XX_HLSQ_CONTROL_2_REG_FACEREGID(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT) & A5XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK;
+}
+
+#define REG_A5XX_HLSQ_CONTROL_3_REG				0x0000e787
+#define A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__MASK		0x000000ff
+#define A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__SHIFT		0
+static inline uint32_t A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__SHIFT) & A5XX_HLSQ_CONTROL_3_REG_FRAGCOORDXYREGID__MASK;
+}
+
+#define REG_A5XX_HLSQ_CONTROL_4_REG				0x0000e788
+#define A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__MASK		0x00ff0000
+#define A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__SHIFT		16
+static inline uint32_t A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__SHIFT) & A5XX_HLSQ_CONTROL_4_REG_XYCOORDREGID__MASK;
+}
+#define A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__MASK		0xff000000
+#define A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__SHIFT		24
+static inline uint32_t A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__SHIFT) & A5XX_HLSQ_CONTROL_4_REG_ZWCOORDREGID__MASK;
+}
+
+#define REG_A5XX_HLSQ_UPDATE_CNTL				0x0000e78a
+
+#define REG_A5XX_HLSQ_VS_CONTROL_REG				0x0000e78b
+#define A5XX_HLSQ_VS_CONTROL_REG_ENABLED			0x00000001
+#define A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK	0x000000fe
+#define A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT	1
+static inline uint32_t A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_FS_CONTROL_REG				0x0000e78c
+#define A5XX_HLSQ_FS_CONTROL_REG_ENABLED			0x00000001
+#define A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK	0x000000fe
+#define A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT	1
+static inline uint32_t A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_HS_CONTROL_REG				0x0000e78d
+#define A5XX_HLSQ_HS_CONTROL_REG_ENABLED			0x00000001
+#define A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK	0x000000fe
+#define A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT	1
+static inline uint32_t A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_DS_CONTROL_REG				0x0000e78e
+#define A5XX_HLSQ_DS_CONTROL_REG_ENABLED			0x00000001
+#define A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK	0x000000fe
+#define A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT	1
+static inline uint32_t A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_GS_CONTROL_REG				0x0000e78f
+#define A5XX_HLSQ_GS_CONTROL_REG_ENABLED			0x00000001
+#define A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK	0x000000fe
+#define A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT	1
+static inline uint32_t A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A5XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
+}
+#define A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK		0x00007f00
+#define A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT		8
+static inline uint32_t A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT) & A5XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK;
+}
+
+#define REG_A5XX_HLSQ_CS_CONFIG					0x0000e790
+
+#define REG_A5XX_HLSQ_VS_CNTL					0x0000e791
+#define A5XX_HLSQ_VS_CNTL_INSTRLEN__MASK			0xfffffffe
+#define A5XX_HLSQ_VS_CNTL_INSTRLEN__SHIFT			1
+static inline uint32_t A5XX_HLSQ_VS_CNTL_INSTRLEN(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_VS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_VS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_FS_CNTL					0x0000e792
+#define A5XX_HLSQ_FS_CNTL_INSTRLEN__MASK			0xfffffffe
+#define A5XX_HLSQ_FS_CNTL_INSTRLEN__SHIFT			1
+static inline uint32_t A5XX_HLSQ_FS_CNTL_INSTRLEN(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_FS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_FS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_HS_CNTL					0x0000e793
+#define A5XX_HLSQ_HS_CNTL_INSTRLEN__MASK			0xfffffffe
+#define A5XX_HLSQ_HS_CNTL_INSTRLEN__SHIFT			1
+static inline uint32_t A5XX_HLSQ_HS_CNTL_INSTRLEN(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_HS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_HS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_DS_CNTL					0x0000e794
+#define A5XX_HLSQ_DS_CNTL_INSTRLEN__MASK			0xfffffffe
+#define A5XX_HLSQ_DS_CNTL_INSTRLEN__SHIFT			1
+static inline uint32_t A5XX_HLSQ_DS_CNTL_INSTRLEN(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_DS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_DS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_GS_CNTL					0x0000e795
+#define A5XX_HLSQ_GS_CNTL_INSTRLEN__MASK			0xfffffffe
+#define A5XX_HLSQ_GS_CNTL_INSTRLEN__SHIFT			1
+static inline uint32_t A5XX_HLSQ_GS_CNTL_INSTRLEN(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_GS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_GS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_CS_CNTL					0x0000e796
+#define A5XX_HLSQ_CS_CNTL_INSTRLEN__MASK			0xfffffffe
+#define A5XX_HLSQ_CS_CNTL_INSTRLEN__SHIFT			1
+static inline uint32_t A5XX_HLSQ_CS_CNTL_INSTRLEN(uint32_t val)
+{
+	return ((val) << A5XX_HLSQ_CS_CNTL_INSTRLEN__SHIFT) & A5XX_HLSQ_CS_CNTL_INSTRLEN__MASK;
+}
+
+#define REG_A5XX_HLSQ_CS_KERNEL_GROUP_X				0x0000e7b9
+
+#define REG_A5XX_HLSQ_CS_KERNEL_GROUP_Y				0x0000e7ba
+
+#define REG_A5XX_HLSQ_CS_KERNEL_GROUP_Z				0x0000e7bb
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_0				0x0000e7b0
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_1				0x0000e7b1
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_2				0x0000e7b2
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_3				0x0000e7b3
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_4				0x0000e7b4
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_5				0x0000e7b5
+
+#define REG_A5XX_HLSQ_CS_NDRANGE_6				0x0000e7b6
+
+#define REG_A5XX_HLSQ_CS_CNTL_0					0x0000e7b7
+
+#define REG_A5XX_HLSQ_CS_CNTL_1					0x0000e7b8
+
+#define REG_A5XX_UNKNOWN_E7C0					0x0000e7c0
+
+#define REG_A5XX_HLSQ_VS_CONSTLEN				0x0000e7c3
+
+#define REG_A5XX_HLSQ_VS_INSTRLEN				0x0000e7c4
+
+#define REG_A5XX_UNKNOWN_E7C5					0x0000e7c5
+
+#define REG_A5XX_UNKNOWN_E7CA					0x0000e7ca
+
+#define REG_A5XX_HLSQ_FS_CONSTLEN				0x0000e7d7
+
+#define REG_A5XX_HLSQ_FS_INSTRLEN				0x0000e7d8
+
+#define REG_A5XX_HLSQ_HS_CONSTLEN				0x0000e7c8
+
+#define REG_A5XX_HLSQ_HS_INSTRLEN				0x0000e7c9
+
+#define REG_A5XX_HLSQ_DS_CONSTLEN				0x0000e7cd
+
+#define REG_A5XX_HLSQ_DS_INSTRLEN				0x0000e7ce
+
+#define REG_A5XX_UNKNOWN_E7CF					0x0000e7cf
+
+#define REG_A5XX_HLSQ_GS_CONSTLEN				0x0000e7d2
+
+#define REG_A5XX_HLSQ_GS_INSTRLEN				0x0000e7d3
+
+#define REG_A5XX_UNKNOWN_E7D4					0x0000e7d4
+
+#define REG_A5XX_UNKNOWN_E7D9					0x0000e7d9
+
+#define REG_A5XX_HLSQ_CONTEXT_SWITCH_CS_SW_3			0x0000e7dc
+
+#define REG_A5XX_HLSQ_CONTEXT_SWITCH_CS_SW_4			0x0000e7dd
+
+#define REG_A5XX_RB_2D_DST_FILL					0x00002101
+
+#define REG_A5XX_RB_2D_SRC_INFO					0x00002107
+#define A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__MASK			0x000000ff
+#define A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__SHIFT			0
+static inline uint32_t A5XX_RB_2D_SRC_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+	return ((val) << A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__SHIFT) & A5XX_RB_2D_SRC_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_RB_2D_SRC_INFO_COLOR_SWAP__MASK			0x00000c00
+#define A5XX_RB_2D_SRC_INFO_COLOR_SWAP__SHIFT			10
+static inline uint32_t A5XX_RB_2D_SRC_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A5XX_RB_2D_SRC_INFO_COLOR_SWAP__SHIFT) & A5XX_RB_2D_SRC_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_RB_2D_SRC_LO					0x00002108
+
+#define REG_A5XX_RB_2D_SRC_HI					0x00002109
+
+#define REG_A5XX_RB_2D_DST_INFO					0x00002110
+#define A5XX_RB_2D_DST_INFO_COLOR_FORMAT__MASK			0x000000ff
+#define A5XX_RB_2D_DST_INFO_COLOR_FORMAT__SHIFT			0
+static inline uint32_t A5XX_RB_2D_DST_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+	return ((val) << A5XX_RB_2D_DST_INFO_COLOR_FORMAT__SHIFT) & A5XX_RB_2D_DST_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_RB_2D_DST_INFO_COLOR_SWAP__MASK			0x00000c00
+#define A5XX_RB_2D_DST_INFO_COLOR_SWAP__SHIFT			10
+static inline uint32_t A5XX_RB_2D_DST_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A5XX_RB_2D_DST_INFO_COLOR_SWAP__SHIFT) & A5XX_RB_2D_DST_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_RB_2D_SRC_FLAGS_LO				0x00002140
+
+#define REG_A5XX_RB_2D_SRC_FLAGS_HI				0x00002141
+
+#define REG_A5XX_RB_2D_DST_LO					0x00002111
+
+#define REG_A5XX_RB_2D_DST_HI					0x00002112
+
+#define REG_A5XX_RB_2D_DST_FLAGS_LO				0x00002143
+
+#define REG_A5XX_RB_2D_DST_FLAGS_HI				0x00002144
+
+#define REG_A5XX_GRAS_2D_SRC_INFO				0x00002181
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__MASK		0x000000ff
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__SHIFT		0
+static inline uint32_t A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+	return ((val) << A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__SHIFT) & A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__MASK			0x00000c00
+#define A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__SHIFT			10
+static inline uint32_t A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__SHIFT) & A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_GRAS_2D_DST_INFO				0x00002182
+#define A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__MASK		0x000000ff
+#define A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__SHIFT		0
+static inline uint32_t A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT(enum a5xx_color_fmt val)
+{
+	return ((val) << A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__SHIFT) & A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT__MASK;
+}
+#define A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__MASK			0x00000c00
+#define A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__SHIFT			10
+static inline uint32_t A5XX_GRAS_2D_DST_INFO_COLOR_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__SHIFT) & A5XX_GRAS_2D_DST_INFO_COLOR_SWAP__MASK;
+}
+
+#define REG_A5XX_TEX_SAMP_0					0x00000000
+#define A5XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR			0x00000001
+#define A5XX_TEX_SAMP_0_XY_MAG__MASK				0x00000006
+#define A5XX_TEX_SAMP_0_XY_MAG__SHIFT				1
+static inline uint32_t A5XX_TEX_SAMP_0_XY_MAG(enum a5xx_tex_filter val)
+{
+	return ((val) << A5XX_TEX_SAMP_0_XY_MAG__SHIFT) & A5XX_TEX_SAMP_0_XY_MAG__MASK;
+}
+#define A5XX_TEX_SAMP_0_XY_MIN__MASK				0x00000018
+#define A5XX_TEX_SAMP_0_XY_MIN__SHIFT				3
+static inline uint32_t A5XX_TEX_SAMP_0_XY_MIN(enum a5xx_tex_filter val)
+{
+	return ((val) << A5XX_TEX_SAMP_0_XY_MIN__SHIFT) & A5XX_TEX_SAMP_0_XY_MIN__MASK;
+}
+#define A5XX_TEX_SAMP_0_WRAP_S__MASK				0x000000e0
+#define A5XX_TEX_SAMP_0_WRAP_S__SHIFT				5
+static inline uint32_t A5XX_TEX_SAMP_0_WRAP_S(enum a5xx_tex_clamp val)
+{
+	return ((val) << A5XX_TEX_SAMP_0_WRAP_S__SHIFT) & A5XX_TEX_SAMP_0_WRAP_S__MASK;
+}
+#define A5XX_TEX_SAMP_0_WRAP_T__MASK				0x00000700
+#define A5XX_TEX_SAMP_0_WRAP_T__SHIFT				8
+static inline uint32_t A5XX_TEX_SAMP_0_WRAP_T(enum a5xx_tex_clamp val)
+{
+	return ((val) << A5XX_TEX_SAMP_0_WRAP_T__SHIFT) & A5XX_TEX_SAMP_0_WRAP_T__MASK;
+}
+#define A5XX_TEX_SAMP_0_WRAP_R__MASK				0x00003800
+#define A5XX_TEX_SAMP_0_WRAP_R__SHIFT				11
+static inline uint32_t A5XX_TEX_SAMP_0_WRAP_R(enum a5xx_tex_clamp val)
+{
+	return ((val) << A5XX_TEX_SAMP_0_WRAP_R__SHIFT) & A5XX_TEX_SAMP_0_WRAP_R__MASK;
+}
+#define A5XX_TEX_SAMP_0_ANISO__MASK				0x0001c000
+#define A5XX_TEX_SAMP_0_ANISO__SHIFT				14
+static inline uint32_t A5XX_TEX_SAMP_0_ANISO(enum a5xx_tex_aniso val)
+{
+	return ((val) << A5XX_TEX_SAMP_0_ANISO__SHIFT) & A5XX_TEX_SAMP_0_ANISO__MASK;
+}
+#define A5XX_TEX_SAMP_0_LOD_BIAS__MASK				0xfff80000
+#define A5XX_TEX_SAMP_0_LOD_BIAS__SHIFT				19
+static inline uint32_t A5XX_TEX_SAMP_0_LOD_BIAS(float val)
+{
+	return ((((int32_t)(val * 256.0))) << A5XX_TEX_SAMP_0_LOD_BIAS__SHIFT) & A5XX_TEX_SAMP_0_LOD_BIAS__MASK;
+}
+
+#define REG_A5XX_TEX_SAMP_1					0x00000001
+#define A5XX_TEX_SAMP_1_COMPARE_FUNC__MASK			0x0000000e
+#define A5XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT			1
+static inline uint32_t A5XX_TEX_SAMP_1_COMPARE_FUNC(enum adreno_compare_func val)
+{
+	return ((val) << A5XX_TEX_SAMP_1_COMPARE_FUNC__SHIFT) & A5XX_TEX_SAMP_1_COMPARE_FUNC__MASK;
+}
+#define A5XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF			0x00000010
+#define A5XX_TEX_SAMP_1_UNNORM_COORDS				0x00000020
+#define A5XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR			0x00000040
+#define A5XX_TEX_SAMP_1_MAX_LOD__MASK				0x000fff00
+#define A5XX_TEX_SAMP_1_MAX_LOD__SHIFT				8
+static inline uint32_t A5XX_TEX_SAMP_1_MAX_LOD(float val)
+{
+	return ((((uint32_t)(val * 256.0))) << A5XX_TEX_SAMP_1_MAX_LOD__SHIFT) & A5XX_TEX_SAMP_1_MAX_LOD__MASK;
+}
+#define A5XX_TEX_SAMP_1_MIN_LOD__MASK				0xfff00000
+#define A5XX_TEX_SAMP_1_MIN_LOD__SHIFT				20
+static inline uint32_t A5XX_TEX_SAMP_1_MIN_LOD(float val)
+{
+	return ((((uint32_t)(val * 256.0))) << A5XX_TEX_SAMP_1_MIN_LOD__SHIFT) & A5XX_TEX_SAMP_1_MIN_LOD__MASK;
+}
+
+#define REG_A5XX_TEX_SAMP_2					0x00000002
+
+#define REG_A5XX_TEX_SAMP_3					0x00000003
+
+#define REG_A5XX_TEX_CONST_0					0x00000000
+#define A5XX_TEX_CONST_0_TILE_MODE__MASK			0x00000003
+#define A5XX_TEX_CONST_0_TILE_MODE__SHIFT			0
+static inline uint32_t A5XX_TEX_CONST_0_TILE_MODE(enum a5xx_tile_mode val)
+{
+	return ((val) << A5XX_TEX_CONST_0_TILE_MODE__SHIFT) & A5XX_TEX_CONST_0_TILE_MODE__MASK;
+}
+#define A5XX_TEX_CONST_0_SRGB					0x00000004
+#define A5XX_TEX_CONST_0_SWIZ_X__MASK				0x00000070
+#define A5XX_TEX_CONST_0_SWIZ_X__SHIFT				4
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_X(enum a5xx_tex_swiz val)
+{
+	return ((val) << A5XX_TEX_CONST_0_SWIZ_X__SHIFT) & A5XX_TEX_CONST_0_SWIZ_X__MASK;
+}
+#define A5XX_TEX_CONST_0_SWIZ_Y__MASK				0x00000380
+#define A5XX_TEX_CONST_0_SWIZ_Y__SHIFT				7
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_Y(enum a5xx_tex_swiz val)
+{
+	return ((val) << A5XX_TEX_CONST_0_SWIZ_Y__SHIFT) & A5XX_TEX_CONST_0_SWIZ_Y__MASK;
+}
+#define A5XX_TEX_CONST_0_SWIZ_Z__MASK				0x00001c00
+#define A5XX_TEX_CONST_0_SWIZ_Z__SHIFT				10
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_Z(enum a5xx_tex_swiz val)
+{
+	return ((val) << A5XX_TEX_CONST_0_SWIZ_Z__SHIFT) & A5XX_TEX_CONST_0_SWIZ_Z__MASK;
+}
+#define A5XX_TEX_CONST_0_SWIZ_W__MASK				0x0000e000
+#define A5XX_TEX_CONST_0_SWIZ_W__SHIFT				13
+static inline uint32_t A5XX_TEX_CONST_0_SWIZ_W(enum a5xx_tex_swiz val)
+{
+	return ((val) << A5XX_TEX_CONST_0_SWIZ_W__SHIFT) & A5XX_TEX_CONST_0_SWIZ_W__MASK;
+}
+#define A5XX_TEX_CONST_0_FMT__MASK				0x3fc00000
+#define A5XX_TEX_CONST_0_FMT__SHIFT				22
+static inline uint32_t A5XX_TEX_CONST_0_FMT(enum a5xx_tex_fmt val)
+{
+	return ((val) << A5XX_TEX_CONST_0_FMT__SHIFT) & A5XX_TEX_CONST_0_FMT__MASK;
+}
+#define A5XX_TEX_CONST_0_SWAP__MASK				0xc0000000
+#define A5XX_TEX_CONST_0_SWAP__SHIFT				30
+static inline uint32_t A5XX_TEX_CONST_0_SWAP(enum a3xx_color_swap val)
+{
+	return ((val) << A5XX_TEX_CONST_0_SWAP__SHIFT) & A5XX_TEX_CONST_0_SWAP__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_1					0x00000001
+#define A5XX_TEX_CONST_1_WIDTH__MASK				0x00007fff
+#define A5XX_TEX_CONST_1_WIDTH__SHIFT				0
+static inline uint32_t A5XX_TEX_CONST_1_WIDTH(uint32_t val)
+{
+	return ((val) << A5XX_TEX_CONST_1_WIDTH__SHIFT) & A5XX_TEX_CONST_1_WIDTH__MASK;
+}
+#define A5XX_TEX_CONST_1_HEIGHT__MASK				0x3fff8000
+#define A5XX_TEX_CONST_1_HEIGHT__SHIFT				15
+static inline uint32_t A5XX_TEX_CONST_1_HEIGHT(uint32_t val)
+{
+	return ((val) << A5XX_TEX_CONST_1_HEIGHT__SHIFT) & A5XX_TEX_CONST_1_HEIGHT__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_2					0x00000002
+#define A5XX_TEX_CONST_2_FETCHSIZE__MASK			0x0000000f
+#define A5XX_TEX_CONST_2_FETCHSIZE__SHIFT			0
+static inline uint32_t A5XX_TEX_CONST_2_FETCHSIZE(enum a5xx_tex_fetchsize val)
+{
+	return ((val) << A5XX_TEX_CONST_2_FETCHSIZE__SHIFT) & A5XX_TEX_CONST_2_FETCHSIZE__MASK;
+}
+#define A5XX_TEX_CONST_2_PITCH__MASK				0x1fffff80
+#define A5XX_TEX_CONST_2_PITCH__SHIFT				7
+static inline uint32_t A5XX_TEX_CONST_2_PITCH(uint32_t val)
+{
+	return ((val) << A5XX_TEX_CONST_2_PITCH__SHIFT) & A5XX_TEX_CONST_2_PITCH__MASK;
+}
+#define A5XX_TEX_CONST_2_TYPE__MASK				0x60000000
+#define A5XX_TEX_CONST_2_TYPE__SHIFT				29
+static inline uint32_t A5XX_TEX_CONST_2_TYPE(enum a5xx_tex_type val)
+{
+	return ((val) << A5XX_TEX_CONST_2_TYPE__SHIFT) & A5XX_TEX_CONST_2_TYPE__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_3					0x00000003
+#define A5XX_TEX_CONST_3_ARRAY_PITCH__MASK			0x00003fff
+#define A5XX_TEX_CONST_3_ARRAY_PITCH__SHIFT			0
+static inline uint32_t A5XX_TEX_CONST_3_ARRAY_PITCH(uint32_t val)
+{
+	return ((val >> 12) << A5XX_TEX_CONST_3_ARRAY_PITCH__SHIFT) & A5XX_TEX_CONST_3_ARRAY_PITCH__MASK;
+}
+#define A5XX_TEX_CONST_3_FLAG					0x10000000
+
+#define REG_A5XX_TEX_CONST_4					0x00000004
+#define A5XX_TEX_CONST_4_BASE_LO__MASK				0xffffffe0
+#define A5XX_TEX_CONST_4_BASE_LO__SHIFT				5
+static inline uint32_t A5XX_TEX_CONST_4_BASE_LO(uint32_t val)
+{
+	return ((val >> 5) << A5XX_TEX_CONST_4_BASE_LO__SHIFT) & A5XX_TEX_CONST_4_BASE_LO__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_5					0x00000005
+#define A5XX_TEX_CONST_5_BASE_HI__MASK				0x0001ffff
+#define A5XX_TEX_CONST_5_BASE_HI__SHIFT				0
+static inline uint32_t A5XX_TEX_CONST_5_BASE_HI(uint32_t val)
+{
+	return ((val) << A5XX_TEX_CONST_5_BASE_HI__SHIFT) & A5XX_TEX_CONST_5_BASE_HI__MASK;
+}
+#define A5XX_TEX_CONST_5_DEPTH__MASK				0x3ffe0000
+#define A5XX_TEX_CONST_5_DEPTH__SHIFT				17
+static inline uint32_t A5XX_TEX_CONST_5_DEPTH(uint32_t val)
+{
+	return ((val) << A5XX_TEX_CONST_5_DEPTH__SHIFT) & A5XX_TEX_CONST_5_DEPTH__MASK;
+}
+
+#define REG_A5XX_TEX_CONST_6					0x00000006
+
+#define REG_A5XX_TEX_CONST_7					0x00000007
+
+#define REG_A5XX_TEX_CONST_8					0x00000008
+
+#define REG_A5XX_TEX_CONST_9					0x00000009
+
+#define REG_A5XX_TEX_CONST_10					0x0000000a
+
+#define REG_A5XX_TEX_CONST_11					0x0000000b
+
+
+#endif /* A5XX_XML */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_common.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    431 bytes, from 2016-04-26 17:56:44)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1572 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml          (  90321 bytes, from 2016-11-28 16:50:05)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml         (   1773 bytes, from 2015-09-24 17:30:00)
 
 Copyright (C) 2013-2016 by the following authors:
@@ -172,6 +173,14 @@ enum a3xx_color_swap {
 	XYZW = 3,
 };
 
+enum a3xx_rb_blend_opcode {
+	BLEND_DST_PLUS_SRC = 0,
+	BLEND_SRC_MINUS_DST = 1,
+	BLEND_DST_MINUS_SRC = 2,
+	BLEND_MIN_DST_SRC = 3,
+	BLEND_MAX_DST_SRC = 4,
+};
+
 #define REG_AXXX_CP_RB_BASE					0x000001c0
 
 #define REG_AXXX_CP_RB_CNTL					0x000001c1
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_device.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_device.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_device.c	2016-12-11 17:42:23.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_device.c	2017-02-12 17:25:51.000000000 -0500
@@ -25,9 +25,6 @@ bool hang_debug = false;
 MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)");
 module_param_named(hang_debug, hang_debug, bool, 0600);
 
-struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
-struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
-
 static const struct adreno_info gpulist[] = {
 	{
 		.rev   = ADRENO_REV(3, 0, 5, ANY_ID),
@@ -77,6 +74,15 @@ static const struct adreno_info gpulist[
 		.pfpfw = "/*(DEBLOBBED)*/",
 		.gmem  = (SZ_1M + SZ_512K),
 		.init  = a4xx_gpu_init,
+	}, {
+		.rev = ADRENO_REV(5, 3, 0, ANY_ID),
+		.revn = 530,
+		.name = "A530",
+		.pm4fw = "/*(DEBLOBBED)*/",
+		.pfpfw = "/*(DEBLOBBED)*/",
+		.gmem = SZ_1M,
+		.init = a5xx_gpu_init,
+		.gpmufw = "/*(DEBLOBBED)*/",
 	},
 };
 
@@ -143,12 +149,16 @@ struct msm_gpu *adreno_load_gpu(struct d
 		mutex_lock(&dev->struct_mutex);
 		gpu->funcs->pm_resume(gpu);
 		mutex_unlock(&dev->struct_mutex);
+
+		disable_irq(gpu->irq);
+
 		ret = gpu->funcs->hw_init(gpu);
 		if (ret) {
 			dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
 			gpu->funcs->destroy(gpu);
 			gpu = NULL;
 		} else {
+			enable_irq(gpu->irq);
 			/* give inactive pm a chance to kick in: */
 			msm_gpu_retire(gpu);
 		}
@@ -164,12 +174,20 @@ static void set_gpu_pdev(struct drm_devi
 	priv->gpu_pdev = pdev;
 }
 
+static const struct {
+	const char *str;
+	uint32_t flag;
+} quirks[] = {
+	{ "qcom,gpu-quirk-two-pass-use-wfi", ADRENO_QUIRK_TWO_PASS_USE_WFI },
+	{ "qcom,gpu-quirk-fault-detect-mask", ADRENO_QUIRK_FAULT_DETECT_MASK },
+};
+
 static int adreno_bind(struct device *dev, struct device *master, void *data)
 {
 	static struct adreno_platform_config config = {};
 	struct device_node *child, *node = dev->of_node;
 	u32 val;
-	int ret;
+	int ret, i;
 
 	ret = of_property_read_u32(node, "qcom,chipid", &val);
 	if (ret) {
@@ -203,6 +221,10 @@ static int adreno_bind(struct device *de
 		return -ENXIO;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(quirks); i++)
+		if (of_property_read_bool(node, quirks[i].str))
+			config.quirks |= quirks[i].flag;
+
 	dev->platform_data = &config;
 	set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev));
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c	2016-12-11 17:42:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.c	2017-02-12 17:25:48.000000000 -0500
@@ -22,7 +22,7 @@
 #include "msm_mmu.h"
 
 #define RB_SIZE    SZ_32K
-#define RB_BLKSIZE 16
+#define RB_BLKSIZE 32
 
 int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value)
 {
@@ -54,9 +54,6 @@ int adreno_get_param(struct msm_gpu *gpu
 	}
 }
 
-#define rbmemptr(adreno_gpu, member)  \
-	((adreno_gpu)->memptrs_iova + offsetof(struct adreno_rbmemptrs, member))
-
 int adreno_hw_init(struct msm_gpu *gpu)
 {
 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -79,11 +76,14 @@ int adreno_hw_init(struct msm_gpu *gpu)
 			(adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0));
 
 	/* Setup ringbuffer address: */
-	adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_BASE, gpu->rb_iova);
+	adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_BASE,
+		REG_ADRENO_CP_RB_BASE_HI, gpu->rb_iova);
 
-	if (!adreno_is_a430(adreno_gpu))
-		adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
-						rbmemptr(adreno_gpu, rptr));
+	if (!adreno_is_a430(adreno_gpu)) {
+		adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
+			REG_ADRENO_CP_RB_RPTR_ADDR_HI,
+			rbmemptr(adreno_gpu, rptr));
+	}
 
 	return 0;
 }
@@ -126,11 +126,14 @@ void adreno_recover(struct msm_gpu *gpu)
 	adreno_gpu->memptrs->wptr  = 0;
 
 	gpu->funcs->pm_resume(gpu);
+
+	disable_irq(gpu->irq);
 	ret = gpu->funcs->hw_init(gpu);
 	if (ret) {
 		dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
 		/* hmm, oh well? */
 	}
+	enable_irq(gpu->irq);
 }
 
 void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
@@ -210,7 +213,14 @@ void adreno_submit(struct msm_gpu *gpu,
 void adreno_flush(struct msm_gpu *gpu)
 {
 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
-	uint32_t wptr = get_wptr(gpu->rb);
+	uint32_t wptr;
+
+	/*
+	 * Mask wptr value that we calculate to fit in the HW range. This is
+	 * to account for the possibility that the last command fit exactly into
+	 * the ringbuffer and rb->next hasn't wrapped to zero yet
+	 */
+	wptr = get_wptr(gpu->rb) & ((gpu->rb->size / 4) - 1);
 
 	/* ensure writes to ringbuffer have hit system memory: */
 	mb();
@@ -218,19 +228,18 @@ void adreno_flush(struct msm_gpu *gpu)
 	adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr);
 }
 
-void adreno_idle(struct msm_gpu *gpu)
+bool adreno_idle(struct msm_gpu *gpu)
 {
 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
 	uint32_t wptr = get_wptr(gpu->rb);
-	int ret;
 
 	/* wait for CP to drain ringbuffer: */
-	ret = spin_until(get_rptr(adreno_gpu) == wptr);
-
-	if (ret)
-		DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+	if (!spin_until(get_rptr(adreno_gpu) == wptr))
+		return true;
 
 	/* TODO maybe we need to reset GPU here to recover from hang? */
+	DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
+	return false;
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -278,7 +287,6 @@ void adreno_show(struct msm_gpu *gpu, st
 void adreno_dump_info(struct msm_gpu *gpu)
 {
 	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
-	int i;
 
 	printk("revision: %d (%d.%d.%d.%d)\n",
 			adreno_gpu->info->revn, adreno_gpu->rev.core,
@@ -290,11 +298,6 @@ void adreno_dump_info(struct msm_gpu *gp
 	printk("rptr:     %d\n", get_rptr(adreno_gpu));
 	printk("wptr:     %d\n", adreno_gpu->memptrs->wptr);
 	printk("rb wptr:  %d\n", get_wptr(gpu->rb));
-
-	for (i = 0; i < 8; i++) {
-		printk("CP_SCRATCH_REG%d: %u\n", i,
-			gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
-	}
 }
 
 /* would be nice to not have to duplicate the _show() stuff with printk(): */
@@ -342,7 +345,6 @@ int adreno_gpu_init(struct drm_device *d
 {
 	struct adreno_platform_config *config = pdev->dev.platform_data;
 	struct msm_gpu *gpu = &adreno_gpu->base;
-	struct msm_mmu *mmu;
 	int ret;
 
 	adreno_gpu->funcs = funcs;
@@ -350,6 +352,7 @@ int adreno_gpu_init(struct drm_device *d
 	adreno_gpu->gmem = adreno_gpu->info->gmem;
 	adreno_gpu->revn = adreno_gpu->info->revn;
 	adreno_gpu->rev = config->rev;
+	adreno_gpu->quirks = config->quirks;
 
 	gpu->fast_rate = config->fast_rate;
 	gpu->slow_rate = config->slow_rate;
@@ -381,8 +384,8 @@ int adreno_gpu_init(struct drm_device *d
 		return ret;
 	}
 
-	mmu = gpu->mmu;
-	if (mmu) {
+	if (gpu->aspace && gpu->aspace->mmu) {
+		struct msm_mmu *mmu = gpu->aspace->mmu;
 		ret = mmu->funcs->attach(mmu, iommu_ports,
 				ARRAY_SIZE(iommu_ports));
 		if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_gpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,9 @@
 #include "adreno_pm4.xml.h"
 
 #define REG_ADRENO_DEFINE(_offset, _reg) [_offset] = (_reg) + 1
+#define REG_SKIP ~0
+#define REG_ADRENO_SKIP(_offset) [_offset] = REG_SKIP
+
 /**
  * adreno_regs: List of registers that are used in across all
  * 3D devices. Each device type has different offset value for the same
@@ -35,73 +38,21 @@
  * and are indexed by the enumeration values defined in this enum
  */
 enum adreno_regs {
-	REG_ADRENO_CP_DEBUG,
-	REG_ADRENO_CP_ME_RAM_WADDR,
-	REG_ADRENO_CP_ME_RAM_DATA,
-	REG_ADRENO_CP_PFP_UCODE_DATA,
-	REG_ADRENO_CP_PFP_UCODE_ADDR,
-	REG_ADRENO_CP_WFI_PEND_CTR,
 	REG_ADRENO_CP_RB_BASE,
+	REG_ADRENO_CP_RB_BASE_HI,
 	REG_ADRENO_CP_RB_RPTR_ADDR,
+	REG_ADRENO_CP_RB_RPTR_ADDR_HI,
 	REG_ADRENO_CP_RB_RPTR,
 	REG_ADRENO_CP_RB_WPTR,
-	REG_ADRENO_CP_PROTECT_CTRL,
-	REG_ADRENO_CP_ME_CNTL,
 	REG_ADRENO_CP_RB_CNTL,
-	REG_ADRENO_CP_IB1_BASE,
-	REG_ADRENO_CP_IB1_BUFSZ,
-	REG_ADRENO_CP_IB2_BASE,
-	REG_ADRENO_CP_IB2_BUFSZ,
-	REG_ADRENO_CP_TIMESTAMP,
-	REG_ADRENO_CP_ME_RAM_RADDR,
-	REG_ADRENO_CP_ROQ_ADDR,
-	REG_ADRENO_CP_ROQ_DATA,
-	REG_ADRENO_CP_MERCIU_ADDR,
-	REG_ADRENO_CP_MERCIU_DATA,
-	REG_ADRENO_CP_MERCIU_DATA2,
-	REG_ADRENO_CP_MEQ_ADDR,
-	REG_ADRENO_CP_MEQ_DATA,
-	REG_ADRENO_CP_HW_FAULT,
-	REG_ADRENO_CP_PROTECT_STATUS,
-	REG_ADRENO_SCRATCH_ADDR,
-	REG_ADRENO_SCRATCH_UMSK,
-	REG_ADRENO_SCRATCH_REG2,
-	REG_ADRENO_RBBM_STATUS,
-	REG_ADRENO_RBBM_PERFCTR_CTL,
-	REG_ADRENO_RBBM_PERFCTR_LOAD_CMD0,
-	REG_ADRENO_RBBM_PERFCTR_LOAD_CMD1,
-	REG_ADRENO_RBBM_PERFCTR_LOAD_CMD2,
-	REG_ADRENO_RBBM_PERFCTR_PWR_1_LO,
-	REG_ADRENO_RBBM_INT_0_MASK,
-	REG_ADRENO_RBBM_INT_0_STATUS,
-	REG_ADRENO_RBBM_AHB_ERROR_STATUS,
-	REG_ADRENO_RBBM_PM_OVERRIDE2,
-	REG_ADRENO_RBBM_AHB_CMD,
-	REG_ADRENO_RBBM_INT_CLEAR_CMD,
-	REG_ADRENO_RBBM_SW_RESET_CMD,
-	REG_ADRENO_RBBM_CLOCK_CTL,
-	REG_ADRENO_RBBM_AHB_ME_SPLIT_STATUS,
-	REG_ADRENO_RBBM_AHB_PFP_SPLIT_STATUS,
-	REG_ADRENO_VPC_DEBUG_RAM_SEL,
-	REG_ADRENO_VPC_DEBUG_RAM_READ,
-	REG_ADRENO_VSC_SIZE_ADDRESS,
-	REG_ADRENO_VFD_CONTROL_0,
-	REG_ADRENO_VFD_INDEX_MAX,
-	REG_ADRENO_SP_VS_PVT_MEM_ADDR_REG,
-	REG_ADRENO_SP_FS_PVT_MEM_ADDR_REG,
-	REG_ADRENO_SP_VS_OBJ_START_REG,
-	REG_ADRENO_SP_FS_OBJ_START_REG,
-	REG_ADRENO_PA_SC_AA_CONFIG,
-	REG_ADRENO_SQ_GPR_MANAGEMENT,
-	REG_ADRENO_SQ_INST_STORE_MANAGMENT,
-	REG_ADRENO_TP0_CHICKEN,
-	REG_ADRENO_RBBM_RBBM_CTL,
-	REG_ADRENO_UCHE_INVALIDATE0,
-	REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_LO,
-	REG_ADRENO_RBBM_PERFCTR_LOAD_VALUE_HI,
 	REG_ADRENO_REGISTER_MAX,
 };
 
+enum adreno_quirks {
+	ADRENO_QUIRK_TWO_PASS_USE_WFI = 1,
+	ADRENO_QUIRK_FAULT_DETECT_MASK = 2,
+};
+
 struct adreno_rev {
 	uint8_t  core;
 	uint8_t  major;
@@ -122,12 +73,16 @@ struct adreno_info {
 	uint32_t revn;
 	const char *name;
 	const char *pm4fw, *pfpfw;
+	const char *gpmufw;
 	uint32_t gmem;
 	struct msm_gpu *(*init)(struct drm_device *dev);
 };
 
 const struct adreno_info *adreno_info(struct adreno_rev rev);
 
+#define rbmemptr(adreno_gpu, member)  \
+	((adreno_gpu)->memptrs_iova + offsetof(struct adreno_rbmemptrs, member))
+
 struct adreno_rbmemptrs {
 	volatile uint32_t rptr;
 	volatile uint32_t wptr;
@@ -153,7 +108,7 @@ struct adreno_gpu {
 	// different for z180..
 	struct adreno_rbmemptrs *memptrs;
 	struct drm_gem_object *memptrs_bo;
-	uint32_t memptrs_iova;
+	uint64_t memptrs_iova;
 
 	/*
 	 * Register offsets are different between some GPUs.
@@ -161,6 +116,8 @@ struct adreno_gpu {
 	 * code (a3xx_gpu.c) and stored in this common location.
 	 */
 	const unsigned int *reg_offsets;
+
+	uint32_t quirks;
 };
 #define to_adreno_gpu(x) container_of(x, struct adreno_gpu, base)
 
@@ -171,6 +128,7 @@ struct adreno_platform_config {
 #ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *bus_scale_table;
 #endif
+	uint32_t quirks;
 };
 
 #define ADRENO_IDLE_TIMEOUT msecs_to_jiffies(1000)
@@ -234,6 +192,11 @@ static inline int adreno_is_a430(struct
        return gpu->revn == 430;
 }
 
+static inline int adreno_is_a530(struct adreno_gpu *gpu)
+{
+	return gpu->revn == 530;
+}
+
 int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value);
 int adreno_hw_init(struct msm_gpu *gpu);
 uint32_t adreno_last_fence(struct msm_gpu *gpu);
@@ -241,7 +204,7 @@ void adreno_recover(struct msm_gpu *gpu)
 void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 		struct msm_file_private *ctx);
 void adreno_flush(struct msm_gpu *gpu);
-void adreno_idle(struct msm_gpu *gpu);
+bool adreno_idle(struct msm_gpu *gpu);
 #ifdef CONFIG_DEBUG_FS
 void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
 #endif
@@ -278,8 +241,38 @@ OUT_PKT3(struct msm_ringbuffer *ring, ui
 	OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8));
 }
 
+static inline u32 PM4_PARITY(u32 val)
+{
+	return (0x9669 >> (0xF & (val ^
+		(val >> 4) ^ (val >> 8) ^ (val >> 12) ^
+		(val >> 16) ^ ((val) >> 20) ^ (val >> 24) ^
+		(val >> 28)))) & 1;
+}
+
+/* Maximum number of values that can be executed for one opcode */
+#define TYPE4_MAX_PAYLOAD 127
+
+#define PKT4(_reg, _cnt) \
+	(CP_TYPE4_PKT | ((_cnt) << 0) | (PM4_PARITY((_cnt)) << 7) | \
+	 (((_reg) & 0x3FFFF) << 8) | (PM4_PARITY((_reg)) << 27))
+
+static inline void
+OUT_PKT4(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt)
+{
+	adreno_wait_ring(ring->gpu, cnt + 1);
+	OUT_RING(ring, PKT4(regindx, cnt));
+}
+
+static inline void
+OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt)
+{
+	adreno_wait_ring(ring->gpu, cnt + 1);
+	OUT_RING(ring, CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) |
+		((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23));
+}
+
 /*
- * adreno_checkreg_off() - Checks the validity of a register enum
+ * adreno_reg_check() - Checks the validity of a register enum
  * @gpu:		Pointer to struct adreno_gpu
  * @offset_name:	The register enum that is checked
  */
@@ -290,6 +283,16 @@ static inline bool adreno_reg_check(stru
 			!gpu->reg_offsets[offset_name]) {
 		BUG();
 	}
+
+	/*
+	 * REG_SKIP is a special value that tell us that the register in
+	 * question isn't implemented on target but don't trigger a BUG(). This
+	 * is used to cleanly implement adreno_gpu_write64() and
+	 * adreno_gpu_read64() in a generic fashion
+	 */
+	if (gpu->reg_offsets[offset_name] == REG_SKIP)
+		return false;
+
 	return true;
 }
 
@@ -311,4 +314,39 @@ static inline void adreno_gpu_write(stru
 		gpu_write(&gpu->base, reg - 1, data);
 }
 
+struct msm_gpu *a3xx_gpu_init(struct drm_device *dev);
+struct msm_gpu *a4xx_gpu_init(struct drm_device *dev);
+struct msm_gpu *a5xx_gpu_init(struct drm_device *dev);
+
+static inline void adreno_gpu_write64(struct adreno_gpu *gpu,
+		enum adreno_regs lo, enum adreno_regs hi, u64 data)
+{
+	adreno_gpu_write(gpu, lo, lower_32_bits(data));
+	adreno_gpu_write(gpu, hi, upper_32_bits(data));
+}
+
+/*
+ * Given a register and a count, return a value to program into
+ * REG_CP_PROTECT_REG(n) - this will block both reads and writes for _len
+ * registers starting at _reg.
+ *
+ * The register base needs to be a multiple of the length. If it is not, the
+ * hardware will quietly mask off the bits for you and shift the size. For
+ * example, if you intend the protection to start at 0x07 for a length of 4
+ * (0x07-0x0A) the hardware will actually protect (0x04-0x07) which might
+ * expose registers you intended to protect!
+ */
+#define ADRENO_PROTECT_RW(_reg, _len) \
+	((1 << 30) | (1 << 29) | \
+	((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF))
+
+/*
+ * Same as above, but allow reads over the range. For areas of mixed use (such
+ * as performance counters) this allows us to protect a much larger range with a
+ * single register
+ */
+#define ADRENO_PROTECT_RDONLY(_reg, _len) \
+	((1 << 29) \
+	((ilog2((_len)) & 0x1F) << 24) | (((_reg) << 2) & 0xFFFFF))
+
 #endif /* __ADRENO_GPU_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,13 +8,14 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    398 bytes, from 2015-09-24 17:25:31)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno.xml               (    431 bytes, from 2016-04-26 17:56:44)
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml  (   1572 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32901 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  11518 bytes, from 2016-02-10 21:03:25)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  16166 bytes, from 2016-02-11 21:20:31)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83967 bytes, from 2016-02-10 17:07:21)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 109916 bytes, from 2016-02-20 18:44:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml          (  32907 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml (  12025 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml    (  22544 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml          (  83840 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml          ( 110765 bytes, from 2016-11-26 23:01:48)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a5xx.xml          (  90321 bytes, from 2016-11-28 16:50:05)
 - /home/robclark/src/freedreno/envytools/rnndb/adreno/ocmem.xml         (   1773 bytes, from 2015-09-24 17:30:00)
 
 Copyright (C) 2013-2016 by the following authors:
@@ -58,6 +59,7 @@ enum vgt_event_type {
 	RST_PIX_CNT = 13,
 	RST_VTX_CNT = 14,
 	TILE_FLUSH = 15,
+	STAT_EVENT = 16,
 	CACHE_FLUSH_AND_INV_TS_EVENT = 20,
 	ZPASS_DONE = 21,
 	CACHE_FLUSH_AND_INV_EVENT = 22,
@@ -65,6 +67,10 @@ enum vgt_event_type {
 	PERFCOUNTER_STOP = 24,
 	VS_FETCH_DONE = 27,
 	FACENESS_FLUSH = 28,
+	UNK_1C = 28,
+	UNK_1D = 29,
+	BLIT = 30,
+	UNK_26 = 38,
 };
 
 enum pc_di_primtype {
@@ -82,7 +88,6 @@ enum pc_di_primtype {
 	DI_PT_LINESTRIP_ADJ = 11,
 	DI_PT_TRI_ADJ = 12,
 	DI_PT_TRISTRIP_ADJ = 13,
-	DI_PT_PATCHES = 34,
 };
 
 enum pc_di_src_sel {
@@ -110,11 +115,15 @@ enum adreno_pm4_packet_type {
 	CP_TYPE1_PKT = 0x40000000,
 	CP_TYPE2_PKT = 0x80000000,
 	CP_TYPE3_PKT = 0xc0000000,
+	CP_TYPE4_PKT = 0x40000000,
+	CP_TYPE7_PKT = 0x70000000,
 };
 
 enum adreno_pm4_type3_packets {
 	CP_ME_INIT = 72,
 	CP_NOP = 16,
+	CP_PREEMPT_ENABLE = 28,
+	CP_PREEMPT_TOKEN = 30,
 	CP_INDIRECT_BUFFER = 63,
 	CP_INDIRECT_BUFFER_PFD = 55,
 	CP_WAIT_FOR_IDLE = 38,
@@ -163,6 +172,7 @@ enum adreno_pm4_type3_packets {
 	CP_TEST_TWO_MEMS = 113,
 	CP_REG_WR_NO_CTXT = 120,
 	CP_RECORD_PFP_TIMESTAMP = 17,
+	CP_SET_SECURE_MODE = 102,
 	CP_WAIT_FOR_ME = 19,
 	CP_SET_DRAW_STATE = 67,
 	CP_DRAW_INDX_OFFSET = 56,
@@ -178,6 +188,22 @@ enum adreno_pm4_type3_packets {
 	CP_WAIT_MEM_WRITES = 18,
 	CP_COND_REG_EXEC = 71,
 	CP_MEM_TO_REG = 66,
+	CP_EXEC_CS = 51,
+	CP_PERFCOUNTER_ACTION = 80,
+	CP_SMMU_TABLE_UPDATE = 83,
+	CP_CONTEXT_REG_BUNCH = 92,
+	CP_YIELD_ENABLE = 28,
+	CP_SKIP_IB2_ENABLE_GLOBAL = 29,
+	CP_SKIP_IB2_ENABLE_LOCAL = 35,
+	CP_SET_SUBDRAW_SIZE = 53,
+	CP_SET_VISIBILITY_OVERRIDE = 100,
+	CP_PREEMPT_ENABLE_GLOBAL = 105,
+	CP_PREEMPT_ENABLE_LOCAL = 106,
+	CP_CONTEXT_SWITCH_YIELD = 107,
+	CP_SET_RENDER_MODE = 108,
+	CP_COMPUTE_CHECKPOINT = 110,
+	CP_MEM_TO_MEM = 115,
+	CP_BLIT = 44,
 	IN_IB_PREFETCH_END = 23,
 	IN_SUBBLK_PREFETCH = 31,
 	IN_INSTR_PREFETCH = 32,
@@ -196,6 +222,7 @@ enum adreno_state_block {
 	SB_VERT_SHADER = 4,
 	SB_GEOM_SHADER = 5,
 	SB_FRAG_SHADER = 6,
+	SB_COMPUTE_SHADER = 7,
 };
 
 enum adreno_state_type {
@@ -218,6 +245,17 @@ enum a4xx_index_size {
 	INDEX4_SIZE_32_BIT = 2,
 };
 
+enum render_mode_cmd {
+	BYPASS = 1,
+	GMEM = 3,
+	BLIT2D = 5,
+};
+
+enum cp_blit_cmd {
+	BLIT_OP_FILL = 0,
+	BLIT_OP_BLIT = 1,
+};
+
 #define REG_CP_LOAD_STATE_0					0x00000000
 #define CP_LOAD_STATE_0_DST_OFF__MASK				0x0000ffff
 #define CP_LOAD_STATE_0_DST_OFF__SHIFT				0
@@ -258,6 +296,14 @@ static inline uint32_t CP_LOAD_STATE_1_E
 	return ((val >> 2) << CP_LOAD_STATE_1_EXT_SRC_ADDR__SHIFT) & CP_LOAD_STATE_1_EXT_SRC_ADDR__MASK;
 }
 
+#define REG_CP_LOAD_STATE_2					0x00000002
+#define CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__MASK			0xffffffff
+#define CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__SHIFT			0
+static inline uint32_t CP_LOAD_STATE_2_EXT_SRC_ADDR_HI(uint32_t val)
+{
+	return ((val) << CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__SHIFT) & CP_LOAD_STATE_2_EXT_SRC_ADDR_HI__MASK;
+}
+
 #define REG_CP_DRAW_INDX_0					0x00000000
 #define CP_DRAW_INDX_0_VIZ_QUERY__MASK				0xffffffff
 #define CP_DRAW_INDX_0_VIZ_QUERY__SHIFT				0
@@ -389,7 +435,12 @@ static inline uint32_t CP_DRAW_INDX_OFFS
 {
 	return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
 }
-#define CP_DRAW_INDX_OFFSET_0_TESSELLATE			0x00000100
+#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK			0x00000300
+#define CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT			8
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_VIS_CULL(enum pc_di_vis_cull_mode val)
+{
+	return ((val) << CP_DRAW_INDX_OFFSET_0_VIS_CULL__SHIFT) & CP_DRAW_INDX_OFFSET_0_VIS_CULL__MASK;
+}
 #define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK			0x00000c00
 #define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT			10
 static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum a4xx_index_size val)
@@ -437,30 +488,40 @@ static inline uint32_t CP_DRAW_INDX_OFFS
 	return ((val) << CP_DRAW_INDX_OFFSET_5_INDX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_5_INDX_SIZE__MASK;
 }
 
-#define REG_CP_SET_DRAW_STATE_0					0x00000000
-#define CP_SET_DRAW_STATE_0_COUNT__MASK				0x0000ffff
-#define CP_SET_DRAW_STATE_0_COUNT__SHIFT			0
-static inline uint32_t CP_SET_DRAW_STATE_0_COUNT(uint32_t val)
+static inline uint32_t REG_CP_SET_DRAW_STATE_(uint32_t i0) { return 0x00000000 + 0x3*i0; }
+
+static inline uint32_t REG_CP_SET_DRAW_STATE__0(uint32_t i0) { return 0x00000000 + 0x3*i0; }
+#define CP_SET_DRAW_STATE__0_COUNT__MASK			0x0000ffff
+#define CP_SET_DRAW_STATE__0_COUNT__SHIFT			0
+static inline uint32_t CP_SET_DRAW_STATE__0_COUNT(uint32_t val)
 {
-	return ((val) << CP_SET_DRAW_STATE_0_COUNT__SHIFT) & CP_SET_DRAW_STATE_0_COUNT__MASK;
+	return ((val) << CP_SET_DRAW_STATE__0_COUNT__SHIFT) & CP_SET_DRAW_STATE__0_COUNT__MASK;
 }
-#define CP_SET_DRAW_STATE_0_DIRTY				0x00010000
-#define CP_SET_DRAW_STATE_0_DISABLE				0x00020000
-#define CP_SET_DRAW_STATE_0_DISABLE_ALL_GROUPS			0x00040000
-#define CP_SET_DRAW_STATE_0_LOAD_IMMED				0x00080000
-#define CP_SET_DRAW_STATE_0_GROUP_ID__MASK			0x1f000000
-#define CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT			24
-static inline uint32_t CP_SET_DRAW_STATE_0_GROUP_ID(uint32_t val)
+#define CP_SET_DRAW_STATE__0_DIRTY				0x00010000
+#define CP_SET_DRAW_STATE__0_DISABLE				0x00020000
+#define CP_SET_DRAW_STATE__0_DISABLE_ALL_GROUPS			0x00040000
+#define CP_SET_DRAW_STATE__0_LOAD_IMMED				0x00080000
+#define CP_SET_DRAW_STATE__0_GROUP_ID__MASK			0x1f000000
+#define CP_SET_DRAW_STATE__0_GROUP_ID__SHIFT			24
+static inline uint32_t CP_SET_DRAW_STATE__0_GROUP_ID(uint32_t val)
 {
-	return ((val) << CP_SET_DRAW_STATE_0_GROUP_ID__SHIFT) & CP_SET_DRAW_STATE_0_GROUP_ID__MASK;
+	return ((val) << CP_SET_DRAW_STATE__0_GROUP_ID__SHIFT) & CP_SET_DRAW_STATE__0_GROUP_ID__MASK;
 }
 
-#define REG_CP_SET_DRAW_STATE_1					0x00000001
-#define CP_SET_DRAW_STATE_1_ADDR__MASK				0xffffffff
-#define CP_SET_DRAW_STATE_1_ADDR__SHIFT				0
-static inline uint32_t CP_SET_DRAW_STATE_1_ADDR(uint32_t val)
+static inline uint32_t REG_CP_SET_DRAW_STATE__1(uint32_t i0) { return 0x00000001 + 0x3*i0; }
+#define CP_SET_DRAW_STATE__1_ADDR_LO__MASK			0xffffffff
+#define CP_SET_DRAW_STATE__1_ADDR_LO__SHIFT			0
+static inline uint32_t CP_SET_DRAW_STATE__1_ADDR_LO(uint32_t val)
 {
-	return ((val) << CP_SET_DRAW_STATE_1_ADDR__SHIFT) & CP_SET_DRAW_STATE_1_ADDR__MASK;
+	return ((val) << CP_SET_DRAW_STATE__1_ADDR_LO__SHIFT) & CP_SET_DRAW_STATE__1_ADDR_LO__MASK;
+}
+
+static inline uint32_t REG_CP_SET_DRAW_STATE__2(uint32_t i0) { return 0x00000002 + 0x3*i0; }
+#define CP_SET_DRAW_STATE__2_ADDR_HI__MASK			0xffffffff
+#define CP_SET_DRAW_STATE__2_ADDR_HI__SHIFT			0
+static inline uint32_t CP_SET_DRAW_STATE__2_ADDR_HI(uint32_t val)
+{
+	return ((val) << CP_SET_DRAW_STATE__2_ADDR_HI__SHIFT) & CP_SET_DRAW_STATE__2_ADDR_HI__MASK;
 }
 
 #define REG_CP_SET_BIN_0					0x00000000
@@ -533,5 +594,192 @@ static inline uint32_t CP_REG_TO_MEM_1_D
 	return ((val) << CP_REG_TO_MEM_1_DEST__SHIFT) & CP_REG_TO_MEM_1_DEST__MASK;
 }
 
+#define REG_CP_DISPATCH_COMPUTE_0				0x00000000
+
+#define REG_CP_DISPATCH_COMPUTE_1				0x00000001
+#define CP_DISPATCH_COMPUTE_1_X__MASK				0xffffffff
+#define CP_DISPATCH_COMPUTE_1_X__SHIFT				0
+static inline uint32_t CP_DISPATCH_COMPUTE_1_X(uint32_t val)
+{
+	return ((val) << CP_DISPATCH_COMPUTE_1_X__SHIFT) & CP_DISPATCH_COMPUTE_1_X__MASK;
+}
+
+#define REG_CP_DISPATCH_COMPUTE_2				0x00000002
+#define CP_DISPATCH_COMPUTE_2_Y__MASK				0xffffffff
+#define CP_DISPATCH_COMPUTE_2_Y__SHIFT				0
+static inline uint32_t CP_DISPATCH_COMPUTE_2_Y(uint32_t val)
+{
+	return ((val) << CP_DISPATCH_COMPUTE_2_Y__SHIFT) & CP_DISPATCH_COMPUTE_2_Y__MASK;
+}
+
+#define REG_CP_DISPATCH_COMPUTE_3				0x00000003
+#define CP_DISPATCH_COMPUTE_3_Z__MASK				0xffffffff
+#define CP_DISPATCH_COMPUTE_3_Z__SHIFT				0
+static inline uint32_t CP_DISPATCH_COMPUTE_3_Z(uint32_t val)
+{
+	return ((val) << CP_DISPATCH_COMPUTE_3_Z__SHIFT) & CP_DISPATCH_COMPUTE_3_Z__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_0				0x00000000
+#define CP_SET_RENDER_MODE_0_MODE__MASK				0x000001ff
+#define CP_SET_RENDER_MODE_0_MODE__SHIFT			0
+static inline uint32_t CP_SET_RENDER_MODE_0_MODE(enum render_mode_cmd val)
+{
+	return ((val) << CP_SET_RENDER_MODE_0_MODE__SHIFT) & CP_SET_RENDER_MODE_0_MODE__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_1				0x00000001
+#define CP_SET_RENDER_MODE_1_ADDR_0_LO__MASK			0xffffffff
+#define CP_SET_RENDER_MODE_1_ADDR_0_LO__SHIFT			0
+static inline uint32_t CP_SET_RENDER_MODE_1_ADDR_0_LO(uint32_t val)
+{
+	return ((val) << CP_SET_RENDER_MODE_1_ADDR_0_LO__SHIFT) & CP_SET_RENDER_MODE_1_ADDR_0_LO__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_2				0x00000002
+#define CP_SET_RENDER_MODE_2_ADDR_0_HI__MASK			0xffffffff
+#define CP_SET_RENDER_MODE_2_ADDR_0_HI__SHIFT			0
+static inline uint32_t CP_SET_RENDER_MODE_2_ADDR_0_HI(uint32_t val)
+{
+	return ((val) << CP_SET_RENDER_MODE_2_ADDR_0_HI__SHIFT) & CP_SET_RENDER_MODE_2_ADDR_0_HI__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_3				0x00000003
+#define CP_SET_RENDER_MODE_3_GMEM_ENABLE			0x00000010
+
+#define REG_CP_SET_RENDER_MODE_4				0x00000004
+
+#define REG_CP_SET_RENDER_MODE_5				0x00000005
+#define CP_SET_RENDER_MODE_5_ADDR_1_LEN__MASK			0xffffffff
+#define CP_SET_RENDER_MODE_5_ADDR_1_LEN__SHIFT			0
+static inline uint32_t CP_SET_RENDER_MODE_5_ADDR_1_LEN(uint32_t val)
+{
+	return ((val) << CP_SET_RENDER_MODE_5_ADDR_1_LEN__SHIFT) & CP_SET_RENDER_MODE_5_ADDR_1_LEN__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_6				0x00000006
+#define CP_SET_RENDER_MODE_6_ADDR_1_LO__MASK			0xffffffff
+#define CP_SET_RENDER_MODE_6_ADDR_1_LO__SHIFT			0
+static inline uint32_t CP_SET_RENDER_MODE_6_ADDR_1_LO(uint32_t val)
+{
+	return ((val) << CP_SET_RENDER_MODE_6_ADDR_1_LO__SHIFT) & CP_SET_RENDER_MODE_6_ADDR_1_LO__MASK;
+}
+
+#define REG_CP_SET_RENDER_MODE_7				0x00000007
+#define CP_SET_RENDER_MODE_7_ADDR_1_HI__MASK			0xffffffff
+#define CP_SET_RENDER_MODE_7_ADDR_1_HI__SHIFT			0
+static inline uint32_t CP_SET_RENDER_MODE_7_ADDR_1_HI(uint32_t val)
+{
+	return ((val) << CP_SET_RENDER_MODE_7_ADDR_1_HI__SHIFT) & CP_SET_RENDER_MODE_7_ADDR_1_HI__MASK;
+}
+
+#define REG_CP_PERFCOUNTER_ACTION_0				0x00000000
+
+#define REG_CP_PERFCOUNTER_ACTION_1				0x00000001
+#define CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__MASK			0xffffffff
+#define CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__SHIFT		0
+static inline uint32_t CP_PERFCOUNTER_ACTION_1_ADDR_0_LO(uint32_t val)
+{
+	return ((val) << CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__SHIFT) & CP_PERFCOUNTER_ACTION_1_ADDR_0_LO__MASK;
+}
+
+#define REG_CP_PERFCOUNTER_ACTION_2				0x00000002
+#define CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__MASK			0xffffffff
+#define CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__SHIFT		0
+static inline uint32_t CP_PERFCOUNTER_ACTION_2_ADDR_0_HI(uint32_t val)
+{
+	return ((val) << CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__SHIFT) & CP_PERFCOUNTER_ACTION_2_ADDR_0_HI__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_0					0x00000000
+#define CP_EVENT_WRITE_0_EVENT__MASK				0x000000ff
+#define CP_EVENT_WRITE_0_EVENT__SHIFT				0
+static inline uint32_t CP_EVENT_WRITE_0_EVENT(enum vgt_event_type val)
+{
+	return ((val) << CP_EVENT_WRITE_0_EVENT__SHIFT) & CP_EVENT_WRITE_0_EVENT__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_1					0x00000001
+#define CP_EVENT_WRITE_1_ADDR_0_LO__MASK			0xffffffff
+#define CP_EVENT_WRITE_1_ADDR_0_LO__SHIFT			0
+static inline uint32_t CP_EVENT_WRITE_1_ADDR_0_LO(uint32_t val)
+{
+	return ((val) << CP_EVENT_WRITE_1_ADDR_0_LO__SHIFT) & CP_EVENT_WRITE_1_ADDR_0_LO__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_2					0x00000002
+#define CP_EVENT_WRITE_2_ADDR_0_HI__MASK			0xffffffff
+#define CP_EVENT_WRITE_2_ADDR_0_HI__SHIFT			0
+static inline uint32_t CP_EVENT_WRITE_2_ADDR_0_HI(uint32_t val)
+{
+	return ((val) << CP_EVENT_WRITE_2_ADDR_0_HI__SHIFT) & CP_EVENT_WRITE_2_ADDR_0_HI__MASK;
+}
+
+#define REG_CP_EVENT_WRITE_3					0x00000003
+
+#define REG_CP_BLIT_0						0x00000000
+#define CP_BLIT_0_OP__MASK					0x0000000f
+#define CP_BLIT_0_OP__SHIFT					0
+static inline uint32_t CP_BLIT_0_OP(enum cp_blit_cmd val)
+{
+	return ((val) << CP_BLIT_0_OP__SHIFT) & CP_BLIT_0_OP__MASK;
+}
+
+#define REG_CP_BLIT_1						0x00000001
+#define CP_BLIT_1_SRC_X1__MASK					0x0000ffff
+#define CP_BLIT_1_SRC_X1__SHIFT					0
+static inline uint32_t CP_BLIT_1_SRC_X1(uint32_t val)
+{
+	return ((val) << CP_BLIT_1_SRC_X1__SHIFT) & CP_BLIT_1_SRC_X1__MASK;
+}
+#define CP_BLIT_1_SRC_Y1__MASK					0xffff0000
+#define CP_BLIT_1_SRC_Y1__SHIFT					16
+static inline uint32_t CP_BLIT_1_SRC_Y1(uint32_t val)
+{
+	return ((val) << CP_BLIT_1_SRC_Y1__SHIFT) & CP_BLIT_1_SRC_Y1__MASK;
+}
+
+#define REG_CP_BLIT_2						0x00000002
+#define CP_BLIT_2_SRC_X2__MASK					0x0000ffff
+#define CP_BLIT_2_SRC_X2__SHIFT					0
+static inline uint32_t CP_BLIT_2_SRC_X2(uint32_t val)
+{
+	return ((val) << CP_BLIT_2_SRC_X2__SHIFT) & CP_BLIT_2_SRC_X2__MASK;
+}
+#define CP_BLIT_2_SRC_Y2__MASK					0xffff0000
+#define CP_BLIT_2_SRC_Y2__SHIFT					16
+static inline uint32_t CP_BLIT_2_SRC_Y2(uint32_t val)
+{
+	return ((val) << CP_BLIT_2_SRC_Y2__SHIFT) & CP_BLIT_2_SRC_Y2__MASK;
+}
+
+#define REG_CP_BLIT_3						0x00000003
+#define CP_BLIT_3_DST_X1__MASK					0x0000ffff
+#define CP_BLIT_3_DST_X1__SHIFT					0
+static inline uint32_t CP_BLIT_3_DST_X1(uint32_t val)
+{
+	return ((val) << CP_BLIT_3_DST_X1__SHIFT) & CP_BLIT_3_DST_X1__MASK;
+}
+#define CP_BLIT_3_DST_Y1__MASK					0xffff0000
+#define CP_BLIT_3_DST_Y1__SHIFT					16
+static inline uint32_t CP_BLIT_3_DST_Y1(uint32_t val)
+{
+	return ((val) << CP_BLIT_3_DST_Y1__SHIFT) & CP_BLIT_3_DST_Y1__MASK;
+}
+
+#define REG_CP_BLIT_4						0x00000004
+#define CP_BLIT_4_DST_X2__MASK					0x0000ffff
+#define CP_BLIT_4_DST_X2__SHIFT					0
+static inline uint32_t CP_BLIT_4_DST_X2(uint32_t val)
+{
+	return ((val) << CP_BLIT_4_DST_X2__SHIFT) & CP_BLIT_4_DST_X2__MASK;
+}
+#define CP_BLIT_4_DST_Y2__MASK					0xffff0000
+#define CP_BLIT_4_DST_Y2__SHIFT					16
+static inline uint32_t CP_BLIT_4_DST_Y2(uint32_t val)
+{
+	return ((val) << CP_BLIT_4_DST_Y2__SHIFT) & CP_BLIT_4_DST_Y2__MASK;
+}
+
 
 #endif /* ADRENO_PM4_XML */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/dsi_host.c	2017-02-12 16:03:20.000000000 -0500
@@ -982,7 +982,7 @@ static int dsi_tx_buf_alloc(struct msm_d
 	struct drm_device *dev = msm_host->dev;
 	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	int ret;
-	u32 iova;
+	uint64_t iova;
 
 	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
 		mutex_lock(&dev->struct_mutex);
@@ -1147,7 +1147,7 @@ static int dsi_cmd_dma_tx(struct msm_dsi
 {
 	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	int ret;
-	u32 dma_base;
+	uint64_t dma_base;
 	bool triggered;
 
 	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/dsi.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/dsi/sfpb.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/edp/edp.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/edp/edp.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/edp/edp.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/edp/edp.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/hdmi/hdmi.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/hdmi/qfprom.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,8 @@ msm-y := \
 	adreno/adreno_gpu.o \
 	adreno/a3xx_gpu.o \
 	adreno/a4xx_gpu.o \
+	adreno/a5xx_gpu.o \
+	adreno/a5xx_power.o \
 	hdmi/hdmi.o \
 	hdmi/hdmi_audio.o \
 	hdmi/hdmi_bridge.o \
@@ -37,6 +39,7 @@ msm-y := \
 	mdp/mdp5/mdp5_irq.o \
 	mdp/mdp5/mdp5_mdss.o \
 	mdp/mdp5/mdp5_kms.o \
+	mdp/mdp5/mdp5_pipe.o \
 	mdp/mdp5/mdp5_plane.o \
 	mdp/mdp5/mdp5_smp.o \
 	msm_atomic.o \
@@ -48,6 +51,7 @@ msm-y := \
 	msm_gem_prime.o \
 	msm_gem_shrinker.o \
 	msm_gem_submit.o \
+	msm_gem_vma.o \
 	msm_gpu.o \
 	msm_iommu.o \
 	msm_perf.o \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -373,7 +373,7 @@ static void update_cursor(struct drm_crt
 	if (mdp4_crtc->cursor.stale) {
 		struct drm_gem_object *next_bo = mdp4_crtc->cursor.next_bo;
 		struct drm_gem_object *prev_bo = mdp4_crtc->cursor.scanout_bo;
-		uint32_t iova = mdp4_crtc->cursor.next_iova;
+		uint64_t iova = mdp4_crtc->cursor.next_iova;
 
 		if (next_bo) {
 			/* take a obj ref + iova ref when we start scanning out: */
@@ -418,7 +418,7 @@ static int mdp4_crtc_cursor_set(struct d
 	struct drm_device *dev = crtc->dev;
 	struct drm_gem_object *cursor_bo, *old_bo;
 	unsigned long flags;
-	uint32_t iova;
+	uint64_t iova;
 	int ret;
 
 	if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <drm/drm_print.h>
 
 #include "msm_drv.h"
 #include "mdp4_kms.h"
@@ -29,7 +30,16 @@ void mdp4_set_irqmask(struct mdp_kms *md
 
 static void mdp4_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
 {
+	struct mdp4_kms *mdp4_kms = container_of(irq, struct mdp4_kms, error_handler);
+	static DEFINE_RATELIMIT_STATE(rs, 5*HZ, 1);
+	extern bool dumpstate;
+
 	DRM_ERROR_RATELIMITED("errors: %08x\n", irqstatus);
+
+	if (dumpstate && __ratelimit(&rs)) {
+		struct drm_printer p = drm_info_printer(mdp4_kms->dev->dev);
+		drm_state_dump(mdp4_kms->dev, &p);
+	}
 }
 
 void mdp4_irq_preinstall(struct msm_kms *kms)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 
 
 #include "msm_drv.h"
+#include "msm_gem.h"
 #include "msm_mmu.h"
 #include "mdp4_kms.h"
 
@@ -159,17 +160,18 @@ static void mdp4_destroy(struct msm_kms
 {
 	struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
 	struct device *dev = mdp4_kms->dev->dev;
-	struct msm_mmu *mmu = mdp4_kms->mmu;
-
-	if (mmu) {
-		mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
-		mmu->funcs->destroy(mmu);
-	}
+	struct msm_gem_address_space *aspace = mdp4_kms->aspace;
 
 	if (mdp4_kms->blank_cursor_iova)
 		msm_gem_put_iova(mdp4_kms->blank_cursor_bo, mdp4_kms->id);
 	drm_gem_object_unreference_unlocked(mdp4_kms->blank_cursor_bo);
 
+	if (aspace) {
+		aspace->mmu->funcs->detach(aspace->mmu,
+				iommu_ports, ARRAY_SIZE(iommu_ports));
+		msm_gem_address_space_destroy(aspace);
+	}
+
 	if (mdp4_kms->rpm_enabled)
 		pm_runtime_disable(dev);
 
@@ -440,7 +442,7 @@ struct msm_kms *mdp4_kms_init(struct drm
 	struct mdp4_platform_config *config = mdp4_get_config(pdev);
 	struct mdp4_kms *mdp4_kms;
 	struct msm_kms *kms = NULL;
-	struct msm_mmu *mmu;
+	struct msm_gem_address_space *aspace;
 	int irq, ret;
 
 	mdp4_kms = kzalloc(sizeof(*mdp4_kms), GFP_KERNEL);
@@ -531,24 +533,26 @@ struct msm_kms *mdp4_kms_init(struct drm
 	mdelay(16);
 
 	if (config->iommu) {
-		mmu = msm_iommu_new(&pdev->dev, config->iommu);
-		if (IS_ERR(mmu)) {
-			ret = PTR_ERR(mmu);
+		aspace = msm_gem_address_space_create(&pdev->dev,
+				config->iommu, "mdp4");
+		if (IS_ERR(aspace)) {
+			ret = PTR_ERR(aspace);
 			goto fail;
 		}
-		ret = mmu->funcs->attach(mmu, iommu_ports,
+
+		mdp4_kms->aspace = aspace;
+
+		ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports,
 				ARRAY_SIZE(iommu_ports));
 		if (ret)
 			goto fail;
-
-		mdp4_kms->mmu = mmu;
 	} else {
 		dev_info(dev->dev, "no iommu, fallback to phys "
 				"contig buffers for scanout\n");
-		mmu = NULL;
+		aspace = NULL;
 	}
 
-	mdp4_kms->id = msm_register_mmu(dev, mmu);
+	mdp4_kms->id = msm_register_address_space(dev, aspace);
 	if (mdp4_kms->id < 0) {
 		ret = mdp4_kms->id;
 		dev_err(dev->dev, "failed to register mdp4 iommu: %d\n", ret);
@@ -598,6 +602,10 @@ static struct mdp4_platform_config *mdp4
 	/* TODO: Chips that aren't apq8064 have a 200 Mhz max_clk */
 	config.max_clk = 266667000;
 	config.iommu = iommu_domain_alloc(&platform_bus_type);
+	if (config.iommu) {
+		config.iommu->geometry.aperture_start = 0x1000;
+		config.iommu->geometry.aperture_end = 0xffffffff;
+	}
 
 	return &config;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,7 @@ struct mdp4_kms {
 	struct clk *pclk;
 	struct clk *lut_clk;
 	struct clk *axi_clk;
-	struct msm_mmu *mmu;
+	struct msm_gem_address_space *aspace;
 
 	struct mdp_irq error_handler;
 
@@ -51,7 +51,7 @@ struct mdp4_kms {
 
 	/* empty/blank cursor bo to use when cursor is "disabled" */
 	struct drm_gem_object *blank_cursor_bo;
-	uint32_t blank_cursor_iova;
+	uint64_t blank_cursor_iova;
 };
 #define to_mdp4_kms(x) container_of(x, struct mdp4_kms, base)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@ enum mdp4_frame_format mdp4_get_frame_fo
 {
 	bool is_tile = false;
 
-	if (fb->modifier[1] == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
+	if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
 		is_tile = true;
 
 	if (fb->pixel_format == DRM_FORMAT_NV12 && is_tile)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c	2017-02-12 16:03:20.000000000 -0500
@@ -550,6 +550,10 @@ static struct mdp5_cfg_platform *mdp5_ge
 	static struct mdp5_cfg_platform config = {};
 
 	config.iommu = iommu_domain_alloc(&platform_bus_type);
+	if (config.iommu) {
+		config.iommu->geometry.aperture_start = 0x1000;
+		config.iommu->geometry.aperture_end = 0xffffffff;
+	}
 
 	return &config;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,11 +27,8 @@
 #define CURSOR_WIDTH	64
 #define CURSOR_HEIGHT	64
 
-#define SSPP_MAX	(SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */
-
 struct mdp5_crtc {
 	struct drm_crtc base;
-	char name[8];
 	int id;
 	bool enabled;
 
@@ -102,7 +99,7 @@ static u32 crtc_flush(struct drm_crtc *c
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 
-	DBG("%s: flush=%08x", mdp5_crtc->name, flush_mask);
+	DBG("%s: flush=%08x", crtc->name, flush_mask);
 	return mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask);
 }
 
@@ -136,7 +133,6 @@ static void complete_flip(struct drm_crt
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct drm_pending_vblank_event *event;
-	struct drm_plane *plane;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
@@ -148,16 +144,12 @@ static void complete_flip(struct drm_crt
 		 */
 		if (!file || (event->base.file_priv == file)) {
 			mdp5_crtc->event = NULL;
-			DBG("%s: send event: %p", mdp5_crtc->name, event);
+			DBG("%s: send event: %p", crtc->name, event);
 			drm_crtc_send_vblank_event(crtc, event);
 		}
 	}
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 
-	drm_atomic_crtc_for_each_plane(plane, crtc) {
-		mdp5_plane_complete_flip(plane);
-	}
-
 	if (mdp5_crtc->ctl && !crtc->state->enable) {
 		/* set STAGE_UNUSED for all layers */
 		mdp5_ctl_blend(mdp5_crtc->ctl, NULL, 0, 0);
@@ -295,7 +287,7 @@ static void mdp5_crtc_mode_set_nofb(stru
 	mode = &crtc->state->adjusted_mode;
 
 	DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-			mdp5_crtc->name, mode->base.id, mode->name,
+			crtc->name, mode->base.id, mode->name,
 			mode->vrefresh, mode->clock,
 			mode->hdisplay, mode->hsync_start,
 			mode->hsync_end, mode->htotal,
@@ -315,7 +307,7 @@ static void mdp5_crtc_disable(struct drm
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 	struct mdp5_kms *mdp5_kms = get_kms(crtc);
 
-	DBG("%s", mdp5_crtc->name);
+	DBG("%s", crtc->name);
 
 	if (WARN_ON(!mdp5_crtc->enabled))
 		return;
@@ -334,7 +326,7 @@ static void mdp5_crtc_enable(struct drm_
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 	struct mdp5_kms *mdp5_kms = get_kms(crtc);
 
-	DBG("%s", mdp5_crtc->name);
+	DBG("%s", crtc->name);
 
 	if (WARN_ON(mdp5_crtc->enabled))
 		return;
@@ -372,7 +364,6 @@ static bool is_fullscreen(struct drm_crt
 static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 		struct drm_crtc_state *state)
 {
-	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
 	struct mdp5_kms *mdp5_kms = get_kms(crtc);
 	struct drm_plane *plane;
 	struct drm_device *dev = crtc->dev;
@@ -381,7 +372,7 @@ static int mdp5_crtc_atomic_check(struct
 	const struct drm_plane_state *pstate;
 	int cnt = 0, base = 0, i;
 
-	DBG("%s: check", mdp5_crtc->name);
+	DBG("%s: check", crtc->name);
 
 	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
 		pstates[cnt].plane = plane;
@@ -405,14 +396,14 @@ static int mdp5_crtc_atomic_check(struct
 	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
 
 	if ((cnt + base) >= hw_cfg->lm.nb_stages) {
-		dev_err(dev->dev, "too many planes!\n");
+		dev_err(dev->dev, "too many planes! cnt=%d, base=%d\n", cnt, base);
 		return -EINVAL;
 	}
 
 	for (i = 0; i < cnt; i++) {
 		pstates[i].state->stage = STAGE_BASE + i + base;
-		DBG("%s: assign pipe %s on stage=%d", mdp5_crtc->name,
-				pipe2name(mdp5_plane_pipe(pstates[i].plane)),
+		DBG("%s: assign pipe %s on stage=%d", crtc->name,
+				pstates[i].plane->name,
 				pstates[i].state->stage);
 	}
 
@@ -422,8 +413,7 @@ static int mdp5_crtc_atomic_check(struct
 static void mdp5_crtc_atomic_begin(struct drm_crtc *crtc,
 				   struct drm_crtc_state *old_crtc_state)
 {
-	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
-	DBG("%s: begin", mdp5_crtc->name);
+	DBG("%s: begin", crtc->name);
 }
 
 static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -433,7 +423,7 @@ static void mdp5_crtc_atomic_flush(struc
 	struct drm_device *dev = crtc->dev;
 	unsigned long flags;
 
-	DBG("%s: event: %p", mdp5_crtc->name, crtc->state->event);
+	DBG("%s: event: %p", crtc->name, crtc->state->event);
 
 	WARN_ON(mdp5_crtc->event);
 
@@ -499,7 +489,8 @@ static int mdp5_crtc_cursor_set(struct d
 	struct drm_device *dev = crtc->dev;
 	struct mdp5_kms *mdp5_kms = get_kms(crtc);
 	struct drm_gem_object *cursor_bo, *old_bo = NULL;
-	uint32_t blendcfg, cursor_addr, stride;
+	uint32_t blendcfg, stride;
+	uint64_t cursor_addr;
 	int ret, lm;
 	enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL;
 	uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0);
@@ -653,7 +644,7 @@ static void mdp5_crtc_err_irq(struct mdp
 {
 	struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc, err);
 
-	DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
+	DBG("%s: error: %08x", mdp5_crtc->base.name, irqstatus);
 }
 
 static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
@@ -775,9 +766,6 @@ struct drm_crtc *mdp5_crtc_init(struct d
 	mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
 	mdp5_crtc->err.irq = mdp5_crtc_err_irq;
 
-	snprintf(mdp5_crtc->name, sizeof(mdp5_crtc->name), "%s:%d",
-			pipe2name(mdp5_plane_pipe(plane)), id);
-
 	drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs,
 				  NULL);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,8 @@
 
 #include <linux/irq.h>
 
+#include <drm/drm_print.h>
+
 #include "msm_drv.h"
 #include "mdp5_kms.h"
 
@@ -30,7 +32,18 @@ void mdp5_set_irqmask(struct mdp_kms *md
 
 static void mdp5_irq_error_handler(struct mdp_irq *irq, uint32_t irqstatus)
 {
+	struct mdp5_kms *mdp5_kms = container_of(irq, struct mdp5_kms, error_handler);
+	static DEFINE_RATELIMIT_STATE(rs, 5*HZ, 1);
+	extern bool dumpstate;
+
 	DRM_ERROR_RATELIMITED("errors: %08x\n", irqstatus);
+
+	if (dumpstate && __ratelimit(&rs)) {
+		struct drm_printer p = drm_info_printer(mdp5_kms->dev->dev);
+		drm_state_dump(mdp5_kms->dev, &p);
+		if (mdp5_kms->smp)
+			mdp5_smp_dump(mdp5_kms->smp, &p);
+	}
 }
 
 void mdp5_irq_preinstall(struct msm_kms *kms)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@
 #include <linux/of_irq.h>
 
 #include "msm_drv.h"
+#include "msm_gem.h"
 #include "msm_mmu.h"
 #include "mdp5_kms.h"
 
@@ -71,21 +72,57 @@ static int mdp5_hw_init(struct msm_kms *
 	return 0;
 }
 
+struct mdp5_state *mdp5_get_state(struct drm_atomic_state *s)
+{
+	struct msm_drm_private *priv = s->dev->dev_private;
+	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+	struct msm_kms_state *state = to_kms_state(s);
+	struct mdp5_state *new_state;
+	int ret;
+
+	if (state->state)
+		return state->state;
+
+	ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
+	if (ret)
+		return ERR_PTR(ret);
+
+	new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
+	if (!new_state)
+		return ERR_PTR(-ENOMEM);
+
+	/* Copy state: */
+	new_state->hwpipe = mdp5_kms->state->hwpipe;
+	if (mdp5_kms->smp)
+		new_state->smp = mdp5_kms->state->smp;
+
+	state->state = new_state;
+
+	return new_state;
+}
+
+static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
+{
+	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+	swap(to_kms_state(state)->state, mdp5_kms->state);
+}
+
 static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 {
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+
 	mdp5_enable(mdp5_kms);
+
+	if (mdp5_kms->smp)
+		mdp5_smp_prepare_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
 }
 
 static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 {
-	int i;
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
-	struct drm_plane *plane;
-	struct drm_plane_state *plane_state;
 
-	for_each_plane_in_state(state, plane, plane_state, i)
-		mdp5_plane_complete_commit(plane, plane_state);
+	if (mdp5_kms->smp)
+		mdp5_smp_complete_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
 
 	mdp5_disable(mdp5_kms);
 }
@@ -117,13 +154,65 @@ static int mdp5_set_split_display(struct
 static void mdp5_kms_destroy(struct msm_kms *kms)
 {
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
-	struct msm_mmu *mmu = mdp5_kms->mmu;
+	struct msm_gem_address_space *aspace = mdp5_kms->aspace;
+	int i;
 
-	if (mmu) {
-		mmu->funcs->detach(mmu, iommu_ports, ARRAY_SIZE(iommu_ports));
-		mmu->funcs->destroy(mmu);
+	for (i = 0; i < mdp5_kms->num_hwpipes; i++)
+		mdp5_pipe_destroy(mdp5_kms->hwpipes[i]);
+
+	if (aspace) {
+		aspace->mmu->funcs->detach(aspace->mmu,
+				iommu_ports, ARRAY_SIZE(iommu_ports));
+		msm_gem_address_space_destroy(aspace);
+	}
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int smp_show(struct seq_file *m, void *arg)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct msm_drm_private *priv = dev->dev_private;
+	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+	struct drm_printer p = drm_seq_file_printer(m);
+
+	if (!mdp5_kms->smp) {
+		drm_printf(&p, "no SMP pool\n");
+		return 0;
+	}
+
+	mdp5_smp_dump(mdp5_kms->smp, &p);
+
+	return 0;
+}
+
+static struct drm_info_list mdp5_debugfs_list[] = {
+		{"smp", smp_show },
+};
+
+static int mdp5_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
+{
+	struct drm_device *dev = minor->dev;
+	int ret;
+
+	ret = drm_debugfs_create_files(mdp5_debugfs_list,
+			ARRAY_SIZE(mdp5_debugfs_list),
+			minor->debugfs_root, minor);
+
+	if (ret) {
+		dev_err(dev->dev, "could not install mdp5_debugfs_list\n");
+		return ret;
 	}
+
+	return 0;
+}
+
+static void mdp5_kms_debugfs_cleanup(struct msm_kms *kms, struct drm_minor *minor)
+{
+	drm_debugfs_remove_files(mdp5_debugfs_list,
+			ARRAY_SIZE(mdp5_debugfs_list), minor);
 }
+#endif
 
 static const struct mdp_kms_funcs kms_funcs = {
 	.base = {
@@ -134,6 +223,7 @@ static const struct mdp_kms_funcs kms_fu
 		.irq             = mdp5_irq,
 		.enable_vblank   = mdp5_enable_vblank,
 		.disable_vblank  = mdp5_disable_vblank,
+		.swap_state      = mdp5_swap_state,
 		.prepare_commit  = mdp5_prepare_commit,
 		.complete_commit = mdp5_complete_commit,
 		.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
@@ -141,6 +231,10 @@ static const struct mdp_kms_funcs kms_fu
 		.round_pixclk    = mdp5_round_pixclk,
 		.set_split_display = mdp5_set_split_display,
 		.destroy         = mdp5_kms_destroy,
+#ifdef CONFIG_DEBUG_FS
+		.debugfs_init    = mdp5_kms_debugfs_init,
+		.debugfs_cleanup = mdp5_kms_debugfs_cleanup,
+#endif
 	},
 	.set_irqmask         = mdp5_set_irqmask,
 };
@@ -321,15 +415,6 @@ static int modeset_init_intf(struct mdp5
 
 static int modeset_init(struct mdp5_kms *mdp5_kms)
 {
-	static const enum mdp5_pipe crtcs[] = {
-			SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
-	};
-	static const enum mdp5_pipe vig_planes[] = {
-			SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3,
-	};
-	static const enum mdp5_pipe dma_planes[] = {
-			SSPP_DMA0, SSPP_DMA1,
-	};
 	struct drm_device *dev = mdp5_kms->dev;
 	struct msm_drm_private *priv = dev->dev_private;
 	const struct mdp5_cfg_hw *hw_cfg;
@@ -337,58 +422,35 @@ static int modeset_init(struct mdp5_kms
 
 	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
 
-	/* construct CRTCs and their private planes: */
-	for (i = 0; i < hw_cfg->pipe_rgb.count; i++) {
+	/* Construct planes equaling the number of hw pipes, and CRTCs
+	 * for the N layer-mixers (LM).  The first N planes become primary
+	 * planes for the CRTCs, with the remainder as overlay planes:
+	 */
+	for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
+		bool primary = i < mdp5_cfg->lm.count;
 		struct drm_plane *plane;
 		struct drm_crtc *crtc;
 
-		plane = mdp5_plane_init(dev, crtcs[i], true,
-			hw_cfg->pipe_rgb.base[i], hw_cfg->pipe_rgb.caps);
+		plane = mdp5_plane_init(dev, primary);
 		if (IS_ERR(plane)) {
 			ret = PTR_ERR(plane);
-			dev_err(dev->dev, "failed to construct plane for %s (%d)\n",
-					pipe2name(crtcs[i]), ret);
+			dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret);
 			goto fail;
 		}
+		priv->planes[priv->num_planes++] = plane;
+
+		if (!primary)
+			continue;
 
 		crtc  = mdp5_crtc_init(dev, plane, i);
 		if (IS_ERR(crtc)) {
 			ret = PTR_ERR(crtc);
-			dev_err(dev->dev, "failed to construct crtc for %s (%d)\n",
-					pipe2name(crtcs[i]), ret);
+			dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
 			goto fail;
 		}
 		priv->crtcs[priv->num_crtcs++] = crtc;
 	}
 
-	/* Construct video planes: */
-	for (i = 0; i < hw_cfg->pipe_vig.count; i++) {
-		struct drm_plane *plane;
-
-		plane = mdp5_plane_init(dev, vig_planes[i], false,
-			hw_cfg->pipe_vig.base[i], hw_cfg->pipe_vig.caps);
-		if (IS_ERR(plane)) {
-			ret = PTR_ERR(plane);
-			dev_err(dev->dev, "failed to construct %s plane: %d\n",
-					pipe2name(vig_planes[i]), ret);
-			goto fail;
-		}
-	}
-
-	/* DMA planes */
-	for (i = 0; i < hw_cfg->pipe_dma.count; i++) {
-		struct drm_plane *plane;
-
-		plane = mdp5_plane_init(dev, dma_planes[i], false,
-				hw_cfg->pipe_dma.base[i], hw_cfg->pipe_dma.caps);
-		if (IS_ERR(plane)) {
-			ret = PTR_ERR(plane);
-			dev_err(dev->dev, "failed to construct %s plane: %d\n",
-					pipe2name(dma_planes[i]), ret);
-			goto fail;
-		}
-	}
-
 	/* Construct encoders and modeset initialize connector devices
 	 * for each external display interface.
 	 */
@@ -564,7 +626,7 @@ struct msm_kms *mdp5_kms_init(struct drm
 	struct mdp5_kms *mdp5_kms;
 	struct mdp5_cfg *config;
 	struct msm_kms *kms;
-	struct msm_mmu *mmu;
+	struct msm_gem_address_space *aspace;
 	int irq, i, ret;
 
 	/* priv->kms would have been populated by the MDP5 driver */
@@ -606,30 +668,29 @@ struct msm_kms *mdp5_kms_init(struct drm
 	mdelay(16);
 
 	if (config->platform.iommu) {
-		mmu = msm_iommu_new(&pdev->dev, config->platform.iommu);
-		if (IS_ERR(mmu)) {
-			ret = PTR_ERR(mmu);
-			dev_err(&pdev->dev, "failed to init iommu: %d\n", ret);
-			iommu_domain_free(config->platform.iommu);
+		aspace = msm_gem_address_space_create(&pdev->dev,
+				config->platform.iommu, "mdp5");
+		if (IS_ERR(aspace)) {
+			ret = PTR_ERR(aspace);
 			goto fail;
 		}
 
-		ret = mmu->funcs->attach(mmu, iommu_ports,
+		mdp5_kms->aspace = aspace;
+
+		ret = aspace->mmu->funcs->attach(aspace->mmu, iommu_ports,
 				ARRAY_SIZE(iommu_ports));
 		if (ret) {
 			dev_err(&pdev->dev, "failed to attach iommu: %d\n",
 				ret);
-			mmu->funcs->destroy(mmu);
 			goto fail;
 		}
 	} else {
 		dev_info(&pdev->dev,
 			 "no iommu, fallback to phys contig buffers for scanout\n");
-		mmu = NULL;
+		aspace = NULL;;
 	}
-	mdp5_kms->mmu = mmu;
 
-	mdp5_kms->id = msm_register_mmu(dev, mmu);
+	mdp5_kms->id = msm_register_address_space(dev, aspace);
 	if (mdp5_kms->id < 0) {
 		ret = mdp5_kms->id;
 		dev_err(&pdev->dev, "failed to register mdp5 iommu: %d\n", ret);
@@ -644,8 +705,8 @@ struct msm_kms *mdp5_kms_init(struct drm
 
 	dev->mode_config.min_width = 0;
 	dev->mode_config.min_height = 0;
-	dev->mode_config.max_width = config->hw->lm.max_width;
-	dev->mode_config.max_height = config->hw->lm.max_height;
+	dev->mode_config.max_width = 0xffff;
+	dev->mode_config.max_height = 0xffff;
 
 	dev->driver->get_vblank_timestamp = mdp5_get_vblank_timestamp;
 	dev->driver->get_scanout_position = mdp5_get_scanoutpos;
@@ -673,6 +734,69 @@ static void mdp5_destroy(struct platform
 
 	if (mdp5_kms->rpm_enabled)
 		pm_runtime_disable(&pdev->dev);
+
+	kfree(mdp5_kms->state);
+}
+
+static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
+		const enum mdp5_pipe *pipes, const uint32_t *offsets,
+		uint32_t caps)
+{
+	struct drm_device *dev = mdp5_kms->dev;
+	int i, ret;
+
+	for (i = 0; i < cnt; i++) {
+		struct mdp5_hw_pipe *hwpipe;
+
+		hwpipe = mdp5_pipe_init(pipes[i], offsets[i], caps);
+		if (IS_ERR(hwpipe)) {
+			ret = PTR_ERR(hwpipe);
+			dev_err(dev->dev, "failed to construct pipe for %s (%d)\n",
+					pipe2name(pipes[i]), ret);
+			return ret;
+		}
+		hwpipe->idx = mdp5_kms->num_hwpipes;
+		mdp5_kms->hwpipes[mdp5_kms->num_hwpipes++] = hwpipe;
+	}
+
+	return 0;
+}
+
+static int hwpipe_init(struct mdp5_kms *mdp5_kms)
+{
+	static const enum mdp5_pipe rgb_planes[] = {
+			SSPP_RGB0, SSPP_RGB1, SSPP_RGB2, SSPP_RGB3,
+	};
+	static const enum mdp5_pipe vig_planes[] = {
+			SSPP_VIG0, SSPP_VIG1, SSPP_VIG2, SSPP_VIG3,
+	};
+	static const enum mdp5_pipe dma_planes[] = {
+			SSPP_DMA0, SSPP_DMA1,
+	};
+	const struct mdp5_cfg_hw *hw_cfg;
+	int ret;
+
+	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
+
+	/* Construct RGB pipes: */
+	ret = construct_pipes(mdp5_kms, hw_cfg->pipe_rgb.count, rgb_planes,
+			hw_cfg->pipe_rgb.base, hw_cfg->pipe_rgb.caps);
+	if (ret)
+		return ret;
+
+	/* Construct video (VIG) pipes: */
+	ret = construct_pipes(mdp5_kms, hw_cfg->pipe_vig.count, vig_planes,
+			hw_cfg->pipe_vig.base, hw_cfg->pipe_vig.caps);
+	if (ret)
+		return ret;
+
+	/* Construct DMA pipes: */
+	ret = construct_pipes(mdp5_kms, hw_cfg->pipe_dma.count, dma_planes,
+			hw_cfg->pipe_dma.base, hw_cfg->pipe_dma.caps);
+	if (ret)
+		return ret;
+
+	return 0;
 }
 
 static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
@@ -696,6 +820,13 @@ static int mdp5_init(struct platform_dev
 	mdp5_kms->dev = dev;
 	mdp5_kms->pdev = pdev;
 
+	drm_modeset_lock_init(&mdp5_kms->state_lock);
+	mdp5_kms->state = kzalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
+	if (!mdp5_kms->state) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
 	mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5");
 	if (IS_ERR(mdp5_kms->mmio)) {
 		ret = PTR_ERR(mdp5_kms->mmio);
@@ -749,7 +880,7 @@ static int mdp5_init(struct platform_dev
 	 * this section initializes the SMP:
 	 */
 	if (mdp5_kms->caps & MDP_CAP_SMP) {
-		mdp5_kms->smp = mdp5_smp_init(mdp5_kms->dev, &config->hw->smp);
+		mdp5_kms->smp = mdp5_smp_init(mdp5_kms, &config->hw->smp);
 		if (IS_ERR(mdp5_kms->smp)) {
 			ret = PTR_ERR(mdp5_kms->smp);
 			mdp5_kms->smp = NULL;
@@ -764,6 +895,10 @@ static int mdp5_init(struct platform_dev
 		goto fail;
 	}
 
+	ret = hwpipe_init(mdp5_kms);
+	if (ret)
+		goto fail;
+
 	/* set uninit-ed kms */
 	priv->kms = &mdp5_kms->base.base;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,11 @@
 #include "mdp5_cfg.h"	/* must be included before mdp5.xml.h */
 #include "mdp5.xml.h"
 #include "mdp5_ctl.h"
+#include "mdp5_pipe.h"
 #include "mdp5_smp.h"
 
+struct mdp5_state;
+
 struct mdp5_kms {
 	struct mdp_kms base;
 
@@ -33,13 +36,21 @@ struct mdp5_kms {
 
 	struct platform_device *pdev;
 
+	unsigned num_hwpipes;
+	struct mdp5_hw_pipe *hwpipes[SSPP_MAX];
+
 	struct mdp5_cfg_handler *cfg;
 	uint32_t caps;	/* MDP capabilities (MDP_CAP_XXX bits) */
 
+	/**
+	 * Global atomic state.  Do not access directly, use mdp5_get_state()
+	 */
+	struct mdp5_state *state;
+	struct drm_modeset_lock state_lock;
 
 	/* mapper-id used to request GEM buffer mapped for scanout: */
 	int id;
-	struct msm_mmu *mmu;
+	struct msm_gem_address_space *aspace;
 
 	struct mdp5_smp *smp;
 	struct mdp5_ctl_manager *ctlm;
@@ -65,9 +76,27 @@ struct mdp5_kms {
 };
 #define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
 
+/* Global atomic state for tracking resources that are shared across
+ * multiple kms objects (planes/crtcs/etc).
+ *
+ * For atomic updates which require modifying global state,
+ */
+struct mdp5_state {
+	struct mdp5_hw_pipe_state hwpipe;
+	struct mdp5_smp_state smp;
+};
+
+struct mdp5_state *__must_check
+mdp5_get_state(struct drm_atomic_state *s);
+
+/* Atomic plane state.  Subclasses the base drm_plane_state in order to
+ * track assigned hwpipe and hw specific state.
+ */
 struct mdp5_plane_state {
 	struct drm_plane_state base;
 
+	struct mdp5_hw_pipe *hwpipe;
+
 	/* aligned with property */
 	uint8_t premultiplied;
 	uint8_t zpos;
@@ -75,13 +104,6 @@ struct mdp5_plane_state {
 
 	/* assigned by crtc blender */
 	enum mdp_mixer_stage_id stage;
-
-	/* some additional transactional status to help us know in the
-	 * apply path whether we need to update SMP allocation, and
-	 * whether current update is still pending:
-	 */
-	bool mode_changed : 1;
-	bool pending : 1;
 };
 #define to_mdp5_plane_state(x) \
 		container_of(x, struct mdp5_plane_state, base)
@@ -114,6 +136,18 @@ static inline u32 mdp5_read(struct mdp5_
 	return msm_readl(mdp5_kms->mmio + reg);
 }
 
+static inline const char *stage2name(enum mdp_mixer_stage_id stage)
+{
+	static const char *names[] = {
+#define NAME(n) [n] = #n
+		NAME(STAGE_UNUSED), NAME(STAGE_BASE),
+		NAME(STAGE0), NAME(STAGE1), NAME(STAGE2),
+		NAME(STAGE3), NAME(STAGE4), NAME(STAGE6),
+#undef NAME
+	};
+	return names[stage];
+}
+
 static inline const char *pipe2name(enum mdp5_pipe pipe)
 {
 	static const char *names[] = {
@@ -196,13 +230,8 @@ int mdp5_irq_domain_init(struct mdp5_kms
 void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
 
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
-void mdp5_plane_complete_flip(struct drm_plane *plane);
-void mdp5_plane_complete_commit(struct drm_plane *plane,
-	struct drm_plane_state *state);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
-struct drm_plane *mdp5_plane_init(struct drm_device *dev,
-		enum mdp5_pipe pipe, bool private_plane,
-		uint32_t reg_offset, uint32_t caps);
+struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary);
 
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 "mdp5_kms.h"
+
+struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
+		struct drm_plane *plane, uint32_t caps, uint32_t blkcfg)
+{
+	struct msm_drm_private *priv = s->dev->dev_private;
+	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+	struct mdp5_state *state;
+	struct mdp5_hw_pipe_state *old_state, *new_state;
+	struct mdp5_hw_pipe *hwpipe = NULL;
+	int i;
+
+	state = mdp5_get_state(s);
+	if (IS_ERR(state))
+		return ERR_CAST(state);
+
+	/* grab old_state after mdp5_get_state(), since now we hold lock: */
+	old_state = &mdp5_kms->state->hwpipe;
+	new_state = &state->hwpipe;
+
+	for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
+		struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
+
+		/* skip if already in-use.. check both new and old state,
+		 * since we cannot immediately re-use a pipe that is
+		 * released in the current update in some cases:
+		 *  (1) mdp5 can have SMP (non-double-buffered)
+		 *  (2) hw pipe previously assigned to different CRTC
+		 *      (vblanks might not be aligned)
+		 */
+		if (new_state->hwpipe_to_plane[cur->idx] ||
+				old_state->hwpipe_to_plane[cur->idx])
+			continue;
+
+		/* skip if doesn't support some required caps: */
+		if (caps & ~cur->caps)
+			continue;
+
+		/* possible candidate, take the one with the
+		 * fewest unneeded caps bits set:
+		 */
+		if (!hwpipe || (hweight_long(cur->caps & ~caps) <
+				hweight_long(hwpipe->caps & ~caps)))
+			hwpipe = cur;
+	}
+
+	if (!hwpipe)
+		return ERR_PTR(-ENOMEM);
+
+	if (mdp5_kms->smp) {
+		int ret;
+
+		DBG("%s: alloc SMP blocks", hwpipe->name);
+		ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp,
+				hwpipe->pipe, blkcfg);
+		if (ret)
+			return ERR_PTR(-ENOMEM);
+
+		hwpipe->blkcfg = blkcfg;
+	}
+
+	DBG("%s: assign to plane %s for caps %x",
+			hwpipe->name, plane->name, caps);
+	new_state->hwpipe_to_plane[hwpipe->idx] = plane;
+
+	return hwpipe;
+}
+
+void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
+{
+	struct msm_drm_private *priv = s->dev->dev_private;
+	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
+	struct mdp5_state *state = mdp5_get_state(s);
+	struct mdp5_hw_pipe_state *new_state = &state->hwpipe;
+
+	if (!hwpipe)
+		return;
+
+	if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
+		return;
+
+	DBG("%s: release from plane %s", hwpipe->name,
+		new_state->hwpipe_to_plane[hwpipe->idx]->name);
+
+	if (mdp5_kms->smp) {
+		DBG("%s: free SMP blocks", hwpipe->name);
+		mdp5_smp_release(mdp5_kms->smp, &state->smp, hwpipe->pipe);
+	}
+
+	new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
+}
+
+void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
+{
+	kfree(hwpipe);
+}
+
+struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
+		uint32_t reg_offset, uint32_t caps)
+{
+	struct mdp5_hw_pipe *hwpipe;
+
+	hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
+	if (!hwpipe)
+		return ERR_PTR(-ENOMEM);
+
+	hwpipe->name = pipe2name(pipe);
+	hwpipe->pipe = pipe;
+	hwpipe->reg_offset = reg_offset;
+	hwpipe->caps = caps;
+	hwpipe->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
+
+	spin_lock_init(&hwpipe->pipe_lock);
+
+	return hwpipe;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 __MDP5_PIPE_H__
+#define __MDP5_PIPE_H__
+
+#define SSPP_MAX	(SSPP_RGB3 + 1) /* TODO: Add SSPP_MAX in mdp5.xml.h */
+
+/* represents a hw pipe, which is dynamically assigned to a plane */
+struct mdp5_hw_pipe {
+	int idx;
+
+	const char *name;
+	enum mdp5_pipe pipe;
+
+	spinlock_t pipe_lock;     /* protect REG_MDP5_PIPE_* registers */
+	uint32_t reg_offset;
+	uint32_t caps;
+
+	uint32_t flush_mask;      /* used to commit pipe registers */
+
+	/* number of smp blocks per plane, ie:
+	 *   nblks_y | (nblks_u << 8) | (nblks_v << 16)
+	 */
+	uint32_t blkcfg;
+};
+
+/* global atomic state of assignment between pipes and planes: */
+struct mdp5_hw_pipe_state {
+	struct drm_plane *hwpipe_to_plane[SSPP_MAX];
+};
+
+struct mdp5_hw_pipe *__must_check
+mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane,
+		uint32_t caps, uint32_t blkcfg);
+void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe);
+
+struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
+		uint32_t reg_offset, uint32_t caps);
+void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe);
+
+#endif /* __MDP5_PIPE_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,19 +16,11 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <drm/drm_print.h>
 #include "mdp5_kms.h"
 
 struct mdp5_plane {
 	struct drm_plane base;
-	const char *name;
-
-	enum mdp5_pipe pipe;
-
-	spinlock_t pipe_lock;	/* protect REG_MDP5_PIPE_* registers */
-	uint32_t reg_offset;
-	uint32_t caps;
-
-	uint32_t flush_mask;	/* used to commit pipe registers */
 
 	uint32_t nformats;
 	uint32_t formats[32];
@@ -69,21 +61,12 @@ static void mdp5_plane_destroy(struct dr
 static void mdp5_plane_install_rotation_property(struct drm_device *dev,
 		struct drm_plane *plane)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-
-	if (!(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP) &&
-		!(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP))
-		return;
-
-	if (!dev->mode_config.rotation_property)
-		dev->mode_config.rotation_property =
-			drm_mode_create_rotation_property(dev,
-				DRM_ROTATE_0 | DRM_REFLECT_X | DRM_REFLECT_Y);
-
-	if (dev->mode_config.rotation_property)
-		drm_object_attach_property(&plane->base,
-			dev->mode_config.rotation_property,
-			DRM_ROTATE_0);
+	drm_plane_create_rotation_property(plane,
+					   DRM_ROTATE_0,
+					   DRM_ROTATE_0 |
+					   DRM_ROTATE_180 |
+					   DRM_REFLECT_X |
+					   DRM_REFLECT_Y);
 }
 
 /* helper to install properties which are common to planes and crtcs */
@@ -184,6 +167,20 @@ done:
 #undef SET_PROPERTY
 }
 
+static void
+mdp5_plane_atomic_print_state(struct drm_printer *p,
+		const struct drm_plane_state *state)
+{
+	struct mdp5_plane_state *pstate = to_mdp5_plane_state(state);
+
+	drm_printf(p, "\thwpipe=%s\n", pstate->hwpipe ?
+			pstate->hwpipe->name : "(null)");
+	drm_printf(p, "\tpremultiplied=%u\n", pstate->premultiplied);
+	drm_printf(p, "\tzpos=%u\n", pstate->zpos);
+	drm_printf(p, "\talpha=%u\n", pstate->alpha);
+	drm_printf(p, "\tstage=%s\n", stage2name(pstate->stage));
+}
+
 static void mdp5_plane_reset(struct drm_plane *plane)
 {
 	struct mdp5_plane_state *mdp5_state;
@@ -222,19 +219,18 @@ mdp5_plane_duplicate_state(struct drm_pl
 	if (mdp5_state && mdp5_state->base.fb)
 		drm_framebuffer_reference(mdp5_state->base.fb);
 
-	mdp5_state->mode_changed = false;
-	mdp5_state->pending = false;
-
 	return &mdp5_state->base;
 }
 
 static void mdp5_plane_destroy_state(struct drm_plane *plane,
 		struct drm_plane_state *state)
 {
+	struct mdp5_plane_state *pstate = to_mdp5_plane_state(state);
+
 	if (state->fb)
 		drm_framebuffer_unreference(state->fb);
 
-	kfree(to_mdp5_plane_state(state));
+	kfree(pstate);
 }
 
 static const struct drm_plane_funcs mdp5_plane_funcs = {
@@ -247,99 +243,114 @@ static const struct drm_plane_funcs mdp5
 		.reset = mdp5_plane_reset,
 		.atomic_duplicate_state = mdp5_plane_duplicate_state,
 		.atomic_destroy_state = mdp5_plane_destroy_state,
+		.atomic_print_state = mdp5_plane_atomic_print_state,
 };
 
 static int mdp5_plane_prepare_fb(struct drm_plane *plane,
 				 struct drm_plane_state *new_state)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
 	struct mdp5_kms *mdp5_kms = get_kms(plane);
 	struct drm_framebuffer *fb = new_state->fb;
 
 	if (!new_state->fb)
 		return 0;
 
-	DBG("%s: prepare: FB[%u]", mdp5_plane->name, fb->base.id);
+	DBG("%s: prepare: FB[%u]", plane->name, fb->base.id);
 	return msm_framebuffer_prepare(fb, mdp5_kms->id);
 }
 
 static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
 				  struct drm_plane_state *old_state)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
 	struct mdp5_kms *mdp5_kms = get_kms(plane);
 	struct drm_framebuffer *fb = old_state->fb;
 
 	if (!fb)
 		return;
 
-	DBG("%s: cleanup: FB[%u]", mdp5_plane->name, fb->base.id);
+	DBG("%s: cleanup: FB[%u]", plane->name, fb->base.id);
 	msm_framebuffer_cleanup(fb, mdp5_kms->id);
 }
 
 static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		struct drm_plane_state *state)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+	struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
 	struct drm_plane_state *old_state = plane->state;
-	const struct mdp_format *format;
-	bool vflip, hflip;
+	struct mdp5_cfg *config = mdp5_cfg_get_config(get_kms(plane)->cfg);
+	bool new_hwpipe = false;
+	uint32_t max_width, max_height;
+	uint32_t caps = 0;
 
-	DBG("%s: check (%d -> %d)", mdp5_plane->name,
+	DBG("%s: check (%d -> %d)", plane->name,
 			plane_enabled(old_state), plane_enabled(state));
 
+	max_width = config->hw->lm.max_width << 16;
+	max_height = config->hw->lm.max_height << 16;
+
+	/* Make sure source dimensions are within bounds. */
+	if ((state->src_w > max_width) || (state->src_h > max_height)) {
+		struct drm_rect src = drm_plane_state_src(state);
+		DBG("Invalid source size "DRM_RECT_FP_FMT,
+				DRM_RECT_FP_ARG(&src));
+		return -ERANGE;
+	}
+
 	if (plane_enabled(state)) {
+		unsigned int rotation;
+		const struct mdp_format *format;
+		struct mdp5_kms *mdp5_kms = get_kms(plane);
+		uint32_t blkcfg = 0;
+
 		format = to_mdp_format(msm_framebuffer_format(state->fb));
-		if (MDP_FORMAT_IS_YUV(format) &&
-			!pipe_supports_yuv(mdp5_plane->caps)) {
-			DBG("Pipe doesn't support YUV\n");
+		if (MDP_FORMAT_IS_YUV(format))
+			caps |= MDP_PIPE_CAP_SCALE | MDP_PIPE_CAP_CSC;
 
-			return -EINVAL;
-		}
+		if (((state->src_w >> 16) != state->crtc_w) ||
+				((state->src_h >> 16) != state->crtc_h))
+			caps |= MDP_PIPE_CAP_SCALE;
 
-		if (!(mdp5_plane->caps & MDP_PIPE_CAP_SCALE) &&
-			(((state->src_w >> 16) != state->crtc_w) ||
-			((state->src_h >> 16) != state->crtc_h))) {
-			DBG("Pipe doesn't support scaling (%dx%d -> %dx%d)\n",
-				state->src_w >> 16, state->src_h >> 16,
-				state->crtc_w, state->crtc_h);
+		rotation = drm_rotation_simplify(state->rotation,
+						 DRM_ROTATE_0 |
+						 DRM_REFLECT_X |
+						 DRM_REFLECT_Y);
 
-			return -EINVAL;
-		}
+		if (rotation & DRM_REFLECT_X)
+			caps |= MDP_PIPE_CAP_HFLIP;
 
-		hflip = !!(state->rotation & DRM_REFLECT_X);
-		vflip = !!(state->rotation & DRM_REFLECT_Y);
-		if ((vflip && !(mdp5_plane->caps & MDP_PIPE_CAP_VFLIP)) ||
-			(hflip && !(mdp5_plane->caps & MDP_PIPE_CAP_HFLIP))) {
-			DBG("Pipe doesn't support flip\n");
+		if (rotation & DRM_REFLECT_Y)
+			caps |= MDP_PIPE_CAP_VFLIP;
 
-			return -EINVAL;
-		}
-	}
+		/* (re)allocate hw pipe if we don't have one or caps-mismatch: */
+		if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps))
+			new_hwpipe = true;
 
-	if (plane_enabled(state) && plane_enabled(old_state)) {
-		/* we cannot change SMP block configuration during scanout: */
-		bool full_modeset = false;
-		if (state->fb->pixel_format != old_state->fb->pixel_format) {
-			DBG("%s: pixel_format change!", mdp5_plane->name);
-			full_modeset = true;
-		}
-		if (state->src_w != old_state->src_w) {
-			DBG("%s: src_w change!", mdp5_plane->name);
-			full_modeset = true;
-		}
-		if (to_mdp5_plane_state(old_state)->pending) {
-			DBG("%s: still pending!", mdp5_plane->name);
-			full_modeset = true;
+		if (mdp5_kms->smp) {
+			const struct mdp_format *format =
+				to_mdp_format(msm_framebuffer_format(state->fb));
+
+			blkcfg = mdp5_smp_calculate(mdp5_kms->smp, format,
+					state->src_w >> 16, false);
+
+			if (mdp5_state->hwpipe && (mdp5_state->hwpipe->blkcfg != blkcfg))
+				new_hwpipe = true;
 		}
-		if (full_modeset) {
-			struct drm_crtc_state *crtc_state =
-					drm_atomic_get_crtc_state(state->state, state->crtc);
-			crtc_state->mode_changed = true;
-			to_mdp5_plane_state(state)->mode_changed = true;
+
+		/* (re)assign hwpipe if needed, otherwise keep old one: */
+		if (new_hwpipe) {
+			/* TODO maybe we want to re-assign hwpipe sometimes
+			 * in cases when we no-longer need some caps to make
+			 * it available for other planes?
+			 */
+			struct mdp5_hw_pipe *old_hwpipe = mdp5_state->hwpipe;
+			mdp5_state->hwpipe = mdp5_pipe_assign(state->state,
+					plane, caps, blkcfg);
+			if (IS_ERR(mdp5_state->hwpipe)) {
+				DBG("%s: failed to assign hwpipe!", plane->name);
+				return PTR_ERR(mdp5_state->hwpipe);
+			}
+			mdp5_pipe_release(state->state, old_hwpipe);
 		}
-	} else {
-		to_mdp5_plane_state(state)->mode_changed = true;
 	}
 
 	return 0;
@@ -348,16 +359,13 @@ static int mdp5_plane_atomic_check(struc
 static void mdp5_plane_atomic_update(struct drm_plane *plane,
 				     struct drm_plane_state *old_state)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
 	struct drm_plane_state *state = plane->state;
 
-	DBG("%s: update", mdp5_plane->name);
+	DBG("%s: update", plane->name);
 
-	if (!plane_enabled(state)) {
-		to_mdp5_plane_state(state)->pending = true;
-	} else if (to_mdp5_plane_state(state)->mode_changed) {
+	if (plane_enabled(state)) {
 		int ret;
-		to_mdp5_plane_state(state)->pending = true;
+
 		ret = mdp5_plane_mode_set(plane,
 				state->crtc, state->fb,
 				state->crtc_x, state->crtc_y,
@@ -366,11 +374,6 @@ static void mdp5_plane_atomic_update(str
 				state->src_w, state->src_h);
 		/* atomic_check should have ensured that this doesn't fail */
 		WARN_ON(ret < 0);
-	} else {
-		unsigned long flags;
-		spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
-		set_scanout_locked(plane, state->fb);
-		spin_unlock_irqrestore(&mdp5_plane->pipe_lock, flags);
 	}
 }
 
@@ -384,9 +387,9 @@ static const struct drm_plane_helper_fun
 static void set_scanout_locked(struct drm_plane *plane,
 		struct drm_framebuffer *fb)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
 	struct mdp5_kms *mdp5_kms = get_kms(plane);
-	enum mdp5_pipe pipe = mdp5_plane->pipe;
+	struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(plane->state)->hwpipe;
+	enum mdp5_pipe pipe = hwpipe->pipe;
 
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_STRIDE_A(pipe),
 			MDP5_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
@@ -666,18 +669,19 @@ static int mdp5_plane_mode_set(struct dr
 		uint32_t src_x, uint32_t src_y,
 		uint32_t src_w, uint32_t src_h)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
 	struct drm_plane_state *pstate = plane->state;
+	struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(pstate)->hwpipe;
 	struct mdp5_kms *mdp5_kms = get_kms(plane);
-	enum mdp5_pipe pipe = mdp5_plane->pipe;
+	enum mdp5_pipe pipe = hwpipe->pipe;
 	const struct mdp_format *format;
 	uint32_t nplanes, config = 0;
 	uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,};
-	bool pe = mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT;
+	bool pe = hwpipe->caps & MDP_PIPE_CAP_SW_PIX_EXT;
 	int pe_left[COMP_MAX], pe_right[COMP_MAX];
 	int pe_top[COMP_MAX], pe_bottom[COMP_MAX];
 	uint32_t hdecm = 0, vdecm = 0;
 	uint32_t pix_format;
+	unsigned int rotation;
 	bool vflip, hflip;
 	unsigned long flags;
 	int ret;
@@ -697,27 +701,10 @@ static int mdp5_plane_mode_set(struct dr
 	src_w = src_w >> 16;
 	src_h = src_h >> 16;
 
-	DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", mdp5_plane->name,
+	DBG("%s: FB[%u] %u,%u,%u,%u -> CRTC[%u] %d,%d,%u,%u", plane->name,
 			fb->base.id, src_x, src_y, src_w, src_h,
 			crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
 
-	/* Request some memory from the SMP: */
-	if (mdp5_kms->smp) {
-		ret = mdp5_smp_request(mdp5_kms->smp,
-				mdp5_plane->pipe, format, src_w, false);
-		if (ret)
-			return ret;
-	}
-
-	/*
-	 * Currently we update the hw for allocations/requests immediately,
-	 * but once atomic modeset/pageflip is in place, the allocation
-	 * would move into atomic->check_plane_state(), while updating the
-	 * hw would remain here:
-	 */
-	if (mdp5_kms->smp)
-		mdp5_smp_configure(mdp5_kms->smp, pipe);
-
 	ret = calc_scalex_steps(plane, pix_format, src_w, crtc_w, phasex_step);
 	if (ret)
 		return ret;
@@ -726,7 +713,7 @@ static int mdp5_plane_mode_set(struct dr
 	if (ret)
 		return ret;
 
-	if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
+	if (hwpipe->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
 		calc_pixel_ext(format, src_w, crtc_w, phasex_step,
 					 pe_left, pe_right, true);
 		calc_pixel_ext(format, src_h, crtc_h, phasey_step,
@@ -740,14 +727,18 @@ static int mdp5_plane_mode_set(struct dr
 	config |= get_scale_config(format, src_h, crtc_h, false);
 	DBG("scale config = %x", config);
 
-	hflip = !!(pstate->rotation & DRM_REFLECT_X);
-	vflip = !!(pstate->rotation & DRM_REFLECT_Y);
+	rotation = drm_rotation_simplify(pstate->rotation,
+					 DRM_ROTATE_0 |
+					 DRM_REFLECT_X |
+					 DRM_REFLECT_Y);
+	hflip = !!(rotation & DRM_REFLECT_X);
+	vflip = !!(rotation & DRM_REFLECT_Y);
 
-	spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
+	spin_lock_irqsave(&hwpipe->pipe_lock, flags);
 
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_IMG_SIZE(pipe),
-			MDP5_PIPE_SRC_IMG_SIZE_WIDTH(fb->width) |
-			MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(fb->height));
+			MDP5_PIPE_SRC_IMG_SIZE_WIDTH(min(fb->width, src_w)) |
+			MDP5_PIPE_SRC_IMG_SIZE_HEIGHT(min(fb->height, src_h)));
 
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_SIZE(pipe),
 			MDP5_PIPE_SRC_SIZE_WIDTH(src_w) |
@@ -792,12 +783,12 @@ static int mdp5_plane_mode_set(struct dr
 	/* not using secure mode: */
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
 
-	if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT)
+	if (hwpipe->caps & MDP_PIPE_CAP_SW_PIX_EXT)
 		mdp5_write_pixel_ext(mdp5_kms, pipe, format,
 				src_w, pe_left, pe_right,
 				src_h, pe_top, pe_bottom);
 
-	if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
+	if (hwpipe->caps & MDP_PIPE_CAP_SCALE) {
 		mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
 				phasex_step[COMP_0]);
 		mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
@@ -812,7 +803,7 @@ static int mdp5_plane_mode_set(struct dr
 		mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
 	}
 
-	if (mdp5_plane->caps & MDP_PIPE_CAP_CSC) {
+	if (hwpipe->caps & MDP_PIPE_CAP_CSC) {
 		if (MDP_FORMAT_IS_YUV(format))
 			csc_enable(mdp5_kms, pipe,
 					mdp_get_default_csc_cfg(CSC_YUV2RGB));
@@ -822,56 +813,33 @@ static int mdp5_plane_mode_set(struct dr
 
 	set_scanout_locked(plane, fb);
 
-	spin_unlock_irqrestore(&mdp5_plane->pipe_lock, flags);
+	spin_unlock_irqrestore(&hwpipe->pipe_lock, flags);
 
 	return ret;
 }
 
-void mdp5_plane_complete_flip(struct drm_plane *plane)
+enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
 {
-	struct mdp5_kms *mdp5_kms = get_kms(plane);
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-	enum mdp5_pipe pipe = mdp5_plane->pipe;
-
-	DBG("%s: complete flip", mdp5_plane->name);
-
-	if (mdp5_kms->smp)
-		mdp5_smp_commit(mdp5_kms->smp, pipe);
+	struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
 
-	to_mdp5_plane_state(plane->state)->pending = false;
-}
+	if (WARN_ON(!pstate->hwpipe))
+		return 0;
 
-enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
-{
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-	return mdp5_plane->pipe;
+	return pstate->hwpipe->pipe;
 }
 
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
 {
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-
-	return mdp5_plane->flush_mask;
-}
+	struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
 
-/* called after vsync in thread context */
-void mdp5_plane_complete_commit(struct drm_plane *plane,
-	struct drm_plane_state *state)
-{
-	struct mdp5_kms *mdp5_kms = get_kms(plane);
-	struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-	enum mdp5_pipe pipe = mdp5_plane->pipe;
+	if (WARN_ON(!pstate->hwpipe))
+		return 0;
 
-	if (!plane_enabled(plane->state) && mdp5_kms->smp) {
-		DBG("%s: free SMP", mdp5_plane->name);
-		mdp5_smp_release(mdp5_kms->smp, pipe);
-	}
+	return pstate->hwpipe->flush_mask;
 }
 
 /* initialize plane */
-struct drm_plane *mdp5_plane_init(struct drm_device *dev,
-		enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset,
-		uint32_t caps)
+struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
 {
 	struct drm_plane *plane = NULL;
 	struct mdp5_plane *mdp5_plane;
@@ -886,19 +854,10 @@ struct drm_plane *mdp5_plane_init(struct
 
 	plane = &mdp5_plane->base;
 
-	mdp5_plane->pipe = pipe;
-	mdp5_plane->name = pipe2name(pipe);
-	mdp5_plane->caps = caps;
-
 	mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
-		ARRAY_SIZE(mdp5_plane->formats),
-		!pipe_supports_yuv(mdp5_plane->caps));
-
-	mdp5_plane->flush_mask = mdp_ctl_flush_mask_pipe(pipe);
-	mdp5_plane->reg_offset = reg_offset;
-	spin_lock_init(&mdp5_plane->pipe_lock);
+		ARRAY_SIZE(mdp5_plane->formats), false);
 
-	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+	type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
 				 mdp5_plane->formats, mdp5_plane->nformats,
 				 type, NULL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,72 +21,6 @@
 #include "mdp5_smp.h"
 
 
-/* SMP - Shared Memory Pool
- *
- * These are shared between all the clients, where each plane in a
- * scanout buffer is a SMP client.  Ie. scanout of 3 plane I420 on
- * pipe VIG0 => 3 clients: VIG0_Y, VIG0_CB, VIG0_CR.
- *
- * Based on the size of the attached scanout buffer, a certain # of
- * blocks must be allocated to that client out of the shared pool.
- *
- * In some hw, some blocks are statically allocated for certain pipes
- * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0).
- *
- * For each block that can be dynamically allocated, it can be either
- *     free:
- *     The block is free.
- *
- *     pending:
- *     The block is allocated to some client and not free.
- *
- *     configured:
- *     The block is allocated to some client, and assigned to that
- *     client in MDP5_SMP_ALLOC registers.
- *
- *     inuse:
- *     The block is being actively used by a client.
- *
- * The updates happen in the following steps:
- *
- *  1) mdp5_smp_request():
- *     When plane scanout is setup, calculate required number of
- *     blocks needed per client, and request. Blocks neither inuse nor
- *     configured nor pending by any other client are added to client's
- *     pending set.
- *     For shrinking, blocks in pending but not in configured can be freed
- *     directly, but those already in configured will be freed later by
- *     mdp5_smp_commit.
- *
- *  2) mdp5_smp_configure():
- *     As hw is programmed, before FLUSH, MDP5_SMP_ALLOC registers
- *     are configured for the union(pending, inuse)
- *     Current pending is copied to configured.
- *     It is assumed that mdp5_smp_request and mdp5_smp_configure not run
- *     concurrently for the same pipe.
- *
- *  3) mdp5_smp_commit():
- *     After next vblank, copy configured -> inuse.  Optionally update
- *     MDP5_SMP_ALLOC registers if there are newly unused blocks
- *
- *  4) mdp5_smp_release():
- *     Must be called after the pipe is disabled and no longer uses any SMB
- *
- * On the next vblank after changes have been committed to hw, the
- * client's pending blocks become it's in-use blocks (and no-longer
- * in-use blocks become available to other clients).
- *
- * btw, hurray for confusing overloaded acronyms!  :-/
- *
- * NOTE: for atomic modeset/pageflip NONBLOCK operations, step #1
- * should happen at (or before)? atomic->check().  And we'd need
- * an API to discard previous requests if update is aborted or
- * (test-only).
- *
- * TODO would perhaps be nice to have debugfs to dump out kernel
- * inuse and pending state of all clients..
- */
-
 struct mdp5_smp {
 	struct drm_device *dev;
 
@@ -94,16 +28,8 @@ struct mdp5_smp {
 
 	int blk_cnt;
 	int blk_size;
-
-	spinlock_t state_lock;
-	mdp5_smp_state_t state; /* to track smp allocation amongst pipes: */
-
-	struct mdp5_client_smp_state client_state[MAX_CLIENTS];
 };
 
-static void update_smp_state(struct mdp5_smp *smp,
-		u32 cid, mdp5_smp_state_t *assigned);
-
 static inline
 struct mdp5_kms *get_kms(struct mdp5_smp *smp)
 {
@@ -134,57 +60,38 @@ static inline u32 pipe2client(enum mdp5_
 	return mdp5_cfg->smp.clients[pipe] + plane;
 }
 
-/* step #1: update # of blocks pending for the client: */
+/* allocate blocks for the specified request: */
 static int smp_request_block(struct mdp5_smp *smp,
+		struct mdp5_smp_state *state,
 		u32 cid, int nblks)
 {
-	struct mdp5_kms *mdp5_kms = get_kms(smp);
-	struct mdp5_client_smp_state *ps = &smp->client_state[cid];
-	int i, ret, avail, cur_nblks, cnt = smp->blk_cnt;
+	void *cs = state->client_state[cid];
+	int i, avail, cnt = smp->blk_cnt;
 	uint8_t reserved;
-	unsigned long flags;
 
-	reserved = smp->reserved[cid];
+	/* we shouldn't be requesting blocks for an in-use client: */
+	WARN_ON(bitmap_weight(cs, cnt) > 0);
 
-	spin_lock_irqsave(&smp->state_lock, flags);
+	reserved = smp->reserved[cid];
 
 	if (reserved) {
 		nblks = max(0, nblks - reserved);
 		DBG("%d MMBs allocated (%d reserved)", nblks, reserved);
 	}
 
-	avail = cnt - bitmap_weight(smp->state, cnt);
+	avail = cnt - bitmap_weight(state->state, cnt);
 	if (nblks > avail) {
-		dev_err(mdp5_kms->dev->dev, "out of blks (req=%d > avail=%d)\n",
+		dev_err(smp->dev->dev, "out of blks (req=%d > avail=%d)\n",
 				nblks, avail);
-		ret = -ENOSPC;
-		goto fail;
+		return -ENOSPC;
 	}
 
-	cur_nblks = bitmap_weight(ps->pending, cnt);
-	if (nblks > cur_nblks) {
-		/* grow the existing pending reservation: */
-		for (i = cur_nblks; i < nblks; i++) {
-			int blk = find_first_zero_bit(smp->state, cnt);
-			set_bit(blk, ps->pending);
-			set_bit(blk, smp->state);
-		}
-	} else {
-		/* shrink the existing pending reservation: */
-		for (i = cur_nblks; i > nblks; i--) {
-			int blk = find_first_bit(ps->pending, cnt);
-			clear_bit(blk, ps->pending);
-
-			/* clear in global smp_state if not in configured
-			 * otherwise until _commit()
-			 */
-			if (!test_bit(blk, ps->configured))
-				clear_bit(blk, smp->state);
-		}
+	for (i = 0; i < nblks; i++) {
+		int blk = find_first_zero_bit(state->state, cnt);
+		set_bit(blk, cs);
+		set_bit(blk, state->state);
 	}
 
-fail:
-	spin_unlock_irqrestore(&smp->state_lock, flags);
 	return 0;
 }
 
@@ -209,14 +116,15 @@ static void set_fifo_thresholds(struct m
  * decimated width.  Ie. SMP buffering sits downstream of decimation (which
  * presumably happens during the dma from scanout buffer).
  */
-int mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe,
-		const struct mdp_format *format, u32 width, bool hdecim)
+uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
+		const struct mdp_format *format,
+		u32 width, bool hdecim)
 {
 	struct mdp5_kms *mdp5_kms = get_kms(smp);
-	struct drm_device *dev = mdp5_kms->dev;
 	int rev = mdp5_cfg_get_hw_rev(mdp5_kms->cfg);
-	int i, hsub, nplanes, nlines, nblks, ret;
+	int i, hsub, nplanes, nlines;
 	u32 fmt = format->base.pixel_format;
+	uint32_t blkcfg = 0;
 
 	nplanes = drm_format_num_planes(fmt);
 	hsub = drm_format_horz_chroma_subsampling(fmt);
@@ -239,7 +147,7 @@ int mdp5_smp_request(struct mdp5_smp *sm
 			hsub = 1;
 	}
 
-	for (i = 0, nblks = 0; i < nplanes; i++) {
+	for (i = 0; i < nplanes; i++) {
 		int n, fetch_stride, cpp;
 
 		cpp = drm_format_plane_cpp(fmt, i);
@@ -251,60 +159,72 @@ int mdp5_smp_request(struct mdp5_smp *sm
 		if (rev == 0)
 			n = roundup_pow_of_two(n);
 
+		blkcfg |= (n << (8 * i));
+	}
+
+	return blkcfg;
+}
+
+int mdp5_smp_assign(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+		enum mdp5_pipe pipe, uint32_t blkcfg)
+{
+	struct mdp5_kms *mdp5_kms = get_kms(smp);
+	struct drm_device *dev = mdp5_kms->dev;
+	int i, ret;
+
+	for (i = 0; i < pipe2nclients(pipe); i++) {
+		u32 cid = pipe2client(pipe, i);
+		int n = blkcfg & 0xff;
+
+		if (!n)
+			continue;
+
 		DBG("%s[%d]: request %d SMP blocks", pipe2name(pipe), i, n);
-		ret = smp_request_block(smp, pipe2client(pipe, i), n);
+		ret = smp_request_block(smp, state, cid, n);
 		if (ret) {
 			dev_err(dev->dev, "Cannot allocate %d SMP blocks: %d\n",
 					n, ret);
 			return ret;
 		}
 
-		nblks += n;
+		blkcfg >>= 8;
 	}
 
-	set_fifo_thresholds(smp, pipe, nblks);
+	state->assigned |= (1 << pipe);
 
 	return 0;
 }
 
 /* Release SMP blocks for all clients of the pipe */
-void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe)
+void mdp5_smp_release(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+		enum mdp5_pipe pipe)
 {
 	int i;
-	unsigned long flags;
 	int cnt = smp->blk_cnt;
 
 	for (i = 0; i < pipe2nclients(pipe); i++) {
-		mdp5_smp_state_t assigned;
 		u32 cid = pipe2client(pipe, i);
-		struct mdp5_client_smp_state *ps = &smp->client_state[cid];
-
-		spin_lock_irqsave(&smp->state_lock, flags);
-
-		/* clear hw assignment */
-		bitmap_or(assigned, ps->inuse, ps->configured, cnt);
-		update_smp_state(smp, CID_UNUSED, &assigned);
-
-		/* free to global pool */
-		bitmap_andnot(smp->state, smp->state, ps->pending, cnt);
-		bitmap_andnot(smp->state, smp->state, assigned, cnt);
+		void *cs = state->client_state[cid];
 
-		/* clear client's infor */
-		bitmap_zero(ps->pending, cnt);
-		bitmap_zero(ps->configured, cnt);
-		bitmap_zero(ps->inuse, cnt);
+		/* update global state: */
+		bitmap_andnot(state->state, state->state, cs, cnt);
 
-		spin_unlock_irqrestore(&smp->state_lock, flags);
+		/* clear client's state */
+		bitmap_zero(cs, cnt);
 	}
 
-	set_fifo_thresholds(smp, pipe, 0);
+	state->released |= (1 << pipe);
 }
 
-static void update_smp_state(struct mdp5_smp *smp,
+/* NOTE: SMP_ALLOC_* regs are *not* double buffered, so release has to
+ * happen after scanout completes.
+ */
+static unsigned update_smp_state(struct mdp5_smp *smp,
 		u32 cid, mdp5_smp_state_t *assigned)
 {
 	struct mdp5_kms *mdp5_kms = get_kms(smp);
 	int cnt = smp->blk_cnt;
+	unsigned nblks = 0;
 	u32 blk, val;
 
 	for_each_set_bit(blk, *assigned, cnt) {
@@ -330,62 +250,88 @@ static void update_smp_state(struct mdp5
 
 		mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_W_REG(idx), val);
 		mdp5_write(mdp5_kms, REG_MDP5_SMP_ALLOC_R_REG(idx), val);
+
+		nblks++;
 	}
+
+	return nblks;
 }
 
-/* step #2: configure hw for union(pending, inuse): */
-void mdp5_smp_configure(struct mdp5_smp *smp, enum mdp5_pipe pipe)
+void mdp5_smp_prepare_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
 {
-	int cnt = smp->blk_cnt;
-	mdp5_smp_state_t assigned;
-	int i;
+	enum mdp5_pipe pipe;
 
-	for (i = 0; i < pipe2nclients(pipe); i++) {
-		u32 cid = pipe2client(pipe, i);
-		struct mdp5_client_smp_state *ps = &smp->client_state[cid];
+	for_each_set_bit(pipe, &state->assigned, sizeof(state->assigned) * 8) {
+		unsigned i, nblks = 0;
 
-		/*
-		 * if vblank has not happened since last smp_configure
-		 * skip the configure for now
-		 */
-		if (!bitmap_equal(ps->inuse, ps->configured, cnt))
-			continue;
+		for (i = 0; i < pipe2nclients(pipe); i++) {
+			u32 cid = pipe2client(pipe, i);
+			void *cs = state->client_state[cid];
 
-		bitmap_copy(ps->configured, ps->pending, cnt);
-		bitmap_or(assigned, ps->inuse, ps->configured, cnt);
-		update_smp_state(smp, cid, &assigned);
+			nblks += update_smp_state(smp, cid, cs);
+
+			DBG("assign %s:%u, %u blks",
+				pipe2name(pipe), i, nblks);
+		}
+
+		set_fifo_thresholds(smp, pipe, nblks);
+	}
+
+	state->assigned = 0;
+}
+
+void mdp5_smp_complete_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state)
+{
+	enum mdp5_pipe pipe;
+
+	for_each_set_bit(pipe, &state->released, sizeof(state->released) * 8) {
+		DBG("release %s", pipe2name(pipe));
+		set_fifo_thresholds(smp, pipe, 0);
 	}
+
+	state->released = 0;
 }
 
-/* step #3: after vblank, copy configured -> inuse: */
-void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe)
+void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)
 {
-	int cnt = smp->blk_cnt;
-	mdp5_smp_state_t released;
-	int i;
+	struct mdp5_kms *mdp5_kms = get_kms(smp);
+	struct mdp5_hw_pipe_state *hwpstate;
+	struct mdp5_smp_state *state;
+	int total = 0, i, j;
 
-	for (i = 0; i < pipe2nclients(pipe); i++) {
-		u32 cid = pipe2client(pipe, i);
-		struct mdp5_client_smp_state *ps = &smp->client_state[cid];
+	drm_printf(p, "name\tinuse\tplane\n");
+	drm_printf(p, "----\t-----\t-----\n");
 
-		/*
-		 * Figure out if there are any blocks we where previously
-		 * using, which can be released and made available to other
-		 * clients:
-		 */
-		if (bitmap_andnot(released, ps->inuse, ps->configured, cnt)) {
-			unsigned long flags;
+	if (drm_can_sleep())
+		drm_modeset_lock(&mdp5_kms->state_lock, NULL);
 
-			spin_lock_irqsave(&smp->state_lock, flags);
-			/* clear released blocks: */
-			bitmap_andnot(smp->state, smp->state, released, cnt);
-			spin_unlock_irqrestore(&smp->state_lock, flags);
+	/* grab these *after* we hold the state_lock */
+	hwpstate = &mdp5_kms->state->hwpipe;
+	state = &mdp5_kms->state->smp;
 
-			update_smp_state(smp, CID_UNUSED, &released);
-		}
+	for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
+		struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
+		struct drm_plane *plane = hwpstate->hwpipe_to_plane[hwpipe->idx];
+		enum mdp5_pipe pipe = hwpipe->pipe;
+		for (j = 0; j < pipe2nclients(pipe); j++) {
+			u32 cid = pipe2client(pipe, j);
+			void *cs = state->client_state[cid];
+			int inuse = bitmap_weight(cs, smp->blk_cnt);
 
-		bitmap_copy(ps->inuse, ps->configured, cnt);
+			drm_printf(p, "%s:%d\t%d\t%s\n",
+				pipe2name(pipe), j, inuse,
+				plane ? plane->name : NULL);
+
+			total += inuse;
+		}
 	}
+
+	drm_printf(p, "TOTAL:\t%d\t(of %d)\n", total, smp->blk_cnt);
+	drm_printf(p, "AVAIL:\t%d\n", smp->blk_cnt -
+			bitmap_weight(state->state, smp->blk_cnt));
+
+	if (drm_can_sleep())
+		drm_modeset_unlock(&mdp5_kms->state_lock);
 }
 
 void mdp5_smp_destroy(struct mdp5_smp *smp)
@@ -393,8 +339,9 @@ void mdp5_smp_destroy(struct mdp5_smp *s
 	kfree(smp);
 }
 
-struct mdp5_smp *mdp5_smp_init(struct drm_device *dev, const struct mdp5_smp_block *cfg)
+struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_block *cfg)
 {
+	struct mdp5_smp_state *state = &mdp5_kms->state->smp;
 	struct mdp5_smp *smp = NULL;
 	int ret;
 
@@ -404,14 +351,13 @@ struct mdp5_smp *mdp5_smp_init(struct dr
 		goto fail;
 	}
 
-	smp->dev = dev;
+	smp->dev = mdp5_kms->dev;
 	smp->blk_cnt = cfg->mmb_count;
 	smp->blk_size = cfg->mmb_size;
 
 	/* statically tied MMBs cannot be re-allocated: */
-	bitmap_copy(smp->state, cfg->reserved_state, smp->blk_cnt);
+	bitmap_copy(state->state, cfg->reserved_state, smp->blk_cnt);
 	memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved));
-	spin_lock_init(&smp->state_lock);
 
 	return smp;
 fail:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,12 +19,53 @@
 #ifndef __MDP5_SMP_H__
 #define __MDP5_SMP_H__
 
+#include <drm/drm_print.h>
+
 #include "msm_drv.h"
 
-struct mdp5_client_smp_state {
-	mdp5_smp_state_t inuse;
-	mdp5_smp_state_t configured;
-	mdp5_smp_state_t pending;
+/*
+ * SMP - Shared Memory Pool:
+ *
+ * SMP blocks are shared between all the clients, where each plane in
+ * a scanout buffer is a SMP client.  Ie. scanout of 3 plane I420 on
+ * pipe VIG0 => 3 clients: VIG0_Y, VIG0_CB, VIG0_CR.
+ *
+ * Based on the size of the attached scanout buffer, a certain # of
+ * blocks must be allocated to that client out of the shared pool.
+ *
+ * In some hw, some blocks are statically allocated for certain pipes
+ * and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0).
+ *
+ *
+ * Atomic SMP State:
+ *
+ * On atomic updates that modify SMP configuration, the state is cloned
+ * (copied) and modified.  For test-only, or in cases where atomic
+ * update fails (or if we hit ww_mutex deadlock/backoff condition) the
+ * new state is simply thrown away.
+ *
+ * Because the SMP registers are not double buffered, updates are a
+ * two step process:
+ *
+ * 1) in _prepare_commit() we configure things (via read-modify-write)
+ *    for the newly assigned pipes, so we don't take away blocks
+ *    assigned to pipes that are still scanning out
+ * 2) in _complete_commit(), after vblank/etc, we clear things for the
+ *    released clients, since at that point old pipes are no longer
+ *    scanning out.
+ */
+struct mdp5_smp_state {
+	/* global state of what blocks are in use: */
+	mdp5_smp_state_t state;
+
+	/* per client state of what blocks they are using: */
+	mdp5_smp_state_t client_state[MAX_CLIENTS];
+
+	/* assigned pipes (hw updated at _prepare_commit()): */
+	unsigned long assigned;
+
+	/* released pipes (hw updated at _complete_commit()): */
+	unsigned long released;
 };
 
 struct mdp5_kms;
@@ -36,13 +77,22 @@ struct mdp5_smp;
  * which is then used to call the other mdp5_smp_*(handler, ...) functions.
  */
 
-struct mdp5_smp *mdp5_smp_init(struct drm_device *dev, const struct mdp5_smp_block *cfg);
+struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms,
+		const struct mdp5_smp_block *cfg);
 void  mdp5_smp_destroy(struct mdp5_smp *smp);
 
-int  mdp5_smp_request(struct mdp5_smp *smp, enum mdp5_pipe pipe,
-		const struct mdp_format *format, u32 width, bool hdecim);
-void mdp5_smp_configure(struct mdp5_smp *smp, enum mdp5_pipe pipe);
-void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe);
-void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe);
+void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p);
+
+uint32_t mdp5_smp_calculate(struct mdp5_smp *smp,
+		const struct mdp_format *format,
+		u32 width, bool hdecim);
+
+int mdp5_smp_assign(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+		enum mdp5_pipe pipe, uint32_t blkcfg);
+void mdp5_smp_release(struct mdp5_smp *smp, struct mdp5_smp_state *state,
+		enum mdp5_pipe pipe);
+
+void mdp5_smp_prepare_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state);
+void mdp5_smp_complete_commit(struct mdp5_smp *smp, struct mdp5_smp_state *state);
 
 #endif /* __MDP5_SMP_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,9 +8,17 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /local/mnt/workspace/source_trees/envytools/rnndb/../rnndb/mdp/mdp5.xml   (  36965 bytes, from 2016-05-10 05:06:30)
-- /local/mnt/workspace/source_trees/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-05-09 06:32:54)
-- /local/mnt/workspace/source_trees/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2016-01-07 08:45:55)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2015-05-20 20:03:07)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  41472 bytes, from 2016-01-22 18:18:18)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-20 20:03:14)
 
 Copyright (C) 2013-2016 by the following authors:
 - Rob Clark <robdclark@gmail.com> (robclark)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/mdp/mdp_common.xml.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@ The rules-ng-ng source files this header
 - /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1572 bytes, from 2016-02-10 17:07:21)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
 - /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2849 bytes, from 2015-09-18 12:07:28)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  37194 bytes, from 2015-09-18 12:07:28)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36965 bytes, from 2016-11-26 23:01:08)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  27887 bytes, from 2015-10-22 16:34:52)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    602 bytes, from 2015-10-22 16:35:02)
 - /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_atomic.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_atomic.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_atomic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_atomic.c	2017-02-12 16:03:20.000000000 -0500
@@ -141,7 +141,7 @@ static void complete_commit(struct msm_c
 
 	kms->funcs->complete_commit(kms, state);
 
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 
 	commit_destroy(c);
 }
@@ -217,8 +217,9 @@ int msm_atomic_commit(struct drm_device
 		if ((plane->state->fb != plane_state->fb) && plane_state->fb) {
 			struct drm_gem_object *obj = msm_framebuffer_bo(plane_state->fb, 0);
 			struct msm_gem_object *msm_obj = to_msm_bo(obj);
+			struct dma_fence *fence = reservation_object_get_excl_rcu(msm_obj->resv);
 
-			plane_state->fence = reservation_object_get_excl_rcu(msm_obj->resv);
+			drm_atomic_set_fence_for_plane(plane_state, fence);
 		}
 	}
 
@@ -240,6 +241,10 @@ int msm_atomic_commit(struct drm_device
 
 	drm_atomic_helper_swap_state(state, true);
 
+	/* swap driver private state while still holding state_lock */
+	if (to_kms_state(state)->state)
+		priv->kms->funcs->swap_state(priv->kms, state);
+
 	/*
 	 * Everything below can be run asynchronously without the need to grab
 	 * any modeset locks at all under one conditions: It must be guaranteed
@@ -256,6 +261,7 @@ int msm_atomic_commit(struct drm_device
 	 * current layout.
 	 */
 
+	drm_atomic_state_get(state);
 	if (nonblock) {
 		queue_work(priv->atomic_wq, &c->work);
 		return 0;
@@ -269,3 +275,30 @@ error:
 	drm_atomic_helper_cleanup_planes(dev, state);
 	return ret;
 }
+
+struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
+{
+	struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
+
+	if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
+		kfree(state);
+		return NULL;
+	}
+
+	return &state->base;
+}
+
+void msm_atomic_state_clear(struct drm_atomic_state *s)
+{
+	struct msm_kms_state *state = to_kms_state(s);
+	drm_atomic_state_default_clear(&state->base);
+	kfree(state->state);
+	state->state = NULL;
+}
+
+void msm_atomic_state_free(struct drm_atomic_state *state)
+{
+	kfree(to_kms_state(state)->state);
+	drm_atomic_state_default_release(state);
+	kfree(state);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_debugfs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_debugfs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@
 #ifdef CONFIG_DEBUG_FS
 #include "msm_drv.h"
 #include "msm_gpu.h"
+#include "msm_kms.h"
+#include "msm_debugfs.h"
 
 static int msm_gpu_show(struct drm_device *dev, struct seq_file *m)
 {
@@ -141,6 +143,7 @@ int msm_debugfs_late_init(struct drm_dev
 int msm_debugfs_init(struct drm_minor *minor)
 {
 	struct drm_device *dev = minor->dev;
+	struct msm_drm_private *priv = dev->dev_private;
 	int ret;
 
 	ret = drm_debugfs_create_files(msm_debugfs_list,
@@ -152,15 +155,25 @@ int msm_debugfs_init(struct drm_minor *m
 		return ret;
 	}
 
-	return 0;
+	if (priv->kms->funcs->debugfs_init)
+		ret = priv->kms->funcs->debugfs_init(priv->kms, minor);
+
+	return ret;
 }
 
 void msm_debugfs_cleanup(struct drm_minor *minor)
 {
+	struct drm_device *dev = minor->dev;
+	struct msm_drm_private *priv = dev->dev_private;
+
 	drm_debugfs_remove_files(msm_debugfs_list,
 			ARRAY_SIZE(msm_debugfs_list), minor);
-	if (!minor->dev->dev_private)
+	if (!priv)
 		return;
+
+	if (priv->kms->funcs->debugfs_cleanup)
+		priv->kms->funcs->debugfs_cleanup(priv->kms, minor);
+
 	msm_rd_debugfs_cleanup(minor);
 	msm_perf_debugfs_cleanup(minor);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,8 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <drm/drm_of.h>
+
 #include "msm_drv.h"
 #include "msm_debugfs.h"
 #include "msm_fence.h"
@@ -44,17 +46,21 @@ static const struct drm_mode_config_func
 	.output_poll_changed = msm_fb_output_poll_changed,
 	.atomic_check = msm_atomic_check,
 	.atomic_commit = msm_atomic_commit,
+	.atomic_state_alloc = msm_atomic_state_alloc,
+	.atomic_state_clear = msm_atomic_state_clear,
+	.atomic_state_free = msm_atomic_state_free,
 };
 
-int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu)
+int msm_register_address_space(struct drm_device *dev,
+		struct msm_gem_address_space *aspace)
 {
 	struct msm_drm_private *priv = dev->dev_private;
-	int idx = priv->num_mmus++;
+	int idx = priv->num_aspaces++;
 
-	if (WARN_ON(idx >= ARRAY_SIZE(priv->mmus)))
+	if (WARN_ON(idx >= ARRAY_SIZE(priv->aspace)))
 		return -EINVAL;
 
-	priv->mmus[idx] = mmu;
+	priv->aspace[idx] = aspace;
 
 	return idx;
 }
@@ -77,6 +83,10 @@ static char *vram = "16m";
 MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU)");
 module_param(vram, charp, 0);
 
+bool dumpstate = false;
+MODULE_PARM_DESC(dumpstate, "Dump KMS state on errors");
+module_param(dumpstate, bool, 0600);
+
 /*
  * Util/helpers:
  */
@@ -766,9 +776,7 @@ static const struct file_operations fops
 	.open               = drm_open,
 	.release            = drm_release,
 	.unlocked_ioctl     = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl       = drm_compat_ioctl,
-#endif
 	.poll               = drm_poll,
 	.read               = drm_read,
 	.llseek             = no_llseek,
@@ -903,10 +911,8 @@ static int add_components_mdp(struct dev
 		 * remote-endpoint isn't a component that we need to add
 		 */
 		if (of_device_is_compatible(np, "qcom,mdp4") &&
-		    ep.port == 0) {
-			of_node_put(ep_node);
+		    ep.port == 0)
 			continue;
-		}
 
 		/*
 		 * It's okay if some of the ports don't have a remote endpoint
@@ -914,15 +920,12 @@ static int add_components_mdp(struct dev
 		 * any external interface.
 		 */
 		intf = of_graph_get_remote_port_parent(ep_node);
-		if (!intf) {
-			of_node_put(ep_node);
+		if (!intf)
 			continue;
-		}
-
-		component_match_add(master_dev, matchptr, compare_of, intf);
 
+		drm_of_component_match_add(master_dev, matchptr, compare_of,
+					   intf);
 		of_node_put(intf);
-		of_node_put(ep_node);
 	}
 
 	return 0;
@@ -962,8 +965,8 @@ static int add_display_components(struct
 		put_device(mdp_dev);
 
 		/* add the MDP component itself */
-		component_match_add(dev, matchptr, compare_of,
-				    mdp_dev->of_node);
+		drm_of_component_match_add(dev, matchptr, compare_of,
+					   mdp_dev->of_node);
 	} else {
 		/* MDP4 */
 		mdp_dev = dev;
@@ -996,7 +999,7 @@ static int add_gpu_components(struct dev
 	if (!np)
 		return 0;
 
-	component_match_add(dev, matchptr, compare_of, np);
+	drm_of_component_match_add(dev, matchptr, compare_of, np);
 
 	of_node_put(np);
 
@@ -1035,7 +1038,13 @@ static int msm_pdev_probe(struct platfor
 	if (ret)
 		return ret;
 
-	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+	/* on all devices that I am aware of, iommu's which can map
+	 * any address the cpu can see are used:
+	 */
+	ret = dma_set_mask_and_coherent(&pdev->dev, ~0);
+	if (ret)
+		return ret;
+
 	return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -52,6 +52,8 @@ struct msm_perf_state;
 struct msm_gem_submit;
 struct msm_fence_context;
 struct msm_fence_cb;
+struct msm_gem_address_space;
+struct msm_gem_vma;
 
 #define NUM_DOMAINS 2    /* one for KMS, then one per gpu core (?) */
 
@@ -121,12 +123,16 @@ struct msm_drm_private {
 	uint32_t pending_crtcs;
 	wait_queue_head_t pending_crtcs_event;
 
-	/* registered MMUs: */
-	unsigned int num_mmus;
-	struct msm_mmu *mmus[NUM_DOMAINS];
+	/* Registered address spaces.. currently this is fixed per # of
+	 * iommu's.  Ie. one for display block and one for gpu block.
+	 * Eventually, to do per-process gpu pagetables, we'll want one
+	 * of these per-process.
+	 */
+	unsigned int num_aspaces;
+	struct msm_gem_address_space *aspace[NUM_DOMAINS];
 
 	unsigned int num_planes;
-	struct drm_plane *planes[8];
+	struct drm_plane *planes[16];
 
 	unsigned int num_crtcs;
 	struct drm_crtc *crtcs[8];
@@ -173,8 +179,22 @@ int msm_atomic_check(struct drm_device *
 		     struct drm_atomic_state *state);
 int msm_atomic_commit(struct drm_device *dev,
 		struct drm_atomic_state *state, bool nonblock);
+struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
+void msm_atomic_state_clear(struct drm_atomic_state *state);
+void msm_atomic_state_free(struct drm_atomic_state *state);
 
-int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
+int msm_register_address_space(struct drm_device *dev,
+		struct msm_gem_address_space *aspace);
+
+void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
+		struct msm_gem_vma *vma, struct sg_table *sgt);
+int msm_gem_map_vma(struct msm_gem_address_space *aspace,
+		struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
+
+void msm_gem_address_space_destroy(struct msm_gem_address_space *aspace);
+struct msm_gem_address_space *
+msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
+		const char *name);
 
 void msm_gem_submit_free(struct msm_gem_submit *submit);
 int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
@@ -189,9 +209,9 @@ int msm_gem_mmap(struct file *filp, stru
 int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 uint64_t msm_gem_mmap_offset(struct drm_gem_object *obj);
 int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
-		uint32_t *iova);
-int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova);
-uint32_t msm_gem_iova(struct drm_gem_object *obj, int id);
+		uint64_t *iova);
+int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint64_t *iova);
+uint64_t msm_gem_iova(struct drm_gem_object *obj, int id);
 struct page **msm_gem_get_pages(struct drm_gem_object *obj);
 void msm_gem_put_pages(struct drm_gem_object *obj);
 void msm_gem_put_iova(struct drm_gem_object *obj, int id);
@@ -217,7 +237,7 @@ void msm_gem_vunmap(struct drm_gem_objec
 int msm_gem_sync_object(struct drm_gem_object *obj,
 		struct msm_fence_context *fctx, bool exclusive);
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-		struct msm_gpu *gpu, bool exclusive, struct fence *fence);
+		struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence);
 void msm_gem_move_to_inactive(struct drm_gem_object *obj);
 int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout);
 int msm_gem_cpu_fini(struct drm_gem_object *obj);
@@ -303,8 +323,8 @@ void __iomem *msm_ioremap(struct platfor
 void msm_writel(u32 data, void __iomem *addr);
 u32 msm_readl(const void __iomem *addr);
 
-#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
-#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+#define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
+#define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
 
 static inline int align_pitch(int width, int bpp)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,11 +88,11 @@ int msm_framebuffer_prepare(struct drm_f
 {
 	struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
 	int ret, i, n = drm_format_num_planes(fb->pixel_format);
-	uint32_t iova;
+	uint64_t iova;
 
 	for (i = 0; i < n; i++) {
 		ret = msm_gem_get_iova(msm_fb->planes[i], id, &iova);
-		DBG("FB[%u]: iova[%d]: %08x (%d)", fb->base.id, i, iova, ret);
+		DBG("FB[%u]: iova[%d]: %08llx (%d)", fb->base.id, i, iova, ret);
 		if (ret)
 			return ret;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,7 @@ struct msm_fbdev {
 
 static struct fb_ops msm_fb_ops = {
 	.owner = THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 
 	/* Note: to properly handle manual update displays, we wrap the
 	 * basic fbdev ops which write to the framebuffer
@@ -49,12 +50,6 @@ static struct fb_ops msm_fb_ops = {
 	.fb_copyarea = drm_fb_helper_sys_copyarea,
 	.fb_imageblit = drm_fb_helper_sys_imageblit,
 	.fb_mmap = msm_fbdev_mmap,
-
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
 };
 
 static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
@@ -81,7 +76,7 @@ static int msm_fbdev_create(struct drm_f
 	struct drm_framebuffer *fb = NULL;
 	struct fb_info *fbi = NULL;
 	struct drm_mode_fb_cmd2 mode_cmd = {0};
-	uint32_t paddr;
+	uint64_t paddr;
 	int ret, size;
 
 	DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 #include "msm_drv.h"
 #include "msm_fence.h"
@@ -32,7 +32,7 @@ msm_fence_context_alloc(struct drm_devic
 
 	fctx->dev = dev;
 	fctx->name = name;
-	fctx->context = fence_context_alloc(1);
+	fctx->context = dma_fence_context_alloc(1);
 	init_waitqueue_head(&fctx->event);
 	spin_lock_init(&fctx->spinlock);
 
@@ -100,52 +100,52 @@ void msm_update_fence(struct msm_fence_c
 
 struct msm_fence {
 	struct msm_fence_context *fctx;
-	struct fence base;
+	struct dma_fence base;
 };
 
-static inline struct msm_fence *to_msm_fence(struct fence *fence)
+static inline struct msm_fence *to_msm_fence(struct dma_fence *fence)
 {
 	return container_of(fence, struct msm_fence, base);
 }
 
-static const char *msm_fence_get_driver_name(struct fence *fence)
+static const char *msm_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "msm";
 }
 
-static const char *msm_fence_get_timeline_name(struct fence *fence)
+static const char *msm_fence_get_timeline_name(struct dma_fence *fence)
 {
 	struct msm_fence *f = to_msm_fence(fence);
 	return f->fctx->name;
 }
 
-static bool msm_fence_enable_signaling(struct fence *fence)
+static bool msm_fence_enable_signaling(struct dma_fence *fence)
 {
 	return true;
 }
 
-static bool msm_fence_signaled(struct fence *fence)
+static bool msm_fence_signaled(struct dma_fence *fence)
 {
 	struct msm_fence *f = to_msm_fence(fence);
 	return fence_completed(f->fctx, f->base.seqno);
 }
 
-static void msm_fence_release(struct fence *fence)
+static void msm_fence_release(struct dma_fence *fence)
 {
 	struct msm_fence *f = to_msm_fence(fence);
 	kfree_rcu(f, base.rcu);
 }
 
-static const struct fence_ops msm_fence_ops = {
+static const struct dma_fence_ops msm_fence_ops = {
 	.get_driver_name = msm_fence_get_driver_name,
 	.get_timeline_name = msm_fence_get_timeline_name,
 	.enable_signaling = msm_fence_enable_signaling,
 	.signaled = msm_fence_signaled,
-	.wait = fence_default_wait,
+	.wait = dma_fence_default_wait,
 	.release = msm_fence_release,
 };
 
-struct fence *
+struct dma_fence *
 msm_fence_alloc(struct msm_fence_context *fctx)
 {
 	struct msm_fence *f;
@@ -156,8 +156,8 @@ msm_fence_alloc(struct msm_fence_context
 
 	f->fctx = fctx;
 
-	fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
-			fctx->context, ++fctx->last_fence);
+	dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
+		       fctx->context, ++fctx->last_fence);
 
 	return &f->base;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fence.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fence.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_fence.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_fence.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,6 @@ int msm_queue_fence_cb(struct msm_fence_
 		struct msm_fence_cb *cb, uint32_t fence);
 void msm_update_fence(struct msm_fence_context *fctx, uint32_t fence);
 
-struct fence * msm_fence_alloc(struct msm_fence_context *fctx);
+struct dma_fence * msm_fence_alloc(struct msm_fence_context *fctx);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -225,16 +225,14 @@ int msm_gem_fault(struct vm_area_struct
 	}
 
 	/* We don't use vmf->pgoff since that has the fake offset: */
-	pgoff = ((unsigned long)vmf->virtual_address -
-			vma->vm_start) >> PAGE_SHIFT;
+	pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
 	pfn = page_to_pfn(pages[pgoff]);
 
-	VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+	VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
 			pfn, pfn << PAGE_SHIFT);
 
-	ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
-			__pfn_to_pfn_t(pfn, PFN_DEV));
+	ret = vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
 
 out_unlock:
 	mutex_unlock(&dev->struct_mutex);
@@ -296,12 +294,10 @@ put_iova(struct drm_gem_object *obj)
 	WARN_ON(!mutex_is_locked(&dev->struct_mutex));
 
 	for (id = 0; id < ARRAY_SIZE(msm_obj->domain); id++) {
-		struct msm_mmu *mmu = priv->mmus[id];
-		if (mmu && msm_obj->domain[id].iova) {
-			uint32_t offset = msm_obj->domain[id].iova;
-			mmu->funcs->unmap(mmu, offset, msm_obj->sgt, obj->size);
-			msm_obj->domain[id].iova = 0;
-		}
+		if (!priv->aspace[id])
+			continue;
+		msm_gem_unmap_vma(priv->aspace[id],
+				&msm_obj->domain[id], msm_obj->sgt);
 	}
 }
 
@@ -313,7 +309,7 @@ put_iova(struct drm_gem_object *obj)
  * the refcnt counter needs to be atomic_t.
  */
 int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id,
-		uint32_t *iova)
+		uint64_t *iova)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	int ret = 0;
@@ -326,16 +322,8 @@ int msm_gem_get_iova_locked(struct drm_g
 			return PTR_ERR(pages);
 
 		if (iommu_present(&platform_bus_type)) {
-			struct msm_mmu *mmu = priv->mmus[id];
-			uint32_t offset;
-
-			if (WARN_ON(!mmu))
-				return -EINVAL;
-
-			offset = (uint32_t)mmap_offset(obj);
-			ret = mmu->funcs->map(mmu, offset, msm_obj->sgt,
-					obj->size, IOMMU_READ | IOMMU_WRITE);
-			msm_obj->domain[id].iova = offset;
+			ret = msm_gem_map_vma(priv->aspace[id], &msm_obj->domain[id],
+					msm_obj->sgt, obj->size >> PAGE_SHIFT);
 		} else {
 			msm_obj->domain[id].iova = physaddr(obj);
 		}
@@ -348,7 +336,7 @@ int msm_gem_get_iova_locked(struct drm_g
 }
 
 /* get iova, taking a reference.  Should have a matching put */
-int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint32_t *iova)
+int msm_gem_get_iova(struct drm_gem_object *obj, int id, uint64_t *iova)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	int ret;
@@ -370,7 +358,7 @@ int msm_gem_get_iova(struct drm_gem_obje
 /* get iova without taking a reference, used in places where you have
  * already done a 'msm_gem_get_iova()'.
  */
-uint32_t msm_gem_iova(struct drm_gem_object *obj, int id)
+uint64_t msm_gem_iova(struct drm_gem_object *obj, int id)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	WARN_ON(!msm_obj->domain[id].iova);
@@ -521,7 +509,7 @@ int msm_gem_sync_object(struct drm_gem_o
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	struct reservation_object_list *fobj;
-	struct fence *fence;
+	struct dma_fence *fence;
 	int i, ret;
 
 	if (!exclusive) {
@@ -540,7 +528,7 @@ int msm_gem_sync_object(struct drm_gem_o
 		fence = reservation_object_get_excl(msm_obj->resv);
 		/* don't need to wait on our own fences, since ring is fifo */
 		if (fence && (fence->context != fctx->context)) {
-			ret = fence_wait(fence, true);
+			ret = dma_fence_wait(fence, true);
 			if (ret)
 				return ret;
 		}
@@ -553,7 +541,7 @@ int msm_gem_sync_object(struct drm_gem_o
 		fence = rcu_dereference_protected(fobj->shared[i],
 						reservation_object_held(msm_obj->resv));
 		if (fence->context != fctx->context) {
-			ret = fence_wait(fence, true);
+			ret = dma_fence_wait(fence, true);
 			if (ret)
 				return ret;
 		}
@@ -563,7 +551,7 @@ int msm_gem_sync_object(struct drm_gem_o
 }
 
 void msm_gem_move_to_active(struct drm_gem_object *obj,
-		struct msm_gpu *gpu, bool exclusive, struct fence *fence)
+		struct msm_gpu *gpu, bool exclusive, struct dma_fence *fence)
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED);
@@ -616,10 +604,10 @@ int msm_gem_cpu_fini(struct drm_gem_obje
 }
 
 #ifdef CONFIG_DEBUG_FS
-static void describe_fence(struct fence *fence, const char *type,
+static void describe_fence(struct dma_fence *fence, const char *type,
 		struct seq_file *m)
 {
-	if (!fence_is_signaled(fence))
+	if (!dma_fence_is_signaled(fence))
 		seq_printf(m, "\t%9s: %s %s seq %u\n", type,
 				fence->ops->get_driver_name(fence),
 				fence->ops->get_timeline_name(fence),
@@ -631,9 +619,11 @@ void msm_gem_describe(struct drm_gem_obj
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 	struct reservation_object *robj = msm_obj->resv;
 	struct reservation_object_list *fobj;
-	struct fence *fence;
+	struct msm_drm_private *priv = obj->dev->dev_private;
+	struct dma_fence *fence;
 	uint64_t off = drm_vma_node_start(&obj->vma_node);
 	const char *madv;
+	unsigned id;
 
 	WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
 
@@ -650,10 +640,15 @@ void msm_gem_describe(struct drm_gem_obj
 		break;
 	}
 
-	seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu%s\n",
+	seq_printf(m, "%08x: %c %2d (%2d) %08llx %p\t",
 			msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
 			obj->name, obj->refcount.refcount.counter,
-			off, msm_obj->vaddr, obj->size, madv);
+			off, msm_obj->vaddr);
+
+	for (id = 0; id < priv->num_aspaces; id++)
+		seq_printf(m, " %08llx", msm_obj->domain[id].iova);
+
+	seq_printf(m, " %zu%s\n", obj->size, madv);
 
 	rcu_read_lock();
 	fobj = rcu_dereference(robj->fence);
@@ -761,7 +756,6 @@ static int msm_gem_new_impl(struct drm_d
 {
 	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_gem_object *msm_obj;
-	unsigned sz;
 	bool use_vram = false;
 
 	switch (flags & MSM_BO_CACHE_MASK) {
@@ -783,16 +777,12 @@ static int msm_gem_new_impl(struct drm_d
 	if (WARN_ON(use_vram && !priv->vram.size))
 		return -EINVAL;
 
-	sz = sizeof(*msm_obj);
-	if (use_vram)
-		sz += sizeof(struct drm_mm_node);
-
-	msm_obj = kzalloc(sz, GFP_KERNEL);
+	msm_obj = kzalloc(sizeof(*msm_obj), GFP_KERNEL);
 	if (!msm_obj)
 		return -ENOMEM;
 
 	if (use_vram)
-		msm_obj->vram_node = (void *)&msm_obj[1];
+		msm_obj->vram_node = &msm_obj->domain[0].node;
 
 	msm_obj->flags = flags;
 	msm_obj->madv = MSM_MADV_WILLNEED;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,20 @@
 /* Additional internal-use only BO flags: */
 #define MSM_BO_STOLEN        0x10000000    /* try to use stolen/splash memory */
 
+struct msm_gem_address_space {
+	const char *name;
+	/* NOTE: mm managed at the page level, size is in # of pages
+	 * and position mm_node->start is in # of pages:
+	 */
+	struct drm_mm mm;
+	struct msm_mmu *mmu;
+};
+
+struct msm_gem_vma {
+	struct drm_mm_node node;
+	uint64_t iova;
+};
+
 struct msm_gem_object {
 	struct drm_gem_object base;
 
@@ -61,10 +75,7 @@ struct msm_gem_object {
 	struct sg_table *sgt;
 	void *vaddr;
 
-	struct {
-		// XXX
-		uint32_t iova;
-	} domain[NUM_DOMAINS];
+	struct msm_gem_vma domain[NUM_DOMAINS];
 
 	/* normally (resv == &_resv) except for imported bo's */
 	struct reservation_object *resv;
@@ -104,7 +115,7 @@ struct msm_gem_submit {
 	struct list_head node;   /* node in gpu submit_list */
 	struct list_head bo_list;
 	struct ww_acquire_ctx ticket;
-	struct fence *fence;
+	struct dma_fence *fence;
 	struct pid *pid;    /* submitting process */
 	bool valid;         /* true if no cmdstream patching needed */
 	unsigned int nr_cmds;
@@ -112,13 +123,13 @@ struct msm_gem_submit {
 	struct {
 		uint32_t type;
 		uint32_t size;  /* in dwords */
-		uint32_t iova;
+		uint64_t iova;
 		uint32_t idx;   /* cmdstream buffer idx in bos[] */
 	} *cmd;  /* array of size nr_cmds */
 	struct {
 		uint32_t flags;
 		struct msm_gem_object *obj;
-		uint32_t iova;
+		uint64_t iova;
 	} bos[0];
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem_shrinker.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem_shrinker.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem_shrinker.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem_shrinker.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,33 +18,24 @@
 #include "msm_drv.h"
 #include "msm_gem.h"
 
-static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
+static bool msm_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
 {
-	if (!mutex_is_locked(mutex))
+	switch (mutex_trylock_recursive(&dev->struct_mutex)) {
+	case MUTEX_TRYLOCK_FAILED:
 		return false;
 
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
-	return mutex->owner == task;
-#else
-	/* Since UP may be pre-empted, we cannot assume that we own the lock */
-	return false;
-#endif
-}
+	case MUTEX_TRYLOCK_SUCCESS:
+		*unlock = true;
+		return true;
 
-static bool msm_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
-{
-	if (!mutex_trylock(&dev->struct_mutex)) {
-		if (!mutex_is_locked_by(&dev->struct_mutex, current))
-			return false;
+	case MUTEX_TRYLOCK_RECURSIVE:
 		*unlock = false;
-	} else {
-		*unlock = true;
+		return true;
 	}
 
-	return true;
+	BUG();
 }
 
-
 static unsigned long
 msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem_submit.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem_submit.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem_submit.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem_submit.c	2017-02-12 16:03:20.000000000 -0500
@@ -60,7 +60,7 @@ static struct msm_gem_submit *submit_cre
 
 void msm_gem_submit_free(struct msm_gem_submit *submit)
 {
-	fence_put(submit->fence);
+	dma_fence_put(submit->fence);
 	list_del(&submit->node);
 	put_pid(submit->pid);
 	kfree(submit);
@@ -106,7 +106,8 @@ static int submit_lookup_objects(struct
 			pagefault_disable();
 		}
 
-		if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) {
+		if ((submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) ||
+			!(submit_bo.flags & MSM_SUBMIT_BO_FLAGS)) {
 			DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
 			ret = -EINVAL;
 			goto out_unlock;
@@ -241,7 +242,7 @@ static int submit_pin_objects(struct msm
 
 	for (i = 0; i < submit->nr_bos; i++) {
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
-		uint32_t iova;
+		uint64_t iova;
 
 		/* if locking succeeded, pin bo: */
 		ret = msm_gem_get_iova_locked(&msm_obj->base,
@@ -266,7 +267,7 @@ static int submit_pin_objects(struct msm
 }
 
 static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
-		struct msm_gem_object **obj, uint32_t *iova, bool *valid)
+		struct msm_gem_object **obj, uint64_t *iova, bool *valid)
 {
 	if (idx >= submit->nr_bos) {
 		DRM_ERROR("invalid buffer index: %u (out of %u)\n",
@@ -290,7 +291,7 @@ static int submit_reloc(struct msm_gem_s
 {
 	uint32_t i, last_offset = 0;
 	uint32_t *ptr;
-	int ret;
+	int ret = 0;
 
 	if (offset % 4) {
 		DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
@@ -312,17 +313,19 @@ static int submit_reloc(struct msm_gem_s
 		struct drm_msm_gem_submit_reloc submit_reloc;
 		void __user *userptr =
 			u64_to_user_ptr(relocs + (i * sizeof(submit_reloc)));
-		uint32_t iova, off;
+		uint32_t off;
+		uint64_t iova;
 		bool valid;
 
 		ret = copy_from_user(&submit_reloc, userptr, sizeof(submit_reloc));
 		if (ret)
-			return -EFAULT;
+			goto out;
 
 		if (submit_reloc.submit_offset % 4) {
 			DRM_ERROR("non-aligned reloc offset: %u\n",
 					submit_reloc.submit_offset);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 
 		/* offset in dwords: */
@@ -331,12 +334,13 @@ static int submit_reloc(struct msm_gem_s
 		if ((off >= (obj->base.size / 4)) ||
 				(off < last_offset)) {
 			DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out;
 		}
 
 		ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid);
 		if (ret)
-			return ret;
+			goto out;
 
 		if (valid)
 			continue;
@@ -353,9 +357,10 @@ static int submit_reloc(struct msm_gem_s
 		last_offset = off;
 	}
 
+out:
 	msm_gem_put_vaddr_locked(&obj->base);
 
-	return 0;
+	return ret;
 }
 
 static void submit_cleanup(struct msm_gem_submit *submit)
@@ -380,7 +385,7 @@ int msm_ioctl_gem_submit(struct drm_devi
 	struct msm_file_private *ctx = file->driver_priv;
 	struct msm_gem_submit *submit;
 	struct msm_gpu *gpu = priv->gpu;
-	struct fence *in_fence = NULL;
+	struct dma_fence *in_fence = NULL;
 	struct sync_file *sync_file = NULL;
 	int out_fence_fd = -1;
 	unsigned i;
@@ -439,7 +444,7 @@ int msm_ioctl_gem_submit(struct drm_devi
 		 */
 
 		if (in_fence->context != gpu->fctx->context) {
-			ret = fence_wait(in_fence, true);
+			ret = dma_fence_wait(in_fence, true);
 			if (ret)
 				goto out;
 		}
@@ -461,7 +466,7 @@ int msm_ioctl_gem_submit(struct drm_devi
 		void __user *userptr =
 			u64_to_user_ptr(args->cmds + (i * sizeof(submit_cmd)));
 		struct msm_gem_object *msm_obj;
-		uint32_t iova;
+		uint64_t iova;
 
 		ret = copy_from_user(&submit_cmd, userptr, sizeof(submit_cmd));
 		if (ret) {
@@ -542,7 +547,7 @@ int msm_ioctl_gem_submit(struct drm_devi
 
 out:
 	if (in_fence)
-		fence_put(in_fence);
+		dma_fence_put(in_fence);
 	submit_cleanup(submit);
 	if (ret)
 		msm_gem_submit_free(submit);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem_vma.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem_vma.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gem_vma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gem_vma.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 Red Hat
+ * Author: Rob Clark <robdclark@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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 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 "msm_drv.h"
+#include "msm_gem.h"
+#include "msm_mmu.h"
+
+void
+msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
+		struct msm_gem_vma *vma, struct sg_table *sgt)
+{
+	if (!vma->iova)
+		return;
+
+	if (aspace->mmu) {
+		unsigned size = vma->node.size << PAGE_SHIFT;
+		aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, sgt, size);
+	}
+
+	drm_mm_remove_node(&vma->node);
+
+	vma->iova = 0;
+}
+
+int
+msm_gem_map_vma(struct msm_gem_address_space *aspace,
+		struct msm_gem_vma *vma, struct sg_table *sgt, int npages)
+{
+	int ret;
+
+	if (WARN_ON(drm_mm_node_allocated(&vma->node)))
+		return 0;
+
+	ret = drm_mm_insert_node(&aspace->mm, &vma->node, npages,
+			0, DRM_MM_SEARCH_DEFAULT);
+	if (ret)
+		return ret;
+
+	vma->iova = vma->node.start << PAGE_SHIFT;
+
+	if (aspace->mmu) {
+		unsigned size = npages << PAGE_SHIFT;
+		ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt,
+				size, IOMMU_READ | IOMMU_WRITE);
+	}
+
+	return ret;
+}
+
+void
+msm_gem_address_space_destroy(struct msm_gem_address_space *aspace)
+{
+	drm_mm_takedown(&aspace->mm);
+	if (aspace->mmu)
+		aspace->mmu->funcs->destroy(aspace->mmu);
+	kfree(aspace);
+}
+
+struct msm_gem_address_space *
+msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain,
+		const char *name)
+{
+	struct msm_gem_address_space *aspace;
+
+	aspace = kzalloc(sizeof(*aspace), GFP_KERNEL);
+	if (!aspace)
+		return ERR_PTR(-ENOMEM);
+
+	aspace->name = name;
+	aspace->mmu = msm_iommu_new(dev, domain);
+
+	drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT),
+			(domain->geometry.aperture_end >> PAGE_SHIFT) - 1);
+
+	return aspace;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gpu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gpu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -91,21 +91,20 @@ static int disable_pwrrail(struct msm_gp
 
 static int enable_clk(struct msm_gpu *gpu)
 {
-	struct clk *rate_clk = NULL;
 	int i;
 
-	/* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
-	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
-		if (gpu->grp_clks[i]) {
-			clk_prepare(gpu->grp_clks[i]);
-			rate_clk = gpu->grp_clks[i];
-		}
-	}
+	if (gpu->grp_clks[0] && gpu->fast_rate)
+		clk_set_rate(gpu->grp_clks[0], gpu->fast_rate);
 
-	if (rate_clk && gpu->fast_rate)
-		clk_set_rate(rate_clk, gpu->fast_rate);
+	/* Set the RBBM timer rate to 19.2Mhz */
+	if (gpu->grp_clks[2])
+		clk_set_rate(gpu->grp_clks[2], 19200000);
 
-	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
+	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+		if (gpu->grp_clks[i])
+			clk_prepare(gpu->grp_clks[i]);
+
+	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
 		if (gpu->grp_clks[i])
 			clk_enable(gpu->grp_clks[i]);
 
@@ -114,24 +113,22 @@ static int enable_clk(struct msm_gpu *gp
 
 static int disable_clk(struct msm_gpu *gpu)
 {
-	struct clk *rate_clk = NULL;
 	int i;
 
-	/* NOTE: kgsl_pwrctrl_clk() ignores grp_clks[0].. */
-	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--) {
-		if (gpu->grp_clks[i]) {
+	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
+		if (gpu->grp_clks[i])
 			clk_disable(gpu->grp_clks[i]);
-			rate_clk = gpu->grp_clks[i];
-		}
-	}
 
-	if (rate_clk && gpu->slow_rate)
-		clk_set_rate(rate_clk, gpu->slow_rate);
-
-	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i > 0; i--)
+	for (i = ARRAY_SIZE(gpu->grp_clks) - 1; i >= 0; i--)
 		if (gpu->grp_clks[i])
 			clk_unprepare(gpu->grp_clks[i]);
 
+	if (gpu->grp_clks[0] && gpu->slow_rate)
+		clk_set_rate(gpu->grp_clks[0], gpu->slow_rate);
+
+	if (gpu->grp_clks[2])
+		clk_set_rate(gpu->grp_clks[2], 0);
+
 	return 0;
 }
 
@@ -476,7 +473,7 @@ static void retire_submits(struct msm_gp
 		submit = list_first_entry(&gpu->submit_list,
 				struct msm_gem_submit, node);
 
-		if (fence_is_signaled(submit->fence)) {
+		if (dma_fence_is_signaled(submit->fence)) {
 			retire_submit(gpu, submit);
 		} else {
 			break;
@@ -528,7 +525,7 @@ void msm_gpu_submit(struct msm_gpu *gpu,
 
 	for (i = 0; i < submit->nr_bos; i++) {
 		struct msm_gem_object *msm_obj = submit->bos[i].obj;
-		uint32_t iova;
+		uint64_t iova;
 
 		/* can't happen yet.. but when we add 2d support we'll have
 		 * to deal w/ cross-ring synchronization:
@@ -563,8 +560,8 @@ static irqreturn_t irq_handler(int irq,
 }
 
 static const char *clk_names[] = {
-		"src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk",
-		"alt_mem_iface_clk",
+		"core_clk", "iface_clk", "rbbmtimer_clk", "mem_clk",
+		"mem_iface_clk", "alt_mem_iface_clk",
 };
 
 int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
@@ -656,12 +653,17 @@ int msm_gpu_init(struct drm_device *drm,
 	 */
 	iommu = iommu_domain_alloc(&platform_bus_type);
 	if (iommu) {
+		/* TODO 32b vs 64b address space.. */
+		iommu->geometry.aperture_start = SZ_16M;
+		iommu->geometry.aperture_end = 0xffffffff;
+
 		dev_info(drm->dev, "%s: using IOMMU\n", name);
-		gpu->mmu = msm_iommu_new(&pdev->dev, iommu);
-		if (IS_ERR(gpu->mmu)) {
-			ret = PTR_ERR(gpu->mmu);
+		gpu->aspace = msm_gem_address_space_create(&pdev->dev,
+				iommu, "gpu");
+		if (IS_ERR(gpu->aspace)) {
+			ret = PTR_ERR(gpu->aspace);
 			dev_err(drm->dev, "failed to init iommu: %d\n", ret);
-			gpu->mmu = NULL;
+			gpu->aspace = NULL;
 			iommu_domain_free(iommu);
 			goto fail;
 		}
@@ -669,7 +671,7 @@ int msm_gpu_init(struct drm_device *drm,
 	} else {
 		dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
 	}
-	gpu->id = msm_register_mmu(drm, gpu->mmu);
+	gpu->id = msm_register_address_space(drm, gpu->aspace);
 
 
 	/* Create ringbuffer: */
@@ -705,8 +707,8 @@ void msm_gpu_cleanup(struct msm_gpu *gpu
 		msm_ringbuffer_destroy(gpu->rb);
 	}
 
-	if (gpu->mmu)
-		gpu->mmu->funcs->destroy(gpu->mmu);
+	if (gpu->aspace)
+		msm_gem_address_space_destroy(gpu->aspace);
 
 	if (gpu->fctx)
 		msm_fence_context_free(gpu->fctx);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gpu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gpu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_gpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_gpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -50,7 +50,7 @@ struct msm_gpu_funcs {
 	void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit,
 			struct msm_file_private *ctx);
 	void (*flush)(struct msm_gpu *gpu);
-	void (*idle)(struct msm_gpu *gpu);
+	bool (*idle)(struct msm_gpu *gpu);
 	irqreturn_t (*irq)(struct msm_gpu *irq);
 	uint32_t (*last_fence)(struct msm_gpu *gpu);
 	void (*recover)(struct msm_gpu *gpu);
@@ -80,7 +80,7 @@ struct msm_gpu {
 
 	/* ringbuffer: */
 	struct msm_ringbuffer *rb;
-	uint32_t rb_iova;
+	uint64_t rb_iova;
 
 	/* list of GEM active objects: */
 	struct list_head active_list;
@@ -98,7 +98,7 @@ struct msm_gpu {
 	void __iomem *mmio;
 	int irq;
 
-	struct msm_mmu *mmu;
+	struct msm_gem_address_space *aspace;
 	int id;
 
 	/* Power Control: */
@@ -154,6 +154,45 @@ static inline u32 gpu_read(struct msm_gp
 	return msm_readl(gpu->mmio + (reg << 2));
 }
 
+static inline void gpu_rmw(struct msm_gpu *gpu, u32 reg, u32 mask, u32 or)
+{
+	uint32_t val = gpu_read(gpu, reg);
+
+	val &= ~mask;
+	gpu_write(gpu, reg, val | or);
+}
+
+static inline u64 gpu_read64(struct msm_gpu *gpu, u32 lo, u32 hi)
+{
+	u64 val;
+
+	/*
+	 * Why not a readq here? Two reasons: 1) many of the LO registers are
+	 * not quad word aligned and 2) the GPU hardware designers have a bit
+	 * of a history of putting registers where they fit, especially in
+	 * spins. The longer a GPU family goes the higher the chance that
+	 * we'll get burned.  We could do a series of validity checks if we
+	 * wanted to, but really is a readq() that much better? Nah.
+	 */
+
+	/*
+	 * For some lo/hi registers (like perfcounters), the hi value is latched
+	 * when the lo is read, so make sure to read the lo first to trigger
+	 * that
+	 */
+	val = (u64) msm_readl(gpu->mmio + (lo << 2));
+	val |= ((u64) msm_readl(gpu->mmio + (hi << 2)) << 32);
+
+	return val;
+}
+
+static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
+{
+	/* Why not a writeq here? Read the screed above */
+	msm_writel(lower_32_bits(val), gpu->mmio + (lo << 2));
+	msm_writel(upper_32_bits(val), gpu->mmio + (hi << 2));
+}
+
 int msm_gpu_pm_suspend(struct msm_gpu *gpu);
 int msm_gpu_pm_resume(struct msm_gpu *gpu);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_iommu.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_iommu.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,13 +45,13 @@ static void msm_iommu_detach(struct msm_
 	iommu_detach_device(iommu->domain, mmu->dev);
 }
 
-static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
+static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
 		struct sg_table *sgt, unsigned len, int prot)
 {
 	struct msm_iommu *iommu = to_msm_iommu(mmu);
 	struct iommu_domain *domain = iommu->domain;
 	struct scatterlist *sg;
-	unsigned int da = iova;
+	unsigned long da = iova;
 	unsigned int i, j;
 	int ret;
 
@@ -62,7 +62,7 @@ static int msm_iommu_map(struct msm_mmu
 		dma_addr_t pa = sg_phys(sg) - sg->offset;
 		size_t bytes = sg->length + sg->offset;
 
-		VERB("map[%d]: %08x %08lx(%zx)", i, da, (unsigned long)pa, bytes);
+		VERB("map[%d]: %08lx %08lx(%zx)", i, da, (unsigned long)pa, bytes);
 
 		ret = iommu_map(domain, da, pa, bytes, prot);
 		if (ret)
@@ -84,13 +84,13 @@ fail:
 	return ret;
 }
 
-static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova,
+static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova,
 		struct sg_table *sgt, unsigned len)
 {
 	struct msm_iommu *iommu = to_msm_iommu(mmu);
 	struct iommu_domain *domain = iommu->domain;
 	struct scatterlist *sg;
-	unsigned int da = iova;
+	unsigned long da = iova;
 	int i;
 
 	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
@@ -101,7 +101,7 @@ static int msm_iommu_unmap(struct msm_mm
 		if (unmapped < bytes)
 			return unmapped;
 
-		VERB("unmap[%d]: %08x(%zx)", i, da, bytes);
+		VERB("unmap[%d]: %08lx(%zx)", i, da, bytes);
 
 		BUG_ON(!PAGE_ALIGNED(bytes));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_kms.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_kms.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_kms.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_kms.h	2017-02-12 16:03:20.000000000 -0500
@@ -40,6 +40,8 @@ struct msm_kms_funcs {
 	irqreturn_t (*irq)(struct msm_kms *kms);
 	int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
 	void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
+	/* swap global atomic state: */
+	void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
 	/* modeset, bracketing atomic_commit(): */
 	void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
 	void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
@@ -56,6 +58,11 @@ struct msm_kms_funcs {
 			bool is_cmd_mode);
 	/* cleanup: */
 	void (*destroy)(struct msm_kms *kms);
+#ifdef CONFIG_DEBUG_FS
+	/* debugfs: */
+	int (*debugfs_init)(struct msm_kms *kms, struct drm_minor *minor);
+	void (*debugfs_cleanup)(struct msm_kms *kms, struct drm_minor *minor);
+#endif
 };
 
 struct msm_kms {
@@ -65,6 +72,18 @@ struct msm_kms {
 	int irq;
 };
 
+/**
+ * Subclass of drm_atomic_state, to allow kms backend to have driver
+ * private global state.  The kms backend can do whatever it wants
+ * with the ->state ptr.  On ->atomic_state_clear() the ->state ptr
+ * is kfree'd and set back to NULL.
+ */
+struct msm_kms_state {
+	struct drm_atomic_state base;
+	void *state;
+};
+#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
+
 static inline void msm_kms_init(struct msm_kms *kms,
 		const struct msm_kms_funcs *funcs)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_mmu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_mmu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_mmu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_mmu.h	2017-02-12 16:03:20.000000000 -0500
@@ -23,9 +23,9 @@
 struct msm_mmu_funcs {
 	int (*attach)(struct msm_mmu *mmu, const char * const *names, int cnt);
 	void (*detach)(struct msm_mmu *mmu, const char * const *names, int cnt);
-	int (*map)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+	int (*map)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
 			unsigned len, int prot);
-	int (*unmap)(struct msm_mmu *mmu, uint32_t iova, struct sg_table *sgt,
+	int (*unmap)(struct msm_mmu *mmu, uint64_t iova, struct sg_table *sgt,
 			unsigned len);
 	void (*destroy)(struct msm_mmu *mmu);
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_rd.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_rd.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_rd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_rd.c	2017-02-12 16:03:20.000000000 -0500
@@ -289,7 +289,7 @@ void msm_rd_debugfs_cleanup(struct drm_m
 
 static void snapshot_buf(struct msm_rd_state *rd,
 		struct msm_gem_submit *submit, int idx,
-		uint32_t iova, uint32_t size)
+		uint64_t iova, uint32_t size)
 {
 	struct msm_gem_object *obj = submit->bos[idx].obj;
 	const char *buf;
@@ -306,7 +306,7 @@ static void snapshot_buf(struct msm_rd_s
 	}
 
 	rd_write_section(rd, RD_GPUADDR,
-			(uint32_t[2]){ iova, size }, 8);
+			(uint32_t[3]){ iova, size, iova >> 32 }, 12);
 	rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size);
 
 	msm_gem_put_vaddr_locked(&obj->base);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/msm/msm_ringbuffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,8 @@ struct msm_ringbuffer *msm_ringbuffer_ne
 	struct msm_ringbuffer *ring;
 	int ret;
 
-	size = ALIGN(size, 4);   /* size should be dword aligned */
+	if (WARN_ON(!is_power_of_2(size)))
+		return ERR_PTR(-EINVAL);
 
 	ring = kzalloc(sizeof(*ring), GFP_KERNEL);
 	if (!ring) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,19 @@
+config DRM_MXS
+	bool
+	help
+	  Choose this option to select drivers for MXS FB devices
+
+config DRM_MXSFB
+	tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
+	depends on DRM && OF
+	depends on COMMON_CLK
+	select DRM_MXS
+	select DRM_KMS_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_PANEL
+	help
+	  Choose this option if you have an i.MX23/i.MX28/i.MX6SX MXSFB
+	  LCD controller.
+
+	  If M is selected the module will be called mxsfb.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2 @@
+mxsfb-y := mxsfb_drv.o mxsfb_crtc.o mxsfb_out.o
+obj-$(CONFIG_DRM_MXSFB)	+= mxsfb.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_crtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * This code is based on drivers/video/fbdev/mxsfb.c :
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/of_graph.h>
+#include <linux/platform_data/simplefb.h>
+#include <video/videomode.h>
+
+#include "mxsfb_drv.h"
+#include "mxsfb_regs.h"
+
+static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
+{
+	return (val & mxsfb->devdata->hs_wdth_mask) <<
+		mxsfb->devdata->hs_wdth_shift;
+}
+
+/* Setup the MXSFB registers for decoding the pixels out of the framebuffer */
+static int mxsfb_set_pixel_fmt(struct mxsfb_drm_private *mxsfb)
+{
+	struct drm_crtc *crtc = &mxsfb->pipe.crtc;
+	struct drm_device *drm = crtc->dev;
+	const u32 format = crtc->primary->state->fb->pixel_format;
+	u32 ctrl, ctrl1;
+
+	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER;
+
+	/*
+	 * WARNING: The bus width, CTRL_SET_BUS_WIDTH(), is configured to
+	 * match the selected mode here. This differs from the original
+	 * MXSFB driver, which had the option to configure the bus width
+	 * to arbitrary value. This limitation should not pose an issue.
+	 */
+
+	/* CTRL1 contains IRQ config and status bits, preserve those. */
+	ctrl1 = readl(mxsfb->base + LCDC_CTRL1);
+	ctrl1 &= CTRL1_CUR_FRAME_DONE_IRQ_EN | CTRL1_CUR_FRAME_DONE_IRQ;
+
+	switch (format) {
+	case DRM_FORMAT_RGB565:
+		dev_dbg(drm->dev, "Setting up RGB565 mode\n");
+		ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_16BIT);
+		ctrl |= CTRL_SET_WORD_LENGTH(0);
+		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0xf);
+		break;
+	case DRM_FORMAT_XRGB8888:
+		dev_dbg(drm->dev, "Setting up XRGB8888 mode\n");
+		ctrl |= CTRL_SET_BUS_WIDTH(STMLCDIF_24BIT);
+		ctrl |= CTRL_SET_WORD_LENGTH(3);
+		/* Do not use packed pixels = one pixel per word instead. */
+		ctrl1 |= CTRL1_SET_BYTE_PACKAGING(0x7);
+		break;
+	default:
+		dev_err(drm->dev, "Unhandled pixel format %08x\n", format);
+		return -EINVAL;
+	}
+
+	writel(ctrl1, mxsfb->base + LCDC_CTRL1);
+	writel(ctrl, mxsfb->base + LCDC_CTRL);
+
+	return 0;
+}
+
+static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
+{
+	u32 reg;
+
+	if (mxsfb->clk_disp_axi)
+		clk_prepare_enable(mxsfb->clk_disp_axi);
+	clk_prepare_enable(mxsfb->clk);
+	mxsfb_enable_axi_clk(mxsfb);
+
+	/* If it was disabled, re-enable the mode again */
+	writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
+
+	/* Enable the SYNC signals first, then the DMA engine */
+	reg = readl(mxsfb->base + LCDC_VDCTRL4);
+	reg |= VDCTRL4_SYNC_SIGNALS_ON;
+	writel(reg, mxsfb->base + LCDC_VDCTRL4);
+
+	writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
+}
+
+static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
+{
+	u32 reg;
+
+	/*
+	 * Even if we disable the controller here, it will still continue
+	 * until its FIFOs are running out of data
+	 */
+	writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_CLR);
+
+	readl_poll_timeout(mxsfb->base + LCDC_CTRL, reg, !(reg & CTRL_RUN),
+			   0, 1000);
+
+	reg = readl(mxsfb->base + LCDC_VDCTRL4);
+	reg &= ~VDCTRL4_SYNC_SIGNALS_ON;
+	writel(reg, mxsfb->base + LCDC_VDCTRL4);
+
+	mxsfb_disable_axi_clk(mxsfb);
+
+	clk_disable_unprepare(mxsfb->clk);
+	if (mxsfb->clk_disp_axi)
+		clk_disable_unprepare(mxsfb->clk_disp_axi);
+}
+
+static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
+{
+	struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
+	const u32 bus_flags = mxsfb->connector.display_info.bus_flags;
+	u32 vdctrl0, vsync_pulse_len, hsync_pulse_len;
+	int err;
+
+	/*
+	 * It seems, you can't re-program the controller if it is still
+	 * running. This may lead to shifted pictures (FIFO issue?), so
+	 * first stop the controller and drain its FIFOs.
+	 */
+	mxsfb_enable_axi_clk(mxsfb);
+
+	/* Clear the FIFOs */
+	writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
+
+	err = mxsfb_set_pixel_fmt(mxsfb);
+	if (err)
+		return;
+
+	clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
+
+	writel(TRANSFER_COUNT_SET_VCOUNT(m->crtc_vdisplay) |
+	       TRANSFER_COUNT_SET_HCOUNT(m->crtc_hdisplay),
+	       mxsfb->base + mxsfb->devdata->transfer_count);
+
+	vsync_pulse_len = m->crtc_vsync_end - m->crtc_vsync_start;
+
+	vdctrl0 = VDCTRL0_ENABLE_PRESENT |	/* Always in DOTCLOCK mode */
+		  VDCTRL0_VSYNC_PERIOD_UNIT |
+		  VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
+		  VDCTRL0_SET_VSYNC_PULSE_WIDTH(vsync_pulse_len);
+	if (m->flags & DRM_MODE_FLAG_PHSYNC)
+		vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
+	if (m->flags & DRM_MODE_FLAG_PVSYNC)
+		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
+	if (bus_flags & DRM_BUS_FLAG_DE_HIGH)
+		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
+	if (bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
+		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING;
+
+	writel(vdctrl0, mxsfb->base + LCDC_VDCTRL0);
+
+	/* Frame length in lines. */
+	writel(m->crtc_vtotal, mxsfb->base + LCDC_VDCTRL1);
+
+	/* Line length in units of clocks or pixels. */
+	hsync_pulse_len = m->crtc_hsync_end - m->crtc_hsync_start;
+	writel(set_hsync_pulse_width(mxsfb, hsync_pulse_len) |
+	       VDCTRL2_SET_HSYNC_PERIOD(m->crtc_htotal),
+	       mxsfb->base + LCDC_VDCTRL2);
+
+	writel(SET_HOR_WAIT_CNT(m->crtc_hblank_end - m->crtc_hsync_end) |
+	       SET_VERT_WAIT_CNT(m->crtc_vblank_end - m->crtc_vsync_end),
+	       mxsfb->base + LCDC_VDCTRL3);
+
+	writel(SET_DOTCLK_H_VALID_DATA_CNT(m->hdisplay),
+	       mxsfb->base + LCDC_VDCTRL4);
+
+	mxsfb_disable_axi_clk(mxsfb);
+}
+
+void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb)
+{
+	mxsfb_crtc_mode_set_nofb(mxsfb);
+	mxsfb_enable_controller(mxsfb);
+}
+
+void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb)
+{
+	mxsfb_disable_controller(mxsfb);
+}
+
+void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
+			       struct drm_plane_state *state)
+{
+	struct drm_simple_display_pipe *pipe = &mxsfb->pipe;
+	struct drm_crtc *crtc = &pipe->crtc;
+	struct drm_framebuffer *fb = pipe->plane.state->fb;
+	struct drm_pending_vblank_event *event;
+	struct drm_gem_cma_object *gem;
+
+	if (!crtc)
+		return;
+
+	spin_lock_irq(&crtc->dev->event_lock);
+	event = crtc->state->event;
+	if (event) {
+		crtc->state->event = NULL;
+
+		if (drm_crtc_vblank_get(crtc) == 0) {
+			drm_crtc_arm_vblank_event(crtc, event);
+		} else {
+			drm_crtc_send_vblank_event(crtc, event);
+		}
+	}
+	spin_unlock_irq(&crtc->dev->event_lock);
+
+	if (!fb)
+		return;
+
+	gem = drm_fb_cma_get_gem_obj(fb, 0);
+
+	mxsfb_enable_axi_clk(mxsfb);
+	writel(gem->paddr, mxsfb->base + mxsfb->devdata->next_buf);
+	mxsfb_disable_axi_clk(mxsfb);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * This code is based on drivers/video/fbdev/mxsfb.c :
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/list.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/pm_runtime.h>
+#include <linux/reservation.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_simple_kms_helper.h>
+
+#include "mxsfb_drv.h"
+#include "mxsfb_regs.h"
+
+enum mxsfb_devtype {
+	MXSFB_V3,
+	MXSFB_V4,
+};
+
+static const struct mxsfb_devdata mxsfb_devdata[] = {
+	[MXSFB_V3] = {
+		.transfer_count	= LCDC_V3_TRANSFER_COUNT,
+		.cur_buf	= LCDC_V3_CUR_BUF,
+		.next_buf	= LCDC_V3_NEXT_BUF,
+		.debug0		= LCDC_V3_DEBUG0,
+		.hs_wdth_mask	= 0xff,
+		.hs_wdth_shift	= 24,
+		.ipversion	= 3,
+	},
+	[MXSFB_V4] = {
+		.transfer_count	= LCDC_V4_TRANSFER_COUNT,
+		.cur_buf	= LCDC_V4_CUR_BUF,
+		.next_buf	= LCDC_V4_NEXT_BUF,
+		.debug0		= LCDC_V4_DEBUG0,
+		.hs_wdth_mask	= 0x3fff,
+		.hs_wdth_shift	= 18,
+		.ipversion	= 4,
+	},
+};
+
+static const uint32_t mxsfb_formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB565
+};
+
+static struct mxsfb_drm_private *
+drm_pipe_to_mxsfb_drm_private(struct drm_simple_display_pipe *pipe)
+{
+	return container_of(pipe, struct mxsfb_drm_private, pipe);
+}
+
+void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb)
+{
+	if (mxsfb->clk_axi)
+		clk_prepare_enable(mxsfb->clk_axi);
+}
+
+void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb)
+{
+	if (mxsfb->clk_axi)
+		clk_disable_unprepare(mxsfb->clk_axi);
+}
+
+static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
+	.fb_create		= drm_fb_cma_create,
+	.atomic_check		= drm_atomic_helper_check,
+	.atomic_commit		= drm_atomic_helper_commit,
+};
+
+static void mxsfb_pipe_enable(struct drm_simple_display_pipe *pipe,
+			      struct drm_crtc_state *crtc_state)
+{
+	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+
+	mxsfb_crtc_enable(mxsfb);
+}
+
+static void mxsfb_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+
+	mxsfb_crtc_disable(mxsfb);
+}
+
+static void mxsfb_pipe_update(struct drm_simple_display_pipe *pipe,
+			      struct drm_plane_state *plane_state)
+{
+	struct mxsfb_drm_private *mxsfb = drm_pipe_to_mxsfb_drm_private(pipe);
+
+	mxsfb_plane_atomic_update(mxsfb, plane_state);
+}
+
+static int mxsfb_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
+				 struct drm_plane_state *plane_state)
+{
+	return drm_fb_cma_prepare_fb(&pipe->plane, plane_state);
+}
+
+struct drm_simple_display_pipe_funcs mxsfb_funcs = {
+	.enable		= mxsfb_pipe_enable,
+	.disable	= mxsfb_pipe_disable,
+	.update		= mxsfb_pipe_update,
+	.prepare_fb	= mxsfb_pipe_prepare_fb,
+};
+
+static int mxsfb_load(struct drm_device *drm, unsigned long flags)
+{
+	struct platform_device *pdev = to_platform_device(drm->dev);
+	struct mxsfb_drm_private *mxsfb;
+	struct resource *res;
+	int ret;
+
+	mxsfb = devm_kzalloc(&pdev->dev, sizeof(*mxsfb), GFP_KERNEL);
+	if (!mxsfb)
+		return -ENOMEM;
+
+	drm->dev_private = mxsfb;
+	mxsfb->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mxsfb->base = devm_ioremap_resource(drm->dev, res);
+	if (IS_ERR(mxsfb->base))
+		return PTR_ERR(mxsfb->base);
+
+	mxsfb->clk = devm_clk_get(drm->dev, NULL);
+	if (IS_ERR(mxsfb->clk))
+		return PTR_ERR(mxsfb->clk);
+
+	mxsfb->clk_axi = devm_clk_get(drm->dev, "axi");
+	if (IS_ERR(mxsfb->clk_axi))
+		mxsfb->clk_axi = NULL;
+
+	mxsfb->clk_disp_axi = devm_clk_get(drm->dev, "disp_axi");
+	if (IS_ERR(mxsfb->clk_disp_axi))
+		mxsfb->clk_disp_axi = NULL;
+
+	ret = dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32));
+	if (ret)
+		return ret;
+
+	pm_runtime_enable(drm->dev);
+
+	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+	if (ret < 0) {
+		dev_err(drm->dev, "Failed to initialise vblank\n");
+		goto err_vblank;
+	}
+
+	/* Modeset init */
+	drm_mode_config_init(drm);
+
+	ret = mxsfb_create_output(drm);
+	if (ret < 0) {
+		dev_err(drm->dev, "Failed to create outputs\n");
+		goto err_vblank;
+	}
+
+	ret = drm_simple_display_pipe_init(drm, &mxsfb->pipe, &mxsfb_funcs,
+			mxsfb_formats, ARRAY_SIZE(mxsfb_formats),
+			&mxsfb->connector);
+	if (ret < 0) {
+		dev_err(drm->dev, "Cannot setup simple display pipe\n");
+		goto err_vblank;
+	}
+
+	ret = drm_panel_attach(mxsfb->panel, &mxsfb->connector);
+	if (ret) {
+		dev_err(drm->dev, "Cannot connect panel\n");
+		goto err_vblank;
+	}
+
+	drm->mode_config.min_width	= MXSFB_MIN_XRES;
+	drm->mode_config.min_height	= MXSFB_MIN_YRES;
+	drm->mode_config.max_width	= MXSFB_MAX_XRES;
+	drm->mode_config.max_height	= MXSFB_MAX_YRES;
+	drm->mode_config.funcs		= &mxsfb_mode_config_funcs;
+
+	drm_mode_config_reset(drm);
+
+	pm_runtime_get_sync(drm->dev);
+	ret = drm_irq_install(drm, platform_get_irq(pdev, 0));
+	pm_runtime_put_sync(drm->dev);
+
+	if (ret < 0) {
+		dev_err(drm->dev, "Failed to install IRQ handler\n");
+		goto err_irq;
+	}
+
+	drm_kms_helper_poll_init(drm);
+
+	mxsfb->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
+					  drm->mode_config.num_connector);
+	if (IS_ERR(mxsfb->fbdev)) {
+		mxsfb->fbdev = NULL;
+		dev_err(drm->dev, "Failed to init FB CMA area\n");
+		goto err_cma;
+	}
+
+	platform_set_drvdata(pdev, drm);
+
+	drm_helper_hpd_irq_event(drm);
+
+	return 0;
+
+err_cma:
+	drm_irq_uninstall(drm);
+err_irq:
+	drm_panel_detach(mxsfb->panel);
+err_vblank:
+	pm_runtime_disable(drm->dev);
+
+	return ret;
+}
+
+static void mxsfb_unload(struct drm_device *drm)
+{
+	struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+	if (mxsfb->fbdev)
+		drm_fbdev_cma_fini(mxsfb->fbdev);
+
+	drm_kms_helper_poll_fini(drm);
+	drm_mode_config_cleanup(drm);
+	drm_vblank_cleanup(drm);
+
+	pm_runtime_get_sync(drm->dev);
+	drm_irq_uninstall(drm);
+	pm_runtime_put_sync(drm->dev);
+
+	drm->dev_private = NULL;
+
+	pm_runtime_disable(drm->dev);
+}
+
+static void mxsfb_lastclose(struct drm_device *drm)
+{
+	struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(mxsfb->fbdev);
+}
+
+static int mxsfb_enable_vblank(struct drm_device *drm, unsigned int crtc)
+{
+	struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+	/* Clear and enable VBLANK IRQ */
+	mxsfb_enable_axi_clk(mxsfb);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_SET);
+	mxsfb_disable_axi_clk(mxsfb);
+
+	return 0;
+}
+
+static void mxsfb_disable_vblank(struct drm_device *drm, unsigned int crtc)
+{
+	struct mxsfb_drm_private *mxsfb = drm->dev_private;
+
+	/* Disable and clear VBLANK IRQ */
+	mxsfb_enable_axi_clk(mxsfb);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ_EN, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+	mxsfb_disable_axi_clk(mxsfb);
+}
+
+static void mxsfb_irq_preinstall(struct drm_device *drm)
+{
+	mxsfb_disable_vblank(drm, 0);
+}
+
+static irqreturn_t mxsfb_irq_handler(int irq, void *data)
+{
+	struct drm_device *drm = data;
+	struct mxsfb_drm_private *mxsfb = drm->dev_private;
+	u32 reg;
+
+	mxsfb_enable_axi_clk(mxsfb);
+
+	reg = readl(mxsfb->base + LCDC_CTRL1);
+
+	if (reg & CTRL1_CUR_FRAME_DONE_IRQ)
+		drm_crtc_handle_vblank(&mxsfb->pipe.crtc);
+
+	writel(CTRL1_CUR_FRAME_DONE_IRQ, mxsfb->base + LCDC_CTRL1 + REG_CLR);
+
+	mxsfb_disable_axi_clk(mxsfb);
+
+	return IRQ_HANDLED;
+}
+
+static const struct file_operations fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.poll		= drm_poll,
+	.read		= drm_read,
+	.llseek		= noop_llseek,
+	.mmap		= drm_gem_cma_mmap,
+};
+
+static struct drm_driver mxsfb_driver = {
+	.driver_features	= DRIVER_GEM | DRIVER_MODESET |
+				  DRIVER_PRIME | DRIVER_ATOMIC |
+				  DRIVER_HAVE_IRQ,
+	.lastclose		= mxsfb_lastclose,
+	.irq_handler		= mxsfb_irq_handler,
+	.irq_preinstall		= mxsfb_irq_preinstall,
+	.irq_uninstall		= mxsfb_irq_preinstall,
+	.get_vblank_counter	= drm_vblank_no_hw_counter,
+	.enable_vblank		= mxsfb_enable_vblank,
+	.disable_vblank		= mxsfb_disable_vblank,
+	.gem_free_object	= drm_gem_cma_free_object,
+	.gem_vm_ops		= &drm_gem_cma_vm_ops,
+	.dumb_create		= drm_gem_cma_dumb_create,
+	.dumb_map_offset	= drm_gem_cma_dumb_map_offset,
+	.dumb_destroy		= drm_gem_dumb_destroy,
+	.prime_handle_to_fd	= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle	= drm_gem_prime_fd_to_handle,
+	.gem_prime_export	= drm_gem_prime_export,
+	.gem_prime_import	= drm_gem_prime_import,
+	.gem_prime_get_sg_table	= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap		= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap	= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap		= drm_gem_cma_prime_mmap,
+	.fops	= &fops,
+	.name	= "mxsfb-drm",
+	.desc	= "MXSFB Controller DRM",
+	.date	= "20160824",
+	.major	= 1,
+	.minor	= 0,
+};
+
+static const struct platform_device_id mxsfb_devtype[] = {
+	{ .name = "imx23-fb", .driver_data = MXSFB_V3, },
+	{ .name = "imx28-fb", .driver_data = MXSFB_V4, },
+	{ .name = "imx6sx-fb", .driver_data = MXSFB_V4, },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
+
+static const struct of_device_id mxsfb_dt_ids[] = {
+	{ .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
+	{ .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
+	{ .compatible = "fsl,imx6sx-lcdif", .data = &mxsfb_devtype[2], },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
+
+static int mxsfb_probe(struct platform_device *pdev)
+{
+	struct drm_device *drm;
+	const struct of_device_id *of_id =
+			of_match_device(mxsfb_dt_ids, &pdev->dev);
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	if (of_id)
+		pdev->id_entry = of_id->data;
+
+	drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev);
+	if (!drm)
+		return -ENOMEM;
+
+	ret = mxsfb_load(drm, 0);
+	if (ret)
+		goto err_free;
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto err_unload;
+
+	return 0;
+
+err_unload:
+	mxsfb_unload(drm);
+err_free:
+	drm_dev_unref(drm);
+
+	return ret;
+}
+
+static int mxsfb_remove(struct platform_device *pdev)
+{
+	struct drm_device *drm = platform_get_drvdata(pdev);
+
+	drm_dev_unregister(drm);
+	mxsfb_unload(drm);
+	drm_dev_unref(drm);
+
+	return 0;
+}
+
+static struct platform_driver mxsfb_platform_driver = {
+	.probe		= mxsfb_probe,
+	.remove		= mxsfb_remove,
+	.id_table	= mxsfb_devtype,
+	.driver	= {
+		.name		= "mxsfb",
+		.of_match_table	= mxsfb_dt_ids,
+	},
+};
+
+module_platform_driver(mxsfb_platform_driver);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("Freescale MXS DRM/KMS driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller 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.
+ */
+
+#ifndef __MXSFB_DRV_H__
+#define __MXSFB_DRV_H__
+
+struct mxsfb_devdata {
+	unsigned int	 transfer_count;
+	unsigned int	 cur_buf;
+	unsigned int	 next_buf;
+	unsigned int	 debug0;
+	unsigned int	 hs_wdth_mask;
+	unsigned int	 hs_wdth_shift;
+	unsigned int	 ipversion;
+};
+
+struct mxsfb_drm_private {
+	const struct mxsfb_devdata	*devdata;
+
+	void __iomem			*base;	/* registers */
+	struct clk			*clk;
+	struct clk			*clk_axi;
+	struct clk			*clk_disp_axi;
+
+	struct drm_simple_display_pipe	pipe;
+	struct drm_connector		connector;
+	struct drm_panel		*panel;
+	struct drm_fbdev_cma		*fbdev;
+};
+
+int mxsfb_setup_crtc(struct drm_device *dev);
+int mxsfb_create_output(struct drm_device *dev);
+
+void mxsfb_enable_axi_clk(struct mxsfb_drm_private *mxsfb);
+void mxsfb_disable_axi_clk(struct mxsfb_drm_private *mxsfb);
+
+void mxsfb_crtc_enable(struct mxsfb_drm_private *mxsfb);
+void mxsfb_crtc_disable(struct mxsfb_drm_private *mxsfb);
+void mxsfb_plane_atomic_update(struct mxsfb_drm_private *mxsfb,
+			       struct drm_plane_state *state);
+
+#endif /* __MXSFB_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_out.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_out.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_out.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_out.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 Marek Vasut <marex@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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/of_graph.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_simple_kms_helper.h>
+#include <drm/drmP.h>
+
+#include "mxsfb_drv.h"
+
+static struct mxsfb_drm_private *
+drm_connector_to_mxsfb_drm_private(struct drm_connector *connector)
+{
+	return container_of(connector, struct mxsfb_drm_private, connector);
+}
+
+static int mxsfb_panel_get_modes(struct drm_connector *connector)
+{
+	struct mxsfb_drm_private *mxsfb =
+			drm_connector_to_mxsfb_drm_private(connector);
+
+	if (mxsfb->panel)
+		return mxsfb->panel->funcs->get_modes(mxsfb->panel);
+
+	return 0;
+}
+
+static const struct
+drm_connector_helper_funcs mxsfb_panel_connector_helper_funcs = {
+	.get_modes = mxsfb_panel_get_modes,
+};
+
+static enum drm_connector_status
+mxsfb_panel_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct mxsfb_drm_private *mxsfb =
+			drm_connector_to_mxsfb_drm_private(connector);
+
+	if (mxsfb->panel)
+		return connector_status_connected;
+
+	return connector_status_disconnected;
+}
+
+static void mxsfb_panel_connector_destroy(struct drm_connector *connector)
+{
+	struct mxsfb_drm_private *mxsfb =
+			drm_connector_to_mxsfb_drm_private(connector);
+
+	if (mxsfb->panel)
+		drm_panel_detach(mxsfb->panel);
+
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs mxsfb_panel_connector_funcs = {
+	.dpms			= drm_atomic_helper_connector_dpms,
+	.detect			= mxsfb_panel_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= mxsfb_panel_connector_destroy,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+};
+
+static int mxsfb_attach_endpoint(struct drm_device *drm,
+				 const struct of_endpoint *ep)
+{
+	struct mxsfb_drm_private *mxsfb = drm->dev_private;
+	struct device_node *np;
+	struct drm_panel *panel;
+	int ret = -EPROBE_DEFER;
+
+	np = of_graph_get_remote_port_parent(ep->local_node);
+	panel = of_drm_find_panel(np);
+	of_node_put(np);
+
+	if (!panel)
+		return -EPROBE_DEFER;
+
+	mxsfb->connector.dpms = DRM_MODE_DPMS_OFF;
+	mxsfb->connector.polled = 0;
+	drm_connector_helper_add(&mxsfb->connector,
+			&mxsfb_panel_connector_helper_funcs);
+	ret = drm_connector_init(drm, &mxsfb->connector,
+				 &mxsfb_panel_connector_funcs,
+				 DRM_MODE_CONNECTOR_Unknown);
+	if (!ret)
+		mxsfb->panel = panel;
+
+	return ret;
+}
+
+int mxsfb_create_output(struct drm_device *drm)
+{
+	struct device_node *ep_np = NULL;
+	struct of_endpoint ep;
+	int ret;
+
+	for_each_endpoint_of_node(drm->dev->of_node, ep_np) {
+		ret = of_graph_parse_endpoint(ep_np, &ep);
+		if (!ret)
+			ret = mxsfb_attach_endpoint(drm, &ep);
+
+		if (ret) {
+			of_node_put(ep_np);
+			return ret;
+		}
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_regs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_regs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/mxsfb/mxsfb_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/mxsfb/mxsfb_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ * Copyright (C) 2016 Marek Vasut <marex@denx.de>
+ *
+ * i.MX23/i.MX28/i.MX6SX MXSFB LCD controller 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.
+ */
+
+#ifndef __MXSFB_REGS_H__
+#define __MXSFB_REGS_H__
+
+#define REG_SET	4
+#define REG_CLR	8
+
+#define LCDC_CTRL			0x00
+#define LCDC_CTRL1			0x10
+#define LCDC_V3_TRANSFER_COUNT		0x20
+#define LCDC_V4_TRANSFER_COUNT		0x30
+#define LCDC_V4_CUR_BUF			0x40
+#define LCDC_V4_NEXT_BUF		0x50
+#define LCDC_V3_CUR_BUF			0x30
+#define LCDC_V3_NEXT_BUF		0x40
+#define LCDC_VDCTRL0			0x70
+#define LCDC_VDCTRL1			0x80
+#define LCDC_VDCTRL2			0x90
+#define LCDC_VDCTRL3			0xa0
+#define LCDC_VDCTRL4			0xb0
+#define LCDC_V4_DEBUG0			0x1d0
+#define LCDC_V3_DEBUG0			0x1f0
+
+#define CTRL_SFTRST			(1 << 31)
+#define CTRL_CLKGATE			(1 << 30)
+#define CTRL_BYPASS_COUNT		(1 << 19)
+#define CTRL_VSYNC_MODE			(1 << 18)
+#define CTRL_DOTCLK_MODE		(1 << 17)
+#define CTRL_DATA_SELECT		(1 << 16)
+#define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
+#define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
+#define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
+#define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
+#define CTRL_MASTER			(1 << 5)
+#define CTRL_DF16			(1 << 3)
+#define CTRL_DF18			(1 << 2)
+#define CTRL_DF24			(1 << 1)
+#define CTRL_RUN			(1 << 0)
+
+#define CTRL1_FIFO_CLEAR		(1 << 21)
+#define CTRL1_SET_BYTE_PACKAGING(x)	(((x) & 0xf) << 16)
+#define CTRL1_GET_BYTE_PACKAGING(x)	(((x) >> 16) & 0xf)
+#define CTRL1_CUR_FRAME_DONE_IRQ_EN	(1 << 13)
+#define CTRL1_CUR_FRAME_DONE_IRQ	(1 << 9)
+
+#define TRANSFER_COUNT_SET_VCOUNT(x)	(((x) & 0xffff) << 16)
+#define TRANSFER_COUNT_GET_VCOUNT(x)	(((x) >> 16) & 0xffff)
+#define TRANSFER_COUNT_SET_HCOUNT(x)	((x) & 0xffff)
+#define TRANSFER_COUNT_GET_HCOUNT(x)	((x) & 0xffff)
+
+#define VDCTRL0_ENABLE_PRESENT		(1 << 28)
+#define VDCTRL0_VSYNC_ACT_HIGH		(1 << 27)
+#define VDCTRL0_HSYNC_ACT_HIGH		(1 << 26)
+#define VDCTRL0_DOTCLK_ACT_FALLING	(1 << 25)
+#define VDCTRL0_ENABLE_ACT_HIGH		(1 << 24)
+#define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
+#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
+#define VDCTRL0_HALF_LINE		(1 << 19)
+#define VDCTRL0_HALF_LINE_MODE		(1 << 18)
+#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+
+#define VDCTRL2_SET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
+#define VDCTRL2_GET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
+
+#define VDCTRL3_MUX_SYNC_SIGNALS	(1 << 29)
+#define VDCTRL3_VSYNC_ONLY		(1 << 28)
+#define SET_HOR_WAIT_CNT(x)		(((x) & 0xfff) << 16)
+#define GET_HOR_WAIT_CNT(x)		(((x) >> 16) & 0xfff)
+#define SET_VERT_WAIT_CNT(x)		((x) & 0xffff)
+#define GET_VERT_WAIT_CNT(x)		((x) & 0xffff)
+
+#define VDCTRL4_SET_DOTCLK_DLY(x)	(((x) & 0x7) << 29) /* v4 only */
+#define VDCTRL4_GET_DOTCLK_DLY(x)	(((x) >> 29) & 0x7) /* v4 only */
+#define VDCTRL4_SYNC_SIGNALS_ON		(1 << 18)
+#define SET_DOTCLK_H_VALID_DATA_CNT(x)	((x) & 0x3ffff)
+
+#define DEBUG0_HSYNC			(1 < 26)
+#define DEBUG0_VSYNC			(1 < 25)
+
+#define MXSFB_MIN_XRES			120
+#define MXSFB_MIN_YRES			120
+#define MXSFB_MAX_XRES			0xffff
+#define MXSFB_MAX_YRES			0xffff
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define TRANSP 3
+
+#define STMLCDIF_8BIT  1 /* pixel data bus to the display is of 8 bit width */
+#define STMLCDIF_16BIT 0 /* pixel data bus to the display is of 16 bit width */
+#define STMLCDIF_18BIT 2 /* pixel data bus to the display is of 18 bit width */
+#define STMLCDIF_24BIT 3 /* pixel data bus to the display is of 24 bit width */
+
+#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
+#define MXSFB_SYNC_DOTCLK_FALLING_ACT	(1 << 7) /* negative edge sampling */
+
+#endif /* __MXSFB_REGS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/dispnv04/crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -702,7 +702,7 @@ static void nv_crtc_prepare(struct drm_c
 	if (nv_two_heads(dev))
 		NVSetOwner(dev, nv_crtc->index);
 
-	drm_vblank_pre_modeset(dev, nv_crtc->index);
+	drm_crtc_vblank_off(crtc);
 	funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 
 	NVBlankScreen(dev, nv_crtc->index, true);
@@ -734,7 +734,7 @@ static void nv_crtc_commit(struct drm_cr
 #endif
 
 	funcs->dpms(crtc, DRM_MODE_DPMS_ON);
-	drm_vblank_post_modeset(dev, nv_crtc->index);
+	drm_crtc_vblank_on(crtc);
 }
 
 static void nv_crtc_destroy(struct drm_crtc *crtc)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/dispnv04/hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -222,6 +222,7 @@ nouveau_hw_get_clock(struct drm_device *
 		uint32_t mpllP;
 
 		pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
+		mpllP = (mpllP >> 8) & 0xf;
 		if (!mpllP)
 			mpllP = 4;
 
@@ -232,7 +233,7 @@ nouveau_hw_get_clock(struct drm_device *
 		uint32_t clock;
 
 		pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
-		return clock;
+		return clock / 1000;
 	}
 
 	ret = nouveau_hw_get_pllvals(dev, plltype, &pllvals);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/dispnv04/overlay.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include "nouveau_connector.h"
 #include "nouveau_display.h"
 #include "nvreg.h"
-
+#include "disp.h"
 
 struct nouveau_plane {
 	struct drm_plane base;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvif/cl5070.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvif/cl5070.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvif/cl5070.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,8 @@ struct nv50_disp_mthd_v1 {
 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR                                     0x22
 #define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT                                  0x23
 #define NV50_DISP_MTHD_V1_SOR_DP_PWR                                       0x24
+#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK                                  0x25
+#define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI                                  0x26
 #define NV50_DISP_MTHD_V1_PIOR_PWR                                         0x30
 	__u8  method;
 	__u16 hasht;
@@ -90,6 +92,21 @@ struct nv50_disp_sor_dp_pwr_v0 {
 	__u8  pad02[6];
 };
 
+struct nv50_disp_sor_dp_mst_link_v0 {
+	__u8  version;
+	__u8  state;
+	__u8  pad02[6];
+};
+
+struct nv50_disp_sor_dp_mst_vcpi_v0 {
+	__u8  version;
+	__u8  pad01[1];
+	__u8  start_slot;
+	__u8  num_slots;
+	__u16 pbn;
+	__u16 aligned_pbn;
+};
+
 struct nv50_disp_pior_pwr_v0 {
 	__u8  version;
 	__u8  state;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvif/class.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvif/class.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvif/class.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvif/class.h	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@
 #define GM107_DISP                                    /* cl5070.h */ 0x00009470
 #define GM200_DISP                                    /* cl5070.h */ 0x00009570
 #define GP100_DISP                                    /* cl5070.h */ 0x00009770
-#define GP104_DISP                                    /* cl5070.h */ 0x00009870
+#define GP102_DISP                                    /* cl5070.h */ 0x00009870
 
 #define NV31_MPEG                                                    0x00003174
 #define G82_MPEG                                                     0x00008274
@@ -90,7 +90,7 @@
 #define GM107_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000947d
 #define GM200_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000957d
 #define GP100_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000977d
-#define GP104_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000987d
+#define GP102_DISP_CORE_CHANNEL_DMA                   /* cl507d.h */ 0x0000987d
 
 #define NV50_DISP_OVERLAY_CHANNEL_DMA                 /* cl507e.h */ 0x0000507e
 #define G82_DISP_OVERLAY_CHANNEL_DMA                  /* cl507e.h */ 0x0000827e
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvif/object.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvif/object.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvif/object.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvif/object.h	2017-02-12 16:03:20.000000000 -0500
@@ -66,6 +66,35 @@ void nvif_object_unmap(struct nvif_objec
 
 #define nvif_mthd(a,b,c,d) nvif_object_mthd((a), (b), (c), (d))
 
+struct nvif_mclass {
+	s32 oclass;
+	int version;
+};
+
+#define nvif_mclass(o,m) ({                                                    \
+	struct nvif_object *object = (o);                                      \
+	struct nvif_sclass *sclass;                                            \
+	const typeof(m[0]) *mclass = (m);                                      \
+	int ret = -ENODEV;                                                     \
+	int cnt, i, j;                                                         \
+                                                                               \
+	cnt = nvif_object_sclass_get(object, &sclass);                         \
+	if (cnt >= 0) {                                                        \
+		for (i = 0; ret < 0 && mclass[i].oclass; i++) {                \
+			for (j = 0; j < cnt; j++) {                            \
+				if (mclass[i].oclass  == sclass[j].oclass &&   \
+				    mclass[i].version >= sclass[j].minver &&   \
+				    mclass[i].version <= sclass[j].maxver) {   \
+					ret = i;                               \
+					break;                                 \
+				}                                              \
+			}                                                      \
+		}                                                              \
+		nvif_object_sclass_put(&sclass);                               \
+	}                                                                      \
+	ret;                                                                   \
+})
+
 /*XXX*/
 #include <core/object.h>
 #define nvxx_object(a) ({                                                      \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,5 +8,5 @@ int gk104_ce_new(struct nvkm_device *, i
 int gm107_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
 int gm200_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
 int gp100_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
-int gp104_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
+int gp102_ce_new(struct nvkm_device *, int, struct nvkm_engine **);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ int gk110_disp_new(struct nvkm_device *,
 int gm107_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int gm200_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 int gp100_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
-int gp104_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
+int gp102_disp_new(struct nvkm_device *, int, struct nvkm_disp **);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/boost.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #ifndef __NVBIOS_BOOST_H__
 #define __NVBIOS_BOOST_H__
-u16 nvbios_boostTe(struct nvkm_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *);
+u32 nvbios_boostTe(struct nvkm_bios *, u8 *, u8 *, u8 *, u8 *, u8 *, u8 *);
 
 struct nvbios_boostE {
 	u8  pstate;
@@ -8,10 +8,10 @@ struct nvbios_boostE {
 	u32 max;
 };
 
-u16 nvbios_boostEe(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *);
-u16 nvbios_boostEp(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *,
+u32 nvbios_boostEe(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *);
+u32 nvbios_boostEp(struct nvkm_bios *, int idx, u8 *, u8 *, u8 *, u8 *,
 		   struct nvbios_boostE *);
-u16 nvbios_boostEm(struct nvkm_bios *, u8, u8 *, u8 *, u8 *, u8 *,
+u32 nvbios_boostEm(struct nvkm_bios *, u8, u8 *, u8 *, u8 *, u8 *,
 		   struct nvbios_boostE *);
 
 struct nvbios_boostS {
@@ -21,7 +21,7 @@ struct nvbios_boostS {
 	u32 max;
 };
 
-u16 nvbios_boostSe(struct nvkm_bios *, int, u16, u8 *, u8 *, u8, u8);
-u16 nvbios_boostSp(struct nvkm_bios *, int, u16, u8 *, u8 *, u8, u8,
+u32 nvbios_boostSe(struct nvkm_bios *, int, u32, u8 *, u8 *, u8, u8);
+u32 nvbios_boostSp(struct nvkm_bios *, int, u32, u8 *, u8 *, u8, u8,
 		   struct nvbios_boostS *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/cstep.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #ifndef __NVBIOS_CSTEP_H__
 #define __NVBIOS_CSTEP_H__
-u16 nvbios_cstepTe(struct nvkm_bios *,
+u32 nvbios_cstepTe(struct nvkm_bios *,
 		   u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz);
 
 struct nvbios_cstepE {
@@ -8,10 +8,10 @@ struct nvbios_cstepE {
 	u8  index;
 };
 
-u16 nvbios_cstepEe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
-u16 nvbios_cstepEp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
+u32 nvbios_cstepEe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
+u32 nvbios_cstepEp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
 		   struct nvbios_cstepE *);
-u16 nvbios_cstepEm(struct nvkm_bios *, u8 pstate, u8 *ver, u8 *hdr,
+u32 nvbios_cstepEm(struct nvkm_bios *, u8 pstate, u8 *ver, u8 *hdr,
 		   struct nvbios_cstepE *);
 
 struct nvbios_cstepX {
@@ -20,7 +20,7 @@ struct nvbios_cstepX {
 	u8  voltage;
 };
 
-u16 nvbios_cstepXe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
-u16 nvbios_cstepXp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
+u32 nvbios_cstepXe(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr);
+u32 nvbios_cstepXp(struct nvkm_bios *, int idx, u8 *ver, u8 *hdr,
 		   struct nvbios_cstepX *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/fan.h	2017-02-12 16:03:20.000000000 -0500
@@ -2,5 +2,5 @@
 #define __NVBIOS_FAN_H__
 #include <subdev/bios/therm.h>
 
-u16 nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan);
+u32 nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,7 @@ enum dcb_gpio_func_name {
 	DCB_GPIO_TVDAC1 = 0x2d,
 	DCB_GPIO_FAN = 0x09,
 	DCB_GPIO_FAN_SENSE = 0x3d,
+	DCB_GPIO_LOGO_LED_PWM = 0x84,
 	DCB_GPIO_UNUSED = 0xff,
 	DCB_GPIO_VID0 = 0x04,
 	DCB_GPIO_VID1 = 0x05,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/iccsense.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,10 +1,16 @@
 #ifndef __NVBIOS_ICCSENSE_H__
 #define __NVBIOS_ICCSENSE_H__
+struct pwr_rail_resistor_t {
+	u8 mohm;
+	bool enabled;
+};
+
 struct pwr_rail_t {
 	u8 mode;
 	u8 extdev_id;
-	u8 resistor_mohm;
-	u8 rail;
+	u8 resistor_count;
+	struct pwr_rail_resistor_t resistors[3];
+	u16 config;
 };
 
 struct nvbios_iccsense {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/perf.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #ifndef __NVBIOS_PERF_H__
 #define __NVBIOS_PERF_H__
-u16 nvbios_perf_table(struct nvkm_bios *, u8 *ver, u8 *hdr,
+u32 nvbios_perf_table(struct nvkm_bios *, u8 *ver, u8 *hdr,
 		      u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
 
 struct nvbios_perfE {
@@ -17,9 +17,9 @@ struct nvbios_perfE {
 	u8  pcie_width;
 };
 
-u16 nvbios_perf_entry(struct nvkm_bios *, int idx,
+u32 nvbios_perf_entry(struct nvkm_bios *, int idx,
 		      u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_perfEp(struct nvkm_bios *, int idx,
+u32 nvbios_perfEp(struct nvkm_bios *, int idx,
 		  u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *);
 
 struct nvbios_perfS {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/timing.h	2017-02-12 16:03:20.000000000 -0500
@@ -2,10 +2,10 @@
 #define __NVBIOS_TIMING_H__
 #include <subdev/bios/ramcfg.h>
 
-u16 nvbios_timingTe(struct nvkm_bios *,
+u32 nvbios_timingTe(struct nvkm_bios *,
 		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz);
-u16 nvbios_timingEe(struct nvkm_bios *, int idx,
+u32 nvbios_timingEe(struct nvkm_bios *, int idx,
 		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_timingEp(struct nvkm_bios *, int idx,
+u32 nvbios_timingEp(struct nvkm_bios *, int idx,
 		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vmap.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,21 +1,24 @@
 #ifndef __NVBIOS_VMAP_H__
 #define __NVBIOS_VMAP_H__
 struct nvbios_vmap {
+	u8  max0;
+	u8  max1;
+	u8  max2;
 };
 
-u16 nvbios_vmap_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_vmap_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+u32 nvbios_vmap_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_vmap_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
 		      struct nvbios_vmap *);
 
 struct nvbios_vmap_entry {
-	u8  unk0;
+	u8  mode;
 	u8  link;
 	u32 min;
 	u32 max;
 	s32 arg[6];
 };
 
-u16 nvbios_vmap_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
-u16 nvbios_vmap_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
+u32 nvbios_vmap_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
+u32 nvbios_vmap_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
 			    struct nvbios_vmap_entry *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h	2017-02-12 16:03:20.000000000 -0500
@@ -13,16 +13,17 @@ struct nvbios_volt {
 	u32 base;
 
 	/* GPIO mode */
-	u8  vidmask;
-	s16 step;
+	bool ranged;
+	u8   vidmask;
+	s16  step;
 
 	/* PWM mode */
 	u32 pwm_freq;
 	u32 pwm_range;
 };
 
-u16 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
-u16 nvbios_volt_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
+u32 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+u32 nvbios_volt_parse(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
 		      struct nvbios_volt *);
 
 struct nvbios_volt_entry {
@@ -30,7 +31,7 @@ struct nvbios_volt_entry {
 	u8  vid;
 };
 
-u16 nvbios_volt_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
-u16 nvbios_volt_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
+u32 nvbios_volt_entry(struct nvkm_bios *, int idx, u8 *ver, u8 *len);
+u32 nvbios_volt_entry_parse(struct nvkm_bios *, int idx, u8 *ver, u8 *len,
 			    struct nvbios_volt_entry *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/vpstate.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,24 @@
+#ifndef __NVBIOS_VPSTATE_H__
+#define __NVBIOS_VPSTATE_H__
+struct nvbios_vpstate_header {
+	u32 offset;
+
+	u8 version;
+	u8 hlen;
+	u8 ecount;
+	u8 elen;
+	u8 scount;
+	u8 slen;
+
+	u8 base_id;
+	u8 boost_id;
+	u8 tdp_id;
+};
+struct nvbios_vpstate_entry {
+	u8  pstate;
+	u16 clock_mhz;
+};
+int nvbios_vpstate_parse(struct nvkm_bios *, struct nvbios_vpstate_header *);
+int nvbios_vpstate_entry(struct nvkm_bios *, struct nvbios_vpstate_header *,
+			 u8 idx, struct nvbios_vpstate_entry *);
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/clk.h	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,10 @@
 struct nvbios_pll;
 struct nvkm_pll_vals;
 
+#define NVKM_CLK_CSTATE_DEFAULT -1 /* POSTed default */
+#define NVKM_CLK_CSTATE_BASE    -2 /* pstate base */
+#define NVKM_CLK_CSTATE_HIGHEST -3 /* highest possible */
+
 enum nv_clk_src {
 	nv_clk_src_crystal,
 	nv_clk_src_href,
@@ -52,6 +56,7 @@ struct nvkm_cstate {
 	struct list_head head;
 	u8  voltage;
 	u32 domain[nv_clk_src_max];
+	u8  id;
 };
 
 struct nvkm_pstate {
@@ -67,7 +72,8 @@ struct nvkm_pstate {
 struct nvkm_domain {
 	enum nv_clk_src name;
 	u8 bios; /* 0xff for none */
-#define NVKM_CLK_DOM_FLAG_CORE 0x01
+#define NVKM_CLK_DOM_FLAG_CORE    0x01
+#define NVKM_CLK_DOM_FLAG_VPSTATE 0x02
 	u8 flags;
 	const char *mname;
 	int mdiv;
@@ -93,10 +99,16 @@ struct nvkm_clk {
 	int ustate_ac; /* user-requested (-1 disabled, -2 perfmon) */
 	int ustate_dc; /* user-requested (-1 disabled, -2 perfmon) */
 	int astate; /* perfmon adjustment (base) */
-	int tstate; /* thermal adjustment (max-) */
 	int dstate; /* display adjustment (min+) */
+	u8  temp;
 
 	bool allow_reclock;
+#define NVKM_CLK_BOOST_NONE 0x0
+#define NVKM_CLK_BOOST_BIOS 0x1
+#define NVKM_CLK_BOOST_FULL 0x2
+	u8  boost_mode;
+	u32 base_khz;
+	u32 boost_khz;
 
 	/*XXX: die, these are here *only* to support the completely
 	 *     bat-shit insane what-was-nouveau_hw.c code
@@ -110,7 +122,7 @@ int nvkm_clk_read(struct nvkm_clk *, enu
 int nvkm_clk_ustate(struct nvkm_clk *, int req, int pwr);
 int nvkm_clk_astate(struct nvkm_clk *, int req, int rel, bool wait);
 int nvkm_clk_dstate(struct nvkm_clk *, int req, int rel);
-int nvkm_clk_tstate(struct nvkm_clk *, int req, int rel);
+int nvkm_clk_tstate(struct nvkm_clk *, u8 temperature);
 
 int nv04_clk_new(struct nvkm_device *, int, struct nvkm_clk **);
 int nv40_clk_new(struct nvkm_device *, int, struct nvkm_clk **);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h	2017-02-12 16:03:20.000000000 -0500
@@ -93,8 +93,9 @@ int gk104_fb_new(struct nvkm_device *, i
 int gk20a_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gm107_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gm200_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
+int gm20b_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 int gp100_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
-int gp104_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
+int gp102_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
 
 #include <subdev/bios.h>
 #include <subdev/bios/ramcfg.h>
@@ -156,4 +157,6 @@ struct nvkm_ram_func {
 	int (*prog)(struct nvkm_ram *);
 	void (*tidy)(struct nvkm_ram *);
 };
+
+extern const u8 gf100_pte_storage_type_map[256];
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,8 @@ int gk110_pmu_new(struct nvkm_device *,
 int gk208_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
 int gk20a_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
 int gm107_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
+int gp100_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
+int gp102_pmu_new(struct nvkm_device *, int, struct nvkm_pmu **);
 
 /* interface to MEMX process running on PMU */
 struct nvkm_memx;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,12 +15,28 @@ struct nvkm_volt {
 
 	u32 max_uv;
 	u32 min_uv;
+
+	/*
+	 * These are fully functional map entries creating a sw ceiling for
+	 * the voltage. These all can describe different kind of curves, so
+	 * that for any given temperature a different one can return the lowest
+	 * value of all three.
+	 */
+	u8 max0_id;
+	u8 max1_id;
+	u8 max2_id;
+
+	int speedo;
 };
 
+int nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temperature);
+int nvkm_volt_map_min(struct nvkm_volt *volt, u8 id);
 int nvkm_volt_get(struct nvkm_volt *);
-int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition);
+int nvkm_volt_set_id(struct nvkm_volt *, u8 id, u8 min_id, u8 temp,
+		     int condition);
 
 int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
+int gf100_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
 int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
 int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
 int gm20b_volt_new(struct nvkm_device *, int, struct nvkm_volt **);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/Kbuild linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/Kbuild
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@ nouveau-$(CONFIG_DEBUG_FS) += nouveau_de
 nouveau-y += nouveau_drm.o
 nouveau-y += nouveau_hwmon.o
 nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
+nouveau-$(CONFIG_LEDS_CLASS) += nouveau_led.o
 nouveau-y += nouveau_nvif.o
 nouveau-$(CONFIG_NOUVEAU_PLATFORM_DRIVER) += nouveau_platform.o
 nouveau-y += nouveau_usif.o # userspace <-> nvif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,12 +30,37 @@
  * Register locations derived from NVClock by Roderick Colenbrander
  */
 
+#include <linux/apple-gmux.h>
 #include <linux/backlight.h>
+#include <linux/idr.h>
 
 #include "nouveau_drv.h"
 #include "nouveau_reg.h"
 #include "nouveau_encoder.h"
 
+static struct ida bl_ida;
+#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
+
+struct backlight_connector {
+	struct list_head head;
+	int id;
+};
+
+static bool
+nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector
+		*connector)
+{
+	const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
+	if (nb < 0 || nb >= 100)
+		return false;
+	if (nb > 0)
+		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
+	else
+		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight");
+	connector->id = nb;
+	return true;
+}
+
 static int
 nv40_get_intensity(struct backlight_device *bd)
 {
@@ -74,6 +99,8 @@ nv40_backlight_init(struct drm_connector
 	struct nvif_object *device = &drm->device.object;
 	struct backlight_properties props;
 	struct backlight_device *bd;
+	struct backlight_connector bl_connector;
+	char backlight_name[BL_NAME_SIZE];
 
 	if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
 		return 0;
@@ -81,10 +108,19 @@ nv40_backlight_init(struct drm_connector
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
-	bd = backlight_device_register("nv_backlight", connector->kdev, drm,
+	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
+		return 0;
+	}
+	bd = backlight_device_register(backlight_name , connector->kdev, drm,
 				       &nv40_bl_ops, &props);
-	if (IS_ERR(bd))
+
+	if (IS_ERR(bd)) {
+		if (bl_connector.id > 0)
+			ida_simple_remove(&bl_ida, bl_connector.id);
 		return PTR_ERR(bd);
+	}
+	list_add(&bl_connector.head, &drm->bl_connectors);
 	drm->backlight = bd;
 	bd->props.brightness = nv40_get_intensity(bd);
 	backlight_update_status(bd);
@@ -182,6 +218,8 @@ nv50_backlight_init(struct drm_connector
 	struct backlight_properties props;
 	struct backlight_device *bd;
 	const struct backlight_ops *ops;
+	struct backlight_connector bl_connector;
+	char backlight_name[BL_NAME_SIZE];
 
 	nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
 	if (!nv_encoder) {
@@ -203,11 +241,20 @@ nv50_backlight_init(struct drm_connector
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 100;
-	bd = backlight_device_register("nv_backlight", connector->kdev,
+	if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
+		NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
+		return 0;
+	}
+	bd = backlight_device_register(backlight_name , connector->kdev,
 				       nv_encoder, ops, &props);
-	if (IS_ERR(bd))
+
+	if (IS_ERR(bd)) {
+		if (bl_connector.id > 0)
+			ida_simple_remove(&bl_ida, bl_connector.id);
 		return PTR_ERR(bd);
+	}
 
+	list_add(&bl_connector.head, &drm->bl_connectors);
 	drm->backlight = bd;
 	bd->props.brightness = bd->ops->get_brightness(bd);
 	backlight_update_status(bd);
@@ -221,6 +268,13 @@ nouveau_backlight_init(struct drm_device
 	struct nvif_device *device = &drm->device;
 	struct drm_connector *connector;
 
+	if (apple_gmux_present()) {
+		NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
+		return 0;
+	}
+
+	INIT_LIST_HEAD(&drm->bl_connectors);
+
 	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)
@@ -232,6 +286,7 @@ nouveau_backlight_init(struct drm_device
 		case NV_DEVICE_INFO_V0_TESLA:
 		case NV_DEVICE_INFO_V0_FERMI:
 		case NV_DEVICE_INFO_V0_KEPLER:
+		case NV_DEVICE_INFO_V0_MAXWELL:
 			return nv50_backlight_init(connector);
 		default:
 			break;
@@ -246,9 +301,27 @@ void
 nouveau_backlight_exit(struct drm_device *dev)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct backlight_connector *connector;
+
+	list_for_each_entry(connector, &drm->bl_connectors, head) {
+		if (connector->id >= 0)
+			ida_simple_remove(&bl_ida, connector->id);
+	}
 
 	if (drm->backlight) {
 		backlight_device_unregister(drm->backlight);
 		drm->backlight = NULL;
 	}
 }
+
+void
+nouveau_backlight_ctor(void)
+{
+	ida_init(&bl_ida);
+}
+
+void
+nouveau_backlight_dtor(void)
+{
+	ida_destroy(&bl_ida);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2017-02-12 16:03:20.000000000 -0500
@@ -333,6 +333,9 @@ get_fp_strap(struct drm_device *dev, str
 	if (bios->major_version < 5 && bios->data[0x48] & 0x4)
 		return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
 
+	if (drm->device.info.family >= NV_DEVICE_INFO_V0_MAXWELL)
+		return nvif_rd32(device, 0x001800) & 0x0000000f;
+	else
 	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
 		return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
 	else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,10 +31,8 @@
 
 #define DCB_LOC_ON_CHIP 0
 
-#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
-#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
-#define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); })
-#define ROM64(x) le64_to_cpu(*(u64 *)&(x))
+#define ROM16(x) get_unaligned_le16(&(x))
+#define ROM32(x) get_unaligned_le32(&(x))
 #define ROMPTR(d,x) ({            \
 	struct nouveau_drm *drm = nouveau_drm((d)); \
 	ROM16(x) ? &drm->vbios.data[ROM16(x)] : NULL; \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2017-02-12 16:03:20.000000000 -0500
@@ -83,13 +83,13 @@ nv10_bo_get_tile_region(struct drm_devic
 
 static void
 nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile,
-			struct fence *fence)
+			struct dma_fence *fence)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 
 	if (tile) {
 		spin_lock(&drm->tile.lock);
-		tile->fence = (struct nouveau_fence *)fence_get(fence);
+		tile->fence = (struct nouveau_fence *)dma_fence_get(fence);
 		tile->used = false;
 		spin_unlock(&drm->tile.lock);
 	}
@@ -1209,6 +1209,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_o
 			       nvbo->page_shift != vma->vm->mmu->lpg_shift)) {
 			nvkm_vm_map(vma, new_mem->mm_node);
 		} else {
+			WARN_ON(ttm_bo_wait(bo, false, false));
 			nvkm_vm_unmap(vma);
 		}
 	}
@@ -1243,7 +1244,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_
 {
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
 	struct drm_device *dev = drm->dev;
-	struct fence *fence = reservation_object_get_excl(bo->resv);
+	struct dma_fence *fence = reservation_object_get_excl(bo->resv);
 
 	nv10_bo_put_tile_region(dev, *old_tile, fence);
 	*old_tile = new_tile;
@@ -1561,6 +1562,7 @@ struct ttm_bo_driver nouveau_bo_driver =
 	.ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate,
 	.invalidate_caches = nouveau_bo_invalidate_caches,
 	.init_mem_type = nouveau_bo_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = nouveau_bo_evict_flags,
 	.move_notify = nouveau_bo_move_ntfy,
 	.move = nouveau_bo_move,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/vga_switcheroo.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_crtc_helper.h>
 
@@ -47,6 +48,301 @@
 #include <nvif/cl0046.h>
 #include <nvif/event.h>
 
+struct drm_display_mode *
+nouveau_conn_native_mode(struct drm_connector *connector)
+{
+	const struct drm_connector_helper_funcs *helper = connector->helper_private;
+	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	struct drm_device *dev = connector->dev;
+	struct drm_display_mode *mode, *largest = NULL;
+	int high_w = 0, high_h = 0, high_v = 0;
+
+	list_for_each_entry(mode, &connector->probed_modes, head) {
+		mode->vrefresh = drm_mode_vrefresh(mode);
+		if (helper->mode_valid(connector, mode) != MODE_OK ||
+		    (mode->flags & DRM_MODE_FLAG_INTERLACE))
+			continue;
+
+		/* Use preferred mode if there is one.. */
+		if (mode->type & DRM_MODE_TYPE_PREFERRED) {
+			NV_DEBUG(drm, "native mode from preferred\n");
+			return drm_mode_duplicate(dev, mode);
+		}
+
+		/* Otherwise, take the resolution with the largest width, then
+		 * height, then vertical refresh
+		 */
+		if (mode->hdisplay < high_w)
+			continue;
+
+		if (mode->hdisplay == high_w && mode->vdisplay < high_h)
+			continue;
+
+		if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
+		    mode->vrefresh < high_v)
+			continue;
+
+		high_w = mode->hdisplay;
+		high_h = mode->vdisplay;
+		high_v = mode->vrefresh;
+		largest = mode;
+	}
+
+	NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n",
+		      high_w, high_h, high_v);
+	return largest ? drm_mode_duplicate(dev, largest) : NULL;
+}
+
+int
+nouveau_conn_atomic_get_property(struct drm_connector *connector,
+				 const struct drm_connector_state *state,
+				 struct drm_property *property, u64 *val)
+{
+	struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
+	struct nouveau_display *disp = nouveau_display(connector->dev);
+	struct drm_device *dev = connector->dev;
+
+	if (property == dev->mode_config.scaling_mode_property)
+		*val = asyc->scaler.mode;
+	else if (property == disp->underscan_property)
+		*val = asyc->scaler.underscan.mode;
+	else if (property == disp->underscan_hborder_property)
+		*val = asyc->scaler.underscan.hborder;
+	else if (property == disp->underscan_vborder_property)
+		*val = asyc->scaler.underscan.vborder;
+	else if (property == disp->dithering_mode)
+		*val = asyc->dither.mode;
+	else if (property == disp->dithering_depth)
+		*val = asyc->dither.depth;
+	else if (property == disp->vibrant_hue_property)
+		*val = asyc->procamp.vibrant_hue;
+	else if (property == disp->color_vibrance_property)
+		*val = asyc->procamp.color_vibrance;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+int
+nouveau_conn_atomic_set_property(struct drm_connector *connector,
+				 struct drm_connector_state *state,
+				 struct drm_property *property, u64 val)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
+	struct nouveau_display *disp = nouveau_display(dev);
+
+	if (property == dev->mode_config.scaling_mode_property) {
+		switch (val) {
+		case DRM_MODE_SCALE_NONE:
+			/* We allow 'None' for EDID modes, even on a fixed
+			 * panel (some exist with support for lower refresh
+			 * rates, which people might want to use for power-
+			 * saving purposes).
+			 *
+			 * Non-EDID modes will force the use of GPU scaling
+			 * to the native mode regardless of this setting.
+			 */
+			switch (connector->connector_type) {
+			case DRM_MODE_CONNECTOR_LVDS:
+			case DRM_MODE_CONNECTOR_eDP:
+				/* ... except prior to G80, where the code
+				 * doesn't support such things.
+				 */
+				if (disp->disp.oclass < NV50_DISP)
+					return -EINVAL;
+				break;
+			default:
+				break;
+			}
+		case DRM_MODE_SCALE_FULLSCREEN:
+		case DRM_MODE_SCALE_CENTER:
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		if (asyc->scaler.mode != val) {
+			asyc->scaler.mode = val;
+			asyc->set.scaler = true;
+		}
+	} else
+	if (property == disp->underscan_property) {
+		if (asyc->scaler.underscan.mode != val) {
+			asyc->scaler.underscan.mode = val;
+			asyc->set.scaler = true;
+		}
+	} else
+	if (property == disp->underscan_hborder_property) {
+		if (asyc->scaler.underscan.hborder != val) {
+			asyc->scaler.underscan.hborder = val;
+			asyc->set.scaler = true;
+		}
+	} else
+	if (property == disp->underscan_vborder_property) {
+		if (asyc->scaler.underscan.vborder != val) {
+			asyc->scaler.underscan.vborder = val;
+			asyc->set.scaler = true;
+		}
+	} else
+	if (property == disp->dithering_mode) {
+		if (asyc->dither.mode != val) {
+			asyc->dither.mode = val;
+			asyc->set.dither = true;
+		}
+	} else
+	if (property == disp->dithering_depth) {
+		if (asyc->dither.mode != val) {
+			asyc->dither.depth = val;
+			asyc->set.dither = true;
+		}
+	} else
+	if (property == disp->vibrant_hue_property) {
+		if (asyc->procamp.vibrant_hue != val) {
+			asyc->procamp.vibrant_hue = val;
+			asyc->set.procamp = true;
+		}
+	} else
+	if (property == disp->color_vibrance_property) {
+		if (asyc->procamp.color_vibrance != val) {
+			asyc->procamp.color_vibrance = val;
+			asyc->set.procamp = true;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void
+nouveau_conn_atomic_destroy_state(struct drm_connector *connector,
+				  struct drm_connector_state *state)
+{
+	struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
+	__drm_atomic_helper_connector_destroy_state(&asyc->state);
+	kfree(asyc);
+}
+
+struct drm_connector_state *
+nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
+{
+	struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
+	struct nouveau_conn_atom *asyc;
+	if (!(asyc = kmalloc(sizeof(*asyc), GFP_KERNEL)))
+		return NULL;
+	__drm_atomic_helper_connector_duplicate_state(connector, &asyc->state);
+	asyc->dither = armc->dither;
+	asyc->scaler = armc->scaler;
+	asyc->procamp = armc->procamp;
+	asyc->set.mask = 0;
+	return &asyc->state;
+}
+
+void
+nouveau_conn_reset(struct drm_connector *connector)
+{
+	struct nouveau_conn_atom *asyc;
+
+	if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
+		return;
+
+	if (connector->state)
+		__drm_atomic_helper_connector_destroy_state(connector->state);
+	__drm_atomic_helper_connector_reset(connector, &asyc->state);
+	asyc->dither.mode = DITHERING_MODE_AUTO;
+	asyc->dither.depth = DITHERING_DEPTH_AUTO;
+	asyc->scaler.mode = DRM_MODE_SCALE_NONE;
+	asyc->scaler.underscan.mode = UNDERSCAN_OFF;
+	asyc->procamp.color_vibrance = 150;
+	asyc->procamp.vibrant_hue = 90;
+
+	if (nouveau_display(connector->dev)->disp.oclass < NV50_DISP) {
+		switch (connector->connector_type) {
+		case DRM_MODE_CONNECTOR_LVDS:
+			/* See note in nouveau_conn_atomic_set_property(). */
+			asyc->scaler.mode = DRM_MODE_SCALE_FULLSCREEN;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+void
+nouveau_conn_attach_properties(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
+	struct nouveau_display *disp = nouveau_display(dev);
+
+	/* Init DVI-I specific properties. */
+	if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
+		drm_object_attach_property(&connector->base, dev->mode_config.
+					   dvi_i_subconnector_property, 0);
+
+	/* Add overscan compensation options to digital outputs. */
+	if (disp->underscan_property &&
+	    (connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
+	     connector->connector_type == DRM_MODE_CONNECTOR_DVII ||
+	     connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
+	     connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)) {
+		drm_object_attach_property(&connector->base,
+					   disp->underscan_property,
+					   UNDERSCAN_OFF);
+		drm_object_attach_property(&connector->base,
+					   disp->underscan_hborder_property, 0);
+		drm_object_attach_property(&connector->base,
+					   disp->underscan_vborder_property, 0);
+	}
+
+	/* Add hue and saturation options. */
+	if (disp->vibrant_hue_property)
+		drm_object_attach_property(&connector->base,
+					   disp->vibrant_hue_property,
+					   armc->procamp.vibrant_hue);
+	if (disp->color_vibrance_property)
+		drm_object_attach_property(&connector->base,
+					   disp->color_vibrance_property,
+					   armc->procamp.color_vibrance);
+
+	/* Scaling mode property. */
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_TV:
+		break;
+	case DRM_MODE_CONNECTOR_VGA:
+		if (disp->disp.oclass < NV50_DISP)
+			break; /* Can only scale on DFPs. */
+		/* Fall-through. */
+	default:
+		drm_object_attach_property(&connector->base, dev->mode_config.
+					   scaling_mode_property,
+					   armc->scaler.mode);
+		break;
+	}
+
+	/* Dithering properties. */
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_TV:
+	case DRM_MODE_CONNECTOR_VGA:
+		break;
+	default:
+		if (disp->dithering_mode) {
+			drm_object_attach_property(&connector->base,
+						   disp->dithering_mode,
+						   armc->dither.mode);
+		}
+		if (disp->dithering_depth) {
+			drm_object_attach_property(&connector->base,
+						   disp->dithering_depth,
+						   armc->dither.depth);
+		}
+		break;
+	}
+}
+
 MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
 int nouveau_tv_disable = 0;
 module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
@@ -151,7 +447,9 @@ nouveau_connector_ddc_detect(struct drm_
 
 		if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
 			int ret = nouveau_dp_detect(nv_encoder);
-			if (ret == 0)
+			if (ret == NOUVEAU_DP_MST)
+				return NULL;
+			if (ret == NOUVEAU_DP_SST)
 				break;
 		} else
 		if ((vga_switcheroo_handler_flags() &
@@ -465,199 +763,39 @@ static int
 nouveau_connector_set_property(struct drm_connector *connector,
 			       struct drm_property *property, uint64_t value)
 {
-	struct nouveau_display *disp = nouveau_display(connector->dev);
+	struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
-	struct drm_device *dev = connector->dev;
-	struct nouveau_crtc *nv_crtc;
 	int ret;
 
-	nv_crtc = NULL;
-	if (connector->encoder && connector->encoder->crtc)
-		nv_crtc = nouveau_crtc(connector->encoder->crtc);
-
-	/* Scaling mode */
-	if (property == dev->mode_config.scaling_mode_property) {
-		bool modeset = false;
-
-		switch (value) {
-		case DRM_MODE_SCALE_NONE:
-			/* We allow 'None' for EDID modes, even on a fixed
-			 * panel (some exist with support for lower refresh
-			 * rates, which people might want to use for power
-			 * saving purposes).
-			 *
-			 * Non-EDID modes will force the use of GPU scaling
-			 * to the native mode regardless of this setting.
-			 */
-			switch (nv_connector->type) {
-			case DCB_CONNECTOR_LVDS:
-			case DCB_CONNECTOR_LVDS_SPWG:
-			case DCB_CONNECTOR_eDP:
-				/* ... except prior to G80, where the code
-				 * doesn't support such things.
-				 */
-				if (disp->disp.oclass < NV50_DISP)
-					return -EINVAL;
-				break;
-			default:
-				break;
-			}
-			break;
-		case DRM_MODE_SCALE_FULLSCREEN:
-		case DRM_MODE_SCALE_CENTER:
-		case DRM_MODE_SCALE_ASPECT:
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		/* Changing between GPU and panel scaling requires a full
-		 * modeset
-		 */
-		if ((nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) ||
-		    (value == DRM_MODE_SCALE_NONE))
-			modeset = true;
-		nv_connector->scaling_mode = value;
-
-		if (!nv_crtc)
-			return 0;
-
-		if (modeset || !nv_crtc->set_scale) {
-			ret = drm_crtc_helper_set_mode(&nv_crtc->base,
-							&nv_crtc->base.mode,
-							nv_crtc->base.x,
-							nv_crtc->base.y, NULL);
-			if (!ret)
-				return -EINVAL;
-		} else {
-			ret = nv_crtc->set_scale(nv_crtc, true);
-			if (ret)
-				return ret;
-		}
-
-		return 0;
-	}
-
-	/* Underscan */
-	if (property == disp->underscan_property) {
-		if (nv_connector->underscan != value) {
-			nv_connector->underscan = value;
-			if (!nv_crtc || !nv_crtc->set_scale)
-				return 0;
-
-			return nv_crtc->set_scale(nv_crtc, true);
-		}
-
-		return 0;
-	}
-
-	if (property == disp->underscan_hborder_property) {
-		if (nv_connector->underscan_hborder != value) {
-			nv_connector->underscan_hborder = value;
-			if (!nv_crtc || !nv_crtc->set_scale)
-				return 0;
-
-			return nv_crtc->set_scale(nv_crtc, true);
-		}
-
-		return 0;
-	}
-
-	if (property == disp->underscan_vborder_property) {
-		if (nv_connector->underscan_vborder != value) {
-			nv_connector->underscan_vborder = value;
-			if (!nv_crtc || !nv_crtc->set_scale)
-				return 0;
-
-			return nv_crtc->set_scale(nv_crtc, true);
-		}
-
-		return 0;
-	}
-
-	/* Dithering */
-	if (property == disp->dithering_mode) {
-		nv_connector->dithering_mode = value;
-		if (!nv_crtc || !nv_crtc->set_dither)
-			return 0;
-
-		return nv_crtc->set_dither(nv_crtc, true);
-	}
-
-	if (property == disp->dithering_depth) {
-		nv_connector->dithering_depth = value;
-		if (!nv_crtc || !nv_crtc->set_dither)
-			return 0;
-
-		return nv_crtc->set_dither(nv_crtc, true);
-	}
+	if (connector->dev->mode_config.funcs->atomic_commit)
+		return drm_atomic_helper_connector_set_property(connector, property, value);
 
-	if (nv_crtc && nv_crtc->set_color_vibrance) {
-		/* Hue */
-		if (property == disp->vibrant_hue_property) {
-			nv_crtc->vibrant_hue = value - 90;
-			return nv_crtc->set_color_vibrance(nv_crtc, true);
-		}
-		/* Saturation */
-		if (property == disp->color_vibrance_property) {
-			nv_crtc->color_vibrance = value - 100;
-			return nv_crtc->set_color_vibrance(nv_crtc, true);
-		}
+	ret = connector->funcs->atomic_set_property(&nv_connector->base,
+						    &asyc->state,
+						    property, value);
+	if (ret) {
+		if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV)
+			return get_slave_funcs(encoder)->set_property(
+				encoder, connector, property, value);
+		return ret;
 	}
 
-	if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV)
-		return get_slave_funcs(encoder)->set_property(
-			encoder, connector, property, value);
-
-	return -EINVAL;
-}
-
-static struct drm_display_mode *
-nouveau_connector_native_mode(struct drm_connector *connector)
-{
-	const struct drm_connector_helper_funcs *helper = connector->helper_private;
-	struct nouveau_drm *drm = nouveau_drm(connector->dev);
-	struct nouveau_connector *nv_connector = nouveau_connector(connector);
-	struct drm_device *dev = connector->dev;
-	struct drm_display_mode *mode, *largest = NULL;
-	int high_w = 0, high_h = 0, high_v = 0;
-
-	list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
-		mode->vrefresh = drm_mode_vrefresh(mode);
-		if (helper->mode_valid(connector, mode) != MODE_OK ||
-		    (mode->flags & DRM_MODE_FLAG_INTERLACE))
-			continue;
-
-		/* Use preferred mode if there is one.. */
-		if (mode->type & DRM_MODE_TYPE_PREFERRED) {
-			NV_DEBUG(drm, "native mode from preferred\n");
-			return drm_mode_duplicate(dev, mode);
-		}
-
-		/* Otherwise, take the resolution with the largest width, then
-		 * height, then vertical refresh
-		 */
-		if (mode->hdisplay < high_w)
-			continue;
-
-		if (mode->hdisplay == high_w && mode->vdisplay < high_h)
-			continue;
-
-		if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
-		    mode->vrefresh < high_v)
-			continue;
+	nv_connector->scaling_mode = asyc->scaler.mode;
+	nv_connector->dithering_mode = asyc->dither.mode;
 
-		high_w = mode->hdisplay;
-		high_h = mode->vdisplay;
-		high_v = mode->vrefresh;
-		largest = mode;
+	if (connector->encoder && connector->encoder->crtc) {
+		ret = drm_crtc_helper_set_mode(connector->encoder->crtc,
+					      &connector->encoder->crtc->mode,
+					       connector->encoder->crtc->x,
+					       connector->encoder->crtc->y,
+					       NULL);
+		if (!ret)
+			return -EINVAL;
 	}
 
-	NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n",
-		      high_w, high_h, high_v);
-	return largest ? drm_mode_duplicate(dev, largest) : NULL;
+	return 0;
 }
 
 struct moderec {
@@ -805,8 +943,7 @@ nouveau_connector_get_modes(struct drm_c
 	 * the list of modes.
 	 */
 	if (!nv_connector->native_mode)
-		nv_connector->native_mode =
-			nouveau_connector_native_mode(connector);
+		nv_connector->native_mode = nouveau_conn_native_mode(connector);
 	if (ret == 0 && nv_connector->native_mode) {
 		struct drm_display_mode *mode;
 
@@ -934,56 +1071,42 @@ nouveau_connector_helper_funcs = {
 	.best_encoder = nouveau_connector_best_encoder,
 };
 
+static int
+nouveau_connector_dpms(struct drm_connector *connector, int mode)
+{
+	if (connector->dev->mode_config.funcs->atomic_commit)
+		return drm_atomic_helper_connector_dpms(connector, mode);
+	return drm_helper_connector_dpms(connector, mode);
+}
+
 static const struct drm_connector_funcs
 nouveau_connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = nouveau_connector_dpms,
+	.reset = nouveau_conn_reset,
 	.detect = nouveau_connector_detect,
-	.destroy = nouveau_connector_destroy,
+	.force = nouveau_connector_force,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = nouveau_connector_set_property,
-	.force = nouveau_connector_force
+	.destroy = nouveau_connector_destroy,
+	.atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
+	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
+	.atomic_set_property = nouveau_conn_atomic_set_property,
+	.atomic_get_property = nouveau_conn_atomic_get_property,
 };
 
 static const struct drm_connector_funcs
 nouveau_connector_funcs_lvds = {
-	.dpms = drm_helper_connector_dpms,
+	.dpms = nouveau_connector_dpms,
+	.reset = nouveau_conn_reset,
 	.detect = nouveau_connector_detect_lvds,
-	.destroy = nouveau_connector_destroy,
+	.force = nouveau_connector_force,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.set_property = nouveau_connector_set_property,
-	.force = nouveau_connector_force
-};
-
-static int
-nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
-{
-	struct nouveau_encoder *nv_encoder = NULL;
-
-	if (connector->encoder)
-		nv_encoder = nouveau_encoder(connector->encoder);
-	if (nv_encoder && nv_encoder->dcb &&
-	    nv_encoder->dcb->type == DCB_OUTPUT_DP) {
-		if (mode == DRM_MODE_DPMS_ON) {
-			u8 data = DP_SET_POWER_D0;
-			nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1);
-			usleep_range(1000, 2000);
-		} else {
-			u8 data = DP_SET_POWER_D3;
-			nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1);
-		}
-	}
-
-	return drm_helper_connector_dpms(connector, mode);
-}
-
-static const struct drm_connector_funcs
-nouveau_connector_funcs_dp = {
-	.dpms = nouveau_connector_dp_dpms,
-	.detect = nouveau_connector_detect,
 	.destroy = nouveau_connector_destroy,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.set_property = nouveau_connector_set_property,
-	.force = nouveau_connector_force
+	.atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
+	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
+	.atomic_set_property = nouveau_conn_atomic_set_property,
+	.atomic_get_property = nouveau_conn_atomic_get_property,
 };
 
 static int
@@ -995,19 +1118,20 @@ nouveau_connector_hotplug(struct nvif_no
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	const struct nvif_notify_conn_rep_v0 *rep = notify->data;
 	const char *name = connector->name;
+	struct nouveau_encoder *nv_encoder;
 
 	if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
+		NV_DEBUG(drm, "service %s\n", name);
+		if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP)))
+			nv50_mstm_service(nv_encoder->dp.mstm);
 	} else {
 		bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
 
 		NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
-
-		mutex_lock(&drm->dev->mode_config.mutex);
-		if (plugged)
-			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
-		else
-			drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-		mutex_unlock(&drm->dev->mode_config.mutex);
+		if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) {
+			if (!plugged)
+				nv50_mstm_remove(nv_encoder->dp.mstm);
+		}
 
 		drm_helper_hpd_irq_event(connector->dev);
 	}
@@ -1188,7 +1312,7 @@ nouveau_connector_create(struct drm_devi
 			return ERR_PTR(ret);
 		}
 
-		funcs = &nouveau_connector_funcs_dp;
+		funcs = &nouveau_connector_funcs;
 		break;
 	default:
 		funcs = &nouveau_connector_funcs;
@@ -1202,38 +1326,10 @@ nouveau_connector_create(struct drm_devi
 	drm_connector_init(dev, connector, funcs, type);
 	drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
 
-	/* Init DVI-I specific properties */
-	if (nv_connector->type == DCB_CONNECTOR_DVI_I)
-		drm_object_attach_property(&connector->base, dev->mode_config.dvi_i_subconnector_property, 0);
-
-	/* Add overscan compensation options to digital outputs */
-	if (disp->underscan_property &&
-	    (type == DRM_MODE_CONNECTOR_DVID ||
-	     type == DRM_MODE_CONNECTOR_DVII ||
-	     type == DRM_MODE_CONNECTOR_HDMIA ||
-	     type == DRM_MODE_CONNECTOR_DisplayPort)) {
-		drm_object_attach_property(&connector->base,
-					      disp->underscan_property,
-					      UNDERSCAN_OFF);
-		drm_object_attach_property(&connector->base,
-					      disp->underscan_hborder_property,
-					      0);
-		drm_object_attach_property(&connector->base,
-					      disp->underscan_vborder_property,
-					      0);
-	}
-
-	/* Add hue and saturation options */
-	if (disp->vibrant_hue_property)
-		drm_object_attach_property(&connector->base,
-					      disp->vibrant_hue_property,
-					      90);
-	if (disp->color_vibrance_property)
-		drm_object_attach_property(&connector->base,
-					      disp->color_vibrance_property,
-					      150);
+	connector->funcs->reset(connector);
+	nouveau_conn_attach_properties(connector);
 
-	/* default scaling mode */
+	/* Default scaling mode */
 	switch (nv_connector->type) {
 	case DCB_CONNECTOR_LVDS:
 	case DCB_CONNECTOR_LVDS_SPWG:
@@ -1250,23 +1346,6 @@ nouveau_connector_create(struct drm_devi
 		break;
 	}
 
-	/* scaling mode property */
-	switch (nv_connector->type) {
-	case DCB_CONNECTOR_TV_0:
-	case DCB_CONNECTOR_TV_1:
-	case DCB_CONNECTOR_TV_3:
-		break;
-	case DCB_CONNECTOR_VGA:
-		if (disp->disp.oclass < NV50_DISP)
-			break; /* can only scale on DFPs */
-		/* fall-through */
-	default:
-		drm_object_attach_property(&connector->base, dev->mode_config.
-					   scaling_mode_property,
-					   nv_connector->scaling_mode);
-		break;
-	}
-
 	/* dithering properties */
 	switch (nv_connector->type) {
 	case DCB_CONNECTOR_TV_0:
@@ -1275,20 +1354,7 @@ nouveau_connector_create(struct drm_devi
 	case DCB_CONNECTOR_VGA:
 		break;
 	default:
-		if (disp->dithering_mode) {
-			nv_connector->dithering_mode = DITHERING_MODE_AUTO;
-			drm_object_attach_property(&connector->base,
-						   disp->dithering_mode,
-						   nv_connector->
-						   dithering_mode);
-		}
-		if (disp->dithering_depth) {
-			nv_connector->dithering_depth = DITHERING_DEPTH_AUTO;
-			drm_object_attach_property(&connector->base,
-						   disp->dithering_depth,
-						   nv_connector->
-						   dithering_depth);
-		}
+		nv_connector->dithering_mode = DITHERING_MODE_AUTO;
 		break;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_connector.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,30 +35,6 @@
 
 struct nvkm_i2c_port;
 
-enum nouveau_underscan_type {
-	UNDERSCAN_OFF,
-	UNDERSCAN_ON,
-	UNDERSCAN_AUTO,
-};
-
-/* the enum values specifically defined here match nv50/nvd0 hw values, and
- * the code relies on this
- */
-enum nouveau_dithering_mode {
-	DITHERING_MODE_OFF = 0x00,
-	DITHERING_MODE_ON = 0x01,
-	DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
-	DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
-	DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
-	DITHERING_MODE_AUTO
-};
-
-enum nouveau_dithering_depth {
-	DITHERING_DEPTH_6BPC = 0x00,
-	DITHERING_DEPTH_8BPC = 0x02,
-	DITHERING_DEPTH_AUTO
-};
-
 struct nouveau_connector {
 	struct drm_connector base;
 	enum dcb_connector_type type;
@@ -70,12 +46,7 @@ struct nouveau_connector {
 	struct drm_dp_aux aux;
 
 	int dithering_mode;
-	int dithering_depth;
 	int scaling_mode;
-	bool scaling_full;
-	enum nouveau_underscan_type underscan;
-	u32 underscan_hborder;
-	u32 underscan_vborder;
 
 	struct nouveau_encoder *detected_encoder;
 	struct edid *edid;
@@ -109,5 +80,74 @@ nouveau_connector_create(struct drm_devi
 extern int nouveau_tv_disable;
 extern int nouveau_ignorelid;
 extern int nouveau_duallink;
+extern int nouveau_hdmimhz;
+
+#include <drm/drm_crtc.h>
+#define nouveau_conn_atom(p)                                                   \
+	container_of((p), struct nouveau_conn_atom, state)
+
+struct nouveau_conn_atom {
+	struct drm_connector_state state;
+
+	struct {
+		/* The enum values specifically defined here match nv50/gf119
+		 * hw values, and the code relies on this.
+		 */
+		enum {
+			DITHERING_MODE_OFF = 0x00,
+			DITHERING_MODE_ON = 0x01,
+			DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
+			DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
+			DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
+			DITHERING_MODE_AUTO
+		} mode;
+		enum {
+			DITHERING_DEPTH_6BPC = 0x00,
+			DITHERING_DEPTH_8BPC = 0x02,
+			DITHERING_DEPTH_AUTO
+		} depth;
+	} dither;
 
+	struct {
+		int mode;	/* DRM_MODE_SCALE_* */
+		struct {
+			enum {
+				UNDERSCAN_OFF,
+				UNDERSCAN_ON,
+				UNDERSCAN_AUTO,
+			} mode;
+			u32 hborder;
+			u32 vborder;
+		} underscan;
+		bool full;
+	} scaler;
+
+	struct {
+		int color_vibrance;
+		int vibrant_hue;
+	} procamp;
+
+	union {
+		struct {
+			bool dither:1;
+			bool scaler:1;
+			bool procamp:1;
+		};
+		u8 mask;
+	} set;
+};
+
+void nouveau_conn_attach_properties(struct drm_connector *);
+void nouveau_conn_reset(struct drm_connector *);
+struct drm_connector_state *
+nouveau_conn_atomic_duplicate_state(struct drm_connector *);
+void nouveau_conn_atomic_destroy_state(struct drm_connector *,
+				       struct drm_connector_state *);
+int nouveau_conn_atomic_set_property(struct drm_connector *,
+				     struct drm_connector_state *,
+				     struct drm_property *, u64);
+int nouveau_conn_atomic_get_property(struct drm_connector *,
+				     const struct drm_connector_state *,
+				     struct drm_property *, u64 *);
+struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
 #endif /* __NOUVEAU_CONNECTOR_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_crtc.h	2017-02-12 16:03:20.000000000 -0500
@@ -38,8 +38,6 @@ struct nouveau_crtc {
 	uint32_t dpms_saved_fp_control;
 	uint32_t fp_users;
 	int saturation;
-	int color_vibrance;
-	int vibrant_hue;
 	int sharpness;
 	int last_dpms;
 
@@ -54,7 +52,6 @@ struct nouveau_crtc {
 
 	struct {
 		struct nouveau_bo *nvbo;
-		bool visible;
 		uint32_t offset;
 		void (*set_offset)(struct nouveau_crtc *, uint32_t offset);
 		void (*set_pos)(struct nouveau_crtc *, int x, int y);
@@ -70,10 +67,6 @@ struct nouveau_crtc {
 		int depth;
 	} lut;
 
-	int (*set_dither)(struct nouveau_crtc *crtc, bool update);
-	int (*set_scale)(struct nouveau_crtc *crtc, bool update);
-	int (*set_color_vibrance)(struct nouveau_crtc *crtc, bool update);
-
 	void (*save)(struct drm_crtc *crtc);
 	void (*restore)(struct drm_crtc *crtc);
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,10 @@
  *
  */
 
+#include <acpi/video.h>
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
 
 #include <nvif/class.h>
@@ -92,7 +95,7 @@ calc(int blanks, int blanke, int total,
 	return line;
 }
 
-int
+static int
 nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
 				ktime_t *stime, ktime_t *etime)
 {
@@ -158,9 +161,13 @@ nouveau_display_vblstamp(struct drm_devi
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		if (nouveau_crtc(crtc)->index == pipe) {
+			struct drm_display_mode *mode;
+			if (dev->mode_config.funcs->atomic_commit)
+				mode = &crtc->state->adjusted_mode;
+			else
+				mode = &crtc->hwmode;
 			return drm_calc_vbltimestamp_from_scanoutpos(dev,
-					pipe, max_error, time, flags,
-					&crtc->hwmode);
+					pipe, max_error, time, flags, mode);
 		}
 	}
 
@@ -217,10 +224,6 @@ static void
 nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
 {
 	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
-	struct nouveau_display *disp = nouveau_display(drm_fb->dev);
-
-	if (disp->fb_dtor)
-		disp->fb_dtor(drm_fb);
 
 	if (fb->nvbo)
 		drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
@@ -245,57 +248,45 @@ static const struct drm_framebuffer_func
 };
 
 int
-nouveau_framebuffer_init(struct drm_device *dev,
-			 struct nouveau_framebuffer *nv_fb,
-			 const struct drm_mode_fb_cmd2 *mode_cmd,
-			 struct nouveau_bo *nvbo)
+nouveau_framebuffer_new(struct drm_device *dev,
+			const struct drm_mode_fb_cmd2 *mode_cmd,
+			struct nouveau_bo *nvbo,
+			struct nouveau_framebuffer **pfb)
 {
-	struct nouveau_display *disp = nouveau_display(dev);
-	struct drm_framebuffer *fb = &nv_fb->base;
+	struct nouveau_framebuffer *fb;
 	int ret;
 
-	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
-	nv_fb->nvbo = nvbo;
-
-	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
-	if (ret)
-		return ret;
+	if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))
+		return -ENOMEM;
 
-	if (disp->fb_ctor) {
-		ret = disp->fb_ctor(fb);
-		if (ret)
-			disp->fb_dtor(fb);
-	}
+	drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+	fb->nvbo = nvbo;
 
+	ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs);
+	if (ret)
+		kfree(fb);
 	return ret;
 }
 
-static struct drm_framebuffer *
+struct drm_framebuffer *
 nouveau_user_framebuffer_create(struct drm_device *dev,
 				struct drm_file *file_priv,
 				const struct drm_mode_fb_cmd2 *mode_cmd)
 {
-	struct nouveau_framebuffer *nouveau_fb;
+	struct nouveau_framebuffer *fb;
+	struct nouveau_bo *nvbo;
 	struct drm_gem_object *gem;
-	int ret = -ENOMEM;
+	int ret;
 
 	gem = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
 	if (!gem)
 		return ERR_PTR(-ENOENT);
+	nvbo = nouveau_gem_object(gem);
 
-	nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
-	if (!nouveau_fb)
-		goto err_unref;
-
-	ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
-	if (ret)
-		goto err;
-
-	return &nouveau_fb->base;
+	ret = nouveau_framebuffer_new(dev, mode_cmd, nvbo, &fb);
+	if (ret == 0)
+		return &fb->base;
 
-err:
-	kfree(nouveau_fb);
-err_unref:
 	drm_gem_object_unreference_unlocked(gem);
 	return ERR_PTR(ret);
 }
@@ -358,6 +349,55 @@ static struct nouveau_drm_prop_enum_list
 	}                                                                      \
 } while(0)
 
+static void
+nouveau_display_hpd_work(struct work_struct *work)
+{
+	struct nouveau_drm *drm = container_of(work, typeof(*drm), hpd_work);
+
+	pm_runtime_get_sync(drm->dev->dev);
+
+	drm_helper_hpd_irq_event(drm->dev);
+
+	pm_runtime_mark_last_busy(drm->dev->dev);
+	pm_runtime_put_sync(drm->dev->dev);
+}
+
+#ifdef CONFIG_ACPI
+
+/*
+ * Hans de Goede: This define belongs in acpi/video.h, I've submitted a patch
+ * to the acpi subsys to move it there from drivers/acpi/acpi_video.c .
+ * This should be dropped once that is merged.
+ */
+#ifndef ACPI_VIDEO_NOTIFY_PROBE
+#define ACPI_VIDEO_NOTIFY_PROBE			0x81
+#endif
+
+static int
+nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
+			  void *data)
+{
+	struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
+	struct acpi_bus_event *info = data;
+
+	if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
+		if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
+			/*
+			 * This may be the only indication we receive of a
+			 * connector hotplug on a runtime suspended GPU,
+			 * schedule hpd_work to check.
+			 */
+			schedule_work(&drm->hpd_work);
+
+			/* acpi-video should not generate keypresses for this */
+			return NOTIFY_BAD;
+		}
+	}
+
+	return NOTIFY_DONE;
+}
+#endif
+
 int
 nouveau_display_init(struct drm_device *dev)
 {
@@ -371,7 +411,8 @@ nouveau_display_init(struct drm_device *
 		return ret;
 
 	/* enable polling for external displays */
-	drm_kms_helper_poll_enable(dev);
+	if (!dev->mode_config.poll_enabled)
+		drm_kms_helper_poll_enable(dev);
 
 	/* enable hotplug interrupts */
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -385,16 +426,19 @@ nouveau_display_init(struct drm_device *
 }
 
 void
-nouveau_display_fini(struct drm_device *dev)
+nouveau_display_fini(struct drm_device *dev, bool suspend)
 {
 	struct nouveau_display *disp = nouveau_display(dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct drm_connector *connector;
-	int head;
+	struct drm_crtc *crtc;
+
+	if (!suspend)
+		drm_crtc_force_disable_all(dev);
 
 	/* Make sure that drm and hw vblank irqs get properly disabled. */
-	for (head = 0; head < dev->mode_config.num_crtc; head++)
-		drm_vblank_off(dev, head);
+	drm_for_each_crtc(crtc, dev)
+		drm_crtc_vblank_off(crtc);
 
 	/* disable flip completion events */
 	nvif_notify_put(&drm->flip);
@@ -495,7 +539,7 @@ nouveau_display_create(struct drm_device
 
 	if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
 		static const u16 oclass[] = {
-			GP104_DISP,
+			GP102_DISP,
 			GP100_DISP,
 			GM200_DISP,
 			GM107_DISP,
@@ -530,6 +574,8 @@ nouveau_display_create(struct drm_device
 	if (ret)
 		goto disp_create_err;
 
+	drm_mode_config_reset(dev);
+
 	if (dev->mode_config.num_crtc) {
 		ret = nouveau_display_vblank_init(dev);
 		if (ret)
@@ -537,6 +583,12 @@ nouveau_display_create(struct drm_device
 	}
 
 	nouveau_backlight_init(dev);
+	INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
+#ifdef CONFIG_ACPI
+	drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
+	register_acpi_notifier(&drm->acpi_nb);
+#endif
+
 	return 0;
 
 vblank_err:
@@ -552,11 +604,13 @@ nouveau_display_destroy(struct drm_devic
 {
 	struct nouveau_display *disp = nouveau_display(dev);
 
+#ifdef CONFIG_ACPI
+	unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
+#endif
 	nouveau_backlight_exit(dev);
 	nouveau_display_vblank_fini(dev);
 
 	drm_kms_helper_poll_fini(dev);
-	drm_crtc_force_disable_all(dev);
 	drm_mode_config_cleanup(dev);
 
 	if (disp->dtor)
@@ -568,12 +622,138 @@ nouveau_display_destroy(struct drm_devic
 	kfree(disp);
 }
 
+static int
+nouveau_atomic_disable_connector(struct drm_atomic_state *state,
+				 struct drm_connector *connector)
+{
+	struct drm_connector_state *connector_state;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_plane_state *plane_state;
+	struct drm_plane *plane;
+	int ret;
+
+	if (!(crtc = connector->state->crtc))
+		return 0;
+
+	connector_state = drm_atomic_get_connector_state(state, connector);
+	if (IS_ERR(connector_state))
+		return PTR_ERR(connector_state);
+
+	ret = drm_atomic_set_crtc_for_connector(connector_state, NULL);
+	if (ret)
+		return ret;
+
+	crtc_state = drm_atomic_get_crtc_state(state, crtc);
+	if (IS_ERR(crtc_state))
+		return PTR_ERR(crtc_state);
+
+	ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
+	if (ret)
+		return ret;
+
+	crtc_state->active = false;
+
+	drm_for_each_plane_mask(plane, connector->dev, crtc_state->plane_mask) {
+		plane_state = drm_atomic_get_plane_state(state, plane);
+		if (IS_ERR(plane_state))
+			return PTR_ERR(plane_state);
+
+		ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
+		if (ret)
+			return ret;
+
+		drm_atomic_set_fb_for_plane(plane_state, NULL);
+	}
+
+	return 0;
+}
+
+static int
+nouveau_atomic_disable(struct drm_device *dev,
+		       struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_atomic_state *state;
+	struct drm_connector *connector;
+	int ret;
+
+	state = drm_atomic_state_alloc(dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = ctx;
+
+	drm_for_each_connector(connector, dev) {
+		ret = nouveau_atomic_disable_connector(state, connector);
+		if (ret)
+			break;
+	}
+
+	if (ret == 0)
+		ret = drm_atomic_commit(state);
+	drm_atomic_state_put(state);
+	return ret;
+}
+
+static struct drm_atomic_state *
+nouveau_atomic_suspend(struct drm_device *dev)
+{
+	struct drm_modeset_acquire_ctx ctx;
+	struct drm_atomic_state *state;
+	int ret;
+
+	drm_modeset_acquire_init(&ctx, 0);
+
+retry:
+	ret = drm_modeset_lock_all_ctx(dev, &ctx);
+	if (ret < 0) {
+		state = ERR_PTR(ret);
+		goto unlock;
+	}
+
+	state = drm_atomic_helper_duplicate_state(dev, &ctx);
+	if (IS_ERR(state))
+		goto unlock;
+
+	ret = nouveau_atomic_disable(dev, &ctx);
+	if (ret < 0) {
+		drm_atomic_state_put(state);
+		state = ERR_PTR(ret);
+		goto unlock;
+	}
+
+unlock:
+	if (PTR_ERR(state) == -EDEADLK) {
+		drm_modeset_backoff(&ctx);
+		goto retry;
+	}
+
+	drm_modeset_drop_locks(&ctx);
+	drm_modeset_acquire_fini(&ctx);
+	return state;
+}
+
 int
 nouveau_display_suspend(struct drm_device *dev, bool runtime)
 {
+	struct nouveau_display *disp = nouveau_display(dev);
 	struct drm_crtc *crtc;
 
-	nouveau_display_fini(dev);
+	if (dev->mode_config.funcs->atomic_commit) {
+		if (!runtime) {
+			disp->suspend = nouveau_atomic_suspend(dev);
+			if (IS_ERR(disp->suspend)) {
+				int ret = PTR_ERR(disp->suspend);
+				disp->suspend = NULL;
+				return ret;
+			}
+		}
+
+		nouveau_display_fini(dev, true);
+		return 0;
+	}
+
+	nouveau_display_fini(dev, true);
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_framebuffer *nouveau_fb;
@@ -600,9 +780,19 @@ nouveau_display_suspend(struct drm_devic
 void
 nouveau_display_resume(struct drm_device *dev, bool runtime)
 {
+	struct nouveau_display *disp = nouveau_display(dev);
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct drm_crtc *crtc;
-	int ret, head;
+	int ret;
+
+	if (dev->mode_config.funcs->atomic_commit) {
+		nouveau_display_init(dev);
+		if (disp->suspend) {
+			drm_atomic_helper_resume(dev, disp->suspend);
+			disp->suspend = NULL;
+		}
+		return;
+	}
 
 	/* re-pin fb/cursors */
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -647,10 +837,6 @@ nouveau_display_resume(struct drm_device
 
 	drm_helper_resume_force_mode(dev);
 
-	/* Make sure that drm and hw vblank irqs get resumed if needed. */
-	for (head = 0; head < dev->mode_config.num_crtc; head++)
-		drm_vblank_on(dev, head);
-
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 
@@ -692,10 +878,7 @@ nouveau_page_flip_emit(struct nouveau_ch
 	if (ret)
 		goto fail;
 
-	if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
-		BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
-	else
-		BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1);
+	BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
 	OUT_RING  (chan, 0x00000000);
 	FIRE_RING (chan);
 
@@ -724,6 +907,8 @@ nouveau_crtc_page_flip(struct drm_crtc *
 	struct nouveau_channel *chan;
 	struct nouveau_cli *cli;
 	struct nouveau_fence *fence;
+	struct nv04_display *dispnv04 = nv04_display(dev);
+	int head = nouveau_crtc(crtc)->index;
 	int ret;
 
 	chan = drm->channel;
@@ -770,32 +955,23 @@ nouveau_crtc_page_flip(struct drm_crtc *
 	drm_crtc_vblank_get(crtc);
 
 	/* Emit a page flip */
-	if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
-		ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);
+	if (swap_interval) {
+		ret = RING_SPACE(chan, 8);
 		if (ret)
 			goto fail_unreserve;
-	} else {
-		struct nv04_display *dispnv04 = nv04_display(dev);
-		int head = nouveau_crtc(crtc)->index;
-
-		if (swap_interval) {
-			ret = RING_SPACE(chan, 8);
-			if (ret)
-				goto fail_unreserve;
-
-			BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
-			OUT_RING  (chan, 0);
-			BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
-			OUT_RING  (chan, head);
-			BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
-			OUT_RING  (chan, 0);
-			BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
-			OUT_RING  (chan, 0);
-		}
 
-		nouveau_bo_ref(new_bo, &dispnv04->image[head]);
+		BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
+		OUT_RING  (chan, 0);
+		BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
+		OUT_RING  (chan, head);
+		BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
+		OUT_RING  (chan, 0);
+		BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
+		OUT_RING  (chan, 0);
 	}
 
+	nouveau_bo_ref(new_bo, &dispnv04->image[head]);
+
 	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
 	if (ret)
 		goto fail_unreserve;
@@ -843,16 +1019,8 @@ nouveau_finish_page_flip(struct nouveau_
 
 	s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
 	if (s->event) {
-		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
-			drm_crtc_arm_vblank_event(s->crtc, s->event);
-		} else {
-			drm_crtc_send_vblank_event(s->crtc, s->event);
-
-			/* Give up ownership of vblank for page-flipped crtc */
-			drm_crtc_vblank_put(s->crtc);
-		}
-	}
-	else {
+		drm_crtc_arm_vblank_event(s->crtc, s->event);
+	} else {
 		/* Give up ownership of vblank for page-flipped crtc */
 		drm_crtc_vblank_put(s->crtc);
 	}
@@ -874,12 +1042,10 @@ nouveau_flip_complete(struct nvif_notify
 	struct nouveau_page_flip_state state;
 
 	if (!nouveau_finish_page_flip(chan, &state)) {
-		if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
-			nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
-					 state.offset + state.crtc->y *
-					 state.pitch + state.crtc->x *
-					 state.bpp / 8);
-		}
+		nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
+				 state.offset + state.crtc->y *
+				 state.pitch + state.crtc->x *
+				 state.bpp / 8);
 	}
 
 	return NVIF_NOTIFY_KEEP;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_display.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_display.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_display.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_display.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,8 +22,9 @@ nouveau_framebuffer(struct drm_framebuff
 	return container_of(fb, struct nouveau_framebuffer, base);
 }
 
-int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *,
-			     const struct drm_mode_fb_cmd2 *, struct nouveau_bo *);
+int nouveau_framebuffer_new(struct drm_device *,
+			    const struct drm_mode_fb_cmd2 *,
+			    struct nouveau_bo *, struct nouveau_framebuffer **);
 
 struct nouveau_page_flip_state {
 	struct list_head head;
@@ -39,9 +40,6 @@ struct nouveau_display {
 	int  (*init)(struct drm_device *);
 	void (*fini)(struct drm_device *);
 
-	int  (*fb_ctor)(struct drm_framebuffer *);
-	void (*fb_dtor)(struct drm_framebuffer *);
-
 	struct nvif_object disp;
 
 	struct drm_property *dithering_mode;
@@ -52,6 +50,8 @@ struct nouveau_display {
 	/* not really hue and saturation: */
 	struct drm_property *vibrant_hue_property;
 	struct drm_property *color_vibrance_property;
+
+	struct drm_atomic_state *suspend;
 };
 
 static inline struct nouveau_display *
@@ -63,7 +63,7 @@ nouveau_display(struct drm_device *dev)
 int  nouveau_display_create(struct drm_device *dev);
 void nouveau_display_destroy(struct drm_device *dev);
 int  nouveau_display_init(struct drm_device *dev);
-void nouveau_display_fini(struct drm_device *dev);
+void nouveau_display_fini(struct drm_device *dev, bool suspend);
 int  nouveau_display_suspend(struct drm_device *dev, bool runtime);
 void nouveau_display_resume(struct drm_device *dev, bool runtime);
 int  nouveau_display_vblank_enable(struct drm_device *, unsigned int);
@@ -91,6 +91,8 @@ int nouveau_crtc_set_config(struct drm_m
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
 extern int nouveau_backlight_init(struct drm_device *);
 extern void nouveau_backlight_exit(struct drm_device *);
+extern void nouveau_backlight_ctor(void);
+extern void nouveau_backlight_dtor(void);
 #else
 static inline int
 nouveau_backlight_init(struct drm_device *dev)
@@ -101,6 +103,17 @@ nouveau_backlight_init(struct drm_device
 static inline void
 nouveau_backlight_exit(struct drm_device *dev) {
 }
+
+static inline void
+nouveau_backlight_ctor(void) {
+}
+
+static inline void
+nouveau_backlight_dtor(void) {
+}
 #endif
 
+struct drm_framebuffer *
+nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
+				const struct drm_mode_fb_cmd2 *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,13 @@
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
 
+#include <nvif/class.h>
+#include <nvif/cl5070.h>
+
+MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
+static int nouveau_mst = 1;
+module_param_named(mst, nouveau_mst, int, 0400);
+
 static void
 nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_aux *aux, u8 *dpcd)
 {
@@ -55,14 +62,14 @@ nouveau_dp_detect(struct nouveau_encoder
 	struct drm_device *dev = nv_encoder->base.base.dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nvkm_i2c_aux *aux;
-	u8 *dpcd = nv_encoder->dp.dpcd;
+	u8 dpcd[8];
 	int ret;
 
 	aux = nv_encoder->aux;
 	if (!aux)
 		return -ENODEV;
 
-	ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, 8);
+	ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, sizeof(dpcd));
 	if (ret)
 		return ret;
 
@@ -84,5 +91,11 @@ nouveau_dp_detect(struct nouveau_encoder
 		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
 
 	nouveau_dp_probe_oui(dev, aux, dpcd);
-	return 0;
+
+	ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst);
+	if (ret == 1)
+		return NOUVEAU_DP_MST;
+	if (ret == 0)
+		return NOUVEAU_DP_SST;
+	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_drm.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,7 @@
 #include "nouveau_ttm.h"
 #include "nouveau_gem.h"
 #include "nouveau_vga.h"
+#include "nouveau_led.h"
 #include "nouveau_hwmon.h"
 #include "nouveau_acpi.h"
 #include "nouveau_bios.h"
@@ -475,6 +476,7 @@ nouveau_drm_load(struct drm_device *dev,
 	nouveau_hwmon_init(dev);
 	nouveau_accel_init(drm);
 	nouveau_fbcon_init(dev);
+	nouveau_led_init(dev);
 
 	if (nouveau_runtime_pm != 0) {
 		pm_runtime_use_autosuspend(dev->dev);
@@ -510,13 +512,14 @@ nouveau_drm_unload(struct drm_device *de
 		pm_runtime_forbid(dev->dev);
 	}
 
+	nouveau_led_fini(dev);
 	nouveau_fbcon_fini(dev);
 	nouveau_accel_fini(drm);
 	nouveau_hwmon_fini(dev);
 	nouveau_debugfs_fini(drm);
 
 	if (dev->mode_config.num_crtc)
-		nouveau_display_fini(dev);
+		nouveau_display_fini(dev, false);
 	nouveau_display_destroy(dev);
 
 	nouveau_bios_takedown(dev);
@@ -561,6 +564,8 @@ nouveau_do_suspend(struct drm_device *de
 	struct nouveau_cli *cli;
 	int ret;
 
+	nouveau_led_suspend(dev);
+
 	if (dev->mode_config.num_crtc) {
 		NV_INFO(drm, "suspending console...\n");
 		nouveau_fbcon_set_suspend(dev, 1);
@@ -649,6 +654,8 @@ nouveau_do_resume(struct drm_device *dev
 		nouveau_fbcon_set_suspend(dev, 0);
 	}
 
+	nouveau_led_resume(dev);
+
 	return 0;
 }
 
@@ -692,7 +699,12 @@ nouveau_pmops_resume(struct device *dev)
 		return ret;
 	pci_set_master(pdev);
 
-	return nouveau_do_resume(drm_dev, false);
+	ret = nouveau_do_resume(drm_dev, false);
+
+	/* Monitors may have been connected / disconnected during suspend */
+	schedule_work(&nouveau_drm(drm_dev)->hpd_work);
+
+	return ret;
 }
 
 static int
@@ -761,11 +773,18 @@ nouveau_pmops_runtime_resume(struct devi
 	pci_set_master(pdev);
 
 	ret = nouveau_do_resume(drm_dev, true);
-	drm_kms_helper_poll_enable(drm_dev);
+
+	if (!drm_dev->mode_config.poll_enabled)
+		drm_kms_helper_poll_enable(drm_dev);
+
 	/* do magic */
 	nvif_mask(&device->object, 0x088488, (1 << 25), (1 << 25));
 	vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_ON);
 	drm_dev->switch_power_state = DRM_SWITCH_POWER_ON;
+
+	/* Monitors may have been connected / disconnected during suspend */
+	schedule_work(&nouveau_drm(drm_dev)->hpd_work);
+
 	return ret;
 }
 
@@ -1030,6 +1049,7 @@ static void nouveau_display_options(void
 	DRM_DEBUG_DRIVER("... modeset      : %d\n", nouveau_modeset);
 	DRM_DEBUG_DRIVER("... runpm        : %d\n", nouveau_runtime_pm);
 	DRM_DEBUG_DRIVER("... vram_pushbuf : %d\n", nouveau_vram_pushbuf);
+	DRM_DEBUG_DRIVER("... hdmimhz      : %d\n", nouveau_hdmimhz);
 }
 
 static const struct dev_pm_ops nouveau_pm_ops = {
@@ -1105,6 +1125,7 @@ nouveau_drm_init(void)
 #endif
 
 	nouveau_register_dsm_handler();
+	nouveau_backlight_ctor();
 	return drm_pci_init(&driver_pci, &nouveau_drm_pci_driver);
 }
 
@@ -1115,6 +1136,7 @@ nouveau_drm_exit(void)
 		return;
 
 	drm_pci_exit(&driver_pci, &nouveau_drm_pci_driver);
+	nouveau_backlight_dtor();
 	nouveau_unregister_dsm_handler();
 
 #ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,8 @@
  *      - implemented limited ABI16/NVIF interop
  */
 
+#include <linux/notifier.h>
+
 #include <nvif/client.h>
 #include <nvif/device.h>
 #include <nvif/ioctl.h>
@@ -161,11 +163,21 @@ struct nouveau_drm {
 	struct nvbios vbios;
 	struct nouveau_display *display;
 	struct backlight_device *backlight;
+	struct list_head bl_connectors;
+	struct work_struct hpd_work;
+	struct work_struct fbcon_work;
+	int fbcon_new_state;
+#ifdef CONFIG_ACPI
+	struct notifier_block acpi_nb;
+#endif
 
 	/* power management */
 	struct nouveau_hwmon *hwmon;
 	struct nouveau_debugfs *debugfs;
 
+	/* led management */
+	struct nouveau_led *led;
+
 	/* display power reference */
 	bool have_disp_power_ref;
 
@@ -201,6 +213,10 @@ void nouveau_drm_device_remove(struct dr
 	if (unlikely(drm_debug & DRM_UT_DRIVER))                               \
 		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
 } while(0)
+#define NV_ATOMIC(drm,f,a...) do {                                             \
+	if (unlikely(drm_debug & DRM_UT_ATOMIC))                               \
+		NV_PRINTK(info, &(drm)->client, f, ##a);                       \
+} while(0)
 
 extern int nouveau_modeset;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_encoder.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,7 @@
 #include <subdev/bios/dcb.h>
 
 #include <drm/drm_encoder_slave.h>
+#include <drm/drm_dp_mst_helper.h>
 #include "dispnv04/disp.h"
 
 #define NV_DPMS_CLEARED 0x80
@@ -57,15 +58,16 @@ struct nouveau_encoder {
 
 	union {
 		struct {
-			u8  dpcd[8];
+			struct nv50_mstm *mstm;
 			int link_nr;
 			int link_bw;
-			u32 datarate;
 		} dp;
 	};
 
 	void (*enc_save)(struct drm_encoder *encoder);
 	void (*enc_restore)(struct drm_encoder *encoder);
+	void (*update)(struct nouveau_encoder *, u8 head,
+		       struct drm_display_mode *, u8 proto, u8 depth);
 };
 
 struct nouveau_encoder *
@@ -90,9 +92,17 @@ get_slave_funcs(struct drm_encoder *enc)
 }
 
 /* nouveau_dp.c */
+enum nouveau_dp_status {
+	NOUVEAU_DP_SST,
+	NOUVEAU_DP_MST,
+};
+
 int nouveau_dp_detect(struct nouveau_encoder *);
 
 struct nouveau_connector *
 nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
 
+int nv50_mstm_detect(struct nv50_mstm *, u8 dpcd[8], int allow);
+void nv50_mstm_remove(struct nv50_mstm *);
+void nv50_mstm_service(struct nv50_mstm *);
 #endif /* __NOUVEAU_ENCODER_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,7 @@ static void
 nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct nouveau_fbdev *fbcon = info->par;
-	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 	struct nvif_device *device = &drm->device;
 	int ret;
 
@@ -90,7 +90,7 @@ static void
 nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
 {
 	struct nouveau_fbdev *fbcon = info->par;
-	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 	struct nvif_device *device = &drm->device;
 	int ret;
 
@@ -122,7 +122,7 @@ static void
 nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct nouveau_fbdev *fbcon = info->par;
-	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 	struct nvif_device *device = &drm->device;
 	int ret;
 
@@ -154,7 +154,7 @@ static int
 nouveau_fbcon_sync(struct fb_info *info)
 {
 	struct nouveau_fbdev *fbcon = info->par;
-	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret;
 
@@ -181,7 +181,7 @@ static int
 nouveau_fbcon_open(struct fb_info *info, int user)
 {
 	struct nouveau_fbdev *fbcon = info->par;
-	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 	int ret = pm_runtime_get_sync(drm->dev->dev);
 	if (ret < 0 && ret != -EACCES)
 		return ret;
@@ -192,42 +192,30 @@ static int
 nouveau_fbcon_release(struct fb_info *info, int user)
 {
 	struct nouveau_fbdev *fbcon = info->par;
-	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 	pm_runtime_put(drm->dev->dev);
 	return 0;
 }
 
 static struct fb_ops nouveau_fbcon_ops = {
 	.owner = THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_open = nouveau_fbcon_open,
 	.fb_release = nouveau_fbcon_release,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
 	.fb_fillrect = nouveau_fbcon_fillrect,
 	.fb_copyarea = nouveau_fbcon_copyarea,
 	.fb_imageblit = nouveau_fbcon_imageblit,
 	.fb_sync = nouveau_fbcon_sync,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 static struct fb_ops nouveau_fbcon_sw_ops = {
 	.owner = THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_open = nouveau_fbcon_open,
 	.fb_release = nouveau_fbcon_release,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 void
@@ -333,16 +321,15 @@ nouveau_fbcon_create(struct drm_fb_helpe
 {
 	struct nouveau_fbdev *fbcon =
 		container_of(helper, struct nouveau_fbdev, helper);
-	struct drm_device *dev = fbcon->dev;
+	struct drm_device *dev = fbcon->helper.dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nvif_device *device = &drm->device;
 	struct fb_info *info;
-	struct drm_framebuffer *fb;
-	struct nouveau_framebuffer *nouveau_fb;
+	struct nouveau_framebuffer *fb;
 	struct nouveau_channel *chan;
 	struct nouveau_bo *nvbo;
 	struct drm_mode_fb_cmd2 mode_cmd;
-	int size, ret;
+	int ret;
 
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
@@ -353,16 +340,17 @@ nouveau_fbcon_create(struct drm_fb_helpe
 	mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
 							  sizes->surface_depth);
 
-	size = mode_cmd.pitches[0] * mode_cmd.height;
-	size = roundup(size, PAGE_SIZE);
-
-	ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
-			      0, 0x0000, &nvbo);
+	ret = nouveau_gem_new(dev, mode_cmd.pitches[0] * mode_cmd.height,
+			      0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
 	if (ret) {
 		NV_ERROR(drm, "failed to allocate framebuffer\n");
 		goto out;
 	}
 
+	ret = nouveau_framebuffer_new(dev, &mode_cmd, nvbo, &fb);
+	if (ret)
+		goto out_unref;
+
 	ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false);
 	if (ret) {
 		NV_ERROR(drm, "failed to pin fb: %d\n", ret);
@@ -377,8 +365,7 @@ nouveau_fbcon_create(struct drm_fb_helpe
 
 	chan = nouveau_nofbaccel ? NULL : drm->channel;
 	if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
-		ret = nouveau_bo_vma_add(nvbo, drm->client.vm,
-					&fbcon->nouveau_fb.vma);
+		ret = nouveau_bo_vma_add(nvbo, drm->client.vm, &fb->vma);
 		if (ret) {
 			NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
 			chan = NULL;
@@ -394,13 +381,8 @@ nouveau_fbcon_create(struct drm_fb_helpe
 
 	info->par = fbcon;
 
-	nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo);
-
-	nouveau_fb = &fbcon->nouveau_fb;
-	fb = &nouveau_fb->base;
-
 	/* setup helper */
-	fbcon->helper.fb = fb;
+	fbcon->helper.fb = &fb->base;
 
 	strcpy(info->fix.id, "nouveaufb");
 	if (!chan)
@@ -411,14 +393,14 @@ nouveau_fbcon_create(struct drm_fb_helpe
 			      FBINFO_HWACCEL_IMAGEBLIT;
 	info->flags |= FBINFO_CAN_FORCE_OUTPUT;
 	info->fbops = &nouveau_fbcon_sw_ops;
-	info->fix.smem_start = nvbo->bo.mem.bus.base +
-			       nvbo->bo.mem.bus.offset;
-	info->fix.smem_len = size;
+	info->fix.smem_start = fb->nvbo->bo.mem.bus.base +
+			       fb->nvbo->bo.mem.bus.offset;
+	info->fix.smem_len = fb->nvbo->bo.mem.num_pages << PAGE_SHIFT;
 
-	info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
-	info->screen_size = size;
+	info->screen_base = nvbo_kmap_obj_iovirtual(fb->nvbo);
+	info->screen_size = fb->nvbo->bo.mem.num_pages << PAGE_SHIFT;
 
-	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+	drm_fb_helper_fill_fix(info, fb->base.pitches[0], fb->base.depth);
 	drm_fb_helper_fill_var(info, &fbcon->helper, sizes->fb_width, sizes->fb_height);
 
 	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
@@ -429,20 +411,19 @@ nouveau_fbcon_create(struct drm_fb_helpe
 
 	/* To allow resizeing without swapping buffers */
 	NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n",
-		nouveau_fb->base.width, nouveau_fb->base.height,
-		nvbo->bo.offset, nvbo);
+		fb->base.width, fb->base.height, fb->nvbo->bo.offset, nvbo);
 
 	vga_switcheroo_client_fb_set(dev->pdev, info);
 	return 0;
 
 out_unlock:
 	if (chan)
-		nouveau_bo_vma_del(nvbo, &fbcon->nouveau_fb.vma);
-	nouveau_bo_unmap(nvbo);
+		nouveau_bo_vma_del(fb->nvbo, &fb->vma);
+	nouveau_bo_unmap(fb->nvbo);
 out_unpin:
-	nouveau_bo_unpin(nvbo);
+	nouveau_bo_unpin(fb->nvbo);
 out_unref:
-	nouveau_bo_ref(NULL, &nvbo);
+	nouveau_bo_ref(NULL, &fb->nvbo);
 out:
 	return ret;
 }
@@ -458,28 +439,26 @@ nouveau_fbcon_output_poll_changed(struct
 static int
 nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
 {
-	struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb;
+	struct nouveau_framebuffer *nouveau_fb = nouveau_framebuffer(fbcon->helper.fb);
 
 	drm_fb_helper_unregister_fbi(&fbcon->helper);
 	drm_fb_helper_release_fbi(&fbcon->helper);
+	drm_fb_helper_fini(&fbcon->helper);
 
 	if (nouveau_fb->nvbo) {
-		nouveau_bo_unmap(nouveau_fb->nvbo);
 		nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
+		nouveau_bo_unmap(nouveau_fb->nvbo);
 		nouveau_bo_unpin(nouveau_fb->nvbo);
-		drm_gem_object_unreference_unlocked(&nouveau_fb->nvbo->gem);
-		nouveau_fb->nvbo = NULL;
+		drm_framebuffer_unreference(&nouveau_fb->base);
 	}
-	drm_fb_helper_fini(&fbcon->helper);
-	drm_framebuffer_unregister_private(&nouveau_fb->base);
-	drm_framebuffer_cleanup(&nouveau_fb->base);
+
 	return 0;
 }
 
 void nouveau_fbcon_gpu_lockup(struct fb_info *info)
 {
 	struct nouveau_fbdev *fbcon = info->par;
-	struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
+	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 
 	NV_ERROR(drm, "GPU lockup - switching to software fbcon\n");
 	info->flags |= FBINFO_HWACCEL_DISABLED;
@@ -491,19 +470,43 @@ static const struct drm_fb_helper_funcs
 	.fb_probe = nouveau_fbcon_create,
 };
 
+static void
+nouveau_fbcon_set_suspend_work(struct work_struct *work)
+{
+	struct nouveau_drm *drm = container_of(work, typeof(*drm), fbcon_work);
+	int state = READ_ONCE(drm->fbcon_new_state);
+
+	if (state == FBINFO_STATE_RUNNING)
+		pm_runtime_get_sync(drm->dev->dev);
+
+	console_lock();
+	if (state == FBINFO_STATE_RUNNING)
+		nouveau_fbcon_accel_restore(drm->dev);
+	drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
+	if (state != FBINFO_STATE_RUNNING)
+		nouveau_fbcon_accel_save_disable(drm->dev);
+	console_unlock();
+
+	if (state == FBINFO_STATE_RUNNING) {
+		pm_runtime_mark_last_busy(drm->dev->dev);
+		pm_runtime_put_sync(drm->dev->dev);
+	}
+}
+
 void
 nouveau_fbcon_set_suspend(struct drm_device *dev, int state)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
-	if (drm->fbcon) {
-		console_lock();
-		if (state == FBINFO_STATE_RUNNING)
-			nouveau_fbcon_accel_restore(dev);
-		drm_fb_helper_set_suspend(&drm->fbcon->helper, state);
-		if (state != FBINFO_STATE_RUNNING)
-			nouveau_fbcon_accel_save_disable(dev);
-		console_unlock();
-	}
+
+	if (!drm->fbcon)
+		return;
+
+	drm->fbcon_new_state = state;
+	/* Since runtime resume can happen as a result of a sysfs operation,
+	 * it's possible we already have the console locked. So handle fbcon
+	 * init/deinit from a seperate work thread
+	 */
+	schedule_work(&drm->fbcon_work);
 }
 
 int
@@ -522,8 +525,8 @@ nouveau_fbcon_init(struct drm_device *de
 	if (!fbcon)
 		return -ENOMEM;
 
-	fbcon->dev = dev;
 	drm->fbcon = fbcon;
+	INIT_WORK(&drm->fbcon_work, nouveau_fbcon_set_suspend_work);
 
 	drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
 
@@ -545,7 +548,8 @@ nouveau_fbcon_init(struct drm_device *de
 		preferred_bpp = 32;
 
 	/* disable all the possible outputs/crtcs before entering KMS mode */
-	drm_helper_disable_unused_functions(dev);
+	if (!dev->mode_config.funcs->atomic_commit)
+		drm_helper_disable_unused_functions(dev);
 
 	ret = drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,8 +33,6 @@
 
 struct nouveau_fbdev {
 	struct drm_fb_helper helper;
-	struct nouveau_framebuffer nouveau_fb;
-	struct drm_device *dev;
 	unsigned int saved_flags;
 	struct nvif_object surf2d;
 	struct nvif_object clip;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 
 #include <linux/ktime.h>
 #include <linux/hrtimer.h>
-#include <trace/events/fence.h>
+#include <trace/events/dma_fence.h>
 
 #include <nvif/cl826e.h>
 #include <nvif/notify.h>
@@ -38,11 +38,11 @@
 #include "nouveau_dma.h"
 #include "nouveau_fence.h"
 
-static const struct fence_ops nouveau_fence_ops_uevent;
-static const struct fence_ops nouveau_fence_ops_legacy;
+static const struct dma_fence_ops nouveau_fence_ops_uevent;
+static const struct dma_fence_ops nouveau_fence_ops_legacy;
 
 static inline struct nouveau_fence *
-from_fence(struct fence *fence)
+from_fence(struct dma_fence *fence)
 {
 	return container_of(fence, struct nouveau_fence, base);
 }
@@ -58,23 +58,23 @@ nouveau_fence_signal(struct nouveau_fenc
 {
 	int drop = 0;
 
-	fence_signal_locked(&fence->base);
+	dma_fence_signal_locked(&fence->base);
 	list_del(&fence->head);
 	rcu_assign_pointer(fence->channel, NULL);
 
-	if (test_bit(FENCE_FLAG_USER_BITS, &fence->base.flags)) {
+	if (test_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags)) {
 		struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
 
 		if (!--fctx->notify_ref)
 			drop = 1;
 	}
 
-	fence_put(&fence->base);
+	dma_fence_put(&fence->base);
 	return drop;
 }
 
 static struct nouveau_fence *
-nouveau_local_fence(struct fence *fence, struct nouveau_drm *drm) {
+nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm) {
 	struct nouveau_fence_priv *priv = (void*)drm->fence;
 
 	if (fence->ops != &nouveau_fence_ops_legacy &&
@@ -201,7 +201,7 @@ nouveau_fence_context_new(struct nouveau
 
 struct nouveau_fence_work {
 	struct work_struct work;
-	struct fence_cb cb;
+	struct dma_fence_cb cb;
 	void (*func)(void *);
 	void *data;
 };
@@ -214,7 +214,7 @@ nouveau_fence_work_handler(struct work_s
 	kfree(work);
 }
 
-static void nouveau_fence_work_cb(struct fence *fence, struct fence_cb *cb)
+static void nouveau_fence_work_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
 {
 	struct nouveau_fence_work *work = container_of(cb, typeof(*work), cb);
 
@@ -222,12 +222,12 @@ static void nouveau_fence_work_cb(struct
 }
 
 void
-nouveau_fence_work(struct fence *fence,
+nouveau_fence_work(struct dma_fence *fence,
 		   void (*func)(void *), void *data)
 {
 	struct nouveau_fence_work *work;
 
-	if (fence_is_signaled(fence))
+	if (dma_fence_is_signaled(fence))
 		goto err;
 
 	work = kmalloc(sizeof(*work), GFP_KERNEL);
@@ -245,7 +245,7 @@ nouveau_fence_work(struct fence *fence,
 	work->func = func;
 	work->data = data;
 
-	if (fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0)
+	if (dma_fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0)
 		goto err_free;
 	return;
 
@@ -266,17 +266,17 @@ nouveau_fence_emit(struct nouveau_fence
 	fence->timeout  = jiffies + (15 * HZ);
 
 	if (priv->uevent)
-		fence_init(&fence->base, &nouveau_fence_ops_uevent,
-			   &fctx->lock, fctx->context, ++fctx->sequence);
+		dma_fence_init(&fence->base, &nouveau_fence_ops_uevent,
+			       &fctx->lock, fctx->context, ++fctx->sequence);
 	else
-		fence_init(&fence->base, &nouveau_fence_ops_legacy,
-			   &fctx->lock, fctx->context, ++fctx->sequence);
+		dma_fence_init(&fence->base, &nouveau_fence_ops_legacy,
+			       &fctx->lock, fctx->context, ++fctx->sequence);
 	kref_get(&fctx->fence_ref);
 
-	trace_fence_emit(&fence->base);
+	trace_dma_fence_emit(&fence->base);
 	ret = fctx->emit(fence);
 	if (!ret) {
-		fence_get(&fence->base);
+		dma_fence_get(&fence->base);
 		spin_lock_irq(&fctx->lock);
 
 		if (nouveau_fence_update(chan, fctx))
@@ -298,7 +298,7 @@ nouveau_fence_done(struct nouveau_fence
 		struct nouveau_channel *chan;
 		unsigned long flags;
 
-		if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
+		if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
 			return true;
 
 		spin_lock_irqsave(&fctx->lock, flags);
@@ -307,11 +307,11 @@ nouveau_fence_done(struct nouveau_fence
 			nvif_notify_put(&fctx->notify);
 		spin_unlock_irqrestore(&fctx->lock, flags);
 	}
-	return fence_is_signaled(&fence->base);
+	return dma_fence_is_signaled(&fence->base);
 }
 
 static long
-nouveau_fence_wait_legacy(struct fence *f, bool intr, long wait)
+nouveau_fence_wait_legacy(struct dma_fence *f, bool intr, long wait)
 {
 	struct nouveau_fence *fence = from_fence(f);
 	unsigned long sleep_time = NSEC_PER_MSEC / 1000;
@@ -330,7 +330,7 @@ nouveau_fence_wait_legacy(struct fence *
 		__set_current_state(intr ? TASK_INTERRUPTIBLE :
 					   TASK_UNINTERRUPTIBLE);
 
-		kt = ktime_set(0, sleep_time);
+		kt = sleep_time;
 		schedule_hrtimeout(&kt, HRTIMER_MODE_REL);
 		sleep_time *= 2;
 		if (sleep_time > NSEC_PER_MSEC)
@@ -378,7 +378,7 @@ nouveau_fence_wait(struct nouveau_fence
 	if (!lazy)
 		return nouveau_fence_wait_busy(fence, intr);
 
-	ret = fence_wait_timeout(&fence->base, intr, 15 * HZ);
+	ret = dma_fence_wait_timeout(&fence->base, intr, 15 * HZ);
 	if (ret < 0)
 		return ret;
 	else if (!ret)
@@ -391,7 +391,7 @@ int
 nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool exclusive, bool intr)
 {
 	struct nouveau_fence_chan *fctx = chan->fence;
-	struct fence *fence;
+	struct dma_fence *fence;
 	struct reservation_object *resv = nvbo->bo.resv;
 	struct reservation_object_list *fobj;
 	struct nouveau_fence *f;
@@ -421,7 +421,7 @@ nouveau_fence_sync(struct nouveau_bo *nv
 		}
 
 		if (must_wait)
-			ret = fence_wait(fence, intr);
+			ret = dma_fence_wait(fence, intr);
 
 		return ret;
 	}
@@ -446,7 +446,7 @@ nouveau_fence_sync(struct nouveau_bo *nv
 		}
 
 		if (must_wait)
-			ret = fence_wait(fence, intr);
+			ret = dma_fence_wait(fence, intr);
 	}
 
 	return ret;
@@ -456,7 +456,7 @@ void
 nouveau_fence_unref(struct nouveau_fence **pfence)
 {
 	if (*pfence)
-		fence_put(&(*pfence)->base);
+		dma_fence_put(&(*pfence)->base);
 	*pfence = NULL;
 }
 
@@ -484,12 +484,12 @@ nouveau_fence_new(struct nouveau_channel
 	return ret;
 }
 
-static const char *nouveau_fence_get_get_driver_name(struct fence *fence)
+static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence)
 {
 	return "nouveau";
 }
 
-static const char *nouveau_fence_get_timeline_name(struct fence *f)
+static const char *nouveau_fence_get_timeline_name(struct dma_fence *f)
 {
 	struct nouveau_fence *fence = from_fence(f);
 	struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
@@ -503,7 +503,7 @@ static const char *nouveau_fence_get_tim
  * result. The drm node should still be there, so we can derive the index from
  * the fence context.
  */
-static bool nouveau_fence_is_signaled(struct fence *f)
+static bool nouveau_fence_is_signaled(struct dma_fence *f)
 {
 	struct nouveau_fence *fence = from_fence(f);
 	struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
@@ -519,7 +519,7 @@ static bool nouveau_fence_is_signaled(st
 	return ret;
 }
 
-static bool nouveau_fence_no_signaling(struct fence *f)
+static bool nouveau_fence_no_signaling(struct dma_fence *f)
 {
 	struct nouveau_fence *fence = from_fence(f);
 
@@ -530,30 +530,30 @@ static bool nouveau_fence_no_signaling(s
 	WARN_ON(atomic_read(&fence->base.refcount.refcount) <= 1);
 
 	/*
-	 * This needs uevents to work correctly, but fence_add_callback relies on
+	 * This needs uevents to work correctly, but dma_fence_add_callback relies on
 	 * being able to enable signaling. It will still get signaled eventually,
 	 * just not right away.
 	 */
 	if (nouveau_fence_is_signaled(f)) {
 		list_del(&fence->head);
 
-		fence_put(&fence->base);
+		dma_fence_put(&fence->base);
 		return false;
 	}
 
 	return true;
 }
 
-static void nouveau_fence_release(struct fence *f)
+static void nouveau_fence_release(struct dma_fence *f)
 {
 	struct nouveau_fence *fence = from_fence(f);
 	struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
 
 	kref_put(&fctx->fence_ref, nouveau_fence_context_put);
-	fence_free(&fence->base);
+	dma_fence_free(&fence->base);
 }
 
-static const struct fence_ops nouveau_fence_ops_legacy = {
+static const struct dma_fence_ops nouveau_fence_ops_legacy = {
 	.get_driver_name = nouveau_fence_get_get_driver_name,
 	.get_timeline_name = nouveau_fence_get_timeline_name,
 	.enable_signaling = nouveau_fence_no_signaling,
@@ -562,7 +562,7 @@ static const struct fence_ops nouveau_fe
 	.release = nouveau_fence_release
 };
 
-static bool nouveau_fence_enable_signaling(struct fence *f)
+static bool nouveau_fence_enable_signaling(struct dma_fence *f)
 {
 	struct nouveau_fence *fence = from_fence(f);
 	struct nouveau_fence_chan *fctx = nouveau_fctx(fence);
@@ -573,18 +573,18 @@ static bool nouveau_fence_enable_signali
 
 	ret = nouveau_fence_no_signaling(f);
 	if (ret)
-		set_bit(FENCE_FLAG_USER_BITS, &fence->base.flags);
+		set_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags);
 	else if (!--fctx->notify_ref)
 		nvif_notify_put(&fctx->notify);
 
 	return ret;
 }
 
-static const struct fence_ops nouveau_fence_ops_uevent = {
+static const struct dma_fence_ops nouveau_fence_ops_uevent = {
 	.get_driver_name = nouveau_fence_get_get_driver_name,
 	.get_timeline_name = nouveau_fence_get_timeline_name,
 	.enable_signaling = nouveau_fence_enable_signaling,
 	.signaled = nouveau_fence_is_signaled,
-	.wait = fence_default_wait,
-	.release = NULL
+	.wait = dma_fence_default_wait,
+	.release = nouveau_fence_release
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fence.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fence.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_fence.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_fence.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,14 +1,14 @@
 #ifndef __NOUVEAU_FENCE_H__
 #define __NOUVEAU_FENCE_H__
 
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 #include <nvif/notify.h>
 
 struct nouveau_drm;
 struct nouveau_bo;
 
 struct nouveau_fence {
-	struct fence base;
+	struct dma_fence base;
 
 	struct list_head head;
 
@@ -24,7 +24,7 @@ void nouveau_fence_unref(struct nouveau_
 
 int  nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *);
 bool nouveau_fence_done(struct nouveau_fence *);
-void nouveau_fence_work(struct fence *, void (*)(void *), void *);
+void nouveau_fence_work(struct dma_fence *, void (*)(void *), void *);
 int  nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
 int  nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr);
 
@@ -92,7 +92,6 @@ struct nv84_fence_chan {
 	struct nouveau_fence_chan base;
 	struct nvkm_vma vma;
 	struct nvkm_vma vma_gart;
-	struct nvkm_vma dispc_vma[4];
 };
 
 struct nv84_fence_priv {
@@ -100,9 +99,9 @@ struct nv84_fence_priv {
 	struct nouveau_bo *bo;
 	struct nouveau_bo *bo_gart;
 	u32 *suspend;
+	struct mutex mutex;
 };
 
-u64  nv84_fence_crtc(struct nouveau_channel *, int);
 int  nv84_fence_context_new(struct nouveau_channel *);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -119,7 +119,7 @@ nouveau_gem_object_unmap(struct nouveau_
 	const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM;
 	struct reservation_object *resv = nvbo->bo.resv;
 	struct reservation_object_list *fobj;
-	struct fence *fence = NULL;
+	struct dma_fence *fence = NULL;
 
 	fobj = reservation_object_get_list(resv);
 
@@ -369,7 +369,7 @@ validate_init(struct nouveau_channel *ch
 {
 	struct nouveau_cli *cli = nouveau_cli(file_priv);
 	int trycnt = 0;
-	int ret, i;
+	int ret = -EINVAL, i;
 	struct nouveau_bo *res_bo = NULL;
 	LIST_HEAD(gart_list);
 	LIST_HEAD(vram_list);
@@ -861,6 +861,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_de
 	struct nouveau_bo *nvbo;
 	bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
 	bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE);
+	long lret;
 	int ret;
 
 	gem = drm_gem_object_lookup(file_priv, req->handle);
@@ -868,19 +869,15 @@ nouveau_gem_ioctl_cpu_prep(struct drm_de
 		return -ENOENT;
 	nvbo = nouveau_gem_object(gem);
 
-	if (no_wait)
-		ret = reservation_object_test_signaled_rcu(nvbo->bo.resv, write) ? 0 : -EBUSY;
-	else {
-		long lret;
+	lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true,
+						   no_wait ? 0 : 30 * HZ);
+	if (!lret)
+		ret = -EBUSY;
+	else if (lret > 0)
+		ret = 0;
+	else
+		ret = lret;
 
-		lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, 30 * HZ);
-		if (!lret)
-			ret = -EBUSY;
-		else if (lret > 0)
-			ret = 0;
-		else
-			ret = lret;
-	}
 	nouveau_bo_sync_for_cpu(nvbo);
 	drm_gem_object_unreference_unlocked(gem);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_led.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_led.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_led.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_led.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 Martin Peres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Authors:
+ *  Martin Peres <martin.peres@free.fr>
+ */
+
+#include <linux/leds.h>
+
+#include "nouveau_led.h"
+#include <nvkm/subdev/gpio.h>
+
+static enum led_brightness
+nouveau_led_get_brightness(struct led_classdev *led)
+{
+	struct drm_device *drm_dev = container_of(led, struct nouveau_led, led)->dev;
+	struct nouveau_drm *drm = nouveau_drm(drm_dev);
+	struct nvif_object *device = &drm->device.object;
+	u32 div, duty;
+
+	div =  nvif_rd32(device, 0x61c880) & 0x00ffffff;
+	duty = nvif_rd32(device, 0x61c884) & 0x00ffffff;
+
+	if (div > 0)
+		return duty * LED_FULL / div;
+	else
+		return 0;
+}
+
+static void
+nouveau_led_set_brightness(struct led_classdev *led, enum led_brightness value)
+{
+	struct drm_device *drm_dev = container_of(led, struct nouveau_led, led)->dev;
+	struct nouveau_drm *drm = nouveau_drm(drm_dev);
+	struct nvif_object *device = &drm->device.object;
+
+	u32 input_clk = 27e6; /* PDISPLAY.SOR[1].PWM is connected to the crystal */
+	u32 freq = 100; /* this is what nvidia uses and it should be good-enough */
+	u32 div, duty;
+
+	div = input_clk / freq;
+	duty = value * div / LED_FULL;
+
+	/* for now, this is safe to directly poke those registers because:
+	 *  - A: nvidia never puts the logo led to any other PWM controler
+	 *       than PDISPLAY.SOR[1].PWM.
+	 *  - B: nouveau does not touch these registers anywhere else
+	 */
+	nvif_wr32(device, 0x61c880, div);
+	nvif_wr32(device, 0x61c884, 0xc0000000 | duty);
+}
+
+
+int
+nouveau_led_init(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nvkm_gpio *gpio = nvxx_gpio(&drm->device);
+	struct dcb_gpio_func logo_led;
+	int ret;
+
+	if (!gpio)
+		return 0;
+
+	/* check that there is a GPIO controlling the logo LED */
+	if (nvkm_gpio_find(gpio, 0, DCB_GPIO_LOGO_LED_PWM, 0xff, &logo_led))
+		return 0;
+
+	drm->led = kzalloc(sizeof(*drm->led), GFP_KERNEL);
+	if (!drm->led)
+		return -ENOMEM;
+	drm->led->dev = dev;
+
+	drm->led->led.name = "nvidia-logo";
+	drm->led->led.max_brightness = 255;
+	drm->led->led.brightness_get = nouveau_led_get_brightness;
+	drm->led->led.brightness_set = nouveau_led_set_brightness;
+
+	ret = led_classdev_register(dev->dev, &drm->led->led);
+	if (ret) {
+		kfree(drm->led);
+		return ret;
+	}
+
+	return 0;
+}
+
+void
+nouveau_led_suspend(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+
+	if (drm->led)
+		led_classdev_suspend(&drm->led->led);
+}
+
+void
+nouveau_led_resume(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+
+	if (drm->led)
+		led_classdev_resume(&drm->led->led);
+}
+
+void
+nouveau_led_fini(struct drm_device *dev)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+
+	if (drm->led) {
+		led_classdev_unregister(&drm->led->led);
+		kfree(drm->led);
+		drm->led = NULL;
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_led.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_led.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_led.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_led.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Martin Peres
+ *
+ * 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: Martin Peres <martin.peres@free.fr>
+ */
+
+#ifndef __NOUVEAU_LED_H__
+#define __NOUVEAU_LED_H__
+
+#include "nouveau_drv.h"
+
+struct led_classdev;
+
+struct nouveau_led {
+	struct drm_device *dev;
+
+	struct led_classdev led;
+};
+
+static inline struct nouveau_led *
+nouveau_led(struct drm_device *dev)
+{
+	return nouveau_drm(dev)->led;
+}
+
+/* nouveau_led.c */
+#if IS_REACHABLE(CONFIG_LEDS_CLASS)
+int  nouveau_led_init(struct drm_device *dev);
+void nouveau_led_suspend(struct drm_device *dev);
+void nouveau_led_resume(struct drm_device *dev);
+void nouveau_led_fini(struct drm_device *dev);
+#else
+static inline int  nouveau_led_init(struct drm_device *dev) { return 0; };
+static inline void nouveau_led_suspend(struct drm_device *dev) { };
+static inline void nouveau_led_resume(struct drm_device *dev) { };
+static inline void nouveau_led_fini(struct drm_device *dev) { };
+#endif
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nouveau_usif.c	2017-02-12 16:03:20.000000000 -0500
@@ -313,7 +313,8 @@ usif_ioctl(struct drm_file *filp, void _
 	if (!(ret = nvif_unpack(-ENOSYS, &data, &size, argv->v0, 0, 0, true))) {
 		/* block access to objects not created via this interface */
 		owner = argv->v0.owner;
-		if (argv->v0.object == 0ULL)
+		if (argv->v0.object == 0ULL &&
+		    argv->v0.type != NVIF_IOCTL_V0_DEL)
 			argv->v0.owner = NVDRM_OBJECT_ANY; /* except client */
 		else
 			argv->v0.owner = NVDRM_OBJECT_USIF;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv04_fbcon.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@ int
 nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret;
 
@@ -50,7 +50,7 @@ int
 nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret;
 
@@ -77,7 +77,7 @@ int
 nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	uint32_t fg;
 	uint32_t bg;
@@ -133,7 +133,7 @@ int
 nv04_fbcon_accel_init(struct fb_info *info)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct drm_device *dev = nfbdev->dev;
+	struct drm_device *dev = nfbdev->helper.dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_channel *chan = drm->channel;
 	struct nvif_device *device = &drm->device;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv04_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv04_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv04_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv04_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,6 +110,6 @@ nv04_fence_create(struct nouveau_drm *dr
 	priv->base.context_new = nv04_fence_context_new;
 	priv->base.context_del = nv04_fence_context_del;
 	priv->base.contexts = 15;
-	priv->base.context_base = fence_context_alloc(priv->base.contexts);
+	priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv10_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv10_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv10_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv10_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,16 +57,13 @@ void
 nv10_fence_context_del(struct nouveau_channel *chan)
 {
 	struct nv10_fence_chan *fctx = chan->fence;
-	int i;
 	nouveau_fence_context_del(&fctx->base);
-	for (i = 0; i < ARRAY_SIZE(fctx->head); i++)
-		nvif_object_fini(&fctx->head[i]);
 	nvif_object_fini(&fctx->sema);
 	chan->fence = NULL;
 	nouveau_fence_context_free(&fctx->base);
 }
 
-int
+static int
 nv10_fence_context_new(struct nouveau_channel *chan)
 {
 	struct nv10_fence_chan *fctx;
@@ -107,7 +104,7 @@ nv10_fence_create(struct nouveau_drm *dr
 	priv->base.context_new = nv10_fence_context_new;
 	priv->base.context_del = nv10_fence_context_del;
 	priv->base.contexts = 31;
-	priv->base.context_base = fence_context_alloc(priv->base.contexts);
+	priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
 	spin_lock_init(&priv->lock);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv10_fence.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv10_fence.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv10_fence.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv10_fence.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,6 @@
 struct nv10_fence_chan {
 	struct nouveau_fence_chan base;
 	struct nvif_object sema;
-	struct nvif_object head[4];
 };
 
 struct nv10_fence_priv {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv17_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv17_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv17_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv17_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -126,7 +126,7 @@ nv17_fence_create(struct nouveau_drm *dr
 	priv->base.context_new = nv17_fence_context_new;
 	priv->base.context_del = nv10_fence_context_del;
 	priv->base.contexts = 31;
-	priv->base.context_base = fence_context_alloc(priv->base.contexts);
+	priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
 	spin_lock_init(&priv->lock);
 
 	ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,10 +25,12 @@
 #include <linux/dma-mapping.h>
 
 #include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc_helper.h>
-#include <drm/drm_plane_helper.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_plane_helper.h>
 
 #include <nvif/class.h>
 #include <nvif/cl0002.h>
@@ -38,6 +40,7 @@
 #include <nvif/cl507c.h>
 #include <nvif/cl507d.h>
 #include <nvif/cl507e.h>
+#include <nvif/event.h>
 
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
@@ -46,6 +49,7 @@
 #include "nouveau_encoder.h"
 #include "nouveau_crtc.h"
 #include "nouveau_fence.h"
+#include "nouveau_fbcon.h"
 #include "nv50_display.h"
 
 #define EVO_DMA_NR 9
@@ -61,6 +65,227 @@
 #define EVO_MAST_NTFY     EVO_SYNC(      0, 0x00)
 #define EVO_FLIP_SEM0(c)  EVO_SYNC((c) + 1, 0x00)
 #define EVO_FLIP_SEM1(c)  EVO_SYNC((c) + 1, 0x10)
+#define EVO_FLIP_NTFY0(c) EVO_SYNC((c) + 1, 0x20)
+#define EVO_FLIP_NTFY1(c) EVO_SYNC((c) + 1, 0x30)
+
+/******************************************************************************
+ * Atomic state
+ *****************************************************************************/
+#define nv50_atom(p) container_of((p), struct nv50_atom, state)
+
+struct nv50_atom {
+	struct drm_atomic_state state;
+
+	struct list_head outp;
+	bool lock_core;
+	bool flush_disable;
+};
+
+struct nv50_outp_atom {
+	struct list_head head;
+
+	struct drm_encoder *encoder;
+	bool flush_disable;
+
+	union {
+		struct {
+			bool ctrl:1;
+		};
+		u8 mask;
+	} clr;
+
+	union {
+		struct {
+			bool ctrl:1;
+		};
+		u8 mask;
+	} set;
+};
+
+#define nv50_head_atom(p) container_of((p), struct nv50_head_atom, state)
+
+struct nv50_head_atom {
+	struct drm_crtc_state state;
+
+	struct {
+		u16 iW;
+		u16 iH;
+		u16 oW;
+		u16 oH;
+	} view;
+
+	struct nv50_head_mode {
+		bool interlace;
+		u32 clock;
+		struct {
+			u16 active;
+			u16 synce;
+			u16 blanke;
+			u16 blanks;
+		} h;
+		struct {
+			u32 active;
+			u16 synce;
+			u16 blanke;
+			u16 blanks;
+			u16 blank2s;
+			u16 blank2e;
+			u16 blankus;
+		} v;
+	} mode;
+
+	struct {
+		u32 handle;
+		u64 offset:40;
+	} lut;
+
+	struct {
+		bool visible;
+		u32 handle;
+		u64 offset:40;
+		u8  format;
+		u8  kind:7;
+		u8  layout:1;
+		u8  block:4;
+		u32 pitch:20;
+		u16 x;
+		u16 y;
+		u16 w;
+		u16 h;
+	} core;
+
+	struct {
+		bool visible;
+		u32 handle;
+		u64 offset:40;
+		u8  layout:1;
+		u8  format:1;
+	} curs;
+
+	struct {
+		u8  depth;
+		u8  cpp;
+		u16 x;
+		u16 y;
+		u16 w;
+		u16 h;
+	} base;
+
+	struct {
+		u8 cpp;
+	} ovly;
+
+	struct {
+		bool enable:1;
+		u8 bits:2;
+		u8 mode:4;
+	} dither;
+
+	struct {
+		struct {
+			u16 cos:12;
+			u16 sin:12;
+		} sat;
+	} procamp;
+
+	union {
+		struct {
+			bool core:1;
+			bool curs:1;
+		};
+		u8 mask;
+	} clr;
+
+	union {
+		struct {
+			bool core:1;
+			bool curs:1;
+			bool view:1;
+			bool mode:1;
+			bool base:1;
+			bool ovly:1;
+			bool dither:1;
+			bool procamp:1;
+		};
+		u16 mask;
+	} set;
+};
+
+static inline struct nv50_head_atom *
+nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc)
+{
+	struct drm_crtc_state *statec = drm_atomic_get_crtc_state(state, crtc);
+	if (IS_ERR(statec))
+		return (void *)statec;
+	return nv50_head_atom(statec);
+}
+
+#define nv50_wndw_atom(p) container_of((p), struct nv50_wndw_atom, state)
+
+struct nv50_wndw_atom {
+	struct drm_plane_state state;
+	u8 interval;
+
+	struct drm_rect clip;
+
+	struct {
+		u32  handle;
+		u16  offset:12;
+		bool awaken:1;
+	} ntfy;
+
+	struct {
+		u32 handle;
+		u16 offset:12;
+		u32 acquire;
+		u32 release;
+	} sema;
+
+	struct {
+		u8 enable:2;
+	} lut;
+
+	struct {
+		u8  mode:2;
+		u8  interval:4;
+
+		u8  format;
+		u8  kind:7;
+		u8  layout:1;
+		u8  block:4;
+		u32 pitch:20;
+		u16 w;
+		u16 h;
+
+		u32 handle;
+		u64 offset;
+	} image;
+
+	struct {
+		u16 x;
+		u16 y;
+	} point;
+
+	union {
+		struct {
+			bool ntfy:1;
+			bool sema:1;
+			bool image:1;
+		};
+		u8 mask;
+	} clr;
+
+	union {
+		struct {
+			bool ntfy:1;
+			bool sema:1;
+			bool image:1;
+			bool lut:1;
+			bool point:1;
+		};
+		u8 mask;
+	} set;
+};
 
 /******************************************************************************
  * EVO channel
@@ -133,34 +358,6 @@ nv50_pioc_create(struct nvif_device *dev
 }
 
 /******************************************************************************
- * Cursor Immediate
- *****************************************************************************/
-
-struct nv50_curs {
-	struct nv50_pioc base;
-};
-
-static int
-nv50_curs_create(struct nvif_device *device, struct nvif_object *disp,
-		 int head, struct nv50_curs *curs)
-{
-	struct nv50_disp_cursor_v0 args = {
-		.head = head,
-	};
-	static const s32 oclass[] = {
-		GK104_DISP_CURSOR,
-		GF110_DISP_CURSOR,
-		GT214_DISP_CURSOR,
-		G82_DISP_CURSOR,
-		NV50_DISP_CURSOR,
-		0
-	};
-
-	return nv50_pioc_create(device, disp, oclass, head, &args, sizeof(args),
-				&curs->base);
-}
-
-/******************************************************************************
  * Overlay Immediate
  *****************************************************************************/
 
@@ -192,6 +389,11 @@ nv50_oimm_create(struct nvif_device *dev
  * DMA EVO channel
  *****************************************************************************/
 
+struct nv50_dmac_ctxdma {
+	struct list_head head;
+	struct nvif_object object;
+};
+
 struct nv50_dmac {
 	struct nv50_chan base;
 	dma_addr_t handle;
@@ -199,6 +401,7 @@ struct nv50_dmac {
 
 	struct nvif_object sync;
 	struct nvif_object vram;
+	struct list_head ctxdma;
 
 	/* Protects against concurrent pushbuf access to this channel, lock is
 	 * grabbed by evo_wait (if the pushbuf reservation is successful) and
@@ -207,9 +410,82 @@ struct nv50_dmac {
 };
 
 static void
+nv50_dmac_ctxdma_del(struct nv50_dmac_ctxdma *ctxdma)
+{
+	nvif_object_fini(&ctxdma->object);
+	list_del(&ctxdma->head);
+	kfree(ctxdma);
+}
+
+static struct nv50_dmac_ctxdma *
+nv50_dmac_ctxdma_new(struct nv50_dmac *dmac, struct nouveau_framebuffer *fb)
+{
+	struct nouveau_drm *drm = nouveau_drm(fb->base.dev);
+	struct nv50_dmac_ctxdma *ctxdma;
+	const u8    kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
+	const u32 handle = 0xfb000000 | kind;
+	struct {
+		struct nv_dma_v0 base;
+		union {
+			struct nv50_dma_v0 nv50;
+			struct gf100_dma_v0 gf100;
+			struct gf119_dma_v0 gf119;
+		};
+	} args = {};
+	u32 argc = sizeof(args.base);
+	int ret;
+
+	list_for_each_entry(ctxdma, &dmac->ctxdma, head) {
+		if (ctxdma->object.handle == handle)
+			return ctxdma;
+	}
+
+	if (!(ctxdma = kzalloc(sizeof(*ctxdma), GFP_KERNEL)))
+		return ERR_PTR(-ENOMEM);
+	list_add(&ctxdma->head, &dmac->ctxdma);
+
+	args.base.target = NV_DMA_V0_TARGET_VRAM;
+	args.base.access = NV_DMA_V0_ACCESS_RDWR;
+	args.base.start  = 0;
+	args.base.limit  = drm->device.info.ram_user - 1;
+
+	if (drm->device.info.chipset < 0x80) {
+		args.nv50.part = NV50_DMA_V0_PART_256;
+		argc += sizeof(args.nv50);
+	} else
+	if (drm->device.info.chipset < 0xc0) {
+		args.nv50.part = NV50_DMA_V0_PART_256;
+		args.nv50.kind = kind;
+		argc += sizeof(args.nv50);
+	} else
+	if (drm->device.info.chipset < 0xd0) {
+		args.gf100.kind = kind;
+		argc += sizeof(args.gf100);
+	} else {
+		args.gf119.page = GF119_DMA_V0_PAGE_LP;
+		args.gf119.kind = kind;
+		argc += sizeof(args.gf119);
+	}
+
+	ret = nvif_object_init(&dmac->base.user, handle, NV_DMA_IN_MEMORY,
+			       &args, argc, &ctxdma->object);
+	if (ret) {
+		nv50_dmac_ctxdma_del(ctxdma);
+		return ERR_PTR(ret);
+	}
+
+	return ctxdma;
+}
+
+static void
 nv50_dmac_destroy(struct nv50_dmac *dmac, struct nvif_object *disp)
 {
 	struct nvif_device *device = dmac->base.device;
+	struct nv50_dmac_ctxdma *ctxdma, *ctxtmp;
+
+	list_for_each_entry_safe(ctxdma, ctxtmp, &dmac->ctxdma, head) {
+		nv50_dmac_ctxdma_del(ctxdma);
+	}
 
 	nvif_object_fini(&dmac->vram);
 	nvif_object_fini(&dmac->sync);
@@ -278,6 +554,7 @@ nv50_dmac_create(struct nvif_device *dev
 	if (ret)
 		return ret;
 
+	INIT_LIST_HEAD(&dmac->ctxdma);
 	return ret;
 }
 
@@ -297,7 +574,7 @@ nv50_core_create(struct nvif_device *dev
 		.pushbuf = 0xb0007d00,
 	};
 	static const s32 oclass[] = {
-		GP104_DISP_CORE_CHANNEL_DMA,
+		GP102_DISP_CORE_CHANNEL_DMA,
 		GP100_DISP_CORE_CHANNEL_DMA,
 		GM200_DISP_CORE_CHANNEL_DMA,
 		GM107_DISP_CORE_CHANNEL_DMA,
@@ -381,34 +658,23 @@ nv50_ovly_create(struct nvif_device *dev
 
 struct nv50_head {
 	struct nouveau_crtc base;
-	struct nouveau_bo *image;
-	struct nv50_curs curs;
-	struct nv50_sync sync;
 	struct nv50_ovly ovly;
 	struct nv50_oimm oimm;
 };
 
 #define nv50_head(c) ((struct nv50_head *)nouveau_crtc(c))
-#define nv50_curs(c) (&nv50_head(c)->curs)
-#define nv50_sync(c) (&nv50_head(c)->sync)
 #define nv50_ovly(c) (&nv50_head(c)->ovly)
 #define nv50_oimm(c) (&nv50_head(c)->oimm)
 #define nv50_chan(c) (&(c)->base.base)
 #define nv50_vers(c) nv50_chan(c)->user.oclass
 
-struct nv50_fbdma {
-	struct list_head head;
-	struct nvif_object core;
-	struct nvif_object base[4];
-};
-
 struct nv50_disp {
 	struct nvif_object *disp;
 	struct nv50_mast mast;
 
-	struct list_head fbdma;
-
 	struct nouveau_bo *sync;
+
+	struct mutex mutex;
 };
 
 static struct nv50_disp *
@@ -419,12 +685,6 @@ nv50_disp(struct drm_device *dev)
 
 #define nv50_mast(d) (&nv50_disp(d)->mast)
 
-static struct drm_crtc *
-nv50_display_crtc_get(struct drm_encoder *encoder)
-{
-	return nouveau_encoder(encoder)->crtc;
-}
-
 /******************************************************************************
  * EVO channel helpers
  *****************************************************************************/
@@ -463,812 +723,1465 @@ evo_kick(u32 *push, void *evoc)
 	mutex_unlock(&dmac->lock);
 }
 
-#if 1
-#define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m))
-#define evo_data(p,d)   *((p)++) = (d)
-#else
 #define evo_mthd(p,m,s) do {                                                   \
 	const u32 _m = (m), _s = (s);                                          \
-	printk(KERN_ERR "%04x %d %s\n", _m, _s, __func__);                     \
+	if (drm_debug & DRM_UT_KMS)                                            \
+		printk(KERN_ERR "%04x %d %s\n", _m, _s, __func__);             \
 	*((p)++) = ((_s << 18) | _m);                                          \
 } while(0)
+
 #define evo_data(p,d) do {                                                     \
 	const u32 _d = (d);                                                    \
-	printk(KERN_ERR "\t%08x\n", _d);                                       \
+	if (drm_debug & DRM_UT_KMS)                                            \
+		printk(KERN_ERR "\t%08x\n", _d);                               \
 	*((p)++) = _d;                                                         \
 } while(0)
-#endif
 
-static bool
-evo_sync_wait(void *data)
+/******************************************************************************
+ * Plane
+ *****************************************************************************/
+#define nv50_wndw(p) container_of((p), struct nv50_wndw, plane)
+
+struct nv50_wndw {
+	const struct nv50_wndw_func *func;
+	struct nv50_dmac *dmac;
+
+	struct drm_plane plane;
+
+	struct nvif_notify notify;
+	u16 ntfy;
+	u16 sema;
+	u32 data;
+};
+
+struct nv50_wndw_func {
+	void *(*dtor)(struct nv50_wndw *);
+	int (*acquire)(struct nv50_wndw *, struct nv50_wndw_atom *asyw,
+		       struct nv50_head_atom *asyh);
+	void (*release)(struct nv50_wndw *, struct nv50_wndw_atom *asyw,
+			struct nv50_head_atom *asyh);
+	void (*prepare)(struct nv50_wndw *, struct nv50_head_atom *asyh,
+			struct nv50_wndw_atom *asyw);
+
+	void (*sema_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+	void (*sema_clr)(struct nv50_wndw *);
+	void (*ntfy_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+	void (*ntfy_clr)(struct nv50_wndw *);
+	int (*ntfy_wait_begun)(struct nv50_wndw *, struct nv50_wndw_atom *);
+	void (*image_set)(struct nv50_wndw *, struct nv50_wndw_atom *);
+	void (*image_clr)(struct nv50_wndw *);
+	void (*lut)(struct nv50_wndw *, struct nv50_wndw_atom *);
+	void (*point)(struct nv50_wndw *, struct nv50_wndw_atom *);
+
+	u32 (*update)(struct nv50_wndw *, u32 interlock);
+};
+
+static int
+nv50_wndw_wait_armed(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
-	if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000)
-		return true;
-	usleep_range(1, 2);
-	return false;
+	if (asyw->set.ntfy)
+		return wndw->func->ntfy_wait_begun(wndw, asyw);
+	return 0;
 }
 
-static int
-evo_sync(struct drm_device *dev)
+static u32
+nv50_wndw_flush_clr(struct nv50_wndw *wndw, u32 interlock, bool flush,
+		    struct nv50_wndw_atom *asyw)
 {
-	struct nvif_device *device = &nouveau_drm(dev)->device;
-	struct nv50_disp *disp = nv50_disp(dev);
-	struct nv50_mast *mast = nv50_mast(dev);
-	u32 *push = evo_wait(mast, 8);
-	if (push) {
-		nouveau_bo_wr32(disp->sync, EVO_MAST_NTFY, 0x00000000);
-		evo_mthd(push, 0x0084, 1);
-		evo_data(push, 0x80000000 | EVO_MAST_NTFY);
-		evo_mthd(push, 0x0080, 2);
-		evo_data(push, 0x00000000);
-		evo_data(push, 0x00000000);
-		evo_kick(push, mast);
-		if (nvif_msec(device, 2000,
-			if (evo_sync_wait(disp->sync))
-				break;
-		) >= 0)
-			return 0;
-	}
+	if (asyw->clr.sema && (!asyw->set.sema || flush))
+		wndw->func->sema_clr(wndw);
+	if (asyw->clr.ntfy && (!asyw->set.ntfy || flush))
+		wndw->func->ntfy_clr(wndw);
+	if (asyw->clr.image && (!asyw->set.image || flush))
+		wndw->func->image_clr(wndw);
 
-	return -EBUSY;
+	return flush ? wndw->func->update(wndw, interlock) : 0;
 }
 
-/******************************************************************************
- * Page flipping channel
- *****************************************************************************/
-struct nouveau_bo *
-nv50_display_crtc_sema(struct drm_device *dev, int crtc)
+static u32
+nv50_wndw_flush_set(struct nv50_wndw *wndw, u32 interlock,
+		    struct nv50_wndw_atom *asyw)
 {
-	return nv50_disp(dev)->sync;
-}
+	if (interlock) {
+		asyw->image.mode = 0;
+		asyw->image.interval = 1;
+	}
 
-struct nv50_display_flip {
-	struct nv50_disp *disp;
-	struct nv50_sync *chan;
-};
+	if (asyw->set.sema ) wndw->func->sema_set (wndw, asyw);
+	if (asyw->set.ntfy ) wndw->func->ntfy_set (wndw, asyw);
+	if (asyw->set.image) wndw->func->image_set(wndw, asyw);
+	if (asyw->set.lut  ) wndw->func->lut      (wndw, asyw);
+	if (asyw->set.point) wndw->func->point    (wndw, asyw);
 
-static bool
-nv50_display_flip_wait(void *data)
+	return wndw->func->update(wndw, interlock);
+}
+
+static void
+nv50_wndw_atomic_check_release(struct nv50_wndw *wndw,
+			       struct nv50_wndw_atom *asyw,
+			       struct nv50_head_atom *asyh)
 {
-	struct nv50_display_flip *flip = data;
-	if (nouveau_bo_rd32(flip->disp->sync, flip->chan->addr / 4) ==
-					      flip->chan->data)
-		return true;
-	usleep_range(1, 2);
-	return false;
+	struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
+	NV_ATOMIC(drm, "%s release\n", wndw->plane.name);
+	wndw->func->release(wndw, asyw, asyh);
+	asyw->ntfy.handle = 0;
+	asyw->sema.handle = 0;
 }
 
-void
-nv50_display_flip_stop(struct drm_crtc *crtc)
+static int
+nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
+			       struct nv50_wndw_atom *asyw,
+			       struct nv50_head_atom *asyh)
 {
-	struct nvif_device *device = &nouveau_drm(crtc->dev)->device;
-	struct nv50_display_flip flip = {
-		.disp = nv50_disp(crtc->dev),
-		.chan = nv50_sync(crtc),
-	};
-	u32 *push;
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb);
+	struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
+	int ret;
 
-	push = evo_wait(flip.chan, 8);
-	if (push) {
-		evo_mthd(push, 0x0084, 1);
-		evo_data(push, 0x00000000);
-		evo_mthd(push, 0x0094, 1);
-		evo_data(push, 0x00000000);
-		evo_mthd(push, 0x00c0, 1);
-		evo_data(push, 0x00000000);
-		evo_mthd(push, 0x0080, 1);
-		evo_data(push, 0x00000000);
-		evo_kick(push, flip.chan);
+	NV_ATOMIC(drm, "%s acquire\n", wndw->plane.name);
+	asyw->clip.x1 = 0;
+	asyw->clip.y1 = 0;
+	asyw->clip.x2 = asyh->state.mode.hdisplay;
+	asyw->clip.y2 = asyh->state.mode.vdisplay;
+
+	asyw->image.w = fb->base.width;
+	asyw->image.h = fb->base.height;
+	asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
+	if (asyw->image.kind) {
+		asyw->image.layout = 0;
+		if (drm->device.info.chipset >= 0xc0)
+			asyw->image.block = fb->nvbo->tile_mode >> 4;
+		else
+			asyw->image.block = fb->nvbo->tile_mode;
+		asyw->image.pitch = (fb->base.pitches[0] / 4) << 4;
+	} else {
+		asyw->image.layout = 1;
+		asyw->image.block  = 0;
+		asyw->image.pitch  = fb->base.pitches[0];
 	}
 
-	nvif_msec(device, 2000,
-		if (nv50_display_flip_wait(&flip))
-			break;
-	);
+	ret = wndw->func->acquire(wndw, asyw, asyh);
+	if (ret)
+		return ret;
+
+	if (asyw->set.image) {
+		if (!(asyw->image.mode = asyw->interval ? 0 : 1))
+			asyw->image.interval = asyw->interval;
+		else
+			asyw->image.interval = 0;
+	}
+
+	return 0;
 }
 
-int
-nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
-		       struct nouveau_channel *chan, u32 swap_interval)
+static int
+nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
 {
-	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct nv50_head *head = nv50_head(crtc);
-	struct nv50_sync *sync = nv50_sync(crtc);
-	u32 *push;
+	struct nouveau_drm *drm = nouveau_drm(plane->dev);
+	struct nv50_wndw *wndw = nv50_wndw(plane);
+	struct nv50_wndw_atom *armw = nv50_wndw_atom(wndw->plane.state);
+	struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);
+	struct nv50_head_atom *harm = NULL, *asyh = NULL;
+	bool varm = false, asyv = false, asym = false;
 	int ret;
 
-	if (crtc->primary->fb->width != fb->width ||
-	    crtc->primary->fb->height != fb->height)
-		return -EINVAL;
-
-	swap_interval <<= 4;
-	if (swap_interval == 0)
-		swap_interval |= 0x100;
-	if (chan == NULL)
-		evo_sync(crtc->dev);
-
-	push = evo_wait(sync, 128);
-	if (unlikely(push == NULL))
-		return -EBUSY;
+	NV_ATOMIC(drm, "%s atomic_check\n", plane->name);
+	if (asyw->state.crtc) {
+		asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
+		if (IS_ERR(asyh))
+			return PTR_ERR(asyh);
+		asym = drm_atomic_crtc_needs_modeset(&asyh->state);
+		asyv = asyh->state.active;
+	}
 
-	if (chan && chan->user.oclass < G82_CHANNEL_GPFIFO) {
-		ret = RING_SPACE(chan, 8);
-		if (ret)
-			return ret;
+	if (armw->state.crtc) {
+		harm = nv50_head_atom_get(asyw->state.state, armw->state.crtc);
+		if (IS_ERR(harm))
+			return PTR_ERR(harm);
+		varm = harm->state.crtc->state->active;
+	}
 
-		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2);
-		OUT_RING  (chan, NvEvoSema0 + nv_crtc->index);
-		OUT_RING  (chan, sync->addr ^ 0x10);
-		BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1);
-		OUT_RING  (chan, sync->data + 1);
-		BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_OFFSET, 2);
-		OUT_RING  (chan, sync->addr);
-		OUT_RING  (chan, sync->data);
-	} else
-	if (chan && chan->user.oclass < FERMI_CHANNEL_GPFIFO) {
-		u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
-		ret = RING_SPACE(chan, 12);
-		if (ret)
-			return ret;
+	if (asyv) {
+		asyw->point.x = asyw->state.crtc_x;
+		asyw->point.y = asyw->state.crtc_y;
+		if (memcmp(&armw->point, &asyw->point, sizeof(asyw->point)))
+			asyw->set.point = true;
 
-		BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1);
-		OUT_RING  (chan, chan->vram.handle);
-		BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-		OUT_RING  (chan, upper_32_bits(addr ^ 0x10));
-		OUT_RING  (chan, lower_32_bits(addr ^ 0x10));
-		OUT_RING  (chan, sync->data + 1);
-		OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
-		BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-		OUT_RING  (chan, upper_32_bits(addr));
-		OUT_RING  (chan, lower_32_bits(addr));
-		OUT_RING  (chan, sync->data);
-		OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL);
+		if (!varm || asym || armw->state.fb != asyw->state.fb) {
+			ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh);
+			if (ret)
+				return ret;
+		}
 	} else
-	if (chan) {
-		u64 addr = nv84_fence_crtc(chan, nv_crtc->index) + sync->addr;
-		ret = RING_SPACE(chan, 10);
-		if (ret)
-			return ret;
-
-		BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-		OUT_RING  (chan, upper_32_bits(addr ^ 0x10));
-		OUT_RING  (chan, lower_32_bits(addr ^ 0x10));
-		OUT_RING  (chan, sync->data + 1);
-		OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG |
-				 NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
-		BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4);
-		OUT_RING  (chan, upper_32_bits(addr));
-		OUT_RING  (chan, lower_32_bits(addr));
-		OUT_RING  (chan, sync->data);
-		OUT_RING  (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL |
-				 NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD);
+	if (varm) {
+		nv50_wndw_atomic_check_release(wndw, asyw, harm);
+	} else {
+		return 0;
 	}
 
-	if (chan) {
-		sync->addr ^= 0x10;
-		sync->data++;
-		FIRE_RING (chan);
+	if (!asyv || asym) {
+		asyw->clr.ntfy = armw->ntfy.handle != 0;
+		asyw->clr.sema = armw->sema.handle != 0;
+		if (wndw->func->image_clr)
+			asyw->clr.image = armw->image.handle != 0;
+		asyw->set.lut = wndw->func->lut && asyv;
 	}
 
-	/* queue the flip */
-	evo_mthd(push, 0x0100, 1);
-	evo_data(push, 0xfffe0000);
-	evo_mthd(push, 0x0084, 1);
-	evo_data(push, swap_interval);
-	if (!(swap_interval & 0x00000100)) {
-		evo_mthd(push, 0x00e0, 1);
-		evo_data(push, 0x40000000);
+	return 0;
+}
+
+static void
+nv50_wndw_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state)
+{
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(old_state->fb);
+	struct nouveau_drm *drm = nouveau_drm(plane->dev);
+
+	NV_ATOMIC(drm, "%s cleanup: %p\n", plane->name, old_state->fb);
+	if (!old_state->fb)
+		return;
+
+	nouveau_bo_unpin(fb->nvbo);
+}
+
+static int
+nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
+{
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(state->fb);
+	struct nouveau_drm *drm = nouveau_drm(plane->dev);
+	struct nv50_wndw *wndw = nv50_wndw(plane);
+	struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);
+	struct nv50_head_atom *asyh;
+	struct nv50_dmac_ctxdma *ctxdma;
+	int ret;
+
+	NV_ATOMIC(drm, "%s prepare: %p\n", plane->name, state->fb);
+	if (!asyw->state.fb)
+		return 0;
+
+	ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM, true);
+	if (ret)
+		return ret;
+
+	ctxdma = nv50_dmac_ctxdma_new(wndw->dmac, fb);
+	if (IS_ERR(ctxdma)) {
+		nouveau_bo_unpin(fb->nvbo);
+		return PTR_ERR(ctxdma);
 	}
-	evo_mthd(push, 0x0088, 4);
-	evo_data(push, sync->addr);
-	evo_data(push, sync->data++);
-	evo_data(push, sync->data);
-	evo_data(push, sync->base.sync.handle);
-	evo_mthd(push, 0x00a0, 2);
-	evo_data(push, 0x00000000);
-	evo_data(push, 0x00000000);
-	evo_mthd(push, 0x00c0, 1);
-	evo_data(push, nv_fb->r_handle);
-	evo_mthd(push, 0x0110, 2);
-	evo_data(push, 0x00000000);
-	evo_data(push, 0x00000000);
-	if (nv50_vers(sync) < GF110_DISP_BASE_CHANNEL_DMA) {
-		evo_mthd(push, 0x0800, 5);
-		evo_data(push, nv_fb->nvbo->bo.offset >> 8);
-		evo_data(push, 0);
-		evo_data(push, (fb->height << 16) | fb->width);
-		evo_data(push, nv_fb->r_pitch);
-		evo_data(push, nv_fb->r_format);
-	} else {
-		evo_mthd(push, 0x0400, 5);
-		evo_data(push, nv_fb->nvbo->bo.offset >> 8);
-		evo_data(push, 0);
-		evo_data(push, (fb->height << 16) | fb->width);
-		evo_data(push, nv_fb->r_pitch);
-		evo_data(push, nv_fb->r_format);
+
+	asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.resv);
+	asyw->image.handle = ctxdma->object.handle;
+	asyw->image.offset = fb->nvbo->bo.offset;
+
+	if (wndw->func->prepare) {
+		asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
+		if (IS_ERR(asyh))
+			return PTR_ERR(asyh);
+
+		wndw->func->prepare(wndw, asyh, asyw);
 	}
-	evo_mthd(push, 0x0080, 1);
-	evo_data(push, 0x00000000);
-	evo_kick(push, sync);
 
-	nouveau_bo_ref(nv_fb->nvbo, &head->image);
+	return 0;
+}
+
+static const struct drm_plane_helper_funcs
+nv50_wndw_helper = {
+	.prepare_fb = nv50_wndw_prepare_fb,
+	.cleanup_fb = nv50_wndw_cleanup_fb,
+	.atomic_check = nv50_wndw_atomic_check,
+};
+
+static void
+nv50_wndw_atomic_destroy_state(struct drm_plane *plane,
+			       struct drm_plane_state *state)
+{
+	struct nv50_wndw_atom *asyw = nv50_wndw_atom(state);
+	__drm_atomic_helper_plane_destroy_state(&asyw->state);
+	dma_fence_put(asyw->state.fence);
+	kfree(asyw);
+}
+
+static struct drm_plane_state *
+nv50_wndw_atomic_duplicate_state(struct drm_plane *plane)
+{
+	struct nv50_wndw_atom *armw = nv50_wndw_atom(plane->state);
+	struct nv50_wndw_atom *asyw;
+	if (!(asyw = kmalloc(sizeof(*asyw), GFP_KERNEL)))
+		return NULL;
+	__drm_atomic_helper_plane_duplicate_state(plane, &asyw->state);
+	asyw->state.fence = NULL;
+	asyw->interval = 1;
+	asyw->sema = armw->sema;
+	asyw->ntfy = armw->ntfy;
+	asyw->image = armw->image;
+	asyw->point = armw->point;
+	asyw->lut = armw->lut;
+	asyw->clr.mask = 0;
+	asyw->set.mask = 0;
+	return &asyw->state;
+}
+
+static void
+nv50_wndw_reset(struct drm_plane *plane)
+{
+	struct nv50_wndw_atom *asyw;
+
+	if (WARN_ON(!(asyw = kzalloc(sizeof(*asyw), GFP_KERNEL))))
+		return;
+
+	if (plane->state)
+		plane->funcs->atomic_destroy_state(plane, plane->state);
+	plane->state = &asyw->state;
+	plane->state->plane = plane;
+	plane->state->rotation = DRM_ROTATE_0;
+}
+
+static void
+nv50_wndw_destroy(struct drm_plane *plane)
+{
+	struct nv50_wndw *wndw = nv50_wndw(plane);
+	void *data;
+	nvif_notify_fini(&wndw->notify);
+	data = wndw->func->dtor(wndw);
+	drm_plane_cleanup(&wndw->plane);
+	kfree(data);
+}
+
+static const struct drm_plane_funcs
+nv50_wndw = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = nv50_wndw_destroy,
+	.reset = nv50_wndw_reset,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.atomic_duplicate_state = nv50_wndw_atomic_duplicate_state,
+	.atomic_destroy_state = nv50_wndw_atomic_destroy_state,
+};
+
+static void
+nv50_wndw_fini(struct nv50_wndw *wndw)
+{
+	nvif_notify_put(&wndw->notify);
+}
+
+static void
+nv50_wndw_init(struct nv50_wndw *wndw)
+{
+	nvif_notify_get(&wndw->notify);
+}
+
+static int
+nv50_wndw_ctor(const struct nv50_wndw_func *func, struct drm_device *dev,
+	       enum drm_plane_type type, const char *name, int index,
+	       struct nv50_dmac *dmac, const u32 *format, int nformat,
+	       struct nv50_wndw *wndw)
+{
+	int ret;
+
+	wndw->func = func;
+	wndw->dmac = dmac;
+
+	ret = drm_universal_plane_init(dev, &wndw->plane, 0, &nv50_wndw, format,
+				       nformat, type, "%s-%d", name, index);
+	if (ret)
+		return ret;
+
+	drm_plane_helper_add(&wndw->plane, &nv50_wndw_helper);
 	return 0;
 }
 
 /******************************************************************************
- * CRTC
+ * Cursor plane
  *****************************************************************************/
+#define nv50_curs(p) container_of((p), struct nv50_curs, wndw)
+
+struct nv50_curs {
+	struct nv50_wndw wndw;
+	struct nvif_object chan;
+};
+
+static u32
+nv50_curs_update(struct nv50_wndw *wndw, u32 interlock)
+{
+	struct nv50_curs *curs = nv50_curs(wndw);
+	nvif_wr32(&curs->chan, 0x0080, 0x00000000);
+	return 0;
+}
+
+static void
+nv50_curs_point(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+	struct nv50_curs *curs = nv50_curs(wndw);
+	nvif_wr32(&curs->chan, 0x0084, (asyw->point.y << 16) | asyw->point.x);
+}
+
+static void
+nv50_curs_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
+		  struct nv50_wndw_atom *asyw)
+{
+	asyh->curs.handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle;
+	asyh->curs.offset = asyw->image.offset;
+	asyh->set.curs = asyh->curs.visible;
+}
+
+static void
+nv50_curs_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+		  struct nv50_head_atom *asyh)
+{
+	asyh->curs.visible = false;
+}
+
 static int
-nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
+nv50_curs_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+		  struct nv50_head_atom *asyh)
 {
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-	struct nouveau_connector *nv_connector;
-	struct drm_connector *connector;
-	u32 *push, mode = 0x00;
+	int ret;
 
-	nv_connector = nouveau_crtc_connector_get(nv_crtc);
-	connector = &nv_connector->base;
-	if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
-		if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
-			mode = DITHERING_MODE_DYNAMIC2X2;
-	} else {
-		mode = nv_connector->dithering_mode;
-	}
+	ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip,
+					   DRM_PLANE_HELPER_NO_SCALING,
+					   DRM_PLANE_HELPER_NO_SCALING,
+					   true, true);
+	asyh->curs.visible = asyw->state.visible;
+	if (ret || !asyh->curs.visible)
+		return ret;
 
-	if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) {
-		if (connector->display_info.bpc >= 8)
-			mode |= DITHERING_DEPTH_8BPC;
-	} else {
-		mode |= nv_connector->dithering_depth;
+	switch (asyw->state.fb->width) {
+	case 32: asyh->curs.layout = 0; break;
+	case 64: asyh->curs.layout = 1; break;
+	default:
+		return -EINVAL;
 	}
 
-	push = evo_wait(mast, 4);
-	if (push) {
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x08a0 + (nv_crtc->index * 0x0400), 1);
-			evo_data(push, mode);
-		} else
-		if (nv50_vers(mast) < GK104_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0490 + (nv_crtc->index * 0x0300), 1);
-			evo_data(push, mode);
-		} else {
-			evo_mthd(push, 0x04a0 + (nv_crtc->index * 0x0300), 1);
-			evo_data(push, mode);
-		}
+	if (asyw->state.fb->width != asyw->state.fb->height)
+		return -EINVAL;
 
-		if (update) {
-			evo_mthd(push, 0x0080, 1);
-			evo_data(push, 0x00000000);
-		}
-		evo_kick(push, mast);
+	switch (asyw->state.fb->pixel_format) {
+	case DRM_FORMAT_ARGB8888: asyh->curs.format = 1; break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
 	}
 
 	return 0;
 }
 
+static void *
+nv50_curs_dtor(struct nv50_wndw *wndw)
+{
+	struct nv50_curs *curs = nv50_curs(wndw);
+	nvif_object_fini(&curs->chan);
+	return curs;
+}
+
+static const u32
+nv50_curs_format[] = {
+	DRM_FORMAT_ARGB8888,
+};
+
+static const struct nv50_wndw_func
+nv50_curs = {
+	.dtor = nv50_curs_dtor,
+	.acquire = nv50_curs_acquire,
+	.release = nv50_curs_release,
+	.prepare = nv50_curs_prepare,
+	.point = nv50_curs_point,
+	.update = nv50_curs_update,
+};
+
 static int
-nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update)
+nv50_curs_new(struct nouveau_drm *drm, struct nv50_head *head,
+	      struct nv50_curs **pcurs)
 {
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-	struct drm_display_mode *omode, *umode = &nv_crtc->base.mode;
-	struct drm_crtc *crtc = &nv_crtc->base;
-	struct nouveau_connector *nv_connector;
-	int mode = DRM_MODE_SCALE_NONE;
-	u32 oX, oY, *push;
+	static const struct nvif_mclass curses[] = {
+		{ GK104_DISP_CURSOR, 0 },
+		{ GF110_DISP_CURSOR, 0 },
+		{ GT214_DISP_CURSOR, 0 },
+		{   G82_DISP_CURSOR, 0 },
+		{  NV50_DISP_CURSOR, 0 },
+		{}
+	};
+	struct nv50_disp_cursor_v0 args = {
+		.head = head->base.index,
+	};
+	struct nv50_disp *disp = nv50_disp(drm->dev);
+	struct nv50_curs *curs;
+	int cid, ret;
 
-	/* start off at the resolution we programmed the crtc for, this
-	 * effectively handles NONE/FULL scaling
-	 */
-	nv_connector = nouveau_crtc_connector_get(nv_crtc);
-	if (nv_connector && nv_connector->native_mode) {
-		mode = nv_connector->scaling_mode;
-		if (nv_connector->scaling_full) /* non-EDID LVDS/eDP mode */
-			mode = DRM_MODE_SCALE_FULLSCREEN;
+	cid = nvif_mclass(disp->disp, curses);
+	if (cid < 0) {
+		NV_ERROR(drm, "No supported cursor immediate class\n");
+		return cid;
 	}
 
-	if (mode != DRM_MODE_SCALE_NONE)
-		omode = nv_connector->native_mode;
-	else
-		omode = umode;
+	if (!(curs = *pcurs = kzalloc(sizeof(*curs), GFP_KERNEL)))
+		return -ENOMEM;
 
-	oX = omode->hdisplay;
-	oY = omode->vdisplay;
-	if (omode->flags & DRM_MODE_FLAG_DBLSCAN)
-		oY *= 2;
+	ret = nv50_wndw_ctor(&nv50_curs, drm->dev, DRM_PLANE_TYPE_CURSOR,
+			     "curs", head->base.index, &disp->mast.base,
+			     nv50_curs_format, ARRAY_SIZE(nv50_curs_format),
+			     &curs->wndw);
+	if (ret) {
+		kfree(curs);
+		return ret;
+	}
 
-	/* add overscan compensation if necessary, will keep the aspect
-	 * ratio the same as the backend mode unless overridden by the
-	 * user setting both hborder and vborder properties.
-	 */
-	if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON ||
-			     (nv_connector->underscan == UNDERSCAN_AUTO &&
-			      drm_detect_hdmi_monitor(nv_connector->edid)))) {
-		u32 bX = nv_connector->underscan_hborder;
-		u32 bY = nv_connector->underscan_vborder;
-		u32 aspect = (oY << 19) / oX;
+	ret = nvif_object_init(disp->disp, 0, curses[cid].oclass, &args,
+			       sizeof(args), &curs->chan);
+	if (ret) {
+		NV_ERROR(drm, "curs%04x allocation failed: %d\n",
+			 curses[cid].oclass, ret);
+		return ret;
+	}
 
-		if (bX) {
-			oX -= (bX * 2);
-			if (bY) oY -= (bY * 2);
-			else    oY  = ((oX * aspect) + (aspect / 2)) >> 19;
-		} else {
-			oX -= (oX >> 4) + 32;
-			if (bY) oY -= (bY * 2);
-			else    oY  = ((oX * aspect) + (aspect / 2)) >> 19;
-		}
+	return 0;
+}
+
+/******************************************************************************
+ * Primary plane
+ *****************************************************************************/
+#define nv50_base(p) container_of((p), struct nv50_base, wndw)
+
+struct nv50_base {
+	struct nv50_wndw wndw;
+	struct nv50_sync chan;
+	int id;
+};
+
+static int
+nv50_base_notify(struct nvif_notify *notify)
+{
+	return NVIF_NOTIFY_KEEP;
+}
+
+static void
+nv50_base_lut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+	struct nv50_base *base = nv50_base(wndw);
+	u32 *push;
+	if ((push = evo_wait(&base->chan, 2))) {
+		evo_mthd(push, 0x00e0, 1);
+		evo_data(push, asyw->lut.enable << 30);
+		evo_kick(push, &base->chan);
 	}
+}
 
-	/* handle CENTER/ASPECT scaling, taking into account the areas
-	 * removed already for overscan compensation
-	 */
-	switch (mode) {
-	case DRM_MODE_SCALE_CENTER:
-		oX = min((u32)umode->hdisplay, oX);
-		oY = min((u32)umode->vdisplay, oY);
-		/* fall-through */
-	case DRM_MODE_SCALE_ASPECT:
-		if (oY < oX) {
-			u32 aspect = (umode->hdisplay << 19) / umode->vdisplay;
-			oX = ((oY * aspect) + (aspect / 2)) >> 19;
-		} else {
-			u32 aspect = (umode->vdisplay << 19) / umode->hdisplay;
-			oY = ((oX * aspect) + (aspect / 2)) >> 19;
-		}
-		break;
-	default:
-		break;
+static void
+nv50_base_image_clr(struct nv50_wndw *wndw)
+{
+	struct nv50_base *base = nv50_base(wndw);
+	u32 *push;
+	if ((push = evo_wait(&base->chan, 4))) {
+		evo_mthd(push, 0x0084, 1);
+		evo_data(push, 0x00000000);
+		evo_mthd(push, 0x00c0, 1);
+		evo_data(push, 0x00000000);
+		evo_kick(push, &base->chan);
 	}
+}
 
-	push = evo_wait(mast, 8);
-	if (push) {
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			/*XXX: SCALE_CTRL_ACTIVE??? */
-			evo_mthd(push, 0x08d8 + (nv_crtc->index * 0x400), 2);
-			evo_data(push, (oY << 16) | oX);
-			evo_data(push, (oY << 16) | oX);
-			evo_mthd(push, 0x08a4 + (nv_crtc->index * 0x400), 1);
+static void
+nv50_base_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+	struct nv50_base *base = nv50_base(wndw);
+	const s32 oclass = base->chan.base.base.user.oclass;
+	u32 *push;
+	if ((push = evo_wait(&base->chan, 10))) {
+		evo_mthd(push, 0x0084, 1);
+		evo_data(push, (asyw->image.mode << 8) |
+			       (asyw->image.interval << 4));
+		evo_mthd(push, 0x00c0, 1);
+		evo_data(push, asyw->image.handle);
+		if (oclass < G82_DISP_BASE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0800, 5);
+			evo_data(push, asyw->image.offset >> 8);
 			evo_data(push, 0x00000000);
-			evo_mthd(push, 0x08c8 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, umode->vdisplay << 16 | umode->hdisplay);
+			evo_data(push, (asyw->image.h << 16) | asyw->image.w);
+			evo_data(push, (asyw->image.layout << 20) |
+					asyw->image.pitch |
+					asyw->image.block);
+			evo_data(push, (asyw->image.kind << 16) |
+				       (asyw->image.format << 8));
+		} else
+		if (oclass < GF110_DISP_BASE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0800, 5);
+			evo_data(push, asyw->image.offset >> 8);
+			evo_data(push, 0x00000000);
+			evo_data(push, (asyw->image.h << 16) | asyw->image.w);
+			evo_data(push, (asyw->image.layout << 20) |
+					asyw->image.pitch |
+					asyw->image.block);
+			evo_data(push, asyw->image.format << 8);
 		} else {
-			evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3);
-			evo_data(push, (oY << 16) | oX);
-			evo_data(push, (oY << 16) | oX);
-			evo_data(push, (oY << 16) | oX);
-			evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1);
+			evo_mthd(push, 0x0400, 5);
+			evo_data(push, asyw->image.offset >> 8);
 			evo_data(push, 0x00000000);
-			evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1);
-			evo_data(push, umode->vdisplay << 16 | umode->hdisplay);
+			evo_data(push, (asyw->image.h << 16) | asyw->image.w);
+			evo_data(push, (asyw->image.layout << 24) |
+					asyw->image.pitch |
+					asyw->image.block);
+			evo_data(push, asyw->image.format << 8);
 		}
+		evo_kick(push, &base->chan);
+	}
+}
 
-		evo_kick(push, mast);
+static void
+nv50_base_ntfy_clr(struct nv50_wndw *wndw)
+{
+	struct nv50_base *base = nv50_base(wndw);
+	u32 *push;
+	if ((push = evo_wait(&base->chan, 2))) {
+		evo_mthd(push, 0x00a4, 1);
+		evo_data(push, 0x00000000);
+		evo_kick(push, &base->chan);
+	}
+}
 
-		if (update) {
-			nv50_display_flip_stop(crtc);
-			nv50_display_flip_next(crtc, crtc->primary->fb,
-					       NULL, 1);
-		}
+static void
+nv50_base_ntfy_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+	struct nv50_base *base = nv50_base(wndw);
+	u32 *push;
+	if ((push = evo_wait(&base->chan, 3))) {
+		evo_mthd(push, 0x00a0, 2);
+		evo_data(push, (asyw->ntfy.awaken << 30) | asyw->ntfy.offset);
+		evo_data(push, asyw->ntfy.handle);
+		evo_kick(push, &base->chan);
 	}
+}
 
-	return 0;
+static void
+nv50_base_sema_clr(struct nv50_wndw *wndw)
+{
+	struct nv50_base *base = nv50_base(wndw);
+	u32 *push;
+	if ((push = evo_wait(&base->chan, 2))) {
+		evo_mthd(push, 0x0094, 1);
+		evo_data(push, 0x00000000);
+		evo_kick(push, &base->chan);
+	}
 }
 
-static int
-nv50_crtc_set_raster_vblank_dmi(struct nouveau_crtc *nv_crtc, u32 usec)
+static void
+nv50_base_sema_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
 {
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
+	struct nv50_base *base = nv50_base(wndw);
 	u32 *push;
+	if ((push = evo_wait(&base->chan, 5))) {
+		evo_mthd(push, 0x0088, 4);
+		evo_data(push, asyw->sema.offset);
+		evo_data(push, asyw->sema.acquire);
+		evo_data(push, asyw->sema.release);
+		evo_data(push, asyw->sema.handle);
+		evo_kick(push, &base->chan);
+	}
+}
 
-	push = evo_wait(mast, 8);
-	if (!push)
-		return -ENOMEM;
+static u32
+nv50_base_update(struct nv50_wndw *wndw, u32 interlock)
+{
+	struct nv50_base *base = nv50_base(wndw);
+	u32 *push;
 
-	evo_mthd(push, 0x0828 + (nv_crtc->index * 0x400), 1);
-	evo_data(push, usec);
-	evo_kick(push, mast);
+	if (!(push = evo_wait(&base->chan, 2)))
+		return 0;
+	evo_mthd(push, 0x0080, 1);
+	evo_data(push, interlock);
+	evo_kick(push, &base->chan);
+
+	if (base->chan.base.base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA)
+		return interlock ? 2 << (base->id * 8) : 0;
+	return interlock ? 2 << (base->id * 4) : 0;
+}
+
+static int
+nv50_base_ntfy_wait_begun(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
+{
+	struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
+	struct nv50_disp *disp = nv50_disp(wndw->plane.dev);
+	if (nvif_msec(&drm->device, 2000ULL,
+		u32 data = nouveau_bo_rd32(disp->sync, asyw->ntfy.offset / 4);
+		if ((data & 0xc0000000) == 0x40000000)
+			break;
+		usleep_range(1, 2);
+	) < 0)
+		return -ETIMEDOUT;
 	return 0;
 }
 
+static void
+nv50_base_release(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+		  struct nv50_head_atom *asyh)
+{
+	asyh->base.cpp = 0;
+}
+
 static int
-nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
+nv50_base_acquire(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
+		  struct nv50_head_atom *asyh)
 {
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-	u32 *push, hue, vib;
-	int adj;
+	const u32 format = asyw->state.fb->pixel_format;
+	const struct drm_format_info *info;
+	int ret;
 
-	adj = (nv_crtc->color_vibrance > 0) ? 50 : 0;
-	vib = ((nv_crtc->color_vibrance * 2047 + adj) / 100) & 0xfff;
-	hue = ((nv_crtc->vibrant_hue * 2047) / 100) & 0xfff;
+	info = drm_format_info(format);
+	if (!info || !info->depth)
+		return -EINVAL;
 
-	push = evo_wait(mast, 16);
-	if (push) {
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x08a8 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, (hue << 20) | (vib << 8));
-		} else {
-			evo_mthd(push, 0x0498 + (nv_crtc->index * 0x300), 1);
-			evo_data(push, (hue << 20) | (vib << 8));
-		}
+	ret = drm_plane_helper_check_state(&asyw->state, &asyw->clip,
+					   DRM_PLANE_HELPER_NO_SCALING,
+					   DRM_PLANE_HELPER_NO_SCALING,
+					   false, true);
+	if (ret)
+		return ret;
 
-		if (update) {
-			evo_mthd(push, 0x0080, 1);
-			evo_data(push, 0x00000000);
-		}
-		evo_kick(push, mast);
+	asyh->base.depth = info->depth;
+	asyh->base.cpp = info->cpp[0];
+	asyh->base.x = asyw->state.src.x1 >> 16;
+	asyh->base.y = asyw->state.src.y1 >> 16;
+	asyh->base.w = asyw->state.fb->width;
+	asyh->base.h = asyw->state.fb->height;
+
+	switch (format) {
+	case DRM_FORMAT_C8         : asyw->image.format = 0x1e; break;
+	case DRM_FORMAT_RGB565     : asyw->image.format = 0xe8; break;
+	case DRM_FORMAT_XRGB1555   :
+	case DRM_FORMAT_ARGB1555   : asyw->image.format = 0xe9; break;
+	case DRM_FORMAT_XRGB8888   :
+	case DRM_FORMAT_ARGB8888   : asyw->image.format = 0xcf; break;
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_ABGR2101010: asyw->image.format = 0xd1; break;
+	case DRM_FORMAT_XBGR8888   :
+	case DRM_FORMAT_ABGR8888   : asyw->image.format = 0xd5; break;
+	default:
+		WARN_ON(1);
+		return -EINVAL;
 	}
 
+	asyw->lut.enable = 1;
+	asyw->set.image = true;
 	return 0;
 }
 
+static void *
+nv50_base_dtor(struct nv50_wndw *wndw)
+{
+	struct nv50_disp *disp = nv50_disp(wndw->plane.dev);
+	struct nv50_base *base = nv50_base(wndw);
+	nv50_dmac_destroy(&base->chan.base, disp->disp);
+	return base;
+}
+
+static const u32
+nv50_base_format[] = {
+	DRM_FORMAT_C8,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_ABGR2101010,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_ABGR8888,
+};
+
+static const struct nv50_wndw_func
+nv50_base = {
+	.dtor = nv50_base_dtor,
+	.acquire = nv50_base_acquire,
+	.release = nv50_base_release,
+	.sema_set = nv50_base_sema_set,
+	.sema_clr = nv50_base_sema_clr,
+	.ntfy_set = nv50_base_ntfy_set,
+	.ntfy_clr = nv50_base_ntfy_clr,
+	.ntfy_wait_begun = nv50_base_ntfy_wait_begun,
+	.image_set = nv50_base_image_set,
+	.image_clr = nv50_base_image_clr,
+	.lut = nv50_base_lut,
+	.update = nv50_base_update,
+};
+
 static int
-nv50_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb,
-		    int x, int y, bool update)
+nv50_base_new(struct nouveau_drm *drm, struct nv50_head *head,
+	      struct nv50_base **pbase)
 {
-	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb);
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
+	struct nv50_disp *disp = nv50_disp(drm->dev);
+	struct nv50_base *base;
+	int ret;
+
+	if (!(base = *pbase = kzalloc(sizeof(*base), GFP_KERNEL)))
+		return -ENOMEM;
+	base->id = head->base.index;
+	base->wndw.ntfy = EVO_FLIP_NTFY0(base->id);
+	base->wndw.sema = EVO_FLIP_SEM0(base->id);
+	base->wndw.data = 0x00000000;
+
+	ret = nv50_wndw_ctor(&nv50_base, drm->dev, DRM_PLANE_TYPE_PRIMARY,
+			     "base", base->id, &base->chan.base,
+			     nv50_base_format, ARRAY_SIZE(nv50_base_format),
+			     &base->wndw);
+	if (ret) {
+		kfree(base);
+		return ret;
+	}
+
+	ret = nv50_base_create(&drm->device, disp->disp, base->id,
+			       disp->sync->bo.offset, &base->chan);
+	if (ret)
+		return ret;
+
+	return nvif_notify_init(&base->chan.base.base.user, nv50_base_notify,
+				false,
+				NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT,
+				&(struct nvif_notify_uevent_req) {},
+				sizeof(struct nvif_notify_uevent_req),
+				sizeof(struct nvif_notify_uevent_rep),
+				&base->wndw.notify);
+}
+
+/******************************************************************************
+ * Head
+ *****************************************************************************/
+static void
+nv50_head_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
 	u32 *push;
+	if ((push = evo_wait(core, 2))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+			evo_mthd(push, 0x08a8 + (head->base.index * 0x400), 1);
+		else
+			evo_mthd(push, 0x0498 + (head->base.index * 0x300), 1);
+		evo_data(push, (asyh->procamp.sat.sin << 20) |
+			       (asyh->procamp.sat.cos << 8));
+		evo_kick(push, core);
+	}
+}
 
-	push = evo_wait(mast, 16);
-	if (push) {
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0860 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, nvfb->nvbo->bo.offset >> 8);
-			evo_mthd(push, 0x0868 + (nv_crtc->index * 0x400), 3);
-			evo_data(push, (fb->height << 16) | fb->width);
-			evo_data(push, nvfb->r_pitch);
-			evo_data(push, nvfb->r_format);
-			evo_mthd(push, 0x08c0 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, (y << 16) | x);
-			if (nv50_vers(mast) > NV50_DISP_CORE_CHANNEL_DMA) {
-				evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-				evo_data(push, nvfb->r_handle);
-			}
-		} else {
-			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_handle);
-			evo_mthd(push, 0x04b0 + (nv_crtc->index * 0x300), 1);
-			evo_data(push, (y << 16) | x);
-		}
+static void
+nv50_head_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 *push;
+	if ((push = evo_wait(core, 2))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+			evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1);
+		else
+		if (core->base.user.oclass < GK104_DISP_CORE_CHANNEL_DMA)
+			evo_mthd(push, 0x0490 + (head->base.index * 0x0300), 1);
+		else
+			evo_mthd(push, 0x04a0 + (head->base.index * 0x0300), 1);
+		evo_data(push, (asyh->dither.mode << 3) |
+			       (asyh->dither.bits << 1) |
+			        asyh->dither.enable);
+		evo_kick(push, core);
+	}
+}
 
-		if (update) {
-			evo_mthd(push, 0x0080, 1);
-			evo_data(push, 0x00000000);
+static void
+nv50_head_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 bounds = 0;
+	u32 *push;
+
+	if (asyh->base.cpp) {
+		switch (asyh->base.cpp) {
+		case 8: bounds |= 0x00000500; break;
+		case 4: bounds |= 0x00000300; break;
+		case 2: bounds |= 0x00000100; break;
+		default:
+			WARN_ON(1);
+			break;
 		}
-		evo_kick(push, mast);
+		bounds |= 0x00000001;
 	}
 
-	nv_crtc->fb.handle = nvfb->r_handle;
-	return 0;
+	if ((push = evo_wait(core, 2))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+			evo_mthd(push, 0x0904 + head->base.index * 0x400, 1);
+		else
+			evo_mthd(push, 0x04d4 + head->base.index * 0x300, 1);
+		evo_data(push, bounds);
+		evo_kick(push, core);
+	}
 }
 
 static void
-nv50_crtc_cursor_show(struct nouveau_crtc *nv_crtc)
+nv50_head_base(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-	u32 *push = evo_wait(mast, 16);
-	if (push) {
-		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
-			evo_data(push, 0x85000000);
-			evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
-		} else
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 2);
-			evo_data(push, 0x85000000);
-			evo_data(push, nv_crtc->cursor.nvbo->bo.offset >> 8);
-			evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
-			evo_data(push, mast->base.vram.handle);
-		} else {
-			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, mast->base.vram.handle);
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 bounds = 0;
+	u32 *push;
+
+	if (asyh->base.cpp) {
+		switch (asyh->base.cpp) {
+		case 8: bounds |= 0x00000500; break;
+		case 4: bounds |= 0x00000300; break;
+		case 2: bounds |= 0x00000100; break;
+		case 1: bounds |= 0x00000000; break;
+		default:
+			WARN_ON(1);
+			break;
 		}
-		evo_kick(push, mast);
+		bounds |= 0x00000001;
+	}
+
+	if ((push = evo_wait(core, 2))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+			evo_mthd(push, 0x0900 + head->base.index * 0x400, 1);
+		else
+			evo_mthd(push, 0x04d0 + head->base.index * 0x300, 1);
+		evo_data(push, bounds);
+		evo_kick(push, core);
 	}
-	nv_crtc->cursor.visible = true;
 }
 
 static void
-nv50_crtc_cursor_hide(struct nouveau_crtc *nv_crtc)
+nv50_head_curs_clr(struct nv50_head *head)
 {
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-	u32 *push = evo_wait(mast, 16);
-	if (push) {
-		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 *push;
+	if ((push = evo_wait(core, 4))) {
+		if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
 			evo_data(push, 0x05000000);
 		} else
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0880 + (nv_crtc->index * 0x400), 1);
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0880 + head->base.index * 0x400, 1);
 			evo_data(push, 0x05000000);
-			evo_mthd(push, 0x089c + (nv_crtc->index * 0x400), 1);
+			evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
 			evo_data(push, 0x00000000);
 		} else {
-			evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 1);
+			evo_mthd(push, 0x0480 + head->base.index * 0x300, 1);
 			evo_data(push, 0x05000000);
-			evo_mthd(push, 0x048c + (nv_crtc->index * 0x300), 1);
+			evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
 			evo_data(push, 0x00000000);
 		}
-		evo_kick(push, mast);
+		evo_kick(push, core);
 	}
-	nv_crtc->cursor.visible = false;
 }
 
 static void
-nv50_crtc_cursor_show_hide(struct nouveau_crtc *nv_crtc, bool show, bool update)
+nv50_head_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
-	struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
-
-	if (show && nv_crtc->cursor.nvbo && nv_crtc->base.enabled)
-		nv50_crtc_cursor_show(nv_crtc);
-	else
-		nv50_crtc_cursor_hide(nv_crtc);
-
-	if (update) {
-		u32 *push = evo_wait(mast, 2);
-		if (push) {
-			evo_mthd(push, 0x0080, 1);
-			evo_data(push, 0x00000000);
-			evo_kick(push, mast);
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 *push;
+	if ((push = evo_wait(core, 5))) {
+		if (core->base.user.oclass < G82_DISP_BASE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
+			evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
+						    (asyh->curs.format << 24));
+			evo_data(push, asyh->curs.offset >> 8);
+		} else
+		if (core->base.user.oclass < GF110_DISP_BASE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0880 + head->base.index * 0x400, 2);
+			evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
+						    (asyh->curs.format << 24));
+			evo_data(push, asyh->curs.offset >> 8);
+			evo_mthd(push, 0x089c + head->base.index * 0x400, 1);
+			evo_data(push, asyh->curs.handle);
+		} else {
+			evo_mthd(push, 0x0480 + head->base.index * 0x300, 2);
+			evo_data(push, 0x80000000 | (asyh->curs.layout << 26) |
+						    (asyh->curs.format << 24));
+			evo_data(push, asyh->curs.offset >> 8);
+			evo_mthd(push, 0x048c + head->base.index * 0x300, 1);
+			evo_data(push, asyh->curs.handle);
 		}
+		evo_kick(push, core);
 	}
 }
 
 static void
-nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
+nv50_head_core_clr(struct nv50_head *head)
 {
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 *push;
+	if ((push = evo_wait(core, 2))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
+			evo_mthd(push, 0x0874 + head->base.index * 0x400, 1);
+		else
+			evo_mthd(push, 0x0474 + head->base.index * 0x300, 1);
+		evo_data(push, 0x00000000);
+		evo_kick(push, core);
+	}
 }
 
 static void
-nv50_crtc_prepare(struct drm_crtc *crtc)
+nv50_head_core_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct nv50_mast *mast = nv50_mast(crtc->dev);
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
 	u32 *push;
+	if ((push = evo_wait(core, 9))) {
+		if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
+			evo_data(push, asyh->core.offset >> 8);
+			evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
+			evo_data(push, (asyh->core.h << 16) | asyh->core.w);
+			evo_data(push, asyh->core.layout << 20 |
+				       (asyh->core.pitch >> 8) << 8 |
+				       asyh->core.block);
+			evo_data(push, asyh->core.kind << 16 |
+				       asyh->core.format << 8);
+			evo_data(push, asyh->core.handle);
+			evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
+			evo_data(push, (asyh->core.y << 16) | asyh->core.x);
+			/* EVO will complain with INVALID_STATE if we have an
+			 * active cursor and (re)specify HeadSetContextDmaIso
+			 * without also updating HeadSetOffsetCursor.
+			 */
+			asyh->set.curs = asyh->curs.visible;
+		} else
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0860 + head->base.index * 0x400, 1);
+			evo_data(push, asyh->core.offset >> 8);
+			evo_mthd(push, 0x0868 + head->base.index * 0x400, 4);
+			evo_data(push, (asyh->core.h << 16) | asyh->core.w);
+			evo_data(push, asyh->core.layout << 20 |
+				       (asyh->core.pitch >> 8) << 8 |
+				       asyh->core.block);
+			evo_data(push, asyh->core.format << 8);
+			evo_data(push, asyh->core.handle);
+			evo_mthd(push, 0x08c0 + head->base.index * 0x400, 1);
+			evo_data(push, (asyh->core.y << 16) | asyh->core.x);
+		} else {
+			evo_mthd(push, 0x0460 + head->base.index * 0x300, 1);
+			evo_data(push, asyh->core.offset >> 8);
+			evo_mthd(push, 0x0468 + head->base.index * 0x300, 4);
+			evo_data(push, (asyh->core.h << 16) | asyh->core.w);
+			evo_data(push, asyh->core.layout << 24 |
+				       (asyh->core.pitch >> 8) << 8 |
+				       asyh->core.block);
+			evo_data(push, asyh->core.format << 8);
+			evo_data(push, asyh->core.handle);
+			evo_mthd(push, 0x04b0 + head->base.index * 0x300, 1);
+			evo_data(push, (asyh->core.y << 16) | asyh->core.x);
+		}
+		evo_kick(push, core);
+	}
+}
 
-	nv50_display_flip_stop(crtc);
-
-	push = evo_wait(mast, 6);
-	if (push) {
-		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, 0x00000000);
-			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
+static void
+nv50_head_lut_clr(struct nv50_head *head)
+{
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 *push;
+	if ((push = evo_wait(core, 4))) {
+		if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
 			evo_data(push, 0x40000000);
 		} else
-		if (nv50_vers(mast) <  GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, 0x00000000);
-			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 1);
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 1);
 			evo_data(push, 0x40000000);
-			evo_mthd(push, 0x085c + (nv_crtc->index * 0x400), 1);
+			evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
 			evo_data(push, 0x00000000);
 		} else {
-			evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
-			evo_data(push, 0x00000000);
-			evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 1);
+			evo_mthd(push, 0x0440 + (head->base.index * 0x300), 1);
 			evo_data(push, 0x03000000);
-			evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
+			evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
 			evo_data(push, 0x00000000);
 		}
-
-		evo_kick(push, mast);
+		evo_kick(push, core);
 	}
-
-	nv50_crtc_cursor_show_hide(nv_crtc, false, false);
 }
 
 static void
-nv50_crtc_commit(struct drm_crtc *crtc)
+nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct nv50_mast *mast = nv50_mast(crtc->dev);
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
 	u32 *push;
-
-	push = evo_wait(mast, 32);
-	if (push) {
-		if (nv50_vers(mast) < G82_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, nv_crtc->fb.handle);
-			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
+	if ((push = evo_wait(core, 7))) {
+		if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
 			evo_data(push, 0xc0000000);
-			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
+			evo_data(push, asyh->lut.offset >> 8);
 		} else
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0874 + (nv_crtc->index * 0x400), 1);
-			evo_data(push, nv_crtc->fb.handle);
-			evo_mthd(push, 0x0840 + (nv_crtc->index * 0x400), 2);
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2);
 			evo_data(push, 0xc0000000);
-			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
-			evo_mthd(push, 0x085c + (nv_crtc->index * 0x400), 1);
-			evo_data(push, mast->base.vram.handle);
+			evo_data(push, asyh->lut.offset >> 8);
+			evo_mthd(push, 0x085c + (head->base.index * 0x400), 1);
+			evo_data(push, asyh->lut.handle);
 		} else {
-			evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1);
-			evo_data(push, nv_crtc->fb.handle);
-			evo_mthd(push, 0x0440 + (nv_crtc->index * 0x300), 4);
+			evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4);
 			evo_data(push, 0x83000000);
-			evo_data(push, nv_crtc->lut.nvbo->bo.offset >> 8);
+			evo_data(push, asyh->lut.offset >> 8);
 			evo_data(push, 0x00000000);
 			evo_data(push, 0x00000000);
-			evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1);
-			evo_data(push, mast->base.vram.handle);
-			evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1);
+			evo_mthd(push, 0x045c + (head->base.index * 0x300), 1);
+			evo_data(push, asyh->lut.handle);
+		}
+		evo_kick(push, core);
+	}
+}
+
+static void
+nv50_head_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	struct nv50_head_mode *m = &asyh->mode;
+	u32 *push;
+	if ((push = evo_wait(core, 14))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x0804 + (head->base.index * 0x400), 2);
+			evo_data(push, 0x00800000 | m->clock);
+			evo_data(push, m->interlace ? 0x00000002 : 0x00000000);
+			evo_mthd(push, 0x0810 + (head->base.index * 0x400), 7);
+			evo_data(push, 0x00000000);
+			evo_data(push, (m->v.active  << 16) | m->h.active );
+			evo_data(push, (m->v.synce   << 16) | m->h.synce  );
+			evo_data(push, (m->v.blanke  << 16) | m->h.blanke );
+			evo_data(push, (m->v.blanks  << 16) | m->h.blanks );
+			evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
+			evo_data(push, asyh->mode.v.blankus);
+			evo_mthd(push, 0x082c + (head->base.index * 0x400), 1);
+			evo_data(push, 0x00000000);
+		} else {
+			evo_mthd(push, 0x0410 + (head->base.index * 0x300), 6);
+			evo_data(push, 0x00000000);
+			evo_data(push, (m->v.active  << 16) | m->h.active );
+			evo_data(push, (m->v.synce   << 16) | m->h.synce  );
+			evo_data(push, (m->v.blanke  << 16) | m->h.blanke );
+			evo_data(push, (m->v.blanks  << 16) | m->h.blanks );
+			evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
+			evo_mthd(push, 0x042c + (head->base.index * 0x300), 2);
+			evo_data(push, 0x00000000); /* ??? */
 			evo_data(push, 0xffffff00);
+			evo_mthd(push, 0x0450 + (head->base.index * 0x300), 3);
+			evo_data(push, m->clock * 1000);
+			evo_data(push, 0x00200000); /* ??? */
+			evo_data(push, m->clock * 1000);
 		}
+		evo_kick(push, core);
+	}
+}
 
-		evo_kick(push, mast);
+static void
+nv50_head_view(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+	struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
+	u32 *push;
+	if ((push = evo_wait(core, 10))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+			evo_mthd(push, 0x08a4 + (head->base.index * 0x400), 1);
+			evo_data(push, 0x00000000);
+			evo_mthd(push, 0x08c8 + (head->base.index * 0x400), 1);
+			evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
+			evo_mthd(push, 0x08d8 + (head->base.index * 0x400), 2);
+			evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+			evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+		} else {
+			evo_mthd(push, 0x0494 + (head->base.index * 0x300), 1);
+			evo_data(push, 0x00000000);
+			evo_mthd(push, 0x04b8 + (head->base.index * 0x300), 1);
+			evo_data(push, (asyh->view.iH << 16) | asyh->view.iW);
+			evo_mthd(push, 0x04c0 + (head->base.index * 0x300), 3);
+			evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+			evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+			evo_data(push, (asyh->view.oH << 16) | asyh->view.oW);
+		}
+		evo_kick(push, core);
 	}
+}
 
-	nv50_crtc_cursor_show_hide(nv_crtc, true, true);
-	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
+static void
+nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool y)
+{
+	if (asyh->clr.core && (!asyh->set.core || y))
+		nv50_head_lut_clr(head);
+	if (asyh->clr.core && (!asyh->set.core || y))
+		nv50_head_core_clr(head);
+	if (asyh->clr.curs && (!asyh->set.curs || y))
+		nv50_head_curs_clr(head);
 }
 
-static bool
-nv50_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
-		     struct drm_display_mode *adjusted_mode)
+static void
+nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
-	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-	return true;
+	if (asyh->set.view   ) nv50_head_view    (head, asyh);
+	if (asyh->set.mode   ) nv50_head_mode    (head, asyh);
+	if (asyh->set.core   ) nv50_head_lut_set (head, asyh);
+	if (asyh->set.core   ) nv50_head_core_set(head, asyh);
+	if (asyh->set.curs   ) nv50_head_curs_set(head, asyh);
+	if (asyh->set.base   ) nv50_head_base    (head, asyh);
+	if (asyh->set.ovly   ) nv50_head_ovly    (head, asyh);
+	if (asyh->set.dither ) nv50_head_dither  (head, asyh);
+	if (asyh->set.procamp) nv50_head_procamp (head, asyh);
 }
 
-static int
-nv50_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb)
+static void
+nv50_head_atomic_check_procamp(struct nv50_head_atom *armh,
+			       struct nv50_head_atom *asyh,
+			       struct nouveau_conn_atom *asyc)
 {
-	struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->primary->fb);
-	struct nv50_head *head = nv50_head(crtc);
-	int ret;
+	const int vib = asyc->procamp.color_vibrance - 100;
+	const int hue = asyc->procamp.vibrant_hue - 90;
+	const int adj = (vib > 0) ? 50 : 0;
+	asyh->procamp.sat.cos = ((vib * 2047 + adj) / 100) & 0xfff;
+	asyh->procamp.sat.sin = ((hue * 2047) / 100) & 0xfff;
+	asyh->set.procamp = true;
+}
 
-	ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM, true);
-	if (ret == 0) {
-		if (head->image)
-			nouveau_bo_unpin(head->image);
-		nouveau_bo_ref(nvfb->nvbo, &head->image);
+static void
+nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
+			      struct nv50_head_atom *asyh,
+			      struct nouveau_conn_atom *asyc)
+{
+	struct drm_connector *connector = asyc->state.connector;
+	u32 mode = 0x00;
+
+	if (asyc->dither.mode == DITHERING_MODE_AUTO) {
+		if (asyh->base.depth > connector->display_info.bpc * 3)
+			mode = DITHERING_MODE_DYNAMIC2X2;
+	} else {
+		mode = asyc->dither.mode;
 	}
 
-	return ret;
+	if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
+		if (connector->display_info.bpc >= 8)
+			mode |= DITHERING_DEPTH_8BPC;
+	} else {
+		mode |= asyc->dither.depth;
+	}
+
+	asyh->dither.enable = mode;
+	asyh->dither.bits = mode >> 1;
+	asyh->dither.mode = mode >> 3;
+	asyh->set.dither = true;
 }
 
-static int
-nv50_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)
+static void
+nv50_head_atomic_check_view(struct nv50_head_atom *armh,
+			    struct nv50_head_atom *asyh,
+			    struct nouveau_conn_atom *asyc)
 {
-	struct nv50_mast *mast = nv50_mast(crtc->dev);
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct nouveau_connector *nv_connector;
-	u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1;
-	u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1;
-	u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks;
-	u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks;
-	u32 vblan2e = 0, vblan2s = 1, vblankus = 0;
-	u32 *push;
-	int ret;
-
-	hactive = mode->htotal;
-	hsynce  = mode->hsync_end - mode->hsync_start - 1;
-	hbackp  = mode->htotal - mode->hsync_end;
-	hblanke = hsynce + hbackp;
-	hfrontp = mode->hsync_start - mode->hdisplay;
-	hblanks = mode->htotal - hfrontp - 1;
+	struct drm_connector *connector = asyc->state.connector;
+	struct drm_display_mode *omode = &asyh->state.adjusted_mode;
+	struct drm_display_mode *umode = &asyh->state.mode;
+	int mode = asyc->scaler.mode;
+	struct edid *edid;
 
-	vactive = mode->vtotal * vscan / ilace;
-	vsynce  = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1;
-	vbackp  = (mode->vtotal - mode->vsync_end) * vscan / ilace;
-	vblanke = vsynce + vbackp;
-	vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace;
-	vblanks = vactive - vfrontp - 1;
-	/* XXX: Safe underestimate, even "0" works */
-	vblankus = (vactive - mode->vdisplay - 2) * hactive;
-	vblankus *= 1000;
-	vblankus /= mode->clock;
+	if (connector->edid_blob_ptr)
+		edid = (struct edid *)connector->edid_blob_ptr->data;
+	else
+		edid = NULL;
 
-	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
-		vblan2e = vactive + vsynce + vbackp;
-		vblan2s = vblan2e + (mode->vdisplay * vscan / ilace);
-		vactive = (vactive * 2) + 1;
+	if (!asyc->scaler.full) {
+		if (mode == DRM_MODE_SCALE_NONE)
+			omode = umode;
+	} else {
+		/* Non-EDID LVDS/eDP mode. */
+		mode = DRM_MODE_SCALE_FULLSCREEN;
 	}
 
-	ret = nv50_crtc_swap_fbs(crtc, old_fb);
-	if (ret)
-		return ret;
+	asyh->view.iW = umode->hdisplay;
+	asyh->view.iH = umode->vdisplay;
+	asyh->view.oW = omode->hdisplay;
+	asyh->view.oH = omode->vdisplay;
+	if (omode->flags & DRM_MODE_FLAG_DBLSCAN)
+		asyh->view.oH *= 2;
 
-	push = evo_wait(mast, 64);
-	if (push) {
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-			evo_mthd(push, 0x0804 + (nv_crtc->index * 0x400), 2);
-			evo_data(push, 0x00800000 | mode->clock);
-			evo_data(push, (ilace == 2) ? 2 : 0);
-			evo_mthd(push, 0x0810 + (nv_crtc->index * 0x400), 6);
-			evo_data(push, 0x00000000);
-			evo_data(push, (vactive << 16) | hactive);
-			evo_data(push, ( vsynce << 16) | hsynce);
-			evo_data(push, (vblanke << 16) | hblanke);
-			evo_data(push, (vblanks << 16) | hblanks);
-			evo_data(push, (vblan2e << 16) | vblan2s);
-			evo_mthd(push, 0x082c + (nv_crtc->index * 0x400), 1);
-			evo_data(push, 0x00000000);
-			evo_mthd(push, 0x0900 + (nv_crtc->index * 0x400), 2);
-			evo_data(push, 0x00000311);
-			evo_data(push, 0x00000100);
+	/* Add overscan compensation if necessary, will keep the aspect
+	 * ratio the same as the backend mode unless overridden by the
+	 * user setting both hborder and vborder properties.
+	 */
+	if ((asyc->scaler.underscan.mode == UNDERSCAN_ON ||
+	    (asyc->scaler.underscan.mode == UNDERSCAN_AUTO &&
+	     drm_detect_hdmi_monitor(edid)))) {
+		u32 bX = asyc->scaler.underscan.hborder;
+		u32 bY = asyc->scaler.underscan.vborder;
+		u32 r = (asyh->view.oH << 19) / asyh->view.oW;
+
+		if (bX) {
+			asyh->view.oW -= (bX * 2);
+			if (bY) asyh->view.oH -= (bY * 2);
+			else    asyh->view.oH  = ((asyh->view.oW * r) + (r / 2)) >> 19;
 		} else {
-			evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 6);
-			evo_data(push, 0x00000000);
-			evo_data(push, (vactive << 16) | hactive);
-			evo_data(push, ( vsynce << 16) | hsynce);
-			evo_data(push, (vblanke << 16) | hblanke);
-			evo_data(push, (vblanks << 16) | hblanks);
-			evo_data(push, (vblan2e << 16) | vblan2s);
-			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, 0x04d0 + (nv_crtc->index * 0x300), 2);
-			evo_data(push, 0x00000311);
-			evo_data(push, 0x00000100);
+			asyh->view.oW -= (asyh->view.oW >> 4) + 32;
+			if (bY) asyh->view.oH -= (bY * 2);
+			else    asyh->view.oH  = ((asyh->view.oW * r) + (r / 2)) >> 19;
 		}
+	}
 
-		evo_kick(push, mast);
+	/* Handle CENTER/ASPECT scaling, taking into account the areas
+	 * removed already for overscan compensation.
+	 */
+	switch (mode) {
+	case DRM_MODE_SCALE_CENTER:
+		asyh->view.oW = min((u16)umode->hdisplay, asyh->view.oW);
+		asyh->view.oH = min((u16)umode->vdisplay, asyh->view.oH);
+		/* fall-through */
+	case DRM_MODE_SCALE_ASPECT:
+		if (asyh->view.oH < asyh->view.oW) {
+			u32 r = (asyh->view.iW << 19) / asyh->view.iH;
+			asyh->view.oW = ((asyh->view.oH * r) + (r / 2)) >> 19;
+		} else {
+			u32 r = (asyh->view.iH << 19) / asyh->view.iW;
+			asyh->view.oH = ((asyh->view.oW * r) + (r / 2)) >> 19;
+		}
+		break;
+	default:
+		break;
 	}
 
-	nv_connector = nouveau_crtc_connector_get(nv_crtc);
-	nv50_crtc_set_dither(nv_crtc, false);
-	nv50_crtc_set_scale(nv_crtc, false);
+	asyh->set.view = true;
+}
 
-	/* G94 only accepts this after setting scale */
-	if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA)
-		nv50_crtc_set_raster_vblank_dmi(nv_crtc, vblankus);
+static void
+nv50_head_atomic_check_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+	struct drm_display_mode *mode = &asyh->state.adjusted_mode;
+	u32 ilace   = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1;
+	u32 vscan   = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1;
+	u32 hbackp  =  mode->htotal - mode->hsync_end;
+	u32 vbackp  = (mode->vtotal - mode->vsync_end) * vscan / ilace;
+	u32 hfrontp =  mode->hsync_start - mode->hdisplay;
+	u32 vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace;
+	struct nv50_head_mode *m = &asyh->mode;
 
-	nv50_crtc_set_color_vibrance(nv_crtc, false);
-	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, false);
-	return 0;
+	m->h.active = mode->htotal;
+	m->h.synce  = mode->hsync_end - mode->hsync_start - 1;
+	m->h.blanke = m->h.synce + hbackp;
+	m->h.blanks = mode->htotal - hfrontp - 1;
+
+	m->v.active = mode->vtotal * vscan / ilace;
+	m->v.synce  = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1;
+	m->v.blanke = m->v.synce + vbackp;
+	m->v.blanks = m->v.active - vfrontp - 1;
+
+	/*XXX: Safe underestimate, even "0" works */
+	m->v.blankus = (m->v.active - mode->vdisplay - 2) * m->h.active;
+	m->v.blankus *= 1000;
+	m->v.blankus /= mode->clock;
+
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		m->v.blank2e =  m->v.active + m->v.synce + vbackp;
+		m->v.blank2s =  m->v.blank2e + (mode->vdisplay * vscan / ilace);
+		m->v.active  = (m->v.active * 2) + 1;
+		m->interlace = true;
+	} else {
+		m->v.blank2e = 0;
+		m->v.blank2s = 1;
+		m->interlace = false;
+	}
+	m->clock = mode->clock;
+
+	drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
+	asyh->set.mode = true;
 }
 
 static int
-nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
-			struct drm_framebuffer *old_fb)
+nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state)
 {
 	struct nouveau_drm *drm = nouveau_drm(crtc->dev);
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	int ret;
+	struct nv50_disp *disp = nv50_disp(crtc->dev);
+	struct nv50_head *head = nv50_head(crtc);
+	struct nv50_head_atom *armh = nv50_head_atom(crtc->state);
+	struct nv50_head_atom *asyh = nv50_head_atom(state);
+	struct nouveau_conn_atom *asyc = NULL;
+	struct drm_connector_state *conns;
+	struct drm_connector *conn;
+	int i;
 
-	if (!crtc->primary->fb) {
-		NV_DEBUG(drm, "No FB bound\n");
-		return 0;
+	NV_ATOMIC(drm, "%s atomic_check %d\n", crtc->name, asyh->state.active);
+	if (asyh->state.active) {
+		for_each_connector_in_state(asyh->state.state, conn, conns, i) {
+			if (conns->crtc == crtc) {
+				asyc = nouveau_conn_atom(conns);
+				break;
+			}
+		}
+
+		if (armh->state.active) {
+			if (asyc) {
+				if (asyh->state.mode_changed)
+					asyc->set.scaler = true;
+				if (armh->base.depth != asyh->base.depth)
+					asyc->set.dither = true;
+			}
+		} else {
+			asyc->set.mask = ~0;
+			asyh->set.mask = ~0;
+		}
+
+		if (asyh->state.mode_changed)
+			nv50_head_atomic_check_mode(head, asyh);
+
+		if (asyc) {
+			if (asyc->set.scaler)
+				nv50_head_atomic_check_view(armh, asyh, asyc);
+			if (asyc->set.dither)
+				nv50_head_atomic_check_dither(armh, asyh, asyc);
+			if (asyc->set.procamp)
+				nv50_head_atomic_check_procamp(armh, asyh, asyc);
+		}
+
+		if ((asyh->core.visible = (asyh->base.cpp != 0))) {
+			asyh->core.x = asyh->base.x;
+			asyh->core.y = asyh->base.y;
+			asyh->core.w = asyh->base.w;
+			asyh->core.h = asyh->base.h;
+		} else
+		if ((asyh->core.visible = asyh->curs.visible)) {
+			/*XXX: We need to either find some way of having the
+			 *     primary base layer appear black, while still
+			 *     being able to display the other layers, or we
+			 *     need to allocate a dummy black surface here.
+			 */
+			asyh->core.x = 0;
+			asyh->core.y = 0;
+			asyh->core.w = asyh->state.mode.hdisplay;
+			asyh->core.h = asyh->state.mode.vdisplay;
+		}
+		asyh->core.handle = disp->mast.base.vram.handle;
+		asyh->core.offset = 0;
+		asyh->core.format = 0xcf;
+		asyh->core.kind = 0;
+		asyh->core.layout = 1;
+		asyh->core.block = 0;
+		asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4;
+		asyh->lut.handle = disp->mast.base.vram.handle;
+		asyh->lut.offset = head->base.lut.nvbo->bo.offset;
+		asyh->set.base = armh->base.cpp != asyh->base.cpp;
+		asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp;
+	} else {
+		asyh->core.visible = false;
+		asyh->curs.visible = false;
+		asyh->base.cpp = 0;
+		asyh->ovly.cpp = 0;
 	}
 
-	ret = nv50_crtc_swap_fbs(crtc, old_fb);
-	if (ret)
-		return ret;
+	if (!drm_atomic_crtc_needs_modeset(&asyh->state)) {
+		if (asyh->core.visible) {
+			if (memcmp(&armh->core, &asyh->core, sizeof(asyh->core)))
+				asyh->set.core = true;
+		} else
+		if (armh->core.visible) {
+			asyh->clr.core = true;
+		}
 
-	nv50_display_flip_stop(crtc);
-	nv50_crtc_set_image(nv_crtc, crtc->primary->fb, x, y, true);
-	nv50_display_flip_next(crtc, crtc->primary->fb, NULL, 1);
-	return 0;
-}
+		if (asyh->curs.visible) {
+			if (memcmp(&armh->curs, &asyh->curs, sizeof(asyh->curs)))
+				asyh->set.curs = true;
+		} else
+		if (armh->curs.visible) {
+			asyh->clr.curs = true;
+		}
+	} else {
+		asyh->clr.core = armh->core.visible;
+		asyh->clr.curs = armh->curs.visible;
+		asyh->set.core = asyh->core.visible;
+		asyh->set.curs = asyh->curs.visible;
+	}
 
-static int
-nv50_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);
-	nv50_display_flip_stop(crtc);
-	nv50_crtc_set_image(nv_crtc, fb, x, y, true);
+	if (asyh->clr.mask || asyh->set.mask)
+		nv50_atom(asyh->state.state)->lock_core = true;
 	return 0;
 }
 
 static void
-nv50_crtc_lut_load(struct drm_crtc *crtc)
+nv50_head_lut_load(struct drm_crtc *crtc)
 {
 	struct nv50_disp *disp = nv50_disp(crtc->dev);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -1292,64 +2205,95 @@ nv50_crtc_lut_load(struct drm_crtc *crtc
 	}
 }
 
-static void
-nv50_crtc_disable(struct drm_crtc *crtc)
+static int
+nv50_head_mode_set_base_atomic(struct drm_crtc *crtc,
+			       struct drm_framebuffer *fb, int x, int y,
+			       enum mode_set_atomic state)
 {
-	struct nv50_head *head = nv50_head(crtc);
-	evo_sync(crtc->dev);
-	if (head->image)
-		nouveau_bo_unpin(head->image);
-	nouveau_bo_ref(NULL, &head->image);
+	WARN_ON(1);
+	return 0;
 }
 
+static const struct drm_crtc_helper_funcs
+nv50_head_help = {
+	.mode_set_base_atomic = nv50_head_mode_set_base_atomic,
+	.load_lut = nv50_head_lut_load,
+	.atomic_check = nv50_head_atomic_check,
+};
+
+/* This is identical to the version in the atomic helpers, except that
+ * it supports non-vblanked ("async") page flips.
+ */
 static int
-nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
-		     uint32_t handle, uint32_t width, uint32_t height)
+nv50_head_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+		    struct drm_pending_vblank_event *event, u32 flags)
 {
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct drm_gem_object *gem = NULL;
-	struct nouveau_bo *nvbo = NULL;
+	struct drm_plane *plane = crtc->primary;
+	struct drm_atomic_state *state;
+	struct drm_plane_state *plane_state;
+	struct drm_crtc_state *crtc_state;
 	int ret = 0;
 
-	if (handle) {
-		if (width != 64 || height != 64)
-			return -EINVAL;
+	state = drm_atomic_state_alloc(plane->dev);
+	if (!state)
+		return -ENOMEM;
 
-		gem = drm_gem_object_lookup(file_priv, handle);
-		if (unlikely(!gem))
-			return -ENOENT;
-		nvbo = nouveau_gem_object(gem);
+	state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
+retry:
+	crtc_state = drm_atomic_get_crtc_state(state, crtc);
+	if (IS_ERR(crtc_state)) {
+		ret = PTR_ERR(crtc_state);
+		goto fail;
+	}
+	crtc_state->event = event;
 
-		ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, true);
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state)) {
+		ret = PTR_ERR(plane_state);
+		goto fail;
 	}
 
-	if (ret == 0) {
-		if (nv_crtc->cursor.nvbo)
-			nouveau_bo_unpin(nv_crtc->cursor.nvbo);
-		nouveau_bo_ref(nvbo, &nv_crtc->cursor.nvbo);
+	ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
+	if (ret != 0)
+		goto fail;
+	drm_atomic_set_fb_for_plane(plane_state, fb);
+
+	/* Make sure we don't accidentally do a full modeset. */
+	state->allow_modeset = false;
+	if (!crtc_state->active) {
+		DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n",
+				 crtc->base.id);
+		ret = -EINVAL;
+		goto fail;
 	}
-	drm_gem_object_unreference_unlocked(gem);
 
-	nv50_crtc_cursor_show_hide(nv_crtc, true, true);
+	if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
+		nv50_wndw_atom(plane_state)->interval = 0;
+
+	ret = drm_atomic_nonblocking_commit(state);
+fail:
+	if (ret == -EDEADLK)
+		goto backoff;
+
+	drm_atomic_state_put(state);
 	return ret;
-}
 
-static int
-nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	struct nv50_curs *curs = nv50_curs(crtc);
-	struct nv50_chan *chan = nv50_chan(curs);
-	nvif_wr32(&chan->user, 0x0084, (y << 16) | (x & 0xffff));
-	nvif_wr32(&chan->user, 0x0080, 0x00000000);
+backoff:
+	drm_atomic_state_clear(state);
+	drm_atomic_legacy_backoff(state);
 
-	nv_crtc->cursor_saved_x = x;
-	nv_crtc->cursor_saved_y = y;
-	return 0;
+	/*
+	 * Someone might have exchanged the framebuffer while we dropped locks
+	 * in the backoff code. We need to fix up the fb refcount tracking the
+	 * core does for us.
+	 */
+	plane->old_fb = plane->fb;
+
+	goto retry;
 }
 
 static int
-nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
+nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
 		    uint32_t size)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -1361,47 +2305,71 @@ nv50_crtc_gamma_set(struct drm_crtc *crt
 		nv_crtc->lut.b[i] = b[i];
 	}
 
-	nv50_crtc_lut_load(crtc);
-
+	nv50_head_lut_load(crtc);
 	return 0;
 }
 
 static void
-nv50_crtc_cursor_restore(struct nouveau_crtc *nv_crtc, int x, int y)
+nv50_head_atomic_destroy_state(struct drm_crtc *crtc,
+			       struct drm_crtc_state *state)
 {
-	nv50_crtc_cursor_move(&nv_crtc->base, x, y);
+	struct nv50_head_atom *asyh = nv50_head_atom(state);
+	__drm_atomic_helper_crtc_destroy_state(&asyh->state);
+	kfree(asyh);
+}
 
-	nv50_crtc_cursor_show_hide(nv_crtc, true, true);
+static struct drm_crtc_state *
+nv50_head_atomic_duplicate_state(struct drm_crtc *crtc)
+{
+	struct nv50_head_atom *armh = nv50_head_atom(crtc->state);
+	struct nv50_head_atom *asyh;
+	if (!(asyh = kmalloc(sizeof(*asyh), GFP_KERNEL)))
+		return NULL;
+	__drm_atomic_helper_crtc_duplicate_state(crtc, &asyh->state);
+	asyh->view = armh->view;
+	asyh->mode = armh->mode;
+	asyh->lut  = armh->lut;
+	asyh->core = armh->core;
+	asyh->curs = armh->curs;
+	asyh->base = armh->base;
+	asyh->ovly = armh->ovly;
+	asyh->dither = armh->dither;
+	asyh->procamp = armh->procamp;
+	asyh->clr.mask = 0;
+	asyh->set.mask = 0;
+	return &asyh->state;
 }
 
 static void
-nv50_crtc_destroy(struct drm_crtc *crtc)
+__drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
+			       struct drm_crtc_state *state)
+{
+	if (crtc->state)
+		crtc->funcs->atomic_destroy_state(crtc, crtc->state);
+	crtc->state = state;
+	crtc->state->crtc = crtc;
+}
+
+static void
+nv50_head_reset(struct drm_crtc *crtc)
+{
+	struct nv50_head_atom *asyh;
+
+	if (WARN_ON(!(asyh = kzalloc(sizeof(*asyh), GFP_KERNEL))))
+		return;
+
+	__drm_atomic_helper_crtc_reset(crtc, &asyh->state);
+}
+
+static void
+nv50_head_destroy(struct drm_crtc *crtc)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nv50_disp *disp = nv50_disp(crtc->dev);
 	struct nv50_head *head = nv50_head(crtc);
-	struct nv50_fbdma *fbdma;
-
-	list_for_each_entry(fbdma, &disp->fbdma, head) {
-		nvif_object_fini(&fbdma->base[nv_crtc->index]);
-	}
 
 	nv50_dmac_destroy(&head->ovly.base, disp->disp);
 	nv50_pioc_destroy(&head->oimm.base);
-	nv50_dmac_destroy(&head->sync.base, disp->disp);
-	nv50_pioc_destroy(&head->curs.base);
-
-	/*XXX: this shouldn't be necessary, but the core doesn't call
-	 *     disconnect() during the cleanup paths
-	 */
-	if (head->image)
-		nouveau_bo_unpin(head->image);
-	nouveau_bo_ref(NULL, &head->image);
-
-	/*XXX: ditto */
-	if (nv_crtc->cursor.nvbo)
-		nouveau_bo_unpin(nv_crtc->cursor.nvbo);
-	nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
 
 	nouveau_bo_unmap(nv_crtc->lut.nvbo);
 	if (nv_crtc->lut.nvbo)
@@ -1412,34 +2380,27 @@ nv50_crtc_destroy(struct drm_crtc *crtc)
 	kfree(crtc);
 }
 
-static const struct drm_crtc_helper_funcs nv50_crtc_hfunc = {
-	.dpms = nv50_crtc_dpms,
-	.prepare = nv50_crtc_prepare,
-	.commit = nv50_crtc_commit,
-	.mode_fixup = nv50_crtc_mode_fixup,
-	.mode_set = nv50_crtc_mode_set,
-	.mode_set_base = nv50_crtc_mode_set_base,
-	.mode_set_base_atomic = nv50_crtc_mode_set_base_atomic,
-	.load_lut = nv50_crtc_lut_load,
-	.disable = nv50_crtc_disable,
-};
-
-static const struct drm_crtc_funcs nv50_crtc_func = {
-	.cursor_set = nv50_crtc_cursor_set,
-	.cursor_move = nv50_crtc_cursor_move,
-	.gamma_set = nv50_crtc_gamma_set,
-	.set_config = nouveau_crtc_set_config,
-	.destroy = nv50_crtc_destroy,
-	.page_flip = nouveau_crtc_page_flip,
+static const struct drm_crtc_funcs
+nv50_head_func = {
+	.reset = nv50_head_reset,
+	.gamma_set = nv50_head_gamma_set,
+	.destroy = nv50_head_destroy,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = nv50_head_page_flip,
+	.set_property = drm_atomic_helper_crtc_set_property,
+	.atomic_duplicate_state = nv50_head_atomic_duplicate_state,
+	.atomic_destroy_state = nv50_head_atomic_destroy_state,
 };
 
 static int
-nv50_crtc_create(struct drm_device *dev, int index)
+nv50_head_create(struct drm_device *dev, int index)
 {
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nvif_device *device = &drm->device;
 	struct nv50_disp *disp = nv50_disp(dev);
 	struct nv50_head *head;
+	struct nv50_base *base;
+	struct nv50_curs *curs;
 	struct drm_crtc *crtc;
 	int ret, i;
 
@@ -1448,21 +2409,25 @@ nv50_crtc_create(struct drm_device *dev,
 		return -ENOMEM;
 
 	head->base.index = index;
-	head->base.set_dither = nv50_crtc_set_dither;
-	head->base.set_scale = nv50_crtc_set_scale;
-	head->base.set_color_vibrance = nv50_crtc_set_color_vibrance;
-	head->base.color_vibrance = 50;
-	head->base.vibrant_hue = 0;
-	head->base.cursor.set_pos = nv50_crtc_cursor_restore;
 	for (i = 0; i < 256; i++) {
 		head->base.lut.r[i] = i << 8;
 		head->base.lut.g[i] = i << 8;
 		head->base.lut.b[i] = i << 8;
 	}
 
+	ret = nv50_base_new(drm, head, &base);
+	if (ret == 0)
+		ret = nv50_curs_new(drm, head, &curs);
+	if (ret) {
+		kfree(head);
+		return ret;
+	}
+
 	crtc = &head->base.base;
-	drm_crtc_init(dev, crtc, &nv50_crtc_func);
-	drm_crtc_helper_add(crtc, &nv50_crtc_hfunc);
+	drm_crtc_init_with_planes(dev, crtc, &base->wndw.plane,
+				  &curs->wndw.plane, &nv50_head_func,
+				  "head-%d", head->base.index);
+	drm_crtc_helper_add(crtc, &nv50_head_help);
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
 	ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
@@ -1481,20 +2446,6 @@ nv50_crtc_create(struct drm_device *dev,
 	if (ret)
 		goto out;
 
-	/* allocate cursor resources */
-	ret = nv50_curs_create(device, disp->disp, index, &head->curs);
-	if (ret)
-		goto out;
-
-	/* allocate page flip / sync resources */
-	ret = nv50_base_create(device, disp->disp, index, disp->sync->bo.offset,
-			       &head->sync);
-	if (ret)
-		goto out;
-
-	head->sync.addr = EVO_FLIP_SEM0(index);
-	head->sync.data = 0x00000000;
-
 	/* allocate overlay resources */
 	ret = nv50_oimm_create(device, disp->disp, index, &head->oimm);
 	if (ret)
@@ -1507,43 +2458,64 @@ nv50_crtc_create(struct drm_device *dev,
 
 out:
 	if (ret)
-		nv50_crtc_destroy(crtc);
+		nv50_head_destroy(crtc);
 	return ret;
 }
 
 /******************************************************************************
- * Encoder helpers
+ * Output path helpers
  *****************************************************************************/
-static bool
-nv50_encoder_mode_fixup(struct drm_encoder *encoder,
-			const struct drm_display_mode *mode,
-			struct drm_display_mode *adjusted_mode)
+static int
+nv50_outp_atomic_check_view(struct drm_encoder *encoder,
+			    struct drm_crtc_state *crtc_state,
+			    struct drm_connector_state *conn_state,
+			    struct drm_display_mode *native_mode)
 {
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nouveau_connector *nv_connector;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	struct drm_display_mode *mode = &crtc_state->mode;
+	struct drm_connector *connector = conn_state->connector;
+	struct nouveau_conn_atom *asyc = nouveau_conn_atom(conn_state);
+	struct nouveau_drm *drm = nouveau_drm(encoder->dev);
 
-	nv_connector = nouveau_encoder_connector_get(nv_encoder);
-	if (nv_connector && nv_connector->native_mode) {
-		nv_connector->scaling_full = false;
-		if (nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) {
-			switch (nv_connector->type) {
-			case DCB_CONNECTOR_LVDS:
-			case DCB_CONNECTOR_LVDS_SPWG:
-			case DCB_CONNECTOR_eDP:
-				/* force use of scaler for non-edid modes */
-				if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
-					return true;
-				nv_connector->scaling_full = true;
+	NV_ATOMIC(drm, "%s atomic_check\n", encoder->name);
+	asyc->scaler.full = false;
+	if (!native_mode)
+		return 0;
+
+	if (asyc->scaler.mode == DRM_MODE_SCALE_NONE) {
+		switch (connector->connector_type) {
+		case DRM_MODE_CONNECTOR_LVDS:
+		case DRM_MODE_CONNECTOR_eDP:
+			/* Force use of scaler for non-EDID modes. */
+			if (adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
 				break;
-			default:
-				return true;
-			}
+			mode = native_mode;
+			asyc->scaler.full = true;
+			break;
+		default:
+			break;
 		}
+	} else {
+		mode = native_mode;
+	}
 
-		drm_mode_copy(adjusted_mode, nv_connector->native_mode);
+	if (!drm_mode_equal(adjusted_mode, mode)) {
+		drm_mode_copy(adjusted_mode, mode);
+		crtc_state->mode_changed = true;
 	}
 
-	return true;
+	return 0;
+}
+
+static int
+nv50_outp_atomic_check(struct drm_encoder *encoder,
+		       struct drm_crtc_state *crtc_state,
+		       struct drm_connector_state *conn_state)
+{
+	struct nouveau_connector *nv_connector =
+		nouveau_connector(conn_state->connector);
+	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+					   nv_connector->native_mode);
 }
 
 /******************************************************************************
@@ -1574,21 +2546,39 @@ nv50_dac_dpms(struct drm_encoder *encode
 }
 
 static void
-nv50_dac_commit(struct drm_encoder *encoder)
+nv50_dac_disable(struct drm_encoder *encoder)
 {
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nv50_mast *mast = nv50_mast(encoder->dev);
+	const int or = nv_encoder->or;
+	u32 *push;
+
+	if (nv_encoder->crtc) {
+		push = evo_wait(mast, 4);
+		if (push) {
+			if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
+				evo_mthd(push, 0x0400 + (or * 0x080), 1);
+				evo_data(push, 0x00000000);
+			} else {
+				evo_mthd(push, 0x0180 + (or * 0x020), 1);
+				evo_data(push, 0x00000000);
+			}
+			evo_kick(push, mast);
+		}
+	}
+
+	nv_encoder->crtc = NULL;
 }
 
 static void
-nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
-		  struct drm_display_mode *adjusted_mode)
+nv50_dac_enable(struct drm_encoder *encoder)
 {
 	struct nv50_mast *mast = nv50_mast(encoder->dev);
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct drm_display_mode *mode = &nv_crtc->base.state->adjusted_mode;
 	u32 *push;
 
-	nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON);
-
 	push = evo_wait(mast, 8);
 	if (push) {
 		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
@@ -1627,33 +2617,6 @@ nv50_dac_mode_set(struct drm_encoder *en
 	nv_encoder->crtc = encoder->crtc;
 }
 
-static void
-nv50_dac_disconnect(struct drm_encoder *encoder)
-{
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nv50_mast *mast = nv50_mast(encoder->dev);
-	const int or = nv_encoder->or;
-	u32 *push;
-
-	if (nv_encoder->crtc) {
-		nv50_crtc_prepare(nv_encoder->crtc);
-
-		push = evo_wait(mast, 4);
-		if (push) {
-			if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-				evo_mthd(push, 0x0400 + (or * 0x080), 1);
-				evo_data(push, 0x00000000);
-			} else {
-				evo_mthd(push, 0x0180 + (or * 0x020), 1);
-				evo_data(push, 0x00000000);
-			}
-			evo_kick(push, mast);
-		}
-	}
-
-	nv_encoder->crtc = NULL;
-}
-
 static enum drm_connector_status
 nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 {
@@ -1681,6 +2644,15 @@ nv50_dac_detect(struct drm_encoder *enco
 	return connector_status_connected;
 }
 
+static const struct drm_encoder_helper_funcs
+nv50_dac_help = {
+	.dpms = nv50_dac_dpms,
+	.atomic_check = nv50_outp_atomic_check,
+	.enable = nv50_dac_enable,
+	.disable = nv50_dac_disable,
+	.detect = nv50_dac_detect
+};
+
 static void
 nv50_dac_destroy(struct drm_encoder *encoder)
 {
@@ -1688,18 +2660,8 @@ nv50_dac_destroy(struct drm_encoder *enc
 	kfree(encoder);
 }
 
-static const struct drm_encoder_helper_funcs nv50_dac_hfunc = {
-	.dpms = nv50_dac_dpms,
-	.mode_fixup = nv50_encoder_mode_fixup,
-	.prepare = nv50_dac_disconnect,
-	.commit = nv50_dac_commit,
-	.mode_set = nv50_dac_mode_set,
-	.disable = nv50_dac_disconnect,
-	.get_crtc = nv50_display_crtc_get,
-	.detect = nv50_dac_detect
-};
-
-static const struct drm_encoder_funcs nv50_dac_func = {
+static const struct drm_encoder_funcs
+nv50_dac_func = {
 	.destroy = nv50_dac_destroy,
 };
 
@@ -1726,8 +2688,9 @@ nv50_dac_create(struct drm_connector *co
 	encoder = to_drm_encoder(nv_encoder);
 	encoder->possible_crtcs = dcbe->heads;
 	encoder->possible_clones = 0;
-	drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type, NULL);
-	drm_encoder_helper_add(encoder, &nv50_dac_hfunc);
+	drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type,
+			 "dac-%04x-%04x", dcbe->hasht, dcbe->hashm);
+	drm_encoder_helper_add(encoder, &nv50_dac_help);
 
 	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
@@ -1737,7 +2700,26 @@ nv50_dac_create(struct drm_connector *co
  * Audio
  *****************************************************************************/
 static void
-nv50_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
+nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
+{
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nv50_disp *disp = nv50_disp(encoder->dev);
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_sor_hda_eld_v0 eld;
+	} args = {
+		.base.version = 1,
+		.base.method  = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
+		.base.hasht   = nv_encoder->dcb->hasht,
+		.base.hashm   = (0xf0ff & nv_encoder->dcb->hashm) |
+				(0x0100 << nv_crtc->index),
+	};
+
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
+}
+
+static void
+nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -1768,30 +2750,30 @@ nv50_audio_mode_set(struct drm_encoder *
 		  sizeof(args.base) + drm_eld_size(args.data));
 }
 
+/******************************************************************************
+ * HDMI
+ *****************************************************************************/
 static void
-nv50_audio_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
+nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
 	struct {
 		struct nv50_disp_mthd_v1 base;
-		struct nv50_disp_sor_hda_eld_v0 eld;
+		struct nv50_disp_sor_hdmi_pwr_v0 pwr;
 	} args = {
 		.base.version = 1,
-		.base.method  = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
-		.base.hasht   = nv_encoder->dcb->hasht,
-		.base.hashm   = (0xf0ff & nv_encoder->dcb->hashm) |
-				(0x0100 << nv_crtc->index),
+		.base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
+		.base.hasht  = nv_encoder->dcb->hasht,
+		.base.hashm  = (0xf0ff & nv_encoder->dcb->hashm) |
+			       (0x0100 << nv_crtc->index),
 	};
 
 	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 }
 
-/******************************************************************************
- * HDMI
- *****************************************************************************/
 static void
-nv50_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode)
+nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
@@ -1821,26 +2803,635 @@ nv50_hdmi_mode_set(struct drm_encoder *e
 	args.pwr.max_ac_packet = max_ac_packet / 32;
 
 	nvif_mthd(disp->disp, 0, &args, sizeof(args));
-	nv50_audio_mode_set(encoder, mode);
+	nv50_audio_enable(encoder, mode);
+}
+
+/******************************************************************************
+ * MST
+ *****************************************************************************/
+#define nv50_mstm(p) container_of((p), struct nv50_mstm, mgr)
+#define nv50_mstc(p) container_of((p), struct nv50_mstc, connector)
+#define nv50_msto(p) container_of((p), struct nv50_msto, encoder)
+
+struct nv50_mstm {
+	struct nouveau_encoder *outp;
+
+	struct drm_dp_mst_topology_mgr mgr;
+	struct nv50_msto *msto[4];
+
+	bool modified;
+};
+
+struct nv50_mstc {
+	struct nv50_mstm *mstm;
+	struct drm_dp_mst_port *port;
+	struct drm_connector connector;
+
+	struct drm_display_mode *native;
+	struct edid *edid;
+
+	int pbn;
+};
+
+struct nv50_msto {
+	struct drm_encoder encoder;
+
+	struct nv50_head *head;
+	struct nv50_mstc *mstc;
+	bool disabled;
+};
+
+static struct drm_dp_payload *
+nv50_msto_payload(struct nv50_msto *msto)
+{
+	struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
+	struct nv50_mstc *mstc = msto->mstc;
+	struct nv50_mstm *mstm = mstc->mstm;
+	int vcpi = mstc->port->vcpi.vcpi, i;
+
+	NV_ATOMIC(drm, "%s: vcpi %d\n", msto->encoder.name, vcpi);
+	for (i = 0; i < mstm->mgr.max_payloads; i++) {
+		struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
+		NV_ATOMIC(drm, "%s: %d: vcpi %d start 0x%02x slots 0x%02x\n",
+			  mstm->outp->base.base.name, i, payload->vcpi,
+			  payload->start_slot, payload->num_slots);
+	}
+
+	for (i = 0; i < mstm->mgr.max_payloads; i++) {
+		struct drm_dp_payload *payload = &mstm->mgr.payloads[i];
+		if (payload->vcpi == vcpi)
+			return payload;
+	}
+
+	return NULL;
 }
 
 static void
-nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
+nv50_msto_cleanup(struct nv50_msto *msto)
 {
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nv50_disp *disp = nv50_disp(encoder->dev);
+	struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
+	struct nv50_mstc *mstc = msto->mstc;
+	struct nv50_mstm *mstm = mstc->mstm;
+
+	NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);
+	if (mstc->port && mstc->port->vcpi.vcpi > 0 && !nv50_msto_payload(msto))
+		drm_dp_mst_deallocate_vcpi(&mstm->mgr, mstc->port);
+	if (msto->disabled) {
+		msto->mstc = NULL;
+		msto->head = NULL;
+		msto->disabled = false;
+	}
+}
+
+static void
+nv50_msto_prepare(struct nv50_msto *msto)
+{
+	struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
+	struct nv50_mstc *mstc = msto->mstc;
+	struct nv50_mstm *mstm = mstc->mstm;
 	struct {
 		struct nv50_disp_mthd_v1 base;
-		struct nv50_disp_sor_hdmi_pwr_v0 pwr;
+		struct nv50_disp_sor_dp_mst_vcpi_v0 vcpi;
 	} args = {
 		.base.version = 1,
-		.base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
-		.base.hasht  = nv_encoder->dcb->hasht,
-		.base.hashm  = (0xf0ff & nv_encoder->dcb->hashm) |
-			       (0x0100 << nv_crtc->index),
+		.base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI,
+		.base.hasht  = mstm->outp->dcb->hasht,
+		.base.hashm  = (0xf0ff & mstm->outp->dcb->hashm) |
+			       (0x0100 << msto->head->base.index),
 	};
 
-	nvif_mthd(disp->disp, 0, &args, sizeof(args));
+	NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
+	if (mstc->port && mstc->port->vcpi.vcpi > 0) {
+		struct drm_dp_payload *payload = nv50_msto_payload(msto);
+		if (payload) {
+			args.vcpi.start_slot = payload->start_slot;
+			args.vcpi.num_slots = payload->num_slots;
+			args.vcpi.pbn = mstc->port->vcpi.pbn;
+			args.vcpi.aligned_pbn = mstc->port->vcpi.aligned_pbn;
+		}
+	}
+
+	NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n",
+		  msto->encoder.name, msto->head->base.base.name,
+		  args.vcpi.start_slot, args.vcpi.num_slots,
+		  args.vcpi.pbn, args.vcpi.aligned_pbn);
+	nvif_mthd(&drm->display->disp, 0, &args, sizeof(args));
+}
+
+static int
+nv50_msto_atomic_check(struct drm_encoder *encoder,
+		       struct drm_crtc_state *crtc_state,
+		       struct drm_connector_state *conn_state)
+{
+	struct nv50_mstc *mstc = nv50_mstc(conn_state->connector);
+	struct nv50_mstm *mstm = mstc->mstm;
+	int bpp = conn_state->connector->display_info.bpc * 3;
+	int slots;
+
+	mstc->pbn = drm_dp_calc_pbn_mode(crtc_state->adjusted_mode.clock, bpp);
+
+	slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
+	if (slots < 0)
+		return slots;
+
+	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+					   mstc->native);
+}
+
+static void
+nv50_msto_enable(struct drm_encoder *encoder)
+{
+	struct nv50_head *head = nv50_head(encoder->crtc);
+	struct nv50_msto *msto = nv50_msto(encoder);
+	struct nv50_mstc *mstc = NULL;
+	struct nv50_mstm *mstm = NULL;
+	struct drm_connector *connector;
+	u8 proto, depth;
+	int slots;
+	bool r;
+
+	drm_for_each_connector(connector, encoder->dev) {
+		if (connector->state->best_encoder == &msto->encoder) {
+			mstc = nv50_mstc(connector);
+			mstm = mstc->mstm;
+			break;
+		}
+	}
+
+	if (WARN_ON(!mstc))
+		return;
+
+	r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, &slots);
+	WARN_ON(!r);
+
+	if (mstm->outp->dcb->sorconf.link & 1)
+		proto = 0x8;
+	else
+		proto = 0x9;
+
+	switch (mstc->connector.display_info.bpc) {
+	case  6: depth = 0x2; break;
+	case  8: depth = 0x5; break;
+	case 10:
+	default: depth = 0x6; break;
+	}
+
+	mstm->outp->update(mstm->outp, head->base.index,
+			   &head->base.base.state->adjusted_mode, proto, depth);
+
+	msto->head = head;
+	msto->mstc = mstc;
+	mstm->modified = true;
+}
+
+static void
+nv50_msto_disable(struct drm_encoder *encoder)
+{
+	struct nv50_msto *msto = nv50_msto(encoder);
+	struct nv50_mstc *mstc = msto->mstc;
+	struct nv50_mstm *mstm = mstc->mstm;
+
+	if (mstc->port)
+		drm_dp_mst_reset_vcpi_slots(&mstm->mgr, mstc->port);
+
+	mstm->outp->update(mstm->outp, msto->head->base.index, NULL, 0, 0);
+	mstm->modified = true;
+	msto->disabled = true;
+}
+
+static const struct drm_encoder_helper_funcs
+nv50_msto_help = {
+	.disable = nv50_msto_disable,
+	.enable = nv50_msto_enable,
+	.atomic_check = nv50_msto_atomic_check,
+};
+
+static void
+nv50_msto_destroy(struct drm_encoder *encoder)
+{
+	struct nv50_msto *msto = nv50_msto(encoder);
+	drm_encoder_cleanup(&msto->encoder);
+	kfree(msto);
+}
+
+static const struct drm_encoder_funcs
+nv50_msto = {
+	.destroy = nv50_msto_destroy,
+};
+
+static int
+nv50_msto_new(struct drm_device *dev, u32 heads, const char *name, int id,
+	      struct nv50_msto **pmsto)
+{
+	struct nv50_msto *msto;
+	int ret;
+
+	if (!(msto = *pmsto = kzalloc(sizeof(*msto), GFP_KERNEL)))
+		return -ENOMEM;
+
+	ret = drm_encoder_init(dev, &msto->encoder, &nv50_msto,
+			       DRM_MODE_ENCODER_DPMST, "%s-mst-%d", name, id);
+	if (ret) {
+		kfree(*pmsto);
+		*pmsto = NULL;
+		return ret;
+	}
+
+	drm_encoder_helper_add(&msto->encoder, &nv50_msto_help);
+	msto->encoder.possible_crtcs = heads;
+	return 0;
+}
+
+static struct drm_encoder *
+nv50_mstc_atomic_best_encoder(struct drm_connector *connector,
+			      struct drm_connector_state *connector_state)
+{
+	struct nv50_head *head = nv50_head(connector_state->crtc);
+	struct nv50_mstc *mstc = nv50_mstc(connector);
+	if (mstc->port) {
+		struct nv50_mstm *mstm = mstc->mstm;
+		return &mstm->msto[head->base.index]->encoder;
+	}
+	return NULL;
+}
+
+static struct drm_encoder *
+nv50_mstc_best_encoder(struct drm_connector *connector)
+{
+	struct nv50_mstc *mstc = nv50_mstc(connector);
+	if (mstc->port) {
+		struct nv50_mstm *mstm = mstc->mstm;
+		return &mstm->msto[0]->encoder;
+	}
+	return NULL;
+}
+
+static enum drm_mode_status
+nv50_mstc_mode_valid(struct drm_connector *connector,
+		     struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static int
+nv50_mstc_get_modes(struct drm_connector *connector)
+{
+	struct nv50_mstc *mstc = nv50_mstc(connector);
+	int ret = 0;
+
+	mstc->edid = drm_dp_mst_get_edid(&mstc->connector, mstc->port->mgr, mstc->port);
+	drm_mode_connector_update_edid_property(&mstc->connector, mstc->edid);
+	if (mstc->edid) {
+		ret = drm_add_edid_modes(&mstc->connector, mstc->edid);
+		drm_edid_to_eld(&mstc->connector, mstc->edid);
+	}
+
+	if (!mstc->connector.display_info.bpc)
+		mstc->connector.display_info.bpc = 8;
+
+	if (mstc->native)
+		drm_mode_destroy(mstc->connector.dev, mstc->native);
+	mstc->native = nouveau_conn_native_mode(&mstc->connector);
+	return ret;
+}
+
+static const struct drm_connector_helper_funcs
+nv50_mstc_help = {
+	.get_modes = nv50_mstc_get_modes,
+	.mode_valid = nv50_mstc_mode_valid,
+	.best_encoder = nv50_mstc_best_encoder,
+	.atomic_best_encoder = nv50_mstc_atomic_best_encoder,
+};
+
+static enum drm_connector_status
+nv50_mstc_detect(struct drm_connector *connector, bool force)
+{
+	struct nv50_mstc *mstc = nv50_mstc(connector);
+	if (!mstc->port)
+		return connector_status_disconnected;
+	return drm_dp_mst_detect_port(connector, mstc->port->mgr, mstc->port);
+}
+
+static void
+nv50_mstc_destroy(struct drm_connector *connector)
+{
+	struct nv50_mstc *mstc = nv50_mstc(connector);
+	drm_connector_cleanup(&mstc->connector);
+	kfree(mstc);
+}
+
+static const struct drm_connector_funcs
+nv50_mstc = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.reset = nouveau_conn_reset,
+	.detect = nv50_mstc_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = drm_atomic_helper_connector_set_property,
+	.destroy = nv50_mstc_destroy,
+	.atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
+	.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
+	.atomic_set_property = nouveau_conn_atomic_set_property,
+	.atomic_get_property = nouveau_conn_atomic_get_property,
+};
+
+static int
+nv50_mstc_new(struct nv50_mstm *mstm, struct drm_dp_mst_port *port,
+	      const char *path, struct nv50_mstc **pmstc)
+{
+	struct drm_device *dev = mstm->outp->base.base.dev;
+	struct nv50_mstc *mstc;
+	int ret, i;
+
+	if (!(mstc = *pmstc = kzalloc(sizeof(*mstc), GFP_KERNEL)))
+		return -ENOMEM;
+	mstc->mstm = mstm;
+	mstc->port = port;
+
+	ret = drm_connector_init(dev, &mstc->connector, &nv50_mstc,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret) {
+		kfree(*pmstc);
+		*pmstc = NULL;
+		return ret;
+	}
+
+	drm_connector_helper_add(&mstc->connector, &nv50_mstc_help);
+
+	mstc->connector.funcs->reset(&mstc->connector);
+	nouveau_conn_attach_properties(&mstc->connector);
+
+	for (i = 0; i < ARRAY_SIZE(mstm->msto) && mstm->msto; i++)
+		drm_mode_connector_attach_encoder(&mstc->connector, &mstm->msto[i]->encoder);
+
+	drm_object_attach_property(&mstc->connector.base, dev->mode_config.path_property, 0);
+	drm_object_attach_property(&mstc->connector.base, dev->mode_config.tile_property, 0);
+	drm_mode_connector_set_path_property(&mstc->connector, path);
+	return 0;
+}
+
+static void
+nv50_mstm_cleanup(struct nv50_mstm *mstm)
+{
+	struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev);
+	struct drm_encoder *encoder;
+	int ret;
+
+	NV_ATOMIC(drm, "%s: mstm cleanup\n", mstm->outp->base.base.name);
+	ret = drm_dp_check_act_status(&mstm->mgr);
+
+	ret = drm_dp_update_payload_part2(&mstm->mgr);
+
+	drm_for_each_encoder(encoder, mstm->outp->base.base.dev) {
+		if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
+			struct nv50_msto *msto = nv50_msto(encoder);
+			struct nv50_mstc *mstc = msto->mstc;
+			if (mstc && mstc->mstm == mstm)
+				nv50_msto_cleanup(msto);
+		}
+	}
+
+	mstm->modified = false;
+}
+
+static void
+nv50_mstm_prepare(struct nv50_mstm *mstm)
+{
+	struct nouveau_drm *drm = nouveau_drm(mstm->outp->base.base.dev);
+	struct drm_encoder *encoder;
+	int ret;
+
+	NV_ATOMIC(drm, "%s: mstm prepare\n", mstm->outp->base.base.name);
+	ret = drm_dp_update_payload_part1(&mstm->mgr);
+
+	drm_for_each_encoder(encoder, mstm->outp->base.base.dev) {
+		if (encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
+			struct nv50_msto *msto = nv50_msto(encoder);
+			struct nv50_mstc *mstc = msto->mstc;
+			if (mstc && mstc->mstm == mstm)
+				nv50_msto_prepare(msto);
+		}
+	}
+}
+
+static void
+nv50_mstm_hotplug(struct drm_dp_mst_topology_mgr *mgr)
+{
+	struct nv50_mstm *mstm = nv50_mstm(mgr);
+	drm_kms_helper_hotplug_event(mstm->outp->base.base.dev);
+}
+
+static void
+nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
+			    struct drm_connector *connector)
+{
+	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+	struct nv50_mstc *mstc = nv50_mstc(connector);
+
+	drm_connector_unregister(&mstc->connector);
+
+	drm_modeset_lock_all(drm->dev);
+	drm_fb_helper_remove_one_connector(&drm->fbcon->helper, &mstc->connector);
+	mstc->port = NULL;
+	drm_modeset_unlock_all(drm->dev);
+
+	drm_connector_unreference(&mstc->connector);
+}
+
+static void
+nv50_mstm_register_connector(struct drm_connector *connector)
+{
+	struct nouveau_drm *drm = nouveau_drm(connector->dev);
+
+	drm_modeset_lock_all(drm->dev);
+	drm_fb_helper_add_one_connector(&drm->fbcon->helper, connector);
+	drm_modeset_unlock_all(drm->dev);
+
+	drm_connector_register(connector);
+}
+
+static struct drm_connector *
+nv50_mstm_add_connector(struct drm_dp_mst_topology_mgr *mgr,
+			struct drm_dp_mst_port *port, const char *path)
+{
+	struct nv50_mstm *mstm = nv50_mstm(mgr);
+	struct nv50_mstc *mstc;
+	int ret;
+
+	ret = nv50_mstc_new(mstm, port, path, &mstc);
+	if (ret) {
+		if (mstc)
+			mstc->connector.funcs->destroy(&mstc->connector);
+		return NULL;
+	}
+
+	return &mstc->connector;
+}
+
+static const struct drm_dp_mst_topology_cbs
+nv50_mstm = {
+	.add_connector = nv50_mstm_add_connector,
+	.register_connector = nv50_mstm_register_connector,
+	.destroy_connector = nv50_mstm_destroy_connector,
+	.hotplug = nv50_mstm_hotplug,
+};
+
+void
+nv50_mstm_service(struct nv50_mstm *mstm)
+{
+	struct drm_dp_aux *aux = mstm->mgr.aux;
+	bool handled = true;
+	int ret;
+	u8 esi[8] = {};
+
+	while (handled) {
+		ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8);
+		if (ret != 8) {
+			drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false);
+			return;
+		}
+
+		drm_dp_mst_hpd_irq(&mstm->mgr, esi, &handled);
+		if (!handled)
+			break;
+
+		drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1], 3);
+	}
+}
+
+void
+nv50_mstm_remove(struct nv50_mstm *mstm)
+{
+	if (mstm)
+		drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false);
+}
+
+static int
+nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state)
+{
+	struct nouveau_encoder *outp = mstm->outp;
+	struct {
+		struct nv50_disp_mthd_v1 base;
+		struct nv50_disp_sor_dp_mst_link_v0 mst;
+	} args = {
+		.base.version = 1,
+		.base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_LINK,
+		.base.hasht = outp->dcb->hasht,
+		.base.hashm = outp->dcb->hashm,
+		.mst.state = state,
+	};
+	struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev);
+	struct nvif_object *disp = &drm->display->disp;
+	int ret;
+
+	if (dpcd >= 0x12) {
+		ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CTRL, &dpcd);
+		if (ret < 0)
+			return ret;
+
+		dpcd &= ~DP_MST_EN;
+		if (state)
+			dpcd |= DP_MST_EN;
+
+		ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, dpcd);
+		if (ret < 0)
+			return ret;
+	}
+
+	return nvif_mthd(disp, 0, &args, sizeof(args));
+}
+
+int
+nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow)
+{
+	int ret, state = 0;
+
+	if (!mstm)
+		return 0;
+
+	if (dpcd[0] >= 0x12) {
+		ret = drm_dp_dpcd_readb(mstm->mgr.aux, DP_MSTM_CAP, &dpcd[1]);
+		if (ret < 0)
+			return ret;
+
+		if (!(dpcd[1] & DP_MST_CAP))
+			dpcd[0] = 0x11;
+		else
+			state = allow;
+	}
+
+	ret = nv50_mstm_enable(mstm, dpcd[0], state);
+	if (ret)
+		return ret;
+
+	ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, state);
+	if (ret)
+		return nv50_mstm_enable(mstm, dpcd[0], 0);
+
+	return mstm->mgr.mst_state;
+}
+
+static void
+nv50_mstm_fini(struct nv50_mstm *mstm)
+{
+	if (mstm && mstm->mgr.mst_state)
+		drm_dp_mst_topology_mgr_suspend(&mstm->mgr);
+}
+
+static void
+nv50_mstm_init(struct nv50_mstm *mstm)
+{
+	if (mstm && mstm->mgr.mst_state)
+		drm_dp_mst_topology_mgr_resume(&mstm->mgr);
+}
+
+static void
+nv50_mstm_del(struct nv50_mstm **pmstm)
+{
+	struct nv50_mstm *mstm = *pmstm;
+	if (mstm) {
+		kfree(*pmstm);
+		*pmstm = NULL;
+	}
+}
+
+static int
+nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max,
+	      int conn_base_id, struct nv50_mstm **pmstm)
+{
+	const int max_payloads = hweight8(outp->dcb->heads);
+	struct drm_device *dev = outp->base.base.dev;
+	struct nv50_mstm *mstm;
+	int ret, i;
+	u8 dpcd;
+
+	/* This is a workaround for some monitors not functioning
+	 * correctly in MST mode on initial module load.  I think
+	 * some bad interaction with the VBIOS may be responsible.
+	 *
+	 * A good ol' off and on again seems to work here ;)
+	 */
+	ret = drm_dp_dpcd_readb(aux, DP_DPCD_REV, &dpcd);
+	if (ret >= 0 && dpcd >= 0x12)
+		drm_dp_dpcd_writeb(aux, DP_MSTM_CTRL, 0);
+
+	if (!(mstm = *pmstm = kzalloc(sizeof(*mstm), GFP_KERNEL)))
+		return -ENOMEM;
+	mstm->outp = outp;
+	mstm->mgr.cbs = &nv50_mstm;
+
+	ret = drm_dp_mst_topology_mgr_init(&mstm->mgr, dev->dev, aux, aux_max,
+					   max_payloads, conn_base_id);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < max_payloads; i++) {
+		ret = nv50_msto_new(dev, outp->dcb->heads, outp->base.base.name,
+				    i, &mstm->msto[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 /******************************************************************************
@@ -1861,89 +3452,91 @@ nv50_sor_dpms(struct drm_encoder *encode
 		.base.hashm  = nv_encoder->dcb->hashm,
 		.pwr.state = mode == DRM_MODE_DPMS_ON,
 	};
-	struct {
-		struct nv50_disp_mthd_v1 base;
-		struct nv50_disp_sor_dp_pwr_v0 pwr;
-	} link = {
-		.base.version = 1,
-		.base.method = NV50_DISP_MTHD_V1_SOR_DP_PWR,
-		.base.hasht  = nv_encoder->dcb->hasht,
-		.base.hashm  = nv_encoder->dcb->hashm,
-		.pwr.state = mode == DRM_MODE_DPMS_ON,
-	};
-	struct drm_device *dev = encoder->dev;
-	struct drm_encoder *partner;
-
-	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;
+	nvif_mthd(disp->disp, 0, &args, sizeof(args));
+}
 
-		if (nv_partner != nv_encoder &&
-		    nv_partner->dcb->or == nv_encoder->dcb->or) {
-			if (nv_partner->last_dpms == DRM_MODE_DPMS_ON)
-				return;
-			break;
-		}
-	}
+static void
+nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head,
+		struct drm_display_mode *mode, u8 proto, u8 depth)
+{
+	struct nv50_dmac *core = &nv50_mast(nv_encoder->base.base.dev)->base;
+	u32 *push;
 
-	if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
-		args.pwr.state = 1;
-		nvif_mthd(disp->disp, 0, &args, sizeof(args));
-		nvif_mthd(disp->disp, 0, &link, sizeof(link));
+	if (!mode) {
+		nv_encoder->ctrl &= ~BIT(head);
+		if (!(nv_encoder->ctrl & 0x0000000f))
+			nv_encoder->ctrl = 0;
 	} else {
-		nvif_mthd(disp->disp, 0, &args, sizeof(args));
+		nv_encoder->ctrl |= proto << 8;
+		nv_encoder->ctrl |= BIT(head);
 	}
-}
 
-static void
-nv50_sor_ctrl(struct nouveau_encoder *nv_encoder, u32 mask, u32 data)
-{
-	struct nv50_mast *mast = nv50_mast(nv_encoder->base.base.dev);
-	u32 temp = (nv_encoder->ctrl & ~mask) | (data & mask), *push;
-	if (temp != nv_encoder->ctrl && (push = evo_wait(mast, 2))) {
-		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
+	if ((push = evo_wait(core, 6))) {
+		if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) {
+			if (mode) {
+				if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+					nv_encoder->ctrl |= 0x00001000;
+				if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+					nv_encoder->ctrl |= 0x00002000;
+				nv_encoder->ctrl |= depth << 16;
+			}
 			evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1);
-			evo_data(push, (nv_encoder->ctrl = temp));
 		} else {
+			if (mode) {
+				u32 magic = 0x31ec6000 | (head << 25);
+				u32 syncs = 0x00000001;
+				if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+					syncs |= 0x00000008;
+				if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+					syncs |= 0x00000010;
+				if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+					magic |= 0x00000001;
+
+				evo_mthd(push, 0x0404 + (head * 0x300), 2);
+				evo_data(push, syncs | (depth << 6));
+				evo_data(push, magic);
+			}
 			evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1);
-			evo_data(push, (nv_encoder->ctrl = temp));
 		}
-		evo_kick(push, mast);
+		evo_data(push, nv_encoder->ctrl);
+		evo_kick(push, core);
 	}
 }
 
 static void
-nv50_sor_disconnect(struct drm_encoder *encoder)
+nv50_sor_disable(struct drm_encoder *encoder)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc);
 
-	nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
 	nv_encoder->crtc = NULL;
 
 	if (nv_crtc) {
-		nv50_crtc_prepare(&nv_crtc->base);
-		nv50_sor_ctrl(nv_encoder, 1 << nv_crtc->index, 0);
-		nv50_audio_disconnect(encoder, nv_crtc);
-		nv50_hdmi_disconnect(&nv_encoder->base.base, nv_crtc);
-	}
-}
+		struct nvkm_i2c_aux *aux = nv_encoder->aux;
+		u8 pwr;
 
-static void
-nv50_sor_commit(struct drm_encoder *encoder)
-{
+		if (aux) {
+			int ret = nvkm_rdaux(aux, DP_SET_POWER, &pwr, 1);
+			if (ret == 0) {
+				pwr &= ~DP_SET_POWER_MASK;
+				pwr |=  DP_SET_POWER_D3;
+				nvkm_wraux(aux, DP_SET_POWER, &pwr, 1);
+			}
+		}
+
+		nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0);
+		nv50_audio_disable(encoder, nv_crtc);
+		nv50_hdmi_disable(&nv_encoder->base.base, nv_crtc);
+	}
 }
 
 static void
-nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
-		  struct drm_display_mode *mode)
+nv50_sor_enable(struct drm_encoder *encoder)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
+	struct drm_display_mode *mode = &nv_crtc->base.state->adjusted_mode;
 	struct {
 		struct nv50_disp_mthd_v1 base;
 		struct nv50_disp_sor_lvds_script_v0 lvds;
@@ -1954,13 +3547,10 @@ nv50_sor_mode_set(struct drm_encoder *en
 		.base.hashm   = nv_encoder->dcb->hashm,
 	};
 	struct nv50_disp *disp = nv50_disp(encoder->dev);
-	struct nv50_mast *mast = nv50_mast(encoder->dev);
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_connector *nv_connector;
 	struct nvbios *bios = &drm->vbios;
-	u32 mask, ctrl;
-	u8 owner = 1 << nv_crtc->index;
 	u8 proto = 0xf;
 	u8 depth = 0x0;
 
@@ -1985,7 +3575,7 @@ nv50_sor_mode_set(struct drm_encoder *en
 			proto = 0x2;
 		}
 
-		nv50_hdmi_mode_set(&nv_encoder->base.base, mode);
+		nv50_hdmi_enable(&nv_encoder->base.base, mode);
 		break;
 	case DCB_OUTPUT_LVDS:
 		proto = 0x0;
@@ -2019,94 +3609,60 @@ nv50_sor_mode_set(struct drm_encoder *en
 		nvif_mthd(disp->disp, 0, &lvds, sizeof(lvds));
 		break;
 	case DCB_OUTPUT_DP:
-		if (nv_connector->base.display_info.bpc == 6) {
-			nv_encoder->dp.datarate = mode->clock * 18 / 8;
+		if (nv_connector->base.display_info.bpc == 6)
 			depth = 0x2;
-		} else
-		if (nv_connector->base.display_info.bpc == 8) {
-			nv_encoder->dp.datarate = mode->clock * 24 / 8;
+		else
+		if (nv_connector->base.display_info.bpc == 8)
 			depth = 0x5;
-		} else {
-			nv_encoder->dp.datarate = mode->clock * 30 / 8;
+		else
 			depth = 0x6;
-		}
 
 		if (nv_encoder->dcb->sorconf.link & 1)
 			proto = 0x8;
 		else
 			proto = 0x9;
-		nv50_audio_mode_set(encoder, mode);
+
+		nv50_audio_enable(encoder, mode);
 		break;
 	default:
 		BUG_ON(1);
 		break;
 	}
 
-	nv50_sor_dpms(&nv_encoder->base.base, DRM_MODE_DPMS_ON);
-
-	if (nv50_vers(mast) >= GF110_DISP) {
-		u32 *push = evo_wait(mast, 3);
-		if (push) {
-			u32 magic = 0x31ec6000 | (nv_crtc->index << 25);
-			u32 syncs = 0x00000001;
-
-			if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-				syncs |= 0x00000008;
-			if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-				syncs |= 0x00000010;
-
-			if (mode->flags & DRM_MODE_FLAG_INTERLACE)
-				magic |= 0x00000001;
-
-			evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2);
-			evo_data(push, syncs | (depth << 6));
-			evo_data(push, magic);
-			evo_kick(push, mast);
-		}
-
-		ctrl = proto << 8;
-		mask = 0x00000f00;
-	} else {
-		ctrl = (depth << 16) | (proto << 8);
-		if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-			ctrl |= 0x00001000;
-		if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-			ctrl |= 0x00002000;
-		mask = 0x000f3f00;
-	}
-
-	nv50_sor_ctrl(nv_encoder, mask | owner, ctrl | owner);
+	nv_encoder->update(nv_encoder, nv_crtc->index, mode, proto, depth);
 }
 
+static const struct drm_encoder_helper_funcs
+nv50_sor_help = {
+	.dpms = nv50_sor_dpms,
+	.atomic_check = nv50_outp_atomic_check,
+	.enable = nv50_sor_enable,
+	.disable = nv50_sor_disable,
+};
+
 static void
 nv50_sor_destroy(struct drm_encoder *encoder)
 {
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	nv50_mstm_del(&nv_encoder->dp.mstm);
 	drm_encoder_cleanup(encoder);
 	kfree(encoder);
 }
 
-static const struct drm_encoder_helper_funcs nv50_sor_hfunc = {
-	.dpms = nv50_sor_dpms,
-	.mode_fixup = nv50_encoder_mode_fixup,
-	.prepare = nv50_sor_disconnect,
-	.commit = nv50_sor_commit,
-	.mode_set = nv50_sor_mode_set,
-	.disable = nv50_sor_disconnect,
-	.get_crtc = nv50_display_crtc_get,
-};
-
-static const struct drm_encoder_funcs nv50_sor_func = {
+static const struct drm_encoder_funcs
+nv50_sor_func = {
 	.destroy = nv50_sor_destroy,
 };
 
 static int
 nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe)
 {
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_drm *drm = nouveau_drm(connector->dev);
 	struct nvkm_i2c *i2c = nvxx_i2c(&drm->device);
 	struct nouveau_encoder *nv_encoder;
 	struct drm_encoder *encoder;
-	int type;
+	int type, ret;
 
 	switch (dcbe->type) {
 	case DCB_OUTPUT_LVDS: type = DRM_MODE_ENCODER_LVDS; break;
@@ -2122,7 +3678,16 @@ nv50_sor_create(struct drm_connector *co
 		return -ENOMEM;
 	nv_encoder->dcb = dcbe;
 	nv_encoder->or = ffs(dcbe->or) - 1;
-	nv_encoder->last_dpms = DRM_MODE_DPMS_OFF;
+	nv_encoder->update = nv50_sor_update;
+
+	encoder = to_drm_encoder(nv_encoder);
+	encoder->possible_crtcs = dcbe->heads;
+	encoder->possible_clones = 0;
+	drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type,
+			 "sor-%04x-%04x", dcbe->hasht, dcbe->hashm);
+	drm_encoder_helper_add(encoder, &nv50_sor_help);
+
+	drm_mode_connector_attach_encoder(connector, encoder);
 
 	if (dcbe->type == DCB_OUTPUT_DP) {
 		struct nvkm_i2c_aux *aux =
@@ -2131,6 +3696,15 @@ nv50_sor_create(struct drm_connector *co
 			nv_encoder->i2c = &aux->i2c;
 			nv_encoder->aux = aux;
 		}
+
+		/*TODO: Use DP Info Table to check for support. */
+		if (nv50_disp(encoder->dev)->disp->oclass >= GF110_DISP) {
+			ret = nv50_mstm_new(nv_encoder, &nv_connector->aux, 16,
+					    nv_connector->base.base.id,
+					    &nv_encoder->dp.mstm);
+			if (ret)
+				return ret;
+		}
 	} else {
 		struct nvkm_i2c_bus *bus =
 			nvkm_i2c_bus_find(i2c, dcbe->i2c_index);
@@ -2138,20 +3712,12 @@ nv50_sor_create(struct drm_connector *co
 			nv_encoder->i2c = &bus->i2c;
 	}
 
-	encoder = to_drm_encoder(nv_encoder);
-	encoder->possible_crtcs = dcbe->heads;
-	encoder->possible_clones = 0;
-	drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type, NULL);
-	drm_encoder_helper_add(encoder, &nv50_sor_hfunc);
-
-	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
 }
 
 /******************************************************************************
  * PIOR
  *****************************************************************************/
-
 static void
 nv50_pior_dpms(struct drm_encoder *encoder, int mode)
 {
@@ -2172,30 +3738,48 @@ nv50_pior_dpms(struct drm_encoder *encod
 	nvif_mthd(disp->disp, 0, &args, sizeof(args));
 }
 
-static bool
-nv50_pior_mode_fixup(struct drm_encoder *encoder,
-		     const struct drm_display_mode *mode,
-		     struct drm_display_mode *adjusted_mode)
+static int
+nv50_pior_atomic_check(struct drm_encoder *encoder,
+		       struct drm_crtc_state *crtc_state,
+		       struct drm_connector_state *conn_state)
 {
-	if (!nv50_encoder_mode_fixup(encoder, mode, adjusted_mode))
-		return false;
-	adjusted_mode->clock *= 2;
-	return true;
+	int ret = nv50_outp_atomic_check(encoder, crtc_state, conn_state);
+	if (ret)
+		return ret;
+	crtc_state->adjusted_mode.clock *= 2;
+	return 0;
 }
 
 static void
-nv50_pior_commit(struct drm_encoder *encoder)
+nv50_pior_disable(struct drm_encoder *encoder)
 {
+	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
+	struct nv50_mast *mast = nv50_mast(encoder->dev);
+	const int or = nv_encoder->or;
+	u32 *push;
+
+	if (nv_encoder->crtc) {
+		push = evo_wait(mast, 4);
+		if (push) {
+			if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
+				evo_mthd(push, 0x0700 + (or * 0x040), 1);
+				evo_data(push, 0x00000000);
+			}
+			evo_kick(push, mast);
+		}
+	}
+
+	nv_encoder->crtc = NULL;
 }
 
 static void
-nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
-		   struct drm_display_mode *adjusted_mode)
+nv50_pior_enable(struct drm_encoder *encoder)
 {
 	struct nv50_mast *mast = nv50_mast(encoder->dev);
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
 	struct nouveau_connector *nv_connector;
+	struct drm_display_mode *mode = &nv_crtc->base.state->adjusted_mode;
 	u8 owner = 1 << nv_crtc->index;
 	u8 proto, depth;
 	u32 *push;
@@ -2218,8 +3802,6 @@ nv50_pior_mode_set(struct drm_encoder *e
 		break;
 	}
 
-	nv50_pior_dpms(encoder, DRM_MODE_DPMS_ON);
-
 	push = evo_wait(mast, 8);
 	if (push) {
 		if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
@@ -2238,29 +3820,13 @@ nv50_pior_mode_set(struct drm_encoder *e
 	nv_encoder->crtc = encoder->crtc;
 }
 
-static void
-nv50_pior_disconnect(struct drm_encoder *encoder)
-{
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	struct nv50_mast *mast = nv50_mast(encoder->dev);
-	const int or = nv_encoder->or;
-	u32 *push;
-
-	if (nv_encoder->crtc) {
-		nv50_crtc_prepare(nv_encoder->crtc);
-
-		push = evo_wait(mast, 4);
-		if (push) {
-			if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) {
-				evo_mthd(push, 0x0700 + (or * 0x040), 1);
-				evo_data(push, 0x00000000);
-			}
-			evo_kick(push, mast);
-		}
-	}
-
-	nv_encoder->crtc = NULL;
-}
+static const struct drm_encoder_helper_funcs
+nv50_pior_help = {
+	.dpms = nv50_pior_dpms,
+	.atomic_check = nv50_pior_atomic_check,
+	.enable = nv50_pior_enable,
+	.disable = nv50_pior_disable,
+};
 
 static void
 nv50_pior_destroy(struct drm_encoder *encoder)
@@ -2269,17 +3835,8 @@ nv50_pior_destroy(struct drm_encoder *en
 	kfree(encoder);
 }
 
-static const struct drm_encoder_helper_funcs nv50_pior_hfunc = {
-	.dpms = nv50_pior_dpms,
-	.mode_fixup = nv50_pior_mode_fixup,
-	.prepare = nv50_pior_disconnect,
-	.commit = nv50_pior_commit,
-	.mode_set = nv50_pior_mode_set,
-	.disable = nv50_pior_disconnect,
-	.get_crtc = nv50_display_crtc_get,
-};
-
-static const struct drm_encoder_funcs nv50_pior_func = {
+static const struct drm_encoder_funcs
+nv50_pior_func = {
 	.destroy = nv50_pior_destroy,
 };
 
@@ -2321,149 +3878,470 @@ nv50_pior_create(struct drm_connector *c
 	encoder = to_drm_encoder(nv_encoder);
 	encoder->possible_crtcs = dcbe->heads;
 	encoder->possible_clones = 0;
-	drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type, NULL);
-	drm_encoder_helper_add(encoder, &nv50_pior_hfunc);
+	drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type,
+			 "pior-%04x-%04x", dcbe->hasht, dcbe->hashm);
+	drm_encoder_helper_add(encoder, &nv50_pior_help);
 
 	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
 }
 
 /******************************************************************************
- * Framebuffer
+ * Atomic
  *****************************************************************************/
 
 static void
-nv50_fbdma_fini(struct nv50_fbdma *fbdma)
+nv50_disp_atomic_commit_core(struct nouveau_drm *drm, u32 interlock)
 {
-	int i;
-	for (i = 0; i < ARRAY_SIZE(fbdma->base); i++)
-		nvif_object_fini(&fbdma->base[i]);
-	nvif_object_fini(&fbdma->core);
-	list_del(&fbdma->head);
-	kfree(fbdma);
+	struct nv50_disp *disp = nv50_disp(drm->dev);
+	struct nv50_dmac *core = &disp->mast.base;
+	struct nv50_mstm *mstm;
+	struct drm_encoder *encoder;
+	u32 *push;
+
+	NV_ATOMIC(drm, "commit core %08x\n", interlock);
+
+	drm_for_each_encoder(encoder, drm->dev) {
+		if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+			mstm = nouveau_encoder(encoder)->dp.mstm;
+			if (mstm && mstm->modified)
+				nv50_mstm_prepare(mstm);
+		}
+	}
+
+	if ((push = evo_wait(core, 5))) {
+		evo_mthd(push, 0x0084, 1);
+		evo_data(push, 0x80000000);
+		evo_mthd(push, 0x0080, 2);
+		evo_data(push, interlock);
+		evo_data(push, 0x00000000);
+		nouveau_bo_wr32(disp->sync, 0, 0x00000000);
+		evo_kick(push, core);
+		if (nvif_msec(&drm->device, 2000ULL,
+			if (nouveau_bo_rd32(disp->sync, 0))
+				break;
+			usleep_range(1, 2);
+		) < 0)
+			NV_ERROR(drm, "EVO timeout\n");
+	}
+
+	drm_for_each_encoder(encoder, drm->dev) {
+		if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+			mstm = nouveau_encoder(encoder)->dp.mstm;
+			if (mstm && mstm->modified)
+				nv50_mstm_cleanup(mstm);
+		}
+	}
 }
 
-static int
-nv50_fbdma_init(struct drm_device *dev, u32 name, u64 offset, u64 length, u8 kind)
+static void
+nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
 {
+	struct drm_device *dev = state->dev;
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	struct drm_plane_state *plane_state;
+	struct drm_plane *plane;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nv50_disp *disp = nv50_disp(dev);
-	struct nv50_mast *mast = nv50_mast(dev);
-	struct __attribute__ ((packed)) {
-		struct nv_dma_v0 base;
-		union {
-			struct nv50_dma_v0 nv50;
-			struct gf100_dma_v0 gf100;
-			struct gf119_dma_v0 gf119;
-		};
-	} args = {};
-	struct nv50_fbdma *fbdma;
-	struct drm_crtc *crtc;
-	u32 size = sizeof(args.base);
-	int ret;
+	struct nv50_atom *atom = nv50_atom(state);
+	struct nv50_outp_atom *outp, *outt;
+	u32 interlock_core = 0;
+	u32 interlock_chan = 0;
+	int i;
 
-	list_for_each_entry(fbdma, &disp->fbdma, head) {
-		if (fbdma->core.handle == name)
-			return 0;
+	NV_ATOMIC(drm, "commit %d %d\n", atom->lock_core, atom->flush_disable);
+	drm_atomic_helper_wait_for_fences(dev, state, false);
+	drm_atomic_helper_wait_for_dependencies(state);
+	drm_atomic_helper_update_legacy_modeset_state(dev, state);
+
+	if (atom->lock_core)
+		mutex_lock(&disp->mutex);
+
+	/* Disable head(s). */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		struct nv50_head_atom *asyh = nv50_head_atom(crtc->state);
+		struct nv50_head *head = nv50_head(crtc);
+
+		NV_ATOMIC(drm, "%s: clr %04x (set %04x)\n", crtc->name,
+			  asyh->clr.mask, asyh->set.mask);
+
+		if (asyh->clr.mask) {
+			nv50_head_flush_clr(head, asyh, atom->flush_disable);
+			interlock_core |= 1;
+		}
 	}
 
-	fbdma = kzalloc(sizeof(*fbdma), GFP_KERNEL);
-	if (!fbdma)
-		return -ENOMEM;
-	list_add(&fbdma->head, &disp->fbdma);
+	/* Disable plane(s). */
+	for_each_plane_in_state(state, plane, plane_state, i) {
+		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
+		struct nv50_wndw *wndw = nv50_wndw(plane);
 
-	args.base.target = NV_DMA_V0_TARGET_VRAM;
-	args.base.access = NV_DMA_V0_ACCESS_RDWR;
-	args.base.start = offset;
-	args.base.limit = offset + length - 1;
+		NV_ATOMIC(drm, "%s: clr %02x (set %02x)\n", plane->name,
+			  asyw->clr.mask, asyw->set.mask);
+		if (!asyw->clr.mask)
+			continue;
 
-	if (drm->device.info.chipset < 0x80) {
-		args.nv50.part = NV50_DMA_V0_PART_256;
-		size += sizeof(args.nv50);
-	} else
-	if (drm->device.info.chipset < 0xc0) {
-		args.nv50.part = NV50_DMA_V0_PART_256;
-		args.nv50.kind = kind;
-		size += sizeof(args.nv50);
-	} else
-	if (drm->device.info.chipset < 0xd0) {
-		args.gf100.kind = kind;
-		size += sizeof(args.gf100);
-	} else {
-		args.gf119.page = GF119_DMA_V0_PAGE_LP;
-		args.gf119.kind = kind;
-		size += sizeof(args.gf119);
+		interlock_chan |= nv50_wndw_flush_clr(wndw, interlock_core,
+						      atom->flush_disable,
+						      asyw);
 	}
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+	/* Disable output path(s). */
+	list_for_each_entry(outp, &atom->outp, head) {
+		const struct drm_encoder_helper_funcs *help;
+		struct drm_encoder *encoder;
+
+		encoder = outp->encoder;
+		help = encoder->helper_private;
+
+		NV_ATOMIC(drm, "%s: clr %02x (set %02x)\n", encoder->name,
+			  outp->clr.mask, outp->set.mask);
+
+		if (outp->clr.mask) {
+			help->disable(encoder);
+			interlock_core |= 1;
+			if (outp->flush_disable) {
+				nv50_disp_atomic_commit_core(drm, interlock_chan);
+				interlock_core = 0;
+				interlock_chan = 0;
+			}
+		}
+	}
+
+	/* Flush disable. */
+	if (interlock_core) {
+		if (atom->flush_disable) {
+			nv50_disp_atomic_commit_core(drm, interlock_chan);
+			interlock_core = 0;
+			interlock_chan = 0;
+		}
+	}
+
+	/* Update output path(s). */
+	list_for_each_entry_safe(outp, outt, &atom->outp, head) {
+		const struct drm_encoder_helper_funcs *help;
+		struct drm_encoder *encoder;
+
+		encoder = outp->encoder;
+		help = encoder->helper_private;
+
+		NV_ATOMIC(drm, "%s: set %02x (clr %02x)\n", encoder->name,
+			  outp->set.mask, outp->clr.mask);
+
+		if (outp->set.mask) {
+			help->enable(encoder);
+			interlock_core = 1;
+		}
+
+		list_del(&outp->head);
+		kfree(outp);
+	}
+
+	/* Update head(s). */
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		struct nv50_head_atom *asyh = nv50_head_atom(crtc->state);
 		struct nv50_head *head = nv50_head(crtc);
-		int ret = nvif_object_init(&head->sync.base.base.user, name,
-					   NV_DMA_IN_MEMORY, &args, size,
-					   &fbdma->base[head->base.index]);
-		if (ret) {
-			nv50_fbdma_fini(fbdma);
-			return ret;
+
+		NV_ATOMIC(drm, "%s: set %04x (clr %04x)\n", crtc->name,
+			  asyh->set.mask, asyh->clr.mask);
+
+		if (asyh->set.mask) {
+			nv50_head_flush_set(head, asyh);
+			interlock_core = 1;
 		}
 	}
 
-	ret = nvif_object_init(&mast->base.base.user, name, NV_DMA_IN_MEMORY,
-			       &args, size, &fbdma->core);
-	if (ret) {
-		nv50_fbdma_fini(fbdma);
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		if (crtc->state->event)
+			drm_crtc_vblank_get(crtc);
+	}
+
+	/* Update plane(s). */
+	for_each_plane_in_state(state, plane, plane_state, i) {
+		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
+		struct nv50_wndw *wndw = nv50_wndw(plane);
+
+		NV_ATOMIC(drm, "%s: set %02x (clr %02x)\n", plane->name,
+			  asyw->set.mask, asyw->clr.mask);
+		if ( !asyw->set.mask &&
+		    (!asyw->clr.mask || atom->flush_disable))
+			continue;
+
+		interlock_chan |= nv50_wndw_flush_set(wndw, interlock_core, asyw);
+	}
+
+	/* Flush update. */
+	if (interlock_core) {
+		if (!interlock_chan && atom->state.legacy_cursor_update) {
+			u32 *push = evo_wait(&disp->mast, 2);
+			if (push) {
+				evo_mthd(push, 0x0080, 1);
+				evo_data(push, 0x00000000);
+				evo_kick(push, &disp->mast);
+			}
+		} else {
+			nv50_disp_atomic_commit_core(drm, interlock_chan);
+		}
+	}
+
+	if (atom->lock_core)
+		mutex_unlock(&disp->mutex);
+
+	/* Wait for HW to signal completion. */
+	for_each_plane_in_state(state, plane, plane_state, i) {
+		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane->state);
+		struct nv50_wndw *wndw = nv50_wndw(plane);
+		int ret = nv50_wndw_wait_armed(wndw, asyw);
+		if (ret)
+			NV_ERROR(drm, "%s: timeout\n", plane->name);
+	}
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		if (crtc->state->event) {
+			unsigned long flags;
+			/* Get correct count/ts if racing with vblank irq */
+			drm_accurate_vblank_count(crtc);
+			spin_lock_irqsave(&crtc->dev->event_lock, flags);
+			drm_crtc_send_vblank_event(crtc, crtc->state->event);
+			spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+			crtc->state->event = NULL;
+			drm_crtc_vblank_put(crtc);
+		}
+	}
+
+	drm_atomic_helper_commit_hw_done(state);
+	drm_atomic_helper_cleanup_planes(dev, state);
+	drm_atomic_helper_commit_cleanup_done(state);
+	drm_atomic_state_put(state);
+}
+
+static void
+nv50_disp_atomic_commit_work(struct work_struct *work)
+{
+	struct drm_atomic_state *state =
+		container_of(work, typeof(*state), commit_work);
+	nv50_disp_atomic_commit_tail(state);
+}
+
+static int
+nv50_disp_atomic_commit(struct drm_device *dev,
+			struct drm_atomic_state *state, bool nonblock)
+{
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nv50_disp *disp = nv50_disp(dev);
+	struct drm_plane_state *plane_state;
+	struct drm_plane *plane;
+	struct drm_crtc *crtc;
+	bool active = false;
+	int ret, i;
+
+	ret = pm_runtime_get_sync(dev->dev);
+	if (ret < 0 && ret != -EACCES)
 		return ret;
+
+	ret = drm_atomic_helper_setup_commit(state, nonblock);
+	if (ret)
+		goto done;
+
+	INIT_WORK(&state->commit_work, nv50_disp_atomic_commit_work);
+
+	ret = drm_atomic_helper_prepare_planes(dev, state);
+	if (ret)
+		goto done;
+
+	if (!nonblock) {
+		ret = drm_atomic_helper_wait_for_fences(dev, state, true);
+		if (ret)
+			goto done;
+	}
+
+	for_each_plane_in_state(state, plane, plane_state, i) {
+		struct nv50_wndw_atom *asyw = nv50_wndw_atom(plane_state);
+		struct nv50_wndw *wndw = nv50_wndw(plane);
+		if (asyw->set.image) {
+			asyw->ntfy.handle = wndw->dmac->sync.handle;
+			asyw->ntfy.offset = wndw->ntfy;
+			asyw->ntfy.awaken = false;
+			asyw->set.ntfy = true;
+			nouveau_bo_wr32(disp->sync, wndw->ntfy / 4, 0x00000000);
+			wndw->ntfy ^= 0x10;
+		}
+	}
+
+	drm_atomic_helper_swap_state(state, true);
+	drm_atomic_state_get(state);
+
+	if (nonblock)
+		queue_work(system_unbound_wq, &state->commit_work);
+	else
+		nv50_disp_atomic_commit_tail(state);
+
+	drm_for_each_crtc(crtc, dev) {
+		if (crtc->state->enable) {
+			if (!drm->have_disp_power_ref) {
+				drm->have_disp_power_ref = true;
+				return ret;
+			}
+			active = true;
+			break;
+		}
+	}
+
+	if (!active && drm->have_disp_power_ref) {
+		pm_runtime_put_autosuspend(dev->dev);
+		drm->have_disp_power_ref = false;
+	}
+
+done:
+	pm_runtime_put_autosuspend(dev->dev);
+	return ret;
+}
+
+static struct nv50_outp_atom *
+nv50_disp_outp_atomic_add(struct nv50_atom *atom, struct drm_encoder *encoder)
+{
+	struct nv50_outp_atom *outp;
+
+	list_for_each_entry(outp, &atom->outp, head) {
+		if (outp->encoder == encoder)
+			return outp;
+	}
+
+	outp = kzalloc(sizeof(*outp), GFP_KERNEL);
+	if (!outp)
+		return ERR_PTR(-ENOMEM);
+
+	list_add(&outp->head, &atom->outp);
+	outp->encoder = encoder;
+	return outp;
+}
+
+static int
+nv50_disp_outp_atomic_check_clr(struct nv50_atom *atom,
+				struct drm_connector *connector)
+{
+	struct drm_encoder *encoder = connector->state->best_encoder;
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	struct nv50_outp_atom *outp;
+
+	if (!(crtc = connector->state->crtc))
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(&atom->state, crtc);
+	if (crtc->state->active && drm_atomic_crtc_needs_modeset(crtc_state)) {
+		outp = nv50_disp_outp_atomic_add(atom, encoder);
+		if (IS_ERR(outp))
+			return PTR_ERR(outp);
+
+		if (outp->encoder->encoder_type == DRM_MODE_ENCODER_DPMST) {
+			outp->flush_disable = true;
+			atom->flush_disable = true;
+		}
+		outp->clr.ctrl = true;
+		atom->lock_core = true;
 	}
 
 	return 0;
 }
 
-static void
-nv50_fb_dtor(struct drm_framebuffer *fb)
+static int
+nv50_disp_outp_atomic_check_set(struct nv50_atom *atom,
+				struct drm_connector_state *connector_state)
 {
+	struct drm_encoder *encoder = connector_state->best_encoder;
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	struct nv50_outp_atom *outp;
+
+	if (!(crtc = connector_state->crtc))
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(&atom->state, crtc);
+	if (crtc_state->active && drm_atomic_crtc_needs_modeset(crtc_state)) {
+		outp = nv50_disp_outp_atomic_add(atom, encoder);
+		if (IS_ERR(outp))
+			return PTR_ERR(outp);
+
+		outp->set.ctrl = true;
+		atom->lock_core = true;
+	}
+
+	return 0;
 }
 
 static int
-nv50_fb_ctor(struct drm_framebuffer *fb)
+nv50_disp_atomic_check(struct drm_device *dev, struct drm_atomic_state *state)
 {
-	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
-	struct nouveau_drm *drm = nouveau_drm(fb->dev);
-	struct nouveau_bo *nvbo = nv_fb->nvbo;
-	struct nv50_disp *disp = nv50_disp(fb->dev);
-	u8 kind = nouveau_bo_tile_layout(nvbo) >> 8;
-	u8 tile = nvbo->tile_mode;
+	struct nv50_atom *atom = nv50_atom(state);
+	struct drm_connector_state *connector_state;
+	struct drm_connector *connector;
+	int ret, i;
 
-	if (drm->device.info.chipset >= 0xc0)
-		tile >>= 4; /* yep.. */
+	ret = drm_atomic_helper_check(dev, state);
+	if (ret)
+		return ret;
 
-	switch (fb->depth) {
-	case  8: nv_fb->r_format = 0x1e00; break;
-	case 15: nv_fb->r_format = 0xe900; break;
-	case 16: nv_fb->r_format = 0xe800; break;
-	case 24:
-	case 32: nv_fb->r_format = 0xcf00; break;
-	case 30: nv_fb->r_format = 0xd100; break;
-	default:
-		 NV_ERROR(drm, "unknown depth %d\n", fb->depth);
-		 return -EINVAL;
+	for_each_connector_in_state(state, connector, connector_state, i) {
+		ret = nv50_disp_outp_atomic_check_clr(atom, connector);
+		if (ret)
+			return ret;
+
+		ret = nv50_disp_outp_atomic_check_set(atom, connector_state);
+		if (ret)
+			return ret;
 	}
 
-	if (disp->disp->oclass < G82_DISP) {
-		nv_fb->r_pitch   = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
-					    (fb->pitches[0] | 0x00100000);
-		nv_fb->r_format |= kind << 16;
-	} else
-	if (disp->disp->oclass < GF110_DISP) {
-		nv_fb->r_pitch  = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
-					   (fb->pitches[0] | 0x00100000);
-	} else {
-		nv_fb->r_pitch  = kind ? (((fb->pitches[0] / 4) << 4) | tile) :
-					   (fb->pitches[0] | 0x01000000);
+	return 0;
+}
+
+static void
+nv50_disp_atomic_state_clear(struct drm_atomic_state *state)
+{
+	struct nv50_atom *atom = nv50_atom(state);
+	struct nv50_outp_atom *outp, *outt;
+
+	list_for_each_entry_safe(outp, outt, &atom->outp, head) {
+		list_del(&outp->head);
+		kfree(outp);
 	}
-	nv_fb->r_handle = 0xffff0000 | kind;
 
-	return nv50_fbdma_init(fb->dev, nv_fb->r_handle, 0,
-			       drm->device.info.ram_user, kind);
+	drm_atomic_state_default_clear(state);
 }
 
+static void
+nv50_disp_atomic_state_free(struct drm_atomic_state *state)
+{
+	struct nv50_atom *atom = nv50_atom(state);
+	drm_atomic_state_default_release(&atom->state);
+	kfree(atom);
+}
+
+static struct drm_atomic_state *
+nv50_disp_atomic_state_alloc(struct drm_device *dev)
+{
+	struct nv50_atom *atom;
+	if (!(atom = kzalloc(sizeof(*atom), GFP_KERNEL)) ||
+	    drm_atomic_state_init(dev, &atom->state) < 0) {
+		kfree(atom);
+		return NULL;
+	}
+	INIT_LIST_HEAD(&atom->outp);
+	return &atom->state;
+}
+
+static const struct drm_mode_config_funcs
+nv50_disp_func = {
+	.fb_create = nouveau_user_framebuffer_create,
+	.output_poll_changed = nouveau_fbcon_output_poll_changed,
+	.atomic_check = nv50_disp_atomic_check,
+	.atomic_commit = nv50_disp_atomic_commit,
+	.atomic_state_alloc = nv50_disp_atomic_state_alloc,
+	.atomic_state_clear = nv50_disp_atomic_state_clear,
+	.atomic_state_free = nv50_disp_atomic_state_free,
+};
+
 /******************************************************************************
  * Init
  *****************************************************************************/
@@ -2471,12 +4349,30 @@ nv50_fb_ctor(struct drm_framebuffer *fb)
 void
 nv50_display_fini(struct drm_device *dev)
 {
+	struct nouveau_encoder *nv_encoder;
+	struct drm_encoder *encoder;
+	struct drm_plane *plane;
+
+	drm_for_each_plane(plane, dev) {
+		struct nv50_wndw *wndw = nv50_wndw(plane);
+		if (plane->funcs != &nv50_wndw)
+			continue;
+		nv50_wndw_fini(wndw);
+	}
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+			nv_encoder = nouveau_encoder(encoder);
+			nv50_mstm_fini(nv_encoder->dp.mstm);
+		}
+	}
 }
 
 int
 nv50_display_init(struct drm_device *dev)
 {
-	struct nv50_disp *disp = nv50_disp(dev);
+	struct drm_encoder *encoder;
+	struct drm_plane *plane;
 	struct drm_crtc *crtc;
 	u32 *push;
 
@@ -2484,16 +4380,35 @@ nv50_display_init(struct drm_device *dev
 	if (!push)
 		return -EBUSY;
 
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct nv50_sync *sync = nv50_sync(crtc);
-
-		nv50_crtc_lut_load(crtc);
-		nouveau_bo_wr32(disp->sync, sync->addr / 4, sync->data);
-	}
-
 	evo_mthd(push, 0x0088, 1);
 	evo_data(push, nv50_mast(dev)->base.sync.handle);
 	evo_kick(push, nv50_mast(dev));
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+		if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) {
+			const struct drm_encoder_helper_funcs *help;
+			struct nouveau_encoder *nv_encoder;
+
+			nv_encoder = nouveau_encoder(encoder);
+			help = encoder->helper_private;
+			if (help && help->dpms)
+				help->dpms(encoder, DRM_MODE_DPMS_ON);
+
+			nv50_mstm_init(nv_encoder->dp.mstm);
+		}
+	}
+
+	drm_for_each_crtc(crtc, dev) {
+		nv50_head_lut_load(crtc);
+	}
+
+	drm_for_each_plane(plane, dev) {
+		struct nv50_wndw *wndw = nv50_wndw(plane);
+		if (plane->funcs != &nv50_wndw)
+			continue;
+		nv50_wndw_init(wndw);
+	}
+
 	return 0;
 }
 
@@ -2501,11 +4416,6 @@ void
 nv50_display_destroy(struct drm_device *dev)
 {
 	struct nv50_disp *disp = nv50_disp(dev);
-	struct nv50_fbdma *fbdma, *fbtmp;
-
-	list_for_each_entry_safe(fbdma, fbtmp, &disp->fbdma, head) {
-		nv50_fbdma_fini(fbdma);
-	}
 
 	nv50_dmac_destroy(&disp->mast.base, disp->disp);
 
@@ -2518,6 +4428,10 @@ nv50_display_destroy(struct drm_device *
 	kfree(disp);
 }
 
+MODULE_PARM_DESC(atomic, "Expose atomic ioctl (default: disabled)");
+static int nouveau_atomic = 0;
+module_param_named(atomic, nouveau_atomic, int, 0400);
+
 int
 nv50_display_create(struct drm_device *dev)
 {
@@ -2532,15 +4446,17 @@ nv50_display_create(struct drm_device *d
 	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
 	if (!disp)
 		return -ENOMEM;
-	INIT_LIST_HEAD(&disp->fbdma);
+
+	mutex_init(&disp->mutex);
 
 	nouveau_display(dev)->priv = disp;
 	nouveau_display(dev)->dtor = nv50_display_destroy;
 	nouveau_display(dev)->init = nv50_display_init;
 	nouveau_display(dev)->fini = nv50_display_fini;
-	nouveau_display(dev)->fb_ctor = nv50_fb_ctor;
-	nouveau_display(dev)->fb_dtor = nv50_fb_dtor;
 	disp->disp = &nouveau_display(dev)->disp;
+	dev->mode_config.funcs = &nv50_disp_func;
+	if (nouveau_atomic)
+		dev->driver->driver_features |= DRIVER_ATOMIC;
 
 	/* small shared memory area we use for notifiers and semaphores */
 	ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
@@ -2572,7 +4488,7 @@ nv50_display_create(struct drm_device *d
 		crtcs = 2;
 
 	for (i = 0; i < crtcs; i++) {
-		ret = nv50_crtc_create(dev, i);
+		ret = nv50_head_create(dev, i);
 		if (ret)
 			goto out;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_display.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_display.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_display.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_display.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,11 +35,4 @@ int  nv50_display_create(struct drm_devi
 void nv50_display_destroy(struct drm_device *);
 int  nv50_display_init(struct drm_device *);
 void nv50_display_fini(struct drm_device *);
-
-void nv50_display_flip_stop(struct drm_crtc *);
-int  nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
-			    struct nouveau_channel *, u32 swap_interval);
-
-struct nouveau_bo *nv50_display_crtc_sema(struct drm_device *, int head);
-
 #endif /* __NV50_DISPLAY_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_fbcon.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@ int
 nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret;
 
@@ -65,7 +65,7 @@ int
 nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret;
 
@@ -93,7 +93,7 @@ int
 nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	uint32_t dwords, *data = (uint32_t *)image->data;
 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
@@ -148,8 +148,8 @@ int
 nv50_fbcon_accel_init(struct fb_info *info)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
-	struct drm_device *dev = nfbdev->dev;
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(nfbdev->helper.fb);
+	struct drm_device *dev = nfbdev->helper.dev;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret, format;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv50_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv50_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,13 +35,12 @@
 static int
 nv50_fence_context_new(struct nouveau_channel *chan)
 {
-	struct drm_device *dev = chan->drm->dev;
 	struct nv10_fence_priv *priv = chan->drm->fence;
 	struct nv10_fence_chan *fctx;
 	struct ttm_mem_reg *mem = &priv->bo->bo.mem;
 	u32 start = mem->start * PAGE_SIZE;
 	u32 limit = start + mem->size - 1;
-	int ret, i;
+	int ret;
 
 	fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
 	if (!fctx)
@@ -60,23 +59,6 @@ nv50_fence_context_new(struct nouveau_ch
 					.limit = limit,
 			       }, sizeof(struct nv_dma_v0),
 			       &fctx->sema);
-
-	/* dma objects for display sync channel semaphore blocks */
-	for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
-		struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
-		u32 start = bo->bo.mem.start * PAGE_SIZE;
-		u32 limit = start + bo->bo.mem.size - 1;
-
-		ret = nvif_object_init(&chan->user, NvEvoSema0 + i,
-				       NV_DMA_IN_MEMORY, &(struct nv_dma_v0) {
-						.target = NV_DMA_V0_TARGET_VRAM,
-						.access = NV_DMA_V0_ACCESS_RDWR,
-						.start = start,
-						.limit = limit,
-				       }, sizeof(struct nv_dma_v0),
-				       &fctx->head[i]);
-	}
-
 	if (ret)
 		nv10_fence_context_del(chan);
 	return ret;
@@ -97,7 +79,7 @@ nv50_fence_create(struct nouveau_drm *dr
 	priv->base.context_new = nv50_fence_context_new;
 	priv->base.context_del = nv10_fence_context_del;
 	priv->base.contexts = 127;
-	priv->base.context_base = fence_context_alloc(priv->base.contexts);
+	priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
 	spin_lock_init(&priv->lock);
 
 	ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv84_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv84_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nv84_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nv84_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,13 +28,6 @@
 
 #include "nv50_display.h"
 
-u64
-nv84_fence_crtc(struct nouveau_channel *chan, int crtc)
-{
-	struct nv84_fence_chan *fctx = chan->fence;
-	return fctx->dispc_vma[crtc].offset;
-}
-
 static int
 nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
 {
@@ -110,19 +103,14 @@ nv84_fence_read(struct nouveau_channel *
 static void
 nv84_fence_context_del(struct nouveau_channel *chan)
 {
-	struct drm_device *dev = chan->drm->dev;
 	struct nv84_fence_priv *priv = chan->drm->fence;
 	struct nv84_fence_chan *fctx = chan->fence;
-	int i;
-
-	for (i = 0; i < dev->mode_config.num_crtc; i++) {
-		struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
-		nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
-	}
 
 	nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
+	mutex_lock(&priv->mutex);
 	nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
 	nouveau_bo_vma_del(priv->bo, &fctx->vma);
+	mutex_unlock(&priv->mutex);
 	nouveau_fence_context_del(&fctx->base);
 	chan->fence = NULL;
 	nouveau_fence_context_free(&fctx->base);
@@ -134,7 +122,7 @@ nv84_fence_context_new(struct nouveau_ch
 	struct nouveau_cli *cli = (void *)chan->user.client;
 	struct nv84_fence_priv *priv = chan->drm->fence;
 	struct nv84_fence_chan *fctx;
-	int ret, i;
+	int ret;
 
 	fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
 	if (!fctx)
@@ -148,17 +136,13 @@ nv84_fence_context_new(struct nouveau_ch
 	fctx->base.sync32 = nv84_fence_sync32;
 	fctx->base.sequence = nv84_fence_read(chan);
 
+	mutex_lock(&priv->mutex);
 	ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma);
 	if (ret == 0) {
 		ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm,
 					&fctx->vma_gart);
 	}
-
-	/* map display semaphore buffers into channel's vm */
-	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
-		struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
-		ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]);
-	}
+	mutex_unlock(&priv->mutex);
 
 	if (ret)
 		nv84_fence_context_del(chan);
@@ -229,9 +213,11 @@ nv84_fence_create(struct nouveau_drm *dr
 	priv->base.context_del = nv84_fence_context_del;
 
 	priv->base.contexts = fifo->nr;
-	priv->base.context_base = fence_context_alloc(priv->base.contexts);
+	priv->base.context_base = dma_fence_context_alloc(priv->base.contexts);
 	priv->base.uevent = true;
 
+	mutex_init(&priv->mutex);
+
 	/* Use VRAM if there is any ; otherwise fallback to system memory */
 	domain = drm->device.info.ram_size != 0 ? TTM_PL_FLAG_VRAM :
 			 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvc0_fbcon.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@ int
 nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret;
 
@@ -65,7 +65,7 @@ int
 nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret;
 
@@ -93,7 +93,7 @@ int
 nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
+	struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
 	struct nouveau_channel *chan = drm->channel;
 	uint32_t dwords, *data = (uint32_t *)image->data;
 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
@@ -148,8 +148,8 @@ int
 nvc0_fbcon_accel_init(struct fb_info *info)
 {
 	struct nouveau_fbdev *nfbdev = info->par;
-	struct drm_device *dev = nfbdev->dev;
-	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
+	struct drm_device *dev = nfbdev->helper.dev;
+	struct nouveau_framebuffer *fb = nouveau_framebuffer(nfbdev->helper.fb);
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_channel *chan = drm->channel;
 	int ret, format;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvif/client.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvif/client.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvif/client.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvif/client.c	2017-02-12 16:03:20.000000000 -0500
@@ -55,7 +55,7 @@ nvif_client_fini(struct nvif_client *cli
 	}
 }
 
-const struct nvif_driver *
+static const struct nvif_driver *
 nvif_drivers[] = {
 #ifdef __KERNEL__
 	&nvif_driver_nvkm,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvif/notify.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvif/notify.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvif/notify.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvif/notify.c	2017-02-12 16:03:20.000000000 -0500
@@ -155,10 +155,8 @@ nvif_notify_fini(struct nvif_notify *not
 	int ret = nvif_notify_put(notify);
 	if (ret >= 0 && object) {
 		ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
-		if (ret == 0) {
-			notify->object = NULL;
-			kfree((void *)notify->data);
-		}
+		notify->object = NULL;
+		kfree((void *)notify->data);
 	}
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/core/firmware.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/core/firmware.c	2016-12-11 17:42:06.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/core/firmware.c	2017-02-12 17:25:23.000000000 -0500
@@ -20,6 +20,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 #include <core/device.h>
+#include <core/firmware.h>
 
 /**
  * nvkm_firmware_get - load firmware from the official nvidia/chip/ directory
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gf100.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gf100_ce_data[] = {
+static uint32_t gf100_ce_data[] = {
 /* 0x0000: ctx_object */
 	0x00000000,
 /* 0x0004: ctx_query_address_high */
@@ -171,7 +171,7 @@ uint32_t gf100_ce_data[] = {
 	0x00000800,
 };
 
-uint32_t gf100_ce_code[] = {
+static uint32_t gf100_ce_code[] = {
 /* 0x0000: main */
 	0x04fe04bd,
 	0x3517f000,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/fuc/gt215.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gt215_ce_data[] = {
+static uint32_t gt215_ce_data[] = {
 /* 0x0000: ctx_object */
 	0x00000000,
 /* 0x0004: ctx_dma */
@@ -183,7 +183,7 @@ uint32_t gt215_ce_data[] = {
 	0x00000800,
 };
 
-uint32_t gt215_ce_code[] = {
+static uint32_t gt215_ce_code[] = {
 /* 0x0000: main */
 	0x04fe04bd,
 	0x3517f000,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 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 "priv.h"
+#include <core/enum.h>
+
+#include <nvif/class.h>
+
+static const struct nvkm_engine_func
+gp102_ce = {
+	.intr = gp100_ce_intr,
+	.sclass = {
+		{ -1, -1, PASCAL_DMA_COPY_B },
+		{ -1, -1, PASCAL_DMA_COPY_A },
+		{}
+	}
+};
+
+int
+gp102_ce_new(struct nvkm_device *device, int index,
+	     struct nvkm_engine **pengine)
+{
+	return nvkm_engine_new_(&gp102_ce, device, index, true, pengine);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/gp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- * Copyright 2015 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 "priv.h"
-#include <core/enum.h>
-
-#include <nvif/class.h>
-
-static const struct nvkm_engine_func
-gp104_ce = {
-	.intr = gp100_ce_intr,
-	.sclass = {
-		{ -1, -1, PASCAL_DMA_COPY_B },
-		{ -1, -1, PASCAL_DMA_COPY_A },
-		{}
-	}
-};
-
-int
-gp104_ce_new(struct nvkm_device *device, int index,
-	     struct nvkm_engine **pengine)
-{
-	return nvkm_engine_new_(&gp104_ce, device, index, true, pengine);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -4,4 +4,4 @@ nvkm-y += nvkm/engine/ce/gk104.o
 nvkm-y += nvkm/engine/ce/gm107.o
 nvkm-y += nvkm/engine/ce/gm200.o
 nvkm-y += nvkm/engine/ce/gp100.o
-nvkm-y += nvkm/engine/ce/gp104.o
+nvkm-y += nvkm/engine/ce/gp102.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -1357,7 +1357,7 @@ nvc0_chipset = {
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.ce[1] = gf100_ce_new,
 	.disp = gt215_disp_new,
@@ -1394,7 +1394,7 @@ nvc1_chipset = {
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.disp = gt215_disp_new,
 	.dma = gf100_dma_new,
@@ -1430,7 +1430,7 @@ nvc3_chipset = {
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.disp = gt215_disp_new,
 	.dma = gf100_dma_new,
@@ -1466,7 +1466,7 @@ nvc4_chipset = {
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.ce[1] = gf100_ce_new,
 	.disp = gt215_disp_new,
@@ -1503,7 +1503,7 @@ nvc8_chipset = {
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.ce[1] = gf100_ce_new,
 	.disp = gt215_disp_new,
@@ -1540,7 +1540,7 @@ nvce_chipset = {
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.ce[1] = gf100_ce_new,
 	.disp = gt215_disp_new,
@@ -1577,7 +1577,7 @@ nvcf_chipset = {
 	.pmu = gf100_pmu_new,
 	.therm = gt215_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.disp = gt215_disp_new,
 	.dma = gf100_dma_new,
@@ -1612,6 +1612,7 @@ nvd7_chipset = {
 	.pci = gf106_pci_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.disp = gf119_disp_new,
 	.dma = gf119_dma_new,
@@ -1647,7 +1648,7 @@ nvd9_chipset = {
 	.pmu = gf119_pmu_new,
 	.therm = gf119_therm_new,
 	.timer = nv41_timer_new,
-	.volt = nv40_volt_new,
+	.volt = gf100_volt_new,
 	.ce[0] = gf100_ce_new,
 	.disp = gf119_disp_new,
 	.dma = gf119_dma_new,
@@ -1851,7 +1852,7 @@ nvf1_chipset = {
 	.fb = gk104_fb_new,
 	.fuse = gf100_fuse_new,
 	.gpio = gk104_gpio_new,
-	.i2c = gf119_i2c_new,
+	.i2c = gk104_i2c_new,
 	.ibus = gk104_ibus_new,
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
@@ -1965,7 +1966,7 @@ nv117_chipset = {
 	.fb = gm107_fb_new,
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
-	.i2c = gf119_i2c_new,
+	.i2c = gk104_i2c_new,
 	.ibus = gk104_ibus_new,
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
@@ -1999,7 +2000,7 @@ nv118_chipset = {
 	.fb = gm107_fb_new,
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
-	.i2c = gf119_i2c_new,
+	.i2c = gk104_i2c_new,
 	.ibus = gk104_ibus_new,
 	.iccsense = gf100_iccsense_new,
 	.imem = nv50_instmem_new,
@@ -2130,7 +2131,7 @@ nv12b_chipset = {
 	.bar = gk20a_bar_new,
 	.bus = gf100_bus_new,
 	.clk = gm20b_clk_new,
-	.fb = gk20a_fb_new,
+	.fb = gm20b_fb_new,
 	.fuse = gm107_fuse_new,
 	.ibus = gk20a_ibus_new,
 	.imem = gk20a_instmem_new,
@@ -2166,6 +2167,7 @@ nv130_chipset = {
 	.mmu = gf100_mmu_new,
 	.secboot = gm200_secboot_new,
 	.pci = gp100_pci_new,
+	.pmu = gp100_pmu_new,
 	.timer = gk20a_timer_new,
 	.top = gk104_top_new,
 	.ce[0] = gp100_ce_new,
@@ -2182,13 +2184,42 @@ nv130_chipset = {
 };
 
 static const struct nvkm_device_chip
+nv132_chipset = {
+	.name = "GP102",
+	.bar = gf100_bar_new,
+	.bios = nvkm_bios_new,
+	.bus = gf100_bus_new,
+	.devinit = gm200_devinit_new,
+	.fb = gp102_fb_new,
+	.fuse = gm107_fuse_new,
+	.gpio = gk104_gpio_new,
+	.i2c = gm200_i2c_new,
+	.ibus = gm200_ibus_new,
+	.imem = nv50_instmem_new,
+	.ltc = gp100_ltc_new,
+	.mc = gp100_mc_new,
+	.mmu = gf100_mmu_new,
+	.pci = gp100_pci_new,
+	.pmu = gp102_pmu_new,
+	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
+	.ce[0] = gp102_ce_new,
+	.ce[1] = gp102_ce_new,
+	.ce[2] = gp102_ce_new,
+	.ce[3] = gp102_ce_new,
+	.disp = gp102_disp_new,
+	.dma = gf119_dma_new,
+	.fifo = gp100_fifo_new,
+};
+
+static const struct nvkm_device_chip
 nv134_chipset = {
 	.name = "GP104",
 	.bar = gf100_bar_new,
 	.bios = nvkm_bios_new,
 	.bus = gf100_bus_new,
 	.devinit = gm200_devinit_new,
-	.fb = gp104_fb_new,
+	.fb = gp102_fb_new,
 	.fuse = gm107_fuse_new,
 	.gpio = gk104_gpio_new,
 	.i2c = gm200_i2c_new,
@@ -2198,13 +2229,43 @@ nv134_chipset = {
 	.mc = gp100_mc_new,
 	.mmu = gf100_mmu_new,
 	.pci = gp100_pci_new,
+	.pmu = gp102_pmu_new,
 	.timer = gk20a_timer_new,
 	.top = gk104_top_new,
-	.ce[0] = gp104_ce_new,
-	.ce[1] = gp104_ce_new,
-	.ce[2] = gp104_ce_new,
-	.ce[3] = gp104_ce_new,
-	.disp = gp104_disp_new,
+	.ce[0] = gp102_ce_new,
+	.ce[1] = gp102_ce_new,
+	.ce[2] = gp102_ce_new,
+	.ce[3] = gp102_ce_new,
+	.disp = gp102_disp_new,
+	.dma = gf119_dma_new,
+	.fifo = gp100_fifo_new,
+};
+
+static const struct nvkm_device_chip
+nv136_chipset = {
+	.name = "GP106",
+	.bar = gf100_bar_new,
+	.bios = nvkm_bios_new,
+	.bus = gf100_bus_new,
+	.devinit = gm200_devinit_new,
+	.fb = gp102_fb_new,
+	.fuse = gm107_fuse_new,
+	.gpio = gk104_gpio_new,
+	.i2c = gm200_i2c_new,
+	.ibus = gm200_ibus_new,
+	.imem = nv50_instmem_new,
+	.ltc = gp100_ltc_new,
+	.mc = gp100_mc_new,
+	.mmu = gf100_mmu_new,
+	.pci = gp100_pci_new,
+	.pmu = gp102_pmu_new,
+	.timer = gk20a_timer_new,
+	.top = gk104_top_new,
+	.ce[0] = gp102_ce_new,
+	.ce[1] = gp102_ce_new,
+	.ce[2] = gp102_ce_new,
+	.ce[3] = gp102_ce_new,
+	.disp = gp102_disp_new,
 	.dma = gf119_dma_new,
 	.fifo = gp100_fifo_new,
 };
@@ -2643,7 +2704,9 @@ nvkm_device_ctor(const struct nvkm_devic
 		case 0x126: device->chip = &nv126_chipset; break;
 		case 0x12b: device->chip = &nv12b_chipset; break;
 		case 0x130: device->chip = &nv130_chipset; break;
+		case 0x132: device->chip = &nv132_chipset; break;
 		case 0x134: device->chip = &nv134_chipset; break;
+		case 0x136: device->chip = &nv136_chipset; break;
 		default:
 			nvdev_error(device, "unknown chipset (%08x)\n", boot0);
 			goto done;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -1665,14 +1665,31 @@ nvkm_device_pci_new(struct pci_dev *pci_
 	*pdevice = &pdev->device;
 	pdev->pdev = pci_dev;
 
-	return nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev,
-				pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE :
-				pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ?
-				NVKM_DEVICE_AGP : NVKM_DEVICE_PCI,
-				(u64)pci_domain_nr(pci_dev->bus) << 32 |
-				     pci_dev->bus->number << 16 |
-				     PCI_SLOT(pci_dev->devfn) << 8 |
-				     PCI_FUNC(pci_dev->devfn), name,
-				cfg, dbg, detect, mmio, subdev_mask,
-				&pdev->device);
+	ret = nvkm_device_ctor(&nvkm_device_pci_func, quirk, &pci_dev->dev,
+			       pci_is_pcie(pci_dev) ? NVKM_DEVICE_PCIE :
+			       pci_find_capability(pci_dev, PCI_CAP_ID_AGP) ?
+			       NVKM_DEVICE_AGP : NVKM_DEVICE_PCI,
+			       (u64)pci_domain_nr(pci_dev->bus) << 32 |
+				    pci_dev->bus->number << 16 |
+				    PCI_SLOT(pci_dev->devfn) << 8 |
+				    PCI_FUNC(pci_dev->devfn), name,
+			       cfg, dbg, detect, mmio, subdev_mask,
+			       &pdev->device);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * Set a preliminary DMA mask based on the .dma_bits member of the
+	 * MMU subdevice. This allows other subdevices to create DMA mappings
+	 * in their init() or oneinit() methods, which may be called before the
+	 * TTM layer sets the DMA mask definitively.
+	 * This is necessary for platforms where the default DMA mask of 32
+	 * does not cover any system memory, i.e., when all RAM is > 4 GB.
+	 */
+	if (pdev->device.mmu)
+		dma_set_mask_and_coherent(&pci_dev->dev,
+				DMA_BIT_MASK(pdev->device.mmu->dma_bits));
+
+	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,7 @@ nvkm_device_tegra_probe_iommu(struct nvk
 
 	if (iommu_present(&platform_bus_type)) {
 		tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
-		if (IS_ERR(tdev->iommu.domain))
+		if (!tdev->iommu.domain)
 			goto error;
 
 		/*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c	2017-02-12 16:03:20.000000000 -0500
@@ -326,7 +326,7 @@ nvkm_udevice = {
 	.sclass = nvkm_udevice_child_get,
 };
 
-int
+static int
 nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
 		 struct nvkm_object **pobject)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "dmacnv50.h"
+#include "rootnv50.h"
+
+#include <nvif/class.h>
+
+const struct nv50_disp_dmac_oclass
+gp102_disp_base_oclass = {
+	.base.oclass = GK110_DISP_BASE_CHANNEL_DMA,
+	.base.minver = 0,
+	.base.maxver = 0,
+	.ctor = nv50_disp_base_new,
+	.func = &gp102_disp_dmac_func,
+	.mthd = &gf119_disp_base_chan_mthd,
+	.chid = 1,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/*
- * Copyright 2016 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 <bskeggs@redhat.com>
- */
-#include "dmacnv50.h"
-#include "rootnv50.h"
-
-#include <nvif/class.h>
-
-const struct nv50_disp_dmac_oclass
-gp104_disp_base_oclass = {
-	.base.oclass = GK110_DISP_BASE_CHANNEL_DMA,
-	.base.minver = 0,
-	.base.maxver = 0,
-	.ctor = nv50_disp_base_new,
-	.func = &gp104_disp_dmac_func,
-	.mthd = &gf119_disp_base_chan_mthd,
-	.chid = 1,
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -82,7 +82,7 @@ nv50_disp_chan_mthd(struct nv50_disp_cha
 
 			if (mthd->addr) {
 				snprintf(cname_, sizeof(cname_), "%s %d",
-					 mthd->name, chan->chid);
+					 mthd->name, chan->chid.user);
 				cname = cname_;
 			}
 
@@ -139,7 +139,7 @@ nv50_disp_chan_uevent_ctor(struct nvkm_o
 	if (!(ret = nvif_unvers(ret, &data, &size, args->none))) {
 		notify->size  = sizeof(struct nvif_notify_uevent_rep);
 		notify->types = 1;
-		notify->index = chan->chid;
+		notify->index = chan->chid.user;
 		return 0;
 	}
 
@@ -153,27 +153,27 @@ nv50_disp_chan_uevent = {
 	.fini = nv50_disp_chan_uevent_fini,
 };
 
-int
+static int
 nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
 {
 	struct nv50_disp_chan *chan = nv50_disp_chan(object);
 	struct nv50_disp *disp = chan->root->disp;
 	struct nvkm_device *device = disp->base.engine.subdev.device;
-	*data = nvkm_rd32(device, 0x640000 + (chan->chid * 0x1000) + addr);
+	*data = nvkm_rd32(device, 0x640000 + (chan->chid.user * 0x1000) + addr);
 	return 0;
 }
 
-int
+static int
 nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
 {
 	struct nv50_disp_chan *chan = nv50_disp_chan(object);
 	struct nv50_disp *disp = chan->root->disp;
 	struct nvkm_device *device = disp->base.engine.subdev.device;
-	nvkm_wr32(device, 0x640000 + (chan->chid * 0x1000) + addr, data);
+	nvkm_wr32(device, 0x640000 + (chan->chid.user * 0x1000) + addr, data);
 	return 0;
 }
 
-int
+static int
 nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
 		    struct nvkm_event **pevent)
 {
@@ -189,14 +189,14 @@ nv50_disp_chan_ntfy(struct nvkm_object *
 	return -EINVAL;
 }
 
-int
+static int
 nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
 {
 	struct nv50_disp_chan *chan = nv50_disp_chan(object);
 	struct nv50_disp *disp = chan->root->disp;
 	struct nvkm_device *device = disp->base.engine.subdev.device;
 	*addr = device->func->resource_addr(device, 0) +
-		0x640000 + (chan->chid * 0x1000);
+		0x640000 + (chan->chid.user * 0x1000);
 	*size = 0x001000;
 	return 0;
 }
@@ -243,8 +243,8 @@ nv50_disp_chan_dtor(struct nvkm_object *
 {
 	struct nv50_disp_chan *chan = nv50_disp_chan(object);
 	struct nv50_disp *disp = chan->root->disp;
-	if (chan->chid >= 0)
-		disp->chan[chan->chid] = NULL;
+	if (chan->chid.user >= 0)
+		disp->chan[chan->chid.user] = NULL;
 	return chan->func->dtor ? chan->func->dtor(chan) : chan;
 }
 
@@ -263,7 +263,7 @@ nv50_disp_chan = {
 int
 nv50_disp_chan_ctor(const struct nv50_disp_chan_func *func,
 		    const struct nv50_disp_chan_mthd *mthd,
-		    struct nv50_disp_root *root, int chid, int head,
+		    struct nv50_disp_root *root, int ctrl, int user, int head,
 		    const struct nvkm_oclass *oclass,
 		    struct nv50_disp_chan *chan)
 {
@@ -273,21 +273,22 @@ nv50_disp_chan_ctor(const struct nv50_di
 	chan->func = func;
 	chan->mthd = mthd;
 	chan->root = root;
-	chan->chid = chid;
+	chan->chid.ctrl = ctrl;
+	chan->chid.user = user;
 	chan->head = head;
 
-	if (disp->chan[chan->chid]) {
-		chan->chid = -1;
+	if (disp->chan[chan->chid.user]) {
+		chan->chid.user = -1;
 		return -EBUSY;
 	}
-	disp->chan[chan->chid] = chan;
+	disp->chan[chan->chid.user] = chan;
 	return 0;
 }
 
 int
 nv50_disp_chan_new_(const struct nv50_disp_chan_func *func,
 		    const struct nv50_disp_chan_mthd *mthd,
-		    struct nv50_disp_root *root, int chid, int head,
+		    struct nv50_disp_root *root, int ctrl, int user, int head,
 		    const struct nvkm_oclass *oclass,
 		    struct nvkm_object **pobject)
 {
@@ -297,5 +298,6 @@ nv50_disp_chan_new_(const struct nv50_di
 		return -ENOMEM;
 	*pobject = &chan->object;
 
-	return nv50_disp_chan_ctor(func, mthd, root, chid, head, oclass, chan);
+	return nv50_disp_chan_ctor(func, mthd, root, ctrl, user,
+				   head, oclass, chan);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,11 @@ struct nv50_disp_chan {
 	const struct nv50_disp_chan_func *func;
 	const struct nv50_disp_chan_mthd *mthd;
 	struct nv50_disp_root *root;
-	int chid;
+
+	struct {
+		int ctrl;
+		int user;
+	} chid;
 	int head;
 
 	struct nvkm_object object;
@@ -25,11 +29,11 @@ struct nv50_disp_chan_func {
 
 int nv50_disp_chan_ctor(const struct nv50_disp_chan_func *,
 			const struct nv50_disp_chan_mthd *,
-			struct nv50_disp_root *, int chid, int head,
+			struct nv50_disp_root *, int ctrl, int user, int head,
 			const struct nvkm_oclass *, struct nv50_disp_chan *);
 int nv50_disp_chan_new_(const struct nv50_disp_chan_func *,
 			const struct nv50_disp_chan_mthd *,
-			struct nv50_disp_root *, int chid, int head,
+			struct nv50_disp_root *, int ctrl, int user, int head,
 			const struct nvkm_oclass *, struct nvkm_object **);
 
 extern const struct nv50_disp_chan_func nv50_disp_pioc_func;
@@ -90,13 +94,16 @@ extern const struct nv50_disp_chan_mthd
 struct nv50_disp_pioc_oclass {
 	int (*ctor)(const struct nv50_disp_chan_func *,
 		    const struct nv50_disp_chan_mthd *,
-		    struct nv50_disp_root *, int chid,
+		    struct nv50_disp_root *, int ctrl, int user,
 		    const struct nvkm_oclass *, void *data, u32 size,
 		    struct nvkm_object **);
 	struct nvkm_sclass base;
 	const struct nv50_disp_chan_func *func;
 	const struct nv50_disp_chan_mthd *mthd;
-	int chid;
+	struct {
+		int ctrl;
+		int user;
+	} chid;
 };
 
 extern const struct nv50_disp_pioc_oclass nv50_disp_oimm_oclass;
@@ -114,15 +121,17 @@ extern const struct nv50_disp_pioc_oclas
 extern const struct nv50_disp_pioc_oclass gk104_disp_oimm_oclass;
 extern const struct nv50_disp_pioc_oclass gk104_disp_curs_oclass;
 
+extern const struct nv50_disp_pioc_oclass gp102_disp_oimm_oclass;
+extern const struct nv50_disp_pioc_oclass gp102_disp_curs_oclass;
 
 int nv50_disp_curs_new(const struct nv50_disp_chan_func *,
 		       const struct nv50_disp_chan_mthd *,
-		       struct nv50_disp_root *, int chid,
+		       struct nv50_disp_root *, int ctrl, int user,
 		       const struct nvkm_oclass *, void *data, u32 size,
 		       struct nvkm_object **);
 int nv50_disp_oimm_new(const struct nv50_disp_chan_func *,
 		       const struct nv50_disp_chan_mthd *,
-		       struct nv50_disp_root *, int chid,
+		       struct nv50_disp_root *, int ctrl, int user,
 		       const struct nvkm_oclass *, void *data, u32 size,
 		       struct nvkm_object **);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@
 
 #include <nvif/class.h>
 
-const struct nv50_disp_mthd_list
+static const struct nv50_disp_mthd_list
 g94_disp_core_mthd_sor = {
 	.mthd = 0x0040,
 	.addr = 0x000008,
@@ -43,8 +43,8 @@ g94_disp_core_chan_mthd = {
 	.prev = 0x000004,
 	.data = {
 		{ "Global", 1, &nv50_disp_core_mthd_base },
-		{    "DAC", 3, &g84_disp_core_mthd_dac  },
-		{    "SOR", 4, &g94_disp_core_mthd_sor  },
+		{    "DAC", 3, &g84_disp_core_mthd_dac },
+		{    "SOR", 4, &g94_disp_core_mthd_sor },
 		{   "PIOR", 3, &nv50_disp_core_mthd_pior },
 		{   "HEAD", 2, &g84_disp_core_mthd_head },
 		{}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "dmacnv50.h"
+#include "rootnv50.h"
+
+#include <subdev/timer.h>
+
+#include <nvif/class.h>
+
+static int
+gp102_disp_core_init(struct nv50_disp_dmac *chan)
+{
+	struct nv50_disp *disp = chan->base.root->disp;
+	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
+	struct nvkm_device *device = subdev->device;
+
+	/* enable error reporting */
+	nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000001);
+
+	/* initialise channel for dma command submission */
+	nvkm_wr32(device, 0x611494, chan->push);
+	nvkm_wr32(device, 0x611498, 0x00010000);
+	nvkm_wr32(device, 0x61149c, 0x00000001);
+	nvkm_mask(device, 0x610490, 0x00000010, 0x00000010);
+	nvkm_wr32(device, 0x640000, 0x00000000);
+	nvkm_wr32(device, 0x610490, 0x01000013);
+
+	/* wait for it to go inactive */
+	if (nvkm_msec(device, 2000,
+		if (!(nvkm_rd32(device, 0x610490) & 0x80000000))
+			break;
+	) < 0) {
+		nvkm_error(subdev, "core init: %08x\n",
+			   nvkm_rd32(device, 0x610490));
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static const struct nv50_disp_dmac_func
+gp102_disp_core_func = {
+	.init = gp102_disp_core_init,
+	.fini = gf119_disp_core_fini,
+	.bind = gf119_disp_dmac_bind,
+};
+
+const struct nv50_disp_dmac_oclass
+gp102_disp_core_oclass = {
+	.base.oclass = GP102_DISP_CORE_CHANNEL_DMA,
+	.base.minver = 0,
+	.base.maxver = 0,
+	.ctor = nv50_disp_core_new,
+	.func = &gp102_disp_core_func,
+	.mthd = &gk104_disp_core_chan_mthd,
+	.chid = 0,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/*
- * Copyright 2016 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 <bskeggs@redhat.com>
- */
-#include "dmacnv50.h"
-#include "rootnv50.h"
-
-#include <subdev/timer.h>
-
-#include <nvif/class.h>
-
-static int
-gp104_disp_core_init(struct nv50_disp_dmac *chan)
-{
-	struct nv50_disp *disp = chan->base.root->disp;
-	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
-	struct nvkm_device *device = subdev->device;
-
-	/* enable error reporting */
-	nvkm_mask(device, 0x6100a0, 0x00000001, 0x00000001);
-
-	/* initialise channel for dma command submission */
-	nvkm_wr32(device, 0x611494, chan->push);
-	nvkm_wr32(device, 0x611498, 0x00010000);
-	nvkm_wr32(device, 0x61149c, 0x00000001);
-	nvkm_mask(device, 0x610490, 0x00000010, 0x00000010);
-	nvkm_wr32(device, 0x640000, 0x00000000);
-	nvkm_wr32(device, 0x610490, 0x01000013);
-
-	/* wait for it to go inactive */
-	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610490) & 0x80000000))
-			break;
-	) < 0) {
-		nvkm_error(subdev, "core init: %08x\n",
-			   nvkm_rd32(device, 0x610490));
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-const struct nv50_disp_dmac_func
-gp104_disp_core_func = {
-	.init = gp104_disp_core_init,
-	.fini = gf119_disp_core_fini,
-	.bind = gf119_disp_dmac_bind,
-};
-
-const struct nv50_disp_dmac_oclass
-gp104_disp_core_oclass = {
-	.base.oclass = GP104_DISP_CORE_CHANNEL_DMA,
-	.base.minver = 0,
-	.base.maxver = 0,
-	.ctor = nv50_disp_core_new,
-	.func = &gp104_disp_core_func,
-	.mthd = &gk104_disp_core_chan_mthd,
-	.chid = 0,
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursg84.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ g84_disp_curs_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_curs_new,
 	.func = &nv50_disp_pioc_func,
-	.chid = 7,
+	.chid = { 7, 7 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ gf119_disp_curs_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_curs_new,
 	.func = &gf119_disp_pioc_func,
-	.chid = 13,
+	.chid = { 13, 13 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ gk104_disp_curs_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_curs_new,
 	.func = &gf119_disp_pioc_func,
-	.chid = 13,
+	.chid = { 13, 13 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "channv50.h"
+#include "rootnv50.h"
+
+#include <nvif/class.h>
+
+const struct nv50_disp_pioc_oclass
+gp102_disp_curs_oclass = {
+	.base.oclass = GK104_DISP_CURSOR,
+	.base.minver = 0,
+	.base.maxver = 0,
+	.ctor = nv50_disp_curs_new,
+	.func = &gf119_disp_pioc_func,
+	.chid = { 13, 17 },
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgt215.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ gt215_disp_curs_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_curs_new,
 	.func = &nv50_disp_pioc_func,
-	.chid = 7,
+	.chid = { 7, 7 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 int
 nv50_disp_curs_new(const struct nv50_disp_chan_func *func,
 		   const struct nv50_disp_chan_mthd *mthd,
-		   struct nv50_disp_root *root, int chid,
+		   struct nv50_disp_root *root, int ctrl, int user,
 		   const struct nvkm_oclass *oclass, void *data, u32 size,
 		   struct nvkm_object **pobject)
 {
@@ -54,7 +54,7 @@ nv50_disp_curs_new(const struct nv50_dis
 	} else
 		return ret;
 
-	return nv50_disp_chan_new_(func, mthd, root, chid + head,
+	return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head,
 				   head, oclass, pobject);
 }
 
@@ -65,5 +65,5 @@ nv50_disp_curs_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_curs_new,
 	.func = &nv50_disp_pioc_func,
-	.chid = 7,
+	.chid = { 7, 7 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,8 +32,8 @@ gf119_disp_dmac_bind(struct nv50_disp_dm
 		     struct nvkm_object *object, u32 handle)
 {
 	return nvkm_ramht_insert(chan->base.root->ramht, object,
-				 chan->base.chid, -9, handle,
-				 chan->base.chid << 27 | 0x00000001);
+				 chan->base.chid.user, -9, handle,
+				 chan->base.chid.user << 27 | 0x00000001);
 }
 
 void
@@ -42,22 +42,23 @@ gf119_disp_dmac_fini(struct nv50_disp_dm
 	struct nv50_disp *disp = chan->base.root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->base.chid;
+	int ctrl = chan->base.chid.ctrl;
+	int user = chan->base.chid.user;
 
 	/* deactivate channel */
-	nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00001010, 0x00001000);
-	nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000003, 0x00000000);
+	nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000);
+	nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000);
 	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x001e0000))
+		if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000))
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d fini: %08x\n", chid,
-			   nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d fini: %08x\n", user,
+			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
 	}
 
 	/* disable error reporting and completion notification */
-	nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000);
-	nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000);
+	nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
+	nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
 }
 
 static int
@@ -66,26 +67,27 @@ gf119_disp_dmac_init(struct nv50_disp_dm
 	struct nv50_disp *disp = chan->base.root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->base.chid;
+	int ctrl = chan->base.chid.ctrl;
+	int user = chan->base.chid.user;
 
 	/* enable error reporting */
-	nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
+	nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
 
 	/* initialise channel for dma command submission */
-	nvkm_wr32(device, 0x610494 + (chid * 0x0010), chan->push);
-	nvkm_wr32(device, 0x610498 + (chid * 0x0010), 0x00010000);
-	nvkm_wr32(device, 0x61049c + (chid * 0x0010), 0x00000001);
-	nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010);
-	nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000);
-	nvkm_wr32(device, 0x610490 + (chid * 0x0010), 0x00000013);
+	nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push);
+	nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000);
+	nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001);
+	nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010);
+	nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
+	nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013);
 
 	/* wait for it to go inactive */
 	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x80000000))
+		if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000))
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d init: %08x\n", chid,
-			   nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d init: %08x\n", user,
+			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
 		return -EBUSY;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "dmacnv50.h"
+#include "rootnv50.h"
+
+#include <subdev/timer.h>
+
+static int
+gp102_disp_dmac_init(struct nv50_disp_dmac *chan)
+{
+	struct nv50_disp *disp = chan->base.root->disp;
+	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
+	struct nvkm_device *device = subdev->device;
+	int ctrl = chan->base.chid.ctrl;
+	int user = chan->base.chid.user;
+
+	/* enable error reporting */
+	nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
+
+	/* initialise channel for dma command submission */
+	nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push);
+	nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000);
+	nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001);
+	nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010);
+	nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
+	nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013);
+
+	/* wait for it to go inactive */
+	if (nvkm_msec(device, 2000,
+		if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000))
+			break;
+	) < 0) {
+		nvkm_error(subdev, "ch %d init: %08x\n", user,
+			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+const struct nv50_disp_dmac_func
+gp102_disp_dmac_func = {
+	.init = gp102_disp_dmac_init,
+	.fini = gf119_disp_dmac_fini,
+	.bind = gf119_disp_dmac_bind,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,66 +0,0 @@
-/*
- * Copyright 2016 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 <bskeggs@redhat.com>
- */
-#include "dmacnv50.h"
-#include "rootnv50.h"
-
-#include <subdev/timer.h>
-
-static int
-gp104_disp_dmac_init(struct nv50_disp_dmac *chan)
-{
-	struct nv50_disp *disp = chan->base.root->disp;
-	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
-	struct nvkm_device *device = subdev->device;
-	int chid = chan->base.chid;
-
-	/* enable error reporting */
-	nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
-
-	/* initialise channel for dma command submission */
-	nvkm_wr32(device, 0x611494 + (chid * 0x0010), chan->push);
-	nvkm_wr32(device, 0x611498 + (chid * 0x0010), 0x00010000);
-	nvkm_wr32(device, 0x61149c + (chid * 0x0010), 0x00000001);
-	nvkm_mask(device, 0x610490 + (chid * 0x0010), 0x00000010, 0x00000010);
-	nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000);
-	nvkm_wr32(device, 0x610490 + (chid * 0x0010), 0x00000013);
-
-	/* wait for it to go inactive */
-	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x80000000))
-			break;
-	) < 0) {
-		nvkm_error(subdev, "ch %d init: %08x\n", chid,
-			   nvkm_rd32(device, 0x610490 + (chid * 0x10)));
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-const struct nv50_disp_dmac_func
-gp104_disp_dmac_func = {
-	.init = gp104_disp_dmac_init,
-	.fini = gf119_disp_dmac_fini,
-	.bind = gf119_disp_dmac_bind,
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -149,7 +149,7 @@ nv50_disp_dmac_new_(const struct nv50_di
 	chan->func = func;
 
 	ret = nv50_disp_chan_ctor(&nv50_disp_dmac_func_, mthd, root,
-				  chid, head, oclass, &chan->base);
+				  chid, chid, head, oclass, &chan->base);
 	if (ret)
 		return ret;
 
@@ -179,9 +179,9 @@ nv50_disp_dmac_bind(struct nv50_disp_dma
 		    struct nvkm_object *object, u32 handle)
 {
 	return nvkm_ramht_insert(chan->base.root->ramht, object,
-				 chan->base.chid, -10, handle,
-				 chan->base.chid << 28 |
-				 chan->base.chid);
+				 chan->base.chid.user, -10, handle,
+				 chan->base.chid.user << 28 |
+				 chan->base.chid.user);
 }
 
 static void
@@ -190,21 +190,22 @@ nv50_disp_dmac_fini(struct nv50_disp_dma
 	struct nv50_disp *disp = chan->base.root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->base.chid;
+	int ctrl = chan->base.chid.ctrl;
+	int user = chan->base.chid.user;
 
 	/* deactivate channel */
-	nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00001010, 0x00001000);
-	nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000003, 0x00000000);
+	nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000);
+	nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000);
 	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x001e0000))
+		if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000))
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d fini timeout, %08x\n", chid,
-			   nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d fini timeout, %08x\n", user,
+			   nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
 	}
 
 	/* disable error reporting and completion notifications */
-	nvkm_mask(device, 0x610028, 0x00010001 << chid, 0x00000000 << chid);
+	nvkm_mask(device, 0x610028, 0x00010001 << user, 0x00000000 << user);
 }
 
 static int
@@ -213,26 +214,27 @@ nv50_disp_dmac_init(struct nv50_disp_dma
 	struct nv50_disp *disp = chan->base.root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->base.chid;
+	int ctrl = chan->base.chid.ctrl;
+	int user = chan->base.chid.user;
 
 	/* enable error reporting */
-	nvkm_mask(device, 0x610028, 0x00010000 << chid, 0x00010000 << chid);
+	nvkm_mask(device, 0x610028, 0x00010000 << user, 0x00010000 << user);
 
 	/* initialise channel for dma command submission */
-	nvkm_wr32(device, 0x610204 + (chid * 0x0010), chan->push);
-	nvkm_wr32(device, 0x610208 + (chid * 0x0010), 0x00010000);
-	nvkm_wr32(device, 0x61020c + (chid * 0x0010), chid);
-	nvkm_mask(device, 0x610200 + (chid * 0x0010), 0x00000010, 0x00000010);
-	nvkm_wr32(device, 0x640000 + (chid * 0x1000), 0x00000000);
-	nvkm_wr32(device, 0x610200 + (chid * 0x0010), 0x00000013);
+	nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push);
+	nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000);
+	nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl);
+	nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010);
+	nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), 0x00000000);
+	nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013);
 
 	/* wait for it to go inactive */
 	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x80000000))
+		if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000))
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d init timeout, %08x\n", chid,
-			   nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d init timeout, %08x\n", user,
+			   nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
 		return -EBUSY;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@ int gf119_disp_dmac_bind(struct nv50_dis
 extern const struct nv50_disp_dmac_func gf119_disp_core_func;
 void gf119_disp_core_fini(struct nv50_disp_dmac *);
 
-extern const struct nv50_disp_dmac_func gp104_disp_dmac_func;
+extern const struct nv50_disp_dmac_func gp102_disp_dmac_func;
 
 struct nv50_disp_dmac_oclass {
 	int (*ctor)(const struct nv50_disp_dmac_func *,
@@ -95,7 +95,7 @@ extern const struct nv50_disp_dmac_oclas
 
 extern const struct nv50_disp_dmac_oclass gp100_disp_core_oclass;
 
-extern const struct nv50_disp_dmac_oclass gp104_disp_core_oclass;
-extern const struct nv50_disp_dmac_oclass gp104_disp_base_oclass;
-extern const struct nv50_disp_dmac_oclass gp104_disp_ovly_oclass;
+extern const struct nv50_disp_dmac_oclass gp102_disp_core_oclass;
+extern const struct nv50_disp_dmac_oclass gp102_disp_base_oclass;
+extern const struct nv50_disp_dmac_oclass gp102_disp_ovly_oclass;
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c	2017-02-12 16:03:20.000000000 -0500
@@ -319,9 +319,8 @@ static const struct dp_rates {
 };
 
 void
-nvkm_dp_train(struct work_struct *w)
+nvkm_dp_train(struct nvkm_output_dp *outp)
 {
-	struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work);
 	struct nv50_disp *disp = nv50_disp(outp->base.disp);
 	const struct dp_rates *cfg = nvkm_dp_rates;
 	struct dp_state _dp = {
@@ -353,9 +352,6 @@ nvkm_dp_train(struct work_struct *w)
 	}
 	cfg--;
 
-	/* disable link interrupt handling during link training */
-	nvkm_notify_put(&outp->irq);
-
 	/* ensure sink is not in a low-power state */
 	if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
 		if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
@@ -400,9 +396,6 @@ nvkm_dp_train(struct work_struct *w)
 
 	dp_link_train_fini(dp);
 
-	/* signal completion and enable link interrupt handling */
 	OUTP_DBG(&outp->base, "training complete");
 	atomic_set(&outp->lt.done, 1);
-	wake_up(&outp->lt.wait);
-	nvkm_notify_get(&outp->irq);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 #ifndef __NVKM_DISP_DPORT_H__
 #define __NVKM_DISP_DPORT_H__
-#include <core/os.h>
+struct nvkm_output_dp;
 
 /* DPCD Receiver Capabilities */
 #define DPCD_RC00_DPCD_REV                                              0x00000
@@ -77,5 +77,5 @@
 #define DPCD_SC00_SET_POWER_D0                                             0x01
 #define DPCD_SC00_SET_POWER_D3                                             0x03
 
-void nvkm_dp_train(struct work_struct *);
+void nvkm_dp_train(struct nvkm_output_dp *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c	2017-02-12 16:03:20.000000000 -0500
@@ -203,17 +203,20 @@ gf119_disp_intr_unk2_0(struct nv50_disp
 	/* see note in nv50_disp_intr_unk20_0() */
 	if (outp && outp->info.type == DCB_OUTPUT_DP) {
 		struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
-		struct nvbios_init init = {
-			.subdev = subdev,
-			.bios = subdev->device->bios,
-			.outp = &outp->info,
-			.crtc = head,
-			.offset = outpdp->info.script[4],
-			.execute = 1,
-		};
+		if (!outpdp->lt.mst) {
+			struct nvbios_init init = {
+				.subdev = subdev,
+				.bios = subdev->device->bios,
+				.outp = &outp->info,
+				.crtc = head,
+				.offset = outpdp->info.script[4],
+				.execute = 1,
+			};
 
-		nvbios_exec(&init);
-		atomic_set(&outpdp->lt.done, 0);
+			nvkm_notify_put(&outpdp->irq);
+			nvbios_exec(&init);
+			atomic_set(&outpdp->lt.done, 0);
+		}
 	}
 }
 
@@ -314,7 +317,7 @@ gf119_disp_intr_unk2_2(struct nv50_disp
 			break;
 		}
 
-		if (nvkm_output_dp_train(outp, pclk, true))
+		if (nvkm_output_dp_train(outp, pclk))
 			OUTP_ERR(outp, "link not trained before attach");
 	} else {
 		if (disp->func->sor.magic)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "nv50.h"
+#include "rootnv50.h"
+
+static void
+gp102_disp_intr_error(struct nv50_disp *disp, int chid)
+{
+	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
+	struct nvkm_device *device = subdev->device;
+	u32 mthd = nvkm_rd32(device, 0x6111f0 + (chid * 12));
+	u32 data = nvkm_rd32(device, 0x6111f4 + (chid * 12));
+	u32 unkn = nvkm_rd32(device, 0x6111f8 + (chid * 12));
+
+	nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n",
+		   chid, (mthd & 0x0000ffc), data, mthd, unkn);
+
+	if (chid < ARRAY_SIZE(disp->chan)) {
+		switch (mthd & 0xffc) {
+		case 0x0080:
+			nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
+			break;
+		default:
+			break;
+		}
+	}
+
+	nvkm_wr32(device, 0x61009c, (1 << chid));
+	nvkm_wr32(device, 0x6111f0 + (chid * 12), 0x90000000);
+}
+
+static const struct nv50_disp_func
+gp102_disp = {
+	.intr = gf119_disp_intr,
+	.intr_error = gp102_disp_intr_error,
+	.uevent = &gf119_disp_chan_uevent,
+	.super = gf119_disp_intr_supervisor,
+	.root = &gp102_disp_root_oclass,
+	.head.vblank_init = gf119_disp_vblank_init,
+	.head.vblank_fini = gf119_disp_vblank_fini,
+	.head.scanoutpos = gf119_disp_root_scanoutpos,
+	.outp.internal.crt = nv50_dac_output_new,
+	.outp.internal.tmds = nv50_sor_output_new,
+	.outp.internal.lvds = nv50_sor_output_new,
+	.outp.internal.dp = gm200_sor_dp_new,
+	.dac.nr = 3,
+	.dac.power = nv50_dac_power,
+	.dac.sense = nv50_dac_sense,
+	.sor.nr = 4,
+	.sor.power = nv50_sor_power,
+	.sor.hda_eld = gf119_hda_eld,
+	.sor.hdmi = gk104_hdmi_ctrl,
+	.sor.magic = gm200_sor_magic,
+};
+
+int
+gp102_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
+{
+	return gf119_disp_new_(&gp102_disp, device, index, pdisp);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/*
- * Copyright 2016 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 <bskeggs@redhat.com>
- */
-#include "nv50.h"
-#include "rootnv50.h"
-
-static void
-gp104_disp_intr_error(struct nv50_disp *disp, int chid)
-{
-	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
-	struct nvkm_device *device = subdev->device;
-	u32 mthd = nvkm_rd32(device, 0x6111f0 + (chid * 12));
-	u32 data = nvkm_rd32(device, 0x6111f4 + (chid * 12));
-	u32 unkn = nvkm_rd32(device, 0x6111f8 + (chid * 12));
-
-	nvkm_error(subdev, "chid %d mthd %04x data %08x %08x %08x\n",
-		   chid, (mthd & 0x0000ffc), data, mthd, unkn);
-
-	if (chid < ARRAY_SIZE(disp->chan)) {
-		switch (mthd & 0xffc) {
-		case 0x0080:
-			nv50_disp_chan_mthd(disp->chan[chid], NV_DBG_ERROR);
-			break;
-		default:
-			break;
-		}
-	}
-
-	nvkm_wr32(device, 0x61009c, (1 << chid));
-	nvkm_wr32(device, 0x6111f0 + (chid * 12), 0x90000000);
-}
-
-static const struct nv50_disp_func
-gp104_disp = {
-	.intr = gf119_disp_intr,
-	.intr_error = gp104_disp_intr_error,
-	.uevent = &gf119_disp_chan_uevent,
-	.super = gf119_disp_intr_supervisor,
-	.root = &gp104_disp_root_oclass,
-	.head.vblank_init = gf119_disp_vblank_init,
-	.head.vblank_fini = gf119_disp_vblank_fini,
-	.head.scanoutpos = gf119_disp_root_scanoutpos,
-	.outp.internal.crt = nv50_dac_output_new,
-	.outp.internal.tmds = nv50_sor_output_new,
-	.outp.internal.lvds = nv50_sor_output_new,
-	.outp.internal.dp = gm200_sor_dp_new,
-	.dac.nr = 3,
-	.dac.power = nv50_dac_power,
-	.dac.sense = nv50_dac_sense,
-	.sor.nr = 4,
-	.sor.power = nv50_sor_power,
-	.sor.hda_eld = gf119_hda_eld,
-	.sor.hdmi = gk104_hdmi_ctrl,
-	.sor.magic = gm200_sor_magic,
-};
-
-int
-gp104_disp_new(struct nvkm_device *device, int index, struct nvkm_disp **pdisp)
-{
-	return gf119_disp_new_(&gp104_disp, device, index, pdisp);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,7 @@ gt215_hda_eld(NV50_DISP_MTHD_V1)
 			);
 		}
 		for (i = 0; i < size; i++)
-			nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[0]);
+			nvkm_wr32(device, 0x61c440 + soff, (i << 8) | args->v0.data[i]);
 		for (; i < 0x60; i++)
 			nvkm_wr32(device, 0x61c440 + soff, (i << 8));
 		nvkm_mask(device, 0x61c448 + soff, 0x80000003, 0x80000003);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@ nvkm-y += nvkm/engine/disp/gk110.o
 nvkm-y += nvkm/engine/disp/gm107.o
 nvkm-y += nvkm/engine/disp/gm200.o
 nvkm-y += nvkm/engine/disp/gp100.o
-nvkm-y += nvkm/engine/disp/gp104.o
+nvkm-y += nvkm/engine/disp/gp102.o
 
 nvkm-y += nvkm/engine/disp/outp.o
 nvkm-y += nvkm/engine/disp/outpdp.o
@@ -48,14 +48,14 @@ nvkm-y += nvkm/engine/disp/rootgk110.o
 nvkm-y += nvkm/engine/disp/rootgm107.o
 nvkm-y += nvkm/engine/disp/rootgm200.o
 nvkm-y += nvkm/engine/disp/rootgp100.o
-nvkm-y += nvkm/engine/disp/rootgp104.o
+nvkm-y += nvkm/engine/disp/rootgp102.o
 
 nvkm-y += nvkm/engine/disp/channv50.o
 nvkm-y += nvkm/engine/disp/changf119.o
 
 nvkm-y += nvkm/engine/disp/dmacnv50.o
 nvkm-y += nvkm/engine/disp/dmacgf119.o
-nvkm-y += nvkm/engine/disp/dmacgp104.o
+nvkm-y += nvkm/engine/disp/dmacgp102.o
 
 nvkm-y += nvkm/engine/disp/basenv50.o
 nvkm-y += nvkm/engine/disp/baseg84.o
@@ -64,7 +64,7 @@ nvkm-y += nvkm/engine/disp/basegt215.o
 nvkm-y += nvkm/engine/disp/basegf119.o
 nvkm-y += nvkm/engine/disp/basegk104.o
 nvkm-y += nvkm/engine/disp/basegk110.o
-nvkm-y += nvkm/engine/disp/basegp104.o
+nvkm-y += nvkm/engine/disp/basegp102.o
 
 nvkm-y += nvkm/engine/disp/corenv50.o
 nvkm-y += nvkm/engine/disp/coreg84.o
@@ -77,7 +77,7 @@ nvkm-y += nvkm/engine/disp/coregk110.o
 nvkm-y += nvkm/engine/disp/coregm107.o
 nvkm-y += nvkm/engine/disp/coregm200.o
 nvkm-y += nvkm/engine/disp/coregp100.o
-nvkm-y += nvkm/engine/disp/coregp104.o
+nvkm-y += nvkm/engine/disp/coregp102.o
 
 nvkm-y += nvkm/engine/disp/ovlynv50.o
 nvkm-y += nvkm/engine/disp/ovlyg84.o
@@ -85,7 +85,7 @@ nvkm-y += nvkm/engine/disp/ovlygt200.o
 nvkm-y += nvkm/engine/disp/ovlygt215.o
 nvkm-y += nvkm/engine/disp/ovlygf119.o
 nvkm-y += nvkm/engine/disp/ovlygk104.o
-nvkm-y += nvkm/engine/disp/ovlygp104.o
+nvkm-y += nvkm/engine/disp/ovlygp102.o
 
 nvkm-y += nvkm/engine/disp/piocnv50.o
 nvkm-y += nvkm/engine/disp/piocgf119.o
@@ -95,9 +95,11 @@ nvkm-y += nvkm/engine/disp/cursg84.o
 nvkm-y += nvkm/engine/disp/cursgt215.o
 nvkm-y += nvkm/engine/disp/cursgf119.o
 nvkm-y += nvkm/engine/disp/cursgk104.o
+nvkm-y += nvkm/engine/disp/cursgp102.o
 
 nvkm-y += nvkm/engine/disp/oimmnv50.o
 nvkm-y += nvkm/engine/disp/oimmg84.o
 nvkm-y += nvkm/engine/disp/oimmgt215.o
 nvkm-y += nvkm/engine/disp/oimmgf119.o
 nvkm-y += nvkm/engine/disp/oimmgk104.o
+nvkm-y += nvkm/engine/disp/oimmgp102.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -433,8 +433,6 @@ nv50_disp_dptmds_war(struct nvkm_device
 	case 0x94:
 	case 0x96:
 	case 0x98:
-	case 0xaa:
-	case 0xac:
 		return true;
 	default:
 		break;
@@ -590,6 +588,7 @@ nv50_disp_intr_unk20_0(struct nv50_disp
 			.execute = 1,
 		};
 
+		nvkm_notify_put(&outpdp->irq);
 		nvbios_exec(&init);
 		atomic_set(&outpdp->lt.done, 0);
 	}
@@ -779,7 +778,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp
 			break;
 		}
 
-		if (nvkm_output_dp_train(outp, datarate / soff, true))
+		if (nvkm_output_dp_train(outp, datarate / soff))
 			OUTP_ERR(outp, "link not trained before attach");
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmg84.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ g84_disp_oimm_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_oimm_new,
 	.func = &nv50_disp_pioc_func,
-	.chid = 5,
+	.chid = { 5, 5 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ gf119_disp_oimm_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_oimm_new,
 	.func = &gf119_disp_pioc_func,
-	.chid = 9,
+	.chid = { 9, 9 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ gk104_disp_oimm_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_oimm_new,
 	.func = &gf119_disp_pioc_func,
-	.chid = 9,
+	.chid = { 9, 9 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "channv50.h"
+#include "rootnv50.h"
+
+#include <nvif/class.h>
+
+const struct nv50_disp_pioc_oclass
+gp102_disp_oimm_oclass = {
+	.base.oclass = GK104_DISP_OVERLAY,
+	.base.minver = 0,
+	.base.maxver = 0,
+	.ctor = nv50_disp_oimm_new,
+	.func = &gf119_disp_pioc_func,
+	.chid = { 9, 13 },
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgt215.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,5 +33,5 @@ gt215_disp_oimm_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_oimm_new,
 	.func = &nv50_disp_pioc_func,
-	.chid = 5,
+	.chid = { 5, 5 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 int
 nv50_disp_oimm_new(const struct nv50_disp_chan_func *func,
 		   const struct nv50_disp_chan_mthd *mthd,
-		   struct nv50_disp_root *root, int chid,
+		   struct nv50_disp_root *root, int ctrl, int user,
 		   const struct nvkm_oclass *oclass, void *data, u32 size,
 		   struct nvkm_object **pobject)
 {
@@ -54,7 +54,7 @@ nv50_disp_oimm_new(const struct nv50_dis
 	} else
 		return ret;
 
-	return nv50_disp_chan_new_(func, mthd, root, chid + head,
+	return nv50_disp_chan_new_(func, mthd, root, ctrl + head, user + head,
 				   head, oclass, pobject);
 }
 
@@ -65,5 +65,5 @@ nv50_disp_oimm_oclass = {
 	.base.maxver = 0,
 	.ctor = nv50_disp_oimm_new,
 	.func = &nv50_disp_pioc_func,
-	.chid = 5,
+	.chid = { 5, 5 },
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <nvif/event.h>
 
 int
-nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
+nvkm_output_dp_train(struct nvkm_output *base, u32 datarate)
 {
 	struct nvkm_output_dp *outp = nvkm_output_dp(base);
 	bool retrain = true;
@@ -39,6 +39,8 @@ nvkm_output_dp_train(struct nvkm_output
 	u32 linkrate;
 	int ret, i;
 
+	mutex_lock(&outp->mutex);
+
 	/* check that the link is trained at a high enough rate */
 	ret = nvkm_rdaux(outp->aux, DPCD_LC00_LINK_BW_SET, link, 2);
 	if (ret) {
@@ -88,19 +90,10 @@ done:
 			outp->dpcd[DPCD_RC02] =
 				outp->base.info.dpconf.link_nr;
 		}
-		atomic_set(&outp->lt.done, 0);
-		schedule_work(&outp->lt.work);
-	} else {
-		nvkm_notify_get(&outp->irq);
-	}
-
-	if (wait) {
-		if (!wait_event_timeout(outp->lt.wait,
-					atomic_read(&outp->lt.done),
-					msecs_to_jiffies(2000)))
-			ret = -ETIMEDOUT;
+		nvkm_dp_train(outp);
 	}
 
+	mutex_unlock(&outp->mutex);
 	return ret;
 }
 
@@ -118,7 +111,7 @@ nvkm_output_dp_enable(struct nvkm_output
 
 		if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dpcd,
 				sizeof(outp->dpcd))) {
-			nvkm_output_dp_train(&outp->base, 0, true);
+			nvkm_output_dp_train(&outp->base, 0);
 			return;
 		}
 	}
@@ -165,10 +158,10 @@ nvkm_output_dp_irq(struct nvkm_notify *n
 	};
 
 	OUTP_DBG(&outp->base, "IRQ: %d", line->mask);
-	nvkm_output_dp_train(&outp->base, 0, true);
+	nvkm_output_dp_train(&outp->base, 0);
 
 	nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep));
-	return NVKM_NOTIFY_DROP;
+	return NVKM_NOTIFY_KEEP;
 }
 
 static void
@@ -177,7 +170,6 @@ nvkm_output_dp_fini(struct nvkm_output *
 	struct nvkm_output_dp *outp = nvkm_output_dp(base);
 	nvkm_notify_put(&outp->hpd);
 	nvkm_notify_put(&outp->irq);
-	flush_work(&outp->lt.work);
 	nvkm_output_dp_enable(outp, false);
 }
 
@@ -187,6 +179,7 @@ nvkm_output_dp_init(struct nvkm_output *
 	struct nvkm_output_dp *outp = nvkm_output_dp(base);
 	nvkm_notify_put(&outp->base.conn->hpd);
 	nvkm_output_dp_enable(outp, true);
+	nvkm_notify_get(&outp->irq);
 	nvkm_notify_get(&outp->hpd);
 }
 
@@ -238,11 +231,6 @@ nvkm_output_dp_ctor(const struct nvkm_ou
 	OUTP_DBG(&outp->base, "bios dp %02x %02x %02x %02x",
 		 outp->version, hdr, cnt, len);
 
-	/* link training */
-	INIT_WORK(&outp->lt.work, nvkm_dp_train);
-	init_waitqueue_head(&outp->lt.wait);
-	atomic_set(&outp->lt.done, 0);
-
 	/* link maintenance */
 	ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_irq, true,
 			       &(struct nvkm_i2c_ntfy_req) {
@@ -257,6 +245,9 @@ nvkm_output_dp_ctor(const struct nvkm_ou
 		return ret;
 	}
 
+	mutex_init(&outp->mutex);
+	atomic_set(&outp->lt.done, 0);
+
 	/* hotplug detect, replaces gpio-based mechanism with aux events */
 	ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_hpd, true,
 			       &(struct nvkm_i2c_ntfy_req) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h	2017-02-12 16:03:20.000000000 -0500
@@ -29,10 +29,10 @@ struct nvkm_output_dp {
 	bool present;
 	u8 dpcd[16];
 
+	struct mutex mutex;
 	struct {
-		struct work_struct work;
-		wait_queue_head_t wait;
 		atomic_t done;
+		bool mst;
 	} lt;
 };
 
@@ -41,9 +41,11 @@ struct nvkm_output_dp_func {
 	int (*lnk_pwr)(struct nvkm_output_dp *, int nr);
 	int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef);
 	int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc);
+	void (*vcpi)(struct nvkm_output_dp *, int head, u8 start_slot,
+		     u8 num_slots, u16 pbn, u16 aligned_pbn);
 };
 
-int nvkm_output_dp_train(struct nvkm_output *, u32 rate, bool wait);
+int nvkm_output_dp_train(struct nvkm_output *, u32 rate);
 
 int nvkm_output_dp_ctor(const struct nvkm_output_dp_func *, struct nvkm_disp *,
 			int index, struct dcb_output *, struct nvkm_i2c_aux *,
@@ -63,6 +65,7 @@ int gf119_sor_dp_new(struct nvkm_disp *,
 		     struct nvkm_output **);
 int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
 int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int);
+void gf119_sor_dp_vcpi(struct nvkm_output_dp *, int, u8, u8, u16, u16);
 
 int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
 		     struct nvkm_output **);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 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 "dmacnv50.h"
+#include "rootnv50.h"
+
+#include <nvif/class.h>
+
+const struct nv50_disp_dmac_oclass
+gp102_disp_ovly_oclass = {
+	.base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA,
+	.base.minver = 0,
+	.base.maxver = 0,
+	.ctor = nv50_disp_ovly_new,
+	.func = &gp102_disp_dmac_func,
+	.mthd = &gk104_disp_ovly_chan_mthd,
+	.chid = 5,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/*
- * Copyright 2012 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 "dmacnv50.h"
-#include "rootnv50.h"
-
-#include <nvif/class.h>
-
-const struct nv50_disp_dmac_oclass
-gp104_disp_ovly_oclass = {
-	.base.oclass = GK104_DISP_OVERLAY_CONTROL_DMA,
-	.base.minver = 0,
-	.base.maxver = 0,
-	.ctor = nv50_disp_ovly_new,
-	.func = &gp104_disp_dmac_func,
-	.mthd = &gk104_disp_ovly_chan_mthd,
-	.chid = 5,
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,20 +32,21 @@ gf119_disp_pioc_fini(struct nv50_disp_ch
 	struct nv50_disp *disp = chan->root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->chid;
+	int ctrl = chan->chid.ctrl;
+	int user = chan->chid.user;
 
-	nvkm_mask(device, 0x610490 + (chid * 0x10), 0x00000001, 0x00000000);
+	nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000);
 	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610490 + (chid * 0x10)) & 0x00030000))
+		if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000))
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d fini: %08x\n", chid,
-			   nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d fini: %08x\n", user,
+			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
 	}
 
 	/* disable error reporting and completion notification */
-	nvkm_mask(device, 0x610090, 0x00000001 << chid, 0x00000000);
-	nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000000);
+	nvkm_mask(device, 0x610090, 0x00000001 << user, 0x00000000);
+	nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000000);
 }
 
 static int
@@ -54,20 +55,21 @@ gf119_disp_pioc_init(struct nv50_disp_ch
 	struct nv50_disp *disp = chan->root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->chid;
+	int ctrl = chan->chid.ctrl;
+	int user = chan->chid.user;
 
 	/* enable error reporting */
-	nvkm_mask(device, 0x6100a0, 0x00000001 << chid, 0x00000001 << chid);
+	nvkm_mask(device, 0x6100a0, 0x00000001 << user, 0x00000001 << user);
 
 	/* activate channel */
-	nvkm_wr32(device, 0x610490 + (chid * 0x10), 0x00000001);
+	nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001);
 	if (nvkm_msec(device, 2000,
-		u32 tmp = nvkm_rd32(device, 0x610490 + (chid * 0x10));
+		u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10));
 		if ((tmp & 0x00030000) == 0x00010000)
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d init: %08x\n", chid,
-			   nvkm_rd32(device, 0x610490 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d init: %08x\n", user,
+			   nvkm_rd32(device, 0x610490 + (ctrl * 0x10)));
 		return -EBUSY;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,15 +32,16 @@ nv50_disp_pioc_fini(struct nv50_disp_cha
 	struct nv50_disp *disp = chan->root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->chid;
+	int ctrl = chan->chid.ctrl;
+	int user = chan->chid.user;
 
-	nvkm_mask(device, 0x610200 + (chid * 0x10), 0x00000001, 0x00000000);
+	nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000);
 	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000))
+		if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000))
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d timeout: %08x\n", chid,
-			   nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d timeout: %08x\n", user,
+			   nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
 	}
 }
 
@@ -50,26 +51,27 @@ nv50_disp_pioc_init(struct nv50_disp_cha
 	struct nv50_disp *disp = chan->root->disp;
 	struct nvkm_subdev *subdev = &disp->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int chid = chan->chid;
+	int ctrl = chan->chid.ctrl;
+	int user = chan->chid.user;
 
-	nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00002000);
+	nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000);
 	if (nvkm_msec(device, 2000,
-		if (!(nvkm_rd32(device, 0x610200 + (chid * 0x10)) & 0x00030000))
+		if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000))
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d timeout0: %08x\n", chid,
-			   nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d timeout0: %08x\n", user,
+			   nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
 		return -EBUSY;
 	}
 
-	nvkm_wr32(device, 0x610200 + (chid * 0x10), 0x00000001);
+	nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001);
 	if (nvkm_msec(device, 2000,
-		u32 tmp = nvkm_rd32(device, 0x610200 + (chid * 0x10));
+		u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10));
 		if ((tmp & 0x00030000) == 0x00010000)
 			break;
 	) < 0) {
-		nvkm_error(subdev, "ch %d timeout1: %08x\n", chid,
-			   nvkm_rd32(device, 0x610200 + (chid * 0x10)));
+		nvkm_error(subdev, "ch %d timeout1: %08x\n", user,
+			   nvkm_rd32(device, 0x610200 + (ctrl * 0x10)));
 		return -EBUSY;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "rootnv50.h"
+#include "dmacnv50.h"
+
+#include <nvif/class.h>
+
+static const struct nv50_disp_root_func
+gp102_disp_root = {
+	.init = gf119_disp_root_init,
+	.fini = gf119_disp_root_fini,
+	.dmac = {
+		&gp102_disp_core_oclass,
+		&gp102_disp_base_oclass,
+		&gp102_disp_ovly_oclass,
+	},
+	.pioc = {
+		&gp102_disp_oimm_oclass,
+		&gp102_disp_curs_oclass,
+	},
+};
+
+static int
+gp102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
+		    void *data, u32 size, struct nvkm_object **pobject)
+{
+	return nv50_disp_root_new_(&gp102_disp_root, disp, oclass,
+				   data, size, pobject);
+}
+
+const struct nvkm_disp_oclass
+gp102_disp_root_oclass = {
+	.base.oclass = GP102_DISP,
+	.base.minver = -1,
+	.base.maxver = -1,
+	.ctor = gp102_disp_root_new,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,58 +0,0 @@
-/*
- * Copyright 2016 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 <bskeggs@redhat.com>
- */
-#include "rootnv50.h"
-#include "dmacnv50.h"
-
-#include <nvif/class.h>
-
-static const struct nv50_disp_root_func
-gp104_disp_root = {
-	.init = gf119_disp_root_init,
-	.fini = gf119_disp_root_fini,
-	.dmac = {
-		&gp104_disp_core_oclass,
-		&gp104_disp_base_oclass,
-		&gp104_disp_ovly_oclass,
-	},
-	.pioc = {
-		&gk104_disp_oimm_oclass,
-		&gk104_disp_curs_oclass,
-	},
-};
-
-static int
-gp104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass,
-		    void *data, u32 size, struct nvkm_object **pobject)
-{
-	return nv50_disp_root_new_(&gp104_disp_root, disp, oclass,
-				   data, size, pobject);
-}
-
-const struct nvkm_disp_oclass
-gp104_disp_root_oclass = {
-	.base.oclass = GP104_DISP,
-	.base.minver = -1,
-	.base.maxver = -1,
-	.ctor = gp104_disp_root_new,
-};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,7 +66,7 @@ nv50_disp_root_scanoutpos(NV50_DISP_MTHD
 	return 0;
 }
 
-int
+static int
 nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
 {
 	union {
@@ -173,13 +173,56 @@ nv50_disp_root_mthd_(struct nvkm_object
 				return 0;
 			} else
 			if (args->v0.state != 0) {
-				nvkm_output_dp_train(&outpdp->base, 0, true);
+				nvkm_output_dp_train(&outpdp->base, 0);
 				return 0;
 			}
 		} else
 			return ret;
 	}
 		break;
+	case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: {
+		struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
+		union {
+			struct nv50_disp_sor_dp_mst_link_v0 v0;
+		} *args = data;
+		int ret = -ENOSYS;
+		nvif_ioctl(object, "disp sor dp mst link size %d\n", size);
+		if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+			nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n",
+				   args->v0.version, args->v0.state);
+			if (outpdp->lt.mst != !!args->v0.state) {
+				outpdp->lt.mst = !!args->v0.state;
+				atomic_set(&outpdp->lt.done, 0);
+				nvkm_output_dp_train(&outpdp->base, 0);
+			}
+			return 0;
+		} else
+			return ret;
+	}
+		break;
+	case NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI: {
+		struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
+		union {
+			struct nv50_disp_sor_dp_mst_vcpi_v0 v0;
+		} *args = data;
+		int ret = -ENOSYS;
+		nvif_ioctl(object, "disp sor dp mst vcpi size %d\n", size);
+		if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+			nvif_ioctl(object, "disp sor dp mst vcpi vers %d "
+					   "slot %02x/%02x pbn %04x/%04x\n",
+				   args->v0.version, args->v0.start_slot,
+				   args->v0.num_slots, args->v0.pbn,
+				   args->v0.aligned_pbn);
+			if (!outpdp->func->vcpi)
+				return -ENODEV;
+			outpdp->func->vcpi(outpdp, head, args->v0.start_slot,
+					   args->v0.num_slots, args->v0.pbn,
+					   args->v0.aligned_pbn);
+			return 0;
+		} else
+			return ret;
+	}
+		break;
 	case NV50_DISP_MTHD_V1_PIOR_PWR:
 		if (!func->pior.power)
 			return -ENODEV;
@@ -207,8 +250,8 @@ nv50_disp_root_pioc_new_(const struct nv
 {
 	const struct nv50_disp_pioc_oclass *sclass = oclass->priv;
 	struct nv50_disp_root *root = nv50_disp_root(oclass->parent);
-	return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid,
-			    oclass, data, size, pobject);
+	return sclass->ctor(sclass->func, sclass->mthd, root, sclass->chid.ctrl,
+			    sclass->chid.user, oclass, data, size, pobject);
 }
 
 static int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,5 +41,5 @@ extern const struct nvkm_disp_oclass gk1
 extern const struct nvkm_disp_oclass gm107_disp_root_oclass;
 extern const struct nvkm_disp_oclass gm200_disp_root_oclass;
 extern const struct nvkm_disp_oclass gp100_disp_root_oclass;
-extern const struct nvkm_disp_oclass gp104_disp_root_oclass;
+extern const struct nvkm_disp_oclass gp102_disp_root_oclass;
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,14 +45,6 @@ static const struct nvkm_output_func
 g94_sor_output_func = {
 };
 
-int
-g94_sor_output_new(struct nvkm_disp *disp, int index,
-		   struct dcb_output *dcbE, struct nvkm_output **poutp)
-{
-	return nvkm_output_new_(&g94_sor_output_func, disp,
-				index, dcbE, poutp);
-}
-
 /*******************************************************************************
  * DisplayPort
  ******************************************************************************/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,11 +56,13 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_
 
 	clksor |= bw << 18;
 	dpctrl |= ((1 << nr) - 1) << 16;
+	if (outp->lt.mst)
+		dpctrl |= 0x40000000;
 	if (ef)
 		dpctrl |= 0x00004000;
 
 	nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
-	nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl);
+	nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
 	return 0;
 }
 
@@ -101,12 +103,24 @@ gf119_sor_dp_drv_ctl(struct nvkm_output_
 	return 0;
 }
 
+void
+gf119_sor_dp_vcpi(struct nvkm_output_dp *outp, int head, u8 slot,
+		  u8 slot_nr, u16 pbn, u16 aligned)
+{
+	struct nvkm_device *device = outp->base.disp->engine.subdev.device;
+	const u32 hoff = head * 0x800;
+
+	nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot);
+	nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn);
+}
+
 static const struct nvkm_output_dp_func
 gf119_sor_dp_func = {
 	.pattern = gf119_sor_dp_pattern,
 	.lnk_pwr = g94_sor_dp_lnk_pwr,
 	.lnk_ctl = gf119_sor_dp_lnk_ctl,
 	.drv_ctl = gf119_sor_dp_drv_ctl,
+	.vcpi = gf119_sor_dp_vcpi,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,6 +43,7 @@ gm107_sor_dp_func = {
 	.lnk_pwr = g94_sor_dp_lnk_pwr,
 	.lnk_ctl = gf119_sor_dp_lnk_ctl,
 	.drv_ctl = gf119_sor_dp_drv_ctl,
+	.vcpi = gf119_sor_dp_vcpi,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c	2017-02-12 16:03:20.000000000 -0500
@@ -120,6 +120,7 @@ gm200_sor_dp_func = {
 	.lnk_pwr = gm200_sor_dp_lnk_pwr,
 	.lnk_ctl = gf119_sor_dp_lnk_ctl,
 	.drv_ctl = gm200_sor_dp_drv_ctl,
+	.vcpi = gf119_sor_dp_vcpi,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c	2017-02-12 16:03:20.000000000 -0500
@@ -129,7 +129,7 @@ g84_fifo_chan_engine_fini(struct nvkm_fi
 }
 
 
-int
+static int
 g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
 			  struct nvkm_engine *engine)
 {
@@ -170,7 +170,7 @@ g84_fifo_chan_engine_ctor(struct nvkm_fi
 	return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
 }
 
-int
+static int
 g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
 			  struct nvkm_object *object)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,7 +180,8 @@ gf100_fifo_recover(struct gf100_fifo *fi
 	list_del_init(&chan->head);
 	chan->killed = true;
 
-	fifo->recover.mask |= 1ULL << engine->subdev.index;
+	if (engine != &fifo->base.engine)
+		fifo->recover.mask |= 1ULL << engine->subdev.index;
 	schedule_work(&fifo->recover.work);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -743,14 +743,14 @@ gk104_fifo_fault_engine[] = {
 	{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
 	{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
 	{ 0x06, "SCHED" },
-	{ 0x07, "HOST0" },
-	{ 0x08, "HOST1" },
-	{ 0x09, "HOST2" },
-	{ 0x0a, "HOST3" },
-	{ 0x0b, "HOST4" },
-	{ 0x0c, "HOST5" },
-	{ 0x0d, "HOST6" },
-	{ 0x0e, "HOST7" },
+	{ 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO },
+	{ 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO },
+	{ 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO },
 	{ 0x0f, "HOSTSR" },
 	{ 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
 	{ 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,14 +32,14 @@ gm107_fifo_fault_engine[] = {
 	{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
 	{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
 	{ 0x06, "SCHED" },
-	{ 0x07, "HOST0" },
-	{ 0x08, "HOST1" },
-	{ 0x09, "HOST2" },
-	{ 0x0a, "HOST3" },
-	{ 0x0b, "HOST4" },
-	{ 0x0c, "HOST5" },
-	{ 0x0d, "HOST6" },
-	{ 0x0e, "HOST7" },
+	{ 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO },
+	{ 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO },
+	{ 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO },
 	{ 0x0f, "HOSTSR" },
 	{ 0x13, "PERF" },
 	{ 0x17, "PMU" },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,17 +30,17 @@ gp100_fifo_fault_engine[] = {
 	{ 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
 	{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
 	{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
-	{ 0x06, "HOST0" },
-	{ 0x07, "HOST1" },
-	{ 0x08, "HOST2" },
-	{ 0x09, "HOST3" },
-	{ 0x0a, "HOST4" },
-	{ 0x0b, "HOST5" },
-	{ 0x0c, "HOST6" },
-	{ 0x0d, "HOST7" },
-	{ 0x0e, "HOST8" },
-	{ 0x0f, "HOST9" },
-	{ 0x10, "HOST10" },
+	{ 0x06, "HOST0", NULL, NVKM_ENGINE_FIFO },
+	{ 0x07, "HOST1", NULL, NVKM_ENGINE_FIFO },
+	{ 0x08, "HOST2", NULL, NVKM_ENGINE_FIFO },
+	{ 0x09, "HOST3", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0a, "HOST4", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0b, "HOST5", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0c, "HOST6", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0d, "HOST7", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0e, "HOST8", NULL, NVKM_ENGINE_FIFO },
+	{ 0x0f, "HOST9", NULL, NVKM_ENGINE_FIFO },
+	{ 0x10, "HOST10", NULL, NVKM_ENGINE_FIFO },
 	{ 0x13, "PERF" },
 	{ 0x17, "PMU" },
 	{ 0x18, "PTP" },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -60,6 +60,7 @@ gf100_fifo_gpfifo_engine_fini(struct nvk
 	struct nvkm_gpuobj *inst = chan->base.inst;
 	int ret = 0;
 
+	mutex_lock(&subdev->mutex);
 	nvkm_wr32(device, 0x002634, chan->base.chid);
 	if (nvkm_msec(device, 2000,
 		if (nvkm_rd32(device, 0x002634) == chan->base.chid)
@@ -67,10 +68,12 @@ gf100_fifo_gpfifo_engine_fini(struct nvk
 	) < 0) {
 		nvkm_error(subdev, "channel %d [%s] kick timeout\n",
 			   chan->base.chid, chan->base.object.client->name);
-		ret = -EBUSY;
-		if (suspend)
-			return ret;
+		ret = -ETIMEDOUT;
 	}
+	mutex_unlock(&subdev->mutex);
+
+	if (ret && suspend)
+		return ret;
 
 	if (offset) {
 		nvkm_kmap(inst);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,9 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo
 	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
 	struct nvkm_client *client = chan->base.object.client;
+	int ret = 0;
 
+	mutex_lock(&subdev->mutex);
 	nvkm_wr32(device, 0x002634, chan->base.chid);
 	if (nvkm_msec(device, 2000,
 		if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
@@ -48,10 +50,10 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo
 	) < 0) {
 		nvkm_error(subdev, "channel %d [%s] kick timeout\n",
 			   chan->base.chid, client->name);
-		return -EBUSY;
+		ret = -ETIMEDOUT;
 	}
-
-	return 0;
+	mutex_unlock(&subdev->mutex);
+	return ret;
 }
 
 static u32
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c	2017-02-12 16:03:20.000000000 -0500
@@ -218,7 +218,7 @@ gf117_grctx_generate_attrib(struct gf100
 	}
 }
 
-void
+static void
 gf117_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c	2017-02-12 16:03:20.000000000 -0500
@@ -933,7 +933,7 @@ gm107_grctx_generate_attrib(struct gf100
 	}
 }
 
-void
+static void
 gm107_grctx_generate_tpcid(struct gf100_gr *gr)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxnv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -106,6 +106,7 @@
 #define CP_SEEK_2      0x00c800ff
 
 #include "ctxnv40.h"
+#include "nv50.h"
 
 #include <subdev/fb.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf100.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gf100_grgpc_data[] = {
+static uint32_t gf100_grgpc_data[] = {
 /* 0x0000: gpc_mmio_list_head */
 	0x00000064,
 /* 0x0004: gpc_mmio_list_tail */
@@ -36,7 +36,7 @@ uint32_t gf100_grgpc_data[] = {
 	0x00000000,
 };
 
-uint32_t gf100_grgpc_code[] = {
+static uint32_t gf100_grgpc_code[] = {
 	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgf117.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gf117_grgpc_data[] = {
+static uint32_t gf117_grgpc_data[] = {
 /* 0x0000: gpc_mmio_list_head */
 	0x0000006c,
 /* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gf117_grgpc_data[] = {
 	0x00000000,
 };
 
-uint32_t gf117_grgpc_code[] = {
+static uint32_t gf117_grgpc_code[] = {
 	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk104.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gk104_grgpc_data[] = {
+static uint32_t gk104_grgpc_data[] = {
 /* 0x0000: gpc_mmio_list_head */
 	0x0000006c,
 /* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gk104_grgpc_data[] = {
 	0x00000000,
 };
 
-uint32_t gk104_grgpc_code[] = {
+static uint32_t gk104_grgpc_code[] = {
 	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk110.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gk110_grgpc_data[] = {
+static uint32_t gk110_grgpc_data[] = {
 /* 0x0000: gpc_mmio_list_head */
 	0x0000006c,
 /* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gk110_grgpc_data[] = {
 	0x00000000,
 };
 
-uint32_t gk110_grgpc_code[] = {
+static uint32_t gk110_grgpc_code[] = {
 	0x03a10ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgk208.fuc5.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gk208_grgpc_data[] = {
+static uint32_t gk208_grgpc_data[] = {
 /* 0x0000: gpc_mmio_list_head */
 	0x0000006c,
 /* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gk208_grgpc_data[] = {
 	0x00000000,
 };
 
-uint32_t gk208_grgpc_code[] = {
+static uint32_t gk208_grgpc_code[] = {
 	0x03140ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/gpcgm107.fuc5.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gm107_grgpc_data[] = {
+static uint32_t gm107_grgpc_data[] = {
 /* 0x0000: gpc_mmio_list_head */
 	0x0000006c,
 /* 0x0004: gpc_mmio_list_tail */
@@ -40,7 +40,7 @@ uint32_t gm107_grgpc_data[] = {
 	0x00000000,
 };
 
-uint32_t gm107_grgpc_code[] = {
+static uint32_t gm107_grgpc_code[] = {
 	0x03410ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf100.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gf100_grhub_data[] = {
+static uint32_t gf100_grhub_data[] = {
 /* 0x0000: hub_mmio_list_head */
 	0x00000300,
 /* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gf100_grhub_data[] = {
 	0x0417e91c,
 };
 
-uint32_t gf100_grhub_code[] = {
+static uint32_t gf100_grhub_code[] = {
 	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgf117.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gf117_grhub_data[] = {
+static uint32_t gf117_grhub_data[] = {
 /* 0x0000: hub_mmio_list_head */
 	0x00000300,
 /* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gf117_grhub_data[] = {
 	0x0417e91c,
 };
 
-uint32_t gf117_grhub_code[] = {
+static uint32_t gf117_grhub_code[] = {
 	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk104.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gk104_grhub_data[] = {
+static uint32_t gk104_grhub_data[] = {
 /* 0x0000: hub_mmio_list_head */
 	0x00000300,
 /* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gk104_grhub_data[] = {
 	0x0417e91c,
 };
 
-uint32_t gk104_grhub_code[] = {
+static uint32_t gk104_grhub_code[] = {
 	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk110.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gk110_grhub_data[] = {
+static uint32_t gk110_grhub_data[] = {
 /* 0x0000: hub_mmio_list_head */
 	0x00000300,
 /* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gk110_grhub_data[] = {
 	0x0417e91c,
 };
 
-uint32_t gk110_grhub_code[] = {
+static uint32_t gk110_grhub_code[] = {
 	0x039b0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgk208.fuc5.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gk208_grhub_data[] = {
+static uint32_t gk208_grhub_data[] = {
 /* 0x0000: hub_mmio_list_head */
 	0x00000300,
 /* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gk208_grhub_data[] = {
 	0x0417e91c,
 };
 
-uint32_t gk208_grhub_code[] = {
+static uint32_t gk208_grhub_code[] = {
 	0x030e0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/fuc/hubgm107.fuc5.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gm107_grhub_data[] = {
+static uint32_t gm107_grhub_data[] = {
 /* 0x0000: hub_mmio_list_head */
 	0x00000300,
 /* 0x0004: hub_mmio_list_tail */
@@ -205,7 +205,7 @@ uint32_t gm107_grhub_data[] = {
 	0x0417e91c,
 };
 
-uint32_t gm107_grhub_code[] = {
+static uint32_t gm107_grhub_code[] = {
 	0x030e0ef5,
 /* 0x0004: queue_put */
 	0x9800d898,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -1041,6 +1041,13 @@ gf100_gr_trap_tpc(struct gf100_gr *gr, i
 		stat &= ~0x00000008;
 	}
 
+	if (stat & 0x00000010) {
+		u32 trap = nvkm_rd32(device, TPC_UNIT(gpc, tpc, 0x0430));
+		nvkm_error(subdev, "GPC%d/TPC%d/MPC: %08x\n", gpc, tpc, trap);
+		nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x0430), 0xc0000000);
+		stat &= ~0x00000010;
+	}
+
 	if (stat) {
 		nvkm_error(subdev, "GPC%d/TPC%d/%08x: unknown\n", gpc, tpc, stat);
 	}
@@ -1258,7 +1265,7 @@ gf100_gr_ctxctl_isr(struct gf100_gr *gr)
 	struct nvkm_device *device = subdev->device;
 	u32 stat = nvkm_rd32(device, 0x409c18);
 
-	if (stat & 0x00000001) {
+	if (!gr->firmware && (stat & 0x00000001)) {
 		u32 code = nvkm_rd32(device, 0x409814);
 		if (code == E_BAD_FWMTHD) {
 			u32 class = nvkm_rd32(device, 0x409808);
@@ -1270,15 +1277,14 @@ gf100_gr_ctxctl_isr(struct gf100_gr *gr)
 			nvkm_error(subdev, "FECS MTHD subc %d class %04x "
 					   "mthd %04x data %08x\n",
 				   subc, class, mthd, data);
-
-			nvkm_wr32(device, 0x409c20, 0x00000001);
-			stat &= ~0x00000001;
 		} else {
 			nvkm_error(subdev, "FECS ucode error %d\n", code);
 		}
+		nvkm_wr32(device, 0x409c20, 0x00000001);
+		stat &= ~0x00000001;
 	}
 
-	if (stat & 0x00080000) {
+	if (!gr->firmware && (stat & 0x00080000)) {
 		nvkm_error(subdev, "FECS watchdog timeout\n");
 		gf100_gr_ctxctl_debug(gr);
 		nvkm_wr32(device, 0x409c20, 0x00080000);
@@ -1384,7 +1390,7 @@ gf100_gr_intr(struct nvkm_gr *base)
 	nvkm_fifo_chan_put(device->fifo, flags, &chan);
 }
 
-void
+static void
 gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
 		 struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
 {
@@ -1701,7 +1707,7 @@ gf100_gr_oneinit(struct nvkm_gr *base)
 	return 0;
 }
 
-int
+static int
 gf100_gr_init_(struct nvkm_gr *base)
 {
 	struct gf100_gr *gr = gf100_gr(base);
@@ -1756,6 +1762,50 @@ gf100_gr_ = {
 };
 
 int
+gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname,
+			struct gf100_gr_fuc *fuc, int ret)
+{
+	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+	struct nvkm_device *device = subdev->device;
+	const struct firmware *fw;
+	char f[32];
+
+	/* see if this firmware has a legacy path */
+	if (!strcmp(fwname, "fecs_inst"))
+		fwname = "fuc409c";
+	else if (!strcmp(fwname, "fecs_data"))
+		fwname = "fuc409d";
+	else if (!strcmp(fwname, "gpccs_inst"))
+		fwname = "fuc41ac";
+	else if (!strcmp(fwname, "gpccs_data"))
+		fwname = "fuc41ad";
+	else {
+		/* nope, let's just return the error we got */
+		nvkm_error(subdev, "failed to load %s\n", fwname);
+		return ret;
+	}
+
+	/* yes, try to load from the legacy path */
+	nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname);
+
+	snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
+	ret = request_firmware(&fw, f, device->dev);
+	if (ret) {
+		snprintf(f, sizeof(f), "nouveau/%s", fwname);
+		ret = request_firmware(&fw, f, device->dev);
+		if (ret) {
+			nvkm_error(subdev, "failed to load %s\n", fwname);
+			return ret;
+		}
+	}
+
+	fuc->size = fw->size;
+	fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
+	release_firmware(fw);
+	return (fuc->data != NULL) ? 0 : -ENOMEM;
+}
+
+int
 gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
 		 struct gf100_gr_fuc *fuc)
 {
@@ -1765,10 +1815,8 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, co
 	int ret;
 
 	ret = nvkm_firmware_get(device, fwname, &fw);
-	if (ret) {
-		nvkm_error(subdev, "failed to load %s\n", fwname);
-		return ret;
-	}
+	if (ret)
+		return gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret);
 
 	fuc->size = fw->size;
 	fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,7 @@ gf117_gr_pack_mmio[] = {
 
 #include "fuc/hubgf117.fuc3.h"
 
-struct gf100_gr_ucode
+static struct gf100_gr_ucode
 gf117_gr_fecs_ucode = {
 	.code.data = gf117_grhub_code,
 	.code.size = sizeof(gf117_grhub_code),
@@ -112,7 +112,7 @@ gf117_gr_fecs_ucode = {
 
 #include "fuc/gpcgf117.fuc3.h"
 
-struct gf100_gr_ucode
+static struct gf100_gr_ucode
 gf117_gr_gpccs_ucode = {
 	.code.data = gf117_grgpc_code,
 	.code.size = sizeof(gf117_grgpc_code),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c	2017-02-12 16:03:20.000000000 -0500
@@ -308,7 +308,7 @@ gm107_gr_init_bios(struct gf100_gr *gr)
 	}
 }
 
-int
+static int
 gm107_gr_init(struct gf100_gr *gr)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c	2017-02-12 16:03:20.000000000 -0500
@@ -187,6 +187,7 @@ nv30_gr = {
 		{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
 		{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
 		{ -1, -1, 0x0397, &nv04_gr_object }, /* rankine */
+		{ -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
 		{}
 	}
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c	2017-02-12 16:03:20.000000000 -0500
@@ -123,6 +123,7 @@ nv34_gr = {
 		{ -1, -1, 0x0389, &nv04_gr_object }, /* sifm (nv30) */
 		{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
 		{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
+		{ -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
 		{ -1, -1, 0x0697, &nv04_gr_object }, /* rankine */
 		{}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c	2017-02-12 16:03:20.000000000 -0500
@@ -124,6 +124,7 @@ nv35_gr = {
 		{ -1, -1, 0x038a, &nv04_gr_object }, /* ifc (nv30) */
 		{ -1, -1, 0x039e, &nv04_gr_object }, /* swzsurf (nv30) */
 		{ -1, -1, 0x0497, &nv04_gr_object }, /* rankine */
+		{ -1, -1, 0x0597, &nv04_gr_object }, /* kelvin */
 		{}
 	}
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,7 @@ nvkm_perfdom_find(struct nvkm_pm *pm, in
 	return NULL;
 }
 
-struct nvkm_perfsig *
+static struct nvkm_perfsig *
 nvkm_perfsig_find(struct nvkm_pm *pm, u8 di, u8 si, struct nvkm_perfdom **pdom)
 {
 	struct nvkm_perfdom *dom = *pdom;
@@ -699,7 +699,7 @@ nvkm_pm_oclass_get(struct nvkm_oclass *o
 	return 1;
 }
 
-int
+static int
 nvkm_perfsrc_new(struct nvkm_pm *pm, struct nvkm_perfsig *sig,
 		 const struct nvkm_specsrc *spec)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/pm/gf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,7 @@ gf100_pm_gpc[] = {
 	{}
 };
 
-const struct nvkm_specdom
+static const struct nvkm_specdom
 gf100_pm_part[] = {
 	{ 0xe0, (const struct nvkm_specsig[]) {
 			{ 0x0f, "part00_pbfb_00", gf100_pbfb_sources },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/engine/sec/fuc/g98.fuc0s.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t g98_sec_data[] = {
+static uint32_t g98_sec_data[] = {
 /* 0x0000: ctx_dma */
 /* 0x0000: ctx_dma_query */
 	0x00000000,
@@ -150,7 +150,7 @@ uint32_t g98_sec_data[] = {
 	0x00000000,
 };
 
-uint32_t g98_sec_code[] = {
+static uint32_t g98_sec_code[] = {
 	0x17f004bd,
 	0x0010fe35,
 	0xf10004fe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,7 @@ nv50_bar_oneinit(struct nvkm_bar *base)
 	start = 0x0100000000ULL;
 	limit = start + device->func->resource_size(device, 3);
 
-	ret = nvkm_vm_new(device, start, limit, start, &bar3_lock, &vm);
+	ret = nvkm_vm_new(device, start, limit - start, start, &bar3_lock, &vm);
 	if (ret)
 		return ret;
 
@@ -117,7 +117,7 @@ nv50_bar_oneinit(struct nvkm_bar *base)
 	start = 0x0000000000ULL;
 	limit = start + device->func->resource_size(device, 1);
 
-	ret = nvkm_vm_new(device, start, limit--, start, &bar1_lock, &vm);
+	ret = nvkm_vm_new(device, start, limit-- - start, start, &bar1_lock, &vm);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/boost.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,16 +25,16 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/boost.h>
 
-u16
+u32
 nvbios_boostTe(struct nvkm_bios *bios,
 	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
 	struct bit_entry bit_P;
-	u16 boost = 0x0000;
+	u32 boost = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version == 2)
-			boost = nvbios_rd16(bios, bit_P.offset + 0x30);
+			boost = nvbios_rd32(bios, bit_P.offset + 0x30);
 
 		if (boost) {
 			*ver = nvbios_rd08(bios, boost + 0);
@@ -52,15 +52,15 @@ nvbios_boostTe(struct nvkm_bios *bios,
 		}
 	}
 
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_boostEe(struct nvkm_bios *bios, int idx,
 	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	u8  snr, ssz;
-	u16 data = nvbios_boostTe(bios, ver, hdr, cnt, len, &snr, &ssz);
+	u32 data = nvbios_boostTe(bios, ver, hdr, cnt, len, &snr, &ssz);
 	if (data && idx < *cnt) {
 		data = data + *hdr + (idx * (*len + (snr * ssz)));
 		*hdr = *len;
@@ -68,14 +68,14 @@ nvbios_boostEe(struct nvkm_bios *bios, i
 		*len = ssz;
 		return data;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_boostEp(struct nvkm_bios *bios, int idx,
 	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info)
 {
-	u16 data = nvbios_boostEe(bios, idx, ver, hdr, cnt, len);
+	u32 data = nvbios_boostEe(bios, idx, ver, hdr, cnt, len);
 	memset(info, 0x00, sizeof(*info));
 	if (data) {
 		info->pstate = (nvbios_rd16(bios, data + 0x00) & 0x01e0) >> 5;
@@ -85,7 +85,7 @@ nvbios_boostEp(struct nvkm_bios *bios, i
 	return data;
 }
 
-u16
+u32
 nvbios_boostEm(struct nvkm_bios *bios, u8 pstate,
 	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_boostE *info)
 {
@@ -97,21 +97,21 @@ nvbios_boostEm(struct nvkm_bios *bios, u
 	return data;
 }
 
-u16
+u32
 nvbios_boostSe(struct nvkm_bios *bios, int idx,
-	       u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len)
+	       u32 data, u8 *ver, u8 *hdr, u8 cnt, u8 len)
 {
 	if (data && idx < cnt) {
 		data = data + *hdr + (idx * len);
 		*hdr = len;
 		return data;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_boostSp(struct nvkm_bios *bios, int idx,
-	       u16 data, u8 *ver, u8 *hdr, u8 cnt, u8 len,
+	       u32 data, u8 *ver, u8 *hdr, u8 cnt, u8 len,
 	       struct nvbios_boostS *info)
 {
 	data = nvbios_boostSe(bios, idx, data, ver, hdr, cnt, len);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/cstep.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,16 +25,16 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/cstep.h>
 
-u16
+u32
 nvbios_cstepTe(struct nvkm_bios *bios,
 	       u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *xnr, u8 *xsz)
 {
 	struct bit_entry bit_P;
-	u16 cstep = 0x0000;
+	u32 cstep = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version == 2)
-			cstep = nvbios_rd16(bios, bit_P.offset + 0x34);
+			cstep = nvbios_rd32(bios, bit_P.offset + 0x34);
 
 		if (cstep) {
 			*ver = nvbios_rd08(bios, cstep + 0);
@@ -52,27 +52,27 @@ nvbios_cstepTe(struct nvkm_bios *bios,
 		}
 	}
 
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_cstepEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
 {
 	u8  cnt, len, xnr, xsz;
-	u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
+	u32 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
 	if (data && idx < cnt) {
 		data = data + *hdr + (idx * len);
 		*hdr = len;
 		return data;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_cstepEp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
 	       struct nvbios_cstepE *info)
 {
-	u16 data = nvbios_cstepEe(bios, idx, ver, hdr);
+	u32 data = nvbios_cstepEe(bios, idx, ver, hdr);
 	memset(info, 0x00, sizeof(*info));
 	if (data) {
 		info->pstate = (nvbios_rd16(bios, data + 0x00) & 0x01e0) >> 5;
@@ -81,7 +81,7 @@ nvbios_cstepEp(struct nvkm_bios *bios, i
 	return data;
 }
 
-u16
+u32
 nvbios_cstepEm(struct nvkm_bios *bios, u8 pstate, u8 *ver, u8 *hdr,
 	       struct nvbios_cstepE *info)
 {
@@ -93,24 +93,24 @@ nvbios_cstepEm(struct nvkm_bios *bios, u
 	return data;
 }
 
-u16
+u32
 nvbios_cstepXe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr)
 {
 	u8  cnt, len, xnr, xsz;
-	u16 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
+	u32 data = nvbios_cstepTe(bios, ver, hdr, &cnt, &len, &xnr, &xsz);
 	if (data && idx < xnr) {
 		data = data + *hdr + (cnt * len) + (idx * xsz);
 		*hdr = xsz;
 		return data;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_cstepXp(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
 	       struct nvbios_cstepX *info)
 {
-	u16 data = nvbios_cstepXe(bios, idx, ver, hdr);
+	u32 data = nvbios_cstepXe(bios, idx, ver, hdr);
 	memset(info, 0x00, sizeof(*info));
 	if (data) {
 		info->freq    = nvbios_rd16(bios, data + 0x00) * 1000;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/dp.c	2017-02-12 16:03:20.000000000 -0500
@@ -207,8 +207,11 @@ nvbios_dpcfg_match(struct nvkm_bios *bio
 	if (*ver >= 0x30) {
 		const u8 vsoff[] = { 0, 4, 7, 9 };
 		idx = (pc * 10) + vsoff[vs] + pe;
-		if (*ver >= 0x40 && *hdr >= 0x12)
+		if (*ver >= 0x40 && *ver <= 0x41 && *hdr >= 0x12)
 			idx += nvbios_rd08(bios, outp + 0x11) * 40;
+		else
+		if (*ver >= 0x42)
+			idx += nvbios_rd08(bios, outp + 0x11) * 10;
 	} else {
 		while ((data = nvbios_dpcfg_entry(bios, outp, ++idx,
 						  ver, hdr, cnt, len))) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,15 +25,15 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/fan.h>
 
-u16
+static u32
 nvbios_fan_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	struct bit_entry bit_P;
-	u16 fan = 0x0000;
+	u32 fan = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version == 2 && bit_P.length >= 0x5a)
-			fan = nvbios_rd16(bios, bit_P.offset + 0x58);
+			fan = nvbios_rd32(bios, bit_P.offset + 0x58);
 
 		if (fan) {
 			*ver = nvbios_rd08(bios, fan + 0);
@@ -49,25 +49,25 @@ nvbios_fan_table(struct nvkm_bios *bios,
 		}
 	}
 
-	return 0x0000;
+	return 0;
 }
 
-u16
+static u32
 nvbios_fan_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
 		 u8 *cnt, u8 *len)
 {
-	u16 data = nvbios_fan_table(bios, ver, hdr, cnt, len);
+	u32 data = nvbios_fan_table(bios, ver, hdr, cnt, len);
 	if (data && idx < *cnt)
 		return data + *hdr + (idx * (*len));
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan)
 {
 	u8 ver, hdr, cnt, len;
 
-	u16 data = nvbios_fan_entry(bios, 0, &ver, &hdr, &cnt, &len);
+	u32 data = nvbios_fan_entry(bios, 0, &ver, &hdr, &cnt, &len);
 	if (data) {
 		u8 type = nvbios_rd08(bios, data + 0x00);
 		switch (type) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,20 +23,21 @@
  */
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
+#include <subdev/bios/extdev.h>
 #include <subdev/bios/iccsense.h>
 
-static u16
+static u32
 nvbios_iccsense_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt,
 		      u8 *len)
 {
 	struct bit_entry bit_P;
-	u16 iccsense;
+	u32 iccsense;
 
 	if (bit_entry(bios, 'P', &bit_P) || bit_P.version != 2 ||
 	    bit_P.length < 0x2c)
 		return 0;
 
-	iccsense = nvbios_rd16(bios, bit_P.offset + 0x28);
+	iccsense = nvbios_rd32(bios, bit_P.offset + 0x28);
 	if (!iccsense)
 		return 0;
 
@@ -60,7 +61,7 @@ nvbios_iccsense_parse(struct nvkm_bios *
 {
 	struct nvkm_subdev *subdev = &bios->subdev;
 	u8 ver, hdr, cnt, len, i;
-	u16 table, entry;
+	u32 table, entry;
 
 	table = nvbios_iccsense_table(bios, &ver, &hdr, &cnt, &len);
 	if (!table || !cnt)
@@ -77,23 +78,47 @@ nvbios_iccsense_parse(struct nvkm_bios *
 		return -ENOMEM;
 
 	for (i = 0; i < cnt; ++i) {
+		struct nvbios_extdev_func extdev;
 		struct pwr_rail_t *rail = &iccsense->rail[i];
+		u8 res_start = 0;
+		int r;
+
 		entry = table + hdr + i * len;
 
 		switch(ver) {
 		case 0x10:
 			rail->mode = nvbios_rd08(bios, entry + 0x1);
 			rail->extdev_id = nvbios_rd08(bios, entry + 0x2);
-			rail->resistor_mohm = nvbios_rd08(bios, entry + 0x3);
-			rail->rail = nvbios_rd08(bios, entry + 0x4);
+			res_start = 0x3;
 			break;
 		case 0x20:
 			rail->mode = nvbios_rd08(bios, entry);
 			rail->extdev_id = nvbios_rd08(bios, entry + 0x1);
-			rail->resistor_mohm = nvbios_rd08(bios, entry + 0x5);
-			rail->rail = nvbios_rd08(bios, entry + 0x6);
+			res_start = 0x5;
 			break;
 		};
+
+		if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev))
+			continue;
+
+		switch (extdev.type) {
+		case NVBIOS_EXTDEV_INA209:
+		case NVBIOS_EXTDEV_INA219:
+			rail->resistor_count = 1;
+			break;
+		case NVBIOS_EXTDEV_INA3221:
+			rail->resistor_count = 3;
+			break;
+		default:
+			rail->resistor_count = 0;
+			break;
+		};
+
+		for (r = 0; r < rail->resistor_count; ++r) {
+			rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2);
+			rail->resistors[r].enabled = !(nvbios_rd08(bios, entry + res_start + r * 2 + 1) & 0x40);
+		}
+		rail->config = nvbios_rd16(bios, entry + res_start + rail->resistor_count * 2);
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@ nvkm-y += nvkm/subdev/bios/timing.o
 nvkm-y += nvkm/subdev/bios/therm.o
 nvkm-y += nvkm/subdev/bios/vmap.o
 nvkm-y += nvkm/subdev/bios/volt.o
+nvkm-y += nvkm/subdev/bios/vpstate.o
 nvkm-y += nvkm/subdev/bios/xpio.o
 nvkm-y += nvkm/subdev/bios/M0203.o
 nvkm-y += nvkm/subdev/bios/M0205.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/mxm.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,7 +81,7 @@ mxm_sor_map(struct nvkm_bios *bios, u8 c
 		u16 map = nvbios_rd16(bios, mxm + 4);
 		if (map) {
 			ver = nvbios_rd08(bios, map);
-			if (ver == 0x10) {
+			if (ver == 0x10 || ver == 0x11) {
 				if (conn < nvbios_rd08(bios, map + 3)) {
 					map += nvbios_rd08(bios, map + 1);
 					map += conn;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/perf.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,16 +26,16 @@
 #include <subdev/bios/perf.h>
 #include <subdev/pci.h>
 
-u16
+u32
 nvbios_perf_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr,
 		  u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
 	struct bit_entry bit_P;
-	u16 perf = 0x0000;
+	u32 perf = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version <= 2) {
-			perf = nvbios_rd16(bios, bit_P.offset + 0);
+			perf = nvbios_rd32(bios, bit_P.offset + 0);
 			if (perf) {
 				*ver = nvbios_rd08(bios, perf + 0);
 				*hdr = nvbios_rd08(bios, perf + 1);
@@ -72,15 +72,15 @@ nvbios_perf_table(struct nvkm_bios *bios
 		}
 	}
 
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_perf_entry(struct nvkm_bios *bios, int idx,
 		  u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	u8  snr, ssz;
-	u16 perf = nvbios_perf_table(bios, ver, hdr, cnt, len, &snr, &ssz);
+	u32 perf = nvbios_perf_table(bios, ver, hdr, cnt, len, &snr, &ssz);
 	if (perf && idx < *cnt) {
 		perf = perf + *hdr + (idx * (*len + (snr * ssz)));
 		*hdr = *len;
@@ -88,14 +88,14 @@ nvbios_perf_entry(struct nvkm_bios *bios
 		*len = ssz;
 		return perf;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_perfEp(struct nvkm_bios *bios, int idx,
 	      u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_perfE *info)
 {
-	u16 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len);
+	u32 perf = nvbios_perf_entry(bios, idx, ver, hdr, cnt, len);
 	memset(info, 0x00, sizeof(*info));
 	info->pstate = nvbios_rd08(bios, perf + 0x00);
 	switch (!!perf * *ver) {
@@ -163,7 +163,7 @@ nvbios_perfEp(struct nvkm_bios *bios, in
 		info->pcie_width = 0xff;
 		break;
 	default:
-		return 0x0000;
+		return 0;
 	}
 	return perf;
 }
@@ -202,7 +202,7 @@ nvbios_perf_fan_parse(struct nvkm_bios *
 		      struct nvbios_perf_fan *fan)
 {
 	u8  ver, hdr, cnt, len, snr, ssz;
-	u16 perf = nvbios_perf_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
+	u32 perf = nvbios_perf_table(bios, &ver, &hdr, &cnt, &len, &snr, &ssz);
 	if (!perf)
 		return -ENODEV;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@ struct nvbios_source {
 	bool rw;
 	bool ignore_checksum;
 	bool no_pcir;
+	bool require_checksum;
 };
 
 int nvbios_extend(struct nvkm_bios *, u32 length);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -99,6 +99,7 @@ nvbios_acpi_fast = {
 	.init = acpi_init,
 	.read = acpi_read_fast,
 	.rw = false,
+	.require_checksum = true,
 };
 
 const struct nvbios_source
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c	2017-02-12 16:03:20.000000000 -0500
@@ -86,9 +86,12 @@ shadow_image(struct nvkm_bios *bios, int
 		    nvbios_checksum(&bios->data[image.base], image.size)) {
 			nvkm_debug(subdev, "%08x: checksum failed\n",
 				   image.base);
-			if (mthd->func->rw)
+			if (!mthd->func->require_checksum) {
+				if (mthd->func->rw)
+					score += 1;
 				score += 1;
-			score += 1;
+			} else
+				return 0;
 		} else {
 			score += 3;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/therm.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,17 +25,17 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/therm.h>
 
-static u16
+static u32
 therm_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt)
 {
 	struct bit_entry bit_P;
-	u16 therm = 0;
+	u32 therm = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version == 1)
-			therm = nvbios_rd16(bios, bit_P.offset + 12);
+			therm = nvbios_rd32(bios, bit_P.offset + 12);
 		else if (bit_P.version == 2)
-			therm = nvbios_rd16(bios, bit_P.offset + 16);
+			therm = nvbios_rd32(bios, bit_P.offset + 16);
 		else
 			nvkm_error(&bios->subdev,
 				   "unknown offset for thermal in BIT P %d\n",
@@ -44,7 +44,7 @@ therm_table(struct nvkm_bios *bios, u8 *
 
 	/* exit now if we haven't found the thermal table */
 	if (!therm)
-		return 0x0000;
+		return 0;
 
 	*ver = nvbios_rd08(bios, therm + 0);
 	*hdr = nvbios_rd08(bios, therm + 1);
@@ -53,14 +53,14 @@ therm_table(struct nvkm_bios *bios, u8 *
 	return therm + nvbios_rd08(bios, therm + 1);
 }
 
-static u16
+static u32
 nvbios_therm_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
 {
 	u8 hdr, cnt;
-	u16 therm = therm_table(bios, ver, &hdr, len, &cnt);
+	u32 therm = therm_table(bios, ver, &hdr, len, &cnt);
 	if (therm && idx < cnt)
 		return therm + idx * *len;
-	return 0x0000;
+	return 0;
 }
 
 int
@@ -70,7 +70,7 @@ nvbios_therm_sensor_parse(struct nvkm_bi
 {
 	s8 thrs_section, sensor_section, offset;
 	u8 ver, len, i;
-	u16 entry;
+	u32 entry;
 
 	/* we only support the core domain for now */
 	if (domain != NVBIOS_THERM_DOMAIN_CORE)
@@ -154,7 +154,7 @@ nvbios_therm_fan_parse(struct nvkm_bios
 {
 	struct nvbios_therm_trip_point *cur_trip = NULL;
 	u8 ver, len, i;
-	u16 entry;
+	u32 entry;
 
 	uint8_t duty_lut[] = { 0, 0, 25, 0, 40, 0, 50, 0,
 				75, 0, 85, 0, 100, 0, 100, 0 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,19 +25,19 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/timing.h>
 
-u16
+u32
 nvbios_timingTe(struct nvkm_bios *bios,
 		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, u8 *snr, u8 *ssz)
 {
 	struct bit_entry bit_P;
-	u16 timing = 0x0000;
+	u32 timing = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version == 1)
-			timing = nvbios_rd16(bios, bit_P.offset + 4);
+			timing = nvbios_rd32(bios, bit_P.offset + 4);
 		else
 		if (bit_P.version == 2)
-			timing = nvbios_rd16(bios, bit_P.offset + 8);
+			timing = nvbios_rd32(bios, bit_P.offset + 8);
 
 		if (timing) {
 			*ver = nvbios_rd08(bios, timing + 0);
@@ -62,15 +62,15 @@ nvbios_timingTe(struct nvkm_bios *bios,
 		}
 	}
 
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_timingEe(struct nvkm_bios *bios, int idx,
 		u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	u8  snr, ssz;
-	u16 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz);
+	u32 timing = nvbios_timingTe(bios, ver, hdr, cnt, len, &snr, &ssz);
 	if (timing && idx < *cnt) {
 		timing += *hdr + idx * (*len + (snr * ssz));
 		*hdr = *len;
@@ -78,14 +78,14 @@ nvbios_timingEe(struct nvkm_bios *bios,
 		*len = ssz;
 		return timing;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_timingEp(struct nvkm_bios *bios, int idx,
 		u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_ramcfg *p)
 {
-	u16 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
+	u32 data = nvbios_timingEe(bios, idx, ver, hdr, cnt, len), temp;
 	p->timing_ver = *ver;
 	p->timing_hdr = *hdr;
 	switch (!!data * *ver) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vmap.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,15 +25,15 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/vmap.h>
 
-u16
+u32
 nvbios_vmap_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	struct bit_entry bit_P;
-	u16 vmap = 0x0000;
+	u32 vmap = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version == 2) {
-			vmap = nvbios_rd16(bios, bit_P.offset + 0x20);
+			vmap = nvbios_rd32(bios, bit_P.offset + 0x20);
 			if (vmap) {
 				*ver = nvbios_rd08(bios, vmap + 0);
 				switch (*ver) {
@@ -50,40 +50,50 @@ nvbios_vmap_table(struct nvkm_bios *bios
 		}
 	}
 
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_vmap_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
 		  struct nvbios_vmap *info)
 {
-	u16 vmap = nvbios_vmap_table(bios, ver, hdr, cnt, len);
+	u32 vmap = nvbios_vmap_table(bios, ver, hdr, cnt, len);
 	memset(info, 0x00, sizeof(*info));
 	switch (!!vmap * *ver) {
 	case 0x10:
+		info->max0 = 0xff;
+		info->max1 = 0xff;
+		info->max2 = 0xff;
+		break;
 	case 0x20:
+		info->max0 = nvbios_rd08(bios, vmap + 0x7);
+		info->max1 = nvbios_rd08(bios, vmap + 0x8);
+		if (*len >= 0xc)
+			info->max2 = nvbios_rd08(bios, vmap + 0xc);
+		else
+			info->max2 = 0xff;
 		break;
 	}
 	return vmap;
 }
 
-u16
+u32
 nvbios_vmap_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
 {
 	u8  hdr, cnt;
-	u16 vmap = nvbios_vmap_table(bios, ver, &hdr, &cnt, len);
+	u32 vmap = nvbios_vmap_table(bios, ver, &hdr, &cnt, len);
 	if (vmap && idx < cnt) {
 		vmap = vmap + hdr + (idx * *len);
 		return vmap;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_vmap_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
 			struct nvbios_vmap_entry *info)
 {
-	u16 vmap = nvbios_vmap_entry(bios, idx, ver, len);
+	u32 vmap = nvbios_vmap_entry(bios, idx, ver, len);
 	memset(info, 0x00, sizeof(*info));
 	switch (!!vmap * *ver) {
 	case 0x10:
@@ -95,7 +105,7 @@ nvbios_vmap_entry_parse(struct nvkm_bios
 		info->arg[2] = nvbios_rd32(bios, vmap + 0x10);
 		break;
 	case 0x20:
-		info->unk0   = nvbios_rd08(bios, vmap + 0x00);
+		info->mode   = nvbios_rd08(bios, vmap + 0x00);
 		info->link   = nvbios_rd08(bios, vmap + 0x01);
 		info->min    = nvbios_rd32(bios, vmap + 0x02);
 		info->max    = nvbios_rd32(bios, vmap + 0x06);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,18 +25,18 @@
 #include <subdev/bios/bit.h>
 #include <subdev/bios/volt.h>
 
-u16
+u32
 nvbios_volt_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
 {
 	struct bit_entry bit_P;
-	u16 volt = 0x0000;
+	u32 volt = 0;
 
 	if (!bit_entry(bios, 'P', &bit_P)) {
 		if (bit_P.version == 2)
-			volt = nvbios_rd16(bios, bit_P.offset + 0x0c);
+			volt = nvbios_rd32(bios, bit_P.offset + 0x0c);
 		else
 		if (bit_P.version == 1)
-			volt = nvbios_rd16(bios, bit_P.offset + 0x10);
+			volt = nvbios_rd32(bios, bit_P.offset + 0x10);
 
 		if (volt) {
 			*ver = nvbios_rd08(bios, volt + 0);
@@ -62,33 +62,37 @@ nvbios_volt_table(struct nvkm_bios *bios
 		}
 	}
 
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len,
 		  struct nvbios_volt *info)
 {
-	u16 volt = nvbios_volt_table(bios, ver, hdr, cnt, len);
+	u32 volt = nvbios_volt_table(bios, ver, hdr, cnt, len);
 	memset(info, 0x00, sizeof(*info));
 	switch (!!volt * *ver) {
 	case 0x12:
 		info->type    = NVBIOS_VOLT_GPIO;
 		info->vidmask = nvbios_rd08(bios, volt + 0x04);
+		info->ranged  = false;
 		break;
 	case 0x20:
 		info->type    = NVBIOS_VOLT_GPIO;
 		info->vidmask = nvbios_rd08(bios, volt + 0x05);
+		info->ranged  = false;
 		break;
 	case 0x30:
 		info->type    = NVBIOS_VOLT_GPIO;
 		info->vidmask = nvbios_rd08(bios, volt + 0x04);
+		info->ranged  = false;
 		break;
 	case 0x40:
 		info->type    = NVBIOS_VOLT_GPIO;
 		info->base    = nvbios_rd32(bios, volt + 0x04);
 		info->step    = nvbios_rd16(bios, volt + 0x08);
 		info->vidmask = nvbios_rd08(bios, volt + 0x0b);
+		info->ranged  = true; /* XXX: find the flag byte */
 		/*XXX*/
 		info->min     = 0;
 		info->max     = info->base;
@@ -104,32 +108,34 @@ nvbios_volt_parse(struct nvkm_bios *bios
 			info->pwm_freq  = nvbios_rd32(bios, volt + 0x5) / 1000;
 			info->pwm_range = nvbios_rd32(bios, volt + 0x16);
 		} else {
-			info->type      = NVBIOS_VOLT_GPIO;
-			info->vidmask   = nvbios_rd08(bios, volt + 0x06);
-			info->step      = nvbios_rd16(bios, volt + 0x16);
+			info->type    = NVBIOS_VOLT_GPIO;
+			info->vidmask = nvbios_rd08(bios, volt + 0x06);
+			info->step    = nvbios_rd16(bios, volt + 0x16);
+			info->ranged  =
+				!!(nvbios_rd08(bios, volt + 0x4) & 0x2);
 		}
 		break;
 	}
 	return volt;
 }
 
-u16
+u32
 nvbios_volt_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len)
 {
 	u8  hdr, cnt;
-	u16 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len);
+	u32 volt = nvbios_volt_table(bios, ver, &hdr, &cnt, len);
 	if (volt && idx < cnt) {
 		volt = volt + hdr + (idx * *len);
 		return volt;
 	}
-	return 0x0000;
+	return 0;
 }
 
-u16
+u32
 nvbios_volt_entry_parse(struct nvkm_bios *bios, int idx, u8 *ver, u8 *len,
 			struct nvbios_volt_entry *info)
 {
-	u16 volt = nvbios_volt_entry(bios, idx, ver, len);
+	u32 volt = nvbios_volt_entry(bios, idx, ver, len);
 	memset(info, 0x00, sizeof(*info));
 	switch (!!volt * *ver) {
 	case 0x12:
@@ -142,7 +148,10 @@ nvbios_volt_entry_parse(struct nvkm_bios
 		info->vid     = nvbios_rd08(bios, volt + 0x01) >> 2;
 		break;
 	case 0x40:
+		break;
 	case 0x50:
+		info->voltage = nvbios_rd32(bios, volt) & 0x001fffff;
+		info->vid     = (nvbios_rd32(bios, volt) >> 23) & 0xff;
 		break;
 	}
 	return volt;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/bios/vpstate.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Karol Herbst
+ *
+ * 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: Karol Herbst
+ */
+#include <subdev/bios.h>
+#include <subdev/bios/bit.h>
+#include <subdev/bios/vpstate.h>
+
+static u32
+nvbios_vpstate_offset(struct nvkm_bios *b)
+{
+	struct bit_entry bit_P;
+
+	if (!bit_entry(b, 'P', &bit_P)) {
+		if (bit_P.version == 2)
+			return nvbios_rd32(b, bit_P.offset + 0x38);
+	}
+
+	return 0x0000;
+}
+
+int
+nvbios_vpstate_parse(struct nvkm_bios *b, struct nvbios_vpstate_header *h)
+{
+	if (!h)
+		return -EINVAL;
+
+	h->offset = nvbios_vpstate_offset(b);
+	if (!h->offset)
+		return -ENODEV;
+
+	h->version = nvbios_rd08(b, h->offset);
+	switch (h->version) {
+	case 0x10:
+		h->hlen     = nvbios_rd08(b, h->offset + 0x1);
+		h->elen     = nvbios_rd08(b, h->offset + 0x2);
+		h->slen     = nvbios_rd08(b, h->offset + 0x3);
+		h->scount   = nvbios_rd08(b, h->offset + 0x4);
+		h->ecount   = nvbios_rd08(b, h->offset + 0x5);
+
+		h->base_id  = nvbios_rd08(b, h->offset + 0x0f);
+		h->boost_id = nvbios_rd08(b, h->offset + 0x10);
+		h->tdp_id   = nvbios_rd08(b, h->offset + 0x11);
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+int
+nvbios_vpstate_entry(struct nvkm_bios *b, struct nvbios_vpstate_header *h,
+		     u8 idx, struct nvbios_vpstate_entry *e)
+{
+	u32 offset;
+
+	if (!e || !h || idx > h->ecount)
+		return -EINVAL;
+
+	offset = h->offset + h->hlen + idx * (h->elen + (h->slen * h->scount));
+	e->pstate    = nvbios_rd08(b, offset);
+	e->clock_mhz = nvbios_rd16(b, offset + 0x5);
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 #include <subdev/bios/boost.h>
 #include <subdev/bios/cstep.h>
 #include <subdev/bios/perf.h>
+#include <subdev/bios/vpstate.h>
 #include <subdev/fb.h>
 #include <subdev/therm.h>
 #include <subdev/volt.h>
@@ -43,13 +44,13 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bo
 	struct nvkm_bios *bios = clk->subdev.device->bios;
 	struct nvbios_boostE boostE;
 	u8  ver, hdr, cnt, len;
-	u16 data;
+	u32 data;
 
 	data = nvbios_boostEm(bios, pstate, &ver, &hdr, &cnt, &len, &boostE);
 	if (data) {
 		struct nvbios_boostS boostS;
 		u8  idx = 0, sver, shdr;
-		u16 subd;
+		u32 subd;
 
 		input = max(boostE.min, input);
 		input = min(boostE.max, input);
@@ -74,6 +75,88 @@ nvkm_clk_adjust(struct nvkm_clk *clk, bo
 /******************************************************************************
  * C-States
  *****************************************************************************/
+static bool
+nvkm_cstate_valid(struct nvkm_clk *clk, struct nvkm_cstate *cstate,
+		  u32 max_volt, int temp)
+{
+	const struct nvkm_domain *domain = clk->domains;
+	struct nvkm_volt *volt = clk->subdev.device->volt;
+	int voltage;
+
+	while (domain && domain->name != nv_clk_src_max) {
+		if (domain->flags & NVKM_CLK_DOM_FLAG_VPSTATE) {
+			u32 freq = cstate->domain[domain->name];
+			switch (clk->boost_mode) {
+			case NVKM_CLK_BOOST_NONE:
+				if (clk->base_khz && freq > clk->base_khz)
+					return false;
+			case NVKM_CLK_BOOST_BIOS:
+				if (clk->boost_khz && freq > clk->boost_khz)
+					return false;
+			}
+		}
+		domain++;
+	}
+
+	if (!volt)
+		return true;
+
+	voltage = nvkm_volt_map(volt, cstate->voltage, temp);
+	if (voltage < 0)
+		return false;
+	return voltage <= min(max_volt, volt->max_uv);
+}
+
+static struct nvkm_cstate *
+nvkm_cstate_find_best(struct nvkm_clk *clk, struct nvkm_pstate *pstate,
+		      struct nvkm_cstate *start)
+{
+	struct nvkm_device *device = clk->subdev.device;
+	struct nvkm_volt *volt = device->volt;
+	struct nvkm_cstate *cstate;
+	int max_volt;
+
+	if (!pstate || !start)
+		return NULL;
+
+	if (!volt)
+		return start;
+
+	max_volt = volt->max_uv;
+	if (volt->max0_id != 0xff)
+		max_volt = min(max_volt,
+			       nvkm_volt_map(volt, volt->max0_id, clk->temp));
+	if (volt->max1_id != 0xff)
+		max_volt = min(max_volt,
+			       nvkm_volt_map(volt, volt->max1_id, clk->temp));
+	if (volt->max2_id != 0xff)
+		max_volt = min(max_volt,
+			       nvkm_volt_map(volt, volt->max2_id, clk->temp));
+
+	for (cstate = start; &cstate->head != &pstate->list;
+	     cstate = list_entry(cstate->head.prev, typeof(*cstate), head)) {
+		if (nvkm_cstate_valid(clk, cstate, max_volt, clk->temp))
+			break;
+	}
+
+	return cstate;
+}
+
+static struct nvkm_cstate *
+nvkm_cstate_get(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
+{
+	struct nvkm_cstate *cstate;
+	if (cstatei == NVKM_CLK_CSTATE_HIGHEST)
+		return list_last_entry(&pstate->list, typeof(*cstate), head);
+	else {
+		list_for_each_entry(cstate, &pstate->list, head) {
+			if (cstate->id == cstatei)
+				return cstate;
+		}
+	}
+	return NULL;
+}
+
 static int
 nvkm_cstate_prog(struct nvkm_clk *clk, struct nvkm_pstate *pstate, int cstatei)
 {
@@ -85,7 +168,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, s
 	int ret;
 
 	if (!list_empty(&pstate->list)) {
-		cstate = list_entry(pstate->list.prev, typeof(*cstate), head);
+		cstate = nvkm_cstate_get(clk, pstate, cstatei);
+		cstate = nvkm_cstate_find_best(clk, pstate, cstate);
 	} else {
 		cstate = &pstate->base;
 	}
@@ -99,7 +183,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, s
 	}
 
 	if (volt) {
-		ret = nvkm_volt_set_id(volt, cstate->voltage, +1);
+		ret = nvkm_volt_set_id(volt, cstate->voltage,
+				       pstate->base.voltage, clk->temp, +1);
 		if (ret && ret != -ENODEV) {
 			nvkm_error(subdev, "failed to raise voltage: %d\n", ret);
 			return ret;
@@ -113,7 +198,8 @@ nvkm_cstate_prog(struct nvkm_clk *clk, s
 	}
 
 	if (volt) {
-		ret = nvkm_volt_set_id(volt, cstate->voltage, -1);
+		ret = nvkm_volt_set_id(volt, cstate->voltage,
+				       pstate->base.voltage, clk->temp, -1);
 		if (ret && ret != -ENODEV)
 			nvkm_error(subdev, "failed to lower voltage: %d\n", ret);
 	}
@@ -138,22 +224,27 @@ static int
 nvkm_cstate_new(struct nvkm_clk *clk, int idx, struct nvkm_pstate *pstate)
 {
 	struct nvkm_bios *bios = clk->subdev.device->bios;
+	struct nvkm_volt *volt = clk->subdev.device->volt;
 	const struct nvkm_domain *domain = clk->domains;
 	struct nvkm_cstate *cstate = NULL;
 	struct nvbios_cstepX cstepX;
 	u8  ver, hdr;
-	u16 data;
+	u32 data;
 
 	data = nvbios_cstepXp(bios, idx, &ver, &hdr, &cstepX);
 	if (!data)
 		return -ENOENT;
 
+	if (volt && nvkm_volt_map_min(volt, cstepX.voltage) > volt->max_uv)
+		return -EINVAL;
+
 	cstate = kzalloc(sizeof(*cstate), GFP_KERNEL);
 	if (!cstate)
 		return -ENOMEM;
 
 	*cstate = pstate->base;
 	cstate->voltage = cstepX.voltage;
+	cstate->id = idx;
 
 	while (domain && domain->name != nv_clk_src_max) {
 		if (domain->flags & NVKM_CLK_DOM_FLAG_CORE) {
@@ -175,7 +266,7 @@ static int
 nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei)
 {
 	struct nvkm_subdev *subdev = &clk->subdev;
-	struct nvkm_ram *ram = subdev->device->fb->ram;
+	struct nvkm_fb *fb = subdev->device->fb;
 	struct nvkm_pci *pci = subdev->device->pci;
 	struct nvkm_pstate *pstate;
 	int ret, idx = 0;
@@ -190,7 +281,8 @@ nvkm_pstate_prog(struct nvkm_clk *clk, i
 
 	nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width);
 
-	if (ram && ram->func->calc) {
+	if (fb && fb->ram && fb->ram->func->calc) {
+		struct nvkm_ram *ram = fb->ram;
 		int khz = pstate->base.domain[nv_clk_src_mem];
 		do {
 			ret = ram->func->calc(ram, khz);
@@ -200,7 +292,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, i
 		ram->func->tidy(ram);
 	}
 
-	return nvkm_cstate_prog(clk, pstate, 0);
+	return nvkm_cstate_prog(clk, pstate, NVKM_CLK_CSTATE_HIGHEST);
 }
 
 static void
@@ -214,14 +306,14 @@ nvkm_pstate_work(struct work_struct *wor
 		return;
 	clk->pwrsrc = power_supply_is_system_supplied();
 
-	nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d D %d\n",
+	nvkm_trace(subdev, "P %d PWR %d U(AC) %d U(DC) %d A %d T %d°C D %d\n",
 		   clk->pstate, clk->pwrsrc, clk->ustate_ac, clk->ustate_dc,
-		   clk->astate, clk->tstate, clk->dstate);
+		   clk->astate, clk->temp, clk->dstate);
 
 	pstate = clk->pwrsrc ? clk->ustate_ac : clk->ustate_dc;
 	if (clk->state_nr && pstate != -1) {
 		pstate = (pstate < 0) ? clk->astate : pstate;
-		pstate = min(pstate, clk->state_nr - 1 + clk->tstate);
+		pstate = min(pstate, clk->state_nr - 1);
 		pstate = max(pstate, clk->dstate);
 	} else {
 		pstate = clk->pstate = -1;
@@ -316,7 +408,7 @@ nvkm_pstate_new(struct nvkm_clk *clk, in
 	struct nvbios_cstepE cstepE;
 	struct nvbios_perfE perfE;
 	u8  ver, hdr, cnt, len;
-	u16 data;
+	u32 data;
 
 	data = nvbios_perfEp(bios, idx, &ver, &hdr, &cnt, &len, &perfE);
 	if (!data)
@@ -448,13 +540,12 @@ nvkm_clk_astate(struct nvkm_clk *clk, in
 }
 
 int
-nvkm_clk_tstate(struct nvkm_clk *clk, int req, int rel)
+nvkm_clk_tstate(struct nvkm_clk *clk, u8 temp)
 {
-	if (!rel) clk->tstate  = req;
-	if ( rel) clk->tstate += rel;
-	clk->tstate = min(clk->tstate, 0);
-	clk->tstate = max(clk->tstate, -(clk->state_nr - 1));
-	return nvkm_pstate_calc(clk, true);
+	if (clk->temp == temp)
+		return 0;
+	clk->temp = temp;
+	return nvkm_pstate_calc(clk, false);
 }
 
 int
@@ -524,9 +615,9 @@ nvkm_clk_init(struct nvkm_subdev *subdev
 		return clk->func->init(clk);
 
 	clk->astate = clk->state_nr - 1;
-	clk->tstate = 0;
 	clk->dstate = 0;
 	clk->pstate = -1;
+	clk->temp = 90; /* reasonable default value */
 	nvkm_pstate_calc(clk, true);
 	return 0;
 }
@@ -561,10 +652,22 @@ int
 nvkm_clk_ctor(const struct nvkm_clk_func *func, struct nvkm_device *device,
 	      int index, bool allow_reclock, struct nvkm_clk *clk)
 {
+	struct nvkm_subdev *subdev = &clk->subdev;
+	struct nvkm_bios *bios = device->bios;
 	int ret, idx, arglen;
 	const char *mode;
+	struct nvbios_vpstate_header h;
+
+	nvkm_subdev_ctor(&nvkm_clk, device, index, subdev);
+
+	if (bios && !nvbios_vpstate_parse(bios, &h)) {
+		struct nvbios_vpstate_entry base, boost;
+		if (!nvbios_vpstate_entry(bios, &h, h.boost_id, &boost))
+			clk->boost_khz = boost.clock_mhz * 1000;
+		if (!nvbios_vpstate_entry(bios, &h, h.base_id, &base))
+			clk->base_khz = base.clock_mhz * 1000;
+	}
 
-	nvkm_subdev_ctor(&nvkm_clk, device, index, &clk->subdev);
 	clk->func = func;
 	INIT_LIST_HEAD(&clk->states);
 	clk->domains = func->domains;
@@ -607,6 +710,8 @@ nvkm_clk_ctor(const struct nvkm_clk_func
 	if (mode)
 		clk->ustate_dc = nvkm_clk_nstate(clk, mode, arglen);
 
+	clk->boost_mode = nvkm_longopt(device->cfgopt, "NvBoost",
+				       NVKM_CLK_BOOST_NONE);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -457,7 +457,7 @@ gf100_clk = {
 		{ nv_clk_src_hubk06 , 0x00 },
 		{ nv_clk_src_hubk01 , 0x01 },
 		{ nv_clk_src_copy   , 0x02 },
-		{ nv_clk_src_gpc    , 0x03, 0, "core", 2000 },
+		{ nv_clk_src_gpc    , 0x03, NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
 		{ nv_clk_src_rop    , 0x04 },
 		{ nv_clk_src_mem    , 0x05, 0, "memory", 1000 },
 		{ nv_clk_src_vdec   , 0x06 },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -491,7 +491,7 @@ gk104_clk = {
 	.domains = {
 		{ nv_clk_src_crystal, 0xff },
 		{ nv_clk_src_href   , 0xff },
-		{ nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE, "core", 2000 },
+		{ nv_clk_src_gpc    , 0x00, NVKM_CLK_DOM_FLAG_CORE | NVKM_CLK_DOM_FLAG_VPSTATE, "core", 2000 },
 		{ nv_clk_src_hubk07 , 0x01, NVKM_CLK_DOM_FLAG_CORE },
 		{ nv_clk_src_rop    , 0x02, NVKM_CLK_DOM_FLAG_CORE },
 		{ nv_clk_src_mem    , 0x03, 0, "memory", 500 },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,7 +180,7 @@ gt215_clk_read(struct nvkm_clk *base, en
 	return 0;
 }
 
-int
+static int
 gt215_clk_info(struct nvkm_clk *base, int idx, u32 khz,
 	       struct gt215_clk_info *info)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
 #include <subdev/bios/pmu.h>
+#include <subdev/timer.h>
 
 static void
 pmu_code(struct nv50_devinit *init, u32 pmu, u32 img, u32 len, bool sec)
@@ -123,21 +124,13 @@ gm200_devinit_post(struct nvkm_devinit *
 		return -EINVAL;
 	}
 
-	/* reset PMU and load init table parser ucode */
-	if (post) {
-		nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
-		nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
-		nvkm_rd32(device, 0x000200);
-		while (nvkm_rd32(device, 0x10a10c) & 0x00000006) {
-		}
-	}
-
 	ret = pmu_load(init, 0x04, post, &exec, &args);
 	if (ret)
 		return ret;
 
 	/* upload first chunk of init data */
 	if (post) {
+		// devinit tables
 		u32 pmu = pmu_args(init, args + 0x08, 0x08);
 		u32 img = nvbios_rd16(bios, bit_I.offset + 0x14);
 		u32 len = nvbios_rd16(bios, bit_I.offset + 0x16);
@@ -146,6 +139,7 @@ gm200_devinit_post(struct nvkm_devinit *
 
 	/* upload second chunk of init data */
 	if (post) {
+		// devinit boot scripts
 		u32 pmu = pmu_args(init, args + 0x08, 0x10);
 		u32 img = nvbios_rd16(bios, bit_I.offset + 0x18);
 		u32 len = nvbios_rd16(bios, bit_I.offset + 0x1a);
@@ -156,8 +150,11 @@ gm200_devinit_post(struct nvkm_devinit *
 	if (post) {
 		nvkm_wr32(device, 0x10a040, 0x00005000);
 		pmu_exec(init, exec);
-		while (!(nvkm_rd32(device, 0x10a040) & 0x00002000)) {
-		}
+		if (nvkm_msec(device, 2000,
+			if (nvkm_rd32(device, 0x10a040) & 0x00002000)
+				break;
+		) < 0)
+			return -ETIMEDOUT;
 	}
 
 	/* load and execute some other ucode image (bios therm?) */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,24 +50,33 @@ gf100_fb_intr(struct nvkm_fb *base)
 }
 
 int
-gf100_fb_oneinit(struct nvkm_fb *fb)
+gf100_fb_oneinit(struct nvkm_fb *base)
 {
-	struct nvkm_device *device = fb->subdev.device;
+	struct gf100_fb *fb = gf100_fb(base);
+	struct nvkm_device *device = fb->base.subdev.device;
 	int ret, size = 0x1000;
 
 	size = nvkm_longopt(device->cfgopt, "MmuDebugBufferSize", size);
 	size = min(size, 0x1000);
 
 	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
-			      false, &fb->mmu_rd);
+			      false, &fb->base.mmu_rd);
 	if (ret)
 		return ret;
 
 	ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size, 0x1000,
-			      false, &fb->mmu_wr);
+			      false, &fb->base.mmu_wr);
 	if (ret)
 		return ret;
 
+	fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+	if (fb->r100c10_page) {
+		fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
+					   PAGE_SIZE, DMA_BIDIRECTIONAL);
+		if (dma_mapping_error(device->dev, fb->r100c10))
+			return -EFAULT;
+	}
+
 	return 0;
 }
 
@@ -123,14 +132,6 @@ gf100_fb_new_(const struct nvkm_fb_func
 	nvkm_fb_ctor(func, device, index, &fb->base);
 	*pfb = &fb->base;
 
-	fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-	if (fb->r100c10_page) {
-		fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
-					   PAGE_SIZE, DMA_BIDIRECTIONAL);
-		if (dma_mapping_error(device->dev, fb->r100c10))
-			return -EFAULT;
-	}
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h	2017-02-12 16:03:20.000000000 -0500
@@ -16,4 +16,8 @@ void gf100_fb_init(struct nvkm_fb *);
 void gf100_fb_intr(struct nvkm_fb *);
 
 void gp100_fb_init(struct nvkm_fb *);
+
+void gm200_fb_init_page(struct nvkm_fb *fb);
+void gm200_fb_init(struct nvkm_fb *base);
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2014-2016, NVIDIA CORPORATION. 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"),
@@ -20,27 +20,21 @@
  * DEALINGS IN THE SOFTWARE.
  */
 #include "priv.h"
+#include "gf100.h"
 
-#include <core/memory.h>
-
-static void
-gk20a_fb_init(struct nvkm_fb *fb)
-{
-	struct nvkm_device *device = fb->subdev.device;
-	nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->mmu_wr) >> 8);
-	nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->mmu_rd) >> 8);
-}
-
+/* GK20A's FB is similar to GF100's, but without the ability to allocate VRAM */
 static const struct nvkm_fb_func
 gk20a_fb = {
+	.dtor = gf100_fb_dtor,
 	.oneinit = gf100_fb_oneinit,
-	.init = gk20a_fb_init,
+	.init = gf100_fb_init,
 	.init_page = gf100_fb_init_page,
+	.intr = gf100_fb_intr,
 	.memtype_valid = gf100_fb_memtype_valid,
 };
 
 int
 gk20a_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
 {
-	return nvkm_fb_new_(&gk20a_fb, device, index, pfb);
+	return gf100_fb_new_(&gk20a_fb, device, index, pfb);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@ gm200_fb_init_page(struct nvkm_fb *fb)
 	}
 }
 
-static void
+void
 gm200_fb_init(struct nvkm_fb *base)
 {
 	struct gf100_fb *fb = gf100_fb(base);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#include "priv.h"
+#include "gf100.h"
+
+/* GM20B's FB is similar to GM200, but without the ability to allocate VRAM */
+static const struct nvkm_fb_func
+gm20b_fb = {
+	.dtor = gf100_fb_dtor,
+	.oneinit = gf100_fb_oneinit,
+	.init = gm200_fb_init,
+	.init_page = gm200_fb_init_page,
+	.intr = gf100_fb_intr,
+	.memtype_valid = gf100_fb_memtype_valid,
+};
+
+int
+gm20b_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
+{
+	return gf100_fb_new_(&gm20b_fb, device, index, pfb);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "gf100.h"
+#include "ram.h"
+
+#include <core/memory.h>
+
+static const struct nvkm_fb_func
+gp102_fb = {
+	.dtor = gf100_fb_dtor,
+	.oneinit = gf100_fb_oneinit,
+	.init = gp100_fb_init,
+	.init_page = gm200_fb_init_page,
+	.ram_new = gp100_ram_new,
+	.memtype_valid = gf100_fb_memtype_valid,
+};
+
+int
+gp102_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
+{
+	return gf100_fb_new_(&gp102_fb, device, index, pfb);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp104.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-/*
- * Copyright 2016 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 <bskeggs@redhat.com>
- */
-#include "gf100.h"
-#include "ram.h"
-
-#include <core/memory.h>
-
-static const struct nvkm_fb_func
-gp104_fb = {
-	.dtor = gf100_fb_dtor,
-	.oneinit = gf100_fb_oneinit,
-	.init = gp100_fb_init,
-	.init_page = gm200_fb_init_page,
-	.ram_new = gp100_ram_new,
-	.memtype_valid = gf100_fb_memtype_valid,
-};
-
-int
-gp104_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
-{
-	return gf100_fb_new_(&gp104_fb, device, index, pfb);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,9 @@ nvkm-y += nvkm/subdev/fb/gk104.o
 nvkm-y += nvkm/subdev/fb/gk20a.o
 nvkm-y += nvkm/subdev/fb/gm107.o
 nvkm-y += nvkm/subdev/fb/gm200.o
+nvkm-y += nvkm/subdev/fb/gm20b.o
 nvkm-y += nvkm/subdev/fb/gp100.o
-nvkm-y += nvkm/subdev/fb/gp104.o
+nvkm-y += nvkm/subdev/fb/gp102.o
 
 nvkm-y += nvkm/subdev/fb/ram.o
 nvkm-y += nvkm/subdev/fb/ramnv04.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -210,6 +210,23 @@ nv50_fb_intr(struct nvkm_fb *base)
 	nvkm_fifo_chan_put(fifo, flags, &chan);
 }
 
+static int
+nv50_fb_oneinit(struct nvkm_fb *base)
+{
+	struct nv50_fb *fb = nv50_fb(base);
+	struct nvkm_device *device = fb->base.subdev.device;
+
+	fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+	if (fb->r100c08_page) {
+		fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
+					   PAGE_SIZE, DMA_BIDIRECTIONAL);
+		if (dma_mapping_error(device->dev, fb->r100c08))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 static void
 nv50_fb_init(struct nvkm_fb *base)
 {
@@ -245,6 +262,7 @@ nv50_fb_dtor(struct nvkm_fb *base)
 static const struct nvkm_fb_func
 nv50_fb_ = {
 	.dtor = nv50_fb_dtor,
+	.oneinit = nv50_fb_oneinit,
 	.init = nv50_fb_init,
 	.intr = nv50_fb_intr,
 	.ram_new = nv50_fb_ram_new,
@@ -263,16 +281,6 @@ nv50_fb_new_(const struct nv50_fb_func *
 	fb->func = func;
 	*pfb = &fb->base;
 
-	fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-	if (fb->r100c08_page) {
-		fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
-					   PAGE_SIZE, DMA_BIDIRECTIONAL);
-		if (dma_mapping_error(device->dev, fb->r100c08))
-			return -EFAULT;
-	} else {
-		nvkm_warn(&fb->base.subdev, "failed 100c08 page alloc\n");
-	}
-
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -420,8 +420,6 @@ gf100_ram_tidy(struct nvkm_ram *base)
 	ram_exec(&ram->fuc, false);
 }
 
-extern const u8 gf100_pte_storage_type_map[256];
-
 void
 gf100_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -259,7 +259,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *r
 
 	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
 	ram_block(fuc);
-	ram_wr32(fuc, 0x62c000, 0x0f0f0000);
+
+	if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+		ram_wr32(fuc, 0x62c000, 0x0f0f0000);
 
 	/* MR1: turn termination on early, for some reason.. */
 	if ((ram->base.mr[1] & 0x03c) != 0x030) {
@@ -658,7 +660,9 @@ gk104_ram_calc_gddr5(struct gk104_ram *r
 		gk104_ram_train(fuc, 0x80020000, 0x01000000);
 
 	ram_unblock(fuc);
-	ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
+
+	if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+		ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
 	if (next->bios.rammap_11_08_01)
 		data = 0x00000800;
@@ -706,7 +710,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *r
 
 	ram_mask(fuc, 0x10f808, 0x40000000, 0x40000000);
 	ram_block(fuc);
-	ram_wr32(fuc, 0x62c000, 0x0f0f0000);
+
+	if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+		ram_wr32(fuc, 0x62c000, 0x0f0f0000);
 
 	if (vc == 1 && ram_have(fuc, gpio2E)) {
 		u32 temp  = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[1]);
@@ -936,7 +942,9 @@ gk104_ram_calc_sddr3(struct gk104_ram *r
 	ram_nsec(fuc, 1000);
 
 	ram_unblock(fuc);
-	ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
+
+	if (nvkm_device_engine(ram->base.fb->subdev.device, NVKM_ENGINE_DISP))
+		ram_wr32(fuc, 0x62c000, 0x0f0f0f00);
 
 	if (next->bios.rammap_11_08_01)
 		data = 0x00000800;
@@ -1530,6 +1538,12 @@ gk104_ram_func = {
 int
 gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
 {
+	return gk104_ram_ctor(fb, pram, 0x022554);
+}
+
+int
+gk104_ram_ctor(struct nvkm_fb *fb, struct nvkm_ram **pram, u32 maskaddr)
+{
 	struct nvkm_subdev *subdev = &fb->subdev;
 	struct nvkm_device *device = subdev->device;
 	struct nvkm_bios *bios = device->bios;
@@ -1544,7 +1558,7 @@ gk104_ram_new(struct nvkm_fb *fb, struct
 		return -ENOMEM;
 	*pram = &ram->base;
 
-	ret = gf100_ram_ctor(&gk104_ram_func, fb, 0x022554, &ram->base);
+	ret = gf100_ram_ctor(&gk104_ram_func, fb, maskaddr, &ram->base);
 	if (ret)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,18 +23,8 @@
  */
 #include "ram.h"
 
-static const struct nvkm_ram_func
-gm107_ram_func = {
-	.init = gk104_ram_init,
-	.get = gf100_ram_get,
-	.put = gf100_ram_put,
-};
-
 int
 gm107_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
 {
-	if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL)))
-		return -ENOMEM;
-
-	return gf100_ram_ctor(&gm107_ram_func, fb, 0x021c14, *pram);
+	return gk104_ram_ctor(fb, pram, 0x021c14);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c	2017-02-12 16:03:20.000000000 -0500
@@ -92,13 +92,13 @@ gp100_ram_new(struct nvkm_fb *fb, struct
 	enum nvkm_ram_type type = nvkm_fb_bios_memtype(device->bios);
 	const u32 rsvd_head = ( 256 * 1024); /* vga memory */
 	const u32 rsvd_tail = (1024 * 1024); /* vbios etc */
-	u32 fbpa_num = nvkm_rd32(device, 0x022438), fbpa;
+	u32 fbpa_num = nvkm_rd32(device, 0x02243c), fbpa;
 	u32 fbio_opt = nvkm_rd32(device, 0x021c14);
 	u64 part, size = 0, comm = ~0ULL;
 	bool mixed = false;
 	int ret;
 
-	nvkm_debug(subdev, "022438: %08x\n", fbpa_num);
+	nvkm_debug(subdev, "02243c: %08x\n", fbpa_num);
 	nvkm_debug(subdev, "021c14: %08x\n", fbio_opt);
 	for (fbpa = 0; fbpa < fbpa_num; fbpa++) {
 		if (!(fbio_opt & (1 << fbpa))) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c	2017-02-12 16:03:20.000000000 -0500
@@ -95,7 +95,7 @@ struct gt215_ram {
 	struct gt215_ltrain ltrain;
 };
 
-void
+static void
 gt215_link_train_calc(u32 *vals, struct gt215_ltrain *train)
 {
 	int i, lo, hi;
@@ -149,7 +149,7 @@ gt215_link_train_calc(u32 *vals, struct
 /*
  * Link training for (at least) DDR3
  */
-int
+static int
 gt215_link_train(struct gt215_ram *ram)
 {
 	struct gt215_ltrain *train = &ram->ltrain;
@@ -267,7 +267,7 @@ out:
 	return ret;
 }
 
-int
+static int
 gt215_link_train_init(struct gt215_ram *ram)
 {
 	static const u32 pattern[16] = {
@@ -333,7 +333,7 @@ gt215_link_train_init(struct gt215_ram *
 	return 0;
 }
 
-void
+static void
 gt215_link_train_fini(struct gt215_ram *ram)
 {
 	if (ram->ltrain.mem)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@ int  gf100_ram_ctor(const struct nvkm_ra
 int  gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **);
 void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **);
 
+int  gk104_ram_ctor(struct nvkm_fb *, struct nvkm_ram **, u32);
 int  gk104_ram_init(struct nvkm_ram *ram);
 
 /* RAM type-specific MR calculation routines */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,7 @@
  *          Ben Skeggs
  */
 #include "priv.h"
+#include "ram.h"
 
 struct ramxlat {
 	int id;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,7 @@
  * 	    Roy Spliet <rspliet@eclipso.eu>
  */
 #include "priv.h"
+#include "ram.h"
 
 struct ramxlat {
 	int id;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/gk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@ gk104_gpio_intr_stat(struct nvkm_gpio *g
 	nvkm_wr32(device, 0x00dc80, intr1);
 }
 
-void
+static void
 gk104_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data)
 {
 	struct nvkm_device *device = gpio->subdev.device;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,7 +74,7 @@ nvkm_i2c_aux_i2c_func(struct i2c_adapter
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-const struct i2c_algorithm
+static const struct i2c_algorithm
 nvkm_i2c_aux_i2c_algo = {
 	.master_xfer = nvkm_i2c_aux_i2c_xfer,
 	.functionality = nvkm_i2c_aux_i2c_func
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c	2017-02-12 16:03:20.000000000 -0500
@@ -79,7 +79,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *ob
 	struct g94_i2c_aux *aux = g94_i2c_aux(obj);
 	struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
 	const u32 base = aux->ch * 0x50;
-	u32 ctrl, stat, timeout, retries;
+	u32 ctrl, stat, timeout, retries = 0;
 	u32 xbuf[4] = {};
 	int ret, i;
 
@@ -111,7 +111,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *ob
 	nvkm_wr32(device, 0x00e4e0 + base, addr);
 
 	/* (maybe) retry transaction a number of times on failure... */
-	for (retries = 0; !ret && retries < 32; retries++) {
+	do {
 		/* reset, and delay a while if this is a retry */
 		nvkm_wr32(device, 0x00e4e4 + base, 0x80000000 | ctrl);
 		nvkm_wr32(device, 0x00e4e4 + base, 0x00000000 | ctrl);
@@ -131,20 +131,20 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *ob
 				goto out;
 			}
 		} while (ctrl & 0x00010000);
-		ret = 1;
+		ret = 0;
 
 		/* read status, and check if transaction completed ok */
 		stat = nvkm_mask(device, 0x00e4e8 + base, 0, 0);
 		if ((stat & 0x000f0000) == 0x00080000 ||
 		    (stat & 0x000f0000) == 0x00020000)
-			ret = retry ? 0 : 1;
+			ret = 1;
 		if ((stat & 0x00000100))
 			ret = -ETIMEDOUT;
 		if ((stat & 0x00000e00))
 			ret = -EIO;
 
 		AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat);
-	}
+	} while (ret && retry && retries++ < 32);
 
 	if (type & 1) {
 		for (i = 0; i < 16; i += 4) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c	2017-02-12 16:03:20.000000000 -0500
@@ -79,7 +79,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *
 	struct gm200_i2c_aux *aux = gm200_i2c_aux(obj);
 	struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
 	const u32 base = aux->ch * 0x50;
-	u32 ctrl, stat, timeout, retries;
+	u32 ctrl, stat, timeout, retries = 0;
 	u32 xbuf[4] = {};
 	int ret, i;
 
@@ -111,7 +111,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *
 	nvkm_wr32(device, 0x00d950 + base, addr);
 
 	/* (maybe) retry transaction a number of times on failure... */
-	for (retries = 0; !ret && retries < 32; retries++) {
+	do {
 		/* reset, and delay a while if this is a retry */
 		nvkm_wr32(device, 0x00d954 + base, 0x80000000 | ctrl);
 		nvkm_wr32(device, 0x00d954 + base, 0x00000000 | ctrl);
@@ -131,20 +131,20 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *
 				goto out;
 			}
 		} while (ctrl & 0x00010000);
-		ret = 1;
+		ret = 0;
 
 		/* read status, and check if transaction completed ok */
 		stat = nvkm_mask(device, 0x00d958 + base, 0, 0);
 		if ((stat & 0x000f0000) == 0x00080000 ||
 		    (stat & 0x000f0000) == 0x00020000)
-			ret = retry ? 0 : 1;
+			ret = 1;
 		if ((stat & 0x00000100))
 			ret = -ETIMEDOUT;
 		if ((stat & 0x00000e00))
 			ret = -EIO;
 
 		AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat);
-	}
+	} while (ret && retry && retries++ < 32);
 
 	if (type & 1) {
 		for (i = 0; i < 16; i += 4) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@ gk20a_ibus_init_ibus_ring(struct nvkm_su
 	nvkm_mask(device, 0x137250, 0x3f, 0);
 
 	nvkm_mask(device, 0x000200, 0x20, 0);
-	usleep_range(20, 30);
+	udelay(20);
 	nvkm_mask(device, 0x000200, 0x20, 0x20);
 
 	nvkm_wr32(device, 0x12004c, 0x4);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -96,60 +96,12 @@ nvkm_iccsense_ina3221_read(struct nvkm_i
 }
 
 static void
-nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense,
-			    struct nvkm_iccsense_sensor *sensor)
-{
-	struct nvkm_subdev *subdev = &iccsense->subdev;
-	/* configuration:
-	 * 0x0007: 0x0007 shunt and bus continous
-	 * 0x0078: 0x0078 128 samples shunt
-	 * 0x0780: 0x0780 128 samples bus
-	 * 0x1800: 0x0000 +-40 mV shunt range
-	 * 0x2000: 0x0000 16V FSR
-         */
-	u16 value = 0x07ff;
-	nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
-	nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
-}
-
-static void
-nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense,
-			     struct nvkm_iccsense_sensor *sensor)
-{
-	struct nvkm_subdev *subdev = &iccsense->subdev;
-	/* configuration:
-	 * 0x0007: 0x0007 shunt and bus continous
-	 * 0x0031: 0x0000 140 us conversion time shunt
-	 * 0x01c0: 0x0000 140 us conversion time bus
-	 * 0x0f00: 0x0f00 1024 samples
-	 * 0x7000: 0x?000 channels
-         */
-	u16 value = 0x0e07;
-	if (sensor->rail_mask & 0x1)
-		value |= 0x1 << 14;
-	if (sensor->rail_mask & 0x2)
-		value |= 0x1 << 13;
-	if (sensor->rail_mask & 0x4)
-		value |= 0x1 << 12;
-	nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
-	nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
-}
-
-static void
 nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense,
 		            struct nvkm_iccsense_sensor *sensor)
 {
-	switch (sensor->type) {
-	case NVBIOS_EXTDEV_INA209:
-	case NVBIOS_EXTDEV_INA219:
-		nvkm_iccsense_ina209_config(iccsense, sensor);
-		break;
-	case NVBIOS_EXTDEV_INA3221:
-		nvkm_iccsense_ina3221_config(iccsense, sensor);
-		break;
-	default:
-		break;
-	}
+	struct nvkm_subdev *subdev = &iccsense->subdev;
+	nvkm_trace(subdev, "write config of extdev %i: 0x%04x\n", sensor->id, sensor->config);
+	nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, sensor->config);
 }
 
 int
@@ -196,7 +148,6 @@ nvkm_iccsense_dtor(struct nvkm_subdev *s
 static struct nvkm_iccsense_sensor*
 nvkm_iccsense_create_sensor(struct nvkm_iccsense *iccsense, u8 id)
 {
-
 	struct nvkm_subdev *subdev = &iccsense->subdev;
 	struct nvkm_bios *bios = subdev->device->bios;
 	struct nvkm_i2c *i2c = subdev->device->i2c;
@@ -245,7 +196,7 @@ nvkm_iccsense_create_sensor(struct nvkm_
 	sensor->type = extdev.type;
 	sensor->i2c = &i2c_bus->i2c;
 	sensor->addr = addr;
-	sensor->rail_mask = 0x0;
+	sensor->config = 0x0;
 	return sensor;
 }
 
@@ -273,48 +224,56 @@ nvkm_iccsense_oneinit(struct nvkm_subdev
 
 	iccsense->data_valid = true;
 	for (i = 0; i < stbl.nr_entry; ++i) {
-		struct pwr_rail_t *r = &stbl.rail[i];
-		struct nvkm_iccsense_rail *rail;
+		struct pwr_rail_t *pwr_rail = &stbl.rail[i];
 		struct nvkm_iccsense_sensor *sensor;
-		int (*read)(struct nvkm_iccsense *,
-			    struct nvkm_iccsense_rail *);
+		int r;
 
-		if (!r->mode || r->resistor_mohm == 0)
+		if (pwr_rail->mode != 1 || !pwr_rail->resistor_count)
 			continue;
 
-		sensor = nvkm_iccsense_get_sensor(iccsense, r->extdev_id);
+		sensor = nvkm_iccsense_get_sensor(iccsense, pwr_rail->extdev_id);
 		if (!sensor)
 			continue;
 
-		switch (sensor->type) {
-		case NVBIOS_EXTDEV_INA209:
-			if (r->rail != 0)
-				continue;
-			read = nvkm_iccsense_ina209_read;
-			break;
-		case NVBIOS_EXTDEV_INA219:
-			if (r->rail != 0)
+		if (!sensor->config)
+			sensor->config = pwr_rail->config;
+		else if (sensor->config != pwr_rail->config)
+			nvkm_error(subdev, "config mismatch found for extdev %i\n", pwr_rail->extdev_id);
+
+		for (r = 0; r < pwr_rail->resistor_count; ++r) {
+			struct nvkm_iccsense_rail *rail;
+			struct pwr_rail_resistor_t *res = &pwr_rail->resistors[r];
+			int (*read)(struct nvkm_iccsense *,
+				    struct nvkm_iccsense_rail *);
+
+			if (!res->mohm || !res->enabled)
 				continue;
-			read = nvkm_iccsense_ina219_read;
-			break;
-		case NVBIOS_EXTDEV_INA3221:
-			if (r->rail >= 3)
+
+			switch (sensor->type) {
+			case NVBIOS_EXTDEV_INA209:
+				read = nvkm_iccsense_ina209_read;
+				break;
+			case NVBIOS_EXTDEV_INA219:
+				read = nvkm_iccsense_ina219_read;
+				break;
+			case NVBIOS_EXTDEV_INA3221:
+				read = nvkm_iccsense_ina3221_read;
+				break;
+			default:
 				continue;
-			read = nvkm_iccsense_ina3221_read;
-			break;
-		default:
-			continue;
-		}
+			}
 
-		rail = kmalloc(sizeof(*rail), GFP_KERNEL);
-		if (!rail)
-			return -ENOMEM;
-		sensor->rail_mask |= 1 << r->rail;
-		rail->read = read;
-		rail->sensor = sensor;
-		rail->idx = r->rail;
-		rail->mohm = r->resistor_mohm;
-		list_add_tail(&rail->head, &iccsense->rails);
+			rail = kmalloc(sizeof(*rail), GFP_KERNEL);
+			if (!rail)
+				return -ENOMEM;
+
+			rail->read = read;
+			rail->sensor = sensor;
+			rail->idx = r;
+			rail->mohm = res->mohm;
+			nvkm_debug(subdev, "create rail for extdev %i: { idx: %i, mohm: %i }\n", pwr_rail->extdev_id, r, rail->mohm);
+			list_add_tail(&rail->head, &iccsense->rails);
+		}
 	}
 	return 0;
 }
@@ -329,7 +288,8 @@ nvkm_iccsense_init(struct nvkm_subdev *s
 	return 0;
 }
 
-struct nvkm_subdev_func iccsense_func = {
+static const struct nvkm_subdev_func
+iccsense_func = {
 	.oneinit = nvkm_iccsense_oneinit,
 	.init = nvkm_iccsense_init,
 	.dtor = nvkm_iccsense_dtor,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/iccsense/priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,7 @@ struct nvkm_iccsense_sensor {
 	enum nvbios_extdev_type type;
 	struct i2c_adapter *i2c;
 	u8 addr;
-	u8 rail_mask;
+	u16 config;
 };
 
 struct nvkm_iccsense_rail {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@ nvkm_instobj_dtor(struct nvkm_memory *me
 	return iobj;
 }
 
-const struct nvkm_memory_func
+static const struct nvkm_memory_func
 nvkm_instobj_func = {
 	.dtor = nvkm_instobj_dtor,
 	.target = nvkm_instobj_target,
@@ -156,7 +156,7 @@ nvkm_instobj_wr32_slow(struct nvkm_memor
 	return nvkm_wo32(iobj->parent, offset, data);
 }
 
-const struct nvkm_memory_func
+static const struct nvkm_memory_func
 nvkm_instobj_func_slow = {
 	.dtor = nvkm_instobj_dtor,
 	.target = nvkm_instobj_target,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,8 +47,10 @@ nvkm_ltc_tags_clear(struct nvkm_ltc *ltc
 
 	BUG_ON((first > limit) || (limit >= ltc->num_tags));
 
+	mutex_lock(&ltc->subdev.mutex);
 	ltc->func->cbc_clear(ltc, first, limit);
 	ltc->func->cbc_wait(ltc);
+	mutex_unlock(&ltc->subdev.mutex);
 }
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@ g84_mc_reset[] = {
 	{}
 };
 
-const struct nvkm_mc_map
+static const struct nvkm_mc_map
 g84_mc_intr[] = {
 	{ 0x04000000, NVKM_ENGINE_DISP },
 	{ 0x00020000, NVKM_ENGINE_VP },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -250,6 +250,10 @@ nvkm_mxm_new_(struct nvkm_device *device
 	}
 
 	nvkm_info(&mxm->subdev, "BIOS version %d.%d\n", ver >> 4, ver & 0x0f);
+	nvkm_debug(&mxm->subdev, "module flags: %02x\n",
+		   nvbios_rd08(bios, data + 0x01));
+	nvkm_debug(&mxm->subdev, "config flags: %02x\n",
+		   nvbios_rd08(bios, data + 0x02));
 
 	if (mxm_shadow(mxm, ver)) {
 		nvkm_warn(&mxm->subdev, "failed to locate valid SIS\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/mxms.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,8 +23,8 @@
  */
 #include "mxms.h"
 
-#define ROM16(x) le16_to_cpu(*(u16 *)&(x))
-#define ROM32(x) le32_to_cpu(*(u32 *)&(x))
+#define ROM16(x) get_unaligned_le16(&(x))
+#define ROM32(x) get_unaligned_le32(&(x))
 
 static u8 *
 mxms_data(struct nvkm_mxm *mxm)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/mxm/nv50.c	2017-02-12 16:03:20.000000000 -0500
@@ -190,8 +190,8 @@ mxm_dcb_sanitise(struct nvkm_mxm *mxm)
 	struct nvkm_bios *bios = subdev->device->bios;
 	u8  ver, hdr, cnt, len;
 	u16 dcb = dcb_table(bios, &ver, &hdr, &cnt, &len);
-	if (dcb == 0x0000 || ver != 0x40) {
-		nvkm_debug(subdev, "unsupported DCB version\n");
+	if (dcb == 0x0000 || (ver != 0x40 && ver != 0x41)) {
+		nvkm_warn(subdev, "unsupported DCB version\n");
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,225 +32,85 @@ nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool
 		pmu->func->pgob(pmu, enable);
 }
 
-int
-nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
-	      u32 process, u32 message, u32 data0, u32 data1)
-{
-	struct nvkm_subdev *subdev = &pmu->subdev;
-	struct nvkm_device *device = subdev->device;
-	u32 addr;
-
-	mutex_lock(&subdev->mutex);
-	/* wait for a free slot in the fifo */
-	addr  = nvkm_rd32(device, 0x10a4a0);
-	if (nvkm_msec(device, 2000,
-		u32 tmp = nvkm_rd32(device, 0x10a4b0);
-		if (tmp != (addr ^ 8))
-			break;
-	) < 0) {
-		mutex_unlock(&subdev->mutex);
-		return -EBUSY;
-	}
-
-	/* we currently only support a single process at a time waiting
-	 * on a synchronous reply, take the PMU mutex and tell the
-	 * receive handler what we're waiting for
-	 */
-	if (reply) {
-		pmu->recv.message = message;
-		pmu->recv.process = process;
-	}
-
-	/* acquire data segment access */
-	do {
-		nvkm_wr32(device, 0x10a580, 0x00000001);
-	} while (nvkm_rd32(device, 0x10a580) != 0x00000001);
-
-	/* write the packet */
-	nvkm_wr32(device, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) +
-				pmu->send.base));
-	nvkm_wr32(device, 0x10a1c4, process);
-	nvkm_wr32(device, 0x10a1c4, message);
-	nvkm_wr32(device, 0x10a1c4, data0);
-	nvkm_wr32(device, 0x10a1c4, data1);
-	nvkm_wr32(device, 0x10a4a0, (addr + 1) & 0x0f);
-
-	/* release data segment access */
-	nvkm_wr32(device, 0x10a580, 0x00000000);
-
-	/* wait for reply, if requested */
-	if (reply) {
-		wait_event(pmu->recv.wait, (pmu->recv.process == 0));
-		reply[0] = pmu->recv.data[0];
-		reply[1] = pmu->recv.data[1];
-	}
-
-	mutex_unlock(&subdev->mutex);
-	return 0;
-}
-
 static void
 nvkm_pmu_recv(struct work_struct *work)
 {
-	struct nvkm_pmu *pmu = container_of(work, struct nvkm_pmu, recv.work);
-	struct nvkm_subdev *subdev = &pmu->subdev;
-	struct nvkm_device *device = subdev->device;
-	u32 process, message, data0, data1;
-
-	/* nothing to do if GET == PUT */
-	u32 addr =  nvkm_rd32(device, 0x10a4cc);
-	if (addr == nvkm_rd32(device, 0x10a4c8))
-		return;
-
-	/* acquire data segment access */
-	do {
-		nvkm_wr32(device, 0x10a580, 0x00000002);
-	} while (nvkm_rd32(device, 0x10a580) != 0x00000002);
-
-	/* read the packet */
-	nvkm_wr32(device, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) +
-				pmu->recv.base));
-	process = nvkm_rd32(device, 0x10a1c4);
-	message = nvkm_rd32(device, 0x10a1c4);
-	data0   = nvkm_rd32(device, 0x10a1c4);
-	data1   = nvkm_rd32(device, 0x10a1c4);
-	nvkm_wr32(device, 0x10a4cc, (addr + 1) & 0x0f);
-
-	/* release data segment access */
-	nvkm_wr32(device, 0x10a580, 0x00000000);
-
-	/* wake process if it's waiting on a synchronous reply */
-	if (pmu->recv.process) {
-		if (process == pmu->recv.process &&
-		    message == pmu->recv.message) {
-			pmu->recv.data[0] = data0;
-			pmu->recv.data[1] = data1;
-			pmu->recv.process = 0;
-			wake_up(&pmu->recv.wait);
-			return;
-		}
-	}
+	struct nvkm_pmu *pmu = container_of(work, typeof(*pmu), recv.work);
+	return pmu->func->recv(pmu);
+}
 
-	/* right now there's no other expected responses from the engine,
-	 * so assume that any unexpected message is an error.
-	 */
-	nvkm_warn(subdev, "%c%c%c%c %08x %08x %08x %08x\n",
-		  (char)((process & 0x000000ff) >>  0),
-		  (char)((process & 0x0000ff00) >>  8),
-		  (char)((process & 0x00ff0000) >> 16),
-		  (char)((process & 0xff000000) >> 24),
-		  process, message, data0, data1);
+int
+nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
+	      u32 process, u32 message, u32 data0, u32 data1)
+{
+	if (!pmu || !pmu->func->send)
+		return -ENODEV;
+	return pmu->func->send(pmu, reply, process, message, data0, data1);
 }
 
 static void
 nvkm_pmu_intr(struct nvkm_subdev *subdev)
 {
 	struct nvkm_pmu *pmu = nvkm_pmu(subdev);
-	struct nvkm_device *device = pmu->subdev.device;
-	u32 disp = nvkm_rd32(device, 0x10a01c);
-	u32 intr = nvkm_rd32(device, 0x10a008) & disp & ~(disp >> 16);
-
-	if (intr & 0x00000020) {
-		u32 stat = nvkm_rd32(device, 0x10a16c);
-		if (stat & 0x80000000) {
-			nvkm_error(subdev, "UAS fault at %06x addr %08x\n",
-				   stat & 0x00ffffff,
-				   nvkm_rd32(device, 0x10a168));
-			nvkm_wr32(device, 0x10a16c, 0x00000000);
-			intr &= ~0x00000020;
-		}
-	}
-
-	if (intr & 0x00000040) {
-		schedule_work(&pmu->recv.work);
-		nvkm_wr32(device, 0x10a004, 0x00000040);
-		intr &= ~0x00000040;
-	}
-
-	if (intr & 0x00000080) {
-		nvkm_info(subdev, "wr32 %06x %08x\n",
-			  nvkm_rd32(device, 0x10a7a0),
-			  nvkm_rd32(device, 0x10a7a4));
-		nvkm_wr32(device, 0x10a004, 0x00000080);
-		intr &= ~0x00000080;
-	}
-
-	if (intr) {
-		nvkm_error(subdev, "intr %08x\n", intr);
-		nvkm_wr32(device, 0x10a004, intr);
-	}
+	if (!pmu->func->intr)
+		return;
+	pmu->func->intr(pmu);
 }
 
 static int
 nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
 {
 	struct nvkm_pmu *pmu = nvkm_pmu(subdev);
-	struct nvkm_device *device = pmu->subdev.device;
 
-	nvkm_wr32(device, 0x10a014, 0x00000060);
+	if (pmu->func->fini)
+		pmu->func->fini(pmu);
+
 	flush_work(&pmu->recv.work);
 	return 0;
 }
 
 static int
-nvkm_pmu_init(struct nvkm_subdev *subdev)
+nvkm_pmu_reset(struct nvkm_pmu *pmu)
 {
-	struct nvkm_pmu *pmu = nvkm_pmu(subdev);
 	struct nvkm_device *device = pmu->subdev.device;
-	int i;
 
-	/* prevent previous ucode from running, wait for idle, reset */
-	nvkm_wr32(device, 0x10a014, 0x0000ffff); /* INTR_EN_CLR = ALL */
+	if (!(nvkm_rd32(device, 0x000200) & 0x00002000))
+		return 0;
+
+	/* Inhibit interrupts, and wait for idle. */
+	nvkm_wr32(device, 0x10a014, 0x0000ffff);
 	nvkm_msec(device, 2000,
 		if (!nvkm_rd32(device, 0x10a04c))
 			break;
 	);
-	nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
-	nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
-	nvkm_rd32(device, 0x000200);
+
+	/* Reset. */
+	pmu->func->reset(pmu);
+
+	/* Wait for IMEM/DMEM scrubbing to be complete. */
 	nvkm_msec(device, 2000,
 		if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
 			break;
 	);
 
-	/* upload data segment */
-	nvkm_wr32(device, 0x10a1c0, 0x01000000);
-	for (i = 0; i < pmu->func->data.size / 4; i++)
-		nvkm_wr32(device, 0x10a1c4, pmu->func->data.data[i]);
-
-	/* upload code segment */
-	nvkm_wr32(device, 0x10a180, 0x01000000);
-	for (i = 0; i < pmu->func->code.size / 4; i++) {
-		if ((i & 0x3f) == 0)
-			nvkm_wr32(device, 0x10a188, i >> 6);
-		nvkm_wr32(device, 0x10a184, pmu->func->code.data[i]);
-	}
-
-	/* start it running */
-	nvkm_wr32(device, 0x10a10c, 0x00000000);
-	nvkm_wr32(device, 0x10a104, 0x00000000);
-	nvkm_wr32(device, 0x10a100, 0x00000002);
-
-	/* wait for valid host->pmu ring configuration */
-	if (nvkm_msec(device, 2000,
-		if (nvkm_rd32(device, 0x10a4d0))
-			break;
-	) < 0)
-		return -EBUSY;
-	pmu->send.base = nvkm_rd32(device, 0x10a4d0) & 0x0000ffff;
-	pmu->send.size = nvkm_rd32(device, 0x10a4d0) >> 16;
+	return 0;
+}
 
-	/* wait for valid pmu->host ring configuration */
-	if (nvkm_msec(device, 2000,
-		if (nvkm_rd32(device, 0x10a4dc))
-			break;
-	) < 0)
-		return -EBUSY;
-	pmu->recv.base = nvkm_rd32(device, 0x10a4dc) & 0x0000ffff;
-	pmu->recv.size = nvkm_rd32(device, 0x10a4dc) >> 16;
+static int
+nvkm_pmu_preinit(struct nvkm_subdev *subdev)
+{
+	struct nvkm_pmu *pmu = nvkm_pmu(subdev);
+	return nvkm_pmu_reset(pmu);
+}
 
-	nvkm_wr32(device, 0x10a010, 0x000000e0);
-	return 0;
+static int
+nvkm_pmu_init(struct nvkm_subdev *subdev)
+{
+	struct nvkm_pmu *pmu = nvkm_pmu(subdev);
+	int ret = nvkm_pmu_reset(pmu);
+	if (ret == 0 && pmu->func->init)
+		ret = pmu->func->init(pmu);
+	return ret;
 }
 
 static void *
@@ -262,6 +122,7 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev
 static const struct nvkm_subdev_func
 nvkm_pmu = {
 	.dtor = nvkm_pmu_dtor,
+	.preinit = nvkm_pmu_preinit,
 	.init = nvkm_pmu_init,
 	.fini = nvkm_pmu_fini,
 	.intr = nvkm_pmu_intr,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gf100_pmu_data[] = {
+static uint32_t gf100_pmu_data[] = {
 /* 0x0000: proc_kern */
 	0x52544e49,
 	0x00000000,
@@ -916,7 +916,7 @@ uint32_t gf100_pmu_data[] = {
 	0x00000000,
 };
 
-uint32_t gf100_pmu_code[] = {
+static uint32_t gf100_pmu_code[] = {
 	0x03920ef5,
 /* 0x0004: rd32 */
 	0x07a007f1,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf119.fuc4.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gf119_pmu_data[] = {
+static uint32_t gf119_pmu_data[] = {
 /* 0x0000: proc_kern */
 	0x52544e49,
 	0x00000000,
@@ -915,7 +915,7 @@ uint32_t gf119_pmu_data[] = {
 	0x00000000,
 };
 
-uint32_t gf119_pmu_code[] = {
+static uint32_t gf119_pmu_code[] = {
 	0x03410ef5,
 /* 0x0004: rd32 */
 	0x07a007f1,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gk208_pmu_data[] = {
+static uint32_t gk208_pmu_data[] = {
 /* 0x0000: proc_kern */
 	0x52544e49,
 	0x00000000,
@@ -915,7 +915,7 @@ uint32_t gk208_pmu_data[] = {
 	0x00000000,
 };
 
-uint32_t gk208_pmu_code[] = {
+static uint32_t gk208_pmu_code[] = {
 	0x02f90ef5,
 /* 0x0004: rd32 */
 	0xf607a040,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,4 +1,4 @@
-uint32_t gt215_pmu_data[] = {
+static uint32_t gt215_pmu_data[] = {
 /* 0x0000: proc_kern */
 	0x52544e49,
 	0x00000000,
@@ -916,7 +916,7 @@ uint32_t gt215_pmu_data[] = {
 	0x00000000,
 };
 
-uint32_t gt215_pmu_code[] = {
+static uint32_t gt215_pmu_code[] = {
 	0x03920ef5,
 /* 0x0004: rd32 */
 	0x07a007f1,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,12 @@ gf100_pmu = {
 	.code.size = sizeof(gf100_pmu_code),
 	.data.data = gf100_pmu_data,
 	.data.size = sizeof(gf100_pmu_data),
+	.reset = gt215_pmu_reset,
+	.init = gt215_pmu_init,
+	.fini = gt215_pmu_fini,
+	.intr = gt215_pmu_intr,
+	.send = gt215_pmu_send,
+	.recv = gt215_pmu_recv,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gf119.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,12 @@ gf119_pmu = {
 	.code.size = sizeof(gf119_pmu_code),
 	.data.data = gf119_pmu_data,
 	.data.size = sizeof(gf119_pmu_data),
+	.reset = gt215_pmu_reset,
+	.init = gt215_pmu_init,
+	.fini = gt215_pmu_fini,
+	.intr = gt215_pmu_intr,
+	.send = gt215_pmu_send,
+	.recv = gt215_pmu_recv,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -109,6 +109,12 @@ gk104_pmu = {
 	.code.size = sizeof(gk104_pmu_code),
 	.data.data = gk104_pmu_data,
 	.data.size = sizeof(gk104_pmu_data),
+	.reset = gt215_pmu_reset,
+	.init = gt215_pmu_init,
+	.fini = gt215_pmu_fini,
+	.intr = gt215_pmu_intr,
+	.send = gt215_pmu_send,
+	.recv = gt215_pmu_recv,
 	.pgob = gk104_pmu_pgob,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk110.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,6 +88,12 @@ gk110_pmu = {
 	.code.size = sizeof(gk110_pmu_code),
 	.data.data = gk110_pmu_data,
 	.data.size = sizeof(gk110_pmu_data),
+	.reset = gt215_pmu_reset,
+	.init = gt215_pmu_init,
+	.fini = gt215_pmu_fini,
+	.intr = gt215_pmu_intr,
+	.send = gt215_pmu_send,
+	.recv = gt215_pmu_recv,
 	.pgob = gk110_pmu_pgob,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk208.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,12 @@ gk208_pmu = {
 	.code.size = sizeof(gk208_pmu_code),
 	.data.data = gk208_pmu_data,
 	.data.size = sizeof(gk208_pmu_data),
+	.reset = gt215_pmu_reset,
+	.init = gt215_pmu_init,
+	.fini = gt215_pmu_fini,
+	.intr = gt215_pmu_intr,
+	.send = gt215_pmu_send,
+	.recv = gt215_pmu_recv,
 	.pgob = gk110_pmu_pgob,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm107.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,12 @@ gm107_pmu = {
 	.code.size = sizeof(gm107_pmu_code),
 	.data.data = gm107_pmu_data,
 	.data.size = sizeof(gm107_pmu_data),
+	.reset = gt215_pmu_reset,
+	.init = gt215_pmu_init,
+	.fini = gt215_pmu_fini,
+	.intr = gt215_pmu_intr,
+	.send = gt215_pmu_send,
+	.recv = gt215_pmu_recv,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp100.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+static const struct nvkm_pmu_func
+gp100_pmu = {
+	.reset = gt215_pmu_reset,
+};
+
+int
+gp100_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu)
+{
+	return nvkm_pmu_new_(&gp100_pmu, device, index, ppmu);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 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 <bskeggs@redhat.com>
+ */
+#include "priv.h"
+
+static void
+gp102_pmu_reset(struct nvkm_pmu *pmu)
+{
+	struct nvkm_device *device = pmu->subdev.device;
+	nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000001);
+	nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000000);
+}
+
+static const struct nvkm_pmu_func
+gp102_pmu = {
+	.reset = gp102_pmu_reset,
+};
+
+int
+gp102_pmu_new(struct nvkm_device *device, int index, struct nvkm_pmu **ppmu)
+{
+	return nvkm_pmu_new_(&gp102_pmu, device, index, ppmu);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,21 +24,229 @@
 #include "priv.h"
 #include "fuc/gt215.fuc3.h"
 
-static void
+#include <subdev/timer.h>
+
+int
+gt215_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
+	       u32 process, u32 message, u32 data0, u32 data1)
+{
+	struct nvkm_subdev *subdev = &pmu->subdev;
+	struct nvkm_device *device = subdev->device;
+	u32 addr;
+
+	mutex_lock(&subdev->mutex);
+	/* wait for a free slot in the fifo */
+	addr  = nvkm_rd32(device, 0x10a4a0);
+	if (nvkm_msec(device, 2000,
+		u32 tmp = nvkm_rd32(device, 0x10a4b0);
+		if (tmp != (addr ^ 8))
+			break;
+	) < 0) {
+		mutex_unlock(&subdev->mutex);
+		return -EBUSY;
+	}
+
+	/* we currently only support a single process at a time waiting
+	 * on a synchronous reply, take the PMU mutex and tell the
+	 * receive handler what we're waiting for
+	 */
+	if (reply) {
+		pmu->recv.message = message;
+		pmu->recv.process = process;
+	}
+
+	/* acquire data segment access */
+	do {
+		nvkm_wr32(device, 0x10a580, 0x00000001);
+	} while (nvkm_rd32(device, 0x10a580) != 0x00000001);
+
+	/* write the packet */
+	nvkm_wr32(device, 0x10a1c0, 0x01000000 | (((addr & 0x07) << 4) +
+				pmu->send.base));
+	nvkm_wr32(device, 0x10a1c4, process);
+	nvkm_wr32(device, 0x10a1c4, message);
+	nvkm_wr32(device, 0x10a1c4, data0);
+	nvkm_wr32(device, 0x10a1c4, data1);
+	nvkm_wr32(device, 0x10a4a0, (addr + 1) & 0x0f);
+
+	/* release data segment access */
+	nvkm_wr32(device, 0x10a580, 0x00000000);
+
+	/* wait for reply, if requested */
+	if (reply) {
+		wait_event(pmu->recv.wait, (pmu->recv.process == 0));
+		reply[0] = pmu->recv.data[0];
+		reply[1] = pmu->recv.data[1];
+	}
+
+	mutex_unlock(&subdev->mutex);
+	return 0;
+}
+
+void
+gt215_pmu_recv(struct nvkm_pmu *pmu)
+{
+	struct nvkm_subdev *subdev = &pmu->subdev;
+	struct nvkm_device *device = subdev->device;
+	u32 process, message, data0, data1;
+
+	/* nothing to do if GET == PUT */
+	u32 addr =  nvkm_rd32(device, 0x10a4cc);
+	if (addr == nvkm_rd32(device, 0x10a4c8))
+		return;
+
+	/* acquire data segment access */
+	do {
+		nvkm_wr32(device, 0x10a580, 0x00000002);
+	} while (nvkm_rd32(device, 0x10a580) != 0x00000002);
+
+	/* read the packet */
+	nvkm_wr32(device, 0x10a1c0, 0x02000000 | (((addr & 0x07) << 4) +
+				pmu->recv.base));
+	process = nvkm_rd32(device, 0x10a1c4);
+	message = nvkm_rd32(device, 0x10a1c4);
+	data0   = nvkm_rd32(device, 0x10a1c4);
+	data1   = nvkm_rd32(device, 0x10a1c4);
+	nvkm_wr32(device, 0x10a4cc, (addr + 1) & 0x0f);
+
+	/* release data segment access */
+	nvkm_wr32(device, 0x10a580, 0x00000000);
+
+	/* wake process if it's waiting on a synchronous reply */
+	if (pmu->recv.process) {
+		if (process == pmu->recv.process &&
+		    message == pmu->recv.message) {
+			pmu->recv.data[0] = data0;
+			pmu->recv.data[1] = data1;
+			pmu->recv.process = 0;
+			wake_up(&pmu->recv.wait);
+			return;
+		}
+	}
+
+	/* right now there's no other expected responses from the engine,
+	 * so assume that any unexpected message is an error.
+	 */
+	nvkm_warn(subdev, "%c%c%c%c %08x %08x %08x %08x\n",
+		  (char)((process & 0x000000ff) >>  0),
+		  (char)((process & 0x0000ff00) >>  8),
+		  (char)((process & 0x00ff0000) >> 16),
+		  (char)((process & 0xff000000) >> 24),
+		  process, message, data0, data1);
+}
+
+void
+gt215_pmu_intr(struct nvkm_pmu *pmu)
+{
+	struct nvkm_subdev *subdev = &pmu->subdev;
+	struct nvkm_device *device = subdev->device;
+	u32 disp = nvkm_rd32(device, 0x10a01c);
+	u32 intr = nvkm_rd32(device, 0x10a008) & disp & ~(disp >> 16);
+
+	if (intr & 0x00000020) {
+		u32 stat = nvkm_rd32(device, 0x10a16c);
+		if (stat & 0x80000000) {
+			nvkm_error(subdev, "UAS fault at %06x addr %08x\n",
+				   stat & 0x00ffffff,
+				   nvkm_rd32(device, 0x10a168));
+			nvkm_wr32(device, 0x10a16c, 0x00000000);
+			intr &= ~0x00000020;
+		}
+	}
+
+	if (intr & 0x00000040) {
+		schedule_work(&pmu->recv.work);
+		nvkm_wr32(device, 0x10a004, 0x00000040);
+		intr &= ~0x00000040;
+	}
+
+	if (intr & 0x00000080) {
+		nvkm_info(subdev, "wr32 %06x %08x\n",
+			  nvkm_rd32(device, 0x10a7a0),
+			  nvkm_rd32(device, 0x10a7a4));
+		nvkm_wr32(device, 0x10a004, 0x00000080);
+		intr &= ~0x00000080;
+	}
+
+	if (intr) {
+		nvkm_error(subdev, "intr %08x\n", intr);
+		nvkm_wr32(device, 0x10a004, intr);
+	}
+}
+
+void
+gt215_pmu_fini(struct nvkm_pmu *pmu)
+{
+	nvkm_wr32(pmu->subdev.device, 0x10a014, 0x00000060);
+}
+
+void
 gt215_pmu_reset(struct nvkm_pmu *pmu)
 {
 	struct nvkm_device *device = pmu->subdev.device;
-	nvkm_mask(device, 0x022210, 0x00000001, 0x00000000);
-	nvkm_mask(device, 0x022210, 0x00000001, 0x00000001);
+	nvkm_mask(device, 0x000200, 0x00002000, 0x00000000);
+	nvkm_mask(device, 0x000200, 0x00002000, 0x00002000);
+	nvkm_rd32(device, 0x000200);
+}
+
+int
+gt215_pmu_init(struct nvkm_pmu *pmu)
+{
+	struct nvkm_device *device = pmu->subdev.device;
+	int i;
+
+	/* upload data segment */
+	nvkm_wr32(device, 0x10a1c0, 0x01000000);
+	for (i = 0; i < pmu->func->data.size / 4; i++)
+		nvkm_wr32(device, 0x10a1c4, pmu->func->data.data[i]);
+
+	/* upload code segment */
+	nvkm_wr32(device, 0x10a180, 0x01000000);
+	for (i = 0; i < pmu->func->code.size / 4; i++) {
+		if ((i & 0x3f) == 0)
+			nvkm_wr32(device, 0x10a188, i >> 6);
+		nvkm_wr32(device, 0x10a184, pmu->func->code.data[i]);
+	}
+
+	/* start it running */
+	nvkm_wr32(device, 0x10a10c, 0x00000000);
+	nvkm_wr32(device, 0x10a104, 0x00000000);
+	nvkm_wr32(device, 0x10a100, 0x00000002);
+
+	/* wait for valid host->pmu ring configuration */
+	if (nvkm_msec(device, 2000,
+		if (nvkm_rd32(device, 0x10a4d0))
+			break;
+	) < 0)
+		return -EBUSY;
+	pmu->send.base = nvkm_rd32(device, 0x10a4d0) & 0x0000ffff;
+	pmu->send.size = nvkm_rd32(device, 0x10a4d0) >> 16;
+
+	/* wait for valid pmu->host ring configuration */
+	if (nvkm_msec(device, 2000,
+		if (nvkm_rd32(device, 0x10a4dc))
+			break;
+	) < 0)
+		return -EBUSY;
+	pmu->recv.base = nvkm_rd32(device, 0x10a4dc) & 0x0000ffff;
+	pmu->recv.size = nvkm_rd32(device, 0x10a4dc) >> 16;
+
+	nvkm_wr32(device, 0x10a010, 0x000000e0);
+	return 0;
 }
 
 static const struct nvkm_pmu_func
 gt215_pmu = {
-	.reset = gt215_pmu_reset,
 	.code.data = gt215_pmu_code,
 	.code.size = sizeof(gt215_pmu_code),
 	.data.data = gt215_pmu_data,
 	.data.size = sizeof(gt215_pmu_data),
+	.reset = gt215_pmu_reset,
+	.init = gt215_pmu_init,
+	.fini = gt215_pmu_fini,
+	.intr = gt215_pmu_intr,
+	.send = gt215_pmu_send,
+	.recv = gt215_pmu_recv,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -8,3 +8,5 @@ nvkm-y += nvkm/subdev/pmu/gk110.o
 nvkm-y += nvkm/subdev/pmu/gk208.o
 nvkm-y += nvkm/subdev/pmu/gk20a.o
 nvkm-y += nvkm/subdev/pmu/gm107.o
+nvkm-y += nvkm/subdev/pmu/gp100.o
+nvkm-y += nvkm/subdev/pmu/gp102.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -8,8 +8,6 @@ int nvkm_pmu_new_(const struct nvkm_pmu_
 		  int index, struct nvkm_pmu **);
 
 struct nvkm_pmu_func {
-	void (*reset)(struct nvkm_pmu *);
-
 	struct {
 		u32 *data;
 		u32  size;
@@ -20,8 +18,22 @@ struct nvkm_pmu_func {
 		u32  size;
 	} data;
 
+	void (*reset)(struct nvkm_pmu *);
+	int (*init)(struct nvkm_pmu *);
+	void (*fini)(struct nvkm_pmu *);
+	void (*intr)(struct nvkm_pmu *);
+	int (*send)(struct nvkm_pmu *, u32 reply[2], u32 process,
+		    u32 message, u32 data0, u32 data1);
+	void (*recv)(struct nvkm_pmu *);
 	void (*pgob)(struct nvkm_pmu *, bool);
 };
 
+void gt215_pmu_reset(struct nvkm_pmu *);
+int gt215_pmu_init(struct nvkm_pmu *);
+void gt215_pmu_fini(struct nvkm_pmu *);
+void gt215_pmu_intr(struct nvkm_pmu *);
+void gt215_pmu_recv(struct nvkm_pmu *);
+int gt215_pmu_send(struct nvkm_pmu *, u32[2], u32, u32, u32, u32);
+
 void gk110_pmu_pgob(struct nvkm_pmu *, bool);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c	2016-12-11 17:42:16.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c	2017-02-12 17:25:38.000000000 -0500
@@ -1364,7 +1364,7 @@ gm200_secboot_init(struct nvkm_secboot *
 	return 0;
 }
 
-int
+static int
 gm200_secboot_fini(struct nvkm_secboot *sb, bool suspend)
 {
 	struct gm200_secboot *gsb = gm200_secboot(sb);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/vmap.h>
 #include <subdev/bios/volt.h>
+#include <subdev/therm.h>
 
 int
 nvkm_volt_get(struct nvkm_volt *volt)
@@ -50,33 +51,45 @@ static int
 nvkm_volt_set(struct nvkm_volt *volt, u32 uv)
 {
 	struct nvkm_subdev *subdev = &volt->subdev;
-	int i, ret = -EINVAL;
+	int i, ret = -EINVAL, best_err = volt->max_uv, best = -1;
 
 	if (volt->func->volt_set)
 		return volt->func->volt_set(volt, uv);
 
 	for (i = 0; i < volt->vid_nr; i++) {
-		if (volt->vid[i].uv == uv) {
-			ret = volt->func->vid_set(volt, volt->vid[i].vid);
-			nvkm_debug(subdev, "set %duv: %d\n", uv, ret);
+		int err = volt->vid[i].uv - uv;
+		if (err < 0 || err > best_err)
+			continue;
+
+		best_err = err;
+		best = i;
+		if (best_err == 0)
 			break;
-		}
 	}
+
+	if (best == -1) {
+		nvkm_error(subdev, "couldn't set %iuv\n", uv);
+		return ret;
+	}
+
+	ret = volt->func->vid_set(volt, volt->vid[best].vid);
+	nvkm_debug(subdev, "set req %duv to %duv: %d\n", uv,
+		   volt->vid[best].uv, ret);
 	return ret;
 }
 
-static int
-nvkm_volt_map(struct nvkm_volt *volt, u8 id)
+int
+nvkm_volt_map_min(struct nvkm_volt *volt, u8 id)
 {
 	struct nvkm_bios *bios = volt->subdev.device->bios;
 	struct nvbios_vmap_entry info;
 	u8  ver, len;
-	u16 vmap;
+	u32 vmap;
 
 	vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info);
 	if (vmap) {
 		if (info.link != 0xff) {
-			int ret = nvkm_volt_map(volt, info.link);
+			int ret = nvkm_volt_map_min(volt, info.link);
 			if (ret < 0)
 				return ret;
 			info.min += ret;
@@ -88,19 +101,79 @@ nvkm_volt_map(struct nvkm_volt *volt, u8
 }
 
 int
-nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, int condition)
+nvkm_volt_map(struct nvkm_volt *volt, u8 id, u8 temp)
+{
+	struct nvkm_bios *bios = volt->subdev.device->bios;
+	struct nvbios_vmap_entry info;
+	u8  ver, len;
+	u32 vmap;
+
+	vmap = nvbios_vmap_entry_parse(bios, id, &ver, &len, &info);
+	if (vmap) {
+		s64 result;
+
+		if (volt->speedo < 0)
+			return volt->speedo;
+
+		if (ver == 0x10 || (ver == 0x20 && info.mode == 0)) {
+			result  = div64_s64((s64)info.arg[0], 10);
+			result += div64_s64((s64)info.arg[1] * volt->speedo, 10);
+			result += div64_s64((s64)info.arg[2] * volt->speedo * volt->speedo, 100000);
+		} else if (ver == 0x20) {
+			switch (info.mode) {
+			/* 0x0 handled above! */
+			case 0x1:
+				result =  ((s64)info.arg[0] * 15625) >> 18;
+				result += ((s64)info.arg[1] * volt->speedo * 15625) >> 18;
+				result += ((s64)info.arg[2] * temp * 15625) >> 10;
+				result += ((s64)info.arg[3] * volt->speedo * temp * 15625) >> 18;
+				result += ((s64)info.arg[4] * volt->speedo * volt->speedo * 15625) >> 30;
+				result += ((s64)info.arg[5] * temp * temp * 15625) >> 18;
+				break;
+			case 0x3:
+				result = (info.min + info.max) / 2;
+				break;
+			case 0x2:
+			default:
+				result = info.min;
+				break;
+			}
+		} else {
+			return -ENODEV;
+		}
+
+		result = min(max(result, (s64)info.min), (s64)info.max);
+
+		if (info.link != 0xff) {
+			int ret = nvkm_volt_map(volt, info.link, temp);
+			if (ret < 0)
+				return ret;
+			result += ret;
+		}
+		return result;
+	}
+
+	return id ? id * 10000 : -ENODEV;
+}
+
+int
+nvkm_volt_set_id(struct nvkm_volt *volt, u8 id, u8 min_id, u8 temp,
+		 int condition)
 {
 	int ret;
 
 	if (volt->func->set_id)
 		return volt->func->set_id(volt, id, condition);
 
-	ret = nvkm_volt_map(volt, id);
+	ret = nvkm_volt_map(volt, id, temp);
 	if (ret >= 0) {
 		int prev = nvkm_volt_get(volt);
 		if (!condition || prev < 0 ||
 		    (condition < 0 && ret < prev) ||
 		    (condition > 0 && ret > prev)) {
+			int min = nvkm_volt_map(volt, min_id, temp);
+			if (min >= 0)
+				ret = max(min, ret);
 			ret = nvkm_volt_set(volt, ret);
 		} else {
 			ret = 0;
@@ -112,14 +185,16 @@ nvkm_volt_set_id(struct nvkm_volt *volt,
 static void
 nvkm_volt_parse_bios(struct nvkm_bios *bios, struct nvkm_volt *volt)
 {
+	struct nvkm_subdev *subdev = &bios->subdev;
 	struct nvbios_volt_entry ivid;
 	struct nvbios_volt info;
 	u8  ver, hdr, cnt, len;
-	u16 data;
+	u32 data;
 	int i;
 
 	data = nvbios_volt_parse(bios, &ver, &hdr, &cnt, &len, &info);
-	if (data && info.vidmask && info.base && info.step) {
+	if (data && info.vidmask && info.base && info.step && info.ranged) {
+		nvkm_debug(subdev, "found ranged based VIDs\n");
 		volt->min_uv = info.min;
 		volt->max_uv = info.max;
 		for (i = 0; i < info.vidmask + 1; i++) {
@@ -132,7 +207,8 @@ nvkm_volt_parse_bios(struct nvkm_bios *b
 			info.base += info.step;
 		}
 		volt->vid_mask = info.vidmask;
-	} else if (data && info.vidmask) {
+	} else if (data && info.vidmask && !info.ranged) {
+		nvkm_debug(subdev, "found entry based VIDs\n");
 		volt->min_uv = 0xffffffff;
 		volt->max_uv = 0;
 		for (i = 0; i < cnt; i++) {
@@ -154,6 +230,14 @@ nvkm_volt_parse_bios(struct nvkm_bios *b
 }
 
 static int
+nvkm_volt_speedo_read(struct nvkm_volt *volt)
+{
+	if (volt->func->speedo_read)
+		return volt->func->speedo_read(volt);
+	return -EINVAL;
+}
+
+static int
 nvkm_volt_init(struct nvkm_subdev *subdev)
 {
 	struct nvkm_volt *volt = nvkm_volt(subdev);
@@ -167,6 +251,21 @@ nvkm_volt_init(struct nvkm_subdev *subde
 	return 0;
 }
 
+static int
+nvkm_volt_oneinit(struct nvkm_subdev *subdev)
+{
+	struct nvkm_volt *volt = nvkm_volt(subdev);
+
+	volt->speedo = nvkm_volt_speedo_read(volt);
+	if (volt->speedo > 0)
+		nvkm_debug(&volt->subdev, "speedo %x\n", volt->speedo);
+
+	if (volt->func->oneinit)
+		return volt->func->oneinit(volt);
+
+	return 0;
+}
+
 static void *
 nvkm_volt_dtor(struct nvkm_subdev *subdev)
 {
@@ -177,6 +276,7 @@ static const struct nvkm_subdev_func
 nvkm_volt = {
 	.dtor = nvkm_volt_dtor,
 	.init = nvkm_volt_init,
+	.oneinit = nvkm_volt_oneinit,
 };
 
 void
@@ -191,9 +291,22 @@ nvkm_volt_ctor(const struct nvkm_volt_fu
 
 	/* Assuming the non-bios device should build the voltage table later */
 	if (bios) {
+		u8 ver, hdr, cnt, len;
+		struct nvbios_vmap vmap;
+
 		nvkm_volt_parse_bios(bios, volt);
 		nvkm_debug(&volt->subdev, "min: %iuv max: %iuv\n",
 			   volt->min_uv, volt->max_uv);
+
+		if (nvbios_vmap_parse(bios, &ver, &hdr, &cnt, &len, &vmap)) {
+			volt->max0_id = vmap.max0;
+			volt->max1_id = vmap.max1;
+			volt->max2_id = vmap.max2;
+		} else {
+			volt->max0_id = 0xff;
+			volt->max1_id = 0xff;
+			volt->max2_id = 0xff;
+		}
 	}
 
 	if (volt->vid_nr) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gf100.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2016 Karol Herbst
+ *
+ * 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: Karol Herbst
+ */
+#include "priv.h"
+
+#include <subdev/fuse.h>
+
+static int
+gf100_volt_speedo_read(struct nvkm_volt *volt)
+{
+	struct nvkm_device *device = volt->subdev.device;
+	struct nvkm_fuse *fuse = device->fuse;
+
+	if (!fuse)
+		return -EINVAL;
+
+	return nvkm_fuse_read(fuse, 0x1cc);
+}
+
+int
+gf100_volt_oneinit(struct nvkm_volt *volt)
+{
+	struct nvkm_subdev *subdev = &volt->subdev;
+	if (volt->speedo <= 0)
+		nvkm_error(subdev, "couldn't find speedo value, volting not "
+			   "possible\n");
+	return 0;
+}
+
+static const struct nvkm_volt_func
+gf100_volt = {
+	.oneinit = gf100_volt_oneinit,
+	.vid_get = nvkm_voltgpio_get,
+	.vid_set = nvkm_voltgpio_set,
+	.speedo_read = gf100_volt_speedo_read,
+};
+
+int
+gf100_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt)
+{
+	struct nvkm_volt *volt;
+	int ret;
+
+	ret = nvkm_volt_new_(&gf100_volt, device, index, &volt);
+	*pvolt = volt;
+	if (ret)
+		return ret;
+
+	return nvkm_voltgpio_init(volt);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 #include <subdev/gpio.h>
 #include <subdev/bios.h>
 #include <subdev/bios/volt.h>
+#include <subdev/fuse.h>
 
 #define gk104_volt(p) container_of((p), struct gk104_volt, base)
 struct gk104_volt {
@@ -34,7 +35,7 @@ struct gk104_volt {
 	struct nvbios_volt bios;
 };
 
-int
+static int
 gk104_volt_get(struct nvkm_volt *base)
 {
 	struct nvbios_volt *bios = &gk104_volt(base)->bios;
@@ -47,7 +48,7 @@ gk104_volt_get(struct nvkm_volt *base)
 	return bios->base + bios->pwm_range * duty / div;
 }
 
-int
+static int
 gk104_volt_set(struct nvkm_volt *base, u32 uv)
 {
 	struct nvbios_volt *bios = &gk104_volt(base)->bios;
@@ -64,13 +65,33 @@ gk104_volt_set(struct nvkm_volt *base, u
 	return 0;
 }
 
+static int
+gk104_volt_speedo_read(struct nvkm_volt *volt)
+{
+	struct nvkm_device *device = volt->subdev.device;
+	struct nvkm_fuse *fuse = device->fuse;
+	int ret;
+
+	if (!fuse)
+		return -EINVAL;
+
+	nvkm_wr32(device, 0x122634, 0x0);
+	ret = nvkm_fuse_read(fuse, 0x3a8);
+	nvkm_wr32(device, 0x122634, 0x41);
+	return ret;
+}
+
 static const struct nvkm_volt_func
 gk104_volt_pwm = {
+	.oneinit = gf100_volt_oneinit,
 	.volt_get = gk104_volt_get,
 	.volt_set = gk104_volt_set,
+	.speedo_read = gk104_volt_speedo_read,
 }, gk104_volt_gpio = {
+	.oneinit = gf100_volt_oneinit,
 	.vid_get = nvkm_voltgpio_get,
 	.vid_set = nvkm_voltgpio_set,
+	.speedo_read = gk104_volt_speedo_read,
 };
 
 int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gm20b.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 
 #include <core/tegra.h>
 
-const struct cvb_coef gm20b_cvb_coef[] = {
+static const struct cvb_coef gm20b_cvb_coef[] = {
 	/* KHz,             c0,      c1,   c2 */
 	/*  76800 */ { 1786666,  -85625, 1632 },
 	/* 153600 */ { 1846729,  -87525, 1632 },
@@ -58,7 +58,7 @@ static const struct cvb_coef gm20b_na_cv
 	/* 998400 */ { 1316991, 8144, -940, 808, -21583, 226 },
 };
 
-const u32 speedo_to_vmin[] = {
+static const u32 speedo_to_vmin[] = {
 	/*   0,      1,      2,      3,      4, */
 	950000, 840000, 818750, 840000, 810000,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,6 +25,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/gpio.h>
 #include <subdev/gpio.h>
+#include "priv.h"
 
 static const u8 tags[] = {
 	DCB_GPIO_VID0, DCB_GPIO_VID1, DCB_GPIO_VID2, DCB_GPIO_VID3,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,7 @@
 nvkm-y += nvkm/subdev/volt/base.o
 nvkm-y += nvkm/subdev/volt/gpio.o
 nvkm-y += nvkm/subdev/volt/nv40.o
+nvkm-y += nvkm/subdev/volt/gf100.o
 nvkm-y += nvkm/subdev/volt/gk104.o
 nvkm-y += nvkm/subdev/volt/gk20a.o
 nvkm-y += nvkm/subdev/volt/gm20b.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,11 +9,13 @@ int nvkm_volt_new_(const struct nvkm_vol
 		   int index, struct nvkm_volt **);
 
 struct nvkm_volt_func {
+	int (*oneinit)(struct nvkm_volt *);
 	int (*volt_get)(struct nvkm_volt *);
 	int (*volt_set)(struct nvkm_volt *, u32 uv);
 	int (*vid_get)(struct nvkm_volt *);
 	int (*vid_set)(struct nvkm_volt *, u8 vid);
 	int (*set_id)(struct nvkm_volt *, u8 id, int condition);
+	int (*speedo_read)(struct nvkm_volt *);
 };
 
 int nvkm_voltgpio_init(struct nvkm_volt *);
@@ -23,4 +25,6 @@ int nvkm_voltgpio_set(struct nvkm_volt *
 int nvkm_voltpwm_init(struct nvkm_volt *volt);
 int nvkm_voltpwm_get(struct nvkm_volt *volt);
 int nvkm_voltpwm_set(struct nvkm_volt *volt, u32 uv);
+
+int gf100_volt_oneinit(struct nvkm_volt *);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/connector-analog-tv.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,23 +24,24 @@ struct panel_drv_data {
 
 	struct device *dev;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 
 	bool invert_polarity;
 };
 
-static const struct omap_video_timings tvc_pal_timings = {
-	.x_res		= 720,
-	.y_res		= 574,
+static const struct videomode tvc_pal_vm = {
+	.hactive	= 720,
+	.vactive	= 574,
 	.pixelclock	= 13500000,
-	.hsw		= 64,
-	.hfp		= 12,
-	.hbp		= 68,
-	.vsw		= 5,
-	.vfp		= 5,
-	.vbp		= 41,
+	.hsync_len	= 64,
+	.hfront_porch	= 12,
+	.hback_porch	= 68,
+	.vsync_len	= 5,
+	.vfront_porch	= 5,
+	.vback_porch	= 41,
 
-	.interlace	= true,
+	.flags		= DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
+			  DISPLAY_FLAGS_VSYNC_LOW,
 };
 
 static const struct of_device_id tvc_of_match[];
@@ -92,7 +93,7 @@ static int tvc_enable(struct omap_dss_de
 	if (omapdss_device_is_enabled(dssdev))
 		return 0;
 
-	in->ops.atv->set_timings(in, &ddata->timings);
+	in->ops.atv->set_timings(in, &ddata->vm);
 
 	if (!ddata->dev->of_node) {
 		in->ops.atv->set_type(in, OMAP_DSS_VENC_TYPE_COMPOSITE);
@@ -126,32 +127,32 @@ static void tvc_disable(struct omap_dss_
 }
 
 static void tvc_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.atv->set_timings(in, timings);
+	in->ops.atv->set_timings(in, vm);
 }
 
 static void tvc_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->timings;
+	*vm = ddata->vm;
 }
 
 static int tvc_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.atv->check_timings(in, timings);
+	return in->ops.atv->check_timings(in, vm);
 }
 
 static u32 tvc_get_wss(struct omap_dss_device *dssdev)
@@ -253,14 +254,14 @@ static int tvc_probe(struct platform_dev
 		return -ENODEV;
 	}
 
-	ddata->timings = tvc_pal_timings;
+	ddata->vm = tvc_pal_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->driver = &tvc_driver;
 	dssdev->dev = &pdev->dev;
 	dssdev->type = OMAP_DISPLAY_TYPE_VENC;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = tvc_pal_timings;
+	dssdev->panel.vm = tvc_pal_vm;
 
 	r = omapdss_register_display(dssdev);
 	if (r) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/connector-dvi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/connector-dvi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/connector-dvi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/connector-dvi.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,32 +19,30 @@
 
 #include "../dss/omapdss.h"
 
-static const struct omap_video_timings dvic_default_timings = {
-	.x_res		= 640,
-	.y_res		= 480,
+static const struct videomode dvic_default_vm = {
+	.hactive	= 640,
+	.vactive	= 480,
 
 	.pixelclock	= 23500000,
 
-	.hfp		= 48,
-	.hsw		= 32,
-	.hbp		= 80,
+	.hfront_porch	= 48,
+	.hsync_len	= 32,
+	.hback_porch	= 80,
 
-	.vfp		= 3,
-	.vsw		= 4,
-	.vbp		= 7,
+	.vfront_porch	= 3,
+	.vsync_len	= 4,
+	.vback_porch	= 7,
 
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.flags		= DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH |
+			  DISPLAY_FLAGS_SYNC_NEGEDGE | DISPLAY_FLAGS_DE_HIGH |
+			  DISPLAY_FLAGS_PIXDATA_POSEDGE,
 };
 
 struct panel_drv_data {
 	struct omap_dss_device dssdev;
 	struct omap_dss_device *in;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 
 	struct i2c_adapter *i2c_adapter;
 };
@@ -90,7 +88,7 @@ static int dvic_enable(struct omap_dss_d
 	if (omapdss_device_is_enabled(dssdev))
 		return 0;
 
-	in->ops.dvi->set_timings(in, &ddata->timings);
+	in->ops.dvi->set_timings(in, &ddata->vm);
 
 	r = in->ops.dvi->enable(in);
 	if (r)
@@ -115,32 +113,32 @@ static void dvic_disable(struct omap_dss
 }
 
 static void dvic_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dvi->set_timings(in, timings);
+	in->ops.dvi->set_timings(in, vm);
 }
 
 static void dvic_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->timings;
+	*vm = ddata->vm;
 }
 
 static int dvic_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			      struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.dvi->check_timings(in, timings);
+	return in->ops.dvi->check_timings(in, vm);
 }
 
 static int dvic_ddc_read(struct i2c_adapter *adapter,
@@ -287,14 +285,14 @@ static int dvic_probe(struct platform_de
 	if (r)
 		return r;
 
-	ddata->timings = dvic_default_timings;
+	ddata->vm = dvic_default_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->driver = &dvic_driver;
 	dssdev->dev = &pdev->dev;
 	dssdev->type = OMAP_DISPLAY_TYPE_DVI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = dvic_default_timings;
+	dssdev->panel.vm = dvic_default_vm;
 
 	r = omapdss_register_display(dssdev);
 	if (r) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,21 +21,18 @@
 
 #include "../dss/omapdss.h"
 
-static const struct omap_video_timings hdmic_default_timings = {
-	.x_res		= 640,
-	.y_res		= 480,
+static const struct videomode hdmic_default_vm = {
+	.hactive	= 640,
+	.vactive	= 480,
 	.pixelclock	= 25175000,
-	.hsw		= 96,
-	.hfp		= 16,
-	.hbp		= 48,
-	.vsw		= 2,
-	.vfp		= 11,
-	.vbp		= 31,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hsync_len	= 96,
+	.hfront_porch	= 16,
+	.hback_porch	= 48,
+	.vsync_len	= 2,
+	.vfront_porch	= 11,
+	.vback_porch	= 31,
 
-	.interlace	= false,
+	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
 };
 
 struct panel_drv_data {
@@ -44,7 +41,7 @@ struct panel_drv_data {
 
 	struct device *dev;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 
 	int hpd_gpio;
 };
@@ -96,7 +93,7 @@ static int hdmic_enable(struct omap_dss_
 	if (omapdss_device_is_enabled(dssdev))
 		return 0;
 
-	in->ops.hdmi->set_timings(in, &ddata->timings);
+	in->ops.hdmi->set_timings(in, &ddata->vm);
 
 	r = in->ops.hdmi->enable(in);
 	if (r)
@@ -123,32 +120,32 @@ static void hdmic_disable(struct omap_ds
 }
 
 static void hdmic_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			      struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.hdmi->set_timings(in, timings);
+	in->ops.hdmi->set_timings(in, vm);
 }
 
 static void hdmic_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			      struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->timings;
+	*vm = ddata->vm;
 }
 
 static int hdmic_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			       struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.hdmi->check_timings(in, timings);
+	return in->ops.hdmi->check_timings(in, vm);
 }
 
 static int hdmic_read_edid(struct omap_dss_device *dssdev,
@@ -259,14 +256,14 @@ static int hdmic_probe(struct platform_d
 			goto err_reg;
 	}
 
-	ddata->timings = hdmic_default_timings;
+	ddata->vm = hdmic_default_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->driver = &hdmic_driver;
 	dssdev->dev = &pdev->dev;
 	dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = hdmic_default_timings;
+	dssdev->panel.vm = hdmic_default_vm;
 
 	r = omapdss_register_display(dssdev);
 	if (r) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/encoder-opa362.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@ struct panel_drv_data {
 
 	struct gpio_desc *enable_gpio;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 };
 
 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -90,7 +90,7 @@ static int opa362_enable(struct omap_dss
 	if (omapdss_device_is_enabled(dssdev))
 		return 0;
 
-	in->ops.atv->set_timings(in, &ddata->timings);
+	in->ops.atv->set_timings(in, &ddata->vm);
 
 	r = in->ops.atv->enable(in);
 	if (r)
@@ -123,38 +123,38 @@ static void opa362_disable(struct omap_d
 }
 
 static void opa362_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			       struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
 	dev_dbg(dssdev->dev, "set_timings\n");
 
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.atv->set_timings(in, timings);
+	in->ops.atv->set_timings(in, vm);
 }
 
 static void opa362_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			       struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
 	dev_dbg(dssdev->dev, "get_timings\n");
 
-	*timings = ddata->timings;
+	*vm = ddata->vm;
 }
 
 static int opa362_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
 	dev_dbg(dssdev->dev, "check_timings\n");
 
-	return in->ops.atv->check_timings(in, timings);
+	return in->ops.atv->check_timings(in, vm);
 }
 
 static void opa362_set_type(struct omap_dss_device *dssdev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tfp410.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@ struct panel_drv_data {
 	int pd_gpio;
 	int data_lines;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 };
 
 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -81,7 +81,7 @@ static int tfp410_enable(struct omap_dss
 	if (omapdss_device_is_enabled(dssdev))
 		return 0;
 
-	in->ops.dpi->set_timings(in, &ddata->timings);
+	in->ops.dpi->set_timings(in, &ddata->vm);
 	if (ddata->data_lines)
 		in->ops.dpi->set_data_lines(in, ddata->data_lines);
 
@@ -113,44 +113,43 @@ static void tfp410_disable(struct omap_d
 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 }
 
-static void tfp410_fix_timings(struct omap_video_timings *timings)
+static void tfp410_fix_timings(struct videomode *vm)
 {
-	timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+	vm->flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+		     DISPLAY_FLAGS_SYNC_POSEDGE;
 }
 
 static void tfp410_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			       struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	tfp410_fix_timings(timings);
+	tfp410_fix_timings(vm);
 
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dpi->set_timings(in, timings);
+	in->ops.dpi->set_timings(in, vm);
 }
 
 static void tfp410_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			       struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->timings;
+	*vm = ddata->vm;
 }
 
 static int tfp410_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	tfp410_fix_timings(timings);
+	tfp410_fix_timings(vm);
 
-	return in->ops.dpi->check_timings(in, timings);
+	return in->ops.dpi->check_timings(in, vm);
 }
 
 static const struct omapdss_dvi_ops tfp410_dvi_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@ struct panel_drv_data {
 	struct gpio_desc *ls_oe_gpio;
 	struct gpio_desc *hpd_gpio;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 };
 
 #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev)
@@ -80,7 +80,7 @@ static int tpd_enable(struct omap_dss_de
 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
 		return 0;
 
-	in->ops.hdmi->set_timings(in, &ddata->timings);
+	in->ops.hdmi->set_timings(in, &ddata->vm);
 
 	r = in->ops.hdmi->enable(in);
 	if (r)
@@ -105,33 +105,33 @@ static void tpd_disable(struct omap_dss_
 }
 
 static void tpd_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->timings = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.hdmi->set_timings(in, timings);
+	in->ops.hdmi->set_timings(in, vm);
 }
 
 static void tpd_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->timings;
+	*vm = ddata->vm;
 }
 
 static int tpd_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 	int r;
 
-	r = in->ops.hdmi->check_timings(in, timings);
+	r = in->ops.hdmi->check_timings(in, vm);
 
 	return r;
 }
@@ -234,25 +234,30 @@ static int tpd_probe(struct platform_dev
 	if (r)
 		return r;
 
-
 	gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0,
 		 GPIOD_OUT_LOW);
-	if (IS_ERR(gpio))
+	if (IS_ERR(gpio)) {
+		r = PTR_ERR(gpio);
 		goto err_gpio;
+	}
 
 	ddata->ct_cp_hpd_gpio = gpio;
 
 	gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1,
 		 GPIOD_OUT_LOW);
-	if (IS_ERR(gpio))
+	if (IS_ERR(gpio)) {
+		r = PTR_ERR(gpio);
 		goto err_gpio;
+	}
 
 	ddata->ls_oe_gpio = gpio;
 
 	gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2,
 		GPIOD_IN);
-	if (IS_ERR(gpio))
+	if (IS_ERR(gpio)) {
+		r = PTR_ERR(gpio);
 		goto err_gpio;
+	}
 
 	ddata->hpd_gpio = gpio;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-dpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@ struct panel_drv_data {
 
 	int data_lines;
 
-	struct omap_video_timings videomode;
+	struct videomode vm;
 
 	/* used for non-DT boot, to be removed */
 	int backlight_gpio;
@@ -80,7 +80,7 @@ static int panel_dpi_enable(struct omap_
 
 	if (ddata->data_lines)
 		in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
+	in->ops.dpi->set_timings(in, &ddata->vm);
 
 	r = in->ops.dpi->enable(in);
 	if (r)
@@ -122,32 +122,32 @@ static void panel_dpi_disable(struct oma
 }
 
 static void panel_dpi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dpi->set_timings(in, timings);
+	in->ops.dpi->set_timings(in, vm);
 }
 
 static void panel_dpi_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->videomode;
+	*vm = ddata->vm;
 }
 
 static int panel_dpi_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				   struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.dpi->check_timings(in, timings);
+	return in->ops.dpi->check_timings(in, vm);
 }
 
 static struct omap_dss_driver panel_dpi_ops = {
@@ -169,7 +169,6 @@ static int panel_dpi_probe_pdata(struct
 	const struct panel_dpi_platform_data *pdata;
 	struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 	struct omap_dss_device *dssdev, *in;
-	struct videomode vm;
 	int r;
 
 	pdata = dev_get_platdata(&pdev->dev);
@@ -185,8 +184,7 @@ static int panel_dpi_probe_pdata(struct
 
 	ddata->data_lines = pdata->data_lines;
 
-	videomode_from_timing(pdata->display_timing, &vm);
-	videomode_to_omap_video_timings(&vm, &ddata->videomode);
+	videomode_from_timing(pdata->display_timing, &ddata->vm);
 
 	dssdev = &ddata->dssdev;
 	dssdev->name = pdata->name;
@@ -214,7 +212,6 @@ static int panel_dpi_probe_of(struct pla
 	struct omap_dss_device *in;
 	int r;
 	struct display_timing timing;
-	struct videomode vm;
 	struct gpio_desc *gpio;
 
 	gpio = devm_gpiod_get_optional(&pdev->dev, "enable", GPIOD_OUT_LOW);
@@ -245,8 +242,7 @@ static int panel_dpi_probe_of(struct pla
 		return r;
 	}
 
-	videomode_from_timing(&timing, &vm);
-	videomode_to_omap_video_timings(&vm, &ddata->videomode);
+	videomode_from_timing(&timing, &ddata->vm);
 
 	in = omapdss_of_find_source_for_first_ep(node);
 	if (IS_ERR(in)) {
@@ -295,7 +291,7 @@ static int panel_dpi_probe(struct platfo
 	dssdev->driver = &panel_dpi_ops;
 	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
+	dssdev->panel.vm = ddata->vm;
 	dssdev->phy.dpi.data_lines = ddata->data_lines;
 
 	r = omapdss_register_display(dssdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@ struct panel_drv_data {
 	struct omap_dss_device dssdev;
 	struct omap_dss_device *in;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 
 	struct platform_device *pdev;
 
@@ -382,8 +382,8 @@ static const struct backlight_ops dsicm_
 static void dsicm_get_resolution(struct omap_dss_device *dssdev,
 		u16 *xres, u16 *yres)
 {
-	*xres = dssdev->panel.timings.x_res;
-	*yres = dssdev->panel.timings.y_res;
+	*xres = dssdev->panel.vm.hactive;
+	*yres = dssdev->panel.vm.vactive;
 }
 
 static ssize_t dsicm_num_errors_show(struct device *dev,
@@ -589,7 +589,7 @@ static int dsicm_power_on(struct panel_d
 	struct omap_dss_dsi_config dsi_config = {
 		.mode = OMAP_DSS_DSI_CMD_MODE,
 		.pixel_format = OMAP_DSS_DSI_FMT_RGB888,
-		.timings = &ddata->timings,
+		.vm = &ddata->vm,
 		.hs_clk_min = 150000000,
 		.hs_clk_max = 300000000,
 		.lp_clk_min = 7000000,
@@ -892,8 +892,8 @@ static int dsicm_update(struct omap_dss_
 
 	/* XXX no need to send this every frame, but dsi break if not done */
 	r = dsicm_set_update_window(ddata, 0, 0,
-			dssdev->panel.timings.x_res,
-			dssdev->panel.timings.y_res);
+			dssdev->panel.vm.hactive,
+			dssdev->panel.vm.vactive);
 	if (r)
 		goto err;
 
@@ -1023,9 +1023,8 @@ static int dsicm_memory_read(struct omap
 		goto err1;
 	}
 
-	size = min(w * h * 3,
-			dssdev->panel.timings.x_res *
-			dssdev->panel.timings.y_res * 3);
+	size = min((u32)w * h * 3,
+		   dssdev->panel.vm.hactive * dssdev->panel.vm.vactive * 3);
 
 	in->ops.dsi->bus_lock(in);
 
@@ -1186,14 +1185,14 @@ static int dsicm_probe(struct platform_d
 	if (r)
 		return r;
 
-	ddata->timings.x_res = 864;
-	ddata->timings.y_res = 480;
-	ddata->timings.pixelclock = 864 * 480 * 60;
+	ddata->vm.hactive = 864;
+	ddata->vm.vactive = 480;
+	ddata->vm.pixelclock = 864 * 480 * 60;
 
 	dssdev = &ddata->dssdev;
 	dssdev->dev = dev;
 	dssdev->driver = &dsicm_ops;
-	dssdev->panel.timings = ddata->timings;
+	dssdev->panel.vm = ddata->vm;
 	dssdev->type = OMAP_DISPLAY_TYPE_DSI;
 	dssdev->owner = THIS_MODULE;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-lgphilips-lb035q02.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,25 +19,28 @@
 
 #include "../dss/omapdss.h"
 
-static struct omap_video_timings lb035q02_timings = {
-	.x_res = 320,
-	.y_res = 240,
+static struct videomode lb035q02_vm = {
+	.hactive = 320,
+	.vactive = 240,
 
 	.pixelclock	= 6500000,
 
-	.hsw		= 2,
-	.hfp		= 20,
-	.hbp		= 68,
+	.hsync_len	= 2,
+	.hfront_porch	= 20,
+	.hback_porch	= 68,
 
-	.vsw		= 2,
-	.vfp		= 4,
-	.vbp		= 18,
+	.vsync_len	= 2,
+	.vfront_porch	= 4,
+	.vback_porch	= 18,
 
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+			  DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE |
+			  DISPLAY_FLAGS_PIXDATA_POSEDGE,
+	/*
+	 * Note: According to the panel documentation:
+	 * DE is active LOW
+	 * DATA needs to be driven on the FALLING edge
+	 */
 };
 
 struct panel_drv_data {
@@ -48,7 +51,7 @@ struct panel_drv_data {
 
 	int data_lines;
 
-	struct omap_video_timings videomode;
+	struct videomode vm;
 
 	struct gpio_desc *enable_gpio;
 };
@@ -158,7 +161,7 @@ static int lb035q02_enable(struct omap_d
 
 	if (ddata->data_lines)
 		in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
+	in->ops.dpi->set_timings(in, &ddata->vm);
 
 	r = in->ops.dpi->enable(in);
 	if (r)
@@ -189,32 +192,32 @@ static void lb035q02_disable(struct omap
 }
 
 static void lb035q02_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dpi->set_timings(in, timings);
+	in->ops.dpi->set_timings(in, vm);
 }
 
 static void lb035q02_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->videomode;
+	*vm = ddata->vm;
 }
 
 static int lb035q02_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.dpi->check_timings(in, timings);
+	return in->ops.dpi->check_timings(in, vm);
 }
 
 static struct omap_dss_driver lb035q02_ops = {
@@ -278,14 +281,14 @@ static int lb035q02_panel_spi_probe(stru
 	if (r)
 		return r;
 
-	ddata->videomode = lb035q02_timings;
+	ddata->vm = lb035q02_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->dev = &spi->dev;
 	dssdev->driver = &lb035q02_ops;
 	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
+	dssdev->panel.vm = ddata->vm;
 	dssdev->phy.dpi.data_lines = ddata->data_lines;
 
 	r = omapdss_register_display(dssdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-nec-nl8048hl11.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@ struct panel_drv_data {
 	struct omap_dss_device	dssdev;
 	struct omap_dss_device *in;
 
-	struct omap_video_timings videomode;
+	struct videomode vm;
 
 	int data_lines;
 
@@ -65,22 +65,20 @@ static const struct {
 	{ 156, 0x00 }, { 157, 0x00 }, { 2, 0x00 },
 };
 
-static const struct omap_video_timings nec_8048_panel_timings = {
-	.x_res		= LCD_XRES,
-	.y_res		= LCD_YRES,
+static const struct videomode nec_8048_panel_vm = {
+	.hactive	= LCD_XRES,
+	.vactive	= LCD_YRES,
 	.pixelclock	= LCD_PIXEL_CLOCK,
-	.hfp		= 6,
-	.hsw		= 1,
-	.hbp		= 4,
-	.vfp		= 3,
-	.vsw		= 1,
-	.vbp		= 4,
+	.hfront_porch	= 6,
+	.hsync_len	= 1,
+	.hback_porch	= 4,
+	.vfront_porch	= 3,
+	.vsync_len	= 1,
+	.vback_porch	= 4,
 
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+			  DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+			  DISPLAY_FLAGS_PIXDATA_POSEDGE,
 };
 
 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -157,7 +155,7 @@ static int nec_8048_enable(struct omap_d
 
 	if (ddata->data_lines)
 		in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
+	in->ops.dpi->set_timings(in, &ddata->vm);
 
 	r = in->ops.dpi->enable(in);
 	if (r)
@@ -188,32 +186,32 @@ static void nec_8048_disable(struct omap
 }
 
 static void nec_8048_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dpi->set_timings(in, timings);
+	in->ops.dpi->set_timings(in, vm);
 }
 
 static void nec_8048_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->videomode;
+	*vm = ddata->vm;
 }
 
 static int nec_8048_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.dpi->check_timings(in, timings);
+	return in->ops.dpi->check_timings(in, vm);
 }
 
 static struct omap_dss_driver nec_8048_ops = {
@@ -306,14 +304,14 @@ static int nec_8048_probe(struct spi_dev
 			goto err_gpio;
 	}
 
-	ddata->videomode = nec_8048_panel_timings;
+	ddata->vm = nec_8048_panel_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->dev = &spi->dev;
 	dssdev->driver = &nec_8048_ops;
 	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
+	dssdev->panel.vm = ddata->vm;
 
 	r = omapdss_register_display(dssdev);
 	if (r) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-sharp-ls037v7dw01.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,7 +26,7 @@ struct panel_drv_data {
 
 	int data_lines;
 
-	struct omap_video_timings videomode;
+	struct videomode vm;
 
 	struct gpio_desc *resb_gpio;	/* low = reset active min 20 us */
 	struct gpio_desc *ini_gpio;	/* high = power on */
@@ -35,25 +35,27 @@ struct panel_drv_data {
 	struct gpio_desc *ud_gpio;	/* high = conventional vertical scanning */
 };
 
-static const struct omap_video_timings sharp_ls_timings = {
-	.x_res = 480,
-	.y_res = 640,
+static const struct videomode sharp_ls_vm = {
+	.hactive = 480,
+	.vactive = 640,
 
 	.pixelclock	= 19200000,
 
-	.hsw		= 2,
-	.hfp		= 1,
-	.hbp		= 28,
+	.hsync_len	= 2,
+	.hfront_porch	= 1,
+	.hback_porch	= 28,
 
-	.vsw		= 1,
-	.vfp		= 1,
-	.vbp		= 1,
+	.vsync_len	= 1,
+	.vfront_porch	= 1,
+	.vback_porch	= 1,
 
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+			  DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE |
+			  DISPLAY_FLAGS_PIXDATA_POSEDGE,
+	/*
+	 * Note: According to the panel documentation:
+	 * DATA needs to be driven on the FALLING edge
+	 */
 };
 
 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -99,7 +101,7 @@ static int sharp_ls_enable(struct omap_d
 
 	if (ddata->data_lines)
 		in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
+	in->ops.dpi->set_timings(in, &ddata->vm);
 
 	if (ddata->vcc) {
 		r = regulator_enable(ddata->vcc);
@@ -154,32 +156,32 @@ static void sharp_ls_disable(struct omap
 }
 
 static void sharp_ls_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dpi->set_timings(in, timings);
+	in->ops.dpi->set_timings(in, vm);
 }
 
 static void sharp_ls_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->videomode;
+	*vm = ddata->vm;
 }
 
 static int sharp_ls_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.dpi->check_timings(in, timings);
+	return in->ops.dpi->check_timings(in, vm);
 }
 
 static struct omap_dss_driver sharp_ls_ops = {
@@ -279,14 +281,14 @@ static int sharp_ls_probe(struct platfor
 	if (r)
 		return r;
 
-	ddata->videomode = sharp_ls_timings;
+	ddata->vm = sharp_ls_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->dev = &pdev->dev;
 	dssdev->driver = &sharp_ls_ops;
 	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
+	dssdev->panel.vm = ddata->vm;
 	dssdev->phy.dpi.data_lines = ddata->data_lines;
 
 	r = omapdss_register_display(dssdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,7 @@ struct panel_drv_data {
 	int reset_gpio;
 	int datapairs;
 
-	struct omap_video_timings videomode;
+	struct videomode vm;
 
 	char		*name;
 	int		enabled;
@@ -92,23 +92,20 @@ struct panel_drv_data {
 	struct backlight_device *bl_dev;
 };
 
-static const struct omap_video_timings acx565akm_panel_timings = {
-	.x_res		= 800,
-	.y_res		= 480,
+static const struct videomode acx565akm_panel_vm = {
+	.hactive	= 800,
+	.vactive	= 480,
 	.pixelclock	= 24000000,
-	.hfp		= 28,
-	.hsw		= 4,
-	.hbp		= 24,
-	.vfp		= 3,
-	.vsw		= 3,
-	.vbp		= 4,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hfront_porch	= 28,
+	.hsync_len	= 4,
+	.hback_porch	= 24,
+	.vfront_porch	= 3,
+	.vsync_len	= 3,
+	.vback_porch	= 4,
 
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+			  DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_NEGEDGE |
+			  DISPLAY_FLAGS_PIXDATA_POSEDGE,
 };
 
 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -548,7 +545,7 @@ static int acx565akm_panel_power_on(stru
 
 	dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 
-	in->ops.sdi->set_timings(in, &ddata->videomode);
+	in->ops.sdi->set_timings(in, &ddata->vm);
 
 	if (ddata->datapairs > 0)
 		in->ops.sdi->set_datapairs(in, ddata->datapairs);
@@ -662,32 +659,32 @@ static void acx565akm_disable(struct oma
 }
 
 static void acx565akm_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.sdi->set_timings(in, timings);
+	in->ops.sdi->set_timings(in, vm);
 }
 
 static void acx565akm_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->videomode;
+	*vm = ddata->vm;
 }
 
 static int acx565akm_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				   struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.sdi->check_timings(in, timings);
+	return in->ops.sdi->check_timings(in, vm);
 }
 
 static struct omap_dss_driver acx565akm_ops = {
@@ -845,14 +842,14 @@ static int acx565akm_probe(struct spi_de
 	acx565akm_bl_update_status(bldev);
 
 
-	ddata->videomode = acx565akm_panel_timings;
+	ddata->vm = acx565akm_panel_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->dev = &spi->dev;
 	dssdev->driver = &acx565akm_ops;
 	dssdev->type = OMAP_DISPLAY_TYPE_SDI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
+	dssdev->panel.vm = ddata->vm;
 
 	r = omapdss_register_display(dssdev);
 	if (r) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td028ttec1.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,28 +37,29 @@ struct panel_drv_data {
 
 	int data_lines;
 
-	struct omap_video_timings videomode;
+	struct videomode vm;
 
 	struct spi_device *spi_dev;
 };
 
-static struct omap_video_timings td028ttec1_panel_timings = {
-	.x_res		= 480,
-	.y_res		= 640,
+static struct videomode td028ttec1_panel_vm = {
+	.hactive	= 480,
+	.vactive	= 640,
 	.pixelclock	= 22153000,
-	.hfp		= 24,
-	.hsw		= 8,
-	.hbp		= 8,
-	.vfp		= 4,
-	.vsw		= 2,
-	.vbp		= 2,
-
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
+	.hfront_porch	= 24,
+	.hsync_len	= 8,
+	.hback_porch	= 8,
+	.vfront_porch	= 4,
+	.vsync_len	= 2,
+	.vback_porch	= 2,
 
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+			  DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+			  DISPLAY_FLAGS_PIXDATA_NEGEDGE,
+	/*
+	 * Note: According to the panel documentation:
+	 * SYNC needs to be driven on the FALLING edge
+	 */
 };
 
 #define JBT_COMMAND	0x000
@@ -208,7 +209,7 @@ static int td028ttec1_panel_enable(struc
 
 	if (ddata->data_lines)
 		in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
+	in->ops.dpi->set_timings(in, &ddata->vm);
 
 	r = in->ops.dpi->enable(in);
 	if (r)
@@ -325,32 +326,32 @@ static void td028ttec1_panel_disable(str
 }
 
 static void td028ttec1_panel_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+					 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dpi->set_timings(in, timings);
+	in->ops.dpi->set_timings(in, vm);
 }
 
 static void td028ttec1_panel_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+					 struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->videomode;
+	*vm = ddata->vm;
 }
 
 static int td028ttec1_panel_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+					  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.dpi->check_timings(in, timings);
+	return in->ops.dpi->check_timings(in, vm);
 }
 
 static struct omap_dss_driver td028ttec1_ops = {
@@ -414,14 +415,14 @@ static int td028ttec1_panel_probe(struct
 	if (r)
 		return r;
 
-	ddata->videomode = td028ttec1_panel_timings;
+	ddata->vm = td028ttec1_panel_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->dev = &spi->dev;
 	dssdev->driver = &td028ttec1_ops;
 	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
+	dssdev->panel.vm = ddata->vm;
 	dssdev->phy.dpi.data_lines = ddata->data_lines;
 
 	r = omapdss_register_display(dssdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ struct panel_drv_data {
 	struct omap_dss_device	dssdev;
 	struct omap_dss_device *in;
 
-	struct omap_video_timings videomode;
+	struct videomode vm;
 
 	int data_lines;
 
@@ -72,25 +72,27 @@ struct panel_drv_data {
 	u32 power_on_resume:1;
 };
 
-static const struct omap_video_timings tpo_td043_timings = {
-	.x_res		= 800,
-	.y_res		= 480,
+static const struct videomode tpo_td043_vm = {
+	.hactive	= 800,
+	.vactive	= 480,
 
 	.pixelclock	= 36000000,
 
-	.hsw		= 1,
-	.hfp		= 68,
-	.hbp		= 214,
+	.hsync_len	= 1,
+	.hfront_porch	= 68,
+	.hback_porch	= 214,
 
-	.vsw		= 1,
-	.vfp		= 39,
-	.vbp		= 34,
+	.vsync_len	= 1,
+	.vfront_porch	= 39,
+	.vback_porch	= 34,
 
-	.vsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.hsync_level	= OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge	= OMAPDSS_DRIVE_SIG_FALLING_EDGE,
-	.de_level	= OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge	= OMAPDSS_DRIVE_SIG_RISING_EDGE,
+	.flags		= DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+			  DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+			  DISPLAY_FLAGS_PIXDATA_NEGEDGE,
+	/*
+	 * Note: According to the panel documentation:
+	 * SYNC needs to be driven on the FALLING edge
+	 */
 };
 
 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
@@ -378,7 +380,7 @@ static int tpo_td043_enable(struct omap_
 
 	if (ddata->data_lines)
 		in->ops.dpi->set_data_lines(in, ddata->data_lines);
-	in->ops.dpi->set_timings(in, &ddata->videomode);
+	in->ops.dpi->set_timings(in, &ddata->vm);
 
 	r = in->ops.dpi->enable(in);
 	if (r)
@@ -418,32 +420,32 @@ static void tpo_td043_disable(struct oma
 }
 
 static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	ddata->videomode = *timings;
-	dssdev->panel.timings = *timings;
+	ddata->vm = *vm;
+	dssdev->panel.vm = *vm;
 
-	in->ops.dpi->set_timings(in, timings);
+	in->ops.dpi->set_timings(in, vm);
 }
 
 static void tpo_td043_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				  struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 
-	*timings = ddata->videomode;
+	*vm = ddata->vm;
 }
 
 static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				   struct videomode *vm)
 {
 	struct panel_drv_data *ddata = to_panel_data(dssdev);
 	struct omap_dss_device *in = ddata->in;
 
-	return in->ops.dpi->check_timings(in, timings);
+	return in->ops.dpi->check_timings(in, vm);
 }
 
 static struct omap_dss_driver tpo_td043_ops = {
@@ -546,14 +548,14 @@ static int tpo_td043_probe(struct spi_de
 		goto err_sysfs;
 	}
 
-	ddata->videomode = tpo_td043_timings;
+	ddata->vm = tpo_td043_vm;
 
 	dssdev = &ddata->dssdev;
 	dssdev->dev = &spi->dev;
 	dssdev->driver = &tpo_td043_ops;
 	dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 	dssdev->owner = THIS_MODULE;
-	dssdev->panel.timings = ddata->videomode;
+	dssdev->panel.vm = ddata->vm;
 
 	r = omapdss_register_display(dssdev);
 	if (r) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dispc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dispc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dispc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dispc.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,7 @@ struct dispc_features {
 	unsigned long max_lcd_pclk;
 	unsigned long max_tv_pclk;
 	int (*calc_scaling) (unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
+		const struct videomode *vm,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -1679,7 +1679,7 @@ static void dispc_ovl_set_scaling_uv(enu
 {
 	int scale_x = out_width != orig_width;
 	int scale_y = out_height != orig_height;
-	bool chroma_upscale = plane != OMAP_DSS_WB ? true : false;
+	bool chroma_upscale = plane != OMAP_DSS_WB;
 
 	if (!dss_has_feature(FEAT_HANDLE_UV_SEPARATE))
 		return;
@@ -2179,7 +2179,7 @@ static void calc_tiler_rotation_offset(u
  * undocumented horizontal position and timing related limitations.
  */
 static int check_horiz_timing_omap3(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *t, u16 pos_x,
+		const struct videomode *vm, u16 pos_x,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		bool five_taps)
 {
@@ -2189,14 +2189,16 @@ static int check_horiz_timing_omap3(unsi
 	u64 val, blank;
 	int i;
 
-	nonactive = t->x_res + t->hfp + t->hsw + t->hbp - out_width;
+	nonactive = vm->hactive + vm->hfront_porch + vm->hsync_len +
+		    vm->hback_porch - out_width;
 
 	i = 0;
 	if (out_height < height)
 		i++;
 	if (out_width < width)
 		i++;
-	blank = div_u64((u64)(t->hbp + t->hsw + t->hfp) * lclk, pclk);
+	blank = div_u64((u64)(vm->hback_porch + vm->hsync_len + vm->hfront_porch) *
+			lclk, pclk);
 	DSSDBG("blanking period + ppl = %llu (limit = %u)\n", blank, limits[i]);
 	if (blank <= limits[i])
 		return -EINVAL;
@@ -2231,7 +2233,7 @@ static int check_horiz_timing_omap3(unsi
 }
 
 static unsigned long calc_core_clk_five_taps(unsigned long pclk,
-		const struct omap_video_timings *mgr_timings, u16 width,
+		const struct videomode *vm, u16 width,
 		u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode)
 {
@@ -2242,7 +2244,7 @@ static unsigned long calc_core_clk_five_
 		return (unsigned long) pclk;
 
 	if (height > out_height) {
-		unsigned int ppl = mgr_timings->x_res;
+		unsigned int ppl = vm->hactive;
 
 		tmp = (u64)pclk * height * out_width;
 		do_div(tmp, 2 * out_height * ppl);
@@ -2324,7 +2326,7 @@ static unsigned long calc_core_clk_44xx(
 }
 
 static int dispc_ovl_calc_scaling_24xx(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
+		const struct videomode *vm,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -2370,7 +2372,7 @@ static int dispc_ovl_calc_scaling_24xx(u
 }
 
 static int dispc_ovl_calc_scaling_34xx(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
+		const struct videomode *vm,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -2392,7 +2394,7 @@ static int dispc_ovl_calc_scaling_34xx(u
 				*five_taps = false;
 again:
 		if (*five_taps)
-			*core_clk = calc_core_clk_five_taps(pclk, mgr_timings,
+			*core_clk = calc_core_clk_five_taps(pclk, vm,
 						in_width, in_height, out_width,
 						out_height, color_mode);
 		else
@@ -2400,7 +2402,7 @@ again:
 					in_height, out_width, out_height,
 					mem_to_mem);
 
-		error = check_horiz_timing_omap3(pclk, lclk, mgr_timings,
+		error = check_horiz_timing_omap3(pclk, lclk, vm,
 				pos_x, in_width, in_height, out_width,
 				out_height, *five_taps);
 		if (error && *five_taps) {
@@ -2435,7 +2437,7 @@ again:
 		return -EINVAL;
 	}
 
-	if (check_horiz_timing_omap3(pclk, lclk, mgr_timings, pos_x, in_width,
+	if (check_horiz_timing_omap3(pclk, lclk, vm, pos_x, in_width,
 				in_height, out_width, out_height, *five_taps)) {
 			DSSERR("horizontal timing too tight\n");
 			return -EINVAL;
@@ -2455,7 +2457,7 @@ again:
 }
 
 static int dispc_ovl_calc_scaling_44xx(unsigned long pclk, unsigned long lclk,
-		const struct omap_video_timings *mgr_timings,
+		const struct videomode *vm,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		int *x_predecim, int *y_predecim, int *decim_x, int *decim_y,
@@ -2501,7 +2503,7 @@ static int dispc_ovl_calc_scaling_44xx(u
 
 static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk,
 		enum omap_overlay_caps caps,
-		const struct omap_video_timings *mgr_timings,
+		const struct videomode *vm,
 		u16 width, u16 height, u16 out_width, u16 out_height,
 		enum omap_color_mode color_mode, bool *five_taps,
 		int *x_predecim, int *y_predecim, u16 pos_x,
@@ -2515,7 +2517,7 @@ static int dispc_ovl_calc_scaling(unsign
 	if (width == out_width && height == out_height)
 		return 0;
 
-	if (!mem_to_mem && (pclk == 0 || mgr_timings->pixelclock == 0)) {
+	if (!mem_to_mem && (pclk == 0 || vm->pixelclock == 0)) {
 		DSSERR("cannot calculate scaling settings: pclk is zero\n");
 		return -EINVAL;
 	}
@@ -2551,7 +2553,7 @@ static int dispc_ovl_calc_scaling(unsign
 	if (decim_y > *y_predecim || out_height > height * 8)
 		return -EINVAL;
 
-	ret = dispc.feat->calc_scaling(pclk, lclk, mgr_timings, width, height,
+	ret = dispc.feat->calc_scaling(pclk, lclk, vm, width, height,
 		out_width, out_height, color_mode, five_taps,
 		x_predecim, y_predecim, &decim_x, &decim_y, pos_x, &core_clk,
 		mem_to_mem);
@@ -2591,7 +2593,7 @@ static int dispc_ovl_setup_common(enum o
 		u16 out_width, u16 out_height, enum omap_color_mode color_mode,
 		u8 rotation, bool mirror, u8 zorder, u8 pre_mult_alpha,
 		u8 global_alpha, enum omap_dss_rotation_type rotation_type,
-		bool replication, const struct omap_video_timings *mgr_timings,
+		bool replication, const struct videomode *vm,
 		bool mem_to_mem)
 {
 	bool five_taps = true;
@@ -2605,7 +2607,7 @@ static int dispc_ovl_setup_common(enum o
 	u16 in_height = height;
 	u16 in_width = width;
 	int x_predecim = 1, y_predecim = 1;
-	bool ilace = mgr_timings->interlace;
+	bool ilace = !!(vm->flags & DISPLAY_FLAGS_INTERLACED);
 	unsigned long pclk = dispc_plane_pclk_rate(plane);
 	unsigned long lclk = dispc_plane_lclk_rate(plane);
 
@@ -2647,7 +2649,7 @@ static int dispc_ovl_setup_common(enum o
 	if (!dss_feat_color_mode_supported(plane, color_mode))
 		return -EINVAL;
 
-	r = dispc_ovl_calc_scaling(pclk, lclk, caps, mgr_timings, in_width,
+	r = dispc_ovl_calc_scaling(pclk, lclk, caps, vm, in_width,
 			in_height, out_width, out_height, color_mode,
 			&five_taps, &x_predecim, &y_predecim, pos_x,
 			rotation_type, mem_to_mem);
@@ -2784,7 +2786,7 @@ static int dispc_ovl_setup_common(enum o
 }
 
 int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
-		bool replication, const struct omap_video_timings *mgr_timings,
+		bool replication, const struct videomode *vm,
 		bool mem_to_mem)
 {
 	int r;
@@ -2803,14 +2805,14 @@ int dispc_ovl_setup(enum omap_plane plan
 		oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
 		oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
 		oi->mirror, oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
-		oi->rotation_type, replication, mgr_timings, mem_to_mem);
+		oi->rotation_type, replication, vm, mem_to_mem);
 
 	return r;
 }
 EXPORT_SYMBOL(dispc_ovl_setup);
 
 int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
-		bool mem_to_mem, const struct omap_video_timings *mgr_timings)
+		bool mem_to_mem, const struct videomode *vm)
 {
 	int r;
 	u32 l;
@@ -2819,8 +2821,8 @@ int dispc_wb_setup(const struct omap_dss
 	const u8 zorder = 0, global_alpha = 0;
 	const bool replication = false;
 	bool truncation;
-	int in_width = mgr_timings->x_res;
-	int in_height = mgr_timings->y_res;
+	int in_width = vm->hactive;
+	int in_height = vm->vactive;
 	enum omap_overlay_caps caps =
 		OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
 
@@ -2833,7 +2835,7 @@ int dispc_wb_setup(const struct omap_dss
 		wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
 		wi->height, wi->color_mode, wi->rotation, wi->mirror, zorder,
 		wi->pre_mult_alpha, global_alpha, wi->rotation_type,
-		replication, mgr_timings, mem_to_mem);
+		replication, vm, mem_to_mem);
 
 	switch (wi->color_mode) {
 	case OMAP_DSS_COLOR_RGB16:
@@ -2867,8 +2869,8 @@ int dispc_wb_setup(const struct omap_dss
 	} else {
 		int wbdelay;
 
-		wbdelay = min(mgr_timings->vfp + mgr_timings->vsw +
-			mgr_timings->vbp, 255);
+		wbdelay = min(vm->vfront_porch +
+			      vm->vsync_len + vm->vback_porch, (u32)255);
 
 		/* WBDELAYCOUNT */
 		REG_FLD_MOD(DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0);
@@ -3093,10 +3095,10 @@ static bool _dispc_mgr_size_ok(u16 width
 		height <= dispc.feat->mgr_height_max;
 }
 
-static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
+static bool _dispc_lcd_timings_ok(int hsync_len, int hfp, int hbp,
 		int vsw, int vfp, int vbp)
 {
-	if (hsw < 1 || hsw > dispc.feat->sw_max ||
+	if (hsync_len < 1 || hsync_len > dispc.feat->sw_max ||
 			hfp < 1 || hfp > dispc.feat->hp_max ||
 			hbp < 1 || hbp > dispc.feat->hp_max ||
 			vsw < 1 || vsw > dispc.feat->sw_max ||
@@ -3110,113 +3112,77 @@ static bool _dispc_mgr_pclk_ok(enum omap
 		unsigned long pclk)
 {
 	if (dss_mgr_is_lcd(channel))
-		return pclk <= dispc.feat->max_lcd_pclk ? true : false;
+		return pclk <= dispc.feat->max_lcd_pclk;
 	else
-		return pclk <= dispc.feat->max_tv_pclk ? true : false;
+		return pclk <= dispc.feat->max_tv_pclk;
 }
 
-bool dispc_mgr_timings_ok(enum omap_channel channel,
-		const struct omap_video_timings *timings)
+bool dispc_mgr_timings_ok(enum omap_channel channel, const struct videomode *vm)
 {
-	if (!_dispc_mgr_size_ok(timings->x_res, timings->y_res))
+	if (!_dispc_mgr_size_ok(vm->hactive, vm->vactive))
 		return false;
 
-	if (!_dispc_mgr_pclk_ok(channel, timings->pixelclock))
+	if (!_dispc_mgr_pclk_ok(channel, vm->pixelclock))
 		return false;
 
 	if (dss_mgr_is_lcd(channel)) {
 		/* TODO: OMAP4+ supports interlace for LCD outputs */
-		if (timings->interlace)
+		if (vm->flags & DISPLAY_FLAGS_INTERLACED)
 			return false;
 
-		if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
-				timings->hbp, timings->vsw, timings->vfp,
-				timings->vbp))
+		if (!_dispc_lcd_timings_ok(vm->hsync_len,
+				vm->hfront_porch, vm->hback_porch,
+				vm->vsync_len, vm->vfront_porch,
+				vm->vback_porch))
 			return false;
 	}
 
 	return true;
 }
 
-static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
-		int hfp, int hbp, int vsw, int vfp, int vbp,
-		enum omap_dss_signal_level vsync_level,
-		enum omap_dss_signal_level hsync_level,
-		enum omap_dss_signal_edge data_pclk_edge,
-		enum omap_dss_signal_level de_level,
-		enum omap_dss_signal_edge sync_pclk_edge)
-
+static void _dispc_mgr_set_lcd_timings(enum omap_channel channel,
+				       const struct videomode *vm)
 {
 	u32 timing_h, timing_v, l;
 	bool onoff, rf, ipc, vs, hs, de;
 
-	timing_h = FLD_VAL(hsw-1, dispc.feat->sw_start, 0) |
-			FLD_VAL(hfp-1, dispc.feat->fp_start, 8) |
-			FLD_VAL(hbp-1, dispc.feat->bp_start, 20);
-	timing_v = FLD_VAL(vsw-1, dispc.feat->sw_start, 0) |
-			FLD_VAL(vfp, dispc.feat->fp_start, 8) |
-			FLD_VAL(vbp, dispc.feat->bp_start, 20);
+	timing_h = FLD_VAL(vm->hsync_len - 1, dispc.feat->sw_start, 0) |
+		   FLD_VAL(vm->hfront_porch - 1, dispc.feat->fp_start, 8) |
+		   FLD_VAL(vm->hback_porch - 1, dispc.feat->bp_start, 20);
+	timing_v = FLD_VAL(vm->vsync_len - 1, dispc.feat->sw_start, 0) |
+		   FLD_VAL(vm->vfront_porch, dispc.feat->fp_start, 8) |
+		   FLD_VAL(vm->vback_porch, dispc.feat->bp_start, 20);
 
 	dispc_write_reg(DISPC_TIMING_H(channel), timing_h);
 	dispc_write_reg(DISPC_TIMING_V(channel), timing_v);
 
-	switch (vsync_level) {
-	case OMAPDSS_SIG_ACTIVE_LOW:
-		vs = true;
-		break;
-	case OMAPDSS_SIG_ACTIVE_HIGH:
+	if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
 		vs = false;
-		break;
-	default:
-		BUG();
-	}
+	else
+		vs = true;
 
-	switch (hsync_level) {
-	case OMAPDSS_SIG_ACTIVE_LOW:
-		hs = true;
-		break;
-	case OMAPDSS_SIG_ACTIVE_HIGH:
+	if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
 		hs = false;
-		break;
-	default:
-		BUG();
-	}
+	else
+		hs = true;
 
-	switch (de_level) {
-	case OMAPDSS_SIG_ACTIVE_LOW:
-		de = true;
-		break;
-	case OMAPDSS_SIG_ACTIVE_HIGH:
+	if (vm->flags & DISPLAY_FLAGS_DE_HIGH)
 		de = false;
-		break;
-	default:
-		BUG();
-	}
+	else
+		de = true;
 
-	switch (data_pclk_edge) {
-	case OMAPDSS_DRIVE_SIG_RISING_EDGE:
+	if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
 		ipc = false;
-		break;
-	case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
+	else
 		ipc = true;
-		break;
-	default:
-		BUG();
-	}
 
 	/* always use the 'rf' setting */
 	onoff = true;
 
-	switch (sync_pclk_edge) {
-	case OMAPDSS_DRIVE_SIG_FALLING_EDGE:
-		rf = false;
-		break;
-	case OMAPDSS_DRIVE_SIG_RISING_EDGE:
+	if (vm->flags & DISPLAY_FLAGS_SYNC_POSEDGE)
 		rf = true;
-		break;
-	default:
-		BUG();
-	}
+	else
+		rf = false;
 
 	l = FLD_VAL(onoff, 17, 17) |
 		FLD_VAL(rf, 16, 16) |
@@ -3253,13 +3219,13 @@ static void _dispc_mgr_set_lcd_timings(e
 
 /* change name to mode? */
 void dispc_mgr_set_timings(enum omap_channel channel,
-		const struct omap_video_timings *timings)
+			   const struct videomode *vm)
 {
 	unsigned xtot, ytot;
 	unsigned long ht, vt;
-	struct omap_video_timings t = *timings;
+	struct videomode t = *vm;
 
-	DSSDBG("channel %d xres %u yres %u\n", channel, t.x_res, t.y_res);
+	DSSDBG("channel %d xres %u yres %u\n", channel, t.hactive, t.vactive);
 
 	if (!dispc_mgr_timings_ok(channel, &t)) {
 		BUG();
@@ -3267,34 +3233,37 @@ void dispc_mgr_set_timings(enum omap_cha
 	}
 
 	if (dss_mgr_is_lcd(channel)) {
-		_dispc_mgr_set_lcd_timings(channel, t.hsw, t.hfp, t.hbp, t.vsw,
-				t.vfp, t.vbp, t.vsync_level, t.hsync_level,
-				t.data_pclk_edge, t.de_level, t.sync_pclk_edge);
+		_dispc_mgr_set_lcd_timings(channel, &t);
 
-		xtot = t.x_res + t.hfp + t.hsw + t.hbp;
-		ytot = t.y_res + t.vfp + t.vsw + t.vbp;
+		xtot = t.hactive + t.hfront_porch + t.hsync_len + t.hback_porch;
+		ytot = t.vactive + t.vfront_porch + t.vsync_len + t.vback_porch;
 
-		ht = timings->pixelclock / xtot;
-		vt = timings->pixelclock / xtot / ytot;
+		ht = vm->pixelclock / xtot;
+		vt = vm->pixelclock / xtot / ytot;
 
-		DSSDBG("pck %u\n", timings->pixelclock);
-		DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
-			t.hsw, t.hfp, t.hbp, t.vsw, t.vfp, t.vbp);
+		DSSDBG("pck %lu\n", vm->pixelclock);
+		DSSDBG("hsync_len %d hfp %d hbp %d vsw %d vfp %d vbp %d\n",
+			t.hsync_len, t.hfront_porch, t.hback_porch,
+			t.vsync_len, t.vfront_porch, t.vback_porch);
 		DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n",
-			t.vsync_level, t.hsync_level, t.data_pclk_edge,
-			t.de_level, t.sync_pclk_edge);
+			!!(t.flags & DISPLAY_FLAGS_VSYNC_HIGH),
+			!!(t.flags & DISPLAY_FLAGS_HSYNC_HIGH),
+			!!(t.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE),
+			!!(t.flags & DISPLAY_FLAGS_DE_HIGH),
+			!!(t.flags & DISPLAY_FLAGS_SYNC_POSEDGE));
 
 		DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt);
 	} else {
-		if (t.interlace)
-			t.y_res /= 2;
+		if (t.flags & DISPLAY_FLAGS_INTERLACED)
+			t.vactive /= 2;
 
 		if (dispc.feat->supports_double_pixel)
-			REG_FLD_MOD(DISPC_CONTROL, t.double_pixel ? 1 : 0,
-				19, 17);
+			REG_FLD_MOD(DISPC_CONTROL,
+				    !!(t.flags & DISPLAY_FLAGS_DOUBLECLK),
+				    19, 17);
 	}
 
-	dispc_mgr_set_size(channel, t.x_res, t.y_res);
+	dispc_mgr_set_size(channel, t.hactive, t.vactive);
 }
 EXPORT_SYMBOL(dispc_mgr_set_timings);
 
@@ -4214,23 +4183,20 @@ EXPORT_SYMBOL(dispc_free_irq);
  */
 
 static const struct dispc_errata_i734_data {
-	struct omap_video_timings timings;
+	struct videomode vm;
 	struct omap_overlay_info ovli;
 	struct omap_overlay_manager_info mgri;
 	struct dss_lcd_mgr_config lcd_conf;
 } i734 = {
-	.timings = {
-		.x_res = 8, .y_res = 1,
+	.vm = {
+		.hactive = 8, .vactive = 1,
 		.pixelclock = 16000000,
-		.hsw = 8, .hfp = 4, .hbp = 4,
-		.vsw = 1, .vfp = 1, .vbp = 1,
-		.vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-		.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-		.interlace = false,
-		.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
-		.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
-		.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
-		.double_pixel = false,
+		.hsync_len = 8, .hfront_porch = 4, .hback_porch = 4,
+		.vsync_len = 1, .vfront_porch = 1, .vback_porch = 1,
+
+		.flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
+			 DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_SYNC_POSEDGE |
+			 DISPLAY_FLAGS_PIXDATA_POSEDGE,
 	},
 	.ovli = {
 		.screen_width = 1,
@@ -4320,7 +4286,7 @@ static void dispc_errata_i734_wa(void)
 
 	/* Setup and enable GFX plane */
 	dispc_ovl_set_channel_out(OMAP_DSS_GFX, OMAP_DSS_CHANNEL_LCD);
-	dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.timings, false);
+	dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.vm, false);
 	dispc_ovl_enable(OMAP_DSS_GFX, true);
 
 	/* Set up and enable display manager for LCD1 */
@@ -4328,7 +4294,7 @@ static void dispc_errata_i734_wa(void)
 	dispc_calc_clock_rates(dss_get_dispc_clk_rate(),
 			       &lcd_conf.clock_info);
 	dispc_mgr_set_lcd_config(OMAP_DSS_CHANNEL_LCD, &lcd_conf);
-	dispc_mgr_set_timings(OMAP_DSS_CHANNEL_LCD, &i734.timings);
+	dispc_mgr_set_timings(OMAP_DSS_CHANNEL_LCD, &i734.vm);
 
 	dispc_clear_irqstatus(framedone_irq);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/display.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,8 +35,8 @@
 void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
 			u16 *xres, u16 *yres)
 {
-	*xres = dssdev->panel.timings.x_res;
-	*yres = dssdev->panel.timings.y_res;
+	*xres = dssdev->panel.vm.hactive;
+	*yres = dssdev->panel.vm.vactive;
 }
 EXPORT_SYMBOL(omapdss_default_get_resolution);
 
@@ -72,9 +72,9 @@ int omapdss_default_get_recommended_bpp(
 EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
 
 void omapdss_default_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
-	*timings = dssdev->panel.timings;
+	*vm = dssdev->panel.vm;
 }
 EXPORT_SYMBOL(omapdss_default_get_timings);
 
@@ -217,73 +217,3 @@ struct omap_dss_device *omap_dss_find_de
 	return NULL;
 }
 EXPORT_SYMBOL(omap_dss_find_device);
-
-void videomode_to_omap_video_timings(const struct videomode *vm,
-		struct omap_video_timings *ovt)
-{
-	memset(ovt, 0, sizeof(*ovt));
-
-	ovt->pixelclock = vm->pixelclock;
-	ovt->x_res = vm->hactive;
-	ovt->hbp = vm->hback_porch;
-	ovt->hfp = vm->hfront_porch;
-	ovt->hsw = vm->hsync_len;
-	ovt->y_res = vm->vactive;
-	ovt->vbp = vm->vback_porch;
-	ovt->vfp = vm->vfront_porch;
-	ovt->vsw = vm->vsync_len;
-
-	ovt->vsync_level = vm->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
-		OMAPDSS_SIG_ACTIVE_HIGH :
-		OMAPDSS_SIG_ACTIVE_LOW;
-	ovt->hsync_level = vm->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
-		OMAPDSS_SIG_ACTIVE_HIGH :
-		OMAPDSS_SIG_ACTIVE_LOW;
-	ovt->de_level = vm->flags & DISPLAY_FLAGS_DE_HIGH ?
-		OMAPDSS_SIG_ACTIVE_HIGH :
-		OMAPDSS_SIG_ACTIVE_LOW;
-	ovt->data_pclk_edge = vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ?
-		OMAPDSS_DRIVE_SIG_RISING_EDGE :
-		OMAPDSS_DRIVE_SIG_FALLING_EDGE;
-
-	ovt->sync_pclk_edge = ovt->data_pclk_edge;
-}
-EXPORT_SYMBOL(videomode_to_omap_video_timings);
-
-void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
-		struct videomode *vm)
-{
-	memset(vm, 0, sizeof(*vm));
-
-	vm->pixelclock = ovt->pixelclock;
-
-	vm->hactive = ovt->x_res;
-	vm->hback_porch = ovt->hbp;
-	vm->hfront_porch = ovt->hfp;
-	vm->hsync_len = ovt->hsw;
-	vm->vactive = ovt->y_res;
-	vm->vback_porch = ovt->vbp;
-	vm->vfront_porch = ovt->vfp;
-	vm->vsync_len = ovt->vsw;
-
-	if (ovt->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		vm->flags |= DISPLAY_FLAGS_HSYNC_HIGH;
-	else
-		vm->flags |= DISPLAY_FLAGS_HSYNC_LOW;
-
-	if (ovt->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		vm->flags |= DISPLAY_FLAGS_VSYNC_HIGH;
-	else
-		vm->flags |= DISPLAY_FLAGS_VSYNC_LOW;
-
-	if (ovt->de_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		vm->flags |= DISPLAY_FLAGS_DE_HIGH;
-	else
-		vm->flags |= DISPLAY_FLAGS_DE_LOW;
-
-	if (ovt->data_pclk_edge == OMAPDSS_DRIVE_SIG_RISING_EDGE)
-		vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
-	else
-		vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
-}
-EXPORT_SYMBOL(omap_video_timings_to_videomode);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dpi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dpi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@ struct dpi_data {
 
 	struct mutex lock;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 	struct dss_lcd_mgr_config mgr_config;
 	int data_lines;
 
@@ -333,31 +333,31 @@ static int dpi_set_mode(struct dpi_data
 {
 	struct omap_dss_device *out = &dpi->output;
 	enum omap_channel channel = out->dispc_channel;
-	struct omap_video_timings *t = &dpi->timings;
+	struct videomode *vm = &dpi->vm;
 	int lck_div = 0, pck_div = 0;
 	unsigned long fck = 0;
 	unsigned long pck;
 	int r = 0;
 
 	if (dpi->pll)
-		r = dpi_set_pll_clk(dpi, channel, t->pixelclock, &fck,
+		r = dpi_set_pll_clk(dpi, channel, vm->pixelclock, &fck,
 				&lck_div, &pck_div);
 	else
-		r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
+		r = dpi_set_dispc_clk(dpi, vm->pixelclock, &fck,
 				&lck_div, &pck_div);
 	if (r)
 		return r;
 
 	pck = fck / lck_div / pck_div;
 
-	if (pck != t->pixelclock) {
-		DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
-			t->pixelclock, pck);
+	if (pck != vm->pixelclock) {
+		DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n",
+			vm->pixelclock, pck);
 
-		t->pixelclock = pck;
+		vm->pixelclock = pck;
 	}
 
-	dss_mgr_set_timings(channel, t);
+	dss_mgr_set_timings(channel, vm);
 
 	return 0;
 }
@@ -476,7 +476,7 @@ static void dpi_display_disable(struct o
 }
 
 static void dpi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
 	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 
@@ -484,25 +484,25 @@ static void dpi_set_timings(struct omap_
 
 	mutex_lock(&dpi->lock);
 
-	dpi->timings = *timings;
+	dpi->vm = *vm;
 
 	mutex_unlock(&dpi->lock);
 }
 
 static void dpi_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
 	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 
 	mutex_lock(&dpi->lock);
 
-	*timings = dpi->timings;
+	*vm = dpi->vm;
 
 	mutex_unlock(&dpi->lock);
 }
 
 static int dpi_check_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
 	enum omap_channel channel = dpi->output.dispc_channel;
@@ -512,23 +512,23 @@ static int dpi_check_timings(struct omap
 	struct dpi_clk_calc_ctx ctx;
 	bool ok;
 
-	if (timings->x_res % 8 != 0)
+	if (vm->hactive % 8 != 0)
 		return -EINVAL;
 
-	if (!dispc_mgr_timings_ok(channel, timings))
+	if (!dispc_mgr_timings_ok(channel, vm))
 		return -EINVAL;
 
-	if (timings->pixelclock == 0)
+	if (vm->pixelclock == 0)
 		return -EINVAL;
 
 	if (dpi->pll) {
-		ok = dpi_pll_clk_calc(dpi, timings->pixelclock, &ctx);
+		ok = dpi_pll_clk_calc(dpi, vm->pixelclock, &ctx);
 		if (!ok)
 			return -EINVAL;
 
 		fck = ctx.pll_cinfo.clkout[ctx.clkout_idx];
 	} else {
-		ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
+		ok = dpi_dss_clk_calc(vm->pixelclock, &ctx);
 		if (!ok)
 			return -EINVAL;
 
@@ -540,7 +540,7 @@ static int dpi_check_timings(struct omap
 
 	pck = fck / lck_div / pck_div;
 
-	timings->pixelclock = pck;
+	vm->pixelclock = pck;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dsi.c	2017-02-12 16:03:20.000000000 -0500
@@ -289,7 +289,7 @@ struct dsi_clk_calc_ctx {
 	struct dss_pll_clock_info dsi_cinfo;
 	struct dispc_clock_info dispc_cinfo;
 
-	struct omap_video_timings dispc_vm;
+	struct videomode vm;
 	struct omap_dss_dsi_videomode_timings dsi_vm;
 };
 
@@ -383,7 +383,7 @@ struct dsi_data {
 	unsigned scp_clk_refcount;
 
 	struct dss_lcd_mgr_config mgr_config;
-	struct omap_video_timings timings;
+	struct videomode vm;
 	enum omap_dss_dsi_pixel_format pix_fmt;
 	enum omap_dss_dsi_mode mode;
 	struct omap_dss_dsi_videomode_timings vm_timings;
@@ -3321,12 +3321,12 @@ static void dsi_config_vp_num_line_buffe
 
 	if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) {
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
-		struct omap_video_timings *timings = &dsi->timings;
+		struct videomode *vm = &dsi->vm;
 		/*
 		 * Don't use line buffers if width is greater than the video
 		 * port's line buffer size
 		 */
-		if (dsi->line_buffer_size <= timings->x_res * bpp / 8)
+		if (dsi->line_buffer_size <= vm->hactive * bpp / 8)
 			num_line_buffers = 0;
 		else
 			num_line_buffers = 2;
@@ -3453,7 +3453,7 @@ static void dsi_config_cmd_mode_interlea
 	int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
 	int tclk_trail, ths_exit, exiths_clk;
 	bool ddr_alwon;
-	struct omap_video_timings *timings = &dsi->timings;
+	struct videomode *vm = &dsi->vm;
 	int bpp = dsi_get_pixel_size(dsi->pix_fmt);
 	int ndl = dsi->num_lanes_used - 1;
 	int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1;
@@ -3494,7 +3494,7 @@ static void dsi_config_cmd_mode_interlea
 
 	exiths_clk = ths_exit + tclk_trail;
 
-	width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+	width_bytes = DIV_ROUND_UP(vm->hactive * bpp, 8);
 	bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
 
 	if (!hsa_blanking_mode) {
@@ -3705,7 +3705,7 @@ static void dsi_proto_timings(struct pla
 		int vbp = dsi->vm_timings.vbp;
 		int window_sync = dsi->vm_timings.window_sync;
 		bool hsync_end;
-		struct omap_video_timings *timings = &dsi->timings;
+		struct videomode *vm = &dsi->vm;
 		int bpp = dsi_get_pixel_size(dsi->pix_fmt);
 		int tl, t_he, width_bytes;
 
@@ -3713,7 +3713,7 @@ static void dsi_proto_timings(struct pla
 		t_he = hsync_end ?
 			((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0;
 
-		width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
+		width_bytes = DIV_ROUND_UP(vm->hactive * bpp, 8);
 
 		/* TL = t_HS + HSA + t_HE + HFP + ceil((WC + 6) / NDL) + HBP */
 		tl = DIV_ROUND_UP(4, ndl) + (hsync_end ? hsa : 0) + t_he + hfp +
@@ -3722,7 +3722,7 @@ static void dsi_proto_timings(struct pla
 		DSSDBG("HBP: %d, HFP: %d, HSA: %d, TL: %d TXBYTECLKHS\n", hbp,
 			hfp, hsync_end ? hsa : 0, tl);
 		DSSDBG("VBP: %d, VFP: %d, VSA: %d, VACT: %d lines\n", vbp, vfp,
-			vsa, timings->y_res);
+			vsa, vm->vactive);
 
 		r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
 		r = FLD_MOD(r, hbp, 11, 0);	/* HBP */
@@ -3738,7 +3738,7 @@ static void dsi_proto_timings(struct pla
 		dsi_write_reg(dsidev, DSI_VM_TIMING2, r);
 
 		r = dsi_read_reg(dsidev, DSI_VM_TIMING3);
-		r = FLD_MOD(r, timings->y_res, 14, 0);	/* VACT */
+		r = FLD_MOD(r, vm->vactive, 14, 0);	/* VACT */
 		r = FLD_MOD(r, tl, 31, 16);		/* TL */
 		dsi_write_reg(dsidev, DSI_VM_TIMING3, r);
 	}
@@ -3856,7 +3856,7 @@ static int dsi_enable_video_output(struc
 		/* MODE, 1 = video mode */
 		REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
 
-		word_count = DIV_ROUND_UP(dsi->timings.x_res * bpp, 8);
+		word_count = DIV_ROUND_UP(dsi->vm.hactive * bpp, 8);
 
 		dsi_vc_write_long_header(dsidev, channel, data_type,
 				word_count, 0);
@@ -3918,8 +3918,8 @@ static void dsi_update_screen_dispc(stru
 	int r;
 	const unsigned channel = dsi->update_channel;
 	const unsigned line_buf_size = dsi->line_buffer_size;
-	u16 w = dsi->timings.x_res;
-	u16 h = dsi->timings.y_res;
+	u16 w = dsi->vm.hactive;
+	u16 h = dsi->vm.vactive;
 
 	DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
 
@@ -3969,7 +3969,7 @@ static void dsi_update_screen_dispc(stru
 		msecs_to_jiffies(250));
 	BUG_ON(r == 0);
 
-	dss_mgr_set_timings(dispc_channel, &dsi->timings);
+	dss_mgr_set_timings(dispc_channel, &dsi->vm);
 
 	dss_mgr_start_update(dispc_channel);
 
@@ -4056,8 +4056,8 @@ static int dsi_update(struct omap_dss_de
 	dsi->framedone_callback = callback;
 	dsi->framedone_data = data;
 
-	dw = dsi->timings.x_res;
-	dh = dsi->timings.y_res;
+	dw = dsi->vm.hactive;
+	dh = dsi->vm.vactive;
 
 #ifdef DSI_PERF_MEASURE
 	dsi->update_bytes = dw * dh *
@@ -4120,16 +4120,21 @@ static int dsi_display_init_dispc(struct
 
 	/*
 	 * override interlace, logic level and edge related parameters in
-	 * omap_video_timings with default values
+	 * videomode with default values
 	 */
-	dsi->timings.interlace = false;
-	dsi->timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	dsi->timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	dsi->timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	dsi->timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	dsi->timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
+	dsi->vm.flags &= ~DISPLAY_FLAGS_INTERLACED;
+	dsi->vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW;
+	dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
+	dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
+	dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+	dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+	dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+	dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+	dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+	dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+	dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
 
-	dss_mgr_set_timings(channel, &dsi->timings);
+	dss_mgr_set_timings(channel, &dsi->vm);
 
 	r = dsi_configure_dispc_clocks(dsidev);
 	if (r)
@@ -4331,7 +4336,7 @@ static void print_dsi_vm(const char *str
 
 	wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
 	pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
-	bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
+	bl = t->hss + t->hsa + t->hse + t->hbp + t->hfront_porch;
 	tot = bl + pps;
 
 #define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
@@ -4340,14 +4345,14 @@ static void print_dsi_vm(const char *str
 			"%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
 			str,
 			byteclk,
-			t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
+			t->hss, t->hsa, t->hse, t->hbp, pps, t->hfront_porch,
 			bl, pps, tot,
 			TO_DSI_T(t->hss),
 			TO_DSI_T(t->hsa),
 			TO_DSI_T(t->hse),
 			TO_DSI_T(t->hbp),
 			TO_DSI_T(pps),
-			TO_DSI_T(t->hfp),
+			TO_DSI_T(t->hfront_porch),
 
 			TO_DSI_T(bl),
 			TO_DSI_T(pps),
@@ -4356,13 +4361,13 @@ static void print_dsi_vm(const char *str
 #undef TO_DSI_T
 }
 
-static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
+static void print_dispc_vm(const char *str, const struct videomode *vm)
 {
-	unsigned long pck = t->pixelclock;
+	unsigned long pck = vm->pixelclock;
 	int hact, bl, tot;
 
-	hact = t->x_res;
-	bl = t->hsw + t->hbp + t->hfp;
+	hact = vm->hactive;
+	bl = vm->hsync_len + vm->hbp + vm->hfront_porch;
 	tot = hact + bl;
 
 #define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
@@ -4371,12 +4376,12 @@ static void print_dispc_vm(const char *s
 			"%u/%u/%u/%u = %u + %u = %u\n",
 			str,
 			pck,
-			t->hsw, t->hbp, hact, t->hfp,
+			vm->hsync_len, vm->hbp, hact, vm->hfront_porch,
 			bl, hact, tot,
-			TO_DISPC_T(t->hsw),
-			TO_DISPC_T(t->hbp),
+			TO_DISPC_T(vm->hsync_len),
+			TO_DISPC_T(vm->hbp),
 			TO_DISPC_T(hact),
-			TO_DISPC_T(t->hfp),
+			TO_DISPC_T(vm->hfront_porch),
 			TO_DISPC_T(bl),
 			TO_DISPC_T(hact),
 			TO_DISPC_T(tot));
@@ -4387,7 +4392,7 @@ static void print_dispc_vm(const char *s
 static void print_dsi_dispc_vm(const char *str,
 		const struct omap_dss_dsi_videomode_timings *t)
 {
-	struct omap_video_timings vm = { 0 };
+	struct videomode vm = { 0 };
 	unsigned long byteclk = t->hsclk / 4;
 	unsigned long pck;
 	u64 dsi_tput;
@@ -4396,13 +4401,13 @@ static void print_dsi_dispc_vm(const cha
 	dsi_tput = (u64)byteclk * t->ndl * 8;
 	pck = (u32)div64_u64(dsi_tput, t->bitspp);
 	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
-	dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
+	dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfront_porch;
 
 	vm.pixelclock = pck;
-	vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
+	vm.hsync_len = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
 	vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
-	vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
-	vm.x_res = t->hact;
+	vm.hfront_porch = div64_u64((u64)t->hfront_porch * pck, byteclk);
+	vm.hactive = t->hact;
 
 	print_dispc_vm(str, &vm);
 }
@@ -4412,19 +4417,19 @@ static bool dsi_cm_calc_dispc_cb(int lck
 		unsigned long pck, void *data)
 {
 	struct dsi_clk_calc_ctx *ctx = data;
-	struct omap_video_timings *t = &ctx->dispc_vm;
+	struct videomode *vm = &ctx->vm;
 
 	ctx->dispc_cinfo.lck_div = lckd;
 	ctx->dispc_cinfo.pck_div = pckd;
 	ctx->dispc_cinfo.lck = lck;
 	ctx->dispc_cinfo.pck = pck;
 
-	*t = *ctx->config->timings;
-	t->pixelclock = pck;
-	t->x_res = ctx->config->timings->x_res;
-	t->y_res = ctx->config->timings->y_res;
-	t->hsw = t->hfp = t->hbp = t->vsw = 1;
-	t->vfp = t->vbp = 0;
+	*vm = *ctx->config->vm;
+	vm->pixelclock = pck;
+	vm->hactive = ctx->config->vm->hactive;
+	vm->vactive = ctx->config->vm->vactive;
+	vm->hsync_len = vm->hfront_porch = vm->hback_porch = vm->vsync_len = 1;
+	vm->vfront_porch = vm->vback_porch = 0;
 
 	return true;
 }
@@ -4475,7 +4480,7 @@ static bool dsi_cm_calc(struct dsi_data
 	 * especially as we go to LP between each pixel packet due to HW
 	 * "feature". So let's just estimate very roughly and multiply by 1.5.
 	 */
-	pck = cfg->timings->pixelclock;
+	pck = cfg->vm->pixelclock;
 	pck = pck * 3 / 2;
 	txbyteclk = pck * bitspp / 8 / ndl;
 
@@ -4510,14 +4515,14 @@ static bool dsi_vm_calc_blanking(struct
 	int dispc_htot, dispc_hbl; /* pixels */
 	int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
 	int hfp, hsa, hbp;
-	const struct omap_video_timings *req_vm;
-	struct omap_video_timings *dispc_vm;
+	const struct videomode *req_vm;
+	struct videomode *dispc_vm;
 	struct omap_dss_dsi_videomode_timings *dsi_vm;
 	u64 dsi_tput, dispc_tput;
 
 	dsi_tput = (u64)byteclk * ndl * 8;
 
-	req_vm = cfg->timings;
+	req_vm = cfg->vm;
 	req_pck_min = ctx->req_pck_min;
 	req_pck_max = ctx->req_pck_max;
 	req_pck_nom = ctx->req_pck_nom;
@@ -4525,9 +4530,10 @@ static bool dsi_vm_calc_blanking(struct
 	dispc_pck = ctx->dispc_cinfo.pck;
 	dispc_tput = (u64)dispc_pck * bitspp;
 
-	xres = req_vm->x_res;
+	xres = req_vm->hactive;
 
-	panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
+	panel_hbl = req_vm->hfront_porch + req_vm->hback_porch +
+		    req_vm->hsync_len;
 	panel_htot = xres + panel_hbl;
 
 	dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
@@ -4557,7 +4563,7 @@ static bool dsi_vm_calc_blanking(struct
 	hss = DIV_ROUND_UP(4, ndl);
 
 	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
-		if (ndl == 3 && req_vm->hsw == 0)
+		if (ndl == 3 && req_vm->hsync_len == 0)
 			hse = 1;
 		else
 			hse = DIV_ROUND_UP(4, ndl);
@@ -4596,14 +4602,14 @@ static bool dsi_vm_calc_blanking(struct
 
 	if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
 		hsa = 0;
-	} else if (ndl == 3 && req_vm->hsw == 0) {
+	} else if (ndl == 3 && req_vm->hsync_len == 0) {
 		hsa = 0;
 	} else {
-		hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
+		hsa = div64_u64((u64)req_vm->hsync_len * byteclk, req_pck_nom);
 		hsa = max(hsa - hse, 1);
 	}
 
-	hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
+	hbp = div64_u64((u64)req_vm->hback_porch * byteclk, req_pck_nom);
 	hbp = max(hbp, 1);
 
 	hfp = dsi_hbl - (hss + hsa + hse + hbp);
@@ -4633,10 +4639,10 @@ static bool dsi_vm_calc_blanking(struct
 	dsi_vm->hact = xres;
 	dsi_vm->hfp = hfp;
 
-	dsi_vm->vsa = req_vm->vsw;
-	dsi_vm->vbp = req_vm->vbp;
-	dsi_vm->vact = req_vm->y_res;
-	dsi_vm->vfp = req_vm->vfp;
+	dsi_vm->vsa = req_vm->vsync_len;
+	dsi_vm->vbp = req_vm->vback_porch;
+	dsi_vm->vact = req_vm->vactive;
+	dsi_vm->vfp = req_vm->vfront_porch;
 
 	dsi_vm->trans_mode = cfg->trans_mode;
 
@@ -4650,19 +4656,19 @@ static bool dsi_vm_calc_blanking(struct
 
 	/* setup DISPC videomode */
 
-	dispc_vm = &ctx->dispc_vm;
+	dispc_vm = &ctx->vm;
 	*dispc_vm = *req_vm;
 	dispc_vm->pixelclock = dispc_pck;
 
 	if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
-		hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
+		hsa = div64_u64((u64)req_vm->hsync_len * dispc_pck,
 				req_pck_nom);
 		hsa = max(hsa, 1);
 	} else {
 		hsa = 1;
 	}
 
-	hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
+	hbp = div64_u64((u64)req_vm->hback_porch * dispc_pck, req_pck_nom);
 	hbp = max(hbp, 1);
 
 	hfp = dispc_hbl - hsa - hbp;
@@ -4685,9 +4691,9 @@ static bool dsi_vm_calc_blanking(struct
 	if (hfp < 1)
 		return false;
 
-	dispc_vm->hfp = hfp;
-	dispc_vm->hsw = hsa;
-	dispc_vm->hbp = hbp;
+	dispc_vm->hfront_porch = hfp;
+	dispc_vm->hsync_len = hsa;
+	dispc_vm->hback_porch = hbp;
 
 	return true;
 }
@@ -4707,9 +4713,9 @@ static bool dsi_vm_calc_dispc_cb(int lck
 		return false;
 
 #ifdef PRINT_VERBOSE_VM_TIMINGS
-	print_dispc_vm("dispc", &ctx->dispc_vm);
+	print_dispc_vm("dispc", &ctx->vm);
 	print_dsi_vm("dsi  ", &ctx->dsi_vm);
-	print_dispc_vm("req  ", ctx->config->timings);
+	print_dispc_vm("req  ", ctx->config->vm);
 	print_dsi_dispc_vm("act  ", &ctx->dsi_vm);
 #endif
 
@@ -4758,7 +4764,7 @@ static bool dsi_vm_calc(struct dsi_data
 		const struct omap_dss_dsi_config *cfg,
 		struct dsi_clk_calc_ctx *ctx)
 {
-	const struct omap_video_timings *t = cfg->timings;
+	const struct videomode *vm = cfg->vm;
 	unsigned long clkin;
 	unsigned long pll_min;
 	unsigned long pll_max;
@@ -4774,9 +4780,9 @@ static bool dsi_vm_calc(struct dsi_data
 	ctx->config = cfg;
 
 	/* these limits should come from the panel driver */
-	ctx->req_pck_min = t->pixelclock - 1000;
-	ctx->req_pck_nom = t->pixelclock;
-	ctx->req_pck_max = t->pixelclock + 1000;
+	ctx->req_pck_min = vm->pixelclock - 1000;
+	ctx->req_pck_nom = vm->pixelclock;
+	ctx->req_pck_max = vm->pixelclock + 1000;
 
 	byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
 	pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
@@ -4833,7 +4839,7 @@ static int dsi_set_config(struct omap_ds
 	dsi->user_dsi_cinfo = ctx.dsi_cinfo;
 	dsi->user_dispc_cinfo = ctx.dispc_cinfo;
 
-	dsi->timings = ctx.dispc_vm;
+	dsi->vm = ctx.vm;
 	dsi->vm_timings = ctx.dsi_vm;
 
 	mutex_unlock(&dsi->lock);
@@ -5342,7 +5348,7 @@ static int dsi_bind(struct device *dev,
 
 	dsi->phy_base = devm_ioremap(&dsidev->dev, res->start,
 		resource_size(res));
-	if (!dsi->proto_base) {
+	if (!dsi->phy_base) {
 		DSSERR("can't ioremap DSI PHY\n");
 		return -ENOMEM;
 	}
@@ -5362,7 +5368,7 @@ static int dsi_bind(struct device *dev,
 
 	dsi->pll_base = devm_ioremap(&dsidev->dev, res->start,
 		resource_size(res));
-	if (!dsi->proto_base) {
+	if (!dsi->pll_base) {
 		DSSERR("can't ioremap DSI PLL\n");
 		return -ENOMEM;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dss.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dss.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/dss.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/dss.h	2017-02-12 16:03:20.000000000 -0500
@@ -366,8 +366,7 @@ bool dispc_div_calc(unsigned long dispc,
 		unsigned long pck_min, unsigned long pck_max,
 		dispc_div_calc_func func, void *data);
 
-bool dispc_mgr_timings_ok(enum omap_channel channel,
-		const struct omap_video_timings *timings);
+bool dispc_mgr_timings_ok(enum omap_channel channel, const struct videomode *vm);
 int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
 		struct dispc_clock_info *cinfo);
 
@@ -390,7 +389,7 @@ void dispc_wb_enable(bool enable);
 bool dispc_wb_is_enabled(void);
 void dispc_wb_set_channel_in(enum dss_writeback_channel channel);
 int dispc_wb_setup(const struct omap_dss_writeback_info *wi,
-		bool mem_to_mem, const struct omap_video_timings *timings);
+		bool mem_to_mem, const struct videomode *vm);
 
 /* VENC */
 int venc_init_platform_driver(void) __init;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4.c	2017-02-12 16:03:20.000000000 -0500
@@ -155,7 +155,7 @@ static void hdmi_power_off_core(struct o
 static int hdmi_power_on_full(struct omap_dss_device *dssdev)
 {
 	int r;
-	struct omap_video_timings *p;
+	struct videomode *vm;
 	enum omap_channel channel = dssdev->dispc_channel;
 	struct hdmi_wp_data *wp = &hdmi.wp;
 	struct dss_pll_clock_info hdmi_cinfo = { 0 };
@@ -169,12 +169,13 @@ static int hdmi_power_on_full(struct oma
 	hdmi_wp_clear_irqenable(wp, 0xffffffff);
 	hdmi_wp_set_irqstatus(wp, 0xffffffff);
 
-	p = &hdmi.cfg.timings;
+	vm = &hdmi.cfg.vm;
 
-	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
+	DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive,
+	       vm->vactive);
 
-	pc = p->pixelclock;
-	if (p->double_pixel)
+	pc = vm->pixelclock;
+	if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
 		pc *= 2;
 
 	/* DSS_HDMI_TCLK is bitclk / 10 */
@@ -209,7 +210,7 @@ static int hdmi_power_on_full(struct oma
 	hdmi4_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
 
 	/* tv size */
-	dss_mgr_set_timings(channel, p);
+	dss_mgr_set_timings(channel, vm);
 
 	r = dss_mgr_enable(channel);
 	if (r)
@@ -255,30 +256,30 @@ static void hdmi_power_off_full(struct o
 }
 
 static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
-					struct omap_video_timings *timings)
+				     struct videomode *vm)
 {
-	if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings))
+	if (!dispc_mgr_timings_ok(dssdev->dispc_channel, vm))
 		return -EINVAL;
 
 	return 0;
 }
 
 static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				    struct videomode *vm)
 {
 	mutex_lock(&hdmi.lock);
 
-	hdmi.cfg.timings = *timings;
+	hdmi.cfg.vm = *vm;
 
-	dispc_set_tv_pclk(timings->pixelclock);
+	dispc_set_tv_pclk(vm->pixelclock);
 
 	mutex_unlock(&hdmi.lock);
 }
 
 static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				     struct videomode *vm)
 {
-	*timings = hdmi.cfg.timings;
+	*vm = hdmi.cfg.vm;
 }
 
 static void hdmi_dump_regs(struct seq_file *s)
@@ -352,7 +353,7 @@ static int hdmi_display_enable(struct om
 
 	if (hdmi.audio_configured) {
 		r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
-				       hdmi.cfg.timings.pixelclock);
+				       hdmi.cfg.vm.pixelclock);
 		if (r) {
 			DSSERR("Error restoring audio configuration: %d", r);
 			hdmi.audio_abort_cb(&hdmi.pdev->dev);
@@ -643,7 +644,7 @@ static int hdmi_audio_config(struct devi
 	}
 
 	ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio,
-				 hd->cfg.timings.pixelclock);
+				 hd->cfg.vm.pixelclock);
 	if (!ret) {
 		hd->audio_configured = true;
 		hd->audio_config = *dss_audio;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -310,7 +310,7 @@ void hdmi4_configure(struct hdmi_core_da
 	struct hdmi_wp_data *wp, struct hdmi_config *cfg)
 {
 	/* HDMI */
-	struct omap_video_timings video_timing;
+	struct videomode vm;
 	struct hdmi_video_format video_format;
 	/* HDMI core */
 	struct hdmi_core_video_config v_core_cfg;
@@ -318,16 +318,16 @@ void hdmi4_configure(struct hdmi_core_da
 
 	hdmi_core_init(&v_core_cfg);
 
-	hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
+	hdmi_wp_init_vid_fmt_timings(&video_format, &vm, cfg);
 
-	hdmi_wp_video_config_timing(wp, &video_timing);
+	hdmi_wp_video_config_timing(wp, &vm);
 
 	/* video config */
 	video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
 
 	hdmi_wp_video_config_format(wp, &video_format);
 
-	hdmi_wp_video_config_interface(wp, &video_timing);
+	hdmi_wp_video_config_interface(wp, &vm);
 
 	/*
 	 * configure core video part
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5.c	2017-02-12 16:03:20.000000000 -0500
@@ -172,7 +172,7 @@ static void hdmi_power_off_core(struct o
 static int hdmi_power_on_full(struct omap_dss_device *dssdev)
 {
 	int r;
-	struct omap_video_timings *p;
+	struct videomode *vm;
 	enum omap_channel channel = dssdev->dispc_channel;
 	struct dss_pll_clock_info hdmi_cinfo = { 0 };
 	unsigned pc;
@@ -181,12 +181,13 @@ static int hdmi_power_on_full(struct oma
 	if (r)
 		return r;
 
-	p = &hdmi.cfg.timings;
+	vm = &hdmi.cfg.vm;
 
-	DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
+	DSSDBG("hdmi_power_on hactive= %d vactive = %d\n", vm->hactive,
+	       vm->vactive);
 
-	pc = p->pixelclock;
-	if (p->double_pixel)
+	pc = vm->pixelclock;
+	if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
 		pc *= 2;
 
 	/* DSS_HDMI_TCLK is bitclk / 10 */
@@ -226,7 +227,7 @@ static int hdmi_power_on_full(struct oma
 	hdmi5_configure(&hdmi.core, &hdmi.wp, &hdmi.cfg);
 
 	/* tv size */
-	dss_mgr_set_timings(channel, p);
+	dss_mgr_set_timings(channel, vm);
 
 	r = dss_mgr_enable(channel);
 	if (r)
@@ -272,30 +273,30 @@ static void hdmi_power_off_full(struct o
 }
 
 static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
-					struct omap_video_timings *timings)
+				     struct videomode *vm)
 {
-	if (!dispc_mgr_timings_ok(dssdev->dispc_channel, timings))
+	if (!dispc_mgr_timings_ok(dssdev->dispc_channel, vm))
 		return -EINVAL;
 
 	return 0;
 }
 
 static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				    struct videomode *vm)
 {
 	mutex_lock(&hdmi.lock);
 
-	hdmi.cfg.timings = *timings;
+	hdmi.cfg.vm = *vm;
 
-	dispc_set_tv_pclk(timings->pixelclock);
+	dispc_set_tv_pclk(vm->pixelclock);
 
 	mutex_unlock(&hdmi.lock);
 }
 
 static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+				     struct videomode *vm)
 {
-	*timings = hdmi.cfg.timings;
+	*vm = hdmi.cfg.vm;
 }
 
 static void hdmi_dump_regs(struct seq_file *s)
@@ -378,7 +379,7 @@ static int hdmi_display_enable(struct om
 
 	if (hdmi.audio_configured) {
 		r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, &hdmi.audio_config,
-				       hdmi.cfg.timings.pixelclock);
+				       hdmi.cfg.vm.pixelclock);
 		if (r) {
 			DSSERR("Error restoring audio configuration: %d", r);
 			hdmi.audio_abort_cb(&hdmi.pdev->dev);
@@ -669,7 +670,7 @@ static int hdmi_audio_config(struct devi
 	}
 
 	ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio,
-				 hd->cfg.timings.pixelclock);
+				 hd->cfg.vm.pixelclock);
 
 	if (!ret) {
 		hd->audio_configured = true;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi5_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -292,35 +292,35 @@ static void hdmi_core_init(struct hdmi_c
 {
 	DSSDBG("hdmi_core_init\n");
 
-	video_cfg->v_fc_config.timings = cfg->timings;
+	video_cfg->v_fc_config.vm = cfg->vm;
 
 	/* video core */
 	video_cfg->data_enable_pol = 1; /* It is always 1*/
-	video_cfg->hblank = cfg->timings.hfp +
-				cfg->timings.hbp + cfg->timings.hsw;
+	video_cfg->hblank = cfg->vm.hfront_porch +
+			    cfg->vm.hback_porch + cfg->vm.hsync_len;
 	video_cfg->vblank_osc = 0;
-	video_cfg->vblank = cfg->timings.vsw +
-				cfg->timings.vfp + cfg->timings.vbp;
+	video_cfg->vblank = cfg->vm.vsync_len + cfg->vm.vfront_porch +
+			    cfg->vm.vback_porch;
 	video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode;
 
-	if (cfg->timings.interlace) {
+	if (cfg->vm.flags & DISPLAY_FLAGS_INTERLACED) {
 		/* set vblank_osc if vblank is fractional */
 		if (video_cfg->vblank % 2 != 0)
 			video_cfg->vblank_osc = 1;
 
-		video_cfg->v_fc_config.timings.y_res /= 2;
+		video_cfg->v_fc_config.vm.vactive /= 2;
 		video_cfg->vblank /= 2;
-		video_cfg->v_fc_config.timings.vfp /= 2;
-		video_cfg->v_fc_config.timings.vsw /= 2;
-		video_cfg->v_fc_config.timings.vbp /= 2;
+		video_cfg->v_fc_config.vm.vfront_porch /= 2;
+		video_cfg->v_fc_config.vm.vsync_len /= 2;
+		video_cfg->v_fc_config.vm.vback_porch /= 2;
 	}
 
-	if (cfg->timings.double_pixel) {
-		video_cfg->v_fc_config.timings.x_res *= 2;
+	if (cfg->vm.flags & DISPLAY_FLAGS_DOUBLECLK) {
+		video_cfg->v_fc_config.vm.hactive *= 2;
 		video_cfg->hblank *= 2;
-		video_cfg->v_fc_config.timings.hfp *= 2;
-		video_cfg->v_fc_config.timings.hsw *= 2;
-		video_cfg->v_fc_config.timings.hbp *= 2;
+		video_cfg->v_fc_config.vm.hfront_porch *= 2;
+		video_cfg->v_fc_config.vm.hsync_len *= 2;
+		video_cfg->v_fc_config.vm.hback_porch *= 2;
 	}
 }
 
@@ -329,13 +329,12 @@ static void hdmi_core_video_config(struc
 			struct hdmi_core_vid_config *cfg)
 {
 	void __iomem *base = core->base;
+	struct videomode *vm = &cfg->v_fc_config.vm;
 	unsigned char r = 0;
 	bool vsync_pol, hsync_pol;
 
-	vsync_pol =
-		cfg->v_fc_config.timings.vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
-	hsync_pol =
-		cfg->v_fc_config.timings.hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
+	vsync_pol = !!(vm->flags & DISPLAY_FLAGS_VSYNC_HIGH);
+	hsync_pol = !!(vm->flags & DISPLAY_FLAGS_HSYNC_HIGH);
 
 	/* Set hsync, vsync and data-enable polarity  */
 	r = hdmi_read_reg(base, HDMI_CORE_FC_INVIDCONF);
@@ -343,20 +342,16 @@ static void hdmi_core_video_config(struc
 	r = FLD_MOD(r, hsync_pol, 5, 5);
 	r = FLD_MOD(r, cfg->data_enable_pol, 4, 4);
 	r = FLD_MOD(r, cfg->vblank_osc, 1, 1);
-	r = FLD_MOD(r, cfg->v_fc_config.timings.interlace, 0, 0);
+	r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 0, 0);
 	hdmi_write_reg(base, HDMI_CORE_FC_INVIDCONF, r);
 
 	/* set x resolution */
-	REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1,
-			cfg->v_fc_config.timings.x_res >> 8, 4, 0);
-	REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0,
-			cfg->v_fc_config.timings.x_res & 0xFF, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV1, vm->hactive >> 8, 4, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_INHACTIV0, vm->hactive & 0xFF, 7, 0);
 
 	/* set y resolution */
-	REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1,
-			cfg->v_fc_config.timings.y_res >> 8, 4, 0);
-	REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0,
-			cfg->v_fc_config.timings.y_res & 0xFF, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV1, vm->vactive >> 8, 4, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_INVACTIV0, vm->vactive & 0xFF, 7, 0);
 
 	/* set horizontal blanking pixels */
 	REG_FLD_MOD(base, HDMI_CORE_FC_INHBLANK1, cfg->hblank >> 8, 4, 0);
@@ -366,30 +361,28 @@ static void hdmi_core_video_config(struc
 	REG_FLD_MOD(base, HDMI_CORE_FC_INVBLANK, cfg->vblank, 7, 0);
 
 	/* set horizontal sync offset */
-	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1,
-			cfg->v_fc_config.timings.hfp >> 8, 4, 0);
-	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0,
-			cfg->v_fc_config.timings.hfp & 0xFF, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY1, vm->hfront_porch >> 8,
+		    4, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINDELAY0, vm->hfront_porch & 0xFF,
+		    7, 0);
 
 	/* set vertical sync offset */
-	REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY,
-			cfg->v_fc_config.timings.vfp, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINDELAY, vm->vfront_porch, 7, 0);
 
 	/* set horizontal sync pulse width */
-	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1,
-			(cfg->v_fc_config.timings.hsw >> 8), 1, 0);
-	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0,
-			cfg->v_fc_config.timings.hsw & 0xFF, 7, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH1, (vm->hsync_len >> 8),
+		    1, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_HSYNCINWIDTH0, vm->hsync_len & 0xFF,
+		    7, 0);
 
 	/*  set vertical sync pulse width */
-	REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH,
-			cfg->v_fc_config.timings.vsw, 5, 0);
+	REG_FLD_MOD(base, HDMI_CORE_FC_VSYNCINWIDTH, vm->vsync_len, 5, 0);
 
 	/* select DVI mode */
 	REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF,
-			cfg->v_fc_config.hdmi_dvi_mode, 3, 3);
+		    cfg->v_fc_config.hdmi_dvi_mode, 3, 3);
 
-	if (cfg->v_fc_config.timings.double_pixel)
+	if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
 		REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 2, 7, 4);
 	else
 		REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, 1, 7, 4);
@@ -616,7 +609,7 @@ int hdmi5_core_handle_irqs(struct hdmi_c
 void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
 		struct hdmi_config *cfg)
 {
-	struct omap_video_timings video_timing;
+	struct videomode vm;
 	struct hdmi_video_format video_format;
 	struct hdmi_core_vid_config v_core_cfg;
 
@@ -624,16 +617,16 @@ void hdmi5_configure(struct hdmi_core_da
 
 	hdmi_core_init(&v_core_cfg, cfg);
 
-	hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
+	hdmi_wp_init_vid_fmt_timings(&video_format, &vm, cfg);
 
-	hdmi_wp_video_config_timing(wp, &video_timing);
+	hdmi_wp_video_config_timing(wp, &vm);
 
 	/* video config */
 	video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
 
 	hdmi_wp_video_config_format(wp, &video_format);
 
-	hdmi_wp_video_config_interface(wp, &video_timing);
+	hdmi_wp_video_config_interface(wp, &vm);
 
 	/* support limited range with 24 bit color depth for now */
 	hdmi_core_configure_range(core);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi.h	2017-02-12 16:03:20.000000000 -0500
@@ -181,7 +181,7 @@ struct hdmi_video_format {
 };
 
 struct hdmi_config {
-	struct omap_video_timings timings;
+	struct videomode vm;
 	struct hdmi_avi_infoframe infoframe;
 	enum hdmi_core_hdmi_dvi hdmi_dvi_mode;
 };
@@ -298,11 +298,11 @@ int hdmi_wp_set_pll_pwr(struct hdmi_wp_d
 void hdmi_wp_video_config_format(struct hdmi_wp_data *wp,
 		struct hdmi_video_format *video_fmt);
 void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings);
+		struct videomode *vm);
 void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings);
+		struct videomode *vm);
 void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
-		struct omap_video_timings *timings, struct hdmi_config *param);
+		struct videomode *vm, struct hdmi_config *param);
 int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
 phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c	2017-02-12 16:03:20.000000000 -0500
@@ -144,87 +144,84 @@ void hdmi_wp_video_config_format(struct
 }
 
 void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings)
+				    struct videomode *vm)
 {
 	u32 r;
 	bool vsync_pol, hsync_pol;
 	DSSDBG("Enter hdmi_wp_video_config_interface\n");
 
-	vsync_pol = timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
-	hsync_pol = timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH;
+	vsync_pol = !!(vm->flags & DISPLAY_FLAGS_VSYNC_HIGH);
+	hsync_pol = !!(vm->flags & DISPLAY_FLAGS_HSYNC_HIGH);
 
 	r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG);
 	r = FLD_MOD(r, vsync_pol, 7, 7);
 	r = FLD_MOD(r, hsync_pol, 6, 6);
-	r = FLD_MOD(r, timings->interlace, 3, 3);
+	r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 3, 3);
 	r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */
 	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r);
 }
 
 void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
-		struct omap_video_timings *timings)
+				 struct videomode *vm)
 {
 	u32 timing_h = 0;
 	u32 timing_v = 0;
-	unsigned hsw_offset = 1;
+	unsigned hsync_len_offset = 1;
 
 	DSSDBG("Enter hdmi_wp_video_config_timing\n");
 
 	/*
 	 * On OMAP4 and OMAP5 ES1 the HSW field is programmed as is. On OMAP5
-	 * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsw-1.
+	 * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsync_len-1.
 	 * However, we don't support OMAP5 ES1 at all, so we can just check for
 	 * OMAP4 here.
 	 */
 	if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 ||
 	    omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
 	    omapdss_get_version() == OMAPDSS_VER_OMAP4)
-		hsw_offset = 0;
+		hsync_len_offset = 0;
 
-	timing_h |= FLD_VAL(timings->hbp, 31, 20);
-	timing_h |= FLD_VAL(timings->hfp, 19, 8);
-	timing_h |= FLD_VAL(timings->hsw - hsw_offset, 7, 0);
+	timing_h |= FLD_VAL(vm->hback_porch, 31, 20);
+	timing_h |= FLD_VAL(vm->hfront_porch, 19, 8);
+	timing_h |= FLD_VAL(vm->hsync_len - hsync_len_offset, 7, 0);
 	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_H, timing_h);
 
-	timing_v |= FLD_VAL(timings->vbp, 31, 20);
-	timing_v |= FLD_VAL(timings->vfp, 19, 8);
-	timing_v |= FLD_VAL(timings->vsw, 7, 0);
+	timing_v |= FLD_VAL(vm->vback_porch, 31, 20);
+	timing_v |= FLD_VAL(vm->vfront_porch, 19, 8);
+	timing_v |= FLD_VAL(vm->vsync_len, 7, 0);
 	hdmi_write_reg(wp->base, HDMI_WP_VIDEO_TIMING_V, timing_v);
 }
 
 void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
-		struct omap_video_timings *timings, struct hdmi_config *param)
+		struct videomode *vm, struct hdmi_config *param)
 {
 	DSSDBG("Enter hdmi_wp_video_init_format\n");
 
 	video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444;
-	video_fmt->y_res = param->timings.y_res;
-	video_fmt->x_res = param->timings.x_res;
+	video_fmt->y_res = param->vm.vactive;
+	video_fmt->x_res = param->vm.hactive;
 
-	timings->hbp = param->timings.hbp;
-	timings->hfp = param->timings.hfp;
-	timings->hsw = param->timings.hsw;
-	timings->vbp = param->timings.vbp;
-	timings->vfp = param->timings.vfp;
-	timings->vsw = param->timings.vsw;
+	vm->hback_porch = param->vm.hback_porch;
+	vm->hfront_porch = param->vm.hfront_porch;
+	vm->hsync_len = param->vm.hsync_len;
+	vm->vback_porch = param->vm.vback_porch;
+	vm->vfront_porch = param->vm.vfront_porch;
+	vm->vsync_len = param->vm.vsync_len;
 
-	timings->vsync_level = param->timings.vsync_level;
-	timings->hsync_level = param->timings.hsync_level;
-	timings->interlace = param->timings.interlace;
-	timings->double_pixel = param->timings.double_pixel;
+	vm->flags = param->vm.flags;
 
-	if (param->timings.interlace) {
+	if (param->vm.flags & DISPLAY_FLAGS_INTERLACED) {
 		video_fmt->y_res /= 2;
-		timings->vbp /= 2;
-		timings->vfp /= 2;
-		timings->vsw /= 2;
+		vm->vback_porch /= 2;
+		vm->vfront_porch /= 2;
+		vm->vsync_len /= 2;
 	}
 
-	if (param->timings.double_pixel) {
+	if (param->vm.flags & DISPLAY_FLAGS_DOUBLECLK) {
 		video_fmt->x_res *= 2;
-		timings->hfp *= 2;
-		timings->hsw *= 2;
-		timings->hbp *= 2;
+		vm->hfront_porch *= 2;
+		vm->hsync_len *= 2;
+		vm->hback_porch *= 2;
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/omapdss.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/omapdss.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/omapdss.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/omapdss.h	2017-02-12 16:03:20.000000000 -0500
@@ -290,7 +290,7 @@ struct omap_dss_dsi_videomode_timings {
 struct omap_dss_dsi_config {
 	enum omap_dss_dsi_mode mode;
 	enum omap_dss_dsi_pixel_format pixel_format;
-	const struct omap_video_timings *timings;
+	const struct videomode *vm;
 
 	unsigned long hs_clk_min, hs_clk_max;
 	unsigned long lp_clk_min, lp_clk_max;
@@ -299,48 +299,12 @@ struct omap_dss_dsi_config {
 	enum omap_dss_dsi_trans_mode trans_mode;
 };
 
-struct omap_video_timings {
-	/* Unit: pixels */
-	u16 x_res;
-	/* Unit: pixels */
-	u16 y_res;
-	/* Unit: Hz */
-	u32 pixelclock;
-	/* Unit: pixel clocks */
-	u16 hsw;	/* Horizontal synchronization pulse width */
-	/* Unit: pixel clocks */
-	u16 hfp;	/* Horizontal front porch */
-	/* Unit: pixel clocks */
-	u16 hbp;	/* Horizontal back porch */
-	/* Unit: line clocks */
-	u16 vsw;	/* Vertical synchronization pulse width */
-	/* Unit: line clocks */
-	u16 vfp;	/* Vertical front porch */
-	/* Unit: line clocks */
-	u16 vbp;	/* Vertical back porch */
-
-	/* Vsync logic level */
-	enum omap_dss_signal_level vsync_level;
-	/* Hsync logic level */
-	enum omap_dss_signal_level hsync_level;
-	/* Interlaced or Progressive timings */
-	bool interlace;
-	/* Pixel clock edge to drive LCD data */
-	enum omap_dss_signal_edge data_pclk_edge;
-	/* Data enable logic level */
-	enum omap_dss_signal_level de_level;
-	/* Pixel clock edges to drive HSYNC and VSYNC signals */
-	enum omap_dss_signal_edge sync_pclk_edge;
-
-	bool double_pixel;
-};
-
-/* Hardcoded timings for tv modes. Venc only uses these to
+/* Hardcoded videomodes for tv. Venc only uses these to
  * identify the mode, and does not actually use the configs
  * itself. However, the configs should be something that
  * a normal monitor can also show */
-extern const struct omap_video_timings omap_dss_pal_timings;
-extern const struct omap_video_timings omap_dss_ntsc_timings;
+extern const struct videomode omap_dss_pal_vm;
+extern const struct videomode omap_dss_ntsc_vm;
 
 struct omap_dss_cpr_coefs {
 	s16 rr, rg, rb;
@@ -502,11 +466,11 @@ struct omapdss_dpi_ops {
 	void (*disable)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			     struct videomode *vm);
 	void (*set_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 	void (*get_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 
 	void (*set_data_lines)(struct omap_dss_device *dssdev, int data_lines);
 };
@@ -521,11 +485,11 @@ struct omapdss_sdi_ops {
 	void (*disable)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			     struct videomode *vm);
 	void (*set_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 	void (*get_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 
 	void (*set_datapairs)(struct omap_dss_device *dssdev, int datapairs);
 };
@@ -540,11 +504,11 @@ struct omapdss_dvi_ops {
 	void (*disable)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			     struct videomode *vm);
 	void (*set_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 	void (*get_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 };
 
 struct omapdss_atv_ops {
@@ -557,11 +521,11 @@ struct omapdss_atv_ops {
 	void (*disable)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			     struct videomode *vm);
 	void (*set_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 	void (*get_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 
 	void (*set_type)(struct omap_dss_device *dssdev,
 		enum omap_dss_venc_type type);
@@ -582,11 +546,11 @@ struct omapdss_hdmi_ops {
 	void (*disable)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			     struct videomode *vm);
 	void (*set_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 	void (*get_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 
 	int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
 	bool (*detect)(struct omap_dss_device *dssdev);
@@ -692,7 +656,7 @@ struct omap_dss_device {
 	} phy;
 
 	struct {
-		struct omap_video_timings timings;
+		struct videomode vm;
 
 		enum omap_dss_dsi_pixel_format dsi_pix_fmt;
 		enum omap_dss_dsi_mode dsi_mode;
@@ -785,11 +749,11 @@ struct omap_dss_driver {
 	int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
 
 	int (*check_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			     struct videomode *vm);
 	void (*set_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 	void (*get_timings)(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings);
+			    struct videomode *vm);
 
 	int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
 	u32 (*get_wss)(struct omap_dss_device *dssdev);
@@ -819,11 +783,6 @@ struct omap_dss_device *omap_dss_find_de
 		int (*match)(struct omap_dss_device *dssdev, void *data));
 const char *omapdss_get_default_display_name(void);
 
-void videomode_to_omap_video_timings(const struct videomode *vm,
-		struct omap_video_timings *ovt);
-void omap_video_timings_to_videomode(const struct omap_video_timings *ovt,
-		struct videomode *vm);
-
 int dss_feat_get_num_mgrs(void);
 int dss_feat_get_num_ovls(void);
 enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
@@ -852,7 +811,7 @@ void omapdss_default_get_resolution(stru
 		u16 *xres, u16 *yres);
 int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
 void omapdss_default_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings);
+				 struct videomode *vm);
 
 typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
 int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
@@ -906,7 +865,7 @@ void dispc_mgr_go(enum omap_channel chan
 void dispc_mgr_set_lcd_config(enum omap_channel channel,
 		const struct dss_lcd_mgr_config *config);
 void dispc_mgr_set_timings(enum omap_channel channel,
-		const struct omap_video_timings *timings);
+		const struct videomode *vm);
 void dispc_mgr_setup(enum omap_channel channel,
 		const struct omap_overlay_manager_info *info);
 u32 dispc_mgr_gamma_size(enum omap_channel channel);
@@ -919,8 +878,7 @@ bool dispc_ovl_enabled(enum omap_plane p
 void dispc_ovl_set_channel_out(enum omap_plane plane,
 		enum omap_channel channel);
 int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi,
-		bool replication, const struct omap_video_timings *mgr_timings,
-		bool mem_to_mem);
+		bool replication, const struct videomode *vm, bool mem_to_mem);
 
 enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel);
 
@@ -934,7 +892,7 @@ struct dss_mgr_ops {
 	int (*enable)(enum omap_channel channel);
 	void (*disable)(enum omap_channel channel);
 	void (*set_timings)(enum omap_channel channel,
-			const struct omap_video_timings *timings);
+			const struct videomode *vm);
 	void (*set_lcd_config)(enum omap_channel channel,
 			const struct dss_lcd_mgr_config *config);
 	int (*register_framedone_handler)(enum omap_channel channel,
@@ -951,7 +909,7 @@ int dss_mgr_connect(enum omap_channel ch
 void dss_mgr_disconnect(enum omap_channel channel,
 		struct omap_dss_device *dst);
 void dss_mgr_set_timings(enum omap_channel channel,
-		const struct omap_video_timings *timings);
+		const struct videomode *vm);
 void dss_mgr_set_lcd_config(enum omap_channel channel,
 		const struct dss_lcd_mgr_config *config);
 int dss_mgr_enable(enum omap_channel channel);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/output.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/output.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/output.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/output.c	2017-02-12 16:03:20.000000000 -0500
@@ -201,10 +201,9 @@ void dss_mgr_disconnect(enum omap_channe
 }
 EXPORT_SYMBOL(dss_mgr_disconnect);
 
-void dss_mgr_set_timings(enum omap_channel channel,
-		const struct omap_video_timings *timings)
+void dss_mgr_set_timings(enum omap_channel channel, const struct videomode *vm)
 {
-	dss_mgr_ops->set_timings(channel, timings);
+	dss_mgr_ops->set_timings(channel, vm);
 }
 EXPORT_SYMBOL(dss_mgr_set_timings);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/rfbi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/rfbi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/rfbi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/rfbi.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,7 +113,7 @@ static struct {
 
 	struct semaphore bus_lock;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 	int pixel_size;
 	int data_lines;
 	struct rfbi_timings intf_timings;
@@ -308,15 +308,15 @@ static int rfbi_transfer_area(struct oma
 	u32 l;
 	int r;
 	struct omap_overlay_manager *mgr = rfbi.output.manager;
-	u16 width = rfbi.timings.x_res;
-	u16 height = rfbi.timings.y_res;
+	u16 width = rfbi.vm.hactive;
+	u16 height = rfbi.vm.vactive;
 
 	/*BUG_ON(callback == 0);*/
 	BUG_ON(rfbi.framedone_callback != NULL);
 
 	DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
 
-	dss_mgr_set_timings(mgr, &rfbi.timings);
+	dss_mgr_set_timings(mgr, &rfbi.vm);
 
 	r = dss_mgr_enable(mgr);
 	if (r)
@@ -777,8 +777,8 @@ static int rfbi_update(struct omap_dss_d
 
 static void rfbi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
 {
-	rfbi.timings.x_res = w;
-	rfbi.timings.y_res = h;
+	rfbi.vm.hactive = w;
+	rfbi.vm.vactive = h;
 }
 
 static void rfbi_set_pixel_size(struct omap_dss_device *dssdev, int pixel_size)
@@ -854,25 +854,30 @@ static void rfbi_config_lcd_manager(stru
 	dss_mgr_set_lcd_config(mgr, &mgr_config);
 
 	/*
-	 * Set rfbi.timings with default values, the x_res and y_res fields
+	 * Set rfbi.timings with default values, the hactive and vactive fields
 	 * are expected to be already configured by the panel driver via
 	 * omapdss_rfbi_set_size()
 	 */
-	rfbi.timings.hsw = 1;
-	rfbi.timings.hfp = 1;
-	rfbi.timings.hbp = 1;
-	rfbi.timings.vsw = 1;
-	rfbi.timings.vfp = 0;
-	rfbi.timings.vbp = 0;
+	rfbi.vm.hsync_len = 1;
+	rfbi.vm.hfront_porch = 1;
+	rfbi.vm.hback_porch = 1;
+	rfbi.vm.vsync_len = 1;
+	rfbi.vm.vfront_porch = 0;
+	rfbi.vm.vback_porch = 0;
 
-	rfbi.timings.interlace = false;
-	rfbi.timings.hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	rfbi.timings.vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	rfbi.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	rfbi.timings.de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	rfbi.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
+	rfbi.vm.flags &= ~DISPLAY_FLAGS_INTERLACED;
+	rfbi.vm.flags &= ~DISPLAY_FLAGS_HSYNC_LOW;
+	rfbi.vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
+	rfbi.vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
+	rfbi.vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+	rfbi.vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+	rfbi.vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+	rfbi.vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+	rfbi.vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+	rfbi.vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+	rfbi.vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
 
-	dss_mgr_set_timings(mgr, &rfbi.timings);
+	dss_mgr_set_timings(mgr, &rfbi.vm);
 }
 
 static int rfbi_display_enable(struct omap_dss_device *dssdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/sdi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/sdi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/sdi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/sdi.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@ static struct {
 	struct regulator *vdds_sdi_reg;
 
 	struct dss_lcd_mgr_config mgr_config;
-	struct omap_video_timings timings;
+	struct videomode vm;
 	int datapairs;
 
 	struct omap_dss_device output;
@@ -131,7 +131,7 @@ static int sdi_display_enable(struct oma
 {
 	struct omap_dss_device *out = &sdi.output;
 	enum omap_channel channel = dssdev->dispc_channel;
-	struct omap_video_timings *t = &sdi.timings;
+	struct videomode *vm = &sdi.vm;
 	unsigned long fck;
 	struct dispc_clock_info dispc_cinfo;
 	unsigned long pck;
@@ -151,10 +151,9 @@ static int sdi_display_enable(struct oma
 		goto err_get_dispc;
 
 	/* 15.5.9.1.2 */
-	t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+	vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_SYNC_POSEDGE;
 
-	r = sdi_calc_clock_div(t->pixelclock, &fck, &dispc_cinfo);
+	r = sdi_calc_clock_div(vm->pixelclock, &fck, &dispc_cinfo);
 	if (r)
 		goto err_calc_clock_div;
 
@@ -162,15 +161,15 @@ static int sdi_display_enable(struct oma
 
 	pck = fck / dispc_cinfo.lck_div / dispc_cinfo.pck_div;
 
-	if (pck != t->pixelclock) {
-		DSSWARN("Could not find exact pixel clock. Requested %d Hz, got %lu Hz\n",
-			t->pixelclock, pck);
+	if (pck != vm->pixelclock) {
+		DSSWARN("Could not find exact pixel clock. Requested %lu Hz, got %lu Hz\n",
+			vm->pixelclock, pck);
 
-		t->pixelclock = pck;
+		vm->pixelclock = pck;
 	}
 
 
-	dss_mgr_set_timings(channel, t);
+	dss_mgr_set_timings(channel, vm);
 
 	r = dss_set_fck_rate(fck);
 	if (r)
@@ -229,26 +228,26 @@ static void sdi_display_disable(struct o
 }
 
 static void sdi_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
-	sdi.timings = *timings;
+	sdi.vm = *vm;
 }
 
 static void sdi_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			    struct videomode *vm)
 {
-	*timings = sdi.timings;
+	*vm = sdi.vm;
 }
 
 static int sdi_check_timings(struct omap_dss_device *dssdev,
-			struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	enum omap_channel channel = dssdev->dispc_channel;
 
-	if (!dispc_mgr_timings_ok(channel, timings))
+	if (!dispc_mgr_timings_ok(channel, vm))
 		return -EINVAL;
 
-	if (timings->pixelclock == 0)
+	if (vm->pixelclock == 0)
 		return -EINVAL;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/venc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/venc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/dss/venc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/dss/venc.c	2017-02-12 16:03:20.000000000 -0500
@@ -262,47 +262,41 @@ static const struct venc_config venc_con
 	.fid_ext_start_y__fid_ext_offset_y	= 0x01380005,
 };
 
-const struct omap_video_timings omap_dss_pal_timings = {
-	.x_res		= 720,
-	.y_res		= 574,
+const struct videomode omap_dss_pal_vm = {
+	.hactive	= 720,
+	.vactive	= 574,
 	.pixelclock	= 13500000,
-	.hsw		= 64,
-	.hfp		= 12,
-	.hbp		= 68,
-	.vsw		= 5,
-	.vfp		= 5,
-	.vbp		= 41,
-
-	.interlace	= true,
+	.hsync_len	= 64,
+	.hfront_porch	= 12,
+	.hback_porch	= 68,
+	.vsync_len	= 5,
+	.vfront_porch	= 5,
+	.vback_porch	= 41,
 
-	.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-	.vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.flags		= DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
+			  DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH |
+			  DISPLAY_FLAGS_PIXDATA_POSEDGE |
+			  DISPLAY_FLAGS_SYNC_NEGEDGE,
 };
-EXPORT_SYMBOL(omap_dss_pal_timings);
+EXPORT_SYMBOL(omap_dss_pal_vm);
 
-const struct omap_video_timings omap_dss_ntsc_timings = {
-	.x_res		= 720,
-	.y_res		= 482,
+const struct videomode omap_dss_ntsc_vm = {
+	.hactive	= 720,
+	.vactive	= 482,
 	.pixelclock	= 13500000,
-	.hsw		= 64,
-	.hfp		= 16,
-	.hbp		= 58,
-	.vsw		= 6,
-	.vfp		= 6,
-	.vbp		= 31,
-
-	.interlace	= true,
+	.hsync_len	= 64,
+	.hfront_porch	= 16,
+	.hback_porch	= 58,
+	.vsync_len	= 6,
+	.vfront_porch	= 6,
+	.vback_porch	= 31,
 
-	.hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-	.vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
-	.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
-	.de_level = OMAPDSS_SIG_ACTIVE_HIGH,
-	.sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
+	.flags		= DISPLAY_FLAGS_INTERLACED | DISPLAY_FLAGS_HSYNC_LOW |
+			  DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_DE_HIGH |
+			  DISPLAY_FLAGS_PIXDATA_POSEDGE |
+			  DISPLAY_FLAGS_SYNC_NEGEDGE,
 };
-EXPORT_SYMBOL(omap_dss_ntsc_timings);
+EXPORT_SYMBOL(omap_dss_ntsc_vm);
 
 static struct {
 	struct platform_device *pdev;
@@ -313,7 +307,7 @@ static struct {
 
 	struct clk	*tv_dac_clk;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 	enum omap_dss_venc_type type;
 	bool invert_polarity;
 
@@ -427,13 +421,12 @@ static void venc_runtime_put(void)
 	WARN_ON(r < 0 && r != -ENOSYS);
 }
 
-static const struct venc_config *venc_timings_to_config(
-		struct omap_video_timings *timings)
+static const struct venc_config *venc_timings_to_config(struct videomode *vm)
 {
-	if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+	if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0)
 		return &venc_config_pal_trm;
 
-	if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+	if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0)
 		return &venc_config_ntsc_trm;
 
 	BUG();
@@ -451,7 +444,7 @@ static int venc_power_on(struct omap_dss
 		goto err0;
 
 	venc_reset();
-	venc_write_config(venc_timings_to_config(&venc.timings));
+	venc_write_config(venc_timings_to_config(&venc.vm));
 
 	dss_set_venc_output(venc.type);
 	dss_set_dac_pwrdn_bgz(1);
@@ -468,7 +461,7 @@ static int venc_power_on(struct omap_dss
 
 	venc_write_reg(VENC_OUTPUT_CONTROL, l);
 
-	dss_mgr_set_timings(channel, &venc.timings);
+	dss_mgr_set_timings(channel, &venc.vm);
 
 	r = regulator_enable(venc.vdda_dac_reg);
 	if (r)
@@ -546,17 +539,17 @@ static void venc_display_disable(struct
 }
 
 static void venc_set_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	DSSDBG("venc_set_timings\n");
 
 	mutex_lock(&venc.venc_lock);
 
 	/* Reset WSS data when the TV standard changes. */
-	if (memcmp(&venc.timings, timings, sizeof(*timings)))
+	if (memcmp(&venc.vm, vm, sizeof(*vm)))
 		venc.wss_data = 0;
 
-	venc.timings = *timings;
+	venc.vm = *vm;
 
 	dispc_set_tv_pclk(13500000);
 
@@ -564,25 +557,25 @@ static void venc_set_timings(struct omap
 }
 
 static int venc_check_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			      struct videomode *vm)
 {
 	DSSDBG("venc_check_timings\n");
 
-	if (memcmp(&omap_dss_pal_timings, timings, sizeof(*timings)) == 0)
+	if (memcmp(&omap_dss_pal_vm, vm, sizeof(*vm)) == 0)
 		return 0;
 
-	if (memcmp(&omap_dss_ntsc_timings, timings, sizeof(*timings)) == 0)
+	if (memcmp(&omap_dss_ntsc_vm, vm, sizeof(*vm)) == 0)
 		return 0;
 
 	return -EINVAL;
 }
 
 static void venc_get_timings(struct omap_dss_device *dssdev,
-		struct omap_video_timings *timings)
+			     struct videomode *vm)
 {
 	mutex_lock(&venc.venc_lock);
 
-	*timings = venc.timings;
+	*vm = venc.vm;
 
 	mutex_unlock(&venc.venc_lock);
 }
@@ -602,7 +595,7 @@ static int venc_set_wss(struct omap_dss_
 
 	mutex_lock(&venc.venc_lock);
 
-	config = venc_timings_to_config(&venc.timings);
+	config = venc_timings_to_config(&venc.vm);
 
 	/* Invert due to VENC_L21_WC_CTL:INV=1 */
 	venc.wss_data = (wss ^ 0xfffff) << 8;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_connector.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_connector.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_connector.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_connector.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,73 +42,6 @@ bool omap_connector_get_hdmi_mode(struct
 	return omap_connector->hdmi_mode;
 }
 
-void copy_timings_omap_to_drm(struct drm_display_mode *mode,
-		struct omap_video_timings *timings)
-{
-	mode->clock = timings->pixelclock / 1000;
-
-	mode->hdisplay = timings->x_res;
-	mode->hsync_start = mode->hdisplay + timings->hfp;
-	mode->hsync_end = mode->hsync_start + timings->hsw;
-	mode->htotal = mode->hsync_end + timings->hbp;
-
-	mode->vdisplay = timings->y_res;
-	mode->vsync_start = mode->vdisplay + timings->vfp;
-	mode->vsync_end = mode->vsync_start + timings->vsw;
-	mode->vtotal = mode->vsync_end + timings->vbp;
-
-	mode->flags = 0;
-
-	if (timings->interlace)
-		mode->flags |= DRM_MODE_FLAG_INTERLACE;
-
-	if (timings->double_pixel)
-		mode->flags |= DRM_MODE_FLAG_DBLCLK;
-
-	if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		mode->flags |= DRM_MODE_FLAG_PHSYNC;
-	else
-		mode->flags |= DRM_MODE_FLAG_NHSYNC;
-
-	if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
-		mode->flags |= DRM_MODE_FLAG_PVSYNC;
-	else
-		mode->flags |= DRM_MODE_FLAG_NVSYNC;
-}
-
-void copy_timings_drm_to_omap(struct omap_video_timings *timings,
-		struct drm_display_mode *mode)
-{
-	timings->pixelclock = mode->clock * 1000;
-
-	timings->x_res = mode->hdisplay;
-	timings->hfp = mode->hsync_start - mode->hdisplay;
-	timings->hsw = mode->hsync_end - mode->hsync_start;
-	timings->hbp = mode->htotal - mode->hsync_end;
-
-	timings->y_res = mode->vdisplay;
-	timings->vfp = mode->vsync_start - mode->vdisplay;
-	timings->vsw = mode->vsync_end - mode->vsync_start;
-	timings->vbp = mode->vtotal - mode->vsync_end;
-
-	timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
-	timings->double_pixel = !!(mode->flags & DRM_MODE_FLAG_DBLCLK);
-
-	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
-		timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	else
-		timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW;
-
-	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
-		timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	else
-		timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW;
-
-	timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
-	timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
-	timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE;
-}
-
 static enum drm_connector_status omap_connector_detect(
 		struct drm_connector *connector, bool force)
 {
@@ -185,11 +118,11 @@ static int omap_connector_get_modes(stru
 		kfree(edid);
 	} else {
 		struct drm_display_mode *mode = drm_mode_create(dev);
-		struct omap_video_timings timings = {0};
+		struct videomode vm = {0};
 
-		dssdrv->get_timings(dssdev, &timings);
+		dssdrv->get_timings(dssdev, &vm);
 
-		copy_timings_omap_to_drm(mode, &timings);
+		drm_display_mode_from_videomode(&vm, mode);
 
 		mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 		drm_mode_set_name(mode);
@@ -207,12 +140,14 @@ static int omap_connector_mode_valid(str
 	struct omap_connector *omap_connector = to_omap_connector(connector);
 	struct omap_dss_device *dssdev = omap_connector->dssdev;
 	struct omap_dss_driver *dssdrv = dssdev->driver;
-	struct omap_video_timings timings = {0};
+	struct videomode vm = {0};
 	struct drm_device *dev = connector->dev;
 	struct drm_display_mode *new_mode;
 	int r, ret = MODE_BAD;
 
-	copy_timings_drm_to_omap(&timings, mode);
+	drm_display_mode_to_videomode(mode, &vm);
+	vm.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
+		    DISPLAY_FLAGS_SYNC_NEGEDGE;
 	mode->vrefresh = drm_mode_vrefresh(mode);
 
 	/*
@@ -221,13 +156,13 @@ static int omap_connector_mode_valid(str
 	 * panel's timings
 	 */
 	if (dssdrv->check_timings) {
-		r = dssdrv->check_timings(dssdev, &timings);
+		r = dssdrv->check_timings(dssdev, &vm);
 	} else {
-		struct omap_video_timings t = {0};
+		struct videomode t = {0};
 
 		dssdrv->get_timings(dssdev, &t);
 
-		if (memcmp(&timings, &t, sizeof(struct omap_video_timings)))
+		if (memcmp(&vm, &t, sizeof(struct videomode)))
 			r = -EINVAL;
 		else
 			r = 0;
@@ -236,7 +171,7 @@ static int omap_connector_mode_valid(str
 	if (!r) {
 		/* check if vrefresh is still valid */
 		new_mode = drm_mode_duplicate(dev, mode);
-		new_mode->clock = timings.pixelclock / 1000;
+		new_mode->clock = vm.pixelclock / 1000;
 		new_mode->vrefresh = 0;
 		if (mode->vrefresh == drm_mode_vrefresh(new_mode))
 			ret = MODE_OK;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@ struct omap_crtc {
 	const char *name;
 	enum omap_channel channel;
 
-	struct omap_video_timings timings;
+	struct videomode vm;
 
 	struct omap_drm_irq vblank_irq;
 	struct omap_drm_irq error_irq;
@@ -56,10 +56,10 @@ uint32_t pipe2vbl(struct drm_crtc *crtc)
 	return dispc_mgr_get_vsync_irq(omap_crtc->channel);
 }
 
-struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
+struct videomode *omap_crtc_timings(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-	return &omap_crtc->timings;
+	return &omap_crtc->vm;
 }
 
 enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
@@ -201,7 +201,7 @@ static int omap_crtc_dss_enable(enum oma
 
 	dispc_mgr_setup(omap_crtc->channel, &info);
 	dispc_mgr_set_timings(omap_crtc->channel,
-			&omap_crtc->timings);
+			&omap_crtc->vm);
 	omap_crtc_set_enabled(&omap_crtc->base, true);
 
 	return 0;
@@ -215,11 +215,11 @@ static void omap_crtc_dss_disable(enum o
 }
 
 static void omap_crtc_dss_set_timings(enum omap_channel channel,
-		const struct omap_video_timings *timings)
+		const struct videomode *vm)
 {
 	struct omap_crtc *omap_crtc = omap_crtcs[channel];
 	DBG("%s", omap_crtc->name);
-	omap_crtc->timings = *timings;
+	omap_crtc->vm = *vm;
 }
 
 static void omap_crtc_dss_set_lcd_config(enum omap_channel channel,
@@ -369,7 +369,10 @@ static void omap_crtc_mode_set_nofb(stru
 	    mode->vdisplay, mode->vsync_start, mode->vsync_end, mode->vtotal,
 	    mode->type, mode->flags);
 
-	copy_timings_drm_to_omap(&omap_crtc->timings, mode);
+	drm_display_mode_to_videomode(mode, &omap_crtc->vm);
+	omap_crtc->vm.flags |= DISPLAY_FLAGS_DE_HIGH |
+			       DISPLAY_FLAGS_PIXDATA_POSEDGE |
+			       DISPLAY_FLAGS_SYNC_NEGEDGE;
 }
 
 static int omap_crtc_atomic_check(struct drm_crtc *crtc,
@@ -411,19 +414,6 @@ static void omap_crtc_atomic_flush(struc
 		dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
 	}
 
-	if (crtc->state->color_mgmt_changed) {
-		struct drm_color_lut *lut = NULL;
-		uint length = 0;
-
-		if (crtc->state->gamma_lut) {
-			lut = (struct drm_color_lut *)
-				crtc->state->gamma_lut->data;
-			length = crtc->state->gamma_lut->length /
-				sizeof(*lut);
-		}
-		dispc_mgr_set_gamma(omap_crtc->channel, lut, length);
-	}
-
 	if (dispc_mgr_is_enabled(omap_crtc->channel)) {
 
 		DBG("%s: GO", omap_crtc->name);
@@ -438,13 +428,14 @@ static void omap_crtc_atomic_flush(struc
 	}
 }
 
-static bool omap_crtc_is_plane_prop(struct drm_device *dev,
+static bool omap_crtc_is_plane_prop(struct drm_crtc *crtc,
 	struct drm_property *property)
 {
+	struct drm_device *dev = crtc->dev;
 	struct omap_drm_private *priv = dev->dev_private;
 
 	return property == priv->zorder_prop ||
-		property == dev->mode_config.rotation_property;
+		property == crtc->primary->rotation_property;
 }
 
 static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
@@ -452,9 +443,7 @@ static int omap_crtc_atomic_set_property
 					 struct drm_property *property,
 					 uint64_t val)
 {
-	struct drm_device *dev = crtc->dev;
-
-	if (omap_crtc_is_plane_prop(dev, property)) {
+	if (omap_crtc_is_plane_prop(crtc, property)) {
 		struct drm_plane_state *plane_state;
 		struct drm_plane *plane = crtc->primary;
 
@@ -479,9 +468,7 @@ static int omap_crtc_atomic_get_property
 					 struct drm_property *property,
 					 uint64_t *val)
 {
-	struct drm_device *dev = crtc->dev;
-
-	if (omap_crtc_is_plane_prop(dev, property)) {
+	if (omap_crtc_is_plane_prop(crtc, property)) {
 		/*
 		 * Delegate property get to the primary plane. The
 		 * drm_atomic_plane_get_property() function isn't exported, but
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -105,7 +105,7 @@ static void omap_atomic_complete(struct
 
 	dispc_runtime_put();
 
-	drm_atomic_state_free(old_state);
+	drm_atomic_state_put(old_state);
 
 	/* Complete the commit, wake up any waiter. */
 	spin_lock(&priv->commit.lock);
@@ -176,6 +176,7 @@ static int omap_atomic_commit(struct drm
 	/* Swap the state, this is the point of no return. */
 	drm_atomic_helper_swap_state(state, true);
 
+	drm_atomic_state_get(state);
 	if (nonblock)
 		schedule_work(&commit->work);
 	else
@@ -266,13 +267,15 @@ cleanup:
 }
 
 static int omap_modeset_create_crtc(struct drm_device *dev, int id,
-				    enum omap_channel channel)
+				    enum omap_channel channel,
+				    u32 possible_crtcs)
 {
 	struct omap_drm_private *priv = dev->dev_private;
 	struct drm_plane *plane;
 	struct drm_crtc *crtc;
 
-	plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_PRIMARY);
+	plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_PRIMARY,
+		possible_crtcs);
 	if (IS_ERR(plane))
 		return PTR_ERR(plane);
 
@@ -292,16 +295,6 @@ static int omap_modeset_init_properties(
 {
 	struct omap_drm_private *priv = dev->dev_private;
 
-	if (priv->has_dmm) {
-		dev->mode_config.rotation_property =
-			drm_mode_create_rotation_property(dev,
-				DRM_ROTATE_0 | DRM_ROTATE_90 |
-				DRM_ROTATE_180 | DRM_ROTATE_270 |
-				DRM_REFLECT_X | DRM_REFLECT_Y);
-		if (!dev->mode_config.rotation_property)
-			return -ENOMEM;
-	}
-
 	priv->zorder_prop = drm_property_create_range(dev, 0, "zorder", 0, 3);
 	if (!priv->zorder_prop)
 		return -ENOMEM;
@@ -318,6 +311,7 @@ static int omap_modeset_init(struct drm_
 	int num_crtcs;
 	int i, id = 0;
 	int ret;
+	u32 possible_crtcs;
 
 	drm_mode_config_init(dev);
 
@@ -334,6 +328,7 @@ static int omap_modeset_init(struct drm_
 	 * We use the num_crtc argument to limit the number of crtcs we create.
 	 */
 	num_crtcs = min3(num_crtc, num_mgrs, num_ovls);
+	possible_crtcs = (1 << num_crtcs) - 1;
 
 	dssdev = NULL;
 
@@ -397,7 +392,8 @@ static int omap_modeset_init(struct drm_
 		 * allocated crtc, we create a new crtc for it
 		 */
 		if (!channel_used(dev, channel)) {
-			ret = omap_modeset_create_crtc(dev, id, channel);
+			ret = omap_modeset_create_crtc(dev, id, channel,
+				possible_crtcs);
 			if (ret < 0) {
 				dev_err(dev->dev,
 					"could not create CRTC (channel %u)\n",
@@ -427,7 +423,8 @@ static int omap_modeset_init(struct drm_
 			return -ENOMEM;
 		}
 
-		ret = omap_modeset_create_crtc(dev, id, i);
+		ret = omap_modeset_create_crtc(dev, id, i,
+			possible_crtcs);
 		if (ret < 0) {
 			dev_err(dev->dev,
 				"could not create CRTC (channel %u)\n", i);
@@ -441,7 +438,8 @@ static int omap_modeset_init(struct drm_
 	for (; id < num_ovls; id++) {
 		struct drm_plane *plane;
 
-		plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_OVERLAY);
+		plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_OVERLAY,
+			possible_crtcs);
 		if (IS_ERR(plane))
 			return PTR_ERR(plane);
 
@@ -752,22 +750,32 @@ static void dev_lastclose(struct drm_dev
 
 	DBG("lastclose: dev=%p", dev);
 
-	if (dev->mode_config.rotation_property) {
-		/* need to restore default rotation state.. not sure
-		 * if there is a cleaner way to restore properties to
-		 * default state?  Maybe a flag that properties should
-		 * automatically be restored to default state on
-		 * lastclose?
-		 */
-		for (i = 0; i < priv->num_crtcs; i++) {
-			drm_object_property_set_value(&priv->crtcs[i]->base,
-					dev->mode_config.rotation_property, 0);
-		}
+	/* need to restore default rotation state.. not sure
+	 * if there is a cleaner way to restore properties to
+	 * default state?  Maybe a flag that properties should
+	 * automatically be restored to default state on
+	 * lastclose?
+	 */
+	for (i = 0; i < priv->num_crtcs; i++) {
+		struct drm_crtc *crtc = priv->crtcs[i];
 
-		for (i = 0; i < priv->num_planes; i++) {
-			drm_object_property_set_value(&priv->planes[i]->base,
-					dev->mode_config.rotation_property, 0);
-		}
+		if (!crtc->primary->rotation_property)
+			continue;
+
+		drm_object_property_set_value(&crtc->base,
+					      crtc->primary->rotation_property,
+					      DRM_ROTATE_0);
+	}
+
+	for (i = 0; i < priv->num_planes; i++) {
+		struct drm_plane *plane = priv->planes[i];
+
+		if (!plane->rotation_property)
+			continue;
+
+		drm_object_property_set_value(&plane->base,
+					      plane->rotation_property,
+					      DRM_ROTATE_0);
 	}
 
 	if (priv->fbdev) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -148,7 +148,7 @@ static inline void omap_fbdev_free(struc
 }
 #endif
 
-struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
+struct videomode *omap_crtc_timings(struct drm_crtc *crtc);
 enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
 void omap_crtc_pre_init(void);
 void omap_crtc_pre_uninit(void);
@@ -157,7 +157,8 @@ struct drm_crtc *omap_crtc_init(struct d
 int omap_crtc_wait_pending(struct drm_crtc *crtc);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
-		int id, enum drm_plane_type type);
+		int id, enum drm_plane_type type,
+		u32 possible_crtcs);
 void omap_plane_install_properties(struct drm_plane *plane,
 		struct drm_mode_object *obj);
 
@@ -171,11 +172,6 @@ struct drm_encoder *omap_connector_attac
 		struct drm_connector *connector);
 bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
 
-void copy_timings_omap_to_drm(struct drm_display_mode *mode,
-		struct omap_video_timings *timings);
-void copy_timings_drm_to_omap(struct omap_video_timings *timings,
-		struct drm_display_mode *mode);
-
 uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
 		uint32_t max_formats, enum omap_color_mode supported_modes);
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_encoder.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,7 @@ static void omap_encoder_disable(struct
 
 static int omap_encoder_update(struct drm_encoder *encoder,
 			       enum omap_channel channel,
-			       struct omap_video_timings *timings)
+			       struct videomode *vm)
 {
 	struct drm_device *dev = encoder->dev;
 	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
@@ -111,13 +111,13 @@ static int omap_encoder_update(struct dr
 	int ret;
 
 	if (dssdrv->check_timings) {
-		ret = dssdrv->check_timings(dssdev, timings);
+		ret = dssdrv->check_timings(dssdev, vm);
 	} else {
-		struct omap_video_timings t = {0};
+		struct videomode t = {0};
 
 		dssdrv->get_timings(dssdev, &t);
 
-		if (memcmp(timings, &t, sizeof(struct omap_video_timings)))
+		if (memcmp(vm, &t, sizeof(struct videomode)))
 			ret = -EINVAL;
 		else
 			ret = 0;
@@ -129,7 +129,7 @@ static int omap_encoder_update(struct dr
 	}
 
 	if (dssdrv->set_timings)
-		dssdrv->set_timings(dssdev, timings);
+		dssdrv->set_timings(dssdev, vm);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -82,6 +82,7 @@ fallback:
 
 static struct fb_ops omap_fb_ops = {
 	.owner = THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 
 	/* Note: to properly handle manual update displays, we wrap the
 	 * basic fbdev ops which write to the framebuffer
@@ -92,11 +93,7 @@ static struct fb_ops omap_fb_ops = {
 	.fb_copyarea = drm_fb_helper_sys_copyarea,
 	.fb_imageblit = drm_fb_helper_sys_imageblit,
 
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
 	.fb_pan_display = omap_fbdev_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
 };
 
 static int omap_fbdev_create(struct drm_fb_helper *helper,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -336,8 +336,10 @@ static void omap_gem_detach_pages(struct
 	if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
 		int i, npages = obj->size >> PAGE_SHIFT;
 		for (i = 0; i < npages; i++) {
-			dma_unmap_page(obj->dev->dev, omap_obj->addrs[i],
-					PAGE_SIZE, DMA_BIDIRECTIONAL);
+			if (omap_obj->addrs[i])
+				dma_unmap_page(obj->dev->dev,
+					       omap_obj->addrs[i],
+					       PAGE_SIZE, DMA_BIDIRECTIONAL);
 		}
 	}
 
@@ -396,8 +398,7 @@ static int fault_1d(struct drm_gem_objec
 	pgoff_t pgoff;
 
 	/* We don't use vmf->pgoff since that has the fake offset: */
-	pgoff = ((unsigned long)vmf->virtual_address -
-			vma->vm_start) >> PAGE_SHIFT;
+	pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
 	if (omap_obj->pages) {
 		omap_gem_cpu_sync(obj, pgoff);
@@ -407,11 +408,10 @@ static int fault_1d(struct drm_gem_objec
 		pfn = (omap_obj->paddr >> PAGE_SHIFT) + pgoff;
 	}
 
-	VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+	VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
 			pfn, pfn << PAGE_SHIFT);
 
-	return vm_insert_mixed(vma, (unsigned long)vmf->virtual_address,
-			__pfn_to_pfn_t(pfn, PFN_DEV));
+	return vm_insert_mixed(vma, vmf->address, __pfn_to_pfn_t(pfn, PFN_DEV));
 }
 
 /* Special handling for the case of faulting in 2d tiled buffers */
@@ -425,7 +425,7 @@ static int fault_2d(struct drm_gem_objec
 	struct page *pages[64];  /* XXX is this too much to have on stack? */
 	unsigned long pfn;
 	pgoff_t pgoff, base_pgoff;
-	void __user *vaddr;
+	unsigned long vaddr;
 	int i, ret, slots;
 
 	/*
@@ -445,8 +445,7 @@ static int fault_2d(struct drm_gem_objec
 	const int m = 1 + ((omap_obj->width << fmt) / PAGE_SIZE);
 
 	/* We don't use vmf->pgoff since that has the fake offset: */
-	pgoff = ((unsigned long)vmf->virtual_address -
-			vma->vm_start) >> PAGE_SHIFT;
+	pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
 	/*
 	 * Actual address we start mapping at is rounded down to previous slot
@@ -457,7 +456,7 @@ static int fault_2d(struct drm_gem_objec
 	/* figure out buffer width in slots */
 	slots = omap_obj->width >> priv->usergart[fmt].slot_shift;
 
-	vaddr = vmf->virtual_address - ((pgoff - base_pgoff) << PAGE_SHIFT);
+	vaddr = vmf->address - ((pgoff - base_pgoff) << PAGE_SHIFT);
 
 	entry = &priv->usergart[fmt].entry[priv->usergart[fmt].last];
 
@@ -501,12 +500,11 @@ static int fault_2d(struct drm_gem_objec
 
 	pfn = entry->paddr >> PAGE_SHIFT;
 
-	VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address,
+	VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
 			pfn, pfn << PAGE_SHIFT);
 
 	for (i = n; i > 0; i--) {
-		vm_insert_mixed(vma, (unsigned long)vaddr,
-				__pfn_to_pfn_t(pfn, PFN_DEV));
+		vm_insert_mixed(vma, vaddr, __pfn_to_pfn_t(pfn, PFN_DEV));
 		pfn += priv->usergart[fmt].stride_pfn;
 		vaddr += PAGE_SIZE * m;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/omapdrm/omap_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/omapdrm/omap_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,16 +108,12 @@ static void omap_plane_atomic_update(str
 	win.src_x = state->src_x >> 16;
 	win.src_y = state->src_y >> 16;
 
-	switch (state->rotation & DRM_ROTATE_MASK) {
-	case DRM_ROTATE_90:
-	case DRM_ROTATE_270:
+	if (drm_rotation_90_or_270(state->rotation)) {
 		win.src_w = state->src_h >> 16;
 		win.src_h = state->src_w >> 16;
-		break;
-	default:
+	} else {
 		win.src_w = state->src_w >> 16;
 		win.src_h = state->src_h >> 16;
-		break;
 	}
 
 	/* update scanout: */
@@ -135,7 +131,9 @@ static void omap_plane_atomic_update(str
 	/* and finally, update omapdss: */
 	ret = dispc_ovl_setup(omap_plane->id, &info, false,
 			      omap_crtc_timings(state->crtc), false);
-	if (WARN_ON(ret)) {
+	if (ret) {
+		dev_err(plane->dev->dev, "Failed to setup plane %s\n",
+			omap_plane->name);
 		dispc_ovl_enable(omap_plane->id, false);
 		return;
 	}
@@ -161,12 +159,20 @@ static int omap_plane_atomic_check(struc
 {
 	struct drm_crtc_state *crtc_state;
 
-	if (!state->crtc)
+	if (!state->fb)
 		return 0;
 
-	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
-	if (IS_ERR(crtc_state))
-		return PTR_ERR(crtc_state);
+	/* crtc should only be NULL when disabling (i.e., !state->fb) */
+	if (WARN_ON(!state->crtc))
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc);
+	/* we should have a crtc state if the plane is attached to a crtc */
+	if (WARN_ON(!crtc_state))
+		return 0;
+
+	if (!crtc_state->enable)
+		return 0;
 
 	if (state->crtc_x < 0 || state->crtc_y < 0)
 		return -EINVAL;
@@ -177,11 +183,9 @@ static int omap_plane_atomic_check(struc
 	if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay)
 		return -EINVAL;
 
-	if (state->fb) {
-		if (state->rotation != DRM_ROTATE_0 &&
-		    !omap_framebuffer_supports_rotation(state->fb))
-			return -EINVAL;
-	}
+	if (state->rotation != DRM_ROTATE_0 &&
+	    !omap_framebuffer_supports_rotation(state->fb))
+		return -EINVAL;
 
 	return 0;
 }
@@ -215,9 +219,17 @@ void omap_plane_install_properties(struc
 	struct omap_drm_private *priv = dev->dev_private;
 
 	if (priv->has_dmm) {
-		struct drm_property *prop = dev->mode_config.rotation_property;
+		if (!plane->rotation_property)
+			drm_plane_create_rotation_property(plane,
+							   DRM_ROTATE_0,
+							   DRM_ROTATE_0 | DRM_ROTATE_90 |
+							   DRM_ROTATE_180 | DRM_ROTATE_270 |
+							   DRM_REFLECT_X | DRM_REFLECT_Y);
 
-		drm_object_attach_property(obj, prop, 0);
+		/* Attach the rotation property also to the crtc object */
+		if (plane->rotation_property && obj != &plane->base)
+			drm_object_attach_property(obj, plane->rotation_property,
+						   DRM_ROTATE_0);
 	}
 
 	drm_object_attach_property(obj, priv->zorder_prop, 0);
@@ -344,9 +356,9 @@ static const uint32_t error_irqs[] = {
 
 /* initialize plane */
 struct drm_plane *omap_plane_init(struct drm_device *dev,
-		int id, enum drm_plane_type type)
+		int id, enum drm_plane_type type,
+		u32 possible_crtcs)
 {
-	struct omap_drm_private *priv = dev->dev_private;
 	struct drm_plane *plane;
 	struct omap_plane *omap_plane;
 	int ret;
@@ -369,7 +381,7 @@ struct drm_plane *omap_plane_init(struct
 	omap_plane->error_irq.irq = omap_plane_error_irq;
 	omap_irq_register(dev, &omap_plane->error_irq);
 
-	ret = drm_universal_plane_init(dev, plane, (1 << priv->num_crtcs) - 1,
+	ret = drm_universal_plane_init(dev, plane, possible_crtcs,
 				       &omap_plane_funcs, omap_plane->formats,
 				       omap_plane->nformats, type, NULL);
 	if (ret < 0)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/panel/panel-simple.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/panel/panel-simple.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/panel/panel-simple.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/panel/panel-simple.c	2017-02-12 16:03:20.000000000 -0500
@@ -120,7 +120,7 @@ static int panel_simple_get_fixed_modes(
 
 		mode->type |= DRM_MODE_TYPE_DRIVER;
 
-		if (panel->desc->num_modes == 1)
+		if (panel->desc->num_timings == 1)
 			mode->type |= DRM_MODE_TYPE_PREFERRED;
 
 		drm_mode_probed_add(connector, mode);
@@ -555,6 +555,91 @@ static const struct panel_desc auo_b133h
 	},
 };
 
+static const struct display_timing auo_g133han01_timings = {
+	.pixelclock = { 134000000, 141200000, 149000000 },
+	.hactive = { 1920, 1920, 1920 },
+	.hfront_porch = { 39, 58, 77 },
+	.hback_porch = { 59, 88, 117 },
+	.hsync_len = { 28, 42, 56 },
+	.vactive = { 1080, 1080, 1080 },
+	.vfront_porch = { 3, 8, 11 },
+	.vback_porch = { 5, 14, 19 },
+	.vsync_len = { 4, 14, 19 },
+};
+
+static const struct panel_desc auo_g133han01 = {
+	.timings = &auo_g133han01_timings,
+	.num_timings = 1,
+	.bpc = 8,
+	.size = {
+		.width = 293,
+		.height = 165,
+	},
+	.delay = {
+		.prepare = 200,
+		.enable = 50,
+		.disable = 50,
+		.unprepare = 1000,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+};
+
+static const struct display_timing auo_g185han01_timings = {
+	.pixelclock = { 120000000, 144000000, 175000000 },
+	.hactive = { 1920, 1920, 1920 },
+	.hfront_porch = { 18, 60, 74 },
+	.hback_porch = { 12, 44, 54 },
+	.hsync_len = { 10, 24, 32 },
+	.vactive = { 1080, 1080, 1080 },
+	.vfront_porch = { 6, 10, 40 },
+	.vback_porch = { 2, 5, 20 },
+	.vsync_len = { 2, 5, 20 },
+};
+
+static const struct panel_desc auo_g185han01 = {
+	.timings = &auo_g185han01_timings,
+	.num_timings = 1,
+	.bpc = 8,
+	.size = {
+		.width = 409,
+		.height = 230,
+	},
+	.delay = {
+		.prepare = 50,
+		.enable = 200,
+		.disable = 110,
+		.unprepare = 1000,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
+static const struct drm_display_mode auo_t215hvn01_mode = {
+	.clock = 148800,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 88,
+	.hsync_end = 1920 + 88 + 44,
+	.htotal = 1920 + 88 + 44 + 148,
+	.vdisplay = 1080,
+	.vsync_start = 1080 + 4,
+	.vsync_end = 1080 + 4 + 5,
+	.vtotal = 1080 + 4 + 5 + 36,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc auo_t215hvn01 = {
+	.modes = &auo_t215hvn01_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.size = {
+		.width = 430,
+		.height = 270,
+	},
+	.delay = {
+		.disable = 5,
+		.unprepare = 1000,
+	}
+};
+
 static const struct drm_display_mode avic_tm070ddh03_mode = {
 	.clock = 51200,
 	.hdisplay = 1024,
@@ -583,6 +668,30 @@ static const struct panel_desc avic_tm07
 	},
 };
 
+static const struct drm_display_mode chunghwa_claa070wp03xg_mode = {
+	.clock = 66770,
+	.hdisplay = 800,
+	.hsync_start = 800 + 49,
+	.hsync_end = 800 + 49 + 33,
+	.htotal = 800 + 49 + 33 + 17,
+	.vdisplay = 1280,
+	.vsync_start = 1280 + 1,
+	.vsync_end = 1280 + 1 + 7,
+	.vtotal = 1280 + 1 + 7 + 15,
+	.vrefresh = 60,
+	.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc chunghwa_claa070wp03xg = {
+	.modes = &chunghwa_claa070wp03xg_mode,
+	.num_modes = 1,
+	.bpc = 6,
+	.size = {
+		.width = 94,
+		.height = 150,
+	},
+};
+
 static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
 	.clock = 72070,
 	.hdisplay = 1366,
@@ -877,27 +986,31 @@ static const struct panel_desc innolux_g
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
 };
 
-static const struct drm_display_mode innolux_g121i1_l01_mode = {
-	.clock = 71000,
-	.hdisplay = 1280,
-	.hsync_start = 1280 + 64,
-	.hsync_end = 1280 + 64 + 32,
-	.htotal = 1280 + 64 + 32 + 64,
-	.vdisplay = 800,
-	.vsync_start = 800 + 9,
-	.vsync_end = 800 + 9 + 6,
-	.vtotal = 800 + 9 + 6 + 9,
-	.vrefresh = 60,
+static const struct display_timing innolux_g121i1_l01_timing = {
+	.pixelclock = { 67450000, 71000000, 74550000 },
+	.hactive = { 1280, 1280, 1280 },
+	.hfront_porch = { 40, 80, 160 },
+	.hback_porch = { 39, 79, 159 },
+	.hsync_len = { 1, 1, 1 },
+	.vactive = { 800, 800, 800 },
+	.vfront_porch = { 5, 11, 100 },
+	.vback_porch = { 4, 11, 99 },
+	.vsync_len = { 1, 1, 1 },
 };
 
 static const struct panel_desc innolux_g121i1_l01 = {
-	.modes = &innolux_g121i1_l01_mode,
-	.num_modes = 1,
+	.timings = &innolux_g121i1_l01_timing,
+	.num_timings = 1,
 	.bpc = 6,
 	.size = {
 		.width = 261,
 		.height = 163,
 	},
+	.delay = {
+		.enable = 200,
+		.disable = 20,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
 };
 
 static const struct drm_display_mode innolux_g121x1_l03_mode = {
@@ -1164,6 +1277,29 @@ static const struct panel_desc nec_nl482
 	.bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
 };
 
+static const struct drm_display_mode nvd_9128_mode = {
+	.clock = 29500,
+	.hdisplay = 800,
+	.hsync_start = 800 + 130,
+	.hsync_end = 800 + 130 + 98,
+	.htotal = 800 + 0 + 130 + 98,
+	.vdisplay = 480,
+	.vsync_start = 480 + 10,
+	.vsync_end = 480 + 10 + 50,
+	.vtotal = 480 + 0 + 10 + 50,
+};
+
+static const struct panel_desc nvd_9128 = {
+	.modes = &nvd_9128_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.size = {
+		.width = 156,
+		.height = 88,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
 static const struct display_timing okaya_rs800480t_7x0gp_timing = {
 	.pixelclock = { 30000000, 30000000, 40000000 },
 	.hactive = { 800, 800, 800 },
@@ -1409,6 +1545,7 @@ static const struct drm_display_mode sha
 static const struct panel_desc sharp_lq123p1jx31 = {
 	.modes = &sharp_lq123p1jx31_mode,
 	.num_modes = 1,
+	.bpc = 8,
 	.size = {
 		.width = 259,
 		.height = 173,
@@ -1420,6 +1557,30 @@ static const struct panel_desc sharp_lq1
 	},
 };
 
+static const struct drm_display_mode sharp_lq150x1lg11_mode = {
+	.clock = 71100,
+	.hdisplay = 1024,
+	.hsync_start = 1024 + 168,
+	.hsync_end = 1024 + 168 + 64,
+	.htotal = 1024 + 168 + 64 + 88,
+	.vdisplay = 768,
+	.vsync_start = 768 + 37,
+	.vsync_end = 768 + 37 + 2,
+	.vtotal = 768 + 37 + 2 + 8,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc sharp_lq150x1lg11 = {
+	.modes = &sharp_lq150x1lg11_mode,
+	.num_modes = 1,
+	.bpc = 6,
+	.size = {
+		.width = 304,
+		.height = 228,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB565_1X16,
+};
+
 static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = {
 	.clock = 33300,
 	.hdisplay = 800,
@@ -1575,9 +1736,21 @@ static const struct of_device_id platfor
 		.compatible = "auo,b133xtn01",
 		.data = &auo_b133xtn01,
 	}, {
+		.compatible = "auo,g133han01",
+		.data = &auo_g133han01,
+	}, {
+		.compatible = "auo,g185han01",
+		.data = &auo_g185han01,
+	}, {
+		.compatible = "auo,t215hvn01",
+		.data = &auo_t215hvn01,
+	}, {
 		.compatible = "avic,tm070ddh03",
 		.data = &avic_tm070ddh03,
 	}, {
+		.compatible = "chunghwa,claa070wp03xg",
+		.data = &chunghwa_claa070wp03xg,
+	}, {
 		.compatible = "chunghwa,claa101wa01a",
 		.data = &chunghwa_claa101wa01a
 	}, {
@@ -1653,6 +1826,9 @@ static const struct of_device_id platfor
 		.compatible = "nec,nl4827hc19-05b",
 		.data = &nec_nl4827hc19_05b,
 	}, {
+		.compatible = "nvd,9128",
+		.data = &nvd_9128,
+	}, {
 		.compatible = "okaya,rs800480t-7x0gp",
 		.data = &okaya_rs800480t_7x0gp,
 	}, {
@@ -1683,6 +1859,9 @@ static const struct of_device_id platfor
 		.compatible = "sharp,lq123p1jx31",
 		.data = &sharp_lq123p1jx31,
 	}, {
+		.compatible = "sharp,lq150x1lg11",
+		.data = &sharp_lq150x1lg11,
+	}, {
 		.compatible = "shelly,sca07010-bfn-lnn",
 		.data = &shelly_sca07010_bfn_lnn,
 	}, {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_cmd.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_cmd.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -578,7 +578,7 @@ int qxl_hw_surface_dealloc(struct qxl_de
 	return 0;
 }
 
-int qxl_update_surface(struct qxl_device *qdev, struct qxl_bo *surf)
+static int qxl_update_surface(struct qxl_device *qdev, struct qxl_bo *surf)
 {
 	struct qxl_rect rect;
 	int ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_debugfs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_debugfs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -123,9 +123,6 @@ int qxl_debugfs_add_files(struct qxl_dev
 	qdev->debugfs_count = i;
 #if defined(CONFIG_DEBUG_FS)
 	drm_debugfs_create_files(files, nfiles,
-				 qdev->ddev->control->debugfs_root,
-				 qdev->ddev->control);
-	drm_debugfs_create_files(files, nfiles,
 				 qdev->ddev->primary->debugfs_root,
 				 qdev->ddev->primary);
 #endif
@@ -140,9 +137,6 @@ void qxl_debugfs_remove_files(struct qxl
 	for (i = 0; i < qdev->debugfs_count; i++) {
 		drm_debugfs_remove_files(qdev->debugfs[i].files,
 					 qdev->debugfs[i].num_files,
-					 qdev->ddev->control);
-		drm_debugfs_remove_files(qdev->debugfs[i].files,
-					 qdev->debugfs[i].num_files,
 					 qdev->ddev->primary);
 	}
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_display.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@ static bool qxl_head_enabled(struct qxl_
 	return head->width && head->height;
 }
 
-void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count)
+static void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count)
 {
 	if (qdev->client_monitors_config &&
 	    count > qdev->client_monitors_config->count) {
@@ -57,11 +57,18 @@ void qxl_alloc_client_monitors_config(st
 	qdev->client_monitors_config->count = count;
 }
 
+enum {
+	MONITORS_CONFIG_MODIFIED,
+	MONITORS_CONFIG_UNCHANGED,
+	MONITORS_CONFIG_BAD_CRC,
+};
+
 static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev)
 {
 	int i;
 	int num_monitors;
 	uint32_t crc;
+	int status = MONITORS_CONFIG_UNCHANGED;
 
 	num_monitors = qdev->rom->client_monitors_config.count;
 	crc = crc32(0, (const uint8_t *)&qdev->rom->client_monitors_config,
@@ -70,7 +77,7 @@ static int qxl_display_copy_rom_client_m
 		qxl_io_log(qdev, "crc mismatch: have %X (%zd) != %X\n", crc,
 			   sizeof(qdev->rom->client_monitors_config),
 			   qdev->rom->client_monitors_config_crc);
-		return 1;
+		return MONITORS_CONFIG_BAD_CRC;
 	}
 	if (num_monitors > qdev->monitors_config->max_allowed) {
 		DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n",
@@ -79,6 +86,10 @@ static int qxl_display_copy_rom_client_m
 	} else {
 		num_monitors = qdev->rom->client_monitors_config.count;
 	}
+	if (qdev->client_monitors_config
+	      && (num_monitors != qdev->client_monitors_config->count)) {
+		status = MONITORS_CONFIG_MODIFIED;
+	}
 	qxl_alloc_client_monitors_config(qdev, num_monitors);
 	/* we copy max from the client but it isn't used */
 	qdev->client_monitors_config->max_allowed =
@@ -88,17 +99,39 @@ static int qxl_display_copy_rom_client_m
 			&qdev->rom->client_monitors_config.heads[i];
 		struct qxl_head *client_head =
 			&qdev->client_monitors_config->heads[i];
-		client_head->x = c_rect->left;
-		client_head->y = c_rect->top;
-		client_head->width = c_rect->right - c_rect->left;
-		client_head->height = c_rect->bottom - c_rect->top;
-		client_head->surface_id = 0;
-		client_head->id = i;
-		client_head->flags = 0;
+		if (client_head->x != c_rect->left) {
+			client_head->x = c_rect->left;
+			status = MONITORS_CONFIG_MODIFIED;
+		}
+		if (client_head->y != c_rect->top) {
+			client_head->y = c_rect->top;
+			status = MONITORS_CONFIG_MODIFIED;
+		}
+		if (client_head->width != c_rect->right - c_rect->left) {
+			client_head->width = c_rect->right - c_rect->left;
+			status = MONITORS_CONFIG_MODIFIED;
+		}
+		if (client_head->height != c_rect->bottom - c_rect->top) {
+			client_head->height = c_rect->bottom - c_rect->top;
+			status = MONITORS_CONFIG_MODIFIED;
+		}
+		if (client_head->surface_id != 0) {
+			client_head->surface_id = 0;
+			status = MONITORS_CONFIG_MODIFIED;
+		}
+		if (client_head->id != i) {
+			client_head->id = i;
+			status = MONITORS_CONFIG_MODIFIED;
+		}
+		if (client_head->flags != 0) {
+			client_head->flags = 0;
+			status = MONITORS_CONFIG_MODIFIED;
+		}
 		DRM_DEBUG_KMS("read %dx%d+%d+%d\n", client_head->width, client_head->height,
 			  client_head->x, client_head->y);
 	}
-	return 0;
+
+	return status;
 }
 
 static void qxl_update_offset_props(struct qxl_device *qdev)
@@ -124,9 +157,18 @@ void qxl_display_read_client_monitors_co
 {
 
 	struct drm_device *dev = qdev->ddev;
-	while (qxl_display_copy_rom_client_monitors_config(qdev)) {
+	int status;
+
+	status = qxl_display_copy_rom_client_monitors_config(qdev);
+	while (status == MONITORS_CONFIG_BAD_CRC) {
 		qxl_io_log(qdev, "failed crc check for client_monitors_config,"
 				 " retrying\n");
+		status = qxl_display_copy_rom_client_monitors_config(qdev);
+	}
+	if (status == MONITORS_CONFIG_UNCHANGED) {
+		qxl_io_log(qdev, "config unchanged\n");
+		DRM_DEBUG("ignoring unchanged client monitors config");
+		return;
 	}
 
 	drm_modeset_lock_all(dev);
@@ -157,6 +199,9 @@ static int qxl_add_monitors_config_modes
 	mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false,
 			    false);
 	mode->type |= DRM_MODE_TYPE_PREFERRED;
+	mode->hdisplay = head->width;
+	mode->vdisplay = head->height;
+	drm_mode_set_name(mode);
 	*pwidth = head->width;
 	*pheight = head->height;
 	drm_mode_probed_add(connector, mode);
@@ -607,7 +652,7 @@ static bool qxl_crtc_mode_fixup(struct d
 	return true;
 }
 
-void
+static void
 qxl_send_monitors_config(struct qxl_device *qdev)
 {
 	int i;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
  * Definitions taken from spice-protocol, plus kernel driver specific bits.
  */
 
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 #include <linux/workqueue.h>
 #include <linux/firmware.h>
 #include <linux/platform_device.h>
@@ -190,7 +190,7 @@ enum {
  * spice-protocol/qxl_dev.h */
 #define QXL_MAX_RES 96
 struct qxl_release {
-	struct fence base;
+	struct dma_fence base;
 
 	int id;
 	int type;
@@ -395,16 +395,11 @@ qxl_framebuffer_init(struct drm_device *
 		     struct drm_gem_object *obj,
 		     const struct drm_framebuffer_funcs *funcs);
 void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
-void qxl_send_monitors_config(struct qxl_device *qdev);
 int qxl_create_monitors_object(struct qxl_device *qdev);
 int qxl_destroy_monitors_object(struct qxl_device *qdev);
 
-/* used by qxl_debugfs only */
-void qxl_crtc_set_from_monitors_config(struct qxl_device *qdev);
-void qxl_alloc_client_monitors_config(struct qxl_device *qdev, unsigned count);
-
 /* qxl_gem.c */
-int qxl_gem_init(struct qxl_device *qdev);
+void qxl_gem_init(struct qxl_device *qdev);
 void qxl_gem_fini(struct qxl_device *qdev);
 int qxl_gem_object_create(struct qxl_device *qdev, int size,
 			  int alignment, int initial_domain,
@@ -574,6 +569,5 @@ int qxl_bo_check_id(struct qxl_device *q
 struct qxl_drv_surface *
 qxl_surface_lookup(struct drm_device *dev, int surface_id);
 void qxl_surface_evict(struct qxl_device *qdev, struct qxl_bo *surf, bool freeing);
-int qxl_update_surface(struct qxl_device *qdev, struct qxl_bo *surf);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,16 +81,10 @@ static struct fb_deferred_io qxl_defio =
 
 static struct fb_ops qxlfb_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_fillrect = drm_fb_helper_sys_fillrect,
 	.fb_copyarea = drm_fb_helper_sys_copyarea,
 	.fb_imageblit = drm_fb_helper_sys_imageblit,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 static void qxlfb_destroy_pinned_object(struct drm_gem_object *gobj)
@@ -197,7 +191,7 @@ static int qxlfb_framebuffer_dirty(struc
 	/*
 	 * we are using a shadow draw buffer, at qdev->surface0_shadow
 	 */
-	qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]", clips->x1, clips->x2,
+	qxl_io_log(qdev, "dirty x[%d, %d], y[%d, %d]\n", clips->x1, clips->x2,
 		   clips->y1, clips->y2);
 	image->dx = clips->x1;
 	image->dy = clips->y1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -111,10 +111,9 @@ void qxl_gem_object_close(struct drm_gem
 {
 }
 
-int qxl_gem_init(struct qxl_device *qdev)
+void qxl_gem_init(struct qxl_device *qdev)
 {
 	INIT_LIST_HEAD(&qdev->gem.objects);
-	return 0;
 }
 
 void qxl_gem_fini(struct qxl_device *qdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -131,7 +131,7 @@ static int qxl_device_init(struct qxl_de
 	mutex_init(&qdev->update_area_mutex);
 	mutex_init(&qdev->release_mutex);
 	mutex_init(&qdev->surf_evict_mutex);
-	INIT_LIST_HEAD(&qdev->gem.objects);
+	qxl_gem_init(qdev);
 
 	qdev->rom_base = pci_resource_start(pdev, 2);
 	qdev->rom_size = pci_resource_len(pdev, 2);
@@ -273,6 +273,7 @@ static void qxl_device_fini(struct qxl_d
 	qxl_ring_free(qdev->command_ring);
 	qxl_ring_free(qdev->cursor_ring);
 	qxl_ring_free(qdev->release_ring);
+	qxl_gem_fini(qdev);
 	qxl_bo_fini(qdev);
 	io_mapping_free(qdev->surface_mapping);
 	io_mapping_free(qdev->vram_mapping);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_release.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_release.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_release.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_release.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
  */
 #include "qxl_drv.h"
 #include "qxl_object.h"
-#include <trace/events/fence.h>
+#include <trace/events/dma_fence.h>
 
 /*
  * drawable cmd cache - allocate a bunch of VRAM pages, suballocate
@@ -40,23 +40,24 @@
 static const int release_size_per_bo[] = { RELEASE_SIZE, SURFACE_RELEASE_SIZE, RELEASE_SIZE };
 static const int releases_per_bo[] = { RELEASES_PER_BO, SURFACE_RELEASES_PER_BO, RELEASES_PER_BO };
 
-static const char *qxl_get_driver_name(struct fence *fence)
+static const char *qxl_get_driver_name(struct dma_fence *fence)
 {
 	return "qxl";
 }
 
-static const char *qxl_get_timeline_name(struct fence *fence)
+static const char *qxl_get_timeline_name(struct dma_fence *fence)
 {
 	return "release";
 }
 
-static bool qxl_nop_signaling(struct fence *fence)
+static bool qxl_nop_signaling(struct dma_fence *fence)
 {
 	/* fences are always automatically signaled, so just pretend we did this.. */
 	return true;
 }
 
-static long qxl_fence_wait(struct fence *fence, bool intr, signed long timeout)
+static long qxl_fence_wait(struct dma_fence *fence, bool intr,
+			   signed long timeout)
 {
 	struct qxl_device *qdev;
 	struct qxl_release *release;
@@ -71,7 +72,7 @@ static long qxl_fence_wait(struct fence
 retry:
 	sc++;
 
-	if (fence_is_signaled(fence))
+	if (dma_fence_is_signaled(fence))
 		goto signaled;
 
 	qxl_io_notify_oom(qdev);
@@ -80,11 +81,11 @@ retry:
 		if (!qxl_queue_garbage_collect(qdev, true))
 			break;
 
-		if (fence_is_signaled(fence))
+		if (dma_fence_is_signaled(fence))
 			goto signaled;
 	}
 
-	if (fence_is_signaled(fence))
+	if (dma_fence_is_signaled(fence))
 		goto signaled;
 
 	if (have_drawable_releases || sc < 4) {
@@ -96,9 +97,9 @@ retry:
 			return 0;
 
 		if (have_drawable_releases && sc > 300) {
-			FENCE_WARN(fence, "failed to wait on release %llu "
-					  "after spincount %d\n",
-					  fence->context & ~0xf0000000, sc);
+			DMA_FENCE_WARN(fence, "failed to wait on release %llu "
+				       "after spincount %d\n",
+				       fence->context & ~0xf0000000, sc);
 			goto signaled;
 		}
 		goto retry;
@@ -115,7 +116,7 @@ signaled:
 	return end - cur;
 }
 
-static const struct fence_ops qxl_fence_ops = {
+static const struct dma_fence_ops qxl_fence_ops = {
 	.get_driver_name = qxl_get_driver_name,
 	.get_timeline_name = qxl_get_timeline_name,
 	.enable_signaling = qxl_nop_signaling,
@@ -133,7 +134,7 @@ qxl_release_alloc(struct qxl_device *qde
 	release = kmalloc(size, GFP_KERNEL);
 	if (!release) {
 		DRM_ERROR("Out of memory\n");
-		return 0;
+		return -ENOMEM;
 	}
 	release->base.ops = NULL;
 	release->type = type;
@@ -192,8 +193,8 @@ qxl_release_free(struct qxl_device *qdev
 		WARN_ON(list_empty(&release->bos));
 		qxl_release_free_list(release);
 
-		fence_signal(&release->base);
-		fence_put(&release->base);
+		dma_fence_signal(&release->base);
+		dma_fence_put(&release->base);
 	} else {
 		qxl_release_free_list(release);
 		kfree(release);
@@ -453,9 +454,9 @@ void qxl_release_fence_buffer_objects(st
 	 * Since we never really allocated a context and we don't want to conflict,
 	 * set the highest bits. This will break if we really allow exporting of dma-bufs.
 	 */
-	fence_init(&release->base, &qxl_fence_ops, &qdev->release_lock,
-		   release->id | 0xf0000000, release->base.seqno);
-	trace_fence_emit(&release->base);
+	dma_fence_init(&release->base, &qxl_fence_ops, &qdev->release_lock,
+		       release->id | 0xf0000000, release->base.seqno);
+	trace_dma_fence_emit(&release->base);
 
 	driver = bdev->driver;
 	glob = bo->glob;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/qxl/qxl_ttm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/qxl/qxl_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -387,6 +387,7 @@ static struct ttm_bo_driver qxl_bo_drive
 	.ttm_tt_unpopulate = &qxl_ttm_tt_unpopulate,
 	.invalidate_caches = &qxl_invalidate_caches,
 	.init_mem_type = &qxl_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = &qxl_evict_flags,
 	.move = &qxl_bo_move,
 	.verify_access = &qxl_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1156,7 +1156,7 @@ static int dce4_crtc_do_set_base(struct
 	u32 tmp, viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
-	char *format_name;
+	struct drm_format_name_buf format_name;
 
 	/* no fb bound */
 	if (!atomic && !crtc->primary->fb) {
@@ -1260,9 +1260,8 @@ static int dce4_crtc_do_set_base(struct
 		bypass_lut = true;
 		break;
 	default:
-		format_name = drm_get_format_name(target_fb->pixel_format);
-		DRM_ERROR("Unsupported screen format %s\n", format_name);
-		kfree(format_name);
+		DRM_ERROR("Unsupported screen format %s\n",
+		          drm_get_format_name(target_fb->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
@@ -1473,7 +1472,7 @@ static int avivo_crtc_do_set_base(struct
 	u32 viewport_w, viewport_h;
 	int r;
 	bool bypass_lut = false;
-	char *format_name;
+	struct drm_format_name_buf format_name;
 
 	/* no fb bound */
 	if (!atomic && !crtc->primary->fb) {
@@ -1563,9 +1562,8 @@ static int avivo_crtc_do_set_base(struct
 		bypass_lut = true;
 		break;
 	default:
-		format_name = drm_get_format_name(target_fb->pixel_format);
-		DRM_ERROR("Unsupported screen format %s\n", format_name);
-		kfree(format_name);
+		DRM_ERROR("Unsupported screen format %s\n",
+		          drm_get_format_name(target_fb->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/atombios_encoders.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/atombios_encoders.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/atombios_encoders.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon.h"
 #include "radeon_audio.h"
+#include "radeon_asic.h"
 #include "atom.h"
 #include <linux/backlight.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/evergreen_cs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/evergreen_cs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
  */
 #include <drm/drmP.h>
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "evergreend.h"
 #include "evergreen_reg_safe.h"
 #include "cayman_reg_safe.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/r600_cs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/r600_cs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/r600_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/r600_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/kernel.h>
 #include <drm/drmP.h>
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "r600d.h"
 #include "r600_reg_safe.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,7 @@
 
 #include "atom.h"
 #include "atom-bits.h"
+#include "radeon_asic.h"
 
 extern void
 radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_enum,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_bios.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_bios.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_bios.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_bios.c	2017-02-12 16:03:20.000000000 -0500
@@ -603,8 +603,9 @@ static bool radeon_acpi_vfct_bios(struct
 	GOP_VBIOS_CONTENT *vbios;
 	VFCT_IMAGE_HEADER *vhdr;
 
-	if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
+	if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
 		return false;
+	tbl_size = hdr->length;
 	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
 		DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
 		goto out_unmap;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_clocks.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_clocks.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_clocks.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_clocks.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,7 @@
 #include <drm/radeon_drm.h>
 #include "radeon_reg.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 
 /* 10 khz */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_cursor.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_cursor.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2017-02-12 16:03:20.000000000 -0500
@@ -90,6 +90,9 @@ static void radeon_show_cursor(struct dr
 	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 	struct radeon_device *rdev = crtc->dev->dev_private;
 
+	if (radeon_crtc->cursor_out_of_bounds)
+		return;
+
 	if (ASIC_IS_DCE4(rdev)) {
 		WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
 		       upper_32_bits(radeon_crtc->cursor_addr));
@@ -143,21 +146,25 @@ static int radeon_cursor_move_locked(str
 	int xorigin = 0, yorigin = 0;
 	int w = radeon_crtc->cursor_width;
 
+	radeon_crtc->cursor_x = x;
+	radeon_crtc->cursor_y = y;
+
 	if (ASIC_IS_AVIVO(rdev)) {
 		/* avivo cursor are offset into the total surface */
 		x += crtc->x;
 		y += crtc->y;
 	}
-	DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 
-	if (x < 0) {
+	if (x < 0)
 		xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
-		x = 0;
-	}
-	if (y < 0) {
+	if (y < 0)
 		yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
-		y = 0;
+
+	if (!ASIC_IS_AVIVO(rdev)) {
+		x += crtc->x;
+		y += crtc->y;
 	}
+	DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 
 	/* fixed on DCE6 and newer */
 	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
@@ -180,27 +187,31 @@ static int radeon_cursor_move_locked(str
 		if (i > 1) {
 			int cursor_end, frame_end;
 
-			cursor_end = x - xorigin + w;
+			cursor_end = x + w;
 			frame_end = crtc->x + crtc->mode.crtc_hdisplay;
 			if (cursor_end >= frame_end) {
 				w = w - (cursor_end - frame_end);
 				if (!(frame_end & 0x7f))
 					w--;
-			} else {
-				if (!(cursor_end & 0x7f))
-					w--;
+			} else if (cursor_end <= 0) {
+				goto out_of_bounds;
+			} else if (!(cursor_end & 0x7f)) {
+				w--;
 			}
 			if (w <= 0) {
-				w = 1;
-				cursor_end = x - xorigin + w;
-				if (!(cursor_end & 0x7f)) {
-					x--;
-					WARN_ON_ONCE(x < 0);
-				}
+				goto out_of_bounds;
 			}
 		}
 	}
 
+	if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
+	    x >= (crtc->x + crtc->mode.crtc_hdisplay) ||
+	    y >= (crtc->y + crtc->mode.crtc_vdisplay))
+		goto out_of_bounds;
+
+	x += xorigin;
+	y += yorigin;
+
 	if (ASIC_IS_DCE4(rdev)) {
 		WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
 		WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
@@ -212,6 +223,9 @@ static int radeon_cursor_move_locked(str
 		WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
 		       ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
 	} else {
+		x -= crtc->x;
+		y -= crtc->y;
+
 		if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
 			y *= 2;
 
@@ -229,9 +243,19 @@ static int radeon_cursor_move_locked(str
 		       yorigin * 256);
 	}
 
-	radeon_crtc->cursor_x = x;
-	radeon_crtc->cursor_y = y;
+	if (radeon_crtc->cursor_out_of_bounds) {
+		radeon_crtc->cursor_out_of_bounds = false;
+		if (radeon_crtc->cursor_bo)
+			radeon_show_cursor(crtc);
+	}
+
+	return 0;
 
+ out_of_bounds:
+	if (!radeon_crtc->cursor_out_of_bounds) {
+		radeon_hide_cursor(crtc);
+		radeon_crtc->cursor_out_of_bounds = true;
+	}
 	return 0;
 }
 
@@ -297,22 +321,23 @@ int radeon_crtc_cursor_set2(struct drm_c
 		return ret;
 	}
 
-	radeon_crtc->cursor_width = width;
-	radeon_crtc->cursor_height = height;
-
 	radeon_lock_cursor(crtc, true);
 
-	if (hot_x != radeon_crtc->cursor_hot_x ||
+	if (width != radeon_crtc->cursor_width ||
+	    height != radeon_crtc->cursor_height ||
+	    hot_x != radeon_crtc->cursor_hot_x ||
 	    hot_y != radeon_crtc->cursor_hot_y) {
 		int x, y;
 
 		x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
 		y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
 
-		radeon_cursor_move_locked(crtc, x, y);
-
+		radeon_crtc->cursor_width = width;
+		radeon_crtc->cursor_height = height;
 		radeon_crtc->cursor_hot_x = hot_x;
 		radeon_crtc->cursor_hot_y = hot_y;
+
+		radeon_cursor_move_locked(crtc, x, y);
 	}
 
 	radeon_show_cursor(crtc);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_device.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -1333,7 +1333,7 @@ int radeon_device_init(struct radeon_dev
 	for (i = 0; i < RADEON_NUM_RINGS; i++) {
 		rdev->ring[i].idx = i;
 	}
-	rdev->fence_context = fence_context_alloc(RADEON_NUM_RINGS);
+	rdev->fence_context = dma_fence_context_alloc(RADEON_NUM_RINGS);
 
 	DRM_INFO("initializing kernel modesetting (%s 0x%04X:0x%04X 0x%04X:0x%04X 0x%02X).\n",
 		 radeon_family_name[rdev->family], pdev->vendor, pdev->device,
@@ -1664,7 +1664,10 @@ int radeon_suspend_kms(struct drm_device
 
 	radeon_suspend(rdev);
 	radeon_hpd_fini(rdev);
-	/* evict remaining vram memory */
+	/* evict remaining vram memory
+	 * This second call to evict vram is to evict the gart page table
+	 * using the CPU.
+	 */
 	radeon_bo_evict_vram(rdev);
 
 	radeon_agp_suspend(rdev);
@@ -1946,9 +1949,6 @@ int radeon_debugfs_add_files(struct rade
 	rdev->debugfs_count = i;
 #if defined(CONFIG_DEBUG_FS)
 	drm_debugfs_create_files(files, nfiles,
-				 rdev->ddev->control->debugfs_root,
-				 rdev->ddev->control);
-	drm_debugfs_create_files(files, nfiles,
 				 rdev->ddev->primary->debugfs_root,
 				 rdev->ddev->primary);
 #endif
@@ -1963,9 +1963,6 @@ static void radeon_debugfs_remove_files(
 	for (i = 0; i < rdev->debugfs_count; i++) {
 		drm_debugfs_remove_files(rdev->debugfs[i].files,
 					 rdev->debugfs[i].num_files,
-					 rdev->ddev->control);
-		drm_debugfs_remove_files(rdev->debugfs[i].files,
-					 rdev->debugfs[i].num_files,
 					 rdev->ddev->primary);
 	}
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_display.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_display.c	2017-02-12 16:03:20.000000000 -0500
@@ -437,7 +437,7 @@ static void radeon_flip_work_func(struct
 				down_read(&rdev->exclusive_lock);
 			}
 		} else
-			r = fence_wait(work->fence, false);
+			r = dma_fence_wait(work->fence, false);
 
 		if (r)
 			DRM_ERROR("failed to wait on page flip fence (%d)!\n", r);
@@ -447,7 +447,7 @@ static void radeon_flip_work_func(struct
 		 * confused about which BO the CRTC is scanning out
 		 */
 
-		fence_put(work->fence);
+		dma_fence_put(work->fence);
 		work->fence = NULL;
 	}
 
@@ -542,7 +542,7 @@ static int radeon_crtc_page_flip_target(
 		DRM_ERROR("failed to pin new rbo buffer before flip\n");
 		goto cleanup;
 	}
-	work->fence = fence_get(reservation_object_get_excl(new_rbo->tbo.resv));
+	work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.resv));
 	radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL);
 	radeon_bo_unreserve(new_rbo);
 
@@ -617,7 +617,7 @@ pflip_cleanup:
 
 cleanup:
 	drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
-	fence_put(work->fence);
+	dma_fence_put(work->fence);
 	kfree(work);
 	return r;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_dp_mst.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_dp_mst.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_dp_mst.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_dp_mst.c	2017-02-12 16:03:20.000000000 -0500
@@ -223,7 +223,8 @@ radeon_dp_mst_mode_valid(struct drm_conn
 	return MODE_OK;
 }
 
-struct drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
+static struct
+drm_encoder *radeon_mst_best_encoder(struct drm_connector *connector)
 {
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
@@ -341,7 +342,8 @@ const struct drm_dp_mst_topology_cbs mst
 	.hotplug = radeon_dp_mst_hotplug,
 };
 
-struct radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder)
+static struct
+radeon_connector *radeon_mst_find_connector(struct drm_encoder *encoder)
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_connector *connector;
@@ -597,7 +599,7 @@ static const struct drm_encoder_helper_f
 	.commit = radeon_mst_encoder_commit,
 };
 
-void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder)
+static void radeon_dp_mst_encoder_destroy(struct drm_encoder *encoder)
 {
 	drm_encoder_cleanup(encoder);
 	kfree(encoder);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -97,9 +97,10 @@
  *   2.46.0 - Add PFP_SYNC_ME support on evergreen
  *   2.47.0 - Add UVD_NO_OP register support
  *   2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI
+ *   2.49.0 - DRM_RADEON_GEM_INFO ioctl returns correct vram_size/visible values
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	48
+#define KMS_DRIVER_MINOR	49
 #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);
@@ -366,11 +367,10 @@ static void
 radeon_pci_shutdown(struct pci_dev *pdev)
 {
 	/* if we are running in a VM, make sure the device
-	 * torn down properly on reboot/shutdown.
-	 * unfortunately we can't detect certain
-	 * hypervisors so just do this all the time.
+	 * torn down properly on reboot/shutdown
 	 */
-	radeon_pci_remove(pdev);
+	if (radeon_device_is_virtual())
+		radeon_pci_remove(pdev);
 }
 
 static int radeon_pmops_suspend(struct device *dev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,28 +74,22 @@ radeonfb_release(struct fb_info *info, i
 
 static struct fb_ops radeonfb_ops = {
 	.owner = THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_open = radeonfb_open,
 	.fb_release = radeonfb_release,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
 	.fb_fillrect = drm_fb_helper_cfb_fillrect,
 	.fb_copyarea = drm_fb_helper_cfb_copyarea,
 	.fb_imageblit = drm_fb_helper_cfb_imageblit,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 
-int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
+int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool tiled)
 {
 	int aligned = width;
 	int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
 	int pitch_mask = 0;
 
-	switch (bpp / 8) {
+	switch (cpp) {
 	case 1:
 		pitch_mask = align_large ? 255 : 127;
 		break;
@@ -110,7 +104,7 @@ int radeon_align_pitch(struct radeon_dev
 
 	aligned += pitch_mask;
 	aligned &= ~pitch_mask;
-	return aligned;
+	return aligned * cpp;
 }
 
 static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
@@ -139,13 +133,13 @@ static int radeonfb_create_pinned_object
 	int ret;
 	int aligned_size, size;
 	int height = mode_cmd->height;
-	u32 bpp, depth;
+	u32 cpp;
 
-	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
+	cpp = drm_format_plane_cpp(mode_cmd->pixel_format, 0);
 
 	/* need to align pitch with crtc limits */
-	mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, bpp,
-						  fb_tiled) * ((bpp + 1) / 8);
+	mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp,
+						  fb_tiled);
 
 	if (rdev->family >= CHIP_R600)
 		height = ALIGN(mode_cmd->height, 8);
@@ -165,11 +159,11 @@ static int radeonfb_create_pinned_object
 		tiling_flags = RADEON_TILING_MACRO;
 
 #ifdef __BIG_ENDIAN
-	switch (bpp) {
-	case 32:
+	switch (cpp) {
+	case 4:
 		tiling_flags |= RADEON_TILING_SWAP_32BIT;
 		break;
-	case 16:
+	case 2:
 		tiling_flags |= RADEON_TILING_SWAP_16BIT;
 	default:
 		break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -141,8 +141,10 @@ int radeon_fence_emit(struct radeon_devi
 	(*fence)->seq = seq = ++rdev->fence_drv[ring].sync_seq[ring];
 	(*fence)->ring = ring;
 	(*fence)->is_vm_update = false;
-	fence_init(&(*fence)->base, &radeon_fence_ops,
-		   &rdev->fence_queue.lock, rdev->fence_context + ring, seq);
+	dma_fence_init(&(*fence)->base, &radeon_fence_ops,
+		       &rdev->fence_queue.lock,
+		       rdev->fence_context + ring,
+		       seq);
 	radeon_fence_ring_emit(rdev, ring, *fence);
 	trace_radeon_fence_emit(rdev->ddev, ring, (*fence)->seq);
 	radeon_fence_schedule_check(rdev, ring);
@@ -169,18 +171,18 @@ static int radeon_fence_check_signaled(w
 	 */
 	seq = atomic64_read(&fence->rdev->fence_drv[fence->ring].last_seq);
 	if (seq >= fence->seq) {
-		int ret = fence_signal_locked(&fence->base);
+		int ret = dma_fence_signal_locked(&fence->base);
 
 		if (!ret)
-			FENCE_TRACE(&fence->base, "signaled from irq context\n");
+			DMA_FENCE_TRACE(&fence->base, "signaled from irq context\n");
 		else
-			FENCE_TRACE(&fence->base, "was already signaled\n");
+			DMA_FENCE_TRACE(&fence->base, "was already signaled\n");
 
 		radeon_irq_kms_sw_irq_put(fence->rdev, fence->ring);
 		__remove_wait_queue(&fence->rdev->fence_queue, &fence->fence_wake);
-		fence_put(&fence->base);
+		dma_fence_put(&fence->base);
 	} else
-		FENCE_TRACE(&fence->base, "pending\n");
+		DMA_FENCE_TRACE(&fence->base, "pending\n");
 	return 0;
 }
 
@@ -351,7 +353,7 @@ static bool radeon_fence_seq_signaled(st
 	return false;
 }
 
-static bool radeon_fence_is_signaled(struct fence *f)
+static bool radeon_fence_is_signaled(struct dma_fence *f)
 {
 	struct radeon_fence *fence = to_radeon_fence(f);
 	struct radeon_device *rdev = fence->rdev;
@@ -381,7 +383,7 @@ static bool radeon_fence_is_signaled(str
  * to fence_queue that checks if this fence is signaled, and if so it
  * signals the fence and removes itself.
  */
-static bool radeon_fence_enable_signaling(struct fence *f)
+static bool radeon_fence_enable_signaling(struct dma_fence *f)
 {
 	struct radeon_fence *fence = to_radeon_fence(f);
 	struct radeon_device *rdev = fence->rdev;
@@ -414,9 +416,9 @@ static bool radeon_fence_enable_signalin
 	fence->fence_wake.private = NULL;
 	fence->fence_wake.func = radeon_fence_check_signaled;
 	__add_wait_queue(&rdev->fence_queue, &fence->fence_wake);
-	fence_get(f);
+	dma_fence_get(f);
 
-	FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring);
+	DMA_FENCE_TRACE(&fence->base, "armed on ring %i!\n", fence->ring);
 	return true;
 }
 
@@ -436,9 +438,9 @@ bool radeon_fence_signaled(struct radeon
 	if (radeon_fence_seq_signaled(fence->rdev, fence->seq, fence->ring)) {
 		int ret;
 
-		ret = fence_signal(&fence->base);
+		ret = dma_fence_signal(&fence->base);
 		if (!ret)
-			FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n");
+			DMA_FENCE_TRACE(&fence->base, "signaled from radeon_fence_signaled\n");
 		return true;
 	}
 	return false;
@@ -552,7 +554,7 @@ long radeon_fence_wait_timeout(struct ra
 	 * exclusive_lock is not held in that case.
 	 */
 	if (WARN_ON_ONCE(!to_radeon_fence(&fence->base)))
-		return fence_wait(&fence->base, intr);
+		return dma_fence_wait(&fence->base, intr);
 
 	seq[fence->ring] = fence->seq;
 	r = radeon_fence_wait_seq_timeout(fence->rdev, seq, intr, timeout);
@@ -560,9 +562,9 @@ long radeon_fence_wait_timeout(struct ra
 		return r;
 	}
 
-	r_sig = fence_signal(&fence->base);
+	r_sig = dma_fence_signal(&fence->base);
 	if (!r_sig)
-		FENCE_TRACE(&fence->base, "signaled from fence_wait\n");
+		DMA_FENCE_TRACE(&fence->base, "signaled from fence_wait\n");
 	return r;
 }
 
@@ -697,7 +699,7 @@ int radeon_fence_wait_empty(struct radeo
  */
 struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence)
 {
-	fence_get(&fence->base);
+	dma_fence_get(&fence->base);
 	return fence;
 }
 
@@ -714,7 +716,7 @@ void radeon_fence_unref(struct radeon_fe
 
 	*fence = NULL;
 	if (tmp) {
-		fence_put(&tmp->base);
+		dma_fence_put(&tmp->base);
 	}
 }
 
@@ -1028,12 +1030,12 @@ int radeon_debugfs_fence_init(struct rad
 #endif
 }
 
-static const char *radeon_fence_get_driver_name(struct fence *fence)
+static const char *radeon_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "radeon";
 }
 
-static const char *radeon_fence_get_timeline_name(struct fence *f)
+static const char *radeon_fence_get_timeline_name(struct dma_fence *f)
 {
 	struct radeon_fence *fence = to_radeon_fence(f);
 	switch (fence->ring) {
@@ -1051,16 +1053,16 @@ static const char *radeon_fence_get_time
 
 static inline bool radeon_test_signaled(struct radeon_fence *fence)
 {
-	return test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
+	return test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags);
 }
 
 struct radeon_wait_cb {
-	struct fence_cb base;
+	struct dma_fence_cb base;
 	struct task_struct *task;
 };
 
 static void
-radeon_fence_wait_cb(struct fence *fence, struct fence_cb *cb)
+radeon_fence_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
 {
 	struct radeon_wait_cb *wait =
 		container_of(cb, struct radeon_wait_cb, base);
@@ -1068,7 +1070,7 @@ radeon_fence_wait_cb(struct fence *fence
 	wake_up_process(wait->task);
 }
 
-static signed long radeon_fence_default_wait(struct fence *f, bool intr,
+static signed long radeon_fence_default_wait(struct dma_fence *f, bool intr,
 					     signed long t)
 {
 	struct radeon_fence *fence = to_radeon_fence(f);
@@ -1077,7 +1079,7 @@ static signed long radeon_fence_default_
 
 	cb.task = current;
 
-	if (fence_add_callback(f, &cb.base, radeon_fence_wait_cb))
+	if (dma_fence_add_callback(f, &cb.base, radeon_fence_wait_cb))
 		return t;
 
 	while (t > 0) {
@@ -1105,12 +1107,12 @@ static signed long radeon_fence_default_
 	}
 
 	__set_current_state(TASK_RUNNING);
-	fence_remove_callback(f, &cb.base);
+	dma_fence_remove_callback(f, &cb.base);
 
 	return t;
 }
 
-const struct fence_ops radeon_fence_ops = {
+const struct dma_fence_ops radeon_fence_ops = {
 	.get_driver_name = radeon_fence_get_driver_name,
 	.get_timeline_name = radeon_fence_get_timeline_name,
 	.enable_signaling = radeon_fence_enable_signaling,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -220,8 +220,8 @@ int radeon_gem_info_ioctl(struct drm_dev
 
 	man = &rdev->mman.bdev.man[TTM_PL_VRAM];
 
-	args->vram_size = rdev->mc.real_vram_size;
-	args->vram_visible = (u64)man->size << PAGE_SHIFT;
+	args->vram_size = (u64)man->size << PAGE_SHIFT;
+	args->vram_visible = rdev->mc.visible_vram_size;
 	args->vram_visible -= rdev->vram_pin_size;
 	args->gart_size = rdev->mc.gtt_size;
 	args->gart_size -= rdev->gart_pin_size;
@@ -745,7 +745,8 @@ int radeon_mode_dumb_create(struct drm_f
 	uint32_t handle;
 	int r;
 
-	args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
+	args->pitch = radeon_align_pitch(rdev, args->width,
+					 DIV_ROUND_UP(args->bpp, 8), 0);
 	args->size = args->pitch * args->height;
 	args->size = ALIGN(args->size, PAGE_SIZE);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon.h	2017-02-12 16:03:20.000000000 -0500
@@ -66,7 +66,7 @@
 #include <linux/kref.h>
 #include <linux/interval_tree.h>
 #include <linux/hashtable.h>
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 #include <ttm/ttm_bo_api.h>
 #include <ttm/ttm_bo_driver.h>
@@ -367,7 +367,7 @@ struct radeon_fence_driver {
 };
 
 struct radeon_fence {
-	struct fence		base;
+	struct dma_fence		base;
 
 	struct radeon_device	*rdev;
 	uint64_t		seq;
@@ -746,7 +746,7 @@ struct radeon_flip_work {
 	uint64_t			base;
 	struct drm_pending_vblank_event *event;
 	struct radeon_bo		*old_rbo;
-	struct fence			*fence;
+	struct dma_fence		*fence;
 	bool				async;
 };
 
@@ -2514,9 +2514,9 @@ void cik_mm_wdoorbell(struct radeon_devi
 /*
  * Cast helper
  */
-extern const struct fence_ops radeon_fence_ops;
+extern const struct dma_fence_ops radeon_fence_ops;
 
-static inline struct radeon_fence *to_radeon_fence(struct fence *f)
+static inline struct radeon_fence *to_radeon_fence(struct dma_fence *f)
 {
 	struct radeon_fence *__f = container_of(f, struct radeon_fence, base);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/radeon_drm.h>
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 #include <linux/backlight.h>
 #ifdef CONFIG_PMAC_BACKLIGHT
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2017-02-12 16:03:20.000000000 -0500
@@ -330,6 +330,7 @@ struct radeon_crtc {
 	u16 lut_r[256], lut_g[256], lut_b[256];
 	bool enabled;
 	bool can_tile;
+	bool cursor_out_of_bounds;
 	uint32_t crtc_offset;
 	struct drm_gem_object *cursor_bo;
 	uint64_t cursor_addr;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,7 @@ static bool radeon_pm_in_vbl(struct rade
 static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish);
 static void radeon_pm_update_profile(struct radeon_device *rdev);
 static void radeon_pm_set_clocks(struct radeon_device *rdev);
+static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev);
 
 int radeon_pm_get_type_index(struct radeon_device *rdev,
 			     enum radeon_pm_state_type ps_type,
@@ -79,6 +80,8 @@ void radeon_pm_acpi_event_handler(struct
 				radeon_dpm_enable_bapm(rdev, rdev->pm.dpm.ac_power);
 		}
 		mutex_unlock(&rdev->pm.mutex);
+		/* allow new DPM state to be picked */
+		radeon_pm_compute_clocks_dpm(rdev);
 	} else if (rdev->pm.pm_method == PM_METHOD_PROFILE) {
 		if (rdev->pm.profile == PM_PROFILE_AUTO) {
 			mutex_lock(&rdev->pm.mutex);
@@ -882,7 +885,8 @@ static struct radeon_ps *radeon_dpm_pick
 		dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF;
 	/* balanced states don't exist at the moment */
 	if (dpm_state == POWER_STATE_TYPE_BALANCED)
-		dpm_state = POWER_STATE_TYPE_PERFORMANCE;
+		dpm_state = rdev->pm.dpm.ac_power ?
+			POWER_STATE_TYPE_PERFORMANCE : POWER_STATE_TYPE_BATTERY;
 
 restart_search:
 	/* Pick the best power state based on current conditions */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_sync.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_sync.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_sync.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_sync.c	2017-02-12 16:03:20.000000000 -0500
@@ -92,7 +92,7 @@ int radeon_sync_resv(struct radeon_devic
 		     bool shared)
 {
 	struct reservation_object_list *flist;
-	struct fence *f;
+	struct dma_fence *f;
 	struct radeon_fence *fence;
 	unsigned i;
 	int r = 0;
@@ -103,7 +103,7 @@ int radeon_sync_resv(struct radeon_devic
 	if (fence && fence->rdev == rdev)
 		radeon_sync_fence(sync, fence);
 	else if (f)
-		r = fence_wait(f, true);
+		r = dma_fence_wait(f, true);
 
 	flist = reservation_object_get_list(resv);
 	if (shared || !flist || r)
@@ -116,7 +116,7 @@ int radeon_sync_resv(struct radeon_devic
 		if (fence && fence->rdev == rdev)
 			radeon_sync_fence(sync, fence);
 		else
-			r = fence_wait(f, true);
+			r = dma_fence_wait(f, true);
 
 		if (r)
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -863,6 +863,7 @@ static struct ttm_bo_driver radeon_bo_dr
 	.ttm_tt_unpopulate = &radeon_ttm_tt_unpopulate,
 	.invalidate_caches = &radeon_invalidate_caches,
 	.init_mem_type = &radeon_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = &radeon_evict_flags,
 	.move = &radeon_bo_move,
 	.verify_access = &radeon_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_uvd.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_uvd.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/radeon_uvd.c	2016-12-11 17:42:56.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/radeon_uvd.c	2017-02-12 17:26:37.000000000 -0500
@@ -459,7 +459,7 @@ static int radeon_uvd_cs_msg(struct rade
 {
 	int32_t *msg, msg_type, handle;
 	unsigned img_size = 0;
-	struct fence *f;
+	struct dma_fence *f;
 	void *ptr;
 
 	int i, r;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/si.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/si.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/si.c	2016-12-11 17:42:46.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/si.c	2017-02-12 17:26:24.000000000 -0500
@@ -1573,15 +1573,14 @@ static int si_init_microcode(struct rade
 	int err;
 	int new_fw = 0;
 	bool new_smc = false;
+	bool si58_fw = false;
+	bool banks2_fw = false;
 
 	DRM_DEBUG("\n");
 
 	switch (rdev->family) {
 	case CHIP_TAHITI:
 		chip_name = "TAHITI";
-		/* XXX: figure out which Tahitis need the new ucode */
-		if (0)
-			new_smc = true;
 		new_chip_name = "tahiti";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1593,12 +1592,9 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_PITCAIRN:
 		chip_name = "PITCAIRN";
-		if ((rdev->pdev->revision == 0x81) ||
-		    (rdev->pdev->device == 0x6810) ||
-		    (rdev->pdev->device == 0x6811) ||
-		    (rdev->pdev->device == 0x6816) ||
-		    (rdev->pdev->device == 0x6817) ||
-		    (rdev->pdev->device == 0x6806))
+		if ((rdev->pdev->revision == 0x81) &&
+		    ((rdev->pdev->device == 0x6810) ||
+		     (rdev->pdev->device == 0x6811)))
 			new_smc = true;
 		new_chip_name = "pitcairn";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
@@ -1611,15 +1607,15 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_VERDE:
 		chip_name = "VERDE";
-		if ((rdev->pdev->revision == 0x81) ||
-		    (rdev->pdev->revision == 0x83) ||
-		    (rdev->pdev->revision == 0x87) ||
-		    (rdev->pdev->device == 0x6820) ||
-		    (rdev->pdev->device == 0x6821) ||
-		    (rdev->pdev->device == 0x6822) ||
-		    (rdev->pdev->device == 0x6823) ||
-		    (rdev->pdev->device == 0x682A) ||
-		    (rdev->pdev->device == 0x682B))
+		if (((rdev->pdev->device == 0x6820) &&
+		     ((rdev->pdev->revision == 0x81) ||
+		      (rdev->pdev->revision == 0x83))) ||
+		    ((rdev->pdev->device == 0x6821) &&
+		     ((rdev->pdev->revision == 0x83) ||
+		      (rdev->pdev->revision == 0x87))) ||
+		    ((rdev->pdev->revision == 0x87) &&
+		     ((rdev->pdev->device == 0x6823) ||
+		      (rdev->pdev->device == 0x682b))))
 			new_smc = true;
 		new_chip_name = "verde";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
@@ -1632,12 +1628,13 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_OLAND:
 		chip_name = "OLAND";
-		if ((rdev->pdev->revision == 0xC7) ||
-		    (rdev->pdev->revision == 0x80) ||
-		    (rdev->pdev->revision == 0x81) ||
-		    (rdev->pdev->revision == 0x83) ||
-		    (rdev->pdev->device == 0x6604) ||
-		    (rdev->pdev->device == 0x6605))
+		if (((rdev->pdev->revision == 0x81) &&
+		     ((rdev->pdev->device == 0x6600) ||
+		      (rdev->pdev->device == 0x6604) ||
+		      (rdev->pdev->device == 0x6605) ||
+		      (rdev->pdev->device == 0x6610))) ||
+		    ((rdev->pdev->revision == 0x83) &&
+		     (rdev->pdev->device == 0x6610)))
 			new_smc = true;
 		new_chip_name = "oland";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
@@ -1649,13 +1646,17 @@ static int si_init_microcode(struct rade
 		break;
 	case CHIP_HAINAN:
 		chip_name = "HAINAN";
-		if ((rdev->pdev->revision == 0x81) ||
-		    (rdev->pdev->revision == 0x83) ||
-		    (rdev->pdev->revision == 0xC3) ||
-		    (rdev->pdev->device == 0x6664) ||
-		    (rdev->pdev->device == 0x6665) ||
-		    (rdev->pdev->device == 0x6667))
+		if (((rdev->pdev->revision == 0x81) &&
+		     (rdev->pdev->device == 0x6660)) ||
+		    ((rdev->pdev->revision == 0x83) &&
+		     ((rdev->pdev->device == 0x6660) ||
+		      (rdev->pdev->device == 0x6663) ||
+		      (rdev->pdev->device == 0x6665) ||
+		      (rdev->pdev->device == 0x6667))))
 			new_smc = true;
+		else if ((rdev->pdev->revision == 0xc3) &&
+			 (rdev->pdev->device == 0x6665))
+			banks2_fw = true;
 		new_chip_name = "hainan";
 		pfp_req_size = SI_PFP_UCODE_SIZE * 4;
 		me_req_size = SI_PM4_UCODE_SIZE * 4;
@@ -1667,6 +1668,10 @@ static int si_init_microcode(struct rade
 	default: BUG();
 	}
 
+	/* this memory configuration requires special firmware */
+	if (((RREG32(MC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
+		si58_fw = true;
+
 	DRM_INFO("Loading %s Microcode\n", new_chip_name);
 
 	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
@@ -1770,7 +1775,10 @@ static int si_init_microcode(struct rade
 		}
 	}
 
-	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
+	if (si58_fw)
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/");
+	else
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	err = reject_firmware(&rdev->mc_fw, fw_name, rdev->dev);
 	if (err) {
 		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
@@ -1801,7 +1809,9 @@ static int si_init_microcode(struct rade
 		}
 	}
 
-	if (new_smc)
+	if (banks2_fw)
+		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/");
+	else if (new_smc)
 		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
 	else
 		snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", new_chip_name);
@@ -7780,7 +7790,7 @@ static void si_program_aspm(struct radeo
 	}
 }
 
-int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev)
+static int si_vce_send_vcepll_ctlreq(struct radeon_device *rdev)
 {
 	unsigned i;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/radeon/si_dpm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/si_dpm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/radeon/si_dpm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/radeon/si_dpm.c	2017-02-12 16:03:20.000000000 -0500
@@ -3008,29 +3008,6 @@ static void si_apply_state_adjust_rules(
 		    (rdev->pdev->device == 0x6817) ||
 		    (rdev->pdev->device == 0x6806))
 			max_mclk = 120000;
-	} else if (rdev->family == CHIP_VERDE) {
-		if ((rdev->pdev->revision == 0x81) ||
-		    (rdev->pdev->revision == 0x83) ||
-		    (rdev->pdev->revision == 0x87) ||
-		    (rdev->pdev->device == 0x6820) ||
-		    (rdev->pdev->device == 0x6821) ||
-		    (rdev->pdev->device == 0x6822) ||
-		    (rdev->pdev->device == 0x6823) ||
-		    (rdev->pdev->device == 0x682A) ||
-		    (rdev->pdev->device == 0x682B)) {
-			max_sclk = 75000;
-			max_mclk = 80000;
-		}
-	} else if (rdev->family == CHIP_OLAND) {
-		if ((rdev->pdev->revision == 0xC7) ||
-		    (rdev->pdev->revision == 0x80) ||
-		    (rdev->pdev->revision == 0x81) ||
-		    (rdev->pdev->revision == 0x83) ||
-		    (rdev->pdev->device == 0x6604) ||
-		    (rdev->pdev->device == 0x6605)) {
-			max_sclk = 75000;
-			max_mclk = 80000;
-		}
 	} else if (rdev->family == CHIP_HAINAN) {
 		if ((rdev->pdev->revision == 0x81) ||
 		    (rdev->pdev->revision == 0x83) ||
@@ -3039,7 +3016,6 @@ static void si_apply_state_adjust_rules(
 		    (rdev->pdev->device == 0x6665) ||
 		    (rdev->pdev->device == 0x6667)) {
 			max_sclk = 75000;
-			max_mclk = 80000;
 		}
 	}
 	/* Apply dpm quirks */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -149,8 +149,8 @@ static void rcar_du_crtc_set_display_tim
 	rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);
 
 	/* Signal polarities */
-	value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
-	      | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL)
+	value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
+	      | ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
 	      | DSMR_DIPM_DISP | DSMR_CSPM;
 	rcar_du_crtc_write(rcrtc, DSMR, value);
 
@@ -172,7 +172,7 @@ static void rcar_du_crtc_set_display_tim
 					mode->crtc_vsync_start - 1);
 	rcar_du_crtc_write(rcrtc, VCR,  mode->crtc_vtotal - 1);
 
-	rcar_du_crtc_write(rcrtc, DESR,  mode->htotal - mode->hsync_start);
+	rcar_du_crtc_write(rcrtc, DESR,  mode->htotal - mode->hsync_start - 1);
 	rcar_du_crtc_write(rcrtc, DEWR,  mode->hdisplay);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,6 +110,27 @@ static const struct rcar_du_device_info
 	.num_lvds = 1,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7792_info = {
+	.gen = 2,
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+	.num_crtcs = 2,
+	.routes = {
+		/* R8A7792 has two RGB outputs. */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(0),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 0,
+		},
+		[RCAR_DU_OUTPUT_DPAD1] = {
+			.possible_crtcs = BIT(1),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 1,
+		},
+	},
+	.num_lvds = 0,
+};
+
 static const struct rcar_du_device_info rcar_du_r8a7794_info = {
 	.gen = 2,
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
@@ -157,13 +178,39 @@ static const struct rcar_du_device_info
 	.num_lvds = 1,
 };
 
+static const struct rcar_du_device_info rcar_du_r8a7796_info = {
+	.gen = 3,
+	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
+		  | RCAR_DU_FEATURE_EXT_CTRL_REGS
+		  | RCAR_DU_FEATURE_VSP1_SOURCE,
+	.num_crtcs = 3,
+	.routes = {
+		/* R8A7796 has one RGB output, one LVDS output and one
+		 * (currently unsupported) HDMI output.
+		 */
+		[RCAR_DU_OUTPUT_DPAD0] = {
+			.possible_crtcs = BIT(2),
+			.encoder_type = DRM_MODE_ENCODER_NONE,
+			.port = 0,
+		},
+		[RCAR_DU_OUTPUT_LVDS0] = {
+			.possible_crtcs = BIT(0),
+			.encoder_type = DRM_MODE_ENCODER_LVDS,
+			.port = 2,
+		},
+	},
+	.num_lvds = 1,
+};
+
 static const struct of_device_id rcar_du_of_table[] = {
 	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
 	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
 	{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
+	{ .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info },
 	{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
 	{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
 	{ .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
+	{ .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
 	{ }
 };
 
@@ -201,9 +248,7 @@ static const struct file_operations rcar
 	.open		= drm_open,
 	.release	= drm_release,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl	= drm_compat_ioctl,
-#endif
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.llseek		= no_llseek,
@@ -285,7 +330,6 @@ static int rcar_du_remove(struct platfor
 
 	drm_kms_helper_poll_fini(ddev);
 	drm_mode_config_cleanup(ddev);
-	drm_vblank_cleanup(ddev);
 
 	drm_dev_unref(ddev);
 
@@ -294,18 +338,12 @@ static int rcar_du_remove(struct platfor
 
 static int rcar_du_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
 	struct rcar_du_device *rcdu;
 	struct drm_device *ddev;
 	struct resource *mem;
 	int ret;
 
-	if (np == NULL) {
-		dev_err(&pdev->dev, "no device tree node\n");
-		return -ENODEV;
-	}
-
-	/* Allocate and initialize the DRM and R-Car device structures. */
+	/* Allocate and initialize the R-Car device structure. */
 	rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
 	if (rcdu == NULL)
 		return -ENOMEM;
@@ -315,31 +353,22 @@ static int rcar_du_probe(struct platform
 	rcdu->dev = &pdev->dev;
 	rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
 
-	ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
-	if (IS_ERR(ddev))
-		return PTR_ERR(ddev);
-
-	rcdu->ddev = ddev;
-	ddev->dev_private = rcdu;
-
 	platform_set_drvdata(pdev, rcdu);
 
 	/* I/O resources */
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
-	if (IS_ERR(rcdu->mmio)) {
-		ret = PTR_ERR(rcdu->mmio);
-		goto error;
-	}
-
-	/* Initialize vertical blanking interrupts handling. Start with vblank
-	 * disabled for all CRTCs.
-	 */
-	ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
-	if (ret < 0)
-		goto error;
+	if (IS_ERR(rcdu->mmio))
+		return PTR_ERR(rcdu->mmio);
 
 	/* DRM/KMS objects */
+	ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
+	if (IS_ERR(ddev))
+		return PTR_ERR(ddev);
+
+	rcdu->ddev = ddev;
+	ddev->dev_private = rcdu;
+
 	ret = rcar_du_modeset_init(rcdu);
 	if (ret < 0) {
 		if (ret != -EPROBE_DEFER)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_group.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_group.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_group.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_group.c	2017-02-12 16:03:20.000000000 -0500
@@ -105,16 +105,20 @@ static void rcar_du_group_setup(struct r
 	if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
 		rcar_du_group_setup_defr8(rgrp);
 
-		/* Configure input dot clock routing. We currently hardcode the
-		 * configuration to routing DOTCLKINn to DUn.
+		/*
+		 * Configure input dot clock routing. We currently hardcode the
+		 * configuration to routing DOTCLKINn to DUn. Register fields
+		 * depend on the DU generation, but the resulting value is 0 in
+		 * all cases.
+		 *
+		 * On Gen2 a single register in the first group controls dot
+		 * clock selection for all channels, while on Gen3 dot clocks
+		 * are setup through per-group registers, only available when
+		 * the group has two channels.
 		 */
-		rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE |
-				    DIDSR_LCDS_DCLKIN(2) |
-				    DIDSR_LCDS_DCLKIN(1) |
-				    DIDSR_LCDS_DCLKIN(0) |
-				    DIDSR_PDCS_CLK(2, 0) |
-				    DIDSR_PDCS_CLK(1, 0) |
-				    DIDSR_PDCS_CLK(0, 0));
+		if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
+		    (rcdu->info->gen == 3 &&  rgrp->num_crtcs > 1))
+			rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
 	}
 
 	if (rcdu->info->gen >= 3)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,7 +108,7 @@ int rcar_du_hdmienc_init(struct rcar_du_
 	if (hdmienc == NULL)
 		return -ENOMEM;
 
-	/* Locate drm bridge from the hdmi encoder DT node */
+	/* Locate the DRM bridge from the HDMI encoder DT node. */
 	bridge = of_drm_find_bridge(np);
 	if (!bridge)
 		return -EPROBE_DEFER;
@@ -123,7 +123,7 @@ int rcar_du_hdmienc_init(struct rcar_du_
 	renc->hdmi = hdmienc;
 	hdmienc->renc = renc;
 
-	/* Link drm_bridge to encoder */
+	/* Link the bridge to the encoder. */
 	bridge->encoder = encoder;
 	encoder->bridge = bridge;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -272,7 +272,7 @@ static void rcar_du_atomic_complete(stru
 
 	drm_atomic_helper_cleanup_planes(dev, old_state);
 
-	drm_atomic_state_free(old_state);
+	drm_atomic_state_put(old_state);
 
 	/* Complete the commit, wake up any waiter. */
 	spin_lock(&rcdu->commit.wait.lock);
@@ -338,6 +338,7 @@ static int rcar_du_atomic_commit(struct
 	/* Swap the state, this is the point of no return. */
 	drm_atomic_helper_swap_state(state, true);
 
+	drm_atomic_state_get(state);
 	if (nonblock)
 		schedule_work(&commit->work);
 	else
@@ -453,13 +454,13 @@ static int rcar_du_encoders_init_one(str
 	}
 
 	ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector);
-	of_node_put(encoder);
-	of_node_put(connector);
-
 	if (ret && ret != -EPROBE_DEFER)
 		dev_warn(rcdu->dev,
-			 "failed to initialize encoder %s (%d), skipping\n",
-			 encoder->full_name, ret);
+			 "failed to initialize encoder %s on output %u (%d), skipping\n",
+			 of_node_full_name(encoder), output, ret);
+
+	of_node_put(encoder);
+	of_node_put(connector);
 
 	return ret;
 }
@@ -567,6 +568,13 @@ int rcar_du_modeset_init(struct rcar_du_
 	if (ret < 0)
 		return ret;
 
+	/* Initialize vertical blanking interrupts handling. Start with vblank
+	 * disabled for all CRTCs.
+	 */
+	ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
+	if (ret < 0)
+		return ret;
+
 	/* Initialize the groups. */
 	num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,16 +61,9 @@ static const struct drm_connector_helper
 	.get_modes = rcar_du_lvds_connector_get_modes,
 };
 
-static enum drm_connector_status
-rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static const struct drm_connector_funcs connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.reset = drm_atomic_helper_connector_reset,
-	.detect = rcar_du_lvds_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = drm_connector_cleanup,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -79,7 +72,7 @@ static const struct drm_connector_funcs
 
 int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
 				struct rcar_du_encoder *renc,
-				/* TODO const */ struct device_node *np)
+				const struct device_node *np)
 {
 	struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
 	struct rcar_du_lvds_connector *lvdscon;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,6 @@ struct rcar_du_encoder;
 
 int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
 				struct rcar_du_encoder *renc,
-				struct device_node *np);
+				const struct device_node *np);
 
 #endif /* __RCAR_DU_LVDSCON_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,14 @@ static void rcar_du_lvdsenc_start_gen3(s
 
 	rcar_lvds_write(lvds, LVDPLLCR, pllcr);
 
-	/* Turn the PLL on, set it to LVDS normal mode, wait for the startup
+	/* Turn all the channels on. */
+	rcar_lvds_write(lvds, LVDCR1,
+			LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
+			LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
+			LVDCR1_CLKSTBY_GEN3);
+
+	/*
+	 * Turn the PLL on, set it to LVDS normal mode, wait for the startup
 	 * delay and turn the output on.
 	 */
 	lvdcr0 = LVDCR0_PLLON;
@@ -117,12 +124,6 @@ static void rcar_du_lvdsenc_start_gen3(s
 
 	lvdcr0 |= LVDCR0_LVRES;
 	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
-
-	/* Turn all the channels on. */
-	rcar_lvds_write(lvds, LVDCR1,
-			LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
-			LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
-			LVDCR1_CLKSTBY_GEN3);
 }
 
 static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
@@ -241,10 +242,8 @@ int rcar_du_lvdsenc_init(struct rcar_du_
 
 	for (i = 0; i < rcdu->info->num_lvds; ++i) {
 		lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
-		if (lvds == NULL) {
-			dev_err(&pdev->dev, "failed to allocate private data\n");
+		if (lvds == NULL)
 			return -ENOMEM;
-		}
 
 		lvds->dev = rcdu;
 		lvds->index = i;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/dw-mipi-dsi.c	2017-02-12 16:03:20.000000000 -0500
@@ -969,12 +969,6 @@ static struct drm_connector_helper_funcs
 	.mode_valid = dw_mipi_dsi_mode_valid,
 };
 
-static enum drm_connector_status
-dw_mipi_dsi_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void dw_mipi_dsi_drm_connector_destroy(struct drm_connector *connector)
 {
 	drm_connector_unregister(connector);
@@ -984,7 +978,6 @@ static void dw_mipi_dsi_drm_connector_de
 static struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = dw_mipi_dsi_detect,
 	.destroy = dw_mipi_dsi_drm_connector_destroy,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,6 @@
 config DRM_ROCKCHIP
 	tristate "DRM Support for Rockchip"
 	depends on DRM && ROCKCHIP_IOMMU
-	depends on RESET_CONTROLLER
 	select DRM_GEM_CMA_HELPER
 	select DRM_KMS_HELPER
 	select DRM_PANEL
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/rockchip_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
@@ -274,9 +275,7 @@ static const struct file_operations rock
 	.poll = drm_poll,
 	.read = drm_read,
 	.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.release = drm_release,
 };
 
@@ -388,7 +387,7 @@ static void rockchip_add_endpoints(struc
 			continue;
 		}
 
-		component_match_add(dev, match, compare_of, remote);
+		drm_of_component_match_add(dev, match, compare_of, remote);
 		of_node_put(remote);
 	}
 }
@@ -437,7 +436,8 @@ static int rockchip_drm_platform_probe(s
 		}
 
 		of_node_put(iommu);
-		component_match_add(dev, &match, compare_of, port->parent);
+		drm_of_component_match_add(dev, &match, compare_of,
+					   port->parent);
 		of_node_put(port);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,15 +37,11 @@ static int rockchip_fbdev_mmap(struct fb
 
 static struct fb_ops rockchip_drm_fbdev_ops = {
 	.owner		= THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_mmap	= rockchip_fbdev_mmap,
 	.fb_fillrect	= drm_fb_helper_cfb_fillrect,
 	.fb_copyarea	= drm_fb_helper_cfb_copyarea,
 	.fb_imageblit	= drm_fb_helper_cfb_imageblit,
-	.fb_check_var	= drm_fb_helper_check_var,
-	.fb_set_par	= drm_fb_helper_set_par,
-	.fb_blank	= drm_fb_helper_blank,
-	.fb_pan_display	= drm_fb_helper_pan_display,
-	.fb_setcmap	= drm_fb_helper_setcmap,
 };
 
 static int rockchip_drm_fbdev_create(struct drm_fb_helper *helper,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/savage/savage_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/savage/savage_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/savage/savage_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/savage/savage_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,9 +42,7 @@ static const struct file_operations sava
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = drm_legacy_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/savage/savage_state.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/savage/savage_state.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/savage/savage_state.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/savage/savage_state.c	2017-02-12 16:03:20.000000000 -0500
@@ -1004,6 +1004,7 @@ int savage_bci_cmdbuf(struct drm_device
 		kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size);
 		if (IS_ERR(kvb_addr)) {
 			ret = PTR_ERR(kvb_addr);
+			kvb_addr = NULL;
 			goto done;
 		}
 		cmdbuf->vb_addr = kvb_addr;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/shmobile/shmob_drm_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -669,15 +669,8 @@ static void shmob_drm_connector_destroy(
 	drm_connector_cleanup(connector);
 }
 
-static enum drm_connector_status
-shmob_drm_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static const struct drm_connector_funcs connector_funcs = {
 	.dpms = drm_helper_connector_dpms,
-	.detect = shmob_drm_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = shmob_drm_connector_destroy,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/shmobile/shmob_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -245,9 +245,7 @@ static const struct file_operations shmo
 	.open		= drm_open,
 	.release	= drm_release,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl	= drm_compat_ioctl,
-#endif
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.llseek		= no_llseek,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sis/sis_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sis/sis_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sis/sis_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sis/sis_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,9 +72,7 @@ static const struct file_operations sis_
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = drm_legacy_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sti/sti_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sti/sti_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sti/sti_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sti/sti_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_of.h>
 
 #include "sti_crtc.h"
 #include "sti_drv.h"
@@ -184,7 +185,7 @@ static void sti_atomic_complete(struct s
 	drm_atomic_helper_wait_for_vblanks(drm, state);
 
 	drm_atomic_helper_cleanup_planes(drm, state);
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 }
 
 static void sti_atomic_work(struct work_struct *work)
@@ -237,6 +238,7 @@ static int sti_atomic_commit(struct drm_
 
 	drm_atomic_helper_swap_state(state, true);
 
+	drm_atomic_state_get(state);
 	if (nonblock)
 		sti_atomic_schedule(private, state);
 	else
@@ -295,9 +297,7 @@ static const struct file_operations sti_
 	.poll = drm_poll,
 	.read = drm_read,
 	.unlocked_ioctl = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.release = drm_release,
 };
 
@@ -443,8 +443,8 @@ static int sti_platform_probe(struct pla
 	child_np = of_get_next_available_child(node, NULL);
 
 	while (child_np) {
-		component_match_add(dev, &match, compare_of, child_np);
-		of_node_put(child_np);
+		drm_of_component_match_add(dev, &match, compare_of,
+					   child_np);
 		child_np = of_get_next_available_child(node, child_np);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sti/sti_hda.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sti/sti_hda.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sti/sti_hda.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sti/sti_hda.c	2017-02-12 16:03:20.000000000 -0500
@@ -642,12 +642,6 @@ struct drm_connector_helper_funcs sti_hd
 	.mode_valid = sti_hda_connector_mode_valid,
 };
 
-static enum drm_connector_status
-sti_hda_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static int sti_hda_late_register(struct drm_connector *connector)
 {
 	struct sti_hda_connector *hda_connector
@@ -665,7 +659,6 @@ static int sti_hda_late_register(struct
 static const struct drm_connector_funcs sti_hda_connector_funcs = {
 	.dpms = drm_atomic_helper_connector_dpms,
 	.fill_modes = drm_helper_probe_single_connector_modes,
-	.detect = sti_hda_connector_detect,
 	.destroy = drm_connector_cleanup,
 	.reset = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_backend.c	2017-02-12 16:03:20.000000000 -0500
@@ -95,6 +95,22 @@ static int sun4i_backend_drm_format_to_l
 		*mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
 		break;
 
+	case DRM_FORMAT_ARGB4444:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_ARGB4444;
+		break;
+
+	case DRM_FORMAT_ARGB1555:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_ARGB1555;
+		break;
+
+	case DRM_FORMAT_RGBA5551:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_RGBA5551;
+		break;
+
+	case DRM_FORMAT_RGBA4444:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_RGBA4444;
+		break;
+
 	case DRM_FORMAT_XRGB8888:
 		*mode = SUN4I_BACKEND_LAY_FBFMT_XRGB8888;
 		break;
@@ -103,6 +119,10 @@ static int sun4i_backend_drm_format_to_l
 		*mode = SUN4I_BACKEND_LAY_FBFMT_RGB888;
 		break;
 
+	case DRM_FORMAT_RGB565:
+		*mode = SUN4I_BACKEND_LAY_FBFMT_RGB565;
+		break;
+
 	default:
 		return -EINVAL;
 	}
@@ -389,7 +409,7 @@ static void sun4i_backend_unbind(struct
 	reset_control_assert(backend->reset);
 }
 
-static struct component_ops sun4i_backend_ops = {
+static const struct component_ops sun4i_backend_ops = {
 	.bind	= sun4i_backend_bind,
 	.unbind	= sun4i_backend_unbind,
 };
@@ -408,6 +428,7 @@ static int sun4i_backend_remove(struct p
 
 static const struct of_device_id sun4i_backend_of_table[] = {
 	{ .compatible = "allwinner,sun5i-a13-display-backend" },
+	{ .compatible = "allwinner,sun6i-a31-display-backend" },
 	{ .compatible = "allwinner,sun8i-a33-display-backend" },
 	{ }
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_of.h>
 
 #include "sun4i_crtc.h"
 #include "sun4i_drv.h"
@@ -52,9 +53,7 @@ static const struct file_operations sun4
 	.open		= drm_open,
 	.release	= drm_release,
 	.unlocked_ioctl	= drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl	= drm_compat_ioctl,
-#endif
 	.poll		= drm_poll,
 	.read		= drm_read,
 	.llseek		= no_llseek,
@@ -201,12 +200,15 @@ static const struct component_master_ops
 static bool sun4i_drv_node_is_frontend(struct device_node *node)
 {
 	return of_device_is_compatible(node, "allwinner,sun5i-a13-display-frontend") ||
+		of_device_is_compatible(node, "allwinner,sun6i-a31-display-frontend") ||
 		of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend");
 }
 
 static bool sun4i_drv_node_is_tcon(struct device_node *node)
 {
 	return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
+		of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
+		of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
 		of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
 }
 
@@ -239,7 +241,7 @@ static int sun4i_drv_add_endpoints(struc
 		/* Add current component */
 		DRM_DEBUG_DRIVER("Adding component %s\n",
 				 of_node_full_name(node));
-		component_match_add(dev, match, compare_of, node);
+		drm_of_component_match_add(dev, match, compare_of, node);
 		count++;
 	}
 
@@ -322,6 +324,8 @@ static int sun4i_drv_remove(struct platf
 
 static const struct of_device_id sun4i_drv_of_table[] = {
 	{ .compatible = "allwinner,sun5i-a13-display-engine" },
+	{ .compatible = "allwinner,sun6i-a31-display-engine" },
+	{ .compatible = "allwinner,sun6i-a31s-display-engine" },
 	{ .compatible = "allwinner,sun8i-a33-display-engine" },
 	{ }
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_layer.c	2017-02-12 16:03:20.000000000 -0500
@@ -73,12 +73,18 @@ static const struct drm_plane_funcs sun4
 static const uint32_t sun4i_backend_layer_formats_primary[] = {
 	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGB565,
 	DRM_FORMAT_XRGB8888,
 };
 
 static const uint32_t sun4i_backend_layer_formats_overlay[] = {
 	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_RGBA5551,
+	DRM_FORMAT_RGBA4444,
 	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGB565,
 	DRM_FORMAT_XRGB8888,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_rgb.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,12 +110,6 @@ static struct drm_connector_helper_funcs
 	.mode_valid	= sun4i_rgb_mode_valid,
 };
 
-static enum drm_connector_status
-sun4i_rgb_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void
 sun4i_rgb_connector_destroy(struct drm_connector *connector)
 {
@@ -129,7 +123,6 @@ sun4i_rgb_connector_destroy(struct drm_c
 
 static struct drm_connector_funcs sun4i_rgb_con_funcs = {
 	.dpms			= drm_atomic_helper_connector_dpms,
-	.detect			= sun4i_rgb_connector_detect,
 	.fill_modes		= drm_helper_probe_single_connector_modes,
 	.destroy		= sun4i_rgb_connector_destroy,
 	.reset			= drm_atomic_helper_connector_reset,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/component.h>
 #include <linux/ioport.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/of_graph.h>
 #include <linux/of_irq.h>
 #include <linux/regmap.h>
@@ -62,7 +63,7 @@ void sun4i_tcon_channel_disable(struct s
 		return;
 	}
 
-	WARN_ON(!tcon->has_channel_1);
+	WARN_ON(!tcon->quirks->has_channel_1);
 	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
 			   SUN4I_TCON1_CTL_TCON_ENABLE, 0);
 	clk_disable_unprepare(tcon->sclk1);
@@ -80,7 +81,7 @@ void sun4i_tcon_channel_enable(struct su
 		return;
 	}
 
-	WARN_ON(!tcon->has_channel_1);
+	WARN_ON(!tcon->quirks->has_channel_1);
 	regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
 			   SUN4I_TCON1_CTL_TCON_ENABLE,
 			   SUN4I_TCON1_CTL_TCON_ENABLE);
@@ -202,7 +203,7 @@ void sun4i_tcon1_mode_set(struct sun4i_t
 	u8 clk_delay;
 	u32 val;
 
-	WARN_ON(!tcon->has_channel_1);
+	WARN_ON(!tcon->quirks->has_channel_1);
 
 	/* Adjust clock delay */
 	clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
@@ -266,7 +267,7 @@ void sun4i_tcon1_mode_set(struct sun4i_t
 	/*
 	 * FIXME: Undocumented bits
 	 */
-	if (tcon->has_mux)
+	if (tcon->quirks->has_unknown_mux)
 		regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1);
 }
 EXPORT_SYMBOL(sun4i_tcon1_mode_set);
@@ -327,7 +328,7 @@ static int sun4i_tcon_init_clocks(struct
 		return PTR_ERR(tcon->sclk0);
 	}
 
-	if (tcon->has_channel_1) {
+	if (tcon->quirks->has_channel_1) {
 		tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
 		if (IS_ERR(tcon->sclk1)) {
 			dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
@@ -487,14 +488,7 @@ static int sun4i_tcon_bind(struct device
 	drv->tcon = tcon;
 	tcon->drm = drm;
 	tcon->dev = dev;
-
-	if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon")) {
-		tcon->has_mux = true;
-		tcon->has_channel_1 = true;
-	} else {
-		tcon->has_mux = false;
-		tcon->has_channel_1 = false;
-	}
+	tcon->quirks = of_device_get_match_data(dev);
 
 	tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
 	if (IS_ERR(tcon->lcd_rst)) {
@@ -551,7 +545,7 @@ static void sun4i_tcon_unbind(struct dev
 	sun4i_tcon_free_clocks(tcon);
 }
 
-static struct component_ops sun4i_tcon_ops = {
+static const struct component_ops sun4i_tcon_ops = {
 	.bind	= sun4i_tcon_bind,
 	.unbind	= sun4i_tcon_unbind,
 };
@@ -588,9 +582,28 @@ static int sun4i_tcon_remove(struct plat
 	return 0;
 }
 
+static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
+	.has_unknown_mux = true,
+	.has_channel_1	= true,
+};
+
+static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
+	.has_channel_1	= true,
+};
+
+static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
+	.has_channel_1	= true,
+};
+
+static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
+	/* nothing is supported */
+};
+
 static const struct of_device_id sun4i_tcon_of_table[] = {
-	{ .compatible = "allwinner,sun5i-a13-tcon" },
-	{ .compatible = "allwinner,sun8i-a33-tcon" },
+	{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
+	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
+	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
+	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_tcon.h	2017-02-12 16:03:20.000000000 -0500
@@ -142,6 +142,11 @@
 
 #define SUN4I_TCON_MAX_CHANNELS		2
 
+struct sun4i_tcon_quirks {
+	bool	has_unknown_mux; /* sun5i has undocumented mux */
+	bool	has_channel_1;	/* a33 does not have channel 1 */
+};
+
 struct sun4i_tcon {
 	struct device			*dev;
 	struct drm_device		*drm;
@@ -160,12 +165,10 @@ struct sun4i_tcon {
 	/* Reset control */
 	struct reset_control		*lcd_rst;
 
-	/* Platform adjustments */
-	bool				has_mux;
-
 	struct drm_panel		*panel;
 
-	bool				has_channel_1;
+	/* Platform adjustments */
+	const struct sun4i_tcon_quirks	*quirks;
 };
 
 struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun4i_tv.c	2017-02-12 16:03:20.000000000 -0500
@@ -537,12 +537,6 @@ static struct drm_connector_helper_funcs
 	.mode_valid	= sun4i_tv_comp_mode_valid,
 };
 
-static enum drm_connector_status
-sun4i_tv_comp_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
 static void
 sun4i_tv_comp_connector_destroy(struct drm_connector *connector)
 {
@@ -551,7 +545,6 @@ sun4i_tv_comp_connector_destroy(struct d
 
 static struct drm_connector_funcs sun4i_tv_comp_connector_funcs = {
 	.dpms			= drm_atomic_helper_connector_dpms,
-	.detect			= sun4i_tv_comp_connector_detect,
 	.fill_modes		= drm_helper_probe_single_connector_modes,
 	.destroy		= sun4i_tv_comp_connector_destroy,
 	.reset			= drm_atomic_helper_connector_reset,
@@ -667,7 +660,7 @@ static void sun4i_tv_unbind(struct devic
 	clk_disable_unprepare(tv->clk);
 }
 
-static struct component_ops sun4i_tv_ops = {
+static const struct component_ops sun4i_tv_ops = {
 	.bind	= sun4i_tv_bind,
 	.unbind	= sun4i_tv_unbind,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun6i_drc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun6i_drc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/sun4i/sun6i_drc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/sun4i/sun6i_drc.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,7 +80,7 @@ static void sun6i_drc_unbind(struct devi
 	reset_control_assert(drc->reset);
 }
 
-static struct component_ops sun6i_drc_ops = {
+static const struct component_ops sun6i_drc_ops = {
 	.bind	= sun6i_drc_bind,
 	.unbind	= sun6i_drc_unbind,
 };
@@ -98,6 +98,8 @@ static int sun6i_drc_remove(struct platf
 }
 
 static const struct of_device_id sun6i_drc_of_table[] = {
+	{ .compatible = "allwinner,sun6i-a31-drc" },
+	{ .compatible = "allwinner,sun6i-a31s-drc" },
 	{ .compatible = "allwinner,sun8i-a33-drc" },
 	{ }
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,9 +49,7 @@ static const struct file_operations tdfx
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = drm_legacy_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tegra/dpaux.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/dpaux.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tegra/dpaux.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/dpaux.c	2017-02-12 16:03:20.000000000 -0500
@@ -539,9 +539,9 @@ static int tegra_dpaux_probe(struct plat
 	dpaux->desc.owner = THIS_MODULE;
 
 	dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux);
-	if (!dpaux->pinctrl) {
+	if (IS_ERR(dpaux->pinctrl)) {
 		dev_err(&pdev->dev, "failed to register pincontrol\n");
-		return -ENODEV;
+		return PTR_ERR(dpaux->pinctrl);
 	}
 #endif
 	/* enable and clear all interrupts */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tegra/drm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/drm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tegra/drm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/drm.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,7 +63,7 @@ static void tegra_atomic_complete(struct
 	drm_atomic_helper_wait_for_vblanks(drm, state);
 
 	drm_atomic_helper_cleanup_planes(drm, state);
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 }
 
 static void tegra_atomic_work(struct work_struct *work)
@@ -96,6 +96,7 @@ static int tegra_atomic_commit(struct dr
 
 	drm_atomic_helper_swap_state(state, true);
 
+	drm_atomic_state_get(state);
 	if (nonblock)
 		tegra_atomic_schedule(tegra, state);
 	else
@@ -801,9 +802,7 @@ static const struct file_operations tegr
 	.mmap = tegra_drm_mmap,
 	.poll = drm_poll,
 	.read = drm_read,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tegra/fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tegra/fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -186,14 +186,10 @@ unreference:
 #ifdef CONFIG_DRM_FBDEV_EMULATION
 static struct fb_ops tegra_fb_ops = {
 	.owner = THIS_MODULE,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_fillrect = drm_fb_helper_sys_fillrect,
 	.fb_copyarea = drm_fb_helper_sys_copyarea,
 	.fb_imageblit = drm_fb_helper_sys_imageblit,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_setcmap = drm_fb_helper_setcmap,
 };
 
 static int tegra_fbdev_probe(struct drm_fb_helper *helper,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tegra/gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tegra/gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -2,7 +2,7 @@
  * NVIDIA Tegra DRM GEM helper functions
  *
  * Copyright (C) 2012 Sascha Hauer, Pengutronix
- * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved.
+ * Copyright (C) 2013-2015 NVIDIA CORPORATION, All rights reserved.
  *
  * Based on the GEM/CMA helpers
  *
@@ -36,6 +36,8 @@ static dma_addr_t tegra_bo_pin(struct ho
 {
 	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 
+	*sgt = obj->sgt;
+
 	return obj->paddr;
 }
 
@@ -47,23 +49,51 @@ static void *tegra_bo_mmap(struct host1x
 {
 	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 
-	return obj->vaddr;
+	if (obj->vaddr)
+		return obj->vaddr;
+	else if (obj->gem.import_attach)
+		return dma_buf_vmap(obj->gem.import_attach->dmabuf);
+	else
+		return vmap(obj->pages, obj->num_pages, VM_MAP,
+			    pgprot_writecombine(PAGE_KERNEL));
 }
 
 static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
 {
+	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+
+	if (obj->vaddr)
+		return;
+	else if (obj->gem.import_attach)
+		dma_buf_vunmap(obj->gem.import_attach->dmabuf, addr);
+	else
+		vunmap(addr);
 }
 
 static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page)
 {
 	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 
-	return obj->vaddr + page * PAGE_SIZE;
+	if (obj->vaddr)
+		return obj->vaddr + page * PAGE_SIZE;
+	else if (obj->gem.import_attach)
+		return dma_buf_kmap(obj->gem.import_attach->dmabuf, page);
+	else
+		return vmap(obj->pages + page, 1, VM_MAP,
+			    pgprot_writecombine(PAGE_KERNEL));
 }
 
 static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
 			    void *addr)
 {
+	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
+
+	if (obj->vaddr)
+		return;
+	else if (obj->gem.import_attach)
+		dma_buf_kunmap(obj->gem.import_attach->dmabuf, page, addr);
+	else
+		vunmap(addr);
 }
 
 static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
@@ -318,11 +348,6 @@ static struct tegra_bo *tegra_bo_import(
 	get_dma_buf(buf);
 
 	bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
-	if (!bo->sgt) {
-		err = -ENOMEM;
-		goto detach;
-	}
-
 	if (IS_ERR(bo->sgt)) {
 		err = PTR_ERR(bo->sgt);
 		goto detach;
@@ -427,10 +452,10 @@ static int tegra_bo_fault(struct vm_area
 	if (!bo->pages)
 		return VM_FAULT_SIGBUS;
 
-	offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT;
+	offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 	page = bo->pages[offset];
 
-	err = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);
+	err = vm_insert_page(vma, vmf->address, page);
 	switch (err) {
 	case -EAGAIN:
 	case 0:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tegra/gr3d.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/gr3d.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tegra/gr3d.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/gr3d.c	2017-02-12 16:03:20.000000000 -0500
@@ -268,9 +268,9 @@ static int gr3d_probe(struct platform_de
 
 	if (of_device_is_compatible(np, "nvidia,tegra30-gr3d")) {
 		gr3d->clk_secondary = devm_clk_get(&pdev->dev, "3d2");
-		if (IS_ERR(gr3d->clk)) {
+		if (IS_ERR(gr3d->clk_secondary)) {
 			dev_err(&pdev->dev, "cannot get secondary clock\n");
-			return PTR_ERR(gr3d->clk);
+			return PTR_ERR(gr3d->clk_secondary);
 		}
 
 		gr3d->rst_secondary = devm_reset_control_get(&pdev->dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tegra/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/tegra/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,6 @@ config DRM_TEGRA
 	depends on ARCH_TEGRA || (ARM && COMPILE_TEST)
 	depends on COMMON_CLK
 	depends on DRM
-	depends on RESET_CONTROLLER
 	select DRM_KMS_HELPER
 	select DRM_MIPI_DSI
 	select DRM_PANEL
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tegra/sor.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/sor.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tegra/sor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tegra/sor.c	2017-02-12 16:03:20.000000000 -0500
@@ -349,8 +349,6 @@ static struct clk *tegra_clk_sor_brick_r
 	brick->hw.init = &init;
 
 	clk = devm_clk_register(sor->dev, &brick->hw);
-	if (IS_ERR(clk))
-		kfree(brick);
 
 	return clk;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,11 +21,15 @@
 #include <drm/drm_flip_work.h>
 #include <drm/drm_plane_helper.h>
 #include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/dma-mapping.h>
 
 #include "tilcdc_drv.h"
 #include "tilcdc_regs.h"
 
-#define TILCDC_VBLANK_SAFETY_THRESHOLD_US 1000
+#define TILCDC_VBLANK_SAFETY_THRESHOLD_US	1000
+#define TILCDC_PALETTE_SIZE			32
+#define TILCDC_PALETTE_FIRST_ENTRY		0x4000
 
 struct tilcdc_crtc {
 	struct drm_crtc base;
@@ -33,7 +37,9 @@ struct tilcdc_crtc {
 	struct drm_plane primary;
 	const struct tilcdc_panel_info *info;
 	struct drm_pending_vblank_event *event;
+	struct mutex enable_lock;
 	bool enabled;
+	bool shutdown;
 	wait_queue_head_t frame_done_wq;
 	bool frame_done;
 	spinlock_t irq_lock;
@@ -53,6 +59,11 @@ struct tilcdc_crtc {
 
 	int sync_lost_count;
 	bool frame_intact;
+	struct work_struct recover_work;
+
+	dma_addr_t palette_dma_handle;
+	u16 *palette_base;
+	struct completion palette_loaded;
 };
 #define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)
 
@@ -71,17 +82,16 @@ static void set_scanout(struct drm_crtc
 {
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
 	struct drm_gem_cma_object *gem;
-	unsigned int depth, bpp;
 	dma_addr_t start, end;
 	u64 dma_base_and_ceiling;
 
-	drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
 	gem = drm_fb_cma_get_gem_obj(fb, 0);
 
 	start = gem->paddr + fb->offsets[0] +
 		crtc->y * fb->pitches[0] +
-		crtc->x * bpp / 8;
+		crtc->x * drm_format_plane_cpp(fb->pixel_format, 0);
 
 	end = start + (crtc->mode.vdisplay * fb->pitches[0]);
 
@@ -90,7 +100,10 @@ static void set_scanout(struct drm_crtc
 	 * unlikely that LCDC would fetch the DMA addresses in the middle of
 	 * an update.
 	 */
-	dma_base_and_ceiling = (u64)(end - 1) << 32 | start;
+	if (priv->rev == 1)
+		end -= 1;
+
+	dma_base_and_ceiling = (u64)end << 32 | start;
 	tilcdc_write64(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, dma_base_and_ceiling);
 
 	if (tilcdc_crtc->curr_fb)
@@ -100,6 +113,56 @@ static void set_scanout(struct drm_crtc
 	tilcdc_crtc->curr_fb = fb;
 }
 
+/*
+ * The driver currently only supports only true color formats. For
+ * true color the palette block is bypassed, but a 32 byte palette
+ * should still be loaded. The first 16-bit entry must be 0x4000 while
+ * all other entries must be zeroed.
+ */
+static void tilcdc_crtc_load_palette(struct drm_crtc *crtc)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	int ret;
+
+	reinit_completion(&tilcdc_crtc->palette_loaded);
+
+	/* Tell the LCDC where the palette is located. */
+	tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG,
+		     tilcdc_crtc->palette_dma_handle);
+	tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG,
+		     (u32) tilcdc_crtc->palette_dma_handle +
+		     TILCDC_PALETTE_SIZE - 1);
+
+	/* Set dma load mode for palette loading only. */
+	tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG,
+			  LCDC_PALETTE_LOAD_MODE(PALETTE_ONLY),
+			  LCDC_PALETTE_LOAD_MODE_MASK);
+
+	/* Enable DMA Palette Loaded Interrupt */
+	if (priv->rev == 1)
+		tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA);
+	else
+		tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_PL_INT_ENA);
+
+	/* Enable LCDC DMA and wait for palette to be loaded. */
+	tilcdc_clear_irqstatus(dev, 0xffffffff);
+	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+
+	ret = wait_for_completion_timeout(&tilcdc_crtc->palette_loaded,
+					  msecs_to_jiffies(50));
+	if (ret == 0)
+		dev_err(dev->dev, "%s: Palette loading timeout", __func__);
+
+	/* Disable LCDC DMA and DMA Palette Loaded Interrupt. */
+	tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+	if (priv->rev == 1)
+		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA);
+	else
+		tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG, LCDC_V2_PL_INT_ENA);
+}
+
 static void tilcdc_crtc_enable_irqs(struct drm_device *dev)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
@@ -108,6 +171,7 @@ static void tilcdc_crtc_enable_irqs(stru
 
 	if (priv->rev == 1) {
 		tilcdc_set(dev, LCDC_RASTER_CTRL_REG,
+			LCDC_V1_SYNC_LOST_INT_ENA | LCDC_V1_FRAME_DONE_INT_ENA |
 			LCDC_V1_UNDERFLOW_INT_ENA);
 		tilcdc_set(dev, LCDC_DMA_CTRL_REG,
 			LCDC_V1_END_OF_FRAME_INT_ENA);
@@ -126,6 +190,7 @@ static void tilcdc_crtc_disable_irqs(str
 	/* disable irqs that we might have enabled: */
 	if (priv->rev == 1) {
 		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+			LCDC_V1_SYNC_LOST_INT_ENA | LCDC_V1_FRAME_DONE_INT_ENA |
 			LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA);
 		tilcdc_clear(dev, LCDC_DMA_CTRL_REG,
 			LCDC_V1_END_OF_FRAME_INT_ENA);
@@ -150,193 +215,68 @@ static void reset(struct drm_crtc *crtc)
 	tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET);
 }
 
-static void tilcdc_crtc_enable(struct drm_crtc *crtc)
+/*
+ * Calculate the percentage difference between the requested pixel clock rate
+ * and the effective rate resulting from calculating the clock divider value.
+ */
+static unsigned int tilcdc_pclk_diff(unsigned long rate,
+				     unsigned long real_rate)
 {
-	struct drm_device *dev = crtc->dev;
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-
-	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
-	if (tilcdc_crtc->enabled)
-		return;
-
-	pm_runtime_get_sync(dev->dev);
-
-	reset(crtc);
-
-	tilcdc_crtc_enable_irqs(dev);
-
-	tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
-	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY));
-	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
-
-	drm_crtc_vblank_on(crtc);
+	int r = rate / 100, rr = real_rate / 100;
 
-	tilcdc_crtc->enabled = true;
+	return (unsigned int)(abs(((rr - r) * 100) / r));
 }
 
-void tilcdc_crtc_disable(struct drm_crtc *crtc)
+static void tilcdc_crtc_set_clk(struct drm_crtc *crtc)
 {
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct tilcdc_drm_private *priv = dev->dev_private;
-
-	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
-	if (!tilcdc_crtc->enabled)
-		return;
-
-	tilcdc_crtc->frame_done = false;
-	tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
-
-	/*
-	 * if necessary wait for framedone irq which will still come
-	 * before putting things to sleep..
-	 */
-	if (priv->rev == 2) {
-		int ret = wait_event_timeout(tilcdc_crtc->frame_done_wq,
-					     tilcdc_crtc->frame_done,
-					     msecs_to_jiffies(500));
-		if (ret == 0)
-			dev_err(dev->dev, "%s: timeout waiting for framedone\n",
-				__func__);
-	}
-
-	drm_crtc_vblank_off(crtc);
-
-	tilcdc_crtc_disable_irqs(dev);
-
-	pm_runtime_put_sync(dev->dev);
-
-	if (tilcdc_crtc->next_fb) {
-		drm_flip_work_queue(&tilcdc_crtc->unref_work,
-				    tilcdc_crtc->next_fb);
-		tilcdc_crtc->next_fb = NULL;
-	}
-
-	if (tilcdc_crtc->curr_fb) {
-		drm_flip_work_queue(&tilcdc_crtc->unref_work,
-				    tilcdc_crtc->curr_fb);
-		tilcdc_crtc->curr_fb = NULL;
-	}
-
-	drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
-	tilcdc_crtc->last_vblank = ktime_set(0, 0);
-
-	tilcdc_crtc->enabled = false;
-}
-
-static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
-{
-	return crtc->state && crtc->state->enable && crtc->state->active;
-}
-
-static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
-{
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-	struct tilcdc_drm_private *priv = crtc->dev->dev_private;
-
-	drm_modeset_lock_crtc(crtc, NULL);
-	tilcdc_crtc_disable(crtc);
-	drm_modeset_unlock_crtc(crtc);
-
-	flush_workqueue(priv->wq);
-
-	of_node_put(crtc->port);
-	drm_crtc_cleanup(crtc);
-	drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
-}
-
-int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
-		struct drm_framebuffer *fb,
-		struct drm_pending_vblank_event *event)
-{
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-	struct drm_device *dev = crtc->dev;
-	unsigned long flags;
-
-	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
-	if (tilcdc_crtc->event) {
-		dev_err(dev->dev, "already pending page flip!\n");
-		return -EBUSY;
-	}
-
-	drm_framebuffer_reference(fb);
-
-	crtc->primary->fb = fb;
-
-	spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
-
-	if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) {
-		ktime_t next_vblank;
-		s64 tdiff;
-
-		next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
-			1000000 / crtc->hwmode.vrefresh);
-
-		tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));
-
-		if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US)
-			tilcdc_crtc->next_fb = fb;
-	}
-
-	if (tilcdc_crtc->next_fb != fb)
-		set_scanout(crtc, fb);
-
-	tilcdc_crtc->event = event;
-
-	spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
-
-	return 0;
-}
-
-static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
-		const struct drm_display_mode *mode,
-		struct drm_display_mode *adjusted_mode)
-{
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	unsigned long clk_rate, real_rate, req_rate;
+	unsigned int clkdiv;
+	int ret;
 
-	if (!tilcdc_crtc->simulate_vesa_sync)
-		return true;
+	clkdiv = 2; /* first try using a standard divider of 2 */
 
-	/*
-	 * tilcdc does not generate VESA-compliant sync but aligns
-	 * VS on the second edge of HS instead of first edge.
-	 * We use adjusted_mode, to fixup sync by aligning both rising
-	 * edges and add HSKEW offset to fix the sync.
-	 */
-	adjusted_mode->hskew = mode->hsync_end - mode->hsync_start;
-	adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW;
+	/* mode.clock is in KHz, set_rate wants parameter in Hz */
+	req_rate = crtc->mode.clock * 1000;
 
-	if (mode->flags & DRM_MODE_FLAG_NHSYNC) {
-		adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC;
-		adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC;
-	} else {
-		adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC;
-		adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC;
-	}
+	ret = clk_set_rate(priv->clk, req_rate * clkdiv);
+	clk_rate = clk_get_rate(priv->clk);
+	if (ret < 0) {
+		/*
+		 * If we fail to set the clock rate (some architectures don't
+		 * use the common clock framework yet and may not implement
+		 * all the clk API calls for every clock), try the next best
+		 * thing: adjusting the clock divider, unless clk_get_rate()
+		 * failed as well.
+		 */
+		if (!clk_rate) {
+			/* Nothing more we can do. Just bail out. */
+			dev_err(dev->dev,
+				"failed to set the pixel clock - unable to read current lcdc clock rate\n");
+			return;
+		}
 
-	return true;
-}
+		clkdiv = DIV_ROUND_CLOSEST(clk_rate, req_rate);
 
-static void tilcdc_crtc_set_clk(struct drm_crtc *crtc)
-{
-	struct drm_device *dev = crtc->dev;
-	struct tilcdc_drm_private *priv = dev->dev_private;
-	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
-	const unsigned clkdiv = 2; /* using a fixed divider of 2 */
-	int ret;
+		/*
+		 * Emit a warning if the real clock rate resulting from the
+		 * calculated divider differs much from the requested rate.
+		 *
+		 * 5% is an arbitrary value - LCDs are usually quite tolerant
+		 * about pixel clock rates.
+		 */
+		real_rate = clkdiv * req_rate;
 
-	/* mode.clock is in KHz, set_rate wants parameter in Hz */
-	ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv);
-	if (ret < 0) {
-		dev_err(dev->dev, "failed to set display clock rate to: %d\n",
-			crtc->mode.clock);
-		return;
+		if (tilcdc_pclk_diff(clk_rate, real_rate) > 5) {
+			dev_warn(dev->dev,
+				 "effective pixel clock rate (%luHz) differs from the calculated rate (%luHz)\n",
+				 clk_rate, real_rate);
+		}
 	}
 
-	tilcdc_crtc->lcd_fck_rate = clk_get_rate(priv->clk);
+	tilcdc_crtc->lcd_fck_rate = clk_rate;
 
 	DBG("lcd_clk=%u, mode clock=%d, div=%u",
 	    tilcdc_crtc->lcd_fck_rate, crtc->mode.clock, clkdiv);
@@ -351,7 +291,7 @@ static void tilcdc_crtc_set_clk(struct d
 				LCDC_V2_CORE_CLK_EN);
 }
 
-static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc)
+static void tilcdc_crtc_set_mode(struct drm_crtc *crtc)
 {
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
@@ -361,8 +301,6 @@ static void tilcdc_crtc_mode_set_nofb(st
 	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
 	struct drm_framebuffer *fb = crtc->primary->state->fb;
 
-	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
-
 	if (WARN_ON(!info))
 		return;
 
@@ -461,16 +399,16 @@ static void tilcdc_crtc_mode_set_nofb(st
 	if (info->tft_alt_mode)
 		reg |= LCDC_TFT_ALT_ENABLE;
 	if (priv->rev == 2) {
-		unsigned int depth, bpp;
-
-		drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp);
-		switch (bpp) {
-		case 16:
+		switch (fb->pixel_format) {
+		case DRM_FORMAT_BGR565:
+		case DRM_FORMAT_RGB565:
 			break;
-		case 32:
+		case DRM_FORMAT_XBGR8888:
+		case DRM_FORMAT_XRGB8888:
 			reg |= LCDC_V2_TFT_24BPP_UNPACK;
 			/* fallthrough */
-		case 24:
+		case DRM_FORMAT_BGR888:
+		case DRM_FORMAT_RGB888:
 			reg |= LCDC_V2_TFT_24BPP_MODE;
 			break;
 		default:
@@ -511,15 +449,226 @@ static void tilcdc_crtc_mode_set_nofb(st
 	else
 		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER);
 
-	drm_framebuffer_reference(fb);
+	tilcdc_crtc_set_clk(crtc);
+
+	tilcdc_crtc_load_palette(crtc);
 
 	set_scanout(crtc, fb);
 
-	tilcdc_crtc_set_clk(crtc);
+	drm_framebuffer_reference(fb);
 
 	crtc->hwmode = crtc->state->adjusted_mode;
 }
 
+static void tilcdc_crtc_enable(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+
+	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+	mutex_lock(&tilcdc_crtc->enable_lock);
+	if (tilcdc_crtc->enabled || tilcdc_crtc->shutdown) {
+		mutex_unlock(&tilcdc_crtc->enable_lock);
+		return;
+	}
+
+	pm_runtime_get_sync(dev->dev);
+
+	reset(crtc);
+
+	tilcdc_crtc_set_mode(crtc);
+
+	tilcdc_crtc_enable_irqs(dev);
+
+	tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE);
+	tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG,
+			  LCDC_PALETTE_LOAD_MODE(DATA_ONLY),
+			  LCDC_PALETTE_LOAD_MODE_MASK);
+	tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+
+	drm_crtc_vblank_on(crtc);
+
+	tilcdc_crtc->enabled = true;
+	mutex_unlock(&tilcdc_crtc->enable_lock);
+}
+
+static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	struct tilcdc_drm_private *priv = dev->dev_private;
+	int ret;
+
+	mutex_lock(&tilcdc_crtc->enable_lock);
+	if (shutdown)
+		tilcdc_crtc->shutdown = true;
+	if (!tilcdc_crtc->enabled) {
+		mutex_unlock(&tilcdc_crtc->enable_lock);
+		return;
+	}
+	tilcdc_crtc->frame_done = false;
+	tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE);
+
+	/*
+	 * Wait for framedone irq which will still come before putting
+	 * things to sleep..
+	 */
+	ret = wait_event_timeout(tilcdc_crtc->frame_done_wq,
+				 tilcdc_crtc->frame_done,
+				 msecs_to_jiffies(500));
+	if (ret == 0)
+		dev_err(dev->dev, "%s: timeout waiting for framedone\n",
+			__func__);
+
+	drm_crtc_vblank_off(crtc);
+
+	tilcdc_crtc_disable_irqs(dev);
+
+	pm_runtime_put_sync(dev->dev);
+
+	if (tilcdc_crtc->next_fb) {
+		drm_flip_work_queue(&tilcdc_crtc->unref_work,
+				    tilcdc_crtc->next_fb);
+		tilcdc_crtc->next_fb = NULL;
+	}
+
+	if (tilcdc_crtc->curr_fb) {
+		drm_flip_work_queue(&tilcdc_crtc->unref_work,
+				    tilcdc_crtc->curr_fb);
+		tilcdc_crtc->curr_fb = NULL;
+	}
+
+	drm_flip_work_commit(&tilcdc_crtc->unref_work, priv->wq);
+	tilcdc_crtc->last_vblank = 0;
+
+	tilcdc_crtc->enabled = false;
+	mutex_unlock(&tilcdc_crtc->enable_lock);
+}
+
+static void tilcdc_crtc_disable(struct drm_crtc *crtc)
+{
+	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+	tilcdc_crtc_off(crtc, false);
+}
+
+void tilcdc_crtc_shutdown(struct drm_crtc *crtc)
+{
+	tilcdc_crtc_off(crtc, true);
+}
+
+static bool tilcdc_crtc_is_on(struct drm_crtc *crtc)
+{
+	return crtc->state && crtc->state->enable && crtc->state->active;
+}
+
+static void tilcdc_crtc_recover_work(struct work_struct *work)
+{
+	struct tilcdc_crtc *tilcdc_crtc =
+		container_of(work, struct tilcdc_crtc, recover_work);
+	struct drm_crtc *crtc = &tilcdc_crtc->base;
+
+	dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__);
+
+	drm_modeset_lock_crtc(crtc, NULL);
+
+	if (!tilcdc_crtc_is_on(crtc))
+		goto out;
+
+	tilcdc_crtc_disable(crtc);
+	tilcdc_crtc_enable(crtc);
+out:
+	drm_modeset_unlock_crtc(crtc);
+}
+
+static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct tilcdc_drm_private *priv = crtc->dev->dev_private;
+
+	drm_modeset_lock_crtc(crtc, NULL);
+	tilcdc_crtc_disable(crtc);
+	drm_modeset_unlock_crtc(crtc);
+
+	flush_workqueue(priv->wq);
+
+	of_node_put(crtc->port);
+	drm_crtc_cleanup(crtc);
+	drm_flip_work_cleanup(&tilcdc_crtc->unref_work);
+}
+
+int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
+		struct drm_framebuffer *fb,
+		struct drm_pending_vblank_event *event)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+	unsigned long flags;
+
+	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
+
+	if (tilcdc_crtc->event) {
+		dev_err(dev->dev, "already pending page flip!\n");
+		return -EBUSY;
+	}
+
+	drm_framebuffer_reference(fb);
+
+	crtc->primary->fb = fb;
+
+	spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
+
+	if (crtc->hwmode.vrefresh && ktime_to_ns(tilcdc_crtc->last_vblank)) {
+		ktime_t next_vblank;
+		s64 tdiff;
+
+		next_vblank = ktime_add_us(tilcdc_crtc->last_vblank,
+			1000000 / crtc->hwmode.vrefresh);
+
+		tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));
+
+		if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US)
+			tilcdc_crtc->next_fb = fb;
+	}
+
+	if (tilcdc_crtc->next_fb != fb)
+		set_scanout(crtc, fb);
+
+	tilcdc_crtc->event = event;
+
+	spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
+
+	return 0;
+}
+
+static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc,
+		const struct drm_display_mode *mode,
+		struct drm_display_mode *adjusted_mode)
+{
+	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
+
+	if (!tilcdc_crtc->simulate_vesa_sync)
+		return true;
+
+	/*
+	 * tilcdc does not generate VESA-compliant sync but aligns
+	 * VS on the second edge of HS instead of first edge.
+	 * We use adjusted_mode, to fixup sync by aligning both rising
+	 * edges and add HSKEW offset to fix the sync.
+	 */
+	adjusted_mode->hskew = mode->hsync_end - mode->hsync_start;
+	adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW;
+
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC) {
+		adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC;
+		adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC;
+	} else {
+		adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC;
+		adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC;
+	}
+
+	return true;
+}
+
 static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc,
 				    struct drm_crtc_state *state)
 {
@@ -560,7 +709,6 @@ static const struct drm_crtc_helper_func
 		.enable		= tilcdc_crtc_enable,
 		.disable	= tilcdc_crtc_disable,
 		.atomic_check	= tilcdc_crtc_atomic_check,
-		.mode_set_nofb	= tilcdc_crtc_mode_set_nofb,
 };
 
 int tilcdc_crtc_max_width(struct drm_crtc *crtc)
@@ -708,7 +856,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_c
 	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct tilcdc_drm_private *priv = dev->dev_private;
-	uint32_t stat;
+	uint32_t stat, reg;
 
 	stat = tilcdc_read_irqstatus(dev);
 	tilcdc_clear_irqstatus(dev, stat);
@@ -756,28 +904,57 @@ irqreturn_t tilcdc_crtc_irq(struct drm_c
 	}
 
 	if (stat & LCDC_FIFO_UNDERFLOW)
-		dev_err_ratelimited(dev->dev, "%s(0x%08x): FIFO underfow",
+		dev_err_ratelimited(dev->dev, "%s(0x%08x): FIFO underflow",
 				    __func__, stat);
 
-	/* For revision 2 only */
-	if (priv->rev == 2) {
-		if (stat & LCDC_FRAME_DONE) {
-			tilcdc_crtc->frame_done = true;
-			wake_up(&tilcdc_crtc->frame_done_wq);
-		}
+	if (stat & LCDC_PL_LOAD_DONE) {
+		complete(&tilcdc_crtc->palette_loaded);
+		if (priv->rev == 1)
+			tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+				     LCDC_V1_PL_INT_ENA);
+		else
+			tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
+				     LCDC_V2_PL_INT_ENA);
+	}
 
-		if (stat & LCDC_SYNC_LOST) {
-			dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
-					    __func__, stat);
-			tilcdc_crtc->frame_intact = false;
+	if (stat & LCDC_SYNC_LOST) {
+		dev_err_ratelimited(dev->dev, "%s(0x%08x): Sync lost",
+				    __func__, stat);
+		tilcdc_crtc->frame_intact = false;
+		if (priv->rev == 1) {
+			reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG);
+			if (reg & LCDC_RASTER_ENABLE) {
+				tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+					     LCDC_RASTER_ENABLE);
+				tilcdc_set(dev, LCDC_RASTER_CTRL_REG,
+					   LCDC_RASTER_ENABLE);
+			}
+		} else {
 			if (tilcdc_crtc->sync_lost_count++ >
 			    SYNC_LOST_COUNT_LIMIT) {
-				dev_err(dev->dev, "%s(0x%08x): Sync lost flood detected, disabling the interrupt", __func__, stat);
+				dev_err(dev->dev,
+					"%s(0x%08x): Sync lost flood detected, recovering",
+					__func__, stat);
+				queue_work(system_wq,
+					   &tilcdc_crtc->recover_work);
 				tilcdc_write(dev, LCDC_INT_ENABLE_CLR_REG,
 					     LCDC_SYNC_LOST);
+				tilcdc_crtc->sync_lost_count = 0;
 			}
 		}
+	}
 
+	if (stat & LCDC_FRAME_DONE) {
+		tilcdc_crtc->frame_done = true;
+		wake_up(&tilcdc_crtc->frame_done_wq);
+		/* rev 1 lcdc appears to hang if irq is not disbaled here */
+		if (priv->rev == 1)
+			tilcdc_clear(dev, LCDC_RASTER_CTRL_REG,
+				     LCDC_V1_FRAME_DONE_INT_ENA);
+	}
+
+	/* For revision 2 only */
+	if (priv->rev == 2) {
 		/* Indicate to LCDC that the interrupt service routine has
 		 * completed, see 13.3.6.1.6 in AM335x TRM.
 		 */
@@ -787,7 +964,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_c
 	return IRQ_HANDLED;
 }
 
-struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev)
+int tilcdc_crtc_create(struct drm_device *dev)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
 	struct tilcdc_crtc *tilcdc_crtc;
@@ -797,21 +974,33 @@ struct drm_crtc *tilcdc_crtc_create(stru
 	tilcdc_crtc = devm_kzalloc(dev->dev, sizeof(*tilcdc_crtc), GFP_KERNEL);
 	if (!tilcdc_crtc) {
 		dev_err(dev->dev, "allocation failed\n");
-		return NULL;
+		return -ENOMEM;
 	}
 
+	init_completion(&tilcdc_crtc->palette_loaded);
+	tilcdc_crtc->palette_base = dmam_alloc_coherent(dev->dev,
+					TILCDC_PALETTE_SIZE,
+					&tilcdc_crtc->palette_dma_handle,
+					GFP_KERNEL | __GFP_ZERO);
+	if (!tilcdc_crtc->palette_base)
+		return -ENOMEM;
+	*tilcdc_crtc->palette_base = TILCDC_PALETTE_FIRST_ENTRY;
+
 	crtc = &tilcdc_crtc->base;
 
 	ret = tilcdc_plane_init(dev, &tilcdc_crtc->primary);
 	if (ret < 0)
 		goto fail;
 
+	mutex_init(&tilcdc_crtc->enable_lock);
+
 	init_waitqueue_head(&tilcdc_crtc->frame_done_wq);
 
 	drm_flip_work_init(&tilcdc_crtc->unref_work,
 			"unref", unref_worker);
 
 	spin_lock_init(&tilcdc_crtc->irq_lock);
+	INIT_WORK(&tilcdc_crtc->recover_work, tilcdc_crtc_recover_work);
 
 	ret = drm_crtc_init_with_planes(dev, crtc,
 					&tilcdc_crtc->primary,
@@ -837,13 +1026,15 @@ struct drm_crtc *tilcdc_crtc_create(stru
 		if (!crtc->port) { /* This should never happen */
 			dev_err(dev->dev, "Port node not found in %s\n",
 				dev->dev->of_node->full_name);
+			ret = -EINVAL;
 			goto fail;
 		}
 	}
 
-	return crtc;
+	priv->crtc = crtc;
+	return 0;
 
 fail:
 	tilcdc_crtc_destroy(crtc);
-	return NULL;
+	return -ENOMEM;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -127,24 +127,16 @@ static int tilcdc_commit(struct drm_devi
 	 * current layout.
 	 */
 
-	/* Keep HW on while we commit the state. */
-	pm_runtime_get_sync(dev->dev);
-
 	drm_atomic_helper_commit_modeset_disables(dev, state);
 
 	drm_atomic_helper_commit_planes(dev, state, 0);
 
 	drm_atomic_helper_commit_modeset_enables(dev, state);
 
-	/* Now HW should remain on if need becase the crtc is enabled */
-	pm_runtime_put_sync(dev->dev);
-
 	drm_atomic_helper_wait_for_vblanks(dev, state);
 
 	drm_atomic_helper_cleanup_planes(dev, state);
 
-	drm_atomic_state_free(state);
-
 	return 0;
 }
 
@@ -155,15 +147,11 @@ static const struct drm_mode_config_func
 	.atomic_commit = tilcdc_commit,
 };
 
-static int modeset_init(struct drm_device *dev)
+static void modeset_init(struct drm_device *dev)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
 	struct tilcdc_module *mod;
 
-	drm_mode_config_init(dev);
-
-	priv->crtc = tilcdc_crtc_create(dev);
-
 	list_for_each_entry(mod, &module_list, list) {
 		DBG("loading module: %s", mod->name);
 		mod->funcs->modeset_init(mod, dev);
@@ -174,8 +162,6 @@ static int modeset_init(struct drm_devic
 	dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc);
 	dev->mode_config.max_height = 2048;
 	dev->mode_config.funcs = &mode_config_funcs;
-
-	return 0;
 }
 
 #ifdef CONFIG_CPU_FREQ
@@ -196,22 +182,29 @@ static int cpufreq_transition(struct not
  * DRM operations:
  */
 
-static int tilcdc_unload(struct drm_device *dev)
+static void tilcdc_fini(struct drm_device *dev)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
 
-	tilcdc_remove_external_encoders(dev);
+	if (priv->crtc)
+		tilcdc_crtc_shutdown(priv->crtc);
+
+	if (priv->is_registered)
+		drm_dev_unregister(dev);
 
-	drm_fbdev_cma_fini(priv->fbdev);
 	drm_kms_helper_poll_fini(dev);
-	drm_mode_config_cleanup(dev);
-	drm_vblank_cleanup(dev);
+
+	if (priv->fbdev)
+		drm_fbdev_cma_fini(priv->fbdev);
 
 	drm_irq_uninstall(dev);
+	drm_mode_config_cleanup(dev);
+	tilcdc_remove_external_device(dev);
 
 #ifdef CONFIG_CPU_FREQ
-	cpufreq_unregister_notifier(&priv->freq_transition,
-			CPUFREQ_TRANSITION_NOTIFIER);
+	if (priv->freq_transition.notifier_call)
+		cpufreq_unregister_notifier(&priv->freq_transition,
+					    CPUFREQ_TRANSITION_NOTIFIER);
 #endif
 
 	if (priv->clk)
@@ -220,61 +213,71 @@ static int tilcdc_unload(struct drm_devi
 	if (priv->mmio)
 		iounmap(priv->mmio);
 
-	flush_workqueue(priv->wq);
-	destroy_workqueue(priv->wq);
+	if (priv->wq) {
+		flush_workqueue(priv->wq);
+		destroy_workqueue(priv->wq);
+	}
 
 	dev->dev_private = NULL;
 
 	pm_runtime_disable(dev->dev);
 
-	return 0;
+	drm_dev_unref(dev);
 }
 
-static int tilcdc_load(struct drm_device *dev, unsigned long flags)
+static int tilcdc_init(struct drm_driver *ddrv, struct device *dev)
 {
-	struct platform_device *pdev = dev->platformdev;
-	struct device_node *node = pdev->dev.of_node;
+	struct drm_device *ddev;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct device_node *node = dev->of_node;
 	struct tilcdc_drm_private *priv;
 	struct resource *res;
 	u32 bpp = 0;
 	int ret;
 
-	priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
-		dev_err(dev->dev, "failed to allocate private data\n");
+		dev_err(dev, "failed to allocate private data\n");
 		return -ENOMEM;
 	}
 
-	dev->dev_private = priv;
+	ddev = drm_dev_alloc(ddrv, dev);
+	if (IS_ERR(ddev))
+		return PTR_ERR(ddev);
+
+	ddev->platformdev = pdev;
+	ddev->dev_private = priv;
+	platform_set_drvdata(pdev, ddev);
+	drm_mode_config_init(ddev);
 
 	priv->is_componentized =
-		tilcdc_get_external_components(dev->dev, NULL) > 0;
+		tilcdc_get_external_components(dev, NULL) > 0;
 
 	priv->wq = alloc_ordered_workqueue("tilcdc", 0);
 	if (!priv->wq) {
 		ret = -ENOMEM;
-		goto fail_unset_priv;
+		goto init_failed;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
-		dev_err(dev->dev, "failed to get memory resource\n");
+		dev_err(dev, "failed to get memory resource\n");
 		ret = -EINVAL;
-		goto fail_free_wq;
+		goto init_failed;
 	}
 
 	priv->mmio = ioremap_nocache(res->start, resource_size(res));
 	if (!priv->mmio) {
-		dev_err(dev->dev, "failed to ioremap\n");
+		dev_err(dev, "failed to ioremap\n");
 		ret = -ENOMEM;
-		goto fail_free_wq;
+		goto init_failed;
 	}
 
-	priv->clk = clk_get(dev->dev, "fck");
+	priv->clk = clk_get(dev, "fck");
 	if (IS_ERR(priv->clk)) {
-		dev_err(dev->dev, "failed to get functional clock\n");
+		dev_err(dev, "failed to get functional clock\n");
 		ret = -ENODEV;
-		goto fail_iounmap;
+		goto init_failed;
 	}
 
 #ifdef CONFIG_CPU_FREQ
@@ -282,8 +285,9 @@ static int tilcdc_load(struct drm_device
 	ret = cpufreq_register_notifier(&priv->freq_transition,
 			CPUFREQ_TRANSITION_NOTIFIER);
 	if (ret) {
-		dev_err(dev->dev, "failed to register cpufreq notifier\n");
-		goto fail_put_clk;
+		dev_err(dev, "failed to register cpufreq notifier\n");
+		priv->freq_transition.notifier_call = NULL;
+		goto init_failed;
 	}
 #endif
 
@@ -292,22 +296,22 @@ static int tilcdc_load(struct drm_device
 
 	DBG("Maximum Bandwidth Value %d", priv->max_bandwidth);
 
-	if (of_property_read_u32(node, "ti,max-width", &priv->max_width))
+	if (of_property_read_u32(node, "max-width", &priv->max_width))
 		priv->max_width = TILCDC_DEFAULT_MAX_WIDTH;
 
 	DBG("Maximum Horizontal Pixel Width Value %dpixels", priv->max_width);
 
-	if (of_property_read_u32(node, "ti,max-pixelclock",
+	if (of_property_read_u32(node, "max-pixelclock",
 					&priv->max_pixelclock))
 		priv->max_pixelclock = TILCDC_DEFAULT_MAX_PIXELCLOCK;
 
 	DBG("Maximum Pixel Clock Value %dKHz", priv->max_pixelclock);
 
-	pm_runtime_enable(dev->dev);
+	pm_runtime_enable(dev);
 
 	/* Determine LCD IP Version */
-	pm_runtime_get_sync(dev->dev);
-	switch (tilcdc_read(dev, LCDC_PID_REG)) {
+	pm_runtime_get_sync(dev);
+	switch (tilcdc_read(ddev, LCDC_PID_REG)) {
 	case 0x4c100102:
 		priv->rev = 1;
 		break;
@@ -316,14 +320,14 @@ static int tilcdc_load(struct drm_device
 		priv->rev = 2;
 		break;
 	default:
-		dev_warn(dev->dev, "Unknown PID Reg value 0x%08x, "
-				"defaulting to LCD revision 1\n",
-				tilcdc_read(dev, LCDC_PID_REG));
+		dev_warn(dev, "Unknown PID Reg value 0x%08x, "
+			"defaulting to LCD revision 1\n",
+			tilcdc_read(ddev, LCDC_PID_REG));
 		priv->rev = 1;
 		break;
 	}
 
-	pm_runtime_put_sync(dev->dev);
+	pm_runtime_put_sync(dev);
 
 	if (priv->rev == 1) {
 		DBG("Revision 1 LCDC supports only RGB565 format");
@@ -356,91 +360,67 @@ static int tilcdc_load(struct drm_device
 		}
 	}
 
-	ret = modeset_init(dev);
+	ret = tilcdc_crtc_create(ddev);
 	if (ret < 0) {
-		dev_err(dev->dev, "failed to initialize mode setting\n");
-		goto fail_cpufreq_unregister;
+		dev_err(dev, "failed to create crtc\n");
+		goto init_failed;
 	}
-
-	platform_set_drvdata(pdev, dev);
+	modeset_init(ddev);
 
 	if (priv->is_componentized) {
-		ret = component_bind_all(dev->dev, dev);
+		ret = component_bind_all(dev, ddev);
 		if (ret < 0)
-			goto fail_mode_config_cleanup;
+			goto init_failed;
 
-		ret = tilcdc_add_external_encoders(dev);
+		ret = tilcdc_add_component_encoder(ddev);
 		if (ret < 0)
-			goto fail_component_cleanup;
+			goto init_failed;
+	} else {
+		ret = tilcdc_attach_external_device(ddev);
+		if (ret)
+			goto init_failed;
 	}
 
-	if ((priv->num_encoders == 0) || (priv->num_connectors == 0)) {
-		dev_err(dev->dev, "no encoders/connectors found\n");
+	if (!priv->external_connector &&
+	    ((priv->num_encoders == 0) || (priv->num_connectors == 0))) {
+		dev_err(dev, "no encoders/connectors found\n");
 		ret = -ENXIO;
-		goto fail_external_cleanup;
+		goto init_failed;
 	}
 
-	ret = drm_vblank_init(dev, 1);
+	ret = drm_vblank_init(ddev, 1);
 	if (ret < 0) {
-		dev_err(dev->dev, "failed to initialize vblank\n");
-		goto fail_external_cleanup;
+		dev_err(dev, "failed to initialize vblank\n");
+		goto init_failed;
 	}
 
-	ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
+	ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
 	if (ret < 0) {
-		dev_err(dev->dev, "failed to install IRQ handler\n");
-		goto fail_vblank_cleanup;
+		dev_err(dev, "failed to install IRQ handler\n");
+		goto init_failed;
 	}
 
-	drm_mode_config_reset(dev);
+	drm_mode_config_reset(ddev);
 
-	priv->fbdev = drm_fbdev_cma_init(dev, bpp,
-			dev->mode_config.num_crtc,
-			dev->mode_config.num_connector);
+	priv->fbdev = drm_fbdev_cma_init(ddev, bpp,
+			ddev->mode_config.num_crtc,
+			ddev->mode_config.num_connector);
 	if (IS_ERR(priv->fbdev)) {
 		ret = PTR_ERR(priv->fbdev);
-		goto fail_irq_uninstall;
+		goto init_failed;
 	}
 
-	drm_kms_helper_poll_init(dev);
-
-	return 0;
-
-fail_irq_uninstall:
-	drm_irq_uninstall(dev);
-
-fail_vblank_cleanup:
-	drm_vblank_cleanup(dev);
-
-fail_component_cleanup:
-	if (priv->is_componentized)
-		component_unbind_all(dev->dev, dev);
-
-fail_mode_config_cleanup:
-	drm_mode_config_cleanup(dev);
-
-fail_external_cleanup:
-	tilcdc_remove_external_encoders(dev);
-
-fail_cpufreq_unregister:
-	pm_runtime_disable(dev->dev);
-#ifdef CONFIG_CPU_FREQ
-	cpufreq_unregister_notifier(&priv->freq_transition,
-			CPUFREQ_TRANSITION_NOTIFIER);
-
-fail_put_clk:
-#endif
-	clk_put(priv->clk);
+	drm_kms_helper_poll_init(ddev);
 
-fail_iounmap:
-	iounmap(priv->mmio);
+	ret = drm_dev_register(ddev, 0);
+	if (ret)
+		goto init_failed;
 
-fail_free_wq:
-	flush_workqueue(priv->wq);
-	destroy_workqueue(priv->wq);
+	priv->is_registered = true;
+	return 0;
 
-fail_unset_priv:
-	dev->dev_private = NULL;
+init_failed:
+	tilcdc_fini(ddev);
 
 	return ret;
 }
@@ -575,9 +555,7 @@ static const struct file_operations fops
 	.open               = drm_open,
 	.release            = drm_release,
 	.unlocked_ioctl     = drm_ioctl,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl       = drm_compat_ioctl,
-#endif
 	.poll               = drm_poll,
 	.read               = drm_read,
 	.llseek             = no_llseek,
@@ -587,8 +565,6 @@ static const struct file_operations fops
 static struct drm_driver tilcdc_driver = {
 	.driver_features    = (DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET |
 			       DRIVER_PRIME | DRIVER_ATOMIC),
-	.load               = tilcdc_load,
-	.unload             = tilcdc_unload,
 	.lastclose          = tilcdc_lastclose,
 	.irq_handler        = tilcdc_irq,
 	.get_vblank_counter = drm_vblank_no_hw_counter,
@@ -662,10 +638,9 @@ static const struct dev_pm_ops tilcdc_pm
 /*
  * Platform driver:
  */
-
 static int tilcdc_bind(struct device *dev)
 {
-	return drm_platform_init(&tilcdc_driver, to_platform_device(dev));
+	return tilcdc_init(&tilcdc_driver, dev);
 }
 
 static void tilcdc_unbind(struct device *dev)
@@ -676,7 +651,7 @@ static void tilcdc_unbind(struct device
 	if (!ddev->dev_private)
 		return;
 
-	drm_put_dev(dev_get_drvdata(dev));
+	tilcdc_fini(dev_get_drvdata(dev));
 }
 
 static const struct component_master_ops tilcdc_comp_ops = {
@@ -699,7 +674,7 @@ static int tilcdc_pdev_probe(struct plat
 	if (ret < 0)
 		return ret;
 	else if (ret == 0)
-		return drm_platform_init(&tilcdc_driver, pdev);
+		return tilcdc_init(&tilcdc_driver, &pdev->dev);
 	else
 		return component_master_add_with_match(&pdev->dev,
 						       &tilcdc_comp_ops,
@@ -714,7 +689,7 @@ static int tilcdc_pdev_remove(struct pla
 	if (ret < 0)
 		return ret;
 	else if (ret == 0)
-		drm_put_dev(platform_get_drvdata(pdev));
+		tilcdc_fini(platform_get_drvdata(pdev));
 	else
 		component_master_del(&pdev->dev, &tilcdc_comp_ops);
 
@@ -723,6 +698,7 @@ static int tilcdc_pdev_remove(struct pla
 
 static struct of_device_id tilcdc_of_match[] = {
 		{ .compatible = "ti,am33xx-tilcdc", },
+		{ .compatible = "ti,da850-tilcdc", },
 		{ },
 };
 MODULE_DEVICE_TABLE(of, tilcdc_of_match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,6 +33,7 @@
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_bridge.h>
 
 /* Defaulting to pixel clock defined on AM335x */
 #define TILCDC_DEFAULT_MAX_PIXELCLOCK  126000
@@ -87,8 +88,12 @@ struct tilcdc_drm_private {
 
 	unsigned int num_connectors;
 	struct drm_connector *connectors[8];
-	const struct drm_connector_helper_funcs *connector_funcs[8];
 
+	struct drm_encoder *external_encoder;
+	struct drm_connector *external_connector;
+	const struct drm_connector_helper_funcs *connector_funcs;
+
+	bool is_registered;
 	bool is_componentized;
 };
 
@@ -163,7 +168,7 @@ struct tilcdc_panel_info {
 
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 
-struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev);
+int tilcdc_crtc_create(struct drm_device *dev);
 irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc);
 void tilcdc_crtc_update_clk(struct drm_crtc *crtc);
 void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc,
@@ -172,7 +177,7 @@ void tilcdc_crtc_set_simulate_vesa_sync(
 					bool simulate_vesa_sync);
 int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode);
 int tilcdc_crtc_max_width(struct drm_crtc *crtc);
-void tilcdc_crtc_disable(struct drm_crtc *crtc);
+void tilcdc_crtc_shutdown(struct drm_crtc *crtc);
 int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
 		struct drm_framebuffer *fb,
 		struct drm_pending_vblank_event *event);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/component.h>
 #include <linux/of_graph.h>
+#include <drm/drm_of.h>
 
 #include "tilcdc_drv.h"
 #include "tilcdc_external.h"
@@ -27,44 +28,50 @@ static const struct tilcdc_panel_info pa
 		.raster_order           = 0,
 };
 
+static const struct tilcdc_panel_info panel_info_default = {
+		.ac_bias                = 255,
+		.ac_bias_intrpt         = 0,
+		.dma_burst_sz           = 16,
+		.bpp                    = 16,
+		.fdd                    = 0x80,
+		.tft_alt_mode           = 0,
+		.sync_edge              = 0,
+		.sync_ctrl              = 1,
+		.raster_order           = 0,
+};
+
 static int tilcdc_external_mode_valid(struct drm_connector *connector,
 				      struct drm_display_mode *mode)
 {
 	struct tilcdc_drm_private *priv = connector->dev->dev_private;
-	int ret, i;
+	int ret;
 
 	ret = tilcdc_crtc_mode_valid(priv->crtc, mode);
 	if (ret != MODE_OK)
 		return ret;
 
-	for (i = 0; i < priv->num_connectors &&
-		     priv->connectors[i] != connector; i++)
-		;
-
-	BUG_ON(priv->connectors[i] != connector);
-	BUG_ON(!priv->connector_funcs[i]);
+	BUG_ON(priv->external_connector != connector);
+	BUG_ON(!priv->connector_funcs);
 
 	/* If the connector has its own mode_valid call it. */
-	if (!IS_ERR(priv->connector_funcs[i]) &&
-	    priv->connector_funcs[i]->mode_valid)
-		return priv->connector_funcs[i]->mode_valid(connector, mode);
+	if (!IS_ERR(priv->connector_funcs) &&
+	    priv->connector_funcs->mode_valid)
+		return priv->connector_funcs->mode_valid(connector, mode);
 
 	return MODE_OK;
 }
 
-static int tilcdc_add_external_encoder(struct drm_device *dev,
-				       struct drm_connector *connector)
+static int tilcdc_add_external_connector(struct drm_device *dev,
+					 struct drm_connector *connector)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
 	struct drm_connector_helper_funcs *connector_funcs;
 
-	priv->connectors[priv->num_connectors] = connector;
-	priv->encoders[priv->num_encoders++] = connector->encoder;
-
-	/* Only tda998x is supported at the moment. */
-	tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true);
-	tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x);
+	/* There should never be more than one connector */
+	if (WARN_ON(priv->external_connector))
+		return -EINVAL;
 
+	priv->external_connector = connector;
 	connector_funcs = devm_kzalloc(dev->dev, sizeof(*connector_funcs),
 				       GFP_KERNEL);
 	if (!connector_funcs)
@@ -77,56 +84,177 @@ static int tilcdc_add_external_encoder(s
 	 * everything else but use our own mode_valid() (above).
 	 */
 	if (connector->helper_private) {
-		priv->connector_funcs[priv->num_connectors] =
-			connector->helper_private;
-		*connector_funcs = *priv->connector_funcs[priv->num_connectors];
+		priv->connector_funcs =	connector->helper_private;
+		*connector_funcs = *priv->connector_funcs;
 	} else {
-		priv->connector_funcs[priv->num_connectors] = ERR_PTR(-ENOENT);
+		priv->connector_funcs = ERR_PTR(-ENOENT);
 	}
 	connector_funcs->mode_valid = tilcdc_external_mode_valid;
 	drm_connector_helper_add(connector, connector_funcs);
-	priv->num_connectors++;
 
-	dev_dbg(dev->dev, "External encoder '%s' connected\n",
-		connector->encoder->name);
+	dev_dbg(dev->dev, "External connector '%s' connected\n",
+		connector->name);
 
 	return 0;
 }
 
-int tilcdc_add_external_encoders(struct drm_device *dev)
+static
+struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev,
+						    struct drm_encoder *encoder)
 {
-	struct tilcdc_drm_private *priv = dev->dev_private;
 	struct drm_connector *connector;
-	int num_internal_connectors = priv->num_connectors;
+	int i;
 
-	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-		bool found = false;
-		int i, ret;
+	list_for_each_entry(connector, &ddev->mode_config.connector_list, head)
+		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
+			if (connector->encoder_ids[i] == encoder->base.id)
+				return connector;
 
-		for (i = 0; i < num_internal_connectors; i++)
-			if (connector == priv->connectors[i])
-				found = true;
-		if (!found) {
-			ret = tilcdc_add_external_encoder(dev, connector);
-			if (ret)
-				return ret;
-		}
+	dev_err(ddev->dev, "No connector found for %s encoder (id %d)\n",
+		encoder->name, encoder->base.id);
+
+	return NULL;
+}
+
+int tilcdc_add_component_encoder(struct drm_device *ddev)
+{
+	struct tilcdc_drm_private *priv = ddev->dev_private;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &ddev->mode_config.encoder_list, head)
+		if (encoder->possible_crtcs & (1 << priv->crtc->index))
+			break;
+
+	if (!encoder) {
+		dev_err(ddev->dev, "%s: No suitable encoder found\n", __func__);
+		return -ENODEV;
 	}
-	return 0;
+
+	connector = tilcdc_encoder_find_connector(ddev, encoder);
+
+	if (!connector)
+		return -ENODEV;
+
+	/* Only tda998x is supported at the moment. */
+	tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true);
+	tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x);
+
+	return tilcdc_add_external_connector(ddev, connector);
 }
 
-void tilcdc_remove_external_encoders(struct drm_device *dev)
+void tilcdc_remove_external_device(struct drm_device *dev)
 {
 	struct tilcdc_drm_private *priv = dev->dev_private;
-	int i;
 
 	/* Restore the original helper functions, if any. */
-	for (i = 0; i < priv->num_connectors; i++)
-		if (IS_ERR(priv->connector_funcs[i]))
-			drm_connector_helper_add(priv->connectors[i], NULL);
-		else if (priv->connector_funcs[i])
-			drm_connector_helper_add(priv->connectors[i],
-						 priv->connector_funcs[i]);
+	if (IS_ERR(priv->connector_funcs))
+		drm_connector_helper_add(priv->external_connector, NULL);
+	else if (priv->connector_funcs)
+		drm_connector_helper_add(priv->external_connector,
+					 priv->connector_funcs);
+}
+
+static const struct drm_encoder_funcs tilcdc_external_encoder_funcs = {
+	.destroy	= drm_encoder_cleanup,
+};
+
+static
+int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge)
+{
+	struct tilcdc_drm_private *priv = ddev->dev_private;
+	struct drm_connector *connector;
+	int ret;
+
+	priv->external_encoder->possible_crtcs = BIT(0);
+	priv->external_encoder->bridge = bridge;
+	bridge->encoder = priv->external_encoder;
+
+	ret = drm_bridge_attach(ddev, bridge);
+	if (ret) {
+		dev_err(ddev->dev, "drm_bridge_attach() failed %d\n", ret);
+		return ret;
+	}
+
+	tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default);
+
+	connector = tilcdc_encoder_find_connector(ddev, priv->external_encoder);
+	if (!connector)
+		return -ENODEV;
+
+	ret = tilcdc_add_external_connector(ddev, connector);
+
+	return ret;
+}
+
+static int tilcdc_node_has_port(struct device_node *dev_node)
+{
+	struct device_node *node;
+
+	node = of_get_child_by_name(dev_node, "ports");
+	if (!node)
+		node = of_get_child_by_name(dev_node, "port");
+	if (!node)
+		return 0;
+	of_node_put(node);
+
+	return 1;
+}
+
+static
+struct device_node *tilcdc_get_remote_node(struct device_node *node)
+{
+	struct device_node *ep;
+	struct device_node *parent;
+
+	if (!tilcdc_node_has_port(node))
+		return NULL;
+
+	ep = of_graph_get_next_endpoint(node, NULL);
+	if (!ep)
+		return NULL;
+
+	parent = of_graph_get_remote_port_parent(ep);
+	of_node_put(ep);
+
+	return parent;
+}
+
+int tilcdc_attach_external_device(struct drm_device *ddev)
+{
+	struct tilcdc_drm_private *priv = ddev->dev_private;
+	struct device_node *remote_node;
+	struct drm_bridge *bridge;
+	int ret;
+
+	remote_node = tilcdc_get_remote_node(ddev->dev->of_node);
+	if (!remote_node)
+		return 0;
+
+	bridge = of_drm_find_bridge(remote_node);
+	of_node_put(remote_node);
+	if (!bridge)
+		return -EPROBE_DEFER;
+
+	priv->external_encoder = devm_kzalloc(ddev->dev,
+					      sizeof(*priv->external_encoder),
+					      GFP_KERNEL);
+	if (!priv->external_encoder)
+		return -ENOMEM;
+
+	ret = drm_encoder_init(ddev, priv->external_encoder,
+			       &tilcdc_external_encoder_funcs,
+			       DRM_MODE_ENCODER_NONE, NULL);
+	if (ret) {
+		dev_err(ddev->dev, "drm_encoder_init() failed %d\n", ret);
+		return ret;
+	}
+
+	ret = tilcdc_attach_bridge(ddev, bridge);
+	if (ret)
+		drm_encoder_cleanup(priv->external_encoder);
+
+	return ret;
 }
 
 static int dev_match_of(struct device *dev, void *data)
@@ -140,16 +268,10 @@ int tilcdc_get_external_components(struc
 	struct device_node *node;
 	struct device_node *ep = NULL;
 	int count = 0;
+	int ret = 0;
 
-	/* Avoid error print by of_graph_get_next_endpoint() if there
-	 * is no ports present.
-	 */
-	node = of_get_child_by_name(dev->of_node, "ports");
-	if (!node)
-		node = of_get_child_by_name(dev->of_node, "port");
-	if (!node)
+	if (!tilcdc_node_has_port(dev->of_node))
 		return 0;
-	of_node_put(node);
 
 	while ((ep = of_graph_get_next_endpoint(dev->of_node, ep))) {
 		node = of_graph_get_remote_port_parent(ep);
@@ -159,16 +281,20 @@ int tilcdc_get_external_components(struc
 		}
 
 		dev_dbg(dev, "Subdevice node '%s' found\n", node->name);
-		if (match)
-			component_match_add(dev, match, dev_match_of, node);
-		of_node_put(node);
-		count++;
-	}
 
-	if (count > 1) {
-		dev_err(dev, "Only one external encoder is supported\n");
-		return -EINVAL;
+		if (of_device_is_compatible(node, "nxp,tda998x")) {
+			if (match)
+				drm_of_component_match_add(dev, match,
+							   dev_match_of, node);
+			ret = 1;
+		}
+
+		of_node_put(node);
+		if (count++ > 1) {
+			dev_err(dev, "Only one port is supported\n");
+			return -EINVAL;
+		}
 	}
 
-	return count;
+	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_external.h	2017-02-12 16:03:20.000000000 -0500
@@ -18,8 +18,9 @@
 #ifndef __TILCDC_EXTERNAL_H__
 #define __TILCDC_EXTERNAL_H__
 
-int tilcdc_add_external_encoders(struct drm_device *dev);
-void tilcdc_remove_external_encoders(struct drm_device *dev);
+int tilcdc_add_component_encoder(struct drm_device *dev);
+void tilcdc_remove_external_device(struct drm_device *dev);
 int tilcdc_get_external_components(struct device *dev,
 				   struct component_match **match);
+int tilcdc_attach_external_device(struct drm_device *ddev);
 #endif /* __TILCDC_SLAVE_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_panel.c	2017-02-12 16:03:20.000000000 -0500
@@ -144,13 +144,6 @@ static void panel_connector_destroy(stru
 	drm_connector_cleanup(connector);
 }
 
-static enum drm_connector_status panel_connector_detect(
-		struct drm_connector *connector,
-		bool force)
-{
-	return connector_status_connected;
-}
-
 static int panel_connector_get_modes(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -197,7 +190,6 @@ static struct drm_encoder *panel_connect
 static const struct drm_connector_funcs panel_connector_funcs = {
 	.destroy            = panel_connector_destroy,
 	.dpms               = drm_atomic_helper_connector_dpms,
-	.detect             = panel_connector_detect,
 	.fill_modes         = drm_helper_probe_single_connector_modes,
 	.reset              = drm_atomic_helper_connector_reset,
 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
@@ -240,8 +232,6 @@ static struct drm_connector *panel_conne
 	if (ret)
 		goto fail;
 
-	drm_connector_register(connector);
-
 	return connector;
 
 fail:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@ static int tilcdc_plane_atomic_check(str
 {
 	struct drm_crtc_state *crtc_state;
 	struct drm_plane_state *old_state = plane->state;
-	unsigned int depth, bpp;
+	unsigned int pitch;
 
 	if (!state->crtc)
 		return 0;
@@ -68,8 +68,9 @@ static int tilcdc_plane_atomic_check(str
 		return -EINVAL;
 	}
 
-	drm_fb_get_bpp_depth(state->fb->pixel_format, &depth, &bpp);
-	if (state->fb->pitches[0] != crtc_state->mode.hdisplay * bpp / 8) {
+	pitch = crtc_state->mode.hdisplay *
+		drm_format_plane_cpp(state->fb->pixel_format, 0);
+	if (state->fb->pitches[0] != pitch) {
 		dev_err(plane->dev->dev,
 			"Invalid pitch: fb and crtc widths must be the same");
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_regs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_regs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,11 +34,14 @@
 
 /* LCDC DMA Control Register */
 #define LCDC_DMA_BURST_SIZE(x)                   ((x) << 4)
+#define LCDC_DMA_BURST_SIZE_MASK                 ((0x7) << 4)
 #define LCDC_DMA_BURST_1                         0x0
 #define LCDC_DMA_BURST_2                         0x1
 #define LCDC_DMA_BURST_4                         0x2
 #define LCDC_DMA_BURST_8                         0x3
 #define LCDC_DMA_BURST_16                        0x4
+#define LCDC_DMA_FIFO_THRESHOLD(x)               ((x) << 8)
+#define LCDC_DMA_FIFO_THRESHOLD_MASK             ((0x3) << 8)
 #define LCDC_V1_END_OF_FRAME_INT_ENA             BIT(2)
 #define LCDC_V2_END_OF_FRAME0_INT_ENA            BIT(8)
 #define LCDC_V2_END_OF_FRAME1_INT_ENA            BIT(9)
@@ -46,10 +49,12 @@
 
 /* LCDC Control Register */
 #define LCDC_CLK_DIVISOR(x)                      ((x) << 8)
+#define LCDC_CLK_DIVISOR_MASK                    ((0xFF) << 8)
 #define LCDC_RASTER_MODE                         0x01
 
 /* LCDC Raster Control Register */
 #define LCDC_PALETTE_LOAD_MODE(x)                ((x) << 20)
+#define LCDC_PALETTE_LOAD_MODE_MASK              ((0x3) << 20)
 #define PALETTE_AND_DATA                         0x00
 #define PALETTE_ONLY                             0x01
 #define DATA_ONLY                                0x02
@@ -61,6 +66,8 @@
 #define LCDC_V2_UNDERFLOW_INT_ENA                BIT(5)
 #define LCDC_V1_PL_INT_ENA                       BIT(4)
 #define LCDC_V2_PL_INT_ENA                       BIT(6)
+#define LCDC_V1_SYNC_LOST_INT_ENA                BIT(5)
+#define LCDC_V1_FRAME_DONE_INT_ENA               BIT(3)
 #define LCDC_MONOCHROME_MODE                     BIT(1)
 #define LCDC_RASTER_ENABLE                       BIT(0)
 #define LCDC_TFT_ALT_ENABLE                      BIT(23)
@@ -74,7 +81,9 @@
 
 /* LCDC Raster Timing 2 Register */
 #define LCDC_AC_BIAS_TRANSITIONS_PER_INT(x)      ((x) << 16)
+#define LCDC_AC_BIAS_TRANSITIONS_PER_INT_MASK    ((0xF) << 16)
 #define LCDC_AC_BIAS_FREQUENCY(x)                ((x) << 8)
+#define LCDC_AC_BIAS_FREQUENCY_MASK              ((0xFF) << 8)
 #define LCDC_SYNC_CTRL                           BIT(25)
 #define LCDC_SYNC_EDGE                           BIT(24)
 #define LCDC_INVERT_PIXEL_CLOCK                  BIT(22)
@@ -139,6 +148,12 @@ static inline u32 tilcdc_read(struct drm
 	return ioread32(priv->mmio + reg);
 }
 
+static inline void tilcdc_write_mask(struct drm_device *dev, u32 reg,
+				     u32 val, u32 mask)
+{
+	tilcdc_write(dev, reg, (tilcdc_read(dev, reg) & ~mask) | (val & mask));
+}
+
 static inline void tilcdc_set(struct drm_device *dev, u32 reg, u32 mask)
 {
 	tilcdc_write(dev, reg, tilcdc_read(dev, reg) | mask);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c	2017-02-12 16:03:20.000000000 -0500
@@ -249,8 +249,6 @@ static struct drm_connector *tfp410_conn
 	if (ret)
 		goto fail;
 
-	drm_connector_register(connector);
-
 	return connector;
 
 fail:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2017-02-12 16:03:20.000000000 -0500
@@ -148,7 +148,7 @@ static void ttm_bo_release_list(struct k
 	BUG_ON(!list_empty(&bo->ddestroy));
 	ttm_tt_destroy(bo->ttm);
 	atomic_dec(&bo->glob->bo_count);
-	fence_put(bo->moving);
+	dma_fence_put(bo->moving);
 	if (bo->resv == &bo->ttm_resv)
 		reservation_object_fini(&bo->ttm_resv);
 	mutex_destroy(&bo->wu_mutex);
@@ -426,20 +426,20 @@ static void ttm_bo_cleanup_memtype_use(s
 static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo)
 {
 	struct reservation_object_list *fobj;
-	struct fence *fence;
+	struct dma_fence *fence;
 	int i;
 
 	fobj = reservation_object_get_list(bo->resv);
 	fence = reservation_object_get_excl(bo->resv);
 	if (fence && !fence->ops->signaled)
-		fence_enable_sw_signaling(fence);
+		dma_fence_enable_sw_signaling(fence);
 
 	for (i = 0; fobj && i < fobj->shared_count; ++i) {
 		fence = rcu_dereference_protected(fobj->shared[i],
 					reservation_object_held(bo->resv));
 
 		if (!fence->ops->signaled)
-			fence_enable_sw_signaling(fence);
+			dma_fence_enable_sw_signaling(fence);
 	}
 }
 
@@ -717,6 +717,20 @@ out:
 	return ret;
 }
 
+bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
+			      const struct ttm_place *place)
+{
+	/* Don't evict this BO if it's outside of the
+	 * requested placement range
+	 */
+	if (place->fpfn >= (bo->mem.start + bo->mem.size) ||
+	    (place->lpfn && place->lpfn <= bo->mem.start))
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(ttm_bo_eviction_valuable);
+
 static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
 				uint32_t mem_type,
 				const struct ttm_place *place,
@@ -731,21 +745,16 @@ static int ttm_mem_evict_first(struct tt
 	spin_lock(&glob->lru_lock);
 	list_for_each_entry(bo, &man->lru, lru) {
 		ret = __ttm_bo_reserve(bo, false, true, NULL);
-		if (!ret) {
-			if (place && (place->fpfn || place->lpfn)) {
-				/* Don't evict this BO if it's outside of the
-				 * requested placement range
-				 */
-				if (place->fpfn >= (bo->mem.start + bo->mem.size) ||
-				    (place->lpfn && place->lpfn <= bo->mem.start)) {
-					__ttm_bo_unreserve(bo);
-					ret = -EBUSY;
-					continue;
-				}
-			}
+		if (ret)
+			continue;
 
-			break;
+		if (place && !bdev->driver->eviction_valuable(bo, place)) {
+			__ttm_bo_unreserve(bo);
+			ret = -EBUSY;
+			continue;
 		}
+
+		break;
 	}
 
 	if (ret) {
@@ -792,11 +801,11 @@ static int ttm_bo_add_move_fence(struct
 				 struct ttm_mem_type_manager *man,
 				 struct ttm_mem_reg *mem)
 {
-	struct fence *fence;
+	struct dma_fence *fence;
 	int ret;
 
 	spin_lock(&man->move_lock);
-	fence = fence_get(man->move);
+	fence = dma_fence_get(man->move);
 	spin_unlock(&man->move_lock);
 
 	if (fence) {
@@ -806,7 +815,7 @@ static int ttm_bo_add_move_fence(struct
 		if (unlikely(ret))
 			return ret;
 
-		fence_put(bo->moving);
+		dma_fence_put(bo->moving);
 		bo->moving = fence;
 	}
 
@@ -1286,7 +1295,7 @@ static int ttm_bo_force_list_clean(struc
 {
 	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
 	struct ttm_bo_global *glob = bdev->glob;
-	struct fence *fence;
+	struct dma_fence *fence;
 	int ret;
 
 	/*
@@ -1309,12 +1318,12 @@ static int ttm_bo_force_list_clean(struc
 	spin_unlock(&glob->lru_lock);
 
 	spin_lock(&man->move_lock);
-	fence = fence_get(man->move);
+	fence = dma_fence_get(man->move);
 	spin_unlock(&man->move_lock);
 
 	if (fence) {
-		ret = fence_wait(fence, false);
-		fence_put(fence);
+		ret = dma_fence_wait(fence, false);
+		dma_fence_put(fence);
 		if (ret) {
 			if (allow_errors) {
 				return ret;
@@ -1343,7 +1352,7 @@ int ttm_bo_clean_mm(struct ttm_bo_device
 		       mem_type);
 		return ret;
 	}
-	fence_put(man->move);
+	dma_fence_put(man->move);
 
 	man->use_type = false;
 	man->has_type = false;
@@ -1602,7 +1611,14 @@ EXPORT_SYMBOL(ttm_bo_unmap_virtual);
 int ttm_bo_wait(struct ttm_buffer_object *bo,
 		bool interruptible, bool no_wait)
 {
-	long timeout = no_wait ? 0 : 15 * HZ;
+	long timeout = 15 * HZ;
+
+	if (no_wait) {
+		if (reservation_object_test_signaled_rcu(bo->resv, true))
+			return 0;
+		else
+			return -EBUSY;
+	}
 
 	timeout = reservation_object_wait_timeout_rcu(bo->resv, true,
 						      interruptible, timeout);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_bo_util.c	2017-02-12 16:03:20.000000000 -0500
@@ -644,7 +644,7 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_ob
 EXPORT_SYMBOL(ttm_bo_kunmap);
 
 int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo,
-			      struct fence *fence,
+			      struct dma_fence *fence,
 			      bool evict,
 			      struct ttm_mem_reg *new_mem)
 {
@@ -674,8 +674,8 @@ int ttm_bo_move_accel_cleanup(struct ttm
 		 * operation has completed.
 		 */
 
-		fence_put(bo->moving);
-		bo->moving = fence_get(fence);
+		dma_fence_put(bo->moving);
+		bo->moving = dma_fence_get(fence);
 
 		ret = ttm_buffer_object_transfer(bo, &ghost_obj);
 		if (ret)
@@ -706,7 +706,7 @@ int ttm_bo_move_accel_cleanup(struct ttm
 EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);
 
 int ttm_bo_pipeline_move(struct ttm_buffer_object *bo,
-			 struct fence *fence, bool evict,
+			 struct dma_fence *fence, bool evict,
 			 struct ttm_mem_reg *new_mem)
 {
 	struct ttm_bo_device *bdev = bo->bdev;
@@ -730,8 +730,8 @@ int ttm_bo_pipeline_move(struct ttm_buff
 		 * operation has completed.
 		 */
 
-		fence_put(bo->moving);
-		bo->moving = fence_get(fence);
+		dma_fence_put(bo->moving);
+		bo->moving = dma_fence_get(fence);
 
 		ret = ttm_buffer_object_transfer(bo, &ghost_obj);
 		if (ret)
@@ -761,16 +761,16 @@ int ttm_bo_pipeline_move(struct ttm_buff
 		 */
 
 		spin_lock(&from->move_lock);
-		if (!from->move || fence_is_later(fence, from->move)) {
-			fence_put(from->move);
-			from->move = fence_get(fence);
+		if (!from->move || dma_fence_is_later(fence, from->move)) {
+			dma_fence_put(from->move);
+			from->move = dma_fence_get(fence);
 		}
 		spin_unlock(&from->move_lock);
 
 		ttm_bo_free_old_node(bo);
 
-		fence_put(bo->moving);
-		bo->moving = fence_get(fence);
+		dma_fence_put(bo->moving);
+		bo->moving = dma_fence_get(fence);
 
 	} else {
 		/**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_bo_vm.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@ static int ttm_bo_vm_fault_idle(struct t
 	/*
 	 * Quick non-stalling check for idle.
 	 */
-	if (fence_is_signaled(bo->moving))
+	if (dma_fence_is_signaled(bo->moving))
 		goto out_clear;
 
 	/*
@@ -67,14 +67,14 @@ static int ttm_bo_vm_fault_idle(struct t
 			goto out_unlock;
 
 		up_read(&vma->vm_mm->mmap_sem);
-		(void) fence_wait(bo->moving, true);
+		(void) dma_fence_wait(bo->moving, true);
 		goto out_unlock;
 	}
 
 	/*
 	 * Ordinary wait.
 	 */
-	ret = fence_wait(bo->moving, true);
+	ret = dma_fence_wait(bo->moving, true);
 	if (unlikely(ret != 0)) {
 		ret = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS :
 			VM_FAULT_NOPAGE;
@@ -82,7 +82,7 @@ static int ttm_bo_vm_fault_idle(struct t
 	}
 
 out_clear:
-	fence_put(bo->moving);
+	dma_fence_put(bo->moving);
 	bo->moving = NULL;
 
 out_unlock:
@@ -101,7 +101,7 @@ static int ttm_bo_vm_fault(struct vm_are
 	struct page *page;
 	int ret;
 	int i;
-	unsigned long address = (unsigned long)vmf->virtual_address;
+	unsigned long address = vmf->address;
 	int retval = VM_FAULT_NOPAGE;
 	struct ttm_mem_type_manager *man =
 		&bdev->man[bo->mem.mem_type];
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/ttm/ttm_execbuf_util.c	2017-02-12 16:03:20.000000000 -0500
@@ -179,7 +179,8 @@ int ttm_eu_reserve_buffers(struct ww_acq
 EXPORT_SYMBOL(ttm_eu_reserve_buffers);
 
 void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket,
-				 struct list_head *list, struct fence *fence)
+				 struct list_head *list,
+				 struct dma_fence *fence)
 {
 	struct ttm_validate_buffer *entry;
 	struct ttm_buffer_object *bo;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/udl/udl_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/udl/udl_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/udl/udl_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/udl/udl_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,9 +44,7 @@ static const struct file_operations udl_
 	.read = drm_read,
 	.unlocked_ioctl	= drm_ioctl,
 	.release = drm_release,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/udl/udl_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/udl/udl_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/udl/udl_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/udl/udl_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -254,16 +254,10 @@ static int udl_fb_release(struct fb_info
 
 static struct fb_ops udlfb_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par,
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_fillrect = drm_fb_helper_sys_fillrect,
 	.fb_copyarea = drm_fb_helper_sys_copyarea,
 	.fb_imageblit = drm_fb_helper_sys_imageblit,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 	.fb_mmap = udl_fb_mmap,
 	.fb_open = udl_fb_open,
 	.fb_release = udl_fb_release,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/udl/udl_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/udl/udl_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/udl/udl_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/udl/udl_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -107,14 +107,13 @@ int udl_gem_fault(struct vm_area_struct
 	unsigned int page_offset;
 	int ret = 0;
 
-	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
-		PAGE_SHIFT;
+	page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
 	if (!obj->pages)
 		return VM_FAULT_SIGBUS;
 
 	page = obj->pages[page_offset];
-	ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page);
+	ret = vm_insert_page(vma, vmf->address, page);
 	switch (ret) {
 	case -EAGAIN:
 	case 0:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,7 @@ vc4-y := \
 	vc4_kms.o \
 	vc4_gem.o \
 	vc4_hdmi.o \
+	vc4_vec.o \
 	vc4_hvs.o \
 	vc4_irq.o \
 	vc4_plane.o \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_crtc.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_crtc.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_crtc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_crtc.c	2017-02-12 16:03:20.000000000 -0500
@@ -83,8 +83,7 @@ struct vc4_crtc_data {
 	/* Which channel of the HVS this pixelvalve sources from. */
 	int hvs_channel;
 
-	enum vc4_encoder_type encoder0_type;
-	enum vc4_encoder_type encoder1_type;
+	enum vc4_encoder_type encoder_types[4];
 };
 
 #define CRTC_WRITE(offset, val) writel(val, vc4_crtc->regs + (offset))
@@ -669,6 +668,14 @@ void vc4_disable_vblank(struct drm_devic
 	CRTC_WRITE(PV_INTEN, 0);
 }
 
+/* Must be called with the event lock held */
+bool vc4_event_pending(struct drm_crtc *crtc)
+{
+	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+
+	return !!vc4_crtc->event;
+}
+
 static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
 {
 	struct drm_crtc *crtc = &vc4_crtc->base;
@@ -832,7 +839,7 @@ static void vc4_crtc_destroy_state(struc
 
 	}
 
-	__drm_atomic_helper_crtc_destroy_state(state);
+	drm_atomic_helper_crtc_destroy_state(crtc, state);
 }
 
 static const struct drm_crtc_funcs vc4_crtc_funcs = {
@@ -859,20 +866,26 @@ static const struct drm_crtc_helper_func
 
 static const struct vc4_crtc_data pv0_data = {
 	.hvs_channel = 0,
-	.encoder0_type = VC4_ENCODER_TYPE_DSI0,
-	.encoder1_type = VC4_ENCODER_TYPE_DPI,
+	.encoder_types = {
+		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI0,
+		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_DPI,
+	},
 };
 
 static const struct vc4_crtc_data pv1_data = {
 	.hvs_channel = 2,
-	.encoder0_type = VC4_ENCODER_TYPE_DSI1,
-	.encoder1_type = VC4_ENCODER_TYPE_SMI,
+	.encoder_types = {
+		[PV_CONTROL_CLK_SELECT_DSI] = VC4_ENCODER_TYPE_DSI1,
+		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_SMI,
+	},
 };
 
 static const struct vc4_crtc_data pv2_data = {
 	.hvs_channel = 1,
-	.encoder0_type = VC4_ENCODER_TYPE_VEC,
-	.encoder1_type = VC4_ENCODER_TYPE_HDMI,
+	.encoder_types = {
+		[PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI] = VC4_ENCODER_TYPE_HDMI,
+		[PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC,
+	},
 };
 
 static const struct of_device_id vc4_crtc_dt_match[] = {
@@ -886,17 +899,20 @@ static void vc4_set_crtc_possible_masks(
 					struct drm_crtc *crtc)
 {
 	struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
+	const struct vc4_crtc_data *crtc_data = vc4_crtc->data;
+	const enum vc4_encoder_type *encoder_types = crtc_data->encoder_types;
 	struct drm_encoder *encoder;
 
 	drm_for_each_encoder(encoder, drm) {
 		struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
+		int i;
 
-		if (vc4_encoder->type == vc4_crtc->data->encoder0_type) {
-			vc4_encoder->clock_select = 0;
-			encoder->possible_crtcs |= drm_crtc_mask(crtc);
-		} else if (vc4_encoder->type == vc4_crtc->data->encoder1_type) {
-			vc4_encoder->clock_select = 1;
-			encoder->possible_crtcs |= drm_crtc_mask(crtc);
+		for (i = 0; i < ARRAY_SIZE(crtc_data->encoder_types); i++) {
+			if (vc4_encoder->type == encoder_types[i]) {
+				vc4_encoder->clock_select = i;
+				encoder->possible_crtcs |= drm_crtc_mask(crtc);
+				break;
+			}
 		}
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,7 @@ static const struct drm_info_list vc4_de
 	{"bo_stats", vc4_bo_stats_debugfs, 0},
 	{"dpi_regs", vc4_dpi_debugfs_regs, 0},
 	{"hdmi_regs", vc4_hdmi_debugfs_regs, 0},
+	{"vec_regs", vc4_vec_debugfs_regs, 0},
 	{"hvs_regs", vc4_hvs_debugfs_regs, 0},
 	{"crtc0_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)0},
 	{"crtc1_regs", vc4_crtc_debugfs_regs, 0, (void *)(uintptr_t)1},
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,23 +61,28 @@ static int vc4_get_param_ioctl(struct dr
 		if (ret < 0)
 			return ret;
 		args->value = V3D_READ(V3D_IDENT0);
-		pm_runtime_put(&vc4->v3d->pdev->dev);
+		pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+		pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
 		break;
 	case DRM_VC4_PARAM_V3D_IDENT1:
 		ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
 		if (ret < 0)
 			return ret;
 		args->value = V3D_READ(V3D_IDENT1);
-		pm_runtime_put(&vc4->v3d->pdev->dev);
+		pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+		pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
 		break;
 	case DRM_VC4_PARAM_V3D_IDENT2:
 		ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
 		if (ret < 0)
 			return ret;
 		args->value = V3D_READ(V3D_IDENT2);
-		pm_runtime_put(&vc4->v3d->pdev->dev);
+		pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+		pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
 		break;
 	case DRM_VC4_PARAM_SUPPORTS_BRANCHES:
+	case DRM_VC4_PARAM_SUPPORTS_ETC1:
+	case DRM_VC4_PARAM_SUPPORTS_THREADED_FS:
 		args->value = true;
 		break;
 	default:
@@ -103,9 +108,7 @@ static const struct file_operations vc4_
 	.mmap = vc4_mmap,
 	.poll = drm_poll,
 	.read = drm_read,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
@@ -274,12 +277,14 @@ static void vc4_drm_unbind(struct device
 	struct drm_device *drm = platform_get_drvdata(pdev);
 	struct vc4_dev *vc4 = to_vc4_dev(drm);
 
+	drm_dev_unregister(drm);
+
 	if (vc4->fbdev)
 		drm_fbdev_cma_fini(vc4->fbdev);
 
 	drm_mode_config_cleanup(drm);
 
-	drm_put_dev(drm);
+	drm_dev_unref(drm);
 }
 
 static const struct component_master_ops vc4_drm_ops = {
@@ -289,6 +294,7 @@ static const struct component_master_ops
 
 static struct platform_driver *const component_drivers[] = {
 	&vc4_hdmi_driver,
+	&vc4_vec_driver,
 	&vc4_dpi_driver,
 	&vc4_hvs_driver,
 	&vc4_crtc_driver,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@ struct vc4_dev {
 	struct vc4_crtc *crtc[3];
 	struct vc4_v3d *v3d;
 	struct vc4_dpi *dpi;
+	struct vc4_vec *vec;
 
 	struct drm_fbdev_cma *fbdev;
 
@@ -194,6 +195,7 @@ to_vc4_plane(struct drm_plane *plane)
 }
 
 enum vc4_encoder_type {
+	VC4_ENCODER_TYPE_NONE,
 	VC4_ENCODER_TYPE_HDMI,
 	VC4_ENCODER_TYPE_VEC,
 	VC4_ENCODER_TYPE_DSI0,
@@ -381,6 +383,8 @@ struct vc4_validated_shader_info {
 
 	uint32_t num_uniform_addr_offsets;
 	uint32_t *uniform_addr_offsets;
+
+	bool is_threaded;
 };
 
 /**
@@ -440,6 +444,7 @@ int vc4_bo_stats_debugfs(struct seq_file
 extern struct platform_driver vc4_crtc_driver;
 int vc4_enable_vblank(struct drm_device *dev, unsigned int crtc_id);
 void vc4_disable_vblank(struct drm_device *dev, unsigned int crtc_id);
+bool vc4_event_pending(struct drm_crtc *crtc);
 int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
 int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
 			    unsigned int flags, int *vpos, int *hpos,
@@ -483,6 +488,10 @@ int vc4_queue_seqno_cb(struct drm_device
 extern struct platform_driver vc4_hdmi_driver;
 int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused);
 
+/* vc4_hdmi.c */
+extern struct platform_driver vc4_vec_driver;
+int vc4_vec_debugfs_regs(struct seq_file *m, void *unused);
+
 /* vc4_irq.c */
 irqreturn_t vc4_irq(int irq, void *arg);
 void vc4_irq_preinstall(struct drm_device *dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_gem.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_gem.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_gem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_gem.c	2017-02-12 16:03:20.000000000 -0500
@@ -544,14 +544,15 @@ vc4_cl_lookup_bos(struct drm_device *dev
 
 	handles = drm_malloc_ab(exec->bo_count, sizeof(uint32_t));
 	if (!handles) {
+		ret = -ENOMEM;
 		DRM_ERROR("Failed to allocate incoming GEM handles\n");
 		goto fail;
 	}
 
-	ret = copy_from_user(handles,
-			     (void __user *)(uintptr_t)args->bo_handles,
-			     exec->bo_count * sizeof(uint32_t));
-	if (ret) {
+	if (copy_from_user(handles,
+			   (void __user *)(uintptr_t)args->bo_handles,
+			   exec->bo_count * sizeof(uint32_t))) {
+		ret = -EFAULT;
 		DRM_ERROR("Failed to copy in GEM handles\n");
 		goto fail;
 	}
@@ -593,12 +594,14 @@ vc4_get_bcl(struct drm_device *dev, stru
 					  args->shader_rec_count);
 	struct vc4_bo *bo;
 
-	if (uniforms_offset < shader_rec_offset ||
+	if (shader_rec_offset < args->bin_cl_size ||
+	    uniforms_offset < shader_rec_offset ||
 	    exec_size < uniforms_offset ||
 	    args->shader_rec_count >= (UINT_MAX /
 					  sizeof(struct vc4_shader_state)) ||
 	    temp_size < exec_size) {
 		DRM_ERROR("overflow in exec arguments\n");
+		ret = -EINVAL;
 		goto fail;
 	}
 
@@ -708,8 +711,10 @@ vc4_complete_exec(struct drm_device *dev
 	}
 
 	mutex_lock(&vc4->power_lock);
-	if (--vc4->power_refcount == 0)
-		pm_runtime_put(&vc4->v3d->pdev->dev);
+	if (--vc4->power_refcount == 0) {
+		pm_runtime_mark_last_busy(&vc4->v3d->pdev->dev);
+		pm_runtime_put_autosuspend(&vc4->v3d->pdev->dev);
+	}
 	mutex_unlock(&vc4->power_lock);
 
 	kfree(exec);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,7 +61,7 @@ vc4_atomic_complete_commit(struct vc4_co
 
 	drm_atomic_helper_cleanup_planes(dev, state);
 
-	drm_atomic_state_free(state);
+	drm_atomic_state_put(state);
 
 	up(&vc4->async_modeset);
 
@@ -119,17 +119,34 @@ static int vc4_atomic_commit(struct drm_
 
 	/* Make sure that any outstanding modesets have finished. */
 	if (nonblock) {
-		ret = down_trylock(&vc4->async_modeset);
-		if (ret) {
+		struct drm_crtc *crtc;
+		struct drm_crtc_state *crtc_state;
+		unsigned long flags;
+		bool busy = false;
+
+		/*
+		 * If there's an undispatched event to send then we're
+		 * obviously still busy.  If there isn't, then we can
+		 * unconditionally wait for the semaphore because it
+		 * shouldn't be contended (for long).
+		 *
+		 * This is to prevent a race where queuing a new flip
+		 * from userspace immediately on receipt of an event
+		 * beats our clean-up and returns EBUSY.
+		 */
+		spin_lock_irqsave(&dev->event_lock, flags);
+		for_each_crtc_in_state(state, crtc, crtc_state, i)
+			busy |= vc4_event_pending(crtc);
+		spin_unlock_irqrestore(&dev->event_lock, flags);
+		if (busy) {
 			kfree(c);
 			return -EBUSY;
 		}
-	} else {
-		ret = down_interruptible(&vc4->async_modeset);
-		if (ret) {
-			kfree(c);
-			return ret;
-		}
+	}
+	ret = down_interruptible(&vc4->async_modeset);
+	if (ret) {
+		kfree(c);
+		return ret;
 	}
 
 	ret = drm_atomic_helper_prepare_planes(dev, state);
@@ -173,6 +190,7 @@ static int vc4_atomic_commit(struct drm_
 	 * current layout.
 	 */
 
+	drm_atomic_state_get(state);
 	if (nonblock) {
 		vc4_queue_seqno_cb(dev, &c->cb, wait_seqno,
 				   vc4_atomic_complete_commit_seqno_cb);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -858,7 +858,7 @@ struct drm_plane *vc4_plane_init(struct
 		}
 	}
 	plane = &vc4_plane->base;
-	ret = drm_universal_plane_init(dev, plane, 0xff,
+	ret = drm_universal_plane_init(dev, plane, 0,
 				       &vc4_plane_funcs,
 				       formats, num_formats,
 				       type, NULL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_regs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_regs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -177,8 +177,9 @@
 # define PV_CONTROL_WAIT_HSTART			BIT(12)
 # define PV_CONTROL_PIXEL_REP_MASK		VC4_MASK(5, 4)
 # define PV_CONTROL_PIXEL_REP_SHIFT		4
-# define PV_CONTROL_CLK_SELECT_DSI_VEC		0
+# define PV_CONTROL_CLK_SELECT_DSI		0
 # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI	1
+# define PV_CONTROL_CLK_SELECT_VEC		2
 # define PV_CONTROL_CLK_SELECT_MASK		VC4_MASK(3, 2)
 # define PV_CONTROL_CLK_SELECT_SHIFT		2
 # define PV_CONTROL_FIFO_CLR			BIT(1)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_render_cl.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_render_cl.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_render_cl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_render_cl.c	2017-02-12 16:03:20.000000000 -0500
@@ -461,7 +461,7 @@ static int vc4_rcl_surface_setup(struct
 		}
 
 		ret = vc4_full_res_bounds_check(exec, *obj, surf);
-		if (!ret)
+		if (ret)
 			return ret;
 
 		return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_v3d.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_v3d.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_v3d.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_v3d.c	2017-02-12 16:03:20.000000000 -0500
@@ -222,6 +222,8 @@ static int vc4_v3d_bind(struct device *d
 		return ret;
 	}
 
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
 	pm_runtime_enable(dev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_validate.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_validate.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_validate.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_validate.c	2017-02-12 16:03:20.000000000 -0500
@@ -644,6 +644,13 @@ reloc_tex(struct vc4_exec_info *exec,
 		cpp = 1;
 		break;
 	case VC4_TEXTURE_TYPE_ETC1:
+		/* ETC1 is arranged as 64-bit blocks, where each block is 4x4
+		 * pixels.
+		 */
+		cpp = 8;
+		width = (width + 3) >> 2;
+		height = (height + 3) >> 2;
+		break;
 	case VC4_TEXTURE_TYPE_BW1:
 	case VC4_TEXTURE_TYPE_A4:
 	case VC4_TEXTURE_TYPE_A1:
@@ -782,11 +789,6 @@ validate_gl_shader_rec(struct drm_device
 	exec->shader_rec_v += roundup(packet_size, 16);
 	exec->shader_rec_size -= packet_size;
 
-	if (!(*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD)) {
-		DRM_ERROR("Multi-threaded fragment shaders not supported.\n");
-		return -EINVAL;
-	}
-
 	for (i = 0; i < shader_reloc_count; i++) {
 		if (src_handles[i] > exec->bo_count) {
 			DRM_ERROR("Shader handle %d too big\n", src_handles[i]);
@@ -803,6 +805,18 @@ validate_gl_shader_rec(struct drm_device
 			return -EINVAL;
 	}
 
+	if (((*(uint16_t *)pkt_u & VC4_SHADER_FLAG_FS_SINGLE_THREAD) == 0) !=
+	    to_vc4_bo(&bo[0]->base)->validated_shader->is_threaded) {
+		DRM_ERROR("Thread mode of CL and FS do not match\n");
+		return -EINVAL;
+	}
+
+	if (to_vc4_bo(&bo[1]->base)->validated_shader->is_threaded ||
+	    to_vc4_bo(&bo[2]->base)->validated_shader->is_threaded) {
+		DRM_ERROR("cs and vs cannot be threaded\n");
+		return -EINVAL;
+	}
+
 	for (i = 0; i < shader_reloc_count; i++) {
 		struct vc4_validated_shader_info *validated_shader;
 		uint32_t o = shader_reloc_offsets[i];
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_validate_shaders.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_validate_shaders.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_validate_shaders.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_validate_shaders.c	2017-02-12 16:03:20.000000000 -0500
@@ -83,6 +83,13 @@ struct vc4_shader_validation_state {
 	 * basic blocks.
 	 */
 	bool needs_uniform_address_for_loop;
+
+	/* Set when we find an instruction writing the top half of the
+	 * register files.  If we allowed writing the unusable regs in
+	 * a threaded shader, then the other shader running on our
+	 * QPU's clamp validation would be invalid.
+	 */
+	bool all_registers_used;
 };
 
 static uint32_t
@@ -119,6 +126,13 @@ raddr_add_a_to_live_reg_index(uint64_t i
 }
 
 static bool
+live_reg_is_upper_half(uint32_t lri)
+{
+	return	(lri >= 16 && lri < 32) ||
+		(lri >= 32 + 16 && lri < 32 + 32);
+}
+
+static bool
 is_tmu_submit(uint32_t waddr)
 {
 	return (waddr == QPU_W_TMU0_S ||
@@ -390,6 +404,9 @@ check_reg_write(struct vc4_validated_sha
 		} else {
 			validation_state->live_immediates[lri] = ~0;
 		}
+
+		if (live_reg_is_upper_half(lri))
+			validation_state->all_registers_used = true;
 	}
 
 	switch (waddr) {
@@ -598,6 +615,11 @@ check_instruction_reads(struct vc4_valid
 		}
 	}
 
+	if ((raddr_a >= 16 && raddr_a < 32) ||
+	    (raddr_b >= 16 && raddr_b < 32 && sig != QPU_SIG_SMALL_IMM)) {
+		validation_state->all_registers_used = true;
+	}
+
 	return true;
 }
 
@@ -608,9 +630,7 @@ static bool
 vc4_validate_branches(struct vc4_shader_validation_state *validation_state)
 {
 	uint32_t max_branch_target = 0;
-	bool found_shader_end = false;
 	int ip;
-	int shader_end_ip = 0;
 	int last_branch = -2;
 
 	for (ip = 0; ip < validation_state->max_ip; ip++) {
@@ -621,8 +641,13 @@ vc4_validate_branches(struct vc4_shader_
 		uint32_t branch_target_ip;
 
 		if (sig == QPU_SIG_PROG_END) {
-			shader_end_ip = ip;
-			found_shader_end = true;
+			/* There are two delay slots after program end is
+			 * signaled that are still executed, then we're
+			 * finished.  validation_state->max_ip is the
+			 * instruction after the last valid instruction in the
+			 * program.
+			 */
+			validation_state->max_ip = ip + 3;
 			continue;
 		}
 
@@ -676,15 +701,9 @@ vc4_validate_branches(struct vc4_shader_
 		}
 		set_bit(after_delay_ip, validation_state->branch_targets);
 		max_branch_target = max(max_branch_target, after_delay_ip);
-
-		/* There are two delay slots after program end is signaled
-		 * that are still executed, then we're finished.
-		 */
-		if (found_shader_end && ip == shader_end_ip + 2)
-			break;
 	}
 
-	if (max_branch_target > shader_end_ip) {
+	if (max_branch_target > validation_state->max_ip - 3) {
 		DRM_ERROR("Branch landed after QPU_SIG_PROG_END");
 		return false;
 	}
@@ -756,6 +775,7 @@ vc4_validate_shader(struct drm_gem_cma_o
 {
 	bool found_shader_end = false;
 	int shader_end_ip = 0;
+	uint32_t last_thread_switch_ip = -3;
 	uint32_t ip;
 	struct vc4_validated_shader_info *validated_shader = NULL;
 	struct vc4_shader_validation_state validation_state;
@@ -788,6 +808,17 @@ vc4_validate_shader(struct drm_gem_cma_o
 		if (!vc4_handle_branch_target(&validation_state))
 			goto fail;
 
+		if (ip == last_thread_switch_ip + 3) {
+			/* Reset r0-r3 live clamp data */
+			int i;
+
+			for (i = 64; i < LIVE_REG_COUNT; i++) {
+				validation_state.live_min_clamp_offsets[i] = ~0;
+				validation_state.live_max_clamp_regs[i] = false;
+				validation_state.live_immediates[i] = ~0;
+			}
+		}
+
 		switch (sig) {
 		case QPU_SIG_NONE:
 		case QPU_SIG_WAIT_FOR_SCOREBOARD:
@@ -797,6 +828,8 @@ vc4_validate_shader(struct drm_gem_cma_o
 		case QPU_SIG_LOAD_TMU1:
 		case QPU_SIG_PROG_END:
 		case QPU_SIG_SMALL_IMM:
+		case QPU_SIG_THREAD_SWITCH:
+		case QPU_SIG_LAST_THREAD_SWITCH:
 			if (!check_instruction_writes(validated_shader,
 						      &validation_state)) {
 				DRM_ERROR("Bad write at ip %d\n", ip);
@@ -812,6 +845,18 @@ vc4_validate_shader(struct drm_gem_cma_o
 				shader_end_ip = ip;
 			}
 
+			if (sig == QPU_SIG_THREAD_SWITCH ||
+			    sig == QPU_SIG_LAST_THREAD_SWITCH) {
+				validated_shader->is_threaded = true;
+
+				if (ip < last_thread_switch_ip + 3) {
+					DRM_ERROR("Thread switch too soon after "
+						  "last switch at ip %d\n", ip);
+					goto fail;
+				}
+				last_thread_switch_ip = ip;
+			}
+
 			break;
 
 		case QPU_SIG_LOAD_IMM:
@@ -826,6 +871,13 @@ vc4_validate_shader(struct drm_gem_cma_o
 			if (!check_branch(inst, validated_shader,
 					  &validation_state, ip))
 				goto fail;
+
+			if (ip < last_thread_switch_ip + 3) {
+				DRM_ERROR("Branch in thread switch at ip %d",
+					  ip);
+				goto fail;
+			}
+
 			break;
 		default:
 			DRM_ERROR("Unsupported QPU signal %d at "
@@ -847,6 +899,14 @@ vc4_validate_shader(struct drm_gem_cma_o
 		goto fail;
 	}
 
+	/* Might corrupt other thread */
+	if (validated_shader->is_threaded &&
+	    validation_state.all_registers_used) {
+		DRM_ERROR("Shader uses threading, but uses the upper "
+			  "half of the registers, too\n");
+		goto fail;
+	}
+
 	/* If we did a backwards branch and we haven't emitted a uniforms
 	 * reset since then, we still need the uniforms stream to have the
 	 * uniforms address available so that the backwards branch can do its
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_vec.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_vec.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vc4/vc4_vec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vc4/vc4_vec.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * This program is free software; you can 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/>.
+ */
+
+/**
+ * DOC: VC4 SDTV module
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_panel.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+
+#include "vc4_drv.h"
+#include "vc4_regs.h"
+
+/* WSE Registers */
+#define VEC_WSE_RESET			0xc0
+
+#define VEC_WSE_CONTROL			0xc4
+#define VEC_WSE_WSS_ENABLE		BIT(7)
+
+#define VEC_WSE_WSS_DATA		0xc8
+#define VEC_WSE_VPS_DATA1		0xcc
+#define VEC_WSE_VPS_CONTROL		0xd0
+
+/* VEC Registers */
+#define VEC_REVID			0x100
+
+#define VEC_CONFIG0			0x104
+#define VEC_CONFIG0_YDEL_MASK		GENMASK(28, 26)
+#define VEC_CONFIG0_YDEL(x)		((x) << 26)
+#define VEC_CONFIG0_CDEL_MASK		GENMASK(25, 24)
+#define VEC_CONFIG0_CDEL(x)		((x) << 24)
+#define VEC_CONFIG0_PBPR_FIL		BIT(18)
+#define VEC_CONFIG0_CHROMA_GAIN_MASK	GENMASK(17, 16)
+#define VEC_CONFIG0_CHROMA_GAIN_UNITY	(0 << 16)
+#define VEC_CONFIG0_CHROMA_GAIN_1_32	(1 << 16)
+#define VEC_CONFIG0_CHROMA_GAIN_1_16	(2 << 16)
+#define VEC_CONFIG0_CHROMA_GAIN_1_8	(3 << 16)
+#define VEC_CONFIG0_CBURST_GAIN_MASK	GENMASK(14, 13)
+#define VEC_CONFIG0_CBURST_GAIN_UNITY	(0 << 13)
+#define VEC_CONFIG0_CBURST_GAIN_1_128	(1 << 13)
+#define VEC_CONFIG0_CBURST_GAIN_1_64	(2 << 13)
+#define VEC_CONFIG0_CBURST_GAIN_1_32	(3 << 13)
+#define VEC_CONFIG0_CHRBW1		BIT(11)
+#define VEC_CONFIG0_CHRBW0		BIT(10)
+#define VEC_CONFIG0_SYNCDIS		BIT(9)
+#define VEC_CONFIG0_BURDIS		BIT(8)
+#define VEC_CONFIG0_CHRDIS		BIT(7)
+#define VEC_CONFIG0_PDEN		BIT(6)
+#define VEC_CONFIG0_YCDELAY		BIT(4)
+#define VEC_CONFIG0_RAMPEN		BIT(2)
+#define VEC_CONFIG0_YCDIS		BIT(2)
+#define VEC_CONFIG0_STD_MASK		GENMASK(1, 0)
+#define VEC_CONFIG0_NTSC_STD		0
+#define VEC_CONFIG0_PAL_BDGHI_STD	1
+#define VEC_CONFIG0_PAL_N_STD		3
+
+#define VEC_SCHPH			0x108
+#define VEC_SOFT_RESET			0x10c
+#define VEC_CLMP0_START			0x144
+#define VEC_CLMP0_END			0x148
+#define VEC_FREQ3_2			0x180
+#define VEC_FREQ1_0			0x184
+
+#define VEC_CONFIG1			0x188
+#define VEC_CONFIG_VEC_RESYNC_OFF	BIT(18)
+#define VEC_CONFIG_RGB219		BIT(17)
+#define VEC_CONFIG_CBAR_EN		BIT(16)
+#define VEC_CONFIG_TC_OBB		BIT(15)
+#define VEC_CONFIG1_OUTPUT_MODE_MASK	GENMASK(12, 10)
+#define VEC_CONFIG1_C_Y_CVBS		(0 << 10)
+#define VEC_CONFIG1_CVBS_Y_C		(1 << 10)
+#define VEC_CONFIG1_PR_Y_PB		(2 << 10)
+#define VEC_CONFIG1_RGB			(4 << 10)
+#define VEC_CONFIG1_Y_C_CVBS		(5 << 10)
+#define VEC_CONFIG1_C_CVBS_Y		(6 << 10)
+#define VEC_CONFIG1_C_CVBS_CVBS		(7 << 10)
+#define VEC_CONFIG1_DIS_CHR		BIT(9)
+#define VEC_CONFIG1_DIS_LUMA		BIT(8)
+#define VEC_CONFIG1_YCBCR_IN		BIT(6)
+#define VEC_CONFIG1_DITHER_TYPE_LFSR	0
+#define VEC_CONFIG1_DITHER_TYPE_COUNTER	BIT(5)
+#define VEC_CONFIG1_DITHER_EN		BIT(4)
+#define VEC_CONFIG1_CYDELAY		BIT(3)
+#define VEC_CONFIG1_LUMADIS		BIT(2)
+#define VEC_CONFIG1_COMPDIS		BIT(1)
+#define VEC_CONFIG1_CUSTOM_FREQ		BIT(0)
+
+#define VEC_CONFIG2			0x18c
+#define VEC_CONFIG2_PROG_SCAN		BIT(15)
+#define VEC_CONFIG2_SYNC_ADJ_MASK	GENMASK(14, 12)
+#define VEC_CONFIG2_SYNC_ADJ(x)		(((x) / 2) << 12)
+#define VEC_CONFIG2_PBPR_EN		BIT(10)
+#define VEC_CONFIG2_UV_DIG_DIS		BIT(6)
+#define VEC_CONFIG2_RGB_DIG_DIS		BIT(5)
+#define VEC_CONFIG2_TMUX_MASK		GENMASK(3, 2)
+#define VEC_CONFIG2_TMUX_DRIVE0		(0 << 2)
+#define VEC_CONFIG2_TMUX_RG_COMP	(1 << 2)
+#define VEC_CONFIG2_TMUX_UV_YC		(2 << 2)
+#define VEC_CONFIG2_TMUX_SYNC_YC	(3 << 2)
+
+#define VEC_INTERRUPT_CONTROL		0x190
+#define VEC_INTERRUPT_STATUS		0x194
+#define VEC_FCW_SECAM_B			0x198
+#define VEC_SECAM_GAIN_VAL		0x19c
+
+#define VEC_CONFIG3			0x1a0
+#define VEC_CONFIG3_HORIZ_LEN_STD	(0 << 0)
+#define VEC_CONFIG3_HORIZ_LEN_MPEG1_SIF	(1 << 0)
+#define VEC_CONFIG3_SHAPE_NON_LINEAR	BIT(1)
+
+#define VEC_STATUS0			0x200
+#define VEC_MASK0			0x204
+
+#define VEC_CFG				0x208
+#define VEC_CFG_SG_MODE_MASK		GENMASK(6, 5)
+#define VEC_CFG_SG_MODE(x)		((x) << 5)
+#define VEC_CFG_SG_EN			BIT(4)
+#define VEC_CFG_VEC_EN			BIT(3)
+#define VEC_CFG_MB_EN			BIT(2)
+#define VEC_CFG_ENABLE			BIT(1)
+#define VEC_CFG_TB_EN			BIT(0)
+
+#define VEC_DAC_TEST			0x20c
+
+#define VEC_DAC_CONFIG			0x210
+#define VEC_DAC_CONFIG_LDO_BIAS_CTRL(x)	((x) << 24)
+#define VEC_DAC_CONFIG_DRIVER_CTRL(x)	((x) << 16)
+#define VEC_DAC_CONFIG_DAC_CTRL(x)	(x)
+
+#define VEC_DAC_MISC			0x214
+#define VEC_DAC_MISC_VCD_CTRL_MASK	GENMASK(31, 16)
+#define VEC_DAC_MISC_VCD_CTRL(x)	((x) << 16)
+#define VEC_DAC_MISC_VID_ACT		BIT(8)
+#define VEC_DAC_MISC_VCD_PWRDN		BIT(6)
+#define VEC_DAC_MISC_BIAS_PWRDN		BIT(5)
+#define VEC_DAC_MISC_DAC_PWRDN		BIT(2)
+#define VEC_DAC_MISC_LDO_PWRDN		BIT(1)
+#define VEC_DAC_MISC_DAC_RST_N		BIT(0)
+
+
+/* General VEC hardware state. */
+struct vc4_vec {
+	struct platform_device *pdev;
+
+	struct drm_encoder *encoder;
+	struct drm_connector *connector;
+
+	void __iomem *regs;
+
+	struct clk *clock;
+
+	const struct vc4_vec_tv_mode *tv_mode;
+};
+
+#define VEC_READ(offset) readl(vec->regs + (offset))
+#define VEC_WRITE(offset, val) writel(val, vec->regs + (offset))
+
+/* VC4 VEC encoder KMS struct */
+struct vc4_vec_encoder {
+	struct vc4_encoder base;
+	struct vc4_vec *vec;
+};
+
+static inline struct vc4_vec_encoder *
+to_vc4_vec_encoder(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct vc4_vec_encoder, base.base);
+}
+
+/* VC4 VEC connector KMS struct */
+struct vc4_vec_connector {
+	struct drm_connector base;
+	struct vc4_vec *vec;
+
+	/* Since the connector is attached to just the one encoder,
+	 * this is the reference to it so we can do the best_encoder()
+	 * hook.
+	 */
+	struct drm_encoder *encoder;
+};
+
+static inline struct vc4_vec_connector *
+to_vc4_vec_connector(struct drm_connector *connector)
+{
+	return container_of(connector, struct vc4_vec_connector, base);
+}
+
+enum vc4_vec_tv_mode_id {
+	VC4_VEC_TV_MODE_NTSC,
+	VC4_VEC_TV_MODE_NTSC_J,
+	VC4_VEC_TV_MODE_PAL,
+	VC4_VEC_TV_MODE_PAL_M,
+};
+
+struct vc4_vec_tv_mode {
+	const struct drm_display_mode *mode;
+	void (*mode_set)(struct vc4_vec *vec);
+};
+
+#define VEC_REG(reg) { reg, #reg }
+static const struct {
+	u32 reg;
+	const char *name;
+} vec_regs[] = {
+	VEC_REG(VEC_WSE_CONTROL),
+	VEC_REG(VEC_WSE_WSS_DATA),
+	VEC_REG(VEC_WSE_VPS_DATA1),
+	VEC_REG(VEC_WSE_VPS_CONTROL),
+	VEC_REG(VEC_REVID),
+	VEC_REG(VEC_CONFIG0),
+	VEC_REG(VEC_SCHPH),
+	VEC_REG(VEC_CLMP0_START),
+	VEC_REG(VEC_CLMP0_END),
+	VEC_REG(VEC_FREQ3_2),
+	VEC_REG(VEC_FREQ1_0),
+	VEC_REG(VEC_CONFIG1),
+	VEC_REG(VEC_CONFIG2),
+	VEC_REG(VEC_INTERRUPT_CONTROL),
+	VEC_REG(VEC_INTERRUPT_STATUS),
+	VEC_REG(VEC_FCW_SECAM_B),
+	VEC_REG(VEC_SECAM_GAIN_VAL),
+	VEC_REG(VEC_CONFIG3),
+	VEC_REG(VEC_STATUS0),
+	VEC_REG(VEC_MASK0),
+	VEC_REG(VEC_CFG),
+	VEC_REG(VEC_DAC_TEST),
+	VEC_REG(VEC_DAC_CONFIG),
+	VEC_REG(VEC_DAC_MISC),
+};
+
+#ifdef CONFIG_DEBUG_FS
+int vc4_vec_debugfs_regs(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *)m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct vc4_dev *vc4 = to_vc4_dev(dev);
+	struct vc4_vec *vec = vc4->vec;
+	int i;
+
+	if (!vec)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(vec_regs); i++) {
+		seq_printf(m, "%s (0x%04x): 0x%08x\n",
+			   vec_regs[i].name, vec_regs[i].reg,
+			   VEC_READ(vec_regs[i].reg));
+	}
+
+	return 0;
+}
+#endif
+
+static void vc4_vec_ntsc_mode_set(struct vc4_vec *vec)
+{
+	VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD | VEC_CONFIG0_PDEN);
+	VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+}
+
+static void vc4_vec_ntsc_j_mode_set(struct vc4_vec *vec)
+{
+	VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_NTSC_STD);
+	VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+}
+
+static const struct drm_display_mode ntsc_mode = {
+	DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
+		 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
+		 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0,
+		 DRM_MODE_FLAG_INTERLACE)
+};
+
+static void vc4_vec_pal_mode_set(struct vc4_vec *vec)
+{
+	VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
+	VEC_WRITE(VEC_CONFIG1, VEC_CONFIG1_C_CVBS_CVBS);
+}
+
+static void vc4_vec_pal_m_mode_set(struct vc4_vec *vec)
+{
+	VEC_WRITE(VEC_CONFIG0, VEC_CONFIG0_PAL_BDGHI_STD);
+	VEC_WRITE(VEC_CONFIG1,
+		  VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ);
+	VEC_WRITE(VEC_FREQ3_2, 0x223b);
+	VEC_WRITE(VEC_FREQ1_0, 0x61d1);
+}
+
+static const struct drm_display_mode pal_mode = {
+	DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
+		 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
+		 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0,
+		 DRM_MODE_FLAG_INTERLACE)
+};
+
+static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
+	[VC4_VEC_TV_MODE_NTSC] = {
+		.mode = &ntsc_mode,
+		.mode_set = vc4_vec_ntsc_mode_set,
+	},
+	[VC4_VEC_TV_MODE_NTSC_J] = {
+		.mode = &ntsc_mode,
+		.mode_set = vc4_vec_ntsc_j_mode_set,
+	},
+	[VC4_VEC_TV_MODE_PAL] = {
+		.mode = &pal_mode,
+		.mode_set = vc4_vec_pal_mode_set,
+	},
+	[VC4_VEC_TV_MODE_PAL_M] = {
+		.mode = &pal_mode,
+		.mode_set = vc4_vec_pal_m_mode_set,
+	},
+};
+
+static enum drm_connector_status
+vc4_vec_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_unknown;
+}
+
+static void vc4_vec_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static int vc4_vec_connector_get_modes(struct drm_connector *connector)
+{
+	struct drm_connector_state *state = connector->state;
+	struct drm_display_mode *mode;
+
+	mode = drm_mode_duplicate(connector->dev,
+				  vc4_vec_tv_modes[state->tv.mode].mode);
+	if (!mode) {
+		DRM_ERROR("Failed to create a new display mode\n");
+		return -ENOMEM;
+	}
+
+	drm_mode_probed_add(connector, mode);
+
+	return 1;
+}
+
+static const struct drm_connector_funcs vc4_vec_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.detect = vc4_vec_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = drm_atomic_helper_connector_set_property,
+	.destroy = vc4_vec_connector_destroy,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_connector_helper_funcs vc4_vec_connector_helper_funcs = {
+	.get_modes = vc4_vec_connector_get_modes,
+};
+
+static struct drm_connector *vc4_vec_connector_init(struct drm_device *dev,
+						    struct vc4_vec *vec)
+{
+	struct drm_connector *connector = NULL;
+	struct vc4_vec_connector *vec_connector;
+
+	vec_connector = devm_kzalloc(dev->dev, sizeof(*vec_connector),
+				     GFP_KERNEL);
+	if (!vec_connector)
+		return ERR_PTR(-ENOMEM);
+
+	connector = &vec_connector->base;
+	connector->interlace_allowed = true;
+
+	vec_connector->encoder = vec->encoder;
+	vec_connector->vec = vec;
+
+	drm_connector_init(dev, connector, &vc4_vec_connector_funcs,
+			   DRM_MODE_CONNECTOR_Composite);
+	drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs);
+
+	drm_object_attach_property(&connector->base,
+				   dev->mode_config.tv_mode_property,
+				   VC4_VEC_TV_MODE_NTSC);
+	vec->tv_mode = &vc4_vec_tv_modes[VC4_VEC_TV_MODE_NTSC];
+
+	drm_mode_connector_attach_encoder(connector, vec->encoder);
+
+	return connector;
+}
+
+static const struct drm_encoder_funcs vc4_vec_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static void vc4_vec_encoder_disable(struct drm_encoder *encoder)
+{
+	struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
+	struct vc4_vec *vec = vc4_vec_encoder->vec;
+	int ret;
+
+	VEC_WRITE(VEC_CFG, 0);
+	VEC_WRITE(VEC_DAC_MISC,
+		  VEC_DAC_MISC_VCD_PWRDN |
+		  VEC_DAC_MISC_BIAS_PWRDN |
+		  VEC_DAC_MISC_DAC_PWRDN |
+		  VEC_DAC_MISC_LDO_PWRDN);
+
+	clk_disable_unprepare(vec->clock);
+
+	ret = pm_runtime_put(&vec->pdev->dev);
+	if (ret < 0) {
+		DRM_ERROR("Failed to release power domain: %d\n", ret);
+		return;
+	}
+}
+
+static void vc4_vec_encoder_enable(struct drm_encoder *encoder)
+{
+	struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
+	struct vc4_vec *vec = vc4_vec_encoder->vec;
+	int ret;
+
+	ret = pm_runtime_get_sync(&vec->pdev->dev);
+	if (ret < 0) {
+		DRM_ERROR("Failed to retain power domain: %d\n", ret);
+		return;
+	}
+
+	/*
+	 * We need to set the clock rate each time we enable the encoder
+	 * because there's a chance we share the same parent with the HDMI
+	 * clock, and both drivers are requesting different rates.
+	 * The good news is, these 2 encoders cannot be enabled at the same
+	 * time, thus preventing incompatible rate requests.
+	 */
+	ret = clk_set_rate(vec->clock, 108000000);
+	if (ret) {
+		DRM_ERROR("Failed to set clock rate: %d\n", ret);
+		return;
+	}
+
+	ret = clk_prepare_enable(vec->clock);
+	if (ret) {
+		DRM_ERROR("Failed to turn on core clock: %d\n", ret);
+		return;
+	}
+
+	/* Reset the different blocks */
+	VEC_WRITE(VEC_WSE_RESET, 1);
+	VEC_WRITE(VEC_SOFT_RESET, 1);
+
+	/* Disable the CGSM-A and WSE blocks */
+	VEC_WRITE(VEC_WSE_CONTROL, 0);
+
+	/* Write config common to all modes. */
+
+	/*
+	 * Color subcarrier phase: phase = 360 * SCHPH / 256.
+	 * 0x28 <=> 39.375 deg.
+	 */
+	VEC_WRITE(VEC_SCHPH, 0x28);
+
+	/*
+	 * Reset to default values.
+	 */
+	VEC_WRITE(VEC_CLMP0_START, 0xac);
+	VEC_WRITE(VEC_CLMP0_END, 0xec);
+	VEC_WRITE(VEC_CONFIG2,
+		  VEC_CONFIG2_UV_DIG_DIS | VEC_CONFIG2_RGB_DIG_DIS);
+	VEC_WRITE(VEC_CONFIG3, VEC_CONFIG3_HORIZ_LEN_STD);
+	VEC_WRITE(VEC_DAC_CONFIG,
+		  VEC_DAC_CONFIG_DAC_CTRL(0xc) |
+		  VEC_DAC_CONFIG_DRIVER_CTRL(0xc) |
+		  VEC_DAC_CONFIG_LDO_BIAS_CTRL(0x46));
+
+	/* Mask all interrupts. */
+	VEC_WRITE(VEC_MASK0, 0);
+
+	vec->tv_mode->mode_set(vec);
+
+	VEC_WRITE(VEC_DAC_MISC,
+		  VEC_DAC_MISC_VID_ACT | VEC_DAC_MISC_DAC_RST_N);
+	VEC_WRITE(VEC_CFG, VEC_CFG_VEC_EN);
+}
+
+
+static bool vc4_vec_encoder_mode_fixup(struct drm_encoder *encoder,
+				       const struct drm_display_mode *mode,
+				       struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static void vc4_vec_encoder_atomic_mode_set(struct drm_encoder *encoder,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state)
+{
+	struct vc4_vec_encoder *vc4_vec_encoder = to_vc4_vec_encoder(encoder);
+	struct vc4_vec *vec = vc4_vec_encoder->vec;
+
+	vec->tv_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
+}
+
+static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder,
+					struct drm_crtc_state *crtc_state,
+					struct drm_connector_state *conn_state)
+{
+	const struct vc4_vec_tv_mode *vec_mode;
+
+	vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode];
+
+	if (conn_state->crtc &&
+	    !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode))
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct drm_encoder_helper_funcs vc4_vec_encoder_helper_funcs = {
+	.disable = vc4_vec_encoder_disable,
+	.enable = vc4_vec_encoder_enable,
+	.mode_fixup = vc4_vec_encoder_mode_fixup,
+	.atomic_check = vc4_vec_encoder_atomic_check,
+	.atomic_mode_set = vc4_vec_encoder_atomic_mode_set,
+};
+
+static const struct of_device_id vc4_vec_dt_match[] = {
+	{ .compatible = "brcm,bcm2835-vec", .data = NULL },
+	{ /* sentinel */ },
+};
+
+static const char * const tv_mode_names[] = {
+	[VC4_VEC_TV_MODE_NTSC] = "NTSC",
+	[VC4_VEC_TV_MODE_NTSC_J] = "NTSC-J",
+	[VC4_VEC_TV_MODE_PAL] = "PAL",
+	[VC4_VEC_TV_MODE_PAL_M] = "PAL-M",
+};
+
+static int vc4_vec_bind(struct device *dev, struct device *master, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = dev_get_drvdata(master);
+	struct vc4_dev *vc4 = to_vc4_dev(drm);
+	struct vc4_vec *vec;
+	struct vc4_vec_encoder *vc4_vec_encoder;
+	int ret;
+
+	ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names),
+					    tv_mode_names);
+	if (ret)
+		return ret;
+
+	vec = devm_kzalloc(dev, sizeof(*vec), GFP_KERNEL);
+	if (!vec)
+		return -ENOMEM;
+
+	vc4_vec_encoder = devm_kzalloc(dev, sizeof(*vc4_vec_encoder),
+				       GFP_KERNEL);
+	if (!vc4_vec_encoder)
+		return -ENOMEM;
+	vc4_vec_encoder->base.type = VC4_ENCODER_TYPE_VEC;
+	vc4_vec_encoder->vec = vec;
+	vec->encoder = &vc4_vec_encoder->base.base;
+
+	vec->pdev = pdev;
+	vec->regs = vc4_ioremap_regs(pdev, 0);
+	if (IS_ERR(vec->regs))
+		return PTR_ERR(vec->regs);
+
+	vec->clock = devm_clk_get(dev, NULL);
+	if (IS_ERR(vec->clock)) {
+		ret = PTR_ERR(vec->clock);
+		if (ret != -EPROBE_DEFER)
+			DRM_ERROR("Failed to get clock: %d\n", ret);
+		return ret;
+	}
+
+	pm_runtime_enable(dev);
+
+	drm_encoder_init(drm, vec->encoder, &vc4_vec_encoder_funcs,
+			 DRM_MODE_ENCODER_TVDAC, NULL);
+	drm_encoder_helper_add(vec->encoder, &vc4_vec_encoder_helper_funcs);
+
+	vec->connector = vc4_vec_connector_init(drm, vec);
+	if (IS_ERR(vec->connector)) {
+		ret = PTR_ERR(vec->connector);
+		goto err_destroy_encoder;
+	}
+
+	dev_set_drvdata(dev, vec);
+
+	vc4->vec = vec;
+
+	return 0;
+
+err_destroy_encoder:
+	drm_encoder_cleanup(vec->encoder);
+	pm_runtime_disable(dev);
+
+	return ret;
+}
+
+static void vc4_vec_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct drm_device *drm = dev_get_drvdata(master);
+	struct vc4_dev *vc4 = to_vc4_dev(drm);
+	struct vc4_vec *vec = dev_get_drvdata(dev);
+
+	vc4_vec_connector_destroy(vec->connector);
+	drm_encoder_cleanup(vec->encoder);
+	pm_runtime_disable(dev);
+
+	vc4->vec = NULL;
+}
+
+static const struct component_ops vc4_vec_ops = {
+	.bind   = vc4_vec_bind,
+	.unbind = vc4_vec_unbind,
+};
+
+static int vc4_vec_dev_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &vc4_vec_ops);
+}
+
+static int vc4_vec_dev_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &vc4_vec_ops);
+	return 0;
+}
+
+struct platform_driver vc4_vec_driver = {
+	.probe = vc4_vec_dev_probe,
+	.remove = vc4_vec_dev_remove,
+	.driver = {
+		.name = "vc4_vec",
+		.of_match_table = vc4_vec_dt_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vgem/vgem_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vgem/vgem_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vgem/vgem_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vgem/vgem_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@ static int vgem_gem_fault(struct vm_area
 {
 	struct drm_vgem_gem_object *obj = vma->vm_private_data;
 	/* We don't use vmf->pgoff since that has the fake offset */
-	unsigned long vaddr = (unsigned long)vmf->virtual_address;
+	unsigned long vaddr = vmf->address;
 	struct page *page;
 
 	page = shmem_read_mapping_page(file_inode(obj->base.filp)->i_mapping,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vgem/vgem_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vgem/vgem_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vgem/vgem_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vgem/vgem_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,56 +28,57 @@
 #define VGEM_FENCE_TIMEOUT (10*HZ)
 
 struct vgem_fence {
-	struct fence base;
+	struct dma_fence base;
 	struct spinlock lock;
 	struct timer_list timer;
 };
 
-static const char *vgem_fence_get_driver_name(struct fence *fence)
+static const char *vgem_fence_get_driver_name(struct dma_fence *fence)
 {
 	return "vgem";
 }
 
-static const char *vgem_fence_get_timeline_name(struct fence *fence)
+static const char *vgem_fence_get_timeline_name(struct dma_fence *fence)
 {
 	return "unbound";
 }
 
-static bool vgem_fence_signaled(struct fence *fence)
+static bool vgem_fence_signaled(struct dma_fence *fence)
 {
 	return false;
 }
 
-static bool vgem_fence_enable_signaling(struct fence *fence)
+static bool vgem_fence_enable_signaling(struct dma_fence *fence)
 {
 	return true;
 }
 
-static void vgem_fence_release(struct fence *base)
+static void vgem_fence_release(struct dma_fence *base)
 {
 	struct vgem_fence *fence = container_of(base, typeof(*fence), base);
 
 	del_timer_sync(&fence->timer);
-	fence_free(&fence->base);
+	dma_fence_free(&fence->base);
 }
 
-static void vgem_fence_value_str(struct fence *fence, char *str, int size)
+static void vgem_fence_value_str(struct dma_fence *fence, char *str, int size)
 {
 	snprintf(str, size, "%u", fence->seqno);
 }
 
-static void vgem_fence_timeline_value_str(struct fence *fence, char *str,
+static void vgem_fence_timeline_value_str(struct dma_fence *fence, char *str,
 					  int size)
 {
-	snprintf(str, size, "%u", fence_is_signaled(fence) ? fence->seqno : 0);
+	snprintf(str, size, "%u",
+		 dma_fence_is_signaled(fence) ? fence->seqno : 0);
 }
 
-static const struct fence_ops vgem_fence_ops = {
+static const struct dma_fence_ops vgem_fence_ops = {
 	.get_driver_name = vgem_fence_get_driver_name,
 	.get_timeline_name = vgem_fence_get_timeline_name,
 	.enable_signaling = vgem_fence_enable_signaling,
 	.signaled = vgem_fence_signaled,
-	.wait = fence_default_wait,
+	.wait = dma_fence_default_wait,
 	.release = vgem_fence_release,
 
 	.fence_value_str = vgem_fence_value_str,
@@ -88,11 +89,11 @@ static void vgem_fence_timeout(unsigned
 {
 	struct vgem_fence *fence = (struct vgem_fence *)data;
 
-	fence_signal(&fence->base);
+	dma_fence_signal(&fence->base);
 }
 
-static struct fence *vgem_fence_create(struct vgem_file *vfile,
-				       unsigned int flags)
+static struct dma_fence *vgem_fence_create(struct vgem_file *vfile,
+					   unsigned int flags)
 {
 	struct vgem_fence *fence;
 
@@ -101,8 +102,8 @@ static struct fence *vgem_fence_create(s
 		return NULL;
 
 	spin_lock_init(&fence->lock);
-	fence_init(&fence->base, &vgem_fence_ops, &fence->lock,
-		   fence_context_alloc(1), 1);
+	dma_fence_init(&fence->base, &vgem_fence_ops, &fence->lock,
+		       dma_fence_context_alloc(1), 1);
 
 	setup_timer(&fence->timer, vgem_fence_timeout, (unsigned long)fence);
 
@@ -125,7 +126,6 @@ static int attach_dmabuf(struct drm_devi
 		return PTR_ERR(dmabuf);
 
 	obj->dma_buf = dmabuf;
-	drm_gem_object_reference(obj);
 	return 0;
 }
 
@@ -157,7 +157,7 @@ int vgem_fence_attach_ioctl(struct drm_d
 	struct vgem_file *vfile = file->driver_priv;
 	struct reservation_object *resv;
 	struct drm_gem_object *obj;
-	struct fence *fence;
+	struct dma_fence *fence;
 	int ret;
 
 	if (arg->flags & ~VGEM_FENCE_WRITE)
@@ -190,12 +190,12 @@ int vgem_fence_attach_ioctl(struct drm_d
 
 	/* Expose the fence via the dma-buf */
 	ret = 0;
-	mutex_lock(&resv->lock.base);
+	ww_mutex_lock(&resv->lock, NULL);
 	if (arg->flags & VGEM_FENCE_WRITE)
 		reservation_object_add_excl_fence(resv, fence);
 	else if ((ret = reservation_object_reserve_shared(resv)) == 0)
 		reservation_object_add_shared_fence(resv, fence);
-	mutex_unlock(&resv->lock.base);
+	ww_mutex_unlock(&resv->lock);
 
 	/* Record the fence in our idr for later signaling */
 	if (ret == 0) {
@@ -209,8 +209,8 @@ int vgem_fence_attach_ioctl(struct drm_d
 	}
 err_fence:
 	if (ret) {
-		fence_signal(fence);
-		fence_put(fence);
+		dma_fence_signal(fence);
+		dma_fence_put(fence);
 	}
 err:
 	drm_gem_object_unreference_unlocked(obj);
@@ -239,7 +239,7 @@ int vgem_fence_signal_ioctl(struct drm_d
 {
 	struct vgem_file *vfile = file->driver_priv;
 	struct drm_vgem_fence_signal *arg = data;
-	struct fence *fence;
+	struct dma_fence *fence;
 	int ret = 0;
 
 	if (arg->flags)
@@ -253,11 +253,11 @@ int vgem_fence_signal_ioctl(struct drm_d
 	if (IS_ERR(fence))
 		return PTR_ERR(fence);
 
-	if (fence_is_signaled(fence))
+	if (dma_fence_is_signaled(fence))
 		ret = -ETIMEDOUT;
 
-	fence_signal(fence);
-	fence_put(fence);
+	dma_fence_signal(fence);
+	dma_fence_put(fence);
 	return ret;
 }
 
@@ -271,8 +271,8 @@ int vgem_fence_open(struct vgem_file *vf
 
 static int __vgem_fence_idr_fini(int id, void *p, void *data)
 {
-	fence_signal(p);
-	fence_put(p);
+	dma_fence_signal(p);
+	dma_fence_put(p);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/via/via_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/via/via_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/via/via_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/via/via_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,9 +64,7 @@ static const struct file_operations via_
 	.unlocked_ioctl = drm_ioctl,
 	.mmap = drm_legacy_mmap,
 	.poll = drm_poll,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,10 +1,10 @@
 config DRM_VIRTIO_GPU
 	tristate "Virtio GPU driver"
 	depends on DRM && VIRTIO
-        select DRM_KMS_HELPER
-        select DRM_TTM
+	select DRM_KMS_HELPER
+	select DRM_TTM
 	help
 	   This is the virtual GPU driver for virtio.  It can be used with
-           QEMU based VMMs (like KVM or Xen).
+	   QEMU based VMMs (like KVM or Xen).
 
 	   If unsure say M.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_drm_bus.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_drm_bus.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_drm_bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_drm_bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,16 +28,6 @@
 
 #include "virtgpu_drv.h"
 
-int drm_virtio_set_busid(struct drm_device *dev, struct drm_master *master)
-{
-	struct pci_dev *pdev = dev->pdev;
-
-	if (pdev) {
-		return drm_pci_set_busid(dev, master);
-	}
-	return 0;
-}
-
 static void virtio_pci_kick_out_firmware_fb(struct pci_dev *pci_dev)
 {
 	struct apertures_struct *ap;
@@ -71,13 +61,22 @@ int drm_virtio_init(struct drm_driver *d
 
 	if (strcmp(vdev->dev.parent->bus->name, "pci") == 0) {
 		struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
+		const char *pname = dev_name(&pdev->dev);
 		bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
+		char unique[20];
 
-		DRM_INFO("pci: %s detected\n",
-			 vga ? "virtio-vga" : "virtio-gpu-pci");
+		DRM_INFO("pci: %s detected at %s\n",
+			 vga ? "virtio-vga" : "virtio-gpu-pci",
+			 pname);
 		dev->pdev = pdev;
 		if (vga)
 			virtio_pci_kick_out_firmware_fb(pdev);
+
+		snprintf(unique, sizeof(unique), "pci:%s", pname);
+		ret = drm_dev_set_unique(dev, unique);
+		if (ret)
+			goto err_free;
+
 	}
 
 	ret = drm_dev_register(dev, 0);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,16 +108,13 @@ static const struct file_operations virt
 	.read = drm_read,
 	.unlocked_ioctl	= drm_ioctl,
 	.release = drm_release,
-#ifdef CONFIG_COMPAT
 	.compat_ioctl = drm_compat_ioctl,
-#endif
 	.llseek = noop_llseek,
 };
 
 
 static struct drm_driver driver = {
 	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC,
-	.set_busid = drm_virtio_set_busid,
 	.load = virtio_gpu_driver_load,
 	.unload = virtio_gpu_driver_unload,
 	.open = virtio_gpu_driver_open,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,6 @@
 #define DRIVER_PATCHLEVEL 1
 
 /* virtgpu_drm_bus.c */
-int drm_virtio_set_busid(struct drm_device *dev, struct drm_master *master);
 int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev);
 
 struct virtio_gpu_object {
@@ -82,7 +81,7 @@ struct virtio_gpu_fence_driver {
 };
 
 struct virtio_gpu_fence {
-	struct fence f;
+	struct dma_fence f;
 	struct virtio_gpu_fence_driver *drv;
 	struct list_head node;
 	uint64_t seq;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -200,16 +200,10 @@ static void virtio_gpu_3d_imageblit(stru
 
 static struct fb_ops virtio_gpufb_ops = {
 	.owner = THIS_MODULE,
-	.fb_check_var = drm_fb_helper_check_var,
-	.fb_set_par = drm_fb_helper_set_par, /* TODO: copy vmwgfx */
+	DRM_FB_HELPER_DEFAULT_OPS,
 	.fb_fillrect = virtio_gpu_3d_fillrect,
 	.fb_copyarea = virtio_gpu_3d_copyarea,
 	.fb_imageblit = virtio_gpu_3d_imageblit,
-	.fb_pan_display = drm_fb_helper_pan_display,
-	.fb_blank = drm_fb_helper_blank,
-	.fb_setcmap = drm_fb_helper_setcmap,
-	.fb_debug_enter = drm_fb_helper_debug_enter,
-	.fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
 static int virtio_gpu_vmap_fb(struct virtio_gpu_device *vgdev,
@@ -337,7 +331,7 @@ static int virtio_gpufb_create(struct dr
 	info->fbops = &virtio_gpufb_ops;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
-	info->screen_base = obj->vmap;
+	info->screen_buffer = obj->vmap;
 	info->screen_size = obj->gem_base.size;
 	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
 	drm_fb_helper_fill_var(info, &vfbdev->helper,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,22 +26,22 @@
 #include <drm/drmP.h>
 #include "virtgpu_drv.h"
 
-static const char *virtio_get_driver_name(struct fence *f)
+static const char *virtio_get_driver_name(struct dma_fence *f)
 {
 	return "virtio_gpu";
 }
 
-static const char *virtio_get_timeline_name(struct fence *f)
+static const char *virtio_get_timeline_name(struct dma_fence *f)
 {
 	return "controlq";
 }
 
-static bool virtio_enable_signaling(struct fence *f)
+static bool virtio_enable_signaling(struct dma_fence *f)
 {
 	return true;
 }
 
-static bool virtio_signaled(struct fence *f)
+static bool virtio_signaled(struct dma_fence *f)
 {
 	struct virtio_gpu_fence *fence = to_virtio_fence(f);
 
@@ -50,26 +50,26 @@ static bool virtio_signaled(struct fence
 	return false;
 }
 
-static void virtio_fence_value_str(struct fence *f, char *str, int size)
+static void virtio_fence_value_str(struct dma_fence *f, char *str, int size)
 {
 	struct virtio_gpu_fence *fence = to_virtio_fence(f);
 
 	snprintf(str, size, "%llu", fence->seq);
 }
 
-static void virtio_timeline_value_str(struct fence *f, char *str, int size)
+static void virtio_timeline_value_str(struct dma_fence *f, char *str, int size)
 {
 	struct virtio_gpu_fence *fence = to_virtio_fence(f);
 
 	snprintf(str, size, "%llu", (u64)atomic64_read(&fence->drv->last_seq));
 }
 
-static const struct fence_ops virtio_fence_ops = {
+static const struct dma_fence_ops virtio_fence_ops = {
 	.get_driver_name     = virtio_get_driver_name,
 	.get_timeline_name   = virtio_get_timeline_name,
 	.enable_signaling    = virtio_enable_signaling,
 	.signaled            = virtio_signaled,
-	.wait                = fence_default_wait,
+	.wait                = dma_fence_default_wait,
 	.fence_value_str     = virtio_fence_value_str,
 	.timeline_value_str  = virtio_timeline_value_str,
 };
@@ -88,9 +88,9 @@ int virtio_gpu_fence_emit(struct virtio_
 	spin_lock_irqsave(&drv->lock, irq_flags);
 	(*fence)->drv = drv;
 	(*fence)->seq = ++drv->sync_seq;
-	fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock,
-		   drv->context, (*fence)->seq);
-	fence_get(&(*fence)->f);
+	dma_fence_init(&(*fence)->f, &virtio_fence_ops, &drv->lock,
+		       drv->context, (*fence)->seq);
+	dma_fence_get(&(*fence)->f);
 	list_add_tail(&(*fence)->node, &drv->fences);
 	spin_unlock_irqrestore(&drv->lock, irq_flags);
 
@@ -111,9 +111,9 @@ void virtio_gpu_fence_event_process(stru
 	list_for_each_entry_safe(fence, tmp, &drv->fences, node) {
 		if (last_seq < fence->seq)
 			continue;
-		fence_signal_locked(&fence->f);
+		dma_fence_signal_locked(&fence->f);
 		list_del(&fence->node);
-		fence_put(&fence->f);
+		dma_fence_put(&fence->f);
 	}
 	spin_unlock_irqrestore(&drv->lock, irq_flags);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -172,7 +172,7 @@ static int virtio_gpu_execbuffer_ioctl(s
 	/* fence the command bo */
 	virtio_gpu_unref_list(&validate_list);
 	drm_free_large(buflist);
-	fence_put(&fence->f);
+	dma_fence_put(&fence->f);
 	return 0;
 
 out_unresv:
@@ -298,7 +298,7 @@ static int virtio_gpu_resource_create_io
 		drm_gem_object_release(obj);
 		if (vgdev->has_virgl_3d) {
 			virtio_gpu_unref_list(&validate_list);
-			fence_put(&fence->f);
+			dma_fence_put(&fence->f);
 		}
 		return ret;
 	}
@@ -309,13 +309,13 @@ static int virtio_gpu_resource_create_io
 
 	if (vgdev->has_virgl_3d) {
 		virtio_gpu_unref_list(&validate_list);
-		fence_put(&fence->f);
+		dma_fence_put(&fence->f);
 	}
 	return 0;
 fail_unref:
 	if (vgdev->has_virgl_3d) {
 		virtio_gpu_unref_list(&validate_list);
-		fence_put(&fence->f);
+		dma_fence_put(&fence->f);
 	}
 //fail_obj:
 //	drm_gem_object_handle_unreference_unlocked(obj);
@@ -383,7 +383,7 @@ static int virtio_gpu_transfer_from_host
 	reservation_object_add_excl_fence(qobj->tbo.resv,
 					  &fence->f);
 
-	fence_put(&fence->f);
+	dma_fence_put(&fence->f);
 out_unres:
 	virtio_gpu_object_unreserve(qobj);
 out:
@@ -431,7 +431,7 @@ static int virtio_gpu_transfer_to_host_i
 			 args->level, &box, &fence);
 		reservation_object_add_excl_fence(qobj->tbo.resv,
 						  &fence->f);
-		fence_put(&fence->f);
+		dma_fence_put(&fence->f);
 	}
 
 out_unres:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -159,7 +159,7 @@ int virtio_gpu_driver_load(struct drm_de
 	virtio_gpu_init_vq(&vgdev->ctrlq, virtio_gpu_dequeue_ctrl_func);
 	virtio_gpu_init_vq(&vgdev->cursorq, virtio_gpu_dequeue_cursor_func);
 
-	vgdev->fence_drv.context = fence_context_alloc(1);
+	vgdev->fence_drv.context = dma_fence_context_alloc(1);
 	spin_lock_init(&vgdev->fence_drv.lock);
 	INIT_LIST_HEAD(&vgdev->fence_drv.fences);
 	INIT_LIST_HEAD(&vgdev->cap_cache);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_plane.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,8 +88,8 @@ static void virtio_gpu_primary_plane_upd
 				(vgdev, handle, 0,
 				 cpu_to_le32(plane->state->src_w >> 16),
 				 cpu_to_le32(plane->state->src_h >> 16),
-				 plane->state->src_x >> 16,
-				 plane->state->src_y >> 16, NULL);
+				 cpu_to_le32(plane->state->src_x >> 16),
+				 cpu_to_le32(plane->state->src_y >> 16), NULL);
 		}
 	} else {
 		handle = 0;
@@ -152,7 +152,7 @@ static void virtio_gpu_cursor_plane_upda
 		if (!ret) {
 			reservation_object_add_excl_fence(bo->tbo.resv,
 							  &fence->f);
-			fence_put(&fence->f);
+			dma_fence_put(&fence->f);
 			fence = NULL;
 			virtio_gpu_object_unreserve(bo);
 			virtio_gpu_object_wait(bo, false);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_ttm.c	2017-02-12 16:03:20.000000000 -0500
@@ -425,6 +425,7 @@ static struct ttm_bo_driver virtio_gpu_b
 	.ttm_tt_unpopulate = &virtio_gpu_ttm_tt_unpopulate,
 	.invalidate_caches = &virtio_gpu_invalidate_caches,
 	.init_mem_type = &virtio_gpu_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = &virtio_gpu_evict_flags,
 	.move = &virtio_gpu_bo_move,
 	.verify_access = &virtio_gpu_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/virtio/virtgpu_vq.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,7 @@ void virtio_gpu_cursor_ack(struct virtqu
 int virtio_gpu_alloc_vbufs(struct virtio_gpu_device *vgdev)
 {
 	struct virtio_gpu_vbuffer *vbuf;
-	int i, size, count = 0;
+	int i, size, count = 16;
 	void *ptr;
 
 	INIT_LIST_HEAD(&vgdev->free_vbufs);
@@ -109,8 +109,10 @@ void virtio_gpu_free_vbufs(struct virtio
 
 	spin_lock(&vgdev->free_vbufs_lock);
 	for (i = 0; i < count; i++) {
-		if (WARN_ON(list_empty(&vgdev->free_vbufs)))
+		if (WARN_ON(list_empty(&vgdev->free_vbufs))) {
+			spin_unlock(&vgdev->free_vbufs_lock);
 			return;
+		}
 		vbuf = list_first_entry(&vgdev->free_vbufs,
 					struct virtio_gpu_vbuffer, list);
 		list_del(&vbuf->list);
@@ -295,6 +297,8 @@ void virtio_gpu_dequeue_cursor_func(stru
 
 static int virtio_gpu_queue_ctrl_buffer_locked(struct virtio_gpu_device *vgdev,
 					       struct virtio_gpu_vbuffer *vbuf)
+		__releases(&vgdev->ctrlq.qlock)
+		__acquires(&vgdev->ctrlq.qlock)
 {
 	struct virtqueue *vq = vgdev->ctrlq.vq;
 	struct scatterlist *sgs[3], vcmd, vout, vresp;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -849,6 +849,7 @@ struct ttm_bo_driver vmw_bo_driver = {
 	.ttm_tt_unpopulate = &vmw_ttm_unpopulate,
 	.invalidate_caches = vmw_invalidate_caches,
 	.init_mem_type = vmw_init_mem_type,
+	.eviction_valuable = ttm_bo_eviction_valuable,
 	.evict_flags = vmw_evict_flags,
 	.move = NULL,
 	.verify_access = vmw_verify_access,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c	2017-02-12 16:03:20.000000000 -0500
@@ -465,33 +465,33 @@ static int vmw_fb_kms_detach(struct vmw_
 
 static int vmw_fb_kms_framebuffer(struct fb_info *info)
 {
-	struct drm_mode_fb_cmd mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd;
 	struct vmw_fb_par *par = info->par;
 	struct fb_var_screeninfo *var = &info->var;
 	struct drm_framebuffer *cur_fb;
 	struct vmw_framebuffer *vfb;
-	int ret = 0;
+	int ret = 0, depth;
 	size_t new_bo_size;
 
-	ret = vmw_fb_compute_depth(var, &mode_cmd.depth);
+	ret = vmw_fb_compute_depth(var, &depth);
 	if (ret)
 		return ret;
 
 	mode_cmd.width = var->xres;
 	mode_cmd.height = var->yres;
-	mode_cmd.bpp = var->bits_per_pixel;
-	mode_cmd.pitch = ((mode_cmd.bpp + 7) / 8) * mode_cmd.width;
+	mode_cmd.pitches[0] = ((var->bits_per_pixel + 7) / 8) * mode_cmd.width;
+	mode_cmd.pixel_format =
+		drm_mode_legacy_fb_format(var->bits_per_pixel, depth);
 
 	cur_fb = par->set_fb;
 	if (cur_fb && cur_fb->width == mode_cmd.width &&
 	    cur_fb->height == mode_cmd.height &&
-	    cur_fb->bits_per_pixel == mode_cmd.bpp &&
-	    cur_fb->depth == mode_cmd.depth &&
-	    cur_fb->pitches[0] == mode_cmd.pitch)
+	    cur_fb->pixel_format == mode_cmd.pixel_format &&
+	    cur_fb->pitches[0] == mode_cmd.pitches[0])
 		return 0;
 
 	/* Need new buffer object ? */
-	new_bo_size = (size_t) mode_cmd.pitch * (size_t) mode_cmd.height;
+	new_bo_size = (size_t) mode_cmd.pitches[0] * (size_t) mode_cmd.height;
 	ret = vmw_fb_kms_detach(par,
 				par->bo_size < new_bo_size ||
 				par->bo_size > 2*new_bo_size,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,7 +108,7 @@ fman_from_fence(struct vmw_fence_obj *fe
  * objects with actions attached to them.
  */
 
-static void vmw_fence_obj_destroy(struct fence *f)
+static void vmw_fence_obj_destroy(struct dma_fence *f)
 {
 	struct vmw_fence_obj *fence =
 		container_of(f, struct vmw_fence_obj, base);
@@ -123,17 +123,17 @@ static void vmw_fence_obj_destroy(struct
 	fence->destroy(fence);
 }
 
-static const char *vmw_fence_get_driver_name(struct fence *f)
+static const char *vmw_fence_get_driver_name(struct dma_fence *f)
 {
 	return "vmwgfx";
 }
 
-static const char *vmw_fence_get_timeline_name(struct fence *f)
+static const char *vmw_fence_get_timeline_name(struct dma_fence *f)
 {
 	return "svga";
 }
 
-static bool vmw_fence_enable_signaling(struct fence *f)
+static bool vmw_fence_enable_signaling(struct dma_fence *f)
 {
 	struct vmw_fence_obj *fence =
 		container_of(f, struct vmw_fence_obj, base);
@@ -152,12 +152,12 @@ static bool vmw_fence_enable_signaling(s
 }
 
 struct vmwgfx_wait_cb {
-	struct fence_cb base;
+	struct dma_fence_cb base;
 	struct task_struct *task;
 };
 
 static void
-vmwgfx_wait_cb(struct fence *fence, struct fence_cb *cb)
+vmwgfx_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
 {
 	struct vmwgfx_wait_cb *wait =
 		container_of(cb, struct vmwgfx_wait_cb, base);
@@ -167,7 +167,7 @@ vmwgfx_wait_cb(struct fence *fence, stru
 
 static void __vmw_fences_update(struct vmw_fence_manager *fman);
 
-static long vmw_fence_wait(struct fence *f, bool intr, signed long timeout)
+static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout)
 {
 	struct vmw_fence_obj *fence =
 		container_of(f, struct vmw_fence_obj, base);
@@ -197,7 +197,7 @@ static long vmw_fence_wait(struct fence
 
 	while (ret > 0) {
 		__vmw_fences_update(fman);
-		if (test_bit(FENCE_FLAG_SIGNALED_BIT, &f->flags))
+		if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags))
 			break;
 
 		if (intr)
@@ -225,7 +225,7 @@ out:
 	return ret;
 }
 
-static struct fence_ops vmw_fence_ops = {
+static struct dma_fence_ops vmw_fence_ops = {
 	.get_driver_name = vmw_fence_get_driver_name,
 	.get_timeline_name = vmw_fence_get_timeline_name,
 	.enable_signaling = vmw_fence_enable_signaling,
@@ -298,7 +298,7 @@ struct vmw_fence_manager *vmw_fence_mana
 	fman->event_fence_action_size =
 		ttm_round_pot(sizeof(struct vmw_event_fence_action));
 	mutex_init(&fman->goal_irq_mutex);
-	fman->ctx = fence_context_alloc(1);
+	fman->ctx = dma_fence_context_alloc(1);
 
 	return fman;
 }
@@ -326,8 +326,8 @@ static int vmw_fence_obj_init(struct vmw
 	unsigned long irq_flags;
 	int ret = 0;
 
-	fence_init(&fence->base, &vmw_fence_ops, &fman->lock,
-		   fman->ctx, seqno);
+	dma_fence_init(&fence->base, &vmw_fence_ops, &fman->lock,
+		       fman->ctx, seqno);
 	INIT_LIST_HEAD(&fence->seq_passed_actions);
 	fence->destroy = destroy;
 
@@ -431,7 +431,7 @@ static bool vmw_fence_goal_check_locked(
 	u32 goal_seqno;
 	u32 *fifo_mem;
 
-	if (fence_is_signaled_locked(&fence->base))
+	if (dma_fence_is_signaled_locked(&fence->base))
 		return false;
 
 	fifo_mem = fman->dev_priv->mmio_virt;
@@ -459,7 +459,7 @@ rerun:
 	list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
 		if (seqno - fence->base.seqno < VMW_FENCE_WRAP) {
 			list_del_init(&fence->head);
-			fence_signal_locked(&fence->base);
+			dma_fence_signal_locked(&fence->base);
 			INIT_LIST_HEAD(&action_list);
 			list_splice_init(&fence->seq_passed_actions,
 					 &action_list);
@@ -500,18 +500,18 @@ bool vmw_fence_obj_signaled(struct vmw_f
 {
 	struct vmw_fence_manager *fman = fman_from_fence(fence);
 
-	if (test_bit(FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->base.flags))
 		return 1;
 
 	vmw_fences_update(fman);
 
-	return fence_is_signaled(&fence->base);
+	return dma_fence_is_signaled(&fence->base);
 }
 
 int vmw_fence_obj_wait(struct vmw_fence_obj *fence, bool lazy,
 		       bool interruptible, unsigned long timeout)
 {
-	long ret = fence_wait_timeout(&fence->base, interruptible, timeout);
+	long ret = dma_fence_wait_timeout(&fence->base, interruptible, timeout);
 
 	if (likely(ret > 0))
 		return 0;
@@ -530,7 +530,7 @@ void vmw_fence_obj_flush(struct vmw_fenc
 
 static void vmw_fence_destroy(struct vmw_fence_obj *fence)
 {
-	fence_free(&fence->base);
+	dma_fence_free(&fence->base);
 }
 
 int vmw_fence_create(struct vmw_fence_manager *fman,
@@ -669,7 +669,7 @@ void vmw_fence_fifo_down(struct vmw_fenc
 		struct vmw_fence_obj *fence =
 			list_entry(fman->fence_list.prev, struct vmw_fence_obj,
 				   head);
-		fence_get(&fence->base);
+		dma_fence_get(&fence->base);
 		spin_unlock_irq(&fman->lock);
 
 		ret = vmw_fence_obj_wait(fence, false, false,
@@ -677,7 +677,7 @@ void vmw_fence_fifo_down(struct vmw_fenc
 
 		if (unlikely(ret != 0)) {
 			list_del_init(&fence->head);
-			fence_signal(&fence->base);
+			dma_fence_signal(&fence->base);
 			INIT_LIST_HEAD(&action_list);
 			list_splice_init(&fence->seq_passed_actions,
 					 &action_list);
@@ -685,7 +685,7 @@ void vmw_fence_fifo_down(struct vmw_fenc
 		}
 
 		BUG_ON(!list_empty(&fence->head));
-		fence_put(&fence->base);
+		dma_fence_put(&fence->base);
 		spin_lock_irq(&fman->lock);
 	}
 	spin_unlock_irq(&fman->lock);
@@ -884,7 +884,7 @@ static void vmw_fence_obj_add_action(str
 	spin_lock_irqsave(&fman->lock, irq_flags);
 
 	fman->pending_actions[action->type]++;
-	if (fence_is_signaled_locked(&fence->base)) {
+	if (dma_fence_is_signaled_locked(&fence->base)) {
 		struct list_head action_list;
 
 		INIT_LIST_HEAD(&action_list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 
 #ifndef _VMWGFX_FENCE_H_
 
-#include <linux/fence.h>
+#include <linux/dma-fence.h>
 
 #define VMW_FENCE_WAIT_TIMEOUT (5*HZ)
 
@@ -52,7 +52,7 @@ struct vmw_fence_action {
 };
 
 struct vmw_fence_obj {
-	struct fence base;
+	struct dma_fence base;
 
 	struct list_head head;
 	struct list_head seq_passed_actions;
@@ -71,14 +71,14 @@ vmw_fence_obj_unreference(struct vmw_fen
 
 	*fence_p = NULL;
 	if (fence)
-		fence_put(&fence->base);
+		dma_fence_put(&fence->base);
 }
 
 static inline struct vmw_fence_obj *
 vmw_fence_obj_reference(struct vmw_fence_obj *fence)
 {
 	if (fence)
-		fence_get(&fence->base);
+		dma_fence_get(&fence->base);
 	return fence;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2017-02-12 16:03:20.000000000 -0500
@@ -516,7 +516,7 @@ static const struct drm_framebuffer_func
 static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv,
 					   struct vmw_surface *surface,
 					   struct vmw_framebuffer **out,
-					   const struct drm_mode_fb_cmd
+					   const struct drm_mode_fb_cmd2
 					   *mode_cmd,
 					   bool is_dmabuf_proxy)
 
@@ -525,6 +525,7 @@ static int vmw_kms_new_framebuffer_surfa
 	struct vmw_framebuffer_surface *vfbs;
 	enum SVGA3dSurfaceFormat format;
 	int ret;
+	struct drm_format_name_buf format_name;
 
 	/* 3D is only supported on HWv8 and newer hosts */
 	if (dev_priv->active_display_unit == vmw_du_legacy)
@@ -548,21 +549,22 @@ static int vmw_kms_new_framebuffer_surfa
 		return -EINVAL;
 	}
 
-	switch (mode_cmd->depth) {
-	case 32:
+	switch (mode_cmd->pixel_format) {
+	case DRM_FORMAT_ARGB8888:
 		format = SVGA3D_A8R8G8B8;
 		break;
-	case 24:
+	case DRM_FORMAT_XRGB8888:
 		format = SVGA3D_X8R8G8B8;
 		break;
-	case 16:
+	case DRM_FORMAT_RGB565:
 		format = SVGA3D_R5G6B5;
 		break;
-	case 15:
+	case DRM_FORMAT_XRGB1555:
 		format = SVGA3D_A1R5G5B5;
 		break;
 	default:
-		DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+		DRM_ERROR("Invalid pixel format: %s\n",
+			  drm_get_format_name(mode_cmd->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
@@ -581,14 +583,9 @@ static int vmw_kms_new_framebuffer_surfa
 		goto out_err1;
 	}
 
-	/* XXX get the first 3 from the surface info */
-	vfbs->base.base.bits_per_pixel = mode_cmd->bpp;
-	vfbs->base.base.pitches[0] = mode_cmd->pitch;
-	vfbs->base.base.depth = mode_cmd->depth;
-	vfbs->base.base.width = mode_cmd->width;
-	vfbs->base.base.height = mode_cmd->height;
+	drm_helper_mode_fill_fb_struct(&vfbs->base.base, mode_cmd);
 	vfbs->surface = vmw_surface_reference(surface);
-	vfbs->base.user_handle = mode_cmd->handle;
+	vfbs->base.user_handle = mode_cmd->handles[0];
 	vfbs->is_dmabuf_proxy = is_dmabuf_proxy;
 
 	*out = &vfbs->base;
@@ -755,7 +752,7 @@ static int vmw_framebuffer_unpin(struct
  * 0 on success, error code otherwise
  */
 static int vmw_create_dmabuf_proxy(struct drm_device *dev,
-				   const struct drm_mode_fb_cmd *mode_cmd,
+				   const struct drm_mode_fb_cmd2 *mode_cmd,
 				   struct vmw_dma_buffer *dmabuf_mob,
 				   struct vmw_surface **srf_out)
 {
@@ -763,17 +760,18 @@ static int vmw_create_dmabuf_proxy(struc
 	struct drm_vmw_size content_base_size;
 	struct vmw_resource *res;
 	unsigned int bytes_pp;
+	struct drm_format_name_buf format_name;
 	int ret;
 
-	switch (mode_cmd->depth) {
-	case 32:
-	case 24:
+	switch (mode_cmd->pixel_format) {
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XRGB8888:
 		format = SVGA3D_X8R8G8B8;
 		bytes_pp = 4;
 		break;
 
-	case 16:
-	case 15:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_XRGB1555:
 		format = SVGA3D_R5G6B5;
 		bytes_pp = 2;
 		break;
@@ -784,11 +782,12 @@ static int vmw_create_dmabuf_proxy(struc
 		break;
 
 	default:
-		DRM_ERROR("Invalid framebuffer format %d\n", mode_cmd->depth);
+		DRM_ERROR("Invalid framebuffer format %s\n",
+			  drm_get_format_name(mode_cmd->pixel_format, &format_name));
 		return -EINVAL;
 	}
 
-	content_base_size.width  = mode_cmd->pitch / bytes_pp;
+	content_base_size.width  = mode_cmd->pitches[0] / bytes_pp;
 	content_base_size.height = mode_cmd->height;
 	content_base_size.depth  = 1;
 
@@ -826,16 +825,17 @@ static int vmw_create_dmabuf_proxy(struc
 static int vmw_kms_new_framebuffer_dmabuf(struct vmw_private *dev_priv,
 					  struct vmw_dma_buffer *dmabuf,
 					  struct vmw_framebuffer **out,
-					  const struct drm_mode_fb_cmd
+					  const struct drm_mode_fb_cmd2
 					  *mode_cmd)
 
 {
 	struct drm_device *dev = dev_priv->dev;
 	struct vmw_framebuffer_dmabuf *vfbd;
 	unsigned int requested_size;
+	struct drm_format_name_buf format_name;
 	int ret;
 
-	requested_size = mode_cmd->height * mode_cmd->pitch;
+	requested_size = mode_cmd->height * mode_cmd->pitches[0];
 	if (unlikely(requested_size > dmabuf->base.num_pages * PAGE_SIZE)) {
 		DRM_ERROR("Screen buffer object size is too small "
 			  "for requested mode.\n");
@@ -844,27 +844,16 @@ static int vmw_kms_new_framebuffer_dmabu
 
 	/* Limited framebuffer color depth support for screen objects */
 	if (dev_priv->active_display_unit == vmw_du_screen_object) {
-		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;
+		switch (mode_cmd->pixel_format) {
+		case DRM_FORMAT_XRGB8888:
+		case DRM_FORMAT_ARGB8888:
+			break;
+		case DRM_FORMAT_XRGB1555:
+		case DRM_FORMAT_RGB565:
+			break;
 		default:
-			DRM_ERROR("Invalid color depth: %d\n", mode_cmd->depth);
+			DRM_ERROR("Invalid pixel format: %s\n",
+				  drm_get_format_name(mode_cmd->pixel_format, &format_name));
 			return -EINVAL;
 		}
 	}
@@ -875,14 +864,10 @@ static int vmw_kms_new_framebuffer_dmabu
 		goto out_err1;
 	}
 
-	vfbd->base.base.bits_per_pixel = mode_cmd->bpp;
-	vfbd->base.base.pitches[0] = mode_cmd->pitch;
-	vfbd->base.base.depth = mode_cmd->depth;
-	vfbd->base.base.width = mode_cmd->width;
-	vfbd->base.base.height = mode_cmd->height;
+	drm_helper_mode_fill_fb_struct(&vfbd->base.base, mode_cmd);
 	vfbd->base.dmabuf = true;
 	vfbd->buffer = vmw_dmabuf_reference(dmabuf);
-	vfbd->base.user_handle = mode_cmd->handle;
+	vfbd->base.user_handle = mode_cmd->handles[0];
 	*out = &vfbd->base;
 
 	ret = drm_framebuffer_init(dev, &vfbd->base.base,
@@ -916,7 +901,7 @@ vmw_kms_new_framebuffer(struct vmw_priva
 			struct vmw_dma_buffer *dmabuf,
 			struct vmw_surface *surface,
 			bool only_2d,
-			const struct drm_mode_fb_cmd *mode_cmd)
+			const struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct vmw_framebuffer *vfb = NULL;
 	bool is_dmabuf_proxy = false;
@@ -971,7 +956,7 @@ vmw_kms_new_framebuffer(struct vmw_priva
 
 static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 						 struct drm_file *file_priv,
-						 const struct drm_mode_fb_cmd2 *mode_cmd2)
+						 const struct drm_mode_fb_cmd2 *mode_cmd)
 {
 	struct vmw_private *dev_priv = vmw_priv(dev);
 	struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
@@ -979,16 +964,8 @@ static struct drm_framebuffer *vmw_kms_f
 	struct vmw_surface *surface = NULL;
 	struct vmw_dma_buffer *bo = NULL;
 	struct ttm_base_object *user_obj;
-	struct drm_mode_fb_cmd mode_cmd;
 	int ret;
 
-	mode_cmd.width = mode_cmd2->width;
-	mode_cmd.height = mode_cmd2->height;
-	mode_cmd.pitch = mode_cmd2->pitches[0];
-	mode_cmd.handle = mode_cmd2->handles[0];
-	drm_fb_get_bpp_depth(mode_cmd2->pixel_format, &mode_cmd.depth,
-				    &mode_cmd.bpp);
-
 	/**
 	 * This code should be conditioned on Screen Objects not being used.
 	 * If screen objects are used, we can allocate a GMR to hold the
@@ -996,8 +973,8 @@ static struct drm_framebuffer *vmw_kms_f
 	 */
 
 	if (!vmw_kms_validate_mode_vram(dev_priv,
-					mode_cmd.pitch,
-					mode_cmd.height)) {
+					mode_cmd->pitches[0],
+					mode_cmd->height)) {
 		DRM_ERROR("Requested mode exceed bounding box limit.\n");
 		return ERR_PTR(-ENOMEM);
 	}
@@ -1011,7 +988,7 @@ static struct drm_framebuffer *vmw_kms_f
 	 * command stream using user-space handles.
 	 */
 
-	user_obj = ttm_base_object_lookup(tfile, mode_cmd.handle);
+	user_obj = ttm_base_object_lookup(tfile, mode_cmd->handles[0]);
 	if (unlikely(user_obj == NULL)) {
 		DRM_ERROR("Could not locate requested kms frame buffer.\n");
 		return ERR_PTR(-ENOENT);
@@ -1023,14 +1000,14 @@ static struct drm_framebuffer *vmw_kms_f
 
 	/* returns either a dmabuf or surface */
 	ret = vmw_user_lookup_handle(dev_priv, tfile,
-				     mode_cmd.handle,
+				     mode_cmd->handles[0],
 				     &surface, &bo);
 	if (ret)
 		goto err_out;
 
 	vfb = vmw_kms_new_framebuffer(dev_priv, bo, surface,
 				      !(dev_priv->capabilities & SVGA_CAP_3D),
-				      &mode_cmd);
+				      mode_cmd);
 	if (IS_ERR(vfb)) {
 		ret = PTR_ERR(vfb);
 		goto err_out;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h	2017-02-12 16:03:20.000000000 -0500
@@ -248,7 +248,7 @@ vmw_kms_new_framebuffer(struct vmw_priva
 			struct vmw_dma_buffer *dmabuf,
 			struct vmw_surface *surface,
 			bool only_2d,
-			const struct drm_mode_fb_cmd *mode_cmd);
+			const struct drm_mode_fb_cmd2 *mode_cmd);
 int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
 			    unsigned unit,
 			    u32 max_width,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c	2017-02-12 16:03:20.000000000 -0500
@@ -575,7 +575,7 @@ static int vmw_user_dmabuf_synccpu_grab(
 		long lret;
 
 		lret = reservation_object_wait_timeout_rcu(bo->resv, true, true,
-					nonblock ? 0 : MAX_SCHEDULE_TIMEOUT);
+							   nonblock ? 0 : MAX_SCHEDULE_TIMEOUT);
 		if (!lret)
 			return -EBUSY;
 		else if (lret < 0)
@@ -1454,7 +1454,7 @@ void vmw_fence_single_bo(struct ttm_buff
 	if (fence == NULL) {
 		vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
 		reservation_object_add_excl_fence(bo->resv, &fence->base);
-		fence_put(&fence->base);
+		dma_fence_put(&fence->base);
 	} else
 		reservation_object_add_excl_fence(bo->resv, &fence->base);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,8 @@
+config DRM_ZTE
+	tristate "DRM Support for ZTE SoCs"
+	depends on DRM && ARCH_ZX
+	select DRM_KMS_CMA_HELPER
+	select DRM_KMS_FB_HELPER
+	select DRM_KMS_HELPER
+	help
+	  Choose this option to enable DRM on ZTE ZX SoCs.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/Makefile linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/Makefile
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+zxdrm-y := \
+	zx_drm_drv.o \
+	zx_hdmi.o \
+	zx_plane.o \
+	zx_vou.o
+
+obj-$(CONFIG_DRM_ZTE) += zxdrm.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_drm_drv.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_drm_drv.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_drm_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_drm_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/of_platform.h>
+#include <linux/spinlock.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drmP.h>
+
+#include "zx_drm_drv.h"
+#include "zx_vou.h"
+
+struct zx_drm_private {
+	struct drm_fbdev_cma *fbdev;
+};
+
+static void zx_drm_fb_output_poll_changed(struct drm_device *drm)
+{
+	struct zx_drm_private *priv = drm->dev_private;
+
+	drm_fbdev_cma_hotplug_event(priv->fbdev);
+}
+
+static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = {
+	.fb_create = drm_fb_cma_create,
+	.output_poll_changed = zx_drm_fb_output_poll_changed,
+	.atomic_check = drm_atomic_helper_check,
+	.atomic_commit = drm_atomic_helper_commit,
+};
+
+static void zx_drm_lastclose(struct drm_device *drm)
+{
+	struct zx_drm_private *priv = drm->dev_private;
+
+	drm_fbdev_cma_restore_mode(priv->fbdev);
+}
+
+static const struct file_operations zx_drm_fops = {
+	.owner = THIS_MODULE,
+	.open = drm_open,
+	.release = drm_release,
+	.unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = drm_compat_ioctl,
+#endif
+	.poll = drm_poll,
+	.read = drm_read,
+	.llseek = noop_llseek,
+	.mmap = drm_gem_cma_mmap,
+};
+
+static struct drm_driver zx_drm_driver = {
+	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
+			   DRIVER_ATOMIC,
+	.lastclose = zx_drm_lastclose,
+	.get_vblank_counter = drm_vblank_no_hw_counter,
+	.enable_vblank = zx_vou_enable_vblank,
+	.disable_vblank = zx_vou_disable_vblank,
+	.gem_free_object = drm_gem_cma_free_object,
+	.gem_vm_ops = &drm_gem_cma_vm_ops,
+	.dumb_create = drm_gem_cma_dumb_create,
+	.dumb_map_offset = drm_gem_cma_dumb_map_offset,
+	.dumb_destroy = drm_gem_dumb_destroy,
+	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
+	.gem_prime_export = drm_gem_prime_export,
+	.gem_prime_import = drm_gem_prime_import,
+	.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap = drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap = drm_gem_cma_prime_mmap,
+	.fops = &zx_drm_fops,
+	.name = "zx-vou",
+	.desc = "ZTE VOU Controller DRM",
+	.date = "20160811",
+	.major = 1,
+	.minor = 0,
+};
+
+static int zx_drm_bind(struct device *dev)
+{
+	struct drm_device *drm;
+	struct zx_drm_private *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	drm = drm_dev_alloc(&zx_drm_driver, dev);
+	if (IS_ERR(drm))
+		return PTR_ERR(drm);
+
+	drm->dev_private = priv;
+	dev_set_drvdata(dev, drm);
+
+	drm_mode_config_init(drm);
+	drm->mode_config.min_width = 16;
+	drm->mode_config.min_height = 16;
+	drm->mode_config.max_width = 4096;
+	drm->mode_config.max_height = 4096;
+	drm->mode_config.funcs = &zx_drm_mode_config_funcs;
+
+	ret = component_bind_all(dev, drm);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to bind all components: %d\n", ret);
+		goto out_unregister;
+	}
+
+	ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "failed to init vblank: %d\n", ret);
+		goto out_unbind;
+	}
+
+	/*
+	 * We will manage irq handler on our own.  In this case, irq_enabled
+	 * need to be true for using vblank core support.
+	 */
+	drm->irq_enabled = true;
+
+	drm_mode_config_reset(drm);
+	drm_kms_helper_poll_init(drm);
+
+	priv->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc,
+					 drm->mode_config.num_connector);
+	if (IS_ERR(priv->fbdev)) {
+		ret = PTR_ERR(priv->fbdev);
+		DRM_DEV_ERROR(dev, "failed to init cma fbdev: %d\n", ret);
+		priv->fbdev = NULL;
+		goto out_poll_fini;
+	}
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto out_fbdev_fini;
+
+	return 0;
+
+out_fbdev_fini:
+	if (priv->fbdev) {
+		drm_fbdev_cma_fini(priv->fbdev);
+		priv->fbdev = NULL;
+	}
+out_poll_fini:
+	drm_kms_helper_poll_fini(drm);
+	drm_mode_config_cleanup(drm);
+	drm_vblank_cleanup(drm);
+out_unbind:
+	component_unbind_all(dev, drm);
+out_unregister:
+	dev_set_drvdata(dev, NULL);
+	drm->dev_private = NULL;
+	drm_dev_unref(drm);
+	return ret;
+}
+
+static void zx_drm_unbind(struct device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(dev);
+	struct zx_drm_private *priv = drm->dev_private;
+
+	drm_dev_unregister(drm);
+	if (priv->fbdev) {
+		drm_fbdev_cma_fini(priv->fbdev);
+		priv->fbdev = NULL;
+	}
+	drm_kms_helper_poll_fini(drm);
+	drm_mode_config_cleanup(drm);
+	drm_vblank_cleanup(drm);
+	component_unbind_all(dev, drm);
+	dev_set_drvdata(dev, NULL);
+	drm->dev_private = NULL;
+	drm_dev_unref(drm);
+}
+
+static const struct component_master_ops zx_drm_master_ops = {
+	.bind = zx_drm_bind,
+	.unbind = zx_drm_unbind,
+};
+
+static int compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int zx_drm_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *parent = dev->of_node;
+	struct device_node *child;
+	struct component_match *match = NULL;
+	int ret;
+
+	ret = of_platform_populate(parent, NULL, NULL, dev);
+	if (ret)
+		return ret;
+
+	for_each_available_child_of_node(parent, child) {
+		component_match_add(dev, &match, compare_of, child);
+		of_node_put(child);
+	}
+
+	return component_master_add_with_match(dev, &zx_drm_master_ops, match);
+}
+
+static int zx_drm_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &zx_drm_master_ops);
+	return 0;
+}
+
+static const struct of_device_id zx_drm_of_match[] = {
+	{ .compatible = "zte,zx296718-vou", },
+	{ /* end */ },
+};
+MODULE_DEVICE_TABLE(of, zx_drm_of_match);
+
+static struct platform_driver zx_drm_platform_driver = {
+	.probe = zx_drm_probe,
+	.remove = zx_drm_remove,
+	.driver	= {
+		.name = "zx-drm",
+		.of_match_table	= zx_drm_of_match,
+	},
+};
+
+static struct platform_driver *drivers[] = {
+	&zx_crtc_driver,
+	&zx_hdmi_driver,
+	&zx_drm_platform_driver,
+};
+
+static int zx_drm_init(void)
+{
+	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_init(zx_drm_init);
+
+static void zx_drm_exit(void)
+{
+	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_exit(zx_drm_exit);
+
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("ZTE ZX VOU DRM driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_drm_drv.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_drm_drv.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_drm_drv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_drm_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ZX_DRM_DRV_H__
+#define __ZX_DRM_DRV_H__
+
+extern struct platform_driver zx_crtc_driver;
+extern struct platform_driver zx_hdmi_driver;
+
+static inline u32 zx_readl(void __iomem *reg)
+{
+	return readl_relaxed(reg);
+}
+
+static inline void zx_writel(void __iomem *reg, u32 val)
+{
+	writel_relaxed(val, reg);
+}
+
+static inline void zx_writel_mask(void __iomem *reg, u32 mask, u32 val)
+{
+	u32 tmp;
+
+	tmp = zx_readl(reg);
+	tmp = (tmp & ~mask) | (val & mask);
+	zx_writel(reg, tmp);
+}
+
+#endif /* __ZX_DRM_DRV_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_hdmi.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_hdmi.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_hdmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_hdmi.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,624 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hdmi.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_of.h>
+#include <drm/drmP.h>
+
+#include "zx_hdmi_regs.h"
+#include "zx_vou.h"
+
+#define ZX_HDMI_INFOFRAME_SIZE		31
+#define DDC_SEGMENT_ADDR		0x30
+
+struct zx_hdmi_i2c {
+	struct i2c_adapter adap;
+	struct mutex lock;
+};
+
+struct zx_hdmi {
+	struct drm_connector connector;
+	struct drm_encoder encoder;
+	struct zx_hdmi_i2c *ddc;
+	struct device *dev;
+	struct drm_device *drm;
+	void __iomem *mmio;
+	struct clk *cec_clk;
+	struct clk *osc_clk;
+	struct clk *xclk;
+	bool sink_is_hdmi;
+	bool sink_has_audio;
+	const struct vou_inf *inf;
+};
+
+#define to_zx_hdmi(x) container_of(x, struct zx_hdmi, x)
+
+static const struct vou_inf vou_inf_hdmi = {
+	.id = VOU_HDMI,
+	.data_sel = VOU_YUV444,
+	.clocks_en_bits = BIT(24) | BIT(18) | BIT(6),
+	.clocks_sel_bits = BIT(13) | BIT(2),
+};
+
+static inline u8 hdmi_readb(struct zx_hdmi *hdmi, u16 offset)
+{
+	return readl_relaxed(hdmi->mmio + offset * 4);
+}
+
+static inline void hdmi_writeb(struct zx_hdmi *hdmi, u16 offset, u8 val)
+{
+	writel_relaxed(val, hdmi->mmio + offset * 4);
+}
+
+static inline void hdmi_writeb_mask(struct zx_hdmi *hdmi, u16 offset,
+				    u8 mask, u8 val)
+{
+	u8 tmp;
+
+	tmp = hdmi_readb(hdmi, offset);
+	tmp = (tmp & ~mask) | (val & mask);
+	hdmi_writeb(hdmi, offset, tmp);
+}
+
+static int zx_hdmi_infoframe_trans(struct zx_hdmi *hdmi,
+				   union hdmi_infoframe *frame, u8 fsel)
+{
+	u8 buffer[ZX_HDMI_INFOFRAME_SIZE];
+	int num;
+	int i;
+
+	hdmi_writeb(hdmi, TPI_INFO_FSEL, fsel);
+
+	num = hdmi_infoframe_pack(frame, buffer, ZX_HDMI_INFOFRAME_SIZE);
+	if (num < 0) {
+		DRM_DEV_ERROR(hdmi->dev, "failed to pack infoframe: %d\n", num);
+		return num;
+	}
+
+	for (i = 0; i < num; i++)
+		hdmi_writeb(hdmi, TPI_INFO_B0 + i, buffer[i]);
+
+	hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_RPT,
+			 TPI_INFO_TRANS_RPT);
+	hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_EN,
+			 TPI_INFO_TRANS_EN);
+
+	return num;
+}
+
+static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi,
+				    struct drm_display_mode *mode)
+{
+	union hdmi_infoframe frame;
+	int ret;
+
+	ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
+							  mode);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n",
+			      ret);
+		return ret;
+	}
+
+	return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_VSIF);
+}
+
+static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
+				    struct drm_display_mode *mode)
+{
+	union hdmi_infoframe frame;
+	int ret;
+
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
+			      ret);
+		return ret;
+	}
+
+	/* We always use YUV444 for HDMI output. */
+	frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
+
+	return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AVI);
+}
+
+static void zx_hdmi_encoder_mode_set(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adj_mode)
+{
+	struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
+
+	if (hdmi->sink_is_hdmi) {
+		zx_hdmi_config_video_avi(hdmi, mode);
+		zx_hdmi_config_video_vsi(hdmi, mode);
+	}
+}
+
+static void zx_hdmi_phy_start(struct zx_hdmi *hdmi)
+{
+	/* Copy from ZTE BSP code */
+	hdmi_writeb(hdmi, 0x222, 0x0);
+	hdmi_writeb(hdmi, 0x224, 0x4);
+	hdmi_writeb(hdmi, 0x909, 0x0);
+	hdmi_writeb(hdmi, 0x7b0, 0x90);
+	hdmi_writeb(hdmi, 0x7b1, 0x00);
+	hdmi_writeb(hdmi, 0x7b2, 0xa7);
+	hdmi_writeb(hdmi, 0x7b8, 0xaa);
+	hdmi_writeb(hdmi, 0x7b2, 0xa7);
+	hdmi_writeb(hdmi, 0x7b3, 0x0f);
+	hdmi_writeb(hdmi, 0x7b4, 0x0f);
+	hdmi_writeb(hdmi, 0x7b5, 0x55);
+	hdmi_writeb(hdmi, 0x7b7, 0x03);
+	hdmi_writeb(hdmi, 0x7b9, 0x12);
+	hdmi_writeb(hdmi, 0x7ba, 0x32);
+	hdmi_writeb(hdmi, 0x7bc, 0x68);
+	hdmi_writeb(hdmi, 0x7be, 0x40);
+	hdmi_writeb(hdmi, 0x7bf, 0x84);
+	hdmi_writeb(hdmi, 0x7c1, 0x0f);
+	hdmi_writeb(hdmi, 0x7c8, 0x02);
+	hdmi_writeb(hdmi, 0x7c9, 0x03);
+	hdmi_writeb(hdmi, 0x7ca, 0x40);
+	hdmi_writeb(hdmi, 0x7dc, 0x31);
+	hdmi_writeb(hdmi, 0x7e2, 0x04);
+	hdmi_writeb(hdmi, 0x7e0, 0x06);
+	hdmi_writeb(hdmi, 0x7cb, 0x68);
+	hdmi_writeb(hdmi, 0x7f9, 0x02);
+	hdmi_writeb(hdmi, 0x7b6, 0x02);
+	hdmi_writeb(hdmi, 0x7f3, 0x0);
+}
+
+static void zx_hdmi_hw_enable(struct zx_hdmi *hdmi)
+{
+	/* Enable pclk */
+	hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, CLKPWD_PDIDCK);
+
+	/* Enable HDMI for TX */
+	hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, FUNC_HDMI_EN);
+
+	/* Enable deep color packet */
+	hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
+
+	/* Enable HDMI/MHL mode for output */
+	hdmi_writeb_mask(hdmi, TEST_TXCTRL, TEST_TXCTRL_HDMI_MODE,
+			 TEST_TXCTRL_HDMI_MODE);
+
+	/* Configure reg_qc_sel */
+	hdmi_writeb(hdmi, HDMICTL4, 0x3);
+
+	/* Enable interrupt */
+	hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT,
+			 INTR1_MONITOR_DETECT);
+
+	/* Start up phy */
+	zx_hdmi_phy_start(hdmi);
+}
+
+static void zx_hdmi_hw_disable(struct zx_hdmi *hdmi)
+{
+	/* Disable interrupt */
+	hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, 0);
+
+	/* Disable deep color packet */
+	hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
+
+	/* Disable HDMI for TX */
+	hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, 0);
+
+	/* Disable pclk */
+	hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, 0);
+}
+
+static void zx_hdmi_encoder_enable(struct drm_encoder *encoder)
+{
+	struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
+
+	clk_prepare_enable(hdmi->cec_clk);
+	clk_prepare_enable(hdmi->osc_clk);
+	clk_prepare_enable(hdmi->xclk);
+
+	zx_hdmi_hw_enable(hdmi);
+
+	vou_inf_enable(hdmi->inf, encoder->crtc);
+}
+
+static void zx_hdmi_encoder_disable(struct drm_encoder *encoder)
+{
+	struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
+
+	vou_inf_disable(hdmi->inf, encoder->crtc);
+
+	zx_hdmi_hw_disable(hdmi);
+
+	clk_disable_unprepare(hdmi->xclk);
+	clk_disable_unprepare(hdmi->osc_clk);
+	clk_disable_unprepare(hdmi->cec_clk);
+}
+
+static const struct drm_encoder_helper_funcs zx_hdmi_encoder_helper_funcs = {
+	.enable	= zx_hdmi_encoder_enable,
+	.disable = zx_hdmi_encoder_disable,
+	.mode_set = zx_hdmi_encoder_mode_set,
+};
+
+static const struct drm_encoder_funcs zx_hdmi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static int zx_hdmi_connector_get_modes(struct drm_connector *connector)
+{
+	struct zx_hdmi *hdmi = to_zx_hdmi(connector);
+	struct edid *edid;
+	int ret;
+
+	edid = drm_get_edid(connector, &hdmi->ddc->adap);
+	if (!edid)
+		return 0;
+
+	hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
+	hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
+	drm_mode_connector_update_edid_property(connector, edid);
+	ret = drm_add_edid_modes(connector, edid);
+	kfree(edid);
+
+	return ret;
+}
+
+static enum drm_mode_status
+zx_hdmi_connector_mode_valid(struct drm_connector *connector,
+			     struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs zx_hdmi_connector_helper_funcs = {
+	.get_modes = zx_hdmi_connector_get_modes,
+	.mode_valid = zx_hdmi_connector_mode_valid,
+};
+
+static enum drm_connector_status
+zx_hdmi_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct zx_hdmi *hdmi = to_zx_hdmi(connector);
+
+	return (hdmi_readb(hdmi, TPI_HPD_RSEN) & TPI_HPD_CONNECTION) ?
+		connector_status_connected : connector_status_disconnected;
+}
+
+static const struct drm_connector_funcs zx_hdmi_connector_funcs = {
+	.dpms = drm_atomic_helper_connector_dpms,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.detect = zx_hdmi_connector_detect,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi)
+{
+	struct drm_encoder *encoder = &hdmi->encoder;
+
+	encoder->possible_crtcs = VOU_CRTC_MASK;
+
+	drm_encoder_init(drm, encoder, &zx_hdmi_encoder_funcs,
+			 DRM_MODE_ENCODER_TMDS, NULL);
+	drm_encoder_helper_add(encoder, &zx_hdmi_encoder_helper_funcs);
+
+	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
+
+	drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs,
+			   DRM_MODE_CONNECTOR_HDMIA);
+	drm_connector_helper_add(&hdmi->connector,
+				 &zx_hdmi_connector_helper_funcs);
+
+	drm_mode_connector_attach_encoder(&hdmi->connector, encoder);
+
+	return 0;
+}
+
+static irqreturn_t zx_hdmi_irq_thread(int irq, void *dev_id)
+{
+	struct zx_hdmi *hdmi = dev_id;
+
+	drm_helper_hpd_irq_event(hdmi->connector.dev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t zx_hdmi_irq_handler(int irq, void *dev_id)
+{
+	struct zx_hdmi *hdmi = dev_id;
+	u8 lstat;
+
+	lstat = hdmi_readb(hdmi, L1_INTR_STAT);
+
+	/* Monitor detect/HPD interrupt */
+	if (lstat & L1_INTR_STAT_INTR1) {
+		u8 stat;
+
+		stat = hdmi_readb(hdmi, INTR1_STAT);
+		hdmi_writeb(hdmi, INTR1_STAT, stat);
+
+		if (stat & INTR1_MONITOR_DETECT)
+			return IRQ_WAKE_THREAD;
+	}
+
+	return IRQ_NONE;
+}
+
+static int zx_hdmi_i2c_read(struct zx_hdmi *hdmi, struct i2c_msg *msg)
+{
+	int len = msg->len;
+	u8 *buf = msg->buf;
+	int retry = 0;
+	int ret = 0;
+
+	/* Bits [9:8] of bytes */
+	hdmi_writeb(hdmi, ZX_DDC_DIN_CNT2, (len >> 8) & 0xff);
+	/* Bits [7:0] of bytes */
+	hdmi_writeb(hdmi, ZX_DDC_DIN_CNT1, len & 0xff);
+
+	/* Clear FIFO */
+	hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, DDC_CMD_CLEAR_FIFO);
+
+	/* Kick off the read */
+	hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK,
+			 DDC_CMD_SEQUENTIAL_READ);
+
+	while (len > 0) {
+		int cnt, i;
+
+		/* FIFO needs some time to get ready */
+		usleep_range(500, 1000);
+
+		cnt = hdmi_readb(hdmi, ZX_DDC_DOUT_CNT) & DDC_DOUT_CNT_MASK;
+		if (cnt == 0) {
+			if (++retry > 5) {
+				DRM_DEV_ERROR(hdmi->dev,
+					      "DDC FIFO read timed out!");
+				return -ETIMEDOUT;
+			}
+			continue;
+		}
+
+		for (i = 0; i < cnt; i++)
+			*buf++ = hdmi_readb(hdmi, ZX_DDC_DATA);
+		len -= cnt;
+	}
+
+	return ret;
+}
+
+static int zx_hdmi_i2c_write(struct zx_hdmi *hdmi, struct i2c_msg *msg)
+{
+	/*
+	 * The DDC I2C adapter is only for reading EDID data, so we assume
+	 * that the write to this adapter must be the EDID data offset.
+	 */
+	if ((msg->len != 1) ||
+	    ((msg->addr != DDC_ADDR) && (msg->addr != DDC_SEGMENT_ADDR)))
+		return -EINVAL;
+
+	if (msg->addr == DDC_SEGMENT_ADDR)
+		hdmi_writeb(hdmi, ZX_DDC_SEGM, msg->addr << 1);
+	else if (msg->addr == DDC_ADDR)
+		hdmi_writeb(hdmi, ZX_DDC_ADDR, msg->addr << 1);
+
+	hdmi_writeb(hdmi, ZX_DDC_OFFSET, msg->buf[0]);
+
+	return 0;
+}
+
+static int zx_hdmi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			    int num)
+{
+	struct zx_hdmi *hdmi = i2c_get_adapdata(adap);
+	struct zx_hdmi_i2c *ddc = hdmi->ddc;
+	int i, ret = 0;
+
+	mutex_lock(&ddc->lock);
+
+	/* Enable DDC master access */
+	hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, HW_DDC_MASTER);
+
+	for (i = 0; i < num; i++) {
+		DRM_DEV_DEBUG(hdmi->dev,
+			      "xfer: num: %d/%d, len: %d, flags: %#x\n",
+			      i + 1, num, msgs[i].len, msgs[i].flags);
+
+		if (msgs[i].flags & I2C_M_RD)
+			ret = zx_hdmi_i2c_read(hdmi, &msgs[i]);
+		else
+			ret = zx_hdmi_i2c_write(hdmi, &msgs[i]);
+
+		if (ret < 0)
+			break;
+	}
+
+	if (!ret)
+		ret = num;
+
+	/* Disable DDC master access */
+	hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, 0);
+
+	mutex_unlock(&ddc->lock);
+
+	return ret;
+}
+
+static u32 zx_hdmi_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm zx_hdmi_algorithm = {
+	.master_xfer	= zx_hdmi_i2c_xfer,
+	.functionality	= zx_hdmi_i2c_func,
+};
+
+static int zx_hdmi_ddc_register(struct zx_hdmi *hdmi)
+{
+	struct i2c_adapter *adap;
+	struct zx_hdmi_i2c *ddc;
+	int ret;
+
+	ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL);
+	if (!ddc)
+		return -ENOMEM;
+
+	hdmi->ddc = ddc;
+	mutex_init(&ddc->lock);
+
+	adap = &ddc->adap;
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_DDC;
+	adap->dev.parent = hdmi->dev;
+	adap->algo = &zx_hdmi_algorithm;
+	snprintf(adap->name, sizeof(adap->name), "zx hdmi i2c");
+
+	ret = i2c_add_adapter(adap);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "failed to add I2C adapter: %d\n",
+			      ret);
+		return ret;
+	}
+
+	i2c_set_adapdata(adap, hdmi);
+
+	return 0;
+}
+
+static int zx_hdmi_bind(struct device *dev, struct device *master, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct resource *res;
+	struct zx_hdmi *hdmi;
+	int irq;
+	int ret;
+
+	hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
+	if (!hdmi)
+		return -ENOMEM;
+
+	hdmi->dev = dev;
+	hdmi->drm = drm;
+	hdmi->inf = &vou_inf_hdmi;
+
+	dev_set_drvdata(dev, hdmi);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hdmi->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(hdmi->mmio)) {
+		ret = PTR_ERR(hdmi->mmio);
+		DRM_DEV_ERROR(dev, "failed to remap hdmi region: %d\n", ret);
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	hdmi->cec_clk = devm_clk_get(hdmi->dev, "osc_cec");
+	if (IS_ERR(hdmi->cec_clk)) {
+		ret = PTR_ERR(hdmi->cec_clk);
+		DRM_DEV_ERROR(dev, "failed to get cec_clk: %d\n", ret);
+		return ret;
+	}
+
+	hdmi->osc_clk = devm_clk_get(hdmi->dev, "osc_clk");
+	if (IS_ERR(hdmi->osc_clk)) {
+		ret = PTR_ERR(hdmi->osc_clk);
+		DRM_DEV_ERROR(dev, "failed to get osc_clk: %d\n", ret);
+		return ret;
+	}
+
+	hdmi->xclk = devm_clk_get(hdmi->dev, "xclk");
+	if (IS_ERR(hdmi->xclk)) {
+		ret = PTR_ERR(hdmi->xclk);
+		DRM_DEV_ERROR(dev, "failed to get xclk: %d\n", ret);
+		return ret;
+	}
+
+	ret = zx_hdmi_ddc_register(hdmi);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret);
+		return ret;
+	}
+
+	ret = zx_hdmi_register(drm, hdmi);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to register hdmi: %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_request_threaded_irq(dev, irq, zx_hdmi_irq_handler,
+					zx_hdmi_irq_thread, IRQF_SHARED,
+					dev_name(dev), hdmi);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void zx_hdmi_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct zx_hdmi *hdmi = dev_get_drvdata(dev);
+
+	hdmi->connector.funcs->destroy(&hdmi->connector);
+	hdmi->encoder.funcs->destroy(&hdmi->encoder);
+}
+
+static const struct component_ops zx_hdmi_component_ops = {
+	.bind = zx_hdmi_bind,
+	.unbind = zx_hdmi_unbind,
+};
+
+static int zx_hdmi_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &zx_hdmi_component_ops);
+}
+
+static int zx_hdmi_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &zx_hdmi_component_ops);
+	return 0;
+}
+
+static const struct of_device_id zx_hdmi_of_match[] = {
+	{ .compatible = "zte,zx296718-hdmi", },
+	{ /* end */ },
+};
+MODULE_DEVICE_TABLE(of, zx_hdmi_of_match);
+
+struct platform_driver zx_hdmi_driver = {
+	.probe = zx_hdmi_probe,
+	.remove = zx_hdmi_remove,
+	.driver	= {
+		.name = "zx-hdmi",
+		.of_match_table	= zx_hdmi_of_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_hdmi_regs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_hdmi_regs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_hdmi_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_hdmi_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ZX_HDMI_REGS_H__
+#define __ZX_HDMI_REGS_H__
+
+#define FUNC_SEL			0x000b
+#define FUNC_HDMI_EN			BIT(0)
+#define CLKPWD				0x000d
+#define CLKPWD_PDIDCK			BIT(2)
+#define P2T_CTRL			0x0066
+#define P2T_DC_PKT_EN			BIT(7)
+#define L1_INTR_STAT			0x007e
+#define L1_INTR_STAT_INTR1		BIT(0)
+#define INTR1_STAT			0x008f
+#define INTR1_MASK			0x0095
+#define INTR1_MONITOR_DETECT		(BIT(5) | BIT(6))
+#define ZX_DDC_ADDR			0x00ed
+#define ZX_DDC_SEGM			0x00ee
+#define ZX_DDC_OFFSET			0x00ef
+#define ZX_DDC_DIN_CNT1			0x00f0
+#define ZX_DDC_DIN_CNT2			0x00f1
+#define ZX_DDC_CMD			0x00f3
+#define DDC_CMD_MASK			0xf
+#define DDC_CMD_CLEAR_FIFO		0x9
+#define DDC_CMD_SEQUENTIAL_READ		0x2
+#define ZX_DDC_DATA			0x00f4
+#define ZX_DDC_DOUT_CNT			0x00f5
+#define DDC_DOUT_CNT_MASK		0x1f
+#define TEST_TXCTRL			0x00f7
+#define TEST_TXCTRL_HDMI_MODE		BIT(1)
+#define HDMICTL4			0x0235
+#define TPI_HPD_RSEN			0x063b
+#define TPI_HPD_CONNECTION		(BIT(1) | BIT(2))
+#define TPI_INFO_FSEL			0x06bf
+#define FSEL_AVI			0
+#define FSEL_GBD			1
+#define FSEL_AUDIO			2
+#define FSEL_SPD			3
+#define FSEL_MPEG			4
+#define FSEL_VSIF			5
+#define TPI_INFO_B0			0x06c0
+#define TPI_INFO_EN			0x06df
+#define TPI_INFO_TRANS_EN		BIT(7)
+#define TPI_INFO_TRANS_RPT		BIT(6)
+#define TPI_DDC_MASTER_EN		0x06f8
+#define HW_DDC_MASTER			BIT(7)
+
+#endif /* __ZX_HDMI_REGS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_plane.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_plane.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_plane.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_plane.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "zx_drm_drv.h"
+#include "zx_plane.h"
+#include "zx_plane_regs.h"
+#include "zx_vou.h"
+
+struct zx_plane {
+	struct drm_plane plane;
+	void __iomem *layer;
+	void __iomem *csc;
+	void __iomem *hbsc;
+	void __iomem *rsz;
+};
+
+#define to_zx_plane(plane)	container_of(plane, struct zx_plane, plane)
+
+static const uint32_t gl_formats[] = {
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ARGB4444,
+};
+
+static int zx_gl_plane_atomic_check(struct drm_plane *plane,
+				    struct drm_plane_state *plane_state)
+{
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_crtc *crtc = plane_state->crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_rect clip;
+
+	if (!crtc || !fb)
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(plane_state->state,
+							crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	/* nothing to check when disabling or disabled */
+	if (!crtc_state->enable)
+		return 0;
+
+	/* plane must be enabled */
+	if (!plane_state->crtc)
+		return -EINVAL;
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc_state->adjusted_mode.hdisplay;
+	clip.y2 = crtc_state->adjusted_mode.vdisplay;
+
+	return drm_plane_helper_check_state(plane_state, &clip,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    false, true);
+}
+
+static int zx_gl_get_fmt(uint32_t format)
+{
+	switch (format) {
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XRGB8888:
+		return GL_FMT_ARGB8888;
+	case DRM_FORMAT_RGB888:
+		return GL_FMT_RGB888;
+	case DRM_FORMAT_RGB565:
+		return GL_FMT_RGB565;
+	case DRM_FORMAT_ARGB1555:
+		return GL_FMT_ARGB1555;
+	case DRM_FORMAT_ARGB4444:
+		return GL_FMT_ARGB4444;
+	default:
+		WARN_ONCE(1, "invalid pixel format %d\n", format);
+		return -EINVAL;
+	}
+}
+
+static inline void zx_gl_set_update(struct zx_plane *zplane)
+{
+	void __iomem *layer = zplane->layer;
+
+	zx_writel_mask(layer + GL_CTRL0, GL_UPDATE, GL_UPDATE);
+}
+
+static inline void zx_gl_rsz_set_update(struct zx_plane *zplane)
+{
+	zx_writel(zplane->rsz + RSZ_ENABLE_CFG, 1);
+}
+
+void zx_plane_set_update(struct drm_plane *plane)
+{
+	struct zx_plane *zplane = to_zx_plane(plane);
+
+	zx_gl_rsz_set_update(zplane);
+	zx_gl_set_update(zplane);
+}
+
+static void zx_gl_rsz_setup(struct zx_plane *zplane, u32 src_w, u32 src_h,
+			    u32 dst_w, u32 dst_h)
+{
+	void __iomem *rsz = zplane->rsz;
+
+	zx_writel(rsz + RSZ_SRC_CFG, RSZ_VER(src_h - 1) | RSZ_HOR(src_w - 1));
+	zx_writel(rsz + RSZ_DEST_CFG, RSZ_VER(dst_h - 1) | RSZ_HOR(dst_w - 1));
+
+	zx_gl_rsz_set_update(zplane);
+}
+
+static void zx_gl_plane_atomic_update(struct drm_plane *plane,
+				      struct drm_plane_state *old_state)
+{
+	struct zx_plane *zplane = to_zx_plane(plane);
+	struct drm_framebuffer *fb = plane->state->fb;
+	struct drm_gem_cma_object *cma_obj;
+	void __iomem *layer = zplane->layer;
+	void __iomem *csc = zplane->csc;
+	void __iomem *hbsc = zplane->hbsc;
+	u32 src_x, src_y, src_w, src_h;
+	u32 dst_x, dst_y, dst_w, dst_h;
+	unsigned int bpp;
+	uint32_t format;
+	dma_addr_t paddr;
+	u32 stride;
+	int fmt;
+
+	if (!fb)
+		return;
+
+	format = fb->pixel_format;
+	stride = fb->pitches[0];
+
+	src_x = plane->state->src_x >> 16;
+	src_y = plane->state->src_y >> 16;
+	src_w = plane->state->src_w >> 16;
+	src_h = plane->state->src_h >> 16;
+
+	dst_x = plane->state->crtc_x;
+	dst_y = plane->state->crtc_y;
+	dst_w = plane->state->crtc_w;
+	dst_h = plane->state->crtc_h;
+
+	bpp = drm_format_plane_cpp(format, 0);
+
+	cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
+	paddr = cma_obj->paddr + fb->offsets[0];
+	paddr += src_y * stride + src_x * bpp / 8;
+	zx_writel(layer + GL_ADDR, paddr);
+
+	/* Set up source height/width register */
+	zx_writel(layer + GL_SRC_SIZE, GL_SRC_W(src_w) | GL_SRC_H(src_h));
+
+	/* Set up start position register */
+	zx_writel(layer + GL_POS_START, GL_POS_X(dst_x) | GL_POS_Y(dst_y));
+
+	/* Set up end position register */
+	zx_writel(layer + GL_POS_END,
+		  GL_POS_X(dst_x + dst_w) | GL_POS_Y(dst_y + dst_h));
+
+	/* Set up stride register */
+	zx_writel(layer + GL_STRIDE, stride & 0xffff);
+
+	/* Set up graphic layer data format */
+	fmt = zx_gl_get_fmt(format);
+	if (fmt >= 0)
+		zx_writel_mask(layer + GL_CTRL1, GL_DATA_FMT_MASK,
+			       fmt << GL_DATA_FMT_SHIFT);
+
+	/* Initialize global alpha with a sane value */
+	zx_writel_mask(layer + GL_CTRL2, GL_GLOBAL_ALPHA_MASK,
+		       0xff << GL_GLOBAL_ALPHA_SHIFT);
+
+	/* Setup CSC for the GL */
+	if (dst_h > 720)
+		zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
+			       CSC_BT709_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
+	else
+		zx_writel_mask(csc + CSC_CTRL0, CSC_COV_MODE_MASK,
+			       CSC_BT601_IMAGE_RGB2YCBCR << CSC_COV_MODE_SHIFT);
+	zx_writel_mask(csc + CSC_CTRL0, CSC_WORK_ENABLE, CSC_WORK_ENABLE);
+
+	/* Always use scaler since it exists (set for not bypass) */
+	zx_writel_mask(layer + GL_CTRL3, GL_SCALER_BYPASS_MODE,
+		       GL_SCALER_BYPASS_MODE);
+
+	zx_gl_rsz_setup(zplane, src_w, src_h, dst_w, dst_h);
+
+	/* Enable HBSC block */
+	zx_writel_mask(hbsc + HBSC_CTRL0, HBSC_CTRL_EN, HBSC_CTRL_EN);
+
+	zx_gl_set_update(zplane);
+}
+
+static const struct drm_plane_helper_funcs zx_gl_plane_helper_funcs = {
+	.atomic_check = zx_gl_plane_atomic_check,
+	.atomic_update = zx_gl_plane_atomic_update,
+};
+
+static void zx_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_helper_disable(plane);
+	drm_plane_cleanup(plane);
+}
+
+static const struct drm_plane_funcs zx_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = zx_plane_destroy,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static void zx_plane_hbsc_init(struct zx_plane *zplane)
+{
+	void __iomem *hbsc = zplane->hbsc;
+
+	/*
+	 *  Initialize HBSC block with a sane configuration per recommedation
+	 *  from ZTE BSP code.
+	 */
+	zx_writel(hbsc + HBSC_SATURATION, 0x200);
+	zx_writel(hbsc + HBSC_HUE, 0x0);
+	zx_writel(hbsc + HBSC_BRIGHT, 0x0);
+	zx_writel(hbsc + HBSC_CONTRAST, 0x200);
+
+	zx_writel(hbsc + HBSC_THRESHOLD_COL1, (0x3ac << 16) | 0x40);
+	zx_writel(hbsc + HBSC_THRESHOLD_COL2, (0x3c0 << 16) | 0x40);
+	zx_writel(hbsc + HBSC_THRESHOLD_COL3, (0x3c0 << 16) | 0x40);
+}
+
+struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
+				struct zx_layer_data *data,
+				enum drm_plane_type type)
+{
+	const struct drm_plane_helper_funcs *helper;
+	struct zx_plane *zplane;
+	struct drm_plane *plane;
+	const uint32_t *formats;
+	unsigned int format_count;
+	int ret;
+
+	zplane = devm_kzalloc(dev, sizeof(*zplane), GFP_KERNEL);
+	if (!zplane)
+		return ERR_PTR(-ENOMEM);
+
+	plane = &zplane->plane;
+
+	zplane->layer = data->layer;
+	zplane->hbsc = data->hbsc;
+	zplane->csc = data->csc;
+	zplane->rsz = data->rsz;
+
+	zx_plane_hbsc_init(zplane);
+
+	switch (type) {
+	case DRM_PLANE_TYPE_PRIMARY:
+		helper = &zx_gl_plane_helper_funcs;
+		formats = gl_formats;
+		format_count = ARRAY_SIZE(gl_formats);
+		break;
+	case DRM_PLANE_TYPE_OVERLAY:
+		/* TODO: add video layer (vl) support */
+		break;
+	default:
+		return ERR_PTR(-ENODEV);
+	}
+
+	ret = drm_universal_plane_init(drm, plane, VOU_CRTC_MASK,
+				       &zx_plane_funcs, formats, format_count,
+				       type, NULL);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to init universal plane: %d\n", ret);
+		return ERR_PTR(ret);
+	}
+
+	drm_plane_helper_add(plane, helper);
+
+	return plane;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_plane.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_plane.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_plane.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_plane.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ZX_PLANE_H__
+#define __ZX_PLANE_H__
+
+struct zx_layer_data {
+	void __iomem *layer;
+	void __iomem *csc;
+	void __iomem *hbsc;
+	void __iomem *rsz;
+};
+
+struct drm_plane *zx_plane_init(struct drm_device *drm, struct device *dev,
+				struct zx_layer_data *data,
+				enum drm_plane_type type);
+void zx_plane_set_update(struct drm_plane *plane);
+
+#endif /* __ZX_PLANE_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_plane_regs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_plane_regs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_plane_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_plane_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ZX_PLANE_REGS_H__
+#define __ZX_PLANE_REGS_H__
+
+/* GL registers */
+#define GL_CTRL0			0x00
+#define GL_UPDATE			BIT(5)
+#define GL_CTRL1			0x04
+#define GL_DATA_FMT_SHIFT		0
+#define GL_DATA_FMT_MASK		(0xf << GL_DATA_FMT_SHIFT)
+#define GL_FMT_ARGB8888			0
+#define GL_FMT_RGB888			1
+#define GL_FMT_RGB565			2
+#define GL_FMT_ARGB1555			3
+#define GL_FMT_ARGB4444			4
+#define GL_CTRL2			0x08
+#define GL_GLOBAL_ALPHA_SHIFT		8
+#define GL_GLOBAL_ALPHA_MASK		(0xff << GL_GLOBAL_ALPHA_SHIFT)
+#define GL_CTRL3			0x0c
+#define GL_SCALER_BYPASS_MODE		BIT(0)
+#define GL_STRIDE			0x18
+#define GL_ADDR				0x1c
+#define GL_SRC_SIZE			0x38
+#define GL_SRC_W_SHIFT			16
+#define GL_SRC_W_MASK			(0x3fff << GL_SRC_W_SHIFT)
+#define GL_SRC_H_SHIFT			0
+#define GL_SRC_H_MASK			(0x3fff << GL_SRC_H_SHIFT)
+#define GL_POS_START			0x9c
+#define GL_POS_END			0xa0
+#define GL_POS_X_SHIFT			16
+#define GL_POS_X_MASK			(0x1fff << GL_POS_X_SHIFT)
+#define GL_POS_Y_SHIFT			0
+#define GL_POS_Y_MASK			(0x1fff << GL_POS_Y_SHIFT)
+
+#define GL_SRC_W(x)	(((x) << GL_SRC_W_SHIFT) & GL_SRC_W_MASK)
+#define GL_SRC_H(x)	(((x) << GL_SRC_H_SHIFT) & GL_SRC_H_MASK)
+#define GL_POS_X(x)	(((x) << GL_POS_X_SHIFT) & GL_POS_X_MASK)
+#define GL_POS_Y(x)	(((x) << GL_POS_Y_SHIFT) & GL_POS_Y_MASK)
+
+/* CSC registers */
+#define CSC_CTRL0			0x30
+#define CSC_COV_MODE_SHIFT		16
+#define CSC_COV_MODE_MASK		(0xffff << CSC_COV_MODE_SHIFT)
+#define CSC_BT601_IMAGE_RGB2YCBCR	0
+#define CSC_BT601_IMAGE_YCBCR2RGB	1
+#define CSC_BT601_VIDEO_RGB2YCBCR	2
+#define CSC_BT601_VIDEO_YCBCR2RGB	3
+#define CSC_BT709_IMAGE_RGB2YCBCR	4
+#define CSC_BT709_IMAGE_YCBCR2RGB	5
+#define CSC_BT709_VIDEO_RGB2YCBCR	6
+#define CSC_BT709_VIDEO_YCBCR2RGB	7
+#define CSC_BT2020_IMAGE_RGB2YCBCR	8
+#define CSC_BT2020_IMAGE_YCBCR2RGB	9
+#define CSC_BT2020_VIDEO_RGB2YCBCR	10
+#define CSC_BT2020_VIDEO_YCBCR2RGB	11
+#define CSC_WORK_ENABLE			BIT(0)
+
+/* RSZ registers */
+#define RSZ_SRC_CFG			0x00
+#define RSZ_DEST_CFG			0x04
+#define RSZ_ENABLE_CFG			0x14
+
+#define RSZ_VER_SHIFT			16
+#define RSZ_VER_MASK			(0xffff << RSZ_VER_SHIFT)
+#define RSZ_HOR_SHIFT			0
+#define RSZ_HOR_MASK			(0xffff << RSZ_HOR_SHIFT)
+
+#define RSZ_VER(x)	(((x) << RSZ_VER_SHIFT) & RSZ_VER_MASK)
+#define RSZ_HOR(x)	(((x) << RSZ_HOR_SHIFT) & RSZ_HOR_MASK)
+
+/* HBSC registers */
+#define HBSC_SATURATION			0x00
+#define HBSC_HUE			0x04
+#define HBSC_BRIGHT			0x08
+#define HBSC_CONTRAST			0x0c
+#define HBSC_THRESHOLD_COL1		0x10
+#define HBSC_THRESHOLD_COL2		0x14
+#define HBSC_THRESHOLD_COL3		0x18
+#define HBSC_CTRL0			0x28
+#define HBSC_CTRL_EN			BIT(2)
+
+#endif /* __ZX_PLANE_REGS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_vou.c linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_vou.c
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_vou.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_vou.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,661 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/of_address.h>
+#include <video/videomode.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drmP.h>
+
+#include "zx_drm_drv.h"
+#include "zx_plane.h"
+#include "zx_vou.h"
+#include "zx_vou_regs.h"
+
+#define GL_NUM	2
+#define VL_NUM	3
+
+enum vou_chn_type {
+	VOU_CHN_MAIN,
+	VOU_CHN_AUX,
+};
+
+struct zx_crtc_regs {
+	u32 fir_active;
+	u32 fir_htiming;
+	u32 fir_vtiming;
+	u32 timing_shift;
+	u32 timing_pi_shift;
+};
+
+static const struct zx_crtc_regs main_crtc_regs = {
+	.fir_active = FIR_MAIN_ACTIVE,
+	.fir_htiming = FIR_MAIN_H_TIMING,
+	.fir_vtiming = FIR_MAIN_V_TIMING,
+	.timing_shift = TIMING_MAIN_SHIFT,
+	.timing_pi_shift = TIMING_MAIN_PI_SHIFT,
+};
+
+static const struct zx_crtc_regs aux_crtc_regs = {
+	.fir_active = FIR_AUX_ACTIVE,
+	.fir_htiming = FIR_AUX_H_TIMING,
+	.fir_vtiming = FIR_AUX_V_TIMING,
+	.timing_shift = TIMING_AUX_SHIFT,
+	.timing_pi_shift = TIMING_AUX_PI_SHIFT,
+};
+
+struct zx_crtc_bits {
+	u32 polarity_mask;
+	u32 polarity_shift;
+	u32 int_frame_mask;
+	u32 tc_enable;
+	u32 gl_enable;
+};
+
+static const struct zx_crtc_bits main_crtc_bits = {
+	.polarity_mask = MAIN_POL_MASK,
+	.polarity_shift = MAIN_POL_SHIFT,
+	.int_frame_mask = TIMING_INT_MAIN_FRAME,
+	.tc_enable = MAIN_TC_EN,
+	.gl_enable = OSD_CTRL0_GL0_EN,
+};
+
+static const struct zx_crtc_bits aux_crtc_bits = {
+	.polarity_mask = AUX_POL_MASK,
+	.polarity_shift = AUX_POL_SHIFT,
+	.int_frame_mask = TIMING_INT_AUX_FRAME,
+	.tc_enable = AUX_TC_EN,
+	.gl_enable = OSD_CTRL0_GL1_EN,
+};
+
+struct zx_crtc {
+	struct drm_crtc crtc;
+	struct drm_plane *primary;
+	struct zx_vou_hw *vou;
+	void __iomem *chnreg;
+	const struct zx_crtc_regs *regs;
+	const struct zx_crtc_bits *bits;
+	enum vou_chn_type chn_type;
+	struct clk *pixclk;
+};
+
+#define to_zx_crtc(x) container_of(x, struct zx_crtc, crtc)
+
+struct zx_vou_hw {
+	struct device *dev;
+	void __iomem *osd;
+	void __iomem *timing;
+	void __iomem *vouctl;
+	void __iomem *otfppu;
+	void __iomem *dtrc;
+	struct clk *axi_clk;
+	struct clk *ppu_clk;
+	struct clk *main_clk;
+	struct clk *aux_clk;
+	struct zx_crtc *main_crtc;
+	struct zx_crtc *aux_crtc;
+};
+
+static inline struct zx_vou_hw *crtc_to_vou(struct drm_crtc *crtc)
+{
+	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+
+	return zcrtc->vou;
+}
+
+void vou_inf_enable(const struct vou_inf *inf, struct drm_crtc *crtc)
+{
+	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+	struct zx_vou_hw *vou = zcrtc->vou;
+	bool is_main = zcrtc->chn_type == VOU_CHN_MAIN;
+	u32 data_sel_shift = inf->id << 1;
+
+	/* Select data format */
+	zx_writel_mask(vou->vouctl + VOU_INF_DATA_SEL, 0x3 << data_sel_shift,
+		       inf->data_sel << data_sel_shift);
+
+	/* Select channel */
+	zx_writel_mask(vou->vouctl + VOU_INF_CH_SEL, 0x1 << inf->id,
+		       zcrtc->chn_type << inf->id);
+
+	/* Select interface clocks */
+	zx_writel_mask(vou->vouctl + VOU_CLK_SEL, inf->clocks_sel_bits,
+		       is_main ? 0 : inf->clocks_sel_bits);
+
+	/* Enable interface clocks */
+	zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits,
+		       inf->clocks_en_bits);
+
+	/* Enable the device */
+	zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 1 << inf->id);
+}
+
+void vou_inf_disable(const struct vou_inf *inf, struct drm_crtc *crtc)
+{
+	struct zx_vou_hw *vou = crtc_to_vou(crtc);
+
+	/* Disable the device */
+	zx_writel_mask(vou->vouctl + VOU_INF_EN, 1 << inf->id, 0);
+
+	/* Disable interface clocks */
+	zx_writel_mask(vou->vouctl + VOU_CLK_EN, inf->clocks_en_bits, 0);
+}
+
+static inline void vou_chn_set_update(struct zx_crtc *zcrtc)
+{
+	zx_writel(zcrtc->chnreg + CHN_UPDATE, 1);
+}
+
+static void zx_crtc_enable(struct drm_crtc *crtc)
+{
+	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
+	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+	struct zx_vou_hw *vou = zcrtc->vou;
+	const struct zx_crtc_regs *regs = zcrtc->regs;
+	const struct zx_crtc_bits *bits = zcrtc->bits;
+	struct videomode vm;
+	u32 pol = 0;
+	u32 val;
+	int ret;
+
+	drm_display_mode_to_videomode(mode, &vm);
+
+	/* Set up timing parameters */
+	val = V_ACTIVE(vm.vactive - 1);
+	val |= H_ACTIVE(vm.hactive - 1);
+	zx_writel(vou->timing + regs->fir_active, val);
+
+	val = SYNC_WIDE(vm.hsync_len - 1);
+	val |= BACK_PORCH(vm.hback_porch - 1);
+	val |= FRONT_PORCH(vm.hfront_porch - 1);
+	zx_writel(vou->timing + regs->fir_htiming, val);
+
+	val = SYNC_WIDE(vm.vsync_len - 1);
+	val |= BACK_PORCH(vm.vback_porch - 1);
+	val |= FRONT_PORCH(vm.vfront_porch - 1);
+	zx_writel(vou->timing + regs->fir_vtiming, val);
+
+	/* Set up polarities */
+	if (vm.flags & DISPLAY_FLAGS_VSYNC_LOW)
+		pol |= 1 << POL_VSYNC_SHIFT;
+	if (vm.flags & DISPLAY_FLAGS_HSYNC_LOW)
+		pol |= 1 << POL_HSYNC_SHIFT;
+
+	zx_writel_mask(vou->timing + TIMING_CTRL, bits->polarity_mask,
+		       pol << bits->polarity_shift);
+
+	/* Setup SHIFT register by following what ZTE BSP does */
+	zx_writel(vou->timing + regs->timing_shift, H_SHIFT_VAL);
+	zx_writel(vou->timing + regs->timing_pi_shift, H_PI_SHIFT_VAL);
+
+	/* Enable TIMING_CTRL */
+	zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable,
+		       bits->tc_enable);
+
+	/* Configure channel screen size */
+	zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_W_MASK,
+		       vm.hactive << CHN_SCREEN_W_SHIFT);
+	zx_writel_mask(zcrtc->chnreg + CHN_CTRL1, CHN_SCREEN_H_MASK,
+		       vm.vactive << CHN_SCREEN_H_SHIFT);
+
+	/* Update channel */
+	vou_chn_set_update(zcrtc);
+
+	/* Enable channel */
+	zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, CHN_ENABLE);
+
+	/* Enable Graphic Layer */
+	zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable,
+		       bits->gl_enable);
+
+	drm_crtc_vblank_on(crtc);
+
+	ret = clk_set_rate(zcrtc->pixclk, mode->clock * 1000);
+	if (ret) {
+		DRM_DEV_ERROR(vou->dev, "failed to set pixclk rate: %d\n", ret);
+		return;
+	}
+
+	ret = clk_prepare_enable(zcrtc->pixclk);
+	if (ret)
+		DRM_DEV_ERROR(vou->dev, "failed to enable pixclk: %d\n", ret);
+}
+
+static void zx_crtc_disable(struct drm_crtc *crtc)
+{
+	struct zx_crtc *zcrtc = to_zx_crtc(crtc);
+	const struct zx_crtc_bits *bits = zcrtc->bits;
+	struct zx_vou_hw *vou = zcrtc->vou;
+
+	clk_disable_unprepare(zcrtc->pixclk);
+
+	drm_crtc_vblank_off(crtc);
+
+	/* Disable Graphic Layer */
+	zx_writel_mask(vou->osd + OSD_CTRL0, bits->gl_enable, 0);
+
+	/* Disable channel */
+	zx_writel_mask(zcrtc->chnreg + CHN_CTRL0, CHN_ENABLE, 0);
+
+	/* Disable TIMING_CTRL */
+	zx_writel_mask(vou->timing + TIMING_TC_ENABLE, bits->tc_enable, 0);
+}
+
+static void zx_crtc_atomic_flush(struct drm_crtc *crtc,
+				  struct drm_crtc_state *old_state)
+{
+	struct drm_pending_vblank_event *event = crtc->state->event;
+
+	if (!event)
+		return;
+
+	crtc->state->event = NULL;
+
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (drm_crtc_vblank_get(crtc) == 0)
+		drm_crtc_arm_vblank_event(crtc, event);
+	else
+		drm_crtc_send_vblank_event(crtc, event);
+	spin_unlock_irq(&crtc->dev->event_lock);
+}
+
+static const struct drm_crtc_helper_funcs zx_crtc_helper_funcs = {
+	.enable = zx_crtc_enable,
+	.disable = zx_crtc_disable,
+	.atomic_flush = zx_crtc_atomic_flush,
+};
+
+static const struct drm_crtc_funcs zx_crtc_funcs = {
+	.destroy = drm_crtc_cleanup,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
+static int zx_crtc_init(struct drm_device *drm, struct zx_vou_hw *vou,
+			enum vou_chn_type chn_type)
+{
+	struct device *dev = vou->dev;
+	struct zx_layer_data data;
+	struct zx_crtc *zcrtc;
+	int ret;
+
+	zcrtc = devm_kzalloc(dev, sizeof(*zcrtc), GFP_KERNEL);
+	if (!zcrtc)
+		return -ENOMEM;
+
+	zcrtc->vou = vou;
+	zcrtc->chn_type = chn_type;
+
+	if (chn_type == VOU_CHN_MAIN) {
+		data.layer = vou->osd + MAIN_GL_OFFSET;
+		data.csc = vou->osd + MAIN_CSC_OFFSET;
+		data.hbsc = vou->osd + MAIN_HBSC_OFFSET;
+		data.rsz = vou->otfppu + MAIN_RSZ_OFFSET;
+		zcrtc->chnreg = vou->osd + OSD_MAIN_CHN;
+		zcrtc->regs = &main_crtc_regs;
+		zcrtc->bits = &main_crtc_bits;
+	} else {
+		data.layer = vou->osd + AUX_GL_OFFSET;
+		data.csc = vou->osd + AUX_CSC_OFFSET;
+		data.hbsc = vou->osd + AUX_HBSC_OFFSET;
+		data.rsz = vou->otfppu + AUX_RSZ_OFFSET;
+		zcrtc->chnreg = vou->osd + OSD_AUX_CHN;
+		zcrtc->regs = &aux_crtc_regs;
+		zcrtc->bits = &aux_crtc_bits;
+	}
+
+	zcrtc->pixclk = devm_clk_get(dev, (chn_type == VOU_CHN_MAIN) ?
+					  "main_wclk" : "aux_wclk");
+	if (IS_ERR(zcrtc->pixclk)) {
+		ret = PTR_ERR(zcrtc->pixclk);
+		DRM_DEV_ERROR(dev, "failed to get pix clk: %d\n", ret);
+		return ret;
+	}
+
+	zcrtc->primary = zx_plane_init(drm, dev, &data, DRM_PLANE_TYPE_PRIMARY);
+	if (IS_ERR(zcrtc->primary)) {
+		ret = PTR_ERR(zcrtc->primary);
+		DRM_DEV_ERROR(dev, "failed to init primary plane: %d\n", ret);
+		return ret;
+	}
+
+	ret = drm_crtc_init_with_planes(drm, &zcrtc->crtc, zcrtc->primary, NULL,
+					&zx_crtc_funcs, NULL);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to init drm crtc: %d\n", ret);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&zcrtc->crtc, &zx_crtc_helper_funcs);
+
+	if (chn_type == VOU_CHN_MAIN)
+		vou->main_crtc = zcrtc;
+	else
+		vou->aux_crtc = zcrtc;
+
+	return 0;
+}
+
+static inline struct drm_crtc *zx_find_crtc(struct drm_device *drm, int pipe)
+{
+	struct drm_crtc *crtc;
+
+	list_for_each_entry(crtc, &drm->mode_config.crtc_list, head)
+		if (crtc->index == pipe)
+			return crtc;
+
+	return NULL;
+}
+
+int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+	struct drm_crtc *crtc;
+	struct zx_crtc *zcrtc;
+	struct zx_vou_hw *vou;
+	u32 int_frame_mask;
+
+	crtc = zx_find_crtc(drm, pipe);
+	if (!crtc)
+		return 0;
+
+	vou = crtc_to_vou(crtc);
+	zcrtc = to_zx_crtc(crtc);
+	int_frame_mask = zcrtc->bits->int_frame_mask;
+
+	zx_writel_mask(vou->timing + TIMING_INT_CTRL, int_frame_mask,
+		       int_frame_mask);
+
+	return 0;
+}
+
+void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe)
+{
+	struct drm_crtc *crtc;
+	struct zx_crtc *zcrtc;
+	struct zx_vou_hw *vou;
+
+	crtc = zx_find_crtc(drm, pipe);
+	if (!crtc)
+		return;
+
+	vou = crtc_to_vou(crtc);
+	zcrtc = to_zx_crtc(crtc);
+
+	zx_writel_mask(vou->timing + TIMING_INT_CTRL,
+		       zcrtc->bits->int_frame_mask, 0);
+}
+
+static irqreturn_t vou_irq_handler(int irq, void *dev_id)
+{
+	struct zx_vou_hw *vou = dev_id;
+	u32 state;
+
+	/* Handle TIMING_CTRL frame interrupts */
+	state = zx_readl(vou->timing + TIMING_INT_STATE);
+	zx_writel(vou->timing + TIMING_INT_STATE, state);
+
+	if (state & TIMING_INT_MAIN_FRAME)
+		drm_crtc_handle_vblank(&vou->main_crtc->crtc);
+
+	if (state & TIMING_INT_AUX_FRAME)
+		drm_crtc_handle_vblank(&vou->aux_crtc->crtc);
+
+	/* Handle OSD interrupts */
+	state = zx_readl(vou->osd + OSD_INT_STA);
+	zx_writel(vou->osd + OSD_INT_CLRSTA, state);
+
+	if (state & OSD_INT_MAIN_UPT) {
+		vou_chn_set_update(vou->main_crtc);
+		zx_plane_set_update(vou->main_crtc->primary);
+	}
+
+	if (state & OSD_INT_AUX_UPT) {
+		vou_chn_set_update(vou->aux_crtc);
+		zx_plane_set_update(vou->aux_crtc->primary);
+	}
+
+	if (state & OSD_INT_ERROR)
+		DRM_DEV_ERROR(vou->dev, "OSD ERROR: 0x%08x!\n", state);
+
+	return IRQ_HANDLED;
+}
+
+static void vou_dtrc_init(struct zx_vou_hw *vou)
+{
+	/* Clear bit for bypass by ID */
+	zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL,
+		       TILE2RASTESCAN_BYPASS_MODE, 0);
+
+	/* Select ARIDR mode */
+	zx_writel_mask(vou->dtrc + DTRC_DETILE_CTRL, DETILE_ARIDR_MODE_MASK,
+		       DETILE_ARID_IN_ARIDR);
+
+	/* Bypass decompression for both frames */
+	zx_writel_mask(vou->dtrc + DTRC_F0_CTRL, DTRC_DECOMPRESS_BYPASS,
+		       DTRC_DECOMPRESS_BYPASS);
+	zx_writel_mask(vou->dtrc + DTRC_F1_CTRL, DTRC_DECOMPRESS_BYPASS,
+		       DTRC_DECOMPRESS_BYPASS);
+
+	/* Set up ARID register */
+	zx_writel(vou->dtrc + DTRC_ARID, DTRC_ARID3(0xf) | DTRC_ARID2(0xe) |
+		  DTRC_ARID1(0xf) | DTRC_ARID0(0xe));
+}
+
+static void vou_hw_init(struct zx_vou_hw *vou)
+{
+	/* Set GL0 to main channel and GL1 to aux channel */
+	zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL0_SEL, 0);
+	zx_writel_mask(vou->osd + OSD_CTRL0, OSD_CTRL0_GL1_SEL,
+		       OSD_CTRL0_GL1_SEL);
+
+	/* Release reset for all VOU modules */
+	zx_writel(vou->vouctl + VOU_SOFT_RST, ~0);
+
+	/* Select main clock for GL0 and aux clock for GL1 module */
+	zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL0_SEL, 0);
+	zx_writel_mask(vou->vouctl + VOU_CLK_SEL, VOU_CLK_GL1_SEL,
+		       VOU_CLK_GL1_SEL);
+
+	/* Enable clock auto-gating for all VOU modules */
+	zx_writel(vou->vouctl + VOU_CLK_REQEN, ~0);
+
+	/* Enable all VOU module clocks */
+	zx_writel(vou->vouctl + VOU_CLK_EN, ~0);
+
+	/* Clear both OSD and TIMING_CTRL interrupt state */
+	zx_writel(vou->osd + OSD_INT_CLRSTA, ~0);
+	zx_writel(vou->timing + TIMING_INT_STATE, ~0);
+
+	/* Enable OSD and TIMING_CTRL interrrupts */
+	zx_writel(vou->osd + OSD_INT_MSK, OSD_INT_ENABLE);
+	zx_writel(vou->timing + TIMING_INT_CTRL, TIMING_INT_ENABLE);
+
+	/* Select GPC as input to gl/vl scaler as a sane default setting */
+	zx_writel(vou->otfppu + OTFPPU_RSZ_DATA_SOURCE, 0x2a);
+
+	/*
+	 * Needs to reset channel and layer logic per frame when frame starts
+	 * to get VOU work properly.
+	 */
+	zx_writel_mask(vou->osd + OSD_RST_CLR, RST_PER_FRAME, RST_PER_FRAME);
+
+	vou_dtrc_init(vou);
+}
+
+static int zx_crtc_bind(struct device *dev, struct device *master, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct drm_device *drm = data;
+	struct zx_vou_hw *vou;
+	struct resource *res;
+	int irq;
+	int ret;
+
+	vou = devm_kzalloc(dev, sizeof(*vou), GFP_KERNEL);
+	if (!vou)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "osd");
+	vou->osd = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vou->osd)) {
+		ret = PTR_ERR(vou->osd);
+		DRM_DEV_ERROR(dev, "failed to remap osd region: %d\n", ret);
+		return ret;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "timing_ctrl");
+	vou->timing = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vou->timing)) {
+		ret = PTR_ERR(vou->timing);
+		DRM_DEV_ERROR(dev, "failed to remap timing_ctrl region: %d\n",
+			      ret);
+		return ret;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dtrc");
+	vou->dtrc = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vou->dtrc)) {
+		ret = PTR_ERR(vou->dtrc);
+		DRM_DEV_ERROR(dev, "failed to remap dtrc region: %d\n", ret);
+		return ret;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vou_ctrl");
+	vou->vouctl = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vou->vouctl)) {
+		ret = PTR_ERR(vou->vouctl);
+		DRM_DEV_ERROR(dev, "failed to remap vou_ctrl region: %d\n",
+			      ret);
+		return ret;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otfppu");
+	vou->otfppu = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vou->otfppu)) {
+		ret = PTR_ERR(vou->otfppu);
+		DRM_DEV_ERROR(dev, "failed to remap otfppu region: %d\n", ret);
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	vou->axi_clk = devm_clk_get(dev, "aclk");
+	if (IS_ERR(vou->axi_clk)) {
+		ret = PTR_ERR(vou->axi_clk);
+		DRM_DEV_ERROR(dev, "failed to get axi_clk: %d\n", ret);
+		return ret;
+	}
+
+	vou->ppu_clk = devm_clk_get(dev, "ppu_wclk");
+	if (IS_ERR(vou->ppu_clk)) {
+		ret = PTR_ERR(vou->ppu_clk);
+		DRM_DEV_ERROR(dev, "failed to get ppu_clk: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(vou->axi_clk);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to enable axi_clk: %d\n", ret);
+		return ret;
+	}
+
+	clk_prepare_enable(vou->ppu_clk);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to enable ppu_clk: %d\n", ret);
+		goto disable_axi_clk;
+	}
+
+	vou->dev = dev;
+	dev_set_drvdata(dev, vou);
+
+	vou_hw_init(vou);
+
+	ret = devm_request_irq(dev, irq, vou_irq_handler, 0, "zx_vou", vou);
+	if (ret < 0) {
+		DRM_DEV_ERROR(dev, "failed to request vou irq: %d\n", ret);
+		goto disable_ppu_clk;
+	}
+
+	ret = zx_crtc_init(drm, vou, VOU_CHN_MAIN);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to init main channel crtc: %d\n",
+			      ret);
+		goto disable_ppu_clk;
+	}
+
+	ret = zx_crtc_init(drm, vou, VOU_CHN_AUX);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to init aux channel crtc: %d\n",
+			      ret);
+		goto disable_ppu_clk;
+	}
+
+	return 0;
+
+disable_ppu_clk:
+	clk_disable_unprepare(vou->ppu_clk);
+disable_axi_clk:
+	clk_disable_unprepare(vou->axi_clk);
+	return ret;
+}
+
+static void zx_crtc_unbind(struct device *dev, struct device *master,
+			   void *data)
+{
+	struct zx_vou_hw *vou = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(vou->axi_clk);
+	clk_disable_unprepare(vou->ppu_clk);
+}
+
+static const struct component_ops zx_crtc_component_ops = {
+	.bind = zx_crtc_bind,
+	.unbind = zx_crtc_unbind,
+};
+
+static int zx_crtc_probe(struct platform_device *pdev)
+{
+	return component_add(&pdev->dev, &zx_crtc_component_ops);
+}
+
+static int zx_crtc_remove(struct platform_device *pdev)
+{
+	component_del(&pdev->dev, &zx_crtc_component_ops);
+	return 0;
+}
+
+static const struct of_device_id zx_crtc_of_match[] = {
+	{ .compatible = "zte,zx296718-dpc", },
+	{ /* end */ },
+};
+MODULE_DEVICE_TABLE(of, zx_crtc_of_match);
+
+struct platform_driver zx_crtc_driver = {
+	.probe = zx_crtc_probe,
+	.remove = zx_crtc_remove,
+	.driver	= {
+		.name = "zx-crtc",
+		.of_match_table	= zx_crtc_of_match,
+	},
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_vou.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_vou.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_vou.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_vou.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ZX_VOU_H__
+#define __ZX_VOU_H__
+
+#define VOU_CRTC_MASK		0x3
+
+/* VOU output interfaces */
+enum vou_inf_id {
+	VOU_HDMI	= 0,
+	VOU_RGB_LCD	= 1,
+	VOU_TV_ENC	= 2,
+	VOU_MIPI_DSI	= 3,
+	VOU_LVDS	= 4,
+	VOU_VGA		= 5,
+};
+
+enum vou_inf_data_sel {
+	VOU_YUV444	= 0,
+	VOU_RGB_101010	= 1,
+	VOU_RGB_888	= 2,
+	VOU_RGB_666	= 3,
+};
+
+struct vou_inf {
+	enum vou_inf_id id;
+	enum vou_inf_data_sel data_sel;
+	u32 clocks_en_bits;
+	u32 clocks_sel_bits;
+};
+
+void vou_inf_enable(const struct vou_inf *inf, struct drm_crtc *crtc);
+void vou_inf_disable(const struct vou_inf *inf, struct drm_crtc *crtc);
+
+int zx_vou_enable_vblank(struct drm_device *drm, unsigned int pipe);
+void zx_vou_disable_vblank(struct drm_device *drm, unsigned int pipe);
+
+#endif /* __ZX_VOU_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_vou_regs.h linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_vou_regs.h
--- linux-libre-4.9-gnu/drivers/gpu/drm/zte/zx_vou_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/drm/zte/zx_vou_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2016 Linaro Ltd.
+ * Copyright 2016 ZTE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __ZX_VOU_REGS_H__
+#define __ZX_VOU_REGS_H__
+
+/* Sub-module offset */
+#define MAIN_GL_OFFSET			0x130
+#define MAIN_CSC_OFFSET			0x580
+#define MAIN_HBSC_OFFSET		0x820
+#define MAIN_RSZ_OFFSET			0x600 /* OTFPPU sub-module */
+
+#define AUX_GL_OFFSET			0x200
+#define AUX_CSC_OFFSET			0x5d0
+#define AUX_HBSC_OFFSET			0x860
+#define AUX_RSZ_OFFSET			0x800
+
+/* OSD (GPC_GLOBAL) registers */
+#define OSD_INT_STA			0x04
+#define OSD_INT_CLRSTA			0x08
+#define OSD_INT_MSK			0x0c
+#define OSD_INT_AUX_UPT			BIT(14)
+#define OSD_INT_MAIN_UPT		BIT(13)
+#define OSD_INT_GL1_LBW			BIT(10)
+#define OSD_INT_GL0_LBW			BIT(9)
+#define OSD_INT_VL2_LBW			BIT(8)
+#define OSD_INT_VL1_LBW			BIT(7)
+#define OSD_INT_VL0_LBW			BIT(6)
+#define OSD_INT_BUS_ERR			BIT(3)
+#define OSD_INT_CFG_ERR			BIT(2)
+#define OSD_INT_ERROR (\
+	OSD_INT_GL1_LBW | OSD_INT_GL0_LBW | \
+	OSD_INT_VL2_LBW | OSD_INT_VL1_LBW | OSD_INT_VL0_LBW | \
+	OSD_INT_BUS_ERR | OSD_INT_CFG_ERR \
+)
+#define OSD_INT_ENABLE (OSD_INT_ERROR | OSD_INT_AUX_UPT | OSD_INT_MAIN_UPT)
+#define OSD_CTRL0			0x10
+#define OSD_CTRL0_GL0_EN		BIT(7)
+#define OSD_CTRL0_GL0_SEL		BIT(6)
+#define OSD_CTRL0_GL1_EN		BIT(5)
+#define OSD_CTRL0_GL1_SEL		BIT(4)
+#define OSD_RST_CLR			0x1c
+#define RST_PER_FRAME			BIT(19)
+
+/* Main/Aux channel registers */
+#define OSD_MAIN_CHN			0x470
+#define OSD_AUX_CHN			0x4d0
+#define CHN_CTRL0			0x00
+#define CHN_ENABLE			BIT(0)
+#define CHN_CTRL1			0x04
+#define CHN_SCREEN_W_SHIFT		18
+#define CHN_SCREEN_W_MASK		(0x1fff << CHN_SCREEN_W_SHIFT)
+#define CHN_SCREEN_H_SHIFT		5
+#define CHN_SCREEN_H_MASK		(0x1fff << CHN_SCREEN_H_SHIFT)
+#define CHN_UPDATE			0x08
+
+/* TIMING_CTRL registers */
+#define TIMING_TC_ENABLE		0x04
+#define AUX_TC_EN			BIT(1)
+#define MAIN_TC_EN			BIT(0)
+#define FIR_MAIN_ACTIVE			0x08
+#define FIR_AUX_ACTIVE			0x0c
+#define V_ACTIVE_SHIFT			16
+#define V_ACTIVE_MASK			(0xffff << V_ACTIVE_SHIFT)
+#define H_ACTIVE_SHIFT			0
+#define H_ACTIVE_MASK			(0xffff << H_ACTIVE_SHIFT)
+#define FIR_MAIN_H_TIMING		0x10
+#define FIR_MAIN_V_TIMING		0x14
+#define FIR_AUX_H_TIMING		0x18
+#define FIR_AUX_V_TIMING		0x1c
+#define SYNC_WIDE_SHIFT			22
+#define SYNC_WIDE_MASK			(0x3ff << SYNC_WIDE_SHIFT)
+#define BACK_PORCH_SHIFT		11
+#define BACK_PORCH_MASK			(0x7ff << BACK_PORCH_SHIFT)
+#define FRONT_PORCH_SHIFT		0
+#define FRONT_PORCH_MASK		(0x7ff << FRONT_PORCH_SHIFT)
+#define TIMING_CTRL			0x20
+#define AUX_POL_SHIFT			3
+#define AUX_POL_MASK			(0x7 << AUX_POL_SHIFT)
+#define MAIN_POL_SHIFT			0
+#define MAIN_POL_MASK			(0x7 << MAIN_POL_SHIFT)
+#define POL_DE_SHIFT			2
+#define POL_VSYNC_SHIFT			1
+#define POL_HSYNC_SHIFT			0
+#define TIMING_INT_CTRL			0x24
+#define TIMING_INT_STATE		0x28
+#define TIMING_INT_AUX_FRAME		BIT(3)
+#define TIMING_INT_MAIN_FRAME		BIT(1)
+#define TIMING_INT_AUX_FRAME_SEL_VSW	(0x2 << 10)
+#define TIMING_INT_MAIN_FRAME_SEL_VSW	(0x2 << 6)
+#define TIMING_INT_ENABLE (\
+	TIMING_INT_MAIN_FRAME_SEL_VSW | TIMING_INT_AUX_FRAME_SEL_VSW | \
+	TIMING_INT_MAIN_FRAME | TIMING_INT_AUX_FRAME \
+)
+#define TIMING_MAIN_SHIFT		0x2c
+#define TIMING_AUX_SHIFT		0x30
+#define H_SHIFT_VAL			0x0048
+#define TIMING_MAIN_PI_SHIFT		0x68
+#define TIMING_AUX_PI_SHIFT		0x6c
+#define H_PI_SHIFT_VAL			0x000f
+
+#define V_ACTIVE(x)	(((x) << V_ACTIVE_SHIFT) & V_ACTIVE_MASK)
+#define H_ACTIVE(x)	(((x) << H_ACTIVE_SHIFT) & H_ACTIVE_MASK)
+
+#define SYNC_WIDE(x)	(((x) << SYNC_WIDE_SHIFT) & SYNC_WIDE_MASK)
+#define BACK_PORCH(x)	(((x) << BACK_PORCH_SHIFT) & BACK_PORCH_MASK)
+#define FRONT_PORCH(x)	(((x) << FRONT_PORCH_SHIFT) & FRONT_PORCH_MASK)
+
+/* DTRC registers */
+#define DTRC_F0_CTRL			0x2c
+#define DTRC_F1_CTRL			0x5c
+#define DTRC_DECOMPRESS_BYPASS		BIT(17)
+#define DTRC_DETILE_CTRL		0x68
+#define TILE2RASTESCAN_BYPASS_MODE	BIT(30)
+#define DETILE_ARIDR_MODE_MASK		(0x3 << 0)
+#define DETILE_ARID_ALL			0
+#define DETILE_ARID_IN_ARIDR		1
+#define DETILE_ARID_BYP_BUT_ARIDR	2
+#define DETILE_ARID_IN_ARIDR2		3
+#define DTRC_ARID			0x6c
+#define DTRC_ARID3_SHIFT		24
+#define DTRC_ARID3_MASK			(0xff << DTRC_ARID3_SHIFT)
+#define DTRC_ARID2_SHIFT		16
+#define DTRC_ARID2_MASK			(0xff << DTRC_ARID2_SHIFT)
+#define DTRC_ARID1_SHIFT		8
+#define DTRC_ARID1_MASK			(0xff << DTRC_ARID1_SHIFT)
+#define DTRC_ARID0_SHIFT		0
+#define DTRC_ARID0_MASK			(0xff << DTRC_ARID0_SHIFT)
+#define DTRC_DEC2DDR_ARID		0x70
+
+#define DTRC_ARID3(x)	(((x) << DTRC_ARID3_SHIFT) & DTRC_ARID3_MASK)
+#define DTRC_ARID2(x)	(((x) << DTRC_ARID2_SHIFT) & DTRC_ARID2_MASK)
+#define DTRC_ARID1(x)	(((x) << DTRC_ARID1_SHIFT) & DTRC_ARID1_MASK)
+#define DTRC_ARID0(x)	(((x) << DTRC_ARID0_SHIFT) & DTRC_ARID0_MASK)
+
+/* VOU_CTRL registers */
+#define VOU_INF_EN			0x00
+#define VOU_INF_CH_SEL			0x04
+#define VOU_INF_DATA_SEL		0x08
+#define VOU_SOFT_RST			0x14
+#define VOU_CLK_SEL			0x18
+#define VOU_CLK_GL1_SEL			BIT(5)
+#define VOU_CLK_GL0_SEL			BIT(4)
+#define VOU_CLK_REQEN			0x20
+#define VOU_CLK_EN			0x24
+
+/* OTFPPU_CTRL registers */
+#define OTFPPU_RSZ_DATA_SOURCE		0x04
+
+#endif /* __ZX_VOU_REGS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/host1x/dev.h linux-libre-4.10-rc8-gnu/drivers/gpu/host1x/dev.h
--- linux-libre-4.9-gnu/drivers/gpu/host1x/dev.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/host1x/dev.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, NVIDIA Corporation.
+ * Copyright (c) 2012-2015, NVIDIA 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,
@@ -120,6 +120,7 @@ struct host1x {
 
 	struct host1x_syncpt *nop_sp;
 
+	struct mutex syncpt_mutex;
 	struct mutex chlist_mutex;
 	struct host1x_channel chlist;
 	unsigned long allocated_channels;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/host1x/job.c linux-libre-4.10-rc8-gnu/drivers/gpu/host1x/job.c
--- linux-libre-4.9-gnu/drivers/gpu/host1x/job.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/host1x/job.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Tegra host1x Job
  *
- * Copyright (c) 2010-2013, NVIDIA Corporation.
+ * Copyright (c) 2010-2015, NVIDIA 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,
@@ -539,9 +539,12 @@ int host1x_job_pin(struct host1x_job *jo
 
 		g->base = job->gather_addr_phys[i];
 
-		for (j = i + 1; j < job->num_gathers; j++)
-			if (job->gathers[j].bo == g->bo)
+		for (j = i + 1; j < job->num_gathers; j++) {
+			if (job->gathers[j].bo == g->bo) {
 				job->gathers[j].handled = true;
+				job->gathers[j].base = g->base;
+			}
+		}
 
 		err = do_relocs(job, g->bo);
 		if (err)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/host1x/syncpt.c linux-libre-4.10-rc8-gnu/drivers/gpu/host1x/syncpt.c
--- linux-libre-4.9-gnu/drivers/gpu/host1x/syncpt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/host1x/syncpt.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * Tegra host1x Syncpoints
  *
- * Copyright (c) 2010-2013, NVIDIA Corporation.
+ * Copyright (c) 2010-2015, NVIDIA 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,
@@ -61,22 +61,24 @@ static struct host1x_syncpt *host1x_sync
 	struct host1x_syncpt *sp = host->syncpt;
 	char *name;
 
+	mutex_lock(&host->syncpt_mutex);
+
 	for (i = 0; i < host->info->nb_pts && sp->name; i++, sp++)
 		;
 
 	if (i >= host->info->nb_pts)
-		return NULL;
+		goto unlock;
 
 	if (flags & HOST1X_SYNCPT_HAS_BASE) {
 		sp->base = host1x_syncpt_base_request(host);
 		if (!sp->base)
-			return NULL;
+			goto unlock;
 	}
 
 	name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id,
 			dev ? dev_name(dev) : NULL);
 	if (!name)
-		return NULL;
+		goto free_base;
 
 	sp->dev = dev;
 	sp->name = name;
@@ -86,7 +88,15 @@ static struct host1x_syncpt *host1x_sync
 	else
 		sp->client_managed = false;
 
+	mutex_unlock(&host->syncpt_mutex);
 	return sp;
+
+free_base:
+	host1x_syncpt_base_free(sp->base);
+	sp->base = NULL;
+unlock:
+	mutex_unlock(&host->syncpt_mutex);
+	return NULL;
 }
 
 u32 host1x_syncpt_id(struct host1x_syncpt *sp)
@@ -378,6 +388,7 @@ int host1x_syncpt_init(struct host1x *ho
 	for (i = 0; i < host->info->nb_bases; i++)
 		bases[i].id = i;
 
+	mutex_init(&host->syncpt_mutex);
 	host->syncpt = syncpt;
 	host->bases = bases;
 
@@ -405,12 +416,16 @@ void host1x_syncpt_free(struct host1x_sy
 	if (!sp)
 		return;
 
+	mutex_lock(&sp->host->syncpt_mutex);
+
 	host1x_syncpt_base_free(sp->base);
 	kfree(sp->name);
 	sp->base = NULL;
 	sp->dev = NULL;
 	sp->name = NULL;
 	sp->client_managed = false;
+
+	mutex_unlock(&sp->host->syncpt_mutex);
 }
 EXPORT_SYMBOL(host1x_syncpt_free);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-common.c linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-common.c
--- linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,6 +88,8 @@ enum ipu_color_space ipu_drm_fourcc_to_c
 	case DRM_FORMAT_YVU420:
 	case DRM_FORMAT_YUV422:
 	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
 	case DRM_FORMAT_NV12:
 	case DRM_FORMAT_NV21:
 	case DRM_FORMAT_NV16:
@@ -1284,8 +1286,11 @@ static int ipu_irq_init(struct ipu_soc *
 		return ret;
 	}
 
-	for (i = 0; i < IPU_NUM_IRQS; i += 32)
+	/* Mask and clear all interrupts */
+	for (i = 0; i < IPU_NUM_IRQS; i += 32) {
 		ipu_cm_write(ipu, 0, IPU_INT_CTRL(i / 32));
+		ipu_cm_write(ipu, ~unused[i / 32], IPU_INT_STAT(i / 32));
+	}
 
 	for (i = 0; i < IPU_NUM_IRQS; i += 32) {
 		gc = irq_get_domain_generic_chip(ipu->domain, i);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-cpmem.c linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-cpmem.c
--- linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-cpmem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-cpmem.c	2017-02-12 16:03:20.000000000 -0500
@@ -417,42 +417,6 @@ void ipu_cpmem_set_yuv_planar_full(struc
 }
 EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar_full);
 
-void ipu_cpmem_set_yuv_planar(struct ipuv3_channel *ch,
-			      u32 pixel_format, int stride, int height)
-{
-	int fourcc, u_offset, v_offset;
-	int uv_stride = 0;
-
-	fourcc = v4l2_pix_fmt_to_drm_fourcc(pixel_format);
-	switch (fourcc) {
-	case DRM_FORMAT_YUV420:
-		uv_stride = stride / 2;
-		u_offset = stride * height;
-		v_offset = u_offset + (uv_stride * height / 2);
-		break;
-	case DRM_FORMAT_YVU420:
-		uv_stride = stride / 2;
-		v_offset = stride * height;
-		u_offset = v_offset + (uv_stride * height / 2);
-		break;
-	case DRM_FORMAT_YUV422:
-		uv_stride = stride / 2;
-		u_offset = stride * height;
-		v_offset = u_offset + (uv_stride * height);
-		break;
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV16:
-		uv_stride = stride;
-		u_offset = stride * height;
-		v_offset = 0;
-		break;
-	default:
-		return;
-	}
-	ipu_cpmem_set_yuv_planar_full(ch, uv_stride, u_offset, v_offset);
-}
-EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar);
-
 static const struct ipu_rgb def_xrgb_32 = {
 	.red	= { .offset = 16, .length = 8, },
 	.green	= { .offset =  8, .length = 8, },
@@ -590,6 +554,13 @@ int ipu_cpmem_set_fmt(struct ipuv3_chann
 		/* burst size */
 		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
 		break;
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		/* pix format */
+		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 0);
+		/* burst size */
+		ipu_ch_param_write_field(ch, IPU_FIELD_NPB, 31);
+		break;
 	case DRM_FORMAT_NV12:
 		/* pix format */
 		ipu_ch_param_write_field(ch, IPU_FIELD_PFS, 4);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-csi.c linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-csi.c
--- linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-csi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-csi.c	2017-02-12 16:03:20.000000000 -0500
@@ -529,6 +529,22 @@ void ipu_csi_set_window(struct ipu_csi *
 }
 EXPORT_SYMBOL_GPL(ipu_csi_set_window);
 
+void ipu_csi_set_downsize(struct ipu_csi *csi, bool horiz, bool vert)
+{
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&csi->lock, flags);
+
+	reg = ipu_csi_read(csi, CSI_OUT_FRM_CTRL);
+	reg &= ~(CSI_HORI_DOWNSIZE_EN | CSI_VERT_DOWNSIZE_EN);
+	reg |= (horiz ? CSI_HORI_DOWNSIZE_EN : 0) |
+	       (vert ? CSI_VERT_DOWNSIZE_EN : 0);
+	ipu_csi_write(csi, reg, CSI_OUT_FRM_CTRL);
+
+	spin_unlock_irqrestore(&csi->lock, flags);
+}
+
 void ipu_csi_set_test_generator(struct ipu_csi *csi, bool active,
 				u32 r_value, u32 g_value, u32 b_value,
 				u32 pix_clk)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-di.c linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-di.c
--- linux-libre-4.9-gnu/drivers/gpu/ipu-v3/ipu-di.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/ipu-di.c	2017-02-12 16:03:20.000000000 -0500
@@ -535,7 +535,7 @@ int ipu_di_adjust_videomode(struct ipu_d
 		return -EINVAL;
 	}
 
-	dev_warn(di->ipu->dev, "videomode adapted for IPU restrictions\n");
+	dev_dbg(di->ipu->dev, "videomode adapted for IPU restrictions\n");
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ipu_di_adjust_videomode);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/ipu-v3/Kconfig linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/Kconfig
--- linux-libre-4.9-gnu/drivers/gpu/ipu-v3/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/ipu-v3/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,6 @@
 config IMX_IPUV3_CORE
 	tristate "IPUv3 core support"
 	depends on SOC_IMX5 || SOC_IMX6Q || ARCH_MULTIPLATFORM
-	depends on RESET_CONTROLLER
 	select GENERIC_IRQ_CHIP
 	help
 	  Choose this if you have a i.MX5/6 system and want to use the Image
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/gpu/vga/vgaarb.c linux-libre-4.10-rc8-gnu/drivers/gpu/vga/vgaarb.c
--- linux-libre-4.9-gnu/drivers/gpu/vga/vgaarb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/gpu/vga/vgaarb.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,10 @@
 
 #define pr_fmt(fmt) "vgaarb: " fmt
 
+#define vgaarb_dbg(dev, fmt, arg...)	dev_dbg(dev, "vgaarb: " fmt, ##arg)
+#define vgaarb_info(dev, fmt, arg...)	dev_info(dev, "vgaarb: " fmt, ##arg)
+#define vgaarb_err(dev, fmt, arg...)	dev_err(dev, "vgaarb: " fmt, ##arg)
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -188,6 +192,7 @@ static void vga_check_first_use(void)
 static struct vga_device *__vga_tryget(struct vga_device *vgadev,
 				       unsigned int rsrc)
 {
+	struct device *dev = &vgadev->pdev->dev;
 	unsigned int wants, legacy_wants, match;
 	struct vga_device *conflict;
 	unsigned int pci_bits;
@@ -203,8 +208,8 @@ static struct vga_device *__vga_tryget(s
 	    (vgadev->decodes & VGA_RSRC_LEGACY_MEM))
 		rsrc |= VGA_RSRC_LEGACY_MEM;
 
-	pr_debug("%s: %d\n", __func__, rsrc);
-	pr_debug("%s: owns: %d\n", __func__, vgadev->owns);
+	vgaarb_dbg(dev, "%s: %d\n", __func__, rsrc);
+	vgaarb_dbg(dev, "%s: owns: %d\n", __func__, vgadev->owns);
 
 	/* Check what resources we need to acquire */
 	wants = rsrc & ~vgadev->owns;
@@ -336,9 +341,10 @@ lock_them:
 
 static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
 {
+	struct device *dev = &vgadev->pdev->dev;
 	unsigned int old_locks = vgadev->locks;
 
-	pr_debug("%s\n", __func__);
+	vgaarb_dbg(dev, "%s\n", __func__);
 
 	/* Update our counters, and account for equivalent legacy resources
 	 * if we decode them
@@ -611,7 +617,7 @@ static bool vga_arbiter_add_pci_device(s
 	/* Allocate structure */
 	vgadev = kzalloc(sizeof(struct vga_device), GFP_KERNEL);
 	if (vgadev == NULL) {
-		pr_err("failed to allocate pci device\n");
+		vgaarb_err(&pdev->dev, "failed to allocate VGA arbiter data\n");
 		/*
 		 * What to do on allocation failure ? For now, let's just do
 		 * nothing, I'm not sure there is anything saner to be done.
@@ -663,7 +669,7 @@ static bool vga_arbiter_add_pci_device(s
 	 */
 	if (vga_default == NULL &&
 	    ((vgadev->owns & VGA_RSRC_LEGACY_MASK) == VGA_RSRC_LEGACY_MASK)) {
-		pr_info("setting as boot device: PCI:%s\n", pci_name(pdev));
+		vgaarb_info(&pdev->dev, "setting as boot VGA device\n");
 		vga_set_default_device(pdev);
 	}
 
@@ -672,8 +678,7 @@ static bool vga_arbiter_add_pci_device(s
 	/* Add to the list */
 	list_add(&vgadev->list, &vga_list);
 	vga_count++;
-	pr_info("device added: PCI:%s,decodes=%s,owns=%s,locks=%s\n",
-		pci_name(pdev),
+	vgaarb_info(&pdev->dev, "VGA device added: decodes=%s,owns=%s,locks=%s\n",
 		vga_iostate_to_str(vgadev->decodes),
 		vga_iostate_to_str(vgadev->owns),
 		vga_iostate_to_str(vgadev->locks));
@@ -725,6 +730,7 @@ bail:
 static inline void vga_update_device_decodes(struct vga_device *vgadev,
 					     int new_decodes)
 {
+	struct device *dev = &vgadev->pdev->dev;
 	int old_decodes, decodes_removed, decodes_unlocked;
 
 	old_decodes = vgadev->decodes;
@@ -732,8 +738,7 @@ static inline void vga_update_device_dec
 	decodes_unlocked = vgadev->locks & decodes_removed;
 	vgadev->decodes = new_decodes;
 
-	pr_info("device changed decodes: PCI:%s,olddecodes=%s,decodes=%s:owns=%s\n",
-		pci_name(vgadev->pdev),
+	vgaarb_info(dev, "changed VGA decodes: olddecodes=%s,decodes=%s:owns=%s\n",
 		vga_iostate_to_str(old_decodes),
 		vga_iostate_to_str(vgadev->decodes),
 		vga_iostate_to_str(vgadev->owns));
@@ -754,7 +759,7 @@ static inline void vga_update_device_dec
 	if (!(old_decodes & VGA_RSRC_LEGACY_MASK) &&
 	    new_decodes & VGA_RSRC_LEGACY_MASK)
 		vga_decode_count++;
-	pr_debug("decoding count now is: %d\n", vga_decode_count);
+	vgaarb_dbg(dev, "decoding count now is: %d\n", vga_decode_count);
 }
 
 static void __vga_set_legacy_decoding(struct pci_dev *pdev,
@@ -1022,21 +1027,16 @@ static ssize_t vga_arb_write(struct file
 
 	unsigned int io_state;
 
-	char *kbuf, *curr_pos;
+	char kbuf[64], *curr_pos;
 	size_t remaining = count;
 
 	int ret_val;
 	int i;
 
-
-	kbuf = kmalloc(count + 1, GFP_KERNEL);
-	if (!kbuf)
-		return -ENOMEM;
-
-	if (copy_from_user(kbuf, buf, count)) {
-		kfree(kbuf);
+	if (count >= sizeof(kbuf))
+		return -EINVAL;
+	if (copy_from_user(kbuf, buf, count))
 		return -EFAULT;
-	}
 	curr_pos = kbuf;
 	kbuf[count] = '\0';	/* Just to make sure... */
 
@@ -1189,24 +1189,25 @@ static ssize_t vga_arb_write(struct file
 				ret_val = -EPROTO;
 				goto done;
 			}
-			pr_debug("%s ==> %x:%x:%x.%x\n", curr_pos,
-				domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
 			pdev = pci_get_domain_bus_and_slot(domain, bus, devfn);
-			pr_debug("pdev %p\n", pdev);
 			if (!pdev) {
-				pr_err("invalid PCI address %x:%x:%x\n",
-					domain, bus, devfn);
+				pr_debug("invalid PCI address %04x:%02x:%02x.%x\n",
+					 domain, bus, PCI_SLOT(devfn),
+					 PCI_FUNC(devfn));
 				ret_val = -ENODEV;
 				goto done;
 			}
+
+			pr_debug("%s ==> %04x:%02x:%02x.%x pdev %p\n", curr_pos,
+				domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+				pdev);
 		}
 
 		vgadev = vgadev_find(pdev);
 		pr_debug("vgadev %p\n", vgadev);
 		if (vgadev == NULL) {
 			if (pdev) {
-				pr_err("this pci device is not a vga device\n");
+				vgaarb_dbg(&pdev->dev, "not a VGA device\n");
 				pci_dev_put(pdev);
 			}
 
@@ -1226,7 +1227,7 @@ static ssize_t vga_arb_write(struct file
 			}
 		}
 		if (i == MAX_USER_CARDS) {
-			pr_err("maximum user cards (%d) number reached!\n",
+			vgaarb_dbg(&pdev->dev, "maximum user cards (%d) number reached, ignoring this one!\n",
 				MAX_USER_CARDS);
 			pci_dev_put(pdev);
 			/* XXX: which value to return? */
@@ -1259,11 +1260,9 @@ static ssize_t vga_arb_write(struct file
 		goto done;
 	}
 	/* If we got here, the message written is not part of the protocol! */
-	kfree(kbuf);
 	return -EPROTO;
 
 done:
-	kfree(kbuf);
 	return ret_val;
 }
 
@@ -1317,8 +1316,8 @@ static int vga_arb_release(struct inode
 		uc = &priv->cards[i];
 		if (uc->pdev == NULL)
 			continue;
-		pr_debug("uc->io_cnt == %d, uc->mem_cnt == %d\n",
-			 uc->io_cnt, uc->mem_cnt);
+		vgaarb_dbg(&uc->pdev->dev, "uc->io_cnt == %d, uc->mem_cnt == %d\n",
+			uc->io_cnt, uc->mem_cnt);
 		while (uc->io_cnt--)
 			vga_put(uc->pdev, VGA_RSRC_LEGACY_IO);
 		while (uc->mem_cnt--)
@@ -1371,7 +1370,7 @@ static int pci_notify(struct notifier_bl
 	struct pci_dev *pdev = to_pci_dev(dev);
 	bool notify = false;
 
-	pr_debug("%s\n", __func__);
+	vgaarb_dbg(dev, "%s\n", __func__);
 
 	/* For now we're only intereted in devices added and removed. I didn't
 	 * test this thing here, so someone needs to double check for the
@@ -1423,9 +1422,8 @@ static int __init vga_arb_device_init(vo
 			       PCI_ANY_ID, pdev)) != NULL)
 		vga_arbiter_add_pci_device(pdev);
 
-	pr_info("loaded\n");
-
 	list_for_each_entry(vgadev, &vga_list, list) {
+		struct device *dev = &vgadev->pdev->dev;
 #if defined(CONFIG_X86) || defined(CONFIG_IA64)
 		/*
 		 * Override vga_arbiter_add_pci_device()'s I/O based detection
@@ -1458,21 +1456,19 @@ static int __init vga_arb_device_init(vo
 				continue;
 
 			if (!vga_default_device())
-				pr_info("setting as boot device: PCI:%s\n",
-					pci_name(vgadev->pdev));
+				vgaarb_info(dev, "setting as boot device\n");
 			else if (vgadev->pdev != vga_default_device())
-				pr_info("overriding boot device: PCI:%s\n",
-					pci_name(vgadev->pdev));
+				vgaarb_info(dev, "overriding boot device\n");
 			vga_set_default_device(vgadev->pdev);
 		}
 #endif
 		if (vgadev->bridge_has_one_vga)
-			pr_info("bridge control possible %s\n",
-				pci_name(vgadev->pdev));
+			vgaarb_info(dev, "bridge control possible\n");
 		else
-			pr_info("no bridge control possible %s\n",
-				pci_name(vgadev->pdev));
+			vgaarb_info(dev, "no bridge control possible\n");
 	}
+
+	pr_info("loaded\n");
 	return rc;
 }
 subsys_initcall(vga_arb_device_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-asus.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-asus.c
--- linux-libre-4.9-gnu/drivers/hid/hid-asus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-asus.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,12 @@
  *  This module based on hid-ortek by
  *  Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
  *  Copyright (c) 2011 Jiri Kosina
+ *
+ *  This module has been updated to add support for Asus i2c touchpad.
+ *
+ *  Copyright (c) 2016 Brendan McGrath <redmcg@redmandi.dyndns.org>
+ *  Copyright (c) 2016 Victor Vlasenko <victor.vlasenko@sysgears.com>
+ *  Copyright (c) 2016 Frederik Wenigwieser <frederik.wenigwieser@gmail.com>
  */
 
 /*
@@ -20,16 +26,292 @@
  * any later version.
  */
 
-#include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/input/mt.h>
 
 #include "hid-ids.h"
 
+MODULE_AUTHOR("Yusuke Fujimaki <usk.fujimaki@gmail.com>");
+MODULE_AUTHOR("Brendan McGrath <redmcg@redmandi.dyndns.org>");
+MODULE_AUTHOR("Victor Vlasenko <victor.vlasenko@sysgears.com>");
+MODULE_AUTHOR("Frederik Wenigwieser <frederik.wenigwieser@gmail.com>");
+MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
+
+#define FEATURE_REPORT_ID 0x0d
+#define INPUT_REPORT_ID 0x5d
+
+#define INPUT_REPORT_SIZE 28
+
+#define MAX_CONTACTS 5
+
+#define MAX_X 2794
+#define MAX_Y 1758
+#define MAX_TOUCH_MAJOR 8
+#define MAX_PRESSURE 128
+
+#define CONTACT_DATA_SIZE 5
+
+#define BTN_LEFT_MASK 0x01
+#define CONTACT_TOOL_TYPE_MASK 0x80
+#define CONTACT_X_MSB_MASK 0xf0
+#define CONTACT_Y_MSB_MASK 0x0f
+#define CONTACT_TOUCH_MAJOR_MASK 0x07
+#define CONTACT_PRESSURE_MASK 0x7f
+
+#define QUIRK_FIX_NOTEBOOK_REPORT	BIT(0)
+#define QUIRK_NO_INIT_REPORTS		BIT(1)
+#define QUIRK_SKIP_INPUT_MAPPING	BIT(2)
+#define QUIRK_IS_MULTITOUCH		BIT(3)
+
+#define KEYBOARD_QUIRKS			(QUIRK_FIX_NOTEBOOK_REPORT | \
+						 QUIRK_NO_INIT_REPORTS)
+#define TOUCHPAD_QUIRKS			(QUIRK_NO_INIT_REPORTS | \
+						 QUIRK_SKIP_INPUT_MAPPING | \
+						 QUIRK_IS_MULTITOUCH)
+
+#define TRKID_SGN       ((TRKID_MAX + 1) >> 1)
+
+struct asus_drvdata {
+	unsigned long quirks;
+	struct input_dev *input;
+};
+
+static void asus_report_contact_down(struct input_dev *input,
+		int toolType, u8 *data)
+{
+	int touch_major, pressure;
+	int x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1];
+	int y = MAX_Y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]);
+
+	if (toolType == MT_TOOL_PALM) {
+		touch_major = MAX_TOUCH_MAJOR;
+		pressure = MAX_PRESSURE;
+	} else {
+		touch_major = (data[3] >> 4) & CONTACT_TOUCH_MAJOR_MASK;
+		pressure = data[4] & CONTACT_PRESSURE_MASK;
+	}
+
+	input_report_abs(input, ABS_MT_POSITION_X, x);
+	input_report_abs(input, ABS_MT_POSITION_Y, y);
+	input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major);
+	input_report_abs(input, ABS_MT_PRESSURE, pressure);
+}
+
+/* Required for Synaptics Palm Detection */
+static void asus_report_tool_width(struct input_dev *input)
+{
+	struct input_mt *mt = input->mt;
+	struct input_mt_slot *oldest;
+	int oldid, count, i;
+
+	oldest = NULL;
+	oldid = mt->trkid;
+	count = 0;
+
+	for (i = 0; i < mt->num_slots; ++i) {
+		struct input_mt_slot *ps = &mt->slots[i];
+		int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID);
+
+		if (id < 0)
+			continue;
+		if ((id - oldid) & TRKID_SGN) {
+			oldest = ps;
+			oldid = id;
+		}
+		count++;
+	}
+
+	if (oldest) {
+		input_report_abs(input, ABS_TOOL_WIDTH,
+			input_mt_get_value(oldest, ABS_MT_TOUCH_MAJOR));
+	}
+}
+
+static void asus_report_input(struct input_dev *input, u8 *data)
+{
+	int i;
+	u8 *contactData = data + 2;
+
+	for (i = 0; i < MAX_CONTACTS; i++) {
+		bool down = !!(data[1] & BIT(i+3));
+		int toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ?
+						MT_TOOL_PALM : MT_TOOL_FINGER;
+
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, toolType, down);
+
+		if (down) {
+			asus_report_contact_down(input, toolType, contactData);
+			contactData += CONTACT_DATA_SIZE;
+		}
+	}
+
+	input_report_key(input, BTN_LEFT, data[1] & BTN_LEFT_MASK);
+	asus_report_tool_width(input);
+
+	input_mt_sync_frame(input);
+	input_sync(input);
+}
+
+static int asus_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *data, int size)
+{
+	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+
+	if (drvdata->quirks & QUIRK_IS_MULTITOUCH &&
+					 data[0] == INPUT_REPORT_ID &&
+						size == INPUT_REPORT_SIZE) {
+		asus_report_input(drvdata->input, data);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
+{
+	struct input_dev *input = hi->input;
+	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+
+	if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+		int ret;
+
+		input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0);
+		input_set_abs_params(input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0);
+		input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0);
+		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0);
+		input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0);
+
+		__set_bit(BTN_LEFT, input->keybit);
+		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+
+		ret = input_mt_init_slots(input, MAX_CONTACTS, INPUT_MT_POINTER);
+
+		if (ret) {
+			hid_err(hdev, "Asus input mt init slots failed: %d\n", ret);
+			return ret;
+		}
+	}
+
+	drvdata->input = input;
+
+	return 0;
+}
+
+static int asus_input_mapping(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit,
+		int *max)
+{
+	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+
+	if (drvdata->quirks & QUIRK_SKIP_INPUT_MAPPING) {
+		/* Don't map anything from the HID report.
+		 * We do it all manually in asus_input_configured
+		 */
+		return -1;
+	}
+
+	return 0;
+}
+
+static int asus_start_multitouch(struct hid_device *hdev)
+{
+	int ret;
+	const unsigned char buf[] = { FEATURE_REPORT_ID, 0x00, 0x03, 0x01, 0x00 };
+	unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
+
+	if (!dmabuf) {
+		ret = -ENOMEM;
+		hid_err(hdev, "Asus failed to alloc dma buf: %d\n", ret);
+		return ret;
+	}
+
+	ret = hid_hw_raw_request(hdev, dmabuf[0], dmabuf, sizeof(buf),
+					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
+
+	kfree(dmabuf);
+
+	if (ret != sizeof(buf)) {
+		hid_err(hdev, "Asus failed to start multitouch: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
+{
+	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+
+	if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
+		return asus_start_multitouch(hdev);
+
+	return 0;
+}
+
+static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	struct asus_drvdata *drvdata;
+
+	drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (drvdata == NULL) {
+		hid_err(hdev, "Can't alloc Asus descriptor\n");
+		return -ENOMEM;
+	}
+
+	hid_set_drvdata(hdev, drvdata);
+
+	drvdata->quirks = id->driver_data;
+
+	if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
+		hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "Asus hid parse failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		hid_err(hdev, "Asus hw start failed: %d\n", ret);
+		return ret;
+	}
+
+	if (!drvdata->input) {
+		hid_err(hdev, "Asus input not registered\n");
+		ret = -ENOMEM;
+		goto err_stop_hw;
+	}
+
+	if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+		drvdata->input->name = "Asus TouchPad";
+	} else {
+		drvdata->input->name = "Asus Keyboard";
+	}
+
+	if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+		ret = asus_start_multitouch(hdev);
+		if (ret)
+			goto err_stop_hw;
+	}
+
+	return 0;
+err_stop_hw:
+	hid_hw_stop(hdev);
+	return ret;
+}
+
 static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) {
+	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+
+	if (drvdata->quirks & QUIRK_FIX_NOTEBOOK_REPORT &&
+			*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x65) {
 		hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
 		rdesc[55] = 0xdd;
 	}
@@ -37,15 +319,25 @@ static __u8 *asus_report_fixup(struct hi
 }
 
 static const struct hid_device_id asus_devices[] = {
-	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) },
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
+		 USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD), KEYBOARD_QUIRKS},
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
+			 USB_DEVICE_ID_ASUSTEK_TOUCHPAD), TOUCHPAD_QUIRKS },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, asus_devices);
 
 static struct hid_driver asus_driver = {
-	.name = "asus",
-	.id_table = asus_devices,
-	.report_fixup = asus_report_fixup
+	.name			= "asus",
+	.id_table		= asus_devices,
+	.report_fixup		= asus_report_fixup,
+	.probe                  = asus_probe,
+	.input_mapping          = asus_input_mapping,
+	.input_configured       = asus_input_configured,
+#ifdef CONFIG_PM
+	.reset_resume           = asus_reset_resume,
+#endif
+	.raw_event		= asus_raw_event
 };
 module_hid_driver(asus_driver);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-core.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-core.c
--- linux-libre-4.9-gnu/drivers/hid/hid-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -727,8 +727,9 @@ static void hid_scan_collection(struct h
 	    (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
 	     hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 ||
 	     hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
+	     hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 ||
+	     hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 ||
 	     hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP ||
-	     hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
 	     hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
 	    hid->group == HID_GROUP_MULTITOUCH)
 		hid->group = HID_GROUP_GENERIC;
@@ -1857,6 +1858,7 @@ static const struct hid_device_id hid_ha
 	{ 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_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD) },
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_TOUCHPAD) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_BETOP_2185BFM, 0x2208) },
@@ -1883,6 +1885,9 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELCOM, USB_DEVICE_ID_DELCOM_VISUAL_IND) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
+#if IS_ENABLED(CONFIG_HID_MAYFLASH)
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3) },
+#endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_WN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DREAM_CHEEKY, USB_DEVICE_ID_DREAM_CHEEKY_FA) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
@@ -1983,8 +1988,9 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) },
@@ -2059,6 +2065,9 @@ static const struct hid_device_id hid_ha
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER) },
@@ -2086,6 +2095,7 @@ static const struct hid_device_id hid_ha
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) },
@@ -2486,6 +2496,7 @@ static const struct hid_device_id hid_ig
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
 #if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-corsair.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-corsair.c
--- linux-libre-4.9-gnu/drivers/hid/hid-corsair.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-corsair.c	2017-02-12 16:03:20.000000000 -0500
@@ -148,26 +148,36 @@ static enum led_brightness k90_backlight
 	struct usb_interface *usbif = to_usb_interface(dev->parent);
 	struct usb_device *usbdev = interface_to_usbdev(usbif);
 	int brightness;
-	char data[8];
+	char *data;
+
+	data = kmalloc(8, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 			      K90_REQUEST_STATUS,
 			      USB_DIR_IN | USB_TYPE_VENDOR |
 			      USB_RECIP_DEVICE, 0, 0, data, 8,
 			      USB_CTRL_SET_TIMEOUT);
-	if (ret < 0) {
+	if (ret < 5) {
 		dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
 			 ret);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 	brightness = data[4];
 	if (brightness < 0 || brightness > 3) {
 		dev_warn(dev,
 			 "Read invalid backlight brightness: %02hhx.\n",
 			 data[4]);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
-	return brightness;
+	ret = brightness;
+out:
+	kfree(data);
+
+	return ret;
 }
 
 static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev)
@@ -253,17 +263,22 @@ static ssize_t k90_show_macro_mode(struc
 	struct usb_interface *usbif = to_usb_interface(dev->parent);
 	struct usb_device *usbdev = interface_to_usbdev(usbif);
 	const char *macro_mode;
-	char data[8];
+	char *data;
+
+	data = kmalloc(2, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 			      K90_REQUEST_GET_MODE,
 			      USB_DIR_IN | USB_TYPE_VENDOR |
 			      USB_RECIP_DEVICE, 0, 0, data, 2,
 			      USB_CTRL_SET_TIMEOUT);
-	if (ret < 0) {
+	if (ret < 1) {
 		dev_warn(dev, "Failed to get K90 initial mode (error %d).\n",
 			 ret);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
 	switch (data[0]) {
@@ -277,10 +292,15 @@ static ssize_t k90_show_macro_mode(struc
 	default:
 		dev_warn(dev, "K90 in unknown mode: %02hhx.\n",
 			 data[0]);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
-	return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+	ret = snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+out:
+	kfree(data);
+
+	return ret;
 }
 
 static ssize_t k90_store_macro_mode(struct device *dev,
@@ -320,26 +340,36 @@ static ssize_t k90_show_current_profile(
 	struct usb_interface *usbif = to_usb_interface(dev->parent);
 	struct usb_device *usbdev = interface_to_usbdev(usbif);
 	int current_profile;
-	char data[8];
+	char *data;
+
+	data = kmalloc(8, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
 	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
 			      K90_REQUEST_STATUS,
 			      USB_DIR_IN | USB_TYPE_VENDOR |
 			      USB_RECIP_DEVICE, 0, 0, data, 8,
 			      USB_CTRL_SET_TIMEOUT);
-	if (ret < 0) {
+	if (ret < 8) {
 		dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
 			 ret);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 	current_profile = data[7];
 	if (current_profile < 1 || current_profile > 3) {
 		dev_warn(dev, "Read invalid current profile: %02hhx.\n",
 			 data[7]);
-		return -EIO;
+		ret = -EIO;
+		goto out;
 	}
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+out:
+	kfree(data);
+
+	return ret;
 }
 
 static ssize_t k90_store_current_profile(struct device *dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-cp2112.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-cp2112.c
--- linux-libre-4.9-gnu/drivers/hid/hid-cp2112.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-cp2112.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,7 @@
  *   http://www.silabs.com/Support%20Documents/TechnicalDocs/AN495.pdf
  */
 
+#include <linux/gpio.h>
 #include <linux/gpio/driver.h>
 #include <linux/hid.h>
 #include <linux/i2c.h>
@@ -167,7 +168,13 @@ struct cp2112_device {
 	atomic_t xfer_avail;
 	struct gpio_chip gc;
 	u8 *in_out_buffer;
-	spinlock_t lock;
+	struct mutex lock;
+
+	struct gpio_desc *desc[8];
+	bool gpio_poll;
+	struct delayed_work gpio_poll_worker;
+	unsigned long irq_mask;
+	u8 gpio_prev_state;
 };
 
 static int gpio_push_pull = 0xFF;
@@ -179,10 +186,9 @@ static int cp2112_gpio_direction_input(s
 	struct cp2112_device *dev = gpiochip_get_data(chip);
 	struct hid_device *hdev = dev->hdev;
 	u8 *buf = dev->in_out_buffer;
-	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&dev->lock, flags);
+	mutex_lock(&dev->lock);
 
 	ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
 				 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
@@ -206,8 +212,8 @@ static int cp2112_gpio_direction_input(s
 	ret = 0;
 
 exit:
-	spin_unlock_irqrestore(&dev->lock, flags);
-	return ret <= 0 ? ret : -EIO;
+	mutex_unlock(&dev->lock);
+	return ret < 0 ? ret : -EIO;
 }
 
 static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -215,10 +221,9 @@ static void cp2112_gpio_set(struct gpio_
 	struct cp2112_device *dev = gpiochip_get_data(chip);
 	struct hid_device *hdev = dev->hdev;
 	u8 *buf = dev->in_out_buffer;
-	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&dev->lock, flags);
+	mutex_lock(&dev->lock);
 
 	buf[0] = CP2112_GPIO_SET;
 	buf[1] = value ? 0xff : 0;
@@ -230,18 +235,17 @@ static void cp2112_gpio_set(struct gpio_
 	if (ret < 0)
 		hid_err(hdev, "error setting GPIO values: %d\n", ret);
 
-	spin_unlock_irqrestore(&dev->lock, flags);
+	mutex_unlock(&dev->lock);
 }
 
-static int cp2112_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int cp2112_gpio_get_all(struct gpio_chip *chip)
 {
 	struct cp2112_device *dev = gpiochip_get_data(chip);
 	struct hid_device *hdev = dev->hdev;
 	u8 *buf = dev->in_out_buffer;
-	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&dev->lock, flags);
+	mutex_lock(&dev->lock);
 
 	ret = hid_hw_raw_request(hdev, CP2112_GPIO_GET, buf,
 				 CP2112_GPIO_GET_LENGTH, HID_FEATURE_REPORT,
@@ -252,24 +256,34 @@ static int cp2112_gpio_get(struct gpio_c
 		goto exit;
 	}
 
-	ret = (buf[1] >> offset) & 1;
+	ret = buf[1];
 
 exit:
-	spin_unlock_irqrestore(&dev->lock, flags);
+	mutex_unlock(&dev->lock);
 
 	return ret;
 }
 
+static int cp2112_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	int ret;
+
+	ret = cp2112_gpio_get_all(chip);
+	if (ret < 0)
+		return ret;
+
+	return (ret >> offset) & 1;
+}
+
 static int cp2112_gpio_direction_output(struct gpio_chip *chip,
 					unsigned offset, int value)
 {
 	struct cp2112_device *dev = gpiochip_get_data(chip);
 	struct hid_device *hdev = dev->hdev;
 	u8 *buf = dev->in_out_buffer;
-	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&dev->lock, flags);
+	mutex_lock(&dev->lock);
 
 	ret = hid_hw_raw_request(hdev, CP2112_GPIO_CONFIG, buf,
 				 CP2112_GPIO_CONFIG_LENGTH, HID_FEATURE_REPORT,
@@ -290,7 +304,7 @@ static int cp2112_gpio_direction_output(
 		goto fail;
 	}
 
-	spin_unlock_irqrestore(&dev->lock, flags);
+	mutex_unlock(&dev->lock);
 
 	/*
 	 * Set gpio value when output direction is already set,
@@ -301,7 +315,7 @@ static int cp2112_gpio_direction_output(
 	return 0;
 
 fail:
-	spin_unlock_irqrestore(&dev->lock, flags);
+	mutex_unlock(&dev->lock);
 	return ret < 0 ? ret : -EIO;
 }
 
@@ -1041,6 +1055,166 @@ static void chmod_sysfs_attrs(struct hid
 	}
 }
 
+static void cp2112_gpio_irq_ack(struct irq_data *d)
+{
+}
+
+static void cp2112_gpio_irq_mask(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct cp2112_device *dev = gpiochip_get_data(gc);
+
+	__clear_bit(d->hwirq, &dev->irq_mask);
+}
+
+static void cp2112_gpio_irq_unmask(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct cp2112_device *dev = gpiochip_get_data(gc);
+
+	__set_bit(d->hwirq, &dev->irq_mask);
+}
+
+static void cp2112_gpio_poll_callback(struct work_struct *work)
+{
+	struct cp2112_device *dev = container_of(work, struct cp2112_device,
+						 gpio_poll_worker.work);
+	struct irq_data *d;
+	u8 gpio_mask;
+	u8 virqs = (u8)dev->irq_mask;
+	u32 irq_type;
+	int irq, virq, ret;
+
+	ret = cp2112_gpio_get_all(&dev->gc);
+	if (ret == -ENODEV) /* the hardware has been disconnected */
+		return;
+	if (ret < 0)
+		goto exit;
+
+	gpio_mask = ret;
+
+	while (virqs) {
+		virq = ffs(virqs) - 1;
+		virqs &= ~BIT(virq);
+
+		if (!dev->gc.to_irq)
+			break;
+
+		irq = dev->gc.to_irq(&dev->gc, virq);
+
+		d = irq_get_irq_data(irq);
+		if (!d)
+			continue;
+
+		irq_type = irqd_get_trigger_type(d);
+
+		if (gpio_mask & BIT(virq)) {
+			/* Level High */
+
+			if (irq_type & IRQ_TYPE_LEVEL_HIGH)
+				handle_nested_irq(irq);
+
+			if ((irq_type & IRQ_TYPE_EDGE_RISING) &&
+			    !(dev->gpio_prev_state & BIT(virq)))
+				handle_nested_irq(irq);
+		} else {
+			/* Level Low */
+
+			if (irq_type & IRQ_TYPE_LEVEL_LOW)
+				handle_nested_irq(irq);
+
+			if ((irq_type & IRQ_TYPE_EDGE_FALLING) &&
+			    (dev->gpio_prev_state & BIT(virq)))
+				handle_nested_irq(irq);
+		}
+	}
+
+	dev->gpio_prev_state = gpio_mask;
+
+exit:
+	if (dev->gpio_poll)
+		schedule_delayed_work(&dev->gpio_poll_worker, 10);
+}
+
+
+static unsigned int cp2112_gpio_irq_startup(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct cp2112_device *dev = gpiochip_get_data(gc);
+
+	INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
+
+	cp2112_gpio_direction_input(gc, d->hwirq);
+
+	if (!dev->gpio_poll) {
+		dev->gpio_poll = true;
+		schedule_delayed_work(&dev->gpio_poll_worker, 0);
+	}
+
+	cp2112_gpio_irq_unmask(d);
+	return 0;
+}
+
+static void cp2112_gpio_irq_shutdown(struct irq_data *d)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct cp2112_device *dev = gpiochip_get_data(gc);
+
+	cancel_delayed_work_sync(&dev->gpio_poll_worker);
+}
+
+static int cp2112_gpio_irq_type(struct irq_data *d, unsigned int type)
+{
+	return 0;
+}
+
+static struct irq_chip cp2112_gpio_irqchip = {
+	.name = "cp2112-gpio",
+	.irq_startup = cp2112_gpio_irq_startup,
+	.irq_shutdown = cp2112_gpio_irq_shutdown,
+	.irq_ack = cp2112_gpio_irq_ack,
+	.irq_mask = cp2112_gpio_irq_mask,
+	.irq_unmask = cp2112_gpio_irq_unmask,
+	.irq_set_type = cp2112_gpio_irq_type,
+};
+
+static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev,
+					      int pin)
+{
+	int ret;
+
+	if (dev->desc[pin])
+		return -EINVAL;
+
+	dev->desc[pin] = gpiochip_request_own_desc(&dev->gc, pin,
+						   "HID/I2C:Event");
+	if (IS_ERR(dev->desc[pin])) {
+		dev_err(dev->gc.parent, "Failed to request GPIO\n");
+		return PTR_ERR(dev->desc[pin]);
+	}
+
+	ret = gpiochip_lock_as_irq(&dev->gc, pin);
+	if (ret) {
+		dev_err(dev->gc.parent, "Failed to lock GPIO as interrupt\n");
+		goto err_desc;
+	}
+
+	ret = gpiod_to_irq(dev->desc[pin]);
+	if (ret < 0) {
+		dev_err(dev->gc.parent, "Failed to translate GPIO to IRQ\n");
+		goto err_lock;
+	}
+
+	return ret;
+
+err_lock:
+	gpiochip_unlock_as_irq(&dev->gc, pin);
+err_desc:
+	gpiochip_free_own_desc(dev->desc[pin]);
+	dev->desc[pin] = NULL;
+	return ret;
+}
+
 static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	struct cp2112_device *dev;
@@ -1057,7 +1231,7 @@ static int cp2112_probe(struct hid_devic
 	if (!dev->in_out_buffer)
 		return -ENOMEM;
 
-	spin_lock_init(&dev->lock);
+	mutex_init(&dev->lock);
 
 	ret = hid_parse(hdev);
 	if (ret) {
@@ -1163,8 +1337,17 @@ static int cp2112_probe(struct hid_devic
 	chmod_sysfs_attrs(hdev);
 	hid_hw_power(hdev, PM_HINT_NORMAL);
 
+	ret = gpiochip_irqchip_add(&dev->gc, &cp2112_gpio_irqchip, 0,
+				   handle_simple_irq, IRQ_TYPE_NONE);
+	if (ret) {
+		dev_err(dev->gc.parent, "failed to add IRQ chip\n");
+		goto err_sysfs_remove;
+	}
+
 	return ret;
 
+err_sysfs_remove:
+	sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group);
 err_gpiochip_remove:
 	gpiochip_remove(&dev->gc);
 err_free_i2c:
@@ -1181,10 +1364,22 @@ err_hid_stop:
 static void cp2112_remove(struct hid_device *hdev)
 {
 	struct cp2112_device *dev = hid_get_drvdata(hdev);
+	int i;
 
 	sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group);
-	gpiochip_remove(&dev->gc);
 	i2c_del_adapter(&dev->adap);
+
+	if (dev->gpio_poll) {
+		dev->gpio_poll = false;
+		cancel_delayed_work_sync(&dev->gpio_poll_worker);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(dev->desc); i++) {
+		gpiochip_unlock_as_irq(&dev->gc, i);
+		gpiochip_free_own_desc(dev->desc[i]);
+	}
+
+	gpiochip_remove(&dev->gc);
 	/* i2c_del_adapter has finished removing all i2c devices from our
 	 * adapter. Well behaved devices should no longer call our cp2112_xfer
 	 * and should have waited for any pending calls to finish. It has also
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-cypress.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-cypress.c
--- linux-libre-4.9-gnu/drivers/hid/hid-cypress.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-cypress.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,9 @@ static __u8 *cp_report_fixup(struct hid_
 	if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
 		return rdesc;
 
+	if (*rsize < 4)
+		return rdesc;
+
 	for (i = 0; i < *rsize - 4; i++)
 		if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
 			rdesc[i] = 0x19;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-ids.h linux-libre-4.10-rc8-gnu/drivers/hid/hid-ids.h
--- linux-libre-4.9-gnu/drivers/hid/hid-ids.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-ids.h	2017-02-12 16:03:20.000000000 -0500
@@ -76,6 +76,9 @@
 #define USB_VENDOR_ID_ALPS_JP		0x044E
 #define HID_DEVICE_ID_ALPS_U1_DUAL	0x120B
 
+#define USB_VENDOR_ID_AMI		0x046b
+#define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE	0xff10
+
 #define USB_VENDOR_ID_ANTON		0x1130
 #define USB_DEVICE_ID_ANTON_TOUCH_PAD	0x3101
 
@@ -171,6 +174,7 @@
 #define USB_DEVICE_ID_ASUSTEK_LCM	0x1726
 #define USB_DEVICE_ID_ASUSTEK_LCM2	0x175b
 #define USB_DEVICE_ID_ASUSTEK_NOTEBOOK_KEYBOARD	0x8585
+#define USB_DEVICE_ID_ASUSTEK_TOUCHPAD	0x0101
 
 #define USB_VENDOR_ID_ATEN		0x0557
 #define USB_DEVICE_ID_ATEN_UC100KM	0x2004
@@ -315,8 +319,11 @@
 #define USB_VENDOR_ID_DMI		0x0c0b
 #define USB_DEVICE_ID_DMI_ENC		0x5fab
 
-#define USB_VENDOR_ID_DRAGONRISE	0x0079
-#define USB_DEVICE_ID_DRAGONRISE_WIIU	0x1800
+#define USB_VENDOR_ID_DRAGONRISE		0x0079
+#define USB_DEVICE_ID_DRAGONRISE_WIIU		0x1800
+#define USB_DEVICE_ID_DRAGONRISE_PS3		0x1801
+#define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR	0x1803
+#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE	0x1843
 
 #define USB_VENDOR_ID_DWAV		0x0eef
 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER	0x0001
@@ -362,6 +369,9 @@
 #define USB_VENDOR_ID_FLATFROG		0x25b5
 #define USB_DEVICE_ID_MULTITOUCH_3200	0x0002
 
+#define USB_VENDOR_ID_FUTABA            0x0547
+#define USB_DEVICE_ID_LED_DISPLAY       0x7000
+
 #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
@@ -718,8 +728,9 @@
 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3    0x07dc
 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2  0x07e2
 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4 0x07e4
+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2 0x07e8
 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9
-#define USB_DEVICE_ID_MS_TYPE_COVER_3    0x07de
 #define USB_DEVICE_ID_MS_POWER_COVER     0x07da
 
 #define USB_VENDOR_ID_MOJO		0x8282
@@ -808,6 +819,9 @@
 #define USB_VENDOR_ID_PETALYNX		0x18b1
 #define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
 
+#define USB_VENDOR_ID_PETZL		0x2122
+#define USB_DEVICE_ID_PETZL_HEADLAMP	0x1234
+
 #define USB_VENDOR_ID_PHILIPS		0x0471
 #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
 
@@ -903,6 +917,8 @@
 #define USB_DEVICE_ID_SONY_PS3_BDREMOTE		0x0306
 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
 #define USB_DEVICE_ID_SONY_PS4_CONTROLLER	0x05c4
+#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2	0x09cc
+#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE	0x0ba0
 #define USB_DEVICE_ID_SONY_MOTION_CONTROLLER	0x03d5
 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER	0x042f
 #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER		0x0002
@@ -959,6 +975,9 @@
 #define USB_VENDOR_ID_THINGM		0x27b8
 #define USB_DEVICE_ID_BLINK1		0x01ed
 
+#define USB_VENDOR_ID_THQ		0x20d6
+#define USB_DEVICE_ID_THQ_PS3_UDRAW	0xcb17
+
 #define USB_VENDOR_ID_THRUSTMASTER	0x044f
 
 #define USB_VENDOR_ID_TIVO		0x150a
@@ -1034,6 +1053,10 @@
 #define USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH	0x0500
 #define USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET	0x0502
 
+#define	USB_VENDOR_ID_WEIDA		0x2575
+#define	USB_DEVICE_ID_WEIDA_8752	0xC300
+#define	USB_DEVICE_ID_WEIDA_8755	0xC301
+
 #define USB_VENDOR_ID_WISEGROUP		0x0925
 #define USB_DEVICE_ID_SMARTJOY_PLUS	0x0005
 #define USB_DEVICE_ID_SUPER_JOY_BOX_3	0x8888
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-input.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-input.c
--- linux-libre-4.9-gnu/drivers/hid/hid-input.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-input.c	2017-02-12 16:03:20.000000000 -0500
@@ -253,6 +253,7 @@ __s32 hidinput_calc_abs_res(const struct
 	case ABS_RX:
 	case ABS_RY:
 	case ABS_RZ:
+	case ABS_WHEEL:
 	case ABS_TILT_X:
 	case ABS_TILT_Y:
 		if (field->unit == 0x14) {		/* If degrees */
@@ -1468,6 +1469,31 @@ static void hidinput_cleanup_hidinput(st
 	kfree(hidinput);
 }
 
+static struct hid_input *hidinput_match(struct hid_report *report)
+{
+	struct hid_device *hid = report->device;
+	struct hid_input *hidinput;
+
+	list_for_each_entry(hidinput, &hid->inputs, list) {
+		if (hidinput->report &&
+		    hidinput->report->id == report->id)
+			return hidinput;
+	}
+
+	return NULL;
+}
+
+static inline void hidinput_configure_usages(struct hid_input *hidinput,
+					     struct hid_report *report)
+{
+	int i, j;
+
+	for (i = 0; i < report->maxfield; i++)
+		for (j = 0; j < report->field[i]->maxusage; j++)
+			hidinput_configure_usage(hidinput, report->field[i],
+						 report->field[i]->usage + j);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -1478,8 +1504,8 @@ int hidinput_connect(struct hid_device *
 {
 	struct hid_driver *drv = hid->driver;
 	struct hid_report *report;
-	struct hid_input *hidinput = NULL;
-	int i, j, k;
+	struct hid_input *next, *hidinput = NULL;
+	int i, k;
 
 	INIT_LIST_HEAD(&hid->inputs);
 	INIT_WORK(&hid->led_work, hidinput_led_worker);
@@ -1509,43 +1535,40 @@ int hidinput_connect(struct hid_device *
 			if (!report->maxfield)
 				continue;
 
+			/*
+			 * Find the previous hidinput report attached
+			 * to this report id.
+			 */
+			if (hid->quirks & HID_QUIRK_MULTI_INPUT)
+				hidinput = hidinput_match(report);
+
 			if (!hidinput) {
 				hidinput = hidinput_allocate(hid);
 				if (!hidinput)
 					goto out_unwind;
 			}
 
-			for (i = 0; i < report->maxfield; i++)
-				for (j = 0; j < report->field[i]->maxusage; j++)
-					hidinput_configure_usage(hidinput, report->field[i],
-								 report->field[i]->usage + j);
-
-			if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
-			    !hidinput_has_been_populated(hidinput))
-				continue;
+			hidinput_configure_usages(hidinput, report);
 
-			if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
-				/* This will leave hidinput NULL, so that it
-				 * allocates another one if we have more inputs on
-				 * the same interface. Some devices (e.g. Happ's
-				 * UGCI) cram a lot of unrelated inputs into the
-				 * same interface. */
+			if (hid->quirks & HID_QUIRK_MULTI_INPUT)
 				hidinput->report = report;
-				if (drv->input_configured &&
-				    drv->input_configured(hid, hidinput))
-					goto out_cleanup;
-				if (input_register_device(hidinput->input))
-					goto out_cleanup;
-				hidinput = NULL;
-			}
 		}
 	}
 
-	if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
-	    !hidinput_has_been_populated(hidinput)) {
-		/* no need to register an input device not populated */
-		hidinput_cleanup_hidinput(hid, hidinput);
-		hidinput = NULL;
+	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
+		if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
+		    !hidinput_has_been_populated(hidinput)) {
+			/* no need to register an input device not populated */
+			hidinput_cleanup_hidinput(hid, hidinput);
+			continue;
+		}
+
+		if (drv->input_configured &&
+		    drv->input_configured(hid, hidinput))
+			goto out_unwind;
+		if (input_register_device(hidinput->input))
+			goto out_unwind;
+		hidinput->registered = true;
 	}
 
 	if (list_empty(&hid->inputs)) {
@@ -1553,20 +1576,8 @@ int hidinput_connect(struct hid_device *
 		goto out_unwind;
 	}
 
-	if (hidinput) {
-		if (drv->input_configured &&
-		    drv->input_configured(hid, hidinput))
-			goto out_cleanup;
-		if (input_register_device(hidinput->input))
-			goto out_cleanup;
-	}
-
 	return 0;
 
-out_cleanup:
-	list_del(&hidinput->list);
-	input_free_device(hidinput->input);
-	kfree(hidinput);
 out_unwind:
 	/* unwind the ones we already registered */
 	hidinput_disconnect(hid);
@@ -1583,7 +1594,10 @@ void hidinput_disconnect(struct hid_devi
 
 	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
 		list_del(&hidinput->list);
-		input_unregister_device(hidinput->input);
+		if (hidinput->registered)
+			input_unregister_device(hidinput->input);
+		else
+			input_free_device(hidinput->input);
 		kfree(hidinput);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-lg.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-lg.c
--- linux-libre-4.9-gnu/drivers/hid/hid-lg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-lg.c	2017-02-12 16:03:20.000000000 -0500
@@ -872,7 +872,7 @@ static const struct hid_device_id lg_dev
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG),
 		.driver_data = LG_NOGET | LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
-		.driver_data = LG_FF2 },
+		.driver_data = LG_NOGET | LG_FF2 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940),
 		.driver_data = LG_FF3 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-mf.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-mf.c
--- linux-libre-4.9-gnu/drivers/hid/hid-mf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-mf.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,166 @@
+/*
+ * Force feedback support for Mayflash game controller adapters.
+ *
+ * These devices are manufactured by Mayflash but identify themselves
+ * using the vendor ID of DragonRise Inc.
+ *
+ * Tested with:
+ * 0079:1801 "DragonRise Inc. Mayflash PS3 Game Controller Adapter"
+ *
+ * The following adapters probably work too, but need to be tested:
+ * 0079:1800 "DragonRise Inc. Mayflash WIIU Game Controller Adapter"
+ * 0079:1843 "DragonRise Inc. Mayflash GameCube Game Controller Adapter"
+ *
+ * Copyright (c) 2016 Marcel Hasler <mahasler@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.
+ */
+
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+struct mf_device {
+	struct hid_report *report;
+};
+
+static int mf_play(struct input_dev *dev, void *data, struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct mf_device *mf = data;
+	int strong, weak;
+
+	strong = effect->u.rumble.strong_magnitude;
+	weak = effect->u.rumble.weak_magnitude;
+
+	dbg_hid("Called with 0x%04x 0x%04x.\n", strong, weak);
+
+	strong = strong * 0xff / 0xffff;
+	weak = weak * 0xff / 0xffff;
+
+	dbg_hid("Running with 0x%02x 0x%02x.\n", strong, weak);
+
+	mf->report->field[0]->value[0] = weak;
+	mf->report->field[0]->value[1] = strong;
+	hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT);
+
+	return 0;
+}
+
+static int mf_init(struct hid_device *hid)
+{
+	struct mf_device *mf;
+
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+
+	struct list_head *report_ptr;
+	struct hid_report *report;
+
+	struct list_head *input_ptr = &hid->inputs;
+	struct hid_input *input;
+
+	struct input_dev *dev;
+
+	int error;
+
+	/* Setup each of the four inputs */
+	list_for_each(report_ptr, report_list) {
+		report = list_entry(report_ptr, struct hid_report, list);
+
+		if (report->maxfield < 1 || report->field[0]->report_count < 2) {
+			hid_err(hid, "Invalid report, this should never happen!\n");
+			return -ENODEV;
+		}
+
+		if (list_is_last(input_ptr, &hid->inputs)) {
+			hid_err(hid, "Missing input, this should never happen!\n");
+			return -ENODEV;
+		}
+
+		input_ptr = input_ptr->next;
+		input = list_entry(input_ptr, struct hid_input, list);
+
+		mf = kzalloc(sizeof(struct mf_device), GFP_KERNEL);
+		if (!mf)
+			return -ENOMEM;
+
+		dev = input->input;
+		set_bit(FF_RUMBLE, dev->ffbit);
+
+		error = input_ff_create_memless(dev, mf, mf_play);
+		if (error) {
+			kfree(mf);
+			return error;
+		}
+
+		mf->report = report;
+		mf->report->field[0]->value[0] = 0x00;
+		mf->report->field[0]->value[1] = 0x00;
+		hid_hw_request(hid, mf->report, HID_REQ_SET_REPORT);
+	}
+
+	hid_info(hid, "Force feedback for HJZ Mayflash game controller "
+		      "adapters by Marcel Hasler <mahasler@gmail.com>\n");
+
+	return 0;
+}
+
+static int mf_probe(struct hid_device *hid, const struct hid_device_id *id)
+{
+	int error;
+
+	dev_dbg(&hid->dev, "Mayflash HID hardware probe...\n");
+
+	/* Split device into four inputs */
+	hid->quirks |= HID_QUIRK_MULTI_INPUT;
+
+	error = hid_parse(hid);
+	if (error) {
+		hid_err(hid, "HID parse failed.\n");
+		return error;
+	}
+
+	error = hid_hw_start(hid, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (error) {
+		hid_err(hid, "HID hw start failed\n");
+		return error;
+	}
+
+	error = mf_init(hid);
+	if (error) {
+		hid_err(hid, "Force feedback init failed.\n");
+		hid_hw_stop(hid);
+		return error;
+	}
+
+	return 0;
+}
+
+static const struct hid_device_id mf_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3),  },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, mf_devices);
+
+static struct hid_driver mf_driver = {
+	.name = "hid_mf",
+	.id_table = mf_devices,
+	.probe = mf_probe,
+};
+module_hid_driver(mf_driver);
+
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-microsoft.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-microsoft.c
--- linux-libre-4.9-gnu/drivers/hid/hid-microsoft.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-microsoft.c	2017-02-12 16:03:20.000000000 -0500
@@ -280,9 +280,11 @@ static const struct hid_device_id ms_dev
 		.driver_data = MS_HIDINPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
 		.driver_data = MS_HIDINPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP),
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4),
 		.driver_data = MS_HIDINPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2),
+		.driver_data = MS_HIDINPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP),
 		.driver_data = MS_HIDINPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
 		.driver_data = MS_HIDINPUT },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-multitouch.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-multitouch.c
--- linux-libre-4.9-gnu/drivers/hid/hid-multitouch.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-multitouch.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,6 +108,7 @@ struct mt_device {
 	int cc_value_index;	/* contact count value index in the field */
 	unsigned last_slot_field;	/* the last field of a slot */
 	unsigned mt_report_id;	/* the report ID of the multitouch device */
+	unsigned long initial_quirks;	/* initial quirks state */
 	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */
 	__s16 inputmode_index;	/* InputMode HID feature index in the report */
 	__s16 maxcontact_report_id;	/* Maximum Contact Number HID feature,
@@ -318,13 +319,10 @@ static void mt_get_feature(struct hid_de
 	u8 *buf;
 
 	/*
-	 * Only fetch the feature report if initial reports are not already
-	 * been retrieved. Currently this is only done for Windows 8 touch
-	 * devices.
+	 * Do not fetch the feature report if the device has been explicitly
+	 * marked as non-capable.
 	 */
-	if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS))
-		return;
-	if (td->mtclass.name != MT_CLS_WIN_8)
+	if (td->initial_quirks & HID_QUIRK_NO_INIT_REPORTS)
 		return;
 
 	buf = hid_alloc_report_buf(report, GFP_KERNEL);
@@ -567,6 +565,14 @@ static int mt_touch_input_mapping(struct
 
 	case HID_UP_BUTTON:
 		code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
+		/*
+		 * MS PTP spec says that external buttons left and right have
+		 * usages 2 and 3.
+		 */
+		if (cls->name == MT_CLS_WIN_8 &&
+		    field->application == HID_DG_TOUCHPAD &&
+		    (usage->hid & HID_USAGE) > 1)
+			code--;
 		hid_map_usage(hi, usage, bit, max, EV_KEY, code);
 		input_set_capability(hi->input, EV_KEY, code);
 		return 1;
@@ -842,7 +848,9 @@ static int mt_input_mapping(struct hid_d
 	if (!td->mtclass.export_all_inputs &&
 	    field->application != HID_DG_TOUCHSCREEN &&
 	    field->application != HID_DG_PEN &&
-	    field->application != HID_DG_TOUCHPAD)
+	    field->application != HID_DG_TOUCHPAD &&
+	    field->application != HID_GD_KEYBOARD &&
+	    field->application != HID_CP_CONSUMER_CONTROL)
 		return -1;
 
 	/*
@@ -1083,36 +1091,6 @@ static int mt_probe(struct hid_device *h
 		}
 	}
 
-	/* This allows the driver to correctly support devices
-	 * that emit events over several HID messages.
-	 */
-	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
-
-	/*
-	 * This allows the driver to handle different input sensors
-	 * that emits events through different reports on the same HID
-	 * device.
-	 */
-	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
-	hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
-
-	/*
-	 * Handle special quirks for Windows 8 certified devices.
-	 */
-	if (id->group == HID_GROUP_MULTITOUCH_WIN_8)
-		/*
-		 * Some multitouch screens do not like to be polled for input
-		 * reports. Fortunately, the Win8 spec says that all touches
-		 * should be sent during each report, making the initialization
-		 * of input reports unnecessary.
-		 *
-		 * In addition some touchpads do not behave well if we read
-		 * all feature reports from them. Instead we prevent
-		 * initial report fetching and then selectively fetch each
-		 * report we are interested in.
-		 */
-		hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
-
 	td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
 	if (!td) {
 		dev_err(&hdev->dev, "cannot allocate multitouch data\n");
@@ -1136,6 +1114,39 @@ static int mt_probe(struct hid_device *h
 	if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
 		td->serial_maybe = true;
 
+	/*
+	 * Store the initial quirk state
+	 */
+	td->initial_quirks = hdev->quirks;
+
+	/* This allows the driver to correctly support devices
+	 * that emit events over several HID messages.
+	 */
+	hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC;
+
+	/*
+	 * This allows the driver to handle different input sensors
+	 * that emits events through different reports on the same HID
+	 * device.
+	 */
+	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+	hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT;
+
+	/*
+	 * Some multitouch screens do not like to be polled for input
+	 * reports. Fortunately, the Win8 spec says that all touches
+	 * should be sent during each report, making the initialization
+	 * of input reports unnecessary. For Win7 devices, well, let's hope
+	 * they will still be happy (this is only be a problem if a touch
+	 * was already there while probing the device).
+	 *
+	 * In addition some touchpads do not behave well if we read
+	 * all feature reports from them. Instead we prevent
+	 * initial report fetching and then selectively fetch each
+	 * report we are interested in.
+	 */
+	hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
+
 	ret = hid_parse(hdev);
 	if (ret != 0)
 		return ret;
@@ -1204,8 +1215,11 @@ static int mt_resume(struct hid_device *
 
 static void mt_remove(struct hid_device *hdev)
 {
+	struct mt_device *td = hid_get_drvdata(hdev);
+
 	sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
 	hid_hw_stop(hdev);
+	hdev->quirks = td->initial_quirks;
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-sensor-hub.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-sensor-hub.c
--- linux-libre-4.9-gnu/drivers/hid/hid-sensor-hub.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-sensor-hub.c	2017-02-12 16:03:20.000000000 -0500
@@ -212,7 +212,6 @@ int sensor_hub_set_feature(struct hid_se
 	__s32 value;
 	int ret = 0;
 
-	memset(buffer, 0, buffer_size);
 	mutex_lock(&data->mutex);
 	report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
 	if (!report || (field_index >= report->maxfield)) {
@@ -256,6 +255,8 @@ int sensor_hub_get_feature(struct hid_se
 	int buffer_index = 0;
 	int i;
 
+	memset(buffer, 0, buffer_size);
+
 	mutex_lock(&data->mutex);
 	report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT);
 	if (!report || (field_index >= report->maxfield) ||
@@ -795,6 +796,12 @@ static const struct hid_device_id sensor
 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
 			USB_DEVICE_ID_MS_TYPE_COVER_2),
 			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROSOFT,
+			0x07bd), /* Microsoft Surface 3 */
+			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_MICROCHIP,
+			0x0f01), /* MM7150 */
+			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0,
 			USB_DEVICE_ID_STM_HID_SENSOR),
 			.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-sony.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-sony.c
--- linux-libre-4.9-gnu/drivers/hid/hid-sony.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-sony.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,8 @@
 #include <linux/list.h>
 #include <linux/idr.h>
 #include <linux/input/mt.h>
+#include <linux/crc32.h>
+#include <asm/unaligned.h>
 
 #include "hid-ids.h"
 
@@ -374,7 +376,7 @@ static u8 dualshock4_usb_rdesc[] = {
 	0x65, 0x00,         /*      Unit,                           */
 	0x05, 0x09,         /*      Usage Page (Button),            */
 	0x19, 0x01,         /*      Usage Minimum (01h),            */
-	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
+	0x29, 0x0D,         /*      Usage Maximum (0Dh),            */
 	0x15, 0x00,         /*      Logical Minimum (0),            */
 	0x25, 0x01,         /*      Logical Maximum (1),            */
 	0x75, 0x01,         /*      Report Size (1),                */
@@ -403,14 +405,14 @@ static u8 dualshock4_usb_rdesc[] = {
 	0x19, 0x40,         /*      Usage Minimum (40h),            */
 	0x29, 0x42,         /*      Usage Maximum (42h),            */
 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
-	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
+	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
 	0x75, 0x10,         /*      Report Size (16),               */
 	0x95, 0x03,         /*      Report Count (3),               */
 	0x81, 0x02,         /*      Input (Variable),               */
 	0x19, 0x43,         /*      Usage Minimum (43h),            */
 	0x29, 0x45,         /*      Usage Maximum (45h),            */
-	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
-	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
+	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
+	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
 	0x95, 0x03,         /*      Report Count (3),               */
 	0x81, 0x02,         /*      Input (Variable),               */
 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
@@ -687,7 +689,7 @@ static u8 dualshock4_bt_rdesc[] = {
 	0x81, 0x42,         /*      Input (Variable, Null State),   */
 	0x05, 0x09,         /*      Usage Page (Button),            */
 	0x19, 0x01,         /*      Usage Minimum (01h),            */
-	0x29, 0x0E,         /*      Usage Maximum (0Eh),            */
+	0x29, 0x0D,         /*      Usage Maximum (0Dh),            */
 	0x15, 0x00,         /*      Logical Minimum (0),            */
 	0x25, 0x01,         /*      Logical Maximum (1),            */
 	0x75, 0x01,         /*      Report Size (1),                */
@@ -712,14 +714,14 @@ static u8 dualshock4_bt_rdesc[] = {
 	0x19, 0x40,         /*      Usage Minimum (40h),            */
 	0x29, 0x42,         /*      Usage Maximum (42h),            */
 	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
-	0x26, 0x00, 0x7F,   /*      Logical Maximum (32767),        */
+	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
 	0x75, 0x10,         /*      Report Size (16),               */
 	0x95, 0x03,         /*      Report Count (3),               */
 	0x81, 0x02,         /*      Input (Variable),               */
 	0x19, 0x43,         /*      Usage Minimum (43h),            */
 	0x29, 0x45,         /*      Usage Maximum (45h),            */
-	0x16, 0x00, 0xE0,   /*      Logical Minimum (-8192),        */
-	0x26, 0xFF, 0x1F,   /*      Logical Maximum (8191),         */
+	0x16, 0x00, 0x80,   /*      Logical Minimum (-32768),       */
+	0x26, 0xFF, 0x7F,   /*      Logical Maximum (32767),        */
 	0x95, 0x03,         /*      Report Count (3),               */
 	0x81, 0x02,         /*      Input (Variable),               */
 	0x06, 0x00, 0xFF,   /*      Usage Page (FF00h),             */
@@ -975,6 +977,32 @@ static const unsigned int buzz_keymap[]
 	[20] = BTN_TRIGGER_HAPPY20,
 };
 
+static const unsigned int ds4_absmap[] = {
+	[0x30] = ABS_X,
+	[0x31] = ABS_Y,
+	[0x32] = ABS_RX, /* right stick X */
+	[0x33] = ABS_Z, /* L2 */
+	[0x34] = ABS_RZ, /* R2 */
+	[0x35] = ABS_RY, /* right stick Y */
+};
+
+static const unsigned int ds4_keymap[] = {
+	[0x1] = BTN_WEST, /* Square */
+	[0x2] = BTN_SOUTH, /* Cross */
+	[0x3] = BTN_EAST, /* Circle */
+	[0x4] = BTN_NORTH, /* Triangle */
+	[0x5] = BTN_TL, /* L1 */
+	[0x6] = BTN_TR, /* R1 */
+	[0x7] = BTN_TL2, /* L2 */
+	[0x8] = BTN_TR2, /* R2 */
+	[0x9] = BTN_SELECT, /* Share */
+	[0xa] = BTN_START, /* Options */
+	[0xb] = BTN_THUMBL, /* L3 */
+	[0xc] = BTN_THUMBR, /* R3 */
+	[0xd] = BTN_MODE, /* PS */
+};
+
+
 static enum power_supply_property sony_battery_props[] = {
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_CAPACITY,
@@ -1019,14 +1047,24 @@ struct motion_output_report_02 {
 	u8 rumble;
 };
 
-#define DS4_REPORT_0x02_SIZE 37
-#define DS4_REPORT_0x05_SIZE 32
-#define DS4_REPORT_0x11_SIZE 78
-#define DS4_REPORT_0x81_SIZE 7
+#define DS4_FEATURE_REPORT_0x02_SIZE 37
+#define DS4_FEATURE_REPORT_0x81_SIZE 7
+#define DS4_INPUT_REPORT_0x11_SIZE 78
+#define DS4_OUTPUT_REPORT_0x05_SIZE 32
+#define DS4_OUTPUT_REPORT_0x11_SIZE 78
 #define SIXAXIS_REPORT_0xF2_SIZE 17
 #define SIXAXIS_REPORT_0xF5_SIZE 8
 #define MOTION_REPORT_0x02_SIZE 49
 
+/* Offsets relative to USB input report (0x1). Bluetooth (0x11) requires an
+ * additional +2.
+ */
+#define DS4_INPUT_REPORT_BUTTON_OFFSET    5
+#define DS4_INPUT_REPORT_BATTERY_OFFSET  30
+#define DS4_INPUT_REPORT_TOUCHPAD_OFFSET 33
+
+#define DS4_TOUCHPAD_SUFFIX " Touchpad"
+
 static DEFINE_SPINLOCK(sony_dev_list_lock);
 static LIST_HEAD(sony_device_list);
 static DEFINE_IDA(sony_device_id_allocator);
@@ -1035,6 +1073,7 @@ struct sony_sc {
 	spinlock_t lock;
 	struct list_head list_node;
 	struct hid_device *hdev;
+	struct input_dev *touchpad;
 	struct led_classdev *leds[MAX_LEDS];
 	unsigned long quirks;
 	struct work_struct state_worker;
@@ -1060,8 +1099,11 @@ struct sony_sc {
 	u8 led_delay_on[MAX_LEDS];
 	u8 led_delay_off[MAX_LEDS];
 	u8 led_count;
+	bool ds4_dongle_connected;
 };
 
+static void sony_set_leds(struct sony_sc *sc);
+
 static inline void sony_schedule_work(struct sony_sc *sc)
 {
 	if (!sc->defer_initialization)
@@ -1130,6 +1172,37 @@ static int ps3remote_mapping(struct hid_
 	return 1;
 }
 
+static int ds4_mapping(struct hid_device *hdev, struct hid_input *hi,
+		       struct hid_field *field, struct hid_usage *usage,
+		       unsigned long **bit, int *max)
+{
+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) {
+		unsigned int key = usage->hid & HID_USAGE;
+
+		if (key >= ARRAY_SIZE(ds4_keymap))
+			return -1;
+
+		key = ds4_keymap[key];
+		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key);
+		return 1;
+	} else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_GENDESK) {
+		unsigned int abs = usage->hid & HID_USAGE;
+
+		/* Let the HID parser deal with the HAT. */
+		if (usage->hid == HID_GD_HATSWITCH)
+			return 0;
+
+		if (abs >= ARRAY_SIZE(ds4_absmap))
+			return -1;
+
+		abs = ds4_absmap[abs];
+		hid_map_usage_clear(hi, usage, bit, max, EV_ABS, abs);
+		return 1;
+	}
+
+	return 0;
+}
+
 static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc,
 		unsigned int *rsize)
 {
@@ -1219,23 +1292,22 @@ static void sixaxis_parse_report(struct
 
 static void dualshock4_parse_report(struct sony_sc *sc, u8 *rd, int size)
 {
-	struct hid_input *hidinput = list_entry(sc->hdev->inputs.next,
-						struct hid_input, list);
-	struct input_dev *input_dev = hidinput->input;
 	unsigned long flags;
-	int n, offset;
+	int n, m, offset, num_touch_data, max_touch_data;
 	u8 cable_state, battery_capacity, battery_charging;
 
-	/*
-	 * Battery and touchpad data starts at byte 30 in the USB report and
-	 * 32 in Bluetooth report.
-	 */
-	offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 30 : 32;
+	/* When using Bluetooth the header is 2 bytes longer, so skip these. */
+	int data_offset = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 0 : 2;
+
+	/* Second bit of third button byte is for the touchpad button. */
+	offset = data_offset + DS4_INPUT_REPORT_BUTTON_OFFSET;
+	input_report_key(sc->touchpad, BTN_LEFT, rd[offset+2] & 0x2);
 
 	/*
-	 * The lower 4 bits of byte 30 contain the battery level
+	 * The lower 4 bits of byte 30 (or 32 for BT) contain the battery level
 	 * and the 5th bit contains the USB cable state.
 	 */
+	offset = data_offset + DS4_INPUT_REPORT_BATTERY_OFFSET;
 	cable_state = (rd[offset] >> 4) & 0x01;
 	battery_capacity = rd[offset] & 0x0F;
 
@@ -1262,30 +1334,52 @@ static void dualshock4_parse_report(stru
 	sc->battery_charging = battery_charging;
 	spin_unlock_irqrestore(&sc->lock, flags);
 
-	offset += 5;
-
 	/*
-	 * The Dualshock 4 multi-touch trackpad data starts at offset 35 on USB
-	 * and 37 on Bluetooth.
-	 * The first 7 bits of the first byte is a counter and bit 8 is a touch
-	 * indicator that is 0 when pressed and 1 when not pressed.
-	 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
-	 * The data for the second touch is in the same format and immediatly
-	 * follows the data for the first.
+	 * The Dualshock 4 multi-touch trackpad data starts at offset 33 on USB
+	 * and 35 on Bluetooth.
+	 * The first byte indicates the number of touch data in the report.
+	 * Trackpad data starts 2 bytes later (e.g. 35 for USB).
 	 */
-	for (n = 0; n < 2; n++) {
-		u16 x, y;
+	offset = data_offset + DS4_INPUT_REPORT_TOUCHPAD_OFFSET;
+	max_touch_data = (sc->quirks & DUALSHOCK4_CONTROLLER_USB) ? 3 : 4;
+	if (rd[offset] > 0 && rd[offset] <= max_touch_data)
+		num_touch_data = rd[offset];
+	else
+		num_touch_data = 1;
+	offset += 1;
 
-		x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
-		y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
+	for (m = 0; m < num_touch_data; m++) {
+		/* Skip past timestamp */
+		offset += 1;
 
-		input_mt_slot(input_dev, n);
-		input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
-					!(rd[offset] >> 7));
-		input_report_abs(input_dev, ABS_MT_POSITION_X, x);
-		input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
+		/*
+		 * The first 7 bits of the first byte is a counter and bit 8 is
+		 * a touch indicator that is 0 when pressed and 1 when not
+		 * pressed.
+		 * The next 3 bytes are two 12 bit touch coordinates, X and Y.
+		 * The data for the second touch is in the same format and
+		 * immediately follows the data for the first.
+		 */
+		for (n = 0; n < 2; n++) {
+			u16 x, y;
+			bool active;
 
-		offset += 4;
+			x = rd[offset+1] | ((rd[offset+2] & 0xF) << 8);
+			y = ((rd[offset+2] & 0xF0) >> 4) | (rd[offset+3] << 4);
+
+			active = !(rd[offset] >> 7);
+			input_mt_slot(sc->touchpad, n);
+			input_mt_report_slot_state(sc->touchpad, MT_TOOL_FINGER, active);
+
+			if (active) {
+				input_report_abs(sc->touchpad, ABS_MT_POSITION_X, x);
+				input_report_abs(sc->touchpad, ABS_MT_POSITION_Y, y);
+			}
+
+			offset += 4;
+		}
+		input_mt_sync_frame(sc->touchpad);
+		input_sync(sc->touchpad);
 	}
 }
 
@@ -1324,6 +1418,46 @@ static int sony_raw_event(struct hid_dev
 	} else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 &&
 			size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT)
 			&& rd[0] == 0x11 && size == 78)) {
+		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
+			/* CRC check */
+			u8 bthdr = 0xA1;
+			u32 crc;
+			u32 report_crc;
+
+			crc = crc32_le(0xFFFFFFFF, &bthdr, 1);
+			crc = ~crc32_le(crc, rd, DS4_INPUT_REPORT_0x11_SIZE-4);
+			report_crc = get_unaligned_le32(&rd[DS4_INPUT_REPORT_0x11_SIZE-4]);
+			if (crc != report_crc) {
+				hid_dbg(sc->hdev, "DualShock 4 input report's CRC check failed, received crc 0x%0x != 0x%0x\n",
+					report_crc, crc);
+				return -EILSEQ;
+			}
+		}
+
+		/*
+		 * In the case of a DS4 USB dongle, bit[2] of byte 31 indicates
+		 * if a DS4 is actually connected (indicated by '0').
+		 * For non-dongle, this bit is always 0 (connected).
+		 */
+		if (sc->hdev->vendor == USB_VENDOR_ID_SONY &&
+		    sc->hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) {
+			bool connected = (rd[31] & 0x04) ? false : true;
+
+			if (!sc->ds4_dongle_connected && connected) {
+				hid_info(sc->hdev, "DualShock 4 USB dongle: controller connected\n");
+				sony_set_leds(sc);
+				sc->ds4_dongle_connected = true;
+			} else if (sc->ds4_dongle_connected && !connected) {
+				hid_info(sc->hdev, "DualShock 4 USB dongle: controller disconnected\n");
+				sc->ds4_dongle_connected = false;
+				/* Return 0, so hidraw can get the report. */
+				return 0;
+			} else if (!sc->ds4_dongle_connected) {
+				/* Return 0, so hidraw can get the report. */
+				return 0;
+			}
+		}
+
 		dualshock4_parse_report(sc, rd, size);
 	}
 
@@ -1367,47 +1501,84 @@ static int sony_mapping(struct hid_devic
 	if (sc->quirks & PS3REMOTE)
 		return ps3remote_mapping(hdev, hi, field, usage, bit, max);
 
+
+	if (sc->quirks & DUALSHOCK4_CONTROLLER)
+		return ds4_mapping(hdev, hi, field, usage, bit, max);
+
 	/* Let hid-core decide for the others */
 	return 0;
 }
 
-static int sony_register_touchpad(struct hid_input *hi, int touch_count,
+static int sony_register_touchpad(struct sony_sc *sc, int touch_count,
 					int w, int h)
 {
-	struct input_dev *input_dev = hi->input;
+	size_t name_sz;
+	char *name;
 	int ret;
 
-	ret = input_mt_init_slots(input_dev, touch_count, 0);
+	sc->touchpad = input_allocate_device();
+	if (!sc->touchpad)
+		return -ENOMEM;
+
+	input_set_drvdata(sc->touchpad, sc);
+	sc->touchpad->dev.parent = &sc->hdev->dev;
+	sc->touchpad->phys = sc->hdev->phys;
+	sc->touchpad->uniq = sc->hdev->uniq;
+	sc->touchpad->id.bustype = sc->hdev->bus;
+	sc->touchpad->id.vendor = sc->hdev->vendor;
+	sc->touchpad->id.product = sc->hdev->product;
+	sc->touchpad->id.version = sc->hdev->version;
+
+	/* Append a suffix to the controller name as there are various
+	 * DS4 compatible non-Sony devices with different names.
+	 */
+	name_sz = strlen(sc->hdev->name) + sizeof(DS4_TOUCHPAD_SUFFIX);
+	name = kzalloc(name_sz, GFP_KERNEL);
+	if (!name) {
+		ret = -ENOMEM;
+		goto err;
+	}
+	snprintf(name, name_sz, "%s" DS4_TOUCHPAD_SUFFIX, sc->hdev->name);
+	sc->touchpad->name = name;
+
+	ret = input_mt_init_slots(sc->touchpad, touch_count, 0);
 	if (ret < 0)
-		return ret;
+		goto err;
 
-	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, w, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, h, 0, 0);
+	/* We map the button underneath the touchpad to BTN_LEFT. */
+	__set_bit(EV_KEY, sc->touchpad->evbit);
+	__set_bit(BTN_LEFT, sc->touchpad->keybit);
+	__set_bit(INPUT_PROP_BUTTONPAD, sc->touchpad->propbit);
+
+	input_set_abs_params(sc->touchpad, ABS_MT_POSITION_X, 0, w, 0, 0);
+	input_set_abs_params(sc->touchpad, ABS_MT_POSITION_Y, 0, h, 0, 0);
+
+	ret = input_register_device(sc->touchpad);
+	if (ret < 0)
+		goto err;
 
 	return 0;
+
+err:
+	kfree(sc->touchpad->name);
+	sc->touchpad->name = NULL;
+
+	input_free_device(sc->touchpad);
+	sc->touchpad = NULL;
+
+	return ret;
 }
 
-static int sony_input_configured(struct hid_device *hdev,
-					struct hid_input *hidinput)
+static void sony_unregister_touchpad(struct sony_sc *sc)
 {
-	struct sony_sc *sc = hid_get_drvdata(hdev);
-	int ret;
+	if (!sc->touchpad)
+		return;
 
-	/*
-	 * The Dualshock 4 touchpad supports 2 touches and has a
-	 * resolution of 1920x942 (44.86 dots/mm).
-	 */
-	if (sc->quirks & DUALSHOCK4_CONTROLLER) {
-		ret = sony_register_touchpad(hidinput, 2, 1920, 942);
-		if (ret) {
-			hid_err(sc->hdev,
-				"Unable to initialize multi-touch slots: %d\n",
-				ret);
-			return ret;
-		}
-	}
+	kfree(sc->touchpad->name);
+	sc->touchpad->name = NULL;
 
-	return 0;
+	input_unregister_device(sc->touchpad);
+	sc->touchpad = NULL;
 }
 
 /*
@@ -1483,11 +1654,11 @@ static int dualshock4_set_operational_bt
 	u8 *buf;
 	int ret;
 
-	buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL);
+	buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
-	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE,
+	ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_FEATURE_REPORT_0x02_SIZE,
 				HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
 
 	kfree(buf);
@@ -1892,14 +2063,14 @@ static void dualshock4_send_output_repor
 	 * 0xD0 - 66hz
 	 */
 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
-		memset(buf, 0, DS4_REPORT_0x05_SIZE);
+		memset(buf, 0, DS4_OUTPUT_REPORT_0x05_SIZE);
 		buf[0] = 0x05;
 		buf[1] = 0xFF;
 		offset = 4;
 	} else {
-		memset(buf, 0, DS4_REPORT_0x11_SIZE);
+		memset(buf, 0, DS4_OUTPUT_REPORT_0x11_SIZE);
 		buf[0] = 0x11;
-		buf[1] = 0x80;
+		buf[1] = 0xC0; /* HID + CRC */
 		buf[3] = 0x0F;
 		offset = 6;
 	}
@@ -1925,10 +2096,17 @@ static void dualshock4_send_output_repor
 	buf[offset++] = sc->led_delay_off[3];
 
 	if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
-		hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE);
-	else
-		hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE,
-				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+		hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x05_SIZE);
+	else {
+		/* CRC generation */
+		u8 bthdr = 0xA2;
+		u32 crc;
+
+		crc = crc32_le(0xFFFFFFFF, &bthdr, 1);
+		crc = ~crc32_le(crc, buf, DS4_OUTPUT_REPORT_0x11_SIZE-4);
+		put_unaligned_le32(crc, &buf[74]);
+		hid_hw_output_report(hdev, buf, DS4_OUTPUT_REPORT_0x11_SIZE);
+	}
 }
 
 static void motion_send_output_report(struct sony_sc *sc)
@@ -1972,10 +2150,10 @@ static int sony_allocate_output_report(s
 			kmalloc(sizeof(union sixaxis_output_report_01),
 				GFP_KERNEL);
 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT)
-		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE,
+		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x11_SIZE,
 						GFP_KERNEL);
 	else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB)
-		sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE,
+		sc->output_report_dmabuf = kmalloc(DS4_OUTPUT_REPORT_0x05_SIZE,
 						GFP_KERNEL);
 	else if (sc->quirks & MOTION_CONTROLLER)
 		sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE,
@@ -2220,7 +2398,7 @@ static int sony_check_add(struct sony_sc
 			return 0;
 		}
 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) {
-		buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL);
+		buf = kmalloc(DS4_FEATURE_REPORT_0x81_SIZE, GFP_KERNEL);
 		if (!buf)
 			return -ENOMEM;
 
@@ -2230,16 +2408,22 @@ static int sony_check_add(struct sony_sc
 		 * offset 1.
 		 */
 		ret = hid_hw_raw_request(sc->hdev, 0x81, buf,
-				DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
+				DS4_FEATURE_REPORT_0x81_SIZE, HID_FEATURE_REPORT,
 				HID_REQ_GET_REPORT);
 
-		if (ret != DS4_REPORT_0x81_SIZE) {
+		if (ret != DS4_FEATURE_REPORT_0x81_SIZE) {
 			hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n");
 			ret = ret < 0 ? ret : -EINVAL;
 			goto out_free;
 		}
 
 		memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address));
+
+		snprintf(sc->hdev->uniq, sizeof(sc->hdev->uniq),
+			"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+			sc->mac_address[5], sc->mac_address[4],
+			sc->mac_address[3], sc->mac_address[2],
+			sc->mac_address[1], sc->mac_address[0]);
 	} else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) ||
 			(sc->quirks & NAVIGATION_CONTROLLER_USB)) {
 		buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL);
@@ -2329,45 +2513,12 @@ static inline void sony_cancel_work_sync
 		cancel_work_sync(&sc->state_worker);
 }
 
-static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
+static int sony_input_configured(struct hid_device *hdev,
+					struct hid_input *hidinput)
 {
-	int ret;
+	struct sony_sc *sc = hid_get_drvdata(hdev);
 	int append_dev_id;
-	unsigned long quirks = id->driver_data;
-	struct sony_sc *sc;
-	unsigned int connect_mask = HID_CONNECT_DEFAULT;
-
-	if (!strcmp(hdev->name, "FutureMax Dance Mat"))
-		quirks |= FUTUREMAX_DANCE_MAT;
-
-	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
-	if (sc == NULL) {
-		hid_err(hdev, "can't alloc sony descriptor\n");
-		return -ENOMEM;
-	}
-
-	spin_lock_init(&sc->lock);
-
-	sc->quirks = quirks;
-	hid_set_drvdata(hdev, sc);
-	sc->hdev = hdev;
-
-	ret = hid_parse(hdev);
-	if (ret) {
-		hid_err(hdev, "parse failed\n");
-		return ret;
-	}
-
-	if (sc->quirks & VAIO_RDESC_CONSTANT)
-		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
-	else if (sc->quirks & SIXAXIS_CONTROLLER)
-		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
-
-	ret = hid_hw_start(hdev, connect_mask);
-	if (ret) {
-		hid_err(hdev, "hw start failed\n");
-		return ret;
-	}
+	int ret;
 
 	ret = sony_set_device_id(sc);
 	if (ret < 0) {
@@ -2415,11 +2566,6 @@ static int sony_probe(struct hid_device
 		sony_init_output_report(sc, sixaxis_send_output_report);
 	} else if (sc->quirks & DUALSHOCK4_CONTROLLER) {
 		if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) {
-			/*
-			 * The DualShock 4 wants output reports sent on the ctrl
-			 * endpoint when connected via Bluetooth.
-			 */
-			hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
 			ret = dualshock4_set_operational_bt(hdev);
 			if (ret < 0) {
 				hid_err(hdev, "failed to set the Dualshock 4 operational mode\n");
@@ -2427,6 +2573,18 @@ static int sony_probe(struct hid_device
 			}
 		}
 
+		/*
+		 * The Dualshock 4 touchpad supports 2 touches and has a
+		 * resolution of 1920x942 (44.86 dots/mm).
+		 */
+		ret = sony_register_touchpad(sc, 2, 1920, 942);
+		if (ret) {
+			hid_err(sc->hdev,
+			"Unable to initialize multi-touch slots: %d\n",
+			ret);
+			goto err_stop;
+		}
+
 		sony_init_output_report(sc, dualshock4_send_output_report);
 	} else if (sc->quirks & MOTION_CONTROLLER) {
 		sony_init_output_report(sc, motion_send_output_report);
@@ -2482,17 +2640,84 @@ err_stop:
 	return ret;
 }
 
+static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+	unsigned long quirks = id->driver_data;
+	struct sony_sc *sc;
+	unsigned int connect_mask = HID_CONNECT_DEFAULT;
+
+	if (!strcmp(hdev->name, "FutureMax Dance Mat"))
+		quirks |= FUTUREMAX_DANCE_MAT;
+
+	sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);
+	if (sc == NULL) {
+		hid_err(hdev, "can't alloc sony descriptor\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&sc->lock);
+
+	sc->quirks = quirks;
+	hid_set_drvdata(hdev, sc);
+	sc->hdev = hdev;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		return ret;
+	}
+
+	if (sc->quirks & VAIO_RDESC_CONSTANT)
+		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+	else if (sc->quirks & SIXAXIS_CONTROLLER)
+		connect_mask |= HID_CONNECT_HIDDEV_FORCE;
+
+	/* Patch the hw version on DS4 compatible devices, so applications can
+	 * distinguish between the default HID mappings and the mappings defined
+	 * by the Linux game controller spec. This is important for the SDL2
+	 * library, which has a game controller database, which uses device ids
+	 * in combination with version as a key.
+	 */
+	if (sc->quirks & DUALSHOCK4_CONTROLLER)
+		hdev->version |= 0x8000;
+
+	ret = hid_hw_start(hdev, connect_mask);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		return ret;
+	}
+
+	/* sony_input_configured can fail, but this doesn't result
+	 * in hid_hw_start failures (intended). Check whether
+	 * the HID layer claimed the device else fail.
+	 * We don't know the actual reason for the failure, most
+	 * likely it is due to EEXIST in case of double connection
+	 * of USB and Bluetooth, but could have been due to ENOMEM
+	 * or other reasons as well.
+	 */
+	if (!(hdev->claimed & HID_CLAIMED_INPUT)) {
+		hid_err(hdev, "failed to claim input\n");
+		return -ENODEV;
+	}
+
+	return ret;
+}
+
 static void sony_remove(struct hid_device *hdev)
 {
 	struct sony_sc *sc = hid_get_drvdata(hdev);
 
+	hid_hw_close(hdev);
+
 	if (sc->quirks & SONY_LED_SUPPORT)
 		sony_leds_remove(sc);
 
-	if (sc->quirks & SONY_BATTERY_SUPPORT) {
-		hid_hw_close(hdev);
+	if (sc->quirks & SONY_BATTERY_SUPPORT)
 		sony_battery_remove(sc);
-	}
+
+	if (sc->touchpad)
+		sony_unregister_touchpad(sc);
 
 	sony_cancel_work_sync(sc);
 
@@ -2596,6 +2821,12 @@ static const struct hid_device_id sony_d
 		.driver_data = DUALSHOCK4_CONTROLLER_USB },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER),
 		.driver_data = DUALSHOCK4_CONTROLLER_BT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
+		.driver_data = DUALSHOCK4_CONTROLLER_USB },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2),
+		.driver_data = DUALSHOCK4_CONTROLLER_BT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE),
+		.driver_data = DUALSHOCK4_CONTROLLER_USB },
 	/* Nyko Core Controller for PS3 */
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SINO_LITE, USB_DEVICE_ID_SINO_LITE_CONTROLLER),
 		.driver_data = SIXAXIS_CONTROLLER_USB | SINO_LITE_CONTROLLER },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/hid-udraw-ps3.c linux-libre-4.10-rc8-gnu/drivers/hid/hid-udraw-ps3.c
--- linux-libre-4.9-gnu/drivers/hid/hid-udraw-ps3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/hid-udraw-ps3.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,474 @@
+/*
+ * HID driver for THQ PS3 uDraw tablet
+ *
+ * Copyright (C) 2016 Red Hat Inc. All Rights Reserved
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include "hid-ids.h"
+
+MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_DESCRIPTION("PS3 uDraw tablet driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Protocol information from:
+ * http://brandonw.net/udraw/
+ * and the source code of:
+ * https://vvvv.org/contribution/udraw-hid
+ */
+
+/*
+ * The device is setup with multiple input devices:
+ * - the touch area which works as a touchpad
+ * - the tablet area which works as a touchpad/drawing tablet
+ * - a joypad with a d-pad, and 7 buttons
+ * - an accelerometer device
+ */
+
+enum {
+	TOUCH_NONE,
+	TOUCH_PEN,
+	TOUCH_FINGER,
+	TOUCH_TWOFINGER
+};
+
+enum {
+	AXIS_X,
+	AXIS_Y,
+	AXIS_Z
+};
+
+/*
+ * Accelerometer min/max values
+ * in order, X, Y and Z
+ */
+static struct {
+	int min;
+	int max;
+} accel_limits[] = {
+	[AXIS_X] = { 490, 534 },
+	[AXIS_Y] = { 490, 534 },
+	[AXIS_Z] = { 492, 536 }
+};
+
+#define DEVICE_NAME "THQ uDraw Game Tablet for PS3"
+/* resolution in pixels */
+#define RES_X 1920
+#define RES_Y 1080
+/* size in mm */
+#define WIDTH  160
+#define HEIGHT 90
+#define PRESSURE_OFFSET 113
+#define MAX_PRESSURE (255 - PRESSURE_OFFSET)
+
+struct udraw {
+	struct input_dev *joy_input_dev;
+	struct input_dev *touch_input_dev;
+	struct input_dev *pen_input_dev;
+	struct input_dev *accel_input_dev;
+	struct hid_device *hdev;
+
+	/*
+	 * The device's two-finger support is pretty unreliable, as
+	 * the device could report a single touch when the two fingers
+	 * are too close together, and the distance between fingers, even
+	 * though reported is not in the same unit as the touches.
+	 *
+	 * We'll make do without it, and try to report the first touch
+	 * as reliably as possible.
+	 */
+	int last_one_finger_x;
+	int last_one_finger_y;
+	int last_two_finger_x;
+	int last_two_finger_y;
+};
+
+static int clamp_accel(int axis, int offset)
+{
+	axis = clamp(axis,
+			accel_limits[offset].min,
+			accel_limits[offset].max);
+	axis = (axis - accel_limits[offset].min) /
+			((accel_limits[offset].max -
+			  accel_limits[offset].min) * 0xFF);
+	return axis;
+}
+
+static int udraw_raw_event(struct hid_device *hdev, struct hid_report *report,
+	 u8 *data, int len)
+{
+	struct udraw *udraw = hid_get_drvdata(hdev);
+	int touch;
+	int x, y, z;
+
+	if (len != 27)
+		return 0;
+
+	if (data[11] == 0x00)
+		touch = TOUCH_NONE;
+	else if (data[11] == 0x40)
+		touch = TOUCH_PEN;
+	else if (data[11] == 0x80)
+		touch = TOUCH_FINGER;
+	else
+		touch = TOUCH_TWOFINGER;
+
+	/* joypad */
+	input_report_key(udraw->joy_input_dev, BTN_WEST, data[0] & 1);
+	input_report_key(udraw->joy_input_dev, BTN_SOUTH, !!(data[0] & 2));
+	input_report_key(udraw->joy_input_dev, BTN_EAST, !!(data[0] & 4));
+	input_report_key(udraw->joy_input_dev, BTN_NORTH, !!(data[0] & 8));
+
+	input_report_key(udraw->joy_input_dev, BTN_SELECT, !!(data[1] & 1));
+	input_report_key(udraw->joy_input_dev, BTN_START, !!(data[1] & 2));
+	input_report_key(udraw->joy_input_dev, BTN_MODE, !!(data[1] & 16));
+
+	x = y = 0;
+	switch (data[2]) {
+	case 0x0:
+		y = -127;
+		break;
+	case 0x1:
+		y = -127;
+		x = 127;
+		break;
+	case 0x2:
+		x = 127;
+		break;
+	case 0x3:
+		y = 127;
+		x = 127;
+		break;
+	case 0x4:
+		y = 127;
+		break;
+	case 0x5:
+		y = 127;
+		x = -127;
+		break;
+	case 0x6:
+		x = -127;
+		break;
+	case 0x7:
+		y = -127;
+		x = -127;
+		break;
+	default:
+		break;
+	}
+
+	input_report_abs(udraw->joy_input_dev, ABS_X, x);
+	input_report_abs(udraw->joy_input_dev, ABS_Y, y);
+
+	input_sync(udraw->joy_input_dev);
+
+	/* For pen and touchpad */
+	x = y = 0;
+	if (touch != TOUCH_NONE) {
+		if (data[15] != 0x0F)
+			x = data[15] * 256 + data[17];
+		if (data[16] != 0x0F)
+			y = data[16] * 256 + data[18];
+	}
+
+	if (touch == TOUCH_FINGER) {
+		/* Save the last one-finger touch */
+		udraw->last_one_finger_x = x;
+		udraw->last_one_finger_y = y;
+		udraw->last_two_finger_x = -1;
+		udraw->last_two_finger_y = -1;
+	} else if (touch == TOUCH_TWOFINGER) {
+		/*
+		 * We have a problem because x/y is the one for the
+		 * second finger but we want the first finger given
+		 * to user-space otherwise it'll look as if it jumped.
+		 *
+		 * See the udraw struct definition for why this was
+		 * implemented this way.
+		 */
+		if (udraw->last_two_finger_x == -1) {
+			/* Save the position of the 2nd finger */
+			udraw->last_two_finger_x = x;
+			udraw->last_two_finger_y = y;
+
+			x = udraw->last_one_finger_x;
+			y = udraw->last_one_finger_y;
+		} else {
+			/*
+			 * Offset the 2-finger coords using the
+			 * saved data from the first finger
+			 */
+			x = x - (udraw->last_two_finger_x
+				- udraw->last_one_finger_x);
+			y = y - (udraw->last_two_finger_y
+				- udraw->last_one_finger_y);
+		}
+	}
+
+	/* touchpad */
+	if (touch == TOUCH_FINGER || touch == TOUCH_TWOFINGER) {
+		input_report_key(udraw->touch_input_dev, BTN_TOUCH, 1);
+		input_report_key(udraw->touch_input_dev, BTN_TOOL_FINGER,
+				touch == TOUCH_FINGER);
+		input_report_key(udraw->touch_input_dev, BTN_TOOL_DOUBLETAP,
+				touch == TOUCH_TWOFINGER);
+
+		input_report_abs(udraw->touch_input_dev, ABS_X, x);
+		input_report_abs(udraw->touch_input_dev, ABS_Y, y);
+	} else {
+		input_report_key(udraw->touch_input_dev, BTN_TOUCH, 0);
+		input_report_key(udraw->touch_input_dev, BTN_TOOL_FINGER, 0);
+		input_report_key(udraw->touch_input_dev, BTN_TOOL_DOUBLETAP, 0);
+	}
+	input_sync(udraw->touch_input_dev);
+
+	/* pen */
+	if (touch == TOUCH_PEN) {
+		int level;
+
+		level = clamp(data[13] - PRESSURE_OFFSET,
+				0, MAX_PRESSURE);
+
+		input_report_key(udraw->pen_input_dev, BTN_TOUCH, (level != 0));
+		input_report_key(udraw->pen_input_dev, BTN_TOOL_PEN, 1);
+		input_report_abs(udraw->pen_input_dev, ABS_PRESSURE, level);
+		input_report_abs(udraw->pen_input_dev, ABS_X, x);
+		input_report_abs(udraw->pen_input_dev, ABS_Y, y);
+	} else {
+		input_report_key(udraw->pen_input_dev, BTN_TOUCH, 0);
+		input_report_key(udraw->pen_input_dev, BTN_TOOL_PEN, 0);
+		input_report_abs(udraw->pen_input_dev, ABS_PRESSURE, 0);
+	}
+	input_sync(udraw->pen_input_dev);
+
+	/* accel */
+	x = (data[19] + (data[20] << 8));
+	x = clamp_accel(x, AXIS_X);
+	y = (data[21] + (data[22] << 8));
+	y = clamp_accel(y, AXIS_Y);
+	z = (data[23] + (data[24] << 8));
+	z = clamp_accel(z, AXIS_Z);
+	input_report_abs(udraw->accel_input_dev, ABS_X, x);
+	input_report_abs(udraw->accel_input_dev, ABS_Y, y);
+	input_report_abs(udraw->accel_input_dev, ABS_Z, z);
+	input_sync(udraw->accel_input_dev);
+
+	/* let hidraw and hiddev handle the report */
+	return 0;
+}
+
+static int udraw_open(struct input_dev *dev)
+{
+	struct udraw *udraw = input_get_drvdata(dev);
+
+	return hid_hw_open(udraw->hdev);
+}
+
+static void udraw_close(struct input_dev *dev)
+{
+	struct udraw *udraw = input_get_drvdata(dev);
+
+	hid_hw_close(udraw->hdev);
+}
+
+static struct input_dev *allocate_and_setup(struct hid_device *hdev,
+		const char *name)
+{
+	struct input_dev *input_dev;
+
+	input_dev = devm_input_allocate_device(&hdev->dev);
+	if (!input_dev)
+		return NULL;
+
+	input_dev->name = name;
+	input_dev->phys = hdev->phys;
+	input_dev->dev.parent = &hdev->dev;
+	input_dev->open = udraw_open;
+	input_dev->close = udraw_close;
+	input_dev->uniq = hdev->uniq;
+	input_dev->id.bustype = hdev->bus;
+	input_dev->id.vendor  = hdev->vendor;
+	input_dev->id.product = hdev->product;
+	input_dev->id.version = hdev->version;
+	input_set_drvdata(input_dev, hid_get_drvdata(hdev));
+
+	return input_dev;
+}
+
+static bool udraw_setup_touch(struct udraw *udraw,
+		struct hid_device *hdev)
+{
+	struct input_dev *input_dev;
+
+	input_dev = allocate_and_setup(hdev, DEVICE_NAME " Touchpad");
+	if (!input_dev)
+		return false;
+
+	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+
+	input_set_abs_params(input_dev, ABS_X, 0, RES_X, 1, 0);
+	input_abs_set_res(input_dev, ABS_X, RES_X / WIDTH);
+	input_set_abs_params(input_dev, ABS_Y, 0, RES_Y, 1, 0);
+	input_abs_set_res(input_dev, ABS_Y, RES_Y / HEIGHT);
+
+	set_bit(BTN_TOUCH, input_dev->keybit);
+	set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+	set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+
+	set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
+	udraw->touch_input_dev = input_dev;
+
+	return true;
+}
+
+static bool udraw_setup_pen(struct udraw *udraw,
+		struct hid_device *hdev)
+{
+	struct input_dev *input_dev;
+
+	input_dev = allocate_and_setup(hdev, DEVICE_NAME " Pen");
+	if (!input_dev)
+		return false;
+
+	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+
+	input_set_abs_params(input_dev, ABS_X, 0, RES_X, 1, 0);
+	input_abs_set_res(input_dev, ABS_X, RES_X / WIDTH);
+	input_set_abs_params(input_dev, ABS_Y, 0, RES_Y, 1, 0);
+	input_abs_set_res(input_dev, ABS_Y, RES_Y / HEIGHT);
+	input_set_abs_params(input_dev, ABS_PRESSURE,
+			0, MAX_PRESSURE, 0, 0);
+
+	set_bit(BTN_TOUCH, input_dev->keybit);
+	set_bit(BTN_TOOL_PEN, input_dev->keybit);
+
+	set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
+	udraw->pen_input_dev = input_dev;
+
+	return true;
+}
+
+static bool udraw_setup_accel(struct udraw *udraw,
+		struct hid_device *hdev)
+{
+	struct input_dev *input_dev;
+
+	input_dev = allocate_and_setup(hdev, DEVICE_NAME " Accelerometer");
+	if (!input_dev)
+		return false;
+
+	input_dev->evbit[0] = BIT(EV_ABS);
+
+	/* 1G accel is reported as ~256, so clamp to 2G */
+	input_set_abs_params(input_dev, ABS_X, -512, 512, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, -512, 512, 0, 0);
+	input_set_abs_params(input_dev, ABS_Z, -512, 512, 0, 0);
+
+	set_bit(INPUT_PROP_ACCELEROMETER, input_dev->propbit);
+
+	udraw->accel_input_dev = input_dev;
+
+	return true;
+}
+
+static bool udraw_setup_joypad(struct udraw *udraw,
+		struct hid_device *hdev)
+{
+	struct input_dev *input_dev;
+
+	input_dev = allocate_and_setup(hdev, DEVICE_NAME " Joypad");
+	if (!input_dev)
+		return false;
+
+	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+
+	set_bit(BTN_SOUTH, input_dev->keybit);
+	set_bit(BTN_NORTH, input_dev->keybit);
+	set_bit(BTN_EAST, input_dev->keybit);
+	set_bit(BTN_WEST, input_dev->keybit);
+	set_bit(BTN_SELECT, input_dev->keybit);
+	set_bit(BTN_START, input_dev->keybit);
+	set_bit(BTN_MODE, input_dev->keybit);
+
+	input_set_abs_params(input_dev, ABS_X, -127, 127, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, -127, 127, 0, 0);
+
+	udraw->joy_input_dev = input_dev;
+
+	return true;
+}
+
+static int udraw_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	struct udraw *udraw;
+	int ret;
+
+	udraw = devm_kzalloc(&hdev->dev, sizeof(struct udraw), GFP_KERNEL);
+	if (!udraw)
+		return -ENOMEM;
+
+	udraw->hdev = hdev;
+	udraw->last_two_finger_x = -1;
+	udraw->last_two_finger_y = -1;
+
+	hid_set_drvdata(hdev, udraw);
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		return ret;
+	}
+
+	if (!udraw_setup_joypad(udraw, hdev) ||
+	    !udraw_setup_touch(udraw, hdev) ||
+	    !udraw_setup_pen(udraw, hdev) ||
+	    !udraw_setup_accel(udraw, hdev)) {
+		hid_err(hdev, "could not allocate interfaces\n");
+		return -ENOMEM;
+	}
+
+	ret = input_register_device(udraw->joy_input_dev) ||
+		input_register_device(udraw->touch_input_dev) ||
+		input_register_device(udraw->pen_input_dev) ||
+		input_register_device(udraw->accel_input_dev);
+	if (ret) {
+		hid_err(hdev, "failed to register interfaces\n");
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW | HID_CONNECT_DRIVER);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct hid_device_id udraw_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, udraw_devices);
+
+static struct hid_driver udraw_driver = {
+	.name = "hid-udraw",
+	.id_table = udraw_devices,
+	.raw_event = udraw_raw_event,
+	.probe = udraw_probe,
+};
+module_hid_driver(udraw_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/i2c-hid/i2c-hid.c linux-libre-4.10-rc8-gnu/drivers/hid/i2c-hid/i2c-hid.c
--- linux-libre-4.9-gnu/drivers/hid/i2c-hid/i2c-hid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/i2c-hid/i2c-hid.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/input.h>
+#include <linux/irq.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
@@ -37,10 +38,15 @@
 #include <linux/mutex.h>
 #include <linux/acpi.h>
 #include <linux/of.h>
-#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/i2c/i2c-hid.h>
 
+#include "../hid-ids.h"
+
+/* quirks to control the device */
+#define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV	BIT(0)
+
 /* flags */
 #define I2C_HID_STARTED		0
 #define I2C_HID_RESET_PENDING	1
@@ -143,10 +149,9 @@ struct i2c_hid {
 	char			*argsbuf;	/* Command arguments buffer */
 
 	unsigned long		flags;		/* device flags */
+	unsigned long		quirks;		/* Various quirks */
 
 	wait_queue_head_t	wait;		/* For waiting the interrupt */
-	struct gpio_desc	*desc;
-	int			irq;
 
 	struct i2c_hid_platform_data pdata;
 
@@ -154,6 +159,39 @@ struct i2c_hid {
 	struct mutex		reset_lock;
 };
 
+static const struct i2c_hid_quirks {
+	__u16 idVendor;
+	__u16 idProduct;
+	__u32 quirks;
+} i2c_hid_quirks[] = {
+	{ USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8752,
+		I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
+	{ USB_VENDOR_ID_WEIDA, USB_DEVICE_ID_WEIDA_8755,
+		I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
+	{ 0, 0 }
+};
+
+/*
+ * i2c_hid_lookup_quirk: return any quirks associated with a I2C HID device
+ * @idVendor: the 16-bit vendor ID
+ * @idProduct: the 16-bit product ID
+ *
+ * Returns: a u32 quirks value.
+ */
+static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
+{
+	u32 quirks = 0;
+	int n;
+
+	for (n = 0; i2c_hid_quirks[n].idVendor; n++)
+		if (i2c_hid_quirks[n].idVendor == idVendor &&
+		    (i2c_hid_quirks[n].idProduct == (__u16)HID_ANY_ID ||
+		     i2c_hid_quirks[n].idProduct == idProduct))
+			quirks = i2c_hid_quirks[n].quirks;
+
+	return quirks;
+}
+
 static int __i2c_hid_command(struct i2c_client *client,
 		const struct i2c_hid_cmd *command, u8 reportID,
 		u8 reportType, u8 *args, int args_len,
@@ -346,11 +384,27 @@ static int i2c_hid_set_power(struct i2c_
 
 	i2c_hid_dbg(ihid, "%s\n", __func__);
 
+	/*
+	 * Some devices require to send a command to wakeup before power on.
+	 * The call will get a return value (EREMOTEIO) but device will be
+	 * triggered and activated. After that, it goes like a normal device.
+	 */
+	if (power_state == I2C_HID_PWR_ON &&
+	    ihid->quirks & I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV) {
+		ret = i2c_hid_command(client, &hid_set_power_cmd, NULL, 0);
+
+		/* Device was already activated */
+		if (!ret)
+			goto set_pwr_exit;
+	}
+
 	ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,
 		0, NULL, 0, NULL, 0);
+
 	if (ret)
 		dev_err(&client->dev, "failed to change power setting.\n");
 
+set_pwr_exit:
 	return ret;
 }
 
@@ -372,6 +426,15 @@ static int i2c_hid_hwreset(struct i2c_cl
 	if (ret)
 		goto out_unlock;
 
+	/*
+	 * The HID over I2C specification states that if a DEVICE needs time
+	 * after the PWR_ON request, it should utilise CLOCK stretching.
+	 * However, it has been observered that the Windows driver provides a
+	 * 1ms sleep between the PWR_ON and RESET requests and that some devices
+	 * rely on this.
+	 */
+	usleep_range(1000, 5000);
+
 	i2c_hid_dbg(ihid, "resetting...\n");
 
 	ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
@@ -716,9 +779,11 @@ static int i2c_hid_start(struct hid_devi
 	i2c_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize);
 
 	if (bufsize > ihid->bufsize) {
+		disable_irq(client->irq);
 		i2c_hid_free_buffers(ihid);
 
 		ret = i2c_hid_alloc_buffers(ihid, bufsize);
+		enable_irq(client->irq);
 
 		if (ret)
 			return ret;
@@ -806,18 +871,21 @@ static struct hid_ll_driver i2c_hid_ll_d
 static int i2c_hid_init_irq(struct i2c_client *client)
 {
 	struct i2c_hid *ihid = i2c_get_clientdata(client);
+	unsigned long irqflags = 0;
 	int ret;
 
-	dev_dbg(&client->dev, "Requesting IRQ: %d\n", ihid->irq);
+	dev_dbg(&client->dev, "Requesting IRQ: %d\n", client->irq);
 
-	ret = request_threaded_irq(ihid->irq, NULL, i2c_hid_irq,
-			IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-			client->name, ihid);
+	if (!irq_get_trigger_type(client->irq))
+		irqflags = IRQF_TRIGGER_LOW;
+
+	ret = request_threaded_irq(client->irq, NULL, i2c_hid_irq,
+				   irqflags | IRQF_ONESHOT, client->name, ihid);
 	if (ret < 0) {
 		dev_warn(&client->dev,
 			"Could not register for %s interrupt, irq = %d,"
 			" ret = %d\n",
-			client->name, ihid->irq, ret);
+			client->name, client->irq, ret);
 
 		return ret;
 	}
@@ -864,14 +932,6 @@ static int i2c_hid_fetch_hid_descriptor(
 }
 
 #ifdef CONFIG_ACPI
-
-/* Default GPIO mapping */
-static const struct acpi_gpio_params i2c_hid_irq_gpio = { 0, 0, true };
-static const struct acpi_gpio_mapping i2c_hid_acpi_gpios[] = {
-	{ "gpios", &i2c_hid_irq_gpio, 1 },
-	{ },
-};
-
 static int i2c_hid_acpi_pdata(struct i2c_client *client,
 		struct i2c_hid_platform_data *pdata)
 {
@@ -882,7 +942,6 @@ static int i2c_hid_acpi_pdata(struct i2c
 	union acpi_object *obj;
 	struct acpi_device *adev;
 	acpi_handle handle;
-	int ret;
 
 	handle = ACPI_HANDLE(&client->dev);
 	if (!handle || acpi_bus_get_device(handle, &adev))
@@ -898,9 +957,7 @@ static int i2c_hid_acpi_pdata(struct i2c
 	pdata->hid_descriptor_address = obj->integer.value;
 	ACPI_FREE(obj);
 
-	/* GPIOs are optional */
-	ret = acpi_dev_add_driver_gpios(adev, i2c_hid_acpi_gpios);
-	return ret < 0 && ret != -ENXIO ? ret : 0;
+	return 0;
 }
 
 static const struct acpi_device_id i2c_hid_acpi_match[] = {
@@ -964,6 +1021,19 @@ static int i2c_hid_probe(struct i2c_clie
 
 	dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
 
+	if (!client->irq) {
+		dev_err(&client->dev,
+			"HID over i2c has not been provided an Int IRQ\n");
+		return -EINVAL;
+	}
+
+	if (client->irq < 0) {
+		if (client->irq != -EPROBE_DEFER)
+			dev_err(&client->dev,
+				"HID over i2c doesn't have a valid IRQ\n");
+		return client->irq;
+	}
+
 	ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
 	if (!ihid)
 		return -ENOMEM;
@@ -983,23 +1053,6 @@ static int i2c_hid_probe(struct i2c_clie
 		ihid->pdata = *platform_data;
 	}
 
-	if (client->irq > 0) {
-		ihid->irq = client->irq;
-	} else if (ACPI_COMPANION(&client->dev)) {
-		ihid->desc = gpiod_get(&client->dev, NULL, GPIOD_IN);
-		if (IS_ERR(ihid->desc)) {
-			dev_err(&client->dev, "Failed to get GPIO interrupt\n");
-			return PTR_ERR(ihid->desc);
-		}
-
-		ihid->irq = gpiod_to_irq(ihid->desc);
-		if (ihid->irq < 0) {
-			gpiod_put(ihid->desc);
-			dev_err(&client->dev, "Failed to convert GPIO to IRQ\n");
-			return ihid->irq;
-		}
-	}
-
 	i2c_set_clientdata(client, ihid);
 
 	ihid->client = client;
@@ -1050,6 +1103,8 @@ static int i2c_hid_probe(struct i2c_clie
 		 client->name, hid->vendor, hid->product);
 	strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
 
+	ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
+
 	ret = hid_add_device(hid);
 	if (ret) {
 		if (ret != -ENODEV)
@@ -1064,16 +1119,13 @@ err_mem_free:
 	hid_destroy_device(hid);
 
 err_irq:
-	free_irq(ihid->irq, ihid);
+	free_irq(client->irq, ihid);
 
 err_pm:
 	pm_runtime_put_noidle(&client->dev);
 	pm_runtime_disable(&client->dev);
 
 err:
-	if (ihid->desc)
-		gpiod_put(ihid->desc);
-
 	i2c_hid_free_buffers(ihid);
 	kfree(ihid);
 	return ret;
@@ -1092,18 +1144,13 @@ static int i2c_hid_remove(struct i2c_cli
 	hid = ihid->hid;
 	hid_destroy_device(hid);
 
-	free_irq(ihid->irq, ihid);
+	free_irq(client->irq, ihid);
 
 	if (ihid->bufsize)
 		i2c_hid_free_buffers(ihid);
 
-	if (ihid->desc)
-		gpiod_put(ihid->desc);
-
 	kfree(ihid);
 
-	acpi_dev_remove_driver_gpios(ACPI_COMPANION(&client->dev));
-
 	return 0;
 }
 
@@ -1142,11 +1189,11 @@ static int i2c_hid_suspend(struct device
 		/* Save some power */
 		i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
 
-		disable_irq(ihid->irq);
+		disable_irq(client->irq);
 	}
 
 	if (device_may_wakeup(&client->dev)) {
-		wake_status = enable_irq_wake(ihid->irq);
+		wake_status = enable_irq_wake(client->irq);
 		if (!wake_status)
 			ihid->irq_wake_enabled = true;
 		else
@@ -1166,7 +1213,7 @@ static int i2c_hid_resume(struct device
 	int wake_status;
 
 	if (device_may_wakeup(&client->dev) && ihid->irq_wake_enabled) {
-		wake_status = disable_irq_wake(ihid->irq);
+		wake_status = disable_irq_wake(client->irq);
 		if (!wake_status)
 			ihid->irq_wake_enabled = false;
 		else
@@ -1179,7 +1226,7 @@ static int i2c_hid_resume(struct device
 	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
 
-	enable_irq(ihid->irq);
+	enable_irq(client->irq);
 	ret = i2c_hid_hwreset(client);
 	if (ret)
 		return ret;
@@ -1197,19 +1244,17 @@ static int i2c_hid_resume(struct device
 static int i2c_hid_runtime_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	struct i2c_hid *ihid = i2c_get_clientdata(client);
 
 	i2c_hid_set_power(client, I2C_HID_PWR_SLEEP);
-	disable_irq(ihid->irq);
+	disable_irq(client->irq);
 	return 0;
 }
 
 static int i2c_hid_runtime_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	struct i2c_hid *ihid = i2c_get_clientdata(client);
 
-	enable_irq(ihid->irq);
+	enable_irq(client->irq);
 	i2c_hid_set_power(client, I2C_HID_PWR_ON);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ipc/ipc.c linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ipc/ipc.c
--- linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ipc/ipc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ipc/ipc.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,6 @@
 #include <linux/jiffies.h>
 #include "client.h"
 #include "hw-ish.h"
-#include "utils.h"
 #include "hbm.h"
 
 /* For FW reset flow */
@@ -310,6 +309,7 @@ static int write_ipc_from_queue(struct i
 						((uint32_t)tv_utc.tv_usec);
 		ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
 		ts_format.ts2_source = HOST_UTC_TIME_USEC;
+		ts_format.reserved = 0;
 
 		time_update.primary_host_time = usec_system;
 		time_update.secondary_host_time = usec_utc;
@@ -427,6 +427,59 @@ static int ipc_send_mng_msg(struct ishtp
 		sizeof(uint32_t) + size);
 }
 
+#define WAIT_FOR_FW_RDY			0x1
+#define WAIT_FOR_INPUT_RDY		0x2
+
+/**
+ * timed_wait_for_timeout() - wait special event with timeout
+ * @dev: ISHTP device pointer
+ * @condition: indicate the condition for waiting
+ * @timeinc: time slice for every wait cycle, in ms
+ * @timeout: time in ms for timeout
+ *
+ * This function will check special event to be ready in a loop, the loop
+ * period is specificd in timeinc. Wait timeout will causes failure.
+ *
+ * Return: 0 for success else failure code
+ */
+static int timed_wait_for_timeout(struct ishtp_device *dev, int condition,
+				unsigned int timeinc, unsigned int timeout)
+{
+	bool complete = false;
+	int ret;
+
+	do {
+		if (condition == WAIT_FOR_FW_RDY) {
+			complete = ishtp_fw_is_ready(dev);
+		} else if (condition == WAIT_FOR_INPUT_RDY) {
+			complete = ish_is_input_ready(dev);
+		} else {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (!complete) {
+			unsigned long left_time;
+
+			left_time = msleep_interruptible(timeinc);
+			timeout -= (timeinc - left_time);
+		}
+	} while (!complete && timeout > 0);
+
+	if (complete)
+		ret = 0;
+	else
+		ret = -EBUSY;
+
+out:
+	return ret;
+}
+
+#define TIME_SLICE_FOR_FW_RDY_MS		100
+#define TIME_SLICE_FOR_INPUT_RDY_MS		100
+#define TIMEOUT_FOR_FW_RDY_MS			2000
+#define TIMEOUT_FOR_INPUT_RDY_MS		2000
+
 /**
  * ish_fw_reset_handler() - FW reset handler
  * @dev: ishtp device pointer
@@ -456,8 +509,8 @@ static int ish_fw_reset_handler(struct i
 	ishtp_reset_handler(dev);
 
 	if (!ish_is_input_ready(dev))
-		timed_wait_for_timeout(WAIT_FOR_SEND_SLICE,
-			ish_is_input_ready(dev), (2 * HZ));
+		timed_wait_for_timeout(dev, WAIT_FOR_INPUT_RDY,
+			TIME_SLICE_FOR_INPUT_RDY_MS, TIMEOUT_FOR_INPUT_RDY_MS);
 
 	/* ISH FW is dead */
 	if (!ish_is_input_ready(dev))
@@ -472,8 +525,8 @@ static int ish_fw_reset_handler(struct i
 			 sizeof(uint32_t));
 
 	/* Wait for ISH FW'es ILUP and ISHTP_READY */
-	timed_wait_for_timeout(WAIT_FOR_SEND_SLICE, ishtp_fw_is_ready(dev),
-		(2 * HZ));
+	timed_wait_for_timeout(dev, WAIT_FOR_FW_RDY,
+			TIME_SLICE_FOR_FW_RDY_MS, TIMEOUT_FOR_FW_RDY_MS);
 	if (!ishtp_fw_is_ready(dev)) {
 		/* ISH FW is dead */
 		uint32_t	ish_status;
@@ -487,6 +540,8 @@ static int ish_fw_reset_handler(struct i
 	return	0;
 }
 
+#define TIMEOUT_FOR_HW_RDY_MS			300
+
 /**
  * ish_fw_reset_work_fn() - FW reset worker function
  * @unused: not used
@@ -500,7 +555,7 @@ static void fw_reset_work_fn(struct work
 	rv = ish_fw_reset_handler(ishtp_dev);
 	if (!rv) {
 		/* ISH is ILUP & ISHTP-ready. Restart ISHTP */
-		schedule_timeout(HZ / 3);
+		msleep_interruptible(TIMEOUT_FOR_HW_RDY_MS);
 		ishtp_dev->recvd_hw_ready = 1;
 		wake_up_interruptible(&ishtp_dev->wait_hw_ready);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ipc/utils.h linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ipc/utils.h
--- linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ipc/utils.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ipc/utils.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-/*
- * Utility macros of ISH
- *
- * Copyright (c) 2014-2016, 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.
- */
-#ifndef UTILS__H
-#define UTILS__H
-
-#define	WAIT_FOR_SEND_SLICE	(HZ / 10)
-#define	WAIT_FOR_CONNECT_SLICE	(HZ / 10)
-
-/*
- * Waits for specified event when a thread that triggers event can't signal
- * Also, waits *at_least* `timeinc` after condition is satisfied
- */
-#define	timed_wait_for(timeinc, condition)			\
-	do {							\
-		int completed = 0;				\
-		do {						\
-			unsigned long	j;			\
-			int	done = 0;			\
-								\
-			completed = (condition);		\
-			for (j = jiffies, done = 0; !done; ) {	\
-				schedule_timeout(timeinc);	\
-				if (time_is_before_eq_jiffies(j + timeinc)) \
-					done = 1;		\
-			}					\
-		} while (!(completed));				\
-	} while (0)
-
-
-/*
- * Waits for specified event when a thread that triggers event
- * can't signal with timeout (use whenever we may hang)
- */
-#define	timed_wait_for_timeout(timeinc, condition, timeout)	\
-	do {							\
-		int	t = timeout;				\
-		do {						\
-			unsigned long	j;			\
-			int	done = 0;			\
-								\
-			for (j = jiffies, done = 0; !done; ) {	\
-				schedule_timeout(timeinc);	\
-				if (time_is_before_eq_jiffies(j + timeinc)) \
-					done = 1;		\
-			} \
-			t -= timeinc;				\
-			if (t <= 0)				\
-				break;				\
-		} while (!(condition));				\
-	} while (0)
-
-#endif /* UTILS__H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ishtp/bus.c linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ishtp/bus.c
--- linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ishtp/bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ishtp/bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -585,14 +585,7 @@ int ishtp_bus_new_client(struct ishtp_de
 	 */
 	i = dev->fw_client_presentation_num - 1;
 	device_uuid = dev->fw_clients[i].props.protocol_name;
-	dev_name = kasprintf(GFP_KERNEL,
-		"{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
-		device_uuid.b[3], device_uuid.b[2], device_uuid.b[1],
-		device_uuid.b[0], device_uuid.b[5], device_uuid.b[4],
-		device_uuid.b[7], device_uuid.b[6], device_uuid.b[8],
-		device_uuid.b[9], device_uuid.b[10], device_uuid.b[11],
-		device_uuid.b[12], device_uuid.b[13], device_uuid.b[14],
-		device_uuid.b[15]);
+	dev_name = kasprintf(GFP_KERNEL, "{%pUL}", device_uuid.b);
 	if (!dev_name)
 		return	-ENOMEM;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ishtp/hbm.c linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ishtp/hbm.c
--- linux-libre-4.9-gnu/drivers/hid/intel-ish-hid/ishtp/hbm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/intel-ish-hid/ishtp/hbm.c	2017-02-12 16:03:20.000000000 -0500
@@ -378,11 +378,10 @@ static void ishtp_hbm_cl_disconnect_res(
 	list_for_each_entry(cl, &dev->cl_list, link) {
 		if (!rs->status && ishtp_hbm_cl_addr_equal(cl, rs)) {
 			cl->state = ISHTP_CL_DISCONNECTED;
+			wake_up_interruptible(&cl->wait_ctrl_res);
 			break;
 		}
 	}
-	if (cl)
-		wake_up_interruptible(&cl->wait_ctrl_res);
 	spin_unlock_irqrestore(&dev->cl_list_lock, flags);
 }
 
@@ -431,11 +430,10 @@ static void ishtp_hbm_cl_connect_res(str
 				cl->state = ISHTP_CL_DISCONNECTED;
 				cl->status = -ENODEV;
 			}
+			wake_up_interruptible(&cl->wait_ctrl_res);
 			break;
 		}
 	}
-	if (cl)
-		wake_up_interruptible(&cl->wait_ctrl_res);
 	spin_unlock_irqrestore(&dev->cl_list_lock, flags);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/Kconfig linux-libre-4.10-rc8-gnu/drivers/hid/Kconfig
--- linux-libre-4.9-gnu/drivers/hid/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -138,7 +138,7 @@ config HID_ASUS
 	tristate "Asus"
 	depends on I2C_HID
 	---help---
-	Support for Asus notebook built-in keyboard via i2c.
+	Support for Asus notebook built-in keyboard and touchpad via i2c.
 
 	Supported devices:
 	- EeeBook X205TA
@@ -214,7 +214,7 @@ config HID_CMEDIA
 
 config HID_CP2112
 	tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
-	depends on USB_HID && I2C && GPIOLIB
+	depends on USB_HID && I2C && GPIOLIB && GPIOLIB_IRQCHIP
 	---help---
 	Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
 	This is a HID device driver which registers as an i2c adapter
@@ -512,6 +512,14 @@ config HID_MAGICMOUSE
 	Say Y here if you want support for the multi-touch features of the
 	Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad.
 
+config HID_MAYFLASH
+	tristate "Mayflash game controller adapter force feedback"
+	depends on HID
+	select INPUT_FF_MEMLESS
+	---help---
+	Say Y here if you have HJZ Mayflash PS3 game controller adapters
+	and want to enable force feedback support.
+
 config HID_MICROSOFT
 	tristate "Microsoft non-fully HID-compliant devices"
 	depends on HID
@@ -861,6 +869,13 @@ config THRUSTMASTER_FF
 	  a THRUSTMASTER Dual Trigger 3-in-1 or a THRUSTMASTER Ferrari GT
 	  Rumble Force or Force Feedback Wheel.
 
+config HID_UDRAW_PS3
+	tristate "THQ PS3 uDraw tablet"
+	depends on HID
+	---help---
+	  Say Y here if you want to use the THQ uDraw gaming tablet for
+	  the PS3.
+
 config HID_WACOM
 	tristate "Wacom Intuos/Graphire tablet support (USB)"
 	depends on HID
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/Makefile linux-libre-4.10-rc8-gnu/drivers/hid/Makefile
--- linux-libre-4.9-gnu/drivers/hid/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -58,6 +58,7 @@ obj-$(CONFIG_HID_LOGITECH)	+= hid-logite
 obj-$(CONFIG_HID_LOGITECH_DJ)	+= hid-logitech-dj.o
 obj-$(CONFIG_HID_LOGITECH_HIDPP)	+= hid-logitech-hidpp.o
 obj-$(CONFIG_HID_MAGICMOUSE)	+= hid-magicmouse.o
+obj-$(CONFIG_HID_MAYFLASH)	+= hid-mf.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
 obj-$(CONFIG_HID_MONTEREY)	+= hid-monterey.o
 obj-$(CONFIG_HID_MULTITOUCH)	+= hid-multitouch.o
@@ -96,6 +97,7 @@ obj-$(CONFIG_HID_TIVO)		+= hid-tivo.o
 obj-$(CONFIG_HID_TOPSEED)	+= hid-topseed.o
 obj-$(CONFIG_HID_TWINHAN)	+= hid-twinhan.o
 obj-$(CONFIG_HID_UCLOGIC)	+= hid-uclogic.o
+obj-$(CONFIG_HID_UDRAW_PS3)	+= hid-udraw-ps3.o
 obj-$(CONFIG_HID_LED)		+= hid-led.o
 obj-$(CONFIG_HID_XINMO)		+= hid-xinmo.o
 obj-$(CONFIG_HID_ZEROPLUS)	+= hid-zpff.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/usbhid/hid-core.c linux-libre-4.10-rc8-gnu/drivers/hid/usbhid/hid-core.c
--- linux-libre-4.9-gnu/drivers/hid/usbhid/hid-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/usbhid/hid-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1459,7 +1459,7 @@ static int hid_post_reset(struct usb_int
 	rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL);
 	if (!rdesc) {
 		dbg_hid("couldn't allocate rdesc memory (post_reset)\n");
-		return 1;
+		return -ENOMEM;
 	}
 	status = hid_get_class_descriptor(dev,
 				interface->desc.bInterfaceNumber,
@@ -1467,13 +1467,13 @@ static int hid_post_reset(struct usb_int
 	if (status < 0) {
 		dbg_hid("reading report descriptor failed (post_reset)\n");
 		kfree(rdesc);
-		return 1;
+		return status;
 	}
 	status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize);
 	kfree(rdesc);
 	if (status != 0) {
 		dbg_hid("report descriptor changed\n");
-		return 1;
+		return -EPERM;
 	}
 
 	/* No need to do another reset or clear a halted endpoint */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/usbhid/hid-quirks.c linux-libre-4.10-rc8-gnu/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-4.9-gnu/drivers/hid/usbhid/hid-quirks.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/usbhid/hid-quirks.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,6 +57,7 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
@@ -82,10 +83,14 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3, HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR, HID_QUIRK_MULTI_INPUT },
+	{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE, HID_QUIRK_MULTI_INPUT },
 	{ USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL },
 	{ USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
@@ -101,8 +106,9 @@ static const struct hid_blacklist {
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4, HID_QUIRK_NO_INIT_REPORTS },
+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_2, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS },
-	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/wacom.h linux-libre-4.10-rc8-gnu/drivers/hid/wacom.h
--- linux-libre-4.9-gnu/drivers/hid/wacom.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/wacom.h	2017-02-12 16:03:20.000000000 -0500
@@ -210,7 +210,7 @@ int wacom_setup_pad_input_capabilities(s
 				       struct wacom_wac *wacom_wac);
 void wacom_wac_usage_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage);
-int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
+void wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value);
 void wacom_wac_report(struct hid_device *hdev, struct hid_report *report);
 void wacom_battery_work(struct work_struct *work);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/wacom_sys.c linux-libre-4.10-rc8-gnu/drivers/hid/wacom_sys.c
--- linux-libre-4.9-gnu/drivers/hid/wacom_sys.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/wacom_sys.c	2017-02-12 16:03:20.000000000 -0500
@@ -122,6 +122,7 @@ static void wacom_feature_mapping(struct
 	struct hid_data *hid_data = &wacom->wacom_wac.hid_data;
 	u8 *data;
 	int ret;
+	int n;
 
 	switch (usage->hid) {
 	case HID_DG_CONTACTMAX:
@@ -159,22 +160,48 @@ static void wacom_feature_mapping(struct
 
 	case HID_UP_DIGITIZER:
 		if (field->report->id == 0x0B &&
-		    (field->application == WACOM_G9_DIGITIZER ||
-		     field->application == WACOM_G11_DIGITIZER)) {
+		    (field->application == WACOM_HID_G9_PEN ||
+		     field->application == WACOM_HID_G11_PEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
 
-	case WACOM_G9_PAGE:
-	case WACOM_G11_PAGE:
+	case WACOM_HID_WD_DATAMODE:
+		wacom->wacom_wac.mode_report = field->report->id;
+		wacom->wacom_wac.mode_value = 2;
+		break;
+
+	case WACOM_HID_UP_G9:
+	case WACOM_HID_UP_G11:
 		if (field->report->id == 0x03 &&
-		    (field->application == WACOM_G9_TOUCHSCREEN ||
-		     field->application == WACOM_G11_TOUCHSCREEN)) {
+		    (field->application == WACOM_HID_G9_TOUCHSCREEN ||
+		     field->application == WACOM_HID_G11_TOUCHSCREEN)) {
 			wacom->wacom_wac.mode_report = field->report->id;
 			wacom->wacom_wac.mode_value = 0;
 		}
 		break;
+	case WACOM_HID_WD_OFFSETLEFT:
+	case WACOM_HID_WD_OFFSETTOP:
+	case WACOM_HID_WD_OFFSETRIGHT:
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		/* read manually */
+		n = hid_report_len(field->report);
+		data = hid_alloc_report_buf(field->report, GFP_KERNEL);
+		if (!data)
+			break;
+		data[0] = field->report->id;
+		ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
+					data, n, WAC_CMD_RETRIES);
+		if (ret == n) {
+			ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT,
+						   data, n, 0);
+		} else {
+			hid_warn(hdev, "%s: could not retrieve sensor offsets\n",
+				 __func__);
+		}
+		kfree(data);
+		break;
 	}
 }
 
@@ -240,6 +267,30 @@ static void wacom_usage_mapping(struct h
 			features->touch_max = 1;
 	}
 
+	/*
+	 * ISDv4 devices which predate HID's adoption of the
+	 * HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
+	 * position instead. We can accurately detect if a
+	 * usage with that value should be HID_DG_BARRELSWITCH2
+	 * based on the surrounding usages, which have remained
+	 * constant across generations.
+	 */
+	if (features->type == HID_GENERIC &&
+	    usage->hid == 0x000D0000 &&
+	    field->application == HID_DG_PEN &&
+	    field->physical == HID_DG_STYLUS) {
+		int i = usage->usage_index;
+
+		if (i-4 >= 0 && i+1 < field->maxusage &&
+		    field->usage[i-4].hid == HID_DG_TIPSWITCH &&
+		    field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
+		    field->usage[i-2].hid == HID_DG_ERASER &&
+		    field->usage[i-1].hid == HID_DG_INVERT &&
+		    field->usage[i+1].hid == HID_DG_INRANGE) {
+			usage->hid = HID_DG_BARRELSWITCH2;
+		}
+	}
+
 	switch (usage->hid) {
 	case HID_GD_X:
 		features->x_max = field->logical_maximum;
@@ -1916,6 +1967,19 @@ static void wacom_update_name(struct wac
 				/* shift everything including the terminator */
 				memmove(gap, gap+1, strlen(gap));
 			}
+
+			/* strip off excessive prefixing */
+			if (strstr(name, "Wacom Co.,Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co.,Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+			if (strstr(name, "Wacom Co., Ltd. Wacom ") == name) {
+				int n = strlen(name);
+				int x = strlen("Wacom Co., Ltd. ");
+				memmove(name, name+x, n-x+1);
+			}
+
 			/* get rid of trailing whitespace */
 			if (name[strlen(name)-1] == ' ')
 				name[strlen(name)-1] = '\0';
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/wacom_wac.c linux-libre-4.10-rc8-gnu/drivers/hid/wacom_wac.c
--- linux-libre-4.9-gnu/drivers/hid/wacom_wac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/wacom_wac.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(touch_arbitration, " on
 static void wacom_report_numbered_buttons(struct input_dev *input_dev,
 				int button_count, int mask);
 
+static int wacom_numbered_button_to_key(int n);
+
 /*
  * Percent of battery capacity for Graphire.
  * 8th value means AC online and show 100% capacity.
@@ -164,19 +166,21 @@ static int wacom_pl_irq(struct wacom_wac
 		wacom->id[0] = STYLUS_DEVICE_ID;
 	}
 
-	pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
-	if (features->pressure_max > 255)
-		pressure = (pressure << 1) | ((data[4] >> 6) & 1);
-	pressure += (features->pressure_max + 1) / 2;
+	if (prox) {
+		pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
+		if (features->pressure_max > 255)
+			pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+		pressure += (features->pressure_max + 1) / 2;
 
-	input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
-	input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
-	input_report_abs(input, ABS_PRESSURE, pressure);
+		input_report_abs(input, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
+		input_report_abs(input, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
+		input_report_abs(input, ABS_PRESSURE, pressure);
 
-	input_report_key(input, BTN_TOUCH, data[4] & 0x08);
-	input_report_key(input, BTN_STYLUS, data[4] & 0x10);
-	/* Only allow the stylus2 button to be reported for the pen tool. */
-	input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
+		input_report_key(input, BTN_TOUCH, data[4] & 0x08);
+		input_report_key(input, BTN_STYLUS, data[4] & 0x10);
+		/* Only allow the stylus2 button to be reported for the pen tool. */
+		input_report_key(input, BTN_STYLUS2, (wacom->tool[0] == BTN_TOOL_PEN) && (data[4] & 0x20));
+	}
 
 	if (!prox)
 		wacom->id[0] = 0;
@@ -588,6 +592,11 @@ static int wacom_intuos_pad(struct wacom
 	return 1;
 }
 
+static int wacom_intuos_id_mangle(int tool_id)
+{
+	return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
+}
+
 static int wacom_intuos_get_tool_type(int tool_id)
 {
 	int tool_type;
@@ -595,7 +604,7 @@ static int wacom_intuos_get_tool_type(in
 	switch (tool_id) {
 	case 0x812: /* Inking pen */
 	case 0x801: /* Intuos3 Inking pen */
-	case 0x120802: /* Intuos4/5 Inking Pen */
+	case 0x12802: /* Intuos4/5 Inking Pen */
 	case 0x012:
 		tool_type = BTN_TOOL_PENCIL;
 		break;
@@ -610,11 +619,11 @@ static int wacom_intuos_get_tool_type(in
 	case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
 	case 0x8e2: /* IntuosHT2 pen */
 	case 0x022:
-	case 0x100804: /* Intuos4/5 13HD/24HD Art Pen */
-	case 0x140802: /* Intuos4/5 13HD/24HD Classic Pen */
-	case 0x160802: /* Cintiq 13HD Pro Pen */
-	case 0x180802: /* DTH2242 Pen */
-	case 0x100802: /* Intuos4/5 13HD/24HD General Pen */
+	case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
+	case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
+	case 0x16802: /* Cintiq 13HD Pro Pen */
+	case 0x18802: /* DTH2242 Pen */
+	case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
 		tool_type = BTN_TOOL_PEN;
 		break;
 
@@ -638,6 +647,7 @@ static int wacom_intuos_get_tool_type(in
 		break;
 
 	case 0x82a: /* Eraser */
+	case 0x84a:
 	case 0x85a:
 	case 0x91a:
 	case 0xd1a:
@@ -648,12 +658,12 @@ static int wacom_intuos_get_tool_type(in
 	case 0x80c: /* Intuos4/5 13HD/24HD Marker Pen Eraser */
 	case 0x80a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 	case 0x90a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x14080a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
-	case 0x10090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
-	case 0x10080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
-	case 0x16080a: /* Cintiq 13HD Pro Pen Eraser */
-	case 0x18080a: /* DTH2242 Eraser */
-	case 0x10080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
+	case 0x1480a: /* Intuos4/5 13HD/24HD Classic Pen Eraser */
+	case 0x1090a: /* Intuos4/5 13HD/24HD Airbrush Eraser */
+	case 0x1080c: /* Intuos4/5 13HD/24HD Art Pen Eraser */
+	case 0x1680a: /* Cintiq 13HD Pro Pen Eraser */
+	case 0x1880a: /* DTH2242 Eraser */
+	case 0x1080a: /* Intuos4/5 13HD/24HD General Pen Eraser */
 		tool_type = BTN_TOOL_RUBBER;
 		break;
 
@@ -662,7 +672,7 @@ static int wacom_intuos_get_tool_type(in
 	case 0x112:
 	case 0x913: /* Intuos3 Airbrush */
 	case 0x902: /* Intuos4/5 13HD/24HD Airbrush */
-	case 0x100902: /* Intuos4/5 13HD/24HD Airbrush */
+	case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */
 		tool_type = BTN_TOOL_AIRBRUSH;
 		break;
 
@@ -693,7 +703,7 @@ static int wacom_intuos_inout(struct wac
 			(data[6] << 4) + (data[7] >> 4);
 
 		wacom->id[idx] = (data[2] << 4) | (data[3] >> 4) |
-			((data[7] & 0x0f) << 20) | ((data[8] & 0xf0) << 12);
+		     ((data[7] & 0x0f) << 16) | ((data[8] & 0xf0) << 8);
 
 		wacom->tool[idx] = wacom_intuos_get_tool_type(wacom->id[idx]);
 
@@ -923,7 +933,7 @@ static int wacom_intuos_general(struct w
 	 * don't report events for invalid data
 	 */
 	/* older I4 styli don't work with new Cintiqs */
-	if ((!((wacom->id[idx] >> 20) & 0x01) &&
+	if ((!((wacom->id[idx] >> 16) & 0x01) &&
 			(features->type == WACOM_21UX2)) ||
 	    /* Only large Intuos support Lense Cursor */
 	    (wacom->tool[idx] == BTN_TOOL_LENS &&
@@ -1059,7 +1069,8 @@ static int wacom_intuos_general(struct w
 		break;
 	}
 
-	input_report_abs(input, ABS_MISC, wacom->id[idx]); /* report tool id */
+	input_report_abs(input, ABS_MISC,
+			 wacom_intuos_id_mangle(wacom->id[idx])); /* report tool id */
 	input_report_key(input, wacom->tool[idx], 1);
 	input_event(input, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 	wacom->reporting_data = true;
@@ -1435,11 +1446,59 @@ static int wacom_tpc_irq(struct wacom_wa
 	return 0;
 }
 
+static int wacom_equivalent_usage(int usage)
+{
+	if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) {
+		int subpage = (usage & 0xFF00) << 8;
+		int subusage = (usage & 0xFF);
+
+		if (subpage == WACOM_HID_SP_PAD ||
+		    subpage == WACOM_HID_SP_BUTTON ||
+		    subpage == WACOM_HID_SP_DIGITIZER ||
+		    subpage == WACOM_HID_SP_DIGITIZERINFO ||
+		    usage == WACOM_HID_WD_SENSE ||
+		    usage == WACOM_HID_WD_SERIALHI ||
+		    usage == WACOM_HID_WD_TOOLTYPE ||
+		    usage == WACOM_HID_WD_DISTANCE ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP ||
+		    usage == WACOM_HID_WD_TOUCHSTRIP2 ||
+		    usage == WACOM_HID_WD_TOUCHRING ||
+		    usage == WACOM_HID_WD_TOUCHRINGSTATUS) {
+			return usage;
+		}
+
+		if (subpage == HID_UP_UNDEFINED)
+			subpage = HID_UP_DIGITIZER;
+
+		return subpage | subusage;
+	}
+
+	return usage;
+}
+
 static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage,
 		struct hid_field *field, __u8 type, __u16 code, int fuzz)
 {
+	struct wacom *wacom = input_get_drvdata(input);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	int fmin = field->logical_minimum;
 	int fmax = field->logical_maximum;
+	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
+	int resolution_code = code;
+
+	if (equivalent_usage == HID_DG_TWIST) {
+		resolution_code = ABS_RZ;
+	}
+
+	if (equivalent_usage == HID_GD_X) {
+		fmin += features->offset_left;
+		fmax -= features->offset_right;
+	}
+	if (equivalent_usage == HID_GD_Y) {
+		fmin += features->offset_top;
+		fmax -= features->offset_bottom;
+	}
 
 	usage->type = type;
 	usage->code = code;
@@ -1450,7 +1509,7 @@ static void wacom_map_usage(struct input
 	case EV_ABS:
 		input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
 		input_abs_set_res(input, code,
-				  hidinput_calc_abs_res(field, code));
+				  hidinput_calc_abs_res(field, resolution_code));
 		break;
 	case EV_KEY:
 		input_set_capability(input, EV_KEY, code);
@@ -1458,6 +1517,172 @@ static void wacom_map_usage(struct input
 	case EV_MSC:
 		input_set_capability(input, EV_MSC, code);
 		break;
+	case EV_SW:
+		input_set_capability(input, EV_SW, code);
+		break;
+	}
+}
+
+static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
+		struct hid_field *field, struct hid_usage *usage)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
+	struct input_dev *input = wacom_wac->pad_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_X:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 0);
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Y:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 0);
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	case WACOM_HID_WD_ACCELEROMETER_Z:
+		__set_bit(INPUT_PROP_ACCELEROMETER, input->propbit);
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	case WACOM_HID_WD_BUTTONHOME:
+	case WACOM_HID_WD_BUTTONUP:
+	case WACOM_HID_WD_BUTTONDOWN:
+	case WACOM_HID_WD_BUTTONLEFT:
+	case WACOM_HID_WD_BUTTONRIGHT:
+	case WACOM_HID_WD_BUTTONCENTER:
+		wacom_map_usage(input, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	case WACOM_HID_WD_TOUCHONOFF:
+		wacom_map_usage(input, usage, field, EV_SW, SW_MUTE_DEVICE, 0);
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0);
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	case WACOM_HID_WD_TOUCHSTRIP2:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_RY, 0);
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	case WACOM_HID_WD_TOUCHRING:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	}
+
+	switch (equivalent_usage & 0xfffffff0) {
+	case WACOM_HID_WD_EXPRESSKEY00:
+		wacom_map_usage(input, usage, field, EV_KEY,
+				wacom_numbered_button_to_key(features->numbered_buttons),
+				0);
+		features->numbered_buttons++;
+		features->device_type |= WACOM_DEVICETYPE_PAD;
+		break;
+	}
+}
+
+static void wacom_wac_pad_battery_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_BATTERY_LEVEL:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		break;
+
+	case WACOM_HID_WD_BATTERY_CHARGING:
+		wacom_wac->hid_data.bat_charging = value;
+		wacom_wac->hid_data.ps_connected = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		break;
+	}
+}
+
+static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field,
+		struct hid_usage *usage, __s32 value)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct input_dev *input = wacom_wac->pad_input;
+	struct wacom_features *features = &wacom_wac->features;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+
+	if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) {
+		wacom_wac->hid_data.inrange_state |= value;
+	}
+
+	switch (equivalent_usage) {
+	case WACOM_HID_WD_TOUCHRINGSTATUS:
+		break;
+
+	default:
+		features->input_event_flag = true;
+		input_event(input, usage->type, usage->code, value);
+		break;
+	}
+}
+
+static void wacom_wac_pad_pre_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+	wacom_wac->hid_data.inrange_state = 0;
+}
+
+static void wacom_wac_pad_battery_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
+
+	if (features->quirks & WACOM_QUIRK_BATTERY) {
+		int capacity = wacom_wac->hid_data.battery_capacity;
+		bool charging = wacom_wac->hid_data.bat_charging;
+		bool connected = wacom_wac->hid_data.bat_connected;
+		bool powered = wacom_wac->hid_data.ps_connected;
+
+		wacom_notify_battery(wacom_wac, capacity, charging,
+				     connected, powered);
+	}
+}
+
+static void wacom_wac_pad_report(struct hid_device *hdev,
+		struct hid_report *report)
+{
+	struct wacom *wacom = hid_get_drvdata(hdev);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
+	struct input_dev *input = wacom_wac->pad_input;
+	bool active = wacom_wac->hid_data.inrange_state != 0;
+
+	/* report prox for expresskey events */
+	if (wacom_equivalent_usage(report->field[0]->physical) == HID_DG_TABLETFUNCTIONKEY) {
+		features->input_event_flag = true;
+		input_event(input, EV_ABS, ABS_MISC, active ? PAD_DEVICE_ID : 0);
+	}
+
+	if (features->input_event_flag) {
+		features->input_event_flag = false;
+		input_sync(input);
 	}
 }
 
@@ -1466,25 +1691,43 @@ static void wacom_wac_pen_usage_mapping(
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
 		break;
 	case HID_GD_Y:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4);
 		break;
+	case WACOM_HID_WD_DISTANCE:
+	case HID_GD_Z:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_DISTANCE, 0);
+		break;
 	case HID_DG_TIPPRESSURE:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0);
 		break;
 	case HID_DG_INRANGE:
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
 		break;
+	case HID_DG_BATTERYSTRENGTH:
+		features->quirks |= WACOM_QUIRK_BATTERY;
+		break;
 	case HID_DG_INVERT:
 		wacom_map_usage(input, usage, field, EV_KEY,
 				BTN_TOOL_RUBBER, 0);
 		break;
+	case HID_DG_TILT_X:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_X, 0);
+		break;
+	case HID_DG_TILT_Y:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_TILT_Y, 0);
+		break;
+	case HID_DG_TWIST:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_Z, 0);
+		break;
 	case HID_DG_ERASER:
 	case HID_DG_TIPSWITCH:
 		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
@@ -1498,39 +1741,131 @@ static void wacom_wac_pen_usage_mapping(
 	case HID_DG_TOOLSERIALNUMBER:
 		wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
 		break;
+	case WACOM_HID_WD_SENSE:
+		features->quirks |= WACOM_QUIRK_SENSE;
+		wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
+		break;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_MISC, 0);
+		set_bit(EV_KEY, input->evbit);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
+		input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
+		input_set_capability(input, EV_KEY, BTN_TOOL_BRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_PENCIL);
+		input_set_capability(input, EV_KEY, BTN_TOOL_AIRBRUSH);
+		input_set_capability(input, EV_KEY, BTN_TOOL_MOUSE);
+		input_set_capability(input, EV_KEY, BTN_TOOL_LENS);
+		break;
+	case WACOM_HID_WD_FINGERWHEEL:
+		wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
+		break;
 	}
 }
 
-static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
+static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct wacom_features *features = &wacom_wac->features;
 	struct input_dev *input = wacom_wac->pen_input;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	/* checking which Tool / tip switch to send */
-	switch (usage->hid) {
+	switch (equivalent_usage) {
+	case HID_GD_Z:
+		/*
+		 * HID_GD_Z "should increase as the control's position is
+		 * moved from high to low", while ABS_DISTANCE instead
+		 * increases in value as the tool moves from low to high.
+		 */
+		value = field->logical_maximum - value;
+		break;
 	case HID_DG_INRANGE:
 		wacom_wac->hid_data.inrange_state = value;
-		return 0;
+		if (!(features->quirks & WACOM_QUIRK_SENSE))
+			wacom_wac->hid_data.sense_state = value;
+		return;
+	case HID_DG_BATTERYSTRENGTH:
+		wacom_wac->hid_data.battery_capacity = value;
+		wacom_wac->hid_data.bat_connected = 1;
+		break;
 	case HID_DG_INVERT:
 		wacom_wac->hid_data.invert_state = value;
-		return 0;
+		return;
 	case HID_DG_ERASER:
 	case HID_DG_TIPSWITCH:
 		wacom_wac->hid_data.tipswitch |= value;
-		return 0;
+		return;
+	case HID_DG_TOOLSERIALNUMBER:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
+		wacom_wac->serial[0] |= value;
+		return;
+	case WACOM_HID_WD_SENSE:
+		wacom_wac->hid_data.sense_state = value;
+		return;
+	case WACOM_HID_WD_SERIALHI:
+		wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
+		wacom_wac->serial[0] |= ((__u64)value) << 32;
+		/*
+		 * Non-USI EMR devices may contain additional tool type
+		 * information here. See WACOM_HID_WD_TOOLTYPE case for
+		 * more details.
+		 */
+		if (value >> 20 == 1) {
+			wacom_wac->id[0] |= value & 0xFFFFF;
+		}
+		return;
+	case WACOM_HID_WD_TOOLTYPE:
+		/*
+		 * Some devices (MobileStudio Pro, and possibly later
+		 * devices as well) do not return the complete tool
+		 * type in their WACOM_HID_WD_TOOLTYPE usage. Use a
+		 * bitwise OR so the complete value can be built
+		 * up over time :(
+		 */
+		wacom_wac->id[0] |= value;
+		return;
+	case WACOM_HID_WD_OFFSETLEFT:
+		if (features->offset_left && value != features->offset_left)
+			hid_warn(hdev, "%s: overriding exising left offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_left);
+		features->offset_left = value;
+		return;
+	case WACOM_HID_WD_OFFSETRIGHT:
+		if (features->offset_right && value != features->offset_right)
+			hid_warn(hdev, "%s: overriding exising right offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_right);
+		features->offset_right = value;
+		return;
+	case WACOM_HID_WD_OFFSETTOP:
+		if (features->offset_top && value != features->offset_top)
+			hid_warn(hdev, "%s: overriding exising top offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_top);
+		features->offset_top = value;
+		return;
+	case WACOM_HID_WD_OFFSETBOTTOM:
+		if (features->offset_bottom && value != features->offset_bottom)
+			hid_warn(hdev, "%s: overriding exising bottom offset "
+				 "%d -> %d\n", __func__, value,
+				 features->offset_bottom);
+		features->offset_bottom = value;
+		return;
 	}
 
 	/* send pen events only when touch is up or forced out
 	 * or touch arbitration is off
 	 */
 	if (!usage->type || delay_pen_events(wacom_wac))
-		return 0;
+		return;
 
-	input_event(input, usage->type, usage->code, value);
+	/* send pen events only when the pen is in/entering/leaving proximity */
+	if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
+		return;
 
-	return 0;
+	input_event(input, usage->type, usage->code, value);
 }
 
 static void wacom_wac_pen_pre_report(struct hid_device *hdev,
@@ -1546,24 +1881,53 @@ static void wacom_wac_pen_report(struct
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->pen_input;
 	bool prox = wacom_wac->hid_data.inrange_state;
+	bool range = wacom_wac->hid_data.sense_state;
 
-	if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */
+	if (!wacom_wac->tool[0] && prox) { /* first in prox */
 		/* Going into proximity select tool */
-		wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
-						BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+		if (wacom_wac->hid_data.invert_state)
+			wacom_wac->tool[0] = BTN_TOOL_RUBBER;
+		else if (wacom_wac->id[0])
+			wacom_wac->tool[0] = wacom_intuos_get_tool_type(wacom_wac->id[0]);
+		else
+			wacom_wac->tool[0] = BTN_TOOL_PEN;
+	}
 
 	/* keep pen state for touch events */
-	wacom_wac->shared->stylus_in_proximity = prox;
+	wacom_wac->shared->stylus_in_proximity = range;
 
-	if (!delay_pen_events(wacom_wac)) {
+	if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
+		int id = wacom_wac->id[0];
+
+		/*
+		 * Non-USI EMR tools should have their IDs mangled to
+		 * match the legacy behavior of wacom_intuos_general
+		 */
+		if (wacom_wac->serial[0] >> 52 == 1)
+			id = wacom_intuos_id_mangle(id);
+
+		/*
+		 * To ensure compatibility with xf86-input-wacom, we should
+		 * report the BTN_TOOL_* event prior to the ABS_MISC or
+		 * MSC_SERIAL events.
+		 */
 		input_report_key(input, BTN_TOUCH,
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], prox);
+		if (wacom_wac->serial[0]) {
+			input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
+			input_report_abs(input, ABS_MISC, id);
+		}
 
 		wacom_wac->hid_data.tipswitch = false;
 
 		input_sync(input);
 	}
+
+	if (!prox) {
+		wacom_wac->tool[0] = 0;
+		wacom_wac->id[0] = 0;
+	}
 }
 
 static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
@@ -1573,8 +1937,9 @@ static void wacom_wac_finger_usage_mappi
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->touch_input;
 	unsigned touch_max = wacom_wac->features.touch_max;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		if (touch_max == 1)
 			wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4);
@@ -1644,13 +2009,14 @@ static void wacom_wac_finger_slot(struct
 	}
 }
 
-static int wacom_wac_finger_event(struct hid_device *hdev,
+static void wacom_wac_finger_event(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage, __s32 value)
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
 
-	switch (usage->hid) {
+	switch (equivalent_usage) {
 	case HID_GD_X:
 		wacom_wac->hid_data.x = value;
 		break;
@@ -1673,11 +2039,9 @@ static int wacom_wac_finger_event(struct
 
 
 	if (usage->usage_index + 1 == field->report_count) {
-		if (usage->hid == wacom_wac->hid_data.last_slot_field)
+		if (equivalent_usage == wacom_wac->hid_data.last_slot_field)
 			wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input);
 	}
-
-	return 0;
 }
 
 static void wacom_wac_finger_pre_report(struct hid_device *hdev,
@@ -1762,28 +2126,30 @@ void wacom_wac_usage_mapping(struct hid_
 	/* currently, only direct devices have proper hid report descriptors */
 	features->device_type |= WACOM_DEVICETYPE_DIRECT;
 
-	if (WACOM_PEN_FIELD(field))
-		return wacom_wac_pen_usage_mapping(hdev, field, usage);
-
-	if (WACOM_FINGER_FIELD(field))
-		return wacom_wac_finger_usage_mapping(hdev, field, usage);
+	if (WACOM_PAD_FIELD(field))
+		wacom_wac_pad_usage_mapping(hdev, field, usage);
+	else if (WACOM_PEN_FIELD(field))
+		wacom_wac_pen_usage_mapping(hdev, field, usage);
+	else if (WACOM_FINGER_FIELD(field))
+		wacom_wac_finger_usage_mapping(hdev, field, usage);
 }
 
-int wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
+void wacom_wac_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 
 	if (wacom->wacom_wac.features.type != HID_GENERIC)
-		return 0;
-
-	if (WACOM_PEN_FIELD(field))
-		return wacom_wac_pen_event(hdev, field, usage, value);
-
-	if (WACOM_FINGER_FIELD(field))
-		return wacom_wac_finger_event(hdev, field, usage, value);
+		return;
 
-	return 0;
+	if (WACOM_PAD_FIELD(field)) {
+		wacom_wac_pad_battery_event(hdev, field, usage, value);
+		if (wacom->wacom_wac.pad_input)
+			wacom_wac_pad_event(hdev, field, usage, value);
+	} else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
+		wacom_wac_pen_event(hdev, field, usage, value);
+	else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
+		wacom_wac_finger_event(hdev, field, usage, value);
 }
 
 static void wacom_report_events(struct hid_device *hdev, struct hid_report *report)
@@ -1814,19 +2180,33 @@ void wacom_wac_report(struct hid_device
 	if (wacom_wac->features.type != HID_GENERIC)
 		return;
 
-	if (WACOM_PEN_FIELD(field))
+	if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
+		wacom_wac_pad_pre_report(hdev, report);
+	else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
 		wacom_wac_pen_pre_report(hdev, report);
-
-	if (WACOM_FINGER_FIELD(field))
+	else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
 		wacom_wac_finger_pre_report(hdev, report);
 
 	wacom_report_events(hdev, report);
 
-	if (WACOM_PEN_FIELD(field))
-		return wacom_wac_pen_report(hdev, report);
+	/*
+	 * Non-input reports may be sent prior to the device being
+	 * completely initialized. Since only their events need
+	 * to be processed, exit after 'wacom_report_events' has
+	 * been called to prevent potential crashes in the report-
+	 * processing functions.
+	 */
+	if (report->type != HID_INPUT_REPORT)
+		return;
 
-	if (WACOM_FINGER_FIELD(field))
-		return wacom_wac_finger_report(hdev, report);
+	if (WACOM_PAD_FIELD(field)) {
+		wacom_wac_pad_battery_report(hdev, report);
+		if (wacom->wacom_wac.pad_input)
+			wacom_wac_pad_report(hdev, report);
+	} else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
+		wacom_wac_pen_report(hdev, report);
+	else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
+		wacom_wac_finger_report(hdev, report);
 }
 
 static int wacom_bpt_touch(struct wacom_wac *wacom)
@@ -2399,6 +2779,8 @@ void wacom_setup_device_quirks(struct wa
 	struct wacom_features *features = &wacom->wacom_wac.features;
 
 	/* The pen and pad share the same interface on most devices */
+	if (features->numbered_buttons > 0)
+		features->device_type |= WACOM_DEVICETYPE_PAD;
 	if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 ||
 	    features->type == DTUS ||
 	    (features->type >= INTUOS3S && features->type <= WACOM_MO)) {
@@ -2448,7 +2830,7 @@ void wacom_setup_device_quirks(struct wa
 	/*
 	 * Raw Wacom-mode pen and touch events both come from interface
 	 * 0, whose HID descriptor has an application usage of 0xFF0D
-	 * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back
+	 * (i.e., WACOM_HID_WD_DIGITIZER). We route pen packets back
 	 * out through the HID_GENERIC device created for interface 1,
 	 * so rewrite this one to be of type WACOM_DEVICETYPE_TOUCH.
 	 */
@@ -2530,10 +2912,12 @@ int wacom_setup_pen_input_capabilities(s
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 	__set_bit(ABS_MISC, input_dev->absbit);
 
-	input_set_abs_params(input_dev, ABS_X, features->x_min,
-			     features->x_max, features->x_fuzz, 0);
-	input_set_abs_params(input_dev, ABS_Y, features->y_min,
-			     features->y_max, features->y_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_X, 0 + features->offset_left,
+			     features->x_max - features->offset_right,
+			     features->x_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0 + features->offset_top,
+			     features->y_max - features->offset_bottom,
+			     features->y_fuzz, 0);
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0,
 		features->pressure_max, features->pressure_fuzz, 0);
 
@@ -2769,17 +3153,29 @@ int wacom_setup_touch_input_capabilities
 	return 0;
 }
 
+static int wacom_numbered_button_to_key(int n)
+{
+	if (n < 10)
+		return BTN_0 + n;
+	else if (n < 16)
+		return BTN_A + (n-10);
+	else if (n < 18)
+		return BTN_BASE + (n-16);
+	else
+		return 0;
+}
+
 static void wacom_setup_numbered_buttons(struct input_dev *input_dev,
 				int button_count)
 {
 	int i;
 
-	for (i = 0; i < button_count && i < 10; i++)
-		__set_bit(BTN_0 + i, input_dev->keybit);
-	for (i = 10; i < button_count && i < 16; i++)
-		__set_bit(BTN_A + (i-10), input_dev->keybit);
-	for (i = 16; i < button_count && i < 18; i++)
-		__set_bit(BTN_BASE + (i-16), input_dev->keybit);
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			__set_bit(key, input_dev->keybit);
+	}
 }
 
 static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group)
@@ -2881,12 +3277,12 @@ static void wacom_report_numbered_button
 	for (i = 0; i < wacom->led.count; i++)
 		wacom_update_led(wacom,  button_count, mask, i);
 
-	for (i = 0; i < button_count && i < 10; i++)
-		input_report_key(input_dev, BTN_0 + i, mask & (1 << i));
-	for (i = 10; i < button_count && i < 16; i++)
-		input_report_key(input_dev, BTN_A + (i-10), mask & (1 << i));
-	for (i = 16; i < button_count && i < 18; i++)
-		input_report_key(input_dev, BTN_BASE + (i-16), mask & (1 << i));
+	for (i = 0; i < button_count; i++) {
+		int key = wacom_numbered_button_to_key(i);
+
+		if (key)
+			input_report_key(input_dev, key, mask & (1 << i));
+	}
 }
 
 int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
@@ -2906,8 +3302,12 @@ int wacom_setup_pad_input_capabilities(s
 	__set_bit(ABS_MISC, input_dev->absbit);
 
 	/* kept for making legacy xf86-input-wacom accepting the pad */
-	input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_X].minimum ||
+	      input_dev->absinfo[ABS_X].maximum)))
+		input_set_abs_params(input_dev, ABS_X, 0, 1, 0, 0);
+	if (!(input_dev->absinfo && (input_dev->absinfo[ABS_Y].minimum ||
+	      input_dev->absinfo[ABS_Y].maximum)))
+		input_set_abs_params(input_dev, ABS_Y, 0, 1, 0, 0);
 
 	/* kept for making udev and libwacom accepting the pad */
 	__set_bit(BTN_STYLUS, input_dev->keybit);
@@ -3027,6 +3427,9 @@ int wacom_setup_pad_input_capabilities(s
 		input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0);
 		break;
 
+	case HID_GENERIC:
+		break;
+
 	default:
 		/* no pad supported */
 		return -ENODEV;
@@ -3233,26 +3636,30 @@ static const struct wacom_features wacom
 	  INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xF4 =
-	{ "Wacom Cintiq 24HD", 104080, 65200, 2047, 63,
+	{ "Wacom Cintiq 24HD", 104480, 65600, 2047, 63,
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xF8 =
-	{ "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */
+	{ "Wacom Cintiq 24HD touch", 104480, 65600, 2047, 63, /* Pen */
 	  WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 16,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
 static const struct wacom_features wacom_features_0xF6 =
 	{ "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x32A =
-	{ "Wacom Cintiq 27QHD", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x32B =
-	{ "Wacom Cintiq 27QHD touch", 119740, 67520, 2047, 63,
+	{ "Wacom Cintiq 27QHD touch", 120140, 67920, 2047, 63,
 	  WACOM_27QHD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 0,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x32C };
 static const struct wacom_features wacom_features_0x32C =
 	{ "Wacom Cintiq 27QHD touch", .type = WACOM_27QHDT,
@@ -3267,13 +3674,15 @@ static const struct wacom_features wacom
 	{ "Wacom Cintiq 12WX", 53020, 33440, 1023, 63,
 	  WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 10 };
 static const struct wacom_features wacom_features_0x304 =
-	{ "Wacom Cintiq 13HD", 59152, 33448, 1023, 63,
+	{ "Wacom Cintiq 13HD", 59552, 33848, 1023, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x333 =
-	{ "Wacom Cintiq 13HD touch", 59152, 33448, 2047, 63,
+	{ "Wacom Cintiq 13HD touch", 59552, 33848, 2047, 63,
 	  WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x335 };
 static const struct wacom_features wacom_features_0x335 =
 	{ "Wacom Cintiq 13HD touch", .type = WACOM_24HDT, /* Touch */
@@ -3290,42 +3699,50 @@ static const struct wacom_features wacom
 	{ "Wacom DTU1631", 34623, 19553, 511, 0,
 	  DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xFB =
-	{ "Wacom DTU1031", 21896, 13760, 511, 0,
+	{ "Wacom DTU1031", 22096, 13960, 511, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x32F =
-	{ "Wacom DTU1031X", 22472, 12728, 511, 0,
+	{ "Wacom DTU1031X", 22672, 12928, 511, 0,
 	  DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 0,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x336 =
-	{ "Wacom DTU1141", 23472, 13203, 1023, 0,
+	{ "Wacom DTU1141", 23672, 13403, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 static const struct wacom_features wacom_features_0x57 =
-	{ "Wacom DTK2241", 95640, 54060, 2047, 63,
+	{ "Wacom DTK2241", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x59 = /* Pen */
-	{ "Wacom DTH2242", 95640, 54060, 2047, 63,
+	{ "Wacom DTH2242", 95840, 54260, 2047, 63,
 	  DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 6,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D };
 static const struct wacom_features wacom_features_0x5D = /* Touch */
 	{ "Wacom DTH2242",       .type = WACOM_24HDT,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0xCC =
-	{ "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63,
+	{ "Wacom Cintiq 21UX2", 87200, 65600, 2047, 63,
 	  WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0xFA =
-	{ "Wacom Cintiq 22HD", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HD", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET };
 static const struct wacom_features wacom_features_0x5B =
-	{ "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63,
+	{ "Wacom Cintiq 22HDT", 95840, 54260, 2047, 63,
 	  WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 18,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e };
 static const struct wacom_features wacom_features_0x5E =
 	{ "Wacom Cintiq 22HDT", .type = WACOM_24HDT,
@@ -3469,18 +3886,20 @@ static const struct wacom_features wacom
 	{ "ISD-V4", 12800, 8000, 255, 0,
 	  TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x307 =
-	{ "Wacom ISDv5 307", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 307", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 };
 static const struct wacom_features wacom_features_0x309 =
 	{ "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x30A =
-	{ "Wacom ISDv5 30A", 59152, 33448, 2047, 63,
+	{ "Wacom ISDv5 30A", 59552, 33848, 2047, 63,
 	  CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 9,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C };
 static const struct wacom_features wacom_features_0x30C =
 	{ "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */
@@ -3496,6 +3915,7 @@ static const struct wacom_features wacom
 	{ "Wacom ISDv5 325", 59552, 33848, 2047, 63,
 	  CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11,
 	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+	  WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
 	  .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };
 static const struct wacom_features wacom_features_0x326 = /* Touch */
 	{ "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
@@ -3525,8 +3945,9 @@ static const struct wacom_features wacom
 	  INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
 	  .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x343 =
-	{ "Wacom DTK1651", 34616, 19559, 1023, 0,
+	{ "Wacom DTK1651", 34816, 19759, 1023, 0,
 	  DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4,
+	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET,
 	  WACOM_DTU_OFFSET, WACOM_DTU_OFFSET };
 
 static const struct wacom_features wacom_features_HID_ANY_ID =
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hid/wacom_wac.h linux-libre-4.10-rc8-gnu/drivers/hid/wacom_wac.h
--- linux-libre-4.9-gnu/drivers/hid/wacom_wac.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hid/wacom_wac.h	2017-02-12 16:03:20.000000000 -0500
@@ -74,6 +74,7 @@
 
 /* device quirks */
 #define WACOM_QUIRK_BBTOUCH_LOWRES	0x0001
+#define WACOM_QUIRK_SENSE		0x0002
 #define WACOM_QUIRK_BATTERY		0x0008
 
 /* device types */
@@ -84,23 +85,66 @@
 #define WACOM_DEVICETYPE_WL_MONITOR     0x0008
 #define WACOM_DEVICETYPE_DIRECT         0x0010
 
-#define WACOM_VENDORDEFINED_PEN		0xff0d0001
-#define WACOM_G9_PAGE			0xff090000
-#define WACOM_G9_DIGITIZER		(WACOM_G9_PAGE | 0x02)
-#define WACOM_G9_TOUCHSCREEN		(WACOM_G9_PAGE | 0x11)
-#define WACOM_G11_PAGE			0xff110000
-#define WACOM_G11_DIGITIZER		(WACOM_G11_PAGE | 0x02)
-#define WACOM_G11_TOUCHSCREEN		(WACOM_G11_PAGE | 0x11)
+#define WACOM_HID_UP_WACOMDIGITIZER     0xff0d0000
+#define WACOM_HID_SP_PAD                0x00040000
+#define WACOM_HID_SP_BUTTON             0x00090000
+#define WACOM_HID_SP_DIGITIZER          0x000d0000
+#define WACOM_HID_SP_DIGITIZERINFO      0x00100000
+#define WACOM_HID_WD_DIGITIZER          (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
+#define WACOM_HID_WD_SENSE              (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
+#define WACOM_HID_WD_DIGITIZERFNKEYS    (WACOM_HID_UP_WACOMDIGITIZER | 0x39)
+#define WACOM_HID_WD_SERIALHI           (WACOM_HID_UP_WACOMDIGITIZER | 0x5c)
+#define WACOM_HID_WD_TOOLTYPE           (WACOM_HID_UP_WACOMDIGITIZER | 0x77)
+#define WACOM_HID_WD_DISTANCE           (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
+#define WACOM_HID_WD_TOUCHSTRIP         (WACOM_HID_UP_WACOMDIGITIZER | 0x0136)
+#define WACOM_HID_WD_TOUCHSTRIP2        (WACOM_HID_UP_WACOMDIGITIZER | 0x0137)
+#define WACOM_HID_WD_TOUCHRING          (WACOM_HID_UP_WACOMDIGITIZER | 0x0138)
+#define WACOM_HID_WD_TOUCHRINGSTATUS    (WACOM_HID_UP_WACOMDIGITIZER | 0x0139)
+#define WACOM_HID_WD_ACCELEROMETER_X    (WACOM_HID_UP_WACOMDIGITIZER | 0x0401)
+#define WACOM_HID_WD_ACCELEROMETER_Y    (WACOM_HID_UP_WACOMDIGITIZER | 0x0402)
+#define WACOM_HID_WD_ACCELEROMETER_Z    (WACOM_HID_UP_WACOMDIGITIZER | 0x0403)
+#define WACOM_HID_WD_BATTERY_CHARGING   (WACOM_HID_UP_WACOMDIGITIZER | 0x0404)
+#define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
+#define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
+#define WACOM_HID_WD_EXPRESSKEYCAP00    (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)
+#define WACOM_HID_WD_BUTTONHOME         (WACOM_HID_UP_WACOMDIGITIZER | 0x0990)
+#define WACOM_HID_WD_BUTTONUP           (WACOM_HID_UP_WACOMDIGITIZER | 0x0991)
+#define WACOM_HID_WD_BUTTONDOWN         (WACOM_HID_UP_WACOMDIGITIZER | 0x0992)
+#define WACOM_HID_WD_BUTTONLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0993)
+#define WACOM_HID_WD_BUTTONRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0994)
+#define WACOM_HID_WD_BUTTONCENTER       (WACOM_HID_UP_WACOMDIGITIZER | 0x0995)
+#define WACOM_HID_WD_TOUCHONOFF         (WACOM_HID_UP_WACOMDIGITIZER | 0x0996)
+#define WACOM_HID_WD_FINGERWHEEL        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
+#define WACOM_HID_WD_OFFSETLEFT         (WACOM_HID_UP_WACOMDIGITIZER | 0x0d30)
+#define WACOM_HID_WD_OFFSETTOP          (WACOM_HID_UP_WACOMDIGITIZER | 0x0d31)
+#define WACOM_HID_WD_OFFSETRIGHT        (WACOM_HID_UP_WACOMDIGITIZER | 0x0d32)
+#define WACOM_HID_WD_OFFSETBOTTOM       (WACOM_HID_UP_WACOMDIGITIZER | 0x0d33)
+#define WACOM_HID_WD_DATAMODE           (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
+#define WACOM_HID_WD_DIGITIZERINFO      (WACOM_HID_UP_WACOMDIGITIZER | 0x1013)
+#define WACOM_HID_UP_G9                 0xff090000
+#define WACOM_HID_G9_PEN                (WACOM_HID_UP_G9 | 0x02)
+#define WACOM_HID_G9_TOUCHSCREEN        (WACOM_HID_UP_G9 | 0x11)
+#define WACOM_HID_UP_G11                0xff110000
+#define WACOM_HID_G11_PEN               (WACOM_HID_UP_G11 | 0x02)
+#define WACOM_HID_G11_TOUCHSCREEN       (WACOM_HID_UP_G11 | 0x11)
+
+#define WACOM_PAD_FIELD(f)	(((f)->physical == HID_DG_TABLETFUNCTIONKEY) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERFNKEYS) || \
+				 ((f)->physical == WACOM_HID_WD_DIGITIZERINFO))
 
 #define WACOM_PEN_FIELD(f)	(((f)->logical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_STYLUS) || \
 				 ((f)->physical == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_PEN) || \
 				 ((f)->application == HID_DG_DIGITIZER) || \
-				 ((f)->application == WACOM_VENDORDEFINED_PEN))
+				 ((f)->application == WACOM_HID_WD_DIGITIZER) || \
+				 ((f)->application == WACOM_HID_G9_PEN) || \
+				 ((f)->application == WACOM_HID_G11_PEN))
 #define WACOM_FINGER_FIELD(f)	(((f)->logical == HID_DG_FINGER) || \
 				 ((f)->physical == HID_DG_FINGER) || \
-				 ((f)->application == HID_DG_TOUCHSCREEN))
+				 ((f)->application == HID_DG_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G9_TOUCHSCREEN) || \
+				 ((f)->application == WACOM_HID_G11_TOUCHSCREEN))
 
 enum {
 	PENPARTNER = 0,
@@ -167,8 +211,10 @@ struct wacom_features {
 	int x_resolution;
 	int y_resolution;
 	int numbered_buttons;
-	int x_min;
-	int y_min;
+	int offset_left;
+	int offset_right;
+	int offset_top;
+	int offset_bottom;
 	int device_type;
 	int x_phy;
 	int y_phy;
@@ -186,6 +232,7 @@ struct wacom_features {
 	int pktlen;
 	bool check_for_hid_type;
 	int hid_type;
+	bool input_event_flag;
 };
 
 struct wacom_shared {
@@ -202,6 +249,7 @@ struct wacom_shared {
 struct hid_data {
 	__s16 inputmode;	/* InputMode HID feature, -1 if non-existent */
 	__s16 inputmode_index;	/* InputMode HID feature index in the report */
+	bool sense_state;
 	bool inrange_state;
 	bool invert_state;
 	bool tipswitch;
@@ -217,6 +265,10 @@ struct hid_data {
 	int last_slot_field;
 	int num_expected;
 	int num_received;
+	int battery_capacity;
+	int bat_charging;
+	int bat_connected;
+	int ps_connected;
 };
 
 struct wacom_remote_data {
@@ -234,7 +286,7 @@ struct wacom_wac {
 	unsigned char data[WACOM_PKGLEN_MAX];
 	int tool[2];
 	int id[2];
-	__u32 serial[2];
+	__u64 serial[2];
 	bool reporting_data;
 	struct wacom_features features;
 	struct wacom_shared *shared;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hsi/clients/ssi_protocol.c linux-libre-4.10-rc8-gnu/drivers/hsi/clients/ssi_protocol.c
--- linux-libre-4.9-gnu/drivers/hsi/clients/ssi_protocol.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hsi/clients/ssi_protocol.c	2017-02-12 16:03:20.000000000 -0500
@@ -960,15 +960,6 @@ static int ssip_pn_stop(struct net_devic
 	return 0;
 }
 
-static int ssip_pn_set_mtu(struct net_device *dev, int new_mtu)
-{
-	if (new_mtu > SSIP_MAX_MTU || new_mtu < PHONET_MIN_MTU)
-		return -EINVAL;
-	dev->mtu = new_mtu;
-
-	return 0;
-}
-
 static void ssip_xmit_work(struct work_struct *work)
 {
 	struct ssi_protocol *ssi =
@@ -1060,7 +1051,6 @@ static const struct net_device_ops ssip_
 	.ndo_open	= ssip_pn_open,
 	.ndo_stop	= ssip_pn_stop,
 	.ndo_start_xmit	= ssip_pn_xmit,
-	.ndo_change_mtu	= ssip_pn_set_mtu,
 };
 
 static void ssip_pn_setup(struct net_device *dev)
@@ -1136,6 +1126,10 @@ static int ssi_protocol_probe(struct dev
 		goto out1;
 	}
 
+	/* MTU range: 6 - 65535 */
+	ssi->netdev->min_mtu = PHONET_MIN_MTU;
+	ssi->netdev->max_mtu = SSIP_MAX_MTU;
+
 	SET_NETDEV_DEV(ssi->netdev, dev);
 	netif_carrier_off(ssi->netdev);
 	err = register_netdev(ssi->netdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/channel.c linux-libre-4.10-rc8-gnu/drivers/hv/channel.c
--- linux-libre-4.9-gnu/drivers/hv/channel.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/channel.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@
  * vmbus_setevent- Trigger an event notification on the specified
  * channel.
  */
-static void vmbus_setevent(struct vmbus_channel *channel)
+void vmbus_setevent(struct vmbus_channel *channel)
 {
 	struct hv_monitor_page *monitorpage;
 
@@ -65,6 +65,7 @@ static void vmbus_setevent(struct vmbus_
 		vmbus_set_event(channel);
 	}
 }
+EXPORT_SYMBOL_GPL(vmbus_setevent);
 
 /*
  * vmbus_open - Open the specified channel.
@@ -635,8 +636,6 @@ int vmbus_sendpacket_ctl(struct vmbus_ch
 	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
 	struct kvec bufferlist[3];
 	u64 aligned_data = 0;
-	int ret;
-	bool signal = false;
 	bool lock = channel->acquire_ring_lock;
 	int num_vecs = ((bufferlen != 0) ? 3 : 1);
 
@@ -656,33 +655,9 @@ int vmbus_sendpacket_ctl(struct vmbus_ch
 	bufferlist[2].iov_base = &aligned_data;
 	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
-	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, num_vecs,
-				  &signal, lock, channel->signal_policy);
-
-	/*
-	 * Signalling the host is conditional on many factors:
-	 * 1. The ring state changed from being empty to non-empty.
-	 *    This is tracked by the variable "signal".
-	 * 2. The variable kick_q tracks if more data will be placed
-	 *    on the ring. We will not signal if more data is
-	 *    to be placed.
-	 *
-	 * Based on the channel signal state, we will decide
-	 * which signaling policy will be applied.
-	 *
-	 * If we cannot write to the ring-buffer; signal the host
-	 * even if we may not have written anything. This is a rare
-	 * enough condition that it should not matter.
-	 * NOTE: in this case, the hvsock channel is an exception, because
-	 * it looks the host side's hvsock implementation has a throttling
-	 * mechanism which can hurt the performance otherwise.
-	 */
-
-	if (((ret == 0) && kick_q && signal) ||
-	    (ret && !is_hvsock_channel(channel)))
-		vmbus_setevent(channel);
+	return hv_ringbuffer_write(channel, bufferlist, num_vecs,
+				   lock, kick_q);
 
-	return ret;
 }
 EXPORT_SYMBOL(vmbus_sendpacket_ctl);
 
@@ -723,7 +698,6 @@ int vmbus_sendpacket_pagebuffer_ctl(stru
 				     u32 flags,
 				     bool kick_q)
 {
-	int ret;
 	int i;
 	struct vmbus_channel_packet_page_buffer desc;
 	u32 descsize;
@@ -731,7 +705,6 @@ int vmbus_sendpacket_pagebuffer_ctl(stru
 	u32 packetlen_aligned;
 	struct kvec bufferlist[3];
 	u64 aligned_data = 0;
-	bool signal = false;
 	bool lock = channel->acquire_ring_lock;
 
 	if (pagecount > MAX_PAGE_BUFFER_COUNT)
@@ -769,29 +742,8 @@ int vmbus_sendpacket_pagebuffer_ctl(stru
 	bufferlist[2].iov_base = &aligned_data;
 	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
-	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3,
-				  &signal, lock, channel->signal_policy);
-
-	/*
-	 * Signalling the host is conditional on many factors:
-	 * 1. The ring state changed from being empty to non-empty.
-	 *    This is tracked by the variable "signal".
-	 * 2. The variable kick_q tracks if more data will be placed
-	 *    on the ring. We will not signal if more data is
-	 *    to be placed.
-	 *
-	 * Based on the channel signal state, we will decide
-	 * which signaling policy will be applied.
-	 *
-	 * If we cannot write to the ring-buffer; signal the host
-	 * even if we may not have written anything. This is a rare
-	 * enough condition that it should not matter.
-	 */
-
-	if (((ret == 0) && kick_q && signal) || (ret))
-		vmbus_setevent(channel);
-
-	return ret;
+	return hv_ringbuffer_write(channel, bufferlist, 3,
+				   lock, kick_q);
 }
 EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl);
 
@@ -822,12 +774,10 @@ int vmbus_sendpacket_mpb_desc(struct vmb
 			      u32 desc_size,
 			      void *buffer, u32 bufferlen, u64 requestid)
 {
-	int ret;
 	u32 packetlen;
 	u32 packetlen_aligned;
 	struct kvec bufferlist[3];
 	u64 aligned_data = 0;
-	bool signal = false;
 	bool lock = channel->acquire_ring_lock;
 
 	packetlen = desc_size + bufferlen;
@@ -848,13 +798,8 @@ int vmbus_sendpacket_mpb_desc(struct vmb
 	bufferlist[2].iov_base = &aligned_data;
 	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
-	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3,
-				  &signal, lock, channel->signal_policy);
-
-	if (ret == 0 && signal)
-		vmbus_setevent(channel);
-
-	return ret;
+	return hv_ringbuffer_write(channel, bufferlist, 3,
+				   lock, true);
 }
 EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);
 
@@ -866,14 +811,12 @@ int vmbus_sendpacket_multipagebuffer(str
 				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 kvec bufferlist[3];
 	u64 aligned_data = 0;
-	bool signal = false;
 	bool lock = channel->acquire_ring_lock;
 	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
 					 multi_pagebuffer->len);
@@ -913,13 +856,8 @@ int vmbus_sendpacket_multipagebuffer(str
 	bufferlist[2].iov_base = &aligned_data;
 	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
 
-	ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3,
-				  &signal, lock, channel->signal_policy);
-
-	if (ret == 0 && signal)
-		vmbus_setevent(channel);
-
-	return ret;
+	return hv_ringbuffer_write(channel, bufferlist, 3,
+				   lock, true);
 }
 EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
 
@@ -941,16 +879,9 @@ __vmbus_recvpacket(struct vmbus_channel
 		   u32 bufferlen, u32 *buffer_actual_len, u64 *requestid,
 		   bool raw)
 {
-	int ret;
-	bool signal = false;
-
-	ret = hv_ringbuffer_read(&channel->inbound, buffer, bufferlen,
-				 buffer_actual_len, requestid, &signal, raw);
-
-	if (signal)
-		vmbus_setevent(channel);
+	return hv_ringbuffer_read(channel, buffer, bufferlen,
+				  buffer_actual_len, requestid, raw);
 
-	return ret;
 }
 
 int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/channel_mgmt.c linux-libre-4.10-rc8-gnu/drivers/hv/channel_mgmt.c
--- linux-libre-4.9-gnu/drivers/hv/channel_mgmt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/channel_mgmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -134,7 +134,7 @@ static const struct vmbus_device vmbus_d
 	},
 
 	/* Unknown GUID */
-	{ .dev_type = HV_UNKOWN,
+	{ .dev_type = HV_UNKNOWN,
 	  .perf_device = false,
 	},
 };
@@ -163,9 +163,9 @@ static u16 hv_get_dev_type(const struct
 	u16 i;
 
 	if (is_hvsock_channel(channel) || is_unsupported_vmbus_devs(guid))
-		return HV_UNKOWN;
+		return HV_UNKNOWN;
 
-	for (i = HV_IDE; i < HV_UNKOWN; i++) {
+	for (i = HV_IDE; i < HV_UNKNOWN; i++) {
 		if (!uuid_le_cmp(*guid, vmbus_devs[i].guid))
 			return i;
 	}
@@ -389,6 +389,7 @@ void vmbus_free_channels(void)
 {
 	struct vmbus_channel *channel, *tmp;
 
+	mutex_lock(&vmbus_connection.channel_mutex);
 	list_for_each_entry_safe(channel, tmp, &vmbus_connection.chn_list,
 		listentry) {
 		/* hv_process_channel_removal() needs this */
@@ -396,6 +397,7 @@ void vmbus_free_channels(void)
 
 		vmbus_device_unregister(channel->device_obj);
 	}
+	mutex_unlock(&vmbus_connection.channel_mutex);
 }
 
 /*
@@ -447,8 +449,6 @@ static void vmbus_process_offer(struct v
 	}
 
 	dev_type = hv_get_dev_type(newchannel);
-	if (dev_type == HV_NIC)
-		set_channel_signal_state(newchannel, HV_SIGNAL_POLICY_EXPLICIT);
 
 	init_vp_index(newchannel, dev_type);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/connection.c linux-libre-4.10-rc8-gnu/drivers/hv/connection.c
--- linux-libre-4.9-gnu/drivers/hv/connection.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/connection.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,7 @@ struct vmbus_connection vmbus_connection
 	.conn_state		= DISCONNECTED,
 	.next_gpadl_handle	= ATOMIC_INIT(0xE1E10),
 };
+EXPORT_SYMBOL_GPL(vmbus_connection);
 
 /*
  * Negotiated protocol version with the host.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/hv_balloon.c linux-libre-4.10-rc8-gnu/drivers/hv/hv_balloon.c
--- linux-libre-4.9-gnu/drivers/hv/hv_balloon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/hv_balloon.c	2017-02-12 16:03:20.000000000 -0500
@@ -564,6 +564,11 @@ struct hv_dynmem_device {
 	 * next version to try.
 	 */
 	__u32 next_version;
+
+	/*
+	 * The negotiated version agreed by host.
+	 */
+	__u32 version;
 };
 
 static struct hv_dynmem_device dm_device;
@@ -645,6 +650,7 @@ static void hv_bring_pgs_online(struct h
 {
 	int i;
 
+	pr_debug("Online %lu pages starting at pfn 0x%lx\n", size, start_pfn);
 	for (i = 0; i < size; i++)
 		hv_page_online_one(has, pfn_to_page(start_pfn + i));
 }
@@ -685,7 +691,7 @@ static void hv_mem_hot_add(unsigned long
 				(HA_CHUNK << PAGE_SHIFT));
 
 		if (ret) {
-			pr_info("hot_add memory failed error is %d\n", ret);
+			pr_warn("hot_add memory failed error is %d\n", ret);
 			if (ret == -EEXIST) {
 				/*
 				 * This error indicates that the error
@@ -814,6 +820,9 @@ static unsigned long handle_pg_range(uns
 	unsigned long old_covered_state;
 	unsigned long res = 0, flags;
 
+	pr_debug("Hot adding %lu pages starting at pfn 0x%lx.\n", pg_count,
+		pg_start);
+
 	spin_lock_irqsave(&dm_device.ha_lock, flags);
 	list_for_each_entry(has, &dm_device.ha_region_list, list) {
 		/*
@@ -1025,8 +1034,13 @@ static void process_info(struct hv_dynme
 
 	switch (info_hdr->type) {
 	case INFO_TYPE_MAX_PAGE_CNT:
-		pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n");
-		pr_info("Data Size is %d\n", info_hdr->data_size);
+		if (info_hdr->data_size == sizeof(__u64)) {
+			__u64 *max_page_count = (__u64 *)&info_hdr[1];
+
+			pr_info("INFO_TYPE_MAX_PAGE_CNT = %llu\n",
+				*max_page_count);
+		}
+
 		break;
 	default:
 		pr_info("Received Unknown type: %d\n", info_hdr->type);
@@ -1196,8 +1210,6 @@ static unsigned int alloc_balloon_pages(
 	return num_pages;
 }
 
-
-
 static void balloon_up(struct work_struct *dummy)
 {
 	unsigned int num_pages = dm_device.balloon_wrk.num_pages;
@@ -1224,6 +1236,10 @@ static void balloon_up(struct work_struc
 
 	/* Refuse to balloon below the floor, keep the 2M granularity. */
 	if (avail_pages < num_pages || avail_pages - num_pages < floor) {
+		pr_warn("Balloon request will be partially fulfilled. %s\n",
+			avail_pages < num_pages ? "Not enough memory." :
+			"Balloon floor reached.");
+
 		num_pages = avail_pages > floor ? (avail_pages - floor) : 0;
 		num_pages -= num_pages % PAGES_IN_2M;
 	}
@@ -1245,6 +1261,9 @@ static void balloon_up(struct work_struc
 		}
 
 		if (num_ballooned == 0 || num_ballooned == num_pages) {
+			pr_debug("Ballooned %u out of %u requested pages.\n",
+				num_pages, dm_device.balloon_wrk.num_pages);
+
 			bl_resp->more_pages = 0;
 			done = true;
 			dm_device.state = DM_INITIALIZED;
@@ -1292,12 +1311,16 @@ static void balloon_down(struct hv_dynme
 	int range_count = req->range_count;
 	struct dm_unballoon_response resp;
 	int i;
+	unsigned int prev_pages_ballooned = dm->num_pages_ballooned;
 
 	for (i = 0; i < range_count; i++) {
 		free_balloon_pages(dm, &range_array[i]);
 		complete(&dm_device.config_event);
 	}
 
+	pr_debug("Freed %u ballooned pages.\n",
+		prev_pages_ballooned - dm->num_pages_ballooned);
+
 	if (req->more_pages == 1)
 		return;
 
@@ -1365,6 +1388,7 @@ static void version_resp(struct hv_dynme
 	version_req.hdr.size = sizeof(struct dm_version_request);
 	version_req.hdr.trans_id = atomic_inc_return(&trans_id);
 	version_req.version.version = dm->next_version;
+	dm->version = version_req.version.version;
 
 	/*
 	 * Set the next version to try in case current version fails.
@@ -1501,7 +1525,11 @@ static int balloon_probe(struct hv_devic
 	struct dm_version_request version_req;
 	struct dm_capabilities cap_msg;
 
+#ifdef CONFIG_MEMORY_HOTPLUG
 	do_hot_add = hot_add;
+#else
+	do_hot_add = false;
+#endif
 
 	/*
 	 * First allocate a send buffer.
@@ -1553,6 +1581,7 @@ static int balloon_probe(struct hv_devic
 	version_req.hdr.trans_id = atomic_inc_return(&trans_id);
 	version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN10;
 	version_req.is_last_attempt = 0;
+	dm_device.version = version_req.version.version;
 
 	ret = vmbus_sendpacket(dev->channel, &version_req,
 				sizeof(struct dm_version_request),
@@ -1575,6 +1604,11 @@ static int balloon_probe(struct hv_devic
 		ret = -ETIMEDOUT;
 		goto probe_error2;
 	}
+
+	pr_info("Using Dynamic Memory protocol version %u.%u\n",
+		DYNMEM_MAJOR_VERSION(dm_device.version),
+		DYNMEM_MINOR_VERSION(dm_device.version));
+
 	/*
 	 * Now submit our capabilities to the host.
 	 */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/hv.c linux-libre-4.10-rc8-gnu/drivers/hv/hv.c
--- linux-libre-4.9-gnu/drivers/hv/hv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/hv.c	2017-02-12 16:03:20.000000000 -0500
@@ -135,9 +135,9 @@ u64 hv_do_hypercall(u64 control, void *i
 EXPORT_SYMBOL_GPL(hv_do_hypercall);
 
 #ifdef CONFIG_X86_64
-static cycle_t read_hv_clock_tsc(struct clocksource *arg)
+static u64 read_hv_clock_tsc(struct clocksource *arg)
 {
-	cycle_t current_tick;
+	u64 current_tick;
 	struct ms_hyperv_tsc_page *tsc_pg = hv_context.tsc_page;
 
 	if (tsc_pg->tsc_sequence != 0) {
@@ -146,7 +146,7 @@ static cycle_t read_hv_clock_tsc(struct
 		 */
 
 		while (1) {
-			cycle_t tmp;
+			u64 tmp;
 			u32 sequence = tsc_pg->tsc_sequence;
 			u64 cur_tsc;
 			u64 scale = tsc_pg->tsc_scale;
@@ -350,7 +350,7 @@ int hv_post_message(union hv_connection_
 static int hv_ce_set_next_event(unsigned long delta,
 				struct clock_event_device *evt)
 {
-	cycle_t current_tick;
+	u64 current_tick;
 
 	WARN_ON(!clockevent_state_oneshot(evt));
 
@@ -575,7 +575,7 @@ void hv_synic_clockevents_cleanup(void)
 	if (!(ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE))
 		return;
 
-	for_each_online_cpu(cpu)
+	for_each_present_cpu(cpu)
 		clockevents_unbind_device(hv_context.clk_evt[cpu], cpu);
 }
 
@@ -594,8 +594,10 @@ void hv_synic_cleanup(void *arg)
 		return;
 
 	/* Turn off clockevent device */
-	if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
+	if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE) {
+		clockevents_unbind_device(hv_context.clk_evt[cpu], cpu);
 		hv_ce_shutdown(hv_context.clk_evt[cpu]);
+	}
 
 	rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/hv_snapshot.c linux-libre-4.10-rc8-gnu/drivers/hv/hv_snapshot.c
--- linux-libre-4.9-gnu/drivers/hv/hv_snapshot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/hv_snapshot.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,10 @@
 #define VSS_MINOR  0
 #define VSS_VERSION    (VSS_MAJOR << 16 | VSS_MINOR)
 
-#define VSS_USERSPACE_TIMEOUT (msecs_to_jiffies(10 * 1000))
+/*
+ * Timeout values are based on expecations from host
+ */
+#define VSS_FREEZE_TIMEOUT (15 * 60)
 
 /*
  * Global state maintained for transaction that is being processed. For a class
@@ -120,7 +123,7 @@ static int vss_handle_handshake(struct h
 	default:
 		return -EINVAL;
 	}
-	pr_debug("VSS: userspace daemon ver. %d connected\n", dm_reg_value);
+	pr_info("VSS: userspace daemon ver. %d connected\n", dm_reg_value);
 	return 0;
 }
 
@@ -128,8 +131,10 @@ static int vss_on_msg(void *msg, int len
 {
 	struct hv_vss_msg *vss_msg = (struct hv_vss_msg *)msg;
 
-	if (len != sizeof(*vss_msg))
+	if (len != sizeof(*vss_msg)) {
+		pr_debug("VSS: Message size does not match length\n");
 		return -EINVAL;
+	}
 
 	if (vss_msg->vss_hdr.operation == VSS_OP_REGISTER ||
 	    vss_msg->vss_hdr.operation == VSS_OP_REGISTER1) {
@@ -137,8 +142,11 @@ static int vss_on_msg(void *msg, int len
 		 * Don't process registration messages if we're in the middle
 		 * of a transaction processing.
 		 */
-		if (vss_transaction.state > HVUTIL_READY)
+		if (vss_transaction.state > HVUTIL_READY) {
+			pr_debug("VSS: Got unexpected registration request\n");
 			return -EINVAL;
+		}
+
 		return vss_handle_handshake(vss_msg);
 	} else if (vss_transaction.state == HVUTIL_USERSPACE_REQ) {
 		vss_transaction.state = HVUTIL_USERSPACE_RECV;
@@ -155,7 +163,7 @@ static int vss_on_msg(void *msg, int len
 		}
 	} else {
 		/* This is a spurious call! */
-		pr_warn("VSS: Transaction not active\n");
+		pr_debug("VSS: Transaction not active\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -168,8 +176,10 @@ static void vss_send_op(void)
 	struct hv_vss_msg *vss_msg;
 
 	/* The transaction state is wrong. */
-	if (vss_transaction.state != HVUTIL_HOSTMSG_RECEIVED)
+	if (vss_transaction.state != HVUTIL_HOSTMSG_RECEIVED) {
+		pr_debug("VSS: Unexpected attempt to send to daemon\n");
 		return;
+	}
 
 	vss_msg = kzalloc(sizeof(*vss_msg), GFP_KERNEL);
 	if (!vss_msg)
@@ -179,7 +189,8 @@ static void vss_send_op(void)
 
 	vss_transaction.state = HVUTIL_USERSPACE_REQ;
 
-	schedule_delayed_work(&vss_timeout_work, VSS_USERSPACE_TIMEOUT);
+	schedule_delayed_work(&vss_timeout_work, op == VSS_OP_FREEZE ?
+			VSS_FREEZE_TIMEOUT * HZ : HV_UTIL_TIMEOUT * HZ);
 
 	rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL);
 	if (rc) {
@@ -210,9 +221,13 @@ static void vss_handle_request(struct wo
 	case VSS_OP_HOT_BACKUP:
 		if (vss_transaction.state < HVUTIL_READY) {
 			/* Userspace is not registered yet */
+			pr_debug("VSS: Not ready for request.\n");
 			vss_respond_to_host(HV_E_FAIL);
 			return;
 		}
+
+		pr_debug("VSS: Received request for op code: %d\n",
+			vss_transaction.msg->vss_hdr.operation);
 		vss_transaction.state = HVUTIL_HOSTMSG_RECEIVED;
 		vss_send_op();
 		return;
@@ -353,8 +368,10 @@ hv_vss_init(struct hv_util_service *srv)
 
 	hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL,
 				    vss_on_msg, vss_on_reset);
-	if (!hvt)
+	if (!hvt) {
+		pr_warn("VSS: Failed to initialize transport\n");
 		return -EFAULT;
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/hv_util.c linux-libre-4.10-rc8-gnu/drivers/hv/hv_util.c
--- linux-libre-4.9-gnu/drivers/hv/hv_util.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/hv_util.c	2017-02-12 16:03:20.000000000 -0500
@@ -389,16 +389,19 @@ static int util_probe(struct hv_device *
 		ts_srv_version = TS_VERSION_1;
 		hb_srv_version = HB_VERSION_1;
 		break;
-	case(VERSION_WIN10):
+	case VERSION_WIN7:
+	case VERSION_WIN8:
+	case VERSION_WIN8_1:
 		util_fw_version = UTIL_FW_VERSION;
 		sd_srv_version = SD_VERSION;
-		ts_srv_version = TS_VERSION;
+		ts_srv_version = TS_VERSION_3;
 		hb_srv_version = HB_VERSION;
 		break;
+	case VERSION_WIN10:
 	default:
 		util_fw_version = UTIL_FW_VERSION;
 		sd_srv_version = SD_VERSION;
-		ts_srv_version = TS_VERSION_3;
+		ts_srv_version = TS_VERSION;
 		hb_srv_version = HB_VERSION;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/hyperv_vmbus.h linux-libre-4.10-rc8-gnu/drivers/hv/hyperv_vmbus.h
--- linux-libre-4.9-gnu/drivers/hv/hyperv_vmbus.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/hyperv_vmbus.h	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 /*
  * Timeout for guest-host handshake for services.
  */
-#define HV_UTIL_NEGO_TIMEOUT 60
+#define HV_UTIL_NEGO_TIMEOUT 55
 
 /*
  * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent
@@ -527,14 +527,14 @@ int hv_ringbuffer_init(struct hv_ring_bu
 
 void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info);
 
-int hv_ringbuffer_write(struct hv_ring_buffer_info *ring_info,
+int hv_ringbuffer_write(struct vmbus_channel *channel,
 		    struct kvec *kv_list,
-		    u32 kv_count, bool *signal, bool lock,
-		    enum hv_signal_policy policy);
+		    u32 kv_count, bool lock,
+		    bool kick_q);
 
-int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
+int hv_ringbuffer_read(struct vmbus_channel *channel,
 		       void *buffer, u32 buflen, u32 *buffer_actual_len,
-		       u64 *requestid, bool *signal, bool raw);
+		       u64 *requestid, bool raw);
 
 void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info,
 			    struct hv_ring_buffer_debug_info *debug_info);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/ring_buffer.c linux-libre-4.10-rc8-gnu/drivers/hv/ring_buffer.c
--- linux-libre-4.9-gnu/drivers/hv/ring_buffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/ring_buffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,21 +66,25 @@ u32 hv_end_read(struct hv_ring_buffer_in
  *	   once the ring buffer is empty, it will clear the
  *	   interrupt_mask and re-check to see if new data has
  *	   arrived.
+ *
+ * KYS: Oct. 30, 2016:
+ * It looks like Windows hosts have logic to deal with DOS attacks that
+ * can be triggered if it receives interrupts when it is not expecting
+ * the interrupt. The host expects interrupts only when the ring
+ * transitions from empty to non-empty (or full to non full on the guest
+ * to host ring).
+ * So, base the signaling decision solely on the ring state until the
+ * host logic is fixed.
  */
 
-static bool hv_need_to_signal(u32 old_write, struct hv_ring_buffer_info *rbi,
-			      enum hv_signal_policy policy)
+static void hv_signal_on_write(u32 old_write, struct vmbus_channel *channel,
+			       bool kick_q)
 {
+	struct hv_ring_buffer_info *rbi = &channel->outbound;
+
 	virt_mb();
 	if (READ_ONCE(rbi->ring_buffer->interrupt_mask))
-		return false;
-
-	/*
-	 * When the client wants to control signaling,
-	 * we only honour the host interrupt mask.
-	 */
-	if (policy == HV_SIGNAL_POLICY_EXPLICIT)
-		return true;
+		return;
 
 	/* check interrupt_mask before read_index */
 	virt_rmb();
@@ -89,9 +93,9 @@ static bool hv_need_to_signal(u32 old_wr
 	 * ring transitions from being empty to non-empty.
 	 */
 	if (old_write == READ_ONCE(rbi->ring_buffer->read_index))
-		return true;
+		vmbus_setevent(channel);
 
-	return false;
+	return;
 }
 
 /* Get the next write location for the specified ring buffer. */
@@ -280,9 +284,9 @@ void hv_ringbuffer_cleanup(struct hv_rin
 }
 
 /* Write to the ring buffer. */
-int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info,
-		    struct kvec *kv_list, u32 kv_count, bool *signal, bool lock,
-		    enum hv_signal_policy policy)
+int hv_ringbuffer_write(struct vmbus_channel *channel,
+		    struct kvec *kv_list, u32 kv_count, bool lock,
+		    bool kick_q)
 {
 	int i = 0;
 	u32 bytes_avail_towrite;
@@ -292,6 +296,7 @@ int hv_ringbuffer_write(struct hv_ring_b
 	u32 old_write;
 	u64 prev_indices = 0;
 	unsigned long flags = 0;
+	struct hv_ring_buffer_info *outring_info = &channel->outbound;
 
 	for (i = 0; i < kv_count; i++)
 		totalbytes_towrite += kv_list[i].iov_len;
@@ -344,13 +349,13 @@ int hv_ringbuffer_write(struct hv_ring_b
 	if (lock)
 		spin_unlock_irqrestore(&outring_info->ring_lock, flags);
 
-	*signal = hv_need_to_signal(old_write, outring_info, policy);
+	hv_signal_on_write(old_write, channel, kick_q);
 	return 0;
 }
 
-int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info,
+int hv_ringbuffer_read(struct vmbus_channel *channel,
 		       void *buffer, u32 buflen, u32 *buffer_actual_len,
-		       u64 *requestid, bool *signal, bool raw)
+		       u64 *requestid, bool raw)
 {
 	u32 bytes_avail_toread;
 	u32 next_read_location = 0;
@@ -359,6 +364,7 @@ int hv_ringbuffer_read(struct hv_ring_bu
 	u32 offset;
 	u32 packetlen;
 	int ret = 0;
+	struct hv_ring_buffer_info *inring_info = &channel->inbound;
 
 	if (buflen <= 0)
 		return -EINVAL;
@@ -377,6 +383,7 @@ int hv_ringbuffer_read(struct hv_ring_bu
 		return ret;
 	}
 
+	init_cached_read_index(channel);
 	next_read_location = hv_get_next_read_location(inring_info);
 	next_read_location = hv_copyfrom_ringbuffer(inring_info, &desc,
 						    sizeof(desc),
@@ -416,7 +423,7 @@ int hv_ringbuffer_read(struct hv_ring_bu
 	/* Update the read index */
 	hv_set_next_read_location(inring_info, next_read_location);
 
-	*signal = hv_need_to_signal_on_read(inring_info);
+	hv_signal_on_read(channel);
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hv/vmbus_drv.c linux-libre-4.10-rc8-gnu/drivers/hv/vmbus_drv.c
--- linux-libre-4.9-gnu/drivers/hv/vmbus_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hv/vmbus_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,6 +45,11 @@
 #include <linux/random.h>
 #include "hyperv_vmbus.h"
 
+struct vmbus_dynid {
+	struct list_head node;
+	struct hv_vmbus_device_id id;
+};
+
 static struct acpi_device  *hv_acpi_dev;
 
 static struct completion probe_event;
@@ -500,7 +505,7 @@ static ssize_t device_show(struct device
 static DEVICE_ATTR_RO(device);
 
 /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
-static struct attribute *vmbus_attrs[] = {
+static struct attribute *vmbus_dev_attrs[] = {
 	&dev_attr_id.attr,
 	&dev_attr_state.attr,
 	&dev_attr_monitor_id.attr,
@@ -528,7 +533,7 @@ static struct attribute *vmbus_attrs[] =
 	&dev_attr_device.attr,
 	NULL,
 };
-ATTRIBUTE_GROUPS(vmbus);
+ATTRIBUTE_GROUPS(vmbus_dev);
 
 /*
  * vmbus_uevent - add uevent for our device
@@ -565,10 +570,29 @@ static inline bool is_null_guid(const uu
  * 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,
+static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv,
 					const uuid_le *guid)
 {
+	const struct hv_vmbus_device_id *id = NULL;
+	struct vmbus_dynid *dynid;
+
+	/* Look at the dynamic ids first, before the static ones */
+	spin_lock(&drv->dynids.lock);
+	list_for_each_entry(dynid, &drv->dynids.list, node) {
+		if (!uuid_le_cmp(dynid->id.guid, *guid)) {
+			id = &dynid->id;
+			break;
+		}
+	}
+	spin_unlock(&drv->dynids.lock);
+
+	if (id)
+		return id;
+
+	id = drv->id_table;
+	if (id == NULL)
+		return NULL; /* empty device table */
+
 	for (; !is_null_guid(&id->guid); id++)
 		if (!uuid_le_cmp(id->guid, *guid))
 			return id;
@@ -576,6 +600,134 @@ static const struct hv_vmbus_device_id *
 	return NULL;
 }
 
+/* vmbus_add_dynid - add a new device ID to this driver and re-probe devices */
+static int vmbus_add_dynid(struct hv_driver *drv, uuid_le *guid)
+{
+	struct vmbus_dynid *dynid;
+
+	dynid = kzalloc(sizeof(*dynid), GFP_KERNEL);
+	if (!dynid)
+		return -ENOMEM;
+
+	dynid->id.guid = *guid;
+
+	spin_lock(&drv->dynids.lock);
+	list_add_tail(&dynid->node, &drv->dynids.list);
+	spin_unlock(&drv->dynids.lock);
+
+	return driver_attach(&drv->driver);
+}
+
+static void vmbus_free_dynids(struct hv_driver *drv)
+{
+	struct vmbus_dynid *dynid, *n;
+
+	spin_lock(&drv->dynids.lock);
+	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
+		list_del(&dynid->node);
+		kfree(dynid);
+	}
+	spin_unlock(&drv->dynids.lock);
+}
+
+/* Parse string of form: 1b4e28ba-2fa1-11d2-883f-b9a761bde3f */
+static int get_uuid_le(const char *str, uuid_le *uu)
+{
+	unsigned int b[16];
+	int i;
+
+	if (strlen(str) < 37)
+		return -1;
+
+	for (i = 0; i < 36; i++) {
+		switch (i) {
+		case 8: case 13: case 18: case 23:
+			if (str[i] != '-')
+				return -1;
+			break;
+		default:
+			if (!isxdigit(str[i]))
+				return -1;
+		}
+	}
+
+	/* unparse little endian output byte order */
+	if (sscanf(str,
+		   "%2x%2x%2x%2x-%2x%2x-%2x%2x-%2x%2x-%2x%2x%2x%2x%2x%2x",
+		   &b[3], &b[2], &b[1], &b[0],
+		   &b[5], &b[4], &b[7], &b[6], &b[8], &b[9],
+		   &b[10], &b[11], &b[12], &b[13], &b[14], &b[15]) != 16)
+		return -1;
+
+	for (i = 0; i < 16; i++)
+		uu->b[i] = b[i];
+	return 0;
+}
+
+/*
+ * store_new_id - sysfs frontend to vmbus_add_dynid()
+ *
+ * Allow GUIDs to be added to an existing driver via sysfs.
+ */
+static ssize_t new_id_store(struct device_driver *driver, const char *buf,
+			    size_t count)
+{
+	struct hv_driver *drv = drv_to_hv_drv(driver);
+	uuid_le guid = NULL_UUID_LE;
+	ssize_t retval;
+
+	if (get_uuid_le(buf, &guid) != 0)
+		return -EINVAL;
+
+	if (hv_vmbus_get_id(drv, &guid))
+		return -EEXIST;
+
+	retval = vmbus_add_dynid(drv, &guid);
+	if (retval)
+		return retval;
+	return count;
+}
+static DRIVER_ATTR_WO(new_id);
+
+/*
+ * store_remove_id - remove a PCI device ID from this driver
+ *
+ * Removes a dynamic pci device ID to this driver.
+ */
+static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
+			       size_t count)
+{
+	struct hv_driver *drv = drv_to_hv_drv(driver);
+	struct vmbus_dynid *dynid, *n;
+	uuid_le guid = NULL_UUID_LE;
+	size_t retval = -ENODEV;
+
+	if (get_uuid_le(buf, &guid))
+		return -EINVAL;
+
+	spin_lock(&drv->dynids.lock);
+	list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
+		struct hv_vmbus_device_id *id = &dynid->id;
+
+		if (!uuid_le_cmp(id->guid, guid)) {
+			list_del(&dynid->node);
+			kfree(dynid);
+			retval = count;
+			break;
+		}
+	}
+	spin_unlock(&drv->dynids.lock);
+
+	return retval;
+}
+static DRIVER_ATTR_WO(remove_id);
+
+static struct attribute *vmbus_drv_attrs[] = {
+	&driver_attr_new_id.attr,
+	&driver_attr_remove_id.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(vmbus_drv);
 
 
 /*
@@ -590,7 +742,7 @@ static int vmbus_match(struct device *de
 	if (is_hvsock_channel(hv_dev->channel))
 		return drv->hvsock;
 
-	if (hv_vmbus_get_id(drv->id_table, &hv_dev->dev_type))
+	if (hv_vmbus_get_id(drv, &hv_dev->dev_type))
 		return 1;
 
 	return 0;
@@ -607,7 +759,7 @@ static int vmbus_probe(struct device *ch
 	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);
+	dev_id = hv_vmbus_get_id(drv, &dev->dev_type);
 	if (drv->probe) {
 		ret = drv->probe(dev, dev_id);
 		if (ret != 0)
@@ -684,7 +836,8 @@ static struct bus_type  hv_bus = {
 	.remove =		vmbus_remove,
 	.probe =		vmbus_probe,
 	.uevent =		vmbus_uevent,
-	.dev_groups =		vmbus_groups,
+	.dev_groups =		vmbus_dev_groups,
+	.drv_groups =		vmbus_drv_groups,
 };
 
 struct onmessage_work_context {
@@ -905,6 +1058,9 @@ int __vmbus_driver_register(struct hv_dr
 	hv_driver->driver.mod_name = mod_name;
 	hv_driver->driver.bus = &hv_bus;
 
+	spin_lock_init(&hv_driver->dynids.lock);
+	INIT_LIST_HEAD(&hv_driver->dynids.list);
+
 	ret = driver_register(&hv_driver->driver);
 
 	return ret;
@@ -923,8 +1079,10 @@ void vmbus_driver_unregister(struct hv_d
 {
 	pr_info("unregistering driver %s\n", hv_driver->name);
 
-	if (!vmbus_exists())
+	if (!vmbus_exists()) {
 		driver_unregister(&hv_driver->driver);
+		vmbus_free_dynids(hv_driver);
+	}
 }
 EXPORT_SYMBOL_GPL(vmbus_driver_unregister);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/adm1025.c linux-libre-4.10-rc8-gnu/drivers/hwmon/adm1025.c
--- linux-libre-4.9-gnu/drivers/hwmon/adm1025.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/adm1025.c	2017-02-12 16:03:20.000000000 -0500
@@ -93,7 +93,7 @@ static const int in_scale[6] = { 2500, 2
 
 #define IN_FROM_REG(reg, scale)	(((reg) * (scale) + 96) / 192)
 #define IN_TO_REG(val, scale)	((val) <= 0 ? 0 : \
-				 (val) * 192 >= (scale) * 255 ? 255 : \
+				 (val) >= (scale) * 255 / 192 ? 255 : \
 				 ((val) * 192 + (scale) / 2) / (scale))
 
 #define TEMP_FROM_REG(reg)	((reg) * 1000)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/adm1026.c linux-libre-4.10-rc8-gnu/drivers/hwmon/adm1026.c
--- linux-libre-4.9-gnu/drivers/hwmon/adm1026.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/adm1026.c	2017-02-12 16:03:20.000000000 -0500
@@ -197,8 +197,9 @@ static int adm1026_scaling[] = { /* .001
 	};
 #define NEG12_OFFSET  16000
 #define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from))
-#define INS_TO_REG(n, val)  (clamp_val(SCALE(val, adm1026_scaling[n], 192),\
-	0, 255))
+#define INS_TO_REG(n, val)	\
+		SCALE(clamp_val(val, 0, 255 * adm1026_scaling[n] / 192), \
+		      adm1026_scaling[n], 192)
 #define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n]))
 
 /*
@@ -215,11 +216,11 @@ static int adm1026_scaling[] = { /* .001
 #define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0)
 
 /* Temperature is reported in 1 degC increments */
-#define TEMP_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \
-					/ 1000, -127, 127))
+#define TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \
+					   1000)
 #define TEMP_FROM_REG(val) ((val) * 1000)
-#define OFFSET_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \
-					  / 1000, -127, 127))
+#define OFFSET_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \
+					     1000)
 #define OFFSET_FROM_REG(val) ((val) * 1000)
 
 #define PWM_TO_REG(val) (clamp_val(val, 0, 255))
@@ -233,7 +234,8 @@ static int adm1026_scaling[] = { /* .001
  *   indicates that the DAC could be used to drive the fans, but in our
  *   example board (Arima HDAMA) it isn't connected to the fans at all.
  */
-#define DAC_TO_REG(val) (clamp_val(((((val) * 255) + 500) / 2500), 0, 255))
+#define DAC_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, 0, 2500) * 255, \
+					  2500)
 #define DAC_FROM_REG(val) (((val) * 2500) / 255)
 
 /*
@@ -593,7 +595,10 @@ static ssize_t set_in16_min(struct devic
 		return err;
 
 	mutex_lock(&data->update_lock);
-	data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET);
+	data->in_min[16] = INS_TO_REG(16,
+				      clamp_val(val, INT_MIN,
+						INT_MAX - NEG12_OFFSET) +
+				      NEG12_OFFSET);
 	adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -618,7 +623,10 @@ static ssize_t set_in16_max(struct devic
 		return err;
 
 	mutex_lock(&data->update_lock);
-	data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET);
+	data->in_max[16] = INS_TO_REG(16,
+				      clamp_val(val, INT_MIN,
+						INT_MAX - NEG12_OFFSET) +
+				      NEG12_OFFSET);
 	adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]);
 	mutex_unlock(&data->update_lock);
 	return count;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/adm9240.c linux-libre-4.10-rc8-gnu/drivers/hwmon/adm9240.c
--- linux-libre-4.9-gnu/drivers/hwmon/adm9240.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/adm9240.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,13 +98,15 @@ static inline unsigned int IN_FROM_REG(u
 
 static inline u8 IN_TO_REG(unsigned long val, int n)
 {
-	return clamp_val(SCALE(val, 192, nom_mv[n]), 0, 255);
+	val = clamp_val(val, 0, nom_mv[n] * 255 / 192);
+	return SCALE(val, 192, nom_mv[n]);
 }
 
 /* temperature range: -40..125, 127 disables temperature alarm */
 static inline s8 TEMP_TO_REG(long val)
 {
-	return clamp_val(SCALE(val, 1, 1000), -40, 127);
+	val = clamp_val(val, -40000, 127000);
+	return SCALE(val, 1, 1000);
 }
 
 /* two fans, each with low fan speed limit */
@@ -122,7 +124,8 @@ static inline unsigned int FAN_FROM_REG(
 /* analog out 0..1250mV */
 static inline u8 AOUT_TO_REG(unsigned long val)
 {
-	return clamp_val(SCALE(val, 255, 1250), 0, 255);
+	val = clamp_val(val, 0, 1250);
+	return SCALE(val, 255, 1250);
 }
 
 static inline unsigned int AOUT_FROM_REG(u8 reg)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/adt7411.c linux-libre-4.10-rc8-gnu/drivers/hwmon/adt7411.c
--- linux-libre-4.9-gnu/drivers/hwmon/adt7411.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/adt7411.c	2017-02-12 16:03:20.000000000 -0500
@@ -55,7 +55,7 @@ struct adt7411_data {
 	struct mutex device_lock;	/* for "atomic" device accesses */
 	struct mutex update_lock;
 	unsigned long next_update;
-	int vref_cached;
+	long vref_cached;
 	struct i2c_client *client;
 	bool use_ext_temp;
 };
@@ -114,85 +114,6 @@ static int adt7411_modify_bit(struct i2c
 	return ret;
 }
 
-static ssize_t adt7411_show_vdd(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct adt7411_data *data = dev_get_drvdata(dev);
-	struct i2c_client *client = data->client;
-	int ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
-			ADT7411_REG_VDD_MSB, 2);
-
-	return ret < 0 ? ret : sprintf(buf, "%u\n", ret * 7000 / 1024);
-}
-
-static ssize_t adt7411_show_temp(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	int nr = to_sensor_dev_attr(attr)->index;
-	struct adt7411_data *data = dev_get_drvdata(dev);
-	struct i2c_client *client = data->client;
-	int val;
-	struct {
-		u8 low;
-		u8 high;
-	} reg[2] = {
-		{ ADT7411_REG_INT_TEMP_VDD_LSB, ADT7411_REG_INT_TEMP_MSB },
-		{ ADT7411_REG_EXT_TEMP_AIN14_LSB,
-		  ADT7411_REG_EXT_TEMP_AIN1_MSB },
-	};
-
-	val = adt7411_read_10_bit(client, reg[nr].low, reg[nr].high, 0);
-	if (val < 0)
-		return val;
-
-	val = val & 0x200 ? val - 0x400 : val; /* 10 bit signed */
-
-	return sprintf(buf, "%d\n", val * 250);
-}
-
-static ssize_t adt7411_show_input(struct device *dev,
-				  struct device_attribute *attr, char *buf)
-{
-	int nr = to_sensor_dev_attr(attr)->index;
-	struct adt7411_data *data = dev_get_drvdata(dev);
-	struct i2c_client *client = data->client;
-	int val;
-	u8 lsb_reg, lsb_shift;
-
-	mutex_lock(&data->update_lock);
-	if (time_after_eq(jiffies, data->next_update)) {
-		val = i2c_smbus_read_byte_data(client, ADT7411_REG_CFG3);
-		if (val < 0)
-			goto exit_unlock;
-
-		if (val & ADT7411_CFG3_REF_VDD) {
-			val = adt7411_read_10_bit(client,
-					ADT7411_REG_INT_TEMP_VDD_LSB,
-					ADT7411_REG_VDD_MSB, 2);
-			if (val < 0)
-				goto exit_unlock;
-
-			data->vref_cached = val * 7000 / 1024;
-		} else {
-			data->vref_cached = 2250;
-		}
-
-		data->next_update = jiffies + HZ;
-	}
-
-	lsb_reg = ADT7411_REG_EXT_TEMP_AIN14_LSB + (nr >> 2);
-	lsb_shift = 2 * (nr & 0x03);
-	val = adt7411_read_10_bit(client, lsb_reg,
-			ADT7411_REG_EXT_TEMP_AIN1_MSB + nr, lsb_shift);
-	if (val < 0)
-		goto exit_unlock;
-
-	val = sprintf(buf, "%u\n", val * data->vref_cached / 1024);
- exit_unlock:
-	mutex_unlock(&data->update_lock);
-	return val;
-}
-
 static ssize_t adt7411_show_bit(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -228,65 +149,157 @@ static ssize_t adt7411_set_bit(struct de
 	return ret < 0 ? ret : count;
 }
 
-
 #define ADT7411_BIT_ATTR(__name, __reg, __bit) \
 	SENSOR_DEVICE_ATTR_2(__name, S_IRUGO | S_IWUSR, adt7411_show_bit, \
 	adt7411_set_bit, __bit, __reg)
 
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7411_show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, adt7411_show_temp, NULL, 1);
-static DEVICE_ATTR(in0_input, S_IRUGO, adt7411_show_vdd, NULL);
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, adt7411_show_input, NULL, 0);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, adt7411_show_input, NULL, 1);
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, adt7411_show_input, NULL, 2);
-static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, adt7411_show_input, NULL, 3);
-static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, adt7411_show_input, NULL, 4);
-static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, adt7411_show_input, NULL, 5);
-static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, adt7411_show_input, NULL, 6);
-static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, adt7411_show_input, NULL, 7);
 static ADT7411_BIT_ATTR(no_average, ADT7411_REG_CFG2, ADT7411_CFG2_DISABLE_AVG);
 static ADT7411_BIT_ATTR(fast_sampling, ADT7411_REG_CFG3, ADT7411_CFG3_ADC_CLK_225);
 static ADT7411_BIT_ATTR(adc_ref_vdd, ADT7411_REG_CFG3, ADT7411_CFG3_REF_VDD);
 
 static struct attribute *adt7411_attrs[] = {
-	&sensor_dev_attr_temp1_input.dev_attr.attr,
-	&sensor_dev_attr_temp2_input.dev_attr.attr,
-	&dev_attr_in0_input.attr,
-	&sensor_dev_attr_in1_input.dev_attr.attr,
-	&sensor_dev_attr_in2_input.dev_attr.attr,
-	&sensor_dev_attr_in3_input.dev_attr.attr,
-	&sensor_dev_attr_in4_input.dev_attr.attr,
-	&sensor_dev_attr_in5_input.dev_attr.attr,
-	&sensor_dev_attr_in6_input.dev_attr.attr,
-	&sensor_dev_attr_in7_input.dev_attr.attr,
-	&sensor_dev_attr_in8_input.dev_attr.attr,
 	&sensor_dev_attr_no_average.dev_attr.attr,
 	&sensor_dev_attr_fast_sampling.dev_attr.attr,
 	&sensor_dev_attr_adc_ref_vdd.dev_attr.attr,
 	NULL
 };
+ATTRIBUTE_GROUPS(adt7411);
 
-static umode_t adt7411_attrs_visible(struct kobject *kobj,
-				     struct attribute *attr, int index)
+static int adt7411_read_in_vdd(struct device *dev, u32 attr, long *val)
 {
-	struct device *dev = container_of(kobj, struct device, kobj);
 	struct adt7411_data *data = dev_get_drvdata(dev);
-	bool visible = true;
+	struct i2c_client *client = data->client;
+	int ret;
 
-	if (attr == &sensor_dev_attr_temp2_input.dev_attr.attr)
-		visible = data->use_ext_temp;
-	else if (attr == &sensor_dev_attr_in1_input.dev_attr.attr ||
-		 attr == &sensor_dev_attr_in2_input.dev_attr.attr)
-		visible = !data->use_ext_temp;
+	switch (attr) {
+	case hwmon_in_input:
+		ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
+					  ADT7411_REG_VDD_MSB, 2);
+		if (ret < 0)
+			return ret;
+		*val = ret * 7000 / 1024;
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
 
-	return visible ? attr->mode : 0;
+static int adt7411_read_in_chan(struct device *dev, u32 attr, int channel,
+				long *val)
+{
+	struct adt7411_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+
+	int ret;
+	int lsb_reg, lsb_shift;
+	int nr = channel - 1;
+
+	mutex_lock(&data->update_lock);
+	if (time_after_eq(jiffies, data->next_update)) {
+		ret = i2c_smbus_read_byte_data(client, ADT7411_REG_CFG3);
+		if (ret < 0)
+			goto exit_unlock;
+
+		if (ret & ADT7411_CFG3_REF_VDD) {
+			ret = adt7411_read_in_vdd(dev, hwmon_in_input,
+						  &data->vref_cached);
+			if (ret < 0)
+				goto exit_unlock;
+		} else {
+			data->vref_cached = 2250;
+		}
+
+		data->next_update = jiffies + HZ;
+	}
+
+	switch (attr) {
+	case hwmon_in_input:
+		lsb_reg = ADT7411_REG_EXT_TEMP_AIN14_LSB + (nr >> 2);
+		lsb_shift = 2 * (nr & 0x03);
+		ret = adt7411_read_10_bit(client, lsb_reg,
+					  ADT7411_REG_EXT_TEMP_AIN1_MSB + nr,
+					  lsb_shift);
+		if (ret < 0)
+			goto exit_unlock;
+		*val = ret * data->vref_cached / 1024;
+		ret = 0;
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+ exit_unlock:
+	mutex_unlock(&data->update_lock);
+	return ret;
 }
 
-static const struct attribute_group adt7411_group = {
-	.attrs = adt7411_attrs,
-	.is_visible = adt7411_attrs_visible,
-};
-__ATTRIBUTE_GROUPS(adt7411);
+static int adt7411_read_in(struct device *dev, u32 attr, int channel,
+			   long *val)
+{
+	if (channel == 0)
+		return adt7411_read_in_vdd(dev, attr, val);
+	else
+		return adt7411_read_in_chan(dev, attr, channel, val);
+}
+
+static int adt7411_read_temp(struct device *dev, u32 attr, int channel,
+			     long *val)
+{
+	struct adt7411_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int ret, regl, regh;
+
+	switch (attr) {
+	case hwmon_temp_input:
+		regl = channel ? ADT7411_REG_EXT_TEMP_AIN14_LSB :
+				 ADT7411_REG_INT_TEMP_VDD_LSB;
+		regh = channel ? ADT7411_REG_EXT_TEMP_AIN1_MSB :
+				 ADT7411_REG_INT_TEMP_MSB;
+		ret = adt7411_read_10_bit(client, regl, regh, 0);
+		if (ret < 0)
+			return ret;
+		ret = ret & 0x200 ? ret - 0x400 : ret; /* 10 bit signed */
+		*val = ret * 250;
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int adt7411_read(struct device *dev, enum hwmon_sensor_types type,
+			u32 attr, int channel, long *val)
+{
+	switch (type) {
+	case hwmon_in:
+		return adt7411_read_in(dev, attr, channel, val);
+	case hwmon_temp:
+		return adt7411_read_temp(dev, attr, channel, val);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static umode_t adt7411_is_visible(const void *_data,
+				  enum hwmon_sensor_types type,
+				  u32 attr, int channel)
+{
+	const struct adt7411_data *data = _data;
+
+	switch (type) {
+	case hwmon_in:
+		if (channel > 0 && channel < 3)
+			return data->use_ext_temp ? 0 : S_IRUGO;
+		else
+			return S_IRUGO;
+	case hwmon_temp:
+		if (channel == 1)
+			return data->use_ext_temp ? S_IRUGO : 0;
+		else
+			return S_IRUGO;
+	default:
+		return 0;
+	}
+}
 
 static int adt7411_detect(struct i2c_client *client,
 			  struct i2c_board_info *info)
@@ -358,6 +371,51 @@ static int adt7411_init_device(struct ad
 	return i2c_smbus_write_byte_data(data->client, ADT7411_REG_CFG1, val);
 }
 
+static const u32 adt7411_in_config[] = {
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	HWMON_I_INPUT,
+	0
+};
+
+static const struct hwmon_channel_info adt7411_in = {
+	.type = hwmon_in,
+	.config = adt7411_in_config,
+};
+
+static const u32 adt7411_temp_config[] = {
+	HWMON_T_INPUT,
+	HWMON_T_INPUT,
+	0
+};
+
+static const struct hwmon_channel_info adt7411_temp = {
+	.type = hwmon_temp,
+	.config = adt7411_temp_config,
+};
+
+static const struct hwmon_channel_info *adt7411_info[] = {
+	&adt7411_in,
+	&adt7411_temp,
+	NULL
+};
+
+static const struct hwmon_ops adt7411_hwmon_ops = {
+	.is_visible = adt7411_is_visible,
+	.read = adt7411_read,
+};
+
+static const struct hwmon_chip_info adt7411_chip_info = {
+	.ops = &adt7411_hwmon_ops,
+	.info = adt7411_info,
+};
+
 static int adt7411_probe(struct i2c_client *client,
 				   const struct i2c_device_id *id)
 {
@@ -382,9 +440,10 @@ static int adt7411_probe(struct i2c_clie
 	/* force update on first occasion */
 	data->next_update = jiffies;
 
-	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
-							   data,
-							   adt7411_groups);
+	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+							 data,
+							 &adt7411_chip_info,
+							 adt7411_groups);
 	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/adt7462.c linux-libre-4.10-rc8-gnu/drivers/hwmon/adt7462.c
--- linux-libre-4.9-gnu/drivers/hwmon/adt7462.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/adt7462.c	2017-02-12 16:03:20.000000000 -0500
@@ -810,8 +810,8 @@ static ssize_t set_temp_min(struct devic
 	if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
 		return -EINVAL;
 
+	temp = clamp_val(temp, -64000, 191000);
 	temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
-	temp = clamp_val(temp, 0, 255);
 
 	mutex_lock(&data->lock);
 	data->temp_min[attr->index] = temp;
@@ -848,8 +848,8 @@ static ssize_t set_temp_max(struct devic
 	if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index))
 		return -EINVAL;
 
+	temp = clamp_val(temp, -64000, 191000);
 	temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
-	temp = clamp_val(temp, 0, 255);
 
 	mutex_lock(&data->lock);
 	data->temp_max[attr->index] = temp;
@@ -912,9 +912,9 @@ static ssize_t set_volt_max(struct devic
 	if (kstrtol(buf, 10, &temp) || !x)
 		return -EINVAL;
 
+	temp = clamp_val(temp, 0, 255 * x / 1000);
 	temp *= 1000; /* convert mV to uV */
 	temp = DIV_ROUND_CLOSEST(temp, x);
-	temp = clamp_val(temp, 0, 255);
 
 	mutex_lock(&data->lock);
 	data->volt_max[attr->index] = temp;
@@ -954,9 +954,9 @@ static ssize_t set_volt_min(struct devic
 	if (kstrtol(buf, 10, &temp) || !x)
 		return -EINVAL;
 
+	temp = clamp_val(temp, 0, 255 * x / 1000);
 	temp *= 1000; /* convert mV to uV */
 	temp = DIV_ROUND_CLOSEST(temp, x);
-	temp = clamp_val(temp, 0, 255);
 
 	mutex_lock(&data->lock);
 	data->volt_min[attr->index] = temp;
@@ -1220,8 +1220,8 @@ static ssize_t set_pwm_hyst(struct devic
 	if (kstrtol(buf, 10, &temp))
 		return -EINVAL;
 
+	temp = clamp_val(temp, 0, 15000);
 	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = clamp_val(temp, 0, 15);
 
 	/* package things up */
 	temp &= ADT7462_PWM_HYST_MASK;
@@ -1306,8 +1306,8 @@ static ssize_t set_pwm_tmin(struct devic
 	if (kstrtol(buf, 10, &temp))
 		return -EINVAL;
 
+	temp = clamp_val(temp, -64000, 191000);
 	temp = DIV_ROUND_CLOSEST(temp, 1000) + 64;
-	temp = clamp_val(temp, 0, 255);
 
 	mutex_lock(&data->lock);
 	data->pwm_tmin[attr->index] = temp;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/adt7470.c linux-libre-4.10-rc8-gnu/drivers/hwmon/adt7470.c
--- linux-libre-4.9-gnu/drivers/hwmon/adt7470.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/adt7470.c	2017-02-12 16:03:20.000000000 -0500
@@ -483,8 +483,8 @@ static ssize_t set_temp_min(struct devic
 	if (kstrtol(buf, 10, &temp))
 		return -EINVAL;
 
+	temp = clamp_val(temp, -128000, 127000);
 	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = clamp_val(temp, -128, 127);
 
 	mutex_lock(&data->lock);
 	data->temp_min[attr->index] = temp;
@@ -517,8 +517,8 @@ static ssize_t set_temp_max(struct devic
 	if (kstrtol(buf, 10, &temp))
 		return -EINVAL;
 
+	temp = clamp_val(temp, -128000, 127000);
 	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = clamp_val(temp, -128, 127);
 
 	mutex_lock(&data->lock);
 	data->temp_max[attr->index] = temp;
@@ -880,8 +880,8 @@ static ssize_t set_pwm_tmin(struct devic
 	if (kstrtol(buf, 10, &temp))
 		return -EINVAL;
 
+	temp = clamp_val(temp, -128000, 127000);
 	temp = DIV_ROUND_CLOSEST(temp, 1000);
-	temp = clamp_val(temp, -128, 127);
 
 	mutex_lock(&data->lock);
 	data->pwm_tmin[attr->index] = temp;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/amc6821.c linux-libre-4.10-rc8-gnu/drivers/hwmon/amc6821.c
--- linux-libre-4.9-gnu/drivers/hwmon/amc6821.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/amc6821.c	2017-02-12 16:03:20.000000000 -0500
@@ -188,8 +188,8 @@ static struct amc6821_data *amc6821_upda
 			!data->valid) {
 
 		for (i = 0; i < TEMP_IDX_LEN; i++)
-			data->temp[i] = i2c_smbus_read_byte_data(client,
-				temp_reg[i]);
+			data->temp[i] = (int8_t)i2c_smbus_read_byte_data(
+				client, temp_reg[i]);
 
 		data->stat1 = i2c_smbus_read_byte_data(client,
 			AMC6821_REG_STAT1);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/coretemp.c linux-libre-4.10-rc8-gnu/drivers/hwmon/coretemp.c
--- linux-libre-4.9-gnu/drivers/hwmon/coretemp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/coretemp.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,6 +51,7 @@ static int force_tjmax;
 module_param_named(tjmax, force_tjmax, int, 0444);
 MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
 
+#define PKG_SYSFS_ATTR_NO	1	/* Sysfs attribute for package temp */
 #define BASE_SYSFS_ATTR_NO	2	/* Sysfs Base attr no for coretemp */
 #define NUM_REAL_CORES		128	/* Number of Real cores per cpu */
 #define CORETEMP_NAME_LENGTH	19	/* String Length of attrs */
@@ -58,7 +59,6 @@ MODULE_PARM_DESC(tjmax, "TjMax value in
 #define TOTAL_ATTRS		(MAX_CORE_ATTRS + 1)
 #define MAX_CORE_DATA		(NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
 
-#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)
 
@@ -102,20 +102,17 @@ struct temp_data {
 
 /* Platform Data per Physical CPU */
 struct platform_data {
-	struct device *hwmon_dev;
-	u16 phys_proc_id;
-	struct temp_data *core_data[MAX_CORE_DATA];
+	struct device		*hwmon_dev;
+	u16			pkg_id;
+	struct cpumask		cpumask;
+	struct temp_data	*core_data[MAX_CORE_DATA];
 	struct device_attribute name_attr;
 };
 
-struct pdev_entry {
-	struct list_head list;
-	struct platform_device *pdev;
-	u16 phys_proc_id;
-};
-
-static LIST_HEAD(pdev_list);
-static DEFINE_MUTEX(pdev_list_mutex);
+/* Keep track of how many package pointers we allocated in init() */
+static int max_packages __read_mostly;
+/* Array of package pointers. Serialized by cpu hotplug lock */
+static struct platform_device **pkg_devices;
 
 static ssize_t show_label(struct device *dev,
 				struct device_attribute *devattr, char *buf)
@@ -125,7 +122,7 @@ static ssize_t show_label(struct device
 	struct temp_data *tdata = pdata->core_data[attr->index];
 
 	if (tdata->is_pkg_data)
-		return sprintf(buf, "Physical id %u\n", pdata->phys_proc_id);
+		return sprintf(buf, "Package id %u\n", pdata->pkg_id);
 
 	return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
 }
@@ -138,7 +135,9 @@ static ssize_t show_crit_alarm(struct de
 	struct platform_data *pdata = dev_get_drvdata(dev);
 	struct temp_data *tdata = pdata->core_data[attr->index];
 
+	mutex_lock(&tdata->update_lock);
 	rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
+	mutex_unlock(&tdata->update_lock);
 
 	return sprintf(buf, "%d\n", (eax >> 5) & 1);
 }
@@ -435,18 +434,10 @@ static int chk_ucode_version(unsigned in
 
 static struct platform_device *coretemp_get_pdev(unsigned int cpu)
 {
-	u16 phys_proc_id = TO_PHYS_ID(cpu);
-	struct pdev_entry *p;
-
-	mutex_lock(&pdev_list_mutex);
-
-	list_for_each_entry(p, &pdev_list, list)
-		if (p->phys_proc_id == phys_proc_id) {
-			mutex_unlock(&pdev_list_mutex);
-			return p->pdev;
-		}
+	int pkgid = topology_logical_package_id(cpu);
 
-	mutex_unlock(&pdev_list_mutex);
+	if (pkgid >= 0 && pkgid < max_packages)
+		return pkg_devices[pkgid];
 	return NULL;
 }
 
@@ -483,21 +474,11 @@ static int create_core_data(struct platf
 	 * The attr number is always core id + 2
 	 * The Pkgtemp will always show up as temp1_*, if available
 	 */
-	attr_no = pkg_flag ? 1 : TO_ATTR_NO(cpu);
+	attr_no = pkg_flag ? PKG_SYSFS_ATTR_NO : TO_ATTR_NO(cpu);
 
 	if (attr_no > MAX_CORE_DATA - 1)
 		return -ERANGE;
 
-	/*
-	 * Provide a single set of attributes for all HT siblings of a core
-	 * to avoid duplicate sensors (the processor ID and core ID of all
-	 * HT siblings of a core are the same).
-	 * Skip if a HT sibling of this core is already registered.
-	 * This is not an error.
-	 */
-	if (pdata->core_data[attr_no] != NULL)
-		return 0;
-
 	tdata = init_temp_data(cpu, pkg_flag);
 	if (!tdata)
 		return -ENOMEM;
@@ -539,21 +520,14 @@ exit_free:
 	return err;
 }
 
-static void coretemp_add_core(unsigned int cpu, int pkg_flag)
+static void
+coretemp_add_core(struct platform_device *pdev, unsigned int cpu, int pkg_flag)
 {
-	struct platform_device *pdev = coretemp_get_pdev(cpu);
-	int err;
-
-	if (!pdev)
-		return;
-
-	err = create_core_data(pdev, cpu, pkg_flag);
-	if (err)
+	if (create_core_data(pdev, cpu, pkg_flag))
 		dev_err(&pdev->dev, "Adding Core %u failed\n", cpu);
 }
 
-static void coretemp_remove_core(struct platform_data *pdata,
-				 int indx)
+static void coretemp_remove_core(struct platform_data *pdata, int indx)
 {
 	struct temp_data *tdata = pdata->core_data[indx];
 
@@ -574,7 +548,7 @@ static int coretemp_probe(struct platfor
 	if (!pdata)
 		return -ENOMEM;
 
-	pdata->phys_proc_id = pdev->id;
+	pdata->pkg_id = pdev->id;
 	platform_set_drvdata(pdev, pdata);
 
 	pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
@@ -602,85 +576,33 @@ static struct platform_driver coretemp_d
 	.remove = coretemp_remove,
 };
 
-static int coretemp_device_add(unsigned int cpu)
+static struct platform_device *coretemp_device_add(unsigned int cpu)
 {
-	int err;
+	int err, pkgid = topology_logical_package_id(cpu);
 	struct platform_device *pdev;
-	struct pdev_entry *pdev_entry;
 
-	mutex_lock(&pdev_list_mutex);
-
-	pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu));
-	if (!pdev) {
-		err = -ENOMEM;
-		pr_err("Device allocation failed\n");
-		goto exit;
-	}
+	if (pkgid < 0)
+		return ERR_PTR(-ENOMEM);
 
-	pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
-	if (!pdev_entry) {
-		err = -ENOMEM;
-		goto exit_device_put;
-	}
+	pdev = platform_device_alloc(DRVNAME, pkgid);
+	if (!pdev)
+		return ERR_PTR(-ENOMEM);
 
 	err = platform_device_add(pdev);
 	if (err) {
-		pr_err("Device addition failed (%d)\n", err);
-		goto exit_device_free;
-	}
-
-	pdev_entry->pdev = pdev;
-	pdev_entry->phys_proc_id = pdev->id;
-
-	list_add_tail(&pdev_entry->list, &pdev_list);
-	mutex_unlock(&pdev_list_mutex);
-
-	return 0;
-
-exit_device_free:
-	kfree(pdev_entry);
-exit_device_put:
-	platform_device_put(pdev);
-exit:
-	mutex_unlock(&pdev_list_mutex);
-	return err;
-}
-
-static void coretemp_device_remove(unsigned int cpu)
-{
-	struct pdev_entry *p, *n;
-	u16 phys_proc_id = TO_PHYS_ID(cpu);
-
-	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
-		if (p->phys_proc_id != phys_proc_id)
-			continue;
-		platform_device_unregister(p->pdev);
-		list_del(&p->list);
-		kfree(p);
+		platform_device_put(pdev);
+		return ERR_PTR(err);
 	}
-	mutex_unlock(&pdev_list_mutex);
-}
-
-static bool is_any_core_online(struct platform_data *pdata)
-{
-	int i;
 
-	/* Find online cores, except pkgtemp data */
-	for (i = MAX_CORE_DATA - 1; i >= 0; --i) {
-		if (pdata->core_data[i] &&
-			!pdata->core_data[i]->is_pkg_data) {
-			return true;
-		}
-	}
-	return false;
+	pkg_devices[pkgid] = pdev;
+	return pdev;
 }
 
-static void get_core_online(unsigned int cpu)
+static int coretemp_cpu_online(unsigned int cpu)
 {
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	struct platform_device *pdev = coretemp_get_pdev(cpu);
-	int err;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	struct platform_data *pdata;
 
 	/*
 	 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
@@ -688,12 +610,12 @@ static void get_core_online(unsigned int
 	 * without thermal sensors will be filtered out.
 	 */
 	if (!cpu_has(c, X86_FEATURE_DTHERM))
-		return;
+		return -ENODEV;
 
 	if (!pdev) {
 		/* Check the microcode version of the CPU */
 		if (chk_ucode_version(cpu))
-			return;
+			return -EINVAL;
 
 		/*
 		 * Alright, we have DTS support.
@@ -701,101 +623,100 @@ static void get_core_online(unsigned int
 		 * online. So, initialize per-pkg data structures and
 		 * then bring this core online.
 		 */
-		err = coretemp_device_add(cpu);
-		if (err)
-			return;
+		pdev = coretemp_device_add(cpu);
+		if (IS_ERR(pdev))
+			return PTR_ERR(pdev);
+
 		/*
 		 * Check whether pkgtemp support is available.
 		 * If so, add interfaces for pkgtemp.
 		 */
 		if (cpu_has(c, X86_FEATURE_PTS))
-			coretemp_add_core(cpu, 1);
+			coretemp_add_core(pdev, cpu, 1);
 	}
+
+	pdata = platform_get_drvdata(pdev);
 	/*
-	 * Physical CPU device already exists.
-	 * So, just add interfaces for this core.
+	 * Check whether a thread sibling is already online. If not add the
+	 * interface for this CPU core.
 	 */
-	coretemp_add_core(cpu, 0);
+	if (!cpumask_intersects(&pdata->cpumask, topology_sibling_cpumask(cpu)))
+		coretemp_add_core(pdev, cpu, 0);
+
+	cpumask_set_cpu(cpu, &pdata->cpumask);
+	return 0;
 }
 
-static void put_core_offline(unsigned int cpu)
+static int coretemp_cpu_offline(unsigned int cpu)
 {
-	int i, indx;
-	struct platform_data *pdata;
 	struct platform_device *pdev = coretemp_get_pdev(cpu);
+	struct platform_data *pd;
+	struct temp_data *tdata;
+	int indx, target;
 
 	/* If the physical CPU device does not exist, just return */
 	if (!pdev)
-		return;
-
-	pdata = platform_get_drvdata(pdev);
-
-	indx = TO_ATTR_NO(cpu);
+		return 0;
 
 	/* The core id is too big, just return */
+	indx = TO_ATTR_NO(cpu);
 	if (indx > MAX_CORE_DATA - 1)
-		return;
+		return 0;
 
-	if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu)
-		coretemp_remove_core(pdata, indx);
+	pd = platform_get_drvdata(pdev);
+	tdata = pd->core_data[indx];
+
+	cpumask_clear_cpu(cpu, &pd->cpumask);
 
 	/*
-	 * If a HT sibling of a core is taken offline, but another HT sibling
-	 * of the same core is still online, register the alternate sibling.
-	 * This ensures that exactly one set of attributes is provided as long
-	 * as at least one HT sibling of a core is online.
+	 * If this is the last thread sibling, remove the CPU core
+	 * interface, If there is still a sibling online, transfer the
+	 * target cpu of that core interface to it.
 	 */
-	for_each_sibling(i, cpu) {
-		if (i != cpu) {
-			get_core_online(i);
-			/*
-			 * Display temperature sensor data for one HT sibling
-			 * per core only, so abort the loop after one such
-			 * sibling has been found.
-			 */
-			break;
-		}
+	target = cpumask_any_and(&pd->cpumask, topology_sibling_cpumask(cpu));
+	if (target >= nr_cpu_ids) {
+		coretemp_remove_core(pd, indx);
+	} else if (tdata && tdata->cpu == cpu) {
+		mutex_lock(&tdata->update_lock);
+		tdata->cpu = target;
+		mutex_unlock(&tdata->update_lock);
 	}
+
 	/*
-	 * If all cores in this pkg are offline, remove the device.
-	 * coretemp_device_remove calls unregister_platform_device,
-	 * which in turn calls coretemp_remove. This removes the
-	 * pkgtemp entry and does other clean ups.
+	 * If all cores in this pkg are offline, remove the device. This
+	 * will invoke the platform driver remove function, which cleans up
+	 * the rest.
 	 */
-	if (!is_any_core_online(pdata))
-		coretemp_device_remove(cpu);
-}
-
-static int coretemp_cpu_callback(struct notifier_block *nfb,
-				 unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long) hcpu;
+	if (cpumask_empty(&pd->cpumask)) {
+		pkg_devices[topology_logical_package_id(cpu)] = NULL;
+		platform_device_unregister(pdev);
+		return 0;
+	}
 
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_DOWN_FAILED:
-		get_core_online(cpu);
-		break;
-	case CPU_DOWN_PREPARE:
-		put_core_offline(cpu);
-		break;
+	/*
+	 * Check whether this core is the target for the package
+	 * interface. We need to assign it to some other cpu.
+	 */
+	tdata = pd->core_data[PKG_SYSFS_ATTR_NO];
+	if (tdata && tdata->cpu == cpu) {
+		target = cpumask_first(&pd->cpumask);
+		mutex_lock(&tdata->update_lock);
+		tdata->cpu = target;
+		mutex_unlock(&tdata->update_lock);
 	}
-	return NOTIFY_OK;
+	return 0;
 }
-
-static struct notifier_block coretemp_cpu_notifier __refdata = {
-	.notifier_call = coretemp_cpu_callback,
-};
-
 static const struct x86_cpu_id __initconst coretemp_ids[] = {
 	{ X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM },
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, coretemp_ids);
 
+static enum cpuhp_state coretemp_hp_online;
+
 static int __init coretemp_init(void)
 {
-	int i, err;
+	int err;
 
 	/*
 	 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
@@ -805,54 +726,38 @@ static int __init coretemp_init(void)
 	if (!x86_match_cpu(coretemp_ids))
 		return -ENODEV;
 
+	max_packages = topology_max_packages();
+	pkg_devices = kzalloc(max_packages * sizeof(struct platform_device *),
+			      GFP_KERNEL);
+	if (!pkg_devices)
+		return -ENOMEM;
+
 	err = platform_driver_register(&coretemp_driver);
 	if (err)
-		goto exit;
-
-	cpu_notifier_register_begin();
-	for_each_online_cpu(i)
-		get_core_online(i);
-
-#ifndef CONFIG_HOTPLUG_CPU
-	if (list_empty(&pdev_list)) {
-		cpu_notifier_register_done();
-		err = -ENODEV;
-		goto exit_driver_unreg;
-	}
-#endif
+		return err;
 
-	__register_hotcpu_notifier(&coretemp_cpu_notifier);
-	cpu_notifier_register_done();
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/coretemp:online",
+				coretemp_cpu_online, coretemp_cpu_offline);
+	if (err < 0)
+		goto outdrv;
+	coretemp_hp_online = err;
 	return 0;
 
-#ifndef CONFIG_HOTPLUG_CPU
-exit_driver_unreg:
+outdrv:
 	platform_driver_unregister(&coretemp_driver);
-#endif
-exit:
+	kfree(pkg_devices);
 	return err;
 }
+module_init(coretemp_init)
 
 static void __exit coretemp_exit(void)
 {
-	struct pdev_entry *p, *n;
-
-	cpu_notifier_register_begin();
-	__unregister_hotcpu_notifier(&coretemp_cpu_notifier);
-	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
-		platform_device_unregister(p->pdev);
-		list_del(&p->list);
-		kfree(p);
-	}
-	mutex_unlock(&pdev_list_mutex);
-	cpu_notifier_register_done();
+	cpuhp_remove_state(coretemp_hp_online);
 	platform_driver_unregister(&coretemp_driver);
+	kfree(pkg_devices);
 }
+module_exit(coretemp_exit)
 
 MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");
 MODULE_DESCRIPTION("Intel Core temperature monitor");
 MODULE_LICENSE("GPL");
-
-module_init(coretemp_init)
-module_exit(coretemp_exit)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/ds620.c linux-libre-4.10-rc8-gnu/drivers/hwmon/ds620.c
--- linux-libre-4.9-gnu/drivers/hwmon/ds620.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/ds620.c	2017-02-12 16:03:20.000000000 -0500
@@ -166,7 +166,7 @@ static ssize_t set_temp(struct device *d
 	if (res)
 		return res;
 
-	val = (val * 10 / 625) * 8;
+	val = (clamp_val(val, -128000, 128000) * 10 / 625) * 8;
 
 	mutex_lock(&data->update_lock);
 	data->temp[attr->index] = val;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/emc2103.c linux-libre-4.10-rc8-gnu/drivers/hwmon/emc2103.c
--- linux-libre-4.9-gnu/drivers/hwmon/emc2103.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/emc2103.c	2017-02-12 16:03:20.000000000 -0500
@@ -251,7 +251,7 @@ static ssize_t set_temp_min(struct devic
 	if (result < 0)
 		return result;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -63, 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, -63000, 127000), 1000);
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[nr] = val;
@@ -273,7 +273,7 @@ static ssize_t set_temp_max(struct devic
 	if (result < 0)
 		return result;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -63, 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, -63000, 127000), 1000);
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = val;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/emc6w201.c linux-libre-4.10-rc8-gnu/drivers/hwmon/emc6w201.c
--- linux-libre-4.9-gnu/drivers/hwmon/emc6w201.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/emc6w201.c	2017-02-12 16:03:20.000000000 -0500
@@ -215,12 +215,13 @@ static ssize_t set_in(struct device *dev
 	if (err < 0)
 		return err;
 
-	val = DIV_ROUND_CLOSEST(val * 0xC0, nominal_mv[nr]);
+	val = clamp_val(val, 0, 255 * nominal_mv[nr] / 192);
+	val = DIV_ROUND_CLOSEST(val * 192, nominal_mv[nr]);
 	reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr)
 			  : EMC6W201_REG_IN_HIGH(nr);
 
 	mutex_lock(&data->update_lock);
-	data->in[sf][nr] = clamp_val(val, 0, 255);
+	data->in[sf][nr] = val;
 	err = emc6w201_write8(client, reg, data->in[sf][nr]);
 	mutex_unlock(&data->update_lock);
 
@@ -252,12 +253,13 @@ static ssize_t set_temp(struct device *d
 	if (err < 0)
 		return err;
 
+	val = clamp_val(val, -127000, 127000);
 	val = DIV_ROUND_CLOSEST(val, 1000);
 	reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr)
 			  : EMC6W201_REG_TEMP_HIGH(nr);
 
 	mutex_lock(&data->update_lock);
-	data->temp[sf][nr] = clamp_val(val, -127, 127);
+	data->temp[sf][nr] = val;
 	err = emc6w201_write8(client, reg, data->temp[sf][nr]);
 	mutex_unlock(&data->update_lock);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/g762.c linux-libre-4.10-rc8-gnu/drivers/hwmon/g762.c
--- linux-libre-4.9-gnu/drivers/hwmon/g762.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/g762.c	2017-02-12 16:03:20.000000000 -0500
@@ -193,14 +193,17 @@ static inline unsigned int rpm_from_cnt(
  * Convert fan RPM value from sysfs into count value for fan controller
  * register (FAN_SET_CNT).
  */
-static inline unsigned char cnt_from_rpm(u32 rpm, u32 clk_freq, u16 p,
+static inline unsigned char cnt_from_rpm(unsigned long rpm, u32 clk_freq, u16 p,
 					 u8 clk_div, u8 gear_mult)
 {
-	if (!rpm)         /* to stop the fan, set cnt to 255 */
+	unsigned long f1 = clk_freq * 30 * gear_mult;
+	unsigned long f2 = p * clk_div;
+
+	if (!rpm)	/* to stop the fan, set cnt to 255 */
 		return 0xff;
 
-	return clamp_val(((clk_freq * 30 * gear_mult) / (rpm * p * clk_div)),
-			 0, 255);
+	rpm = clamp_val(rpm, f1 / (255 * f2), ULONG_MAX / f2);
+	return DIV_ROUND_CLOSEST(f1, rpm * f2);
 }
 
 /* helper to grab and cache data, at most one time per second */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/hwmon.c linux-libre-4.10-rc8-gnu/drivers/hwmon/hwmon.c
--- linux-libre-4.9-gnu/drivers/hwmon/hwmon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/hwmon.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,12 +38,15 @@ struct hwmon_device {
 
 #define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
 
+#define MAX_SYSFS_ATTR_NAME_LENGTH	32
+
 struct hwmon_device_attribute {
 	struct device_attribute dev_attr;
 	const struct hwmon_ops *ops;
 	enum hwmon_sensor_types type;
 	u32 attr;
 	int index;
+	char name[MAX_SYSFS_ATTR_NAME_LENGTH];
 };
 
 #define to_hwmon_attr(d) \
@@ -178,6 +181,22 @@ static ssize_t hwmon_attr_show(struct de
 	return sprintf(buf, "%ld\n", val);
 }
 
+static ssize_t hwmon_attr_show_string(struct device *dev,
+				      struct device_attribute *devattr,
+				      char *buf)
+{
+	struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
+	char *s;
+	int ret;
+
+	ret = hattr->ops->read_string(dev, hattr->type, hattr->attr,
+				      hattr->index, &s);
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%s\n", s);
+}
+
 static ssize_t hwmon_attr_store(struct device *dev,
 				struct device_attribute *devattr,
 				const char *buf, size_t count)
@@ -205,6 +224,17 @@ static int hwmon_attr_base(enum hwmon_se
 	return 1;
 }
 
+static bool is_string_attr(enum hwmon_sensor_types type, u32 attr)
+{
+	return (type == hwmon_temp && attr == hwmon_temp_label) ||
+	       (type == hwmon_in && attr == hwmon_in_label) ||
+	       (type == hwmon_curr && attr == hwmon_curr_label) ||
+	       (type == hwmon_power && attr == hwmon_power_label) ||
+	       (type == hwmon_energy && attr == hwmon_energy_label) ||
+	       (type == hwmon_humidity && attr == hwmon_humidity_label) ||
+	       (type == hwmon_fan && attr == hwmon_fan_label);
+}
+
 static struct attribute *hwmon_genattr(struct device *dev,
 				       const void *drvdata,
 				       enum hwmon_sensor_types type,
@@ -218,6 +248,7 @@ static struct attribute *hwmon_genattr(s
 	struct attribute *a;
 	umode_t mode;
 	char *name;
+	bool is_string = is_string_attr(type, attr);
 
 	/* The attribute is invisible if there is no template string */
 	if (!template)
@@ -227,32 +258,31 @@ static struct attribute *hwmon_genattr(s
 	if (!mode)
 		return ERR_PTR(-ENOENT);
 
-	if ((mode & S_IRUGO) && !ops->read)
+	if ((mode & S_IRUGO) && ((is_string && !ops->read_string) ||
+				 (!is_string && !ops->read)))
 		return ERR_PTR(-EINVAL);
 	if ((mode & S_IWUGO) && !ops->write)
 		return ERR_PTR(-EINVAL);
 
+	hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL);
+	if (!hattr)
+		return ERR_PTR(-ENOMEM);
+
 	if (type == hwmon_chip) {
 		name = (char *)template;
 	} else {
-		name = devm_kzalloc(dev, strlen(template) + 16, GFP_KERNEL);
-		if (!name)
-			return ERR_PTR(-ENOMEM);
-		scnprintf(name, strlen(template) + 16, template,
+		scnprintf(hattr->name, sizeof(hattr->name), template,
 			  index + hwmon_attr_base(type));
+		name = hattr->name;
 	}
 
-	hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL);
-	if (!hattr)
-		return ERR_PTR(-ENOMEM);
-
 	hattr->type = type;
 	hattr->attr = attr;
 	hattr->index = index;
 	hattr->ops = ops;
 
 	dattr = &hattr->dev_attr;
-	dattr->show = hwmon_attr_show;
+	dattr->show = is_string ? hwmon_attr_show_string : hwmon_attr_show;
 	dattr->store = hwmon_attr_store;
 
 	a = &dattr->attr;
@@ -263,7 +293,11 @@ static struct attribute *hwmon_genattr(s
 	return a;
 }
 
-static const char * const hwmon_chip_attr_templates[] = {
+/*
+ * Chip attributes are not attribute templates but actual sysfs attributes.
+ * See hwmon_genattr() for special handling.
+ */
+static const char * const hwmon_chip_attrs[] = {
 	[hwmon_chip_temp_reset_history] = "temp_reset_history",
 	[hwmon_chip_in_reset_history] = "in_reset_history",
 	[hwmon_chip_curr_reset_history] = "curr_reset_history",
@@ -400,7 +434,7 @@ static const char * const hwmon_pwm_attr
 };
 
 static const char * const *__templates[] = {
-	[hwmon_chip] = hwmon_chip_attr_templates,
+	[hwmon_chip] = hwmon_chip_attrs,
 	[hwmon_temp] = hwmon_temp_attr_templates,
 	[hwmon_in] = hwmon_in_attr_templates,
 	[hwmon_curr] = hwmon_curr_attr_templates,
@@ -412,7 +446,7 @@ static const char * const *__templates[]
 };
 
 static const int __templates_size[] = {
-	[hwmon_chip] = ARRAY_SIZE(hwmon_chip_attr_templates),
+	[hwmon_chip] = ARRAY_SIZE(hwmon_chip_attrs),
 	[hwmon_temp] = ARRAY_SIZE(hwmon_temp_attr_templates),
 	[hwmon_in] = ARRAY_SIZE(hwmon_in_attr_templates),
 	[hwmon_curr] = ARRAY_SIZE(hwmon_curr_attr_templates),
@@ -526,9 +560,9 @@ __hwmon_device_register(struct device *d
 
 	hdev = &hwdev->dev;
 
-	if (chip && chip->ops->is_visible) {
+	if (chip) {
 		struct attribute **attrs;
-		int ngroups = 2;
+		int ngroups = 2; /* terminating NULL plus &hwdev->groups */
 
 		if (groups)
 			for (i = 0; groups[i]; i++)
@@ -572,7 +606,7 @@ __hwmon_device_register(struct device *d
 	if (err)
 		goto free_hwmon;
 
-	if (chip && chip->ops->is_visible && chip->ops->read &&
+	if (chip && chip->ops->read &&
 	    chip->info[0]->type == hwmon_chip &&
 	    (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
 		const struct hwmon_channel_info **info = chip->info;
@@ -626,8 +660,8 @@ EXPORT_SYMBOL_GPL(hwmon_device_register_
  * @dev: the parent device
  * @name: hwmon name attribute
  * @drvdata: driver data to attach to created device
- * @info: Pointer to hwmon chip information
- * @groups - pointer to list of driver specific attribute groups
+ * @info: pointer to hwmon chip information
+ * @extra_groups: pointer to list of additional non-standard attribute groups
  *
  * hwmon_device_unregister() must be called when the device is no
  * longer needed.
@@ -638,12 +672,12 @@ struct device *
 hwmon_device_register_with_info(struct device *dev, const char *name,
 				void *drvdata,
 				const struct hwmon_chip_info *chip,
-				const struct attribute_group **groups)
+				const struct attribute_group **extra_groups)
 {
-	if (chip && (!chip->ops || !chip->info))
+	if (chip && (!chip->ops || !chip->ops->is_visible || !chip->info))
 		return ERR_PTR(-EINVAL);
 
-	return __hwmon_device_register(dev, name, drvdata, chip, groups);
+	return __hwmon_device_register(dev, name, drvdata, chip, extra_groups);
 }
 EXPORT_SYMBOL_GPL(hwmon_device_register_with_info);
 
@@ -658,6 +692,9 @@ EXPORT_SYMBOL_GPL(hwmon_device_register_
  */
 struct device *hwmon_device_register(struct device *dev)
 {
+	dev_warn(dev,
+		 "hwmon_device_register() is deprecated. Please convert the driver to use hwmon_device_register_with_info().\n");
+
 	return hwmon_device_register_with_groups(dev, NULL, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(hwmon_device_register);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/Kconfig linux-libre-4.10-rc8-gnu/drivers/hwmon/Kconfig
--- linux-libre-4.9-gnu/drivers/hwmon/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -907,6 +907,17 @@ config SENSORS_MCP3021
 	  This driver can also be built as a module.  If so, the module
 	  will be called mcp3021.
 
+config SENSORS_TC654
+	tristate "Microchip TC654/TC655 and compatibles"
+	depends on I2C
+	help
+	  If you say yes here you get support for TC654 and TC655.
+	  The TC654 and TC655 are PWM mode fan speed controllers with
+	  FanSense technology for use with brushless DC fans.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tc654.
+
 config SENSORS_MENF21BMC_HWMON
 	tristate "MEN 14F021P00 BMC Hardware Monitoring"
 	depends on MFD_MENF21BMC
@@ -1068,8 +1079,8 @@ config SENSORS_LM90
 	  LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
 	  Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
 	  MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
-	  Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, and GMT G781
-	  sensor chips.
+	  Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, GMT G781, and
+	  Texas Instruments TMP451 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm90.
@@ -1591,6 +1602,17 @@ config SENSORS_TMP103
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp103.
 
+config SENSORS_TMP108
+	tristate "Texas Instruments TMP108"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  If you say yes here you get support for Texas Instruments TMP108
+	  sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tmp108.
+
 config SENSORS_TMP401
 	tristate "Texas Instruments TMP401 and compatibles"
 	depends on I2C
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/lm85.c linux-libre-4.10-rc8-gnu/drivers/hwmon/lm85.c
--- linux-libre-4.9-gnu/drivers/hwmon/lm85.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/lm85.c	2017-02-12 16:03:20.000000000 -0500
@@ -136,7 +136,8 @@ static const int lm85_scaling[] = {  /*
 #define SCALE(val, from, to)	(((val) * (to) + ((from) / 2)) / (from))
 
 #define INS_TO_REG(n, val)	\
-		clamp_val(SCALE(val, lm85_scaling[n], 192), 0, 255)
+		SCALE(clamp_val(val, 0, 255 * lm85_scaling[n] / 192), \
+		      lm85_scaling[n], 192)
 
 #define INSEXT_FROM_REG(n, val, ext)	\
 		SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n])
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/lm87.c linux-libre-4.10-rc8-gnu/drivers/hwmon/lm87.c
--- linux-libre-4.9-gnu/drivers/hwmon/lm87.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/lm87.c	2017-02-12 16:03:20.000000000 -0500
@@ -121,7 +121,7 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A,
 
 #define IN_FROM_REG(reg, scale)	(((reg) * (scale) + 96) / 192)
 #define IN_TO_REG(val, scale)	((val) <= 0 ? 0 : \
-				 (val) * 192 >= (scale) * 255 ? 255 : \
+				 (val) >= (scale) * 255 / 192 ? 255 : \
 				 ((val) * 192 + (scale) / 2) / (scale))
 
 #define TEMP_FROM_REG(reg)	((reg) * 1000)
@@ -154,7 +154,6 @@ static u8 LM87_REG_TEMP_LOW[3] = { 0x3A,
  */
 
 struct lm87_data {
-	struct device *hwmon_dev;
 	struct mutex update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* In jiffies */
@@ -181,6 +180,8 @@ struct lm87_data {
 	u16 alarms;		/* register values, combined */
 	u8 vid;			/* register values, combined */
 	u8 vrm;
+
+	const struct attribute_group *attr_groups[6];
 };
 
 static inline int lm87_read_value(struct i2c_client *client, u8 reg)
@@ -195,7 +196,7 @@ static inline int lm87_write_value(struc
 
 static struct lm87_data *lm87_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 
 	mutex_lock(&data->update_lock);
@@ -309,7 +310,7 @@ static ssize_t show_in_max(struct device
 static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
@@ -330,7 +331,7 @@ static ssize_t set_in_min(struct device
 static ssize_t set_in_max(struct device *dev,  struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
@@ -396,7 +397,7 @@ static ssize_t show_temp_high(struct dev
 static ssize_t set_temp_low(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
@@ -416,7 +417,7 @@ static ssize_t set_temp_low(struct devic
 static ssize_t set_temp_high(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
@@ -495,7 +496,7 @@ static ssize_t show_fan_div(struct devic
 static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
@@ -522,7 +523,7 @@ static ssize_t set_fan_min(struct device
 static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 			   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 	int nr = to_sensor_dev_attr(attr)->index;
 	long val;
@@ -635,7 +636,7 @@ static ssize_t show_aout(struct device *
 static ssize_t set_aout(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
+	struct i2c_client *client = dev_get_drvdata(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
 	long val;
 	int err;
@@ -841,23 +842,18 @@ static int lm87_detect(struct i2c_client
 	return 0;
 }
 
-static void lm87_remove_files(struct i2c_client *client)
+static void lm87_restore_config(void *arg)
 {
-	struct device *dev = &client->dev;
+	struct i2c_client *client = arg;
+	struct lm87_data *data = i2c_get_clientdata(client);
 
-	sysfs_remove_group(&dev->kobj, &lm87_group);
-	sysfs_remove_group(&dev->kobj, &lm87_group_in6);
-	sysfs_remove_group(&dev->kobj, &lm87_group_fan1);
-	sysfs_remove_group(&dev->kobj, &lm87_group_in7);
-	sysfs_remove_group(&dev->kobj, &lm87_group_fan2);
-	sysfs_remove_group(&dev->kobj, &lm87_group_temp3);
-	sysfs_remove_group(&dev->kobj, &lm87_group_in0_5);
-	sysfs_remove_group(&dev->kobj, &lm87_group_vid);
+	lm87_write_value(client, LM87_REG_CONFIG, data->config);
 }
 
-static void lm87_init_client(struct i2c_client *client)
+static int lm87_init_client(struct i2c_client *client)
 {
 	struct lm87_data *data = i2c_get_clientdata(client);
+	int rc;
 
 	if (dev_get_platdata(&client->dev)) {
 		data->channel = *(u8 *)dev_get_platdata(&client->dev);
@@ -868,6 +864,10 @@ static void lm87_init_client(struct i2c_
 	}
 	data->config = lm87_read_value(client, LM87_REG_CONFIG) & 0x6F;
 
+	rc = devm_add_action(&client->dev, lm87_restore_config, client);
+	if (rc)
+		return rc;
+
 	if (!(data->config & 0x01)) {
 		int i;
 
@@ -895,12 +895,15 @@ static void lm87_init_client(struct i2c_
 	if ((data->config & 0x09) != 0x01)
 		lm87_write_value(client, LM87_REG_CONFIG,
 				 (data->config & 0x77) | 0x01);
+	return 0;
 }
 
 static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct lm87_data *data;
+	struct device *hwmon_dev;
 	int err;
+	unsigned int group_tail = 0;
 
 	data = devm_kzalloc(&client->dev, sizeof(struct lm87_data), GFP_KERNEL);
 	if (!data)
@@ -910,7 +913,9 @@ static int lm87_probe(struct i2c_client
 	mutex_init(&data->update_lock);
 
 	/* Initialize the LM87 chip */
-	lm87_init_client(client);
+	err = lm87_init_client(client);
+	if (err)
+		return err;
 
 	data->in_scale[0] = 2500;
 	data->in_scale[1] = 2700;
@@ -921,72 +926,34 @@ static int lm87_probe(struct i2c_client
 	data->in_scale[6] = 1875;
 	data->in_scale[7] = 1875;
 
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &lm87_group);
-	if (err)
-		goto exit_stop;
-
-	if (data->channel & CHAN_NO_FAN(0)) {
-		err = sysfs_create_group(&client->dev.kobj, &lm87_group_in6);
-		if (err)
-			goto exit_remove;
-	} else {
-		err = sysfs_create_group(&client->dev.kobj, &lm87_group_fan1);
-		if (err)
-			goto exit_remove;
-	}
+	/*
+	 * Construct the list of attributes, the list depends on the
+	 * configuration of the chip
+	 */
+	data->attr_groups[group_tail++] = &lm87_group;
+	if (data->channel & CHAN_NO_FAN(0))
+		data->attr_groups[group_tail++] = &lm87_group_in6;
+	else
+		data->attr_groups[group_tail++] = &lm87_group_fan1;
 
-	if (data->channel & CHAN_NO_FAN(1)) {
-		err = sysfs_create_group(&client->dev.kobj, &lm87_group_in7);
-		if (err)
-			goto exit_remove;
-	} else {
-		err = sysfs_create_group(&client->dev.kobj, &lm87_group_fan2);
-		if (err)
-			goto exit_remove;
-	}
+	if (data->channel & CHAN_NO_FAN(1))
+		data->attr_groups[group_tail++] = &lm87_group_in7;
+	else
+		data->attr_groups[group_tail++] = &lm87_group_fan2;
 
-	if (data->channel & CHAN_TEMP3) {
-		err = sysfs_create_group(&client->dev.kobj, &lm87_group_temp3);
-		if (err)
-			goto exit_remove;
-	} else {
-		err = sysfs_create_group(&client->dev.kobj, &lm87_group_in0_5);
-		if (err)
-			goto exit_remove;
-	}
+	if (data->channel & CHAN_TEMP3)
+		data->attr_groups[group_tail++] = &lm87_group_temp3;
+	else
+		data->attr_groups[group_tail++] = &lm87_group_in0_5;
 
 	if (!(data->channel & CHAN_NO_VID)) {
 		data->vrm = vid_which_vrm();
-		err = sysfs_create_group(&client->dev.kobj, &lm87_group_vid);
-		if (err)
-			goto exit_remove;
-	}
-
-	data->hwmon_dev = hwmon_device_register(&client->dev);
-	if (IS_ERR(data->hwmon_dev)) {
-		err = PTR_ERR(data->hwmon_dev);
-		goto exit_remove;
+		data->attr_groups[group_tail++] = &lm87_group_vid;
 	}
 
-	return 0;
-
-exit_remove:
-	lm87_remove_files(client);
-exit_stop:
-	lm87_write_value(client, LM87_REG_CONFIG, data->config);
-	return err;
-}
-
-static int lm87_remove(struct i2c_client *client)
-{
-	struct lm87_data *data = i2c_get_clientdata(client);
-
-	hwmon_device_unregister(data->hwmon_dev);
-	lm87_remove_files(client);
-
-	lm87_write_value(client, LM87_REG_CONFIG, data->config);
-	return 0;
+	hwmon_dev = devm_hwmon_device_register_with_groups(
+	    &client->dev, client->name, client, data->attr_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
 }
 
 /*
@@ -1006,7 +973,6 @@ static struct i2c_driver lm87_driver = {
 		.name	= "lm87",
 	},
 	.probe		= lm87_probe,
-	.remove		= lm87_remove,
 	.id_table	= lm87_id,
 	.detect		= lm87_detect,
 	.address_list	= normal_i2c,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/lm90.c linux-libre-4.10-rc8-gnu/drivers/hwmon/lm90.c
--- linux-libre-4.9-gnu/drivers/hwmon/lm90.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/lm90.c	2017-02-12 16:03:20.000000000 -0500
@@ -1036,7 +1036,7 @@ static const u8 lm90_temp_emerg_index[3]
 };
 
 static const u8 lm90_min_alarm_bits[3] = { 5, 3, 11 };
-static const u8 lm90_max_alarm_bits[3] = { 0, 4, 12 };
+static const u8 lm90_max_alarm_bits[3] = { 6, 4, 12 };
 static const u8 lm90_crit_alarm_bits[3] = { 0, 1, 9 };
 static const u8 lm90_emergency_alarm_bits[3] = { 15, 13, 14 };
 static const u8 lm90_fault_bits[3] = { 0, 2, 10 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/Makefile linux-libre-4.10-rc8-gnu/drivers/hwmon/Makefile
--- linux-libre-4.9-gnu/drivers/hwmon/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -122,6 +122,7 @@ obj-$(CONFIG_SENSORS_MAX6697)	+= max6697
 obj-$(CONFIG_SENSORS_MAX31790)	+= max31790.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
 obj-$(CONFIG_SENSORS_MCP3021)	+= mcp3021.o
+obj-$(CONFIG_SENSORS_TC654)	+= tc654.o
 obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
 obj-$(CONFIG_SENSORS_NCT6683)	+= nct6683.o
 obj-$(CONFIG_SENSORS_NCT6775)	+= nct6775.o
@@ -152,6 +153,7 @@ obj-$(CONFIG_SENSORS_TC74)	+= tc74.o
 obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
 obj-$(CONFIG_SENSORS_TMP102)	+= tmp102.o
 obj-$(CONFIG_SENSORS_TMP103)	+= tmp103.o
+obj-$(CONFIG_SENSORS_TMP108)	+= tmp108.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
 obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/mcp3021.c linux-libre-4.10-rc8-gnu/drivers/hwmon/mcp3021.c
--- linux-libre-4.9-gnu/drivers/hwmon/mcp3021.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/mcp3021.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,6 +4,7 @@
  * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc.
  * Author: Mingkai Hu <Mingkai.hu@freescale.com>
  * Reworked by Sven Schuchmann <schuchmann@schleissheimer.de>
+ * DT support added by Clemens Gruber <clemens.gruber@pqgruber.com>
  *
  * This driver export the value of analog input voltage to sysfs, the
  * voltage unit is mV. Through the sysfs interface, lm-sensors tool
@@ -22,11 +23,13 @@
 #include <linux/i2c.h>
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
-/* Vdd info */
-#define MCP3021_VDD_MAX		5500
-#define MCP3021_VDD_MIN		2700
-#define MCP3021_VDD_REF		3300
+/* Vdd / reference voltage in millivolt */
+#define MCP3021_VDD_REF_MAX	5500
+#define MCP3021_VDD_REF_MIN	2700
+#define MCP3021_VDD_REF_DEFAULT	3300
 
 /* output format */
 #define MCP3021_SAR_SHIFT	2
@@ -47,7 +50,7 @@ enum chips {
  */
 struct mcp3021_data {
 	struct device *hwmon_dev;
-	u32 vdd;	/* device power supply */
+	u32 vdd;        /* supply and reference voltage in millivolt */
 	u16 sar_shift;
 	u16 sar_mask;
 	u8 output_res;
@@ -99,13 +102,14 @@ static ssize_t show_in_input(struct devi
 	return sprintf(buf, "%d\n", in_input);
 }
 
-static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL);
+static DEVICE_ATTR(in0_input, 0444, show_in_input, NULL);
 
 static int mcp3021_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	int err;
 	struct mcp3021_data *data = NULL;
+	struct device_node *np = client->dev.of_node;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
 		return -ENODEV;
@@ -117,6 +121,21 @@ static int mcp3021_probe(struct i2c_clie
 
 	i2c_set_clientdata(client, data);
 
+	if (np) {
+		if (!of_property_read_u32(np, "reference-voltage-microvolt",
+					  &data->vdd))
+			data->vdd /= 1000;
+		else
+			data->vdd = MCP3021_VDD_REF_DEFAULT;
+	} else {
+		u32 *pdata = dev_get_platdata(&client->dev);
+
+		if (pdata)
+			data->vdd = *pdata;
+		else
+			data->vdd = MCP3021_VDD_REF_DEFAULT;
+	}
+
 	switch (id->driver_data) {
 	case mcp3021:
 		data->sar_shift = MCP3021_SAR_SHIFT;
@@ -131,13 +150,8 @@ static int mcp3021_probe(struct i2c_clie
 		break;
 	}
 
-	if (dev_get_platdata(&client->dev)) {
-		data->vdd = *(u32 *)dev_get_platdata(&client->dev);
-		if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN)
-			return -EINVAL;
-	} else {
-		data->vdd = MCP3021_VDD_REF;
-	}
+	if (data->vdd > MCP3021_VDD_REF_MAX || data->vdd < MCP3021_VDD_REF_MIN)
+		return -EINVAL;
 
 	err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr);
 	if (err)
@@ -173,9 +187,19 @@ static const struct i2c_device_id mcp302
 };
 MODULE_DEVICE_TABLE(i2c, mcp3021_id);
 
+#ifdef CONFIG_OF
+static const struct of_device_id of_mcp3021_match[] = {
+	{ .compatible = "microchip,mcp3021", .data = (void *)mcp3021 },
+	{ .compatible = "microchip,mcp3221", .data = (void *)mcp3221 },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, of_mcp3021_match);
+#endif
+
 static struct i2c_driver mcp3021_driver = {
 	.driver = {
 		.name = "mcp3021",
+		.of_match_table = of_match_ptr(of_mcp3021_match),
 	},
 	.probe = mcp3021_probe,
 	.remove = mcp3021_remove,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/nct7802.c linux-libre-4.10-rc8-gnu/drivers/hwmon/nct7802.c
--- linux-libre-4.9-gnu/drivers/hwmon/nct7802.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/nct7802.c	2017-02-12 16:03:20.000000000 -0500
@@ -259,13 +259,15 @@ static int nct7802_read_fan_min(struct n
 		ret = 0;
 	else if (ret)
 		ret = DIV_ROUND_CLOSEST(1350000U, ret);
+	else
+		ret = 1350000U;
 abort:
 	mutex_unlock(&data->access_lock);
 	return ret;
 }
 
 static int nct7802_write_fan_min(struct nct7802_data *data, u8 reg_fan_low,
-				 u8 reg_fan_high, unsigned int limit)
+				 u8 reg_fan_high, unsigned long limit)
 {
 	int err;
 
@@ -326,8 +328,8 @@ static int nct7802_write_voltage(struct
 	int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
 	int err;
 
+	voltage = clamp_val(voltage, 0, 0x3ff * nct7802_vmul[nr]);
 	voltage = DIV_ROUND_CLOSEST(voltage, nct7802_vmul[nr]);
-	voltage = clamp_val(voltage, 0, 0x3ff);
 
 	mutex_lock(&data->access_lock);
 	err = regmap_write(data->regmap,
@@ -402,7 +404,7 @@ static ssize_t store_temp(struct device
 	if (err < 0)
 		return err;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
 
 	err = regmap_write(data->regmap, nr, val & 0xff);
 	return err ? : count;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/pmbus/adm1275.c linux-libre-4.10-rc8-gnu/drivers/hwmon/pmbus/adm1275.c
--- linux-libre-4.9-gnu/drivers/hwmon/pmbus/adm1275.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/pmbus/adm1275.c	2017-02-12 16:03:20.000000000 -0500
@@ -499,15 +499,27 @@ static int adm1275_probe(struct i2c_clie
 		pindex = 2;
 		tindex = 3;
 
-		info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT;
+		info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT |
+			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+
+		/* Enable VOUT if not enabled (it is disabled by default) */
+		if (!(config & ADM1278_VOUT_EN)) {
+			config |= ADM1278_VOUT_EN;
+			ret = i2c_smbus_write_byte_data(client,
+							ADM1275_PMON_CONFIG,
+							config);
+			if (ret < 0) {
+				dev_err(&client->dev,
+					"Failed to enable VOUT monitoring\n");
+				return -ENODEV;
+			}
+		}
+
 		if (config & ADM1278_TEMP1_EN)
 			info->func[0] |=
 				PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
 		if (config & ADM1278_VIN_EN)
 			info->func[0] |= PMBUS_HAVE_VIN;
-		if (config & ADM1278_VOUT_EN)
-			info->func[0] |=
-				PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
 		break;
 	case adm1293:
 	case adm1294:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/scpi-hwmon.c linux-libre-4.10-rc8-gnu/drivers/hwmon/scpi-hwmon.c
--- linux-libre-4.9-gnu/drivers/hwmon/scpi-hwmon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/scpi-hwmon.c	2017-02-12 16:03:20.000000000 -0500
@@ -251,6 +251,7 @@ static const struct of_device_id scpi_of
 	{.compatible = "arm,scpi-sensors"},
 	{},
 };
+MODULE_DEVICE_TABLE(of, scpi_of_match);
 
 static struct platform_driver scpi_hwmon_platdrv = {
 	.driver = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/smsc47m192.c linux-libre-4.10-rc8-gnu/drivers/hwmon/smsc47m192.c
--- linux-libre-4.9-gnu/drivers/hwmon/smsc47m192.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/smsc47m192.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,14 +77,15 @@ static inline unsigned int IN_FROM_REG(u
 
 static inline u8 IN_TO_REG(unsigned long val, int n)
 {
-	return clamp_val(SCALE(val, 192, nom_mv[n]), 0, 255);
+	val = clamp_val(val, 0, nom_mv[n] * 255 / 192);
+	return SCALE(val, 192, nom_mv[n]);
 }
 
 /*
  * TEMP: 0.001 degC units (-128C to +127C)
  * REG: 1C/bit, two's complement
  */
-static inline s8 TEMP_TO_REG(int val)
+static inline s8 TEMP_TO_REG(long val)
 {
 	return SCALE(clamp_val(val, -128000, 127000), 1, 1000);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/tc654.c linux-libre-4.10-rc8-gnu/drivers/hwmon/tc654.c
--- linux-libre-4.9-gnu/drivers/hwmon/tc654.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/tc654.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,514 @@
+/*
+ * tc654.c - Linux kernel modules for fan speed controller
+ *
+ * Copyright (C) 2016 Allied Telesis Labs NZ
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/bitops.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/util_macros.h>
+
+enum tc654_regs {
+	TC654_REG_RPM1 = 0x00,	/* RPM Output 1 */
+	TC654_REG_RPM2 = 0x01,	/* RPM Output 2 */
+	TC654_REG_FAN_FAULT1 = 0x02,	/* Fan Fault 1 Threshold */
+	TC654_REG_FAN_FAULT2 = 0x03,	/* Fan Fault 2 Threshold */
+	TC654_REG_CONFIG = 0x04,	/* Configuration */
+	TC654_REG_STATUS = 0x05,	/* Status */
+	TC654_REG_DUTY_CYCLE = 0x06,	/* Fan Speed Duty Cycle */
+	TC654_REG_MFR_ID = 0x07,	/* Manufacturer Identification */
+	TC654_REG_VER_ID = 0x08,	/* Version Identification */
+};
+
+/* Macros to easily index the registers */
+#define TC654_REG_RPM(idx)		(TC654_REG_RPM1 + (idx))
+#define TC654_REG_FAN_FAULT(idx)	(TC654_REG_FAN_FAULT1 + (idx))
+
+/* Config register bits */
+#define TC654_REG_CONFIG_RES		BIT(6)	/* Resolution Selection */
+#define TC654_REG_CONFIG_DUTYC		BIT(5)	/* Duty Cycle Control */
+#define TC654_REG_CONFIG_SDM		BIT(0)	/* Shutdown Mode */
+
+/* Status register bits */
+#define TC654_REG_STATUS_F2F		BIT(1)	/* Fan 2 Fault */
+#define TC654_REG_STATUS_F1F		BIT(0)	/* Fan 1 Fault */
+
+/* RPM resolution for RPM Output registers */
+#define TC654_HIGH_RPM_RESOLUTION	25	/* 25 RPM resolution */
+#define TC654_LOW_RPM_RESOLUTION	50	/* 50 RPM resolution */
+
+/* Convert to the fan fault RPM threshold from register value */
+#define TC654_FAN_FAULT_FROM_REG(val)	((val) * 50)	/* 50 RPM resolution */
+
+/* Convert to register value from the fan fault RPM threshold */
+#define TC654_FAN_FAULT_TO_REG(val)	(((val) / 50) & 0xff)
+
+/* Register data is read (and cached) at most once per second. */
+#define TC654_UPDATE_INTERVAL		HZ
+
+struct tc654_data {
+	struct i2c_client *client;
+
+	/* update mutex */
+	struct mutex update_lock;
+
+	/* tc654 register cache */
+	bool valid;
+	unsigned long last_updated;	/* in jiffies */
+
+	u8 rpm_output[2];	/* The fan RPM data for fans 1 and 2 is then
+				 * written to registers RPM1 and RPM2
+				 */
+	u8 fan_fault[2];	/* The Fan Fault Threshold Registers are used to
+				 * set the fan fault threshold levels for fan 1
+				 * and fan 2
+				 */
+	u8 config;	/* The Configuration Register is an 8-bit read/
+			 * writable multi-function control register
+			 *   7: Fan Fault Clear
+			 *      1 = Clear Fan Fault
+			 *      0 = Normal Operation (default)
+			 *   6: Resolution Selection for RPM Output Registers
+			 *      RPM Output Registers (RPM1 and RPM2) will be
+			 *      set for
+			 *      1 = 25 RPM (9-bit) resolution
+			 *      0 = 50 RPM (8-bit) resolution (default)
+			 *   5: Duty Cycle Control Method
+			 *      The V OUT duty cycle will be controlled via
+			 *      1 = the SMBus interface.
+			 *      0 = via the V IN analog input pin. (default)
+			 * 4,3: Fan 2 Pulses Per Rotation
+			 *      00 = 1
+			 *      01 = 2 (default)
+			 *      10 = 4
+			 *      11 = 8
+			 * 2,1: Fan 1 Pulses Per Rotation
+			 *      00 = 1
+			 *      01 = 2 (default)
+			 *      10 = 4
+			 *      11 = 8
+			 *   0: Shutdown Mode
+			 *      1 = Shutdown mode.
+			 *      0 = Normal operation. (default)
+			 */
+	u8 status;	/* The Status register provides all the information
+			 * about what is going on within the TC654/TC655
+			 * devices.
+			 * 7,6: Unimplemented, Read as '0'
+			 *   5: Over-Temperature Fault Condition
+			 *      1 = Over-Temperature condition has occurred
+			 *      0 = Normal operation. V IN is less than 2.6V
+			 *   4: RPM2 Counter Overflow
+			 *      1 = Fault condition
+			 *      0 = Normal operation
+			 *   3: RPM1 Counter Overflow
+			 *      1 = Fault condition
+			 *      0 = Normal operation
+			 *   2: V IN Input Status
+			 *      1 = V IN is open
+			 *      0 = Normal operation. voltage present at V IN
+			 *   1: Fan 2 Fault
+			 *      1 = Fault condition
+			 *      0 = Normal operation
+			 *   0: Fan 1 Fault
+			 *      1 = Fault condition
+			 *      0 = Normal operation
+			 */
+	u8 duty_cycle;	/* The DUTY_CYCLE register is a 4-bit read/
+			 * writable register used to control the duty
+			 * cycle of the V OUT output.
+			 */
+};
+
+/* helper to grab and cache data, at most one time per second */
+static struct tc654_data *tc654_update_client(struct device *dev)
+{
+	struct tc654_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	int ret = 0;
+
+	mutex_lock(&data->update_lock);
+	if (time_before(jiffies, data->last_updated + TC654_UPDATE_INTERVAL) &&
+	    likely(data->valid))
+		goto out;
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_RPM(0));
+	if (ret < 0)
+		goto out;
+	data->rpm_output[0] = ret;
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_RPM(1));
+	if (ret < 0)
+		goto out;
+	data->rpm_output[1] = ret;
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_FAN_FAULT(0));
+	if (ret < 0)
+		goto out;
+	data->fan_fault[0] = ret;
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_FAN_FAULT(1));
+	if (ret < 0)
+		goto out;
+	data->fan_fault[1] = ret;
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_CONFIG);
+	if (ret < 0)
+		goto out;
+	data->config = ret;
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_STATUS);
+	if (ret < 0)
+		goto out;
+	data->status = ret;
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_DUTY_CYCLE);
+	if (ret < 0)
+		goto out;
+	data->duty_cycle = ret & 0x0f;
+
+	data->last_updated = jiffies;
+	data->valid = true;
+out:
+	mutex_unlock(&data->update_lock);
+
+	if (ret < 0)		/* upon error, encode it in return value */
+		data = ERR_PTR(ret);
+
+	return data;
+}
+
+/*
+ * sysfs attributes
+ */
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *da,
+			char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct tc654_data *data = tc654_update_client(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	if (data->config & TC654_REG_CONFIG_RES)
+		val = data->rpm_output[nr] * TC654_HIGH_RPM_RESOLUTION;
+	else
+		val = data->rpm_output[nr] * TC654_LOW_RPM_RESOLUTION;
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
+			    char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct tc654_data *data = tc654_update_client(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n",
+		       TC654_FAN_FAULT_FROM_REG(data->fan_fault[nr]));
+}
+
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct tc654_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	unsigned long val;
+	int ret;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	val = clamp_val(val, 0, 12750);
+
+	mutex_lock(&data->update_lock);
+
+	data->fan_fault[nr] = TC654_FAN_FAULT_TO_REG(val);
+	ret = i2c_smbus_write_byte_data(client, TC654_REG_FAN_FAULT(nr),
+					data->fan_fault[nr]);
+
+	mutex_unlock(&data->update_lock);
+	return ret < 0 ? ret : count;
+}
+
+static ssize_t show_fan_alarm(struct device *dev, struct device_attribute *da,
+			      char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct tc654_data *data = tc654_update_client(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	if (nr == 0)
+		val = !!(data->status & TC654_REG_STATUS_F1F);
+	else
+		val = !!(data->status & TC654_REG_STATUS_F2F);
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static const u8 TC654_FAN_PULSE_SHIFT[] = { 1, 3 };
+
+static ssize_t show_fan_pulses(struct device *dev, struct device_attribute *da,
+			       char *buf)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct tc654_data *data = tc654_update_client(dev);
+	u8 val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = BIT((data->config >> TC654_FAN_PULSE_SHIFT[nr]) & 0x03);
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t set_fan_pulses(struct device *dev, struct device_attribute *da,
+			      const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(da)->index;
+	struct tc654_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	u8 config;
+	unsigned long val;
+	int ret;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	switch (val) {
+	case 1:
+		config = 0;
+		break;
+	case 2:
+		config = 1;
+		break;
+	case 4:
+		config = 2;
+		break;
+	case 8:
+		config = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->update_lock);
+
+	data->config &= ~(0x03 << TC654_FAN_PULSE_SHIFT[nr]);
+	data->config |= (config << TC654_FAN_PULSE_SHIFT[nr]);
+	ret = i2c_smbus_write_byte_data(client, TC654_REG_CONFIG, data->config);
+
+	mutex_unlock(&data->update_lock);
+	return ret < 0 ? ret : count;
+}
+
+static ssize_t show_pwm_mode(struct device *dev,
+			     struct device_attribute *da, char *buf)
+{
+	struct tc654_data *data = tc654_update_client(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", !!(data->config & TC654_REG_CONFIG_DUTYC));
+}
+
+static ssize_t set_pwm_mode(struct device *dev,
+			    struct device_attribute *da,
+			    const char *buf, size_t count)
+{
+	struct tc654_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	unsigned long val;
+	int ret;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	if (val != 0 && val != 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	if (val)
+		data->config |= TC654_REG_CONFIG_DUTYC;
+	else
+		data->config &= ~TC654_REG_CONFIG_DUTYC;
+
+	ret = i2c_smbus_write_byte_data(client, TC654_REG_CONFIG, data->config);
+
+	mutex_unlock(&data->update_lock);
+	return ret < 0 ? ret : count;
+}
+
+static const int tc654_pwm_map[16] = { 77,  88, 102, 112, 124, 136, 148, 160,
+				      172, 184, 196, 207, 219, 231, 243, 255};
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
+			char *buf)
+{
+	struct tc654_data *data = tc654_update_client(dev);
+	int pwm;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	if (data->config & TC654_REG_CONFIG_SDM)
+		pwm = 0;
+	else
+		pwm = tc654_pwm_map[data->duty_cycle];
+
+	return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *da,
+		       const char *buf, size_t count)
+{
+	struct tc654_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	unsigned long val;
+	int ret;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+	if (val > 255)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	if (val == 0)
+		data->config |= TC654_REG_CONFIG_SDM;
+	else
+		data->config &= ~TC654_REG_CONFIG_SDM;
+
+	data->duty_cycle = find_closest(val, tc654_pwm_map,
+					ARRAY_SIZE(tc654_pwm_map));
+
+	ret = i2c_smbus_write_byte_data(client, TC654_REG_CONFIG, data->config);
+	if (ret < 0)
+		goto out;
+
+	ret = i2c_smbus_write_byte_data(client, TC654_REG_DUTY_CYCLE,
+					data->duty_cycle);
+
+out:
+	mutex_unlock(&data->update_lock);
+	return ret < 0 ? ret : count;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
+			  set_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
+			  set_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
+			  set_fan_pulses, 0);
+static SENSOR_DEVICE_ATTR(fan2_pulses, S_IWUSR | S_IRUGO, show_fan_pulses,
+			  set_fan_pulses, 1);
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
+			  show_pwm_mode, set_pwm_mode, 0);
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm,
+			  set_pwm, 0);
+
+/* Driver data */
+static struct attribute *tc654_attrs[] = {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
+	&sensor_dev_attr_fan1_pulses.dev_attr.attr,
+	&sensor_dev_attr_fan2_pulses.dev_attr.attr,
+	&sensor_dev_attr_pwm1_mode.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	NULL
+};
+
+ATTRIBUTE_GROUPS(tc654);
+
+/*
+ * device probe and removal
+ */
+
+static int tc654_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct tc654_data *data;
+	struct device *hwmon_dev;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	data = devm_kzalloc(dev, sizeof(struct tc654_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->client = client;
+	mutex_init(&data->update_lock);
+
+	ret = i2c_smbus_read_byte_data(client, TC654_REG_CONFIG);
+	if (ret < 0)
+		return ret;
+
+	data->config = ret;
+
+	hwmon_dev =
+	    devm_hwmon_device_register_with_groups(dev, client->name, data,
+						   tc654_groups);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static const struct i2c_device_id tc654_id[] = {
+	{"tc654", 0},
+	{"tc655", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, tc654_id);
+
+static struct i2c_driver tc654_driver = {
+	.driver = {
+		   .name = "tc654",
+		   },
+	.probe = tc654_probe,
+	.id_table = tc654_id,
+};
+
+module_i2c_driver(tc654_driver);
+
+MODULE_AUTHOR("Allied Telesis Labs");
+MODULE_DESCRIPTION("Microchip TC654/TC655 driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/tmp108.c linux-libre-4.10-rc8-gnu/drivers/hwmon/tmp108.c
--- linux-libre-4.9-gnu/drivers/hwmon/tmp108.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/tmp108.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,469 @@
+/* Texas Instruments TMP108 SMBus temperature sensor driver
+ *
+ * Copyright (C) 2016 John Muir <john@jmuir.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#define	DRIVER_NAME "tmp108"
+
+#define	TMP108_REG_TEMP		0x00
+#define	TMP108_REG_CONF		0x01
+#define	TMP108_REG_TLOW		0x02
+#define	TMP108_REG_THIGH	0x03
+
+#define TMP108_TEMP_MIN_MC	-50000 /* Minimum millicelcius. */
+#define TMP108_TEMP_MAX_MC	127937 /* Maximum millicelcius. */
+
+/* Configuration register bits.
+ * Note: these bit definitions are byte swapped.
+ */
+#define TMP108_CONF_M0		0x0100 /* Sensor mode. */
+#define TMP108_CONF_M1		0x0200
+#define TMP108_CONF_TM		0x0400 /* Thermostat mode. */
+#define TMP108_CONF_FL		0x0800 /* Watchdog flag - TLOW */
+#define TMP108_CONF_FH		0x1000 /* Watchdog flag - THIGH */
+#define TMP108_CONF_CR0		0x2000 /* Conversion rate. */
+#define TMP108_CONF_CR1		0x4000
+#define TMP108_CONF_ID		0x8000
+#define TMP108_CONF_HYS0	0x0010 /* Hysteresis. */
+#define TMP108_CONF_HYS1	0x0020
+#define TMP108_CONF_POL		0x0080 /* Polarity of alert. */
+
+/* Defaults set by the hardware upon reset. */
+#define TMP108_CONF_DEFAULTS		(TMP108_CONF_CR0 | TMP108_CONF_TM |\
+					 TMP108_CONF_HYS0 | TMP108_CONF_M1)
+/* These bits are read-only. */
+#define TMP108_CONF_READ_ONLY		(TMP108_CONF_FL | TMP108_CONF_FH |\
+					 TMP108_CONF_ID)
+
+#define TMP108_CONF_MODE_MASK		(TMP108_CONF_M0|TMP108_CONF_M1)
+#define TMP108_MODE_SHUTDOWN		0x0000
+#define TMP108_MODE_ONE_SHOT		TMP108_CONF_M0
+#define TMP108_MODE_CONTINUOUS		TMP108_CONF_M1		/* Default */
+					/* When M1 is set, M0 is ignored. */
+
+#define TMP108_CONF_CONVRATE_MASK	(TMP108_CONF_CR0|TMP108_CONF_CR1)
+#define TMP108_CONVRATE_0P25HZ		0x0000
+#define TMP108_CONVRATE_1HZ		TMP108_CONF_CR0		/* Default */
+#define TMP108_CONVRATE_4HZ		TMP108_CONF_CR1
+#define TMP108_CONVRATE_16HZ		(TMP108_CONF_CR0|TMP108_CONF_CR1)
+
+#define TMP108_CONF_HYSTERESIS_MASK	(TMP108_CONF_HYS0|TMP108_CONF_HYS1)
+#define TMP108_HYSTERESIS_0C		0x0000
+#define TMP108_HYSTERESIS_1C		TMP108_CONF_HYS0	/* Default */
+#define TMP108_HYSTERESIS_2C		TMP108_CONF_HYS1
+#define TMP108_HYSTERESIS_4C		(TMP108_CONF_HYS0|TMP108_CONF_HYS1)
+
+#define TMP108_CONVERSION_TIME_MS	30	/* in milli-seconds */
+
+struct tmp108 {
+	struct regmap *regmap;
+	u16 orig_config;
+	unsigned long ready_time;
+};
+
+/* convert 12-bit TMP108 register value to milliCelsius */
+static inline int tmp108_temp_reg_to_mC(s16 val)
+{
+	return (val & ~0x0f) * 1000 / 256;
+}
+
+/* convert milliCelsius to left adjusted 12-bit TMP108 register value */
+static inline u16 tmp108_mC_to_temp_reg(int val)
+{
+	return (val * 256) / 1000;
+}
+
+static int tmp108_read(struct device *dev, enum hwmon_sensor_types type,
+		       u32 attr, int channel, long *temp)
+{
+	struct tmp108 *tmp108 = dev_get_drvdata(dev);
+	unsigned int regval;
+	int err, hyst;
+
+	if (type == hwmon_chip) {
+		if (attr == hwmon_chip_update_interval) {
+			err = regmap_read(tmp108->regmap, TMP108_REG_CONF,
+					  &regval);
+			if (err < 0)
+				return err;
+			switch (regval & TMP108_CONF_CONVRATE_MASK) {
+			case TMP108_CONVRATE_0P25HZ:
+			default:
+				*temp = 4000;
+				break;
+			case TMP108_CONVRATE_1HZ:
+				*temp = 1000;
+				break;
+			case TMP108_CONVRATE_4HZ:
+				*temp = 250;
+				break;
+			case TMP108_CONVRATE_16HZ:
+				*temp = 63;
+				break;
+			}
+			return 0;
+		}
+		return -EOPNOTSUPP;
+	}
+
+	switch (attr) {
+	case hwmon_temp_input:
+		/* Is it too early to return a conversion ? */
+		if (time_before(jiffies, tmp108->ready_time)) {
+			dev_dbg(dev, "%s: Conversion not ready yet..\n",
+				__func__);
+			return -EAGAIN;
+		}
+		err = regmap_read(tmp108->regmap, TMP108_REG_TEMP, &regval);
+		if (err < 0)
+			return err;
+		*temp = tmp108_temp_reg_to_mC(regval);
+		break;
+	case hwmon_temp_min:
+	case hwmon_temp_max:
+		err = regmap_read(tmp108->regmap, attr == hwmon_temp_min ?
+				  TMP108_REG_TLOW : TMP108_REG_THIGH, &regval);
+		if (err < 0)
+			return err;
+		*temp = tmp108_temp_reg_to_mC(regval);
+		break;
+	case hwmon_temp_min_alarm:
+	case hwmon_temp_max_alarm:
+		err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &regval);
+		if (err < 0)
+			return err;
+		*temp = !!(regval & (attr == hwmon_temp_min_alarm ?
+				     TMP108_CONF_FL : TMP108_CONF_FH));
+		break;
+	case hwmon_temp_min_hyst:
+	case hwmon_temp_max_hyst:
+		err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &regval);
+		if (err < 0)
+			return err;
+		switch (regval & TMP108_CONF_HYSTERESIS_MASK) {
+		case TMP108_HYSTERESIS_0C:
+		default:
+			hyst = 0;
+			break;
+		case TMP108_HYSTERESIS_1C:
+			hyst = 1000;
+			break;
+		case TMP108_HYSTERESIS_2C:
+			hyst = 2000;
+			break;
+		case TMP108_HYSTERESIS_4C:
+			hyst = 4000;
+			break;
+		}
+		err = regmap_read(tmp108->regmap, attr == hwmon_temp_min_hyst ?
+				  TMP108_REG_TLOW : TMP108_REG_THIGH, &regval);
+		if (err < 0)
+			return err;
+		*temp = tmp108_temp_reg_to_mC(regval);
+		if (attr == hwmon_temp_min_hyst)
+			*temp += hyst;
+		else
+			*temp -= hyst;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int tmp108_write(struct device *dev, enum hwmon_sensor_types type,
+			u32 attr, int channel, long temp)
+{
+	struct tmp108 *tmp108 = dev_get_drvdata(dev);
+	u32 regval, mask;
+	int err;
+
+	if (type == hwmon_chip) {
+		if (attr == hwmon_chip_update_interval) {
+			if (temp < 156)
+				mask = TMP108_CONVRATE_16HZ;
+			else if (temp < 625)
+				mask = TMP108_CONVRATE_4HZ;
+			else if (temp < 2500)
+				mask = TMP108_CONVRATE_1HZ;
+			else
+				mask = TMP108_CONVRATE_0P25HZ;
+			return regmap_update_bits(tmp108->regmap,
+						  TMP108_REG_CONF,
+						  TMP108_CONF_CONVRATE_MASK,
+						  mask);
+		}
+		return -EOPNOTSUPP;
+	}
+
+	switch (attr) {
+	case hwmon_temp_min:
+	case hwmon_temp_max:
+		temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC);
+		return regmap_write(tmp108->regmap,
+				    attr == hwmon_temp_min ?
+					TMP108_REG_TLOW : TMP108_REG_THIGH,
+				    tmp108_mC_to_temp_reg(temp));
+	case hwmon_temp_min_hyst:
+	case hwmon_temp_max_hyst:
+		temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC);
+		err = regmap_read(tmp108->regmap,
+				  attr == hwmon_temp_min_hyst ?
+					TMP108_REG_TLOW : TMP108_REG_THIGH,
+				  &regval);
+		if (err < 0)
+			return err;
+		if (attr == hwmon_temp_min_hyst)
+			temp -= tmp108_temp_reg_to_mC(regval);
+		else
+			temp = tmp108_temp_reg_to_mC(regval) - temp;
+		if (temp < 500)
+			mask = TMP108_HYSTERESIS_0C;
+		else if (temp < 1500)
+			mask = TMP108_HYSTERESIS_1C;
+		else if (temp < 3000)
+			mask = TMP108_HYSTERESIS_2C;
+		else
+			mask = TMP108_HYSTERESIS_4C;
+		return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
+					  TMP108_CONF_HYSTERESIS_MASK, mask);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type,
+				 u32 attr, int channel)
+{
+	if (type == hwmon_chip && attr == hwmon_chip_update_interval)
+		return 0644;
+
+	if (type != hwmon_temp)
+		return 0;
+
+	switch (attr) {
+	case hwmon_temp_input:
+	case hwmon_temp_min_alarm:
+	case hwmon_temp_max_alarm:
+		return 0444;
+	case hwmon_temp_min:
+	case hwmon_temp_max:
+	case hwmon_temp_min_hyst:
+	case hwmon_temp_max_hyst:
+		return 0644;
+	default:
+		return 0;
+	}
+}
+
+static u32 tmp108_chip_config[] = {
+	HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
+	0
+};
+
+static const struct hwmon_channel_info tmp108_chip = {
+	.type = hwmon_chip,
+	.config = tmp108_chip_config,
+};
+
+static u32 tmp108_temp_config[] = {
+	HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | HWMON_T_MIN_HYST
+		| HWMON_T_MAX_HYST | HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM,
+	0
+};
+
+static const struct hwmon_channel_info tmp108_temp = {
+	.type = hwmon_temp,
+	.config = tmp108_temp_config,
+};
+
+static const struct hwmon_channel_info *tmp108_info[] = {
+	&tmp108_chip,
+	&tmp108_temp,
+	NULL
+};
+
+static const struct hwmon_ops tmp108_hwmon_ops = {
+	.is_visible = tmp108_is_visible,
+	.read = tmp108_read,
+	.write = tmp108_write,
+};
+
+static const struct hwmon_chip_info tmp108_chip_info = {
+	.ops = &tmp108_hwmon_ops,
+	.info = tmp108_info,
+};
+
+static void tmp108_restore_config(void *data)
+{
+	struct tmp108 *tmp108 = data;
+
+	regmap_write(tmp108->regmap, TMP108_REG_CONF, tmp108->orig_config);
+}
+
+static bool tmp108_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return reg != TMP108_REG_TEMP;
+}
+
+static bool tmp108_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	/* Configuration register must be volatile to enable FL and FH. */
+	return reg == TMP108_REG_TEMP || reg == TMP108_REG_CONF;
+}
+
+static const struct regmap_config tmp108_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 16,
+	.max_register = TMP108_REG_THIGH,
+	.writeable_reg = tmp108_is_writeable_reg,
+	.volatile_reg = tmp108_is_volatile_reg,
+	.val_format_endian = REGMAP_ENDIAN_BIG,
+	.cache_type = REGCACHE_RBTREE,
+	.use_single_rw = true,
+};
+
+static int tmp108_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct device *hwmon_dev;
+	struct tmp108 *tmp108;
+	int err;
+	u32 config;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_err(dev,
+			"adapter doesn't support SMBus word transactions\n");
+		return -ENODEV;
+	}
+
+	tmp108 = devm_kzalloc(dev, sizeof(*tmp108), GFP_KERNEL);
+	if (!tmp108)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, tmp108);
+
+	tmp108->regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config);
+	if (IS_ERR(tmp108->regmap)) {
+		err = PTR_ERR(tmp108->regmap);
+		dev_err(dev, "regmap init failed: %d", err);
+		return err;
+	}
+
+	err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config);
+	if (err < 0) {
+		dev_err(dev, "error reading config register: %d", err);
+		return err;
+	}
+	tmp108->orig_config = config;
+
+	/* Only continuous mode is supported. */
+	config &= ~TMP108_CONF_MODE_MASK;
+	config |= TMP108_MODE_CONTINUOUS;
+
+	/* Only comparator mode is supported. */
+	config &= ~TMP108_CONF_TM;
+
+	err = regmap_write(tmp108->regmap, TMP108_REG_CONF, config);
+	if (err < 0) {
+		dev_err(dev, "error writing config register: %d", err);
+		return err;
+	}
+
+	tmp108->ready_time = jiffies;
+	if ((tmp108->orig_config & TMP108_CONF_MODE_MASK) ==
+	    TMP108_MODE_SHUTDOWN)
+		tmp108->ready_time +=
+			msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
+
+	err = devm_add_action_or_reset(dev, tmp108_restore_config, tmp108);
+	if (err) {
+		dev_err(dev, "add action or reset failed: %d", err);
+		return err;
+	}
+
+	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+							 tmp108,
+							 &tmp108_chip_info,
+							 NULL);
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static int __maybe_unused tmp108_suspend(struct device *dev)
+{
+	struct tmp108 *tmp108 = dev_get_drvdata(dev);
+
+	return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
+				  TMP108_CONF_MODE_MASK, TMP108_MODE_SHUTDOWN);
+}
+
+static int __maybe_unused tmp108_resume(struct device *dev)
+{
+	struct tmp108 *tmp108 = dev_get_drvdata(dev);
+	int err;
+
+	err = regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
+				 TMP108_CONF_MODE_MASK, TMP108_MODE_CONTINUOUS);
+	tmp108->ready_time = jiffies +
+			     msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
+	return err;
+}
+
+static SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume);
+
+static const struct i2c_device_id tmp108_i2c_ids[] = {
+	{ "tmp108", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id tmp108_of_ids[] = {
+	{ .compatible = "ti,tmp108", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, tmp108_of_ids);
+#endif
+
+static struct i2c_driver tmp108_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.pm	= &tmp108_dev_pm_ops,
+		.of_match_table = of_match_ptr(tmp108_of_ids),
+	},
+	.probe		= tmp108_probe,
+	.id_table	= tmp108_i2c_ids,
+};
+
+module_i2c_driver(tmp108_driver);
+
+MODULE_AUTHOR("John Muir <john@jmuir.com>");
+MODULE_DESCRIPTION("Texas Instruments TMP108 temperature sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwmon/via-cputemp.c linux-libre-4.10-rc8-gnu/drivers/hwmon/via-cputemp.c
--- linux-libre-4.9-gnu/drivers/hwmon/via-cputemp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwmon/via-cputemp.c	2017-02-12 16:03:20.000000000 -0500
@@ -220,7 +220,7 @@ struct pdev_entry {
 static LIST_HEAD(pdev_list);
 static DEFINE_MUTEX(pdev_list_mutex);
 
-static int via_cputemp_device_add(unsigned int cpu)
+static int via_cputemp_online(unsigned int cpu)
 {
 	int err;
 	struct platform_device *pdev;
@@ -261,7 +261,7 @@ exit:
 	return err;
 }
 
-static void via_cputemp_device_remove(unsigned int cpu)
+static int via_cputemp_down_prep(unsigned int cpu)
 {
 	struct pdev_entry *p;
 
@@ -272,33 +272,13 @@ static void via_cputemp_device_remove(un
 			list_del(&p->list);
 			mutex_unlock(&pdev_list_mutex);
 			kfree(p);
-			return;
+			return 0;
 		}
 	}
 	mutex_unlock(&pdev_list_mutex);
+	return 0;
 }
 
-static int via_cputemp_cpu_callback(struct notifier_block *nfb,
-				    unsigned long action, void *hcpu)
-{
-	unsigned int cpu = (unsigned long) hcpu;
-
-	switch (action) {
-	case CPU_ONLINE:
-	case CPU_DOWN_FAILED:
-		via_cputemp_device_add(cpu);
-		break;
-	case CPU_DOWN_PREPARE:
-		via_cputemp_device_remove(cpu);
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block via_cputemp_cpu_notifier __refdata = {
-	.notifier_call = via_cputemp_cpu_callback,
-};
-
 static const struct x86_cpu_id __initconst cputemp_ids[] = {
 	{ X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */
 	{ X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */
@@ -307,9 +287,11 @@ static const struct x86_cpu_id __initcon
 };
 MODULE_DEVICE_TABLE(x86cpu, cputemp_ids);
 
+static enum cpuhp_state via_temp_online;
+
 static int __init via_cputemp_init(void)
 {
-	int i, err;
+	int err;
 
 	if (!x86_match_cpu(cputemp_ids))
 		return -ENODEV;
@@ -318,58 +300,33 @@ static int __init via_cputemp_init(void)
 	if (err)
 		goto exit;
 
-	cpu_notifier_register_begin();
-	for_each_online_cpu(i) {
-		struct cpuinfo_x86 *c = &cpu_data(i);
-
-		if (c->x86 != 6)
-			continue;
-
-		if (c->x86_model < 0x0a)
-			continue;
-
-		if (c->x86_model > 0x0f) {
-			pr_warn("Unknown CPU model 0x%x\n", c->x86_model);
-			continue;
-		}
-
-		via_cputemp_device_add(i);
-	}
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/via:online",
+				via_cputemp_online, via_cputemp_down_prep);
+	if (err < 0)
+		goto exit_driver_unreg;
+	via_temp_online = err;
 
 #ifndef CONFIG_HOTPLUG_CPU
 	if (list_empty(&pdev_list)) {
-		cpu_notifier_register_done();
 		err = -ENODEV;
-		goto exit_driver_unreg;
+		goto exit_hp_unreg;
 	}
 #endif
-
-	__register_hotcpu_notifier(&via_cputemp_cpu_notifier);
-	cpu_notifier_register_done();
 	return 0;
 
 #ifndef CONFIG_HOTPLUG_CPU
+exit_hp_unreg:
+	cpuhp_remove_state_nocalls(via_temp_online);
+#endif
 exit_driver_unreg:
 	platform_driver_unregister(&via_cputemp_driver);
-#endif
 exit:
 	return err;
 }
 
 static void __exit via_cputemp_exit(void)
 {
-	struct pdev_entry *p, *n;
-
-	cpu_notifier_register_begin();
-	__unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
-	mutex_lock(&pdev_list_mutex);
-	list_for_each_entry_safe(p, n, &pdev_list, list) {
-		platform_device_unregister(p->pdev);
-		list_del(&p->list);
-		kfree(p);
-	}
-	mutex_unlock(&pdev_list_mutex);
-	cpu_notifier_register_done();
+	cpuhp_remove_state(via_temp_online);
 	platform_driver_unregister(&via_cputemp_driver);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight.c	2017-02-12 16:03:20.000000000 -0500
@@ -368,6 +368,52 @@ struct coresight_device *coresight_get_s
 	return csdev;
 }
 
+static int coresight_enabled_sink(struct device *dev, void *data)
+{
+	bool *reset = data;
+	struct coresight_device *csdev = to_coresight_device(dev);
+
+	if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
+	     csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) &&
+	     csdev->activated) {
+		/*
+		 * Now that we have a handle on the sink for this session,
+		 * disable the sysFS "enable_sink" flag so that possible
+		 * concurrent perf session that wish to use another sink don't
+		 * trip on it.  Doing so has no ramification for the current
+		 * session.
+		 */
+		if (*reset)
+			csdev->activated = false;
+
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * coresight_get_enabled_sink - returns the first enabled sink found on the bus
+ * @deactivate:	Whether the 'enable_sink' flag should be reset
+ *
+ * When operated from perf the deactivate parameter should be set to 'true'.
+ * That way the "enabled_sink" flag of the sink that was selected can be reset,
+ * allowing for other concurrent perf sessions to choose a different sink.
+ *
+ * When operated from sysFS users have full control and as such the deactivate
+ * parameter should be set to 'false', hence mandating users to explicitly
+ * clear the flag.
+ */
+struct coresight_device *coresight_get_enabled_sink(bool deactivate)
+{
+	struct device *dev = NULL;
+
+	dev = bus_find_device(&coresight_bustype, NULL, &deactivate,
+			      coresight_enabled_sink);
+
+	return dev ? to_coresight_device(dev) : NULL;
+}
+
 /**
  * _coresight_build_path - recursively build a path from a @csdev to a sink.
  * @csdev:	The device to start from.
@@ -380,6 +426,7 @@ struct coresight_device *coresight_get_s
  * last one.
  */
 static int _coresight_build_path(struct coresight_device *csdev,
+				 struct coresight_device *sink,
 				 struct list_head *path)
 {
 	int i;
@@ -387,15 +434,15 @@ static int _coresight_build_path(struct
 	struct coresight_node *node;
 
 	/* An activated sink has been found.  Enqueue the element */
-	if ((csdev->type == CORESIGHT_DEV_TYPE_SINK ||
-	     csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && csdev->activated)
+	if (csdev == sink)
 		goto out;
 
 	/* Not a sink - recursively explore each port found on this element */
 	for (i = 0; i < csdev->nr_outport; i++) {
 		struct coresight_device *child_dev = csdev->conns[i].child_dev;
 
-		if (child_dev && _coresight_build_path(child_dev, path) == 0) {
+		if (child_dev &&
+		    _coresight_build_path(child_dev, sink, path) == 0) {
 			found = true;
 			break;
 		}
@@ -422,18 +469,22 @@ out:
 	return 0;
 }
 
-struct list_head *coresight_build_path(struct coresight_device *csdev)
+struct list_head *coresight_build_path(struct coresight_device *source,
+				       struct coresight_device *sink)
 {
 	struct list_head *path;
 	int rc;
 
+	if (!sink)
+		return ERR_PTR(-EINVAL);
+
 	path = kzalloc(sizeof(struct list_head), GFP_KERNEL);
 	if (!path)
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(path);
 
-	rc = _coresight_build_path(csdev, path);
+	rc = _coresight_build_path(source, sink, path);
 	if (rc) {
 		kfree(path);
 		return ERR_PTR(rc);
@@ -497,6 +548,7 @@ static int coresight_validate_source(str
 int coresight_enable(struct coresight_device *csdev)
 {
 	int cpu, ret = 0;
+	struct coresight_device *sink;
 	struct list_head *path;
 
 	mutex_lock(&coresight_mutex);
@@ -508,7 +560,17 @@ int coresight_enable(struct coresight_de
 	if (csdev->enable)
 		goto out;
 
-	path = coresight_build_path(csdev);
+	/*
+	 * Search for a valid sink for this session but don't reset the
+	 * "enable_sink" flag in sysFS.  Users get to do that explicitly.
+	 */
+	sink = coresight_get_enabled_sink(false);
+	if (!sink) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	path = coresight_build_path(csdev, sink);
 	if (IS_ERR(path)) {
 		pr_err("building path(s) failed\n");
 		ret = PTR_ERR(path);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm3x.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm3x.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm3x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm3x.c	2017-02-12 16:03:20.000000000 -0500
@@ -804,10 +804,10 @@ static int etm_probe(struct amba_device
 
 	if (!etm_count++) {
 		cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
-					  "AP_ARM_CORESIGHT_STARTING",
+					  "arm/coresight:starting",
 					  etm_starting_cpu, etm_dying_cpu);
 		ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
-						"AP_ARM_CORESIGHT_ONLINE",
+						"arm/coresight:online",
 						etm_online_cpu, NULL);
 		if (ret < 0)
 			goto err_arch_supported;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm3x-sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -146,7 +146,7 @@ static ssize_t mode_store(struct device
 			goto err_unlock;
 		}
 		config->ctrl |= ETMCR_STALL_MODE;
-	 } else
+	} else
 		config->ctrl &= ~ETMCR_STALL_MODE;
 
 	if (config->mode & ETM_MODE_TIMESTAMP) {
@@ -164,6 +164,16 @@ static ssize_t mode_store(struct device
 	else
 		config->ctrl &= ~ETMCR_CTXID_SIZE;
 
+	if (config->mode & ETM_MODE_BBROAD)
+		config->ctrl |= ETMCR_BRANCH_BROADCAST;
+	else
+		config->ctrl &= ~ETMCR_BRANCH_BROADCAST;
+
+	if (config->mode & ETM_MODE_RET_STACK)
+		config->ctrl |= ETMCR_RETURN_STACK;
+	else
+		config->ctrl &= ~ETMCR_RETURN_STACK;
+
 	if (config->mode & (ETM_MODE_EXCL_KERN | ETM_MODE_EXCL_USER))
 		etm_config_trace_mode(config);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm4x.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm4x.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm4x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm4x.c	2017-02-12 16:03:20.000000000 -0500
@@ -986,11 +986,11 @@ static int etm4_probe(struct amba_device
 		dev_err(dev, "ETM arch init failed\n");
 
 	if (!etm4_count++) {
-		cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT4_STARTING,
-					  "AP_ARM_CORESIGHT4_STARTING",
+		cpuhp_setup_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING,
+					  "arm/coresight4:starting",
 					  etm4_starting_cpu, etm4_dying_cpu);
 		ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
-						"AP_ARM_CORESIGHT4_ONLINE",
+						"arm/coresight4:online",
 						etm4_online_cpu, NULL);
 		if (ret < 0)
 			goto err_arch_supported;
@@ -1037,7 +1037,7 @@ static int etm4_probe(struct amba_device
 
 err_arch_supported:
 	if (--etm4_count == 0) {
-		cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT4_STARTING);
+		cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
 		if (hp_online)
 			cpuhp_remove_state_nocalls(hp_online);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm.h linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm.h
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm.h	2017-02-12 16:03:20.000000000 -0500
@@ -89,11 +89,13 @@
 /* ETMCR - 0x00 */
 #define ETMCR_PWD_DWN		BIT(0)
 #define ETMCR_STALL_MODE	BIT(7)
+#define ETMCR_BRANCH_BROADCAST	BIT(8)
 #define ETMCR_ETM_PRG		BIT(10)
 #define ETMCR_ETM_EN		BIT(11)
 #define ETMCR_CYC_ACC		BIT(12)
 #define ETMCR_CTXID_SIZE	(BIT(14)|BIT(15))
 #define ETMCR_TIMESTAMP_EN	BIT(28)
+#define ETMCR_RETURN_STACK	BIT(29)
 /* ETMCCR - 0x04 */
 #define ETMCCR_FIFOFULL		BIT(23)
 /* ETMPDCR - 0x310 */
@@ -110,8 +112,11 @@
 #define ETM_MODE_STALL		BIT(2)
 #define ETM_MODE_TIMESTAMP	BIT(3)
 #define ETM_MODE_CTXID		BIT(4)
+#define ETM_MODE_BBROAD		BIT(5)
+#define ETM_MODE_RET_STACK	BIT(6)
 #define ETM_MODE_ALL		(ETM_MODE_EXCLUDE | ETM_MODE_CYCACC | \
 				 ETM_MODE_STALL | ETM_MODE_TIMESTAMP | \
+				 ETM_MODE_BBROAD | ETM_MODE_RET_STACK | \
 				 ETM_MODE_CTXID | ETM_MODE_EXCL_KERN | \
 				 ETM_MODE_EXCL_USER)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm-perf.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm-perf.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-etm-perf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-etm-perf.c	2017-02-12 16:03:20.000000000 -0500
@@ -202,6 +202,21 @@ static void *etm_setup_aux(int event_cpu
 	if (!event_data)
 		return NULL;
 
+	/*
+	 * In theory nothing prevent tracers in a trace session from being
+	 * associated with different sinks, nor having a sink per tracer.  But
+	 * until we have HW with this kind of topology we need to assume tracers
+	 * in a trace session are using the same sink.  Therefore go through
+	 * the coresight bus and pick the first enabled sink.
+	 *
+	 * When operated from sysFS users are responsible to enable the sink
+	 * while from perf, the perf tools will do it based on the choice made
+	 * on the cmd line.  As such the "enable_sink" flag in sysFS is reset.
+	 */
+	sink = coresight_get_enabled_sink(true);
+	if (!sink)
+		goto err;
+
 	INIT_WORK(&event_data->work, free_event_data);
 
 	mask = &event_data->mask;
@@ -219,25 +234,11 @@ static void *etm_setup_aux(int event_cpu
 		 * list of devices from source to sink that can be
 		 * referenced later when the path is actually needed.
 		 */
-		event_data->path[cpu] = coresight_build_path(csdev);
+		event_data->path[cpu] = coresight_build_path(csdev, sink);
 		if (IS_ERR(event_data->path[cpu]))
 			goto err;
 	}
 
-	/*
-	 * In theory nothing prevent tracers in a trace session from being
-	 * associated with different sinks, nor having a sink per tracer.  But
-	 * until we have HW with this kind of topology and a way to convey
-	 * sink assignement from the perf cmd line we need to assume tracers
-	 * in a trace session are using the same sink.  Therefore pick the sink
-	 * found at the end of the first available path.
-	 */
-	cpu = cpumask_first(mask);
-	/* Grab the sink at the end of the path */
-	sink = coresight_get_sink(event_data->path[cpu]);
-	if (!sink)
-		goto err;
-
 	if (!sink_ops(sink)->alloc_buffer)
 		goto err;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-priv.h linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-priv.h
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -111,7 +111,9 @@ static inline void CS_UNLOCK(void __iome
 void coresight_disable_path(struct list_head *path);
 int coresight_enable_path(struct list_head *path, u32 mode);
 struct coresight_device *coresight_get_sink(struct list_head *path);
-struct list_head *coresight_build_path(struct coresight_device *csdev);
+struct coresight_device *coresight_get_enabled_sink(bool reset);
+struct list_head *coresight_build_path(struct coresight_device *csdev,
+				       struct coresight_device *sink);
 void coresight_release_path(struct list_head *path);
 
 #ifdef CONFIG_CORESIGHT_SOURCE_ETM3X
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-stm.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-stm.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-stm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-stm.c	2017-02-12 16:03:20.000000000 -0500
@@ -406,7 +406,7 @@ static long stm_generic_set_options(stru
 	return 0;
 }
 
-static ssize_t stm_generic_packet(struct stm_data *stm_data,
+static ssize_t notrace stm_generic_packet(struct stm_data *stm_data,
 				  unsigned int master,
 				  unsigned int channel,
 				  unsigned int packet,
@@ -419,10 +419,10 @@ static ssize_t stm_generic_packet(struct
 						   struct stm_drvdata, stm);
 
 	if (!(drvdata && local_read(&drvdata->mode)))
-		return 0;
+		return -EACCES;
 
 	if (channel >= drvdata->numsp)
-		return 0;
+		return -EINVAL;
 
 	ch_addr = (unsigned long)stm_channel_addr(drvdata, channel);
 
@@ -920,6 +920,11 @@ static struct amba_id stm_ids[] = {
 		.mask   = 0x0003ffff,
 		.data	= "STM32",
 	},
+	{
+		.id	= 0x0003b963,
+		.mask	= 0x0003ffff,
+		.data	= "STM500",
+	},
 	{ 0, 0},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-tmc-etf.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,7 @@ static void tmc_etb_disable_hw(struct tm
 	 * When operating in sysFS mode the content of the buffer needs to be
 	 * read before the TMC is disabled.
 	 */
-	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+	if (drvdata->mode == CS_MODE_SYSFS)
 		tmc_etb_dump_hw(drvdata);
 	tmc_disable_hw(drvdata);
 
@@ -103,19 +103,14 @@ static void tmc_etf_disable_hw(struct tm
 	CS_LOCK(drvdata->base);
 }
 
-static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
 {
 	int ret = 0;
 	bool used = false;
 	char *buf = NULL;
-	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	 /* This shouldn't be happening */
-	if (WARN_ON(mode != CS_MODE_SYSFS))
-		return -EINVAL;
-
 	/*
 	 * If we don't have a buffer release the lock and allocate memory.
 	 * Otherwise keep the lock and move along.
@@ -138,13 +133,12 @@ static int tmc_enable_etf_sink_sysfs(str
 		goto out;
 	}
 
-	val = local_xchg(&drvdata->mode, mode);
 	/*
 	 * In sysFS mode we can have multiple writers per sink.  Since this
 	 * sink is already enabled no memory is needed and the HW need not be
 	 * touched.
 	 */
-	if (val == CS_MODE_SYSFS)
+	if (drvdata->mode == CS_MODE_SYSFS)
 		goto out;
 
 	/*
@@ -163,6 +157,7 @@ static int tmc_enable_etf_sink_sysfs(str
 		drvdata->buf = buf;
 	}
 
+	drvdata->mode = CS_MODE_SYSFS;
 	tmc_etb_enable_hw(drvdata);
 out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -177,34 +172,29 @@ out:
 	return ret;
 }
 
-static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etf_sink_perf(struct coresight_device *csdev)
 {
 	int ret = 0;
-	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	 /* This shouldn't be happening */
-	if (WARN_ON(mode != CS_MODE_PERF))
-		return -EINVAL;
-
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	val = local_xchg(&drvdata->mode, mode);
 	/*
 	 * In Perf mode there can be only one writer per sink.  There
 	 * is also no need to continue if the ETB/ETR is already operated
 	 * from sysFS.
 	 */
-	if (val != CS_MODE_DISABLED) {
+	if (drvdata->mode != CS_MODE_DISABLED) {
 		ret = -EINVAL;
 		goto out;
 	}
 
+	drvdata->mode = CS_MODE_PERF;
 	tmc_etb_enable_hw(drvdata);
 out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -216,9 +206,9 @@ static int tmc_enable_etf_sink(struct co
 {
 	switch (mode) {
 	case CS_MODE_SYSFS:
-		return tmc_enable_etf_sink_sysfs(csdev, mode);
+		return tmc_enable_etf_sink_sysfs(csdev);
 	case CS_MODE_PERF:
-		return tmc_enable_etf_sink_perf(csdev, mode);
+		return tmc_enable_etf_sink_perf(csdev);
 	}
 
 	/* We shouldn't be here */
@@ -227,7 +217,6 @@ static int tmc_enable_etf_sink(struct co
 
 static void tmc_disable_etf_sink(struct coresight_device *csdev)
 {
-	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
@@ -237,10 +226,11 @@ static void tmc_disable_etf_sink(struct
 		return;
 	}
 
-	val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
 	/* Disable the TMC only if it needs to */
-	if (val != CS_MODE_DISABLED)
+	if (drvdata->mode != CS_MODE_DISABLED) {
 		tmc_etb_disable_hw(drvdata);
+		drvdata->mode = CS_MODE_DISABLED;
+	}
 
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
@@ -260,7 +250,7 @@ static int tmc_enable_etf_link(struct co
 	}
 
 	tmc_etf_enable_hw(drvdata);
-	local_set(&drvdata->mode, CS_MODE_SYSFS);
+	drvdata->mode = CS_MODE_SYSFS;
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_info(drvdata->dev, "TMC-ETF enabled\n");
@@ -280,7 +270,7 @@ static void tmc_disable_etf_link(struct
 	}
 
 	tmc_etf_disable_hw(drvdata);
-	local_set(&drvdata->mode, CS_MODE_DISABLED);
+	drvdata->mode = CS_MODE_DISABLED;
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
 	dev_info(drvdata->dev, "TMC disabled\n");
@@ -383,7 +373,7 @@ static void tmc_update_etf_buffer(struct
 		return;
 
 	/* This shouldn't happen */
-	if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
+	if (WARN_ON_ONCE(drvdata->mode != CS_MODE_PERF))
 		return;
 
 	CS_UNLOCK(drvdata->base);
@@ -504,7 +494,6 @@ const struct coresight_ops tmc_etf_cs_op
 
 int tmc_read_prepare_etb(struct tmc_drvdata *drvdata)
 {
-	long val;
 	enum tmc_mode mode;
 	int ret = 0;
 	unsigned long flags;
@@ -528,9 +517,8 @@ int tmc_read_prepare_etb(struct tmc_drvd
 		goto out;
 	}
 
-	val = local_read(&drvdata->mode);
 	/* Don't interfere if operated from Perf */
-	if (val == CS_MODE_PERF) {
+	if (drvdata->mode == CS_MODE_PERF) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -542,7 +530,7 @@ int tmc_read_prepare_etb(struct tmc_drvd
 	}
 
 	/* Disable the TMC if need be */
-	if (val == CS_MODE_SYSFS)
+	if (drvdata->mode == CS_MODE_SYSFS)
 		tmc_etb_disable_hw(drvdata);
 
 	drvdata->reading = true;
@@ -573,7 +561,7 @@ int tmc_read_unprepare_etb(struct tmc_dr
 	}
 
 	/* Re-enable the TMC if need be */
-	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+	if (drvdata->mode == CS_MODE_SYSFS) {
 		/*
 		 * The trace run will continue with the same allocated trace
 		 * buffer. As such zero-out the buffer so that we don't end
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-tmc-etr.c	2017-02-12 16:03:20.000000000 -0500
@@ -86,26 +86,22 @@ static void tmc_etr_disable_hw(struct tm
 	 * When operating in sysFS mode the content of the buffer needs to be
 	 * read before the TMC is disabled.
 	 */
-	if (local_read(&drvdata->mode) == CS_MODE_SYSFS)
+	if (drvdata->mode == CS_MODE_SYSFS)
 		tmc_etr_dump_hw(drvdata);
 	tmc_disable_hw(drvdata);
 
 	CS_LOCK(drvdata->base);
 }
 
-static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
 {
 	int ret = 0;
 	bool used = false;
-	long val;
 	unsigned long flags;
 	void __iomem *vaddr = NULL;
 	dma_addr_t paddr;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	 /* This shouldn't be happening */
-	if (WARN_ON(mode != CS_MODE_SYSFS))
-		return -EINVAL;
 
 	/*
 	 * If we don't have a buffer release the lock and allocate memory.
@@ -134,13 +130,12 @@ static int tmc_enable_etr_sink_sysfs(str
 		goto out;
 	}
 
-	val = local_xchg(&drvdata->mode, mode);
 	/*
 	 * In sysFS mode we can have multiple writers per sink.  Since this
 	 * sink is already enabled no memory is needed and the HW need not be
 	 * touched.
 	 */
-	if (val == CS_MODE_SYSFS)
+	if (drvdata->mode == CS_MODE_SYSFS)
 		goto out;
 
 	/*
@@ -155,8 +150,7 @@ static int tmc_enable_etr_sink_sysfs(str
 		drvdata->buf = drvdata->vaddr;
 	}
 
-	memset(drvdata->vaddr, 0, drvdata->size);
-
+	drvdata->mode = CS_MODE_SYSFS;
 	tmc_etr_enable_hw(drvdata);
 out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -171,34 +165,29 @@ out:
 	return ret;
 }
 
-static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, u32 mode)
+static int tmc_enable_etr_sink_perf(struct coresight_device *csdev)
 {
 	int ret = 0;
-	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	 /* This shouldn't be happening */
-	if (WARN_ON(mode != CS_MODE_PERF))
-		return -EINVAL;
-
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	val = local_xchg(&drvdata->mode, mode);
 	/*
 	 * In Perf mode there can be only one writer per sink.  There
 	 * is also no need to continue if the ETR is already operated
 	 * from sysFS.
 	 */
-	if (val != CS_MODE_DISABLED) {
+	if (drvdata->mode != CS_MODE_DISABLED) {
 		ret = -EINVAL;
 		goto out;
 	}
 
+	drvdata->mode = CS_MODE_PERF;
 	tmc_etr_enable_hw(drvdata);
 out:
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -210,9 +199,9 @@ static int tmc_enable_etr_sink(struct co
 {
 	switch (mode) {
 	case CS_MODE_SYSFS:
-		return tmc_enable_etr_sink_sysfs(csdev, mode);
+		return tmc_enable_etr_sink_sysfs(csdev);
 	case CS_MODE_PERF:
-		return tmc_enable_etr_sink_perf(csdev, mode);
+		return tmc_enable_etr_sink_perf(csdev);
 	}
 
 	/* We shouldn't be here */
@@ -221,7 +210,6 @@ static int tmc_enable_etr_sink(struct co
 
 static void tmc_disable_etr_sink(struct coresight_device *csdev)
 {
-	long val;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
@@ -231,10 +219,11 @@ static void tmc_disable_etr_sink(struct
 		return;
 	}
 
-	val = local_xchg(&drvdata->mode, CS_MODE_DISABLED);
 	/* Disable the TMC only if it needs to */
-	if (val != CS_MODE_DISABLED)
+	if (drvdata->mode != CS_MODE_DISABLED) {
 		tmc_etr_disable_hw(drvdata);
+		drvdata->mode = CS_MODE_DISABLED;
+	}
 
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
@@ -253,7 +242,6 @@ const struct coresight_ops tmc_etr_cs_op
 int tmc_read_prepare_etr(struct tmc_drvdata *drvdata)
 {
 	int ret = 0;
-	long val;
 	unsigned long flags;
 
 	/* config types are set a boot time and never change */
@@ -266,9 +254,8 @@ int tmc_read_prepare_etr(struct tmc_drvd
 		goto out;
 	}
 
-	val = local_read(&drvdata->mode);
 	/* Don't interfere if operated from Perf */
-	if (val == CS_MODE_PERF) {
+	if (drvdata->mode == CS_MODE_PERF) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -280,7 +267,7 @@ int tmc_read_prepare_etr(struct tmc_drvd
 	}
 
 	/* Disable the TMC if need be */
-	if (val == CS_MODE_SYSFS)
+	if (drvdata->mode == CS_MODE_SYSFS)
 		tmc_etr_disable_hw(drvdata);
 
 	drvdata->reading = true;
@@ -303,7 +290,7 @@ int tmc_read_unprepare_etr(struct tmc_dr
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
 	/* RE-enable the TMC if need be */
-	if (local_read(&drvdata->mode) == CS_MODE_SYSFS) {
+	if (drvdata->mode == CS_MODE_SYSFS) {
 		/*
 		 * The trace run will continue with the same allocated trace
 		 * buffer. The trace buffer is cleared in tmc_etr_enable_hw(),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-tmc.h linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-tmc.h
--- linux-libre-4.9-gnu/drivers/hwtracing/coresight/coresight-tmc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/coresight/coresight-tmc.h	2017-02-12 16:03:20.000000000 -0500
@@ -117,7 +117,7 @@ struct tmc_drvdata {
 	void __iomem		*vaddr;
 	u32			size;
 	u32			len;
-	local_t			mode;
+	u32			mode;
 	enum tmc_config_type	config_type;
 	enum tmc_mem_intf_width	memwidth;
 	u32			trigger_cntr;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/intel_th/core.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/core.c
--- linux-libre-4.9-gnu/drivers/hwtracing/intel_th/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,6 +29,9 @@
 #include "intel_th.h"
 #include "debug.h"
 
+static bool host_mode __read_mostly;
+module_param(host_mode, bool, 0444);
+
 static DEFINE_IDA(intel_th_ida);
 
 static int intel_th_match(struct device *dev, struct device_driver *driver)
@@ -380,7 +383,7 @@ static void intel_th_device_free(struct
 /*
  * Intel(R) Trace Hub subdevices
  */
-static struct intel_th_subdevice {
+static const struct intel_th_subdevice {
 	const char		*name;
 	struct resource		res[3];
 	unsigned		nres;
@@ -527,14 +530,19 @@ static int intel_th_populate(struct inte
 {
 	struct resource res[3];
 	unsigned int req = 0;
-	int i, err;
+	int src, dst, err;
 
 	/* create devices for each intel_th_subdevice */
-	for (i = 0; i < ARRAY_SIZE(intel_th_subdevices); i++) {
-		struct intel_th_subdevice *subdev = &intel_th_subdevices[i];
+	for (src = 0, dst = 0; src < ARRAY_SIZE(intel_th_subdevices); src++) {
+		const struct intel_th_subdevice *subdev =
+			&intel_th_subdevices[src];
 		struct intel_th_device *thdev;
 		int r;
 
+		/* only allow SOURCE and SWITCH devices in host mode */
+		if (host_mode && subdev->type == INTEL_TH_OUTPUT)
+			continue;
+
 		thdev = intel_th_device_alloc(th, subdev->type, subdev->name,
 					      subdev->id);
 		if (!thdev) {
@@ -577,10 +585,12 @@ static int intel_th_populate(struct inte
 		}
 
 		if (subdev->type == INTEL_TH_OUTPUT) {
-			thdev->dev.devt = MKDEV(th->major, i);
+			thdev->dev.devt = MKDEV(th->major, dst);
 			thdev->output.type = subdev->otype;
 			thdev->output.port = -1;
 			thdev->output.scratchpad = subdev->scrpd;
+		} else if (subdev->type == INTEL_TH_SWITCH) {
+			thdev->host_mode = host_mode;
 		}
 
 		err = device_add(&thdev->dev);
@@ -597,14 +607,14 @@ static int intel_th_populate(struct inte
 				req++;
 		}
 
-		th->thdev[i] = thdev;
+		th->thdev[dst++] = thdev;
 	}
 
 	return 0;
 
 kill_subdevs:
-	for (i-- ; i >= 0; i--)
-		intel_th_device_remove(th->thdev[i]);
+	for (; dst >= 0; dst--)
+		intel_th_device_remove(th->thdev[dst]);
 
 	return err;
 }
@@ -717,7 +727,7 @@ void intel_th_free(struct intel_th *th)
 
 	intel_th_request_hub_module_flush(th);
 	for (i = 0; i < TH_SUBDEVICE_MAX; i++)
-		if (th->thdev[i] != th->hub)
+		if (th->thdev[i] && th->thdev[i] != th->hub)
 			intel_th_device_remove(th->thdev[i]);
 
 	intel_th_device_remove(th->hub);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/intel_th/gth.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/gth.c
--- linux-libre-4.9-gnu/drivers/hwtracing/intel_th/gth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/gth.c	2017-02-12 16:03:20.000000000 -0500
@@ -564,6 +564,9 @@ static int intel_th_gth_assign(struct in
 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
 	int i, id;
 
+	if (thdev->host_mode)
+		return -EBUSY;
+
 	if (othdev->type != INTEL_TH_OUTPUT)
 		return -EINVAL;
 
@@ -600,6 +603,9 @@ static void intel_th_gth_unassign(struct
 	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
 	int port = othdev->output.port;
 
+	if (thdev->host_mode)
+		return;
+
 	spin_lock(&gth->gth_lock);
 	othdev->output.port = -1;
 	othdev->output.active = false;
@@ -654,9 +660,24 @@ static int intel_th_gth_probe(struct int
 	gth->base = base;
 	spin_lock_init(&gth->gth_lock);
 
+	/*
+	 * Host mode can be signalled via SW means or via SCRPD_DEBUGGER_IN_USE
+	 * bit. Either way, don't reset HW in this case, and don't export any
+	 * capture configuration attributes. Also, refuse to assign output
+	 * drivers to ports, see intel_th_gth_assign().
+	 */
+	if (thdev->host_mode)
+		goto done;
+
 	ret = intel_th_gth_reset(gth);
-	if (ret)
-		return ret;
+	if (ret) {
+		if (ret != -EBUSY)
+			return ret;
+
+		thdev->host_mode = true;
+
+		goto done;
+	}
 
 	for (i = 0; i < TH_CONFIGURABLE_MASTERS + 1; i++)
 		gth->master[i] = -1;
@@ -677,6 +698,7 @@ static int intel_th_gth_probe(struct int
 		return -ENOMEM;
 	}
 
+done:
 	dev_set_drvdata(dev, gth);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/intel_th/intel_th.h linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/intel_th.h
--- linux-libre-4.9-gnu/drivers/hwtracing/intel_th/intel_th.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/intel_th.h	2017-02-12 16:03:20.000000000 -0500
@@ -54,6 +54,7 @@ struct intel_th_output {
  * @num_resources:	number of resources in @resource array
  * @type:		INTEL_TH_{SOURCE,OUTPUT,SWITCH}
  * @id:			device instance or -1
+ * @host_mode:		Intel TH is controlled by an external debug host
  * @output:		output descriptor for INTEL_TH_OUTPUT devices
  * @name:		device name to match the driver
  */
@@ -64,6 +65,9 @@ struct intel_th_device {
 	unsigned int	type;
 	int		id;
 
+	/* INTEL_TH_SWITCH specific */
+	bool			host_mode;
+
 	/* INTEL_TH_OUTPUT specific */
 	struct intel_th_output	output;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/intel_th/sth.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/sth.c
--- linux-libre-4.9-gnu/drivers/hwtracing/intel_th/sth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/intel_th/sth.c	2017-02-12 16:03:20.000000000 -0500
@@ -67,10 +67,13 @@ static void sth_iowrite(void __iomem *de
 	}
 }
 
-static ssize_t sth_stm_packet(struct stm_data *stm_data, unsigned int master,
-			      unsigned int channel, unsigned int packet,
-			      unsigned int flags, unsigned int size,
-			      const unsigned char *payload)
+static ssize_t notrace sth_stm_packet(struct stm_data *stm_data,
+				      unsigned int master,
+				      unsigned int channel,
+				      unsigned int packet,
+				      unsigned int flags,
+				      unsigned int size,
+				      const unsigned char *payload)
 {
 	struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
 	struct intel_th_channel __iomem *out =
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/stm/core.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/core.c
--- linux-libre-4.9-gnu/drivers/hwtracing/stm/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -361,7 +361,7 @@ static int stm_char_open(struct inode *i
 	struct stm_file *stmf;
 	struct device *dev;
 	unsigned int major = imajor(inode);
-	int err = -ENODEV;
+	int err = -ENOMEM;
 
 	dev = class_find_device(&stm_class, NULL, &major, major_match);
 	if (!dev)
@@ -369,8 +369,9 @@ static int stm_char_open(struct inode *i
 
 	stmf = kzalloc(sizeof(*stmf), GFP_KERNEL);
 	if (!stmf)
-		return -ENOMEM;
+		goto err_put_device;
 
+	err = -ENODEV;
 	stm_output_init(&stmf->output);
 	stmf->stm = to_stm_device(dev);
 
@@ -382,9 +383,10 @@ static int stm_char_open(struct inode *i
 	return nonseekable_open(inode, file);
 
 err_free:
+	kfree(stmf);
+err_put_device:
 	/* matches class_find_device() above */
 	put_device(dev);
-	kfree(stmf);
 
 	return err;
 }
@@ -425,7 +427,7 @@ static int stm_file_assign(struct stm_fi
 	return ret;
 }
 
-static ssize_t stm_write(struct stm_data *data, unsigned int master,
+static ssize_t notrace stm_write(struct stm_data *data, unsigned int master,
 			  unsigned int channel, const char *buf, size_t count)
 {
 	unsigned int flags = STP_PACKET_TIMESTAMPED;
@@ -1121,8 +1123,9 @@ void stm_source_unregister_device(struct
 }
 EXPORT_SYMBOL_GPL(stm_source_unregister_device);
 
-int stm_source_write(struct stm_source_data *data, unsigned int chan,
-		     const char *buf, size_t count)
+int notrace stm_source_write(struct stm_source_data *data,
+			     unsigned int chan,
+			     const char *buf, size_t count)
 {
 	struct stm_source_device *src = data->src;
 	struct stm_device *stm;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/stm/dummy_stm.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/dummy_stm.c
--- linux-libre-4.9-gnu/drivers/hwtracing/stm/dummy_stm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/dummy_stm.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,7 @@
 #include <linux/slab.h>
 #include <linux/stm.h>
 
-static ssize_t
+static ssize_t notrace
 dummy_stm_packet(struct stm_data *stm_data, unsigned int master,
 		 unsigned int channel, unsigned int packet, unsigned int flags,
 		 unsigned int size, const unsigned char *payload)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/stm/ftrace.c linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/ftrace.c
--- linux-libre-4.9-gnu/drivers/hwtracing/stm/ftrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/ftrace.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,87 @@
+/*
+ * Simple kernel driver to link kernel Ftrace and an STM device
+ * Copyright (c) 2016, Linaro 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.
+ *
+ * STM Ftrace will be registered as a trace_export.
+ */
+
+#include <linux/module.h>
+#include <linux/stm.h>
+#include <linux/trace.h>
+
+#define STM_FTRACE_NR_CHANNELS 1
+#define STM_FTRACE_CHAN 0
+
+static int stm_ftrace_link(struct stm_source_data *data);
+static void stm_ftrace_unlink(struct stm_source_data *data);
+
+static struct stm_ftrace {
+	struct stm_source_data	data;
+	struct trace_export	ftrace;
+} stm_ftrace = {
+	.data	= {
+		.name		= "ftrace",
+		.nr_chans	= STM_FTRACE_NR_CHANNELS,
+		.link		= stm_ftrace_link,
+		.unlink		= stm_ftrace_unlink,
+	},
+};
+
+/**
+ * stm_ftrace_write() - write data to STM via 'stm_ftrace' source
+ * @buf:	buffer containing the data packet
+ * @len:	length of the data packet
+ */
+static void notrace
+stm_ftrace_write(const void *buf, unsigned int len)
+{
+	stm_source_write(&stm_ftrace.data, STM_FTRACE_CHAN, buf, len);
+}
+
+static int stm_ftrace_link(struct stm_source_data *data)
+{
+	struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
+
+	sf->ftrace.write = stm_ftrace_write;
+
+	return register_ftrace_export(&sf->ftrace);
+}
+
+static void stm_ftrace_unlink(struct stm_source_data *data)
+{
+	struct stm_ftrace *sf = container_of(data, struct stm_ftrace, data);
+
+	unregister_ftrace_export(&sf->ftrace);
+}
+
+static int __init stm_ftrace_init(void)
+{
+	int ret;
+
+	ret = stm_source_register_device(NULL, &stm_ftrace.data);
+	if (ret)
+		pr_err("Failed to register stm_source - ftrace.\n");
+
+	return ret;
+}
+
+static void __exit stm_ftrace_exit(void)
+{
+	stm_source_unregister_device(&stm_ftrace.data);
+}
+
+module_init(stm_ftrace_init);
+module_exit(stm_ftrace_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("stm_ftrace driver");
+MODULE_AUTHOR("Chunyan Zhang <zhang.chunyan@linaro.org>");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/stm/Kconfig linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/Kconfig
--- linux-libre-4.9-gnu/drivers/hwtracing/stm/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -39,4 +39,15 @@ config STM_SOURCE_HEARTBEAT
 	  If you want to send heartbeat messages over STM devices,
 	  say Y.
 
+config STM_SOURCE_FTRACE
+	tristate "Copy the output from kernel Ftrace to STM engine"
+	depends on FUNCTION_TRACER
+	help
+	  This option can be used to copy the output from kernel Ftrace
+	  to STM engine. Enabling this option will introduce a slight
+	  timing effect.
+
+	  If you want to send kernel Ftrace messages over STM devices,
+	  say Y.
+
 endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/hwtracing/stm/Makefile linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/Makefile
--- linux-libre-4.9-gnu/drivers/hwtracing/stm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/hwtracing/stm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,8 @@ obj-$(CONFIG_STM_DUMMY)	+= dummy_stm.o
 
 obj-$(CONFIG_STM_SOURCE_CONSOLE)	+= stm_console.o
 obj-$(CONFIG_STM_SOURCE_HEARTBEAT)	+= stm_heartbeat.o
+obj-$(CONFIG_STM_SOURCE_FTRACE)		+= stm_ftrace.o
 
 stm_console-y		:= console.o
 stm_heartbeat-y		:= heartbeat.o
+stm_ftrace-y		:= ftrace.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-axxia.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-axxia.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-axxia.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-axxia.c	2017-02-12 16:03:20.000000000 -0500
@@ -489,7 +489,7 @@ static const struct i2c_algorithm axxia_
 	.functionality = axxia_i2c_func,
 };
 
-static struct i2c_adapter_quirks axxia_i2c_quirks = {
+static const struct i2c_adapter_quirks axxia_i2c_quirks = {
 	.max_read_len = 255,
 	.max_write_len = 255,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-bcm2835.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-bcm2835.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-bcm2835.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-bcm2835.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,20 +50,19 @@
 #define BCM2835_I2C_S_CLKT	BIT(9)
 #define BCM2835_I2C_S_LEN	BIT(10) /* Fake bit for SW error reporting */
 
-#define BCM2835_I2C_BITMSK_S	0x03FF
-
 #define BCM2835_I2C_CDIV_MIN	0x0002
 #define BCM2835_I2C_CDIV_MAX	0xFFFE
 
-#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000))
-
 struct bcm2835_i2c_dev {
 	struct device *dev;
 	void __iomem *regs;
 	struct clk *clk;
 	int irq;
+	u32 bus_clk_rate;
 	struct i2c_adapter adapter;
 	struct completion completion;
+	struct i2c_msg *curr_msg;
+	int num_msgs;
 	u32 msg_err;
 	u8 *msg_buf;
 	size_t msg_buf_remaining;
@@ -80,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(stru
 	return readl(i2c_dev->regs + reg);
 }
 
+static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 divider;
+
+	divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
+			       i2c_dev->bus_clk_rate);
+	/*
+	 * Per the datasheet, the register is always interpreted as an even
+	 * number, by rounding down. In other words, the LSB is ignored. So,
+	 * if the LSB is set, increment the divider to avoid any issue.
+	 */
+	if (divider & 1)
+		divider++;
+	if ((divider < BCM2835_I2C_CDIV_MIN) ||
+	    (divider > BCM2835_I2C_CDIV_MAX)) {
+		dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
+		return -EINVAL;
+	}
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
+
+	return 0;
+}
+
 static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
 {
 	u32 val;
@@ -110,106 +133,159 @@ static void bcm2835_drain_rxfifo(struct
 	}
 }
 
+/*
+ * Repeated Start Condition (Sr)
+ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it
+ * talks about reading from a slave with 10 bit address. This is achieved by
+ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then
+ * issue a read.
+ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the
+ * firmware actually does it using polling and says that it's a workaround for
+ * a problem in the state machine.
+ * It turns out that it is possible to use the TXW interrupt to know when the
+ * transfer is active, provided the FIFO has not been prefilled.
+ */
+
+static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev)
+{
+	u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN;
+	struct i2c_msg *msg = i2c_dev->curr_msg;
+	bool last_msg = (i2c_dev->num_msgs == 1);
+
+	if (!i2c_dev->num_msgs)
+		return;
+
+	i2c_dev->num_msgs--;
+	i2c_dev->msg_buf = msg->buf;
+	i2c_dev->msg_buf_remaining = msg->len;
+
+	if (msg->flags & I2C_M_RD)
+		c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
+	else
+		c |= BCM2835_I2C_C_INTT;
+
+	if (last_msg)
+		c |= BCM2835_I2C_C_INTD;
+
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
+}
+
+/*
+ * Note about I2C_C_CLEAR on error:
+ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
+ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through
+ * the state machine to send a NACK and a STOP. Since we're setting CLEAR
+ * without I2CEN, that NACK will be hanging around queued up for next time
+ * we start the engine.
+ */
+
 static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
 {
 	struct bcm2835_i2c_dev *i2c_dev = data;
 	u32 val, err;
 
 	val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
-	val &= BCM2835_I2C_BITMSK_S;
-	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
 
 	err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
 	if (err) {
 		i2c_dev->msg_err = err;
-		complete(&i2c_dev->completion);
-		return IRQ_HANDLED;
-	}
-
-	if (val & BCM2835_I2C_S_RXD) {
-		bcm2835_drain_rxfifo(i2c_dev);
-		if (!(val & BCM2835_I2C_S_DONE))
-			return IRQ_HANDLED;
+		goto complete;
 	}
 
 	if (val & BCM2835_I2C_S_DONE) {
-		if (i2c_dev->msg_buf_remaining)
+		if (i2c_dev->curr_msg->flags & I2C_M_RD) {
+			bcm2835_drain_rxfifo(i2c_dev);
+			val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+		}
+
+		if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining)
 			i2c_dev->msg_err = BCM2835_I2C_S_LEN;
 		else
 			i2c_dev->msg_err = 0;
-		complete(&i2c_dev->completion);
-		return IRQ_HANDLED;
+		goto complete;
 	}
 
-	if (val & BCM2835_I2C_S_TXD) {
+	if (val & BCM2835_I2C_S_TXW) {
+		if (!i2c_dev->msg_buf_remaining) {
+			i2c_dev->msg_err = val | BCM2835_I2C_S_LEN;
+			goto complete;
+		}
+
 		bcm2835_fill_txfifo(i2c_dev);
+
+		if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) {
+			i2c_dev->curr_msg++;
+			bcm2835_i2c_start_transfer(i2c_dev);
+		}
+
+		return IRQ_HANDLED;
+	}
+
+	if (val & BCM2835_I2C_S_RXR) {
+		if (!i2c_dev->msg_buf_remaining) {
+			i2c_dev->msg_err = val | BCM2835_I2C_S_LEN;
+			goto complete;
+		}
+
+		bcm2835_drain_rxfifo(i2c_dev);
 		return IRQ_HANDLED;
 	}
 
 	return IRQ_NONE;
+
+complete:
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT |
+			   BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE);
+	complete(&i2c_dev->completion);
+
+	return IRQ_HANDLED;
 }
 
-static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
-				struct i2c_msg *msg)
+static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			    int num)
 {
-	u32 c;
+	struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
 	unsigned long time_left;
+	int i, ret;
 
-	i2c_dev->msg_buf = msg->buf;
-	i2c_dev->msg_buf_remaining = msg->len;
-	reinit_completion(&i2c_dev->completion);
+	for (i = 0; i < (num - 1); i++)
+		if (msgs[i].flags & I2C_M_RD) {
+			dev_warn_once(i2c_dev->dev,
+				      "only one read message supported, has to be last\n");
+			return -EOPNOTSUPP;
+		}
 
-	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+	ret = bcm2835_i2c_set_divider(i2c_dev);
+	if (ret)
+		return ret;
 
-	if (msg->flags & I2C_M_RD) {
-		c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
-	} else {
-		c = BCM2835_I2C_C_INTT;
-		bcm2835_fill_txfifo(i2c_dev);
-	}
-	c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN;
+	i2c_dev->curr_msg = msgs;
+	i2c_dev->num_msgs = num;
+	reinit_completion(&i2c_dev->completion);
 
-	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
-	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
-	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
+	bcm2835_i2c_start_transfer(i2c_dev);
 
 	time_left = wait_for_completion_timeout(&i2c_dev->completion,
-						BCM2835_I2C_TIMEOUT);
-	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+						adap->timeout);
 	if (!time_left) {
+		bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
+				   BCM2835_I2C_C_CLEAR);
 		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
 		return -ETIMEDOUT;
 	}
 
-	if (likely(!i2c_dev->msg_err))
-		return 0;
-
-	if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) &&
-	    (msg->flags & I2C_M_IGNORE_NAK))
-		return 0;
+	if (!i2c_dev->msg_err)
+		return num;
 
-	dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+	dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
 
 	if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
 		return -EREMOTEIO;
-	else
-		return -EIO;
-}
-
-static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
-			    int num)
-{
-	struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
-	int i;
-	int ret = 0;
-
-	for (i = 0; i < num; i++) {
-		ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
-		if (ret)
-			break;
-	}
 
-	return ret ?: i;
+	return -EIO;
 }
 
 static u32 bcm2835_i2c_func(struct i2c_adapter *adap)
@@ -235,7 +311,6 @@ static int bcm2835_i2c_probe(struct plat
 {
 	struct bcm2835_i2c_dev *i2c_dev;
 	struct resource *mem, *irq;
-	u32 bus_clk_rate, divider;
 	int ret;
 	struct i2c_adapter *adap;
 
@@ -259,27 +334,12 @@ static int bcm2835_i2c_probe(struct plat
 	}
 
 	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
-				   &bus_clk_rate);
+				   &i2c_dev->bus_clk_rate);
 	if (ret < 0) {
 		dev_warn(&pdev->dev,
 			 "Could not read clock-frequency property\n");
-		bus_clk_rate = 100000;
-	}
-
-	divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate);
-	/*
-	 * Per the datasheet, the register is always interpreted as an even
-	 * number, by rounding down. In other words, the LSB is ignored. So,
-	 * if the LSB is set, increment the divider to avoid any issue.
-	 */
-	if (divider & 1)
-		divider++;
-	if ((divider < BCM2835_I2C_CDIV_MIN) ||
-	    (divider > BCM2835_I2C_CDIV_MAX)) {
-		dev_err(&pdev->dev, "Invalid clock-frequency\n");
-		return -ENODEV;
+		i2c_dev->bus_clk_rate = 100000;
 	}
-	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
 
 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!irq) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-bcm-iproc.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-bcm-iproc.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-bcm-iproc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-bcm-iproc.c	2017-02-12 16:03:20.000000000 -0500
@@ -395,7 +395,7 @@ static const struct i2c_algorithm bcm_ip
 	.functionality = bcm_iproc_i2c_functionality,
 };
 
-static struct i2c_adapter_quirks bcm_iproc_i2c_quirks = {
+static const struct i2c_adapter_quirks bcm_iproc_i2c_quirks = {
 	/* need to reserve one byte in the FIFO for the slave address */
 	.max_read_len = M_TX_RX_FIFO_SIZE - 1,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-cadence.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-cadence.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-cadence.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-cadence.c	2017-02-12 16:03:20.000000000 -0500
@@ -962,10 +962,6 @@ static int cdns_i2c_probe(struct platfor
 		goto err_clk_dis;
 	}
 
-	ret = i2c_add_adapter(&id->adap);
-	if (ret < 0)
-		goto err_clk_dis;
-
 	/*
 	 * Cadence I2C controller has a bug wherein it generates
 	 * invalid read transaction after HW timeout in master receiver mode.
@@ -975,6 +971,10 @@ static int cdns_i2c_probe(struct platfor
 	 */
 	cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
 
+	ret = i2c_add_adapter(&id->adap);
+	if (ret < 0)
+		goto err_clk_dis;
+
 	dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n",
 		 id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-core.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-core.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -536,6 +536,8 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 	intr_mask = DW_IC_INTR_DEFAULT_MASK;
 
 	for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
+		u32 flags = msgs[dev->msg_write_idx].flags;
+
 		/*
 		 * if target address has changed, we need to
 		 * reprogram the target address in the i2c
@@ -581,8 +583,15 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 			 * detected from the registers so we set it always
 			 * when writing/reading the last byte.
 			 */
+
+			/*
+			 * i2c-core.c always sets the buffer length of
+			 * I2C_FUNC_SMBUS_BLOCK_DATA to 1. The length will
+			 * be adjusted when receiving the first byte.
+			 * Thus we can't stop the transaction here.
+			 */
 			if (dev->msg_write_idx == dev->msgs_num - 1 &&
-			    buf_len == 1)
+			    buf_len == 1 && !(flags & I2C_M_RECV_LEN))
 				cmd |= BIT(9);
 
 			if (need_restart) {
@@ -607,7 +616,12 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 		dev->tx_buf = buf;
 		dev->tx_buf_len = buf_len;
 
-		if (buf_len > 0) {
+		/*
+		 * Because we don't know the buffer length in the
+		 * I2C_FUNC_SMBUS_BLOCK_DATA case, we can't stop
+		 * the transaction here.
+		 */
+		if (buf_len > 0 || flags & I2C_M_RECV_LEN) {
 			/* more bytes to be written */
 			dev->status |= STATUS_WRITE_IN_PROGRESS;
 			break;
@@ -628,6 +642,24 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
 	dw_writel(dev, intr_mask,  DW_IC_INTR_MASK);
 }
 
+static u8
+i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
+{
+	struct i2c_msg *msgs = dev->msgs;
+	u32 flags = msgs[dev->msg_read_idx].flags;
+
+	/*
+	 * Adjust the buffer length and mask the flag
+	 * after receiving the first byte.
+	 */
+	len += (flags & I2C_CLIENT_PEC) ? 2 : 1;
+	dev->tx_buf_len = len - min_t(u8, len, dev->rx_outstanding);
+	msgs[dev->msg_read_idx].len = len;
+	msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN;
+
+	return len;
+}
+
 static void
 i2c_dw_read(struct dw_i2c_dev *dev)
 {
@@ -652,7 +684,15 @@ i2c_dw_read(struct dw_i2c_dev *dev)
 		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);
+			u32 flags = msgs[dev->msg_read_idx].flags;
+
+			*buf = dw_readl(dev, DW_IC_DATA_CMD);
+			/* Ensure length byte is a valid value */
+			if (flags & I2C_M_RECV_LEN &&
+				*buf <= I2C_SMBUS_BLOCK_MAX && *buf > 0) {
+				len = i2c_dw_recv_len(dev, *buf);
+			}
+			buf++;
 			dev->rx_outstanding--;
 		}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-core.h linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-core.h
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-core.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,14 @@
  *
  */
 
+#include <linux/i2c.h>
+
+#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C |			\
+					I2C_FUNC_SMBUS_BYTE |		\
+					I2C_FUNC_SMBUS_BYTE_DATA |	\
+					I2C_FUNC_SMBUS_WORD_DATA |	\
+					I2C_FUNC_SMBUS_BLOCK_DATA |	\
+					I2C_FUNC_SMBUS_I2C_BLOCK)
 
 #define DW_IC_CON_MASTER		0x1
 #define DW_IC_CON_SPEED_STD		0x2
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-pcidrv.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,12 +71,6 @@ struct dw_pci_controller {
 				DW_IC_CON_SLAVE_DISABLE |	\
 				DW_IC_CON_RESTART_EN)
 
-#define DW_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C |			\
-					I2C_FUNC_SMBUS_BYTE |		\
-					I2C_FUNC_SMBUS_BYTE_DATA |	\
-					I2C_FUNC_SMBUS_WORD_DATA |	\
-					I2C_FUNC_SMBUS_I2C_BLOCK)
-
 /* Merrifield HCNT/LCNT/SDA hold time */
 static struct dw_scl_sda_cfg mrfld_config = {
 	.ss_hcnt = 0x2f8,
@@ -147,6 +141,7 @@ static struct dw_pci_controller dw_pci_c
 		.bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 32,
 		.rx_fifo_depth = 32,
+		.functionality = I2C_FUNC_10BIT_ADDR,
 		.clk_khz      = 25000,
 		.setup = mfld_setup,
 	},
@@ -155,6 +150,7 @@ static struct dw_pci_controller dw_pci_c
 		.bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 		.tx_fifo_depth = 64,
 		.rx_fifo_depth = 64,
+		.functionality = I2C_FUNC_10BIT_ADDR,
 		.scl_sda_cfg = &mrfld_config,
 		.setup = mrfld_setup,
 	},
@@ -249,7 +245,7 @@ static int i2c_dw_pci_probe(struct pci_d
 	}
 
 	dev->functionality = controller->functionality |
-				DW_DEFAULT_FUNCTIONALITY;
+				DW_IC_DEFAULT_FUNCTIONALITY;
 
 	dev->master_cfg = controller->bus_cfg;
 	if (controller->scl_sda_cfg) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-platdrv.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-platdrv.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-designware-platdrv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-designware-platdrv.c	2017-02-12 16:03:20.000000000 -0500
@@ -150,6 +150,29 @@ static int i2c_dw_plat_prepare_clk(struc
 	return 0;
 }
 
+static void dw_i2c_set_fifo_size(struct dw_i2c_dev *dev, int id)
+{
+	u32 param, tx_fifo_depth, rx_fifo_depth;
+
+	/*
+	 * Try to detect the FIFO depth if not set by interface driver,
+	 * the depth could be from 2 to 256 from HW spec.
+	 */
+	param = i2c_dw_read_comp_param(dev);
+	tx_fifo_depth = ((param >> 16) & 0xff) + 1;
+	rx_fifo_depth = ((param >> 8)  & 0xff) + 1;
+	if (!dev->tx_fifo_depth) {
+		dev->tx_fifo_depth = tx_fifo_depth;
+		dev->rx_fifo_depth = rx_fifo_depth;
+		dev->adapter.nr = id;
+	} else if (tx_fifo_depth >= 2) {
+		dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
+				tx_fifo_depth);
+		dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
+				rx_fifo_depth);
+	}
+}
+
 static int dw_i2c_plat_probe(struct platform_device *pdev)
 {
 	struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -176,9 +199,6 @@ static int dw_i2c_plat_probe(struct plat
 	dev->irq = irq;
 	platform_set_drvdata(pdev, dev);
 
-	/* fast mode by default because of legacy reasons */
-	dev->clk_freq = 400000;
-
 	if (pdata) {
 		dev->clk_freq = pdata->i2c_scl_freq;
 	} else {
@@ -193,8 +213,16 @@ static int dw_i2c_plat_probe(struct plat
 	}
 
 	acpi_speed = i2c_acpi_find_bus_speed(&pdev->dev);
-	if (acpi_speed)
-		dev->clk_freq = acpi_speed;
+	/*
+	 * Find bus speed from the "clock-frequency" device property, ACPI
+	 * or by using fast mode if neither is set.
+	 */
+	if (acpi_speed && dev->clk_freq)
+		dev->clk_freq = min(dev->clk_freq, acpi_speed);
+	else if (acpi_speed || dev->clk_freq)
+		dev->clk_freq = max(dev->clk_freq, acpi_speed);
+	else
+		dev->clk_freq = 400000;
 
 	if (has_acpi_companion(&pdev->dev))
 		dw_i2c_acpi_configure(pdev);
@@ -214,13 +242,7 @@ static int dw_i2c_plat_probe(struct plat
 	if (r)
 		return r;
 
-	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->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
 
 	dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
 			  DW_IC_CON_RESTART_EN;
@@ -246,13 +268,7 @@ static int dw_i2c_plat_probe(struct plat
 				1000000);
 	}
 
-	if (!dev->tx_fifo_depth) {
-		u32 param1 = i2c_dw_read_comp_param(dev);
-
-		dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
-		dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
-		dev->adapter.nr = pdev->id;
-	}
+	dw_i2c_set_fifo_size(dev, pdev->id);
 
 	adap = &dev->adapter;
 	adap->owner = THIS_MODULE;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-dln2.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-dln2.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-dln2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-dln2.c	2017-02-12 16:03:20.000000000 -0500
@@ -182,7 +182,7 @@ static const struct i2c_algorithm dln2_i
 	.functionality = dln2_i2c_func,
 };
 
-static struct i2c_adapter_quirks dln2_i2c_quirks = {
+static const struct i2c_adapter_quirks dln2_i2c_quirks = {
 	.max_read_len = DLN2_I2C_MAX_XFER_SIZE,
 	.max_write_len = DLN2_I2C_MAX_XFER_SIZE,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-i801.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-i801.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-i801.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-i801.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,7 +118,6 @@
 #define SMBSLVSTS(p)	(16 + (p)->smba)	/* ICH3 and later */
 #define SMBSLVCMD(p)	(17 + (p)->smba)	/* ICH3 and later */
 #define SMBNTFDADD(p)	(20 + (p)->smba)	/* ICH3 and later */
-#define SMBNTFDDAT(p)	(22 + (p)->smba)	/* ICH3 and later */
 
 /* PCI Address Constants */
 #define SMBBAR		4
@@ -137,27 +136,27 @@
 #define SBREG_SMBCTRL		0xc6000c
 
 /* Host status bits for SMBPCISTS */
-#define SMBPCISTS_INTS		0x08
+#define SMBPCISTS_INTS		BIT(3)
 
 /* Control bits for SMBPCICTL */
-#define SMBPCICTL_INTDIS	0x0400
+#define SMBPCICTL_INTDIS	BIT(10)
 
 /* Host configuration bits for SMBHSTCFG */
-#define SMBHSTCFG_HST_EN	1
-#define SMBHSTCFG_SMB_SMI_EN	2
-#define SMBHSTCFG_I2C_EN	4
-#define SMBHSTCFG_SPD_WD	0x10
+#define SMBHSTCFG_HST_EN	BIT(0)
+#define SMBHSTCFG_SMB_SMI_EN	BIT(1)
+#define SMBHSTCFG_I2C_EN	BIT(2)
+#define SMBHSTCFG_SPD_WD	BIT(4)
 
 /* TCO configuration bits for TCOCTL */
-#define TCOCTL_EN		0x0100
+#define TCOCTL_EN		BIT(8)
 
 /* Auxiliary status register bits, ICH4+ only */
-#define SMBAUXSTS_CRCE		1
-#define SMBAUXSTS_STCO		2
+#define SMBAUXSTS_CRCE		BIT(0)
+#define SMBAUXSTS_STCO		BIT(1)
 
 /* Auxiliary control register bits, ICH4+ only */
-#define SMBAUXCTL_CRC		1
-#define SMBAUXCTL_E32B		2
+#define SMBAUXCTL_CRC		BIT(0)
+#define SMBAUXCTL_E32B		BIT(1)
 
 /* Other settings */
 #define MAX_RETRIES		400
@@ -172,27 +171,27 @@
 #define I801_I2C_BLOCK_DATA	0x18	/* ICH5 and later */
 
 /* I801 Host Control register bits */
-#define SMBHSTCNT_INTREN	0x01
-#define SMBHSTCNT_KILL		0x02
-#define SMBHSTCNT_LAST_BYTE	0x20
-#define SMBHSTCNT_START		0x40
-#define SMBHSTCNT_PEC_EN	0x80	/* ICH3 and later */
+#define SMBHSTCNT_INTREN	BIT(0)
+#define SMBHSTCNT_KILL		BIT(1)
+#define SMBHSTCNT_LAST_BYTE	BIT(5)
+#define SMBHSTCNT_START		BIT(6)
+#define SMBHSTCNT_PEC_EN	BIT(7)	/* ICH3 and later */
 
 /* I801 Hosts Status register bits */
-#define SMBHSTSTS_BYTE_DONE	0x80
-#define SMBHSTSTS_INUSE_STS	0x40
-#define SMBHSTSTS_SMBALERT_STS	0x20
-#define SMBHSTSTS_FAILED	0x10
-#define SMBHSTSTS_BUS_ERR	0x08
-#define SMBHSTSTS_DEV_ERR	0x04
-#define SMBHSTSTS_INTR		0x02
-#define SMBHSTSTS_HOST_BUSY	0x01
+#define SMBHSTSTS_BYTE_DONE	BIT(7)
+#define SMBHSTSTS_INUSE_STS	BIT(6)
+#define SMBHSTSTS_SMBALERT_STS	BIT(5)
+#define SMBHSTSTS_FAILED	BIT(4)
+#define SMBHSTSTS_BUS_ERR	BIT(3)
+#define SMBHSTSTS_DEV_ERR	BIT(2)
+#define SMBHSTSTS_INTR		BIT(1)
+#define SMBHSTSTS_HOST_BUSY	BIT(0)
 
-/* Host Notify Status registers bits */
-#define SMBSLVSTS_HST_NTFY_STS	1
+/* Host Notify Status register bits */
+#define SMBSLVSTS_HST_NTFY_STS	BIT(0)
 
-/* Host Notify Command registers bits */
-#define SMBSLVCMD_HST_NTFY_INTREN	0x01
+/* Host Notify Command register bits */
+#define SMBSLVCMD_HST_NTFY_INTREN	BIT(0)
 
 #define STATUS_ERROR_FLAGS	(SMBHSTSTS_FAILED | SMBHSTSTS_BUS_ERR | \
 				 SMBHSTSTS_DEV_ERR)
@@ -243,6 +242,7 @@ struct i801_priv {
 	struct i2c_adapter adapter;
 	unsigned long smba;
 	unsigned char original_hstcfg;
+	unsigned char original_slvcmd;
 	struct pci_dev *pci_dev;
 	unsigned int features;
 
@@ -269,20 +269,17 @@ struct i801_priv {
 	 */
 	bool acpi_reserved;
 	struct mutex acpi_lock;
-	struct smbus_host_notify *host_notify;
 };
 
-#define SMBHSTNTFY_SIZE		8
-
-#define FEATURE_SMBUS_PEC	(1 << 0)
-#define FEATURE_BLOCK_BUFFER	(1 << 1)
-#define FEATURE_BLOCK_PROC	(1 << 2)
-#define FEATURE_I2C_BLOCK_READ	(1 << 3)
-#define FEATURE_IRQ		(1 << 4)
-#define FEATURE_HOST_NOTIFY	(1 << 5)
+#define FEATURE_SMBUS_PEC	BIT(0)
+#define FEATURE_BLOCK_BUFFER	BIT(1)
+#define FEATURE_BLOCK_PROC	BIT(2)
+#define FEATURE_I2C_BLOCK_READ	BIT(3)
+#define FEATURE_IRQ		BIT(4)
+#define FEATURE_HOST_NOTIFY	BIT(5)
 /* Not really a feature, but it's convenient to handle it as such */
-#define FEATURE_IDF		(1 << 15)
-#define FEATURE_TCO		(1 << 16)
+#define FEATURE_IDF		BIT(15)
+#define FEATURE_TCO		BIT(16)
 
 static const char *i801_feature_names[] = {
 	"SMBus PEC",
@@ -582,12 +579,15 @@ static void i801_isr_byte_done(struct i8
 static irqreturn_t i801_host_notify_isr(struct i801_priv *priv)
 {
 	unsigned short addr;
-	unsigned int data;
 
 	addr = inb_p(SMBNTFDADD(priv)) >> 1;
-	data = inw_p(SMBNTFDDAT(priv));
 
-	i2c_handle_smbus_host_notify(priv->host_notify, addr, data);
+	/*
+	 * With the tested platforms, reading SMBNTFDDAT (22 + (p)->smba)
+	 * always returns 0. Our current implementation doesn't provide
+	 * data, so we just ignore it.
+	 */
+	i2c_handle_smbus_host_notify(&priv->adapter, addr);
 
 	/* clear Host Notify bit and return */
 	outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv));
@@ -950,23 +950,29 @@ static u32 i801_func(struct i2c_adapter
 		I2C_FUNC_SMBUS_HOST_NOTIFY : 0);
 }
 
-static int i801_enable_host_notify(struct i2c_adapter *adapter)
+static void i801_enable_host_notify(struct i2c_adapter *adapter)
 {
 	struct i801_priv *priv = i2c_get_adapdata(adapter);
 
 	if (!(priv->features & FEATURE_HOST_NOTIFY))
-		return -ENOTSUPP;
+		return;
 
-	if (!priv->host_notify)
-		priv->host_notify = i2c_setup_smbus_host_notify(adapter);
-	if (!priv->host_notify)
-		return -ENOMEM;
+	priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
+
+	if (!(SMBSLVCMD_HST_NTFY_INTREN & priv->original_slvcmd))
+		outb_p(SMBSLVCMD_HST_NTFY_INTREN | priv->original_slvcmd,
+		       SMBSLVCMD(priv));
 
-	outb_p(SMBSLVCMD_HST_NTFY_INTREN, SMBSLVCMD(priv));
 	/* clear Host Notify bit to allow a new notification */
 	outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv));
+}
 
-	return 0;
+static void i801_disable_host_notify(struct i801_priv *priv)
+{
+	if (!(priv->features & FEATURE_HOST_NOTIFY))
+		return;
+
+	outb_p(priv->original_slvcmd, SMBSLVCMD(priv));
 }
 
 static const struct i2c_algorithm smbus_algorithm = {
@@ -1633,14 +1639,7 @@ static int i801_probe(struct pci_dev *de
 		return err;
 	}
 
-	/*
-	 * Enable Host Notify for chips that supports it.
-	 * It is done after i2c_add_adapter() so that we are sure the work queue
-	 * is not used if i2c_add_adapter() fails.
-	 */
-	err = i801_enable_host_notify(&priv->adapter);
-	if (err && err != -ENOTSUPP)
-		dev_warn(&dev->dev, "Unable to enable SMBus Host Notify\n");
+	i801_enable_host_notify(&priv->adapter);
 
 	i801_probe_optional_slaves(priv);
 	/* We ignore errors - multiplexing is optional */
@@ -1663,6 +1662,7 @@ static void i801_remove(struct pci_dev *
 	pm_runtime_forbid(&dev->dev);
 	pm_runtime_get_noresume(&dev->dev);
 
+	i801_disable_host_notify(priv);
 	i801_del_mux(priv);
 	i2c_del_adapter(&priv->adapter);
 	i801_acpi_remove(priv);
@@ -1690,11 +1690,8 @@ static int i801_resume(struct device *de
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct i801_priv *priv = pci_get_drvdata(pci_dev);
-	int err;
 
-	err = i801_enable_host_notify(&priv->adapter);
-	if (err && err != -ENOTSUPP)
-		dev_warn(dev, "Unable to enable SMBus Host Notify\n");
+	i801_enable_host_notify(&priv->adapter);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-imx-lpi2c.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-imx-lpi2c.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-imx-lpi2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-imx-lpi2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,672 @@
+/*
+ * This is i.MX low power i2c controller driver.
+ *
+ * Copyright 2016 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "imx-lpi2c"
+
+#define LPI2C_PARAM	0x04	/* i2c RX/TX FIFO size */
+#define LPI2C_MCR	0x10	/* i2c contrl register */
+#define LPI2C_MSR	0x14	/* i2c status register */
+#define LPI2C_MIER	0x18	/* i2c interrupt enable */
+#define LPI2C_MCFGR0	0x20	/* i2c master configuration */
+#define LPI2C_MCFGR1	0x24	/* i2c master configuration */
+#define LPI2C_MCFGR2	0x28	/* i2c master configuration */
+#define LPI2C_MCFGR3	0x2C	/* i2c master configuration */
+#define LPI2C_MCCR0	0x48	/* i2c master clk configuration */
+#define LPI2C_MCCR1	0x50	/* i2c master clk configuration */
+#define LPI2C_MFCR	0x58	/* i2c master FIFO control */
+#define LPI2C_MFSR	0x5C	/* i2c master FIFO status */
+#define LPI2C_MTDR	0x60	/* i2c master TX data register */
+#define LPI2C_MRDR	0x70	/* i2c master RX data register */
+
+/* i2c command */
+#define TRAN_DATA	0X00
+#define RECV_DATA	0X01
+#define GEN_STOP	0X02
+#define RECV_DISCARD	0X03
+#define GEN_START	0X04
+#define START_NACK	0X05
+#define START_HIGH	0X06
+#define START_HIGH_NACK	0X07
+
+#define MCR_MEN		BIT(0)
+#define MCR_RST		BIT(1)
+#define MCR_DOZEN	BIT(2)
+#define MCR_DBGEN	BIT(3)
+#define MCR_RTF		BIT(8)
+#define MCR_RRF		BIT(9)
+#define MSR_TDF		BIT(0)
+#define MSR_RDF		BIT(1)
+#define MSR_SDF		BIT(9)
+#define MSR_NDF		BIT(10)
+#define MSR_ALF		BIT(11)
+#define MSR_MBF		BIT(24)
+#define MSR_BBF		BIT(25)
+#define MIER_TDIE	BIT(0)
+#define MIER_RDIE	BIT(1)
+#define MIER_SDIE	BIT(9)
+#define MIER_NDIE	BIT(10)
+#define MCFGR1_AUTOSTOP	BIT(8)
+#define MCFGR1_IGNACK	BIT(9)
+#define MRDR_RXEMPTY	BIT(14)
+
+#define I2C_CLK_RATIO	2
+#define CHUNK_DATA	256
+
+#define LPI2C_DEFAULT_RATE	100000
+#define STARDARD_MAX_BITRATE	400000
+#define FAST_MAX_BITRATE	1000000
+#define FAST_PLUS_MAX_BITRATE	3400000
+#define HIGHSPEED_MAX_BITRATE	5000000
+
+enum lpi2c_imx_mode {
+	STANDARD,	/* 100+Kbps */
+	FAST,		/* 400+Kbps */
+	FAST_PLUS,	/* 1.0+Mbps */
+	HS,		/* 3.4+Mbps */
+	ULTRA_FAST,	/* 5.0+Mbps */
+};
+
+enum lpi2c_imx_pincfg {
+	TWO_PIN_OD,
+	TWO_PIN_OO,
+	TWO_PIN_PP,
+	FOUR_PIN_PP,
+};
+
+struct lpi2c_imx_struct {
+	struct i2c_adapter	adapter;
+	struct clk		*clk;
+	void __iomem		*base;
+	__u8			*rx_buf;
+	__u8			*tx_buf;
+	struct completion	complete;
+	unsigned int		msglen;
+	unsigned int		delivered;
+	unsigned int		block_data;
+	unsigned int		bitrate;
+	unsigned int		txfifosize;
+	unsigned int		rxfifosize;
+	enum lpi2c_imx_mode	mode;
+};
+
+static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
+			      unsigned int enable)
+{
+	writel(enable, lpi2c_imx->base + LPI2C_MIER);
+}
+
+static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned long orig_jiffies = jiffies;
+	unsigned int temp;
+
+	while (1) {
+		temp = readl(lpi2c_imx->base + LPI2C_MSR);
+
+		/* check for arbitration lost, clear if set */
+		if (temp & MSR_ALF) {
+			writel(temp, lpi2c_imx->base + LPI2C_MSR);
+			return -EAGAIN;
+		}
+
+		if (temp & (MSR_BBF | MSR_MBF))
+			break;
+
+		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
+			dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
+			return -ETIMEDOUT;
+		}
+		schedule();
+	}
+
+	return 0;
+}
+
+static void lpi2c_imx_set_mode(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned int bitrate = lpi2c_imx->bitrate;
+	enum lpi2c_imx_mode mode;
+
+	if (bitrate < STARDARD_MAX_BITRATE)
+		mode = STANDARD;
+	else if (bitrate < FAST_MAX_BITRATE)
+		mode = FAST;
+	else if (bitrate < FAST_PLUS_MAX_BITRATE)
+		mode = FAST_PLUS;
+	else if (bitrate < HIGHSPEED_MAX_BITRATE)
+		mode = HS;
+	else
+		mode = ULTRA_FAST;
+
+	lpi2c_imx->mode = mode;
+}
+
+static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
+			   struct i2c_msg *msgs)
+{
+	unsigned int temp;
+	u8 read;
+
+	temp = readl(lpi2c_imx->base + LPI2C_MCR);
+	temp |= MCR_RRF | MCR_RTF;
+	writel(temp, lpi2c_imx->base + LPI2C_MCR);
+	writel(0x7f00, lpi2c_imx->base + LPI2C_MSR);
+
+	read = msgs->flags & I2C_M_RD;
+	temp = (msgs->addr << 1 | read) | (GEN_START << 8);
+	writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+
+	return lpi2c_imx_bus_busy(lpi2c_imx);
+}
+
+static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned long orig_jiffies = jiffies;
+	unsigned int temp;
+
+	writel(GEN_STOP << 8, lpi2c_imx->base + LPI2C_MTDR);
+
+	do {
+		temp = readl(lpi2c_imx->base + LPI2C_MSR);
+		if (temp & MSR_SDF)
+			break;
+
+		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
+			dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
+			break;
+		}
+		schedule();
+
+	} while (1);
+}
+
+/* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
+static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	u8 prescale, filt, sethold, clkhi, clklo, datavd;
+	unsigned int clk_rate, clk_cycle;
+	enum lpi2c_imx_pincfg pincfg;
+	unsigned int temp;
+
+	lpi2c_imx_set_mode(lpi2c_imx);
+
+	clk_rate = clk_get_rate(lpi2c_imx->clk);
+	if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
+		filt = 0;
+	else
+		filt = 2;
+
+	for (prescale = 0; prescale <= 7; prescale++) {
+		clk_cycle = clk_rate / ((1 << prescale) * lpi2c_imx->bitrate)
+			    - 3 - (filt >> 1);
+		clkhi = (clk_cycle + I2C_CLK_RATIO) / (I2C_CLK_RATIO + 1);
+		clklo = clk_cycle - clkhi;
+		if (clklo < 64)
+			break;
+	}
+
+	if (prescale > 7)
+		return -EINVAL;
+
+	/* set MCFGR1: PINCFG, PRESCALE, IGNACK */
+	if (lpi2c_imx->mode == ULTRA_FAST)
+		pincfg = TWO_PIN_OO;
+	else
+		pincfg = TWO_PIN_OD;
+	temp = prescale | pincfg << 24;
+
+	if (lpi2c_imx->mode == ULTRA_FAST)
+		temp |= MCFGR1_IGNACK;
+
+	writel(temp, lpi2c_imx->base + LPI2C_MCFGR1);
+
+	/* set MCFGR2: FILTSDA, FILTSCL */
+	temp = (filt << 16) | (filt << 24);
+	writel(temp, lpi2c_imx->base + LPI2C_MCFGR2);
+
+	/* set MCCR: DATAVD, SETHOLD, CLKHI, CLKLO */
+	sethold = clkhi;
+	datavd = clkhi >> 1;
+	temp = datavd << 24 | sethold << 16 | clkhi << 8 | clklo;
+
+	if (lpi2c_imx->mode == HS)
+		writel(temp, lpi2c_imx->base + LPI2C_MCCR1);
+	else
+		writel(temp, lpi2c_imx->base + LPI2C_MCCR0);
+
+	return 0;
+}
+
+static int lpi2c_imx_master_enable(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned int temp;
+	int ret;
+
+	ret = clk_enable(lpi2c_imx->clk);
+	if (ret)
+		return ret;
+
+	temp = MCR_RST;
+	writel(temp, lpi2c_imx->base + LPI2C_MCR);
+	writel(0, lpi2c_imx->base + LPI2C_MCR);
+
+	ret = lpi2c_imx_config(lpi2c_imx);
+	if (ret)
+		goto clk_disable;
+
+	temp = readl(lpi2c_imx->base + LPI2C_MCR);
+	temp |= MCR_MEN;
+	writel(temp, lpi2c_imx->base + LPI2C_MCR);
+
+	return 0;
+
+clk_disable:
+	clk_disable(lpi2c_imx->clk);
+
+	return ret;
+}
+
+static int lpi2c_imx_master_disable(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	u32 temp;
+
+	temp = readl(lpi2c_imx->base + LPI2C_MCR);
+	temp &= ~MCR_MEN;
+	writel(temp, lpi2c_imx->base + LPI2C_MCR);
+
+	clk_disable(lpi2c_imx->clk);
+
+	return 0;
+}
+
+static int lpi2c_imx_msg_complete(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned long timeout;
+
+	timeout = wait_for_completion_timeout(&lpi2c_imx->complete, HZ);
+
+	return timeout ? 0 : -ETIMEDOUT;
+}
+
+static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned long orig_jiffies = jiffies;
+	u32 txcnt;
+
+	do {
+		txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
+
+		if (readl(lpi2c_imx->base + LPI2C_MSR) & MSR_NDF) {
+			dev_dbg(&lpi2c_imx->adapter.dev, "NDF detected\n");
+			return -EIO;
+		}
+
+		if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
+			dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
+			return -ETIMEDOUT;
+		}
+		schedule();
+
+	} while (txcnt);
+
+	return 0;
+}
+
+static void lpi2c_imx_set_tx_watermark(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	writel(lpi2c_imx->txfifosize >> 1, lpi2c_imx->base + LPI2C_MFCR);
+}
+
+static void lpi2c_imx_set_rx_watermark(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned int temp, remaining;
+
+	remaining = lpi2c_imx->msglen - lpi2c_imx->delivered;
+
+	if (remaining > (lpi2c_imx->rxfifosize >> 1))
+		temp = lpi2c_imx->rxfifosize >> 1;
+	else
+		temp = 0;
+
+	writel(temp << 16, lpi2c_imx->base + LPI2C_MFCR);
+}
+
+static void lpi2c_imx_write_txfifo(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned int data, txcnt;
+
+	txcnt = readl(lpi2c_imx->base + LPI2C_MFSR) & 0xff;
+
+	while (txcnt < lpi2c_imx->txfifosize) {
+		if (lpi2c_imx->delivered == lpi2c_imx->msglen)
+			break;
+
+		data = lpi2c_imx->tx_buf[lpi2c_imx->delivered++];
+		writel(data, lpi2c_imx->base + LPI2C_MTDR);
+		txcnt++;
+	}
+
+	if (lpi2c_imx->delivered < lpi2c_imx->msglen)
+		lpi2c_imx_intctrl(lpi2c_imx, MIER_TDIE | MIER_NDIE);
+	else
+		complete(&lpi2c_imx->complete);
+}
+
+static void lpi2c_imx_read_rxfifo(struct lpi2c_imx_struct *lpi2c_imx)
+{
+	unsigned int blocklen, remaining;
+	unsigned int temp, data;
+
+	do {
+		data = readl(lpi2c_imx->base + LPI2C_MRDR);
+		if (data & MRDR_RXEMPTY)
+			break;
+
+		lpi2c_imx->rx_buf[lpi2c_imx->delivered++] = data & 0xff;
+	} while (1);
+
+	/*
+	 * First byte is the length of remaining packet in the SMBus block
+	 * data read. Add it to msgs->len.
+	 */
+	if (lpi2c_imx->block_data) {
+		blocklen = lpi2c_imx->rx_buf[0];
+		lpi2c_imx->msglen += blocklen;
+	}
+
+	remaining = lpi2c_imx->msglen - lpi2c_imx->delivered;
+
+	if (!remaining) {
+		complete(&lpi2c_imx->complete);
+		return;
+	}
+
+	/* not finished, still waiting for rx data */
+	lpi2c_imx_set_rx_watermark(lpi2c_imx);
+
+	/* multiple receive commands */
+	if (lpi2c_imx->block_data) {
+		lpi2c_imx->block_data = 0;
+		temp = remaining;
+		temp |= (RECV_DATA << 8);
+		writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+	} else if (!(lpi2c_imx->delivered & 0xff)) {
+		temp = (remaining > CHUNK_DATA ? CHUNK_DATA : remaining) - 1;
+		temp |= (RECV_DATA << 8);
+		writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+	}
+
+	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE);
+}
+
+static void lpi2c_imx_write(struct lpi2c_imx_struct *lpi2c_imx,
+			    struct i2c_msg *msgs)
+{
+	lpi2c_imx->tx_buf = msgs->buf;
+	lpi2c_imx_set_tx_watermark(lpi2c_imx);
+	lpi2c_imx_write_txfifo(lpi2c_imx);
+}
+
+static void lpi2c_imx_read(struct lpi2c_imx_struct *lpi2c_imx,
+			   struct i2c_msg *msgs)
+{
+	unsigned int temp;
+
+	lpi2c_imx->rx_buf = msgs->buf;
+	lpi2c_imx->block_data = msgs->flags & I2C_M_RECV_LEN;
+
+	lpi2c_imx_set_rx_watermark(lpi2c_imx);
+	temp = msgs->len > CHUNK_DATA ? CHUNK_DATA - 1 : msgs->len - 1;
+	temp |= (RECV_DATA << 8);
+	writel(temp, lpi2c_imx->base + LPI2C_MTDR);
+
+	lpi2c_imx_intctrl(lpi2c_imx, MIER_RDIE | MIER_NDIE);
+}
+
+static int lpi2c_imx_xfer(struct i2c_adapter *adapter,
+			  struct i2c_msg *msgs, int num)
+{
+	struct lpi2c_imx_struct *lpi2c_imx = i2c_get_adapdata(adapter);
+	unsigned int temp;
+	int i, result;
+
+	result = lpi2c_imx_master_enable(lpi2c_imx);
+	if (result)
+		return result;
+
+	for (i = 0; i < num; i++) {
+		result = lpi2c_imx_start(lpi2c_imx, &msgs[i]);
+		if (result)
+			goto disable;
+
+		/* quick smbus */
+		if (num == 1 && msgs[0].len == 0)
+			goto stop;
+
+		lpi2c_imx->delivered = 0;
+		lpi2c_imx->msglen = msgs[i].len;
+		init_completion(&lpi2c_imx->complete);
+
+		if (msgs[i].flags & I2C_M_RD)
+			lpi2c_imx_read(lpi2c_imx, &msgs[i]);
+		else
+			lpi2c_imx_write(lpi2c_imx, &msgs[i]);
+
+		result = lpi2c_imx_msg_complete(lpi2c_imx);
+		if (result)
+			goto stop;
+
+		if (!(msgs[i].flags & I2C_M_RD)) {
+			result = lpi2c_imx_txfifo_empty(lpi2c_imx);
+			if (result)
+				goto stop;
+		}
+	}
+
+stop:
+	lpi2c_imx_stop(lpi2c_imx);
+
+	temp = readl(lpi2c_imx->base + LPI2C_MSR);
+	if ((temp & MSR_NDF) && !result)
+		result = -EIO;
+
+disable:
+	lpi2c_imx_master_disable(lpi2c_imx);
+
+	dev_dbg(&lpi2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
+		(result < 0) ? "error" : "success msg",
+		(result < 0) ? result : num);
+
+	return (result < 0) ? result : num;
+}
+
+static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
+{
+	struct lpi2c_imx_struct *lpi2c_imx = dev_id;
+	unsigned int temp;
+
+	lpi2c_imx_intctrl(lpi2c_imx, 0);
+	temp = readl(lpi2c_imx->base + LPI2C_MSR);
+
+	if (temp & MSR_RDF)
+		lpi2c_imx_read_rxfifo(lpi2c_imx);
+
+	if (temp & MSR_TDF)
+		lpi2c_imx_write_txfifo(lpi2c_imx);
+
+	if (temp & MSR_NDF)
+		complete(&lpi2c_imx->complete);
+
+	return IRQ_HANDLED;
+}
+
+static u32 lpi2c_imx_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+		I2C_FUNC_SMBUS_READ_BLOCK_DATA;
+}
+
+static struct i2c_algorithm lpi2c_imx_algo = {
+	.master_xfer	= lpi2c_imx_xfer,
+	.functionality	= lpi2c_imx_func,
+};
+
+static const struct of_device_id lpi2c_imx_of_match[] = {
+	{ .compatible = "fsl,imx7ulp-lpi2c" },
+	{ .compatible = "fsl,imx8dv-lpi2c" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);
+
+static int lpi2c_imx_probe(struct platform_device *pdev)
+{
+	struct lpi2c_imx_struct *lpi2c_imx;
+	struct resource *res;
+	unsigned int temp;
+	int irq, ret;
+
+	lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL);
+	if (!lpi2c_imx)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lpi2c_imx->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(lpi2c_imx->base))
+		return PTR_ERR(lpi2c_imx->base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "can't get irq number\n");
+		return irq;
+	}
+
+	lpi2c_imx->adapter.owner	= THIS_MODULE;
+	lpi2c_imx->adapter.algo		= &lpi2c_imx_algo;
+	lpi2c_imx->adapter.dev.parent	= &pdev->dev;
+	lpi2c_imx->adapter.dev.of_node	= pdev->dev.of_node;
+	strlcpy(lpi2c_imx->adapter.name, pdev->name,
+		sizeof(lpi2c_imx->adapter.name));
+
+	lpi2c_imx->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(lpi2c_imx->clk)) {
+		dev_err(&pdev->dev, "can't get I2C peripheral clock\n");
+		return PTR_ERR(lpi2c_imx->clk);
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+				   "clock-frequency", &lpi2c_imx->bitrate);
+	if (ret)
+		lpi2c_imx->bitrate = LPI2C_DEFAULT_RATE;
+
+	ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, 0,
+			       pdev->name, lpi2c_imx);
+	if (ret) {
+		dev_err(&pdev->dev, "can't claim irq %d\n", irq);
+		return ret;
+	}
+
+	i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
+	platform_set_drvdata(pdev, lpi2c_imx);
+
+	ret = clk_prepare_enable(lpi2c_imx->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "clk enable failed %d\n", ret);
+		return ret;
+	}
+
+	temp = readl(lpi2c_imx->base + LPI2C_PARAM);
+	lpi2c_imx->txfifosize = 1 << (temp & 0x0f);
+	lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f);
+
+	clk_disable(lpi2c_imx->clk);
+
+	ret = i2c_add_adapter(&lpi2c_imx->adapter);
+	if (ret)
+		goto clk_unprepare;
+
+	dev_info(&lpi2c_imx->adapter.dev, "LPI2C adapter registered\n");
+
+	return 0;
+
+clk_unprepare:
+	clk_unprepare(lpi2c_imx->clk);
+
+	return ret;
+}
+
+static int lpi2c_imx_remove(struct platform_device *pdev)
+{
+	struct lpi2c_imx_struct *lpi2c_imx = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&lpi2c_imx->adapter);
+
+	clk_unprepare(lpi2c_imx->clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lpi2c_imx_suspend(struct device *dev)
+{
+	pinctrl_pm_select_sleep_state(dev);
+
+	return 0;
+}
+
+static int lpi2c_imx_resume(struct device *dev)
+{
+	pinctrl_pm_select_default_state(dev);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(imx_lpi2c_pm, lpi2c_imx_suspend, lpi2c_imx_resume);
+
+static struct platform_driver lpi2c_imx_driver = {
+	.probe = lpi2c_imx_probe,
+	.remove = lpi2c_imx_remove,
+	.driver = {
+		.name = DRIVER_NAME,
+		.of_match_table = lpi2c_imx_of_match,
+		.pm = &imx_lpi2c_pm,
+	},
+};
+
+module_platform_driver(lpi2c_imx_driver);
+
+MODULE_AUTHOR("Gao Pan <pandy.gao@nxp.com>");
+MODULE_DESCRIPTION("I2C adapter driver for LPI2C bus");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-mlxcpld.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-mlxcpld.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-mlxcpld.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-mlxcpld.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+/* General defines */
+#define MLXPLAT_CPLD_LPC_I2C_BASE_ADDR	0x2000
+#define MLXCPLD_I2C_DEVICE_NAME		"i2c_mlxcpld"
+#define MLXCPLD_I2C_VALID_FLAG		(I2C_M_RECV_LEN | I2C_M_RD)
+#define MLXCPLD_I2C_BUS_NUM		1
+#define MLXCPLD_I2C_DATA_REG_SZ		36
+#define MLXCPLD_I2C_MAX_ADDR_LEN	4
+#define MLXCPLD_I2C_RETR_NUM		2
+#define MLXCPLD_I2C_XFER_TO		500000 /* usec */
+#define MLXCPLD_I2C_POLL_TIME		2000   /* usec */
+
+/* LPC I2C registers */
+#define MLXCPLD_LPCI2C_LPF_REG		0x0
+#define MLXCPLD_LPCI2C_CTRL_REG		0x1
+#define MLXCPLD_LPCI2C_HALF_CYC_REG	0x4
+#define MLXCPLD_LPCI2C_I2C_HOLD_REG	0x5
+#define MLXCPLD_LPCI2C_CMD_REG		0x6
+#define MLXCPLD_LPCI2C_NUM_DAT_REG	0x7
+#define MLXCPLD_LPCI2C_NUM_ADDR_REG	0x8
+#define MLXCPLD_LPCI2C_STATUS_REG	0x9
+#define MLXCPLD_LPCI2C_DATA_REG		0xa
+
+/* LPC I2C masks and parametres */
+#define MLXCPLD_LPCI2C_RST_SEL_MASK	0x1
+#define MLXCPLD_LPCI2C_TRANS_END	0x1
+#define MLXCPLD_LPCI2C_STATUS_NACK	0x10
+#define MLXCPLD_LPCI2C_NO_IND		0
+#define MLXCPLD_LPCI2C_ACK_IND		1
+#define MLXCPLD_LPCI2C_NACK_IND		2
+
+struct  mlxcpld_i2c_curr_xfer {
+	u8 cmd;
+	u8 addr_width;
+	u8 data_len;
+	u8 msg_num;
+	struct i2c_msg *msg;
+};
+
+struct mlxcpld_i2c_priv {
+	struct i2c_adapter adap;
+	u32 base_addr;
+	struct mutex lock;
+	struct  mlxcpld_i2c_curr_xfer xfer;
+	struct device *dev;
+};
+
+static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr)
+{
+	int i;
+
+	for (i = 0; i < len - len % 4; i += 4)
+		outl(*(u32 *)(data + i), addr + i);
+	for (; i < len; ++i)
+		outb(*(data + i), addr + i);
+}
+
+static void mlxcpld_i2c_lpc_read_buf(u8 *data, u8 len, u32 addr)
+{
+	int i;
+
+	for (i = 0; i < len - len % 4; i += 4)
+		*(u32 *)(data + i) = inl(addr + i);
+	for (; i < len; ++i)
+		*(data + i) = inb(addr + i);
+}
+
+static void mlxcpld_i2c_read_comm(struct mlxcpld_i2c_priv *priv, u8 offs,
+				  u8 *data, u8 datalen)
+{
+	u32 addr = priv->base_addr + offs;
+
+	switch (datalen) {
+	case 1:
+		*(data) = inb(addr);
+		break;
+	case 2:
+		*((u16 *)data) = inw(addr);
+		break;
+	case 3:
+		*((u16 *)data) = inw(addr);
+		*(data + 2) = inb(addr + 2);
+		break;
+	case 4:
+		*((u32 *)data) = inl(addr);
+		break;
+	default:
+		mlxcpld_i2c_lpc_read_buf(data, datalen, addr);
+		break;
+	}
+}
+
+static void mlxcpld_i2c_write_comm(struct mlxcpld_i2c_priv *priv, u8 offs,
+				   u8 *data, u8 datalen)
+{
+	u32 addr = priv->base_addr + offs;
+
+	switch (datalen) {
+	case 1:
+		outb(*(data), addr);
+		break;
+	case 2:
+		outw(*((u16 *)data), addr);
+		break;
+	case 3:
+		outw(*((u16 *)data), addr);
+		outb(*(data + 2), addr + 2);
+		break;
+	case 4:
+		outl(*((u32 *)data), addr);
+		break;
+	default:
+		mlxcpld_i2c_lpc_write_buf(data, datalen, addr);
+		break;
+	}
+}
+
+/*
+ * Check validity of received i2c messages parameters.
+ * Returns 0 if OK, other - in case of invalid parameters.
+ */
+static int mlxcpld_i2c_check_msg_params(struct mlxcpld_i2c_priv *priv,
+					struct i2c_msg *msgs, int num)
+{
+	int i;
+
+	if (!num) {
+		dev_err(priv->dev, "Incorrect 0 num of messages\n");
+		return -EINVAL;
+	}
+
+	if (unlikely(msgs[0].addr > 0x7f)) {
+		dev_err(priv->dev, "Invalid address 0x%03x\n",
+			msgs[0].addr);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num; ++i) {
+		if (unlikely(!msgs[i].buf)) {
+			dev_err(priv->dev, "Invalid buf in msg[%d]\n",
+				i);
+			return -EINVAL;
+		}
+		if (unlikely(msgs[0].addr != msgs[i].addr)) {
+			dev_err(priv->dev, "Invalid addr in msg[%d]\n",
+				i);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Check if transfer is completed and status of operation.
+ * Returns 0 - transfer completed (both ACK or NACK),
+ * negative - transfer isn't finished.
+ */
+static int mlxcpld_i2c_check_status(struct mlxcpld_i2c_priv *priv, int *status)
+{
+	u8 val;
+
+	mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1);
+
+	if (val & MLXCPLD_LPCI2C_TRANS_END) {
+		if (val & MLXCPLD_LPCI2C_STATUS_NACK)
+			/*
+			 * The slave is unable to accept the data. No such
+			 * slave, command not understood, or unable to accept
+			 * any more data.
+			 */
+			*status = MLXCPLD_LPCI2C_NACK_IND;
+		else
+			*status = MLXCPLD_LPCI2C_ACK_IND;
+		return 0;
+	}
+	*status = MLXCPLD_LPCI2C_NO_IND;
+
+	return -EIO;
+}
+
+static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv,
+					struct i2c_msg *msgs, int num,
+					u8 comm_len)
+{
+	priv->xfer.msg = msgs;
+	priv->xfer.msg_num = num;
+
+	/*
+	 * All upper layers currently are never use transfer with more than
+	 * 2 messages. Actually, it's also not so relevant in Mellanox systems
+	 * because of HW limitation. Max size of transfer is not more than 32
+	 * bytes in the current x86 LPCI2C bridge.
+	 */
+	priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
+
+	if (priv->xfer.cmd == I2C_M_RD && comm_len != msgs[0].len) {
+		priv->xfer.addr_width = msgs[0].len;
+		priv->xfer.data_len = comm_len - priv->xfer.addr_width;
+	} else {
+		priv->xfer.addr_width = 0;
+		priv->xfer.data_len = comm_len;
+	}
+}
+
+/* Reset CPLD LPCI2C block */
+static void mlxcpld_i2c_reset(struct mlxcpld_i2c_priv *priv)
+{
+	u8 val;
+
+	mutex_lock(&priv->lock);
+
+	mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1);
+	val &= ~MLXCPLD_LPCI2C_RST_SEL_MASK;
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CTRL_REG, &val, 1);
+
+	mutex_unlock(&priv->lock);
+}
+
+/* Make sure the CPLD is ready to start transmitting. */
+static int mlxcpld_i2c_check_busy(struct mlxcpld_i2c_priv *priv)
+{
+	u8 val;
+
+	mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_STATUS_REG, &val, 1);
+
+	if (val & MLXCPLD_LPCI2C_TRANS_END)
+		return 0;
+
+	return -EIO;
+}
+
+static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
+{
+	int timeout = 0;
+
+	do {
+		if (!mlxcpld_i2c_check_busy(priv))
+			break;
+		usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
+		timeout += MLXCPLD_I2C_POLL_TIME;
+	} while (timeout <= MLXCPLD_I2C_XFER_TO);
+
+	if (timeout > MLXCPLD_I2C_XFER_TO)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/*
+ * Wait for master transfer to complete.
+ * It puts current process to sleep until we get interrupt or timeout expires.
+ * Returns the number of transferred or read bytes or error (<0).
+ */
+static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
+{
+	int status, i, timeout = 0;
+	u8 datalen;
+
+	do {
+		usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
+		if (!mlxcpld_i2c_check_status(priv, &status))
+			break;
+		timeout += MLXCPLD_I2C_POLL_TIME;
+	} while (status == 0 && timeout < MLXCPLD_I2C_XFER_TO);
+
+	switch (status) {
+	case MLXCPLD_LPCI2C_NO_IND:
+		return -ETIMEDOUT;
+
+	case MLXCPLD_LPCI2C_ACK_IND:
+		if (priv->xfer.cmd != I2C_M_RD)
+			return (priv->xfer.addr_width + priv->xfer.data_len);
+
+		if (priv->xfer.msg_num == 1)
+			i = 0;
+		else
+			i = 1;
+
+		if (!priv->xfer.msg[i].buf)
+			return -EINVAL;
+
+		/*
+		 * Actual read data len will be always the same as
+		 * requested len. 0xff (line pull-up) will be returned
+		 * if slave has no data to return. Thus don't read
+		 * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.
+		 */
+		datalen = priv->xfer.data_len;
+
+		mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG,
+				      priv->xfer.msg[i].buf, datalen);
+
+		return datalen;
+
+	case MLXCPLD_LPCI2C_NACK_IND:
+		return -ENXIO;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv)
+{
+	int i, len = 0;
+	u8 cmd;
+
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
+			       &priv->xfer.data_len, 1);
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG,
+			       &priv->xfer.addr_width, 1);
+
+	for (i = 0; i < priv->xfer.msg_num; i++) {
+		if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) {
+			/* Don't write to CPLD buffer in read transaction */
+			mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_DATA_REG +
+					       len, priv->xfer.msg[i].buf,
+					       priv->xfer.msg[i].len);
+			len += priv->xfer.msg[i].len;
+		}
+	}
+
+	/*
+	 * Set target slave address with command for master transfer.
+	 * It should be latest executed function before CPLD transaction.
+	 */
+	cmd = (priv->xfer.msg[0].addr << 1) | priv->xfer.cmd;
+	mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_CMD_REG, &cmd, 1);
+}
+
+/*
+ * Generic lpc-i2c transfer.
+ * Returns the number of processed messages or error (<0).
+ */
+static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			    int num)
+{
+	struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
+	u8 comm_len = 0;
+	int i, err;
+
+	err = mlxcpld_i2c_check_msg_params(priv, msgs, num);
+	if (err) {
+		dev_err(priv->dev, "Incorrect message\n");
+		return err;
+	}
+
+	for (i = 0; i < num; ++i)
+		comm_len += msgs[i].len;
+
+	/* Check bus state */
+	if (mlxcpld_i2c_wait_for_free(priv)) {
+		dev_err(priv->dev, "LPCI2C bridge is busy\n");
+
+		/*
+		 * Usually it means something serious has happened.
+		 * We can not have unfinished previous transfer
+		 * so it doesn't make any sense to try to stop it.
+		 * Probably we were not able to recover from the
+		 * previous error.
+		 * The only reasonable thing - is soft reset.
+		 */
+		mlxcpld_i2c_reset(priv);
+		if (mlxcpld_i2c_check_busy(priv)) {
+			dev_err(priv->dev, "LPCI2C bridge is busy after reset\n");
+			return -EIO;
+		}
+	}
+
+	mlxcpld_i2c_set_transf_data(priv, msgs, num, comm_len);
+
+	mutex_lock(&priv->lock);
+
+	/* Do real transfer. Can't fail */
+	mlxcpld_i2c_xfer_msg(priv);
+
+	/* Wait for transaction complete */
+	err = mlxcpld_i2c_wait_for_tc(priv);
+
+	mutex_unlock(&priv->lock);
+
+	return err < 0 ? err : num;
+}
+
+static u32 mlxcpld_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static const struct i2c_algorithm mlxcpld_i2c_algo = {
+	.master_xfer	= mlxcpld_i2c_xfer,
+	.functionality	= mlxcpld_i2c_func
+};
+
+static struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
+	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
+	.max_read_len = MLXCPLD_I2C_DATA_REG_SZ - MLXCPLD_I2C_MAX_ADDR_LEN,
+	.max_write_len = MLXCPLD_I2C_DATA_REG_SZ,
+	.max_comb_1st_msg_len = 4,
+};
+
+static struct i2c_adapter mlxcpld_i2c_adapter = {
+	.owner          = THIS_MODULE,
+	.name           = "i2c-mlxcpld",
+	.class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+	.algo           = &mlxcpld_i2c_algo,
+	.quirks		= &mlxcpld_i2c_quirks,
+	.retries	= MLXCPLD_I2C_RETR_NUM,
+	.nr		= MLXCPLD_I2C_BUS_NUM,
+};
+
+static int mlxcpld_i2c_probe(struct platform_device *pdev)
+{
+	struct mlxcpld_i2c_priv *priv;
+	int err;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	mutex_init(&priv->lock);
+	platform_set_drvdata(pdev, priv);
+
+	priv->dev = &pdev->dev;
+
+	/* Register with i2c layer */
+	mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
+	priv->adap = mlxcpld_i2c_adapter;
+	priv->adap.dev.parent = &pdev->dev;
+	priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
+	i2c_set_adapdata(&priv->adap, priv);
+
+	err = i2c_add_numbered_adapter(&priv->adap);
+	if (err)
+		mutex_destroy(&priv->lock);
+
+	return err;
+}
+
+static int mlxcpld_i2c_remove(struct platform_device *pdev)
+{
+	struct mlxcpld_i2c_priv *priv = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(&priv->adap);
+	mutex_destroy(&priv->lock);
+
+	return 0;
+}
+
+static struct platform_driver mlxcpld_i2c_driver = {
+	.probe		= mlxcpld_i2c_probe,
+	.remove		= mlxcpld_i2c_remove,
+	.driver = {
+		.name = MLXCPLD_I2C_DEVICE_NAME,
+	},
+};
+
+module_platform_driver(mlxcpld_i2c_driver);
+
+MODULE_AUTHOR("Michael Shych <michaels@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox I2C-CPLD controller driver");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:i2c-mlxcpld");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-octeon-core.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-octeon-core.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-octeon-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-octeon-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,24 +36,6 @@ static bool octeon_i2c_test_iflg(struct
 	return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG);
 }
 
-static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first)
-{
-	if (octeon_i2c_test_iflg(i2c))
-		return true;
-
-	if (*first) {
-		*first = false;
-		return false;
-	}
-
-	/*
-	 * IRQ has signaled an event but IFLG hasn't changed.
-	 * Sleep and retry once.
-	 */
-	usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
-	return octeon_i2c_test_iflg(i2c);
-}
-
 /**
  * octeon_i2c_wait - wait for the IFLG to be set
  * @i2c: The struct octeon_i2c
@@ -63,7 +45,6 @@ static bool octeon_i2c_test_ready(struct
 static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
 	long time_left;
-	bool first = true;
 
 	/*
 	 * Some chip revisions don't assert the irq in the interrupt
@@ -80,7 +61,7 @@ static int octeon_i2c_wait(struct octeon
 	}
 
 	i2c->int_enable(i2c);
-	time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, &first),
+	time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c),
 				       i2c->adap.timeout);
 	i2c->int_disable(i2c);
 
@@ -102,25 +83,6 @@ static bool octeon_i2c_hlc_test_valid(st
 	return (__raw_readq(i2c->twsi_base + SW_TWSI(i2c)) & SW_TWSI_V) == 0;
 }
 
-static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first)
-{
-	/* check if valid bit is cleared */
-	if (octeon_i2c_hlc_test_valid(i2c))
-		return true;
-
-	if (*first) {
-		*first = false;
-		return false;
-	}
-
-	/*
-	 * IRQ has signaled an event but valid bit isn't cleared.
-	 * Sleep and retry once.
-	 */
-	usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
-	return octeon_i2c_hlc_test_valid(i2c);
-}
-
 static void octeon_i2c_hlc_int_clear(struct octeon_i2c *i2c)
 {
 	/* clear ST/TS events, listen for neither */
@@ -176,7 +138,6 @@ static void octeon_i2c_hlc_disable(struc
  */
 static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
-	bool first = true;
 	int time_left;
 
 	/*
@@ -195,7 +156,7 @@ static int octeon_i2c_hlc_wait(struct oc
 
 	i2c->hlc_int_enable(i2c);
 	time_left = wait_event_timeout(i2c->queue,
-				       octeon_i2c_hlc_test_ready(i2c, &first),
+				       octeon_i2c_hlc_test_valid(i2c),
 				       i2c->adap.timeout);
 	i2c->hlc_int_disable(i2c);
 	if (!time_left)
@@ -381,7 +342,9 @@ static int octeon_i2c_read(struct octeon
 		if (result)
 			return result;
 
-		data[i] = octeon_i2c_data_read(i2c);
+		data[i] = octeon_i2c_data_read(i2c, &result);
+		if (result)
+			return result;
 		if (recv_len && i == 0) {
 			if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
 				return -EPROTO;
@@ -789,6 +752,9 @@ static void octeon_i2c_prepare_recovery(
 	struct octeon_i2c *i2c = i2c_get_adapdata(adap);
 
 	octeon_i2c_hlc_disable(i2c);
+	octeon_i2c_reg_write(i2c, SW_TWSI_EOP_TWSI_RST, 0);
+	/* wait for software reset to settle */
+	udelay(5);
 
 	/*
 	 * Bring control register to a good state regardless
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-octeon-core.h linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-octeon-core.h
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-octeon-core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-octeon-core.h	2017-02-12 16:03:20.000000000 -0500
@@ -141,11 +141,14 @@ static inline void octeon_i2c_writeq_flu
  */
 static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
 {
+	int tries = 1000;
 	u64 tmp;
 
 	__raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c));
 	do {
 		tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+		if (--tries < 0)
+			return;
 	} while ((tmp & SW_TWSI_V) != 0);
 }
 
@@ -163,24 +166,32 @@ static inline void octeon_i2c_reg_write(
  *
  * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
  */
-static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg)
+static inline int octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg,
+				      int *error)
 {
+	int tries = 1000;
 	u64 tmp;
 
 	__raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c));
 	do {
 		tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+		if (--tries < 0) {
+			/* signal that the returned data is invalid */
+			if (error)
+				*error = -EIO;
+			return 0;
+		}
 	} while ((tmp & SW_TWSI_V) != 0);
 
 	return tmp & 0xFF;
 }
 
 #define octeon_i2c_ctl_read(i2c)					\
-	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL)
-#define octeon_i2c_data_read(i2c)					\
-	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA)
+	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL)
+#define octeon_i2c_data_read(i2c, error)				\
+	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error)
 #define octeon_i2c_stat_read(i2c)					\
-	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT)
+	octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT, NULL)
 
 /**
  * octeon_i2c_read_int - read the TWSI_INT register
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-piix4.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-piix4.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-piix4.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-piix4.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,7 @@
 #define SMBSLVDAT	(0xC + piix4_smba)
 
 /* count for request_region */
-#define SMBIOSIZE	8
+#define SMBIOSIZE	9
 
 /* PCI Address Constants */
 #define SMBBA		0x090
@@ -585,12 +585,33 @@ static s32 piix4_access_sb800(struct i2c
 		 u8 command, int size, union i2c_smbus_data *data)
 {
 	struct i2c_piix4_adapdata *adapdata = i2c_get_adapdata(adap);
+	unsigned short piix4_smba = adapdata->smba;
+	int retries = MAX_TIMEOUT;
+	int smbslvcnt;
 	u8 smba_en_lo;
 	u8 port;
 	int retval;
 
 	mutex_lock(&piix4_mutex_sb800);
 
+	/* Request the SMBUS semaphore, avoid conflicts with the IMC */
+	smbslvcnt  = inb_p(SMBSLVCNT);
+	do {
+		outb_p(smbslvcnt | 0x10, SMBSLVCNT);
+
+		/* Check the semaphore status */
+		smbslvcnt  = inb_p(SMBSLVCNT);
+		if (smbslvcnt & 0x10)
+			break;
+
+		usleep_range(1000, 2000);
+	} while (--retries);
+	/* SMBus is still owned by the IMC, we give up */
+	if (!retries) {
+		mutex_unlock(&piix4_mutex_sb800);
+		return -EBUSY;
+	}
+
 	outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX);
 	smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1);
 
@@ -604,6 +625,9 @@ static s32 piix4_access_sb800(struct i2c
 
 	outb_p(smba_en_lo, SB800_PIIX4_SMB_IDX + 1);
 
+	/* Release the semaphore */
+	outb_p(smbslvcnt | 0x20, SMBSLVCNT);
+
 	mutex_unlock(&piix4_mutex_sb800);
 
 	return retval;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-pxa.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-pxa.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-pxa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-pxa.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,8 @@ struct pxa_reg_layout {
 	u32 isar;
 	u32 ilcr;
 	u32 iwcr;
+	u32 fm;
+	u32 hs;
 };
 
 enum pxa_i2c_types {
@@ -55,8 +57,12 @@ enum pxa_i2c_types {
 	REGS_PXA3XX,
 	REGS_CE4100,
 	REGS_PXA910,
+	REGS_A3700,
 };
 
+#define ICR_BUSMODE_FM	(1 << 16)	   /* shifted fast mode for armada-3700 */
+#define ICR_BUSMODE_HS	(1 << 17)	   /* shifted high speed mode for armada-3700 */
+
 /*
  * I2C registers definitions
  */
@@ -91,6 +97,15 @@ static struct pxa_reg_layout pxa_reg_lay
 		.ilcr = 0x28,
 		.iwcr = 0x30,
 	},
+	[REGS_A3700] = {
+		.ibmr =	0x00,
+		.idbr =	0x04,
+		.icr =	0x08,
+		.isr =	0x0c,
+		.isar =	0x10,
+		.fm = ICR_BUSMODE_FM,
+		.hs = ICR_BUSMODE_HS,
+	},
 };
 
 static const struct platform_device_id i2c_pxa_id_table[] = {
@@ -98,6 +113,7 @@ static const struct platform_device_id i
 	{ "pxa3xx-pwri2c",	REGS_PXA3XX },
 	{ "ce4100-i2c",		REGS_CE4100 },
 	{ "pxa910-i2c",		REGS_PXA910 },
+	{ "armada-3700-i2c",	REGS_A3700  },
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
@@ -193,6 +209,8 @@ struct pxa_i2c {
 	unsigned char		master_code;
 	unsigned long		rate;
 	bool			highmode_enter;
+	u32			fm_mask;
+	u32			hs_mask;
 };
 
 #define _IBMR(i2c)	((i2c)->reg_ibmr)
@@ -503,8 +521,8 @@ static void i2c_pxa_reset(struct pxa_i2c
 		writel(i2c->slave_addr, _ISAR(i2c));
 
 	/* set control register values */
-	writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
-	writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c));
+	writel(I2C_ICR_INIT | (i2c->fast_mode ? i2c->fm_mask : 0), _ICR(i2c));
+	writel(readl(_ICR(i2c)) | (i2c->high_mode ? i2c->hs_mask : 0), _ICR(i2c));
 
 #ifdef CONFIG_I2C_PXA_SLAVE
 	dev_info(&i2c->adap.dev, "Enabling slave mode\n");
@@ -1137,6 +1155,7 @@ static const struct of_device_id i2c_pxa
 	{ .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX },
 	{ .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX },
 	{ .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 },
+	{ .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 },
 	{}
 };
 MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids);
@@ -1234,6 +1253,9 @@ static int i2c_pxa_probe(struct platform
 	i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
 	i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
 	i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
+	i2c->fm_mask = pxa_reg_layout[i2c_type].fm ? : ICR_FM;
+	i2c->hs_mask = pxa_reg_layout[i2c_type].hs ? : ICR_HS;
+
 	if (i2c_type != REGS_CE4100)
 		i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-pxa-pci.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-pxa-pci.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-pxa-pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-pxa-pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,9 +1,13 @@
 /*
+ * CE4100 PCI-I2C glue code for PXA's driver
+ * Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ * License: GPL v2
+ *
  * The CE4100's I2C device is more or less the same one as found on PXA.
  * It does not support slave mode, the register slightly moved. This PCI
  * device provides three bars, every contains a single I2C controller.
  */
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/i2c/pxa-i2c.h>
@@ -134,35 +138,17 @@ err_mem:
 	return ret;
 }
 
-static void ce4100_i2c_remove(struct pci_dev *dev)
-{
-	struct ce4100_devices *sds;
-	unsigned int i;
-
-	sds = pci_get_drvdata(dev);
-
-	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
-		platform_device_unregister(sds->pdev[i]);
-
-	pci_disable_device(dev);
-	kfree(sds);
-}
-
 static const struct pci_device_id ce4100_i2c_devices[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
 	{ },
 };
-MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
 
 static struct pci_driver ce4100_i2c_driver = {
+	.driver = {
+		.suppress_bind_attrs = true,
+	},
 	.name           = "ce4100_i2c",
 	.id_table       = ce4100_i2c_devices,
 	.probe          = ce4100_i2c_probe,
-	.remove         = ce4100_i2c_remove,
 };
-
-module_pci_driver(ce4100_i2c_driver);
-
-MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
+builtin_pci_driver(ce4100_i2c_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-qup.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-qup.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-qup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-qup.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/acpi.h>
 #include <linux/atomic.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -132,6 +133,10 @@
 /* Max timeout in ms for 32k bytes */
 #define TOUT_MAX			300
 
+/* Default values. Use these if FW query fails */
+#define DEFAULT_CLK_FREQ 100000
+#define DEFAULT_SRC_CLK 20000000
+
 struct qup_i2c_block {
 	int	count;
 	int	pos;
@@ -525,6 +530,33 @@ static int qup_i2c_get_data_len(struct q
 	return data_len;
 }
 
+static bool qup_i2c_check_msg_len(struct i2c_msg *msg)
+{
+	return ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN));
+}
+
+static int qup_i2c_set_tags_smb(u16 addr, u8 *tags, struct qup_i2c_dev *qup,
+			struct i2c_msg *msg)
+{
+	int len = 0;
+
+	if (msg->len > 1) {
+		tags[len++] = QUP_TAG_V2_DATARD_STOP;
+		tags[len++] = qup_i2c_get_data_len(qup) - 1;
+	} else {
+		tags[len++] = QUP_TAG_V2_START;
+		tags[len++] = addr & 0xff;
+
+		if (msg->flags & I2C_M_TEN)
+			tags[len++] = addr >> 8;
+
+		tags[len++] = QUP_TAG_V2_DATARD;
+		/* Read 1 byte indicating the length of the SMBus message */
+		tags[len++] = 1;
+	}
+	return len;
+}
+
 static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,
 			    struct i2c_msg *msg,  int is_dma)
 {
@@ -534,6 +566,10 @@ static int qup_i2c_set_tags(u8 *tags, st
 
 	int last = (qup->blk.pos == (qup->blk.count - 1)) && (qup->is_last);
 
+	/* Handle tags for SMBus block read */
+	if (qup_i2c_check_msg_len(msg))
+		return qup_i2c_set_tags_smb(addr, tags, qup, msg);
+
 	if (qup->blk.pos == 0) {
 		tags[len++] = QUP_TAG_V2_START;
 		tags[len++] = addr & 0xff;
@@ -1056,9 +1092,17 @@ static int qup_i2c_read_fifo_v2(struct q
 				struct i2c_msg *msg)
 {
 	u32 val;
-	int idx, pos = 0, ret = 0, total;
+	int idx, pos = 0, ret = 0, total, msg_offset = 0;
 
+	/*
+	 * If the message length is already read in
+	 * the first byte of the buffer, account for
+	 * that by setting the offset
+	 */
+	if (qup_i2c_check_msg_len(msg) && (msg->len > 1))
+		msg_offset = 1;
 	total = qup_i2c_get_data_len(qup);
+	total -= msg_offset;
 
 	/* 2 extra bytes for read tags */
 	while (pos < (total + 2)) {
@@ -1078,8 +1122,8 @@ static int qup_i2c_read_fifo_v2(struct q
 
 			if (pos >= (total + 2))
 				goto out;
-
-			msg->buf[qup->pos++] = val & 0xff;
+			msg->buf[qup->pos + msg_offset] = val & 0xff;
+			qup->pos++;
 		}
 	}
 
@@ -1119,6 +1163,20 @@ static int qup_i2c_read_one_v2(struct qu
 			goto err;
 
 		qup->blk.pos++;
+
+		/* Handle SMBus block read length */
+		if (qup_i2c_check_msg_len(msg) && (msg->len == 1)) {
+			if (msg->buf[0] > I2C_SMBUS_BLOCK_MAX) {
+				ret = -EPROTO;
+				goto err;
+			}
+			msg->len += msg->buf[0];
+			qup->pos = 0;
+			qup_i2c_set_blk_data(qup, msg);
+			/* set tag length for block read */
+			qup->blk.tx_tag_len = 2;
+			qup_i2c_set_read_mode_v2(qup, msg->buf[0]);
+		}
 	} while (qup->blk.pos < qup->blk.count);
 
 err:
@@ -1204,6 +1262,11 @@ static int qup_i2c_xfer(struct i2c_adapt
 			goto out;
 		}
 
+		if (qup_i2c_check_msg_len(&msgs[idx])) {
+			ret = -EINVAL;
+			goto out;
+		}
+
 		if (msgs[idx].flags & I2C_M_RD)
 			ret = qup_i2c_read_one(qup, &msgs[idx]);
 		else
@@ -1358,14 +1421,13 @@ static void qup_i2c_disable_clocks(struc
 static int qup_i2c_probe(struct platform_device *pdev)
 {
 	static const int blk_sizes[] = {4, 16, 32};
-	struct device_node *node = pdev->dev.of_node;
 	struct qup_i2c_dev *qup;
 	unsigned long one_bit_t;
 	struct resource *res;
 	u32 io_mode, hw_ver, size;
 	int ret, fs_div, hs_div;
-	int src_clk_freq;
-	u32 clk_freq = 100000;
+	u32 src_clk_freq = DEFAULT_SRC_CLK;
+	u32 clk_freq = DEFAULT_CLK_FREQ;
 	int blocks;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
@@ -1376,7 +1438,11 @@ static int qup_i2c_probe(struct platform
 	init_completion(&qup->xfer);
 	platform_set_drvdata(pdev, qup);
 
-	of_property_read_u32(node, "clock-frequency", &clk_freq);
+	ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
+	if (ret) {
+		dev_notice(qup->dev, "using default clock-frequency %d",
+			DEFAULT_CLK_FREQ);
+	}
 
 	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
 		qup->adap.algo = &qup_i2c_algo;
@@ -1452,20 +1518,30 @@ nodma:
 		return qup->irq;
 	}
 
-	qup->clk = devm_clk_get(qup->dev, "core");
-	if (IS_ERR(qup->clk)) {
-		dev_err(qup->dev, "Could not get core clock\n");
-		return PTR_ERR(qup->clk);
-	}
+	if (has_acpi_companion(qup->dev)) {
+		ret = device_property_read_u32(qup->dev,
+				"src-clock-hz", &src_clk_freq);
+		if (ret) {
+			dev_notice(qup->dev, "using default src-clock-hz %d",
+				DEFAULT_SRC_CLK);
+		}
+		ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
+	} else {
+		qup->clk = devm_clk_get(qup->dev, "core");
+		if (IS_ERR(qup->clk)) {
+			dev_err(qup->dev, "Could not get core clock\n");
+			return PTR_ERR(qup->clk);
+		}
 
-	qup->pclk = devm_clk_get(qup->dev, "iface");
-	if (IS_ERR(qup->pclk)) {
-		dev_err(qup->dev, "Could not get iface clock\n");
-		return PTR_ERR(qup->pclk);
+		qup->pclk = devm_clk_get(qup->dev, "iface");
+		if (IS_ERR(qup->pclk)) {
+			dev_err(qup->dev, "Could not get iface clock\n");
+			return PTR_ERR(qup->pclk);
+		}
+		qup_i2c_enable_clocks(qup);
+		src_clk_freq = clk_get_rate(qup->clk);
 	}
 
-	qup_i2c_enable_clocks(qup);
-
 	/*
 	 * Bootloaders might leave a pending interrupt on certain QUP's,
 	 * so we reset the core before registering for interrupts.
@@ -1512,7 +1588,6 @@ nodma:
 	size = QUP_INPUT_FIFO_SIZE(io_mode);
 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
-	src_clk_freq = clk_get_rate(qup->clk);
 	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
 	hs_div = 3;
 	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
@@ -1631,6 +1706,14 @@ static const struct of_device_id qup_i2c
 };
 MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
 
+#if IS_ENABLED(CONFIG_ACPI)
+static const struct acpi_device_id qup_i2c_acpi_match[] = {
+	{ "QCOM8010"},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match);
+#endif
+
 static struct platform_driver qup_i2c_driver = {
 	.probe  = qup_i2c_probe,
 	.remove = qup_i2c_remove,
@@ -1638,6 +1721,7 @@ static struct platform_driver qup_i2c_dr
 		.name = "i2c_qup",
 		.pm = &qup_i2c_qup_pm_ops,
 		.of_match_table = qup_i2c_dt_match,
+		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-rcar.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-rcar.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-rcar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-rcar.c	2017-02-12 16:03:20.000000000 -0500
@@ -793,7 +793,6 @@ static const struct i2c_algorithm rcar_i
 };
 
 static const struct of_device_id rcar_i2c_dt_ids[] = {
-	{ .compatible = "renesas,i2c-rcar", .data = (void *)I2C_RCAR_GEN1 },
 	{ .compatible = "renesas,i2c-r8a7778", .data = (void *)I2C_RCAR_GEN1 },
 	{ .compatible = "renesas,i2c-r8a7779", .data = (void *)I2C_RCAR_GEN1 },
 	{ .compatible = "renesas,i2c-r8a7790", .data = (void *)I2C_RCAR_GEN2 },
@@ -803,6 +802,10 @@ static const struct of_device_id rcar_i2
 	{ .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 },
 	{ .compatible = "renesas,i2c-r8a7795", .data = (void *)I2C_RCAR_GEN3 },
 	{ .compatible = "renesas,i2c-r8a7796", .data = (void *)I2C_RCAR_GEN3 },
+	{ .compatible = "renesas,i2c-rcar", .data = (void *)I2C_RCAR_GEN1 },	/* Deprecated */
+	{ .compatible = "renesas,rcar-gen1-i2c", .data = (void *)I2C_RCAR_GEN1 },
+	{ .compatible = "renesas,rcar-gen2-i2c", .data = (void *)I2C_RCAR_GEN2 },
+	{ .compatible = "renesas,rcar-gen3-i2c", .data = (void *)I2C_RCAR_GEN3 },
 	{},
 };
 MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-sh_mobile.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-sh_mobile.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-sh_mobile.c	2017-02-12 16:03:20.000000000 -0500
@@ -827,7 +827,6 @@ static const struct sh_mobile_dt_config
 };
 
 static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
-	{ .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
 	{ .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config },
 	{ .compatible = "renesas,iic-r8a7790", .data = &fast_clock_dt_config },
@@ -835,8 +834,11 @@ static const struct of_device_id sh_mobi
 	{ .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-r8a7794", .data = &fast_clock_dt_config },
+	{ .compatible = "renesas,rcar-gen2-iic", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config },
+	{ .compatible = "renesas,rcar-gen3-iic", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config },
+	{ .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
 	{},
 };
 MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-uniphier.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-uniphier.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-uniphier.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-uniphier.c	2017-02-12 16:03:20.000000000 -0500
@@ -373,7 +373,7 @@ static int uniphier_i2c_probe(struct pla
 	if (!clk_rate) {
 		dev_err(dev, "input clock rate should not be zero\n");
 		ret = -EINVAL;
-		goto err;
+		goto disable_clk;
 	}
 
 	init_completion(&priv->comp);
@@ -392,11 +392,11 @@ static int uniphier_i2c_probe(struct pla
 			       priv);
 	if (ret) {
 		dev_err(dev, "failed to request irq %d\n", irq);
-		goto err;
+		goto disable_clk;
 	}
 
 	ret = i2c_add_adapter(&priv->adap);
-err:
+disable_clk:
 	if (ret)
 		clk_disable_unprepare(priv->clk);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-uniphier-f.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-uniphier-f.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-uniphier-f.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-uniphier-f.c	2017-02-12 16:03:20.000000000 -0500
@@ -528,7 +528,7 @@ static int uniphier_fi2c_probe(struct pl
 	if (!clk_rate) {
 		dev_err(dev, "input clock rate should not be zero\n");
 		ret = -EINVAL;
-		goto err;
+		goto disable_clk;
 	}
 
 	init_completion(&priv->comp);
@@ -547,11 +547,11 @@ static int uniphier_fi2c_probe(struct pl
 			       pdev->name, priv);
 	if (ret) {
 		dev_err(dev, "failed to request irq %d\n", irq);
-		goto err;
+		goto disable_clk;
 	}
 
 	ret = i2c_add_adapter(&priv->adap);
-err:
+disable_clk:
 	if (ret)
 		clk_disable_unprepare(priv->clk);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-viperboard.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-viperboard.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-viperboard.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-viperboard.c	2017-02-12 16:03:20.000000000 -0500
@@ -354,7 +354,7 @@ static const struct i2c_algorithm vprbrd
 	.functionality	= vprbrd_i2c_func,
 };
 
-static struct i2c_adapter_quirks vprbrd_quirks = {
+static const struct i2c_adapter_quirks vprbrd_quirks = {
 	.max_read_len = 2048,
 	.max_write_len = 2048,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-xgene-slimpro.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-xgene-slimpro.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-xgene-slimpro.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-xgene-slimpro.c	2017-02-12 16:03:20.000000000 -0500
@@ -415,6 +415,7 @@ static int xgene_slimpro_i2c_probe(struc
 	adapter->algo = &xgene_slimpro_i2c_algorithm;
 	adapter->class = I2C_CLASS_HWMON;
 	adapter->dev.parent = &pdev->dev;
+	adapter->dev.of_node = pdev->dev.of_node;
 	i2c_set_adapdata(adapter, ctx);
 	rc = i2c_add_adapter(adapter);
 	if (rc) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/i2c-xlp9xx.c linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-xlp9xx.c
--- linux-libre-4.9-gnu/drivers/i2c/busses/i2c-xlp9xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/i2c-xlp9xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -393,6 +393,7 @@ static int xlp9xx_i2c_probe(struct platf
 	init_completion(&priv->msg_complete);
 	priv->adapter.dev.parent = &pdev->dev;
 	priv->adapter.algo = &xlp9xx_i2c_algo;
+	ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&pdev->dev));
 	priv->adapter.dev.of_node = pdev->dev.of_node;
 	priv->dev = &pdev->dev;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/Kconfig linux-libre-4.10-rc8-gnu/drivers/i2c/busses/Kconfig
--- linux-libre-4.9-gnu/drivers/i2c/busses/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -426,7 +426,7 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
 
 config I2C_CADENCE
 	tristate "Cadence I2C Controller"
-	depends on ARCH_ZYNQ || ARM64
+	depends on ARCH_ZYNQ || ARM64 || XTENSA
 	help
 	  Say yes here to select Cadence I2C Host Controller. This controller is
 	  e.g. used by Xilinx Zynq.
@@ -597,6 +597,16 @@ config I2C_IMX
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-imx.
 
+config I2C_IMX_LPI2C
+	tristate "IMX Low Power I2C interface"
+	depends on ARCH_MXC || COMPILE_TEST
+	help
+          Say Y here if you want to use the Low Power IIC bus controller
+          on the Freescale i.MX processors.
+
+          This driver can also be built as a module. If so, the module
+          will be called i2c-imx-lpi2c.
+
 config I2C_IOP3XX
 	tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
 	depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
@@ -763,7 +773,7 @@ config I2C_PUV3
 
 config I2C_PXA
 	tristate "Intel PXA2XX I2C adapter"
-	depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
+	depends on ARCH_PXA || ARCH_MMP || ARCH_MVEBU || (X86_32 && PCI && OF)
 	help
 	  If you have devices in the PXA I2C bus, say yes to this option.
 	  This driver can also be built as a module.  If so, the module
@@ -1150,6 +1160,17 @@ config I2C_ELEKTOR
 	  This support is also available as a module.  If so, the module
 	  will be called i2c-elektor.
 
+config I2C_MLXCPLD
+	tristate "Mellanox I2C driver"
+	depends on X86_64
+	help
+	  This exposes the Mellanox platform I2C busses to the linux I2C layer
+	  for X86 based systems.
+	  Controller is implemented as CPLD logic.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called as i2c-mlxcpld.
+
 config I2C_PCA_ISA
 	tristate "PCA9564/PCA9665 on an ISA bus"
 	depends on ISA
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/busses/Makefile linux-libre-4.10-rc8-gnu/drivers/i2c/busses/Makefile
--- linux-libre-4.9-gnu/drivers/i2c/busses/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/busses/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -56,6 +56,7 @@ obj-$(CONFIG_I2C_HIX5HD2)	+= i2c-hix5hd2
 obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IMG)		+= i2c-img-scb.o
 obj-$(CONFIG_I2C_IMX)		+= i2c-imx.o
+obj-$(CONFIG_I2C_IMX_LPI2C)	+= i2c-imx-lpi2c.o
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_JZ4780)	+= i2c-jz4780.o
 obj-$(CONFIG_I2C_KEMPLD)	+= i2c-kempld.o
@@ -116,6 +117,7 @@ obj-$(CONFIG_I2C_BCM_KONA)	+= i2c-bcm-ko
 obj-$(CONFIG_I2C_BRCMSTB)	+= i2c-brcmstb.o
 obj-$(CONFIG_I2C_CROS_EC_TUNNEL)	+= i2c-cros-ec-tunnel.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
+obj-$(CONFIG_I2C_MLXCPLD)	+= i2c-mlxcpld.o
 obj-$(CONFIG_I2C_OPAL)		+= i2c-opal.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/i2c-core.c linux-libre-4.10-rc8-gnu/drivers/i2c/i2c-core.c
--- linux-libre-4.9-gnu/drivers/i2c/i2c-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/i2c-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #define pr_fmt(fmt) "i2c-core: " fmt
 
 #include <dt-bindings/i2c/i2c.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/acpi.h>
 #include <linux/clk/clk-conf.h>
 #include <linux/completion.h>
@@ -65,6 +65,9 @@
 #define I2C_ADDR_OFFSET_TEN_BIT	0xa000
 #define I2C_ADDR_OFFSET_SLAVE	0x1000
 
+#define I2C_ADDR_7BITS_MAX	0x77
+#define I2C_ADDR_7BITS_COUNT	(I2C_ADDR_7BITS_MAX + 1)
+
 /* core_lock protects i2c_adapter_idr, and guarantees
    that device detection, deletion of detected devices, and attach_adapter
    calls are serialized */
@@ -77,9 +80,10 @@ static int i2c_detect(struct i2c_adapter
 static struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE;
 static bool is_registered;
 
-void i2c_transfer_trace_reg(void)
+int i2c_transfer_trace_reg(void)
 {
 	static_key_slow_inc(&i2c_trace_msg);
+	return 0;
 }
 
 void i2c_transfer_trace_unreg(void)
@@ -676,9 +680,12 @@ static inline int i2c_acpi_install_space
 
 /* ------------------------------------------------------------------------- */
 
-static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
 						const struct i2c_client *client)
 {
+	if (!(id && client))
+		return NULL;
+
 	while (id->name[0]) {
 		if (strcmp(client->name, id->name) == 0)
 			return id;
@@ -686,17 +693,16 @@ static const struct i2c_device_id *i2c_m
 	}
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(i2c_match_id);
 
 static int i2c_device_match(struct device *dev, struct device_driver *drv)
 {
 	struct i2c_client	*client = i2c_verify_client(dev);
 	struct i2c_driver	*driver;
 
-	if (!client)
-		return 0;
 
 	/* Attempt an OF style match */
-	if (of_driver_match_device(dev, drv))
+	if (i2c_of_match_device(drv->of_match_table, client))
 		return 1;
 
 	/* Then ACPI style match */
@@ -704,9 +710,10 @@ static int i2c_device_match(struct devic
 		return 1;
 
 	driver = to_i2c_driver(drv);
-	/* match on an id table if there is one */
-	if (driver->id_table)
-		return i2c_match_id(driver->id_table, client) != NULL;
+
+	/* Finally an I2C match */
+	if (i2c_match_id(driver->id_table, client))
+		return 1;
 
 	return 0;
 }
@@ -893,6 +900,25 @@ static void i2c_init_recovery(struct i2c
 	adap->bus_recovery_info = NULL;
 }
 
+static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client)
+{
+	struct i2c_adapter *adap = client->adapter;
+	unsigned int irq;
+
+	if (!adap->host_notify_domain)
+		return -ENXIO;
+
+	if (client->flags & I2C_CLIENT_TEN)
+		return -EINVAL;
+
+	irq = irq_find_mapping(adap->host_notify_domain, client->addr);
+	if (!irq)
+		irq = irq_create_mapping(adap->host_notify_domain,
+					 client->addr);
+
+	return irq > 0 ? irq : -ENXIO;
+}
+
 static int i2c_device_probe(struct device *dev)
 {
 	struct i2c_client	*client = i2c_verify_client(dev);
@@ -905,7 +931,10 @@ static int i2c_device_probe(struct devic
 	if (!client->irq) {
 		int irq = -ENOENT;
 
-		if (dev->of_node) {
+		if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
+			dev_dbg(dev, "Using Host Notify IRQ\n");
+			irq = i2c_smbus_host_notify_to_irq(client);
+		} else if (dev->of_node) {
 			irq = of_irq_get_byname(dev->of_node, "irq");
 			if (irq == -EINVAL || irq == -ENODATA)
 				irq = of_irq_get(dev->of_node, 0);
@@ -914,6 +943,7 @@ static int i2c_device_probe(struct devic
 		}
 		if (irq == -EPROBE_DEFER)
 			return irq;
+
 		if (irq < 0)
 			irq = 0;
 
@@ -921,7 +951,13 @@ static int i2c_device_probe(struct devic
 	}
 
 	driver = to_i2c_driver(dev->driver);
-	if (!driver->probe || !driver->id_table)
+
+	/*
+	 * An I2C ID table is not mandatory, if and only if, a suitable Device
+	 * Tree match table entry is supplied for the probing device.
+	 */
+	if (!driver->id_table &&
+	    !i2c_of_match_device(dev->driver->of_match_table, client))
 		return -ENODEV;
 
 	if (client->flags & I2C_CLIENT_WAKE) {
@@ -956,7 +992,18 @@ static int i2c_device_probe(struct devic
 	if (status == -EPROBE_DEFER)
 		goto err_clear_wakeup_irq;
 
-	status = driver->probe(client, i2c_match_id(driver->id_table, client));
+	/*
+	 * When there are no more users of probe(),
+	 * rename probe_new to probe.
+	 */
+	if (driver->probe_new)
+		status = driver->probe_new(client);
+	else if (driver->probe)
+		status = driver->probe(client,
+				       i2c_match_id(driver->id_table, client));
+	else
+		status = -EINVAL;
+
 	if (status)
 		goto err_detach_pm_domain;
 
@@ -1657,7 +1704,7 @@ static struct i2c_client *of_i2c_registe
 
 	if (i2c_check_addr_validity(addr, info.flags)) {
 		dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
-			info.addr, node->full_name);
+			addr, node->full_name);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -1665,6 +1712,9 @@ static struct i2c_client *of_i2c_registe
 	info.of_node = of_node_get(node);
 	info.archdata = &dev_ad;
 
+	if (of_property_read_bool(node, "host-notify"))
+		info.flags |= I2C_CLIENT_HOST_NOTIFY;
+
 	if (of_get_property(node, "wakeup-source", NULL))
 		info.flags |= I2C_CLIENT_WAKE;
 
@@ -1767,6 +1817,52 @@ struct i2c_adapter *of_get_i2c_adapter_b
 	return adapter;
 }
 EXPORT_SYMBOL(of_get_i2c_adapter_by_node);
+
+static const struct of_device_id*
+i2c_of_match_device_sysfs(const struct of_device_id *matches,
+				  struct i2c_client *client)
+{
+	const char *name;
+
+	for (; matches->compatible[0]; matches++) {
+		/*
+		 * Adding devices through the i2c sysfs interface provides us
+		 * a string to match which may be compatible with the device
+		 * tree compatible strings, however with no actual of_node the
+		 * of_match_device() will not match
+		 */
+		if (sysfs_streq(client->name, matches->compatible))
+			return matches;
+
+		name = strchr(matches->compatible, ',');
+		if (!name)
+			name = matches->compatible;
+		else
+			name++;
+
+		if (sysfs_streq(client->name, name))
+			return matches;
+	}
+
+	return NULL;
+}
+
+const struct of_device_id
+*i2c_of_match_device(const struct of_device_id *matches,
+		     struct i2c_client *client)
+{
+	const struct of_device_id *match;
+
+	if (!(client && matches))
+		return NULL;
+
+	match = of_match_device(matches, &client->dev);
+	if (match)
+		return match;
+
+	return i2c_of_match_device_sysfs(matches, client);
+}
+EXPORT_SYMBOL_GPL(i2c_of_match_device);
 #else
 static void of_i2c_register_devices(struct i2c_adapter *adap) { }
 #endif /* CONFIG_OF */
@@ -1800,6 +1896,79 @@ static const struct i2c_lock_operations
 	.unlock_bus =  i2c_adapter_unlock_bus,
 };
 
+static void i2c_host_notify_irq_teardown(struct i2c_adapter *adap)
+{
+	struct irq_domain *domain = adap->host_notify_domain;
+	irq_hw_number_t hwirq;
+
+	if (!domain)
+		return;
+
+	for (hwirq = 0 ; hwirq < I2C_ADDR_7BITS_COUNT ; hwirq++)
+		irq_dispose_mapping(irq_find_mapping(domain, hwirq));
+
+	irq_domain_remove(domain);
+	adap->host_notify_domain = NULL;
+}
+
+static int i2c_host_notify_irq_map(struct irq_domain *h,
+					  unsigned int virq,
+					  irq_hw_number_t hw_irq_num)
+{
+	irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops i2c_host_notify_irq_ops = {
+	.map = i2c_host_notify_irq_map,
+};
+
+static int i2c_setup_host_notify_irq_domain(struct i2c_adapter *adap)
+{
+	struct irq_domain *domain;
+
+	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_HOST_NOTIFY))
+		return 0;
+
+	domain = irq_domain_create_linear(adap->dev.fwnode,
+					  I2C_ADDR_7BITS_COUNT,
+					  &i2c_host_notify_irq_ops, adap);
+	if (!domain)
+		return -ENOMEM;
+
+	adap->host_notify_domain = domain;
+
+	return 0;
+}
+
+/**
+ * i2c_handle_smbus_host_notify - Forward a Host Notify event to the correct
+ * I2C client.
+ * @adap: the adapter
+ * @addr: the I2C address of the notifying device
+ * Context: can't sleep
+ *
+ * Helper function to be called from an I2C bus driver's interrupt
+ * handler. It will schedule the Host Notify IRQ.
+ */
+int i2c_handle_smbus_host_notify(struct i2c_adapter *adap, unsigned short addr)
+{
+	int irq;
+
+	if (!adap)
+		return -EINVAL;
+
+	irq = irq_find_mapping(adap->host_notify_domain, addr);
+	if (irq <= 0)
+		return -ENXIO;
+
+	generic_handle_irq(irq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
+
 static int i2c_register_adapter(struct i2c_adapter *adap)
 {
 	int res = -EINVAL;
@@ -1831,6 +2000,14 @@ static int i2c_register_adapter(struct i
 	if (adap->timeout == 0)
 		adap->timeout = HZ;
 
+	/* register soft irqs for Host Notify */
+	res = i2c_setup_host_notify_irq_domain(adap);
+	if (res) {
+		pr_err("adapter '%s': can't create Host Notify IRQs (%d)\n",
+		       adap->name, res);
+		goto out_list;
+	}
+
 	dev_set_name(&adap->dev, "i2c-%d", adap->nr);
 	adap->dev.bus = &i2c_bus_type;
 	adap->dev.type = &i2c_adapter_type;
@@ -2068,6 +2245,8 @@ void i2c_del_adapter(struct i2c_adapter
 
 	pm_runtime_disable(&adap->dev);
 
+	i2c_host_notify_irq_teardown(adap);
+
 	/* wait until all references to the device are gone
 	 *
 	 * FIXME: This is old code and should ideally be replaced by an
@@ -3453,7 +3632,7 @@ int i2c_slave_register(struct i2c_client
 	int ret;
 
 	if (!client || !slave_cb) {
-		WARN(1, "insufficent data\n");
+		WARN(1, "insufficient data\n");
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/i2c-dev.c linux-libre-4.10-rc8-gnu/drivers/i2c/i2c-dev.c
--- linux-libre-4.9-gnu/drivers/i2c/i2c-dev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/i2c-dev.c	2017-02-12 16:03:20.000000000 -0500
@@ -331,7 +331,7 @@ static noinline int i2cdev_ioctl_smbus(s
 		unsigned long arg)
 {
 	struct i2c_smbus_ioctl_data data_arg;
-	union i2c_smbus_data temp;
+	union i2c_smbus_data temp = {};
 	int datasize, res;
 
 	if (copy_from_user(&data_arg,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/i2c-smbus.c linux-libre-4.10-rc8-gnu/drivers/i2c/i2c-smbus.c
--- linux-libre-4.9-gnu/drivers/i2c/i2c-smbus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/i2c-smbus.c	2017-02-12 16:03:20.000000000 -0500
@@ -241,108 +241,6 @@ int i2c_handle_smbus_alert(struct i2c_cl
 }
 EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert);
 
-static void smbus_host_notify_work(struct work_struct *work)
-{
-	struct alert_data alert;
-	struct i2c_adapter *adapter;
-	unsigned long flags;
-	u16 payload;
-	u8 addr;
-	struct smbus_host_notify *data;
-
-	data = container_of(work, struct smbus_host_notify, work);
-
-	spin_lock_irqsave(&data->lock, flags);
-	payload = data->payload;
-	addr = data->addr;
-	adapter = data->adapter;
-
-	/* clear the pending bit and release the spinlock */
-	data->pending = false;
-	spin_unlock_irqrestore(&data->lock, flags);
-
-	if (!adapter || !addr)
-		return;
-
-	alert.type = I2C_PROTOCOL_SMBUS_HOST_NOTIFY;
-	alert.addr = addr;
-	alert.data = payload;
-
-	device_for_each_child(&adapter->dev, &alert, smbus_do_alert);
-}
-
-/**
- * i2c_setup_smbus_host_notify - Allocate a new smbus_host_notify for the given
- * I2C adapter.
- * @adapter: the adapter we want to associate a Host Notify function
- *
- * Returns a struct smbus_host_notify pointer on success, and NULL on failure.
- * The resulting smbus_host_notify must not be freed afterwards, it is a
- * managed resource already.
- */
-struct smbus_host_notify *i2c_setup_smbus_host_notify(struct i2c_adapter *adap)
-{
-	struct smbus_host_notify *host_notify;
-
-	host_notify = devm_kzalloc(&adap->dev, sizeof(struct smbus_host_notify),
-				   GFP_KERNEL);
-	if (!host_notify)
-		return NULL;
-
-	host_notify->adapter = adap;
-
-	spin_lock_init(&host_notify->lock);
-	INIT_WORK(&host_notify->work, smbus_host_notify_work);
-
-	return host_notify;
-}
-EXPORT_SYMBOL_GPL(i2c_setup_smbus_host_notify);
-
-/**
- * i2c_handle_smbus_host_notify - Forward a Host Notify event to the correct
- * I2C client.
- * @host_notify: the struct host_notify attached to the relevant adapter
- * @addr: the I2C address of the notifying device
- * @data: the payload of the notification
- * Context: can't sleep
- *
- * Helper function to be called from an I2C bus driver's interrupt
- * handler. It will schedule the Host Notify work, in turn calling the
- * corresponding I2C device driver's alert function.
- *
- * host_notify should be a valid pointer previously returned by
- * i2c_setup_smbus_host_notify().
- */
-int i2c_handle_smbus_host_notify(struct smbus_host_notify *host_notify,
-				 unsigned short addr, unsigned int data)
-{
-	unsigned long flags;
-	struct i2c_adapter *adapter;
-
-	if (!host_notify || !host_notify->adapter)
-		return -EINVAL;
-
-	adapter = host_notify->adapter;
-
-	spin_lock_irqsave(&host_notify->lock, flags);
-
-	if (host_notify->pending) {
-		spin_unlock_irqrestore(&host_notify->lock, flags);
-		dev_warn(&adapter->dev, "Host Notify already scheduled.\n");
-		return -EBUSY;
-	}
-
-	host_notify->payload = data;
-	host_notify->addr = addr;
-
-	/* Mark that there is a pending notification and release the lock */
-	host_notify->pending = true;
-	spin_unlock_irqrestore(&host_notify->lock, flags);
-
-	return schedule_work(&host_notify->work);
-}
-EXPORT_SYMBOL_GPL(i2c_handle_smbus_host_notify);
-
 module_i2c_driver(smbalert_driver);
 
 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/Kconfig linux-libre-4.10-rc8-gnu/drivers/i2c/Kconfig
--- linux-libre-4.9-gnu/drivers/i2c/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@ menu "I2C support"
 config I2C
 	tristate "I2C support"
 	select RT_MUTEXES
+	select IRQ_DOMAIN
 	---help---
 	  I2C (pronounce: I-squared-C) is a slow serial bus protocol used in
 	  many micro controller applications and developed by Philips.  SMBus,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/muxes/i2c-mux-gpio.c linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/i2c-mux-gpio.c
--- linux-libre-4.9-gnu/drivers/i2c/muxes/i2c-mux-gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/i2c-mux-gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@
 struct gpiomux {
 	struct i2c_mux_gpio_platform_data data;
 	unsigned gpio_base;
+	struct gpio_desc **gpios;
+	int *values;
 };
 
 static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
@@ -28,8 +30,10 @@ static void i2c_mux_gpio_set(const struc
 	int i;
 
 	for (i = 0; i < mux->data.n_gpios; i++)
-		gpio_set_value_cansleep(mux->gpio_base + mux->data.gpios[i],
-					val & (1 << i));
+		mux->values[i] = (val >> i) & 1;
+
+	gpiod_set_array_value_cansleep(mux->data.n_gpios,
+				       mux->gpios, mux->values);
 }
 
 static int i2c_mux_gpio_select(struct i2c_mux_core *muxc, u32 chan)
@@ -176,12 +180,16 @@ static int i2c_mux_gpio_probe(struct pla
 	if (!parent)
 		return -EPROBE_DEFER;
 
-	muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
+	muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values,
+			     mux->data.n_gpios * sizeof(*mux->gpios) +
+			     mux->data.n_gpios * sizeof(*mux->values), 0,
 			     i2c_mux_gpio_select, NULL);
 	if (!muxc) {
 		ret = -ENOMEM;
 		goto alloc_failed;
 	}
+	mux->gpios = muxc->priv;
+	mux->values = (int *)(mux->gpios + mux->data.n_gpios);
 	muxc->priv = mux;
 
 	platform_set_drvdata(pdev, muxc);
@@ -219,10 +227,12 @@ static int i2c_mux_gpio_probe(struct pla
 			goto err_request_gpio;
 		}
 
+		gpio_desc = gpio_to_desc(gpio_base + mux->data.gpios[i]);
+		mux->gpios[i] = gpio_desc;
+
 		if (!muxc->mux_locked)
 			continue;
 
-		gpio_desc = gpio_to_desc(gpio_base + mux->data.gpios[i]);
 		gpio_dev = &gpio_desc->gdev->dev;
 		muxc->mux_locked = i2c_root_adapter(gpio_dev) == root;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/muxes/i2c-mux-mlxcpld.c linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/i2c-mux-mlxcpld.c
--- linux-libre-4.9-gnu/drivers/i2c/muxes/i2c-mux-mlxcpld.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/i2c-mux-mlxcpld.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,222 @@
+/*
+ * drivers/i2c/muxes/i2c-mux-mlxcpld.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Michael Shych <michaels@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/i2c/mlxcpld.h>
+
+#define CPLD_MUX_MAX_NCHANS	8
+
+/* mlxcpld_mux - mux control structure:
+ * @last_chan - last register value
+ * @client - I2C device client
+ */
+struct mlxcpld_mux {
+	u8 last_chan;
+	struct i2c_client *client;
+};
+
+/* MUX logic description.
+ * Driver can support different mux control logic, according to CPLD
+ * implementation.
+ *
+ * Connectivity schema.
+ *
+ * i2c-mlxcpld                                 Digital               Analog
+ * driver
+ * *--------*                                 * -> mux1 (virt bus2) -> mux -> |
+ * | I2CLPC | i2c physical                    * -> mux2 (virt bus3) -> mux -> |
+ * | bridge | bus 1                 *---------*                               |
+ * | logic  |---------------------> * mux reg *                               |
+ * | in CPLD|                       *---------*                               |
+ * *--------*   i2c-mux-mlxpcld          ^    * -> muxn (virt busn) -> mux -> |
+ *     |        driver                   |                                    |
+ *     |        *---------------*        |                              Devices
+ *     |        * CPLD (i2c bus)* select |
+ *     |        * registers for *--------*
+ *     |        * mux selection * deselect
+ *     |        *---------------*
+ *     |                 |
+ * <-------->     <----------->
+ * i2c cntrl      Board cntrl reg
+ * reg space      space (mux select,
+ *                IO, LED, WD, info)
+ *
+ */
+
+static const struct i2c_device_id mlxcpld_mux_id[] = {
+	{ "mlxcpld_mux_module", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mlxcpld_mux_id);
+
+/* Write to mux register. Don't use i2c_transfer() and i2c_smbus_xfer()
+ * for this as they will try to lock adapter a second time.
+ */
+static int mlxcpld_mux_reg_write(struct i2c_adapter *adap,
+				 struct i2c_client *client, u8 val)
+{
+	struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
+	int ret = -ENODEV;
+
+	if (adap->algo->master_xfer) {
+		struct i2c_msg msg;
+		u8 msgbuf[] = {pdata->sel_reg_addr, val};
+
+		msg.addr = client->addr;
+		msg.flags = 0;
+		msg.len = 2;
+		msg.buf = msgbuf;
+		ret = __i2c_transfer(adap, &msg, 1);
+
+		if (ret >= 0 && ret != 1)
+			ret = -EREMOTEIO;
+	} else if (adap->algo->smbus_xfer) {
+		union i2c_smbus_data data;
+
+		data.byte = val;
+		ret = adap->algo->smbus_xfer(adap, client->addr,
+					     client->flags, I2C_SMBUS_WRITE,
+					     pdata->sel_reg_addr,
+					     I2C_SMBUS_BYTE_DATA, &data);
+	}
+
+	return ret;
+}
+
+static int mlxcpld_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+	struct mlxcpld_mux *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+	u8 regval = chan + 1;
+	int err = 0;
+
+	/* Only select the channel if its different from the last channel */
+	if (data->last_chan != regval) {
+		err = mlxcpld_mux_reg_write(muxc->parent, client, regval);
+		data->last_chan = err < 0 ? 0 : regval;
+	}
+
+	return err;
+}
+
+static int mlxcpld_mux_deselect(struct i2c_mux_core *muxc, u32 chan)
+{
+	struct mlxcpld_mux *data = i2c_mux_priv(muxc);
+	struct i2c_client *client = data->client;
+
+	/* Deselect active channel */
+	data->last_chan = 0;
+
+	return mlxcpld_mux_reg_write(muxc->parent, client, data->last_chan);
+}
+
+/* Probe/reomove functions */
+static int mlxcpld_mux_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
+	struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&client->dev);
+	struct i2c_mux_core *muxc;
+	int num, force;
+	struct mlxcpld_mux *data;
+	int err;
+
+	if (!pdata)
+		return -EINVAL;
+
+	if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -ENODEV;
+
+	muxc = i2c_mux_alloc(adap, &client->dev, CPLD_MUX_MAX_NCHANS,
+			     sizeof(*data), 0, mlxcpld_mux_select_chan,
+			     mlxcpld_mux_deselect);
+	if (!muxc)
+		return -ENOMEM;
+
+	data = i2c_mux_priv(muxc);
+	i2c_set_clientdata(client, muxc);
+	data->client = client;
+	data->last_chan = 0; /* force the first selection */
+
+	/* Create an adapter for each channel. */
+	for (num = 0; num < CPLD_MUX_MAX_NCHANS; num++) {
+		if (num >= pdata->num_adaps)
+			/* discard unconfigured channels */
+			break;
+
+		force = pdata->adap_ids[num];
+
+		err = i2c_mux_add_adapter(muxc, force, num, 0);
+		if (err)
+			goto virt_reg_failed;
+	}
+
+	return 0;
+
+virt_reg_failed:
+	i2c_mux_del_adapters(muxc);
+	return err;
+}
+
+static int mlxcpld_mux_remove(struct i2c_client *client)
+{
+	struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+
+	i2c_mux_del_adapters(muxc);
+	return 0;
+}
+
+static struct i2c_driver mlxcpld_mux_driver = {
+	.driver		= {
+		.name	= "mlxcpld-mux",
+	},
+	.probe		= mlxcpld_mux_probe,
+	.remove		= mlxcpld_mux_remove,
+	.id_table	= mlxcpld_mux_id,
+};
+
+module_i2c_driver(mlxcpld_mux_driver);
+
+MODULE_AUTHOR("Michael Shych (michaels@mellanox.com)");
+MODULE_DESCRIPTION("Mellanox I2C-CPLD-MUX driver");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:i2c-mux-mlxcpld");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c
--- linux-libre-4.9-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/i2c-mux-pca954x.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/acpi.h>
 #include <linux/device.h>
 #include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
@@ -120,6 +121,21 @@ static const struct i2c_device_id pca954
 };
 MODULE_DEVICE_TABLE(i2c, pca954x_id);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id pca954x_acpi_ids[] = {
+	{ .id = "PCA9540", .driver_data = pca_9540 },
+	{ .id = "PCA9542", .driver_data = pca_9540 },
+	{ .id = "PCA9543", .driver_data = pca_9543 },
+	{ .id = "PCA9544", .driver_data = pca_9544 },
+	{ .id = "PCA9545", .driver_data = pca_9545 },
+	{ .id = "PCA9546", .driver_data = pca_9545 },
+	{ .id = "PCA9547", .driver_data = pca_9547 },
+	{ .id = "PCA9548", .driver_data = pca_9548 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, pca954x_acpi_ids);
+#endif
+
 #ifdef CONFIG_OF
 static const struct of_device_id pca954x_of_match[] = {
 	{ .compatible = "nxp,pca9540", .data = &chips[pca_9540] },
@@ -151,6 +167,9 @@ static int pca954x_reg_write(struct i2c_
 		buf[0] = val;
 		msg.buf = buf;
 		ret = __i2c_transfer(adap, &msg, 1);
+
+		if (ret >= 0 && ret != 1)
+			ret = -EREMOTEIO;
 	} else {
 		union i2c_smbus_data data;
 		ret = adap->algo->smbus_xfer(adap, client->addr,
@@ -179,7 +198,7 @@ static int pca954x_select_chan(struct i2
 	/* Only select the channel if its different from the last channel */
 	if (data->last_chan != regval) {
 		ret = pca954x_reg_write(muxc->parent, client, regval);
-		data->last_chan = ret ? 0 : regval;
+		data->last_chan = ret < 0 ? 0 : regval;
 	}
 
 	return ret;
@@ -245,8 +264,17 @@ static int pca954x_probe(struct i2c_clie
 	match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
 	if (match)
 		data->chip = of_device_get_match_data(&client->dev);
-	else
+	else if (id)
 		data->chip = &chips[id->driver_data];
+	else {
+		const struct acpi_device_id *acpi_id;
+
+		acpi_id = acpi_match_device(ACPI_PTR(pca954x_acpi_ids),
+						&client->dev);
+		if (!acpi_id)
+			return -ENODEV;
+		data->chip = &chips[acpi_id->driver_data];
+	}
 
 	data->last_chan = 0;		   /* force the first selection */
 
@@ -321,6 +349,7 @@ static struct i2c_driver pca954x_driver
 		.name	= "pca954x",
 		.pm	= &pca954x_pm,
 		.of_match_table = of_match_ptr(pca954x_of_match),
+		.acpi_match_table = ACPI_PTR(pca954x_acpi_ids),
 	},
 	.probe		= pca954x_probe,
 	.remove		= pca954x_remove,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/muxes/Kconfig linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/Kconfig
--- linux-libre-4.9-gnu/drivers/i2c/muxes/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -82,4 +82,15 @@ config I2C_DEMUX_PINCTRL
 	  demultiplexer that uses the pinctrl subsystem. This is useful if you
 	  want to change the I2C master at run-time depending on features.
 
+config I2C_MUX_MLXCPLD
+        tristate "Mellanox CPLD based I2C multiplexer"
+        help
+          If you say yes to this option, support will be included for a
+          CPLD based I2C multiplexer. This driver provides access to
+          I2C busses connected through a MUX, which is controlled
+          by a CPLD register.
+
+          This driver can also be built as a module.  If so, the module
+          will be called i2c-mux-mlxcpld.
+
 endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/i2c/muxes/Makefile linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/Makefile
--- linux-libre-4.9-gnu/drivers/i2c/muxes/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/i2c/muxes/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,7 @@ obj-$(CONFIG_I2C_ARB_GPIO_CHALLENGE)	+=
 obj-$(CONFIG_I2C_DEMUX_PINCTRL)		+= i2c-demux-pinctrl.o
 
 obj-$(CONFIG_I2C_MUX_GPIO)	+= i2c-mux-gpio.o
+obj-$(CONFIG_I2C_MUX_MLXCPLD)	+= i2c-mux-mlxcpld.o
 obj-$(CONFIG_I2C_MUX_PCA9541)	+= i2c-mux-pca9541.o
 obj-$(CONFIG_I2C_MUX_PCA954x)	+= i2c-mux-pca954x.o
 obj-$(CONFIG_I2C_MUX_PINCTRL)	+= i2c-mux-pinctrl.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/hpt366.c linux-libre-4.10-rc8-gnu/drivers/ide/hpt366.c
--- linux-libre-4.9-gnu/drivers/ide/hpt366.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/hpt366.c	2017-02-12 16:03:20.000000000 -0500
@@ -130,7 +130,7 @@
 #include <linux/ide.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #define DRV_NAME "hpt366"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-atapi.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-atapi.c
--- linux-libre-4.9-gnu/drivers/ide/ide-atapi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-atapi.c	2017-02-12 16:03:20.000000000 -0500
@@ -211,7 +211,7 @@ void ide_prep_sense(ide_drive_t *drive,
 	sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
 	sense_rq->cmd[4] = cmd_len;
 	sense_rq->cmd_type = REQ_TYPE_ATA_SENSE;
-	sense_rq->cmd_flags |= REQ_PREEMPT;
+	sense_rq->rq_flags |= RQF_PREEMPT;
 
 	if (drive->media == ide_tape)
 		sense_rq->cmd[13] = REQ_IDETAPE_PC1;
@@ -295,7 +295,7 @@ int ide_cd_expiry(ide_drive_t *drive)
 		wait = ATAPI_WAIT_PC;
 		break;
 	default:
-		if (!(rq->cmd_flags & REQ_QUIET))
+		if (!(rq->rq_flags & RQF_QUIET))
 			printk(KERN_INFO PFX "cmd 0x%x timed out\n",
 					 rq->cmd[0]);
 		wait = 0;
@@ -375,7 +375,7 @@ int ide_check_ireason(ide_drive_t *drive
 	}
 
 	if (dev_is_idecd(drive) && rq->cmd_type == REQ_TYPE_ATA_PC)
-		rq->cmd_flags |= REQ_FAILED;
+		rq->rq_flags |= RQF_FAILED;
 
 	return 1;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-cd.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-cd.c
--- linux-libre-4.9-gnu/drivers/ide/ide-cd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-cd.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,7 +98,7 @@ static int cdrom_log_sense(ide_drive_t *
 	struct request_sense *sense = &drive->sense_data;
 	int log = 0;
 
-	if (!sense || !rq || (rq->cmd_flags & REQ_QUIET))
+	if (!sense || !rq || (rq->rq_flags & RQF_QUIET))
 		return 0;
 
 	ide_debug_log(IDE_DBG_SENSE, "sense_key: 0x%x", sense->sense_key);
@@ -291,7 +291,7 @@ static int cdrom_decode_status(ide_drive
 		 * (probably while trying to recover from a former error).
 		 * Just give up.
 		 */
-		rq->cmd_flags |= REQ_FAILED;
+		rq->rq_flags |= RQF_FAILED;
 		return 2;
 	}
 
@@ -311,7 +311,7 @@ static int cdrom_decode_status(ide_drive
 			cdrom_saw_media_change(drive);
 
 			if (rq->cmd_type == REQ_TYPE_FS &&
-			    !(rq->cmd_flags & REQ_QUIET))
+			    !(rq->rq_flags & RQF_QUIET))
 				printk(KERN_ERR PFX "%s: tray open\n",
 					drive->name);
 		}
@@ -346,7 +346,7 @@ static int cdrom_decode_status(ide_drive
 		 * No point in retrying after an illegal request or data
 		 * protect error.
 		 */
-		if (!(rq->cmd_flags & REQ_QUIET))
+		if (!(rq->rq_flags & RQF_QUIET))
 			ide_dump_status(drive, "command error", stat);
 		do_end_request = 1;
 		break;
@@ -355,14 +355,14 @@ static int cdrom_decode_status(ide_drive
 		 * No point in re-trying a zillion times on a bad sector.
 		 * If we got here the error is not correctable.
 		 */
-		if (!(rq->cmd_flags & REQ_QUIET))
+		if (!(rq->rq_flags & RQF_QUIET))
 			ide_dump_status(drive, "media error "
 					"(bad sector)", stat);
 		do_end_request = 1;
 		break;
 	case BLANK_CHECK:
 		/* disk appears blank? */
-		if (!(rq->cmd_flags & REQ_QUIET))
+		if (!(rq->rq_flags & RQF_QUIET))
 			ide_dump_status(drive, "media error (blank)",
 					stat);
 		do_end_request = 1;
@@ -380,7 +380,7 @@ static int cdrom_decode_status(ide_drive
 	}
 
 	if (rq->cmd_type != REQ_TYPE_FS) {
-		rq->cmd_flags |= REQ_FAILED;
+		rq->rq_flags |= RQF_FAILED;
 		do_end_request = 1;
 	}
 
@@ -422,19 +422,19 @@ static void ide_cd_request_sense_fixup(i
 int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
 		    int write, void *buffer, unsigned *bufflen,
 		    struct request_sense *sense, int timeout,
-		    unsigned int cmd_flags)
+		    req_flags_t rq_flags)
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct request_sense local_sense;
 	int retries = 10;
-	unsigned int flags = 0;
+	req_flags_t flags = 0;
 
 	if (!sense)
 		sense = &local_sense;
 
 	ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x, timeout: %d, "
-				  "cmd_flags: 0x%x",
-				  cmd[0], write, timeout, cmd_flags);
+				  "rq_flags: 0x%x",
+				  cmd[0], write, timeout, rq_flags);
 
 	/* start of retry loop */
 	do {
@@ -446,7 +446,7 @@ int ide_cd_queue_pc(ide_drive_t *drive,
 		memcpy(rq->cmd, cmd, BLK_MAX_CDB);
 		rq->cmd_type = REQ_TYPE_ATA_PC;
 		rq->sense = sense;
-		rq->cmd_flags |= cmd_flags;
+		rq->rq_flags |= rq_flags;
 		rq->timeout = timeout;
 		if (buffer) {
 			error = blk_rq_map_kern(drive->queue, rq, buffer,
@@ -462,14 +462,14 @@ int ide_cd_queue_pc(ide_drive_t *drive,
 		if (buffer)
 			*bufflen = rq->resid_len;
 
-		flags = rq->cmd_flags;
+		flags = rq->rq_flags;
 		blk_put_request(rq);
 
 		/*
 		 * FIXME: we should probably abort/retry or something in case of
 		 * failure.
 		 */
-		if (flags & REQ_FAILED) {
+		if (flags & RQF_FAILED) {
 			/*
 			 * The request failed.  Retry if it was due to a unit
 			 * attention status (usually means media was changed).
@@ -494,10 +494,10 @@ int ide_cd_queue_pc(ide_drive_t *drive,
 		}
 
 		/* end of retry loop */
-	} while ((flags & REQ_FAILED) && retries >= 0);
+	} while ((flags & RQF_FAILED) && retries >= 0);
 
 	/* return an error if the command failed */
-	return (flags & REQ_FAILED) ? -EIO : 0;
+	return (flags & RQF_FAILED) ? -EIO : 0;
 }
 
 /*
@@ -589,7 +589,7 @@ static ide_startstop_t cdrom_newpc_intr(
 					"(%u bytes)\n", drive->name, __func__,
 					cmd->nleft);
 				if (!write)
-					rq->cmd_flags |= REQ_FAILED;
+					rq->rq_flags |= RQF_FAILED;
 				uptodate = 0;
 			}
 		} else if (rq->cmd_type != REQ_TYPE_BLOCK_PC) {
@@ -607,7 +607,7 @@ static ide_startstop_t cdrom_newpc_intr(
 			}
 
 			if (!uptodate)
-				rq->cmd_flags |= REQ_FAILED;
+				rq->rq_flags |= RQF_FAILED;
 		}
 		goto out_end;
 	}
@@ -745,9 +745,9 @@ static void cdrom_do_block_pc(ide_drive_
 				  rq->cmd[0], rq->cmd_type);
 
 	if (rq->cmd_type == REQ_TYPE_BLOCK_PC)
-		rq->cmd_flags |= REQ_QUIET;
+		rq->rq_flags |= RQF_QUIET;
 	else
-		rq->cmd_flags &= ~REQ_FAILED;
+		rq->rq_flags &= ~RQF_FAILED;
 
 	drive->dma = 0;
 
@@ -867,7 +867,7 @@ int cdrom_check_status(ide_drive_t *driv
 	 */
 	cmd[7] = cdi->sanyo_slot % 3;
 
-	return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, REQ_QUIET);
+	return ide_cd_queue_pc(drive, cmd, 0, NULL, NULL, sense, 0, RQF_QUIET);
 }
 
 static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
@@ -890,7 +890,7 @@ static int cdrom_read_capacity(ide_drive
 	cmd[0] = GPCMD_READ_CDVD_CAPACITY;
 
 	stat = ide_cd_queue_pc(drive, cmd, 0, &capbuf, &len, sense, 0,
-			       REQ_QUIET);
+			       RQF_QUIET);
 	if (stat)
 		return stat;
 
@@ -943,7 +943,7 @@ static int cdrom_read_tocentry(ide_drive
 	if (msf_flag)
 		cmd[1] = 2;
 
-	return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, REQ_QUIET);
+	return ide_cd_queue_pc(drive, cmd, 0, buf, &buflen, sense, 0, RQF_QUIET);
 }
 
 /* Try to read the entire TOC for the disk into our internal buffer. */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-cd.h linux-libre-4.10-rc8-gnu/drivers/ide/ide-cd.h
--- linux-libre-4.9-gnu/drivers/ide/ide-cd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-cd.h	2017-02-12 16:03:20.000000000 -0500
@@ -101,7 +101,7 @@ void ide_cd_log_error(const char *, stru
 
 /* ide-cd.c functions used by ide-cd_ioctl.c */
 int ide_cd_queue_pc(ide_drive_t *, const unsigned char *, int, void *,
-		    unsigned *, struct request_sense *, int, unsigned int);
+		    unsigned *, struct request_sense *, int, req_flags_t);
 int ide_cd_read_toc(ide_drive_t *, struct request_sense *);
 int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
 void ide_cdrom_update_speed(ide_drive_t *, u8 *);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-cd_ioctl.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-cd_ioctl.c
--- linux-libre-4.9-gnu/drivers/ide/ide-cd_ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-cd_ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -305,7 +305,7 @@ int ide_cdrom_reset(struct cdrom_device_
 
 	rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
 	rq->cmd_type = REQ_TYPE_DRV_PRIV;
-	rq->cmd_flags = REQ_QUIET;
+	rq->rq_flags = RQF_QUIET;
 	ret = blk_execute_rq(drive->queue, cd->disk, rq, 0);
 	blk_put_request(rq);
 	/*
@@ -449,7 +449,7 @@ int ide_cdrom_packet(struct cdrom_device
 			    struct packet_command *cgc)
 {
 	ide_drive_t *drive = cdi->handle;
-	unsigned int flags = 0;
+	req_flags_t flags = 0;
 	unsigned len = cgc->buflen;
 
 	if (cgc->timeout <= 0)
@@ -463,7 +463,7 @@ int ide_cdrom_packet(struct cdrom_device
 		memset(cgc->sense, 0, sizeof(struct request_sense));
 
 	if (cgc->quiet)
-		flags |= REQ_QUIET;
+		flags |= RQF_QUIET;
 
 	cgc->stat = ide_cd_queue_pc(drive, cgc->cmd,
 				    cgc->data_direction == CGC_DATA_WRITE,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-disk.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-disk.c
--- linux-libre-4.9-gnu/drivers/ide/ide-disk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-disk.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/div64.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-io.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-io.c
--- linux-libre-4.9-gnu/drivers/ide/ide-io.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-io.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,7 +51,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 int ide_end_rq(ide_drive_t *drive, struct request *rq, int error,
@@ -307,7 +307,7 @@ static ide_startstop_t start_request (id
 {
 	ide_startstop_t startstop;
 
-	BUG_ON(!(rq->cmd_flags & REQ_STARTED));
+	BUG_ON(!(rq->rq_flags & RQF_STARTED));
 
 #ifdef DEBUG
 	printk("%s: start_request: current=0x%08lx\n",
@@ -316,7 +316,7 @@ static ide_startstop_t start_request (id
 
 	/* bail early if we've exceeded max_failures */
 	if (drive->max_failures && (drive->failures > drive->max_failures)) {
-		rq->cmd_flags |= REQ_FAILED;
+		rq->rq_flags |= RQF_FAILED;
 		goto kill_rq;
 	}
 
@@ -539,7 +539,7 @@ repeat:
 		 */
 		if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
 		    ata_pm_request(rq) == 0 &&
-		    (rq->cmd_flags & REQ_PREEMPT) == 0) {
+		    (rq->rq_flags & RQF_PREEMPT) == 0) {
 			/* there should be no pending command at this point */
 			ide_unlock_port(hwif);
 			goto plug_device;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-iops.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-iops.c
--- linux-libre-4.9-gnu/drivers/ide/ide-iops.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-iops.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 void SELECT_MASK(ide_drive_t *drive, int mask)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-pm.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-pm.c
--- linux-libre-4.9-gnu/drivers/ide/ide-pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@ static int ide_pm_execute_rq(struct requ
 
 	spin_lock_irq(q->queue_lock);
 	if (unlikely(blk_queue_dying(q))) {
-		rq->cmd_flags |= REQ_QUIET;
+		rq->rq_flags |= RQF_QUIET;
 		rq->errors = -ENXIO;
 		__blk_end_request_all(rq, rq->errors);
 		spin_unlock_irq(q->queue_lock);
@@ -90,7 +90,7 @@ int generic_ide_resume(struct device *de
 	memset(&rqpm, 0, sizeof(rqpm));
 	rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
 	rq->cmd_type = REQ_TYPE_ATA_PM_RESUME;
-	rq->cmd_flags |= REQ_PREEMPT;
+	rq->rq_flags |= RQF_PREEMPT;
 	rq->special = &rqpm;
 	rqpm.pm_step = IDE_PM_START_RESUME;
 	rqpm.pm_state = PM_EVENT_ON;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-probe.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-probe.c
--- linux-libre-4.9-gnu/drivers/ide/ide-probe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-probe.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/ide/ide-proc.c linux-libre-4.10-rc8-gnu/drivers/ide/ide-proc.c
--- linux-libre-4.9-gnu/drivers/ide/ide-proc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/ide/ide-proc.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 
 #include <linux/module.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/errno.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/idle/i7300_idle.c linux-libre-4.10-rc8-gnu/drivers/idle/i7300_idle.c
--- linux-libre-4.9-gnu/drivers/idle/i7300_idle.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/idle/i7300_idle.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,612 +0,0 @@
-/*
- * (C) Copyright 2008 Intel Corporation
- * Authors:
- * Andy Henroid <andrew.d.henroid@intel.com>
- * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- */
-
-/*
- * Save DIMM power on Intel 7300-based platforms when all CPUs/cores
- * are idle, using the DIMM thermal throttling capability.
- *
- * This driver depends on the Intel integrated DMA controller (I/O AT).
- * If the driver for I/O AT (drivers/dma/ioatdma*) is also enabled,
- * this driver should work cooperatively.
- */
-
-/* #define DEBUG */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/gfp.h>
-#include <linux/sched.h>
-#include <linux/notifier.h>
-#include <linux/cpumask.h>
-#include <linux/ktime.h>
-#include <linux/delay.h>
-#include <linux/debugfs.h>
-#include <linux/stop_machine.h>
-#include <linux/i7300_idle.h>
-
-#include <asm/idle.h>
-
-#include "../dma/ioat/hw.h"
-#include "../dma/ioat/registers.h"
-
-#define I7300_IDLE_DRIVER_VERSION	"1.55"
-#define I7300_PRINT			"i7300_idle:"
-
-#define MAX_STOP_RETRIES	10
-
-static int debug;
-module_param_named(debug, debug, uint, 0644);
-MODULE_PARM_DESC(debug, "Enable debug printks in this driver");
-
-static int forceload;
-module_param_named(forceload, forceload, uint, 0644);
-MODULE_PARM_DESC(debug, "Enable driver testing on unvalidated i5000");
-
-#define dprintk(fmt, arg...) \
-	do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0)
-
-/*
- * Value to set THRTLOW to when initiating throttling
- *  0 = No throttling
- *  1 = Throttle when > 4 activations per eval window (Maximum throttling)
- *  2 = Throttle when > 8 activations
- *  168 = Throttle when > 672 activations (Minimum throttling)
- */
-#define MAX_THROTTLE_LOW_LIMIT		168
-static uint throttle_low_limit = 1;
-module_param_named(throttle_low_limit, throttle_low_limit, uint, 0644);
-MODULE_PARM_DESC(throttle_low_limit,
-		"Value for THRTLOWLM activation field "
-		"(0 = disable throttle, 1 = Max throttle, 168 = Min throttle)");
-
-/*
- * simple invocation and duration statistics
- */
-static unsigned long total_starts;
-static unsigned long total_us;
-
-#ifdef DEBUG
-static unsigned long past_skip;
-#endif
-
-static struct pci_dev *fbd_dev;
-
-static raw_spinlock_t i7300_idle_lock;
-static int i7300_idle_active;
-
-static u8 i7300_idle_thrtctl_saved;
-static u8 i7300_idle_thrtlow_saved;
-static u32 i7300_idle_mc_saved;
-
-static cpumask_var_t idle_cpumask;
-static ktime_t start_ktime;
-static unsigned long avg_idle_us;
-
-static struct dentry *debugfs_dir;
-
-/* Begin: I/O AT Helper routines */
-
-#define IOAT_CHANBASE(ioat_ctl, chan) (ioat_ctl + 0x80 + 0x80 * chan)
-/* Snoop control (disable snoops when coherency is not important) */
-#define IOAT_DESC_SADDR_SNP_CTL (1UL << 1)
-#define IOAT_DESC_DADDR_SNP_CTL (1UL << 2)
-
-static struct pci_dev *ioat_dev;
-static struct ioat_dma_descriptor *ioat_desc; /* I/O AT desc & data (1 page) */
-static unsigned long ioat_desc_phys;
-static u8 *ioat_iomap; /* I/O AT memory-mapped control regs (aka CB_BAR) */
-static u8 *ioat_chanbase;
-
-/* Start I/O AT memory copy */
-static int i7300_idle_ioat_start(void)
-{
-	u32 err;
-	/* Clear error (due to circular descriptor pointer) */
-	err = readl(ioat_chanbase + IOAT_CHANERR_OFFSET);
-	if (err)
-		writel(err, ioat_chanbase + IOAT_CHANERR_OFFSET);
-
-	writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-	return 0;
-}
-
-/* Stop I/O AT memory copy */
-static void i7300_idle_ioat_stop(void)
-{
-	int i;
-	u64 sts;
-
-	for (i = 0; i < MAX_STOP_RETRIES; i++) {
-		writeb(IOAT_CHANCMD_RESET,
-			ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-
-		udelay(10);
-
-		sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
-			IOAT_CHANSTS_STATUS;
-
-		if (sts != IOAT_CHANSTS_ACTIVE)
-			break;
-
-	}
-
-	if (i == MAX_STOP_RETRIES) {
-		dprintk("failed to stop I/O AT after %d retries\n",
-			MAX_STOP_RETRIES);
-	}
-}
-
-/* Test I/O AT by copying 1024 byte from 2k to 1k */
-static int __init i7300_idle_ioat_selftest(u8 *ctl,
-		struct ioat_dma_descriptor *desc, unsigned long desc_phys)
-{
-	u64 chan_sts;
-
-	memset(desc, 0, 2048);
-	memset((u8 *) desc + 2048, 0xab, 1024);
-
-	desc[0].size = 1024;
-	desc[0].ctl = 0;
-	desc[0].src_addr = desc_phys + 2048;
-	desc[0].dst_addr = desc_phys + 1024;
-	desc[0].next = 0;
-
-	writeb(IOAT_CHANCMD_RESET, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-	writeb(IOAT_CHANCMD_START, ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-
-	udelay(1000);
-
-	chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
-			IOAT_CHANSTS_STATUS;
-
-	if (chan_sts != IOAT_CHANSTS_DONE) {
-		/* Not complete, reset the channel */
-		writeb(IOAT_CHANCMD_RESET,
-		       ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-		return -1;
-	}
-
-	if (*(u32 *) ((u8 *) desc + 3068) != 0xabababab ||
-	    *(u32 *) ((u8 *) desc + 2044) != 0xabababab) {
-		dprintk("Data values src 0x%x, dest 0x%x, memset 0x%x\n",
-			*(u32 *) ((u8 *) desc + 2048),
-			*(u32 *) ((u8 *) desc + 1024),
-			*(u32 *) ((u8 *) desc + 3072));
-		return -1;
-	}
-	return 0;
-}
-
-static struct device dummy_dma_dev = {
-	.init_name = "fallback device",
-	.coherent_dma_mask = DMA_BIT_MASK(64),
-	.dma_mask = &dummy_dma_dev.coherent_dma_mask,
-};
-
-/* Setup and initialize I/O AT */
-/* This driver needs I/O AT as the throttling takes effect only when there is
- * some memory activity. We use I/O AT to set up a dummy copy, while all CPUs
- * go idle and memory is throttled.
- */
-static int __init i7300_idle_ioat_init(void)
-{
-	u8 ver, chan_count, ioat_chan;
-	u16 chan_ctl;
-
-	ioat_iomap = (u8 *) ioremap_nocache(pci_resource_start(ioat_dev, 0),
-					    pci_resource_len(ioat_dev, 0));
-
-	if (!ioat_iomap) {
-		printk(KERN_ERR I7300_PRINT "failed to map I/O AT registers\n");
-		goto err_ret;
-	}
-
-	ver = readb(ioat_iomap + IOAT_VER_OFFSET);
-	if (ver != IOAT_VER_1_2) {
-		printk(KERN_ERR I7300_PRINT "unknown I/O AT version (%u.%u)\n",
-			ver >> 4, ver & 0xf);
-		goto err_unmap;
-	}
-
-	chan_count = readb(ioat_iomap + IOAT_CHANCNT_OFFSET);
-	if (!chan_count) {
-		printk(KERN_ERR I7300_PRINT "unexpected # of I/O AT channels "
-			"(%u)\n",
-			chan_count);
-		goto err_unmap;
-	}
-
-	ioat_chan = chan_count - 1;
-	ioat_chanbase = IOAT_CHANBASE(ioat_iomap, ioat_chan);
-
-	chan_ctl = readw(ioat_chanbase + IOAT_CHANCTRL_OFFSET);
-	if (chan_ctl & IOAT_CHANCTRL_CHANNEL_IN_USE) {
-		printk(KERN_ERR I7300_PRINT "channel %d in use\n", ioat_chan);
-		goto err_unmap;
-	}
-
-	writew(IOAT_CHANCTRL_CHANNEL_IN_USE,
-		ioat_chanbase + IOAT_CHANCTRL_OFFSET);
-
-	ioat_desc = (struct ioat_dma_descriptor *)dma_alloc_coherent(
-			&dummy_dma_dev, 4096,
-			(dma_addr_t *)&ioat_desc_phys, GFP_KERNEL);
-	if (!ioat_desc) {
-		printk(KERN_ERR I7300_PRINT "failed to allocate I/O AT desc\n");
-		goto err_mark_unused;
-	}
-
-	writel(ioat_desc_phys & 0xffffffffUL,
-	       ioat_chanbase + IOAT1_CHAINADDR_OFFSET_LOW);
-	writel(ioat_desc_phys >> 32,
-	       ioat_chanbase + IOAT1_CHAINADDR_OFFSET_HIGH);
-
-	if (i7300_idle_ioat_selftest(ioat_iomap, ioat_desc, ioat_desc_phys)) {
-		printk(KERN_ERR I7300_PRINT "I/O AT self-test failed\n");
-		goto err_free;
-	}
-
-	/* Setup circular I/O AT descriptor chain */
-	ioat_desc[0].ctl = IOAT_DESC_SADDR_SNP_CTL | IOAT_DESC_DADDR_SNP_CTL;
-	ioat_desc[0].src_addr = ioat_desc_phys + 2048;
-	ioat_desc[0].dst_addr = ioat_desc_phys + 3072;
-	ioat_desc[0].size = 128;
-	ioat_desc[0].next = ioat_desc_phys + sizeof(struct ioat_dma_descriptor);
-
-	ioat_desc[1].ctl = ioat_desc[0].ctl;
-	ioat_desc[1].src_addr = ioat_desc[0].src_addr;
-	ioat_desc[1].dst_addr = ioat_desc[0].dst_addr;
-	ioat_desc[1].size = ioat_desc[0].size;
-	ioat_desc[1].next = ioat_desc_phys;
-
-	return 0;
-
-err_free:
-	dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
-err_mark_unused:
-	writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
-err_unmap:
-	iounmap(ioat_iomap);
-err_ret:
-	return -ENODEV;
-}
-
-/* Cleanup I/O AT */
-static void __exit i7300_idle_ioat_exit(void)
-{
-	int i;
-	u64 chan_sts;
-
-	i7300_idle_ioat_stop();
-
-	/* Wait for a while for the channel to halt before releasing */
-	for (i = 0; i < MAX_STOP_RETRIES; i++) {
-		writeb(IOAT_CHANCMD_RESET,
-		       ioat_chanbase + IOAT1_CHANCMD_OFFSET);
-
-		chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
-			IOAT_CHANSTS_STATUS;
-
-		if (chan_sts != IOAT_CHANSTS_ACTIVE) {
-			writew(0, ioat_chanbase + IOAT_CHANCTRL_OFFSET);
-			break;
-		}
-		udelay(1000);
-	}
-
-	chan_sts = readq(ioat_chanbase + IOAT1_CHANSTS_OFFSET) &
-			IOAT_CHANSTS_STATUS;
-
-	/*
-	 * We tried to reset multiple times. If IO A/T channel is still active
-	 * flag an error and return without cleanup. Memory leak is better
-	 * than random corruption in that extreme error situation.
-	 */
-	if (chan_sts == IOAT_CHANSTS_ACTIVE) {
-		printk(KERN_ERR I7300_PRINT "Unable to stop IO A/T channels."
-			" Not freeing resources\n");
-		return;
-	}
-
-	dma_free_coherent(&dummy_dma_dev, 4096, (void *)ioat_desc, 0);
-	iounmap(ioat_iomap);
-}
-
-/* End: I/O AT Helper routines */
-
-#define DIMM_THRTLOW 0x64
-#define DIMM_THRTCTL 0x67
-#define DIMM_THRTCTL_THRMHUNT (1UL << 0)
-#define DIMM_MC 0x40
-#define DIMM_GTW_MODE (1UL << 17)
-#define DIMM_GBLACT 0x60
-
-/*
- * Keep track of an exponential-decaying average of recent idle durations.
- * The latest duration gets DURATION_WEIGHT_PCT percentage weight
- * in this average, with the old average getting the remaining weight.
- *
- * High weights emphasize recent history, low weights include long history.
- */
-#define DURATION_WEIGHT_PCT 55
-
-/*
- * When the decaying average of recent durations or the predicted duration
- * of the next timer interrupt is shorter than duration_threshold, the
- * driver will decline to throttle.
- */
-#define DURATION_THRESHOLD_US 100
-
-
-/* Store DIMM thermal throttle configuration */
-static int i7300_idle_thrt_save(void)
-{
-	u32 new_mc_val;
-	u8 gblactlm;
-
-	pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &i7300_idle_thrtctl_saved);
-	pci_read_config_byte(fbd_dev, DIMM_THRTLOW, &i7300_idle_thrtlow_saved);
-	pci_read_config_dword(fbd_dev, DIMM_MC, &i7300_idle_mc_saved);
-	/*
-	 * Make sure we have Global Throttling Window Mode set to have a
-	 * "short" window. This (mostly) works around an issue where
-	 * throttling persists until the end of the global throttling window
-	 * size. On the tested system, this was resulting in a maximum of
-	 * 64 ms to exit throttling (average 32 ms). The actual numbers
-	 * depends on system frequencies. Setting the short window reduces
-	 * this by a factor of 4096.
-	 *
-	 * We will only do this only if the system is set for
-	 * unlimited-activations while in open-loop throttling (i.e., when
-	 * Global Activation Throttle Limit is zero).
-	 */
-	pci_read_config_byte(fbd_dev, DIMM_GBLACT, &gblactlm);
-	dprintk("thrtctl_saved = 0x%02x, thrtlow_saved = 0x%02x\n",
-		i7300_idle_thrtctl_saved,
-		i7300_idle_thrtlow_saved);
-	dprintk("mc_saved = 0x%08x, gblactlm = 0x%02x\n",
-		i7300_idle_mc_saved,
-		gblactlm);
-	if (gblactlm == 0) {
-		new_mc_val = i7300_idle_mc_saved | DIMM_GTW_MODE;
-		pci_write_config_dword(fbd_dev, DIMM_MC, new_mc_val);
-		return 0;
-	} else {
-		dprintk("could not set GTW_MODE = 1 (OLTT enabled)\n");
-		return -ENODEV;
-	}
-}
-
-/* Restore DIMM thermal throttle configuration */
-static void i7300_idle_thrt_restore(void)
-{
-	pci_write_config_dword(fbd_dev, DIMM_MC, i7300_idle_mc_saved);
-	pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
-	pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
-}
-
-/* Enable DIMM thermal throttling */
-static void i7300_idle_start(void)
-{
-	u8 new_ctl;
-	u8 limit;
-
-	new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
-	pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
-
-	limit = throttle_low_limit;
-	if (unlikely(limit > MAX_THROTTLE_LOW_LIMIT))
-		limit = MAX_THROTTLE_LOW_LIMIT;
-
-	pci_write_config_byte(fbd_dev, DIMM_THRTLOW, limit);
-
-	new_ctl = i7300_idle_thrtctl_saved | DIMM_THRTCTL_THRMHUNT;
-	pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
-}
-
-/* Disable DIMM thermal throttling */
-static void i7300_idle_stop(void)
-{
-	u8 new_ctl;
-	u8 got_ctl;
-
-	new_ctl = i7300_idle_thrtctl_saved & ~DIMM_THRTCTL_THRMHUNT;
-	pci_write_config_byte(fbd_dev, DIMM_THRTCTL, new_ctl);
-
-	pci_write_config_byte(fbd_dev, DIMM_THRTLOW, i7300_idle_thrtlow_saved);
-	pci_write_config_byte(fbd_dev, DIMM_THRTCTL, i7300_idle_thrtctl_saved);
-	pci_read_config_byte(fbd_dev, DIMM_THRTCTL, &got_ctl);
-	WARN_ON_ONCE(got_ctl != i7300_idle_thrtctl_saved);
-}
-
-
-/*
- * i7300_avg_duration_check()
- * return 0 if the decaying average of recent idle durations is
- * more than DURATION_THRESHOLD_US
- */
-static int i7300_avg_duration_check(void)
-{
-	if (avg_idle_us >= DURATION_THRESHOLD_US)
-		return 0;
-
-#ifdef DEBUG
-	past_skip++;
-#endif
-	return 1;
-}
-
-/* Idle notifier to look at idle CPUs */
-static int i7300_idle_notifier(struct notifier_block *nb, unsigned long val,
-				void *data)
-{
-	unsigned long flags;
-	ktime_t now_ktime;
-	static ktime_t idle_begin_time;
-	static int time_init = 1;
-
-	if (!throttle_low_limit)
-		return 0;
-
-	if (unlikely(time_init)) {
-		time_init = 0;
-		idle_begin_time = ktime_get();
-	}
-
-	raw_spin_lock_irqsave(&i7300_idle_lock, flags);
-	if (val == IDLE_START) {
-
-		cpumask_set_cpu(smp_processor_id(), idle_cpumask);
-
-		if (cpumask_weight(idle_cpumask) != num_online_cpus())
-			goto end;
-
-		now_ktime = ktime_get();
-		idle_begin_time = now_ktime;
-
-		if (i7300_avg_duration_check())
-			goto end;
-
-		i7300_idle_active = 1;
-		total_starts++;
-		start_ktime = now_ktime;
-
-		i7300_idle_start();
-		i7300_idle_ioat_start();
-
-	} else if (val == IDLE_END) {
-		cpumask_clear_cpu(smp_processor_id(), idle_cpumask);
-		if (cpumask_weight(idle_cpumask) == (num_online_cpus() - 1)) {
-			/* First CPU coming out of idle */
-			u64 idle_duration_us;
-
-			now_ktime = ktime_get();
-
-			idle_duration_us = ktime_to_us(ktime_sub
-						(now_ktime, idle_begin_time));
-
-			avg_idle_us =
-				((100 - DURATION_WEIGHT_PCT) * avg_idle_us +
-				 DURATION_WEIGHT_PCT * idle_duration_us) / 100;
-
-			if (i7300_idle_active) {
-				ktime_t idle_ktime;
-
-				idle_ktime = ktime_sub(now_ktime, start_ktime);
-				total_us += ktime_to_us(idle_ktime);
-
-				i7300_idle_ioat_stop();
-				i7300_idle_stop();
-				i7300_idle_active = 0;
-			}
-		}
-	}
-end:
-	raw_spin_unlock_irqrestore(&i7300_idle_lock, flags);
-	return 0;
-}
-
-static struct notifier_block i7300_idle_nb = {
-	.notifier_call = i7300_idle_notifier,
-};
-
-MODULE_DEVICE_TABLE(pci, pci_tbl);
-
-static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
-				loff_t *off)
-{
-	unsigned long *p = fp->private_data;
-	char buf[32];
-	int len;
-
-	len = snprintf(buf, 32, "%lu\n", *p);
-	return simple_read_from_buffer(ubuf, count, off, buf, len);
-}
-
-static const struct file_operations idle_fops = {
-	.open	= simple_open,
-	.read	= stats_read_ul,
-	.llseek = default_llseek,
-};
-
-struct debugfs_file_info {
-	void *ptr;
-	char name[32];
-	struct dentry *file;
-} debugfs_file_list[] = {
-				{&total_starts, "total_starts", NULL},
-				{&total_us, "total_us", NULL},
-#ifdef DEBUG
-				{&past_skip, "past_skip", NULL},
-#endif
-				{NULL, "", NULL}
-			};
-
-static int __init i7300_idle_init(void)
-{
-	raw_spin_lock_init(&i7300_idle_lock);
-	total_us = 0;
-
-	if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev, forceload))
-		return -ENODEV;
-
-	if (i7300_idle_thrt_save())
-		return -ENODEV;
-
-	if (i7300_idle_ioat_init())
-		return -ENODEV;
-
-	if (!zalloc_cpumask_var(&idle_cpumask, GFP_KERNEL))
-		return -ENOMEM;
-
-	debugfs_dir = debugfs_create_dir("i7300_idle", NULL);
-	if (debugfs_dir) {
-		int i = 0;
-
-		while (debugfs_file_list[i].ptr != NULL) {
-			debugfs_file_list[i].file = debugfs_create_file(
-					debugfs_file_list[i].name,
-					S_IRUSR,
-					debugfs_dir,
-					debugfs_file_list[i].ptr,
-					&idle_fops);
-			i++;
-		}
-	}
-
-	idle_notifier_register(&i7300_idle_nb);
-
-	printk(KERN_INFO "i7300_idle: loaded v%s\n", I7300_IDLE_DRIVER_VERSION);
-	return 0;
-}
-
-static void __exit i7300_idle_exit(void)
-{
-	idle_notifier_unregister(&i7300_idle_nb);
-	free_cpumask_var(idle_cpumask);
-
-	if (debugfs_dir) {
-		int i = 0;
-
-		while (debugfs_file_list[i].file != NULL) {
-			debugfs_remove(debugfs_file_list[i].file);
-			i++;
-		}
-
-		debugfs_remove(debugfs_dir);
-	}
-	i7300_idle_thrt_restore();
-	i7300_idle_ioat_exit();
-}
-
-module_init(i7300_idle_init);
-module_exit(i7300_idle_exit);
-
-MODULE_AUTHOR("Andy Henroid <andrew.d.henroid@intel.com>");
-MODULE_DESCRIPTION("Intel Chipset DIMM Idle Power Saving Driver v"
-			I7300_IDLE_DRIVER_VERSION);
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/idle/intel_idle.c linux-libre-4.10-rc8-gnu/drivers/idle/intel_idle.c
--- linux-libre-4.9-gnu/drivers/idle/intel_idle.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/idle/intel_idle.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,8 +98,6 @@ static int intel_idle(struct cpuidle_dev
 			struct cpuidle_driver *drv, int index);
 static void intel_idle_freeze(struct cpuidle_device *dev,
 			      struct cpuidle_driver *drv, int index);
-static int intel_idle_cpu_init(int cpu);
-
 static struct cpuidle_state *cpuidle_state_table;
 
 /*
@@ -724,6 +722,50 @@ static struct cpuidle_state atom_cstates
 	{
 		.enter = NULL }
 };
+static struct cpuidle_state tangier_cstates[] = {
+	{
+		.name = "C1-TNG",
+		.desc = "MWAIT 0x00",
+		.flags = MWAIT2flg(0x00),
+		.exit_latency = 1,
+		.target_residency = 4,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C4-TNG",
+		.desc = "MWAIT 0x30",
+		.flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 100,
+		.target_residency = 400,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C6-TNG",
+		.desc = "MWAIT 0x52",
+		.flags = MWAIT2flg(0x52) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 140,
+		.target_residency = 560,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C7-TNG",
+		.desc = "MWAIT 0x60",
+		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 1200,
+		.target_residency = 4000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.name = "C9-TNG",
+		.desc = "MWAIT 0x64",
+		.flags = MWAIT2flg(0x64) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.exit_latency = 10000,
+		.target_residency = 20000,
+		.enter = &intel_idle,
+		.enter_freeze = intel_idle_freeze, },
+	{
+		.enter = NULL }
+};
 static struct cpuidle_state avn_cstates[] = {
 	{
 		.name = "C1-AVN",
@@ -907,51 +949,15 @@ static void intel_idle_freeze(struct cpu
 	mwait_idle_with_hints(eax, ecx);
 }
 
-static void __setup_broadcast_timer(void *arg)
+static void __setup_broadcast_timer(bool on)
 {
-	unsigned long on = (unsigned long)arg;
-
 	if (on)
 		tick_broadcast_enable();
 	else
 		tick_broadcast_disable();
 }
 
-static int cpu_hotplug_notify(struct notifier_block *n,
-			      unsigned long action, void *hcpu)
-{
-	int hotcpu = (unsigned long)hcpu;
-	struct cpuidle_device *dev;
-
-	switch (action & ~CPU_TASKS_FROZEN) {
-	case CPU_ONLINE:
-
-		if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
-			smp_call_function_single(hotcpu, __setup_broadcast_timer,
-						 (void *)true, 1);
-
-		/*
-		 * Some systems can hotplug a cpu at runtime after
-		 * the kernel has booted, we have to initialize the
-		 * driver in this case
-		 */
-		dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
-		if (dev->registered)
-			break;
-
-		if (intel_idle_cpu_init(hotcpu))
-			return NOTIFY_BAD;
-
-		break;
-	}
-	return NOTIFY_OK;
-}
-
-static struct notifier_block cpu_hotplug_notifier = {
-	.notifier_call = cpu_hotplug_notify,
-};
-
-static void auto_demotion_disable(void *dummy)
+static void auto_demotion_disable(void)
 {
 	unsigned long long msr_bits;
 
@@ -959,7 +965,7 @@ static void auto_demotion_disable(void *
 	msr_bits &= ~(icpu->auto_demotion_disable_flags);
 	wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits);
 }
-static void c1e_promotion_disable(void *dummy)
+static void c1e_promotion_disable(void)
 {
 	unsigned long long msr_bits;
 
@@ -978,6 +984,10 @@ static const struct idle_cpu idle_cpu_at
 	.state_table = atom_cstates,
 };
 
+static const struct idle_cpu idle_cpu_tangier = {
+	.state_table = tangier_cstates,
+};
+
 static const struct idle_cpu idle_cpu_lincroft = {
 	.state_table = atom_cstates,
 	.auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE,
@@ -1066,6 +1076,7 @@ static const struct x86_cpu_id intel_idl
 	ICPU(INTEL_FAM6_SANDYBRIDGE_X,		idle_cpu_snb),
 	ICPU(INTEL_FAM6_ATOM_CEDARVIEW,		idle_cpu_atom),
 	ICPU(INTEL_FAM6_ATOM_SILVERMONT1,	idle_cpu_byt),
+	ICPU(INTEL_FAM6_ATOM_MERRIFIELD,	idle_cpu_tangier),
 	ICPU(INTEL_FAM6_ATOM_AIRMONT,		idle_cpu_cht),
 	ICPU(INTEL_FAM6_IVYBRIDGE,		idle_cpu_ivb),
 	ICPU(INTEL_FAM6_IVYBRIDGE_X,		idle_cpu_ivt),
@@ -1084,6 +1095,7 @@ static const struct x86_cpu_id intel_idl
 	ICPU(INTEL_FAM6_KABYLAKE_DESKTOP,	idle_cpu_skl),
 	ICPU(INTEL_FAM6_SKYLAKE_X,		idle_cpu_skx),
 	ICPU(INTEL_FAM6_XEON_PHI_KNL,		idle_cpu_knl),
+	ICPU(INTEL_FAM6_XEON_PHI_KNM,		idle_cpu_knl),
 	ICPU(INTEL_FAM6_ATOM_GOLDMONT,		idle_cpu_bxt),
 	ICPU(INTEL_FAM6_ATOM_DENVERTON,		idle_cpu_dnv),
 	{}
@@ -1373,12 +1385,11 @@ static void __init intel_idle_cpuidle_dr
  * allocate, initialize, register cpuidle_devices
  * @cpu: cpu/core to initialize
  */
-static int intel_idle_cpu_init(int cpu)
+static int intel_idle_cpu_init(unsigned int cpu)
 {
 	struct cpuidle_device *dev;
 
 	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
-
 	dev->cpu = cpu;
 
 	if (cpuidle_register_device(dev)) {
@@ -1387,17 +1398,36 @@ static int intel_idle_cpu_init(int cpu)
 	}
 
 	if (icpu->auto_demotion_disable_flags)
-		smp_call_function_single(cpu, auto_demotion_disable, NULL, 1);
+		auto_demotion_disable();
 
 	if (icpu->disable_promotion_to_c1e)
-		smp_call_function_single(cpu, c1e_promotion_disable, NULL, 1);
+		c1e_promotion_disable();
+
+	return 0;
+}
+
+static int intel_idle_cpu_online(unsigned int cpu)
+{
+	struct cpuidle_device *dev;
+
+	if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
+		__setup_broadcast_timer(true);
+
+	/*
+	 * Some systems can hotplug a cpu at runtime after
+	 * the kernel has booted, we have to initialize the
+	 * driver in this case
+	 */
+	dev = per_cpu_ptr(intel_idle_cpuidle_devices, cpu);
+	if (!dev->registered)
+		return intel_idle_cpu_init(cpu);
 
 	return 0;
 }
 
 static int __init intel_idle_init(void)
 {
-	int retval, i;
+	int retval;
 
 	/* Do not load intel_idle at all for now if idle= is passed */
 	if (boot_option_idle_override != IDLE_NO_OVERRIDE)
@@ -1417,35 +1447,29 @@ static int __init intel_idle_init(void)
 		struct cpuidle_driver *drv = cpuidle_get_driver();
 		printk(KERN_DEBUG PREFIX "intel_idle yielding to %s",
 			drv ? drv->name : "none");
-		free_percpu(intel_idle_cpuidle_devices);
-		return retval;
-	}
-
-	cpu_notifier_register_begin();
-
-	for_each_online_cpu(i) {
-		retval = intel_idle_cpu_init(i);
-		if (retval) {
-			intel_idle_cpuidle_devices_uninit();
-			cpu_notifier_register_done();
-			cpuidle_unregister_driver(&intel_idle_driver);
-			free_percpu(intel_idle_cpuidle_devices);
-			return retval;
-		}
+		goto init_driver_fail;
 	}
-	__register_cpu_notifier(&cpu_hotplug_notifier);
 
 	if (boot_cpu_has(X86_FEATURE_ARAT))	/* Always Reliable APIC Timer */
 		lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
-	else
-		on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
 
-	cpu_notifier_register_done();
+	retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
+				   intel_idle_cpu_online, NULL);
+	if (retval < 0)
+		goto hp_setup_fail;
 
 	pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n",
 		lapic_timer_reliable_states);
 
 	return 0;
+
+hp_setup_fail:
+	intel_idle_cpuidle_devices_uninit();
+	cpuidle_unregister_driver(&intel_idle_driver);
+init_driver_fail:
+	free_percpu(intel_idle_cpuidle_devices);
+	return retval;
+
 }
 device_initcall(intel_idle_init);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/idle/Kconfig linux-libre-4.10-rc8-gnu/drivers/idle/Kconfig
--- linux-libre-4.9-gnu/drivers/idle/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/idle/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -8,20 +8,3 @@ config INTEL_IDLE
 	  native Intel hardware idle features.  The acpi_idle driver
 	  can be configured at the same time, in order to handle
 	  processors intel_idle does not support.
-
-menu "Memory power savings"
-depends on X86_64
-
-config I7300_IDLE_IOAT_CHANNEL
-	bool
-
-config I7300_IDLE
-	tristate "Intel chipset idle memory power saving driver"
-	select I7300_IDLE_IOAT_CHANNEL
-	help
-	  Enable memory power savings when idle with certain Intel server
-	  chipsets. The chipset must have I/O AT support, such as the
-	  Intel 7300. The power savings depends on the type and quantity of
-	  DRAM devices.
-
-endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/idle/Makefile linux-libre-4.10-rc8-gnu/drivers/idle/Makefile
--- linux-libre-4.9-gnu/drivers/idle/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/idle/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,2 @@
-obj-$(CONFIG_I7300_IDLE)			+= i7300_idle.o
 obj-$(CONFIG_INTEL_IDLE)			+= intel_idle.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/da280.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/da280.c
--- linux-libre-4.9-gnu/drivers/iio/accel/da280.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/da280.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,183 @@
+/**
+ * IIO driver for the MiraMEMS DA280 3-axis accelerometer and
+ * IIO driver for the MiraMEMS DA226 2-axis accelerometer
+ *
+ * Copyright (c) 2016 Hans de Goede <hdegoede@redhat.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.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/byteorder/generic.h>
+
+#define DA280_REG_CHIP_ID		0x01
+#define DA280_REG_ACC_X_LSB		0x02
+#define DA280_REG_ACC_Y_LSB		0x04
+#define DA280_REG_ACC_Z_LSB		0x06
+#define DA280_REG_MODE_BW		0x11
+
+#define DA280_CHIP_ID			0x13
+#define DA280_MODE_ENABLE		0x1e
+#define DA280_MODE_DISABLE		0x9e
+
+enum { da226, da280 };
+
+/*
+ * a value of + or -4096 corresponds to + or - 1G
+ * scale = 9.81 / 4096 = 0.002395019
+ */
+
+static const int da280_nscale = 2395019;
+
+#define DA280_CHANNEL(reg, axis) {	\
+	.type = IIO_ACCEL,	\
+	.address = reg,	\
+	.modified = 1,	\
+	.channel2 = IIO_MOD_##axis,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec da280_channels[] = {
+	DA280_CHANNEL(DA280_REG_ACC_X_LSB, X),
+	DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y),
+	DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),
+};
+
+struct da280_data {
+	struct i2c_client *client;
+};
+
+static int da280_enable(struct i2c_client *client, bool enable)
+{
+	u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE;
+
+	return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data);
+}
+
+static int da280_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct da280_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = i2c_smbus_read_word_data(data->client, chan->address);
+		if (ret < 0)
+			return ret;
+		/*
+		 * Values are 14 bits, stored as 16 bits with the 2
+		 * least significant bits always 0.
+		 */
+		*val = (short)ret >> 2;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = da280_nscale;
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info da280_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= da280_read_raw,
+};
+
+static int da280_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct da280_data *data;
+
+	ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
+	if (ret != DA280_CHIP_ID)
+		return (ret < 0) ? ret : -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &da280_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = da280_channels;
+	if (id->driver_data == da226) {
+		indio_dev->name = "da226";
+		indio_dev->num_channels = 2;
+	} else {
+		indio_dev->name = "da280";
+		indio_dev->num_channels = 3;
+	}
+
+	ret = da280_enable(client, true);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "device_register failed\n");
+		da280_enable(client, false);
+	}
+
+	return ret;
+}
+
+static int da280_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+
+	return da280_enable(client, false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int da280_suspend(struct device *dev)
+{
+	return da280_enable(to_i2c_client(dev), false);
+}
+
+static int da280_resume(struct device *dev)
+{
+	return da280_enable(to_i2c_client(dev), true);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);
+
+static const struct i2c_device_id da280_i2c_id[] = {
+	{ "da226", da226 },
+	{ "da280", da280 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
+
+static struct i2c_driver da280_driver = {
+	.driver = {
+		.name = "da280",
+		.pm = &da280_pm_ops,
+	},
+	.probe		= da280_probe,
+	.remove		= da280_remove,
+	.id_table	= da280_i2c_id,
+};
+
+module_i2c_driver(da280_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/da311.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/da311.c
--- linux-libre-4.9-gnu/drivers/iio/accel/da311.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/da311.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,305 @@
+/**
+ * IIO driver for the MiraMEMS DA311 3-axis accelerometer
+ *
+ * Copyright (c) 2016 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (c) 2011-2013 MiraMEMS Sensing Technology Co., 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.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/byteorder/generic.h>
+
+#define DA311_CHIP_ID			0x13
+
+/*
+ * Note register addressed go from 0 - 0x3f and then wrap.
+ * For some reason there are 2 banks with 0 - 0x3f addresses,
+ * rather then a single 0-0x7f bank.
+ */
+
+/* Bank 0 regs */
+#define DA311_REG_BANK			0x0000
+#define DA311_REG_LDO_REG		0x0006
+#define DA311_REG_CHIP_ID		0x000f
+#define DA311_REG_TEMP_CFG_REG		0x001f
+#define DA311_REG_CTRL_REG1		0x0020
+#define DA311_REG_CTRL_REG3		0x0022
+#define DA311_REG_CTRL_REG4		0x0023
+#define DA311_REG_CTRL_REG5		0x0024
+#define DA311_REG_CTRL_REG6		0x0025
+#define DA311_REG_STATUS_REG		0x0027
+#define DA311_REG_OUT_X_L		0x0028
+#define DA311_REG_OUT_X_H		0x0029
+#define DA311_REG_OUT_Y_L		0x002a
+#define DA311_REG_OUT_Y_H		0x002b
+#define DA311_REG_OUT_Z_L		0x002c
+#define DA311_REG_OUT_Z_H		0x002d
+#define DA311_REG_INT1_CFG		0x0030
+#define DA311_REG_INT1_SRC		0x0031
+#define DA311_REG_INT1_THS		0x0032
+#define DA311_REG_INT1_DURATION		0x0033
+#define DA311_REG_INT2_CFG		0x0034
+#define DA311_REG_INT2_SRC		0x0035
+#define DA311_REG_INT2_THS		0x0036
+#define DA311_REG_INT2_DURATION		0x0037
+#define DA311_REG_CLICK_CFG		0x0038
+#define DA311_REG_CLICK_SRC		0x0039
+#define DA311_REG_CLICK_THS		0x003a
+#define DA311_REG_TIME_LIMIT		0x003b
+#define DA311_REG_TIME_LATENCY		0x003c
+#define DA311_REG_TIME_WINDOW		0x003d
+
+/* Bank 1 regs */
+#define DA311_REG_SOFT_RESET		0x0105
+#define DA311_REG_OTP_XOFF_L		0x0110
+#define DA311_REG_OTP_XOFF_H		0x0111
+#define DA311_REG_OTP_YOFF_L		0x0112
+#define DA311_REG_OTP_YOFF_H		0x0113
+#define DA311_REG_OTP_ZOFF_L		0x0114
+#define DA311_REG_OTP_ZOFF_H		0x0115
+#define DA311_REG_OTP_XSO		0x0116
+#define DA311_REG_OTP_YSO		0x0117
+#define DA311_REG_OTP_ZSO		0x0118
+#define DA311_REG_OTP_TRIM_OSC		0x011b
+#define DA311_REG_LPF_ABSOLUTE		0x011c
+#define DA311_REG_TEMP_OFF1		0x0127
+#define DA311_REG_TEMP_OFF2		0x0128
+#define DA311_REG_TEMP_OFF3		0x0129
+#define DA311_REG_OTP_TRIM_THERM_H	0x011a
+
+/*
+ * a value of + or -1024 corresponds to + or - 1G
+ * scale = 9.81 / 1024 = 0.009580078
+ */
+
+static const int da311_nscale = 9580078;
+
+#define DA311_CHANNEL(reg, axis) {	\
+	.type = IIO_ACCEL,	\
+	.address = reg,	\
+	.modified = 1,	\
+	.channel2 = IIO_MOD_##axis,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec da311_channels[] = {
+	/* | 0x80 comes from the android driver */
+	DA311_CHANNEL(DA311_REG_OUT_X_L | 0x80, X),
+	DA311_CHANNEL(DA311_REG_OUT_Y_L | 0x80, Y),
+	DA311_CHANNEL(DA311_REG_OUT_Z_L | 0x80, Z),
+};
+
+struct da311_data {
+	struct i2c_client *client;
+};
+
+static int da311_register_mask_write(struct i2c_client *client, u16 addr,
+				     u8 mask, u8 data)
+{
+	int ret;
+	u8 tmp_data = 0;
+
+	if (addr & 0xff00) {
+		/* Select bank 1 */
+		ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x01);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (mask != 0xff) {
+		ret = i2c_smbus_read_byte_data(client, addr);
+		if (ret < 0)
+			return ret;
+		tmp_data = ret;
+	}
+
+	tmp_data &= ~mask;
+	tmp_data |= data & mask;
+	ret = i2c_smbus_write_byte_data(client, addr & 0xff, tmp_data);
+	if (ret < 0)
+		return ret;
+
+	if (addr & 0xff00) {
+		/* Back to bank 0 */
+		ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x00);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* Init sequence taken from the android driver */
+static int da311_reset(struct i2c_client *client)
+{
+	const struct {
+		u16 addr;
+		u8 mask;
+		u8 data;
+	} init_data[] = {
+		{ DA311_REG_TEMP_CFG_REG,       0xff,   0x08 },
+		{ DA311_REG_CTRL_REG5,          0xff,   0x80 },
+		{ DA311_REG_CTRL_REG4,          0x30,   0x00 },
+		{ DA311_REG_CTRL_REG1,          0xff,   0x6f },
+		{ DA311_REG_TEMP_CFG_REG,       0xff,   0x88 },
+		{ DA311_REG_LDO_REG,            0xff,   0x02 },
+		{ DA311_REG_OTP_TRIM_OSC,       0xff,   0x27 },
+		{ DA311_REG_LPF_ABSOLUTE,       0xff,   0x30 },
+		{ DA311_REG_TEMP_OFF1,          0xff,   0x3f },
+		{ DA311_REG_TEMP_OFF2,          0xff,   0xff },
+		{ DA311_REG_TEMP_OFF3,          0xff,   0x0f },
+	};
+	int i, ret;
+
+	/* Reset */
+	ret = da311_register_mask_write(client, DA311_REG_SOFT_RESET,
+					0xff, 0xaa);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(init_data); i++) {
+		ret = da311_register_mask_write(client,
+						init_data[i].addr,
+						init_data[i].mask,
+						init_data[i].data);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int da311_enable(struct i2c_client *client, bool enable)
+{
+	u8 data = enable ? 0x00 : 0x20;
+
+	return da311_register_mask_write(client, DA311_REG_TEMP_CFG_REG,
+					 0x20, data);
+}
+
+static int da311_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct da311_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = i2c_smbus_read_word_data(data->client, chan->address);
+		if (ret < 0)
+			return ret;
+		/*
+		 * Values are 12 bits, stored as 16 bits with the 4
+		 * least significant bits always 0.
+		 */
+		*val = (short)ret >> 4;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = da311_nscale;
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info da311_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= da311_read_raw,
+};
+
+static int da311_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct da311_data *data;
+
+	ret = i2c_smbus_read_byte_data(client, DA311_REG_CHIP_ID);
+	if (ret != DA311_CHIP_ID)
+		return (ret < 0) ? ret : -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &da311_info;
+	indio_dev->name = "da311";
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = da311_channels;
+	indio_dev->num_channels = ARRAY_SIZE(da311_channels);
+
+	ret = da311_reset(client);
+	if (ret < 0)
+		return ret;
+
+	ret = da311_enable(client, true);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "device_register failed\n");
+		da311_enable(client, false);
+	}
+
+	return ret;
+}
+
+static int da311_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+
+	return da311_enable(client, false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int da311_suspend(struct device *dev)
+{
+	return da311_enable(to_i2c_client(dev), false);
+}
+
+static int da311_resume(struct device *dev)
+{
+	return da311_enable(to_i2c_client(dev), true);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume);
+
+static const struct i2c_device_id da311_i2c_id[] = {
+	{"da311", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, da311_i2c_id);
+
+static struct i2c_driver da311_driver = {
+	.driver = {
+		.name = "da311",
+		.pm = &da311_pm_ops,
+	},
+	.probe		= da311_probe,
+	.remove		= da311_remove,
+	.id_table	= da311_i2c_id,
+};
+
+module_i2c_driver(da311_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("MiraMEMS DA311 3-Axis Accelerometer driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/dmard10.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/dmard10.c
--- linux-libre-4.9-gnu/drivers/iio/accel/dmard10.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/dmard10.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,266 @@
+/**
+ * IIO driver for the 3-axis accelerometer Domintech ARD10.
+ *
+ * Copyright (c) 2016 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (c) 2012 Domintech Technology Co., 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.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/byteorder/generic.h>
+
+#define DMARD10_REG_ACTR			0x00
+#define DMARD10_REG_AFEM			0x0c
+#define DMARD10_REG_STADR			0x12
+#define DMARD10_REG_STAINT			0x1c
+#define DMARD10_REG_MISC2			0x1f
+#define DMARD10_REG_PD				0x21
+
+#define DMARD10_MODE_OFF			0x00
+#define DMARD10_MODE_STANDBY			0x02
+#define DMARD10_MODE_ACTIVE			0x06
+#define DMARD10_MODE_READ_OTP			0x12
+#define DMARD10_MODE_RESET_DATA_PATH		0x82
+
+/* AFEN set 1, ATM[2:0]=b'000 (normal), EN_Z/Y/X/T=1 */
+#define DMARD10_VALUE_AFEM_AFEN_NORMAL		0x8f
+/* ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ) */
+#define DMARD10_VALUE_CKSEL_ODR_100_204		0x74
+/* INTC[6:5]=b'00 */
+#define DMARD10_VALUE_INTC			0x00
+/* TAP1/TAP2 Average 2 */
+#define DMARD10_VALUE_TAPNS_AVE_2		0x11
+
+#define DMARD10_VALUE_STADR			0x55
+#define DMARD10_VALUE_STAINT			0xaa
+#define DMARD10_VALUE_MISC2_OSCA_EN		0x08
+#define DMARD10_VALUE_PD_RST			0x52
+
+/* Offsets into the buffer read in dmard10_read_raw() */
+#define DMARD10_X_OFFSET			1
+#define DMARD10_Y_OFFSET			2
+#define DMARD10_Z_OFFSET			3
+
+/*
+ * a value of + or -128 corresponds to + or - 1G
+ * scale = 9.81 / 128 = 0.076640625
+ */
+
+static const int dmard10_nscale = 76640625;
+
+#define DMARD10_CHANNEL(reg, axis) {	\
+	.type = IIO_ACCEL,	\
+	.address = reg,	\
+	.modified = 1,	\
+	.channel2 = IIO_MOD_##axis,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec dmard10_channels[] = {
+	DMARD10_CHANNEL(DMARD10_X_OFFSET, X),
+	DMARD10_CHANNEL(DMARD10_Y_OFFSET, Y),
+	DMARD10_CHANNEL(DMARD10_Z_OFFSET, Z),
+};
+
+struct dmard10_data {
+	struct i2c_client *client;
+};
+
+/* Init sequence taken from the android driver */
+static int dmard10_reset(struct i2c_client *client)
+{
+	unsigned char buffer[7];
+	int ret;
+
+	/* 1. Powerdown reset */
+	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_PD,
+						DMARD10_VALUE_PD_RST);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * 2. ACTR => Standby mode => Download OTP to parameter reg =>
+	 *    Standby mode => Reset data path => Standby mode
+	 */
+	buffer[0] = DMARD10_REG_ACTR;
+	buffer[1] = DMARD10_MODE_STANDBY;
+	buffer[2] = DMARD10_MODE_READ_OTP;
+	buffer[3] = DMARD10_MODE_STANDBY;
+	buffer[4] = DMARD10_MODE_RESET_DATA_PATH;
+	buffer[5] = DMARD10_MODE_STANDBY;
+	ret = i2c_master_send(client, buffer, 6);
+	if (ret < 0)
+		return ret;
+
+	/* 3. OSCA_EN = 1, TSTO = b'000 (INT1 = normal, TEST0 = normal) */
+	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_MISC2,
+						DMARD10_VALUE_MISC2_OSCA_EN);
+	if (ret < 0)
+		return ret;
+
+	/* 4. AFEN = 1 (AFE will powerdown after ADC) */
+	buffer[0] = DMARD10_REG_AFEM;
+	buffer[1] = DMARD10_VALUE_AFEM_AFEN_NORMAL;
+	buffer[2] = DMARD10_VALUE_CKSEL_ODR_100_204;
+	buffer[3] = DMARD10_VALUE_INTC;
+	buffer[4] = DMARD10_VALUE_TAPNS_AVE_2;
+	buffer[5] = 0x00; /* DLYC, no delay timing */
+	buffer[6] = 0x07; /* INTD=1 push-pull, INTA=1 active high, AUTOT=1 */
+	ret = i2c_master_send(client, buffer, 7);
+	if (ret < 0)
+		return ret;
+
+	/* 5. Activation mode */
+	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_ACTR,
+						DMARD10_MODE_ACTIVE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* Shutdown sequence taken from the android driver */
+static int dmard10_shutdown(struct i2c_client *client)
+{
+	unsigned char buffer[3];
+
+	buffer[0] = DMARD10_REG_ACTR;
+	buffer[1] = DMARD10_MODE_STANDBY;
+	buffer[2] = DMARD10_MODE_OFF;
+
+	return i2c_master_send(client, buffer, 3);
+}
+
+static int dmard10_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct dmard10_data *data = iio_priv(indio_dev);
+	__le16 buf[4];
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		/*
+		 * Read 8 bytes starting at the REG_STADR register, trying to
+		 * read the individual X, Y, Z registers will always read 0.
+		 */
+		ret = i2c_smbus_read_i2c_block_data(data->client,
+						    DMARD10_REG_STADR,
+						    sizeof(buf), (u8 *)buf);
+		if (ret < 0)
+			return ret;
+		ret = le16_to_cpu(buf[chan->address]);
+		*val = sign_extend32(ret, 12);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = dmard10_nscale;
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info dmard10_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= dmard10_read_raw,
+};
+
+static int dmard10_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct dmard10_data *data;
+
+	/* These 2 registers have special POR reset values used for id */
+	ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STADR);
+	if (ret != DMARD10_VALUE_STADR)
+		return (ret < 0) ? ret : -ENODEV;
+
+	ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STAINT);
+	if (ret != DMARD10_VALUE_STAINT)
+		return (ret < 0) ? ret : -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev) {
+		dev_err(&client->dev, "iio allocation failed!\n");
+		return -ENOMEM;
+	}
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &dmard10_info;
+	indio_dev->name = "dmard10";
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = dmard10_channels;
+	indio_dev->num_channels = ARRAY_SIZE(dmard10_channels);
+
+	ret = dmard10_reset(client);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "device_register failed\n");
+		dmard10_shutdown(client);
+	}
+
+	return ret;
+}
+
+static int dmard10_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+
+	return dmard10_shutdown(client);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int dmard10_suspend(struct device *dev)
+{
+	return dmard10_shutdown(to_i2c_client(dev));
+}
+
+static int dmard10_resume(struct device *dev)
+{
+	return dmard10_reset(to_i2c_client(dev));
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend, dmard10_resume);
+
+static const struct i2c_device_id dmard10_i2c_id[] = {
+	{"dmard10", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id);
+
+static struct i2c_driver dmard10_driver = {
+	.driver = {
+		.name = "dmard10",
+		.pm = &dmard10_pm_ops,
+	},
+	.probe		= dmard10_probe,
+	.remove		= dmard10_remove,
+	.id_table	= dmard10_i2c_id,
+};
+
+module_i2c_driver(dmard10_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Domintech ARD10 3-Axis Accelerometer driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/accel/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/accel/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -52,6 +52,26 @@ config BMC150_ACCEL_SPI
 	tristate
 	select REGMAP_SPI
 
+config DA280
+	tristate "MiraMEMS DA280 3-axis 14-bit digital accelerometer driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the MiraMEMS DA280 3-axis 14-bit
+	  digital accelerometer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called da280.
+
+config DA311
+	tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the MiraMEMS DA311 3-axis 12-bit
+	  digital accelerometer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called da311.
+
 config DMARD06
 	tristate "Domintech DMARD06 Digital Accelerometer Driver"
 	depends on OF || COMPILE_TEST
@@ -73,6 +93,16 @@ config DMARD09
 	  Choosing M will build the driver as a module. If so, the module
 	  will be called dmard09.
 
+config DMARD10
+	tristate "Domintech DMARD10 3-axis Accelerometer Driver"
+	depends on I2C
+	help
+	  Say yes here to get support for the Domintech DMARD10 3-axis
+	  accelerometer.
+
+	  Choosing M will build the driver as a module. If so, the module
+	  will be called dmard10.
+
 config HID_SENSOR_ACCEL_3D
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
@@ -97,7 +127,8 @@ config IIO_ST_ACCEL_3AXIS
 	help
 	  Say yes here to build support for STMicroelectronics accelerometers:
 	  LSM303DLH, LSM303DLHC, LIS3DH, LSM330D, LSM330DL, LSM330DLC,
-	  LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL.
+	  LIS331DLH, LSM303DL, LSM303DLM, LSM330, LIS2DH12, H3LIS331DL,
+	  LNG2DM
 
 	  This driver can also be built as a module. If so, these modules
 	  will be created:
@@ -273,6 +304,18 @@ config MXC6255
 	  To compile this driver as a module, choose M here: the module will be
 	  called mxc6255.
 
+config SCA3000
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	depends on SPI
+	tristate "VTI SCA3000 series accelerometers"
+	help
+	  Say Y here to build support for the VTI SCA3000 series of SPI
+	  accelerometers. These devices use a hardware ring buffer.
+
+	  To compile this driver as a module, say M here: the module will be
+	  called sca3000.
+
 config STK8312
 	tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
 	depends on I2C
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/accel/Makefile
--- linux-libre-4.9-gnu/drivers/iio/accel/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -8,8 +8,11 @@ obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
 obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
 obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
+obj-$(CONFIG_DA280)	+= da280.o
+obj-$(CONFIG_DA311)	+= da311.o
 obj-$(CONFIG_DMARD06)	+= dmard06.o
 obj-$(CONFIG_DMARD09)	+= dmard09.o
+obj-$(CONFIG_DMARD10)	+= dmard10.o
 obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
 obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
 obj-$(CONFIG_KXSD9)	+= kxsd9.o
@@ -32,6 +35,8 @@ obj-$(CONFIG_MMA9553)		+= mma9553.o
 obj-$(CONFIG_MXC4005)		+= mxc4005.o
 obj-$(CONFIG_MXC6255)		+= mxc6255.o
 
+obj-$(CONFIG_SCA3000)		+= sca3000.o
+
 obj-$(CONFIG_STK8312)		+= stk8312.o
 obj-$(CONFIG_STK8BA50)		+= stk8ba50.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/mma7660.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/mma7660.c
--- linux-libre-4.9-gnu/drivers/iio/accel/mma7660.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/mma7660.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@
 
 #define MMA7660_SCALE_AVAIL	"0.467142857"
 
-const int mma7660_nscale = 467142857;
+static const int mma7660_nscale = 467142857;
 
 #define MMA7660_CHANNEL(reg, axis) {	\
 	.type = IIO_ACCEL,	\
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/mma8452.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/mma8452.c
--- linux-libre-4.9-gnu/drivers/iio/accel/mma8452.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/mma8452.c	2017-02-12 16:03:20.000000000 -0500
@@ -459,12 +459,14 @@ static int mma8452_read_raw(struct iio_d
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		if (iio_buffer_enabled(indio_dev))
-			return -EBUSY;
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
 
 		mutex_lock(&data->lock);
 		ret = mma8452_read(data, buffer);
 		mutex_unlock(&data->lock);
+		iio_device_release_direct_mode(indio_dev);
 		if (ret < 0)
 			return ret;
 
@@ -664,37 +666,46 @@ static int mma8452_write_raw(struct iio_
 	struct mma8452_data *data = iio_priv(indio_dev);
 	int i, ret;
 
-	if (iio_buffer_enabled(indio_dev))
-		return -EBUSY;
+	ret = iio_device_claim_direct_mode(indio_dev);
+	if (ret)
+		return ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		i = mma8452_get_samp_freq_index(data, val, val2);
-		if (i < 0)
-			return i;
-
+		if (i < 0) {
+			ret = i;
+			break;
+		}
 		data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK;
 		data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT;
 
-		return mma8452_change_config(data, MMA8452_CTRL_REG1,
-					     data->ctrl_reg1);
+		ret = mma8452_change_config(data, MMA8452_CTRL_REG1,
+					    data->ctrl_reg1);
+		break;
 	case IIO_CHAN_INFO_SCALE:
 		i = mma8452_get_scale_index(data, val, val2);
-		if (i < 0)
-			return i;
+		if (i < 0) {
+			ret = i;
+			break;
+		}
 
 		data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK;
 		data->data_cfg |= i;
 
-		return mma8452_change_config(data, MMA8452_DATA_CFG,
-					     data->data_cfg);
+		ret = mma8452_change_config(data, MMA8452_DATA_CFG,
+					    data->data_cfg);
+		break;
 	case IIO_CHAN_INFO_CALIBBIAS:
-		if (val < -128 || val > 127)
-			return -EINVAL;
+		if (val < -128 || val > 127) {
+			ret = -EINVAL;
+			break;
+		}
 
-		return mma8452_change_config(data,
-					     MMA8452_OFF_X + chan->scan_index,
-					     val);
+		ret = mma8452_change_config(data,
+					    MMA8452_OFF_X + chan->scan_index,
+					    val);
+		break;
 
 	case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
 		if (val == 0 && val2 == 0) {
@@ -703,23 +714,30 @@ static int mma8452_write_raw(struct iio_
 			data->data_cfg |= MMA8452_DATA_CFG_HPF_MASK;
 			ret = mma8452_set_hp_filter_frequency(data, val, val2);
 			if (ret < 0)
-				return ret;
+				break;
 		}
 
-		return mma8452_change_config(data, MMA8452_DATA_CFG,
+		ret = mma8452_change_config(data, MMA8452_DATA_CFG,
 					     data->data_cfg);
+		break;
 
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
 		ret = mma8452_get_odr_index(data);
 
 		for (i = 0; i < ARRAY_SIZE(mma8452_os_ratio); i++) {
-			if (mma8452_os_ratio[i][ret] == val)
-				return mma8452_set_power_mode(data, i);
+			if (mma8452_os_ratio[i][ret] == val) {
+				ret = mma8452_set_power_mode(data, i);
+				break;
+			}
 		}
-
+		break;
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
+		break;
 	}
+
+	iio_device_release_direct_mode(indio_dev);
+	return ret;
 }
 
 static int mma8452_read_thresh(struct iio_dev *indio_dev,
@@ -1347,20 +1365,9 @@ static int mma8452_data_rdy_trigger_set_
 	return mma8452_change_config(data, MMA8452_CTRL_REG4, reg);
 }
 
-static int mma8452_validate_device(struct iio_trigger *trig,
-				   struct iio_dev *indio_dev)
-{
-	struct iio_dev *indio = iio_trigger_get_drvdata(trig);
-
-	if (indio != indio_dev)
-		return -EINVAL;
-
-	return 0;
-}
-
 static const struct iio_trigger_ops mma8452_trigger_ops = {
 	.set_trigger_state = mma8452_data_rdy_trigger_set_state,
-	.validate_device = mma8452_validate_device,
+	.validate_device = iio_trigger_validate_own_device,
 	.owner = THIS_MODULE,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/sca3000.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/sca3000.c
--- linux-libre-4.9-gnu/drivers/iio/accel/sca3000.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/sca3000.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1576 @@
+/*
+ * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org>
+ *
+ * See industrialio/accels/sca3000.h for comments.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+
+#define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02)
+#define SCA3000_READ_REG(a) ((a) << 2)
+
+#define SCA3000_REG_REVID_ADDR				0x00
+#define   SCA3000_REG_REVID_MAJOR_MASK			GENMASK(8, 4)
+#define   SCA3000_REG_REVID_MINOR_MASK			GENMASK(3, 0)
+
+#define SCA3000_REG_STATUS_ADDR				0x02
+#define   SCA3000_LOCKED				BIT(5)
+#define   SCA3000_EEPROM_CS_ERROR			BIT(1)
+#define   SCA3000_SPI_FRAME_ERROR			BIT(0)
+ 
+/* All reads done using register decrement so no need to directly access LSBs */
+#define SCA3000_REG_X_MSB_ADDR				0x05
+#define SCA3000_REG_Y_MSB_ADDR				0x07
+#define SCA3000_REG_Z_MSB_ADDR				0x09
+
+#define SCA3000_REG_RING_OUT_ADDR			0x0f
+
+/* Temp read untested - the e05 doesn't have the sensor */
+#define SCA3000_REG_TEMP_MSB_ADDR			0x13
+
+#define SCA3000_REG_MODE_ADDR				0x14
+#define SCA3000_MODE_PROT_MASK				0x28
+#define   SCA3000_REG_MODE_RING_BUF_ENABLE		BIT(7)
+#define   SCA3000_REG_MODE_RING_BUF_8BIT		BIT(6)
+
+/*
+ * Free fall detection triggers an interrupt if the acceleration
+ * is below a threshold for equivalent of 25cm drop
+ */
+#define   SCA3000_REG_MODE_FREE_FALL_DETECT		BIT(4)
+#define   SCA3000_REG_MODE_MEAS_MODE_NORMAL		0x00
+#define   SCA3000_REG_MODE_MEAS_MODE_OP_1		0x01
+#define   SCA3000_REG_MODE_MEAS_MODE_OP_2		0x02
+
+/*
+ * In motion detection mode the accelerations are band pass filtered
+ * (approx 1 - 25Hz) and then a programmable threshold used to trigger
+ * and interrupt.
+ */
+#define   SCA3000_REG_MODE_MEAS_MODE_MOT_DET		0x03
+#define   SCA3000_REG_MODE_MODE_MASK			0x03
+
+#define SCA3000_REG_BUF_COUNT_ADDR			0x15
+
+#define SCA3000_REG_INT_STATUS_ADDR			0x16
+#define   SCA3000_REG_INT_STATUS_THREE_QUARTERS		BIT(7)
+#define   SCA3000_REG_INT_STATUS_HALF			BIT(6)
+	
+#define SCA3000_INT_STATUS_FREE_FALL			BIT(3)
+#define SCA3000_INT_STATUS_Y_TRIGGER			BIT(2)
+#define SCA3000_INT_STATUS_X_TRIGGER			BIT(1)
+#define SCA3000_INT_STATUS_Z_TRIGGER			BIT(0)
+
+/* Used to allow access to multiplexed registers */
+#define SCA3000_REG_CTRL_SEL_ADDR			0x18
+/* Only available for SCA3000-D03 and SCA3000-D01 */
+#define   SCA3000_REG_CTRL_SEL_I2C_DISABLE		0x01
+#define   SCA3000_REG_CTRL_SEL_MD_CTRL			0x02
+#define   SCA3000_REG_CTRL_SEL_MD_Y_TH			0x03
+#define   SCA3000_REG_CTRL_SEL_MD_X_TH			0x04
+#define   SCA3000_REG_CTRL_SEL_MD_Z_TH			0x05
+/*
+ * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device
+ * will not function
+ */
+#define   SCA3000_REG_CTRL_SEL_OUT_CTRL			0x0B
+
+#define     SCA3000_REG_OUT_CTRL_PROT_MASK		0xE0
+#define     SCA3000_REG_OUT_CTRL_BUF_X_EN		0x10
+#define     SCA3000_REG_OUT_CTRL_BUF_Y_EN		0x08
+#define     SCA3000_REG_OUT_CTRL_BUF_Z_EN		0x04
+#define     SCA3000_REG_OUT_CTRL_BUF_DIV_MASK		0x03
+#define     SCA3000_REG_OUT_CTRL_BUF_DIV_4		0x02
+#define     SCA3000_REG_OUT_CTRL_BUF_DIV_2		0x01
+
+
+/*
+ * Control which motion detector interrupts are on.
+ * For now only OR combinations are supported.
+ */
+#define SCA3000_MD_CTRL_PROT_MASK			0xC0
+#define SCA3000_MD_CTRL_OR_Y				BIT(0)
+#define SCA3000_MD_CTRL_OR_X				BIT(1)
+#define SCA3000_MD_CTRL_OR_Z				BIT(2)
+/* Currently unsupported */
+#define SCA3000_MD_CTRL_AND_Y				BIT(3)
+#define SCA3000_MD_CTRL_AND_X				BIT(4)
+#define SAC3000_MD_CTRL_AND_Z				BIT(5)
+
+/*
+ * Some control registers of complex access methods requiring this register to
+ * be used to remove a lock.
+ */
+#define SCA3000_REG_UNLOCK_ADDR				0x1e
+
+#define SCA3000_REG_INT_MASK_ADDR			0x21
+#define   SCA3000_REG_INT_MASK_PROT_MASK		0x1C
+ 
+#define   SCA3000_REG_INT_MASK_RING_THREE_QUARTER	BIT(7)
+#define   SCA3000_REG_INT_MASK_RING_HALF		BIT(6)
+
+#define SCA3000_REG_INT_MASK_ALL_INTS			0x02
+#define SCA3000_REG_INT_MASK_ACTIVE_HIGH		0x01
+#define SCA3000_REG_INT_MASK_ACTIVE_LOW			0x00
+/* Values of multiplexed registers (write to ctrl_data after select) */
+#define SCA3000_REG_CTRL_DATA_ADDR			0x22
+
+/*
+ * Measurement modes available on some sca3000 series chips. Code assumes others
+ * may become available in the future.
+ *
+ * Bypass - Bypass the low-pass filter in the signal channel so as to increase
+ *          signal bandwidth.
+ *
+ * Narrow - Narrow low-pass filtering of the signal channel and half output
+ *          data rate by decimation.
+ *
+ * Wide - Widen low-pass filtering of signal channel to increase bandwidth
+ */
+#define SCA3000_OP_MODE_BYPASS				0x01
+#define SCA3000_OP_MODE_NARROW				0x02
+#define SCA3000_OP_MODE_WIDE				0x04
+#define SCA3000_MAX_TX 6
+#define SCA3000_MAX_RX 2
+
+/**
+ * struct sca3000_state - device instance state information
+ * @us:			the associated spi device
+ * @info:			chip variant information
+ * @last_timestamp:		the timestamp of the last event
+ * @mo_det_use_count:		reference counter for the motion detection unit
+ * @lock:			lock used to protect elements of sca3000_state
+ *				and the underlying device state.
+ * @tx:			dma-able transmit buffer
+ * @rx:			dma-able receive buffer
+ **/
+struct sca3000_state {
+	struct spi_device		*us;
+	const struct sca3000_chip_info	*info;
+	s64				last_timestamp;
+	int				mo_det_use_count;
+	struct mutex			lock;
+	/* Can these share a cacheline ? */
+	u8				rx[384] ____cacheline_aligned;
+	u8				tx[6] ____cacheline_aligned;
+};
+
+/**
+ * struct sca3000_chip_info - model dependent parameters
+ * @scale:			scale * 10^-6
+ * @temp_output:		some devices have temperature sensors.
+ * @measurement_mode_freq:	normal mode sampling frequency
+ * @measurement_mode_3db_freq:	3db cutoff frequency of the low pass filter for
+ * the normal measurement mode.
+ * @option_mode_1:		first optional mode. Not all models have one
+ * @option_mode_1_freq:		option mode 1 sampling frequency
+ * @option_mode_1_3db_freq:	3db cutoff frequency of the low pass filter for
+ * the first option mode.
+ * @option_mode_2:		second optional mode. Not all chips have one
+ * @option_mode_2_freq:		option mode 2 sampling frequency
+ * @option_mode_2_3db_freq:	3db cutoff frequency of the low pass filter for
+ * the second option mode.
+ * @mod_det_mult_xz:		Bit wise multipliers to calculate the threshold
+ * for motion detection in the x and z axis.
+ * @mod_det_mult_y:		Bit wise multipliers to calculate the threshold
+ * for motion detection in the y axis.
+ *
+ * This structure is used to hold information about the functionality of a given
+ * sca3000 variant.
+ **/
+struct sca3000_chip_info {
+	unsigned int		scale;
+	bool			temp_output;
+	int			measurement_mode_freq;
+	int			measurement_mode_3db_freq;
+	int			option_mode_1;
+	int			option_mode_1_freq;
+	int			option_mode_1_3db_freq;
+	int			option_mode_2;
+	int			option_mode_2_freq;
+	int			option_mode_2_3db_freq;
+	int			mot_det_mult_xz[6];
+	int			mot_det_mult_y[7];
+};
+
+enum sca3000_variant {
+	d01,
+	e02,
+	e04,
+	e05,
+};
+
+/*
+ * Note where option modes are not defined, the chip simply does not
+ * support any.
+ * Other chips in the sca3000 series use i2c and are not included here.
+ *
+ * Some of these devices are only listed in the family data sheet and
+ * do not actually appear to be available.
+ */
+static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = {
+	[d01] = {
+		.scale = 7357,
+		.temp_output = true,
+		.measurement_mode_freq = 250,
+		.measurement_mode_3db_freq = 45,
+		.option_mode_1 = SCA3000_OP_MODE_BYPASS,
+		.option_mode_1_freq = 250,
+		.option_mode_1_3db_freq = 70,
+		.mot_det_mult_xz = {50, 100, 200, 350, 650, 1300},
+		.mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750},
+	},
+	[e02] = {
+		.scale = 9810,
+		.measurement_mode_freq = 125,
+		.measurement_mode_3db_freq = 40,
+		.option_mode_1 = SCA3000_OP_MODE_NARROW,
+		.option_mode_1_freq = 63,
+		.option_mode_1_3db_freq = 11,
+		.mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050},
+		.mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700},
+	},
+	[e04] = {
+		.scale = 19620,
+		.measurement_mode_freq = 100,
+		.measurement_mode_3db_freq = 38,
+		.option_mode_1 = SCA3000_OP_MODE_NARROW,
+		.option_mode_1_freq = 50,
+		.option_mode_1_3db_freq = 9,
+		.option_mode_2 = SCA3000_OP_MODE_WIDE,
+		.option_mode_2_freq = 400,
+		.option_mode_2_3db_freq = 70,
+		.mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100},
+		.mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000},
+	},
+	[e05] = {
+		.scale = 61313,
+		.measurement_mode_freq = 200,
+		.measurement_mode_3db_freq = 60,
+		.option_mode_1 = SCA3000_OP_MODE_NARROW,
+		.option_mode_1_freq = 50,
+		.option_mode_1_3db_freq = 9,
+		.option_mode_2 = SCA3000_OP_MODE_WIDE,
+		.option_mode_2_freq = 400,
+		.option_mode_2_3db_freq = 75,
+		.mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900},
+		.mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600},
+	},
+};
+
+static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val)
+{
+	st->tx[0] = SCA3000_WRITE_REG(address);
+	st->tx[1] = val;
+	return spi_write(st->us, st->tx, 2);
+}
+
+static int sca3000_read_data_short(struct sca3000_state *st,
+				   u8 reg_address_high,
+				   int len)
+{
+	struct spi_transfer xfer[2] = {
+		{
+			.len = 1,
+			.tx_buf = st->tx,
+		}, {
+			.len = len,
+			.rx_buf = st->rx,
+		}
+	};
+	st->tx[0] = SCA3000_READ_REG(reg_address_high);
+
+	return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
+}
+
+/**
+ * sca3000_reg_lock_on() - test if the ctrl register lock is on
+ * @st: Driver specific device instance data.
+ *
+ * Lock must be held.
+ **/
+static int sca3000_reg_lock_on(struct sca3000_state *st)
+{
+	int ret;
+
+	ret = sca3000_read_data_short(st, SCA3000_REG_STATUS_ADDR, 1);
+	if (ret < 0)
+		return ret;
+
+	return !(st->rx[0] & SCA3000_LOCKED);
+}
+
+/**
+ * __sca3000_unlock_reg_lock() - unlock the control registers
+ * @st: Driver specific device instance data.
+ *
+ * Note the device does not appear to support doing this in a single transfer.
+ * This should only ever be used as part of ctrl reg read.
+ * Lock must be held before calling this
+ */
+static int __sca3000_unlock_reg_lock(struct sca3000_state *st)
+{
+	struct spi_transfer xfer[3] = {
+		{
+			.len = 2,
+			.cs_change = 1,
+			.tx_buf = st->tx,
+		}, {
+			.len = 2,
+			.cs_change = 1,
+			.tx_buf = st->tx + 2,
+		}, {
+			.len = 2,
+			.tx_buf = st->tx + 4,
+		},
+	};
+	st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
+	st->tx[1] = 0x00;
+	st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
+	st->tx[3] = 0x50;
+	st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR);
+	st->tx[5] = 0xA0;
+
+	return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
+}
+
+/**
+ * sca3000_write_ctrl_reg() write to a lock protect ctrl register
+ * @st: Driver specific device instance data.
+ * @sel: selects which registers we wish to write to
+ * @val: the value to be written
+ *
+ * Certain control registers are protected against overwriting by the lock
+ * register and use a shared write address. This function allows writing of
+ * these registers.
+ * Lock must be held.
+ */
+static int sca3000_write_ctrl_reg(struct sca3000_state *st,
+				  u8 sel,
+				  uint8_t val)
+{
+	int ret;
+
+	ret = sca3000_reg_lock_on(st);
+	if (ret < 0)
+		goto error_ret;
+	if (ret) {
+		ret = __sca3000_unlock_reg_lock(st);
+		if (ret)
+			goto error_ret;
+	}
+
+	/* Set the control select register */
+	ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, sel);
+	if (ret)
+		goto error_ret;
+
+	/* Write the actual value into the register */
+	ret = sca3000_write_reg(st, SCA3000_REG_CTRL_DATA_ADDR, val);
+
+error_ret:
+	return ret;
+}
+
+/**
+ * sca3000_read_ctrl_reg() read from lock protected control register.
+ * @st: Driver specific device instance data.
+ * @ctrl_reg: Which ctrl register do we want to read.
+ *
+ * Lock must be held.
+ */
+static int sca3000_read_ctrl_reg(struct sca3000_state *st,
+				 u8 ctrl_reg)
+{
+	int ret;
+
+	ret = sca3000_reg_lock_on(st);
+	if (ret < 0)
+		goto error_ret;
+	if (ret) {
+		ret = __sca3000_unlock_reg_lock(st);
+		if (ret)
+			goto error_ret;
+	}
+	/* Set the control select register */
+	ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, ctrl_reg);
+	if (ret)
+		goto error_ret;
+	ret = sca3000_read_data_short(st, SCA3000_REG_CTRL_DATA_ADDR, 1);
+	if (ret)
+		goto error_ret;
+	return st->rx[0];
+error_ret:
+	return ret;
+}
+
+/**
+ * sca3000_show_rev() - sysfs interface to read the chip revision number
+ * @indio_dev: Device instance specific generic IIO data.
+ * Driver specific device instance data can be obtained via
+ * via iio_priv(indio_dev)
+ */
+static int sca3000_print_rev(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct sca3000_state *st = iio_priv(indio_dev);
+
+	mutex_lock(&st->lock);
+	ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1);
+	if (ret < 0)
+		goto error_ret;
+	dev_info(&indio_dev->dev,
+		 "sca3000 revision major=%lu, minor=%lu\n",
+		 st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK,
+		 st->rx[0] & SCA3000_REG_REVID_MINOR_MASK);
+error_ret:
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+static ssize_t
+sca3000_show_available_3db_freqs(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int len;
+
+	len = sprintf(buf, "%d", st->info->measurement_mode_3db_freq);
+	if (st->info->option_mode_1)
+		len += sprintf(buf + len, " %d",
+			       st->info->option_mode_1_3db_freq);
+	if (st->info->option_mode_2)
+		len += sprintf(buf + len, " %d",
+			       st->info->option_mode_2_3db_freq);
+	len += sprintf(buf + len, "\n");
+
+	return len;
+}
+
+static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available,
+		       S_IRUGO, sca3000_show_available_3db_freqs,
+		       NULL, 0);
+
+static const struct iio_event_spec sca3000_event = {
+	.type = IIO_EV_TYPE_MAG,
+	.dir = IIO_EV_DIR_RISING,
+	.mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE),
+};
+
+/*
+ * Note the hack in the number of bits to pretend we have 2 more than
+ * we do in the fifo.
+ */
+#define SCA3000_CHAN(index, mod)				\
+	{							\
+		.type = IIO_ACCEL,				\
+		.modified = 1,					\
+		.channel2 = mod,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |\
+			BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),\
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+		.address = index,				\
+		.scan_index = index,				\
+		.scan_type = {					\
+			.sign = 's',				\
+			.realbits = 13,				\
+			.storagebits = 16,			\
+			.shift = 3,				\
+			.endianness = IIO_BE,			\
+		},						\
+		.event_spec = &sca3000_event,			\
+		.num_event_specs = 1,				\
+	}
+
+static const struct iio_event_spec sca3000_freefall_event_spec = {
+	.type = IIO_EV_TYPE_MAG,
+	.dir = IIO_EV_DIR_FALLING,
+	.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
+		BIT(IIO_EV_INFO_PERIOD),
+};
+
+static const struct iio_chan_spec sca3000_channels[] = {
+	SCA3000_CHAN(0, IIO_MOD_X),
+	SCA3000_CHAN(1, IIO_MOD_Y),
+	SCA3000_CHAN(2, IIO_MOD_Z),
+	{
+		.type = IIO_ACCEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_X_AND_Y_AND_Z,
+		.scan_index = -1, /* Fake channel */
+		.event_spec = &sca3000_freefall_event_spec,
+		.num_event_specs = 1,
+	},
+};
+
+static const struct iio_chan_spec sca3000_channels_with_temp[] = {
+	SCA3000_CHAN(0, IIO_MOD_X),
+	SCA3000_CHAN(1, IIO_MOD_Y),
+	SCA3000_CHAN(2, IIO_MOD_Z),
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_OFFSET),
+		/* No buffer support */
+		.scan_index = -1,
+	},
+	{
+		.type = IIO_ACCEL,
+		.modified = 1,
+		.channel2 = IIO_MOD_X_AND_Y_AND_Z,
+		.scan_index = -1, /* Fake channel */
+		.event_spec = &sca3000_freefall_event_spec,
+		.num_event_specs = 1,
+	},
+};
+
+static u8 sca3000_addresses[3][3] = {
+	[0] = {SCA3000_REG_X_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_X_TH,
+	       SCA3000_MD_CTRL_OR_X},
+	[1] = {SCA3000_REG_Y_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Y_TH,
+	       SCA3000_MD_CTRL_OR_Y},
+	[2] = {SCA3000_REG_Z_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Z_TH,
+	       SCA3000_MD_CTRL_OR_Z},
+};
+
+/**
+ * __sca3000_get_base_freq() - obtain mode specific base frequency
+ * @st: Private driver specific device instance specific state.
+ * @info: chip type specific information.
+ * @base_freq: Base frequency for the current measurement mode.
+ *
+ * lock must be held
+ */
+static inline int __sca3000_get_base_freq(struct sca3000_state *st,
+					  const struct sca3000_chip_info *info,
+					  int *base_freq)
+{
+	int ret;
+
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		goto error_ret;
+	switch (SCA3000_REG_MODE_MODE_MASK & st->rx[0]) {
+	case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
+		*base_freq = info->measurement_mode_freq;
+		break;
+	case SCA3000_REG_MODE_MEAS_MODE_OP_1:
+		*base_freq = info->option_mode_1_freq;
+		break;
+	case SCA3000_REG_MODE_MEAS_MODE_OP_2:
+		*base_freq = info->option_mode_2_freq;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+error_ret:
+	return ret;
+}
+
+/**
+ * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ
+ * @st: Private driver specific device instance specific state.
+ * @val: The frequency read back.
+ *
+ * lock must be held
+ **/
+static int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val)
+{
+	int ret;
+
+	ret = __sca3000_get_base_freq(st, st->info, val);
+	if (ret)
+		return ret;
+
+	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
+	if (ret < 0)
+		return ret;
+
+	if (*val > 0) {
+		ret &= SCA3000_REG_OUT_CTRL_BUF_DIV_MASK;
+		switch (ret) {
+		case SCA3000_REG_OUT_CTRL_BUF_DIV_2:
+			*val /= 2;
+			break;
+		case SCA3000_REG_OUT_CTRL_BUF_DIV_4:
+			*val /= 4;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ
+ * @st: Private driver specific device instance specific state.
+ * @val: The frequency desired.
+ *
+ * lock must be held
+ */
+static int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val)
+{
+	int ret, base_freq, ctrlval;
+
+	ret = __sca3000_get_base_freq(st, st->info, &base_freq);
+	if (ret)
+		return ret;
+
+	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
+	if (ret < 0)
+		return ret;
+
+	ctrlval = ret & ~SCA3000_REG_OUT_CTRL_BUF_DIV_MASK;
+
+	if (val == base_freq / 2)
+		ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_2;
+	if (val == base_freq / 4)
+		ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_4;
+	else if (val != base_freq)
+		return -EINVAL;
+
+	return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
+				     ctrlval);
+}
+
+static int sca3000_read_3db_freq(struct sca3000_state *st, int *val)
+{
+	int ret;
+
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		return ret;
+
+	/* mask bottom 2 bits - only ones that are relevant */
+	st->rx[0] &= SCA3000_REG_MODE_MODE_MASK;
+	switch (st->rx[0]) {
+	case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
+		*val = st->info->measurement_mode_3db_freq;
+		return IIO_VAL_INT;
+	case SCA3000_REG_MODE_MEAS_MODE_MOT_DET:
+		return -EBUSY;
+	case SCA3000_REG_MODE_MEAS_MODE_OP_1:
+		*val = st->info->option_mode_1_3db_freq;
+		return IIO_VAL_INT;
+	case SCA3000_REG_MODE_MEAS_MODE_OP_2:
+		*val = st->info->option_mode_2_3db_freq;
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int sca3000_write_3db_freq(struct sca3000_state *st, int val)
+{
+	int ret;
+	int mode;
+
+	if (val == st->info->measurement_mode_3db_freq)
+		mode = SCA3000_REG_MODE_MEAS_MODE_NORMAL;
+	else if (st->info->option_mode_1 &&
+		 (val == st->info->option_mode_1_3db_freq))
+		mode = SCA3000_REG_MODE_MEAS_MODE_OP_1;
+	else if (st->info->option_mode_2 &&
+		 (val == st->info->option_mode_2_3db_freq))
+		mode = SCA3000_REG_MODE_MEAS_MODE_OP_2;
+	else
+		return -EINVAL;
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		return ret;
+
+	st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK;
+	st->rx[0] |= (mode & SCA3000_REG_MODE_MODE_MASK);
+
+	return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]);
+}
+
+static int sca3000_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val,
+			    int *val2,
+			    long mask)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret;
+	u8 address;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&st->lock);
+		if (chan->type == IIO_ACCEL) {
+			if (st->mo_det_use_count) {
+				mutex_unlock(&st->lock);
+				return -EBUSY;
+			}
+			address = sca3000_addresses[chan->address][0];
+			ret = sca3000_read_data_short(st, address, 2);
+			if (ret < 0) {
+				mutex_unlock(&st->lock);
+				return ret;
+			}
+			*val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF;
+			*val = ((*val) << (sizeof(*val) * 8 - 13)) >>
+				(sizeof(*val) * 8 - 13);
+		} else {
+			/* get the temperature when available */
+			ret = sca3000_read_data_short(st,
+						      SCA3000_REG_TEMP_MSB_ADDR,
+						      2);
+			if (ret < 0) {
+				mutex_unlock(&st->lock);
+				return ret;
+			}
+			*val = ((st->rx[0] & 0x3F) << 3) |
+			       ((st->rx[1] & 0xE0) >> 5);
+		}
+		mutex_unlock(&st->lock);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		if (chan->type == IIO_ACCEL)
+			*val2 = st->info->scale;
+		else /* temperature */
+			*val2 = 555556;
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = -214;
+		*val2 = 600000;
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		mutex_lock(&st->lock);
+		ret = sca3000_read_raw_samp_freq(st, val);
+		mutex_unlock(&st->lock);
+		return ret ? ret : IIO_VAL_INT;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		mutex_lock(&st->lock);
+		ret = sca3000_read_3db_freq(st, val);
+		mutex_unlock(&st->lock);
+		return ret;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int sca3000_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		if (val2)
+			return -EINVAL;
+		mutex_lock(&st->lock);
+		ret = sca3000_write_raw_samp_freq(st, val);
+		mutex_unlock(&st->lock);
+		return ret;
+	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+		if (val2)
+			return -EINVAL;
+		mutex_lock(&st->lock);
+		ret = sca3000_write_3db_freq(st, val);
+		mutex_unlock(&st->lock);
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * sca3000_read_av_freq() - sysfs function to get available frequencies
+ * @dev: Device structure for this device.
+ * @attr: Description of the attribute.
+ * @buf: Incoming string
+ *
+ * The later modes are only relevant to the ring buffer - and depend on current
+ * mode. Note that data sheet gives rather wide tolerances for these so integer
+ * division will give good enough answer and not all chips have them specified
+ * at all.
+ **/
+static ssize_t sca3000_read_av_freq(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int len = 0, ret, val;
+
+	mutex_lock(&st->lock);
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	val = st->rx[0];
+	mutex_unlock(&st->lock);
+	if (ret)
+		goto error_ret;
+
+	switch (val & SCA3000_REG_MODE_MODE_MASK) {
+	case SCA3000_REG_MODE_MEAS_MODE_NORMAL:
+		len += sprintf(buf + len, "%d %d %d\n",
+			       st->info->measurement_mode_freq,
+			       st->info->measurement_mode_freq / 2,
+			       st->info->measurement_mode_freq / 4);
+		break;
+	case SCA3000_REG_MODE_MEAS_MODE_OP_1:
+		len += sprintf(buf + len, "%d %d %d\n",
+			       st->info->option_mode_1_freq,
+			       st->info->option_mode_1_freq / 2,
+			       st->info->option_mode_1_freq / 4);
+		break;
+	case SCA3000_REG_MODE_MEAS_MODE_OP_2:
+		len += sprintf(buf + len, "%d %d %d\n",
+			       st->info->option_mode_2_freq,
+			       st->info->option_mode_2_freq / 2,
+			       st->info->option_mode_2_freq / 4);
+		break;
+	}
+	return len;
+error_ret:
+	return ret;
+}
+
+/*
+ * Should only really be registered if ring buffer support is compiled in.
+ * Does no harm however and doing it right would add a fair bit of complexity
+ */
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq);
+
+/**
+ * sca3000_read_event_value() - query of a threshold or period
+ **/
+static int sca3000_read_event_value(struct iio_dev *indio_dev,
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir,
+				    enum iio_event_info info,
+				    int *val, int *val2)
+{
+	int ret, i;
+	struct sca3000_state *st = iio_priv(indio_dev);
+
+	switch (info) {
+	case IIO_EV_INFO_VALUE:
+		mutex_lock(&st->lock);
+		ret = sca3000_read_ctrl_reg(st,
+					    sca3000_addresses[chan->address][1]);
+		mutex_unlock(&st->lock);
+		if (ret < 0)
+			return ret;
+		*val = 0;
+		if (chan->channel2 == IIO_MOD_Y)
+			for_each_set_bit(i, (unsigned long *)&ret,
+					 ARRAY_SIZE(st->info->mot_det_mult_y))
+				*val += st->info->mot_det_mult_y[i];
+		else
+			for_each_set_bit(i, (unsigned long *)&ret,
+					 ARRAY_SIZE(st->info->mot_det_mult_xz))
+				*val += st->info->mot_det_mult_xz[i];
+
+		return IIO_VAL_INT;
+	case IIO_EV_INFO_PERIOD:
+		*val = 0;
+		*val2 = 226000;
+		return IIO_VAL_INT_PLUS_MICRO;
+	default:
+		return -EINVAL;
+	}
+}
+
+/**
+ * sca3000_write_value() - control of threshold and period
+ * @indio_dev: Device instance specific IIO information.
+ * @chan: Description of the channel for which the event is being
+ * configured.
+ * @type: The type of event being configured, here magnitude rising
+ * as everything else is read only.
+ * @dir: Direction of the event (here rising)
+ * @info: What information about the event are we configuring.
+ * Here the threshold only.
+ * @val: Integer part of the value being written..
+ * @val2: Non integer part of the value being written. Here always 0.
+ */
+static int sca3000_write_event_value(struct iio_dev *indio_dev,
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir,
+				     enum iio_event_info info,
+				     int val, int val2)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret;
+	int i;
+	u8 nonlinear = 0;
+
+	if (chan->channel2 == IIO_MOD_Y) {
+		i = ARRAY_SIZE(st->info->mot_det_mult_y);
+		while (i > 0)
+			if (val >= st->info->mot_det_mult_y[--i]) {
+				nonlinear |= (1 << i);
+				val -= st->info->mot_det_mult_y[i];
+			}
+	} else {
+		i = ARRAY_SIZE(st->info->mot_det_mult_xz);
+		while (i > 0)
+			if (val >= st->info->mot_det_mult_xz[--i]) {
+				nonlinear |= (1 << i);
+				val -= st->info->mot_det_mult_xz[i];
+			}
+	}
+
+	mutex_lock(&st->lock);
+	ret = sca3000_write_ctrl_reg(st,
+				     sca3000_addresses[chan->address][1],
+				     nonlinear);
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+static struct attribute *sca3000_attributes[] = {
+	&iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group sca3000_attribute_group = {
+	.attrs = sca3000_attributes,
+};
+
+static int sca3000_read_data(struct sca3000_state *st,
+			     u8 reg_address_high,
+			     u8 *rx,
+			     int len)
+{
+	int ret;
+	struct spi_transfer xfer[2] = {
+		{
+			.len = 1,
+			.tx_buf = st->tx,
+		}, {
+			.len = len,
+			.rx_buf = rx,
+		}
+	};
+
+	st->tx[0] = SCA3000_READ_REG(reg_address_high);
+	ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
+	if (ret) {
+		dev_err(get_device(&st->us->dev), "problem reading register");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * sca3000_ring_int_process() - ring specific interrupt handling.
+ * @val: Value of the interrupt status register.
+ * @indio_dev: Device instance specific IIO device structure.
+ */
+static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret, i, num_available;
+
+	mutex_lock(&st->lock);
+
+	if (val & SCA3000_REG_INT_STATUS_HALF) {
+		ret = sca3000_read_data_short(st, SCA3000_REG_BUF_COUNT_ADDR,
+					      1);
+		if (ret)
+			goto error_ret;
+		num_available = st->rx[0];
+		/*
+		 * num_available is the total number of samples available
+		 * i.e. number of time points * number of channels.
+		 */
+		ret = sca3000_read_data(st, SCA3000_REG_RING_OUT_ADDR, st->rx,
+					num_available * 2);
+		if (ret)
+			goto error_ret;
+		for (i = 0; i < num_available / 3; i++) {
+			/*
+			 * Dirty hack to cover for 11 bit in fifo, 13 bit
+			 * direct reading.
+			 *
+			 * In theory the bottom two bits are undefined.
+			 * In reality they appear to always be 0.
+			 */
+			iio_push_to_buffers(indio_dev, st->rx + i * 3 * 2);
+		}
+	}
+error_ret:
+	mutex_unlock(&st->lock);
+}
+
+/**
+ * sca3000_event_handler() - handling ring and non ring events
+ * @irq: The irq being handled.
+ * @private: struct iio_device pointer for the device.
+ *
+ * Ring related interrupt handler. Depending on event, push to
+ * the ring buffer event chrdev or the event one.
+ *
+ * This function is complicated by the fact that the devices can signify ring
+ * and non ring events via the same interrupt line and they can only
+ * be distinguished via a read of the relevant status register.
+ */
+static irqreturn_t sca3000_event_handler(int irq, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret, val;
+	s64 last_timestamp = iio_get_time_ns(indio_dev);
+
+	/*
+	 * Could lead if badly timed to an extra read of status reg,
+	 * but ensures no interrupt is missed.
+	 */
+	mutex_lock(&st->lock);
+	ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1);
+	val = st->rx[0];
+	mutex_unlock(&st->lock);
+	if (ret)
+		goto done;
+
+	sca3000_ring_int_process(val, indio_dev);
+
+	if (val & SCA3000_INT_STATUS_FREE_FALL)
+		iio_push_event(indio_dev,
+			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+						  0,
+						  IIO_MOD_X_AND_Y_AND_Z,
+						  IIO_EV_TYPE_MAG,
+						  IIO_EV_DIR_FALLING),
+			       last_timestamp);
+
+	if (val & SCA3000_INT_STATUS_Y_TRIGGER)
+		iio_push_event(indio_dev,
+			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+						  0,
+						  IIO_MOD_Y,
+						  IIO_EV_TYPE_MAG,
+						  IIO_EV_DIR_RISING),
+			       last_timestamp);
+
+	if (val & SCA3000_INT_STATUS_X_TRIGGER)
+		iio_push_event(indio_dev,
+			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+						  0,
+						  IIO_MOD_X,
+						  IIO_EV_TYPE_MAG,
+						  IIO_EV_DIR_RISING),
+			       last_timestamp);
+
+	if (val & SCA3000_INT_STATUS_Z_TRIGGER)
+		iio_push_event(indio_dev,
+			       IIO_MOD_EVENT_CODE(IIO_ACCEL,
+						  0,
+						  IIO_MOD_Z,
+						  IIO_EV_TYPE_MAG,
+						  IIO_EV_DIR_RISING),
+			       last_timestamp);
+
+done:
+	return IRQ_HANDLED;
+}
+
+/**
+ * sca3000_read_event_config() what events are enabled
+ **/
+static int sca3000_read_event_config(struct iio_dev *indio_dev,
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret;
+	/* read current value of mode register */
+	mutex_lock(&st->lock);
+
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		goto error_ret;
+
+	switch (chan->channel2) {
+	case IIO_MOD_X_AND_Y_AND_Z:
+		ret = !!(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT);
+		break;
+	case IIO_MOD_X:
+	case IIO_MOD_Y:
+	case IIO_MOD_Z:
+		/*
+		 * Motion detection mode cannot run at the same time as
+		 * acceleration data being read.
+		 */
+		if ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
+		    != SCA3000_REG_MODE_MEAS_MODE_MOT_DET) {
+			ret = 0;
+		} else {
+			ret = sca3000_read_ctrl_reg(st,
+						SCA3000_REG_CTRL_SEL_MD_CTRL);
+			if (ret < 0)
+				goto error_ret;
+			/* only supporting logical or's for now */
+			ret = !!(ret & sca3000_addresses[chan->address][2]);
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+error_ret:
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret;
+
+	/* read current value of mode register */
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		return ret;
+
+	/* if off and should be on */
+	if (state && !(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT))
+		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
+					 st->rx[0] | SCA3000_REG_MODE_FREE_FALL_DETECT);
+	/* if on and should be off */
+	else if (!state && (st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT))
+		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
+					 st->rx[0] & ~SCA3000_REG_MODE_FREE_FALL_DETECT);
+	else
+		return 0;
+}
+
+static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis,
+					   int state)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret, ctrlval;
+
+	/*
+	 * First read the motion detector config to find out if
+	 * this axis is on
+	 */
+	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
+	if (ret < 0)
+		return ret;
+	ctrlval = ret;
+	/* if off and should be on */
+	if (state && !(ctrlval & sca3000_addresses[axis][2])) {
+		ret = sca3000_write_ctrl_reg(st,
+					     SCA3000_REG_CTRL_SEL_MD_CTRL,
+					     ctrlval |
+					     sca3000_addresses[axis][2]);
+		if (ret)
+			return ret;
+		st->mo_det_use_count++;
+	} else if (!state && (ctrlval & sca3000_addresses[axis][2])) {
+		ret = sca3000_write_ctrl_reg(st,
+					     SCA3000_REG_CTRL_SEL_MD_CTRL,
+					     ctrlval &
+					     ~(sca3000_addresses[axis][2]));
+		if (ret)
+			return ret;
+		st->mo_det_use_count--;
+	}
+
+	/* read current value of mode register */
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		return ret;
+	/* if off and should be on */
+	if ((st->mo_det_use_count) &&
+	    ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
+	     != SCA3000_REG_MODE_MEAS_MODE_MOT_DET))
+		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
+			(st->rx[0] & ~SCA3000_REG_MODE_MODE_MASK)
+			| SCA3000_REG_MODE_MEAS_MODE_MOT_DET);
+	/* if on and should be off */
+	else if (!(st->mo_det_use_count) &&
+		 ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK)
+		  == SCA3000_REG_MODE_MEAS_MODE_MOT_DET))
+		return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
+			st->rx[0] & SCA3000_REG_MODE_MODE_MASK);
+	else
+		return 0;
+}
+
+/**
+ * sca3000_write_event_config() - simple on off control for motion detector
+ * @indio_dev: IIO device instance specific structure. Data specific to this
+ * particular driver may be accessed via iio_priv(indio_dev).
+ * @chan: Description of the channel whose event we are configuring.
+ * @type: The type of event.
+ * @dir: The direction of the event.
+ * @state: Desired state of event being configured.
+ *
+ * This is a per axis control, but enabling any will result in the
+ * motion detector unit being enabled.
+ * N.B. enabling motion detector stops normal data acquisition.
+ * There is a complexity in knowing which mode to return to when
+ * this mode is disabled.  Currently normal mode is assumed.
+ **/
+static int sca3000_write_event_config(struct iio_dev *indio_dev,
+				      const struct iio_chan_spec *chan,
+				      enum iio_event_type type,
+				      enum iio_event_direction dir,
+				      int state)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&st->lock);
+	switch (chan->channel2) {
+	case IIO_MOD_X_AND_Y_AND_Z:
+		ret = sca3000_freefall_set_state(indio_dev, state);
+		break;
+
+	case IIO_MOD_X:
+	case IIO_MOD_Y:
+	case IIO_MOD_Z:
+		ret = sca3000_motion_detect_set_state(indio_dev,
+						      chan->address,
+						      state);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+static int sca3000_configure_ring(struct iio_dev *indio_dev)
+{
+	struct iio_buffer *buffer;
+
+	buffer = iio_kfifo_allocate();
+	if (!buffer)
+		return -ENOMEM;
+
+	iio_device_attach_buffer(indio_dev, buffer);
+	indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
+
+	return 0;
+}
+
+static void sca3000_unconfigure_ring(struct iio_dev *indio_dev)
+{
+	iio_kfifo_free(indio_dev->buffer);
+}
+
+static inline
+int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state)
+{
+	struct sca3000_state *st = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&st->lock);
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		goto error_ret;
+	if (state) {
+		dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n");
+		ret = sca3000_write_reg(st,
+			SCA3000_REG_MODE_ADDR,
+			(st->rx[0] | SCA3000_REG_MODE_RING_BUF_ENABLE));
+	} else
+		ret = sca3000_write_reg(st,
+			SCA3000_REG_MODE_ADDR,
+			(st->rx[0] & ~SCA3000_REG_MODE_RING_BUF_ENABLE));
+error_ret:
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+/**
+ * sca3000_hw_ring_preenable() - hw ring buffer preenable function
+ * @indio_dev: structure representing the IIO device. Device instance
+ * specific state can be accessed via iio_priv(indio_dev).
+ *
+ * Very simple enable function as the chip will allows normal reads
+ * during ring buffer operation so as long as it is indeed running
+ * before we notify the core, the precise ordering does not matter.
+ */
+static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct sca3000_state *st = iio_priv(indio_dev);
+
+	mutex_lock(&st->lock);
+
+	/* Enable the 50% full interrupt */
+	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
+	if (ret)
+		goto error_unlock;
+	ret = sca3000_write_reg(st,
+				SCA3000_REG_INT_MASK_ADDR,
+				st->rx[0] | SCA3000_REG_INT_MASK_RING_HALF);
+	if (ret)
+		goto error_unlock;
+
+	mutex_unlock(&st->lock);
+
+	return __sca3000_hw_ring_state_set(indio_dev, 1);
+
+error_unlock:
+	mutex_unlock(&st->lock);
+
+	return ret;
+}
+
+static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev)
+{
+	int ret;
+	struct sca3000_state *st = iio_priv(indio_dev);
+
+	ret = __sca3000_hw_ring_state_set(indio_dev, 0);
+	if (ret)
+		return ret;
+
+	/* Disable the 50% full interrupt */
+	mutex_lock(&st->lock);
+
+	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
+	if (ret)
+		goto unlock;
+	ret = sca3000_write_reg(st,
+				SCA3000_REG_INT_MASK_ADDR,
+				st->rx[0] & ~SCA3000_REG_INT_MASK_RING_HALF);
+unlock:
+	mutex_unlock(&st->lock);
+	return ret;
+}
+
+static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = {
+	.preenable = &sca3000_hw_ring_preenable,
+	.postdisable = &sca3000_hw_ring_postdisable,
+};
+
+/**
+ * sca3000_clean_setup() - get the device into a predictable state
+ * @st: Device instance specific private data structure
+ *
+ * Devices use flash memory to store many of the register values
+ * and hence can come up in somewhat unpredictable states.
+ * Hence reset everything on driver load.
+ */
+static int sca3000_clean_setup(struct sca3000_state *st)
+{
+	int ret;
+
+	mutex_lock(&st->lock);
+	/* Ensure all interrupts have been acknowledged */
+	ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1);
+	if (ret)
+		goto error_ret;
+
+	/* Turn off all motion detection channels */
+	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL);
+	if (ret < 0)
+		goto error_ret;
+	ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL,
+				     ret & SCA3000_MD_CTRL_PROT_MASK);
+	if (ret)
+		goto error_ret;
+
+	/* Disable ring buffer */
+	ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
+	if (ret < 0)
+		goto error_ret;
+	ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL,
+				     (ret & SCA3000_REG_OUT_CTRL_PROT_MASK)
+				     | SCA3000_REG_OUT_CTRL_BUF_X_EN
+				     | SCA3000_REG_OUT_CTRL_BUF_Y_EN
+				     | SCA3000_REG_OUT_CTRL_BUF_Z_EN
+				     | SCA3000_REG_OUT_CTRL_BUF_DIV_4);
+	if (ret)
+		goto error_ret;
+	/* Enable interrupts, relevant to mode and set up as active low */
+	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
+	if (ret)
+		goto error_ret;
+	ret = sca3000_write_reg(st,
+				SCA3000_REG_INT_MASK_ADDR,
+				(ret & SCA3000_REG_INT_MASK_PROT_MASK)
+				| SCA3000_REG_INT_MASK_ACTIVE_LOW);
+	if (ret)
+		goto error_ret;
+	/*
+	 * Select normal measurement mode, free fall off, ring off
+	 * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5
+	 * as that occurs in one of the example on the datasheet
+	 */
+	ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1);
+	if (ret)
+		goto error_ret;
+	ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR,
+				(st->rx[0] & SCA3000_MODE_PROT_MASK));
+
+error_ret:
+	mutex_unlock(&st->lock);
+	return ret;
+}
+
+static const struct iio_info sca3000_info = {
+	.attrs = &sca3000_attribute_group,
+	.read_raw = &sca3000_read_raw,
+	.write_raw = &sca3000_write_raw,
+	.read_event_value = &sca3000_read_event_value,
+	.write_event_value = &sca3000_write_event_value,
+	.read_event_config = &sca3000_read_event_config,
+	.write_event_config = &sca3000_write_event_config,
+	.driver_module = THIS_MODULE,
+};
+
+static int sca3000_probe(struct spi_device *spi)
+{
+	int ret;
+	struct sca3000_state *st;
+	struct iio_dev *indio_dev;
+
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	st = iio_priv(indio_dev);
+	spi_set_drvdata(spi, indio_dev);
+	st->us = spi;
+	mutex_init(&st->lock);
+	st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi)
+					      ->driver_data];
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->info = &sca3000_info;
+	if (st->info->temp_output) {
+		indio_dev->channels = sca3000_channels_with_temp;
+		indio_dev->num_channels =
+			ARRAY_SIZE(sca3000_channels_with_temp);
+	} else {
+		indio_dev->channels = sca3000_channels;
+		indio_dev->num_channels = ARRAY_SIZE(sca3000_channels);
+	}
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	sca3000_configure_ring(indio_dev);
+
+	if (spi->irq) {
+		ret = request_threaded_irq(spi->irq,
+					   NULL,
+					   &sca3000_event_handler,
+					   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					   "sca3000",
+					   indio_dev);
+		if (ret)
+			return ret;
+	}
+	indio_dev->setup_ops = &sca3000_ring_setup_ops;
+	ret = sca3000_clean_setup(st);
+	if (ret)
+		goto error_free_irq;
+
+	ret = sca3000_print_rev(indio_dev);
+	if (ret)
+		goto error_free_irq;
+
+	return iio_device_register(indio_dev);
+
+error_free_irq:
+	if (spi->irq)
+		free_irq(spi->irq, indio_dev);
+
+	return ret;
+}
+
+static int sca3000_stop_all_interrupts(struct sca3000_state *st)
+{
+	int ret;
+
+	mutex_lock(&st->lock);
+	ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1);
+	if (ret)
+		goto error_ret;
+	ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR,
+				(st->rx[0] &
+				 ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER |
+				   SCA3000_REG_INT_MASK_RING_HALF |
+				   SCA3000_REG_INT_MASK_ALL_INTS)));
+error_ret:
+	mutex_unlock(&st->lock);
+	return ret;
+}
+
+static int sca3000_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct sca3000_state *st = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	/* Must ensure no interrupts can be generated after this! */
+	sca3000_stop_all_interrupts(st);
+	if (spi->irq)
+		free_irq(spi->irq, indio_dev);
+
+	sca3000_unconfigure_ring(indio_dev);
+
+	return 0;
+}
+
+static const struct spi_device_id sca3000_id[] = {
+	{"sca3000_d01", d01},
+	{"sca3000_e02", e02},
+	{"sca3000_e04", e04},
+	{"sca3000_e05", e05},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, sca3000_id);
+
+static struct spi_driver sca3000_driver = {
+	.driver = {
+		.name = "sca3000",
+	},
+	.probe = sca3000_probe,
+	.remove = sca3000_remove,
+	.id_table = sca3000_id,
+};
+module_spi_driver(sca3000_driver);
+
+MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
+MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/st_accel_core.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel_core.c
--- linux-libre-4.9-gnu/drivers/iio/accel/st_accel_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,194 +43,6 @@
 #define ST_ACCEL_FS_AVL_200G			200
 #define ST_ACCEL_FS_AVL_400G			400
 
-/* CUSTOM VALUES FOR SENSOR 1 */
-#define ST_ACCEL_1_WAI_EXP			0x33
-#define ST_ACCEL_1_ODR_ADDR			0x20
-#define ST_ACCEL_1_ODR_MASK			0xf0
-#define ST_ACCEL_1_ODR_AVL_1HZ_VAL		0x01
-#define ST_ACCEL_1_ODR_AVL_10HZ_VAL		0x02
-#define ST_ACCEL_1_ODR_AVL_25HZ_VAL		0x03
-#define ST_ACCEL_1_ODR_AVL_50HZ_VAL		0x04
-#define ST_ACCEL_1_ODR_AVL_100HZ_VAL		0x05
-#define ST_ACCEL_1_ODR_AVL_200HZ_VAL		0x06
-#define ST_ACCEL_1_ODR_AVL_400HZ_VAL		0x07
-#define ST_ACCEL_1_ODR_AVL_1600HZ_VAL		0x08
-#define ST_ACCEL_1_FS_ADDR			0x23
-#define ST_ACCEL_1_FS_MASK			0x30
-#define ST_ACCEL_1_FS_AVL_2_VAL			0x00
-#define ST_ACCEL_1_FS_AVL_4_VAL			0x01
-#define ST_ACCEL_1_FS_AVL_8_VAL			0x02
-#define ST_ACCEL_1_FS_AVL_16_VAL		0x03
-#define ST_ACCEL_1_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(1000)
-#define ST_ACCEL_1_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(2000)
-#define ST_ACCEL_1_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(4000)
-#define ST_ACCEL_1_FS_AVL_16_GAIN		IIO_G_TO_M_S_2(12000)
-#define ST_ACCEL_1_BDU_ADDR			0x23
-#define ST_ACCEL_1_BDU_MASK			0x80
-#define ST_ACCEL_1_DRDY_IRQ_ADDR		0x22
-#define ST_ACCEL_1_DRDY_IRQ_INT1_MASK		0x10
-#define ST_ACCEL_1_DRDY_IRQ_INT2_MASK		0x08
-#define ST_ACCEL_1_IHL_IRQ_ADDR			0x25
-#define ST_ACCEL_1_IHL_IRQ_MASK			0x02
-#define ST_ACCEL_1_MULTIREAD_BIT		true
-
-/* CUSTOM VALUES FOR SENSOR 2 */
-#define ST_ACCEL_2_WAI_EXP			0x32
-#define ST_ACCEL_2_ODR_ADDR			0x20
-#define ST_ACCEL_2_ODR_MASK			0x18
-#define ST_ACCEL_2_ODR_AVL_50HZ_VAL		0x00
-#define ST_ACCEL_2_ODR_AVL_100HZ_VAL		0x01
-#define ST_ACCEL_2_ODR_AVL_400HZ_VAL		0x02
-#define ST_ACCEL_2_ODR_AVL_1000HZ_VAL		0x03
-#define ST_ACCEL_2_PW_ADDR			0x20
-#define ST_ACCEL_2_PW_MASK			0xe0
-#define ST_ACCEL_2_FS_ADDR			0x23
-#define ST_ACCEL_2_FS_MASK			0x30
-#define ST_ACCEL_2_FS_AVL_2_VAL			0X00
-#define ST_ACCEL_2_FS_AVL_4_VAL			0X01
-#define ST_ACCEL_2_FS_AVL_8_VAL			0x03
-#define ST_ACCEL_2_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(1000)
-#define ST_ACCEL_2_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(2000)
-#define ST_ACCEL_2_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(3900)
-#define ST_ACCEL_2_BDU_ADDR			0x23
-#define ST_ACCEL_2_BDU_MASK			0x80
-#define ST_ACCEL_2_DRDY_IRQ_ADDR		0x22
-#define ST_ACCEL_2_DRDY_IRQ_INT1_MASK		0x02
-#define ST_ACCEL_2_DRDY_IRQ_INT2_MASK		0x10
-#define ST_ACCEL_2_IHL_IRQ_ADDR			0x22
-#define ST_ACCEL_2_IHL_IRQ_MASK			0x80
-#define ST_ACCEL_2_OD_IRQ_ADDR			0x22
-#define ST_ACCEL_2_OD_IRQ_MASK			0x40
-#define ST_ACCEL_2_MULTIREAD_BIT		true
-
-/* CUSTOM VALUES FOR SENSOR 3 */
-#define ST_ACCEL_3_WAI_EXP			0x40
-#define ST_ACCEL_3_ODR_ADDR			0x20
-#define ST_ACCEL_3_ODR_MASK			0xf0
-#define ST_ACCEL_3_ODR_AVL_3HZ_VAL		0x01
-#define ST_ACCEL_3_ODR_AVL_6HZ_VAL		0x02
-#define ST_ACCEL_3_ODR_AVL_12HZ_VAL		0x03
-#define ST_ACCEL_3_ODR_AVL_25HZ_VAL		0x04
-#define ST_ACCEL_3_ODR_AVL_50HZ_VAL		0x05
-#define ST_ACCEL_3_ODR_AVL_100HZ_VAL		0x06
-#define ST_ACCEL_3_ODR_AVL_200HZ_VAL		0x07
-#define ST_ACCEL_3_ODR_AVL_400HZ_VAL		0x08
-#define ST_ACCEL_3_ODR_AVL_800HZ_VAL		0x09
-#define ST_ACCEL_3_ODR_AVL_1600HZ_VAL		0x0a
-#define ST_ACCEL_3_FS_ADDR			0x24
-#define ST_ACCEL_3_FS_MASK			0x38
-#define ST_ACCEL_3_FS_AVL_2_VAL			0X00
-#define ST_ACCEL_3_FS_AVL_4_VAL			0X01
-#define ST_ACCEL_3_FS_AVL_6_VAL			0x02
-#define ST_ACCEL_3_FS_AVL_8_VAL			0x03
-#define ST_ACCEL_3_FS_AVL_16_VAL		0x04
-#define ST_ACCEL_3_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(61)
-#define ST_ACCEL_3_FS_AVL_4_GAIN		IIO_G_TO_M_S_2(122)
-#define ST_ACCEL_3_FS_AVL_6_GAIN		IIO_G_TO_M_S_2(183)
-#define ST_ACCEL_3_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(244)
-#define ST_ACCEL_3_FS_AVL_16_GAIN		IIO_G_TO_M_S_2(732)
-#define ST_ACCEL_3_BDU_ADDR			0x20
-#define ST_ACCEL_3_BDU_MASK			0x08
-#define ST_ACCEL_3_DRDY_IRQ_ADDR		0x23
-#define ST_ACCEL_3_DRDY_IRQ_INT1_MASK		0x80
-#define ST_ACCEL_3_DRDY_IRQ_INT2_MASK		0x00
-#define ST_ACCEL_3_IHL_IRQ_ADDR			0x23
-#define ST_ACCEL_3_IHL_IRQ_MASK			0x40
-#define ST_ACCEL_3_IG1_EN_ADDR			0x23
-#define ST_ACCEL_3_IG1_EN_MASK			0x08
-#define ST_ACCEL_3_MULTIREAD_BIT		false
-
-/* CUSTOM VALUES FOR SENSOR 4 */
-#define ST_ACCEL_4_WAI_EXP			0x3a
-#define ST_ACCEL_4_ODR_ADDR			0x20
-#define ST_ACCEL_4_ODR_MASK			0x30 /* DF1 and DF0 */
-#define ST_ACCEL_4_ODR_AVL_40HZ_VAL		0x00
-#define ST_ACCEL_4_ODR_AVL_160HZ_VAL		0x01
-#define ST_ACCEL_4_ODR_AVL_640HZ_VAL		0x02
-#define ST_ACCEL_4_ODR_AVL_2560HZ_VAL		0x03
-#define ST_ACCEL_4_PW_ADDR			0x20
-#define ST_ACCEL_4_PW_MASK			0xc0
-#define ST_ACCEL_4_FS_ADDR			0x21
-#define ST_ACCEL_4_FS_MASK			0x80
-#define ST_ACCEL_4_FS_AVL_2_VAL			0X00
-#define ST_ACCEL_4_FS_AVL_6_VAL			0X01
-#define ST_ACCEL_4_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(1024)
-#define ST_ACCEL_4_FS_AVL_6_GAIN		IIO_G_TO_M_S_2(340)
-#define ST_ACCEL_4_BDU_ADDR			0x21
-#define ST_ACCEL_4_BDU_MASK			0x40
-#define ST_ACCEL_4_DRDY_IRQ_ADDR		0x21
-#define ST_ACCEL_4_DRDY_IRQ_INT1_MASK		0x04
-#define ST_ACCEL_4_MULTIREAD_BIT		true
-
-/* CUSTOM VALUES FOR SENSOR 5 */
-#define ST_ACCEL_5_WAI_EXP			0x3b
-#define ST_ACCEL_5_ODR_ADDR			0x20
-#define ST_ACCEL_5_ODR_MASK			0x80
-#define ST_ACCEL_5_ODR_AVL_100HZ_VAL		0x00
-#define ST_ACCEL_5_ODR_AVL_400HZ_VAL		0x01
-#define ST_ACCEL_5_PW_ADDR			0x20
-#define ST_ACCEL_5_PW_MASK			0x40
-#define ST_ACCEL_5_FS_ADDR			0x20
-#define ST_ACCEL_5_FS_MASK			0x20
-#define ST_ACCEL_5_FS_AVL_2_VAL			0X00
-#define ST_ACCEL_5_FS_AVL_8_VAL			0X01
-/* TODO: check these resulting gain settings, these are not in the datsheet */
-#define ST_ACCEL_5_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(18000)
-#define ST_ACCEL_5_FS_AVL_8_GAIN		IIO_G_TO_M_S_2(72000)
-#define ST_ACCEL_5_DRDY_IRQ_ADDR		0x22
-#define ST_ACCEL_5_DRDY_IRQ_INT1_MASK		0x04
-#define ST_ACCEL_5_DRDY_IRQ_INT2_MASK		0x20
-#define ST_ACCEL_5_IHL_IRQ_ADDR			0x22
-#define ST_ACCEL_5_IHL_IRQ_MASK			0x80
-#define ST_ACCEL_5_OD_IRQ_ADDR			0x22
-#define ST_ACCEL_5_OD_IRQ_MASK			0x40
-#define ST_ACCEL_5_IG1_EN_ADDR			0x21
-#define ST_ACCEL_5_IG1_EN_MASK			0x08
-#define ST_ACCEL_5_MULTIREAD_BIT		false
-
-/* CUSTOM VALUES FOR SENSOR 6 */
-#define ST_ACCEL_6_WAI_EXP			0x32
-#define ST_ACCEL_6_ODR_ADDR			0x20
-#define ST_ACCEL_6_ODR_MASK			0x18
-#define ST_ACCEL_6_ODR_AVL_50HZ_VAL		0x00
-#define ST_ACCEL_6_ODR_AVL_100HZ_VAL		0x01
-#define ST_ACCEL_6_ODR_AVL_400HZ_VAL		0x02
-#define ST_ACCEL_6_ODR_AVL_1000HZ_VAL		0x03
-#define ST_ACCEL_6_PW_ADDR			0x20
-#define ST_ACCEL_6_PW_MASK			0x20
-#define ST_ACCEL_6_FS_ADDR			0x23
-#define ST_ACCEL_6_FS_MASK			0x30
-#define ST_ACCEL_6_FS_AVL_100_VAL		0x00
-#define ST_ACCEL_6_FS_AVL_200_VAL		0x01
-#define ST_ACCEL_6_FS_AVL_400_VAL		0x03
-#define ST_ACCEL_6_FS_AVL_100_GAIN		IIO_G_TO_M_S_2(49000)
-#define ST_ACCEL_6_FS_AVL_200_GAIN		IIO_G_TO_M_S_2(98000)
-#define ST_ACCEL_6_FS_AVL_400_GAIN		IIO_G_TO_M_S_2(195000)
-#define ST_ACCEL_6_BDU_ADDR			0x23
-#define ST_ACCEL_6_BDU_MASK			0x80
-#define ST_ACCEL_6_DRDY_IRQ_ADDR		0x22
-#define ST_ACCEL_6_DRDY_IRQ_INT1_MASK		0x02
-#define ST_ACCEL_6_DRDY_IRQ_INT2_MASK		0x10
-#define ST_ACCEL_6_IHL_IRQ_ADDR			0x22
-#define ST_ACCEL_6_IHL_IRQ_MASK			0x80
-#define ST_ACCEL_6_MULTIREAD_BIT		true
-
-/* CUSTOM VALUES FOR SENSOR 7 */
-#define ST_ACCEL_7_ODR_ADDR			0x20
-#define ST_ACCEL_7_ODR_MASK			0x30
-#define ST_ACCEL_7_ODR_AVL_280HZ_VAL		0x00
-#define ST_ACCEL_7_ODR_AVL_560HZ_VAL		0x01
-#define ST_ACCEL_7_ODR_AVL_1120HZ_VAL		0x02
-#define ST_ACCEL_7_ODR_AVL_4480HZ_VAL		0x03
-#define ST_ACCEL_7_PW_ADDR			0x20
-#define ST_ACCEL_7_PW_MASK			0xc0
-#define ST_ACCEL_7_FS_AVL_2_GAIN		IIO_G_TO_M_S_2(488)
-#define ST_ACCEL_7_BDU_ADDR			0x21
-#define ST_ACCEL_7_BDU_MASK			0x40
-#define ST_ACCEL_7_DRDY_IRQ_ADDR		0x21
-#define ST_ACCEL_7_DRDY_IRQ_INT1_MASK		0x04
-#define ST_ACCEL_7_MULTIREAD_BIT		false
-
 static const struct iio_chan_spec st_accel_8bit_channels[] = {
 	ST_SENSORS_LSM_CHANNELS(IIO_ACCEL,
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -281,7 +93,7 @@ static const struct iio_chan_spec st_acc
 
 static const struct st_sensor_settings st_accel_sensors_settings[] = {
 	{
-		.wai = ST_ACCEL_1_WAI_EXP,
+		.wai = 0x33,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LIS3DH_ACCEL_DEV_NAME,
@@ -294,22 +106,22 @@ static const struct st_sensor_settings s
 		},
 		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
 		.odr = {
-			.addr = ST_ACCEL_1_ODR_ADDR,
-			.mask = ST_ACCEL_1_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0xf0,
 			.odr_avl = {
-				{ 1, ST_ACCEL_1_ODR_AVL_1HZ_VAL, },
-				{ 10, ST_ACCEL_1_ODR_AVL_10HZ_VAL, },
-				{ 25, ST_ACCEL_1_ODR_AVL_25HZ_VAL, },
-				{ 50, ST_ACCEL_1_ODR_AVL_50HZ_VAL, },
-				{ 100, ST_ACCEL_1_ODR_AVL_100HZ_VAL, },
-				{ 200, ST_ACCEL_1_ODR_AVL_200HZ_VAL, },
-				{ 400, ST_ACCEL_1_ODR_AVL_400HZ_VAL, },
-				{ 1600, ST_ACCEL_1_ODR_AVL_1600HZ_VAL, },
+				{ .hz = 1, .value = 0x01, },
+				{ .hz = 10, .value = 0x02, },
+				{ .hz = 25, .value = 0x03, },
+				{ .hz = 50, .value = 0x04, },
+				{ .hz = 100, .value = 0x05, },
+				{ .hz = 200, .value = 0x06, },
+				{ .hz = 400, .value = 0x07, },
+				{ .hz = 1600, .value = 0x08, },
 			},
 		},
 		.pw = {
-			.addr = ST_ACCEL_1_ODR_ADDR,
-			.mask = ST_ACCEL_1_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0xf0,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.enable_axis = {
@@ -317,48 +129,48 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_ACCEL_1_FS_ADDR,
-			.mask = ST_ACCEL_1_FS_MASK,
+			.addr = 0x23,
+			.mask = 0x30,
 			.fs_avl = {
 				[0] = {
 					.num = ST_ACCEL_FS_AVL_2G,
-					.value = ST_ACCEL_1_FS_AVL_2_VAL,
-					.gain = ST_ACCEL_1_FS_AVL_2_GAIN,
+					.value = 0x00,
+					.gain = IIO_G_TO_M_S_2(1000),
 				},
 				[1] = {
 					.num = ST_ACCEL_FS_AVL_4G,
-					.value = ST_ACCEL_1_FS_AVL_4_VAL,
-					.gain = ST_ACCEL_1_FS_AVL_4_GAIN,
+					.value = 0x01,
+					.gain = IIO_G_TO_M_S_2(2000),
 				},
 				[2] = {
 					.num = ST_ACCEL_FS_AVL_8G,
-					.value = ST_ACCEL_1_FS_AVL_8_VAL,
-					.gain = ST_ACCEL_1_FS_AVL_8_GAIN,
+					.value = 0x02,
+					.gain = IIO_G_TO_M_S_2(4000),
 				},
 				[3] = {
 					.num = ST_ACCEL_FS_AVL_16G,
-					.value = ST_ACCEL_1_FS_AVL_16_VAL,
-					.gain = ST_ACCEL_1_FS_AVL_16_GAIN,
+					.value = 0x03,
+					.gain = IIO_G_TO_M_S_2(12000),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_ACCEL_1_BDU_ADDR,
-			.mask = ST_ACCEL_1_BDU_MASK,
+			.addr = 0x23,
+			.mask = 0x80,
 		},
 		.drdy_irq = {
-			.addr = ST_ACCEL_1_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_ACCEL_1_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_ACCEL_1_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_ACCEL_1_IHL_IRQ_ADDR,
-			.mask_ihl = ST_ACCEL_1_IHL_IRQ_MASK,
+			.addr = 0x22,
+			.mask_int1 = 0x10,
+			.mask_int2 = 0x08,
+			.addr_ihl = 0x25,
+			.mask_ihl = 0x02,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_ACCEL_1_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_ACCEL_2_WAI_EXP,
+		.wai = 0x32,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LIS331DLH_ACCEL_DEV_NAME,
@@ -368,18 +180,18 @@ static const struct st_sensor_settings s
 		},
 		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
 		.odr = {
-			.addr = ST_ACCEL_2_ODR_ADDR,
-			.mask = ST_ACCEL_2_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x18,
 			.odr_avl = {
-				{ 50, ST_ACCEL_2_ODR_AVL_50HZ_VAL, },
-				{ 100, ST_ACCEL_2_ODR_AVL_100HZ_VAL, },
-				{ 400, ST_ACCEL_2_ODR_AVL_400HZ_VAL, },
-				{ 1000, ST_ACCEL_2_ODR_AVL_1000HZ_VAL, },
+				{ .hz = 50, .value = 0x00, },
+				{ .hz = 100, .value = 0x01, },
+				{ .hz = 400, .value = 0x02, },
+				{ .hz = 1000, .value = 0x03, },
 			},
 		},
 		.pw = {
-			.addr = ST_ACCEL_2_PW_ADDR,
-			.mask = ST_ACCEL_2_PW_MASK,
+			.addr = 0x20,
+			.mask = 0xe0,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -388,69 +200,69 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_ACCEL_2_FS_ADDR,
-			.mask = ST_ACCEL_2_FS_MASK,
+			.addr = 0x23,
+			.mask = 0x30,
 			.fs_avl = {
 				[0] = {
 					.num = ST_ACCEL_FS_AVL_2G,
-					.value = ST_ACCEL_2_FS_AVL_2_VAL,
-					.gain = ST_ACCEL_2_FS_AVL_2_GAIN,
+					.value = 0x00,
+					.gain = IIO_G_TO_M_S_2(1000),
 				},
 				[1] = {
 					.num = ST_ACCEL_FS_AVL_4G,
-					.value = ST_ACCEL_2_FS_AVL_4_VAL,
-					.gain = ST_ACCEL_2_FS_AVL_4_GAIN,
+					.value = 0x01,
+					.gain = IIO_G_TO_M_S_2(2000),
 				},
 				[2] = {
 					.num = ST_ACCEL_FS_AVL_8G,
-					.value = ST_ACCEL_2_FS_AVL_8_VAL,
-					.gain = ST_ACCEL_2_FS_AVL_8_GAIN,
+					.value = 0x03,
+					.gain = IIO_G_TO_M_S_2(3900),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_ACCEL_2_BDU_ADDR,
-			.mask = ST_ACCEL_2_BDU_MASK,
+			.addr = 0x23,
+			.mask = 0x80,
 		},
 		.drdy_irq = {
-			.addr = ST_ACCEL_2_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_ACCEL_2_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_ACCEL_2_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_ACCEL_2_IHL_IRQ_ADDR,
-			.mask_ihl = ST_ACCEL_2_IHL_IRQ_MASK,
-			.addr_od = ST_ACCEL_2_OD_IRQ_ADDR,
-			.mask_od = ST_ACCEL_2_OD_IRQ_MASK,
+			.addr = 0x22,
+			.mask_int1 = 0x02,
+			.mask_int2 = 0x10,
+			.addr_ihl = 0x22,
+			.mask_ihl = 0x80,
+			.addr_od = 0x22,
+			.mask_od = 0x40,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_ACCEL_2_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_ACCEL_3_WAI_EXP,
+		.wai = 0x40,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LSM330_ACCEL_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_accel_16bit_channels,
 		.odr = {
-			.addr = ST_ACCEL_3_ODR_ADDR,
-			.mask = ST_ACCEL_3_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0xf0,
 			.odr_avl = {
-				{ 3, ST_ACCEL_3_ODR_AVL_3HZ_VAL },
-				{ 6, ST_ACCEL_3_ODR_AVL_6HZ_VAL, },
-				{ 12, ST_ACCEL_3_ODR_AVL_12HZ_VAL, },
-				{ 25, ST_ACCEL_3_ODR_AVL_25HZ_VAL, },
-				{ 50, ST_ACCEL_3_ODR_AVL_50HZ_VAL, },
-				{ 100, ST_ACCEL_3_ODR_AVL_100HZ_VAL, },
-				{ 200, ST_ACCEL_3_ODR_AVL_200HZ_VAL, },
-				{ 400, ST_ACCEL_3_ODR_AVL_400HZ_VAL, },
-				{ 800, ST_ACCEL_3_ODR_AVL_800HZ_VAL, },
-				{ 1600, ST_ACCEL_3_ODR_AVL_1600HZ_VAL, },
+				{ .hz = 3, .value = 0x01, },
+				{ .hz = 6, .value = 0x02, },
+				{ .hz = 12, .value = 0x03, },
+				{ .hz = 25, .value = 0x04, },
+				{ .hz = 50, .value = 0x05, },
+				{ .hz = 100, .value = 0x06, },
+				{ .hz = 200, .value = 0x07, },
+				{ .hz = 400, .value = 0x08, },
+				{ .hz = 800, .value = 0x09, },
+				{ .hz = 1600, .value = 0x0a, },
 			},
 		},
 		.pw = {
-			.addr = ST_ACCEL_3_ODR_ADDR,
-			.mask = ST_ACCEL_3_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0xf0,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.enable_axis = {
@@ -458,75 +270,75 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_ACCEL_3_FS_ADDR,
-			.mask = ST_ACCEL_3_FS_MASK,
+			.addr = 0x24,
+			.mask = 0x38,
 			.fs_avl = {
 				[0] = {
 					.num = ST_ACCEL_FS_AVL_2G,
-					.value = ST_ACCEL_3_FS_AVL_2_VAL,
-					.gain = ST_ACCEL_3_FS_AVL_2_GAIN,
+					.value = 0x00,
+					.gain = IIO_G_TO_M_S_2(61),
 				},
 				[1] = {
 					.num = ST_ACCEL_FS_AVL_4G,
-					.value = ST_ACCEL_3_FS_AVL_4_VAL,
-					.gain = ST_ACCEL_3_FS_AVL_4_GAIN,
+					.value = 0x01,
+					.gain = IIO_G_TO_M_S_2(122),
 				},
 				[2] = {
 					.num = ST_ACCEL_FS_AVL_6G,
-					.value = ST_ACCEL_3_FS_AVL_6_VAL,
-					.gain = ST_ACCEL_3_FS_AVL_6_GAIN,
+					.value = 0x02,
+					.gain = IIO_G_TO_M_S_2(183),
 				},
 				[3] = {
 					.num = ST_ACCEL_FS_AVL_8G,
-					.value = ST_ACCEL_3_FS_AVL_8_VAL,
-					.gain = ST_ACCEL_3_FS_AVL_8_GAIN,
+					.value = 0x03,
+					.gain = IIO_G_TO_M_S_2(244),
 				},
 				[4] = {
 					.num = ST_ACCEL_FS_AVL_16G,
-					.value = ST_ACCEL_3_FS_AVL_16_VAL,
-					.gain = ST_ACCEL_3_FS_AVL_16_GAIN,
+					.value = 0x04,
+					.gain = IIO_G_TO_M_S_2(732),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_ACCEL_3_BDU_ADDR,
-			.mask = ST_ACCEL_3_BDU_MASK,
+			.addr = 0x20,
+			.mask = 0x08,
 		},
 		.drdy_irq = {
-			.addr = ST_ACCEL_3_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_ACCEL_3_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_ACCEL_3_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_ACCEL_3_IHL_IRQ_ADDR,
-			.mask_ihl = ST_ACCEL_3_IHL_IRQ_MASK,
+			.addr = 0x23,
+			.mask_int1 = 0x80,
+			.mask_int2 = 0x00,
+			.addr_ihl = 0x23,
+			.mask_ihl = 0x40,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 			.ig1 = {
-				.en_addr = ST_ACCEL_3_IG1_EN_ADDR,
-				.en_mask = ST_ACCEL_3_IG1_EN_MASK,
+				.en_addr = 0x23,
+				.en_mask = 0x08,
 			},
 		},
-		.multi_read_bit = ST_ACCEL_3_MULTIREAD_BIT,
+		.multi_read_bit = false,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_ACCEL_4_WAI_EXP,
+		.wai = 0x3a,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LIS3LV02DL_ACCEL_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
 		.odr = {
-			.addr = ST_ACCEL_4_ODR_ADDR,
-			.mask = ST_ACCEL_4_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x30, /* DF1 and DF0 */
 			.odr_avl = {
-				{ 40, ST_ACCEL_4_ODR_AVL_40HZ_VAL },
-				{ 160, ST_ACCEL_4_ODR_AVL_160HZ_VAL, },
-				{ 640, ST_ACCEL_4_ODR_AVL_640HZ_VAL, },
-				{ 2560, ST_ACCEL_4_ODR_AVL_2560HZ_VAL, },
+				{ .hz = 40, .value = 0x00, },
+				{ .hz = 160, .value = 0x01, },
+				{ .hz = 640, .value = 0x02, },
+				{ .hz = 2560, .value = 0x03, },
 			},
 		},
 		.pw = {
-			.addr = ST_ACCEL_4_PW_ADDR,
-			.mask = ST_ACCEL_4_PW_MASK,
+			.addr = 0x20,
+			.mask = 0xc0,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -535,51 +347,59 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_ACCEL_4_FS_ADDR,
-			.mask = ST_ACCEL_4_FS_MASK,
+			.addr = 0x21,
+			.mask = 0x80,
 			.fs_avl = {
 				[0] = {
 					.num = ST_ACCEL_FS_AVL_2G,
-					.value = ST_ACCEL_4_FS_AVL_2_VAL,
-					.gain = ST_ACCEL_4_FS_AVL_2_GAIN,
+					.value = 0x00,
+					.gain = IIO_G_TO_M_S_2(1000),
 				},
 				[1] = {
 					.num = ST_ACCEL_FS_AVL_6G,
-					.value = ST_ACCEL_4_FS_AVL_6_VAL,
-					.gain = ST_ACCEL_4_FS_AVL_6_GAIN,
+					.value = 0x01,
+					.gain = IIO_G_TO_M_S_2(3000),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_ACCEL_4_BDU_ADDR,
-			.mask = ST_ACCEL_4_BDU_MASK,
+			.addr = 0x21,
+			.mask = 0x40,
+		},
+		/*
+		 * Data Alignment Setting - needs to be set to get
+		 * left-justified data like all other sensors.
+		 */
+		.das = {
+			.addr = 0x21,
+			.mask = 0x01,
 		},
 		.drdy_irq = {
-			.addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
+			.addr = 0x21,
+			.mask_int1 = 0x04,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2, /* guess */
 	},
 	{
-		.wai = ST_ACCEL_5_WAI_EXP,
+		.wai = 0x3b,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LIS331DL_ACCEL_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_accel_8bit_channels,
 		.odr = {
-			.addr = ST_ACCEL_5_ODR_ADDR,
-			.mask = ST_ACCEL_5_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x80,
 			.odr_avl = {
-				{ 100, ST_ACCEL_5_ODR_AVL_100HZ_VAL },
-				{ 400, ST_ACCEL_5_ODR_AVL_400HZ_VAL, },
+				{ .hz = 100, .value = 0x00, },
+				{ .hz = 400, .value = 0x01, },
 			},
 		},
 		.pw = {
-			.addr = ST_ACCEL_5_PW_ADDR,
-			.mask = ST_ACCEL_5_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x40,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -588,54 +408,58 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_ACCEL_5_FS_ADDR,
-			.mask = ST_ACCEL_5_FS_MASK,
+			.addr = 0x20,
+			.mask = 0x20,
+			/*
+			 * TODO: check these resulting gain settings, these are
+			 * not in the datsheet
+			 */
 			.fs_avl = {
 				[0] = {
 					.num = ST_ACCEL_FS_AVL_2G,
-					.value = ST_ACCEL_5_FS_AVL_2_VAL,
-					.gain = ST_ACCEL_5_FS_AVL_2_GAIN,
+					.value = 0x00,
+					.gain = IIO_G_TO_M_S_2(18000),
 				},
 				[1] = {
 					.num = ST_ACCEL_FS_AVL_8G,
-					.value = ST_ACCEL_5_FS_AVL_8_VAL,
-					.gain = ST_ACCEL_5_FS_AVL_8_GAIN,
+					.value = 0x01,
+					.gain = IIO_G_TO_M_S_2(72000),
 				},
 			},
 		},
 		.drdy_irq = {
-			.addr = ST_ACCEL_5_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_ACCEL_5_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_ACCEL_5_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_ACCEL_5_IHL_IRQ_ADDR,
-			.mask_ihl = ST_ACCEL_5_IHL_IRQ_MASK,
-			.addr_od = ST_ACCEL_5_OD_IRQ_ADDR,
-			.mask_od = ST_ACCEL_5_OD_IRQ_MASK,
+			.addr = 0x22,
+			.mask_int1 = 0x04,
+			.mask_int2 = 0x20,
+			.addr_ihl = 0x22,
+			.mask_ihl = 0x80,
+			.addr_od = 0x22,
+			.mask_od = 0x40,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_ACCEL_5_MULTIREAD_BIT,
+		.multi_read_bit = false,
 		.bootime = 2, /* guess */
 	},
 	{
-		.wai = ST_ACCEL_6_WAI_EXP,
+		.wai = 0x32,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = H3LIS331DL_DRIVER_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
 		.odr = {
-			.addr = ST_ACCEL_6_ODR_ADDR,
-			.mask = ST_ACCEL_6_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x18,
 			.odr_avl = {
-				{ 50, ST_ACCEL_6_ODR_AVL_50HZ_VAL },
-				{ 100, ST_ACCEL_6_ODR_AVL_100HZ_VAL, },
-				{ 400, ST_ACCEL_6_ODR_AVL_400HZ_VAL, },
-				{ 1000, ST_ACCEL_6_ODR_AVL_1000HZ_VAL, },
+				{ .hz = 50, .value = 0x00, },
+				{ .hz = 100, .value = 0x01, },
+				{ .hz = 400, .value = 0x02, },
+				{ .hz = 1000, .value = 0x03, },
 			},
 		},
 		.pw = {
-			.addr = ST_ACCEL_6_PW_ADDR,
-			.mask = ST_ACCEL_6_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x20,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -644,38 +468,38 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_ACCEL_6_FS_ADDR,
-			.mask = ST_ACCEL_6_FS_MASK,
+			.addr = 0x23,
+			.mask = 0x30,
 			.fs_avl = {
 				[0] = {
 					.num = ST_ACCEL_FS_AVL_100G,
-					.value = ST_ACCEL_6_FS_AVL_100_VAL,
-					.gain = ST_ACCEL_6_FS_AVL_100_GAIN,
+					.value = 0x00,
+					.gain = IIO_G_TO_M_S_2(49000),
 				},
 				[1] = {
 					.num = ST_ACCEL_FS_AVL_200G,
-					.value = ST_ACCEL_6_FS_AVL_200_VAL,
-					.gain = ST_ACCEL_6_FS_AVL_200_GAIN,
+					.value = 0x01,
+					.gain = IIO_G_TO_M_S_2(98000),
 				},
 				[2] = {
 					.num = ST_ACCEL_FS_AVL_400G,
-					.value = ST_ACCEL_6_FS_AVL_400_VAL,
-					.gain = ST_ACCEL_6_FS_AVL_400_GAIN,
+					.value = 0x03,
+					.gain = IIO_G_TO_M_S_2(195000),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_ACCEL_6_BDU_ADDR,
-			.mask = ST_ACCEL_6_BDU_MASK,
+			.addr = 0x23,
+			.mask = 0x80,
 		},
 		.drdy_irq = {
-			.addr = ST_ACCEL_6_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_ACCEL_6_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_ACCEL_6_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_ACCEL_6_IHL_IRQ_ADDR,
-			.mask_ihl = ST_ACCEL_6_IHL_IRQ_MASK,
+			.addr = 0x22,
+			.mask_int1 = 0x02,
+			.mask_int2 = 0x10,
+			.addr_ihl = 0x22,
+			.mask_ihl = 0x80,
 		},
-		.multi_read_bit = ST_ACCEL_6_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
@@ -685,18 +509,18 @@ static const struct st_sensor_settings s
 		},
 		.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
 		.odr = {
-			.addr = ST_ACCEL_7_ODR_ADDR,
-			.mask = ST_ACCEL_7_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x30,
 			.odr_avl = {
-				{ 280, ST_ACCEL_7_ODR_AVL_280HZ_VAL, },
-				{ 560, ST_ACCEL_7_ODR_AVL_560HZ_VAL, },
-				{ 1120, ST_ACCEL_7_ODR_AVL_1120HZ_VAL, },
-				{ 4480, ST_ACCEL_7_ODR_AVL_4480HZ_VAL, },
+				{ .hz = 280, .value = 0x00, },
+				{ .hz = 560, .value = 0x01, },
+				{ .hz = 1120, .value = 0x02, },
+				{ .hz = 4480, .value = 0x03, },
 			},
 		},
 		.pw = {
-			.addr = ST_ACCEL_7_PW_ADDR,
-			.mask = ST_ACCEL_7_PW_MASK,
+			.addr = 0x20,
+			.mask = 0xc0,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -708,7 +532,7 @@ static const struct st_sensor_settings s
 			.fs_avl = {
 				[0] = {
 					.num = ST_ACCEL_FS_AVL_2G,
-					.gain = ST_ACCEL_7_FS_AVL_2_GAIN,
+					.gain = IIO_G_TO_M_S_2(488),
 				},
 			},
 		},
@@ -719,11 +543,78 @@ static const struct st_sensor_settings s
 		.bdu = {
 		},
 		.drdy_irq = {
-			.addr = ST_ACCEL_7_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_ACCEL_7_DRDY_IRQ_INT1_MASK,
+			.addr = 0x21,
+			.mask_int1 = 0x04,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_ACCEL_7_MULTIREAD_BIT,
+		.multi_read_bit = false,
+		.bootime = 2,
+	},
+	{
+		.wai = 0x33,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+		.sensors_supported = {
+			[0] = LNG2DM_ACCEL_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_accel_8bit_channels,
+		.odr = {
+			.addr = 0x20,
+			.mask = 0xf0,
+			.odr_avl = {
+				{ .hz = 1, .value = 0x01, },
+				{ .hz = 10, .value = 0x02, },
+				{ .hz = 25, .value = 0x03, },
+				{ .hz = 50, .value = 0x04, },
+				{ .hz = 100, .value = 0x05, },
+				{ .hz = 200, .value = 0x06, },
+				{ .hz = 400, .value = 0x07, },
+				{ .hz = 1600, .value = 0x08, },
+			},
+		},
+		.pw = {
+			.addr = 0x20,
+			.mask = 0xf0,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = 0x23,
+			.mask = 0x30,
+			.fs_avl = {
+				[0] = {
+					.num = ST_ACCEL_FS_AVL_2G,
+					.value = 0x00,
+					.gain = IIO_G_TO_M_S_2(15600),
+				},
+				[1] = {
+					.num = ST_ACCEL_FS_AVL_4G,
+					.value = 0x01,
+					.gain = IIO_G_TO_M_S_2(31200),
+				},
+				[2] = {
+					.num = ST_ACCEL_FS_AVL_8G,
+					.value = 0x02,
+					.gain = IIO_G_TO_M_S_2(62500),
+				},
+				[3] = {
+					.num = ST_ACCEL_FS_AVL_16G,
+					.value = 0x03,
+					.gain = IIO_G_TO_M_S_2(187500),
+				},
+			},
+		},
+		.drdy_irq = {
+			.addr = 0x22,
+			.mask_int1 = 0x10,
+			.mask_int2 = 0x08,
+			.addr_ihl = 0x25,
+			.mask_ihl = 0x02,
+			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
+		},
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/st_accel.h linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel.h
--- linux-libre-4.9-gnu/drivers/iio/accel/st_accel.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,7 @@
 #define LSM303AGR_ACCEL_DEV_NAME	"lsm303agr_accel"
 #define LIS2DH12_ACCEL_DEV_NAME		"lis2dh12_accel"
 #define LIS3L02DQ_ACCEL_DEV_NAME	"lis3l02dq"
+#define LNG2DM_ACCEL_DEV_NAME		"lng2dm"
 
 /**
 * struct st_sensors_platform_data - default accel platform data
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/st_accel_i2c.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel_i2c.c
--- linux-libre-4.9-gnu/drivers/iio/accel/st_accel_i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel_i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,6 +84,10 @@ static const struct of_device_id st_acce
 		.compatible = "st,lis3l02dq",
 		.data = LIS3L02DQ_ACCEL_DEV_NAME,
 	},
+	{
+		.compatible = "st,lng2dm-accel",
+		.data = LNG2DM_ACCEL_DEV_NAME,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, st_accel_of_match);
@@ -135,6 +139,7 @@ static const struct i2c_device_id st_acc
 	{ LSM303AGR_ACCEL_DEV_NAME },
 	{ LIS2DH12_ACCEL_DEV_NAME },
 	{ LIS3L02DQ_ACCEL_DEV_NAME },
+	{ LNG2DM_ACCEL_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/accel/st_accel_spi.c linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel_spi.c
--- linux-libre-4.9-gnu/drivers/iio/accel/st_accel_spi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/accel/st_accel_spi.c	2017-02-12 16:03:20.000000000 -0500
@@ -60,6 +60,7 @@ static const struct spi_device_id st_acc
 	{ LSM303AGR_ACCEL_DEV_NAME },
 	{ LIS2DH12_ACCEL_DEV_NAME },
 	{ LIS3L02DQ_ACCEL_DEV_NAME },
+	{ LNG2DM_ACCEL_DEV_NAME },
 	{},
 };
 MODULE_DEVICE_TABLE(spi, st_accel_id_table);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/ad7766.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/ad7766.c
--- linux-libre-4.9-gnu/drivers/iio/adc/ad7766.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/ad7766.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,330 @@
+/*
+ * AD7766/AD7767 SPI ADC driver
+ *
+ * Copyright 2016 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+struct ad7766_chip_info {
+	unsigned int decimation_factor;
+};
+
+enum {
+	AD7766_SUPPLY_AVDD = 0,
+	AD7766_SUPPLY_DVDD = 1,
+	AD7766_SUPPLY_VREF = 2,
+	AD7766_NUM_SUPPLIES = 3
+};
+
+struct ad7766 {
+	const struct ad7766_chip_info *chip_info;
+	struct spi_device *spi;
+	struct clk *mclk;
+	struct gpio_desc *pd_gpio;
+	struct regulator_bulk_data reg[AD7766_NUM_SUPPLIES];
+
+	struct iio_trigger *trig;
+
+	struct spi_transfer xfer;
+	struct spi_message msg;
+
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 * Make the buffer large enough for one 24 bit sample and one 64 bit
+	 * aligned 64 bit timestamp.
+	 */
+	unsigned char data[ALIGN(3, sizeof(s64)) + sizeof(s64)]
+			____cacheline_aligned;
+};
+
+/*
+ * AD7766 and AD7767 variations are interface compatible, the main difference is
+ * analog performance. Both parts will use the same ID.
+ */
+enum ad7766_device_ids {
+	ID_AD7766,
+	ID_AD7766_1,
+	ID_AD7766_2,
+};
+
+static irqreturn_t ad7766_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct ad7766 *ad7766 = iio_priv(indio_dev);
+	int ret;
+
+	ret = spi_sync(ad7766->spi, &ad7766->msg);
+	if (ret < 0)
+		goto done;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, ad7766->data,
+		pf->timestamp);
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int ad7766_preenable(struct iio_dev *indio_dev)
+{
+	struct ad7766 *ad7766 = iio_priv(indio_dev);
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ad7766->reg), ad7766->reg);
+	if (ret < 0) {
+		dev_err(&ad7766->spi->dev, "Failed to enable supplies: %d\n",
+			ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(ad7766->mclk);
+	if (ret < 0) {
+		dev_err(&ad7766->spi->dev, "Failed to enable MCLK: %d\n", ret);
+		regulator_bulk_disable(ARRAY_SIZE(ad7766->reg), ad7766->reg);
+		return ret;
+	}
+
+	if (ad7766->pd_gpio)
+		gpiod_set_value(ad7766->pd_gpio, 0);
+
+	return 0;
+}
+
+static int ad7766_postdisable(struct iio_dev *indio_dev)
+{
+	struct ad7766 *ad7766 = iio_priv(indio_dev);
+
+	if (ad7766->pd_gpio)
+		gpiod_set_value(ad7766->pd_gpio, 1);
+
+	/*
+	 * The PD pin is synchronous to the clock, so give it some time to
+	 * notice the change before we disable the clock.
+	 */
+	msleep(20);
+
+	clk_disable_unprepare(ad7766->mclk);
+	regulator_bulk_disable(ARRAY_SIZE(ad7766->reg), ad7766->reg);
+
+	return 0;
+}
+
+static int ad7766_read_raw(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, int *val, int *val2, long info)
+{
+	struct ad7766 *ad7766 = iio_priv(indio_dev);
+	struct regulator *vref = ad7766->reg[AD7766_SUPPLY_VREF].consumer;
+	int scale_uv;
+
+	switch (info) {
+	case IIO_CHAN_INFO_SCALE:
+		scale_uv = regulator_get_voltage(vref);
+		if (scale_uv < 0)
+			return scale_uv;
+		*val = scale_uv / 1000;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = clk_get_rate(ad7766->mclk) /
+			ad7766->chip_info->decimation_factor;
+		return IIO_VAL_INT;
+	}
+	return -EINVAL;
+}
+
+static const struct iio_chan_spec ad7766_channels[] = {
+	{
+		.type = IIO_VOLTAGE,
+		.indexed = 1,
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.scan_type = {
+			.sign = 's',
+			.realbits = 24,
+			.storagebits = 32,
+			.endianness = IIO_BE,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static const struct ad7766_chip_info ad7766_chip_info[] = {
+	[ID_AD7766] = {
+		.decimation_factor = 8,
+	},
+	[ID_AD7766_1] = {
+		.decimation_factor = 16,
+	},
+	[ID_AD7766_2] = {
+		.decimation_factor = 32,
+	},
+};
+
+static const struct iio_buffer_setup_ops ad7766_buffer_setup_ops = {
+	.preenable = &ad7766_preenable,
+	.postenable = &iio_triggered_buffer_postenable,
+	.predisable = &iio_triggered_buffer_predisable,
+	.postdisable = &ad7766_postdisable,
+};
+
+static const struct iio_info ad7766_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = &ad7766_read_raw,
+};
+
+static irqreturn_t ad7766_irq(int irq, void *private)
+{
+	iio_trigger_poll(private);
+	return IRQ_HANDLED;
+}
+
+static int ad7766_set_trigger_state(struct iio_trigger *trig, bool enable)
+{
+	struct ad7766 *ad7766 = iio_trigger_get_drvdata(trig);
+
+	if (enable)
+		enable_irq(ad7766->spi->irq);
+	else
+		disable_irq(ad7766->spi->irq);
+
+	return 0;
+}
+
+static const struct iio_trigger_ops ad7766_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = ad7766_set_trigger_state,
+	.validate_device = iio_trigger_validate_own_device,
+};
+
+static int ad7766_probe(struct spi_device *spi)
+{
+	const struct spi_device_id *id = spi_get_device_id(spi);
+	struct iio_dev *indio_dev;
+	struct ad7766 *ad7766;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*ad7766));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	ad7766 = iio_priv(indio_dev);
+	ad7766->chip_info = &ad7766_chip_info[id->driver_data];
+
+	ad7766->mclk = devm_clk_get(&spi->dev, "mclk");
+	if (IS_ERR(ad7766->mclk))
+		return PTR_ERR(ad7766->mclk);
+
+	ad7766->reg[AD7766_SUPPLY_AVDD].supply = "avdd";
+	ad7766->reg[AD7766_SUPPLY_DVDD].supply = "dvdd";
+	ad7766->reg[AD7766_SUPPLY_VREF].supply = "vref";
+
+	ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(ad7766->reg),
+		ad7766->reg);
+	if (ret)
+		return ret;
+
+	ad7766->pd_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown",
+		GPIOD_OUT_HIGH);
+	if (IS_ERR(ad7766->pd_gpio))
+		return PTR_ERR(ad7766->pd_gpio);
+
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->name = spi_get_device_id(spi)->name;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = ad7766_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ad7766_channels);
+	indio_dev->info = &ad7766_info;
+
+	if (spi->irq > 0) {
+		ad7766->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
+			indio_dev->name, indio_dev->id);
+		if (!ad7766->trig)
+			return -ENOMEM;
+
+		ad7766->trig->ops = &ad7766_trigger_ops;
+		ad7766->trig->dev.parent = &spi->dev;
+		iio_trigger_set_drvdata(ad7766->trig, ad7766);
+
+		ret = devm_request_irq(&spi->dev, spi->irq, ad7766_irq,
+			IRQF_TRIGGER_FALLING, dev_name(&spi->dev),
+			ad7766->trig);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * The device generates interrupts as long as it is powered up.
+		 * Some platforms might not allow the option to power it down so
+		 * disable the interrupt to avoid extra load on the system
+		 */
+		disable_irq(spi->irq);
+
+		ret = devm_iio_trigger_register(&spi->dev, ad7766->trig);
+		if (ret)
+			return ret;
+	}
+
+	spi_set_drvdata(spi, indio_dev);
+
+	ad7766->spi = spi;
+
+	/* First byte always 0 */
+	ad7766->xfer.rx_buf = &ad7766->data[1];
+	ad7766->xfer.len = 3;
+
+	spi_message_init(&ad7766->msg);
+	spi_message_add_tail(&ad7766->xfer, &ad7766->msg);
+
+	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+		&iio_pollfunc_store_time, &ad7766_trigger_handler,
+		&ad7766_buffer_setup_ops);
+	if (ret)
+		return ret;
+
+	ret = devm_iio_device_register(&spi->dev, indio_dev);
+	if (ret)
+		return ret;
+	return 0;
+}
+
+static const struct spi_device_id ad7766_id[] = {
+	{"ad7766", ID_AD7766},
+	{"ad7766-1", ID_AD7766_1},
+	{"ad7766-2", ID_AD7766_2},
+	{"ad7767", ID_AD7766},
+	{"ad7767-1", ID_AD7766_1},
+	{"ad7767-2", ID_AD7766_2},
+	{}
+};
+MODULE_DEVICE_TABLE(spi, ad7766_id);
+
+static struct spi_driver ad7766_driver = {
+	.driver = {
+		.name	= "ad7766",
+	},
+	.probe		= ad7766_probe,
+	.id_table	= ad7766_id,
+};
+module_spi_driver(ad7766_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Analog Devices AD7766 and AD7767 ADCs driver support");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/at91_adc.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/at91_adc.c
--- linux-libre-4.9-gnu/drivers/iio/adc/at91_adc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/at91_adc.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,7 @@
 #include <linux/iio/trigger.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
+#include <linux/pinctrl/consumer.h>
 
 /* Registers */
 #define AT91_ADC_CR		0x00		/* Control Register */
@@ -1347,6 +1348,32 @@ static int at91_adc_remove(struct platfo
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int at91_adc_suspend(struct device *dev)
+{
+	struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev));
+	struct at91_adc_state *st = iio_priv(idev);
+
+	pinctrl_pm_select_sleep_state(dev);
+	clk_disable_unprepare(st->clk);
+
+	return 0;
+}
+
+static int at91_adc_resume(struct device *dev)
+{
+	struct iio_dev *idev = platform_get_drvdata(to_platform_device(dev));
+	struct at91_adc_state *st = iio_priv(idev);
+
+	clk_prepare_enable(st->clk);
+	pinctrl_pm_select_default_state(dev);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume);
+
 static struct at91_adc_caps at91sam9260_caps = {
 	.calc_startup_ticks = calc_startup_ticks_9260,
 	.num_channels = 4,
@@ -1441,6 +1468,7 @@ static struct platform_driver at91_adc_d
 	.driver = {
 		   .name = DRIVER_NAME,
 		   .of_match_table = of_match_ptr(at91_adc_dt_ids),
+		   .pm = &at91_adc_pm_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/envelope-detector.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/envelope-detector.c
--- linux-libre-4.9-gnu/drivers/iio/adc/envelope-detector.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/envelope-detector.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,422 @@
+/*
+ * Driver for an envelope detector using a DAC and a comparator
+ *
+ * Copyright (C) 2016 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <peda@axentia.se>
+ *
+ * This program is free software; you can 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 DAC is used to find the peak level of an alternating voltage input
+ * signal by a binary search using the output of a comparator wired to
+ * an interrupt pin. Like so:
+ *                           _
+ *                          | \
+ *     input +------>-------|+ \
+ *                          |   \
+ *            .-------.     |    }---.
+ *            |       |     |   /    |
+ *            |    dac|-->--|- /     |
+ *            |       |     |_/      |
+ *            |       |              |
+ *            |       |              |
+ *            |    irq|------<-------'
+ *            |       |
+ *            '-------'
+ */
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+
+struct envelope {
+	spinlock_t comp_lock; /* protects comp */
+	int comp;
+
+	struct mutex read_lock; /* protects everything else */
+
+	int comp_irq;
+	u32 comp_irq_trigger;
+	u32 comp_irq_trigger_inv;
+
+	struct iio_channel *dac;
+	struct delayed_work comp_timeout;
+
+	unsigned int comp_interval;
+	bool invert;
+	u32 dac_max;
+
+	int high;
+	int level;
+	int low;
+
+	struct completion done;
+};
+
+/*
+ * The envelope_detector_comp_latch function works together with the compare
+ * interrupt service routine below (envelope_detector_comp_isr) as a latch
+ * (one-bit memory) for if the interrupt has triggered since last calling
+ * this function.
+ * The ..._comp_isr function disables the interrupt so that the cpu does not
+ * need to service a possible interrupt flood from the comparator when no-one
+ * cares anyway, and this ..._comp_latch function reenables them again if
+ * needed.
+ */
+static int envelope_detector_comp_latch(struct envelope *env)
+{
+	int comp;
+
+	spin_lock_irq(&env->comp_lock);
+	comp = env->comp;
+	env->comp = 0;
+	spin_unlock_irq(&env->comp_lock);
+
+	if (!comp)
+		return 0;
+
+	/*
+	 * The irq was disabled, and is reenabled just now.
+	 * But there might have been a pending irq that
+	 * happened while the irq was disabled that fires
+	 * just as the irq is reenabled. That is not what
+	 * is desired.
+	 */
+	enable_irq(env->comp_irq);
+
+	/* So, synchronize this possibly pending irq... */
+	synchronize_irq(env->comp_irq);
+
+	/* ...and redo the whole dance. */
+	spin_lock_irq(&env->comp_lock);
+	comp = env->comp;
+	env->comp = 0;
+	spin_unlock_irq(&env->comp_lock);
+
+	if (comp)
+		enable_irq(env->comp_irq);
+
+	return 1;
+}
+
+static irqreturn_t envelope_detector_comp_isr(int irq, void *ctx)
+{
+	struct envelope *env = ctx;
+
+	spin_lock(&env->comp_lock);
+	env->comp = 1;
+	disable_irq_nosync(env->comp_irq);
+	spin_unlock(&env->comp_lock);
+
+	return IRQ_HANDLED;
+}
+
+static void envelope_detector_setup_compare(struct envelope *env)
+{
+	int ret;
+
+	/*
+	 * Do a binary search for the peak input level, and stop
+	 * when that level is "trapped" between two adjacent DAC
+	 * values.
+	 * When invert is active, use the midpoint floor so that
+	 * env->level ends up as env->low when the termination
+	 * criteria below is fulfilled, and use the midpoint
+	 * ceiling when invert is not active so that env->level
+	 * ends up as env->high in that case.
+	 */
+	env->level = (env->high + env->low + !env->invert) / 2;
+
+	if (env->high == env->low + 1) {
+		complete(&env->done);
+		return;
+	}
+
+	/* Set a "safe" DAC level (if there is such a thing)... */
+	ret = iio_write_channel_raw(env->dac, env->invert ? 0 : env->dac_max);
+	if (ret < 0)
+		goto err;
+
+	/* ...clear the comparison result... */
+	envelope_detector_comp_latch(env);
+
+	/* ...set the real DAC level... */
+	ret = iio_write_channel_raw(env->dac, env->level);
+	if (ret < 0)
+		goto err;
+
+	/* ...and wait for a bit to see if the latch catches anything. */
+	schedule_delayed_work(&env->comp_timeout,
+			      msecs_to_jiffies(env->comp_interval));
+	return;
+
+err:
+	env->level = ret;
+	complete(&env->done);
+}
+
+static void envelope_detector_timeout(struct work_struct *work)
+{
+	struct envelope *env = container_of(work, struct envelope,
+					    comp_timeout.work);
+
+	/* Adjust low/high depending on the latch content... */
+	if (!envelope_detector_comp_latch(env) ^ !env->invert)
+		env->low = env->level;
+	else
+		env->high = env->level;
+
+	/* ...and continue the search. */
+	envelope_detector_setup_compare(env);
+}
+
+static int envelope_detector_read_raw(struct iio_dev *indio_dev,
+				      struct iio_chan_spec const *chan,
+				      int *val, int *val2, long mask)
+{
+	struct envelope *env = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		/*
+		 * When invert is active, start with high=max+1 and low=0
+		 * since we will end up with the low value when the
+		 * termination criteria is fulfilled (rounding down). And
+		 * start with high=max and low=-1 when invert is not active
+		 * since we will end up with the high value in that case.
+		 * This ensures that the returned value in both cases are
+		 * in the same range as the DAC and is a value that has not
+		 * triggered the comparator.
+		 */
+		mutex_lock(&env->read_lock);
+		env->high = env->dac_max + env->invert;
+		env->low = -1 + env->invert;
+		envelope_detector_setup_compare(env);
+		wait_for_completion(&env->done);
+		if (env->level < 0) {
+			ret = env->level;
+			goto err_unlock;
+		}
+		*val = env->invert ? env->dac_max - env->level : env->level;
+		mutex_unlock(&env->read_lock);
+
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		return iio_read_channel_scale(env->dac, val, val2);
+	}
+
+	return -EINVAL;
+
+err_unlock:
+	mutex_unlock(&env->read_lock);
+	return ret;
+}
+
+static ssize_t envelope_show_invert(struct iio_dev *indio_dev,
+				    uintptr_t private,
+				    struct iio_chan_spec const *ch, char *buf)
+{
+	struct envelope *env = iio_priv(indio_dev);
+
+	return sprintf(buf, "%u\n", env->invert);
+}
+
+static ssize_t envelope_store_invert(struct iio_dev *indio_dev,
+				     uintptr_t private,
+				     struct iio_chan_spec const *ch,
+				     const char *buf, size_t len)
+{
+	struct envelope *env = iio_priv(indio_dev);
+	unsigned long invert;
+	int ret;
+	u32 trigger;
+
+	ret = kstrtoul(buf, 0, &invert);
+	if (ret < 0)
+		return ret;
+	if (invert > 1)
+		return -EINVAL;
+
+	trigger = invert ? env->comp_irq_trigger_inv : env->comp_irq_trigger;
+
+	mutex_lock(&env->read_lock);
+	if (invert != env->invert)
+		ret = irq_set_irq_type(env->comp_irq, trigger);
+	if (!ret) {
+		env->invert = invert;
+		ret = len;
+	}
+	mutex_unlock(&env->read_lock);
+
+	return ret;
+}
+
+static ssize_t envelope_show_comp_interval(struct iio_dev *indio_dev,
+					   uintptr_t private,
+					   struct iio_chan_spec const *ch,
+					   char *buf)
+{
+	struct envelope *env = iio_priv(indio_dev);
+
+	return sprintf(buf, "%u\n", env->comp_interval);
+}
+
+static ssize_t envelope_store_comp_interval(struct iio_dev *indio_dev,
+					    uintptr_t private,
+					    struct iio_chan_spec const *ch,
+					    const char *buf, size_t len)
+{
+	struct envelope *env = iio_priv(indio_dev);
+	unsigned long interval;
+	int ret;
+
+	ret = kstrtoul(buf, 0, &interval);
+	if (ret < 0)
+		return ret;
+	if (interval > 1000)
+		return -EINVAL;
+
+	mutex_lock(&env->read_lock);
+	env->comp_interval = interval;
+	mutex_unlock(&env->read_lock);
+
+	return len;
+}
+
+static const struct iio_chan_spec_ext_info envelope_detector_ext_info[] = {
+	{ .name = "invert",
+	  .read = envelope_show_invert,
+	  .write = envelope_store_invert, },
+	{ .name = "compare_interval",
+	  .read = envelope_show_comp_interval,
+	  .write = envelope_store_comp_interval, },
+	{ /* sentinel */ }
+};
+
+static const struct iio_chan_spec envelope_detector_iio_channel = {
+	.type = IIO_ALTVOLTAGE,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
+			    | BIT(IIO_CHAN_INFO_SCALE),
+	.ext_info = envelope_detector_ext_info,
+	.indexed = 1,
+};
+
+static const struct iio_info envelope_detector_info = {
+	.read_raw = &envelope_detector_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int envelope_detector_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct iio_dev *indio_dev;
+	struct envelope *env;
+	enum iio_chan_type type;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*env));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, indio_dev);
+	env = iio_priv(indio_dev);
+	env->comp_interval = 50; /* some sensible default? */
+
+	spin_lock_init(&env->comp_lock);
+	mutex_init(&env->read_lock);
+	init_completion(&env->done);
+	INIT_DELAYED_WORK(&env->comp_timeout, envelope_detector_timeout);
+
+	indio_dev->name = dev_name(dev);
+	indio_dev->dev.parent = dev;
+	indio_dev->dev.of_node = dev->of_node;
+	indio_dev->info = &envelope_detector_info;
+	indio_dev->channels = &envelope_detector_iio_channel;
+	indio_dev->num_channels = 1;
+
+	env->dac = devm_iio_channel_get(dev, "dac");
+	if (IS_ERR(env->dac)) {
+		if (PTR_ERR(env->dac) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get dac input channel\n");
+		return PTR_ERR(env->dac);
+	}
+
+	env->comp_irq = platform_get_irq_byname(pdev, "comp");
+	if (env->comp_irq < 0) {
+		if (env->comp_irq != -EPROBE_DEFER)
+			dev_err(dev, "failed to get compare interrupt\n");
+		return env->comp_irq;
+	}
+
+	ret = devm_request_irq(dev, env->comp_irq, envelope_detector_comp_isr,
+			       0, "envelope-detector", env);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "failed to request interrupt\n");
+		return ret;
+	}
+	env->comp_irq_trigger = irq_get_trigger_type(env->comp_irq);
+	if (env->comp_irq_trigger & IRQF_TRIGGER_RISING)
+		env->comp_irq_trigger_inv |= IRQF_TRIGGER_FALLING;
+	if (env->comp_irq_trigger & IRQF_TRIGGER_FALLING)
+		env->comp_irq_trigger_inv |= IRQF_TRIGGER_RISING;
+	if (env->comp_irq_trigger & IRQF_TRIGGER_HIGH)
+		env->comp_irq_trigger_inv |= IRQF_TRIGGER_LOW;
+	if (env->comp_irq_trigger & IRQF_TRIGGER_LOW)
+		env->comp_irq_trigger_inv |= IRQF_TRIGGER_HIGH;
+
+	ret = iio_get_channel_type(env->dac, &type);
+	if (ret < 0)
+		return ret;
+
+	if (type != IIO_VOLTAGE) {
+		dev_err(dev, "dac is of the wrong type\n");
+		return -EINVAL;
+	}
+
+	ret = iio_read_max_channel_raw(env->dac, &env->dac_max);
+	if (ret < 0) {
+		dev_err(dev, "dac does not indicate its raw maximum value\n");
+		return ret;
+	}
+
+	return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id envelope_detector_match[] = {
+	{ .compatible = "axentia,tse850-envelope-detector", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, envelope_detector_match);
+
+static struct platform_driver envelope_detector_driver = {
+	.probe = envelope_detector_probe,
+	.driver = {
+		.name = "iio-envelope-detector",
+		.of_match_table = envelope_detector_match,
+	},
+};
+module_platform_driver(envelope_detector_driver);
+
+MODULE_DESCRIPTION("Envelope detector using a DAC and a comparator");
+MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/adc/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/adc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -58,6 +58,18 @@ config AD7476
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7476.
 
+config AD7766
+	tristate "Analog Devices AD7766/AD7767 ADC driver"
+	depends on SPI_MASTER
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for Analog Devices AD7766, AD7766-1,
+	  AD7766-2, AD7767, AD7767-1, AD7767-2 SPI analog to digital converters.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called ad7766.
+
 config AD7791
 	tristate "Analog Devices AD7791 ADC driver"
 	depends on SPI
@@ -195,6 +207,16 @@ config DA9150_GPADC
 	  To compile this driver as a module, choose M here: the module will be
 	  called berlin2-adc.
 
+config ENVELOPE_DETECTOR
+	tristate "Envelope detector using a DAC and a comparator"
+	depends on OF
+	help
+	  Say yes here to build support for an envelope detector using a DAC
+	  and a comparator.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called envelope-detector.
+
 config EXYNOS_ADC
 	tristate "Exynos ADC driver support"
 	depends on ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
@@ -419,6 +441,28 @@ config ROCKCHIP_SARADC
 	  To compile this driver as a module, choose M here: the
 	  module will be called rockchip_saradc.
 
+config STM32_ADC_CORE
+	tristate "STMicroelectronics STM32 adc core"
+	depends on ARCH_STM32 || COMPILE_TEST
+	depends on OF
+	depends on REGULATOR
+	help
+	  Select this option to enable the core driver for STMicroelectronics
+	  STM32 analog-to-digital converter (ADC).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called stm32-adc-core.
+
+config STM32_ADC
+	tristate "STMicroelectronics STM32 adc"
+	depends on STM32_ADC_CORE
+	help
+	  Say yes here to build support for STMicroelectronics stm32 Analog
+	  to Digital Converter (ADC).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called stm32-adc.
+
 config STX104
 	tristate "Apex Embedded Systems STX104 driver"
 	depends on X86 && ISA_BUS_API
@@ -449,6 +493,8 @@ config TI_ADC081C
 config TI_ADC0832
 	tristate "Texas Instruments ADC0831/ADC0832/ADC0834/ADC0838"
 	depends on SPI
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  If you say yes here you get support for Texas Instruments ADC0831,
 	  ADC0832, ADC0834, ADC0838 ADC chips.
@@ -515,7 +561,7 @@ config TI_ADS8688
 
 config TI_AM335X_ADC
 	tristate "TI's AM335X ADC driver"
-	depends on MFD_TI_AM335X_TSCADC
+	depends on MFD_TI_AM335X_TSCADC && HAS_DMA
 	select IIO_BUFFER
 	select IIO_KFIFO_BUF
 	help
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/adc/Makefile
--- linux-libre-4.9-gnu/drivers/iio/adc/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,7 @@ obj-$(CONFIG_AD7291) += ad7291.o
 obj-$(CONFIG_AD7298) += ad7298.o
 obj-$(CONFIG_AD7923) += ad7923.o
 obj-$(CONFIG_AD7476) += ad7476.o
+obj-$(CONFIG_AD7766) += ad7766.o
 obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7887) += ad7887.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_BCM_IPROC_ADC) += bcm_iproc
 obj-$(CONFIG_BERLIN2_ADC) += berlin2-adc.o
 obj-$(CONFIG_CC10001_ADC) += cc10001_adc.o
 obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
+obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
 obj-$(CONFIG_HI8435) += hi8435.o
@@ -41,6 +43,8 @@ obj-$(CONFIG_QCOM_SPMI_IADC) += qcom-spm
 obj-$(CONFIG_QCOM_SPMI_VADC) += qcom-spmi-vadc.o
 obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
 obj-$(CONFIG_STX104) += stx104.o
+obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
+obj-$(CONFIG_STM32_ADC) += stm32-adc.o
 obj-$(CONFIG_TI_ADC081C) += ti-adc081c.o
 obj-$(CONFIG_TI_ADC0832) += ti-adc0832.o
 obj-$(CONFIG_TI_ADC12138) += ti-adc12138.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/max1027.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/max1027.c
--- linux-libre-4.9-gnu/drivers/iio/adc/max1027.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/max1027.c	2017-02-12 16:03:20.000000000 -0500
@@ -238,7 +238,9 @@ static int max1027_read_single_value(str
 
 	/* Configure conversion register with the requested chan */
 	st->reg = MAX1027_CONV_REG | MAX1027_CHAN(chan->channel) |
-		  MAX1027_NOSCAN | !!(chan->type == IIO_TEMP);
+		  MAX1027_NOSCAN;
+	if (chan->type == IIO_TEMP)
+		st->reg |= MAX1027_TEMP;
 	ret = spi_write(st->spi, &st->reg, 1);
 	if (ret < 0) {
 		dev_err(&indio_dev->dev,
@@ -360,17 +362,6 @@ static int max1027_set_trigger_state(str
 	return 0;
 }
 
-static int max1027_validate_device(struct iio_trigger *trig,
-				   struct iio_dev *indio_dev)
-{
-	struct iio_dev *indio = iio_trigger_get_drvdata(trig);
-
-	if (indio != indio_dev)
-		return -EINVAL;
-
-	return 0;
-}
-
 static irqreturn_t max1027_trigger_handler(int irq, void *private)
 {
 	struct iio_poll_func *pf = (struct iio_poll_func *)private;
@@ -391,7 +382,7 @@ static irqreturn_t max1027_trigger_handl
 
 static const struct iio_trigger_ops max1027_trigger_ops = {
 	.owner = THIS_MODULE,
-	.validate_device = &max1027_validate_device,
+	.validate_device = &iio_trigger_validate_own_device,
 	.set_trigger_state = &max1027_set_trigger_state,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/palmas_gpadc.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/palmas_gpadc.c
--- linux-libre-4.9-gnu/drivers/iio/adc/palmas_gpadc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/palmas_gpadc.c	2017-02-12 16:03:20.000000000 -0500
@@ -775,7 +775,7 @@ static int palmas_adc_wakeup_reset(struc
 
 static int palmas_gpadc_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct palmas_gpadc *adc = iio_priv(indio_dev);
 	int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
 	int ret;
@@ -798,7 +798,7 @@ static int palmas_gpadc_suspend(struct d
 
 static int palmas_gpadc_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct palmas_gpadc *adc = iio_priv(indio_dev);
 	int wakeup = adc->wakeup1_enable || adc->wakeup2_enable;
 	int ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/stm32-adc.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/stm32-adc.c
--- linux-libre-4.9-gnu/drivers/iio/adc/stm32-adc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/stm32-adc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,518 @@
+/*
+ * This file is part of STM32 ADC driver
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
+ *
+ * License type: GPLv2
+ *
+ * This program is free software; you can 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/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/iio/iio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include "stm32-adc-core.h"
+
+/* STM32F4 - Registers for each ADC instance */
+#define STM32F4_ADC_SR			0x00
+#define STM32F4_ADC_CR1			0x04
+#define STM32F4_ADC_CR2			0x08
+#define STM32F4_ADC_SMPR1		0x0C
+#define STM32F4_ADC_SMPR2		0x10
+#define STM32F4_ADC_HTR			0x24
+#define STM32F4_ADC_LTR			0x28
+#define STM32F4_ADC_SQR1		0x2C
+#define STM32F4_ADC_SQR2		0x30
+#define STM32F4_ADC_SQR3		0x34
+#define STM32F4_ADC_JSQR		0x38
+#define STM32F4_ADC_JDR1		0x3C
+#define STM32F4_ADC_JDR2		0x40
+#define STM32F4_ADC_JDR3		0x44
+#define STM32F4_ADC_JDR4		0x48
+#define STM32F4_ADC_DR			0x4C
+
+/* STM32F4_ADC_SR - bit fields */
+#define STM32F4_STRT			BIT(4)
+#define STM32F4_EOC			BIT(1)
+
+/* STM32F4_ADC_CR1 - bit fields */
+#define STM32F4_SCAN			BIT(8)
+#define STM32F4_EOCIE			BIT(5)
+
+/* STM32F4_ADC_CR2 - bit fields */
+#define STM32F4_SWSTART			BIT(30)
+#define STM32F4_EXTEN_MASK		GENMASK(29, 28)
+#define STM32F4_EOCS			BIT(10)
+#define STM32F4_ADON			BIT(0)
+
+/* STM32F4_ADC_SQR1 - bit fields */
+#define STM32F4_L_SHIFT			20
+#define STM32F4_L_MASK			GENMASK(23, 20)
+
+/* STM32F4_ADC_SQR3 - bit fields */
+#define STM32F4_SQ1_SHIFT		0
+#define STM32F4_SQ1_MASK		GENMASK(4, 0)
+
+#define STM32_ADC_TIMEOUT_US		100000
+#define STM32_ADC_TIMEOUT	(msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
+
+/**
+ * struct stm32_adc - private data of each ADC IIO instance
+ * @common:		reference to ADC block common data
+ * @offset:		ADC instance register offset in ADC block
+ * @completion:		end of single conversion completion
+ * @buffer:		data buffer
+ * @clk:		clock for this adc instance
+ * @irq:		interrupt for this adc instance
+ * @lock:		spinlock
+ */
+struct stm32_adc {
+	struct stm32_adc_common	*common;
+	u32			offset;
+	struct completion	completion;
+	u16			*buffer;
+	struct clk		*clk;
+	int			irq;
+	spinlock_t		lock;		/* interrupt lock */
+};
+
+/**
+ * struct stm32_adc_chan_spec - specification of stm32 adc channel
+ * @type:	IIO channel type
+ * @channel:	channel number (single ended)
+ * @name:	channel name (single ended)
+ */
+struct stm32_adc_chan_spec {
+	enum iio_chan_type	type;
+	int			channel;
+	const char		*name;
+};
+
+/* Input definitions common for all STM32F4 instances */
+static const struct stm32_adc_chan_spec stm32f4_adc123_channels[] = {
+	{ IIO_VOLTAGE, 0, "in0" },
+	{ IIO_VOLTAGE, 1, "in1" },
+	{ IIO_VOLTAGE, 2, "in2" },
+	{ IIO_VOLTAGE, 3, "in3" },
+	{ IIO_VOLTAGE, 4, "in4" },
+	{ IIO_VOLTAGE, 5, "in5" },
+	{ IIO_VOLTAGE, 6, "in6" },
+	{ IIO_VOLTAGE, 7, "in7" },
+	{ IIO_VOLTAGE, 8, "in8" },
+	{ IIO_VOLTAGE, 9, "in9" },
+	{ IIO_VOLTAGE, 10, "in10" },
+	{ IIO_VOLTAGE, 11, "in11" },
+	{ IIO_VOLTAGE, 12, "in12" },
+	{ IIO_VOLTAGE, 13, "in13" },
+	{ IIO_VOLTAGE, 14, "in14" },
+	{ IIO_VOLTAGE, 15, "in15" },
+};
+
+/**
+ * STM32 ADC registers access routines
+ * @adc: stm32 adc instance
+ * @reg: reg offset in adc instance
+ *
+ * Note: All instances share same base, with 0x0, 0x100 or 0x200 offset resp.
+ * for adc1, adc2 and adc3.
+ */
+static u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg)
+{
+	return readl_relaxed(adc->common->base + adc->offset + reg);
+}
+
+static u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg)
+{
+	return readw_relaxed(adc->common->base + adc->offset + reg);
+}
+
+static void stm32_adc_writel(struct stm32_adc *adc, u32 reg, u32 val)
+{
+	writel_relaxed(val, adc->common->base + adc->offset + reg);
+}
+
+static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&adc->lock, flags);
+	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) | bits);
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&adc->lock, flags);
+	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) & ~bits);
+	spin_unlock_irqrestore(&adc->lock, flags);
+}
+
+/**
+ * stm32_adc_conv_irq_enable() - Enable end of conversion interrupt
+ * @adc: stm32 adc instance
+ */
+static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
+{
+	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
+};
+
+/**
+ * stm32_adc_conv_irq_disable() - Disable end of conversion interrupt
+ * @adc: stm32 adc instance
+ */
+static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
+{
+	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_EOCIE);
+}
+
+/**
+ * stm32_adc_start_conv() - Start conversions for regular channels.
+ * @adc: stm32 adc instance
+ */
+static void stm32_adc_start_conv(struct stm32_adc *adc)
+{
+	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
+	stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_EOCS | STM32F4_ADON);
+
+	/* Wait for Power-up time (tSTAB from datasheet) */
+	usleep_range(2, 3);
+
+	/* Software start ? (e.g. trigger detection disabled ?) */
+	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & STM32F4_EXTEN_MASK))
+		stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
+}
+
+static void stm32_adc_stop_conv(struct stm32_adc *adc)
+{
+	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
+	stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
+
+	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
+	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_ADON);
+}
+
+/**
+ * stm32_adc_single_conv() - Performs a single conversion
+ * @indio_dev: IIO device
+ * @chan: IIO channel
+ * @res: conversion result
+ *
+ * The function performs a single conversion on a given channel:
+ * - Program sequencer with one channel (e.g. in SQ1 with len = 1)
+ * - Use SW trigger
+ * - Start conversion, then wait for interrupt completion.
+ */
+static int stm32_adc_single_conv(struct iio_dev *indio_dev,
+				 const struct iio_chan_spec *chan,
+				 int *res)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	long timeout;
+	u32 val;
+	u16 result;
+	int ret;
+
+	reinit_completion(&adc->completion);
+
+	adc->buffer = &result;
+
+	/* Program chan number in regular sequence */
+	val = stm32_adc_readl(adc, STM32F4_ADC_SQR3);
+	val &= ~STM32F4_SQ1_MASK;
+	val |= chan->channel << STM32F4_SQ1_SHIFT;
+	stm32_adc_writel(adc, STM32F4_ADC_SQR3, val);
+
+	/* Set regular sequence len (0 for 1 conversion) */
+	stm32_adc_clr_bits(adc, STM32F4_ADC_SQR1, STM32F4_L_MASK);
+
+	/* Trigger detection disabled (conversion can be launched in SW) */
+	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
+
+	stm32_adc_conv_irq_enable(adc);
+
+	stm32_adc_start_conv(adc);
+
+	timeout = wait_for_completion_interruptible_timeout(
+					&adc->completion, STM32_ADC_TIMEOUT);
+	if (timeout == 0) {
+		ret = -ETIMEDOUT;
+	} else if (timeout < 0) {
+		ret = timeout;
+	} else {
+		*res = result;
+		ret = IIO_VAL_INT;
+	}
+
+	stm32_adc_stop_conv(adc);
+
+	stm32_adc_conv_irq_disable(adc);
+
+	return ret;
+}
+
+static int stm32_adc_read_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2, long mask)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
+		if (chan->type == IIO_VOLTAGE)
+			ret = stm32_adc_single_conv(indio_dev, chan, val);
+		else
+			ret = -EINVAL;
+		iio_device_release_direct_mode(indio_dev);
+		return ret;
+
+	case IIO_CHAN_INFO_SCALE:
+		*val = adc->common->vref_mv;
+		*val2 = chan->scan_type.realbits;
+		return IIO_VAL_FRACTIONAL_LOG2;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t stm32_adc_isr(int irq, void *data)
+{
+	struct stm32_adc *adc = data;
+	u32 status = stm32_adc_readl(adc, STM32F4_ADC_SR);
+
+	if (status & STM32F4_EOC) {
+		*adc->buffer = stm32_adc_readw(adc, STM32F4_ADC_DR);
+		complete(&adc->completion);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int stm32_adc_of_xlate(struct iio_dev *indio_dev,
+			      const struct of_phandle_args *iiospec)
+{
+	int i;
+
+	for (i = 0; i < indio_dev->num_channels; i++)
+		if (indio_dev->channels[i].channel == iiospec->args[0])
+			return i;
+
+	return -EINVAL;
+}
+
+/**
+ * stm32_adc_debugfs_reg_access - read or write register value
+ *
+ * To read a value from an ADC register:
+ *   echo [ADC reg offset] > direct_reg_access
+ *   cat direct_reg_access
+ *
+ * To write a value in a ADC register:
+ *   echo [ADC_reg_offset] [value] > direct_reg_access
+ */
+static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
+					unsigned reg, unsigned writeval,
+					unsigned *readval)
+{
+	struct stm32_adc *adc = iio_priv(indio_dev);
+
+	if (!readval)
+		stm32_adc_writel(adc, reg, writeval);
+	else
+		*readval = stm32_adc_readl(adc, reg);
+
+	return 0;
+}
+
+static const struct iio_info stm32_adc_iio_info = {
+	.read_raw = stm32_adc_read_raw,
+	.debugfs_reg_access = stm32_adc_debugfs_reg_access,
+	.of_xlate = stm32_adc_of_xlate,
+	.driver_module = THIS_MODULE,
+};
+
+static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
+				    struct iio_chan_spec *chan,
+				    const struct stm32_adc_chan_spec *channel,
+				    int scan_index)
+{
+	chan->type = channel->type;
+	chan->channel = channel->channel;
+	chan->datasheet_name = channel->name;
+	chan->scan_index = scan_index;
+	chan->indexed = 1;
+	chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+	chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+	chan->scan_type.sign = 'u';
+	chan->scan_type.realbits = 12;
+	chan->scan_type.storagebits = 16;
+}
+
+static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
+{
+	struct device_node *node = indio_dev->dev.of_node;
+	struct property *prop;
+	const __be32 *cur;
+	struct iio_chan_spec *channels;
+	int scan_index = 0, num_channels;
+	u32 val;
+
+	num_channels = of_property_count_u32_elems(node, "st,adc-channels");
+	if (num_channels < 0 ||
+	    num_channels >= ARRAY_SIZE(stm32f4_adc123_channels)) {
+		dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
+		return num_channels < 0 ? num_channels : -EINVAL;
+	}
+
+	channels = devm_kcalloc(&indio_dev->dev, num_channels,
+				sizeof(struct iio_chan_spec), GFP_KERNEL);
+	if (!channels)
+		return -ENOMEM;
+
+	of_property_for_each_u32(node, "st,adc-channels", prop, cur, val) {
+		if (val >= ARRAY_SIZE(stm32f4_adc123_channels)) {
+			dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
+			return -EINVAL;
+		}
+		stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
+					&stm32f4_adc123_channels[val],
+					scan_index);
+		scan_index++;
+	}
+
+	indio_dev->num_channels = scan_index;
+	indio_dev->channels = channels;
+
+	return 0;
+}
+
+static int stm32_adc_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev;
+	struct stm32_adc *adc;
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	adc = iio_priv(indio_dev);
+	adc->common = dev_get_drvdata(pdev->dev.parent);
+	spin_lock_init(&adc->lock);
+	init_completion(&adc->completion);
+
+	indio_dev->name = dev_name(&pdev->dev);
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->info = &stm32_adc_iio_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	platform_set_drvdata(pdev, adc);
+
+	ret = of_property_read_u32(pdev->dev.of_node, "reg", &adc->offset);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "missing reg property\n");
+		return -EINVAL;
+	}
+
+	adc->irq = platform_get_irq(pdev, 0);
+	if (adc->irq < 0) {
+		dev_err(&pdev->dev, "failed to get irq\n");
+		return adc->irq;
+	}
+
+	ret = devm_request_irq(&pdev->dev, adc->irq, stm32_adc_isr,
+			       0, pdev->name, adc);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request IRQ\n");
+		return ret;
+	}
+
+	adc->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(adc->clk)) {
+		dev_err(&pdev->dev, "Can't get clock\n");
+		return PTR_ERR(adc->clk);
+	}
+
+	ret = clk_prepare_enable(adc->clk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "clk enable failed\n");
+		return ret;
+	}
+
+	ret = stm32_adc_chan_of_init(indio_dev);
+	if (ret < 0)
+		goto err_clk_disable;
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "iio dev register failed\n");
+		goto err_clk_disable;
+	}
+
+	return 0;
+
+err_clk_disable:
+	clk_disable_unprepare(adc->clk);
+
+	return ret;
+}
+
+static int stm32_adc_remove(struct platform_device *pdev)
+{
+	struct stm32_adc *adc = platform_get_drvdata(pdev);
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+
+	iio_device_unregister(indio_dev);
+	clk_disable_unprepare(adc->clk);
+
+	return 0;
+}
+
+static const struct of_device_id stm32_adc_of_match[] = {
+	{ .compatible = "st,stm32f4-adc" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
+
+static struct platform_driver stm32_adc_driver = {
+	.probe = stm32_adc_probe,
+	.remove = stm32_adc_remove,
+	.driver = {
+		.name = "stm32-adc",
+		.of_match_table = stm32_adc_of_match,
+	},
+};
+module_platform_driver(stm32_adc_driver);
+
+MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 ADC IIO driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:stm32-adc");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/stm32-adc-core.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/stm32-adc-core.c
--- linux-libre-4.9-gnu/drivers/iio/adc/stm32-adc-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/stm32-adc-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,303 @@
+/*
+ * This file is part of STM32 ADC driver
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
+ *
+ * Inspired from: fsl-imx25-tsadc
+ *
+ * License type: GPLv2
+ *
+ * This program is free software; you can 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/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdesc.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+#include "stm32-adc-core.h"
+
+/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
+#define STM32F4_ADC_CSR			(STM32_ADCX_COMN_OFFSET + 0x00)
+#define STM32F4_ADC_CCR			(STM32_ADCX_COMN_OFFSET + 0x04)
+
+/* STM32F4_ADC_CSR - bit fields */
+#define STM32F4_EOC3			BIT(17)
+#define STM32F4_EOC2			BIT(9)
+#define STM32F4_EOC1			BIT(1)
+
+/* STM32F4_ADC_CCR - bit fields */
+#define STM32F4_ADC_ADCPRE_SHIFT	16
+#define STM32F4_ADC_ADCPRE_MASK		GENMASK(17, 16)
+
+/* STM32 F4 maximum analog clock rate (from datasheet) */
+#define STM32F4_ADC_MAX_CLK_RATE	36000000
+
+/**
+ * struct stm32_adc_priv - stm32 ADC core private data
+ * @irq:		irq for ADC block
+ * @domain:		irq domain reference
+ * @aclk:		clock reference for the analog circuitry
+ * @vref:		regulator reference
+ * @common:		common data for all ADC instances
+ */
+struct stm32_adc_priv {
+	int				irq;
+	struct irq_domain		*domain;
+	struct clk			*aclk;
+	struct regulator		*vref;
+	struct stm32_adc_common		common;
+};
+
+static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
+{
+	return container_of(com, struct stm32_adc_priv, common);
+}
+
+/* STM32F4 ADC internal common clock prescaler division ratios */
+static int stm32f4_pclk_div[] = {2, 4, 6, 8};
+
+/**
+ * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler
+ * @priv: stm32 ADC core private data
+ * Select clock prescaler used for analog conversions, before using ADC.
+ */
+static int stm32f4_adc_clk_sel(struct platform_device *pdev,
+			       struct stm32_adc_priv *priv)
+{
+	unsigned long rate;
+	u32 val;
+	int i;
+
+	rate = clk_get_rate(priv->aclk);
+	for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
+		if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
+			break;
+	}
+	if (i >= ARRAY_SIZE(stm32f4_pclk_div))
+		return -EINVAL;
+
+	val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
+	val &= ~STM32F4_ADC_ADCPRE_MASK;
+	val |= i << STM32F4_ADC_ADCPRE_SHIFT;
+	writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR);
+
+	dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n",
+		rate / (stm32f4_pclk_div[i] * 1000));
+
+	return 0;
+}
+
+/* ADC common interrupt for all instances */
+static void stm32_adc_irq_handler(struct irq_desc *desc)
+{
+	struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	u32 status;
+
+	chained_irq_enter(chip, desc);
+	status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR);
+
+	if (status & STM32F4_EOC1)
+		generic_handle_irq(irq_find_mapping(priv->domain, 0));
+
+	if (status & STM32F4_EOC2)
+		generic_handle_irq(irq_find_mapping(priv->domain, 1));
+
+	if (status & STM32F4_EOC3)
+		generic_handle_irq(irq_find_mapping(priv->domain, 2));
+
+	chained_irq_exit(chip, desc);
+};
+
+static int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq,
+				irq_hw_number_t hwirq)
+{
+	irq_set_chip_data(irq, d->host_data);
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
+
+	return 0;
+}
+
+static void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq)
+{
+	irq_set_chip_and_handler(irq, NULL, NULL);
+	irq_set_chip_data(irq, NULL);
+}
+
+static const struct irq_domain_ops stm32_adc_domain_ops = {
+	.map = stm32_adc_domain_map,
+	.unmap  = stm32_adc_domain_unmap,
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static int stm32_adc_irq_probe(struct platform_device *pdev,
+			       struct stm32_adc_priv *priv)
+{
+	struct device_node *np = pdev->dev.of_node;
+
+	priv->irq = platform_get_irq(pdev, 0);
+	if (priv->irq < 0) {
+		dev_err(&pdev->dev, "failed to get irq\n");
+		return priv->irq;
+	}
+
+	priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
+					     &stm32_adc_domain_ops,
+					     priv);
+	if (!priv->domain) {
+		dev_err(&pdev->dev, "Failed to add irq domain\n");
+		return -ENOMEM;
+	}
+
+	irq_set_chained_handler(priv->irq, stm32_adc_irq_handler);
+	irq_set_handler_data(priv->irq, priv);
+
+	return 0;
+}
+
+static void stm32_adc_irq_remove(struct platform_device *pdev,
+				 struct stm32_adc_priv *priv)
+{
+	int hwirq;
+
+	for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
+		irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
+	irq_domain_remove(priv->domain);
+	irq_set_chained_handler(priv->irq, NULL);
+}
+
+static int stm32_adc_probe(struct platform_device *pdev)
+{
+	struct stm32_adc_priv *priv;
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->common.base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->common.base))
+		return PTR_ERR(priv->common.base);
+
+	priv->vref = devm_regulator_get(&pdev->dev, "vref");
+	if (IS_ERR(priv->vref)) {
+		ret = PTR_ERR(priv->vref);
+		dev_err(&pdev->dev, "vref get failed, %d\n", ret);
+		return ret;
+	}
+
+	ret = regulator_enable(priv->vref);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "vref enable failed\n");
+		return ret;
+	}
+
+	ret = regulator_get_voltage(priv->vref);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
+		goto err_regulator_disable;
+	}
+	priv->common.vref_mv = ret / 1000;
+	dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
+
+	priv->aclk = devm_clk_get(&pdev->dev, "adc");
+	if (IS_ERR(priv->aclk)) {
+		ret = PTR_ERR(priv->aclk);
+		dev_err(&pdev->dev, "Can't get 'adc' clock\n");
+		goto err_regulator_disable;
+	}
+
+	ret = clk_prepare_enable(priv->aclk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "adc clk enable failed\n");
+		goto err_regulator_disable;
+	}
+
+	ret = stm32f4_adc_clk_sel(pdev, priv);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "adc clk selection failed\n");
+		goto err_clk_disable;
+	}
+
+	ret = stm32_adc_irq_probe(pdev, priv);
+	if (ret < 0)
+		goto err_clk_disable;
+
+	platform_set_drvdata(pdev, &priv->common);
+
+	ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to populate DT children\n");
+		goto err_irq_remove;
+	}
+
+	return 0;
+
+err_irq_remove:
+	stm32_adc_irq_remove(pdev, priv);
+
+err_clk_disable:
+	clk_disable_unprepare(priv->aclk);
+
+err_regulator_disable:
+	regulator_disable(priv->vref);
+
+	return ret;
+}
+
+static int stm32_adc_remove(struct platform_device *pdev)
+{
+	struct stm32_adc_common *common = platform_get_drvdata(pdev);
+	struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
+
+	of_platform_depopulate(&pdev->dev);
+	stm32_adc_irq_remove(pdev, priv);
+	clk_disable_unprepare(priv->aclk);
+	regulator_disable(priv->vref);
+
+	return 0;
+}
+
+static const struct of_device_id stm32_adc_of_match[] = {
+	{ .compatible = "st,stm32f4-adc-core" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
+
+static struct platform_driver stm32_adc_driver = {
+	.probe = stm32_adc_probe,
+	.remove = stm32_adc_remove,
+	.driver = {
+		.name = "stm32-adc-core",
+		.of_match_table = stm32_adc_of_match,
+	},
+};
+module_platform_driver(stm32_adc_driver);
+
+MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 ADC core driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:stm32-adc-core");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/stm32-adc-core.h linux-libre-4.10-rc8-gnu/drivers/iio/adc/stm32-adc-core.h
--- linux-libre-4.9-gnu/drivers/iio/adc/stm32-adc-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/stm32-adc-core.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,52 @@
+/*
+ * This file is part of STM32 ADC driver
+ *
+ * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
+ * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
+ *
+ * License type: GPLv2
+ *
+ * This program is free software; you can 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 __STM32_ADC_H
+#define __STM32_ADC_H
+
+/*
+ * STM32 - ADC global register map
+ * ________________________________________________________
+ * | Offset |                 Register                    |
+ * --------------------------------------------------------
+ * | 0x000  |                Master ADC1                  |
+ * --------------------------------------------------------
+ * | 0x100  |                Slave ADC2                   |
+ * --------------------------------------------------------
+ * | 0x200  |                Slave ADC3                   |
+ * --------------------------------------------------------
+ * | 0x300  |         Master & Slave common regs          |
+ * --------------------------------------------------------
+ */
+#define STM32_ADC_MAX_ADCS		3
+#define STM32_ADCX_COMN_OFFSET		0x300
+
+/**
+ * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
+ * @base:		control registers base cpu addr
+ * @vref_mv:		vref voltage (mv)
+ */
+struct stm32_adc_common {
+	void __iomem			*base;
+	int				vref_mv;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/ti-adc0832.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/ti-adc0832.c
--- linux-libre-4.9-gnu/drivers/iio/adc/ti-adc0832.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/ti-adc0832.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,10 @@
 #include <linux/spi/spi.h>
 #include <linux/iio/iio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
 
 enum {
 	adc0831,
@@ -38,10 +42,16 @@ struct adc0832 {
 		.indexed = 1,						\
 		.channel = chan,					\
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.scan_index = chan,					\
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = 8,					\
+			.storagebits = 8,				\
+		},							\
 	}
 
-#define ADC0832_VOLTAGE_CHANNEL_DIFF(chan1, chan2)			\
+#define ADC0832_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si)			\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.indexed = 1,						\
@@ -49,18 +59,26 @@ struct adc0832 {
 		.channel2 = (chan2),					\
 		.differential = 1,					\
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.scan_index = si,					\
+		.scan_type = {						\
+			.sign = 'u',					\
+			.realbits = 8,					\
+			.storagebits = 8,				\
+		},							\
 	}
 
 static const struct iio_chan_spec adc0831_channels[] = {
-	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 0),
+	IIO_CHAN_SOFT_TIMESTAMP(1),
 };
 
 static const struct iio_chan_spec adc0832_channels[] = {
 	ADC0832_VOLTAGE_CHANNEL(0),
 	ADC0832_VOLTAGE_CHANNEL(1),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 2),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 3),
+	IIO_CHAN_SOFT_TIMESTAMP(4),
 };
 
 static const struct iio_chan_spec adc0834_channels[] = {
@@ -68,10 +86,11 @@ static const struct iio_chan_spec adc083
 	ADC0832_VOLTAGE_CHANNEL(1),
 	ADC0832_VOLTAGE_CHANNEL(2),
 	ADC0832_VOLTAGE_CHANNEL(3),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 4),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 5),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3, 6),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2, 7),
+	IIO_CHAN_SOFT_TIMESTAMP(8),
 };
 
 static const struct iio_chan_spec adc0838_channels[] = {
@@ -83,14 +102,15 @@ static const struct iio_chan_spec adc083
 	ADC0832_VOLTAGE_CHANNEL(5),
 	ADC0832_VOLTAGE_CHANNEL(6),
 	ADC0832_VOLTAGE_CHANNEL(7),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(4, 5),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(5, 4),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(6, 7),
-	ADC0832_VOLTAGE_CHANNEL_DIFF(7, 6),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(0, 1, 8),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(1, 0, 9),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(2, 3, 10),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(3, 2, 11),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(4, 5, 12),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(5, 4, 13),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(6, 7, 14),
+	ADC0832_VOLTAGE_CHANNEL_DIFF(7, 6, 15),
+	IIO_CHAN_SOFT_TIMESTAMP(16),
 };
 
 static int adc0831_adc_conversion(struct adc0832 *adc)
@@ -178,6 +198,42 @@ static const struct iio_info adc0832_inf
 	.driver_module = THIS_MODULE,
 };
 
+static irqreturn_t adc0832_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct adc0832 *adc = iio_priv(indio_dev);
+	u8 data[24] = { }; /* 16x 1 byte ADC data + 8 bytes timestamp */
+	int scan_index;
+	int i = 0;
+
+	mutex_lock(&adc->lock);
+
+	for_each_set_bit(scan_index, indio_dev->active_scan_mask,
+			 indio_dev->masklength) {
+		const struct iio_chan_spec *scan_chan =
+				&indio_dev->channels[scan_index];
+		int ret = adc0832_adc_conversion(adc, scan_chan->channel,
+						 scan_chan->differential);
+		if (ret < 0) {
+			dev_warn(&adc->spi->dev,
+				 "failed to get conversion data\n");
+			goto out;
+		}
+
+		data[i] = ret;
+		i++;
+	}
+	iio_push_to_buffers_with_timestamp(indio_dev, data,
+					   iio_get_time_ns(indio_dev));
+out:
+	mutex_unlock(&adc->lock);
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
 static int adc0832_probe(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev;
@@ -233,9 +289,20 @@ static int adc0832_probe(struct spi_devi
 
 	spi_set_drvdata(spi, indio_dev);
 
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 adc0832_trigger_handler, NULL);
+	if (ret)
+		goto err_reg_disable;
+
 	ret = iio_device_register(indio_dev);
 	if (ret)
-		regulator_disable(adc->reg);
+		goto err_buffer_cleanup;
+
+	return 0;
+err_buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+err_reg_disable:
+	regulator_disable(adc->reg);
 
 	return ret;
 }
@@ -246,6 +313,7 @@ static int adc0832_remove(struct spi_dev
 	struct adc0832 *adc = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
 	regulator_disable(adc->reg);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/ti-adc161s626.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/ti-adc161s626.c
--- linux-libre-4.9-gnu/drivers/iio/adc/ti-adc161s626.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/ti-adc161s626.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
+#include <linux/regulator/consumer.h>
 
 #define TI_ADC_DRV_NAME	"ti-adc161s626"
 
@@ -39,7 +40,9 @@ static const struct iio_chan_spec ti_adc
 	{
 		.type = IIO_VOLTAGE,
 		.channel = 0,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OFFSET),
 		.scan_index = 0,
 		.scan_type = {
 			.sign = 's',
@@ -54,7 +57,9 @@ static const struct iio_chan_spec ti_adc
 	{
 		.type = IIO_VOLTAGE,
 		.channel = 0,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OFFSET),
 		.scan_index = 0,
 		.scan_type = {
 			.sign = 's',
@@ -68,6 +73,8 @@ static const struct iio_chan_spec ti_adc
 struct ti_adc_data {
 	struct iio_dev *indio_dev;
 	struct spi_device *spi;
+	struct regulator *ref;
+
 	u8 read_size;
 	u8 shift;
 
@@ -135,18 +142,32 @@ static int ti_adc_read_raw(struct iio_de
 	struct ti_adc_data *data = iio_priv(indio_dev);
 	int ret;
 
-	if (mask != IIO_CHAN_INFO_RAW)
-		return -EINVAL;
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
 
-	ret = iio_device_claim_direct_mode(indio_dev);
-	if (ret)
-		return ret;
+		ret = ti_adc_read_measurement(data, chan, val);
+		iio_device_release_direct_mode(indio_dev);
 
-	ret = ti_adc_read_measurement(data, chan, val);
-	iio_device_release_direct_mode(indio_dev);
+		if (ret)
+			return ret;
 
-	if (!ret)
 		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		ret = regulator_get_voltage(data->ref);
+		if (ret < 0)
+			return ret;
+
+		*val = ret / 1000;
+		*val2 = chan->scan_type.realbits;
+
+		return IIO_VAL_FRACTIONAL_LOG2;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = 1 << (chan->scan_type.realbits - 1);
+		return IIO_VAL_INT;
+	}
 
 	return 0;
 }
@@ -191,10 +212,17 @@ static int ti_adc_probe(struct spi_devic
 		break;
 	}
 
+	data->ref = devm_regulator_get(&spi->dev, "vdda");
+	if (!IS_ERR(data->ref)) {
+		ret = regulator_enable(data->ref);
+		if (ret < 0)
+			return ret;
+	}
+
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
 					 ti_adc_trigger_handler, NULL);
 	if (ret)
-		return ret;
+		goto error_regulator_disable;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
@@ -205,15 +233,20 @@ static int ti_adc_probe(struct spi_devic
 error_unreg_buffer:
 	iio_triggered_buffer_cleanup(indio_dev);
 
+error_regulator_disable:
+	regulator_disable(data->ref);
+
 	return ret;
 }
 
 static int ti_adc_remove(struct spi_device *spi)
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	struct ti_adc_data *data = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
+	regulator_disable(data->ref);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/adc/ti_am335x_adc.c linux-libre-4.10-rc8-gnu/drivers/iio/adc/ti_am335x_adc.c
--- linux-libre-4.9-gnu/drivers/iio/adc/ti_am335x_adc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/adc/ti_am335x_adc.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,10 +30,28 @@
 #include <linux/iio/buffer.h>
 #include <linux/iio/kfifo_buf.h>
 
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+
+#define DMA_BUFFER_SIZE		SZ_2K
+
+struct tiadc_dma {
+	struct dma_slave_config	conf;
+	struct dma_chan		*chan;
+	dma_addr_t		addr;
+	dma_cookie_t		cookie;
+	u8			*buf;
+	int			current_period;
+	int			period_size;
+	u8			fifo_thresh;
+};
+
 struct tiadc_device {
 	struct ti_tscadc_dev *mfd_tscadc;
+	struct tiadc_dma dma;
 	struct mutex fifo1_lock; /* to protect fifo access */
 	int channels;
+	int total_ch_enabled;
 	u8 channel_line[8];
 	u8 channel_step[8];
 	int buffer_en_ch_steps;
@@ -198,6 +216,67 @@ static irqreturn_t tiadc_worker_h(int ir
 	return IRQ_HANDLED;
 }
 
+static void tiadc_dma_rx_complete(void *param)
+{
+	struct iio_dev *indio_dev = param;
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	u8 *data;
+	int i;
+
+	data = dma->buf + dma->current_period * dma->period_size;
+	dma->current_period = 1 - dma->current_period; /* swap the buffer ID */
+
+	for (i = 0; i < dma->period_size; i += indio_dev->scan_bytes) {
+		iio_push_to_buffers(indio_dev, data);
+		data += indio_dev->scan_bytes;
+	}
+}
+
+static int tiadc_start_dma(struct iio_dev *indio_dev)
+{
+	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	struct dma_async_tx_descriptor *desc;
+
+	dma->current_period = 0; /* We start to fill period 0 */
+	/*
+	 * Make the fifo thresh as the multiple of total number of
+	 * channels enabled, so make sure that cyclic DMA period
+	 * length is also a multiple of total number of channels
+	 * enabled. This ensures that no invalid data is reported
+	 * to the stack via iio_push_to_buffers().
+	 */
+	dma->fifo_thresh = rounddown(FIFO1_THRESHOLD + 1,
+				     adc_dev->total_ch_enabled) - 1;
+	/* Make sure that period length is multiple of fifo thresh level */
+	dma->period_size = rounddown(DMA_BUFFER_SIZE / 2,
+				    (dma->fifo_thresh + 1) * sizeof(u16));
+
+	dma->conf.src_maxburst = dma->fifo_thresh + 1;
+	dmaengine_slave_config(dma->chan, &dma->conf);
+
+	desc = dmaengine_prep_dma_cyclic(dma->chan, dma->addr,
+					 dma->period_size * 2,
+					 dma->period_size, DMA_DEV_TO_MEM,
+					 DMA_PREP_INTERRUPT);
+	if (!desc)
+		return -EBUSY;
+
+	desc->callback = tiadc_dma_rx_complete;
+	desc->callback_param = indio_dev;
+
+	dma->cookie = dmaengine_submit(desc);
+
+	dma_async_issue_pending(dma->chan);
+
+	tiadc_writel(adc_dev, REG_FIFO1THR, dma->fifo_thresh);
+	tiadc_writel(adc_dev, REG_DMA1REQ, dma->fifo_thresh);
+	tiadc_writel(adc_dev, REG_DMAENABLE_SET, DMA_FIFO1);
+
+	return 0;
+}
+
 static int tiadc_buffer_preenable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
@@ -218,20 +297,30 @@ static int tiadc_buffer_preenable(struct
 static int tiadc_buffer_postenable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
+	unsigned int irq_enable;
 	unsigned int enb = 0;
 	u8 bit;
 
 	tiadc_step_config(indio_dev);
-	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels)
+	for_each_set_bit(bit, indio_dev->active_scan_mask, adc_dev->channels) {
 		enb |= (get_adc_step_bit(adc_dev, bit) << 1);
+		adc_dev->total_ch_enabled++;
+	}
 	adc_dev->buffer_en_ch_steps = enb;
 
+	if (dma->chan)
+		tiadc_start_dma(indio_dev);
+
 	am335x_tsc_se_set_cache(adc_dev->mfd_tscadc, enb);
 
 	tiadc_writel(adc_dev,  REG_IRQSTATUS, IRQENB_FIFO1THRES
 				| IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW);
-	tiadc_writel(adc_dev,  REG_IRQENABLE, IRQENB_FIFO1THRES
-				| IRQENB_FIFO1OVRRUN);
+
+	irq_enable = IRQENB_FIFO1OVRRUN;
+	if (!dma->chan)
+		irq_enable |= IRQENB_FIFO1THRES;
+	tiadc_writel(adc_dev,  REG_IRQENABLE, irq_enable);
 
 	return 0;
 }
@@ -239,12 +328,18 @@ static int tiadc_buffer_postenable(struc
 static int tiadc_buffer_predisable(struct iio_dev *indio_dev)
 {
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
 	int fifo1count, i, read;
 
 	tiadc_writel(adc_dev, REG_IRQCLR, (IRQENB_FIFO1THRES |
 				IRQENB_FIFO1OVRRUN | IRQENB_FIFO1UNDRFLW));
 	am335x_tsc_se_clr(adc_dev->mfd_tscadc, adc_dev->buffer_en_ch_steps);
 	adc_dev->buffer_en_ch_steps = 0;
+	adc_dev->total_ch_enabled = 0;
+	if (dma->chan) {
+		tiadc_writel(adc_dev, REG_DMAENABLE_CLEAR, 0x2);
+		dmaengine_terminate_async(dma->chan);
+	}
 
 	/* Flush FIFO of leftover data in the time it takes to disable adc */
 	fifo1count = tiadc_readl(adc_dev, REG_FIFO1CNT);
@@ -430,6 +525,41 @@ static const struct iio_info tiadc_info
 	.driver_module = THIS_MODULE,
 };
 
+static int tiadc_request_dma(struct platform_device *pdev,
+			     struct tiadc_device *adc_dev)
+{
+	struct tiadc_dma	*dma = &adc_dev->dma;
+	dma_cap_mask_t		mask;
+
+	/* Default slave configuration parameters */
+	dma->conf.direction = DMA_DEV_TO_MEM;
+	dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_CYCLIC, mask);
+
+	/* Get a channel for RX */
+	dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
+	if (IS_ERR(dma->chan)) {
+		int ret = PTR_ERR(dma->chan);
+
+		dma->chan = NULL;
+		return ret;
+	}
+
+	/* RX buffer */
+	dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
+				      &dma->addr, GFP_KERNEL);
+	if (!dma->buf)
+		goto err;
+
+	return 0;
+err:
+	dma_release_channel(dma->chan);
+	return -ENOMEM;
+}
+
 static int tiadc_parse_dt(struct platform_device *pdev,
 			  struct tiadc_device *adc_dev)
 {
@@ -512,8 +642,14 @@ static int tiadc_probe(struct platform_d
 
 	platform_set_drvdata(pdev, indio_dev);
 
+	err = tiadc_request_dma(pdev, adc_dev);
+	if (err && err == -EPROBE_DEFER)
+		goto err_dma;
+
 	return 0;
 
+err_dma:
+	iio_device_unregister(indio_dev);
 err_buffer_unregister:
 	tiadc_iio_buffered_hardware_remove(indio_dev);
 err_free_channels:
@@ -525,8 +661,14 @@ static int tiadc_remove(struct platform_
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct tiadc_device *adc_dev = iio_priv(indio_dev);
+	struct tiadc_dma *dma = &adc_dev->dma;
 	u32 step_en;
 
+	if (dma->chan) {
+		dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
+				  dma->buf, dma->addr);
+		dma_release_channel(dma->chan);
+	}
 	iio_device_unregister(indio_dev);
 	tiadc_iio_buffered_hardware_remove(indio_dev);
 	tiadc_channels_remove(indio_dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
--- linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,322 @@
+/*
+ * cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
+ *
+ * Copyright (C) 2016 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.
+ *
+ * This driver uses the cros-ec interface to communicate with the Chrome OS
+ * EC about sensors data. Data access is presented through iio sysfs.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/kernel.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include "cros_ec_sensors_core.h"
+
+#define CROS_EC_SENSORS_MAX_CHANNELS 4
+
+/* State data for ec_sensors iio driver. */
+struct cros_ec_sensors_state {
+	/* Shared by all sensors */
+	struct cros_ec_sensors_core_state core;
+
+	struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
+};
+
+static int cros_ec_sensors_read(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+	s16 data = 0;
+	s64 val64;
+	int i;
+	int ret;
+	int idx = chan->scan_index;
+
+	mutex_lock(&st->core.cmd_lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data);
+		if (ret < 0)
+			break;
+
+		*val = data;
+		break;
+	case IIO_CHAN_INFO_CALIBBIAS:
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
+		st->core.param.sensor_offset.flags = 0;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		if (ret < 0)
+			break;
+
+		/* Save values */
+		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+			st->core.calib[i] =
+				st->core.resp->sensor_offset.offset[i];
+
+		*val = st->core.calib[idx];
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+		st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		if (ret < 0)
+			break;
+
+		val64 = st->core.resp->sensor_range.ret;
+		switch (st->core.type) {
+		case MOTIONSENSE_TYPE_ACCEL:
+			/*
+			 * EC returns data in g, iio exepects m/s^2.
+			 * Do not use IIO_G_TO_M_S_2 to avoid precision loss.
+			 */
+			*val = div_s64(val64 * 980665, 10);
+			*val2 = 10000 << (CROS_EC_SENSOR_BITS - 1);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		case MOTIONSENSE_TYPE_GYRO:
+			/*
+			 * EC returns data in dps, iio expects rad/s.
+			 * Do not use IIO_DEGREE_TO_RAD to avoid precision
+			 * loss. Round to the nearest integer.
+			 */
+			*val = div_s64(val64 * 314159 + 9000000ULL, 1000);
+			*val2 = 18000 << (CROS_EC_SENSOR_BITS - 1);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		case MOTIONSENSE_TYPE_MAG:
+			/*
+			 * EC returns data in 16LSB / uT,
+			 * iio expects Gauss
+			 */
+			*val = val64;
+			*val2 = 100 << (CROS_EC_SENSOR_BITS - 1);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		break;
+	default:
+		ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
+						mask);
+		break;
+	}
+	mutex_unlock(&st->core.cmd_lock);
+
+	return ret;
+}
+
+static int cros_ec_sensors_write(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+	int i;
+	int ret;
+	int idx = chan->scan_index;
+
+	mutex_lock(&st->core.cmd_lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBBIAS:
+		st->core.calib[idx] = val;
+
+		/* Send to EC for each axis, even if not complete */
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
+		st->core.param.sensor_offset.flags =
+			MOTION_SENSE_SET_OFFSET;
+		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+			st->core.param.sensor_offset.offset[i] =
+				st->core.calib[i];
+		st->core.param.sensor_offset.temp =
+			EC_MOTION_SENSE_INVALID_CALIB_TEMP;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		if (st->core.type == MOTIONSENSE_TYPE_MAG) {
+			ret = -EINVAL;
+			break;
+		}
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+		st->core.param.sensor_range.data = val;
+
+		/* Always roundup, so caller gets at least what it asks for. */
+		st->core.param.sensor_range.roundup = 1;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		break;
+	default:
+		ret = cros_ec_sensors_core_write(
+				&st->core, chan, val, val2, mask);
+		break;
+	}
+
+	mutex_unlock(&st->core.cmd_lock);
+
+	return ret;
+}
+
+static const struct iio_info ec_sensors_info = {
+	.read_raw = &cros_ec_sensors_read,
+	.write_raw = &cros_ec_sensors_write,
+	.driver_module = THIS_MODULE,
+};
+
+static int cros_ec_sensors_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
+	struct cros_ec_device *ec_device;
+	struct iio_dev *indio_dev;
+	struct cros_ec_sensors_state *state;
+	struct iio_chan_spec *channel;
+	int ret, i;
+
+	if (!ec_dev || !ec_dev->ec_dev) {
+		dev_warn(&pdev->dev, "No CROS EC device found.\n");
+		return -EINVAL;
+	}
+	ec_device = ec_dev->ec_dev;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+	if (ret)
+		return ret;
+
+	indio_dev->info = &ec_sensors_info;
+	state = iio_priv(indio_dev);
+	for (channel = state->channels, i = CROS_EC_SENSOR_X;
+	     i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
+		/* Common part */
+		channel->info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_CALIBBIAS);
+		channel->info_mask_shared_by_all =
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_FREQUENCY) |
+			BIT(IIO_CHAN_INFO_SAMP_FREQ);
+		channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
+		channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
+		channel->scan_index = i;
+		channel->ext_info = cros_ec_sensors_ext_info;
+		channel->modified = 1;
+		channel->channel2 = IIO_MOD_X + i;
+		channel->scan_type.sign = 's';
+
+		/* Sensor specific */
+		switch (state->core.type) {
+		case MOTIONSENSE_TYPE_ACCEL:
+			channel->type = IIO_ACCEL;
+			break;
+		case MOTIONSENSE_TYPE_GYRO:
+			channel->type = IIO_ANGL_VEL;
+			break;
+		case MOTIONSENSE_TYPE_MAG:
+			channel->type = IIO_MAGN;
+			break;
+		default:
+			dev_err(&pdev->dev, "Unknown motion sensor\n");
+			return -EINVAL;
+		}
+	}
+
+	/* Timestamp */
+	channel->type = IIO_TIMESTAMP;
+	channel->channel = -1;
+	channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
+	channel->scan_type.sign = 's';
+	channel->scan_type.realbits = 64;
+	channel->scan_type.storagebits = 64;
+
+	indio_dev->channels = state->channels;
+	indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
+
+	/* There is only enough room for accel and gyro in the io space */
+	if ((state->core.ec->cmd_readmem != NULL) &&
+	    (state->core.type != MOTIONSENSE_TYPE_MAG))
+		state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc;
+	else
+		state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 cros_ec_sensors_capture, NULL);
+	if (ret)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_uninit_buffer;
+
+	return 0;
+
+error_uninit_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return ret;
+}
+
+static int cros_ec_sensors_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return 0;
+}
+
+static const struct platform_device_id cros_ec_sensors_ids[] = {
+	{
+		.name = "cros-ec-accel",
+	},
+	{
+		.name = "cros-ec-gyro",
+	},
+	{
+		.name = "cros-ec-mag",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
+
+static struct platform_driver cros_ec_sensors_platform_driver = {
+	.driver = {
+		.name	= "cros-ec-sensors",
+	},
+	.probe		= cros_ec_sensors_probe,
+	.remove		= cros_ec_sensors_remove,
+	.id_table	= cros_ec_sensors_ids,
+};
+module_platform_driver(cros_ec_sensors_platform_driver);
+
+MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
--- linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,450 @@
+/*
+ * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
+ *
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/kernel.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+
+#include "cros_ec_sensors_core.h"
+
+static char *cros_ec_loc[] = {
+	[MOTIONSENSE_LOC_BASE] = "base",
+	[MOTIONSENSE_LOC_LID] = "lid",
+	[MOTIONSENSE_LOC_MAX] = "unknown",
+};
+
+int cros_ec_sensors_core_init(struct platform_device *pdev,
+			      struct iio_dev *indio_dev,
+			      bool physical_device)
+{
+	struct device *dev = &pdev->dev;
+	struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
+	struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
+	struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	state->ec = ec->ec_dev;
+	state->msg = devm_kzalloc(&pdev->dev,
+				max((u16)sizeof(struct ec_params_motion_sense),
+				state->ec->max_response), GFP_KERNEL);
+	if (!state->msg)
+		return -ENOMEM;
+
+	state->resp = (struct ec_response_motion_sense *)state->msg->data;
+
+	mutex_init(&state->cmd_lock);
+
+	/* Set up the host command structure. */
+	state->msg->version = 2;
+	state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+	state->msg->outsize = sizeof(struct ec_params_motion_sense);
+
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->name = pdev->name;
+
+	if (physical_device) {
+		indio_dev->modes = INDIO_DIRECT_MODE;
+
+		state->param.cmd = MOTIONSENSE_CMD_INFO;
+		state->param.info.sensor_num = sensor_platform->sensor_num;
+		if (cros_ec_motion_send_host_cmd(state, 0)) {
+			dev_warn(dev, "Can not access sensor info\n");
+			return -EIO;
+		}
+		state->type = state->resp->info.type;
+		state->loc = state->resp->info.location;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
+
+int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
+				 u16 opt_length)
+{
+	int ret;
+
+	if (opt_length)
+		state->msg->insize = min(opt_length, state->ec->max_response);
+	else
+		state->msg->insize = state->ec->max_response;
+
+	memcpy(state->msg->data, &state->param, sizeof(state->param));
+
+	ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
+	if (ret < 0)
+		return -EIO;
+
+	if (ret &&
+	    state->resp != (struct ec_response_motion_sense *)state->msg->data)
+		memcpy(state->resp, state->msg->data, ret);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_motion_send_host_cmd);
+
+static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev,
+		uintptr_t private, const struct iio_chan_spec *chan,
+		const char *buf, size_t len)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	int ret, i;
+	bool calibrate;
+
+	ret = strtobool(buf, &calibrate);
+	if (ret < 0)
+		return ret;
+	if (!calibrate)
+		return -EINVAL;
+
+	mutex_lock(&st->cmd_lock);
+	st->param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB;
+	ret = cros_ec_motion_send_host_cmd(st, 0);
+	if (ret != 0) {
+		dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n");
+	} else {
+		/* Save values */
+		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+			st->calib[i] = st->resp->perform_calib.offset[i];
+	}
+	mutex_unlock(&st->cmd_lock);
+
+	return ret ? ret : len;
+}
+
+static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
+		uintptr_t private, const struct iio_chan_spec *chan,
+		char *buf)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", cros_ec_loc[st->loc]);
+}
+
+const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = {
+	{
+		.name = "calibrate",
+		.shared = IIO_SHARED_BY_ALL,
+		.write = cros_ec_sensors_calibrate
+	},
+	{
+		.name = "location",
+		.shared = IIO_SHARED_BY_ALL,
+		.read = cros_ec_sensors_loc
+	},
+	{ },
+};
+EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info);
+
+/**
+ * cros_ec_sensors_idx_to_reg - convert index into offset in shared memory
+ * @st:		pointer to state information for device
+ * @idx:	sensor index (should be element of enum sensor_index)
+ *
+ * Return:	address to read at
+ */
+static unsigned int cros_ec_sensors_idx_to_reg(
+					struct cros_ec_sensors_core_state *st,
+					unsigned int idx)
+{
+	/*
+	 * When using LPC interface, only space for 2 Accel and one Gyro.
+	 * First halfword of MOTIONSENSE_TYPE_ACCEL is used by angle.
+	 */
+	if (st->type == MOTIONSENSE_TYPE_ACCEL)
+		return EC_MEMMAP_ACC_DATA + sizeof(u16) *
+			(1 + idx + st->param.info.sensor_num *
+			 CROS_EC_SENSOR_MAX_AXIS);
+
+	return EC_MEMMAP_GYRO_DATA + sizeof(u16) * idx;
+}
+
+static int cros_ec_sensors_cmd_read_u8(struct cros_ec_device *ec,
+				       unsigned int offset, u8 *dest)
+{
+	return ec->cmd_readmem(ec, offset, 1, dest);
+}
+
+static int cros_ec_sensors_cmd_read_u16(struct cros_ec_device *ec,
+					 unsigned int offset, u16 *dest)
+{
+	__le16 tmp;
+	int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
+
+	if (ret >= 0)
+		*dest = le16_to_cpu(tmp);
+
+	return ret;
+}
+
+/**
+ * cros_ec_sensors_read_until_not_busy() - read until is not busy
+ *
+ * @st:	pointer to state information for device
+ *
+ * Read from EC status byte until it reads not busy.
+ * Return: 8-bit status if ok, -errno on failure.
+ */
+static int cros_ec_sensors_read_until_not_busy(
+					struct cros_ec_sensors_core_state *st)
+{
+	struct cros_ec_device *ec = st->ec;
+	u8 status;
+	int ret, attempts = 0;
+
+	ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
+	if (ret < 0)
+		return ret;
+
+	while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
+		/* Give up after enough attempts, return error. */
+		if (attempts++ >= 50)
+			return -EIO;
+
+		/* Small delay every so often. */
+		if (attempts % 5 == 0)
+			msleep(25);
+
+		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
+						  &status);
+		if (ret < 0)
+			return ret;
+	}
+
+	return status;
+}
+
+/**
+ * read_ec_sensors_data_unsafe() - read acceleration data from EC shared memory
+ * @indio_dev:	pointer to IIO device
+ * @scan_mask:	bitmap of the sensor indices to scan
+ * @data:	location to store data
+ *
+ * This is the unsafe function for reading the EC data. It does not guarantee
+ * that the EC will not modify the data as it is being read in.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
+			 unsigned long scan_mask, s16 *data)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	struct cros_ec_device *ec = st->ec;
+	unsigned int i;
+	int ret;
+
+	/* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
+	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
+		ret = cros_ec_sensors_cmd_read_u16(ec,
+					     cros_ec_sensors_idx_to_reg(st, i),
+					     data);
+		if (ret < 0)
+			return ret;
+
+		data++;
+	}
+
+	return 0;
+}
+
+int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
+			     unsigned long scan_mask, s16 *data)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	struct cros_ec_device *ec = st->ec;
+	u8 samp_id = 0xff, status = 0;
+	int ret, attempts = 0;
+
+	/*
+	 * Continually read all data from EC until the status byte after
+	 * all reads reflects that the EC is not busy and the sample id
+	 * matches the sample id from before all reads. This guarantees
+	 * that data read in was not modified by the EC while reading.
+	 */
+	while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
+			  EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
+		/* If we have tried to read too many times, return error. */
+		if (attempts++ >= 5)
+			return -EIO;
+
+		/* Read status byte until EC is not busy. */
+		ret = cros_ec_sensors_read_until_not_busy(st);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * Store the current sample id so that we can compare to the
+		 * sample id after reading the data.
+		 */
+		samp_id = ret & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
+
+		/* Read all EC data, format it, and store it into data. */
+		ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask,
+						       data);
+		if (ret < 0)
+			return ret;
+
+		/* Read status byte. */
+		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
+						  &status);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc);
+
+int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
+			     unsigned long scan_mask, s16 *data)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	int ret;
+	unsigned int i;
+
+	/* Read all sensor data through a command. */
+	st->param.cmd = MOTIONSENSE_CMD_DATA;
+	ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->data));
+	if (ret != 0) {
+		dev_warn(&indio_dev->dev, "Unable to read sensor data\n");
+		return ret;
+	}
+
+	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
+		*data = st->resp->data.data[i];
+		data++;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
+
+irqreturn_t cros_ec_sensors_capture(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&st->cmd_lock);
+
+	/* Clear capture data. */
+	memset(st->samples, 0, indio_dev->scan_bytes);
+
+	/* Read data based on which channels are enabled in scan mask. */
+	ret = st->read_ec_sensors_data(indio_dev,
+				       *(indio_dev->active_scan_mask),
+				       (s16 *)st->samples);
+	if (ret < 0)
+		goto done;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
+					   iio_get_time_ns(indio_dev));
+
+done:
+	/*
+	 * Tell the core we are done with this trigger and ready for the
+	 * next one.
+	 */
+	iio_trigger_notify_done(indio_dev->trig);
+
+	mutex_unlock(&st->cmd_lock);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_capture);
+
+int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	int ret = IIO_VAL_INT;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+		st->param.ec_rate.data =
+			EC_MOTION_SENSE_NO_VALUE;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		else
+			*val = st->resp->ec_rate.ret;
+		break;
+	case IIO_CHAN_INFO_FREQUENCY:
+		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
+		st->param.sensor_odr.data =
+			EC_MOTION_SENSE_NO_VALUE;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		else
+			*val = st->resp->sensor_odr.ret;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
+
+int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_FREQUENCY:
+		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
+		st->param.sensor_odr.data = val;
+
+		/* Always roundup, so caller gets at least what it asks for. */
+		st->param.sensor_odr.roundup = 1;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+		st->param.ec_rate.data = val;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		else
+			st->curr_sampl_freq = val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
+
+MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
--- linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,175 @@
+/*
+ * ChromeOS EC sensor hub
+ *
+ * Copyright (C) 2016 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 __CROS_EC_SENSORS_CORE_H
+#define __CROS_EC_SENSORS_CORE_H
+
+#include <linux/irqreturn.h>
+
+enum {
+	CROS_EC_SENSOR_X,
+	CROS_EC_SENSOR_Y,
+	CROS_EC_SENSOR_Z,
+	CROS_EC_SENSOR_MAX_AXIS,
+};
+
+/* EC returns sensor values using signed 16 bit registers */
+#define CROS_EC_SENSOR_BITS 16
+
+/*
+ * 4 16 bit channels are allowed.
+ * Good enough for current sensors, they use up to 3 16 bit vectors.
+ */
+#define CROS_EC_SAMPLE_SIZE  (sizeof(s64) * 2)
+
+/* Minimum sampling period to use when device is suspending */
+#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000  /* 1 second */
+
+/**
+ * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver
+ * @ec:				cros EC device structure
+ * @cmd_lock:			lock used to prevent simultaneous access to the
+ *				commands.
+ * @msg:			cros EC command structure
+ * @param:			motion sensor parameters structure
+ * @resp:			motion sensor response structure
+ * @type:			type of motion sensor
+ * @loc:			location where the motion sensor is placed
+ * @calib:			calibration parameters. Note that trigger
+ *				captured data will always provide the calibrated
+ *				data
+ * @samples:			static array to hold data from a single capture.
+ *				For each channel we need 2 bytes, except for
+ *				the timestamp. The timestamp is always last and
+ *				is always 8-byte aligned.
+ * @read_ec_sensors_data:	function used for accessing sensors values
+ * @cuur_sampl_freq:		current sampling period
+ */
+struct cros_ec_sensors_core_state {
+	struct cros_ec_device *ec;
+	struct mutex cmd_lock;
+
+	struct cros_ec_command *msg;
+	struct ec_params_motion_sense param;
+	struct ec_response_motion_sense *resp;
+
+	enum motionsensor_type type;
+	enum motionsensor_location loc;
+
+	s16 calib[CROS_EC_SENSOR_MAX_AXIS];
+
+	u8 samples[CROS_EC_SAMPLE_SIZE];
+
+	int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
+				    unsigned long scan_mask, s16 *data);
+
+	int curr_sampl_freq;
+};
+
+/**
+ * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory
+ * @indio_dev:	pointer to IIO device
+ * @scan_mask:	bitmap of the sensor indices to scan
+ * @data:	location to store data
+ *
+ * This is the safe function for reading the EC data. It guarantees that the
+ * data sampled was not modified by the EC while being read.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,
+			     s16 *data);
+
+/**
+ * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol
+ * @indio_dev:	pointer to IIO device
+ * @scan_mask:	bitmap of the sensor indices to scan
+ * @data:	location to store data
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
+			     s16 *data);
+
+/**
+ * cros_ec_sensors_core_init() - basic initialization of the core structure
+ * @pdev:		platform device created for the sensors
+ * @indio_dev:		iio device structure of the device
+ * @physical_device:	true if the device refers to a physical device
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_sensors_core_init(struct platform_device *pdev,
+			      struct iio_dev *indio_dev, bool physical_device);
+
+/**
+ * cros_ec_sensors_capture() - the trigger handler function
+ * @irq:	the interrupt number.
+ * @p:		a pointer to the poll function.
+ *
+ * On a trigger event occurring, if the pollfunc is attached then this
+ * handler is called as a threaded interrupt (and hence may sleep). It
+ * is responsible for grabbing data from the device and pushing it into
+ * the associated buffer.
+ *
+ * Return: IRQ_HANDLED
+ */
+irqreturn_t cros_ec_sensors_capture(int irq, void *p);
+
+/**
+ * cros_ec_motion_send_host_cmd() - send motion sense host command
+ * @st:		pointer to state information for device
+ * @opt_length:	optional length to reduce the response size, useful on the data
+ *		path. Otherwise, the maximal allowed response size is used
+ *
+ * When called, the sub-command is assumed to be set in param->cmd.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st,
+				 u16 opt_length);
+
+/**
+ * cros_ec_sensors_core_read() - function to request a value from the sensor
+ * @st:		pointer to state information for device
+ * @chan:	channel specification structure table
+ * @val:	will contain one element making up the returned value
+ * @val2:	will contain another element making up the returned value
+ * @mask:	specifies which values to be requested
+ *
+ * Return:	the type of value returned by the device
+ */
+int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2, long mask);
+
+/**
+ * cros_ec_sensors_core_write() - function to write a value to the sensor
+ * @st:		pointer to state information for device
+ * @chan:	channel specification structure table
+ * @val:	first part of value to write
+ * @val2:	second part of value to write
+ * @mask:	specifies which values to write
+ *
+ * Return:	the type of value returned by the device
+ */
+int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask);
+
+/* List of extended channel specification for all sensors */
+extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
+
+#endif  /* __CROS_EC_SENSORS_CORE_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,22 @@
+#
+# Chrome OS Embedded Controller managed sensors library
+#
+config IIO_CROS_EC_SENSORS_CORE
+	tristate "ChromeOS EC Sensors Core"
+	depends on SYSFS && MFD_CROS_EC
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Base module for the ChromeOS EC Sensors module.
+	  Contains core functions used by other IIO CrosEC sensor
+	  drivers.
+	  Define common attributes and sysfs interrupt handler.
+
+config IIO_CROS_EC_SENSORS
+	tristate "ChromeOS EC Contiguous Sensors"
+	depends on IIO_CROS_EC_SENSORS_CORE
+	help
+	  Module to handle 3d contiguous sensors like
+	  Accelerometers, Gyroscope and Magnetometer that are
+	  presented by the ChromeOS EC Sensor hub.
+	  Creates an IIO device for each functions.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/Makefile
--- linux-libre-4.9-gnu/drivers/iio/common/cros_ec_sensors/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/cros_ec_sensors/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,6 @@
+#
+# Makefile for sensors seen through the ChromeOS EC sensor hub.
+#
+
+obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
+obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c linux-libre-4.10-rc8-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
--- linux-libre-4.9-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/hid-sensors/hid-sensor-attributes.c	2017-02-12 16:03:20.000000000 -0500
@@ -201,7 +201,7 @@ int hid_sensor_write_samp_freq_value(str
 	int ret;
 
 	if (val1 < 0 || val2 < 0)
-		ret = -EINVAL;
+		return -EINVAL;
 
 	value = val1 * pow_10(6) + val2;
 	if (value) {
@@ -250,6 +250,9 @@ int hid_sensor_write_raw_hyst_value(stru
 	s32 value;
 	int ret;
 
+	if (val1 < 0 || val2 < 0)
+		return -EINVAL;
+
 	value = convert_to_vtf_format(st->sensitivity.size,
 				st->sensitivity.unit_expo,
 				val1, val2);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/common/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/common/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,7 @@
 # IIO common modules
 #
 
+source "drivers/iio/common/cros_ec_sensors/Kconfig"
 source "drivers/iio/common/hid-sensors/Kconfig"
 source "drivers/iio/common/ms_sensors/Kconfig"
 source "drivers/iio/common/ssp_sensors/Kconfig"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/common/Makefile
--- linux-libre-4.9-gnu/drivers/iio/common/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-y += cros_ec_sensors/
 obj-y += hid-sensors/
 obj-y += ms_sensors/
 obj-y += ssp_sensors/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c linux-libre-4.10-rc8-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c
--- linux-libre-4.9-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/st_sensors/st_sensors_buffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,9 @@ static int st_sensors_get_buffer_element
 
 	for_each_set_bit(i, indio_dev->active_scan_mask, num_data_channels) {
 		const struct iio_chan_spec *channel = &indio_dev->channels[i];
-		unsigned int bytes_to_read = channel->scan_type.realbits >> 3;
+		unsigned int bytes_to_read =
+			DIV_ROUND_UP(channel->scan_type.realbits +
+				     channel->scan_type.shift, 8);
 		unsigned int storage_bytes =
 			channel->scan_type.storagebits >> 3;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/common/st_sensors/st_sensors_core.c linux-libre-4.10-rc8-gnu/drivers/iio/common/st_sensors/st_sensors_core.c
--- linux-libre-4.9-gnu/drivers/iio/common/st_sensors/st_sensors_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/common/st_sensors/st_sensors_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -401,6 +401,15 @@ int st_sensors_init_sensor(struct iio_de
 			return err;
 	}
 
+	/* set DAS */
+	if (sdata->sensor_settings->das.addr) {
+		err = st_sensors_write_data_with_mask(indio_dev,
+					sdata->sensor_settings->das.addr,
+					sdata->sensor_settings->das.mask, 1);
+		if (err < 0)
+			return err;
+	}
+
 	if (sdata->int_pin_open_drain) {
 		dev_info(&indio_dev->dev,
 			 "set interrupt line to open drain mode\n");
@@ -483,8 +492,10 @@ static int st_sensors_read_axis_data(str
 	int err;
 	u8 *outdata;
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
-	unsigned int byte_for_channel = ch->scan_type.realbits >> 3;
+	unsigned int byte_for_channel;
 
+	byte_for_channel = DIV_ROUND_UP(ch->scan_type.realbits +
+					ch->scan_type.shift, 8);
 	outdata = kmalloc(byte_for_channel, GFP_KERNEL);
 	if (!outdata)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/counter/104-quad-8.c linux-libre-4.10-rc8-gnu/drivers/iio/counter/104-quad-8.c
--- linux-libre-4.9-gnu/drivers/iio/counter/104-quad-8.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/counter/104-quad-8.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,596 @@
+/*
+ * IIO driver for the ACCES 104-QUAD-8
+ * Copyright (C) 2016 William Breathitt Gray
+ *
+ * This program is free software; you can 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.
+ *
+ * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4.
+ */
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/isa.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#define QUAD8_EXTENT 32
+
+static unsigned int base[max_num_isa_dev(QUAD8_EXTENT)];
+static unsigned int num_quad8;
+module_param_array(base, uint, &num_quad8, 0);
+MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
+
+#define QUAD8_NUM_COUNTERS 8
+
+/**
+ * struct quad8_iio - IIO device private data structure
+ * @preset:		array of preset values
+ * @count_mode:		array of count mode configurations
+ * @quadrature_mode:	array of quadrature mode configurations
+ * @quadrature_scale:	array of quadrature mode scale configurations
+ * @ab_enable:		array of A and B inputs enable configurations
+ * @preset_enable:	array of set_to_preset_on_index attribute configurations
+ * @synchronous_mode:	array of index function synchronous mode configurations
+ * @index_polarity:	array of index function polarity configurations
+ * @base:		base port address of the IIO device
+ */
+struct quad8_iio {
+	unsigned int preset[QUAD8_NUM_COUNTERS];
+	unsigned int count_mode[QUAD8_NUM_COUNTERS];
+	unsigned int quadrature_mode[QUAD8_NUM_COUNTERS];
+	unsigned int quadrature_scale[QUAD8_NUM_COUNTERS];
+	unsigned int ab_enable[QUAD8_NUM_COUNTERS];
+	unsigned int preset_enable[QUAD8_NUM_COUNTERS];
+	unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
+	unsigned int index_polarity[QUAD8_NUM_COUNTERS];
+	unsigned int base;
+};
+
+static int quad8_read_raw(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan, int *val, int *val2, long mask)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const int base_offset = priv->base + 2 * chan->channel;
+	unsigned int flags;
+	unsigned int borrow;
+	unsigned int carry;
+	int i;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (chan->type == IIO_INDEX) {
+			*val = !!(inb(priv->base + 0x16) & BIT(chan->channel));
+			return IIO_VAL_INT;
+		}
+
+		flags = inb(base_offset);
+		borrow = flags & BIT(0);
+		carry = !!(flags & BIT(1));
+
+		/* Borrow XOR Carry effectively doubles count range */
+		*val = (borrow ^ carry) << 24;
+
+		/* Reset Byte Pointer; transfer Counter to Output Latch */
+		outb(0x11, base_offset + 1);
+
+		for (i = 0; i < 3; i++)
+			*val |= (unsigned int)inb(base_offset) << (8 * i);
+
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_ENABLE:
+		*val = priv->ab_enable[chan->channel];
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 1;
+		*val2 = priv->quadrature_scale[chan->channel];
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+
+	return -EINVAL;
+}
+
+static int quad8_write_raw(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const int base_offset = priv->base + 2 * chan->channel;
+	int i;
+	unsigned int ior_cfg;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (chan->type == IIO_INDEX)
+			return -EINVAL;
+
+		/* Only 24-bit values are supported */
+		if ((unsigned int)val > 0xFFFFFF)
+			return -EINVAL;
+
+		/* Reset Byte Pointer */
+		outb(0x01, base_offset + 1);
+
+		/* Counter can only be set via Preset Register */
+		for (i = 0; i < 3; i++)
+			outb(val >> (8 * i), base_offset);
+
+		/* Transfer Preset Register to Counter */
+		outb(0x08, base_offset + 1);
+
+		/* Reset Byte Pointer */
+		outb(0x01, base_offset + 1);
+
+		/* Set Preset Register back to original value */
+		val = priv->preset[chan->channel];
+		for (i = 0; i < 3; i++)
+			outb(val >> (8 * i), base_offset);
+
+		/* Reset Borrow, Carry, Compare, and Sign flags */
+		outb(0x02, base_offset + 1);
+		/* Reset Error flag */
+		outb(0x06, base_offset + 1);
+
+		return 0;
+	case IIO_CHAN_INFO_ENABLE:
+		/* only boolean values accepted */
+		if (val < 0 || val > 1)
+			return -EINVAL;
+
+		priv->ab_enable[chan->channel] = val;
+
+		ior_cfg = val | priv->preset_enable[chan->channel] << 1;
+
+		/* Load I/O control configuration */
+		outb(0x40 | ior_cfg, base_offset + 1);
+
+		return 0;
+	case IIO_CHAN_INFO_SCALE:
+		/* Quadrature scaling only available in quadrature mode */
+		if (!priv->quadrature_mode[chan->channel] && (val2 || val != 1))
+			return -EINVAL;
+
+		/* Only three gain states (1, 0.5, 0.25) */
+		if (val == 1 && !val2)
+			priv->quadrature_scale[chan->channel] = 0;
+		else if (!val)
+			switch (val2) {
+			case 500000:
+				priv->quadrature_scale[chan->channel] = 1;
+				break;
+			case 250000:
+				priv->quadrature_scale[chan->channel] = 2;
+				break;
+			default:
+				return -EINVAL;
+			}
+		else
+			return -EINVAL;
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info quad8_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = quad8_read_raw,
+	.write_raw = quad8_write_raw
+};
+
+static ssize_t quad8_read_preset(struct iio_dev *indio_dev, uintptr_t private,
+	const struct iio_chan_spec *chan, char *buf)
+{
+	const struct quad8_iio *const priv = iio_priv(indio_dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", priv->preset[chan->channel]);
+}
+
+static ssize_t quad8_write_preset(struct iio_dev *indio_dev, uintptr_t private,
+	const struct iio_chan_spec *chan, const char *buf, size_t len)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const int base_offset = priv->base + 2 * chan->channel;
+	unsigned int preset;
+	int ret;
+	int i;
+
+	ret = kstrtouint(buf, 0, &preset);
+	if (ret)
+		return ret;
+
+	/* Only 24-bit values are supported */
+	if (preset > 0xFFFFFF)
+		return -EINVAL;
+
+	priv->preset[chan->channel] = preset;
+
+	/* Reset Byte Pointer */
+	outb(0x01, base_offset + 1);
+
+	/* Set Preset Register */
+	for (i = 0; i < 3; i++)
+		outb(preset >> (8 * i), base_offset);
+
+	return len;
+}
+
+static ssize_t quad8_read_set_to_preset_on_index(struct iio_dev *indio_dev,
+	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
+{
+	const struct quad8_iio *const priv = iio_priv(indio_dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n",
+		!priv->preset_enable[chan->channel]);
+}
+
+static ssize_t quad8_write_set_to_preset_on_index(struct iio_dev *indio_dev,
+	uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
+	size_t len)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const int base_offset = priv->base + 2 * chan->channel + 1;
+	bool preset_enable;
+	int ret;
+	unsigned int ior_cfg;
+
+	ret = kstrtobool(buf, &preset_enable);
+	if (ret)
+		return ret;
+
+	/* Preset enable is active low in Input/Output Control register */
+	preset_enable = !preset_enable;
+
+	priv->preset_enable[chan->channel] = preset_enable;
+
+	ior_cfg = priv->ab_enable[chan->channel] |
+		(unsigned int)preset_enable << 1;
+
+	/* Load I/O control configuration to Input / Output Control Register */
+	outb(0x40 | ior_cfg, base_offset);
+
+	return len;
+}
+
+static const char *const quad8_noise_error_states[] = {
+	"No excessive noise is present at the count inputs",
+	"Excessive noise is present at the count inputs"
+};
+
+static int quad8_get_noise_error(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const int base_offset = priv->base + 2 * chan->channel + 1;
+
+	return !!(inb(base_offset) & BIT(4));
+}
+
+static const struct iio_enum quad8_noise_error_enum = {
+	.items = quad8_noise_error_states,
+	.num_items = ARRAY_SIZE(quad8_noise_error_states),
+	.get = quad8_get_noise_error
+};
+
+static const char *const quad8_count_direction_states[] = {
+	"down",
+	"up"
+};
+
+static int quad8_get_count_direction(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const int base_offset = priv->base + 2 * chan->channel + 1;
+
+	return !!(inb(base_offset) & BIT(5));
+}
+
+static const struct iio_enum quad8_count_direction_enum = {
+	.items = quad8_count_direction_states,
+	.num_items = ARRAY_SIZE(quad8_count_direction_states),
+	.get = quad8_get_count_direction
+};
+
+static const char *const quad8_count_modes[] = {
+	"normal",
+	"range limit",
+	"non-recycle",
+	"modulo-n"
+};
+
+static int quad8_set_count_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int count_mode)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	unsigned int mode_cfg = count_mode << 1;
+	const int base_offset = priv->base + 2 * chan->channel + 1;
+
+	priv->count_mode[chan->channel] = count_mode;
+
+	/* Add quadrature mode configuration */
+	if (priv->quadrature_mode[chan->channel])
+		mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
+
+	/* Load mode configuration to Counter Mode Register */
+	outb(0x20 | mode_cfg, base_offset);
+
+	return 0;
+}
+
+static int quad8_get_count_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan)
+{
+	const struct quad8_iio *const priv = iio_priv(indio_dev);
+
+	return priv->count_mode[chan->channel];
+}
+
+static const struct iio_enum quad8_count_mode_enum = {
+	.items = quad8_count_modes,
+	.num_items = ARRAY_SIZE(quad8_count_modes),
+	.set = quad8_set_count_mode,
+	.get = quad8_get_count_mode
+};
+
+static const char *const quad8_synchronous_modes[] = {
+	"non-synchronous",
+	"synchronous"
+};
+
+static int quad8_set_synchronous_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int synchronous_mode)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const unsigned int idr_cfg = synchronous_mode |
+		priv->index_polarity[chan->channel] << 1;
+	const int base_offset = priv->base + 2 * chan->channel + 1;
+
+	/* Index function must be non-synchronous in non-quadrature mode */
+	if (synchronous_mode && !priv->quadrature_mode[chan->channel])
+		return -EINVAL;
+
+	priv->synchronous_mode[chan->channel] = synchronous_mode;
+
+	/* Load Index Control configuration to Index Control Register */
+	outb(0x60 | idr_cfg, base_offset);
+
+	return 0;
+}
+
+static int quad8_get_synchronous_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan)
+{
+	const struct quad8_iio *const priv = iio_priv(indio_dev);
+
+	return priv->synchronous_mode[chan->channel];
+}
+
+static const struct iio_enum quad8_synchronous_mode_enum = {
+	.items = quad8_synchronous_modes,
+	.num_items = ARRAY_SIZE(quad8_synchronous_modes),
+	.set = quad8_set_synchronous_mode,
+	.get = quad8_get_synchronous_mode
+};
+
+static const char *const quad8_quadrature_modes[] = {
+	"non-quadrature",
+	"quadrature"
+};
+
+static int quad8_set_quadrature_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int quadrature_mode)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	unsigned int mode_cfg = priv->count_mode[chan->channel] << 1;
+	const int base_offset = priv->base + 2 * chan->channel + 1;
+
+	if (quadrature_mode)
+		mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
+	else {
+		/* Quadrature scaling only available in quadrature mode */
+		priv->quadrature_scale[chan->channel] = 0;
+
+		/* Synchronous function not supported in non-quadrature mode */
+		if (priv->synchronous_mode[chan->channel])
+			quad8_set_synchronous_mode(indio_dev, chan, 0);
+	}
+
+	priv->quadrature_mode[chan->channel] = quadrature_mode;
+
+	/* Load mode configuration to Counter Mode Register */
+	outb(0x20 | mode_cfg, base_offset);
+
+	return 0;
+}
+
+static int quad8_get_quadrature_mode(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan)
+{
+	const struct quad8_iio *const priv = iio_priv(indio_dev);
+
+	return priv->quadrature_mode[chan->channel];
+}
+
+static const struct iio_enum quad8_quadrature_mode_enum = {
+	.items = quad8_quadrature_modes,
+	.num_items = ARRAY_SIZE(quad8_quadrature_modes),
+	.set = quad8_set_quadrature_mode,
+	.get = quad8_get_quadrature_mode
+};
+
+static const char *const quad8_index_polarity_modes[] = {
+	"negative",
+	"positive"
+};
+
+static int quad8_set_index_polarity(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan, unsigned int index_polarity)
+{
+	struct quad8_iio *const priv = iio_priv(indio_dev);
+	const unsigned int idr_cfg = priv->synchronous_mode[chan->channel] |
+		index_polarity << 1;
+	const int base_offset = priv->base + 2 * chan->channel + 1;
+
+	priv->index_polarity[chan->channel] = index_polarity;
+
+	/* Load Index Control configuration to Index Control Register */
+	outb(0x60 | idr_cfg, base_offset);
+
+	return 0;
+}
+
+static int quad8_get_index_polarity(struct iio_dev *indio_dev,
+	const struct iio_chan_spec *chan)
+{
+	const struct quad8_iio *const priv = iio_priv(indio_dev);
+
+	return priv->index_polarity[chan->channel];
+}
+
+static const struct iio_enum quad8_index_polarity_enum = {
+	.items = quad8_index_polarity_modes,
+	.num_items = ARRAY_SIZE(quad8_index_polarity_modes),
+	.set = quad8_set_index_polarity,
+	.get = quad8_get_index_polarity
+};
+
+static const struct iio_chan_spec_ext_info quad8_count_ext_info[] = {
+	{
+		.name = "preset",
+		.shared = IIO_SEPARATE,
+		.read = quad8_read_preset,
+		.write = quad8_write_preset
+	},
+	{
+		.name = "set_to_preset_on_index",
+		.shared = IIO_SEPARATE,
+		.read = quad8_read_set_to_preset_on_index,
+		.write = quad8_write_set_to_preset_on_index
+	},
+	IIO_ENUM("noise_error", IIO_SEPARATE, &quad8_noise_error_enum),
+	IIO_ENUM_AVAILABLE("noise_error", &quad8_noise_error_enum),
+	IIO_ENUM("count_direction", IIO_SEPARATE, &quad8_count_direction_enum),
+	IIO_ENUM_AVAILABLE("count_direction", &quad8_count_direction_enum),
+	IIO_ENUM("count_mode", IIO_SEPARATE, &quad8_count_mode_enum),
+	IIO_ENUM_AVAILABLE("count_mode", &quad8_count_mode_enum),
+	IIO_ENUM("quadrature_mode", IIO_SEPARATE, &quad8_quadrature_mode_enum),
+	IIO_ENUM_AVAILABLE("quadrature_mode", &quad8_quadrature_mode_enum),
+	{}
+};
+
+static const struct iio_chan_spec_ext_info quad8_index_ext_info[] = {
+	IIO_ENUM("synchronous_mode", IIO_SEPARATE,
+		&quad8_synchronous_mode_enum),
+	IIO_ENUM_AVAILABLE("synchronous_mode", &quad8_synchronous_mode_enum),
+	IIO_ENUM("index_polarity", IIO_SEPARATE, &quad8_index_polarity_enum),
+	IIO_ENUM_AVAILABLE("index_polarity", &quad8_index_polarity_enum),
+	{}
+};
+
+#define QUAD8_COUNT_CHAN(_chan) {					\
+	.type = IIO_COUNT,						\
+	.channel = (_chan),						\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
+		BIT(IIO_CHAN_INFO_ENABLE) | BIT(IIO_CHAN_INFO_SCALE),	\
+	.ext_info = quad8_count_ext_info,				\
+	.indexed = 1							\
+}
+
+#define QUAD8_INDEX_CHAN(_chan) {			\
+	.type = IIO_INDEX,				\
+	.channel = (_chan),				\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.ext_info = quad8_index_ext_info,		\
+	.indexed = 1					\
+}
+
+static const struct iio_chan_spec quad8_channels[] = {
+	QUAD8_COUNT_CHAN(0), QUAD8_INDEX_CHAN(0),
+	QUAD8_COUNT_CHAN(1), QUAD8_INDEX_CHAN(1),
+	QUAD8_COUNT_CHAN(2), QUAD8_INDEX_CHAN(2),
+	QUAD8_COUNT_CHAN(3), QUAD8_INDEX_CHAN(3),
+	QUAD8_COUNT_CHAN(4), QUAD8_INDEX_CHAN(4),
+	QUAD8_COUNT_CHAN(5), QUAD8_INDEX_CHAN(5),
+	QUAD8_COUNT_CHAN(6), QUAD8_INDEX_CHAN(6),
+	QUAD8_COUNT_CHAN(7), QUAD8_INDEX_CHAN(7)
+};
+
+static int quad8_probe(struct device *dev, unsigned int id)
+{
+	struct iio_dev *indio_dev;
+	struct quad8_iio *priv;
+	int i, j;
+	unsigned int base_offset;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	if (!devm_request_region(dev, base[id], QUAD8_EXTENT,
+		dev_name(dev))) {
+		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
+			base[id], base[id] + QUAD8_EXTENT);
+		return -EBUSY;
+	}
+
+	indio_dev->info = &quad8_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->num_channels = ARRAY_SIZE(quad8_channels);
+	indio_dev->channels = quad8_channels;
+	indio_dev->name = dev_name(dev);
+
+	priv = iio_priv(indio_dev);
+	priv->base = base[id];
+
+	/* Reset all counters and disable interrupt function */
+	outb(0x01, base[id] + 0x11);
+	/* Set initial configuration for all counters */
+	for (i = 0; i < QUAD8_NUM_COUNTERS; i++) {
+		base_offset = base[id] + 2 * i;
+		/* Reset Byte Pointer */
+		outb(0x01, base_offset + 1);
+		/* Reset Preset Register */
+		for (j = 0; j < 3; j++)
+			outb(0x00, base_offset);
+		/* Reset Borrow, Carry, Compare, and Sign flags */
+		outb(0x04, base_offset + 1);
+		/* Reset Error flag */
+		outb(0x06, base_offset + 1);
+		/* Binary encoding; Normal count; non-quadrature mode */
+		outb(0x20, base_offset + 1);
+		/* Disable A and B inputs; preset on index; FLG1 as Carry */
+		outb(0x40, base_offset + 1);
+		/* Disable index function; negative index polarity */
+		outb(0x60, base_offset + 1);
+	}
+	/* Enable all counters */
+	outb(0x00, base[id] + 0x11);
+
+	return devm_iio_device_register(dev, indio_dev);
+}
+
+static struct isa_driver quad8_driver = {
+	.probe = quad8_probe,
+	.driver = {
+		.name = "104-quad-8"
+	}
+};
+
+module_isa_driver(quad8_driver, num_quad8);
+
+MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
+MODULE_DESCRIPTION("ACCES 104-QUAD-8 IIO driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/counter/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/counter/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/counter/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/counter/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,24 @@
+#
+# Counter devices
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Counters"
+
+config 104_QUAD_8
+	tristate "ACCES 104-QUAD-8 driver"
+	depends on X86 && ISA_BUS_API
+	help
+	  Say yes here to build support for the ACCES 104-QUAD-8 quadrature
+	  encoder counter/interface device family (104-QUAD-8, 104-QUAD-4).
+
+	  Performing a write to a counter's IIO_CHAN_INFO_RAW sets the counter and
+	  also clears the counter's respective error flag. Although the counters
+	  have a 25-bit range, only the lower 24 bits may be set, either directly
+	  or via a counter's preset attribute. Interrupts are not supported by
+	  this driver.
+
+	  The base port addresses for the devices may be configured via the base
+	  array module parameter.
+
+endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/counter/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/counter/Makefile
--- linux-libre-4.9-gnu/drivers/iio/counter/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/counter/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+#
+# Makefile for IIO counter devices
+#
+
+# When adding new entries keep the list in alphabetical order
+
+obj-$(CONFIG_104_QUAD_8)	+= 104-quad-8.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/dac/ad5592r.c linux-libre-4.10-rc8-gnu/drivers/iio/dac/ad5592r.c
--- linux-libre-4.9-gnu/drivers/iio/dac/ad5592r.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/dac/ad5592r.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #define AD5592R_GPIO_READBACK_EN	BIT(10)
 #define AD5592R_LDAC_READBACK_EN	BIT(6)
 
-static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, u16 *buf)
+static int ad5592r_spi_wnop_r16(struct ad5592r_state *st, __be16 *buf)
 {
 	struct spi_device *spi = container_of(st->dev, struct spi_device, dev);
 	struct spi_transfer t = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/dac/dpot-dac.c linux-libre-4.10-rc8-gnu/drivers/iio/dac/dpot-dac.c
--- linux-libre-4.9-gnu/drivers/iio/dac/dpot-dac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/dac/dpot-dac.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,266 @@
+/*
+ * IIO DAC emulation driver using a digital potentiometer
+ *
+ * Copyright (C) 2016 Axentia Technologies AB
+ *
+ * Author: Peter Rosin <peda@axentia.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * It is assumed that the dpot is used as a voltage divider between the
+ * current dpot wiper setting and the maximum resistance of the dpot. The
+ * divided voltage is provided by a vref regulator.
+ *
+ *                   .------.
+ *    .-----------.  |      |
+ *    | vref      |--'    .---.
+ *    | regulator |--.    |   |
+ *    '-----------'  |    | d |
+ *                   |    | p |
+ *                   |    | o |  wiper
+ *                   |    | t |<---------+
+ *                   |    |   |
+ *                   |    '---'       dac output voltage
+ *                   |      |
+ *                   '------+------------+
+ */
+
+#include <linux/err.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+struct dpot_dac {
+	struct regulator *vref;
+	struct iio_channel *dpot;
+	u32 max_ohms;
+};
+
+static const struct iio_chan_spec dpot_dac_iio_channel = {
+	.type = IIO_VOLTAGE,
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
+			    | BIT(IIO_CHAN_INFO_SCALE),
+	.info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW),
+	.output = 1,
+	.indexed = 1,
+};
+
+static int dpot_dac_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask)
+{
+	struct dpot_dac *dac = iio_priv(indio_dev);
+	int ret;
+	unsigned long long tmp;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		return iio_read_channel_raw(dac->dpot, val);
+
+	case IIO_CHAN_INFO_SCALE:
+		ret = iio_read_channel_scale(dac->dpot, val, val2);
+		switch (ret) {
+		case IIO_VAL_FRACTIONAL_LOG2:
+			tmp = *val * 1000000000LL;
+			do_div(tmp, dac->max_ohms);
+			tmp *= regulator_get_voltage(dac->vref) / 1000;
+			do_div(tmp, 1000000000LL);
+			*val = tmp;
+			return ret;
+		case IIO_VAL_INT:
+			/*
+			 * Convert integer scale to fractional scale by
+			 * setting the denominator (val2) to one...
+			 */
+			*val2 = 1;
+			ret = IIO_VAL_FRACTIONAL;
+			/* ...and fall through. */
+		case IIO_VAL_FRACTIONAL:
+			*val *= regulator_get_voltage(dac->vref) / 1000;
+			*val2 *= dac->max_ohms;
+			break;
+		}
+
+		return ret;
+	}
+
+	return -EINVAL;
+}
+
+static int dpot_dac_read_avail(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       const int **vals, int *type, int *length,
+			       long mask)
+{
+	struct dpot_dac *dac = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		*type = IIO_VAL_INT;
+		return iio_read_avail_channel_raw(dac->dpot, vals, length);
+	}
+
+	return -EINVAL;
+}
+
+static int dpot_dac_write_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int val, int val2, long mask)
+{
+	struct dpot_dac *dac = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		return iio_write_channel_raw(dac->dpot, val);
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info dpot_dac_info = {
+	.read_raw = dpot_dac_read_raw,
+	.read_avail = dpot_dac_read_avail,
+	.write_raw = dpot_dac_write_raw,
+	.driver_module = THIS_MODULE,
+};
+
+static int dpot_dac_channel_max_ohms(struct iio_dev *indio_dev)
+{
+	struct device *dev = &indio_dev->dev;
+	struct dpot_dac *dac = iio_priv(indio_dev);
+	unsigned long long tmp;
+	int ret;
+	int val;
+	int val2;
+	int max;
+
+	ret = iio_read_max_channel_raw(dac->dpot, &max);
+	if (ret < 0) {
+		dev_err(dev, "dpot does not indicate its raw maximum value\n");
+		return ret;
+	}
+
+	switch (iio_read_channel_scale(dac->dpot, &val, &val2)) {
+	case IIO_VAL_INT:
+		return max * val;
+	case IIO_VAL_FRACTIONAL:
+		tmp = (unsigned long long)max * val;
+		do_div(tmp, val2);
+		return tmp;
+	case IIO_VAL_FRACTIONAL_LOG2:
+		tmp = val * 1000000000LL * max >> val2;
+		do_div(tmp, 1000000000LL);
+		return tmp;
+	default:
+		dev_err(dev, "dpot has a scale that is too weird\n");
+	}
+
+	return -EINVAL;
+}
+
+static int dpot_dac_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct iio_dev *indio_dev;
+	struct dpot_dac *dac;
+	enum iio_chan_type type;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*dac));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, indio_dev);
+	dac = iio_priv(indio_dev);
+
+	indio_dev->name = dev_name(dev);
+	indio_dev->dev.parent = dev;
+	indio_dev->info = &dpot_dac_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = &dpot_dac_iio_channel;
+	indio_dev->num_channels = 1;
+
+	dac->vref = devm_regulator_get(dev, "vref");
+	if (IS_ERR(dac->vref)) {
+		if (PTR_ERR(dac->vref) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to get vref regulator\n");
+		return PTR_ERR(dac->vref);
+	}
+
+	dac->dpot = devm_iio_channel_get(dev, "dpot");
+	if (IS_ERR(dac->dpot)) {
+		if (PTR_ERR(dac->dpot) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get dpot input channel\n");
+		return PTR_ERR(dac->dpot);
+	}
+
+	ret = iio_get_channel_type(dac->dpot, &type);
+	if (ret < 0)
+		return ret;
+
+	if (type != IIO_RESISTANCE) {
+		dev_err(dev, "dpot is of the wrong type\n");
+		return -EINVAL;
+	}
+
+	ret = dpot_dac_channel_max_ohms(indio_dev);
+	if (ret < 0)
+		return ret;
+	dac->max_ohms = ret;
+
+	ret = regulator_enable(dac->vref);
+	if (ret) {
+		dev_err(dev, "failed to enable the vref regulator\n");
+		return ret;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(dev, "failed to register iio device\n");
+		goto disable_reg;
+	}
+
+	return 0;
+
+disable_reg:
+	regulator_disable(dac->vref);
+	return ret;
+}
+
+static int dpot_dac_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct dpot_dac *dac = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	regulator_disable(dac->vref);
+
+	return 0;
+}
+
+static const struct of_device_id dpot_dac_match[] = {
+	{ .compatible = "dpot-dac" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, dpot_dac_match);
+
+static struct platform_driver dpot_dac_driver = {
+	.probe = dpot_dac_probe,
+	.remove = dpot_dac_remove,
+	.driver = {
+		.name = "iio-dpot-dac",
+		.of_match_table = dpot_dac_match,
+	},
+};
+module_platform_driver(dpot_dac_driver);
+
+MODULE_DESCRIPTION("DAC emulation driver using a digital potentiometer");
+MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/dac/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/dac/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/dac/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/dac/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -200,6 +200,16 @@ config AD8801
 	  To compile this driver as a module choose M here: the module will be called
 	  ad8801.
 
+config DPOT_DAC
+	tristate "DAC emulation using a DPOT"
+	depends on OF
+	help
+	  Say yes here to build support for DAC emulation using a digital
+	  potentiometer.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called dpot-dac.
+
 config LPC18XX_DAC
 	tristate "NXP LPC18xx DAC driver"
 	depends on ARCH_LPC18XX || COMPILE_TEST
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/dac/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/dac/Makefile
--- linux-libre-4.9-gnu/drivers/iio/dac/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/dac/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@ obj-$(CONFIG_AD5686) += ad5686.o
 obj-$(CONFIG_AD7303) += ad7303.o
 obj-$(CONFIG_AD8801) += ad8801.o
 obj-$(CONFIG_CIO_DAC) += cio-dac.o
+obj-$(CONFIG_DPOT_DAC) += dpot-dac.o
 obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o
 obj-$(CONFIG_M62332) += m62332.o
 obj-$(CONFIG_MAX517) += max517.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/dac/mcp4725.c linux-libre-4.10-rc8-gnu/drivers/iio/dac/mcp4725.c
--- linux-libre-4.9-gnu/drivers/iio/dac/mcp4725.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/dac/mcp4725.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@
 #include <linux/i2c.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
@@ -26,12 +28,20 @@
 
 #define MCP4725_DRV_NAME "mcp4725"
 
+#define MCP472X_REF_VDD			0x00
+#define MCP472X_REF_VREF_UNBUFFERED	0x02
+#define MCP472X_REF_VREF_BUFFERED	0x03
+
 struct mcp4725_data {
 	struct i2c_client *client;
-	u16 vref_mv;
+	int id;
+	unsigned ref_mode;
+	bool vref_buffered;
 	u16 dac_value;
 	bool powerdown;
 	unsigned powerdown_mode;
+	struct regulator *vdd_reg;
+	struct regulator *vref_reg;
 };
 
 static int mcp4725_suspend(struct device *dev)
@@ -86,6 +96,7 @@ static ssize_t mcp4725_store_eeprom(stru
 		return 0;
 
 	inoutbuf[0] = 0x60; /* write EEPROM */
+	inoutbuf[0] |= data->ref_mode << 3;
 	inoutbuf[1] = data->dac_value >> 4;
 	inoutbuf[2] = (data->dac_value & 0xf) << 4;
 
@@ -278,18 +289,49 @@ static int mcp4725_set_value(struct iio_
 		return 0;
 }
 
+static int mcp4726_set_cfg(struct iio_dev *indio_dev)
+{
+	struct mcp4725_data *data = iio_priv(indio_dev);
+	u8 outbuf[3];
+	int ret;
+
+	outbuf[0] = 0x40;
+	outbuf[0] |= data->ref_mode << 3;
+	if (data->powerdown)
+		outbuf[0] |= data->powerdown << 1;
+	outbuf[1] = data->dac_value >> 4;
+	outbuf[2] = (data->dac_value & 0xf) << 4;
+
+	ret = i2c_master_send(data->client, outbuf, 3);
+	if (ret < 0)
+		return ret;
+	else if (ret != 3)
+		return -EIO;
+	else
+		return 0;
+}
+
 static int mcp4725_read_raw(struct iio_dev *indio_dev,
 			   struct iio_chan_spec const *chan,
 			   int *val, int *val2, long mask)
 {
 	struct mcp4725_data *data = iio_priv(indio_dev);
+	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		*val = data->dac_value;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
-		*val = data->vref_mv;
+		if (data->ref_mode == MCP472X_REF_VDD)
+			ret = regulator_get_voltage(data->vdd_reg);
+		else
+			ret = regulator_get_voltage(data->vref_reg);
+
+		if (ret < 0)
+			return ret;
+
+		*val = ret / 1000;
 		*val2 = 12;
 		return IIO_VAL_FRACTIONAL_LOG2;
 	}
@@ -323,27 +365,98 @@ static const struct iio_info mcp4725_inf
 	.driver_module = THIS_MODULE,
 };
 
+#ifdef CONFIG_OF
+static int mcp4725_probe_dt(struct device *dev,
+			    struct mcp4725_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	/* check if is the vref-supply defined */
+	pdata->use_vref = of_property_read_bool(np, "vref-supply");
+	pdata->vref_buffered =
+		of_property_read_bool(np, "microchip,vref-buffered");
+
+	return 0;
+}
+#else
+static int mcp4725_probe_dt(struct device *dev,
+			    struct mcp4725_platform_data *platform_data)
+{
+	return -ENODEV;
+}
+#endif
+
 static int mcp4725_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct mcp4725_data *data;
 	struct iio_dev *indio_dev;
-	struct mcp4725_platform_data *platform_data = client->dev.platform_data;
-	u8 inbuf[3];
+	struct mcp4725_platform_data *pdata, pdata_dt;
+	u8 inbuf[4];
 	u8 pd;
+	u8 ref;
 	int err;
 
-	if (!platform_data || !platform_data->vref_mv) {
-		dev_err(&client->dev, "invalid platform data");
-		return -EINVAL;
-	}
-
 	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 	if (indio_dev == NULL)
 		return -ENOMEM;
 	data = iio_priv(indio_dev);
 	i2c_set_clientdata(client, indio_dev);
 	data->client = client;
+	data->id = id->driver_data;
+	pdata = dev_get_platdata(&client->dev);
+
+	if (!pdata) {
+		err = mcp4725_probe_dt(&client->dev, &pdata_dt);
+		if (err) {
+			dev_err(&client->dev,
+				"invalid platform or devicetree data");
+			return err;
+		}
+		pdata = &pdata_dt;
+	}
+
+	if (data->id == MCP4725 && pdata->use_vref) {
+		dev_err(&client->dev,
+			"external reference is unavailable on MCP4725");
+		return -EINVAL;
+	}
+
+	if (!pdata->use_vref && pdata->vref_buffered) {
+		dev_err(&client->dev,
+			"buffering is unavailable on the internal reference");
+		return -EINVAL;
+	}
+
+	if (!pdata->use_vref)
+		data->ref_mode = MCP472X_REF_VDD;
+	else
+		data->ref_mode = pdata->vref_buffered ?
+			MCP472X_REF_VREF_BUFFERED :
+			MCP472X_REF_VREF_UNBUFFERED;
+
+	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
+	if (IS_ERR(data->vdd_reg))
+		return PTR_ERR(data->vdd_reg);
+
+	err = regulator_enable(data->vdd_reg);
+	if (err)
+		return err;
+
+	if (pdata->use_vref) {
+		data->vref_reg = devm_regulator_get(&client->dev, "vref");
+		if (IS_ERR(data->vref_reg)) {
+			err = PTR_ERR(data->vref_reg);
+			goto err_disable_vdd_reg;
+		}
+
+		err = regulator_enable(data->vref_reg);
+		if (err)
+			goto err_disable_vdd_reg;
+	}
 
 	indio_dev->dev.parent = &client->dev;
 	indio_dev->name = id->name;
@@ -352,25 +465,56 @@ static int mcp4725_probe(struct i2c_clie
 	indio_dev->num_channels = 1;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 
-	data->vref_mv = platform_data->vref_mv;
+	/* read current DAC value and settings */
+	err = i2c_master_recv(client, inbuf, data->id == MCP4725 ? 3 : 4);
 
-	/* read current DAC value */
-	err = i2c_master_recv(client, inbuf, 3);
 	if (err < 0) {
 		dev_err(&client->dev, "failed to read DAC value");
-		return err;
+		goto err_disable_vref_reg;
 	}
 	pd = (inbuf[0] >> 1) & 0x3;
 	data->powerdown = pd > 0 ? true : false;
-	data->powerdown_mode = pd ? pd - 1 : 2; /* largest register to gnd */
+	data->powerdown_mode = pd ? pd - 1 : 2; /* largest resistor to gnd */
 	data->dac_value = (inbuf[1] << 4) | (inbuf[2] >> 4);
+	if (data->id == MCP4726)
+		ref = (inbuf[3] >> 3) & 0x3;
 
-	return iio_device_register(indio_dev);
+	if (data->id == MCP4726 && ref != data->ref_mode) {
+		dev_info(&client->dev,
+			"voltage reference mode differs (conf: %u, eeprom: %u), setting %u",
+			data->ref_mode, ref, data->ref_mode);
+		err = mcp4726_set_cfg(indio_dev);
+		if (err < 0)
+			goto err_disable_vref_reg;
+	}
+ 
+	err = iio_device_register(indio_dev);
+	if (err)
+		goto err_disable_vref_reg;
+
+	return 0;
+
+err_disable_vref_reg:
+	if (data->vref_reg)
+		regulator_disable(data->vref_reg);
+
+err_disable_vdd_reg:
+	regulator_disable(data->vdd_reg);
+
+	return err;
 }
 
 static int mcp4725_remove(struct i2c_client *client)
 {
-	iio_device_unregister(i2c_get_clientdata(client));
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct mcp4725_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	if (data->vref_reg)
+		regulator_disable(data->vref_reg);
+	regulator_disable(data->vdd_reg);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/gyro/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/gyro/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/gyro/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/gyro/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -84,6 +84,24 @@ config HID_SENSOR_GYRO_3D
 	  Say yes here to build support for the HID SENSOR
 	  Gyroscope 3D.
 
+config MPU3050
+	tristate
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select REGMAP
+
+config MPU3050_I2C
+	tristate "Invensense MPU3050 devices on I2C"
+	depends on !(INPUT_MPU3050=y || INPUT_MPU3050=m)
+	depends on I2C
+	select MPU3050
+	select REGMAP_I2C
+	select I2C_MUX
+	help
+	  This driver supports the Invensense MPU3050 gyroscope over I2C.
+	  This driver can be built as a module. The module will be called
+	  inv-mpu3050-i2c.
+
 config IIO_ST_GYRO_3AXIS
 	tristate "STMicroelectronics gyroscopes 3-Axis Driver"
 	depends on (I2C || SPI_MASTER) && SYSFS
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/gyro/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/gyro/Makefile
--- linux-libre-4.9-gnu/drivers/iio/gyro/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/gyro/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,11 @@ obj-$(CONFIG_BMG160_SPI) += bmg160_spi.o
 
 obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
 
+# Currently this is rolled into one module, split it if
+# we ever create a separate SPI interface for MPU-3050
+obj-$(CONFIG_MPU3050) += mpu3050.o
+mpu3050-objs := mpu3050-core.o mpu3050-i2c.o
+
 itg3200-y               := itg3200_core.o
 itg3200-$(CONFIG_IIO_BUFFER) += itg3200_buffer.o
 obj-$(CONFIG_ITG3200)   += itg3200.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/gyro/mpu3050-core.c linux-libre-4.10-rc8-gnu/drivers/iio/gyro/mpu3050-core.c
--- linux-libre-4.9-gnu/drivers/iio/gyro/mpu3050-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/gyro/mpu3050-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1306 @@
+/*
+ * MPU3050 gyroscope driver
+ *
+ * Copyright (C) 2016 Linaro Ltd.
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Based on the input subsystem driver, Copyright (C) 2011 Wistron Co.Ltd
+ * Joseph Lai <joseph_lai@wistron.com> and trimmed down by
+ * Alan Cox <alan@linux.intel.com> in turn based on bma023.c.
+ * Device behaviour based on a misc driver posted by Nathan Royer in 2011.
+ *
+ * TODO: add support for setting up the low pass 3dB frequency.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+
+#include "mpu3050.h"
+
+#define MPU3050_CHIP_ID		0x69
+
+/*
+ * Register map: anything suffixed *_H is a big-endian high byte and always
+ * followed by the corresponding low byte (*_L) even though these are not
+ * explicitly included in the register definitions.
+ */
+#define MPU3050_CHIP_ID_REG	0x00
+#define MPU3050_PRODUCT_ID_REG	0x01
+#define MPU3050_XG_OFFS_TC	0x05
+#define MPU3050_YG_OFFS_TC	0x08
+#define MPU3050_ZG_OFFS_TC	0x0B
+#define MPU3050_X_OFFS_USR_H	0x0C
+#define MPU3050_Y_OFFS_USR_H	0x0E
+#define MPU3050_Z_OFFS_USR_H	0x10
+#define MPU3050_FIFO_EN		0x12
+#define MPU3050_AUX_VDDIO	0x13
+#define MPU3050_SLV_ADDR	0x14
+#define MPU3050_SMPLRT_DIV	0x15
+#define MPU3050_DLPF_FS_SYNC	0x16
+#define MPU3050_INT_CFG		0x17
+#define MPU3050_AUX_ADDR	0x18
+#define MPU3050_INT_STATUS	0x1A
+#define MPU3050_TEMP_H		0x1B
+#define MPU3050_XOUT_H		0x1D
+#define MPU3050_YOUT_H		0x1F
+#define MPU3050_ZOUT_H		0x21
+#define MPU3050_DMP_CFG1	0x35
+#define MPU3050_DMP_CFG2	0x36
+#define MPU3050_BANK_SEL	0x37
+#define MPU3050_MEM_START_ADDR	0x38
+#define MPU3050_MEM_R_W		0x39
+#define MPU3050_FIFO_COUNT_H	0x3A
+#define MPU3050_FIFO_R		0x3C
+#define MPU3050_USR_CTRL	0x3D
+#define MPU3050_PWR_MGM		0x3E
+
+/* MPU memory bank read options */
+#define MPU3050_MEM_PRFTCH	BIT(5)
+#define MPU3050_MEM_USER_BANK	BIT(4)
+/* Bits 8-11 select memory bank */
+#define MPU3050_MEM_RAM_BANK_0	0
+#define MPU3050_MEM_RAM_BANK_1	1
+#define MPU3050_MEM_RAM_BANK_2	2
+#define MPU3050_MEM_RAM_BANK_3	3
+#define MPU3050_MEM_OTP_BANK_0	4
+
+#define MPU3050_AXIS_REGS(axis) (MPU3050_XOUT_H + (axis * 2))
+
+/* Register bits */
+
+/* FIFO Enable */
+#define MPU3050_FIFO_EN_FOOTER		BIT(0)
+#define MPU3050_FIFO_EN_AUX_ZOUT	BIT(1)
+#define MPU3050_FIFO_EN_AUX_YOUT	BIT(2)
+#define MPU3050_FIFO_EN_AUX_XOUT	BIT(3)
+#define MPU3050_FIFO_EN_GYRO_ZOUT	BIT(4)
+#define MPU3050_FIFO_EN_GYRO_YOUT	BIT(5)
+#define MPU3050_FIFO_EN_GYRO_XOUT	BIT(6)
+#define MPU3050_FIFO_EN_TEMP_OUT	BIT(7)
+
+/*
+ * Digital Low Pass filter (DLPF)
+ * Full Scale (FS)
+ * and Synchronization
+ */
+#define MPU3050_EXT_SYNC_NONE		0x00
+#define MPU3050_EXT_SYNC_TEMP		0x20
+#define MPU3050_EXT_SYNC_GYROX		0x40
+#define MPU3050_EXT_SYNC_GYROY		0x60
+#define MPU3050_EXT_SYNC_GYROZ		0x80
+#define MPU3050_EXT_SYNC_ACCELX	0xA0
+#define MPU3050_EXT_SYNC_ACCELY	0xC0
+#define MPU3050_EXT_SYNC_ACCELZ	0xE0
+#define MPU3050_EXT_SYNC_MASK		0xE0
+#define MPU3050_EXT_SYNC_SHIFT		5
+
+#define MPU3050_FS_250DPS		0x00
+#define MPU3050_FS_500DPS		0x08
+#define MPU3050_FS_1000DPS		0x10
+#define MPU3050_FS_2000DPS		0x18
+#define MPU3050_FS_MASK			0x18
+#define MPU3050_FS_SHIFT		3
+
+#define MPU3050_DLPF_CFG_256HZ_NOLPF2	0x00
+#define MPU3050_DLPF_CFG_188HZ		0x01
+#define MPU3050_DLPF_CFG_98HZ		0x02
+#define MPU3050_DLPF_CFG_42HZ		0x03
+#define MPU3050_DLPF_CFG_20HZ		0x04
+#define MPU3050_DLPF_CFG_10HZ		0x05
+#define MPU3050_DLPF_CFG_5HZ		0x06
+#define MPU3050_DLPF_CFG_2100HZ_NOLPF	0x07
+#define MPU3050_DLPF_CFG_MASK		0x07
+#define MPU3050_DLPF_CFG_SHIFT		0
+
+/* Interrupt config */
+#define MPU3050_INT_RAW_RDY_EN		BIT(0)
+#define MPU3050_INT_DMP_DONE_EN		BIT(1)
+#define MPU3050_INT_MPU_RDY_EN		BIT(2)
+#define MPU3050_INT_ANYRD_2CLEAR	BIT(4)
+#define MPU3050_INT_LATCH_EN		BIT(5)
+#define MPU3050_INT_OPEN		BIT(6)
+#define MPU3050_INT_ACTL		BIT(7)
+/* Interrupt status */
+#define MPU3050_INT_STATUS_RAW_RDY	BIT(0)
+#define MPU3050_INT_STATUS_DMP_DONE	BIT(1)
+#define MPU3050_INT_STATUS_MPU_RDY	BIT(2)
+#define MPU3050_INT_STATUS_FIFO_OVFLW	BIT(7)
+/* USR_CTRL */
+#define MPU3050_USR_CTRL_FIFO_EN	BIT(6)
+#define MPU3050_USR_CTRL_AUX_IF_EN	BIT(5)
+#define MPU3050_USR_CTRL_AUX_IF_RST	BIT(3)
+#define MPU3050_USR_CTRL_FIFO_RST	BIT(1)
+#define MPU3050_USR_CTRL_GYRO_RST	BIT(0)
+/* PWR_MGM */
+#define MPU3050_PWR_MGM_PLL_X		0x01
+#define MPU3050_PWR_MGM_PLL_Y		0x02
+#define MPU3050_PWR_MGM_PLL_Z		0x03
+#define MPU3050_PWR_MGM_CLKSEL_MASK	0x07
+#define MPU3050_PWR_MGM_STBY_ZG		BIT(3)
+#define MPU3050_PWR_MGM_STBY_YG		BIT(4)
+#define MPU3050_PWR_MGM_STBY_XG		BIT(5)
+#define MPU3050_PWR_MGM_SLEEP		BIT(6)
+#define MPU3050_PWR_MGM_RESET		BIT(7)
+#define MPU3050_PWR_MGM_MASK		0xff
+
+/*
+ * Fullscale precision is (for finest precision) +/- 250 deg/s, so the full
+ * scale is actually 500 deg/s. All 16 bits are then used to cover this scale,
+ * in two's complement.
+ */
+static unsigned int mpu3050_fs_precision[] = {
+	IIO_DEGREE_TO_RAD(250),
+	IIO_DEGREE_TO_RAD(500),
+	IIO_DEGREE_TO_RAD(1000),
+	IIO_DEGREE_TO_RAD(2000)
+};
+
+/*
+ * Regulator names
+ */
+static const char mpu3050_reg_vdd[] = "vdd";
+static const char mpu3050_reg_vlogic[] = "vlogic";
+
+static unsigned int mpu3050_get_freq(struct mpu3050 *mpu3050)
+{
+	unsigned int freq;
+
+	if (mpu3050->lpf == MPU3050_DLPF_CFG_256HZ_NOLPF2)
+		freq = 8000;
+	else
+		freq = 1000;
+	freq /= (mpu3050->divisor + 1);
+
+	return freq;
+}
+
+static int mpu3050_start_sampling(struct mpu3050 *mpu3050)
+{
+	__be16 raw_val[3];
+	int ret;
+	int i;
+
+	/* Reset */
+	ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM,
+				 MPU3050_PWR_MGM_RESET, MPU3050_PWR_MGM_RESET);
+	if (ret)
+		return ret;
+
+	/* Turn on the Z-axis PLL */
+	ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM,
+				 MPU3050_PWR_MGM_CLKSEL_MASK,
+				 MPU3050_PWR_MGM_PLL_Z);
+	if (ret)
+		return ret;
+
+	/* Write calibration offset registers */
+	for (i = 0; i < 3; i++)
+		raw_val[i] = cpu_to_be16(mpu3050->calibration[i]);
+
+	ret = regmap_bulk_write(mpu3050->map, MPU3050_X_OFFS_USR_H, raw_val,
+				sizeof(raw_val));
+	if (ret)
+		return ret;
+
+	/* Set low pass filter (sample rate), sync and full scale */
+	ret = regmap_write(mpu3050->map, MPU3050_DLPF_FS_SYNC,
+			   MPU3050_EXT_SYNC_NONE << MPU3050_EXT_SYNC_SHIFT |
+			   mpu3050->fullscale << MPU3050_FS_SHIFT |
+			   mpu3050->lpf << MPU3050_DLPF_CFG_SHIFT);
+	if (ret)
+		return ret;
+
+	/* Set up sampling frequency */
+	ret = regmap_write(mpu3050->map, MPU3050_SMPLRT_DIV, mpu3050->divisor);
+	if (ret)
+		return ret;
+
+	/*
+	 * Max 50 ms start-up time after setting DLPF_FS_SYNC
+	 * according to the data sheet, then wait for the next sample
+	 * at this frequency T = 1000/f ms.
+	 */
+	msleep(50 + 1000 / mpu3050_get_freq(mpu3050));
+
+	return 0;
+}
+
+static int mpu3050_set_8khz_samplerate(struct mpu3050 *mpu3050)
+{
+	int ret;
+	u8 divisor;
+	enum mpu3050_lpf lpf;
+
+	lpf = mpu3050->lpf;
+	divisor = mpu3050->divisor;
+
+	mpu3050->lpf = LPF_256_HZ_NOLPF; /* 8 kHz base frequency */
+	mpu3050->divisor = 0; /* Divide by 1 */
+	ret = mpu3050_start_sampling(mpu3050);
+
+	mpu3050->lpf = lpf;
+	mpu3050->divisor = divisor;
+
+	return ret;
+}
+
+static int mpu3050_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2,
+			    long mask)
+{
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+	int ret;
+	__be16 raw_val;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_OFFSET:
+		switch (chan->type) {
+		case IIO_TEMP:
+			/* The temperature scaling is (x+23000)/280 Celsius */
+			*val = 23000;
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_CALIBBIAS:
+		switch (chan->type) {
+		case IIO_ANGL_VEL:
+			*val = mpu3050->calibration[chan->scan_index-1];
+			return IIO_VAL_INT;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = mpu3050_get_freq(mpu3050);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_TEMP:
+			/* Millidegrees, see about temperature scaling above */
+			*val = 1000;
+			*val2 = 280;
+			return IIO_VAL_FRACTIONAL;
+		case IIO_ANGL_VEL:
+			/*
+			 * Convert to the corresponding full scale in
+			 * radians. All 16 bits are used with sign to
+			 * span the available scale: to account for the one
+			 * missing value if we multiply by 1/S16_MAX, instead
+			 * multiply with 2/U16_MAX.
+			 */
+			*val = mpu3050_fs_precision[mpu3050->fullscale] * 2;
+			*val2 = U16_MAX;
+			return IIO_VAL_FRACTIONAL;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_RAW:
+		/* Resume device */
+		pm_runtime_get_sync(mpu3050->dev);
+		mutex_lock(&mpu3050->lock);
+
+		ret = mpu3050_set_8khz_samplerate(mpu3050);
+		if (ret)
+			goto out_read_raw_unlock;
+
+		switch (chan->type) {
+		case IIO_TEMP:
+			ret = regmap_bulk_read(mpu3050->map, MPU3050_TEMP_H,
+					       &raw_val, sizeof(raw_val));
+			if (ret) {
+				dev_err(mpu3050->dev,
+					"error reading temperature\n");
+				goto out_read_raw_unlock;
+			}
+
+			*val = be16_to_cpu(raw_val);
+			ret = IIO_VAL_INT;
+
+			goto out_read_raw_unlock;
+		case IIO_ANGL_VEL:
+			ret = regmap_bulk_read(mpu3050->map,
+				       MPU3050_AXIS_REGS(chan->scan_index-1),
+				       &raw_val,
+				       sizeof(raw_val));
+			if (ret) {
+				dev_err(mpu3050->dev,
+					"error reading axis data\n");
+				goto out_read_raw_unlock;
+			}
+
+			*val = be16_to_cpu(raw_val);
+			ret = IIO_VAL_INT;
+
+			goto out_read_raw_unlock;
+		default:
+			ret = -EINVAL;
+			goto out_read_raw_unlock;
+		}
+	default:
+		break;
+	}
+
+	return -EINVAL;
+
+out_read_raw_unlock:
+	mutex_unlock(&mpu3050->lock);
+	pm_runtime_mark_last_busy(mpu3050->dev);
+	pm_runtime_put_autosuspend(mpu3050->dev);
+
+	return ret;
+}
+
+static int mpu3050_write_raw(struct iio_dev *indio_dev,
+			     const struct iio_chan_spec *chan,
+			     int val, int val2, long mask)
+{
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+	/*
+	 * Couldn't figure out a way to precalculate these at compile time.
+	 */
+	unsigned int fs250 =
+		DIV_ROUND_CLOSEST(mpu3050_fs_precision[0] * 1000000 * 2,
+				  U16_MAX);
+	unsigned int fs500 =
+		DIV_ROUND_CLOSEST(mpu3050_fs_precision[1] * 1000000 * 2,
+				  U16_MAX);
+	unsigned int fs1000 =
+		DIV_ROUND_CLOSEST(mpu3050_fs_precision[2] * 1000000 * 2,
+				  U16_MAX);
+	unsigned int fs2000 =
+		DIV_ROUND_CLOSEST(mpu3050_fs_precision[3] * 1000000 * 2,
+				  U16_MAX);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBBIAS:
+		if (chan->type != IIO_ANGL_VEL)
+			return -EINVAL;
+		mpu3050->calibration[chan->scan_index-1] = val;
+		return 0;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		/*
+		 * The max samplerate is 8000 Hz, the minimum
+		 * 1000 / 256 ~= 4 Hz
+		 */
+		if (val < 4 || val > 8000)
+			return -EINVAL;
+
+		/*
+		 * Above 1000 Hz we must turn off the digital low pass filter
+		 * so we get a base frequency of 8kHz to the divider
+		 */
+		if (val > 1000) {
+			mpu3050->lpf = LPF_256_HZ_NOLPF;
+			mpu3050->divisor = DIV_ROUND_CLOSEST(8000, val) - 1;
+			return 0;
+		}
+
+		mpu3050->lpf = LPF_188_HZ;
+		mpu3050->divisor = DIV_ROUND_CLOSEST(1000, val) - 1;
+		return 0;
+	case IIO_CHAN_INFO_SCALE:
+		if (chan->type != IIO_ANGL_VEL)
+			return -EINVAL;
+		/*
+		 * We support +/-250, +/-500, +/-1000 and +/2000 deg/s
+		 * which means we need to round to the closest radians
+		 * which will be roughly +/-4.3, +/-8.7, +/-17.5, +/-35
+		 * rad/s. The scale is then for the 16 bits used to cover
+		 * it 2/(2^16) of that.
+		 */
+
+		/* Just too large, set the max range */
+		if (val != 0) {
+			mpu3050->fullscale = FS_2000_DPS;
+			return 0;
+		}
+
+		/*
+		 * Now we're dealing with fractions below zero in millirad/s
+		 * do some integer interpolation and match with the closest
+		 * fullscale in the table.
+		 */
+		if (val2 <= fs250 ||
+		    val2 < ((fs500 + fs250) / 2))
+			mpu3050->fullscale = FS_250_DPS;
+		else if (val2 <= fs500 ||
+			 val2 < ((fs1000 + fs500) / 2))
+			mpu3050->fullscale = FS_500_DPS;
+		else if (val2 <= fs1000 ||
+			 val2 < ((fs2000 + fs1000) / 2))
+			mpu3050->fullscale = FS_1000_DPS;
+		else
+			/* Catch-all */
+			mpu3050->fullscale = FS_2000_DPS;
+		return 0;
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static irqreturn_t mpu3050_trigger_handler(int irq, void *p)
+{
+	const struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+	int ret;
+	/*
+	 * Temperature 1*16 bits
+	 * Three axes 3*16 bits
+	 * Timestamp 64 bits (4*16 bits)
+	 * Sum total 8*16 bits
+	 */
+	__be16 hw_values[8];
+	s64 timestamp;
+	unsigned int datums_from_fifo = 0;
+
+	/*
+	 * If we're using the hardware trigger, get the precise timestamp from
+	 * the top half of the threaded IRQ handler. Otherwise get the
+	 * timestamp here so it will be close in time to the actual values
+	 * read from the registers.
+	 */
+	if (iio_trigger_using_own(indio_dev))
+		timestamp = mpu3050->hw_timestamp;
+	else
+		timestamp = iio_get_time_ns(indio_dev);
+
+	mutex_lock(&mpu3050->lock);
+
+	/* Using the hardware IRQ trigger? Check the buffer then. */
+	if (mpu3050->hw_irq_trigger) {
+		__be16 raw_fifocnt;
+		u16 fifocnt;
+		/* X, Y, Z + temperature */
+		unsigned int bytes_per_datum = 8;
+		bool fifo_overflow = false;
+
+		ret = regmap_bulk_read(mpu3050->map,
+				       MPU3050_FIFO_COUNT_H,
+				       &raw_fifocnt,
+				       sizeof(raw_fifocnt));
+		if (ret)
+			goto out_trigger_unlock;
+		fifocnt = be16_to_cpu(raw_fifocnt);
+
+		if (fifocnt == 512) {
+			dev_info(mpu3050->dev,
+				 "FIFO overflow! Emptying and resetting FIFO\n");
+			fifo_overflow = true;
+			/* Reset and enable the FIFO */
+			ret = regmap_update_bits(mpu3050->map,
+						 MPU3050_USR_CTRL,
+						 MPU3050_USR_CTRL_FIFO_EN |
+						 MPU3050_USR_CTRL_FIFO_RST,
+						 MPU3050_USR_CTRL_FIFO_EN |
+						 MPU3050_USR_CTRL_FIFO_RST);
+			if (ret) {
+				dev_info(mpu3050->dev, "error resetting FIFO\n");
+				goto out_trigger_unlock;
+			}
+			mpu3050->pending_fifo_footer = false;
+		}
+
+		if (fifocnt)
+			dev_dbg(mpu3050->dev,
+				"%d bytes in the FIFO\n",
+				fifocnt);
+
+		while (!fifo_overflow && fifocnt > bytes_per_datum) {
+			unsigned int toread;
+			unsigned int offset;
+			__be16 fifo_values[5];
+
+			/*
+			 * If there is a FIFO footer in the pipe, first clear
+			 * that out. This follows the complex algorithm in the
+			 * datasheet that states that you may never leave the
+			 * FIFO empty after the first reading: you have to
+			 * always leave two footer bytes in it. The footer is
+			 * in practice just two zero bytes.
+			 */
+			if (mpu3050->pending_fifo_footer) {
+				toread = bytes_per_datum + 2;
+				offset = 0;
+			} else {
+				toread = bytes_per_datum;
+				offset = 1;
+				/* Put in some dummy value */
+				fifo_values[0] = 0xAAAA;
+			}
+
+			ret = regmap_bulk_read(mpu3050->map,
+					       MPU3050_FIFO_R,
+					       &fifo_values[offset],
+					       toread);
+
+			dev_dbg(mpu3050->dev,
+				"%04x %04x %04x %04x %04x\n",
+				fifo_values[0],
+				fifo_values[1],
+				fifo_values[2],
+				fifo_values[3],
+				fifo_values[4]);
+
+			/* Index past the footer (fifo_values[0]) and push */
+			iio_push_to_buffers_with_timestamp(indio_dev,
+							   &fifo_values[1],
+							   timestamp);
+
+			fifocnt -= toread;
+			datums_from_fifo++;
+			mpu3050->pending_fifo_footer = true;
+
+			/*
+			 * If we're emptying the FIFO, just make sure to
+			 * check if something new appeared.
+			 */
+			if (fifocnt < bytes_per_datum) {
+				ret = regmap_bulk_read(mpu3050->map,
+						       MPU3050_FIFO_COUNT_H,
+						       &raw_fifocnt,
+						       sizeof(raw_fifocnt));
+				if (ret)
+					goto out_trigger_unlock;
+				fifocnt = be16_to_cpu(raw_fifocnt);
+			}
+
+			if (fifocnt < bytes_per_datum)
+				dev_dbg(mpu3050->dev,
+					"%d bytes left in the FIFO\n",
+					fifocnt);
+
+			/*
+			 * At this point, the timestamp that triggered the
+			 * hardware interrupt is no longer valid for what
+			 * we are reading (the interrupt likely fired for
+			 * the value on the top of the FIFO), so set the
+			 * timestamp to zero and let userspace deal with it.
+			 */
+			timestamp = 0;
+		}
+	}
+
+	/*
+	 * If we picked some datums from the FIFO that's enough, else
+	 * fall through and just read from the current value registers.
+	 * This happens in two cases:
+	 *
+	 * - We are using some other trigger (external, like an HRTimer)
+	 *   than the sensor's own sample generator. In this case the
+	 *   sensor is just set to the max sampling frequency and we give
+	 *   the trigger a copy of the latest value every time we get here.
+	 *
+	 * - The hardware trigger is active but unused and we actually use
+	 *   another trigger which calls here with a frequency higher
+	 *   than what the device provides data. We will then just read
+	 *   duplicate values directly from the hardware registers.
+	 */
+	if (datums_from_fifo) {
+		dev_dbg(mpu3050->dev,
+			"read %d datums from the FIFO\n",
+			datums_from_fifo);
+		goto out_trigger_unlock;
+	}
+
+	ret = regmap_bulk_read(mpu3050->map, MPU3050_TEMP_H, &hw_values,
+			       sizeof(hw_values));
+	if (ret) {
+		dev_err(mpu3050->dev,
+			"error reading axis data\n");
+		goto out_trigger_unlock;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, hw_values, timestamp);
+
+out_trigger_unlock:
+	mutex_unlock(&mpu3050->lock);
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int mpu3050_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+
+	pm_runtime_get_sync(mpu3050->dev);
+
+	/* Unless we have OUR trigger active, run at full speed */
+	if (!mpu3050->hw_irq_trigger)
+		return mpu3050_set_8khz_samplerate(mpu3050);
+
+	return 0;
+}
+
+static int mpu3050_buffer_postdisable(struct iio_dev *indio_dev)
+{
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+
+	pm_runtime_mark_last_busy(mpu3050->dev);
+	pm_runtime_put_autosuspend(mpu3050->dev);
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops mpu3050_buffer_setup_ops = {
+	.preenable = mpu3050_buffer_preenable,
+	.postenable = iio_triggered_buffer_postenable,
+	.predisable = iio_triggered_buffer_predisable,
+	.postdisable = mpu3050_buffer_postdisable,
+};
+
+static const struct iio_mount_matrix *
+mpu3050_get_mount_matrix(const struct iio_dev *indio_dev,
+			 const struct iio_chan_spec *chan)
+{
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+
+	return &mpu3050->orientation;
+}
+
+static const struct iio_chan_spec_ext_info mpu3050_ext_info[] = {
+	IIO_MOUNT_MATRIX(IIO_SHARED_BY_TYPE, mpu3050_get_mount_matrix),
+	{ },
+};
+
+#define MPU3050_AXIS_CHANNEL(axis, index)				\
+	{								\
+		.type = IIO_ANGL_VEL,					\
+		.modified = 1,						\
+		.channel2 = IIO_MOD_##axis,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
+			BIT(IIO_CHAN_INFO_CALIBBIAS),			\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+		.ext_info = mpu3050_ext_info,				\
+		.scan_index = index,					\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 16,					\
+			.storagebits = 16,				\
+			.endianness = IIO_BE,				\
+		},							\
+	}
+
+static const struct iio_chan_spec mpu3050_channels[] = {
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OFFSET),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_BE,
+		},
+	},
+	MPU3050_AXIS_CHANNEL(X, 1),
+	MPU3050_AXIS_CHANNEL(Y, 2),
+	MPU3050_AXIS_CHANNEL(Z, 3),
+	IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+/* Four channels apart from timestamp, scan mask = 0x0f */
+static const unsigned long mpu3050_scan_masks[] = { 0xf, 0 };
+
+/*
+ * These are just the hardcoded factors resulting from the more elaborate
+ * calculations done with fractions in the scale raw get/set functions.
+ */
+static IIO_CONST_ATTR(anglevel_scale_available,
+		      "0.000122070 "
+		      "0.000274658 "
+		      "0.000518798 "
+		      "0.001068115");
+
+static struct attribute *mpu3050_attributes[] = {
+	&iio_const_attr_anglevel_scale_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group mpu3050_attribute_group = {
+	.attrs = mpu3050_attributes,
+};
+
+static const struct iio_info mpu3050_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = mpu3050_read_raw,
+	.write_raw = mpu3050_write_raw,
+	.attrs = &mpu3050_attribute_group,
+};
+
+/**
+ * mpu3050_read_mem() - read MPU-3050 internal memory
+ * @mpu3050: device to read from
+ * @bank: target bank
+ * @addr: target address
+ * @len: number of bytes
+ * @buf: the buffer to store the read bytes in
+ */
+static int mpu3050_read_mem(struct mpu3050 *mpu3050,
+			    u8 bank,
+			    u8 addr,
+			    u8 len,
+			    u8 *buf)
+{
+	int ret;
+
+	ret = regmap_write(mpu3050->map,
+			   MPU3050_BANK_SEL,
+			   bank);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(mpu3050->map,
+			   MPU3050_MEM_START_ADDR,
+			   addr);
+	if (ret)
+		return ret;
+
+	return regmap_bulk_read(mpu3050->map,
+				MPU3050_MEM_R_W,
+				buf,
+				len);
+}
+
+static int mpu3050_hw_init(struct mpu3050 *mpu3050)
+{
+	int ret;
+	u8 otp[8];
+
+	/* Reset */
+	ret = regmap_update_bits(mpu3050->map,
+				 MPU3050_PWR_MGM,
+				 MPU3050_PWR_MGM_RESET,
+				 MPU3050_PWR_MGM_RESET);
+	if (ret)
+		return ret;
+
+	/* Turn on the PLL */
+	ret = regmap_update_bits(mpu3050->map,
+				 MPU3050_PWR_MGM,
+				 MPU3050_PWR_MGM_CLKSEL_MASK,
+				 MPU3050_PWR_MGM_PLL_Z);
+	if (ret)
+		return ret;
+
+	/* Disable IRQs */
+	ret = regmap_write(mpu3050->map,
+			   MPU3050_INT_CFG,
+			   0);
+	if (ret)
+		return ret;
+
+	/* Read out the 8 bytes of OTP (one-time-programmable) memory */
+	ret = mpu3050_read_mem(mpu3050,
+			       (MPU3050_MEM_PRFTCH |
+				MPU3050_MEM_USER_BANK |
+				MPU3050_MEM_OTP_BANK_0),
+			       0,
+			       sizeof(otp),
+			       otp);
+	if (ret)
+		return ret;
+
+	/* This is device-unique data so it goes into the entropy pool */
+	add_device_randomness(otp, sizeof(otp));
+
+	dev_info(mpu3050->dev,
+		 "die ID: %04X, wafer ID: %02X, A lot ID: %04X, "
+		 "W lot ID: %03X, WP ID: %01X, rev ID: %02X\n",
+		 /* Die ID, bits 0-12 */
+		 (otp[1] << 8 | otp[0]) & 0x1fff,
+		 /* Wafer ID, bits 13-17 */
+		 ((otp[2] << 8 | otp[1]) & 0x03e0) >> 5,
+		 /* A lot ID, bits 18-33 */
+		 ((otp[4] << 16 | otp[3] << 8 | otp[2]) & 0x3fffc) >> 2,
+		 /* W lot ID, bits 34-45 */
+		 ((otp[5] << 8 | otp[4]) & 0x3ffc) >> 2,
+		 /* WP ID, bits 47-49 */
+		 ((otp[6] << 8 | otp[5]) & 0x0380) >> 7,
+		 /* rev ID, bits 50-55 */
+		 otp[6] >> 2);
+
+	return 0;
+}
+
+static int mpu3050_power_up(struct mpu3050 *mpu3050)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(mpu3050->regs), mpu3050->regs);
+	if (ret) {
+		dev_err(mpu3050->dev, "cannot enable regulators\n");
+		return ret;
+	}
+	/*
+	 * 20-100 ms start-up time for register read/write according to
+	 * the datasheet, be on the safe side and wait 200 ms.
+	 */
+	msleep(200);
+
+	/* Take device out of sleep mode */
+	ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM,
+				 MPU3050_PWR_MGM_SLEEP, 0);
+	if (ret) {
+		dev_err(mpu3050->dev, "error setting power mode\n");
+		return ret;
+	}
+	msleep(10);
+
+	return 0;
+}
+
+static int mpu3050_power_down(struct mpu3050 *mpu3050)
+{
+	int ret;
+
+	/*
+	 * Put MPU-3050 into sleep mode before cutting regulators.
+	 * This is important, because we may not be the sole user
+	 * of the regulator so the power may stay on after this, and
+	 * then we would be wasting power unless we go to sleep mode
+	 * first.
+	 */
+	ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM,
+				 MPU3050_PWR_MGM_SLEEP, MPU3050_PWR_MGM_SLEEP);
+	if (ret)
+		dev_err(mpu3050->dev, "error putting to sleep\n");
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(mpu3050->regs), mpu3050->regs);
+	if (ret)
+		dev_err(mpu3050->dev, "error disabling regulators\n");
+
+	return 0;
+}
+
+static irqreturn_t mpu3050_irq_handler(int irq, void *p)
+{
+	struct iio_trigger *trig = p;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+
+	if (!mpu3050->hw_irq_trigger)
+		return IRQ_NONE;
+
+	/* Get the time stamp as close in time as possible */
+	mpu3050->hw_timestamp = iio_get_time_ns(indio_dev);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t mpu3050_irq_thread(int irq, void *p)
+{
+	struct iio_trigger *trig = p;
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+	unsigned int val;
+	int ret;
+
+	/* ACK IRQ and check if it was from us */
+	ret = regmap_read(mpu3050->map, MPU3050_INT_STATUS, &val);
+	if (ret) {
+		dev_err(mpu3050->dev, "error reading IRQ status\n");
+		return IRQ_HANDLED;
+	}
+	if (!(val & MPU3050_INT_STATUS_RAW_RDY))
+		return IRQ_NONE;
+
+	iio_trigger_poll_chained(p);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * mpu3050_drdy_trigger_set_state() - set data ready interrupt state
+ * @trig: trigger instance
+ * @enable: true if trigger should be enabled, false to disable
+ */
+static int mpu3050_drdy_trigger_set_state(struct iio_trigger *trig,
+					  bool enable)
+{
+	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+	unsigned int val;
+	int ret;
+
+	/* Disabling trigger: disable interrupt and return */
+	if (!enable) {
+		/* Disable all interrupts */
+		ret = regmap_write(mpu3050->map,
+				   MPU3050_INT_CFG,
+				   0);
+		if (ret)
+			dev_err(mpu3050->dev, "error disabling IRQ\n");
+
+		/* Clear IRQ flag */
+		ret = regmap_read(mpu3050->map, MPU3050_INT_STATUS, &val);
+		if (ret)
+			dev_err(mpu3050->dev, "error clearing IRQ status\n");
+
+		/* Disable all things in the FIFO and reset it */
+		ret = regmap_write(mpu3050->map, MPU3050_FIFO_EN, 0);
+		if (ret)
+			dev_err(mpu3050->dev, "error disabling FIFO\n");
+
+		ret = regmap_write(mpu3050->map, MPU3050_USR_CTRL,
+				   MPU3050_USR_CTRL_FIFO_RST);
+		if (ret)
+			dev_err(mpu3050->dev, "error resetting FIFO\n");
+
+		pm_runtime_mark_last_busy(mpu3050->dev);
+		pm_runtime_put_autosuspend(mpu3050->dev);
+		mpu3050->hw_irq_trigger = false;
+
+		return 0;
+	} else {
+		/* Else we're enabling the trigger from this point */
+		pm_runtime_get_sync(mpu3050->dev);
+		mpu3050->hw_irq_trigger = true;
+
+		/* Disable all things in the FIFO */
+		ret = regmap_write(mpu3050->map, MPU3050_FIFO_EN, 0);
+		if (ret)
+			return ret;
+
+		/* Reset and enable the FIFO */
+		ret = regmap_update_bits(mpu3050->map, MPU3050_USR_CTRL,
+					 MPU3050_USR_CTRL_FIFO_EN |
+					 MPU3050_USR_CTRL_FIFO_RST,
+					 MPU3050_USR_CTRL_FIFO_EN |
+					 MPU3050_USR_CTRL_FIFO_RST);
+		if (ret)
+			return ret;
+
+		mpu3050->pending_fifo_footer = false;
+
+		/* Turn on the FIFO for temp+X+Y+Z */
+		ret = regmap_write(mpu3050->map, MPU3050_FIFO_EN,
+				   MPU3050_FIFO_EN_TEMP_OUT |
+				   MPU3050_FIFO_EN_GYRO_XOUT |
+				   MPU3050_FIFO_EN_GYRO_YOUT |
+				   MPU3050_FIFO_EN_GYRO_ZOUT |
+				   MPU3050_FIFO_EN_FOOTER);
+		if (ret)
+			return ret;
+
+		/* Configure the sample engine */
+		ret = mpu3050_start_sampling(mpu3050);
+		if (ret)
+			return ret;
+
+		/* Clear IRQ flag */
+		ret = regmap_read(mpu3050->map, MPU3050_INT_STATUS, &val);
+		if (ret)
+			dev_err(mpu3050->dev, "error clearing IRQ status\n");
+
+		/* Give us interrupts whenever there is new data ready */
+		val = MPU3050_INT_RAW_RDY_EN;
+
+		if (mpu3050->irq_actl)
+			val |= MPU3050_INT_ACTL;
+		if (mpu3050->irq_latch)
+			val |= MPU3050_INT_LATCH_EN;
+		if (mpu3050->irq_opendrain)
+			val |= MPU3050_INT_OPEN;
+
+		ret = regmap_write(mpu3050->map, MPU3050_INT_CFG, val);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct iio_trigger_ops mpu3050_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = mpu3050_drdy_trigger_set_state,
+};
+
+static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
+{
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+	unsigned long irq_trig;
+	int ret;
+
+	mpu3050->trig = devm_iio_trigger_alloc(&indio_dev->dev,
+					       "%s-dev%d",
+					       indio_dev->name,
+					       indio_dev->id);
+	if (!mpu3050->trig)
+		return -ENOMEM;
+
+	/* Check if IRQ is open drain */
+	if (of_property_read_bool(mpu3050->dev->of_node, "drive-open-drain"))
+		mpu3050->irq_opendrain = true;
+
+	irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+	/*
+	 * Configure the interrupt generator hardware to supply whatever
+	 * the interrupt is configured for, edges low/high level low/high,
+	 * we can provide it all.
+	 */
+	switch (irq_trig) {
+	case IRQF_TRIGGER_RISING:
+		dev_info(&indio_dev->dev,
+			 "pulse interrupts on the rising edge\n");
+		if (mpu3050->irq_opendrain) {
+			dev_info(&indio_dev->dev,
+				 "rising edge incompatible with open drain\n");
+			mpu3050->irq_opendrain = false;
+		}
+		break;
+	case IRQF_TRIGGER_FALLING:
+		mpu3050->irq_actl = true;
+		dev_info(&indio_dev->dev,
+			 "pulse interrupts on the falling edge\n");
+		break;
+	case IRQF_TRIGGER_HIGH:
+		mpu3050->irq_latch = true;
+		dev_info(&indio_dev->dev,
+			 "interrupts active high level\n");
+		if (mpu3050->irq_opendrain) {
+			dev_info(&indio_dev->dev,
+				 "active high incompatible with open drain\n");
+			mpu3050->irq_opendrain = false;
+		}
+		/*
+		 * With level IRQs, we mask the IRQ until it is processed,
+		 * but with edge IRQs (pulses) we can queue several interrupts
+		 * in the top half.
+		 */
+		irq_trig |= IRQF_ONESHOT;
+		break;
+	case IRQF_TRIGGER_LOW:
+		mpu3050->irq_latch = true;
+		mpu3050->irq_actl = true;
+		irq_trig |= IRQF_ONESHOT;
+		dev_info(&indio_dev->dev,
+			 "interrupts active low level\n");
+		break;
+	default:
+		/* This is the most preferred mode, if possible */
+		dev_err(&indio_dev->dev,
+			"unsupported IRQ trigger specified (%lx), enforce "
+			"rising edge\n", irq_trig);
+		irq_trig = IRQF_TRIGGER_RISING;
+		break;
+	}
+
+	/* An open drain line can be shared with several devices */
+	if (mpu3050->irq_opendrain)
+		irq_trig |= IRQF_SHARED;
+
+	ret = request_threaded_irq(irq,
+				   mpu3050_irq_handler,
+				   mpu3050_irq_thread,
+				   irq_trig,
+				   mpu3050->trig->name,
+				   mpu3050->trig);
+	if (ret) {
+		dev_err(mpu3050->dev,
+			"can't get IRQ %d, error %d\n", irq, ret);
+		return ret;
+	}
+
+	mpu3050->irq = irq;
+	mpu3050->trig->dev.parent = mpu3050->dev;
+	mpu3050->trig->ops = &mpu3050_trigger_ops;
+	iio_trigger_set_drvdata(mpu3050->trig, indio_dev);
+
+	ret = iio_trigger_register(mpu3050->trig);
+	if (ret)
+		return ret;
+
+	indio_dev->trig = iio_trigger_get(mpu3050->trig);
+
+	return 0;
+}
+
+int mpu3050_common_probe(struct device *dev,
+			 struct regmap *map,
+			 int irq,
+			 const char *name)
+{
+	struct iio_dev *indio_dev;
+	struct mpu3050 *mpu3050;
+	unsigned int val;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*mpu3050));
+	if (!indio_dev)
+		return -ENOMEM;
+	mpu3050 = iio_priv(indio_dev);
+
+	mpu3050->dev = dev;
+	mpu3050->map = map;
+	mutex_init(&mpu3050->lock);
+	/* Default fullscale: 2000 degrees per second */
+	mpu3050->fullscale = FS_2000_DPS;
+	/* 1 kHz, divide by 100, default frequency = 10 Hz */
+	mpu3050->lpf = MPU3050_DLPF_CFG_188HZ;
+	mpu3050->divisor = 99;
+
+	/* Read the mounting matrix, if present */
+	ret = of_iio_read_mount_matrix(dev, "mount-matrix",
+				       &mpu3050->orientation);
+	if (ret)
+		return ret;
+
+	/* Fetch and turn on regulators */
+	mpu3050->regs[0].supply = mpu3050_reg_vdd;
+	mpu3050->regs[1].supply = mpu3050_reg_vlogic;
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(mpu3050->regs),
+				      mpu3050->regs);
+	if (ret) {
+		dev_err(dev, "Cannot get regulators\n");
+		return ret;
+	}
+
+	ret = mpu3050_power_up(mpu3050);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(map, MPU3050_CHIP_ID_REG, &val);
+	if (ret) {
+		dev_err(dev, "could not read device ID\n");
+		ret = -ENODEV;
+
+		goto err_power_down;
+	}
+
+	if (val != MPU3050_CHIP_ID) {
+		dev_err(dev, "unsupported chip id %02x\n", (u8)val);
+		ret = -ENODEV;
+		goto err_power_down;
+	}
+
+	ret = regmap_read(map, MPU3050_PRODUCT_ID_REG, &val);
+	if (ret) {
+		dev_err(dev, "could not read device ID\n");
+		ret = -ENODEV;
+
+		goto err_power_down;
+	}
+	dev_info(dev, "found MPU-3050 part no: %d, version: %d\n",
+		 ((val >> 4) & 0xf), (val & 0xf));
+
+	ret = mpu3050_hw_init(mpu3050);
+	if (ret)
+		goto err_power_down;
+
+	indio_dev->dev.parent = dev;
+	indio_dev->channels = mpu3050_channels;
+	indio_dev->num_channels = ARRAY_SIZE(mpu3050_channels);
+	indio_dev->info = &mpu3050_info;
+	indio_dev->available_scan_masks = mpu3050_scan_masks;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = name;
+
+	ret = iio_triggered_buffer_setup(indio_dev, iio_pollfunc_store_time,
+					 mpu3050_trigger_handler,
+					 &mpu3050_buffer_setup_ops);
+	if (ret) {
+		dev_err(dev, "triggered buffer setup failed\n");
+		goto err_power_down;
+	}
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(dev, "device register failed\n");
+		goto err_cleanup_buffer;
+	}
+
+	dev_set_drvdata(dev, indio_dev);
+
+	/* Check if we have an assigned IRQ to use as trigger */
+	if (irq) {
+		ret = mpu3050_trigger_probe(indio_dev, irq);
+		if (ret)
+			dev_err(dev, "failed to register trigger\n");
+	}
+
+	/* Enable runtime PM */
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+	/*
+	 * Set autosuspend to two orders of magnitude larger than the
+	 * start-up time. 100ms start-up time means 10000ms autosuspend,
+	 * i.e. 10 seconds.
+	 */
+	pm_runtime_set_autosuspend_delay(dev, 10000);
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_put(dev);
+
+	return 0;
+
+err_cleanup_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+err_power_down:
+	mpu3050_power_down(mpu3050);
+
+	return ret;
+}
+EXPORT_SYMBOL(mpu3050_common_probe);
+
+int mpu3050_common_remove(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+
+	pm_runtime_get_sync(dev);
+	pm_runtime_put_noidle(dev);
+	pm_runtime_disable(dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+	if (mpu3050->irq)
+		free_irq(mpu3050->irq, mpu3050);
+	iio_device_unregister(indio_dev);
+	mpu3050_power_down(mpu3050);
+
+	return 0;
+}
+EXPORT_SYMBOL(mpu3050_common_remove);
+
+#ifdef CONFIG_PM
+static int mpu3050_runtime_suspend(struct device *dev)
+{
+	return mpu3050_power_down(iio_priv(dev_get_drvdata(dev)));
+}
+
+static int mpu3050_runtime_resume(struct device *dev)
+{
+	return mpu3050_power_up(iio_priv(dev_get_drvdata(dev)));
+}
+#endif /* CONFIG_PM */
+
+const struct dev_pm_ops mpu3050_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(mpu3050_runtime_suspend,
+			   mpu3050_runtime_resume, NULL)
+};
+EXPORT_SYMBOL(mpu3050_dev_pm_ops);
+
+MODULE_AUTHOR("Linus Walleij");
+MODULE_DESCRIPTION("MPU3050 gyroscope driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/gyro/mpu3050.h linux-libre-4.10-rc8-gnu/drivers/iio/gyro/mpu3050.h
--- linux-libre-4.9-gnu/drivers/iio/gyro/mpu3050.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/gyro/mpu3050.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,96 @@
+#include <linux/iio/iio.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/i2c.h>
+
+/**
+ * enum mpu3050_fullscale - indicates the full range of the sensor in deg/sec
+ */
+enum mpu3050_fullscale {
+	FS_250_DPS = 0,
+	FS_500_DPS,
+	FS_1000_DPS,
+	FS_2000_DPS,
+};
+
+/**
+ * enum mpu3050_lpf - indicates the low pass filter width
+ */
+enum mpu3050_lpf {
+	/* This implicity sets sample frequency to 8 kHz */
+	LPF_256_HZ_NOLPF = 0,
+	/* All others sets the sample frequency to 1 kHz */
+	LPF_188_HZ,
+	LPF_98_HZ,
+	LPF_42_HZ,
+	LPF_20_HZ,
+	LPF_10_HZ,
+	LPF_5_HZ,
+	LPF_2100_HZ_NOLPF,
+};
+
+enum mpu3050_axis {
+	AXIS_X = 0,
+	AXIS_Y,
+	AXIS_Z,
+	AXIS_MAX,
+};
+
+/**
+ * struct mpu3050 - instance state container for the device
+ * @dev: parent device for this instance
+ * @orientation: mounting matrix, flipped axis etc
+ * @map: regmap to reach the registers
+ * @lock: serialization lock to marshal all requests
+ * @irq: the IRQ used for this device
+ * @regs: the regulators to power this device
+ * @fullscale: the current fullscale setting for the device
+ * @lpf: digital low pass filter setting for the device
+ * @divisor: base frequency divider: divides 8 or 1 kHz
+ * @calibration: the three signed 16-bit calibration settings that
+ * get written into the offset registers for each axis to compensate
+ * for DC offsets
+ * @trig: trigger for the MPU-3050 interrupt, if present
+ * @hw_irq_trigger: hardware interrupt trigger is in use
+ * @irq_actl: interrupt is active low
+ * @irq_latch: latched IRQ, this means that it is a level IRQ
+ * @irq_opendrain: the interrupt line shall be configured open drain
+ * @pending_fifo_footer: tells us if there is a pending footer in the FIFO
+ * that we have to read out first when handling the FIFO
+ * @hw_timestamp: latest hardware timestamp from the trigger IRQ, when in
+ * use
+ * @i2cmux: an I2C mux reflecting the fact that this sensor is a hub with
+ * a pass-through I2C interface coming out of it: this device needs to be
+ * powered up in order to reach devices on the other side of this mux
+ */
+struct mpu3050 {
+	struct device *dev;
+	struct iio_mount_matrix orientation;
+	struct regmap *map;
+	struct mutex lock;
+	int irq;
+	struct regulator_bulk_data regs[2];
+	enum mpu3050_fullscale fullscale;
+	enum mpu3050_lpf lpf;
+	u8 divisor;
+	s16 calibration[3];
+	struct iio_trigger *trig;
+	bool hw_irq_trigger;
+	bool irq_actl;
+	bool irq_latch;
+	bool irq_opendrain;
+	bool pending_fifo_footer;
+	s64 hw_timestamp;
+	struct i2c_mux_core *i2cmux;
+};
+
+/* Probe called from different transports */
+int mpu3050_common_probe(struct device *dev,
+			 struct regmap *map,
+			 int irq,
+			 const char *name);
+int mpu3050_common_remove(struct device *dev);
+
+/* PM ops */
+extern const struct dev_pm_ops mpu3050_dev_pm_ops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/gyro/mpu3050-i2c.c linux-libre-4.10-rc8-gnu/drivers/iio/gyro/mpu3050-i2c.c
--- linux-libre-4.9-gnu/drivers/iio/gyro/mpu3050-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/gyro/mpu3050-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,124 @@
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/pm_runtime.h>
+
+#include "mpu3050.h"
+
+static const struct regmap_config mpu3050_i2c_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int mpu3050_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id)
+{
+	struct mpu3050 *mpu3050 = i2c_mux_priv(mux);
+
+	/* Just power up the device, that is all that is needed */
+	pm_runtime_get_sync(mpu3050->dev);
+	return 0;
+}
+
+static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
+{
+	struct mpu3050 *mpu3050 = i2c_mux_priv(mux);
+
+	pm_runtime_mark_last_busy(mpu3050->dev);
+	pm_runtime_put_autosuspend(mpu3050->dev);
+	return 0;
+}
+
+static int mpu3050_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct regmap *regmap;
+	const char *name;
+	struct mpu3050 *mpu3050;
+	int ret;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_I2C_BLOCK))
+		return -EOPNOTSUPP;
+
+	if (id)
+		name = id->name;
+	else
+		return -ENODEV;
+
+	regmap = devm_regmap_init_i2c(client, &mpu3050_i2c_regmap_config);
+	if (IS_ERR(regmap)) {
+		dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+			(int)PTR_ERR(regmap));
+		return PTR_ERR(regmap);
+	}
+
+	ret = mpu3050_common_probe(&client->dev, regmap, client->irq, name);
+	if (ret)
+		return ret;
+
+	/* The main driver is up, now register the I2C mux */
+	mpu3050 = iio_priv(dev_get_drvdata(&client->dev));
+	mpu3050->i2cmux = i2c_mux_alloc(client->adapter, &client->dev,
+					1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
+					mpu3050_i2c_bypass_select,
+					mpu3050_i2c_bypass_deselect);
+	/* Just fail the mux, there is no point in killing the driver */
+	if (!mpu3050->i2cmux)
+		dev_err(&client->dev, "failed to allocate I2C mux\n");
+	else {
+		mpu3050->i2cmux->priv = mpu3050;
+		ret = i2c_mux_add_adapter(mpu3050->i2cmux, 0, 0, 0);
+		if (ret)
+			dev_err(&client->dev, "failed to add I2C mux\n");
+	}
+
+	return 0;
+}
+
+static int mpu3050_i2c_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
+	struct mpu3050 *mpu3050 = iio_priv(indio_dev);
+
+	if (mpu3050->i2cmux)
+		i2c_mux_del_adapters(mpu3050->i2cmux);
+
+	return mpu3050_common_remove(&client->dev);
+}
+
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct i2c_device_id mpu3050_i2c_id[] = {
+	{ "mpu3050" },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, mpu3050_i2c_id);
+
+static const struct of_device_id mpu3050_i2c_of_match[] = {
+	{ .compatible = "invensense,mpu3050", .data = "mpu3050" },
+	/* Deprecated vendor ID from the Input driver */
+	{ .compatible = "invn,mpu3050", .data = "mpu3050" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, mpu3050_i2c_of_match);
+
+static struct i2c_driver mpu3050_i2c_driver = {
+	.probe = mpu3050_i2c_probe,
+	.remove = mpu3050_i2c_remove,
+	.id_table = mpu3050_i2c_id,
+	.driver = {
+		.of_match_table = mpu3050_i2c_of_match,
+		.name = "mpu3050-i2c",
+		.pm = &mpu3050_dev_pm_ops,
+	},
+};
+module_i2c_driver(mpu3050_i2c_driver);
+
+MODULE_AUTHOR("Linus Walleij");
+MODULE_DESCRIPTION("Invensense MPU3050 gyroscope driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/gyro/st_gyro_core.c linux-libre-4.10-rc8-gnu/drivers/iio/gyro/st_gyro_core.c
--- linux-libre-4.9-gnu/drivers/iio/gyro/st_gyro_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/gyro/st_gyro_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,79 +39,6 @@
 #define ST_GYRO_FS_AVL_500DPS			500
 #define ST_GYRO_FS_AVL_2000DPS			2000
 
-/* CUSTOM VALUES FOR SENSOR 1 */
-#define ST_GYRO_1_WAI_EXP			0xd3
-#define ST_GYRO_1_ODR_ADDR			0x20
-#define ST_GYRO_1_ODR_MASK			0xc0
-#define ST_GYRO_1_ODR_AVL_100HZ_VAL		0x00
-#define ST_GYRO_1_ODR_AVL_200HZ_VAL		0x01
-#define ST_GYRO_1_ODR_AVL_400HZ_VAL		0x02
-#define ST_GYRO_1_ODR_AVL_800HZ_VAL		0x03
-#define ST_GYRO_1_PW_ADDR			0x20
-#define ST_GYRO_1_PW_MASK			0x08
-#define ST_GYRO_1_FS_ADDR			0x23
-#define ST_GYRO_1_FS_MASK			0x30
-#define ST_GYRO_1_FS_AVL_250_VAL		0x00
-#define ST_GYRO_1_FS_AVL_500_VAL		0x01
-#define ST_GYRO_1_FS_AVL_2000_VAL		0x02
-#define ST_GYRO_1_FS_AVL_250_GAIN		IIO_DEGREE_TO_RAD(8750)
-#define ST_GYRO_1_FS_AVL_500_GAIN		IIO_DEGREE_TO_RAD(17500)
-#define ST_GYRO_1_FS_AVL_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
-#define ST_GYRO_1_BDU_ADDR			0x23
-#define ST_GYRO_1_BDU_MASK			0x80
-#define ST_GYRO_1_DRDY_IRQ_ADDR			0x22
-#define ST_GYRO_1_DRDY_IRQ_INT2_MASK		0x08
-#define ST_GYRO_1_MULTIREAD_BIT			true
-
-/* CUSTOM VALUES FOR SENSOR 2 */
-#define ST_GYRO_2_WAI_EXP			0xd4
-#define ST_GYRO_2_ODR_ADDR			0x20
-#define ST_GYRO_2_ODR_MASK			0xc0
-#define ST_GYRO_2_ODR_AVL_95HZ_VAL		0x00
-#define ST_GYRO_2_ODR_AVL_190HZ_VAL		0x01
-#define ST_GYRO_2_ODR_AVL_380HZ_VAL		0x02
-#define ST_GYRO_2_ODR_AVL_760HZ_VAL		0x03
-#define ST_GYRO_2_PW_ADDR			0x20
-#define ST_GYRO_2_PW_MASK			0x08
-#define ST_GYRO_2_FS_ADDR			0x23
-#define ST_GYRO_2_FS_MASK			0x30
-#define ST_GYRO_2_FS_AVL_250_VAL		0x00
-#define ST_GYRO_2_FS_AVL_500_VAL		0x01
-#define ST_GYRO_2_FS_AVL_2000_VAL		0x02
-#define ST_GYRO_2_FS_AVL_250_GAIN		IIO_DEGREE_TO_RAD(8750)
-#define ST_GYRO_2_FS_AVL_500_GAIN		IIO_DEGREE_TO_RAD(17500)
-#define ST_GYRO_2_FS_AVL_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
-#define ST_GYRO_2_BDU_ADDR			0x23
-#define ST_GYRO_2_BDU_MASK			0x80
-#define ST_GYRO_2_DRDY_IRQ_ADDR			0x22
-#define ST_GYRO_2_DRDY_IRQ_INT2_MASK		0x08
-#define ST_GYRO_2_MULTIREAD_BIT			true
-
-/* CUSTOM VALUES FOR SENSOR 3 */
-#define ST_GYRO_3_WAI_EXP			0xd7
-#define ST_GYRO_3_ODR_ADDR			0x20
-#define ST_GYRO_3_ODR_MASK			0xc0
-#define ST_GYRO_3_ODR_AVL_95HZ_VAL		0x00
-#define ST_GYRO_3_ODR_AVL_190HZ_VAL		0x01
-#define ST_GYRO_3_ODR_AVL_380HZ_VAL		0x02
-#define ST_GYRO_3_ODR_AVL_760HZ_VAL		0x03
-#define ST_GYRO_3_PW_ADDR			0x20
-#define ST_GYRO_3_PW_MASK			0x08
-#define ST_GYRO_3_FS_ADDR			0x23
-#define ST_GYRO_3_FS_MASK			0x30
-#define ST_GYRO_3_FS_AVL_250_VAL		0x00
-#define ST_GYRO_3_FS_AVL_500_VAL		0x01
-#define ST_GYRO_3_FS_AVL_2000_VAL		0x02
-#define ST_GYRO_3_FS_AVL_250_GAIN		IIO_DEGREE_TO_RAD(8750)
-#define ST_GYRO_3_FS_AVL_500_GAIN		IIO_DEGREE_TO_RAD(17500)
-#define ST_GYRO_3_FS_AVL_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
-#define ST_GYRO_3_BDU_ADDR			0x23
-#define ST_GYRO_3_BDU_MASK			0x80
-#define ST_GYRO_3_DRDY_IRQ_ADDR			0x22
-#define ST_GYRO_3_DRDY_IRQ_INT2_MASK		0x08
-#define ST_GYRO_3_MULTIREAD_BIT			true
-
-
 static const struct iio_chan_spec st_gyro_16bit_channels[] = {
 	ST_SENSORS_LSM_CHANNELS(IIO_ANGL_VEL,
 			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -130,7 +57,7 @@ static const struct iio_chan_spec st_gyr
 
 static const struct st_sensor_settings st_gyro_sensors_settings[] = {
 	{
-		.wai = ST_GYRO_1_WAI_EXP,
+		.wai = 0xd3,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = L3G4200D_GYRO_DEV_NAME,
@@ -138,18 +65,18 @@ static const struct st_sensor_settings s
 		},
 		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 		.odr = {
-			.addr = ST_GYRO_1_ODR_ADDR,
-			.mask = ST_GYRO_1_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0xc0,
 			.odr_avl = {
-				{ 100, ST_GYRO_1_ODR_AVL_100HZ_VAL, },
-				{ 200, ST_GYRO_1_ODR_AVL_200HZ_VAL, },
-				{ 400, ST_GYRO_1_ODR_AVL_400HZ_VAL, },
-				{ 800, ST_GYRO_1_ODR_AVL_800HZ_VAL, },
+				{ .hz = 100, .value = 0x00, },
+				{ .hz = 200, .value = 0x01, },
+				{ .hz = 400, .value = 0x02, },
+				{ .hz = 800, .value = 0x03, },
 			},
 		},
 		.pw = {
-			.addr = ST_GYRO_1_PW_ADDR,
-			.mask = ST_GYRO_1_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x08,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -158,33 +85,33 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_GYRO_1_FS_ADDR,
-			.mask = ST_GYRO_1_FS_MASK,
+			.addr = 0x23,
+			.mask = 0x30,
 			.fs_avl = {
 				[0] = {
 					.num = ST_GYRO_FS_AVL_250DPS,
-					.value = ST_GYRO_1_FS_AVL_250_VAL,
-					.gain = ST_GYRO_1_FS_AVL_250_GAIN,
+					.value = 0x00,
+					.gain = IIO_DEGREE_TO_RAD(8750),
 				},
 				[1] = {
 					.num = ST_GYRO_FS_AVL_500DPS,
-					.value = ST_GYRO_1_FS_AVL_500_VAL,
-					.gain = ST_GYRO_1_FS_AVL_500_GAIN,
+					.value = 0x01,
+					.gain = IIO_DEGREE_TO_RAD(17500),
 				},
 				[2] = {
 					.num = ST_GYRO_FS_AVL_2000DPS,
-					.value = ST_GYRO_1_FS_AVL_2000_VAL,
-					.gain = ST_GYRO_1_FS_AVL_2000_GAIN,
+					.value = 0x02,
+					.gain = IIO_DEGREE_TO_RAD(70000),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_GYRO_1_BDU_ADDR,
-			.mask = ST_GYRO_1_BDU_MASK,
+			.addr = 0x23,
+			.mask = 0x80,
 		},
 		.drdy_irq = {
-			.addr = ST_GYRO_1_DRDY_IRQ_ADDR,
-			.mask_int2 = ST_GYRO_1_DRDY_IRQ_INT2_MASK,
+			.addr = 0x22,
+			.mask_int2 = 0x08,
 			/*
 			 * The sensor has IHL (active low) and open
 			 * drain settings, but only for INT1 and not
@@ -192,11 +119,11 @@ static const struct st_sensor_settings s
 			 */
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_GYRO_1_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_GYRO_2_WAI_EXP,
+		.wai = 0xd4,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = L3GD20_GYRO_DEV_NAME,
@@ -208,18 +135,18 @@ static const struct st_sensor_settings s
 		},
 		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 		.odr = {
-			.addr = ST_GYRO_2_ODR_ADDR,
-			.mask = ST_GYRO_2_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0xc0,
 			.odr_avl = {
-				{ 95, ST_GYRO_2_ODR_AVL_95HZ_VAL, },
-				{ 190, ST_GYRO_2_ODR_AVL_190HZ_VAL, },
-				{ 380, ST_GYRO_2_ODR_AVL_380HZ_VAL, },
-				{ 760, ST_GYRO_2_ODR_AVL_760HZ_VAL, },
+				{ .hz = 95, .value = 0x00, },
+				{ .hz = 190, .value = 0x01, },
+				{ .hz = 380, .value = 0x02, },
+				{ .hz = 760, .value = 0x03, },
 			},
 		},
 		.pw = {
-			.addr = ST_GYRO_2_PW_ADDR,
-			.mask = ST_GYRO_2_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x08,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -228,33 +155,33 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_GYRO_2_FS_ADDR,
-			.mask = ST_GYRO_2_FS_MASK,
+			.addr = 0x23,
+			.mask = 0x30,
 			.fs_avl = {
 				[0] = {
 					.num = ST_GYRO_FS_AVL_250DPS,
-					.value = ST_GYRO_2_FS_AVL_250_VAL,
-					.gain = ST_GYRO_2_FS_AVL_250_GAIN,
+					.value = 0x00,
+					.gain = IIO_DEGREE_TO_RAD(8750),
 				},
 				[1] = {
 					.num = ST_GYRO_FS_AVL_500DPS,
-					.value = ST_GYRO_2_FS_AVL_500_VAL,
-					.gain = ST_GYRO_2_FS_AVL_500_GAIN,
+					.value = 0x01,
+					.gain = IIO_DEGREE_TO_RAD(17500),
 				},
 				[2] = {
 					.num = ST_GYRO_FS_AVL_2000DPS,
-					.value = ST_GYRO_2_FS_AVL_2000_VAL,
-					.gain = ST_GYRO_2_FS_AVL_2000_GAIN,
+					.value = 0x02,
+					.gain = IIO_DEGREE_TO_RAD(70000),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_GYRO_2_BDU_ADDR,
-			.mask = ST_GYRO_2_BDU_MASK,
+			.addr = 0x23,
+			.mask = 0x80,
 		},
 		.drdy_irq = {
-			.addr = ST_GYRO_2_DRDY_IRQ_ADDR,
-			.mask_int2 = ST_GYRO_2_DRDY_IRQ_INT2_MASK,
+			.addr = 0x22,
+			.mask_int2 = 0x08,
 			/*
 			 * The sensor has IHL (active low) and open
 			 * drain settings, but only for INT1 and not
@@ -262,29 +189,29 @@ static const struct st_sensor_settings s
 			 */
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_GYRO_2_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_GYRO_3_WAI_EXP,
+		.wai = 0xd7,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = L3GD20_GYRO_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 		.odr = {
-			.addr = ST_GYRO_3_ODR_ADDR,
-			.mask = ST_GYRO_3_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0xc0,
 			.odr_avl = {
-				{ 95, ST_GYRO_3_ODR_AVL_95HZ_VAL, },
-				{ 190, ST_GYRO_3_ODR_AVL_190HZ_VAL, },
-				{ 380, ST_GYRO_3_ODR_AVL_380HZ_VAL, },
-				{ 760, ST_GYRO_3_ODR_AVL_760HZ_VAL, },
+				{ .hz = 95, .value = 0x00, },
+				{ .hz = 190, .value = 0x01, },
+				{ .hz = 380, .value = 0x02, },
+				{ .hz = 760, .value = 0x03, },
 			},
 		},
 		.pw = {
-			.addr = ST_GYRO_3_PW_ADDR,
-			.mask = ST_GYRO_3_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x08,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -293,33 +220,33 @@ static const struct st_sensor_settings s
 			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
 		},
 		.fs = {
-			.addr = ST_GYRO_3_FS_ADDR,
-			.mask = ST_GYRO_3_FS_MASK,
+			.addr = 0x23,
+			.mask = 0x30,
 			.fs_avl = {
 				[0] = {
 					.num = ST_GYRO_FS_AVL_250DPS,
-					.value = ST_GYRO_3_FS_AVL_250_VAL,
-					.gain = ST_GYRO_3_FS_AVL_250_GAIN,
+					.value = 0x00,
+					.gain = IIO_DEGREE_TO_RAD(8750),
 				},
 				[1] = {
 					.num = ST_GYRO_FS_AVL_500DPS,
-					.value = ST_GYRO_3_FS_AVL_500_VAL,
-					.gain = ST_GYRO_3_FS_AVL_500_GAIN,
+					.value = 0x01,
+					.gain = IIO_DEGREE_TO_RAD(17500),
 				},
 				[2] = {
 					.num = ST_GYRO_FS_AVL_2000DPS,
-					.value = ST_GYRO_3_FS_AVL_2000_VAL,
-					.gain = ST_GYRO_3_FS_AVL_2000_GAIN,
+					.value = 0x02,
+					.gain = IIO_DEGREE_TO_RAD(70000),
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_GYRO_3_BDU_ADDR,
-			.mask = ST_GYRO_3_BDU_MASK,
+			.addr = 0x23,
+			.mask = 0x80,
 		},
 		.drdy_irq = {
-			.addr = ST_GYRO_3_DRDY_IRQ_ADDR,
-			.mask_int2 = ST_GYRO_3_DRDY_IRQ_INT2_MASK,
+			.addr = 0x22,
+			.mask_int2 = 0x08,
 			/*
 			 * The sensor has IHL (active low) and open
 			 * drain settings, but only for INT1 and not
@@ -327,7 +254,7 @@ static const struct st_sensor_settings s
 			 */
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_GYRO_3_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/health/afe4403.c linux-libre-4.10-rc8-gnu/drivers/iio/health/afe4403.c
--- linux-libre-4.9-gnu/drivers/iio/health/afe4403.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/health/afe4403.c	2017-02-12 16:03:20.000000000 -0500
@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, afe4403_of_match
 
 static int __maybe_unused afe4403_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
 	struct afe4403_data *afe = iio_priv(indio_dev);
 	int ret;
 
@@ -443,7 +443,7 @@ static int __maybe_unused afe4403_suspen
 
 static int __maybe_unused afe4403_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev *indio_dev = spi_get_drvdata(to_spi_device(dev));
 	struct afe4403_data *afe = iio_priv(indio_dev);
 	int ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/health/afe4404.c linux-libre-4.10-rc8-gnu/drivers/iio/health/afe4404.c
--- linux-libre-4.9-gnu/drivers/iio/health/afe4404.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/health/afe4404.c	2017-02-12 16:03:20.000000000 -0500
@@ -428,7 +428,7 @@ MODULE_DEVICE_TABLE(of, afe4404_of_match
 
 static int __maybe_unused afe4404_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 	struct afe4404_data *afe = iio_priv(indio_dev);
 	int ret;
 
@@ -449,7 +449,7 @@ static int __maybe_unused afe4404_suspen
 
 static int __maybe_unused afe4404_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 	struct afe4404_data *afe = iio_priv(indio_dev);
 	int ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/health/max30100.c linux-libre-4.10-rc8-gnu/drivers/iio/health/max30100.c
--- linux-libre-4.9-gnu/drivers/iio/health/max30100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/health/max30100.c	2017-02-12 16:03:20.000000000 -0500
@@ -238,7 +238,7 @@ static irqreturn_t max30100_interrupt_ha
 
 	mutex_lock(&data->lock);
 
-	while (cnt || (cnt = max30100_fifo_count(data) > 0)) {
+	while (cnt || (cnt = max30100_fifo_count(data)) > 0) {
 		ret = max30100_read_measurement(data);
 		if (ret)
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/dht11.c linux-libre-4.10-rc8-gnu/drivers/iio/humidity/dht11.c
--- linux-libre-4.9-gnu/drivers/iio/humidity/dht11.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/dht11.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,8 @@
  * a) select an implementation using busy loop polling on those systems
  * b) use the checksum to do some probabilistic decoding
  */
-#define DHT11_START_TRANSMISSION	18  /* ms */
+#define DHT11_START_TRANSMISSION_MIN	18000  /* us */
+#define DHT11_START_TRANSMISSION_MAX	20000  /* us */
 #define DHT11_MIN_TIMERES	34000  /* ns */
 #define DHT11_THRESHOLD		49000  /* ns */
 #define DHT11_AMBIG_LOW		23000  /* ns */
@@ -228,7 +229,8 @@ static int dht11_read_raw(struct iio_dev
 		ret = gpio_direction_output(dht11->gpio, 0);
 		if (ret)
 			goto err;
-		msleep(DHT11_START_TRANSMISSION);
+		usleep_range(DHT11_START_TRANSMISSION_MIN,
+			     DHT11_START_TRANSMISSION_MAX);
 		ret = gpio_direction_input(dht11->gpio);
 		if (ret)
 			goto err;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/hdc100x.c linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hdc100x.c
--- linux-libre-4.9-gnu/drivers/iio/humidity/hdc100x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hdc100x.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,11 +22,15 @@
 
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
 
 #define HDC100X_REG_TEMP			0x00
 #define HDC100X_REG_HUMIDITY			0x01
 
 #define HDC100X_REG_CONFIG			0x02
+#define HDC100X_REG_CONFIG_ACQ_MODE		BIT(12)
 #define HDC100X_REG_CONFIG_HEATER_EN		BIT(13)
 
 struct hdc100x_data {
@@ -87,22 +91,40 @@ static const struct iio_chan_spec hdc100
 			BIT(IIO_CHAN_INFO_SCALE) |
 			BIT(IIO_CHAN_INFO_INT_TIME) |
 			BIT(IIO_CHAN_INFO_OFFSET),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_BE,
+		},
 	},
 	{
 		.type = IIO_HUMIDITYRELATIVE,
 		.address = HDC100X_REG_HUMIDITY,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 			BIT(IIO_CHAN_INFO_SCALE) |
-			BIT(IIO_CHAN_INFO_INT_TIME)
+			BIT(IIO_CHAN_INFO_INT_TIME),
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 'u',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_BE,
+		},
 	},
 	{
 		.type = IIO_CURRENT,
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
 		.extend_name = "heater",
 		.output = 1,
+		.scan_index = -1,
 	},
+	IIO_CHAN_SOFT_TIMESTAMP(2),
 };
 
+static const unsigned long hdc100x_scan_masks[] = {0x3, 0};
+
 static int hdc100x_update_config(struct hdc100x_data *data, int mask, int val)
 {
 	int tmp = (~mask & data->config) | val;
@@ -183,7 +205,14 @@ static int hdc100x_read_raw(struct iio_d
 			*val = hdc100x_get_heater_status(data);
 			ret = IIO_VAL_INT;
 		} else {
+			ret = iio_device_claim_direct_mode(indio_dev);
+			if (ret) {
+				mutex_unlock(&data->lock);
+				return ret;
+			}
+
 			ret = hdc100x_get_measurement(data, chan);
+			iio_device_release_direct_mode(indio_dev);
 			if (ret >= 0) {
 				*val = ret;
 				ret = IIO_VAL_INT;
@@ -246,6 +275,78 @@ static int hdc100x_write_raw(struct iio_
 	}
 }
 
+static int hdc100x_buffer_postenable(struct iio_dev *indio_dev)
+{
+	struct hdc100x_data *data = iio_priv(indio_dev);
+	int ret;
+
+	/* Buffer is enabled. First set ACQ Mode, then attach poll func */
+	mutex_lock(&data->lock);
+	ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE,
+				    HDC100X_REG_CONFIG_ACQ_MODE);
+	mutex_unlock(&data->lock);
+	if (ret)
+		return ret;
+
+	return iio_triggered_buffer_postenable(indio_dev);
+}
+
+static int hdc100x_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct hdc100x_data *data = iio_priv(indio_dev);
+	int ret;
+
+	/* First detach poll func, then reset ACQ mode. OK to disable buffer */
+	ret = iio_triggered_buffer_predisable(indio_dev);
+	if (ret)
+		return ret;
+
+	mutex_lock(&data->lock);
+	ret = hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static const struct iio_buffer_setup_ops hdc_buffer_setup_ops = {
+	.postenable  = hdc100x_buffer_postenable,
+	.predisable  = hdc100x_buffer_predisable,
+};
+
+static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct hdc100x_data *data = iio_priv(indio_dev);
+	struct i2c_client *client = data->client;
+	int delay = data->adc_int_us[0] + data->adc_int_us[1];
+	int ret;
+	s16 buf[8];  /* 2x s16 + padding + 8 byte timestamp */
+
+	/* dual read starts at temp register */
+	mutex_lock(&data->lock);
+	ret = i2c_smbus_write_byte(client, HDC100X_REG_TEMP);
+	if (ret < 0) {
+		dev_err(&client->dev, "cannot start measurement\n");
+		goto err;
+	}
+	usleep_range(delay, delay + 1000);
+
+	ret = i2c_master_recv(client, (u8 *)buf, 4);
+	if (ret < 0) {
+		dev_err(&client->dev, "cannot read sensor data\n");
+		goto err;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+					   iio_get_time_ns(indio_dev));
+err:
+	mutex_unlock(&data->lock);
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
 static const struct iio_info hdc100x_info = {
 	.read_raw = hdc100x_read_raw,
 	.write_raw = hdc100x_write_raw,
@@ -258,6 +359,7 @@ static int hdc100x_probe(struct i2c_clie
 {
 	struct iio_dev *indio_dev;
 	struct hdc100x_data *data;
+	int ret;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA |
 				     I2C_FUNC_SMBUS_BYTE | I2C_FUNC_I2C))
@@ -279,12 +381,35 @@ static int hdc100x_probe(struct i2c_clie
 
 	indio_dev->channels = hdc100x_channels;
 	indio_dev->num_channels = ARRAY_SIZE(hdc100x_channels);
+	indio_dev->available_scan_masks = hdc100x_scan_masks;
 
 	/* be sure we are in a known state */
 	hdc100x_set_it_time(data, 0, hdc100x_int_time[0][0]);
 	hdc100x_set_it_time(data, 1, hdc100x_int_time[1][0]);
+	hdc100x_update_config(data, HDC100X_REG_CONFIG_ACQ_MODE, 0);
 
-	return devm_iio_device_register(&client->dev, indio_dev);
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 hdc100x_trigger_handler,
+					 &hdc_buffer_setup_ops);
+	if (ret < 0) {
+		dev_err(&client->dev, "iio triggered buffer setup failed\n");
+		return ret;
+	}
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		iio_triggered_buffer_cleanup(indio_dev);
+
+	return ret;
+}
+
+static int hdc100x_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return 0;
 }
 
 static const struct i2c_device_id hdc100x_id[] = {
@@ -298,6 +423,7 @@ static struct i2c_driver hdc100x_driver
 		.name	= "hdc100x",
 	},
 	.probe = hdc100x_probe,
+	.remove = hdc100x_remove,
 	.id_table = hdc100x_id,
 };
 module_i2c_driver(hdc100x_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/hts221_buffer.c linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_buffer.c
--- linux-libre-4.9-gnu/drivers/iio/humidity/hts221_buffer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_buffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,168 @@
+/*
+ * STMicroelectronics hts221 sensor driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/events.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/buffer.h>
+
+#include "hts221.h"
+
+#define HTS221_REG_STATUS_ADDR		0x27
+#define HTS221_RH_DRDY_MASK		BIT(1)
+#define HTS221_TEMP_DRDY_MASK		BIT(0)
+
+static int hts221_trig_set_state(struct iio_trigger *trig, bool state)
+{
+	struct iio_dev *iio_dev = iio_trigger_get_drvdata(trig);
+	struct hts221_hw *hw = iio_priv(iio_dev);
+
+	return hts221_config_drdy(hw, state);
+}
+
+static const struct iio_trigger_ops hts221_trigger_ops = {
+	.owner = THIS_MODULE,
+	.set_trigger_state = hts221_trig_set_state,
+};
+
+static irqreturn_t hts221_trigger_handler_thread(int irq, void *private)
+{
+	struct hts221_hw *hw = (struct hts221_hw *)private;
+	u8 status;
+	int err;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_STATUS_ADDR, sizeof(status),
+			   &status);
+	if (err < 0)
+		return IRQ_HANDLED;
+
+	/* 
+	 * H_DA bit (humidity data available) is routed to DRDY line.
+	 * Humidity sample is computed after temperature one.
+	 * Here we can assume data channels are both available if H_DA bit
+	 * is set in status register
+	 */
+	if (!(status & HTS221_RH_DRDY_MASK))
+		return IRQ_NONE;
+
+	iio_trigger_poll_chained(hw->trig);
+
+	return IRQ_HANDLED;
+}
+
+int hts221_allocate_trigger(struct hts221_hw *hw)
+{
+	struct iio_dev *iio_dev = iio_priv_to_dev(hw);
+	unsigned long irq_type;
+	int err;
+
+	irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
+
+	switch (irq_type) {
+	case IRQF_TRIGGER_HIGH:
+	case IRQF_TRIGGER_RISING:
+		break;
+	default:
+		dev_info(hw->dev,
+			 "mode %lx unsupported, using IRQF_TRIGGER_RISING\n",
+			 irq_type);
+		irq_type = IRQF_TRIGGER_RISING;
+		break;
+	}
+
+	err = devm_request_threaded_irq(hw->dev, hw->irq, NULL,
+					hts221_trigger_handler_thread,
+					irq_type | IRQF_ONESHOT,
+					hw->name, hw);
+	if (err) {
+		dev_err(hw->dev, "failed to request trigger irq %d\n",
+			hw->irq);
+		return err;
+	}
+
+	hw->trig = devm_iio_trigger_alloc(hw->dev, "%s-trigger",
+					  iio_dev->name);
+	if (!hw->trig)
+		return -ENOMEM;
+
+	iio_trigger_set_drvdata(hw->trig, iio_dev);
+	hw->trig->ops = &hts221_trigger_ops;
+	hw->trig->dev.parent = hw->dev;
+	iio_dev->trig = iio_trigger_get(hw->trig);
+
+	return devm_iio_trigger_register(hw->dev, hw->trig);
+}
+
+static int hts221_buffer_preenable(struct iio_dev *iio_dev)
+{
+	return hts221_power_on(iio_priv(iio_dev));
+}
+
+static int hts221_buffer_postdisable(struct iio_dev *iio_dev)
+{
+	return hts221_power_off(iio_priv(iio_dev));
+}
+
+static const struct iio_buffer_setup_ops hts221_buffer_ops = {
+	.preenable = hts221_buffer_preenable,
+	.postenable = iio_triggered_buffer_postenable,
+	.predisable = iio_triggered_buffer_predisable,
+	.postdisable = hts221_buffer_postdisable,
+};
+
+static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
+{
+	u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)];
+	struct iio_poll_func *pf = p;
+	struct iio_dev *iio_dev = pf->indio_dev;
+	struct hts221_hw *hw = iio_priv(iio_dev);
+	struct iio_chan_spec const *ch;
+	int err;
+
+	/* humidity data */
+	ch = &iio_dev->channels[HTS221_SENSOR_H];
+	err = hw->tf->read(hw->dev, ch->address, HTS221_DATA_SIZE,
+			   buffer);
+	if (err < 0)
+		goto out;
+
+	/* temperature data */
+	ch = &iio_dev->channels[HTS221_SENSOR_T];
+	err = hw->tf->read(hw->dev, ch->address, HTS221_DATA_SIZE,
+			   buffer + HTS221_DATA_SIZE);
+	if (err < 0)
+		goto out;
+
+	iio_push_to_buffers_with_timestamp(iio_dev, buffer,
+					   iio_get_time_ns(iio_dev));
+
+out:
+	iio_trigger_notify_done(hw->trig);
+
+	return IRQ_HANDLED;
+}
+
+int hts221_allocate_buffers(struct hts221_hw *hw)
+{
+	return devm_iio_triggered_buffer_setup(hw->dev, iio_priv_to_dev(hw),
+					NULL, hts221_buffer_handler_thread,
+					&hts221_buffer_ops);
+}
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics hts221 buffer driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/hts221_core.c linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_core.c
--- linux-libre-4.9-gnu/drivers/iio/humidity/hts221_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,687 @@
+/*
+ * STMicroelectronics hts221 sensor driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/iio/sysfs.h>
+#include <linux/delay.h>
+#include <asm/unaligned.h>
+
+#include "hts221.h"
+
+#define HTS221_REG_WHOAMI_ADDR		0x0f
+#define HTS221_REG_WHOAMI_VAL		0xbc
+
+#define HTS221_REG_CNTRL1_ADDR		0x20
+#define HTS221_REG_CNTRL2_ADDR		0x21
+#define HTS221_REG_CNTRL3_ADDR		0x22
+
+#define HTS221_REG_AVG_ADDR		0x10
+#define HTS221_REG_H_OUT_L		0x28
+#define HTS221_REG_T_OUT_L		0x2a
+
+#define HTS221_HUMIDITY_AVG_MASK	0x07
+#define HTS221_TEMP_AVG_MASK		0x38
+
+#define HTS221_ODR_MASK			0x87
+#define HTS221_BDU_MASK			BIT(2)
+
+#define HTS221_DRDY_MASK		BIT(2)
+
+#define HTS221_ENABLE_SENSOR		BIT(7)
+
+#define HTS221_HUMIDITY_AVG_4		0x00 /* 0.4 %RH */
+#define HTS221_HUMIDITY_AVG_8		0x01 /* 0.3 %RH */
+#define HTS221_HUMIDITY_AVG_16		0x02 /* 0.2 %RH */
+#define HTS221_HUMIDITY_AVG_32		0x03 /* 0.15 %RH */
+#define HTS221_HUMIDITY_AVG_64		0x04 /* 0.1 %RH */
+#define HTS221_HUMIDITY_AVG_128		0x05 /* 0.07 %RH */
+#define HTS221_HUMIDITY_AVG_256		0x06 /* 0.05 %RH */
+#define HTS221_HUMIDITY_AVG_512		0x07 /* 0.03 %RH */
+
+#define HTS221_TEMP_AVG_2		0x00 /* 0.08 degC */
+#define HTS221_TEMP_AVG_4		0x08 /* 0.05 degC */
+#define HTS221_TEMP_AVG_8		0x10 /* 0.04 degC */
+#define HTS221_TEMP_AVG_16		0x18 /* 0.03 degC */
+#define HTS221_TEMP_AVG_32		0x20 /* 0.02 degC */
+#define HTS221_TEMP_AVG_64		0x28 /* 0.015 degC */
+#define HTS221_TEMP_AVG_128		0x30 /* 0.01 degC */
+#define HTS221_TEMP_AVG_256		0x38 /* 0.007 degC */
+
+/* calibration registers */
+#define HTS221_REG_0RH_CAL_X_H		0x36
+#define HTS221_REG_1RH_CAL_X_H		0x3a
+#define HTS221_REG_0RH_CAL_Y_H		0x30
+#define HTS221_REG_1RH_CAL_Y_H		0x31
+#define HTS221_REG_0T_CAL_X_L		0x3c
+#define HTS221_REG_1T_CAL_X_L		0x3e
+#define HTS221_REG_0T_CAL_Y_H		0x32
+#define HTS221_REG_1T_CAL_Y_H		0x33
+#define HTS221_REG_T1_T0_CAL_Y_H	0x35
+
+struct hts221_odr {
+	u8 hz;
+	u8 val;
+};
+
+struct hts221_avg {
+	u8 addr;
+	u8 mask;
+	struct hts221_avg_avl avg_avl[HTS221_AVG_DEPTH];
+};
+
+static const struct hts221_odr hts221_odr_table[] = {
+	{  1, 0x01 },	/* 1Hz */
+	{  7, 0x02 },	/* 7Hz */
+	{ 13, 0x03 },	/* 12.5Hz */
+};
+
+static const struct hts221_avg hts221_avg_list[] = {
+	{
+		.addr = HTS221_REG_AVG_ADDR,
+		.mask = HTS221_HUMIDITY_AVG_MASK,
+		.avg_avl = {
+			{ 4, HTS221_HUMIDITY_AVG_4 },
+			{ 8, HTS221_HUMIDITY_AVG_8 },
+			{ 16, HTS221_HUMIDITY_AVG_16 },
+			{ 32, HTS221_HUMIDITY_AVG_32 },
+			{ 64, HTS221_HUMIDITY_AVG_64 },
+			{ 128, HTS221_HUMIDITY_AVG_128 },
+			{ 256, HTS221_HUMIDITY_AVG_256 },
+			{ 512, HTS221_HUMIDITY_AVG_512 },
+		},
+	},
+	{
+		.addr = HTS221_REG_AVG_ADDR,
+		.mask = HTS221_TEMP_AVG_MASK,
+		.avg_avl = {
+			{ 2, HTS221_TEMP_AVG_2 },
+			{ 4, HTS221_TEMP_AVG_4 },
+			{ 8, HTS221_TEMP_AVG_8 },
+			{ 16, HTS221_TEMP_AVG_16 },
+			{ 32, HTS221_TEMP_AVG_32 },
+			{ 64, HTS221_TEMP_AVG_64 },
+			{ 128, HTS221_TEMP_AVG_128 },
+			{ 256, HTS221_TEMP_AVG_256 },
+		},
+	},
+};
+
+static const struct iio_chan_spec hts221_channels[] = {
+	{
+		.type = IIO_HUMIDITYRELATIVE,
+		.address = HTS221_REG_H_OUT_L,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_OFFSET) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_LE,
+		},
+	},
+	{
+		.type = IIO_TEMP,
+		.address = HTS221_REG_T_OUT_L,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_OFFSET) |
+				      BIT(IIO_CHAN_INFO_SCALE) |
+				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+		.scan_index = 1,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 16,
+			.storagebits = 16,
+			.endianness = IIO_LE,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(2),
+};
+
+static int hts221_write_with_mask(struct hts221_hw *hw, u8 addr, u8 mask,
+				  u8 val)
+{
+	u8 data;
+	int err;
+
+	mutex_lock(&hw->lock);
+
+	err = hw->tf->read(hw->dev, addr, sizeof(data), &data);
+	if (err < 0) {
+		dev_err(hw->dev, "failed to read %02x register\n", addr);
+		goto unlock;
+	}
+
+	data = (data & ~mask) | (val & mask);
+
+	err = hw->tf->write(hw->dev, addr, sizeof(data), &data);
+	if (err < 0)
+		dev_err(hw->dev, "failed to write %02x register\n", addr);
+
+unlock:
+	mutex_unlock(&hw->lock);
+
+	return err;
+}
+
+static int hts221_check_whoami(struct hts221_hw *hw)
+{
+	u8 data;
+	int err;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_WHOAMI_ADDR, sizeof(data),
+			   &data);
+	if (err < 0) {
+		dev_err(hw->dev, "failed to read whoami register\n");
+		return err;
+	}
+
+	if (data != HTS221_REG_WHOAMI_VAL) {
+		dev_err(hw->dev, "wrong whoami {%02x vs %02x}\n",
+			data, HTS221_REG_WHOAMI_VAL);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+int hts221_config_drdy(struct hts221_hw *hw, bool enable)
+{
+	u8 val = enable ? BIT(2) : 0;
+	int err;
+
+	err = hts221_write_with_mask(hw, HTS221_REG_CNTRL3_ADDR,
+				     HTS221_DRDY_MASK, val);
+
+	return err < 0 ? err : 0;
+}
+
+static int hts221_update_odr(struct hts221_hw *hw, u8 odr)
+{
+	int i, err;
+	u8 val;
+
+	for (i = 0; i < ARRAY_SIZE(hts221_odr_table); i++)
+		if (hts221_odr_table[i].hz == odr)
+			break;
+
+	if (i == ARRAY_SIZE(hts221_odr_table))
+		return -EINVAL;
+
+	val = HTS221_ENABLE_SENSOR | HTS221_BDU_MASK | hts221_odr_table[i].val;
+	err = hts221_write_with_mask(hw, HTS221_REG_CNTRL1_ADDR,
+				     HTS221_ODR_MASK, val);
+	if (err < 0)
+		return err;
+
+	hw->odr = odr;
+
+	return 0;
+}
+
+static int hts221_update_avg(struct hts221_hw *hw,
+			     enum hts221_sensor_type type,
+			     u16 val)
+{
+	int i, err;
+	const struct hts221_avg *avg = &hts221_avg_list[type];
+
+	for (i = 0; i < HTS221_AVG_DEPTH; i++)
+		if (avg->avg_avl[i].avg == val)
+			break;
+
+	if (i == HTS221_AVG_DEPTH)
+		return -EINVAL;
+
+	err = hts221_write_with_mask(hw, avg->addr, avg->mask,
+				     avg->avg_avl[i].val);
+	if (err < 0)
+		return err;
+
+	hw->sensors[type].cur_avg_idx = i;
+
+	return 0;
+}
+
+static ssize_t hts221_sysfs_sampling_freq(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	int i;
+	ssize_t len = 0;
+
+	for (i = 0; i < ARRAY_SIZE(hts221_odr_table); i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
+				 hts221_odr_table[i].hz);
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static ssize_t
+hts221_sysfs_rh_oversampling_avail(struct device *dev,
+				   struct device_attribute *attr,
+				   char *buf)
+{
+	const struct hts221_avg *avg = &hts221_avg_list[HTS221_SENSOR_H];
+	ssize_t len = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
+				 avg->avg_avl[i].avg);
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static ssize_t
+hts221_sysfs_temp_oversampling_avail(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	const struct hts221_avg *avg = &hts221_avg_list[HTS221_SENSOR_T];
+	ssize_t len = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(avg->avg_avl); i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ",
+				 avg->avg_avl[i].avg);
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+int hts221_power_on(struct hts221_hw *hw)
+{
+	return hts221_update_odr(hw, hw->odr);
+}
+
+int hts221_power_off(struct hts221_hw *hw)
+{
+	u8 data[] = {0x00, 0x00};
+
+	return hw->tf->write(hw->dev, HTS221_REG_CNTRL1_ADDR, sizeof(data),
+			     data);
+}
+
+static int hts221_parse_temp_caldata(struct hts221_hw *hw)
+{
+	int err, *slope, *b_gen;
+	s16 cal_x0, cal_x1, cal_y0, cal_y1;
+	u8 cal0, cal1;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_0T_CAL_Y_H,
+			   sizeof(cal0), &cal0);
+	if (err < 0)
+		return err;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_T1_T0_CAL_Y_H,
+			   sizeof(cal1), &cal1);
+	if (err < 0)
+		return err;
+	cal_y0 = (le16_to_cpu(cal1 & 0x3) << 8) | cal0;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_1T_CAL_Y_H,
+			   sizeof(cal0), &cal0);
+	if (err < 0)
+		return err;
+	cal_y1 = (((cal1 & 0xc) >> 2) << 8) | cal0;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_0T_CAL_X_L, sizeof(cal_x0),
+			   (u8 *)&cal_x0);
+	if (err < 0)
+		return err;
+	cal_x0 = le16_to_cpu(cal_x0);
+
+	err = hw->tf->read(hw->dev, HTS221_REG_1T_CAL_X_L, sizeof(cal_x1),
+			   (u8 *)&cal_x1);
+	if (err < 0)
+		return err;
+	cal_x1 = le16_to_cpu(cal_x1);
+
+	slope = &hw->sensors[HTS221_SENSOR_T].slope;
+	b_gen = &hw->sensors[HTS221_SENSOR_T].b_gen;
+
+	*slope = ((cal_y1 - cal_y0) * 8000) / (cal_x1 - cal_x0);
+	*b_gen = (((s32)cal_x1 * cal_y0 - (s32)cal_x0 * cal_y1) * 1000) /
+		 (cal_x1 - cal_x0);
+	*b_gen *= 8;
+
+	return 0;
+}
+
+static int hts221_parse_rh_caldata(struct hts221_hw *hw)
+{
+	int err, *slope, *b_gen;
+	s16 cal_x0, cal_x1, cal_y0, cal_y1;
+	u8 data;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_0RH_CAL_Y_H, sizeof(data),
+			   &data);
+	if (err < 0)
+		return err;
+	cal_y0 = data;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_1RH_CAL_Y_H, sizeof(data),
+			   &data);
+	if (err < 0)
+		return err;
+	cal_y1 = data;
+
+	err = hw->tf->read(hw->dev, HTS221_REG_0RH_CAL_X_H, sizeof(cal_x0),
+			   (u8 *)&cal_x0);
+	if (err < 0)
+		return err;
+	cal_x0 = le16_to_cpu(cal_x0);
+
+	err = hw->tf->read(hw->dev, HTS221_REG_1RH_CAL_X_H, sizeof(cal_x1),
+			   (u8 *)&cal_x1);
+	if (err < 0)
+		return err;
+	cal_x1 = le16_to_cpu(cal_x1);
+
+	slope = &hw->sensors[HTS221_SENSOR_H].slope;
+	b_gen = &hw->sensors[HTS221_SENSOR_H].b_gen;
+
+	*slope = ((cal_y1 - cal_y0) * 8000) / (cal_x1 - cal_x0);
+	*b_gen = (((s32)cal_x1 * cal_y0 - (s32)cal_x0 * cal_y1) * 1000) /
+		 (cal_x1 - cal_x0);
+	*b_gen *= 8;
+
+	return 0;
+}
+
+static int hts221_get_sensor_scale(struct hts221_hw *hw,
+				   enum iio_chan_type ch_type,
+				   int *val, int *val2)
+{
+	s64 tmp;
+	s32 rem, div, data;
+
+	switch (ch_type) {
+	case IIO_HUMIDITYRELATIVE:
+		data = hw->sensors[HTS221_SENSOR_H].slope;
+		div = (1 << 4) * 1000;
+		break;
+	case IIO_TEMP:
+		data = hw->sensors[HTS221_SENSOR_T].slope;
+		div = (1 << 6) * 1000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	tmp = div_s64(data * 1000000000LL, div);
+	tmp = div_s64_rem(tmp, 1000000000LL, &rem);
+
+	*val = tmp;
+	*val2 = rem;
+
+	return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int hts221_get_sensor_offset(struct hts221_hw *hw,
+				    enum iio_chan_type ch_type,
+				    int *val, int *val2)
+{
+	s64 tmp;
+	s32 rem, div, data;
+
+	switch (ch_type) {
+	case IIO_HUMIDITYRELATIVE:
+		data = hw->sensors[HTS221_SENSOR_H].b_gen;
+		div = hw->sensors[HTS221_SENSOR_H].slope;
+		break;
+	case IIO_TEMP:
+		data = hw->sensors[HTS221_SENSOR_T].b_gen;
+		div = hw->sensors[HTS221_SENSOR_T].slope;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	tmp = div_s64(data * 1000000000LL, div);
+	tmp = div_s64_rem(tmp, 1000000000LL, &rem);
+
+	*val = tmp;
+	*val2 = rem;
+
+	return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int hts221_read_oneshot(struct hts221_hw *hw, u8 addr, int *val)
+{
+	u8 data[HTS221_DATA_SIZE];
+	int err;
+
+	err = hts221_power_on(hw);
+	if (err < 0)
+		return err;
+
+	msleep(50);
+
+	err = hw->tf->read(hw->dev, addr, sizeof(data), data);
+	if (err < 0)
+		return err;
+
+	hts221_power_off(hw);
+
+	*val = (s16)get_unaligned_le16(data);
+
+	return IIO_VAL_INT;
+}
+
+static int hts221_read_raw(struct iio_dev *iio_dev,
+			   struct iio_chan_spec const *ch,
+			   int *val, int *val2, long mask)
+{
+	struct hts221_hw *hw = iio_priv(iio_dev);
+	int ret;
+
+	ret = iio_device_claim_direct_mode(iio_dev);
+	if (ret)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = hts221_read_oneshot(hw, ch->address, val);
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		ret = hts221_get_sensor_scale(hw, ch->type, val, val2);
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		ret = hts221_get_sensor_offset(hw, ch->type, val, val2);
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = hw->odr;
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO: {
+		u8 idx;
+		const struct hts221_avg *avg;
+
+		switch (ch->type) {
+		case IIO_HUMIDITYRELATIVE:
+			avg = &hts221_avg_list[HTS221_SENSOR_H];
+			idx = hw->sensors[HTS221_SENSOR_H].cur_avg_idx;
+			*val = avg->avg_avl[idx].avg;
+			ret = IIO_VAL_INT;
+			break;
+		case IIO_TEMP:
+			avg = &hts221_avg_list[HTS221_SENSOR_T];
+			idx = hw->sensors[HTS221_SENSOR_T].cur_avg_idx;
+			*val = avg->avg_avl[idx].avg;
+			ret = IIO_VAL_INT;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	iio_device_release_direct_mode(iio_dev);
+
+	return ret;
+}
+
+static int hts221_write_raw(struct iio_dev *iio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	struct hts221_hw *hw = iio_priv(iio_dev);
+	int ret;
+
+	ret = iio_device_claim_direct_mode(iio_dev);
+	if (ret)
+		return ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = hts221_update_odr(hw, val);
+		break;
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		switch (chan->type) {
+		case IIO_HUMIDITYRELATIVE:
+			ret = hts221_update_avg(hw, HTS221_SENSOR_H, val);
+			break;
+		case IIO_TEMP:
+			ret = hts221_update_avg(hw, HTS221_SENSOR_T, val);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	iio_device_release_direct_mode(iio_dev);
+
+	return ret;
+}
+
+static int hts221_validate_trigger(struct iio_dev *iio_dev,
+				   struct iio_trigger *trig)
+{
+	struct hts221_hw *hw = iio_priv(iio_dev);
+
+	return hw->trig == trig ? 0 : -EINVAL;
+}
+
+static IIO_DEVICE_ATTR(in_humidity_oversampling_ratio_available, S_IRUGO,
+		       hts221_sysfs_rh_oversampling_avail, NULL, 0);
+static IIO_DEVICE_ATTR(in_temp_oversampling_ratio_available, S_IRUGO,
+		       hts221_sysfs_temp_oversampling_avail, NULL, 0);
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hts221_sysfs_sampling_freq);
+
+static struct attribute *hts221_attributes[] = {
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	&iio_dev_attr_in_humidity_oversampling_ratio_available.dev_attr.attr,
+	&iio_dev_attr_in_temp_oversampling_ratio_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group hts221_attribute_group = {
+	.attrs = hts221_attributes,
+};
+
+static const struct iio_info hts221_info = {
+	.driver_module = THIS_MODULE,
+	.attrs = &hts221_attribute_group,
+	.read_raw = hts221_read_raw,
+	.write_raw = hts221_write_raw,
+	.validate_trigger = hts221_validate_trigger,
+};
+
+static const unsigned long hts221_scan_masks[] = {0x3, 0x0};
+
+int hts221_probe(struct iio_dev *iio_dev)
+{
+	struct hts221_hw *hw = iio_priv(iio_dev);
+	int err;
+	u8 data;
+
+	mutex_init(&hw->lock);
+
+	err = hts221_check_whoami(hw);
+	if (err < 0)
+		return err;
+
+	hw->odr = hts221_odr_table[0].hz;
+
+	iio_dev->modes = INDIO_DIRECT_MODE;
+	iio_dev->dev.parent = hw->dev;
+	iio_dev->available_scan_masks = hts221_scan_masks;
+	iio_dev->channels = hts221_channels;
+	iio_dev->num_channels = ARRAY_SIZE(hts221_channels);
+	iio_dev->name = HTS221_DEV_NAME;
+	iio_dev->info = &hts221_info;
+
+	/* configure humidity sensor */
+	err = hts221_parse_rh_caldata(hw);
+	if (err < 0) {
+		dev_err(hw->dev, "failed to get rh calibration data\n");
+		return err;
+	}
+
+	data = hts221_avg_list[HTS221_SENSOR_H].avg_avl[3].avg;
+	err = hts221_update_avg(hw, HTS221_SENSOR_H, data);
+	if (err < 0) {
+		dev_err(hw->dev, "failed to set rh oversampling ratio\n");
+		return err;
+	}
+
+	/* configure temperature sensor */
+	err = hts221_parse_temp_caldata(hw);
+	if (err < 0) {
+		dev_err(hw->dev,
+			"failed to get temperature calibration data\n");
+		return err;
+	}
+
+	data = hts221_avg_list[HTS221_SENSOR_T].avg_avl[3].avg;
+	err = hts221_update_avg(hw, HTS221_SENSOR_T, data);
+	if (err < 0) {
+		dev_err(hw->dev,
+			"failed to set temperature oversampling ratio\n");
+		return err;
+	}
+
+	if (hw->irq > 0) {
+		err = hts221_allocate_buffers(hw);
+		if (err < 0)
+			return err;
+
+		err = hts221_allocate_trigger(hw);
+		if (err)
+			return err;
+	}
+
+	return devm_iio_device_register(hw->dev, iio_dev);
+}
+EXPORT_SYMBOL(hts221_probe);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics hts221 sensor driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/hts221.h linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221.h
--- linux-libre-4.9-gnu/drivers/iio/humidity/hts221.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,73 @@
+/*
+ * STMicroelectronics hts221 sensor driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef HTS221_H
+#define HTS221_H
+
+#define HTS221_DEV_NAME		"hts221"
+
+#include <linux/iio/iio.h>
+
+#define HTS221_RX_MAX_LENGTH	8
+#define HTS221_TX_MAX_LENGTH	8
+
+#define HTS221_DATA_SIZE	2
+
+struct hts221_transfer_buffer {
+	u8 rx_buf[HTS221_RX_MAX_LENGTH];
+	u8 tx_buf[HTS221_TX_MAX_LENGTH] ____cacheline_aligned;
+};
+
+struct hts221_transfer_function {
+	int (*read)(struct device *dev, u8 addr, int len, u8 *data);
+	int (*write)(struct device *dev, u8 addr, int len, u8 *data);
+};
+
+#define HTS221_AVG_DEPTH	8
+struct hts221_avg_avl {
+	u16 avg;
+	u8 val;
+};
+
+enum hts221_sensor_type {
+	HTS221_SENSOR_H,
+	HTS221_SENSOR_T,
+	HTS221_SENSOR_MAX,
+};
+
+struct hts221_sensor {
+	u8 cur_avg_idx;
+	int slope, b_gen;
+};
+
+struct hts221_hw {
+	const char *name;
+	struct device *dev;
+
+	struct mutex lock;
+	struct iio_trigger *trig;
+	int irq;
+
+	struct hts221_sensor sensors[HTS221_SENSOR_MAX];
+
+	u8 odr;
+
+	const struct hts221_transfer_function *tf;
+	struct hts221_transfer_buffer tb;
+};
+
+int hts221_config_drdy(struct hts221_hw *hw, bool enable);
+int hts221_probe(struct iio_dev *iio_dev);
+int hts221_power_on(struct hts221_hw *hw);
+int hts221_power_off(struct hts221_hw *hw);
+int hts221_allocate_buffers(struct hts221_hw *hw);
+int hts221_allocate_trigger(struct hts221_hw *hw);
+
+#endif /* HTS221_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/hts221_i2c.c linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_i2c.c
--- linux-libre-4.9-gnu/drivers/iio/humidity/hts221_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,110 @@
+/*
+ * STMicroelectronics hts221 i2c driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include "hts221.h"
+
+#define I2C_AUTO_INCREMENT	0x80
+
+static int hts221_i2c_read(struct device *dev, u8 addr, int len, u8 *data)
+{
+	struct i2c_msg msg[2];
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (len > 1)
+		addr |= I2C_AUTO_INCREMENT;
+
+	msg[0].addr = client->addr;
+	msg[0].flags = client->flags;
+	msg[0].len = 1;
+	msg[0].buf = &addr;
+
+	msg[1].addr = client->addr;
+	msg[1].flags = client->flags | I2C_M_RD;
+	msg[1].len = len;
+	msg[1].buf = data;
+
+	return i2c_transfer(client->adapter, msg, 2);
+}
+
+static int hts221_i2c_write(struct device *dev, u8 addr, int len, u8 *data)
+{
+	u8 send[len + 1];
+	struct i2c_msg msg;
+	struct i2c_client *client = to_i2c_client(dev);
+
+	if (len > 1)
+		addr |= I2C_AUTO_INCREMENT;
+
+	send[0] = addr;
+	memcpy(&send[1], data, len * sizeof(u8));
+
+	msg.addr = client->addr;
+	msg.flags = client->flags;
+	msg.len = len + 1;
+	msg.buf = send;
+
+	return i2c_transfer(client->adapter, &msg, 1);
+}
+
+static const struct hts221_transfer_function hts221_transfer_fn = {
+	.read = hts221_i2c_read,
+	.write = hts221_i2c_write,
+};
+
+static int hts221_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct hts221_hw *hw;
+	struct iio_dev *iio_dev;
+
+	iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*hw));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, iio_dev);
+
+	hw = iio_priv(iio_dev);
+	hw->name = client->name;
+	hw->dev = &client->dev;
+	hw->irq = client->irq;
+	hw->tf = &hts221_transfer_fn;
+
+	return hts221_probe(iio_dev);
+}
+
+static const struct of_device_id hts221_i2c_of_match[] = {
+	{ .compatible = "st,hts221", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, hts221_i2c_of_match);
+
+static const struct i2c_device_id hts221_i2c_id_table[] = {
+	{ HTS221_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, hts221_i2c_id_table);
+
+static struct i2c_driver hts221_driver = {
+	.driver = {
+		.name = "hts221_i2c",
+		.of_match_table = of_match_ptr(hts221_i2c_of_match),
+	},
+	.probe = hts221_i2c_probe,
+	.id_table = hts221_i2c_id_table,
+};
+module_i2c_driver(hts221_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics hts221 i2c driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/hts221_spi.c linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_spi.c
--- linux-libre-4.9-gnu/drivers/iio/humidity/hts221_spi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/hts221_spi.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,125 @@
+/*
+ * STMicroelectronics hts221 spi driver
+ *
+ * Copyright 2016 STMicroelectronics Inc.
+ *
+ * Lorenzo Bianconi <lorenzo.bianconi@st.com>
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/slab.h>
+#include "hts221.h"
+
+#define SENSORS_SPI_READ	0x80
+#define SPI_AUTO_INCREMENT	0x40
+
+static int hts221_spi_read(struct device *dev, u8 addr, int len, u8 *data)
+{
+	int err;
+	struct spi_device *spi = to_spi_device(dev);
+	struct iio_dev *iio_dev = spi_get_drvdata(spi);
+	struct hts221_hw *hw = iio_priv(iio_dev);
+
+	struct spi_transfer xfers[] = {
+		{
+			.tx_buf = hw->tb.tx_buf,
+			.bits_per_word = 8,
+			.len = 1,
+		},
+		{
+			.rx_buf = hw->tb.rx_buf,
+			.bits_per_word = 8,
+			.len = len,
+		}
+	};
+
+	if (len > 1)
+		addr |= SPI_AUTO_INCREMENT;
+	hw->tb.tx_buf[0] = addr | SENSORS_SPI_READ;
+
+	err = spi_sync_transfer(spi, xfers,  ARRAY_SIZE(xfers));
+	if (err < 0)
+		return err;
+
+	memcpy(data, hw->tb.rx_buf, len * sizeof(u8));
+
+	return len;
+}
+
+static int hts221_spi_write(struct device *dev, u8 addr, int len, u8 *data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct iio_dev *iio_dev = spi_get_drvdata(spi);
+	struct hts221_hw *hw = iio_priv(iio_dev);
+
+	struct spi_transfer xfers = {
+		.tx_buf = hw->tb.tx_buf,
+		.bits_per_word = 8,
+		.len = len + 1,
+	};
+
+	if (len >= HTS221_TX_MAX_LENGTH)
+		return -ENOMEM;
+
+	if (len > 1)
+		addr |= SPI_AUTO_INCREMENT;
+	hw->tb.tx_buf[0] = addr;
+	memcpy(&hw->tb.tx_buf[1], data, len);
+
+	return spi_sync_transfer(spi, &xfers, 1);
+}
+
+static const struct hts221_transfer_function hts221_transfer_fn = {
+	.read = hts221_spi_read,
+	.write = hts221_spi_write,
+};
+
+static int hts221_spi_probe(struct spi_device *spi)
+{
+	struct hts221_hw *hw;
+	struct iio_dev *iio_dev;
+
+	iio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*hw));
+	if (!iio_dev)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, iio_dev);
+
+	hw = iio_priv(iio_dev);
+	hw->name = spi->modalias;
+	hw->dev = &spi->dev;
+	hw->irq = spi->irq;
+	hw->tf = &hts221_transfer_fn;
+
+	return hts221_probe(iio_dev);
+}
+
+static const struct of_device_id hts221_spi_of_match[] = {
+	{ .compatible = "st,hts221", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, hts221_spi_of_match);
+
+static const struct spi_device_id hts221_spi_id_table[] = {
+	{ HTS221_DEV_NAME },
+	{},
+};
+MODULE_DEVICE_TABLE(spi, hts221_spi_id_table);
+
+static struct spi_driver hts221_driver = {
+	.driver = {
+		.name = "hts221_spi",
+		.of_match_table = of_match_ptr(hts221_spi_of_match),
+	},
+	.probe = hts221_spi_probe,
+	.id_table = hts221_spi_id_table,
+};
+module_spi_driver(hts221_driver);
+
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics hts221 spi driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/humidity/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/humidity/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,8 @@ config DHT11
 config HDC100X
 	tristate "TI HDC100x relative humidity and temperature sensor"
 	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say yes here to build support for the Texas Instruments
 	  HDC1000 and HDC1008 relative humidity and temperature sensors.
@@ -34,6 +36,28 @@ config HDC100X
 	  To compile this driver as a module, choose M here: the module
 	  will be called hdc100x.
 
+config HTS221
+	tristate "STMicroelectronics HTS221 sensor Driver"
+	depends on (I2C || SPI)
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	select HTS221_I2C if (I2C)
+	select HTS221_SPI if (SPI_MASTER)
+	help
+	  Say yes here to build support for STMicroelectronics HTS221
+	  temperature-humidity sensor
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called hts221.
+
+config HTS221_I2C
+	tristate
+	depends on HTS221
+
+config HTS221_SPI
+	tristate
+	depends on HTS221
+
 config HTU21
 	tristate "Measurement Specialties HTU21 humidity & temperature sensor"
 	depends on I2C
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/humidity/Makefile
--- linux-libre-4.9-gnu/drivers/iio/humidity/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -5,6 +5,13 @@
 obj-$(CONFIG_AM2315) += am2315.o
 obj-$(CONFIG_DHT11) += dht11.o
 obj-$(CONFIG_HDC100X) += hdc100x.o
+
+hts221-y := hts221_core.o \
+	    hts221_buffer.o
+obj-$(CONFIG_HTS221) += hts221.o
+obj-$(CONFIG_HTS221_I2C) += hts221_i2c.o
+obj-$(CONFIG_HTS221_SPI) += hts221_spi.o
+
 obj-$(CONFIG_HTU21) += htu21.o
 obj-$(CONFIG_SI7005) += si7005.o
 obj-$(CONFIG_SI7020) += si7020.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/humidity/si7020.c linux-libre-4.10-rc8-gnu/drivers/iio/humidity/si7020.c
--- linux-libre-4.9-gnu/drivers/iio/humidity/si7020.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/humidity/si7020.c	2017-02-12 16:03:20.000000000 -0500
@@ -154,8 +154,17 @@ static const struct i2c_device_id si7020
 };
 MODULE_DEVICE_TABLE(i2c, si7020_id);
 
+static const struct of_device_id si7020_dt_ids[] = {
+	{ .compatible = "silabs,si7020" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, si7020_dt_ids);
+
 static struct i2c_driver si7020_driver = {
-	.driver.name	= "si7020",
+	.driver = {
+		.name = "si7020",
+		.of_match_table = of_match_ptr(si7020_dt_ids),
+	},
 	.probe		= si7020_probe,
 	.id_table	= si7020_id,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/imu/bmi160/bmi160_core.c linux-libre-4.10-rc8-gnu/drivers/iio/imu/bmi160/bmi160_core.c
--- linux-libre-4.9-gnu/drivers/iio/imu/bmi160/bmi160_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/imu/bmi160/bmi160_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,10 +66,8 @@
 
 #define BMI160_REG_DUMMY		0x7F
 
-#define BMI160_ACCEL_PMU_MIN_USLEEP	3200
-#define BMI160_ACCEL_PMU_MAX_USLEEP	3800
-#define BMI160_GYRO_PMU_MIN_USLEEP	55000
-#define BMI160_GYRO_PMU_MAX_USLEEP	80000
+#define BMI160_ACCEL_PMU_MIN_USLEEP	3800
+#define BMI160_GYRO_PMU_MIN_USLEEP	80000
 #define BMI160_SOFTRESET_USLEEP		1000
 
 #define BMI160_CHANNEL(_type, _axis, _index) {			\
@@ -151,20 +149,9 @@ static struct bmi160_regs bmi160_regs[]
 	},
 };
 
-struct bmi160_pmu_time {
-	unsigned long min;
-	unsigned long max;
-};
-
-static struct bmi160_pmu_time bmi160_pmu_time[] = {
-	[BMI160_ACCEL] = {
-		.min = BMI160_ACCEL_PMU_MIN_USLEEP,
-		.max = BMI160_ACCEL_PMU_MAX_USLEEP
-	},
-	[BMI160_GYRO] = {
-		.min = BMI160_GYRO_PMU_MIN_USLEEP,
-		.max = BMI160_GYRO_PMU_MIN_USLEEP,
-	},
+static unsigned long bmi160_pmu_time[] = {
+	[BMI160_ACCEL] = BMI160_ACCEL_PMU_MIN_USLEEP,
+	[BMI160_GYRO] = BMI160_GYRO_PMU_MIN_USLEEP,
 };
 
 struct bmi160_scale {
@@ -289,7 +276,7 @@ int bmi160_set_mode(struct bmi160_data *
 	if (ret < 0)
 		return ret;
 
-	usleep_range(bmi160_pmu_time[t].min, bmi160_pmu_time[t].max);
+	usleep_range(bmi160_pmu_time[t], bmi160_pmu_time[t] + 1000);
 
 	return 0;
 }
@@ -398,7 +385,8 @@ static irqreturn_t bmi160_trigger_handle
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct bmi160_data *data = iio_priv(indio_dev);
-	s16 buf[16]; /* 3 sens x 3 axis x s16 + 3 x s16 pad + 4 x s16 tstamp */
+	__le16 buf[16];
+	/* 3 sens x 3 axis x __le16 + 3 x __le16 pad + 4 x __le16 tstamp */
 	int i, ret, j = 0, base = BMI160_REG_DATA_MAGN_XOUT_L;
 	__le16 sample;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c linux-libre-4.10-rc8-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
--- linux-libre-4.9-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -126,7 +126,7 @@ static int inv_mpu_probe(struct i2c_clie
 
 	st = iio_priv(dev_get_drvdata(&client->dev));
 	st->muxc = i2c_mux_alloc(client->adapter, &client->dev,
-				 1, 0, I2C_MUX_LOCKED,
+				 1, 0, I2C_MUX_LOCKED | I2C_MUX_GATE,
 				 inv_mpu6050_select_bypass,
 				 inv_mpu6050_deselect_bypass);
 	if (!st->muxc) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/industrialio-buffer.c linux-libre-4.10-rc8-gnu/drivers/iio/industrialio-buffer.c
--- linux-libre-4.9-gnu/drivers/iio/industrialio-buffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/industrialio-buffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -307,10 +307,9 @@ static int iio_scan_mask_set(struct iio_
 	const unsigned long *mask;
 	unsigned long *trialmask;
 
-	trialmask = kmalloc(sizeof(*trialmask)*
-			    BITS_TO_LONGS(indio_dev->masklength),
-			    GFP_KERNEL);
-
+	trialmask = kmalloc_array(BITS_TO_LONGS(indio_dev->masklength),
+				  sizeof(*trialmask),
+				  GFP_KERNEL);
 	if (trialmask == NULL)
 		return -ENOMEM;
 	if (!indio_dev->masklength) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/industrialio-core.c linux-libre-4.10-rc8-gnu/drivers/iio/industrialio-core.c
--- linux-libre-4.9-gnu/drivers/iio/industrialio-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/industrialio-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,6 +81,8 @@ static const char * const iio_chan_type_
 	[IIO_PH] = "ph",
 	[IIO_UVINDEX] = "uvindex",
 	[IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity",
+	[IIO_COUNT] = "count",
+	[IIO_INDEX] = "index",
 };
 
 static const char * const iio_modifier_names[] = {
@@ -575,66 +577,82 @@ int of_iio_read_mount_matrix(const struc
 #endif
 EXPORT_SYMBOL(of_iio_read_mount_matrix);
 
-/**
- * iio_format_value() - Formats a IIO value into its string representation
- * @buf:	The buffer to which the formatted value gets written
- * @type:	One of the IIO_VAL_... constants. This decides how the val
- *		and val2 parameters are formatted.
- * @size:	Number of IIO value entries contained in vals
- * @vals:	Pointer to the values, exact meaning depends on the
- *		type parameter.
- *
- * Return: 0 by default, a negative number on failure or the
- *	   total number of characters written for a type that belongs
- *	   to the IIO_VAL_... constant.
- */
-ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
+static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
+				  int size, const int *vals)
 {
 	unsigned long long tmp;
+	int tmp0, tmp1;
 	bool scale_db = false;
 
 	switch (type) {
 	case IIO_VAL_INT:
-		return sprintf(buf, "%d\n", vals[0]);
+		return snprintf(buf, len, "%d", vals[0]);
 	case IIO_VAL_INT_PLUS_MICRO_DB:
 		scale_db = true;
 	case IIO_VAL_INT_PLUS_MICRO:
 		if (vals[1] < 0)
-			return sprintf(buf, "-%d.%06u%s\n", abs(vals[0]),
-				       -vals[1], scale_db ? " dB" : "");
+			return snprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
+					-vals[1], scale_db ? " dB" : "");
 		else
-			return sprintf(buf, "%d.%06u%s\n", vals[0], vals[1],
-				scale_db ? " dB" : "");
+			return snprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
+					scale_db ? " dB" : "");
 	case IIO_VAL_INT_PLUS_NANO:
 		if (vals[1] < 0)
-			return sprintf(buf, "-%d.%09u\n", abs(vals[0]),
-				       -vals[1]);
+			return snprintf(buf, len, "-%d.%09u", abs(vals[0]),
+					-vals[1]);
 		else
-			return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
+			return snprintf(buf, len, "%d.%09u", vals[0], vals[1]);
 	case IIO_VAL_FRACTIONAL:
 		tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
-		vals[0] = (int)div_s64_rem(tmp, 1000000000, &vals[1]);
-		return sprintf(buf, "%d.%09u\n", vals[0], abs(vals[1]));
+		tmp1 = vals[1];
+		tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1);
+		return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
 	case IIO_VAL_FRACTIONAL_LOG2:
 		tmp = (s64)vals[0] * 1000000000LL >> vals[1];
-		vals[1] = do_div(tmp, 1000000000LL);
-		vals[0] = tmp;
-		return sprintf(buf, "%d.%09u\n", vals[0], vals[1]);
+		tmp1 = do_div(tmp, 1000000000LL);
+		tmp0 = tmp;
+		return snprintf(buf, len, "%d.%09u", tmp0, tmp1);
 	case IIO_VAL_INT_MULTIPLE:
 	{
 		int i;
-		int len = 0;
+		int l = 0;
 
-		for (i = 0; i < size; ++i)
-			len += snprintf(&buf[len], PAGE_SIZE - len, "%d ",
-								vals[i]);
-		len += snprintf(&buf[len], PAGE_SIZE - len, "\n");
-		return len;
+		for (i = 0; i < size; ++i) {
+			l += snprintf(&buf[l], len - l, "%d ", vals[i]);
+			if (l >= len)
+				break;
+		}
+		return l;
 	}
 	default:
 		return 0;
 	}
 }
+
+/**
+ * iio_format_value() - Formats a IIO value into its string representation
+ * @buf:	The buffer to which the formatted value gets written
+ *		which is assumed to be big enough (i.e. PAGE_SIZE).
+ * @type:	One of the IIO_VAL_... constants. This decides how the val
+ *		and val2 parameters are formatted.
+ * @size:	Number of IIO value entries contained in vals
+ * @vals:	Pointer to the values, exact meaning depends on the
+ *		type parameter.
+ *
+ * Return: 0 by default, a negative number on failure or the
+ *	   total number of characters written for a type that belongs
+ *	   to the IIO_VAL_... constant.
+ */
+ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
+{
+	ssize_t len;
+
+	len = __iio_format_value(buf, PAGE_SIZE, type, size, vals);
+	if (len >= PAGE_SIZE - 1)
+		return -EFBIG;
+
+	return len + sprintf(buf + len, "\n");
+}
 EXPORT_SYMBOL_GPL(iio_format_value);
 
 static ssize_t iio_read_channel_info(struct device *dev,
@@ -662,6 +680,119 @@ static ssize_t iio_read_channel_info(str
 	return iio_format_value(buf, ret, val_len, vals);
 }
 
+static ssize_t iio_format_avail_list(char *buf, const int *vals,
+				     int type, int length)
+{
+	int i;
+	ssize_t len = 0;
+
+	switch (type) {
+	case IIO_VAL_INT:
+		for (i = 0; i < length; i++) {
+			len += __iio_format_value(buf + len, PAGE_SIZE - len,
+						  type, 1, &vals[i]);
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+			if (i < length - 1)
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						" ");
+			else
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						"\n");
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+		}
+		break;
+	default:
+		for (i = 0; i < length / 2; i++) {
+			len += __iio_format_value(buf + len, PAGE_SIZE - len,
+						  type, 2, &vals[i * 2]);
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+			if (i < length / 2 - 1)
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						" ");
+			else
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						"\n");
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+		}
+	}
+
+	return len;
+}
+
+static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
+{
+	int i;
+	ssize_t len;
+
+	len = snprintf(buf, PAGE_SIZE, "[");
+	switch (type) {
+	case IIO_VAL_INT:
+		for (i = 0; i < 3; i++) {
+			len += __iio_format_value(buf + len, PAGE_SIZE - len,
+						  type, 1, &vals[i]);
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+			if (i < 2)
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						" ");
+			else
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						"]\n");
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+		}
+		break;
+	default:
+		for (i = 0; i < 3; i++) {
+			len += __iio_format_value(buf + len, PAGE_SIZE - len,
+						  type, 2, &vals[i * 2]);
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+			if (i < 2)
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						" ");
+			else
+				len += snprintf(buf + len, PAGE_SIZE - len,
+						"]\n");
+			if (len >= PAGE_SIZE)
+				return -EFBIG;
+		}
+	}
+
+	return len;
+}
+
+static ssize_t iio_read_channel_info_avail(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	const int *vals;
+	int ret;
+	int length;
+	int type;
+
+	ret = indio_dev->info->read_avail(indio_dev, this_attr->c,
+					  &vals, &type, &length,
+					  this_attr->address);
+
+	if (ret < 0)
+		return ret;
+	switch (ret) {
+	case IIO_AVAIL_LIST:
+		return iio_format_avail_list(buf, vals, type, length);
+	case IIO_AVAIL_RANGE:
+		return iio_format_avail_range(buf, vals, type);
+	default:
+		return -EINVAL;
+	}
+}
+
 /**
  * iio_str_to_fixpoint() - Parse a fixed-point number from a string
  * @str: The string to parse
@@ -978,6 +1109,40 @@ static int iio_device_add_info_mask_type
 	return attrcount;
 }
 
+static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
+					       struct iio_chan_spec const *chan,
+					       enum iio_shared_by shared_by,
+					       const long *infomask)
+{
+	int i, ret, attrcount = 0;
+	char *avail_postfix;
+
+	for_each_set_bit(i, infomask, sizeof(infomask) * 8) {
+		avail_postfix = kasprintf(GFP_KERNEL,
+					  "%s_available",
+					  iio_chan_info_postfix[i]);
+		if (!avail_postfix)
+			return -ENOMEM;
+
+		ret = __iio_add_chan_devattr(avail_postfix,
+					     chan,
+					     &iio_read_channel_info_avail,
+					     NULL,
+					     i,
+					     shared_by,
+					     &indio_dev->dev,
+					     &indio_dev->channel_attr_list);
+		kfree(avail_postfix);
+		if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
+			continue;
+		else if (ret < 0)
+			return ret;
+		attrcount++;
+	}
+
+	return attrcount;
+}
+
 static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
 					struct iio_chan_spec const *chan)
 {
@@ -993,6 +1158,14 @@ static int iio_device_add_channel_sysfs(
 		return ret;
 	attrcount += ret;
 
+	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
+						  IIO_SEPARATE,
+						  &chan->
+						  info_mask_separate_available);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
+
 	ret = iio_device_add_info_mask_type(indio_dev, chan,
 					    IIO_SHARED_BY_TYPE,
 					    &chan->info_mask_shared_by_type);
@@ -1000,6 +1173,14 @@ static int iio_device_add_channel_sysfs(
 		return ret;
 	attrcount += ret;
 
+	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
+						  IIO_SHARED_BY_TYPE,
+						  &chan->
+						  info_mask_shared_by_type_available);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
+
 	ret = iio_device_add_info_mask_type(indio_dev, chan,
 					    IIO_SHARED_BY_DIR,
 					    &chan->info_mask_shared_by_dir);
@@ -1007,12 +1188,26 @@ static int iio_device_add_channel_sysfs(
 		return ret;
 	attrcount += ret;
 
+	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
+						  IIO_SHARED_BY_DIR,
+						  &chan->info_mask_shared_by_dir_available);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
+
 	ret = iio_device_add_info_mask_type(indio_dev, chan,
 					    IIO_SHARED_BY_ALL,
 					    &chan->info_mask_shared_by_all);
 	if (ret < 0)
 		return ret;
 	attrcount += ret;
+
+	ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
+						  IIO_SHARED_BY_ALL,
+						  &chan->info_mask_shared_by_all_available);
+	if (ret < 0)
+		return ret;
+	attrcount += ret;
 
 	if (chan->ext_info) {
 		unsigned int i = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/industrialio-trigger.c linux-libre-4.10-rc8-gnu/drivers/iio/industrialio-trigger.c
--- linux-libre-4.9-gnu/drivers/iio/industrialio-trigger.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/industrialio-trigger.c	2017-02-12 16:03:20.000000000 -0500
@@ -717,6 +717,27 @@ bool iio_trigger_using_own(struct iio_de
 }
 EXPORT_SYMBOL(iio_trigger_using_own);
 
+/**
+ * iio_trigger_validate_own_device - Check if a trigger and IIO device belong to
+ *  the same device
+ * @trig: The IIO trigger to check
+ * @indio_dev: the IIO device to check
+ *
+ * This function can be used as the validate_device callback for triggers that
+ * can only be attached to their own device.
+ *
+ * Return: 0 if both the trigger and the IIO device belong to the same
+ * device, -EINVAL otherwise.
+ */
+int iio_trigger_validate_own_device(struct iio_trigger *trig,
+	struct iio_dev *indio_dev)
+{
+	if (indio_dev->dev.parent != trig->dev.parent)
+		return -EINVAL;
+	return 0;
+}
+EXPORT_SYMBOL(iio_trigger_validate_own_device);
+
 void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
 {
 	indio_dev->groups[indio_dev->groupcounter++] =
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/inkern.c linux-libre-4.10-rc8-gnu/drivers/iio/inkern.c
--- linux-libre-4.9-gnu/drivers/iio/inkern.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/inkern.c	2017-02-12 16:03:20.000000000 -0500
@@ -658,6 +658,31 @@ err_unlock:
 }
 EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
 
+static int iio_read_channel_attribute(struct iio_channel *chan,
+				      int *val, int *val2,
+				      enum iio_chan_info_enum attribute)
+{
+	int ret;
+
+	mutex_lock(&chan->indio_dev->info_exist_lock);
+	if (chan->indio_dev->info == NULL) {
+		ret = -ENODEV;
+		goto err_unlock;
+	}
+
+	ret = iio_channel_read(chan, val, val2, attribute);
+err_unlock:
+	mutex_unlock(&chan->indio_dev->info_exist_lock);
+
+	return ret;
+}
+
+int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2)
+{
+	return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_OFFSET);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_offset);
+
 int iio_read_channel_processed(struct iio_channel *chan, int *val)
 {
 	int ret;
@@ -687,21 +712,113 @@ EXPORT_SYMBOL_GPL(iio_read_channel_proce
 
 int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
 {
+	return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_SCALE);
+}
+EXPORT_SYMBOL_GPL(iio_read_channel_scale);
+
+static int iio_channel_read_avail(struct iio_channel *chan,
+				  const int **vals, int *type, int *length,
+				  enum iio_chan_info_enum info)
+{
+	if (!iio_channel_has_available(chan->channel, info))
+		return -EINVAL;
+
+	return chan->indio_dev->info->read_avail(chan->indio_dev, chan->channel,
+						 vals, type, length, info);
+}
+
+int iio_read_avail_channel_raw(struct iio_channel *chan,
+			       const int **vals, int *length)
+{
 	int ret;
+	int type;
 
 	mutex_lock(&chan->indio_dev->info_exist_lock);
-	if (chan->indio_dev->info == NULL) {
+	if (!chan->indio_dev->info) {
 		ret = -ENODEV;
 		goto err_unlock;
 	}
 
-	ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE);
+	ret = iio_channel_read_avail(chan,
+				     vals, &type, length, IIO_CHAN_INFO_RAW);
 err_unlock:
 	mutex_unlock(&chan->indio_dev->info_exist_lock);
 
+	if (ret >= 0 && type != IIO_VAL_INT) {
+		/* raw values are assumed to be IIO_VAL_INT */
+		ret = -EINVAL;
+		goto err_unlock;
+	}
+
 	return ret;
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_scale);
+EXPORT_SYMBOL_GPL(iio_read_avail_channel_raw);
+
+static int iio_channel_read_max(struct iio_channel *chan,
+				int *val, int *val2, int *type,
+				enum iio_chan_info_enum info)
+{
+	int unused;
+	const int *vals;
+	int length;
+	int ret;
+
+	if (!val2)
+		val2 = &unused;
+
+	ret = iio_channel_read_avail(chan, &vals, type, &length, info);
+	switch (ret) {
+	case IIO_AVAIL_RANGE:
+		switch (*type) {
+		case IIO_VAL_INT:
+			*val = vals[2];
+			break;
+		default:
+			*val = vals[4];
+			*val2 = vals[5];
+		}
+		return 0;
+
+	case IIO_AVAIL_LIST:
+		if (length <= 0)
+			return -EINVAL;
+		switch (*type) {
+		case IIO_VAL_INT:
+			*val = vals[--length];
+			while (length) {
+				if (vals[--length] > *val)
+					*val = vals[length];
+			}
+			break;
+		default:
+			/* FIXME: learn about max for other iio values */
+			return -EINVAL;
+		}
+		return 0;
+
+	default:
+		return ret;
+	}
+}
+
+int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
+{
+	int ret;
+	int type;
+
+	mutex_lock(&chan->indio_dev->info_exist_lock);
+	if (!chan->indio_dev->info) {
+		ret = -ENODEV;
+		goto err_unlock;
+	}
+
+	ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
+err_unlock:
+	mutex_unlock(&chan->indio_dev->info_exist_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(iio_read_max_channel_raw);
 
 int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -73,6 +73,7 @@ source "drivers/iio/adc/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
 source "drivers/iio/chemical/Kconfig"
 source "drivers/iio/common/Kconfig"
+source "drivers/iio/counter/Kconfig"
 source "drivers/iio/dac/Kconfig"
 source "drivers/iio/dummy/Kconfig"
 source "drivers/iio/frequency/Kconfig"
@@ -87,6 +88,7 @@ if IIO_TRIGGER
    source "drivers/iio/trigger/Kconfig"
 endif #IIO_TRIGGER
 source "drivers/iio/potentiometer/Kconfig"
+source "drivers/iio/potentiostat/Kconfig"
 source "drivers/iio/pressure/Kconfig"
 source "drivers/iio/proximity/Kconfig"
 source "drivers/iio/temperature/Kconfig"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/light/isl29018.c linux-libre-4.10-rc8-gnu/drivers/iio/light/isl29018.c
--- linux-libre-4.9-gnu/drivers/iio/light/isl29018.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/light/isl29018.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,847 @@
+/*
+ * A iio driver for the light sensor ISL 29018/29023/29035.
+ *
+ * IIO driver for monitoring ambient light intensity in luxi, proximity
+ * sensing and infrared sensing.
+ *
+ * Copyright (c) 2010, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/acpi.h>
+
+#define ISL29018_CONV_TIME_MS		100
+
+#define ISL29018_REG_ADD_COMMAND1	0x00
+#define ISL29018_CMD1_OPMODE_SHIFT	5
+#define ISL29018_CMD1_OPMODE_MASK	(7 << ISL29018_CMD1_OPMODE_SHIFT)
+#define ISL29018_CMD1_OPMODE_POWER_DOWN	0
+#define ISL29018_CMD1_OPMODE_ALS_ONCE	1
+#define ISL29018_CMD1_OPMODE_IR_ONCE	2
+#define ISL29018_CMD1_OPMODE_PROX_ONCE	3
+
+#define ISL29018_REG_ADD_COMMAND2	0x01
+#define ISL29018_CMD2_RESOLUTION_SHIFT	2
+#define ISL29018_CMD2_RESOLUTION_MASK	(0x3 << ISL29018_CMD2_RESOLUTION_SHIFT)
+
+#define ISL29018_CMD2_RANGE_SHIFT	0
+#define ISL29018_CMD2_RANGE_MASK	(0x3 << ISL29018_CMD2_RANGE_SHIFT)
+
+#define ISL29018_CMD2_SCHEME_SHIFT	7
+#define ISL29018_CMD2_SCHEME_MASK	(0x1 << ISL29018_CMD2_SCHEME_SHIFT)
+
+#define ISL29018_REG_ADD_DATA_LSB	0x02
+#define ISL29018_REG_ADD_DATA_MSB	0x03
+
+#define ISL29018_REG_TEST		0x08
+#define ISL29018_TEST_SHIFT		0
+#define ISL29018_TEST_MASK		(0xFF << ISL29018_TEST_SHIFT)
+
+#define ISL29035_REG_DEVICE_ID		0x0F
+#define ISL29035_DEVICE_ID_SHIFT	0x03
+#define ISL29035_DEVICE_ID_MASK		(0x7 << ISL29035_DEVICE_ID_SHIFT)
+#define ISL29035_DEVICE_ID		0x5
+#define ISL29035_BOUT_SHIFT		0x07
+#define ISL29035_BOUT_MASK		(0x01 << ISL29035_BOUT_SHIFT)
+
+enum isl29018_int_time {
+	ISL29018_INT_TIME_16,
+	ISL29018_INT_TIME_12,
+	ISL29018_INT_TIME_8,
+	ISL29018_INT_TIME_4,
+};
+
+static const unsigned int isl29018_int_utimes[3][4] = {
+	{90000, 5630, 351, 21},
+	{90000, 5600, 352, 22},
+	{105000, 6500, 410, 25},
+};
+
+static const struct isl29018_scale {
+	unsigned int scale;
+	unsigned int uscale;
+} isl29018_scales[4][4] = {
+	{ {0, 15258}, {0, 61035}, {0, 244140}, {0, 976562} },
+	{ {0, 244140}, {0, 976562}, {3, 906250}, {15, 625000} },
+	{ {3, 906250}, {15, 625000}, {62, 500000}, {250, 0} },
+	{ {62, 500000}, {250, 0}, {1000, 0}, {4000, 0} }
+};
+
+struct isl29018_chip {
+	struct regmap		*regmap;
+	struct mutex		lock;
+	int			type;
+	unsigned int		calibscale;
+	unsigned int		ucalibscale;
+	unsigned int		int_time;
+	struct isl29018_scale	scale;
+	int			prox_scheme;
+	bool			suspended;
+};
+
+static int isl29018_set_integration_time(struct isl29018_chip *chip,
+					 unsigned int utime)
+{
+	unsigned int i;
+	int ret;
+	unsigned int int_time, new_int_time;
+
+	for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i) {
+		if (utime == isl29018_int_utimes[chip->type][i]) {
+			new_int_time = i;
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(isl29018_int_utimes[chip->type]))
+		return -EINVAL;
+
+	ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
+				 ISL29018_CMD2_RESOLUTION_MASK,
+				 i << ISL29018_CMD2_RESOLUTION_SHIFT);
+	if (ret < 0)
+		return ret;
+
+	/* Keep the same range when integration time changes */
+	int_time = chip->int_time;
+	for (i = 0; i < ARRAY_SIZE(isl29018_scales[int_time]); ++i) {
+		if (chip->scale.scale == isl29018_scales[int_time][i].scale &&
+		    chip->scale.uscale == isl29018_scales[int_time][i].uscale) {
+			chip->scale = isl29018_scales[new_int_time][i];
+			break;
+		}
+	}
+	chip->int_time = new_int_time;
+
+	return 0;
+}
+
+static int isl29018_set_scale(struct isl29018_chip *chip, int scale, int uscale)
+{
+	unsigned int i;
+	int ret;
+	struct isl29018_scale new_scale;
+
+	for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i) {
+		if (scale == isl29018_scales[chip->int_time][i].scale &&
+		    uscale == isl29018_scales[chip->int_time][i].uscale) {
+			new_scale = isl29018_scales[chip->int_time][i];
+			break;
+		}
+	}
+
+	if (i >= ARRAY_SIZE(isl29018_scales[chip->int_time]))
+		return -EINVAL;
+
+	ret = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
+				 ISL29018_CMD2_RANGE_MASK,
+				 i << ISL29018_CMD2_RANGE_SHIFT);
+	if (ret < 0)
+		return ret;
+
+	chip->scale = new_scale;
+
+	return 0;
+}
+
+static int isl29018_read_sensor_input(struct isl29018_chip *chip, int mode)
+{
+	int status;
+	unsigned int lsb;
+	unsigned int msb;
+	struct device *dev = regmap_get_device(chip->regmap);
+
+	/* Set mode */
+	status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1,
+			      mode << ISL29018_CMD1_OPMODE_SHIFT);
+	if (status) {
+		dev_err(dev,
+			"Error in setting operating mode err %d\n", status);
+		return status;
+	}
+	msleep(ISL29018_CONV_TIME_MS);
+	status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_LSB, &lsb);
+	if (status < 0) {
+		dev_err(dev,
+			"Error in reading LSB DATA with err %d\n", status);
+		return status;
+	}
+
+	status = regmap_read(chip->regmap, ISL29018_REG_ADD_DATA_MSB, &msb);
+	if (status < 0) {
+		dev_err(dev,
+			"Error in reading MSB DATA with error %d\n", status);
+		return status;
+	}
+	dev_vdbg(dev, "MSB 0x%x and LSB 0x%x\n", msb, lsb);
+
+	return (msb << 8) | lsb;
+}
+
+static int isl29018_read_lux(struct isl29018_chip *chip, int *lux)
+{
+	int lux_data;
+	unsigned int data_x_range;
+
+	lux_data = isl29018_read_sensor_input(chip,
+					      ISL29018_CMD1_OPMODE_ALS_ONCE);
+	if (lux_data < 0)
+		return lux_data;
+
+	data_x_range = lux_data * chip->scale.scale +
+		       lux_data * chip->scale.uscale / 1000000;
+	*lux = data_x_range * chip->calibscale +
+	       data_x_range * chip->ucalibscale / 1000000;
+
+	return 0;
+}
+
+static int isl29018_read_ir(struct isl29018_chip *chip, int *ir)
+{
+	int ir_data;
+
+	ir_data = isl29018_read_sensor_input(chip,
+					     ISL29018_CMD1_OPMODE_IR_ONCE);
+	if (ir_data < 0)
+		return ir_data;
+
+	*ir = ir_data;
+
+	return 0;
+}
+
+static int isl29018_read_proximity_ir(struct isl29018_chip *chip, int scheme,
+				      int *near_ir)
+{
+	int status;
+	int prox_data = -1;
+	int ir_data = -1;
+	struct device *dev = regmap_get_device(chip->regmap);
+
+	/* Do proximity sensing with required scheme */
+	status = regmap_update_bits(chip->regmap, ISL29018_REG_ADD_COMMAND2,
+				    ISL29018_CMD2_SCHEME_MASK,
+				    scheme << ISL29018_CMD2_SCHEME_SHIFT);
+	if (status) {
+		dev_err(dev, "Error in setting operating mode\n");
+		return status;
+	}
+
+	prox_data = isl29018_read_sensor_input(chip,
+					       ISL29018_CMD1_OPMODE_PROX_ONCE);
+	if (prox_data < 0)
+		return prox_data;
+
+	if (scheme == 1) {
+		*near_ir = prox_data;
+		return 0;
+	}
+
+	ir_data = isl29018_read_sensor_input(chip,
+					     ISL29018_CMD1_OPMODE_IR_ONCE);
+	if (ir_data < 0)
+		return ir_data;
+
+	if (prox_data >= ir_data)
+		*near_ir = prox_data - ir_data;
+	else
+		*near_ir = 0;
+
+	return 0;
+}
+
+static ssize_t in_illuminance_scale_available_show
+			(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+	unsigned int i;
+	int len = 0;
+
+	mutex_lock(&chip->lock);
+	for (i = 0; i < ARRAY_SIZE(isl29018_scales[chip->int_time]); ++i)
+		len += sprintf(buf + len, "%d.%06d ",
+			       isl29018_scales[chip->int_time][i].scale,
+			       isl29018_scales[chip->int_time][i].uscale);
+	mutex_unlock(&chip->lock);
+
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static ssize_t in_illuminance_integration_time_available_show
+			(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+	unsigned int i;
+	int len = 0;
+
+	for (i = 0; i < ARRAY_SIZE(isl29018_int_utimes[chip->type]); ++i)
+		len += sprintf(buf + len, "0.%06d ",
+			       isl29018_int_utimes[chip->type][i]);
+
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+/*
+ * From ISL29018 Data Sheet (FN6619.4, Oct 8, 2012) regarding the
+ * infrared suppression:
+ *
+ *   Proximity Sensing Scheme: Bit 7. This bit programs the function
+ * of the proximity detection. Logic 0 of this bit, Scheme 0, makes
+ * full n (4, 8, 12, 16) bits (unsigned) proximity detection. The range
+ * of Scheme 0 proximity count is from 0 to 2^n. Logic 1 of this bit,
+ * Scheme 1, makes n-1 (3, 7, 11, 15) bits (2's complementary)
+ * proximity_less_ambient detection. The range of Scheme 1
+ * proximity count is from -2^(n-1) to 2^(n-1) . The sign bit is extended
+ * for resolutions less than 16. While Scheme 0 has wider dynamic
+ * range, Scheme 1 proximity detection is less affected by the
+ * ambient IR noise variation.
+ *
+ * 0 Sensing IR from LED and ambient
+ * 1 Sensing IR from LED with ambient IR rejection
+ */
+static ssize_t proximity_on_chip_ambient_infrared_suppression_show
+			(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+
+	/*
+	 * Return the "proximity scheme" i.e. if the chip does on chip
+	 * infrared suppression (1 means perform on chip suppression)
+	 */
+	return sprintf(buf, "%d\n", chip->prox_scheme);
+}
+
+static ssize_t proximity_on_chip_ambient_infrared_suppression_store
+			(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+	int val;
+
+	if (kstrtoint(buf, 10, &val))
+		return -EINVAL;
+	if (!(val == 0 || val == 1))
+		return -EINVAL;
+
+	/*
+	 * Get the "proximity scheme" i.e. if the chip does on chip
+	 * infrared suppression (1 means perform on chip suppression)
+	 */
+	mutex_lock(&chip->lock);
+	chip->prox_scheme = val;
+	mutex_unlock(&chip->lock);
+
+	return count;
+}
+
+static int isl29018_write_raw(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      int val,
+			      int val2,
+			      long mask)
+{
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	mutex_lock(&chip->lock);
+	if (chip->suspended) {
+		ret = -EBUSY;
+		goto write_done;
+	}
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (chan->type == IIO_LIGHT) {
+			chip->calibscale = val;
+			chip->ucalibscale = val2;
+			ret = 0;
+		}
+		break;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (chan->type == IIO_LIGHT && !val)
+			ret = isl29018_set_integration_time(chip, val2);
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		if (chan->type == IIO_LIGHT)
+			ret = isl29018_set_scale(chip, val, val2);
+		break;
+	default:
+		break;
+	}
+
+write_done:
+	mutex_unlock(&chip->lock);
+
+	return ret;
+}
+
+static int isl29018_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val,
+			     int *val2,
+			     long mask)
+{
+	int ret = -EINVAL;
+	struct isl29018_chip *chip = iio_priv(indio_dev);
+
+	mutex_lock(&chip->lock);
+	if (chip->suspended) {
+		ret = -EBUSY;
+		goto read_done;
+	}
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_PROCESSED:
+		switch (chan->type) {
+		case IIO_LIGHT:
+			ret = isl29018_read_lux(chip, val);
+			break;
+		case IIO_INTENSITY:
+			ret = isl29018_read_ir(chip, val);
+			break;
+		case IIO_PROXIMITY:
+			ret = isl29018_read_proximity_ir(chip,
+							 chip->prox_scheme,
+							 val);
+			break;
+		default:
+			break;
+		}
+		if (!ret)
+			ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (chan->type == IIO_LIGHT) {
+			*val = 0;
+			*val2 = isl29018_int_utimes[chip->type][chip->int_time];
+			ret = IIO_VAL_INT_PLUS_MICRO;
+		}
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		if (chan->type == IIO_LIGHT) {
+			*val = chip->scale.scale;
+			*val2 = chip->scale.uscale;
+			ret = IIO_VAL_INT_PLUS_MICRO;
+		}
+		break;
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (chan->type == IIO_LIGHT) {
+			*val = chip->calibscale;
+			*val2 = chip->ucalibscale;
+			ret = IIO_VAL_INT_PLUS_MICRO;
+		}
+		break;
+	default:
+		break;
+	}
+
+read_done:
+	mutex_unlock(&chip->lock);
+
+	return ret;
+}
+
+#define ISL29018_LIGHT_CHANNEL {					\
+	.type = IIO_LIGHT,						\
+	.indexed = 1,							\
+	.channel = 0,							\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |		\
+	BIT(IIO_CHAN_INFO_CALIBSCALE) |					\
+	BIT(IIO_CHAN_INFO_SCALE) |					\
+	BIT(IIO_CHAN_INFO_INT_TIME),					\
+}
+
+#define ISL29018_IR_CHANNEL {						\
+	.type = IIO_INTENSITY,						\
+	.modified = 1,							\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.channel2 = IIO_MOD_LIGHT_IR,					\
+}
+
+#define ISL29018_PROXIMITY_CHANNEL {					\
+	.type = IIO_PROXIMITY,						\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+}
+
+static const struct iio_chan_spec isl29018_channels[] = {
+	ISL29018_LIGHT_CHANNEL,
+	ISL29018_IR_CHANNEL,
+	ISL29018_PROXIMITY_CHANNEL,
+};
+
+static const struct iio_chan_spec isl29023_channels[] = {
+	ISL29018_LIGHT_CHANNEL,
+	ISL29018_IR_CHANNEL,
+};
+
+static IIO_DEVICE_ATTR_RO(in_illuminance_integration_time_available, 0);
+static IIO_DEVICE_ATTR_RO(in_illuminance_scale_available, 0);
+static IIO_DEVICE_ATTR_RW(proximity_on_chip_ambient_infrared_suppression, 0);
+
+#define ISL29018_DEV_ATTR(name) (&iio_dev_attr_##name.dev_attr.attr)
+
+static struct attribute *isl29018_attributes[] = {
+	ISL29018_DEV_ATTR(in_illuminance_scale_available),
+	ISL29018_DEV_ATTR(in_illuminance_integration_time_available),
+	ISL29018_DEV_ATTR(proximity_on_chip_ambient_infrared_suppression),
+	NULL
+};
+
+static struct attribute *isl29023_attributes[] = {
+	ISL29018_DEV_ATTR(in_illuminance_scale_available),
+	ISL29018_DEV_ATTR(in_illuminance_integration_time_available),
+	NULL
+};
+
+static const struct attribute_group isl29018_group = {
+	.attrs = isl29018_attributes,
+};
+
+static const struct attribute_group isl29023_group = {
+	.attrs = isl29023_attributes,
+};
+
+enum {
+	isl29018,
+	isl29023,
+	isl29035,
+};
+
+static int isl29018_chip_init(struct isl29018_chip *chip)
+{
+	int status;
+	struct device *dev = regmap_get_device(chip->regmap);
+
+	if (chip->type == isl29035) {
+		unsigned int id;
+
+		status = regmap_read(chip->regmap, ISL29035_REG_DEVICE_ID, &id);
+		if (status < 0) {
+			dev_err(dev,
+				"Error reading ID register with error %d\n",
+				status);
+			return status;
+		}
+
+		id = (id & ISL29035_DEVICE_ID_MASK) >> ISL29035_DEVICE_ID_SHIFT;
+
+		if (id != ISL29035_DEVICE_ID)
+			return -ENODEV;
+
+		/* Clear brownout bit */
+		status = regmap_update_bits(chip->regmap,
+					    ISL29035_REG_DEVICE_ID,
+					    ISL29035_BOUT_MASK, 0);
+		if (status < 0)
+			return status;
+	}
+
+	/*
+	 * Code added per Intersil Application Note 1534:
+	 *     When VDD sinks to approximately 1.8V or below, some of
+	 * the part's registers may change their state. When VDD
+	 * recovers to 2.25V (or greater), the part may thus be in an
+	 * unknown mode of operation. The user can return the part to
+	 * a known mode of operation either by (a) setting VDD = 0V for
+	 * 1 second or more and then powering back up with a slew rate
+	 * of 0.5V/ms or greater, or (b) via I2C disable all ALS/PROX
+	 * conversions, clear the test registers, and then rewrite all
+	 * registers to the desired values.
+	 * ...
+	 * For ISL29011, ISL29018, ISL29021, ISL29023
+	 * 1. Write 0x00 to register 0x08 (TEST)
+	 * 2. Write 0x00 to register 0x00 (CMD1)
+	 * 3. Rewrite all registers to the desired values
+	 *
+	 * ISL29018 Data Sheet (FN6619.1, Feb 11, 2010) essentially says
+	 * the same thing EXCEPT the data sheet asks for a 1ms delay after
+	 * writing the CMD1 register.
+	 */
+	status = regmap_write(chip->regmap, ISL29018_REG_TEST, 0x0);
+	if (status < 0) {
+		dev_err(dev, "Failed to clear isl29018 TEST reg.(%d)\n",
+			status);
+		return status;
+	}
+
+	/*
+	 * See Intersil AN1534 comments above.
+	 * "Operating Mode" (COMMAND1) register is reprogrammed when
+	 * data is read from the device.
+	 */
+	status = regmap_write(chip->regmap, ISL29018_REG_ADD_COMMAND1, 0);
+	if (status < 0) {
+		dev_err(dev, "Failed to clear isl29018 CMD1 reg.(%d)\n",
+			status);
+		return status;
+	}
+
+	usleep_range(1000, 2000);	/* per data sheet, page 10 */
+
+	/* Set defaults */
+	status = isl29018_set_scale(chip, chip->scale.scale,
+				    chip->scale.uscale);
+	if (status < 0) {
+		dev_err(dev, "Init of isl29018 fails\n");
+		return status;
+	}
+
+	status = isl29018_set_integration_time(chip,
+			isl29018_int_utimes[chip->type][chip->int_time]);
+	if (status < 0)
+		dev_err(dev, "Init of isl29018 fails\n");
+
+	return status;
+}
+
+static const struct iio_info isl29018_info = {
+	.attrs = &isl29018_group,
+	.driver_module = THIS_MODULE,
+	.read_raw = isl29018_read_raw,
+	.write_raw = isl29018_write_raw,
+};
+
+static const struct iio_info isl29023_info = {
+	.attrs = &isl29023_group,
+	.driver_module = THIS_MODULE,
+	.read_raw = isl29018_read_raw,
+	.write_raw = isl29018_write_raw,
+};
+
+static bool isl29018_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case ISL29018_REG_ADD_DATA_LSB:
+	case ISL29018_REG_ADD_DATA_MSB:
+	case ISL29018_REG_ADD_COMMAND1:
+	case ISL29018_REG_TEST:
+	case ISL29035_REG_DEVICE_ID:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_config isl29018_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_reg = isl29018_is_volatile_reg,
+	.max_register = ISL29018_REG_TEST,
+	.num_reg_defaults_raw = ISL29018_REG_TEST + 1,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static const struct regmap_config isl29035_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.volatile_reg = isl29018_is_volatile_reg,
+	.max_register = ISL29035_REG_DEVICE_ID,
+	.num_reg_defaults_raw = ISL29035_REG_DEVICE_ID + 1,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+struct isl29018_chip_info {
+	const struct iio_chan_spec *channels;
+	int num_channels;
+	const struct iio_info *indio_info;
+	const struct regmap_config *regmap_cfg;
+};
+
+static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
+	[isl29018] = {
+		.channels = isl29018_channels,
+		.num_channels = ARRAY_SIZE(isl29018_channels),
+		.indio_info = &isl29018_info,
+		.regmap_cfg = &isl29018_regmap_config,
+	},
+	[isl29023] = {
+		.channels = isl29023_channels,
+		.num_channels = ARRAY_SIZE(isl29023_channels),
+		.indio_info = &isl29023_info,
+		.regmap_cfg = &isl29018_regmap_config,
+	},
+	[isl29035] = {
+		.channels = isl29023_channels,
+		.num_channels = ARRAY_SIZE(isl29023_channels),
+		.indio_info = &isl29023_info,
+		.regmap_cfg = &isl29035_regmap_config,
+	},
+};
+
+static const char *isl29018_match_acpi_device(struct device *dev, int *data)
+{
+	const struct acpi_device_id *id;
+
+	id = acpi_match_device(dev->driver->acpi_match_table, dev);
+
+	if (!id)
+		return NULL;
+
+	*data = (int)id->driver_data;
+
+	return dev_name(dev);
+}
+
+static int isl29018_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct isl29018_chip *chip;
+	struct iio_dev *indio_dev;
+	int err;
+	const char *name = NULL;
+	int dev_id = 0;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	chip = iio_priv(indio_dev);
+
+	i2c_set_clientdata(client, indio_dev);
+
+	if (id) {
+		name = id->name;
+		dev_id = id->driver_data;
+	}
+
+	if (ACPI_HANDLE(&client->dev))
+		name = isl29018_match_acpi_device(&client->dev, &dev_id);
+
+	mutex_init(&chip->lock);
+
+	chip->type = dev_id;
+	chip->calibscale = 1;
+	chip->ucalibscale = 0;
+	chip->int_time = ISL29018_INT_TIME_16;
+	chip->scale = isl29018_scales[chip->int_time][0];
+	chip->suspended = false;
+
+	chip->regmap = devm_regmap_init_i2c(client,
+				isl29018_chip_info_tbl[dev_id].regmap_cfg);
+	if (IS_ERR(chip->regmap)) {
+		err = PTR_ERR(chip->regmap);
+		dev_err(&client->dev, "regmap initialization fails: %d\n", err);
+		return err;
+	}
+
+	err = isl29018_chip_init(chip);
+	if (err)
+		return err;
+
+	indio_dev->info = isl29018_chip_info_tbl[dev_id].indio_info;
+	indio_dev->channels = isl29018_chip_info_tbl[dev_id].channels;
+	indio_dev->num_channels = isl29018_chip_info_tbl[dev_id].num_channels;
+	indio_dev->name = name;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int isl29018_suspend(struct device *dev)
+{
+	struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
+
+	mutex_lock(&chip->lock);
+
+	/*
+	 * Since this driver uses only polling commands, we are by default in
+	 * auto shutdown (ie, power-down) mode.
+	 * So we do not have much to do here.
+	 */
+	chip->suspended = true;
+
+	mutex_unlock(&chip->lock);
+
+	return 0;
+}
+
+static int isl29018_resume(struct device *dev)
+{
+	struct isl29018_chip *chip = iio_priv(dev_get_drvdata(dev));
+	int err;
+
+	mutex_lock(&chip->lock);
+
+	err = isl29018_chip_init(chip);
+	if (!err)
+		chip->suspended = false;
+
+	mutex_unlock(&chip->lock);
+
+	return err;
+}
+
+static SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend, isl29018_resume);
+#define ISL29018_PM_OPS (&isl29018_pm_ops)
+#else
+#define ISL29018_PM_OPS NULL
+#endif
+
+static const struct acpi_device_id isl29018_acpi_match[] = {
+	{"ISL29018", isl29018},
+	{"ISL29023", isl29023},
+	{"ISL29035", isl29035},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
+
+static const struct i2c_device_id isl29018_id[] = {
+	{"isl29018", isl29018},
+	{"isl29023", isl29023},
+	{"isl29035", isl29035},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, isl29018_id);
+
+static const struct of_device_id isl29018_of_match[] = {
+	{ .compatible = "isil,isl29018", },
+	{ .compatible = "isil,isl29023", },
+	{ .compatible = "isil,isl29035", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, isl29018_of_match);
+
+static struct i2c_driver isl29018_driver = {
+	.driver	 = {
+			.name = "isl29018",
+			.acpi_match_table = ACPI_PTR(isl29018_acpi_match),
+			.pm = ISL29018_PM_OPS,
+			.of_match_table = isl29018_of_match,
+		    },
+	.probe	 = isl29018_probe,
+	.id_table = isl29018_id,
+};
+module_i2c_driver(isl29018_driver);
+
+MODULE_DESCRIPTION("ISL29018 Ambient Light Sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/light/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/light/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/light/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/light/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -140,6 +140,18 @@ config GP2AP020A00F
 	  To compile this driver as a module, choose M here: the
 	  module will be called gp2ap020a00f.
 
+config SENSORS_ISL29018
+	tristate "Intersil 29018 light and proximity sensor"
+	depends on I2C
+	select REGMAP_I2C
+	default n
+	help
+	 If you say yes here you get support for ambient light sensing and
+	 proximity infrared sensing from Intersil ISL29018.
+	 This driver will provide the measurements of ambient light intensity
+	 in lux, proximity infrared sensing and normal infrared sensing.
+	 Data from sensor is accessible via sysfs.
+
 config ISL29125
 	tristate "Intersil ISL29125 digital color light sensor"
 	depends on I2C
@@ -326,6 +338,13 @@ config SENSORS_TSL2563
 	 This driver can also be built as a module.  If so, the module
 	 will be called tsl2563.
 
+config TSL2583
+	tristate "TAOS TSL2580, TSL2581 and TSL2583 light-to-digital converters"
+	depends on I2C
+	help
+	 Provides support for the TAOS tsl2580, tsl2581 and tsl2583 devices.
+	 Access ALS data via iio, sysfs.
+
 config TSL4531
 	tristate "TAOS TSL4531 ambient light sensors"
 	depends on I2C
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/light/ltr501.c linux-libre-4.10-rc8-gnu/drivers/iio/light/ltr501.c
--- linux-libre-4.9-gnu/drivers/iio/light/ltr501.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/light/ltr501.c	2017-02-12 16:03:20.000000000 -0500
@@ -631,14 +631,16 @@ static int ltr501_read_raw(struct iio_de
 
 	switch (mask) {
 	case IIO_CHAN_INFO_PROCESSED:
-		if (iio_buffer_enabled(indio_dev))
-			return -EBUSY;
-
 		switch (chan->type) {
 		case IIO_LIGHT:
+			ret = iio_device_claim_direct_mode(indio_dev);
+			if (ret)
+				return ret;
+
 			mutex_lock(&data->lock_als);
 			ret = ltr501_read_als(data, buf);
 			mutex_unlock(&data->lock_als);
+			iio_device_release_direct_mode(indio_dev);
 			if (ret < 0)
 				return ret;
 			*val = ltr501_calculate_lux(le16_to_cpu(buf[1]),
@@ -648,8 +650,9 @@ static int ltr501_read_raw(struct iio_de
 			return -EINVAL;
 		}
 	case IIO_CHAN_INFO_RAW:
-		if (iio_buffer_enabled(indio_dev))
-			return -EBUSY;
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
 
 		switch (chan->type) {
 		case IIO_INTENSITY:
@@ -657,21 +660,28 @@ static int ltr501_read_raw(struct iio_de
 			ret = ltr501_read_als(data, buf);
 			mutex_unlock(&data->lock_als);
 			if (ret < 0)
-				return ret;
+				break;
 			*val = le16_to_cpu(chan->address == LTR501_ALS_DATA1 ?
 					   buf[0] : buf[1]);
-			return IIO_VAL_INT;
+			ret = IIO_VAL_INT;
+			break;
 		case IIO_PROXIMITY:
 			mutex_lock(&data->lock_ps);
 			ret = ltr501_read_ps(data);
 			mutex_unlock(&data->lock_ps);
 			if (ret < 0)
-				return ret;
+				break;
 			*val = ret & LTR501_PS_DATA_MASK;
-			return IIO_VAL_INT;
+			ret = IIO_VAL_INT;
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			break;
 		}
+
+		iio_device_release_direct_mode(indio_dev);
+		return ret;
+
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_INTENSITY:
@@ -729,8 +739,9 @@ static int ltr501_write_raw(struct iio_d
 	int i, ret, freq_val, freq_val2;
 	struct ltr501_chip_info *info = data->chip_info;
 
-	if (iio_buffer_enabled(indio_dev))
-		return -EBUSY;
+	ret = iio_device_claim_direct_mode(indio_dev);
+	if (ret)
+		return ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_SCALE:
@@ -739,85 +750,105 @@ static int ltr501_write_raw(struct iio_d
 			i = ltr501_get_gain_index(info->als_gain,
 						  info->als_gain_tbl_size,
 						  val, val2);
-			if (i < 0)
-				return -EINVAL;
+			if (i < 0) {
+				ret = -EINVAL;
+				break;
+			}
 
 			data->als_contr &= ~info->als_gain_mask;
 			data->als_contr |= i << info->als_gain_shift;
 
-			return regmap_write(data->regmap, LTR501_ALS_CONTR,
-					    data->als_contr);
+			ret = regmap_write(data->regmap, LTR501_ALS_CONTR,
+					   data->als_contr);
+			break;
 		case IIO_PROXIMITY:
 			i = ltr501_get_gain_index(info->ps_gain,
 						  info->ps_gain_tbl_size,
 						  val, val2);
-			if (i < 0)
-				return -EINVAL;
+			if (i < 0) {
+				ret = -EINVAL;
+				break;
+			}
 			data->ps_contr &= ~LTR501_CONTR_PS_GAIN_MASK;
 			data->ps_contr |= i << LTR501_CONTR_PS_GAIN_SHIFT;
 
-			return regmap_write(data->regmap, LTR501_PS_CONTR,
-					    data->ps_contr);
+			ret = regmap_write(data->regmap, LTR501_PS_CONTR,
+					   data->ps_contr);
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			break;
 		}
+		break;
+
 	case IIO_CHAN_INFO_INT_TIME:
 		switch (chan->type) {
 		case IIO_INTENSITY:
-			if (val != 0)
-				return -EINVAL;
+			if (val != 0) {
+				ret = -EINVAL;
+				break;
+			}
 			mutex_lock(&data->lock_als);
-			i = ltr501_set_it_time(data, val2);
+			ret = ltr501_set_it_time(data, val2);
 			mutex_unlock(&data->lock_als);
-			return i;
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			break;
 		}
+		break;
+
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		switch (chan->type) {
 		case IIO_INTENSITY:
 			ret = ltr501_als_read_samp_freq(data, &freq_val,
 							&freq_val2);
 			if (ret < 0)
-				return ret;
+				break;
 
 			ret = ltr501_als_write_samp_freq(data, val, val2);
 			if (ret < 0)
-				return ret;
+				break;
 
 			/* update persistence count when changing frequency */
 			ret = ltr501_write_intr_prst(data, chan->type,
 						     0, data->als_period);
 
 			if (ret < 0)
-				return ltr501_als_write_samp_freq(data,
-								  freq_val,
-								  freq_val2);
-			return ret;
+				ret = ltr501_als_write_samp_freq(data, freq_val,
+								 freq_val2);
+			break;
 		case IIO_PROXIMITY:
 			ret = ltr501_ps_read_samp_freq(data, &freq_val,
 						       &freq_val2);
 			if (ret < 0)
-				return ret;
+				break;
 
 			ret = ltr501_ps_write_samp_freq(data, val, val2);
 			if (ret < 0)
-				return ret;
+				break;
 
 			/* update persistence count when changing frequency */
 			ret = ltr501_write_intr_prst(data, chan->type,
 						     0, data->ps_period);
 
 			if (ret < 0)
-				return ltr501_ps_write_samp_freq(data,
-								 freq_val,
-								 freq_val2);
-			return ret;
+				ret = ltr501_ps_write_samp_freq(data, freq_val,
+								freq_val2);
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			break;
 		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
 	}
-	return -EINVAL;
+
+	iio_device_release_direct_mode(indio_dev);
+	return ret;
 }
 
 static int ltr501_read_thresh(struct iio_dev *indio_dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/light/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/light/Makefile
--- linux-libre-4.9-gnu/drivers/iio/light/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/light/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@ obj-$(CONFIG_CM36651)		+= cm36651.o
 obj-$(CONFIG_GP2AP020A00F)	+= gp2ap020a00f.o
 obj-$(CONFIG_HID_SENSOR_ALS)	+= hid-sensor-als.o
 obj-$(CONFIG_HID_SENSOR_PROX)	+= hid-sensor-prox.o
+obj-$(CONFIG_SENSORS_ISL29018)	+= isl29018.o
 obj-$(CONFIG_ISL29125)		+= isl29125.o
 obj-$(CONFIG_JSA1212)		+= jsa1212.o
 obj-$(CONFIG_SENSORS_LM3533)	+= lm3533-als.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_SI1145)		+= si1145.o
 obj-$(CONFIG_STK3310)          += stk3310.o
 obj-$(CONFIG_TCS3414)		+= tcs3414.o
 obj-$(CONFIG_TCS3472)		+= tcs3472.o
+obj-$(CONFIG_TSL2583)		+= tsl2583.o
 obj-$(CONFIG_TSL4531)		+= tsl4531.o
 obj-$(CONFIG_US5182D)		+= us5182d.o
 obj-$(CONFIG_VCNL4000)		+= vcnl4000.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/light/max44000.c linux-libre-4.10-rc8-gnu/drivers/iio/light/max44000.c
--- linux-libre-4.9-gnu/drivers/iio/light/max44000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/light/max44000.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,7 +113,7 @@ static const char max44000_int_time_avai
 	"0.100 "
 	"0.025 "
 	"0.00625 "
-	"0.001625";
+	"0.0015625";
 
 /* Available scales (internal to ulux) with pretty manual alignment: */
 static const int max44000_scale_avail_ulux_array[] = {
@@ -204,17 +204,18 @@ static int max44000_write_alspga(struct
 static int max44000_read_alsval(struct max44000_data *data)
 {
 	u16 regval;
+	__be16 val;
 	int alstim, ret;
 
 	ret = regmap_bulk_read(data->regmap, MAX44000_REG_ALS_DATA_HI,
-			       &regval, sizeof(regval));
+			       &val, sizeof(val));
 	if (ret < 0)
 		return ret;
 	alstim = ret = max44000_read_alstim(data);
 	if (ret < 0)
 		return ret;
 
-	regval = be16_to_cpu(regval);
+	regval = be16_to_cpu(val);
 
 	/*
 	 * Overflow is explained on datasheet page 17.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/light/tsl2583.c linux-libre-4.10-rc8-gnu/drivers/iio/light/tsl2583.c
--- linux-libre-4.9-gnu/drivers/iio/light/tsl2583.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/light/tsl2583.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,913 @@
+/*
+ * Device driver for monitoring ambient light intensity (lux)
+ * within the TAOS tsl258x family of devices (tsl2580, tsl2581, tsl2583).
+ *
+ * Copyright (c) 2011, TAOS Corporation.
+ * Copyright (c) 2016 Brian Masney <masneyb@onstation.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+/* Device Registers and Masks */
+#define TSL2583_CNTRL			0x00
+#define TSL2583_ALS_TIME		0X01
+#define TSL2583_INTERRUPT		0x02
+#define TSL2583_GAIN			0x07
+#define TSL2583_REVID			0x11
+#define TSL2583_CHIPID			0x12
+#define TSL2583_ALS_CHAN0LO		0x14
+#define TSL2583_ALS_CHAN0HI		0x15
+#define TSL2583_ALS_CHAN1LO		0x16
+#define TSL2583_ALS_CHAN1HI		0x17
+#define TSL2583_TMR_LO			0x18
+#define TSL2583_TMR_HI			0x19
+
+/* tsl2583 cmd reg masks */
+#define TSL2583_CMD_REG			0x80
+#define TSL2583_CMD_SPL_FN		0x60
+#define TSL2583_CMD_ALS_INT_CLR		0x01
+
+/* tsl2583 cntrl reg masks */
+#define TSL2583_CNTL_ADC_ENBL		0x02
+#define TSL2583_CNTL_PWR_OFF		0x00
+#define TSL2583_CNTL_PWR_ON		0x01
+
+/* tsl2583 status reg masks */
+#define TSL2583_STA_ADC_VALID		0x01
+#define TSL2583_STA_ADC_INTR		0x10
+
+/* Lux calculation constants */
+#define TSL2583_LUX_CALC_OVER_FLOW	65535
+
+#define TSL2583_INTERRUPT_DISABLED	0x00
+
+#define TSL2583_CHIP_ID			0x90
+#define TSL2583_CHIP_ID_MASK		0xf0
+
+/* Per-device data */
+struct tsl2583_als_info {
+	u16 als_ch0;
+	u16 als_ch1;
+	u16 lux;
+};
+
+struct tsl2583_lux {
+	unsigned int ratio;
+	unsigned int ch0;
+	unsigned int ch1;
+};
+
+static const struct tsl2583_lux tsl2583_default_lux[] = {
+	{  9830,  8520, 15729 },
+	{ 12452, 10807, 23344 },
+	{ 14746,  6383, 11705 },
+	{ 17695,  4063,  6554 },
+	{     0,     0,     0 }  /* Termination segment */
+};
+
+#define TSL2583_MAX_LUX_TABLE_ENTRIES 11
+
+struct tsl2583_settings {
+	int als_time;
+	int als_gain;
+	int als_gain_trim;
+	int als_cal_target;
+
+	/*
+	 * This structure is intentionally large to accommodate updates via
+	 * sysfs. Sized to 11 = max 10 segments + 1 termination segment.
+	 * Assumption is that one and only one type of glass used.
+	 */
+	struct tsl2583_lux als_device_lux[TSL2583_MAX_LUX_TABLE_ENTRIES];
+};
+
+struct tsl2583_chip {
+	struct mutex als_mutex;
+	struct i2c_client *client;
+	struct tsl2583_als_info als_cur_info;
+	struct tsl2583_settings als_settings;
+	int als_time_scale;
+	int als_saturation;
+	bool suspended;
+};
+
+struct gainadj {
+	s16 ch0;
+	s16 ch1;
+	s16 mean;
+};
+
+/* Index = (0 - 3) Used to validate the gain selection index */
+static const struct gainadj gainadj[] = {
+	{ 1, 1, 1 },
+	{ 8, 8, 8 },
+	{ 16, 16, 16 },
+	{ 107, 115, 111 }
+};
+
+/*
+ * Provides initial operational parameter defaults.
+ * These defaults may be changed through the device's sysfs files.
+ */
+static void tsl2583_defaults(struct tsl2583_chip *chip)
+{
+	/*
+	 * The integration time must be a multiple of 50ms and within the
+	 * range [50, 600] ms.
+	 */
+	chip->als_settings.als_time = 100;
+
+	/*
+	 * This is an index into the gainadj table. Assume clear glass as the
+	 * default.
+	 */
+	chip->als_settings.als_gain = 0;
+
+	/* Default gain trim to account for aperture effects */
+	chip->als_settings.als_gain_trim = 1000;
+
+	/* Known external ALS reading used for calibration */
+	chip->als_settings.als_cal_target = 130;
+
+	/* Default lux table. */
+	memcpy(chip->als_settings.als_device_lux, tsl2583_default_lux,
+	       sizeof(tsl2583_default_lux));
+}
+
+/*
+ * Reads and calculates current lux value.
+ * The raw ch0 and ch1 values of the ambient light sensed in the last
+ * integration cycle are read from the device.
+ * Time scale factor array values are adjusted based on the integration time.
+ * The raw values are multiplied by a scale factor, and device gain is obtained
+ * using gain index. Limit checks are done next, then the ratio of a multiple
+ * of ch1 value, to the ch0 value, is calculated. The array als_device_lux[]
+ * declared above is then scanned to find the first ratio value that is just
+ * above the ratio we just calculated. The ch0 and ch1 multiplier constants in
+ * the array are then used along with the time scale factor array values, to
+ * calculate the lux.
+ */
+static int tsl2583_get_lux(struct iio_dev *indio_dev)
+{
+	u16 ch0, ch1; /* separated ch0/ch1 data from device */
+	u32 lux; /* raw lux calculated from device data */
+	u64 lux64;
+	u32 ratio;
+	u8 buf[5];
+	struct tsl2583_lux *p;
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int i, ret;
+
+	ret = i2c_smbus_read_byte_data(chip->client, TSL2583_CMD_REG);
+	if (ret < 0) {
+		dev_err(&chip->client->dev, "%s: failed to read CMD_REG register\n",
+			__func__);
+		goto done;
+	}
+
+	/* is data new & valid */
+	if (!(ret & TSL2583_STA_ADC_INTR)) {
+		dev_err(&chip->client->dev, "%s: data not valid; returning last value\n",
+			__func__);
+		ret = chip->als_cur_info.lux; /* return LAST VALUE */
+		goto done;
+	}
+
+	for (i = 0; i < 4; i++) {
+		int reg = TSL2583_CMD_REG | (TSL2583_ALS_CHAN0LO + i);
+
+		ret = i2c_smbus_read_byte_data(chip->client, reg);
+		if (ret < 0) {
+			dev_err(&chip->client->dev, "%s: failed to read register %x\n",
+				__func__, reg);
+			goto done;
+		}
+		buf[i] = ret;
+	}
+
+	/*
+	 * Clear the pending interrupt status bit on the chip to allow the next
+	 * integration cycle to start. This has to be done even though this
+	 * driver currently does not support interrupts.
+	 */
+	ret = i2c_smbus_write_byte(chip->client,
+				   (TSL2583_CMD_REG | TSL2583_CMD_SPL_FN |
+				    TSL2583_CMD_ALS_INT_CLR));
+	if (ret < 0) {
+		dev_err(&chip->client->dev, "%s: failed to clear the interrupt bit\n",
+			__func__);
+		goto done; /* have no data, so return failure */
+	}
+
+	/* extract ALS/lux data */
+	ch0 = le16_to_cpup((const __le16 *)&buf[0]);
+	ch1 = le16_to_cpup((const __le16 *)&buf[2]);
+
+	chip->als_cur_info.als_ch0 = ch0;
+	chip->als_cur_info.als_ch1 = ch1;
+
+	if ((ch0 >= chip->als_saturation) || (ch1 >= chip->als_saturation))
+		goto return_max;
+
+	if (!ch0) {
+		/*
+		 * The sensor appears to be in total darkness so set the
+		 * calculated lux to 0 and return early to avoid a division by
+		 * zero below when calculating the ratio.
+		 */
+		ret = 0;
+		chip->als_cur_info.lux = 0;
+		goto done;
+	}
+
+	/* calculate ratio */
+	ratio = (ch1 << 15) / ch0;
+
+	/* convert to unscaled lux using the pointer to the table */
+	for (p = (struct tsl2583_lux *)chip->als_settings.als_device_lux;
+	     p->ratio != 0 && p->ratio < ratio; p++)
+		;
+
+	if (p->ratio == 0) {
+		lux = 0;
+	} else {
+		u32 ch0lux, ch1lux;
+
+		ch0lux = ((ch0 * p->ch0) +
+			  (gainadj[chip->als_settings.als_gain].ch0 >> 1))
+			 / gainadj[chip->als_settings.als_gain].ch0;
+		ch1lux = ((ch1 * p->ch1) +
+			  (gainadj[chip->als_settings.als_gain].ch1 >> 1))
+			 / gainadj[chip->als_settings.als_gain].ch1;
+
+		/* note: lux is 31 bit max at this point */
+		if (ch1lux > ch0lux) {
+			dev_dbg(&chip->client->dev, "%s: No Data - Returning 0\n",
+				__func__);
+			ret = 0;
+			chip->als_cur_info.lux = 0;
+			goto done;
+		}
+
+		lux = ch0lux - ch1lux;
+	}
+
+	/* adjust for active time scale */
+	if (chip->als_time_scale == 0)
+		lux = 0;
+	else
+		lux = (lux + (chip->als_time_scale >> 1)) /
+			chip->als_time_scale;
+
+	/*
+	 * Adjust for active gain scale.
+	 * The tsl2583_default_lux tables above have a factor of 8192 built in,
+	 * so we need to shift right.
+	 * User-specified gain provides a multiplier.
+	 * Apply user-specified gain before shifting right to retain precision.
+	 * Use 64 bits to avoid overflow on multiplication.
+	 * Then go back to 32 bits before division to avoid using div_u64().
+	 */
+	lux64 = lux;
+	lux64 = lux64 * chip->als_settings.als_gain_trim;
+	lux64 >>= 13;
+	lux = lux64;
+	lux = (lux + 500) / 1000;
+
+	if (lux > TSL2583_LUX_CALC_OVER_FLOW) { /* check for overflow */
+return_max:
+		lux = TSL2583_LUX_CALC_OVER_FLOW;
+	}
+
+	/* Update the structure with the latest VALID lux. */
+	chip->als_cur_info.lux = lux;
+	ret = lux;
+
+done:
+	return ret;
+}
+
+/*
+ * Obtain single reading and calculate the als_gain_trim (later used
+ * to derive actual lux).
+ * Return updated gain_trim value.
+ */
+static int tsl2583_als_calibrate(struct iio_dev *indio_dev)
+{
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	unsigned int gain_trim_val;
+	int ret;
+	int lux_val;
+
+	ret = i2c_smbus_read_byte_data(chip->client,
+				       TSL2583_CMD_REG | TSL2583_CNTRL);
+	if (ret < 0) {
+		dev_err(&chip->client->dev,
+			"%s: failed to read from the CNTRL register\n",
+			__func__);
+		return ret;
+	}
+
+	if ((ret & (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON))
+			!= (TSL2583_CNTL_ADC_ENBL | TSL2583_CNTL_PWR_ON)) {
+		dev_err(&chip->client->dev,
+			"%s: Device is not powered on and/or ADC is not enabled\n",
+			__func__);
+		return -EINVAL;
+	} else if ((ret & TSL2583_STA_ADC_VALID) != TSL2583_STA_ADC_VALID) {
+		dev_err(&chip->client->dev,
+			"%s: The two ADC channels have not completed an integration cycle\n",
+			__func__);
+		return -ENODATA;
+	}
+
+	lux_val = tsl2583_get_lux(indio_dev);
+	if (lux_val < 0) {
+		dev_err(&chip->client->dev, "%s: failed to get lux\n",
+			__func__);
+		return lux_val;
+	}
+
+	gain_trim_val = (unsigned int)(((chip->als_settings.als_cal_target)
+			* chip->als_settings.als_gain_trim) / lux_val);
+	if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
+		dev_err(&chip->client->dev,
+			"%s: trim_val of %d is not within the range [250, 4000]\n",
+			__func__, gain_trim_val);
+		return -ENODATA;
+	}
+
+	chip->als_settings.als_gain_trim = (int)gain_trim_val;
+
+	return 0;
+}
+
+static int tsl2583_set_als_time(struct tsl2583_chip *chip)
+{
+	int als_count, als_time, ret;
+	u8 val;
+
+	/* determine als integration register */
+	als_count = (chip->als_settings.als_time * 100 + 135) / 270;
+	if (!als_count)
+		als_count = 1; /* ensure at least one cycle */
+
+	/* convert back to time (encompasses overrides) */
+	als_time = (als_count * 27 + 5) / 10;
+
+	val = 256 - als_count;
+	ret = i2c_smbus_write_byte_data(chip->client,
+					TSL2583_CMD_REG | TSL2583_ALS_TIME,
+					val);
+	if (ret < 0) {
+		dev_err(&chip->client->dev, "%s: failed to set the als time to %d\n",
+			__func__, val);
+		return ret;
+	}
+
+	/* set chip struct re scaling and saturation */
+	chip->als_saturation = als_count * 922; /* 90% of full scale */
+	chip->als_time_scale = (als_time + 25) / 50;
+
+	return ret;
+}
+
+static int tsl2583_set_als_gain(struct tsl2583_chip *chip)
+{
+	int ret;
+
+	/* Set the gain based on als_settings struct */
+	ret = i2c_smbus_write_byte_data(chip->client,
+					TSL2583_CMD_REG | TSL2583_GAIN,
+					chip->als_settings.als_gain);
+	if (ret < 0)
+		dev_err(&chip->client->dev,
+			"%s: failed to set the gain to %d\n", __func__,
+			chip->als_settings.als_gain);
+
+	return ret;
+}
+
+static int tsl2583_set_power_state(struct tsl2583_chip *chip, u8 state)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(chip->client,
+					TSL2583_CMD_REG | TSL2583_CNTRL, state);
+	if (ret < 0)
+		dev_err(&chip->client->dev,
+			"%s: failed to set the power state to %d\n", __func__,
+			state);
+
+	return ret;
+}
+
+/*
+ * Turn the device on.
+ * Configuration must be set before calling this function.
+ */
+static int tsl2583_chip_init_and_power_on(struct iio_dev *indio_dev)
+{
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int ret;
+
+	/* Power on the device; ADC off. */
+	ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_smbus_write_byte_data(chip->client,
+					TSL2583_CMD_REG | TSL2583_INTERRUPT,
+					TSL2583_INTERRUPT_DISABLED);
+	if (ret < 0) {
+		dev_err(&chip->client->dev,
+			"%s: failed to disable interrupts\n", __func__);
+		return ret;
+	}
+
+	ret = tsl2583_set_als_time(chip);
+	if (ret < 0)
+		return ret;
+
+	ret = tsl2583_set_als_gain(chip);
+	if (ret < 0)
+		return ret;
+
+	usleep_range(3000, 3500);
+
+	ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_ON |
+					    TSL2583_CNTL_ADC_ENBL);
+	if (ret < 0)
+		return ret;
+
+	chip->suspended = false;
+
+	return ret;
+}
+
+/* Sysfs Interface Functions */
+
+static ssize_t in_illuminance_input_target_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&chip->als_mutex);
+	ret = sprintf(buf, "%d\n", chip->als_settings.als_cal_target);
+	mutex_unlock(&chip->als_mutex);
+
+	return ret;
+}
+
+static ssize_t in_illuminance_input_target_store(struct device *dev,
+						 struct device_attribute *attr,
+						 const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int value;
+
+	if (kstrtoint(buf, 0, &value) || !value)
+		return -EINVAL;
+
+	mutex_lock(&chip->als_mutex);
+	chip->als_settings.als_cal_target = value;
+	mutex_unlock(&chip->als_mutex);
+
+	return len;
+}
+
+static ssize_t in_illuminance_calibrate_store(struct device *dev,
+					      struct device_attribute *attr,
+					      const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int value, ret;
+
+	if (kstrtoint(buf, 0, &value) || value != 1)
+		return -EINVAL;
+
+	mutex_lock(&chip->als_mutex);
+
+	if (chip->suspended) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	ret = tsl2583_als_calibrate(indio_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = len;
+done:
+	mutex_unlock(&chip->als_mutex);
+
+	return ret;
+}
+
+static ssize_t in_illuminance_lux_table_show(struct device *dev,
+					     struct device_attribute *attr,
+					     char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	unsigned int i;
+	int offset = 0;
+
+	for (i = 0; i < ARRAY_SIZE(chip->als_settings.als_device_lux); i++) {
+		offset += sprintf(buf + offset, "%u,%u,%u,",
+				  chip->als_settings.als_device_lux[i].ratio,
+				  chip->als_settings.als_device_lux[i].ch0,
+				  chip->als_settings.als_device_lux[i].ch1);
+		if (chip->als_settings.als_device_lux[i].ratio == 0) {
+			/*
+			 * We just printed the first "0" entry.
+			 * Now get rid of the extra "," and break.
+			 */
+			offset--;
+			break;
+		}
+	}
+
+	offset += sprintf(buf + offset, "\n");
+
+	return offset;
+}
+
+static ssize_t in_illuminance_lux_table_store(struct device *dev,
+					      struct device_attribute *attr,
+					      const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	const unsigned int max_ints = TSL2583_MAX_LUX_TABLE_ENTRIES * 3;
+	int value[TSL2583_MAX_LUX_TABLE_ENTRIES * 3 + 1];
+	int ret = -EINVAL;
+	unsigned int n;
+
+	mutex_lock(&chip->als_mutex);
+
+	get_options(buf, ARRAY_SIZE(value), value);
+
+	/*
+	 * We now have an array of ints starting at value[1], and
+	 * enumerated by value[0].
+	 * We expect each group of three ints is one table entry,
+	 * and the last table entry is all 0.
+	 */
+	n = value[0];
+	if ((n % 3) || n < 6 || n > max_ints) {
+		dev_err(dev,
+			"%s: The number of entries in the lux table must be a multiple of 3 and within the range [6, %d]\n",
+			__func__, max_ints);
+		goto done;
+	}
+	if ((value[n - 2] | value[n - 1] | value[n]) != 0) {
+		dev_err(dev, "%s: The last 3 entries in the lux table must be zeros.\n",
+			__func__);
+		goto done;
+	}
+
+	memcpy(chip->als_settings.als_device_lux, &value[1],
+	       value[0] * sizeof(value[1]));
+
+	ret = len;
+
+done:
+	mutex_unlock(&chip->als_mutex);
+
+	return ret;
+}
+
+static IIO_CONST_ATTR(in_illuminance_calibscale_available, "1 8 16 111");
+static IIO_CONST_ATTR(in_illuminance_integration_time_available,
+		      "0.000050 0.000100 0.000150 0.000200 0.000250 0.000300 0.000350 0.000400 0.000450 0.000500 0.000550 0.000600 0.000650");
+static IIO_DEVICE_ATTR_RW(in_illuminance_input_target, 0);
+static IIO_DEVICE_ATTR_WO(in_illuminance_calibrate, 0);
+static IIO_DEVICE_ATTR_RW(in_illuminance_lux_table, 0);
+
+static struct attribute *sysfs_attrs_ctrl[] = {
+	&iio_const_attr_in_illuminance_calibscale_available.dev_attr.attr,
+	&iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
+	&iio_dev_attr_in_illuminance_input_target.dev_attr.attr,
+	&iio_dev_attr_in_illuminance_calibrate.dev_attr.attr,
+	&iio_dev_attr_in_illuminance_lux_table.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group tsl2583_attribute_group = {
+	.attrs = sysfs_attrs_ctrl,
+};
+
+static const struct iio_chan_spec tsl2583_channels[] = {
+	{
+		.type = IIO_LIGHT,
+		.modified = 1,
+		.channel2 = IIO_MOD_LIGHT_IR,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	},
+	{
+		.type = IIO_LIGHT,
+		.modified = 1,
+		.channel2 = IIO_MOD_LIGHT_BOTH,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+	},
+	{
+		.type = IIO_LIGHT,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+				      BIT(IIO_CHAN_INFO_CALIBBIAS) |
+				      BIT(IIO_CHAN_INFO_CALIBSCALE) |
+				      BIT(IIO_CHAN_INFO_INT_TIME),
+	},
+};
+
+static int tsl2583_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	mutex_lock(&chip->als_mutex);
+
+	if (chip->suspended) {
+		ret = -EBUSY;
+		goto read_done;
+	}
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (chan->type == IIO_LIGHT) {
+			ret = tsl2583_get_lux(indio_dev);
+			if (ret < 0)
+				goto read_done;
+
+			/*
+			 * From page 20 of the TSL2581, TSL2583 data
+			 * sheet (TAOS134 − MARCH 2011):
+			 *
+			 * One of the photodiodes (channel 0) is
+			 * sensitive to both visible and infrared light,
+			 * while the second photodiode (channel 1) is
+			 * sensitive primarily to infrared light.
+			 */
+			if (chan->channel2 == IIO_MOD_LIGHT_BOTH)
+				*val = chip->als_cur_info.als_ch0;
+			else
+				*val = chip->als_cur_info.als_ch1;
+
+			ret = IIO_VAL_INT;
+		}
+		break;
+	case IIO_CHAN_INFO_PROCESSED:
+		if (chan->type == IIO_LIGHT) {
+			ret = tsl2583_get_lux(indio_dev);
+			if (ret < 0)
+				goto read_done;
+
+			*val = ret;
+			ret = IIO_VAL_INT;
+		}
+		break;
+	case IIO_CHAN_INFO_CALIBBIAS:
+		if (chan->type == IIO_LIGHT) {
+			*val = chip->als_settings.als_gain_trim;
+			ret = IIO_VAL_INT;
+		}
+		break;
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (chan->type == IIO_LIGHT) {
+			*val = gainadj[chip->als_settings.als_gain].mean;
+			ret = IIO_VAL_INT;
+		}
+		break;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (chan->type == IIO_LIGHT) {
+			*val = 0;
+			*val2 = chip->als_settings.als_time;
+			ret = IIO_VAL_INT_PLUS_MICRO;
+		}
+		break;
+	default:
+		break;
+	}
+
+read_done:
+	mutex_unlock(&chip->als_mutex);
+
+	return ret;
+}
+
+static int tsl2583_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int ret = -EINVAL;
+
+	mutex_lock(&chip->als_mutex);
+
+	if (chip->suspended) {
+		ret = -EBUSY;
+		goto write_done;
+	}
+
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBBIAS:
+		if (chan->type == IIO_LIGHT) {
+			chip->als_settings.als_gain_trim = val;
+			ret = 0;
+		}
+		break;
+	case IIO_CHAN_INFO_CALIBSCALE:
+		if (chan->type == IIO_LIGHT) {
+			unsigned int i;
+
+			for (i = 0; i < ARRAY_SIZE(gainadj); i++) {
+				if (gainadj[i].mean == val) {
+					chip->als_settings.als_gain = i;
+					ret = tsl2583_set_als_gain(chip);
+					break;
+				}
+			}
+		}
+		break;
+	case IIO_CHAN_INFO_INT_TIME:
+		if (chan->type == IIO_LIGHT && !val && val2 >= 50 &&
+		    val2 <= 650 && !(val2 % 50)) {
+			chip->als_settings.als_time = val2;
+			ret = tsl2583_set_als_time(chip);
+		}
+		break;
+	default:
+		break;
+	}
+
+write_done:
+	mutex_unlock(&chip->als_mutex);
+
+	return ret;
+}
+
+static const struct iio_info tsl2583_info = {
+	.attrs = &tsl2583_attribute_group,
+	.driver_module = THIS_MODULE,
+	.read_raw = tsl2583_read_raw,
+	.write_raw = tsl2583_write_raw,
+};
+
+static int tsl2583_probe(struct i2c_client *clientp,
+			 const struct i2c_device_id *idp)
+{
+	int ret;
+	struct tsl2583_chip *chip;
+	struct iio_dev *indio_dev;
+
+	if (!i2c_check_functionality(clientp->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&clientp->dev, "%s: i2c smbus byte data functionality is unsupported\n",
+			__func__);
+		return -EOPNOTSUPP;
+	}
+
+	indio_dev = devm_iio_device_alloc(&clientp->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	chip = iio_priv(indio_dev);
+	chip->client = clientp;
+	i2c_set_clientdata(clientp, indio_dev);
+
+	mutex_init(&chip->als_mutex);
+	chip->suspended = true;
+
+	ret = i2c_smbus_read_byte_data(clientp,
+				       TSL2583_CMD_REG | TSL2583_CHIPID);
+	if (ret < 0) {
+		dev_err(&clientp->dev,
+			"%s: failed to read the chip ID register\n", __func__);
+		return ret;
+	}
+
+	if ((ret & TSL2583_CHIP_ID_MASK) != TSL2583_CHIP_ID) {
+		dev_err(&clientp->dev, "%s: received an unknown chip ID %x\n",
+			__func__, ret);
+		return -EINVAL;
+	}
+
+	indio_dev->info = &tsl2583_info;
+	indio_dev->channels = tsl2583_channels;
+	indio_dev->num_channels = ARRAY_SIZE(tsl2583_channels);
+	indio_dev->dev.parent = &clientp->dev;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->name = chip->client->name;
+
+	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
+	if (ret) {
+		dev_err(&clientp->dev, "%s: iio registration failed\n",
+			__func__);
+		return ret;
+	}
+
+	/* Load up the V2 defaults (these are hard coded defaults for now) */
+	tsl2583_defaults(chip);
+
+	/* Make sure the chip is on */
+	ret = tsl2583_chip_init_and_power_on(indio_dev);
+	if (ret < 0)
+		return ret;
+
+	dev_info(&clientp->dev, "Light sensor found.\n");
+
+	return 0;
+}
+
+static int __maybe_unused tsl2583_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&chip->als_mutex);
+
+	ret = tsl2583_set_power_state(chip, TSL2583_CNTL_PWR_OFF);
+	chip->suspended = true;
+
+	mutex_unlock(&chip->als_mutex);
+
+	return ret;
+}
+
+static int __maybe_unused tsl2583_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+	struct tsl2583_chip *chip = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&chip->als_mutex);
+
+	ret = tsl2583_chip_init_and_power_on(indio_dev);
+
+	mutex_unlock(&chip->als_mutex);
+
+	return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(tsl2583_pm_ops, tsl2583_suspend, tsl2583_resume);
+
+static struct i2c_device_id tsl2583_idtable[] = {
+	{ "tsl2580", 0 },
+	{ "tsl2581", 1 },
+	{ "tsl2583", 2 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tsl2583_idtable);
+
+static const struct of_device_id tsl2583_of_match[] = {
+	{ .compatible = "amstaos,tsl2580", },
+	{ .compatible = "amstaos,tsl2581", },
+	{ .compatible = "amstaos,tsl2583", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tsl2583_of_match);
+
+/* Driver definition */
+static struct i2c_driver tsl2583_driver = {
+	.driver = {
+		.name = "tsl2583",
+		.pm = &tsl2583_pm_ops,
+		.of_match_table = tsl2583_of_match,
+	},
+	.id_table = tsl2583_idtable,
+	.probe = tsl2583_probe,
+};
+module_i2c_driver(tsl2583_driver);
+
+MODULE_AUTHOR("J. August Brenner <jbrenner@taosinc.com>");
+MODULE_AUTHOR("Brian Masney <masneyb@onstation.org>");
+MODULE_DESCRIPTION("TAOS tsl2583 ambient light sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/magnetometer/ak8974.c linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/ak8974.c
--- linux-libre-4.9-gnu/drivers/iio/magnetometer/ak8974.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/ak8974.c	2017-02-12 16:03:20.000000000 -0500
@@ -287,7 +287,7 @@ static int ak8974_await_drdy(struct ak89
 	return 0;
 }
 
-static int ak8974_getresult(struct ak8974 *ak8974, s16 *result)
+static int ak8974_getresult(struct ak8974 *ak8974, __le16 *result)
 {
 	unsigned int src;
 	int ret;
@@ -395,7 +395,7 @@ static int ak8974_selftest(struct ak8974
 static int ak8974_get_u16_val(struct ak8974 *ak8974, u8 reg, u16 *val)
 {
 	int ret;
-	u16 bulk;
+	__le16 bulk;
 
 	ret = regmap_bulk_read(ak8974->map, reg, &bulk, 2);
 	if (ret)
@@ -453,7 +453,7 @@ static int ak8974_read_raw(struct iio_de
 			   long mask)
 {
 	struct ak8974 *ak8974 = iio_priv(indio_dev);
-	s16 hw_values[3];
+	__le16 hw_values[3];
 	int ret = -EINVAL;
 
 	pm_runtime_get_sync(&ak8974->i2c->dev);
@@ -494,7 +494,7 @@ static void ak8974_fill_buffer(struct ii
 {
 	struct ak8974 *ak8974 = iio_priv(indio_dev);
 	int ret;
-	s16 hw_values[8]; /* Three axes + 64bit padding */
+	__le16 hw_values[8]; /* Three axes + 64bit padding */
 
 	pm_runtime_get_sync(&ak8974->i2c->dev);
 	mutex_lock(&ak8974->lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/magnetometer/ak8975.c linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/ak8975.c
--- linux-libre-4.9-gnu/drivers/iio/magnetometer/ak8975.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/ak8975.c	2017-02-12 16:03:20.000000000 -0500
@@ -690,6 +690,7 @@ static int ak8975_read_axis(struct iio_d
 	struct ak8975_data *data = iio_priv(indio_dev);
 	const struct i2c_client *client = data->client;
 	const struct ak_def *def = data->def;
+	__le16 rval;
 	u16 buff;
 	int ret;
 
@@ -703,7 +704,7 @@ static int ak8975_read_axis(struct iio_d
 
 	ret = i2c_smbus_read_i2c_block_data_or_emulated(
 			client, def->data_regs[index],
-			sizeof(buff), (u8*)&buff);
+			sizeof(rval), (u8*)&rval);
 	if (ret < 0)
 		goto exit;
 
@@ -713,7 +714,7 @@ static int ak8975_read_axis(struct iio_d
 	pm_runtime_put_autosuspend(&data->client->dev);
 
 	/* Swap bytes and convert to valid range. */
-	buff = le16_to_cpu(buff);
+	buff = le16_to_cpu(rval);
 	*val = clamp_t(s16, buff, -def->range, def->range);
 	return IIO_VAL_INT;
 
@@ -813,6 +814,7 @@ static void ak8975_fill_buffer(struct ii
 	const struct ak_def *def = data->def;
 	int ret;
 	s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */
+	__le16 fval[3];
 
 	mutex_lock(&data->lock);
 
@@ -826,17 +828,17 @@ static void ak8975_fill_buffer(struct ii
 	 */
 	ret = i2c_smbus_read_i2c_block_data_or_emulated(client,
 							def->data_regs[0],
-							3 * sizeof(buff[0]),
-							(u8 *)buff);
+							3 * sizeof(fval[0]),
+							(u8 *)fval);
 	if (ret < 0)
 		goto unlock;
 
 	mutex_unlock(&data->lock);
 
 	/* Clamp to valid range. */
-	buff[0] = clamp_t(s16, le16_to_cpu(buff[0]), -def->range, def->range);
-	buff[1] = clamp_t(s16, le16_to_cpu(buff[1]), -def->range, def->range);
-	buff[2] = clamp_t(s16, le16_to_cpu(buff[2]), -def->range, def->range);
+	buff[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range);
+	buff[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range);
+	buff[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range);
 
 	iio_push_to_buffers_with_timestamp(indio_dev, buff,
 					   iio_get_time_ns(indio_dev));
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c
--- linux-libre-4.9-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/hid-sensor-magn-3d.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,9 +42,17 @@ enum magn_3d_channel {
 	MAGN_3D_CHANNEL_MAX,
 };
 
+struct common_attributes {
+	int scale_pre_decml;
+	int scale_post_decml;
+	int scale_precision;
+	int value_offset;
+};
+
 struct magn_3d_state {
 	struct hid_sensor_hub_callbacks callbacks;
-	struct hid_sensor_common common_attributes;
+	struct hid_sensor_common magn_flux_attributes;
+	struct hid_sensor_common rot_attributes;
 	struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX];
 
 	/* dynamically sized array to hold sensor values */
@@ -52,10 +60,8 @@ struct magn_3d_state {
 	/* array of pointers to sensor value */
 	u32 *magn_val_addr[MAGN_3D_CHANNEL_MAX];
 
-	int scale_pre_decml;
-	int scale_post_decml;
-	int scale_precision;
-	int value_offset;
+	struct common_attributes magn_flux_attr;
+	struct common_attributes rot_attr;
 };
 
 static const u32 magn_3d_addresses[MAGN_3D_CHANNEL_MAX] = {
@@ -162,41 +168,74 @@ static int magn_3d_read_raw(struct iio_d
 	*val2 = 0;
 	switch (mask) {
 	case 0:
-		hid_sensor_power_state(&magn_state->common_attributes, true);
+		hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
 		report_id =
 			magn_state->magn[chan->address].report_id;
 		address = magn_3d_addresses[chan->address];
 		if (report_id >= 0)
 			*val = sensor_hub_input_attr_get_raw_value(
-				magn_state->common_attributes.hsdev,
+				magn_state->magn_flux_attributes.hsdev,
 				HID_USAGE_SENSOR_COMPASS_3D, address,
 				report_id,
 				SENSOR_HUB_SYNC);
 		else {
 			*val = 0;
-			hid_sensor_power_state(&magn_state->common_attributes,
-						false);
+			hid_sensor_power_state(
+				&magn_state->magn_flux_attributes,
+				false);
 			return -EINVAL;
 		}
-		hid_sensor_power_state(&magn_state->common_attributes, false);
+		hid_sensor_power_state(&magn_state->magn_flux_attributes,
+					false);
 		ret_type = IIO_VAL_INT;
 		break;
 	case IIO_CHAN_INFO_SCALE:
-		*val = magn_state->scale_pre_decml;
-		*val2 = magn_state->scale_post_decml;
-		ret_type = magn_state->scale_precision;
+		switch (chan->type) {
+		case IIO_MAGN:
+			*val = magn_state->magn_flux_attr.scale_pre_decml;
+			*val2 = magn_state->magn_flux_attr.scale_post_decml;
+			ret_type = magn_state->magn_flux_attr.scale_precision;
+			break;
+		case IIO_ROT:
+			*val = magn_state->rot_attr.scale_pre_decml;
+			*val2 = magn_state->rot_attr.scale_post_decml;
+			ret_type = magn_state->rot_attr.scale_precision;
+			break;
+		default:
+			ret_type = -EINVAL;
+		}
 		break;
 	case IIO_CHAN_INFO_OFFSET:
-		*val = magn_state->value_offset;
-		ret_type = IIO_VAL_INT;
+		switch (chan->type) {
+		case IIO_MAGN:
+			*val = magn_state->magn_flux_attr.value_offset;
+			ret_type = IIO_VAL_INT;
+			break;
+		case IIO_ROT:
+			*val = magn_state->rot_attr.value_offset;
+			ret_type = IIO_VAL_INT;
+			break;
+		default:
+			ret_type = -EINVAL;
+		}
 		break;
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		ret_type = hid_sensor_read_samp_freq_value(
-			&magn_state->common_attributes, val, val2);
+			&magn_state->magn_flux_attributes, val, val2);
 		break;
 	case IIO_CHAN_INFO_HYSTERESIS:
-		ret_type = hid_sensor_read_raw_hyst_value(
-			&magn_state->common_attributes, val, val2);
+		switch (chan->type) {
+		case IIO_MAGN:
+			ret_type = hid_sensor_read_raw_hyst_value(
+				&magn_state->magn_flux_attributes, val, val2);
+			break;
+		case IIO_ROT:
+			ret_type = hid_sensor_read_raw_hyst_value(
+				&magn_state->rot_attributes, val, val2);
+			break;
+		default:
+			ret_type = -EINVAL;
+		}
 		break;
 	default:
 		ret_type = -EINVAL;
@@ -219,11 +258,21 @@ static int magn_3d_write_raw(struct iio_
 	switch (mask) {
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		ret = hid_sensor_write_samp_freq_value(
-				&magn_state->common_attributes, val, val2);
+				&magn_state->magn_flux_attributes, val, val2);
 		break;
 	case IIO_CHAN_INFO_HYSTERESIS:
-		ret = hid_sensor_write_raw_hyst_value(
-				&magn_state->common_attributes, val, val2);
+		switch (chan->type) {
+		case IIO_MAGN:
+			ret = hid_sensor_write_raw_hyst_value(
+				&magn_state->magn_flux_attributes, val, val2);
+			break;
+		case IIO_ROT:
+			ret = hid_sensor_write_raw_hyst_value(
+				&magn_state->rot_attributes, val, val2);
+			break;
+		default:
+			ret = -EINVAL;
+		}
 		break;
 	default:
 		ret = -EINVAL;
@@ -254,7 +303,7 @@ static int magn_3d_proc_event(struct hid
 	struct magn_3d_state *magn_state = iio_priv(indio_dev);
 
 	dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n");
-	if (atomic_read(&magn_state->common_attributes.data_ready))
+	if (atomic_read(&magn_state->magn_flux_attributes.data_ready))
 		hid_sensor_push_data(indio_dev, magn_state->iio_vals);
 
 	return 0;
@@ -389,21 +438,48 @@ static int magn_3d_parse_report(struct p
 	dev_dbg(&pdev->dev, "magn_3d Setup %d IIO channels\n",
 			*chan_count);
 
-	st->scale_precision = hid_sensor_format_scale(
+	st->magn_flux_attr.scale_precision = hid_sensor_format_scale(
 				HID_USAGE_SENSOR_COMPASS_3D,
 				&st->magn[CHANNEL_SCAN_INDEX_X],
-				&st->scale_pre_decml, &st->scale_post_decml);
+				&st->magn_flux_attr.scale_pre_decml,
+				&st->magn_flux_attr.scale_post_decml);
+	st->rot_attr.scale_precision
+		= hid_sensor_format_scale(
+			HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH,
+			&st->magn[CHANNEL_SCAN_INDEX_NORTH_MAGN_TILT_COMP],
+			&st->rot_attr.scale_pre_decml,
+			&st->rot_attr.scale_post_decml);
 
 	/* Set Sensitivity field ids, when there is no individual modifier */
-	if (st->common_attributes.sensitivity.index < 0) {
+	if (st->magn_flux_attributes.sensitivity.index < 0) {
 		sensor_hub_input_get_attribute_info(hsdev,
 			HID_FEATURE_REPORT, usage_id,
 			HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
 			HID_USAGE_SENSOR_DATA_ORIENTATION,
-			&st->common_attributes.sensitivity);
+			&st->magn_flux_attributes.sensitivity);
 		dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n",
-			st->common_attributes.sensitivity.index,
-			st->common_attributes.sensitivity.report_id);
+			st->magn_flux_attributes.sensitivity.index,
+			st->magn_flux_attributes.sensitivity.report_id);
+	}
+	if (st->magn_flux_attributes.sensitivity.index < 0) {
+		sensor_hub_input_get_attribute_info(hsdev,
+			HID_FEATURE_REPORT, usage_id,
+			HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
+			HID_USAGE_SENSOR_ORIENT_MAGN_FLUX,
+			&st->magn_flux_attributes.sensitivity);
+		dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n",
+			st->magn_flux_attributes.sensitivity.index,
+			st->magn_flux_attributes.sensitivity.report_id);
+	}
+	if (st->rot_attributes.sensitivity.index < 0) {
+		sensor_hub_input_get_attribute_info(hsdev,
+			HID_FEATURE_REPORT, usage_id,
+			HID_USAGE_SENSOR_DATA_MOD_CHANGE_SENSITIVITY_ABS |
+			HID_USAGE_SENSOR_ORIENT_COMP_MAGN_NORTH,
+			&st->rot_attributes.sensitivity);
+		dev_dbg(&pdev->dev, "Sensitivity index:report %d:%d\n",
+			st->rot_attributes.sensitivity.index,
+			st->rot_attributes.sensitivity.report_id);
 	}
 
 	return 0;
@@ -428,16 +504,17 @@ static int hid_magn_3d_probe(struct plat
 	platform_set_drvdata(pdev, indio_dev);
 
 	magn_state = iio_priv(indio_dev);
-	magn_state->common_attributes.hsdev = hsdev;
-	magn_state->common_attributes.pdev = pdev;
+	magn_state->magn_flux_attributes.hsdev = hsdev;
+	magn_state->magn_flux_attributes.pdev = pdev;
 
 	ret = hid_sensor_parse_common_attributes(hsdev,
 				HID_USAGE_SENSOR_COMPASS_3D,
-				&magn_state->common_attributes);
+				&magn_state->magn_flux_attributes);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to setup common attributes\n");
 		return ret;
 	}
+	magn_state->rot_attributes = magn_state->magn_flux_attributes;
 
 	ret = magn_3d_parse_report(pdev, hsdev,
 				&channels, &chan_count,
@@ -460,9 +537,9 @@ static int hid_magn_3d_probe(struct plat
 		dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
 		return ret;
 	}
-	atomic_set(&magn_state->common_attributes.data_ready, 0);
+	atomic_set(&magn_state->magn_flux_attributes.data_ready, 0);
 	ret = hid_sensor_setup_trigger(indio_dev, name,
-					&magn_state->common_attributes);
+					&magn_state->magn_flux_attributes);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "trigger setup failed\n");
 		goto error_unreg_buffer_funcs;
@@ -489,7 +566,7 @@ static int hid_magn_3d_probe(struct plat
 error_iio_unreg:
 	iio_device_unregister(indio_dev);
 error_remove_trigger:
-	hid_sensor_remove_trigger(&magn_state->common_attributes);
+	hid_sensor_remove_trigger(&magn_state->magn_flux_attributes);
 error_unreg_buffer_funcs:
 	iio_triggered_buffer_cleanup(indio_dev);
 	return ret;
@@ -504,7 +581,7 @@ static int hid_magn_3d_remove(struct pla
 
 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
 	iio_device_unregister(indio_dev);
-	hid_sensor_remove_trigger(&magn_state->common_attributes);
+	hid_sensor_remove_trigger(&magn_state->magn_flux_attributes);
 	iio_triggered_buffer_cleanup(indio_dev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/magnetometer/st_magn_core.c linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/st_magn_core.c
--- linux-libre-4.9-gnu/drivers/iio/magnetometer/st_magn_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/magnetometer/st_magn_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,139 +46,12 @@
 #define ST_MAGN_FS_AVL_15000MG			15000
 #define ST_MAGN_FS_AVL_16000MG			16000
 
-/* CUSTOM VALUES FOR SENSOR 0 */
-#define ST_MAGN_0_ODR_ADDR			0x00
-#define ST_MAGN_0_ODR_MASK			0x1c
-#define ST_MAGN_0_ODR_AVL_1HZ_VAL		0x00
-#define ST_MAGN_0_ODR_AVL_2HZ_VAL		0x01
-#define ST_MAGN_0_ODR_AVL_3HZ_VAL		0x02
-#define ST_MAGN_0_ODR_AVL_8HZ_VAL		0x03
-#define ST_MAGN_0_ODR_AVL_15HZ_VAL		0x04
-#define ST_MAGN_0_ODR_AVL_30HZ_VAL		0x05
-#define ST_MAGN_0_ODR_AVL_75HZ_VAL		0x06
-#define ST_MAGN_0_ODR_AVL_220HZ_VAL		0x07
-#define ST_MAGN_0_PW_ADDR			0x02
-#define ST_MAGN_0_PW_MASK			0x03
-#define ST_MAGN_0_PW_ON				0x00
-#define ST_MAGN_0_PW_OFF			0x03
-#define ST_MAGN_0_FS_ADDR			0x01
-#define ST_MAGN_0_FS_MASK			0xe0
-#define ST_MAGN_0_FS_AVL_1300_VAL		0x01
-#define ST_MAGN_0_FS_AVL_1900_VAL		0x02
-#define ST_MAGN_0_FS_AVL_2500_VAL		0x03
-#define ST_MAGN_0_FS_AVL_4000_VAL		0x04
-#define ST_MAGN_0_FS_AVL_4700_VAL		0x05
-#define ST_MAGN_0_FS_AVL_5600_VAL		0x06
-#define ST_MAGN_0_FS_AVL_8100_VAL		0x07
-#define ST_MAGN_0_FS_AVL_1300_GAIN_XY		1100
-#define ST_MAGN_0_FS_AVL_1900_GAIN_XY		855
-#define ST_MAGN_0_FS_AVL_2500_GAIN_XY		670
-#define ST_MAGN_0_FS_AVL_4000_GAIN_XY		450
-#define ST_MAGN_0_FS_AVL_4700_GAIN_XY		400
-#define ST_MAGN_0_FS_AVL_5600_GAIN_XY		330
-#define ST_MAGN_0_FS_AVL_8100_GAIN_XY		230
-#define ST_MAGN_0_FS_AVL_1300_GAIN_Z		980
-#define ST_MAGN_0_FS_AVL_1900_GAIN_Z		760
-#define ST_MAGN_0_FS_AVL_2500_GAIN_Z		600
-#define ST_MAGN_0_FS_AVL_4000_GAIN_Z		400
-#define ST_MAGN_0_FS_AVL_4700_GAIN_Z		355
-#define ST_MAGN_0_FS_AVL_5600_GAIN_Z		295
-#define ST_MAGN_0_FS_AVL_8100_GAIN_Z		205
-#define ST_MAGN_0_MULTIREAD_BIT			false
-
-/* CUSTOM VALUES FOR SENSOR 1 */
-#define ST_MAGN_1_WAI_EXP			0x3c
-#define ST_MAGN_1_ODR_ADDR			0x00
-#define ST_MAGN_1_ODR_MASK			0x1c
-#define ST_MAGN_1_ODR_AVL_1HZ_VAL		0x00
-#define ST_MAGN_1_ODR_AVL_2HZ_VAL		0x01
-#define ST_MAGN_1_ODR_AVL_3HZ_VAL		0x02
-#define ST_MAGN_1_ODR_AVL_8HZ_VAL		0x03
-#define ST_MAGN_1_ODR_AVL_15HZ_VAL		0x04
-#define ST_MAGN_1_ODR_AVL_30HZ_VAL		0x05
-#define ST_MAGN_1_ODR_AVL_75HZ_VAL		0x06
-#define ST_MAGN_1_ODR_AVL_220HZ_VAL		0x07
-#define ST_MAGN_1_PW_ADDR			0x02
-#define ST_MAGN_1_PW_MASK			0x03
-#define ST_MAGN_1_PW_ON				0x00
-#define ST_MAGN_1_PW_OFF			0x03
-#define ST_MAGN_1_FS_ADDR			0x01
-#define ST_MAGN_1_FS_MASK			0xe0
-#define ST_MAGN_1_FS_AVL_1300_VAL		0x01
-#define ST_MAGN_1_FS_AVL_1900_VAL		0x02
-#define ST_MAGN_1_FS_AVL_2500_VAL		0x03
-#define ST_MAGN_1_FS_AVL_4000_VAL		0x04
-#define ST_MAGN_1_FS_AVL_4700_VAL		0x05
-#define ST_MAGN_1_FS_AVL_5600_VAL		0x06
-#define ST_MAGN_1_FS_AVL_8100_VAL		0x07
-#define ST_MAGN_1_FS_AVL_1300_GAIN_XY		909
-#define ST_MAGN_1_FS_AVL_1900_GAIN_XY		1169
-#define ST_MAGN_1_FS_AVL_2500_GAIN_XY		1492
-#define ST_MAGN_1_FS_AVL_4000_GAIN_XY		2222
-#define ST_MAGN_1_FS_AVL_4700_GAIN_XY		2500
-#define ST_MAGN_1_FS_AVL_5600_GAIN_XY		3030
-#define ST_MAGN_1_FS_AVL_8100_GAIN_XY		4347
-#define ST_MAGN_1_FS_AVL_1300_GAIN_Z		1020
-#define ST_MAGN_1_FS_AVL_1900_GAIN_Z		1315
-#define ST_MAGN_1_FS_AVL_2500_GAIN_Z		1666
-#define ST_MAGN_1_FS_AVL_4000_GAIN_Z		2500
-#define ST_MAGN_1_FS_AVL_4700_GAIN_Z		2816
-#define ST_MAGN_1_FS_AVL_5600_GAIN_Z		3389
-#define ST_MAGN_1_FS_AVL_8100_GAIN_Z		4878
-#define ST_MAGN_1_MULTIREAD_BIT			false
-
-/* CUSTOM VALUES FOR SENSOR 2 */
-#define ST_MAGN_2_WAI_EXP			0x3d
-#define ST_MAGN_2_ODR_ADDR			0x20
-#define ST_MAGN_2_ODR_MASK			0x1c
-#define ST_MAGN_2_ODR_AVL_1HZ_VAL		0x00
-#define ST_MAGN_2_ODR_AVL_2HZ_VAL		0x01
-#define ST_MAGN_2_ODR_AVL_3HZ_VAL		0x02
-#define ST_MAGN_2_ODR_AVL_5HZ_VAL		0x03
-#define ST_MAGN_2_ODR_AVL_10HZ_VAL		0x04
-#define ST_MAGN_2_ODR_AVL_20HZ_VAL		0x05
-#define ST_MAGN_2_ODR_AVL_40HZ_VAL		0x06
-#define ST_MAGN_2_ODR_AVL_80HZ_VAL		0x07
-#define ST_MAGN_2_PW_ADDR			0x22
-#define ST_MAGN_2_PW_MASK			0x03
-#define ST_MAGN_2_PW_ON				0x00
-#define ST_MAGN_2_PW_OFF			0x03
-#define ST_MAGN_2_FS_ADDR			0x21
-#define ST_MAGN_2_FS_MASK			0x60
-#define ST_MAGN_2_FS_AVL_4000_VAL		0x00
-#define ST_MAGN_2_FS_AVL_8000_VAL		0x01
-#define ST_MAGN_2_FS_AVL_12000_VAL		0x02
-#define ST_MAGN_2_FS_AVL_16000_VAL		0x03
-#define ST_MAGN_2_FS_AVL_4000_GAIN		146
-#define ST_MAGN_2_FS_AVL_8000_GAIN		292
-#define ST_MAGN_2_FS_AVL_12000_GAIN		438
-#define ST_MAGN_2_FS_AVL_16000_GAIN		584
-#define ST_MAGN_2_MULTIREAD_BIT			false
+/* Special L addresses for Sensor 2 */
 #define ST_MAGN_2_OUT_X_L_ADDR			0x28
 #define ST_MAGN_2_OUT_Y_L_ADDR			0x2a
 #define ST_MAGN_2_OUT_Z_L_ADDR			0x2c
 
-/* CUSTOM VALUES FOR SENSOR 3 */
-#define ST_MAGN_3_WAI_ADDR			0x4f
-#define ST_MAGN_3_WAI_EXP			0x40
-#define ST_MAGN_3_ODR_ADDR			0x60
-#define ST_MAGN_3_ODR_MASK			0x0c
-#define ST_MAGN_3_ODR_AVL_10HZ_VAL		0x00
-#define ST_MAGN_3_ODR_AVL_20HZ_VAL		0x01
-#define ST_MAGN_3_ODR_AVL_50HZ_VAL		0x02
-#define ST_MAGN_3_ODR_AVL_100HZ_VAL		0x03
-#define ST_MAGN_3_PW_ADDR			0x60
-#define ST_MAGN_3_PW_MASK			0x03
-#define ST_MAGN_3_PW_ON				0x00
-#define ST_MAGN_3_PW_OFF			0x03
-#define ST_MAGN_3_BDU_ADDR			0x62
-#define ST_MAGN_3_BDU_MASK			0x10
-#define ST_MAGN_3_DRDY_IRQ_ADDR			0x62
-#define ST_MAGN_3_DRDY_INT_MASK			0x01
-#define ST_MAGN_3_IHL_IRQ_ADDR			0x63
-#define ST_MAGN_3_IHL_IRQ_MASK			0x04
-#define ST_MAGN_3_FS_AVL_15000_GAIN		1500
-#define ST_MAGN_3_MULTIREAD_BIT			false
+/* Special L addresses for sensor 3 */
 #define ST_MAGN_3_OUT_X_L_ADDR			0x68
 #define ST_MAGN_3_OUT_Y_L_ADDR			0x6a
 #define ST_MAGN_3_OUT_Z_L_ADDR			0x6c
@@ -240,77 +113,78 @@ static const struct st_sensor_settings s
 		},
 		.ch = (struct iio_chan_spec *)st_magn_16bit_channels,
 		.odr = {
-			.addr = ST_MAGN_0_ODR_ADDR,
-			.mask = ST_MAGN_0_ODR_MASK,
+			.addr = 0x00,
+			.mask = 0x1c,
 			.odr_avl = {
-				{ 1, ST_MAGN_0_ODR_AVL_1HZ_VAL, },
-				{ 2, ST_MAGN_0_ODR_AVL_2HZ_VAL, },
-				{ 3, ST_MAGN_0_ODR_AVL_3HZ_VAL, },
-				{ 8, ST_MAGN_0_ODR_AVL_8HZ_VAL, },
-				{ 15, ST_MAGN_0_ODR_AVL_15HZ_VAL, },
-				{ 30, ST_MAGN_0_ODR_AVL_30HZ_VAL, },
-				{ 75, ST_MAGN_0_ODR_AVL_75HZ_VAL, },
+				{ .hz = 1, .value = 0x00 },
+				{ .hz = 2, .value = 0x01 },
+				{ .hz = 3, .value = 0x02 },
+				{ .hz = 8, .value = 0x03 },
+				{ .hz = 15, .value = 0x04 },
+				{ .hz = 30, .value = 0x05 },
+				{ .hz = 75, .value = 0x06 },
+				/* 220 Hz, 0x07 reportedly exist */
 			},
 		},
 		.pw = {
-			.addr = ST_MAGN_0_PW_ADDR,
-			.mask = ST_MAGN_0_PW_MASK,
-			.value_on = ST_MAGN_0_PW_ON,
-			.value_off = ST_MAGN_0_PW_OFF,
+			.addr = 0x02,
+			.mask = 0x03,
+			.value_on = 0x00,
+			.value_off = 0x03,
 		},
 		.fs = {
-			.addr = ST_MAGN_0_FS_ADDR,
-			.mask = ST_MAGN_0_FS_MASK,
+			.addr = 0x01,
+			.mask = 0xe0,
 			.fs_avl = {
 				[0] = {
 					.num = ST_MAGN_FS_AVL_1300MG,
-					.value = ST_MAGN_0_FS_AVL_1300_VAL,
-					.gain = ST_MAGN_0_FS_AVL_1300_GAIN_XY,
-					.gain2 = ST_MAGN_0_FS_AVL_1300_GAIN_Z,
+					.value = 0x01,
+					.gain = 1100,
+					.gain2 = 980,
 				},
 				[1] = {
 					.num = ST_MAGN_FS_AVL_1900MG,
-					.value = ST_MAGN_0_FS_AVL_1900_VAL,
-					.gain = ST_MAGN_0_FS_AVL_1900_GAIN_XY,
-					.gain2 = ST_MAGN_0_FS_AVL_1900_GAIN_Z,
+					.value = 0x02,
+					.gain = 855,
+					.gain2 = 760,
 				},
 				[2] = {
 					.num = ST_MAGN_FS_AVL_2500MG,
-					.value = ST_MAGN_0_FS_AVL_2500_VAL,
-					.gain = ST_MAGN_0_FS_AVL_2500_GAIN_XY,
-					.gain2 = ST_MAGN_0_FS_AVL_2500_GAIN_Z,
+					.value = 0x03,
+					.gain = 670,
+					.gain2 = 600,
 				},
 				[3] = {
 					.num = ST_MAGN_FS_AVL_4000MG,
-					.value = ST_MAGN_0_FS_AVL_4000_VAL,
-					.gain = ST_MAGN_0_FS_AVL_4000_GAIN_XY,
-					.gain2 = ST_MAGN_0_FS_AVL_4000_GAIN_Z,
+					.value = 0x04,
+					.gain = 450,
+					.gain2 = 400,
 				},
 				[4] = {
 					.num = ST_MAGN_FS_AVL_4700MG,
-					.value = ST_MAGN_0_FS_AVL_4700_VAL,
-					.gain = ST_MAGN_0_FS_AVL_4700_GAIN_XY,
-					.gain2 = ST_MAGN_0_FS_AVL_4700_GAIN_Z,
+					.value = 0x05,
+					.gain = 400,
+					.gain2 = 355,
 				},
 				[5] = {
 					.num = ST_MAGN_FS_AVL_5600MG,
-					.value = ST_MAGN_0_FS_AVL_5600_VAL,
-					.gain = ST_MAGN_0_FS_AVL_5600_GAIN_XY,
-					.gain2 = ST_MAGN_0_FS_AVL_5600_GAIN_Z,
+					.value = 0x06,
+					.gain = 330,
+					.gain2 = 295,
 				},
 				[6] = {
 					.num = ST_MAGN_FS_AVL_8100MG,
-					.value = ST_MAGN_0_FS_AVL_8100_VAL,
-					.gain = ST_MAGN_0_FS_AVL_8100_GAIN_XY,
-					.gain2 = ST_MAGN_0_FS_AVL_8100_GAIN_Z,
+					.value = 0x07,
+					.gain = 230,
+					.gain2 = 205,
 				},
 			},
 		},
-		.multi_read_bit = ST_MAGN_0_MULTIREAD_BIT,
+		.multi_read_bit = false,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_MAGN_1_WAI_EXP,
+		.wai = 0x3c,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LSM303DLHC_MAGN_DEV_NAME,
@@ -318,175 +192,175 @@ static const struct st_sensor_settings s
 		},
 		.ch = (struct iio_chan_spec *)st_magn_16bit_channels,
 		.odr = {
-			.addr = ST_MAGN_1_ODR_ADDR,
-			.mask = ST_MAGN_1_ODR_MASK,
+			.addr = 0x00,
+			.mask = 0x1c,
 			.odr_avl = {
-				{ 1, ST_MAGN_1_ODR_AVL_1HZ_VAL, },
-				{ 2, ST_MAGN_1_ODR_AVL_2HZ_VAL, },
-				{ 3, ST_MAGN_1_ODR_AVL_3HZ_VAL, },
-				{ 8, ST_MAGN_1_ODR_AVL_8HZ_VAL, },
-				{ 15, ST_MAGN_1_ODR_AVL_15HZ_VAL, },
-				{ 30, ST_MAGN_1_ODR_AVL_30HZ_VAL, },
-				{ 75, ST_MAGN_1_ODR_AVL_75HZ_VAL, },
-				{ 220, ST_MAGN_1_ODR_AVL_220HZ_VAL, },
+				{ .hz = 1, .value = 0x00 },
+				{ .hz = 2, .value = 0x01 },
+				{ .hz = 3, .value = 0x02 },
+				{ .hz = 8, .value = 0x03 },
+				{ .hz = 15, .value = 0x04 },
+				{ .hz = 30, .value = 0x05 },
+				{ .hz = 75, .value = 0x06 },
+				{ .hz = 220, .value = 0x07 },
 			},
 		},
 		.pw = {
-			.addr = ST_MAGN_1_PW_ADDR,
-			.mask = ST_MAGN_1_PW_MASK,
-			.value_on = ST_MAGN_1_PW_ON,
-			.value_off = ST_MAGN_1_PW_OFF,
+			.addr = 0x02,
+			.mask = 0x03,
+			.value_on = 0x00,
+			.value_off = 0x03,
 		},
 		.fs = {
-			.addr = ST_MAGN_1_FS_ADDR,
-			.mask = ST_MAGN_1_FS_MASK,
+			.addr = 0x01,
+			.mask = 0xe0,
 			.fs_avl = {
 				[0] = {
 					.num = ST_MAGN_FS_AVL_1300MG,
-					.value = ST_MAGN_1_FS_AVL_1300_VAL,
-					.gain = ST_MAGN_1_FS_AVL_1300_GAIN_XY,
-					.gain2 = ST_MAGN_1_FS_AVL_1300_GAIN_Z,
+					.value = 0x01,
+					.gain = 909,
+					.gain2 = 1020,
 				},
 				[1] = {
 					.num = ST_MAGN_FS_AVL_1900MG,
-					.value = ST_MAGN_1_FS_AVL_1900_VAL,
-					.gain = ST_MAGN_1_FS_AVL_1900_GAIN_XY,
-					.gain2 = ST_MAGN_1_FS_AVL_1900_GAIN_Z,
+					.value = 0x02,
+					.gain = 1169,
+					.gain2 = 1315,
 				},
 				[2] = {
 					.num = ST_MAGN_FS_AVL_2500MG,
-					.value = ST_MAGN_1_FS_AVL_2500_VAL,
-					.gain = ST_MAGN_1_FS_AVL_2500_GAIN_XY,
-					.gain2 = ST_MAGN_1_FS_AVL_2500_GAIN_Z,
+					.value = 0x03,
+					.gain = 1492,
+					.gain2 = 1666,
 				},
 				[3] = {
 					.num = ST_MAGN_FS_AVL_4000MG,
-					.value = ST_MAGN_1_FS_AVL_4000_VAL,
-					.gain = ST_MAGN_1_FS_AVL_4000_GAIN_XY,
-					.gain2 = ST_MAGN_1_FS_AVL_4000_GAIN_Z,
+					.value = 0x04,
+					.gain = 2222,
+					.gain2 = 2500,
 				},
 				[4] = {
 					.num = ST_MAGN_FS_AVL_4700MG,
-					.value = ST_MAGN_1_FS_AVL_4700_VAL,
-					.gain = ST_MAGN_1_FS_AVL_4700_GAIN_XY,
-					.gain2 = ST_MAGN_1_FS_AVL_4700_GAIN_Z,
+					.value = 0x05,
+					.gain = 2500,
+					.gain2 = 2816,
 				},
 				[5] = {
 					.num = ST_MAGN_FS_AVL_5600MG,
-					.value = ST_MAGN_1_FS_AVL_5600_VAL,
-					.gain = ST_MAGN_1_FS_AVL_5600_GAIN_XY,
-					.gain2 = ST_MAGN_1_FS_AVL_5600_GAIN_Z,
+					.value = 0x06,
+					.gain = 3030,
+					.gain2 = 3389,
 				},
 				[6] = {
 					.num = ST_MAGN_FS_AVL_8100MG,
-					.value = ST_MAGN_1_FS_AVL_8100_VAL,
-					.gain = ST_MAGN_1_FS_AVL_8100_GAIN_XY,
-					.gain2 = ST_MAGN_1_FS_AVL_8100_GAIN_Z,
+					.value = 0x07,
+					.gain = 4347,
+					.gain2 = 4878,
 				},
 			},
 		},
-		.multi_read_bit = ST_MAGN_1_MULTIREAD_BIT,
+		.multi_read_bit = false,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_MAGN_2_WAI_EXP,
+		.wai = 0x3d,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LIS3MDL_MAGN_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,
 		.odr = {
-			.addr = ST_MAGN_2_ODR_ADDR,
-			.mask = ST_MAGN_2_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x1c,
 			.odr_avl = {
-				{ 1, ST_MAGN_2_ODR_AVL_1HZ_VAL, },
-				{ 2, ST_MAGN_2_ODR_AVL_2HZ_VAL, },
-				{ 3, ST_MAGN_2_ODR_AVL_3HZ_VAL, },
-				{ 5, ST_MAGN_2_ODR_AVL_5HZ_VAL, },
-				{ 10, ST_MAGN_2_ODR_AVL_10HZ_VAL, },
-				{ 20, ST_MAGN_2_ODR_AVL_20HZ_VAL, },
-				{ 40, ST_MAGN_2_ODR_AVL_40HZ_VAL, },
-				{ 80, ST_MAGN_2_ODR_AVL_80HZ_VAL, },
+				{ .hz = 1, .value = 0x00 },
+				{ .hz = 2, .value = 0x01 },
+				{ .hz = 3, .value = 0x02 },
+				{ .hz = 5, .value = 0x03 },
+				{ .hz = 10, .value = 0x04 },
+				{ .hz = 20, .value = 0x05 },
+				{ .hz = 40, .value = 0x06 },
+				{ .hz = 80, .value = 0x07 },
 			},
 		},
 		.pw = {
-			.addr = ST_MAGN_2_PW_ADDR,
-			.mask = ST_MAGN_2_PW_MASK,
-			.value_on = ST_MAGN_2_PW_ON,
-			.value_off = ST_MAGN_2_PW_OFF,
+			.addr = 0x22,
+			.mask = 0x03,
+			.value_on = 0x00,
+			.value_off = 0x03,
 		},
 		.fs = {
-			.addr = ST_MAGN_2_FS_ADDR,
-			.mask = ST_MAGN_2_FS_MASK,
+			.addr = 0x21,
+			.mask = 0x60,
 			.fs_avl = {
 				[0] = {
 					.num = ST_MAGN_FS_AVL_4000MG,
-					.value = ST_MAGN_2_FS_AVL_4000_VAL,
-					.gain = ST_MAGN_2_FS_AVL_4000_GAIN,
+					.value = 0x00,
+					.gain = 146,
 				},
 				[1] = {
 					.num = ST_MAGN_FS_AVL_8000MG,
-					.value = ST_MAGN_2_FS_AVL_8000_VAL,
-					.gain = ST_MAGN_2_FS_AVL_8000_GAIN,
+					.value = 0x01,
+					.gain = 292,
 				},
 				[2] = {
 					.num = ST_MAGN_FS_AVL_12000MG,
-					.value = ST_MAGN_2_FS_AVL_12000_VAL,
-					.gain = ST_MAGN_2_FS_AVL_12000_GAIN,
+					.value = 0x02,
+					.gain = 438,
 				},
 				[3] = {
 					.num = ST_MAGN_FS_AVL_16000MG,
-					.value = ST_MAGN_2_FS_AVL_16000_VAL,
-					.gain = ST_MAGN_2_FS_AVL_16000_GAIN,
+					.value = 0x03,
+					.gain = 584,
 				},
 			},
 		},
-		.multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
+		.multi_read_bit = false,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_MAGN_3_WAI_EXP,
-		.wai_addr = ST_MAGN_3_WAI_ADDR,
+		.wai = 0x40,
+		.wai_addr = 0x4f,
 		.sensors_supported = {
 			[0] = LSM303AGR_MAGN_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,
 		.odr = {
-			.addr = ST_MAGN_3_ODR_ADDR,
-			.mask = ST_MAGN_3_ODR_MASK,
+			.addr = 0x60,
+			.mask = 0x0c,
 			.odr_avl = {
-				{ 10, ST_MAGN_3_ODR_AVL_10HZ_VAL, },
-				{ 20, ST_MAGN_3_ODR_AVL_20HZ_VAL, },
-				{ 50, ST_MAGN_3_ODR_AVL_50HZ_VAL, },
-				{ 100, ST_MAGN_3_ODR_AVL_100HZ_VAL, },
+				{ .hz = 10, .value = 0x00 },
+				{ .hz = 20, .value = 0x01 },
+				{ .hz = 50, .value = 0x02 },
+				{ .hz = 100, .value = 0x03 },
 			},
 		},
 		.pw = {
-			.addr = ST_MAGN_3_PW_ADDR,
-			.mask = ST_MAGN_3_PW_MASK,
-			.value_on = ST_MAGN_3_PW_ON,
-			.value_off = ST_MAGN_3_PW_OFF,
+			.addr = 0x60,
+			.mask = 0x03,
+			.value_on = 0x00,
+			.value_off = 0x03,
 		},
 		.fs = {
 			.fs_avl = {
 				[0] = {
 					.num = ST_MAGN_FS_AVL_15000MG,
-					.gain = ST_MAGN_3_FS_AVL_15000_GAIN,
+					.gain = 1500,
 				},
 			},
 		},
 		.bdu = {
-			.addr = ST_MAGN_3_BDU_ADDR,
-			.mask = ST_MAGN_3_BDU_MASK,
+			.addr = 0x62,
+			.mask = 0x10,
 		},
 		.drdy_irq = {
-			.addr = ST_MAGN_3_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
-			.addr_ihl = ST_MAGN_3_IHL_IRQ_ADDR,
-			.mask_ihl = ST_MAGN_3_IHL_IRQ_MASK,
+			.addr = 0x62,
+			.mask_int1 = 0x01,
+			.addr_ihl = 0x63,
+			.mask_ihl = 0x04,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
+		.multi_read_bit = false,
 		.bootime = 2,
 	},
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/Makefile
--- linux-libre-4.9-gnu/drivers/iio/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@ obj-y += amplifiers/
 obj-y += buffer/
 obj-y += chemical/
 obj-y += common/
+obj-y += counter/
 obj-y += dac/
 obj-y += dummy/
 obj-y += gyro/
@@ -29,6 +30,7 @@ obj-y += light/
 obj-y += magnetometer/
 obj-y += orientation/
 obj-y += potentiometer/
+obj-y += potentiostat/
 obj-y += pressure/
 obj-y += proximity/
 obj-y += temperature/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/potentiometer/mcp4531.c linux-libre-4.10-rc8-gnu/drivers/iio/potentiometer/mcp4531.c
--- linux-libre-4.9-gnu/drivers/iio/potentiometer/mcp4531.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/potentiometer/mcp4531.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 
 struct mcp4531_cfg {
 	int wipers;
-	int max_pos;
+	int avail[3];
 	int kohms;
 };
 
@@ -78,38 +78,38 @@ enum mcp4531_type {
 };
 
 static const struct mcp4531_cfg mcp4531_cfg[] = {
-	[MCP453x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
-	[MCP453x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
-	[MCP453x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
-	[MCP453x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
-	[MCP454x_502] = { .wipers = 1, .max_pos = 128, .kohms =   5, },
-	[MCP454x_103] = { .wipers = 1, .max_pos = 128, .kohms =  10, },
-	[MCP454x_503] = { .wipers = 1, .max_pos = 128, .kohms =  50, },
-	[MCP454x_104] = { .wipers = 1, .max_pos = 128, .kohms = 100, },
-	[MCP455x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
-	[MCP455x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
-	[MCP455x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
-	[MCP455x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
-	[MCP456x_502] = { .wipers = 1, .max_pos = 256, .kohms =   5, },
-	[MCP456x_103] = { .wipers = 1, .max_pos = 256, .kohms =  10, },
-	[MCP456x_503] = { .wipers = 1, .max_pos = 256, .kohms =  50, },
-	[MCP456x_104] = { .wipers = 1, .max_pos = 256, .kohms = 100, },
-	[MCP463x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
-	[MCP463x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
-	[MCP463x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
-	[MCP463x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
-	[MCP464x_502] = { .wipers = 2, .max_pos = 128, .kohms =   5, },
-	[MCP464x_103] = { .wipers = 2, .max_pos = 128, .kohms =  10, },
-	[MCP464x_503] = { .wipers = 2, .max_pos = 128, .kohms =  50, },
-	[MCP464x_104] = { .wipers = 2, .max_pos = 128, .kohms = 100, },
-	[MCP465x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
-	[MCP465x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
-	[MCP465x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
-	[MCP465x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
-	[MCP466x_502] = { .wipers = 2, .max_pos = 256, .kohms =   5, },
-	[MCP466x_103] = { .wipers = 2, .max_pos = 256, .kohms =  10, },
-	[MCP466x_503] = { .wipers = 2, .max_pos = 256, .kohms =  50, },
-	[MCP466x_104] = { .wipers = 2, .max_pos = 256, .kohms = 100, },
+	[MCP453x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =   5, },
+	[MCP453x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  10, },
+	[MCP453x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  50, },
+	[MCP453x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, },
+	[MCP454x_502] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =   5, },
+	[MCP454x_103] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  10, },
+	[MCP454x_503] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms =  50, },
+	[MCP454x_104] = { .wipers = 1, .avail = { 0, 1, 128 }, .kohms = 100, },
+	[MCP455x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =   5, },
+	[MCP455x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  10, },
+	[MCP455x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  50, },
+	[MCP455x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, },
+	[MCP456x_502] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =   5, },
+	[MCP456x_103] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  10, },
+	[MCP456x_503] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms =  50, },
+	[MCP456x_104] = { .wipers = 1, .avail = { 0, 1, 256 }, .kohms = 100, },
+	[MCP463x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =   5, },
+	[MCP463x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  10, },
+	[MCP463x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  50, },
+	[MCP463x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, },
+	[MCP464x_502] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =   5, },
+	[MCP464x_103] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  10, },
+	[MCP464x_503] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms =  50, },
+	[MCP464x_104] = { .wipers = 2, .avail = { 0, 1, 128 }, .kohms = 100, },
+	[MCP465x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =   5, },
+	[MCP465x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  10, },
+	[MCP465x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  50, },
+	[MCP465x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, },
+	[MCP466x_502] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =   5, },
+	[MCP466x_103] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  10, },
+	[MCP466x_503] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms =  50, },
+	[MCP466x_104] = { .wipers = 2, .avail = { 0, 1, 256 }, .kohms = 100, },
 };
 
 #define MCP4531_WRITE (0 << 2)
@@ -124,13 +124,14 @@ struct mcp4531_data {
 	const struct mcp4531_cfg *cfg;
 };
 
-#define MCP4531_CHANNEL(ch) {					\
-	.type = IIO_RESISTANCE,					\
-	.indexed = 1,						\
-	.output = 1,						\
-	.channel = (ch),					\
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+#define MCP4531_CHANNEL(ch) {						\
+	.type = IIO_RESISTANCE,						\
+	.indexed = 1,							\
+	.output = 1,							\
+	.channel = (ch),						\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
+	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_RAW),	\
 }
 
 static const struct iio_chan_spec mcp4531_channels[] = {
@@ -156,13 +157,31 @@ static int mcp4531_read_raw(struct iio_d
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		*val = 1000 * data->cfg->kohms;
-		*val2 = data->cfg->max_pos;
+		*val2 = data->cfg->avail[2];
 		return IIO_VAL_FRACTIONAL;
 	}
 
 	return -EINVAL;
 }
 
+static int mcp4531_read_avail(struct iio_dev *indio_dev,
+			      struct iio_chan_spec const *chan,
+			      const int **vals, int *type, int *length,
+			      long mask)
+{
+	struct mcp4531_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		*length = ARRAY_SIZE(data->cfg->avail);
+		*vals = data->cfg->avail;
+		*type = IIO_VAL_INT;
+		return IIO_AVAIL_RANGE;
+	}
+
+	return -EINVAL;
+}
+
 static int mcp4531_write_raw(struct iio_dev *indio_dev,
 			     struct iio_chan_spec const *chan,
 			     int val, int val2, long mask)
@@ -172,7 +191,7 @@ static int mcp4531_write_raw(struct iio_
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		if (val > data->cfg->max_pos || val < 0)
+		if (val > data->cfg->avail[2] || val < 0)
 			return -EINVAL;
 		break;
 	default:
@@ -186,6 +205,7 @@ static int mcp4531_write_raw(struct iio_
 
 static const struct iio_info mcp4531_info = {
 	.read_raw = mcp4531_read_raw,
+	.read_avail = mcp4531_read_avail,
 	.write_raw = mcp4531_write_raw,
 	.driver_module = THIS_MODULE,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/potentiostat/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/potentiostat/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/potentiostat/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/potentiostat/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,22 @@
+#
+# Potentiostat drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Digital potentiostats"
+
+config LMP91000
+	tristate "Texas Instruments LMP91000 potentiostat driver"
+	depends on I2C
+	select REGMAP_I2C
+	select IIO_BUFFER
+	select IIO_BUFFER_CB
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Say yes here to build support for the Texas Instruments
+	  LMP91000 digital potentiostat chip.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called lmp91000
+
+endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/potentiostat/lmp91000.c linux-libre-4.10-rc8-gnu/drivers/iio/potentiostat/lmp91000.c
--- linux-libre-4.9-gnu/drivers/iio/potentiostat/lmp91000.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/potentiostat/lmp91000.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,446 @@
+/*
+ * lmp91000.c - Support for Texas Instruments digital potentiostats
+ *
+ * Copyright (C) 2016 Matt Ranostay <mranostay@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.
+ *
+ * TODO: bias voltage + polarity control, and multiple chip support
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define LMP91000_REG_LOCK		0x01
+#define LMP91000_REG_TIACN		0x10
+#define LMP91000_REG_TIACN_GAIN_SHIFT	2
+
+#define LMP91000_REG_REFCN		0x11
+#define LMP91000_REG_REFCN_EXT_REF	0x20
+#define LMP91000_REG_REFCN_50_ZERO	0x80
+
+#define LMP91000_REG_MODECN		0x12
+#define LMP91000_REG_MODECN_3LEAD	0x03
+#define LMP91000_REG_MODECN_TEMP	0x07
+
+#define LMP91000_DRV_NAME	"lmp91000"
+
+static const int lmp91000_tia_gain[] = { 0, 2750, 3500, 7000, 14000, 35000,
+					 120000, 350000 };
+
+static const int lmp91000_rload[] = { 10, 33, 50, 100 };
+
+#define LMP91000_TEMP_BASE	-40
+
+static const u16 lmp91000_temp_lut[] = {
+	1875, 1867, 1860, 1852, 1844, 1836, 1828, 1821, 1813, 1805,
+	1797, 1789, 1782, 1774, 1766, 1758, 1750, 1742, 1734, 1727,
+	1719, 1711, 1703, 1695, 1687, 1679, 1671, 1663, 1656, 1648,
+	1640, 1632, 1624, 1616, 1608, 1600, 1592, 1584, 1576, 1568,
+	1560, 1552, 1544, 1536, 1528, 1520, 1512, 1504, 1496, 1488,
+	1480, 1472, 1464, 1456, 1448, 1440, 1432, 1424, 1415, 1407,
+	1399, 1391, 1383, 1375, 1367, 1359, 1351, 1342, 1334, 1326,
+	1318, 1310, 1302, 1293, 1285, 1277, 1269, 1261, 1253, 1244,
+	1236, 1228, 1220, 1212, 1203, 1195, 1187, 1179, 1170, 1162,
+	1154, 1146, 1137, 1129, 1121, 1112, 1104, 1096, 1087, 1079,
+	1071, 1063, 1054, 1046, 1038, 1029, 1021, 1012, 1004,  996,
+	 987,  979,  971,  962,  954,  945,  937,  929,  920,  912,
+	 903,  895,  886,  878,  870,  861 };
+
+static const struct regmap_config lmp91000_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+struct lmp91000_data {
+	struct regmap *regmap;
+	struct device *dev;
+
+	struct iio_trigger *trig;
+	struct iio_cb_buffer *cb_buffer;
+	struct iio_channel *adc_chan;
+
+	struct completion completion;
+	u8 chan_select;
+
+	u32 buffer[4]; /* 64-bit data + 64-bit timestamp */
+};
+
+static const struct iio_chan_spec lmp91000_channels[] = {
+	{ /* chemical channel mV */
+		.type = IIO_VOLTAGE,
+		.channel = 0,
+		.address = LMP91000_REG_MODECN_3LEAD,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+				      BIT(IIO_CHAN_INFO_OFFSET) |
+				      BIT(IIO_CHAN_INFO_SCALE),
+		.scan_index = 0,
+		.scan_type = {
+			.sign = 's',
+			.realbits = 32,
+			.storagebits = 32,
+		},
+	},
+	IIO_CHAN_SOFT_TIMESTAMP(1),
+	{ /* temperature channel mV */
+		.type = IIO_TEMP,
+		.channel = 1,
+		.address = LMP91000_REG_MODECN_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+		.scan_index = -1,
+	},
+};
+
+static int lmp91000_read(struct lmp91000_data *data, int channel, int *val)
+{
+	int state, ret;
+
+	ret = regmap_read(data->regmap, LMP91000_REG_MODECN, &state);
+	if (ret)
+		return -EINVAL;
+
+	ret = regmap_write(data->regmap, LMP91000_REG_MODECN, channel);
+	if (ret)
+		return -EINVAL;
+
+	/* delay till first temperature reading is complete */
+	if ((state != channel) && (channel == LMP91000_REG_MODECN_TEMP))
+		usleep_range(3000, 4000);
+
+	data->chan_select = channel != LMP91000_REG_MODECN_3LEAD;
+
+	iio_trigger_poll_chained(data->trig);
+
+	ret = wait_for_completion_timeout(&data->completion, HZ);
+	reinit_completion(&data->completion);
+
+	if (!ret)
+		return -ETIMEDOUT;
+
+	*val = data->buffer[data->chan_select];
+
+	return 0;
+}
+
+static irqreturn_t lmp91000_buffer_handler(int irq, void *private)
+{
+	struct iio_poll_func *pf = private;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct lmp91000_data *data = iio_priv(indio_dev);
+	int ret, val;
+
+	memset(data->buffer, 0, sizeof(data->buffer));
+
+	ret = lmp91000_read(data, LMP91000_REG_MODECN_3LEAD, &val);
+	if (!ret) {
+		data->buffer[0] = val;
+		iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+						   iio_get_time_ns(indio_dev));
+	}
+
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+static int lmp91000_read_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask)
+{
+	struct lmp91000_data *data = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_PROCESSED: {
+		int ret = iio_channel_start_all_cb(data->cb_buffer);
+
+		if (ret)
+			return ret;
+
+		ret = lmp91000_read(data, chan->address, val);
+
+		iio_channel_stop_all_cb(data->cb_buffer);
+
+		if (ret)
+			return ret;
+
+		if (mask == IIO_CHAN_INFO_PROCESSED) {
+			int tmp, i;
+
+			ret = iio_convert_raw_to_processed(data->adc_chan,
+							   *val, &tmp, 1);
+			if (ret)
+				return ret;
+
+			for (i = 0; i < ARRAY_SIZE(lmp91000_temp_lut); i++)
+				if (lmp91000_temp_lut[i] < tmp)
+					break;
+
+			*val = (LMP91000_TEMP_BASE + i) * 1000;
+		}
+		return IIO_VAL_INT;
+	}
+	case IIO_CHAN_INFO_OFFSET:
+		return iio_read_channel_offset(data->adc_chan, val, val2);
+	case IIO_CHAN_INFO_SCALE:
+		return iio_read_channel_scale(data->adc_chan, val, val2);
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info lmp91000_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = lmp91000_read_raw,
+};
+
+static int lmp91000_read_config(struct lmp91000_data *data)
+{
+	struct device *dev = data->dev;
+	struct device_node *np = dev->of_node;
+	unsigned int reg, val;
+	int i, ret;
+
+	ret = of_property_read_u32(np, "ti,tia-gain-ohm", &val);
+	if (ret) {
+		if (of_property_read_bool(np, "ti,external-tia-resistor"))
+			val = 0;
+		else {
+			dev_err(dev, "no ti,tia-gain-ohm defined");
+			return ret;
+		}
+	}
+
+	ret = -EINVAL;
+	for (i = 0; i < ARRAY_SIZE(lmp91000_tia_gain); i++) {
+		if (lmp91000_tia_gain[i] == val) {
+			reg = i << LMP91000_REG_TIACN_GAIN_SHIFT;
+			ret = 0;
+			break;
+		}
+	}
+
+	if (ret) {
+		dev_err(dev, "invalid ti,tia-gain-ohm %d\n", val);
+		return ret;
+	}
+
+	ret = of_property_read_u32(np, "ti,rload-ohm", &val);
+	if (ret) {
+		val = 100;
+		dev_info(dev, "no ti,rload-ohm defined, default to %d\n", val);
+	}
+
+	ret = -EINVAL;
+	for (i = 0; i < ARRAY_SIZE(lmp91000_rload); i++) {
+		if (lmp91000_rload[i] == val) {
+			reg |= i;
+			ret = 0;
+			break;
+		}
+	}
+
+	if (ret) {
+		dev_err(dev, "invalid ti,rload-ohm %d\n", val);
+		return ret;
+	}
+
+	regmap_write(data->regmap, LMP91000_REG_LOCK, 0);
+	regmap_write(data->regmap, LMP91000_REG_TIACN, reg);
+	regmap_write(data->regmap, LMP91000_REG_REFCN, LMP91000_REG_REFCN_EXT_REF
+					| LMP91000_REG_REFCN_50_ZERO);
+	regmap_write(data->regmap, LMP91000_REG_LOCK, 1);
+
+	return 0;
+}
+
+static int lmp91000_buffer_cb(const void *val, void *private)
+{
+	struct iio_dev *indio_dev = private;
+	struct lmp91000_data *data = iio_priv(indio_dev);
+
+	data->buffer[data->chan_select] = *((int *)val);
+	complete_all(&data->completion);
+
+	return 0;
+}
+
+static const struct iio_trigger_ops lmp91000_trigger_ops = {
+	.owner = THIS_MODULE,
+};
+
+
+static int lmp91000_buffer_preenable(struct iio_dev *indio_dev)
+{
+	struct lmp91000_data *data = iio_priv(indio_dev);
+
+	return iio_channel_start_all_cb(data->cb_buffer);
+}
+
+static int lmp91000_buffer_predisable(struct iio_dev *indio_dev)
+{
+	struct lmp91000_data *data = iio_priv(indio_dev);
+
+	iio_channel_stop_all_cb(data->cb_buffer);
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops lmp91000_buffer_setup_ops = {
+	.preenable = lmp91000_buffer_preenable,
+	.postenable = iio_triggered_buffer_postenable,
+	.predisable = lmp91000_buffer_predisable,
+};
+
+static int lmp91000_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct device *dev = &client->dev;
+	struct lmp91000_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	indio_dev->info = &lmp91000_info;
+	indio_dev->channels = lmp91000_channels;
+	indio_dev->num_channels = ARRAY_SIZE(lmp91000_channels);
+	indio_dev->name = LMP91000_DRV_NAME;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	i2c_set_clientdata(client, indio_dev);
+
+	data = iio_priv(indio_dev);
+	data->dev = dev;
+	data->regmap = devm_regmap_init_i2c(client, &lmp91000_regmap_config);
+	if (IS_ERR(data->regmap)) {
+		dev_err(dev, "regmap initialization failed.\n");
+		return PTR_ERR(data->regmap);
+	}
+
+	data->trig = devm_iio_trigger_alloc(data->dev, "%s-mux%d",
+					    indio_dev->name, indio_dev->id);
+	if (!data->trig) {
+		dev_err(dev, "cannot allocate iio trigger.\n");
+		return -ENOMEM;
+	}
+
+	data->trig->ops = &lmp91000_trigger_ops;
+	data->trig->dev.parent = dev;
+	init_completion(&data->completion);
+
+	ret = lmp91000_read_config(data);
+	if (ret)
+		return ret;
+
+	ret = iio_trigger_set_immutable(iio_channel_cb_get_iio_dev(data->cb_buffer),
+					data->trig);
+	if (ret) {
+		dev_err(dev, "cannot set immutable trigger.\n");
+		return ret;
+	}
+
+	ret = iio_trigger_register(data->trig);
+	if (ret) {
+		dev_err(dev, "cannot register iio trigger.\n");
+		return ret;
+	}
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 &lmp91000_buffer_handler,
+					 &lmp91000_buffer_setup_ops);
+	if (ret)
+		goto error_unreg_trigger;
+
+	data->cb_buffer = iio_channel_get_all_cb(dev, &lmp91000_buffer_cb,
+						 indio_dev);
+
+	if (IS_ERR(data->cb_buffer)) {
+		if (PTR_ERR(data->cb_buffer) == -ENODEV)
+			ret = -EPROBE_DEFER;
+		else
+			ret = PTR_ERR(data->cb_buffer);
+
+		goto error_unreg_buffer;
+	}
+
+	data->adc_chan = iio_channel_cb_get_channels(data->cb_buffer);
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_unreg_cb_buffer;
+
+	return 0;
+
+error_unreg_cb_buffer:
+	iio_channel_release_all_cb(data->cb_buffer);
+
+error_unreg_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+
+error_unreg_trigger:
+	iio_trigger_unregister(data->trig);
+
+	return ret;
+}
+
+static int lmp91000_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct lmp91000_data *data = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+
+	iio_channel_stop_all_cb(data->cb_buffer);
+	iio_channel_release_all_cb(data->cb_buffer);
+
+	iio_triggered_buffer_cleanup(indio_dev);
+	iio_trigger_unregister(data->trig);
+
+	return 0;
+}
+
+static const struct of_device_id lmp91000_of_match[] = {
+	{ .compatible = "ti,lmp91000", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, lmp91000_of_match);
+
+static const struct i2c_device_id lmp91000_id[] = {
+	{ "lmp91000", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, lmp91000_id);
+
+static struct i2c_driver lmp91000_driver = {
+	.driver = {
+		.name = LMP91000_DRV_NAME,
+		.of_match_table = of_match_ptr(lmp91000_of_match),
+	},
+	.probe = lmp91000_probe,
+	.remove = lmp91000_remove,
+	.id_table = lmp91000_id,
+};
+module_i2c_driver(lmp91000_driver);
+
+MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
+MODULE_DESCRIPTION("LMP91000 digital potentiostat");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/potentiostat/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/potentiostat/Makefile
--- linux-libre-4.9-gnu/drivers/iio/potentiostat/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/potentiostat/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,6 @@
+#
+# Makefile for industrial I/O potentiostat drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_LMP91000) += lmp91000.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/pressure/abp060mg.c linux-libre-4.10-rc8-gnu/drivers/iio/pressure/abp060mg.c
--- linux-libre-4.9-gnu/drivers/iio/pressure/abp060mg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/pressure/abp060mg.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2016 - Marcin Malagowski <mrc@bourne.st>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/iio/iio.h>
+
+#define ABP060MG_ERROR_MASK   0xC000
+#define ABP060MG_RESP_TIME_MS 40
+#define ABP060MG_MIN_COUNTS   1638  /* = 0x0666 (10% of u14) */
+#define ABP060MG_MAX_COUNTS   14745 /* = 0x3999 (90% of u14) */
+#define ABP060MG_NUM_COUNTS   (ABP060MG_MAX_COUNTS - ABP060MG_MIN_COUNTS)
+
+enum abp_variant {
+	/* gage [kPa] */
+	ABP006KG, ABP010KG, ABP016KG, ABP025KG, ABP040KG, ABP060KG, ABP100KG,
+	ABP160KG, ABP250KG, ABP400KG, ABP600KG, ABP001GG,
+	/* differential [kPa] */
+	ABP006KD, ABP010KD, ABP016KD, ABP025KD, ABP040KD, ABP060KD, ABP100KD,
+	ABP160KD, ABP250KD, ABP400KD,
+	/* gage [psi] */
+	ABP001PG, ABP005PG, ABP015PG, ABP030PG, ABP060PG, ABP100PG, ABP150PG,
+	/* differential [psi] */
+	ABP001PD, ABP005PD, ABP015PD, ABP030PD, ABP060PD,
+};
+
+struct abp_config {
+	int min;
+	int max;
+};
+
+static struct abp_config abp_config[] = {
+	/* mbar & kPa variants */
+	[ABP006KG] = { .min =       0, .max =     6000 },
+	[ABP010KG] = { .min =       0, .max =    10000 },
+	[ABP016KG] = { .min =       0, .max =    16000 },
+	[ABP025KG] = { .min =       0, .max =    25000 },
+	[ABP040KG] = { .min =       0, .max =    40000 },
+	[ABP060KG] = { .min =       0, .max =    60000 },
+	[ABP100KG] = { .min =       0, .max =   100000 },
+	[ABP160KG] = { .min =       0, .max =   160000 },
+	[ABP250KG] = { .min =       0, .max =   250000 },
+	[ABP400KG] = { .min =       0, .max =   400000 },
+	[ABP600KG] = { .min =       0, .max =   600000 },
+	[ABP001GG] = { .min =       0, .max =  1000000 },
+	[ABP006KD] = { .min =   -6000, .max =     6000 },
+	[ABP010KD] = { .min =  -10000, .max =    10000 },
+	[ABP016KD] = { .min =  -16000, .max =    16000 },
+	[ABP025KD] = { .min =  -25000, .max =    25000 },
+	[ABP040KD] = { .min =  -40000, .max =    40000 },
+	[ABP060KD] = { .min =  -60000, .max =    60000 },
+	[ABP100KD] = { .min = -100000, .max =   100000 },
+	[ABP160KD] = { .min = -160000, .max =   160000 },
+	[ABP250KD] = { .min = -250000, .max =   250000 },
+	[ABP400KD] = { .min = -400000, .max =   400000 },
+	/* psi variants (1 psi ~ 6895 Pa) */
+	[ABP001PG] = { .min =       0, .max =     6985 },
+	[ABP005PG] = { .min =       0, .max =    34474 },
+	[ABP015PG] = { .min =       0, .max =   103421 },
+	[ABP030PG] = { .min =       0, .max =   206843 },
+	[ABP060PG] = { .min =       0, .max =   413686 },
+	[ABP100PG] = { .min =       0, .max =   689476 },
+	[ABP150PG] = { .min =       0, .max =  1034214 },
+	[ABP001PD] = { .min =   -6895, .max =     6895 },
+	[ABP005PD] = { .min =  -34474, .max =    34474 },
+	[ABP015PD] = { .min = -103421, .max =   103421 },
+	[ABP030PD] = { .min = -206843, .max =   206843 },
+	[ABP060PD] = { .min = -413686, .max =   413686 },
+};
+
+struct abp_state {
+	struct i2c_client *client;
+	struct mutex lock;
+
+	/*
+	 * bus-dependent MEASURE_REQUEST length.
+	 * If no SMBUS_QUICK support, need to send dummy byte
+	 */
+	int mreq_len;
+
+	/* model-dependent values (calculated on probe) */
+	int scale;
+	int offset;
+};
+
+static const struct iio_chan_spec abp060mg_channels[] = {
+	{
+		.type = IIO_PRESSURE,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
+	},
+};
+
+static int abp060mg_get_measurement(struct abp_state *state, int *val)
+{
+	struct i2c_client *client = state->client;
+	__be16 buf[2];
+	u16 pressure;
+	int ret;
+
+	buf[0] = 0;
+	ret = i2c_master_send(client, (u8 *)&buf, state->mreq_len);
+	if (ret < 0)
+		return ret;
+
+	msleep_interruptible(ABP060MG_RESP_TIME_MS);
+
+	ret = i2c_master_recv(client, (u8 *)&buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	pressure = be16_to_cpu(buf[0]);
+	if (pressure & ABP060MG_ERROR_MASK)
+		return -EIO;
+
+	if (pressure < ABP060MG_MIN_COUNTS || pressure > ABP060MG_MAX_COUNTS)
+		return -EIO;
+
+	*val = pressure;
+
+	return IIO_VAL_INT;
+}
+
+static int abp060mg_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan, int *val,
+			int *val2, long mask)
+{
+	struct abp_state *state = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&state->lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = abp060mg_get_measurement(state, val);
+		break;
+	case IIO_CHAN_INFO_OFFSET:
+		*val = state->offset;
+		ret = IIO_VAL_INT;
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		*val = state->scale;
+		*val2 = ABP060MG_NUM_COUNTS * 1000; /* to kPa */
+		ret = IIO_VAL_FRACTIONAL;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&state->lock);
+	return ret;
+}
+
+static const struct iio_info abp060mg_info = {
+	.driver_module = THIS_MODULE,
+	.read_raw = abp060mg_read_raw,
+};
+
+static void abp060mg_init_device(struct iio_dev *indio_dev, unsigned long id)
+{
+	struct abp_state *state = iio_priv(indio_dev);
+	struct abp_config *cfg = &abp_config[id];
+
+	state->scale = cfg->max - cfg->min;
+	state->offset = -ABP060MG_MIN_COUNTS;
+
+	if (cfg->min < 0) /* differential */
+		state->offset -= ABP060MG_NUM_COUNTS >> 1;
+}
+
+static int abp060mg_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct abp_state *state;
+	unsigned long cfg_id = id->driver_data;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*state));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	state = iio_priv(indio_dev);
+	i2c_set_clientdata(client, state);
+	state->client = client;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK))
+		state->mreq_len = 1;
+
+	abp060mg_init_device(indio_dev, cfg_id);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->name = dev_name(&client->dev);
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->info = &abp060mg_info;
+
+	indio_dev->channels = abp060mg_channels;
+	indio_dev->num_channels = ARRAY_SIZE(abp060mg_channels);
+
+	mutex_init(&state->lock);
+
+	return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct i2c_device_id abp060mg_id_table[] = {
+	/* mbar & kPa variants (abp060m [60 mbar] == abp006k [6 kPa]) */
+	/*    gage: */
+	{ "abp060mg", ABP006KG }, { "abp006kg", ABP006KG },
+	{ "abp100mg", ABP010KG }, { "abp010kg", ABP010KG },
+	{ "abp160mg", ABP016KG }, { "abp016kg", ABP016KG },
+	{ "abp250mg", ABP025KG }, { "abp025kg", ABP025KG },
+	{ "abp400mg", ABP040KG }, { "abp040kg", ABP040KG },
+	{ "abp600mg", ABP060KG }, { "abp060kg", ABP060KG },
+	{ "abp001bg", ABP100KG }, { "abp100kg", ABP100KG },
+	{ "abp1_6bg", ABP160KG }, { "abp160kg", ABP160KG },
+	{ "abp2_5bg", ABP250KG }, { "abp250kg", ABP250KG },
+	{ "abp004bg", ABP400KG }, { "abp400kg", ABP400KG },
+	{ "abp006bg", ABP600KG }, { "abp600kg", ABP600KG },
+	{ "abp010bg", ABP001GG }, { "abp001gg", ABP001GG },
+	/*    differential: */
+	{ "abp060md", ABP006KD }, { "abp006kd", ABP006KD },
+	{ "abp100md", ABP010KD }, { "abp010kd", ABP010KD },
+	{ "abp160md", ABP016KD }, { "abp016kd", ABP016KD },
+	{ "abp250md", ABP025KD }, { "abp025kd", ABP025KD },
+	{ "abp400md", ABP040KD }, { "abp040kd", ABP040KD },
+	{ "abp600md", ABP060KD }, { "abp060kd", ABP060KD },
+	{ "abp001bd", ABP100KD }, { "abp100kd", ABP100KD },
+	{ "abp1_6bd", ABP160KD }, { "abp160kd", ABP160KD },
+	{ "abp2_5bd", ABP250KD }, { "abp250kd", ABP250KD },
+	{ "abp004bd", ABP400KD }, { "abp400kd", ABP400KD },
+	/* psi variants */
+	/*    gage: */
+	{ "abp001pg", ABP001PG },
+	{ "abp005pg", ABP005PG },
+	{ "abp015pg", ABP015PG },
+	{ "abp030pg", ABP030PG },
+	{ "abp060pg", ABP060PG },
+	{ "abp100pg", ABP100PG },
+	{ "abp150pg", ABP150PG },
+	/*    differential: */
+	{ "abp001pd", ABP001PD },
+	{ "abp005pd", ABP005PD },
+	{ "abp015pd", ABP015PD },
+	{ "abp030pd", ABP030PD },
+	{ "abp060pd", ABP060PD },
+	{ /* empty */ },
+};
+MODULE_DEVICE_TABLE(i2c, abp060mg_id_table);
+
+static struct i2c_driver abp060mg_driver = {
+	.driver = {
+		.name = "abp060mg",
+	},
+	.probe = abp060mg_probe,
+	.id_table = abp060mg_id_table,
+};
+module_i2c_driver(abp060mg_driver);
+
+MODULE_AUTHOR("Marcin Malagowski <mrc@bourne.st>");
+MODULE_DESCRIPTION("Honeywell ABP pressure sensor driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/pressure/Kconfig linux-libre-4.10-rc8-gnu/drivers/iio/pressure/Kconfig
--- linux-libre-4.9-gnu/drivers/iio/pressure/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/pressure/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -5,6 +5,16 @@
 
 menu "Pressure sensors"
 
+config ABP060MG
+	tristate "Honeywell ABP pressure sensor driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the Honeywell ABP pressure
+	  sensors.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called abp060mg.
+
 config BMP280
 	tristate "Bosch Sensortec BMP180/BMP280 pressure sensor I2C driver"
 	depends on (I2C || SPI_MASTER)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/pressure/Makefile linux-libre-4.10-rc8-gnu/drivers/iio/pressure/Makefile
--- linux-libre-4.9-gnu/drivers/iio/pressure/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/pressure/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -3,6 +3,7 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_ABP060MG) += abp060mg.o
 obj-$(CONFIG_BMP280) += bmp280.o
 bmp280-objs := bmp280-core.o bmp280-regmap.o
 obj-$(CONFIG_BMP280_I2C) += bmp280-i2c.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/pressure/mpl3115.c linux-libre-4.10-rc8-gnu/drivers/iio/pressure/mpl3115.c
--- linux-libre-4.9-gnu/drivers/iio/pressure/mpl3115.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/pressure/mpl3115.c	2017-02-12 16:03:20.000000000 -0500
@@ -82,8 +82,9 @@ static int mpl3115_read_raw(struct iio_d
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
-		if (iio_buffer_enabled(indio_dev))
-			return -EBUSY;
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret)
+			return ret;
 
 		switch (chan->type) {
 		case IIO_PRESSURE: /* in 0.25 pascal / LSB */
@@ -91,32 +92,39 @@ static int mpl3115_read_raw(struct iio_d
 			ret = mpl3115_request(data);
 			if (ret < 0) {
 				mutex_unlock(&data->lock);
-				return ret;
+				break;
 			}
 			ret = i2c_smbus_read_i2c_block_data(data->client,
 				MPL3115_OUT_PRESS, 3, (u8 *) &tmp);
 			mutex_unlock(&data->lock);
 			if (ret < 0)
-				return ret;
+				break;
 			*val = be32_to_cpu(tmp) >> 12;
-			return IIO_VAL_INT;
+			ret = IIO_VAL_INT;
+			break;
 		case IIO_TEMP: /* in 0.0625 celsius / LSB */
 			mutex_lock(&data->lock);
 			ret = mpl3115_request(data);
 			if (ret < 0) {
 				mutex_unlock(&data->lock);
-				return ret;
+				break;
 			}
 			ret = i2c_smbus_read_i2c_block_data(data->client,
 				MPL3115_OUT_TEMP, 2, (u8 *) &tmp);
 			mutex_unlock(&data->lock);
 			if (ret < 0)
-				return ret;
+				break;
 			*val = sign_extend32(be32_to_cpu(tmp) >> 20, 11);
-			return IIO_VAL_INT;
+			ret = IIO_VAL_INT;
+			break;
 		default:
-			return -EINVAL;
+			ret = -EINVAL;
+			break;
 		}
+
+		iio_device_release_direct_mode(indio_dev);
+		return ret;
+
 	case IIO_CHAN_INFO_SCALE:
 		switch (chan->type) {
 		case IIO_PRESSURE:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/pressure/ms5611_core.c linux-libre-4.10-rc8-gnu/drivers/iio/pressure/ms5611_core.c
--- linux-libre-4.9-gnu/drivers/iio/pressure/ms5611_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/pressure/ms5611_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -392,17 +392,14 @@ static int ms5611_init(struct iio_dev *i
 
 	/* Enable attached regulator if any. */
 	st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
-	if (!IS_ERR(st->vdd)) {
-		ret = regulator_enable(st->vdd);
-		if (ret) {
-			dev_err(indio_dev->dev.parent,
-				"failed to enable Vdd supply: %d\n", ret);
-			return ret;
-		}
-	} else {
-		ret = PTR_ERR(st->vdd);
-		if (ret != -ENODEV)
-			return ret;
+	if (IS_ERR(st->vdd))
+		return PTR_ERR(st->vdd);
+
+	ret = regulator_enable(st->vdd);
+	if (ret) {
+		dev_err(indio_dev->dev.parent,
+			"failed to enable Vdd supply: %d\n", ret);
+		return ret;
 	}
 
 	ret = ms5611_reset(indio_dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/pressure/st_pressure_core.c linux-libre-4.10-rc8-gnu/drivers/iio/pressure/st_pressure_core.c
--- linux-libre-4.9-gnu/drivers/iio/pressure/st_pressure_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/pressure/st_pressure_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -112,115 +112,24 @@
 #define ST_PRESS_1_OUT_XL_ADDR			0x28
 #define ST_TEMP_1_OUT_L_ADDR			0x2b
 
-/*
- * CUSTOM VALUES FOR LPS331AP SENSOR
- * See LPS331AP datasheet:
- * http://www2.st.com/resource/en/datasheet/lps331ap.pdf
- */
-#define ST_PRESS_LPS331AP_WAI_EXP		0xbb
-#define ST_PRESS_LPS331AP_ODR_ADDR		0x20
-#define ST_PRESS_LPS331AP_ODR_MASK		0x70
-#define ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL	0x01
-#define ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL	0x05
-#define ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL	0x06
-#define ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL	0x07
-#define ST_PRESS_LPS331AP_PW_ADDR		0x20
-#define ST_PRESS_LPS331AP_PW_MASK		0x80
-#define ST_PRESS_LPS331AP_FS_ADDR		0x23
-#define ST_PRESS_LPS331AP_FS_MASK		0x30
-#define ST_PRESS_LPS331AP_BDU_ADDR		0x20
-#define ST_PRESS_LPS331AP_BDU_MASK		0x04
-#define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR		0x22
-#define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK	0x04
-#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK	0x20
-#define ST_PRESS_LPS331AP_IHL_IRQ_ADDR		0x22
-#define ST_PRESS_LPS331AP_IHL_IRQ_MASK		0x80
-#define ST_PRESS_LPS331AP_OD_IRQ_ADDR		0x22
-#define ST_PRESS_LPS331AP_OD_IRQ_MASK		0x40
-#define ST_PRESS_LPS331AP_MULTIREAD_BIT		true
-
-/*
- * CUSTOM VALUES FOR THE OBSOLETE LPS001WP SENSOR
- */
-
 /* LPS001WP pressure resolution */
 #define ST_PRESS_LPS001WP_LSB_PER_MBAR		16UL
 /* LPS001WP temperature resolution */
 #define ST_PRESS_LPS001WP_LSB_PER_CELSIUS	64UL
-
-#define ST_PRESS_LPS001WP_WAI_EXP		0xba
-#define ST_PRESS_LPS001WP_ODR_ADDR		0x20
-#define ST_PRESS_LPS001WP_ODR_MASK		0x30
-#define ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL	0x01
-#define ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL	0x02
-#define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL	0x03
-#define ST_PRESS_LPS001WP_PW_ADDR		0x20
-#define ST_PRESS_LPS001WP_PW_MASK		0x40
+/* LPS001WP pressure gain */
 #define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \
 	(100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR)
-#define ST_PRESS_LPS001WP_BDU_ADDR		0x20
-#define ST_PRESS_LPS001WP_BDU_MASK		0x04
-#define ST_PRESS_LPS001WP_MULTIREAD_BIT		true
+/* LPS001WP pressure and temp L addresses */
 #define ST_PRESS_LPS001WP_OUT_L_ADDR		0x28
 #define ST_TEMP_LPS001WP_OUT_L_ADDR		0x2a
 
-/*
- * CUSTOM VALUES FOR LPS25H SENSOR
- * See LPS25H datasheet:
- * http://www2.st.com/resource/en/datasheet/lps25h.pdf
- */
-#define ST_PRESS_LPS25H_WAI_EXP			0xbd
-#define ST_PRESS_LPS25H_ODR_ADDR		0x20
-#define ST_PRESS_LPS25H_ODR_MASK		0x70
-#define ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL		0x01
-#define ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL		0x02
-#define ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL	0x03
-#define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL	0x04
-#define ST_PRESS_LPS25H_PW_ADDR			0x20
-#define ST_PRESS_LPS25H_PW_MASK			0x80
-#define ST_PRESS_LPS25H_BDU_ADDR		0x20
-#define ST_PRESS_LPS25H_BDU_MASK		0x04
-#define ST_PRESS_LPS25H_DRDY_IRQ_ADDR		0x23
-#define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK	0x01
-#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK	0x10
-#define ST_PRESS_LPS25H_IHL_IRQ_ADDR		0x22
-#define ST_PRESS_LPS25H_IHL_IRQ_MASK		0x80
-#define ST_PRESS_LPS25H_OD_IRQ_ADDR		0x22
-#define ST_PRESS_LPS25H_OD_IRQ_MASK		0x40
-#define ST_PRESS_LPS25H_MULTIREAD_BIT		true
+/* LPS25H pressure and temp L addresses */
 #define ST_PRESS_LPS25H_OUT_XL_ADDR		0x28
 #define ST_TEMP_LPS25H_OUT_L_ADDR		0x2b
 
-/*
- * CUSTOM VALUES FOR LPS22HB SENSOR
- * See LPS22HB datasheet:
- * http://www2.st.com/resource/en/datasheet/lps22hb.pdf
- */
-
 /* LPS22HB temperature sensitivity */
 #define ST_PRESS_LPS22HB_LSB_PER_CELSIUS	100UL
 
-#define ST_PRESS_LPS22HB_WAI_EXP		0xb1
-#define ST_PRESS_LPS22HB_ODR_ADDR		0x10
-#define ST_PRESS_LPS22HB_ODR_MASK		0x70
-#define ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL	0x01
-#define ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL	0x02
-#define ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL	0x03
-#define ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL	0x04
-#define ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL	0x05
-#define ST_PRESS_LPS22HB_PW_ADDR		0x10
-#define ST_PRESS_LPS22HB_PW_MASK		0x70
-#define ST_PRESS_LPS22HB_BDU_ADDR		0x10
-#define ST_PRESS_LPS22HB_BDU_MASK		0x02
-#define ST_PRESS_LPS22HB_DRDY_IRQ_ADDR		0x12
-#define ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK	0x04
-#define ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK	0x08
-#define ST_PRESS_LPS22HB_IHL_IRQ_ADDR		0x12
-#define ST_PRESS_LPS22HB_IHL_IRQ_MASK		0x80
-#define ST_PRESS_LPS22HB_OD_IRQ_ADDR		0x12
-#define ST_PRESS_LPS22HB_OD_IRQ_MASK		0x40
-#define ST_PRESS_LPS22HB_MULTIREAD_BIT		true
-
 static const struct iio_chan_spec st_press_1_channels[] = {
 	{
 		.type = IIO_PRESSURE,
@@ -321,7 +230,12 @@ static const struct iio_chan_spec st_pre
 
 static const struct st_sensor_settings st_press_sensors_settings[] = {
 	{
-		.wai = ST_PRESS_LPS331AP_WAI_EXP,
+		/*
+		 * CUSTOM VALUES FOR LPS331AP SENSOR
+		 * See LPS331AP datasheet:
+		 * http://www2.st.com/resource/en/datasheet/lps331ap.pdf
+		 */
+		.wai = 0xbb,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LPS331AP_PRESS_DEV_NAME,
@@ -329,24 +243,24 @@ static const struct st_sensor_settings s
 		.ch = (struct iio_chan_spec *)st_press_1_channels,
 		.num_ch = ARRAY_SIZE(st_press_1_channels),
 		.odr = {
-			.addr = ST_PRESS_LPS331AP_ODR_ADDR,
-			.mask = ST_PRESS_LPS331AP_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x70,
 			.odr_avl = {
-				{ 1, ST_PRESS_LPS331AP_ODR_AVL_1HZ_VAL, },
-				{ 7, ST_PRESS_LPS331AP_ODR_AVL_7HZ_VAL, },
-				{ 13, ST_PRESS_LPS331AP_ODR_AVL_13HZ_VAL, },
-				{ 25, ST_PRESS_LPS331AP_ODR_AVL_25HZ_VAL, },
+				{ .hz = 1, .value = 0x01 },
+				{ .hz = 7, .value = 0x05 },
+				{ .hz = 13, .value = 0x06 },
+				{ .hz = 25, .value = 0x07 },
 			},
 		},
 		.pw = {
-			.addr = ST_PRESS_LPS331AP_PW_ADDR,
-			.mask = ST_PRESS_LPS331AP_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x80,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.fs = {
-			.addr = ST_PRESS_LPS331AP_FS_ADDR,
-			.mask = ST_PRESS_LPS331AP_FS_MASK,
+			.addr = 0x23,
+			.mask = 0x30,
 			.fs_avl = {
 				/*
 				 * Pressure and temperature sensitivity values
@@ -360,24 +274,27 @@ static const struct st_sensor_settings s
 			},
 		},
 		.bdu = {
-			.addr = ST_PRESS_LPS331AP_BDU_ADDR,
-			.mask = ST_PRESS_LPS331AP_BDU_MASK,
+			.addr = 0x20,
+			.mask = 0x04,
 		},
 		.drdy_irq = {
-			.addr = ST_PRESS_LPS331AP_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_PRESS_LPS331AP_IHL_IRQ_ADDR,
-			.mask_ihl = ST_PRESS_LPS331AP_IHL_IRQ_MASK,
-			.addr_od = ST_PRESS_LPS331AP_OD_IRQ_ADDR,
-			.mask_od = ST_PRESS_LPS331AP_OD_IRQ_MASK,
+			.addr = 0x22,
+			.mask_int1 = 0x04,
+			.mask_int2 = 0x20,
+			.addr_ihl = 0x22,
+			.mask_ihl = 0x80,
+			.addr_od = 0x22,
+			.mask_od = 0x40,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_PRESS_LPS331AP_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_PRESS_LPS001WP_WAI_EXP,
+		/*
+		 * CUSTOM VALUES FOR LPS001WP SENSOR
+		 */
+		.wai = 0xba,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LPS001WP_PRESS_DEV_NAME,
@@ -385,17 +302,17 @@ static const struct st_sensor_settings s
 		.ch = (struct iio_chan_spec *)st_press_lps001wp_channels,
 		.num_ch = ARRAY_SIZE(st_press_lps001wp_channels),
 		.odr = {
-			.addr = ST_PRESS_LPS001WP_ODR_ADDR,
-			.mask = ST_PRESS_LPS001WP_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x30,
 			.odr_avl = {
-				{ 1, ST_PRESS_LPS001WP_ODR_AVL_1HZ_VAL, },
-				{ 7, ST_PRESS_LPS001WP_ODR_AVL_7HZ_VAL, },
-				{ 13, ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL, },
+				{ .hz = 1, .value = 0x01 },
+				{ .hz = 7, .value = 0x02 },
+				{ .hz = 13, .value = 0x03 },
 			},
 		},
 		.pw = {
-			.addr = ST_PRESS_LPS001WP_PW_ADDR,
-			.mask = ST_PRESS_LPS001WP_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x40,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -413,17 +330,22 @@ static const struct st_sensor_settings s
 			},
 		},
 		.bdu = {
-			.addr = ST_PRESS_LPS001WP_BDU_ADDR,
-			.mask = ST_PRESS_LPS001WP_BDU_MASK,
+			.addr = 0x20,
+			.mask = 0x04,
 		},
 		.drdy_irq = {
 			.addr = 0,
 		},
-		.multi_read_bit = ST_PRESS_LPS001WP_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_PRESS_LPS25H_WAI_EXP,
+		/*
+		 * CUSTOM VALUES FOR LPS25H SENSOR
+		 * See LPS25H datasheet:
+		 * http://www2.st.com/resource/en/datasheet/lps25h.pdf
+		 */
+		.wai = 0xbd,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LPS25H_PRESS_DEV_NAME,
@@ -431,18 +353,18 @@ static const struct st_sensor_settings s
 		.ch = (struct iio_chan_spec *)st_press_1_channels,
 		.num_ch = ARRAY_SIZE(st_press_1_channels),
 		.odr = {
-			.addr = ST_PRESS_LPS25H_ODR_ADDR,
-			.mask = ST_PRESS_LPS25H_ODR_MASK,
+			.addr = 0x20,
+			.mask = 0x70,
 			.odr_avl = {
-				{ 1, ST_PRESS_LPS25H_ODR_AVL_1HZ_VAL, },
-				{ 7, ST_PRESS_LPS25H_ODR_AVL_7HZ_VAL, },
-				{ 13, ST_PRESS_LPS25H_ODR_AVL_13HZ_VAL, },
-				{ 25, ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL, },
+				{ .hz = 1, .value = 0x01 },
+				{ .hz = 7, .value = 0x02 },
+				{ .hz = 13, .value = 0x03 },
+				{ .hz = 25, .value = 0x04 },
 			},
 		},
 		.pw = {
-			.addr = ST_PRESS_LPS25H_PW_ADDR,
-			.mask = ST_PRESS_LPS25H_PW_MASK,
+			.addr = 0x20,
+			.mask = 0x80,
 			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
@@ -460,24 +382,29 @@ static const struct st_sensor_settings s
 			},
 		},
 		.bdu = {
-			.addr = ST_PRESS_LPS25H_BDU_ADDR,
-			.mask = ST_PRESS_LPS25H_BDU_MASK,
+			.addr = 0x20,
+			.mask = 0x04,
 		},
 		.drdy_irq = {
-			.addr = ST_PRESS_LPS25H_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_PRESS_LPS25H_IHL_IRQ_ADDR,
-			.mask_ihl = ST_PRESS_LPS25H_IHL_IRQ_MASK,
-			.addr_od = ST_PRESS_LPS25H_OD_IRQ_ADDR,
-			.mask_od = ST_PRESS_LPS25H_OD_IRQ_MASK,
+			.addr = 0x23,
+			.mask_int1 = 0x01,
+			.mask_int2 = 0x10,
+			.addr_ihl = 0x22,
+			.mask_ihl = 0x80,
+			.addr_od = 0x22,
+			.mask_od = 0x40,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_PRESS_LPS25H_MULTIREAD_BIT,
+		.multi_read_bit = true,
 		.bootime = 2,
 	},
 	{
-		.wai = ST_PRESS_LPS22HB_WAI_EXP,
+		/*
+		 * CUSTOM VALUES FOR LPS22HB SENSOR
+		 * See LPS22HB datasheet:
+		 * http://www2.st.com/resource/en/datasheet/lps22hb.pdf
+		 */
+		.wai = 0xb1,
 		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 		.sensors_supported = {
 			[0] = LPS22HB_PRESS_DEV_NAME,
@@ -485,19 +412,19 @@ static const struct st_sensor_settings s
 		.ch = (struct iio_chan_spec *)st_press_lps22hb_channels,
 		.num_ch = ARRAY_SIZE(st_press_lps22hb_channels),
 		.odr = {
-			.addr = ST_PRESS_LPS22HB_ODR_ADDR,
-			.mask = ST_PRESS_LPS22HB_ODR_MASK,
+			.addr = 0x10,
+			.mask = 0x70,
 			.odr_avl = {
-				{ 1, ST_PRESS_LPS22HB_ODR_AVL_1HZ_VAL, },
-				{ 10, ST_PRESS_LPS22HB_ODR_AVL_10HZ_VAL, },
-				{ 25, ST_PRESS_LPS22HB_ODR_AVL_25HZ_VAL, },
-				{ 50, ST_PRESS_LPS22HB_ODR_AVL_50HZ_VAL, },
-				{ 75, ST_PRESS_LPS22HB_ODR_AVL_75HZ_VAL, },
+				{ .hz = 1, .value = 0x01 },
+				{ .hz = 10, .value = 0x02 },
+				{ .hz = 25, .value = 0x03 },
+				{ .hz = 50, .value = 0x04 },
+				{ .hz = 75, .value = 0x05 },
 			},
 		},
 		.pw = {
-			.addr = ST_PRESS_LPS22HB_PW_ADDR,
-			.mask = ST_PRESS_LPS22HB_PW_MASK,
+			.addr = 0x10,
+			.mask = 0x70,
 			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
 		},
 		.fs = {
@@ -514,20 +441,20 @@ static const struct st_sensor_settings s
 			},
 		},
 		.bdu = {
-			.addr = ST_PRESS_LPS22HB_BDU_ADDR,
-			.mask = ST_PRESS_LPS22HB_BDU_MASK,
+			.addr = 0x10,
+			.mask = 0x02,
 		},
 		.drdy_irq = {
-			.addr = ST_PRESS_LPS22HB_DRDY_IRQ_ADDR,
-			.mask_int1 = ST_PRESS_LPS22HB_DRDY_IRQ_INT1_MASK,
-			.mask_int2 = ST_PRESS_LPS22HB_DRDY_IRQ_INT2_MASK,
-			.addr_ihl = ST_PRESS_LPS22HB_IHL_IRQ_ADDR,
-			.mask_ihl = ST_PRESS_LPS22HB_IHL_IRQ_MASK,
-			.addr_od = ST_PRESS_LPS22HB_OD_IRQ_ADDR,
-			.mask_od = ST_PRESS_LPS22HB_OD_IRQ_MASK,
+			.addr = 0x12,
+			.mask_int1 = 0x04,
+			.mask_int2 = 0x08,
+			.addr_ihl = 0x12,
+			.mask_ihl = 0x80,
+			.addr_od = 0x12,
+			.mask_od = 0x40,
 			.addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
 		},
-		.multi_read_bit = ST_PRESS_LPS22HB_MULTIREAD_BIT,
+		.multi_read_bit = true,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/pressure/zpa2326.c linux-libre-4.10-rc8-gnu/drivers/iio/pressure/zpa2326.c
--- linux-libre-4.9-gnu/drivers/iio/pressure/zpa2326.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/pressure/zpa2326.c	2017-02-12 16:03:20.000000000 -0500
@@ -147,12 +147,8 @@ struct zpa2326_private {
 #define zpa2326_warn(_idev, _format, _arg...) \
 	dev_warn(_idev->dev.parent, _format, ##_arg)
 
-#ifdef DEBUG
 #define zpa2326_dbg(_idev, _format, _arg...) \
 	dev_dbg(_idev->dev.parent, _format, ##_arg)
-#else
-#define zpa2326_dbg(_idev, _format, _arg...)
-#endif
 
 bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c linux-libre-4.10-rc8-gnu/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
--- linux-libre-4.9-gnu/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c	2017-02-12 16:03:20.000000000 -0500
@@ -301,8 +301,6 @@ static int lidar_probe(struct i2c_client
 	if (ret)
 		goto error_unreg_buffer;
 	pm_runtime_enable(&client->dev);
-
-	pm_runtime_mark_last_busy(&client->dev);
 	pm_runtime_idle(&client->dev);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iio/trigger/iio-trig-hrtimer.c linux-libre-4.10-rc8-gnu/drivers/iio/trigger/iio-trig-hrtimer.c
--- linux-libre-4.9-gnu/drivers/iio/trigger/iio-trig-hrtimer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iio/trigger/iio-trig-hrtimer.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,7 +63,7 @@ ssize_t iio_hrtimer_store_sampling_frequ
 		return -EINVAL;
 
 	info->sampling_frequency = val;
-	info->period = ktime_set(0, NSEC_PER_SEC / val);
+	info->period = NSEC_PER_SEC / val;
 
 	return len;
 }
@@ -141,8 +141,7 @@ static struct iio_sw_trigger *iio_trig_h
 	trig_info->timer.function = iio_hrtimer_trig_handler;
 
 	trig_info->sampling_frequency = HRTIMER_DEFAULT_SAMPLING_FREQUENCY;
-	trig_info->period = ktime_set(0, NSEC_PER_SEC /
-				      trig_info->sampling_frequency);
+	trig_info->period = NSEC_PER_SEC / trig_info->sampling_frequency;
 
 	ret = iio_trigger_register(trig_info->swt.trigger);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/agent.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/agent.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/agent.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/agent.c	2017-02-12 16:03:20.000000000 -0500
@@ -156,7 +156,6 @@ int ib_agent_port_open(struct ib_device
 	/* Create new device info */
 	port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
 	if (!port_priv) {
-		dev_err(&device->dev, "No memory for ib_agent_port_private\n");
 		ret = -ENOMEM;
 		goto error1;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/cache.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/cache.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/cache.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/cache.c	2017-02-12 16:03:20.000000000 -0500
@@ -770,12 +770,8 @@ static int _gid_table_setup_one(struct i
 	int err = 0;
 
 	table = kcalloc(ib_dev->phys_port_cnt, sizeof(*table), GFP_KERNEL);
-
-	if (!table) {
-		pr_warn("failed to allocate ib gid cache for %s\n",
-			ib_dev->name);
+	if (!table)
 		return -ENOMEM;
-	}
 
 	for (port = 0; port < ib_dev->phys_port_cnt; port++) {
 		u8 rdma_port = port + rdma_start_port(ib_dev);
@@ -1170,14 +1166,13 @@ int ib_cache_setup_one(struct ib_device
 					  GFP_KERNEL);
 	if (!device->cache.pkey_cache ||
 	    !device->cache.lmc_cache) {
-		pr_warn("Couldn't allocate cache for %s\n", device->name);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto free;
 	}
 
 	err = gid_table_setup_one(device);
 	if (err)
-		/* Allocated memory will be cleaned in the release function */
-		return err;
+		goto free;
 
 	for (p = 0; p <= rdma_end_port(device) - rdma_start_port(device); ++p)
 		ib_cache_update(device, p + rdma_start_port(device));
@@ -1192,6 +1187,9 @@ int ib_cache_setup_one(struct ib_device
 
 err:
 	gid_table_cleanup_one(device);
+free:
+	kfree(device->cache.pkey_cache);
+	kfree(device->cache.lmc_cache);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/cma.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/cma.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/cma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/cma.c	2017-02-12 16:03:20.000000000 -0500
@@ -101,6 +101,49 @@ const char *__attribute_const__ rdma_eve
 }
 EXPORT_SYMBOL(rdma_event_msg);
 
+const char *__attribute_const__ rdma_reject_msg(struct rdma_cm_id *id,
+						int reason)
+{
+	if (rdma_ib_or_roce(id->device, id->port_num))
+		return ibcm_reject_msg(reason);
+
+	if (rdma_protocol_iwarp(id->device, id->port_num))
+		return iwcm_reject_msg(reason);
+
+	WARN_ON_ONCE(1);
+	return "unrecognized transport";
+}
+EXPORT_SYMBOL(rdma_reject_msg);
+
+bool rdma_is_consumer_reject(struct rdma_cm_id *id, int reason)
+{
+	if (rdma_ib_or_roce(id->device, id->port_num))
+		return reason == IB_CM_REJ_CONSUMER_DEFINED;
+
+	if (rdma_protocol_iwarp(id->device, id->port_num))
+		return reason == -ECONNREFUSED;
+
+	WARN_ON_ONCE(1);
+	return false;
+}
+EXPORT_SYMBOL(rdma_is_consumer_reject);
+
+const void *rdma_consumer_reject_data(struct rdma_cm_id *id,
+				      struct rdma_cm_event *ev, u8 *data_len)
+{
+	const void *p;
+
+	if (rdma_is_consumer_reject(id, ev->status)) {
+		*data_len = ev->param.conn.private_data_len;
+		p = ev->param.conn.private_data;
+	} else {
+		*data_len = 0;
+		p = NULL;
+	}
+	return p;
+}
+EXPORT_SYMBOL(rdma_consumer_reject_data);
+
 static void cma_add_one(struct ib_device *device);
 static void cma_remove_one(struct ib_device *device, void *client_data);
 
@@ -116,7 +159,7 @@ static LIST_HEAD(dev_list);
 static LIST_HEAD(listen_any_list);
 static DEFINE_MUTEX(lock);
 static struct workqueue_struct *cma_wq;
-static int cma_pernet_id;
+static unsigned int cma_pernet_id;
 
 struct cma_pernet {
 	struct idr tcp_ps;
@@ -2768,7 +2811,8 @@ static int cma_bind_addr(struct rdma_cm_
 	if (!src_addr || !src_addr->sa_family) {
 		src_addr = (struct sockaddr *) &id->route.addr.src_addr;
 		src_addr->sa_family = dst_addr->sa_family;
-		if (dst_addr->sa_family == AF_INET6) {
+		if (IS_ENABLED(CONFIG_IPV6) &&
+		    dst_addr->sa_family == AF_INET6) {
 			struct sockaddr_in6 *src_addr6 = (struct sockaddr_in6 *) src_addr;
 			struct sockaddr_in6 *dst_addr6 = (struct sockaddr_in6 *) dst_addr;
 			src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/cm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/cm.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,6 +57,54 @@ MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("InfiniBand CM");
 MODULE_LICENSE("Dual BSD/GPL");
 
+static const char * const ibcm_rej_reason_strs[] = {
+	[IB_CM_REJ_NO_QP]			= "no QP",
+	[IB_CM_REJ_NO_EEC]			= "no EEC",
+	[IB_CM_REJ_NO_RESOURCES]		= "no resources",
+	[IB_CM_REJ_TIMEOUT]			= "timeout",
+	[IB_CM_REJ_UNSUPPORTED]			= "unsupported",
+	[IB_CM_REJ_INVALID_COMM_ID]		= "invalid comm ID",
+	[IB_CM_REJ_INVALID_COMM_INSTANCE]	= "invalid comm instance",
+	[IB_CM_REJ_INVALID_SERVICE_ID]		= "invalid service ID",
+	[IB_CM_REJ_INVALID_TRANSPORT_TYPE]	= "invalid transport type",
+	[IB_CM_REJ_STALE_CONN]			= "stale conn",
+	[IB_CM_REJ_RDC_NOT_EXIST]		= "RDC not exist",
+	[IB_CM_REJ_INVALID_GID]			= "invalid GID",
+	[IB_CM_REJ_INVALID_LID]			= "invalid LID",
+	[IB_CM_REJ_INVALID_SL]			= "invalid SL",
+	[IB_CM_REJ_INVALID_TRAFFIC_CLASS]	= "invalid traffic class",
+	[IB_CM_REJ_INVALID_HOP_LIMIT]		= "invalid hop limit",
+	[IB_CM_REJ_INVALID_PACKET_RATE]		= "invalid packet rate",
+	[IB_CM_REJ_INVALID_ALT_GID]		= "invalid alt GID",
+	[IB_CM_REJ_INVALID_ALT_LID]		= "invalid alt LID",
+	[IB_CM_REJ_INVALID_ALT_SL]		= "invalid alt SL",
+	[IB_CM_REJ_INVALID_ALT_TRAFFIC_CLASS]	= "invalid alt traffic class",
+	[IB_CM_REJ_INVALID_ALT_HOP_LIMIT]	= "invalid alt hop limit",
+	[IB_CM_REJ_INVALID_ALT_PACKET_RATE]	= "invalid alt packet rate",
+	[IB_CM_REJ_PORT_CM_REDIRECT]		= "port CM redirect",
+	[IB_CM_REJ_PORT_REDIRECT]		= "port redirect",
+	[IB_CM_REJ_INVALID_MTU]			= "invalid MTU",
+	[IB_CM_REJ_INSUFFICIENT_RESP_RESOURCES]	= "insufficient resp resources",
+	[IB_CM_REJ_CONSUMER_DEFINED]		= "consumer defined",
+	[IB_CM_REJ_INVALID_RNR_RETRY]		= "invalid RNR retry",
+	[IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID]	= "duplicate local comm ID",
+	[IB_CM_REJ_INVALID_CLASS_VERSION]	= "invalid class version",
+	[IB_CM_REJ_INVALID_FLOW_LABEL]		= "invalid flow label",
+	[IB_CM_REJ_INVALID_ALT_FLOW_LABEL]	= "invalid alt flow label",
+};
+
+const char *__attribute_const__ ibcm_reject_msg(int reason)
+{
+	size_t index = reason;
+
+	if (index < ARRAY_SIZE(ibcm_rej_reason_strs) &&
+	    ibcm_rej_reason_strs[index])
+		return ibcm_rej_reason_strs[index];
+	else
+		return "unrecognized reason";
+}
+EXPORT_SYMBOL(ibcm_reject_msg);
+
 static void cm_add_one(struct ib_device *device);
 static void cm_remove_one(struct ib_device *device, void *client_data);
 
@@ -1582,6 +1630,7 @@ static struct cm_id_private * cm_match_r
 	struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
 	struct cm_timewait_info *timewait_info;
 	struct cm_req_msg *req_msg;
+	struct ib_cm_id *cm_id;
 
 	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
@@ -1603,10 +1652,18 @@ static struct cm_id_private * cm_match_r
 	timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
 	if (timewait_info) {
 		cm_cleanup_timewait(cm_id_priv->timewait_info);
+		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
+					   timewait_info->work.remote_id);
+
 		spin_unlock_irq(&cm.lock);
 		cm_issue_rej(work->port, work->mad_recv_wc,
 			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
 			     NULL, 0);
+		if (cur_cm_id_priv) {
+			cm_id = &cur_cm_id_priv->id;
+			ib_send_cm_dreq(cm_id, NULL, 0);
+			cm_deref_id(cur_cm_id_priv);
+		}
 		return NULL;
 	}
 
@@ -1984,6 +2041,9 @@ static int cm_rep_handler(struct cm_work
 	struct cm_id_private *cm_id_priv;
 	struct cm_rep_msg *rep_msg;
 	int ret;
+	struct cm_id_private *cur_cm_id_priv;
+	struct ib_cm_id *cm_id;
+	struct cm_timewait_info *timewait_info;
 
 	rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
 	cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id, 0);
@@ -2018,16 +2078,26 @@ static int cm_rep_handler(struct cm_work
 		goto error;
 	}
 	/* Check for a stale connection. */
-	if (cm_insert_remote_qpn(cm_id_priv->timewait_info)) {
+	timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
+	if (timewait_info) {
 		rb_erase(&cm_id_priv->timewait_info->remote_id_node,
 			 &cm.remote_id_table);
 		cm_id_priv->timewait_info->inserted_remote_id = 0;
+		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
+					   timewait_info->work.remote_id);
+
 		spin_unlock(&cm.lock);
 		spin_unlock_irq(&cm_id_priv->lock);
 		cm_issue_rej(work->port, work->mad_recv_wc,
 			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,
 			     NULL, 0);
 		ret = -EINVAL;
+		if (cur_cm_id_priv) {
+			cm_id = &cur_cm_id_priv->id;
+			ib_send_cm_dreq(cm_id, NULL, 0);
+			cm_deref_id(cur_cm_id_priv);
+		}
+
 		goto error;
 	}
 	spin_unlock(&cm.lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/core_priv.h linux-libre-4.10-rc8-gnu/drivers/infiniband/core/core_priv.h
--- linux-libre-4.9-gnu/drivers/infiniband/core/core_priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/core_priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -72,9 +72,6 @@ void ib_device_unregister_sysfs(struct i
 void ib_cache_setup(void);
 void ib_cache_cleanup(void);
 
-int ib_resolve_eth_dmac(struct ib_qp *qp,
-			struct ib_qp_attr *qp_attr, int *qp_attr_mask);
-
 typedef void (*roce_netdev_callback)(struct ib_device *device, u8 port,
 	      struct net_device *idev, void *cookie);
 
@@ -127,14 +124,7 @@ void ib_cache_release_one(struct ib_devi
 static inline bool rdma_is_upper_dev_rcu(struct net_device *dev,
 					 struct net_device *upper)
 {
-	struct net_device *_upper = NULL;
-	struct list_head *iter;
-
-	netdev_for_each_all_upper_dev_rcu(dev, _upper, iter)
-		if (_upper == upper)
-			break;
-
-	return _upper == upper;
+	return netdev_has_upper_dev_all_rcu(dev, upper);
 }
 
 int addr_init(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/device.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/device.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/device.c	2017-02-12 16:03:20.000000000 -0500
@@ -254,11 +254,8 @@ static int add_client_context(struct ib_
 	unsigned long flags;
 
 	context = kmalloc(sizeof *context, GFP_KERNEL);
-	if (!context) {
-		pr_warn("Couldn't allocate client context for %s/%s\n",
-			device->name, client->name);
+	if (!context)
 		return -ENOMEM;
-	}
 
 	context->client = client;
 	context->data   = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/fmr_pool.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/fmr_pool.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/fmr_pool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/fmr_pool.c	2017-02-12 16:03:20.000000000 -0500
@@ -247,7 +247,6 @@ struct ib_fmr_pool *ib_create_fmr_pool(s
 			kmalloc(IB_FMR_HASH_SIZE * sizeof *pool->cache_bucket,
 				GFP_KERNEL);
 		if (!pool->cache_bucket) {
-			pr_warn(PFX "Failed to allocate cache in pool\n");
 			ret = -ENOMEM;
 			goto out_free_pool;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/iwcm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/iwcm.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/iwcm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/iwcm.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,6 +59,27 @@ MODULE_AUTHOR("Tom Tucker");
 MODULE_DESCRIPTION("iWARP CM");
 MODULE_LICENSE("Dual BSD/GPL");
 
+static const char * const iwcm_rej_reason_strs[] = {
+	[ECONNRESET]			= "reset by remote host",
+	[ECONNREFUSED]			= "refused by remote application",
+	[ETIMEDOUT]			= "setup timeout",
+};
+
+const char *__attribute_const__ iwcm_reject_msg(int reason)
+{
+	size_t index;
+
+	/* iWARP uses negative errnos */
+	index = -reason;
+
+	if (index < ARRAY_SIZE(iwcm_rej_reason_strs) &&
+	    iwcm_rej_reason_strs[index])
+		return iwcm_rej_reason_strs[index];
+	else
+		return "unrecognized reason";
+}
+EXPORT_SYMBOL(iwcm_reject_msg);
+
 static struct ibnl_client_cbs iwcm_nl_cb_table[] = {
 	[RDMA_NL_IWPM_REG_PID] = {.dump = iwpm_register_pid_cb},
 	[RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/iwpm_msg.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/iwpm_msg.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/iwpm_msg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/iwpm_msg.c	2017-02-12 16:03:20.000000000 -0500
@@ -604,7 +604,6 @@ int iwpm_remote_info_cb(struct sk_buff *
 	}
 	rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
 	if (!rem_info) {
-		pr_err("%s: Unable to allocate a remote info\n", __func__);
 		ret = -ENOMEM;
 		return ret;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/iwpm_util.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/iwpm_util.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/iwpm_util.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/iwpm_util.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,6 @@ int iwpm_init(u8 nl_client)
 					sizeof(struct hlist_head), GFP_KERNEL);
 		if (!iwpm_hash_bucket) {
 			ret = -ENOMEM;
-			pr_err("%s Unable to create mapinfo hash table\n", __func__);
 			goto init_exit;
 		}
 		iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE *
@@ -70,7 +69,6 @@ int iwpm_init(u8 nl_client)
 		if (!iwpm_reminfo_bucket) {
 			kfree(iwpm_hash_bucket);
 			ret = -ENOMEM;
-			pr_err("%s Unable to create reminfo hash table\n", __func__);
 			goto init_exit;
 		}
 	}
@@ -128,10 +126,9 @@ int iwpm_create_mapinfo(struct sockaddr_
 	if (!iwpm_valid_client(nl_client))
 		return ret;
 	map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL);
-	if (!map_info) {
-		pr_err("%s: Unable to allocate a mapping info\n", __func__);
+	if (!map_info)
 		return -ENOMEM;
-	}
+
 	memcpy(&map_info->local_sockaddr, local_sockaddr,
 	       sizeof(struct sockaddr_storage));
 	memcpy(&map_info->mapped_sockaddr, mapped_sockaddr,
@@ -309,10 +306,9 @@ struct iwpm_nlmsg_request *iwpm_get_nlms
 	unsigned long flags;
 
 	nlmsg_request = kzalloc(sizeof(struct iwpm_nlmsg_request), gfp);
-	if (!nlmsg_request) {
-		pr_err("%s Unable to allocate a nlmsg_request\n", __func__);
+	if (!nlmsg_request)
 		return NULL;
-	}
+
 	spin_lock_irqsave(&iwpm_nlmsg_req_lock, flags);
 	list_add_tail(&nlmsg_request->inprocess_list, &iwpm_nlmsg_req_list);
 	spin_unlock_irqrestore(&iwpm_nlmsg_req_lock, flags);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/mad.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/mad.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/mad.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/mad.c	2017-02-12 16:03:20.000000000 -0500
@@ -769,7 +769,7 @@ static int handle_outgoing_dr_smp(struct
 	 * If we are at the start of the LID routed part, don't update the
 	 * hop_ptr or hop_cnt.  See section 14.2.2, Vol 1 IB spec.
 	 */
-	if (opa && smp->class_version == OPA_SMP_CLASS_VERSION) {
+	if (opa && smp->class_version == OPA_SM_CLASS_VERSION) {
 		u32 opa_drslid;
 
 		if ((opa_get_smp_direction(opa_smp)
@@ -816,7 +816,6 @@ static int handle_outgoing_dr_smp(struct
 	local = kmalloc(sizeof *local, GFP_ATOMIC);
 	if (!local) {
 		ret = -ENOMEM;
-		dev_err(&device->dev, "No memory for ib_mad_local_private\n");
 		goto out;
 	}
 	local->mad_priv = NULL;
@@ -824,7 +823,6 @@ static int handle_outgoing_dr_smp(struct
 	mad_priv = alloc_mad_private(mad_size, GFP_ATOMIC);
 	if (!mad_priv) {
 		ret = -ENOMEM;
-		dev_err(&device->dev, "No memory for local response MAD\n");
 		kfree(local);
 		goto out;
 	}
@@ -947,9 +945,6 @@ static int alloc_send_rmpp_list(struct i
 	for (left = send_buf->data_len + pad; left > 0; left -= seg_size) {
 		seg = kmalloc(sizeof (*seg) + seg_size, gfp_mask);
 		if (!seg) {
-			dev_err(&send_buf->mad_agent->device->dev,
-				"alloc_send_rmpp_segs: RMPP mem alloc failed for len %zd, gfp %#x\n",
-				sizeof (*seg) + seg_size, gfp_mask);
 			free_send_rmpp_list(send_wr);
 			return -ENOMEM;
 		}
@@ -1362,12 +1357,7 @@ static int allocate_method_table(struct
 {
 	/* Allocate management method table */
 	*method = kzalloc(sizeof **method, GFP_ATOMIC);
-	if (!*method) {
-		pr_err("No memory for ib_mad_mgmt_method_table\n");
-		return -ENOMEM;
-	}
-
-	return 0;
+	return (*method) ? 0 : (-ENOMEM);
 }
 
 /*
@@ -1458,8 +1448,6 @@ static int add_nonoui_reg_req(struct ib_
 		/* Allocate management class table for "new" class version */
 		*class = kzalloc(sizeof **class, GFP_ATOMIC);
 		if (!*class) {
-			dev_err(&agent_priv->agent.device->dev,
-				"No memory for ib_mad_mgmt_class_table\n");
 			ret = -ENOMEM;
 			goto error1;
 		}
@@ -1524,22 +1512,16 @@ static int add_oui_reg_req(struct ib_mad
 	if (!*vendor_table) {
 		/* Allocate mgmt vendor class table for "new" class version */
 		vendor = kzalloc(sizeof *vendor, GFP_ATOMIC);
-		if (!vendor) {
-			dev_err(&agent_priv->agent.device->dev,
-				"No memory for ib_mad_mgmt_vendor_class_table\n");
+		if (!vendor)
 			goto error1;
-		}
 
 		*vendor_table = vendor;
 	}
 	if (!(*vendor_table)->vendor_class[vclass]) {
 		/* Allocate table for this management vendor class */
 		vendor_class = kzalloc(sizeof *vendor_class, GFP_ATOMIC);
-		if (!vendor_class) {
-			dev_err(&agent_priv->agent.device->dev,
-				"No memory for ib_mad_mgmt_vendor_class\n");
+		if (!vendor_class)
 			goto error2;
-		}
 
 		(*vendor_table)->vendor_class[vclass] = vendor_class;
 	}
@@ -1746,7 +1728,7 @@ find_mad_agent(struct ib_mad_port_privat
 			if (!class)
 				goto out;
 			if (convert_mgmt_class(mad_hdr->mgmt_class) >=
-			    IB_MGMT_MAX_METHODS)
+			    ARRAY_SIZE(class->method_table))
 				goto out;
 			method = class->method_table[convert_mgmt_class(
 							mad_hdr->mgmt_class)];
@@ -2167,7 +2149,7 @@ handle_smi(struct ib_mad_port_private *p
 	struct ib_mad_hdr *mad_hdr = (struct ib_mad_hdr *)recv->mad;
 
 	if (opa && mad_hdr->base_version == OPA_MGMT_BASE_VERSION &&
-	    mad_hdr->class_version == OPA_SMI_CLASS_VERSION)
+	    mad_hdr->class_version == OPA_SM_CLASS_VERSION)
 		return handle_opa_smi(port_priv, qp_info, wc, port_num, recv,
 				      response);
 
@@ -2238,11 +2220,8 @@ static void ib_mad_recv_done(struct ib_c
 
 	mad_size = recv->mad_size;
 	response = alloc_mad_private(mad_size, GFP_KERNEL);
-	if (!response) {
-		dev_err(&port_priv->device->dev,
-			"%s: no memory for response buffer\n", __func__);
+	if (!response)
 		goto out;
-	}
 
 	if (rdma_cap_ib_switch(port_priv->device))
 		port_num = wc->port_num;
@@ -2869,8 +2848,6 @@ static int ib_mad_post_receive_mads(stru
 			mad_priv = alloc_mad_private(port_mad_size(qp_info->port_priv),
 						     GFP_ATOMIC);
 			if (!mad_priv) {
-				dev_err(&qp_info->port_priv->device->dev,
-					"No memory for receive buffer\n");
 				ret = -ENOMEM;
 				break;
 			}
@@ -2961,11 +2938,8 @@ static int ib_mad_port_start(struct ib_m
 	u16 pkey_index;
 
 	attr = kmalloc(sizeof *attr, GFP_KERNEL);
-	if (!attr) {
-		dev_err(&port_priv->device->dev,
-			"Couldn't kmalloc ib_qp_attr\n");
+	if (!attr)
 		return -ENOMEM;
-	}
 
 	ret = ib_find_pkey(port_priv->device, port_priv->port_num,
 			   IB_DEFAULT_PKEY_FULL, &pkey_index);
@@ -3135,10 +3109,8 @@ static int ib_mad_port_open(struct ib_de
 
 	/* Create new device info */
 	port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
-	if (!port_priv) {
-		dev_err(&device->dev, "No memory for ib_mad_port_private\n");
+	if (!port_priv)
 		return -ENOMEM;
-	}
 
 	port_priv->device = device;
 	port_priv->port_num = port_num;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/multicast.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/multicast.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/multicast.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/multicast.c	2017-02-12 16:03:20.000000000 -0500
@@ -518,8 +518,11 @@ static void join_handler(int status, str
 		process_join_error(group, status);
 	else {
 		int mgids_changed, is_mgid0;
-		ib_find_pkey(group->port->dev->device, group->port->port_num,
-			     be16_to_cpu(rec->pkey), &pkey_index);
+
+		if (ib_find_pkey(group->port->dev->device,
+				 group->port->port_num, be16_to_cpu(rec->pkey),
+				 &pkey_index))
+			pkey_index = MCAST_INVALID_PKEY_INDEX;
 
 		spin_lock_irq(&group->port->lock);
 		if (group->state == MCAST_BUSY &&
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/roce_gid_mgmt.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/roce_gid_mgmt.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/roce_gid_mgmt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/roce_gid_mgmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -304,10 +304,9 @@ static void enum_netdev_ipv4_ips(struct
 	for_ifa(in_dev) {
 		struct sin_list *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 
-		if (!entry) {
-			pr_warn("roce_gid_mgmt: couldn't allocate entry for IPv4 update\n");
+		if (!entry)
 			continue;
-		}
+
 		entry->ip.sin_family = AF_INET;
 		entry->ip.sin_addr.s_addr = ifa->ifa_address;
 		list_add_tail(&entry->list, &sin_list);
@@ -348,10 +347,8 @@ static void enum_netdev_ipv6_ips(struct
 	list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
 		struct sin6_list *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 
-		if (!entry) {
-			pr_warn("roce_gid_mgmt: couldn't allocate entry for IPv6 update\n");
+		if (!entry)
 			continue;
-		}
 
 		entry->sin6.sin6_family = AF_INET6;
 		entry->sin6.sin6_addr = ifp->addr;
@@ -437,6 +434,26 @@ static void callback_for_addr_gid_device
 			  &parsed->gid_attr);
 }
 
+struct upper_list {
+	struct list_head list;
+	struct net_device *upper;
+};
+
+static int netdev_upper_walk(struct net_device *upper, void *data)
+{
+	struct upper_list *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
+	struct list_head *upper_list = data;
+
+	if (!entry)
+		return 0;
+
+	list_add_tail(&entry->list, upper_list);
+	dev_hold(upper);
+	entry->upper = upper;
+
+	return 0;
+}
+
 static void handle_netdev_upper(struct ib_device *ib_dev, u8 port,
 				void *cookie,
 				void (*handle_netdev)(struct ib_device *ib_dev,
@@ -444,30 +461,12 @@ static void handle_netdev_upper(struct i
 						      struct net_device *ndev))
 {
 	struct net_device *ndev = (struct net_device *)cookie;
-	struct upper_list {
-		struct list_head list;
-		struct net_device *upper;
-	};
-	struct net_device *upper;
-	struct list_head *iter;
 	struct upper_list *upper_iter;
 	struct upper_list *upper_temp;
 	LIST_HEAD(upper_list);
 
 	rcu_read_lock();
-	netdev_for_each_all_upper_dev_rcu(ndev, upper, iter) {
-		struct upper_list *entry = kmalloc(sizeof(*entry),
-						   GFP_ATOMIC);
-
-		if (!entry) {
-			pr_info("roce_gid_mgmt: couldn't allocate entry to delete ndev\n");
-			continue;
-		}
-
-		list_add_tail(&entry->list, &upper_list);
-		dev_hold(upper);
-		entry->upper = upper;
-	}
+	netdev_walk_all_upper_dev_rcu(ndev, netdev_upper_walk, &upper_list);
 	rcu_read_unlock();
 
 	handle_netdev(ib_dev, port, ndev);
@@ -555,10 +554,8 @@ static int netdevice_queue_work(struct n
 	struct netdev_event_work *ndev_work =
 		kmalloc(sizeof(*ndev_work), GFP_KERNEL);
 
-	if (!ndev_work) {
-		pr_warn("roce_gid_mgmt: can't allocate work for netdevice_event\n");
+	if (!ndev_work)
 		return NOTIFY_DONE;
-	}
 
 	memcpy(ndev_work->cmds, cmds, sizeof(ndev_work->cmds));
 	for (i = 0; i < ARRAY_SIZE(ndev_work->cmds) && ndev_work->cmds[i].cb; i++) {
@@ -692,10 +689,8 @@ static int addr_event(struct notifier_bl
 	}
 
 	work = kmalloc(sizeof(*work), GFP_ATOMIC);
-	if (!work) {
-		pr_warn("roce_gid_mgmt: Couldn't allocate work for addr_event\n");
+	if (!work)
 		return NOTIFY_DONE;
-	}
 
 	INIT_WORK(&work->work, update_gid_event_work_handler);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/ucma.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/ucma.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/ucma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/ucma.c	2017-02-12 16:03:20.000000000 -0500
@@ -1584,8 +1584,11 @@ static ssize_t ucma_write(struct file *f
 	struct rdma_ucm_cmd_hdr hdr;
 	ssize_t ret;
 
-	if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
+	if (!ib_safe_file_access(filp)) {
+		pr_err_once("ucma_write: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n",
+			    task_tgid_vnr(current), current->comm);
 		return -EACCES;
+	}
 
 	if (len < sizeof(hdr))
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/ucm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/ucm.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/ucm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/ucm.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <rdma/ib.h>
 #include <rdma/ib_cm.h>
@@ -1104,8 +1104,11 @@ static ssize_t ib_ucm_write(struct file
 	struct ib_ucm_cmd_hdr hdr;
 	ssize_t result;
 
-	if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
+	if (!ib_safe_file_access(filp)) {
+		pr_err_once("ucm_write: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n",
+			    task_tgid_vnr(current), current->comm);
 		return -EACCES;
+	}
 
 	if (len < sizeof(hdr))
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/umem.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/umem.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/umem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/umem.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,7 +51,7 @@ static void __ib_umem_release(struct ib_
 
 	if (umem->nmap > 0)
 		ib_dma_unmap_sg(dev, umem->sg_head.sgl,
-				umem->nmap,
+				umem->npages,
 				DMA_BIDIRECTIONAL);
 
 	for_each_sg(umem->sg_head.sgl, sg, umem->npages, i) {
@@ -134,6 +134,7 @@ struct ib_umem *ib_umem_get(struct ib_uc
 		 IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_MW_BIND));
 
 	if (access & IB_ACCESS_ON_DEMAND) {
+		put_pid(umem->pid);
 		ret = ib_umem_odp_get(context, umem);
 		if (ret) {
 			kfree(umem);
@@ -149,6 +150,7 @@ struct ib_umem *ib_umem_get(struct ib_uc
 
 	page_list = (struct page **) __get_free_page(GFP_KERNEL);
 	if (!page_list) {
+		put_pid(umem->pid);
 		kfree(umem);
 		return ERR_PTR(-ENOMEM);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/umem_odp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/umem_odp.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/umem_odp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/umem_odp.c	2017-02-12 16:03:20.000000000 -0500
@@ -578,7 +578,7 @@ int ib_umem_odp_map_dma_pages(struct ib_
 		 */
 		npages = get_user_pages_remote(owning_process, owning_mm,
 				user_virt, gup_num_pages,
-				flags, local_page_list, NULL);
+				flags, local_page_list, NULL, NULL);
 		up_read(&owning_mm->mmap_sem);
 
 		if (npages < 0)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/user_mad.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/user_mad.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/user_mad.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/user_mad.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,7 +50,7 @@
 #include <linux/semaphore.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <rdma/ib_mad.h>
 #include <rdma/ib_user_mad.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/uverbs_cmd.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/uverbs_cmd.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/uverbs_cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/uverbs_cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "uverbs.h"
 #include "core_priv.h"
@@ -2328,94 +2328,88 @@ static int modify_qp_mask(enum ib_qp_typ
 	}
 }
 
-ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
-			    struct ib_device *ib_dev,
-			    const char __user *buf, int in_len,
-			    int out_len)
+static int modify_qp(struct ib_uverbs_file *file,
+		     struct ib_uverbs_ex_modify_qp *cmd, struct ib_udata *udata)
 {
-	struct ib_uverbs_modify_qp cmd;
-	struct ib_udata            udata;
-	struct ib_qp              *qp;
-	struct ib_qp_attr         *attr;
-	int                        ret;
-
-	if (copy_from_user(&cmd, buf, sizeof cmd))
-		return -EFAULT;
-
-	INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
-		   out_len);
+	struct ib_qp_attr *attr;
+	struct ib_qp *qp;
+	int ret;
 
 	attr = kmalloc(sizeof *attr, GFP_KERNEL);
 	if (!attr)
 		return -ENOMEM;
 
-	qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+	qp = idr_read_qp(cmd->base.qp_handle, file->ucontext);
 	if (!qp) {
 		ret = -EINVAL;
 		goto out;
 	}
 
-	attr->qp_state 		  = cmd.qp_state;
-	attr->cur_qp_state 	  = cmd.cur_qp_state;
-	attr->path_mtu 		  = cmd.path_mtu;
-	attr->path_mig_state 	  = cmd.path_mig_state;
-	attr->qkey 		  = cmd.qkey;
-	attr->rq_psn 		  = cmd.rq_psn;
-	attr->sq_psn 		  = cmd.sq_psn;
-	attr->dest_qp_num 	  = cmd.dest_qp_num;
-	attr->qp_access_flags 	  = cmd.qp_access_flags;
-	attr->pkey_index 	  = cmd.pkey_index;
-	attr->alt_pkey_index 	  = cmd.alt_pkey_index;
-	attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
-	attr->max_rd_atomic 	  = cmd.max_rd_atomic;
-	attr->max_dest_rd_atomic  = cmd.max_dest_rd_atomic;
-	attr->min_rnr_timer 	  = cmd.min_rnr_timer;
-	attr->port_num 		  = cmd.port_num;
-	attr->timeout 		  = cmd.timeout;
-	attr->retry_cnt 	  = cmd.retry_cnt;
-	attr->rnr_retry 	  = cmd.rnr_retry;
-	attr->alt_port_num 	  = cmd.alt_port_num;
-	attr->alt_timeout 	  = cmd.alt_timeout;
+	attr->qp_state		  = cmd->base.qp_state;
+	attr->cur_qp_state	  = cmd->base.cur_qp_state;
+	attr->path_mtu		  = cmd->base.path_mtu;
+	attr->path_mig_state	  = cmd->base.path_mig_state;
+	attr->qkey		  = cmd->base.qkey;
+	attr->rq_psn		  = cmd->base.rq_psn;
+	attr->sq_psn		  = cmd->base.sq_psn;
+	attr->dest_qp_num	  = cmd->base.dest_qp_num;
+	attr->qp_access_flags	  = cmd->base.qp_access_flags;
+	attr->pkey_index	  = cmd->base.pkey_index;
+	attr->alt_pkey_index	  = cmd->base.alt_pkey_index;
+	attr->en_sqd_async_notify = cmd->base.en_sqd_async_notify;
+	attr->max_rd_atomic	  = cmd->base.max_rd_atomic;
+	attr->max_dest_rd_atomic  = cmd->base.max_dest_rd_atomic;
+	attr->min_rnr_timer	  = cmd->base.min_rnr_timer;
+	attr->port_num		  = cmd->base.port_num;
+	attr->timeout		  = cmd->base.timeout;
+	attr->retry_cnt		  = cmd->base.retry_cnt;
+	attr->rnr_retry		  = cmd->base.rnr_retry;
+	attr->alt_port_num	  = cmd->base.alt_port_num;
+	attr->alt_timeout	  = cmd->base.alt_timeout;
+	attr->rate_limit	  = cmd->rate_limit;
 
-	memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
-	attr->ah_attr.grh.flow_label        = cmd.dest.flow_label;
-	attr->ah_attr.grh.sgid_index        = cmd.dest.sgid_index;
-	attr->ah_attr.grh.hop_limit         = cmd.dest.hop_limit;
-	attr->ah_attr.grh.traffic_class     = cmd.dest.traffic_class;
-	attr->ah_attr.dlid 	    	    = cmd.dest.dlid;
-	attr->ah_attr.sl   	    	    = cmd.dest.sl;
-	attr->ah_attr.src_path_bits 	    = cmd.dest.src_path_bits;
-	attr->ah_attr.static_rate   	    = cmd.dest.static_rate;
-	attr->ah_attr.ah_flags 	    	    = cmd.dest.is_global ? IB_AH_GRH : 0;
-	attr->ah_attr.port_num 	    	    = cmd.dest.port_num;
+	memcpy(attr->ah_attr.grh.dgid.raw, cmd->base.dest.dgid, 16);
+	attr->ah_attr.grh.flow_label	= cmd->base.dest.flow_label;
+	attr->ah_attr.grh.sgid_index	= cmd->base.dest.sgid_index;
+	attr->ah_attr.grh.hop_limit	= cmd->base.dest.hop_limit;
+	attr->ah_attr.grh.traffic_class	= cmd->base.dest.traffic_class;
+	attr->ah_attr.dlid		= cmd->base.dest.dlid;
+	attr->ah_attr.sl		= cmd->base.dest.sl;
+	attr->ah_attr.src_path_bits	= cmd->base.dest.src_path_bits;
+	attr->ah_attr.static_rate	= cmd->base.dest.static_rate;
+	attr->ah_attr.ah_flags		= cmd->base.dest.is_global ?
+					  IB_AH_GRH : 0;
+	attr->ah_attr.port_num		= cmd->base.dest.port_num;
 
-	memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
-	attr->alt_ah_attr.grh.flow_label    = cmd.alt_dest.flow_label;
-	attr->alt_ah_attr.grh.sgid_index    = cmd.alt_dest.sgid_index;
-	attr->alt_ah_attr.grh.hop_limit     = cmd.alt_dest.hop_limit;
-	attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
-	attr->alt_ah_attr.dlid 	    	    = cmd.alt_dest.dlid;
-	attr->alt_ah_attr.sl   	    	    = cmd.alt_dest.sl;
-	attr->alt_ah_attr.src_path_bits     = cmd.alt_dest.src_path_bits;
-	attr->alt_ah_attr.static_rate       = cmd.alt_dest.static_rate;
-	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;
+	memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd->base.alt_dest.dgid, 16);
+	attr->alt_ah_attr.grh.flow_label    = cmd->base.alt_dest.flow_label;
+	attr->alt_ah_attr.grh.sgid_index    = cmd->base.alt_dest.sgid_index;
+	attr->alt_ah_attr.grh.hop_limit     = cmd->base.alt_dest.hop_limit;
+	attr->alt_ah_attr.grh.traffic_class = cmd->base.alt_dest.traffic_class;
+	attr->alt_ah_attr.dlid		    = cmd->base.alt_dest.dlid;
+	attr->alt_ah_attr.sl		    = cmd->base.alt_dest.sl;
+	attr->alt_ah_attr.src_path_bits	    = cmd->base.alt_dest.src_path_bits;
+	attr->alt_ah_attr.static_rate	    = cmd->base.alt_dest.static_rate;
+	attr->alt_ah_attr.ah_flags	    = cmd->base.alt_dest.is_global ?
+					      IB_AH_GRH : 0;
+	attr->alt_ah_attr.port_num	    = cmd->base.alt_dest.port_num;
 
 	if (qp->real_qp == qp) {
-		ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask);
-		if (ret)
-			goto release_qp;
+		if (cmd->base.attr_mask & IB_QP_AV) {
+			ret = ib_resolve_eth_dmac(qp->device, &attr->ah_attr);
+			if (ret)
+				goto release_qp;
+		}
 		ret = qp->device->modify_qp(qp, attr,
-			modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+					    modify_qp_mask(qp->qp_type,
+							   cmd->base.attr_mask),
+					    udata);
 	} else {
-		ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+		ret = ib_modify_qp(qp, attr,
+				   modify_qp_mask(qp->qp_type,
+						  cmd->base.attr_mask));
 	}
 
-	if (ret)
-		goto release_qp;
-
-	ret = in_len;
-
 release_qp:
 	put_qp_read(qp);
 
@@ -2425,6 +2419,68 @@ out:
 	return ret;
 }
 
+ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
+			    struct ib_device *ib_dev,
+			    const char __user *buf, int in_len,
+			    int out_len)
+{
+	struct ib_uverbs_ex_modify_qp cmd = {};
+	struct ib_udata udata;
+	int ret;
+
+	if (copy_from_user(&cmd.base, buf, sizeof(cmd.base)))
+		return -EFAULT;
+
+	if (cmd.base.attr_mask &
+	    ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1))
+		return -EOPNOTSUPP;
+
+	INIT_UDATA(&udata, buf + sizeof(cmd.base), NULL,
+		   in_len - sizeof(cmd.base), out_len);
+
+	ret = modify_qp(file, &cmd, &udata);
+	if (ret)
+		return ret;
+
+	return in_len;
+}
+
+int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file,
+			   struct ib_device *ib_dev,
+			   struct ib_udata *ucore,
+			   struct ib_udata *uhw)
+{
+	struct ib_uverbs_ex_modify_qp cmd = {};
+	int ret;
+
+	/*
+	 * Last bit is reserved for extending the attr_mask by
+	 * using another field.
+	 */
+	BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31));
+
+	if (ucore->inlen < sizeof(cmd.base))
+		return -EINVAL;
+
+	ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen));
+	if (ret)
+		return ret;
+
+	if (cmd.base.attr_mask &
+	    ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1))
+		return -EOPNOTSUPP;
+
+	if (ucore->inlen > sizeof(cmd)) {
+		if (ib_is_udata_cleared(ucore, sizeof(cmd),
+					ucore->inlen - sizeof(cmd)))
+			return -EOPNOTSUPP;
+	}
+
+	ret = modify_qp(file, &cmd, uhw);
+
+	return ret;
+}
+
 ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
 			     struct ib_device *ib_dev,
 			     const char __user *buf, int in_len,
@@ -2875,6 +2931,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uv
 	struct ib_ah			*ah;
 	struct ib_ah_attr		attr;
 	int ret;
+	struct ib_udata                   udata;
 
 	if (out_len < sizeof resp)
 		return -ENOSPC;
@@ -2882,6 +2939,10 @@ ssize_t ib_uverbs_create_ah(struct ib_uv
 	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));
+
 	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
 	if (!uobj)
 		return -ENOMEM;
@@ -2908,12 +2969,16 @@ ssize_t ib_uverbs_create_ah(struct ib_uv
 	memset(&attr.dmac, 0, sizeof(attr.dmac));
 	memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);
 
-	ah = ib_create_ah(pd, &attr);
+	ah = pd->device->create_ah(pd, &attr, &udata);
+
 	if (IS_ERR(ah)) {
 		ret = PTR_ERR(ah);
 		goto err_put;
 	}
 
+	ah->device  = pd->device;
+	ah->pd      = pd;
+	atomic_inc(&pd->usecnt);
 	ah->uobject  = uobj;
 	uobj->object = ah;
 
@@ -3124,8 +3189,10 @@ static int kern_spec_to_ib_spec(struct i
 	kern_spec_val = (void *)kern_spec +
 		sizeof(struct ib_uverbs_flow_spec_hdr);
 	kern_spec_mask = kern_spec_val + kern_filter_sz;
+	if (ib_spec->type == (IB_FLOW_SPEC_INNER | IB_FLOW_SPEC_VXLAN_TUNNEL))
+		return -EINVAL;
 
-	switch (ib_spec->type) {
+	switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) {
 	case IB_FLOW_SPEC_ETH:
 		ib_filter_sz = offsetof(struct ib_flow_eth_filter, real_sz);
 		actual_filter_sz = spec_filter_size(kern_spec_mask,
@@ -3175,6 +3242,21 @@ static int kern_spec_to_ib_spec(struct i
 		memcpy(&ib_spec->tcp_udp.val, kern_spec_val, actual_filter_sz);
 		memcpy(&ib_spec->tcp_udp.mask, kern_spec_mask, actual_filter_sz);
 		break;
+	case IB_FLOW_SPEC_VXLAN_TUNNEL:
+		ib_filter_sz = offsetof(struct ib_flow_tunnel_filter, real_sz);
+		actual_filter_sz = spec_filter_size(kern_spec_mask,
+						    kern_filter_sz,
+						    ib_filter_sz);
+		if (actual_filter_sz <= 0)
+			return -EINVAL;
+		ib_spec->tunnel.size = sizeof(struct ib_flow_spec_tunnel);
+		memcpy(&ib_spec->tunnel.val, kern_spec_val, actual_filter_sz);
+		memcpy(&ib_spec->tunnel.mask, kern_spec_mask, actual_filter_sz);
+
+		if ((ntohl(ib_spec->tunnel.mask.tunnel_id)) >= BIT(24) ||
+		    (ntohl(ib_spec->tunnel.val.tunnel_id)) >= BIT(24))
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -3745,7 +3827,6 @@ int ib_uverbs_ex_create_flow(struct ib_u
 		err = PTR_ERR(flow_id);
 		goto err_free;
 	}
-	flow_id->qp = qp;
 	flow_id->uobject = uobj;
 	uobj->object = flow_id;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/uverbs.h linux-libre-4.10-rc8-gnu/drivers/infiniband/core/uverbs.h
--- linux-libre-4.9-gnu/drivers/infiniband/core/uverbs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/uverbs.h	2017-02-12 16:03:20.000000000 -0500
@@ -289,5 +289,6 @@ IB_UVERBS_DECLARE_EX_CMD(modify_wq);
 IB_UVERBS_DECLARE_EX_CMD(destroy_wq);
 IB_UVERBS_DECLARE_EX_CMD(create_rwq_ind_table);
 IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table);
+IB_UVERBS_DECLARE_EX_CMD(modify_qp);
 
 #endif /* UVERBS_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/uverbs_main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/uverbs_main.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/uverbs_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/uverbs_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 #include <linux/anon_inodes.h>
 #include <linux/slab.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <rdma/ib.h>
 
@@ -137,6 +137,7 @@ static int (*uverbs_ex_cmd_table[])(stru
 	[IB_USER_VERBS_EX_CMD_DESTROY_WQ]       = ib_uverbs_ex_destroy_wq,
 	[IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table,
 	[IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table,
+	[IB_USER_VERBS_EX_CMD_MODIFY_QP]        = ib_uverbs_ex_modify_qp,
 };
 
 static void ib_uverbs_add_one(struct ib_device *device);
@@ -746,8 +747,11 @@ static ssize_t ib_uverbs_write(struct fi
 	int srcu_key;
 	ssize_t ret;
 
-	if (WARN_ON_ONCE(!ib_safe_file_access(filp)))
+	if (!ib_safe_file_access(filp)) {
+		pr_err_once("uverbs_write: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n",
+			    task_tgid_vnr(current), current->comm);
 		return -EACCES;
+	}
 
 	if (count < sizeof hdr)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/core/verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/core/verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/core/verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/core/verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -315,7 +315,7 @@ struct ib_ah *ib_create_ah(struct ib_pd
 {
 	struct ib_ah *ah;
 
-	ah = pd->device->create_ah(pd, ah_attr);
+	ah = pd->device->create_ah(pd, ah_attr, NULL);
 
 	if (!IS_ERR(ah)) {
 		ah->device  = pd->device;
@@ -328,7 +328,7 @@ struct ib_ah *ib_create_ah(struct ib_pd
 }
 EXPORT_SYMBOL(ib_create_ah);
 
-static int ib_get_header_version(const union rdma_network_hdr *hdr)
+int ib_get_rdma_header_version(const union rdma_network_hdr *hdr)
 {
 	const struct iphdr *ip4h = (struct iphdr *)&hdr->roce4grh;
 	struct iphdr ip4h_checked;
@@ -359,6 +359,7 @@ static int ib_get_header_version(const u
 		return 4;
 	return 6;
 }
+EXPORT_SYMBOL(ib_get_rdma_header_version);
 
 static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device,
 						     u8 port_num,
@@ -369,7 +370,7 @@ static enum rdma_network_type ib_get_net
 	if (rdma_protocol_ib(device, port_num))
 		return RDMA_NETWORK_IB;
 
-	grh_version = ib_get_header_version((union rdma_network_hdr *)grh);
+	grh_version = ib_get_rdma_header_version((union rdma_network_hdr *)grh);
 
 	if (grh_version == 4)
 		return RDMA_NETWORK_IPV4;
@@ -415,9 +416,9 @@ static int get_sgid_index_from_eth(struc
 				     &context, gid_index);
 }
 
-static int get_gids_from_rdma_hdr(union rdma_network_hdr *hdr,
-				  enum rdma_network_type net_type,
-				  union ib_gid *sgid, union ib_gid *dgid)
+int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
+			      enum rdma_network_type net_type,
+			      union ib_gid *sgid, union ib_gid *dgid)
 {
 	struct sockaddr_in  src_in;
 	struct sockaddr_in  dst_in;
@@ -447,6 +448,7 @@ static int get_gids_from_rdma_hdr(union
 		return -EINVAL;
 	}
 }
+EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr);
 
 int ib_init_ah_from_wc(struct ib_device *device, u8 port_num,
 		       const struct ib_wc *wc, const struct ib_grh *grh,
@@ -469,8 +471,8 @@ int ib_init_ah_from_wc(struct ib_device
 			net_type = ib_get_net_type_by_grh(device, port_num, grh);
 		gid_type = ib_network_to_gid_type(net_type);
 	}
-	ret = get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
-				     &sgid, &dgid);
+	ret = ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
+					&sgid, &dgid);
 	if (ret)
 		return ret;
 
@@ -1014,6 +1016,7 @@ static const struct {
 						 IB_QP_QKEY),
 				 [IB_QPT_GSI] = (IB_QP_CUR_STATE		|
 						 IB_QP_QKEY),
+				 [IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT,
 			 }
 		}
 	},
@@ -1047,6 +1050,7 @@ static const struct {
 						IB_QP_QKEY),
 				[IB_QPT_GSI] = (IB_QP_CUR_STATE			|
 						IB_QP_QKEY),
+				[IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT,
 			}
 		},
 		[IB_QPS_SQD]   = {
@@ -1196,66 +1200,66 @@ int ib_modify_qp_is_ok(enum ib_qp_state
 }
 EXPORT_SYMBOL(ib_modify_qp_is_ok);
 
-int ib_resolve_eth_dmac(struct ib_qp *qp,
-			struct ib_qp_attr *qp_attr, int *qp_attr_mask)
+int ib_resolve_eth_dmac(struct ib_device *device,
+			struct ib_ah_attr *ah_attr)
 {
 	int           ret = 0;
 
-	if (*qp_attr_mask & IB_QP_AV) {
-		if (qp_attr->ah_attr.port_num < rdma_start_port(qp->device) ||
-		    qp_attr->ah_attr.port_num > rdma_end_port(qp->device))
-			return -EINVAL;
+	if (ah_attr->port_num < rdma_start_port(device) ||
+	    ah_attr->port_num > rdma_end_port(device))
+		return -EINVAL;
 
-		if (!rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num))
-			return 0;
+	if (!rdma_cap_eth_ah(device, ah_attr->port_num))
+		return 0;
 
-		if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) {
-			rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw,
-					qp_attr->ah_attr.dmac);
-		} else {
-			union ib_gid		sgid;
-			struct ib_gid_attr	sgid_attr;
-			int			ifindex;
-			int			hop_limit;
+	if (rdma_link_local_addr((struct in6_addr *)ah_attr->grh.dgid.raw)) {
+		rdma_get_ll_mac((struct in6_addr *)ah_attr->grh.dgid.raw,
+				ah_attr->dmac);
+	} else {
+		union ib_gid		sgid;
+		struct ib_gid_attr	sgid_attr;
+		int			ifindex;
+		int			hop_limit;
 
-			ret = ib_query_gid(qp->device,
-					   qp_attr->ah_attr.port_num,
-					   qp_attr->ah_attr.grh.sgid_index,
-					   &sgid, &sgid_attr);
+		ret = ib_query_gid(device,
+				   ah_attr->port_num,
+				   ah_attr->grh.sgid_index,
+				   &sgid, &sgid_attr);
 
-			if (ret || !sgid_attr.ndev) {
-				if (!ret)
-					ret = -ENXIO;
-				goto out;
-			}
+		if (ret || !sgid_attr.ndev) {
+			if (!ret)
+				ret = -ENXIO;
+			goto out;
+		}
 
-			ifindex = sgid_attr.ndev->ifindex;
+		ifindex = sgid_attr.ndev->ifindex;
 
-			ret = rdma_addr_find_l2_eth_by_grh(&sgid,
-							   &qp_attr->ah_attr.grh.dgid,
-							   qp_attr->ah_attr.dmac,
-							   NULL, &ifindex, &hop_limit);
+		ret = rdma_addr_find_l2_eth_by_grh(&sgid,
+						   &ah_attr->grh.dgid,
+						   ah_attr->dmac,
+						   NULL, &ifindex, &hop_limit);
 
-			dev_put(sgid_attr.ndev);
+		dev_put(sgid_attr.ndev);
 
-			qp_attr->ah_attr.grh.hop_limit = hop_limit;
-		}
+		ah_attr->grh.hop_limit = hop_limit;
 	}
 out:
 	return ret;
 }
 EXPORT_SYMBOL(ib_resolve_eth_dmac);
 
-
 int ib_modify_qp(struct ib_qp *qp,
 		 struct ib_qp_attr *qp_attr,
 		 int qp_attr_mask)
 {
-	int ret;
 
-	ret = ib_resolve_eth_dmac(qp, qp_attr, &qp_attr_mask);
-	if (ret)
-		return ret;
+	if (qp_attr_mask & IB_QP_AV) {
+		int ret;
+
+		ret = ib_resolve_eth_dmac(qp->device, &qp_attr->ah_attr);
+		if (ret)
+			return ret;
+	}
 
 	return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL);
 }
@@ -1734,8 +1738,10 @@ struct ib_flow *ib_create_flow(struct ib
 		return ERR_PTR(-ENOSYS);
 
 	flow_id = qp->device->create_flow(qp, flow_attr, domain);
-	if (!IS_ERR(flow_id))
+	if (!IS_ERR(flow_id)) {
 		atomic_inc(&qp->usecnt);
+		flow_id->qp = qp;
+	}
 	return flow_id;
 }
 EXPORT_SYMBOL(ib_create_flow);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb3/cxio_dbg.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb3/cxio_dbg.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb3/cxio_dbg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb3/cxio_dbg.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,10 +45,9 @@ void cxio_dump_tpt(struct cxio_rdev *rde
 	int size = 32;
 
 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
-	if (!m) {
-		PDBG("%s couldn't allocate memory.\n", __func__);
+	if (!m)
 		return;
-	}
+
 	m->mem_id = MEM_PMRX;
 	m->addr = (stag>>8) * 32 + rdev->rnic_info.tpt_base;
 	m->len = size;
@@ -82,10 +81,9 @@ void cxio_dump_pbl(struct cxio_rdev *rde
 	size = npages * sizeof(u64);
 
 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
-	if (!m) {
-		PDBG("%s couldn't allocate memory.\n", __func__);
+	if (!m)
 		return;
-	}
+
 	m->mem_id = MEM_PMRX;
 	m->addr = pbl_addr;
 	m->len = size;
@@ -144,10 +142,9 @@ void cxio_dump_rqt(struct cxio_rdev *rde
 	int rc;
 
 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
-	if (!m) {
-		PDBG("%s couldn't allocate memory.\n", __func__);
+	if (!m)
 		return;
-	}
+
 	m->mem_id = MEM_PMRX;
 	m->addr = ((hwtid)<<10) + rdev->rnic_info.rqt_base;
 	m->len = size;
@@ -177,10 +174,9 @@ void cxio_dump_tcb(struct cxio_rdev *rde
 	int rc;
 
 	m = kmalloc(sizeof(*m) + size, GFP_ATOMIC);
-	if (!m) {
-		PDBG("%s couldn't allocate memory.\n", __func__);
+	if (!m)
 		return;
-	}
+
 	m->mem_id = MEM_CM;
 	m->addr = hwtid * size;
 	m->len = size;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb3/iwch_provider.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,8 @@
 #include "common.h"
 
 static struct ib_ah *iwch_ah_create(struct ib_pd *pd,
-				    struct ib_ah_attr *ah_attr)
+				    struct ib_ah_attr *ah_attr,
+				    struct ib_udata *udata)
 {
 	return ERR_PTR(-ENOSYS);
 }
@@ -1134,16 +1135,7 @@ static int iwch_query_port(struct ib_dev
 
 	memset(props, 0, sizeof(struct ib_port_attr));
 	props->max_mtu = IB_MTU_4096;
-	if (netdev->mtu >= 4096)
-		props->active_mtu = IB_MTU_4096;
-	else if (netdev->mtu >= 2048)
-		props->active_mtu = IB_MTU_2048;
-	else if (netdev->mtu >= 1024)
-		props->active_mtu = IB_MTU_1024;
-	else if (netdev->mtu >= 512)
-		props->active_mtu = IB_MTU_512;
-	else
-		props->active_mtu = IB_MTU_256;
+	props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
 	if (!netif_carrier_ok(netdev))
 		props->state = IB_PORT_DOWN;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/cm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/cm.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -1804,20 +1804,21 @@ static int rx_data(struct c4iw_dev *dev,
 	skb_trim(skb, dlen);
 	mutex_lock(&ep->com.mutex);
 
-	/* update RX credits */
-	update_rx_credits(ep, dlen);
-
 	switch (ep->com.state) {
 	case MPA_REQ_SENT:
+		update_rx_credits(ep, dlen);
 		ep->rcv_seq += dlen;
 		disconnect = process_mpa_reply(ep, skb);
 		break;
 	case MPA_REQ_WAIT:
+		update_rx_credits(ep, dlen);
 		ep->rcv_seq += dlen;
 		disconnect = process_mpa_request(ep, skb);
 		break;
 	case FPDU_MODE: {
 		struct c4iw_qp_attributes attrs;
+
+		update_rx_credits(ep, dlen);
 		BUG_ON(!ep->com.qp);
 		if (status)
 			pr_err("%s Unexpected streaming data." \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/cq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/cq.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/cq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/cq.c	2017-02-12 16:03:20.000000000 -0500
@@ -505,6 +505,15 @@ static int poll_cq(struct t4_wq *wq, str
 	}
 
 	/*
+	 * Special cqe for drain WR completions...
+	 */
+	if (CQE_OPCODE(hw_cqe) == C4IW_DRAIN_OPCODE) {
+		*cookie = CQE_DRAIN_COOKIE(hw_cqe);
+		*cqe = *hw_cqe;
+		goto skip_cqe;
+	}
+
+	/*
 	 * Gotta tweak READ completions:
 	 *	1) the cqe doesn't contain the sq_wptr from the wr.
 	 *	2) opcode not reflected from the wr.
@@ -753,6 +762,9 @@ static int c4iw_poll_cq_one(struct c4iw_
 				c4iw_invalidate_mr(qhp->rhp,
 						   CQE_WRID_FR_STAG(&cqe));
 			break;
+		case C4IW_DRAIN_OPCODE:
+			wc->opcode = IB_WC_SEND;
+			break;
 		default:
 			printk(KERN_ERR MOD "Unexpected opcode %d "
 			       "in the CQE received for QPID=0x%0x\n",
@@ -817,15 +829,8 @@ static int c4iw_poll_cq_one(struct c4iw_
 		}
 	}
 out:
-	if (wq) {
-		if (unlikely(qhp->attr.state != C4IW_QP_STATE_RTS)) {
-			if (t4_sq_empty(wq))
-				complete(&qhp->sq_drained);
-			if (t4_rq_empty(wq))
-				complete(&qhp->rq_drained);
-		}
+	if (wq)
 		spin_unlock(&qhp->lock);
-	}
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/device.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/device.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/device.c	2017-02-12 16:03:20.000000000 -0500
@@ -828,8 +828,10 @@ static int c4iw_rdev_open(struct c4iw_rd
 	}
 	rdev->status_page = (struct t4_dev_status_page *)
 			    __get_free_page(GFP_KERNEL);
-	if (!rdev->status_page)
+	if (!rdev->status_page) {
+		err = -ENOMEM;
 		goto destroy_ocqp_pool;
+	}
 	rdev->status_page->qp_start = rdev->lldi.vr->qp.start;
 	rdev->status_page->qp_size = rdev->lldi.vr->qp.size;
 	rdev->status_page->cq_start = rdev->lldi.vr->cq.start;
@@ -841,14 +843,20 @@ static int c4iw_rdev_open(struct c4iw_rd
 		if (rdev->wr_log) {
 			rdev->wr_log_size = 1 << c4iw_wr_log_size_order;
 			atomic_set(&rdev->wr_log_idx, 0);
-		} else {
-			pr_err(MOD "error allocating wr_log. Logging disabled\n");
 		}
 	}
 
+	rdev->free_workq = create_singlethread_workqueue("iw_cxgb4_free");
+	if (!rdev->free_workq) {
+		err = -ENOMEM;
+		goto err_free_status_page;
+	}
+
 	rdev->status_page->db_off = 0;
 
 	return 0;
+err_free_status_page:
+	free_page((unsigned long)rdev->status_page);
 destroy_ocqp_pool:
 	c4iw_ocqp_pool_destroy(rdev);
 destroy_rqtpool:
@@ -862,6 +870,7 @@ destroy_resource:
 
 static void c4iw_rdev_close(struct c4iw_rdev *rdev)
 {
+	destroy_workqueue(rdev->free_workq);
 	kfree(rdev->wr_log);
 	free_page((unsigned long)rdev->status_page);
 	c4iw_pblpool_destroy(rdev);
@@ -1424,8 +1433,6 @@ static void recover_queues(struct uld_ct
 
 	qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC);
 	if (!qp_list.qps) {
-		printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n",
-		       pci_name(ctx->lldi.pdev));
 		spin_unlock_irq(&ctx->dev->lock);
 		return;
 	}
@@ -1481,6 +1488,7 @@ static int c4iw_uld_control(void *handle
 static struct cxgb4_uld_info c4iw_uld_info = {
 	.name = DRV_NAME,
 	.nrxq = MAX_ULD_QSETS,
+	.ntxq = MAX_ULD_QSETS,
 	.rxq_size = 511,
 	.ciq = true,
 	.lro = false,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2017-02-12 16:03:20.000000000 -0500
@@ -45,6 +45,7 @@
 #include <linux/kref.h>
 #include <linux/timer.h>
 #include <linux/io.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 
@@ -107,6 +108,7 @@ struct c4iw_dev_ucontext {
 	struct list_head qpids;
 	struct list_head cqids;
 	struct mutex lock;
+	struct kref kref;
 };
 
 enum c4iw_rdev_flags {
@@ -183,6 +185,7 @@ struct c4iw_rdev {
 	atomic_t wr_log_idx;
 	struct wr_log_entry *wr_log;
 	int wr_log_size;
+	struct workqueue_struct *free_workq;
 };
 
 static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
@@ -480,8 +483,8 @@ struct c4iw_qp {
 	wait_queue_head_t wait;
 	struct timer_list timer;
 	int sq_sig_all;
-	struct completion rq_drained;
-	struct completion sq_drained;
+	struct work_struct free_work;
+	struct c4iw_ucontext *ucontext;
 };
 
 static inline struct c4iw_qp *to_c4iw_qp(struct ib_qp *ibqp)
@@ -495,6 +498,7 @@ struct c4iw_ucontext {
 	u32 key;
 	spinlock_t mmap_lock;
 	struct list_head mmaps;
+	struct kref kref;
 };
 
 static inline struct c4iw_ucontext *to_c4iw_ucontext(struct ib_ucontext *c)
@@ -502,6 +506,18 @@ static inline struct c4iw_ucontext *to_c
 	return container_of(c, struct c4iw_ucontext, ibucontext);
 }
 
+void _c4iw_free_ucontext(struct kref *kref);
+
+static inline void c4iw_put_ucontext(struct c4iw_ucontext *ucontext)
+{
+	kref_put(&ucontext->kref, _c4iw_free_ucontext);
+}
+
+static inline void c4iw_get_ucontext(struct c4iw_ucontext *ucontext)
+{
+	kref_get(&ucontext->kref);
+}
+
 struct c4iw_mm_entry {
 	struct list_head entry;
 	u64 addr;
@@ -615,6 +631,8 @@ static inline int to_ib_qp_state(int c4i
 	return IB_QPS_ERR;
 }
 
+#define C4IW_DRAIN_OPCODE FW_RI_SGE_EC_CR_RETURN
+
 static inline u32 c4iw_ib_to_tpt_access(int a)
 {
 	return (a & IB_ACCESS_REMOTE_WRITE ? FW_RI_MEM_ACCESS_REM_WRITE : 0) |
@@ -997,8 +1015,6 @@ extern int c4iw_wr_log;
 extern int db_fc_threshold;
 extern int db_coalescing_threshold;
 extern int use_dsgl;
-void c4iw_drain_rq(struct ib_qp *qp);
-void c4iw_drain_sq(struct ib_qp *qp);
 void c4iw_invalidate_mr(struct c4iw_dev *rhp, u32 rkey);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/provider.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/provider.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/provider.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/provider.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,7 +59,9 @@ module_param(fastreg_support, int, 0644)
 MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=1)");
 
 static struct ib_ah *c4iw_ah_create(struct ib_pd *pd,
-				    struct ib_ah_attr *ah_attr)
+				    struct ib_ah_attr *ah_attr,
+				    struct ib_udata *udata)
+
 {
 	return ERR_PTR(-ENOSYS);
 }
@@ -91,17 +93,28 @@ static int c4iw_process_mad(struct ib_de
 	return -ENOSYS;
 }
 
-static int c4iw_dealloc_ucontext(struct ib_ucontext *context)
+void _c4iw_free_ucontext(struct kref *kref)
 {
-	struct c4iw_dev *rhp = to_c4iw_dev(context->device);
-	struct c4iw_ucontext *ucontext = to_c4iw_ucontext(context);
+	struct c4iw_ucontext *ucontext;
+	struct c4iw_dev *rhp;
 	struct c4iw_mm_entry *mm, *tmp;
 
-	PDBG("%s context %p\n", __func__, context);
+	ucontext = container_of(kref, struct c4iw_ucontext, kref);
+	rhp = to_c4iw_dev(ucontext->ibucontext.device);
+
+	PDBG("%s ucontext %p\n", __func__, ucontext);
 	list_for_each_entry_safe(mm, tmp, &ucontext->mmaps, entry)
 		kfree(mm);
 	c4iw_release_dev_ucontext(&rhp->rdev, &ucontext->uctx);
 	kfree(ucontext);
+}
+
+static int c4iw_dealloc_ucontext(struct ib_ucontext *context)
+{
+	struct c4iw_ucontext *ucontext = to_c4iw_ucontext(context);
+
+	PDBG("%s context %p\n", __func__, context);
+	c4iw_put_ucontext(ucontext);
 	return 0;
 }
 
@@ -125,6 +138,7 @@ static struct ib_ucontext *c4iw_alloc_uc
 	c4iw_init_dev_ucontext(&rhp->rdev, &context->uctx);
 	INIT_LIST_HEAD(&context->mmaps);
 	spin_lock_init(&context->mmap_lock);
+	kref_init(&context->kref);
 
 	if (udata->outlen < sizeof(uresp) - sizeof(uresp.reserved)) {
 		if (!warned++)
@@ -359,16 +373,7 @@ static int c4iw_query_port(struct ib_dev
 
 	memset(props, 0, sizeof(struct ib_port_attr));
 	props->max_mtu = IB_MTU_4096;
-	if (netdev->mtu >= 4096)
-		props->active_mtu = IB_MTU_4096;
-	else if (netdev->mtu >= 2048)
-		props->active_mtu = IB_MTU_2048;
-	else if (netdev->mtu >= 1024)
-		props->active_mtu = IB_MTU_1024;
-	else if (netdev->mtu >= 512)
-		props->active_mtu = IB_MTU_512;
-	else
-		props->active_mtu = IB_MTU_256;
+	props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
 	if (!netif_carrier_ok(netdev))
 		props->state = IB_PORT_DOWN;
@@ -605,8 +610,6 @@ int c4iw_register_device(struct c4iw_dev
 	dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
 	dev->ibdev.get_port_immutable = c4iw_port_immutable;
 	dev->ibdev.get_dev_fw_str = get_dev_fw_str;
-	dev->ibdev.drain_sq = c4iw_drain_sq;
-	dev->ibdev.drain_rq = c4iw_drain_rq;
 
 	dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
 	if (!dev->ibdev.iwcm)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/qp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -321,7 +321,8 @@ static int create_qp(struct c4iw_rdev *r
 		FW_RI_RES_WR_DCAEN_V(0) |
 		FW_RI_RES_WR_DCACPU_V(0) |
 		FW_RI_RES_WR_FBMIN_V(2) |
-		FW_RI_RES_WR_FBMAX_V(2) |
+		(t4_sq_onchip(&wq->sq) ? FW_RI_RES_WR_FBMAX_V(2) :
+					 FW_RI_RES_WR_FBMAX_V(3)) |
 		FW_RI_RES_WR_CIDXFTHRESHO_V(0) |
 		FW_RI_RES_WR_CIDXFTHRESH_V(0) |
 		FW_RI_RES_WR_EQSIZE_V(eqsize));
@@ -345,7 +346,7 @@ static int create_qp(struct c4iw_rdev *r
 		FW_RI_RES_WR_DCAEN_V(0) |
 		FW_RI_RES_WR_DCACPU_V(0) |
 		FW_RI_RES_WR_FBMIN_V(2) |
-		FW_RI_RES_WR_FBMAX_V(2) |
+		FW_RI_RES_WR_FBMAX_V(3) |
 		FW_RI_RES_WR_CIDXFTHRESHO_V(0) |
 		FW_RI_RES_WR_CIDXFTHRESH_V(0) |
 		FW_RI_RES_WR_EQSIZE_V(eqsize));
@@ -714,13 +715,32 @@ static int build_inv_stag(union t4_wr *w
 	return 0;
 }
 
-static void _free_qp(struct kref *kref)
+static void free_qp_work(struct work_struct *work)
+{
+	struct c4iw_ucontext *ucontext;
+	struct c4iw_qp *qhp;
+	struct c4iw_dev *rhp;
+
+	qhp = container_of(work, struct c4iw_qp, free_work);
+	ucontext = qhp->ucontext;
+	rhp = qhp->rhp;
+
+	PDBG("%s qhp %p ucontext %p\n", __func__, qhp, ucontext);
+	destroy_qp(&rhp->rdev, &qhp->wq,
+		   ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
+
+	if (ucontext)
+		c4iw_put_ucontext(ucontext);
+	kfree(qhp);
+}
+
+static void queue_qp_free(struct kref *kref)
 {
 	struct c4iw_qp *qhp;
 
 	qhp = container_of(kref, struct c4iw_qp, kref);
 	PDBG("%s qhp %p\n", __func__, qhp);
-	kfree(qhp);
+	queue_work(qhp->rhp->rdev.free_workq, &qhp->free_work);
 }
 
 void c4iw_qp_add_ref(struct ib_qp *qp)
@@ -732,7 +752,7 @@ void c4iw_qp_add_ref(struct ib_qp *qp)
 void c4iw_qp_rem_ref(struct ib_qp *qp)
 {
 	PDBG("%s ib_qp %p\n", __func__, qp);
-	kref_put(&to_c4iw_qp(qp)->kref, _free_qp);
+	kref_put(&to_c4iw_qp(qp)->kref, queue_qp_free);
 }
 
 static void add_to_fc_list(struct list_head *head, struct list_head *entry)
@@ -775,6 +795,64 @@ static int ring_kernel_rq_db(struct c4iw
 	return 0;
 }
 
+static void complete_sq_drain_wr(struct c4iw_qp *qhp, struct ib_send_wr *wr)
+{
+	struct t4_cqe cqe = {};
+	struct c4iw_cq *schp;
+	unsigned long flag;
+	struct t4_cq *cq;
+
+	schp = to_c4iw_cq(qhp->ibqp.send_cq);
+	cq = &schp->cq;
+
+	cqe.u.drain_cookie = wr->wr_id;
+	cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) |
+				 CQE_OPCODE_V(C4IW_DRAIN_OPCODE) |
+				 CQE_TYPE_V(1) |
+				 CQE_SWCQE_V(1) |
+				 CQE_QPID_V(qhp->wq.sq.qid));
+
+	spin_lock_irqsave(&schp->lock, flag);
+	cqe.bits_type_ts = cpu_to_be64(CQE_GENBIT_V((u64)cq->gen));
+	cq->sw_queue[cq->sw_pidx] = cqe;
+	t4_swcq_produce(cq);
+	spin_unlock_irqrestore(&schp->lock, flag);
+
+	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 complete_rq_drain_wr(struct c4iw_qp *qhp, struct ib_recv_wr *wr)
+{
+	struct t4_cqe cqe = {};
+	struct c4iw_cq *rchp;
+	unsigned long flag;
+	struct t4_cq *cq;
+
+	rchp = to_c4iw_cq(qhp->ibqp.recv_cq);
+	cq = &rchp->cq;
+
+	cqe.u.drain_cookie = wr->wr_id;
+	cqe.header = cpu_to_be32(CQE_STATUS_V(T4_ERR_SWFLUSH) |
+				 CQE_OPCODE_V(C4IW_DRAIN_OPCODE) |
+				 CQE_TYPE_V(0) |
+				 CQE_SWCQE_V(1) |
+				 CQE_QPID_V(qhp->wq.sq.qid));
+
+	spin_lock_irqsave(&rchp->lock, flag);
+	cqe.bits_type_ts = cpu_to_be64(CQE_GENBIT_V((u64)cq->gen));
+	cq->sw_queue[cq->sw_pidx] = cqe;
+	t4_swcq_produce(cq);
+	spin_unlock_irqrestore(&rchp->lock, flag);
+
+	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);
+}
+
 int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		   struct ib_send_wr **bad_wr)
 {
@@ -793,8 +871,8 @@ int c4iw_post_send(struct ib_qp *ibqp, s
 	spin_lock_irqsave(&qhp->lock, flag);
 	if (t4_wq_in_error(&qhp->wq)) {
 		spin_unlock_irqrestore(&qhp->lock, flag);
-		*bad_wr = wr;
-		return -EINVAL;
+		complete_sq_drain_wr(qhp, wr);
+		return err;
 	}
 	num_wrs = t4_sq_avail(&qhp->wq);
 	if (num_wrs == 0) {
@@ -936,8 +1014,8 @@ int c4iw_post_receive(struct ib_qp *ibqp
 	spin_lock_irqsave(&qhp->lock, flag);
 	if (t4_wq_in_error(&qhp->wq)) {
 		spin_unlock_irqrestore(&qhp->lock, flag);
-		*bad_wr = wr;
-		return -EINVAL;
+		complete_rq_drain_wr(qhp, wr);
+		return err;
 	}
 	num_wrs = t4_rq_avail(&qhp->wq);
 	if (num_wrs == 0) {
@@ -1549,7 +1627,12 @@ int c4iw_modify_qp(struct c4iw_dev *rhp,
 		}
 		break;
 	case C4IW_QP_STATE_CLOSING:
-		if (!internal) {
+
+		/*
+		 * Allow kernel users to move to ERROR for qp draining.
+		 */
+		if (!internal && (qhp->ibqp.uobject || attrs->next_state !=
+				  C4IW_QP_STATE_ERROR)) {
 			ret = -EINVAL;
 			goto out;
 		}
@@ -1642,7 +1725,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
 	struct c4iw_dev *rhp;
 	struct c4iw_qp *qhp;
 	struct c4iw_qp_attributes attrs;
-	struct c4iw_ucontext *ucontext;
 
 	qhp = to_c4iw_qp(ib_qp);
 	rhp = qhp->rhp;
@@ -1662,11 +1744,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
 	spin_unlock_irq(&rhp->lock);
 	free_ird(rhp, qhp->attr.max_ird);
 
-	ucontext = ib_qp->uobject ?
-		   to_c4iw_ucontext(ib_qp->uobject->context) : NULL;
-	destroy_qp(&rhp->rdev, &qhp->wq,
-		   ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
-
 	c4iw_qp_rem_ref(ib_qp);
 
 	PDBG("%s ib_qp %p qpid 0x%0x\n", __func__, ib_qp, qhp->wq.sq.qid);
@@ -1762,11 +1839,10 @@ struct ib_qp *c4iw_create_qp(struct ib_p
 	qhp->attr.max_ird = 0;
 	qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
 	spin_lock_init(&qhp->lock);
-	init_completion(&qhp->sq_drained);
-	init_completion(&qhp->rq_drained);
 	mutex_init(&qhp->mutex);
 	init_waitqueue_head(&qhp->wait);
 	kref_init(&qhp->kref);
+	INIT_WORK(&qhp->free_work, free_qp_work);
 
 	ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
 	if (ret)
@@ -1853,6 +1929,9 @@ struct ib_qp *c4iw_create_qp(struct ib_p
 			ma_sync_key_mm->len = PAGE_SIZE;
 			insert_mmap(ucontext, ma_sync_key_mm);
 		}
+
+		c4iw_get_ucontext(ucontext);
+		qhp->ucontext = ucontext;
 	}
 	qhp->ibqp.qp_num = qhp->wq.sq.qid;
 	init_timer(&(qhp->timer));
@@ -1957,40 +2036,3 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp,
 	init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
 	return 0;
 }
-
-static void move_qp_to_err(struct c4iw_qp *qp)
-{
-	struct c4iw_qp_attributes attrs = { .next_state = C4IW_QP_STATE_ERROR };
-
-	(void)c4iw_modify_qp(qp->rhp, qp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
-}
-
-void c4iw_drain_sq(struct ib_qp *ibqp)
-{
-	struct c4iw_qp *qp = to_c4iw_qp(ibqp);
-	unsigned long flag;
-	bool need_to_wait;
-
-	move_qp_to_err(qp);
-	spin_lock_irqsave(&qp->lock, flag);
-	need_to_wait = !t4_sq_empty(&qp->wq);
-	spin_unlock_irqrestore(&qp->lock, flag);
-
-	if (need_to_wait)
-		wait_for_completion(&qp->sq_drained);
-}
-
-void c4iw_drain_rq(struct ib_qp *ibqp)
-{
-	struct c4iw_qp *qp = to_c4iw_qp(ibqp);
-	unsigned long flag;
-	bool need_to_wait;
-
-	move_qp_to_err(qp);
-	spin_lock_irqsave(&qp->lock, flag);
-	need_to_wait = !t4_rq_empty(&qp->wq);
-	spin_unlock_irqrestore(&qp->lock, flag);
-
-	if (need_to_wait)
-		wait_for_completion(&qp->rq_drained);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/t4.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/t4.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/cxgb4/t4.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/cxgb4/t4.h	2017-02-12 16:03:20.000000000 -0500
@@ -179,6 +179,7 @@ struct t4_cqe {
 			__be32 wrid_hi;
 			__be32 wrid_low;
 		} gen;
+		u64 drain_cookie;
 	} u;
 	__be64 reserved;
 	__be64 bits_type_ts;
@@ -238,6 +239,7 @@ struct t4_cqe {
 /* generic accessor macros */
 #define CQE_WRID_HI(x)		(be32_to_cpu((x)->u.gen.wrid_hi))
 #define CQE_WRID_LOW(x)		(be32_to_cpu((x)->u.gen.wrid_low))
+#define CQE_DRAIN_COOKIE(x)	((x)->u.drain_cookie)
 
 /* macros for flit 3 of the cqe */
 #define CQE_GENBIT_S	63
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/affinity.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/affinity.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/affinity.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/affinity.c	2017-02-12 16:03:20.000000000 -0500
@@ -125,6 +125,7 @@ int node_affinity_init(void)
 				cpumask_weight(topology_sibling_cpumask(
 					cpumask_first(&node_affinity.proc.mask)
 					));
+	node_affinity.num_possible_nodes = num_possible_nodes();
 	node_affinity.num_online_nodes = num_online_nodes();
 	node_affinity.num_online_cpus = num_online_cpus();
 
@@ -135,7 +136,7 @@ int node_affinity_init(void)
 	 */
 	init_real_cpu_mask();
 
-	hfi1_per_node_cntr = kcalloc(num_possible_nodes(),
+	hfi1_per_node_cntr = kcalloc(node_affinity.num_possible_nodes,
 				     sizeof(*hfi1_per_node_cntr), GFP_KERNEL);
 	if (!hfi1_per_node_cntr)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/affinity.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/affinity.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/affinity.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/affinity.h	2017-02-12 16:03:20.000000000 -0500
@@ -70,14 +70,6 @@ struct cpu_mask_set {
 	uint gen;
 };
 
-struct hfi1_affinity {
-	struct cpu_mask_set def_intr;
-	struct cpu_mask_set rcv_intr;
-	struct cpumask real_cpu_mask;
-	/* spin lock to protect affinity struct */
-	spinlock_t lock;
-};
-
 struct hfi1_msix_entry;
 
 /* Initialize non-HT cpu cores mask */
@@ -115,6 +107,7 @@ struct hfi1_affinity_node_list {
 	struct cpumask real_cpu_mask;
 	struct cpu_mask_set proc;
 	int num_core_siblings;
+	int num_possible_nodes;
 	int num_online_nodes;
 	int num_online_cpus;
 	struct mutex lock; /* protects affinity nodes */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/chip.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/chip.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/chip.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/chip.c	2017-02-12 16:03:20.000000000 -0500
@@ -8477,7 +8477,10 @@ static int do_8051_command(
 	 */
 	if (type == HCMD_WRITE_LCB_CSR) {
 		in_data |= ((*out_data) & 0xffffffffffull) << 8;
-		reg = ((((*out_data) >> 40) & 0xff) <<
+		/* must preserve COMPLETED - it is tied to hardware */
+		reg = read_csr(dd, DC_DC8051_CFG_EXT_DEV_0);
+		reg &= DC_DC8051_CFG_EXT_DEV_0_COMPLETED_SMASK;
+		reg |= ((((*out_data) >> 40) & 0xff) <<
 				DC_DC8051_CFG_EXT_DEV_0_RETURN_CODE_SHIFT)
 		      | ((((*out_data) >> 48) & 0xffff) <<
 				DC_DC8051_CFG_EXT_DEV_0_RSP_DATA_SHIFT);
@@ -9556,11 +9559,11 @@ int bringup_serdes(struct hfi1_pportdata
 	if (HFI1_CAP_IS_KSET(EXTENDED_PSN))
 		add_rcvctrl(dd, RCV_CTRL_RCV_EXTENDED_PSN_ENABLE_SMASK);
 
-	guid = ppd->guid;
+	guid = ppd->guids[HFI1_PORT_GUID_INDEX];
 	if (!guid) {
 		if (dd->base_guid)
 			guid = dd->base_guid + ppd->port - 1;
-		ppd->guid = guid;
+		ppd->guids[HFI1_PORT_GUID_INDEX] = guid;
 	}
 
 	/* Set linkinit_reason on power up per OPA spec */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/chip_registers.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/chip_registers.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/chip_registers.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/chip_registers.h	2017-02-12 16:03:20.000000000 -0500
@@ -415,6 +415,9 @@
 #define ASIC_CFG_SBUS_REQUEST_DATA_IN_SHIFT 32
 #define ASIC_CFG_SBUS_REQUEST_RECEIVER_ADDR_SHIFT 0
 #define ASIC_CFG_SCRATCH (ASIC + 0x000000000020)
+#define ASIC_CFG_SCRATCH_1 (ASIC_CFG_SCRATCH + 0x08)
+#define ASIC_CFG_SCRATCH_2 (ASIC_CFG_SCRATCH + 0x10)
+#define ASIC_CFG_SCRATCH_3 (ASIC_CFG_SCRATCH + 0x18)
 #define ASIC_CFG_THERM_POLL_EN (ASIC + 0x000000000050)
 #define ASIC_EEP_ADDR_CMD (ASIC + 0x000000000308)
 #define ASIC_EEP_ADDR_CMD_EP_ADDR_MASK 0xFFFFFFull
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/debugfs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/debugfs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -541,6 +541,114 @@ static ssize_t asic_flags_write(struct f
 	return ret;
 }
 
+/* read the dc8051 memory */
+static ssize_t dc8051_memory_read(struct file *file, char __user *buf,
+				  size_t count, loff_t *ppos)
+{
+	struct hfi1_pportdata *ppd = private2ppd(file);
+	ssize_t rval;
+	void *tmp;
+	loff_t start, end;
+
+	/* the checks below expect the position to be positive */
+	if (*ppos < 0)
+		return -EINVAL;
+
+	tmp = kzalloc(DC8051_DATA_MEM_SIZE, GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
+
+	/*
+	 * Fill in the requested portion of the temporary buffer from the
+	 * 8051 memory.  The 8051 memory read is done in terms of 8 bytes.
+	 * Adjust start and end to fit.  Skip reading anything if out of
+	 * range.
+	 */
+	start = *ppos & ~0x7;	/* round down */
+	if (start < DC8051_DATA_MEM_SIZE) {
+		end = (*ppos + count + 7) & ~0x7; /* round up */
+		if (end > DC8051_DATA_MEM_SIZE)
+			end = DC8051_DATA_MEM_SIZE;
+		rval = read_8051_data(ppd->dd, start, end - start,
+				      (u64 *)(tmp + start));
+		if (rval)
+			goto done;
+	}
+
+	rval = simple_read_from_buffer(buf, count, ppos, tmp,
+				       DC8051_DATA_MEM_SIZE);
+done:
+	kfree(tmp);
+	return rval;
+}
+
+static ssize_t debugfs_lcb_read(struct file *file, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct hfi1_pportdata *ppd = private2ppd(file);
+	struct hfi1_devdata *dd = ppd->dd;
+	unsigned long total, csr_off;
+	u64 data;
+
+	if (*ppos < 0)
+		return -EINVAL;
+	/* only read 8 byte quantities */
+	if ((count % 8) != 0)
+		return -EINVAL;
+	/* offset must be 8-byte aligned */
+	if ((*ppos % 8) != 0)
+		return -EINVAL;
+	/* do nothing if out of range or zero count */
+	if (*ppos >= (LCB_END - LCB_START) || !count)
+		return 0;
+	/* reduce count if needed */
+	if (*ppos + count > LCB_END - LCB_START)
+		count = (LCB_END - LCB_START) - *ppos;
+
+	csr_off = LCB_START + *ppos;
+	for (total = 0; total < count; total += 8, csr_off += 8) {
+		if (read_lcb_csr(dd, csr_off, (u64 *)&data))
+			break; /* failed */
+		if (put_user(data, (unsigned long __user *)(buf + total)))
+			break;
+	}
+	*ppos += total;
+	return total;
+}
+
+static ssize_t debugfs_lcb_write(struct file *file, const char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	struct hfi1_pportdata *ppd = private2ppd(file);
+	struct hfi1_devdata *dd = ppd->dd;
+	unsigned long total, csr_off, data;
+
+	if (*ppos < 0)
+		return -EINVAL;
+	/* only write 8 byte quantities */
+	if ((count % 8) != 0)
+		return -EINVAL;
+	/* offset must be 8-byte aligned */
+	if ((*ppos % 8) != 0)
+		return -EINVAL;
+	/* do nothing if out of range or zero count */
+	if (*ppos >= (LCB_END - LCB_START) || !count)
+		return 0;
+	/* reduce count if needed */
+	if (*ppos + count > LCB_END - LCB_START)
+		count = (LCB_END - LCB_START) - *ppos;
+
+	csr_off = LCB_START + *ppos;
+	for (total = 0; total < count; total += 8, csr_off += 8) {
+		if (get_user(data, (unsigned long __user *)(buf + total)))
+			break;
+		if (write_lcb_csr(dd, csr_off, data))
+			break; /* failed */
+	}
+	*ppos += total;
+	return total;
+}
+
 /*
  * read the per-port QSFP data for ppd
  */
@@ -931,6 +1039,8 @@ static const struct counter_info port_cn
 	DEBUGFS_XOPS("qsfp2", qsfp2_debugfs_read, qsfp2_debugfs_write,
 		     qsfp2_debugfs_open, qsfp2_debugfs_release),
 	DEBUGFS_OPS("asic_flags", asic_flags_read, asic_flags_write),
+	DEBUGFS_OPS("dc8051_memory", dc8051_memory_read, NULL),
+	DEBUGFS_OPS("lcb", debugfs_lcb_read, debugfs_lcb_write),
 };
 
 static void *_sdma_cpu_list_seq_start(struct seq_file *s, loff_t *pos)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/driver.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/driver.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -795,8 +795,7 @@ static inline void process_rcv_qp_work(s
 				hfi1_schedule_send(qp);
 			spin_unlock_irqrestore(&qp->s_lock, flags);
 		}
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
+		rvt_put_qp(qp);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/eprom.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/eprom.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/eprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/eprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -207,6 +207,40 @@ done_asic:
 /* magic character sequence that trails an image */
 #define IMAGE_TRAIL_MAGIC "egamiAPO"
 
+/* EPROM file types */
+#define HFI1_EFT_PLATFORM_CONFIG 2
+
+/* segment size - 128 KiB */
+#define SEG_SIZE (128 * 1024)
+
+struct hfi1_eprom_footer {
+	u32 oprom_size;		/* size of the oprom, in bytes */
+	u16 num_table_entries;
+	u16 version;		/* version of this footer */
+	u32 magic;		/* must be last */
+};
+
+struct hfi1_eprom_table_entry {
+	u32 type;		/* file type */
+	u32 offset;		/* file offset from start of EPROM */
+	u32 size;		/* file size, in bytes */
+};
+
+/*
+ * Calculate the max number of table entries that will fit within a directory
+ * buffer of size 'dir_size'.
+ */
+#define MAX_TABLE_ENTRIES(dir_size) \
+	(((dir_size) - sizeof(struct hfi1_eprom_footer)) / \
+		sizeof(struct hfi1_eprom_table_entry))
+
+#define DIRECTORY_SIZE(n) (sizeof(struct hfi1_eprom_footer) + \
+	(sizeof(struct hfi1_eprom_table_entry) * (n)))
+
+#define MAGIC4(a, b, c, d) ((d) << 24 | (c) << 16 | (b) << 8 | (a))
+#define FOOTER_MAGIC MAGIC4('e', 'p', 'r', 'm')
+#define FOOTER_VERSION 1
+
 /*
  * Read all of partition 1.  The actual file is at the front.  Adjust
  * the returned size if a trailing image magic is found.
@@ -242,6 +276,167 @@ static int read_partition_platform_confi
 }
 
 /*
+ * The segment magic has been checked.  There is a footer and table of
+ * contents present.
+ *
+ * directory is a u32 aligned buffer of size EP_PAGE_SIZE.
+ */
+static int read_segment_platform_config(struct hfi1_devdata *dd,
+					void *directory, void **data, u32 *size)
+{
+	struct hfi1_eprom_footer *footer;
+	struct hfi1_eprom_table_entry *table;
+	struct hfi1_eprom_table_entry *entry;
+	void *buffer = NULL;
+	void *table_buffer = NULL;
+	int ret, i;
+	u32 directory_size;
+	u32 seg_base, seg_offset;
+	u32 bytes_available, ncopied, to_copy;
+
+	/* the footer is at the end of the directory */
+	footer = (struct hfi1_eprom_footer *)
+			(directory + EP_PAGE_SIZE - sizeof(*footer));
+
+	/* make sure the structure version is supported */
+	if (footer->version != FOOTER_VERSION)
+		return -EINVAL;
+
+	/* oprom size cannot be larger than a segment */
+	if (footer->oprom_size >= SEG_SIZE)
+		return -EINVAL;
+
+	/* the file table must fit in a segment with the oprom */
+	if (footer->num_table_entries >
+			MAX_TABLE_ENTRIES(SEG_SIZE - footer->oprom_size))
+		return -EINVAL;
+
+	/* find the file table start, which precedes the footer */
+	directory_size = DIRECTORY_SIZE(footer->num_table_entries);
+	if (directory_size <= EP_PAGE_SIZE) {
+		/* the file table fits into the directory buffer handed in */
+		table = (struct hfi1_eprom_table_entry *)
+				(directory + EP_PAGE_SIZE - directory_size);
+	} else {
+		/* need to allocate and read more */
+		table_buffer = kmalloc(directory_size, GFP_KERNEL);
+		if (!table_buffer)
+			return -ENOMEM;
+		ret = read_length(dd, SEG_SIZE - directory_size,
+				  directory_size, table_buffer);
+		if (ret)
+			goto done;
+		table = table_buffer;
+	}
+
+	/* look for the platform configuration file in the table */
+	for (entry = NULL, i = 0; i < footer->num_table_entries; i++) {
+		if (table[i].type == HFI1_EFT_PLATFORM_CONFIG) {
+			entry = &table[i];
+			break;
+		}
+	}
+	if (!entry) {
+		ret = -ENOENT;
+		goto done;
+	}
+
+	/*
+	 * Sanity check on the configuration file size - it should never
+	 * be larger than 4 KiB.
+	 */
+	if (entry->size > (4 * 1024)) {
+		dd_dev_err(dd, "Bad configuration file size 0x%x\n",
+			   entry->size);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* check for bogus offset and size that wrap when added together */
+	if (entry->offset + entry->size < entry->offset) {
+		dd_dev_err(dd,
+			   "Bad configuration file start + size 0x%x+0x%x\n",
+			   entry->offset, entry->size);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* allocate the buffer to return */
+	buffer = kmalloc(entry->size, GFP_KERNEL);
+	if (!buffer) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/*
+	 * Extract the file by looping over segments until it is fully read.
+	 */
+	seg_offset = entry->offset % SEG_SIZE;
+	seg_base = entry->offset - seg_offset;
+	ncopied = 0;
+	while (ncopied < entry->size) {
+		/* calculate data bytes available in this segment */
+
+		/* start with the bytes from the current offset to the end */
+		bytes_available = SEG_SIZE - seg_offset;
+		/* subtract off footer and table from segment 0 */
+		if (seg_base == 0) {
+			/*
+			 * Sanity check: should not have a starting point
+			 * at or within the directory.
+			 */
+			if (bytes_available <= directory_size) {
+				dd_dev_err(dd,
+					   "Bad configuration file - offset 0x%x within footer+table\n",
+					   entry->offset);
+				ret = -EINVAL;
+				goto done;
+			}
+			bytes_available -= directory_size;
+		}
+
+		/* calculate bytes wanted */
+		to_copy = entry->size - ncopied;
+
+		/* max out at the available bytes in this segment */
+		if (to_copy > bytes_available)
+			to_copy = bytes_available;
+
+		/*
+		 * Read from the EPROM.
+		 *
+		 * The sanity check for entry->offset is done in read_length().
+		 * The EPROM offset is validated against what the hardware
+		 * addressing supports.  In addition, if the offset is larger
+		 * than the actual EPROM, it silently wraps.  It will work
+		 * fine, though the reader may not get what they expected
+		 * from the EPROM.
+		 */
+		ret = read_length(dd, seg_base + seg_offset, to_copy,
+				  buffer + ncopied);
+		if (ret)
+			goto done;
+
+		ncopied += to_copy;
+
+		/* set up for next segment */
+		seg_offset = footer->oprom_size;
+		seg_base += SEG_SIZE;
+	}
+
+	/* success */
+	ret = 0;
+	*data = buffer;
+	*size = entry->size;
+
+done:
+	kfree(table_buffer);
+	if (ret)
+		kfree(buffer);
+	return ret;
+}
+
+/*
  * Read the platform configuration file from the EPROM.
  *
  * On success, an allocated buffer containing the data and its size are
@@ -253,6 +448,7 @@ static int read_partition_platform_confi
  *   -EBUSY   - not able to acquire access to the EPROM
  *   -ENOENT  - no recognizable file written
  *   -ENOMEM  - buffer could not be allocated
+ *   -EINVAL  - invalid EPROM contentents found
  */
 int eprom_read_platform_config(struct hfi1_devdata *dd, void **data, u32 *size)
 {
@@ -266,21 +462,20 @@ int eprom_read_platform_config(struct hf
 	if (ret)
 		return -EBUSY;
 
-	/* read the last page of P0 for the EPROM format magic */
-	ret = read_length(dd, P1_START - EP_PAGE_SIZE, EP_PAGE_SIZE, directory);
+	/* read the last page of the segment for the EPROM format magic */
+	ret = read_length(dd, SEG_SIZE - EP_PAGE_SIZE, EP_PAGE_SIZE, directory);
 	if (ret)
 		goto done;
 
-	/* last dword of P0 contains a magic indicator */
-	if (directory[EP_PAGE_DWORDS - 1] == 0) {
+	/* last dword of the segment contains a magic value */
+	if (directory[EP_PAGE_DWORDS - 1] == FOOTER_MAGIC) {
+		/* segment format */
+		ret = read_segment_platform_config(dd, directory, data, size);
+	} else {
 		/* partition format */
 		ret = read_partition_platform_config(dd, data, size);
-		goto done;
 	}
 
-	/* nothing recognized */
-	ret = -ENOENT;
-
 done:
 	release_chip_resource(dd, CR_EPROM);
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/firmware.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/firmware.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/firmware.c	2016-12-11 17:57:30.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/firmware.c	2017-02-12 17:49:17.000000000 -0500
@@ -239,6 +239,16 @@ static const u8 all_fabric_serdes_broadc
 const u8 pcie_serdes_broadcast[2] = { 0xe2, 0xe3 };
 static const u8 all_pcie_serdes_broadcast = 0xe0;
 
+static const u32 platform_config_table_limits[PLATFORM_CONFIG_TABLE_MAX] = {
+	0,
+	SYSTEM_TABLE_MAX,
+	PORT_TABLE_MAX,
+	RX_PRESET_TABLE_MAX,
+	TX_PRESET_TABLE_MAX,
+	QSFP_ATTEN_TABLE_MAX,
+	VARIABLE_SETTINGS_TABLE_MAX
+};
+
 /* forwards */
 static void dispose_one_firmware(struct firmware_details *fdet);
 static int load_fabric_serdes_firmware(struct hfi1_devdata *dd,
@@ -263,11 +273,13 @@ static int __read_8051_data(struct hfi1_
 	u64 reg;
 	int count;
 
-	/* start the read at the given address */
-	reg = ((addr & DC_DC8051_CFG_RAM_ACCESS_CTRL_ADDRESS_MASK)
-			<< DC_DC8051_CFG_RAM_ACCESS_CTRL_ADDRESS_SHIFT)
-		| DC_DC8051_CFG_RAM_ACCESS_CTRL_READ_ENA_SMASK;
+	/* step 1: set the address, clear enable */
+	reg = (addr & DC_DC8051_CFG_RAM_ACCESS_CTRL_ADDRESS_MASK)
+			<< DC_DC8051_CFG_RAM_ACCESS_CTRL_ADDRESS_SHIFT;
 	write_csr(dd, DC_DC8051_CFG_RAM_ACCESS_CTRL, reg);
+	/* step 2: enable */
+	write_csr(dd, DC_DC8051_CFG_RAM_ACCESS_CTRL,
+		  reg | DC_DC8051_CFG_RAM_ACCESS_CTRL_READ_ENA_SMASK);
 
 	/* wait until ACCESS_COMPLETED is set */
 	count = 0;
@@ -707,6 +719,9 @@ static int obtain_firmware(struct hfi1_d
 				       &dd->pcidev->dev);
 		if (err) {
 			platform_config = NULL;
+			dd_dev_err(dd,
+				   "%s: No default platform config file found\n",
+				   __func__);
 			goto done;
 		}
 		dd->platform_config.data = platform_config->data;
@@ -1761,8 +1776,17 @@ int parse_platform_config(struct hfi1_de
 	u32 record_idx = 0, table_type = 0, table_length_dwords = 0;
 	int ret = -EINVAL; /* assume failure */
 
+	/*
+	 * For integrated devices that did not fall back to the default file,
+	 * the SI tuning information for active channels is acquired from the
+	 * scratch register bitmap, thus there is no platform config to parse.
+	 * Skip parsing in these situations.
+	 */
+	if (is_integrated(dd) && !platform_config_load)
+		return 0;
+
 	if (!dd->platform_config.data) {
-		dd_dev_info(dd, "%s: Missing config file\n", __func__);
+		dd_dev_err(dd, "%s: Missing config file\n", __func__);
 		goto bail;
 	}
 	ptr = (u32 *)dd->platform_config.data;
@@ -1770,7 +1794,7 @@ int parse_platform_config(struct hfi1_de
 	magic_num = *ptr;
 	ptr++;
 	if (magic_num != PLATFORM_CONFIG_MAGIC_NUM) {
-		dd_dev_info(dd, "%s: Bad config file\n", __func__);
+		dd_dev_err(dd, "%s: Bad config file\n", __func__);
 		goto bail;
 	}
 
@@ -1797,9 +1821,9 @@ int parse_platform_config(struct hfi1_de
 		header1 = *ptr;
 		header2 = *(ptr + 1);
 		if (header1 != ~header2) {
-			dd_dev_info(dd, "%s: Failed validation at offset %ld\n",
-				    __func__, (ptr - (u32 *)
-					       dd->platform_config.data));
+			dd_dev_err(dd, "%s: Failed validation at offset %ld\n",
+				   __func__, (ptr - (u32 *)
+					      dd->platform_config.data));
 			goto bail;
 		}
 
@@ -1841,11 +1865,11 @@ int parse_platform_config(struct hfi1_de
 							table_length_dwords;
 				break;
 			default:
-				dd_dev_info(dd,
-					    "%s: Unknown data table %d, offset %ld\n",
-					    __func__, table_type,
-					    (ptr - (u32 *)
-					     dd->platform_config.data));
+				dd_dev_err(dd,
+					   "%s: Unknown data table %d, offset %ld\n",
+					   __func__, table_type,
+					   (ptr - (u32 *)
+					    dd->platform_config.data));
 				goto bail; /* We don't trust this file now */
 			}
 			pcfgcache->config_tables[table_type].table = ptr;
@@ -1865,11 +1889,11 @@ int parse_platform_config(struct hfi1_de
 			case PLATFORM_CONFIG_VARIABLE_SETTINGS_TABLE:
 				break;
 			default:
-				dd_dev_info(dd,
-					    "%s: Unknown meta table %d, offset %ld\n",
-					    __func__, table_type,
-					    (ptr -
-					     (u32 *)dd->platform_config.data));
+				dd_dev_err(dd,
+					   "%s: Unknown meta table %d, offset %ld\n",
+					   __func__, table_type,
+					   (ptr -
+					    (u32 *)dd->platform_config.data));
 				goto bail; /* We don't trust this file now */
 			}
 			pcfgcache->config_tables[table_type].table_metadata =
@@ -1884,10 +1908,9 @@ int parse_platform_config(struct hfi1_de
 		/* Jump the table */
 		ptr += table_length_dwords;
 		if (crc != *ptr) {
-			dd_dev_info(dd, "%s: Failed CRC check at offset %ld\n",
-				    __func__, (ptr -
-					       (u32 *)
-					       dd->platform_config.data));
+			dd_dev_err(dd, "%s: Failed CRC check at offset %ld\n",
+				   __func__, (ptr -
+				   (u32 *)dd->platform_config.data));
 			goto bail;
 		}
 		/* Jump the CRC DWORD */
@@ -1901,6 +1924,84 @@ bail:
 	return ret;
 }
 
+static void get_integrated_platform_config_field(
+		struct hfi1_devdata *dd,
+		enum platform_config_table_type_encoding table_type,
+		int field_index, u32 *data)
+{
+	struct hfi1_pportdata *ppd = dd->pport;
+	u8 *cache = ppd->qsfp_info.cache;
+	u32 tx_preset = 0;
+
+	switch (table_type) {
+	case PLATFORM_CONFIG_SYSTEM_TABLE:
+		if (field_index == SYSTEM_TABLE_QSFP_POWER_CLASS_MAX)
+			*data = ppd->max_power_class;
+		else if (field_index == SYSTEM_TABLE_QSFP_ATTENUATION_DEFAULT_25G)
+			*data = ppd->default_atten;
+		break;
+	case PLATFORM_CONFIG_PORT_TABLE:
+		if (field_index == PORT_TABLE_PORT_TYPE)
+			*data = ppd->port_type;
+		else if (field_index == PORT_TABLE_LOCAL_ATTEN_25G)
+			*data = ppd->local_atten;
+		else if (field_index == PORT_TABLE_REMOTE_ATTEN_25G)
+			*data = ppd->remote_atten;
+		break;
+	case PLATFORM_CONFIG_RX_PRESET_TABLE:
+		if (field_index == RX_PRESET_TABLE_QSFP_RX_CDR_APPLY)
+			*data = (ppd->rx_preset & QSFP_RX_CDR_APPLY_SMASK) >>
+				QSFP_RX_CDR_APPLY_SHIFT;
+		else if (field_index == RX_PRESET_TABLE_QSFP_RX_EMP_APPLY)
+			*data = (ppd->rx_preset & QSFP_RX_EMP_APPLY_SMASK) >>
+				QSFP_RX_EMP_APPLY_SHIFT;
+		else if (field_index == RX_PRESET_TABLE_QSFP_RX_AMP_APPLY)
+			*data = (ppd->rx_preset & QSFP_RX_AMP_APPLY_SMASK) >>
+				QSFP_RX_AMP_APPLY_SHIFT;
+		else if (field_index == RX_PRESET_TABLE_QSFP_RX_CDR)
+			*data = (ppd->rx_preset & QSFP_RX_CDR_SMASK) >>
+				QSFP_RX_CDR_SHIFT;
+		else if (field_index == RX_PRESET_TABLE_QSFP_RX_EMP)
+			*data = (ppd->rx_preset & QSFP_RX_EMP_SMASK) >>
+				QSFP_RX_EMP_SHIFT;
+		else if (field_index == RX_PRESET_TABLE_QSFP_RX_AMP)
+			*data = (ppd->rx_preset & QSFP_RX_AMP_SMASK) >>
+				QSFP_RX_AMP_SHIFT;
+		break;
+	case PLATFORM_CONFIG_TX_PRESET_TABLE:
+		if (cache[QSFP_EQ_INFO_OFFS] & 0x4)
+			tx_preset = ppd->tx_preset_eq;
+		else
+			tx_preset = ppd->tx_preset_noeq;
+		if (field_index == TX_PRESET_TABLE_PRECUR)
+			*data = (tx_preset & TX_PRECUR_SMASK) >>
+				TX_PRECUR_SHIFT;
+		else if (field_index == TX_PRESET_TABLE_ATTN)
+			*data = (tx_preset & TX_ATTN_SMASK) >>
+				TX_ATTN_SHIFT;
+		else if (field_index == TX_PRESET_TABLE_POSTCUR)
+			*data = (tx_preset & TX_POSTCUR_SMASK) >>
+				TX_POSTCUR_SHIFT;
+		else if (field_index == TX_PRESET_TABLE_QSFP_TX_CDR_APPLY)
+			*data = (tx_preset & QSFP_TX_CDR_APPLY_SMASK) >>
+				QSFP_TX_CDR_APPLY_SHIFT;
+		else if (field_index == TX_PRESET_TABLE_QSFP_TX_EQ_APPLY)
+			*data = (tx_preset & QSFP_TX_EQ_APPLY_SMASK) >>
+				QSFP_TX_EQ_APPLY_SHIFT;
+		else if (field_index == TX_PRESET_TABLE_QSFP_TX_CDR)
+			*data = (tx_preset & QSFP_TX_CDR_SMASK) >>
+				QSFP_TX_CDR_SHIFT;
+		else if (field_index == TX_PRESET_TABLE_QSFP_TX_EQ)
+			*data = (tx_preset & QSFP_TX_EQ_SMASK) >>
+				QSFP_TX_EQ_SHIFT;
+		break;
+	case PLATFORM_CONFIG_QSFP_ATTEN_TABLE:
+	case PLATFORM_CONFIG_VARIABLE_SETTINGS_TABLE:
+	default:
+		break;
+	}
+}
+
 static int get_platform_fw_field_metadata(struct hfi1_devdata *dd, int table,
 					  int field, u32 *field_len_bits,
 					  u32 *field_start_bits)
@@ -1976,6 +2077,15 @@ int get_platform_config_field(struct hfi
 	else
 		return -EINVAL;
 
+	if (is_integrated(dd) && !platform_config_load) {
+		/*
+		 * Use saved configuration from ppd for integrated platforms
+		 */
+		get_integrated_platform_config_field(dd, table_type,
+						     field_index, data);
+		return 0;
+	}
+
 	ret = get_platform_fw_field_metadata(dd, table_type, field_index,
 					     &field_len_bits,
 					     &field_start_bits);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/hfi.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/hfi.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/hfi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/hfi.h	2017-02-12 16:03:20.000000000 -0500
@@ -492,6 +492,9 @@ struct rvt_sge_state;
 #define HFI1_MIN_VLS_SUPPORTED 1
 #define HFI1_MAX_VLS_SUPPORTED 8
 
+#define HFI1_GUIDS_PER_PORT  5
+#define HFI1_PORT_GUID_INDEX 0
+
 static inline void incr_cntr64(u64 *cntr)
 {
 	if (*cntr < (u64)-1LL)
@@ -559,11 +562,20 @@ struct hfi1_pportdata {
 	struct kobject vl2mtu_kobj;
 
 	/* PHY support */
-	u32 port_type;
 	struct qsfp_data qsfp_info;
+	/* Values for SI tuning of SerDes */
+	u32 port_type;
+	u32 tx_preset_eq;
+	u32 tx_preset_noeq;
+	u32 rx_preset;
+	u8  local_atten;
+	u8  remote_atten;
+	u8  default_atten;
+	u8  max_power_class;
+
+	/* GUIDs for this interface, in host order, guids[0] is a port guid */
+	u64 guids[HFI1_GUIDS_PER_PORT];
 
-	/* GUID for this interface, in host order */
-	u64 guid;
 	/* GUID for peer interface, in host order */
 	u64 neighbor_guid;
 
@@ -826,32 +838,29 @@ struct hfi1_devdata {
 	u8 __iomem *kregend;
 	/* physical address of chip for io_remap, etc. */
 	resource_size_t physaddr;
-	/* receive context data */
-	struct hfi1_ctxtdata **rcd;
+	/* Per VL data. Enough for all VLs but not all elements are set/used. */
+	struct per_vl_data vld[PER_VL_SEND_CONTEXTS];
 	/* send context data */
 	struct send_context_info *send_contexts;
 	/* map hardware send contexts to software index */
 	u8 *hw_to_sw;
 	/* spinlock for allocating and releasing send context resources */
 	spinlock_t sc_lock;
-	/* Per VL data. Enough for all VLs but not all elements are set/used. */
-	struct per_vl_data vld[PER_VL_SEND_CONTEXTS];
 	/* lock for pio_map */
 	spinlock_t pio_map_lock;
+	/* Send Context initialization lock. */
+	spinlock_t sc_init_lock;
+	/* lock for sdma_map */
+	spinlock_t                          sde_map_lock;
 	/* array of kernel send contexts */
 	struct send_context **kernel_send_context;
 	/* array of vl maps */
 	struct pio_vl_map __rcu *pio_map;
-	/* seqlock for sc2vl */
-	seqlock_t sc2vl_lock;
-	u64 sc2vl[4];
-	/* Send Context initialization lock. */
-	spinlock_t sc_init_lock;
+	/* default flags to last descriptor */
+	u64 default_desc1;
 
 	/* fields common to all SDMA engines */
 
-	/* default flags to last descriptor */
-	u64 default_desc1;
 	volatile __le64                    *sdma_heads_dma; /* DMA'ed by chip */
 	dma_addr_t                          sdma_heads_phys;
 	void                               *sdma_pad_dma; /* DMA'ed by chip */
@@ -862,8 +871,6 @@ struct hfi1_devdata {
 	u32                                 chip_sdma_engines;
 	/* num used */
 	u32                                 num_sdma;
-	/* lock for sdma_map */
-	spinlock_t                          sde_map_lock;
 	/* array of engines sized by num_sdma */
 	struct sdma_engine                 *per_sdma;
 	/* array of vl maps */
@@ -872,14 +879,11 @@ struct hfi1_devdata {
 	wait_queue_head_t		  sdma_unfreeze_wq;
 	atomic_t			  sdma_unfreeze_count;
 
+	u32 lcb_access_count;		/* count of LCB users */
+
 	/* common data between shared ASIC HFIs in this OS */
 	struct hfi1_asic_data *asic_data;
 
-	/* hfi1_pportdata, points to array of (physical) port-specific
-	 * data structs, indexed by pidx (0..n-1)
-	 */
-	struct hfi1_pportdata *pport;
-
 	/* mem-mapped pointer to base of PIO buffers */
 	void __iomem *piobase;
 	/*
@@ -896,20 +900,13 @@ struct hfi1_devdata {
 	/* send context numbers and sizes for each type */
 	struct sc_config_sizes sc_sizes[SC_MAX];
 
-	u32 lcb_access_count;		/* count of LCB users */
-
 	char *boardname; /* human readable board info */
 
-	/* device (not port) flags, basically device capabilities */
-	u32 flags;
-
 	/* reset value */
 	u64 z_int_counter;
 	u64 z_rcv_limit;
 	u64 z_send_schedule;
-	/* percpu int_counter */
-	u64 __percpu *int_counter;
-	u64 __percpu *rcv_limit;
+
 	u64 __percpu *send_schedule;
 	/* number of receive contexts in use by the driver */
 	u32 num_rcv_contexts;
@@ -924,6 +921,7 @@ struct hfi1_devdata {
 	/* base receive interrupt timeout, in CSR units */
 	u32 rcv_intr_timeout_csr;
 
+	u32 freezelen; /* max length of freezemsg */
 	u64 __iomem *egrtidbase;
 	spinlock_t sendctrl_lock; /* protect changes to SendCtrl */
 	spinlock_t rcvctrl_lock; /* protect changes to RcvCtrl */
@@ -945,7 +943,6 @@ struct hfi1_devdata {
 	 * IB link status cheaply
 	 */
 	struct hfi1_status *status;
-	u32 freezelen; /* max length of freezemsg */
 
 	/* revision register shadow */
 	u64 revision;
@@ -973,6 +970,8 @@ struct hfi1_devdata {
 	u16 rcvegrbufsize_shift;
 	/* both sides of the PCIe link are gen3 capable */
 	u8 link_gen3_capable;
+	/* default link down value (poll/sleep) */
+	u8 link_default;
 	/* localbus width (1, 2,4,8,16,32) from config space  */
 	u32 lbus_width;
 	/* localbus speed in MHz */
@@ -1008,8 +1007,6 @@ struct hfi1_devdata {
 	u8 hfi1_id;
 	/* implementation code */
 	u8 icode;
-	/* default link down value (poll/sleep) */
-	u8 link_default;
 	/* vAU of this device */
 	u8 vau;
 	/* vCU of this device */
@@ -1020,27 +1017,17 @@ struct hfi1_devdata {
 	u16 vl15_init;
 
 	/* Misc small ints */
-	/* Number of physical ports available */
-	u8 num_pports;
-	/* Lowest context number which can be used by user processes */
-	u8 first_user_ctxt;
 	u8 n_krcv_queues;
 	u8 qos_shift;
-	u8 qpn_mask;
 
-	u16 rhf_offset; /* offset of RHF within receive header entry */
 	u16 irev;	/* implementation revision */
 	u16 dc8051_ver; /* 8051 firmware version */
 
+	spinlock_t hfi1_diag_trans_lock; /* protect diag observer ops */
 	struct platform_config platform_config;
 	struct platform_config_cache pcfg_cache;
 
 	struct diag_client *diag_client;
-	spinlock_t hfi1_diag_trans_lock; /* protect diag observer ops */
-
-	u8 psxmitwait_supported;
-	/* cycle length of PS* counters in HW (in picoseconds) */
-	u16 psxmitwait_check_rate;
 
 	/* MSI-X information */
 	struct hfi1_msix_entry *msix_entries;
@@ -1055,6 +1042,9 @@ struct hfi1_devdata {
 
 	struct rcv_array_data rcv_entries;
 
+	/* cycle length of PS* counters in HW (in picoseconds) */
+	u16 psxmitwait_check_rate;
+
 	/*
 	 * 64 bit synthetic counters
 	 */
@@ -1085,11 +1075,11 @@ struct hfi1_devdata {
 	struct err_info_rcvport err_info_rcvport;
 	struct err_info_constraint err_info_rcv_constraint;
 	struct err_info_constraint err_info_xmit_constraint;
-	u8 err_info_uncorrectable;
-	u8 err_info_fmconfig;
 
 	atomic_t drop_packet;
 	u8 do_drop;
+	u8 err_info_uncorrectable;
+	u8 err_info_fmconfig;
 
 	/*
 	 * Software counters for the status bits defined by the
@@ -1112,40 +1102,60 @@ struct hfi1_devdata {
 	u64 sw_cce_err_status_aggregate;
 	/* Software counter that aggregates all bypass packet rcv errors */
 	u64 sw_rcv_bypass_packet_errors;
-	/* receive interrupt functions */
-	rhf_rcv_function_ptr *rhf_rcv_function_map;
+	/* receive interrupt function */
 	rhf_rcv_function_ptr normal_rhf_rcv_functions[8];
 
+	/* Save the enabled LCB error bits */
+	u64 lcb_err_en;
+
 	/*
 	 * Capability to have different send engines simply by changing a
 	 * pointer value.
 	 */
-	send_routine process_pio_send;
+	send_routine process_pio_send ____cacheline_aligned_in_smp;
 	send_routine process_dma_send;
 	void (*pio_inline_send)(struct hfi1_devdata *dd, struct pio_buf *pbuf,
 				u64 pbc, const void *from, size_t count);
+	/* hfi1_pportdata, points to array of (physical) port-specific
+	 * data structs, indexed by pidx (0..n-1)
+	 */
+	struct hfi1_pportdata *pport;
+	/* receive context data */
+	struct hfi1_ctxtdata **rcd;
+	u64 __percpu *int_counter;
+	/* device (not port) flags, basically device capabilities */
+	u16 flags;
+	/* Number of physical ports available */
+	u8 num_pports;
+	/* Lowest context number which can be used by user processes */
+	u8 first_user_ctxt;
+	/* adding a new field here would make it part of this cacheline */
+
+	/* seqlock for sc2vl */
+	seqlock_t sc2vl_lock ____cacheline_aligned_in_smp;
+	u64 sc2vl[4];
+	/* receive interrupt functions */
+	rhf_rcv_function_ptr *rhf_rcv_function_map;
+	u64 __percpu *rcv_limit;
+	u16 rhf_offset; /* offset of RHF within receive header entry */
+	/* adding a new field here would make it part of this cacheline */
 
 	/* OUI comes from the HW. Used everywhere as 3 separate bytes. */
 	u8 oui1;
 	u8 oui2;
 	u8 oui3;
+	u8 dc_shutdown;
+
 	/* Timer and counter used to detect RcvBufOvflCnt changes */
 	struct timer_list rcverr_timer;
-	u32 rcv_ovfl_cnt;
 
 	wait_queue_head_t event_queue;
 
-	/* Save the enabled LCB error bits */
-	u64 lcb_err_en;
-	u8 dc_shutdown;
-
 	/* receive context tail dummy address */
 	__le64 *rcvhdrtail_dummy_kvaddr;
 	dma_addr_t rcvhdrtail_dummy_dma;
 
-	bool eprom_available;	/* true if EPROM is available for this device */
-	bool aspm_supported;	/* Does HW support ASPM */
-	bool aspm_enabled;	/* ASPM state: enabled/disabled */
+	u32 rcv_ovfl_cnt;
 	/* Serialize ASPM enable/disable between multiple verbs contexts */
 	spinlock_t aspm_lock;
 	/* Number of verbs contexts which have disabled ASPM */
@@ -1155,8 +1165,11 @@ struct hfi1_devdata {
 	/* Used to wait for outstanding user space clients before dev removal */
 	struct completion user_comp;
 
-	struct hfi1_affinity *affinity;
+	bool eprom_available;	/* true if EPROM is available for this device */
+	bool aspm_supported;	/* Does HW support ASPM */
+	bool aspm_enabled;	/* ASPM state: enabled/disabled */
 	struct rhashtable sdma_rht;
+
 	struct kobject kobj;
 };
 
@@ -1604,6 +1617,17 @@ static inline u16 hfi1_get_pkey(struct h
 }
 
 /*
+ * Return the indexed GUID from the port GUIDs table.
+ */
+static inline __be64 get_sguid(struct hfi1_ibport *ibp, unsigned int index)
+{
+	struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
+
+	WARN_ON(index >= HFI1_GUIDS_PER_PORT);
+	return cpu_to_be64(ppd->guids[index]);
+}
+
+/*
  * Called by readers of cc_state only, must call under rcu_read_lock().
  */
 static inline struct cc_state *get_cc_state(struct hfi1_pportdata *ppd)
@@ -1982,6 +2006,12 @@ static inline u32 qsfp_resource(struct h
 	return i2c_target(dd->hfi1_id);
 }
 
+/* Is this device integrated or discrete? */
+static inline bool is_integrated(struct hfi1_devdata *dd)
+{
+	return dd->pcidev->device == PCI_DEVICE_ID_INTEL1;
+}
+
 int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp);
 
 #define DD_DEV_ENTRY(dd)       __string(dev, dev_name(&(dd)->pcidev->dev))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/iowait.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/iowait.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/iowait.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/iowait.h	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,7 @@ struct sdma_engine;
 /**
  * struct iowait - linkage for delayed progress/waiting
  * @list: used to add/insert into QP/PQ wait lists
+ * @lock: uses to record the list head lock
  * @tx_head: overflow list of sdma_txreq's
  * @sleep: no space callback
  * @wakeup: space callback wakeup
@@ -91,6 +92,11 @@ struct sdma_engine;
  * so sleeping is not allowed.
  *
  * The wait_dma member along with the iow
+ *
+ * The lock field is used by waiters to record
+ * the seqlock_t that guards the list head.
+ * Waiters explicity know that, but the destroy
+ * code that unwaits QPs does not.
  */
 
 struct iowait {
@@ -103,6 +109,7 @@ struct iowait {
 		unsigned seq);
 	void (*wakeup)(struct iowait *wait, int reason);
 	void (*sdma_drained)(struct iowait *wait);
+	seqlock_t *lock;
 	struct work_struct iowork;
 	wait_queue_head_t wait_dma;
 	wait_queue_head_t wait_pio;
@@ -141,6 +148,7 @@ static inline void iowait_init(
 	void (*sdma_drained)(struct iowait *wait))
 {
 	wait->count = 0;
+	wait->lock = NULL;
 	INIT_LIST_HEAD(&wait->list);
 	INIT_LIST_HEAD(&wait->tx_head);
 	INIT_WORK(&wait->iowork, func);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/mad.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/mad.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/mad.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/mad.c	2017-02-12 16:03:20.000000000 -0500
@@ -128,7 +128,7 @@ static void send_trap(struct hfi1_ibport
 	smp = send_buf->mad;
 	smp->base_version = OPA_MGMT_BASE_VERSION;
 	smp->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
-	smp->class_version = OPA_SMI_CLASS_VERSION;
+	smp->class_version = OPA_SM_CLASS_VERSION;
 	smp->method = IB_MGMT_METHOD_TRAP;
 	ibp->rvp.tid++;
 	smp->tid = cpu_to_be64(ibp->rvp.tid);
@@ -336,20 +336,20 @@ static int __subn_get_opa_nodeinfo(struc
 	ni = (struct opa_node_info *)data;
 
 	/* GUID 0 is illegal */
-	if (am || pidx >= dd->num_pports || dd->pport[pidx].guid == 0) {
+	if (am || pidx >= dd->num_pports || ibdev->node_guid == 0 ||
+	    get_sguid(to_iport(ibdev, port), HFI1_PORT_GUID_INDEX) == 0) {
 		smp->status |= IB_SMP_INVALID_FIELD;
 		return reply((struct ib_mad_hdr *)smp);
 	}
 
-	ni->port_guid = cpu_to_be64(dd->pport[pidx].guid);
+	ni->port_guid = get_sguid(to_iport(ibdev, port), HFI1_PORT_GUID_INDEX);
 	ni->base_version = OPA_MGMT_BASE_VERSION;
-	ni->class_version = OPA_SMI_CLASS_VERSION;
+	ni->class_version = OPA_SM_CLASS_VERSION;
 	ni->node_type = 1;     /* channel adapter */
 	ni->num_ports = ibdev->phys_port_cnt;
 	/* This is already in network order */
 	ni->system_image_guid = ib_hfi1_sys_image_guid;
-	/* Use first-port GUID as node */
-	ni->node_guid = cpu_to_be64(dd->pport->guid);
+	ni->node_guid = ibdev->node_guid;
 	ni->partition_cap = cpu_to_be16(hfi1_get_npkeys(dd));
 	ni->device_id = cpu_to_be16(dd->pcidev->device);
 	ni->revision = cpu_to_be32(dd->minrev);
@@ -373,19 +373,20 @@ static int subn_get_nodeinfo(struct ib_s
 
 	/* GUID 0 is illegal */
 	if (smp->attr_mod || pidx >= dd->num_pports ||
-	    dd->pport[pidx].guid == 0)
+	    ibdev->node_guid == 0 ||
+	    get_sguid(to_iport(ibdev, port), HFI1_PORT_GUID_INDEX) == 0) {
 		smp->status |= IB_SMP_INVALID_FIELD;
-	else
-		nip->port_guid = cpu_to_be64(dd->pport[pidx].guid);
+		return reply((struct ib_mad_hdr *)smp);
+	}
 
+	nip->port_guid = get_sguid(to_iport(ibdev, port), HFI1_PORT_GUID_INDEX);
 	nip->base_version = OPA_MGMT_BASE_VERSION;
-	nip->class_version = OPA_SMI_CLASS_VERSION;
+	nip->class_version = OPA_SM_CLASS_VERSION;
 	nip->node_type = 1;     /* channel adapter */
 	nip->num_ports = ibdev->phys_port_cnt;
 	/* This is already in network order */
 	nip->sys_guid = ib_hfi1_sys_image_guid;
-	 /* Use first-port GUID as node */
-	nip->node_guid = cpu_to_be64(dd->pport->guid);
+	nip->node_guid = ibdev->node_guid;
 	nip->partition_cap = cpu_to_be16(hfi1_get_npkeys(dd));
 	nip->device_id = cpu_to_be16(dd->pcidev->device);
 	nip->revision = cpu_to_be32(dd->minrev);
@@ -2302,7 +2303,7 @@ static int pma_get_opa_classportinfo(str
 		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;
 
 	p->base_version = OPA_MGMT_BASE_VERSION;
-	p->class_version = OPA_SMI_CLASS_VERSION;
+	p->class_version = OPA_SM_CLASS_VERSION;
 	/*
 	 * Expected response time is 4.096 usec. * 2^18 == 1.073741824 sec.
 	 */
@@ -4022,7 +4023,7 @@ static int process_subn_opa(struct ib_de
 
 	am = be32_to_cpu(smp->attr_mod);
 	attr_id = smp->attr_id;
-	if (smp->class_version != OPA_SMI_CLASS_VERSION) {
+	if (smp->class_version != OPA_SM_CLASS_VERSION) {
 		smp->status |= IB_SMP_UNSUP_VERSION;
 		ret = reply((struct ib_mad_hdr *)smp);
 		return ret;
@@ -4232,7 +4233,7 @@ static int process_perf_opa(struct ib_de
 
 	*out_mad = *in_mad;
 
-	if (pmp->mad_hdr.class_version != OPA_SMI_CLASS_VERSION) {
+	if (pmp->mad_hdr.class_version != OPA_SM_CLASS_VERSION) {
 		pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;
 		return reply((struct ib_mad_hdr *)pmp);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/mmu_rb.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/mmu_rb.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/mmu_rb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/mmu_rb.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,7 +81,7 @@ static void do_remove(struct mmu_rb_hand
 		      struct list_head *del_list);
 static void handle_remove(struct work_struct *work);
 
-static struct mmu_notifier_ops mn_opts = {
+static const struct mmu_notifier_ops mn_opts = {
 	.invalidate_page = mmu_notifier_page,
 	.invalidate_range_start = mmu_notifier_range_start,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/pio.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/pio.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/pio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/pio.c	2017-02-12 16:03:20.000000000 -0500
@@ -758,6 +758,7 @@ struct send_context *sc_alloc(struct hfi
 	sc->hw_context = hw_context;
 	cr_group_addresses(sc, &dma);
 	sc->credits = sci->credits;
+	sc->size = sc->credits * PIO_BLOCK_SIZE;
 
 /* PIO Send Memory Address details */
 #define PIO_ADDR_CONTEXT_MASK 0xfful
@@ -1242,6 +1243,7 @@ int sc_enable(struct send_context *sc)
 	sc->free = 0;
 	sc->alloc_free = 0;
 	sc->fill = 0;
+	sc->fill_wrap = 0;
 	sc->sr_head = 0;
 	sc->sr_tail = 0;
 	sc->flags = 0;
@@ -1385,7 +1387,7 @@ struct pio_buf *sc_buffer_alloc(struct s
 	unsigned long flags;
 	unsigned long avail;
 	unsigned long blocks = dwords_to_blocks(dw_len);
-	unsigned long start_fill;
+	u32 fill_wrap;
 	int trycount = 0;
 	u32 head, next;
 
@@ -1410,9 +1412,7 @@ retry:
 			(sc->fill - sc->alloc_free);
 		if (blocks > avail) {
 			/* still no room, actively update */
-			spin_unlock_irqrestore(&sc->alloc_lock, flags);
 			sc_release_update(sc);
-			spin_lock_irqsave(&sc->alloc_lock, flags);
 			sc->alloc_free = ACCESS_ONCE(sc->free);
 			trycount++;
 			goto retry;
@@ -1428,8 +1428,11 @@ retry:
 	head = sc->sr_head;
 
 	/* "allocate" the buffer */
-	start_fill = sc->fill;
 	sc->fill += blocks;
+	fill_wrap = sc->fill_wrap;
+	sc->fill_wrap += blocks;
+	if (sc->fill_wrap >= sc->credits)
+		sc->fill_wrap = sc->fill_wrap - sc->credits;
 
 	/*
 	 * Fill the parts that the releaser looks at before moving the head.
@@ -1458,11 +1461,8 @@ retry:
 	spin_unlock_irqrestore(&sc->alloc_lock, flags);
 
 	/* finish filling in the buffer outside the lock */
-	pbuf->start = sc->base_addr + ((start_fill % sc->credits)
-							* PIO_BLOCK_SIZE);
-	pbuf->size = sc->credits * PIO_BLOCK_SIZE;
-	pbuf->end = sc->base_addr + pbuf->size;
-	pbuf->block_count = blocks;
+	pbuf->start = sc->base_addr + fill_wrap * PIO_BLOCK_SIZE;
+	pbuf->end = sc->base_addr + sc->size;
 	pbuf->qw_written = 0;
 	pbuf->carry_bytes = 0;
 	pbuf->carry.val64 = 0;
@@ -1573,6 +1573,7 @@ static void sc_piobufavail(struct send_c
 		qp = iowait_to_qp(wait);
 		priv = qp->priv;
 		list_del_init(&priv->s_iowait.list);
+		priv->s_iowait.lock = NULL;
 		/* refcount held until actual wake up */
 		qps[n++] = qp;
 	}
@@ -2028,29 +2029,17 @@ freesc15:
 int init_credit_return(struct hfi1_devdata *dd)
 {
 	int ret;
-	int num_numa;
 	int i;
 
-	num_numa = num_online_nodes();
-	/* enforce the expectation that the numas are compact */
-	for (i = 0; i < num_numa; i++) {
-		if (!node_online(i)) {
-			dd_dev_err(dd, "NUMA nodes are not compact\n");
-			ret = -EINVAL;
-			goto done;
-		}
-	}
-
 	dd->cr_base = kcalloc(
-		num_numa,
+		node_affinity.num_possible_nodes,
 		sizeof(struct credit_return_base),
 		GFP_KERNEL);
 	if (!dd->cr_base) {
-		dd_dev_err(dd, "Unable to allocate credit return base\n");
 		ret = -ENOMEM;
 		goto done;
 	}
-	for (i = 0; i < num_numa; i++) {
+	for_each_node_with_cpus(i) {
 		int bytes = TXE_NUM_CONTEXTS * sizeof(struct credit_return);
 
 		set_dev_node(&dd->pcidev->dev, i);
@@ -2077,14 +2066,11 @@ done:
 
 void free_credit_return(struct hfi1_devdata *dd)
 {
-	int num_numa;
 	int i;
 
 	if (!dd->cr_base)
 		return;
-
-	num_numa = num_online_nodes();
-	for (i = 0; i < num_numa; i++) {
+	for (i = 0; i < node_affinity.num_possible_nodes; i++) {
 		if (dd->cr_base[i].va) {
 			dma_free_coherent(&dd->pcidev->dev,
 					  TXE_NUM_CONTEXTS *
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/pio_copy.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/pio_copy.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/pio_copy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/pio_copy.c	2017-02-12 16:03:20.000000000 -0500
@@ -129,8 +129,8 @@ void pio_copy(struct hfi1_devdata *dd, s
 				dest += sizeof(u64);
 			}
 
-			dest -= pbuf->size;
-			dend -= pbuf->size;
+			dest -= pbuf->sc->size;
+			dend -= pbuf->sc->size;
 		}
 
 		/* write 8-byte non-SOP, non-wrap chunk data */
@@ -361,8 +361,8 @@ void seg_pio_copy_start(struct pio_buf *
 				dest += sizeof(u64);
 			}
 
-			dest -= pbuf->size;
-			dend -= pbuf->size;
+			dest -= pbuf->sc->size;
+			dend -= pbuf->sc->size;
 		}
 
 		/* write 8-byte non-SOP, non-wrap chunk data */
@@ -458,8 +458,8 @@ static void mid_copy_mix(struct pio_buf
 			dest += sizeof(u64);
 		}
 
-		dest -= pbuf->size;
-		dend -= pbuf->size;
+		dest -= pbuf->sc->size;
+		dend -= pbuf->sc->size;
 	}
 
 	/* write 8-byte non-SOP, non-wrap chunk data */
@@ -492,7 +492,7 @@ static void mid_copy_mix(struct pio_buf
 		 */
 		/* adjust if we have wrapped */
 		if (dest >= pbuf->end)
-			dest -= pbuf->size;
+			dest -= pbuf->sc->size;
 		/* jump to the SOP range if within the first block */
 		else if (pbuf->qw_written < PIO_BLOCK_QWS)
 			dest += SOP_DISTANCE;
@@ -584,8 +584,8 @@ static void mid_copy_straight(struct pio
 			dest += sizeof(u64);
 		}
 
-		dest -= pbuf->size;
-		dend -= pbuf->size;
+		dest -= pbuf->sc->size;
+		dend -= pbuf->sc->size;
 	}
 
 	/* write 8-byte non-SOP, non-wrap chunk data */
@@ -666,7 +666,7 @@ void seg_pio_copy_mid(struct pio_buf *pb
 			 */
 			/* adjust if we've wrapped */
 			if (dest >= pbuf->end)
-				dest -= pbuf->size;
+				dest -= pbuf->sc->size;
 			/* jump to SOP range if within the first block */
 			else if (pbuf->qw_written < PIO_BLOCK_QWS)
 				dest += SOP_DISTANCE;
@@ -719,7 +719,7 @@ void seg_pio_copy_end(struct pio_buf *pb
 	 */
 	/* adjust if we have wrapped */
 	if (dest >= pbuf->end)
-		dest -= pbuf->size;
+		dest -= pbuf->sc->size;
 	/* jump to the SOP range if within the first block */
 	else if (pbuf->qw_written < PIO_BLOCK_QWS)
 		dest += SOP_DISTANCE;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/pio.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/pio.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/pio.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/pio.h	2017-02-12 16:03:20.000000000 -0500
@@ -83,53 +83,55 @@ struct pio_buf {
 	void *arg;		/* argument for cb */
 	void __iomem *start;	/* buffer start address */
 	void __iomem *end;	/* context end address */
-	unsigned long size;	/* context size, in bytes */
 	unsigned long sent_at;	/* buffer is sent when <= free */
-	u32 block_count;	/* size of buffer, in blocks */
-	u32 qw_written;		/* QW written so far */
-	u32 carry_bytes;	/* number of valid bytes in carry */
 	union mix carry;	/* pending unwritten bytes */
+	u16 qw_written;		/* QW written so far */
+	u8 carry_bytes;	/* number of valid bytes in carry */
 };
 
 /* cache line aligned pio buffer array */
 union pio_shadow_ring {
 	struct pio_buf pbuf;
-	u64 unused[16];		/* cache line spacer */
 } ____cacheline_aligned;
 
 /* per-NUMA send context */
 struct send_context {
 	/* read-only after init */
 	struct hfi1_devdata *dd;		/* device */
-	void __iomem *base_addr;	/* start of PIO memory */
 	union pio_shadow_ring *sr;	/* shadow ring */
+	void __iomem *base_addr;	/* start of PIO memory */
+	u32 __percpu *buffers_allocated;/* count of buffers allocated */
+	u32 size;			/* context size, in bytes */
 
-	volatile __le64 *hw_free;	/* HW free counter */
-	struct work_struct halt_work;	/* halted context work queue entry */
-	unsigned long flags;		/* flags */
 	int node;			/* context home node */
-	int type;			/* context type */
-	u32 sw_index;			/* software index number */
-	u32 hw_context;			/* hardware context number */
-	u32 credits;			/* number of blocks in context */
 	u32 sr_size;			/* size of the shadow ring */
-	u32 group;			/* credit return group */
+	u16 flags;			/* flags */
+	u8  type;			/* context type */
+	u8  sw_index;			/* software index number */
+	u8  hw_context;			/* hardware context number */
+	u8  group;			/* credit return group */
+
 	/* allocator fields */
 	spinlock_t alloc_lock ____cacheline_aligned_in_smp;
+	u32 sr_head;			/* shadow ring head */
 	unsigned long fill;		/* official alloc count */
 	unsigned long alloc_free;	/* copy of free (less cache thrash) */
-	u32 sr_head;			/* shadow ring head */
+	u32 fill_wrap;			/* tracks fill within ring */
+	u32 credits;			/* number of blocks in context */
+	/* adding a new field here would make it part of this cacheline */
+
 	/* releaser fields */
 	spinlock_t release_lock ____cacheline_aligned_in_smp;
-	unsigned long free;		/* official free count */
 	u32 sr_tail;			/* shadow ring tail */
+	unsigned long free;		/* official free count */
+	volatile __le64 *hw_free;	/* HW free counter */
 	/* list for PIO waiters */
 	struct list_head piowait  ____cacheline_aligned_in_smp;
 	spinlock_t credit_ctrl_lock ____cacheline_aligned_in_smp;
-	u64 credit_ctrl;		/* cache for credit control */
 	u32 credit_intr_count;		/* count of credit intr users */
-	u32 __percpu *buffers_allocated;/* count of buffers allocated */
+	u64 credit_ctrl;		/* cache for credit control */
 	wait_queue_head_t halt_wait;    /* wait until kernel sees interrupt */
+	struct work_struct halt_work;	/* halted context work queue entry */
 };
 
 /* send context flags */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/platform.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/platform.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/platform.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/platform.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,90 @@
 #include "efivar.h"
 #include "eprom.h"
 
+static int validate_scratch_checksum(struct hfi1_devdata *dd)
+{
+	u64 checksum = 0, temp_scratch = 0;
+	int i, j, version;
+
+	temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH);
+	version = (temp_scratch & BITMAP_VERSION_SMASK) >> BITMAP_VERSION_SHIFT;
+
+	/* Prevent power on default of all zeroes from passing checksum */
+	if (!version)
+		return 0;
+
+	/*
+	 * ASIC scratch 0 only contains the checksum and bitmap version as
+	 * fields of interest, both of which are handled separately from the
+	 * loop below, so skip it
+	 */
+	checksum += version;
+	for (i = 1; i < ASIC_NUM_SCRATCH; i++) {
+		temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH + (8 * i));
+		for (j = sizeof(u64); j != 0; j -= 2) {
+			checksum += (temp_scratch & 0xFFFF);
+			temp_scratch >>= 16;
+		}
+	}
+
+	while (checksum >> 16)
+		checksum = (checksum & CHECKSUM_MASK) + (checksum >> 16);
+
+	temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH);
+	temp_scratch &= CHECKSUM_SMASK;
+	temp_scratch >>= CHECKSUM_SHIFT;
+
+	if (checksum + temp_scratch == 0xFFFF)
+		return 1;
+	return 0;
+}
+
+static void save_platform_config_fields(struct hfi1_devdata *dd)
+{
+	struct hfi1_pportdata *ppd = dd->pport;
+	u64 temp_scratch = 0, temp_dest = 0;
+
+	temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH_1);
+
+	temp_dest = temp_scratch &
+		    (dd->hfi1_id ? PORT1_PORT_TYPE_SMASK :
+		     PORT0_PORT_TYPE_SMASK);
+	ppd->port_type = temp_dest >>
+			 (dd->hfi1_id ? PORT1_PORT_TYPE_SHIFT :
+			  PORT0_PORT_TYPE_SHIFT);
+
+	temp_dest = temp_scratch &
+		    (dd->hfi1_id ? PORT1_LOCAL_ATTEN_SMASK :
+		     PORT0_LOCAL_ATTEN_SMASK);
+	ppd->local_atten = temp_dest >>
+			   (dd->hfi1_id ? PORT1_LOCAL_ATTEN_SHIFT :
+			    PORT0_LOCAL_ATTEN_SHIFT);
+
+	temp_dest = temp_scratch &
+		    (dd->hfi1_id ? PORT1_REMOTE_ATTEN_SMASK :
+		     PORT0_REMOTE_ATTEN_SMASK);
+	ppd->remote_atten = temp_dest >>
+			    (dd->hfi1_id ? PORT1_REMOTE_ATTEN_SHIFT :
+			     PORT0_REMOTE_ATTEN_SHIFT);
+
+	temp_dest = temp_scratch &
+		    (dd->hfi1_id ? PORT1_DEFAULT_ATTEN_SMASK :
+		     PORT0_DEFAULT_ATTEN_SMASK);
+	ppd->default_atten = temp_dest >>
+			     (dd->hfi1_id ? PORT1_DEFAULT_ATTEN_SHIFT :
+			      PORT0_DEFAULT_ATTEN_SHIFT);
+
+	temp_scratch = read_csr(dd, dd->hfi1_id ? ASIC_CFG_SCRATCH_3 :
+				ASIC_CFG_SCRATCH_2);
+
+	ppd->tx_preset_eq = (temp_scratch & TX_EQ_SMASK) >> TX_EQ_SHIFT;
+	ppd->tx_preset_noeq = (temp_scratch & TX_NO_EQ_SMASK) >> TX_NO_EQ_SHIFT;
+	ppd->rx_preset = (temp_scratch & RX_SMASK) >> RX_SHIFT;
+
+	ppd->max_power_class = (temp_scratch & QSFP_MAX_POWER_SMASK) >>
+				QSFP_MAX_POWER_SHIFT;
+}
+
 void get_platform_config(struct hfi1_devdata *dd)
 {
 	int ret = 0;
@@ -56,38 +140,49 @@ void get_platform_config(struct hfi1_dev
 	u8 *temp_platform_config = NULL;
 	u32 esize;
 
-	ret = eprom_read_platform_config(dd, (void **)&temp_platform_config,
-					 &esize);
-	if (!ret) {
-		/* success */
-		size = esize;
-		goto success;
-	}
-	/* fail, try EFI variable */
-
-	ret = read_hfi1_efi_var(dd, "configuration", &size,
-				(void **)&temp_platform_config);
-	if (!ret)
-		goto success;
+	if (is_integrated(dd)) {
+		if (validate_scratch_checksum(dd)) {
+			save_platform_config_fields(dd);
+			return;
+		}
+		dd_dev_err(dd, "%s: Config bitmap corrupted/uninitialized\n",
+			   __func__);
+		dd_dev_err(dd,
+			   "%s: Please update your BIOS to support active channels\n",
+			   __func__);
+	} else {
+		ret = eprom_read_platform_config(dd,
+						 (void **)&temp_platform_config,
+						 &esize);
+		if (!ret) {
+			/* success */
+			dd->platform_config.data = temp_platform_config;
+			dd->platform_config.size = esize;
+			return;
+		}
+		/* fail, try EFI variable */
 
-	dd_dev_info(dd,
-		    "%s: Failed to get platform config from UEFI, falling back to request firmware\n",
-		    __func__);
+		ret = read_hfi1_efi_var(dd, "configuration", &size,
+					(void **)&temp_platform_config);
+		if (!ret) {
+			dd->platform_config.data = temp_platform_config;
+			dd->platform_config.size = size;
+			return;
+		}
+	}
+	dd_dev_err(dd,
+		   "%s: Failed to get platform config, falling back to sub-optimal default file\n",
+		   __func__);
 	/* fall back to request firmware */
 	platform_config_load = 1;
-	return;
-
-success:
-	dd->platform_config.data = temp_platform_config;
-	dd->platform_config.size = size;
 }
 
 void free_platform_config(struct hfi1_devdata *dd)
 {
 	if (!platform_config_load) {
 		/*
-		 * was loaded from EFI, release memory
-		 * allocated by read_efi_var
+		 * was loaded from EFI or the EPROM, release memory
+		 * allocated by read_efi_var/eprom_read_platform_config
 		 */
 		kfree(dd->platform_config.data);
 	}
@@ -100,12 +195,16 @@ void free_platform_config(struct hfi1_de
 void get_port_type(struct hfi1_pportdata *ppd)
 {
 	int ret;
+	u32 temp;
 
 	ret = get_platform_config_field(ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
-					PORT_TABLE_PORT_TYPE, &ppd->port_type,
+					PORT_TABLE_PORT_TYPE, &temp,
 					4);
-	if (ret)
+	if (ret) {
 		ppd->port_type = PORT_TYPE_UNKNOWN;
+		return;
+	}
+	ppd->port_type = temp;
 }
 
 int set_qsfp_tx(struct hfi1_pportdata *ppd, int on)
@@ -538,6 +637,38 @@ static void apply_tx_lanes(struct hfi1_p
 	}
 }
 
+/*
+ * Return a special SerDes setting for low power AOC cables.  The power class
+ * threshold and setting being used were all found by empirical testing.
+ *
+ * Summary of the logic:
+ *
+ * if (QSFP and QSFP_TYPE == AOC and QSFP_POWER_CLASS < 4)
+ *     return 0xe
+ * return 0; // leave at default
+ */
+static u8 aoc_low_power_setting(struct hfi1_pportdata *ppd)
+{
+	u8 *cache = ppd->qsfp_info.cache;
+	int power_class;
+
+	/* QSFP only */
+	if (ppd->port_type != PORT_TYPE_QSFP)
+		return 0; /* leave at default */
+
+	/* active optical cables only */
+	switch ((cache[QSFP_MOD_TECH_OFFS] & 0xF0) >> 4) {
+	case 0x0 ... 0x9: /* fallthrough */
+	case 0xC: /* fallthrough */
+	case 0xE:
+		/* active AOC */
+		power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]);
+		if (power_class < QSFP_POWER_CLASS_4)
+			return 0xe;
+	}
+	return 0; /* leave at default */
+}
+
 static void apply_tunings(
 		struct hfi1_pportdata *ppd, u32 tx_preset_index,
 		u8 tuning_method, u32 total_atten, u8 limiting_active)
@@ -606,7 +737,17 @@ static void apply_tunings(
 		tx_preset_index, TX_PRESET_TABLE_POSTCUR, &tx_preset, 4);
 	postcur = tx_preset;
 
-	config_data = precur | (attn << 8) | (postcur << 16);
+	/*
+	 * NOTES:
+	 * o The aoc_low_power_setting is applied to all lanes even
+	 *   though only lane 0's value is examined by the firmware.
+	 * o A lingering low power setting after a cable swap does
+	 *   not occur.  On cable unplug the 8051 is reset and
+	 *   restarted on cable insert.  This resets all settings to
+	 *   their default, erasing any previous low power setting.
+	 */
+	config_data = precur | (attn << 8) | (postcur << 16) |
+			(aoc_low_power_setting(ppd) << 24);
 
 	apply_tx_lanes(ppd, TX_EQ_SETTINGS, config_data,
 		       "Applying TX settings");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/platform.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/platform.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/platform.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/platform.h	2017-02-12 16:03:20.000000000 -0500
@@ -168,16 +168,6 @@ struct platform_config_cache {
 	struct platform_config_data config_tables[PLATFORM_CONFIG_TABLE_MAX];
 };
 
-static const u32 platform_config_table_limits[PLATFORM_CONFIG_TABLE_MAX] = {
-	0,
-	SYSTEM_TABLE_MAX,
-	PORT_TABLE_MAX,
-	RX_PRESET_TABLE_MAX,
-	TX_PRESET_TABLE_MAX,
-	QSFP_ATTEN_TABLE_MAX,
-	VARIABLE_SETTINGS_TABLE_MAX
-};
-
 /* This section defines default values and encodings for the
  * fields defined for each table above
  */
@@ -295,6 +285,123 @@ enum link_tuning_encoding {
 	OPA_UNKNOWN_TUNING
 };
 
+/*
+ * Shifts and masks for the link SI tuning values stuffed into the ASIC scratch
+ * registers for integrated platforms
+ */
+#define PORT0_PORT_TYPE_SHIFT		0
+#define PORT0_LOCAL_ATTEN_SHIFT		4
+#define PORT0_REMOTE_ATTEN_SHIFT	10
+#define PORT0_DEFAULT_ATTEN_SHIFT	32
+
+#define PORT1_PORT_TYPE_SHIFT		16
+#define PORT1_LOCAL_ATTEN_SHIFT		20
+#define PORT1_REMOTE_ATTEN_SHIFT	26
+#define PORT1_DEFAULT_ATTEN_SHIFT	40
+
+#define PORT0_PORT_TYPE_MASK		0xFUL
+#define PORT0_LOCAL_ATTEN_MASK		0x3FUL
+#define PORT0_REMOTE_ATTEN_MASK		0x3FUL
+#define PORT0_DEFAULT_ATTEN_MASK	0xFFUL
+
+#define PORT1_PORT_TYPE_MASK		0xFUL
+#define PORT1_LOCAL_ATTEN_MASK		0x3FUL
+#define PORT1_REMOTE_ATTEN_MASK		0x3FUL
+#define PORT1_DEFAULT_ATTEN_MASK	0xFFUL
+
+#define PORT0_PORT_TYPE_SMASK		(PORT0_PORT_TYPE_MASK << \
+					 PORT0_PORT_TYPE_SHIFT)
+#define PORT0_LOCAL_ATTEN_SMASK		(PORT0_LOCAL_ATTEN_MASK << \
+					 PORT0_LOCAL_ATTEN_SHIFT)
+#define PORT0_REMOTE_ATTEN_SMASK	(PORT0_REMOTE_ATTEN_MASK << \
+					 PORT0_REMOTE_ATTEN_SHIFT)
+#define PORT0_DEFAULT_ATTEN_SMASK	(PORT0_DEFAULT_ATTEN_MASK << \
+					 PORT0_DEFAULT_ATTEN_SHIFT)
+
+#define PORT1_PORT_TYPE_SMASK		(PORT1_PORT_TYPE_MASK << \
+					 PORT1_PORT_TYPE_SHIFT)
+#define PORT1_LOCAL_ATTEN_SMASK		(PORT1_LOCAL_ATTEN_MASK << \
+					 PORT1_LOCAL_ATTEN_SHIFT)
+#define PORT1_REMOTE_ATTEN_SMASK	(PORT1_REMOTE_ATTEN_MASK << \
+					 PORT1_REMOTE_ATTEN_SHIFT)
+#define PORT1_DEFAULT_ATTEN_SMASK	(PORT1_DEFAULT_ATTEN_MASK << \
+					 PORT1_DEFAULT_ATTEN_SHIFT)
+
+#define QSFP_MAX_POWER_SHIFT		0
+#define TX_NO_EQ_SHIFT			4
+#define TX_EQ_SHIFT			25
+#define RX_SHIFT			46
+
+#define QSFP_MAX_POWER_MASK		0xFUL
+#define TX_NO_EQ_MASK			0x1FFFFFUL
+#define TX_EQ_MASK			0x1FFFFFUL
+#define RX_MASK				0xFFFFUL
+
+#define QSFP_MAX_POWER_SMASK		(QSFP_MAX_POWER_MASK << \
+					 QSFP_MAX_POWER_SHIFT)
+#define TX_NO_EQ_SMASK			(TX_NO_EQ_MASK << TX_NO_EQ_SHIFT)
+#define TX_EQ_SMASK			(TX_EQ_MASK << TX_EQ_SHIFT)
+#define RX_SMASK			(RX_MASK << RX_SHIFT)
+
+#define TX_PRECUR_SHIFT			0
+#define TX_ATTN_SHIFT			4
+#define QSFP_TX_CDR_APPLY_SHIFT		9
+#define QSFP_TX_EQ_APPLY_SHIFT		10
+#define QSFP_TX_CDR_SHIFT		11
+#define QSFP_TX_EQ_SHIFT		12
+#define TX_POSTCUR_SHIFT		16
+
+#define TX_PRECUR_MASK			0xFUL
+#define TX_ATTN_MASK			0x1FUL
+#define QSFP_TX_CDR_APPLY_MASK		0x1UL
+#define QSFP_TX_EQ_APPLY_MASK		0x1UL
+#define QSFP_TX_CDR_MASK		0x1UL
+#define QSFP_TX_EQ_MASK			0xFUL
+#define TX_POSTCUR_MASK			0x1FUL
+
+#define TX_PRECUR_SMASK			(TX_PRECUR_MASK << TX_PRECUR_SHIFT)
+#define TX_ATTN_SMASK			(TX_ATTN_MASK << TX_ATTN_SHIFT)
+#define QSFP_TX_CDR_APPLY_SMASK		(QSFP_TX_CDR_APPLY_MASK << \
+					 QSFP_TX_CDR_APPLY_SHIFT)
+#define QSFP_TX_EQ_APPLY_SMASK		(QSFP_TX_EQ_APPLY_MASK << \
+					 QSFP_TX_EQ_APPLY_SHIFT)
+#define QSFP_TX_CDR_SMASK		(QSFP_TX_CDR_MASK << QSFP_TX_CDR_SHIFT)
+#define QSFP_TX_EQ_SMASK		(QSFP_TX_EQ_MASK << QSFP_TX_EQ_SHIFT)
+#define TX_POSTCUR_SMASK		(TX_POSTCUR_MASK << TX_POSTCUR_SHIFT)
+
+#define QSFP_RX_CDR_APPLY_SHIFT		0
+#define QSFP_RX_EMP_APPLY_SHIFT		1
+#define QSFP_RX_AMP_APPLY_SHIFT		2
+#define QSFP_RX_CDR_SHIFT		3
+#define QSFP_RX_EMP_SHIFT		4
+#define QSFP_RX_AMP_SHIFT		8
+
+#define QSFP_RX_CDR_APPLY_MASK		0x1UL
+#define QSFP_RX_EMP_APPLY_MASK		0x1UL
+#define QSFP_RX_AMP_APPLY_MASK		0x1UL
+#define QSFP_RX_CDR_MASK		0x1UL
+#define QSFP_RX_EMP_MASK		0xFUL
+#define QSFP_RX_AMP_MASK		0x3UL
+
+#define QSFP_RX_CDR_APPLY_SMASK		(QSFP_RX_CDR_APPLY_MASK << \
+					 QSFP_RX_CDR_APPLY_SHIFT)
+#define QSFP_RX_EMP_APPLY_SMASK		(QSFP_RX_EMP_APPLY_MASK << \
+					 QSFP_RX_EMP_APPLY_SHIFT)
+#define QSFP_RX_AMP_APPLY_SMASK		(QSFP_RX_AMP_APPLY_MASK << \
+					 QSFP_RX_AMP_APPLY_SHIFT)
+#define QSFP_RX_CDR_SMASK		(QSFP_RX_CDR_MASK << QSFP_RX_CDR_SHIFT)
+#define QSFP_RX_EMP_SMASK		(QSFP_RX_EMP_MASK << QSFP_RX_EMP_SHIFT)
+#define QSFP_RX_AMP_SMASK		(QSFP_RX_AMP_MASK << QSFP_RX_AMP_SHIFT)
+
+#define BITMAP_VERSION			1
+#define BITMAP_VERSION_SHIFT		44
+#define BITMAP_VERSION_MASK		0xFUL
+#define BITMAP_VERSION_SMASK		(BITMAP_VERSION_MASK << \
+					 BITMAP_VERSION_SHIFT)
+#define CHECKSUM_SHIFT			48
+#define CHECKSUM_MASK			0xFFFFUL
+#define CHECKSUM_SMASK			(CHECKSUM_MASK << CHECKSUM_SHIFT)
+
 /* platform.c */
 void get_platform_config(struct hfi1_devdata *dd);
 void free_platform_config(struct hfi1_devdata *dd);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/qp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -196,15 +196,18 @@ static void flush_tx_list(struct rvt_qp
 static void flush_iowait(struct rvt_qp *qp)
 {
 	struct hfi1_qp_priv *priv = qp->priv;
-	struct hfi1_ibdev *dev = to_idev(qp->ibqp.device);
 	unsigned long flags;
+	seqlock_t *lock = priv->s_iowait.lock;
 
-	write_seqlock_irqsave(&dev->iowait_lock, flags);
+	if (!lock)
+		return;
+	write_seqlock_irqsave(lock, flags);
 	if (!list_empty(&priv->s_iowait.list)) {
 		list_del_init(&priv->s_iowait.list);
+		priv->s_iowait.lock = NULL;
 		rvt_put_qp(qp);
 	}
-	write_sequnlock_irqrestore(&dev->iowait_lock, flags);
+	write_sequnlock_irqrestore(lock, flags);
 }
 
 static inline int opa_mtu_enum_to_int(int mtu)
@@ -543,6 +546,7 @@ static int iowait_sleep(
 			ibp->rvp.n_dmawait++;
 			qp->s_flags |= RVT_S_WAIT_DMA_DESC;
 			list_add_tail(&priv->s_iowait.list, &sde->dmawait);
+			priv->s_iowait.lock = &dev->iowait_lock;
 			trace_hfi1_qpsleep(qp, RVT_S_WAIT_DMA_DESC);
 			rvt_get_qp(qp);
 		}
@@ -964,6 +968,7 @@ void notify_error_qp(struct rvt_qp *qp)
 	if (!list_empty(&priv->s_iowait.list) && !(qp->s_flags & RVT_S_BUSY)) {
 		qp->s_flags &= ~RVT_S_ANY_WAIT_IO;
 		list_del_init(&priv->s_iowait.list);
+		priv->s_iowait.lock = NULL;
 		rvt_put_qp(qp);
 	}
 	write_sequnlock(&dev->iowait_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/rc.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/rc.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/rc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/rc.c	2017-02-12 16:03:20.000000000 -0500
@@ -276,7 +276,7 @@ static int make_rc_ack(struct hfi1_ibdev
 				rvt_get_mr(ps->s_txreq->mr);
 			qp->s_ack_rdma_sge.sge = e->rdma_sge;
 			qp->s_ack_rdma_sge.num_sge = 1;
-			qp->s_cur_sge = &qp->s_ack_rdma_sge;
+			ps->s_txreq->ss = &qp->s_ack_rdma_sge;
 			if (len > pmtu) {
 				len = pmtu;
 				qp->s_ack_state = OP(RDMA_READ_RESPONSE_FIRST);
@@ -290,7 +290,7 @@ static int make_rc_ack(struct hfi1_ibdev
 			bth2 = mask_psn(qp->s_ack_rdma_psn++);
 		} else {
 			/* COMPARE_SWAP or FETCH_ADD */
-			qp->s_cur_sge = NULL;
+			ps->s_txreq->ss = NULL;
 			len = 0;
 			qp->s_ack_state = OP(ATOMIC_ACKNOWLEDGE);
 			ohdr->u.at.aeth = hfi1_compute_aeth(qp);
@@ -306,7 +306,7 @@ static int make_rc_ack(struct hfi1_ibdev
 		qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE);
 		/* FALLTHROUGH */
 	case OP(RDMA_READ_RESPONSE_MIDDLE):
-		qp->s_cur_sge = &qp->s_ack_rdma_sge;
+		ps->s_txreq->ss = &qp->s_ack_rdma_sge;
 		ps->s_txreq->mr = qp->s_ack_rdma_sge.sge.mr;
 		if (ps->s_txreq->mr)
 			rvt_get_mr(ps->s_txreq->mr);
@@ -335,7 +335,7 @@ normal:
 		 */
 		qp->s_ack_state = OP(SEND_ONLY);
 		qp->s_flags &= ~RVT_S_ACK_PENDING;
-		qp->s_cur_sge = NULL;
+		ps->s_txreq->ss = NULL;
 		if (qp->s_nak_state)
 			ohdr->u.aeth =
 				cpu_to_be32((qp->r_msn & HFI1_MSN_MASK) |
@@ -351,7 +351,7 @@ normal:
 	qp->s_rdma_ack_cnt++;
 	qp->s_hdrwords = hwords;
 	ps->s_txreq->sde = priv->s_sde;
-	qp->s_cur_size = len;
+	ps->s_txreq->s_cur_size = len;
 	hfi1_make_ruc_header(qp, ohdr, bth0, bth2, middle, ps);
 	/* pbc */
 	ps->s_txreq->hdr_dwords = qp->s_hdrwords + 2;
@@ -801,8 +801,8 @@ int hfi1_make_rc_req(struct rvt_qp *qp,
 	qp->s_len -= len;
 	qp->s_hdrwords = hwords;
 	ps->s_txreq->sde = priv->s_sde;
-	qp->s_cur_sge = ss;
-	qp->s_cur_size = len;
+	ps->s_txreq->ss = ss;
+	ps->s_txreq->s_cur_size = len;
 	hfi1_make_ruc_header(
 		qp,
 		ohdr,
@@ -1146,8 +1146,6 @@ void hfi1_rc_send_complete(struct rvt_qp
 {
 	struct ib_other_headers *ohdr;
 	struct rvt_swqe *wqe;
-	struct ib_wc wc;
-	unsigned i;
 	u32 opcode;
 	u32 psn;
 
@@ -1195,22 +1193,8 @@ void hfi1_rc_send_complete(struct rvt_qp
 		qp->s_last = s_last;
 		/* see post_send() */
 		barrier();
-		for (i = 0; i < wqe->wr.num_sge; i++) {
-			struct rvt_sge *sge = &wqe->sg_list[i];
-
-			rvt_put_mr(sge->mr);
-		}
-		/* Post a send completion queue entry if requested. */
-		if (!(qp->s_flags & RVT_S_SIGNAL_REQ_WR) ||
-		    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
-			memset(&wc, 0, sizeof(wc));
-			wc.wr_id = wqe->wr.wr_id;
-			wc.status = IB_WC_SUCCESS;
-			wc.opcode = ib_hfi1_wc_opcode[wqe->wr.opcode];
-			wc.byte_len = wqe->length;
-			wc.qp = &qp->ibqp;
-			rvt_cq_enter(ibcq_to_rvtcq(qp->ibqp.send_cq), &wc, 0);
-		}
+		rvt_put_swqe(wqe);
+		rvt_qp_swqe_complete(qp, wqe, IB_WC_SUCCESS);
 	}
 	/*
 	 * If we were waiting for sends to complete before re-sending,
@@ -1240,9 +1224,6 @@ static struct rvt_swqe *do_rc_completion
 					 struct rvt_swqe *wqe,
 					 struct hfi1_ibport *ibp)
 {
-	struct ib_wc wc;
-	unsigned i;
-
 	lockdep_assert_held(&qp->s_lock);
 	/*
 	 * Don't decrement refcount and don't generate a
@@ -1253,28 +1234,14 @@ static struct rvt_swqe *do_rc_completion
 	    cmp_psn(qp->s_sending_psn, qp->s_sending_hpsn) > 0) {
 		u32 s_last;
 
-		for (i = 0; i < wqe->wr.num_sge; i++) {
-			struct rvt_sge *sge = &wqe->sg_list[i];
-
-			rvt_put_mr(sge->mr);
-		}
+		rvt_put_swqe(wqe);
 		s_last = qp->s_last;
 		if (++s_last >= qp->s_size)
 			s_last = 0;
 		qp->s_last = s_last;
 		/* see post_send() */
 		barrier();
-		/* Post a send completion queue entry if requested. */
-		if (!(qp->s_flags & RVT_S_SIGNAL_REQ_WR) ||
-		    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
-			memset(&wc, 0, sizeof(wc));
-			wc.wr_id = wqe->wr.wr_id;
-			wc.status = IB_WC_SUCCESS;
-			wc.opcode = ib_hfi1_wc_opcode[wqe->wr.opcode];
-			wc.byte_len = wqe->length;
-			wc.qp = &qp->ibqp;
-			rvt_cq_enter(ibcq_to_rvtcq(qp->ibqp.send_cq), &wc, 0);
-		}
+		rvt_qp_swqe_complete(qp, wqe, IB_WC_SUCCESS);
 	} else {
 		struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
 
@@ -2295,7 +2262,7 @@ send_last:
 		hfi1_copy_sge(&qp->r_sge, data, tlen, 1, copy_last);
 		rvt_put_ss(&qp->r_sge);
 		qp->r_msn++;
-		if (!test_and_clear_bit(RVT_R_WRID_VALID, &qp->r_aflags))
+		if (!__test_and_clear_bit(RVT_R_WRID_VALID, &qp->r_aflags))
 			break;
 		wc.wr_id = qp->r_wr_id;
 		wc.status = IB_WC_SUCCESS;
@@ -2410,8 +2377,7 @@ send_last:
 			 * Update the next expected PSN.  We add 1 later
 			 * below, so only add the remainder here.
 			 */
-			if (len > pmtu)
-				qp->r_psn += (len - 1) / pmtu;
+			qp->r_psn += rvt_div_mtu(qp, len - 1);
 		} else {
 			e->rdma_sge.mr = NULL;
 			e->rdma_sge.vaddr = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/ruc.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/ruc.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/ruc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/ruc.c	2017-02-12 16:03:20.000000000 -0500
@@ -239,16 +239,6 @@ bail:
 	return ret;
 }
 
-static __be64 get_sguid(struct hfi1_ibport *ibp, unsigned index)
-{
-	if (!index) {
-		struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
-
-		return cpu_to_be64(ppd->guid);
-	}
-	return ibp->guids[index - 1];
-}
-
 static int gid_ok(union ib_gid *gid, __be64 gid_prefix, __be64 id)
 {
 	return (gid->global.interface_id == id &&
@@ -699,9 +689,9 @@ u32 hfi1_make_grh(struct hfi1_ibport *ib
 	/* The SGID is 32-bit aligned. */
 	hdr->sgid.global.subnet_prefix = ibp->rvp.gid_prefix;
 	hdr->sgid.global.interface_id =
-		grh->sgid_index && grh->sgid_index < ARRAY_SIZE(ibp->guids) ?
-		ibp->guids[grh->sgid_index - 1] :
-			cpu_to_be64(ppd_from_ibp(ibp)->guid);
+		grh->sgid_index < HFI1_GUIDS_PER_PORT ?
+		get_sguid(ibp, grh->sgid_index) :
+		get_sguid(ibp, HFI1_PORT_GUID_INDEX);
 	hdr->dgid = grh->dgid;
 
 	/* GRH header size in 32-bit words. */
@@ -777,8 +767,8 @@ void hfi1_make_ruc_header(struct rvt_qp
 	u32 bth1;
 
 	/* Construct the header. */
-	extra_bytes = -qp->s_cur_size & 3;
-	nwords = (qp->s_cur_size + extra_bytes) >> 2;
+	extra_bytes = -ps->s_txreq->s_cur_size & 3;
+	nwords = (ps->s_txreq->s_cur_size + extra_bytes) >> 2;
 	lrh0 = HFI1_LRH_BTH;
 	if (unlikely(qp->remote_ah_attr.ah_flags & IB_AH_GRH)) {
 		qp->s_hdrwords += hfi1_make_grh(ibp,
@@ -952,7 +942,6 @@ void hfi1_send_complete(struct rvt_qp *q
 			enum ib_wc_status status)
 {
 	u32 old_last, last;
-	unsigned i;
 
 	if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_OR_FLUSH_SEND))
 		return;
@@ -964,32 +953,13 @@ void hfi1_send_complete(struct rvt_qp *q
 	qp->s_last = last;
 	/* See post_send() */
 	barrier();
-	for (i = 0; i < wqe->wr.num_sge; i++) {
-		struct rvt_sge *sge = &wqe->sg_list[i];
-
-		rvt_put_mr(sge->mr);
-	}
+	rvt_put_swqe(wqe);
 	if (qp->ibqp.qp_type == IB_QPT_UD ||
 	    qp->ibqp.qp_type == IB_QPT_SMI ||
 	    qp->ibqp.qp_type == IB_QPT_GSI)
 		atomic_dec(&ibah_to_rvtah(wqe->ud_wr.ah)->refcount);
 
-	/* See ch. 11.2.4.1 and 10.7.3.1 */
-	if (!(qp->s_flags & RVT_S_SIGNAL_REQ_WR) ||
-	    (wqe->wr.send_flags & IB_SEND_SIGNALED) ||
-	    status != IB_WC_SUCCESS) {
-		struct ib_wc wc;
-
-		memset(&wc, 0, sizeof(wc));
-		wc.wr_id = wqe->wr.wr_id;
-		wc.status = status;
-		wc.opcode = ib_hfi1_wc_opcode[wqe->wr.opcode];
-		wc.qp = &qp->ibqp;
-		if (status == IB_WC_SUCCESS)
-			wc.byte_len = wqe->length;
-		rvt_cq_enter(ibcq_to_rvtcq(qp->ibqp.send_cq), &wc,
-			     status != IB_WC_SUCCESS);
-	}
+	rvt_qp_swqe_complete(qp, wqe, status);
 
 	if (qp->s_acked == old_last)
 		qp->s_acked = last;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/sdma.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/sdma.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/sdma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/sdma.c	2017-02-12 16:03:20.000000000 -0500
@@ -375,7 +375,7 @@ static inline void complete_tx(struct sd
 			   sde->head_sn, tx->sn);
 	sde->head_sn++;
 #endif
-	sdma_txclean(sde->dd, tx);
+	__sdma_txclean(sde->dd, tx);
 	if (complete)
 		(*complete)(tx, res);
 	if (wait && iowait_sdma_dec(wait))
@@ -1643,7 +1643,7 @@ static inline u8 ahg_mode(struct sdma_tx
 }
 
 /**
- * sdma_txclean() - clean tx of mappings, descp *kmalloc's
+ * __sdma_txclean() - clean tx of mappings, descp *kmalloc's
  * @dd: hfi1_devdata for unmapping
  * @tx: tx request to clean
  *
@@ -1653,7 +1653,7 @@ static inline u8 ahg_mode(struct sdma_tx
  * The code can be called multiple times without issue.
  *
  */
-void sdma_txclean(
+void __sdma_txclean(
 	struct hfi1_devdata *dd,
 	struct sdma_txreq *tx)
 {
@@ -3065,7 +3065,7 @@ static int _extend_sdma_tx_descs(struct
 		tx->descp[i] = tx->descs[i];
 	return 0;
 enomem:
-	sdma_txclean(dd, tx);
+	__sdma_txclean(dd, tx);
 	return -ENOMEM;
 }
 
@@ -3094,14 +3094,14 @@ int ext_coal_sdma_tx_descs(struct hfi1_d
 
 	rval = _extend_sdma_tx_descs(dd, tx);
 	if (rval) {
-		sdma_txclean(dd, tx);
+		__sdma_txclean(dd, tx);
 		return rval;
 	}
 
 	/* If coalesce buffer is allocated, copy data into it */
 	if (tx->coalesce_buf) {
 		if (type == SDMA_MAP_NONE) {
-			sdma_txclean(dd, tx);
+			__sdma_txclean(dd, tx);
 			return -EINVAL;
 		}
 
@@ -3109,7 +3109,7 @@ int ext_coal_sdma_tx_descs(struct hfi1_d
 			kvaddr = kmap(page);
 			kvaddr += offset;
 		} else if (WARN_ON(!kvaddr)) {
-			sdma_txclean(dd, tx);
+			__sdma_txclean(dd, tx);
 			return -EINVAL;
 		}
 
@@ -3139,7 +3139,7 @@ int ext_coal_sdma_tx_descs(struct hfi1_d
 				      DMA_TO_DEVICE);
 
 		if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
-			sdma_txclean(dd, tx);
+			__sdma_txclean(dd, tx);
 			return -ENOSPC;
 		}
 
@@ -3181,7 +3181,7 @@ int _pad_sdma_tx_descs(struct hfi1_devda
 	if ((unlikely(tx->num_desc == tx->desc_limit))) {
 		rval = _extend_sdma_tx_descs(dd, tx);
 		if (rval) {
-			sdma_txclean(dd, tx);
+			__sdma_txclean(dd, tx);
 			return rval;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/sdma.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/sdma.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/sdma.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/sdma.h	2017-02-12 16:03:20.000000000 -0500
@@ -667,7 +667,13 @@ int ext_coal_sdma_tx_descs(struct hfi1_d
 			   int type, void *kvaddr, struct page *page,
 			   unsigned long offset, u16 len);
 int _pad_sdma_tx_descs(struct hfi1_devdata *, struct sdma_txreq *);
-void sdma_txclean(struct hfi1_devdata *, struct sdma_txreq *);
+void __sdma_txclean(struct hfi1_devdata *, struct sdma_txreq *);
+
+static inline void sdma_txclean(struct hfi1_devdata *dd, struct sdma_txreq *tx)
+{
+	if (tx->num_desc)
+		__sdma_txclean(dd, tx);
+}
 
 /* helpers used by public routines */
 static inline void _sdma_close_tx(struct hfi1_devdata *dd,
@@ -753,7 +759,7 @@ static inline int sdma_txadd_page(
 		       DMA_TO_DEVICE);
 
 	if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
-		sdma_txclean(dd, tx);
+		__sdma_txclean(dd, tx);
 		return -ENOSPC;
 	}
 
@@ -834,7 +840,7 @@ static inline int sdma_txadd_kvaddr(
 		       DMA_TO_DEVICE);
 
 	if (unlikely(dma_mapping_error(&dd->pcidev->dev, addr))) {
-		sdma_txclean(dd, tx);
+		__sdma_txclean(dd, tx);
 		return -ENOSPC;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/uc.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/uc.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/uc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/uc.c	2017-02-12 16:03:20.000000000 -0500
@@ -258,8 +258,8 @@ int hfi1_make_uc_req(struct rvt_qp *qp,
 	qp->s_len -= len;
 	qp->s_hdrwords = hwords;
 	ps->s_txreq->sde = priv->s_sde;
-	qp->s_cur_sge = &qp->s_sge;
-	qp->s_cur_size = len;
+	ps->s_txreq->ss = &qp->s_sge;
+	ps->s_txreq->s_cur_size = len;
 	hfi1_make_ruc_header(qp, ohdr, bth0 | (qp->s_state << 24),
 			     mask_psn(qp->s_psn++), middle, ps);
 	/* pbc */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/ud.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/ud.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/ud.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/ud.c	2017-02-12 16:03:20.000000000 -0500
@@ -354,8 +354,8 @@ int hfi1_make_ud_req(struct rvt_qp *qp,
 
 	/* header size in 32-bit words LRH+BTH+DETH = (8+12+8)/4. */
 	qp->s_hdrwords = 7;
-	qp->s_cur_size = wqe->length;
-	qp->s_cur_sge = &qp->s_sge;
+	ps->s_txreq->s_cur_size = wqe->length;
+	ps->s_txreq->ss = &qp->s_sge;
 	qp->s_srate = ah_attr->static_rate;
 	qp->srate_mbps = ib_rate_to_mbps(qp->s_srate);
 	qp->s_wqe = wqe;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/user_sdma.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/user_sdma.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/user_sdma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/user_sdma.c	2017-02-12 16:03:20.000000000 -0500
@@ -115,6 +115,7 @@ MODULE_PARM_DESC(sdma_comp_size, "Size o
 #define KDETH_HCRC_LOWER_MASK     0xff
 
 #define AHG_KDETH_INTR_SHIFT 12
+#define AHG_KDETH_SH_SHIFT   13
 
 #define PBC2LRH(x) ((((x) & 0xfff) << 2) - 4)
 #define LRH2PBC(x) ((((x) >> 2) + 1) & 0xfff)
@@ -144,8 +145,9 @@ MODULE_PARM_DESC(sdma_comp_size, "Size o
 #define KDETH_OM_LARGE     64
 #define KDETH_OM_MAX_SIZE  (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1))
 
-/* Last packet in the request */
-#define TXREQ_FLAGS_REQ_LAST_PKT BIT(0)
+/* Tx request flag bits */
+#define TXREQ_FLAGS_REQ_ACK   BIT(0)      /* Set the ACK bit in the header */
+#define TXREQ_FLAGS_REQ_DISABLE_SH BIT(1) /* Disable header suppression */
 
 /* SDMA request flag bits */
 #define SDMA_REQ_FOR_THREAD 1
@@ -943,8 +945,13 @@ static int user_sdma_send_pkts(struct us
 		tx->busycount = 0;
 		INIT_LIST_HEAD(&tx->list);
 
+		/*
+		 * For the last packet set the ACK request
+		 * and disable header suppression.
+		 */
 		if (req->seqnum == req->info.npkts - 1)
-			tx->flags |= TXREQ_FLAGS_REQ_LAST_PKT;
+			tx->flags |= (TXREQ_FLAGS_REQ_ACK |
+				      TXREQ_FLAGS_REQ_DISABLE_SH);
 
 		/*
 		 * Calculate the payload size - this is min of the fragment
@@ -963,11 +970,22 @@ static int user_sdma_send_pkts(struct us
 			}
 
 			datalen = compute_data_length(req, tx);
+
+			/*
+			 * Disable header suppression for the payload <= 8DWS.
+			 * If there is an uncorrectable error in the receive
+			 * data FIFO when the received payload size is less than
+			 * or equal to 8DWS then the RxDmaDataFifoRdUncErr is
+			 * not reported.There is set RHF.EccErr if the header
+			 * is not suppressed.
+			 */
 			if (!datalen) {
 				SDMA_DBG(req,
 					 "Request has data but pkt len is 0");
 				ret = -EFAULT;
 				goto free_tx;
+			} else if (datalen <= 32) {
+				tx->flags |= TXREQ_FLAGS_REQ_DISABLE_SH;
 			}
 		}
 
@@ -990,6 +1008,10 @@ static int user_sdma_send_pkts(struct us
 						LRH2PBC(lrhlen);
 					tx->hdr.pbc[0] = cpu_to_le16(pbclen);
 				}
+				ret = check_header_template(req, &tx->hdr,
+							    lrhlen, datalen);
+				if (ret)
+					goto free_tx;
 				ret = sdma_txinit_ahg(&tx->txreq,
 						      SDMA_TXREQ_F_AHG_COPY,
 						      sizeof(tx->hdr) + datalen,
@@ -1351,7 +1373,7 @@ static int set_txreq_header(struct user_
 				req->seqnum));
 
 	/* Set ACK request on last packet */
-	if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT))
+	if (unlikely(tx->flags & TXREQ_FLAGS_REQ_ACK))
 		hdr->bth[2] |= cpu_to_be32(1UL << 31);
 
 	/* Set the new offset */
@@ -1384,8 +1406,8 @@ static int set_txreq_header(struct user_
 		/* Set KDETH.TID based on value for this TID */
 		KDETH_SET(hdr->kdeth.ver_tid_offset, TID,
 			  EXP_TID_GET(tidval, IDX));
-		/* Clear KDETH.SH only on the last packet */
-		if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT))
+		/* Clear KDETH.SH when DISABLE_SH flag is set */
+		if (unlikely(tx->flags & TXREQ_FLAGS_REQ_DISABLE_SH))
 			KDETH_SET(hdr->kdeth.ver_tid_offset, SH, 0);
 		/*
 		 * Set the KDETH.OFFSET and KDETH.OM based on size of
@@ -1429,7 +1451,7 @@ static int set_txreq_header_ahg(struct u
 	/* BTH.PSN and BTH.A */
 	val32 = (be32_to_cpu(hdr->bth[2]) + req->seqnum) &
 		(HFI1_CAP_IS_KSET(EXTENDED_PSN) ? 0x7fffffff : 0xffffff);
-	if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT))
+	if (unlikely(tx->flags & TXREQ_FLAGS_REQ_ACK))
 		val32 |= 1UL << 31;
 	AHG_HEADER_SET(req->ahg, diff, 6, 0, 16, cpu_to_be16(val32 >> 16));
 	AHG_HEADER_SET(req->ahg, diff, 6, 16, 16, cpu_to_be16(val32 & 0xffff));
@@ -1468,19 +1490,23 @@ static int set_txreq_header_ahg(struct u
 		AHG_HEADER_SET(req->ahg, diff, 7, 0, 16,
 			       ((!!(req->omfactor - KDETH_OM_SMALL)) << 15 |
 				((req->tidoffset / req->omfactor) & 0x7fff)));
-		/* KDETH.TIDCtrl, KDETH.TID */
+		/* KDETH.TIDCtrl, KDETH.TID, KDETH.Intr, KDETH.SH */
 		val = cpu_to_le16(((EXP_TID_GET(tidval, CTRL) & 0x3) << 10) |
-					(EXP_TID_GET(tidval, IDX) & 0x3ff));
-		/* Clear KDETH.SH on last packet */
-		if (unlikely(tx->flags & TXREQ_FLAGS_REQ_LAST_PKT)) {
-			val |= cpu_to_le16(KDETH_GET(hdr->kdeth.ver_tid_offset,
-						     INTR) <<
-					   AHG_KDETH_INTR_SHIFT);
-			val &= cpu_to_le16(~(1U << 13));
-			AHG_HEADER_SET(req->ahg, diff, 7, 16, 14, val);
+				   (EXP_TID_GET(tidval, IDX) & 0x3ff));
+
+		if (unlikely(tx->flags & TXREQ_FLAGS_REQ_DISABLE_SH)) {
+			val |= cpu_to_le16((KDETH_GET(hdr->kdeth.ver_tid_offset,
+						      INTR) <<
+					    AHG_KDETH_INTR_SHIFT));
 		} else {
-			AHG_HEADER_SET(req->ahg, diff, 7, 16, 12, val);
+			val |= KDETH_GET(hdr->kdeth.ver_tid_offset, SH) ?
+			       cpu_to_le16(0x1 << AHG_KDETH_SH_SHIFT) :
+			       cpu_to_le16((KDETH_GET(hdr->kdeth.ver_tid_offset,
+						      INTR) <<
+					     AHG_KDETH_INTR_SHIFT));
 		}
+
+		AHG_HEADER_SET(req->ahg, diff, 7, 16, 14, val);
 	}
 
 	trace_hfi1_sdma_user_header_ahg(pq->dd, pq->ctxt, pq->subctxt,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -297,22 +297,6 @@ static inline int wss_exceeds_threshold(
 }
 
 /*
- * Translate ib_wr_opcode into ib_wc_opcode.
- */
-const enum ib_wc_opcode ib_hfi1_wc_opcode[] = {
-	[IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE,
-	[IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE,
-	[IB_WR_SEND] = IB_WC_SEND,
-	[IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
-	[IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
-	[IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
-	[IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD,
-	[IB_WR_SEND_WITH_INV] = IB_WC_SEND,
-	[IB_WR_LOCAL_INV] = IB_WC_LOCAL_INV,
-	[IB_WR_REG_MR] = IB_WC_REG_MR
-};
-
-/*
  * Length of header by opcode, 0 --> not supported
  */
 const u8 hdr_len_by_opcode[256] = {
@@ -694,6 +678,7 @@ static void mem_timer(unsigned long data
 		qp = iowait_to_qp(wait);
 		priv = qp->priv;
 		list_del_init(&priv->s_iowait.list);
+		priv->s_iowait.lock = NULL;
 		/* refcount held until actual wake up */
 		if (!list_empty(list))
 			mod_timer(&dev->mem_timer, jiffies + 1);
@@ -769,6 +754,7 @@ static int wait_kmem(struct hfi1_ibdev *
 				mod_timer(&dev->mem_timer, jiffies + 1);
 			qp->s_flags |= RVT_S_WAIT_KMEM;
 			list_add_tail(&priv->s_iowait.list, &dev->memwait);
+			priv->s_iowait.lock = &dev->iowait_lock;
 			trace_hfi1_qpsleep(qp, RVT_S_WAIT_KMEM);
 			rvt_get_qp(qp);
 		}
@@ -788,10 +774,10 @@ static int wait_kmem(struct hfi1_ibdev *
  */
 static noinline int build_verbs_ulp_payload(
 	struct sdma_engine *sde,
-	struct rvt_sge_state *ss,
 	u32 length,
 	struct verbs_txreq *tx)
 {
+	struct rvt_sge_state *ss = tx->ss;
 	struct rvt_sge *sg_list = ss->sg_list;
 	struct rvt_sge sge = ss->sge;
 	u8 num_sge = ss->num_sge;
@@ -835,7 +821,6 @@ bail_txadd:
 /* New API */
 static int build_verbs_tx_desc(
 	struct sdma_engine *sde,
-	struct rvt_sge_state *ss,
 	u32 length,
 	struct verbs_txreq *tx,
 	struct hfi1_ahg_info *ahg_info,
@@ -879,9 +864,9 @@ static int build_verbs_tx_desc(
 			goto bail_txadd;
 	}
 
-	/* add the ulp payload - if any.  ss can be NULL for acks */
-	if (ss)
-		ret = build_verbs_ulp_payload(sde, ss, length, tx);
+	/* add the ulp payload - if any. tx->ss can be NULL for acks */
+	if (tx->ss)
+		ret = build_verbs_ulp_payload(sde, length, tx);
 bail_txadd:
 	return ret;
 }
@@ -892,8 +877,7 @@ int hfi1_verbs_send_dma(struct rvt_qp *q
 	struct hfi1_qp_priv *priv = qp->priv;
 	struct hfi1_ahg_info *ahg_info = priv->s_ahg;
 	u32 hdrwords = qp->s_hdrwords;
-	struct rvt_sge_state *ss = qp->s_cur_sge;
-	u32 len = qp->s_cur_size;
+	u32 len = ps->s_txreq->s_cur_size;
 	u32 plen = hdrwords + ((len + 3) >> 2) + 2; /* includes pbc */
 	struct hfi1_ibdev *dev = ps->dev;
 	struct hfi1_pportdata *ppd = ps->ppd;
@@ -918,7 +902,7 @@ int hfi1_verbs_send_dma(struct rvt_qp *q
 					 plen);
 		}
 		tx->wqe = qp->s_wqe;
-		ret = build_verbs_tx_desc(tx->sde, ss, len, tx, ahg_info, pbc);
+		ret = build_verbs_tx_desc(tx->sde, len, tx, ahg_info, pbc);
 		if (unlikely(ret))
 			goto bail_build;
 	}
@@ -980,6 +964,7 @@ static int pio_wait(struct rvt_qp *qp,
 			qp->s_flags |= flag;
 			was_empty = list_empty(&sc->piowait);
 			list_add_tail(&priv->s_iowait.list, &sc->piowait);
+			priv->s_iowait.lock = &dev->iowait_lock;
 			trace_hfi1_qpsleep(qp, RVT_S_WAIT_PIO);
 			rvt_get_qp(qp);
 			/* counting: only call wantpiobuf_intr if first user */
@@ -1008,8 +993,8 @@ int hfi1_verbs_send_pio(struct rvt_qp *q
 {
 	struct hfi1_qp_priv *priv = qp->priv;
 	u32 hdrwords = qp->s_hdrwords;
-	struct rvt_sge_state *ss = qp->s_cur_sge;
-	u32 len = qp->s_cur_size;
+	struct rvt_sge_state *ss = ps->s_txreq->ss;
+	u32 len = ps->s_txreq->s_cur_size;
 	u32 dwords = (len + 3) >> 2;
 	u32 plen = hdrwords + dwords + 2; /* includes pbc */
 	struct hfi1_pportdata *ppd = ps->ppd;
@@ -1237,7 +1222,7 @@ static inline send_routine get_send_rout
 		u8 op = get_opcode(h);
 
 		if (piothreshold &&
-		    qp->s_cur_size <= min(piothreshold, qp->pmtu) &&
+		    tx->s_cur_size <= min(piothreshold, qp->pmtu) &&
 		    (BIT(op & OPMASK) & pio_opmask[op >> 5]) &&
 		    iowait_sdma_pending(&priv->s_iowait) == 0 &&
 		    !sdma_txreq_built(&tx->txreq))
@@ -1483,15 +1468,11 @@ static int hfi1_get_guid_be(struct rvt_d
 			    int guid_index, __be64 *guid)
 {
 	struct hfi1_ibport *ibp = container_of(rvp, struct hfi1_ibport, rvp);
-	struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
 
-	if (guid_index == 0)
-		*guid = cpu_to_be64(ppd->guid);
-	else if (guid_index < HFI1_GUIDS_PER_PORT)
-		*guid = ibp->guids[guid_index - 1];
-	else
+	if (guid_index >= HFI1_GUIDS_PER_PORT)
 		return -EINVAL;
 
+	*guid = get_sguid(ibp, guid_index);
 	return 0;
 }
 
@@ -1610,6 +1591,154 @@ static void hfi1_get_dev_fw_str(struct i
 		 dc8051_ver_min(ver));
 }
 
+static const char * const driver_cntr_names[] = {
+	/* must be element 0*/
+	"DRIVER_KernIntr",
+	"DRIVER_ErrorIntr",
+	"DRIVER_Tx_Errs",
+	"DRIVER_Rcv_Errs",
+	"DRIVER_HW_Errs",
+	"DRIVER_NoPIOBufs",
+	"DRIVER_CtxtsOpen",
+	"DRIVER_RcvLen_Errs",
+	"DRIVER_EgrBufFull",
+	"DRIVER_EgrHdrFull"
+};
+
+static const char **dev_cntr_names;
+static const char **port_cntr_names;
+static int num_driver_cntrs = ARRAY_SIZE(driver_cntr_names);
+static int num_dev_cntrs;
+static int num_port_cntrs;
+static int cntr_names_initialized;
+
+/*
+ * Convert a list of names separated by '\n' into an array of NULL terminated
+ * strings. Optionally some entries can be reserved in the array to hold extra
+ * external strings.
+ */
+static int init_cntr_names(const char *names_in,
+			   const int names_len,
+			   int num_extra_names,
+			   int *num_cntrs,
+			   const char ***cntr_names)
+{
+	char *names_out, *p, **q;
+	int i, n;
+
+	n = 0;
+	for (i = 0; i < names_len; i++)
+		if (names_in[i] == '\n')
+			n++;
+
+	names_out = kmalloc((n + num_extra_names) * sizeof(char *) + names_len,
+			    GFP_KERNEL);
+	if (!names_out) {
+		*num_cntrs = 0;
+		*cntr_names = NULL;
+		return -ENOMEM;
+	}
+
+	p = names_out + (n + num_extra_names) * sizeof(char *);
+	memcpy(p, names_in, names_len);
+
+	q = (char **)names_out;
+	for (i = 0; i < n; i++) {
+		q[i] = p;
+		p = strchr(p, '\n');
+		*p++ = '\0';
+	}
+
+	*num_cntrs = n;
+	*cntr_names = (const char **)names_out;
+	return 0;
+}
+
+static struct rdma_hw_stats *alloc_hw_stats(struct ib_device *ibdev,
+					    u8 port_num)
+{
+	int i, err;
+
+	if (!cntr_names_initialized) {
+		struct hfi1_devdata *dd = dd_from_ibdev(ibdev);
+
+		err = init_cntr_names(dd->cntrnames,
+				      dd->cntrnameslen,
+				      num_driver_cntrs,
+				      &num_dev_cntrs,
+				      &dev_cntr_names);
+		if (err)
+			return NULL;
+
+		for (i = 0; i < num_driver_cntrs; i++)
+			dev_cntr_names[num_dev_cntrs + i] =
+				driver_cntr_names[i];
+
+		err = init_cntr_names(dd->portcntrnames,
+				      dd->portcntrnameslen,
+				      0,
+				      &num_port_cntrs,
+				      &port_cntr_names);
+		if (err) {
+			kfree(dev_cntr_names);
+			dev_cntr_names = NULL;
+			return NULL;
+		}
+		cntr_names_initialized = 1;
+	}
+
+	if (!port_num)
+		return rdma_alloc_hw_stats_struct(
+				dev_cntr_names,
+				num_dev_cntrs + num_driver_cntrs,
+				RDMA_HW_STATS_DEFAULT_LIFESPAN);
+	else
+		return rdma_alloc_hw_stats_struct(
+				port_cntr_names,
+				num_port_cntrs,
+				RDMA_HW_STATS_DEFAULT_LIFESPAN);
+}
+
+static u64 hfi1_sps_ints(void)
+{
+	unsigned long flags;
+	struct hfi1_devdata *dd;
+	u64 sps_ints = 0;
+
+	spin_lock_irqsave(&hfi1_devs_lock, flags);
+	list_for_each_entry(dd, &hfi1_dev_list, list) {
+		sps_ints += get_all_cpu_total(dd->int_counter);
+	}
+	spin_unlock_irqrestore(&hfi1_devs_lock, flags);
+	return sps_ints;
+}
+
+static int get_hw_stats(struct ib_device *ibdev, struct rdma_hw_stats *stats,
+			u8 port, int index)
+{
+	u64 *values;
+	int count;
+
+	if (!port) {
+		u64 *stats = (u64 *)&hfi1_stats;
+		int i;
+
+		hfi1_read_cntrs(dd_from_ibdev(ibdev), NULL, &values);
+		values[num_dev_cntrs] = hfi1_sps_ints();
+		for (i = 1; i < num_driver_cntrs; i++)
+			values[num_dev_cntrs + i] = stats[i];
+		count = num_dev_cntrs + num_driver_cntrs;
+	} else {
+		struct hfi1_ibport *ibp = to_iport(ibdev, port);
+
+		hfi1_read_portcntrs(ppd_from_ibp(ibp), NULL, &values);
+		count = num_port_cntrs;
+	}
+
+	memcpy(stats->value, values, count * sizeof(u64));
+	return count;
+}
+
 /**
  * hfi1_register_ib_device - register our device with the infiniband core
  * @dd: the device data structure
@@ -1620,6 +1749,7 @@ int hfi1_register_ib_device(struct hfi1_
 	struct hfi1_ibdev *dev = &dd->verbs_dev;
 	struct ib_device *ibdev = &dev->rdi.ibdev;
 	struct hfi1_pportdata *ppd = dd->pport;
+	struct hfi1_ibport *ibp = &ppd->ibport_data;
 	unsigned i;
 	int ret;
 	size_t lcpysz = IB_DEVICE_NAME_MAX;
@@ -1632,6 +1762,7 @@ int hfi1_register_ib_device(struct hfi1_
 	setup_timer(&dev->mem_timer, mem_timer, (unsigned long)dev);
 
 	seqlock_init(&dev->iowait_lock);
+	seqlock_init(&dev->txwait_lock);
 	INIT_LIST_HEAD(&dev->txwait);
 	INIT_LIST_HEAD(&dev->memwait);
 
@@ -1639,20 +1770,24 @@ int hfi1_register_ib_device(struct hfi1_
 	if (ret)
 		goto err_verbs_txreq;
 
+	/* Use first-port GUID as node guid */
+	ibdev->node_guid = get_sguid(ibp, HFI1_PORT_GUID_INDEX);
+
 	/*
 	 * The system image GUID is supposed to be the same for all
 	 * HFIs in a single system but since there can be other
 	 * device types in the system, we can't be sure this is unique.
 	 */
 	if (!ib_hfi1_sys_image_guid)
-		ib_hfi1_sys_image_guid = cpu_to_be64(ppd->guid);
+		ib_hfi1_sys_image_guid = ibdev->node_guid;
 	lcpysz = strlcpy(ibdev->name, class_name(), lcpysz);
 	strlcpy(ibdev->name + lcpysz, "_%d", IB_DEVICE_NAME_MAX - lcpysz);
 	ibdev->owner = THIS_MODULE;
-	ibdev->node_guid = cpu_to_be64(ppd->guid);
 	ibdev->phys_port_cnt = dd->num_pports;
 	ibdev->dma_device = &dd->pcidev->dev;
 	ibdev->modify_device = modify_device;
+	ibdev->alloc_hw_stats = alloc_hw_stats;
+	ibdev->get_hw_stats = get_hw_stats;
 
 	/* keep process mad in the driver */
 	ibdev->process_mad = hfi1_process_mad;
@@ -1767,6 +1902,10 @@ void hfi1_unregister_ib_device(struct hf
 
 	del_timer_sync(&dev->mem_timer);
 	verbs_txreq_exit(dev);
+
+	kfree(dev_cntr_names);
+	kfree(port_cntr_names);
+	cntr_names_initialized = 0;
 }
 
 void hfi1_cnp_rcv(struct hfi1_packet *packet)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs.h	2017-02-12 16:03:20.000000000 -0500
@@ -73,7 +73,6 @@ struct hfi1_packet;
 #include "iowait.h"
 
 #define HFI1_MAX_RDMA_ATOMIC     16
-#define HFI1_GUIDS_PER_PORT	5
 
 /*
  * Increment this value if any changes that break userspace ABI
@@ -169,8 +168,6 @@ struct hfi1_ibport {
 	struct rvt_qp __rcu *qp[2];
 	struct rvt_ibport rvp;
 
-	__be64 guids[HFI1_GUIDS_PER_PORT	- 1];	/* writable GUIDs */
-
 	/* the first 16 entries are sl_to_vl for !OPA */
 	u8 sl_to_sc[32];
 	u8 sc_to_sl[32];
@@ -180,18 +177,19 @@ struct hfi1_ibdev {
 	struct rvt_dev_info rdi; /* Must be first */
 
 	/* QP numbers are shared by all IB ports */
-	/* protect wait lists */
-	seqlock_t iowait_lock;
+	/* protect txwait list */
+	seqlock_t txwait_lock ____cacheline_aligned_in_smp;
 	struct list_head txwait;        /* list for wait verbs_txreq */
 	struct list_head memwait;       /* list for wait kernel memory */
-	struct list_head txreq_free;
 	struct kmem_cache *verbs_txreq_cache;
-	struct timer_list mem_timer;
+	u64 n_txwait;
+	u64 n_kmem_wait;
 
+	/* protect iowait lists */
+	seqlock_t iowait_lock ____cacheline_aligned_in_smp;
 	u64 n_piowait;
 	u64 n_piodrain;
-	u64 n_txwait;
-	u64 n_kmem_wait;
+	struct timer_list mem_timer;
 
 #ifdef CONFIG_DEBUG_FS
 	/* per HFI debugfs */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,22 +72,22 @@ void hfi1_put_txreq(struct verbs_txreq *
 	kmem_cache_free(dev->verbs_txreq_cache, tx);
 
 	do {
-		seq = read_seqbegin(&dev->iowait_lock);
+		seq = read_seqbegin(&dev->txwait_lock);
 		if (!list_empty(&dev->txwait)) {
 			struct iowait *wait;
 
-			write_seqlock_irqsave(&dev->iowait_lock, flags);
+			write_seqlock_irqsave(&dev->txwait_lock, flags);
 			wait = list_first_entry(&dev->txwait, struct iowait,
 						list);
 			qp = iowait_to_qp(wait);
 			priv = qp->priv;
 			list_del_init(&priv->s_iowait.list);
 			/* refcount held until actual wake up */
-			write_sequnlock_irqrestore(&dev->iowait_lock, flags);
+			write_sequnlock_irqrestore(&dev->txwait_lock, flags);
 			hfi1_qp_wakeup(qp, RVT_S_WAIT_TX);
 			break;
 		}
-	} while (read_seqretry(&dev->iowait_lock, seq));
+	} while (read_seqretry(&dev->txwait_lock, seq));
 }
 
 struct verbs_txreq *__get_txreq(struct hfi1_ibdev *dev,
@@ -96,7 +96,7 @@ struct verbs_txreq *__get_txreq(struct h
 {
 	struct verbs_txreq *tx = ERR_PTR(-EBUSY);
 
-	write_seqlock(&dev->iowait_lock);
+	write_seqlock(&dev->txwait_lock);
 	if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) {
 		struct hfi1_qp_priv *priv;
 
@@ -108,13 +108,14 @@ struct verbs_txreq *__get_txreq(struct h
 			dev->n_txwait++;
 			qp->s_flags |= RVT_S_WAIT_TX;
 			list_add_tail(&priv->s_iowait.list, &dev->txwait);
+			priv->s_iowait.lock = &dev->txwait_lock;
 			trace_hfi1_qpsleep(qp, RVT_S_WAIT_TX);
 			rvt_get_qp(qp);
 		}
 		qp->s_flags &= ~RVT_S_BUSY;
 	}
 out:
-	write_sequnlock(&dev->iowait_lock);
+	write_sequnlock(&dev->txwait_lock);
 	return tx;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hfi1/verbs_txreq.h	2017-02-12 16:03:20.000000000 -0500
@@ -65,6 +65,7 @@ struct verbs_txreq {
 	struct sdma_engine     *sde;
 	struct send_context     *psc;
 	u16                     hdr_dwords;
+	u16			s_cur_size;
 };
 
 struct hfi1_ibdev;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_ah.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_ah.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_ah.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_ah.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,8 @@
 #define HNS_ROCE_VLAN_SL_BIT_MASK	7
 #define HNS_ROCE_VLAN_SL_SHIFT		13
 
-struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *ah_attr)
+struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *ah_attr,
+				 struct ib_udata *udata)
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(ibpd->device);
 	struct device *dev = &hr_dev->pdev->dev;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_alloc.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_alloc.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_alloc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_alloc.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,9 +61,10 @@ int hns_roce_bitmap_alloc(struct hns_roc
 	return ret;
 }
 
-void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj)
+void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj,
+			  int rr)
 {
-	hns_roce_bitmap_free_range(bitmap, obj, 1);
+	hns_roce_bitmap_free_range(bitmap, obj, 1, rr);
 }
 
 int hns_roce_bitmap_alloc_range(struct hns_roce_bitmap *bitmap, int cnt,
@@ -106,7 +107,8 @@ int hns_roce_bitmap_alloc_range(struct h
 }
 
 void hns_roce_bitmap_free_range(struct hns_roce_bitmap *bitmap,
-				unsigned long obj, int cnt)
+				unsigned long obj, int cnt,
+				int rr)
 {
 	int i;
 
@@ -116,7 +118,8 @@ void hns_roce_bitmap_free_range(struct h
 	for (i = 0; i < cnt; i++)
 		clear_bit(obj + i, bitmap->table);
 
-	bitmap->last = min(bitmap->last, obj);
+	if (!rr)
+		bitmap->last = min(bitmap->last, obj);
 	bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
 		       & bitmap->mask;
 	spin_unlock(&bitmap->lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -216,10 +216,10 @@ static int __hns_roce_cmd_mbox_wait(stru
 		goto out;
 
 	/*
-	* It is timeout when wait_for_completion_timeout return 0
-	* The return value is the time limit set in advance
-	* how many seconds showing
-	*/
+	 * It is timeout when wait_for_completion_timeout return 0
+	 * The return value is the time limit set in advance
+	 * how many seconds showing
+	 */
 	if (!wait_for_completion_timeout(&context->done,
 					 msecs_to_jiffies(timeout))) {
 		dev_err(dev, "[cmd]wait_for_completion_timeout timeout\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_cmd.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,7 @@
 #define _HNS_ROCE_CMD_H
 
 #define HNS_ROCE_MAILBOX_SIZE		4096
+#define HNS_ROCE_CMD_TIMEOUT_MSECS	10000
 
 enum {
 	/* TPT commands */
@@ -57,17 +58,6 @@ enum {
 	HNS_ROCE_CMD_QUERY_QP		= 0x22,
 };
 
-enum {
-	HNS_ROCE_CMD_TIME_CLASS_A	= 10000,
-	HNS_ROCE_CMD_TIME_CLASS_B	= 10000,
-	HNS_ROCE_CMD_TIME_CLASS_C	= 10000,
-};
-
-struct hns_roce_cmd_mailbox {
-	void		       *buf;
-	dma_addr_t		dma;
-};
-
 int hns_roce_cmd_mbox(struct hns_roce_dev *hr_dev, u64 in_param, u64 out_param,
 		      unsigned long in_modifier, u8 op_modifier, u16 op,
 		      unsigned long timeout);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_common.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_common.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -57,6 +57,32 @@
 #define roce_set_bit(origin, shift, val) \
 	roce_set_field((origin), (1ul << (shift)), (shift), (val))
 
+/*
+ * roce_hw_index_cmp_lt - Compare two hardware index values in hisilicon
+ *                        SOC, check if a is less than b.
+ * @a: hardware index value
+ * @b: hardware index value
+ * @bits: the number of bits of a and b, range: 0~31.
+ *
+ * Hardware index increases continuously till max value, and then restart
+ * from zero, again and again. Because the bits of reg field is often
+ * limited, the reg field can only hold the low bits of the hardware index
+ * in hisilicon SOC.
+ * In some scenes we need to compare two values(a,b) getted from two reg
+ * fields in this driver, for example:
+ * If a equals 0xfffe, b equals 0x1 and bits equals 16, we think b has
+ * incresed from 0xffff to 0x1 and a is less than b.
+ * If a equals 0xfffe, b equals 0x0xf001 and bits equals 16, we think a
+ * is bigger than b.
+ *
+ * Return true on a less than b, otherwise false.
+ */
+#define roce_hw_index_mask(bits)	((1ul << (bits)) - 1)
+#define roce_hw_index_shift(bits)	(32 - (bits))
+#define roce_hw_index_cmp_lt(a, b, bits) \
+	((int)((((a) - (b)) & roce_hw_index_mask(bits)) << \
+		roce_hw_index_shift(bits)) < 0)
+
 #define ROCEE_GLB_CFG_ROCEE_DB_SQ_MODE_S 3
 #define ROCEE_GLB_CFG_ROCEE_DB_OTH_MODE_S 4
 
@@ -245,16 +271,26 @@
 #define ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M   \
 	(((1UL << 28) - 1) << ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S)
 
+#define ROCEE_SDB_PTR_CMP_BITS 28
+
 #define ROCEE_SDB_INV_CNT_SDB_INV_CNT_S 0
 #define ROCEE_SDB_INV_CNT_SDB_INV_CNT_M   \
 	(((1UL << 16) - 1) << ROCEE_SDB_INV_CNT_SDB_INV_CNT_S)
 
+#define ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S	0
+#define ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M	\
+	(((1UL << 16) - 1) << ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S)
+
+#define ROCEE_SDB_CNT_CMP_BITS 16
+
+#define ROCEE_TSP_BP_ST_QH_FIFO_ENTRY_S	20
+
+#define ROCEE_CNT_CLR_CE_CNT_CLR_CE_S 0
+
 /*************ROCEE_REG DEFINITION****************/
 #define ROCEE_VENDOR_ID_REG			0x0
 #define ROCEE_VENDOR_PART_ID_REG		0x4
 
-#define ROCEE_HW_VERSION_REG			0x8
-
 #define ROCEE_SYS_IMAGE_GUID_L_REG		0xC
 #define ROCEE_SYS_IMAGE_GUID_H_REG		0x10
 
@@ -318,7 +354,11 @@
 
 #define ROCEE_SDB_ISSUE_PTR_REG			0x758
 #define ROCEE_SDB_SEND_PTR_REG			0x75C
+#define ROCEE_CAEP_CQE_WCMD_EMPTY		0x850
+#define ROCEE_SCAEP_WR_CQE_CNT			0x8D0
 #define ROCEE_SDB_INV_CNT_REG			0x9A4
+#define ROCEE_SDB_RETRY_CNT_REG			0x9AC
+#define ROCEE_TSP_BP_ST_REG			0x9EC
 #define ROCEE_ECC_UCERR_ALM0_REG		0xB34
 #define ROCEE_ECC_CERR_ALM0_REG			0xB40
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_cq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_cq.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_cq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_cq.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include "hns_roce_device.h"
 #include "hns_roce_cmd.h"
 #include "hns_roce_hem.h"
-#include "hns_roce_user.h"
+#include <rdma/hns-abi.h>
 #include "hns_roce_common.h"
 
 static void hns_roce_ib_cq_comp(struct hns_roce_cq *hr_cq)
@@ -77,7 +77,7 @@ static int hns_roce_sw2hw_cq(struct hns_
 			     unsigned long cq_num)
 {
 	return hns_roce_cmd_mbox(dev, mailbox->dma, 0, cq_num, 0,
-			    HNS_ROCE_CMD_SW2HW_CQ, HNS_ROCE_CMD_TIME_CLASS_A);
+			    HNS_ROCE_CMD_SW2HW_CQ, HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
 static int hns_roce_cq_alloc(struct hns_roce_dev *hr_dev, int nent,
@@ -166,7 +166,7 @@ err_put:
 	hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn);
 
 err_out:
-	hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn);
+	hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn, BITMAP_NO_RR);
 	return ret;
 }
 
@@ -176,11 +176,10 @@ static int hns_roce_hw2sw_cq(struct hns_
 {
 	return hns_roce_cmd_mbox(dev, 0, mailbox ? mailbox->dma : 0, cq_num,
 				 mailbox ? 0 : 1, HNS_ROCE_CMD_HW2SW_CQ,
-				 HNS_ROCE_CMD_TIME_CLASS_A);
+				 HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
-static void hns_roce_free_cq(struct hns_roce_dev *hr_dev,
-			     struct hns_roce_cq *hr_cq)
+void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
 {
 	struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
 	struct device *dev = &hr_dev->pdev->dev;
@@ -204,7 +203,7 @@ static void hns_roce_free_cq(struct hns_
 	spin_unlock_irq(&cq_table->lock);
 
 	hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn);
-	hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn);
+	hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn, BITMAP_NO_RR);
 }
 
 static int hns_roce_ib_get_cq_umem(struct hns_roce_dev *hr_dev,
@@ -349,6 +348,15 @@ struct ib_cq *hns_roce_ib_create_cq(stru
 		goto err_mtt;
 	}
 
+	/*
+	 * For the QP created by kernel space, tptr value should be initialized
+	 * to zero; For the QP created by user space, it will cause synchronous
+	 * problems if tptr is set to zero here, so we initialze it in user
+	 * space.
+	 */
+	if (!context)
+		*hr_cq->tptr_addr = 0;
+
 	/* Get created cq handler and carry out event */
 	hr_cq->comp = hns_roce_ib_cq_comp;
 	hr_cq->event = hns_roce_ib_cq_event;
@@ -383,19 +391,25 @@ int hns_roce_ib_destroy_cq(struct ib_cq
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(ib_cq->device);
 	struct hns_roce_cq *hr_cq = to_hr_cq(ib_cq);
+	int ret = 0;
 
-	hns_roce_free_cq(hr_dev, hr_cq);
-	hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
+	if (hr_dev->hw->destroy_cq) {
+		ret = hr_dev->hw->destroy_cq(ib_cq);
+	} else {
+		hns_roce_free_cq(hr_dev, hr_cq);
+		hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
 
-	if (ib_cq->uobject)
-		ib_umem_release(hr_cq->umem);
-	else
-		/* Free the buff of stored cq */
-		hns_roce_ib_free_cq_buf(hr_dev, &hr_cq->hr_buf, ib_cq->cqe);
+		if (ib_cq->uobject)
+			ib_umem_release(hr_cq->umem);
+		else
+			/* Free the buff of stored cq */
+			hns_roce_ib_free_cq_buf(hr_dev, &hr_cq->hr_buf,
+						ib_cq->cqe);
 
-	kfree(hr_cq);
+		kfree(hr_cq);
+	}
 
-	return 0;
+	return ret;
 }
 
 void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_device.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_device.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_device.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_device.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,8 @@
 
 #define DRV_NAME "hns_roce"
 
+#define HNS_ROCE_HW_VER1	('h' << 24 | 'i' << 16 | '0' << 8 | '6')
+
 #define MAC_ADDR_OCTET_NUM			6
 #define HNS_ROCE_MAX_MSG_LEN			0x80000000
 
@@ -54,6 +56,12 @@
 #define HNS_ROCE_MAX_INNER_MTPT_NUM		0x7
 #define HNS_ROCE_MAX_MTPT_PBL_NUM		0x100000
 
+#define HNS_ROCE_EACH_FREE_CQ_WAIT_MSECS	20
+#define HNS_ROCE_MAX_FREE_CQ_WAIT_CNT	\
+	(5000 / HNS_ROCE_EACH_FREE_CQ_WAIT_MSECS)
+#define HNS_ROCE_CQE_WCMD_EMPTY_BIT		0x2
+#define HNS_ROCE_MIN_CQE_CNT			16
+
 #define HNS_ROCE_MAX_IRQ_NUM			34
 
 #define HNS_ROCE_COMP_VEC_NUM			32
@@ -70,6 +78,9 @@
 #define HNS_ROCE_MAX_GID_NUM			16
 #define HNS_ROCE_GID_SIZE			16
 
+#define BITMAP_NO_RR				0
+#define BITMAP_RR				1
+
 #define MR_TYPE_MR				0x00
 #define MR_TYPE_DMA				0x03
 
@@ -196,9 +207,9 @@ struct hns_roce_bitmap {
 /* Order = 0: bitmap is biggest, order = max bitmap is least (only a bit) */
 /* Every bit repesent to a partner free/used status in bitmap */
 /*
-* Initial, bits of other bitmap are all 0 except that a bit of max_order is 1
-* Bit = 1 represent to idle and available; bit = 0: not available
-*/
+ * Initial, bits of other bitmap are all 0 except that a bit of max_order is 1
+ * Bit = 1 represent to idle and available; bit = 0: not available
+ */
 struct hns_roce_buddy {
 	/* Members point to every order level bitmap */
 	unsigned long **bits;
@@ -296,7 +307,7 @@ struct hns_roce_cq {
 	u32				cq_depth;
 	u32				cons_index;
 	void __iomem			*cq_db_l;
-	void __iomem			*tptr_addr;
+	u16				*tptr_addr;
 	unsigned long			cqn;
 	u32				vector;
 	atomic_t			refcount;
@@ -360,29 +371,34 @@ struct hns_roce_cmdq {
 	struct mutex		hcr_mutex;
 	struct semaphore	poll_sem;
 	/*
-	* Event mode: cmd register mutex protection,
-	* ensure to not exceed max_cmds and user use limit region
-	*/
+	 * Event mode: cmd register mutex protection,
+	 * ensure to not exceed max_cmds and user use limit region
+	 */
 	struct semaphore	event_sem;
 	int			max_cmds;
 	spinlock_t		context_lock;
 	int			free_head;
 	struct hns_roce_cmd_context *context;
 	/*
-	* Result of get integer part
-	* which max_comds compute according a power of 2
-	*/
+	 * Result of get integer part
+	 * which max_comds compute according a power of 2
+	 */
 	u16			token_mask;
 	/*
-	* Process whether use event mode, init default non-zero
-	* After the event queue of cmd event ready,
-	* can switch into event mode
-	* close device, switch into poll mode(non event mode)
-	*/
+	 * Process whether use event mode, init default non-zero
+	 * After the event queue of cmd event ready,
+	 * can switch into event mode
+	 * close device, switch into poll mode(non event mode)
+	 */
 	u8			use_events;
 	u8			toggle;
 };
 
+struct hns_roce_cmd_mailbox {
+	void		       *buf;
+	dma_addr_t		dma;
+};
+
 struct hns_roce_dev;
 
 struct hns_roce_qp {
@@ -424,8 +440,6 @@ struct hns_roce_ib_iboe {
 	struct net_device      *netdevs[HNS_ROCE_MAX_PORTS];
 	struct notifier_block	nb;
 	struct notifier_block	nb_inet;
-	/* 16 GID is shared by 6 port in v1 engine. */
-	union ib_gid		gid_table[HNS_ROCE_MAX_GID_NUM];
 	u8			phy_port[HNS_ROCE_MAX_PORTS];
 };
 
@@ -519,6 +533,8 @@ struct hns_roce_hw {
 			 struct ib_recv_wr **bad_recv_wr);
 	int (*req_notify_cq)(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
 	int (*poll_cq)(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
+	int (*dereg_mr)(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr);
+	int (*destroy_cq)(struct ib_cq *ibcq);
 	void	*priv;
 };
 
@@ -553,6 +569,8 @@ struct hns_roce_dev {
 
 	int			cmd_mod;
 	int			loop_idc;
+	dma_addr_t		tptr_dma_addr; /*only for hw v1*/
+	u32			tptr_size; /*only for hw v1*/
 	struct hns_roce_hw	*hw;
 };
 
@@ -657,7 +675,8 @@ void hns_roce_cleanup_cq_table(struct hn
 void hns_roce_cleanup_qp_table(struct hns_roce_dev *hr_dev);
 
 int hns_roce_bitmap_alloc(struct hns_roce_bitmap *bitmap, unsigned long *obj);
-void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj);
+void hns_roce_bitmap_free(struct hns_roce_bitmap *bitmap, unsigned long obj,
+			 int rr);
 int hns_roce_bitmap_init(struct hns_roce_bitmap *bitmap, u32 num, u32 mask,
 			 u32 reserved_bot, u32 resetrved_top);
 void hns_roce_bitmap_cleanup(struct hns_roce_bitmap *bitmap);
@@ -665,9 +684,11 @@ void hns_roce_cleanup_bitmap(struct hns_
 int hns_roce_bitmap_alloc_range(struct hns_roce_bitmap *bitmap, int cnt,
 				int align, unsigned long *obj);
 void hns_roce_bitmap_free_range(struct hns_roce_bitmap *bitmap,
-				unsigned long obj, int cnt);
+				unsigned long obj, int cnt,
+				int rr);
 
-struct ib_ah *hns_roce_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
+struct ib_ah *hns_roce_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				 struct ib_udata *udata);
 int hns_roce_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr);
 int hns_roce_destroy_ah(struct ib_ah *ah);
 
@@ -681,6 +702,10 @@ struct ib_mr *hns_roce_reg_user_mr(struc
 				   u64 virt_addr, int access_flags,
 				   struct ib_udata *udata);
 int hns_roce_dereg_mr(struct ib_mr *ibmr);
+int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
+		       struct hns_roce_cmd_mailbox *mailbox,
+		       unsigned long mpt_index);
+unsigned long key_to_hw_index(u32 key);
 
 void hns_roce_buf_free(struct hns_roce_dev *hr_dev, u32 size,
 		       struct hns_roce_buf *buf);
@@ -717,6 +742,7 @@ struct ib_cq *hns_roce_ib_create_cq(stru
 				    struct ib_udata *udata);
 
 int hns_roce_ib_destroy_cq(struct ib_cq *ib_cq);
+void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq);
 
 void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn);
 void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_eq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_eq.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_eq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_eq.c	2017-02-12 16:03:20.000000000 -0500
@@ -371,9 +371,9 @@ static int hns_roce_aeq_ovf_int(struct h
 	int i = 0;
 
 	/**
-	* AEQ overflow ECC mult bit err CEQ overflow alarm
-	* must clear interrupt, mask irq, clear irq, cancel mask operation
-	*/
+	 * AEQ overflow ECC mult bit err CEQ overflow alarm
+	 * must clear interrupt, mask irq, clear irq, cancel mask operation
+	 */
 	aeshift_val = roce_read(hr_dev, ROCEE_CAEP_AEQC_AEQE_SHIFT_REG);
 
 	if (roce_get_bit(aeshift_val,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_hem.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_hem.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_hem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_hem.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,9 +80,9 @@ struct hns_roce_hem *hns_roce_alloc_hem(
 			--order;
 
 		/*
-		* Alloc memory one time. If failed, don't alloc small block
-		* memory, directly return fail.
-		*/
+		 * Alloc memory one time. If failed, don't alloc small block
+		 * memory, directly return fail.
+		 */
 		mem = &chunk->mem[chunk->npages];
 		buf = dma_alloc_coherent(&hr_dev->pdev->dev, PAGE_SIZE << order,
 				&sg_dma_address(mem), gfp_mask);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
+#include <linux/etherdevice.h>
 #include <rdma/ib_umem.h>
 #include "hns_roce_common.h"
 #include "hns_roce_device.h"
@@ -72,6 +73,8 @@ int hns_roce_v1_post_send(struct ib_qp *
 	int nreq = 0;
 	u32 ind = 0;
 	int ret = 0;
+	u8 *smac;
+	int loopback;
 
 	if (unlikely(ibqp->qp_type != IB_QPT_GSI &&
 		ibqp->qp_type != IB_QPT_RC)) {
@@ -129,6 +132,14 @@ int hns_roce_v1_post_send(struct ib_qp *
 				       UD_SEND_WQE_U32_8_DMAC_5_M,
 				       UD_SEND_WQE_U32_8_DMAC_5_S,
 				       ah->av.mac[5]);
+
+			smac = (u8 *)hr_dev->dev_addr[qp->port];
+			loopback = ether_addr_equal_unaligned(ah->av.mac,
+							      smac) ? 1 : 0;
+			roce_set_bit(ud_sq_wqe->u32_8,
+				     UD_SEND_WQE_U32_8_LOOPBACK_INDICATOR_S,
+				     loopback);
+
 			roce_set_field(ud_sq_wqe->u32_8,
 				       UD_SEND_WQE_U32_8_OPERATION_TYPE_M,
 				       UD_SEND_WQE_U32_8_OPERATION_TYPE_S,
@@ -284,6 +295,8 @@ out:
 		roce_set_field(sq_db.u32_4, SQ_DOORBELL_U32_4_SQ_HEAD_M,
 			       SQ_DOORBELL_U32_4_SQ_HEAD_S,
 			      (qp->sq.head & ((qp->sq.wqe_cnt << 1) - 1)));
+		roce_set_field(sq_db.u32_4, SQ_DOORBELL_U32_4_SL_M,
+			       SQ_DOORBELL_U32_4_SL_S, qp->sl);
 		roce_set_field(sq_db.u32_4, SQ_DOORBELL_U32_4_PORT_M,
 			       SQ_DOORBELL_U32_4_PORT_S, qp->phy_port);
 		roce_set_field(sq_db.u32_8, SQ_DOORBELL_U32_8_QPN_M,
@@ -611,6 +624,213 @@ ext_sdb_buf_fail_out:
 	return ret;
 }
 
+static struct hns_roce_qp *hns_roce_v1_create_lp_qp(struct hns_roce_dev *hr_dev,
+						    struct ib_pd *pd)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct ib_qp_init_attr init_attr;
+	struct ib_qp *qp;
+
+	memset(&init_attr, 0, sizeof(struct ib_qp_init_attr));
+	init_attr.qp_type		= IB_QPT_RC;
+	init_attr.sq_sig_type		= IB_SIGNAL_ALL_WR;
+	init_attr.cap.max_recv_wr	= HNS_ROCE_MIN_WQE_NUM;
+	init_attr.cap.max_send_wr	= HNS_ROCE_MIN_WQE_NUM;
+
+	qp = hns_roce_create_qp(pd, &init_attr, NULL);
+	if (IS_ERR(qp)) {
+		dev_err(dev, "Create loop qp for mr free failed!");
+		return NULL;
+	}
+
+	return to_hr_qp(qp);
+}
+
+static int hns_roce_v1_rsv_lp_qp(struct hns_roce_dev *hr_dev)
+{
+	struct hns_roce_caps *caps = &hr_dev->caps;
+	struct device *dev = &hr_dev->pdev->dev;
+	struct ib_cq_init_attr cq_init_attr;
+	struct hns_roce_free_mr *free_mr;
+	struct ib_qp_attr attr = { 0 };
+	struct hns_roce_v1_priv *priv;
+	struct hns_roce_qp *hr_qp;
+	struct ib_cq *cq;
+	struct ib_pd *pd;
+	u64 subnet_prefix;
+	int attr_mask = 0;
+	int i;
+	int ret;
+	u8 phy_port;
+	u8 sl;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	free_mr = &priv->free_mr;
+
+	/* Reserved cq for loop qp */
+	cq_init_attr.cqe		= HNS_ROCE_MIN_WQE_NUM * 2;
+	cq_init_attr.comp_vector	= 0;
+	cq = hns_roce_ib_create_cq(&hr_dev->ib_dev, &cq_init_attr, NULL, NULL);
+	if (IS_ERR(cq)) {
+		dev_err(dev, "Create cq for reseved loop qp failed!");
+		return -ENOMEM;
+	}
+	free_mr->mr_free_cq = to_hr_cq(cq);
+	free_mr->mr_free_cq->ib_cq.device		= &hr_dev->ib_dev;
+	free_mr->mr_free_cq->ib_cq.uobject		= NULL;
+	free_mr->mr_free_cq->ib_cq.comp_handler		= NULL;
+	free_mr->mr_free_cq->ib_cq.event_handler	= NULL;
+	free_mr->mr_free_cq->ib_cq.cq_context		= NULL;
+	atomic_set(&free_mr->mr_free_cq->ib_cq.usecnt, 0);
+
+	pd = hns_roce_alloc_pd(&hr_dev->ib_dev, NULL, NULL);
+	if (IS_ERR(pd)) {
+		dev_err(dev, "Create pd for reseved loop qp failed!");
+		ret = -ENOMEM;
+		goto alloc_pd_failed;
+	}
+	free_mr->mr_free_pd = to_hr_pd(pd);
+	free_mr->mr_free_pd->ibpd.device  = &hr_dev->ib_dev;
+	free_mr->mr_free_pd->ibpd.uobject = NULL;
+	atomic_set(&free_mr->mr_free_pd->ibpd.usecnt, 0);
+
+	attr.qp_access_flags	= IB_ACCESS_REMOTE_WRITE;
+	attr.pkey_index		= 0;
+	attr.min_rnr_timer	= 0;
+	/* Disable read ability */
+	attr.max_dest_rd_atomic = 0;
+	attr.max_rd_atomic	= 0;
+	/* Use arbitrary values as rq_psn and sq_psn */
+	attr.rq_psn		= 0x0808;
+	attr.sq_psn		= 0x0808;
+	attr.retry_cnt		= 7;
+	attr.rnr_retry		= 7;
+	attr.timeout		= 0x12;
+	attr.path_mtu		= IB_MTU_256;
+	attr.ah_attr.ah_flags		= 1;
+	attr.ah_attr.static_rate	= 3;
+	attr.ah_attr.grh.sgid_index	= 0;
+	attr.ah_attr.grh.hop_limit	= 1;
+	attr.ah_attr.grh.flow_label	= 0;
+	attr.ah_attr.grh.traffic_class	= 0;
+
+	subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
+	for (i = 0; i < HNS_ROCE_V1_RESV_QP; i++) {
+		free_mr->mr_free_qp[i] = hns_roce_v1_create_lp_qp(hr_dev, pd);
+		if (IS_ERR(free_mr->mr_free_qp[i])) {
+			dev_err(dev, "Create loop qp failed!\n");
+			goto create_lp_qp_failed;
+		}
+		hr_qp = free_mr->mr_free_qp[i];
+
+		sl = i / caps->num_ports;
+
+		if (caps->num_ports == HNS_ROCE_MAX_PORTS)
+			phy_port = (i >= HNS_ROCE_MAX_PORTS) ? (i - 2) :
+				(i % caps->num_ports);
+		else
+			phy_port = i % caps->num_ports;
+
+		hr_qp->port		= phy_port + 1;
+		hr_qp->phy_port		= phy_port;
+		hr_qp->ibqp.qp_type	= IB_QPT_RC;
+		hr_qp->ibqp.device	= &hr_dev->ib_dev;
+		hr_qp->ibqp.uobject	= NULL;
+		atomic_set(&hr_qp->ibqp.usecnt, 0);
+		hr_qp->ibqp.pd		= pd;
+		hr_qp->ibqp.recv_cq	= cq;
+		hr_qp->ibqp.send_cq	= cq;
+
+		attr.ah_attr.port_num	= phy_port + 1;
+		attr.ah_attr.sl		= sl;
+		attr.port_num		= phy_port + 1;
+
+		attr.dest_qp_num	= hr_qp->qpn;
+		memcpy(attr.ah_attr.dmac, hr_dev->dev_addr[phy_port],
+		       MAC_ADDR_OCTET_NUM);
+
+		memcpy(attr.ah_attr.grh.dgid.raw,
+			&subnet_prefix, sizeof(u64));
+		memcpy(&attr.ah_attr.grh.dgid.raw[8],
+		       hr_dev->dev_addr[phy_port], 3);
+		memcpy(&attr.ah_attr.grh.dgid.raw[13],
+		       hr_dev->dev_addr[phy_port] + 3, 3);
+		attr.ah_attr.grh.dgid.raw[11] = 0xff;
+		attr.ah_attr.grh.dgid.raw[12] = 0xfe;
+		attr.ah_attr.grh.dgid.raw[8] ^= 2;
+
+		attr_mask |= IB_QP_PORT;
+
+		ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, &attr, attr_mask,
+					    IB_QPS_RESET, IB_QPS_INIT);
+		if (ret) {
+			dev_err(dev, "modify qp failed(%d)!\n", ret);
+			goto create_lp_qp_failed;
+		}
+
+		ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, &attr, attr_mask,
+					    IB_QPS_INIT, IB_QPS_RTR);
+		if (ret) {
+			dev_err(dev, "modify qp failed(%d)!\n", ret);
+			goto create_lp_qp_failed;
+		}
+
+		ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, &attr, attr_mask,
+					    IB_QPS_RTR, IB_QPS_RTS);
+		if (ret) {
+			dev_err(dev, "modify qp failed(%d)!\n", ret);
+			goto create_lp_qp_failed;
+		}
+	}
+
+	return 0;
+
+create_lp_qp_failed:
+	for (i -= 1; i >= 0; i--) {
+		hr_qp = free_mr->mr_free_qp[i];
+		if (hns_roce_v1_destroy_qp(&hr_qp->ibqp))
+			dev_err(dev, "Destroy qp %d for mr free failed!\n", i);
+	}
+
+	if (hns_roce_dealloc_pd(pd))
+		dev_err(dev, "Destroy pd for create_lp_qp failed!\n");
+
+alloc_pd_failed:
+	if (hns_roce_ib_destroy_cq(cq))
+		dev_err(dev, "Destroy cq for create_lp_qp failed!\n");
+
+	return -EINVAL;
+}
+
+static void hns_roce_v1_release_lp_qp(struct hns_roce_dev *hr_dev)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_free_mr *free_mr;
+	struct hns_roce_v1_priv *priv;
+	struct hns_roce_qp *hr_qp;
+	int ret;
+	int i;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	free_mr = &priv->free_mr;
+
+	for (i = 0; i < HNS_ROCE_V1_RESV_QP; i++) {
+		hr_qp = free_mr->mr_free_qp[i];
+		ret = hns_roce_v1_destroy_qp(&hr_qp->ibqp);
+		if (ret)
+			dev_err(dev, "Destroy qp %d for mr free failed(%d)!\n",
+				i, ret);
+	}
+
+	ret = hns_roce_ib_destroy_cq(&free_mr->mr_free_cq->ib_cq);
+	if (ret)
+		dev_err(dev, "Destroy cq for mr_free failed(%d)!\n", ret);
+
+	ret = hns_roce_dealloc_pd(&free_mr->mr_free_pd->ibpd);
+	if (ret)
+		dev_err(dev, "Destroy pd for mr_free failed(%d)!\n", ret);
+}
+
 static int hns_roce_db_init(struct hns_roce_dev *hr_dev)
 {
 	struct device *dev = &hr_dev->pdev->dev;
@@ -648,6 +868,223 @@ static int hns_roce_db_init(struct hns_r
 	return 0;
 }
 
+void hns_roce_v1_recreate_lp_qp_work_fn(struct work_struct *work)
+{
+	struct hns_roce_recreate_lp_qp_work *lp_qp_work;
+	struct hns_roce_dev *hr_dev;
+
+	lp_qp_work = container_of(work, struct hns_roce_recreate_lp_qp_work,
+				  work);
+	hr_dev = to_hr_dev(lp_qp_work->ib_dev);
+
+	hns_roce_v1_release_lp_qp(hr_dev);
+
+	if (hns_roce_v1_rsv_lp_qp(hr_dev))
+		dev_err(&hr_dev->pdev->dev, "create reserver qp failed\n");
+
+	if (lp_qp_work->comp_flag)
+		complete(lp_qp_work->comp);
+
+	kfree(lp_qp_work);
+}
+
+static int hns_roce_v1_recreate_lp_qp(struct hns_roce_dev *hr_dev)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_recreate_lp_qp_work *lp_qp_work;
+	struct hns_roce_free_mr *free_mr;
+	struct hns_roce_v1_priv *priv;
+	struct completion comp;
+	unsigned long end =
+	  msecs_to_jiffies(HNS_ROCE_V1_RECREATE_LP_QP_TIMEOUT_MSECS) + jiffies;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	free_mr = &priv->free_mr;
+
+	lp_qp_work = kzalloc(sizeof(struct hns_roce_recreate_lp_qp_work),
+			     GFP_KERNEL);
+
+	INIT_WORK(&(lp_qp_work->work), hns_roce_v1_recreate_lp_qp_work_fn);
+
+	lp_qp_work->ib_dev = &(hr_dev->ib_dev);
+	lp_qp_work->comp = &comp;
+	lp_qp_work->comp_flag = 1;
+
+	init_completion(lp_qp_work->comp);
+
+	queue_work(free_mr->free_mr_wq, &(lp_qp_work->work));
+
+	while (time_before_eq(jiffies, end)) {
+		if (try_wait_for_completion(&comp))
+			return 0;
+		msleep(HNS_ROCE_V1_RECREATE_LP_QP_WAIT_VALUE);
+	}
+
+	lp_qp_work->comp_flag = 0;
+	if (try_wait_for_completion(&comp))
+		return 0;
+
+	dev_warn(dev, "recreate lp qp failed 20s timeout and return failed!\n");
+	return -ETIMEDOUT;
+}
+
+static int hns_roce_v1_send_lp_wqe(struct hns_roce_qp *hr_qp)
+{
+	struct hns_roce_dev *hr_dev = to_hr_dev(hr_qp->ibqp.device);
+	struct device *dev = &hr_dev->pdev->dev;
+	struct ib_send_wr send_wr, *bad_wr;
+	int ret;
+
+	memset(&send_wr, 0, sizeof(send_wr));
+	send_wr.next	= NULL;
+	send_wr.num_sge	= 0;
+	send_wr.send_flags = 0;
+	send_wr.sg_list	= NULL;
+	send_wr.wr_id	= (unsigned long long)&send_wr;
+	send_wr.opcode	= IB_WR_RDMA_WRITE;
+
+	ret = hns_roce_v1_post_send(&hr_qp->ibqp, &send_wr, &bad_wr);
+	if (ret) {
+		dev_err(dev, "Post write wqe for mr free failed(%d)!", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void hns_roce_v1_mr_free_work_fn(struct work_struct *work)
+{
+	struct hns_roce_mr_free_work *mr_work;
+	struct ib_wc wc[HNS_ROCE_V1_RESV_QP];
+	struct hns_roce_free_mr *free_mr;
+	struct hns_roce_cq *mr_free_cq;
+	struct hns_roce_v1_priv *priv;
+	struct hns_roce_dev *hr_dev;
+	struct hns_roce_mr *hr_mr;
+	struct hns_roce_qp *hr_qp;
+	struct device *dev;
+	unsigned long end =
+		msecs_to_jiffies(HNS_ROCE_V1_FREE_MR_TIMEOUT_MSECS) + jiffies;
+	int i;
+	int ret;
+	int ne;
+
+	mr_work = container_of(work, struct hns_roce_mr_free_work, work);
+	hr_mr = (struct hns_roce_mr *)mr_work->mr;
+	hr_dev = to_hr_dev(mr_work->ib_dev);
+	dev = &hr_dev->pdev->dev;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	free_mr = &priv->free_mr;
+	mr_free_cq = free_mr->mr_free_cq;
+
+	for (i = 0; i < HNS_ROCE_V1_RESV_QP; i++) {
+		hr_qp = free_mr->mr_free_qp[i];
+		ret = hns_roce_v1_send_lp_wqe(hr_qp);
+		if (ret) {
+			dev_err(dev,
+			     "Send wqe (qp:0x%lx) for mr free failed(%d)!\n",
+			     hr_qp->qpn, ret);
+			goto free_work;
+		}
+	}
+
+	ne = HNS_ROCE_V1_RESV_QP;
+	do {
+		ret = hns_roce_v1_poll_cq(&mr_free_cq->ib_cq, ne, wc);
+		if (ret < 0) {
+			dev_err(dev,
+			   "(qp:0x%lx) starts, Poll cqe failed(%d) for mr 0x%x free! Remain %d cqe\n",
+			   hr_qp->qpn, ret, hr_mr->key, ne);
+			goto free_work;
+		}
+		ne -= ret;
+		msleep(HNS_ROCE_V1_FREE_MR_WAIT_VALUE);
+	} while (ne && time_before_eq(jiffies, end));
+
+	if (ne != 0)
+		dev_err(dev,
+			"Poll cqe for mr 0x%x free timeout! Remain %d cqe\n",
+			hr_mr->key, ne);
+
+free_work:
+	if (mr_work->comp_flag)
+		complete(mr_work->comp);
+	kfree(mr_work);
+}
+
+int hns_roce_v1_dereg_mr(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_mr_free_work *mr_work;
+	struct hns_roce_free_mr *free_mr;
+	struct hns_roce_v1_priv *priv;
+	struct completion comp;
+	unsigned long end =
+		msecs_to_jiffies(HNS_ROCE_V1_FREE_MR_TIMEOUT_MSECS) + jiffies;
+	unsigned long start = jiffies;
+	int npages;
+	int ret = 0;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	free_mr = &priv->free_mr;
+
+	if (mr->enabled) {
+		if (hns_roce_hw2sw_mpt(hr_dev, NULL, key_to_hw_index(mr->key)
+				       & (hr_dev->caps.num_mtpts - 1)))
+			dev_warn(dev, "HW2SW_MPT failed!\n");
+	}
+
+	mr_work = kzalloc(sizeof(*mr_work), GFP_KERNEL);
+	if (!mr_work) {
+		ret = -ENOMEM;
+		goto free_mr;
+	}
+
+	INIT_WORK(&(mr_work->work), hns_roce_v1_mr_free_work_fn);
+
+	mr_work->ib_dev = &(hr_dev->ib_dev);
+	mr_work->comp = &comp;
+	mr_work->comp_flag = 1;
+	mr_work->mr = (void *)mr;
+	init_completion(mr_work->comp);
+
+	queue_work(free_mr->free_mr_wq, &(mr_work->work));
+
+	while (time_before_eq(jiffies, end)) {
+		if (try_wait_for_completion(&comp))
+			goto free_mr;
+		msleep(HNS_ROCE_V1_FREE_MR_WAIT_VALUE);
+	}
+
+	mr_work->comp_flag = 0;
+	if (try_wait_for_completion(&comp))
+		goto free_mr;
+
+	dev_warn(dev, "Free mr work 0x%x over 50s and failed!\n", mr->key);
+	ret = -ETIMEDOUT;
+
+free_mr:
+	dev_dbg(dev, "Free mr 0x%x use 0x%x us.\n",
+		mr->key, jiffies_to_usecs(jiffies) - jiffies_to_usecs(start));
+
+	if (mr->size != ~0ULL) {
+		npages = ib_umem_page_count(mr->umem);
+		dma_free_coherent(dev, npages * 8, mr->pbl_buf,
+				  mr->pbl_dma_addr);
+	}
+
+	hns_roce_bitmap_free(&hr_dev->mr_table.mtpt_bitmap,
+			     key_to_hw_index(mr->key), 0);
+
+	if (mr->umem)
+		ib_umem_release(mr->umem);
+
+	kfree(mr);
+
+	return ret;
+}
+
 static void hns_roce_db_free(struct hns_roce_dev *hr_dev)
 {
 	struct device *dev = &hr_dev->pdev->dev;
@@ -849,6 +1286,85 @@ static void hns_roce_bt_free(struct hns_
 		priv->bt_table.qpc_buf.buf, priv->bt_table.qpc_buf.map);
 }
 
+static int hns_roce_tptr_init(struct hns_roce_dev *hr_dev)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_buf_list *tptr_buf;
+	struct hns_roce_v1_priv *priv;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	tptr_buf = &priv->tptr_table.tptr_buf;
+
+	/*
+	 * This buffer will be used for CQ's tptr(tail pointer), also
+	 * named ci(customer index). Every CQ will use 2 bytes to save
+	 * cqe ci in hip06. Hardware will read this area to get new ci
+	 * when the queue is almost full.
+	 */
+	tptr_buf->buf = dma_alloc_coherent(dev, HNS_ROCE_V1_TPTR_BUF_SIZE,
+					   &tptr_buf->map, GFP_KERNEL);
+	if (!tptr_buf->buf)
+		return -ENOMEM;
+
+	hr_dev->tptr_dma_addr = tptr_buf->map;
+	hr_dev->tptr_size = HNS_ROCE_V1_TPTR_BUF_SIZE;
+
+	return 0;
+}
+
+static void hns_roce_tptr_free(struct hns_roce_dev *hr_dev)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_buf_list *tptr_buf;
+	struct hns_roce_v1_priv *priv;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	tptr_buf = &priv->tptr_table.tptr_buf;
+
+	dma_free_coherent(dev, HNS_ROCE_V1_TPTR_BUF_SIZE,
+			  tptr_buf->buf, tptr_buf->map);
+}
+
+static int hns_roce_free_mr_init(struct hns_roce_dev *hr_dev)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_free_mr *free_mr;
+	struct hns_roce_v1_priv *priv;
+	int ret = 0;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	free_mr = &priv->free_mr;
+
+	free_mr->free_mr_wq = create_singlethread_workqueue("hns_roce_free_mr");
+	if (!free_mr->free_mr_wq) {
+		dev_err(dev, "Create free mr workqueue failed!\n");
+		return -ENOMEM;
+	}
+
+	ret = hns_roce_v1_rsv_lp_qp(hr_dev);
+	if (ret) {
+		dev_err(dev, "Reserved loop qp failed(%d)!\n", ret);
+		flush_workqueue(free_mr->free_mr_wq);
+		destroy_workqueue(free_mr->free_mr_wq);
+	}
+
+	return ret;
+}
+
+static void hns_roce_free_mr_free(struct hns_roce_dev *hr_dev)
+{
+	struct hns_roce_free_mr *free_mr;
+	struct hns_roce_v1_priv *priv;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	free_mr = &priv->free_mr;
+
+	flush_workqueue(free_mr->free_mr_wq);
+	destroy_workqueue(free_mr->free_mr_wq);
+
+	hns_roce_v1_release_lp_qp(hr_dev);
+}
+
 /**
  * hns_roce_v1_reset - reset RoCE
  * @hr_dev: RoCE device struct pointer
@@ -898,6 +1414,38 @@ int hns_roce_v1_reset(struct hns_roce_de
 	return ret;
 }
 
+static int hns_roce_des_qp_init(struct hns_roce_dev *hr_dev)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_v1_priv *priv;
+	struct hns_roce_des_qp *des_qp;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	des_qp = &priv->des_qp;
+
+	des_qp->requeue_flag = 1;
+	des_qp->qp_wq = create_singlethread_workqueue("hns_roce_destroy_qp");
+	if (!des_qp->qp_wq) {
+		dev_err(dev, "Create destroy qp workqueue failed!\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void hns_roce_des_qp_free(struct hns_roce_dev *hr_dev)
+{
+	struct hns_roce_v1_priv *priv;
+	struct hns_roce_des_qp *des_qp;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	des_qp = &priv->des_qp;
+
+	des_qp->requeue_flag = 0;
+	flush_workqueue(des_qp->qp_wq);
+	destroy_workqueue(des_qp->qp_wq);
+}
+
 void hns_roce_v1_profile(struct hns_roce_dev *hr_dev)
 {
 	int i = 0;
@@ -906,12 +1454,11 @@ void hns_roce_v1_profile(struct hns_roce
 	hr_dev->vendor_id = le32_to_cpu(roce_read(hr_dev, ROCEE_VENDOR_ID_REG));
 	hr_dev->vendor_part_id = le32_to_cpu(roce_read(hr_dev,
 					     ROCEE_VENDOR_PART_ID_REG));
-	hr_dev->hw_rev = le32_to_cpu(roce_read(hr_dev, ROCEE_HW_VERSION_REG));
-
 	hr_dev->sys_image_guid = le32_to_cpu(roce_read(hr_dev,
 					     ROCEE_SYS_IMAGE_GUID_L_REG)) |
 				((u64)le32_to_cpu(roce_read(hr_dev,
 					    ROCEE_SYS_IMAGE_GUID_H_REG)) << 32);
+	hr_dev->hw_rev		= HNS_ROCE_HW_VER1;
 
 	caps->num_qps		= HNS_ROCE_V1_MAX_QP_NUM;
 	caps->max_wqes		= HNS_ROCE_V1_MAX_WQE_NUM;
@@ -1001,18 +1548,44 @@ int hns_roce_v1_init(struct hns_roce_dev
 		goto error_failed_raq_init;
 	}
 
-	hns_roce_port_enable(hr_dev, HNS_ROCE_PORT_UP);
-
 	ret = hns_roce_bt_init(hr_dev);
 	if (ret) {
 		dev_err(dev, "bt init failed!\n");
 		goto error_failed_bt_init;
 	}
 
+	ret = hns_roce_tptr_init(hr_dev);
+	if (ret) {
+		dev_err(dev, "tptr init failed!\n");
+		goto error_failed_tptr_init;
+	}
+
+	ret = hns_roce_des_qp_init(hr_dev);
+	if (ret) {
+		dev_err(dev, "des qp init failed!\n");
+		goto error_failed_des_qp_init;
+	}
+
+	ret = hns_roce_free_mr_init(hr_dev);
+	if (ret) {
+		dev_err(dev, "free mr init failed!\n");
+		goto error_failed_free_mr_init;
+	}
+
+	hns_roce_port_enable(hr_dev, HNS_ROCE_PORT_UP);
+
 	return 0;
 
+error_failed_free_mr_init:
+	hns_roce_des_qp_free(hr_dev);
+
+error_failed_des_qp_init:
+	hns_roce_tptr_free(hr_dev);
+
+error_failed_tptr_init:
+	hns_roce_bt_free(hr_dev);
+
 error_failed_bt_init:
-	hns_roce_port_enable(hr_dev, HNS_ROCE_PORT_DOWN);
 	hns_roce_raq_free(hr_dev);
 
 error_failed_raq_init:
@@ -1022,8 +1595,11 @@ error_failed_raq_init:
 
 void hns_roce_v1_exit(struct hns_roce_dev *hr_dev)
 {
-	hns_roce_bt_free(hr_dev);
 	hns_roce_port_enable(hr_dev, HNS_ROCE_PORT_DOWN);
+	hns_roce_free_mr_free(hr_dev);
+	hns_roce_des_qp_free(hr_dev);
+	hns_roce_tptr_free(hr_dev);
+	hns_roce_bt_free(hr_dev);
 	hns_roce_raq_free(hr_dev);
 	hns_roce_db_free(hr_dev);
 }
@@ -1061,6 +1637,14 @@ void hns_roce_v1_set_mac(struct hns_roce
 	u32 *p;
 	u32 val;
 
+	/*
+	 * When mac changed, loopback may fail
+	 * because of smac not equal to dmac.
+	 * We Need to release and create reserved qp again.
+	 */
+	if (hr_dev->hw->dereg_mr && hns_roce_v1_recreate_lp_qp(hr_dev))
+		dev_warn(&hr_dev->pdev->dev, "recreate lp qp timeout!\n");
+
 	p = (u32 *)(&addr[0]);
 	reg_smac_l = *p;
 	roce_raw_write(reg_smac_l, hr_dev->reg_base + ROCEE_SMAC_L_0_REG +
@@ -1293,9 +1877,9 @@ static void __hns_roce_v1_cq_clean(struc
 	}
 
 	/*
-	* Now backwards through the CQ, removing CQ entries
-	* that match our QP by overwriting them with next entries.
-	*/
+	 * Now backwards through the CQ, removing CQ entries
+	 * that match our QP by overwriting them with next entries.
+	 */
 	while ((int) --prod_index - (int) hr_cq->cons_index >= 0) {
 		cqe = get_cqe(hr_cq, prod_index & hr_cq->ib_cq.cqe);
 		if ((roce_get_field(cqe->cqe_byte_16, CQE_BYTE_16_LOCAL_QPN_M,
@@ -1317,9 +1901,9 @@ static void __hns_roce_v1_cq_clean(struc
 	if (nfreed) {
 		hr_cq->cons_index += nfreed;
 		/*
-		* Make sure update of buffer contents is done before
-		* updating consumer index.
-		*/
+		 * Make sure update of buffer contents is done before
+		 * updating consumer index.
+		 */
 		wmb();
 
 		hns_roce_v1_cq_set_ci(hr_cq, hr_cq->cons_index);
@@ -1339,14 +1923,21 @@ void hns_roce_v1_write_cqc(struct hns_ro
 			   dma_addr_t dma_handle, int nent, u32 vector)
 {
 	struct hns_roce_cq_context *cq_context = NULL;
-	void __iomem *tptr_addr;
+	struct hns_roce_buf_list *tptr_buf;
+	struct hns_roce_v1_priv *priv;
+	dma_addr_t tptr_dma_addr;
+	int offset;
+
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	tptr_buf = &priv->tptr_table.tptr_buf;
 
 	cq_context = mb_buf;
 	memset(cq_context, 0, sizeof(*cq_context));
 
-	tptr_addr = 0;
-	hr_dev->priv_addr = tptr_addr;
-	hr_cq->tptr_addr = tptr_addr;
+	/* Get the tptr for this CQ. */
+	offset = hr_cq->cqn * HNS_ROCE_V1_TPTR_ENTRY_SIZE;
+	tptr_dma_addr = tptr_buf->map + offset;
+	hr_cq->tptr_addr = (u16 *)(tptr_buf->buf + offset);
 
 	/* Register cq_context members */
 	roce_set_field(cq_context->cqc_byte_4,
@@ -1390,10 +1981,10 @@ void hns_roce_v1_write_cqc(struct hns_ro
 	roce_set_field(cq_context->cqc_byte_20,
 		       CQ_CONTEXT_CQC_BYTE_20_CQE_TPTR_ADDR_H_M,
 		       CQ_CONTEXT_CQC_BYTE_20_CQE_TPTR_ADDR_H_S,
-		       (u64)tptr_addr >> 44);
+		       tptr_dma_addr >> 44);
 	cq_context->cqc_byte_20 = cpu_to_le32(cq_context->cqc_byte_20);
 
-	cq_context->cqe_tptr_addr_l = (u32)((u64)tptr_addr >> 12);
+	cq_context->cqe_tptr_addr_l = (u32)(tptr_dma_addr >> 12);
 
 	roce_set_field(cq_context->cqc_byte_32,
 		       CQ_CONTEXT_CQC_BYTE_32_CUR_CQE_BA1_H_M,
@@ -1407,7 +1998,7 @@ void hns_roce_v1_write_cqc(struct hns_ro
 	roce_set_bit(cq_context->cqc_byte_32,
 		     CQ_CQNTEXT_CQC_BYTE_32_TYPE_OF_COMPLETION_NOTIFICATION_S,
 		     0);
-	/*The initial value of cq's ci is 0 */
+	/* The initial value of cq's ci is 0 */
 	roce_set_field(cq_context->cqc_byte_32,
 		       CQ_CONTEXT_CQC_BYTE_32_CQ_CONS_IDX_M,
 		       CQ_CONTEXT_CQC_BYTE_32_CQ_CONS_IDX_S, 0);
@@ -1424,9 +2015,9 @@ int hns_roce_v1_req_notify_cq(struct ib_
 	notification_flag = (flags & IB_CQ_SOLICITED_MASK) ==
 			    IB_CQ_SOLICITED ? CQ_DB_REQ_NOT : CQ_DB_REQ_NOT_SOL;
 	/*
-	* flags = 0; Notification Flag = 1, next
-	* flags = 1; Notification Flag = 0, solocited
-	*/
+	 * flags = 0; Notification Flag = 1, next
+	 * flags = 1; Notification Flag = 0, solocited
+	 */
 	doorbell[0] = hr_cq->cons_index & ((hr_cq->cq_depth << 1) - 1);
 	roce_set_bit(doorbell[1], ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_HW_SYNS_S, 1);
 	roce_set_field(doorbell[1], ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_M,
@@ -1581,10 +2172,10 @@ static int hns_roce_v1_poll_one(struct h
 		wq = &(*cur_qp)->sq;
 		if ((*cur_qp)->sq_signal_bits) {
 			/*
-			* If sg_signal_bit is 1,
-			* firstly tail pointer updated to wqe
-			* which current cqe correspond to
-			*/
+			 * If sg_signal_bit is 1,
+			 * firstly tail pointer updated to wqe
+			 * which current cqe correspond to
+			 */
 			wqe_ctr = (u16)roce_get_field(cqe->cqe_byte_4,
 						      CQE_BYTE_4_WQE_INDEX_M,
 						      CQE_BYTE_4_WQE_INDEX_S);
@@ -1659,8 +2250,14 @@ int hns_roce_v1_poll_cq(struct ib_cq *ib
 			break;
 	}
 
-	if (npolled)
+	if (npolled) {
+		*hr_cq->tptr_addr = hr_cq->cons_index &
+			((hr_cq->cq_depth << 1) - 1);
+
+		/* Memroy barrier */
+		wmb();
 		hns_roce_v1_cq_set_ci(hr_cq, hr_cq->cons_index);
+	}
 
 	spin_unlock_irqrestore(&hr_cq->lock, flags);
 
@@ -1799,12 +2396,12 @@ static int hns_roce_v1_qp_modify(struct
 	if (op[cur_state][new_state] == HNS_ROCE_CMD_2RST_QP)
 		return hns_roce_cmd_mbox(hr_dev, 0, 0, hr_qp->qpn, 2,
 					 HNS_ROCE_CMD_2RST_QP,
-					 HNS_ROCE_CMD_TIME_CLASS_A);
+					 HNS_ROCE_CMD_TIMEOUT_MSECS);
 
 	if (op[cur_state][new_state] == HNS_ROCE_CMD_2ERR_QP)
 		return hns_roce_cmd_mbox(hr_dev, 0, 0, hr_qp->qpn, 2,
 					 HNS_ROCE_CMD_2ERR_QP,
-					 HNS_ROCE_CMD_TIME_CLASS_A);
+					 HNS_ROCE_CMD_TIMEOUT_MSECS);
 
 	mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
 	if (IS_ERR(mailbox))
@@ -1814,7 +2411,7 @@ static int hns_roce_v1_qp_modify(struct
 
 	ret = hns_roce_cmd_mbox(hr_dev, mailbox->dma, 0, hr_qp->qpn, 0,
 				op[cur_state][new_state],
-				HNS_ROCE_CMD_TIME_CLASS_C);
+				HNS_ROCE_CMD_TIMEOUT_MSECS);
 
 	hns_roce_free_cmd_mailbox(hr_dev, mailbox);
 	return ret;
@@ -2000,11 +2597,11 @@ static int hns_roce_v1_m_qp(struct ib_qp
 	}
 
 	/*
-	*Reset to init
-	*	Mandatory param:
-	*	IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT | IB_QP_ACCESS_FLAGS
-	*	Optional param: NA
-	*/
+	 * Reset to init
+	 *	Mandatory param:
+	 *	IB_QP_STATE | IB_QP_PKEY_INDEX | IB_QP_PORT | IB_QP_ACCESS_FLAGS
+	 *	Optional param: NA
+	 */
 	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
 		roce_set_field(context->qpc_bytes_4,
 			       QP_CONTEXT_QPC_BYTES_4_TRANSPORT_SERVICE_TYPE_M,
@@ -2172,24 +2769,14 @@ static int hns_roce_v1_m_qp(struct ib_qp
 			     QP_CONTEXT_QPC_BYTE_32_SIGNALING_TYPE_S,
 			     hr_qp->sq_signal_bits);
 
-		for (port = 0; port < hr_dev->caps.num_ports; port++) {
-			smac = (u8 *)hr_dev->dev_addr[port];
-			dev_dbg(dev, "smac: %2x: %2x: %2x: %2x: %2x: %2x\n",
-				smac[0], smac[1], smac[2], smac[3], smac[4],
-				smac[5]);
-			if ((dmac[0] == smac[0]) && (dmac[1] == smac[1]) &&
-			    (dmac[2] == smac[2]) && (dmac[3] == smac[3]) &&
-			    (dmac[4] == smac[4]) && (dmac[5] == smac[5])) {
-				roce_set_bit(context->qpc_bytes_32,
-				    QP_CONTEXT_QPC_BYTE_32_LOOPBACK_INDICATOR_S,
-				    1);
-				break;
-			}
-		}
-
-		if (hr_dev->loop_idc == 0x1)
+		port = (attr_mask & IB_QP_PORT) ? (attr->port_num - 1) :
+			hr_qp->port;
+		smac = (u8 *)hr_dev->dev_addr[port];
+		/* when dmac equals smac or loop_idc is 1, it should loopback */
+		if (ether_addr_equal_unaligned(dmac, smac) ||
+		    hr_dev->loop_idc == 0x1)
 			roce_set_bit(context->qpc_bytes_32,
-				QP_CONTEXT_QPC_BYTE_32_LOOPBACK_INDICATOR_S, 1);
+			      QP_CONTEXT_QPC_BYTE_32_LOOPBACK_INDICATOR_S, 1);
 
 		roce_set_bit(context->qpc_bytes_32,
 			     QP_CONTEXT_QPC_BYTE_32_GLOBAL_HEADER_S,
@@ -2509,7 +3096,7 @@ static int hns_roce_v1_m_qp(struct ib_qp
 	/* Every status migrate must change state */
 	roce_set_field(context->qpc_bytes_144,
 		       QP_CONTEXT_QPC_BYTES_144_QP_STATE_M,
-		       QP_CONTEXT_QPC_BYTES_144_QP_STATE_S, attr->qp_state);
+		       QP_CONTEXT_QPC_BYTES_144_QP_STATE_S, new_state);
 
 	/* SW pass context to HW */
 	ret = hns_roce_v1_qp_modify(hr_dev, &hr_qp->mtt,
@@ -2522,9 +3109,9 @@ static int hns_roce_v1_m_qp(struct ib_qp
 	}
 
 	/*
-	* Use rst2init to instead of init2init with drv,
-	* need to hw to flash RQ HEAD by DB again
-	*/
+	 * Use rst2init to instead of init2init with drv,
+	 * need to hw to flash RQ HEAD by DB again
+	 */
 	if (cur_state == IB_QPS_INIT && new_state == IB_QPS_INIT) {
 		/* Memory barrier */
 		wmb();
@@ -2619,7 +3206,7 @@ static int hns_roce_v1_query_qpc(struct
 
 	ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, hr_qp->qpn, 0,
 				HNS_ROCE_CMD_QUERY_QP,
-				HNS_ROCE_CMD_TIME_CLASS_A);
+				HNS_ROCE_CMD_TIMEOUT_MSECS);
 	if (!ret)
 		memcpy(hr_context, mailbox->buf, sizeof(*hr_context));
 	else
@@ -2630,8 +3217,78 @@ static int hns_roce_v1_query_qpc(struct
 	return ret;
 }
 
-int hns_roce_v1_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
-			 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
+static int hns_roce_v1_q_sqp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
+			     int qp_attr_mask,
+			     struct ib_qp_init_attr *qp_init_attr)
+{
+	struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
+	struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+	struct hns_roce_sqp_context context;
+	u32 addr;
+
+	mutex_lock(&hr_qp->mutex);
+
+	if (hr_qp->state == IB_QPS_RESET) {
+		qp_attr->qp_state = IB_QPS_RESET;
+		goto done;
+	}
+
+	addr = ROCEE_QP1C_CFG0_0_REG +
+		hr_qp->port * sizeof(struct hns_roce_sqp_context);
+	context.qp1c_bytes_4 = roce_read(hr_dev, addr);
+	context.sq_rq_bt_l = roce_read(hr_dev, addr + 1);
+	context.qp1c_bytes_12 = roce_read(hr_dev, addr + 2);
+	context.qp1c_bytes_16 = roce_read(hr_dev, addr + 3);
+	context.qp1c_bytes_20 = roce_read(hr_dev, addr + 4);
+	context.cur_rq_wqe_ba_l = roce_read(hr_dev, addr + 5);
+	context.qp1c_bytes_28 = roce_read(hr_dev, addr + 6);
+	context.qp1c_bytes_32 = roce_read(hr_dev, addr + 7);
+	context.cur_sq_wqe_ba_l = roce_read(hr_dev, addr + 8);
+	context.qp1c_bytes_40 = roce_read(hr_dev, addr + 9);
+
+	hr_qp->state = roce_get_field(context.qp1c_bytes_4,
+				      QP1C_BYTES_4_QP_STATE_M,
+				      QP1C_BYTES_4_QP_STATE_S);
+	qp_attr->qp_state	= hr_qp->state;
+	qp_attr->path_mtu	= IB_MTU_256;
+	qp_attr->path_mig_state	= IB_MIG_ARMED;
+	qp_attr->qkey		= QKEY_VAL;
+	qp_attr->rq_psn		= 0;
+	qp_attr->sq_psn		= 0;
+	qp_attr->dest_qp_num	= 1;
+	qp_attr->qp_access_flags = 6;
+
+	qp_attr->pkey_index = roce_get_field(context.qp1c_bytes_20,
+					     QP1C_BYTES_20_PKEY_IDX_M,
+					     QP1C_BYTES_20_PKEY_IDX_S);
+	qp_attr->port_num = hr_qp->port + 1;
+	qp_attr->sq_draining = 0;
+	qp_attr->max_rd_atomic = 0;
+	qp_attr->max_dest_rd_atomic = 0;
+	qp_attr->min_rnr_timer = 0;
+	qp_attr->timeout = 0;
+	qp_attr->retry_cnt = 0;
+	qp_attr->rnr_retry = 0;
+	qp_attr->alt_timeout = 0;
+
+done:
+	qp_attr->cur_qp_state = qp_attr->qp_state;
+	qp_attr->cap.max_recv_wr = hr_qp->rq.wqe_cnt;
+	qp_attr->cap.max_recv_sge = hr_qp->rq.max_gs;
+	qp_attr->cap.max_send_wr = hr_qp->sq.wqe_cnt;
+	qp_attr->cap.max_send_sge = hr_qp->sq.max_gs;
+	qp_attr->cap.max_inline_data = 0;
+	qp_init_attr->cap = qp_attr->cap;
+	qp_init_attr->create_flags = 0;
+
+	mutex_unlock(&hr_qp->mutex);
+
+	return 0;
+}
+
+static int hns_roce_v1_q_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
+			    int qp_attr_mask,
+			    struct ib_qp_init_attr *qp_init_attr)
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
 	struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
@@ -2725,9 +3382,7 @@ int hns_roce_v1_query_qp(struct ib_qp *i
 	qp_attr->pkey_index = roce_get_field(context->qpc_bytes_12,
 			      QP_CONTEXT_QPC_BYTES_12_P_KEY_INDEX_M,
 			      QP_CONTEXT_QPC_BYTES_12_P_KEY_INDEX_S);
-	qp_attr->port_num = (u8)roce_get_field(context->qpc_bytes_156,
-			     QP_CONTEXT_QPC_BYTES_156_PORT_NUM_M,
-			     QP_CONTEXT_QPC_BYTES_156_PORT_NUM_S) + 1;
+	qp_attr->port_num = hr_qp->port + 1;
 	qp_attr->sq_draining = 0;
 	qp_attr->max_rd_atomic = roce_get_field(context->qpc_bytes_156,
 				 QP_CONTEXT_QPC_BYTES_156_INITIATOR_DEPTH_M,
@@ -2767,134 +3422,397 @@ out:
 	return ret;
 }
 
-static void hns_roce_v1_destroy_qp_common(struct hns_roce_dev *hr_dev,
-					  struct hns_roce_qp *hr_qp,
-					  int is_user)
+int hns_roce_v1_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
+			 int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
+{
+	struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+
+	return hr_qp->doorbell_qpn <= 1 ?
+		hns_roce_v1_q_sqp(ibqp, qp_attr, qp_attr_mask, qp_init_attr) :
+		hns_roce_v1_q_qp(ibqp, qp_attr, qp_attr_mask, qp_init_attr);
+}
+
+static int check_qp_db_process_status(struct hns_roce_dev *hr_dev,
+				      struct hns_roce_qp *hr_qp,
+				      u32 sdb_issue_ptr,
+				      u32 *sdb_inv_cnt,
+				      u32 *wait_stage)
 {
-	u32 sdbinvcnt;
-	unsigned long end = 0;
-	u32 sdbinvcnt_val;
-	u32 sdbsendptr_val;
-	u32 sdbisusepr_val;
-	struct hns_roce_cq *send_cq, *recv_cq;
 	struct device *dev = &hr_dev->pdev->dev;
+	u32 sdb_retry_cnt, old_retry;
+	u32 sdb_send_ptr, old_send;
+	u32 success_flags = 0;
+	u32 cur_cnt, old_cnt;
+	unsigned long end;
+	u32 send_ptr;
+	u32 inv_cnt;
+	u32 tsp_st;
 
-	if (hr_qp->ibqp.qp_type == IB_QPT_RC) {
-		if (hr_qp->state != IB_QPS_RESET) {
-			/*
-			* Set qp to ERR,
-			* waiting for hw complete processing all dbs
-			*/
-			if (hns_roce_v1_qp_modify(hr_dev, NULL,
-					to_hns_roce_state(
-						(enum ib_qp_state)hr_qp->state),
-						HNS_ROCE_QP_STATE_ERR, NULL,
-						hr_qp))
-				dev_err(dev, "modify QP %06lx to ERR failed.\n",
-					hr_qp->qpn);
+	if (*wait_stage > HNS_ROCE_V1_DB_STAGE2 ||
+	    *wait_stage < HNS_ROCE_V1_DB_STAGE1) {
+		dev_err(dev, "QP(0x%lx) db status wait stage(%d) error!\n",
+			hr_qp->qpn, *wait_stage);
+		return -EINVAL;
+	}
 
-			/* Record issued doorbell */
-			sdbisusepr_val = roce_read(hr_dev,
-					 ROCEE_SDB_ISSUE_PTR_REG);
-			/*
-			* Query db process status,
-			* until hw process completely
-			*/
-			end = msecs_to_jiffies(
-			      HNS_ROCE_QP_DESTROY_TIMEOUT_MSECS) + jiffies;
-			do {
-				sdbsendptr_val = roce_read(hr_dev,
+	/* Calculate the total timeout for the entire verification process */
+	end = msecs_to_jiffies(HNS_ROCE_V1_CHECK_DB_TIMEOUT_MSECS) + jiffies;
+
+	if (*wait_stage == HNS_ROCE_V1_DB_STAGE1) {
+		/* Query db process status, until hw process completely */
+		sdb_send_ptr = roce_read(hr_dev, ROCEE_SDB_SEND_PTR_REG);
+		while (roce_hw_index_cmp_lt(sdb_send_ptr, sdb_issue_ptr,
+					    ROCEE_SDB_PTR_CMP_BITS)) {
+			if (!time_before(jiffies, end)) {
+				dev_dbg(dev, "QP(0x%lx) db process stage1 timeout. issue 0x%x send 0x%x.\n",
+					hr_qp->qpn, sdb_issue_ptr,
+					sdb_send_ptr);
+				return 0;
+			}
+
+			msleep(HNS_ROCE_V1_CHECK_DB_SLEEP_MSECS);
+			sdb_send_ptr = roce_read(hr_dev,
 						 ROCEE_SDB_SEND_PTR_REG);
-				if (!time_before(jiffies, end)) {
-					dev_err(dev, "destroy qp(0x%lx) timeout!!!",
-						hr_qp->qpn);
-					break;
-				}
-			} while ((short)(roce_get_field(sdbsendptr_val,
-					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
-					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) -
-				roce_get_field(sdbisusepr_val,
-					ROCEE_SDB_ISSUE_PTR_SDB_ISSUE_PTR_M,
-					ROCEE_SDB_ISSUE_PTR_SDB_ISSUE_PTR_S)
-				) < 0);
+		}
 
-			/* Get list pointer */
-			sdbinvcnt = roce_read(hr_dev, ROCEE_SDB_INV_CNT_REG);
+		if (roce_get_field(sdb_issue_ptr,
+				   ROCEE_SDB_ISSUE_PTR_SDB_ISSUE_PTR_M,
+				   ROCEE_SDB_ISSUE_PTR_SDB_ISSUE_PTR_S) ==
+		    roce_get_field(sdb_send_ptr,
+				   ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
+				   ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S)) {
+			old_send = roce_read(hr_dev, ROCEE_SDB_SEND_PTR_REG);
+			old_retry = roce_read(hr_dev, ROCEE_SDB_RETRY_CNT_REG);
 
-			/* Query db's list status, until hw reversal */
 			do {
-				sdbinvcnt_val = roce_read(hr_dev,
-						ROCEE_SDB_INV_CNT_REG);
+				tsp_st = roce_read(hr_dev, ROCEE_TSP_BP_ST_REG);
+				if (roce_get_bit(tsp_st,
+					ROCEE_TSP_BP_ST_QH_FIFO_ENTRY_S) == 1) {
+					*wait_stage = HNS_ROCE_V1_DB_WAIT_OK;
+					return 0;
+				}
+
 				if (!time_before(jiffies, end)) {
-					dev_err(dev, "destroy qp(0x%lx) timeout!!!",
-						hr_qp->qpn);
-					dev_err(dev, "SdbInvCnt = 0x%x\n",
-						sdbinvcnt_val);
-					break;
+					dev_dbg(dev, "QP(0x%lx) db process stage1 timeout when send ptr equals issue ptr.\n"
+						     "issue 0x%x send 0x%x.\n",
+						hr_qp->qpn, sdb_issue_ptr,
+						sdb_send_ptr);
+					return 0;
 				}
-			} while ((short)(roce_get_field(sdbinvcnt_val,
-				  ROCEE_SDB_INV_CNT_SDB_INV_CNT_M,
-				  ROCEE_SDB_INV_CNT_SDB_INV_CNT_S) -
-				  (sdbinvcnt + SDB_INV_CNT_OFFSET)) < 0);
 
-			/* Modify qp to reset before destroying qp */
-			if (hns_roce_v1_qp_modify(hr_dev, NULL,
-					to_hns_roce_state(
-					(enum ib_qp_state)hr_qp->state),
-					HNS_ROCE_QP_STATE_RST, NULL, hr_qp))
-				dev_err(dev, "modify QP %06lx to RESET failed.\n",
-					hr_qp->qpn);
+				msleep(HNS_ROCE_V1_CHECK_DB_SLEEP_MSECS);
+
+				sdb_send_ptr = roce_read(hr_dev,
+							ROCEE_SDB_SEND_PTR_REG);
+				sdb_retry_cnt =	roce_read(hr_dev,
+						       ROCEE_SDB_RETRY_CNT_REG);
+				cur_cnt = roce_get_field(sdb_send_ptr,
+					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
+					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
+					roce_get_field(sdb_retry_cnt,
+					ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
+					ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
+				if (!roce_get_bit(tsp_st,
+					ROCEE_CNT_CLR_CE_CNT_CLR_CE_S)) {
+					old_cnt = roce_get_field(old_send,
+					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
+					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
+					roce_get_field(old_retry,
+					ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
+					ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
+					if (cur_cnt - old_cnt > SDB_ST_CMP_VAL)
+						success_flags = 1;
+				} else {
+					old_cnt = roce_get_field(old_send,
+					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
+					ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S);
+					if (cur_cnt - old_cnt > SDB_ST_CMP_VAL)
+						success_flags = 1;
+					else {
+					    send_ptr = roce_get_field(old_send,
+					    ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
+					    ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S) +
+					    roce_get_field(sdb_retry_cnt,
+					    ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_M,
+					    ROCEE_SDB_RETRY_CNT_SDB_RETRY_CT_S);
+					    roce_set_field(old_send,
+					    ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_M,
+					    ROCEE_SDB_SEND_PTR_SDB_SEND_PTR_S,
+						send_ptr);
+					}
+				}
+			} while (!success_flags);
+		}
+
+		*wait_stage = HNS_ROCE_V1_DB_STAGE2;
+
+		/* Get list pointer */
+		*sdb_inv_cnt = roce_read(hr_dev, ROCEE_SDB_INV_CNT_REG);
+		dev_dbg(dev, "QP(0x%lx) db process stage2. inv cnt = 0x%x.\n",
+			hr_qp->qpn, *sdb_inv_cnt);
+	}
+
+	if (*wait_stage == HNS_ROCE_V1_DB_STAGE2) {
+		/* Query db's list status, until hw reversal */
+		inv_cnt = roce_read(hr_dev, ROCEE_SDB_INV_CNT_REG);
+		while (roce_hw_index_cmp_lt(inv_cnt,
+					    *sdb_inv_cnt + SDB_INV_CNT_OFFSET,
+					    ROCEE_SDB_CNT_CMP_BITS)) {
+			if (!time_before(jiffies, end)) {
+				dev_dbg(dev, "QP(0x%lx) db process stage2 timeout. inv cnt 0x%x.\n",
+					hr_qp->qpn, inv_cnt);
+				return 0;
+			}
+
+			msleep(HNS_ROCE_V1_CHECK_DB_SLEEP_MSECS);
+			inv_cnt = roce_read(hr_dev, ROCEE_SDB_INV_CNT_REG);
+		}
+
+		*wait_stage = HNS_ROCE_V1_DB_WAIT_OK;
+	}
+
+	return 0;
+}
+
+static int check_qp_reset_state(struct hns_roce_dev *hr_dev,
+				struct hns_roce_qp *hr_qp,
+				struct hns_roce_qp_work *qp_work_entry,
+				int *is_timeout)
+{
+	struct device *dev = &hr_dev->pdev->dev;
+	u32 sdb_issue_ptr;
+	int ret;
+
+	if (hr_qp->state != IB_QPS_RESET) {
+		/* Set qp to ERR, waiting for hw complete processing all dbs */
+		ret = hns_roce_v1_modify_qp(&hr_qp->ibqp, NULL, 0, hr_qp->state,
+					    IB_QPS_ERR);
+		if (ret) {
+			dev_err(dev, "Modify QP(0x%lx) to ERR failed!\n",
+				hr_qp->qpn);
+			return ret;
+		}
+
+		/* Record issued doorbell */
+		sdb_issue_ptr = roce_read(hr_dev, ROCEE_SDB_ISSUE_PTR_REG);
+		qp_work_entry->sdb_issue_ptr = sdb_issue_ptr;
+		qp_work_entry->db_wait_stage = HNS_ROCE_V1_DB_STAGE1;
+
+		/* Query db process status, until hw process completely */
+		ret = check_qp_db_process_status(hr_dev, hr_qp, sdb_issue_ptr,
+						 &qp_work_entry->sdb_inv_cnt,
+						 &qp_work_entry->db_wait_stage);
+		if (ret) {
+			dev_err(dev, "Check QP(0x%lx) db process status failed!\n",
+				hr_qp->qpn);
+			return ret;
+		}
+
+		if (qp_work_entry->db_wait_stage != HNS_ROCE_V1_DB_WAIT_OK) {
+			qp_work_entry->sche_cnt = 0;
+			*is_timeout = 1;
+			return 0;
+		}
+
+		/* Modify qp to reset before destroying qp */
+		ret = hns_roce_v1_modify_qp(&hr_qp->ibqp, NULL, 0, hr_qp->state,
+					    IB_QPS_RESET);
+		if (ret) {
+			dev_err(dev, "Modify QP(0x%lx) to RST failed!\n",
+				hr_qp->qpn);
+			return ret;
 		}
 	}
 
+	return 0;
+}
+
+static void hns_roce_v1_destroy_qp_work_fn(struct work_struct *work)
+{
+	struct hns_roce_qp_work *qp_work_entry;
+	struct hns_roce_v1_priv *priv;
+	struct hns_roce_dev *hr_dev;
+	struct hns_roce_qp *hr_qp;
+	struct device *dev;
+	int ret;
+
+	qp_work_entry = container_of(work, struct hns_roce_qp_work, work);
+	hr_dev = to_hr_dev(qp_work_entry->ib_dev);
+	dev = &hr_dev->pdev->dev;
+	priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+	hr_qp = qp_work_entry->qp;
+
+	dev_dbg(dev, "Schedule destroy QP(0x%lx) work.\n", hr_qp->qpn);
+
+	qp_work_entry->sche_cnt++;
+
+	/* Query db process status, until hw process completely */
+	ret = check_qp_db_process_status(hr_dev, hr_qp,
+					 qp_work_entry->sdb_issue_ptr,
+					 &qp_work_entry->sdb_inv_cnt,
+					 &qp_work_entry->db_wait_stage);
+	if (ret) {
+		dev_err(dev, "Check QP(0x%lx) db process status failed!\n",
+			hr_qp->qpn);
+		return;
+	}
+
+	if (qp_work_entry->db_wait_stage != HNS_ROCE_V1_DB_WAIT_OK &&
+	    priv->des_qp.requeue_flag) {
+		queue_work(priv->des_qp.qp_wq, work);
+		return;
+	}
+
+	/* Modify qp to reset before destroying qp */
+	ret = hns_roce_v1_modify_qp(&hr_qp->ibqp, NULL, 0, hr_qp->state,
+				    IB_QPS_RESET);
+	if (ret) {
+		dev_err(dev, "Modify QP(0x%lx) to RST failed!\n", hr_qp->qpn);
+		return;
+	}
+
+	hns_roce_qp_remove(hr_dev, hr_qp);
+	hns_roce_qp_free(hr_dev, hr_qp);
+
+	if (hr_qp->ibqp.qp_type == IB_QPT_RC) {
+		/* RC QP, release QPN */
+		hns_roce_release_range_qp(hr_dev, hr_qp->qpn, 1);
+		kfree(hr_qp);
+	} else
+		kfree(hr_to_hr_sqp(hr_qp));
+
+	kfree(qp_work_entry);
+
+	dev_dbg(dev, "Accomplished destroy QP(0x%lx) work.\n", hr_qp->qpn);
+}
+
+int hns_roce_v1_destroy_qp(struct ib_qp *ibqp)
+{
+	struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
+	struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+	struct device *dev = &hr_dev->pdev->dev;
+	struct hns_roce_qp_work qp_work_entry;
+	struct hns_roce_qp_work *qp_work;
+	struct hns_roce_v1_priv *priv;
+	struct hns_roce_cq *send_cq, *recv_cq;
+	int is_user = !!ibqp->pd->uobject;
+	int is_timeout = 0;
+	int ret;
+
+	ret = check_qp_reset_state(hr_dev, hr_qp, &qp_work_entry, &is_timeout);
+	if (ret) {
+		dev_err(dev, "QP reset state check failed(%d)!\n", ret);
+		return ret;
+	}
+
 	send_cq = to_hr_cq(hr_qp->ibqp.send_cq);
 	recv_cq = to_hr_cq(hr_qp->ibqp.recv_cq);
 
 	hns_roce_lock_cqs(send_cq, recv_cq);
-
 	if (!is_user) {
 		__hns_roce_v1_cq_clean(recv_cq, hr_qp->qpn, hr_qp->ibqp.srq ?
 				       to_hr_srq(hr_qp->ibqp.srq) : NULL);
 		if (send_cq != recv_cq)
 			__hns_roce_v1_cq_clean(send_cq, hr_qp->qpn, NULL);
 	}
-
-	hns_roce_qp_remove(hr_dev, hr_qp);
-
 	hns_roce_unlock_cqs(send_cq, recv_cq);
 
-	hns_roce_qp_free(hr_dev, hr_qp);
+	if (!is_timeout) {
+		hns_roce_qp_remove(hr_dev, hr_qp);
+		hns_roce_qp_free(hr_dev, hr_qp);
 
-	/* Not special_QP, free their QPN */
-	if ((hr_qp->ibqp.qp_type == IB_QPT_RC) ||
-	    (hr_qp->ibqp.qp_type == IB_QPT_UC) ||
-	    (hr_qp->ibqp.qp_type == IB_QPT_UD))
-		hns_roce_release_range_qp(hr_dev, hr_qp->qpn, 1);
+		/* RC QP, release QPN */
+		if (hr_qp->ibqp.qp_type == IB_QPT_RC)
+			hns_roce_release_range_qp(hr_dev, hr_qp->qpn, 1);
+	}
 
 	hns_roce_mtt_cleanup(hr_dev, &hr_qp->mtt);
 
-	if (is_user) {
+	if (is_user)
 		ib_umem_release(hr_qp->umem);
-	} else {
+	else {
 		kfree(hr_qp->sq.wrid);
 		kfree(hr_qp->rq.wrid);
+
 		hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
 	}
+
+	if (!is_timeout) {
+		if (hr_qp->ibqp.qp_type == IB_QPT_RC)
+			kfree(hr_qp);
+		else
+			kfree(hr_to_hr_sqp(hr_qp));
+	} else {
+		qp_work = kzalloc(sizeof(*qp_work), GFP_KERNEL);
+		if (!qp_work)
+			return -ENOMEM;
+
+		INIT_WORK(&qp_work->work, hns_roce_v1_destroy_qp_work_fn);
+		qp_work->ib_dev	= &hr_dev->ib_dev;
+		qp_work->qp		= hr_qp;
+		qp_work->db_wait_stage	= qp_work_entry.db_wait_stage;
+		qp_work->sdb_issue_ptr	= qp_work_entry.sdb_issue_ptr;
+		qp_work->sdb_inv_cnt	= qp_work_entry.sdb_inv_cnt;
+		qp_work->sche_cnt	= qp_work_entry.sche_cnt;
+
+		priv = (struct hns_roce_v1_priv *)hr_dev->hw->priv;
+		queue_work(priv->des_qp.qp_wq, &qp_work->work);
+		dev_dbg(dev, "Begin destroy QP(0x%lx) work.\n", hr_qp->qpn);
+	}
+
+	return 0;
 }
 
-int hns_roce_v1_destroy_qp(struct ib_qp *ibqp)
+int hns_roce_v1_destroy_cq(struct ib_cq *ibcq)
 {
-	struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
-	struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+	struct hns_roce_dev *hr_dev = to_hr_dev(ibcq->device);
+	struct hns_roce_cq *hr_cq = to_hr_cq(ibcq);
+	struct device *dev = &hr_dev->pdev->dev;
+	u32 cqe_cnt_ori;
+	u32 cqe_cnt_cur;
+	u32 cq_buf_size;
+	int wait_time = 0;
+	int ret = 0;
 
-	hns_roce_v1_destroy_qp_common(hr_dev, hr_qp, !!ibqp->pd->uobject);
+	hns_roce_free_cq(hr_dev, hr_cq);
 
-	if (hr_qp->ibqp.qp_type == IB_QPT_GSI)
-		kfree(hr_to_hr_sqp(hr_qp));
-	else
-		kfree(hr_qp);
+	/*
+	 * Before freeing cq buffer, we need to ensure that the outstanding CQE
+	 * have been written by checking the CQE counter.
+	 */
+	cqe_cnt_ori = roce_read(hr_dev, ROCEE_SCAEP_WR_CQE_CNT);
+	while (1) {
+		if (roce_read(hr_dev, ROCEE_CAEP_CQE_WCMD_EMPTY) &
+		    HNS_ROCE_CQE_WCMD_EMPTY_BIT)
+			break;
 
-	return 0;
+		cqe_cnt_cur = roce_read(hr_dev, ROCEE_SCAEP_WR_CQE_CNT);
+		if ((cqe_cnt_cur - cqe_cnt_ori) >= HNS_ROCE_MIN_CQE_CNT)
+			break;
+
+		msleep(HNS_ROCE_EACH_FREE_CQ_WAIT_MSECS);
+		if (wait_time > HNS_ROCE_MAX_FREE_CQ_WAIT_CNT) {
+			dev_warn(dev, "Destroy cq 0x%lx timeout!\n",
+				hr_cq->cqn);
+			ret = -ETIMEDOUT;
+			break;
+		}
+		wait_time++;
+	}
+
+	hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
+
+	if (ibcq->uobject)
+		ib_umem_release(hr_cq->umem);
+	else {
+		/* Free the buff of stored cq */
+		cq_buf_size = (ibcq->cqe + 1) * hr_dev->caps.cq_entry_sz;
+		hns_roce_buf_free(hr_dev, cq_buf_size, &hr_cq->hr_buf.hr_buf);
+	}
+
+	kfree(hr_cq);
+
+	return ret;
 }
 
 struct hns_roce_v1_priv hr_v1_priv;
@@ -2917,5 +3835,7 @@ struct hns_roce_hw hns_roce_hw_v1 = {
 	.post_recv = hns_roce_v1_post_recv,
 	.req_notify_cq = hns_roce_v1_req_notify_cq,
 	.poll_cq = hns_roce_v1_poll_cq,
+	.dereg_mr = hns_roce_v1_dereg_mr,
+	.destroy_cq = hns_roce_v1_destroy_cq,
 	.priv = &hr_v1_priv,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_hw_v1.h	2017-02-12 16:03:20.000000000 -0500
@@ -58,6 +58,7 @@
 #define HNS_ROCE_V1_PHY_UAR_NUM				8
 
 #define HNS_ROCE_V1_GID_NUM				16
+#define HNS_ROCE_V1_RESV_QP				8
 
 #define HNS_ROCE_V1_NUM_COMP_EQE			0x8000
 #define HNS_ROCE_V1_NUM_ASYNC_EQE			0x400
@@ -102,8 +103,22 @@
 #define HNS_ROCE_V1_EXT_ODB_ALFUL	\
 	(HNS_ROCE_V1_EXT_ODB_DEPTH - HNS_ROCE_V1_DB_RSVD)
 
+#define HNS_ROCE_V1_DB_WAIT_OK				0
+#define HNS_ROCE_V1_DB_STAGE1				1
+#define HNS_ROCE_V1_DB_STAGE2				2
+#define HNS_ROCE_V1_CHECK_DB_TIMEOUT_MSECS		10000
+#define HNS_ROCE_V1_CHECK_DB_SLEEP_MSECS		20
+#define HNS_ROCE_V1_FREE_MR_TIMEOUT_MSECS		50000
+#define HNS_ROCE_V1_RECREATE_LP_QP_TIMEOUT_MSECS	10000
+#define HNS_ROCE_V1_FREE_MR_WAIT_VALUE			5
+#define HNS_ROCE_V1_RECREATE_LP_QP_WAIT_VALUE		20
+
 #define HNS_ROCE_BT_RSV_BUF_SIZE			(1 << 17)
 
+#define HNS_ROCE_V1_TPTR_ENTRY_SIZE			2
+#define HNS_ROCE_V1_TPTR_BUF_SIZE	\
+	(HNS_ROCE_V1_TPTR_ENTRY_SIZE * HNS_ROCE_V1_MAX_CQ_NUM)
+
 #define HNS_ROCE_ODB_POLL_MODE				0
 
 #define HNS_ROCE_SDB_NORMAL_MODE			0
@@ -140,6 +155,7 @@
 #define SQ_PSN_SHIFT					8
 #define QKEY_VAL					0x80010000
 #define SDB_INV_CNT_OFFSET				8
+#define SDB_ST_CMP_VAL					8
 
 struct hns_roce_cq_context {
 	u32 cqc_byte_4;
@@ -436,6 +452,8 @@ struct hns_roce_ud_send_wqe {
 #define UD_SEND_WQE_U32_8_DMAC_5_M   \
 	(((1UL << 8) - 1) << UD_SEND_WQE_U32_8_DMAC_5_S)
 
+#define UD_SEND_WQE_U32_8_LOOPBACK_INDICATOR_S 22
+
 #define UD_SEND_WQE_U32_8_OPERATION_TYPE_S 16
 #define UD_SEND_WQE_U32_8_OPERATION_TYPE_M   \
 	(((1UL << 4) - 1) << UD_SEND_WQE_U32_8_OPERATION_TYPE_S)
@@ -480,13 +498,17 @@ struct hns_roce_sqp_context {
 	u32 qp1c_bytes_12;
 	u32 qp1c_bytes_16;
 	u32 qp1c_bytes_20;
-	u32 qp1c_bytes_28;
 	u32 cur_rq_wqe_ba_l;
+	u32 qp1c_bytes_28;
 	u32 qp1c_bytes_32;
 	u32 cur_sq_wqe_ba_l;
 	u32 qp1c_bytes_40;
 };
 
+#define QP1C_BYTES_4_QP_STATE_S 0
+#define QP1C_BYTES_4_QP_STATE_M   \
+	(((1UL << 3) - 1) << QP1C_BYTES_4_QP_STATE_S)
+
 #define QP1C_BYTES_4_SQ_WQE_SHIFT_S 8
 #define QP1C_BYTES_4_SQ_WQE_SHIFT_M   \
 	(((1UL << 4) - 1) << QP1C_BYTES_4_SQ_WQE_SHIFT_S)
@@ -952,6 +974,10 @@ struct hns_roce_sq_db {
 #define SQ_DOORBELL_U32_4_SQ_HEAD_M   \
 	(((1UL << 15) - 1) << SQ_DOORBELL_U32_4_SQ_HEAD_S)
 
+#define SQ_DOORBELL_U32_4_SL_S 16
+#define SQ_DOORBELL_U32_4_SL_M   \
+	(((1UL << 2) - 1) << SQ_DOORBELL_U32_4_SL_S)
+
 #define SQ_DOORBELL_U32_4_PORT_S 18
 #define SQ_DOORBELL_U32_4_PORT_M  (((1UL << 3) - 1) << SQ_DOORBELL_U32_4_PORT_S)
 
@@ -979,12 +1005,58 @@ struct hns_roce_bt_table {
 	struct hns_roce_buf_list cqc_buf;
 };
 
+struct hns_roce_tptr_table {
+	struct hns_roce_buf_list tptr_buf;
+};
+
+struct hns_roce_qp_work {
+	struct	work_struct work;
+	struct	ib_device *ib_dev;
+	struct	hns_roce_qp *qp;
+	u32	db_wait_stage;
+	u32	sdb_issue_ptr;
+	u32	sdb_inv_cnt;
+	u32	sche_cnt;
+};
+
+struct hns_roce_des_qp {
+	struct workqueue_struct	*qp_wq;
+	int	requeue_flag;
+};
+
+struct hns_roce_mr_free_work {
+	struct	work_struct work;
+	struct	ib_device *ib_dev;
+	struct	completion *comp;
+	int	comp_flag;
+	void	*mr;
+};
+
+struct hns_roce_recreate_lp_qp_work {
+	struct	work_struct work;
+	struct	ib_device *ib_dev;
+	struct	completion *comp;
+	int	comp_flag;
+};
+
+struct hns_roce_free_mr {
+	struct workqueue_struct *free_mr_wq;
+	struct hns_roce_qp *mr_free_qp[HNS_ROCE_V1_RESV_QP];
+	struct hns_roce_cq *mr_free_cq;
+	struct hns_roce_pd *mr_free_pd;
+};
+
 struct hns_roce_v1_priv {
 	struct hns_roce_db_table  db_table;
 	struct hns_roce_raq_table raq_table;
 	struct hns_roce_bt_table  bt_table;
+	struct hns_roce_tptr_table tptr_table;
+	struct hns_roce_des_qp des_qp;
+	struct hns_roce_free_mr free_mr;
 };
 
 int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset);
+int hns_roce_v1_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
+int hns_roce_v1_destroy_qp(struct ib_qp *ibqp);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_main.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,52 +35,13 @@
 #include <rdma/ib_addr.h>
 #include <rdma/ib_smi.h>
 #include <rdma/ib_user_verbs.h>
+#include <rdma/ib_cache.h>
 #include "hns_roce_common.h"
 #include "hns_roce_device.h"
-#include "hns_roce_user.h"
+#include <rdma/hns-abi.h>
 #include "hns_roce_hem.h"
 
 /**
- * hns_roce_addrconf_ifid_eui48 - Get default gid.
- * @eui: eui.
- * @vlan_id:  gid
- * @dev:  net device
- * Description:
- *    MAC convert to GID
- *        gid[0..7] = fe80 0000 0000 0000
- *        gid[8] = mac[0] ^ 2
- *        gid[9] = mac[1]
- *        gid[10] = mac[2]
- *        gid[11] = ff        (VLAN ID high byte (4 MS bits))
- *        gid[12] = fe        (VLAN ID low byte)
- *        gid[13] = mac[3]
- *        gid[14] = mac[4]
- *        gid[15] = mac[5]
- */
-static void hns_roce_addrconf_ifid_eui48(u8 *eui, u16 vlan_id,
-					 struct net_device *dev)
-{
-	memcpy(eui, dev->dev_addr, 3);
-	memcpy(eui + 5, dev->dev_addr + 3, 3);
-	if (vlan_id < 0x1000) {
-		eui[3] = vlan_id >> 8;
-		eui[4] = vlan_id & 0xff;
-	} else {
-		eui[3] = 0xff;
-		eui[4] = 0xfe;
-	}
-	eui[0] ^= 2;
-}
-
-static void hns_roce_make_default_gid(struct net_device *dev, union ib_gid *gid)
-{
-	memset(gid, 0, sizeof(*gid));
-	gid->raw[0] = 0xFE;
-	gid->raw[1] = 0x80;
-	hns_roce_addrconf_ifid_eui48(&gid->raw[8], 0xffff, dev);
-}
-
-/**
  * hns_get_gid_index - Get gid index.
  * @hr_dev: pointer to structure hns_roce_dev.
  * @port:  port, value range: 0 ~ MAX
@@ -96,30 +57,6 @@ int hns_get_gid_index(struct hns_roce_de
 	return gid_index * hr_dev->caps.num_ports + port;
 }
 
-static int hns_roce_set_gid(struct hns_roce_dev *hr_dev, u8 port, int gid_index,
-		     union ib_gid *gid)
-{
-	struct device *dev = &hr_dev->pdev->dev;
-	u8 gid_idx = 0;
-
-	if (gid_index >= hr_dev->caps.gid_table_len[port]) {
-		dev_err(dev, "gid_index %d illegal, port %d gid range: 0~%d\n",
-			gid_index, port, hr_dev->caps.gid_table_len[port] - 1);
-		return -EINVAL;
-	}
-
-	gid_idx = hns_get_gid_index(hr_dev, port, gid_index);
-
-	if (!memcmp(gid, &hr_dev->iboe.gid_table[gid_idx], sizeof(*gid)))
-		return -EINVAL;
-
-	memcpy(&hr_dev->iboe.gid_table[gid_idx], gid, sizeof(*gid));
-
-	hr_dev->hw->set_gid(hr_dev, port, gid_index, gid);
-
-	return 0;
-}
-
 static void hns_roce_set_mac(struct hns_roce_dev *hr_dev, u8 port, u8 *addr)
 {
 	u8 phy_port;
@@ -135,27 +72,44 @@ static void hns_roce_set_mac(struct hns_
 	hr_dev->hw->set_mac(hr_dev, phy_port, addr);
 }
 
-static void hns_roce_set_mtu(struct hns_roce_dev *hr_dev, u8 port, int mtu)
+static int hns_roce_add_gid(struct ib_device *device, u8 port_num,
+			    unsigned int index, const union ib_gid *gid,
+			    const struct ib_gid_attr *attr, void **context)
 {
-	u8 phy_port = hr_dev->iboe.phy_port[port];
-	enum ib_mtu tmp;
+	struct hns_roce_dev *hr_dev = to_hr_dev(device);
+	u8 port = port_num - 1;
+	unsigned long flags;
 
-	tmp = iboe_get_mtu(mtu);
-	if (!tmp)
-		tmp = IB_MTU_256;
+	if (port >= hr_dev->caps.num_ports)
+		return -EINVAL;
 
-	hr_dev->hw->set_mtu(hr_dev, phy_port, tmp);
+	spin_lock_irqsave(&hr_dev->iboe.lock, flags);
+
+	hr_dev->hw->set_gid(hr_dev, port, index, (union ib_gid *)gid);
+
+	spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
+
+	return 0;
 }
 
-static void hns_roce_update_gids(struct hns_roce_dev *hr_dev, int port)
+static int hns_roce_del_gid(struct ib_device *device, u8 port_num,
+			    unsigned int index, void **context)
 {
-	struct ib_event event;
+	struct hns_roce_dev *hr_dev = to_hr_dev(device);
+	union ib_gid zgid = { {0} };
+	u8 port = port_num - 1;
+	unsigned long flags;
 
-	/* Refresh gid in ib_cache */
-	event.device = &hr_dev->ib_dev;
-	event.element.port_num = port + 1;
-	event.event = IB_EVENT_GID_CHANGE;
-	ib_dispatch_event(&event);
+	if (port >= hr_dev->caps.num_ports)
+		return -EINVAL;
+
+	spin_lock_irqsave(&hr_dev->iboe.lock, flags);
+
+	hr_dev->hw->set_gid(hr_dev, port, index, &zgid);
+
+	spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
+
+	return 0;
 }
 
 static int handle_en_event(struct hns_roce_dev *hr_dev, u8 port,
@@ -163,9 +117,6 @@ static int handle_en_event(struct hns_ro
 {
 	struct device *dev = &hr_dev->pdev->dev;
 	struct net_device *netdev;
-	unsigned long flags;
-	union ib_gid gid;
-	int ret = 0;
 
 	netdev = hr_dev->iboe.netdevs[port];
 	if (!netdev) {
@@ -173,7 +124,7 @@ static int handle_en_event(struct hns_ro
 		return -ENODEV;
 	}
 
-	spin_lock_irqsave(&hr_dev->iboe.lock, flags);
+	spin_lock_bh(&hr_dev->iboe.lock);
 
 	switch (event) {
 	case NETDEV_UP:
@@ -181,23 +132,19 @@ static int handle_en_event(struct hns_ro
 	case NETDEV_REGISTER:
 	case NETDEV_CHANGEADDR:
 		hns_roce_set_mac(hr_dev, port, netdev->dev_addr);
-		hns_roce_make_default_gid(netdev, &gid);
-		ret = hns_roce_set_gid(hr_dev, port, 0, &gid);
-		if (!ret)
-			hns_roce_update_gids(hr_dev, port);
 		break;
 	case NETDEV_DOWN:
 		/*
-		* In v1 engine, only support all ports closed together.
-		*/
+		 * In v1 engine, only support all ports closed together.
+		 */
 		break;
 	default:
 		dev_dbg(dev, "NETDEV event = 0x%x!\n", (u32)(event));
 		break;
 	}
 
-	spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
-	return ret;
+	spin_unlock_bh(&hr_dev->iboe.lock);
+	return 0;
 }
 
 static int hns_roce_netdev_event(struct notifier_block *self,
@@ -224,118 +171,17 @@ static int hns_roce_netdev_event(struct
 	return NOTIFY_DONE;
 }
 
-static void hns_roce_addr_event(int event, struct net_device *event_netdev,
-				struct hns_roce_dev *hr_dev, union ib_gid *gid)
-{
-	struct hns_roce_ib_iboe *iboe = NULL;
-	int gid_table_len = 0;
-	unsigned long flags;
-	union ib_gid zgid;
-	u8 gid_idx = 0;
-	u8 port = 0;
-	int i = 0;
-	int free;
-	struct net_device *real_dev = rdma_vlan_dev_real_dev(event_netdev) ?
-				      rdma_vlan_dev_real_dev(event_netdev) :
-				      event_netdev;
-
-	if (event != NETDEV_UP && event != NETDEV_DOWN)
-		return;
-
-	iboe = &hr_dev->iboe;
-	while (port < hr_dev->caps.num_ports) {
-		if (real_dev == iboe->netdevs[port])
-			break;
-		port++;
-	}
-
-	if (port >= hr_dev->caps.num_ports) {
-		dev_dbg(&hr_dev->pdev->dev, "can't find netdev\n");
-		return;
-	}
-
-	memset(zgid.raw, 0, sizeof(zgid.raw));
-	free = -1;
-	gid_table_len = hr_dev->caps.gid_table_len[port];
-
-	spin_lock_irqsave(&hr_dev->iboe.lock, flags);
-
-	for (i = 0; i < gid_table_len; i++) {
-		gid_idx = hns_get_gid_index(hr_dev, port, i);
-		if (!memcmp(gid->raw, iboe->gid_table[gid_idx].raw,
-			    sizeof(gid->raw)))
-			break;
-		if (free < 0 && !memcmp(zgid.raw,
-			iboe->gid_table[gid_idx].raw, sizeof(zgid.raw)))
-			free = i;
-	}
-
-	if (i >= gid_table_len) {
-		if (free < 0) {
-			spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
-			dev_dbg(&hr_dev->pdev->dev,
-				"gid_index overflow, port(%d)\n", port);
-			return;
-		}
-		if (!hns_roce_set_gid(hr_dev, port, free, gid))
-			hns_roce_update_gids(hr_dev, port);
-	} else if (event == NETDEV_DOWN) {
-		if (!hns_roce_set_gid(hr_dev, port, i, &zgid))
-			hns_roce_update_gids(hr_dev, port);
-	}
-
-	spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
-}
-
-static int hns_roce_inet_event(struct notifier_block *self, unsigned long event,
-			       void *ptr)
-{
-	struct in_ifaddr *ifa = ptr;
-	struct hns_roce_dev *hr_dev;
-	struct net_device *dev = ifa->ifa_dev->dev;
-	union ib_gid gid;
-
-	ipv6_addr_set_v4mapped(ifa->ifa_address, (struct in6_addr *)&gid);
-
-	hr_dev = container_of(self, struct hns_roce_dev, iboe.nb_inet);
-
-	hns_roce_addr_event(event, dev, hr_dev, &gid);
-
-	return NOTIFY_DONE;
-}
-
-static int hns_roce_setup_mtu_gids(struct hns_roce_dev *hr_dev)
+static int hns_roce_setup_mtu_mac(struct hns_roce_dev *hr_dev)
 {
-	struct in_ifaddr *ifa_list = NULL;
-	union ib_gid gid = {{0} };
-	u32 ipaddr = 0;
-	int index = 0;
-	int ret = 0;
-	u8 i = 0;
+	u8 i;
 
 	for (i = 0; i < hr_dev->caps.num_ports; i++) {
-		hns_roce_set_mtu(hr_dev, i,
-				 ib_mtu_enum_to_int(hr_dev->caps.max_mtu));
+		hr_dev->hw->set_mtu(hr_dev, hr_dev->iboe.phy_port[i],
+				    hr_dev->caps.max_mtu);
 		hns_roce_set_mac(hr_dev, i, hr_dev->iboe.netdevs[i]->dev_addr);
-
-		if (hr_dev->iboe.netdevs[i]->ip_ptr) {
-			ifa_list = hr_dev->iboe.netdevs[i]->ip_ptr->ifa_list;
-			index = 1;
-			while (ifa_list) {
-				ipaddr = ifa_list->ifa_address;
-				ipv6_addr_set_v4mapped(ipaddr,
-						       (struct in6_addr *)&gid);
-				ret = hns_roce_set_gid(hr_dev, i, index, &gid);
-				if (ret)
-					break;
-				index++;
-				ifa_list = ifa_list->ifa_next;
-			}
-			hns_roce_update_gids(hr_dev, i);
-		}
 	}
 
-	return ret;
+	return 0;
 }
 
 static int hns_roce_query_device(struct ib_device *ib_dev,
@@ -444,31 +290,6 @@ static enum rdma_link_layer hns_roce_get
 static int hns_roce_query_gid(struct ib_device *ib_dev, u8 port_num, int index,
 			      union ib_gid *gid)
 {
-	struct hns_roce_dev *hr_dev = to_hr_dev(ib_dev);
-	struct device *dev = &hr_dev->pdev->dev;
-	u8 gid_idx = 0;
-	u8 port;
-
-	if (port_num < 1 || port_num > hr_dev->caps.num_ports ||
-	    index >= hr_dev->caps.gid_table_len[port_num - 1]) {
-		dev_err(dev,
-			"port_num %d index %d illegal! correct range: port_num 1~%d index 0~%d!\n",
-			port_num, index, hr_dev->caps.num_ports,
-			hr_dev->caps.gid_table_len[port_num - 1] - 1);
-		return -EINVAL;
-	}
-
-	port = port_num - 1;
-	gid_idx = hns_get_gid_index(hr_dev, port, index);
-	if (gid_idx >= HNS_ROCE_MAX_GID_NUM) {
-		dev_err(dev, "port_num %d index %d illegal! total gid num %d!\n",
-			port_num, index, HNS_ROCE_MAX_GID_NUM);
-		return -EINVAL;
-	}
-
-	memcpy(gid->raw, hr_dev->iboe.gid_table[gid_idx].raw,
-	       HNS_ROCE_GID_SIZE);
-
 	return 0;
 }
 
@@ -549,6 +370,8 @@ static int hns_roce_dealloc_ucontext(str
 static int hns_roce_mmap(struct ib_ucontext *context,
 			 struct vm_area_struct *vma)
 {
+	struct hns_roce_dev *hr_dev = to_hr_dev(context->device);
+
 	if (((vma->vm_end - vma->vm_start) % PAGE_SIZE) != 0)
 		return -EINVAL;
 
@@ -558,10 +381,15 @@ static int hns_roce_mmap(struct ib_ucont
 				       to_hr_ucontext(context)->uar.pfn,
 				       PAGE_SIZE, vma->vm_page_prot))
 			return -EAGAIN;
-
-	} else {
+	} else if (vma->vm_pgoff == 1 && hr_dev->hw_rev == HNS_ROCE_HW_VER1) {
+		/* vm_pgoff: 1 -- TPTR */
+		if (io_remap_pfn_range(vma, vma->vm_start,
+				       hr_dev->tptr_dma_addr >> PAGE_SHIFT,
+				       hr_dev->tptr_size,
+				       vma->vm_page_prot))
+			return -EAGAIN;
+	} else
 		return -EINVAL;
-	}
 
 	return 0;
 }
@@ -605,7 +433,7 @@ static int hns_roce_register_device(stru
 	spin_lock_init(&iboe->lock);
 
 	ib_dev = &hr_dev->ib_dev;
-	strlcpy(ib_dev->name, "hisi_%d", IB_DEVICE_NAME_MAX);
+	strlcpy(ib_dev->name, "hns_%d", IB_DEVICE_NAME_MAX);
 
 	ib_dev->owner			= THIS_MODULE;
 	ib_dev->node_type		= RDMA_NODE_IB_CA;
@@ -639,6 +467,8 @@ static int hns_roce_register_device(stru
 	ib_dev->get_link_layer		= hns_roce_get_link_layer;
 	ib_dev->get_netdev		= hns_roce_get_netdev;
 	ib_dev->query_gid		= hns_roce_query_gid;
+	ib_dev->add_gid			= hns_roce_add_gid;
+	ib_dev->del_gid			= hns_roce_del_gid;
 	ib_dev->query_pkey		= hns_roce_query_pkey;
 	ib_dev->alloc_ucontext		= hns_roce_alloc_ucontext;
 	ib_dev->dealloc_ucontext	= hns_roce_dealloc_ucontext;
@@ -681,32 +511,22 @@ static int hns_roce_register_device(stru
 		return ret;
 	}
 
-	ret = hns_roce_setup_mtu_gids(hr_dev);
+	ret = hns_roce_setup_mtu_mac(hr_dev);
 	if (ret) {
-		dev_err(dev, "roce_setup_mtu_gids failed!\n");
-		goto error_failed_setup_mtu_gids;
+		dev_err(dev, "setup_mtu_mac failed!\n");
+		goto error_failed_setup_mtu_mac;
 	}
 
 	iboe->nb.notifier_call = hns_roce_netdev_event;
 	ret = register_netdevice_notifier(&iboe->nb);
 	if (ret) {
 		dev_err(dev, "register_netdevice_notifier failed!\n");
-		goto error_failed_setup_mtu_gids;
-	}
-
-	iboe->nb_inet.notifier_call = hns_roce_inet_event;
-	ret = register_inetaddr_notifier(&iboe->nb_inet);
-	if (ret) {
-		dev_err(dev, "register inet addr notifier failed!\n");
-		goto error_failed_register_inetaddr_notifier;
+		goto error_failed_setup_mtu_mac;
 	}
 
 	return 0;
 
-error_failed_register_inetaddr_notifier:
-	unregister_netdevice_notifier(&iboe->nb);
-
-error_failed_setup_mtu_gids:
+error_failed_setup_mtu_mac:
 	ib_unregister_device(ib_dev);
 
 	return ret;
@@ -940,10 +760,10 @@ err_unmap_mtt:
 }
 
 /**
-* hns_roce_setup_hca - setup host channel adapter
-* @hr_dev: pointer to hns roce device
-* Return : int
-*/
+ * hns_roce_setup_hca - setup host channel adapter
+ * @hr_dev: pointer to hns roce device
+ * Return : int
+ */
 static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev)
 {
 	int ret;
@@ -1008,11 +828,11 @@ err_uar_table_free:
 }
 
 /**
-* hns_roce_probe - RoCE driver entrance
-* @pdev: pointer to platform device
-* Return : int
-*
-*/
+ * hns_roce_probe - RoCE driver entrance
+ * @pdev: pointer to platform device
+ * Return : int
+ *
+ */
 static int hns_roce_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -1023,9 +843,6 @@ static int hns_roce_probe(struct platfor
 	if (!hr_dev)
 		return -ENOMEM;
 
-	memset((u8 *)hr_dev + sizeof(struct ib_device), 0,
-		sizeof(struct hns_roce_dev) - sizeof(struct ib_device));
-
 	hr_dev->pdev = pdev;
 	platform_set_drvdata(pdev, hr_dev);
 
@@ -1125,9 +942,9 @@ error_failed_get_cfg:
 }
 
 /**
-* hns_roce_remove - remove RoCE device
-* @pdev: pointer to platform device
-*/
+ * hns_roce_remove - remove RoCE device
+ * @pdev: pointer to platform device
+ */
 static int hns_roce_remove(struct platform_device *pdev)
 {
 	struct hns_roce_dev *hr_dev = platform_get_drvdata(pdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_mr.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_mr.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_mr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_mr.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@ static u32 hw_index_to_key(unsigned long
 	return (u32)(ind >> 24) | (ind << 8);
 }
 
-static unsigned long key_to_hw_index(u32 key)
+unsigned long key_to_hw_index(u32 key)
 {
 	return (key << 24) | (key >> 8);
 }
@@ -53,16 +53,16 @@ static int hns_roce_sw2hw_mpt(struct hns
 {
 	return hns_roce_cmd_mbox(hr_dev, mailbox->dma, 0, mpt_index, 0,
 				 HNS_ROCE_CMD_SW2HW_MPT,
-				 HNS_ROCE_CMD_TIME_CLASS_B);
+				 HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
-static int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
+int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
 			      struct hns_roce_cmd_mailbox *mailbox,
 			      unsigned long mpt_index)
 {
 	return hns_roce_cmd_mbox(hr_dev, 0, mailbox ? mailbox->dma : 0,
 				 mpt_index, !mailbox, HNS_ROCE_CMD_HW2SW_MPT,
-				 HNS_ROCE_CMD_TIME_CLASS_B);
+				 HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
 static int hns_roce_buddy_alloc(struct hns_roce_buddy *buddy, int order,
@@ -137,11 +137,13 @@ static int hns_roce_buddy_init(struct hn
 
 	for (i = 0; i <= buddy->max_order; ++i) {
 		s = BITS_TO_LONGS(1 << (buddy->max_order - i));
-		buddy->bits[i] = kmalloc_array(s, sizeof(long), GFP_KERNEL);
-		if (!buddy->bits[i])
-			goto err_out_free;
-
-		bitmap_zero(buddy->bits[i], 1 << (buddy->max_order - i));
+		buddy->bits[i] = kcalloc(s, sizeof(long), GFP_KERNEL |
+					 __GFP_NOWARN);
+		if (!buddy->bits[i]) {
+			buddy->bits[i] = vzalloc(s * sizeof(long));
+			if (!buddy->bits[i])
+				goto err_out_free;
+		}
 	}
 
 	set_bit(0, buddy->bits[buddy->max_order]);
@@ -151,7 +153,7 @@ static int hns_roce_buddy_init(struct hn
 
 err_out_free:
 	for (i = 0; i <= buddy->max_order; ++i)
-		kfree(buddy->bits[i]);
+		kvfree(buddy->bits[i]);
 
 err_out:
 	kfree(buddy->bits);
@@ -164,7 +166,7 @@ static void hns_roce_buddy_cleanup(struc
 	int i;
 
 	for (i = 0; i <= buddy->max_order; ++i)
-		kfree(buddy->bits[i]);
+		kvfree(buddy->bits[i]);
 
 	kfree(buddy->bits);
 	kfree(buddy->num_free);
@@ -287,7 +289,7 @@ static void hns_roce_mr_free(struct hns_
 	}
 
 	hns_roce_bitmap_free(&hr_dev->mr_table.mtpt_bitmap,
-			     key_to_hw_index(mr->key));
+			     key_to_hw_index(mr->key), BITMAP_NO_RR);
 }
 
 static int hns_roce_mr_enable(struct hns_roce_dev *hr_dev,
@@ -605,13 +607,20 @@ err_free:
 
 int hns_roce_dereg_mr(struct ib_mr *ibmr)
 {
+	struct hns_roce_dev *hr_dev = to_hr_dev(ibmr->device);
 	struct hns_roce_mr *mr = to_hr_mr(ibmr);
+	int ret = 0;
 
-	hns_roce_mr_free(to_hr_dev(ibmr->device), mr);
-	if (mr->umem)
-		ib_umem_release(mr->umem);
+	if (hr_dev->hw->dereg_mr) {
+		ret = hr_dev->hw->dereg_mr(hr_dev, mr);
+	} else {
+		hns_roce_mr_free(hr_dev, mr);
 
-	kfree(mr);
+		if (mr->umem)
+			ib_umem_release(mr->umem);
 
-	return 0;
+		kfree(mr);
+	}
+
+	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_pd.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_pd.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_pd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_pd.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@ static int hns_roce_pd_alloc(struct hns_
 
 static void hns_roce_pd_free(struct hns_roce_dev *hr_dev, unsigned long pdn)
 {
-	hns_roce_bitmap_free(&hr_dev->pd_bitmap, pdn);
+	hns_roce_bitmap_free(&hr_dev->pd_bitmap, pdn, BITMAP_NO_RR);
 }
 
 int hns_roce_init_pd_table(struct hns_roce_dev *hr_dev)
@@ -121,7 +121,8 @@ int hns_roce_uar_alloc(struct hns_roce_d
 
 void hns_roce_uar_free(struct hns_roce_dev *hr_dev, struct hns_roce_uar *uar)
 {
-	hns_roce_bitmap_free(&hr_dev->uar_table.bitmap, uar->index);
+	hns_roce_bitmap_free(&hr_dev->uar_table.bitmap, uar->index,
+			     BITMAP_NO_RR);
 }
 
 int hns_roce_init_uar_table(struct hns_roce_dev *hr_dev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_qp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@
 #include "hns_roce_common.h"
 #include "hns_roce_device.h"
 #include "hns_roce_hem.h"
-#include "hns_roce_user.h"
+#include <rdma/hns-abi.h>
 
 #define SQP_NUM				(2 * HNS_ROCE_MAX_PORTS)
 
@@ -250,7 +250,7 @@ void hns_roce_release_range_qp(struct hn
 	if (base_qpn < SQP_NUM)
 		return;
 
-	hns_roce_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
+	hns_roce_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, BITMAP_RR);
 }
 
 static int hns_roce_set_rq_size(struct hns_roce_dev *hr_dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_user.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_user.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/hns/hns_roce_user.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/hns/hns_roce_user.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2016 Hisilicon Limited.
- *
- * 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 _HNS_ROCE_USER_H
-#define _HNS_ROCE_USER_H
-
-struct hns_roce_ib_create_cq {
-	__u64   buf_addr;
-};
-
-struct hns_roce_ib_create_qp {
-	__u64	buf_addr;
-	__u64   db_addr;
-	__u8    log_sq_bb_count;
-	__u8    log_sq_stride;
-	__u8    sq_no_prefetch;
-	__u8    reserved[5];
-};
-
-struct hns_roce_ib_alloc_ucontext_resp {
-	__u32	qp_tab_size;
-};
-
-#endif /*_HNS_ROCE_USER_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,13 +68,13 @@ static void i40iw_disconnect_worker(stru
 
 /**
  * i40iw_free_sqbuf - put back puda buffer if refcount = 0
- * @dev: FPK device
+ * @vsi: pointer to vsi structure
  * @buf: puda buffer to free
  */
-void i40iw_free_sqbuf(struct i40iw_sc_dev *dev, void *bufp)
+void i40iw_free_sqbuf(struct i40iw_sc_vsi *vsi, void *bufp)
 {
 	struct i40iw_puda_buf *buf = (struct i40iw_puda_buf *)bufp;
-	struct i40iw_puda_rsrc *ilq = dev->ilq;
+	struct i40iw_puda_rsrc *ilq = vsi->ilq;
 
 	if (!atomic_dec_return(&buf->refcount))
 		i40iw_puda_ret_bufpool(ilq, buf);
@@ -221,6 +221,7 @@ static void i40iw_get_addr_info(struct i
 	memcpy(cm_info->rem_addr, cm_node->rem_addr, sizeof(cm_info->rem_addr));
 	cm_info->loc_port = cm_node->loc_port;
 	cm_info->rem_port = cm_node->rem_port;
+	cm_info->user_pri = cm_node->user_pri;
 }
 
 /**
@@ -271,6 +272,7 @@ static int i40iw_send_cm_event(struct i4
 		event.provider_data = (void *)cm_node;
 		event.private_data = (void *)cm_node->pdata_buf;
 		event.private_data_len = (u8)cm_node->pdata.size;
+		event.ird = cm_node->ird_size;
 		break;
 	case IW_CM_EVENT_CONNECT_REPLY:
 		i40iw_get_cmevent_info(cm_node, cm_id, &event);
@@ -335,13 +337,13 @@ static struct i40iw_cm_event *i40iw_crea
  */
 static void i40iw_free_retrans_entry(struct i40iw_cm_node *cm_node)
 {
-	struct i40iw_sc_dev *dev = cm_node->dev;
+	struct i40iw_device *iwdev = cm_node->iwdev;
 	struct i40iw_timer_entry *send_entry;
 
 	send_entry = cm_node->send_entry;
 	if (send_entry) {
 		cm_node->send_entry = NULL;
-		i40iw_free_sqbuf(dev, (void *)send_entry->sqbuf);
+		i40iw_free_sqbuf(&iwdev->vsi, (void *)send_entry->sqbuf);
 		kfree(send_entry);
 		atomic_dec(&cm_node->ref_count);
 	}
@@ -360,15 +362,6 @@ static void i40iw_cleanup_retrans_entry(
 	spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
 }
 
-static bool is_remote_ne020_or_chelsio(struct i40iw_cm_node *cm_node)
-{
-	if ((cm_node->rem_mac[0] == 0x0) &&
-	    (((cm_node->rem_mac[1] == 0x12) && (cm_node->rem_mac[2] == 0x55)) ||
-	     ((cm_node->rem_mac[1] == 0x07 && (cm_node->rem_mac[2] == 0x43)))))
-		return true;
-	return false;
-}
-
 /**
  * i40iw_form_cm_frame - get a free packet and build frame
  * @cm_node: connection's node ionfo to use in frame
@@ -384,7 +377,7 @@ static struct i40iw_puda_buf *i40iw_form
 						  u8 flags)
 {
 	struct i40iw_puda_buf *sqbuf;
-	struct i40iw_sc_dev *dev = cm_node->dev;
+	struct i40iw_sc_vsi *vsi = &cm_node->iwdev->vsi;
 	u8 *buf;
 
 	struct tcphdr *tcph;
@@ -396,8 +389,9 @@ static struct i40iw_puda_buf *i40iw_form
 	u32 opts_len = 0;
 	u32 pd_len = 0;
 	u32 hdr_len = 0;
+	u16 vtag;
 
-	sqbuf = i40iw_puda_get_bufpool(dev->ilq);
+	sqbuf = i40iw_puda_get_bufpool(vsi->ilq);
 	if (!sqbuf)
 		return NULL;
 	buf = sqbuf->mem.va;
@@ -408,11 +402,8 @@ static struct i40iw_puda_buf *i40iw_form
 	if (hdr)
 		hdr_len = hdr->size;
 
-	if (pdata) {
+	if (pdata)
 		pd_len = pdata->size;
-		if (!is_remote_ne020_or_chelsio(cm_node))
-			pd_len += MPA_ZERO_PAD_LEN;
-	}
 
 	if (cm_node->vlan_id < VLAN_TAG_PRESENT)
 		eth_hlen += 4;
@@ -445,7 +436,8 @@ static struct i40iw_puda_buf *i40iw_form
 		ether_addr_copy(ethh->h_source, cm_node->loc_mac);
 		if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
 			((struct vlan_ethhdr *)ethh)->h_vlan_proto = htons(ETH_P_8021Q);
-			((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(cm_node->vlan_id);
+			vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | cm_node->vlan_id;
+			((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
 
 			((struct vlan_ethhdr *)ethh)->h_vlan_encapsulated_proto = htons(ETH_P_IP);
 		} else {
@@ -454,7 +446,7 @@ static struct i40iw_puda_buf *i40iw_form
 
 		iph->version = IPVERSION;
 		iph->ihl = 5;	/* 5 * 4Byte words, IP headr len */
-		iph->tos = 0;
+		iph->tos = cm_node->tos;
 		iph->tot_len = htons(packetsize);
 		iph->id = htons(++cm_node->tcp_cntxt.loc_id);
 
@@ -474,13 +466,15 @@ static struct i40iw_puda_buf *i40iw_form
 		ether_addr_copy(ethh->h_source, cm_node->loc_mac);
 		if (cm_node->vlan_id < VLAN_TAG_PRESENT) {
 			((struct vlan_ethhdr *)ethh)->h_vlan_proto = htons(ETH_P_8021Q);
-			((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(cm_node->vlan_id);
+			vtag = (cm_node->user_pri << VLAN_PRIO_SHIFT) | cm_node->vlan_id;
+			((struct vlan_ethhdr *)ethh)->h_vlan_TCI = htons(vtag);
 			((struct vlan_ethhdr *)ethh)->h_vlan_encapsulated_proto = htons(ETH_P_IPV6);
 		} else {
 			ethh->h_proto = htons(ETH_P_IPV6);
 		}
 		ip6h->version = 6;
-		ip6h->flow_lbl[0] = 0;
+		ip6h->priority = cm_node->tos >> 4;
+		ip6h->flow_lbl[0] = cm_node->tos << 4;
 		ip6h->flow_lbl[1] = 0;
 		ip6h->flow_lbl[2] = 0;
 		ip6h->payload_len = htons(packetsize - sizeof(*ip6h));
@@ -1065,7 +1059,7 @@ int i40iw_schedule_cm_timer(struct i40iw
 			    int send_retrans,
 			    int close_when_complete)
 {
-	struct i40iw_sc_dev *dev = cm_node->dev;
+	struct i40iw_sc_vsi *vsi = &cm_node->iwdev->vsi;
 	struct i40iw_cm_core *cm_core = cm_node->cm_core;
 	struct i40iw_timer_entry *new_send;
 	int ret = 0;
@@ -1074,7 +1068,7 @@ int i40iw_schedule_cm_timer(struct i40iw
 
 	new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC);
 	if (!new_send) {
-		i40iw_free_sqbuf(cm_node->dev, (void *)sqbuf);
+		i40iw_free_sqbuf(vsi, (void *)sqbuf);
 		return -ENOMEM;
 	}
 	new_send->retrycount = I40IW_DEFAULT_RETRYS;
@@ -1089,7 +1083,7 @@ int i40iw_schedule_cm_timer(struct i40iw
 		new_send->timetosend += (HZ / 10);
 		if (cm_node->close_entry) {
 			kfree(new_send);
-			i40iw_free_sqbuf(cm_node->dev, (void *)sqbuf);
+			i40iw_free_sqbuf(vsi, (void *)sqbuf);
 			i40iw_pr_err("already close entry\n");
 			return -EINVAL;
 		}
@@ -1104,7 +1098,7 @@ int i40iw_schedule_cm_timer(struct i40iw
 		new_send->timetosend = jiffies + I40IW_RETRY_TIMEOUT;
 
 		atomic_inc(&sqbuf->refcount);
-		i40iw_puda_send_buf(dev->ilq, sqbuf);
+		i40iw_puda_send_buf(vsi->ilq, sqbuf);
 		if (!send_retrans) {
 			i40iw_cleanup_retrans_entry(cm_node);
 			if (close_when_complete)
@@ -1201,6 +1195,7 @@ static void i40iw_cm_timer_tick(unsigned
 	struct i40iw_cm_node *cm_node;
 	struct i40iw_timer_entry *send_entry, *close_entry;
 	struct list_head *list_core_temp;
+	struct i40iw_sc_vsi *vsi;
 	struct list_head *list_node;
 	struct i40iw_cm_core *cm_core = (struct i40iw_cm_core *)pass;
 	u32 settimer = 0;
@@ -1276,9 +1271,10 @@ static void i40iw_cm_timer_tick(unsigned
 		cm_node->cm_core->stats_pkt_retrans++;
 		spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
 
+		vsi = &cm_node->iwdev->vsi;
 		dev = cm_node->dev;
 		atomic_inc(&send_entry->sqbuf->refcount);
-		i40iw_puda_send_buf(dev->ilq, send_entry->sqbuf);
+		i40iw_puda_send_buf(vsi->ilq, send_entry->sqbuf);
 		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
 		if (send_entry->send_retrans) {
 			send_entry->retranscount--;
@@ -1379,10 +1375,11 @@ int i40iw_send_syn(struct i40iw_cm_node
 static void i40iw_send_ack(struct i40iw_cm_node *cm_node)
 {
 	struct i40iw_puda_buf *sqbuf;
+	struct i40iw_sc_vsi *vsi = &cm_node->iwdev->vsi;
 
 	sqbuf = i40iw_form_cm_frame(cm_node, NULL, NULL, NULL, SET_ACK);
 	if (sqbuf)
-		i40iw_puda_send_buf(cm_node->dev->ilq, sqbuf);
+		i40iw_puda_send_buf(vsi->ilq, sqbuf);
 	else
 		i40iw_pr_err("no sqbuf\n");
 }
@@ -1564,9 +1561,15 @@ static enum i40iw_status_code i40iw_del_
 		memcpy(cm_info->loc_addr, child_listen_node->loc_addr,
 		       sizeof(cm_info->loc_addr));
 		cm_info->vlan_id = child_listen_node->vlan_id;
-		ret = i40iw_manage_qhash(iwdev, cm_info,
-					 I40IW_QHASH_TYPE_TCP_SYN,
-					 I40IW_QHASH_MANAGE_TYPE_DELETE, NULL, false);
+		if (child_listen_node->qhash_set) {
+			ret = i40iw_manage_qhash(iwdev, cm_info,
+						 I40IW_QHASH_TYPE_TCP_SYN,
+						 I40IW_QHASH_MANAGE_TYPE_DELETE,
+						 NULL, false);
+			child_listen_node->qhash_set = false;
+		} else {
+			ret = I40IW_SUCCESS;
+		}
 		i40iw_debug(&iwdev->sc_dev,
 			    I40IW_DEBUG_CM,
 			    "freed pointer = %p\n",
@@ -1591,9 +1594,10 @@ static enum i40iw_status_code i40iw_del_
 static struct net_device *i40iw_netdev_vlan_ipv6(u32 *addr, u16 *vlan_id, u8 *mac)
 {
 	struct net_device *ip_dev = NULL;
-#if IS_ENABLED(CONFIG_IPV6)
 	struct in6_addr laddr6;
 
+	if (!IS_ENABLED(CONFIG_IPV6))
+		return NULL;
 	i40iw_copy_ip_htonl(laddr6.in6_u.u6_addr32, addr);
 	if (vlan_id)
 		*vlan_id = I40IW_NO_VLAN;
@@ -1610,7 +1614,6 @@ static struct net_device *i40iw_netdev_v
 		}
 	}
 	rcu_read_unlock();
-#endif
 	return ip_dev;
 }
 
@@ -1646,7 +1649,7 @@ static enum i40iw_status_code i40iw_add_
 {
 	struct net_device *ip_dev;
 	struct inet6_dev *idev;
-	struct inet6_ifaddr *ifp;
+	struct inet6_ifaddr *ifp, *tmp;
 	enum i40iw_status_code ret = 0;
 	struct i40iw_cm_listener *child_listen_node;
 	unsigned long flags;
@@ -1661,7 +1664,7 @@ static enum i40iw_status_code i40iw_add_
 				i40iw_pr_err("idev == NULL\n");
 				break;
 			}
-			list_for_each_entry(ifp, &idev->addr_list, if_list) {
+			list_for_each_entry_safe(ifp, tmp, &idev->addr_list, if_list) {
 				i40iw_debug(&iwdev->sc_dev,
 					    I40IW_DEBUG_CM,
 					    "IP=%pI6, vlan_id=%d, MAC=%pM\n",
@@ -1675,7 +1678,6 @@ static enum i40iw_status_code i40iw_add_
 					    "Allocating child listener %p\n",
 					    child_listen_node);
 				if (!child_listen_node) {
-					i40iw_pr_err("listener memory allocation\n");
 					ret = I40IW_ERR_NO_MEMORY;
 					goto exit;
 				}
@@ -1695,6 +1697,7 @@ static enum i40iw_status_code i40iw_add_
 							 I40IW_QHASH_MANAGE_TYPE_ADD,
 							 NULL, true);
 				if (!ret) {
+					child_listen_node->qhash_set = true;
 					spin_lock_irqsave(&iwdev->cm_core.listen_list_lock, flags);
 					list_add(&child_listen_node->child_listen_list,
 						 &cm_parent_listen_node->child_listen_list);
@@ -1751,7 +1754,6 @@ static enum i40iw_status_code i40iw_add_
 					    "Allocating child listener %p\n",
 					    child_listen_node);
 				if (!child_listen_node) {
-					i40iw_pr_err("listener memory allocation\n");
 					in_dev_put(idev);
 					ret = I40IW_ERR_NO_MEMORY;
 					goto exit;
@@ -1773,6 +1775,7 @@ static enum i40iw_status_code i40iw_add_
 							 NULL,
 							 true);
 				if (!ret) {
+					child_listen_node->qhash_set = true;
 					spin_lock_irqsave(&iwdev->cm_core.listen_list_lock, flags);
 					list_add(&child_listen_node->child_listen_list,
 						 &cm_parent_listen_node->child_listen_list);
@@ -1880,6 +1883,7 @@ static int i40iw_dec_refcnt_listen(struc
 			nfo.loc_port = listener->loc_port;
 			nfo.ipv4 = listener->ipv4;
 			nfo.vlan_id = listener->vlan_id;
+			nfo.user_pri = listener->user_pri;
 
 			if (!list_empty(&listener->child_listen_list)) {
 				i40iw_del_multiple_qhash(listener->iwdev, &nfo, listener);
@@ -2138,6 +2142,20 @@ static struct i40iw_cm_node *i40iw_make_
 	/* set our node specific transport info */
 	cm_node->ipv4 = cm_info->ipv4;
 	cm_node->vlan_id = cm_info->vlan_id;
+	if ((cm_node->vlan_id == I40IW_NO_VLAN) && iwdev->dcb)
+		cm_node->vlan_id = 0;
+	cm_node->tos = cm_info->tos;
+	cm_node->user_pri = cm_info->user_pri;
+	if (listener) {
+		if (listener->tos != cm_info->tos)
+			i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_DCB,
+				    "application TOS[%d] and remote client TOS[%d] mismatch\n",
+				     listener->tos, cm_info->tos);
+		cm_node->tos = max(listener->tos, cm_info->tos);
+		cm_node->user_pri = rt_tos2priority(cm_node->tos);
+		i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_DCB, "listener: TOS:[%d] UP:[%d]\n",
+			    cm_node->tos, cm_node->user_pri);
+	}
 	memcpy(cm_node->loc_addr, cm_info->loc_addr, sizeof(cm_node->loc_addr));
 	memcpy(cm_node->rem_addr, cm_info->rem_addr, sizeof(cm_node->rem_addr));
 	cm_node->loc_port = cm_info->loc_port;
@@ -2162,7 +2180,7 @@ static struct i40iw_cm_node *i40iw_make_
 			I40IW_CM_DEFAULT_RCV_WND_SCALED >> I40IW_CM_DEFAULT_RCV_WND_SCALE;
 	ts = current_kernel_time();
 	cm_node->tcp_cntxt.loc_seq_num = ts.tv_nsec;
-	cm_node->tcp_cntxt.mss = iwdev->mss;
+	cm_node->tcp_cntxt.mss = iwdev->vsi.mss;
 
 	cm_node->iwdev = iwdev;
 	cm_node->dev = &iwdev->sc_dev;
@@ -2236,7 +2254,7 @@ static void i40iw_rem_ref_cm_node(struct
 		i40iw_dec_refcnt_listen(cm_core, cm_node->listener, 0, true);
 	} else {
 		if (!i40iw_listen_port_in_use(cm_core, cm_node->loc_port) &&
-		    cm_node->apbvt_set && cm_node->iwdev) {
+		    cm_node->apbvt_set) {
 			i40iw_manage_apbvt(cm_node->iwdev,
 					   cm_node->loc_port,
 					   I40IW_MANAGE_APBVT_DEL);
@@ -2861,7 +2879,7 @@ static struct i40iw_cm_node *i40iw_creat
 	/* create a CM connection node */
 	cm_node = i40iw_make_cm_node(cm_core, iwdev, cm_info, NULL);
 	if (!cm_node)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	/* set our node side to client (active) side */
 	cm_node->tcp_cntxt.client = 1;
 	cm_node->tcp_cntxt.rcv_wscale = I40IW_CM_DEFAULT_RCV_WND_SCALE;
@@ -2874,7 +2892,8 @@ static struct i40iw_cm_node *i40iw_creat
 						cm_node->vlan_id,
 						I40IW_CM_LISTENER_ACTIVE_STATE);
 		if (!loopback_remotelistener) {
-			i40iw_create_event(cm_node, I40IW_CM_EVENT_ABORTED);
+			i40iw_rem_ref_cm_node(cm_node);
+			return ERR_PTR(-ECONNREFUSED);
 		} else {
 			loopback_cm_info = *cm_info;
 			loopback_cm_info.loc_port = cm_info->rem_port;
@@ -2887,7 +2906,7 @@ static struct i40iw_cm_node *i40iw_creat
 								 loopback_remotelistener);
 			if (!loopback_remotenode) {
 				i40iw_rem_ref_cm_node(cm_node);
-				return NULL;
+				return ERR_PTR(-ENOMEM);
 			}
 			cm_core->stats_loopbacks++;
 			loopback_remotenode->loopbackpartner = cm_node;
@@ -3041,10 +3060,10 @@ static int i40iw_cm_close(struct i40iw_c
 /**
  * i40iw_receive_ilq - recv an ETHERNET packet, and process it
  * through CM
- * @dev: FPK dev struct
+ * @vsi: pointer to the vsi structure
  * @rbuf: receive buffer
  */
-void i40iw_receive_ilq(struct i40iw_sc_dev *dev, struct i40iw_puda_buf *rbuf)
+void i40iw_receive_ilq(struct i40iw_sc_vsi *vsi, struct i40iw_puda_buf *rbuf)
 {
 	struct i40iw_cm_node *cm_node;
 	struct i40iw_cm_listener *listener;
@@ -3052,9 +3071,11 @@ void i40iw_receive_ilq(struct i40iw_sc_d
 	struct ipv6hdr *ip6h;
 	struct tcphdr *tcph;
 	struct i40iw_cm_info cm_info;
+	struct i40iw_sc_dev *dev = vsi->dev;
 	struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
 	struct i40iw_cm_core *cm_core = &iwdev->cm_core;
 	struct vlan_ethhdr *ethh;
+	u16 vtag;
 
 	/* if vlan, then maclen = 18 else 14 */
 	iph = (struct iphdr *)rbuf->iph;
@@ -3068,7 +3089,9 @@ void i40iw_receive_ilq(struct i40iw_sc_d
 	ethh = (struct vlan_ethhdr *)rbuf->mem.va;
 
 	if (ethh->h_vlan_proto == htons(ETH_P_8021Q)) {
-		cm_info.vlan_id = ntohs(ethh->h_vlan_TCI) & VLAN_VID_MASK;
+		vtag = ntohs(ethh->h_vlan_TCI);
+		cm_info.user_pri = (vtag & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+		cm_info.vlan_id = vtag & VLAN_VID_MASK;
 		i40iw_debug(cm_core->dev,
 			    I40IW_DEBUG_CM,
 			    "%s vlan_id=%d\n",
@@ -3083,6 +3106,7 @@ void i40iw_receive_ilq(struct i40iw_sc_d
 		cm_info.loc_addr[0] = ntohl(iph->daddr);
 		cm_info.rem_addr[0] = ntohl(iph->saddr);
 		cm_info.ipv4 = true;
+		cm_info.tos = iph->tos;
 	} else {
 		ip6h = (struct ipv6hdr *)rbuf->iph;
 		i40iw_copy_ip_ntohl(cm_info.loc_addr,
@@ -3090,6 +3114,7 @@ void i40iw_receive_ilq(struct i40iw_sc_d
 		i40iw_copy_ip_ntohl(cm_info.rem_addr,
 				    ip6h->saddr.in6_u.u6_addr32);
 		cm_info.ipv4 = false;
+		cm_info.tos = (ip6h->priority << 4) | (ip6h->flow_lbl[0] >> 4);
 	}
 	cm_info.loc_port = ntohs(tcph->dest);
 	cm_info.rem_port = ntohs(tcph->source);
@@ -3309,6 +3334,8 @@ static void i40iw_cm_init_tsa_conn(struc
 
 	ctx_info->tcp_info_valid = true;
 	ctx_info->iwarp_info_valid = true;
+	ctx_info->add_to_qoslist = true;
+	ctx_info->user_pri = cm_node->user_pri;
 
 	i40iw_init_tcp_ctx(cm_node, &tcp_info, iwqp);
 	if (cm_node->snd_mark_en) {
@@ -3320,33 +3347,47 @@ static void i40iw_cm_init_tsa_conn(struc
 	cm_node->state = I40IW_CM_STATE_OFFLOADED;
 	tcp_info.tcp_state = I40IW_TCP_STATE_ESTABLISHED;
 	tcp_info.src_mac_addr_idx = iwdev->mac_ip_table_idx;
+	tcp_info.tos = cm_node->tos;
 
 	dev->iw_priv_qp_ops->qp_setctx(&iwqp->sc_qp, (u64 *)(iwqp->host_ctx.va), ctx_info);
 
 	/* once tcp_info is set, no need to do it again */
 	ctx_info->tcp_info_valid = false;
 	ctx_info->iwarp_info_valid = false;
+	ctx_info->add_to_qoslist = false;
 }
 
 /**
  * i40iw_cm_disconn - when a connection is being closed
  * @iwqp: associate qp for the connection
  */
-int i40iw_cm_disconn(struct i40iw_qp *iwqp)
+void i40iw_cm_disconn(struct i40iw_qp *iwqp)
 {
 	struct disconn_work *work;
 	struct i40iw_device *iwdev = iwqp->iwdev;
 	struct i40iw_cm_core *cm_core = &iwdev->cm_core;
+	unsigned long flags;
 
 	work = kzalloc(sizeof(*work), GFP_ATOMIC);
 	if (!work)
-		return -ENOMEM;	/* Timer will clean up */
+		return;	/* Timer will clean up */
 
+	spin_lock_irqsave(&iwdev->qptable_lock, flags);
+	if (!iwdev->qp_table[iwqp->ibqp.qp_num]) {
+		spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
+		i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_CM,
+			    "%s qp_id %d is already freed\n",
+			     __func__, iwqp->ibqp.qp_num);
+		kfree(work);
+		return;
+	}
 	i40iw_add_ref(&iwqp->ibqp);
+	spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
+
 	work->iwqp = iwqp;
 	INIT_WORK(&work->work, i40iw_disconnect_worker);
 	queue_work(cm_core->disconn_wq, &work->work);
-	return 0;
+	return;
 }
 
 /**
@@ -3432,7 +3473,7 @@ static void i40iw_cm_disconn_true(struct
 		 *terminate-handler to issue cm_disconn which can re-free
 		 *a QP even after its refcnt=0.
 		 */
-		del_timer(&iwqp->terminate_timer);
+		i40iw_terminate_del_timer(qp);
 		if (!iwqp->flush_issued) {
 			iwqp->flush_issued = 1;
 			issue_flush = 1;
@@ -3462,7 +3503,7 @@ static void i40iw_cm_disconn_true(struct
 		/* Flush the queues */
 		i40iw_flush_wqes(iwdev, iwqp);
 
-		if (qp->term_flags) {
+		if (qp->term_flags && iwqp->ibqp.event_handler) {
 			ibevent.device = iwqp->ibqp.device;
 			ibevent.event = (qp->eventtype == TERM_EVENT_QP_FATAL) ?
 					IB_EVENT_QP_FATAL : IB_EVENT_QP_ACCESS_ERR;
@@ -3571,7 +3612,7 @@ int i40iw_accept(struct iw_cm_id *cm_id,
 	iwqp->cm_node = (void *)cm_node;
 	cm_node->iwqp = iwqp;
 
-	buf_len = conn_param->private_data_len + I40IW_MAX_IETF_SIZE + MPA_ZERO_PAD_LEN;
+	buf_len = conn_param->private_data_len + I40IW_MAX_IETF_SIZE;
 
 	status = i40iw_allocate_dma_mem(dev->hw, &iwqp->ietf_mem, buf_len, 1);
 
@@ -3605,18 +3646,10 @@ int i40iw_accept(struct iw_cm_id *cm_id,
 		iwqp->lsmm_mr = ibmr;
 		if (iwqp->page)
 			iwqp->sc_qp.qp_uk.sq_base = kmap(iwqp->page);
-		if (is_remote_ne020_or_chelsio(cm_node))
-			dev->iw_priv_qp_ops->qp_send_lsmm(
-							&iwqp->sc_qp,
+		dev->iw_priv_qp_ops->qp_send_lsmm(&iwqp->sc_qp,
 							iwqp->ietf_mem.va,
 							(accept.size + conn_param->private_data_len),
 							ibmr->lkey);
-		else
-			dev->iw_priv_qp_ops->qp_send_lsmm(
-							&iwqp->sc_qp,
-							iwqp->ietf_mem.va,
-							(accept.size + conn_param->private_data_len + MPA_ZERO_PAD_LEN),
-							ibmr->lkey);
 
 	} else {
 		if (iwqp->page)
@@ -3714,6 +3747,7 @@ int i40iw_connect(struct iw_cm_id *cm_id
 	struct sockaddr_in6 *raddr6;
 	bool qhash_set = false;
 	int apbvt_set = 0;
+	int err = 0;
 	enum i40iw_status_code status;
 
 	ibqp = i40iw_get_qp(cm_id->device, conn_param->qpn);
@@ -3759,6 +3793,10 @@ int i40iw_connect(struct iw_cm_id *cm_id
 		i40iw_netdev_vlan_ipv6(cm_info.loc_addr, &cm_info.vlan_id, NULL);
 	}
 	cm_info.cm_id = cm_id;
+	cm_info.tos = cm_id->tos;
+	cm_info.user_pri = rt_tos2priority(cm_id->tos);
+	i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_DCB, "%s TOS:[%d] UP:[%d]\n",
+		    __func__, cm_id->tos, cm_info.user_pri);
 	if ((cm_info.ipv4 && (laddr->sin_addr.s_addr != raddr->sin_addr.s_addr)) ||
 	    (!cm_info.ipv4 && memcmp(laddr6->sin6_addr.in6_u.u6_addr32,
 				     raddr6->sin6_addr.in6_u.u6_addr32,
@@ -3790,8 +3828,11 @@ int i40iw_connect(struct iw_cm_id *cm_id
 				       conn_param->private_data_len,
 				       (void *)conn_param->private_data,
 				       &cm_info);
-	if (!cm_node)
-		goto err;
+
+	if (IS_ERR(cm_node)) {
+		err = PTR_ERR(cm_node);
+		goto err_out;
+	}
 
 	i40iw_record_ird_ord(cm_node, (u16)conn_param->ird, (u16)conn_param->ord);
 	if (cm_node->send_rdma0_op == SEND_RDMA_READ_ZERO &&
@@ -3805,10 +3846,12 @@ int i40iw_connect(struct iw_cm_id *cm_id
 	iwqp->cm_id = cm_id;
 	i40iw_add_ref(&iwqp->ibqp);
 
-	if (cm_node->state == I40IW_CM_STATE_SYN_SENT) {
-		if (i40iw_send_syn(cm_node, 0)) {
+	if (cm_node->state != I40IW_CM_STATE_OFFLOADED) {
+		cm_node->state = I40IW_CM_STATE_SYN_SENT;
+		err = i40iw_send_syn(cm_node, 0);
+		if (err) {
 			i40iw_rem_ref_cm_node(cm_node);
-			goto err;
+			goto err_out;
 		}
 	}
 
@@ -3820,24 +3863,25 @@ int i40iw_connect(struct iw_cm_id *cm_id
 		    cm_node->cm_id);
 	return 0;
 
-err:
-	if (cm_node) {
-		if (cm_node->ipv4)
-			i40iw_debug(cm_node->dev,
-				    I40IW_DEBUG_CM,
-				    "Api - connect() FAILED: dest addr=%pI4",
-				    cm_node->rem_addr);
-		else
-			i40iw_debug(cm_node->dev, I40IW_DEBUG_CM,
-				    "Api - connect() FAILED: dest addr=%pI6",
-				    cm_node->rem_addr);
-	}
-	i40iw_manage_qhash(iwdev,
-			   &cm_info,
-			   I40IW_QHASH_TYPE_TCP_ESTABLISHED,
-			   I40IW_QHASH_MANAGE_TYPE_DELETE,
-			   NULL,
-			   false);
+err_out:
+	if (cm_info.ipv4)
+		i40iw_debug(&iwdev->sc_dev,
+			    I40IW_DEBUG_CM,
+			    "Api - connect() FAILED: dest addr=%pI4",
+			    cm_info.rem_addr);
+	else
+		i40iw_debug(&iwdev->sc_dev,
+			    I40IW_DEBUG_CM,
+			    "Api - connect() FAILED: dest addr=%pI6",
+			    cm_info.rem_addr);
+
+	if (qhash_set)
+		i40iw_manage_qhash(iwdev,
+				   &cm_info,
+				   I40IW_QHASH_TYPE_TCP_ESTABLISHED,
+				   I40IW_QHASH_MANAGE_TYPE_DELETE,
+				   NULL,
+				   false);
 
 	if (apbvt_set && !i40iw_listen_port_in_use(&iwdev->cm_core,
 						   cm_info.loc_port))
@@ -3846,7 +3890,7 @@ err:
 				   I40IW_MANAGE_APBVT_DEL);
 	cm_id->rem_ref(cm_id);
 	iwdev->cm_core.stats_connect_errs++;
-	return -ENOMEM;
+	return err;
 }
 
 /**
@@ -3904,6 +3948,10 @@ int i40iw_create_listen(struct iw_cm_id
 
 	cm_id->provider_data = cm_listen_node;
 
+	cm_listen_node->tos = cm_id->tos;
+	cm_listen_node->user_pri = rt_tos2priority(cm_id->tos);
+	cm_info.user_pri = cm_listen_node->user_pri;
+
 	if (!cm_listen_node->reused_node) {
 		if (wildcard) {
 			if (cm_info.ipv4)
@@ -4124,3 +4172,158 @@ static void i40iw_cm_post_event(struct i
 
 	queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
 }
+
+/**
+ * i40iw_qhash_ctrl - enable/disable qhash for list
+ * @iwdev: device pointer
+ * @parent_listen_node: parent listen node
+ * @nfo: cm info node
+ * @ipaddr: Pointer to IPv4 or IPv6 address
+ * @ipv4: flag indicating IPv4 when true
+ * @ifup: flag indicating interface up when true
+ *
+ * Enables or disables the qhash for the node in the child
+ * listen list that matches ipaddr. If no matching IP was found
+ * it will allocate and add a new child listen node to the
+ * parent listen node. The listen_list_lock is assumed to be
+ * held when called.
+ */
+static void i40iw_qhash_ctrl(struct i40iw_device *iwdev,
+			     struct i40iw_cm_listener *parent_listen_node,
+			     struct i40iw_cm_info *nfo,
+			     u32 *ipaddr, bool ipv4, bool ifup)
+{
+	struct list_head *child_listen_list = &parent_listen_node->child_listen_list;
+	struct i40iw_cm_listener *child_listen_node;
+	struct list_head *pos, *tpos;
+	enum i40iw_status_code ret;
+	bool node_allocated = false;
+	enum i40iw_quad_hash_manage_type op =
+		ifup ? I40IW_QHASH_MANAGE_TYPE_ADD : I40IW_QHASH_MANAGE_TYPE_DELETE;
+
+	list_for_each_safe(pos, tpos, child_listen_list) {
+		child_listen_node =
+			list_entry(pos,
+				   struct i40iw_cm_listener,
+				   child_listen_list);
+		if (!memcmp(child_listen_node->loc_addr, ipaddr, ipv4 ? 4 : 16))
+			goto set_qhash;
+	}
+
+	/* if not found then add a child listener if interface is going up */
+	if (!ifup)
+		return;
+	child_listen_node = kzalloc(sizeof(*child_listen_node), GFP_ATOMIC);
+	if (!child_listen_node)
+		return;
+	node_allocated = true;
+	memcpy(child_listen_node, parent_listen_node, sizeof(*child_listen_node));
+
+	memcpy(child_listen_node->loc_addr, ipaddr,  ipv4 ? 4 : 16);
+
+set_qhash:
+	memcpy(nfo->loc_addr,
+	       child_listen_node->loc_addr,
+	       sizeof(nfo->loc_addr));
+	nfo->vlan_id = child_listen_node->vlan_id;
+	ret = i40iw_manage_qhash(iwdev, nfo,
+				 I40IW_QHASH_TYPE_TCP_SYN,
+				 op,
+				 NULL, false);
+	if (!ret) {
+		child_listen_node->qhash_set = ifup;
+		if (node_allocated)
+			list_add(&child_listen_node->child_listen_list,
+				 &parent_listen_node->child_listen_list);
+	} else if (node_allocated) {
+		kfree(child_listen_node);
+	}
+}
+
+/**
+ * i40iw_cm_disconnect_all - disconnect all connected qp's
+ * @iwdev: device pointer
+ */
+void i40iw_cm_disconnect_all(struct i40iw_device *iwdev)
+{
+	struct i40iw_cm_core *cm_core = &iwdev->cm_core;
+	struct list_head *list_core_temp;
+	struct list_head *list_node;
+	struct i40iw_cm_node *cm_node;
+	unsigned long flags;
+	struct list_head connected_list;
+	struct ib_qp_attr attr;
+
+	INIT_LIST_HEAD(&connected_list);
+	spin_lock_irqsave(&cm_core->ht_lock, flags);
+	list_for_each_safe(list_node, list_core_temp, &cm_core->connected_nodes) {
+		cm_node = container_of(list_node, struct i40iw_cm_node, list);
+		atomic_inc(&cm_node->ref_count);
+		list_add(&cm_node->connected_entry, &connected_list);
+	}
+	spin_unlock_irqrestore(&cm_core->ht_lock, flags);
+
+	list_for_each_safe(list_node, list_core_temp, &connected_list) {
+		cm_node = container_of(list_node, struct i40iw_cm_node, connected_entry);
+		attr.qp_state = IB_QPS_ERR;
+		i40iw_modify_qp(&cm_node->iwqp->ibqp, &attr, IB_QP_STATE, NULL);
+		i40iw_rem_ref_cm_node(cm_node);
+	}
+}
+
+/**
+ * i40iw_ifdown_notify - process an ifdown on an interface
+ * @iwdev: device pointer
+ * @ipaddr: Pointer to IPv4 or IPv6 address
+ * @ipv4: flag indicating IPv4 when true
+ * @ifup: flag indicating interface up when true
+ */
+void i40iw_if_notify(struct i40iw_device *iwdev, struct net_device *netdev,
+		     u32 *ipaddr, bool ipv4, bool ifup)
+{
+	struct i40iw_cm_core *cm_core = &iwdev->cm_core;
+	unsigned long flags;
+	struct i40iw_cm_listener *listen_node;
+	static const u32 ip_zero[4] = { 0, 0, 0, 0 };
+	struct i40iw_cm_info nfo;
+	u16 vlan_id = rdma_vlan_dev_vlan_id(netdev);
+	enum i40iw_status_code ret;
+	enum i40iw_quad_hash_manage_type op =
+		ifup ? I40IW_QHASH_MANAGE_TYPE_ADD : I40IW_QHASH_MANAGE_TYPE_DELETE;
+
+	/* Disable or enable qhash for listeners */
+	spin_lock_irqsave(&cm_core->listen_list_lock, flags);
+	list_for_each_entry(listen_node, &cm_core->listen_nodes, list) {
+		if (vlan_id == listen_node->vlan_id &&
+		    (!memcmp(listen_node->loc_addr, ipaddr, ipv4 ? 4 : 16) ||
+		    !memcmp(listen_node->loc_addr, ip_zero, ipv4 ? 4 : 16))) {
+			memcpy(nfo.loc_addr, listen_node->loc_addr,
+			       sizeof(nfo.loc_addr));
+			nfo.loc_port = listen_node->loc_port;
+			nfo.ipv4 = listen_node->ipv4;
+			nfo.vlan_id = listen_node->vlan_id;
+			nfo.user_pri = listen_node->user_pri;
+			if (!list_empty(&listen_node->child_listen_list)) {
+				i40iw_qhash_ctrl(iwdev,
+						 listen_node,
+						 &nfo,
+						 ipaddr, ipv4, ifup);
+			} else if (memcmp(listen_node->loc_addr, ip_zero,
+					  ipv4 ? 4 : 16)) {
+				ret = i40iw_manage_qhash(iwdev,
+							 &nfo,
+							 I40IW_QHASH_TYPE_TCP_SYN,
+							 op,
+							 NULL,
+							 false);
+				if (!ret)
+					listen_node->qhash_set = ifup;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
+
+	/* disconnect any connected qp's on ifdown */
+	if (!ifup)
+		i40iw_cm_disconnect_all(iwdev);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_cm.h	2017-02-12 16:03:20.000000000 -0500
@@ -56,8 +56,6 @@
 
 #define I40IW_MAX_IETF_SIZE      32
 
-#define MPA_ZERO_PAD_LEN	4
-
 /* IETF RTR MSG Fields               */
 #define IETF_PEER_TO_PEER       0x8000
 #define IETF_FLPDU_ZERO_LEN     0x4000
@@ -299,6 +297,7 @@ struct i40iw_cm_listener {
 	enum i40iw_cm_listener_state listener_state;
 	u32 reused_node;
 	u8 user_pri;
+	u8 tos;
 	u16 vlan_id;
 	bool qhash_set;
 	bool ipv4;
@@ -341,9 +340,11 @@ struct i40iw_cm_node {
 	int accept_pend;
 	struct list_head timer_entry;
 	struct list_head reset_entry;
+	struct list_head connected_entry;
 	atomic_t passive_state;
 	bool qhash_set;
 	u8 user_pri;
+	u8 tos;
 	bool ipv4;
 	bool snd_mark_en;
 	u16 lsmm_size;
@@ -368,7 +369,8 @@ struct i40iw_cm_info {
 	u32 rem_addr[4];
 	u16 vlan_id;
 	int backlog;
-	u16 user_pri;
+	u8 user_pri;
+	u8 tos;
 	bool ipv4;
 };
 
@@ -445,4 +447,7 @@ int i40iw_arp_table(struct i40iw_device
 		    u8 *mac_addr,
 		    u32 action);
 
+void i40iw_if_notify(struct i40iw_device *iwdev, struct net_device *netdev,
+		     u32 *ipaddr, bool ipv4, bool ifup);
+void i40iw_cm_disconnect_all(struct i40iw_device *iwdev);
 #endif /* I40IW_CM_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_ctrl.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_ctrl.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_ctrl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_ctrl.c	2017-02-12 16:03:20.000000000 -0500
@@ -103,6 +103,7 @@ static enum i40iw_status_code i40iw_cqp_
 		if (newtail != tail) {
 			/* SUCCESS */
 			I40IW_RING_MOVE_TAIL(cqp->sq_ring);
+			cqp->dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS]++;
 			return 0;
 		}
 		udelay(I40IW_SLEEP_COUNT);
@@ -223,17 +224,150 @@ static enum i40iw_status_code i40iw_sc_p
 }
 
 /**
+ * i40iw_fill_qos_list - Change all unknown qs handles to available ones
+ * @qs_list: list of qs_handles to be fixed with valid qs_handles
+ */
+static void i40iw_fill_qos_list(u16 *qs_list)
+{
+	u16 qshandle = qs_list[0];
+	int i;
+
+	for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
+		if (qs_list[i] == QS_HANDLE_UNKNOWN)
+			qs_list[i] = qshandle;
+		else
+			qshandle = qs_list[i];
+	}
+}
+
+/**
+ * i40iw_qp_from_entry - Given entry, get to the qp structure
+ * @entry: Points to list of qp structure
+ */
+static struct i40iw_sc_qp *i40iw_qp_from_entry(struct list_head *entry)
+{
+	if (!entry)
+		return NULL;
+
+	return (struct i40iw_sc_qp *)((char *)entry - offsetof(struct i40iw_sc_qp, list));
+}
+
+/**
+ * i40iw_get_qp - get the next qp from the list given current qp
+ * @head: Listhead of qp's
+ * @qp: current qp
+ */
+static struct i40iw_sc_qp *i40iw_get_qp(struct list_head *head, struct i40iw_sc_qp *qp)
+{
+	struct list_head *entry = NULL;
+	struct list_head *lastentry;
+
+	if (list_empty(head))
+		return NULL;
+
+	if (!qp) {
+		entry = head->next;
+	} else {
+		lastentry = &qp->list;
+		entry = (lastentry != head) ? lastentry->next : NULL;
+	}
+
+	return i40iw_qp_from_entry(entry);
+}
+
+/**
+ * i40iw_change_l2params - given the new l2 parameters, change all qp
+ * @vsi: pointer to the vsi structure
+ * @l2params: New paramaters from l2
+ */
+void i40iw_change_l2params(struct i40iw_sc_vsi *vsi, struct i40iw_l2params *l2params)
+{
+	struct i40iw_sc_dev *dev = vsi->dev;
+	struct i40iw_sc_qp *qp = NULL;
+	bool qs_handle_change = false;
+	bool mss_change = false;
+	unsigned long flags;
+	u16 qs_handle;
+	int i;
+
+	if (vsi->mss != l2params->mss) {
+		mss_change = true;
+		vsi->mss = l2params->mss;
+	}
+
+	i40iw_fill_qos_list(l2params->qs_handle_list);
+	for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
+		qs_handle = l2params->qs_handle_list[i];
+		if (vsi->qos[i].qs_handle != qs_handle)
+			qs_handle_change = true;
+		else if (!mss_change)
+			continue;       /* no MSS nor qs handle change */
+		spin_lock_irqsave(&vsi->qos[i].lock, flags);
+		qp = i40iw_get_qp(&vsi->qos[i].qplist, qp);
+		while (qp) {
+			if (mss_change)
+				i40iw_qp_mss_modify(dev, qp);
+			if (qs_handle_change) {
+				qp->qs_handle = qs_handle;
+				/* issue cqp suspend command */
+				i40iw_qp_suspend_resume(dev, qp, true);
+			}
+			qp = i40iw_get_qp(&vsi->qos[i].qplist, qp);
+		}
+		spin_unlock_irqrestore(&vsi->qos[i].lock, flags);
+		vsi->qos[i].qs_handle = qs_handle;
+	}
+}
+
+/**
+ * i40iw_qp_rem_qos - remove qp from qos lists during destroy qp
+ * @qp: qp to be removed from qos
+ */
+static void i40iw_qp_rem_qos(struct i40iw_sc_qp *qp)
+{
+	struct i40iw_sc_vsi *vsi = qp->vsi;
+	unsigned long flags;
+
+	if (!qp->on_qoslist)
+		return;
+	spin_lock_irqsave(&vsi->qos[qp->user_pri].lock, flags);
+	list_del(&qp->list);
+	spin_unlock_irqrestore(&vsi->qos[qp->user_pri].lock, flags);
+}
+
+/**
+ * i40iw_qp_add_qos - called during setctx fot qp to be added to qos
+ * @qp: qp to be added to qos
+ */
+void i40iw_qp_add_qos(struct i40iw_sc_qp *qp)
+{
+	struct i40iw_sc_vsi *vsi = qp->vsi;
+	unsigned long flags;
+
+	if (qp->on_qoslist)
+		return;
+	spin_lock_irqsave(&vsi->qos[qp->user_pri].lock, flags);
+	qp->qs_handle = vsi->qos[qp->user_pri].qs_handle;
+	list_add(&qp->list, &vsi->qos[qp->user_pri].qplist);
+	qp->on_qoslist = true;
+	spin_unlock_irqrestore(&vsi->qos[qp->user_pri].lock, flags);
+}
+
+/**
  * i40iw_sc_pd_init - initialize sc pd struct
  * @dev: sc device struct
  * @pd: sc pd ptr
  * @pd_id: pd_id for allocated pd
+ * @abi_ver: ABI version from user context, -1 if not valid
  */
 static void i40iw_sc_pd_init(struct i40iw_sc_dev *dev,
 			     struct i40iw_sc_pd *pd,
-			     u16 pd_id)
+			     u16 pd_id,
+			     int abi_ver)
 {
 	pd->size = sizeof(*pd);
 	pd->pd_id = pd_id;
+	pd->abi_ver = abi_ver;
 	pd->dev = dev;
 }
 
@@ -292,6 +426,9 @@ static enum i40iw_status_code i40iw_sc_c
 	info->dev->cqp = cqp;
 
 	I40IW_RING_INIT(cqp->sq_ring, cqp->sq_size);
+	cqp->dev->cqp_cmd_stats[OP_REQUESTED_COMMANDS] = 0;
+	cqp->dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS] = 0;
+
 	i40iw_debug(cqp->dev, I40IW_DEBUG_WQE,
 		    "%s: sq_size[%04d] hw_sq_size[%04d] sq_base[%p] sq_pa[%llxh] cqp[%p] polarity[x%04X]\n",
 		    __func__, cqp->sq_size, cqp->hw_sq_size,
@@ -302,12 +439,10 @@ static enum i40iw_status_code i40iw_sc_c
 /**
  * i40iw_sc_cqp_create - create cqp during bringup
  * @cqp: struct for cqp hw
- * @disable_pfpdus: if pfpdu to be disabled
  * @maj_err: If error, major err number
  * @min_err: If error, minor err number
  */
 static enum i40iw_status_code i40iw_sc_cqp_create(struct i40iw_sc_cqp *cqp,
-						  bool disable_pfpdus,
 						  u16 *maj_err,
 						  u16 *min_err)
 {
@@ -326,9 +461,6 @@ static enum i40iw_status_code i40iw_sc_c
 	temp = LS_64(cqp->hw_sq_size, I40IW_CQPHC_SQSIZE) |
 	       LS_64(cqp->struct_ver, I40IW_CQPHC_SVER);
 
-	if (disable_pfpdus)
-		temp |= LS_64(1, I40IW_CQPHC_DISABLE_PFPDUS);
-
 	set_64bit_val(cqp->host_ctx, 0, temp);
 	set_64bit_val(cqp->host_ctx, 8, cqp->sq_pa);
 	temp = LS_64(cqp->enabled_vf_count, I40IW_CQPHC_ENABLED_VFS) |
@@ -424,6 +556,7 @@ u64 *i40iw_sc_cqp_get_next_send_wqe(stru
 		return NULL;
 	}
 	I40IW_ATOMIC_RING_MOVE_HEAD(cqp->sq_ring, wqe_idx, ret_code);
+	cqp->dev->cqp_cmd_stats[OP_REQUESTED_COMMANDS]++;
 	if (ret_code)
 		return NULL;
 	if (!wqe_idx)
@@ -559,6 +692,8 @@ static enum i40iw_status_code i40iw_sc_c
 		      I40IW_RING_GETCURRENT_HEAD(ccq->cq_uk.cq_ring));
 	wmb(); /* write shadow area before tail */
 	I40IW_RING_MOVE_TAIL(cqp->sq_ring);
+	ccq->dev->cqp_cmd_stats[OP_COMPLETED_COMMANDS]++;
+
 	return ret_code;
 }
 
@@ -1051,6 +1186,7 @@ static enum i40iw_status_code i40iw_sc_m
 	u64 qw1 = 0;
 	u64 qw2 = 0;
 	u64 temp;
+	struct i40iw_sc_vsi *vsi = info->vsi;
 
 	wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
 	if (!wqe)
@@ -1082,7 +1218,7 @@ static enum i40iw_status_code i40iw_sc_m
 			      LS_64(info->dest_ip[2], I40IW_CQPSQ_QHASH_ADDR2) |
 			      LS_64(info->dest_ip[3], I40IW_CQPSQ_QHASH_ADDR3));
 	}
-	qw2 = LS_64(cqp->dev->qs_handle, I40IW_CQPSQ_QHASH_QS_HANDLE);
+	qw2 = LS_64(vsi->qos[info->user_pri].qs_handle, I40IW_CQPSQ_QHASH_QS_HANDLE);
 	if (info->vlan_valid)
 		qw2 |= LS_64(info->vlan_id, I40IW_CQPSQ_QHASH_VLANID);
 	set_64bit_val(wqe, 16, qw2);
@@ -2103,6 +2239,7 @@ static enum i40iw_status_code i40iw_sc_q
 	u32 offset;
 
 	qp->dev = info->pd->dev;
+	qp->vsi = info->vsi;
 	qp->sq_pa = info->sq_pa;
 	qp->rq_pa = info->rq_pa;
 	qp->hw_host_ctx_pa = info->host_ctx_pa;
@@ -2118,6 +2255,7 @@ static enum i40iw_status_code i40iw_sc_q
 					      offset);
 
 	info->qp_uk_init_info.wqe_alloc_reg = wqe_alloc_reg;
+	info->qp_uk_init_info.abi_ver = qp->pd->abi_ver;
 	ret_code = i40iw_qp_uk_init(&qp->qp_uk, &info->qp_uk_init_info);
 	if (ret_code)
 		return ret_code;
@@ -2136,10 +2274,21 @@ static enum i40iw_status_code i40iw_sc_q
 						    false);
 	i40iw_debug(qp->dev, I40IW_DEBUG_WQE, "%s: hw_sq_size[%04d] sq_ring.size[%04d]\n",
 		    __func__, qp->hw_sq_size, qp->qp_uk.sq_ring.size);
-	ret_code = i40iw_fragcnt_to_wqesize_rq(qp->qp_uk.max_rq_frag_cnt,
-					       &wqe_size);
-	if (ret_code)
-		return ret_code;
+
+	switch (qp->pd->abi_ver) {
+	case 4:
+		ret_code = i40iw_fragcnt_to_wqesize_rq(qp->qp_uk.max_rq_frag_cnt,
+						       &wqe_size);
+		if (ret_code)
+			return ret_code;
+		break;
+	case 5: /* fallthrough until next ABI version */
+	default:
+		if (qp->qp_uk.max_rq_frag_cnt > I40IW_MAX_WQ_FRAGMENT_COUNT)
+			return I40IW_ERR_INVALID_FRAG_COUNT;
+		wqe_size = I40IW_MAX_WQE_SIZE_RQ;
+		break;
+	}
 	qp->hw_rq_size = i40iw_get_encoded_wqe_size(qp->qp_uk.rq_size *
 				(wqe_size / I40IW_QP_WQE_MIN_SIZE), false);
 	i40iw_debug(qp->dev, I40IW_DEBUG_WQE,
@@ -2151,7 +2300,7 @@ static enum i40iw_status_code i40iw_sc_q
 	qp->rq_tph_en = info->rq_tph_en;
 	qp->rcv_tph_en = info->rcv_tph_en;
 	qp->xmit_tph_en = info->xmit_tph_en;
-	qp->qs_handle = qp->pd->dev->qs_handle;
+	qp->qs_handle = qp->vsi->qos[qp->user_pri].qs_handle;
 	qp->exception_lan_queue = qp->pd->dev->exception_lan_queue;
 
 	return 0;
@@ -2296,6 +2445,7 @@ static enum i40iw_status_code i40iw_sc_q
 	struct i40iw_sc_cqp *cqp;
 	u64 header;
 
+	i40iw_qp_rem_qos(qp);
 	cqp = qp->pd->dev->cqp;
 	wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
 	if (!wqe)
@@ -2443,10 +2593,20 @@ static enum i40iw_status_code i40iw_sc_q
 {
 	struct i40iwarp_offload_info *iw;
 	struct i40iw_tcp_offload_info *tcp;
+	struct i40iw_sc_vsi *vsi;
+	struct i40iw_sc_dev *dev;
 	u64 qw0, qw3, qw7 = 0;
 
 	iw = info->iwarp_info;
 	tcp = info->tcp_info;
+	vsi = qp->vsi;
+	dev = qp->dev;
+	if (info->add_to_qoslist) {
+		qp->user_pri = info->user_pri;
+		i40iw_qp_add_qos(qp);
+		i40iw_debug(qp->dev, I40IW_DEBUG_DCB, "%s qp[%d] UP[%d] qset[%d]\n",
+			    __func__, qp->qp_uk.qp_id, qp->user_pri, qp->qs_handle);
+	}
 	qw0 = LS_64(qp->qp_uk.rq_wqe_size, I40IWQPC_RQWQESIZE) |
 	      LS_64(info->err_rq_idx_valid, I40IWQPC_ERR_RQ_IDX_VALID) |
 	      LS_64(qp->rcv_tph_en, I40IWQPC_RCVTPHEN) |
@@ -2487,16 +2647,14 @@ static enum i40iw_status_code i40iw_sc_q
 		       LS_64(iw->rdmap_ver, I40IWQPC_RDMAP_VER);
 
 		qw7 |= LS_64(iw->pd_id, I40IWQPC_PDIDX);
-		set_64bit_val(qp_ctx, 144, qp->q2_pa);
+		set_64bit_val(qp_ctx,
+			      144,
+			      LS_64(qp->q2_pa, I40IWQPC_Q2ADDR) |
+			      LS_64(vsi->fcn_id, I40IWQPC_STAT_INDEX));
 		set_64bit_val(qp_ctx,
 			      152,
 			      LS_64(iw->last_byte_sent, I40IWQPC_LASTBYTESENT));
 
-		/*
-		* Hard-code IRD_SIZE to hw-limit, 128, in qpctx, i.e matching an
-		*advertisable IRD of 64
-		*/
-		iw->ird_size = I40IW_QPCTX_ENCD_MAXIRD;
 		set_64bit_val(qp_ctx,
 			      160,
 			      LS_64(iw->ord_size, I40IWQPC_ORDSIZE) |
@@ -2507,6 +2665,9 @@ static enum i40iw_status_code i40iw_sc_q
 			      LS_64(iw->bind_en, I40IWQPC_BINDEN) |
 			      LS_64(iw->fast_reg_en, I40IWQPC_FASTREGEN) |
 			      LS_64(iw->priv_mode_en, I40IWQPC_PRIVEN) |
+			      LS_64((((vsi->stats_fcn_id_alloc) &&
+				      (dev->is_pf) && (vsi->fcn_id >= I40IW_FIRST_NON_PF_STAT)) ? 1 : 0),
+				    I40IWQPC_USESTATSINSTANCE) |
 			      LS_64(1, I40IWQPC_IWARPMODE) |
 			      LS_64(iw->rcv_mark_en, I40IWQPC_RCVMARKERS) |
 			      LS_64(iw->align_hdrs, I40IWQPC_ALIGNHDRS) |
@@ -2623,7 +2784,9 @@ static enum i40iw_status_code i40iw_sc_a
 	u64 *wqe;
 	struct i40iw_sc_cqp *cqp;
 	u64 header;
+	enum i40iw_page_size page_size;
 
+	page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
 	cqp = dev->cqp;
 	wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
 	if (!wqe)
@@ -2643,7 +2806,7 @@ static enum i40iw_status_code i40iw_sc_a
 		 LS_64(1, I40IW_CQPSQ_STAG_MR) |
 		 LS_64(info->access_rights, I40IW_CQPSQ_STAG_ARIGHTS) |
 		 LS_64(info->chunk_size, I40IW_CQPSQ_STAG_LPBLSIZE) |
-		 LS_64(info->page_size, I40IW_CQPSQ_STAG_HPAGESIZE) |
+		 LS_64(page_size, I40IW_CQPSQ_STAG_HPAGESIZE) |
 		 LS_64(info->remote_access, I40IW_CQPSQ_STAG_REMACCENABLED) |
 		 LS_64(info->use_hmc_fcn_index, I40IW_CQPSQ_STAG_USEHMCFNIDX) |
 		 LS_64(info->use_pf_rid, I40IW_CQPSQ_STAG_USEPFRID) |
@@ -2679,7 +2842,9 @@ static enum i40iw_status_code i40iw_sc_m
 	u32 pble_obj_cnt;
 	bool remote_access;
 	u8 addr_type;
+	enum i40iw_page_size page_size;
 
+	page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
 	if (info->access_rights & (I40IW_ACCESS_FLAGS_REMOTEREAD_ONLY |
 				   I40IW_ACCESS_FLAGS_REMOTEWRITE_ONLY))
 		remote_access = true;
@@ -2722,7 +2887,7 @@ static enum i40iw_status_code i40iw_sc_m
 	header = LS_64(I40IW_CQP_OP_REG_MR, I40IW_CQPSQ_OPCODE) |
 		 LS_64(1, I40IW_CQPSQ_STAG_MR) |
 		 LS_64(info->chunk_size, I40IW_CQPSQ_STAG_LPBLSIZE) |
-		 LS_64(info->page_size, I40IW_CQPSQ_STAG_HPAGESIZE) |
+		 LS_64(page_size, I40IW_CQPSQ_STAG_HPAGESIZE) |
 		 LS_64(info->access_rights, I40IW_CQPSQ_STAG_ARIGHTS) |
 		 LS_64(remote_access, I40IW_CQPSQ_STAG_REMACCENABLED) |
 		 LS_64(addr_type, I40IW_CQPSQ_STAG_VABASEDTO) |
@@ -2937,7 +3102,9 @@ enum i40iw_status_code i40iw_sc_mr_fast_
 	u64 temp, header;
 	u64 *wqe;
 	u32 wqe_idx;
+	enum i40iw_page_size page_size;
 
+	page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
 	wqe = i40iw_qp_get_next_send_wqe(&qp->qp_uk, &wqe_idx, I40IW_QP_WQE_MIN_SIZE,
 					 0, info->wr_id);
 	if (!wqe)
@@ -2964,7 +3131,7 @@ enum i40iw_status_code i40iw_sc_mr_fast_
 		 LS_64(info->stag_idx, I40IWQPSQ_STAGINDEX) |
 		 LS_64(I40IWQP_OP_FAST_REGISTER, I40IWQPSQ_OPCODE) |
 		 LS_64(info->chunk_size, I40IWQPSQ_LPBLSIZE) |
-		 LS_64(info->page_size, I40IWQPSQ_HPAGESIZE) |
+		 LS_64(page_size, I40IWQPSQ_HPAGESIZE) |
 		 LS_64(info->access_rights, I40IWQPSQ_STAGRIGHTS) |
 		 LS_64(info->addr_type, I40IWQPSQ_VABASEDTO) |
 		 LS_64(info->read_fence, I40IWQPSQ_READFENCE) |
@@ -3959,7 +4126,7 @@ enum i40iw_status_code i40iw_process_cqp
 					     struct cqp_commands_info *pcmdinfo)
 {
 	enum i40iw_status_code status = 0;
-	unsigned long	flags;
+	unsigned long flags;
 
 	spin_lock_irqsave(&dev->cqp_lock, flags);
 	if (list_empty(&dev->cqp_cmd_head) && !i40iw_ring_full(dev->cqp))
@@ -3978,7 +4145,7 @@ enum i40iw_status_code i40iw_process_bh(
 {
 	enum i40iw_status_code status = 0;
 	struct cqp_commands_info *pcmdinfo;
-	unsigned long	flags;
+	unsigned long flags;
 
 	spin_lock_irqsave(&dev->cqp_lock, flags);
 	while (!list_empty(&dev->cqp_cmd_head) && !i40iw_ring_full(dev->cqp)) {
@@ -4055,7 +4222,6 @@ static int i40iw_bld_terminate_hdr(struc
 	u16 ddp_seg_len;
 	int copy_len = 0;
 	u8 is_tagged = 0;
-	enum i40iw_flush_opcode flush_code = FLUSH_INVALID;
 	u32 opcode;
 	struct i40iw_terminate_hdr *termhdr;
 
@@ -4228,9 +4394,6 @@ static int i40iw_bld_terminate_hdr(struc
 	if (copy_len)
 		memcpy(termhdr + 1, pkt, copy_len);
 
-	if (flush_code && !info->in_rdrsp_wr)
-		qp->sq_flush = (info->sq) ? true : false;
-
 	return sizeof(struct i40iw_terminate_hdr) + copy_len;
 }
 
@@ -4321,286 +4484,370 @@ void i40iw_terminate_received(struct i40
 }
 
 /**
- * i40iw_hw_stat_init - Initiliaze HW stats table
- * @devstat: pestat struct
+ * i40iw_sc_vsi_init - Initialize virtual device
+ * @vsi: pointer to the vsi structure
+ * @info: parameters to initialize vsi
+ **/
+void i40iw_sc_vsi_init(struct i40iw_sc_vsi *vsi, struct i40iw_vsi_init_info *info)
+{
+	int i;
+
+	vsi->dev = info->dev;
+	vsi->back_vsi = info->back_vsi;
+	vsi->mss = info->params->mss;
+	i40iw_fill_qos_list(info->params->qs_handle_list);
+
+	for (i = 0; i < I40IW_MAX_USER_PRIORITY; i++) {
+		vsi->qos[i].qs_handle =
+			info->params->qs_handle_list[i];
+			i40iw_debug(vsi->dev, I40IW_DEBUG_DCB, "qset[%d]: %d\n", i, vsi->qos[i].qs_handle);
+		spin_lock_init(&vsi->qos[i].lock);
+		INIT_LIST_HEAD(&vsi->qos[i].qplist);
+	}
+}
+
+/**
+ * i40iw_hw_stats_init - Initiliaze HW stats table
+ * @stats: pestat struct
  * @fcn_idx: PCI fn id
- * @hw: PF i40iw_hw structure.
  * @is_pf: Is it a PF?
  *
- * Populate the HW stat table with register offset addr for each
- * stat. And start the perioidic stats timer.
+ * Populate the HW stats table with register offset addr for each
+ * stats. And start the perioidic stats timer.
  */
-static void i40iw_hw_stat_init(struct i40iw_dev_pestat *devstat,
-			       u8 fcn_idx,
-			       struct i40iw_hw *hw, bool is_pf)
+void i40iw_hw_stats_init(struct i40iw_vsi_pestat *stats, u8 fcn_idx, bool is_pf)
 {
-	u32 stat_reg_offset;
-	u32 stat_index;
-	struct i40iw_dev_hw_stat_offsets *stat_table =
-		&devstat->hw_stat_offsets;
-	struct i40iw_dev_hw_stats *last_rd_stats = &devstat->last_read_hw_stats;
-
-	devstat->hw = hw;
+	u32 stats_reg_offset;
+	u32 stats_index;
+	struct i40iw_dev_hw_stats_offsets *stats_table =
+		&stats->hw_stats_offsets;
+	struct i40iw_dev_hw_stats *last_rd_stats = &stats->last_read_hw_stats;
 
 	if (is_pf) {
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP4RXDISCARD] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXDISCARD] =
 				I40E_GLPES_PFIP4RXDISCARD(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP4RXTRUNC] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXTRUNC] =
 				I40E_GLPES_PFIP4RXTRUNC(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP4TXNOROUTE] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4TXNOROUTE] =
 				I40E_GLPES_PFIP4TXNOROUTE(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP6RXDISCARD] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXDISCARD] =
 				I40E_GLPES_PFIP6RXDISCARD(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP6RXTRUNC] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXTRUNC] =
 				I40E_GLPES_PFIP6RXTRUNC(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP6TXNOROUTE] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6TXNOROUTE] =
 				I40E_GLPES_PFIP6TXNOROUTE(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_TCPRTXSEG] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRTXSEG] =
 				I40E_GLPES_PFTCPRTXSEG(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_TCPRXOPTERR] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXOPTERR] =
 				I40E_GLPES_PFTCPRXOPTERR(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_TCPRXPROTOERR] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXPROTOERR] =
 				I40E_GLPES_PFTCPRXPROTOERR(fcn_idx);
 
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXOCTS] =
 				I40E_GLPES_PFIP4RXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXPKTS] =
 				I40E_GLPES_PFIP4RXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXFRAGS] =
 				I40E_GLPES_PFIP4RXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXMCPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXMCPKTS] =
 				I40E_GLPES_PFIP4RXMCPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXOCTS] =
 				I40E_GLPES_PFIP4TXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXPKTS] =
 				I40E_GLPES_PFIP4TXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXFRAGS] =
 				I40E_GLPES_PFIP4TXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXMCPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXMCPKTS] =
 				I40E_GLPES_PFIP4TXMCPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXOCTS] =
 				I40E_GLPES_PFIP6RXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXPKTS] =
 				I40E_GLPES_PFIP6RXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXFRAGS] =
 				I40E_GLPES_PFIP6RXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXMCPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXMCPKTS] =
 				I40E_GLPES_PFIP6RXMCPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXOCTS] =
 				I40E_GLPES_PFIP6TXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
 				I40E_GLPES_PFIP6TXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
 				I40E_GLPES_PFIP6TXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXFRAGS] =
 				I40E_GLPES_PFIP6TXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_TCPRXSEGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPRXSEGS] =
 				I40E_GLPES_PFTCPRXSEGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_TCPTXSEG] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPTXSEG] =
 				I40E_GLPES_PFTCPTXSEGLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMARXRDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXRDS] =
 				I40E_GLPES_PFRDMARXRDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMARXSNDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXSNDS] =
 				I40E_GLPES_PFRDMARXSNDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMARXWRS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXWRS] =
 				I40E_GLPES_PFRDMARXWRSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMATXRDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXRDS] =
 				I40E_GLPES_PFRDMATXRDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMATXSNDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXSNDS] =
 				I40E_GLPES_PFRDMATXSNDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMATXWRS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXWRS] =
 				I40E_GLPES_PFRDMATXWRSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMAVBND] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVBND] =
 				I40E_GLPES_PFRDMAVBNDLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMAVINV] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVINV] =
 				I40E_GLPES_PFRDMAVINVLO(fcn_idx);
 	} else {
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP4RXDISCARD] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXDISCARD] =
 				I40E_GLPES_VFIP4RXDISCARD(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP4RXTRUNC] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4RXTRUNC] =
 				I40E_GLPES_VFIP4RXTRUNC(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP4TXNOROUTE] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP4TXNOROUTE] =
 				I40E_GLPES_VFIP4TXNOROUTE(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP6RXDISCARD] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXDISCARD] =
 				I40E_GLPES_VFIP6RXDISCARD(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP6RXTRUNC] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6RXTRUNC] =
 				I40E_GLPES_VFIP6RXTRUNC(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_IP6TXNOROUTE] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_IP6TXNOROUTE] =
 				I40E_GLPES_VFIP6TXNOROUTE(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_TCPRTXSEG] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRTXSEG] =
 				I40E_GLPES_VFTCPRTXSEG(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_TCPRXOPTERR] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXOPTERR] =
 				I40E_GLPES_VFTCPRXOPTERR(fcn_idx);
-		stat_table->stat_offset_32[I40IW_HW_STAT_INDEX_TCPRXPROTOERR] =
+		stats_table->stats_offset_32[I40IW_HW_STAT_INDEX_TCPRXPROTOERR] =
 				I40E_GLPES_VFTCPRXPROTOERR(fcn_idx);
 
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXOCTS] =
 				I40E_GLPES_VFIP4RXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXPKTS] =
 				I40E_GLPES_VFIP4RXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXFRAGS] =
 				I40E_GLPES_VFIP4RXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4RXMCPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4RXMCPKTS] =
 				I40E_GLPES_VFIP4RXMCPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXOCTS] =
 				I40E_GLPES_VFIP4TXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXPKTS] =
 				I40E_GLPES_VFIP4TXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXFRAGS] =
 				I40E_GLPES_VFIP4TXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP4TXMCPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP4TXMCPKTS] =
 				I40E_GLPES_VFIP4TXMCPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXOCTS] =
 				I40E_GLPES_VFIP6RXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXPKTS] =
 				I40E_GLPES_VFIP6RXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXFRAGS] =
 				I40E_GLPES_VFIP6RXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6RXMCPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6RXMCPKTS] =
 				I40E_GLPES_VFIP6RXMCPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXOCTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXOCTS] =
 				I40E_GLPES_VFIP6TXOCTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
 				I40E_GLPES_VFIP6TXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXPKTS] =
 				I40E_GLPES_VFIP6TXPKTSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_IP6TXFRAGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_IP6TXFRAGS] =
 				I40E_GLPES_VFIP6TXFRAGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_TCPRXSEGS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPRXSEGS] =
 				I40E_GLPES_VFTCPRXSEGSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_TCPTXSEG] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_TCPTXSEG] =
 				I40E_GLPES_VFTCPTXSEGLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMARXRDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXRDS] =
 				I40E_GLPES_VFRDMARXRDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMARXSNDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXSNDS] =
 				I40E_GLPES_VFRDMARXSNDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMARXWRS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMARXWRS] =
 				I40E_GLPES_VFRDMARXWRSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMATXRDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXRDS] =
 				I40E_GLPES_VFRDMATXRDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMATXSNDS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXSNDS] =
 				I40E_GLPES_VFRDMATXSNDSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMATXWRS] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMATXWRS] =
 				I40E_GLPES_VFRDMATXWRSLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMAVBND] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVBND] =
 				I40E_GLPES_VFRDMAVBNDLO(fcn_idx);
-		stat_table->stat_offset_64[I40IW_HW_STAT_INDEX_RDMAVINV] =
+		stats_table->stats_offset_64[I40IW_HW_STAT_INDEX_RDMAVINV] =
 				I40E_GLPES_VFRDMAVINVLO(fcn_idx);
 	}
 
-	for (stat_index = 0; stat_index < I40IW_HW_STAT_INDEX_MAX_64;
-	     stat_index++) {
-		stat_reg_offset = stat_table->stat_offset_64[stat_index];
-		last_rd_stats->stat_value_64[stat_index] =
-			readq(devstat->hw->hw_addr + stat_reg_offset);
+	for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_64;
+	     stats_index++) {
+		stats_reg_offset = stats_table->stats_offset_64[stats_index];
+		last_rd_stats->stats_value_64[stats_index] =
+			readq(stats->hw->hw_addr + stats_reg_offset);
 	}
 
-	for (stat_index = 0; stat_index < I40IW_HW_STAT_INDEX_MAX_32;
-	     stat_index++) {
-		stat_reg_offset = stat_table->stat_offset_32[stat_index];
-		last_rd_stats->stat_value_32[stat_index] =
-			i40iw_rd32(devstat->hw, stat_reg_offset);
+	for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_32;
+	     stats_index++) {
+		stats_reg_offset = stats_table->stats_offset_32[stats_index];
+		last_rd_stats->stats_value_32[stats_index] =
+			i40iw_rd32(stats->hw, stats_reg_offset);
 	}
 }
 
 /**
- * i40iw_hw_stat_read_32 - Read 32-bit HW stat counters and accommodates for roll-overs.
- * @devstat: pestat struct
- * @index: index in HW stat table which contains offset reg-addr
- * @value: hw stat value
+ * i40iw_hw_stats_read_32 - Read 32-bit HW stats counters and accommodates for roll-overs.
+ * @stat: pestat struct
+ * @index: index in HW stats table which contains offset reg-addr
+ * @value: hw stats value
  */
-static void i40iw_hw_stat_read_32(struct i40iw_dev_pestat *devstat,
-				  enum i40iw_hw_stat_index_32b index,
-				  u64 *value)
+void i40iw_hw_stats_read_32(struct i40iw_vsi_pestat *stats,
+			    enum i40iw_hw_stats_index_32b index,
+			    u64 *value)
 {
-	struct i40iw_dev_hw_stat_offsets *stat_table =
-		&devstat->hw_stat_offsets;
-	struct i40iw_dev_hw_stats *last_rd_stats = &devstat->last_read_hw_stats;
-	struct i40iw_dev_hw_stats *hw_stats = &devstat->hw_stats;
-	u64 new_stat_value = 0;
-	u32 stat_reg_offset = stat_table->stat_offset_32[index];
+	struct i40iw_dev_hw_stats_offsets *stats_table =
+		&stats->hw_stats_offsets;
+	struct i40iw_dev_hw_stats *last_rd_stats = &stats->last_read_hw_stats;
+	struct i40iw_dev_hw_stats *hw_stats = &stats->hw_stats;
+	u64 new_stats_value = 0;
+	u32 stats_reg_offset = stats_table->stats_offset_32[index];
 
-	new_stat_value = i40iw_rd32(devstat->hw, stat_reg_offset);
+	new_stats_value = i40iw_rd32(stats->hw, stats_reg_offset);
 	/*roll-over case */
-	if (new_stat_value < last_rd_stats->stat_value_32[index])
-		hw_stats->stat_value_32[index] += new_stat_value;
+	if (new_stats_value < last_rd_stats->stats_value_32[index])
+		hw_stats->stats_value_32[index] += new_stats_value;
 	else
-		hw_stats->stat_value_32[index] +=
-			new_stat_value - last_rd_stats->stat_value_32[index];
-	last_rd_stats->stat_value_32[index] = new_stat_value;
-	*value = hw_stats->stat_value_32[index];
+		hw_stats->stats_value_32[index] +=
+			new_stats_value - last_rd_stats->stats_value_32[index];
+	last_rd_stats->stats_value_32[index] = new_stats_value;
+	*value = hw_stats->stats_value_32[index];
 }
 
 /**
- * i40iw_hw_stat_read_64 - Read HW stat counters (greater than 32-bit) and accommodates for roll-overs.
- * @devstat: pestat struct
- * @index: index in HW stat table which contains offset reg-addr
- * @value: hw stat value
+ * i40iw_hw_stats_read_64 - Read HW stats counters (greater than 32-bit) and accommodates for roll-overs.
+ * @stats: pestat struct
+ * @index: index in HW stats table which contains offset reg-addr
+ * @value: hw stats value
  */
-static void i40iw_hw_stat_read_64(struct i40iw_dev_pestat *devstat,
-				  enum i40iw_hw_stat_index_64b index,
-				  u64 *value)
+void i40iw_hw_stats_read_64(struct i40iw_vsi_pestat *stats,
+			    enum i40iw_hw_stats_index_64b index,
+			    u64 *value)
 {
-	struct i40iw_dev_hw_stat_offsets *stat_table =
-		&devstat->hw_stat_offsets;
-	struct i40iw_dev_hw_stats *last_rd_stats = &devstat->last_read_hw_stats;
-	struct i40iw_dev_hw_stats *hw_stats = &devstat->hw_stats;
-	u64 new_stat_value = 0;
-	u32 stat_reg_offset = stat_table->stat_offset_64[index];
+	struct i40iw_dev_hw_stats_offsets *stats_table =
+		&stats->hw_stats_offsets;
+	struct i40iw_dev_hw_stats *last_rd_stats = &stats->last_read_hw_stats;
+	struct i40iw_dev_hw_stats *hw_stats = &stats->hw_stats;
+	u64 new_stats_value = 0;
+	u32 stats_reg_offset = stats_table->stats_offset_64[index];
 
-	new_stat_value = readq(devstat->hw->hw_addr + stat_reg_offset);
+	new_stats_value = readq(stats->hw->hw_addr + stats_reg_offset);
 	/*roll-over case */
-	if (new_stat_value < last_rd_stats->stat_value_64[index])
-		hw_stats->stat_value_64[index] += new_stat_value;
+	if (new_stats_value < last_rd_stats->stats_value_64[index])
+		hw_stats->stats_value_64[index] += new_stats_value;
 	else
-		hw_stats->stat_value_64[index] +=
-			new_stat_value - last_rd_stats->stat_value_64[index];
-	last_rd_stats->stat_value_64[index] = new_stat_value;
-	*value = hw_stats->stat_value_64[index];
+		hw_stats->stats_value_64[index] +=
+			new_stats_value - last_rd_stats->stats_value_64[index];
+	last_rd_stats->stats_value_64[index] = new_stats_value;
+	*value = hw_stats->stats_value_64[index];
 }
 
 /**
- * i40iw_hw_stat_read_all - read all HW stat counters
- * @devstat: pestat struct
- * @stat_values: hw stats structure
+ * i40iw_hw_stats_read_all - read all HW stat counters
+ * @stats: pestat struct
+ * @stats_values: hw stats structure
  *
  * Read all the HW stat counters and populates hw_stats structure
- * of passed-in dev's pestat as well as copy created in stat_values.
+ * of passed-in vsi's pestat as well as copy created in stat_values.
  */
-static void i40iw_hw_stat_read_all(struct i40iw_dev_pestat *devstat,
-				   struct i40iw_dev_hw_stats *stat_values)
+void i40iw_hw_stats_read_all(struct i40iw_vsi_pestat *stats,
+			     struct i40iw_dev_hw_stats *stats_values)
 {
-	u32 stat_index;
+	u32 stats_index;
+	unsigned long flags;
 
-	for (stat_index = 0; stat_index < I40IW_HW_STAT_INDEX_MAX_32;
-	     stat_index++)
-		i40iw_hw_stat_read_32(devstat, stat_index,
-				      &stat_values->stat_value_32[stat_index]);
-	for (stat_index = 0; stat_index < I40IW_HW_STAT_INDEX_MAX_64;
-	     stat_index++)
-		i40iw_hw_stat_read_64(devstat, stat_index,
-				      &stat_values->stat_value_64[stat_index]);
+	spin_lock_irqsave(&stats->lock, flags);
+
+	for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_32;
+	     stats_index++)
+		i40iw_hw_stats_read_32(stats, stats_index,
+				       &stats_values->stats_value_32[stats_index]);
+	for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_64;
+	     stats_index++)
+		i40iw_hw_stats_read_64(stats, stats_index,
+				       &stats_values->stats_value_64[stats_index]);
+	spin_unlock_irqrestore(&stats->lock, flags);
 }
 
 /**
- * i40iw_hw_stat_refresh_all - Update all HW stat structs
- * @devstat: pestat struct
- * @stat_values: hw stats structure
+ * i40iw_hw_stats_refresh_all - Update all HW stats structs
+ * @stats: pestat struct
  *
- * Read all the HW stat counters to refresh values in hw_stats structure
+ * Read all the HW stats counters to refresh values in hw_stats structure
  * of passed-in dev's pestat
  */
-static void i40iw_hw_stat_refresh_all(struct i40iw_dev_pestat *devstat)
+void i40iw_hw_stats_refresh_all(struct i40iw_vsi_pestat *stats)
 {
-	u64 stat_value;
-	u32 stat_index;
+	u64 stats_value;
+	u32 stats_index;
+	unsigned long flags;
 
-	for (stat_index = 0; stat_index < I40IW_HW_STAT_INDEX_MAX_32;
-	     stat_index++)
-		i40iw_hw_stat_read_32(devstat, stat_index, &stat_value);
-	for (stat_index = 0; stat_index < I40IW_HW_STAT_INDEX_MAX_64;
-	     stat_index++)
-		i40iw_hw_stat_read_64(devstat, stat_index, &stat_value);
+	spin_lock_irqsave(&stats->lock, flags);
+
+	for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_32;
+	     stats_index++)
+		i40iw_hw_stats_read_32(stats, stats_index, &stats_value);
+	for (stats_index = 0; stats_index < I40IW_HW_STAT_INDEX_MAX_64;
+	     stats_index++)
+		i40iw_hw_stats_read_64(stats, stats_index, &stats_value);
+	spin_unlock_irqrestore(&stats->lock, flags);
+}
+
+/**
+ * i40iw_get_fcn_id - Return the function id
+ * @dev: pointer to the device
+ */
+static u8 i40iw_get_fcn_id(struct i40iw_sc_dev *dev)
+{
+	u8 fcn_id = I40IW_INVALID_FCN_ID;
+	u8 i;
+
+	for (i = I40IW_FIRST_NON_PF_STAT; i < I40IW_MAX_STATS_COUNT; i++)
+		if (!dev->fcn_id_array[i]) {
+			fcn_id = i;
+			dev->fcn_id_array[i] = true;
+			break;
+		}
+	return fcn_id;
+}
+
+/**
+ * i40iw_vsi_stats_init - Initialize the vsi statistics
+ * @vsi: pointer to the vsi structure
+ * @info: The info structure used for initialization
+ */
+enum i40iw_status_code i40iw_vsi_stats_init(struct i40iw_sc_vsi *vsi, struct i40iw_vsi_stats_info *info)
+{
+	u8 fcn_id = info->fcn_id;
+
+	if (info->alloc_fcn_id)
+		fcn_id = i40iw_get_fcn_id(vsi->dev);
+
+	if (fcn_id == I40IW_INVALID_FCN_ID)
+		return I40IW_ERR_NOT_READY;
+
+	vsi->pestat = info->pestat;
+	vsi->pestat->hw = vsi->dev->hw;
+
+	if (info->stats_initialize) {
+		i40iw_hw_stats_init(vsi->pestat, fcn_id, true);
+		spin_lock_init(&vsi->pestat->lock);
+		i40iw_hw_stats_start_timer(vsi);
+	}
+	vsi->stats_fcn_id_alloc = info->alloc_fcn_id;
+	vsi->fcn_id = fcn_id;
+	return I40IW_SUCCESS;
+}
+
+/**
+ * i40iw_vsi_stats_free - Free the vsi stats
+ * @vsi: pointer to the vsi structure
+ */
+void i40iw_vsi_stats_free(struct i40iw_sc_vsi *vsi)
+{
+	u8 fcn_id = vsi->fcn_id;
+
+	if ((vsi->stats_fcn_id_alloc) && (fcn_id != I40IW_INVALID_FCN_ID))
+		vsi->dev->fcn_id_array[fcn_id] = false;
+	i40iw_hw_stats_stop_timer(vsi);
 }
 
 static struct i40iw_cqp_ops iw_cqp_ops = {
@@ -4711,24 +4958,6 @@ static struct i40iw_hmc_ops iw_hmc_ops =
 	NULL
 };
 
-static const struct i40iw_device_pestat_ops iw_device_pestat_ops = {
-	i40iw_hw_stat_init,
-	i40iw_hw_stat_read_32,
-	i40iw_hw_stat_read_64,
-	i40iw_hw_stat_read_all,
-	i40iw_hw_stat_refresh_all
-};
-
-/**
- * i40iw_device_init_pestat - Initialize the pestat structure
- * @dev: pestat struct
- */
-enum i40iw_status_code i40iw_device_init_pestat(struct i40iw_dev_pestat *devstat)
-{
-	devstat->ops = iw_device_pestat_ops;
-	return 0;
-}
-
 /**
  * i40iw_device_init - Initialize IWARP device
  * @dev: IWARP device pointer
@@ -4750,14 +4979,7 @@ enum i40iw_status_code i40iw_device_init
 
 	dev->debug_mask = info->debug_mask;
 
-	ret_code = i40iw_device_init_pestat(&dev->dev_pestat);
-	if (ret_code) {
-		i40iw_debug(dev, I40IW_DEBUG_DEV,
-			    "%s: i40iw_device_init_pestat failed\n", __func__);
-		return ret_code;
-	}
 	dev->hmc_fn_id = info->hmc_fn_id;
-	dev->qs_handle = info->qs_handle;
 	dev->exception_lan_queue = info->exception_lan_queue;
 	dev->is_pf = info->is_pf;
 
@@ -4770,15 +4992,10 @@ enum i40iw_status_code i40iw_device_init
 	dev->hw = info->hw;
 	dev->hw->hw_addr = info->bar0;
 
-	val = i40iw_rd32(dev->hw, I40E_GLPCI_DREVID);
-	dev->hw_rev = (u8)RS_32(val, I40E_GLPCI_DREVID_DEFAULT_REVID);
-
 	if (dev->is_pf) {
-		dev->dev_pestat.ops.iw_hw_stat_init(&dev->dev_pestat,
-			dev->hmc_fn_id, dev->hw, true);
-		spin_lock_init(&dev->dev_pestat.stats_lock);
-		/*start the periodic stats_timer */
-		i40iw_hw_stats_start_timer(dev);
+		val = i40iw_rd32(dev->hw, I40E_GLPCI_DREVID);
+		dev->hw_rev = (u8)RS_32(val, I40E_GLPCI_DREVID_DEFAULT_REVID);
+
 		val = i40iw_rd32(dev->hw, I40E_GLPCI_LBARCTRL);
 		db_size = (u8)RS_32(val, I40E_GLPCI_LBARCTRL_PE_DB_SIZE);
 		if ((db_size != I40IW_PE_DB_SIZE_4M) &&
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_d.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_d.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_d.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_d.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,8 @@
 #ifndef I40IW_D_H
 #define I40IW_D_H
 
+#define I40IW_FIRST_USER_QP_ID  2
+
 #define I40IW_DB_ADDR_OFFSET    (4 * 1024 * 1024 - 64 * 1024)
 #define I40IW_VF_DB_ADDR_OFFSET (64 * 1024)
 
@@ -67,6 +69,9 @@
 #define I40IW_STAG_TYPE_NONSHARED 1
 
 #define I40IW_MAX_USER_PRIORITY 8
+#define I40IW_MAX_STATS_COUNT 16
+#define I40IW_FIRST_NON_PF_STAT	4
+
 
 #define LS_64_1(val, bits)      ((u64)(uintptr_t)val << bits)
 #define RS_64_1(val, bits)      ((u64)(uintptr_t)val >> bits)
@@ -74,6 +79,8 @@
 #define RS_32_1(val, bits)      (u32)(val >> bits)
 #define I40E_HI_DWORD(x)        ((u32)((((x) >> 16) >> 16) & 0xFFFFFFFF))
 
+#define QS_HANDLE_UNKNOWN       0xffff
+
 #define LS_64(val, field) (((u64)val << field ## _SHIFT) & (field ## _MASK))
 
 #define RS_64(val, field) ((u64)(val & field ## _MASK) >> field ## _SHIFT)
@@ -1199,8 +1206,11 @@
 #define I40IWQPC_RXCQNUM_SHIFT 32
 #define I40IWQPC_RXCQNUM_MASK (0x1ffffULL << I40IWQPC_RXCQNUM_SHIFT)
 
-#define I40IWQPC_Q2ADDR_SHIFT I40IW_CQPHC_QPCTX_SHIFT
-#define I40IWQPC_Q2ADDR_MASK I40IW_CQPHC_QPCTX_MASK
+#define I40IWQPC_STAT_INDEX_SHIFT 0
+#define I40IWQPC_STAT_INDEX_MASK (0x1fULL << I40IWQPC_STAT_INDEX_SHIFT)
+
+#define I40IWQPC_Q2ADDR_SHIFT 0
+#define I40IWQPC_Q2ADDR_MASK (0xffffffffffffff00ULL << I40IWQPC_Q2ADDR_SHIFT)
 
 #define I40IWQPC_LASTBYTESENT_SHIFT 0
 #define I40IWQPC_LASTBYTESENT_MASK (0xffUL << I40IWQPC_LASTBYTESENT_SHIFT)
@@ -1232,11 +1242,8 @@
 #define I40IWQPC_PRIVEN_SHIFT 25
 #define I40IWQPC_PRIVEN_MASK (1UL << I40IWQPC_PRIVEN_SHIFT)
 
-#define I40IWQPC_LSMMPRESENT_SHIFT 26
-#define I40IWQPC_LSMMPRESENT_MASK (1UL << I40IWQPC_LSMMPRESENT_SHIFT)
-
-#define I40IWQPC_ADJUSTFORLSMM_SHIFT 27
-#define I40IWQPC_ADJUSTFORLSMM_MASK (1UL << I40IWQPC_ADJUSTFORLSMM_SHIFT)
+#define I40IWQPC_USESTATSINSTANCE_SHIFT 26
+#define I40IWQPC_USESTATSINSTANCE_MASK (1UL << I40IWQPC_USESTATSINSTANCE_SHIFT)
 
 #define I40IWQPC_IWARPMODE_SHIFT 28
 #define I40IWQPC_IWARPMODE_MASK (1UL << I40IWQPC_IWARPMODE_SHIFT)
@@ -1713,6 +1720,8 @@ enum i40iw_alignment {
 #define OP_MANAGE_VF_PBLE_BP                    28
 #define OP_QUERY_FPM_VALUES                     29
 #define OP_COMMIT_FPM_VALUES                    30
-#define OP_SIZE_CQP_STAT_ARRAY                  31
+#define OP_REQUESTED_COMMANDS                   31
+#define OP_COMPLETED_COMMANDS                   32
+#define OP_SIZE_CQP_STAT_ARRAY                  33
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw.h	2017-02-12 16:03:20.000000000 -0500
@@ -112,9 +112,12 @@
 #define I40IW_DRV_OPT_MCAST_LOGPORT_MAP    0x00000800
 
 #define IW_HMC_OBJ_TYPE_NUM ARRAY_SIZE(iw_hmc_obj_types)
-#define IW_CFG_FPM_QP_COUNT		32768
-#define I40IW_MAX_PAGES_PER_FMR		512
-#define I40IW_MIN_PAGES_PER_FMR		1
+#define IW_CFG_FPM_QP_COUNT               32768
+#define I40IW_MAX_PAGES_PER_FMR           512
+#define I40IW_MIN_PAGES_PER_FMR           1
+#define I40IW_CQP_COMPL_RQ_WQE_FLUSHED    2
+#define I40IW_CQP_COMPL_SQ_WQE_FLUSHED    3
+#define I40IW_CQP_COMPL_RQ_SQ_WQE_FLUSHED 4
 
 #define I40IW_MTU_TO_MSS		40
 #define I40IW_DEFAULT_MSS		1460
@@ -210,6 +213,12 @@ struct i40iw_msix_vector {
 	u32 ceq_id;
 };
 
+struct l2params_work {
+	struct work_struct work;
+	struct i40iw_device *iwdev;
+	struct i40iw_l2params l2params;
+};
+
 #define I40IW_MSIX_TABLE_SIZE   65
 
 struct virtchnl_work {
@@ -227,6 +236,7 @@ struct i40iw_device {
 	struct net_device *netdev;
 	wait_queue_head_t vchnl_waitq;
 	struct i40iw_sc_dev sc_dev;
+	struct i40iw_sc_vsi vsi;
 	struct i40iw_handler *hdl;
 	struct i40e_info *ldev;
 	struct i40e_client *client;
@@ -280,7 +290,6 @@ struct i40iw_device {
 	u32 sd_type;
 	struct workqueue_struct *param_wq;
 	atomic_t params_busy;
-	u32 mss;
 	enum init_completion_state init_state;
 	u16 mac_ip_table_idx;
 	atomic_t vchnl_msgs;
@@ -297,6 +306,14 @@ struct i40iw_device {
 	u32 mr_stagmask;
 	u32 mpa_version;
 	bool dcb;
+	bool closing;
+	bool reset;
+	u32 used_pds;
+	u32 used_cqs;
+	u32 used_mrs;
+	u32 used_qps;
+	wait_queue_head_t close_wq;
+	atomic64_t use_count;
 };
 
 struct i40iw_ib_device {
@@ -498,7 +515,7 @@ u32 i40iw_initialize_hw_resources(struct
 
 int i40iw_register_rdma_device(struct i40iw_device *iwdev);
 void i40iw_port_ibevent(struct i40iw_device *iwdev);
-int i40iw_cm_disconn(struct i40iw_qp *);
+void i40iw_cm_disconn(struct i40iw_qp *iwqp);
 void i40iw_cm_disconn_worker(void *);
 int mini_cm_recv_pkt(struct i40iw_cm_core *, struct i40iw_device *,
 		     struct sk_buff *);
@@ -508,20 +525,26 @@ enum i40iw_status_code i40iw_handle_cqp_
 enum i40iw_status_code i40iw_add_mac_addr(struct i40iw_device *iwdev,
 					  u8 *mac_addr, u8 *mac_index);
 int i40iw_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *);
+void i40iw_cq_wq_destroy(struct i40iw_device *iwdev, struct i40iw_sc_cq *cq);
 
 void i40iw_rem_pdusecount(struct i40iw_pd *iwpd, struct i40iw_device *iwdev);
 void i40iw_add_pdusecount(struct i40iw_pd *iwpd);
+void i40iw_rem_devusecount(struct i40iw_device *iwdev);
+void i40iw_add_devusecount(struct i40iw_device *iwdev);
 void i40iw_hw_modify_qp(struct i40iw_device *iwdev, struct i40iw_qp *iwqp,
 			struct i40iw_modify_qp_info *info, bool wait);
 
+void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev,
+			     struct i40iw_sc_qp *qp,
+			     bool suspend);
 enum i40iw_status_code i40iw_manage_qhash(struct i40iw_device *iwdev,
 					  struct i40iw_cm_info *cminfo,
 					  enum i40iw_quad_entry_type etype,
 					  enum i40iw_quad_hash_manage_type mtype,
 					  void *cmnode,
 					  bool wait);
-void i40iw_receive_ilq(struct i40iw_sc_dev *dev, struct i40iw_puda_buf *rbuf);
-void i40iw_free_sqbuf(struct i40iw_sc_dev *dev, void *bufp);
+void i40iw_receive_ilq(struct i40iw_sc_vsi *vsi, struct i40iw_puda_buf *rbuf);
+void i40iw_free_sqbuf(struct i40iw_sc_vsi *vsi, void *bufp);
 void i40iw_free_qp_resources(struct i40iw_device *iwdev,
 			     struct i40iw_qp *iwqp,
 			     u32 qp_num);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_hw.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_hw.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,7 @@ u32 i40iw_initialize_hw_resources(struct
 	max_mr = iwdev->sc_dev.hmc_info->hmc_obj[I40IW_HMC_IW_MR].cnt;
 	arp_table_size = iwdev->sc_dev.hmc_info->hmc_obj[I40IW_HMC_IW_ARP].cnt;
 	iwdev->max_cqe = 0xFFFFF;
-	num_pds = max_qp * 4;
+	num_pds = I40IW_MAX_PDS;
 	resources_size = sizeof(struct i40iw_arp_entry) * arp_table_size;
 	resources_size += sizeof(unsigned long) * BITS_TO_LONGS(max_qp);
 	resources_size += sizeof(unsigned long) * BITS_TO_LONGS(max_mr);
@@ -308,7 +308,9 @@ void i40iw_process_aeq(struct i40iw_devi
 			iwqp = iwdev->qp_table[info->qp_cq_id];
 			if (!iwqp) {
 				spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
-				i40iw_pr_err("qp_id %d is already freed\n", info->qp_cq_id);
+				i40iw_debug(dev, I40IW_DEBUG_AEQ,
+					    "%s qp_id %d is already freed\n",
+					    __func__, info->qp_cq_id);
 				continue;
 			}
 			i40iw_add_ref(&iwqp->ibqp);
@@ -359,6 +361,9 @@ void i40iw_process_aeq(struct i40iw_devi
 				continue;
 			i40iw_cm_disconn(iwqp);
 			break;
+		case I40IW_AE_QP_SUSPEND_COMPLETE:
+			i40iw_qp_suspend_resume(dev, &iwqp->sc_qp, false);
+			break;
 		case I40IW_AE_TERMINATE_SENT:
 			i40iw_terminate_send_fin(qp);
 			break;
@@ -404,19 +409,18 @@ void i40iw_process_aeq(struct i40iw_devi
 		case I40IW_AE_LCE_CQ_CATASTROPHIC:
 		case I40IW_AE_UDA_XMIT_DGRAM_TOO_LONG:
 		case I40IW_AE_UDA_XMIT_IPADDR_MISMATCH:
-		case I40IW_AE_QP_SUSPEND_COMPLETE:
 			ctx_info->err_rq_idx_valid = false;
 		default:
-				if (!info->sq && ctx_info->err_rq_idx_valid) {
-					ctx_info->err_rq_idx = info->wqe_idx;
-					ctx_info->tcp_info_valid = false;
-					ctx_info->iwarp_info_valid = false;
-					ret = dev->iw_priv_qp_ops->qp_setctx(&iwqp->sc_qp,
-									     iwqp->host_ctx.va,
-									     ctx_info);
-				}
-				i40iw_terminate_connection(qp, info);
-				break;
+			if (!info->sq && ctx_info->err_rq_idx_valid) {
+				ctx_info->err_rq_idx = info->wqe_idx;
+				ctx_info->tcp_info_valid = false;
+				ctx_info->iwarp_info_valid = false;
+				ret = dev->iw_priv_qp_ops->qp_setctx(&iwqp->sc_qp,
+								     iwqp->host_ctx.va,
+								     ctx_info);
+			}
+			i40iw_terminate_connection(qp, info);
+			break;
 		}
 		if (info->qp)
 			i40iw_rem_ref(&iwqp->ibqp);
@@ -538,6 +542,7 @@ enum i40iw_status_code i40iw_manage_qhas
 {
 	struct i40iw_qhash_table_info *info;
 	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
+	struct i40iw_sc_vsi *vsi = &iwdev->vsi;
 	enum i40iw_status_code status;
 	struct i40iw_cqp *iwcqp = &iwdev->cqp;
 	struct i40iw_cqp_request *cqp_request;
@@ -550,6 +555,7 @@ enum i40iw_status_code i40iw_manage_qhas
 	info = &cqp_info->in.u.manage_qhash_table_entry.info;
 	memset(info, 0, sizeof(*info));
 
+	info->vsi = &iwdev->vsi;
 	info->manage = mtype;
 	info->entry_type = etype;
 	if (cminfo->vlan_id != 0xFFFF) {
@@ -560,8 +566,9 @@ enum i40iw_status_code i40iw_manage_qhas
 	}
 
 	info->ipv4_valid = cminfo->ipv4;
+	info->user_pri = cminfo->user_pri;
 	ether_addr_copy(info->mac_addr, iwdev->netdev->dev_addr);
-	info->qp_num = cpu_to_le32(dev->ilq->qp_id);
+	info->qp_num = cpu_to_le32(vsi->ilq->qp_id);
 	info->dest_port = cpu_to_le16(cminfo->loc_port);
 	info->dest_ip[0] = cpu_to_le32(cminfo->loc_addr[0]);
 	info->dest_ip[1] = cpu_to_le32(cminfo->loc_addr[1]);
@@ -617,6 +624,7 @@ enum i40iw_status_code i40iw_hw_flush_wq
 	struct i40iw_qp_flush_info *hw_info;
 	struct i40iw_cqp_request *cqp_request;
 	struct cqp_commands_info *cqp_info;
+	struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp;
 
 	cqp_request = i40iw_get_cqp_request(&iwdev->cqp, wait);
 	if (!cqp_request)
@@ -631,9 +639,30 @@ enum i40iw_status_code i40iw_hw_flush_wq
 	cqp_info->in.u.qp_flush_wqes.qp = qp;
 	cqp_info->in.u.qp_flush_wqes.scratch = (uintptr_t)cqp_request;
 	status = i40iw_handle_cqp_op(iwdev, cqp_request);
-	if (status)
+	if (status) {
 		i40iw_pr_err("CQP-OP Flush WQE's fail");
-	return status;
+		complete(&iwqp->sq_drained);
+		complete(&iwqp->rq_drained);
+		return status;
+	}
+	if (!cqp_request->compl_info.maj_err_code) {
+		switch (cqp_request->compl_info.min_err_code) {
+		case I40IW_CQP_COMPL_RQ_WQE_FLUSHED:
+			complete(&iwqp->sq_drained);
+			break;
+		case I40IW_CQP_COMPL_SQ_WQE_FLUSHED:
+			complete(&iwqp->rq_drained);
+			break;
+		case I40IW_CQP_COMPL_RQ_SQ_WQE_FLUSHED:
+			break;
+		default:
+			complete(&iwqp->sq_drained);
+			complete(&iwqp->rq_drained);
+			break;
+		}
+	}
+
+	return 0;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_main.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -237,14 +237,11 @@ static irqreturn_t i40iw_irq_handler(int
  */
 static void i40iw_destroy_cqp(struct i40iw_device *iwdev, bool free_hwcqp)
 {
-	enum i40iw_status_code status = 0;
 	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
 	struct i40iw_cqp *cqp = &iwdev->cqp;
 
-	if (free_hwcqp && dev->cqp_ops->cqp_destroy)
-		status = dev->cqp_ops->cqp_destroy(dev->cqp);
-	if (status)
-		i40iw_pr_err("destroy cqp failed");
+	if (free_hwcqp)
+		dev->cqp_ops->cqp_destroy(dev->cqp);
 
 	i40iw_free_dma_mem(dev->hw, &cqp->sq);
 	kfree(cqp->scratch_array);
@@ -270,6 +267,7 @@ static void i40iw_disable_irq(struct i40
 		i40iw_wr32(dev->hw, I40E_PFINT_DYN_CTLN(msix_vec->idx - 1), 0);
 	else
 		i40iw_wr32(dev->hw, I40E_VFINT_DYN_CTLN1(msix_vec->idx - 1), 0);
+	irq_set_affinity_hint(msix_vec->irq, NULL);
 	free_irq(msix_vec->irq, dev_id);
 }
 
@@ -603,7 +601,7 @@ static enum i40iw_status_code i40iw_crea
 		i40iw_pr_err("cqp init status %d\n", status);
 		goto exit;
 	}
-	status = dev->cqp_ops->cqp_create(dev->cqp, true, &maj_err, &min_err);
+	status = dev->cqp_ops->cqp_create(dev->cqp, &maj_err, &min_err);
 	if (status) {
 		i40iw_pr_err("cqp create status %d maj_err %d min_err %d\n",
 			     status, maj_err, min_err);
@@ -688,6 +686,7 @@ static enum i40iw_status_code i40iw_conf
 							 struct i40iw_msix_vector *msix_vec)
 {
 	enum i40iw_status_code status;
+	cpumask_t mask;
 
 	if (iwdev->msix_shared && !ceq_id) {
 		tasklet_init(&iwdev->dpc_tasklet, i40iw_dpc, (unsigned long)iwdev);
@@ -697,12 +696,15 @@ static enum i40iw_status_code i40iw_conf
 		status = request_irq(msix_vec->irq, i40iw_ceq_handler, 0, "CEQ", iwceq);
 	}
 
+	cpumask_clear(&mask);
+	cpumask_set_cpu(msix_vec->cpu_affinity, &mask);
+	irq_set_affinity_hint(msix_vec->irq, &mask);
+
 	if (status) {
 		i40iw_pr_err("ceq irq config fail\n");
 		return I40IW_ERR_CONFIG;
 	}
 	msix_vec->ceq_id = ceq_id;
-	msix_vec->cpu_affinity = 0;
 
 	return 0;
 }
@@ -930,6 +932,7 @@ static enum i40iw_status_code i40iw_init
 	struct i40iw_puda_rsrc_info info;
 	enum i40iw_status_code status;
 
+	memset(&info, 0, sizeof(info));
 	info.type = I40IW_PUDA_RSRC_TYPE_ILQ;
 	info.cq_id = 1;
 	info.qp_id = 0;
@@ -939,10 +942,9 @@ static enum i40iw_status_code i40iw_init
 	info.rq_size = 8192;
 	info.buf_size = 1024;
 	info.tx_buf_cnt = 16384;
-	info.mss = iwdev->mss;
 	info.receive = i40iw_receive_ilq;
 	info.xmit_complete = i40iw_free_sqbuf;
-	status = i40iw_puda_create_rsrc(&iwdev->sc_dev, &info);
+	status = i40iw_puda_create_rsrc(&iwdev->vsi, &info);
 	if (status)
 		i40iw_pr_err("ilq create fail\n");
 	return status;
@@ -959,6 +961,7 @@ static enum i40iw_status_code i40iw_init
 	struct i40iw_puda_rsrc_info info;
 	enum i40iw_status_code status;
 
+	memset(&info, 0, sizeof(info));
 	info.type = I40IW_PUDA_RSRC_TYPE_IEQ;
 	info.cq_id = 2;
 	info.qp_id = iwdev->sc_dev.exception_lan_queue;
@@ -967,9 +970,8 @@ static enum i40iw_status_code i40iw_init
 	info.sq_size = 8192;
 	info.rq_size = 8192;
 	info.buf_size = 2048;
-	info.mss = iwdev->mss;
 	info.tx_buf_cnt = 16384;
-	status = i40iw_puda_create_rsrc(&iwdev->sc_dev, &info);
+	status = i40iw_puda_create_rsrc(&iwdev->vsi, &info);
 	if (status)
 		i40iw_pr_err("ieq create fail\n");
 	return status;
@@ -1159,7 +1161,7 @@ static void i40iw_add_ipv6_addr(struct i
 {
 	struct net_device *ip_dev;
 	struct inet6_dev *idev;
-	struct inet6_ifaddr *ifp;
+	struct inet6_ifaddr *ifp, *tmp;
 	u32 local_ipaddr6[4];
 
 	rcu_read_lock();
@@ -1172,7 +1174,7 @@ static void i40iw_add_ipv6_addr(struct i
 				i40iw_pr_err("ipv6 inet device not found\n");
 				break;
 			}
-			list_for_each_entry(ifp, &idev->addr_list, if_list) {
+			list_for_each_entry_safe(ifp, tmp, &idev->addr_list, if_list) {
 				i40iw_pr_info("IP=%pI6, vlan_id=%d, MAC=%pM\n", &ifp->addr,
 					      rdma_vlan_dev_vlan_id(ip_dev), ip_dev->dev_addr);
 				i40iw_copy_ip_ntohl(local_ipaddr6,
@@ -1294,17 +1296,23 @@ static enum i40iw_status_code i40iw_init
 	enum i40iw_status_code status;
 	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
 	struct i40iw_device_init_info info;
+	struct i40iw_vsi_init_info vsi_info;
 	struct i40iw_dma_mem mem;
+	struct i40iw_l2params l2params;
 	u32 size;
+	struct i40iw_vsi_stats_info stats_info;
+	u16 last_qset = I40IW_NO_QSET;
+	u16 qset;
+	u32 i;
 
+	memset(&l2params, 0, sizeof(l2params));
 	memset(&info, 0, sizeof(info));
 	size = sizeof(struct i40iw_hmc_pble_rsrc) + sizeof(struct i40iw_hmc_info) +
 				(sizeof(struct i40iw_hmc_obj_info) * I40IW_HMC_IW_MAX);
 	iwdev->hmc_info_mem = kzalloc(size, GFP_KERNEL);
-	if (!iwdev->hmc_info_mem) {
-		i40iw_pr_err("memory alloc fail\n");
+	if (!iwdev->hmc_info_mem)
 		return I40IW_ERR_NO_MEMORY;
-	}
+
 	iwdev->pble_rsrc = (struct i40iw_hmc_pble_rsrc *)iwdev->hmc_info_mem;
 	dev->hmc_info = &iwdev->hw.hmc;
 	dev->hmc_info->hmc_obj = (struct i40iw_hmc_obj_info *)(iwdev->pble_rsrc + 1);
@@ -1325,7 +1333,17 @@ static enum i40iw_status_code i40iw_init
 	info.bar0 = ldev->hw_addr;
 	info.hw = &iwdev->hw;
 	info.debug_mask = debug;
-	info.qs_handle = ldev->params.qos.prio_qos[0].qs_handle;
+	l2params.mss =
+		(ldev->params.mtu) ? ldev->params.mtu - I40IW_MTU_TO_MSS : I40IW_DEFAULT_MSS;
+	for (i = 0; i < I40E_CLIENT_MAX_USER_PRIORITY; i++) {
+		qset = ldev->params.qos.prio_qos[i].qs_handle;
+		l2params.qs_handle_list[i] = qset;
+		if (last_qset == I40IW_NO_QSET)
+			last_qset = qset;
+		else if ((qset != last_qset) && (qset != I40IW_NO_QSET))
+			iwdev->dcb = true;
+	}
+	i40iw_pr_info("DCB is set/clear = %d\n", iwdev->dcb);
 	info.exception_lan_queue = 1;
 	info.vchnl_send = i40iw_virtchnl_send;
 	status = i40iw_device_init(&iwdev->sc_dev, &info);
@@ -1334,6 +1352,20 @@ exit:
 		kfree(iwdev->hmc_info_mem);
 		iwdev->hmc_info_mem = NULL;
 	}
+	memset(&vsi_info, 0, sizeof(vsi_info));
+	vsi_info.dev = &iwdev->sc_dev;
+	vsi_info.back_vsi = (void *)iwdev;
+	vsi_info.params = &l2params;
+	i40iw_sc_vsi_init(&iwdev->vsi, &vsi_info);
+
+	if (dev->is_pf) {
+		memset(&stats_info, 0, sizeof(stats_info));
+		stats_info.fcn_id = ldev->fid;
+		stats_info.pestat = kzalloc(sizeof(*stats_info.pestat), GFP_KERNEL);
+		stats_info.stats_initialize = true;
+		if (stats_info.pestat)
+			i40iw_vsi_stats_init(&iwdev->vsi, &stats_info);
+	}
 	return status;
 }
 
@@ -1384,6 +1416,7 @@ static enum i40iw_status_code i40iw_save
 	for (i = 0, ceq_idx = 0; i < iwdev->msix_count; i++, iw_qvinfo++) {
 		iwdev->iw_msixtbl[i].idx = ldev->msix_entries[i].entry;
 		iwdev->iw_msixtbl[i].irq = ldev->msix_entries[i].vector;
+		iwdev->iw_msixtbl[i].cpu_affinity = ceq_idx;
 		if (i == 0) {
 			iw_qvinfo->aeq_idx = 0;
 			if (iwdev->msix_shared)
@@ -1404,18 +1437,19 @@ static enum i40iw_status_code i40iw_save
  * i40iw_deinit_device - clean up the device resources
  * @iwdev: iwarp device
  * @reset: true if called before reset
- * @del_hdl: true if delete hdl entry
  *
  * Destroy the ib device interface, remove the mac ip entry and ipv4/ipv6 addresses,
  * destroy the device queues and free the pble and the hmc objects
  */
-static void i40iw_deinit_device(struct i40iw_device *iwdev, bool reset, bool del_hdl)
+static void i40iw_deinit_device(struct i40iw_device *iwdev, bool reset)
 {
 	struct i40e_info *ldev = iwdev->ldev;
 
 	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
 
 	i40iw_pr_info("state = %d\n", iwdev->init_state);
+	if (iwdev->param_wq)
+		destroy_workqueue(iwdev->param_wq);
 
 	switch (iwdev->init_state) {
 	case RDMA_DEV_REGISTERED:
@@ -1441,10 +1475,10 @@ static void i40iw_deinit_device(struct i
 		i40iw_destroy_aeq(iwdev, reset);
 		/* fallthrough */
 	case IEQ_CREATED:
-		i40iw_puda_dele_resources(dev, I40IW_PUDA_RSRC_TYPE_IEQ, reset);
+		i40iw_puda_dele_resources(&iwdev->vsi, I40IW_PUDA_RSRC_TYPE_IEQ, reset);
 		/* fallthrough */
 	case ILQ_CREATED:
-		i40iw_puda_dele_resources(dev, I40IW_PUDA_RSRC_TYPE_ILQ, reset);
+		i40iw_puda_dele_resources(&iwdev->vsi, I40IW_PUDA_RSRC_TYPE_ILQ, reset);
 		/* fallthrough */
 	case CCQ_CREATED:
 		i40iw_destroy_ccq(iwdev, reset);
@@ -1456,13 +1490,14 @@ static void i40iw_deinit_device(struct i
 		i40iw_del_hmc_objects(dev, dev->hmc_info, true, reset);
 		/* fallthrough */
 	case CQP_CREATED:
-		i40iw_destroy_cqp(iwdev, !reset);
+		i40iw_destroy_cqp(iwdev, true);
 		/* fallthrough */
 	case INITIAL_STATE:
 		i40iw_cleanup_cm_core(&iwdev->cm_core);
-		if (dev->is_pf)
-			i40iw_hw_stats_del_timer(dev);
-
+		if (iwdev->vsi.pestat) {
+			i40iw_vsi_stats_free(&iwdev->vsi);
+			kfree(iwdev->vsi.pestat);
+		}
 		i40iw_del_init_mem(iwdev);
 		break;
 	case INVALID_STATE:
@@ -1472,8 +1507,7 @@ static void i40iw_deinit_device(struct i
 		break;
 	}
 
-	if (del_hdl)
-		i40iw_del_handler(i40iw_find_i40e_handler(ldev));
+	i40iw_del_handler(i40iw_find_i40e_handler(ldev));
 	kfree(iwdev->hdl);
 }
 
@@ -1508,7 +1542,6 @@ static enum i40iw_status_code i40iw_setu
 	iwdev->max_enabled_vfs = iwdev->max_rdma_vfs;
 	iwdev->netdev = ldev->netdev;
 	hdl->client = client;
-	iwdev->mss = (!ldev->params.mtu) ? I40IW_DEFAULT_MSS : ldev->params.mtu - I40IW_MTU_TO_MSS;
 	if (!ldev->ftype)
 		iwdev->db_start = pci_resource_start(ldev->pcidev, 0) + I40IW_DB_ADDR_OFFSET;
 	else
@@ -1528,6 +1561,7 @@ static enum i40iw_status_code i40iw_setu
 
 	init_waitqueue_head(&iwdev->vchnl_waitq);
 	init_waitqueue_head(&dev->vf_reqs);
+	init_waitqueue_head(&iwdev->close_wq);
 
 	status = i40iw_initialize_dev(iwdev, ldev);
 exit:
@@ -1540,6 +1574,20 @@ exit:
 }
 
 /**
+ * i40iw_get_used_rsrc - determine resources used internally
+ * @iwdev: iwarp device
+ *
+ * Called after internal allocations
+ */
+static void i40iw_get_used_rsrc(struct i40iw_device *iwdev)
+{
+	iwdev->used_pds = find_next_zero_bit(iwdev->allocated_pds, iwdev->max_pd, 0);
+	iwdev->used_qps = find_next_zero_bit(iwdev->allocated_qps, iwdev->max_qp, 0);
+	iwdev->used_cqs = find_next_zero_bit(iwdev->allocated_cqs, iwdev->max_cq, 0);
+	iwdev->used_mrs = find_next_zero_bit(iwdev->allocated_mrs, iwdev->max_mr, 0);
+}
+
+/**
  * i40iw_open - client interface operation open for iwarp/uda device
  * @ldev: lan device information
  * @client: iwarp client information, provided during registration
@@ -1611,6 +1659,7 @@ static int i40iw_open(struct i40e_info *
 		status = i40iw_initialize_hw_resources(iwdev);
 		if (status)
 			break;
+		i40iw_get_used_rsrc(iwdev);
 		dev->ccq_ops->ccq_arm(dev->ccq);
 		status = i40iw_hmc_init_pble(&iwdev->sc_dev, iwdev->pble_rsrc);
 		if (status)
@@ -1630,35 +1679,73 @@ static int i40iw_open(struct i40e_info *
 		iwdev->init_state = RDMA_DEV_REGISTERED;
 		iwdev->iw_status = 1;
 		i40iw_port_ibevent(iwdev);
+		iwdev->param_wq = alloc_ordered_workqueue("l2params", WQ_MEM_RECLAIM);
+		if(iwdev->param_wq == NULL)
+			break;
 		i40iw_pr_info("i40iw_open completed\n");
 		return 0;
 	} while (0);
 
 	i40iw_pr_err("status = %d last completion = %d\n", status, iwdev->init_state);
-	i40iw_deinit_device(iwdev, false, false);
+	i40iw_deinit_device(iwdev, false);
 	return -ERESTART;
 }
 
 /**
- * i40iw_l2param_change : handle qs handles for qos and mss change
+ * i40iw_l2params_worker - worker for l2 params change
+ * @work: work pointer for l2 params
+ */
+static void i40iw_l2params_worker(struct work_struct *work)
+{
+	struct l2params_work *dwork =
+	    container_of(work, struct l2params_work, work);
+	struct i40iw_device *iwdev = dwork->iwdev;
+
+	i40iw_change_l2params(&iwdev->vsi, &dwork->l2params);
+	atomic_dec(&iwdev->params_busy);
+	kfree(work);
+}
+
+/**
+ * i40iw_l2param_change - handle qs handles for qos and mss change
  * @ldev: lan device information
  * @client: client for paramater change
  * @params: new parameters from L2
  */
-static void i40iw_l2param_change(struct i40e_info *ldev,
-				 struct i40e_client *client,
+static void i40iw_l2param_change(struct i40e_info *ldev, struct i40e_client *client,
 				 struct i40e_params *params)
 {
 	struct i40iw_handler *hdl;
+	struct i40iw_l2params *l2params;
+	struct l2params_work *work;
 	struct i40iw_device *iwdev;
+	int i;
 
 	hdl = i40iw_find_i40e_handler(ldev);
 	if (!hdl)
 		return;
 
 	iwdev = &hdl->device;
-	if (params->mtu)
-		iwdev->mss = params->mtu - I40IW_MTU_TO_MSS;
+
+	if (atomic_read(&iwdev->params_busy))
+		return;
+
+
+	work = kzalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work)
+		return;
+
+	atomic_inc(&iwdev->params_busy);
+
+	work->iwdev = iwdev;
+	l2params = &work->l2params;
+	for (i = 0; i < I40E_CLIENT_MAX_USER_PRIORITY; i++)
+		l2params->qs_handle_list[i] = params->qos.prio_qos[i].qs_handle;
+
+	l2params->mss = (params->mtu) ? params->mtu - I40IW_MTU_TO_MSS : iwdev->vsi.mss;
+
+	INIT_WORK(&work->work, i40iw_l2params_worker);
+	queue_work(iwdev->param_wq, &work->work);
 }
 
 /**
@@ -1679,8 +1766,11 @@ static void i40iw_close(struct i40e_info
 		return;
 
 	iwdev = &hdl->device;
+	iwdev->closing = true;
+
+	i40iw_cm_disconnect_all(iwdev);
 	destroy_workqueue(iwdev->virtchnl_wq);
-	i40iw_deinit_device(iwdev, reset, true);
+	i40iw_deinit_device(iwdev, reset);
 }
 
 /**
@@ -1701,21 +1791,23 @@ static void i40iw_vf_reset(struct i40e_i
 	struct i40iw_vfdev *tmp_vfdev;
 	unsigned int i;
 	unsigned long flags;
+	struct i40iw_device *iwdev;
 
 	hdl = i40iw_find_i40e_handler(ldev);
 	if (!hdl)
 		return;
 
 	dev = &hdl->device.sc_dev;
+	iwdev = (struct i40iw_device *)dev->back_dev;
 
 	for (i = 0; i < I40IW_MAX_PE_ENABLED_VF_COUNT; i++) {
 		if (!dev->vf_dev[i] || (dev->vf_dev[i]->vf_id != vf_id))
 			continue;
 		/* free all resources allocated on behalf of vf */
 		tmp_vfdev = dev->vf_dev[i];
-		spin_lock_irqsave(&dev->dev_pestat.stats_lock, flags);
+		spin_lock_irqsave(&iwdev->vsi.pestat->lock, flags);
 		dev->vf_dev[i] = NULL;
-		spin_unlock_irqrestore(&dev->dev_pestat.stats_lock, flags);
+		spin_unlock_irqrestore(&iwdev->vsi.pestat->lock, flags);
 		i40iw_del_hmc_objects(dev, &tmp_vfdev->hmc_info, false, false);
 		/* remove vf hmc function */
 		memset(&hmc_fcn_info, 0, sizeof(hmc_fcn_info));
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_osdep.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_osdep.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_osdep.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_osdep.h	2017-02-12 16:03:20.000000000 -0500
@@ -198,6 +198,8 @@ enum i40iw_status_code i40iw_cqp_manage_
 void i40iw_cqp_spawn_worker(struct i40iw_sc_dev *dev,
 			    struct i40iw_virtchnl_work_info *work_info, u32 iw_vf_idx);
 void *i40iw_remove_head(struct list_head *list);
+void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, bool suspend);
+void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp);
 
 void i40iw_term_modify_qp(struct i40iw_sc_qp *qp, u8 next_state, u8 term, u8 term_len);
 void i40iw_terminate_done(struct i40iw_sc_qp *qp, int timeout_occurred);
@@ -207,9 +209,9 @@ void i40iw_terminate_del_timer(struct i4
 enum i40iw_status_code i40iw_hw_manage_vf_pble_bp(struct i40iw_device *iwdev,
 						  struct i40iw_manage_vf_pble_info *info,
 						  bool wait);
-struct i40iw_dev_pestat;
-void i40iw_hw_stats_start_timer(struct i40iw_sc_dev *);
-void i40iw_hw_stats_del_timer(struct i40iw_sc_dev *);
+struct i40iw_sc_vsi;
+void i40iw_hw_stats_start_timer(struct i40iw_sc_vsi *vsi);
+void i40iw_hw_stats_stop_timer(struct i40iw_sc_vsi *vsi);
 #define i40iw_mmiowb() mmiowb()
 void i40iw_wr32(struct i40iw_hw *hw, u32 reg, u32 value);
 u32  i40iw_rd32(struct i40iw_hw *hw, u32 reg);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_pble.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_pble.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_pble.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_pble.c	2017-02-12 16:03:20.000000000 -0500
@@ -353,10 +353,6 @@ static enum i40iw_status_code add_pble_p
 	pages = (idx->rel_pd_idx) ? (I40IW_HMC_PD_CNT_IN_SD -
 			idx->rel_pd_idx) : I40IW_HMC_PD_CNT_IN_SD;
 	pages = min(pages, pble_rsrc->unallocated_pble >> PBLE_512_SHIFT);
-	if (!pages) {
-		ret_code = I40IW_ERR_NO_PBLCHUNKS_AVAILABLE;
-		goto error;
-	}
 	info.chunk = chunk;
 	info.hmc_info = hmc_info;
 	info.pages = pages;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_p.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_p.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_p.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_p.h	2017-02-12 16:03:20.000000000 -0500
@@ -47,8 +47,6 @@ void i40iw_debug_buf(struct i40iw_sc_dev
 enum i40iw_status_code i40iw_device_init(struct i40iw_sc_dev *dev,
 					 struct i40iw_device_init_info *info);
 
-enum i40iw_status_code i40iw_device_init_pestat(struct i40iw_dev_pestat *);
-
 void i40iw_sc_cqp_post_sq(struct i40iw_sc_cqp *cqp);
 
 u64 *i40iw_sc_cqp_get_next_send_wqe(struct i40iw_sc_cqp *cqp, u64 scratch);
@@ -64,7 +62,24 @@ enum i40iw_status_code i40iw_sc_init_iw_
 enum i40iw_status_code i40iw_pf_init_vfhmc(struct i40iw_sc_dev *dev, u8 vf_hmc_fn_id,
 					   u32 *vf_cnt_array);
 
-/* cqp misc functions */
+/* stats functions */
+void i40iw_hw_stats_refresh_all(struct i40iw_vsi_pestat *stats);
+void i40iw_hw_stats_read_all(struct i40iw_vsi_pestat *stats, struct i40iw_dev_hw_stats *stats_values);
+void i40iw_hw_stats_read_32(struct i40iw_vsi_pestat *stats,
+			    enum i40iw_hw_stats_index_32b index,
+			    u64 *value);
+void i40iw_hw_stats_read_64(struct i40iw_vsi_pestat *stats,
+			    enum i40iw_hw_stats_index_64b index,
+			    u64 *value);
+void i40iw_hw_stats_init(struct i40iw_vsi_pestat *stats, u8 index, bool is_pf);
+
+/* vsi misc functions */
+enum i40iw_status_code i40iw_vsi_stats_init(struct i40iw_sc_vsi *vsi, struct i40iw_vsi_stats_info *info);
+void i40iw_vsi_stats_free(struct i40iw_sc_vsi *vsi);
+void i40iw_sc_vsi_init(struct i40iw_sc_vsi *vsi, struct i40iw_vsi_init_info *info);
+
+void i40iw_change_l2params(struct i40iw_sc_vsi *vsi, struct i40iw_l2params *l2params);
+void i40iw_qp_add_qos(struct i40iw_sc_qp *qp);
 
 void i40iw_terminate_send_fin(struct i40iw_sc_qp *qp);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,12 +42,13 @@
 #include "i40iw_p.h"
 #include "i40iw_puda.h"
 
-static void i40iw_ieq_receive(struct i40iw_sc_dev *dev,
+static void i40iw_ieq_receive(struct i40iw_sc_vsi *vsi,
 			      struct i40iw_puda_buf *buf);
-static void i40iw_ieq_tx_compl(struct i40iw_sc_dev *dev, void *sqwrid);
+static void i40iw_ieq_tx_compl(struct i40iw_sc_vsi *vsi, void *sqwrid);
 static void i40iw_ilq_putback_rcvbuf(struct i40iw_sc_qp *qp, u32 wqe_idx);
 static enum i40iw_status_code i40iw_puda_replenish_rq(struct i40iw_puda_rsrc
 						      *rsrc, bool initial);
+static void i40iw_ieq_cleanup_qp(struct i40iw_puda_rsrc *ieq, struct i40iw_sc_qp *qp);
 /**
  * i40iw_puda_get_listbuf - get buffer from puda list
  * @list: list to use for buffers (ILQ or IEQ)
@@ -292,7 +293,7 @@ enum i40iw_status_code i40iw_puda_poll_c
 	unsigned long	flags;
 
 	if ((cq_type == I40IW_CQ_TYPE_ILQ) || (cq_type == I40IW_CQ_TYPE_IEQ)) {
-		rsrc = (cq_type == I40IW_CQ_TYPE_ILQ) ? dev->ilq : dev->ieq;
+		rsrc = (cq_type == I40IW_CQ_TYPE_ILQ) ? cq->vsi->ilq : cq->vsi->ieq;
 	} else {
 		i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s qp_type error\n", __func__);
 		return I40IW_ERR_BAD_PTR;
@@ -335,7 +336,7 @@ enum i40iw_status_code i40iw_puda_poll_c
 		rsrc->stats_pkt_rcvd++;
 		rsrc->compl_rxwqe_idx = info.wqe_idx;
 		i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s RQ completion\n", __func__);
-		rsrc->receive(rsrc->dev, buf);
+		rsrc->receive(rsrc->vsi, buf);
 		if (cq_type == I40IW_CQ_TYPE_ILQ)
 			i40iw_ilq_putback_rcvbuf(&rsrc->qp, info.wqe_idx);
 		else
@@ -345,12 +346,12 @@ enum i40iw_status_code i40iw_puda_poll_c
 		i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s SQ completion\n", __func__);
 		sqwrid = (void *)(uintptr_t)qp->sq_wrtrk_array[info.wqe_idx].wrid;
 		I40IW_RING_SET_TAIL(qp->sq_ring, info.wqe_idx);
-		rsrc->xmit_complete(rsrc->dev, sqwrid);
+		rsrc->xmit_complete(rsrc->vsi, sqwrid);
 		spin_lock_irqsave(&rsrc->bufpool_lock, flags);
 		rsrc->tx_wqe_avail_cnt++;
 		spin_unlock_irqrestore(&rsrc->bufpool_lock, flags);
-		if (!list_empty(&dev->ilq->txpend))
-			i40iw_puda_send_buf(dev->ilq, NULL);
+		if (!list_empty(&rsrc->vsi->ilq->txpend))
+			i40iw_puda_send_buf(rsrc->vsi->ilq, NULL);
 	}
 
 done:
@@ -513,10 +514,8 @@ static void i40iw_puda_qp_setctx(struct
  * i40iw_puda_qp_wqe - setup wqe for qp create
  * @rsrc: resource for qp
  */
-static enum i40iw_status_code i40iw_puda_qp_wqe(struct i40iw_puda_rsrc *rsrc)
+static enum i40iw_status_code i40iw_puda_qp_wqe(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
 {
-	struct i40iw_sc_qp *qp = &rsrc->qp;
-	struct i40iw_sc_dev *dev = rsrc->dev;
 	struct i40iw_sc_cqp *cqp;
 	u64 *wqe;
 	u64 header;
@@ -582,6 +581,7 @@ static enum i40iw_status_code i40iw_puda
 	qp->back_qp = (void *)rsrc;
 	qp->sq_pa = mem->pa;
 	qp->rq_pa = qp->sq_pa + sq_size;
+	qp->vsi = rsrc->vsi;
 	ukqp->sq_base = mem->va;
 	ukqp->rq_base = &ukqp->sq_base[rsrc->sq_size];
 	ukqp->shadow_area = ukqp->rq_base[rsrc->rq_size].elem;
@@ -608,15 +608,63 @@ static enum i40iw_status_code i40iw_puda
 		ukqp->wqe_alloc_reg = (u32 __iomem *)(i40iw_get_hw_addr(qp->pd->dev) +
 						    I40E_VFPE_WQEALLOC1);
 
-	qp->qs_handle = qp->dev->qs_handle;
+	qp->user_pri = 0;
+	i40iw_qp_add_qos(qp);
 	i40iw_puda_qp_setctx(rsrc);
-	ret = i40iw_puda_qp_wqe(rsrc);
+	if (rsrc->ceq_valid)
+		ret = i40iw_cqp_qp_create_cmd(rsrc->dev, qp);
+	else
+		ret = i40iw_puda_qp_wqe(rsrc->dev, qp);
 	if (ret)
 		i40iw_free_dma_mem(rsrc->dev->hw, &rsrc->qpmem);
 	return ret;
 }
 
 /**
+ * i40iw_puda_cq_wqe - setup wqe for cq create
+ * @rsrc: resource for cq
+ */
+static enum i40iw_status_code i40iw_puda_cq_wqe(struct i40iw_sc_dev *dev, struct i40iw_sc_cq *cq)
+{
+	u64 *wqe;
+	struct i40iw_sc_cqp *cqp;
+	u64 header;
+	struct i40iw_ccq_cqe_info compl_info;
+	enum i40iw_status_code status = 0;
+
+	cqp = dev->cqp;
+	wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, 0);
+	if (!wqe)
+		return I40IW_ERR_RING_FULL;
+
+	set_64bit_val(wqe, 0, cq->cq_uk.cq_size);
+	set_64bit_val(wqe, 8, RS_64_1(cq, 1));
+	set_64bit_val(wqe, 16,
+		      LS_64(cq->shadow_read_threshold,
+			    I40IW_CQPSQ_CQ_SHADOW_READ_THRESHOLD));
+	set_64bit_val(wqe, 32, cq->cq_pa);
+
+	set_64bit_val(wqe, 40, cq->shadow_area_pa);
+
+	header = cq->cq_uk.cq_id |
+	    LS_64(I40IW_CQP_OP_CREATE_CQ, I40IW_CQPSQ_OPCODE) |
+	    LS_64(1, I40IW_CQPSQ_CQ_CHKOVERFLOW) |
+	    LS_64(1, I40IW_CQPSQ_CQ_ENCEQEMASK) |
+	    LS_64(1, I40IW_CQPSQ_CQ_CEQIDVALID) |
+	    LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
+	set_64bit_val(wqe, 24, header);
+
+	i40iw_debug_buf(dev, I40IW_DEBUG_PUDA, "PUDA CQE",
+			wqe, I40IW_CQP_WQE_SIZE * 8);
+
+	i40iw_sc_cqp_post_sq(dev->cqp);
+	status = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
+						 I40IW_CQP_OP_CREATE_CQ,
+						 &compl_info);
+	return status;
+}
+
+/**
  * i40iw_puda_cq_create - create cq for resource
  * @rsrc: resource for which cq to create
  */
@@ -624,18 +672,13 @@ static enum i40iw_status_code i40iw_puda
 {
 	struct i40iw_sc_dev *dev = rsrc->dev;
 	struct i40iw_sc_cq *cq = &rsrc->cq;
-	u64 *wqe;
-	struct i40iw_sc_cqp *cqp;
-	u64 header;
 	enum i40iw_status_code ret = 0;
 	u32 tsize, cqsize;
-	u32 shadow_read_threshold = 128;
 	struct i40iw_dma_mem *mem;
-	struct i40iw_ccq_cqe_info compl_info;
 	struct i40iw_cq_init_info info;
 	struct i40iw_cq_uk_init_info *init_info = &info.cq_uk_init_info;
 
-	cq->back_cq = (void *)rsrc;
+	cq->vsi = rsrc->vsi;
 	cqsize = rsrc->cq_size * (sizeof(struct i40iw_cqe));
 	tsize = cqsize + sizeof(struct i40iw_cq_shadow_area);
 	ret = i40iw_allocate_dma_mem(dev->hw, &rsrc->cqmem, tsize,
@@ -656,43 +699,84 @@ static enum i40iw_status_code i40iw_puda
 	init_info->shadow_area = (u64 *)((u8 *)mem->va + cqsize);
 	init_info->cq_size = rsrc->cq_size;
 	init_info->cq_id = rsrc->cq_id;
+	info.ceqe_mask = true;
+	info.ceq_id_valid = true;
 	ret = dev->iw_priv_cq_ops->cq_init(cq, &info);
 	if (ret)
 		goto error;
-	cqp = dev->cqp;
-	wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, 0);
-	if (!wqe) {
-		ret = I40IW_ERR_RING_FULL;
-		goto error;
-	}
+	if (rsrc->ceq_valid)
+		ret = i40iw_cqp_cq_create_cmd(dev, cq);
+	else
+		ret = i40iw_puda_cq_wqe(dev, cq);
+error:
+	if (ret)
+		i40iw_free_dma_mem(dev->hw, &rsrc->cqmem);
+	return ret;
+}
 
-	set_64bit_val(wqe, 0, rsrc->cq_size);
-	set_64bit_val(wqe, 8, RS_64_1(cq, 1));
-	set_64bit_val(wqe, 16, LS_64(shadow_read_threshold, I40IW_CQPSQ_CQ_SHADOW_READ_THRESHOLD));
-	set_64bit_val(wqe, 32, cq->cq_pa);
+/**
+ * i40iw_puda_free_qp - free qp for resource
+ * @rsrc: resource for which qp to free
+ */
+static void i40iw_puda_free_qp(struct i40iw_puda_rsrc *rsrc)
+{
+	enum i40iw_status_code ret;
+	struct i40iw_ccq_cqe_info compl_info;
+	struct i40iw_sc_dev *dev = rsrc->dev;
 
-	set_64bit_val(wqe, 40, cq->shadow_area_pa);
+	if (rsrc->ceq_valid) {
+		i40iw_cqp_qp_destroy_cmd(dev, &rsrc->qp);
+		return;
+	}
 
-	header = rsrc->cq_id |
-	    LS_64(I40IW_CQP_OP_CREATE_CQ, I40IW_CQPSQ_OPCODE) |
-	    LS_64(1, I40IW_CQPSQ_CQ_CHKOVERFLOW) |
-	    LS_64(1, I40IW_CQPSQ_CQ_ENCEQEMASK) |
-	    LS_64(1, I40IW_CQPSQ_CQ_CEQIDVALID) |
-	    LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
-	set_64bit_val(wqe, 24, header);
+	ret = dev->iw_priv_qp_ops->qp_destroy(&rsrc->qp,
+			0, false, true, true);
+	if (ret)
+		i40iw_debug(dev, I40IW_DEBUG_PUDA,
+			    "%s error puda qp destroy wqe\n",
+			    __func__);
 
-	i40iw_debug_buf(dev, I40IW_DEBUG_PUDA, "PUDA CQE",
-			wqe, I40IW_CQP_WQE_SIZE * 8);
+	if (!ret) {
+		ret = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
+				I40IW_CQP_OP_DESTROY_QP,
+				&compl_info);
+		if (ret)
+			i40iw_debug(dev, I40IW_DEBUG_PUDA,
+				    "%s error puda qp destroy failed\n",
+				    __func__);
+	}
+}
 
-	i40iw_sc_cqp_post_sq(dev->cqp);
-	ret = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
-						 I40IW_CQP_OP_CREATE_CQ,
-						 &compl_info);
+/**
+ * i40iw_puda_free_cq - free cq for resource
+ * @rsrc: resource for which cq to free
+ */
+static void i40iw_puda_free_cq(struct i40iw_puda_rsrc *rsrc)
+{
+	enum i40iw_status_code ret;
+	struct i40iw_ccq_cqe_info compl_info;
+	struct i40iw_sc_dev *dev = rsrc->dev;
+
+	if (rsrc->ceq_valid) {
+		i40iw_cqp_cq_destroy_cmd(dev, &rsrc->cq);
+		return;
+	}
+	ret = dev->iw_priv_cq_ops->cq_destroy(&rsrc->cq, 0, true);
 
-error:
 	if (ret)
-		i40iw_free_dma_mem(dev->hw, &rsrc->cqmem);
-	return ret;
+		i40iw_debug(dev, I40IW_DEBUG_PUDA,
+			    "%s error ieq cq destroy\n",
+			    __func__);
+
+	if (!ret) {
+		ret = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
+				I40IW_CQP_OP_DESTROY_CQ,
+				&compl_info);
+		if (ret)
+			i40iw_debug(dev, I40IW_DEBUG_PUDA,
+				    "%s error ieq qp destroy done\n",
+				    __func__);
+	}
 }
 
 /**
@@ -701,25 +785,24 @@ error:
  * @type: type of resource to dele
  * @reset: true if reset chip
  */
-void i40iw_puda_dele_resources(struct i40iw_sc_dev *dev,
+void i40iw_puda_dele_resources(struct i40iw_sc_vsi *vsi,
 			       enum puda_resource_type type,
 			       bool reset)
 {
-	struct i40iw_ccq_cqe_info compl_info;
+	struct i40iw_sc_dev *dev = vsi->dev;
 	struct i40iw_puda_rsrc *rsrc;
 	struct i40iw_puda_buf *buf = NULL;
 	struct i40iw_puda_buf *nextbuf = NULL;
 	struct i40iw_virt_mem *vmem;
-	enum i40iw_status_code ret;
 
 	switch (type) {
 	case I40IW_PUDA_RSRC_TYPE_ILQ:
-		rsrc = dev->ilq;
-		vmem = &dev->ilq_mem;
+		rsrc = vsi->ilq;
+		vmem = &vsi->ilq_mem;
 		break;
 	case I40IW_PUDA_RSRC_TYPE_IEQ:
-		rsrc = dev->ieq;
-		vmem = &dev->ieq_mem;
+		rsrc = vsi->ieq;
+		vmem = &vsi->ieq_mem;
 		break;
 	default:
 		i40iw_debug(dev, I40IW_DEBUG_PUDA, "%s: error resource type = 0x%x\n",
@@ -731,45 +814,14 @@ void i40iw_puda_dele_resources(struct i4
 	case PUDA_HASH_CRC_COMPLETE:
 		i40iw_free_hash_desc(rsrc->hash_desc);
 	case PUDA_QP_CREATED:
-		do {
-			if (reset)
-				break;
-			ret = dev->iw_priv_qp_ops->qp_destroy(&rsrc->qp,
-							      0, false, true, true);
-			if (ret)
-				i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA,
-					    "%s error ieq qp destroy\n",
-					    __func__);
-
-			ret = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
-								 I40IW_CQP_OP_DESTROY_QP,
-								 &compl_info);
-			if (ret)
-				i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA,
-					    "%s error ieq qp destroy done\n",
-					    __func__);
-		} while (0);
+		if (!reset)
+			i40iw_puda_free_qp(rsrc);
 
 		i40iw_free_dma_mem(dev->hw, &rsrc->qpmem);
 		/* fallthrough */
 	case PUDA_CQ_CREATED:
-		do {
-			if (reset)
-				break;
-			ret = dev->iw_priv_cq_ops->cq_destroy(&rsrc->cq, 0, true);
-			if (ret)
-				i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA,
-					    "%s error ieq cq destroy\n",
-					    __func__);
-
-			ret = dev->cqp_ops->poll_for_cqp_op_done(dev->cqp,
-								 I40IW_CQP_OP_DESTROY_CQ,
-								 &compl_info);
-			if (ret)
-				i40iw_debug(rsrc->dev, I40IW_DEBUG_PUDA,
-					    "%s error ieq qp destroy done\n",
-					    __func__);
-		} while (0);
+		if (!reset)
+			i40iw_puda_free_cq(rsrc);
 
 		i40iw_free_dma_mem(dev->hw, &rsrc->cqmem);
 		break;
@@ -825,9 +877,10 @@ static enum i40iw_status_code i40iw_puda
  * @dev: iwarp device
  * @info: resource information
  */
-enum i40iw_status_code i40iw_puda_create_rsrc(struct i40iw_sc_dev *dev,
+enum i40iw_status_code i40iw_puda_create_rsrc(struct i40iw_sc_vsi *vsi,
 					      struct i40iw_puda_rsrc_info *info)
 {
+	struct i40iw_sc_dev *dev = vsi->dev;
 	enum i40iw_status_code ret = 0;
 	struct i40iw_puda_rsrc *rsrc;
 	u32 pudasize;
@@ -840,10 +893,10 @@ enum i40iw_status_code i40iw_puda_create
 	rqwridsize = info->rq_size * 8;
 	switch (info->type) {
 	case I40IW_PUDA_RSRC_TYPE_ILQ:
-		vmem = &dev->ilq_mem;
+		vmem = &vsi->ilq_mem;
 		break;
 	case I40IW_PUDA_RSRC_TYPE_IEQ:
-		vmem = &dev->ieq_mem;
+		vmem = &vsi->ieq_mem;
 		break;
 	default:
 		return I40IW_NOT_SUPPORTED;
@@ -856,28 +909,28 @@ enum i40iw_status_code i40iw_puda_create
 	rsrc = (struct i40iw_puda_rsrc *)vmem->va;
 	spin_lock_init(&rsrc->bufpool_lock);
 	if (info->type == I40IW_PUDA_RSRC_TYPE_ILQ) {
-		dev->ilq = (struct i40iw_puda_rsrc *)vmem->va;
-		dev->ilq_count = info->count;
+		vsi->ilq = (struct i40iw_puda_rsrc *)vmem->va;
+		vsi->ilq_count = info->count;
 		rsrc->receive = info->receive;
 		rsrc->xmit_complete = info->xmit_complete;
 	} else {
-		vmem = &dev->ieq_mem;
-		dev->ieq_count = info->count;
-		dev->ieq = (struct i40iw_puda_rsrc *)vmem->va;
+		vmem = &vsi->ieq_mem;
+		vsi->ieq_count = info->count;
+		vsi->ieq = (struct i40iw_puda_rsrc *)vmem->va;
 		rsrc->receive = i40iw_ieq_receive;
 		rsrc->xmit_complete = i40iw_ieq_tx_compl;
 	}
 
+	rsrc->ceq_valid = info->ceq_valid;
 	rsrc->type = info->type;
 	rsrc->sq_wrtrk_array = (struct i40iw_sq_uk_wr_trk_info *)((u8 *)vmem->va + pudasize);
 	rsrc->rq_wrid_array = (u64 *)((u8 *)vmem->va + pudasize + sqwridsize);
-	rsrc->mss = info->mss;
 	/* Initialize all ieq lists */
 	INIT_LIST_HEAD(&rsrc->bufpool);
 	INIT_LIST_HEAD(&rsrc->txpend);
 
 	rsrc->tx_wqe_avail_cnt = info->sq_size - 1;
-	dev->iw_pd_ops->pd_init(dev, &rsrc->sc_pd, info->pd_id);
+	dev->iw_pd_ops->pd_init(dev, &rsrc->sc_pd, info->pd_id, -1);
 	rsrc->qp_id = info->qp_id;
 	rsrc->cq_id = info->cq_id;
 	rsrc->sq_size = info->sq_size;
@@ -885,6 +938,7 @@ enum i40iw_status_code i40iw_puda_create
 	rsrc->cq_size = info->rq_size + info->sq_size;
 	rsrc->buf_size = info->buf_size;
 	rsrc->dev = dev;
+	rsrc->vsi = vsi;
 
 	ret = i40iw_puda_cq_create(rsrc);
 	if (!ret) {
@@ -919,7 +973,7 @@ enum i40iw_status_code i40iw_puda_create
 	dev->ccq_ops->ccq_arm(&rsrc->cq);
 	return ret;
  error:
-	i40iw_puda_dele_resources(dev, info->type, false);
+	i40iw_puda_dele_resources(vsi, info->type, false);
 
 	return ret;
 }
@@ -1131,7 +1185,7 @@ static enum i40iw_status_code i40iw_ieq_
 	list_add(&buf->list, &pbufl);
 
 	status = i40iw_ieq_create_pbufl(pfpdu, rxlist, &pbufl, buf, fpdu_len);
-	if (!status)
+	if (status)
 		goto error;
 
 	txbuf = i40iw_puda_get_bufpool(ieq);
@@ -1332,7 +1386,7 @@ static void i40iw_ieq_handle_exception(s
 	}
 	if (pfpdu->mode && (fps != pfpdu->fps)) {
 		/* clean up qp as it is new partial sequence */
-		i40iw_ieq_cleanup_qp(ieq->dev, qp);
+		i40iw_ieq_cleanup_qp(ieq, qp);
 		i40iw_debug(ieq->dev, I40IW_DEBUG_IEQ,
 			    "%s: restarting new partial\n", __func__);
 		pfpdu->mode = false;
@@ -1344,7 +1398,7 @@ static void i40iw_ieq_handle_exception(s
 		pfpdu->rcv_nxt = fps;
 		pfpdu->fps = fps;
 		pfpdu->mode = true;
-		pfpdu->max_fpdu_data = ieq->mss;
+		pfpdu->max_fpdu_data = ieq->vsi->mss;
 		pfpdu->pmode_count++;
 		INIT_LIST_HEAD(rxlist);
 		i40iw_ieq_check_first_buf(buf, fps);
@@ -1379,14 +1433,14 @@ static void i40iw_ieq_handle_exception(s
  * @dev: iwarp device
  * @buf: exception buffer received
  */
-static void i40iw_ieq_receive(struct i40iw_sc_dev *dev,
+static void i40iw_ieq_receive(struct i40iw_sc_vsi *vsi,
 			      struct i40iw_puda_buf *buf)
 {
-	struct i40iw_puda_rsrc *ieq = dev->ieq;
+	struct i40iw_puda_rsrc *ieq = vsi->ieq;
 	struct i40iw_sc_qp *qp = NULL;
 	u32 wqe_idx = ieq->compl_rxwqe_idx;
 
-	qp = i40iw_ieq_get_qp(dev, buf);
+	qp = i40iw_ieq_get_qp(vsi->dev, buf);
 	if (!qp) {
 		ieq->stats_bad_qp_id++;
 		i40iw_puda_ret_bufpool(ieq, buf);
@@ -1404,12 +1458,12 @@ static void i40iw_ieq_receive(struct i40
 
 /**
  * i40iw_ieq_tx_compl - put back after sending completed exception buffer
- * @dev: iwarp device
+ * @vsi: pointer to the vsi structure
  * @sqwrid: pointer to puda buffer
  */
-static void i40iw_ieq_tx_compl(struct i40iw_sc_dev *dev, void *sqwrid)
+static void i40iw_ieq_tx_compl(struct i40iw_sc_vsi *vsi, void *sqwrid)
 {
-	struct i40iw_puda_rsrc *ieq = dev->ieq;
+	struct i40iw_puda_rsrc *ieq = vsi->ieq;
 	struct i40iw_puda_buf *buf = (struct i40iw_puda_buf *)sqwrid;
 
 	i40iw_puda_ret_bufpool(ieq, buf);
@@ -1421,15 +1475,14 @@ static void i40iw_ieq_tx_compl(struct i4
 
 /**
  * i40iw_ieq_cleanup_qp - qp is being destroyed
- * @dev: iwarp device
+ * @ieq: ieq resource
  * @qp: all pending fpdu buffers
  */
-void i40iw_ieq_cleanup_qp(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
+static void i40iw_ieq_cleanup_qp(struct i40iw_puda_rsrc *ieq, struct i40iw_sc_qp *qp)
 {
 	struct i40iw_puda_buf *buf;
 	struct i40iw_pfpdu *pfpdu = &qp->pfpdu;
 	struct list_head *rxlist = &pfpdu->rxlist;
-	struct i40iw_puda_rsrc *ieq = dev->ieq;
 
 	if (!pfpdu->mode)
 		return;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_puda.h	2017-02-12 16:03:20.000000000 -0500
@@ -100,6 +100,7 @@ struct i40iw_puda_rsrc_info {
 	enum puda_resource_type type;	/* ILQ or IEQ */
 	u32 count;
 	u16 pd_id;
+	bool ceq_valid;
 	u32 cq_id;
 	u32 qp_id;
 	u32 sq_size;
@@ -107,8 +108,8 @@ struct i40iw_puda_rsrc_info {
 	u16 buf_size;
 	u16 mss;
 	u32 tx_buf_cnt;		/* total bufs allocated will be rq_size + tx_buf_cnt */
-	void (*receive)(struct i40iw_sc_dev *, struct i40iw_puda_buf *);
-	void (*xmit_complete)(struct i40iw_sc_dev *, void *);
+	void (*receive)(struct i40iw_sc_vsi *, struct i40iw_puda_buf *);
+	void (*xmit_complete)(struct i40iw_sc_vsi *, void *);
 };
 
 struct i40iw_puda_rsrc {
@@ -116,6 +117,7 @@ struct i40iw_puda_rsrc {
 	struct i40iw_sc_qp qp;
 	struct i40iw_sc_pd sc_pd;
 	struct i40iw_sc_dev *dev;
+	struct i40iw_sc_vsi *vsi;
 	struct i40iw_dma_mem cqmem;
 	struct i40iw_dma_mem qpmem;
 	struct i40iw_virt_mem ilq_mem;
@@ -123,6 +125,7 @@ struct i40iw_puda_rsrc {
 	enum puda_resource_type type;
 	u16 buf_size;		/*buffer must be max datalen + tcpip hdr + mac */
 	u16 mss;
+	bool ceq_valid;
 	u32 cq_id;
 	u32 qp_id;
 	u32 sq_size;
@@ -142,8 +145,8 @@ struct i40iw_puda_rsrc {
 	u32 avail_buf_count;		/* snapshot of currently available buffers */
 	spinlock_t bufpool_lock;
 	struct i40iw_puda_buf *alloclist;
-	void (*receive)(struct i40iw_sc_dev *, struct i40iw_puda_buf *);
-	void (*xmit_complete)(struct i40iw_sc_dev *, void *);
+	void (*receive)(struct i40iw_sc_vsi *, struct i40iw_puda_buf *);
+	void (*xmit_complete)(struct i40iw_sc_vsi *, void *);
 	/* puda stats */
 	u64 stats_buf_alloc_fail;
 	u64 stats_pkt_rcvd;
@@ -160,14 +163,13 @@ void i40iw_puda_send_buf(struct i40iw_pu
 			 struct i40iw_puda_buf *buf);
 enum i40iw_status_code i40iw_puda_send(struct i40iw_sc_qp *qp,
 				       struct i40iw_puda_send_info *info);
-enum i40iw_status_code i40iw_puda_create_rsrc(struct i40iw_sc_dev *dev,
+enum i40iw_status_code i40iw_puda_create_rsrc(struct i40iw_sc_vsi *vsi,
 					      struct i40iw_puda_rsrc_info *info);
-void i40iw_puda_dele_resources(struct i40iw_sc_dev *dev,
+void i40iw_puda_dele_resources(struct i40iw_sc_vsi *vsi,
 			       enum puda_resource_type type,
 			       bool reset);
 enum i40iw_status_code i40iw_puda_poll_completion(struct i40iw_sc_dev *dev,
 						  struct i40iw_sc_cq *cq, u32 *compl_err);
-void i40iw_ieq_cleanup_qp(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp);
 
 struct i40iw_sc_qp *i40iw_ieq_get_qp(struct i40iw_sc_dev *dev,
 				     struct i40iw_puda_buf *buf);
@@ -180,4 +182,8 @@ void i40iw_ieq_mpa_crc_ae(struct i40iw_s
 void i40iw_free_hash_desc(struct shash_desc *desc);
 void i40iw_ieq_update_tcpip_info(struct i40iw_puda_buf *buf, u16 length,
 				 u32 seqnum);
+enum i40iw_status_code i40iw_cqp_qp_create_cmd(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp);
+enum i40iw_status_code i40iw_cqp_cq_create_cmd(struct i40iw_sc_dev *dev, struct i40iw_sc_cq *cq);
+void i40iw_cqp_qp_destroy_cmd(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp);
+void i40iw_cqp_cq_destroy_cmd(struct i40iw_sc_dev *dev, struct i40iw_sc_cq *cq);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_type.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_type.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_type.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_type.h	2017-02-12 16:03:20.000000000 -0500
@@ -61,7 +61,7 @@ struct i40iw_cq_shadow_area {
 
 struct i40iw_sc_dev;
 struct i40iw_hmc_info;
-struct i40iw_dev_pestat;
+struct i40iw_vsi_pestat;
 
 struct i40iw_cqp_ops;
 struct i40iw_ccq_ops;
@@ -74,6 +74,11 @@ struct i40iw_priv_qp_ops;
 struct i40iw_priv_cq_ops;
 struct i40iw_hmc_ops;
 
+enum i40iw_page_size {
+	I40IW_PAGE_SIZE_4K,
+	I40IW_PAGE_SIZE_2M
+};
+
 enum i40iw_resource_indicator_type {
 	I40IW_RSRC_INDICATOR_TYPE_ADAPTER = 0,
 	I40IW_RSRC_INDICATOR_TYPE_CQ,
@@ -186,7 +191,7 @@ enum i40iw_debug_flag {
 	I40IW_DEBUG_ALL		= 0xFFFFFFFF
 };
 
-enum i40iw_hw_stat_index_32b {
+enum i40iw_hw_stats_index_32b {
 	I40IW_HW_STAT_INDEX_IP4RXDISCARD = 0,
 	I40IW_HW_STAT_INDEX_IP4RXTRUNC,
 	I40IW_HW_STAT_INDEX_IP4TXNOROUTE,
@@ -199,7 +204,7 @@ enum i40iw_hw_stat_index_32b {
 	I40IW_HW_STAT_INDEX_MAX_32
 };
 
-enum i40iw_hw_stat_index_64b {
+enum i40iw_hw_stats_index_64b {
 	I40IW_HW_STAT_INDEX_IP4RXOCTS = 0,
 	I40IW_HW_STAT_INDEX_IP4RXPKTS,
 	I40IW_HW_STAT_INDEX_IP4RXFRAGS,
@@ -229,32 +234,23 @@ enum i40iw_hw_stat_index_64b {
 	I40IW_HW_STAT_INDEX_MAX_64
 };
 
-struct i40iw_dev_hw_stat_offsets {
-	u32 stat_offset_32[I40IW_HW_STAT_INDEX_MAX_32];
-	u32 stat_offset_64[I40IW_HW_STAT_INDEX_MAX_64];
+struct i40iw_dev_hw_stats_offsets {
+	u32 stats_offset_32[I40IW_HW_STAT_INDEX_MAX_32];
+	u32 stats_offset_64[I40IW_HW_STAT_INDEX_MAX_64];
 };
 
 struct i40iw_dev_hw_stats {
-	u64 stat_value_32[I40IW_HW_STAT_INDEX_MAX_32];
-	u64 stat_value_64[I40IW_HW_STAT_INDEX_MAX_64];
-};
-
-struct i40iw_device_pestat_ops {
-	void (*iw_hw_stat_init)(struct i40iw_dev_pestat *, u8, struct i40iw_hw *, bool);
-	void (*iw_hw_stat_read_32)(struct i40iw_dev_pestat *, enum i40iw_hw_stat_index_32b, u64 *);
-	void (*iw_hw_stat_read_64)(struct i40iw_dev_pestat *, enum i40iw_hw_stat_index_64b, u64 *);
-	void (*iw_hw_stat_read_all)(struct i40iw_dev_pestat *, struct i40iw_dev_hw_stats *);
-	void (*iw_hw_stat_refresh_all)(struct i40iw_dev_pestat *);
+	u64 stats_value_32[I40IW_HW_STAT_INDEX_MAX_32];
+	u64 stats_value_64[I40IW_HW_STAT_INDEX_MAX_64];
 };
 
-struct i40iw_dev_pestat {
+struct i40iw_vsi_pestat {
 	struct i40iw_hw *hw;
-	struct i40iw_device_pestat_ops ops;
 	struct i40iw_dev_hw_stats hw_stats;
 	struct i40iw_dev_hw_stats last_read_hw_stats;
-	struct i40iw_dev_hw_stat_offsets hw_stat_offsets;
+	struct i40iw_dev_hw_stats_offsets hw_stats_offsets;
 	struct timer_list stats_timer;
-	spinlock_t stats_lock; /* rdma stats lock */
+	spinlock_t lock; /* rdma stats lock */
 };
 
 struct i40iw_hw {
@@ -284,6 +280,7 @@ struct i40iw_sc_pd {
 	u32 size;
 	struct i40iw_sc_dev *dev;
 	u16 pd_id;
+	int abi_ver;
 };
 
 struct i40iw_cqp_quanta {
@@ -350,6 +347,7 @@ struct i40iw_sc_cq {
 	u64 cq_pa;
 	u64 shadow_area_pa;
 	struct i40iw_sc_dev *dev;
+	struct i40iw_sc_vsi *vsi;
 	void *pbl_list;
 	void *back_cq;
 	u32 ceq_id;
@@ -373,6 +371,7 @@ struct i40iw_sc_qp {
 	u64 shadow_area_pa;
 	u64 q2_pa;
 	struct i40iw_sc_dev *dev;
+	struct i40iw_sc_vsi *vsi;
 	struct i40iw_sc_pd *pd;
 	u64 *hw_host_ctx;
 	void *llp_stream_handle;
@@ -397,6 +396,9 @@ struct i40iw_sc_qp {
 	bool virtual_map;
 	bool flush_sq;
 	bool flush_rq;
+	u8 user_pri;
+	struct list_head list;
+	bool on_qoslist;
 	bool sq_flush;
 	enum i40iw_flush_opcode flush_code;
 	enum i40iw_term_eventtypes eventtype;
@@ -424,10 +426,16 @@ struct i40iw_vchnl_vf_msg_buffer {
 	char parm_buffer[I40IW_VCHNL_MAX_VF_MSG_SIZE - 1];
 };
 
+struct i40iw_qos {
+	struct list_head qplist;
+	spinlock_t lock;	/* qos list */
+	u16 qs_handle;
+};
+
 struct i40iw_vfdev {
 	struct i40iw_sc_dev *pf_dev;
 	u8 *hmc_info_mem;
-	struct i40iw_dev_pestat dev_pestat;
+	struct i40iw_vsi_pestat pestat;
 	struct i40iw_hmc_pble_info *pble_info;
 	struct i40iw_hmc_info hmc_info;
 	struct i40iw_vchnl_vf_msg_buffer vf_msg_buffer;
@@ -441,11 +449,28 @@ struct i40iw_vfdev {
 	bool stats_initialized;
 };
 
+#define I40IW_INVALID_FCN_ID 0xff
+struct i40iw_sc_vsi {
+	struct i40iw_sc_dev *dev;
+	void *back_vsi; /* Owned by OS */
+	u32 ilq_count;
+	struct i40iw_virt_mem ilq_mem;
+	struct i40iw_puda_rsrc *ilq;
+	u32 ieq_count;
+	struct i40iw_virt_mem ieq_mem;
+	struct i40iw_puda_rsrc *ieq;
+	u16 mss;
+	u8 fcn_id;
+	bool stats_fcn_id_alloc;
+	struct i40iw_qos qos[I40IW_MAX_USER_PRIORITY];
+	struct i40iw_vsi_pestat *pestat;
+};
+
 struct i40iw_sc_dev {
 	struct list_head cqp_cmd_head;	/* head of the CQP command list */
 	spinlock_t cqp_lock; /* cqp list sync */
 	struct i40iw_dev_uk dev_uk;
-	struct i40iw_dev_pestat dev_pestat;
+	bool fcn_id_array[I40IW_MAX_STATS_COUNT];
 	struct i40iw_dma_mem vf_fpm_query_buf[I40IW_MAX_PE_ENABLED_VF_COUNT];
 	u64 fpm_query_buf_pa;
 	u64 fpm_commit_buf_pa;
@@ -472,17 +497,9 @@ struct i40iw_sc_dev {
 	struct i40iw_cqp_misc_ops *cqp_misc_ops;
 	struct i40iw_hmc_ops *hmc_ops;
 	struct i40iw_vchnl_if vchnl_if;
-	u32 ilq_count;
-	struct i40iw_virt_mem ilq_mem;
-	struct i40iw_puda_rsrc *ilq;
-	u32 ieq_count;
-	struct i40iw_virt_mem ieq_mem;
-	struct i40iw_puda_rsrc *ieq;
-
 	const struct i40iw_vf_cqp_ops *iw_vf_cqp_ops;
 
 	struct i40iw_hmc_fpm_misc hmc_fpm_misc;
-	u16 qs_handle;
 	u32 debug_mask;
 	u16 exception_lan_queue;
 	u8 hmc_fn_id;
@@ -556,6 +573,19 @@ struct i40iw_l2params {
 	u16 mss;
 };
 
+struct i40iw_vsi_init_info {
+	struct i40iw_sc_dev *dev;
+	void  *back_vsi;
+	struct i40iw_l2params *params;
+};
+
+struct i40iw_vsi_stats_info {
+	struct i40iw_vsi_pestat *pestat;
+	u8 fcn_id;
+	bool alloc_fcn_id;
+	bool stats_initialize;
+};
+
 struct i40iw_device_init_info {
 	u64 fpm_query_buf_pa;
 	u64 fpm_commit_buf_pa;
@@ -564,7 +594,6 @@ struct i40iw_device_init_info {
 	struct i40iw_hw *hw;
 	void __iomem *bar0;
 	enum i40iw_status_code (*vchnl_send)(struct i40iw_sc_dev *, u32, u8 *, u16);
-	u16 qs_handle;
 	u16 exception_lan_queue;
 	u8 hmc_fn_id;
 	bool is_pf;
@@ -722,6 +751,8 @@ struct i40iw_qp_host_ctx_info {
 	bool iwarp_info_valid;
 	bool err_rq_idx_valid;
 	u16 err_rq_idx;
+	bool add_to_qoslist;
+	u8 user_pri;
 };
 
 struct i40iw_aeqe_info {
@@ -814,6 +845,7 @@ struct i40iw_register_shared_stag {
 struct i40iw_qp_init_info {
 	struct i40iw_qp_uk_init_info qp_uk_init_info;
 	struct i40iw_sc_pd *pd;
+	struct i40iw_sc_vsi *vsi;
 	u64 *host_ctx;
 	u8 *q2;
 	u64 sq_pa;
@@ -821,6 +853,7 @@ struct i40iw_qp_init_info {
 	u64 host_ctx_pa;
 	u64 q2_pa;
 	u64 shadow_area_pa;
+	int abi_ver;
 	u8 sq_tph_val;
 	u8 rq_tph_val;
 	u8 type;
@@ -880,13 +913,14 @@ enum i40iw_quad_hash_manage_type {
 };
 
 struct i40iw_qhash_table_info {
+	struct i40iw_sc_vsi *vsi;
 	enum i40iw_quad_hash_manage_type manage;
 	enum i40iw_quad_entry_type entry_type;
 	bool vlan_valid;
 	bool ipv4_valid;
 	u8 mac_addr[6];
 	u16 vlan_id;
-	u16 qs_handle;
+	u8 user_pri;
 	u32 qp_num;
 	u32 dest_ip[4];
 	u32 src_ip[4];
@@ -976,7 +1010,7 @@ struct i40iw_cqp_query_fpm_values {
 struct i40iw_cqp_ops {
 	enum i40iw_status_code (*cqp_init)(struct i40iw_sc_cqp *,
 					   struct i40iw_cqp_init_info *);
-	enum i40iw_status_code (*cqp_create)(struct i40iw_sc_cqp *, bool, u16 *, u16 *);
+	enum i40iw_status_code (*cqp_create)(struct i40iw_sc_cqp *, u16 *, u16 *);
 	void (*cqp_post_sq)(struct i40iw_sc_cqp *);
 	u64 *(*cqp_get_next_send_wqe)(struct i40iw_sc_cqp *, u64 scratch);
 	enum i40iw_status_code (*cqp_destroy)(struct i40iw_sc_cqp *);
@@ -1019,7 +1053,7 @@ struct i40iw_aeq_ops {
 };
 
 struct i40iw_pd_ops {
-	void (*pd_init)(struct i40iw_sc_dev *, struct i40iw_sc_pd *, u16);
+	void (*pd_init)(struct i40iw_sc_dev *, struct i40iw_sc_pd *, u16, int);
 };
 
 struct i40iw_priv_qp_ops {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_ucontext.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_ucontext.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_ucontext.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_ucontext.h	2017-02-12 16:03:20.000000000 -0500
@@ -39,8 +39,8 @@
 
 #include <linux/types.h>
 
-#define I40IW_ABI_USERSPACE_VER 4
-#define I40IW_ABI_KERNEL_VER    4
+#define I40IW_ABI_VER 5
+
 struct i40iw_alloc_ucontext_req {
 	__u32 reserved32;
 	__u8 userspace_ver;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_uk.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_uk.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_uk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_uk.c	2017-02-12 16:03:20.000000000 -0500
@@ -175,12 +175,10 @@ u64 *i40iw_qp_get_next_send_wqe(struct i
 		if (!*wqe_idx)
 			qp->swqe_polarity = !qp->swqe_polarity;
 	}
-
-	for (i = 0; i < wqe_size / I40IW_QP_WQE_MIN_SIZE; i++) {
-		I40IW_RING_MOVE_HEAD(qp->sq_ring, ret_code);
-		if (ret_code)
-			return NULL;
-	}
+	I40IW_RING_MOVE_HEAD_BY_COUNT(qp->sq_ring,
+				      wqe_size / I40IW_QP_WQE_MIN_SIZE, ret_code);
+	if (ret_code)
+		return NULL;
 
 	wqe = qp->sq_base[*wqe_idx].elem;
 
@@ -430,7 +428,7 @@ static enum i40iw_status_code i40iw_inli
 	struct i40iw_inline_rdma_write *op_info;
 	u64 *push;
 	u64 header = 0;
-	u32 i, wqe_idx;
+	u32 wqe_idx;
 	enum i40iw_status_code ret_code;
 	bool read_fence = false;
 	u8 wqe_size;
@@ -465,14 +463,12 @@ static enum i40iw_status_code i40iw_inli
 	src = (u8 *)(op_info->data);
 
 	if (op_info->len <= 16) {
-		for (i = 0; i < op_info->len; i++, src++, dest++)
-			*dest = *src;
+		memcpy(dest, src, op_info->len);
 	} else {
-		for (i = 0; i < 16; i++, src++, dest++)
-			*dest = *src;
+		memcpy(dest, src, 16);
+		src += 16;
 		dest = (u8 *)wqe + 32;
-		for (; i < op_info->len; i++, src++, dest++)
-			*dest = *src;
+		memcpy(dest, src, op_info->len - 16);
 	}
 
 	wmb(); /* make sure WQE is populated before valid bit is set */
@@ -507,7 +503,7 @@ static enum i40iw_status_code i40iw_inli
 	u8 *dest, *src;
 	struct i40iw_post_inline_send *op_info;
 	u64 header;
-	u32 wqe_idx, i;
+	u32 wqe_idx;
 	enum i40iw_status_code ret_code;
 	bool read_fence = false;
 	u8 wqe_size;
@@ -540,14 +536,12 @@ static enum i40iw_status_code i40iw_inli
 	src = (u8 *)(op_info->data);
 
 	if (op_info->len <= 16) {
-		for (i = 0; i < op_info->len; i++, src++, dest++)
-			*dest = *src;
+		memcpy(dest, src, op_info->len);
 	} else {
-		for (i = 0; i < 16; i++, src++, dest++)
-			*dest = *src;
+		memcpy(dest, src, 16);
+		src += 16;
 		dest = (u8 *)wqe + 32;
-		for (; i < op_info->len; i++, src++, dest++)
-			*dest = *src;
+		memcpy(dest, src, op_info->len - 16);
 	}
 
 	wmb(); /* make sure WQE is populated before valid bit is set */
@@ -972,10 +966,6 @@ enum i40iw_status_code i40iw_qp_uk_init(
 	if (ret_code)
 		return ret_code;
 
-	ret_code = i40iw_get_wqe_shift(info->rq_size, info->max_rq_frag_cnt, 0, &rqshift);
-	if (ret_code)
-		return ret_code;
-
 	qp->sq_base = info->sq;
 	qp->rq_base = info->rq;
 	qp->shadow_area = info->shadow_area;
@@ -1004,8 +994,19 @@ enum i40iw_status_code i40iw_qp_uk_init(
 	if (!qp->use_srq) {
 		qp->rq_size = info->rq_size;
 		qp->max_rq_frag_cnt = info->max_rq_frag_cnt;
-		qp->rq_wqe_size = rqshift;
 		I40IW_RING_INIT(qp->rq_ring, qp->rq_size);
+		switch (info->abi_ver) {
+		case 4:
+			ret_code = i40iw_get_wqe_shift(info->rq_size, info->max_rq_frag_cnt, 0, &rqshift);
+			if (ret_code)
+				return ret_code;
+			break;
+		case 5: /* fallthrough until next ABI version */
+		default:
+			rqshift = I40IW_MAX_RQ_WQE_SHIFT;
+			break;
+		}
+		qp->rq_wqe_size = rqshift;
 		qp->rq_wqe_size_multiplier = 4 << rqshift;
 	}
 	qp->ops = iw_qp_uk_ops;
@@ -1190,12 +1191,8 @@ enum i40iw_status_code i40iw_inline_data
 
 	if (data_size <= 16)
 		*wqe_size = I40IW_QP_WQE_MIN_SIZE;
-	else if (data_size <= 48)
-		*wqe_size = 64;
-	else if (data_size <= 80)
-		*wqe_size = 96;
 	else
-		*wqe_size = 128;
+		*wqe_size = 64;
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_user.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_user.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_user.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_user.h	2017-02-12 16:03:20.000000000 -0500
@@ -72,12 +72,13 @@ enum i40iw_device_capabilities_const {
 	I40IW_MAX_SQ_PAYLOAD_SIZE =		2145386496,
 	I40IW_MAX_INLINE_DATA_SIZE =		48,
 	I40IW_MAX_PUSHMODE_INLINE_DATA_SIZE =	48,
-	I40IW_MAX_IRD_SIZE =			32,
-	I40IW_QPCTX_ENCD_MAXIRD =		3,
+	I40IW_MAX_IRD_SIZE =			63,
+	I40IW_MAX_ORD_SIZE =			127,
 	I40IW_MAX_WQ_ENTRIES =			2048,
-	I40IW_MAX_ORD_SIZE =			32,
 	I40IW_Q2_BUFFER_SIZE =			(248 + 100),
-	I40IW_QP_CTX_SIZE =			248
+	I40IW_MAX_WQE_SIZE_RQ =			128,
+	I40IW_QP_CTX_SIZE =			248,
+	I40IW_MAX_PDS = 			32768
 };
 
 #define i40iw_handle void *
@@ -96,13 +97,8 @@ enum i40iw_device_capabilities_const {
 #define i40iw_physical_fragment u64
 #define i40iw_address_list u64 *
 
-#define I40IW_CREATE_STAG(index, key)       (((index) << 8) + (key))
-
-#define I40IW_STAG_KEY_FROM_STAG(stag)      ((stag) && 0x000000FF)
-
-#define I40IW_STAG_INDEX_FROM_STAG(stag)    (((stag) && 0xFFFFFF00) >> 8)
-
 #define	I40IW_MAX_MR_SIZE	0x10000000000L
+#define	I40IW_MAX_RQ_WQE_SHIFT	2
 
 struct i40iw_qp_uk;
 struct i40iw_cq_uk;
@@ -411,7 +407,7 @@ struct i40iw_qp_uk_init_info {
 	u32 max_sq_frag_cnt;
 	u32 max_rq_frag_cnt;
 	u32 max_inline_data;
-
+	int abi_ver;
 };
 
 struct i40iw_cq_uk_init_info {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_utils.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_utils.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_utils.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_utils.c	2017-02-12 16:03:20.000000000 -0500
@@ -153,6 +153,7 @@ int i40iw_inetaddr_event(struct notifier
 	struct i40iw_device *iwdev;
 	struct i40iw_handler *hdl;
 	u32 local_ipaddr;
+	u32 action = I40IW_ARP_ADD;
 
 	hdl = i40iw_find_netdev(event_netdev);
 	if (!hdl)
@@ -164,44 +165,25 @@ int i40iw_inetaddr_event(struct notifier
 	if (netdev != event_netdev)
 		return NOTIFY_DONE;
 
+	if (upper_dev)
+		local_ipaddr = ntohl(
+			((struct in_device *)upper_dev->ip_ptr)->ifa_list->ifa_address);
+	else
+		local_ipaddr = ntohl(ifa->ifa_address);
 	switch (event) {
 	case NETDEV_DOWN:
-		if (upper_dev)
-			local_ipaddr = ntohl(
-				((struct in_device *)upper_dev->ip_ptr)->ifa_list->ifa_address);
-		else
-			local_ipaddr = ntohl(ifa->ifa_address);
-		i40iw_manage_arp_cache(iwdev,
-				       netdev->dev_addr,
-				       &local_ipaddr,
-				       true,
-				       I40IW_ARP_DELETE);
-		return NOTIFY_OK;
+		action = I40IW_ARP_DELETE;
+		/* Fall through */
 	case NETDEV_UP:
-		if (upper_dev)
-			local_ipaddr = ntohl(
-				((struct in_device *)upper_dev->ip_ptr)->ifa_list->ifa_address);
-		else
-			local_ipaddr = ntohl(ifa->ifa_address);
-		i40iw_manage_arp_cache(iwdev,
-				       netdev->dev_addr,
-				       &local_ipaddr,
-				       true,
-				       I40IW_ARP_ADD);
-		break;
+		/* Fall through */
 	case NETDEV_CHANGEADDR:
-		/* Add the address to the IP table */
-		if (upper_dev)
-			local_ipaddr = ntohl(
-				((struct in_device *)upper_dev->ip_ptr)->ifa_list->ifa_address);
-		else
-			local_ipaddr = ntohl(ifa->ifa_address);
-
 		i40iw_manage_arp_cache(iwdev,
 				       netdev->dev_addr,
 				       &local_ipaddr,
 				       true,
-				       I40IW_ARP_ADD);
+				       action);
+		i40iw_if_notify(iwdev, netdev, &local_ipaddr, true,
+				(action == I40IW_ARP_ADD) ? true : false);
 		break;
 	default:
 		break;
@@ -225,6 +207,7 @@ int i40iw_inet6addr_event(struct notifie
 	struct i40iw_device *iwdev;
 	struct i40iw_handler *hdl;
 	u32 local_ipaddr6[4];
+	u32 action = I40IW_ARP_ADD;
 
 	hdl = i40iw_find_netdev(event_netdev);
 	if (!hdl)
@@ -235,24 +218,21 @@ int i40iw_inet6addr_event(struct notifie
 	if (netdev != event_netdev)
 		return NOTIFY_DONE;
 
+	i40iw_copy_ip_ntohl(local_ipaddr6, ifa->addr.in6_u.u6_addr32);
 	switch (event) {
 	case NETDEV_DOWN:
-		i40iw_copy_ip_ntohl(local_ipaddr6, ifa->addr.in6_u.u6_addr32);
-		i40iw_manage_arp_cache(iwdev,
-				       netdev->dev_addr,
-				       local_ipaddr6,
-				       false,
-				       I40IW_ARP_DELETE);
-		return NOTIFY_OK;
+		action = I40IW_ARP_DELETE;
+		/* Fall through */
 	case NETDEV_UP:
 		/* Fall through */
 	case NETDEV_CHANGEADDR:
-		i40iw_copy_ip_ntohl(local_ipaddr6, ifa->addr.in6_u.u6_addr32);
 		i40iw_manage_arp_cache(iwdev,
 				       netdev->dev_addr,
 				       local_ipaddr6,
 				       false,
-				       I40IW_ARP_ADD);
+				       action);
+		i40iw_if_notify(iwdev, netdev, local_ipaddr6, false,
+				(action == I40IW_ARP_ADD) ? true : false);
 		break;
 	default:
 		break;
@@ -392,6 +372,7 @@ static void i40iw_free_qp(struct i40iw_c
 
 	i40iw_rem_pdusecount(iwqp->iwpd, iwdev);
 	i40iw_free_qp_resources(iwdev, iwqp, qp_num);
+	i40iw_rem_devusecount(iwdev);
 }
 
 /**
@@ -415,7 +396,10 @@ static int i40iw_wait_event(struct i40iw
 		i40iw_pr_err("error cqp command 0x%x timed out ret = %d\n",
 			     info->cqp_cmd, timeout_ret);
 		err_code = -ETIME;
-		i40iw_request_reset(iwdev);
+		if (!iwdev->reset) {
+			iwdev->reset = true;
+			i40iw_request_reset(iwdev);
+		}
 		goto done;
 	}
 	cqp_error = cqp_request->compl_info.error;
@@ -445,6 +429,11 @@ enum i40iw_status_code i40iw_handle_cqp_
 	struct cqp_commands_info *info = &cqp_request->info;
 	int err_code = 0;
 
+	if (iwdev->reset) {
+		i40iw_free_cqp_request(&iwdev->cqp, cqp_request);
+		return I40IW_ERR_CQP_COMPL_ERROR;
+	}
+
 	status = i40iw_process_cqp_cmd(dev, info);
 	if (status) {
 		i40iw_pr_err("error cqp command 0x%x failed\n", info->cqp_cmd);
@@ -459,6 +448,26 @@ enum i40iw_status_code i40iw_handle_cqp_
 }
 
 /**
+ * i40iw_add_devusecount - add dev refcount
+ * @iwdev: dev for refcount
+ */
+void i40iw_add_devusecount(struct i40iw_device *iwdev)
+{
+	atomic64_inc(&iwdev->use_count);
+}
+
+/**
+ * i40iw_rem_devusecount - decrement refcount for dev
+ * @iwdev: device
+ */
+void i40iw_rem_devusecount(struct i40iw_device *iwdev)
+{
+	if (!atomic64_dec_and_test(&iwdev->use_count))
+		return;
+	wake_up(&iwdev->close_wq);
+}
+
+/**
  * i40iw_add_pdusecount - add pd refcount
  * @iwpd: pd for refcount
  */
@@ -712,6 +721,51 @@ enum i40iw_status_code i40iw_cqp_sds_cmd
 }
 
 /**
+ * i40iw_qp_suspend_resume - cqp command for suspend/resume
+ * @dev: hardware control device structure
+ * @qp: hardware control qp
+ * @suspend: flag if suspend or resume
+ */
+void i40iw_qp_suspend_resume(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp, bool suspend)
+{
+	struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+	struct i40iw_cqp_request *cqp_request;
+	struct i40iw_sc_cqp *cqp = dev->cqp;
+	struct cqp_commands_info *cqp_info;
+	enum i40iw_status_code status;
+
+	cqp_request = i40iw_get_cqp_request(&iwdev->cqp, false);
+	if (!cqp_request)
+		return;
+
+	cqp_info = &cqp_request->info;
+	cqp_info->cqp_cmd = (suspend) ? OP_SUSPEND : OP_RESUME;
+	cqp_info->in.u.suspend_resume.cqp = cqp;
+	cqp_info->in.u.suspend_resume.qp = qp;
+	cqp_info->in.u.suspend_resume.scratch = (uintptr_t)cqp_request;
+	status = i40iw_handle_cqp_op(iwdev, cqp_request);
+	if (status)
+		i40iw_pr_err("CQP-OP QP Suspend/Resume fail");
+}
+
+/**
+ * i40iw_qp_mss_modify - modify mss for qp
+ * @dev: hardware control device structure
+ * @qp: hardware control qp
+ */
+void i40iw_qp_mss_modify(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
+{
+	struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+	struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp;
+	struct i40iw_modify_qp_info info;
+
+	memset(&info, 0, sizeof(info));
+	info.mss_change = true;
+	info.new_mss = qp->vsi->mss;
+	i40iw_hw_modify_qp(iwdev, iwqp, &info, false);
+}
+
+/**
  * i40iw_term_modify_qp - modify qp for term message
  * @qp: hardware control qp
  * @next_state: qp's next state
@@ -769,6 +823,7 @@ static void i40iw_terminate_timeout(unsi
 	struct i40iw_sc_qp *qp = (struct i40iw_sc_qp *)&iwqp->sc_qp;
 
 	i40iw_terminate_done(qp, 1);
+	i40iw_rem_ref(&iwqp->ibqp);
 }
 
 /**
@@ -780,6 +835,7 @@ void i40iw_terminate_start_timer(struct
 	struct i40iw_qp *iwqp;
 
 	iwqp = (struct i40iw_qp *)qp->back_qp;
+	i40iw_add_ref(&iwqp->ibqp);
 	init_timer(&iwqp->terminate_timer);
 	iwqp->terminate_timer.function = i40iw_terminate_timeout;
 	iwqp->terminate_timer.expires = jiffies + HZ;
@@ -796,7 +852,8 @@ void i40iw_terminate_del_timer(struct i4
 	struct i40iw_qp *iwqp;
 
 	iwqp = (struct i40iw_qp *)qp->back_qp;
-	del_timer(&iwqp->terminate_timer);
+	if (del_timer(&iwqp->terminate_timer))
+		i40iw_rem_ref(&iwqp->ibqp);
 }
 
 /**
@@ -1011,6 +1068,116 @@ enum i40iw_status_code i40iw_vf_wait_vch
 }
 
 /**
+ * i40iw_cqp_cq_create_cmd - create a cq for the cqp
+ * @dev: device pointer
+ * @cq: pointer to created cq
+ */
+enum i40iw_status_code i40iw_cqp_cq_create_cmd(struct i40iw_sc_dev *dev,
+					       struct i40iw_sc_cq *cq)
+{
+	struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+	struct i40iw_cqp *iwcqp = &iwdev->cqp;
+	struct i40iw_cqp_request *cqp_request;
+	struct cqp_commands_info *cqp_info;
+	enum i40iw_status_code status;
+
+	cqp_request = i40iw_get_cqp_request(iwcqp, true);
+	if (!cqp_request)
+		return I40IW_ERR_NO_MEMORY;
+
+	cqp_info = &cqp_request->info;
+	cqp_info->cqp_cmd = OP_CQ_CREATE;
+	cqp_info->post_sq = 1;
+	cqp_info->in.u.cq_create.cq = cq;
+	cqp_info->in.u.cq_create.scratch = (uintptr_t)cqp_request;
+	status = i40iw_handle_cqp_op(iwdev, cqp_request);
+	if (status)
+		i40iw_pr_err("CQP-OP Create QP fail");
+
+	return status;
+}
+
+/**
+ * i40iw_cqp_qp_create_cmd - create a qp for the cqp
+ * @dev: device pointer
+ * @qp: pointer to created qp
+ */
+enum i40iw_status_code i40iw_cqp_qp_create_cmd(struct i40iw_sc_dev *dev,
+					       struct i40iw_sc_qp *qp)
+{
+	struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+	struct i40iw_cqp *iwcqp = &iwdev->cqp;
+	struct i40iw_cqp_request *cqp_request;
+	struct cqp_commands_info *cqp_info;
+	struct i40iw_create_qp_info *qp_info;
+	enum i40iw_status_code status;
+
+	cqp_request = i40iw_get_cqp_request(iwcqp, true);
+	if (!cqp_request)
+		return I40IW_ERR_NO_MEMORY;
+
+	cqp_info = &cqp_request->info;
+	qp_info = &cqp_request->info.in.u.qp_create.info;
+
+	memset(qp_info, 0, sizeof(*qp_info));
+
+	qp_info->cq_num_valid = true;
+	qp_info->next_iwarp_state = I40IW_QP_STATE_RTS;
+
+	cqp_info->cqp_cmd = OP_QP_CREATE;
+	cqp_info->post_sq = 1;
+	cqp_info->in.u.qp_create.qp = qp;
+	cqp_info->in.u.qp_create.scratch = (uintptr_t)cqp_request;
+	status = i40iw_handle_cqp_op(iwdev, cqp_request);
+	if (status)
+		i40iw_pr_err("CQP-OP QP create fail");
+	return status;
+}
+
+/**
+ * i40iw_cqp_cq_destroy_cmd - destroy the cqp cq
+ * @dev: device pointer
+ * @cq: pointer to cq
+ */
+void i40iw_cqp_cq_destroy_cmd(struct i40iw_sc_dev *dev, struct i40iw_sc_cq *cq)
+{
+	struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+
+	i40iw_cq_wq_destroy(iwdev, cq);
+}
+
+/**
+ * i40iw_cqp_qp_destroy_cmd - destroy the cqp
+ * @dev: device pointer
+ * @qp: pointer to qp
+ */
+void i40iw_cqp_qp_destroy_cmd(struct i40iw_sc_dev *dev, struct i40iw_sc_qp *qp)
+{
+	struct i40iw_device *iwdev = (struct i40iw_device *)dev->back_dev;
+	struct i40iw_cqp *iwcqp = &iwdev->cqp;
+	struct i40iw_cqp_request *cqp_request;
+	struct cqp_commands_info *cqp_info;
+	enum i40iw_status_code status;
+
+	cqp_request = i40iw_get_cqp_request(iwcqp, true);
+	if (!cqp_request)
+		return;
+
+	cqp_info = &cqp_request->info;
+	memset(cqp_info, 0, sizeof(*cqp_info));
+
+	cqp_info->cqp_cmd = OP_QP_DESTROY;
+	cqp_info->post_sq = 1;
+	cqp_info->in.u.qp_destroy.qp = qp;
+	cqp_info->in.u.qp_destroy.scratch = (uintptr_t)cqp_request;
+	cqp_info->in.u.qp_destroy.remove_hash_idx = true;
+	status = i40iw_handle_cqp_op(iwdev, cqp_request);
+	if (status)
+		i40iw_pr_err("CQP QP_DESTROY fail");
+}
+
+
+/**
  * i40iw_ieq_mpa_crc_ae - generate AE for crc error
  * @dev: hardware control device structure
  * @qp: hardware control qp
@@ -1208,7 +1375,7 @@ enum i40iw_status_code i40iw_puda_get_tc
 
 	buf->totallen = pkt_len + buf->maclen;
 
-	if (info->payload_len < buf->totallen - 4) {
+	if (info->payload_len < buf->totallen) {
 		i40iw_pr_err("payload_len = 0x%x totallen expected0x%x\n",
 			     info->payload_len, buf->totallen);
 		return I40IW_ERR_INVALID_SIZE;
@@ -1224,27 +1391,29 @@ enum i40iw_status_code i40iw_puda_get_tc
 
 /**
  * i40iw_hw_stats_timeout - Stats timer-handler which updates all HW stats
- * @dev: hardware control device structure
+ * @vsi: pointer to the vsi structure
  */
-static void i40iw_hw_stats_timeout(unsigned long dev)
+static void i40iw_hw_stats_timeout(unsigned long vsi)
 {
-	struct i40iw_sc_dev *pf_dev = (struct i40iw_sc_dev *)dev;
-	struct i40iw_dev_pestat *pf_devstat = &pf_dev->dev_pestat;
-	struct i40iw_dev_pestat *vf_devstat = NULL;
+	struct i40iw_sc_vsi *sc_vsi =  (struct i40iw_sc_vsi *)vsi;
+	struct i40iw_sc_dev *pf_dev = sc_vsi->dev;
+	struct i40iw_vsi_pestat *pf_devstat = sc_vsi->pestat;
+	struct i40iw_vsi_pestat *vf_devstat = NULL;
 	u16 iw_vf_idx;
 	unsigned long flags;
 
 	/*PF*/
-	pf_devstat->ops.iw_hw_stat_read_all(pf_devstat, &pf_devstat->hw_stats);
+	i40iw_hw_stats_read_all(pf_devstat, &pf_devstat->hw_stats);
+
 	for (iw_vf_idx = 0; iw_vf_idx < I40IW_MAX_PE_ENABLED_VF_COUNT; iw_vf_idx++) {
-		spin_lock_irqsave(&pf_devstat->stats_lock, flags);
+		spin_lock_irqsave(&pf_devstat->lock, flags);
 		if (pf_dev->vf_dev[iw_vf_idx]) {
 			if (pf_dev->vf_dev[iw_vf_idx]->stats_initialized) {
-				vf_devstat = &pf_dev->vf_dev[iw_vf_idx]->dev_pestat;
-				vf_devstat->ops.iw_hw_stat_read_all(vf_devstat, &vf_devstat->hw_stats);
+				vf_devstat = &pf_dev->vf_dev[iw_vf_idx]->pestat;
+				i40iw_hw_stats_read_all(vf_devstat, &vf_devstat->hw_stats);
 			}
 		}
-		spin_unlock_irqrestore(&pf_devstat->stats_lock, flags);
+		spin_unlock_irqrestore(&pf_devstat->lock, flags);
 	}
 
 	mod_timer(&pf_devstat->stats_timer,
@@ -1253,26 +1422,26 @@ static void i40iw_hw_stats_timeout(unsig
 
 /**
  * i40iw_hw_stats_start_timer - Start periodic stats timer
- * @dev: hardware control device structure
+ * @vsi: pointer to the vsi structure
  */
-void i40iw_hw_stats_start_timer(struct i40iw_sc_dev *dev)
+void i40iw_hw_stats_start_timer(struct i40iw_sc_vsi *vsi)
 {
-	struct i40iw_dev_pestat *devstat = &dev->dev_pestat;
+	struct i40iw_vsi_pestat *devstat = vsi->pestat;
 
 	init_timer(&devstat->stats_timer);
 	devstat->stats_timer.function = i40iw_hw_stats_timeout;
-	devstat->stats_timer.data = (unsigned long)dev;
+	devstat->stats_timer.data = (unsigned long)vsi;
 	mod_timer(&devstat->stats_timer,
 		  jiffies + msecs_to_jiffies(STATS_TIMER_DELAY));
 }
 
 /**
- * i40iw_hw_stats_del_timer - Delete periodic stats timer
- * @dev: hardware control device structure
+ * i40iw_hw_stats_stop_timer - Delete periodic stats timer
+ * @vsi: pointer to the vsi structure
  */
-void i40iw_hw_stats_del_timer(struct i40iw_sc_dev *dev)
+void i40iw_hw_stats_stop_timer(struct i40iw_sc_vsi *vsi)
 {
-	struct i40iw_dev_pestat *devstat = &dev->dev_pestat;
+	struct i40iw_vsi_pestat *devstat = vsi->pestat;
 
 	del_timer_sync(&devstat->stats_timer);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/random.h>
 #include <linux/highmem.h>
 #include <linux/time.h>
+#include <linux/hugetlb.h>
 #include <asm/byteorder.h>
 #include <net/ip.h>
 #include <rdma/ib_verbs.h>
@@ -67,13 +68,13 @@ static int i40iw_query_device(struct ib_
 	props->vendor_part_id = iwdev->ldev->pcidev->device;
 	props->hw_ver = (u32)iwdev->sc_dev.hw_rev;
 	props->max_mr_size = I40IW_MAX_OUTBOUND_MESSAGE_SIZE;
-	props->max_qp = iwdev->max_qp;
+	props->max_qp = iwdev->max_qp - iwdev->used_qps;
 	props->max_qp_wr = (I40IW_MAX_WQ_ENTRIES >> 2) - 1;
 	props->max_sge = I40IW_MAX_WQ_FRAGMENT_COUNT;
-	props->max_cq = iwdev->max_cq;
+	props->max_cq = iwdev->max_cq - iwdev->used_cqs;
 	props->max_cqe = iwdev->max_cqe;
-	props->max_mr = iwdev->max_mr;
-	props->max_pd = iwdev->max_pd;
+	props->max_mr = iwdev->max_mr - iwdev->used_mrs;
+	props->max_pd = iwdev->max_pd - iwdev->used_pds;
 	props->max_sge_rd = I40IW_MAX_SGE_RD;
 	props->max_qp_rd_atom = I40IW_MAX_IRD_SIZE;
 	props->max_qp_init_rd_atom = props->max_qp_rd_atom;
@@ -99,16 +100,7 @@ static int i40iw_query_port(struct ib_de
 	memset(props, 0, sizeof(*props));
 
 	props->max_mtu = IB_MTU_4096;
-	if (netdev->mtu >= 4096)
-		props->active_mtu = IB_MTU_4096;
-	else if (netdev->mtu >= 2048)
-		props->active_mtu = IB_MTU_2048;
-	else if (netdev->mtu >= 1024)
-		props->active_mtu = IB_MTU_1024;
-	else if (netdev->mtu >= 512)
-		props->active_mtu = IB_MTU_512;
-	else
-		props->active_mtu = IB_MTU_256;
+	props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
 	props->lid = 1;
 	if (netif_carrier_ok(iwdev->netdev))
@@ -144,9 +136,8 @@ static struct ib_ucontext *i40iw_alloc_u
 	if (ib_copy_from_udata(&req, udata, sizeof(req)))
 		return ERR_PTR(-EINVAL);
 
-	if (req.userspace_ver != I40IW_ABI_USERSPACE_VER) {
-		i40iw_pr_err("Invalid userspace driver version detected. Detected version %d, should be %d\n",
-			     req.userspace_ver, I40IW_ABI_USERSPACE_VER);
+	if (req.userspace_ver < 4 || req.userspace_ver > I40IW_ABI_VER) {
+		i40iw_pr_err("Unsupported provider library version %u.\n", req.userspace_ver);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -154,13 +145,14 @@ static struct ib_ucontext *i40iw_alloc_u
 	uresp.max_qps = iwdev->max_qp;
 	uresp.max_pds = iwdev->max_pd;
 	uresp.wq_size = iwdev->max_qp_wr * 2;
-	uresp.kernel_ver = I40IW_ABI_KERNEL_VER;
+	uresp.kernel_ver = req.userspace_ver;
 
 	ucontext = kzalloc(sizeof(*ucontext), GFP_KERNEL);
 	if (!ucontext)
 		return ERR_PTR(-ENOMEM);
 
 	ucontext->iwdev = iwdev;
+	ucontext->abi_ver = req.userspace_ver;
 
 	if (ib_copy_to_udata(udata, &uresp, sizeof(uresp))) {
 		kfree(ucontext);
@@ -254,7 +246,6 @@ static void i40iw_alloc_push_page(struct
 {
 	struct i40iw_cqp_request *cqp_request;
 	struct cqp_commands_info *cqp_info;
-	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
 	enum i40iw_status_code status;
 
 	if (qp->push_idx != I40IW_INVALID_PUSH_PAGE_INDEX)
@@ -270,7 +261,7 @@ static void i40iw_alloc_push_page(struct
 	cqp_info->cqp_cmd = OP_MANAGE_PUSH_PAGE;
 	cqp_info->post_sq = 1;
 
-	cqp_info->in.u.manage_push_page.info.qs_handle = dev->qs_handle;
+	cqp_info->in.u.manage_push_page.info.qs_handle = qp->qs_handle;
 	cqp_info->in.u.manage_push_page.info.free_page = 0;
 	cqp_info->in.u.manage_push_page.cqp = &iwdev->cqp.sc_cqp;
 	cqp_info->in.u.manage_push_page.scratch = (uintptr_t)cqp_request;
@@ -292,7 +283,6 @@ static void i40iw_dealloc_push_page(stru
 {
 	struct i40iw_cqp_request *cqp_request;
 	struct cqp_commands_info *cqp_info;
-	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
 	enum i40iw_status_code status;
 
 	if (qp->push_idx == I40IW_INVALID_PUSH_PAGE_INDEX)
@@ -307,7 +297,7 @@ static void i40iw_dealloc_push_page(stru
 	cqp_info->post_sq = 1;
 
 	cqp_info->in.u.manage_push_page.info.push_idx = qp->push_idx;
-	cqp_info->in.u.manage_push_page.info.qs_handle = dev->qs_handle;
+	cqp_info->in.u.manage_push_page.info.qs_handle = qp->qs_handle;
 	cqp_info->in.u.manage_push_page.info.free_page = 1;
 	cqp_info->in.u.manage_push_page.cqp = &iwdev->cqp.sc_cqp;
 	cqp_info->in.u.manage_push_page.scratch = (uintptr_t)cqp_request;
@@ -334,9 +324,13 @@ static struct ib_pd *i40iw_alloc_pd(stru
 	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
 	struct i40iw_alloc_pd_resp uresp;
 	struct i40iw_sc_pd *sc_pd;
+	struct i40iw_ucontext *ucontext;
 	u32 pd_id = 0;
 	int err;
 
+	if (iwdev->closing)
+		return ERR_PTR(-ENODEV);
+
 	err = i40iw_alloc_resource(iwdev, iwdev->allocated_pds,
 				   iwdev->max_pd, &pd_id, &iwdev->next_pd);
 	if (err) {
@@ -351,15 +345,18 @@ static struct ib_pd *i40iw_alloc_pd(stru
 	}
 
 	sc_pd = &iwpd->sc_pd;
-	dev->iw_pd_ops->pd_init(dev, sc_pd, pd_id);
 
 	if (context) {
+		ucontext = to_ucontext(context);
+		dev->iw_pd_ops->pd_init(dev, sc_pd, pd_id, ucontext->abi_ver);
 		memset(&uresp, 0, sizeof(uresp));
 		uresp.pd_id = pd_id;
 		if (ib_copy_to_udata(udata, &uresp, sizeof(uresp))) {
 			err = -EFAULT;
 			goto error;
 		}
+	} else {
+		dev->iw_pd_ops->pd_init(dev, sc_pd, pd_id, -1);
 	}
 
 	i40iw_add_pdusecount(iwpd);
@@ -516,7 +513,7 @@ static int i40iw_setup_kmode_qp(struct i
 	struct i40iw_dma_mem *mem = &iwqp->kqp.dma_mem;
 	u32 sqdepth, rqdepth;
 	u32 sq_size, rq_size;
-	u8 sqshift, rqshift;
+	u8 sqshift;
 	u32 size;
 	enum i40iw_status_code status;
 	struct i40iw_qp_uk_init_info *ukinfo = &info->qp_uk_init_info;
@@ -525,14 +522,11 @@ static int i40iw_setup_kmode_qp(struct i
 	rq_size = i40iw_qp_roundup(ukinfo->rq_size + 1);
 
 	status = i40iw_get_wqe_shift(sq_size, ukinfo->max_sq_frag_cnt, ukinfo->max_inline_data, &sqshift);
-	if (!status)
-		status = i40iw_get_wqe_shift(rq_size, ukinfo->max_rq_frag_cnt, 0, &rqshift);
-
 	if (status)
 		return -ENOMEM;
 
 	sqdepth = sq_size << sqshift;
-	rqdepth = rq_size << rqshift;
+	rqdepth = rq_size << I40IW_MAX_RQ_WQE_SHIFT;
 
 	size = sqdepth * sizeof(struct i40iw_sq_uk_wr_trk_info) + (rqdepth << 3);
 	iwqp->kqp.wrid_mem = kzalloc(size, GFP_KERNEL);
@@ -602,6 +596,9 @@ static struct ib_qp *i40iw_create_qp(str
 	struct i40iwarp_offload_info *iwarp_info;
 	unsigned long flags;
 
+	if (iwdev->closing)
+		return ERR_PTR(-ENODEV);
+
 	if (init_attr->create_flags)
 		return ERR_PTR(-EINVAL);
 	if (init_attr->cap.max_inline_data > I40IW_MAX_INLINE_DATA_SIZE)
@@ -610,11 +607,15 @@ static struct ib_qp *i40iw_create_qp(str
 	if (init_attr->cap.max_send_sge > I40IW_MAX_WQ_FRAGMENT_COUNT)
 		init_attr->cap.max_send_sge = I40IW_MAX_WQ_FRAGMENT_COUNT;
 
+	if (init_attr->cap.max_recv_sge > I40IW_MAX_WQ_FRAGMENT_COUNT)
+		init_attr->cap.max_recv_sge = I40IW_MAX_WQ_FRAGMENT_COUNT;
+
 	memset(&init_info, 0, sizeof(init_info));
 
 	sq_size = init_attr->cap.max_send_wr;
 	rq_size = init_attr->cap.max_recv_wr;
 
+	init_info.vsi = &iwdev->vsi;
 	init_info.qp_uk_init_info.sq_size = sq_size;
 	init_info.qp_uk_init_info.rq_size = rq_size;
 	init_info.qp_uk_init_info.max_sq_frag_cnt = init_attr->cap.max_send_sge;
@@ -774,6 +775,7 @@ static struct ib_qp *i40iw_create_qp(str
 	iwqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ? 1 : 0;
 	iwdev->qp_table[qp_num] = iwqp;
 	i40iw_add_pdusecount(iwqp->iwpd);
+	i40iw_add_devusecount(iwdev);
 	if (ibpd->uobject && udata) {
 		memset(&uresp, 0, sizeof(uresp));
 		uresp.actual_sq_size = sq_size;
@@ -815,8 +817,9 @@ static int i40iw_query_qp(struct ib_qp *
 	attr->qp_access_flags = 0;
 	attr->cap.max_send_wr = qp->qp_uk.sq_size;
 	attr->cap.max_recv_wr = qp->qp_uk.rq_size;
-	attr->cap.max_recv_sge = 1;
 	attr->cap.max_inline_data = I40IW_MAX_INLINE_DATA_SIZE;
+	attr->cap.max_send_sge = I40IW_MAX_WQ_FRAGMENT_COUNT;
+	attr->cap.max_recv_sge = I40IW_MAX_WQ_FRAGMENT_COUNT;
 	init_attr->event_handler = iwqp->ibqp.event_handler;
 	init_attr->qp_context = iwqp->ibqp.qp_context;
 	init_attr->send_cq = iwqp->ibqp.send_cq;
@@ -884,6 +887,11 @@ int i40iw_modify_qp(struct ib_qp *ibqp,
 	spin_lock_irqsave(&iwqp->lock, flags);
 
 	if (attr_mask & IB_QP_STATE) {
+		if (iwdev->closing && attr->qp_state != IB_QPS_ERR) {
+			err = -EINVAL;
+			goto exit;
+		}
+
 		switch (attr->qp_state) {
 		case IB_QPS_INIT:
 		case IB_QPS_RTR:
@@ -944,7 +952,7 @@ int i40iw_modify_qp(struct ib_qp *ibqp,
 				goto exit;
 			}
 			if (iwqp->sc_qp.term_flags)
-				del_timer(&iwqp->terminate_timer);
+				i40iw_terminate_del_timer(&iwqp->sc_qp);
 			info.next_iwarp_state = I40IW_QP_STATE_ERROR;
 			if ((iwqp->hw_tcp_state > I40IW_TCP_STATE_CLOSED) &&
 			    iwdev->iw_status &&
@@ -1037,11 +1045,11 @@ static void cq_free_resources(struct i40
 }
 
 /**
- * cq_wq_destroy - send cq destroy cqp
+ * i40iw_cq_wq_destroy - send cq destroy cqp
  * @iwdev: iwarp device
  * @cq: hardware control cq
  */
-static void cq_wq_destroy(struct i40iw_device *iwdev, struct i40iw_sc_cq *cq)
+void i40iw_cq_wq_destroy(struct i40iw_device *iwdev, struct i40iw_sc_cq *cq)
 {
 	enum i40iw_status_code status;
 	struct i40iw_cqp_request *cqp_request;
@@ -1080,9 +1088,10 @@ static int i40iw_destroy_cq(struct ib_cq
 	iwcq = to_iwcq(ib_cq);
 	iwdev = to_iwdev(ib_cq->device);
 	cq = &iwcq->sc_cq;
-	cq_wq_destroy(iwdev, cq);
+	i40iw_cq_wq_destroy(iwdev, cq);
 	cq_free_resources(iwdev, iwcq);
 	kfree(iwcq);
+	i40iw_rem_devusecount(iwdev);
 	return 0;
 }
 
@@ -1113,6 +1122,9 @@ static struct ib_cq *i40iw_create_cq(str
 	int err_code;
 	int entries = attr->cqe;
 
+	if (iwdev->closing)
+		return ERR_PTR(-ENODEV);
+
 	if (entries > iwdev->max_cqe)
 		return ERR_PTR(-EINVAL);
 
@@ -1137,7 +1149,8 @@ static struct ib_cq *i40iw_create_cq(str
 	ukinfo->cq_id = cq_num;
 	iwcq->ibcq.cqe = info.cq_uk_init_info.cq_size;
 	info.ceqe_mask = 0;
-	info.ceq_id = 0;
+	if (attr->comp_vector < iwdev->ceqs_count)
+		info.ceq_id = attr->comp_vector;
 	info.ceq_id_valid = true;
 	info.ceqe_mask = 1;
 	info.type = I40IW_CQ_TYPE_IWARP;
@@ -1229,10 +1242,11 @@ static struct ib_cq *i40iw_create_cq(str
 		}
 	}
 
+	i40iw_add_devusecount(iwdev);
 	return (struct ib_cq *)iwcq;
 
 cq_destroy:
-	cq_wq_destroy(iwdev, cq);
+	i40iw_cq_wq_destroy(iwdev, cq);
 cq_free_resources:
 	cq_free_resources(iwdev, iwcq);
 error:
@@ -1266,6 +1280,7 @@ static void i40iw_free_stag(struct i40iw
 
 	stag_idx = (stag & iwdev->mr_stagmask) >> I40IW_CQPSQ_STAG_IDX_SHIFT;
 	i40iw_free_resource(iwdev, iwdev->allocated_mrs, stag_idx);
+	i40iw_rem_devusecount(iwdev);
 }
 
 /**
@@ -1296,19 +1311,18 @@ static u32 i40iw_create_stag(struct i40i
 		stag = stag_index << I40IW_CQPSQ_STAG_IDX_SHIFT;
 		stag |= driver_key;
 		stag += (u32)consumer_key;
+		i40iw_add_devusecount(iwdev);
 	}
 	return stag;
 }
 
 /**
  * i40iw_next_pbl_addr - Get next pbl address
- * @palloc: Poiner to allocated pbles
  * @pbl: pointer to a pble
  * @pinfo: info pointer
  * @idx: index
  */
-static inline u64 *i40iw_next_pbl_addr(struct i40iw_pble_alloc *palloc,
-				       u64 *pbl,
+static inline u64 *i40iw_next_pbl_addr(u64 *pbl,
 				       struct i40iw_pble_info **pinfo,
 				       u32 *idx)
 {
@@ -1336,9 +1350,11 @@ static void i40iw_copy_user_pgaddrs(stru
 	struct i40iw_pble_alloc *palloc = &iwpbl->pble_alloc;
 	struct i40iw_pble_info *pinfo;
 	struct scatterlist *sg;
+	u64 pg_addr = 0;
 	u32 idx = 0;
 
 	pinfo = (level == I40IW_LEVEL_1) ? NULL : palloc->level2.leaf;
+
 	pg_shift = ffs(region->page_size) - 1;
 	for_each_sg(region->sg_head.sgl, sg, region->nmap, entry) {
 		chunk_pages = sg_dma_len(sg) >> pg_shift;
@@ -1346,17 +1362,96 @@ static void i40iw_copy_user_pgaddrs(stru
 		    !iwpbl->qp_mr.sq_page)
 			iwpbl->qp_mr.sq_page = sg_page(sg);
 		for (i = 0; i < chunk_pages; i++) {
-			*pbl = cpu_to_le64(sg_dma_address(sg) + region->page_size * i);
-			pbl = i40iw_next_pbl_addr(palloc, pbl, &pinfo, &idx);
+			pg_addr = sg_dma_address(sg) + region->page_size * i;
+
+			if ((entry + i) == 0)
+				*pbl = cpu_to_le64(pg_addr & iwmr->page_msk);
+			else if (!(pg_addr & ~iwmr->page_msk))
+				*pbl = cpu_to_le64(pg_addr);
+			else
+				continue;
+			pbl = i40iw_next_pbl_addr(pbl, &pinfo, &idx);
 		}
 	}
 }
 
 /**
+ * i40iw_set_hugetlb_params - set MR pg size and mask to huge pg values.
+ * @addr: virtual address
+ * @iwmr: mr pointer for this memory registration
+ */
+static void i40iw_set_hugetlb_values(u64 addr, struct i40iw_mr *iwmr)
+{
+	struct vm_area_struct *vma;
+	struct hstate *h;
+
+	vma = find_vma(current->mm, addr);
+	if (vma && is_vm_hugetlb_page(vma)) {
+		h = hstate_vma(vma);
+		if (huge_page_size(h) == 0x200000) {
+			iwmr->page_size = huge_page_size(h);
+			iwmr->page_msk = huge_page_mask(h);
+		}
+	}
+}
+
+/**
+ * i40iw_check_mem_contiguous - check if pbls stored in arr are contiguous
+ * @arr: lvl1 pbl array
+ * @npages: page count
+ * pg_size: page size
+ *
+ */
+static bool i40iw_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size)
+{
+	u32 pg_idx;
+
+	for (pg_idx = 0; pg_idx < npages; pg_idx++) {
+		if ((*arr + (pg_size * pg_idx)) != arr[pg_idx])
+			return false;
+	}
+	return true;
+}
+
+/**
+ * i40iw_check_mr_contiguous - check if MR is physically contiguous
+ * @palloc: pbl allocation struct
+ * pg_size: page size
+ */
+static bool i40iw_check_mr_contiguous(struct i40iw_pble_alloc *palloc, u32 pg_size)
+{
+	struct i40iw_pble_level2 *lvl2 = &palloc->level2;
+	struct i40iw_pble_info *leaf = lvl2->leaf;
+	u64 *arr = NULL;
+	u64 *start_addr = NULL;
+	int i;
+	bool ret;
+
+	if (palloc->level == I40IW_LEVEL_1) {
+		arr = (u64 *)palloc->level1.addr;
+		ret = i40iw_check_mem_contiguous(arr, palloc->total_cnt, pg_size);
+		return ret;
+	}
+
+	start_addr = (u64 *)leaf->addr;
+
+	for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) {
+		arr = (u64 *)leaf->addr;
+		if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr)
+			return false;
+		ret = i40iw_check_mem_contiguous(arr, leaf->cnt, pg_size);
+		if (!ret)
+			return false;
+	}
+
+	return true;
+}
+
+/**
  * i40iw_setup_pbles - copy user pg address to pble's
  * @iwdev: iwarp device
  * @iwmr: mr pointer for this memory registration
- * @use_pbles: flag if to use pble's or memory (level 0)
+ * @use_pbles: flag if to use pble's
  */
 static int i40iw_setup_pbles(struct i40iw_device *iwdev,
 			     struct i40iw_mr *iwmr,
@@ -1369,9 +1464,6 @@ static int i40iw_setup_pbles(struct i40i
 	enum i40iw_status_code status;
 	enum i40iw_pble_level level = I40IW_LEVEL_1;
 
-	if (!use_pbles && (iwmr->page_cnt > MAX_SAVE_PAGE_ADDRS))
-		return -ENOMEM;
-
 	if (use_pbles) {
 		mutex_lock(&iwdev->pbl_mutex);
 		status = i40iw_get_pble(&iwdev->sc_dev, iwdev->pble_rsrc, palloc, iwmr->page_cnt);
@@ -1388,6 +1480,10 @@ static int i40iw_setup_pbles(struct i40i
 	}
 
 	i40iw_copy_user_pgaddrs(iwmr, pbl, level);
+
+	if (use_pbles)
+		iwmr->pgaddrmem[0] = *pbl;
+
 	return 0;
 }
 
@@ -1409,14 +1505,18 @@ static int i40iw_handle_q_mem(struct i40
 	struct i40iw_cq_mr *cqmr = &iwpbl->cq_mr;
 	struct i40iw_hmc_pble *hmc_p;
 	u64 *arr = iwmr->pgaddrmem;
+	u32 pg_size;
 	int err;
 	int total;
+	bool ret = true;
 
 	total = req->sq_pages + req->rq_pages + req->cq_pages;
+	pg_size = iwmr->page_size;
 
 	err = i40iw_setup_pbles(iwdev, iwmr, use_pbles);
 	if (err)
 		return err;
+
 	if (use_pbles && (palloc->level != I40IW_LEVEL_1)) {
 		i40iw_free_pble(iwdev->pble_rsrc, palloc);
 		iwpbl->pbl_allocated = false;
@@ -1425,26 +1525,44 @@ static int i40iw_handle_q_mem(struct i40
 
 	if (use_pbles)
 		arr = (u64 *)palloc->level1.addr;
-	if (req->reg_type == IW_MEMREG_TYPE_QP) {
+
+	if (iwmr->type == IW_MEMREG_TYPE_QP) {
 		hmc_p = &qpmr->sq_pbl;
 		qpmr->shadow = (dma_addr_t)arr[total];
+
 		if (use_pbles) {
+			ret = i40iw_check_mem_contiguous(arr, req->sq_pages, pg_size);
+			if (ret)
+				ret = i40iw_check_mem_contiguous(&arr[req->sq_pages], req->rq_pages, pg_size);
+		}
+
+		if (!ret) {
 			hmc_p->idx = palloc->level1.idx;
 			hmc_p = &qpmr->rq_pbl;
 			hmc_p->idx = palloc->level1.idx + req->sq_pages;
 		} else {
 			hmc_p->addr = arr[0];
 			hmc_p = &qpmr->rq_pbl;
-			hmc_p->addr = arr[1];
+			hmc_p->addr = arr[req->sq_pages];
 		}
 	} else {		/* CQ */
 		hmc_p = &cqmr->cq_pbl;
 		cqmr->shadow = (dma_addr_t)arr[total];
+
 		if (use_pbles)
+			ret = i40iw_check_mem_contiguous(arr, req->cq_pages, pg_size);
+
+		if (!ret)
 			hmc_p->idx = palloc->level1.idx;
 		else
 			hmc_p->addr = arr[0];
 	}
+
+	if (use_pbles && ret) {
+		i40iw_free_pble(iwdev->pble_rsrc, palloc);
+		iwpbl->pbl_allocated = false;
+	}
+
 	return err;
 }
 
@@ -1642,8 +1760,9 @@ static int i40iw_hwreg_mr(struct i40iw_d
 	stag_info->access_rights = access;
 	stag_info->pd_id = iwpd->sc_pd.pd_id;
 	stag_info->addr_type = I40IW_ADDR_TYPE_VA_BASED;
+	stag_info->page_size = iwmr->page_size;
 
-	if (iwmr->page_cnt > 1) {
+	if (iwpbl->pbl_allocated) {
 		if (palloc->level == I40IW_LEVEL_1) {
 			stag_info->first_pm_pbl_index = palloc->level1.idx;
 			stag_info->chunk_size = 1;
@@ -1699,6 +1818,11 @@ static struct ib_mr *i40iw_reg_user_mr(s
 	bool use_pbles = false;
 	unsigned long flags;
 	int err = -ENOSYS;
+	int ret;
+	int pg_shift;
+
+	if (iwdev->closing)
+		return ERR_PTR(-ENODEV);
 
 	if (length > I40IW_MAX_MR_SIZE)
 		return ERR_PTR(-EINVAL);
@@ -1723,9 +1847,17 @@ static struct ib_mr *i40iw_reg_user_mr(s
 	iwmr->ibmr.pd = pd;
 	iwmr->ibmr.device = pd->device;
 	ucontext = to_ucontext(pd->uobject->context);
-	region_length = region->length + (start & 0xfff);
-	pbl_depth = region_length >> 12;
-	pbl_depth += (region_length & (4096 - 1)) ? 1 : 0;
+
+	iwmr->page_size = region->page_size;
+	iwmr->page_msk = PAGE_MASK;
+
+	if (region->hugetlb && (req.reg_type == IW_MEMREG_TYPE_MEM))
+		i40iw_set_hugetlb_values(start, iwmr);
+
+	region_length = region->length + (start & (iwmr->page_size - 1));
+	pg_shift = ffs(iwmr->page_size) - 1;
+	pbl_depth = region_length >> pg_shift;
+	pbl_depth += (region_length & (iwmr->page_size - 1)) ? 1 : 0;
 	iwmr->length = region->length;
 
 	iwpbl->user_base = virt;
@@ -1755,13 +1887,21 @@ static struct ib_mr *i40iw_reg_user_mr(s
 		spin_unlock_irqrestore(&ucontext->cq_reg_mem_list_lock, flags);
 		break;
 	case IW_MEMREG_TYPE_MEM:
+		use_pbles = (iwmr->page_cnt != 1);
 		access = I40IW_ACCESS_FLAGS_LOCALREAD;
 
-		use_pbles = (iwmr->page_cnt != 1);
 		err = i40iw_setup_pbles(iwdev, iwmr, use_pbles);
 		if (err)
 			goto error;
 
+		if (use_pbles) {
+			ret = i40iw_check_mr_contiguous(palloc, iwmr->page_size);
+			if (ret) {
+				i40iw_free_pble(iwdev->pble_rsrc, palloc);
+				iwpbl->pbl_allocated = false;
+			}
+		}
+
 		access |= i40iw_get_user_access(acc);
 		stag = i40iw_create_stag(iwdev);
 		if (!stag) {
@@ -1778,6 +1918,7 @@ static struct ib_mr *i40iw_reg_user_mr(s
 			i40iw_free_stag(iwdev, stag);
 			goto error;
 		}
+
 		break;
 	default:
 		goto error;
@@ -1789,7 +1930,7 @@ static struct ib_mr *i40iw_reg_user_mr(s
 	return &iwmr->ibmr;
 
 error:
-	if (palloc->level != I40IW_LEVEL_0)
+	if (palloc->level != I40IW_LEVEL_0 && iwpbl->pbl_allocated)
 		i40iw_free_pble(iwdev->pble_rsrc, palloc);
 	ib_umem_release(region);
 	kfree(iwmr);
@@ -2142,7 +2283,6 @@ static int i40iw_post_send(struct ib_qp
 		case IB_WR_REG_MR:
 		{
 			struct i40iw_mr *iwmr = to_iwmr(reg_wr(ib_wr)->mr);
-			int page_shift = ilog2(reg_wr(ib_wr)->mr->page_size);
 			int flags = reg_wr(ib_wr)->access;
 			struct i40iw_pble_alloc *palloc = &iwmr->iwpbl.pble_alloc;
 			struct i40iw_sc_dev *dev = &iwqp->iwdev->sc_dev;
@@ -2153,6 +2293,7 @@ static int i40iw_post_send(struct ib_qp
 			info.access_rights |= i40iw_get_user_access(flags);
 			info.stag_key = reg_wr(ib_wr)->key & 0xff;
 			info.stag_idx = reg_wr(ib_wr)->key >> 8;
+			info.page_size = reg_wr(ib_wr)->mr->page_size;
 			info.wr_id = ib_wr->wr_id;
 
 			info.addr_type = I40IW_ADDR_TYPE_VA_BASED;
@@ -2166,9 +2307,6 @@ static int i40iw_post_send(struct ib_qp
 			if (iwmr->npages > I40IW_MIN_PAGES_PER_FMR)
 				info.chunk_size = 1;
 
-			if (page_shift == 21)
-				info.page_size = 1; /* 2M page */
-
 			ret = dev->iw_priv_qp_ops->iw_mr_fast_register(&iwqp->sc_qp, &info, true);
 			if (ret)
 				err = -ENOMEM;
@@ -2487,21 +2625,17 @@ static int i40iw_get_hw_stats(struct ib_
 {
 	struct i40iw_device *iwdev = to_iwdev(ibdev);
 	struct i40iw_sc_dev *dev = &iwdev->sc_dev;
-	struct i40iw_dev_pestat *devstat = &dev->dev_pestat;
+	struct i40iw_vsi_pestat *devstat = iwdev->vsi.pestat;
 	struct i40iw_dev_hw_stats *hw_stats = &devstat->hw_stats;
-	unsigned long flags;
 
 	if (dev->is_pf) {
-		spin_lock_irqsave(&devstat->stats_lock, flags);
-		devstat->ops.iw_hw_stat_read_all(devstat,
-			&devstat->hw_stats);
-		spin_unlock_irqrestore(&devstat->stats_lock, flags);
+		i40iw_hw_stats_read_all(devstat, &devstat->hw_stats);
 	} else {
 		if (i40iw_vchnl_vf_get_pe_stats(dev, &devstat->hw_stats))
 			return -ENOSYS;
 	}
 
-	memcpy(&stats->value[0], &hw_stats, sizeof(*hw_stats));
+	memcpy(&stats->value[0], hw_stats, sizeof(*hw_stats));
 
 	return stats->num_counters;
 }
@@ -2562,7 +2696,9 @@ static int i40iw_query_pkey(struct ib_de
  * @ah_attr: address handle attributes
  */
 static struct ib_ah *i40iw_create_ah(struct ib_pd *ibpd,
-				     struct ib_ah_attr *attr)
+				     struct ib_ah_attr *attr,
+				     struct ib_udata *udata)
+
 {
 	return ERR_PTR(-ENOSYS);
 }
@@ -2621,7 +2757,7 @@ static struct i40iw_ib_device *i40iw_ini
 	    (1ull << IB_USER_VERBS_CMD_POST_RECV) |
 	    (1ull << IB_USER_VERBS_CMD_POST_SEND);
 	iwibdev->ibdev.phys_port_cnt = 1;
-	iwibdev->ibdev.num_comp_vectors = 1;
+	iwibdev->ibdev.num_comp_vectors = iwdev->ceqs_count;
 	iwibdev->ibdev.dma_device = &pcidev->dev;
 	iwibdev->ibdev.dev.parent = &pcidev->dev;
 	iwibdev->ibdev.query_port = i40iw_query_port;
@@ -2654,7 +2790,6 @@ static struct i40iw_ib_device *i40iw_ini
 	iwibdev->ibdev.iwcm = kzalloc(sizeof(*iwibdev->ibdev.iwcm), GFP_KERNEL);
 	if (!iwibdev->ibdev.iwcm) {
 		ib_dealloc_device(&iwibdev->ibdev);
-		i40iw_pr_err("iwcm == NULL\n");
 		return NULL;
 	}
 
@@ -2719,6 +2854,9 @@ void i40iw_destroy_rdma_device(struct i4
 	i40iw_unregister_rdma_device(iwibdev);
 	kfree(iwibdev->ibdev.iwcm);
 	iwibdev->ibdev.iwcm = NULL;
+	wait_event_timeout(iwibdev->iwdev->close_wq,
+			   !atomic64_read(&iwibdev->iwdev->use_count),
+			   I40IW_EVENT_TIMEOUT);
 	ib_dealloc_device(&iwibdev->ibdev);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_verbs.h	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,7 @@ struct i40iw_ucontext {
 	spinlock_t cq_reg_mem_list_lock; /* memory list for cq's */
 	struct list_head qp_reg_mem_list;
 	spinlock_t qp_reg_mem_list_lock; /* memory list for qp's */
+	int abi_ver;
 };
 
 struct i40iw_pd {
@@ -92,6 +93,8 @@ struct i40iw_mr {
 	struct ib_umem *region;
 	u16 type;
 	u32 page_cnt;
+	u32 page_size;
+	u64 page_msk;
 	u32 npages;
 	u32 stag;
 	u64 length;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/i40iw/i40iw_virtchnl.c	2017-02-12 16:03:20.000000000 -0500
@@ -403,6 +403,19 @@ del_out:
 }
 
 /**
+ * i40iw_vf_init_pestat - Initialize stats for VF
+ * @devL pointer to the VF Device
+ * @stats: Statistics structure pointer
+ * @index: Stats index
+ */
+static void i40iw_vf_init_pestat(struct i40iw_sc_dev *dev, struct i40iw_vsi_pestat *stats, u16 index)
+{
+	stats->hw = dev->hw;
+	i40iw_hw_stats_init(stats, (u8)index, false);
+	spin_lock_init(&stats->lock);
+}
+
+/**
  * i40iw_vchnl_recv_pf - Receive PF virtual channel messages
  * @dev: IWARP device pointer
  * @vf_id: Virtual function ID associated with the message
@@ -421,9 +434,8 @@ enum i40iw_status_code i40iw_vchnl_recv_
 	u16 first_avail_iw_vf = I40IW_MAX_PE_ENABLED_VF_COUNT;
 	struct i40iw_virt_mem vf_dev_mem;
 	struct i40iw_virtchnl_work_info work_info;
-	struct i40iw_dev_pestat *devstat;
+	struct i40iw_vsi_pestat *stats;
 	enum i40iw_status_code ret_code;
-	unsigned long flags;
 
 	if (!dev || !msg || !len)
 		return I40IW_ERR_PARAM;
@@ -496,14 +508,7 @@ enum i40iw_status_code i40iw_vchnl_recv_
 				i40iw_debug(dev, I40IW_DEBUG_VIRT,
 					    "VF%u error CQP HMC Function operation.\n",
 					    vf_id);
-			ret_code = i40iw_device_init_pestat(&vf_dev->dev_pestat);
-			if (ret_code)
-				i40iw_debug(dev, I40IW_DEBUG_VIRT,
-					    "VF%u - i40iw_device_init_pestat failed\n",
-					    vf_id);
-			vf_dev->dev_pestat.ops.iw_hw_stat_init(&vf_dev->dev_pestat,
-							      (u8)vf_dev->pmf_index,
-							      dev->hw, false);
+			i40iw_vf_init_pestat(dev, &vf_dev->pestat, vf_dev->pmf_index);
 			vf_dev->stats_initialized = true;
 		} else {
 			if (vf_dev) {
@@ -534,12 +539,10 @@ enum i40iw_status_code i40iw_vchnl_recv_
 	case I40IW_VCHNL_OP_GET_STATS:
 		if (!vf_dev)
 			return I40IW_ERR_BAD_PTR;
-		devstat = &vf_dev->dev_pestat;
-		spin_lock_irqsave(&dev->dev_pestat.stats_lock, flags);
-		devstat->ops.iw_hw_stat_read_all(devstat, &devstat->hw_stats);
-		spin_unlock_irqrestore(&dev->dev_pestat.stats_lock, flags);
+		stats = &vf_dev->pestat;
+		i40iw_hw_stats_read_all(stats, &stats->hw_stats);
 		vf_dev->msg_count--;
-		vchnl_pf_send_get_pe_stats_resp(dev, vf_id, vchnl_msg, &devstat->hw_stats);
+		vchnl_pf_send_get_pe_stats_resp(dev, vf_id, vchnl_msg, &stats->hw_stats);
 		break;
 	default:
 		i40iw_debug(dev, I40IW_DEBUG_VIRT,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/Makefile linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/Makefile
--- linux-libre-4.9-gnu/drivers/infiniband/hw/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@ obj-$(CONFIG_MLX4_INFINIBAND)		+= mlx4/
 obj-$(CONFIG_MLX5_INFINIBAND)		+= mlx5/
 obj-$(CONFIG_INFINIBAND_NES)		+= nes/
 obj-$(CONFIG_INFINIBAND_OCRDMA)		+= ocrdma/
+obj-$(CONFIG_INFINIBAND_VMWARE_PVRDMA)	+= vmw_pvrdma/
 obj-$(CONFIG_INFINIBAND_USNIC)		+= usnic/
 obj-$(CONFIG_INFINIBAND_HFI1)		+= hfi1/
 obj-$(CONFIG_INFINIBAND_HNS)		+= hns/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/ah.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/ah.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/ah.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/ah.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,7 +114,9 @@ static struct ib_ah *create_iboe_ah(stru
 		       !(1 << ah->av.eth.stat_rate & dev->caps.stat_rate_support))
 			--ah->av.eth.stat_rate;
 	}
-
+	ah->av.eth.sl_tclass_flowlabel |=
+			cpu_to_be32((ah_attr->grh.traffic_class << 20) |
+				    ah_attr->grh.flow_label);
 	/*
 	 * HW requires multicast LID so we just choose one.
 	 */
@@ -122,12 +124,14 @@ static struct ib_ah *create_iboe_ah(stru
 		ah->av.ib.dlid = cpu_to_be16(0xc000);
 
 	memcpy(ah->av.eth.dgid, ah_attr->grh.dgid.raw, 16);
-	ah->av.eth.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 29);
+	ah->av.eth.sl_tclass_flowlabel |= cpu_to_be32(ah_attr->sl << 29);
 
 	return &ah->ibah;
 }
 
-struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				struct ib_udata *udata)
+
 {
 	struct mlx4_ib_ah *ah;
 	struct ib_ah *ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/alias_GUID.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/alias_GUID.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/alias_GUID.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/alias_GUID.c	2017-02-12 16:03:20.000000000 -0500
@@ -755,10 +755,8 @@ static void alias_guid_work(struct work_
 	struct mlx4_ib_dev *dev = container_of(ib_sriov, struct mlx4_ib_dev, sriov);
 
 	rec = kzalloc(sizeof *rec, GFP_KERNEL);
-	if (!rec) {
-		pr_err("alias_guid_work: No Memory\n");
+	if (!rec)
 		return;
-	}
 
 	pr_debug("starting [port: %d]...\n", sriov_alias_port->port + 1);
 	ret = get_next_record_to_update(dev, sriov_alias_port->port, rec);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/cm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/cm.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -247,10 +247,8 @@ id_map_alloc(struct ib_device *ibdev, in
 	struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
 
 	ent = kmalloc(sizeof (struct id_map_entry), GFP_KERNEL);
-	if (!ent) {
-		mlx4_ib_warn(ibdev, "Couldn't allocate id cache entry - out of memory\n");
+	if (!ent)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	ent->sl_cm_id = sl_cm_id;
 	ent->slave_id = slave_id;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/mad.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/mad.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/mad.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/mad.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,8 @@
 #include <linux/mlx4/cmd.h>
 #include <linux/gfp.h>
 #include <rdma/ib_pma.h>
+#include <linux/ip.h>
+#include <net/ipv6.h>
 
 #include <linux/mlx4/driver.h>
 #include "mlx4_ib.h"
@@ -480,6 +482,23 @@ static int find_slave_port_pkey_ix(struc
 	return -EINVAL;
 }
 
+static int get_gids_from_l3_hdr(struct ib_grh *grh, union ib_gid *sgid,
+				union ib_gid *dgid)
+{
+	int version = ib_get_rdma_header_version((const union rdma_network_hdr *)grh);
+	enum rdma_network_type net_type;
+
+	if (version == 4)
+		net_type = RDMA_NETWORK_IPV4;
+	else if (version == 6)
+		net_type = RDMA_NETWORK_IPV6;
+	else
+		return -EINVAL;
+
+	return ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type,
+					 sgid, dgid);
+}
+
 int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
 			  enum ib_qp_type dest_qpt, struct ib_wc *wc,
 			  struct ib_grh *grh, struct ib_mad *mad)
@@ -538,7 +557,10 @@ int mlx4_ib_send_to_slave(struct mlx4_ib
 	memset(&attr, 0, sizeof attr);
 	attr.port_num = port;
 	if (is_eth) {
-		memcpy(&attr.grh.dgid.raw[0], &grh->dgid.raw[0], 16);
+		union ib_gid sgid;
+
+		if (get_gids_from_l3_hdr(grh, &sgid, &attr.grh.dgid))
+			return -EINVAL;
 		attr.ah_flags = IB_AH_GRH;
 	}
 	ah = ib_create_ah(tun_ctx->pd, &attr);
@@ -651,6 +673,11 @@ static int mlx4_ib_demux_mad(struct ib_d
 		is_eth = 1;
 
 	if (is_eth) {
+		union ib_gid dgid;
+		union ib_gid sgid;
+
+		if (get_gids_from_l3_hdr(grh, &sgid, &dgid))
+			return -EINVAL;
 		if (!(wc->wc_flags & IB_WC_GRH)) {
 			mlx4_ib_warn(ibdev, "RoCE grh not present.\n");
 			return -EINVAL;
@@ -659,10 +686,10 @@ static int mlx4_ib_demux_mad(struct ib_d
 			mlx4_ib_warn(ibdev, "RoCE mgmt class is not CM\n");
 			return -EINVAL;
 		}
-		err = mlx4_get_slave_from_roce_gid(dev->dev, port, grh->dgid.raw, &slave);
+		err = mlx4_get_slave_from_roce_gid(dev->dev, port, dgid.raw, &slave);
 		if (err && mlx4_is_mf_bonded(dev->dev)) {
 			other_port = (port == 1) ? 2 : 1;
-			err = mlx4_get_slave_from_roce_gid(dev->dev, other_port, grh->dgid.raw, &slave);
+			err = mlx4_get_slave_from_roce_gid(dev->dev, other_port, dgid.raw, &slave);
 			if (!err) {
 				port = other_port;
 				pr_debug("resolved slave %d from gid %pI6 wire port %d other %d\n",
@@ -702,10 +729,18 @@ static int mlx4_ib_demux_mad(struct ib_d
 
 	/* If a grh is present, we demux according to it */
 	if (wc->wc_flags & IB_WC_GRH) {
-		slave = mlx4_ib_find_real_gid(ibdev, port, grh->dgid.global.interface_id);
-		if (slave < 0) {
-			mlx4_ib_warn(ibdev, "failed matching grh\n");
-			return -ENOENT;
+		if (grh->dgid.global.interface_id ==
+			cpu_to_be64(IB_SA_WELL_KNOWN_GUID) &&
+		    grh->dgid.global.subnet_prefix == cpu_to_be64(
+			atomic64_read(&dev->sriov.demux[port - 1].subnet_prefix))) {
+			slave = 0;
+		} else {
+			slave = mlx4_ib_find_real_gid(ibdev, port,
+						      grh->dgid.global.interface_id);
+			if (slave < 0) {
+				mlx4_ib_warn(ibdev, "failed matching grh\n");
+				return -ENOENT;
+			}
 		}
 	}
 	/* Class-specific handling */
@@ -1102,10 +1137,8 @@ static void handle_slaves_guid_change(st
 
 	in_mad  = kmalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
-	if (!in_mad || !out_mad) {
-		mlx4_ib_warn(&dev->ib_dev, "failed to allocate memory for guid info mads\n");
+	if (!in_mad || !out_mad)
 		goto out;
-	}
 
 	guid_tbl_blk_num  *= 4;
 
@@ -1916,11 +1949,8 @@ static int alloc_pv_object(struct mlx4_i
 
 	*ret_ctx = NULL;
 	ctx = kzalloc(sizeof (struct mlx4_ib_demux_pv_ctx), GFP_KERNEL);
-	if (!ctx) {
-		pr_err("failed allocating pv resource context "
-		       "for port %d, slave %d\n", port, slave);
+	if (!ctx)
 		return -ENOMEM;
-	}
 
 	ctx->ib_dev = &dev->ib_dev;
 	ctx->port = port;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -430,7 +430,7 @@ static int mlx4_ib_query_device(struct i
 	struct mlx4_ib_dev *dev = to_mdev(ibdev);
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
-	int err = -ENOMEM;
+	int err;
 	int have_ib_ports;
 	struct mlx4_uverbs_ex_query_device cmd;
 	struct mlx4_uverbs_ex_query_device_resp resp = {.comp_mask = 0};
@@ -455,6 +455,7 @@ static int mlx4_ib_query_device(struct i
 		sizeof(resp.response_length);
 	in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
 	out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
+	err = -ENOMEM;
 	if (!in_mad || !out_mad)
 		goto out;
 
@@ -547,6 +548,7 @@ static int mlx4_ib_query_device(struct i
 	props->max_map_per_fmr = dev->dev->caps.max_fmr_maps;
 	props->hca_core_clock = dev->dev->caps.hca_core_clock * 1000UL;
 	props->timestamp_mask = 0xFFFFFFFFFFFFULL;
+	props->max_ah = INT_MAX;
 
 	if (!mlx4_is_slave(dev->dev))
 		err = mlx4_get_internal_clock_params(dev->dev, &clock_params);
@@ -697,9 +699,11 @@ static int eth_link_query_port(struct ib
 	if (err)
 		goto out;
 
-	props->active_width	=  (((u8 *)mailbox->buf)[5] == 0x40) ?
-						IB_WIDTH_4X : IB_WIDTH_1X;
-	props->active_speed	= IB_SPEED_QDR;
+	props->active_width	=  (((u8 *)mailbox->buf)[5] == 0x40) ||
+				   (((u8 *)mailbox->buf)[5] == 0x20 /*56Gb*/) ?
+					   IB_WIDTH_4X : IB_WIDTH_1X;
+	props->active_speed	=  (((u8 *)mailbox->buf)[5] == 0x20 /*56Gb*/) ?
+					   IB_SPEED_FDR : IB_SPEED_QDR;
 	props->port_cap_flags	= IB_PORT_CM_SUP | IB_PORT_IP_BASED_GIDS;
 	props->gid_tbl_len	= mdev->dev->caps.gid_table_len[port];
 	props->max_msg_sz	= mdev->dev->caps.max_msg_sz;
@@ -1678,9 +1682,19 @@ static int __mlx4_ib_create_flow(struct
 		size += ret;
 	}
 
+	if (mlx4_is_master(mdev->dev) && flow_type == MLX4_FS_REGULAR &&
+	    flow_attr->num_of_specs == 1) {
+		struct _rule_hw *rule_header = (struct _rule_hw *)(ctrl + 1);
+		enum ib_flow_spec_type header_spec =
+			((union ib_flow_spec *)(flow_attr + 1))->type;
+
+		if (header_spec == IB_FLOW_SPEC_ETH)
+			mlx4_handle_eth_header_mcast_prio(ctrl, rule_header);
+	}
+
 	ret = mlx4_cmd_imm(mdev->dev, mailbox->dma, reg_id, size >> 2, 0,
 			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
-			   MLX4_CMD_WRAPPED);
+			   MLX4_CMD_NATIVE);
 	if (ret == -ENOMEM)
 		pr_err("mcg table is full. Fail to register network rule.\n");
 	else if (ret == -ENXIO)
@@ -1697,7 +1711,7 @@ static int __mlx4_ib_destroy_flow(struct
 	int err;
 	err = mlx4_cmd(dev, reg_id, 0, 0,
 		       MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
-		       MLX4_CMD_WRAPPED);
+		       MLX4_CMD_NATIVE);
 	if (err)
 		pr_err("Fail to detach network rule. registration id = 0x%llx\n",
 		       reg_id);
@@ -2814,20 +2828,22 @@ static void *mlx4_ib_add(struct mlx4_dev
 			kmalloc(BITS_TO_LONGS(ibdev->steer_qpn_count) *
 				sizeof(long),
 				GFP_KERNEL);
-		if (!ibdev->ib_uc_qpns_bitmap) {
-			dev_err(&dev->persist->pdev->dev,
-				"bit map alloc failed\n");
+		if (!ibdev->ib_uc_qpns_bitmap)
 			goto err_steer_qp_release;
-		}
 
-		bitmap_zero(ibdev->ib_uc_qpns_bitmap, ibdev->steer_qpn_count);
-
-		err = mlx4_FLOW_STEERING_IB_UC_QP_RANGE(
-				dev, ibdev->steer_qpn_base,
-				ibdev->steer_qpn_base +
-				ibdev->steer_qpn_count - 1);
-		if (err)
-			goto err_steer_free_bitmap;
+		if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DMFS_IPOIB) {
+			bitmap_zero(ibdev->ib_uc_qpns_bitmap,
+				    ibdev->steer_qpn_count);
+			err = mlx4_FLOW_STEERING_IB_UC_QP_RANGE(
+					dev, ibdev->steer_qpn_base,
+					ibdev->steer_qpn_base +
+					ibdev->steer_qpn_count - 1);
+			if (err)
+				goto err_steer_free_bitmap;
+		} else {
+			bitmap_fill(ibdev->ib_uc_qpns_bitmap,
+				    ibdev->steer_qpn_count);
+		}
 	}
 
 	for (j = 1; j <= ibdev->dev->caps.num_ports; j++)
@@ -3055,15 +3071,12 @@ static void do_slave_init(struct mlx4_ib
 	first_port = find_first_bit(actv_ports.ports, dev->caps.num_ports);
 
 	dm = kcalloc(ports, sizeof(*dm), GFP_ATOMIC);
-	if (!dm) {
-		pr_err("failed to allocate memory for tunneling qp update\n");
+	if (!dm)
 		return;
-	}
 
 	for (i = 0; i < ports; i++) {
 		dm[i] = kmalloc(sizeof (struct mlx4_ib_demux_work), GFP_ATOMIC);
 		if (!dm[i]) {
-			pr_err("failed to allocate memory for tunneling qp update work struct\n");
 			while (--i >= 0)
 				kfree(dm[i]);
 			goto out;
@@ -3223,8 +3236,6 @@ void mlx4_sched_ib_sl2vl_update_work(str
 		ew->port = port;
 		ew->ib_dev = ibdev;
 		queue_work(wq, &ew->work);
-	} else {
-		pr_err("failed to allocate memory for sl2vl update work\n");
 	}
 }
 
@@ -3284,10 +3295,8 @@ static void mlx4_ib_event(struct mlx4_de
 
 	case MLX4_DEV_EVENT_PORT_MGMT_CHANGE:
 		ew = kmalloc(sizeof *ew, GFP_ATOMIC);
-		if (!ew) {
-			pr_err("failed to allocate memory for events work\n");
+		if (!ew)
 			break;
-		}
 
 		INIT_WORK(&ew->work, handle_port_mgmt_change_event);
 		memcpy(&ew->ib_eqe, eqe, sizeof *eqe);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/mcg.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/mcg.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/mcg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/mcg.c	2017-02-12 16:03:20.000000000 -0500
@@ -1142,7 +1142,6 @@ void mlx4_ib_mcg_port_cleanup(struct mlx
 	work = kmalloc(sizeof *work, GFP_KERNEL);
 	if (!work) {
 		ctx->flushing = 0;
-		mcg_warn("failed allocating work for cleanup\n");
 		return;
 	}
 
@@ -1202,10 +1201,8 @@ static int push_deleteing_req(struct mca
 		return 0;
 
 	req = kzalloc(sizeof *req, GFP_KERNEL);
-	if (!req) {
-		mcg_warn_group(group, "failed allocation - may leave stall groups\n");
+	if (!req)
 		return -ENOMEM;
-	}
 
 	if (!list_empty(&group->func[slave].pending)) {
 		pend_req = list_entry(group->func[slave].pending.prev, struct mcast_req, group_list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/mlx4_ib.h	2017-02-12 16:03:20.000000000 -0500
@@ -742,7 +742,8 @@ int mlx4_ib_arm_cq(struct ib_cq *cq, enu
 void __mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq);
 void mlx4_ib_cq_clean(struct mlx4_ib_cq *cq, u32 qpn, struct mlx4_ib_srq *srq);
 
-struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
+struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				struct ib_udata *udata);
 int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr);
 int mlx4_ib_destroy_ah(struct ib_ah *ah);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx4/qp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx4/qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -644,7 +644,7 @@ static int create_qp_common(struct mlx4_
 	int qpn;
 	int err;
 	struct ib_qp_cap backup_cap;
-	struct mlx4_ib_sqp *sqp;
+	struct mlx4_ib_sqp *sqp = NULL;
 	struct mlx4_ib_qp *qp;
 	enum mlx4_ib_qp_type qp_type = (enum mlx4_ib_qp_type) init_attr->qp_type;
 	struct mlx4_ib_cq *mcq;
@@ -933,7 +933,9 @@ err_db:
 		mlx4_db_free(dev->dev, &qp->db);
 
 err:
-	if (!*caller_qp)
+	if (sqp)
+		kfree(sqp);
+	else if (!*caller_qp)
 		kfree(qp);
 	return err;
 }
@@ -1280,7 +1282,8 @@ static int _mlx4_ib_destroy_qp(struct ib
 	if (is_qp0(dev, mqp))
 		mlx4_CLOSE_PORT(dev->dev, mqp->port);
 
-	if (dev->qp1_proxy[mqp->port - 1] == mqp) {
+	if (mqp->mlx4_ib_qp_type == MLX4_IB_QPT_PROXY_GSI &&
+	    dev->qp1_proxy[mqp->port - 1] == mqp) {
 		mutex_lock(&dev->qp1_proxy_lock[mqp->port - 1]);
 		dev->qp1_proxy[mqp->port - 1] = NULL;
 		mutex_unlock(&dev->qp1_proxy_lock[mqp->port - 1]);
@@ -1764,14 +1767,14 @@ static int __mlx4_ib_modify_qp(struct ib
 		u8 port_num = mlx4_is_bonded(to_mdev(ibqp->device)->dev) ? 1 :
 			attr_mask & IB_QP_PORT ? attr->port_num : qp->port;
 		union ib_gid gid;
-		struct ib_gid_attr gid_attr;
+		struct ib_gid_attr gid_attr = {.gid_type = IB_GID_TYPE_IB};
 		u16 vlan = 0xffff;
 		u8 smac[ETH_ALEN];
 		int status = 0;
 		int is_eth = rdma_cap_eth_ah(&dev->ib_dev, port_num) &&
 			attr->ah_attr.ah_flags & IB_AH_GRH;
 
-		if (is_eth) {
+		if (is_eth && attr->ah_attr.ah_flags & IB_AH_GRH) {
 			int index = attr->ah_attr.grh.sgid_index;
 
 			status = ib_get_cached_gid(ibqp->device, port_num,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/ah.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/ah.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/ah.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/ah.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,7 +64,9 @@ static struct ib_ah *create_ib_ah(struct
 	return &ah->ibah;
 }
 
-struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				struct ib_udata *udata)
+
 {
 	struct mlx5_ib_ah *ah;
 	struct mlx5_ib_dev *dev = to_mdev(pd->device);
@@ -75,6 +77,27 @@ struct ib_ah *mlx5_ib_create_ah(struct i
 	if (ll == IB_LINK_LAYER_ETHERNET && !(ah_attr->ah_flags & IB_AH_GRH))
 		return ERR_PTR(-EINVAL);
 
+	if (ll == IB_LINK_LAYER_ETHERNET && udata) {
+		int err;
+		struct mlx5_ib_create_ah_resp resp = {};
+		u32 min_resp_len = offsetof(typeof(resp), dmac) +
+				   sizeof(resp.dmac);
+
+		if (udata->outlen < min_resp_len)
+			return ERR_PTR(-EINVAL);
+
+		resp.response_length = min_resp_len;
+
+		err = ib_resolve_eth_dmac(pd->device, ah_attr);
+		if (err)
+			return ERR_PTR(err);
+
+		memcpy(resp.dmac, ah_attr->dmac, ETH_ALEN);
+		err = ib_copy_to_udata(udata, &resp, resp.response_length);
+		if (err)
+			return ERR_PTR(err);
+	}
+
 	ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
 	if (!ah)
 		return ERR_PTR(-ENOMEM);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/cq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/cq.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/cq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/cq.c	2017-02-12 16:03:20.000000000 -0500
@@ -731,7 +731,7 @@ static int create_cq_user(struct mlx5_ib
 			  int entries, u32 **cqb,
 			  int *cqe_size, int *index, int *inlen)
 {
-	struct mlx5_ib_create_cq ucmd;
+	struct mlx5_ib_create_cq ucmd = {};
 	size_t ucmdlen;
 	int page_shift;
 	__be64 *pas;
@@ -770,7 +770,7 @@ static int create_cq_user(struct mlx5_ib
 	if (err)
 		goto err_umem;
 
-	mlx5_ib_cont_pages(cq->buf.umem, ucmd.buf_addr, &npages, &page_shift,
+	mlx5_ib_cont_pages(cq->buf.umem, ucmd.buf_addr, 0, &npages, &page_shift,
 			   &ncont, NULL);
 	mlx5_ib_dbg(dev, "addr 0x%llx, size %u, npages %d, page_shift %d, ncont %d\n",
 		    ucmd.buf_addr, entries * ucmd.cqe_size, npages, page_shift, ncont);
@@ -792,8 +792,36 @@ static int create_cq_user(struct mlx5_ib
 
 	*index = to_mucontext(context)->uuari.uars[0].index;
 
+	if (ucmd.cqe_comp_en == 1) {
+		if (unlikely((*cqe_size != 64) ||
+			     !MLX5_CAP_GEN(dev->mdev, cqe_compression))) {
+			err = -EOPNOTSUPP;
+			mlx5_ib_warn(dev, "CQE compression is not supported for size %d!\n",
+				     *cqe_size);
+			goto err_cqb;
+		}
+
+		if (unlikely(!ucmd.cqe_comp_res_format ||
+			     !(ucmd.cqe_comp_res_format <
+			       MLX5_IB_CQE_RES_RESERVED) ||
+			     (ucmd.cqe_comp_res_format &
+			      (ucmd.cqe_comp_res_format - 1)))) {
+			err = -EOPNOTSUPP;
+			mlx5_ib_warn(dev, "CQE compression res format %d is not supported!\n",
+				     ucmd.cqe_comp_res_format);
+			goto err_cqb;
+		}
+
+		MLX5_SET(cqc, cqc, cqe_comp_en, 1);
+		MLX5_SET(cqc, cqc, mini_cqe_res_format,
+			 ilog2(ucmd.cqe_comp_res_format));
+	}
+
 	return 0;
 
+err_cqb:
+	kfree(cqb);
+
 err_db:
 	mlx5_ib_db_unmap_user(to_mucontext(context), &cq->db);
 
@@ -1124,7 +1152,7 @@ static int resize_user(struct mlx5_ib_de
 		return err;
 	}
 
-	mlx5_ib_cont_pages(umem, ucmd.buf_addr, &npages, page_shift,
+	mlx5_ib_cont_pages(umem, ucmd.buf_addr, 0, &npages, page_shift,
 			   npas, NULL);
 
 	cq->resize_umem = umem;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/main.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -127,7 +127,7 @@ static int mlx5_netdev_event(struct noti
 
 		if ((upper == ndev || (!upper && ndev == ibdev->roce.netdev))
 		    && ibdev->ib_active) {
-			struct ib_event ibev = {0};
+			struct ib_event ibev = { };
 
 			ibev.device = &ibdev->ib_dev;
 			ibev.event = (event == NETDEV_UP) ?
@@ -496,6 +496,7 @@ static int mlx5_ib_query_device(struct i
 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
 	struct mlx5_core_dev *mdev = dev->mdev;
 	int err = -ENOMEM;
+	int max_sq_desc;
 	int max_rq_sg;
 	int max_sq_sg;
 	u64 min_page_size = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz);
@@ -618,9 +619,10 @@ static int mlx5_ib_query_device(struct i
 	props->max_qp_wr	   = 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
 	max_rq_sg =  MLX5_CAP_GEN(mdev, max_wqe_sz_rq) /
 		     sizeof(struct mlx5_wqe_data_seg);
-	max_sq_sg = (MLX5_CAP_GEN(mdev, max_wqe_sz_sq) -
-		     sizeof(struct mlx5_wqe_ctrl_seg)) /
-		     sizeof(struct mlx5_wqe_data_seg);
+	max_sq_desc = min_t(int, MLX5_CAP_GEN(mdev, max_wqe_sz_sq), 512);
+	max_sq_sg = (max_sq_desc - sizeof(struct mlx5_wqe_ctrl_seg) -
+		     sizeof(struct mlx5_wqe_raddr_seg)) /
+		sizeof(struct mlx5_wqe_data_seg);
 	props->max_sge = min(max_rq_sg, max_sq_sg);
 	props->max_sge_rd	   = MLX5_MAX_SGE_RD;
 	props->max_cq		   = 1 << MLX5_CAP_GEN(mdev, log_max_cq);
@@ -643,6 +645,7 @@ static int mlx5_ib_query_device(struct i
 	props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
 					   props->max_mcast_grp;
 	props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */
+	props->max_ah = INT_MAX;
 	props->hca_core_clock = MLX5_CAP_GEN(mdev, device_frequency_khz);
 	props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;
 
@@ -669,6 +672,40 @@ static int mlx5_ib_query_device(struct i
 			1 << MLX5_CAP_GEN(dev->mdev, log_max_rq);
 	}
 
+	if (field_avail(typeof(resp), mlx5_ib_support_multi_pkt_send_wqes,
+			uhw->outlen)) {
+		resp.mlx5_ib_support_multi_pkt_send_wqes =
+			MLX5_CAP_ETH(mdev, multi_pkt_send_wqe);
+		resp.response_length +=
+			sizeof(resp.mlx5_ib_support_multi_pkt_send_wqes);
+	}
+
+	if (field_avail(typeof(resp), reserved, uhw->outlen))
+		resp.response_length += sizeof(resp.reserved);
+
+	if (field_avail(typeof(resp), cqe_comp_caps, uhw->outlen)) {
+		resp.cqe_comp_caps.max_num =
+			MLX5_CAP_GEN(dev->mdev, cqe_compression) ?
+			MLX5_CAP_GEN(dev->mdev, cqe_compression_max_num) : 0;
+		resp.cqe_comp_caps.supported_format =
+			MLX5_IB_CQE_RES_FORMAT_HASH |
+			MLX5_IB_CQE_RES_FORMAT_CSUM;
+		resp.response_length += sizeof(resp.cqe_comp_caps);
+	}
+
+	if (field_avail(typeof(resp), packet_pacing_caps, uhw->outlen)) {
+		if (MLX5_CAP_QOS(mdev, packet_pacing) &&
+		    MLX5_CAP_GEN(mdev, qos)) {
+			resp.packet_pacing_caps.qp_rate_limit_max =
+				MLX5_CAP_QOS(mdev, packet_pacing_max_rate);
+			resp.packet_pacing_caps.qp_rate_limit_min =
+				MLX5_CAP_QOS(mdev, packet_pacing_min_rate);
+			resp.packet_pacing_caps.supported_qpts |=
+				1 << IB_QPT_RAW_PACKET;
+		}
+		resp.response_length += sizeof(resp.packet_pacing_caps);
+	}
+
 	if (uhw->outlen) {
 		err = ib_copy_to_udata(uhw, &resp, resp.response_length);
 
@@ -1093,7 +1130,8 @@ static struct ib_ucontext *mlx5_ib_alloc
 		resp.response_length += sizeof(resp.cqe_version);
 
 	if (field_avail(typeof(resp), cmds_supp_uhw, udata->outlen)) {
-		resp.cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE;
+		resp.cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE |
+				      MLX5_USER_CMDS_SUPP_UHW_CREATE_AH;
 		resp.response_length += sizeof(resp.cmds_supp_uhw);
 	}
 
@@ -1502,6 +1540,22 @@ static void set_proto(void *outer_c, voi
 	MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_protocol, val);
 }
 
+static void set_flow_label(void *misc_c, void *misc_v, u8 mask, u8 val,
+			   bool inner)
+{
+	if (inner) {
+		MLX5_SET(fte_match_set_misc,
+			 misc_c, inner_ipv6_flow_label, mask);
+		MLX5_SET(fte_match_set_misc,
+			 misc_v, inner_ipv6_flow_label, val);
+	} else {
+		MLX5_SET(fte_match_set_misc,
+			 misc_c, outer_ipv6_flow_label, mask);
+		MLX5_SET(fte_match_set_misc,
+			 misc_v, outer_ipv6_flow_label, val);
+	}
+}
+
 static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val)
 {
 	MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_ecn, mask);
@@ -1515,6 +1569,7 @@ static void set_tos(void *outer_c, void
 #define LAST_IPV4_FIELD tos
 #define LAST_IPV6_FIELD traffic_class
 #define LAST_TCP_UDP_FIELD src_port
+#define LAST_TUNNEL_FIELD tunnel_id
 
 /* Field is the last supported field */
 #define FIELDS_NOT_SUPPORTED(filter, field)\
@@ -1527,155 +1582,164 @@ static void set_tos(void *outer_c, void
 static int parse_flow_attr(u32 *match_c, u32 *match_v,
 			   const union ib_flow_spec *ib_spec)
 {
-	void *outer_headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
-					     outer_headers);
-	void *outer_headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
-					     outer_headers);
 	void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c,
 					   misc_parameters);
 	void *misc_params_v = MLX5_ADDR_OF(fte_match_param, match_v,
 					   misc_parameters);
+	void *headers_c;
+	void *headers_v;
 
-	switch (ib_spec->type) {
+	if (ib_spec->type & IB_FLOW_SPEC_INNER) {
+		headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
+					 inner_headers);
+	} else {
+		headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
+					 outer_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
+					 outer_headers);
+	}
+
+	switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) {
 	case IB_FLOW_SPEC_ETH:
 		if (FIELDS_NOT_SUPPORTED(ib_spec->eth.mask, LAST_ETH_FIELD))
 			return -ENOTSUPP;
 
-		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
 					     dmac_47_16),
 				ib_spec->eth.mask.dst_mac);
-		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 					     dmac_47_16),
 				ib_spec->eth.val.dst_mac);
 
-		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
 					     smac_47_16),
 				ib_spec->eth.mask.src_mac);
-		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 					     smac_47_16),
 				ib_spec->eth.val.src_mac);
 
 		if (ib_spec->eth.mask.vlan_tag) {
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_c,
 				 vlan_tag, 1);
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_v,
 				 vlan_tag, 1);
 
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_c,
 				 first_vid, ntohs(ib_spec->eth.mask.vlan_tag));
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_v,
 				 first_vid, ntohs(ib_spec->eth.val.vlan_tag));
 
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_c,
 				 first_cfi,
 				 ntohs(ib_spec->eth.mask.vlan_tag) >> 12);
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_v,
 				 first_cfi,
 				 ntohs(ib_spec->eth.val.vlan_tag) >> 12);
 
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_c,
 				 first_prio,
 				 ntohs(ib_spec->eth.mask.vlan_tag) >> 13);
-			MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+			MLX5_SET(fte_match_set_lyr_2_4, headers_v,
 				 first_prio,
 				 ntohs(ib_spec->eth.val.vlan_tag) >> 13);
 		}
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c,
 			 ethertype, ntohs(ib_spec->eth.mask.ether_type));
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v,
 			 ethertype, ntohs(ib_spec->eth.val.ether_type));
 		break;
 	case IB_FLOW_SPEC_IPV4:
 		if (FIELDS_NOT_SUPPORTED(ib_spec->ipv4.mask, LAST_IPV4_FIELD))
 			return -ENOTSUPP;
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c,
 			 ethertype, 0xffff);
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v,
 			 ethertype, ETH_P_IP);
 
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
 				    src_ipv4_src_ipv6.ipv4_layout.ipv4),
 		       &ib_spec->ipv4.mask.src_ip,
 		       sizeof(ib_spec->ipv4.mask.src_ip));
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 				    src_ipv4_src_ipv6.ipv4_layout.ipv4),
 		       &ib_spec->ipv4.val.src_ip,
 		       sizeof(ib_spec->ipv4.val.src_ip));
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
 				    dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
 		       &ib_spec->ipv4.mask.dst_ip,
 		       sizeof(ib_spec->ipv4.mask.dst_ip));
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 				    dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
 		       &ib_spec->ipv4.val.dst_ip,
 		       sizeof(ib_spec->ipv4.val.dst_ip));
 
-		set_tos(outer_headers_c, outer_headers_v,
+		set_tos(headers_c, headers_v,
 			ib_spec->ipv4.mask.tos, ib_spec->ipv4.val.tos);
 
-		set_proto(outer_headers_c, outer_headers_v,
+		set_proto(headers_c, headers_v,
 			  ib_spec->ipv4.mask.proto, ib_spec->ipv4.val.proto);
 		break;
 	case IB_FLOW_SPEC_IPV6:
 		if (FIELDS_NOT_SUPPORTED(ib_spec->ipv6.mask, LAST_IPV6_FIELD))
 			return -ENOTSUPP;
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c,
 			 ethertype, 0xffff);
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v,
 			 ethertype, ETH_P_IPV6);
 
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
 				    src_ipv4_src_ipv6.ipv6_layout.ipv6),
 		       &ib_spec->ipv6.mask.src_ip,
 		       sizeof(ib_spec->ipv6.mask.src_ip));
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 				    src_ipv4_src_ipv6.ipv6_layout.ipv6),
 		       &ib_spec->ipv6.val.src_ip,
 		       sizeof(ib_spec->ipv6.val.src_ip));
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_c,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
 				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
 		       &ib_spec->ipv6.mask.dst_ip,
 		       sizeof(ib_spec->ipv6.mask.dst_ip));
-		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, outer_headers_v,
+		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
 		       &ib_spec->ipv6.val.dst_ip,
 		       sizeof(ib_spec->ipv6.val.dst_ip));
 
-		set_tos(outer_headers_c, outer_headers_v,
+		set_tos(headers_c, headers_v,
 			ib_spec->ipv6.mask.traffic_class,
 			ib_spec->ipv6.val.traffic_class);
 
-		set_proto(outer_headers_c, outer_headers_v,
+		set_proto(headers_c, headers_v,
 			  ib_spec->ipv6.mask.next_hdr,
 			  ib_spec->ipv6.val.next_hdr);
 
-		MLX5_SET(fte_match_set_misc, misc_params_c,
-			 outer_ipv6_flow_label,
-			 ntohl(ib_spec->ipv6.mask.flow_label));
-		MLX5_SET(fte_match_set_misc, misc_params_v,
-			 outer_ipv6_flow_label,
-			 ntohl(ib_spec->ipv6.val.flow_label));
+		set_flow_label(misc_params_c, misc_params_v,
+			       ntohl(ib_spec->ipv6.mask.flow_label),
+			       ntohl(ib_spec->ipv6.val.flow_label),
+			       ib_spec->type & IB_FLOW_SPEC_INNER);
+
 		break;
 	case IB_FLOW_SPEC_TCP:
 		if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask,
 					 LAST_TCP_UDP_FIELD))
 			return -ENOTSUPP;
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
 			 0xff);
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, ip_protocol,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
 			 IPPROTO_TCP);
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, tcp_sport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_sport,
 			 ntohs(ib_spec->tcp_udp.mask.src_port));
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, tcp_sport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
 			 ntohs(ib_spec->tcp_udp.val.src_port));
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, tcp_dport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_dport,
 			 ntohs(ib_spec->tcp_udp.mask.dst_port));
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, tcp_dport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
 			 ntohs(ib_spec->tcp_udp.val.dst_port));
 		break;
 	case IB_FLOW_SPEC_UDP:
@@ -1683,21 +1747,31 @@ static int parse_flow_attr(u32 *match_c,
 					 LAST_TCP_UDP_FIELD))
 			return -ENOTSUPP;
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
 			 0xff);
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, ip_protocol,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
 			 IPPROTO_UDP);
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, udp_sport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport,
 			 ntohs(ib_spec->tcp_udp.mask.src_port));
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, udp_sport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
 			 ntohs(ib_spec->tcp_udp.val.src_port));
 
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_c, udp_dport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport,
 			 ntohs(ib_spec->tcp_udp.mask.dst_port));
-		MLX5_SET(fte_match_set_lyr_2_4, outer_headers_v, udp_dport,
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
 			 ntohs(ib_spec->tcp_udp.val.dst_port));
 		break;
+	case IB_FLOW_SPEC_VXLAN_TUNNEL:
+		if (FIELDS_NOT_SUPPORTED(ib_spec->tunnel.mask,
+					 LAST_TUNNEL_FIELD))
+			return -ENOTSUPP;
+
+		MLX5_SET(fte_match_set_misc, misc_params_c, vxlan_vni,
+			 ntohl(ib_spec->tunnel.mask.tunnel_id));
+		MLX5_SET(fte_match_set_misc, misc_params_v, vxlan_vni,
+			 ntohl(ib_spec->tunnel.val.tunnel_id));
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1771,13 +1845,13 @@ static int mlx5_ib_destroy_flow(struct i
 	mutex_lock(&dev->flow_db.lock);
 
 	list_for_each_entry_safe(iter, tmp, &handler->list, list) {
-		mlx5_del_flow_rule(iter->rule);
+		mlx5_del_flow_rules(iter->rule);
 		put_flow_table(dev, iter->prio, true);
 		list_del(&iter->list);
 		kfree(iter);
 	}
 
-	mlx5_del_flow_rule(handler->rule);
+	mlx5_del_flow_rules(handler->rule);
 	put_flow_table(dev, handler->prio, true);
 	mutex_unlock(&dev->flow_db.lock);
 
@@ -1857,7 +1931,7 @@ static struct mlx5_ib_flow_prio *get_flo
 		ft = mlx5_create_auto_grouped_flow_table(ns, priority,
 							 num_entries,
 							 num_groups,
-							 0);
+							 0, 0);
 
 		if (!IS_ERR(ft)) {
 			prio->refcount = 0;
@@ -1877,10 +1951,10 @@ static struct mlx5_ib_flow_handler *crea
 {
 	struct mlx5_flow_table	*ft = ft_prio->flow_table;
 	struct mlx5_ib_flow_handler *handler;
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_spec *spec;
 	const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr);
 	unsigned int spec_index;
-	u32 action;
 	int err = 0;
 
 	if (!is_valid_attr(flow_attr))
@@ -1905,12 +1979,12 @@ static struct mlx5_ib_flow_handler *crea
 	}
 
 	spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
-	action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
+	flow_act.action = dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
 		MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
-	handler->rule = mlx5_add_flow_rule(ft, spec,
-					   action,
-					   MLX5_FS_DEFAULT_FLOW_TAG,
-					   dst);
+	flow_act.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
+	handler->rule = mlx5_add_flow_rules(ft, spec,
+					    &flow_act,
+					    dst, 1);
 
 	if (IS_ERR(handler->rule)) {
 		err = PTR_ERR(handler->rule);
@@ -1941,7 +2015,7 @@ static struct mlx5_ib_flow_handler *crea
 		handler_dst = create_flow_rule(dev, ft_prio,
 					       flow_attr, dst);
 		if (IS_ERR(handler_dst)) {
-			mlx5_del_flow_rule(handler->rule);
+			mlx5_del_flow_rules(handler->rule);
 			ft_prio->refcount--;
 			kfree(handler);
 			handler = handler_dst;
@@ -2004,7 +2078,7 @@ static struct mlx5_ib_flow_handler *crea
 						 &leftovers_specs[LEFTOVERS_UC].flow_attr,
 						 dst);
 		if (IS_ERR(handler_ucast)) {
-			mlx5_del_flow_rule(handler->rule);
+			mlx5_del_flow_rules(handler->rule);
 			ft_prio->refcount--;
 			kfree(handler);
 			handler = handler_ucast;
@@ -2046,7 +2120,7 @@ static struct mlx5_ib_flow_handler *crea
 	return handler_rx;
 
 err_tx:
-	mlx5_del_flow_rule(handler_rx->rule);
+	mlx5_del_flow_rules(handler_rx->rule);
 	ft_rx->refcount--;
 	kfree(handler_rx);
 err:
@@ -2358,6 +2432,8 @@ static void mlx5_ib_event(struct mlx5_co
 		ibev.event = IB_EVENT_CLIENT_REREGISTER;
 		port = (u8)param;
 		break;
+	default:
+		return;
 	}
 
 	ibev.device	      = &ibdev->ib_dev;
@@ -2719,6 +2795,8 @@ static int mlx5_port_immutable(struct ib
 			       struct ib_port_immutable *immutable)
 {
 	struct ib_port_attr attr;
+	struct mlx5_ib_dev *dev = to_mdev(ibdev);
+	enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, port_num);
 	int err;
 
 	err = mlx5_ib_query_port(ibdev, port_num, &attr);
@@ -2728,7 +2806,8 @@ static int mlx5_port_immutable(struct ib
 	immutable->pkey_tbl_len = attr.pkey_tbl_len;
 	immutable->gid_tbl_len = attr.gid_tbl_len;
 	immutable->core_cap_flags = get_core_cap_flags(ibdev);
-	immutable->max_mad_size = IB_MGMT_MAD_SIZE;
+	if ((ll == IB_LINK_LAYER_INFINIBAND) || MLX5_CAP_GEN(dev->mdev, roce))
+		immutable->max_mad_size = IB_MGMT_MAD_SIZE;
 
 	return 0;
 }
@@ -2742,7 +2821,7 @@ static void get_dev_fw_str(struct ib_dev
 		       fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
 }
 
-static int mlx5_roce_lag_init(struct mlx5_ib_dev *dev)
+static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev)
 {
 	struct mlx5_core_dev *mdev = dev->mdev;
 	struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev,
@@ -2771,7 +2850,7 @@ err_destroy_vport_lag:
 	return err;
 }
 
-static void mlx5_roce_lag_cleanup(struct mlx5_ib_dev *dev)
+static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev)
 {
 	struct mlx5_core_dev *mdev = dev->mdev;
 
@@ -2783,7 +2862,21 @@ static void mlx5_roce_lag_cleanup(struct
 	}
 }
 
-static void mlx5_remove_roce_notifier(struct mlx5_ib_dev *dev)
+static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev)
+{
+	int err;
+
+	dev->roce.nb.notifier_call = mlx5_netdev_event;
+	err = register_netdevice_notifier(&dev->roce.nb);
+	if (err) {
+		dev->roce.nb.notifier_call = NULL;
+		return err;
+	}
+
+	return 0;
+}
+
+static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev)
 {
 	if (dev->roce.nb.notifier_call) {
 		unregister_netdevice_notifier(&dev->roce.nb);
@@ -2791,39 +2884,40 @@ static void mlx5_remove_roce_notifier(st
 	}
 }
 
-static int mlx5_enable_roce(struct mlx5_ib_dev *dev)
+static int mlx5_enable_eth(struct mlx5_ib_dev *dev)
 {
 	int err;
 
-	dev->roce.nb.notifier_call = mlx5_netdev_event;
-	err = register_netdevice_notifier(&dev->roce.nb);
-	if (err) {
-		dev->roce.nb.notifier_call = NULL;
+	err = mlx5_add_netdev_notifier(dev);
+	if (err)
 		return err;
-	}
 
-	err = mlx5_nic_vport_enable_roce(dev->mdev);
-	if (err)
-		goto err_unregister_netdevice_notifier;
+	if (MLX5_CAP_GEN(dev->mdev, roce)) {
+		err = mlx5_nic_vport_enable_roce(dev->mdev);
+		if (err)
+			goto err_unregister_netdevice_notifier;
+	}
 
-	err = mlx5_roce_lag_init(dev);
+	err = mlx5_eth_lag_init(dev);
 	if (err)
 		goto err_disable_roce;
 
 	return 0;
 
 err_disable_roce:
-	mlx5_nic_vport_disable_roce(dev->mdev);
+	if (MLX5_CAP_GEN(dev->mdev, roce))
+		mlx5_nic_vport_disable_roce(dev->mdev);
 
 err_unregister_netdevice_notifier:
-	mlx5_remove_roce_notifier(dev);
+	mlx5_remove_netdev_notifier(dev);
 	return err;
 }
 
-static void mlx5_disable_roce(struct mlx5_ib_dev *dev)
+static void mlx5_disable_eth(struct mlx5_ib_dev *dev)
 {
-	mlx5_roce_lag_cleanup(dev);
-	mlx5_nic_vport_disable_roce(dev->mdev);
+	mlx5_eth_lag_cleanup(dev);
+	if (MLX5_CAP_GEN(dev->mdev, roce))
+		mlx5_nic_vport_disable_roce(dev->mdev);
 }
 
 static void mlx5_ib_dealloc_q_counters(struct mlx5_ib_dev *dev)
@@ -2945,9 +3039,6 @@ static void *mlx5_ib_add(struct mlx5_cor
 	port_type_cap = MLX5_CAP_GEN(mdev, port_type);
 	ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
 
-	if ((ll == IB_LINK_LAYER_ETHERNET) && !MLX5_CAP_GEN(mdev, roce))
-		return NULL;
-
 	printk_once(KERN_INFO "%s", mlx5_version);
 
 	dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev));
@@ -2993,6 +3084,8 @@ static void *mlx5_ib_add(struct mlx5_cor
 		(1ull << IB_USER_VERBS_CMD_QUERY_PORT)		|
 		(1ull << IB_USER_VERBS_CMD_ALLOC_PD)		|
 		(1ull << IB_USER_VERBS_CMD_DEALLOC_PD)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_AH)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_AH)		|
 		(1ull << IB_USER_VERBS_CMD_REG_MR)		|
 		(1ull << IB_USER_VERBS_CMD_REREG_MR)		|
 		(1ull << IB_USER_VERBS_CMD_DEREG_MR)		|
@@ -3015,7 +3108,8 @@ static void *mlx5_ib_add(struct mlx5_cor
 	dev->ib_dev.uverbs_ex_cmd_mask =
 		(1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE)	|
 		(1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ)	|
-		(1ull << IB_USER_VERBS_EX_CMD_CREATE_QP);
+		(1ull << IB_USER_VERBS_EX_CMD_CREATE_QP)	|
+		(1ull << IB_USER_VERBS_EX_CMD_MODIFY_QP);
 
 	dev->ib_dev.query_device	= mlx5_ib_query_device;
 	dev->ib_dev.query_port		= mlx5_ib_query_port;
@@ -3126,14 +3220,14 @@ static void *mlx5_ib_add(struct mlx5_cor
 	spin_lock_init(&dev->reset_flow_resource_lock);
 
 	if (ll == IB_LINK_LAYER_ETHERNET) {
-		err = mlx5_enable_roce(dev);
+		err = mlx5_enable_eth(dev);
 		if (err)
 			goto err_free_port;
 	}
 
 	err = create_dev_resources(&dev->devr);
 	if (err)
-		goto err_disable_roce;
+		goto err_disable_eth;
 
 	err = mlx5_ib_odp_init_one(dev);
 	if (err)
@@ -3177,10 +3271,10 @@ err_odp:
 err_rsrc:
 	destroy_dev_resources(&dev->devr);
 
-err_disable_roce:
+err_disable_eth:
 	if (ll == IB_LINK_LAYER_ETHERNET) {
-		mlx5_disable_roce(dev);
-		mlx5_remove_roce_notifier(dev);
+		mlx5_disable_eth(dev);
+		mlx5_remove_netdev_notifier(dev);
 	}
 
 err_free_port:
@@ -3197,14 +3291,14 @@ static void mlx5_ib_remove(struct mlx5_c
 	struct mlx5_ib_dev *dev = context;
 	enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev, 1);
 
-	mlx5_remove_roce_notifier(dev);
+	mlx5_remove_netdev_notifier(dev);
 	ib_unregister_device(&dev->ib_dev);
 	mlx5_ib_dealloc_q_counters(dev);
 	destroy_umrc_res(dev);
 	mlx5_ib_odp_remove_one(dev);
 	destroy_dev_resources(&dev->devr);
 	if (ll == IB_LINK_LAYER_ETHERNET)
-		mlx5_disable_roce(dev);
+		mlx5_disable_eth(dev);
 	kfree(dev->port);
 	ib_dealloc_device(&dev->ib_dev);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/mem.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/mem.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/mem.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/mem.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,12 +37,15 @@
 
 /* @umem: umem object to scan
  * @addr: ib virtual address requested by the user
+ * @max_page_shift: high limit for page_shift - 0 means no limit
  * @count: number of PAGE_SIZE pages covered by umem
  * @shift: page shift for the compound pages found in the region
  * @ncont: number of compund pages
  * @order: log2 of the number of compound pages
  */
-void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift,
+void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
+			unsigned long max_page_shift,
+			int *count, int *shift,
 			int *ncont, int *order)
 {
 	unsigned long tmp;
@@ -72,6 +75,8 @@ void mlx5_ib_cont_pages(struct ib_umem *
 	addr = addr >> page_shift;
 	tmp = (unsigned long)addr;
 	m = find_first_bit(&tmp, BITS_PER_LONG);
+	if (max_page_shift)
+		m = min_t(unsigned long, max_page_shift - page_shift, m);
 	skip = 1 << m;
 	mask = skip - 1;
 	i = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/mlx5_ib.h	2017-02-12 16:03:20.000000000 -0500
@@ -63,6 +63,8 @@ pr_warn("%s:%s:%d:(pid %d): " format, (d
 #define MLX5_IB_DEFAULT_UIDX 0xffffff
 #define MLX5_USER_ASSIGNED_UIDX_MASK __mlx5_mask(qpc, user_index)
 
+#define MLX5_MKEY_PAGE_SHIFT_MASK __mlx5_mask(mkc, log_page_size)
+
 enum {
 	MLX5_IB_MMAP_CMD_SHIFT	= 8,
 	MLX5_IB_MMAP_CMD_MASK	= 0xff,
@@ -153,7 +155,7 @@ struct mlx5_ib_flow_handler {
 	struct list_head		list;
 	struct ib_flow			ibflow;
 	struct mlx5_ib_flow_prio	*prio;
-	struct mlx5_flow_rule	*rule;
+	struct mlx5_flow_handle		*rule;
 };
 
 struct mlx5_ib_flow_db {
@@ -387,6 +389,7 @@ struct mlx5_ib_qp {
 	struct list_head	qps_list;
 	struct list_head	cq_recv_list;
 	struct list_head	cq_send_list;
+	u32			rate_limit;
 };
 
 struct mlx5_ib_cq_buf {
@@ -418,7 +421,7 @@ struct mlx5_umr_wr {
 	struct ib_pd		       *pd;
 	unsigned int			page_shift;
 	unsigned int			npages;
-	u32				length;
+	u64				length;
 	int				access_flags;
 	u32				mkey;
 };
@@ -739,7 +742,8 @@ void mlx5_ib_free_srq_wqe(struct mlx5_ib
 int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
 		 u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
 		 const void *in_mad, void *response_mad);
-struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
+struct ib_ah *mlx5_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				struct ib_udata *udata);
 int mlx5_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr);
 int mlx5_ib_destroy_ah(struct ib_ah *ah);
 struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
@@ -825,7 +829,9 @@ int mlx5_ib_query_port(struct ib_device
 		       struct ib_port_attr *props);
 int mlx5_ib_init_fmr(struct mlx5_ib_dev *dev);
 void mlx5_ib_cleanup_fmr(struct mlx5_ib_dev *dev);
-void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr, int *count, int *shift,
+void mlx5_ib_cont_pages(struct ib_umem *umem, u64 addr,
+			unsigned long max_page_shift,
+			int *count, int *shift,
 			int *ncont, int *order);
 void __mlx5_ib_populate_pas(struct mlx5_ib_dev *dev, struct ib_umem *umem,
 			    int page_shift, size_t offset, size_t num_pages,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/mr.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/mr.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/mr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/mr.c	2017-02-12 16:03:20.000000000 -0500
@@ -628,7 +628,8 @@ int mlx5_mr_cache_init(struct mlx5_ib_de
 		ent->order = i + 2;
 		ent->dev = dev;
 
-		if (dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE)
+		if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) &&
+		    (mlx5_core_is_pf(dev->mdev)))
 			limit = dev->mdev->profile->mr_cache[i].limit;
 		else
 			limit = 0;
@@ -646,6 +647,33 @@ int mlx5_mr_cache_init(struct mlx5_ib_de
 	return 0;
 }
 
+static void wait_for_async_commands(struct mlx5_ib_dev *dev)
+{
+	struct mlx5_mr_cache *cache = &dev->cache;
+	struct mlx5_cache_ent *ent;
+	int total = 0;
+	int i;
+	int j;
+
+	for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
+		ent = &cache->ent[i];
+		for (j = 0 ; j < 1000; j++) {
+			if (!ent->pending)
+				break;
+			msleep(50);
+		}
+	}
+	for (i = 0; i < MAX_MR_CACHE_ENTRIES; i++) {
+		ent = &cache->ent[i];
+		total += ent->pending;
+	}
+
+	if (total)
+		mlx5_ib_warn(dev, "aborted while there are %d pending mr requests\n", total);
+	else
+		mlx5_ib_warn(dev, "done with all pending requests\n");
+}
+
 int mlx5_mr_cache_cleanup(struct mlx5_ib_dev *dev)
 {
 	int i;
@@ -659,6 +687,7 @@ int mlx5_mr_cache_cleanup(struct mlx5_ib
 		clean_keys(dev, i);
 
 	destroy_workqueue(dev->cache.wq);
+	wait_for_async_commands(dev);
 	del_timer_sync(&dev->delay_timer);
 
 	return 0;
@@ -816,29 +845,34 @@ static void prep_umr_unreg_wqe(struct ml
 	umrwr->mkey = key;
 }
 
-static struct ib_umem *mr_umem_get(struct ib_pd *pd, u64 start, u64 length,
-				   int access_flags, int *npages,
-				   int *page_shift, int *ncont, int *order)
+static int mr_umem_get(struct ib_pd *pd, u64 start, u64 length,
+		       int access_flags, struct ib_umem **umem,
+		       int *npages, int *page_shift, int *ncont,
+		       int *order)
 {
 	struct mlx5_ib_dev *dev = to_mdev(pd->device);
-	struct ib_umem *umem = ib_umem_get(pd->uobject->context, start, length,
-					   access_flags, 0);
-	if (IS_ERR(umem)) {
+	int err;
+
+	*umem = ib_umem_get(pd->uobject->context, start, length,
+			    access_flags, 0);
+	err = PTR_ERR_OR_ZERO(*umem);
+	if (err < 0) {
 		mlx5_ib_err(dev, "umem get failed (%ld)\n", PTR_ERR(umem));
-		return (void *)umem;
+		return err;
 	}
 
-	mlx5_ib_cont_pages(umem, start, npages, page_shift, ncont, order);
+	mlx5_ib_cont_pages(*umem, start, MLX5_MKEY_PAGE_SHIFT_MASK, npages,
+			   page_shift, ncont, order);
 	if (!*npages) {
 		mlx5_ib_warn(dev, "avoid zero region\n");
-		ib_umem_release(umem);
-		return ERR_PTR(-EINVAL);
+		ib_umem_release(*umem);
+		return -EINVAL;
 	}
 
 	mlx5_ib_dbg(dev, "npages %d, ncont %d, order %d, page_shift %d\n",
 		    *npages, *ncont, *order, *page_shift);
 
-	return umem;
+	return 0;
 }
 
 static void mlx5_ib_umr_done(struct ib_cq *cq, struct ib_wc *wc)
@@ -1164,11 +1198,11 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct
 
 	mlx5_ib_dbg(dev, "start 0x%llx, virt_addr 0x%llx, length 0x%llx, access_flags 0x%x\n",
 		    start, virt_addr, length, access_flags);
-	umem = mr_umem_get(pd, start, length, access_flags, &npages,
+	err = mr_umem_get(pd, start, length, access_flags, &umem, &npages,
 			   &page_shift, &ncont, &order);
 
-	if (IS_ERR(umem))
-		return (void *)umem;
+        if (err < 0)
+		return ERR_PTR(err);
 
 	if (use_umr(order)) {
 		mr = reg_umr(pd, umem, virt_addr, length, ncont, page_shift,
@@ -1345,10 +1379,9 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *
 		 */
 		flags |= IB_MR_REREG_TRANS;
 		ib_umem_release(mr->umem);
-		mr->umem = mr_umem_get(pd, addr, len, access_flags, &npages,
-				       &page_shift, &ncont, &order);
-		if (IS_ERR(mr->umem)) {
-			err = PTR_ERR(mr->umem);
+		err = mr_umem_get(pd, addr, len, access_flags, &mr->umem,
+				  &npages, &page_shift, &ncont, &order);
+		if (err < 0) {
 			mr->umem = NULL;
 			return err;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/qp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,12 +77,14 @@ struct mlx5_wqe_eth_pad {
 
 enum raw_qp_set_mask_map {
 	MLX5_RAW_QP_MOD_SET_RQ_Q_CTR_ID		= 1UL << 0,
+	MLX5_RAW_QP_RATE_LIMIT			= 1UL << 1,
 };
 
 struct mlx5_modify_raw_qp_param {
 	u16 operation;
 
 	u32 set_mask; /* raw_qp_set_mask_map */
+	u32 rate_limit;
 	u8 rq_q_ctr_id;
 };
 
@@ -351,6 +353,29 @@ static int calc_send_wqe(struct ib_qp_in
 		return ALIGN(max_t(int, inl_size, size), MLX5_SEND_WQE_BB);
 }
 
+static int get_send_sge(struct ib_qp_init_attr *attr, int wqe_size)
+{
+	int max_sge;
+
+	if (attr->qp_type == IB_QPT_RC)
+		max_sge = (min_t(int, wqe_size, 512) -
+			   sizeof(struct mlx5_wqe_ctrl_seg) -
+			   sizeof(struct mlx5_wqe_raddr_seg)) /
+			sizeof(struct mlx5_wqe_data_seg);
+	else if (attr->qp_type == IB_QPT_XRC_INI)
+		max_sge = (min_t(int, wqe_size, 512) -
+			   sizeof(struct mlx5_wqe_ctrl_seg) -
+			   sizeof(struct mlx5_wqe_xrc_seg) -
+			   sizeof(struct mlx5_wqe_raddr_seg)) /
+			sizeof(struct mlx5_wqe_data_seg);
+	else
+		max_sge = (wqe_size - sq_overhead(attr)) /
+			sizeof(struct mlx5_wqe_data_seg);
+
+	return min_t(int, max_sge, wqe_size - sq_overhead(attr) /
+		     sizeof(struct mlx5_wqe_data_seg));
+}
+
 static int calc_sq_size(struct mlx5_ib_dev *dev, struct ib_qp_init_attr *attr,
 			struct mlx5_ib_qp *qp)
 {
@@ -381,13 +406,18 @@ static int calc_sq_size(struct mlx5_ib_d
 	wq_size = roundup_pow_of_two(attr->cap.max_send_wr * wqe_size);
 	qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB;
 	if (qp->sq.wqe_cnt > (1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz))) {
-		mlx5_ib_dbg(dev, "wqe count(%d) exceeds limits(%d)\n",
+		mlx5_ib_dbg(dev, "send queue size (%d * %d / %d -> %d) exceeds limits(%d)\n",
+			    attr->cap.max_send_wr, wqe_size, MLX5_SEND_WQE_BB,
 			    qp->sq.wqe_cnt,
 			    1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz));
 		return -ENOMEM;
 	}
 	qp->sq.wqe_shift = ilog2(MLX5_SEND_WQE_BB);
-	qp->sq.max_gs = attr->cap.max_send_sge;
+	qp->sq.max_gs = get_send_sge(attr, wqe_size);
+	if (qp->sq.max_gs < attr->cap.max_send_sge)
+		return -ENOMEM;
+
+	attr->cap.max_send_sge = qp->sq.max_gs;
 	qp->sq.max_post = wq_size / wqe_size;
 	attr->cap.max_send_wr = qp->sq.max_post;
 
@@ -647,7 +677,7 @@ static int mlx5_ib_umem_get(struct mlx5_
 		return PTR_ERR(*umem);
 	}
 
-	mlx5_ib_cont_pages(*umem, addr, npages, page_shift, ncont, NULL);
+	mlx5_ib_cont_pages(*umem, addr, 0, npages, page_shift, ncont, NULL);
 
 	err = mlx5_ib_get_buf_offset(addr, *page_shift, offset);
 	if (err) {
@@ -700,7 +730,7 @@ static int create_user_rq(struct mlx5_ib
 		return err;
 	}
 
-	mlx5_ib_cont_pages(rwq->umem, ucmd->buf_addr, &npages, &page_shift,
+	mlx5_ib_cont_pages(rwq->umem, ucmd->buf_addr, 0, &npages, &page_shift,
 			   &ncont, NULL);
 	err = mlx5_ib_get_buf_offset(ucmd->buf_addr, page_shift,
 				     &rwq->rq_page_offset);
@@ -2442,8 +2472,14 @@ out:
 }
 
 static int modify_raw_packet_qp_sq(struct mlx5_core_dev *dev,
-				   struct mlx5_ib_sq *sq, int new_state)
+				   struct mlx5_ib_sq *sq,
+				   int new_state,
+				   const struct mlx5_modify_raw_qp_param *raw_qp_param)
 {
+	struct mlx5_ib_qp *ibqp = sq->base.container_mibqp;
+	u32 old_rate = ibqp->rate_limit;
+	u32 new_rate = old_rate;
+	u16 rl_index = 0;
 	void *in;
 	void *sqc;
 	int inlen;
@@ -2459,10 +2495,44 @@ static int modify_raw_packet_qp_sq(struc
 	sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
 	MLX5_SET(sqc, sqc, state, new_state);
 
+	if (raw_qp_param->set_mask & MLX5_RAW_QP_RATE_LIMIT) {
+		if (new_state != MLX5_SQC_STATE_RDY)
+			pr_warn("%s: Rate limit can only be changed when SQ is moving to RDY\n",
+				__func__);
+		else
+			new_rate = raw_qp_param->rate_limit;
+	}
+
+	if (old_rate != new_rate) {
+		if (new_rate) {
+			err = mlx5_rl_add_rate(dev, new_rate, &rl_index);
+			if (err) {
+				pr_err("Failed configuring rate %u: %d\n",
+				       new_rate, err);
+				goto out;
+			}
+		}
+
+		MLX5_SET64(modify_sq_in, in, modify_bitmask, 1);
+		MLX5_SET(sqc, sqc, packet_pacing_rate_limit_index, rl_index);
+	}
+
 	err = mlx5_core_modify_sq(dev, sq->base.mqp.qpn, in, inlen);
-	if (err)
+	if (err) {
+		/* Remove new rate from table if failed */
+		if (new_rate &&
+		    old_rate != new_rate)
+			mlx5_rl_remove_rate(dev, new_rate);
 		goto out;
+	}
 
+	/* Only remove the old rate after new rate was set */
+	if ((old_rate &&
+	    (old_rate != new_rate)) ||
+	    (new_state != MLX5_SQC_STATE_RDY))
+		mlx5_rl_remove_rate(dev, old_rate);
+
+	ibqp->rate_limit = new_rate;
 	sq->state = new_state;
 
 out:
@@ -2477,6 +2547,8 @@ static int modify_raw_packet_qp(struct m
 	struct mlx5_ib_raw_packet_qp *raw_packet_qp = &qp->raw_packet_qp;
 	struct mlx5_ib_rq *rq = &raw_packet_qp->rq;
 	struct mlx5_ib_sq *sq = &raw_packet_qp->sq;
+	int modify_rq = !!qp->rq.wqe_cnt;
+	int modify_sq = !!qp->sq.wqe_cnt;
 	int rq_state;
 	int sq_state;
 	int err;
@@ -2494,10 +2566,18 @@ static int modify_raw_packet_qp(struct m
 		rq_state = MLX5_RQC_STATE_RST;
 		sq_state = MLX5_SQC_STATE_RST;
 		break;
-	case MLX5_CMD_OP_INIT2INIT_QP:
-	case MLX5_CMD_OP_INIT2RTR_QP:
 	case MLX5_CMD_OP_RTR2RTS_QP:
 	case MLX5_CMD_OP_RTS2RTS_QP:
+		if (raw_qp_param->set_mask ==
+		    MLX5_RAW_QP_RATE_LIMIT) {
+			modify_rq = 0;
+			sq_state = sq->state;
+		} else {
+			return raw_qp_param->set_mask ? -EINVAL : 0;
+		}
+		break;
+	case MLX5_CMD_OP_INIT2INIT_QP:
+	case MLX5_CMD_OP_INIT2RTR_QP:
 		if (raw_qp_param->set_mask)
 			return -EINVAL;
 		else
@@ -2507,13 +2587,13 @@ static int modify_raw_packet_qp(struct m
 		return -EINVAL;
 	}
 
-	if (qp->rq.wqe_cnt) {
-		err = modify_raw_packet_qp_rq(dev, rq, rq_state, raw_qp_param);
+	if (modify_rq) {
+		err =  modify_raw_packet_qp_rq(dev, rq, rq_state, raw_qp_param);
 		if (err)
 			return err;
 	}
 
-	if (qp->sq.wqe_cnt) {
+	if (modify_sq) {
 		if (tx_affinity) {
 			err = modify_raw_packet_tx_affinity(dev->mdev, sq,
 							    tx_affinity);
@@ -2521,7 +2601,7 @@ static int modify_raw_packet_qp(struct m
 				return err;
 		}
 
-		return modify_raw_packet_qp_sq(dev->mdev, sq, sq_state);
+		return modify_raw_packet_qp_sq(dev->mdev, sq, sq_state, raw_qp_param);
 	}
 
 	return 0;
@@ -2577,7 +2657,6 @@ static int __mlx5_ib_modify_qp(struct ib
 	struct mlx5_ib_port *mibport = NULL;
 	enum mlx5_qp_state mlx5_cur, mlx5_new;
 	enum mlx5_qp_optpar optpar;
-	int sqd_event;
 	int mlx5_st;
 	int err;
 	u16 op;
@@ -2724,12 +2803,6 @@ static int __mlx5_ib_modify_qp(struct ib
 	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_RTS && new_state == IB_QPS_SQD	&&
-	    attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY && attr->en_sqd_async_notify)
-		sqd_event = 1;
-	else
-		sqd_event = 0;
-
 	if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) {
 		u8 port_num = (attr_mask & IB_QP_PORT ? attr->port_num :
 			       qp->port) - 1;
@@ -2776,6 +2849,12 @@ static int __mlx5_ib_modify_qp(struct ib
 			raw_qp_param.rq_q_ctr_id = mibport->q_cnt_id;
 			raw_qp_param.set_mask |= MLX5_RAW_QP_MOD_SET_RQ_Q_CTR_ID;
 		}
+
+		if (attr_mask & IB_QP_RATE_LIMIT) {
+			raw_qp_param.rate_limit = attr->rate_limit;
+			raw_qp_param.set_mask |= MLX5_RAW_QP_RATE_LIMIT;
+		}
+
 		err = modify_raw_packet_qp(dev, qp, &raw_qp_param, tx_affinity);
 	} else {
 		err = mlx5_core_qp_modify(dev->mdev, op, optpar, context,
@@ -3067,10 +3146,10 @@ static void set_linv_umr_seg(struct mlx5
 {
 	memset(umr, 0, sizeof(*umr));
 	umr->mkey_mask = cpu_to_be64(MLX5_MKEY_MASK_FREE);
-	umr->flags = 1 << 7;
+	umr->flags = MLX5_UMR_INLINE;
 }
 
-static __be64 get_umr_reg_mr_mask(void)
+static __be64 get_umr_reg_mr_mask(int atomic)
 {
 	u64 result;
 
@@ -3083,9 +3162,11 @@ static __be64 get_umr_reg_mr_mask(void)
 		 MLX5_MKEY_MASK_KEY		|
 		 MLX5_MKEY_MASK_RR		|
 		 MLX5_MKEY_MASK_RW		|
-		 MLX5_MKEY_MASK_A		|
 		 MLX5_MKEY_MASK_FREE;
 
+	if (atomic)
+		result |= MLX5_MKEY_MASK_A;
+
 	return cpu_to_be64(result);
 }
 
@@ -3146,7 +3227,7 @@ static __be64 get_umr_update_pd_mask(voi
 }
 
 static void set_reg_umr_segment(struct mlx5_wqe_umr_ctrl_seg *umr,
-				struct ib_send_wr *wr)
+				struct ib_send_wr *wr, int atomic)
 {
 	struct mlx5_umr_wr *umrwr = umr_wr(wr);
 
@@ -3171,7 +3252,7 @@ static void set_reg_umr_segment(struct m
 		if (wr->send_flags & MLX5_IB_SEND_UMR_UPDATE_PD)
 			umr->mkey_mask |= get_umr_update_pd_mask();
 		if (!umr->mkey_mask)
-			umr->mkey_mask = get_umr_reg_mr_mask();
+			umr->mkey_mask = get_umr_reg_mr_mask(atomic);
 	} else {
 		umr->mkey_mask = get_umr_unreg_mr_mask();
 	}
@@ -4024,7 +4105,7 @@ int mlx5_ib_post_send(struct ib_qp *ibqp
 			}
 			qp->sq.wr_data[idx] = MLX5_IB_WR_UMR;
 			ctrl->imm = cpu_to_be32(umr_wr(wr)->mkey);
-			set_reg_umr_segment(seg, wr);
+			set_reg_umr_segment(seg, wr, !!(MLX5_CAP_GEN(mdev, atomic)));
 			seg += sizeof(struct mlx5_wqe_umr_ctrl_seg);
 			size += sizeof(struct mlx5_wqe_umr_ctrl_seg) / 16;
 			if (unlikely((seg == qend)))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/srq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/srq.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mlx5/srq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mlx5/srq.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,7 +118,7 @@ static int create_srq_user(struct ib_pd
 		return err;
 	}
 
-	mlx5_ib_cont_pages(srq->umem, ucmd.buf_addr, &npages,
+	mlx5_ib_cont_pages(srq->umem, ucmd.buf_addr, 0, &npages,
 			   &page_shift, &ncont, NULL);
 	err = mlx5_ib_get_buf_offset(ucmd.buf_addr, page_shift,
 				     &offset);
@@ -203,8 +203,6 @@ static int create_srq_kernel(struct mlx5
 
 	srq->wrid = kmalloc(srq->msrq.max * sizeof(u64), GFP_KERNEL);
 	if (!srq->wrid) {
-		mlx5_ib_dbg(dev, "kmalloc failed %lu\n",
-			    (unsigned long)(srq->msrq.max * sizeof(u64)));
 		err = -ENOMEM;
 		goto err_in;
 	}
@@ -282,6 +280,7 @@ struct ib_srq *mlx5_ib_create_srq(struct
 	mlx5_ib_dbg(dev, "desc_size 0x%x, req wr 0x%x, srq size 0x%x, max_gs 0x%x, max_avail_gather 0x%x\n",
 		    desc_size, init_attr->attr.max_wr, srq->msrq.max, srq->msrq.max_gs,
 		    srq->msrq.max_avail_gather);
+	in.type = init_attr->srq_type;
 
 	if (pd->uobject)
 		err = create_srq_user(pd, srq, &in, udata, buf_size);
@@ -294,7 +293,6 @@ struct ib_srq *mlx5_ib_create_srq(struct
 		goto err_srq;
 	}
 
-	in.type = init_attr->srq_type;
 	in.log_size = ilog2(srq->msrq.max);
 	in.wqe_shift = srq->msrq.wqe_shift - 4;
 	if (srq->wq_sig)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mthca/mthca_av.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mthca/mthca_av.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mthca/mthca_av.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mthca/mthca_av.c	2017-02-12 16:03:20.000000000 -0500
@@ -186,8 +186,8 @@ int mthca_create_ah(struct mthca_dev *de
 
 on_hca_fail:
 	if (ah->type == MTHCA_AH_PCI_POOL) {
-		ah->av = pci_pool_alloc(dev->av_table.pool,
-					GFP_ATOMIC, &ah->avdma);
+		ah->av = pci_pool_zalloc(dev->av_table.pool,
+					 GFP_ATOMIC, &ah->avdma);
 		if (!ah->av)
 			return -ENOMEM;
 
@@ -196,8 +196,6 @@ on_hca_fail:
 
 	ah->key = pd->ntmr.ibmr.lkey;
 
-	memset(av, 0, MTHCA_AV_SIZE);
-
 	av->port_pd = cpu_to_be32(pd->pd_num | (ah_attr->port_num << 24));
 	av->g_slid  = ah_attr->src_path_bits;
 	av->dlid    = cpu_to_be16(ah_attr->dlid);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mthca/mthca_provider.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mthca/mthca_provider.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mthca/mthca_provider.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mthca/mthca_provider.c	2017-02-12 16:03:20.000000000 -0500
@@ -410,7 +410,9 @@ static int mthca_dealloc_pd(struct ib_pd
 }
 
 static struct ib_ah *mthca_ah_create(struct ib_pd *pd,
-				     struct ib_ah_attr *ah_attr)
+				     struct ib_ah_attr *ah_attr,
+				     struct ib_udata *udata)
+
 {
 	int err;
 	struct mthca_ah *ah;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/mthca/mthca_reset.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mthca/mthca_reset.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/mthca/mthca_reset.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/mthca/mthca_reset.c	2017-02-12 16:03:20.000000000 -0500
@@ -96,8 +96,6 @@ int mthca_reset(struct mthca_dev *mdev)
 	hca_header = kmalloc(256, GFP_KERNEL);
 	if (!hca_header) {
 		err = -ENOMEM;
-		mthca_err(mdev, "Couldn't allocate memory to save HCA "
-			  "PCI header, aborting.\n");
 		goto put_dev;
 	}
 
@@ -119,8 +117,6 @@ int mthca_reset(struct mthca_dev *mdev)
 		bridge_header = kmalloc(256, GFP_KERNEL);
 		if (!bridge_header) {
 			err = -ENOMEM;
-			mthca_err(mdev, "Couldn't allocate memory to save HCA "
-				  "bridge PCI header, aborting.\n");
 			goto free_hca;
 		}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,7 +65,6 @@ MODULE_DESCRIPTION("NetEffect RNIC Low-l
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
-int max_mtu = 9000;
 int interrupt_mod_interval = 0;
 
 /* Interoperability */
@@ -516,7 +515,6 @@ static int nes_probe(struct pci_dev *pci
 	/* Allocate hardware structure */
 	nesdev = kzalloc(sizeof(struct nes_device), GFP_KERNEL);
 	if (!nesdev) {
-		printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", pci_name(pcidev));
 		ret = -ENOMEM;
 		goto bail2;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_cm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_cm.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -2282,10 +2282,8 @@ static struct nes_cm_listener *mini_cm_l
 	if (!listener) {
 		/* create a CM listen node (1/2 node to compare incoming traffic to) */
 		listener = kzalloc(sizeof(*listener), GFP_ATOMIC);
-		if (!listener) {
-			nes_debug(NES_DBG_CM, "Not creating listener memory allocation failed\n");
+		if (!listener)
 			return NULL;
-		}
 
 		listener->loc_addr = cm_info->loc_addr;
 		listener->loc_port = cm_info->loc_port;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes.h	2017-02-12 16:03:20.000000000 -0500
@@ -83,6 +83,8 @@
 #define NES_FIRST_QPN           64
 #define NES_SW_CONTEXT_ALIGN    1024
 
+#define NES_MAX_MTU		9000
+
 #define NES_NIC_MAX_NICS        16
 #define NES_MAX_ARP_TABLE_SIZE  4096
 
@@ -169,8 +171,6 @@ do { \
 #include "nes_cm.h"
 #include "nes_mgt.h"
 
-extern int max_mtu;
-#define max_frame_len (max_mtu+ETH_HLEN)
 extern int interrupt_mod_interval;
 extern int nes_if_count;
 extern int mpa_version;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_hw.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_hw.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -351,9 +351,8 @@ struct nes_adapter *nes_init_adapter(str
 
 	/* allocate a new adapter struct */
 	nesadapter = kzalloc(adapter_size, GFP_KERNEL);
-	if (nesadapter == NULL) {
+	if (!nesadapter)
 		return NULL;
-	}
 
 	nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n",
 			nesadapter, (u32)sizeof(struct nes_adapter), adapter_size);
@@ -1007,8 +1006,7 @@ int nes_init_cqp(struct nes_device *nesd
 	/* Allocate a twice the number of CQP requests as the SQ size */
 	nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *
 			2 * NES_CQP_SQ_SIZE, GFP_KERNEL);
-	if (nesdev->nes_cqp_requests == NULL) {
-		nes_debug(NES_DBG_INIT, "Unable to allocate memory CQP request entries.\n");
+	if (!nesdev->nes_cqp_requests) {
 		pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
 				nesdev->cqp.sq_pbase);
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_mgt.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_mgt.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_mgt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_mgt.c	2017-02-12 16:03:20.000000000 -0500
@@ -320,8 +320,7 @@ static int get_fpdu_info(struct nes_devi
 
 	/* 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");
+	if (!fpdu_info) {
 		rc = -ENOMEM;
 		goto out;
 	}
@@ -729,8 +728,7 @@ static int nes_change_quad_hash(struct n
 	}
 
 	qh_chg = kmalloc(sizeof *qh_chg, GFP_ATOMIC);
-	if (qh_chg == NULL) {
-		nes_debug(NES_DBG_PAU, "Failed to get a cqp_request.\n");
+	if (!qh_chg) {
 		ret = -ENOMEM;
 		goto chg_qh_err;
 	}
@@ -880,10 +878,8 @@ int nes_init_mgt_qp(struct nes_device *n
 
 	/* 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");
+	if (!mgtvnic)
 		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 */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_nic.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_nic.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_nic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_nic.c	2017-02-12 16:03:20.000000000 -0500
@@ -662,10 +662,14 @@ tso_sq_no_longer_full:
 				nesnic->sq_head &= nesnic->sq_size-1;
 			}
 		} else {
-			nesvnic->linearized_skbs++;
 			hoffset = skb_transport_header(skb) - skb->data;
 			nhoffset = skb_network_header(skb) - skb->data;
-			skb_linearize(skb);
+			if (skb_linearize(skb)) {
+				nesvnic->tx_sw_dropped++;
+				kfree_skb(skb);
+				return NETDEV_TX_OK;
+			}
+			nesvnic->linearized_skbs++;
 			skb_set_transport_header(skb, hoffset);
 			skb_set_network_header(skb, nhoffset);
 			if (!nes_nic_send(skb, netdev))
@@ -981,20 +985,16 @@ static int nes_netdev_change_mtu(struct
 {
 	struct nes_vnic	*nesvnic = netdev_priv(netdev);
 	struct nes_device *nesdev = nesvnic->nesdev;
-	int ret = 0;
 	u8 jumbomode = 0;
 	u32 nic_active;
 	u32 nic_active_bit;
 	u32 uc_all_active;
 	u32 mc_all_active;
 
-	if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
-		return -EINVAL;
-
 	netdev->mtu = new_mtu;
 	nesvnic->max_frame_size	= new_mtu + VLAN_ETH_HLEN;
 
-	if (netdev->mtu	> 1500)	{
+	if (netdev->mtu	> ETH_DATA_LEN)	{
 		jumbomode=1;
 	}
 	nes_nic_init_timer_defaults(nesdev, jumbomode);
@@ -1020,7 +1020,7 @@ static int nes_netdev_change_mtu(struct
 		nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
 	}
 
-	return ret;
+	return 0;
 }
 
 
@@ -1465,7 +1465,8 @@ static int nes_netdev_set_pauseparam(str
 /**
  * nes_netdev_get_settings
  */
-static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)
+static int nes_netdev_get_link_ksettings(struct net_device *netdev,
+					 struct ethtool_link_ksettings *cmd)
 {
 	struct nes_vnic *nesvnic = netdev_priv(netdev);
 	struct nes_device *nesdev = nesvnic->nesdev;
@@ -1474,54 +1475,59 @@ static int nes_netdev_get_settings(struc
 	u8 phy_type = nesadapter->phy_type[mac_index];
 	u8 phy_index = nesadapter->phy_index[mac_index];
 	u16 phy_data;
+	u32 supported, advertising;
 
-	et_cmd->duplex = DUPLEX_FULL;
-	et_cmd->port   = PORT_MII;
-	et_cmd->maxtxpkt = 511;
-	et_cmd->maxrxpkt = 511;
+	cmd->base.duplex = DUPLEX_FULL;
+	cmd->base.port   = PORT_MII;
 
 	if (nesadapter->OneG_Mode) {
-		ethtool_cmd_speed_set(et_cmd, SPEED_1000);
+		cmd->base.speed = SPEED_1000;
 		if (phy_type == NES_PHY_TYPE_PUMA_1G) {
-			et_cmd->supported   = SUPPORTED_1000baseT_Full;
-			et_cmd->advertising = ADVERTISED_1000baseT_Full;
-			et_cmd->autoneg     = AUTONEG_DISABLE;
-			et_cmd->transceiver = XCVR_INTERNAL;
-			et_cmd->phy_address = mac_index;
+			supported   = SUPPORTED_1000baseT_Full;
+			advertising = ADVERTISED_1000baseT_Full;
+			cmd->base.autoneg     = AUTONEG_DISABLE;
+			cmd->base.phy_address = mac_index;
 		} else {
 			unsigned long flags;
-			et_cmd->supported   = SUPPORTED_1000baseT_Full
-					    | SUPPORTED_Autoneg;
-			et_cmd->advertising = ADVERTISED_1000baseT_Full
-					    | ADVERTISED_Autoneg;
+
+			supported = SUPPORTED_1000baseT_Full
+				| SUPPORTED_Autoneg;
+			advertising = ADVERTISED_1000baseT_Full
+				| ADVERTISED_Autoneg;
 			spin_lock_irqsave(&nesadapter->phy_lock, flags);
 			nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
 			spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
 			if (phy_data & 0x1000)
-				et_cmd->autoneg = AUTONEG_ENABLE;
+				cmd->base.autoneg = AUTONEG_ENABLE;
 			else
-				et_cmd->autoneg = AUTONEG_DISABLE;
-			et_cmd->transceiver = XCVR_EXTERNAL;
-			et_cmd->phy_address = phy_index;
+				cmd->base.autoneg = AUTONEG_DISABLE;
+			cmd->base.phy_address = phy_index;
 		}
+		ethtool_convert_legacy_u32_to_link_mode(
+			cmd->link_modes.supported, supported);
+		ethtool_convert_legacy_u32_to_link_mode(
+			cmd->link_modes.advertising, advertising);
 		return 0;
 	}
 	if ((phy_type == NES_PHY_TYPE_ARGUS) ||
 	    (phy_type == NES_PHY_TYPE_SFP_D) ||
 	    (phy_type == NES_PHY_TYPE_KR)) {
-		et_cmd->transceiver = XCVR_EXTERNAL;
-		et_cmd->port        = PORT_FIBRE;
-		et_cmd->supported   = SUPPORTED_FIBRE;
-		et_cmd->advertising = ADVERTISED_FIBRE;
-		et_cmd->phy_address = phy_index;
+		cmd->base.port        = PORT_FIBRE;
+		supported   = SUPPORTED_FIBRE;
+		advertising = ADVERTISED_FIBRE;
+		cmd->base.phy_address = phy_index;
 	} else {
-		et_cmd->transceiver = XCVR_INTERNAL;
-		et_cmd->supported   = SUPPORTED_10000baseT_Full;
-		et_cmd->advertising = ADVERTISED_10000baseT_Full;
-		et_cmd->phy_address = mac_index;
+		supported   = SUPPORTED_10000baseT_Full;
+		advertising = ADVERTISED_10000baseT_Full;
+		cmd->base.phy_address = mac_index;
 	}
-	ethtool_cmd_speed_set(et_cmd, SPEED_10000);
-	et_cmd->autoneg = AUTONEG_DISABLE;
+	cmd->base.speed = SPEED_10000;
+	cmd->base.autoneg = AUTONEG_DISABLE;
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
+
 	return 0;
 }
 
@@ -1529,7 +1535,9 @@ static int nes_netdev_get_settings(struc
 /**
  * nes_netdev_set_settings
  */
-static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)
+static int
+nes_netdev_set_link_ksettings(struct net_device *netdev,
+			      const struct ethtool_link_ksettings *cmd)
 {
 	struct nes_vnic *nesvnic = netdev_priv(netdev);
 	struct nes_device *nesdev = nesvnic->nesdev;
@@ -1543,7 +1551,7 @@ static int nes_netdev_set_settings(struc
 
 		spin_lock_irqsave(&nesadapter->phy_lock, flags);
 		nes_read_1G_phy_reg(nesdev, 0, phy_index, &phy_data);
-		if (et_cmd->autoneg) {
+		if (cmd->base.autoneg) {
 			/* Turn on Full duplex, Autoneg, and restart autonegotiation */
 			phy_data |= 0x1300;
 		} else {
@@ -1560,8 +1568,6 @@ static int nes_netdev_set_settings(struc
 
 static const struct ethtool_ops nes_ethtool_ops = {
 	.get_link = ethtool_op_get_link,
-	.get_settings = nes_netdev_get_settings,
-	.set_settings = nes_netdev_set_settings,
 	.get_strings = nes_netdev_get_strings,
 	.get_sset_count = nes_netdev_get_sset_count,
 	.get_ethtool_stats = nes_netdev_get_ethtool_stats,
@@ -1570,6 +1576,8 @@ static const struct ethtool_ops nes_etht
 	.set_coalesce = nes_netdev_set_coalesce,
 	.get_pauseparam = nes_netdev_get_pauseparam,
 	.set_pauseparam = nes_netdev_set_pauseparam,
+	.get_link_ksettings = nes_netdev_get_link_ksettings,
+	.set_link_ksettings = nes_netdev_set_link_ksettings,
 };
 
 static void nes_vlan_mode(struct net_device *netdev, struct nes_device *nesdev, netdev_features_t features)
@@ -1658,7 +1666,7 @@ struct net_device *nes_netdev_init(struc
 
 	netdev->watchdog_timeo = NES_TX_TIMEOUT;
 	netdev->irq = nesdev->pcidev->irq;
-	netdev->mtu = ETH_DATA_LEN;
+	netdev->max_mtu = NES_MAX_MTU;
 	netdev->hard_header_len = ETH_HLEN;
 	netdev->addr_len = ETH_ALEN;
 	netdev->type = ARPHRD_ETHER;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/nes/nes_verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -478,17 +478,7 @@ static int nes_query_port(struct ib_devi
 	memset(props, 0, sizeof(*props));
 
 	props->max_mtu = IB_MTU_4096;
-
-	if (netdev->mtu  >= 4096)
-		props->active_mtu = IB_MTU_4096;
-	else if (netdev->mtu  >= 2048)
-		props->active_mtu = IB_MTU_2048;
-	else if (netdev->mtu  >= 1024)
-		props->active_mtu = IB_MTU_1024;
-	else if (netdev->mtu  >= 512)
-		props->active_mtu = IB_MTU_512;
-	else
-		props->active_mtu = IB_MTU_256;
+	props->active_mtu = ib_mtu_int_to_enum(netdev->mtu);
 
 	props->lid = 1;
 	props->lmc = 0;
@@ -771,7 +761,8 @@ static int nes_dealloc_pd(struct ib_pd *
 /**
  * nes_create_ah
  */
-static struct ib_ah *nes_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+static struct ib_ah *nes_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+				   struct ib_udata *udata)
 {
 	return ERR_PTR(-ENOSYS);
 }
@@ -1075,7 +1066,6 @@ static struct ib_qp *nes_create_qp(struc
 			mem = kzalloc(sizeof(*nesqp)+NES_SW_CONTEXT_ALIGN-1, GFP_KERNEL);
 			if (!mem) {
 				nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
-				nes_debug(NES_DBG_QP, "Unable to allocate QP\n");
 				return ERR_PTR(-ENOMEM);
 			}
 			u64nesqp = (unsigned long)mem;
@@ -1475,7 +1465,6 @@ static struct ib_cq *nes_create_cq(struc
 	nescq = kzalloc(sizeof(struct nes_cq), GFP_KERNEL);
 	if (!nescq) {
 		nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
-		nes_debug(NES_DBG_CQ, "Unable to allocate nes_cq struct\n");
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -2408,7 +2397,6 @@ static struct ib_mr *nes_reg_user_mr(str
 			}
 			nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL);
 			if (!nespbl) {
-				nes_debug(NES_DBG_MR, "Unable to allocate PBL\n");
 				ib_umem_release(region);
 				return ERR_PTR(-ENOMEM);
 			}
@@ -2416,7 +2404,6 @@ static struct ib_mr *nes_reg_user_mr(str
 			if (!nesmr) {
 				ib_umem_release(region);
 				kfree(nespbl);
-				nes_debug(NES_DBG_MR, "Unable to allocate nesmr\n");
 				return ERR_PTR(-ENOMEM);
 			}
 			nesmr->region = region;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.c	2017-02-12 16:03:20.000000000 -0500
@@ -154,7 +154,8 @@ static inline int set_av_attr(struct ocr
 	return status;
 }
 
-struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
+struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr,
+			       struct ib_udata *udata)
 {
 	u32 *ahid_addr;
 	int status;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_ah.h	2017-02-12 16:03:20.000000000 -0500
@@ -50,7 +50,9 @@ enum {
 	OCRDMA_AH_L3_TYPE_MASK		= 0x03,
 	OCRDMA_AH_L3_TYPE_SHIFT		= 0x1D /* 29 bits */
 };
-struct ib_ah *ocrdma_create_ah(struct ib_pd *, struct ib_ah_attr *);
+
+struct ib_ah *ocrdma_create_ah(struct ib_pd *, struct ib_ah_attr *,
+			       struct ib_udata *);
 int ocrdma_destroy_ah(struct ib_ah *);
 int ocrdma_query_ah(struct ib_ah *, struct ib_ah_attr *);
 int ocrdma_modify_ah(struct ib_ah *, struct ib_ah_attr *);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -1596,10 +1596,9 @@ void ocrdma_alloc_pd_pool(struct ocrdma_
 
 	dev->pd_mgr = kzalloc(sizeof(struct ocrdma_pd_resource_mgr),
 			      GFP_KERNEL);
-	if (!dev->pd_mgr) {
-		pr_err("%s(%d)Memory allocation failure.\n", __func__, dev->id);
+	if (!dev->pd_mgr)
 		return;
-	}
+
 	status = ocrdma_mbx_alloc_pd_range(dev);
 	if (status) {
 		pr_err("%s(%d) Unable to initialize PD pool, using default.\n",
@@ -1642,7 +1641,7 @@ static int ocrdma_build_q_conf(u32 *num_
 static int ocrdma_mbx_create_ah_tbl(struct ocrdma_dev *dev)
 {
 	int i;
-	int status = 0;
+	int status = -ENOMEM;
 	int max_ah;
 	struct ocrdma_create_ah_tbl *cmd;
 	struct ocrdma_create_ah_tbl_rsp *rsp;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_stats.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/ocrdma/ocrdma_stats.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/ocrdma/ocrdma_stats.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,10 +84,8 @@ bool ocrdma_alloc_stats_resources(struct
 
 	/* Alloc debugfs mem */
 	mem->debugfs_mem = kzalloc(OCRDMA_MAX_DBGFS_MEM, GFP_KERNEL);
-	if (!mem->debugfs_mem) {
-		pr_err("%s: stats debugfs mem allocation failed\n", __func__);
+	if (!mem->debugfs_mem)
 		return false;
-	}
 
 	return true;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/main.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -576,8 +576,7 @@ static int qedr_set_device_attr(struct q
 	return 0;
 }
 
-void qedr_unaffiliated_event(void *context,
-			     u8 event_code)
+void qedr_unaffiliated_event(void *context, u8 event_code)
 {
 	pr_err("unaffiliated event not implemented yet\n");
 }
@@ -792,6 +791,9 @@ static struct qedr_dev *qedr_add(struct
 		if (device_create_file(&dev->ibdev.dev, qedr_attributes[i]))
 			goto sysfs_err;
 
+	if (!test_and_set_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
+		qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ACTIVE);
+
 	DP_DEBUG(dev, QEDR_MSG_INIT, "qedr driver loaded successfully\n");
 	return dev;
 
@@ -824,11 +826,10 @@ static void qedr_remove(struct qedr_dev
 	ib_dealloc_device(&dev->ibdev);
 }
 
-static int qedr_close(struct qedr_dev *dev)
+static void qedr_close(struct qedr_dev *dev)
 {
-	qedr_ib_dispatch_event(dev, 1, IB_EVENT_PORT_ERR);
-
-	return 0;
+	if (test_and_clear_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
+		qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ERR);
 }
 
 static void qedr_shutdown(struct qedr_dev *dev)
@@ -837,6 +838,12 @@ static void qedr_shutdown(struct qedr_de
 	qedr_remove(dev);
 }
 
+static void qedr_open(struct qedr_dev *dev)
+{
+	if (!test_and_set_bit(QEDR_ENET_STATE_BIT, &dev->enet_state))
+		qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_PORT_ACTIVE);
+}
+
 static void qedr_mac_address_change(struct qedr_dev *dev)
 {
 	union ib_gid *sgid = &dev->sgid_tbl[0];
@@ -863,7 +870,7 @@ static void qedr_mac_address_change(stru
 
 	ether_addr_copy(dev->gsi_ll2_mac_address, dev->ndev->dev_addr);
 
-	qedr_ib_dispatch_event(dev, 1, IB_EVENT_GID_CHANGE);
+	qedr_ib_dispatch_event(dev, QEDR_PORT, IB_EVENT_GID_CHANGE);
 
 	if (rc)
 		DP_ERR(dev, "Error updating mac filter\n");
@@ -877,7 +884,7 @@ static void qedr_notify(struct qedr_dev
 {
 	switch (event) {
 	case QEDE_UP:
-		qedr_ib_dispatch_event(dev, 1, IB_EVENT_PORT_ACTIVE);
+		qedr_open(dev);
 		break;
 	case QEDE_DOWN:
 		qedr_close(dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/qedr_cm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/qedr_cm.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/qedr_cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/qedr_cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,11 +87,8 @@ void qedr_ll2_tx_cb(void *_qdev, struct
 	qedr_inc_sw_gsi_cons(&qp->sq);
 	spin_unlock_irqrestore(&qp->q_lock, flags);
 
-	if (cq->ibcq.comp_handler) {
-		spin_lock_irqsave(&cq->comp_handler_lock, flags);
+	if (cq->ibcq.comp_handler)
 		(*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
-		spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
-	}
 }
 
 void qedr_ll2_rx_cb(void *_dev, struct qed_roce_ll2_packet *pkt,
@@ -113,11 +110,8 @@ void qedr_ll2_rx_cb(void *_dev, struct q
 
 	spin_unlock_irqrestore(&qp->q_lock, flags);
 
-	if (cq->ibcq.comp_handler) {
-		spin_lock_irqsave(&cq->comp_handler_lock, flags);
+	if (cq->ibcq.comp_handler)
 		(*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context);
-		spin_unlock_irqrestore(&cq->comp_handler_lock, flags);
-	}
 }
 
 static void qedr_destroy_gsi_cq(struct qedr_dev *dev,
@@ -404,9 +398,9 @@ static inline int qedr_gsi_build_packet(
 	}
 
 	if (ether_addr_equal(udh.eth.smac_h, udh.eth.dmac_h))
-		packet->tx_dest = QED_ROCE_LL2_TX_DEST_NW;
-	else
 		packet->tx_dest = QED_ROCE_LL2_TX_DEST_LB;
+	else
+		packet->tx_dest = QED_ROCE_LL2_TX_DEST_NW;
 
 	packet->roce_mode = roce_mode;
 	memcpy(packet->header.vaddr, ud_header_buffer, header_size);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/qedr.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/qedr.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/qedr.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/qedr.h	2017-02-12 16:03:20.000000000 -0500
@@ -113,6 +113,8 @@ struct qedr_device_attr {
 	struct qed_rdma_events events;
 };
 
+#define QEDR_ENET_STATE_BIT	(0)
+
 struct qedr_dev {
 	struct ib_device	ibdev;
 	struct qed_dev		*cdev;
@@ -153,6 +155,8 @@ struct qedr_dev {
 	struct qedr_cq		*gsi_sqcq;
 	struct qedr_cq		*gsi_rqcq;
 	struct qedr_qp		*gsi_qp;
+
+	unsigned long enet_state;
 };
 
 #define QEDR_MAX_SQ_PBL			(0x8000)
@@ -188,6 +192,7 @@ struct qedr_dev {
 #define QEDR_ROCE_MAX_CNQ_SIZE		(0x4000)
 
 #define QEDR_MAX_PORT			(1)
+#define QEDR_PORT			(1)
 
 #define QEDR_UVERBS(CMD_NAME) (1ull << IB_USER_VERBS_CMD_##CMD_NAME)
 
@@ -251,9 +256,6 @@ struct qedr_cq {
 
 	u16 icid;
 
-	/* Lock to protect completion handler */
-	spinlock_t comp_handler_lock;
-
 	/* Lock to protect multiplem CQ's */
 	spinlock_t cq_lock;
 	u8 arm_flags;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -471,8 +471,6 @@ struct ib_pd *qedr_alloc_pd(struct ib_de
 			    struct ib_ucontext *context, struct ib_udata *udata)
 {
 	struct qedr_dev *dev = get_qedr_dev(ibdev);
-	struct qedr_ucontext *uctx = NULL;
-	struct qedr_alloc_pd_uresp uresp;
 	struct qedr_pd *pd;
 	u16 pd_id;
 	int rc;
@@ -489,21 +487,33 @@ struct ib_pd *qedr_alloc_pd(struct ib_de
 	if (!pd)
 		return ERR_PTR(-ENOMEM);
 
-	dev->ops->rdma_alloc_pd(dev->rdma_ctx, &pd_id);
+	rc = dev->ops->rdma_alloc_pd(dev->rdma_ctx, &pd_id);
+	if (rc)
+		goto err;
 
-	uresp.pd_id = pd_id;
 	pd->pd_id = pd_id;
 
 	if (udata && context) {
+		struct qedr_alloc_pd_uresp uresp;
+
+		uresp.pd_id = pd_id;
+
 		rc = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
-		if (rc)
+		if (rc) {
 			DP_ERR(dev, "copy error pd_id=0x%x.\n", pd_id);
-		uctx = get_qedr_ucontext(context);
-		uctx->pd = pd;
-		pd->uctx = uctx;
+			dev->ops->rdma_dealloc_pd(dev->rdma_ctx, pd_id);
+			goto err;
+		}
+
+		pd->uctx = get_qedr_ucontext(context);
+		pd->uctx->pd = pd;
 	}
 
 	return &pd->ibpd;
+
+err:
+	kfree(pd);
+	return ERR_PTR(rc);
 }
 
 int qedr_dealloc_pd(struct ib_pd *ibpd)
@@ -511,8 +521,10 @@ int qedr_dealloc_pd(struct ib_pd *ibpd)
 	struct qedr_dev *dev = get_qedr_dev(ibpd->device);
 	struct qedr_pd *pd = get_qedr_pd(ibpd);
 
-	if (!pd)
+	if (!pd) {
 		pr_err("Invalid PD received in dealloc_pd\n");
+		return -EINVAL;
+	}
 
 	DP_DEBUG(dev, QEDR_MSG_INIT, "Deallocating PD %d\n", pd->pd_id);
 	dev->ops->rdma_dealloc_pd(dev->rdma_ctx, pd->pd_id);
@@ -888,6 +900,8 @@ struct ib_cq *qedr_create_cq(struct ib_d
 
 		pbl_ptr = cq->q.pbl_tbl->pa;
 		page_cnt = cq->q.pbl_info.num_pbes;
+
+		cq->ibcq.cqe = chain_entries;
 	} else {
 		cq->cq_type = QEDR_CQ_TYPE_KERNEL;
 
@@ -903,6 +917,7 @@ struct ib_cq *qedr_create_cq(struct ib_d
 
 		page_cnt = qed_chain_get_page_cnt(&cq->pbl);
 		pbl_ptr = qed_chain_get_pbl_phys(&cq->pbl);
+		cq->ibcq.cqe = cq->pbl.capacity;
 	}
 
 	qedr_init_cq_params(cq, ctx, dev, vector, chain_entries, page_cnt,
@@ -980,8 +995,13 @@ int qedr_destroy_cq(struct ib_cq *ibcq)
 
 	/* GSIs CQs are handled by driver, so they don't exist in the FW */
 	if (cq->cq_type != QEDR_CQ_TYPE_GSI) {
+		int rc;
+
 		iparams.icid = cq->icid;
-		dev->ops->rdma_destroy_cq(dev->rdma_ctx, &iparams, &oparams);
+		rc = dev->ops->rdma_destroy_cq(dev->rdma_ctx, &iparams,
+					       &oparams);
+		if (rc)
+			return rc;
 		dev->ops->common->chain_free(dev->cdev, &cq->pbl);
 	}
 
@@ -1477,6 +1497,7 @@ struct ib_qp *qedr_create_qp(struct ib_p
 	struct qedr_ucontext *ctx = NULL;
 	struct qedr_create_qp_ureq ureq;
 	struct qedr_qp *qp;
+	struct ib_qp *ibqp;
 	int rc = 0;
 
 	DP_DEBUG(dev, QEDR_MSG_QP, "create qp: called from %s, pd=%p\n",
@@ -1486,13 +1507,13 @@ struct ib_qp *qedr_create_qp(struct ib_p
 	if (rc)
 		return ERR_PTR(rc);
 
+	if (attrs->srq)
+		return ERR_PTR(-EINVAL);
+
 	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
 	if (!qp)
 		return ERR_PTR(-ENOMEM);
 
-	if (attrs->srq)
-		return ERR_PTR(-EINVAL);
-
 	DP_DEBUG(dev, QEDR_MSG_QP,
 		 "create qp: sq_cq=%p, sq_icid=%d, rq_cq=%p, rq_icid=%d\n",
 		 get_qedr_cq(attrs->send_cq),
@@ -1508,7 +1529,10 @@ struct ib_qp *qedr_create_qp(struct ib_p
 			       "create qp: unexpected udata when creating GSI QP\n");
 			goto err0;
 		}
-		return qedr_create_gsi_qp(dev, attrs, qp);
+		ibqp = qedr_create_gsi_qp(dev, attrs, qp);
+		if (IS_ERR(ibqp))
+			kfree(qp);
+		return ibqp;
 	}
 
 	memset(&in_params, 0, sizeof(in_params));
@@ -1586,7 +1610,7 @@ err0:
 	return ERR_PTR(-EFAULT);
 }
 
-enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state qp_state)
+static enum ib_qp_state qedr_get_ibqp_state(enum qed_roce_qp_state qp_state)
 {
 	switch (qp_state) {
 	case QED_ROCE_QP_STATE_RESET:
@@ -1607,7 +1631,8 @@ enum ib_qp_state qedr_get_ibqp_state(enu
 	return IB_QPS_ERR;
 }
 
-enum qed_roce_qp_state qedr_get_state_from_ibqp(enum ib_qp_state qp_state)
+static enum qed_roce_qp_state qedr_get_state_from_ibqp(
+					enum ib_qp_state qp_state)
 {
 	switch (qp_state) {
 	case IB_QPS_RESET:
@@ -1643,7 +1668,7 @@ static int qedr_update_qp_state(struct q
 	int status = 0;
 
 	if (new_state == qp->state)
-		return 1;
+		return 0;
 
 	switch (qp->state) {
 	case QED_ROCE_QP_STATE_RESET:
@@ -1719,6 +1744,14 @@ static int qedr_update_qp_state(struct q
 		/* ERR->XXX */
 		switch (new_state) {
 		case QED_ROCE_QP_STATE_RESET:
+			if ((qp->rq.prod != qp->rq.cons) ||
+			    (qp->sq.prod != qp->sq.cons)) {
+				DP_NOTICE(dev,
+					  "Error->Reset with rq/sq not empty rq.prod=%x rq.cons=%x sq.prod=%x sq.cons=%x\n",
+					  qp->rq.prod, qp->rq.cons, qp->sq.prod,
+					  qp->sq.cons);
+				status = -EINVAL;
+			}
 			break;
 		default:
 			status = -EINVAL;
@@ -1851,7 +1884,6 @@ int qedr_modify_qp(struct ib_qp *ibqp, s
 			 qp_params.sgid.dwords[2], qp_params.sgid.dwords[3]);
 		DP_DEBUG(dev, QEDR_MSG_QP, "remote_mac=[%pM]\n",
 			 qp_params.remote_mac_addr);
-;
 
 		qp_params.mtu = qp->mtu;
 		qp_params.lb_indication = false;
@@ -1960,7 +1992,7 @@ int qedr_modify_qp(struct ib_qp *ibqp, s
 
 	if (attr_mask & IB_QP_STATE) {
 		if ((qp->qp_type != IB_QPT_GSI) && (!udata))
-			qedr_update_qp_state(dev, qp, qp_params.new_state);
+			rc = qedr_update_qp_state(dev, qp, qp_params.new_state);
 		qp->state = qp_params.new_state;
 	}
 
@@ -2002,7 +2034,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
 
 	qp_attr->qp_state = qedr_get_ibqp_state(params.state);
 	qp_attr->cur_qp_state = qedr_get_ibqp_state(params.state);
-	qp_attr->path_mtu = iboe_get_mtu(params.mtu);
+	qp_attr->path_mtu = ib_mtu_int_to_enum(params.mtu);
 	qp_attr->path_mig_state = IB_MIG_MIGRATED;
 	qp_attr->rq_psn = params.rq_psn;
 	qp_attr->sq_psn = params.sq_psn;
@@ -2014,7 +2046,7 @@ int qedr_query_qp(struct ib_qp *ibqp,
 	qp_attr->cap.max_recv_wr = qp->rq.max_wr;
 	qp_attr->cap.max_send_sge = qp->sq.max_sges;
 	qp_attr->cap.max_recv_sge = qp->rq.max_sges;
-	qp_attr->cap.max_inline_data = qp->max_inline_data;
+	qp_attr->cap.max_inline_data = ROCE_REQ_MAX_INLINE_DATA_SIZE;
 	qp_init_attr->cap = qp_attr->cap;
 
 	memcpy(&qp_attr->ah_attr.grh.dgid.raw[0], &params.dgid.bytes[0],
@@ -2064,8 +2096,10 @@ int qedr_destroy_qp(struct ib_qp *ibqp)
 	DP_DEBUG(dev, QEDR_MSG_QP, "destroy qp: destroying %p, qp type=%d\n",
 		 qp, qp->qp_type);
 
-	if (qp->state != (QED_ROCE_QP_STATE_RESET | QED_ROCE_QP_STATE_ERR |
-			  QED_ROCE_QP_STATE_INIT)) {
+	if ((qp->state != QED_ROCE_QP_STATE_RESET) &&
+	    (qp->state != QED_ROCE_QP_STATE_ERR) &&
+	    (qp->state != QED_ROCE_QP_STATE_INIT)) {
+
 		attr.qp_state = IB_QPS_ERR;
 		attr_mask |= IB_QP_STATE;
 
@@ -2094,7 +2128,8 @@ int qedr_destroy_qp(struct ib_qp *ibqp)
 	return rc;
 }
 
-struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
+struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr,
+			     struct ib_udata *udata)
 {
 	struct qedr_ah *ah;
 
@@ -2285,7 +2320,8 @@ int qedr_dereg_mr(struct ib_mr *ib_mr)
 	return rc;
 }
 
-struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd, int max_page_list_len)
+static struct qedr_mr *__qedr_alloc_mr(struct ib_pd *ibpd,
+				       int max_page_list_len)
 {
 	struct qedr_pd *pd = get_qedr_pd(ibpd);
 	struct qedr_dev *dev = get_qedr_dev(ibpd->device);
@@ -2413,8 +2449,7 @@ static void handle_completed_mrs(struct
 		 */
 		pbl = list_first_entry(&info->inuse_pbl_list,
 				       struct qedr_pbl, list_entry);
-		list_del(&pbl->list_entry);
-		list_add_tail(&pbl->list_entry, &info->free_pbl_list);
+		list_move_tail(&pbl->list_entry, &info->free_pbl_list);
 		info->completed_handled++;
 	}
 }
@@ -2620,7 +2655,9 @@ static u32 qedr_prepare_sq_rdma_data(str
 	rwqe2->r_key = cpu_to_le32(rdma_wr(wr)->rkey);
 	DMA_REGPAIR_LE(rwqe2->remote_va, rdma_wr(wr)->remote_addr);
 
-	if (wr->send_flags & IB_SEND_INLINE) {
+	if (wr->send_flags & IB_SEND_INLINE &&
+	    (wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM ||
+	     wr->opcode == IB_WR_RDMA_WRITE)) {
 		u8 flags = 0;
 
 		SET_FIELD2(flags, RDMA_SQ_RDMA_WQE_1ST_INLINE_FLG, 1);
@@ -2686,7 +2723,7 @@ static int qedr_prepare_reg(struct qedr_
 	return 0;
 }
 
-enum ib_wc_opcode qedr_ib_to_wc_opcode(enum ib_wr_opcode opcode)
+static enum ib_wc_opcode qedr_ib_to_wc_opcode(enum ib_wr_opcode opcode)
 {
 	switch (opcode) {
 	case IB_WR_RDMA_WRITE:
@@ -2711,7 +2748,7 @@ enum ib_wc_opcode qedr_ib_to_wc_opcode(e
 	}
 }
 
-inline bool qedr_can_post_send(struct qedr_qp *qp, struct ib_send_wr *wr)
+static inline bool qedr_can_post_send(struct qedr_qp *qp, struct ib_send_wr *wr)
 {
 	int wq_is_full, err_wr, pbl_is_full;
 	struct qedr_dev *dev = qp->dev;
@@ -2748,7 +2785,7 @@ inline bool qedr_can_post_send(struct qe
 	return true;
 }
 
-int __qedr_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+static int __qedr_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 		     struct ib_send_wr **bad_wr)
 {
 	struct qedr_dev *dev = get_qedr_dev(ibqp->device);
@@ -2971,8 +3008,9 @@ int qedr_post_send(struct ib_qp *ibqp, s
 
 	spin_lock_irqsave(&qp->q_lock, flags);
 
-	if ((qp->state == QED_ROCE_QP_STATE_RESET) ||
-	    (qp->state == QED_ROCE_QP_STATE_ERR)) {
+	if ((qp->state != QED_ROCE_QP_STATE_RTS) &&
+	    (qp->state != QED_ROCE_QP_STATE_ERR) &&
+	    (qp->state != QED_ROCE_QP_STATE_SQD)) {
 		spin_unlock_irqrestore(&qp->q_lock, flags);
 		*bad_wr = wr;
 		DP_DEBUG(dev, QEDR_MSG_CQ,
@@ -2981,11 +3019,6 @@ int qedr_post_send(struct ib_qp *ibqp, s
 		return -EINVAL;
 	}
 
-	if (!wr) {
-		DP_ERR(dev, "Got an empty post send.\n");
-		return -EINVAL;
-	}
-
 	while (wr) {
 		rc = __qedr_post_send(ibqp, wr, bad_wr);
 		if (rc)
@@ -3030,8 +3063,7 @@ int qedr_post_recv(struct ib_qp *ibqp, s
 
 	spin_lock_irqsave(&qp->q_lock, flags);
 
-	if ((qp->state == QED_ROCE_QP_STATE_RESET) ||
-	    (qp->state == QED_ROCE_QP_STATE_ERR)) {
+	if (qp->state == QED_ROCE_QP_STATE_RESET) {
 		spin_unlock_irqrestore(&qp->q_lock, flags);
 		*bad_wr = wr;
 		return -EINVAL;
@@ -3173,6 +3205,7 @@ static int process_req(struct qedr_dev *
 
 		/* fill WC */
 		wc->status = status;
+		wc->vendor_err = 0;
 		wc->wc_flags = 0;
 		wc->src_qp = qp->id;
 		wc->qp = &qp->ibqp;
@@ -3220,11 +3253,12 @@ static int qedr_poll_cq_req(struct qedr_
 				  IB_WC_SUCCESS, 0);
 		break;
 	case RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR:
-		DP_ERR(dev,
-		       "Error: POLL CQ with RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR. CQ icid=0x%x, QP icid=0x%x\n",
-		       cq->icid, qp->icid);
+		if (qp->state != QED_ROCE_QP_STATE_ERR)
+			DP_ERR(dev,
+			       "Error: POLL CQ with RDMA_CQE_REQ_STS_WORK_REQUEST_FLUSHED_ERR. CQ icid=0x%x, QP icid=0x%x\n",
+			       cq->icid, qp->icid);
 		cnt = process_req(dev, qp, cq, num_entries, wc, req->sq_cons,
-				  IB_WC_WR_FLUSH_ERR, 0);
+				  IB_WC_WR_FLUSH_ERR, 1);
 		break;
 	default:
 		/* process all WQE before the cosumer */
@@ -3362,6 +3396,7 @@ static void __process_resp_one(struct qe
 
 	/* fill WC */
 	wc->status = wc_status;
+	wc->vendor_err = 0;
 	wc->src_qp = qp->id;
 	wc->qp = &qp->ibqp;
 	wc->wr_id = wr_id;
@@ -3390,6 +3425,7 @@ static int process_resp_flush(struct qed
 	while (num_entries && qp->rq.wqe_cons != hw_cons) {
 		/* fill WC */
 		wc->status = IB_WC_WR_FLUSH_ERR;
+		wc->vendor_err = 0;
 		wc->wc_flags = 0;
 		wc->src_qp = qp->id;
 		wc->byte_len = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/verbs.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/verbs.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qedr/verbs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qedr/verbs.h	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,8 @@ int qedr_query_qp(struct ib_qp *, struct
 		  int qp_attr_mask, struct ib_qp_init_attr *);
 int qedr_destroy_qp(struct ib_qp *ibqp);
 
-struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr);
+struct ib_ah *qedr_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr,
+			     struct ib_udata *udata);
 int qedr_destroy_ah(struct ib_ah *ibah);
 
 int qedr_dereg_mr(struct ib_mr *);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_diag.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_diag.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_diag.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_diag.c	2017-02-12 16:03:20.000000000 -0500
@@ -609,8 +609,6 @@ static ssize_t qib_diagpkt_write(struct
 
 	tmpbuf = vmalloc(plen);
 	if (!tmpbuf) {
-		qib_devinfo(dd->pcidev,
-			"Unable to allocate tmp buffer, failing\n");
 		ret = -ENOMEM;
 		goto bail;
 	}
@@ -702,10 +700,8 @@ int qib_register_observer(struct qib_dev
 	if (!dd || !op)
 		return -EINVAL;
 	olp = vmalloc(sizeof(*olp));
-	if (!olp) {
-		pr_err("vmalloc for observer failed\n");
+	if (!olp)
 		return -ENOMEM;
-	}
 
 	spin_lock_irqsave(&dd->qib_diag_trans_lock, flags);
 	olp->op = op;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_driver.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_driver.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -420,8 +420,7 @@ static u32 qib_rcv_hdrerr(struct qib_ctx
 						if (list_empty(&qp->rspwait)) {
 							qp->r_flags |=
 								RVT_R_RSP_NAK;
-							atomic_inc(
-								&qp->refcount);
+							rvt_get_qp(qp);
 							list_add_tail(
 							 &qp->rspwait,
 							 &rcd->qp_wait_list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_eeprom.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_eeprom.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_eeprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_eeprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -182,12 +182,8 @@ void qib_get_eeprom_info(struct qib_devd
 	 * */
 	len = sizeof(struct qib_flash);
 	buf = vmalloc(len);
-	if (!buf) {
-		qib_dev_err(dd,
-			"Couldn't allocate memory to read %u bytes from eeprom for GUID\n",
-			len);
+	if (!buf)
 		goto bail;
-	}
 
 	/*
 	 * Use "public" eeprom read function, which does locking and
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_file_ops.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_file_ops.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_file_ops.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_file_ops.c	2017-02-12 16:03:20.000000000 -0500
@@ -2066,8 +2066,11 @@ static ssize_t qib_write(struct file *fp
 	ssize_t ret = 0;
 	void *dest;
 
-	if (WARN_ON_ONCE(!ib_safe_file_access(fp)))
+	if (!ib_safe_file_access(fp)) {
+		pr_err_once("qib_write: process %d (%s) changed security contexts after opening file descriptor, this is not allowed.\n",
+			    task_tgid_vnr(current), current->comm);
 		return -EACCES;
+	}
 
 	if (count < sizeof(cmd.type)) {
 		ret = -EINVAL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_iba6120.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_iba6120.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_iba6120.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_iba6120.c	2017-02-12 16:03:20.000000000 -0500
@@ -1759,9 +1759,7 @@ static void pe_boardname(struct qib_devd
 	}
 	namelen = strlen(n) + 1;
 	dd->boardname = kmalloc(namelen, GFP_KERNEL);
-	if (!dd->boardname)
-		qib_dev_err(dd, "Failed allocation for board name: %s\n", n);
-	else
+	if (dd->boardname)
 		snprintf(dd->boardname, namelen, "%s", n);
 
 	if (dd->majrev != 4 || !dd->minrev || dd->minrev > 2)
@@ -2533,8 +2531,6 @@ static void init_6120_cntrnames(struct q
 		dd->cspec->cntrnamelen = 1 + s - cntr6120names;
 	dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs
 		* sizeof(u64), GFP_KERNEL);
-	if (!dd->cspec->cntrs)
-		qib_dev_err(dd, "Failed allocation for counters\n");
 
 	for (i = 0, s = (char *)portcntr6120names; s; i++)
 		s = strchr(s + 1, '\n');
@@ -2542,8 +2538,6 @@ static void init_6120_cntrnames(struct q
 	dd->cspec->portcntrnamelen = sizeof(portcntr6120names) - 1;
 	dd->cspec->portcntrs = kmalloc(dd->cspec->nportcntrs
 		* sizeof(u64), GFP_KERNEL);
-	if (!dd->cspec->portcntrs)
-		qib_dev_err(dd, "Failed allocation for portcounters\n");
 }
 
 static u32 qib_read_6120cntrs(struct qib_devdata *dd, loff_t pos, char **namep,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_iba7220.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_iba7220.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_iba7220.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_iba7220.c	2017-02-12 16:03:20.000000000 -0500
@@ -2070,9 +2070,7 @@ static void qib_7220_boardname(struct qi
 
 	namelen = strlen(n) + 1;
 	dd->boardname = kmalloc(namelen, GFP_KERNEL);
-	if (!dd->boardname)
-		qib_dev_err(dd, "Failed allocation for board name: %s\n", n);
-	else
+	if (dd->boardname)
 		snprintf(dd->boardname, namelen, "%s", n);
 
 	if (dd->majrev != 5 || !dd->minrev || dd->minrev > 2)
@@ -3179,8 +3177,6 @@ static void init_7220_cntrnames(struct q
 		dd->cspec->cntrnamelen = 1 + s - cntr7220names;
 	dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs
 		* sizeof(u64), GFP_KERNEL);
-	if (!dd->cspec->cntrs)
-		qib_dev_err(dd, "Failed allocation for counters\n");
 
 	for (i = 0, s = (char *)portcntr7220names; s; i++)
 		s = strchr(s + 1, '\n');
@@ -3188,8 +3184,6 @@ static void init_7220_cntrnames(struct q
 	dd->cspec->portcntrnamelen = sizeof(portcntr7220names) - 1;
 	dd->cspec->portcntrs = kmalloc(dd->cspec->nportcntrs
 		* sizeof(u64), GFP_KERNEL);
-	if (!dd->cspec->portcntrs)
-		qib_dev_err(dd, "Failed allocation for portcounters\n");
 }
 
 static u32 qib_read_7220cntrs(struct qib_devdata *dd, loff_t pos, char **namep,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_iba7322.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_iba7322.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_iba7322.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_iba7322.c	2017-02-12 16:03:20.000000000 -0500
@@ -3627,9 +3627,7 @@ static unsigned qib_7322_boardname(struc
 
 	namelen = strlen(n) + 1;
 	dd->boardname = kmalloc(namelen, GFP_KERNEL);
-	if (!dd->boardname)
-		qib_dev_err(dd, "Failed allocation for board name: %s\n", n);
-	else
+	if (dd->boardname)
 		snprintf(dd->boardname, namelen, "%s", n);
 
 	snprintf(dd->boardversion, sizeof(dd->boardversion),
@@ -3656,7 +3654,7 @@ static unsigned qib_7322_boardname(struc
 static int qib_do_7322_reset(struct qib_devdata *dd)
 {
 	u64 val;
-	u64 *msix_vecsave;
+	u64 *msix_vecsave = NULL;
 	int i, msix_entries, ret = 1;
 	u16 cmdval;
 	u8 int_line, clinesz;
@@ -3677,10 +3675,7 @@ static int qib_do_7322_reset(struct qib_
 		/* can be up to 512 bytes, too big for stack */
 		msix_vecsave = kmalloc(2 * dd->cspec->num_msix_entries *
 			sizeof(u64), GFP_KERNEL);
-		if (!msix_vecsave)
-			qib_dev_err(dd, "No mem to save MSIx data\n");
-	} else
-		msix_vecsave = NULL;
+	}
 
 	/*
 	 * Core PCI (as of 2.6.18) doesn't save or rewrite the full vector
@@ -5043,8 +5038,6 @@ static void init_7322_cntrnames(struct q
 		dd->cspec->cntrnamelen = 1 + s - cntr7322names;
 	dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs
 		* sizeof(u64), GFP_KERNEL);
-	if (!dd->cspec->cntrs)
-		qib_dev_err(dd, "Failed allocation for counters\n");
 
 	for (i = 0, s = (char *)portcntr7322names; s; i++)
 		s = strchr(s + 1, '\n');
@@ -5053,9 +5046,6 @@ static void init_7322_cntrnames(struct q
 	for (i = 0; i < dd->num_pports; ++i) {
 		dd->pport[i].cpspec->portcntrs = kmalloc(dd->cspec->nportcntrs
 			* sizeof(u64), GFP_KERNEL);
-		if (!dd->pport[i].cpspec->portcntrs)
-			qib_dev_err(dd,
-				"Failed allocation for portcounters\n");
 	}
 }
 
@@ -6461,7 +6451,6 @@ static int qib_init_7322_variables(struc
 		sizeof(*dd->cspec->sendibchk), GFP_KERNEL);
 	if (!dd->cspec->sendchkenable || !dd->cspec->sendgrhchk ||
 		!dd->cspec->sendibchk) {
-		qib_dev_err(dd, "Failed allocation for hdrchk bitmaps\n");
 		ret = -ENOMEM;
 		goto bail;
 	}
@@ -7338,10 +7327,9 @@ struct qib_devdata *qib_init_iba7322_fun
 	tabsize = actual_cnt;
 	dd->cspec->msix_entries = kzalloc(tabsize *
 			sizeof(struct qib_msix_entry), GFP_KERNEL);
-	if (!dd->cspec->msix_entries) {
-		qib_dev_err(dd, "No memory for MSIx table\n");
+	if (!dd->cspec->msix_entries)
 		tabsize = 0;
-	}
+
 	for (i = 0; i < tabsize; i++)
 		dd->cspec->msix_entries[i].msix.entry = i;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_init.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_init.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_init.c	2017-02-12 16:03:20.000000000 -0500
@@ -133,11 +133,8 @@ int qib_create_ctxts(struct qib_devdata
 	 * cleanup iterates across all possible ctxts.
 	 */
 	dd->rcd = kcalloc(dd->ctxtcnt, sizeof(*dd->rcd), GFP_KERNEL);
-	if (!dd->rcd) {
-		qib_dev_err(dd,
-			"Unable to allocate ctxtdata array, failing\n");
+	if (!dd->rcd)
 		return -ENOMEM;
-	}
 
 	/* create (one or more) kctxt */
 	for (i = 0; i < dd->first_user_ctxt; ++i) {
@@ -265,39 +262,23 @@ int qib_init_pportdata(struct qib_pportd
 	size = IB_CC_TABLE_CAP_DEFAULT * sizeof(struct ib_cc_table_entry)
 		* IB_CCT_ENTRIES;
 	ppd->ccti_entries = kzalloc(size, GFP_KERNEL);
-	if (!ppd->ccti_entries) {
-		qib_dev_err(dd,
-		  "failed to allocate congestion control table for port %d!\n",
-		  port);
+	if (!ppd->ccti_entries)
 		goto bail;
-	}
 
 	size = IB_CC_CCS_ENTRIES * sizeof(struct ib_cc_congestion_entry);
 	ppd->congestion_entries = kzalloc(size, GFP_KERNEL);
-	if (!ppd->congestion_entries) {
-		qib_dev_err(dd,
-		 "failed to allocate congestion setting list for port %d!\n",
-		 port);
+	if (!ppd->congestion_entries)
 		goto bail_1;
-	}
 
 	size = sizeof(struct cc_table_shadow);
 	ppd->ccti_entries_shadow = kzalloc(size, GFP_KERNEL);
-	if (!ppd->ccti_entries_shadow) {
-		qib_dev_err(dd,
-		 "failed to allocate shadow ccti list for port %d!\n",
-		 port);
+	if (!ppd->ccti_entries_shadow)
 		goto bail_2;
-	}
 
 	size = sizeof(struct ib_cc_congestion_setting_attr);
 	ppd->congestion_entries_shadow = kzalloc(size, GFP_KERNEL);
-	if (!ppd->congestion_entries_shadow) {
-		qib_dev_err(dd,
-		 "failed to allocate shadow congestion setting list for port %d!\n",
-		 port);
+	if (!ppd->congestion_entries_shadow)
 		goto bail_3;
-	}
 
 	return 0;
 
@@ -391,18 +372,12 @@ static void init_shadow_tids(struct qib_
 	dma_addr_t *addrs;
 
 	pages = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *));
-	if (!pages) {
-		qib_dev_err(dd,
-			"failed to allocate shadow page * array, no expected sends!\n");
+	if (!pages)
 		goto bail;
-	}
 
 	addrs = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t));
-	if (!addrs) {
-		qib_dev_err(dd,
-			"failed to allocate shadow dma handle array, no expected sends!\n");
+	if (!addrs)
 		goto bail_free;
-	}
 
 	dd->pageshadow = pages;
 	dd->physshadow = addrs;
@@ -1026,11 +1001,8 @@ static void qib_verify_pioperf(struct qi
 	cnt = 1024;
 
 	addr = vmalloc(cnt);
-	if (!addr) {
-		qib_devinfo(dd->pcidev,
-			 "Couldn't get memory for checking PIO perf, skipping\n");
+	if (!addr)
 		goto done;
-	}
 
 	preempt_disable();  /* we want reasonably accurate elapsed time */
 	msecs = 1 + jiffies_to_msecs(jiffies);
@@ -1172,9 +1144,6 @@ struct qib_devdata *qib_alloc_devdata(st
 				      sizeof(long), GFP_KERNEL);
 		if (qib_cpulist)
 			qib_cpulist_count = count;
-		else
-			qib_early_err(&pdev->dev,
-				"Could not alloc cpulist info, cpu affinity might be wrong\n");
 	}
 #ifdef CONFIG_DEBUG_FS
 	qib_dbg_ibdev_init(&dd->verbs_dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_rc.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_rc.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_rc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_rc.c	2017-02-12 16:03:20.000000000 -0500
@@ -941,8 +941,6 @@ void qib_rc_send_complete(struct rvt_qp
 {
 	struct ib_other_headers *ohdr;
 	struct rvt_swqe *wqe;
-	struct ib_wc wc;
-	unsigned i;
 	u32 opcode;
 	u32 psn;
 
@@ -988,22 +986,8 @@ void qib_rc_send_complete(struct rvt_qp
 		qp->s_last = s_last;
 		/* see post_send() */
 		barrier();
-		for (i = 0; i < wqe->wr.num_sge; i++) {
-			struct rvt_sge *sge = &wqe->sg_list[i];
-
-			rvt_put_mr(sge->mr);
-		}
-		/* Post a send completion queue entry if requested. */
-		if (!(qp->s_flags & RVT_S_SIGNAL_REQ_WR) ||
-		    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
-			memset(&wc, 0, sizeof(wc));
-			wc.wr_id = wqe->wr.wr_id;
-			wc.status = IB_WC_SUCCESS;
-			wc.opcode = ib_qib_wc_opcode[wqe->wr.opcode];
-			wc.byte_len = wqe->length;
-			wc.qp = &qp->ibqp;
-			rvt_cq_enter(ibcq_to_rvtcq(qp->ibqp.send_cq), &wc, 0);
-		}
+		rvt_put_swqe(wqe);
+		rvt_qp_swqe_complete(qp, wqe, IB_WC_SUCCESS);
 	}
 	/*
 	 * If we were waiting for sends to complete before resending,
@@ -1032,9 +1016,6 @@ static struct rvt_swqe *do_rc_completion
 					 struct rvt_swqe *wqe,
 					 struct qib_ibport *ibp)
 {
-	struct ib_wc wc;
-	unsigned i;
-
 	/*
 	 * Don't decrement refcount and don't generate a
 	 * completion if the SWQE is being resent until the send
@@ -1044,28 +1025,14 @@ static struct rvt_swqe *do_rc_completion
 	    qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) > 0) {
 		u32 s_last;
 
-		for (i = 0; i < wqe->wr.num_sge; i++) {
-			struct rvt_sge *sge = &wqe->sg_list[i];
-
-			rvt_put_mr(sge->mr);
-		}
+		rvt_put_swqe(wqe);
 		s_last = qp->s_last;
 		if (++s_last >= qp->s_size)
 			s_last = 0;
 		qp->s_last = s_last;
 		/* see post_send() */
 		barrier();
-		/* Post a send completion queue entry if requested. */
-		if (!(qp->s_flags & RVT_S_SIGNAL_REQ_WR) ||
-		    (wqe->wr.send_flags & IB_SEND_SIGNALED)) {
-			memset(&wc, 0, sizeof(wc));
-			wc.wr_id = wqe->wr.wr_id;
-			wc.status = IB_WC_SUCCESS;
-			wc.opcode = ib_qib_wc_opcode[wqe->wr.opcode];
-			wc.byte_len = wqe->length;
-			wc.qp = &qp->ibqp;
-			rvt_cq_enter(ibcq_to_rvtcq(qp->ibqp.send_cq), &wc, 0);
-		}
+		rvt_qp_swqe_complete(qp, wqe, IB_WC_SUCCESS);
 	} else
 		this_cpu_inc(*ibp->rvp.rc_delayed_comp);
 
@@ -2112,8 +2079,7 @@ send_last:
 			 * Update the next expected PSN.  We add 1 later
 			 * below, so only add the remainder here.
 			 */
-			if (len > pmtu)
-				qp->r_psn += (len - 1) / pmtu;
+			qp->r_psn += rvt_div_mtu(qp, len - 1);
 		} else {
 			e->rdma_sge.mr = NULL;
 			e->rdma_sge.vaddr = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_ruc.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_ruc.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_ruc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_ruc.c	2017-02-12 16:03:20.000000000 -0500
@@ -793,7 +793,6 @@ void qib_send_complete(struct rvt_qp *qp
 		       enum ib_wc_status status)
 {
 	u32 old_last, last;
-	unsigned i;
 
 	if (!(ib_rvt_state_ops[qp->state] & RVT_PROCESS_OR_FLUSH_SEND))
 		return;
@@ -805,32 +804,13 @@ void qib_send_complete(struct rvt_qp *qp
 	qp->s_last = last;
 	/* See post_send() */
 	barrier();
-	for (i = 0; i < wqe->wr.num_sge; i++) {
-		struct rvt_sge *sge = &wqe->sg_list[i];
-
-		rvt_put_mr(sge->mr);
-	}
+	rvt_put_swqe(wqe);
 	if (qp->ibqp.qp_type == IB_QPT_UD ||
 	    qp->ibqp.qp_type == IB_QPT_SMI ||
 	    qp->ibqp.qp_type == IB_QPT_GSI)
 		atomic_dec(&ibah_to_rvtah(wqe->ud_wr.ah)->refcount);
 
-	/* See ch. 11.2.4.1 and 10.7.3.1 */
-	if (!(qp->s_flags & RVT_S_SIGNAL_REQ_WR) ||
-	    (wqe->wr.send_flags & IB_SEND_SIGNALED) ||
-	    status != IB_WC_SUCCESS) {
-		struct ib_wc wc;
-
-		memset(&wc, 0, sizeof(wc));
-		wc.wr_id = wqe->wr.wr_id;
-		wc.status = status;
-		wc.opcode = ib_qib_wc_opcode[wqe->wr.opcode];
-		wc.qp = &qp->ibqp;
-		if (status == IB_WC_SUCCESS)
-			wc.byte_len = wqe->length;
-		rvt_cq_enter(ibcq_to_rvtcq(qp->ibqp.send_cq), &wc,
-			     status != IB_WC_SUCCESS);
-	}
+	rvt_qp_swqe_complete(qp, wqe, status);
 
 	if (qp->s_acked == old_last)
 		qp->s_acked = last;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/qib/qib_verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/qib/qib_verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,19 +114,6 @@ module_param_named(disable_sma, ib_qib_d
 MODULE_PARM_DESC(disable_sma, "Disable the SMA");
 
 /*
- * Translate ib_wr_opcode into ib_wc_opcode.
- */
-const enum ib_wc_opcode ib_qib_wc_opcode[] = {
-	[IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE,
-	[IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE,
-	[IB_WR_SEND] = IB_WC_SEND,
-	[IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
-	[IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
-	[IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
-	[IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD
-};
-
-/*
  * System image GUID.
  */
 __be64 ib_qib_sys_image_guid;
@@ -464,7 +451,7 @@ static void mem_timer(unsigned long data
 		priv = list_entry(list->next, struct qib_qp_priv, iowait);
 		qp = priv->owner;
 		list_del_init(&priv->iowait);
-		atomic_inc(&qp->refcount);
+		rvt_get_qp(qp);
 		if (!list_empty(list))
 			mod_timer(&dev->mem_timer, jiffies + 1);
 	}
@@ -477,8 +464,7 @@ static void mem_timer(unsigned long data
 			qib_schedule_send(qp);
 		}
 		spin_unlock_irqrestore(&qp->s_lock, flags);
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
+		rvt_put_qp(qp);
 	}
 }
 
@@ -762,7 +748,7 @@ void qib_put_txreq(struct qib_verbs_txre
 				  iowait);
 		qp = priv->owner;
 		list_del_init(&priv->iowait);
-		atomic_inc(&qp->refcount);
+		rvt_get_qp(qp);
 		spin_unlock_irqrestore(&dev->rdi.pending_lock, flags);
 
 		spin_lock_irqsave(&qp->s_lock, flags);
@@ -772,8 +758,7 @@ void qib_put_txreq(struct qib_verbs_txre
 		}
 		spin_unlock_irqrestore(&qp->s_lock, flags);
 
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
+		rvt_put_qp(qp);
 	} else
 		spin_unlock_irqrestore(&dev->rdi.pending_lock, flags);
 }
@@ -808,7 +793,7 @@ void qib_verbs_sdma_desc_avail(struct qi
 			break;
 		avail -= qpp->s_tx->txreq.sg_count;
 		list_del_init(&qpp->iowait);
-		atomic_inc(&qp->refcount);
+		rvt_get_qp(qp);
 		qps[n++] = qp;
 	}
 
@@ -822,8 +807,7 @@ void qib_verbs_sdma_desc_avail(struct qi
 			qib_schedule_send(qp);
 		}
 		spin_unlock(&qp->s_lock);
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
+		rvt_put_qp(qp);
 	}
 }
 
@@ -1288,7 +1272,7 @@ void qib_ib_piobufavail(struct qib_devda
 		priv = list_entry(list->next, struct qib_qp_priv, iowait);
 		qp = priv->owner;
 		list_del_init(&priv->iowait);
-		atomic_inc(&qp->refcount);
+		rvt_get_qp(qp);
 		qps[n++] = qp;
 	}
 	dd->f_wantpiobuf_intr(dd, 0);
@@ -1306,8 +1290,7 @@ full:
 		spin_unlock_irqrestore(&qp->s_lock, flags);
 
 		/* Notify qib_destroy_qp() if it is waiting. */
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
+		rvt_put_qp(qp);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c	2017-02-12 16:03:20.000000000 -0500
@@ -117,10 +117,10 @@ static int enable_qp_grp(struct usnic_ib
 	vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
 
 	res_chunk = get_qp_res_chunk(qp_grp);
-	if (IS_ERR_OR_NULL(res_chunk)) {
+	if (IS_ERR(res_chunk)) {
 		usnic_err("Unable to get qp res with err %ld\n",
 				PTR_ERR(res_chunk));
-		return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
+		return PTR_ERR(res_chunk);
 	}
 
 	for (i = 0; i < res_chunk->cnt; i++) {
@@ -158,10 +158,10 @@ static int disable_qp_grp(struct usnic_i
 	vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
 
 	res_chunk = get_qp_res_chunk(qp_grp);
-	if (IS_ERR_OR_NULL(res_chunk)) {
+	if (IS_ERR(res_chunk)) {
 		usnic_err("Unable to get qp res with err %ld\n",
 			PTR_ERR(res_chunk));
-		return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
+		return PTR_ERR(res_chunk);
 	}
 
 	for (i = 0; i < res_chunk->cnt; i++) {
@@ -186,11 +186,11 @@ static int init_filter_action(struct usn
 	struct usnic_vnic_res_chunk *res_chunk;
 
 	res_chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
-	if (IS_ERR_OR_NULL(res_chunk)) {
+	if (IS_ERR(res_chunk)) {
 		usnic_err("Unable to get %s with err %ld\n",
 			usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ),
 			PTR_ERR(res_chunk));
-		return res_chunk ? PTR_ERR(res_chunk) : -ENOMEM;
+		return PTR_ERR(res_chunk);
 	}
 
 	uaction->vnic_idx = usnic_vnic_get_index(qp_grp->vf->vnic);
@@ -228,8 +228,6 @@ create_roce_custom_flow(struct usnic_ib_
 
 	flow = usnic_fwd_alloc_flow(qp_grp->ufdev, &filter, &uaction);
 	if (IS_ERR_OR_NULL(flow)) {
-		usnic_err("Unable to alloc flow failed with err %ld\n",
-				PTR_ERR(flow));
 		err = flow ? PTR_ERR(flow) : -EFAULT;
 		goto out_unreserve_port;
 	}
@@ -303,8 +301,6 @@ create_udp_flow(struct usnic_ib_qp_grp *
 
 	flow = usnic_fwd_alloc_flow(qp_grp->ufdev, &filter, &uaction);
 	if (IS_ERR_OR_NULL(flow)) {
-		usnic_err("Unable to alloc flow failed with err %ld\n",
-				PTR_ERR(flow));
 		err = flow ? PTR_ERR(flow) : -EFAULT;
 		goto out_put_sock;
 	}
@@ -694,18 +690,14 @@ usnic_ib_qp_grp_create(struct usnic_fwd_
 	}
 
 	qp_grp = kzalloc(sizeof(*qp_grp), GFP_ATOMIC);
-	if (!qp_grp) {
-		usnic_err("Unable to alloc qp_grp - Out of memory\n");
+	if (!qp_grp)
 		return NULL;
-	}
 
 	qp_grp->res_chunk_list = alloc_res_chunk_list(vf->vnic, res_spec,
 							qp_grp);
 	if (IS_ERR_OR_NULL(qp_grp->res_chunk_list)) {
 		err = qp_grp->res_chunk_list ?
 				PTR_ERR(qp_grp->res_chunk_list) : -ENOMEM;
-		usnic_err("Unable to alloc res for %d with err %d\n",
-				qp_grp->grp_id, err);
 		goto out_free_qp_grp;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,12 +87,12 @@ static int usnic_ib_fill_create_qp_resp(
 	resp.bar_len = bar->len;
 
 	chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_RQ);
-	if (IS_ERR_OR_NULL(chunk)) {
+	if (IS_ERR(chunk)) {
 		usnic_err("Failed to get chunk %s for qp_grp %d with err %ld\n",
 			usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_RQ),
 			qp_grp->grp_id,
 			PTR_ERR(chunk));
-		return chunk ? PTR_ERR(chunk) : -ENOMEM;
+		return PTR_ERR(chunk);
 	}
 
 	WARN_ON(chunk->type != USNIC_VNIC_RES_TYPE_RQ);
@@ -101,12 +101,12 @@ static int usnic_ib_fill_create_qp_resp(
 		resp.rq_idx[i] = chunk->res[i]->vnic_idx;
 
 	chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_WQ);
-	if (IS_ERR_OR_NULL(chunk)) {
+	if (IS_ERR(chunk)) {
 		usnic_err("Failed to get chunk %s for qp_grp %d with err %ld\n",
 			usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_WQ),
 			qp_grp->grp_id,
 			PTR_ERR(chunk));
-		return chunk ? PTR_ERR(chunk) : -ENOMEM;
+		return PTR_ERR(chunk);
 	}
 
 	WARN_ON(chunk->type != USNIC_VNIC_RES_TYPE_WQ);
@@ -115,12 +115,12 @@ static int usnic_ib_fill_create_qp_resp(
 		resp.wq_idx[i] = chunk->res[i]->vnic_idx;
 
 	chunk = usnic_ib_qp_grp_get_chunk(qp_grp, USNIC_VNIC_RES_TYPE_CQ);
-	if (IS_ERR_OR_NULL(chunk)) {
+	if (IS_ERR(chunk)) {
 		usnic_err("Failed to get chunk %s for qp_grp %d with err %ld\n",
 			usnic_vnic_res_type_to_str(USNIC_VNIC_RES_TYPE_CQ),
 			qp_grp->grp_id,
 			PTR_ERR(chunk));
-		return chunk ? PTR_ERR(chunk) : -ENOMEM;
+		return PTR_ERR(chunk);
 	}
 
 	WARN_ON(chunk->type != USNIC_VNIC_RES_TYPE_CQ);
@@ -738,7 +738,9 @@ int usnic_ib_mmap(struct ib_ucontext *co
 
 /* In ib callbacks section -  Start of stub funcs */
 struct ib_ah *usnic_ib_create_ah(struct ib_pd *pd,
-					struct ib_ah_attr *ah_attr)
+				 struct ib_ah_attr *ah_attr,
+				 struct ib_udata *udata)
+
 {
 	usnic_dbg("\n");
 	return ERR_PTR(-EPERM);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_ib_verbs.h	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,9 @@ int usnic_ib_dealloc_ucontext(struct ib_
 int usnic_ib_mmap(struct ib_ucontext *context,
 			struct vm_area_struct *vma);
 struct ib_ah *usnic_ib_create_ah(struct ib_pd *pd,
-					struct ib_ah_attr *ah_attr);
+				 struct ib_ah_attr *ah_attr,
+				 struct ib_udata *udata);
+
 int usnic_ib_destroy_ah(struct ib_ah *ah);
 int usnic_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 			struct ib_send_wr **bad_wr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_vnic.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_vnic.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/usnic/usnic_vnic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/usnic/usnic_vnic.c	2017-02-12 16:03:20.000000000 -0500
@@ -241,17 +241,12 @@ usnic_vnic_get_resources(struct usnic_vn
 		return ERR_PTR(-EINVAL);
 
 	ret = kzalloc(sizeof(*ret), GFP_ATOMIC);
-	if (!ret) {
-		usnic_err("Failed to allocate chunk for %s - Out of memory\n",
-				usnic_vnic_pci_name(vnic));
+	if (!ret)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	if (cnt > 0) {
 		ret->res = kcalloc(cnt, sizeof(*(ret->res)), GFP_ATOMIC);
 		if (!ret->res) {
-			usnic_err("Failed to allocate resources for %s. Out of memory\n",
-					usnic_vnic_pci_name(vnic));
 			kfree(ret);
 			return ERR_PTR(-ENOMEM);
 		}
@@ -311,8 +306,10 @@ static int usnic_vnic_alloc_res_chunk(st
 	struct usnic_vnic_res *res;
 
 	cnt = vnic_dev_get_res_count(vnic->vdev, _to_vnic_res_type(type));
-	if (cnt < 1)
+	if (cnt < 1) {
+		usnic_err("Wrong res count with cnt %d\n", cnt);
 		return -EINVAL;
+	}
 
 	chunk->cnt = chunk->free_cnt = cnt;
 	chunk->res = kzalloc(sizeof(*(chunk->res))*cnt, GFP_KERNEL);
@@ -384,12 +381,8 @@ static int usnic_vnic_discover_resources
 			res_type < USNIC_VNIC_RES_TYPE_MAX; res_type++) {
 		err = usnic_vnic_alloc_res_chunk(vnic, res_type,
 						&vnic->chunks[res_type]);
-		if (err) {
-			usnic_err("Failed to alloc res %s with err %d\n",
-					usnic_vnic_res_type_to_str(res_type),
-					err);
+		if (err)
 			goto out_clean_chunks;
-		}
 	}
 
 	return 0;
@@ -454,11 +447,8 @@ struct usnic_vnic *usnic_vnic_alloc(stru
 	}
 
 	vnic = kzalloc(sizeof(*vnic), GFP_KERNEL);
-	if (!vnic) {
-		usnic_err("Failed to alloc vnic for %s - out of memory\n",
-				pci_name(pdev));
+	if (!vnic)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	spin_lock_init(&vnic->res_lock);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/Kconfig linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/Kconfig
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,7 @@
+config INFINIBAND_VMWARE_PVRDMA
+	tristate "VMware Paravirtualized RDMA Driver"
+	depends on NETDEVICES && ETHERNET && PCI && INET && VMXNET3
+	---help---
+	  This driver provides low-level support for VMware Paravirtual
+	  RDMA adapter. It interacts with the VMXNet3 driver to provide
+	  Ethernet capabilities.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/Makefile linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/Makefile
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3 @@
+obj-$(CONFIG_INFINIBAND_VMWARE_PVRDMA) += vmw_pvrdma.o
+
+vmw_pvrdma-y := pvrdma_cmd.o pvrdma_cq.o pvrdma_doorbell.o pvrdma_main.o pvrdma_misc.o pvrdma_mr.o pvrdma_qp.o pvrdma_verbs.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cmd.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cmd.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cmd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/list.h>
+
+#include "pvrdma.h"
+
+#define PVRDMA_CMD_TIMEOUT	10000 /* ms */
+
+static inline int pvrdma_cmd_recv(struct pvrdma_dev *dev,
+				  union pvrdma_cmd_resp *resp,
+				  unsigned resp_code)
+{
+	int err;
+
+	dev_dbg(&dev->pdev->dev, "receive response from device\n");
+
+	err = wait_for_completion_interruptible_timeout(&dev->cmd_done,
+			msecs_to_jiffies(PVRDMA_CMD_TIMEOUT));
+	if (err == 0 || err == -ERESTARTSYS) {
+		dev_warn(&dev->pdev->dev,
+			 "completion timeout or interrupted\n");
+		return -ETIMEDOUT;
+	}
+
+	spin_lock(&dev->cmd_lock);
+	memcpy(resp, dev->resp_slot, sizeof(*resp));
+	spin_unlock(&dev->cmd_lock);
+
+	if (resp->hdr.ack != resp_code) {
+		dev_warn(&dev->pdev->dev,
+			 "unknown response %#x expected %#x\n",
+			 resp->hdr.ack, resp_code);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+int
+pvrdma_cmd_post(struct pvrdma_dev *dev, union pvrdma_cmd_req *req,
+		union pvrdma_cmd_resp *resp, unsigned resp_code)
+{
+	int err;
+
+	dev_dbg(&dev->pdev->dev, "post request to device\n");
+
+	/* Serializiation */
+	down(&dev->cmd_sema);
+
+	BUILD_BUG_ON(sizeof(union pvrdma_cmd_req) !=
+		     sizeof(struct pvrdma_cmd_modify_qp));
+
+	spin_lock(&dev->cmd_lock);
+	memcpy(dev->cmd_slot, req, sizeof(*req));
+	spin_unlock(&dev->cmd_lock);
+
+	init_completion(&dev->cmd_done);
+	pvrdma_write_reg(dev, PVRDMA_REG_REQUEST, 0);
+
+	/* Make sure the request is written before reading status. */
+	mb();
+
+	err = pvrdma_read_reg(dev, PVRDMA_REG_ERR);
+	if (err == 0) {
+		if (resp != NULL)
+			err = pvrdma_cmd_recv(dev, resp, resp_code);
+	} else {
+		dev_warn(&dev->pdev->dev,
+			 "failed to write request error reg: %d\n", err);
+		err = -EFAULT;
+	}
+
+	up(&dev->cmd_sema);
+
+	return err;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/page.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <rdma/ib_addr.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
+
+#include "pvrdma.h"
+
+/**
+ * pvrdma_req_notify_cq - request notification for a completion queue
+ * @ibcq: the completion queue
+ * @notify_flags: notification flags
+ *
+ * @return: 0 for success.
+ */
+int pvrdma_req_notify_cq(struct ib_cq *ibcq,
+			 enum ib_cq_notify_flags notify_flags)
+{
+	struct pvrdma_dev *dev = to_vdev(ibcq->device);
+	struct pvrdma_cq *cq = to_vcq(ibcq);
+	u32 val = cq->cq_handle;
+
+	val |= (notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED ?
+		PVRDMA_UAR_CQ_ARM_SOL : PVRDMA_UAR_CQ_ARM;
+
+	pvrdma_write_uar_cq(dev, val);
+
+	return 0;
+}
+
+/**
+ * pvrdma_create_cq - create completion queue
+ * @ibdev: the device
+ * @attr: completion queue attributes
+ * @context: user context
+ * @udata: user data
+ *
+ * @return: ib_cq completion queue pointer on success,
+ *          otherwise returns negative errno.
+ */
+struct ib_cq *pvrdma_create_cq(struct ib_device *ibdev,
+			       const struct ib_cq_init_attr *attr,
+			       struct ib_ucontext *context,
+			       struct ib_udata *udata)
+{
+	int entries = attr->cqe;
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+	struct pvrdma_cq *cq;
+	int ret;
+	int npages;
+	unsigned long flags;
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_create_cq *cmd = &req.create_cq;
+	struct pvrdma_cmd_create_cq_resp *resp = &rsp.create_cq_resp;
+	struct pvrdma_create_cq ucmd;
+
+	BUILD_BUG_ON(sizeof(struct pvrdma_cqe) != 64);
+
+	entries = roundup_pow_of_two(entries);
+	if (entries < 1 || entries > dev->dsr->caps.max_cqe)
+		return ERR_PTR(-EINVAL);
+
+	if (!atomic_add_unless(&dev->num_cqs, 1, dev->dsr->caps.max_cq))
+		return ERR_PTR(-ENOMEM);
+
+	cq = kzalloc(sizeof(*cq), GFP_KERNEL);
+	if (!cq) {
+		atomic_dec(&dev->num_cqs);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	cq->ibcq.cqe = entries;
+
+	if (context) {
+		if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) {
+			ret = -EFAULT;
+			goto err_cq;
+		}
+
+		cq->umem = ib_umem_get(context, ucmd.buf_addr, ucmd.buf_size,
+				       IB_ACCESS_LOCAL_WRITE, 1);
+		if (IS_ERR(cq->umem)) {
+			ret = PTR_ERR(cq->umem);
+			goto err_cq;
+		}
+
+		npages = ib_umem_page_count(cq->umem);
+	} else {
+		cq->is_kernel = true;
+
+		/* One extra page for shared ring state */
+		npages = 1 + (entries * sizeof(struct pvrdma_cqe) +
+			      PAGE_SIZE - 1) / PAGE_SIZE;
+
+		/* Skip header page. */
+		cq->offset = PAGE_SIZE;
+	}
+
+	if (npages < 0 || npages > PVRDMA_PAGE_DIR_MAX_PAGES) {
+		dev_warn(&dev->pdev->dev,
+			 "overflow pages in completion queue\n");
+		ret = -EINVAL;
+		goto err_umem;
+	}
+
+	ret = pvrdma_page_dir_init(dev, &cq->pdir, npages, cq->is_kernel);
+	if (ret) {
+		dev_warn(&dev->pdev->dev,
+			 "could not allocate page directory\n");
+		goto err_umem;
+	}
+
+	/* Ring state is always the first page. Set in library for user cq. */
+	if (cq->is_kernel)
+		cq->ring_state = cq->pdir.pages[0];
+	else
+		pvrdma_page_dir_insert_umem(&cq->pdir, cq->umem, 0);
+
+	atomic_set(&cq->refcnt, 1);
+	init_waitqueue_head(&cq->wait);
+	spin_lock_init(&cq->cq_lock);
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_CREATE_CQ;
+	cmd->nchunks = npages;
+	cmd->ctx_handle = (context) ?
+		(u64)to_vucontext(context)->ctx_handle : 0;
+	cmd->cqe = entries;
+	cmd->pdir_dma = cq->pdir.dir_dma;
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_CQ_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not create completion queue, error: %d\n", ret);
+		goto err_page_dir;
+	}
+
+	cq->ibcq.cqe = resp->cqe;
+	cq->cq_handle = resp->cq_handle;
+	spin_lock_irqsave(&dev->cq_tbl_lock, flags);
+	dev->cq_tbl[cq->cq_handle % dev->dsr->caps.max_cq] = cq;
+	spin_unlock_irqrestore(&dev->cq_tbl_lock, flags);
+
+	if (context) {
+		cq->uar = &(to_vucontext(context)->uar);
+
+		/* Copy udata back. */
+		if (ib_copy_to_udata(udata, &cq->cq_handle, sizeof(__u32))) {
+			dev_warn(&dev->pdev->dev,
+				 "failed to copy back udata\n");
+			pvrdma_destroy_cq(&cq->ibcq);
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	return &cq->ibcq;
+
+err_page_dir:
+	pvrdma_page_dir_cleanup(dev, &cq->pdir);
+err_umem:
+	if (context)
+		ib_umem_release(cq->umem);
+err_cq:
+	atomic_dec(&dev->num_cqs);
+	kfree(cq);
+
+	return ERR_PTR(ret);
+}
+
+static void pvrdma_free_cq(struct pvrdma_dev *dev, struct pvrdma_cq *cq)
+{
+	atomic_dec(&cq->refcnt);
+	wait_event(cq->wait, !atomic_read(&cq->refcnt));
+
+	if (!cq->is_kernel)
+		ib_umem_release(cq->umem);
+
+	pvrdma_page_dir_cleanup(dev, &cq->pdir);
+	kfree(cq);
+}
+
+/**
+ * pvrdma_destroy_cq - destroy completion queue
+ * @cq: the completion queue to destroy.
+ *
+ * @return: 0 for success.
+ */
+int pvrdma_destroy_cq(struct ib_cq *cq)
+{
+	struct pvrdma_cq *vcq = to_vcq(cq);
+	union pvrdma_cmd_req req;
+	struct pvrdma_cmd_destroy_cq *cmd = &req.destroy_cq;
+	struct pvrdma_dev *dev = to_vdev(cq->device);
+	unsigned long flags;
+	int ret;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_DESTROY_CQ;
+	cmd->cq_handle = vcq->cq_handle;
+
+	ret = pvrdma_cmd_post(dev, &req, NULL, 0);
+	if (ret < 0)
+		dev_warn(&dev->pdev->dev,
+			 "could not destroy completion queue, error: %d\n",
+			 ret);
+
+	/* free cq's resources */
+	spin_lock_irqsave(&dev->cq_tbl_lock, flags);
+	dev->cq_tbl[vcq->cq_handle] = NULL;
+	spin_unlock_irqrestore(&dev->cq_tbl_lock, flags);
+
+	pvrdma_free_cq(dev, vcq);
+	atomic_dec(&dev->num_cqs);
+
+	return ret;
+}
+
+/**
+ * pvrdma_modify_cq - modify the CQ moderation parameters
+ * @ibcq: the CQ to modify
+ * @cq_count: number of CQEs that will trigger an event
+ * @cq_period: max period of time in usec before triggering an event
+ *
+ * @return: -EOPNOTSUPP as CQ resize is not supported.
+ */
+int pvrdma_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline struct pvrdma_cqe *get_cqe(struct pvrdma_cq *cq, int i)
+{
+	return (struct pvrdma_cqe *)pvrdma_page_dir_get_ptr(
+					&cq->pdir,
+					cq->offset +
+					sizeof(struct pvrdma_cqe) * i);
+}
+
+void _pvrdma_flush_cqe(struct pvrdma_qp *qp, struct pvrdma_cq *cq)
+{
+	int head;
+	int has_data;
+
+	if (!cq->is_kernel)
+		return;
+
+	/* Lock held */
+	has_data = pvrdma_idx_ring_has_data(&cq->ring_state->rx,
+					    cq->ibcq.cqe, &head);
+	if (unlikely(has_data > 0)) {
+		int items;
+		int curr;
+		int tail = pvrdma_idx(&cq->ring_state->rx.prod_tail,
+				      cq->ibcq.cqe);
+		struct pvrdma_cqe *cqe;
+		struct pvrdma_cqe *curr_cqe;
+
+		items = (tail > head) ? (tail - head) :
+			(cq->ibcq.cqe - head + tail);
+		curr = --tail;
+		while (items-- > 0) {
+			if (curr < 0)
+				curr = cq->ibcq.cqe - 1;
+			if (tail < 0)
+				tail = cq->ibcq.cqe - 1;
+			curr_cqe = get_cqe(cq, curr);
+			if ((curr_cqe->qp & 0xFFFF) != qp->qp_handle) {
+				if (curr != tail) {
+					cqe = get_cqe(cq, tail);
+					*cqe = *curr_cqe;
+				}
+				tail--;
+			} else {
+				pvrdma_idx_ring_inc(
+					&cq->ring_state->rx.cons_head,
+					cq->ibcq.cqe);
+			}
+			curr--;
+		}
+	}
+}
+
+static int pvrdma_poll_one(struct pvrdma_cq *cq, struct pvrdma_qp **cur_qp,
+			   struct ib_wc *wc)
+{
+	struct pvrdma_dev *dev = to_vdev(cq->ibcq.device);
+	int has_data;
+	unsigned int head;
+	bool tried = false;
+	struct pvrdma_cqe *cqe;
+
+retry:
+	has_data = pvrdma_idx_ring_has_data(&cq->ring_state->rx,
+					    cq->ibcq.cqe, &head);
+	if (has_data == 0) {
+		if (tried)
+			return -EAGAIN;
+
+		pvrdma_write_uar_cq(dev, cq->cq_handle | PVRDMA_UAR_CQ_POLL);
+
+		tried = true;
+		goto retry;
+	} else if (has_data == PVRDMA_INVALID_IDX) {
+		dev_err(&dev->pdev->dev, "CQ ring state invalid\n");
+		return -EAGAIN;
+	}
+
+	cqe = get_cqe(cq, head);
+
+	/* Ensure cqe is valid. */
+	rmb();
+	if (dev->qp_tbl[cqe->qp & 0xffff])
+		*cur_qp = (struct pvrdma_qp *)dev->qp_tbl[cqe->qp & 0xffff];
+	else
+		return -EAGAIN;
+
+	wc->opcode = pvrdma_wc_opcode_to_ib(cqe->opcode);
+	wc->status = pvrdma_wc_status_to_ib(cqe->status);
+	wc->wr_id = cqe->wr_id;
+	wc->qp = &(*cur_qp)->ibqp;
+	wc->byte_len = cqe->byte_len;
+	wc->ex.imm_data = cqe->imm_data;
+	wc->src_qp = cqe->src_qp;
+	wc->wc_flags = pvrdma_wc_flags_to_ib(cqe->wc_flags);
+	wc->pkey_index = cqe->pkey_index;
+	wc->slid = cqe->slid;
+	wc->sl = cqe->sl;
+	wc->dlid_path_bits = cqe->dlid_path_bits;
+	wc->port_num = cqe->port_num;
+	wc->vendor_err = 0;
+
+	/* Update shared ring state */
+	pvrdma_idx_ring_inc(&cq->ring_state->rx.cons_head, cq->ibcq.cqe);
+
+	return 0;
+}
+
+/**
+ * pvrdma_poll_cq - poll for work completion queue entries
+ * @ibcq: completion queue
+ * @num_entries: the maximum number of entries
+ * @entry: pointer to work completion array
+ *
+ * @return: number of polled completion entries
+ */
+int pvrdma_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
+{
+	struct pvrdma_cq *cq = to_vcq(ibcq);
+	struct pvrdma_qp *cur_qp = NULL;
+	unsigned long flags;
+	int npolled;
+
+	if (num_entries < 1 || wc == NULL)
+		return 0;
+
+	spin_lock_irqsave(&cq->cq_lock, flags);
+	for (npolled = 0; npolled < num_entries; ++npolled) {
+		if (pvrdma_poll_one(cq, &cur_qp, wc + npolled))
+			break;
+	}
+
+	spin_unlock_irqrestore(&cq->cq_lock, flags);
+
+	/* Ensure we do not return errors from poll_cq */
+	return npolled;
+}
+
+/**
+ * pvrdma_resize_cq - resize CQ
+ * @ibcq: the completion queue
+ * @entries: CQ entries
+ * @udata: user data
+ *
+ * @return: -EOPNOTSUPP as CQ resize is not supported.
+ */
+int pvrdma_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
+{
+	return -EOPNOTSUPP;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_dev_api.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,586 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PVRDMA_DEV_API_H__
+#define __PVRDMA_DEV_API_H__
+
+#include <linux/types.h>
+
+#include "pvrdma_verbs.h"
+
+#define PVRDMA_VERSION			17
+#define PVRDMA_BOARD_ID			1
+#define PVRDMA_REV_ID			1
+
+/*
+ * Masks and accessors for page directory, which is a two-level lookup:
+ * page directory -> page table -> page. Only one directory for now, but we
+ * could expand that easily. 9 bits for tables, 9 bits for pages, gives one
+ * gigabyte for memory regions and so forth.
+ */
+
+#define PVRDMA_PDIR_SHIFT		18
+#define PVRDMA_PTABLE_SHIFT		9
+#define PVRDMA_PAGE_DIR_DIR(x)		(((x) >> PVRDMA_PDIR_SHIFT) & 0x1)
+#define PVRDMA_PAGE_DIR_TABLE(x)	(((x) >> PVRDMA_PTABLE_SHIFT) & 0x1ff)
+#define PVRDMA_PAGE_DIR_PAGE(x)		((x) & 0x1ff)
+#define PVRDMA_PAGE_DIR_MAX_PAGES	(1 * 512 * 512)
+#define PVRDMA_MAX_FAST_REG_PAGES	128
+
+/*
+ * Max MSI-X vectors.
+ */
+
+#define PVRDMA_MAX_INTERRUPTS	3
+
+/* Register offsets within PCI resource on BAR1. */
+#define PVRDMA_REG_VERSION	0x00	/* R: Version of device. */
+#define PVRDMA_REG_DSRLOW	0x04	/* W: Device shared region low PA. */
+#define PVRDMA_REG_DSRHIGH	0x08	/* W: Device shared region high PA. */
+#define PVRDMA_REG_CTL		0x0c	/* W: PVRDMA_DEVICE_CTL */
+#define PVRDMA_REG_REQUEST	0x10	/* W: Indicate device request. */
+#define PVRDMA_REG_ERR		0x14	/* R: Device error. */
+#define PVRDMA_REG_ICR		0x18	/* R: Interrupt cause. */
+#define PVRDMA_REG_IMR		0x1c	/* R/W: Interrupt mask. */
+#define PVRDMA_REG_MACL		0x20	/* R/W: MAC address low. */
+#define PVRDMA_REG_MACH		0x24	/* R/W: MAC address high. */
+
+/* Object flags. */
+#define PVRDMA_CQ_FLAG_ARMED_SOL	BIT(0)	/* Armed for solicited-only. */
+#define PVRDMA_CQ_FLAG_ARMED		BIT(1)	/* Armed. */
+#define PVRDMA_MR_FLAG_DMA		BIT(0)	/* DMA region. */
+#define PVRDMA_MR_FLAG_FRMR		BIT(1)	/* Fast reg memory region. */
+
+/*
+ * Atomic operation capability (masked versions are extended atomic
+ * operations.
+ */
+
+#define PVRDMA_ATOMIC_OP_COMP_SWAP	BIT(0)	/* Compare and swap. */
+#define PVRDMA_ATOMIC_OP_FETCH_ADD	BIT(1)	/* Fetch and add. */
+#define PVRDMA_ATOMIC_OP_MASK_COMP_SWAP	BIT(2)	/* Masked compare and swap. */
+#define PVRDMA_ATOMIC_OP_MASK_FETCH_ADD	BIT(3)	/* Masked fetch and add. */
+
+/*
+ * Base Memory Management Extension flags to support Fast Reg Memory Regions
+ * and Fast Reg Work Requests. Each flag represents a verb operation and we
+ * must support all of them to qualify for the BMME device cap.
+ */
+
+#define PVRDMA_BMME_FLAG_LOCAL_INV	BIT(0)	/* Local Invalidate. */
+#define PVRDMA_BMME_FLAG_REMOTE_INV	BIT(1)	/* Remote Invalidate. */
+#define PVRDMA_BMME_FLAG_FAST_REG_WR	BIT(2)	/* Fast Reg Work Request. */
+
+/*
+ * GID types. The interpretation of the gid_types bit field in the device
+ * capabilities will depend on the device mode. For now, the device only
+ * supports RoCE as mode, so only the different GID types for RoCE are
+ * defined.
+ */
+
+#define PVRDMA_GID_TYPE_FLAG_ROCE_V1	BIT(0)
+#define PVRDMA_GID_TYPE_FLAG_ROCE_V2	BIT(1)
+
+enum pvrdma_pci_resource {
+	PVRDMA_PCI_RESOURCE_MSIX,	/* BAR0: MSI-X, MMIO. */
+	PVRDMA_PCI_RESOURCE_REG,	/* BAR1: Registers, MMIO. */
+	PVRDMA_PCI_RESOURCE_UAR,	/* BAR2: UAR pages, MMIO, 64-bit. */
+	PVRDMA_PCI_RESOURCE_LAST,	/* Last. */
+};
+
+enum pvrdma_device_ctl {
+	PVRDMA_DEVICE_CTL_ACTIVATE,	/* Activate device. */
+	PVRDMA_DEVICE_CTL_QUIESCE,	/* Quiesce device. */
+	PVRDMA_DEVICE_CTL_RESET,	/* Reset device. */
+};
+
+enum pvrdma_intr_vector {
+	PVRDMA_INTR_VECTOR_RESPONSE,	/* Command response. */
+	PVRDMA_INTR_VECTOR_ASYNC,	/* Async events. */
+	PVRDMA_INTR_VECTOR_CQ,		/* CQ notification. */
+	/* Additional CQ notification vectors. */
+};
+
+enum pvrdma_intr_cause {
+	PVRDMA_INTR_CAUSE_RESPONSE	= (1 << PVRDMA_INTR_VECTOR_RESPONSE),
+	PVRDMA_INTR_CAUSE_ASYNC		= (1 << PVRDMA_INTR_VECTOR_ASYNC),
+	PVRDMA_INTR_CAUSE_CQ		= (1 << PVRDMA_INTR_VECTOR_CQ),
+};
+
+enum pvrdma_intr_type {
+	PVRDMA_INTR_TYPE_INTX,		/* Legacy. */
+	PVRDMA_INTR_TYPE_MSI,		/* MSI. */
+	PVRDMA_INTR_TYPE_MSIX,		/* MSI-X. */
+};
+
+enum pvrdma_gos_bits {
+	PVRDMA_GOS_BITS_UNK,		/* Unknown. */
+	PVRDMA_GOS_BITS_32,		/* 32-bit. */
+	PVRDMA_GOS_BITS_64,		/* 64-bit. */
+};
+
+enum pvrdma_gos_type {
+	PVRDMA_GOS_TYPE_UNK,		/* Unknown. */
+	PVRDMA_GOS_TYPE_LINUX,		/* Linux. */
+};
+
+enum pvrdma_device_mode {
+	PVRDMA_DEVICE_MODE_ROCE,	/* RoCE. */
+	PVRDMA_DEVICE_MODE_IWARP,	/* iWarp. */
+	PVRDMA_DEVICE_MODE_IB,		/* InfiniBand. */
+};
+
+struct pvrdma_gos_info {
+	u32 gos_bits:2;			/* W: PVRDMA_GOS_BITS_ */
+	u32 gos_type:4;			/* W: PVRDMA_GOS_TYPE_ */
+	u32 gos_ver:16;			/* W: Guest OS version. */
+	u32 gos_misc:10;		/* W: Other. */
+	u32 pad;			/* Pad to 8-byte alignment. */
+};
+
+struct pvrdma_device_caps {
+	u64 fw_ver;				/* R: Query device. */
+	__be64 node_guid;
+	__be64 sys_image_guid;
+	u64 max_mr_size;
+	u64 page_size_cap;
+	u64 atomic_arg_sizes;			/* EX verbs. */
+	u32 ex_comp_mask;			/* EX verbs. */
+	u32 device_cap_flags2;			/* EX verbs. */
+	u32 max_fa_bit_boundary;		/* EX verbs. */
+	u32 log_max_atomic_inline_arg;		/* EX verbs. */
+	u32 vendor_id;
+	u32 vendor_part_id;
+	u32 hw_ver;
+	u32 max_qp;
+	u32 max_qp_wr;
+	u32 device_cap_flags;
+	u32 max_sge;
+	u32 max_sge_rd;
+	u32 max_cq;
+	u32 max_cqe;
+	u32 max_mr;
+	u32 max_pd;
+	u32 max_qp_rd_atom;
+	u32 max_ee_rd_atom;
+	u32 max_res_rd_atom;
+	u32 max_qp_init_rd_atom;
+	u32 max_ee_init_rd_atom;
+	u32 max_ee;
+	u32 max_rdd;
+	u32 max_mw;
+	u32 max_raw_ipv6_qp;
+	u32 max_raw_ethy_qp;
+	u32 max_mcast_grp;
+	u32 max_mcast_qp_attach;
+	u32 max_total_mcast_qp_attach;
+	u32 max_ah;
+	u32 max_fmr;
+	u32 max_map_per_fmr;
+	u32 max_srq;
+	u32 max_srq_wr;
+	u32 max_srq_sge;
+	u32 max_uar;
+	u32 gid_tbl_len;
+	u16 max_pkeys;
+	u8  local_ca_ack_delay;
+	u8  phys_port_cnt;
+	u8  mode;				/* PVRDMA_DEVICE_MODE_ */
+	u8  atomic_ops;				/* PVRDMA_ATOMIC_OP_* bits */
+	u8  bmme_flags;				/* FRWR Mem Mgmt Extensions */
+	u8  gid_types;				/* PVRDMA_GID_TYPE_FLAG_ */
+	u8  reserved[4];
+};
+
+struct pvrdma_ring_page_info {
+	u32 num_pages;				/* Num pages incl. header. */
+	u32 reserved;				/* Reserved. */
+	u64 pdir_dma;				/* Page directory PA. */
+};
+
+#pragma pack(push, 1)
+
+struct pvrdma_device_shared_region {
+	u32 driver_version;			/* W: Driver version. */
+	u32 pad;				/* Pad to 8-byte align. */
+	struct pvrdma_gos_info gos_info;	/* W: Guest OS information. */
+	u64 cmd_slot_dma;			/* W: Command slot address. */
+	u64 resp_slot_dma;			/* W: Response slot address. */
+	struct pvrdma_ring_page_info async_ring_pages;
+						/* W: Async ring page info. */
+	struct pvrdma_ring_page_info cq_ring_pages;
+						/* W: CQ ring page info. */
+	u32 uar_pfn;				/* W: UAR pageframe. */
+	u32 pad2;				/* Pad to 8-byte align. */
+	struct pvrdma_device_caps caps;		/* R: Device capabilities. */
+};
+
+#pragma pack(pop)
+
+/* Event types. Currently a 1:1 mapping with enum ib_event. */
+enum pvrdma_eqe_type {
+	PVRDMA_EVENT_CQ_ERR,
+	PVRDMA_EVENT_QP_FATAL,
+	PVRDMA_EVENT_QP_REQ_ERR,
+	PVRDMA_EVENT_QP_ACCESS_ERR,
+	PVRDMA_EVENT_COMM_EST,
+	PVRDMA_EVENT_SQ_DRAINED,
+	PVRDMA_EVENT_PATH_MIG,
+	PVRDMA_EVENT_PATH_MIG_ERR,
+	PVRDMA_EVENT_DEVICE_FATAL,
+	PVRDMA_EVENT_PORT_ACTIVE,
+	PVRDMA_EVENT_PORT_ERR,
+	PVRDMA_EVENT_LID_CHANGE,
+	PVRDMA_EVENT_PKEY_CHANGE,
+	PVRDMA_EVENT_SM_CHANGE,
+	PVRDMA_EVENT_SRQ_ERR,
+	PVRDMA_EVENT_SRQ_LIMIT_REACHED,
+	PVRDMA_EVENT_QP_LAST_WQE_REACHED,
+	PVRDMA_EVENT_CLIENT_REREGISTER,
+	PVRDMA_EVENT_GID_CHANGE,
+};
+
+/* Event queue element. */
+struct pvrdma_eqe {
+	u32 type;	/* Event type. */
+	u32 info;	/* Handle, other. */
+};
+
+/* CQ notification queue element. */
+struct pvrdma_cqne {
+	u32 info;	/* Handle */
+};
+
+enum {
+	PVRDMA_CMD_FIRST,
+	PVRDMA_CMD_QUERY_PORT = PVRDMA_CMD_FIRST,
+	PVRDMA_CMD_QUERY_PKEY,
+	PVRDMA_CMD_CREATE_PD,
+	PVRDMA_CMD_DESTROY_PD,
+	PVRDMA_CMD_CREATE_MR,
+	PVRDMA_CMD_DESTROY_MR,
+	PVRDMA_CMD_CREATE_CQ,
+	PVRDMA_CMD_RESIZE_CQ,
+	PVRDMA_CMD_DESTROY_CQ,
+	PVRDMA_CMD_CREATE_QP,
+	PVRDMA_CMD_MODIFY_QP,
+	PVRDMA_CMD_QUERY_QP,
+	PVRDMA_CMD_DESTROY_QP,
+	PVRDMA_CMD_CREATE_UC,
+	PVRDMA_CMD_DESTROY_UC,
+	PVRDMA_CMD_CREATE_BIND,
+	PVRDMA_CMD_DESTROY_BIND,
+	PVRDMA_CMD_MAX,
+};
+
+enum {
+	PVRDMA_CMD_FIRST_RESP = (1 << 31),
+	PVRDMA_CMD_QUERY_PORT_RESP = PVRDMA_CMD_FIRST_RESP,
+	PVRDMA_CMD_QUERY_PKEY_RESP,
+	PVRDMA_CMD_CREATE_PD_RESP,
+	PVRDMA_CMD_DESTROY_PD_RESP_NOOP,
+	PVRDMA_CMD_CREATE_MR_RESP,
+	PVRDMA_CMD_DESTROY_MR_RESP_NOOP,
+	PVRDMA_CMD_CREATE_CQ_RESP,
+	PVRDMA_CMD_RESIZE_CQ_RESP,
+	PVRDMA_CMD_DESTROY_CQ_RESP_NOOP,
+	PVRDMA_CMD_CREATE_QP_RESP,
+	PVRDMA_CMD_MODIFY_QP_RESP,
+	PVRDMA_CMD_QUERY_QP_RESP,
+	PVRDMA_CMD_DESTROY_QP_RESP,
+	PVRDMA_CMD_CREATE_UC_RESP,
+	PVRDMA_CMD_DESTROY_UC_RESP_NOOP,
+	PVRDMA_CMD_CREATE_BIND_RESP_NOOP,
+	PVRDMA_CMD_DESTROY_BIND_RESP_NOOP,
+	PVRDMA_CMD_MAX_RESP,
+};
+
+struct pvrdma_cmd_hdr {
+	u64 response;		/* Key for response lookup. */
+	u32 cmd;		/* PVRDMA_CMD_ */
+	u32 reserved;		/* Reserved. */
+};
+
+struct pvrdma_cmd_resp_hdr {
+	u64 response;		/* From cmd hdr. */
+	u32 ack;		/* PVRDMA_CMD_XXX_RESP */
+	u8 err;			/* Error. */
+	u8 reserved[3];		/* Reserved. */
+};
+
+struct pvrdma_cmd_query_port {
+	struct pvrdma_cmd_hdr hdr;
+	u8 port_num;
+	u8 reserved[7];
+};
+
+struct pvrdma_cmd_query_port_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	struct pvrdma_port_attr attrs;
+};
+
+struct pvrdma_cmd_query_pkey {
+	struct pvrdma_cmd_hdr hdr;
+	u8 port_num;
+	u8 index;
+	u8 reserved[6];
+};
+
+struct pvrdma_cmd_query_pkey_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u16 pkey;
+	u8 reserved[6];
+};
+
+struct pvrdma_cmd_create_uc {
+	struct pvrdma_cmd_hdr hdr;
+	u32 pfn; /* UAR page frame number */
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_uc_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u32 ctx_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_destroy_uc {
+	struct pvrdma_cmd_hdr hdr;
+	u32 ctx_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_pd {
+	struct pvrdma_cmd_hdr hdr;
+	u32 ctx_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_pd_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u32 pd_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_destroy_pd {
+	struct pvrdma_cmd_hdr hdr;
+	u32 pd_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_mr {
+	struct pvrdma_cmd_hdr hdr;
+	u64 start;
+	u64 length;
+	u64 pdir_dma;
+	u32 pd_handle;
+	u32 access_flags;
+	u32 flags;
+	u32 nchunks;
+};
+
+struct pvrdma_cmd_create_mr_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u32 mr_handle;
+	u32 lkey;
+	u32 rkey;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_destroy_mr {
+	struct pvrdma_cmd_hdr hdr;
+	u32 mr_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_cq {
+	struct pvrdma_cmd_hdr hdr;
+	u64 pdir_dma;
+	u32 ctx_handle;
+	u32 cqe;
+	u32 nchunks;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_cq_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u32 cq_handle;
+	u32 cqe;
+};
+
+struct pvrdma_cmd_resize_cq {
+	struct pvrdma_cmd_hdr hdr;
+	u32 cq_handle;
+	u32 cqe;
+};
+
+struct pvrdma_cmd_resize_cq_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u32 cqe;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_destroy_cq {
+	struct pvrdma_cmd_hdr hdr;
+	u32 cq_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_qp {
+	struct pvrdma_cmd_hdr hdr;
+	u64 pdir_dma;
+	u32 pd_handle;
+	u32 send_cq_handle;
+	u32 recv_cq_handle;
+	u32 srq_handle;
+	u32 max_send_wr;
+	u32 max_recv_wr;
+	u32 max_send_sge;
+	u32 max_recv_sge;
+	u32 max_inline_data;
+	u32 lkey;
+	u32 access_flags;
+	u16 total_chunks;
+	u16 send_chunks;
+	u16 max_atomic_arg;
+	u8 sq_sig_all;
+	u8 qp_type;
+	u8 is_srq;
+	u8 reserved[3];
+};
+
+struct pvrdma_cmd_create_qp_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u32 qpn;
+	u32 max_send_wr;
+	u32 max_recv_wr;
+	u32 max_send_sge;
+	u32 max_recv_sge;
+	u32 max_inline_data;
+};
+
+struct pvrdma_cmd_modify_qp {
+	struct pvrdma_cmd_hdr hdr;
+	u32 qp_handle;
+	u32 attr_mask;
+	struct pvrdma_qp_attr attrs;
+};
+
+struct pvrdma_cmd_query_qp {
+	struct pvrdma_cmd_hdr hdr;
+	u32 qp_handle;
+	u32 attr_mask;
+};
+
+struct pvrdma_cmd_query_qp_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	struct pvrdma_qp_attr attrs;
+};
+
+struct pvrdma_cmd_destroy_qp {
+	struct pvrdma_cmd_hdr hdr;
+	u32 qp_handle;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_destroy_qp_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	u32 events_reported;
+	u8 reserved[4];
+};
+
+struct pvrdma_cmd_create_bind {
+	struct pvrdma_cmd_hdr hdr;
+	u32 mtu;
+	u32 vlan;
+	u32 index;
+	u8 new_gid[16];
+	u8 gid_type;
+	u8 reserved[3];
+};
+
+struct pvrdma_cmd_destroy_bind {
+	struct pvrdma_cmd_hdr hdr;
+	u32 index;
+	u8 dest_gid[16];
+	u8 reserved[4];
+};
+
+union pvrdma_cmd_req {
+	struct pvrdma_cmd_hdr hdr;
+	struct pvrdma_cmd_query_port query_port;
+	struct pvrdma_cmd_query_pkey query_pkey;
+	struct pvrdma_cmd_create_uc create_uc;
+	struct pvrdma_cmd_destroy_uc destroy_uc;
+	struct pvrdma_cmd_create_pd create_pd;
+	struct pvrdma_cmd_destroy_pd destroy_pd;
+	struct pvrdma_cmd_create_mr create_mr;
+	struct pvrdma_cmd_destroy_mr destroy_mr;
+	struct pvrdma_cmd_create_cq create_cq;
+	struct pvrdma_cmd_resize_cq resize_cq;
+	struct pvrdma_cmd_destroy_cq destroy_cq;
+	struct pvrdma_cmd_create_qp create_qp;
+	struct pvrdma_cmd_modify_qp modify_qp;
+	struct pvrdma_cmd_query_qp query_qp;
+	struct pvrdma_cmd_destroy_qp destroy_qp;
+	struct pvrdma_cmd_create_bind create_bind;
+	struct pvrdma_cmd_destroy_bind destroy_bind;
+};
+
+union pvrdma_cmd_resp {
+	struct pvrdma_cmd_resp_hdr hdr;
+	struct pvrdma_cmd_query_port_resp query_port_resp;
+	struct pvrdma_cmd_query_pkey_resp query_pkey_resp;
+	struct pvrdma_cmd_create_uc_resp create_uc_resp;
+	struct pvrdma_cmd_create_pd_resp create_pd_resp;
+	struct pvrdma_cmd_create_mr_resp create_mr_resp;
+	struct pvrdma_cmd_create_cq_resp create_cq_resp;
+	struct pvrdma_cmd_resize_cq_resp resize_cq_resp;
+	struct pvrdma_cmd_create_qp_resp create_qp_resp;
+	struct pvrdma_cmd_query_qp_resp query_qp_resp;
+	struct pvrdma_cmd_destroy_qp_resp destroy_qp_resp;
+};
+
+#endif /* __PVRDMA_DEV_API_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_doorbell.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_doorbell.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_doorbell.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_doorbell.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/bitmap.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include "pvrdma.h"
+
+int pvrdma_uar_table_init(struct pvrdma_dev *dev)
+{
+	u32 num = dev->dsr->caps.max_uar;
+	u32 mask = num - 1;
+	struct pvrdma_id_table *tbl = &dev->uar_table.tbl;
+
+	if (!is_power_of_2(num))
+		return -EINVAL;
+
+	tbl->last = 0;
+	tbl->top = 0;
+	tbl->max = num;
+	tbl->mask = mask;
+	spin_lock_init(&tbl->lock);
+	tbl->table = kcalloc(BITS_TO_LONGS(num), sizeof(long), GFP_KERNEL);
+	if (!tbl->table)
+		return -ENOMEM;
+
+	/* 0th UAR is taken by the device. */
+	set_bit(0, tbl->table);
+
+	return 0;
+}
+
+void pvrdma_uar_table_cleanup(struct pvrdma_dev *dev)
+{
+	struct pvrdma_id_table *tbl = &dev->uar_table.tbl;
+
+	kfree(tbl->table);
+}
+
+int pvrdma_uar_alloc(struct pvrdma_dev *dev, struct pvrdma_uar_map *uar)
+{
+	struct pvrdma_id_table *tbl;
+	unsigned long flags;
+	u32 obj;
+
+	tbl = &dev->uar_table.tbl;
+
+	spin_lock_irqsave(&tbl->lock, flags);
+	obj = find_next_zero_bit(tbl->table, tbl->max, tbl->last);
+	if (obj >= tbl->max) {
+		tbl->top = (tbl->top + tbl->max) & tbl->mask;
+		obj = find_first_zero_bit(tbl->table, tbl->max);
+	}
+
+	if (obj >= tbl->max) {
+		spin_unlock_irqrestore(&tbl->lock, flags);
+		return -ENOMEM;
+	}
+
+	set_bit(obj, tbl->table);
+	obj |= tbl->top;
+
+	spin_unlock_irqrestore(&tbl->lock, flags);
+
+	uar->index = obj;
+	uar->pfn = (pci_resource_start(dev->pdev, PVRDMA_PCI_RESOURCE_UAR) >>
+		    PAGE_SHIFT) + uar->index;
+
+	return 0;
+}
+
+void pvrdma_uar_free(struct pvrdma_dev *dev, struct pvrdma_uar_map *uar)
+{
+	struct pvrdma_id_table *tbl = &dev->uar_table.tbl;
+	unsigned long flags;
+	u32 obj;
+
+	obj = uar->index & (tbl->max - 1);
+	spin_lock_irqsave(&tbl->lock, flags);
+	clear_bit(obj, tbl->table);
+	tbl->last = min(tbl->last, obj);
+	tbl->top = (tbl->top + tbl->max) & tbl->mask;
+	spin_unlock_irqrestore(&tbl->lock, flags);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PVRDMA_H__
+#define __PVRDMA_H__
+
+#include <linux/compiler.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/semaphore.h>
+#include <linux/workqueue.h>
+#include <rdma/ib_umem.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/vmw_pvrdma-abi.h>
+
+#include "pvrdma_ring.h"
+#include "pvrdma_dev_api.h"
+#include "pvrdma_verbs.h"
+
+/* NOT the same as BIT_MASK(). */
+#define PVRDMA_MASK(n) ((n << 1) - 1)
+
+/*
+ * VMware PVRDMA PCI device id.
+ */
+#define PCI_DEVICE_ID_VMWARE_PVRDMA	0x0820
+
+struct pvrdma_dev;
+
+struct pvrdma_page_dir {
+	dma_addr_t dir_dma;
+	u64 *dir;
+	int ntables;
+	u64 **tables;
+	u64 npages;
+	void **pages;
+};
+
+struct pvrdma_cq {
+	struct ib_cq ibcq;
+	int offset;
+	spinlock_t cq_lock; /* Poll lock. */
+	struct pvrdma_uar_map *uar;
+	struct ib_umem *umem;
+	struct pvrdma_ring_state *ring_state;
+	struct pvrdma_page_dir pdir;
+	u32 cq_handle;
+	bool is_kernel;
+	atomic_t refcnt;
+	wait_queue_head_t wait;
+};
+
+struct pvrdma_id_table {
+	u32 last;
+	u32 top;
+	u32 max;
+	u32 mask;
+	spinlock_t lock; /* Table lock. */
+	unsigned long *table;
+};
+
+struct pvrdma_uar_map {
+	unsigned long pfn;
+	void __iomem *map;
+	int index;
+};
+
+struct pvrdma_uar_table {
+	struct pvrdma_id_table tbl;
+	int size;
+};
+
+struct pvrdma_ucontext {
+	struct ib_ucontext ibucontext;
+	struct pvrdma_dev *dev;
+	struct pvrdma_uar_map uar;
+	u64 ctx_handle;
+};
+
+struct pvrdma_pd {
+	struct ib_pd ibpd;
+	u32 pdn;
+	u32 pd_handle;
+	int privileged;
+};
+
+struct pvrdma_mr {
+	u32 mr_handle;
+	u64 iova;
+	u64 size;
+};
+
+struct pvrdma_user_mr {
+	struct ib_mr ibmr;
+	struct ib_umem *umem;
+	struct pvrdma_mr mmr;
+	struct pvrdma_page_dir pdir;
+	u64 *pages;
+	u32 npages;
+	u32 max_pages;
+	u32 page_shift;
+};
+
+struct pvrdma_wq {
+	struct pvrdma_ring *ring;
+	spinlock_t lock; /* Work queue lock. */
+	int wqe_cnt;
+	int wqe_size;
+	int max_sg;
+	int offset;
+};
+
+struct pvrdma_ah {
+	struct ib_ah ibah;
+	struct pvrdma_av av;
+};
+
+struct pvrdma_qp {
+	struct ib_qp ibqp;
+	u32 qp_handle;
+	u32 qkey;
+	struct pvrdma_wq sq;
+	struct pvrdma_wq rq;
+	struct ib_umem *rumem;
+	struct ib_umem *sumem;
+	struct pvrdma_page_dir pdir;
+	int npages;
+	int npages_send;
+	int npages_recv;
+	u32 flags;
+	u8 port;
+	u8 state;
+	bool is_kernel;
+	struct mutex mutex; /* QP state mutex. */
+	atomic_t refcnt;
+	wait_queue_head_t wait;
+};
+
+struct pvrdma_dev {
+	/* PCI device-related information. */
+	struct ib_device ib_dev;
+	struct pci_dev *pdev;
+	void __iomem *regs;
+	struct pvrdma_device_shared_region *dsr; /* Shared region pointer */
+	dma_addr_t dsrbase; /* Shared region base address */
+	void *cmd_slot;
+	void *resp_slot;
+	unsigned long flags;
+	struct list_head device_link;
+
+	/* Locking and interrupt information. */
+	spinlock_t cmd_lock; /* Command lock. */
+	struct semaphore cmd_sema;
+	struct completion cmd_done;
+	struct {
+		enum pvrdma_intr_type type; /* Intr type */
+		struct msix_entry msix_entry[PVRDMA_MAX_INTERRUPTS];
+		irq_handler_t handler[PVRDMA_MAX_INTERRUPTS];
+		u8 enabled[PVRDMA_MAX_INTERRUPTS];
+		u8 size;
+	} intr;
+
+	/* RDMA-related device information. */
+	union ib_gid *sgid_tbl;
+	struct pvrdma_ring_state *async_ring_state;
+	struct pvrdma_page_dir async_pdir;
+	struct pvrdma_ring_state *cq_ring_state;
+	struct pvrdma_page_dir cq_pdir;
+	struct pvrdma_cq **cq_tbl;
+	spinlock_t cq_tbl_lock;
+	struct pvrdma_qp **qp_tbl;
+	spinlock_t qp_tbl_lock;
+	struct pvrdma_uar_table uar_table;
+	struct pvrdma_uar_map driver_uar;
+	__be64 sys_image_guid;
+	spinlock_t desc_lock; /* Device modification lock. */
+	u32 port_cap_mask;
+	struct mutex port_mutex; /* Port modification mutex. */
+	bool ib_active;
+	atomic_t num_qps;
+	atomic_t num_cqs;
+	atomic_t num_pds;
+	atomic_t num_ahs;
+
+	/* Network device information. */
+	struct net_device *netdev;
+	struct notifier_block nb_netdev;
+};
+
+struct pvrdma_netdevice_work {
+	struct work_struct work;
+	struct net_device *event_netdev;
+	unsigned long event;
+};
+
+static inline struct pvrdma_dev *to_vdev(struct ib_device *ibdev)
+{
+	return container_of(ibdev, struct pvrdma_dev, ib_dev);
+}
+
+static inline struct
+pvrdma_ucontext *to_vucontext(struct ib_ucontext *ibucontext)
+{
+	return container_of(ibucontext, struct pvrdma_ucontext, ibucontext);
+}
+
+static inline struct pvrdma_pd *to_vpd(struct ib_pd *ibpd)
+{
+	return container_of(ibpd, struct pvrdma_pd, ibpd);
+}
+
+static inline struct pvrdma_cq *to_vcq(struct ib_cq *ibcq)
+{
+	return container_of(ibcq, struct pvrdma_cq, ibcq);
+}
+
+static inline struct pvrdma_user_mr *to_vmr(struct ib_mr *ibmr)
+{
+	return container_of(ibmr, struct pvrdma_user_mr, ibmr);
+}
+
+static inline struct pvrdma_qp *to_vqp(struct ib_qp *ibqp)
+{
+	return container_of(ibqp, struct pvrdma_qp, ibqp);
+}
+
+static inline struct pvrdma_ah *to_vah(struct ib_ah *ibah)
+{
+	return container_of(ibah, struct pvrdma_ah, ibah);
+}
+
+static inline void pvrdma_write_reg(struct pvrdma_dev *dev, u32 reg, u32 val)
+{
+	writel(cpu_to_le32(val), dev->regs + reg);
+}
+
+static inline u32 pvrdma_read_reg(struct pvrdma_dev *dev, u32 reg)
+{
+	return le32_to_cpu(readl(dev->regs + reg));
+}
+
+static inline void pvrdma_write_uar_cq(struct pvrdma_dev *dev, u32 val)
+{
+	writel(cpu_to_le32(val), dev->driver_uar.map + PVRDMA_UAR_CQ_OFFSET);
+}
+
+static inline void pvrdma_write_uar_qp(struct pvrdma_dev *dev, u32 val)
+{
+	writel(cpu_to_le32(val), dev->driver_uar.map + PVRDMA_UAR_QP_OFFSET);
+}
+
+static inline void *pvrdma_page_dir_get_ptr(struct pvrdma_page_dir *pdir,
+					    u64 offset)
+{
+	return pdir->pages[offset / PAGE_SIZE] + (offset % PAGE_SIZE);
+}
+
+static inline enum pvrdma_mtu ib_mtu_to_pvrdma(enum ib_mtu mtu)
+{
+	return (enum pvrdma_mtu)mtu;
+}
+
+static inline enum ib_mtu pvrdma_mtu_to_ib(enum pvrdma_mtu mtu)
+{
+	return (enum ib_mtu)mtu;
+}
+
+static inline enum pvrdma_port_state ib_port_state_to_pvrdma(
+					enum ib_port_state state)
+{
+	return (enum pvrdma_port_state)state;
+}
+
+static inline enum ib_port_state pvrdma_port_state_to_ib(
+					enum pvrdma_port_state state)
+{
+	return (enum ib_port_state)state;
+}
+
+static inline int ib_port_cap_flags_to_pvrdma(int flags)
+{
+	return flags & PVRDMA_MASK(PVRDMA_PORT_CAP_FLAGS_MAX);
+}
+
+static inline int pvrdma_port_cap_flags_to_ib(int flags)
+{
+	return flags;
+}
+
+static inline enum pvrdma_port_width ib_port_width_to_pvrdma(
+					enum ib_port_width width)
+{
+	return (enum pvrdma_port_width)width;
+}
+
+static inline enum ib_port_width pvrdma_port_width_to_ib(
+					enum pvrdma_port_width width)
+{
+	return (enum ib_port_width)width;
+}
+
+static inline enum pvrdma_port_speed ib_port_speed_to_pvrdma(
+					enum ib_port_speed speed)
+{
+	return (enum pvrdma_port_speed)speed;
+}
+
+static inline enum ib_port_speed pvrdma_port_speed_to_ib(
+					enum pvrdma_port_speed speed)
+{
+	return (enum ib_port_speed)speed;
+}
+
+static inline int pvrdma_qp_attr_mask_to_ib(int attr_mask)
+{
+	return attr_mask;
+}
+
+static inline int ib_qp_attr_mask_to_pvrdma(int attr_mask)
+{
+	return attr_mask & PVRDMA_MASK(PVRDMA_QP_ATTR_MASK_MAX);
+}
+
+static inline enum pvrdma_mig_state ib_mig_state_to_pvrdma(
+					enum ib_mig_state state)
+{
+	return (enum pvrdma_mig_state)state;
+}
+
+static inline enum ib_mig_state pvrdma_mig_state_to_ib(
+					enum pvrdma_mig_state state)
+{
+	return (enum ib_mig_state)state;
+}
+
+static inline int ib_access_flags_to_pvrdma(int flags)
+{
+	return flags;
+}
+
+static inline int pvrdma_access_flags_to_ib(int flags)
+{
+	return flags & PVRDMA_MASK(PVRDMA_ACCESS_FLAGS_MAX);
+}
+
+static inline enum pvrdma_qp_type ib_qp_type_to_pvrdma(enum ib_qp_type type)
+{
+	return (enum pvrdma_qp_type)type;
+}
+
+static inline enum ib_qp_type pvrdma_qp_type_to_ib(enum pvrdma_qp_type type)
+{
+	return (enum ib_qp_type)type;
+}
+
+static inline enum pvrdma_qp_state ib_qp_state_to_pvrdma(enum ib_qp_state state)
+{
+	return (enum pvrdma_qp_state)state;
+}
+
+static inline enum ib_qp_state pvrdma_qp_state_to_ib(enum pvrdma_qp_state state)
+{
+	return (enum ib_qp_state)state;
+}
+
+static inline enum pvrdma_wr_opcode ib_wr_opcode_to_pvrdma(enum ib_wr_opcode op)
+{
+	return (enum pvrdma_wr_opcode)op;
+}
+
+static inline enum ib_wc_status pvrdma_wc_status_to_ib(
+					enum pvrdma_wc_status status)
+{
+	return (enum ib_wc_status)status;
+}
+
+static inline int pvrdma_wc_opcode_to_ib(int opcode)
+{
+	return opcode;
+}
+
+static inline int pvrdma_wc_flags_to_ib(int flags)
+{
+	return flags;
+}
+
+static inline int ib_send_flags_to_pvrdma(int flags)
+{
+	return flags & PVRDMA_MASK(PVRDMA_SEND_FLAGS_MAX);
+}
+
+void pvrdma_qp_cap_to_ib(struct ib_qp_cap *dst,
+			 const struct pvrdma_qp_cap *src);
+void ib_qp_cap_to_pvrdma(struct pvrdma_qp_cap *dst,
+			 const struct ib_qp_cap *src);
+void pvrdma_gid_to_ib(union ib_gid *dst, const union pvrdma_gid *src);
+void ib_gid_to_pvrdma(union pvrdma_gid *dst, const union ib_gid *src);
+void pvrdma_global_route_to_ib(struct ib_global_route *dst,
+			       const struct pvrdma_global_route *src);
+void ib_global_route_to_pvrdma(struct pvrdma_global_route *dst,
+			       const struct ib_global_route *src);
+void pvrdma_ah_attr_to_ib(struct ib_ah_attr *dst,
+			  const struct pvrdma_ah_attr *src);
+void ib_ah_attr_to_pvrdma(struct pvrdma_ah_attr *dst,
+			  const struct ib_ah_attr *src);
+
+int pvrdma_uar_table_init(struct pvrdma_dev *dev);
+void pvrdma_uar_table_cleanup(struct pvrdma_dev *dev);
+
+int pvrdma_uar_alloc(struct pvrdma_dev *dev, struct pvrdma_uar_map *uar);
+void pvrdma_uar_free(struct pvrdma_dev *dev, struct pvrdma_uar_map *uar);
+
+void _pvrdma_flush_cqe(struct pvrdma_qp *qp, struct pvrdma_cq *cq);
+
+int pvrdma_page_dir_init(struct pvrdma_dev *dev, struct pvrdma_page_dir *pdir,
+			 u64 npages, bool alloc_pages);
+void pvrdma_page_dir_cleanup(struct pvrdma_dev *dev,
+			     struct pvrdma_page_dir *pdir);
+int pvrdma_page_dir_insert_dma(struct pvrdma_page_dir *pdir, u64 idx,
+			       dma_addr_t daddr);
+int pvrdma_page_dir_insert_umem(struct pvrdma_page_dir *pdir,
+				struct ib_umem *umem, u64 offset);
+dma_addr_t pvrdma_page_dir_get_dma(struct pvrdma_page_dir *pdir, u64 idx);
+int pvrdma_page_dir_insert_page_list(struct pvrdma_page_dir *pdir,
+				     u64 *page_list, int num_pages);
+
+int pvrdma_cmd_post(struct pvrdma_dev *dev, union pvrdma_cmd_req *req,
+		    union pvrdma_cmd_resp *rsp, unsigned resp_code);
+
+#endif /* __PVRDMA_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1209 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/errno.h>
+#include <linux/inetdevice.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <rdma/ib_addr.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
+#include <net/addrconf.h>
+
+#include "pvrdma.h"
+
+#define DRV_NAME	"vmw_pvrdma"
+#define DRV_VERSION	"1.0.0.0-k"
+
+static DEFINE_MUTEX(pvrdma_device_list_lock);
+static LIST_HEAD(pvrdma_device_list);
+static struct workqueue_struct *event_wq;
+
+static int pvrdma_add_gid(struct ib_device *ibdev,
+			  u8 port_num,
+			  unsigned int index,
+			  const union ib_gid *gid,
+			  const struct ib_gid_attr *attr,
+			  void **context);
+static int pvrdma_del_gid(struct ib_device *ibdev,
+			  u8 port_num,
+			  unsigned int index,
+			  void **context);
+
+
+static ssize_t show_hca(struct device *device, struct device_attribute *attr,
+			char *buf)
+{
+	return sprintf(buf, "VMW_PVRDMA-%s\n", DRV_VERSION);
+}
+
+static ssize_t show_rev(struct device *device, struct device_attribute *attr,
+			char *buf)
+{
+	return sprintf(buf, "%d\n", PVRDMA_REV_ID);
+}
+
+static ssize_t show_board(struct device *device, struct device_attribute *attr,
+			  char *buf)
+{
+	return sprintf(buf, "%d\n", PVRDMA_BOARD_ID);
+}
+
+static DEVICE_ATTR(hw_rev,   S_IRUGO, show_rev,	   NULL);
+static DEVICE_ATTR(hca_type, S_IRUGO, show_hca,	   NULL);
+static DEVICE_ATTR(board_id, S_IRUGO, show_board,  NULL);
+
+static struct device_attribute *pvrdma_class_attributes[] = {
+	&dev_attr_hw_rev,
+	&dev_attr_hca_type,
+	&dev_attr_board_id
+};
+
+static void pvrdma_get_fw_ver_str(struct ib_device *device, char *str,
+				  size_t str_len)
+{
+	struct pvrdma_dev *dev =
+		container_of(device, struct pvrdma_dev, ib_dev);
+	snprintf(str, str_len, "%d.%d.%d\n",
+		 (int) (dev->dsr->caps.fw_ver >> 32),
+		 (int) (dev->dsr->caps.fw_ver >> 16) & 0xffff,
+		 (int) dev->dsr->caps.fw_ver & 0xffff);
+}
+
+static int pvrdma_init_device(struct pvrdma_dev *dev)
+{
+	/*  Initialize some device related stuff */
+	spin_lock_init(&dev->cmd_lock);
+	sema_init(&dev->cmd_sema, 1);
+	atomic_set(&dev->num_qps, 0);
+	atomic_set(&dev->num_cqs, 0);
+	atomic_set(&dev->num_pds, 0);
+	atomic_set(&dev->num_ahs, 0);
+
+	return 0;
+}
+
+static int pvrdma_port_immutable(struct ib_device *ibdev, u8 port_num,
+				 struct ib_port_immutable *immutable)
+{
+	struct ib_port_attr attr;
+	int err;
+
+	err = pvrdma_query_port(ibdev, port_num, &attr);
+	if (err)
+		return err;
+
+	immutable->pkey_tbl_len = attr.pkey_tbl_len;
+	immutable->gid_tbl_len = attr.gid_tbl_len;
+	immutable->core_cap_flags = RDMA_CORE_PORT_IBA_ROCE;
+	immutable->max_mad_size = IB_MGMT_MAD_SIZE;
+	return 0;
+}
+
+static struct net_device *pvrdma_get_netdev(struct ib_device *ibdev,
+					    u8 port_num)
+{
+	struct net_device *netdev;
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+
+	if (port_num != 1)
+		return NULL;
+
+	rcu_read_lock();
+	netdev = dev->netdev;
+	if (netdev)
+		dev_hold(netdev);
+	rcu_read_unlock();
+
+	return netdev;
+}
+
+static int pvrdma_register_device(struct pvrdma_dev *dev)
+{
+	int ret = -1;
+	int i = 0;
+
+	strlcpy(dev->ib_dev.name, "vmw_pvrdma%d", IB_DEVICE_NAME_MAX);
+	dev->ib_dev.node_guid = dev->dsr->caps.node_guid;
+	dev->sys_image_guid = dev->dsr->caps.sys_image_guid;
+	dev->flags = 0;
+	dev->ib_dev.owner = THIS_MODULE;
+	dev->ib_dev.num_comp_vectors = 1;
+	dev->ib_dev.dma_device = &dev->pdev->dev;
+	dev->ib_dev.uverbs_abi_ver = PVRDMA_UVERBS_ABI_VERSION;
+	dev->ib_dev.uverbs_cmd_mask =
+		(1ull << IB_USER_VERBS_CMD_GET_CONTEXT)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)	|
+		(1ull << IB_USER_VERBS_CMD_QUERY_PORT)		|
+		(1ull << IB_USER_VERBS_CMD_ALLOC_PD)		|
+		(1ull << IB_USER_VERBS_CMD_DEALLOC_PD)		|
+		(1ull << IB_USER_VERBS_CMD_REG_MR)		|
+		(1ull << IB_USER_VERBS_CMD_DEREG_MR)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL)	|
+		(1ull << IB_USER_VERBS_CMD_CREATE_CQ)		|
+		(1ull << IB_USER_VERBS_CMD_POLL_CQ)		|
+		(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ)	|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_CQ)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_QP)		|
+		(1ull << IB_USER_VERBS_CMD_MODIFY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_QUERY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_QP)		|
+		(1ull << IB_USER_VERBS_CMD_POST_SEND)		|
+		(1ull << IB_USER_VERBS_CMD_POST_RECV)		|
+		(1ull << IB_USER_VERBS_CMD_CREATE_AH)		|
+		(1ull << IB_USER_VERBS_CMD_DESTROY_AH);
+
+	dev->ib_dev.node_type = RDMA_NODE_IB_CA;
+	dev->ib_dev.phys_port_cnt = dev->dsr->caps.phys_port_cnt;
+
+	dev->ib_dev.query_device = pvrdma_query_device;
+	dev->ib_dev.query_port = pvrdma_query_port;
+	dev->ib_dev.query_gid = pvrdma_query_gid;
+	dev->ib_dev.query_pkey = pvrdma_query_pkey;
+	dev->ib_dev.modify_port	= pvrdma_modify_port;
+	dev->ib_dev.alloc_ucontext = pvrdma_alloc_ucontext;
+	dev->ib_dev.dealloc_ucontext = pvrdma_dealloc_ucontext;
+	dev->ib_dev.mmap = pvrdma_mmap;
+	dev->ib_dev.alloc_pd = pvrdma_alloc_pd;
+	dev->ib_dev.dealloc_pd = pvrdma_dealloc_pd;
+	dev->ib_dev.create_ah = pvrdma_create_ah;
+	dev->ib_dev.destroy_ah = pvrdma_destroy_ah;
+	dev->ib_dev.create_qp = pvrdma_create_qp;
+	dev->ib_dev.modify_qp = pvrdma_modify_qp;
+	dev->ib_dev.query_qp = pvrdma_query_qp;
+	dev->ib_dev.destroy_qp = pvrdma_destroy_qp;
+	dev->ib_dev.post_send = pvrdma_post_send;
+	dev->ib_dev.post_recv = pvrdma_post_recv;
+	dev->ib_dev.create_cq = pvrdma_create_cq;
+	dev->ib_dev.modify_cq = pvrdma_modify_cq;
+	dev->ib_dev.resize_cq = pvrdma_resize_cq;
+	dev->ib_dev.destroy_cq = pvrdma_destroy_cq;
+	dev->ib_dev.poll_cq = pvrdma_poll_cq;
+	dev->ib_dev.req_notify_cq = pvrdma_req_notify_cq;
+	dev->ib_dev.get_dma_mr = pvrdma_get_dma_mr;
+	dev->ib_dev.reg_user_mr	= pvrdma_reg_user_mr;
+	dev->ib_dev.dereg_mr = pvrdma_dereg_mr;
+	dev->ib_dev.alloc_mr = pvrdma_alloc_mr;
+	dev->ib_dev.map_mr_sg = pvrdma_map_mr_sg;
+	dev->ib_dev.add_gid = pvrdma_add_gid;
+	dev->ib_dev.del_gid = pvrdma_del_gid;
+	dev->ib_dev.get_netdev = pvrdma_get_netdev;
+	dev->ib_dev.get_port_immutable = pvrdma_port_immutable;
+	dev->ib_dev.get_link_layer = pvrdma_port_link_layer;
+	dev->ib_dev.get_dev_fw_str = pvrdma_get_fw_ver_str;
+
+	mutex_init(&dev->port_mutex);
+	spin_lock_init(&dev->desc_lock);
+
+	dev->cq_tbl = kcalloc(dev->dsr->caps.max_cq, sizeof(void *),
+			      GFP_KERNEL);
+	if (!dev->cq_tbl)
+		return ret;
+	spin_lock_init(&dev->cq_tbl_lock);
+
+	dev->qp_tbl = kcalloc(dev->dsr->caps.max_qp, sizeof(void *),
+			      GFP_KERNEL);
+	if (!dev->qp_tbl)
+		goto err_cq_free;
+	spin_lock_init(&dev->qp_tbl_lock);
+
+	ret = ib_register_device(&dev->ib_dev, NULL);
+	if (ret)
+		goto err_qp_free;
+
+	for (i = 0; i < ARRAY_SIZE(pvrdma_class_attributes); ++i) {
+		ret = device_create_file(&dev->ib_dev.dev,
+					 pvrdma_class_attributes[i]);
+		if (ret)
+			goto err_class;
+	}
+
+	dev->ib_active = true;
+
+	return 0;
+
+err_class:
+	ib_unregister_device(&dev->ib_dev);
+err_qp_free:
+	kfree(dev->qp_tbl);
+err_cq_free:
+	kfree(dev->cq_tbl);
+
+	return ret;
+}
+
+static irqreturn_t pvrdma_intr0_handler(int irq, void *dev_id)
+{
+	u32 icr = PVRDMA_INTR_CAUSE_RESPONSE;
+	struct pvrdma_dev *dev = dev_id;
+
+	dev_dbg(&dev->pdev->dev, "interrupt 0 (response) handler\n");
+
+	if (dev->intr.type != PVRDMA_INTR_TYPE_MSIX) {
+		/* Legacy intr */
+		icr = pvrdma_read_reg(dev, PVRDMA_REG_ICR);
+		if (icr == 0)
+			return IRQ_NONE;
+	}
+
+	if (icr == PVRDMA_INTR_CAUSE_RESPONSE)
+		complete(&dev->cmd_done);
+
+	return IRQ_HANDLED;
+}
+
+static void pvrdma_qp_event(struct pvrdma_dev *dev, u32 qpn, int type)
+{
+	struct pvrdma_qp *qp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->qp_tbl_lock, flags);
+	qp = dev->qp_tbl[qpn % dev->dsr->caps.max_qp];
+	if (qp)
+		atomic_inc(&qp->refcnt);
+	spin_unlock_irqrestore(&dev->qp_tbl_lock, flags);
+
+	if (qp && qp->ibqp.event_handler) {
+		struct ib_qp *ibqp = &qp->ibqp;
+		struct ib_event e;
+
+		e.device = ibqp->device;
+		e.element.qp = ibqp;
+		e.event = type; /* 1:1 mapping for now. */
+		ibqp->event_handler(&e, ibqp->qp_context);
+	}
+	if (qp) {
+		atomic_dec(&qp->refcnt);
+		if (atomic_read(&qp->refcnt) == 0)
+			wake_up(&qp->wait);
+	}
+}
+
+static void pvrdma_cq_event(struct pvrdma_dev *dev, u32 cqn, int type)
+{
+	struct pvrdma_cq *cq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->cq_tbl_lock, flags);
+	cq = dev->cq_tbl[cqn % dev->dsr->caps.max_cq];
+	if (cq)
+		atomic_inc(&cq->refcnt);
+	spin_unlock_irqrestore(&dev->cq_tbl_lock, flags);
+
+	if (cq && cq->ibcq.event_handler) {
+		struct ib_cq *ibcq = &cq->ibcq;
+		struct ib_event e;
+
+		e.device = ibcq->device;
+		e.element.cq = ibcq;
+		e.event = type; /* 1:1 mapping for now. */
+		ibcq->event_handler(&e, ibcq->cq_context);
+	}
+	if (cq) {
+		atomic_dec(&cq->refcnt);
+		if (atomic_read(&cq->refcnt) == 0)
+			wake_up(&cq->wait);
+	}
+}
+
+static void pvrdma_dispatch_event(struct pvrdma_dev *dev, int port,
+				  enum ib_event_type event)
+{
+	struct ib_event ib_event;
+
+	memset(&ib_event, 0, sizeof(ib_event));
+	ib_event.device = &dev->ib_dev;
+	ib_event.element.port_num = port;
+	ib_event.event = event;
+	ib_dispatch_event(&ib_event);
+}
+
+static void pvrdma_dev_event(struct pvrdma_dev *dev, u8 port, int type)
+{
+	if (port < 1 || port > dev->dsr->caps.phys_port_cnt) {
+		dev_warn(&dev->pdev->dev, "event on port %d\n", port);
+		return;
+	}
+
+	pvrdma_dispatch_event(dev, port, type);
+}
+
+static inline struct pvrdma_eqe *get_eqe(struct pvrdma_dev *dev, unsigned int i)
+{
+	return (struct pvrdma_eqe *)pvrdma_page_dir_get_ptr(
+					&dev->async_pdir,
+					PAGE_SIZE +
+					sizeof(struct pvrdma_eqe) * i);
+}
+
+static irqreturn_t pvrdma_intr1_handler(int irq, void *dev_id)
+{
+	struct pvrdma_dev *dev = dev_id;
+	struct pvrdma_ring *ring = &dev->async_ring_state->rx;
+	int ring_slots = (dev->dsr->async_ring_pages.num_pages - 1) *
+			 PAGE_SIZE / sizeof(struct pvrdma_eqe);
+	unsigned int head;
+
+	dev_dbg(&dev->pdev->dev, "interrupt 1 (async event) handler\n");
+
+	/*
+	 * Don't process events until the IB device is registered. Otherwise
+	 * we'll try to ib_dispatch_event() on an invalid device.
+	 */
+	if (!dev->ib_active)
+		return IRQ_HANDLED;
+
+	while (pvrdma_idx_ring_has_data(ring, ring_slots, &head) > 0) {
+		struct pvrdma_eqe *eqe;
+
+		eqe = get_eqe(dev, head);
+
+		switch (eqe->type) {
+		case PVRDMA_EVENT_QP_FATAL:
+		case PVRDMA_EVENT_QP_REQ_ERR:
+		case PVRDMA_EVENT_QP_ACCESS_ERR:
+		case PVRDMA_EVENT_COMM_EST:
+		case PVRDMA_EVENT_SQ_DRAINED:
+		case PVRDMA_EVENT_PATH_MIG:
+		case PVRDMA_EVENT_PATH_MIG_ERR:
+		case PVRDMA_EVENT_QP_LAST_WQE_REACHED:
+			pvrdma_qp_event(dev, eqe->info, eqe->type);
+			break;
+
+		case PVRDMA_EVENT_CQ_ERR:
+			pvrdma_cq_event(dev, eqe->info, eqe->type);
+			break;
+
+		case PVRDMA_EVENT_SRQ_ERR:
+		case PVRDMA_EVENT_SRQ_LIMIT_REACHED:
+			break;
+
+		case PVRDMA_EVENT_PORT_ACTIVE:
+		case PVRDMA_EVENT_PORT_ERR:
+		case PVRDMA_EVENT_LID_CHANGE:
+		case PVRDMA_EVENT_PKEY_CHANGE:
+		case PVRDMA_EVENT_SM_CHANGE:
+		case PVRDMA_EVENT_CLIENT_REREGISTER:
+		case PVRDMA_EVENT_GID_CHANGE:
+			pvrdma_dev_event(dev, eqe->info, eqe->type);
+			break;
+
+		case PVRDMA_EVENT_DEVICE_FATAL:
+			pvrdma_dev_event(dev, 1, eqe->type);
+			break;
+
+		default:
+			break;
+		}
+
+		pvrdma_idx_ring_inc(&ring->cons_head, ring_slots);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static inline struct pvrdma_cqne *get_cqne(struct pvrdma_dev *dev,
+					   unsigned int i)
+{
+	return (struct pvrdma_cqne *)pvrdma_page_dir_get_ptr(
+					&dev->cq_pdir,
+					PAGE_SIZE +
+					sizeof(struct pvrdma_cqne) * i);
+}
+
+static irqreturn_t pvrdma_intrx_handler(int irq, void *dev_id)
+{
+	struct pvrdma_dev *dev = dev_id;
+	struct pvrdma_ring *ring = &dev->cq_ring_state->rx;
+	int ring_slots = (dev->dsr->cq_ring_pages.num_pages - 1) * PAGE_SIZE /
+			 sizeof(struct pvrdma_cqne);
+	unsigned int head;
+	unsigned long flags;
+
+	dev_dbg(&dev->pdev->dev, "interrupt x (completion) handler\n");
+
+	while (pvrdma_idx_ring_has_data(ring, ring_slots, &head) > 0) {
+		struct pvrdma_cqne *cqne;
+		struct pvrdma_cq *cq;
+
+		cqne = get_cqne(dev, head);
+		spin_lock_irqsave(&dev->cq_tbl_lock, flags);
+		cq = dev->cq_tbl[cqne->info % dev->dsr->caps.max_cq];
+		if (cq)
+			atomic_inc(&cq->refcnt);
+		spin_unlock_irqrestore(&dev->cq_tbl_lock, flags);
+
+		if (cq && cq->ibcq.comp_handler)
+			cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+		if (cq) {
+			atomic_dec(&cq->refcnt);
+			if (atomic_read(&cq->refcnt))
+				wake_up(&cq->wait);
+		}
+		pvrdma_idx_ring_inc(&ring->cons_head, ring_slots);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void pvrdma_disable_msi_all(struct pvrdma_dev *dev)
+{
+	if (dev->intr.type == PVRDMA_INTR_TYPE_MSIX)
+		pci_disable_msix(dev->pdev);
+	else if (dev->intr.type == PVRDMA_INTR_TYPE_MSI)
+		pci_disable_msi(dev->pdev);
+}
+
+static void pvrdma_free_irq(struct pvrdma_dev *dev)
+{
+	int i;
+
+	dev_dbg(&dev->pdev->dev, "freeing interrupts\n");
+
+	if (dev->intr.type == PVRDMA_INTR_TYPE_MSIX) {
+		for (i = 0; i < dev->intr.size; i++) {
+			if (dev->intr.enabled[i]) {
+				free_irq(dev->intr.msix_entry[i].vector, dev);
+				dev->intr.enabled[i] = 0;
+			}
+		}
+	} else if (dev->intr.type == PVRDMA_INTR_TYPE_INTX ||
+		   dev->intr.type == PVRDMA_INTR_TYPE_MSI) {
+		free_irq(dev->pdev->irq, dev);
+	}
+}
+
+static void pvrdma_enable_intrs(struct pvrdma_dev *dev)
+{
+	dev_dbg(&dev->pdev->dev, "enable interrupts\n");
+	pvrdma_write_reg(dev, PVRDMA_REG_IMR, 0);
+}
+
+static void pvrdma_disable_intrs(struct pvrdma_dev *dev)
+{
+	dev_dbg(&dev->pdev->dev, "disable interrupts\n");
+	pvrdma_write_reg(dev, PVRDMA_REG_IMR, ~0);
+}
+
+static int pvrdma_enable_msix(struct pci_dev *pdev, struct pvrdma_dev *dev)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < PVRDMA_MAX_INTERRUPTS; i++) {
+		dev->intr.msix_entry[i].entry = i;
+		dev->intr.msix_entry[i].vector = i;
+
+		switch (i) {
+		case 0:
+			/* CMD ring handler */
+			dev->intr.handler[i] = pvrdma_intr0_handler;
+			break;
+		case 1:
+			/* Async event ring handler */
+			dev->intr.handler[i] = pvrdma_intr1_handler;
+			break;
+		default:
+			/* Completion queue handler */
+			dev->intr.handler[i] = pvrdma_intrx_handler;
+			break;
+		}
+	}
+
+	ret = pci_enable_msix(pdev, dev->intr.msix_entry,
+			      PVRDMA_MAX_INTERRUPTS);
+	if (!ret) {
+		dev->intr.type = PVRDMA_INTR_TYPE_MSIX;
+		dev->intr.size = PVRDMA_MAX_INTERRUPTS;
+	} else if (ret > 0) {
+		ret = pci_enable_msix(pdev, dev->intr.msix_entry, ret);
+		if (!ret) {
+			dev->intr.type = PVRDMA_INTR_TYPE_MSIX;
+			dev->intr.size = ret;
+		} else {
+			dev->intr.size = 0;
+		}
+	}
+
+	dev_dbg(&pdev->dev, "using interrupt type %d, size %d\n",
+		dev->intr.type, dev->intr.size);
+
+	return ret;
+}
+
+static int pvrdma_alloc_intrs(struct pvrdma_dev *dev)
+{
+	int ret = 0;
+	int i;
+
+	if (pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX) &&
+	    pvrdma_enable_msix(dev->pdev, dev)) {
+		/* Try MSI */
+		ret = pci_enable_msi(dev->pdev);
+		if (!ret) {
+			dev->intr.type = PVRDMA_INTR_TYPE_MSI;
+		} else {
+			/* Legacy INTR */
+			dev->intr.type = PVRDMA_INTR_TYPE_INTX;
+		}
+	}
+
+	/* Request First IRQ */
+	switch (dev->intr.type) {
+	case PVRDMA_INTR_TYPE_INTX:
+	case PVRDMA_INTR_TYPE_MSI:
+		ret = request_irq(dev->pdev->irq, pvrdma_intr0_handler,
+				  IRQF_SHARED, DRV_NAME, dev);
+		if (ret) {
+			dev_err(&dev->pdev->dev,
+				"failed to request interrupt\n");
+			goto disable_msi;
+		}
+		break;
+	case PVRDMA_INTR_TYPE_MSIX:
+		ret = request_irq(dev->intr.msix_entry[0].vector,
+				  pvrdma_intr0_handler, 0, DRV_NAME, dev);
+		if (ret) {
+			dev_err(&dev->pdev->dev,
+				"failed to request interrupt 0\n");
+			goto disable_msi;
+		}
+		dev->intr.enabled[0] = 1;
+		break;
+	default:
+		/* Not reached */
+		break;
+	}
+
+	/* For MSIX: request intr for each vector */
+	if (dev->intr.size > 1) {
+		ret = request_irq(dev->intr.msix_entry[1].vector,
+				  pvrdma_intr1_handler, 0, DRV_NAME, dev);
+		if (ret) {
+			dev_err(&dev->pdev->dev,
+				"failed to request interrupt 1\n");
+			goto free_irq;
+		}
+		dev->intr.enabled[1] = 1;
+
+		for (i = 2; i < dev->intr.size; i++) {
+			ret = request_irq(dev->intr.msix_entry[i].vector,
+					  pvrdma_intrx_handler, 0,
+					  DRV_NAME, dev);
+			if (ret) {
+				dev_err(&dev->pdev->dev,
+					"failed to request interrupt %d\n", i);
+				goto free_irq;
+			}
+			dev->intr.enabled[i] = 1;
+		}
+	}
+
+	return 0;
+
+free_irq:
+	pvrdma_free_irq(dev);
+disable_msi:
+	pvrdma_disable_msi_all(dev);
+	return ret;
+}
+
+static void pvrdma_free_slots(struct pvrdma_dev *dev)
+{
+	struct pci_dev *pdev = dev->pdev;
+
+	if (dev->resp_slot)
+		dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->resp_slot,
+				  dev->dsr->resp_slot_dma);
+	if (dev->cmd_slot)
+		dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->cmd_slot,
+				  dev->dsr->cmd_slot_dma);
+}
+
+static int pvrdma_add_gid_at_index(struct pvrdma_dev *dev,
+				   const union ib_gid *gid,
+				   int index)
+{
+	int ret;
+	union pvrdma_cmd_req req;
+	struct pvrdma_cmd_create_bind *cmd_bind = &req.create_bind;
+
+	if (!dev->sgid_tbl) {
+		dev_warn(&dev->pdev->dev, "sgid table not initialized\n");
+		return -EINVAL;
+	}
+
+	memset(cmd_bind, 0, sizeof(*cmd_bind));
+	cmd_bind->hdr.cmd = PVRDMA_CMD_CREATE_BIND;
+	memcpy(cmd_bind->new_gid, gid->raw, 16);
+	cmd_bind->mtu = ib_mtu_enum_to_int(IB_MTU_1024);
+	cmd_bind->vlan = 0xfff;
+	cmd_bind->index = index;
+	cmd_bind->gid_type = PVRDMA_GID_TYPE_FLAG_ROCE_V1;
+
+	ret = pvrdma_cmd_post(dev, &req, NULL, 0);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not create binding, error: %d\n", ret);
+		return -EFAULT;
+	}
+	memcpy(&dev->sgid_tbl[index], gid, sizeof(*gid));
+	return 0;
+}
+
+static int pvrdma_add_gid(struct ib_device *ibdev,
+			  u8 port_num,
+			  unsigned int index,
+			  const union ib_gid *gid,
+			  const struct ib_gid_attr *attr,
+			  void **context)
+{
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+
+	return pvrdma_add_gid_at_index(dev, gid, index);
+}
+
+static int pvrdma_del_gid_at_index(struct pvrdma_dev *dev, int index)
+{
+	int ret;
+	union pvrdma_cmd_req req;
+	struct pvrdma_cmd_destroy_bind *cmd_dest = &req.destroy_bind;
+
+	/* Update sgid table. */
+	if (!dev->sgid_tbl) {
+		dev_warn(&dev->pdev->dev, "sgid table not initialized\n");
+		return -EINVAL;
+	}
+
+	memset(cmd_dest, 0, sizeof(*cmd_dest));
+	cmd_dest->hdr.cmd = PVRDMA_CMD_DESTROY_BIND;
+	memcpy(cmd_dest->dest_gid, &dev->sgid_tbl[index], 16);
+	cmd_dest->index = index;
+
+	ret = pvrdma_cmd_post(dev, &req, NULL, 0);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not destroy binding, error: %d\n", ret);
+		return ret;
+	}
+	memset(&dev->sgid_tbl[index], 0, 16);
+	return 0;
+}
+
+static int pvrdma_del_gid(struct ib_device *ibdev,
+			  u8 port_num,
+			  unsigned int index,
+			  void **context)
+{
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+
+	dev_dbg(&dev->pdev->dev, "removing gid at index %u from %s",
+		index, dev->netdev->name);
+
+	return pvrdma_del_gid_at_index(dev, index);
+}
+
+static void pvrdma_netdevice_event_handle(struct pvrdma_dev *dev,
+					  unsigned long event)
+{
+	switch (event) {
+	case NETDEV_REBOOT:
+	case NETDEV_DOWN:
+		pvrdma_dispatch_event(dev, 1, IB_EVENT_PORT_ERR);
+		break;
+	case NETDEV_UP:
+		pvrdma_dispatch_event(dev, 1, IB_EVENT_PORT_ACTIVE);
+		break;
+	default:
+		dev_dbg(&dev->pdev->dev, "ignore netdevice event %ld on %s\n",
+			event, dev->ib_dev.name);
+		break;
+	}
+}
+
+static void pvrdma_netdevice_event_work(struct work_struct *work)
+{
+	struct pvrdma_netdevice_work *netdev_work;
+	struct pvrdma_dev *dev;
+
+	netdev_work = container_of(work, struct pvrdma_netdevice_work, work);
+
+	mutex_lock(&pvrdma_device_list_lock);
+	list_for_each_entry(dev, &pvrdma_device_list, device_link) {
+		if (dev->netdev == netdev_work->event_netdev) {
+			pvrdma_netdevice_event_handle(dev, netdev_work->event);
+			break;
+		}
+	}
+	mutex_unlock(&pvrdma_device_list_lock);
+
+	kfree(netdev_work);
+}
+
+static int pvrdma_netdevice_event(struct notifier_block *this,
+				  unsigned long event, void *ptr)
+{
+	struct net_device *event_netdev = netdev_notifier_info_to_dev(ptr);
+	struct pvrdma_netdevice_work *netdev_work;
+
+	netdev_work = kmalloc(sizeof(*netdev_work), GFP_ATOMIC);
+	if (!netdev_work)
+		return NOTIFY_BAD;
+
+	INIT_WORK(&netdev_work->work, pvrdma_netdevice_event_work);
+	netdev_work->event_netdev = event_netdev;
+	netdev_work->event = event;
+	queue_work(event_wq, &netdev_work->work);
+
+	return NOTIFY_DONE;
+}
+
+static int pvrdma_pci_probe(struct pci_dev *pdev,
+			    const struct pci_device_id *id)
+{
+	struct pci_dev *pdev_net;
+	struct pvrdma_dev *dev;
+	int ret;
+	unsigned long start;
+	unsigned long len;
+	unsigned int version;
+	dma_addr_t slot_dma = 0;
+
+	dev_dbg(&pdev->dev, "initializing driver %s\n", pci_name(pdev));
+
+	/* Allocate zero-out device */
+	dev = (struct pvrdma_dev *)ib_alloc_device(sizeof(*dev));
+	if (!dev) {
+		dev_err(&pdev->dev, "failed to allocate IB device\n");
+		return -ENOMEM;
+	}
+
+	mutex_lock(&pvrdma_device_list_lock);
+	list_add(&dev->device_link, &pvrdma_device_list);
+	mutex_unlock(&pvrdma_device_list_lock);
+
+	ret = pvrdma_init_device(dev);
+	if (ret)
+		goto err_free_device;
+
+	dev->pdev = pdev;
+	pci_set_drvdata(pdev, dev);
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot enable PCI device\n");
+		goto err_free_device;
+	}
+
+	dev_dbg(&pdev->dev, "PCI resource flags BAR0 %#lx\n",
+		pci_resource_flags(pdev, 0));
+	dev_dbg(&pdev->dev, "PCI resource len %#llx\n",
+		(unsigned long long)pci_resource_len(pdev, 0));
+	dev_dbg(&pdev->dev, "PCI resource start %#llx\n",
+		(unsigned long long)pci_resource_start(pdev, 0));
+	dev_dbg(&pdev->dev, "PCI resource flags BAR1 %#lx\n",
+		pci_resource_flags(pdev, 1));
+	dev_dbg(&pdev->dev, "PCI resource len %#llx\n",
+		(unsigned long long)pci_resource_len(pdev, 1));
+	dev_dbg(&pdev->dev, "PCI resource start %#llx\n",
+		(unsigned long long)pci_resource_start(pdev, 1));
+
+	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM) ||
+	    !(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
+		dev_err(&pdev->dev, "PCI BAR region not MMIO\n");
+		ret = -ENOMEM;
+		goto err_free_device;
+	}
+
+	ret = pci_request_regions(pdev, DRV_NAME);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot request PCI resources\n");
+		goto err_disable_pdev;
+	}
+
+	/* Enable 64-Bit DMA */
+	if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
+		ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+		if (ret != 0) {
+			dev_err(&pdev->dev,
+				"pci_set_consistent_dma_mask failed\n");
+			goto err_free_resource;
+		}
+	} else {
+		ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (ret != 0) {
+			dev_err(&pdev->dev,
+				"pci_set_dma_mask failed\n");
+			goto err_free_resource;
+		}
+	}
+
+	pci_set_master(pdev);
+
+	/* Map register space */
+	start = pci_resource_start(dev->pdev, PVRDMA_PCI_RESOURCE_REG);
+	len = pci_resource_len(dev->pdev, PVRDMA_PCI_RESOURCE_REG);
+	dev->regs = ioremap(start, len);
+	if (!dev->regs) {
+		dev_err(&pdev->dev, "register mapping failed\n");
+		ret = -ENOMEM;
+		goto err_free_resource;
+	}
+
+	/* Setup per-device UAR. */
+	dev->driver_uar.index = 0;
+	dev->driver_uar.pfn =
+		pci_resource_start(dev->pdev, PVRDMA_PCI_RESOURCE_UAR) >>
+		PAGE_SHIFT;
+	dev->driver_uar.map =
+		ioremap(dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+	if (!dev->driver_uar.map) {
+		dev_err(&pdev->dev, "failed to remap UAR pages\n");
+		ret = -ENOMEM;
+		goto err_unmap_regs;
+	}
+
+	version = pvrdma_read_reg(dev, PVRDMA_REG_VERSION);
+	dev_info(&pdev->dev, "device version %d, driver version %d\n",
+		 version, PVRDMA_VERSION);
+	if (version < PVRDMA_VERSION) {
+		dev_err(&pdev->dev, "incompatible device version\n");
+		goto err_uar_unmap;
+	}
+
+	dev->dsr = dma_alloc_coherent(&pdev->dev, sizeof(*dev->dsr),
+				      &dev->dsrbase, GFP_KERNEL);
+	if (!dev->dsr) {
+		dev_err(&pdev->dev, "failed to allocate shared region\n");
+		ret = -ENOMEM;
+		goto err_uar_unmap;
+	}
+
+	/* Setup the shared region */
+	memset(dev->dsr, 0, sizeof(*dev->dsr));
+	dev->dsr->driver_version = PVRDMA_VERSION;
+	dev->dsr->gos_info.gos_bits = sizeof(void *) == 4 ?
+		PVRDMA_GOS_BITS_32 :
+		PVRDMA_GOS_BITS_64;
+	dev->dsr->gos_info.gos_type = PVRDMA_GOS_TYPE_LINUX;
+	dev->dsr->gos_info.gos_ver = 1;
+	dev->dsr->uar_pfn = dev->driver_uar.pfn;
+
+	/* Command slot. */
+	dev->cmd_slot = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+					   &slot_dma, GFP_KERNEL);
+	if (!dev->cmd_slot) {
+		ret = -ENOMEM;
+		goto err_free_dsr;
+	}
+
+	dev->dsr->cmd_slot_dma = (u64)slot_dma;
+
+	/* Response slot. */
+	dev->resp_slot = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+					    &slot_dma, GFP_KERNEL);
+	if (!dev->resp_slot) {
+		ret = -ENOMEM;
+		goto err_free_slots;
+	}
+
+	dev->dsr->resp_slot_dma = (u64)slot_dma;
+
+	/* Async event ring */
+	dev->dsr->async_ring_pages.num_pages = 4;
+	ret = pvrdma_page_dir_init(dev, &dev->async_pdir,
+				   dev->dsr->async_ring_pages.num_pages, true);
+	if (ret)
+		goto err_free_slots;
+	dev->async_ring_state = dev->async_pdir.pages[0];
+	dev->dsr->async_ring_pages.pdir_dma = dev->async_pdir.dir_dma;
+
+	/* CQ notification ring */
+	dev->dsr->cq_ring_pages.num_pages = 4;
+	ret = pvrdma_page_dir_init(dev, &dev->cq_pdir,
+				   dev->dsr->cq_ring_pages.num_pages, true);
+	if (ret)
+		goto err_free_async_ring;
+	dev->cq_ring_state = dev->cq_pdir.pages[0];
+	dev->dsr->cq_ring_pages.pdir_dma = dev->cq_pdir.dir_dma;
+
+	/*
+	 * Write the PA of the shared region to the device. The writes must be
+	 * ordered such that the high bits are written last. When the writes
+	 * complete, the device will have filled out the capabilities.
+	 */
+
+	pvrdma_write_reg(dev, PVRDMA_REG_DSRLOW, (u32)dev->dsrbase);
+	pvrdma_write_reg(dev, PVRDMA_REG_DSRHIGH,
+			 (u32)((u64)(dev->dsrbase) >> 32));
+
+	/* Make sure the write is complete before reading status. */
+	mb();
+
+	/* Currently, the driver only supports RoCE mode. */
+	if (dev->dsr->caps.mode != PVRDMA_DEVICE_MODE_ROCE) {
+		dev_err(&pdev->dev, "unsupported transport %d\n",
+			dev->dsr->caps.mode);
+		ret = -EFAULT;
+		goto err_free_cq_ring;
+	}
+
+	/* Currently, the driver only supports RoCE V1. */
+	if (!(dev->dsr->caps.gid_types & PVRDMA_GID_TYPE_FLAG_ROCE_V1)) {
+		dev_err(&pdev->dev, "driver needs RoCE v1 support\n");
+		ret = -EFAULT;
+		goto err_free_cq_ring;
+	}
+
+	/* Paired vmxnet3 will have same bus, slot. But func will be 0 */
+	pdev_net = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0));
+	if (!pdev_net) {
+		dev_err(&pdev->dev, "failed to find paired net device\n");
+		ret = -ENODEV;
+		goto err_free_cq_ring;
+	}
+
+	if (pdev_net->vendor != PCI_VENDOR_ID_VMWARE ||
+	    pdev_net->device != PCI_DEVICE_ID_VMWARE_VMXNET3) {
+		dev_err(&pdev->dev, "failed to find paired vmxnet3 device\n");
+		pci_dev_put(pdev_net);
+		ret = -ENODEV;
+		goto err_free_cq_ring;
+	}
+
+	dev->netdev = pci_get_drvdata(pdev_net);
+	pci_dev_put(pdev_net);
+	if (!dev->netdev) {
+		dev_err(&pdev->dev, "failed to get vmxnet3 device\n");
+		ret = -ENODEV;
+		goto err_free_cq_ring;
+	}
+
+	dev_info(&pdev->dev, "paired device to %s\n", dev->netdev->name);
+
+	/* Interrupt setup */
+	ret = pvrdma_alloc_intrs(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to allocate interrupts\n");
+		ret = -ENOMEM;
+		goto err_free_cq_ring;
+	}
+
+	/* Allocate UAR table. */
+	ret = pvrdma_uar_table_init(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to allocate UAR table\n");
+		ret = -ENOMEM;
+		goto err_free_intrs;
+	}
+
+	/* Allocate GID table */
+	dev->sgid_tbl = kcalloc(dev->dsr->caps.gid_tbl_len,
+				sizeof(union ib_gid), GFP_KERNEL);
+	if (!dev->sgid_tbl) {
+		ret = -ENOMEM;
+		goto err_free_uar_table;
+	}
+	dev_dbg(&pdev->dev, "gid table len %d\n", dev->dsr->caps.gid_tbl_len);
+
+	pvrdma_enable_intrs(dev);
+
+	/* Activate pvrdma device */
+	pvrdma_write_reg(dev, PVRDMA_REG_CTL, PVRDMA_DEVICE_CTL_ACTIVATE);
+
+	/* Make sure the write is complete before reading status. */
+	mb();
+
+	/* Check if device was successfully activated */
+	ret = pvrdma_read_reg(dev, PVRDMA_REG_ERR);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "failed to activate device\n");
+		ret = -EFAULT;
+		goto err_disable_intr;
+	}
+
+	/* Register IB device */
+	ret = pvrdma_register_device(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register IB device\n");
+		goto err_disable_intr;
+	}
+
+	dev->nb_netdev.notifier_call = pvrdma_netdevice_event;
+	ret = register_netdevice_notifier(&dev->nb_netdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register netdevice events\n");
+		goto err_unreg_ibdev;
+	}
+
+	dev_info(&pdev->dev, "attached to device\n");
+	return 0;
+
+err_unreg_ibdev:
+	ib_unregister_device(&dev->ib_dev);
+err_disable_intr:
+	pvrdma_disable_intrs(dev);
+	kfree(dev->sgid_tbl);
+err_free_uar_table:
+	pvrdma_uar_table_cleanup(dev);
+err_free_intrs:
+	pvrdma_free_irq(dev);
+	pvrdma_disable_msi_all(dev);
+err_free_cq_ring:
+	pvrdma_page_dir_cleanup(dev, &dev->cq_pdir);
+err_free_async_ring:
+	pvrdma_page_dir_cleanup(dev, &dev->async_pdir);
+err_free_slots:
+	pvrdma_free_slots(dev);
+err_free_dsr:
+	dma_free_coherent(&pdev->dev, sizeof(*dev->dsr), dev->dsr,
+			  dev->dsrbase);
+err_uar_unmap:
+	iounmap(dev->driver_uar.map);
+err_unmap_regs:
+	iounmap(dev->regs);
+err_free_resource:
+	pci_release_regions(pdev);
+err_disable_pdev:
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+err_free_device:
+	mutex_lock(&pvrdma_device_list_lock);
+	list_del(&dev->device_link);
+	mutex_unlock(&pvrdma_device_list_lock);
+	ib_dealloc_device(&dev->ib_dev);
+	return ret;
+}
+
+static void pvrdma_pci_remove(struct pci_dev *pdev)
+{
+	struct pvrdma_dev *dev = pci_get_drvdata(pdev);
+
+	if (!dev)
+		return;
+
+	dev_info(&pdev->dev, "detaching from device\n");
+
+	unregister_netdevice_notifier(&dev->nb_netdev);
+	dev->nb_netdev.notifier_call = NULL;
+
+	flush_workqueue(event_wq);
+
+	/* Unregister ib device */
+	ib_unregister_device(&dev->ib_dev);
+
+	mutex_lock(&pvrdma_device_list_lock);
+	list_del(&dev->device_link);
+	mutex_unlock(&pvrdma_device_list_lock);
+
+	pvrdma_disable_intrs(dev);
+	pvrdma_free_irq(dev);
+	pvrdma_disable_msi_all(dev);
+
+	/* Deactivate pvrdma device */
+	pvrdma_write_reg(dev, PVRDMA_REG_CTL, PVRDMA_DEVICE_CTL_RESET);
+	pvrdma_page_dir_cleanup(dev, &dev->cq_pdir);
+	pvrdma_page_dir_cleanup(dev, &dev->async_pdir);
+	pvrdma_free_slots(dev);
+
+	iounmap(dev->regs);
+	kfree(dev->sgid_tbl);
+	kfree(dev->cq_tbl);
+	kfree(dev->qp_tbl);
+	pvrdma_uar_table_cleanup(dev);
+	iounmap(dev->driver_uar.map);
+
+	ib_dealloc_device(&dev->ib_dev);
+
+	/* Free pci resources */
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+static struct pci_device_id pvrdma_pci_table[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_VMWARE, PCI_DEVICE_ID_VMWARE_PVRDMA), },
+	{ 0 },
+};
+
+MODULE_DEVICE_TABLE(pci, pvrdma_pci_table);
+
+static struct pci_driver pvrdma_driver = {
+	.name		= DRV_NAME,
+	.id_table	= pvrdma_pci_table,
+	.probe		= pvrdma_pci_probe,
+	.remove		= pvrdma_pci_remove,
+};
+
+static int __init pvrdma_init(void)
+{
+	int err;
+
+	event_wq = alloc_ordered_workqueue("pvrdma_event_wq", WQ_MEM_RECLAIM);
+	if (!event_wq)
+		return -ENOMEM;
+
+	err = pci_register_driver(&pvrdma_driver);
+	if (err)
+		destroy_workqueue(event_wq);
+
+	return err;
+}
+
+static void __exit pvrdma_cleanup(void)
+{
+	pci_unregister_driver(&pvrdma_driver);
+
+	destroy_workqueue(event_wq);
+}
+
+module_init(pvrdma_init);
+module_exit(pvrdma_cleanup);
+
+MODULE_AUTHOR("VMware, Inc");
+MODULE_DESCRIPTION("VMware Paravirtual RDMA driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("Dual BSD/GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/bitmap.h>
+
+#include "pvrdma.h"
+
+int pvrdma_page_dir_init(struct pvrdma_dev *dev, struct pvrdma_page_dir *pdir,
+			 u64 npages, bool alloc_pages)
+{
+	u64 i;
+
+	if (npages > PVRDMA_PAGE_DIR_MAX_PAGES)
+		return -EINVAL;
+
+	memset(pdir, 0, sizeof(*pdir));
+
+	pdir->dir = dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
+				       &pdir->dir_dma, GFP_KERNEL);
+	if (!pdir->dir)
+		goto err;
+
+	pdir->ntables = PVRDMA_PAGE_DIR_TABLE(npages - 1) + 1;
+	pdir->tables = kcalloc(pdir->ntables, sizeof(*pdir->tables),
+			       GFP_KERNEL);
+	if (!pdir->tables)
+		goto err;
+
+	for (i = 0; i < pdir->ntables; i++) {
+		pdir->tables[i] = dma_alloc_coherent(&dev->pdev->dev, PAGE_SIZE,
+						(dma_addr_t *)&pdir->dir[i],
+						GFP_KERNEL);
+		if (!pdir->tables[i])
+			goto err;
+	}
+
+	pdir->npages = npages;
+
+	if (alloc_pages) {
+		pdir->pages = kcalloc(npages, sizeof(*pdir->pages),
+				      GFP_KERNEL);
+		if (!pdir->pages)
+			goto err;
+
+		for (i = 0; i < pdir->npages; i++) {
+			dma_addr_t page_dma;
+
+			pdir->pages[i] = dma_alloc_coherent(&dev->pdev->dev,
+							    PAGE_SIZE,
+							    &page_dma,
+							    GFP_KERNEL);
+			if (!pdir->pages[i])
+				goto err;
+
+			pvrdma_page_dir_insert_dma(pdir, i, page_dma);
+		}
+	}
+
+	return 0;
+
+err:
+	pvrdma_page_dir_cleanup(dev, pdir);
+
+	return -ENOMEM;
+}
+
+static u64 *pvrdma_page_dir_table(struct pvrdma_page_dir *pdir, u64 idx)
+{
+	return pdir->tables[PVRDMA_PAGE_DIR_TABLE(idx)];
+}
+
+dma_addr_t pvrdma_page_dir_get_dma(struct pvrdma_page_dir *pdir, u64 idx)
+{
+	return pvrdma_page_dir_table(pdir, idx)[PVRDMA_PAGE_DIR_PAGE(idx)];
+}
+
+static void pvrdma_page_dir_cleanup_pages(struct pvrdma_dev *dev,
+					  struct pvrdma_page_dir *pdir)
+{
+	if (pdir->pages) {
+		u64 i;
+
+		for (i = 0; i < pdir->npages && pdir->pages[i]; i++) {
+			dma_addr_t page_dma = pvrdma_page_dir_get_dma(pdir, i);
+
+			dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+					  pdir->pages[i], page_dma);
+		}
+
+		kfree(pdir->pages);
+	}
+}
+
+static void pvrdma_page_dir_cleanup_tables(struct pvrdma_dev *dev,
+					   struct pvrdma_page_dir *pdir)
+{
+	if (pdir->tables) {
+		int i;
+
+		pvrdma_page_dir_cleanup_pages(dev, pdir);
+
+		for (i = 0; i < pdir->ntables; i++) {
+			u64 *table = pdir->tables[i];
+
+			if (table)
+				dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+						  table, pdir->dir[i]);
+		}
+
+		kfree(pdir->tables);
+	}
+}
+
+void pvrdma_page_dir_cleanup(struct pvrdma_dev *dev,
+			     struct pvrdma_page_dir *pdir)
+{
+	if (pdir->dir) {
+		pvrdma_page_dir_cleanup_tables(dev, pdir);
+		dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
+				  pdir->dir, pdir->dir_dma);
+	}
+}
+
+int pvrdma_page_dir_insert_dma(struct pvrdma_page_dir *pdir, u64 idx,
+			       dma_addr_t daddr)
+{
+	u64 *table;
+
+	if (idx >= pdir->npages)
+		return -EINVAL;
+
+	table = pvrdma_page_dir_table(pdir, idx);
+	table[PVRDMA_PAGE_DIR_PAGE(idx)] = daddr;
+
+	return 0;
+}
+
+int pvrdma_page_dir_insert_umem(struct pvrdma_page_dir *pdir,
+				struct ib_umem *umem, u64 offset)
+{
+	u64 i = offset;
+	int j, entry;
+	int ret = 0, len = 0;
+	struct scatterlist *sg;
+
+	if (offset >= pdir->npages)
+		return -EINVAL;
+
+	for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
+		len = sg_dma_len(sg) >> PAGE_SHIFT;
+		for (j = 0; j < len; j++) {
+			dma_addr_t addr = sg_dma_address(sg) +
+					  umem->page_size * j;
+
+			ret = pvrdma_page_dir_insert_dma(pdir, i, addr);
+			if (ret)
+				goto exit;
+
+			i++;
+		}
+	}
+
+exit:
+	return ret;
+}
+
+int pvrdma_page_dir_insert_page_list(struct pvrdma_page_dir *pdir,
+				     u64 *page_list,
+				     int num_pages)
+{
+	int i;
+	int ret;
+
+	if (num_pages > pdir->npages)
+		return -EINVAL;
+
+	for (i = 0; i < num_pages; i++) {
+		ret = pvrdma_page_dir_insert_dma(pdir, i, page_list[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+void pvrdma_qp_cap_to_ib(struct ib_qp_cap *dst, const struct pvrdma_qp_cap *src)
+{
+	dst->max_send_wr = src->max_send_wr;
+	dst->max_recv_wr = src->max_recv_wr;
+	dst->max_send_sge = src->max_send_sge;
+	dst->max_recv_sge = src->max_recv_sge;
+	dst->max_inline_data = src->max_inline_data;
+}
+
+void ib_qp_cap_to_pvrdma(struct pvrdma_qp_cap *dst, const struct ib_qp_cap *src)
+{
+	dst->max_send_wr = src->max_send_wr;
+	dst->max_recv_wr = src->max_recv_wr;
+	dst->max_send_sge = src->max_send_sge;
+	dst->max_recv_sge = src->max_recv_sge;
+	dst->max_inline_data = src->max_inline_data;
+}
+
+void pvrdma_gid_to_ib(union ib_gid *dst, const union pvrdma_gid *src)
+{
+	BUILD_BUG_ON(sizeof(union pvrdma_gid) != sizeof(union ib_gid));
+	memcpy(dst, src, sizeof(*src));
+}
+
+void ib_gid_to_pvrdma(union pvrdma_gid *dst, const union ib_gid *src)
+{
+	BUILD_BUG_ON(sizeof(union pvrdma_gid) != sizeof(union ib_gid));
+	memcpy(dst, src, sizeof(*src));
+}
+
+void pvrdma_global_route_to_ib(struct ib_global_route *dst,
+			       const struct pvrdma_global_route *src)
+{
+	pvrdma_gid_to_ib(&dst->dgid, &src->dgid);
+	dst->flow_label = src->flow_label;
+	dst->sgid_index = src->sgid_index;
+	dst->hop_limit = src->hop_limit;
+	dst->traffic_class = src->traffic_class;
+}
+
+void ib_global_route_to_pvrdma(struct pvrdma_global_route *dst,
+			       const struct ib_global_route *src)
+{
+	ib_gid_to_pvrdma(&dst->dgid, &src->dgid);
+	dst->flow_label = src->flow_label;
+	dst->sgid_index = src->sgid_index;
+	dst->hop_limit = src->hop_limit;
+	dst->traffic_class = src->traffic_class;
+}
+
+void pvrdma_ah_attr_to_ib(struct ib_ah_attr *dst,
+			  const struct pvrdma_ah_attr *src)
+{
+	pvrdma_global_route_to_ib(&dst->grh, &src->grh);
+	dst->dlid = src->dlid;
+	dst->sl = src->sl;
+	dst->src_path_bits = src->src_path_bits;
+	dst->static_rate = src->static_rate;
+	dst->ah_flags = src->ah_flags;
+	dst->port_num = src->port_num;
+	memcpy(&dst->dmac, &src->dmac, sizeof(dst->dmac));
+}
+
+void ib_ah_attr_to_pvrdma(struct pvrdma_ah_attr *dst,
+			  const struct ib_ah_attr *src)
+{
+	ib_global_route_to_pvrdma(&dst->grh, &src->grh);
+	dst->dlid = src->dlid;
+	dst->sl = src->sl;
+	dst->src_path_bits = src->src_path_bits;
+	dst->static_rate = src->static_rate;
+	dst->ah_flags = src->ah_flags;
+	dst->port_num = src->port_num;
+	memcpy(&dst->dmac, &src->dmac, sizeof(dst->dmac));
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include "pvrdma.h"
+
+/**
+ * pvrdma_get_dma_mr - get a DMA memory region
+ * @pd: protection domain
+ * @acc: access flags
+ *
+ * @return: ib_mr pointer on success, otherwise returns an errno.
+ */
+struct ib_mr *pvrdma_get_dma_mr(struct ib_pd *pd, int acc)
+{
+	struct pvrdma_dev *dev = to_vdev(pd->device);
+	struct pvrdma_user_mr *mr;
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_create_mr *cmd = &req.create_mr;
+	struct pvrdma_cmd_create_mr_resp *resp = &rsp.create_mr_resp;
+	int ret;
+
+	/* Support only LOCAL_WRITE flag for DMA MRs */
+	if (acc & ~IB_ACCESS_LOCAL_WRITE) {
+		dev_warn(&dev->pdev->dev,
+			 "unsupported dma mr access flags %#x\n", acc);
+		return ERR_PTR(-EOPNOTSUPP);
+	}
+
+	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+	if (!mr)
+		return ERR_PTR(-ENOMEM);
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_CREATE_MR;
+	cmd->pd_handle = to_vpd(pd)->pd_handle;
+	cmd->access_flags = acc;
+	cmd->flags = PVRDMA_MR_FLAG_DMA;
+
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_MR_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not get DMA mem region, error: %d\n", ret);
+		kfree(mr);
+		return ERR_PTR(ret);
+	}
+
+	mr->mmr.mr_handle = resp->mr_handle;
+	mr->ibmr.lkey = resp->lkey;
+	mr->ibmr.rkey = resp->rkey;
+
+	return &mr->ibmr;
+}
+
+/**
+ * pvrdma_reg_user_mr - register a userspace memory region
+ * @pd: protection domain
+ * @start: starting address
+ * @length: length of region
+ * @virt_addr: I/O virtual address
+ * @access_flags: access flags for memory region
+ * @udata: user data
+ *
+ * @return: ib_mr pointer on success, otherwise returns an errno.
+ */
+struct ib_mr *pvrdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+				 u64 virt_addr, int access_flags,
+				 struct ib_udata *udata)
+{
+	struct pvrdma_dev *dev = to_vdev(pd->device);
+	struct pvrdma_user_mr *mr = NULL;
+	struct ib_umem *umem;
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_create_mr *cmd = &req.create_mr;
+	struct pvrdma_cmd_create_mr_resp *resp = &rsp.create_mr_resp;
+	int nchunks;
+	int ret;
+	int entry;
+	struct scatterlist *sg;
+
+	if (length == 0 || length > dev->dsr->caps.max_mr_size) {
+		dev_warn(&dev->pdev->dev, "invalid mem region length\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	umem = ib_umem_get(pd->uobject->context, start,
+			   length, access_flags, 0);
+	if (IS_ERR(umem)) {
+		dev_warn(&dev->pdev->dev,
+			 "could not get umem for mem region\n");
+		return ERR_CAST(umem);
+	}
+
+	nchunks = 0;
+	for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry)
+		nchunks += sg_dma_len(sg) >> PAGE_SHIFT;
+
+	if (nchunks < 0 || nchunks > PVRDMA_PAGE_DIR_MAX_PAGES) {
+		dev_warn(&dev->pdev->dev, "overflow %d pages in mem region\n",
+			 nchunks);
+		ret = -EINVAL;
+		goto err_umem;
+	}
+
+	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+	if (!mr) {
+		ret = -ENOMEM;
+		goto err_umem;
+	}
+
+	mr->mmr.iova = virt_addr;
+	mr->mmr.size = length;
+	mr->umem = umem;
+
+	ret = pvrdma_page_dir_init(dev, &mr->pdir, nchunks, false);
+	if (ret) {
+		dev_warn(&dev->pdev->dev,
+			 "could not allocate page directory\n");
+		goto err_umem;
+	}
+
+	ret = pvrdma_page_dir_insert_umem(&mr->pdir, mr->umem, 0);
+	if (ret)
+		goto err_pdir;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_CREATE_MR;
+	cmd->start = start;
+	cmd->length = length;
+	cmd->pd_handle = to_vpd(pd)->pd_handle;
+	cmd->access_flags = access_flags;
+	cmd->nchunks = nchunks;
+	cmd->pdir_dma = mr->pdir.dir_dma;
+
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_MR_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not register mem region, error: %d\n", ret);
+		goto err_pdir;
+	}
+
+	mr->mmr.mr_handle = resp->mr_handle;
+	mr->ibmr.lkey = resp->lkey;
+	mr->ibmr.rkey = resp->rkey;
+
+	return &mr->ibmr;
+
+err_pdir:
+	pvrdma_page_dir_cleanup(dev, &mr->pdir);
+err_umem:
+	ib_umem_release(umem);
+	kfree(mr);
+
+	return ERR_PTR(ret);
+}
+
+/**
+ * pvrdma_alloc_mr - allocate a memory region
+ * @pd: protection domain
+ * @mr_type: type of memory region
+ * @max_num_sg: maximum number of pages
+ *
+ * @return: ib_mr pointer on success, otherwise returns an errno.
+ */
+struct ib_mr *pvrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
+			      u32 max_num_sg)
+{
+	struct pvrdma_dev *dev = to_vdev(pd->device);
+	struct pvrdma_user_mr *mr;
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_create_mr *cmd = &req.create_mr;
+	struct pvrdma_cmd_create_mr_resp *resp = &rsp.create_mr_resp;
+	int size = max_num_sg * sizeof(u64);
+	int ret;
+
+	if (mr_type != IB_MR_TYPE_MEM_REG ||
+	    max_num_sg > PVRDMA_MAX_FAST_REG_PAGES)
+		return ERR_PTR(-EINVAL);
+
+	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
+	if (!mr)
+		return ERR_PTR(-ENOMEM);
+
+	mr->pages = kzalloc(size, GFP_KERNEL);
+	if (!mr->pages) {
+		ret = -ENOMEM;
+		goto freemr;
+	}
+
+	ret = pvrdma_page_dir_init(dev, &mr->pdir, max_num_sg, false);
+	if (ret) {
+		dev_warn(&dev->pdev->dev,
+			 "failed to allocate page dir for mr\n");
+		ret = -ENOMEM;
+		goto freepages;
+	}
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_CREATE_MR;
+	cmd->pd_handle = to_vpd(pd)->pd_handle;
+	cmd->access_flags = 0;
+	cmd->flags = PVRDMA_MR_FLAG_FRMR;
+	cmd->nchunks = max_num_sg;
+
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_MR_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not create FR mem region, error: %d\n", ret);
+		goto freepdir;
+	}
+
+	mr->max_pages = max_num_sg;
+	mr->mmr.mr_handle = resp->mr_handle;
+	mr->ibmr.lkey = resp->lkey;
+	mr->ibmr.rkey = resp->rkey;
+	mr->page_shift = PAGE_SHIFT;
+	mr->umem = NULL;
+
+	return &mr->ibmr;
+
+freepdir:
+	pvrdma_page_dir_cleanup(dev, &mr->pdir);
+freepages:
+	kfree(mr->pages);
+freemr:
+	kfree(mr);
+	return ERR_PTR(ret);
+}
+
+/**
+ * pvrdma_dereg_mr - deregister a memory region
+ * @ibmr: memory region
+ *
+ * @return: 0 on success.
+ */
+int pvrdma_dereg_mr(struct ib_mr *ibmr)
+{
+	struct pvrdma_user_mr *mr = to_vmr(ibmr);
+	struct pvrdma_dev *dev = to_vdev(ibmr->device);
+	union pvrdma_cmd_req req;
+	struct pvrdma_cmd_destroy_mr *cmd = &req.destroy_mr;
+	int ret;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_DESTROY_MR;
+	cmd->mr_handle = mr->mmr.mr_handle;
+	ret = pvrdma_cmd_post(dev, &req, NULL, 0);
+	if (ret < 0)
+		dev_warn(&dev->pdev->dev,
+			 "could not deregister mem region, error: %d\n", ret);
+
+	pvrdma_page_dir_cleanup(dev, &mr->pdir);
+	if (mr->umem)
+		ib_umem_release(mr->umem);
+
+	kfree(mr->pages);
+	kfree(mr);
+
+	return 0;
+}
+
+static int pvrdma_set_page(struct ib_mr *ibmr, u64 addr)
+{
+	struct pvrdma_user_mr *mr = to_vmr(ibmr);
+
+	if (mr->npages == mr->max_pages)
+		return -ENOMEM;
+
+	mr->pages[mr->npages++] = addr;
+	return 0;
+}
+
+int pvrdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
+		     unsigned int *sg_offset)
+{
+	struct pvrdma_user_mr *mr = to_vmr(ibmr);
+	struct pvrdma_dev *dev = to_vdev(ibmr->device);
+	int ret;
+
+	mr->npages = 0;
+
+	ret = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, pvrdma_set_page);
+	if (ret < 0)
+		dev_warn(&dev->pdev->dev, "could not map sg to pages\n");
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,972 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/page.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <rdma/ib_addr.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
+
+#include "pvrdma.h"
+
+static inline void get_cqs(struct pvrdma_qp *qp, struct pvrdma_cq **send_cq,
+			   struct pvrdma_cq **recv_cq)
+{
+	*send_cq = to_vcq(qp->ibqp.send_cq);
+	*recv_cq = to_vcq(qp->ibqp.recv_cq);
+}
+
+static void pvrdma_lock_cqs(struct pvrdma_cq *scq, struct pvrdma_cq *rcq,
+			    unsigned long *scq_flags,
+			    unsigned long *rcq_flags)
+	__acquires(scq->cq_lock) __acquires(rcq->cq_lock)
+{
+	if (scq == rcq) {
+		spin_lock_irqsave(&scq->cq_lock, *scq_flags);
+		__acquire(rcq->cq_lock);
+	} else if (scq->cq_handle < rcq->cq_handle) {
+		spin_lock_irqsave(&scq->cq_lock, *scq_flags);
+		spin_lock_irqsave_nested(&rcq->cq_lock, *rcq_flags,
+					 SINGLE_DEPTH_NESTING);
+	} else {
+		spin_lock_irqsave(&rcq->cq_lock, *rcq_flags);
+		spin_lock_irqsave_nested(&scq->cq_lock, *scq_flags,
+					 SINGLE_DEPTH_NESTING);
+	}
+}
+
+static void pvrdma_unlock_cqs(struct pvrdma_cq *scq, struct pvrdma_cq *rcq,
+			      unsigned long *scq_flags,
+			      unsigned long *rcq_flags)
+	__releases(scq->cq_lock) __releases(rcq->cq_lock)
+{
+	if (scq == rcq) {
+		__release(rcq->cq_lock);
+		spin_unlock_irqrestore(&scq->cq_lock, *scq_flags);
+	} else if (scq->cq_handle < rcq->cq_handle) {
+		spin_unlock_irqrestore(&rcq->cq_lock, *rcq_flags);
+		spin_unlock_irqrestore(&scq->cq_lock, *scq_flags);
+	} else {
+		spin_unlock_irqrestore(&scq->cq_lock, *scq_flags);
+		spin_unlock_irqrestore(&rcq->cq_lock, *rcq_flags);
+	}
+}
+
+static void pvrdma_reset_qp(struct pvrdma_qp *qp)
+{
+	struct pvrdma_cq *scq, *rcq;
+	unsigned long scq_flags, rcq_flags;
+
+	/* Clean up cqes */
+	get_cqs(qp, &scq, &rcq);
+	pvrdma_lock_cqs(scq, rcq, &scq_flags, &rcq_flags);
+
+	_pvrdma_flush_cqe(qp, scq);
+	if (scq != rcq)
+		_pvrdma_flush_cqe(qp, rcq);
+
+	pvrdma_unlock_cqs(scq, rcq, &scq_flags, &rcq_flags);
+
+	/*
+	 * Reset queuepair. The checks are because usermode queuepairs won't
+	 * have kernel ringstates.
+	 */
+	if (qp->rq.ring) {
+		atomic_set(&qp->rq.ring->cons_head, 0);
+		atomic_set(&qp->rq.ring->prod_tail, 0);
+	}
+	if (qp->sq.ring) {
+		atomic_set(&qp->sq.ring->cons_head, 0);
+		atomic_set(&qp->sq.ring->prod_tail, 0);
+	}
+}
+
+static int pvrdma_set_rq_size(struct pvrdma_dev *dev,
+			      struct ib_qp_cap *req_cap,
+			      struct pvrdma_qp *qp)
+{
+	if (req_cap->max_recv_wr > dev->dsr->caps.max_qp_wr ||
+	    req_cap->max_recv_sge > dev->dsr->caps.max_sge) {
+		dev_warn(&dev->pdev->dev, "recv queue size invalid\n");
+		return -EINVAL;
+	}
+
+	qp->rq.wqe_cnt = roundup_pow_of_two(max(1U, req_cap->max_recv_wr));
+	qp->rq.max_sg = roundup_pow_of_two(max(1U, req_cap->max_recv_sge));
+
+	/* Write back */
+	req_cap->max_recv_wr = qp->rq.wqe_cnt;
+	req_cap->max_recv_sge = qp->rq.max_sg;
+
+	qp->rq.wqe_size = roundup_pow_of_two(sizeof(struct pvrdma_rq_wqe_hdr) +
+					     sizeof(struct pvrdma_sge) *
+					     qp->rq.max_sg);
+	qp->npages_recv = (qp->rq.wqe_cnt * qp->rq.wqe_size + PAGE_SIZE - 1) /
+			  PAGE_SIZE;
+
+	return 0;
+}
+
+static int pvrdma_set_sq_size(struct pvrdma_dev *dev, struct ib_qp_cap *req_cap,
+			      enum ib_qp_type type, struct pvrdma_qp *qp)
+{
+	if (req_cap->max_send_wr > dev->dsr->caps.max_qp_wr ||
+	    req_cap->max_send_sge > dev->dsr->caps.max_sge) {
+		dev_warn(&dev->pdev->dev, "send queue size invalid\n");
+		return -EINVAL;
+	}
+
+	qp->sq.wqe_cnt = roundup_pow_of_two(max(1U, req_cap->max_send_wr));
+	qp->sq.max_sg = roundup_pow_of_two(max(1U, req_cap->max_send_sge));
+
+	/* Write back */
+	req_cap->max_send_wr = qp->sq.wqe_cnt;
+	req_cap->max_send_sge = qp->sq.max_sg;
+
+	qp->sq.wqe_size = roundup_pow_of_two(sizeof(struct pvrdma_sq_wqe_hdr) +
+					     sizeof(struct pvrdma_sge) *
+					     qp->sq.max_sg);
+	/* Note: one extra page for the header. */
+	qp->npages_send = 1 + (qp->sq.wqe_cnt * qp->sq.wqe_size +
+			       PAGE_SIZE - 1) / PAGE_SIZE;
+
+	return 0;
+}
+
+/**
+ * pvrdma_create_qp - create queue pair
+ * @pd: protection domain
+ * @init_attr: queue pair attributes
+ * @udata: user data
+ *
+ * @return: the ib_qp pointer on success, otherwise returns an errno.
+ */
+struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
+			       struct ib_qp_init_attr *init_attr,
+			       struct ib_udata *udata)
+{
+	struct pvrdma_qp *qp = NULL;
+	struct pvrdma_dev *dev = to_vdev(pd->device);
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_create_qp *cmd = &req.create_qp;
+	struct pvrdma_cmd_create_qp_resp *resp = &rsp.create_qp_resp;
+	struct pvrdma_create_qp ucmd;
+	unsigned long flags;
+	int ret;
+
+	if (init_attr->create_flags) {
+		dev_warn(&dev->pdev->dev,
+			 "invalid create queuepair flags %#x\n",
+			 init_attr->create_flags);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (init_attr->qp_type != IB_QPT_RC &&
+	    init_attr->qp_type != IB_QPT_UD &&
+	    init_attr->qp_type != IB_QPT_GSI) {
+		dev_warn(&dev->pdev->dev, "queuepair type %d not supported\n",
+			 init_attr->qp_type);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (!atomic_add_unless(&dev->num_qps, 1, dev->dsr->caps.max_qp))
+		return ERR_PTR(-ENOMEM);
+
+	switch (init_attr->qp_type) {
+	case IB_QPT_GSI:
+		if (init_attr->port_num == 0 ||
+		    init_attr->port_num > pd->device->phys_port_cnt ||
+		    udata) {
+			dev_warn(&dev->pdev->dev, "invalid queuepair attrs\n");
+			ret = -EINVAL;
+			goto err_qp;
+		}
+		/* fall through */
+	case IB_QPT_RC:
+	case IB_QPT_UD:
+		qp = kzalloc(sizeof(*qp), GFP_KERNEL);
+		if (!qp) {
+			ret = -ENOMEM;
+			goto err_qp;
+		}
+
+		spin_lock_init(&qp->sq.lock);
+		spin_lock_init(&qp->rq.lock);
+		mutex_init(&qp->mutex);
+		atomic_set(&qp->refcnt, 1);
+		init_waitqueue_head(&qp->wait);
+
+		qp->state = IB_QPS_RESET;
+
+		if (pd->uobject && udata) {
+			dev_dbg(&dev->pdev->dev,
+				"create queuepair from user space\n");
+
+			if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) {
+				ret = -EFAULT;
+				goto err_qp;
+			}
+
+			/* set qp->sq.wqe_cnt, shift, buf_size.. */
+			qp->rumem = ib_umem_get(pd->uobject->context,
+						ucmd.rbuf_addr,
+						ucmd.rbuf_size, 0, 0);
+			if (IS_ERR(qp->rumem)) {
+				ret = PTR_ERR(qp->rumem);
+				goto err_qp;
+			}
+
+			qp->sumem = ib_umem_get(pd->uobject->context,
+						ucmd.sbuf_addr,
+						ucmd.sbuf_size, 0, 0);
+			if (IS_ERR(qp->sumem)) {
+				ib_umem_release(qp->rumem);
+				ret = PTR_ERR(qp->sumem);
+				goto err_qp;
+			}
+
+			qp->npages_send = ib_umem_page_count(qp->sumem);
+			qp->npages_recv = ib_umem_page_count(qp->rumem);
+			qp->npages = qp->npages_send + qp->npages_recv;
+		} else {
+			qp->is_kernel = true;
+
+			ret = pvrdma_set_sq_size(to_vdev(pd->device),
+						 &init_attr->cap,
+						 init_attr->qp_type, qp);
+			if (ret)
+				goto err_qp;
+
+			ret = pvrdma_set_rq_size(to_vdev(pd->device),
+						 &init_attr->cap, qp);
+			if (ret)
+				goto err_qp;
+
+			qp->npages = qp->npages_send + qp->npages_recv;
+
+			/* Skip header page. */
+			qp->sq.offset = PAGE_SIZE;
+
+			/* Recv queue pages are after send pages. */
+			qp->rq.offset = qp->npages_send * PAGE_SIZE;
+		}
+
+		if (qp->npages < 0 || qp->npages > PVRDMA_PAGE_DIR_MAX_PAGES) {
+			dev_warn(&dev->pdev->dev,
+				 "overflow pages in queuepair\n");
+			ret = -EINVAL;
+			goto err_umem;
+		}
+
+		ret = pvrdma_page_dir_init(dev, &qp->pdir, qp->npages,
+					   qp->is_kernel);
+		if (ret) {
+			dev_warn(&dev->pdev->dev,
+				 "could not allocate page directory\n");
+			goto err_umem;
+		}
+
+		if (!qp->is_kernel) {
+			pvrdma_page_dir_insert_umem(&qp->pdir, qp->sumem, 0);
+			pvrdma_page_dir_insert_umem(&qp->pdir, qp->rumem,
+						    qp->npages_send);
+		} else {
+			/* Ring state is always the first page. */
+			qp->sq.ring = qp->pdir.pages[0];
+			qp->rq.ring = &qp->sq.ring[1];
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_qp;
+	}
+
+	/* Not supported */
+	init_attr->cap.max_inline_data = 0;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_CREATE_QP;
+	cmd->pd_handle = to_vpd(pd)->pd_handle;
+	cmd->send_cq_handle = to_vcq(init_attr->send_cq)->cq_handle;
+	cmd->recv_cq_handle = to_vcq(init_attr->recv_cq)->cq_handle;
+	cmd->max_send_wr = init_attr->cap.max_send_wr;
+	cmd->max_recv_wr = init_attr->cap.max_recv_wr;
+	cmd->max_send_sge = init_attr->cap.max_send_sge;
+	cmd->max_recv_sge = init_attr->cap.max_recv_sge;
+	cmd->max_inline_data = init_attr->cap.max_inline_data;
+	cmd->sq_sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ? 1 : 0;
+	cmd->qp_type = ib_qp_type_to_pvrdma(init_attr->qp_type);
+	cmd->access_flags = IB_ACCESS_LOCAL_WRITE;
+	cmd->total_chunks = qp->npages;
+	cmd->send_chunks = qp->npages_send - 1;
+	cmd->pdir_dma = qp->pdir.dir_dma;
+
+	dev_dbg(&dev->pdev->dev, "create queuepair with %d, %d, %d, %d\n",
+		cmd->max_send_wr, cmd->max_recv_wr, cmd->max_send_sge,
+		cmd->max_recv_sge);
+
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_QP_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not create queuepair, error: %d\n", ret);
+		goto err_pdir;
+	}
+
+	/* max_send_wr/_recv_wr/_send_sge/_recv_sge/_inline_data */
+	qp->qp_handle = resp->qpn;
+	qp->port = init_attr->port_num;
+	qp->ibqp.qp_num = resp->qpn;
+	spin_lock_irqsave(&dev->qp_tbl_lock, flags);
+	dev->qp_tbl[qp->qp_handle % dev->dsr->caps.max_qp] = qp;
+	spin_unlock_irqrestore(&dev->qp_tbl_lock, flags);
+
+	return &qp->ibqp;
+
+err_pdir:
+	pvrdma_page_dir_cleanup(dev, &qp->pdir);
+err_umem:
+	if (pd->uobject && udata) {
+		if (qp->rumem)
+			ib_umem_release(qp->rumem);
+		if (qp->sumem)
+			ib_umem_release(qp->sumem);
+	}
+err_qp:
+	kfree(qp);
+	atomic_dec(&dev->num_qps);
+
+	return ERR_PTR(ret);
+}
+
+static void pvrdma_free_qp(struct pvrdma_qp *qp)
+{
+	struct pvrdma_dev *dev = to_vdev(qp->ibqp.device);
+	struct pvrdma_cq *scq;
+	struct pvrdma_cq *rcq;
+	unsigned long flags, scq_flags, rcq_flags;
+
+	/* In case cq is polling */
+	get_cqs(qp, &scq, &rcq);
+	pvrdma_lock_cqs(scq, rcq, &scq_flags, &rcq_flags);
+
+	_pvrdma_flush_cqe(qp, scq);
+	if (scq != rcq)
+		_pvrdma_flush_cqe(qp, rcq);
+
+	spin_lock_irqsave(&dev->qp_tbl_lock, flags);
+	dev->qp_tbl[qp->qp_handle] = NULL;
+	spin_unlock_irqrestore(&dev->qp_tbl_lock, flags);
+
+	pvrdma_unlock_cqs(scq, rcq, &scq_flags, &rcq_flags);
+
+	atomic_dec(&qp->refcnt);
+	wait_event(qp->wait, !atomic_read(&qp->refcnt));
+
+	pvrdma_page_dir_cleanup(dev, &qp->pdir);
+
+	kfree(qp);
+
+	atomic_dec(&dev->num_qps);
+}
+
+/**
+ * pvrdma_destroy_qp - destroy a queue pair
+ * @qp: the queue pair to destroy
+ *
+ * @return: 0 on success.
+ */
+int pvrdma_destroy_qp(struct ib_qp *qp)
+{
+	struct pvrdma_qp *vqp = to_vqp(qp);
+	union pvrdma_cmd_req req;
+	struct pvrdma_cmd_destroy_qp *cmd = &req.destroy_qp;
+	int ret;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_DESTROY_QP;
+	cmd->qp_handle = vqp->qp_handle;
+
+	ret = pvrdma_cmd_post(to_vdev(qp->device), &req, NULL, 0);
+	if (ret < 0)
+		dev_warn(&to_vdev(qp->device)->pdev->dev,
+			 "destroy queuepair failed, error: %d\n", ret);
+
+	pvrdma_free_qp(vqp);
+
+	return 0;
+}
+
+/**
+ * pvrdma_modify_qp - modify queue pair attributes
+ * @ibqp: the queue pair
+ * @attr: the new queue pair's attributes
+ * @attr_mask: attributes mask
+ * @udata: user data
+ *
+ * @returns 0 on success, otherwise returns an errno.
+ */
+int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		     int attr_mask, struct ib_udata *udata)
+{
+	struct pvrdma_dev *dev = to_vdev(ibqp->device);
+	struct pvrdma_qp *qp = to_vqp(ibqp);
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_modify_qp *cmd = &req.modify_qp;
+	int cur_state, next_state;
+	int ret;
+
+	/* Sanity checking. Should need lock here */
+	mutex_lock(&qp->mutex);
+	cur_state = (attr_mask & IB_QP_CUR_STATE) ? attr->cur_qp_state :
+		qp->state;
+	next_state = (attr_mask & IB_QP_STATE) ? attr->qp_state : cur_state;
+
+	if (!ib_modify_qp_is_ok(cur_state, next_state, ibqp->qp_type,
+				attr_mask, IB_LINK_LAYER_ETHERNET)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (attr_mask & IB_QP_PORT) {
+		if (attr->port_num == 0 ||
+		    attr->port_num > ibqp->device->phys_port_cnt) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	if (attr_mask & IB_QP_MIN_RNR_TIMER) {
+		if (attr->min_rnr_timer > 31) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	if (attr_mask & IB_QP_PKEY_INDEX) {
+		if (attr->pkey_index >= dev->dsr->caps.max_pkeys) {
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	if (attr_mask & IB_QP_QKEY)
+		qp->qkey = attr->qkey;
+
+	if (cur_state == next_state && cur_state == IB_QPS_RESET) {
+		ret = 0;
+		goto out;
+	}
+
+	qp->state = next_state;
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_MODIFY_QP;
+	cmd->qp_handle = qp->qp_handle;
+	cmd->attr_mask = ib_qp_attr_mask_to_pvrdma(attr_mask);
+	cmd->attrs.qp_state = ib_qp_state_to_pvrdma(attr->qp_state);
+	cmd->attrs.cur_qp_state =
+		ib_qp_state_to_pvrdma(attr->cur_qp_state);
+	cmd->attrs.path_mtu = ib_mtu_to_pvrdma(attr->path_mtu);
+	cmd->attrs.path_mig_state =
+		ib_mig_state_to_pvrdma(attr->path_mig_state);
+	cmd->attrs.qkey = attr->qkey;
+	cmd->attrs.rq_psn = attr->rq_psn;
+	cmd->attrs.sq_psn = attr->sq_psn;
+	cmd->attrs.dest_qp_num = attr->dest_qp_num;
+	cmd->attrs.qp_access_flags =
+		ib_access_flags_to_pvrdma(attr->qp_access_flags);
+	cmd->attrs.pkey_index = attr->pkey_index;
+	cmd->attrs.alt_pkey_index = attr->alt_pkey_index;
+	cmd->attrs.en_sqd_async_notify = attr->en_sqd_async_notify;
+	cmd->attrs.sq_draining = attr->sq_draining;
+	cmd->attrs.max_rd_atomic = attr->max_rd_atomic;
+	cmd->attrs.max_dest_rd_atomic = attr->max_dest_rd_atomic;
+	cmd->attrs.min_rnr_timer = attr->min_rnr_timer;
+	cmd->attrs.port_num = attr->port_num;
+	cmd->attrs.timeout = attr->timeout;
+	cmd->attrs.retry_cnt = attr->retry_cnt;
+	cmd->attrs.rnr_retry = attr->rnr_retry;
+	cmd->attrs.alt_port_num = attr->alt_port_num;
+	cmd->attrs.alt_timeout = attr->alt_timeout;
+	ib_qp_cap_to_pvrdma(&cmd->attrs.cap, &attr->cap);
+	ib_ah_attr_to_pvrdma(&cmd->attrs.ah_attr, &attr->ah_attr);
+	ib_ah_attr_to_pvrdma(&cmd->attrs.alt_ah_attr, &attr->alt_ah_attr);
+
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_MODIFY_QP_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not modify queuepair, error: %d\n", ret);
+	} else if (rsp.hdr.err > 0) {
+		dev_warn(&dev->pdev->dev,
+			 "cannot modify queuepair, error: %d\n", rsp.hdr.err);
+		ret = -EINVAL;
+	}
+
+	if (ret == 0 && next_state == IB_QPS_RESET)
+		pvrdma_reset_qp(qp);
+
+out:
+	mutex_unlock(&qp->mutex);
+
+	return ret;
+}
+
+static inline void *get_sq_wqe(struct pvrdma_qp *qp, int n)
+{
+	return pvrdma_page_dir_get_ptr(&qp->pdir,
+				       qp->sq.offset + n * qp->sq.wqe_size);
+}
+
+static inline void *get_rq_wqe(struct pvrdma_qp *qp, int n)
+{
+	return pvrdma_page_dir_get_ptr(&qp->pdir,
+				       qp->rq.offset + n * qp->rq.wqe_size);
+}
+
+static int set_reg_seg(struct pvrdma_sq_wqe_hdr *wqe_hdr, struct ib_reg_wr *wr)
+{
+	struct pvrdma_user_mr *mr = to_vmr(wr->mr);
+
+	wqe_hdr->wr.fast_reg.iova_start = mr->ibmr.iova;
+	wqe_hdr->wr.fast_reg.pl_pdir_dma = mr->pdir.dir_dma;
+	wqe_hdr->wr.fast_reg.page_shift = mr->page_shift;
+	wqe_hdr->wr.fast_reg.page_list_len = mr->npages;
+	wqe_hdr->wr.fast_reg.length = mr->ibmr.length;
+	wqe_hdr->wr.fast_reg.access_flags = wr->access;
+	wqe_hdr->wr.fast_reg.rkey = wr->key;
+
+	return pvrdma_page_dir_insert_page_list(&mr->pdir, mr->pages,
+						mr->npages);
+}
+
+/**
+ * pvrdma_post_send - post send work request entries on a QP
+ * @ibqp: the QP
+ * @wr: work request list to post
+ * @bad_wr: the first bad WR returned
+ *
+ * @return: 0 on success, otherwise errno returned.
+ */
+int pvrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+		     struct ib_send_wr **bad_wr)
+{
+	struct pvrdma_qp *qp = to_vqp(ibqp);
+	struct pvrdma_dev *dev = to_vdev(ibqp->device);
+	unsigned long flags;
+	struct pvrdma_sq_wqe_hdr *wqe_hdr;
+	struct pvrdma_sge *sge;
+	int i, index;
+	int nreq;
+	int ret;
+
+	/*
+	 * In states lower than RTS, we can fail immediately. In other states,
+	 * just post and let the device figure it out.
+	 */
+	if (qp->state < IB_QPS_RTS) {
+		*bad_wr = wr;
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&qp->sq.lock, flags);
+
+	index = pvrdma_idx(&qp->sq.ring->prod_tail, qp->sq.wqe_cnt);
+	for (nreq = 0; wr; nreq++, wr = wr->next) {
+		unsigned int tail;
+
+		if (unlikely(!pvrdma_idx_ring_has_space(
+				qp->sq.ring, qp->sq.wqe_cnt, &tail))) {
+			dev_warn_ratelimited(&dev->pdev->dev,
+					     "send queue is full\n");
+			*bad_wr = wr;
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		if (unlikely(wr->num_sge > qp->sq.max_sg || wr->num_sge < 0)) {
+			dev_warn_ratelimited(&dev->pdev->dev,
+					     "send SGE overflow\n");
+			*bad_wr = wr;
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (unlikely(wr->opcode < 0)) {
+			dev_warn_ratelimited(&dev->pdev->dev,
+					     "invalid send opcode\n");
+			*bad_wr = wr;
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/*
+		 * Only support UD, RC.
+		 * Need to check opcode table for thorough checking.
+		 * opcode		_UD	_UC	_RC
+		 * _SEND		x	x	x
+		 * _SEND_WITH_IMM	x	x	x
+		 * _RDMA_WRITE			x	x
+		 * _RDMA_WRITE_WITH_IMM		x	x
+		 * _LOCAL_INV			x	x
+		 * _SEND_WITH_INV		x	x
+		 * _RDMA_READ				x
+		 * _ATOMIC_CMP_AND_SWP			x
+		 * _ATOMIC_FETCH_AND_ADD		x
+		 * _MASK_ATOMIC_CMP_AND_SWP		x
+		 * _MASK_ATOMIC_FETCH_AND_ADD		x
+		 * _REG_MR				x
+		 *
+		 */
+		if (qp->ibqp.qp_type != IB_QPT_UD &&
+		    qp->ibqp.qp_type != IB_QPT_RC &&
+			wr->opcode != IB_WR_SEND) {
+			dev_warn_ratelimited(&dev->pdev->dev,
+					     "unsupported queuepair type\n");
+			*bad_wr = wr;
+			ret = -EINVAL;
+			goto out;
+		} else if (qp->ibqp.qp_type == IB_QPT_UD ||
+			   qp->ibqp.qp_type == IB_QPT_GSI) {
+			if (wr->opcode != IB_WR_SEND &&
+			    wr->opcode != IB_WR_SEND_WITH_IMM) {
+				dev_warn_ratelimited(&dev->pdev->dev,
+						     "invalid send opcode\n");
+				*bad_wr = wr;
+				ret = -EINVAL;
+				goto out;
+			}
+		}
+
+		wqe_hdr = (struct pvrdma_sq_wqe_hdr *)get_sq_wqe(qp, index);
+		memset(wqe_hdr, 0, sizeof(*wqe_hdr));
+		wqe_hdr->wr_id = wr->wr_id;
+		wqe_hdr->num_sge = wr->num_sge;
+		wqe_hdr->opcode = ib_wr_opcode_to_pvrdma(wr->opcode);
+		wqe_hdr->send_flags = ib_send_flags_to_pvrdma(wr->send_flags);
+		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+			wqe_hdr->ex.imm_data = wr->ex.imm_data;
+
+		switch (qp->ibqp.qp_type) {
+		case IB_QPT_GSI:
+		case IB_QPT_UD:
+			if (unlikely(!ud_wr(wr)->ah)) {
+				dev_warn_ratelimited(&dev->pdev->dev,
+						     "invalid address handle\n");
+				*bad_wr = wr;
+				ret = -EINVAL;
+				goto out;
+			}
+
+			/*
+			 * Use qkey from qp context if high order bit set,
+			 * otherwise from work request.
+			 */
+			wqe_hdr->wr.ud.remote_qpn = ud_wr(wr)->remote_qpn;
+			wqe_hdr->wr.ud.remote_qkey =
+				ud_wr(wr)->remote_qkey & 0x80000000 ?
+				qp->qkey : ud_wr(wr)->remote_qkey;
+			wqe_hdr->wr.ud.av = to_vah(ud_wr(wr)->ah)->av;
+
+			break;
+		case IB_QPT_RC:
+			switch (wr->opcode) {
+			case IB_WR_RDMA_READ:
+			case IB_WR_RDMA_WRITE:
+			case IB_WR_RDMA_WRITE_WITH_IMM:
+				wqe_hdr->wr.rdma.remote_addr =
+					rdma_wr(wr)->remote_addr;
+				wqe_hdr->wr.rdma.rkey = rdma_wr(wr)->rkey;
+				break;
+			case IB_WR_LOCAL_INV:
+			case IB_WR_SEND_WITH_INV:
+				wqe_hdr->ex.invalidate_rkey =
+					wr->ex.invalidate_rkey;
+				break;
+			case IB_WR_ATOMIC_CMP_AND_SWP:
+			case IB_WR_ATOMIC_FETCH_AND_ADD:
+				wqe_hdr->wr.atomic.remote_addr =
+					atomic_wr(wr)->remote_addr;
+				wqe_hdr->wr.atomic.rkey = atomic_wr(wr)->rkey;
+				wqe_hdr->wr.atomic.compare_add =
+					atomic_wr(wr)->compare_add;
+				if (wr->opcode == IB_WR_ATOMIC_CMP_AND_SWP)
+					wqe_hdr->wr.atomic.swap =
+						atomic_wr(wr)->swap;
+				break;
+			case IB_WR_REG_MR:
+				ret = set_reg_seg(wqe_hdr, reg_wr(wr));
+				if (ret < 0) {
+					dev_warn_ratelimited(&dev->pdev->dev,
+							     "Failed to set fast register work request\n");
+					*bad_wr = wr;
+					goto out;
+				}
+				break;
+			default:
+				break;
+			}
+
+			break;
+		default:
+			dev_warn_ratelimited(&dev->pdev->dev,
+					     "invalid queuepair type\n");
+			ret = -EINVAL;
+			*bad_wr = wr;
+			goto out;
+		}
+
+		sge = (struct pvrdma_sge *)(wqe_hdr + 1);
+		for (i = 0; i < wr->num_sge; i++) {
+			/* Need to check wqe_size 0 or max size */
+			sge->addr = wr->sg_list[i].addr;
+			sge->length = wr->sg_list[i].length;
+			sge->lkey = wr->sg_list[i].lkey;
+			sge++;
+		}
+
+		/* Make sure wqe is written before index update */
+		smp_wmb();
+
+		index++;
+		if (unlikely(index >= qp->sq.wqe_cnt))
+			index = 0;
+		/* Update shared sq ring */
+		pvrdma_idx_ring_inc(&qp->sq.ring->prod_tail,
+				    qp->sq.wqe_cnt);
+	}
+
+	ret = 0;
+
+out:
+	spin_unlock_irqrestore(&qp->sq.lock, flags);
+
+	if (!ret)
+		pvrdma_write_uar_qp(dev, PVRDMA_UAR_QP_SEND | qp->qp_handle);
+
+	return ret;
+}
+
+/**
+ * pvrdma_post_receive - post receive work request entries on a QP
+ * @ibqp: the QP
+ * @wr: the work request list to post
+ * @bad_wr: the first bad WR returned
+ *
+ * @return: 0 on success, otherwise errno returned.
+ */
+int pvrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+		     struct ib_recv_wr **bad_wr)
+{
+	struct pvrdma_dev *dev = to_vdev(ibqp->device);
+	unsigned long flags;
+	struct pvrdma_qp *qp = to_vqp(ibqp);
+	struct pvrdma_rq_wqe_hdr *wqe_hdr;
+	struct pvrdma_sge *sge;
+	int index, nreq;
+	int ret = 0;
+	int i;
+
+	/*
+	 * In the RESET state, we can fail immediately. For other states,
+	 * just post and let the device figure it out.
+	 */
+	if (qp->state == IB_QPS_RESET) {
+		*bad_wr = wr;
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&qp->rq.lock, flags);
+
+	index = pvrdma_idx(&qp->rq.ring->prod_tail, qp->rq.wqe_cnt);
+	for (nreq = 0; wr; nreq++, wr = wr->next) {
+		unsigned int tail;
+
+		if (unlikely(wr->num_sge > qp->rq.max_sg ||
+			     wr->num_sge < 0)) {
+			ret = -EINVAL;
+			*bad_wr = wr;
+			dev_warn_ratelimited(&dev->pdev->dev,
+					     "recv SGE overflow\n");
+			goto out;
+		}
+
+		if (unlikely(!pvrdma_idx_ring_has_space(
+				qp->rq.ring, qp->rq.wqe_cnt, &tail))) {
+			ret = -ENOMEM;
+			*bad_wr = wr;
+			dev_warn_ratelimited(&dev->pdev->dev,
+					     "recv queue full\n");
+			goto out;
+		}
+
+		wqe_hdr = (struct pvrdma_rq_wqe_hdr *)get_rq_wqe(qp, index);
+		wqe_hdr->wr_id = wr->wr_id;
+		wqe_hdr->num_sge = wr->num_sge;
+		wqe_hdr->total_len = 0;
+
+		sge = (struct pvrdma_sge *)(wqe_hdr + 1);
+		for (i = 0; i < wr->num_sge; i++) {
+			sge->addr = wr->sg_list[i].addr;
+			sge->length = wr->sg_list[i].length;
+			sge->lkey = wr->sg_list[i].lkey;
+			sge++;
+		}
+
+		/* Make sure wqe is written before index update */
+		smp_wmb();
+
+		index++;
+		if (unlikely(index >= qp->rq.wqe_cnt))
+			index = 0;
+		/* Update shared rq ring */
+		pvrdma_idx_ring_inc(&qp->rq.ring->prod_tail,
+				    qp->rq.wqe_cnt);
+	}
+
+	spin_unlock_irqrestore(&qp->rq.lock, flags);
+
+	pvrdma_write_uar_qp(dev, PVRDMA_UAR_QP_RECV | qp->qp_handle);
+
+	return ret;
+
+out:
+	spin_unlock_irqrestore(&qp->rq.lock, flags);
+
+	return ret;
+}
+
+/**
+ * pvrdma_query_qp - query a queue pair's attributes
+ * @ibqp: the queue pair to query
+ * @attr: the queue pair's attributes
+ * @attr_mask: attributes mask
+ * @init_attr: initial queue pair attributes
+ *
+ * @returns 0 on success, otherwise returns an errno.
+ */
+int pvrdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		    int attr_mask, struct ib_qp_init_attr *init_attr)
+{
+	struct pvrdma_dev *dev = to_vdev(ibqp->device);
+	struct pvrdma_qp *qp = to_vqp(ibqp);
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_query_qp *cmd = &req.query_qp;
+	struct pvrdma_cmd_query_qp_resp *resp = &rsp.query_qp_resp;
+	int ret = 0;
+
+	mutex_lock(&qp->mutex);
+
+	if (qp->state == IB_QPS_RESET) {
+		attr->qp_state = IB_QPS_RESET;
+		goto out;
+	}
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_QUERY_QP;
+	cmd->qp_handle = qp->qp_handle;
+	cmd->attr_mask = ib_qp_attr_mask_to_pvrdma(attr_mask);
+
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_QUERY_QP_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not query queuepair, error: %d\n", ret);
+		goto out;
+	}
+
+	attr->qp_state = pvrdma_qp_state_to_ib(resp->attrs.qp_state);
+	attr->cur_qp_state =
+		pvrdma_qp_state_to_ib(resp->attrs.cur_qp_state);
+	attr->path_mtu = pvrdma_mtu_to_ib(resp->attrs.path_mtu);
+	attr->path_mig_state =
+		pvrdma_mig_state_to_ib(resp->attrs.path_mig_state);
+	attr->qkey = resp->attrs.qkey;
+	attr->rq_psn = resp->attrs.rq_psn;
+	attr->sq_psn = resp->attrs.sq_psn;
+	attr->dest_qp_num = resp->attrs.dest_qp_num;
+	attr->qp_access_flags =
+		pvrdma_access_flags_to_ib(resp->attrs.qp_access_flags);
+	attr->pkey_index = resp->attrs.pkey_index;
+	attr->alt_pkey_index = resp->attrs.alt_pkey_index;
+	attr->en_sqd_async_notify = resp->attrs.en_sqd_async_notify;
+	attr->sq_draining = resp->attrs.sq_draining;
+	attr->max_rd_atomic = resp->attrs.max_rd_atomic;
+	attr->max_dest_rd_atomic = resp->attrs.max_dest_rd_atomic;
+	attr->min_rnr_timer = resp->attrs.min_rnr_timer;
+	attr->port_num = resp->attrs.port_num;
+	attr->timeout = resp->attrs.timeout;
+	attr->retry_cnt = resp->attrs.retry_cnt;
+	attr->rnr_retry = resp->attrs.rnr_retry;
+	attr->alt_port_num = resp->attrs.alt_port_num;
+	attr->alt_timeout = resp->attrs.alt_timeout;
+	pvrdma_qp_cap_to_ib(&attr->cap, &resp->attrs.cap);
+	pvrdma_ah_attr_to_ib(&attr->ah_attr, &resp->attrs.ah_attr);
+	pvrdma_ah_attr_to_ib(&attr->alt_ah_attr, &resp->attrs.alt_ah_attr);
+
+	qp->state = attr->qp_state;
+
+	ret = 0;
+
+out:
+	attr->cur_qp_state = attr->qp_state;
+
+	init_attr->event_handler = qp->ibqp.event_handler;
+	init_attr->qp_context = qp->ibqp.qp_context;
+	init_attr->send_cq = qp->ibqp.send_cq;
+	init_attr->recv_cq = qp->ibqp.recv_cq;
+	init_attr->srq = qp->ibqp.srq;
+	init_attr->xrcd = NULL;
+	init_attr->cap = attr->cap;
+	init_attr->sq_sig_type = 0;
+	init_attr->qp_type = qp->ibqp.qp_type;
+	init_attr->create_flags = 0;
+	init_attr->port_num = qp->port;
+
+	mutex_unlock(&qp->mutex);
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_ring.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PVRDMA_RING_H__
+#define __PVRDMA_RING_H__
+
+#include <linux/types.h>
+
+#define PVRDMA_INVALID_IDX	-1	/* Invalid index. */
+
+struct pvrdma_ring {
+	atomic_t prod_tail;	/* Producer tail. */
+	atomic_t cons_head;	/* Consumer head. */
+};
+
+struct pvrdma_ring_state {
+	struct pvrdma_ring tx;	/* Tx ring. */
+	struct pvrdma_ring rx;	/* Rx ring. */
+};
+
+static inline int pvrdma_idx_valid(__u32 idx, __u32 max_elems)
+{
+	/* Generates fewer instructions than a less-than. */
+	return (idx & ~((max_elems << 1) - 1)) == 0;
+}
+
+static inline __s32 pvrdma_idx(atomic_t *var, __u32 max_elems)
+{
+	const unsigned int idx = atomic_read(var);
+
+	if (pvrdma_idx_valid(idx, max_elems))
+		return idx & (max_elems - 1);
+	return PVRDMA_INVALID_IDX;
+}
+
+static inline void pvrdma_idx_ring_inc(atomic_t *var, __u32 max_elems)
+{
+	__u32 idx = atomic_read(var) + 1;	/* Increment. */
+
+	idx &= (max_elems << 1) - 1;		/* Modulo size, flip gen. */
+	atomic_set(var, idx);
+}
+
+static inline __s32 pvrdma_idx_ring_has_space(const struct pvrdma_ring *r,
+					      __u32 max_elems, __u32 *out_tail)
+{
+	const __u32 tail = atomic_read(&r->prod_tail);
+	const __u32 head = atomic_read(&r->cons_head);
+
+	if (pvrdma_idx_valid(tail, max_elems) &&
+	    pvrdma_idx_valid(head, max_elems)) {
+		*out_tail = tail & (max_elems - 1);
+		return tail != (head ^ max_elems);
+	}
+	return PVRDMA_INVALID_IDX;
+}
+
+static inline __s32 pvrdma_idx_ring_has_data(const struct pvrdma_ring *r,
+					     __u32 max_elems, __u32 *out_head)
+{
+	const __u32 tail = atomic_read(&r->prod_tail);
+	const __u32 head = atomic_read(&r->cons_head);
+
+	if (pvrdma_idx_valid(tail, max_elems) &&
+	    pvrdma_idx_valid(head, max_elems)) {
+		*out_head = head & (max_elems - 1);
+		return tail != head;
+	}
+	return PVRDMA_INVALID_IDX;
+}
+
+static inline bool pvrdma_idx_ring_is_valid_idx(const struct pvrdma_ring *r,
+						__u32 max_elems, __u32 *idx)
+{
+	const __u32 tail = atomic_read(&r->prod_tail);
+	const __u32 head = atomic_read(&r->cons_head);
+
+	if (pvrdma_idx_valid(tail, max_elems) &&
+	    pvrdma_idx_valid(head, max_elems) &&
+	    pvrdma_idx_valid(*idx, max_elems)) {
+		if (tail > head && (*idx < tail && *idx >= head))
+			return true;
+		else if (head > tail && (*idx >= head || *idx < tail))
+			return true;
+	}
+	return false;
+}
+
+#endif /* __PVRDMA_RING_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,579 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <asm/page.h>
+#include <linux/inet.h>
+#include <linux/io.h>
+#include <rdma/ib_addr.h>
+#include <rdma/ib_smi.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/vmw_pvrdma-abi.h>
+
+#include "pvrdma.h"
+
+/**
+ * pvrdma_query_device - query device
+ * @ibdev: the device to query
+ * @props: the device properties
+ * @uhw: user data
+ *
+ * @return: 0 on success, otherwise negative errno
+ */
+int pvrdma_query_device(struct ib_device *ibdev,
+			struct ib_device_attr *props,
+			struct ib_udata *uhw)
+{
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+
+	if (uhw->inlen || uhw->outlen)
+		return -EINVAL;
+
+	memset(props, 0, sizeof(*props));
+
+	props->fw_ver = dev->dsr->caps.fw_ver;
+	props->sys_image_guid = dev->dsr->caps.sys_image_guid;
+	props->max_mr_size = dev->dsr->caps.max_mr_size;
+	props->page_size_cap = dev->dsr->caps.page_size_cap;
+	props->vendor_id = dev->dsr->caps.vendor_id;
+	props->vendor_part_id = dev->pdev->device;
+	props->hw_ver = dev->dsr->caps.hw_ver;
+	props->max_qp = dev->dsr->caps.max_qp;
+	props->max_qp_wr = dev->dsr->caps.max_qp_wr;
+	props->device_cap_flags = dev->dsr->caps.device_cap_flags;
+	props->max_sge = dev->dsr->caps.max_sge;
+	props->max_cq = dev->dsr->caps.max_cq;
+	props->max_cqe = dev->dsr->caps.max_cqe;
+	props->max_mr = dev->dsr->caps.max_mr;
+	props->max_pd = dev->dsr->caps.max_pd;
+	props->max_qp_rd_atom = dev->dsr->caps.max_qp_rd_atom;
+	props->max_qp_init_rd_atom = dev->dsr->caps.max_qp_init_rd_atom;
+	props->atomic_cap =
+		dev->dsr->caps.atomic_ops &
+		(PVRDMA_ATOMIC_OP_COMP_SWAP | PVRDMA_ATOMIC_OP_FETCH_ADD) ?
+		IB_ATOMIC_HCA : IB_ATOMIC_NONE;
+	props->masked_atomic_cap = props->atomic_cap;
+	props->max_ah = dev->dsr->caps.max_ah;
+	props->max_pkeys = dev->dsr->caps.max_pkeys;
+	props->local_ca_ack_delay = dev->dsr->caps.local_ca_ack_delay;
+	if ((dev->dsr->caps.bmme_flags & PVRDMA_BMME_FLAG_LOCAL_INV) &&
+	    (dev->dsr->caps.bmme_flags & PVRDMA_BMME_FLAG_REMOTE_INV) &&
+	    (dev->dsr->caps.bmme_flags & PVRDMA_BMME_FLAG_FAST_REG_WR)) {
+		props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+	}
+
+	return 0;
+}
+
+/**
+ * pvrdma_query_port - query device port attributes
+ * @ibdev: the device to query
+ * @port: the port number
+ * @props: the device properties
+ *
+ * @return: 0 on success, otherwise negative errno
+ */
+int pvrdma_query_port(struct ib_device *ibdev, u8 port,
+		      struct ib_port_attr *props)
+{
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_query_port *cmd = &req.query_port;
+	struct pvrdma_cmd_query_port_resp *resp = &rsp.query_port_resp;
+	int err;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_QUERY_PORT;
+	cmd->port_num = port;
+
+	err = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_QUERY_PORT_RESP);
+	if (err < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "could not query port, error: %d\n", err);
+		return err;
+	}
+
+	memset(props, 0, sizeof(*props));
+
+	props->state = pvrdma_port_state_to_ib(resp->attrs.state);
+	props->max_mtu = pvrdma_mtu_to_ib(resp->attrs.max_mtu);
+	props->active_mtu = pvrdma_mtu_to_ib(resp->attrs.active_mtu);
+	props->gid_tbl_len = resp->attrs.gid_tbl_len;
+	props->port_cap_flags =
+		pvrdma_port_cap_flags_to_ib(resp->attrs.port_cap_flags);
+	props->max_msg_sz = resp->attrs.max_msg_sz;
+	props->bad_pkey_cntr = resp->attrs.bad_pkey_cntr;
+	props->qkey_viol_cntr = resp->attrs.qkey_viol_cntr;
+	props->pkey_tbl_len = resp->attrs.pkey_tbl_len;
+	props->lid = resp->attrs.lid;
+	props->sm_lid = resp->attrs.sm_lid;
+	props->lmc = resp->attrs.lmc;
+	props->max_vl_num = resp->attrs.max_vl_num;
+	props->sm_sl = resp->attrs.sm_sl;
+	props->subnet_timeout = resp->attrs.subnet_timeout;
+	props->init_type_reply = resp->attrs.init_type_reply;
+	props->active_width = pvrdma_port_width_to_ib(resp->attrs.active_width);
+	props->active_speed = pvrdma_port_speed_to_ib(resp->attrs.active_speed);
+	props->phys_state = resp->attrs.phys_state;
+
+	return 0;
+}
+
+/**
+ * pvrdma_query_gid - query device gid
+ * @ibdev: the device to query
+ * @port: the port number
+ * @index: the index
+ * @gid: the device gid value
+ *
+ * @return: 0 on success, otherwise negative errno
+ */
+int pvrdma_query_gid(struct ib_device *ibdev, u8 port, int index,
+		     union ib_gid *gid)
+{
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+
+	if (index >= dev->dsr->caps.gid_tbl_len)
+		return -EINVAL;
+
+	memcpy(gid, &dev->sgid_tbl[index], sizeof(union ib_gid));
+
+	return 0;
+}
+
+/**
+ * pvrdma_query_pkey - query device port's P_Key table
+ * @ibdev: the device to query
+ * @port: the port number
+ * @index: the index
+ * @pkey: the device P_Key value
+ *
+ * @return: 0 on success, otherwise negative errno
+ */
+int pvrdma_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
+		      u16 *pkey)
+{
+	int err = 0;
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_query_pkey *cmd = &req.query_pkey;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_QUERY_PKEY;
+	cmd->port_num = port;
+	cmd->index = index;
+
+	err = pvrdma_cmd_post(to_vdev(ibdev), &req, &rsp,
+			      PVRDMA_CMD_QUERY_PKEY_RESP);
+	if (err < 0) {
+		dev_warn(&to_vdev(ibdev)->pdev->dev,
+			 "could not query pkey, error: %d\n", err);
+		return err;
+	}
+
+	*pkey = rsp.query_pkey_resp.pkey;
+
+	return 0;
+}
+
+enum rdma_link_layer pvrdma_port_link_layer(struct ib_device *ibdev,
+					    u8 port)
+{
+	return IB_LINK_LAYER_ETHERNET;
+}
+
+int pvrdma_modify_device(struct ib_device *ibdev, int mask,
+			 struct ib_device_modify *props)
+{
+	unsigned long flags;
+
+	if (mask & ~(IB_DEVICE_MODIFY_SYS_IMAGE_GUID |
+		     IB_DEVICE_MODIFY_NODE_DESC)) {
+		dev_warn(&to_vdev(ibdev)->pdev->dev,
+			 "unsupported device modify mask %#x\n", mask);
+		return -EOPNOTSUPP;
+	}
+
+	if (mask & IB_DEVICE_MODIFY_NODE_DESC) {
+		spin_lock_irqsave(&to_vdev(ibdev)->desc_lock, flags);
+		memcpy(ibdev->node_desc, props->node_desc, 64);
+		spin_unlock_irqrestore(&to_vdev(ibdev)->desc_lock, flags);
+	}
+
+	if (mask & IB_DEVICE_MODIFY_SYS_IMAGE_GUID) {
+		mutex_lock(&to_vdev(ibdev)->port_mutex);
+		to_vdev(ibdev)->sys_image_guid =
+			cpu_to_be64(props->sys_image_guid);
+		mutex_unlock(&to_vdev(ibdev)->port_mutex);
+	}
+
+	return 0;
+}
+
+/**
+ * pvrdma_modify_port - modify device port attributes
+ * @ibdev: the device to modify
+ * @port: the port number
+ * @mask: attributes to modify
+ * @props: the device properties
+ *
+ * @return: 0 on success, otherwise negative errno
+ */
+int pvrdma_modify_port(struct ib_device *ibdev, u8 port, int mask,
+		       struct ib_port_modify *props)
+{
+	struct ib_port_attr attr;
+	struct pvrdma_dev *vdev = to_vdev(ibdev);
+	int ret;
+
+	if (mask & ~IB_PORT_SHUTDOWN) {
+		dev_warn(&vdev->pdev->dev,
+			 "unsupported port modify mask %#x\n", mask);
+		return -EOPNOTSUPP;
+	}
+
+	mutex_lock(&vdev->port_mutex);
+	ret = pvrdma_query_port(ibdev, port, &attr);
+	if (ret)
+		goto out;
+
+	vdev->port_cap_mask |= props->set_port_cap_mask;
+	vdev->port_cap_mask &= ~props->clr_port_cap_mask;
+
+	if (mask & IB_PORT_SHUTDOWN)
+		vdev->ib_active = false;
+
+out:
+	mutex_unlock(&vdev->port_mutex);
+	return ret;
+}
+
+/**
+ * pvrdma_alloc_ucontext - allocate ucontext
+ * @ibdev: the IB device
+ * @udata: user data
+ *
+ * @return: the ib_ucontext pointer on success, otherwise errno.
+ */
+struct ib_ucontext *pvrdma_alloc_ucontext(struct ib_device *ibdev,
+					  struct ib_udata *udata)
+{
+	struct pvrdma_dev *vdev = to_vdev(ibdev);
+	struct pvrdma_ucontext *context;
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_create_uc *cmd = &req.create_uc;
+	struct pvrdma_cmd_create_uc_resp *resp = &rsp.create_uc_resp;
+	struct pvrdma_alloc_ucontext_resp uresp = {0};
+	int ret;
+	void *ptr;
+
+	if (!vdev->ib_active)
+		return ERR_PTR(-EAGAIN);
+
+	context = kmalloc(sizeof(*context), GFP_KERNEL);
+	if (!context)
+		return ERR_PTR(-ENOMEM);
+
+	context->dev = vdev;
+	ret = pvrdma_uar_alloc(vdev, &context->uar);
+	if (ret) {
+		kfree(context);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* get ctx_handle from host */
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->pfn = context->uar.pfn;
+	cmd->hdr.cmd = PVRDMA_CMD_CREATE_UC;
+	ret = pvrdma_cmd_post(vdev, &req, &rsp, PVRDMA_CMD_CREATE_UC_RESP);
+	if (ret < 0) {
+		dev_warn(&vdev->pdev->dev,
+			 "could not create ucontext, error: %d\n", ret);
+		ptr = ERR_PTR(ret);
+		goto err;
+	}
+
+	context->ctx_handle = resp->ctx_handle;
+
+	/* copy back to user */
+	uresp.qp_tab_size = vdev->dsr->caps.max_qp;
+	ret = ib_copy_to_udata(udata, &uresp, sizeof(uresp));
+	if (ret) {
+		pvrdma_uar_free(vdev, &context->uar);
+		context->ibucontext.device = ibdev;
+		pvrdma_dealloc_ucontext(&context->ibucontext);
+		return ERR_PTR(-EFAULT);
+	}
+
+	return &context->ibucontext;
+
+err:
+	pvrdma_uar_free(vdev, &context->uar);
+	kfree(context);
+	return ptr;
+}
+
+/**
+ * pvrdma_dealloc_ucontext - deallocate ucontext
+ * @ibcontext: the ucontext
+ *
+ * @return: 0 on success, otherwise errno.
+ */
+int pvrdma_dealloc_ucontext(struct ib_ucontext *ibcontext)
+{
+	struct pvrdma_ucontext *context = to_vucontext(ibcontext);
+	union pvrdma_cmd_req req;
+	struct pvrdma_cmd_destroy_uc *cmd = &req.destroy_uc;
+	int ret;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_DESTROY_UC;
+	cmd->ctx_handle = context->ctx_handle;
+
+	ret = pvrdma_cmd_post(context->dev, &req, NULL, 0);
+	if (ret < 0)
+		dev_warn(&context->dev->pdev->dev,
+			 "destroy ucontext failed, error: %d\n", ret);
+
+	/* Free the UAR even if the device command failed */
+	pvrdma_uar_free(to_vdev(ibcontext->device), &context->uar);
+	kfree(context);
+
+	return ret;
+}
+
+/**
+ * pvrdma_mmap - create mmap region
+ * @ibcontext: the user context
+ * @vma: the VMA
+ *
+ * @return: 0 on success, otherwise errno.
+ */
+int pvrdma_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
+{
+	struct pvrdma_ucontext *context = to_vucontext(ibcontext);
+	unsigned long start = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+	dev_dbg(&context->dev->pdev->dev, "create mmap region\n");
+
+	if ((size != PAGE_SIZE) || (offset & ~PAGE_MASK)) {
+		dev_warn(&context->dev->pdev->dev,
+			 "invalid params for mmap region\n");
+		return -EINVAL;
+	}
+
+	/* Map UAR to kernel space, VM_LOCKED? */
+	vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	if (io_remap_pfn_range(vma, start, context->uar.pfn, size,
+			       vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
+
+/**
+ * pvrdma_alloc_pd - allocate protection domain
+ * @ibdev: the IB device
+ * @context: user context
+ * @udata: user data
+ *
+ * @return: the ib_pd protection domain pointer on success, otherwise errno.
+ */
+struct ib_pd *pvrdma_alloc_pd(struct ib_device *ibdev,
+			      struct ib_ucontext *context,
+			      struct ib_udata *udata)
+{
+	struct pvrdma_pd *pd;
+	struct pvrdma_dev *dev = to_vdev(ibdev);
+	union pvrdma_cmd_req req;
+	union pvrdma_cmd_resp rsp;
+	struct pvrdma_cmd_create_pd *cmd = &req.create_pd;
+	struct pvrdma_cmd_create_pd_resp *resp = &rsp.create_pd_resp;
+	int ret;
+	void *ptr;
+
+	/* Check allowed max pds */
+	if (!atomic_add_unless(&dev->num_pds, 1, dev->dsr->caps.max_pd))
+		return ERR_PTR(-ENOMEM);
+
+	pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+	if (!pd) {
+		ptr = ERR_PTR(-ENOMEM);
+		goto err;
+	}
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_CREATE_PD;
+	cmd->ctx_handle = (context) ? to_vucontext(context)->ctx_handle : 0;
+	ret = pvrdma_cmd_post(dev, &req, &rsp, PVRDMA_CMD_CREATE_PD_RESP);
+	if (ret < 0) {
+		dev_warn(&dev->pdev->dev,
+			 "failed to allocate protection domain, error: %d\n",
+			 ret);
+		ptr = ERR_PTR(ret);
+		goto freepd;
+	}
+
+	pd->privileged = !context;
+	pd->pd_handle = resp->pd_handle;
+	pd->pdn = resp->pd_handle;
+
+	if (context) {
+		if (ib_copy_to_udata(udata, &pd->pdn, sizeof(__u32))) {
+			dev_warn(&dev->pdev->dev,
+				 "failed to copy back protection domain\n");
+			pvrdma_dealloc_pd(&pd->ibpd);
+			return ERR_PTR(-EFAULT);
+		}
+	}
+
+	/* u32 pd handle */
+	return &pd->ibpd;
+
+freepd:
+	kfree(pd);
+err:
+	atomic_dec(&dev->num_pds);
+	return ptr;
+}
+
+/**
+ * pvrdma_dealloc_pd - deallocate protection domain
+ * @pd: the protection domain to be released
+ *
+ * @return: 0 on success, otherwise errno.
+ */
+int pvrdma_dealloc_pd(struct ib_pd *pd)
+{
+	struct pvrdma_dev *dev = to_vdev(pd->device);
+	union pvrdma_cmd_req req;
+	struct pvrdma_cmd_destroy_pd *cmd = &req.destroy_pd;
+	int ret;
+
+	memset(cmd, 0, sizeof(*cmd));
+	cmd->hdr.cmd = PVRDMA_CMD_DESTROY_PD;
+	cmd->pd_handle = to_vpd(pd)->pd_handle;
+
+	ret = pvrdma_cmd_post(dev, &req, NULL, 0);
+	if (ret)
+		dev_warn(&dev->pdev->dev,
+			 "could not dealloc protection domain, error: %d\n",
+			 ret);
+
+	kfree(to_vpd(pd));
+	atomic_dec(&dev->num_pds);
+
+	return 0;
+}
+
+/**
+ * pvrdma_create_ah - create an address handle
+ * @pd: the protection domain
+ * @ah_attr: the attributes of the AH
+ * @udata: user data blob
+ *
+ * @return: the ib_ah pointer on success, otherwise errno.
+ */
+struct ib_ah *pvrdma_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+			       struct ib_udata *udata)
+{
+	struct pvrdma_dev *dev = to_vdev(pd->device);
+	struct pvrdma_ah *ah;
+	enum rdma_link_layer ll;
+
+	if (!(ah_attr->ah_flags & IB_AH_GRH))
+		return ERR_PTR(-EINVAL);
+
+	ll = rdma_port_get_link_layer(pd->device, ah_attr->port_num);
+
+	if (ll != IB_LINK_LAYER_ETHERNET ||
+	    rdma_is_multicast_addr((struct in6_addr *)ah_attr->grh.dgid.raw))
+		return ERR_PTR(-EINVAL);
+
+	if (!atomic_add_unless(&dev->num_ahs, 1, dev->dsr->caps.max_ah))
+		return ERR_PTR(-ENOMEM);
+
+	ah = kzalloc(sizeof(*ah), GFP_KERNEL);
+	if (!ah) {
+		atomic_dec(&dev->num_ahs);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ah->av.port_pd = to_vpd(pd)->pd_handle | (ah_attr->port_num << 24);
+	ah->av.src_path_bits = ah_attr->src_path_bits;
+	ah->av.src_path_bits |= 0x80;
+	ah->av.gid_index = ah_attr->grh.sgid_index;
+	ah->av.hop_limit = ah_attr->grh.hop_limit;
+	ah->av.sl_tclass_flowlabel = (ah_attr->grh.traffic_class << 20) |
+				      ah_attr->grh.flow_label;
+	memcpy(ah->av.dgid, ah_attr->grh.dgid.raw, 16);
+	memcpy(ah->av.dmac, ah_attr->dmac, 6);
+
+	ah->ibah.device = pd->device;
+	ah->ibah.pd = pd;
+	ah->ibah.uobject = NULL;
+
+	return &ah->ibah;
+}
+
+/**
+ * pvrdma_destroy_ah - destroy an address handle
+ * @ah: the address handle to destroyed
+ *
+ * @return: 0 on success.
+ */
+int pvrdma_destroy_ah(struct ib_ah *ah)
+{
+	struct pvrdma_dev *dev = to_vdev(ah->device);
+
+	kfree(to_vah(ah));
+	atomic_dec(&dev->num_ahs);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h
--- linux-libre-4.9-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/hw/vmw_pvrdma/pvrdma_verbs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2012-2016 VMware, Inc.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of EITHER the GNU General Public License
+ * version 2 as published by the Free Software Foundation or the BSD
+ * 2-Clause 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 version 2 for more details at
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program available in the file COPYING in the main
+ * directory of this source tree.
+ *
+ * The BSD 2-Clause License
+ *
+ *     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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PVRDMA_VERBS_H__
+#define __PVRDMA_VERBS_H__
+
+#include <linux/types.h>
+
+union pvrdma_gid {
+	u8	raw[16];
+	struct {
+		__be64	subnet_prefix;
+		__be64	interface_id;
+	} global;
+};
+
+enum pvrdma_link_layer {
+	PVRDMA_LINK_LAYER_UNSPECIFIED,
+	PVRDMA_LINK_LAYER_INFINIBAND,
+	PVRDMA_LINK_LAYER_ETHERNET,
+};
+
+enum pvrdma_mtu {
+	PVRDMA_MTU_256  = 1,
+	PVRDMA_MTU_512  = 2,
+	PVRDMA_MTU_1024 = 3,
+	PVRDMA_MTU_2048 = 4,
+	PVRDMA_MTU_4096 = 5,
+};
+
+static inline int pvrdma_mtu_enum_to_int(enum pvrdma_mtu mtu)
+{
+	switch (mtu) {
+	case PVRDMA_MTU_256:	return  256;
+	case PVRDMA_MTU_512:	return  512;
+	case PVRDMA_MTU_1024:	return 1024;
+	case PVRDMA_MTU_2048:	return 2048;
+	case PVRDMA_MTU_4096:	return 4096;
+	default:		return   -1;
+	}
+}
+
+static inline enum pvrdma_mtu pvrdma_mtu_int_to_enum(int mtu)
+{
+	switch (mtu) {
+	case 256:	return PVRDMA_MTU_256;
+	case 512:	return PVRDMA_MTU_512;
+	case 1024:	return PVRDMA_MTU_1024;
+	case 2048:	return PVRDMA_MTU_2048;
+	case 4096:
+	default:	return PVRDMA_MTU_4096;
+	}
+}
+
+enum pvrdma_port_state {
+	PVRDMA_PORT_NOP			= 0,
+	PVRDMA_PORT_DOWN		= 1,
+	PVRDMA_PORT_INIT		= 2,
+	PVRDMA_PORT_ARMED		= 3,
+	PVRDMA_PORT_ACTIVE		= 4,
+	PVRDMA_PORT_ACTIVE_DEFER	= 5,
+};
+
+enum pvrdma_port_cap_flags {
+	PVRDMA_PORT_SM				= 1 <<  1,
+	PVRDMA_PORT_NOTICE_SUP			= 1 <<  2,
+	PVRDMA_PORT_TRAP_SUP			= 1 <<  3,
+	PVRDMA_PORT_OPT_IPD_SUP			= 1 <<  4,
+	PVRDMA_PORT_AUTO_MIGR_SUP		= 1 <<  5,
+	PVRDMA_PORT_SL_MAP_SUP			= 1 <<  6,
+	PVRDMA_PORT_MKEY_NVRAM			= 1 <<  7,
+	PVRDMA_PORT_PKEY_NVRAM			= 1 <<  8,
+	PVRDMA_PORT_LED_INFO_SUP		= 1 <<  9,
+	PVRDMA_PORT_SM_DISABLED			= 1 << 10,
+	PVRDMA_PORT_SYS_IMAGE_GUID_SUP		= 1 << 11,
+	PVRDMA_PORT_PKEY_SW_EXT_PORT_TRAP_SUP	= 1 << 12,
+	PVRDMA_PORT_EXTENDED_SPEEDS_SUP		= 1 << 14,
+	PVRDMA_PORT_CM_SUP			= 1 << 16,
+	PVRDMA_PORT_SNMP_TUNNEL_SUP		= 1 << 17,
+	PVRDMA_PORT_REINIT_SUP			= 1 << 18,
+	PVRDMA_PORT_DEVICE_MGMT_SUP		= 1 << 19,
+	PVRDMA_PORT_VENDOR_CLASS_SUP		= 1 << 20,
+	PVRDMA_PORT_DR_NOTICE_SUP		= 1 << 21,
+	PVRDMA_PORT_CAP_MASK_NOTICE_SUP		= 1 << 22,
+	PVRDMA_PORT_BOOT_MGMT_SUP		= 1 << 23,
+	PVRDMA_PORT_LINK_LATENCY_SUP		= 1 << 24,
+	PVRDMA_PORT_CLIENT_REG_SUP		= 1 << 25,
+	PVRDMA_PORT_IP_BASED_GIDS		= 1 << 26,
+	PVRDMA_PORT_CAP_FLAGS_MAX		= PVRDMA_PORT_IP_BASED_GIDS,
+};
+
+enum pvrdma_port_width {
+	PVRDMA_WIDTH_1X		= 1,
+	PVRDMA_WIDTH_4X		= 2,
+	PVRDMA_WIDTH_8X		= 4,
+	PVRDMA_WIDTH_12X	= 8,
+};
+
+static inline int pvrdma_width_enum_to_int(enum pvrdma_port_width width)
+{
+	switch (width) {
+	case PVRDMA_WIDTH_1X:	return  1;
+	case PVRDMA_WIDTH_4X:	return  4;
+	case PVRDMA_WIDTH_8X:	return  8;
+	case PVRDMA_WIDTH_12X:	return 12;
+	default:		return -1;
+	}
+}
+
+enum pvrdma_port_speed {
+	PVRDMA_SPEED_SDR	= 1,
+	PVRDMA_SPEED_DDR	= 2,
+	PVRDMA_SPEED_QDR	= 4,
+	PVRDMA_SPEED_FDR10	= 8,
+	PVRDMA_SPEED_FDR	= 16,
+	PVRDMA_SPEED_EDR	= 32,
+};
+
+struct pvrdma_port_attr {
+	enum pvrdma_port_state	state;
+	enum pvrdma_mtu		max_mtu;
+	enum pvrdma_mtu		active_mtu;
+	u32			gid_tbl_len;
+	u32			port_cap_flags;
+	u32			max_msg_sz;
+	u32			bad_pkey_cntr;
+	u32			qkey_viol_cntr;
+	u16			pkey_tbl_len;
+	u16			lid;
+	u16			sm_lid;
+	u8			lmc;
+	u8			max_vl_num;
+	u8			sm_sl;
+	u8			subnet_timeout;
+	u8			init_type_reply;
+	u8			active_width;
+	u8			active_speed;
+	u8			phys_state;
+	u8			reserved[2];
+};
+
+struct pvrdma_global_route {
+	union pvrdma_gid	dgid;
+	u32			flow_label;
+	u8			sgid_index;
+	u8			hop_limit;
+	u8			traffic_class;
+	u8			reserved;
+};
+
+struct pvrdma_grh {
+	__be32			version_tclass_flow;
+	__be16			paylen;
+	u8			next_hdr;
+	u8			hop_limit;
+	union pvrdma_gid	sgid;
+	union pvrdma_gid	dgid;
+};
+
+enum pvrdma_ah_flags {
+	PVRDMA_AH_GRH = 1,
+};
+
+enum pvrdma_rate {
+	PVRDMA_RATE_PORT_CURRENT	= 0,
+	PVRDMA_RATE_2_5_GBPS		= 2,
+	PVRDMA_RATE_5_GBPS		= 5,
+	PVRDMA_RATE_10_GBPS		= 3,
+	PVRDMA_RATE_20_GBPS		= 6,
+	PVRDMA_RATE_30_GBPS		= 4,
+	PVRDMA_RATE_40_GBPS		= 7,
+	PVRDMA_RATE_60_GBPS		= 8,
+	PVRDMA_RATE_80_GBPS		= 9,
+	PVRDMA_RATE_120_GBPS		= 10,
+	PVRDMA_RATE_14_GBPS		= 11,
+	PVRDMA_RATE_56_GBPS		= 12,
+	PVRDMA_RATE_112_GBPS		= 13,
+	PVRDMA_RATE_168_GBPS		= 14,
+	PVRDMA_RATE_25_GBPS		= 15,
+	PVRDMA_RATE_100_GBPS		= 16,
+	PVRDMA_RATE_200_GBPS		= 17,
+	PVRDMA_RATE_300_GBPS		= 18,
+};
+
+struct pvrdma_ah_attr {
+	struct pvrdma_global_route	grh;
+	u16				dlid;
+	u16				vlan_id;
+	u8				sl;
+	u8				src_path_bits;
+	u8				static_rate;
+	u8				ah_flags;
+	u8				port_num;
+	u8				dmac[6];
+	u8				reserved;
+};
+
+enum pvrdma_cq_notify_flags {
+	PVRDMA_CQ_SOLICITED		= 1 << 0,
+	PVRDMA_CQ_NEXT_COMP		= 1 << 1,
+	PVRDMA_CQ_SOLICITED_MASK	= PVRDMA_CQ_SOLICITED |
+					  PVRDMA_CQ_NEXT_COMP,
+	PVRDMA_CQ_REPORT_MISSED_EVENTS	= 1 << 2,
+};
+
+struct pvrdma_qp_cap {
+	u32	max_send_wr;
+	u32	max_recv_wr;
+	u32	max_send_sge;
+	u32	max_recv_sge;
+	u32	max_inline_data;
+	u32	reserved;
+};
+
+enum pvrdma_sig_type {
+	PVRDMA_SIGNAL_ALL_WR,
+	PVRDMA_SIGNAL_REQ_WR,
+};
+
+enum pvrdma_qp_type {
+	PVRDMA_QPT_SMI,
+	PVRDMA_QPT_GSI,
+	PVRDMA_QPT_RC,
+	PVRDMA_QPT_UC,
+	PVRDMA_QPT_UD,
+	PVRDMA_QPT_RAW_IPV6,
+	PVRDMA_QPT_RAW_ETHERTYPE,
+	PVRDMA_QPT_RAW_PACKET = 8,
+	PVRDMA_QPT_XRC_INI = 9,
+	PVRDMA_QPT_XRC_TGT,
+	PVRDMA_QPT_MAX,
+};
+
+enum pvrdma_qp_create_flags {
+	PVRDMA_QP_CREATE_IPOPVRDMA_UD_LSO		= 1 << 0,
+	PVRDMA_QP_CREATE_BLOCK_MULTICAST_LOOPBACK	= 1 << 1,
+};
+
+enum pvrdma_qp_attr_mask {
+	PVRDMA_QP_STATE			= 1 << 0,
+	PVRDMA_QP_CUR_STATE		= 1 << 1,
+	PVRDMA_QP_EN_SQD_ASYNC_NOTIFY	= 1 << 2,
+	PVRDMA_QP_ACCESS_FLAGS		= 1 << 3,
+	PVRDMA_QP_PKEY_INDEX		= 1 << 4,
+	PVRDMA_QP_PORT			= 1 << 5,
+	PVRDMA_QP_QKEY			= 1 << 6,
+	PVRDMA_QP_AV			= 1 << 7,
+	PVRDMA_QP_PATH_MTU		= 1 << 8,
+	PVRDMA_QP_TIMEOUT		= 1 << 9,
+	PVRDMA_QP_RETRY_CNT		= 1 << 10,
+	PVRDMA_QP_RNR_RETRY		= 1 << 11,
+	PVRDMA_QP_RQ_PSN		= 1 << 12,
+	PVRDMA_QP_MAX_QP_RD_ATOMIC	= 1 << 13,
+	PVRDMA_QP_ALT_PATH		= 1 << 14,
+	PVRDMA_QP_MIN_RNR_TIMER		= 1 << 15,
+	PVRDMA_QP_SQ_PSN		= 1 << 16,
+	PVRDMA_QP_MAX_DEST_RD_ATOMIC	= 1 << 17,
+	PVRDMA_QP_PATH_MIG_STATE	= 1 << 18,
+	PVRDMA_QP_CAP			= 1 << 19,
+	PVRDMA_QP_DEST_QPN		= 1 << 20,
+	PVRDMA_QP_ATTR_MASK_MAX		= PVRDMA_QP_DEST_QPN,
+};
+
+enum pvrdma_qp_state {
+	PVRDMA_QPS_RESET,
+	PVRDMA_QPS_INIT,
+	PVRDMA_QPS_RTR,
+	PVRDMA_QPS_RTS,
+	PVRDMA_QPS_SQD,
+	PVRDMA_QPS_SQE,
+	PVRDMA_QPS_ERR,
+};
+
+enum pvrdma_mig_state {
+	PVRDMA_MIG_MIGRATED,
+	PVRDMA_MIG_REARM,
+	PVRDMA_MIG_ARMED,
+};
+
+enum pvrdma_mw_type {
+	PVRDMA_MW_TYPE_1 = 1,
+	PVRDMA_MW_TYPE_2 = 2,
+};
+
+struct pvrdma_qp_attr {
+	enum pvrdma_qp_state	qp_state;
+	enum pvrdma_qp_state	cur_qp_state;
+	enum pvrdma_mtu		path_mtu;
+	enum pvrdma_mig_state	path_mig_state;
+	u32			qkey;
+	u32			rq_psn;
+	u32			sq_psn;
+	u32			dest_qp_num;
+	u32			qp_access_flags;
+	u16			pkey_index;
+	u16			alt_pkey_index;
+	u8			en_sqd_async_notify;
+	u8			sq_draining;
+	u8			max_rd_atomic;
+	u8			max_dest_rd_atomic;
+	u8			min_rnr_timer;
+	u8			port_num;
+	u8			timeout;
+	u8			retry_cnt;
+	u8			rnr_retry;
+	u8			alt_port_num;
+	u8			alt_timeout;
+	u8			reserved[5];
+	struct pvrdma_qp_cap	cap;
+	struct pvrdma_ah_attr	ah_attr;
+	struct pvrdma_ah_attr	alt_ah_attr;
+};
+
+enum pvrdma_send_flags {
+	PVRDMA_SEND_FENCE	= 1 << 0,
+	PVRDMA_SEND_SIGNALED	= 1 << 1,
+	PVRDMA_SEND_SOLICITED	= 1 << 2,
+	PVRDMA_SEND_INLINE	= 1 << 3,
+	PVRDMA_SEND_IP_CSUM	= 1 << 4,
+	PVRDMA_SEND_FLAGS_MAX	= PVRDMA_SEND_IP_CSUM,
+};
+
+enum pvrdma_access_flags {
+	PVRDMA_ACCESS_LOCAL_WRITE	= 1 << 0,
+	PVRDMA_ACCESS_REMOTE_WRITE	= 1 << 1,
+	PVRDMA_ACCESS_REMOTE_READ	= 1 << 2,
+	PVRDMA_ACCESS_REMOTE_ATOMIC	= 1 << 3,
+	PVRDMA_ACCESS_MW_BIND		= 1 << 4,
+	PVRDMA_ZERO_BASED		= 1 << 5,
+	PVRDMA_ACCESS_ON_DEMAND		= 1 << 6,
+	PVRDMA_ACCESS_FLAGS_MAX		= PVRDMA_ACCESS_ON_DEMAND,
+};
+
+int pvrdma_query_device(struct ib_device *ibdev,
+			struct ib_device_attr *props,
+			struct ib_udata *udata);
+int pvrdma_query_port(struct ib_device *ibdev, u8 port,
+		      struct ib_port_attr *props);
+int pvrdma_query_gid(struct ib_device *ibdev, u8 port,
+		     int index, union ib_gid *gid);
+int pvrdma_query_pkey(struct ib_device *ibdev, u8 port,
+		      u16 index, u16 *pkey);
+enum rdma_link_layer pvrdma_port_link_layer(struct ib_device *ibdev,
+					    u8 port);
+int pvrdma_modify_device(struct ib_device *ibdev, int mask,
+			 struct ib_device_modify *props);
+int pvrdma_modify_port(struct ib_device *ibdev, u8 port,
+		       int mask, struct ib_port_modify *props);
+int pvrdma_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
+struct ib_ucontext *pvrdma_alloc_ucontext(struct ib_device *ibdev,
+					  struct ib_udata *udata);
+int pvrdma_dealloc_ucontext(struct ib_ucontext *context);
+struct ib_pd *pvrdma_alloc_pd(struct ib_device *ibdev,
+			      struct ib_ucontext *context,
+			      struct ib_udata *udata);
+int pvrdma_dealloc_pd(struct ib_pd *ibpd);
+struct ib_mr *pvrdma_get_dma_mr(struct ib_pd *pd, int acc);
+struct ib_mr *pvrdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+				 u64 virt_addr, int access_flags,
+				 struct ib_udata *udata);
+int pvrdma_dereg_mr(struct ib_mr *mr);
+struct ib_mr *pvrdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type,
+			      u32 max_num_sg);
+int pvrdma_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg,
+		     int sg_nents, unsigned int *sg_offset);
+int pvrdma_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period);
+int pvrdma_resize_cq(struct ib_cq *ibcq, int entries,
+		     struct ib_udata *udata);
+struct ib_cq *pvrdma_create_cq(struct ib_device *ibdev,
+			       const struct ib_cq_init_attr *attr,
+			       struct ib_ucontext *context,
+			       struct ib_udata *udata);
+int pvrdma_resize_cq(struct ib_cq *ibcq, int entries,
+		     struct ib_udata *udata);
+int pvrdma_destroy_cq(struct ib_cq *cq);
+int pvrdma_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc);
+int pvrdma_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify_flags flags);
+struct ib_ah *pvrdma_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+			       struct ib_udata *udata);
+int pvrdma_destroy_ah(struct ib_ah *ah);
+struct ib_qp *pvrdma_create_qp(struct ib_pd *pd,
+			       struct ib_qp_init_attr *init_attr,
+			       struct ib_udata *udata);
+int pvrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+		     int attr_mask, struct ib_udata *udata);
+int pvrdma_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr,
+		    int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr);
+int pvrdma_destroy_qp(struct ib_qp *qp);
+int pvrdma_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+		     struct ib_send_wr **bad_wr);
+int pvrdma_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+		     struct ib_recv_wr **bad_wr);
+
+#endif /* __PVRDMA_VERBS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/Kconfig linux-libre-4.10-rc8-gnu/drivers/infiniband/Kconfig
--- linux-libre-4.9-gnu/drivers/infiniband/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -73,6 +73,7 @@ source "drivers/infiniband/hw/mlx4/Kconf
 source "drivers/infiniband/hw/mlx5/Kconfig"
 source "drivers/infiniband/hw/nes/Kconfig"
 source "drivers/infiniband/hw/ocrdma/Kconfig"
+source "drivers/infiniband/hw/vmw_pvrdma/Kconfig"
 source "drivers/infiniband/hw/usnic/Kconfig"
 source "drivers/infiniband/hw/hns/Kconfig"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/cq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/cq.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/cq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/cq.c	2017-02-12 16:03:20.000000000 -0500
@@ -119,18 +119,17 @@ void rvt_cq_enter(struct rvt_cq *cq, str
 	if (cq->notify == IB_CQ_NEXT_COMP ||
 	    (cq->notify == IB_CQ_SOLICITED &&
 	     (solicited || entry->status != IB_WC_SUCCESS))) {
-		struct kthread_worker *worker;
 		/*
 		 * This will cause send_complete() to be called in
 		 * another thread.
 		 */
-		smp_read_barrier_depends(); /* see rvt_cq_exit */
-		worker = cq->rdi->worker;
-		if (likely(worker)) {
+		spin_lock(&cq->rdi->n_cqs_lock);
+		if (likely(cq->rdi->worker)) {
 			cq->notify = RVT_CQ_NONE;
 			cq->triggered++;
-			kthread_queue_work(worker, &cq->comptask);
+			kthread_queue_work(cq->rdi->worker, &cq->comptask);
 		}
+		spin_unlock(&cq->rdi->n_cqs_lock);
 	}
 
 	spin_unlock_irqrestore(&cq->lock, flags);
@@ -240,15 +239,15 @@ struct ib_cq *rvt_create_cq(struct ib_de
 		}
 	}
 
-	spin_lock(&rdi->n_cqs_lock);
+	spin_lock_irq(&rdi->n_cqs_lock);
 	if (rdi->n_cqs_allocated == rdi->dparms.props.max_cq) {
-		spin_unlock(&rdi->n_cqs_lock);
+		spin_unlock_irq(&rdi->n_cqs_lock);
 		ret = ERR_PTR(-ENOMEM);
 		goto bail_ip;
 	}
 
 	rdi->n_cqs_allocated++;
-	spin_unlock(&rdi->n_cqs_lock);
+	spin_unlock_irq(&rdi->n_cqs_lock);
 
 	if (cq->ip) {
 		spin_lock_irq(&rdi->pending_lock);
@@ -296,9 +295,9 @@ int rvt_destroy_cq(struct ib_cq *ibcq)
 	struct rvt_dev_info *rdi = cq->rdi;
 
 	kthread_flush_work(&cq->comptask);
-	spin_lock(&rdi->n_cqs_lock);
+	spin_lock_irq(&rdi->n_cqs_lock);
 	rdi->n_cqs_allocated--;
-	spin_unlock(&rdi->n_cqs_lock);
+	spin_unlock_irq(&rdi->n_cqs_lock);
 	if (cq->ip)
 		kref_put(&cq->ip->ref, rvt_release_mmap_info);
 	else
@@ -504,33 +503,23 @@ int rvt_poll_cq(struct ib_cq *ibcq, int
  */
 int rvt_driver_cq_init(struct rvt_dev_info *rdi)
 {
-	int ret = 0;
 	int cpu;
-	struct task_struct *task;
+	struct kthread_worker *worker;
 
 	if (rdi->worker)
 		return 0;
+
 	spin_lock_init(&rdi->n_cqs_lock);
-	rdi->worker = kzalloc(sizeof(*rdi->worker), GFP_KERNEL);
-	if (!rdi->worker)
-		return -ENOMEM;
-	kthread_init_worker(rdi->worker);
-	task = kthread_create_on_node(
-		kthread_worker_fn,
-		rdi->worker,
-		rdi->dparms.node,
-		"%s", rdi->dparms.cq_name);
-	if (IS_ERR(task)) {
-		kfree(rdi->worker);
-		rdi->worker = NULL;
-		return PTR_ERR(task);
-	}
 
-	set_user_nice(task, MIN_NICE);
 	cpu = cpumask_first(cpumask_of_node(rdi->dparms.node));
-	kthread_bind(task, cpu);
-	wake_up_process(task);
-	return ret;
+	worker = kthread_create_worker_on_cpu(cpu, 0,
+					      "%s", rdi->dparms.cq_name);
+	if (IS_ERR(worker))
+		return PTR_ERR(worker);
+
+	set_user_nice(worker->task, MIN_NICE);
+	rdi->worker = worker;
+	return 0;
 }
 
 /**
@@ -541,13 +530,15 @@ void rvt_cq_exit(struct rvt_dev_info *rd
 {
 	struct kthread_worker *worker;
 
+	/* block future queuing from send_complete() */
+	spin_lock_irq(&rdi->n_cqs_lock);
 	worker = rdi->worker;
-	if (!worker)
+	if (!worker) {
+		spin_unlock_irq(&rdi->n_cqs_lock);
 		return;
-	/* blocks future queuing from send_complete() */
+	}
 	rdi->worker = NULL;
-	smp_wmb(); /* See rdi_cq_enter */
-	kthread_flush_worker(worker);
-	kthread_stop(worker->task);
-	kfree(worker);
+	spin_unlock_irq(&rdi->n_cqs_lock);
+
+	kthread_destroy_worker(worker);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/mcast.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/mcast.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/mcast.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/mcast.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,7 +81,7 @@ static struct rvt_mcast_qp *rvt_mcast_qp
 		goto bail;
 
 	mqp->qp = qp;
-	atomic_inc(&qp->refcount);
+	rvt_get_qp(qp);
 
 bail:
 	return mqp;
@@ -92,8 +92,7 @@ static void rvt_mcast_qp_free(struct rvt
 	struct rvt_qp *qp = mqp->qp;
 
 	/* Notify hfi1_destroy_qp() if it is waiting. */
-	if (atomic_dec_and_test(&qp->refcount))
-		wake_up(&qp->wait);
+	rvt_put_qp(qp);
 
 	kfree(mqp);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/mr.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/mr.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/mr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/mr.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,6 +51,7 @@
 #include <rdma/rdma_vt.h>
 #include "vt.h"
 #include "mr.h"
+#include "trace.h"
 
 /**
  * rvt_driver_mr_init - Init MR resources per driver
@@ -84,6 +85,7 @@ int rvt_driver_mr_init(struct rvt_dev_in
 		lkey_table_size = rdi->dparms.lkey_table_size;
 	}
 	rdi->lkey_table.max = 1 << lkey_table_size;
+	rdi->lkey_table.shift = 32 - lkey_table_size;
 	lk_tab_size = rdi->lkey_table.max * sizeof(*rdi->lkey_table.table);
 	rdi->lkey_table.table = (struct rvt_mregion __rcu **)
 			       vmalloc_node(lk_tab_size, rdi->dparms.node);
@@ -402,6 +404,7 @@ struct ib_mr *rvt_reg_user_mr(struct ib_
 		}
 		mr->mr.map[m]->segs[n].vaddr = vaddr;
 		mr->mr.map[m]->segs[n].length = umem->page_size;
+		trace_rvt_mr_user_seg(&mr->mr, m, n, vaddr, umem->page_size);
 		n++;
 		if (n == RVT_SEGSZ) {
 			m++;
@@ -506,6 +509,7 @@ static int rvt_set_page(struct ib_mr *ib
 	n = mapped_segs % RVT_SEGSZ;
 	mr->mr.map[m]->segs[n].vaddr = (void *)addr;
 	mr->mr.map[m]->segs[n].length = ps;
+	trace_rvt_mr_page_seg(&mr->mr, m, n, (void *)addr, ps);
 	mr->mr.length += ps;
 
 	return 0;
@@ -692,6 +696,7 @@ int rvt_map_phys_fmr(struct ib_fmr *ibfm
 	for (i = 0; i < list_len; i++) {
 		fmr->mr.map[m]->segs[n].vaddr = (void *)page_list[i];
 		fmr->mr.map[m]->segs[n].length = ps;
+		trace_rvt_mr_fmr_seg(&fmr->mr, m, n, (void *)page_list[i], ps);
 		if (++n == RVT_SEGSZ) {
 			m++;
 			n = 0;
@@ -774,7 +779,6 @@ int rvt_lkey_ok(struct rvt_lkey_table *r
 	struct rvt_mregion *mr;
 	unsigned n, m;
 	size_t off;
-	struct rvt_dev_info *dev = ib_to_rvt(pd->ibpd.device);
 
 	/*
 	 * We use LKEY == zero for kernel virtual addresses
@@ -782,12 +786,14 @@ int rvt_lkey_ok(struct rvt_lkey_table *r
 	 */
 	rcu_read_lock();
 	if (sge->lkey == 0) {
+		struct rvt_dev_info *dev = ib_to_rvt(pd->ibpd.device);
+
 		if (pd->user)
 			goto bail;
 		mr = rcu_dereference(dev->dma_mr);
 		if (!mr)
 			goto bail;
-		atomic_inc(&mr->refcount);
+		rvt_get_mr(mr);
 		rcu_read_unlock();
 
 		isge->mr = mr;
@@ -798,8 +804,7 @@ int rvt_lkey_ok(struct rvt_lkey_table *r
 		isge->n = 0;
 		goto ok;
 	}
-	mr = rcu_dereference(
-		rkt->table[(sge->lkey >> (32 - dev->dparms.lkey_table_size))]);
+	mr = rcu_dereference(rkt->table[sge->lkey >> rkt->shift]);
 	if (unlikely(!mr || atomic_read(&mr->lkey_invalid) ||
 		     mr->lkey != sge->lkey || mr->pd != &pd->ibpd))
 		goto bail;
@@ -809,7 +814,7 @@ int rvt_lkey_ok(struct rvt_lkey_table *r
 		     off + sge->length > mr->length ||
 		     (mr->access_flags & acc) != acc))
 		goto bail;
-	atomic_inc(&mr->refcount);
+	rvt_get_mr(mr);
 	rcu_read_unlock();
 
 	off += mr->offset;
@@ -887,7 +892,7 @@ int rvt_rkey_ok(struct rvt_qp *qp, struc
 		mr = rcu_dereference(rdi->dma_mr);
 		if (!mr)
 			goto bail;
-		atomic_inc(&mr->refcount);
+		rvt_get_mr(mr);
 		rcu_read_unlock();
 
 		sge->mr = mr;
@@ -899,8 +904,7 @@ int rvt_rkey_ok(struct rvt_qp *qp, struc
 		goto ok;
 	}
 
-	mr = rcu_dereference(
-		rkt->table[(rkey >> (32 - dev->dparms.lkey_table_size))]);
+	mr = rcu_dereference(rkt->table[rkey >> rkt->shift]);
 	if (unlikely(!mr || atomic_read(&mr->lkey_invalid) ||
 		     mr->lkey != rkey || qp->ibqp.pd != mr->pd))
 		goto bail;
@@ -909,7 +913,7 @@ int rvt_rkey_ok(struct rvt_qp *qp, struc
 	if (unlikely(vaddr < mr->iova || off + len > mr->length ||
 		     (mr->access_flags & acc) == 0))
 		goto bail;
-	atomic_inc(&mr->refcount);
+	rvt_get_mr(mr);
 	rcu_read_unlock();
 
 	off += mr->offset;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/qp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -76,6 +76,23 @@ const int ib_rvt_state_ops[IB_QPS_ERR +
 };
 EXPORT_SYMBOL(ib_rvt_state_ops);
 
+/*
+ * Translate ib_wr_opcode into ib_wc_opcode.
+ */
+const enum ib_wc_opcode ib_rvt_wc_opcode[] = {
+	[IB_WR_RDMA_WRITE] = IB_WC_RDMA_WRITE,
+	[IB_WR_RDMA_WRITE_WITH_IMM] = IB_WC_RDMA_WRITE,
+	[IB_WR_SEND] = IB_WC_SEND,
+	[IB_WR_SEND_WITH_IMM] = IB_WC_SEND,
+	[IB_WR_RDMA_READ] = IB_WC_RDMA_READ,
+	[IB_WR_ATOMIC_CMP_AND_SWP] = IB_WC_COMP_SWAP,
+	[IB_WR_ATOMIC_FETCH_AND_ADD] = IB_WC_FETCH_ADD,
+	[IB_WR_SEND_WITH_INV] = IB_WC_SEND,
+	[IB_WR_LOCAL_INV] = IB_WC_LOCAL_INV,
+	[IB_WR_REG_MR] = IB_WC_REG_MR
+};
+EXPORT_SYMBOL(ib_rvt_wc_opcode);
+
 static void get_map_page(struct rvt_qpn_table *qpt,
 			 struct rvt_qpn_map *map,
 			 gfp_t gfp)
@@ -884,7 +901,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd
 	return ret;
 
 bail_ip:
-	kref_put(&qp->ip->ref, rvt_release_mmap_info);
+	if (qp->ip)
+		kref_put(&qp->ip->ref, rvt_release_mmap_info);
 
 bail_qpn:
 	free_qpn(&rdi->qp_dev->qpn_table, qp->ibqp.qp_num);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -45,143 +45,10 @@
  *
  */
 
-#undef TRACE_SYSTEM_VAR
-#define TRACE_SYSTEM_VAR rdmavt
-
-#if !defined(__RDMAVT_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
-#define __RDMAVT_TRACE_H
-
-#include <linux/tracepoint.h>
-#include <linux/trace_seq.h>
-
-#include <rdma/ib_verbs.h>
-#include <rdma/rdma_vt.h>
-
 #define RDI_DEV_ENTRY(rdi)   __string(dev, rdi->driver_f.get_card_name(rdi))
 #define RDI_DEV_ASSIGN(rdi)  __assign_str(dev, rdi->driver_f.get_card_name(rdi))
 
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM rdmavt
-
-TRACE_EVENT(rvt_dbg,
-	TP_PROTO(struct rvt_dev_info *rdi,
-		 const char *msg),
-	TP_ARGS(rdi, msg),
-	TP_STRUCT__entry(
-		RDI_DEV_ENTRY(rdi)
-		__string(msg, msg)
-	),
-	TP_fast_assign(
-		RDI_DEV_ASSIGN(rdi);
-		__assign_str(msg, msg);
-	),
-	TP_printk("[%s]: %s", __get_str(dev), __get_str(msg))
-);
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM rvt_qphash
-DECLARE_EVENT_CLASS(rvt_qphash_template,
-	TP_PROTO(struct rvt_qp *qp, u32 bucket),
-	TP_ARGS(qp, bucket),
-	TP_STRUCT__entry(
-		RDI_DEV_ENTRY(ib_to_rvt(qp->ibqp.device))
-		__field(u32, qpn)
-		__field(u32, bucket)
-	),
-	TP_fast_assign(
-		RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device))
-		__entry->qpn = qp->ibqp.qp_num;
-		__entry->bucket = bucket;
-	),
-	TP_printk(
-		"[%s] qpn 0x%x bucket %u",
-		__get_str(dev),
-		__entry->qpn,
-		__entry->bucket
-	)
-);
-
-DEFINE_EVENT(rvt_qphash_template, rvt_qpinsert,
-	TP_PROTO(struct rvt_qp *qp, u32 bucket),
-	TP_ARGS(qp, bucket));
-
-DEFINE_EVENT(rvt_qphash_template, rvt_qpremove,
-	TP_PROTO(struct rvt_qp *qp, u32 bucket),
-	TP_ARGS(qp, bucket));
-
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM rvt_tx
-
-#define wr_opcode_name(opcode) { IB_WR_##opcode, #opcode  }
-#define show_wr_opcode(opcode)                             \
-__print_symbolic(opcode,                                   \
-	wr_opcode_name(RDMA_WRITE),                        \
-	wr_opcode_name(RDMA_WRITE_WITH_IMM),               \
-	wr_opcode_name(SEND),                              \
-	wr_opcode_name(SEND_WITH_IMM),                     \
-	wr_opcode_name(RDMA_READ),                         \
-	wr_opcode_name(ATOMIC_CMP_AND_SWP),                \
-	wr_opcode_name(ATOMIC_FETCH_AND_ADD),              \
-	wr_opcode_name(LSO),                               \
-	wr_opcode_name(SEND_WITH_INV),                     \
-	wr_opcode_name(RDMA_READ_WITH_INV),                \
-	wr_opcode_name(LOCAL_INV),                         \
-	wr_opcode_name(MASKED_ATOMIC_CMP_AND_SWP),         \
-	wr_opcode_name(MASKED_ATOMIC_FETCH_AND_ADD))
-
-#define POS_PRN \
-"[%s] wr_id %llx qpn %x psn 0x%x lpsn 0x%x length %u opcode 0x%.2x,%s size %u avail %u head %u last %u"
-
-TRACE_EVENT(
-	rvt_post_one_wr,
-	TP_PROTO(struct rvt_qp *qp, struct rvt_swqe *wqe),
-	TP_ARGS(qp, wqe),
-	TP_STRUCT__entry(
-		RDI_DEV_ENTRY(ib_to_rvt(qp->ibqp.device))
-		__field(u64, wr_id)
-		__field(u32, qpn)
-		__field(u32, psn)
-		__field(u32, lpsn)
-		__field(u32, length)
-		__field(u32, opcode)
-		__field(u32, size)
-		__field(u32, avail)
-		__field(u32, head)
-		__field(u32, last)
-	),
-	TP_fast_assign(
-		RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device))
-		__entry->wr_id = wqe->wr.wr_id;
-		__entry->qpn = qp->ibqp.qp_num;
-		__entry->psn = wqe->psn;
-		__entry->lpsn = wqe->lpsn;
-		__entry->length = wqe->length;
-		__entry->opcode = wqe->wr.opcode;
-		__entry->size = qp->s_size;
-		__entry->avail = qp->s_avail;
-		__entry->head = qp->s_head;
-		__entry->last = qp->s_last;
-	),
-	TP_printk(
-		POS_PRN,
-		__get_str(dev),
-		__entry->wr_id,
-		__entry->qpn,
-		__entry->psn,
-		__entry->lpsn,
-		__entry->length,
-		__entry->opcode, show_wr_opcode(__entry->opcode),
-		__entry->size,
-		__entry->avail,
-		__entry->head,
-		__entry->last
-	)
-);
-
-#endif /* __RDMAVT_TRACE_H */
-
-#undef TRACE_INCLUDE_PATH
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE trace
-#include <trace/define_trace.h>
+#include "trace_rvt.h"
+#include "trace_qp.h"
+#include "trace_tx.h"
+#include "trace_mr.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_mr.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_mr.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_mr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_mr.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,112 @@
+/*
+ * Copyright(c) 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  - Neither the name of Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#if !defined(__RVT_TRACE_MR_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __RVT_TRACE_MR_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/rdma_vt.h>
+#include <rdma/rdmavt_mr.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM rvt_mr
+DECLARE_EVENT_CLASS(
+	rvt_mr_template,
+	TP_PROTO(struct rvt_mregion *mr, u16 m, u16 n, void *v, size_t len),
+	TP_ARGS(mr, m, n, v, len),
+	TP_STRUCT__entry(
+		RDI_DEV_ENTRY(ib_to_rvt(mr->pd->device))
+		__field(void *, vaddr)
+		__field(struct page *, page)
+		__field(size_t, len)
+		__field(u32, lkey)
+		__field(u16, m)
+		__field(u16, n)
+	),
+	TP_fast_assign(
+		RDI_DEV_ASSIGN(ib_to_rvt(mr->pd->device));
+		__entry->vaddr = v;
+		__entry->page = virt_to_page(v);
+		__entry->m = m;
+		__entry->n = n;
+		__entry->len = len;
+	),
+	TP_printk(
+		"[%s] vaddr %p page %p m %u n %u len %ld",
+		__get_str(dev),
+		__entry->vaddr,
+		__entry->page,
+		__entry->m,
+		__entry->n,
+		__entry->len
+	)
+);
+
+DEFINE_EVENT(
+	rvt_mr_template, rvt_mr_page_seg,
+	TP_PROTO(struct rvt_mregion *mr, u16 m, u16 n, void *v, size_t len),
+	TP_ARGS(mr, m, n, v, len));
+
+DEFINE_EVENT(
+	rvt_mr_template, rvt_mr_fmr_seg,
+	TP_PROTO(struct rvt_mregion *mr, u16 m, u16 n, void *v, size_t len),
+	TP_ARGS(mr, m, n, v, len));
+
+DEFINE_EVENT(
+	rvt_mr_template, rvt_mr_user_seg,
+	TP_PROTO(struct rvt_mregion *mr, u16 m, u16 n, void *v, size_t len),
+	TP_ARGS(mr, m, n, v, len));
+
+#endif /* __RVT_TRACE_MR_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_mr
+#include <trace/define_trace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_qp.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_qp.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_qp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_qp.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright(c) 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  - Neither the name of Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#if !defined(__RVT_TRACE_QP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __RVT_TRACE_QP_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/rdma_vt.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM rvt_qp
+
+DECLARE_EVENT_CLASS(rvt_qphash_template,
+	TP_PROTO(struct rvt_qp *qp, u32 bucket),
+	TP_ARGS(qp, bucket),
+	TP_STRUCT__entry(
+		RDI_DEV_ENTRY(ib_to_rvt(qp->ibqp.device))
+		__field(u32, qpn)
+		__field(u32, bucket)
+	),
+	TP_fast_assign(
+		RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device))
+		__entry->qpn = qp->ibqp.qp_num;
+		__entry->bucket = bucket;
+	),
+	TP_printk(
+		"[%s] qpn 0x%x bucket %u",
+		__get_str(dev),
+		__entry->qpn,
+		__entry->bucket
+	)
+);
+
+DEFINE_EVENT(rvt_qphash_template, rvt_qpinsert,
+	TP_PROTO(struct rvt_qp *qp, u32 bucket),
+	TP_ARGS(qp, bucket));
+
+DEFINE_EVENT(rvt_qphash_template, rvt_qpremove,
+	TP_PROTO(struct rvt_qp *qp, u32 bucket),
+	TP_ARGS(qp, bucket));
+
+
+#endif /* __RVT_TRACE_QP_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_qp
+#include <trace/define_trace.h>
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_rvt.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_rvt.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_rvt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_rvt.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,81 @@
+/*
+ * Copyright(c) 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  - Neither the name of Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#if !defined(__RVT_TRACE_RVT_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __RVT_TRACE_RVT_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/rdma_vt.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM rvt
+
+TRACE_EVENT(rvt_dbg,
+	TP_PROTO(struct rvt_dev_info *rdi,
+		 const char *msg),
+	TP_ARGS(rdi, msg),
+	TP_STRUCT__entry(
+		RDI_DEV_ENTRY(rdi)
+		__string(msg, msg)
+	),
+	TP_fast_assign(
+		RDI_DEV_ASSIGN(rdi);
+		__assign_str(msg, msg);
+	),
+	TP_printk("[%s]: %s", __get_str(dev), __get_str(msg))
+);
+
+#endif /* __RVT_TRACE_MISC_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_rvt
+#include <trace/define_trace.h>
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_tx.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_tx.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rdmavt/trace_tx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rdmavt/trace_tx.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,132 @@
+/*
+ * Copyright(c) 2016 Intel Corporation.
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  - Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  - Neither the name of Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#if !defined(__RVT_TRACE_TX_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __RVT_TRACE_TX_H
+
+#include <linux/tracepoint.h>
+#include <linux/trace_seq.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/rdma_vt.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM rvt_tx
+
+#define wr_opcode_name(opcode) { IB_WR_##opcode, #opcode  }
+#define show_wr_opcode(opcode)                             \
+__print_symbolic(opcode,                                   \
+	wr_opcode_name(RDMA_WRITE),                        \
+	wr_opcode_name(RDMA_WRITE_WITH_IMM),               \
+	wr_opcode_name(SEND),                              \
+	wr_opcode_name(SEND_WITH_IMM),                     \
+	wr_opcode_name(RDMA_READ),                         \
+	wr_opcode_name(ATOMIC_CMP_AND_SWP),                \
+	wr_opcode_name(ATOMIC_FETCH_AND_ADD),              \
+	wr_opcode_name(LSO),                               \
+	wr_opcode_name(SEND_WITH_INV),                     \
+	wr_opcode_name(RDMA_READ_WITH_INV),                \
+	wr_opcode_name(LOCAL_INV),                         \
+	wr_opcode_name(MASKED_ATOMIC_CMP_AND_SWP),         \
+	wr_opcode_name(MASKED_ATOMIC_FETCH_AND_ADD))
+
+#define POS_PRN \
+"[%s] wr_id %llx qpn %x psn 0x%x lpsn 0x%x length %u opcode 0x%.2x,%s size %u avail %u head %u last %u"
+
+TRACE_EVENT(
+	rvt_post_one_wr,
+	TP_PROTO(struct rvt_qp *qp, struct rvt_swqe *wqe),
+	TP_ARGS(qp, wqe),
+	TP_STRUCT__entry(
+		RDI_DEV_ENTRY(ib_to_rvt(qp->ibqp.device))
+		__field(u64, wr_id)
+		__field(u32, qpn)
+		__field(u32, psn)
+		__field(u32, lpsn)
+		__field(u32, length)
+		__field(u32, opcode)
+		__field(u32, size)
+		__field(u32, avail)
+		__field(u32, head)
+		__field(u32, last)
+	),
+	TP_fast_assign(
+		RDI_DEV_ASSIGN(ib_to_rvt(qp->ibqp.device))
+		__entry->wr_id = wqe->wr.wr_id;
+		__entry->qpn = qp->ibqp.qp_num;
+		__entry->psn = wqe->psn;
+		__entry->lpsn = wqe->lpsn;
+		__entry->length = wqe->length;
+		__entry->opcode = wqe->wr.opcode;
+		__entry->size = qp->s_size;
+		__entry->avail = qp->s_avail;
+		__entry->head = qp->s_head;
+		__entry->last = qp->s_last;
+	),
+	TP_printk(
+		POS_PRN,
+		__get_str(dev),
+		__entry->wr_id,
+		__entry->qpn,
+		__entry->psn,
+		__entry->lpsn,
+		__entry->length,
+		__entry->opcode, show_wr_opcode(__entry->opcode),
+		__entry->size,
+		__entry->avail,
+		__entry->head,
+		__entry->last
+	)
+);
+
+#endif /* __RVT_TRACE_TX_H */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_tx
+#include <trace/define_trace.h>
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_comp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_comp.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_comp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_comp.c	2017-02-12 16:03:20.000000000 -0500
@@ -224,7 +224,7 @@ static inline enum comp_state check_psn(
 		else
 			return COMPST_DONE;
 	} else if ((diff > 0) && (wqe->mask & WR_ATOMIC_OR_READ_MASK)) {
-		return COMPST_ERROR_RETRY;
+		return COMPST_DONE;
 	} else {
 		return COMPST_CHECK_ACK;
 	}
@@ -420,11 +420,12 @@ static void do_complete(struct rxe_qp *q
 	    (wqe->wr.send_flags & IB_SEND_SIGNALED) ||
 	    (qp->req.state == QP_STATE_ERROR)) {
 		make_send_cqe(qp, wqe, &cqe);
+		advance_consumer(qp->sq.queue);
 		rxe_cq_post(qp->scq, &cqe, 0);
+	} else {
+		advance_consumer(qp->sq.queue);
 	}
 
-	advance_consumer(qp->sq.queue);
-
 	/*
 	 * we completed something so let req run again
 	 * if it is trying to fence
@@ -510,6 +511,8 @@ int rxe_completer(void *arg)
 	struct rxe_pkt_info *pkt = NULL;
 	enum comp_state state;
 
+	rxe_add_ref(qp);
+
 	if (!qp->valid) {
 		while ((skb = skb_dequeue(&qp->resp_pkts))) {
 			rxe_drop_ref(qp);
@@ -739,11 +742,13 @@ exit:
 	/* we come here if we are done with processing and want the task to
 	 * exit from the loop calling us
 	 */
+	rxe_drop_ref(qp);
 	return -EAGAIN;
 
 done:
 	/* we come here if we have processed a packet we want the task to call
 	 * us again to see if there is anything else to do
 	 */
+	rxe_drop_ref(qp);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_loc.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_loc.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_loc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_loc.h	2017-02-12 16:03:20.000000000 -0500
@@ -266,8 +266,6 @@ static inline int rxe_xmit_packet(struct
 		return err;
 	}
 
-	atomic_inc(&qp->skb_out);
-
 	if ((qp_type(qp) != IB_QPT_RC) &&
 	    (pkt->mask & RXE_END_MASK)) {
 		pkt->wqe->state = wqe_state_done;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_mr.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_mr.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_mr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_mr.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,9 +59,11 @@ int mem_check_range(struct rxe_mem *mem,
 
 	case RXE_MEM_TYPE_MR:
 	case RXE_MEM_TYPE_FMR:
-		return ((iova < mem->iova) ||
-			((iova + length) > (mem->iova + mem->length))) ?
-			-EFAULT : 0;
+		if (iova < mem->iova ||
+		    length > mem->length ||
+		    iova > mem->iova + mem->length - length)
+			return -EFAULT;
+		return 0;
 
 	default:
 		return -EFAULT;
@@ -355,6 +357,9 @@ int rxe_mem_copy(struct rxe_mem *mem, u6
 	size_t			offset;
 	u32			crc = crcp ? (*crcp) : 0;
 
+	if (length == 0)
+		return 0;
+
 	if (mem->type == RXE_MEM_TYPE_DMA) {
 		u8 *src, *dest;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_net.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_net.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_net.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_net.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 #include "rxe_loc.h"
 
 static LIST_HEAD(rxe_dev_list);
-static spinlock_t dev_list_lock; /* spinlock for device list */
+static DEFINE_SPINLOCK(dev_list_lock); /* spinlock for device list */
 
 struct rxe_dev *net_to_rxe(struct net_device *ndev)
 {
@@ -455,6 +455,7 @@ static int send(struct rxe_dev *rxe, str
 		return -EAGAIN;
 	}
 
+	atomic_inc(&pkt->qp->skb_out);
 	kfree_skb(skb);
 
 	return 0;
@@ -554,7 +555,7 @@ struct rxe_dev *rxe_net_add(struct net_d
 	}
 
 	spin_lock_bh(&dev_list_lock);
-	list_add_tail(&rxe_dev_list, &rxe->list);
+	list_add_tail(&rxe->list, &rxe_dev_list);
 	spin_unlock_bh(&dev_list_lock);
 	return rxe;
 }
@@ -659,8 +660,6 @@ struct notifier_block rxe_net_notifier =
 
 int rxe_net_ipv4_init(void)
 {
-	spin_lock_init(&dev_list_lock);
-
 	recv_sockets.sk4 = rxe_setup_udp_tunnel(&init_net,
 				htons(ROCE_V2_UDP_DPORT), false);
 	if (IS_ERR(recv_sockets.sk4)) {
@@ -676,8 +675,6 @@ int rxe_net_ipv6_init(void)
 {
 #if IS_ENABLED(CONFIG_IPV6)
 
-	spin_lock_init(&dev_list_lock);
-
 	recv_sockets.sk6 = rxe_setup_udp_tunnel(&init_net,
 						htons(ROCE_V2_UDP_DPORT), true);
 	if (IS_ERR(recv_sockets.sk6)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_param.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_param.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_param.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_param.h	2017-02-12 16:03:20.000000000 -0500
@@ -82,7 +82,7 @@ enum rxe_device_param {
 	RXE_MAX_SGE			= 32,
 	RXE_MAX_SGE_RD			= 32,
 	RXE_MAX_CQ			= 16384,
-	RXE_MAX_LOG_CQE			= 13,
+	RXE_MAX_LOG_CQE			= 15,
 	RXE_MAX_MR			= 2 * 1024,
 	RXE_MAX_PD			= 0x7ffc,
 	RXE_MAX_QP_RD_ATOM		= 128,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_pool.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_pool.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_pool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_pool.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,7 +180,6 @@ static int rxe_pool_init_index(struct rx
 	size = BITS_TO_LONGS(max - min + 1) * sizeof(long);
 	pool->table = kmalloc(size, GFP_KERNEL);
 	if (!pool->table) {
-		pr_warn("no memory for bit table\n");
 		err = -ENOMEM;
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_qp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_qp.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_qp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_qp.c	2017-02-12 16:03:20.000000000 -0500
@@ -813,8 +813,7 @@ void rxe_qp_destroy(struct rxe_qp *qp)
 	del_timer_sync(&qp->rnr_nak_timer);
 
 	rxe_cleanup_task(&qp->req.task);
-	if (qp_type(qp) == IB_QPT_RC)
-		rxe_cleanup_task(&qp->comp.task);
+	rxe_cleanup_task(&qp->comp.task);
 
 	/* flush out any receive wr's or pending requests */
 	__rxe_do_task(&qp->req.task);
@@ -855,4 +854,5 @@ void rxe_qp_cleanup(void *arg)
 	free_rd_atomic_resources(qp);
 
 	kernel_sock_shutdown(qp->sk, SHUT_RDWR);
+	sock_release(qp->sk);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_recv.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_recv.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_recv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_recv.c	2017-02-12 16:03:20.000000000 -0500
@@ -391,16 +391,15 @@ int rxe_rcv(struct sk_buff *skb)
 			     payload_size(pkt));
 	calc_icrc = cpu_to_be32(~calc_icrc);
 	if (unlikely(calc_icrc != pack_icrc)) {
-		char saddr[sizeof(struct in6_addr)];
-
 		if (skb->protocol == htons(ETH_P_IPV6))
-			sprintf(saddr, "%pI6", &ipv6_hdr(skb)->saddr);
+			pr_warn_ratelimited("bad ICRC from %pI6c\n",
+					    &ipv6_hdr(skb)->saddr);
 		else if (skb->protocol == htons(ETH_P_IP))
-			sprintf(saddr, "%pI4", &ip_hdr(skb)->saddr);
+			pr_warn_ratelimited("bad ICRC from %pI4\n",
+					    &ip_hdr(skb)->saddr);
 		else
-			sprintf(saddr, "unknown");
+			pr_warn_ratelimited("bad ICRC from unknown\n");
 
-		pr_warn_ratelimited("bad ICRC from %s\n", saddr);
 		goto drop;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_req.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_req.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_req.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_req.c	2017-02-12 16:03:20.000000000 -0500
@@ -548,23 +548,23 @@ static void update_wqe_psn(struct rxe_qp
 static void save_state(struct rxe_send_wqe *wqe,
 		       struct rxe_qp *qp,
 		       struct rxe_send_wqe *rollback_wqe,
-		       struct rxe_qp *rollback_qp)
+		       u32 *rollback_psn)
 {
 	rollback_wqe->state     = wqe->state;
 	rollback_wqe->first_psn = wqe->first_psn;
 	rollback_wqe->last_psn  = wqe->last_psn;
-	rollback_qp->req.psn    = qp->req.psn;
+	*rollback_psn		= qp->req.psn;
 }
 
 static void rollback_state(struct rxe_send_wqe *wqe,
 			   struct rxe_qp *qp,
 			   struct rxe_send_wqe *rollback_wqe,
-			   struct rxe_qp *rollback_qp)
+			   u32 rollback_psn)
 {
 	wqe->state     = rollback_wqe->state;
 	wqe->first_psn = rollback_wqe->first_psn;
 	wqe->last_psn  = rollback_wqe->last_psn;
-	qp->req.psn    = rollback_qp->req.psn;
+	qp->req.psn    = rollback_psn;
 }
 
 static void update_state(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
@@ -593,8 +593,10 @@ int rxe_requester(void *arg)
 	int mtu;
 	int opcode;
 	int ret;
-	struct rxe_qp rollback_qp;
 	struct rxe_send_wqe rollback_wqe;
+	u32 rollback_psn;
+
+	rxe_add_ref(qp);
 
 next_wqe:
 	if (unlikely(!qp->valid || qp->req.state == QP_STATE_ERROR))
@@ -697,6 +699,7 @@ next_wqe:
 			wqe->state = wqe_state_done;
 			wqe->status = IB_WC_SUCCESS;
 			__rxe_do_task(&qp->comp.task);
+			rxe_drop_ref(qp);
 			return 0;
 		}
 		payload = mtu;
@@ -719,7 +722,7 @@ next_wqe:
 	 * rxe_xmit_packet().
 	 * Otherwise, completer might initiate an unjustified retry flow.
 	 */
-	save_state(wqe, qp, &rollback_wqe, &rollback_qp);
+	save_state(wqe, qp, &rollback_wqe, &rollback_psn);
 	update_wqe_state(qp, wqe, &pkt);
 	update_wqe_psn(qp, wqe, &pkt, payload);
 	ret = rxe_xmit_packet(to_rdev(qp->ibqp.device), qp, &pkt, skb);
@@ -727,7 +730,7 @@ next_wqe:
 		qp->need_req_skb = 1;
 		kfree_skb(skb);
 
-		rollback_state(wqe, qp, &rollback_wqe, &rollback_qp);
+		rollback_state(wqe, qp, &rollback_wqe, rollback_psn);
 
 		if (ret == -EAGAIN) {
 			rxe_run_task(&qp->req.task, 1);
@@ -756,8 +759,7 @@ err:
 	 */
 	wqe->wr.send_flags |= IB_SEND_SIGNALED;
 	__rxe_do_task(&qp->comp.task);
-	return -EAGAIN;
-
 exit:
+	rxe_drop_ref(qp);
 	return -EAGAIN;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_resp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_resp.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_resp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_resp.c	2017-02-12 16:03:20.000000000 -0500
@@ -444,6 +444,13 @@ static enum resp_states check_rkey(struc
 		return RESPST_EXECUTE;
 	}
 
+	/* A zero-byte op is not required to set an addr or rkey. */
+	if ((pkt->mask & (RXE_READ_MASK | RXE_WRITE_OR_SEND)) &&
+	    (pkt->mask & RXE_RETH_MASK) &&
+	    reth_len(pkt) == 0) {
+		return RESPST_EXECUTE;
+	}
+
 	va	= qp->resp.va;
 	rkey	= qp->resp.rkey;
 	resid	= qp->resp.resid;
@@ -472,7 +479,7 @@ static enum resp_states check_rkey(struc
 				goto err2;
 			}
 
-			resid = mtu;
+			qp->resp.resid = mtu;
 		} else {
 			if (pktlen != resid) {
 				state = RESPST_ERR_LENGTH;
@@ -680,9 +687,14 @@ static enum resp_states read_reply(struc
 		res->read.va_org	= qp->resp.va;
 
 		res->first_psn		= req_pkt->psn;
-		res->last_psn		= req_pkt->psn +
-					  (reth_len(req_pkt) + mtu - 1) /
-					  mtu - 1;
+
+		if (reth_len(req_pkt)) {
+			res->last_psn	= (req_pkt->psn +
+					   (reth_len(req_pkt) + mtu - 1) /
+					   mtu - 1) & BTH_PSN_MASK;
+		} else {
+			res->last_psn	= res->first_psn;
+		}
 		res->cur_psn		= req_pkt->psn;
 
 		res->read.resid		= qp->resp.resid;
@@ -742,7 +754,8 @@ static enum resp_states read_reply(struc
 	} else {
 		qp->resp.res = NULL;
 		qp->resp.opcode = -1;
-		qp->resp.psn = res->cur_psn;
+		if (psn_compare(res->cur_psn, qp->resp.psn) >= 0)
+			qp->resp.psn = res->cur_psn;
 		state = RESPST_CLEANUP;
 	}
 
@@ -1057,12 +1070,13 @@ static enum resp_states duplicate_reques
 					  struct rxe_pkt_info *pkt)
 {
 	enum resp_states rc;
+	u32 prev_psn = (qp->resp.psn - 1) & BTH_PSN_MASK;
 
 	if (pkt->mask & RXE_SEND_MASK ||
 	    pkt->mask & RXE_WRITE_MASK) {
 		/* SEND. Ack again and cleanup. C9-105. */
 		if (bth_ack(pkt))
-			send_ack(qp, pkt, AETH_ACK_UNLIMITED, qp->resp.psn - 1);
+			send_ack(qp, pkt, AETH_ACK_UNLIMITED, prev_psn);
 		rc = RESPST_CLEANUP;
 		goto out;
 	} else if (pkt->mask & RXE_READ_MASK) {
@@ -1132,6 +1146,7 @@ static enum resp_states duplicate_reques
 					     pkt, skb_copy);
 			if (rc) {
 				pr_err("Failed resending result. This flow is not handled - skb ignored\n");
+				rxe_drop_ref(qp);
 				kfree_skb(skb_copy);
 				rc = RESPST_CLEANUP;
 				goto out;
@@ -1198,6 +1213,8 @@ int rxe_responder(void *arg)
 	struct rxe_pkt_info *pkt = NULL;
 	int ret = 0;
 
+	rxe_add_ref(qp);
+
 	qp->resp.aeth_syndrome = AETH_ACK_UNLIMITED;
 
 	if (!qp->valid) {
@@ -1386,5 +1403,6 @@ int rxe_responder(void *arg)
 exit:
 	ret = -EAGAIN;
 done:
+	rxe_drop_ref(qp);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_srq.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_srq.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_srq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_srq.c	2017-02-12 16:03:20.000000000 -0500
@@ -169,7 +169,7 @@ int rxe_srq_from_attr(struct rxe_dev *rx
 			}
 		}
 
-		err = rxe_queue_resize(q, (unsigned int *)&attr->max_wr,
+		err = rxe_queue_resize(q, &attr->max_wr,
 				       rcv_wqe_size(srq->rq.max_sge),
 				       srq->rq.queue->ip ?
 						srq->rq.queue->ip->context :
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_task.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_task.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_task.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_task.c	2017-02-12 16:03:20.000000000 -0500
@@ -121,6 +121,7 @@ int rxe_init_task(void *obj, struct rxe_
 	task->arg	= arg;
 	task->func	= func;
 	snprintf(task->name, sizeof(task->name), "%s", name);
+	task->destroyed	= false;
 
 	tasklet_init(&task->tasklet, rxe_do_task, (unsigned long)task);
 
@@ -132,11 +133,29 @@ int rxe_init_task(void *obj, struct rxe_
 
 void rxe_cleanup_task(struct rxe_task *task)
 {
+	unsigned long flags;
+	bool idle;
+
+	/*
+	 * Mark the task, then wait for it to finish. It might be
+	 * running in a non-tasklet (direct call) context.
+	 */
+	task->destroyed = true;
+
+	do {
+		spin_lock_irqsave(&task->state_lock, flags);
+		idle = (task->state == TASK_STATE_START);
+		spin_unlock_irqrestore(&task->state_lock, flags);
+	} while (!idle);
+
 	tasklet_kill(&task->tasklet);
 }
 
 void rxe_run_task(struct rxe_task *task, int sched)
 {
+	if (task->destroyed)
+		return;
+
 	if (sched)
 		tasklet_schedule(&task->tasklet);
 	else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_task.h linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_task.h
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_task.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_task.h	2017-02-12 16:03:20.000000000 -0500
@@ -54,6 +54,7 @@ struct rxe_task {
 	int			(*func)(void *arg);
 	int			ret;
 	char			name[16];
+	bool			destroyed;
 };
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/sw/rxe/rxe_verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/sw/rxe/rxe_verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -316,7 +316,9 @@ static int rxe_init_av(struct rxe_dev *r
 	return err;
 }
 
-static struct ib_ah *rxe_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
+static struct ib_ah *rxe_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr,
+				   struct ib_udata *udata)
+
 {
 	int err;
 	struct rxe_dev *rxe = to_rdev(ibpd->device);
@@ -564,7 +566,7 @@ static struct ib_qp *rxe_create_qp(struc
 	if (udata) {
 		if (udata->inlen) {
 			err = -EINVAL;
-			goto err1;
+			goto err2;
 		}
 		qp->is_user = 1;
 	}
@@ -573,12 +575,13 @@ static struct ib_qp *rxe_create_qp(struc
 
 	err = rxe_qp_from_init(rxe, qp, pd, init, udata, ibpd);
 	if (err)
-		goto err2;
+		goto err3;
 
 	return &qp->ibqp;
 
-err2:
+err3:
 	rxe_drop_index(qp);
+err2:
 	rxe_drop_ref(qp);
 err1:
 	return ERR_PTR(err);
@@ -1007,11 +1010,19 @@ static int rxe_peek_cq(struct ib_cq *ibc
 static int rxe_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags)
 {
 	struct rxe_cq *cq = to_rcq(ibcq);
+	unsigned long irq_flags;
+	int ret = 0;
 
+	spin_lock_irqsave(&cq->cq_lock, irq_flags);
 	if (cq->notify != IB_CQ_NEXT_COMP)
 		cq->notify = flags & IB_CQ_SOLICITED_MASK;
 
-	return 0;
+	if ((flags & IB_CQ_REPORT_MISSED_EVENTS) && !queue_empty(cq->queue))
+		ret = 1;
+
+	spin_unlock_irqrestore(&cq->cq_lock, irq_flags);
+
+	return ret;
 }
 
 static struct ib_mr *rxe_get_dma_mr(struct ib_pd *ibpd, int access)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -357,11 +357,8 @@ static int ipoib_cm_nonsrq_init_rx(struc
 	int i;
 
 	rx->rx_ring = vzalloc(ipoib_recvq_size * sizeof *rx->rx_ring);
-	if (!rx->rx_ring) {
-		printk(KERN_WARNING "%s: failed to allocate CM non-SRQ ring (%d entries)\n",
-		       priv->ca->name, ipoib_recvq_size);
+	if (!rx->rx_ring)
 		return -ENOMEM;
-	}
 
 	t = kmalloc(sizeof *t, GFP_KERNEL);
 	if (!t) {
@@ -1054,8 +1051,6 @@ static struct ib_qp *ipoib_cm_create_tx_
 
 	tx_qp = ib_create_qp(priv->pd, &attr);
 	if (PTR_ERR(tx_qp) == -EINVAL) {
-		ipoib_warn(priv, "can't use GFP_NOIO for QPs on device %s, using GFP_KERNEL\n",
-			   priv->ca->name);
 		attr.create_flags &= ~IB_QP_CREATE_USE_GFP_NOIO;
 		tx_qp = ib_create_qp(priv->pd, &attr);
 	}
@@ -1134,7 +1129,6 @@ static int ipoib_cm_tx_init(struct ipoib
 	p->tx_ring = __vmalloc(ipoib_sendq_size * sizeof *p->tx_ring,
 			       GFP_NOIO, PAGE_KERNEL);
 	if (!p->tx_ring) {
-		ipoib_warn(priv, "failed to allocate tx ring\n");
 		ret = -ENOMEM;
 		goto err_tx;
 	}
@@ -1550,8 +1544,6 @@ static void ipoib_cm_create_srq(struct n
 
 	priv->cm.srq_ring = vzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring);
 	if (!priv->cm.srq_ring) {
-		printk(KERN_WARNING "%s: failed to allocate CM SRQ ring (%d entries)\n",
-		       priv->ca->name, ipoib_recvq_size);
 		ib_destroy_srq(priv->cm.srq);
 		priv->cm.srq = NULL;
 		return;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2017-02-12 16:03:20.000000000 -0500
@@ -416,11 +416,8 @@ static void ipoib_ib_handle_tx_wc(struct
 			   "(status=%d, wrid=%d vend_err %x)\n",
 			   wc->status, wr_id, wc->vendor_err);
 		qp_work = kzalloc(sizeof(*qp_work), GFP_ATOMIC);
-		if (!qp_work) {
-			ipoib_warn(priv, "%s Failed alloc ipoib_qp_state_validate for qp: 0x%x\n",
-				   __func__, priv->qp->qp_num);
+		if (!qp_work)
 			return;
-		}
 
 		INIT_WORK(&qp_work->work, ipoib_qp_state_validate_work);
 		qp_work->priv = priv;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -292,6 +292,25 @@ static struct net_device *ipoib_get_mast
 	return dev;
 }
 
+struct ipoib_walk_data {
+	const struct sockaddr *addr;
+	struct net_device *result;
+};
+
+static int ipoib_upper_walk(struct net_device *upper, void *_data)
+{
+	struct ipoib_walk_data *data = _data;
+	int ret = 0;
+
+	if (ipoib_is_dev_match_addr_rcu(data->addr, upper)) {
+		dev_hold(upper);
+		data->result = upper;
+		ret = 1;
+	}
+
+	return ret;
+}
+
 /**
  * Find a net_device matching the given address, which is an upper device of
  * the given net_device.
@@ -304,27 +323,21 @@ static struct net_device *ipoib_get_mast
 static struct net_device *ipoib_get_net_dev_match_addr(
 		const struct sockaddr *addr, struct net_device *dev)
 {
-	struct net_device *upper,
-			  *result = NULL;
-	struct list_head *iter;
+	struct ipoib_walk_data data = {
+		.addr = addr,
+	};
 
 	rcu_read_lock();
 	if (ipoib_is_dev_match_addr_rcu(addr, dev)) {
 		dev_hold(dev);
-		result = dev;
+		data.result = dev;
 		goto out;
 	}
 
-	netdev_for_each_all_upper_dev_rcu(dev, upper, iter) {
-		if (ipoib_is_dev_match_addr_rcu(addr, upper)) {
-			dev_hold(upper);
-			result = upper;
-			break;
-		}
-	}
+	netdev_walk_all_upper_dev_rcu(dev, ipoib_upper_walk, &data);
 out:
 	rcu_read_unlock();
-	return result;
+	return data.result;
 }
 
 /* returns the number of IPoIB netdevs on top a given ipoib device matching a
@@ -1606,11 +1619,8 @@ int ipoib_dev_init(struct net_device *de
 	/* Allocate RX/TX "rings" to hold queued skbs */
 	priv->rx_ring =	kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
 				GFP_KERNEL);
-	if (!priv->rx_ring) {
-		printk(KERN_WARNING "%s: failed to allocate RX ring (%d entries)\n",
-		       ca->name, ipoib_recvq_size);
+	if (!priv->rx_ring)
 		goto out;
-	}
 
 	priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
 	if (!priv->tx_ring) {
@@ -2016,6 +2026,7 @@ static struct net_device *ipoib_add_port
 	/* MTU will be reset when mcast join happens */
 	priv->dev->mtu  = IPOIB_UD_MTU(priv->max_ib_mtu);
 	priv->mcast_mtu  = priv->admin_mtu = priv->dev->mtu;
+	priv->dev->max_mtu = IPOIB_CM_MTU;
 
 	priv->dev->neigh_priv_len = sizeof(struct ipoib_neigh);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2017-02-12 16:03:20.000000000 -0500
@@ -575,8 +575,11 @@ void ipoib_mcast_join_task(struct work_s
 	if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
 		return;
 
-	if (ib_query_port(priv->ca, priv->port, &port_attr) ||
-	    port_attr.state != IB_PORT_ACTIVE) {
+	if (ib_query_port(priv->ca, priv->port, &port_attr)) {
+		ipoib_dbg(priv, "ib_query_port() failed\n");
+		return;
+	}
+	if (port_attr.state != IB_PORT_ACTIVE) {
 		ipoib_dbg(priv, "port state is not ACTIVE (state = %d) suspending join task\n",
 			  port_attr.state);
 		return;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/ipoib/ipoib_vlan.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/init.h>
 #include <linux/seq_file.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "ipoib.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,7 @@
 
 #include <net/sock.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
@@ -651,13 +651,6 @@ iscsi_iser_session_create(struct iscsi_e
 						   SHOST_DIX_GUARD_CRC);
 		}
 
-		/*
-		 * Limit the sg_tablesize and max_sectors based on the device
-		 * max fastreg page list length.
-		 */
-		shost->sg_tablesize = min_t(unsigned short, shost->sg_tablesize,
-			ib_conn->device->ib_device->attrs.max_fast_reg_page_list_len);
-
 		if (iscsi_host_add(shost,
 				   ib_conn->device->ib_device->dma_device)) {
 			mutex_unlock(&iser_conn->state_mutex);
@@ -679,6 +672,10 @@ iscsi_iser_session_create(struct iscsi_e
 	max_fr_sectors = ((shost->sg_tablesize - 1) * PAGE_SIZE) >> 9;
 	shost->max_sectors = min(iser_max_sectors, max_fr_sectors);
 
+	iser_dbg("iser_conn %p, sg_tablesize %u, max_sectors %u\n",
+		 iser_conn, shost->sg_tablesize,
+		 shost->max_sectors);
+
 	if (cmds_max > max_cmds) {
 		iser_info("cmds_max changed from %u to %u\n",
 			  cmds_max, max_cmds);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2017-02-12 16:03:20.000000000 -0500
@@ -496,7 +496,6 @@ struct ib_conn {
  * @rx_descs:         rx buffers array (cyclic buffer)
  * @num_rx_descs:     number of rx descriptors
  * @scsi_sg_tablesize: scsi host sg_tablesize
- * @scsi_max_sectors: scsi host max sectors
  */
 struct iser_conn {
 	struct ib_conn		     ib_conn;
@@ -519,7 +518,6 @@ struct iser_conn {
 	struct iser_rx_desc	     *rx_descs;
 	u32                          num_rx_descs;
 	unsigned short               scsi_sg_tablesize;
-	unsigned int                 scsi_max_sectors;
 	bool			     snd_w_inv;
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/iser/iser_verbs.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/iser/iser_verbs.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/iser/iser_verbs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/iser/iser_verbs.c	2017-02-12 16:03:20.000000000 -0500
@@ -707,18 +707,7 @@ iser_calc_scsi_params(struct iser_conn *
 	sup_sg_tablesize = min_t(unsigned, ISCSI_ISER_MAX_SG_TABLESIZE,
 				 device->ib_device->attrs.max_fast_reg_page_list_len);
 
-	if (sg_tablesize > sup_sg_tablesize) {
-		sg_tablesize = sup_sg_tablesize;
-		iser_conn->scsi_max_sectors = sg_tablesize * SIZE_4K / 512;
-	} else {
-		iser_conn->scsi_max_sectors = max_sectors;
-	}
-
-	iser_conn->scsi_sg_tablesize = sg_tablesize;
-
-	iser_dbg("iser_conn %p, sg_tablesize %u, max_sectors %u\n",
-		 iser_conn, iser_conn->scsi_sg_tablesize,
-		 iser_conn->scsi_max_sectors);
+	iser_conn->scsi_sg_tablesize = min(sg_tablesize, sup_sg_tablesize);
 }
 
 /**
@@ -890,11 +879,14 @@ static int iser_cma_handler(struct rdma_
 	case RDMA_CM_EVENT_ESTABLISHED:
 		iser_connected_handler(cma_id, event->param.conn.private_data);
 		break;
+	case RDMA_CM_EVENT_REJECTED:
+		iser_info("Connection rejected: %s\n",
+			 rdma_reject_msg(cma_id, event->status));
+		/* FALLTHROUGH */
 	case RDMA_CM_EVENT_ADDR_ERROR:
 	case RDMA_CM_EVENT_ROUTE_ERROR:
 	case RDMA_CM_EVENT_CONNECT_ERROR:
 	case RDMA_CM_EVENT_UNREACHABLE:
-	case RDMA_CM_EVENT_REJECTED:
 		iser_connect_error(cma_id);
 		break;
 	case RDMA_CM_EVENT_DISCONNECTED:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/isert/ib_isert.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/isert/ib_isert.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/isert/ib_isert.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/isert/ib_isert.c	2017-02-12 16:03:20.000000000 -0500
@@ -184,7 +184,7 @@ isert_alloc_rx_descriptors(struct isert_
 	isert_conn->rx_descs = kzalloc(ISERT_QP_MAX_RECV_DTOS *
 				sizeof(struct iser_rx_desc), GFP_KERNEL);
 	if (!isert_conn->rx_descs)
-		goto fail;
+		return -ENOMEM;
 
 	rx_desc = isert_conn->rx_descs;
 
@@ -213,9 +213,7 @@ dma_map_fail:
 	}
 	kfree(isert_conn->rx_descs);
 	isert_conn->rx_descs = NULL;
-fail:
 	isert_err("conn %p failed to allocate rx descriptors\n", isert_conn);
-
 	return -ENOMEM;
 }
 
@@ -269,10 +267,8 @@ isert_alloc_comps(struct isert_device *d
 
 	device->comps = kcalloc(device->comps_used, sizeof(struct isert_comp),
 				GFP_KERNEL);
-	if (!device->comps) {
-		isert_err("Unable to allocate completion contexts\n");
+	if (!device->comps)
 		return -ENOMEM;
-	}
 
 	max_cqe = min(ISER_MAX_CQ_LEN, device->ib_device->attrs.max_cqe);
 
@@ -432,10 +428,8 @@ isert_alloc_login_buf(struct isert_conn
 
 	isert_conn->login_req_buf = kzalloc(sizeof(*isert_conn->login_req_buf),
 			GFP_KERNEL);
-	if (!isert_conn->login_req_buf) {
-		isert_err("Unable to allocate isert_conn->login_buf\n");
+	if (!isert_conn->login_req_buf)
 		return -ENOMEM;
-	}
 
 	isert_conn->login_req_dma = ib_dma_map_single(ib_dev,
 				isert_conn->login_req_buf,
@@ -795,6 +789,8 @@ isert_cma_handler(struct rdma_cm_id *cma
 		 */
 		return 1;
 	case RDMA_CM_EVENT_REJECTED:       /* FALLTHRU */
+		isert_info("Connection rejected: %s\n",
+			   rdma_reject_msg(cma_id, event->status));
 	case RDMA_CM_EVENT_UNREACHABLE:    /* FALLTHRU */
 	case RDMA_CM_EVENT_CONNECT_ERROR:
 		ret = isert_connect_error(cma_id);
@@ -1276,11 +1272,8 @@ isert_handle_text_cmd(struct isert_conn
 
 	if (payload_length) {
 		text_in = kzalloc(payload_length, GFP_KERNEL);
-		if (!text_in) {
-			isert_err("Unable to allocate text_in of payload_length: %u\n",
-				  payload_length);
+		if (!text_in)
 			return -ENOMEM;
-		}
 	}
 	cmd->text_in_ptr = text_in;
 
@@ -1851,6 +1844,8 @@ isert_put_response(struct iscsi_conn *co
 		isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev,
 				(void *)cmd->sense_buffer, pdu_len,
 				DMA_TO_DEVICE);
+		if (ib_dma_mapping_error(ib_dev, isert_cmd->pdu_buf_dma))
+			return -ENOMEM;
 
 		isert_cmd->pdu_buf_len = pdu_len;
 		tx_dsg->addr	= isert_cmd->pdu_buf_dma;
@@ -1978,6 +1973,8 @@ isert_put_reject(struct iscsi_cmd *cmd,
 	isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev,
 			(void *)cmd->buf_ptr, ISCSI_HDR_LEN,
 			DMA_TO_DEVICE);
+	if (ib_dma_mapping_error(ib_dev, isert_cmd->pdu_buf_dma))
+		return -ENOMEM;
 	isert_cmd->pdu_buf_len = ISCSI_HDR_LEN;
 	tx_dsg->addr	= isert_cmd->pdu_buf_dma;
 	tx_dsg->length	= ISCSI_HDR_LEN;
@@ -2018,6 +2015,8 @@ isert_put_text_rsp(struct iscsi_cmd *cmd
 
 		isert_cmd->pdu_buf_dma = ib_dma_map_single(ib_dev,
 				txt_rsp_buf, txt_rsp_len, DMA_TO_DEVICE);
+		if (ib_dma_mapping_error(ib_dev, isert_cmd->pdu_buf_dma))
+			return -ENOMEM;
 
 		isert_cmd->pdu_buf_len = txt_rsp_len;
 		tx_dsg->addr	= isert_cmd->pdu_buf_dma;
@@ -2307,10 +2306,9 @@ isert_setup_np(struct iscsi_np *np,
 	int ret;
 
 	isert_np = kzalloc(sizeof(struct isert_np), GFP_KERNEL);
-	if (!isert_np) {
-		isert_err("Unable to allocate struct isert_np\n");
+	if (!isert_np)
 		return -ENOMEM;
-	}
+
 	sema_init(&isert_np->sem, 0);
 	mutex_init(&isert_np->mutex);
 	INIT_LIST_HEAD(&isert_np->accepted);
@@ -2651,7 +2649,6 @@ static int __init isert_init(void)
 					WQ_UNBOUND | WQ_HIGHPRI, 0);
 	if (!isert_comp_wq) {
 		isert_err("Unable to allocate isert_comp_wq\n");
-		ret = -ENOMEM;
 		return -ENOMEM;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/srp/ib_srp.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/srp/ib_srp.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,6 +64,11 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_INFO(release_date, DRV_RELDATE);
 
+#if !defined(CONFIG_DYNAMIC_DEBUG)
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
+#define DYNAMIC_DEBUG_BRANCH(descriptor) false
+#endif
+
 static unsigned int srp_sg_tablesize;
 static unsigned int cmd_sg_entries;
 static unsigned int indirect_sg_entries;
@@ -366,6 +371,7 @@ static struct srp_fr_pool *srp_create_fr
 	struct srp_fr_desc *d;
 	struct ib_mr *mr;
 	int i, ret = -EINVAL;
+	enum ib_mr_type mr_type;
 
 	if (pool_size <= 0)
 		goto err;
@@ -379,11 +385,18 @@ static struct srp_fr_pool *srp_create_fr
 	spin_lock_init(&pool->lock);
 	INIT_LIST_HEAD(&pool->free_list);
 
+	if (device->attrs.device_cap_flags & IB_DEVICE_SG_GAPS_REG)
+		mr_type = IB_MR_TYPE_SG_GAPS;
+	else
+		mr_type = IB_MR_TYPE_MEM_REG;
+
 	for (i = 0, d = &pool->desc[0]; i < pool->size; i++, d++) {
-		mr = ib_alloc_mr(pd, IB_MR_TYPE_MEM_REG,
-				 max_page_list_len);
+		mr = ib_alloc_mr(pd, mr_type, max_page_list_len);
 		if (IS_ERR(mr)) {
 			ret = PTR_ERR(mr);
+			if (ret == -ENOMEM)
+				pr_info("%s: ib_alloc_mr() failed. Try to reduce max_cmd_per_lun, max_sect or ch_count\n",
+					dev_name(&device->dev));
 			goto destroy_pool;
 		}
 		d->mr = mr;
@@ -1266,8 +1279,12 @@ static int srp_map_finish_fmr(struct srp
 	struct ib_pool_fmr *fmr;
 	u64 io_addr = 0;
 
-	if (state->fmr.next >= state->fmr.end)
+	if (state->fmr.next >= state->fmr.end) {
+		shost_printk(KERN_ERR, ch->target->scsi_host,
+			     PFX "Out of MRs (mr_per_cmd = %d)\n",
+			     ch->target->mr_per_cmd);
 		return -ENOMEM;
+	}
 
 	WARN_ON_ONCE(!dev->use_fmr);
 
@@ -1323,8 +1340,12 @@ static int srp_map_finish_fr(struct srp_
 	u32 rkey;
 	int n, err;
 
-	if (state->fr.next >= state->fr.end)
+	if (state->fr.next >= state->fr.end) {
+		shost_printk(KERN_ERR, ch->target->scsi_host,
+			     PFX "Out of MRs (mr_per_cmd = %d)\n",
+			     ch->target->mr_per_cmd);
 		return -ENOMEM;
+	}
 
 	WARN_ON_ONCE(!dev->use_fast_reg);
 
@@ -1556,7 +1577,6 @@ static int srp_map_idb(struct srp_rdma_c
 	return 0;
 }
 
-#if defined(DYNAMIC_DATA_DEBUG)
 static void srp_check_mapping(struct srp_map_state *state,
 			      struct srp_rdma_ch *ch, struct srp_request *req,
 			      struct scatterlist *scat, int count)
@@ -1580,7 +1600,6 @@ static void srp_check_mapping(struct srp
 		       scsi_bufflen(req->scmnd), desc_len, mr_len,
 		       state->ndesc, state->nmdesc);
 }
-#endif
 
 /**
  * srp_map_data() - map SCSI data buffer onto an SRP request
@@ -1669,14 +1688,12 @@ static int srp_map_data(struct scsi_cmnd
 	if (ret < 0)
 		goto unmap;
 
-#if defined(DYNAMIC_DEBUG)
 	{
 		DEFINE_DYNAMIC_DEBUG_METADATA(ddm,
 			"Memory mapping consistency check");
-		if (unlikely(ddm.flags & _DPRINTK_FLAGS_PRINT))
+		if (DYNAMIC_DEBUG_BRANCH(ddm))
 			srp_check_mapping(&state, ch, req, scat, count);
 	}
-#endif
 
 	/* We've mapped the request, now pull as much of the indirect
 	 * descriptor table as we can into the command buffer. If this
@@ -3287,7 +3304,9 @@ static ssize_t srp_create_target(struct
 	 */
 	scsi_host_get(target->scsi_host);
 
-	mutex_lock(&host->add_target_mutex);
+	ret = mutex_lock_interruptible(&host->add_target_mutex);
+	if (ret < 0)
+		goto put;
 
 	ret = srp_parse_options(buf, target);
 	if (ret)
@@ -3443,6 +3462,7 @@ connected:
 out:
 	mutex_unlock(&host->add_target_mutex);
 
+put:
 	scsi_host_put(target->scsi_host);
 	if (ret < 0)
 		scsi_host_put(target->scsi_host);
@@ -3526,6 +3546,7 @@ free_host:
 static void srp_add_one(struct ib_device *device)
 {
 	struct srp_device *srp_dev;
+	struct ib_device_attr *attr = &device->attrs;
 	struct srp_host *host;
 	int mr_page_shift, p;
 	u64 max_pages_per_mr;
@@ -3540,25 +3561,25 @@ static void srp_add_one(struct ib_device
 	 * minimum of 4096 bytes. We're unlikely to build large sglists
 	 * out of smaller entries.
 	 */
-	mr_page_shift		= max(12, ffs(device->attrs.page_size_cap) - 1);
+	mr_page_shift		= max(12, ffs(attr->page_size_cap) - 1);
 	srp_dev->mr_page_size	= 1 << mr_page_shift;
 	srp_dev->mr_page_mask	= ~((u64) srp_dev->mr_page_size - 1);
-	max_pages_per_mr	= device->attrs.max_mr_size;
+	max_pages_per_mr	= attr->max_mr_size;
 	do_div(max_pages_per_mr, srp_dev->mr_page_size);
 	pr_debug("%s: %llu / %u = %llu <> %u\n", __func__,
-		 device->attrs.max_mr_size, srp_dev->mr_page_size,
+		 attr->max_mr_size, srp_dev->mr_page_size,
 		 max_pages_per_mr, SRP_MAX_PAGES_PER_MR);
 	srp_dev->max_pages_per_mr = min_t(u64, SRP_MAX_PAGES_PER_MR,
 					  max_pages_per_mr);
 
 	srp_dev->has_fmr = (device->alloc_fmr && device->dealloc_fmr &&
 			    device->map_phys_fmr && device->unmap_fmr);
-	srp_dev->has_fr = (device->attrs.device_cap_flags &
+	srp_dev->has_fr = (attr->device_cap_flags &
 			   IB_DEVICE_MEM_MGT_EXTENSIONS);
 	if (!never_register && !srp_dev->has_fmr && !srp_dev->has_fr) {
 		dev_warn(&device->dev, "neither FMR nor FR is supported\n");
 	} else if (!never_register &&
-		   device->attrs.max_mr_size >= 2 * srp_dev->mr_page_size) {
+		   attr->max_mr_size >= 2 * srp_dev->mr_page_size) {
 		srp_dev->use_fast_reg = (srp_dev->has_fr &&
 					 (!srp_dev->has_fmr || prefer_fr));
 		srp_dev->use_fmr = !srp_dev->use_fast_reg && srp_dev->has_fmr;
@@ -3571,13 +3592,13 @@ static void srp_add_one(struct ib_device
 	if (srp_dev->use_fast_reg) {
 		srp_dev->max_pages_per_mr =
 			min_t(u32, srp_dev->max_pages_per_mr,
-			      device->attrs.max_fast_reg_page_list_len);
+			      attr->max_fast_reg_page_list_len);
 	}
 	srp_dev->mr_max_size	= srp_dev->mr_page_size *
 				   srp_dev->max_pages_per_mr;
 	pr_debug("%s: mr_page_shift = %d, device->max_mr_size = %#llx, device->max_fast_reg_page_list_len = %u, max_pages_per_mr = %d, mr_max_size = %#x\n",
-		 device->name, mr_page_shift, device->attrs.max_mr_size,
-		 device->attrs.max_fast_reg_page_list_len,
+		 device->name, mr_page_shift, attr->max_mr_size,
+		 attr->max_fast_reg_page_list_len,
 		 srp_dev->max_pages_per_mr, srp_dev->mr_max_size);
 
 	INIT_LIST_HEAD(&srp_dev->dev_list);
@@ -3678,6 +3699,12 @@ static int __init srp_init_module(void)
 		indirect_sg_entries = cmd_sg_entries;
 	}
 
+	if (indirect_sg_entries > SG_MAX_SEGMENTS) {
+		pr_warn("Clamping indirect_sg_entries to %u\n",
+			SG_MAX_SEGMENTS);
+		indirect_sg_entries = SG_MAX_SEGMENTS;
+	}
+
 	srp_remove_wq = create_workqueue("srp_remove");
 	if (!srp_remove_wq) {
 		ret = -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c
--- linux-libre-4.9-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/infiniband/ulp/srpt/ib_srpt.c	2017-02-12 16:03:20.000000000 -0500
@@ -1840,7 +1840,6 @@ static int srpt_cm_req_recv(struct ib_cm
 	struct srpt_rdma_ch *ch, *tmp_ch;
 	u32 it_iu_len;
 	int i, ret = 0;
-	unsigned char *p;
 
 	WARN_ON_ONCE(irqs_disabled());
 
@@ -1994,21 +1993,18 @@ static int srpt_cm_req_recv(struct ib_cm
 			be64_to_cpu(*(__be64 *)(ch->i_port_id + 8)));
 
 	pr_debug("registering session %s\n", ch->sess_name);
-	p = &ch->sess_name[0];
 
-try_again:
 	ch->sess = target_alloc_session(&sport->port_tpg_1, 0, 0,
-					TARGET_PROT_NORMAL, p, ch, NULL);
+					TARGET_PROT_NORMAL, ch->sess_name, ch,
+					NULL);
+	/* Retry without leading "0x" */
+	if (IS_ERR(ch->sess))
+		ch->sess = target_alloc_session(&sport->port_tpg_1, 0, 0,
+						TARGET_PROT_NORMAL,
+						ch->sess_name + 2, ch, NULL);
 	if (IS_ERR(ch->sess)) {
-		pr_info("Rejected login because no ACL has been"
-			" configured yet for initiator %s.\n", p);
-		/*
-		 * XXX: Hack to retry of ch->i_port_id without leading '0x'
-		 */
-		if (p == &ch->sess_name[0]) {
-			p += 2;
-			goto try_again;
-		}
+		pr_info("Rejected login because no ACL has been configured yet for initiator %s.\n",
+			ch->sess_name);
 		rej->reason = cpu_to_be32((PTR_ERR(ch->sess) == -ENOMEM) ?
 				SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES :
 				SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/input-compat.c linux-libre-4.10-rc8-gnu/drivers/input/input-compat.c
--- linux-libre-4.9-gnu/drivers/input/input-compat.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/input-compat.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,7 @@
  */
 
 #include <linux/export.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "input-compat.h"
 
 #ifdef CONFIG_COMPAT
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/joydev.c linux-libre-4.10-rc8-gnu/drivers/input/joydev.c
--- linux-libre-4.9-gnu/drivers/input/joydev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/joydev.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
-#include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/poll.h>
 #include <linux/init.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/joystick/walkera0701.c linux-libre-4.10-rc8-gnu/drivers/input/joystick/walkera0701.c
--- linux-libre-4.9-gnu/drivers/input/joystick/walkera0701.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/joystick/walkera0701.c	2017-02-12 16:03:20.000000000 -0500
@@ -165,7 +165,7 @@ static void walkera0701_irq_handler(void
 				RESERVE + BIN1_PULSE - BIN0_PULSE)	/* frame sync .. */
 		w->counter = 0;
 
-	hrtimer_start(&w->timer, ktime_set(0, BIN_SAMPLE), HRTIMER_MODE_REL);
+	hrtimer_start(&w->timer, BIN_SAMPLE, HRTIMER_MODE_REL);
 }
 
 static enum hrtimer_restart timer_handler(struct hrtimer
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/joystick/xpad.c linux-libre-4.10-rc8-gnu/drivers/input/joystick/xpad.c
--- linux-libre-4.9-gnu/drivers/input/joystick/xpad.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/joystick/xpad.c	2017-02-12 16:03:20.000000000 -0500
@@ -134,6 +134,7 @@ static const struct xpad_device {
 	{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
+	{ 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
 	{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
 	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
@@ -1044,9 +1045,9 @@ static int xpad_play_effect(struct input
 		packet->data[7] = 0x00;
 		packet->data[8] = strong / 512;	/* left actuator */
 		packet->data[9] = weak / 512;	/* right actuator */
-		packet->data[10] = 0xFF;
-		packet->data[11] = 0x00;
-		packet->data[12] = 0x00;
+		packet->data[10] = 0xFF; /* on period */
+		packet->data[11] = 0x00; /* off period */
+		packet->data[12] = 0xFF; /* repeat count */
 		packet->len = 13;
 		packet->pending = true;
 		break;
@@ -1376,6 +1377,12 @@ static int xpad_init_input(struct usb_xp
 	input_dev->name = xpad->name;
 	input_dev->phys = xpad->phys;
 	usb_to_input_id(xpad->udev, &input_dev->id);
+
+	if (xpad->xtype == XTYPE_XBOX360W) {
+		/* x360w controllers and the receiver have different ids */
+		input_dev->id.product = 0x02a1;
+	}
+
 	input_dev->dev.parent = &xpad->intf->dev;
 
 	input_set_drvdata(input_dev, xpad);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/keyboard/gpio_keys.c linux-libre-4.10-rc8-gnu/drivers/input/keyboard/gpio_keys.c
--- linux-libre-4.9-gnu/drivers/input/keyboard/gpio_keys.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/keyboard/gpio_keys.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,15 +26,15 @@
 #include <linux/gpio_keys.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/spinlock.h>
 
 struct gpio_button_data {
 	const struct gpio_keys_button *button;
 	struct input_dev *input;
+	struct gpio_desc *gpiod;
 
 	struct timer_list release_timer;
 	unsigned int release_delay;	/* in msecs, for IRQ-only buttons */
@@ -140,7 +140,7 @@ static void gpio_keys_disable_button(str
 		 */
 		disable_irq(bdata->irq);
 
-		if (gpio_is_valid(bdata->button->gpio))
+		if (bdata->gpiod)
 			cancel_delayed_work_sync(&bdata->work);
 		else
 			del_timer_sync(&bdata->release_timer);
@@ -358,19 +358,20 @@ static void gpio_keys_gpio_report_event(
 	const struct gpio_keys_button *button = bdata->button;
 	struct input_dev *input = bdata->input;
 	unsigned int type = button->type ?: EV_KEY;
-	int state = gpio_get_value_cansleep(button->gpio);
+	int state;
 
+	state = gpiod_get_value_cansleep(bdata->gpiod);
 	if (state < 0) {
-		dev_err(input->dev.parent, "failed to get gpio state\n");
+		dev_err(input->dev.parent,
+			"failed to get gpio state: %d\n", state);
 		return;
 	}
 
-	state = (state ? 1 : 0) ^ button->active_low;
 	if (type == EV_ABS) {
 		if (state)
 			input_event(input, type, button->code, button->value);
 	} else {
-		input_event(input, type, button->code, !!state);
+		input_event(input, type, button->code, state);
 	}
 	input_sync(input);
 }
@@ -456,7 +457,7 @@ static void gpio_keys_quiesce_key(void *
 {
 	struct gpio_button_data *bdata = data;
 
-	if (gpio_is_valid(bdata->button->gpio))
+	if (bdata->gpiod)
 		cancel_delayed_work_sync(&bdata->work);
 	else
 		del_timer_sync(&bdata->release_timer);
@@ -465,7 +466,8 @@ static void gpio_keys_quiesce_key(void *
 static int gpio_keys_setup_key(struct platform_device *pdev,
 				struct input_dev *input,
 				struct gpio_button_data *bdata,
-				const struct gpio_keys_button *button)
+				const struct gpio_keys_button *button,
+				struct fwnode_handle *child)
 {
 	const char *desc = button->desc ? button->desc : "gpio_keys";
 	struct device *dev = &pdev->dev;
@@ -478,18 +480,56 @@ static int gpio_keys_setup_key(struct pl
 	bdata->button = button;
 	spin_lock_init(&bdata->lock);
 
-	if (gpio_is_valid(button->gpio)) {
+	if (child) {
+		bdata->gpiod = devm_get_gpiod_from_child(dev, NULL, child);
+		if (IS_ERR(bdata->gpiod)) {
+			error = PTR_ERR(bdata->gpiod);
+			if (error == -ENOENT) {
+				/*
+				 * GPIO is optional, we may be dealing with
+				 * purely interrupt-driven setup.
+				 */
+				bdata->gpiod = NULL;
+			} else {
+				if (error != -EPROBE_DEFER)
+					dev_err(dev, "failed to get gpio: %d\n",
+						error);
+				return error;
+			}
+		} else {
+			error = gpiod_direction_input(bdata->gpiod);
+			if (error) {
+				dev_err(dev, "Failed to configure GPIO %d as input: %d\n",
+					desc_to_gpio(bdata->gpiod), error);
+				return error;
+			}
+		}
+	} else if (gpio_is_valid(button->gpio)) {
+		/*
+		 * Legacy GPIO number, so request the GPIO here and
+		 * convert it to descriptor.
+		 */
+		unsigned flags = GPIOF_IN;
 
-		error = devm_gpio_request_one(&pdev->dev, button->gpio,
-					      GPIOF_IN, desc);
+		if (button->active_low)
+			flags |= GPIOF_ACTIVE_LOW;
+
+		error = devm_gpio_request_one(&pdev->dev, button->gpio, flags,
+					      desc);
 		if (error < 0) {
 			dev_err(dev, "Failed to request GPIO %d, error %d\n",
 				button->gpio, error);
 			return error;
 		}
 
+		bdata->gpiod = gpio_to_desc(button->gpio);
+		if (!bdata->gpiod)
+			return -EINVAL;
+	}
+
+	if (bdata->gpiod) {
 		if (button->debounce_interval) {
-			error = gpio_set_debounce(button->gpio,
+			error = gpiod_set_debounce(bdata->gpiod,
 					button->debounce_interval * 1000);
 			/* use timer if gpiolib doesn't provide debounce */
 			if (error < 0)
@@ -500,7 +540,7 @@ static int gpio_keys_setup_key(struct pl
 		if (button->irq) {
 			bdata->irq = button->irq;
 		} else {
-			irq = gpio_to_irq(button->gpio);
+			irq = gpiod_to_irq(bdata->gpiod);
 			if (irq < 0) {
 				error = irq;
 				dev_err(dev,
@@ -518,9 +558,10 @@ static int gpio_keys_setup_key(struct pl
 
 	} else {
 		if (!button->irq) {
-			dev_err(dev, "No IRQ specified\n");
+			dev_err(dev, "Found button without gpio or irq\n");
 			return -EINVAL;
 		}
+
 		bdata->irq = button->irq;
 
 		if (button->type && button->type != EV_KEY) {
@@ -575,7 +616,7 @@ static void gpio_keys_report_state(struc
 
 	for (i = 0; i < ddata->pdata->nbuttons; i++) {
 		struct gpio_button_data *bdata = &ddata->data[i];
-		if (gpio_is_valid(bdata->button->gpio))
+		if (bdata->gpiod)
 			gpio_keys_gpio_report_event(bdata);
 	}
 	input_sync(input);
@@ -612,25 +653,18 @@ static void gpio_keys_close(struct input
  * Handlers for alternative sources of platform_data
  */
 
-#ifdef CONFIG_OF
 /*
- * Translate OpenFirmware node properties into platform_data
+ * Translate properties into platform_data
  */
 static struct gpio_keys_platform_data *
 gpio_keys_get_devtree_pdata(struct device *dev)
 {
-	struct device_node *node, *pp;
 	struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button *button;
-	int error;
+	struct fwnode_handle *child;
 	int nbuttons;
-	int i;
-
-	node = dev->of_node;
-	if (!node)
-		return ERR_PTR(-ENODEV);
 
-	nbuttons = of_get_available_child_count(node);
+	nbuttons = device_get_child_node_count(dev);
 	if (nbuttons == 0)
 		return ERR_PTR(-ENODEV);
 
@@ -640,64 +674,47 @@ gpio_keys_get_devtree_pdata(struct devic
 	if (!pdata)
 		return ERR_PTR(-ENOMEM);
 
-	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
-	pdata->nbuttons = nbuttons;
-
-	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
-
-	of_property_read_string(node, "label", &pdata->name);
-
-	i = 0;
-	for_each_available_child_of_node(node, pp) {
-		enum of_gpio_flags flags;
+	button = (struct gpio_keys_button *)(pdata + 1);
 
-		button = &pdata->buttons[i++];
+	pdata->buttons = button;
+	pdata->nbuttons = nbuttons;
 
-		button->gpio = of_get_gpio_flags(pp, 0, &flags);
-		if (button->gpio < 0) {
-			error = button->gpio;
-			if (error != -ENOENT) {
-				if (error != -EPROBE_DEFER)
-					dev_err(dev,
-						"Failed to get gpio flags, error: %d\n",
-						error);
-				return ERR_PTR(error);
-			}
-		} else {
-			button->active_low = flags & OF_GPIO_ACTIVE_LOW;
-		}
+	pdata->rep = device_property_read_bool(dev, "autorepeat");
 
-		button->irq = irq_of_parse_and_map(pp, 0);
+	device_property_read_string(dev, "label", &pdata->name);
 
-		if (!gpio_is_valid(button->gpio) && !button->irq) {
-			dev_err(dev, "Found button without gpios or irqs\n");
-			return ERR_PTR(-EINVAL);
-		}
+	device_for_each_child_node(dev, child) {
+		if (is_of_node(child))
+			button->irq =
+				irq_of_parse_and_map(to_of_node(child), 0);
 
-		if (of_property_read_u32(pp, "linux,code", &button->code)) {
-			dev_err(dev, "Button without keycode: 0x%x\n",
-				button->gpio);
+		if (fwnode_property_read_u32(child, "linux,code",
+					     &button->code)) {
+			dev_err(dev, "Button without keycode\n");
+			fwnode_handle_put(child);
 			return ERR_PTR(-EINVAL);
 		}
 
-		button->desc = of_get_property(pp, "label", NULL);
+		fwnode_property_read_string(child, "label", &button->desc);
 
-		if (of_property_read_u32(pp, "linux,input-type", &button->type))
+		if (fwnode_property_read_u32(child, "linux,input-type",
+					     &button->type))
 			button->type = EV_KEY;
 
-		button->wakeup = of_property_read_bool(pp, "wakeup-source") ||
-				 /* legacy name */
-				 of_property_read_bool(pp, "gpio-key,wakeup");
+		button->wakeup =
+			fwnode_property_read_bool(child, "wakeup-source") ||
+			/* legacy name */
+			fwnode_property_read_bool(child, "gpio-key,wakeup");
 
-		button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL);
+		button->can_disable =
+			fwnode_property_read_bool(child, "linux,can-disable");
 
-		if (of_property_read_u32(pp, "debounce-interval",
+		if (fwnode_property_read_u32(child, "debounce-interval",
 					 &button->debounce_interval))
 			button->debounce_interval = 5;
-	}
 
-	if (pdata->nbuttons == 0)
-		return ERR_PTR(-EINVAL);
+		button++;
+	}
 
 	return pdata;
 }
@@ -708,20 +725,11 @@ static const struct of_device_id gpio_ke
 };
 MODULE_DEVICE_TABLE(of, gpio_keys_of_match);
 
-#else
-
-static inline struct gpio_keys_platform_data *
-gpio_keys_get_devtree_pdata(struct device *dev)
-{
-	return ERR_PTR(-ENODEV);
-}
-
-#endif
-
 static int gpio_keys_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
+	struct fwnode_handle *child = NULL;
 	struct gpio_keys_drvdata *ddata;
 	struct input_dev *input;
 	size_t size;
@@ -774,14 +782,28 @@ static int gpio_keys_probe(struct platfo
 		const struct gpio_keys_button *button = &pdata->buttons[i];
 		struct gpio_button_data *bdata = &ddata->data[i];
 
-		error = gpio_keys_setup_key(pdev, input, bdata, button);
-		if (error)
+		if (!dev_get_platdata(dev)) {
+			child = device_get_next_child_node(&pdev->dev, child);
+			if (!child) {
+				dev_err(&pdev->dev,
+					"missing child device node for entry %d\n",
+					i);
+				return -EINVAL;
+			}
+		}
+
+		error = gpio_keys_setup_key(pdev, input, bdata, button, child);
+		if (error) {
+			fwnode_handle_put(child);
 			return error;
+		}
 
 		if (button->wakeup)
 			wakeup = 1;
 	}
 
+	fwnode_handle_put(child);
+
 	error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
 	if (error) {
 		dev_err(dev, "Unable to export keys/switches, error: %d\n",
@@ -814,8 +836,7 @@ static int gpio_keys_remove(struct platf
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int gpio_keys_suspend(struct device *dev)
+static int __maybe_unused gpio_keys_suspend(struct device *dev)
 {
 	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
 	struct input_dev *input = ddata->input;
@@ -837,7 +858,7 @@ static int gpio_keys_suspend(struct devi
 	return 0;
 }
 
-static int gpio_keys_resume(struct device *dev)
+static int __maybe_unused gpio_keys_resume(struct device *dev)
 {
 	struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
 	struct input_dev *input = ddata->input;
@@ -863,7 +884,6 @@ static int gpio_keys_resume(struct devic
 	gpio_keys_report_state(ddata);
 	return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
 
@@ -873,7 +893,7 @@ static struct platform_driver gpio_keys_
 	.driver		= {
 		.name	= "gpio-keys",
 		.pm	= &gpio_keys_pm_ops,
-		.of_match_table = of_match_ptr(gpio_keys_of_match),
+		.of_match_table = gpio_keys_of_match,
 	}
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/keyboard/gpio_keys_polled.c linux-libre-4.10-rc8-gnu/drivers/input/keyboard/gpio_keys_polled.c
--- linux-libre-4.9-gnu/drivers/input/keyboard/gpio_keys_polled.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/keyboard/gpio_keys_polled.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,10 +30,10 @@
 #define DRV_NAME	"gpio-keys-polled"
 
 struct gpio_keys_button_data {
+	struct gpio_desc *gpiod;
 	int last_state;
 	int count;
 	int threshold;
-	int can_sleep;
 };
 
 struct gpio_keys_polled_dev {
@@ -46,7 +46,7 @@ struct gpio_keys_polled_dev {
 };
 
 static void gpio_keys_button_event(struct input_polled_dev *dev,
-				   struct gpio_keys_button *button,
+				   const struct gpio_keys_button *button,
 				   int state)
 {
 	struct gpio_keys_polled_dev *bdev = dev->private;
@@ -70,21 +70,22 @@ static void gpio_keys_button_event(struc
 }
 
 static void gpio_keys_polled_check_state(struct input_polled_dev *dev,
-					 struct gpio_keys_button *button,
+					 const struct gpio_keys_button *button,
 					 struct gpio_keys_button_data *bdata)
 {
 	int state;
 
-	if (bdata->can_sleep)
-		state = !!gpiod_get_value_cansleep(button->gpiod);
-	else
-		state = !!gpiod_get_value(button->gpiod);
-
-	gpio_keys_button_event(dev, button, state);
+	state = gpiod_get_value_cansleep(bdata->gpiod);
+	if (state < 0) {
+		dev_err(dev->input->dev.parent,
+			"failed to get gpio state: %d\n", state);
+	} else {
+		gpio_keys_button_event(dev, button, state);
 
-	if (state != bdata->last_state) {
-		bdata->count = 0;
-		bdata->last_state = state;
+		if (state != bdata->last_state) {
+			bdata->count = 0;
+			bdata->last_state = state;
+		}
 	}
 }
 
@@ -142,48 +143,35 @@ static void gpio_keys_polled_close(struc
 		pdata->disable(bdev->dev);
 }
 
-static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
+static struct gpio_keys_platform_data *
+gpio_keys_polled_get_devtree_pdata(struct device *dev)
 {
 	struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button *button;
 	struct fwnode_handle *child;
-	int error;
 	int nbuttons;
 
 	nbuttons = device_get_child_node_count(dev);
 	if (nbuttons == 0)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
 	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button),
 			     GFP_KERNEL);
 	if (!pdata)
 		return ERR_PTR(-ENOMEM);
 
-	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
+	button = (struct gpio_keys_button *)(pdata + 1);
+
+	pdata->buttons = button;
+	pdata->nbuttons = nbuttons;
 
 	pdata->rep = device_property_present(dev, "autorepeat");
 	device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
 
 	device_for_each_child_node(dev, child) {
-		struct gpio_desc *desc;
-
-		desc = devm_get_gpiod_from_child(dev, NULL, child);
-		if (IS_ERR(desc)) {
-			error = PTR_ERR(desc);
-			if (error != -EPROBE_DEFER)
-				dev_err(dev,
-					"Failed to get gpio flags, error: %d\n",
-					error);
-			fwnode_handle_put(child);
-			return ERR_PTR(error);
-		}
-
-		button = &pdata->buttons[pdata->nbuttons++];
-		button->gpiod = desc;
-
-		if (fwnode_property_read_u32(child, "linux,code", &button->code)) {
-			dev_err(dev, "Button without keycode: %d\n",
-				pdata->nbuttons - 1);
+		if (fwnode_property_read_u32(child, "linux,code",
+					     &button->code)) {
+			dev_err(dev, "button without keycode\n");
 			fwnode_handle_put(child);
 			return ERR_PTR(-EINVAL);
 		}
@@ -206,10 +194,9 @@ static struct gpio_keys_platform_data *g
 		if (fwnode_property_read_u32(child, "debounce-interval",
 					     &button->debounce_interval))
 			button->debounce_interval = 5;
-	}
 
-	if (pdata->nbuttons == 0)
-		return ERR_PTR(-EINVAL);
+		button++;
+	}
 
 	return pdata;
 }
@@ -220,7 +207,7 @@ static void gpio_keys_polled_set_abs_par
 	int i, min = 0, max = 0;
 
 	for (i = 0; i < pdata->nbuttons; i++) {
-		struct gpio_keys_button *button = &pdata->buttons[i];
+		const struct gpio_keys_button *button = &pdata->buttons[i];
 
 		if (button->type != EV_ABS || button->code != code)
 			continue;
@@ -230,6 +217,7 @@ static void gpio_keys_polled_set_abs_par
 		if (button->value > max)
 			max = button->value;
 	}
+
 	input_set_abs_params(input, code, min, max, 0, 0);
 }
 
@@ -242,6 +230,7 @@ MODULE_DEVICE_TABLE(of, gpio_keys_polled
 static int gpio_keys_polled_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct fwnode_handle *child = NULL;
 	const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev);
 	struct gpio_keys_polled_dev *bdev;
 	struct input_polled_dev *poll_dev;
@@ -254,10 +243,6 @@ static int gpio_keys_polled_probe(struct
 		pdata = gpio_keys_polled_get_devtree_pdata(dev);
 		if (IS_ERR(pdata))
 			return PTR_ERR(pdata);
-		if (!pdata) {
-			dev_err(dev, "missing platform data\n");
-			return -EINVAL;
-		}
 	}
 
 	if (!pdata->poll_interval) {
@@ -300,20 +285,48 @@ static int gpio_keys_polled_probe(struct
 		__set_bit(EV_REP, input->evbit);
 
 	for (i = 0; i < pdata->nbuttons; i++) {
-		struct gpio_keys_button *button = &pdata->buttons[i];
+		const struct gpio_keys_button *button = &pdata->buttons[i];
 		struct gpio_keys_button_data *bdata = &bdev->data[i];
 		unsigned int type = button->type ?: EV_KEY;
 
 		if (button->wakeup) {
 			dev_err(dev, DRV_NAME " does not support wakeup\n");
+			fwnode_handle_put(child);
 			return -EINVAL;
 		}
 
-		/*
-		 * Legacy GPIO number so request the GPIO here and
-		 * convert it to descriptor.
-		 */
-		if (!button->gpiod && gpio_is_valid(button->gpio)) {
+		if (!dev_get_platdata(dev)) {
+			/* No legacy static platform data */
+			child = device_get_next_child_node(dev, child);
+			if (!child) {
+				dev_err(dev, "missing child device node\n");
+				return -EINVAL;
+			}
+
+			bdata->gpiod = devm_get_gpiod_from_child(dev, NULL,
+								 child);
+			if (IS_ERR(bdata->gpiod)) {
+				error = PTR_ERR(bdata->gpiod);
+				if (error != -EPROBE_DEFER)
+					dev_err(dev,
+						"failed to get gpio: %d\n",
+						error);
+				fwnode_handle_put(child);
+				return error;
+			}
+
+			error = gpiod_direction_input(bdata->gpiod);
+			if (error) {
+				dev_err(dev, "Failed to configure GPIO %d as input: %d\n",
+					desc_to_gpio(bdata->gpiod), error);
+				fwnode_handle_put(child);
+				return error;
+			}
+		} else if (gpio_is_valid(button->gpio)) {
+			/*
+			 * Legacy GPIO number so request the GPIO here and
+			 * convert it to descriptor.
+			 */
 			unsigned flags = GPIOF_IN;
 
 			if (button->active_low)
@@ -322,18 +335,21 @@ static int gpio_keys_polled_probe(struct
 			error = devm_gpio_request_one(&pdev->dev, button->gpio,
 					flags, button->desc ? : DRV_NAME);
 			if (error) {
-				dev_err(dev, "unable to claim gpio %u, err=%d\n",
+				dev_err(dev,
+					"unable to claim gpio %u, err=%d\n",
 					button->gpio, error);
 				return error;
 			}
 
-			button->gpiod = gpio_to_desc(button->gpio);
+			bdata->gpiod = gpio_to_desc(button->gpio);
+			if (!bdata->gpiod) {
+				dev_err(dev,
+					"unable to convert gpio %u to descriptor\n",
+					button->gpio);
+				return -EINVAL;
+			}
 		}
 
-		if (IS_ERR(button->gpiod))
-			return PTR_ERR(button->gpiod);
-
-		bdata->can_sleep = gpiod_cansleep(button->gpiod);
 		bdata->last_state = -1;
 		bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
 						pdata->poll_interval);
@@ -344,6 +360,8 @@ static int gpio_keys_polled_probe(struct
 							button->code);
 	}
 
+	fwnode_handle_put(child);
+
 	bdev->poll_dev = poll_dev;
 	bdev->dev = dev;
 	bdev->pdata = pdata;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/keyboard/lpc32xx-keys.c linux-libre-4.10-rc8-gnu/drivers/input/keyboard/lpc32xx-keys.c
--- linux-libre-4.9-gnu/drivers/input/keyboard/lpc32xx-keys.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/keyboard/lpc32xx-keys.c	2017-02-12 16:03:20.000000000 -0500
@@ -182,7 +182,7 @@ static int lpc32xx_kscan_probe(struct pl
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq < 0 || irq >= NR_IRQS) {
+	if (irq < 0) {
 		dev_err(&pdev->dev, "failed to get platform irq\n");
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/keyboard/pxa27x_keypad.c linux-libre-4.10-rc8-gnu/drivers/input/keyboard/pxa27x_keypad.c
--- linux-libre-4.9-gnu/drivers/input/keyboard/pxa27x_keypad.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/keyboard/pxa27x_keypad.c	2017-02-12 16:03:20.000000000 -0500
@@ -316,7 +316,7 @@ static int pxa27x_keypad_build_keycode_f
 	error = of_property_read_u32(np, "marvell,debounce-interval",
 				     &pdata->debounce_interval);
 	if (error) {
-		dev_err(dev, "failed to parse debpunce-interval\n");
+		dev_err(dev, "failed to parse debounce-interval\n");
 		return error;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/keyboard/tca8418_keypad.c linux-libre-4.10-rc8-gnu/drivers/input/keyboard/tca8418_keypad.c
--- linux-libre-4.9-gnu/drivers/input/keyboard/tca8418_keypad.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/keyboard/tca8418_keypad.c	2017-02-12 16:03:20.000000000 -0500
@@ -164,11 +164,18 @@ static void tca8418_read_keypad(struct t
 	int error, col, row;
 	u8 reg, state, code;
 
-	/* Initial read of the key event FIFO */
-	error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
+	do {
+		error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
+		if (error < 0) {
+			dev_err(&keypad_data->client->dev,
+				"unable to read REG_KEY_EVENT_A\n");
+			break;
+		}
+
+		/* Assume that key code 0 signifies empty FIFO */
+		if (reg <= 0)
+			break;
 
-	/* Assume that key code 0 signifies empty FIFO */
-	while (error >= 0 && reg > 0) {
 		state = reg & KEY_EVENT_VALUE;
 		code  = reg & KEY_EVENT_CODE;
 
@@ -184,11 +191,7 @@ static void tca8418_read_keypad(struct t
 
 		/* Read for next loop */
 		error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, &reg);
-	}
-
-	if (error < 0)
-		dev_err(&keypad_data->client->dev,
-			"unable to read REG_KEY_EVENT_A\n");
+	} while (1);
 
 	input_sync(input);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/adxl34x-i2c.c linux-libre-4.10-rc8-gnu/drivers/input/misc/adxl34x-i2c.c
--- linux-libre-4.9-gnu/drivers/input/misc/adxl34x-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/adxl34x-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -136,7 +136,6 @@ static const struct i2c_device_id adxl34
 
 MODULE_DEVICE_TABLE(i2c, adxl34x_id);
 
-#ifdef CONFIG_OF
 static const struct of_device_id adxl34x_of_id[] = {
 	/*
 	 * The ADXL346 is backward-compatible with the ADXL345. Differences are
@@ -153,13 +152,12 @@ static const struct of_device_id adxl34x
 };
 
 MODULE_DEVICE_TABLE(of, adxl34x_of_id);
-#endif
 
 static struct i2c_driver adxl34x_driver = {
 	.driver = {
 		.name = "adxl34x",
 		.pm = &adxl34x_i2c_pm,
-		.of_match_table = of_match_ptr(adxl34x_of_id),
+		.of_match_table = adxl34x_of_id,
 	},
 	.probe    = adxl34x_i2c_probe,
 	.remove   = adxl34x_i2c_remove,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/arizona-haptics.c linux-libre-4.10-rc8-gnu/drivers/input/misc/arizona-haptics.c
--- linux-libre-4.9-gnu/drivers/input/misc/arizona-haptics.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/arizona-haptics.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,8 @@ static void arizona_haptics_work(struct
 						       struct arizona_haptics,
 						       work);
 	struct arizona *arizona = haptics->arizona;
+	struct snd_soc_component *component =
+		snd_soc_dapm_to_component(arizona->dapm);
 	int ret;
 
 	if (!haptics->arizona->dapm) {
@@ -66,7 +68,7 @@ static void arizona_haptics_work(struct
 			return;
 		}
 
-		ret = snd_soc_dapm_enable_pin(arizona->dapm, "HAPTICS");
+		ret = snd_soc_component_enable_pin(component, "HAPTICS");
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to start HAPTICS: %d\n",
 				ret);
@@ -81,7 +83,7 @@ static void arizona_haptics_work(struct
 		}
 	} else {
 		/* This disable sequence will be a noop if already enabled */
-		ret = snd_soc_dapm_disable_pin(arizona->dapm, "HAPTICS");
+		ret = snd_soc_component_disable_pin(component, "HAPTICS");
 		if (ret != 0) {
 			dev_err(arizona->dev, "Failed to disable HAPTICS: %d\n",
 				ret);
@@ -140,11 +142,14 @@ static int arizona_haptics_play(struct i
 static void arizona_haptics_close(struct input_dev *input)
 {
 	struct arizona_haptics *haptics = input_get_drvdata(input);
+	struct snd_soc_component *component;
 
 	cancel_work_sync(&haptics->work);
 
-	if (haptics->arizona->dapm)
-		snd_soc_dapm_disable_pin(haptics->arizona->dapm, "HAPTICS");
+	if (haptics->arizona->dapm) {
+		component = snd_soc_dapm_to_component(haptics->arizona->dapm);
+		snd_soc_component_disable_pin(component, "HAPTICS");
+	}
 }
 
 static int arizona_haptics_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/atlas_btns.c linux-libre-4.10-rc8-gnu/drivers/input/misc/atlas_btns.c
--- linux-libre-4.9-gnu/drivers/input/misc/atlas_btns.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/atlas_btns.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/input.h>
 #include <linux/types.h>
 #include <linux/acpi.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define ACPI_ATLAS_NAME		"Atlas ACPI"
 #define ACPI_ATLAS_CLASS	"Atlas"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/bma150.c linux-libre-4.10-rc8-gnu/drivers/input/misc/bma150.c
--- linux-libre-4.9-gnu/drivers/input/misc/bma150.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/bma150.c	2017-02-12 16:03:20.000000000 -0500
@@ -538,8 +538,13 @@ static int bma150_probe(struct i2c_clien
 		return -EIO;
 	}
 
+	/*
+	 * Note if the IIO CONFIG_BMA180 driver is enabled we want to fail
+	 * the probe for the bma180 as the iio driver is preferred.
+	 */
 	chip_id = i2c_smbus_read_byte_data(client, BMA150_CHIP_ID_REG);
-	if (chip_id != BMA150_CHIP_ID && chip_id != BMA180_CHIP_ID) {
+	if (chip_id != BMA150_CHIP_ID &&
+	    (IS_ENABLED(CONFIG_BMA180) || chip_id != BMA180_CHIP_ID)) {
 		dev_err(&client->dev, "BMA150 chip id error: %d\n", chip_id);
 		return -EINVAL;
 	}
@@ -643,7 +648,9 @@ static UNIVERSAL_DEV_PM_OPS(bma150_pm, b
 
 static const struct i2c_device_id bma150_id[] = {
 	{ "bma150", 0 },
+#if !IS_ENABLED(CONFIG_BMA180)
 	{ "bma180", 0 },
+#endif
 	{ "smb380", 0 },
 	{ "bma023", 0 },
 	{ }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/da9063_onkey.c linux-libre-4.10-rc8-gnu/drivers/input/misc/da9063_onkey.c
--- linux-libre-4.9-gnu/drivers/input/misc/da9063_onkey.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/da9063_onkey.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * OnKey device driver for DA9063 and DA9062 PMICs
+ * OnKey device driver for DA9063, DA9062 and DA9061 PMICs
  * Copyright (C) 2015  Dialog Semiconductor Ltd.
  *
  * This program is free software; you can redistribute it and/or
@@ -87,6 +87,7 @@ static const struct of_device_id da9063_
 	{ .compatible = "dlg,da9062-onkey", .data = &da9062_regs },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
 
 static void da9063_poll_on(struct work_struct *work)
 {
@@ -149,13 +150,13 @@ static void da9063_poll_on(struct work_s
 			 * and then send shutdown command
 			 */
 			dev_dbg(&onkey->input->dev,
-				"Sending SHUTDOWN to DA9063 ...\n");
+				"Sending SHUTDOWN to PMIC ...\n");
 			error = regmap_write(onkey->regmap,
 					     config->onkey_shutdown,
 					     config->onkey_shutdown_mask);
 			if (error)
 				dev_err(&onkey->input->dev,
-					"Cannot SHUTDOWN DA9063: %d\n",
+					"Cannot SHUTDOWN PMIC: %d\n",
 					error);
 		}
 	}
@@ -300,6 +301,6 @@ static struct platform_driver da9063_onk
 module_platform_driver(da9063_onkey_driver);
 
 MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
-MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063 and DA9062");
+MODULE_DESCRIPTION("Onkey device driver for Dialog DA9063, DA9062 and DA9061");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DA9063_DRVNAME_ONKEY);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/drv260x.c linux-libre-4.10-rc8-gnu/drivers/input/misc/drv260x.c
--- linux-libre-4.9-gnu/drivers/input/misc/drv260x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/drv260x.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,8 +18,6 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/module.h>
-#include <linux/of_gpio.h>
-#include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -27,7 +25,6 @@
 #include <linux/regulator/consumer.h>
 
 #include <dt-bindings/input/ti-drv260x.h>
-#include <linux/platform_data/drv260x-pdata.h>
 
 #define DRV260X_STATUS		0x0
 #define DRV260X_MODE		0x1
@@ -468,90 +465,39 @@ static const struct regmap_config drv260
 	.cache_type = REGCACHE_NONE,
 };
 
-#ifdef CONFIG_OF
-static int drv260x_parse_dt(struct device *dev,
-			    struct drv260x_data *haptics)
-{
-	struct device_node *np = dev->of_node;
-	unsigned int voltage;
-	int error;
-
-	error = of_property_read_u32(np, "mode", &haptics->mode);
-	if (error) {
-		dev_err(dev, "%s: No entry for mode\n", __func__);
-		return error;
-	}
-
-	error = of_property_read_u32(np, "library-sel", &haptics->library);
-	if (error) {
-		dev_err(dev, "%s: No entry for library selection\n",
-			__func__);
-		return error;
-	}
-
-	error = of_property_read_u32(np, "vib-rated-mv", &voltage);
-	if (!error)
-		haptics->rated_voltage = drv260x_calculate_voltage(voltage);
-
-
-	error = of_property_read_u32(np, "vib-overdrive-mv", &voltage);
-	if (!error)
-		haptics->overdrive_voltage = drv260x_calculate_voltage(voltage);
-
-	return 0;
-}
-#else
-static inline int drv260x_parse_dt(struct device *dev,
-				   struct drv260x_data *haptics)
-{
-	dev_err(dev, "no platform data defined\n");
-
-	return -EINVAL;
-}
-#endif
-
 static int drv260x_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
-	const struct drv260x_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct device *dev = &client->dev;
 	struct drv260x_data *haptics;
+	u32 voltage;
 	int error;
 
-	haptics = devm_kzalloc(&client->dev, sizeof(*haptics), GFP_KERNEL);
+	haptics = devm_kzalloc(dev, sizeof(*haptics), GFP_KERNEL);
 	if (!haptics)
 		return -ENOMEM;
 
-	haptics->rated_voltage = DRV260X_DEF_OD_CLAMP_VOLT;
-	haptics->rated_voltage = DRV260X_DEF_RATED_VOLT;
-
-	if (pdata) {
-		haptics->mode = pdata->mode;
-		haptics->library = pdata->library_selection;
-		if (pdata->vib_overdrive_voltage)
-			haptics->overdrive_voltage = drv260x_calculate_voltage(pdata->vib_overdrive_voltage);
-		if (pdata->vib_rated_voltage)
-			haptics->rated_voltage = drv260x_calculate_voltage(pdata->vib_rated_voltage);
-	} else if (client->dev.of_node) {
-		error = drv260x_parse_dt(&client->dev, haptics);
-		if (error)
-			return error;
-	} else {
-		dev_err(&client->dev, "Platform data not set\n");
-		return -ENODEV;
+	error = device_property_read_u32(dev, "mode", &haptics->mode);
+	if (error) {
+		dev_err(dev, "Can't fetch 'mode' property: %d\n", error);
+		return error;
 	}
 
-
 	if (haptics->mode < DRV260X_LRA_MODE ||
 	    haptics->mode > DRV260X_ERM_MODE) {
-		dev_err(&client->dev,
-			"Vibrator mode is invalid: %i\n",
-			haptics->mode);
+		dev_err(dev, "Vibrator mode is invalid: %i\n", haptics->mode);
 		return -EINVAL;
 	}
 
+	error = device_property_read_u32(dev, "library-sel", &haptics->library);
+	if (error) {
+		dev_err(dev, "Can't fetch 'library-sel' property: %d\n", error);
+		return error;
+	}
+
 	if (haptics->library < DRV260X_LIB_EMPTY ||
 	    haptics->library > DRV260X_ERM_LIB_F) {
-		dev_err(&client->dev,
+		dev_err(dev,
 			"Library value is invalid: %i\n", haptics->library);
 		return -EINVAL;
 	}
@@ -559,40 +505,44 @@ static int drv260x_probe(struct i2c_clie
 	if (haptics->mode == DRV260X_LRA_MODE &&
 	    haptics->library != DRV260X_LIB_EMPTY &&
 	    haptics->library != DRV260X_LIB_LRA) {
-		dev_err(&client->dev,
-			"LRA Mode with ERM Library mismatch\n");
+		dev_err(dev, "LRA Mode with ERM Library mismatch\n");
 		return -EINVAL;
 	}
 
 	if (haptics->mode == DRV260X_ERM_MODE &&
 	    (haptics->library == DRV260X_LIB_EMPTY ||
 	     haptics->library == DRV260X_LIB_LRA)) {
-		dev_err(&client->dev,
-			"ERM Mode with LRA Library mismatch\n");
+		dev_err(dev, "ERM Mode with LRA Library mismatch\n");
 		return -EINVAL;
 	}
 
-	haptics->regulator = devm_regulator_get(&client->dev, "vbat");
+	error = device_property_read_u32(dev, "vib-rated-mv", &voltage);
+	haptics->rated_voltage = error ? DRV260X_DEF_RATED_VOLT :
+					 drv260x_calculate_voltage(voltage);
+
+	error = device_property_read_u32(dev, "vib-overdrive-mv", &voltage);
+	haptics->overdrive_voltage = error ? DRV260X_DEF_OD_CLAMP_VOLT :
+					     drv260x_calculate_voltage(voltage);
+
+	haptics->regulator = devm_regulator_get(dev, "vbat");
 	if (IS_ERR(haptics->regulator)) {
 		error = PTR_ERR(haptics->regulator);
-		dev_err(&client->dev,
-			"unable to get regulator, error: %d\n", error);
+		dev_err(dev, "unable to get regulator, error: %d\n", error);
 		return error;
 	}
 
-	haptics->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable",
+	haptics->enable_gpio = devm_gpiod_get_optional(dev, "enable",
 						       GPIOD_OUT_HIGH);
 	if (IS_ERR(haptics->enable_gpio))
 		return PTR_ERR(haptics->enable_gpio);
 
-	haptics->input_dev = devm_input_allocate_device(&client->dev);
+	haptics->input_dev = devm_input_allocate_device(dev);
 	if (!haptics->input_dev) {
 		dev_err(&client->dev, "Failed to allocate input device\n");
 		return -ENOMEM;
 	}
 
 	haptics->input_dev->name = "drv260x:haptics";
-	haptics->input_dev->dev.parent = client->dev.parent;
 	haptics->input_dev->close = drv260x_close;
 	input_set_drvdata(haptics->input_dev, haptics);
 	input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
@@ -600,8 +550,7 @@ static int drv260x_probe(struct i2c_clie
 	error = input_ff_create_memless(haptics->input_dev, NULL,
 					drv260x_haptics_play);
 	if (error) {
-		dev_err(&client->dev, "input_ff_create() failed: %d\n",
-			error);
+		dev_err(dev, "input_ff_create() failed: %d\n", error);
 		return error;
 	}
 
@@ -613,21 +562,19 @@ static int drv260x_probe(struct i2c_clie
 	haptics->regmap = devm_regmap_init_i2c(client, &drv260x_regmap_config);
 	if (IS_ERR(haptics->regmap)) {
 		error = PTR_ERR(haptics->regmap);
-		dev_err(&client->dev, "Failed to allocate register map: %d\n",
-			error);
+		dev_err(dev, "Failed to allocate register map: %d\n", error);
 		return error;
 	}
 
 	error = drv260x_init(haptics);
 	if (error) {
-		dev_err(&client->dev, "Device init failed: %d\n", error);
+		dev_err(dev, "Device init failed: %d\n", error);
 		return error;
 	}
 
 	error = input_register_device(haptics->input_dev);
 	if (error) {
-		dev_err(&client->dev, "couldn't register input device: %d\n",
-			error);
+		dev_err(dev, "couldn't register input device: %d\n", error);
 		return error;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/drv2665.c linux-libre-4.10-rc8-gnu/drivers/input/misc/drv2665.c
--- linux-libre-4.9-gnu/drivers/input/misc/drv2665.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/drv2665.c	2017-02-12 16:03:20.000000000 -0500
@@ -125,8 +125,8 @@ static void drv2665_close(struct input_d
 
 	cancel_work_sync(&haptics->work);
 
-	error = regmap_update_bits(haptics->regmap,
-				   DRV2665_CTRL_2, DRV2665_STANDBY, 1);
+	error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
+				   DRV2665_STANDBY, DRV2665_STANDBY);
 	if (error)
 		dev_err(&haptics->client->dev,
 			"Failed to enter standby mode: %d\n", error);
@@ -240,7 +240,7 @@ static int __maybe_unused drv2665_suspen
 
 	if (haptics->input_dev->users) {
 		ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2,
-				DRV2665_STANDBY, 1);
+					 DRV2665_STANDBY, DRV2665_STANDBY);
 		if (ret) {
 			dev_err(dev, "Failed to set standby mode\n");
 			regulator_disable(haptics->regulator);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/drv2667.c linux-libre-4.10-rc8-gnu/drivers/input/misc/drv2667.c
--- linux-libre-4.9-gnu/drivers/input/misc/drv2667.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/drv2667.c	2017-02-12 16:03:20.000000000 -0500
@@ -256,7 +256,7 @@ static void drv2667_close(struct input_d
 	cancel_work_sync(&haptics->work);
 
 	error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
-				DRV2667_STANDBY, 1);
+				   DRV2667_STANDBY, DRV2667_STANDBY);
 	if (error)
 		dev_err(&haptics->client->dev,
 			"Failed to enter standby mode: %d\n", error);
@@ -415,7 +415,7 @@ static int __maybe_unused drv2667_suspen
 
 	if (haptics->input_dev->users) {
 		ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2,
-				DRV2667_STANDBY, 1);
+					 DRV2667_STANDBY, DRV2667_STANDBY);
 		if (ret) {
 			dev_err(dev, "Failed to set standby mode\n");
 			regulator_disable(haptics->regulator);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/Kconfig linux-libre-4.10-rc8-gnu/drivers/input/misc/Kconfig
--- linux-libre-4.9-gnu/drivers/input/misc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -625,11 +625,12 @@ config INPUT_DA9055_ONKEY
 	  will be called da9055_onkey.
 
 config INPUT_DA9063_ONKEY
-	tristate "Dialog DA9062/63 OnKey"
+	tristate "Dialog DA9063/62/61 OnKey"
 	depends on MFD_DA9063 || MFD_DA9062
 	help
-	  Support the ONKEY of Dialog DA9063 and DA9062 Power Management ICs
-	  as an input device capable of reporting the power button status.
+	  Support the ONKEY of Dialog DA9063, DA9062 and DA9061 Power
+	  Management ICs as an input device capable of reporting the
+	  power button status.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called da9063_onkey.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/soc_button_array.c linux-libre-4.10-rc8-gnu/drivers/input/misc/soc_button_array.c
--- linux-libre-4.9-gnu/drivers/input/misc/soc_button_array.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/soc_button_array.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/acpi.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio_keys.h>
+#include <linux/gpio.h>
 #include <linux/platform_device.h>
 
 /*
@@ -92,7 +93,7 @@ soc_button_device_create(struct platform
 			continue;
 
 		gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
-		if (gpio < 0)
+		if (!gpio_is_valid(gpio))
 			continue;
 
 		gpio_keys[n_buttons].type = info->event_type;
@@ -166,6 +167,11 @@ static int soc_button_probe(struct platf
 
 	button_info = (struct soc_button_info *)id->driver_data;
 
+	if (gpiod_count(&pdev->dev, KBUILD_MODNAME) <= 0) {
+		dev_dbg(&pdev->dev, "no GPIO attached, ignoring...\n");
+		return -ENODEV;
+	}
+
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/tps65218-pwrbutton.c linux-libre-4.10-rc8-gnu/drivers/input/misc/tps65218-pwrbutton.c
--- linux-libre-4.9-gnu/drivers/input/misc/tps65218-pwrbutton.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/tps65218-pwrbutton.c	2017-02-12 16:03:20.000000000 -0500
@@ -150,12 +150,20 @@ static int tps6521x_pb_probe(struct plat
 	return 0;
 }
 
+static const struct platform_device_id tps6521x_pwrbtn_id_table[] = {
+	{ "tps65218-pwrbutton", },
+	{ "tps65217-pwrbutton", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, tps6521x_pwrbtn_id_table);
+
 static struct platform_driver tps6521x_pb_driver = {
 	.probe	= tps6521x_pb_probe,
 	.driver	= {
 		.name	= "tps6521x_pwrbutton",
 		.of_match_table = of_tps6521x_pb_match,
 	},
+	.id_table = tps6521x_pwrbtn_id_table,
 };
 module_platform_driver(tps6521x_pb_driver);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/uinput.c linux-libre-4.10-rc8-gnu/drivers/input/misc/uinput.c
--- linux-libre-4.9-gnu/drivers/input/misc/uinput.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/uinput.c	2017-02-12 16:03:20.000000000 -0500
@@ -263,13 +263,21 @@ static int uinput_create_device(struct u
 		return -EINVAL;
 	}
 
-	if (test_bit(ABS_MT_SLOT, dev->absbit)) {
-		nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
-		error = input_mt_init_slots(dev, nslot, 0);
-		if (error)
+	if (test_bit(EV_ABS, dev->evbit)) {
+		input_alloc_absinfo(dev);
+		if (!dev->absinfo) {
+			error = -EINVAL;
 			goto fail1;
-	} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
-		input_set_events_per_packet(dev, 60);
+		}
+
+		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
+			nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
+			error = input_mt_init_slots(dev, nslot, 0);
+			if (error)
+				goto fail1;
+		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+			input_set_events_per_packet(dev, 60);
+		}
 	}
 
 	if (test_bit(EV_FF, dev->evbit) && !udev->ff_effects_max) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/misc/xen-kbdfront.c linux-libre-4.10-rc8-gnu/drivers/input/misc/xen-kbdfront.c
--- linux-libre-4.9-gnu/drivers/input/misc/xen-kbdfront.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/misc/xen-kbdfront.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,7 +108,8 @@ static irqreturn_t input_handler(int rq,
 static int xenkbd_probe(struct xenbus_device *dev,
 				  const struct xenbus_device_id *id)
 {
-	int ret, i, abs;
+	int ret, i;
+	unsigned int abs;
 	struct xenkbd_info *info;
 	struct input_dev *kbd, *ptr;
 
@@ -127,8 +128,7 @@ static int xenkbd_probe(struct xenbus_de
 	if (!info->page)
 		goto error_nomem;
 
-	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
-		abs = 0;
+	abs = xenbus_read_unsigned(dev->otherend, "feature-abs-pointer", 0);
 	if (abs) {
 		ret = xenbus_write(XBT_NIL, dev->nodename,
 				   "request-abs-pointer", "1");
@@ -322,11 +322,8 @@ static void xenkbd_backend_changed(struc
 
 	case XenbusStateInitWait:
 InitWait:
-		ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				   "feature-abs-pointer", "%d", &val);
-		if (ret < 0)
-			val = 0;
-		if (val) {
+		if (xenbus_read_unsigned(info->xbdev->otherend,
+					 "feature-abs-pointer", 0)) {
 			ret = xenbus_write(XBT_NIL, info->xbdev->nodename,
 					   "request-abs-pointer", "1");
 			if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/mouse/alps.c linux-libre-4.10-rc8-gnu/drivers/input/mouse/alps.c
--- linux-libre-4.9-gnu/drivers/input/mouse/alps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/mouse/alps.c	2017-02-12 16:03:20.000000000 -0500
@@ -1153,15 +1153,13 @@ static void alps_process_packet_v7(struc
 		alps_process_touchpad_packet_v7(psmouse);
 }
 
-static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
+static enum SS4_PACKET_ID alps_get_pkt_id_ss4_v2(unsigned char *byte)
 {
-	unsigned char pkt_id = SS4_PACKET_ID_IDLE;
+	enum SS4_PACKET_ID pkt_id = SS4_PACKET_ID_IDLE;
 
 	switch (byte[3] & 0x30) {
 	case 0x00:
-		if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 &&
-		    (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 &&
-		    byte[5] == 0x00) {
+		if (SS4_IS_IDLE_V2(byte)) {
 			pkt_id = SS4_PACKET_ID_IDLE;
 		} else {
 			pkt_id = SS4_PACKET_ID_ONE;
@@ -1188,7 +1186,7 @@ static int alps_decode_ss4_v2(struct alp
 			      unsigned char *p, struct psmouse *psmouse)
 {
 	struct alps_data *priv = psmouse->private;
-	unsigned char pkt_id;
+	enum SS4_PACKET_ID pkt_id;
 	unsigned int no_data_x, no_data_y;
 
 	pkt_id = alps_get_pkt_id_ss4_v2(p);
@@ -1267,18 +1265,12 @@ static int alps_decode_ss4_v2(struct alp
 		break;
 
 	case SS4_PACKET_ID_STICK:
-		if (!(priv->flags & ALPS_DUALPOINT)) {
-			psmouse_warn(psmouse,
-				     "Rejected trackstick packet from non DualPoint device");
-		} else {
-			int x = (s8)(((p[0] & 1) << 7) | (p[1] & 0x7f));
-			int y = (s8)(((p[3] & 1) << 7) | (p[2] & 0x7f));
-			int pressure = (s8)(p[4] & 0x7f);
-
-			input_report_rel(priv->dev2, REL_X, x);
-			input_report_rel(priv->dev2, REL_Y, -y);
-			input_report_abs(priv->dev2, ABS_PRESSURE, pressure);
-		}
+		/*
+		 * x, y, and pressure are decoded in
+		 * alps_process_packet_ss4_v2()
+		 */
+		f->first_mp = 0;
+		f->is_mp = 0;
 		break;
 
 	case SS4_PACKET_ID_IDLE:
@@ -1346,6 +1338,27 @@ static void alps_process_packet_ss4_v2(s
 
 	priv->multi_packet = 0;
 
+	/* Report trackstick */
+	if (alps_get_pkt_id_ss4_v2(packet) == SS4_PACKET_ID_STICK) {
+		if (!(priv->flags & ALPS_DUALPOINT)) {
+			psmouse_warn(psmouse,
+				     "Rejected trackstick packet from non DualPoint device");
+			return;
+		}
+
+		input_report_rel(dev2, REL_X, SS4_TS_X_V2(packet));
+		input_report_rel(dev2, REL_Y, SS4_TS_Y_V2(packet));
+		input_report_abs(dev2, ABS_PRESSURE, SS4_TS_Z_V2(packet));
+
+		input_report_key(dev2, BTN_LEFT, f->ts_left);
+		input_report_key(dev2, BTN_RIGHT, f->ts_right);
+		input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
+
+		input_sync(dev2);
+		return;
+	}
+
+	/* Report touchpad */
 	alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4);
 
 	input_mt_report_finger_count(dev, f->fingers);
@@ -1356,13 +1369,6 @@ static void alps_process_packet_ss4_v2(s
 
 	input_report_abs(dev, ABS_PRESSURE, f->pressure);
 	input_sync(dev);
-
-	if (priv->flags & ALPS_DUALPOINT) {
-		input_report_key(dev2, BTN_LEFT, f->ts_left);
-		input_report_key(dev2, BTN_RIGHT, f->ts_right);
-		input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
-		input_sync(dev2);
-	}
 }
 
 static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/mouse/alps.h linux-libre-4.10-rc8-gnu/drivers/input/mouse/alps.h
--- linux-libre-4.9-gnu/drivers/input/mouse/alps.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/mouse/alps.h	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,15 @@ enum SS4_PACKET_ID {
 
 #define SS4_MASK_NORMAL_BUTTONS		0x07
 
-#define SS4_1F_X_V2(_b)		((_b[0] & 0x0007) |		\
+#define SS4_IS_IDLE_V2(_b)	(((_b[0]) == 0x18) &&		\
+				 ((_b[1]) == 0x10) &&		\
+				 ((_b[2]) == 0x00) &&		\
+				 ((_b[3] & 0x88) == 0x08) &&	\
+				 ((_b[4]) == 0x10) &&		\
+				 ((_b[5]) == 0x00)		\
+				)
+
+#define SS4_1F_X_V2(_b)		(((_b[0]) & 0x0007) |		\
 				 ((_b[1] << 3) & 0x0078) |	\
 				 ((_b[1] << 2) & 0x0380) |	\
 				 ((_b[2] << 5) & 0x1C00)	\
@@ -101,6 +109,18 @@ enum SS4_PACKET_ID {
 #define SS4_IS_MF_CONTINUE(_b)	((_b[2] & 0x10) == 0x10)
 #define SS4_IS_5F_DETECTED(_b)	((_b[2] & 0x10) == 0x10)
 
+#define SS4_TS_X_V2(_b)		(s8)(				\
+				 ((_b[0] & 0x01) << 7) |	\
+				 (_b[1] & 0x7F)		\
+				)
+
+#define SS4_TS_Y_V2(_b)		-(s8)(				\
+				 ((_b[3] & 0x01) << 7) |	\
+				 (_b[2] & 0x7F)		\
+				)
+
+#define SS4_TS_Z_V2(_b)		(s8)(_b[4] & 0x7F)
+
 
 #define SS4_MFPACKET_NO_AX	8160	/* X-Coordinate value */
 #define SS4_MFPACKET_NO_AY	4080	/* Y-Coordinate value */
@@ -146,7 +166,7 @@ struct alps_protocol_info {
  *   (aka command mode response) identifies the firmware minor version.  This
  *   can be used to distinguish different hardware models which are not
  *   uniquely identifiable through their E7 responses.
- * @protocol_info: information about protcol used by the device.
+ * @protocol_info: information about protocol used by the device.
  *
  * Many (but not all) ALPS touchpads can be identified by looking at the
  * values returned in the "E7 report" and/or the "EC report."  This table
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/mouse/amimouse.c linux-libre-4.10-rc8-gnu/drivers/input/mouse/amimouse.c
--- linux-libre-4.9-gnu/drivers/input/mouse/amimouse.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/mouse/amimouse.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/mouse/atarimouse.c linux-libre-4.10-rc8-gnu/drivers/input/mouse/atarimouse.c
--- linux-libre-4.9-gnu/drivers/input/mouse/atarimouse.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/mouse/atarimouse.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@
 
 #include <asm/irq.h>
 #include <asm/setup.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/atarihw.h>
 #include <asm/atarikb.h>
 #include <asm/atariints.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/mouse/elan_i2c_core.c linux-libre-4.10-rc8-gnu/drivers/input/mouse/elan_i2c_core.c
--- linux-libre-4.9-gnu/drivers/input/mouse/elan_i2c_core.c	2016-12-11 17:57:58.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/mouse/elan_i2c_core.c	2017-02-12 17:49:58.000000000 -0500
@@ -1093,19 +1093,18 @@ static int elan_probe(struct i2c_client
 	if (error)
 		return error;
 
+	dev_info(&client->dev,
+		 "Elan Touchpad: Module ID: 0x%04x, Firmware: 0x%04x, Sample: 0x%04x, IAP: 0x%04x\n",
+		 data->product_id,
+		 data->fw_version,
+		 data->sm_version,
+		 data->iap_version);
+
 	dev_dbg(&client->dev,
-		"Elan Touchpad Information:\n"
-		"    Module product ID:  0x%04x\n"
-		"    Firmware Version:  0x%04x\n"
-		"    Sample Version:  0x%04x\n"
-		"    IAP Version:  0x%04x\n"
+		"Elan Touchpad Extra Information:\n"
 		"    Max ABS X,Y:   %d,%d\n"
 		"    Width X,Y:   %d,%d\n"
 		"    Resolution X,Y:   %d,%d (dots/mm)\n",
-		data->product_id,
-		data->fw_version,
-		data->sm_version,
-		data->iap_version,
 		data->max_x, data->max_y,
 		data->width_x, data->width_y,
 		data->x_res, data->y_res);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/mouse/synaptics_i2c.c linux-libre-4.10-rc8-gnu/drivers/input/mouse/synaptics_i2c.c
--- linux-libre-4.9-gnu/drivers/input/mouse/synaptics_i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/mouse/synaptics_i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
  * after soft reset, we should wait for 1 ms
  * before the device becomes operational
  */
-#define SOFT_RESET_DELAY_MS	3
+#define SOFT_RESET_DELAY_US	3000
 /* and after hard reset, we should wait for max 500ms */
 #define HARD_RESET_DELAY_MS	500
 
@@ -311,7 +311,7 @@ static int synaptics_i2c_reset_config(st
 	if (ret) {
 		dev_err(&client->dev, "Unable to reset device\n");
 	} else {
-		msleep(SOFT_RESET_DELAY_MS);
+		usleep_range(SOFT_RESET_DELAY_US, SOFT_RESET_DELAY_US + 100);
 		ret = synaptics_i2c_config(client);
 		if (ret)
 			dev_err(&client->dev, "Unable to config device\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/mouse/trackpoint.c linux-libre-4.10-rc8-gnu/drivers/input/mouse/trackpoint.c
--- linux-libre-4.9-gnu/drivers/input/mouse/trackpoint.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/mouse/trackpoint.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/input.h>
 #include <linux/libps2.h>
 #include <linux/proc_fs.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "psmouse.h"
 #include "trackpoint.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/Kconfig linux-libre-4.10-rc8-gnu/drivers/input/rmi4/Kconfig
--- linux-libre-4.9-gnu/drivers/input/rmi4/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,34 @@ config RMI4_SPI
 
 	  If unsure, say N.
 
+config RMI4_SMB
+	tristate "RMI4 SMB Support"
+	depends on RMI4_CORE && I2C
+	help
+	  Say Y here if you want to support RMI4 devices connected to an SMB
+	  bus.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called rmi_smbus.
+
+config RMI4_F03
+        bool "RMI4 Function 03 (PS2 Guest)"
+	depends on RMI4_CORE
+        help
+          Say Y here if you want to add support for RMI4 function 03.
+
+          Function 03 provides PS2 guest support for RMI4 devices. This
+          includes support for TrackPoints on TouchPads.
+
+config RMI4_F03_SERIO
+	tristate
+	depends on RMI4_CORE
+	depends on RMI4_F03
+	default RMI4_CORE
+	select SERIO
+
 config RMI4_2D_SENSOR
 	bool
 	depends on RMI4_CORE
@@ -62,13 +90,34 @@ config RMI4_F30
 	  Function 30 provides GPIO and LED support for RMI4 devices. This
 	  includes support for buttons on TouchPads and ClickPads.
 
+config RMI4_F34
+	bool "RMI4 Function 34 (Device reflash)"
+	depends on RMI4_CORE
+	select FW_LOADER
+	help
+	  Say Y here if you want to add support for RMI4 function 34.
+
+	  Function 34 provides support for upgrading the firmware on the RMI4
+	  device via the firmware loader interface. This is triggered using a
+	  sysfs attribute.
+
 config RMI4_F54
 	bool "RMI4 Function 54 (Analog diagnostics)"
 	depends on RMI4_CORE
 	depends on VIDEO_V4L2=y || (RMI4_CORE=m && VIDEO_V4L2=m)
 	select VIDEOBUF2_VMALLOC
+	select RMI4_F55
 	help
 	  Say Y here if you want to add support for RMI4 function 54
 
 	  Function 54 provides access to various diagnostic features in certain
 	  RMI4 touch sensors.
+
+config RMI4_F55
+	bool "RMI4 Function 55 (Sensor tuning)"
+	depends on RMI4_CORE
+	help
+	  Say Y here if you want to add support for RMI4 function 55
+
+	  Function 55 provides access to the RMI4 touch sensor tuning
+	  mechanism.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/Makefile linux-libre-4.10-rc8-gnu/drivers/input/rmi4/Makefile
--- linux-libre-4.9-gnu/drivers/input/rmi4/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -4,11 +4,15 @@ rmi_core-y := rmi_bus.o rmi_driver.o rmi
 rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o
 
 # Function drivers
+rmi_core-$(CONFIG_RMI4_F03) += rmi_f03.o
 rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o
 rmi_core-$(CONFIG_RMI4_F12) += rmi_f12.o
 rmi_core-$(CONFIG_RMI4_F30) += rmi_f30.o
+rmi_core-$(CONFIG_RMI4_F34) += rmi_f34.o rmi_f34v7.o
 rmi_core-$(CONFIG_RMI4_F54) += rmi_f54.o
+rmi_core-$(CONFIG_RMI4_F55) += rmi_f55.o
 
 # Transports
 obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o
 obj-$(CONFIG_RMI4_SPI) += rmi_spi.o
+obj-$(CONFIG_RMI4_SMB) += rmi_smbus.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_2d_sensor.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_2d_sensor.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_2d_sensor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_2d_sensor.c	2017-02-12 16:03:20.000000000 -0500
@@ -177,10 +177,12 @@ static void rmi_2d_sensor_set_input_para
 				sensor->dmax = DMAX * res_x;
 		}
 
-		input_set_abs_params(input, ABS_MT_PRESSURE, 0,	0xff, 0, 0);
-		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,	0, 0x0f, 0, 0);
-		input_set_abs_params(input, ABS_MT_TOUCH_MINOR,	0, 0x0f, 0, 0);
-		input_set_abs_params(input, ABS_MT_ORIENTATION,	0, 1, 0, 0);
+		input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0);
+		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
+		input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
+		input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+		input_set_abs_params(input, ABS_MT_TOOL_TYPE,
+				     0, MT_TOOL_MAX, 0, 0);
 
 		if (sensor->sensor_type == rmi_sensor_touchpad)
 			input_flags = INPUT_MT_POINTER;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_2d_sensor.h linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_2d_sensor.h
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_2d_sensor.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_2d_sensor.h	2017-02-12 16:03:20.000000000 -0500
@@ -67,6 +67,8 @@ struct rmi_2d_sensor {
 	u8 report_rel;
 	u8 x_mm;
 	u8 y_mm;
+	enum rmi_reg_state dribble;
+	enum rmi_reg_state palm_detect;
 };
 
 int rmi_2d_sensor_of_probe(struct device *dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_bus.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_bus.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -230,6 +230,9 @@ err_put_device:
 
 void rmi_unregister_function(struct rmi_function *fn)
 {
+	rmi_dbg(RMI_DEBUG_CORE, &fn->dev, "Unregistering F%02X.\n",
+			fn->fd.function_number);
+
 	device_del(&fn->dev);
 	of_node_put(fn->dev.of_node);
 	put_device(&fn->dev);
@@ -302,6 +305,9 @@ struct bus_type rmi_bus_type = {
 
 static struct rmi_function_handler *fn_handlers[] = {
 	&rmi_f01_handler,
+#ifdef CONFIG_RMI4_F03
+	&rmi_f03_handler,
+#endif
 #ifdef CONFIG_RMI4_F11
 	&rmi_f11_handler,
 #endif
@@ -311,9 +317,15 @@ static struct rmi_function_handler *fn_h
 #ifdef CONFIG_RMI4_F30
 	&rmi_f30_handler,
 #endif
+#ifdef CONFIG_RMI4_F34
+	&rmi_f34_handler,
+#endif
 #ifdef CONFIG_RMI4_F54
 	&rmi_f54_handler,
 #endif
+#ifdef CONFIG_RMI4_F55
+	&rmi_f55_handler,
+#endif
 };
 
 static void __rmi_unregister_function_handlers(int start_idx)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_bus.h linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_bus.h
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_bus.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_bus.h	2017-02-12 16:03:20.000000000 -0500
@@ -105,6 +105,18 @@ rmi_get_platform_data(struct rmi_device
 bool rmi_is_physical_device(struct device *dev);
 
 /**
+ * rmi_reset - reset a RMI4 device
+ * @d: Pointer to an RMI device
+ *
+ * Calls for a reset of each function implemented by a specific device.
+ * Returns 0 on success or a negative error code.
+ */
+static inline int rmi_reset(struct rmi_device *d)
+{
+	return d->driver->reset_handler(d);
+}
+
+/**
  * rmi_read - read a single byte
  * @d: Pointer to an RMI device
  * @addr: The address to read from
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_driver.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_driver.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/bitmap.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
+#include <linux/irq.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -33,12 +34,22 @@
 #define RMI_DEVICE_RESET_CMD	0x01
 #define DEFAULT_RESET_DELAY_MS	100
 
-static void rmi_free_function_list(struct rmi_device *rmi_dev)
+void rmi_free_function_list(struct rmi_device *rmi_dev)
 {
 	struct rmi_function *fn, *tmp;
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 
+	rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Freeing function list\n");
+
+	devm_kfree(&rmi_dev->dev, data->irq_memory);
+	data->irq_memory = NULL;
+	data->irq_status = NULL;
+	data->fn_irq_bits = NULL;
+	data->current_irq_mask = NULL;
+	data->new_irq_mask = NULL;
+
 	data->f01_container = NULL;
+	data->f34_container = NULL;
 
 	/* Doing it in the reverse order so F01 will be removed last */
 	list_for_each_entry_safe_reverse(fn, tmp,
@@ -133,7 +144,7 @@ static void process_one_interrupt(struct
 	}
 }
 
-int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
+static int rmi_process_interrupt_requests(struct rmi_device *rmi_dev)
 {
 	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 	struct device *dev = &rmi_dev->dev;
@@ -143,7 +154,7 @@ int rmi_process_interrupt_requests(struc
 	if (!data)
 		return 0;
 
-	if (!rmi_dev->xport->attn_data) {
+	if (!data->attn_data.data) {
 		error = rmi_read_block(rmi_dev,
 				data->f01_container->fd.data_base_addr + 1,
 				data->irq_status, data->num_of_irq_regs);
@@ -178,7 +189,81 @@ int rmi_process_interrupt_requests(struc
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rmi_process_interrupt_requests);
+
+void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status,
+		       void *data, size_t size)
+{
+	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
+	struct rmi4_attn_data attn_data;
+	void *fifo_data;
+
+	if (!drvdata->enabled)
+		return;
+
+	fifo_data = kmemdup(data, size, GFP_ATOMIC);
+	if (!fifo_data)
+		return;
+
+	attn_data.irq_status = irq_status;
+	attn_data.size = size;
+	attn_data.data = fifo_data;
+
+	kfifo_put(&drvdata->attn_fifo, attn_data);
+}
+EXPORT_SYMBOL_GPL(rmi_set_attn_data);
+
+static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
+{
+	struct rmi_device *rmi_dev = dev_id;
+	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
+	struct rmi4_attn_data attn_data = {0};
+	int ret, count;
+
+	count = kfifo_get(&drvdata->attn_fifo, &attn_data);
+	if (count) {
+		*(drvdata->irq_status) = attn_data.irq_status;
+		drvdata->attn_data = attn_data;
+	}
+
+	ret = rmi_process_interrupt_requests(rmi_dev);
+	if (ret)
+		rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+			"Failed to process interrupt request: %d\n", ret);
+
+	if (count)
+		kfree(attn_data.data);
+
+	if (!kfifo_is_empty(&drvdata->attn_fifo))
+		return rmi_irq_fn(irq, dev_id);
+
+	return IRQ_HANDLED;
+}
+
+static int rmi_irq_init(struct rmi_device *rmi_dev)
+{
+	struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+	int irq_flags = irq_get_trigger_type(pdata->irq);
+	int ret;
+
+	if (!irq_flags)
+		irq_flags = IRQF_TRIGGER_LOW;
+
+	ret = devm_request_threaded_irq(&rmi_dev->dev, pdata->irq, NULL,
+					rmi_irq_fn, irq_flags | IRQF_ONESHOT,
+					dev_name(rmi_dev->xport->dev),
+					rmi_dev);
+	if (ret < 0) {
+		dev_err(&rmi_dev->dev, "Failed to register interrupt %d\n",
+			pdata->irq);
+
+		return ret;
+	}
+
+	data->enabled = true;
+
+	return 0;
+}
 
 static int suspend_one_function(struct rmi_function *fn)
 {
@@ -248,7 +333,7 @@ static int rmi_resume_functions(struct r
 	return 0;
 }
 
-static int enable_sensor(struct rmi_device *rmi_dev)
+int rmi_enable_sensor(struct rmi_device *rmi_dev)
 {
 	int retval = 0;
 
@@ -379,8 +464,8 @@ static int rmi_driver_reset_handler(stru
 	return 0;
 }
 
-int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
-			u16 pdt_address)
+static int rmi_read_pdt_entry(struct rmi_device *rmi_dev,
+			      struct pdt_entry *entry, u16 pdt_address)
 {
 	u8 buf[RMI_PDT_ENTRY_SIZE];
 	int error;
@@ -403,7 +488,6 @@ int rmi_read_pdt_entry(struct rmi_device
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rmi_read_pdt_entry);
 
 static void rmi_driver_copy_pdt_to_fd(const struct pdt_entry *pdt,
 				      struct rmi_function_descriptor *fd)
@@ -422,6 +506,7 @@ static void rmi_driver_copy_pdt_to_fd(co
 
 static int rmi_scan_pdt_page(struct rmi_device *rmi_dev,
 			     int page,
+			     int *empty_pages,
 			     void *ctx,
 			     int (*callback)(struct rmi_device *rmi_dev,
 					     void *ctx,
@@ -449,20 +534,30 @@ static int rmi_scan_pdt_page(struct rmi_
 			return retval;
 	}
 
-	return (data->f01_bootloader_mode || addr == pdt_start) ?
+	/*
+	 * Count number of empty PDT pages. If a gap of two pages
+	 * or more is found, stop scanning.
+	 */
+	if (addr == pdt_start)
+		++*empty_pages;
+	else
+		*empty_pages = 0;
+
+	return (data->bootloader_mode || *empty_pages >= 2) ?
 					RMI_SCAN_DONE : RMI_SCAN_CONTINUE;
 }
 
-static int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
-			int (*callback)(struct rmi_device *rmi_dev,
-					void *ctx,
-					const struct pdt_entry *entry))
+int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
+		 int (*callback)(struct rmi_device *rmi_dev,
+		 void *ctx, const struct pdt_entry *entry))
 {
 	int page;
+	int empty_pages = 0;
 	int retval = RMI_SCAN_DONE;
 
 	for (page = 0; page <= RMI4_MAX_PAGE; page++) {
-		retval = rmi_scan_pdt_page(rmi_dev, page, ctx, callback);
+		retval = rmi_scan_pdt_page(rmi_dev, page, &empty_pages,
+					   ctx, callback);
 		if (retval != RMI_SCAN_CONTINUE)
 			break;
 	}
@@ -600,7 +695,6 @@ free_struct_buff:
 	kfree(struct_buf);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(rmi_read_register_desc);
 
 const struct rmi_register_desc_item *rmi_get_register_desc_item(
 				struct rmi_register_descriptor *rdesc, u16 reg)
@@ -616,7 +710,6 @@ const struct rmi_register_desc_item *rmi
 
 	return NULL;
 }
-EXPORT_SYMBOL_GPL(rmi_get_register_desc_item);
 
 size_t rmi_register_desc_calc_size(struct rmi_register_descriptor *rdesc)
 {
@@ -630,7 +723,6 @@ size_t rmi_register_desc_calc_size(struc
 	}
 	return size;
 }
-EXPORT_SYMBOL_GPL(rmi_register_desc_calc_size);
 
 /* Compute the register offset relative to the base address */
 int rmi_register_desc_calc_reg_offset(
@@ -648,7 +740,6 @@ int rmi_register_desc_calc_reg_offset(
 	}
 	return -1;
 }
-EXPORT_SYMBOL_GPL(rmi_register_desc_calc_reg_offset);
 
 bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
 	u8 subpacket)
@@ -657,51 +748,55 @@ bool rmi_register_desc_has_subpacket(con
 				subpacket) == subpacket;
 }
 
-/* Indicates that flash programming is enabled (bootloader mode). */
-#define RMI_F01_STATUS_BOOTLOADER(status)	(!!((status) & 0x40))
-
-/*
- * Given the PDT entry for F01, read the device status register to determine
- * if we're stuck in bootloader mode or not.
- *
- */
 static int rmi_check_bootloader_mode(struct rmi_device *rmi_dev,
 				     const struct pdt_entry *pdt)
 {
-	int error;
-	u8 device_status;
+	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+	int ret;
+	u8 status;
 
-	error = rmi_read(rmi_dev, pdt->data_base_addr + pdt->page_start,
-			 &device_status);
-	if (error) {
-		dev_err(&rmi_dev->dev,
-			"Failed to read device status: %d.\n", error);
-		return error;
+	if (pdt->function_number == 0x34 && pdt->function_version > 1) {
+		ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
+		if (ret) {
+			dev_err(&rmi_dev->dev,
+				"Failed to read F34 status: %d.\n", ret);
+			return ret;
+		}
+
+		if (status & BIT(7))
+			data->bootloader_mode = true;
+	} else if (pdt->function_number == 0x01) {
+		ret = rmi_read(rmi_dev, pdt->data_base_addr, &status);
+		if (ret) {
+			dev_err(&rmi_dev->dev,
+				"Failed to read F01 status: %d.\n", ret);
+			return ret;
+		}
+
+		if (status & BIT(6))
+			data->bootloader_mode = true;
 	}
 
-	return RMI_F01_STATUS_BOOTLOADER(device_status);
+	return 0;
 }
 
 static int rmi_count_irqs(struct rmi_device *rmi_dev,
 			 void *ctx, const struct pdt_entry *pdt)
 {
-	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
 	int *irq_count = ctx;
+	int ret;
 
 	*irq_count += pdt->interrupt_source_count;
-	if (pdt->function_number == 0x01) {
-		data->f01_bootloader_mode =
-			rmi_check_bootloader_mode(rmi_dev, pdt);
-		if (data->f01_bootloader_mode)
-			dev_warn(&rmi_dev->dev,
-				"WARNING: RMI4 device is in bootloader mode!\n");
-	}
+
+	ret = rmi_check_bootloader_mode(rmi_dev, pdt);
+	if (ret < 0)
+		return ret;
 
 	return RMI_SCAN_CONTINUE;
 }
 
-static int rmi_initial_reset(struct rmi_device *rmi_dev,
-			     void *ctx, const struct pdt_entry *pdt)
+int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
+		      const struct pdt_entry *pdt)
 {
 	int error;
 
@@ -720,6 +815,7 @@ static int rmi_initial_reset(struct rmi_
 			return RMI_SCAN_DONE;
 		}
 
+		rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Sending reset\n");
 		error = rmi_write_block(rmi_dev, cmd_addr, &cmd_buf, 1);
 		if (error) {
 			dev_err(&rmi_dev->dev,
@@ -776,6 +872,8 @@ static int rmi_create_function(struct rm
 
 	if (pdt->function_number == 0x01)
 		data->f01_container = fn;
+	else if (pdt->function_number == 0x34)
+		data->f34_container = fn;
 
 	list_add_tail(&fn->node, &data->function_list);
 
@@ -786,23 +884,95 @@ err_put_fn:
 	return error;
 }
 
-int rmi_driver_suspend(struct rmi_device *rmi_dev)
+void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake)
 {
-	int retval = 0;
+	struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+	int irq = pdata->irq;
+	int irq_flags;
+	int retval;
+
+	mutex_lock(&data->enabled_mutex);
+
+	if (data->enabled)
+		goto out;
+
+	enable_irq(irq);
+	data->enabled = true;
+	if (clear_wake && device_may_wakeup(rmi_dev->xport->dev)) {
+		retval = disable_irq_wake(irq);
+		if (retval)
+			dev_warn(&rmi_dev->dev,
+				 "Failed to disable irq for wake: %d\n",
+				 retval);
+	}
+
+	/*
+	 * Call rmi_process_interrupt_requests() after enabling irq,
+	 * otherwise we may lose interrupt on edge-triggered systems.
+	 */
+	irq_flags = irq_get_trigger_type(pdata->irq);
+	if (irq_flags & IRQ_TYPE_EDGE_BOTH)
+		rmi_process_interrupt_requests(rmi_dev);
+
+out:
+	mutex_unlock(&data->enabled_mutex);
+}
+
+void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake)
+{
+	struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
+	struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+	struct rmi4_attn_data attn_data = {0};
+	int irq = pdata->irq;
+	int retval, count;
+
+	mutex_lock(&data->enabled_mutex);
+
+	if (!data->enabled)
+		goto out;
+
+	data->enabled = false;
+	disable_irq(irq);
+	if (enable_wake && device_may_wakeup(rmi_dev->xport->dev)) {
+		retval = enable_irq_wake(irq);
+		if (retval)
+			dev_warn(&rmi_dev->dev,
+				 "Failed to enable irq for wake: %d\n",
+				 retval);
+	}
+
+	/* make sure the fifo is clean */
+	while (!kfifo_is_empty(&data->attn_fifo)) {
+		count = kfifo_get(&data->attn_fifo, &attn_data);
+		if (count)
+			kfree(attn_data.data);
+	}
+
+out:
+	mutex_unlock(&data->enabled_mutex);
+}
+
+int rmi_driver_suspend(struct rmi_device *rmi_dev, bool enable_wake)
+{
+	int retval;
 
 	retval = rmi_suspend_functions(rmi_dev);
 	if (retval)
 		dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
 			retval);
 
+	rmi_disable_irq(rmi_dev, enable_wake);
 	return retval;
 }
 EXPORT_SYMBOL_GPL(rmi_driver_suspend);
 
-int rmi_driver_resume(struct rmi_device *rmi_dev)
+int rmi_driver_resume(struct rmi_device *rmi_dev, bool clear_wake)
 {
 	int retval;
 
+	rmi_enable_irq(rmi_dev, clear_wake);
+
 	retval = rmi_resume_functions(rmi_dev);
 	if (retval)
 		dev_warn(&rmi_dev->dev, "Failed to suspend functions: %d\n",
@@ -816,6 +986,9 @@ static int rmi_driver_remove(struct devi
 {
 	struct rmi_device *rmi_dev = to_rmi_device(dev);
 
+	rmi_disable_irq(rmi_dev, false);
+
+	rmi_f34_remove_sysfs(rmi_dev);
 	rmi_free_function_list(rmi_dev);
 
 	return 0;
@@ -842,15 +1015,95 @@ static inline int rmi_driver_of_probe(st
 }
 #endif
 
+int rmi_probe_interrupts(struct rmi_driver_data *data)
+{
+	struct rmi_device *rmi_dev = data->rmi_dev;
+	struct device *dev = &rmi_dev->dev;
+	int irq_count;
+	size_t size;
+	int retval;
+
+	/*
+	 * We need to count the IRQs and allocate their storage before scanning
+	 * the PDT and creating the function entries, because adding a new
+	 * function can trigger events that result in the IRQ related storage
+	 * being accessed.
+	 */
+	rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Counting IRQs.\n", __func__);
+	irq_count = 0;
+	data->bootloader_mode = false;
+
+	retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
+	if (retval < 0) {
+		dev_err(dev, "IRQ counting failed with code %d.\n", retval);
+		return retval;
+	}
+
+	if (data->bootloader_mode)
+		dev_warn(&rmi_dev->dev, "Device in bootloader mode.\n");
+
+	data->irq_count = irq_count;
+	data->num_of_irq_regs = (data->irq_count + 7) / 8;
+
+	size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
+	data->irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
+	if (!data->irq_memory) {
+		dev_err(dev, "Failed to allocate memory for irq masks.\n");
+		return retval;
+	}
+
+	data->irq_status	= data->irq_memory + size * 0;
+	data->fn_irq_bits	= data->irq_memory + size * 1;
+	data->current_irq_mask	= data->irq_memory + size * 2;
+	data->new_irq_mask	= data->irq_memory + size * 3;
+
+	return retval;
+}
+
+int rmi_init_functions(struct rmi_driver_data *data)
+{
+	struct rmi_device *rmi_dev = data->rmi_dev;
+	struct device *dev = &rmi_dev->dev;
+	int irq_count;
+	int retval;
+
+	irq_count = 0;
+	rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Creating functions.\n", __func__);
+	retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
+	if (retval < 0) {
+		dev_err(dev, "Function creation failed with code %d.\n",
+			retval);
+		goto err_destroy_functions;
+	}
+
+	if (!data->f01_container) {
+		dev_err(dev, "Missing F01 container!\n");
+		retval = -EINVAL;
+		goto err_destroy_functions;
+	}
+
+	retval = rmi_read_block(rmi_dev,
+				data->f01_container->fd.control_base_addr + 1,
+				data->current_irq_mask, data->num_of_irq_regs);
+	if (retval < 0) {
+		dev_err(dev, "%s: Failed to read current IRQ mask.\n",
+			__func__);
+		goto err_destroy_functions;
+	}
+
+	return 0;
+
+err_destroy_functions:
+	rmi_free_function_list(rmi_dev);
+	return retval;
+}
+
 static int rmi_driver_probe(struct device *dev)
 {
 	struct rmi_driver *rmi_driver;
 	struct rmi_driver_data *data;
 	struct rmi_device_platform_data *pdata;
 	struct rmi_device *rmi_dev;
-	size_t size;
-	void *irq_memory;
-	int irq_count;
 	int retval;
 
 	rmi_dbg(RMI_DEBUG_CORE, dev, "%s: Starting probe.\n",
@@ -916,35 +1169,12 @@ static int rmi_driver_probe(struct devic
 			 PDT_PROPERTIES_LOCATION, retval);
 	}
 
-	/*
-	 * We need to count the IRQs and allocate their storage before scanning
-	 * the PDT and creating the function entries, because adding a new
-	 * function can trigger events that result in the IRQ related storage
-	 * being accessed.
-	 */
-	rmi_dbg(RMI_DEBUG_CORE, dev, "Counting IRQs.\n");
-	irq_count = 0;
-	retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_count_irqs);
-	if (retval < 0) {
-		dev_err(dev, "IRQ counting failed with code %d.\n", retval);
-		goto err;
-	}
-	data->irq_count = irq_count;
-	data->num_of_irq_regs = (data->irq_count + 7) / 8;
-
 	mutex_init(&data->irq_mutex);
+	mutex_init(&data->enabled_mutex);
 
-	size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
-	irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
-	if (!irq_memory) {
-		dev_err(dev, "Failed to allocate memory for irq masks.\n");
+	retval = rmi_probe_interrupts(data);
+	if (retval)
 		goto err;
-	}
-
-	data->irq_status	= irq_memory + size * 0;
-	data->fn_irq_bits	= irq_memory + size * 1;
-	data->current_irq_mask	= irq_memory + size * 2;
-	data->new_irq_mask	= irq_memory + size * 3;
 
 	if (rmi_dev->xport->input) {
 		/*
@@ -961,36 +1191,20 @@ static int rmi_driver_probe(struct devic
 			dev_err(dev, "%s: Failed to allocate input device.\n",
 				__func__);
 			retval = -ENOMEM;
-			goto err_destroy_functions;
+			goto err;
 		}
 		rmi_driver_set_input_params(rmi_dev, data->input);
 		data->input->phys = devm_kasprintf(dev, GFP_KERNEL,
 						"%s/input0", dev_name(dev));
 	}
 
-	irq_count = 0;
-	rmi_dbg(RMI_DEBUG_CORE, dev, "Creating functions.");
-	retval = rmi_scan_pdt(rmi_dev, &irq_count, rmi_create_function);
-	if (retval < 0) {
-		dev_err(dev, "Function creation failed with code %d.\n",
-			retval);
-		goto err_destroy_functions;
-	}
-
-	if (!data->f01_container) {
-		dev_err(dev, "Missing F01 container!\n");
-		retval = -EINVAL;
-		goto err_destroy_functions;
-	}
+	retval = rmi_init_functions(data);
+	if (retval)
+		goto err;
 
-	retval = rmi_read_block(rmi_dev,
-				data->f01_container->fd.control_base_addr + 1,
-				data->current_irq_mask, data->num_of_irq_regs);
-	if (retval < 0) {
-		dev_err(dev, "%s: Failed to read current IRQ mask.\n",
-			__func__);
-		goto err_destroy_functions;
-	}
+	retval = rmi_f34_create_sysfs(rmi_dev);
+	if (retval)
+		goto err;
 
 	if (data->input) {
 		rmi_driver_set_input_name(rmi_dev, data->input);
@@ -1003,9 +1217,13 @@ static int rmi_driver_probe(struct devic
 		}
 	}
 
+	retval = rmi_irq_init(rmi_dev);
+	if (retval < 0)
+		goto err_destroy_functions;
+
 	if (data->f01_container->dev.driver)
 		/* Driver already bound, so enable ATTN now. */
-		return enable_sensor(rmi_dev);
+		return rmi_enable_sensor(rmi_dev);
 
 	return 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_driver.h linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_driver.h
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_driver.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_driver.h	2017-02-12 16:03:20.000000000 -0500
@@ -51,9 +51,6 @@ struct pdt_entry {
 	u8 function_number;
 };
 
-int rmi_read_pdt_entry(struct rmi_device *rmi_dev, struct pdt_entry *entry,
-			u16 pdt_address);
-
 #define RMI_REG_DESC_PRESENSE_BITS	(32 * BITS_PER_BYTE)
 #define RMI_REG_DESC_SUBPACKET_BITS	(37 * BITS_PER_BYTE)
 
@@ -95,12 +92,40 @@ bool rmi_register_desc_has_subpacket(con
 bool rmi_is_physical_driver(struct device_driver *);
 int rmi_register_physical_driver(void);
 void rmi_unregister_physical_driver(void);
+void rmi_free_function_list(struct rmi_device *rmi_dev);
+int rmi_enable_sensor(struct rmi_device *rmi_dev);
+int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
+		 int (*callback)(struct rmi_device *rmi_dev, void *ctx,
+		 const struct pdt_entry *entry));
+int rmi_probe_interrupts(struct rmi_driver_data *data);
+void rmi_enable_irq(struct rmi_device *rmi_dev, bool clear_wake);
+void rmi_disable_irq(struct rmi_device *rmi_dev, bool enable_wake);
+int rmi_init_functions(struct rmi_driver_data *data);
+int rmi_initial_reset(struct rmi_device *rmi_dev, void *ctx,
+		      const struct pdt_entry *pdt);
 
 char *rmi_f01_get_product_ID(struct rmi_function *fn);
 
+#ifdef CONFIG_RMI4_F34
+int rmi_f34_create_sysfs(struct rmi_device *rmi_dev);
+void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev);
+#else
+static inline int rmi_f34_create_sysfs(struct rmi_device *rmi_dev)
+{
+	return 0;
+}
+
+static inline void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev)
+{
+}
+#endif /* CONFIG_RMI_F34 */
+
 extern struct rmi_function_handler rmi_f01_handler;
+extern struct rmi_function_handler rmi_f03_handler;
 extern struct rmi_function_handler rmi_f11_handler;
 extern struct rmi_function_handler rmi_f12_handler;
 extern struct rmi_function_handler rmi_f30_handler;
+extern struct rmi_function_handler rmi_f34_handler;
 extern struct rmi_function_handler rmi_f54_handler;
+extern struct rmi_function_handler rmi_f55_handler;
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f01.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f01.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f01.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f01.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,6 +62,8 @@ struct f01_basic_properties {
 #define RMI_F01_STATUS_CODE(status)		((status) & 0x0f)
 /* The device has lost its configuration for some reason. */
 #define RMI_F01_STATUS_UNCONFIGURED(status)	(!!((status) & 0x80))
+/* The device is in bootloader mode */
+#define RMI_F01_STATUS_BOOTLOADER(status)	((status) & 0x40)
 
 /* Control register bits */
 
@@ -326,12 +328,12 @@ static int rmi_f01_probe(struct rmi_func
 	}
 
 	switch (pdata->power_management.nosleep) {
-	case RMI_F01_NOSLEEP_DEFAULT:
+	case RMI_REG_STATE_DEFAULT:
 		break;
-	case RMI_F01_NOSLEEP_OFF:
+	case RMI_REG_STATE_OFF:
 		f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_NOSLEEP_BIT;
 		break;
-	case RMI_F01_NOSLEEP_ON:
+	case RMI_REG_STATE_ON:
 		f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT;
 		break;
 	}
@@ -593,6 +595,10 @@ static int rmi_f01_attention(struct rmi_
 		return error;
 	}
 
+	if (RMI_F01_STATUS_BOOTLOADER(device_status))
+		dev_warn(&fn->dev,
+			 "Device in bootloader mode, please update firmware\n");
+
 	if (RMI_F01_STATUS_UNCONFIGURED(device_status)) {
 		dev_warn(&fn->dev, "Device reset detected.\n");
 		error = rmi_dev->driver->reset_handler(rmi_dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f03.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f03.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f03.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f03.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2015-2016 Red Hat
+ * Copyright (C) 2015 Lyude Paul <thatslyude@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/slab.h>
+#include <linux/serio.h>
+#include <linux/notifier.h>
+#include "rmi_driver.h"
+
+#define RMI_F03_RX_DATA_OFB		0x01
+#define RMI_F03_OB_SIZE			2
+
+#define RMI_F03_OB_OFFSET		2
+#define RMI_F03_OB_DATA_OFFSET		1
+#define RMI_F03_OB_FLAG_TIMEOUT		BIT(6)
+#define RMI_F03_OB_FLAG_PARITY		BIT(7)
+
+#define RMI_F03_DEVICE_COUNT		0x07
+#define RMI_F03_BYTES_PER_DEVICE	0x07
+#define RMI_F03_BYTES_PER_DEVICE_SHIFT	4
+#define RMI_F03_QUEUE_LENGTH		0x0F
+
+struct f03_data {
+	struct rmi_function *fn;
+
+	struct serio *serio;
+
+	u8 device_count;
+	u8 rx_queue_length;
+};
+
+static int rmi_f03_pt_write(struct serio *id, unsigned char val)
+{
+	struct f03_data *f03 = id->port_data;
+	int error;
+
+	rmi_dbg(RMI_DEBUG_FN, &f03->fn->dev,
+		"%s: Wrote %.2hhx to PS/2 passthrough address",
+		__func__, val);
+
+	error = rmi_write(f03->fn->rmi_dev, f03->fn->fd.data_base_addr, val);
+	if (error) {
+		dev_err(&f03->fn->dev,
+			"%s: Failed to write to F03 TX register (%d).\n",
+			__func__, error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int rmi_f03_initialize(struct f03_data *f03)
+{
+	struct rmi_function *fn = f03->fn;
+	struct device *dev = &fn->dev;
+	int error;
+	u8 bytes_per_device;
+	u8 query1;
+	u8 query2[RMI_F03_DEVICE_COUNT * RMI_F03_BYTES_PER_DEVICE];
+	size_t query2_len;
+
+	error = rmi_read(fn->rmi_dev, fn->fd.query_base_addr, &query1);
+	if (error) {
+		dev_err(dev, "Failed to read query register (%d).\n", error);
+		return error;
+	}
+
+	f03->device_count = query1 & RMI_F03_DEVICE_COUNT;
+	bytes_per_device = (query1 >> RMI_F03_BYTES_PER_DEVICE_SHIFT) &
+				RMI_F03_BYTES_PER_DEVICE;
+
+	query2_len = f03->device_count * bytes_per_device;
+
+	/*
+	 * The first generation of image sensors don't have a second part to
+	 * their f03 query, as such we have to set some of these values manually
+	 */
+	if (query2_len < 1) {
+		f03->device_count = 1;
+		f03->rx_queue_length = 7;
+	} else {
+		error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + 1,
+				       query2, query2_len);
+		if (error) {
+			dev_err(dev,
+				"Failed to read second set of query registers (%d).\n",
+				error);
+			return error;
+		}
+
+		f03->rx_queue_length = query2[0] & RMI_F03_QUEUE_LENGTH;
+	}
+
+	return 0;
+}
+
+static int rmi_f03_register_pt(struct f03_data *f03)
+{
+	struct serio *serio;
+
+	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+	if (!serio)
+		return -ENOMEM;
+
+	serio->id.type = SERIO_8042;
+	serio->write = rmi_f03_pt_write;
+	serio->port_data = f03;
+
+	strlcpy(serio->name, "Synaptics RMI4 PS/2 pass-through",
+		sizeof(serio->name));
+	strlcpy(serio->phys, "synaptics-rmi4-pt/serio1",
+		sizeof(serio->phys));
+	serio->dev.parent = &f03->fn->dev;
+
+	f03->serio = serio;
+
+	serio_register_port(serio);
+
+	return 0;
+}
+
+static int rmi_f03_probe(struct rmi_function *fn)
+{
+	struct device *dev = &fn->dev;
+	struct f03_data *f03;
+	int error;
+
+	f03 = devm_kzalloc(dev, sizeof(struct f03_data), GFP_KERNEL);
+	if (!f03)
+		return -ENOMEM;
+
+	f03->fn = fn;
+
+	error = rmi_f03_initialize(f03);
+	if (error < 0)
+		return error;
+
+	if (f03->device_count != 1)
+		dev_warn(dev, "found %d devices on PS/2 passthrough",
+			 f03->device_count);
+
+	dev_set_drvdata(dev, f03);
+
+	error = rmi_f03_register_pt(f03);
+	if (error)
+		return error;
+
+	return 0;
+}
+
+static int rmi_f03_config(struct rmi_function *fn)
+{
+	fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
+
+	return 0;
+}
+
+static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
+{
+	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
+	struct f03_data *f03 = dev_get_drvdata(&fn->dev);
+	u16 data_addr = fn->fd.data_base_addr;
+	const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
+	u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
+	u8 ob_status;
+	u8 ob_data;
+	unsigned int serio_flags;
+	int i;
+	int error;
+
+	if (!rmi_dev)
+		return -ENODEV;
+
+	if (drvdata->attn_data.data) {
+		/* First grab the data passed by the transport device */
+		if (drvdata->attn_data.size < ob_len) {
+			dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
+			return 0;
+		}
+
+		memcpy(obs, drvdata->attn_data.data, ob_len);
+
+		drvdata->attn_data.data += ob_len;
+		drvdata->attn_data.size -= ob_len;
+	} else {
+		/* Grab all of the data registers, and check them for data */
+		error = rmi_read_block(fn->rmi_dev, data_addr + RMI_F03_OB_OFFSET,
+				       &obs, ob_len);
+		if (error) {
+			dev_err(&fn->dev,
+				"%s: Failed to read F03 output buffers: %d\n",
+				__func__, error);
+			serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
+			return error;
+		}
+	}
+
+	for (i = 0; i < ob_len; i += RMI_F03_OB_SIZE) {
+		ob_status = obs[i];
+		ob_data = obs[i + RMI_F03_OB_DATA_OFFSET];
+		serio_flags = 0;
+
+		if (!(ob_status & RMI_F03_RX_DATA_OFB))
+			continue;
+
+		if (ob_status & RMI_F03_OB_FLAG_TIMEOUT)
+			serio_flags |= SERIO_TIMEOUT;
+		if (ob_status & RMI_F03_OB_FLAG_PARITY)
+			serio_flags |= SERIO_PARITY;
+
+		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
+			"%s: Received %.2hhx from PS2 guest T: %c P: %c\n",
+			__func__, ob_data,
+			serio_flags & SERIO_TIMEOUT ?  'Y' : 'N',
+			serio_flags & SERIO_PARITY ? 'Y' : 'N');
+
+		serio_interrupt(f03->serio, ob_data, serio_flags);
+	}
+
+	return 0;
+}
+
+static void rmi_f03_remove(struct rmi_function *fn)
+{
+	struct f03_data *f03 = dev_get_drvdata(&fn->dev);
+
+	serio_unregister_port(f03->serio);
+}
+
+struct rmi_function_handler rmi_f03_handler = {
+	.driver = {
+		.name = "rmi4_f03",
+	},
+	.func = 0x03,
+	.probe = rmi_f03_probe,
+	.config = rmi_f03_config,
+	.attention = rmi_f03_attention,
+	.remove = rmi_f03_remove,
+};
+
+MODULE_AUTHOR("Lyude Paul <thatslyude@gmail.com>");
+MODULE_DESCRIPTION("RMI F03 module");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f11.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f11.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f11.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f11.c	2017-02-12 16:03:20.000000000 -0500
@@ -571,31 +571,48 @@ static inline u8 rmi_f11_parse_finger_st
 
 static void rmi_f11_finger_handler(struct f11_data *f11,
 				   struct rmi_2d_sensor *sensor,
-				   unsigned long *irq_bits, int num_irq_regs)
+				   unsigned long *irq_bits, int num_irq_regs,
+				   int size)
 {
 	const u8 *f_state = f11->data.f_state;
 	u8 finger_state;
 	u8 i;
+	int abs_fingers;
+	int rel_fingers;
+	int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES;
 
 	int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask,
 				  num_irq_regs * 8);
 	int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask,
 				  num_irq_regs * 8);
 
-	for (i = 0; i < sensor->nbr_fingers; i++) {
-		/* Possible of having 4 fingers per f_statet register */
-		finger_state = rmi_f11_parse_finger_state(f_state, i);
-		if (finger_state == F11_RESERVED) {
-			pr_err("Invalid finger state[%d]: 0x%02x", i,
-				finger_state);
-			continue;
-		}
+	if (abs_bits) {
+		if (abs_size > size)
+			abs_fingers = size / RMI_F11_ABS_BYTES;
+		else
+			abs_fingers = sensor->nbr_fingers;
+
+		for (i = 0; i < abs_fingers; i++) {
+			/* Possible of having 4 fingers per f_state register */
+			finger_state = rmi_f11_parse_finger_state(f_state, i);
+			if (finger_state == F11_RESERVED) {
+				pr_err("Invalid finger state[%d]: 0x%02x", i,
+					finger_state);
+				continue;
+			}
 
-		if (abs_bits)
 			rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i],
 							finger_state, i);
+		}
+	}
 
-		if (rel_bits)
+	if (rel_bits) {
+		if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size)
+			rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES;
+		else
+			rel_fingers = sensor->nbr_fingers;
+
+		for (i = 0; i < rel_fingers; i++)
 			rmi_f11_rel_pos_report(f11, i);
 	}
 
@@ -611,7 +628,7 @@ static void rmi_f11_finger_handler(struc
 					      sensor->nbr_fingers,
 					      sensor->dmax);
 
-		for (i = 0; i < sensor->nbr_fingers; i++) {
+		for (i = 0; i < abs_fingers; i++) {
 			finger_state = rmi_f11_parse_finger_state(f_state, i);
 			if (finger_state == F11_RESERVED)
 				/* no need to send twice the error */
@@ -1062,8 +1079,8 @@ static int rmi_f11_initialize(struct rmi
 		rc = rmi_2d_sensor_of_probe(&fn->dev, &f11->sensor_pdata);
 		if (rc)
 			return rc;
-	} else if (pdata->sensor_pdata) {
-		f11->sensor_pdata = *pdata->sensor_pdata;
+	} else {
+		f11->sensor_pdata = pdata->sensor_pdata;
 	}
 
 	f11->rezero_wait_ms = f11->sensor_pdata.rezero_wait;
@@ -1124,6 +1141,8 @@ static int rmi_f11_initialize(struct rmi
 	sensor->topbuttonpad = f11->sensor_pdata.topbuttonpad;
 	sensor->kernel_tracking = f11->sensor_pdata.kernel_tracking;
 	sensor->dmax = f11->sensor_pdata.dmax;
+	sensor->dribble = f11->sensor_pdata.dribble;
+	sensor->palm_detect = f11->sensor_pdata.palm_detect;
 
 	if (f11->sens_query.has_physical_props) {
 		sensor->x_mm = f11->sens_query.x_sensor_size_mm;
@@ -1191,11 +1210,33 @@ static int rmi_f11_initialize(struct rmi
 		ctrl->ctrl0_11[RMI_F11_DELTA_Y_THRESHOLD] =
 			sensor->axis_align.delta_y_threshold;
 
-	if (f11->sens_query.has_dribble)
-		ctrl->ctrl0_11[0] = ctrl->ctrl0_11[0] & ~BIT(6);
+	if (f11->sens_query.has_dribble) {
+		switch (sensor->dribble) {
+		case RMI_REG_STATE_OFF:
+			ctrl->ctrl0_11[0] &= ~BIT(6);
+			break;
+		case RMI_REG_STATE_ON:
+			ctrl->ctrl0_11[0] |= BIT(6);
+			break;
+		case RMI_REG_STATE_DEFAULT:
+		default:
+			break;
+		}
+	}
 
-	if (f11->sens_query.has_palm_det)
-		ctrl->ctrl0_11[11] = ctrl->ctrl0_11[11] & ~BIT(0);
+	if (f11->sens_query.has_palm_det) {
+		switch (sensor->palm_detect) {
+		case RMI_REG_STATE_OFF:
+			ctrl->ctrl0_11[11] &= ~BIT(0);
+			break;
+		case RMI_REG_STATE_ON:
+			ctrl->ctrl0_11[11] |= BIT(0);
+			break;
+		case RMI_REG_STATE_DEFAULT:
+		default:
+			break;
+		}
+	}
 
 	rc = f11_write_control_regs(fn, &f11->sens_query,
 			   &f11->dev_controls, fn->fd.query_base_addr);
@@ -1241,12 +1282,21 @@ static int rmi_f11_attention(struct rmi_
 	struct f11_data *f11 = dev_get_drvdata(&fn->dev);
 	u16 data_base_addr = fn->fd.data_base_addr;
 	int error;
+	int valid_bytes = f11->sensor.pkt_size;
 
-	if (rmi_dev->xport->attn_data) {
-		memcpy(f11->sensor.data_pkt, rmi_dev->xport->attn_data,
-			f11->sensor.attn_size);
-		rmi_dev->xport->attn_data += f11->sensor.attn_size;
-		rmi_dev->xport->attn_size -= f11->sensor.attn_size;
+	if (drvdata->attn_data.data) {
+		/*
+		 * The valid data in the attention report is less then
+		 * expected. Only process the complete fingers.
+		 */
+		if (f11->sensor.attn_size > drvdata->attn_data.size)
+			valid_bytes = drvdata->attn_data.size;
+		else
+			valid_bytes = f11->sensor.attn_size;
+		memcpy(f11->sensor.data_pkt, drvdata->attn_data.data,
+			valid_bytes);
+		drvdata->attn_data.data += f11->sensor.attn_size;
+		drvdata->attn_data.size -= f11->sensor.attn_size;
 	} else {
 		error = rmi_read_block(rmi_dev,
 				data_base_addr, f11->sensor.data_pkt,
@@ -1256,7 +1306,7 @@ static int rmi_f11_attention(struct rmi_
 	}
 
 	rmi_f11_finger_handler(f11, &f11->sensor, irq_bits,
-				drvdata->num_of_irq_regs);
+				drvdata->num_of_irq_regs, valid_bytes);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f12.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f12.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f12.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f12.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,9 +26,12 @@ enum rmi_f12_object_type {
 	RMI_F12_OBJECT_SMALL_OBJECT		= 0x0D,
 };
 
+#define F12_DATA1_BYTES_PER_OBJ			8
+
 struct f12_data {
 	struct rmi_2d_sensor sensor;
 	struct rmi_2d_sensor_platform_data sensor_pdata;
+	bool has_dribble;
 
 	u16 data_addr;
 
@@ -68,10 +71,6 @@ static int rmi_f12_read_sensor_tuning(st
 	u8 buf[15];
 	int pitch_x = 0;
 	int pitch_y = 0;
-	int clip_x_low = 0;
-	int clip_x_high = 0;
-	int clip_y_low = 0;
-	int clip_y_high = 0;
 	int rx_receivers = 0;
 	int tx_receivers = 0;
 	int sensor_flags = 0;
@@ -124,7 +123,9 @@ static int rmi_f12_read_sensor_tuning(st
 	}
 
 	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x low: %d x high: %d y low: %d y high: %d\n",
-		__func__, clip_x_low, clip_x_high, clip_y_low, clip_y_high);
+		__func__,
+		sensor->axis_align.clip_x_low, sensor->axis_align.clip_x_high,
+		sensor->axis_align.clip_y_low, sensor->axis_align.clip_y_high);
 
 	if (rmi_register_desc_has_subpacket(item, 3)) {
 		rx_receivers = buf[offset];
@@ -146,12 +147,16 @@ static int rmi_f12_read_sensor_tuning(st
 	return 0;
 }
 
-static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1)
+static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
 {
 	int i;
 	struct rmi_2d_sensor *sensor = &f12->sensor;
+	int objects = f12->data1->num_subpackets;
 
-	for (i = 0; i < f12->data1->num_subpackets; i++) {
+	if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
+		objects = size / F12_DATA1_BYTES_PER_OBJ;
+
+	for (i = 0; i < objects; i++) {
 		struct rmi_2d_sensor_abs_object *obj = &sensor->objs[i];
 
 		obj->type = RMI_2D_OBJECT_NONE;
@@ -182,7 +187,7 @@ static void rmi_f12_process_objects(stru
 
 		rmi_2d_sensor_abs_process(sensor, obj, i);
 
-		data1 += 8;
+		data1 += F12_DATA1_BYTES_PER_OBJ;
 	}
 
 	if (sensor->kernel_tracking)
@@ -192,7 +197,7 @@ static void rmi_f12_process_objects(stru
 				      sensor->nbr_fingers,
 				      sensor->dmax);
 
-	for (i = 0; i < sensor->nbr_fingers; i++)
+	for (i = 0; i < objects; i++)
 		rmi_2d_sensor_abs_report(sensor, &sensor->objs[i], i);
 }
 
@@ -201,14 +206,20 @@ static int rmi_f12_attention(struct rmi_
 {
 	int retval;
 	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
 	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
 	struct rmi_2d_sensor *sensor = &f12->sensor;
+	int valid_bytes = sensor->pkt_size;
 
-	if (rmi_dev->xport->attn_data) {
-		memcpy(sensor->data_pkt, rmi_dev->xport->attn_data,
-			sensor->attn_size);
-		rmi_dev->xport->attn_data += sensor->attn_size;
-		rmi_dev->xport->attn_size -= sensor->attn_size;
+	if (drvdata->attn_data.data) {
+		if (sensor->attn_size > drvdata->attn_data.size)
+			valid_bytes = drvdata->attn_data.size;
+		else
+			valid_bytes = sensor->attn_size;
+		memcpy(sensor->data_pkt, drvdata->attn_data.data,
+			valid_bytes);
+		drvdata->attn_data.data += sensor->attn_size;
+		drvdata->attn_data.size -= sensor->attn_size;
 	} else {
 		retval = rmi_read_block(rmi_dev, f12->data_addr,
 					sensor->data_pkt, sensor->pkt_size);
@@ -221,19 +232,83 @@ static int rmi_f12_attention(struct rmi_
 
 	if (f12->data1)
 		rmi_f12_process_objects(f12,
-			&sensor->data_pkt[f12->data1_offset]);
+			&sensor->data_pkt[f12->data1_offset], valid_bytes);
 
 	input_mt_sync_frame(sensor->input);
 
 	return 0;
 }
 
+static int rmi_f12_write_control_regs(struct rmi_function *fn)
+{
+	int ret;
+	const struct rmi_register_desc_item *item;
+	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct f12_data *f12 = dev_get_drvdata(&fn->dev);
+	int control_size;
+	char buf[3];
+	u16 control_offset = 0;
+	u8 subpacket_offset = 0;
+
+	if (f12->has_dribble
+	    && (f12->sensor.dribble != RMI_REG_STATE_DEFAULT)) {
+		item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
+		if (item) {
+			control_offset = rmi_register_desc_calc_reg_offset(
+						&f12->control_reg_desc, 20);
+
+			/*
+			 * The byte containing the EnableDribble bit will be
+			 * in either byte 0 or byte 2 of control 20. Depending
+			 * on the existence of subpacket 0. If control 20 is
+			 * larger then 3 bytes, just read the first 3.
+			 */
+			control_size = min(item->reg_size, 3UL);
+
+			ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
+					+ control_offset, buf, control_size);
+			if (ret)
+				return ret;
+
+			if (rmi_register_desc_has_subpacket(item, 0))
+				subpacket_offset += 1;
+
+			switch (f12->sensor.dribble) {
+			case RMI_REG_STATE_OFF:
+				buf[subpacket_offset] &= ~BIT(2);
+				break;
+			case RMI_REG_STATE_ON:
+				buf[subpacket_offset] |= BIT(2);
+				break;
+			case RMI_REG_STATE_DEFAULT:
+			default:
+				break;
+			}
+
+			ret = rmi_write_block(rmi_dev,
+				fn->fd.control_base_addr + control_offset,
+				buf, control_size);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+
+}
+
 static int rmi_f12_config(struct rmi_function *fn)
 {
 	struct rmi_driver *drv = fn->rmi_dev->driver;
+	int ret;
 
 	drv->set_irq_bits(fn->rmi_dev, fn->irq_mask);
 
+	ret = rmi_f12_write_control_regs(fn);
+	if (ret)
+		dev_warn(&fn->dev,
+			"Failed to write F12 control registers: %d\n", ret);
+
 	return 0;
 }
 
@@ -247,7 +322,7 @@ static int rmi_f12_probe(struct rmi_func
 	const struct rmi_register_desc_item *item;
 	struct rmi_2d_sensor *sensor;
 	struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
-	struct rmi_transport_dev *xport = rmi_dev->xport;
+	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
 	u16 data_offset = 0;
 
 	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
@@ -260,7 +335,7 @@ static int rmi_f12_probe(struct rmi_func
 	}
 	++query_addr;
 
-	if (!(buf & 0x1)) {
+	if (!(buf & BIT(0))) {
 		dev_err(&fn->dev,
 			"Behavior of F12 without register descriptors is undefined.\n");
 		return -ENODEV;
@@ -270,12 +345,14 @@ static int rmi_f12_probe(struct rmi_func
 	if (!f12)
 		return -ENOMEM;
 
+	f12->has_dribble = !!(buf & BIT(3));
+
 	if (fn->dev.of_node) {
 		ret = rmi_2d_sensor_of_probe(&fn->dev, &f12->sensor_pdata);
 		if (ret)
 			return ret;
-	} else if (pdata->sensor_pdata) {
-		f12->sensor_pdata = *pdata->sensor_pdata;
+	} else {
+		f12->sensor_pdata = pdata->sensor_pdata;
 	}
 
 	ret = rmi_read_register_desc(rmi_dev, query_addr,
@@ -318,6 +395,7 @@ static int rmi_f12_probe(struct rmi_func
 
 	sensor->x_mm = f12->sensor_pdata.x_mm;
 	sensor->y_mm = f12->sensor_pdata.y_mm;
+	sensor->dribble = f12->sensor_pdata.dribble;
 
 	if (sensor->sensor_type == rmi_sensor_default)
 		sensor->sensor_type =
@@ -343,7 +421,7 @@ static int rmi_f12_probe(struct rmi_func
 	 * HID attention reports.
 	 */
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 0);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 1);
@@ -357,15 +435,15 @@ static int rmi_f12_probe(struct rmi_func
 	}
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 2);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 3);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 4);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 5);
@@ -377,22 +455,22 @@ static int rmi_f12_probe(struct rmi_func
 	}
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 6);
-	if (item && !xport->attn_data) {
+	if (item && !drvdata->attn_data.data) {
 		f12->data6 = item;
 		f12->data6_offset = data_offset;
 		data_offset += item->reg_size;
 	}
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 7);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 8);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 9);
-	if (item && !xport->attn_data) {
+	if (item && !drvdata->attn_data.data) {
 		f12->data9 = item;
 		f12->data9_offset = data_offset;
 		data_offset += item->reg_size;
@@ -401,27 +479,27 @@ static int rmi_f12_probe(struct rmi_func
 	}
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 10);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 11);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 12);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 13);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 14);
-	if (item && !xport->attn_data)
+	if (item && !drvdata->attn_data.data)
 		data_offset += item->reg_size;
 
 	item = rmi_get_register_desc_item(&f12->data_reg_desc, 15);
-	if (item && !xport->attn_data) {
+	if (item && !drvdata->attn_data.data) {
 		f12->data15 = item;
 		f12->data15_offset = data_offset;
 		data_offset += item->reg_size;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f30.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f30.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f30.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f30.c	2017-02-12 16:03:20.000000000 -0500
@@ -99,6 +99,7 @@ static int rmi_f30_attention(struct rmi_
 {
 	struct f30_data *f30 = dev_get_drvdata(&fn->dev);
 	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
 	int retval;
 	int gpiled = 0;
 	int value = 0;
@@ -109,11 +110,15 @@ static int rmi_f30_attention(struct rmi_
 		return 0;
 
 	/* Read the gpi led data. */
-	if (rmi_dev->xport->attn_data) {
-		memcpy(f30->data_regs, rmi_dev->xport->attn_data,
+	if (drvdata->attn_data.data) {
+		if (drvdata->attn_data.size < f30->register_count) {
+			dev_warn(&fn->dev, "F30 interrupted, but data is missing\n");
+			return 0;
+		}
+		memcpy(f30->data_regs, drvdata->attn_data.data,
 			f30->register_count);
-		rmi_dev->xport->attn_data += f30->register_count;
-		rmi_dev->xport->attn_size -= f30->register_count;
+		drvdata->attn_data.data += f30->register_count;
+		drvdata->attn_data.size -= f30->register_count;
 	} else {
 		retval = rmi_read_block(rmi_dev, fn->fd.data_base_addr,
 			f30->data_regs, f30->register_count);
@@ -192,7 +197,7 @@ static int rmi_f30_config(struct rmi_fun
 				rmi_get_platform_data(fn->rmi_dev);
 	int error;
 
-	if (pdata->f30_data && pdata->f30_data->disable) {
+	if (pdata->f30_data.disable) {
 		drv->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
 	} else {
 		/* Write Control Register values back to device */
@@ -351,7 +356,7 @@ static inline int rmi_f30_initialize(str
 	f30->gpioled_key_map = (u16 *)map_memory;
 
 	pdata = rmi_get_platform_data(rmi_dev);
-	if (pdata && f30->has_gpio) {
+	if (f30->has_gpio) {
 		button = BTN_LEFT;
 		for (i = 0; i < f30->gpioled_count; i++) {
 			if (rmi_f30_is_valid_button(i, f30->ctrl)) {
@@ -362,8 +367,7 @@ static inline int rmi_f30_initialize(str
 				 * f30->has_mech_mouse_btns, but I am
 				 * not sure, so use only the pdata info
 				 */
-				if (pdata->f30_data &&
-				    pdata->f30_data->buttonpad)
+				if (pdata->f30_data.buttonpad)
 					break;
 			}
 		}
@@ -378,7 +382,7 @@ static int rmi_f30_probe(struct rmi_func
 	const struct rmi_device_platform_data *pdata =
 				rmi_get_platform_data(fn->rmi_dev);
 
-	if (pdata->f30_data && pdata->f30_data->disable)
+	if (pdata->f30_data.disable)
 		return 0;
 
 	rc = rmi_f30_initialize(fn);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f34.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f34.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f34.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f34.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,516 @@
+/*
+ * Copyright (c) 2007-2016, Synaptics Incorporated
+ * Copyright (C) 2016 Zodiac Inflight Innovations
+ *
+ * This program is free software; you can redistribute it 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/rmi.h>
+#include <linux/firmware.h>
+#include <asm/unaligned.h>
+#include <asm/unaligned.h>
+#include <linux/bitops.h>
+
+#include "rmi_driver.h"
+#include "rmi_f34.h"
+
+static int rmi_f34_write_bootloader_id(struct f34_data *f34)
+{
+	struct rmi_function *fn = f34->fn;
+	struct rmi_device *rmi_dev = fn->rmi_dev;
+	u8 bootloader_id[F34_BOOTLOADER_ID_LEN];
+	int ret;
+
+	ret = rmi_read_block(rmi_dev, fn->fd.query_base_addr,
+			     bootloader_id, sizeof(bootloader_id));
+	if (ret) {
+		dev_err(&fn->dev, "%s: Reading bootloader ID failed: %d\n",
+				__func__, ret);
+		return ret;
+	}
+
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: writing bootloader id '%c%c'\n",
+			__func__, bootloader_id[0], bootloader_id[1]);
+
+	ret = rmi_write_block(rmi_dev,
+			      fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET,
+			      bootloader_id, sizeof(bootloader_id));
+	if (ret) {
+		dev_err(&fn->dev, "Failed to write bootloader ID: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rmi_f34_command(struct f34_data *f34, u8 command,
+			   unsigned int timeout, bool write_bl_id)
+{
+	struct rmi_function *fn = f34->fn;
+	struct rmi_device *rmi_dev = fn->rmi_dev;
+	int ret;
+
+	if (write_bl_id) {
+		ret = rmi_f34_write_bootloader_id(f34);
+		if (ret)
+			return ret;
+	}
+
+	init_completion(&f34->v5.cmd_done);
+
+	ret = rmi_read(rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
+	if (ret) {
+		dev_err(&f34->fn->dev,
+			"%s: Failed to read cmd register: %d (command %#02x)\n",
+			__func__, ret, command);
+		return ret;
+	}
+
+	f34->v5.status |= command & 0x0f;
+
+	ret = rmi_write(rmi_dev, f34->v5.ctrl_address, f34->v5.status);
+	if (ret < 0) {
+		dev_err(&f34->fn->dev,
+			"Failed to write F34 command %#02x: %d\n",
+			command, ret);
+		return ret;
+	}
+
+	if (!wait_for_completion_timeout(&f34->v5.cmd_done,
+				msecs_to_jiffies(timeout))) {
+
+		ret = rmi_read(rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
+		if (ret) {
+			dev_err(&f34->fn->dev,
+				"%s: cmd %#02x timed out: %d\n",
+				__func__, command, ret);
+			return ret;
+		}
+
+		if (f34->v5.status & 0x7f) {
+			dev_err(&f34->fn->dev,
+				"%s: cmd %#02x timed out, status: %#02x\n",
+				__func__, command, f34->v5.status);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int rmi_f34_attention(struct rmi_function *fn, unsigned long *irq_bits)
+{
+	struct f34_data *f34 = dev_get_drvdata(&fn->dev);
+	int ret;
+
+	if (f34->bl_version != 5)
+		return 0;
+
+	ret = rmi_read(f34->fn->rmi_dev, f34->v5.ctrl_address, &f34->v5.status);
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: status: %#02x, ret: %d\n",
+		__func__, f34->v5.status, ret);
+
+	if (!ret && !(f34->v5.status & 0x7f))
+		complete(&f34->v5.cmd_done);
+
+	return 0;
+}
+
+static int rmi_f34_write_blocks(struct f34_data *f34, const void *data,
+				int block_count, u8 command)
+{
+	struct rmi_function *fn = f34->fn;
+	struct rmi_device *rmi_dev = fn->rmi_dev;
+	u16 address = fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET;
+	u8 start_address[] = { 0, 0 };
+	int i;
+	int ret;
+
+	ret = rmi_write_block(rmi_dev, fn->fd.data_base_addr,
+			      start_address, sizeof(start_address));
+	if (ret) {
+		dev_err(&fn->dev, "Failed to write initial zeros: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < block_count; i++) {
+		ret = rmi_write_block(rmi_dev, address,
+				      data, f34->v5.block_size);
+		if (ret) {
+			dev_err(&fn->dev,
+				"failed to write block #%d: %d\n", i, ret);
+			return ret;
+		}
+
+		ret = rmi_f34_command(f34, command, F34_IDLE_WAIT_MS, false);
+		if (ret) {
+			dev_err(&fn->dev,
+				"Failed to write command for block #%d: %d\n",
+				i, ret);
+			return ret;
+		}
+
+		rmi_dbg(RMI_DEBUG_FN, &fn->dev, "wrote block %d of %d\n",
+			i + 1, block_count);
+
+		data += f34->v5.block_size;
+	}
+
+	return 0;
+}
+
+static int rmi_f34_write_firmware(struct f34_data *f34, const void *data)
+{
+	return rmi_f34_write_blocks(f34, data, f34->v5.fw_blocks,
+				    F34_WRITE_FW_BLOCK);
+}
+
+static int rmi_f34_write_config(struct f34_data *f34, const void *data)
+{
+	return rmi_f34_write_blocks(f34, data, f34->v5.config_blocks,
+				    F34_WRITE_CONFIG_BLOCK);
+}
+
+int rmi_f34_enable_flash(struct f34_data *f34)
+{
+	return rmi_f34_command(f34, F34_ENABLE_FLASH_PROG,
+			       F34_ENABLE_WAIT_MS, true);
+}
+
+static int rmi_f34_flash_firmware(struct f34_data *f34,
+				  const struct rmi_f34_firmware *syn_fw)
+{
+	struct rmi_function *fn = f34->fn;
+	int ret;
+
+	if (syn_fw->image_size) {
+		dev_info(&fn->dev, "Erasing firmware...\n");
+		ret = rmi_f34_command(f34, F34_ERASE_ALL,
+				      F34_ERASE_WAIT_MS, true);
+		if (ret)
+			return ret;
+
+		dev_info(&fn->dev, "Writing firmware (%d bytes)...\n",
+			 syn_fw->image_size);
+		ret = rmi_f34_write_firmware(f34, syn_fw->data);
+		if (ret)
+			return ret;
+	}
+
+	if (syn_fw->config_size) {
+		/*
+		 * We only need to erase config if we haven't updated
+		 * firmware.
+		 */
+		if (!syn_fw->image_size) {
+			dev_info(&fn->dev, "Erasing config...\n");
+			ret = rmi_f34_command(f34, F34_ERASE_CONFIG,
+					      F34_ERASE_WAIT_MS, true);
+			if (ret)
+				return ret;
+		}
+
+		dev_info(&fn->dev, "Writing config (%d bytes)...\n",
+			 syn_fw->config_size);
+		ret = rmi_f34_write_config(f34,
+				&syn_fw->data[syn_fw->image_size]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw)
+{
+	const struct rmi_f34_firmware *syn_fw;
+	int ret;
+
+	syn_fw = (const struct rmi_f34_firmware *)fw->data;
+	BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) !=
+			F34_FW_IMAGE_OFFSET);
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+		"FW size:%d, checksum:%08x, image_size:%d, config_size:%d\n",
+		(int)fw->size,
+		le32_to_cpu(syn_fw->checksum),
+		le32_to_cpu(syn_fw->image_size),
+		le32_to_cpu(syn_fw->config_size));
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+		"FW bootloader_id:%02x, product_id:%.*s, info: %02x%02x\n",
+		syn_fw->bootloader_version,
+		(int)sizeof(syn_fw->product_id), syn_fw->product_id,
+		syn_fw->product_info[0], syn_fw->product_info[1]);
+
+	if (syn_fw->image_size &&
+	    syn_fw->image_size != f34->v5.fw_blocks * f34->v5.block_size) {
+		dev_err(&f34->fn->dev,
+			"Bad firmware image: fw size %d, expected %d\n",
+			syn_fw->image_size,
+			f34->v5.fw_blocks * f34->v5.block_size);
+		ret = -EILSEQ;
+		goto out;
+	}
+
+	if (syn_fw->config_size &&
+	    syn_fw->config_size != f34->v5.config_blocks * f34->v5.block_size) {
+		dev_err(&f34->fn->dev,
+			"Bad firmware image: config size %d, expected %d\n",
+			syn_fw->config_size,
+			f34->v5.config_blocks * f34->v5.block_size);
+		ret = -EILSEQ;
+		goto out;
+	}
+
+	if (syn_fw->image_size && !syn_fw->config_size) {
+		dev_err(&f34->fn->dev, "Bad firmware image: no config data\n");
+		ret = -EILSEQ;
+		goto out;
+	}
+
+	dev_info(&f34->fn->dev, "Firmware image OK\n");
+	mutex_lock(&f34->v5.flash_mutex);
+
+	ret = rmi_f34_flash_firmware(f34, syn_fw);
+
+	mutex_unlock(&f34->v5.flash_mutex);
+
+out:
+	return ret;
+}
+
+static int rmi_firmware_update(struct rmi_driver_data *data,
+			       const struct firmware *fw)
+{
+	struct rmi_device *rmi_dev = data->rmi_dev;
+	struct device *dev = &rmi_dev->dev;
+	struct f34_data *f34;
+	int ret;
+
+	if (!data->f34_container) {
+		dev_warn(dev, "%s: No F34 present!\n", __func__);
+		return -EINVAL;
+	}
+
+	f34 = dev_get_drvdata(&data->f34_container->dev);
+
+	if (f34->bl_version == 7) {
+		if (data->pdt_props & HAS_BSR) {
+			dev_err(dev, "%s: LTS not supported\n", __func__);
+			return -ENODEV;
+		}
+	} else if (f34->bl_version != 5) {
+		dev_warn(dev, "F34 V%d not supported!\n",
+			 data->f34_container->fd.function_version);
+		return -ENODEV;
+	}
+
+	/* Enter flash mode */
+	if (f34->bl_version == 7)
+		ret = rmi_f34v7_start_reflash(f34, fw);
+	else
+		ret = rmi_f34_enable_flash(f34);
+	if (ret)
+		return ret;
+
+	rmi_disable_irq(rmi_dev, false);
+
+	/* Tear down functions and re-probe */
+	rmi_free_function_list(rmi_dev);
+
+	ret = rmi_probe_interrupts(data);
+	if (ret)
+		return ret;
+
+	ret = rmi_init_functions(data);
+	if (ret)
+		return ret;
+
+	if (!data->bootloader_mode || !data->f34_container) {
+		dev_warn(dev, "%s: No F34 present or not in bootloader!\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	rmi_enable_irq(rmi_dev, false);
+
+	f34 = dev_get_drvdata(&data->f34_container->dev);
+
+	/* Perform firmware update */
+	if (f34->bl_version == 7)
+		ret = rmi_f34v7_do_reflash(f34, fw);
+	else
+		ret = rmi_f34_update_firmware(f34, fw);
+
+	dev_info(&f34->fn->dev, "Firmware update complete, status:%d\n", ret);
+
+	rmi_disable_irq(rmi_dev, false);
+
+	/* Re-probe */
+	rmi_dbg(RMI_DEBUG_FN, dev, "Re-probing device\n");
+	rmi_free_function_list(rmi_dev);
+
+	ret = rmi_scan_pdt(rmi_dev, NULL, rmi_initial_reset);
+	if (ret < 0)
+		dev_warn(dev, "RMI reset failed!\n");
+
+	ret = rmi_probe_interrupts(data);
+	if (ret)
+		return ret;
+
+	ret = rmi_init_functions(data);
+	if (ret)
+		return ret;
+
+	rmi_enable_irq(rmi_dev, false);
+
+	if (data->f01_container->dev.driver)
+		/* Driver already bound, so enable ATTN now. */
+		return rmi_enable_sensor(rmi_dev);
+
+	rmi_dbg(RMI_DEBUG_FN, dev, "%s complete\n", __func__);
+
+	return ret;
+}
+
+static int rmi_firmware_update(struct rmi_driver_data *data,
+			       const struct firmware *fw);
+
+static ssize_t rmi_driver_update_fw_store(struct device *dev,
+					  struct device_attribute *dattr,
+					  const char *buf, size_t count)
+{
+	struct rmi_driver_data *data = dev_get_drvdata(dev);
+	char fw_name[NAME_MAX];
+	const struct firmware *fw;
+	size_t copy_count = count;
+	int ret;
+
+	if (count == 0 || count >= NAME_MAX)
+		return -EINVAL;
+
+	if (buf[count - 1] == '\0' || buf[count - 1] == '\n')
+		copy_count -= 1;
+
+	strncpy(fw_name, buf, copy_count);
+	fw_name[copy_count] = '\0';
+
+	ret = request_firmware(&fw, fw_name, dev);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "Flashing %s\n", fw_name);
+
+	ret = rmi_firmware_update(data, fw);
+
+	release_firmware(fw);
+
+	return ret ?: count;
+}
+
+static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store);
+
+static struct attribute *rmi_firmware_attrs[] = {
+	&dev_attr_update_fw.attr,
+	NULL
+};
+
+static struct attribute_group rmi_firmware_attr_group = {
+	.attrs = rmi_firmware_attrs,
+};
+
+static int rmi_f34_probe(struct rmi_function *fn)
+{
+	struct f34_data *f34;
+	unsigned char f34_queries[9];
+	bool has_config_id;
+	u8 version = fn->fd.function_version;
+	int ret;
+
+	f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL);
+	if (!f34)
+		return -ENOMEM;
+
+	f34->fn = fn;
+	dev_set_drvdata(&fn->dev, f34);
+
+	/* v5 code only supported version 0, try V7 probe */
+	if (version > 0)
+		return rmi_f34v7_probe(f34);
+	else if (version != 0)
+		return -ENODEV;
+
+	f34->bl_version = 5;
+
+	ret = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
+			     f34_queries, sizeof(f34_queries));
+	if (ret) {
+		dev_err(&fn->dev, "%s: Failed to query properties\n",
+			__func__);
+		return ret;
+	}
+
+	snprintf(f34->bootloader_id, sizeof(f34->bootloader_id),
+		 "%c%c", f34_queries[0], f34_queries[1]);
+
+	mutex_init(&f34->v5.flash_mutex);
+	init_completion(&f34->v5.cmd_done);
+
+	f34->v5.block_size = get_unaligned_le16(&f34_queries[3]);
+	f34->v5.fw_blocks = get_unaligned_le16(&f34_queries[5]);
+	f34->v5.config_blocks = get_unaligned_le16(&f34_queries[7]);
+	f34->v5.ctrl_address = fn->fd.data_base_addr + F34_BLOCK_DATA_OFFSET +
+		f34->v5.block_size;
+	has_config_id = f34_queries[2] & (1 << 2);
+
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Bootloader ID: %s\n",
+		f34->bootloader_id);
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Block size: %d\n",
+		f34->v5.block_size);
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "FW blocks: %d\n",
+		f34->v5.fw_blocks);
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "CFG blocks: %d\n",
+		f34->v5.config_blocks);
+
+	if (has_config_id) {
+		ret = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr,
+				     f34_queries, sizeof(f34_queries));
+		if (ret) {
+			dev_err(&fn->dev, "Failed to read F34 config ID\n");
+			return ret;
+		}
+
+		snprintf(f34->configuration_id, sizeof(f34->configuration_id),
+			 "%02x%02x%02x%02x",
+			 f34_queries[0], f34_queries[1],
+			 f34_queries[2], f34_queries[3]);
+
+		rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Configuration ID: %s\n",
+			 f34->configuration_id);
+	}
+
+	return 0;
+}
+
+int rmi_f34_create_sysfs(struct rmi_device *rmi_dev)
+{
+	return sysfs_create_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
+}
+
+void rmi_f34_remove_sysfs(struct rmi_device *rmi_dev)
+{
+	sysfs_remove_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group);
+}
+
+struct rmi_function_handler rmi_f34_handler = {
+	.driver = {
+		.name = "rmi4_f34",
+	},
+	.func = 0x34,
+	.probe = rmi_f34_probe,
+	.attention = rmi_f34_attention,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f34.h linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f34.h
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f34.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f34.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2007-2016, Synaptics Incorporated
+ * Copyright (C) 2016 Zodiac Inflight Innovations
+ *
+ * This program is free software; you can 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 _RMI_F34_H
+#define _RMI_F34_H
+
+/* F34 image file offsets. */
+#define F34_FW_IMAGE_OFFSET	0x100
+
+/* F34 register offsets. */
+#define F34_BLOCK_DATA_OFFSET	2
+
+/* F34 commands */
+#define F34_WRITE_FW_BLOCK	0x2
+#define F34_ERASE_ALL		0x3
+#define F34_READ_CONFIG_BLOCK	0x5
+#define F34_WRITE_CONFIG_BLOCK	0x6
+#define F34_ERASE_CONFIG	0x7
+#define F34_ENABLE_FLASH_PROG	0xf
+
+#define F34_STATUS_IN_PROGRESS	0xff
+#define F34_STATUS_IDLE		0x80
+
+#define F34_IDLE_WAIT_MS	500
+#define F34_ENABLE_WAIT_MS	300
+#define F34_ERASE_WAIT_MS	5000
+
+#define F34_BOOTLOADER_ID_LEN	2
+
+/* F34 V7 defines */
+#define V7_FLASH_STATUS_OFFSET		0
+#define V7_PARTITION_ID_OFFSET		1
+#define V7_BLOCK_NUMBER_OFFSET		2
+#define V7_TRANSFER_LENGTH_OFFSET	3
+#define V7_COMMAND_OFFSET		4
+#define V7_PAYLOAD_OFFSET		5
+#define V7_BOOTLOADER_ID_OFFSET		1
+
+#define IMAGE_HEADER_VERSION_10		0x10
+
+#define CONFIG_ID_SIZE			32
+#define PRODUCT_ID_SIZE			10
+
+#define ENABLE_WAIT_MS			(1 * 1000)
+#define WRITE_WAIT_MS			(3 * 1000)
+
+#define MIN_SLEEP_TIME_US		50
+#define MAX_SLEEP_TIME_US		100
+
+#define HAS_BSR				BIT(5)
+#define HAS_CONFIG_ID			BIT(3)
+#define HAS_GUEST_CODE			BIT(6)
+#define HAS_DISP_CFG			BIT(5)
+
+/* F34 V7 commands */
+#define CMD_V7_IDLE			0
+#define CMD_V7_ENTER_BL			1
+#define CMD_V7_READ			2
+#define CMD_V7_WRITE			3
+#define CMD_V7_ERASE			4
+#define CMD_V7_ERASE_AP			5
+#define CMD_V7_SENSOR_ID		6
+
+#define v7_CMD_IDLE			0
+#define v7_CMD_WRITE_FW			1
+#define v7_CMD_WRITE_CONFIG		2
+#define v7_CMD_WRITE_LOCKDOWN		3
+#define v7_CMD_WRITE_GUEST_CODE		4
+#define v7_CMD_READ_CONFIG		5
+#define v7_CMD_ERASE_ALL		6
+#define v7_CMD_ERASE_UI_FIRMWARE	7
+#define v7_CMD_ERASE_UI_CONFIG		8
+#define v7_CMD_ERASE_BL_CONFIG		9
+#define v7_CMD_ERASE_DISP_CONFIG	10
+#define v7_CMD_ERASE_FLASH_CONFIG	11
+#define v7_CMD_ERASE_GUEST_CODE		12
+#define v7_CMD_ENABLE_FLASH_PROG	13
+
+#define v7_UI_CONFIG_AREA		0
+#define v7_PM_CONFIG_AREA		1
+#define v7_BL_CONFIG_AREA		2
+#define v7_DP_CONFIG_AREA		3
+#define v7_FLASH_CONFIG_AREA		4
+
+/* F34 V7 partition IDs */
+#define BOOTLOADER_PARTITION		1
+#define DEVICE_CONFIG_PARTITION		2
+#define FLASH_CONFIG_PARTITION		3
+#define MANUFACTURING_BLOCK_PARTITION	4
+#define GUEST_SERIALIZATION_PARTITION	5
+#define GLOBAL_PARAMETERS_PARTITION	6
+#define CORE_CODE_PARTITION		7
+#define CORE_CONFIG_PARTITION		8
+#define GUEST_CODE_PARTITION		9
+#define DISPLAY_CONFIG_PARTITION	10
+
+/* F34 V7 container IDs */
+#define TOP_LEVEL_CONTAINER			0
+#define UI_CONTAINER				1
+#define UI_CONFIG_CONTAINER			2
+#define BL_CONTAINER				3
+#define BL_IMAGE_CONTAINER			4
+#define BL_CONFIG_CONTAINER			5
+#define BL_LOCKDOWN_INFO_CONTAINER		6
+#define PERMANENT_CONFIG_CONTAINER		7
+#define GUEST_CODE_CONTAINER			8
+#define BL_PROTOCOL_DESCRIPTOR_CONTAINER	9
+#define UI_PROTOCOL_DESCRIPTOR_CONTAINER	10
+#define RMI_SELF_DISCOVERY_CONTAINER		11
+#define RMI_PAGE_CONTENT_CONTAINER		12
+#define GENERAL_INFORMATION_CONTAINER		13
+#define DEVICE_CONFIG_CONTAINER			14
+#define FLASH_CONFIG_CONTAINER			15
+#define GUEST_SERIALIZATION_CONTAINER		16
+#define GLOBAL_PARAMETERS_CONTAINER		17
+#define CORE_CODE_CONTAINER			18
+#define CORE_CONFIG_CONTAINER			19
+#define DISPLAY_CONFIG_CONTAINER		20
+
+struct f34v7_query_1_7 {
+	u8 bl_minor_revision;			/* query 1 */
+	u8 bl_major_revision;
+	__le32 bl_fw_id;			/* query 2 */
+	u8 minimum_write_size;			/* query 3 */
+	__le16 block_size;
+	__le16 flash_page_size;
+	__le16 adjustable_partition_area_size;	/* query 4 */
+	__le16 flash_config_length;		/* query 5 */
+	__le16 payload_length;			/* query 6 */
+	u8 partition_support[4];		/* query 7 */
+} __packed;
+
+struct f34v7_data_1_5 {
+	u8 partition_id;
+	__le16 block_offset;
+	__le16 transfer_length;
+	u8 command;
+	u8 payload[2];
+} __packed;
+
+struct block_data {
+	const void *data;
+	int size;
+};
+
+struct partition_table {
+	u8 partition_id;
+	u8 byte_1_reserved;
+	__le16 partition_length;
+	__le16 start_physical_address;
+	__le16 partition_properties;
+} __packed;
+
+struct physical_address {
+	u16 ui_firmware;
+	u16 ui_config;
+	u16 dp_config;
+	u16 guest_code;
+};
+
+struct container_descriptor {
+	__le32 content_checksum;
+	__le16 container_id;
+	u8 minor_version;
+	u8 major_version;
+	u8 reserved_08;
+	u8 reserved_09;
+	u8 reserved_0a;
+	u8 reserved_0b;
+	u8 container_option_flags[4];
+	__le32 content_options_length;
+	__le32 content_options_address;
+	__le32 content_length;
+	__le32 content_address;
+} __packed;
+
+struct block_count {
+	u16 ui_firmware;
+	u16 ui_config;
+	u16 dp_config;
+	u16 fl_config;
+	u16 pm_config;
+	u16 bl_config;
+	u16 lockdown;
+	u16 guest_code;
+};
+
+struct image_header_10 {
+	__le32 checksum;
+	u8 reserved_04;
+	u8 reserved_05;
+	u8 minor_header_version;
+	u8 major_header_version;
+	u8 reserved_08;
+	u8 reserved_09;
+	u8 reserved_0a;
+	u8 reserved_0b;
+	__le32 top_level_container_start_addr;
+};
+
+struct image_metadata {
+	bool contains_firmware_id;
+	bool contains_bootloader;
+	bool contains_display_cfg;
+	bool contains_guest_code;
+	bool contains_flash_config;
+	unsigned int firmware_id;
+	unsigned int checksum;
+	unsigned int bootloader_size;
+	unsigned int display_cfg_offset;
+	unsigned char bl_version;
+	unsigned char product_id[PRODUCT_ID_SIZE + 1];
+	unsigned char cstmr_product_id[PRODUCT_ID_SIZE + 1];
+	struct block_data bootloader;
+	struct block_data ui_firmware;
+	struct block_data ui_config;
+	struct block_data dp_config;
+	struct block_data fl_config;
+	struct block_data bl_config;
+	struct block_data guest_code;
+	struct block_data lockdown;
+	struct block_count blkcount;
+	struct physical_address phyaddr;
+};
+
+struct register_offset {
+	u8 properties;
+	u8 properties_2;
+	u8 block_size;
+	u8 block_count;
+	u8 gc_block_count;
+	u8 flash_status;
+	u8 partition_id;
+	u8 block_number;
+	u8 transfer_length;
+	u8 flash_cmd;
+	u8 payload;
+};
+
+struct rmi_f34_firmware {
+	__le32 checksum;
+	u8 pad1[3];
+	u8 bootloader_version;
+	__le32 image_size;
+	__le32 config_size;
+	u8 product_id[10];
+	u8 product_info[2];
+	u8 pad2[228];
+	u8 data[];
+};
+
+struct f34v5_data {
+	u16 block_size;
+	u16 fw_blocks;
+	u16 config_blocks;
+	u16 ctrl_address;
+	u8 status;
+
+	struct completion cmd_done;
+	struct mutex flash_mutex;
+};
+
+struct f34v7_data {
+	bool has_display_cfg;
+	bool has_guest_code;
+	bool force_update;
+	bool in_bl_mode;
+	u8 *read_config_buf;
+	size_t read_config_buf_size;
+	u8 command;
+	u8 flash_status;
+	u16 block_size;
+	u16 config_block_count;
+	u16 config_size;
+	u16 config_area;
+	u16 flash_config_length;
+	u16 payload_length;
+	u8 partitions;
+	u16 partition_table_bytes;
+	bool new_partition_table;
+
+	struct register_offset off;
+	struct block_count blkcount;
+	struct physical_address phyaddr;
+	struct image_metadata img;
+
+	const void *config_data;
+	const void *image;
+};
+
+struct f34_data {
+	struct rmi_function *fn;
+
+	u8 bl_version;
+	unsigned char bootloader_id[5];
+	unsigned char configuration_id[CONFIG_ID_SIZE*2 + 1];
+
+	union {
+		struct f34v5_data v5;
+		struct f34v7_data v7;
+	};
+};
+
+int rmi_f34v7_start_reflash(struct f34_data *f34, const struct firmware *fw);
+int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw);
+int rmi_f34v7_probe(struct f34_data *f34);
+
+#endif /* _RMI_F34_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f34v7.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f34v7.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f34v7.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f34v7.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1372 @@
+/*
+ * Copyright (c) 2016, Zodiac Inflight Innovations
+ * Copyright (c) 2007-2016, Synaptics Incorporated
+ * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
+ * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.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/rmi.h>
+#include <linux/firmware.h>
+#include <asm/unaligned.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include "rmi_driver.h"
+#include "rmi_f34.h"
+
+static int rmi_f34v7_read_flash_status(struct f34_data *f34)
+{
+	u8 status;
+	u8 command;
+	int ret;
+
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			f34->fn->fd.data_base_addr + f34->v7.off.flash_status,
+			&status,
+			sizeof(status));
+	if (ret < 0) {
+		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+			"%s: Failed to read flash status\n", __func__);
+		return ret;
+	}
+
+	f34->v7.in_bl_mode = status >> 7;
+	f34->v7.flash_status = status & 0x1f;
+
+	if (f34->v7.flash_status != 0x00) {
+		dev_err(&f34->fn->dev, "%s: status=%d, command=0x%02x\n",
+			__func__, f34->v7.flash_status, f34->v7.command);
+	}
+
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			f34->fn->fd.data_base_addr + f34->v7.off.flash_cmd,
+			&command,
+			sizeof(command));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to read flash command\n",
+			__func__);
+		return ret;
+	}
+
+	f34->v7.command = command;
+
+	return 0;
+}
+
+static int rmi_f34v7_wait_for_idle(struct f34_data *f34, int timeout_ms)
+{
+	int count = 0;
+	int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
+
+	do {
+		usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
+
+		count++;
+
+		rmi_f34v7_read_flash_status(f34);
+
+		if ((f34->v7.command == v7_CMD_IDLE)
+		    && (f34->v7.flash_status == 0x00)) {
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"Idle status detected\n");
+			return 0;
+		}
+	} while (count < timeout_count);
+
+	dev_err(&f34->fn->dev,
+		"%s: Timed out waiting for idle status\n", __func__);
+
+	return -ETIMEDOUT;
+}
+
+static int rmi_f34v7_write_command_single_transaction(struct f34_data *f34,
+						      u8 cmd)
+{
+	int ret;
+	u8 base;
+	struct f34v7_data_1_5 data_1_5;
+
+	base = f34->fn->fd.data_base_addr;
+
+	memset(&data_1_5, 0, sizeof(data_1_5));
+
+	switch (cmd) {
+	case v7_CMD_ERASE_ALL:
+		data_1_5.partition_id = CORE_CODE_PARTITION;
+		data_1_5.command = CMD_V7_ERASE_AP;
+		break;
+	case v7_CMD_ERASE_UI_FIRMWARE:
+		data_1_5.partition_id = CORE_CODE_PARTITION;
+		data_1_5.command = CMD_V7_ERASE;
+		break;
+	case v7_CMD_ERASE_BL_CONFIG:
+		data_1_5.partition_id = GLOBAL_PARAMETERS_PARTITION;
+		data_1_5.command = CMD_V7_ERASE;
+		break;
+	case v7_CMD_ERASE_UI_CONFIG:
+		data_1_5.partition_id = CORE_CONFIG_PARTITION;
+		data_1_5.command = CMD_V7_ERASE;
+		break;
+	case v7_CMD_ERASE_DISP_CONFIG:
+		data_1_5.partition_id = DISPLAY_CONFIG_PARTITION;
+		data_1_5.command = CMD_V7_ERASE;
+		break;
+	case v7_CMD_ERASE_FLASH_CONFIG:
+		data_1_5.partition_id = FLASH_CONFIG_PARTITION;
+		data_1_5.command = CMD_V7_ERASE;
+		break;
+	case v7_CMD_ERASE_GUEST_CODE:
+		data_1_5.partition_id = GUEST_CODE_PARTITION;
+		data_1_5.command = CMD_V7_ERASE;
+		break;
+	case v7_CMD_ENABLE_FLASH_PROG:
+		data_1_5.partition_id = BOOTLOADER_PARTITION;
+		data_1_5.command = CMD_V7_ENTER_BL;
+		break;
+	}
+
+	data_1_5.payload[0] = f34->bootloader_id[0];
+	data_1_5.payload[1] = f34->bootloader_id[1];
+
+	ret = rmi_write_block(f34->fn->rmi_dev,
+			base + f34->v7.off.partition_id,
+			&data_1_5, sizeof(data_1_5));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev,
+			"%s: Failed to write single transaction command\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_write_command(struct f34_data *f34, u8 cmd)
+{
+	int ret;
+	u8 base;
+	u8 command;
+
+	base = f34->fn->fd.data_base_addr;
+
+	switch (cmd) {
+	case v7_CMD_WRITE_FW:
+	case v7_CMD_WRITE_CONFIG:
+	case v7_CMD_WRITE_GUEST_CODE:
+		command = CMD_V7_WRITE;
+		break;
+	case v7_CMD_READ_CONFIG:
+		command = CMD_V7_READ;
+		break;
+	case v7_CMD_ERASE_ALL:
+		command = CMD_V7_ERASE_AP;
+		break;
+	case v7_CMD_ERASE_UI_FIRMWARE:
+	case v7_CMD_ERASE_BL_CONFIG:
+	case v7_CMD_ERASE_UI_CONFIG:
+	case v7_CMD_ERASE_DISP_CONFIG:
+	case v7_CMD_ERASE_FLASH_CONFIG:
+	case v7_CMD_ERASE_GUEST_CODE:
+		command = CMD_V7_ERASE;
+		break;
+	case v7_CMD_ENABLE_FLASH_PROG:
+		command = CMD_V7_ENTER_BL;
+		break;
+	default:
+		dev_err(&f34->fn->dev, "%s: Invalid command 0x%02x\n",
+			__func__, cmd);
+		return -EINVAL;
+	}
+
+	f34->v7.command = command;
+
+	switch (cmd) {
+	case v7_CMD_ERASE_ALL:
+	case v7_CMD_ERASE_UI_FIRMWARE:
+	case v7_CMD_ERASE_BL_CONFIG:
+	case v7_CMD_ERASE_UI_CONFIG:
+	case v7_CMD_ERASE_DISP_CONFIG:
+	case v7_CMD_ERASE_FLASH_CONFIG:
+	case v7_CMD_ERASE_GUEST_CODE:
+	case v7_CMD_ENABLE_FLASH_PROG:
+		ret = rmi_f34v7_write_command_single_transaction(f34, cmd);
+		if (ret < 0)
+			return ret;
+		else
+			return 0;
+	default:
+		break;
+	}
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: writing cmd %02X\n",
+		__func__, command);
+
+	ret = rmi_write_block(f34->fn->rmi_dev,
+			base + f34->v7.off.flash_cmd,
+			&command, sizeof(command));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to write flash command\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_write_partition_id(struct f34_data *f34, u8 cmd)
+{
+	int ret;
+	u8 base;
+	u8 partition;
+
+	base = f34->fn->fd.data_base_addr;
+
+	switch (cmd) {
+	case v7_CMD_WRITE_FW:
+		partition = CORE_CODE_PARTITION;
+		break;
+	case v7_CMD_WRITE_CONFIG:
+	case v7_CMD_READ_CONFIG:
+		if (f34->v7.config_area == v7_UI_CONFIG_AREA)
+			partition = CORE_CONFIG_PARTITION;
+		else if (f34->v7.config_area == v7_DP_CONFIG_AREA)
+			partition = DISPLAY_CONFIG_PARTITION;
+		else if (f34->v7.config_area == v7_PM_CONFIG_AREA)
+			partition = GUEST_SERIALIZATION_PARTITION;
+		else if (f34->v7.config_area == v7_BL_CONFIG_AREA)
+			partition = GLOBAL_PARAMETERS_PARTITION;
+		else if (f34->v7.config_area == v7_FLASH_CONFIG_AREA)
+			partition = FLASH_CONFIG_PARTITION;
+		break;
+	case v7_CMD_WRITE_GUEST_CODE:
+		partition = GUEST_CODE_PARTITION;
+		break;
+	case v7_CMD_ERASE_ALL:
+		partition = CORE_CODE_PARTITION;
+		break;
+	case v7_CMD_ERASE_BL_CONFIG:
+		partition = GLOBAL_PARAMETERS_PARTITION;
+		break;
+	case v7_CMD_ERASE_UI_CONFIG:
+		partition = CORE_CONFIG_PARTITION;
+		break;
+	case v7_CMD_ERASE_DISP_CONFIG:
+		partition = DISPLAY_CONFIG_PARTITION;
+		break;
+	case v7_CMD_ERASE_FLASH_CONFIG:
+		partition = FLASH_CONFIG_PARTITION;
+		break;
+	case v7_CMD_ERASE_GUEST_CODE:
+		partition = GUEST_CODE_PARTITION;
+		break;
+	case v7_CMD_ENABLE_FLASH_PROG:
+		partition = BOOTLOADER_PARTITION;
+		break;
+	default:
+		dev_err(&f34->fn->dev, "%s: Invalid command 0x%02x\n",
+			__func__, cmd);
+		return -EINVAL;
+	}
+
+	ret = rmi_write_block(f34->fn->rmi_dev,
+			base + f34->v7.off.partition_id,
+			&partition, sizeof(partition));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to write partition ID\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_read_f34v7_partition_table(struct f34_data *f34)
+{
+	int ret;
+	u8 base;
+	__le16 length;
+	u16 block_number = 0;
+
+	base = f34->fn->fd.data_base_addr;
+
+	f34->v7.config_area = v7_FLASH_CONFIG_AREA;
+
+	ret = rmi_f34v7_write_partition_id(f34, v7_CMD_READ_CONFIG);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_write_block(f34->fn->rmi_dev,
+			base + f34->v7.off.block_number,
+			&block_number, sizeof(block_number));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
+			__func__);
+		return ret;
+	}
+
+	put_unaligned_le16(f34->v7.flash_config_length, &length);
+
+	ret = rmi_write_block(f34->fn->rmi_dev,
+			base + f34->v7.off.transfer_length,
+			&length, sizeof(length));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to write transfer length\n",
+			__func__);
+		return ret;
+	}
+
+	ret = rmi_f34v7_write_command(f34, v7_CMD_READ_CONFIG);
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to write command\n",
+			__func__);
+		return ret;
+	}
+
+	ret = rmi_f34v7_wait_for_idle(f34, WRITE_WAIT_MS);
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to wait for idle status\n",
+			__func__);
+		return ret;
+	}
+
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			base + f34->v7.off.payload,
+			f34->v7.read_config_buf,
+			f34->v7.partition_table_bytes);
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to read block data\n",
+			__func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void rmi_f34v7_parse_partition_table(struct f34_data *f34,
+					    const void *partition_table,
+					    struct block_count *blkcount,
+					    struct physical_address *phyaddr)
+{
+	int i;
+	int index;
+	u16 partition_length;
+	u16 physical_address;
+	const struct partition_table *ptable;
+
+	for (i = 0; i < f34->v7.partitions; i++) {
+		index = i * 8 + 2;
+		ptable = partition_table + index;
+		partition_length = le16_to_cpu(ptable->partition_length);
+		physical_address = le16_to_cpu(ptable->start_physical_address);
+		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+			"%s: Partition entry %d: %*ph\n",
+			__func__, i, sizeof(struct partition_table), ptable);
+		switch (ptable->partition_id & 0x1f) {
+		case CORE_CODE_PARTITION:
+			blkcount->ui_firmware = partition_length;
+			phyaddr->ui_firmware = physical_address;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Core code block count: %d\n",
+				__func__, blkcount->ui_firmware);
+			break;
+		case CORE_CONFIG_PARTITION:
+			blkcount->ui_config = partition_length;
+			phyaddr->ui_config = physical_address;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Core config block count: %d\n",
+				__func__, blkcount->ui_config);
+			break;
+		case DISPLAY_CONFIG_PARTITION:
+			blkcount->dp_config = partition_length;
+			phyaddr->dp_config = physical_address;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Display config block count: %d\n",
+				__func__, blkcount->dp_config);
+			break;
+		case FLASH_CONFIG_PARTITION:
+			blkcount->fl_config = partition_length;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Flash config block count: %d\n",
+				__func__, blkcount->fl_config);
+			break;
+		case GUEST_CODE_PARTITION:
+			blkcount->guest_code = partition_length;
+			phyaddr->guest_code = physical_address;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Guest code block count: %d\n",
+				__func__, blkcount->guest_code);
+			break;
+		case GUEST_SERIALIZATION_PARTITION:
+			blkcount->pm_config = partition_length;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Guest serialization block count: %d\n",
+				__func__, blkcount->pm_config);
+			break;
+		case GLOBAL_PARAMETERS_PARTITION:
+			blkcount->bl_config = partition_length;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Global parameters block count: %d\n",
+				__func__, blkcount->bl_config);
+			break;
+		case DEVICE_CONFIG_PARTITION:
+			blkcount->lockdown = partition_length;
+			rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+				"%s: Device config block count: %d\n",
+				__func__, blkcount->lockdown);
+			break;
+		}
+	}
+}
+
+static int rmi_f34v7_read_queries_bl_version(struct f34_data *f34)
+{
+	int ret;
+	u8 base;
+	int offset;
+	u8 query_0;
+	struct f34v7_query_1_7 query_1_7;
+
+	base = f34->fn->fd.query_base_addr;
+
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			base,
+			&query_0,
+			sizeof(query_0));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev,
+			"%s: Failed to read query 0\n", __func__);
+		return ret;
+	}
+
+	offset = (query_0 & 0x7) + 1;
+
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			base + offset,
+			&query_1_7,
+			sizeof(query_1_7));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to read queries 1 to 7\n",
+			__func__);
+		return ret;
+	}
+
+	f34->bootloader_id[0] = query_1_7.bl_minor_revision;
+	f34->bootloader_id[1] = query_1_7.bl_major_revision;
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "Bootloader V%d.%d\n",
+		f34->bootloader_id[1], f34->bootloader_id[0]);
+
+	return 0;
+}
+
+static int rmi_f34v7_read_queries(struct f34_data *f34)
+{
+	int ret;
+	int i, j;
+	u8 base;
+	int offset;
+	u8 *ptable;
+	u8 query_0;
+	struct f34v7_query_1_7 query_1_7;
+
+	base = f34->fn->fd.query_base_addr;
+
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			base,
+			&query_0,
+			sizeof(query_0));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev,
+			"%s: Failed to read query 0\n", __func__);
+		return ret;
+	}
+
+	offset = (query_0 & 0x07) + 1;
+
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			base + offset,
+			&query_1_7,
+			sizeof(query_1_7));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to read queries 1 to 7\n",
+			__func__);
+		return ret;
+	}
+
+	f34->bootloader_id[0] = query_1_7.bl_minor_revision;
+	f34->bootloader_id[1] = query_1_7.bl_major_revision;
+
+	f34->v7.block_size = le16_to_cpu(query_1_7.block_size);
+	f34->v7.flash_config_length =
+			le16_to_cpu(query_1_7.flash_config_length);
+	f34->v7.payload_length = le16_to_cpu(query_1_7.payload_length);
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: f34->v7.block_size = %d\n",
+		 __func__, f34->v7.block_size);
+
+	f34->v7.off.flash_status = V7_FLASH_STATUS_OFFSET;
+	f34->v7.off.partition_id = V7_PARTITION_ID_OFFSET;
+	f34->v7.off.block_number = V7_BLOCK_NUMBER_OFFSET;
+	f34->v7.off.transfer_length = V7_TRANSFER_LENGTH_OFFSET;
+	f34->v7.off.flash_cmd = V7_COMMAND_OFFSET;
+	f34->v7.off.payload = V7_PAYLOAD_OFFSET;
+
+	f34->v7.has_display_cfg = query_1_7.partition_support[1] & HAS_DISP_CFG;
+	f34->v7.has_guest_code =
+			query_1_7.partition_support[1] & HAS_GUEST_CODE;
+
+	if (query_0 & HAS_CONFIG_ID) {
+		char f34_ctrl[CONFIG_ID_SIZE];
+		int i = 0;
+		u8 *p = f34->configuration_id;
+		*p = '\0';
+
+		ret = rmi_read_block(f34->fn->rmi_dev,
+				f34->fn->fd.control_base_addr,
+				f34_ctrl,
+				sizeof(f34_ctrl));
+		if (ret)
+			return ret;
+
+		/* Eat leading zeros */
+		while (i < sizeof(f34_ctrl) && !f34_ctrl[i])
+			i++;
+
+		for (; i < sizeof(f34_ctrl); i++)
+			p += snprintf(p, f34->configuration_id
+				      + sizeof(f34->configuration_id) - p,
+				      "%02X", f34_ctrl[i]);
+
+		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "Configuration ID: %s\n",
+			f34->configuration_id);
+	}
+
+	f34->v7.partitions = 0;
+	for (i = 0; i < sizeof(query_1_7.partition_support); i++)
+		for (j = 0; j < 8; j++)
+			if (query_1_7.partition_support[i] & (1 << j))
+				f34->v7.partitions++;
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: Supported partitions: %*ph\n",
+		__func__, sizeof(query_1_7.partition_support),
+		query_1_7.partition_support);
+
+
+	f34->v7.partition_table_bytes = f34->v7.partitions * 8 + 2;
+
+	f34->v7.read_config_buf = devm_kzalloc(&f34->fn->dev,
+			f34->v7.partition_table_bytes,
+			GFP_KERNEL);
+	if (!f34->v7.read_config_buf) {
+		f34->v7.read_config_buf_size = 0;
+		return -ENOMEM;
+	}
+
+	f34->v7.read_config_buf_size = f34->v7.partition_table_bytes;
+	ptable = f34->v7.read_config_buf;
+
+	ret = rmi_f34v7_read_f34v7_partition_table(f34);
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to read partition table\n",
+				__func__);
+		return ret;
+	}
+
+	rmi_f34v7_parse_partition_table(f34, ptable,
+					&f34->v7.blkcount, &f34->v7.phyaddr);
+
+	return 0;
+}
+
+static int rmi_f34v7_check_ui_firmware_size(struct f34_data *f34)
+{
+	u16 block_count;
+
+	block_count = f34->v7.img.ui_firmware.size / f34->v7.block_size;
+
+	if (block_count != f34->v7.blkcount.ui_firmware) {
+		dev_err(&f34->fn->dev,
+			"UI firmware size mismatch: %d != %d\n",
+			block_count, f34->v7.blkcount.ui_firmware);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_check_ui_config_size(struct f34_data *f34)
+{
+	u16 block_count;
+
+	block_count = f34->v7.img.ui_config.size / f34->v7.block_size;
+
+	if (block_count != f34->v7.blkcount.ui_config) {
+		dev_err(&f34->fn->dev, "UI config size mismatch\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_check_dp_config_size(struct f34_data *f34)
+{
+	u16 block_count;
+
+	block_count = f34->v7.img.dp_config.size / f34->v7.block_size;
+
+	if (block_count != f34->v7.blkcount.dp_config) {
+		dev_err(&f34->fn->dev, "Display config size mismatch\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_check_guest_code_size(struct f34_data *f34)
+{
+	u16 block_count;
+
+	block_count = f34->v7.img.guest_code.size / f34->v7.block_size;
+	if (block_count != f34->v7.blkcount.guest_code) {
+		dev_err(&f34->fn->dev, "Guest code size mismatch\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_check_bl_config_size(struct f34_data *f34)
+{
+	u16 block_count;
+
+	block_count = f34->v7.img.bl_config.size / f34->v7.block_size;
+
+	if (block_count != f34->v7.blkcount.bl_config) {
+		dev_err(&f34->fn->dev, "Bootloader config size mismatch\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_erase_config(struct f34_data *f34)
+{
+	int ret;
+
+	dev_info(&f34->fn->dev, "Erasing config...\n");
+
+	switch (f34->v7.config_area) {
+	case v7_UI_CONFIG_AREA:
+		ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_CONFIG);
+		if (ret < 0)
+			return ret;
+		break;
+	case v7_DP_CONFIG_AREA:
+		ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_DISP_CONFIG);
+		if (ret < 0)
+			return ret;
+		break;
+	case v7_BL_CONFIG_AREA:
+		ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_BL_CONFIG);
+		if (ret < 0)
+			return ret;
+		break;
+	}
+
+	ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS);
+	if (ret < 0)
+		return ret;
+
+	return ret;
+}
+
+static int rmi_f34v7_erase_guest_code(struct f34_data *f34)
+{
+	int ret;
+
+	dev_info(&f34->fn->dev, "Erasing guest code...\n");
+
+	ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_GUEST_CODE);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rmi_f34v7_erase_all(struct f34_data *f34)
+{
+	int ret;
+
+	dev_info(&f34->fn->dev, "Erasing firmware...\n");
+
+	ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_UI_FIRMWARE);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS);
+	if (ret < 0)
+		return ret;
+
+	f34->v7.config_area = v7_UI_CONFIG_AREA;
+	ret = rmi_f34v7_erase_config(f34);
+	if (ret < 0)
+		return ret;
+
+	if (f34->v7.has_display_cfg) {
+		f34->v7.config_area = v7_DP_CONFIG_AREA;
+		ret = rmi_f34v7_erase_config(f34);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (f34->v7.new_partition_table && f34->v7.has_guest_code) {
+		ret = rmi_f34v7_erase_guest_code(f34);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int rmi_f34v7_read_f34v7_blocks(struct f34_data *f34, u16 block_cnt,
+				       u8 command)
+{
+	int ret;
+	u8 base;
+	__le16 length;
+	u16 transfer;
+	u16 max_transfer;
+	u16 remaining = block_cnt;
+	u16 block_number = 0;
+	u16 index = 0;
+
+	base = f34->fn->fd.data_base_addr;
+
+	ret = rmi_f34v7_write_partition_id(f34, command);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_write_block(f34->fn->rmi_dev,
+			base + f34->v7.off.block_number,
+			&block_number, sizeof(block_number));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
+			__func__);
+		return ret;
+	}
+
+	max_transfer = min(f34->v7.payload_length,
+			   (u16)(PAGE_SIZE / f34->v7.block_size));
+
+	do {
+		transfer = min(remaining, max_transfer);
+		put_unaligned_le16(transfer, &length);
+
+		ret = rmi_write_block(f34->fn->rmi_dev,
+				base + f34->v7.off.transfer_length,
+				&length, sizeof(length));
+		if (ret < 0) {
+			dev_err(&f34->fn->dev,
+				"%s: Write transfer length fail (%d remaining)\n",
+				__func__, remaining);
+			return ret;
+		}
+
+		ret = rmi_f34v7_write_command(f34, command);
+		if (ret < 0)
+			return ret;
+
+		ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS);
+		if (ret < 0) {
+			dev_err(&f34->fn->dev,
+				"%s: Wait for idle failed (%d blks remaining)\n",
+				__func__, remaining);
+			return ret;
+		}
+
+		ret = rmi_read_block(f34->fn->rmi_dev,
+				base + f34->v7.off.payload,
+				&f34->v7.read_config_buf[index],
+				transfer * f34->v7.block_size);
+		if (ret < 0) {
+			dev_err(&f34->fn->dev,
+				"%s: Read block failed (%d blks remaining)\n",
+				__func__, remaining);
+			return ret;
+		}
+
+		index += (transfer * f34->v7.block_size);
+		remaining -= transfer;
+	} while (remaining);
+
+	return 0;
+}
+
+static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34,
+					const void *block_ptr, u16 block_cnt,
+					u8 command)
+{
+	int ret;
+	u8 base;
+	__le16 length;
+	u16 transfer;
+	u16 max_transfer;
+	u16 remaining = block_cnt;
+	u16 block_number = 0;
+
+	base = f34->fn->fd.data_base_addr;
+
+	ret = rmi_f34v7_write_partition_id(f34, command);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_write_block(f34->fn->rmi_dev,
+			base + f34->v7.off.block_number,
+			&block_number, sizeof(block_number));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to write block number\n",
+			__func__);
+		return ret;
+	}
+
+	if (f34->v7.payload_length > (PAGE_SIZE / f34->v7.block_size))
+		max_transfer = PAGE_SIZE / f34->v7.block_size;
+	else
+		max_transfer = f34->v7.payload_length;
+
+	do {
+		transfer = min(remaining, max_transfer);
+		put_unaligned_le16(transfer, &length);
+
+		ret = rmi_write_block(f34->fn->rmi_dev,
+				base + f34->v7.off.transfer_length,
+				&length, sizeof(length));
+		if (ret < 0) {
+			dev_err(&f34->fn->dev,
+				"%s: Write transfer length fail (%d remaining)\n",
+				__func__, remaining);
+			return ret;
+		}
+
+		ret = rmi_f34v7_write_command(f34, command);
+		if (ret < 0)
+			return ret;
+
+		ret = rmi_write_block(f34->fn->rmi_dev,
+				base + f34->v7.off.payload,
+				block_ptr, transfer * f34->v7.block_size);
+		if (ret < 0) {
+			dev_err(&f34->fn->dev,
+				"%s: Failed writing data (%d blks remaining)\n",
+				__func__, remaining);
+			return ret;
+		}
+
+		ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS);
+		if (ret < 0) {
+			dev_err(&f34->fn->dev,
+				"%s: Failed wait for idle (%d blks remaining)\n",
+				__func__, remaining);
+			return ret;
+		}
+
+		block_ptr += (transfer * f34->v7.block_size);
+		remaining -= transfer;
+	} while (remaining);
+
+	return 0;
+}
+
+static int rmi_f34v7_write_config(struct f34_data *f34)
+{
+	return rmi_f34v7_write_f34v7_blocks(f34, f34->v7.config_data,
+					    f34->v7.config_block_count,
+					    v7_CMD_WRITE_CONFIG);
+}
+
+static int rmi_f34v7_write_ui_config(struct f34_data *f34)
+{
+	f34->v7.config_area = v7_UI_CONFIG_AREA;
+	f34->v7.config_data = f34->v7.img.ui_config.data;
+	f34->v7.config_size = f34->v7.img.ui_config.size;
+	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
+
+	return rmi_f34v7_write_config(f34);
+}
+
+static int rmi_f34v7_write_dp_config(struct f34_data *f34)
+{
+	f34->v7.config_area = v7_DP_CONFIG_AREA;
+	f34->v7.config_data = f34->v7.img.dp_config.data;
+	f34->v7.config_size = f34->v7.img.dp_config.size;
+	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
+
+	return rmi_f34v7_write_config(f34);
+}
+
+static int rmi_f34v7_write_guest_code(struct f34_data *f34)
+{
+	return rmi_f34v7_write_f34v7_blocks(f34, f34->v7.img.guest_code.data,
+					    f34->v7.img.guest_code.size /
+							f34->v7.block_size,
+					    v7_CMD_WRITE_GUEST_CODE);
+}
+
+static int rmi_f34v7_write_flash_config(struct f34_data *f34)
+{
+	int ret;
+
+	f34->v7.config_area = v7_FLASH_CONFIG_AREA;
+	f34->v7.config_data = f34->v7.img.fl_config.data;
+	f34->v7.config_size = f34->v7.img.fl_config.size;
+	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
+
+	if (f34->v7.config_block_count != f34->v7.blkcount.fl_config) {
+		dev_err(&f34->fn->dev, "%s: Flash config size mismatch\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	ret = rmi_f34v7_write_command(f34, v7_CMD_ERASE_FLASH_CONFIG);
+	if (ret < 0)
+		return ret;
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+		"%s: Erase flash config command written\n", __func__);
+
+	ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_f34v7_write_config(f34);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rmi_f34v7_write_partition_table(struct f34_data *f34)
+{
+	u16 block_count;
+	int ret;
+
+	block_count = f34->v7.blkcount.bl_config;
+	f34->v7.config_area = v7_BL_CONFIG_AREA;
+	f34->v7.config_size = f34->v7.block_size * block_count;
+	devm_kfree(&f34->fn->dev, f34->v7.read_config_buf);
+	f34->v7.read_config_buf = devm_kzalloc(&f34->fn->dev,
+					       f34->v7.config_size, GFP_KERNEL);
+	if (!f34->v7.read_config_buf) {
+		f34->v7.read_config_buf_size = 0;
+		return -ENOMEM;
+	}
+
+	f34->v7.read_config_buf_size = f34->v7.config_size;
+
+	ret = rmi_f34v7_read_f34v7_blocks(f34, block_count, v7_CMD_READ_CONFIG);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_f34v7_erase_config(f34);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_f34v7_write_flash_config(f34);
+	if (ret < 0)
+		return ret;
+
+	f34->v7.config_area = v7_BL_CONFIG_AREA;
+	f34->v7.config_data = f34->v7.read_config_buf;
+	f34->v7.config_size = f34->v7.img.bl_config.size;
+	f34->v7.config_block_count = f34->v7.config_size / f34->v7.block_size;
+
+	ret = rmi_f34v7_write_config(f34);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int rmi_f34v7_write_firmware(struct f34_data *f34)
+{
+	u16 blk_count;
+
+	blk_count = f34->v7.img.ui_firmware.size / f34->v7.block_size;
+
+	return rmi_f34v7_write_f34v7_blocks(f34, f34->v7.img.ui_firmware.data,
+					    blk_count, v7_CMD_WRITE_FW);
+}
+
+static void rmi_f34v7_compare_partition_tables(struct f34_data *f34)
+{
+	if (f34->v7.phyaddr.ui_firmware != f34->v7.img.phyaddr.ui_firmware) {
+		f34->v7.new_partition_table = true;
+		return;
+	}
+
+	if (f34->v7.phyaddr.ui_config != f34->v7.img.phyaddr.ui_config) {
+		f34->v7.new_partition_table = true;
+		return;
+	}
+
+	if (f34->v7.has_display_cfg &&
+	    f34->v7.phyaddr.dp_config != f34->v7.img.phyaddr.dp_config) {
+		f34->v7.new_partition_table = true;
+		return;
+	}
+
+	if (f34->v7.has_guest_code &&
+	    f34->v7.phyaddr.guest_code != f34->v7.img.phyaddr.guest_code) {
+		f34->v7.new_partition_table = true;
+		return;
+	}
+
+	f34->v7.new_partition_table = false;
+}
+
+static void rmi_f34v7_parse_img_header_10_bl_container(struct f34_data *f34,
+						       const void *image)
+{
+	int i;
+	int num_of_containers;
+	unsigned int addr;
+	unsigned int container_id;
+	unsigned int length;
+	const void *content;
+	const struct container_descriptor *descriptor;
+
+	num_of_containers = f34->v7.img.bootloader.size / 4 - 1;
+
+	for (i = 1; i <= num_of_containers; i++) {
+		addr = get_unaligned_le32(f34->v7.img.bootloader.data + i * 4);
+		descriptor = image + addr;
+		container_id = le16_to_cpu(descriptor->container_id);
+		content = image + le32_to_cpu(descriptor->content_address);
+		length = le32_to_cpu(descriptor->content_length);
+		switch (container_id) {
+		case BL_CONFIG_CONTAINER:
+		case GLOBAL_PARAMETERS_CONTAINER:
+			f34->v7.img.bl_config.data = content;
+			f34->v7.img.bl_config.size = length;
+			break;
+		case BL_LOCKDOWN_INFO_CONTAINER:
+		case DEVICE_CONFIG_CONTAINER:
+			f34->v7.img.lockdown.data = content;
+			f34->v7.img.lockdown.size = length;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static void rmi_f34v7_parse_image_header_10(struct f34_data *f34)
+{
+	unsigned int i;
+	unsigned int num_of_containers;
+	unsigned int addr;
+	unsigned int offset;
+	unsigned int container_id;
+	unsigned int length;
+	const void *image = f34->v7.image;
+	const u8 *content;
+	const struct container_descriptor *descriptor;
+	const struct image_header_10 *header = image;
+
+	f34->v7.img.checksum = le32_to_cpu(header->checksum);
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "%s: f34->v7.img.checksum=%X\n",
+		__func__, f34->v7.img.checksum);
+
+	/* address of top level container */
+	offset = le32_to_cpu(header->top_level_container_start_addr);
+	descriptor = image + offset;
+
+	/* address of top level container content */
+	offset = le32_to_cpu(descriptor->content_address);
+	num_of_containers = le32_to_cpu(descriptor->content_length) / 4;
+
+	for (i = 0; i < num_of_containers; i++) {
+		addr = get_unaligned_le32(image + offset);
+		offset += 4;
+		descriptor = image + addr;
+		container_id = le16_to_cpu(descriptor->container_id);
+		content = image + le32_to_cpu(descriptor->content_address);
+		length = le32_to_cpu(descriptor->content_length);
+
+		rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+			"%s: container_id=%d, length=%d\n", __func__,
+			container_id, length);
+
+		switch (container_id) {
+		case UI_CONTAINER:
+		case CORE_CODE_CONTAINER:
+			f34->v7.img.ui_firmware.data = content;
+			f34->v7.img.ui_firmware.size = length;
+			break;
+		case UI_CONFIG_CONTAINER:
+		case CORE_CONFIG_CONTAINER:
+			f34->v7.img.ui_config.data = content;
+			f34->v7.img.ui_config.size = length;
+			break;
+		case BL_CONTAINER:
+			f34->v7.img.bl_version = *content;
+			f34->v7.img.bootloader.data = content;
+			f34->v7.img.bootloader.size = length;
+			rmi_f34v7_parse_img_header_10_bl_container(f34, image);
+			break;
+		case GUEST_CODE_CONTAINER:
+			f34->v7.img.contains_guest_code = true;
+			f34->v7.img.guest_code.data = content;
+			f34->v7.img.guest_code.size = length;
+			break;
+		case DISPLAY_CONFIG_CONTAINER:
+			f34->v7.img.contains_display_cfg = true;
+			f34->v7.img.dp_config.data = content;
+			f34->v7.img.dp_config.size = length;
+			break;
+		case FLASH_CONFIG_CONTAINER:
+			f34->v7.img.contains_flash_config = true;
+			f34->v7.img.fl_config.data = content;
+			f34->v7.img.fl_config.size = length;
+			break;
+		case GENERAL_INFORMATION_CONTAINER:
+			f34->v7.img.contains_firmware_id = true;
+			f34->v7.img.firmware_id =
+				get_unaligned_le32(content + 4);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static int rmi_f34v7_parse_image_info(struct f34_data *f34)
+{
+	const struct image_header_10 *header = f34->v7.image;
+
+	memset(&f34->v7.img, 0x00, sizeof(f34->v7.img));
+
+	rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev,
+		"%s: header->major_header_version = %d\n",
+		__func__, header->major_header_version);
+
+	switch (header->major_header_version) {
+	case IMAGE_HEADER_VERSION_10:
+		rmi_f34v7_parse_image_header_10(f34);
+		break;
+	default:
+		dev_err(&f34->fn->dev, "Unsupported image file format %02X\n",
+			header->major_header_version);
+		return -EINVAL;
+	}
+
+	if (!f34->v7.img.contains_flash_config) {
+		dev_err(&f34->fn->dev, "%s: No flash config in fw image\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	rmi_f34v7_parse_partition_table(f34, f34->v7.img.fl_config.data,
+			&f34->v7.img.blkcount, &f34->v7.img.phyaddr);
+
+	rmi_f34v7_compare_partition_tables(f34);
+
+	return 0;
+}
+
+int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw)
+{
+	int ret;
+
+	rmi_f34v7_read_queries_bl_version(f34);
+
+	f34->v7.image = fw->data;
+
+	ret = rmi_f34v7_parse_image_info(f34);
+	if (ret < 0)
+		goto fail;
+
+	if (!f34->v7.new_partition_table) {
+		ret = rmi_f34v7_check_ui_firmware_size(f34);
+		if (ret < 0)
+			goto fail;
+
+		ret = rmi_f34v7_check_ui_config_size(f34);
+		if (ret < 0)
+			goto fail;
+
+		if (f34->v7.has_display_cfg &&
+		    f34->v7.img.contains_display_cfg) {
+			ret = rmi_f34v7_check_dp_config_size(f34);
+			if (ret < 0)
+				goto fail;
+		}
+
+		if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) {
+			ret = rmi_f34v7_check_guest_code_size(f34);
+			if (ret < 0)
+				goto fail;
+		}
+	} else {
+		ret = rmi_f34v7_check_bl_config_size(f34);
+		if (ret < 0)
+			goto fail;
+	}
+
+	ret = rmi_f34v7_erase_all(f34);
+	if (ret < 0)
+		goto fail;
+
+	if (f34->v7.new_partition_table) {
+		ret = rmi_f34v7_write_partition_table(f34);
+		if (ret < 0)
+			goto fail;
+		dev_info(&f34->fn->dev, "%s: Partition table programmed\n",
+			 __func__);
+	}
+
+	dev_info(&f34->fn->dev, "Writing firmware (%d bytes)...\n",
+		 f34->v7.img.ui_firmware.size);
+
+	ret = rmi_f34v7_write_firmware(f34);
+	if (ret < 0)
+		goto fail;
+
+	dev_info(&f34->fn->dev, "Writing config (%d bytes)...\n",
+		 f34->v7.img.ui_config.size);
+
+	f34->v7.config_area = v7_UI_CONFIG_AREA;
+	ret = rmi_f34v7_write_ui_config(f34);
+	if (ret < 0)
+		goto fail;
+
+	if (f34->v7.has_display_cfg && f34->v7.img.contains_display_cfg) {
+		dev_info(&f34->fn->dev, "Writing display config...\n");
+
+		ret = rmi_f34v7_write_dp_config(f34);
+		if (ret < 0)
+			goto fail;
+	}
+
+	if (f34->v7.new_partition_table) {
+		if (f34->v7.has_guest_code && f34->v7.img.contains_guest_code) {
+			dev_info(&f34->fn->dev, "Writing guest code...\n");
+
+			ret = rmi_f34v7_write_guest_code(f34);
+			if (ret < 0)
+				goto fail;
+		}
+	}
+
+fail:
+	return ret;
+}
+
+static int rmi_f34v7_enter_flash_prog(struct f34_data *f34)
+{
+	int ret;
+
+	ret = rmi_f34v7_read_flash_status(f34);
+	if (ret < 0)
+		return ret;
+
+	if (f34->v7.in_bl_mode)
+		return 0;
+
+	ret = rmi_f34v7_write_command(f34, v7_CMD_ENABLE_FLASH_PROG);
+	if (ret < 0)
+		return ret;
+
+	ret = rmi_f34v7_wait_for_idle(f34, ENABLE_WAIT_MS);
+	if (ret < 0)
+		return ret;
+
+	if (!f34->v7.in_bl_mode) {
+		dev_err(&f34->fn->dev, "%s: BL mode not entered\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int rmi_f34v7_start_reflash(struct f34_data *f34, const struct firmware *fw)
+{
+	int ret = 0;
+
+	f34->v7.config_area = v7_UI_CONFIG_AREA;
+	f34->v7.image = fw->data;
+
+	ret = rmi_f34v7_parse_image_info(f34);
+	if (ret < 0)
+		goto exit;
+
+	if (!f34->v7.force_update && f34->v7.new_partition_table) {
+		dev_err(&f34->fn->dev, "%s: Partition table mismatch\n",
+				__func__);
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	dev_info(&f34->fn->dev, "Firmware image OK\n");
+
+	ret = rmi_f34v7_read_flash_status(f34);
+	if (ret < 0)
+		goto exit;
+
+	if (f34->v7.in_bl_mode) {
+		dev_info(&f34->fn->dev, "%s: Device in bootloader mode\n",
+				__func__);
+	}
+
+	rmi_f34v7_enter_flash_prog(f34);
+
+	return 0;
+
+exit:
+	return ret;
+}
+
+int rmi_f34v7_probe(struct f34_data *f34)
+{
+	int ret;
+
+	/* Read bootloader version */
+	ret = rmi_read_block(f34->fn->rmi_dev,
+			f34->fn->fd.query_base_addr + V7_BOOTLOADER_ID_OFFSET,
+			f34->bootloader_id,
+			sizeof(f34->bootloader_id));
+	if (ret < 0) {
+		dev_err(&f34->fn->dev, "%s: Failed to read bootloader ID\n",
+			__func__);
+		return ret;
+	}
+
+	if (f34->bootloader_id[1] == '5') {
+		f34->bl_version = 5;
+	} else if (f34->bootloader_id[1] == '6') {
+		f34->bl_version = 6;
+	} else if (f34->bootloader_id[1] == 7) {
+		f34->bl_version = 7;
+	} else {
+		dev_err(&f34->fn->dev, "%s: Unrecognized bootloader version\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	memset(&f34->v7.blkcount, 0x00, sizeof(f34->v7.blkcount));
+	memset(&f34->v7.phyaddr, 0x00, sizeof(f34->v7.phyaddr));
+	rmi_f34v7_read_queries(f34);
+
+	f34->v7.force_update = false;
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f54.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f54.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f54.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f54.c	2017-02-12 16:03:20.000000000 -0500
@@ -200,7 +200,7 @@ static int rmi_f54_request_report(struct
 
 	error = rmi_write(rmi_dev, fn->fd.command_base_addr, F54_GET_REPORT);
 	if (error < 0)
-		return error;
+		goto unlock;
 
 	init_completion(&f54->cmd_done);
 
@@ -209,15 +209,18 @@ static int rmi_f54_request_report(struct
 
 	queue_delayed_work(f54->workqueue, &f54->work, 0);
 
+unlock:
 	mutex_unlock(&f54->data_mutex);
 
-	return 0;
+	return error;
 }
 
 static size_t rmi_f54_get_report_size(struct f54_data *f54)
 {
-	u8 rx = f54->num_rx_electrodes ? : f54->num_rx_electrodes;
-	u8 tx = f54->num_tx_electrodes ? : f54->num_tx_electrodes;
+	struct rmi_device *rmi_dev = f54->fn->rmi_dev;
+	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
+	u8 rx = drv_data->num_rx_electrodes ? : f54->num_rx_electrodes;
+	u8 tx = drv_data->num_tx_electrodes ? : f54->num_tx_electrodes;
 	size_t size;
 
 	switch (rmi_f54_get_reptype(f54, f54->input)) {
@@ -401,6 +404,10 @@ static int rmi_f54_vidioc_enum_input(str
 
 static int rmi_f54_set_input(struct f54_data *f54, unsigned int i)
 {
+	struct rmi_device *rmi_dev = f54->fn->rmi_dev;
+	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
+	u8 rx = drv_data->num_rx_electrodes ? : f54->num_rx_electrodes;
+	u8 tx = drv_data->num_tx_electrodes ? : f54->num_tx_electrodes;
 	struct v4l2_pix_format *f = &f54->format;
 	enum rmi_f54_report_type reptype;
 	int ret;
@@ -415,8 +422,8 @@ static int rmi_f54_set_input(struct f54_
 
 	f54->input = i;
 
-	f->width = f54->num_rx_electrodes;
-	f->height = f54->num_tx_electrodes;
+	f->width = rx;
+	f->height = tx;
 	f->field = V4L2_FIELD_NONE;
 	f->colorspace = V4L2_COLORSPACE_RAW;
 	f->bytesperline = f->width * sizeof(u16);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f55.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f55.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_f55.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_f55.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012-2015 Synaptics Incorporated
+ * Copyright (C) 2016 Zodiac Inflight Innovations
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+
+#define F55_NAME		"rmi4_f55"
+
+/* F55 data offsets */
+#define F55_NUM_RX_OFFSET	0
+#define F55_NUM_TX_OFFSET	1
+#define F55_PHYS_CHAR_OFFSET	2
+
+/* Only read required query registers */
+#define F55_QUERY_LEN		3
+
+/* F55 capabilities */
+#define F55_CAP_SENSOR_ASSIGN	BIT(0)
+
+struct f55_data {
+	struct rmi_function *fn;
+
+	u8 qry[F55_QUERY_LEN];
+	u8 num_rx_electrodes;
+	u8 cfg_num_rx_electrodes;
+	u8 num_tx_electrodes;
+	u8 cfg_num_tx_electrodes;
+};
+
+static int rmi_f55_detect(struct rmi_function *fn)
+{
+	struct rmi_device *rmi_dev = fn->rmi_dev;
+	struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev);
+	struct f55_data *f55;
+	int error;
+
+	f55 = dev_get_drvdata(&fn->dev);
+
+	error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr,
+			       &f55->qry, sizeof(f55->qry));
+	if (error) {
+		dev_err(&fn->dev, "%s: Failed to query F55 properties\n",
+			__func__);
+		return error;
+	}
+
+	f55->num_rx_electrodes = f55->qry[F55_NUM_RX_OFFSET];
+	f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
+
+	f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
+	f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
+
+	drv_data->num_rx_electrodes = f55->cfg_num_rx_electrodes;
+	drv_data->num_tx_electrodes = f55->cfg_num_rx_electrodes;
+
+	if (f55->qry[F55_PHYS_CHAR_OFFSET] & F55_CAP_SENSOR_ASSIGN) {
+		int i, total;
+		u8 buf[256];
+
+		/*
+		 * Calculate the number of enabled receive and transmit
+		 * electrodes by reading F55:Ctrl1 (sensor receiver assignment)
+		 * and F55:Ctrl2 (sensor transmitter assignment). The number of
+		 * enabled electrodes is the sum of all field entries with a
+		 * value other than 0xff.
+		 */
+		error = rmi_read_block(fn->rmi_dev,
+				       fn->fd.control_base_addr + 1,
+				       buf, f55->num_rx_electrodes);
+		if (!error) {
+			total = 0;
+			for (i = 0; i < f55->num_rx_electrodes; i++) {
+				if (buf[i] != 0xff)
+					total++;
+			}
+			f55->cfg_num_rx_electrodes = total;
+			drv_data->num_rx_electrodes = total;
+		}
+
+		error = rmi_read_block(fn->rmi_dev,
+				       fn->fd.control_base_addr + 2,
+				       buf, f55->num_tx_electrodes);
+		if (!error) {
+			total = 0;
+			for (i = 0; i < f55->num_tx_electrodes; i++) {
+				if (buf[i] != 0xff)
+					total++;
+			}
+			f55->cfg_num_tx_electrodes = total;
+			drv_data->num_tx_electrodes = total;
+		}
+	}
+
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_rx_electrodes: %d (raw %d)\n",
+		f55->cfg_num_rx_electrodes, f55->num_rx_electrodes);
+	rmi_dbg(RMI_DEBUG_FN, &fn->dev, "F55 num_tx_electrodes: %d (raw %d)\n",
+		f55->cfg_num_tx_electrodes, f55->num_tx_electrodes);
+
+	return 0;
+}
+
+static int rmi_f55_probe(struct rmi_function *fn)
+{
+	struct f55_data *f55;
+
+	f55 = devm_kzalloc(&fn->dev, sizeof(struct f55_data), GFP_KERNEL);
+	if (!f55)
+		return -ENOMEM;
+
+	f55->fn = fn;
+	dev_set_drvdata(&fn->dev, f55);
+
+	return rmi_f55_detect(fn);
+}
+
+struct rmi_function_handler rmi_f55_handler = {
+	.driver = {
+		.name = F55_NAME,
+	},
+	.func = 0x55,
+	.probe = rmi_f55_probe,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_i2c.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_i2c.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,6 @@
 
 #include <linux/i2c.h>
 #include <linux/rmi.h>
-#include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/regulator/consumer.h>
@@ -35,8 +34,6 @@ struct rmi_i2c_xport {
 	struct mutex page_mutex;
 	int page;
 
-	int irq;
-
 	u8 *tx_buf;
 	size_t tx_buf_size;
 
@@ -177,42 +174,6 @@ static const struct rmi_transport_ops rm
 	.read_block	= rmi_i2c_read_block,
 };
 
-static irqreturn_t rmi_i2c_irq(int irq, void *dev_id)
-{
-	struct rmi_i2c_xport *rmi_i2c = dev_id;
-	struct rmi_device *rmi_dev = rmi_i2c->xport.rmi_dev;
-	int ret;
-
-	ret = rmi_process_interrupt_requests(rmi_dev);
-	if (ret)
-		rmi_dbg(RMI_DEBUG_XPORT, &rmi_dev->dev,
-			"Failed to process interrupt request: %d\n", ret);
-
-	return IRQ_HANDLED;
-}
-
-static int rmi_i2c_init_irq(struct i2c_client *client)
-{
-	struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);
-	int irq_flags = irqd_get_trigger_type(irq_get_irq_data(rmi_i2c->irq));
-	int ret;
-
-	if (!irq_flags)
-		irq_flags = IRQF_TRIGGER_LOW;
-
-	ret = devm_request_threaded_irq(&client->dev, rmi_i2c->irq, NULL,
-			rmi_i2c_irq, irq_flags | IRQF_ONESHOT, client->name,
-			rmi_i2c);
-	if (ret < 0) {
-		dev_warn(&client->dev, "Failed to register interrupt %d\n",
-			rmi_i2c->irq);
-
-		return ret;
-	}
-
-	return 0;
-}
-
 #ifdef CONFIG_OF
 static const struct of_device_id rmi_i2c_of_match[] = {
 	{ .compatible = "syna,rmi4-i2c" },
@@ -255,8 +216,7 @@ static int rmi_i2c_probe(struct i2c_clie
 	if (!client->dev.of_node && client_pdata)
 		*pdata = *client_pdata;
 
-	if (client->irq > 0)
-		rmi_i2c->irq = client->irq;
+	pdata->irq = client->irq;
 
 	rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s.\n",
 			dev_name(&client->dev));
@@ -321,10 +281,6 @@ static int rmi_i2c_probe(struct i2c_clie
 	if (retval)
 		return retval;
 
-	retval = rmi_i2c_init_irq(client);
-	if (retval < 0)
-		return retval;
-
 	dev_info(&client->dev, "registered rmi i2c driver at %#04x.\n",
 			client->addr);
 	return 0;
@@ -337,18 +293,10 @@ static int rmi_i2c_suspend(struct device
 	struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);
 	int ret;
 
-	ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev);
+	ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev, true);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
-	disable_irq(rmi_i2c->irq);
-	if (device_may_wakeup(&client->dev)) {
-		ret = enable_irq_wake(rmi_i2c->irq);
-		if (!ret)
-			dev_warn(dev, "Failed to enable irq for wake: %d\n",
-				ret);
-	}
-
 	regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
 			       rmi_i2c->supplies);
 
@@ -368,15 +316,7 @@ static int rmi_i2c_resume(struct device
 
 	msleep(rmi_i2c->startup_delay);
 
-	enable_irq(rmi_i2c->irq);
-	if (device_may_wakeup(&client->dev)) {
-		ret = disable_irq_wake(rmi_i2c->irq);
-		if (!ret)
-			dev_warn(dev, "Failed to disable irq for wake: %d\n",
-				ret);
-	}
-
-	ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev);
+	ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev, true);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
@@ -391,12 +331,10 @@ static int rmi_i2c_runtime_suspend(struc
 	struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client);
 	int ret;
 
-	ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev);
+	ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev, false);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
-	disable_irq(rmi_i2c->irq);
-
 	regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies),
 			       rmi_i2c->supplies);
 
@@ -416,9 +354,7 @@ static int rmi_i2c_runtime_resume(struct
 
 	msleep(rmi_i2c->startup_delay);
 
-	enable_irq(rmi_i2c->irq);
-
-	ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev);
+	ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev, false);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_smbus.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_smbus.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_smbus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_smbus.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2015 - 2016 Red Hat, Inc
+ * Copyright (c) 2011, 2012 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it 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/delay.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/kconfig.h>
+#include <linux/lockdep.h>
+#include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/rmi.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+
+#define SMB_PROTOCOL_VERSION_ADDRESS	0xfd
+#define SMB_MAX_COUNT			32
+#define RMI_SMB2_MAP_SIZE		8 /* 8 entry of 4 bytes each */
+#define RMI_SMB2_MAP_FLAGS_WE		0x01
+
+struct mapping_table_entry {
+	__le16 rmiaddr;
+	u8 readcount;
+	u8 flags;
+};
+
+struct rmi_smb_xport {
+	struct rmi_transport_dev xport;
+	struct i2c_client *client;
+
+	struct mutex page_mutex;
+	int page;
+	u8 table_index;
+	struct mutex mappingtable_mutex;
+	struct mapping_table_entry mapping_table[RMI_SMB2_MAP_SIZE];
+};
+
+static int rmi_smb_get_version(struct rmi_smb_xport *rmi_smb)
+{
+	struct i2c_client *client = rmi_smb->client;
+	int retval;
+
+	/* Check if for SMBus new version device by reading version byte. */
+	retval = i2c_smbus_read_byte_data(client, SMB_PROTOCOL_VERSION_ADDRESS);
+	if (retval < 0) {
+		dev_err(&client->dev, "failed to get SMBus version number!\n");
+		return retval;
+	}
+	return retval + 1;
+}
+
+/* SMB block write - wrapper over ic2_smb_write_block */
+static int smb_block_write(struct rmi_transport_dev *xport,
+			      u8 commandcode, const void *buf, size_t len)
+{
+	struct rmi_smb_xport *rmi_smb =
+		container_of(xport, struct rmi_smb_xport, xport);
+	struct i2c_client *client = rmi_smb->client;
+	int retval;
+
+	retval = i2c_smbus_write_block_data(client, commandcode, len, buf);
+
+	rmi_dbg(RMI_DEBUG_XPORT, &client->dev,
+		"wrote %zd bytes at %#04x: %d (%*ph)\n",
+		len, commandcode, retval, (int)len, buf);
+
+	return retval;
+}
+
+/*
+ * The function to get command code for smbus operations and keeps
+ * records to the driver mapping table
+ */
+static int rmi_smb_get_command_code(struct rmi_transport_dev *xport,
+		u16 rmiaddr, int bytecount, bool isread, u8 *commandcode)
+{
+	struct rmi_smb_xport *rmi_smb =
+		container_of(xport, struct rmi_smb_xport, xport);
+	int i;
+	int retval;
+	struct mapping_table_entry mapping_data[1];
+
+	mutex_lock(&rmi_smb->mappingtable_mutex);
+	for (i = 0; i < RMI_SMB2_MAP_SIZE; i++) {
+		if (rmi_smb->mapping_table[i].rmiaddr == rmiaddr) {
+			if (isread) {
+				if (rmi_smb->mapping_table[i].readcount
+							== bytecount) {
+					*commandcode = i;
+					retval = 0;
+					goto exit;
+				}
+			} else {
+				if (rmi_smb->mapping_table[i].flags &
+							RMI_SMB2_MAP_FLAGS_WE) {
+					*commandcode = i;
+					retval = 0;
+					goto exit;
+				}
+			}
+		}
+	}
+	i = rmi_smb->table_index;
+	rmi_smb->table_index = (i + 1) % RMI_SMB2_MAP_SIZE;
+
+	/* constructs mapping table data entry. 4 bytes each entry */
+	memset(mapping_data, 0, sizeof(mapping_data));
+
+	mapping_data[0].rmiaddr = cpu_to_le16(rmiaddr);
+	mapping_data[0].readcount = bytecount;
+	mapping_data[0].flags = !isread ? RMI_SMB2_MAP_FLAGS_WE : 0;
+
+	retval = smb_block_write(xport, i + 0x80, mapping_data,
+				 sizeof(mapping_data));
+
+	if (retval < 0) {
+		/*
+		 * if not written to device mapping table
+		 * clear the driver mapping table records
+		 */
+		rmi_smb->mapping_table[i].rmiaddr = 0x0000;
+		rmi_smb->mapping_table[i].readcount = 0;
+		rmi_smb->mapping_table[i].flags = 0;
+		goto exit;
+	}
+	/* save to the driver level mapping table */
+	rmi_smb->mapping_table[i].rmiaddr = rmiaddr;
+	rmi_smb->mapping_table[i].readcount = bytecount;
+	rmi_smb->mapping_table[i].flags = !isread ? RMI_SMB2_MAP_FLAGS_WE : 0;
+	*commandcode = i;
+
+exit:
+	mutex_unlock(&rmi_smb->mappingtable_mutex);
+
+	return retval;
+}
+
+static int rmi_smb_write_block(struct rmi_transport_dev *xport, u16 rmiaddr,
+				const void *databuff, size_t len)
+{
+	int retval = 0;
+	u8 commandcode;
+	struct rmi_smb_xport *rmi_smb =
+		container_of(xport, struct rmi_smb_xport, xport);
+	int cur_len = (int)len;
+
+	mutex_lock(&rmi_smb->page_mutex);
+
+	while (cur_len > 0) {
+		/*
+		 * break into 32 bytes chunks to write get command code
+		 */
+		int block_len = min_t(int, len, SMB_MAX_COUNT);
+
+		retval = rmi_smb_get_command_code(xport, rmiaddr, block_len,
+						  false, &commandcode);
+		if (retval < 0)
+			goto exit;
+
+		retval = smb_block_write(xport, commandcode,
+					 databuff, block_len);
+		if (retval < 0)
+			goto exit;
+
+		/* prepare to write next block of bytes */
+		cur_len -= SMB_MAX_COUNT;
+		databuff += SMB_MAX_COUNT;
+		rmiaddr += SMB_MAX_COUNT;
+	}
+exit:
+	mutex_unlock(&rmi_smb->page_mutex);
+	return retval;
+}
+
+/* SMB block read - wrapper over ic2_smb_read_block */
+static int smb_block_read(struct rmi_transport_dev *xport,
+			     u8 commandcode, void *buf, size_t len)
+{
+	struct rmi_smb_xport *rmi_smb =
+		container_of(xport, struct rmi_smb_xport, xport);
+	struct i2c_client *client = rmi_smb->client;
+	int retval;
+
+	retval = i2c_smbus_read_block_data(client, commandcode, buf);
+	if (retval < 0)
+		return retval;
+
+	return retval;
+}
+
+static int rmi_smb_read_block(struct rmi_transport_dev *xport, u16 rmiaddr,
+			      void *databuff, size_t len)
+{
+	struct rmi_smb_xport *rmi_smb =
+		container_of(xport, struct rmi_smb_xport, xport);
+	int retval;
+	u8 commandcode;
+	int cur_len = (int)len;
+
+	mutex_lock(&rmi_smb->page_mutex);
+	memset(databuff, 0, len);
+
+	while (cur_len > 0) {
+		/* break into 32 bytes chunks to write get command code */
+		int block_len =  min_t(int, cur_len, SMB_MAX_COUNT);
+
+		retval = rmi_smb_get_command_code(xport, rmiaddr, block_len,
+						  true, &commandcode);
+		if (retval < 0)
+			goto exit;
+
+		retval = smb_block_read(xport, commandcode,
+					databuff, block_len);
+		if (retval < 0)
+			goto exit;
+
+		/* prepare to read next block of bytes */
+		cur_len -= SMB_MAX_COUNT;
+		databuff += SMB_MAX_COUNT;
+		rmiaddr += SMB_MAX_COUNT;
+	}
+
+	retval = 0;
+
+exit:
+	mutex_unlock(&rmi_smb->page_mutex);
+	return retval;
+}
+
+static void rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb)
+{
+	/* the mapping table has been flushed, discard the current one */
+	mutex_lock(&rmi_smb->mappingtable_mutex);
+	memset(rmi_smb->mapping_table, 0, sizeof(rmi_smb->mapping_table));
+	mutex_unlock(&rmi_smb->mappingtable_mutex);
+}
+
+static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb)
+{
+	int retval;
+
+	/* we need to get the smbus version to activate the touchpad */
+	retval = rmi_smb_get_version(rmi_smb);
+	if (retval < 0)
+		return retval;
+
+	return 0;
+}
+
+static int rmi_smb_reset(struct rmi_transport_dev *xport, u16 reset_addr)
+{
+	struct rmi_smb_xport *rmi_smb =
+		container_of(xport, struct rmi_smb_xport, xport);
+
+	rmi_smb_clear_state(rmi_smb);
+
+	/*
+	 * we do not call the actual reset command, it has to be handled in
+	 * PS/2 or there will be races between PS/2 and SMBus.
+	 * PS/2 should ensure that a psmouse_reset is called before
+	 * intializing the device and after it has been removed to be in a known
+	 * state.
+	 */
+	return rmi_smb_enable_smbus_mode(rmi_smb);
+}
+
+static const struct rmi_transport_ops rmi_smb_ops = {
+	.write_block	= rmi_smb_write_block,
+	.read_block	= rmi_smb_read_block,
+	.reset		= rmi_smb_reset,
+};
+
+static int rmi_smb_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev);
+	struct rmi_smb_xport *rmi_smb;
+	int retval;
+	int smbus_version;
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+				     I2C_FUNC_SMBUS_HOST_NOTIFY)) {
+		dev_err(&client->dev,
+			"adapter does not support required functionality.\n");
+		return -ENODEV;
+	}
+
+	if (client->irq <= 0) {
+		dev_err(&client->dev, "no IRQ provided, giving up.\n");
+		return client->irq ? client->irq : -ENODEV;
+	}
+
+	rmi_smb = devm_kzalloc(&client->dev, sizeof(struct rmi_smb_xport),
+				GFP_KERNEL);
+	if (!rmi_smb)
+		return -ENOMEM;
+
+	if (!pdata) {
+		dev_err(&client->dev, "no platform data, aborting\n");
+		return -ENOMEM;
+	}
+
+	rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s.\n",
+		dev_name(&client->dev));
+
+	rmi_smb->client = client;
+	mutex_init(&rmi_smb->page_mutex);
+	mutex_init(&rmi_smb->mappingtable_mutex);
+
+	rmi_smb->xport.dev = &client->dev;
+	rmi_smb->xport.pdata = *pdata;
+	rmi_smb->xport.pdata.irq = client->irq;
+	rmi_smb->xport.proto_name = "smb2";
+	rmi_smb->xport.ops = &rmi_smb_ops;
+
+	retval = rmi_smb_get_version(rmi_smb);
+	if (retval < 0)
+		return retval;
+
+	smbus_version = retval;
+	rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d",
+		smbus_version);
+
+	if (smbus_version != 2) {
+		dev_err(&client->dev, "Unrecognized SMB version %d.\n",
+				smbus_version);
+		return -ENODEV;
+	}
+
+	i2c_set_clientdata(client, rmi_smb);
+
+	retval = rmi_register_transport_device(&rmi_smb->xport);
+	if (retval) {
+		dev_err(&client->dev, "Failed to register transport driver at 0x%.2X.\n",
+			client->addr);
+		i2c_set_clientdata(client, NULL);
+		return retval;
+	}
+
+	dev_info(&client->dev, "registered rmi smb driver at %#04x.\n",
+			client->addr);
+	return 0;
+
+}
+
+static int rmi_smb_remove(struct i2c_client *client)
+{
+	struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
+
+	rmi_unregister_transport_device(&rmi_smb->xport);
+
+	return 0;
+}
+
+static int __maybe_unused rmi_smb_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
+	int ret;
+
+	ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, true);
+	if (ret)
+		dev_warn(dev, "Failed to suspend device: %d\n", ret);
+
+	return ret;
+}
+
+static int __maybe_unused rmi_smb_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
+	int ret;
+
+	ret = rmi_driver_suspend(rmi_smb->xport.rmi_dev, false);
+	if (ret)
+		dev_warn(dev, "Failed to suspend device: %d\n", ret);
+
+	return ret;
+}
+
+static int __maybe_unused rmi_smb_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
+	struct rmi_device *rmi_dev = rmi_smb->xport.rmi_dev;
+	int ret;
+
+	rmi_smb_reset(&rmi_smb->xport, 0);
+
+	rmi_reset(rmi_dev);
+
+	ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, true);
+	if (ret)
+		dev_warn(dev, "Failed to resume device: %d\n", ret);
+
+	return 0;
+}
+
+static int __maybe_unused rmi_smb_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct rmi_smb_xport *rmi_smb = i2c_get_clientdata(client);
+	int ret;
+
+	ret = rmi_driver_resume(rmi_smb->xport.rmi_dev, false);
+	if (ret)
+		dev_warn(dev, "Failed to resume device: %d\n", ret);
+
+	return 0;
+}
+
+static const struct dev_pm_ops rmi_smb_pm = {
+	SET_SYSTEM_SLEEP_PM_OPS(rmi_smb_suspend, rmi_smb_resume)
+	SET_RUNTIME_PM_OPS(rmi_smb_runtime_suspend, rmi_smb_runtime_resume,
+			   NULL)
+};
+
+static const struct i2c_device_id rmi_id[] = {
+	{ "rmi4_smbus", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, rmi_id);
+
+static struct i2c_driver rmi_smb_driver = {
+	.driver = {
+		.name	= "rmi4_smbus",
+		.pm	= &rmi_smb_pm,
+	},
+	.id_table	= rmi_id,
+	.probe		= rmi_smb_probe,
+	.remove		= rmi_smb_remove,
+};
+
+module_i2c_driver(rmi_smb_driver);
+
+MODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>");
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@redhat.com>");
+MODULE_DESCRIPTION("RMI4 SMBus driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/rmi4/rmi_spi.c linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_spi.c
--- linux-libre-4.9-gnu/drivers/input/rmi4/rmi_spi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/rmi4/rmi_spi.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,6 @@
 #include <linux/rmi.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/irq.h>
 #include <linux/of.h>
 #include "rmi_driver.h"
 
@@ -44,8 +43,6 @@ struct rmi_spi_xport {
 	struct mutex page_mutex;
 	int page;
 
-	int irq;
-
 	u8 *rx_buf;
 	u8 *tx_buf;
 	int xfer_buf_size;
@@ -326,41 +323,6 @@ static const struct rmi_transport_ops rm
 	.read_block	= rmi_spi_read_block,
 };
 
-static irqreturn_t rmi_spi_irq(int irq, void *dev_id)
-{
-	struct rmi_spi_xport *rmi_spi = dev_id;
-	struct rmi_device *rmi_dev = rmi_spi->xport.rmi_dev;
-	int ret;
-
-	ret = rmi_process_interrupt_requests(rmi_dev);
-	if (ret)
-		rmi_dbg(RMI_DEBUG_XPORT, &rmi_dev->dev,
-			"Failed to process interrupt request: %d\n", ret);
-
-	return IRQ_HANDLED;
-}
-
-static int rmi_spi_init_irq(struct spi_device *spi)
-{
-	struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
-	int irq_flags = irqd_get_trigger_type(irq_get_irq_data(rmi_spi->irq));
-	int ret;
-
-	if (!irq_flags)
-		irq_flags = IRQF_TRIGGER_LOW;
-
-	ret = devm_request_threaded_irq(&spi->dev, rmi_spi->irq, NULL,
-			rmi_spi_irq, irq_flags | IRQF_ONESHOT,
-			dev_name(&spi->dev), rmi_spi);
-	if (ret < 0) {
-		dev_warn(&spi->dev, "Failed to register interrupt %d\n",
-			rmi_spi->irq);
-		return ret;
-	}
-
-	return 0;
-}
-
 #ifdef CONFIG_OF
 static int rmi_spi_of_probe(struct spi_device *spi,
 			struct rmi_device_platform_data *pdata)
@@ -440,8 +402,7 @@ static int rmi_spi_probe(struct spi_devi
 		return retval;
 	}
 
-	if (spi->irq > 0)
-		rmi_spi->irq = spi->irq;
+	pdata->irq = spi->irq;
 
 	rmi_spi->spi = spi;
 	mutex_init(&rmi_spi->page_mutex);
@@ -477,10 +438,6 @@ static int rmi_spi_probe(struct spi_devi
 	if (retval)
 		return retval;
 
-	retval = rmi_spi_init_irq(spi);
-	if (retval < 0)
-		return retval;
-
 	dev_info(&spi->dev, "registered RMI SPI driver\n");
 	return 0;
 }
@@ -492,17 +449,10 @@ static int rmi_spi_suspend(struct device
 	struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
 	int ret;
 
-	ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev);
+	ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev, true);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
-	disable_irq(rmi_spi->irq);
-	if (device_may_wakeup(&spi->dev)) {
-		ret = enable_irq_wake(rmi_spi->irq);
-		if (!ret)
-			dev_warn(dev, "Failed to enable irq for wake: %d\n",
-				ret);
-	}
 	return ret;
 }
 
@@ -512,15 +462,7 @@ static int rmi_spi_resume(struct device
 	struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
 	int ret;
 
-	enable_irq(rmi_spi->irq);
-	if (device_may_wakeup(&spi->dev)) {
-		ret = disable_irq_wake(rmi_spi->irq);
-		if (!ret)
-			dev_warn(dev, "Failed to disable irq for wake: %d\n",
-				ret);
-	}
-
-	ret = rmi_driver_resume(rmi_spi->xport.rmi_dev);
+	ret = rmi_driver_resume(rmi_spi->xport.rmi_dev, true);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
@@ -535,12 +477,10 @@ static int rmi_spi_runtime_suspend(struc
 	struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
 	int ret;
 
-	ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev);
+	ret = rmi_driver_suspend(rmi_spi->xport.rmi_dev, false);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
-	disable_irq(rmi_spi->irq);
-
 	return 0;
 }
 
@@ -550,9 +490,7 @@ static int rmi_spi_runtime_resume(struct
 	struct rmi_spi_xport *rmi_spi = spi_get_drvdata(spi);
 	int ret;
 
-	enable_irq(rmi_spi->irq);
-
-	ret = rmi_driver_resume(rmi_spi->xport.rmi_dev);
+	ret = rmi_driver_resume(rmi_spi->xport.rmi_dev, false);
 	if (ret)
 		dev_warn(dev, "Failed to resume device: %d\n", ret);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/serio/hp_sdc.c linux-libre-4.10-rc8-gnu/drivers/input/serio/hp_sdc.c
--- linux-libre-4.9-gnu/drivers/input/serio/hp_sdc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/serio/hp_sdc.c	2017-02-12 16:03:20.000000000 -0500
@@ -79,7 +79,7 @@
 # define sdc_readb(p)		gsc_readb(p)
 # define sdc_writeb(v,p)	gsc_writeb((v),(p))
 #elif defined(__mc68000__)
-# include <asm/uaccess.h>
+#include <linux/uaccess.h>
 # define sdc_readb(p)		in_8(p)
 # define sdc_writeb(v,p)	out_8((p),(v))
 #else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/serio/i8042.c linux-libre-4.10-rc8-gnu/drivers/input/serio/i8042.c
--- linux-libre-4.9-gnu/drivers/input/serio/i8042.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/serio/i8042.c	2017-02-12 16:03:20.000000000 -0500
@@ -387,7 +387,7 @@ static int i8042_aux_write(struct serio
 
 
 /*
- * i8042_aux_close attempts to clear AUX or KBD port state by disabling
+ * i8042_port_close attempts to clear AUX or KBD port state by disabling
  * and then re-enabling it.
  */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/serio/i8042-x86ia64io.h linux-libre-4.10-rc8-gnu/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-4.9-gnu/drivers/input/serio/i8042-x86ia64io.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/serio/i8042-x86ia64io.h	2017-02-12 16:03:20.000000000 -0500
@@ -211,6 +211,12 @@ static const struct dmi_system_id __init
 			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
 		},
 	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
+		},
+	},
 	{ }
 };
 
@@ -517,79 +523,7 @@ static const struct dmi_system_id i8042_
 	{
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "A455LD"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "K401LB"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "K501LB"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "K501LX"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "R409L"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "V502LX"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X302LA"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X450LD"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X455LAB"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X455LDB"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X455LF"),
-		},
-	},
-	{
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Z450LA"),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
 		},
 	},
 	{ }
@@ -1055,7 +989,11 @@ static int __init i8042_pnp_init(void)
 #if defined(__ia64__)
 		return -ENODEV;
 #else
-		pr_info("PNP: No PS/2 controller found. Probing ports directly.\n");
+		pr_info("PNP: No PS/2 controller found.\n");
+		if (x86_platform.legacy.i8042 !=
+				X86_LEGACY_I8042_EXPECTED_PRESENT)
+			return -ENODEV;
+		pr_info("Probing ports directly.\n");
 		return 0;
 #endif
 	}
@@ -1131,10 +1069,10 @@ static int __init i8042_pnp_init(void)
 	return 0;
 }
 
-#else
+#else  /* !CONFIG_PNP */
 static inline int i8042_pnp_init(void) { return 0; }
 static inline void i8042_pnp_exit(void) { }
-#endif
+#endif /* CONFIG_PNP */
 
 static int __init i8042_platform_init(void)
 {
@@ -1142,8 +1080,8 @@ static int __init i8042_platform_init(vo
 
 #ifdef CONFIG_X86
 	u8 a20_on = 0xdf;
-	/* Just return if pre-detection shows no i8042 controller exist */
-	if (!x86_platform.i8042_detect())
+	/* Just return if platform does not have i8042 controller */
+	if (x86_platform.legacy.i8042 == X86_LEGACY_I8042_PLATFORM_ABSENT)
 		return -ENODEV;
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/serio/q40kbd.c linux-libre-4.10-rc8-gnu/drivers/input/serio/q40kbd.c
--- linux-libre-4.9-gnu/drivers/input/serio/q40kbd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/serio/q40kbd.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 #include <linux/slab.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/q40_master.h>
 #include <asm/irq.h>
 #include <asm/q40ints.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/serio/serport.c linux-libre-4.10-rc8-gnu/drivers/input/serio/serport.c
--- linux-libre-4.9-gnu/drivers/input/serio/serport.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/serio/serport.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
  * the Free Software Foundation.
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/tablet/aiptek.c linux-libre-4.10-rc8-gnu/drivers/input/tablet/aiptek.c
--- linux-libre-4.9-gnu/drivers/input/tablet/aiptek.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/tablet/aiptek.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/usb/input.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/tablet/gtco.c linux-libre-4.10-rc8-gnu/drivers/input/tablet/gtco.c
--- linux-libre-4.9-gnu/drivers/input/tablet/gtco.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/tablet/gtco.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ Scott Hill shill@gtcocalcomp.com
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/usb.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 #include <linux/bitops.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/touchscreen/elants_i2c.c linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/elants_i2c.c
--- linux-libre-4.9-gnu/drivers/input/touchscreen/elants_i2c.c	2016-12-11 17:58:04.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/elants_i2c.c	2017-02-12 17:50:04.000000000 -0500
@@ -914,9 +914,9 @@ static irqreturn_t elants_i2c_irq(int ir
 
 		case QUEUE_HEADER_NORMAL:
 			report_count = ts->buf[FW_HDR_COUNT];
-			if (report_count > 3) {
+			if (report_count == 0 || report_count > 3) {
 				dev_err(&client->dev,
-					"too large report count: %*ph\n",
+					"bad report count: %*ph\n",
 					HEADER_SIZE, ts->buf);
 				break;
 			}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/touchscreen/fsl-imx25-tcq.c linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/fsl-imx25-tcq.c
--- linux-libre-4.9-gnu/drivers/input/touchscreen/fsl-imx25-tcq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/fsl-imx25-tcq.c	2017-02-12 16:03:20.000000000 -0500
@@ -55,6 +55,7 @@ static const struct of_device_id mx25_tc
 	{ .compatible = "fsl,imx25-tcq", },
 	{ /* Sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, mx25_tcq_ids);
 
 #define TSC_4WIRE_PRE_INDEX 0
 #define TSC_4WIRE_X_INDEX 1
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/touchscreen/imx6ul_tsc.c linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/imx6ul_tsc.c
--- linux-libre-4.9-gnu/drivers/input/touchscreen/imx6ul_tsc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/imx6ul_tsc.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,17 +21,25 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/log2.h>
 
 /* ADC configuration registers field define */
 #define ADC_AIEN		(0x1 << 7)
 #define ADC_CONV_DISABLE	0x1F
+#define ADC_AVGE		(0x1 << 5)
 #define ADC_CAL			(0x1 << 7)
 #define ADC_CALF		0x2
 #define ADC_12BIT_MODE		(0x2 << 2)
+#define ADC_CONV_MODE_MASK	(0x3 << 2)
 #define ADC_IPG_CLK		0x00
+#define ADC_INPUT_CLK_MASK	0x3
 #define ADC_CLK_DIV_8		(0x03 << 5)
+#define ADC_CLK_DIV_MASK	(0x3 << 5)
 #define ADC_SHORT_SAMPLE_MODE	(0x0 << 4)
+#define ADC_SAMPLE_MODE_MASK	(0x1 << 4)
 #define ADC_HARDWARE_TRIGGER	(0x1 << 13)
+#define ADC_AVGS_SHIFT		14
+#define ADC_AVGS_MASK		(0x3 << 14)
 #define SELECT_CHANNEL_4	0x04
 #define SELECT_CHANNEL_1	0x01
 #define DISABLE_CONVERSION_INT	(0x0 << 7)
@@ -84,8 +92,10 @@ struct imx6ul_tsc {
 	struct clk *adc_clk;
 	struct gpio_desc *xnur_gpio;
 
-	int measure_delay_time;
-	int pre_charge_time;
+	u32 measure_delay_time;
+	u32 pre_charge_time;
+	bool average_enable;
+	u32 average_select;
 
 	struct completion completion;
 };
@@ -96,17 +106,23 @@ struct imx6ul_tsc {
  */
 static int imx6ul_adc_init(struct imx6ul_tsc *tsc)
 {
-	int adc_hc = 0;
-	int adc_gc;
-	int adc_gs;
-	int adc_cfg;
-	int timeout;
+	u32 adc_hc = 0;
+	u32 adc_gc;
+	u32 adc_gs;
+	u32 adc_cfg;
+	unsigned long timeout;
 
 	reinit_completion(&tsc->completion);
 
 	adc_cfg = readl(tsc->adc_regs + REG_ADC_CFG);
+	adc_cfg &= ~(ADC_CONV_MODE_MASK | ADC_INPUT_CLK_MASK);
 	adc_cfg |= ADC_12BIT_MODE | ADC_IPG_CLK;
+	adc_cfg &= ~(ADC_CLK_DIV_MASK | ADC_SAMPLE_MODE_MASK);
 	adc_cfg |= ADC_CLK_DIV_8 | ADC_SHORT_SAMPLE_MODE;
+	if (tsc->average_enable) {
+		adc_cfg &= ~ADC_AVGS_MASK;
+		adc_cfg |= (tsc->average_select) << ADC_AVGS_SHIFT;
+	}
 	adc_cfg &= ~ADC_HARDWARE_TRIGGER;
 	writel(adc_cfg, tsc->adc_regs + REG_ADC_CFG);
 
@@ -118,6 +134,8 @@ static int imx6ul_adc_init(struct imx6ul
 	/* start ADC calibration */
 	adc_gc = readl(tsc->adc_regs + REG_ADC_GC);
 	adc_gc |= ADC_CAL;
+	if (tsc->average_enable)
+		adc_gc |= ADC_AVGE;
 	writel(adc_gc, tsc->adc_regs + REG_ADC_GC);
 
 	timeout = wait_for_completion_timeout
@@ -148,7 +166,7 @@ static int imx6ul_adc_init(struct imx6ul
  */
 static void imx6ul_tsc_channel_config(struct imx6ul_tsc *tsc)
 {
-	int adc_hc0, adc_hc1, adc_hc2, adc_hc3, adc_hc4;
+	u32 adc_hc0, adc_hc1, adc_hc2, adc_hc3, adc_hc4;
 
 	adc_hc0 = DISABLE_CONVERSION_INT;
 	writel(adc_hc0, tsc->adc_regs + REG_ADC_HC0);
@@ -173,8 +191,8 @@ static void imx6ul_tsc_channel_config(st
  */
 static void imx6ul_tsc_set(struct imx6ul_tsc *tsc)
 {
-	int basic_setting = 0;
-	int start;
+	u32 basic_setting = 0;
+	u32 start;
 
 	basic_setting |= tsc->measure_delay_time << 8;
 	basic_setting |= DETECT_4_WIRE_MODE | AUTO_MEASURE;
@@ -209,8 +227,8 @@ static int imx6ul_tsc_init(struct imx6ul
 
 static void imx6ul_tsc_disable(struct imx6ul_tsc *tsc)
 {
-	int tsc_flow;
-	int adc_cfg;
+	u32 tsc_flow;
+	u32 adc_cfg;
 
 	/* TSC controller enters to idle status */
 	tsc_flow = readl(tsc->tsc_regs + REG_TSC_FLOW_CONTROL);
@@ -227,8 +245,8 @@ static void imx6ul_tsc_disable(struct im
 static bool tsc_wait_detect_mode(struct imx6ul_tsc *tsc)
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(2);
-	int state_machine;
-	int debug_mode2;
+	u32 state_machine;
+	u32 debug_mode2;
 
 	do {
 		if (time_after(jiffies, timeout))
@@ -246,10 +264,10 @@ static bool tsc_wait_detect_mode(struct
 static irqreturn_t tsc_irq_fn(int irq, void *dev_id)
 {
 	struct imx6ul_tsc *tsc = dev_id;
-	int status;
-	int value;
-	int x, y;
-	int start;
+	u32 status;
+	u32 value;
+	u32 x, y;
+	u32 start;
 
 	status = readl(tsc->tsc_regs + REG_TSC_INT_STATUS);
 
@@ -289,8 +307,8 @@ static irqreturn_t tsc_irq_fn(int irq, v
 static irqreturn_t adc_irq_fn(int irq, void *dev_id)
 {
 	struct imx6ul_tsc *tsc = dev_id;
-	int coco;
-	int value;
+	u32 coco;
+	u32 value;
 
 	coco = readl(tsc->adc_regs + REG_ADC_HS);
 	if (coco & 0x01) {
@@ -346,6 +364,7 @@ static int imx6ul_tsc_probe(struct platf
 	int err;
 	int tsc_irq;
 	int adc_irq;
+	u32 average_samples;
 
 	tsc = devm_kzalloc(&pdev->dev, sizeof(*tsc), GFP_KERNEL);
 	if (!tsc)
@@ -450,6 +469,30 @@ static int imx6ul_tsc_probe(struct platf
 	if (err)
 		tsc->pre_charge_time = 0xfff;
 
+	err = of_property_read_u32(np, "touchscreen-average-samples",
+				   &average_samples);
+	if (err)
+		average_samples = 1;
+
+	switch (average_samples) {
+	case 1:
+		tsc->average_enable = false;
+		tsc->average_select = 0; /* value unused; initialize anyway */
+		break;
+	case 4:
+	case 8:
+	case 16:
+	case 32:
+		tsc->average_enable = true;
+		tsc->average_select = ilog2(average_samples) - 2;
+		break;
+	default:
+		dev_err(&pdev->dev,
+			"touchscreen-average-samples (%u) must be 1, 4, 8, 16 or 32\n",
+			average_samples);
+		return -EINVAL;
+	}
+
 	err = input_register_device(tsc->input);
 	if (err) {
 		dev_err(&pdev->dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/touchscreen/melfas_mip4.c linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/melfas_mip4.c
--- linux-libre-4.9-gnu/drivers/input/touchscreen/melfas_mip4.c	2016-12-11 17:58:13.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/melfas_mip4.c	2017-02-12 17:50:18.000000000 -0500
@@ -33,7 +33,7 @@
 
 /*****************************************************************
  * Protocol
- * Version : MIP 4.0 Rev 4.6
+ * Version : MIP 4.0 Rev 5.4
  *****************************************************************/
 
 /* Address */
@@ -81,6 +81,9 @@
 #define MIP4_R1_INFO_IC_HW_CATEGORY		0x77
 #define MIP4_R1_INFO_CONTACT_THD_SCR		0x78
 #define MIP4_R1_INFO_CONTACT_THD_KEY		0x7A
+#define MIP4_R1_INFO_PID				0x7C
+#define MIP4_R1_INFO_VID				0x7E
+#define MIP4_R1_INFO_SLAVE_ADDR			0x80
 
 #define MIP4_R0_EVENT				0x02
 #define MIP4_R1_EVENT_SUPPORTED_FUNC		0x00
@@ -157,7 +160,9 @@ struct mip4_ts {
 
 	char phys[32];
 	char product_name[16];
+	u16 product_id;
 	char ic_name[4];
+	char fw_name[32];
 
 	unsigned int max_x;
 	unsigned int max_y;
@@ -264,6 +269,23 @@ static int mip4_query_device(struct mip4
 		dev_dbg(&ts->client->dev, "product name: %.*s\n",
 			(int)sizeof(ts->product_name), ts->product_name);
 
+	/* Product ID */
+	cmd[0] = MIP4_R0_INFO;
+	cmd[1] = MIP4_R1_INFO_PID;
+	error = mip4_i2c_xfer(ts, cmd, sizeof(cmd), buf, 2);
+	if (error) {
+		dev_warn(&ts->client->dev,
+			 "Failed to retrieve product id: %d\n", error);
+	} else {
+		ts->product_id = get_unaligned_le16(&buf[0]);
+		dev_dbg(&ts->client->dev, "product id: %04X\n", ts->product_id);
+	}
+
+	/* Firmware name */
+	snprintf(ts->fw_name, sizeof(ts->fw_name),
+		"/*(DEBLOBBED)*/", ts->product_id);
+	dev_dbg(&ts->client->dev, "firmware name: %s\n", ts->fw_name);
+
 	/* IC name */
 	cmd[0] = MIP4_R0_INFO;
 	cmd[1] = MIP4_R1_INFO_IC_NAME;
@@ -1269,11 +1291,11 @@ static ssize_t mip4_sysfs_fw_update(stru
 	const struct firmware *fw;
 	int error;
 
-	error = reject_firmware(&fw, MIP4_FW_NAME, dev);
+	error = reject_firmware(&fw, ts->fw_name, dev);
 	if (error) {
 		dev_err(&ts->client->dev,
 			"Failed to retrieve firmware %s: %d\n",
-			MIP4_FW_NAME, error);
+			ts->fw_name, error);
 		return error;
 	}
 
@@ -1348,6 +1370,25 @@ static ssize_t mip4_sysfs_read_hw_versio
 
 static DEVICE_ATTR(hw_version, S_IRUGO, mip4_sysfs_read_hw_version, NULL);
 
+static ssize_t mip4_sysfs_read_product_id(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mip4_ts *ts = i2c_get_clientdata(client);
+	size_t count;
+
+	mutex_lock(&ts->input->mutex);
+
+	count = snprintf(buf, PAGE_SIZE, "%04X\n", ts->product_id);
+
+	mutex_unlock(&ts->input->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(product_id, S_IRUGO, mip4_sysfs_read_product_id, NULL);
+
 static ssize_t mip4_sysfs_read_ic_name(struct device *dev,
 					  struct device_attribute *attr,
 					  char *buf)
@@ -1371,6 +1412,7 @@ static DEVICE_ATTR(ic_name, S_IRUGO, mip
 static struct attribute *mip4_attrs[] = {
 	&dev_attr_fw_version.attr,
 	&dev_attr_hw_version.attr,
+	&dev_attr_product_id.attr,
 	&dev_attr_ic_name.attr,
 	&dev_attr_update_fw.attr,
 	NULL,
@@ -1435,6 +1477,7 @@ static int mip4_probe(struct i2c_client
 
 	input->id.bustype = BUS_I2C;
 	input->id.vendor = 0x13c5;
+	input->id.product = ts->product_id;
 
 	input->open = mip4_input_open;
 	input->close = mip4_input_close;
@@ -1572,6 +1615,6 @@ static struct i2c_driver mip4_driver = {
 module_i2c_driver(mip4_driver);
 
 MODULE_DESCRIPTION("MELFAS MIP4 Touchscreen");
-MODULE_VERSION("2016.09.28");
+MODULE_VERSION("2016.10.31");
 MODULE_AUTHOR("Sangwon Jee <jeesw@melfas.com>");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/touchscreen/raydium_i2c_ts.c linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/raydium_i2c_ts.c
--- linux-libre-4.9-gnu/drivers/input/touchscreen/raydium_i2c_ts.c	2016-12-11 17:58:16.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/raydium_i2c_ts.c	2017-02-12 17:50:21.000000000 -0500
@@ -669,7 +669,7 @@ static int raydium_i2c_do_update_firmwar
 
 		if (ts->boot_mode == RAYDIUM_TS_MAIN) {
 			dev_err(&client->dev,
-				"failied to jump to boot loader: %d\n",
+				"failed to jump to boot loader: %d\n",
 				error);
 			return -EIO;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/touchscreen/silead.c linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/silead.c
--- linux-libre-4.9-gnu/drivers/input/touchscreen/silead.c	2016-12-11 17:58:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/silead.c	2017-02-12 17:50:31.000000000 -0500
@@ -29,6 +29,7 @@
 #include <linux/input/touchscreen.h>
 #include <linux/pm.h>
 #include <linux/irq.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/unaligned.h>
 
@@ -73,6 +74,7 @@ struct silead_ts_data {
 	struct i2c_client *client;
 	struct gpio_desc *gpio_power;
 	struct input_dev *input;
+	struct regulator_bulk_data regulators[2];
 	char fw_name[64];
 	struct touchscreen_properties prop;
 	u32 max_fingers;
@@ -432,6 +434,13 @@ static int silead_ts_set_default_fw_name
 }
 #endif
 
+static void silead_disable_regulator(void *arg)
+{
+	struct silead_ts_data *data = arg;
+
+	regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
+}
+
 static int silead_ts_probe(struct i2c_client *client,
 			   const struct i2c_device_id *id)
 {
@@ -464,6 +473,26 @@ static int silead_ts_probe(struct i2c_cl
 	if (client->irq <= 0)
 		return -ENODEV;
 
+	data->regulators[0].supply = "vddio";
+	data->regulators[1].supply = "avdd";
+	error = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators),
+					data->regulators);
+	if (error)
+		return error;
+
+	/*
+	 * Enable regulators at probe and disable them at remove, we need
+	 * to keep the chip powered otherwise it forgets its firmware.
+	 */
+	error = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
+				      data->regulators);
+	if (error)
+		return error;
+
+	error = devm_add_action_or_reset(dev, silead_disable_regulator, data);
+	if (error)
+		return error;
+
 	/* Power GPIO pin */
 	data->gpio_power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
 	if (IS_ERR(data->gpio_power)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/input/touchscreen/wm97xx-core.c linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/wm97xx-core.c
--- linux-libre-4.9-gnu/drivers/input/touchscreen/wm97xx-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/input/touchscreen/wm97xx-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -682,7 +682,7 @@ static int wm97xx_probe(struct device *d
 	}
 	platform_set_drvdata(wm->battery_dev, wm);
 	wm->battery_dev->dev.parent = dev;
-	wm->battery_dev->dev.platform_data = pdata;
+	wm->battery_dev->dev.platform_data = pdata ? pdata->batt_pdata : NULL;
 	ret = platform_device_add(wm->battery_dev);
 	if (ret < 0)
 		goto batt_reg_err;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/amd_iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/amd_iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/amd_iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/amd_iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -373,6 +373,8 @@ static struct iommu_group *acpihid_devic
 
 	if (!entry->group)
 		entry->group = generic_device_group(dev);
+	else
+		iommu_group_ref_get(entry->group);
 
 	return entry->group;
 }
@@ -1021,7 +1023,7 @@ again:
 	next_tail = (tail + sizeof(*cmd)) % CMD_BUFFER_SIZE;
 	left      = (head - next_tail) % CMD_BUFFER_SIZE;
 
-	if (left <= 2) {
+	if (left <= 0x20) {
 		struct iommu_cmd sync_cmd;
 		int ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/amd_iommu_init.c linux-libre-4.10-rc8-gnu/drivers/iommu/amd_iommu_init.c
--- linux-libre-4.9-gnu/drivers/iommu/amd_iommu_init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/amd_iommu_init.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
 #include <linux/amd-iommu.h>
 #include <linux/export.h>
 #include <linux/iommu.h>
+#include <linux/kmemleak.h>
 #include <asm/pci-direct.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
@@ -2090,6 +2091,7 @@ static struct syscore_ops amd_iommu_sysc
 
 static void __init free_on_init_error(void)
 {
+	kmemleak_free(irq_lookup_table);
 	free_pages((unsigned long)irq_lookup_table,
 		   get_order(rlookup_table_size));
 
@@ -2207,14 +2209,13 @@ static void __init free_dma_resources(vo
 static int __init early_amd_iommu_init(void)
 {
 	struct acpi_table_header *ivrs_base;
-	acpi_size ivrs_size;
 	acpi_status status;
 	int i, remap_cache_sz, ret = 0;
 
 	if (!amd_iommu_detected)
 		return -ENODEV;
 
-	status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size);
+	status = acpi_get_table("IVRS", 0, &ivrs_base);
 	if (status == AE_NOT_FOUND)
 		return -ENODEV;
 	else if (ACPI_FAILURE(status)) {
@@ -2321,6 +2322,8 @@ static int __init early_amd_iommu_init(v
 		irq_lookup_table = (void *)__get_free_pages(
 				GFP_KERNEL | __GFP_ZERO,
 				get_order(rlookup_table_size));
+		kmemleak_alloc(irq_lookup_table, rlookup_table_size,
+			       1, GFP_KERNEL);
 		if (!irq_lookup_table)
 			goto out;
 	}
@@ -2334,7 +2337,7 @@ static int __init early_amd_iommu_init(v
 
 out:
 	/* Don't leak any ACPI memory */
-	early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size);
+	acpi_put_table(ivrs_base);
 	ivrs_base = NULL;
 
 	return ret;
@@ -2358,10 +2361,9 @@ out:
 static bool detect_ivrs(void)
 {
 	struct acpi_table_header *ivrs_base;
-	acpi_size ivrs_size;
 	acpi_status status;
 
-	status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size);
+	status = acpi_get_table("IVRS", 0, &ivrs_base);
 	if (status == AE_NOT_FOUND)
 		return false;
 	else if (ACPI_FAILURE(status)) {
@@ -2370,7 +2372,7 @@ static bool detect_ivrs(void)
 		return false;
 	}
 
-	early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size);
+	acpi_put_table(ivrs_base);
 
 	/* Make sure ACS will be enabled during PCI probe */
 	pci_request_acs();
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/amd_iommu_v2.c linux-libre-4.10-rc8-gnu/drivers/iommu/amd_iommu_v2.c
--- linux-libre-4.9-gnu/drivers/iommu/amd_iommu_v2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/amd_iommu_v2.c	2017-02-12 16:03:20.000000000 -0500
@@ -805,8 +805,10 @@ int amd_iommu_init_device(struct pci_dev
 		goto out_free_domain;
 
 	group = iommu_group_get(&pdev->dev);
-	if (!group)
+	if (!group) {
+		ret = -EINVAL;
 		goto out_free_domain;
+	}
 
 	ret = iommu_attach_group(dev_state->domain, group);
 	if (ret != 0)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/arm-smmu.c linux-libre-4.10-rc8-gnu/drivers/iommu/arm-smmu.c
--- linux-libre-4.9-gnu/drivers/iommu/arm-smmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/arm-smmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,8 @@
 
 #define pr_fmt(fmt) "arm-smmu: " fmt
 
+#include <linux/acpi.h>
+#include <linux/acpi_iort.h>
 #include <linux/atomic.h>
 #include <linux/delay.h>
 #include <linux/dma-iommu.h>
@@ -247,6 +249,7 @@ enum arm_smmu_s2cr_privcfg {
 #define ARM_MMU500_ACTLR_CPRE		(1 << 1)
 
 #define ARM_MMU500_ACR_CACHE_LOCK	(1 << 26)
+#define ARM_MMU500_ACR_SMTNMB_TLBEN	(1 << 8)
 
 #define CB_PAR_F			(1 << 0)
 
@@ -642,7 +645,7 @@ static void arm_smmu_tlb_inv_range_nosyn
 	}
 }
 
-static struct iommu_gather_ops arm_smmu_gather_ops = {
+static const struct iommu_gather_ops arm_smmu_gather_ops = {
 	.tlb_flush_all	= arm_smmu_tlb_inv_context,
 	.tlb_add_flush	= arm_smmu_tlb_inv_range_nosync,
 	.tlb_sync	= arm_smmu_tlb_sync,
@@ -1379,13 +1382,14 @@ static bool arm_smmu_capable(enum iommu_
 
 static int arm_smmu_match_node(struct device *dev, void *data)
 {
-	return dev->of_node == data;
+	return dev->fwnode == data;
 }
 
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static
+struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
 {
 	struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL,
-						np, arm_smmu_match_node);
+						fwnode, arm_smmu_match_node);
 	put_device(dev);
 	return dev ? dev_get_drvdata(dev) : NULL;
 }
@@ -1403,7 +1407,7 @@ static int arm_smmu_add_device(struct de
 		if (ret)
 			goto out_free;
 	} else if (fwspec && fwspec->ops == &arm_smmu_ops) {
-		smmu = arm_smmu_get_by_node(to_of_node(fwspec->iommu_fwnode));
+		smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
 	} else {
 		return -ENODEV;
 	}
@@ -1478,7 +1482,7 @@ static struct iommu_group *arm_smmu_devi
 	}
 
 	if (group)
-		return group;
+		return iommu_group_ref_get(group);
 
 	if (dev_is_pci(dev))
 		group = pci_device_group(dev);
@@ -1581,16 +1585,22 @@ static void arm_smmu_device_reset(struct
 	for (i = 0; i < smmu->num_mapping_groups; ++i)
 		arm_smmu_write_sme(smmu, i);
 
-	/*
-	 * Before clearing ARM_MMU500_ACTLR_CPRE, need to
-	 * clear CACHE_LOCK bit of ACR first. And, CACHE_LOCK
-	 * bit is only present in MMU-500r2 onwards.
-	 */
-	reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
-	major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
-	if ((smmu->model == ARM_MMU500) && (major >= 2)) {
+	if (smmu->model == ARM_MMU500) {
+		/*
+		 * Before clearing ARM_MMU500_ACTLR_CPRE, need to
+		 * clear CACHE_LOCK bit of ACR first. And, CACHE_LOCK
+		 * bit is only present in MMU-500r2 onwards.
+		 */
+		reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID7);
+		major = (reg >> ID7_MAJOR_SHIFT) & ID7_MAJOR_MASK;
 		reg = readl_relaxed(gr0_base + ARM_SMMU_GR0_sACR);
-		reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
+		if (major >= 2)
+			reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
+		/*
+		 * Allow unmatched Stream IDs to allocate bypass
+		 * TLB entries for reduced latency.
+		 */
+		reg |= ARM_MMU500_ACR_SMTNMB_TLBEN;
 		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_sACR);
 	}
 
@@ -1667,7 +1677,7 @@ static int arm_smmu_device_cfg_probe(str
 	unsigned long size;
 	void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
 	u32 id;
-	bool cttw_dt, cttw_reg;
+	bool cttw_reg, cttw_fw = smmu->features & ARM_SMMU_FEAT_COHERENT_WALK;
 	int i;
 
 	dev_notice(smmu->dev, "probing hardware configuration...\n");
@@ -1712,20 +1722,17 @@ static int arm_smmu_device_cfg_probe(str
 
 	/*
 	 * In order for DMA API calls to work properly, we must defer to what
-	 * the DT says about coherency, regardless of what the hardware claims.
+	 * the FW says about coherency, regardless of what the hardware claims.
 	 * Fortunately, this also opens up a workaround for systems where the
 	 * ID register value has ended up configured incorrectly.
 	 */
-	cttw_dt = of_dma_is_coherent(smmu->dev->of_node);
 	cttw_reg = !!(id & ID0_CTTW);
-	if (cttw_dt)
-		smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
-	if (cttw_dt || cttw_reg)
+	if (cttw_fw || cttw_reg)
 		dev_notice(smmu->dev, "\t%scoherent table walk\n",
-			   cttw_dt ? "" : "non-");
-	if (cttw_dt != cttw_reg)
+			   cttw_fw ? "" : "non-");
+	if (cttw_fw != cttw_reg)
 		dev_notice(smmu->dev,
-			   "\t(IDR0.CTTW overridden by dma-coherent property)\n");
+			   "\t(IDR0.CTTW overridden by FW configuration)\n");
 
 	/* Max. number of entries we have for stream matching/indexing */
 	size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
@@ -1906,15 +1913,83 @@ static const struct of_device_id arm_smm
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
 
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
+#ifdef CONFIG_ACPI
+static int acpi_smmu_get_data(u32 model, struct arm_smmu_device *smmu)
+{
+	int ret = 0;
+
+	switch (model) {
+	case ACPI_IORT_SMMU_V1:
+	case ACPI_IORT_SMMU_CORELINK_MMU400:
+		smmu->version = ARM_SMMU_V1;
+		smmu->model = GENERIC_SMMU;
+		break;
+	case ACPI_IORT_SMMU_V2:
+		smmu->version = ARM_SMMU_V2;
+		smmu->model = GENERIC_SMMU;
+		break;
+	case ACPI_IORT_SMMU_CORELINK_MMU500:
+		smmu->version = ARM_SMMU_V2;
+		smmu->model = ARM_MMU500;
+		break;
+	default:
+		ret = -ENODEV;
+	}
+
+	return ret;
+}
+
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+				      struct arm_smmu_device *smmu)
+{
+	struct device *dev = smmu->dev;
+	struct acpi_iort_node *node =
+		*(struct acpi_iort_node **)dev_get_platdata(dev);
+	struct acpi_iort_smmu *iort_smmu;
+	int ret;
+
+	/* Retrieve SMMU1/2 specific data */
+	iort_smmu = (struct acpi_iort_smmu *)node->node_data;
+
+	ret = acpi_smmu_get_data(iort_smmu->model, smmu);
+	if (ret < 0)
+		return ret;
+
+	/* Ignore the configuration access interrupt */
+	smmu->num_global_irqs = 1;
+
+	if (iort_smmu->flags & ACPI_IORT_SMMU_COHERENT_WALK)
+		smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
+
+	return 0;
+}
+#else
+static inline int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+					     struct arm_smmu_device *smmu)
+{
+	return -ENODEV;
+}
+#endif
+
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
+				    struct arm_smmu_device *smmu)
 {
 	const struct arm_smmu_match_data *data;
-	struct resource *res;
-	struct arm_smmu_device *smmu;
 	struct device *dev = &pdev->dev;
-	int num_irqs, i, err;
 	bool legacy_binding;
 
+	if (of_property_read_u32(dev->of_node, "#global-interrupts",
+				 &smmu->num_global_irqs)) {
+		dev_err(dev, "missing #global-interrupts property\n");
+		return -ENODEV;
+	}
+
+	data = of_device_get_match_data(dev);
+	smmu->version = data->version;
+	smmu->model = data->model;
+
+	parse_driver_options(smmu);
+
 	legacy_binding = of_find_property(dev->of_node, "mmu-masters", NULL);
 	if (legacy_binding && !using_generic_binding) {
 		if (!using_legacy_binding)
@@ -1927,6 +2002,19 @@ static int arm_smmu_device_dt_probe(stru
 		return -ENODEV;
 	}
 
+	if (of_dma_is_coherent(dev->of_node))
+		smmu->features |= ARM_SMMU_FEAT_COHERENT_WALK;
+
+	return 0;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct arm_smmu_device *smmu;
+	struct device *dev = &pdev->dev;
+	int num_irqs, i, err;
+
 	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
 	if (!smmu) {
 		dev_err(dev, "failed to allocate arm_smmu_device\n");
@@ -1934,9 +2022,13 @@ static int arm_smmu_device_dt_probe(stru
 	}
 	smmu->dev = dev;
 
-	data = of_device_get_match_data(dev);
-	smmu->version = data->version;
-	smmu->model = data->model;
+	if (dev->of_node)
+		err = arm_smmu_device_dt_probe(pdev, smmu);
+	else
+		err = arm_smmu_device_acpi_probe(pdev, smmu);
+
+	if (err)
+		return err;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	smmu->base = devm_ioremap_resource(dev, res);
@@ -1944,12 +2036,6 @@ static int arm_smmu_device_dt_probe(stru
 		return PTR_ERR(smmu->base);
 	smmu->size = resource_size(res);
 
-	if (of_property_read_u32(dev->of_node, "#global-interrupts",
-				 &smmu->num_global_irqs)) {
-		dev_err(dev, "missing #global-interrupts property\n");
-		return -ENODEV;
-	}
-
 	num_irqs = 0;
 	while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
 		num_irqs++;
@@ -1984,8 +2070,6 @@ static int arm_smmu_device_dt_probe(stru
 	if (err)
 		return err;
 
-	parse_driver_options(smmu);
-
 	if (smmu->version == ARM_SMMU_V2 &&
 	    smmu->num_context_banks != smmu->num_context_irqs) {
 		dev_err(dev,
@@ -2007,7 +2091,7 @@ static int arm_smmu_device_dt_probe(stru
 		}
 	}
 
-	of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
+	iommu_register_instance(dev->fwnode, &arm_smmu_ops);
 	platform_set_drvdata(pdev, smmu);
 	arm_smmu_device_reset(smmu);
 
@@ -2047,7 +2131,7 @@ static struct platform_driver arm_smmu_d
 		.name		= "arm-smmu",
 		.of_match_table	= of_match_ptr(arm_smmu_of_match),
 	},
-	.probe	= arm_smmu_device_dt_probe,
+	.probe	= arm_smmu_device_probe,
 	.remove	= arm_smmu_device_remove,
 };
 
@@ -2090,6 +2174,17 @@ IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-40
 IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", arm_smmu_of_init);
 IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", arm_smmu_of_init);
 
+#ifdef CONFIG_ACPI
+static int __init arm_smmu_acpi_init(struct acpi_table_header *table)
+{
+	if (iort_node_match(ACPI_IORT_NODE_SMMU))
+		return arm_smmu_init();
+
+	return 0;
+}
+IORT_ACPI_DECLARE(arm_smmu, ACPI_SIG_IORT, arm_smmu_acpi_init);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/arm-smmu-v3.c linux-libre-4.10-rc8-gnu/drivers/iommu/arm-smmu-v3.c
--- linux-libre-4.9-gnu/drivers/iommu/arm-smmu-v3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/arm-smmu-v3.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,8 @@
  * This driver is powered by bad coffee and bombay mix.
  */
 
+#include <linux/acpi.h>
+#include <linux/acpi_iort.h>
 #include <linux/delay.h>
 #include <linux/dma-iommu.h>
 #include <linux/err.h>
@@ -1358,7 +1360,7 @@ static void arm_smmu_tlb_inv_range_nosyn
 	} while (size -= granule);
 }
 
-static struct iommu_gather_ops arm_smmu_gather_ops = {
+static const struct iommu_gather_ops arm_smmu_gather_ops = {
 	.tlb_flush_all	= arm_smmu_tlb_inv_context,
 	.tlb_add_flush	= arm_smmu_tlb_inv_range_nosync,
 	.tlb_sync	= arm_smmu_tlb_sync,
@@ -1723,13 +1725,14 @@ static struct platform_driver arm_smmu_d
 
 static int arm_smmu_match_node(struct device *dev, void *data)
 {
-	return dev->of_node == data;
+	return dev->fwnode == data;
 }
 
-static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+static
+struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
 {
 	struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL,
-						np, arm_smmu_match_node);
+						fwnode, arm_smmu_match_node);
 	put_device(dev);
 	return dev ? dev_get_drvdata(dev) : NULL;
 }
@@ -1765,7 +1768,7 @@ static int arm_smmu_add_device(struct de
 		master = fwspec->iommu_priv;
 		smmu = master->smmu;
 	} else {
-		smmu = arm_smmu_get_by_node(to_of_node(fwspec->iommu_fwnode));
+		smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
 		if (!smmu)
 			return -ENODEV;
 		master = kzalloc(sizeof(*master), GFP_KERNEL);
@@ -2380,10 +2383,10 @@ static int arm_smmu_device_reset(struct
 	return 0;
 }
 
-static int arm_smmu_device_probe(struct arm_smmu_device *smmu)
+static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
 {
 	u32 reg;
-	bool coherent;
+	bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
 
 	/* IDR0 */
 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2435,13 +2438,9 @@ static int arm_smmu_device_probe(struct
 		smmu->features |= ARM_SMMU_FEAT_HYP;
 
 	/*
-	 * The dma-coherent property is used in preference to the ID
+	 * The coherency feature as set by FW is used in preference to the ID
 	 * register, but warn on mismatch.
 	 */
-	coherent = of_dma_is_coherent(smmu->dev->of_node);
-	if (coherent)
-		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
-
 	if (!!(reg & IDR0_COHACC) != coherent)
 		dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent property (%s)\n",
 			 coherent ? "true" : "false");
@@ -2562,21 +2561,61 @@ static int arm_smmu_device_probe(struct
 	return 0;
 }
 
-static int arm_smmu_device_dt_probe(struct platform_device *pdev)
+#ifdef CONFIG_ACPI
+static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+				      struct arm_smmu_device *smmu)
+{
+	struct acpi_iort_smmu_v3 *iort_smmu;
+	struct device *dev = smmu->dev;
+	struct acpi_iort_node *node;
+
+	node = *(struct acpi_iort_node **)dev_get_platdata(dev);
+
+	/* Retrieve SMMUv3 specific data */
+	iort_smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
+
+	if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE)
+		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+	return 0;
+}
+#else
+static inline int arm_smmu_device_acpi_probe(struct platform_device *pdev,
+					     struct arm_smmu_device *smmu)
+{
+	return -ENODEV;
+}
+#endif
+
+static int arm_smmu_device_dt_probe(struct platform_device *pdev,
+				    struct arm_smmu_device *smmu)
 {
-	int irq, ret;
-	struct resource *res;
-	struct arm_smmu_device *smmu;
 	struct device *dev = &pdev->dev;
-	bool bypass = true;
 	u32 cells;
+	int ret = -EINVAL;
 
 	if (of_property_read_u32(dev->of_node, "#iommu-cells", &cells))
 		dev_err(dev, "missing #iommu-cells property\n");
 	else if (cells != 1)
 		dev_err(dev, "invalid #iommu-cells value (%d)\n", cells);
 	else
-		bypass = false;
+		ret = 0;
+
+	parse_driver_options(smmu);
+
+	if (of_dma_is_coherent(dev->of_node))
+		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
+
+	return ret;
+}
+
+static int arm_smmu_device_probe(struct platform_device *pdev)
+{
+	int irq, ret;
+	struct resource *res;
+	struct arm_smmu_device *smmu;
+	struct device *dev = &pdev->dev;
+	bool bypass;
 
 	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
 	if (!smmu) {
@@ -2613,10 +2652,19 @@ static int arm_smmu_device_dt_probe(stru
 	if (irq > 0)
 		smmu->gerr_irq = irq;
 
-	parse_driver_options(smmu);
+	if (dev->of_node) {
+		ret = arm_smmu_device_dt_probe(pdev, smmu);
+	} else {
+		ret = arm_smmu_device_acpi_probe(pdev, smmu);
+		if (ret == -ENODEV)
+			return ret;
+	}
+
+	/* Set bypass mode according to firmware probing result */
+	bypass = !!ret;
 
 	/* Probe the h/w */
-	ret = arm_smmu_device_probe(smmu);
+	ret = arm_smmu_device_hw_probe(smmu);
 	if (ret)
 		return ret;
 
@@ -2634,7 +2682,8 @@ static int arm_smmu_device_dt_probe(stru
 		return ret;
 
 	/* And we're up. Go go go! */
-	of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
+	iommu_register_instance(dev->fwnode, &arm_smmu_ops);
+
 #ifdef CONFIG_PCI
 	if (pci_bus_type.iommu_ops != &arm_smmu_ops) {
 		pci_request_acs();
@@ -2677,7 +2726,7 @@ static struct platform_driver arm_smmu_d
 		.name		= "arm-smmu-v3",
 		.of_match_table	= of_match_ptr(arm_smmu_of_match),
 	},
-	.probe	= arm_smmu_device_dt_probe,
+	.probe	= arm_smmu_device_probe,
 	.remove	= arm_smmu_device_remove,
 };
 
@@ -2715,6 +2764,17 @@ static int __init arm_smmu_of_init(struc
 }
 IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
 
+#ifdef CONFIG_ACPI
+static int __init acpi_smmu_v3_init(struct acpi_table_header *table)
+{
+	if (iort_node_match(ACPI_IORT_NODE_SMMU_V3))
+		return arm_smmu_init();
+
+	return 0;
+}
+IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
 MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/dma-iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/dma-iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/dma-iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/dma-iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -432,13 +432,12 @@ int iommu_dma_mmap(struct page **pages,
 	return ret;
 }
 
-dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
-		unsigned long offset, size_t size, int prot)
+static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
+		size_t size, int prot)
 {
 	dma_addr_t dma_addr;
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
 	struct iova_domain *iovad = cookie_iovad(domain);
-	phys_addr_t phys = page_to_phys(page) + offset;
 	size_t iova_off = iova_offset(iovad, phys);
 	size_t len = iova_align(iovad, size + iova_off);
 	struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
@@ -454,6 +453,12 @@ dma_addr_t iommu_dma_map_page(struct dev
 	return dma_addr + iova_off;
 }
 
+dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
+		unsigned long offset, size_t size, int prot)
+{
+	return __iommu_dma_map(dev, page_to_phys(page) + offset, size, prot);
+}
+
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
 		enum dma_data_direction dir, unsigned long attrs)
 {
@@ -624,6 +629,19 @@ void iommu_dma_unmap_sg(struct device *d
 	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), sg_dma_address(sg));
 }
 
+dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+	return __iommu_dma_map(dev, phys, size,
+			dma_direction_to_prot(dir, false) | IOMMU_MMIO);
+}
+
+void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
+		size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+	__iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+}
+
 int iommu_dma_supported(struct device *dev, u64 mask)
 {
 	/*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/dmar.c linux-libre-4.10-rc8-gnu/drivers/iommu/dmar.c
--- linux-libre-4.9-gnu/drivers/iommu/dmar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/dmar.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,7 +68,6 @@ DECLARE_RWSEM(dmar_global_lock);
 LIST_HEAD(dmar_drhd_units);
 
 struct acpi_table_header * __initdata dmar_tbl;
-static acpi_size dmar_tbl_size;
 static int dmar_dev_scope_status = 1;
 static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)];
 
@@ -543,9 +542,7 @@ static int __init dmar_table_detect(void
 	acpi_status status = AE_OK;
 
 	/* if we could find DMAR table, then there are DMAR devices */
-	status = acpi_get_table_with_size(ACPI_SIG_DMAR, 0,
-				(struct acpi_table_header **)&dmar_tbl,
-				&dmar_tbl_size);
+	status = acpi_get_table(ACPI_SIG_DMAR, 0, &dmar_tbl);
 
 	if (ACPI_SUCCESS(status) && !dmar_tbl) {
 		pr_warn("Unable to map DMAR\n");
@@ -906,8 +903,10 @@ int __init detect_intel_iommu(void)
 		x86_init.iommu.iommu_init = intel_iommu_init;
 #endif
 
-	early_acpi_os_unmap_memory((void __iomem *)dmar_tbl, dmar_tbl_size);
-	dmar_tbl = NULL;
+	if (dmar_tbl) {
+		acpi_put_table(dmar_tbl);
+		dmar_tbl = NULL;
+	}
 	up_write(&dmar_global_lock);
 
 	return ret ? 1 : -ENODEV;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/exynos-iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/exynos-iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/exynos-iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/exynos-iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,6 +70,36 @@ static short PG_ENT_SHIFT = -1;
 #define SYSMMU_PG_ENT_SHIFT 0
 #define SYSMMU_V5_PG_ENT_SHIFT 4
 
+static const sysmmu_pte_t *LV1_PROT;
+static const sysmmu_pte_t SYSMMU_LV1_PROT[] = {
+	((0 << 15) | (0 << 10)), /* no access */
+	((1 << 15) | (1 << 10)), /* IOMMU_READ only */
+	((0 << 15) | (1 << 10)), /* IOMMU_WRITE not supported, use read/write */
+	((0 << 15) | (1 << 10)), /* IOMMU_READ | IOMMU_WRITE */
+};
+static const sysmmu_pte_t SYSMMU_V5_LV1_PROT[] = {
+	(0 << 4), /* no access */
+	(1 << 4), /* IOMMU_READ only */
+	(2 << 4), /* IOMMU_WRITE only */
+	(3 << 4), /* IOMMU_READ | IOMMU_WRITE */
+};
+
+static const sysmmu_pte_t *LV2_PROT;
+static const sysmmu_pte_t SYSMMU_LV2_PROT[] = {
+	((0 << 9) | (0 << 4)), /* no access */
+	((1 << 9) | (1 << 4)), /* IOMMU_READ only */
+	((0 << 9) | (1 << 4)), /* IOMMU_WRITE not supported, use read/write */
+	((0 << 9) | (1 << 4)), /* IOMMU_READ | IOMMU_WRITE */
+};
+static const sysmmu_pte_t SYSMMU_V5_LV2_PROT[] = {
+	(0 << 2), /* no access */
+	(1 << 2), /* IOMMU_READ only */
+	(2 << 2), /* IOMMU_WRITE only */
+	(3 << 2), /* IOMMU_READ | IOMMU_WRITE */
+};
+
+#define SYSMMU_SUPPORTED_PROT_BITS (IOMMU_READ | IOMMU_WRITE)
+
 #define sect_to_phys(ent) (((phys_addr_t) ent) << PG_ENT_SHIFT)
 #define section_phys(sent) (sect_to_phys(*(sent)) & SECT_MASK)
 #define section_offs(iova) (iova & (SECT_SIZE - 1))
@@ -97,16 +127,17 @@ static u32 lv2ent_offset(sysmmu_iova_t i
 #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE)
 #define lv2table_base(sent) (sect_to_phys(*(sent) & 0xFFFFFFC0))
 
-#define mk_lv1ent_sect(pa) ((pa >> PG_ENT_SHIFT) | 2)
+#define mk_lv1ent_sect(pa, prot) ((pa >> PG_ENT_SHIFT) | LV1_PROT[prot] | 2)
 #define mk_lv1ent_page(pa) ((pa >> PG_ENT_SHIFT) | 1)
-#define mk_lv2ent_lpage(pa) ((pa >> PG_ENT_SHIFT) | 1)
-#define mk_lv2ent_spage(pa) ((pa >> PG_ENT_SHIFT) | 2)
+#define mk_lv2ent_lpage(pa, prot) ((pa >> PG_ENT_SHIFT) | LV2_PROT[prot] | 1)
+#define mk_lv2ent_spage(pa, prot) ((pa >> PG_ENT_SHIFT) | LV2_PROT[prot] | 2)
 
 #define CTRL_ENABLE	0x5
 #define CTRL_BLOCK	0x7
 #define CTRL_DISABLE	0x0
 
 #define CFG_LRU		0x1
+#define CFG_EAP		(1 << 2)
 #define CFG_QOS(n)	((n & 0xF) << 7)
 #define CFG_ACGEN	(1 << 24) /* System MMU 3.3 only */
 #define CFG_SYSSEL	(1 << 22) /* System MMU 3.2 only */
@@ -206,6 +237,7 @@ static const struct sysmmu_fault_info sy
 struct exynos_iommu_owner {
 	struct list_head controllers;	/* list of sysmmu_drvdata.owner_node */
 	struct iommu_domain *domain;	/* domain this device is attached */
+	struct mutex rpm_lock;		/* for runtime pm of all sysmmus */
 };
 
 /*
@@ -237,8 +269,8 @@ struct sysmmu_drvdata {
 	struct clk *aclk;		/* SYSMMU's aclk clock */
 	struct clk *pclk;		/* SYSMMU's pclk clock */
 	struct clk *clk_master;		/* master's device clock */
-	int activations;		/* number of calls to sysmmu_enable */
 	spinlock_t lock;		/* lock for modyfying state */
+	bool active;			/* current status */
 	struct exynos_iommu_domain *domain; /* domain we belong to */
 	struct list_head domain_node;	/* node for domain clients list */
 	struct list_head owner_node;	/* node for owner controllers list */
@@ -251,25 +283,6 @@ static struct exynos_iommu_domain *to_ex
 	return container_of(dom, struct exynos_iommu_domain, domain);
 }
 
-static bool set_sysmmu_active(struct sysmmu_drvdata *data)
-{
-	/* return true if the System MMU was not active previously
-	   and it needs to be initialized */
-	return ++data->activations == 1;
-}
-
-static bool set_sysmmu_inactive(struct sysmmu_drvdata *data)
-{
-	/* return true if the System MMU is needed to be disabled */
-	BUG_ON(data->activations < 1);
-	return --data->activations == 0;
-}
-
-static bool is_sysmmu_active(struct sysmmu_drvdata *data)
-{
-	return data->activations > 0;
-}
-
 static void sysmmu_unblock(struct sysmmu_drvdata *data)
 {
 	writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
@@ -388,7 +401,7 @@ static irqreturn_t exynos_sysmmu_irq(int
 	unsigned short reg_status, reg_clear;
 	int ret = -ENOSYS;
 
-	WARN_ON(!is_sysmmu_active(data));
+	WARN_ON(!data->active);
 
 	if (MMU_MAJ_VER(data->version) < 5) {
 		reg_status = REG_INT_STATUS;
@@ -434,40 +447,19 @@ static irqreturn_t exynos_sysmmu_irq(int
 	return IRQ_HANDLED;
 }
 
-static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data)
+static void __sysmmu_disable(struct sysmmu_drvdata *data)
 {
+	unsigned long flags;
+
 	clk_enable(data->clk_master);
 
+	spin_lock_irqsave(&data->lock, flags);
 	writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL);
 	writel(0, data->sfrbase + REG_MMU_CFG);
-
-	__sysmmu_disable_clocks(data);
-}
-
-static bool __sysmmu_disable(struct sysmmu_drvdata *data)
-{
-	bool disabled;
-	unsigned long flags;
-
-	spin_lock_irqsave(&data->lock, flags);
-
-	disabled = set_sysmmu_inactive(data);
-
-	if (disabled) {
-		data->pgtable = 0;
-		data->domain = NULL;
-
-		__sysmmu_disable_nocount(data);
-
-		dev_dbg(data->sysmmu, "Disabled\n");
-	} else  {
-		dev_dbg(data->sysmmu, "%d times left to disable\n",
-					data->activations);
-	}
-
+	data->active = false;
 	spin_unlock_irqrestore(&data->lock, flags);
 
-	return disabled;
+	__sysmmu_disable_clocks(data);
 }
 
 static void __sysmmu_init_config(struct sysmmu_drvdata *data)
@@ -481,20 +473,24 @@ static void __sysmmu_init_config(struct
 	else
 		cfg = CFG_QOS(15) | CFG_FLPDCACHE | CFG_ACGEN;
 
+	cfg |= CFG_EAP; /* enable access protection bits check */
+
 	writel(cfg, data->sfrbase + REG_MMU_CFG);
 }
 
-static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
+static void __sysmmu_enable(struct sysmmu_drvdata *data)
 {
+	unsigned long flags;
+
 	__sysmmu_enable_clocks(data);
 
+	spin_lock_irqsave(&data->lock, flags);
 	writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL);
-
 	__sysmmu_init_config(data);
-
 	__sysmmu_set_ptbase(data, data->pgtable);
-
 	writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL);
+	data->active = true;
+	spin_unlock_irqrestore(&data->lock, flags);
 
 	/*
 	 * SYSMMU driver keeps master's clock enabled only for the short
@@ -505,48 +501,18 @@ static void __sysmmu_enable_nocount(stru
 	clk_disable(data->clk_master);
 }
 
-static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable,
-			   struct exynos_iommu_domain *domain)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&data->lock, flags);
-	if (set_sysmmu_active(data)) {
-		data->pgtable = pgtable;
-		data->domain = domain;
-
-		__sysmmu_enable_nocount(data);
-
-		dev_dbg(data->sysmmu, "Enabled\n");
-	} else {
-		ret = (pgtable == data->pgtable) ? 1 : -EBUSY;
-
-		dev_dbg(data->sysmmu, "already enabled\n");
-	}
-
-	if (WARN_ON(ret < 0))
-		set_sysmmu_inactive(data); /* decrement count */
-
-	spin_unlock_irqrestore(&data->lock, flags);
-
-	return ret;
-}
-
 static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 					    sysmmu_iova_t iova)
 {
 	unsigned long flags;
 
-
 	spin_lock_irqsave(&data->lock, flags);
-	if (is_sysmmu_active(data) && data->version >= MAKE_MMU_VER(3, 3)) {
+	if (data->active && data->version >= MAKE_MMU_VER(3, 3)) {
 		clk_enable(data->clk_master);
 		__sysmmu_tlb_invalidate_entry(data, iova, 1);
 		clk_disable(data->clk_master);
 	}
 	spin_unlock_irqrestore(&data->lock, flags);
-
 }
 
 static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
@@ -555,7 +521,7 @@ static void sysmmu_tlb_invalidate_entry(
 	unsigned long flags;
 
 	spin_lock_irqsave(&data->lock, flags);
-	if (is_sysmmu_active(data)) {
+	if (data->active) {
 		unsigned int num_inv = 1;
 
 		clk_enable(data->clk_master);
@@ -578,9 +544,6 @@ static void sysmmu_tlb_invalidate_entry(
 			sysmmu_unblock(data);
 		}
 		clk_disable(data->clk_master);
-	} else {
-		dev_dbg(data->master,
-			"disabled. Skipping TLB invalidation @ %#x\n", iova);
 	}
 	spin_unlock_irqrestore(&data->lock, flags);
 }
@@ -652,10 +615,15 @@ static int __init exynos_sysmmu_probe(st
 
 	__sysmmu_get_version(data);
 	if (PG_ENT_SHIFT < 0) {
-		if (MMU_MAJ_VER(data->version) < 5)
+		if (MMU_MAJ_VER(data->version) < 5) {
 			PG_ENT_SHIFT = SYSMMU_PG_ENT_SHIFT;
-		else
+			LV1_PROT = SYSMMU_LV1_PROT;
+			LV2_PROT = SYSMMU_LV2_PROT;
+		} else {
 			PG_ENT_SHIFT = SYSMMU_V5_PG_ENT_SHIFT;
+			LV1_PROT = SYSMMU_V5_LV1_PROT;
+			LV2_PROT = SYSMMU_V5_LV2_PROT;
+		}
 	}
 
 	pm_runtime_enable(dev);
@@ -665,34 +633,46 @@ static int __init exynos_sysmmu_probe(st
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int exynos_sysmmu_suspend(struct device *dev)
+static int __maybe_unused exynos_sysmmu_suspend(struct device *dev)
 {
 	struct sysmmu_drvdata *data = dev_get_drvdata(dev);
+	struct device *master = data->master;
 
-	dev_dbg(dev, "suspend\n");
-	if (is_sysmmu_active(data)) {
-		__sysmmu_disable_nocount(data);
-		pm_runtime_put(dev);
+	if (master) {
+		struct exynos_iommu_owner *owner = master->archdata.iommu;
+
+		mutex_lock(&owner->rpm_lock);
+		if (data->domain) {
+			dev_dbg(data->sysmmu, "saving state\n");
+			__sysmmu_disable(data);
+		}
+		mutex_unlock(&owner->rpm_lock);
 	}
 	return 0;
 }
 
-static int exynos_sysmmu_resume(struct device *dev)
+static int __maybe_unused exynos_sysmmu_resume(struct device *dev)
 {
 	struct sysmmu_drvdata *data = dev_get_drvdata(dev);
+	struct device *master = data->master;
 
-	dev_dbg(dev, "resume\n");
-	if (is_sysmmu_active(data)) {
-		pm_runtime_get_sync(dev);
-		__sysmmu_enable_nocount(data);
+	if (master) {
+		struct exynos_iommu_owner *owner = master->archdata.iommu;
+
+		mutex_lock(&owner->rpm_lock);
+		if (data->domain) {
+			dev_dbg(data->sysmmu, "restoring state\n");
+			__sysmmu_enable(data);
+		}
+		mutex_unlock(&owner->rpm_lock);
 	}
 	return 0;
 }
-#endif
 
 static const struct dev_pm_ops sysmmu_pm_ops = {
-	SET_LATE_SYSTEM_SLEEP_PM_OPS(exynos_sysmmu_suspend, exynos_sysmmu_resume)
+	SET_RUNTIME_PM_OPS(exynos_sysmmu_suspend, exynos_sysmmu_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
 };
 
 static const struct of_device_id sysmmu_of_match[] __initconst = {
@@ -796,9 +776,12 @@ static void exynos_iommu_domain_free(str
 	spin_lock_irqsave(&domain->lock, flags);
 
 	list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
-		if (__sysmmu_disable(data))
-			data->master = NULL;
+		spin_lock(&data->lock);
+		__sysmmu_disable(data);
+		data->pgtable = 0;
+		data->domain = NULL;
 		list_del_init(&data->domain_node);
+		spin_unlock(&data->lock);
 	}
 
 	spin_unlock_irqrestore(&domain->lock, flags);
@@ -832,31 +815,34 @@ static void exynos_iommu_detach_device(s
 	phys_addr_t pagetable = virt_to_phys(domain->pgtable);
 	struct sysmmu_drvdata *data, *next;
 	unsigned long flags;
-	bool found = false;
 
 	if (!has_sysmmu(dev) || owner->domain != iommu_domain)
 		return;
 
+	mutex_lock(&owner->rpm_lock);
+
+	list_for_each_entry(data, &owner->controllers, owner_node) {
+		pm_runtime_get_noresume(data->sysmmu);
+		if (pm_runtime_active(data->sysmmu))
+			__sysmmu_disable(data);
+		pm_runtime_put(data->sysmmu);
+	}
+
 	spin_lock_irqsave(&domain->lock, flags);
 	list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
-		if (data->master == dev) {
-			if (__sysmmu_disable(data)) {
-				data->master = NULL;
-				list_del_init(&data->domain_node);
-			}
-			pm_runtime_put(data->sysmmu);
-			found = true;
-		}
+		spin_lock(&data->lock);
+		data->pgtable = 0;
+		data->domain = NULL;
+		list_del_init(&data->domain_node);
+		spin_unlock(&data->lock);
 	}
+	owner->domain = NULL;
 	spin_unlock_irqrestore(&domain->lock, flags);
 
-	owner->domain = NULL;
+	mutex_unlock(&owner->rpm_lock);
 
-	if (found)
-		dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n",
-					__func__, &pagetable);
-	else
-		dev_err(dev, "%s: No IOMMU is attached\n", __func__);
+	dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", __func__,
+		&pagetable);
 }
 
 static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
@@ -867,7 +853,6 @@ static int exynos_iommu_attach_device(st
 	struct sysmmu_drvdata *data;
 	phys_addr_t pagetable = virt_to_phys(domain->pgtable);
 	unsigned long flags;
-	int ret = -ENODEV;
 
 	if (!has_sysmmu(dev))
 		return -ENODEV;
@@ -875,29 +860,32 @@ static int exynos_iommu_attach_device(st
 	if (owner->domain)
 		exynos_iommu_detach_device(owner->domain, dev);
 
-	list_for_each_entry(data, &owner->controllers, owner_node) {
-		pm_runtime_get_sync(data->sysmmu);
-		ret = __sysmmu_enable(data, pagetable, domain);
-		if (ret >= 0) {
-			data->master = dev;
+	mutex_lock(&owner->rpm_lock);
 
-			spin_lock_irqsave(&domain->lock, flags);
-			list_add_tail(&data->domain_node, &domain->clients);
-			spin_unlock_irqrestore(&domain->lock, flags);
-		}
+	spin_lock_irqsave(&domain->lock, flags);
+	list_for_each_entry(data, &owner->controllers, owner_node) {
+		spin_lock(&data->lock);
+		data->pgtable = pagetable;
+		data->domain = domain;
+		list_add_tail(&data->domain_node, &domain->clients);
+		spin_unlock(&data->lock);
 	}
+	owner->domain = iommu_domain;
+	spin_unlock_irqrestore(&domain->lock, flags);
 
-	if (ret < 0) {
-		dev_err(dev, "%s: Failed to attach IOMMU with pgtable %pa\n",
-					__func__, &pagetable);
-		return ret;
+	list_for_each_entry(data, &owner->controllers, owner_node) {
+		pm_runtime_get_noresume(data->sysmmu);
+		if (pm_runtime_active(data->sysmmu))
+			__sysmmu_enable(data);
+		pm_runtime_put(data->sysmmu);
 	}
 
-	owner->domain = iommu_domain;
-	dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa %s\n",
-		__func__, &pagetable, (ret == 0) ? "" : ", again");
+	mutex_unlock(&owner->rpm_lock);
 
-	return ret;
+	dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa\n", __func__,
+		&pagetable);
+
+	return 0;
 }
 
 static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain,
@@ -954,7 +942,7 @@ static sysmmu_pte_t *alloc_lv2entry(stru
 
 static int lv1set_section(struct exynos_iommu_domain *domain,
 			  sysmmu_pte_t *sent, sysmmu_iova_t iova,
-			  phys_addr_t paddr, short *pgcnt)
+			  phys_addr_t paddr, int prot, short *pgcnt)
 {
 	if (lv1ent_section(sent)) {
 		WARN(1, "Trying mapping on 1MiB@%#08x that is mapped",
@@ -973,7 +961,7 @@ static int lv1set_section(struct exynos_
 		*pgcnt = 0;
 	}
 
-	update_pte(sent, mk_lv1ent_sect(paddr));
+	update_pte(sent, mk_lv1ent_sect(paddr, prot));
 
 	spin_lock(&domain->lock);
 	if (lv1ent_page_zero(sent)) {
@@ -991,13 +979,13 @@ static int lv1set_section(struct exynos_
 }
 
 static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size,
-								short *pgcnt)
+		       int prot, short *pgcnt)
 {
 	if (size == SPAGE_SIZE) {
 		if (WARN_ON(!lv2ent_fault(pent)))
 			return -EADDRINUSE;
 
-		update_pte(pent, mk_lv2ent_spage(paddr));
+		update_pte(pent, mk_lv2ent_spage(paddr, prot));
 		*pgcnt -= 1;
 	} else { /* size == LPAGE_SIZE */
 		int i;
@@ -1013,7 +1001,7 @@ static int lv2set_page(sysmmu_pte_t *pen
 				return -EADDRINUSE;
 			}
 
-			*pent = mk_lv2ent_lpage(paddr);
+			*pent = mk_lv2ent_lpage(paddr, prot);
 		}
 		dma_sync_single_for_device(dma_dev, pent_base,
 					   sizeof(*pent) * SPAGES_PER_LPAGE,
@@ -1061,13 +1049,14 @@ static int exynos_iommu_map(struct iommu
 	int ret = -ENOMEM;
 
 	BUG_ON(domain->pgtable == NULL);
+	prot &= SYSMMU_SUPPORTED_PROT_BITS;
 
 	spin_lock_irqsave(&domain->pgtablelock, flags);
 
 	entry = section_entry(domain->pgtable, iova);
 
 	if (size == SECT_SIZE) {
-		ret = lv1set_section(domain, entry, iova, paddr,
+		ret = lv1set_section(domain, entry, iova, paddr, prot,
 				     &domain->lv2entcnt[lv1ent_offset(iova)]);
 	} else {
 		sysmmu_pte_t *pent;
@@ -1078,7 +1067,7 @@ static int exynos_iommu_map(struct iommu
 		if (IS_ERR(pent))
 			ret = PTR_ERR(pent);
 		else
-			ret = lv2set_page(pent, paddr, size,
+			ret = lv2set_page(pent, paddr, size, prot,
 				       &domain->lv2entcnt[lv1ent_offset(iova)]);
 	}
 
@@ -1268,10 +1257,20 @@ static int exynos_iommu_of_xlate(struct
 			return -ENOMEM;
 
 		INIT_LIST_HEAD(&owner->controllers);
+		mutex_init(&owner->rpm_lock);
 		dev->archdata.iommu = owner;
 	}
 
 	list_add_tail(&data->owner_node, &owner->controllers);
+	data->master = dev;
+
+	/*
+	 * SYSMMU will be runtime activated via device link (dependency) to its
+	 * master device, so there are no direct calls to pm_runtime_get/put
+	 * in this driver.
+	 */
+	device_link_add(dev, data->sysmmu, DL_FLAG_PM_RUNTIME);
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/intel-iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/intel-iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/intel-iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/intel-iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -2037,6 +2037,25 @@ static int domain_context_mapping_one(st
 	if (context_present(context))
 		goto out_unlock;
 
+	/*
+	 * For kdump cases, old valid entries may be cached due to the
+	 * in-flight DMA and copied pgtable, but there is no unmapping
+	 * behaviour for them, thus we need an explicit cache flush for
+	 * the newly-mapped device. For kdump, at this point, the device
+	 * is supposed to finish reset at its driver probe stage, so no
+	 * in-flight DMA will exist, and we don't need to worry anymore
+	 * hereafter.
+	 */
+	if (context_copied(context)) {
+		u16 did_old = context_domain_id(context);
+
+		if (did_old >= 0 && did_old < cap_ndoms(iommu->cap))
+			iommu->flush.flush_context(iommu, did_old,
+						   (((u16)bus) << 8) | devfn,
+						   DMA_CCMD_MASK_NOBIT,
+						   DMA_CCMD_DEVICE_INVL);
+	}
+
 	pgd = domain->pgd;
 
 	context_clear_entry(context);
@@ -4688,25 +4707,13 @@ static void free_all_cpu_cached_iovas(un
 	}
 }
 
-static int intel_iommu_cpu_notifier(struct notifier_block *nfb,
-				    unsigned long action, void *v)
+static int intel_iommu_cpu_dead(unsigned int cpu)
 {
-	unsigned int cpu = (unsigned long)v;
-
-	switch (action) {
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		free_all_cpu_cached_iovas(cpu);
-		flush_unmaps_timeout(cpu);
-		break;
-	}
-	return NOTIFY_OK;
+	free_all_cpu_cached_iovas(cpu);
+	flush_unmaps_timeout(cpu);
+	return 0;
 }
 
-static struct notifier_block intel_iommu_cpu_nb = {
-	.notifier_call = intel_iommu_cpu_notifier,
-};
-
 static ssize_t intel_iommu_show_version(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
@@ -4855,8 +4862,8 @@ int __init intel_iommu_init(void)
 	bus_register_notifier(&pci_bus_type, &device_nb);
 	if (si_domain && !hw_pass_through)
 		register_memory_notifier(&intel_iommu_memory_nb);
-	register_hotcpu_notifier(&intel_iommu_cpu_nb);
-
+	cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
+			  intel_iommu_cpu_dead);
 	intel_iommu_enabled = 1;
 
 	return 0;
@@ -5197,6 +5204,25 @@ static void intel_iommu_remove_device(st
 }
 
 #ifdef CONFIG_INTEL_IOMMU_SVM
+#define MAX_NR_PASID_BITS (20)
+static inline unsigned long intel_iommu_get_pts(struct intel_iommu *iommu)
+{
+	/*
+	 * Convert ecap_pss to extend context entry pts encoding, also
+	 * respect the soft pasid_max value set by the iommu.
+	 * - number of PASID bits = ecap_pss + 1
+	 * - number of PASID table entries = 2^(pts + 5)
+	 * Therefore, pts = ecap_pss - 4
+	 * e.g. KBL ecap_pss = 0x13, PASID has 20 bits, pts = 15
+	 */
+	if (ecap_pss(iommu->ecap) < 5)
+		return 0;
+
+	/* pasid_max is encoded as actual number of entries not the bits */
+	return find_first_bit((unsigned long *)&iommu->pasid_max,
+			MAX_NR_PASID_BITS) - 5;
+}
+
 int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev)
 {
 	struct device_domain_info *info;
@@ -5229,7 +5255,9 @@ int intel_iommu_enable_pasid(struct inte
 
 	if (!(ctx_lo & CONTEXT_PASIDE)) {
 		context[1].hi = (u64)virt_to_phys(iommu->pasid_state_table);
-		context[1].lo = (u64)virt_to_phys(iommu->pasid_table) | ecap_pss(iommu->ecap);
+		context[1].lo = (u64)virt_to_phys(iommu->pasid_table) |
+			intel_iommu_get_pts(iommu);
+
 		wmb();
 		/* CONTEXT_TT_MULTI_LEVEL and CONTEXT_TT_DEV_IOTLB are both
 		 * extended to permit requests-with-PASID if the PASIDE bit
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -552,6 +552,19 @@ struct iommu_group *iommu_group_get(stru
 EXPORT_SYMBOL_GPL(iommu_group_get);
 
 /**
+ * iommu_group_ref_get - Increment reference on a group
+ * @group: the group to use, must not be NULL
+ *
+ * This function is called by iommu drivers to take additional references on an
+ * existing group.  Returns the given group for convenience.
+ */
+struct iommu_group *iommu_group_ref_get(struct iommu_group *group)
+{
+	kobject_get(group->devices_kobj);
+	return group;
+}
+
+/**
  * iommu_group_put - Decrement group reference
  * @group: the group to use
  *
@@ -1615,6 +1628,46 @@ out:
 	return ret;
 }
 
+struct iommu_instance {
+	struct list_head list;
+	struct fwnode_handle *fwnode;
+	const struct iommu_ops *ops;
+};
+static LIST_HEAD(iommu_instance_list);
+static DEFINE_SPINLOCK(iommu_instance_lock);
+
+void iommu_register_instance(struct fwnode_handle *fwnode,
+			     const struct iommu_ops *ops)
+{
+	struct iommu_instance *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+	if (WARN_ON(!iommu))
+		return;
+
+	of_node_get(to_of_node(fwnode));
+	INIT_LIST_HEAD(&iommu->list);
+	iommu->fwnode = fwnode;
+	iommu->ops = ops;
+	spin_lock(&iommu_instance_lock);
+	list_add_tail(&iommu->list, &iommu_instance_list);
+	spin_unlock(&iommu_instance_lock);
+}
+
+const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode)
+{
+	struct iommu_instance *instance;
+	const struct iommu_ops *ops = NULL;
+
+	spin_lock(&iommu_instance_lock);
+	list_for_each_entry(instance, &iommu_instance_list, list)
+		if (instance->fwnode == fwnode) {
+			ops = instance->ops;
+			break;
+		}
+	spin_unlock(&iommu_instance_lock);
+	return ops;
+}
+
 int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
 		      const struct iommu_ops *ops)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/io-pgtable-arm.c linux-libre-4.10-rc8-gnu/drivers/iommu/io-pgtable-arm.c
--- linux-libre-4.9-gnu/drivers/iommu/io-pgtable-arm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/io-pgtable-arm.c	2017-02-12 16:03:20.000000000 -0500
@@ -916,7 +916,7 @@ static void dummy_tlb_sync(void *cookie)
 	WARN_ON(cookie != cfg_cookie);
 }
 
-static struct iommu_gather_ops dummy_tlb_ops __initdata = {
+static const struct iommu_gather_ops dummy_tlb_ops __initconst = {
 	.tlb_flush_all	= dummy_tlb_flush_all,
 	.tlb_add_flush	= dummy_tlb_add_flush,
 	.tlb_sync	= dummy_tlb_sync,
@@ -980,8 +980,7 @@ static int __init arm_lpae_run_tests(str
 		 * Distinct mappings of different granule sizes.
 		 */
 		iova = 0;
-		j = find_first_bit(&cfg->pgsize_bitmap, BITS_PER_LONG);
-		while (j != BITS_PER_LONG) {
+		for_each_set_bit(j, &cfg->pgsize_bitmap, BITS_PER_LONG) {
 			size = 1UL << j;
 
 			if (ops->map(ops, iova, iova, size, IOMMU_READ |
@@ -999,8 +998,6 @@ static int __init arm_lpae_run_tests(str
 				return __FAIL(ops, i);
 
 			iova += SZ_1G;
-			j++;
-			j = find_next_bit(&cfg->pgsize_bitmap, BITS_PER_LONG, j);
 		}
 
 		/* Partial unmap */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/io-pgtable-arm-v7s.c linux-libre-4.10-rc8-gnu/drivers/iommu/io-pgtable-arm-v7s.c
--- linux-libre-4.9-gnu/drivers/iommu/io-pgtable-arm-v7s.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/io-pgtable-arm-v7s.c	2017-02-12 16:03:20.000000000 -0500
@@ -793,8 +793,7 @@ static int __init arm_v7s_do_selftests(v
 	 * Distinct mappings of different granule sizes.
 	 */
 	iova = 0;
-	i = find_first_bit(&cfg.pgsize_bitmap, BITS_PER_LONG);
-	while (i != BITS_PER_LONG) {
+	for_each_set_bit(i, &cfg.pgsize_bitmap, BITS_PER_LONG) {
 		size = 1UL << i;
 		if (ops->map(ops, iova, iova, size, IOMMU_READ |
 						    IOMMU_WRITE |
@@ -811,8 +810,6 @@ static int __init arm_v7s_do_selftests(v
 			return __FAIL(ops);
 
 		iova += SZ_16M;
-		i++;
-		i = find_next_bit(&cfg.pgsize_bitmap, BITS_PER_LONG, i);
 		loopnr++;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/iova.c linux-libre-4.10-rc8-gnu/drivers/iommu/iova.c
--- linux-libre-4.9-gnu/drivers/iommu/iova.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/iova.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ EXPORT_SYMBOL_GPL(init_iova_domain);
 static struct rb_node *
 __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
 {
-	if ((*limit_pfn != iovad->dma_32bit_pfn) ||
+	if ((*limit_pfn > iovad->dma_32bit_pfn) ||
 		(iovad->cached32_node == NULL))
 		return rb_last(&iovad->rbroot);
 	else {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/mtk_iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/mtk_iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/mtk_iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/mtk_iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -195,14 +195,14 @@ static irqreturn_t mtk_iommu_isr(int irq
 static void mtk_iommu_config(struct mtk_iommu_data *data,
 			     struct device *dev, bool enable)
 {
-	struct mtk_iommu_client_priv *head, *cur, *next;
 	struct mtk_smi_larb_iommu    *larb_mmu;
 	unsigned int                 larbid, portid;
+	struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+	int i;
 
-	head = dev->archdata.iommu;
-	list_for_each_entry_safe(cur, next, &head->client, client) {
-		larbid = MTK_M4U_TO_LARB(cur->mtk_m4u_id);
-		portid = MTK_M4U_TO_PORT(cur->mtk_m4u_id);
+	for (i = 0; i < fwspec->num_ids; ++i) {
+		larbid = MTK_M4U_TO_LARB(fwspec->ids[i]);
+		portid = MTK_M4U_TO_PORT(fwspec->ids[i]);
 		larb_mmu = &data->smi_imu.larb_imu[larbid];
 
 		dev_dbg(dev, "%s iommu port: %d\n",
@@ -282,14 +282,12 @@ static int mtk_iommu_attach_device(struc
 				   struct device *dev)
 {
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
-	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
-	struct mtk_iommu_data *data;
+	struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
 	int ret;
 
-	if (!priv)
+	if (!data)
 		return -ENODEV;
 
-	data = dev_get_drvdata(priv->m4udev);
 	if (!data->m4u_dom) {
 		data->m4u_dom = dom;
 		ret = mtk_iommu_domain_finalise(data);
@@ -310,13 +308,11 @@ static int mtk_iommu_attach_device(struc
 static void mtk_iommu_detach_device(struct iommu_domain *domain,
 				    struct device *dev)
 {
-	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
-	struct mtk_iommu_data *data;
+	struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
 
-	if (!priv)
+	if (!data)
 		return;
 
-	data = dev_get_drvdata(priv->m4udev);
 	mtk_iommu_config(data, dev, false);
 }
 
@@ -366,8 +362,8 @@ static int mtk_iommu_add_device(struct d
 {
 	struct iommu_group *group;
 
-	if (!dev->archdata.iommu) /* Not a iommu client device */
-		return -ENODEV;
+	if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
+		return -ENODEV; /* Not a iommu client device */
 
 	group = iommu_group_get_for_dev(dev);
 	if (IS_ERR(group))
@@ -379,44 +375,33 @@ static int mtk_iommu_add_device(struct d
 
 static void mtk_iommu_remove_device(struct device *dev)
 {
-	struct mtk_iommu_client_priv *head, *cur, *next;
-
-	head = dev->archdata.iommu;
-	if (!head)
+	if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
 		return;
 
-	list_for_each_entry_safe(cur, next, &head->client, client) {
-		list_del(&cur->client);
-		kfree(cur);
-	}
-	kfree(head);
-	dev->archdata.iommu = NULL;
-
 	iommu_group_remove_device(dev);
+	iommu_fwspec_free(dev);
 }
 
 static struct iommu_group *mtk_iommu_device_group(struct device *dev)
 {
-	struct mtk_iommu_data *data;
-	struct mtk_iommu_client_priv *priv;
+	struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
 
-	priv = dev->archdata.iommu;
-	if (!priv)
+	if (!data)
 		return ERR_PTR(-ENODEV);
 
 	/* All the client devices are in the same m4u iommu-group */
-	data = dev_get_drvdata(priv->m4udev);
 	if (!data->m4u_group) {
 		data->m4u_group = iommu_group_alloc();
 		if (IS_ERR(data->m4u_group))
 			dev_err(dev, "Failed to allocate M4U IOMMU group\n");
+	} else {
+		iommu_group_ref_get(data->m4u_group);
 	}
 	return data->m4u_group;
 }
 
 static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
 {
-	struct mtk_iommu_client_priv *head, *priv, *next;
 	struct platform_device *m4updev;
 
 	if (args->args_count != 1) {
@@ -425,38 +410,16 @@ static int mtk_iommu_of_xlate(struct dev
 		return -EINVAL;
 	}
 
-	if (!dev->archdata.iommu) {
+	if (!dev->iommu_fwspec->iommu_priv) {
 		/* Get the m4u device */
 		m4updev = of_find_device_by_node(args->np);
 		if (WARN_ON(!m4updev))
 			return -EINVAL;
 
-		head = kzalloc(sizeof(*head), GFP_KERNEL);
-		if (!head)
-			return -ENOMEM;
-
-		dev->archdata.iommu = head;
-		INIT_LIST_HEAD(&head->client);
-		head->m4udev = &m4updev->dev;
-	} else {
-		head = dev->archdata.iommu;
+		dev->iommu_fwspec->iommu_priv = platform_get_drvdata(m4updev);
 	}
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		goto err_free_mem;
-
-	priv->mtk_m4u_id = args->args[0];
-	list_add_tail(&priv->client, &head->client);
-
-	return 0;
-
-err_free_mem:
-	list_for_each_entry_safe(priv, next, &head->client, client)
-		kfree(priv);
-	kfree(head);
-	dev->archdata.iommu = NULL;
-	return -ENOMEM;
+	return iommu_fwspec_add_ids(dev, args->args, 1);
 }
 
 static struct iommu_ops mtk_iommu_ops = {
@@ -583,17 +546,19 @@ static int mtk_iommu_probe(struct platfo
 			continue;
 
 		plarbdev = of_find_device_by_node(larbnode);
-		of_node_put(larbnode);
 		if (!plarbdev) {
 			plarbdev = of_platform_device_create(
 						larbnode, NULL,
 						platform_bus_type.dev_root);
-			if (!plarbdev)
+			if (!plarbdev) {
+				of_node_put(larbnode);
 				return -EPROBE_DEFER;
+			}
 		}
 		data->smi_imu.larb_imu[i].dev = &plarbdev->dev;
 
-		component_match_add(dev, &match, compare_of, larbnode);
+		component_match_add_release(dev, &match, release_of,
+					    compare_of, larbnode);
 	}
 
 	platform_set_drvdata(pdev, data);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/mtk_iommu.h linux-libre-4.10-rc8-gnu/drivers/iommu/mtk_iommu.h
--- linux-libre-4.9-gnu/drivers/iommu/mtk_iommu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/mtk_iommu.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,12 +34,6 @@ struct mtk_iommu_suspend_reg {
 	u32				int_main_control;
 };
 
-struct mtk_iommu_client_priv {
-	struct list_head		client;
-	unsigned int			mtk_m4u_id;
-	struct device			*m4udev;
-};
-
 struct mtk_iommu_domain;
 
 struct mtk_iommu_data {
@@ -60,6 +54,11 @@ static inline int compare_of(struct devi
 	return dev->of_node == data;
 }
 
+static inline void release_of(struct device *dev, void *data)
+{
+	of_node_put(data);
+}
+
 static inline int mtk_iommu_bind(struct device *dev)
 {
 	struct mtk_iommu_data *data = dev_get_drvdata(dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/mtk_iommu_v1.c linux-libre-4.10-rc8-gnu/drivers/iommu/mtk_iommu_v1.c
--- linux-libre-4.9-gnu/drivers/iommu/mtk_iommu_v1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/mtk_iommu_v1.c	2017-02-12 16:03:20.000000000 -0500
@@ -204,14 +204,14 @@ static irqreturn_t mtk_iommu_isr(int irq
 static void mtk_iommu_config(struct mtk_iommu_data *data,
 			     struct device *dev, bool enable)
 {
-	struct mtk_iommu_client_priv *head, *cur, *next;
 	struct mtk_smi_larb_iommu    *larb_mmu;
 	unsigned int                 larbid, portid;
+	struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+	int i;
 
-	head = dev->archdata.iommu;
-	list_for_each_entry_safe(cur, next, &head->client, client) {
-		larbid = mt2701_m4u_to_larb(cur->mtk_m4u_id);
-		portid = mt2701_m4u_to_port(cur->mtk_m4u_id);
+	for (i = 0; i < fwspec->num_ids; ++i) {
+		larbid = mt2701_m4u_to_larb(fwspec->ids[i]);
+		portid = mt2701_m4u_to_port(fwspec->ids[i]);
 		larb_mmu = &data->smi_imu.larb_imu[larbid];
 
 		dev_dbg(dev, "%s iommu port: %d\n",
@@ -271,14 +271,12 @@ static int mtk_iommu_attach_device(struc
 				   struct device *dev)
 {
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
-	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
-	struct mtk_iommu_data *data;
+	struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
 	int ret;
 
-	if (!priv)
+	if (!data)
 		return -ENODEV;
 
-	data = dev_get_drvdata(priv->m4udev);
 	if (!data->m4u_dom) {
 		data->m4u_dom = dom;
 		ret = mtk_iommu_domain_finalise(data);
@@ -295,13 +293,11 @@ static int mtk_iommu_attach_device(struc
 static void mtk_iommu_detach_device(struct iommu_domain *domain,
 				    struct device *dev)
 {
-	struct mtk_iommu_client_priv *priv = dev->archdata.iommu;
-	struct mtk_iommu_data *data;
+	struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
 
-	if (!priv)
+	if (!data)
 		return;
 
-	data = dev_get_drvdata(priv->m4udev);
 	mtk_iommu_config(data, dev, false);
 }
 
@@ -366,6 +362,8 @@ static phys_addr_t mtk_iommu_iova_to_phy
 	return pa;
 }
 
+static struct iommu_ops mtk_iommu_ops;
+
 /*
  * MTK generation one iommu HW only support one iommu domain, and all the client
  * sharing the same iova address space.
@@ -373,7 +371,7 @@ static phys_addr_t mtk_iommu_iova_to_phy
 static int mtk_iommu_create_mapping(struct device *dev,
 				    struct of_phandle_args *args)
 {
-	struct mtk_iommu_client_priv *head, *priv, *next;
+	struct mtk_iommu_data *data;
 	struct platform_device *m4updev;
 	struct dma_iommu_mapping *mtk_mapping;
 	struct device *m4udev;
@@ -385,41 +383,37 @@ static int mtk_iommu_create_mapping(stru
 		return -EINVAL;
 	}
 
-	if (!dev->archdata.iommu) {
+	if (!dev->iommu_fwspec) {
+		ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_ops);
+		if (ret)
+			return ret;
+	} else if (dev->iommu_fwspec->ops != &mtk_iommu_ops) {
+		return -EINVAL;
+	}
+
+	if (!dev->iommu_fwspec->iommu_priv) {
 		/* Get the m4u device */
 		m4updev = of_find_device_by_node(args->np);
 		if (WARN_ON(!m4updev))
 			return -EINVAL;
 
-		head = kzalloc(sizeof(*head), GFP_KERNEL);
-		if (!head)
-			return -ENOMEM;
-
-		dev->archdata.iommu = head;
-		INIT_LIST_HEAD(&head->client);
-		head->m4udev = &m4updev->dev;
-	} else {
-		head = dev->archdata.iommu;
+		dev->iommu_fwspec->iommu_priv = platform_get_drvdata(m4updev);
 	}
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		ret = -ENOMEM;
-		goto err_free_mem;
-	}
-	priv->mtk_m4u_id = args->args[0];
-	list_add_tail(&priv->client, &head->client);
+	ret = iommu_fwspec_add_ids(dev, args->args, 1);
+	if (ret)
+		return ret;
 
-	m4udev = head->m4udev;
+	data = dev->iommu_fwspec->iommu_priv;
+	m4udev = data->dev;
 	mtk_mapping = m4udev->archdata.iommu;
 	if (!mtk_mapping) {
 		/* MTK iommu support 4GB iova address space. */
 		mtk_mapping = arm_iommu_create_mapping(&platform_bus_type,
 						0, 1ULL << 32);
-		if (IS_ERR(mtk_mapping)) {
-			ret = PTR_ERR(mtk_mapping);
-			goto err_free_mem;
-		}
+		if (IS_ERR(mtk_mapping))
+			return PTR_ERR(mtk_mapping);
+
 		m4udev->archdata.iommu = mtk_mapping;
 	}
 
@@ -432,11 +426,6 @@ static int mtk_iommu_create_mapping(stru
 err_release_mapping:
 	arm_iommu_release_mapping(mtk_mapping);
 	m4udev->archdata.iommu = NULL;
-err_free_mem:
-	list_for_each_entry_safe(priv, next, &head->client, client)
-		kfree(priv);
-	kfree(head);
-	dev->archdata.iommu = NULL;
 	return ret;
 }
 
@@ -458,8 +447,8 @@ static int mtk_iommu_add_device(struct d
 		of_node_put(iommu_spec.np);
 	}
 
-	if (!dev->archdata.iommu) /* Not a iommu client device */
-		return -ENODEV;
+	if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
+		return -ENODEV; /* Not a iommu client device */
 
 	group = iommu_group_get_for_dev(dev);
 	if (IS_ERR(group))
@@ -471,37 +460,27 @@ static int mtk_iommu_add_device(struct d
 
 static void mtk_iommu_remove_device(struct device *dev)
 {
-	struct mtk_iommu_client_priv *head, *cur, *next;
-
-	head = dev->archdata.iommu;
-	if (!head)
+	if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
 		return;
 
-	list_for_each_entry_safe(cur, next, &head->client, client) {
-		list_del(&cur->client);
-		kfree(cur);
-	}
-	kfree(head);
-	dev->archdata.iommu = NULL;
-
 	iommu_group_remove_device(dev);
+	iommu_fwspec_free(dev);
 }
 
 static struct iommu_group *mtk_iommu_device_group(struct device *dev)
 {
-	struct mtk_iommu_data *data;
-	struct mtk_iommu_client_priv *priv;
+	struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
 
-	priv = dev->archdata.iommu;
-	if (!priv)
+	if (!data)
 		return ERR_PTR(-ENODEV);
 
 	/* All the client devices are in the same m4u iommu-group */
-	data = dev_get_drvdata(priv->m4udev);
 	if (!data->m4u_group) {
 		data->m4u_group = iommu_group_alloc();
 		if (IS_ERR(data->m4u_group))
 			dev_err(dev, "Failed to allocate M4U IOMMU group\n");
+	} else {
+		iommu_group_ref_get(data->m4u_group);
 	}
 	return data->m4u_group;
 }
@@ -624,17 +603,19 @@ static int mtk_iommu_probe(struct platfo
 			continue;
 
 		plarbdev = of_find_device_by_node(larb_spec.np);
-		of_node_put(larb_spec.np);
 		if (!plarbdev) {
 			plarbdev = of_platform_device_create(
 						larb_spec.np, NULL,
 						platform_bus_type.dev_root);
-			if (!plarbdev)
+			if (!plarbdev) {
+				of_node_put(larb_spec.np);
 				return -EPROBE_DEFER;
+			}
 		}
 
 		data->smi_imu.larb_imu[larb_nr].dev = &plarbdev->dev;
-		component_match_add(dev, &match, compare_of, larb_spec.np);
+		component_match_add_release(dev, &match, release_of,
+					    compare_of, larb_spec.np);
 		larb_nr++;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/of_iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/of_iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/of_iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/of_iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -96,45 +96,6 @@ int of_get_dma_window(struct device_node
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
-struct of_iommu_node {
-	struct list_head list;
-	struct device_node *np;
-	const struct iommu_ops *ops;
-};
-static LIST_HEAD(of_iommu_list);
-static DEFINE_SPINLOCK(of_iommu_lock);
-
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops)
-{
-	struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
-
-	if (WARN_ON(!iommu))
-		return;
-
-	of_node_get(np);
-	INIT_LIST_HEAD(&iommu->list);
-	iommu->np = np;
-	iommu->ops = ops;
-	spin_lock(&of_iommu_lock);
-	list_add_tail(&iommu->list, &of_iommu_list);
-	spin_unlock(&of_iommu_lock);
-}
-
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
-{
-	struct of_iommu_node *node;
-	const struct iommu_ops *ops = NULL;
-
-	spin_lock(&of_iommu_lock);
-	list_for_each_entry(node, &of_iommu_list, list)
-		if (node->np == np) {
-			ops = node->ops;
-			break;
-		}
-	spin_unlock(&of_iommu_lock);
-	return ops;
-}
-
 static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
 {
 	struct of_phandle_args *iommu_spec = data;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/iommu/s390-iommu.c linux-libre-4.10-rc8-gnu/drivers/iommu/s390-iommu.c
--- linux-libre-4.9-gnu/drivers/iommu/s390-iommu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/iommu/s390-iommu.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,6 @@
 #include <linux/pci.h>
 #include <linux/iommu.h>
 #include <linux/iommu-helper.h>
-#include <linux/pci.h>
 #include <linux/sizes.h>
 #include <asm/pci_dma.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-armada-370-xp.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-armada-370-xp.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-armada-370-xp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-armada-370-xp.c	2017-02-12 16:03:20.000000000 -0500
@@ -578,13 +578,13 @@ static int __init armada_370_xp_mpic_of_
 #ifdef CONFIG_SMP
 		set_smp_cross_call(armada_mpic_send_doorbell);
 		cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_XP_STARTING,
-					  "AP_IRQ_ARMADA_XP_STARTING",
+					  "irqchip/armada/ipi:starting",
 					  armada_xp_mpic_starting_cpu, NULL);
 #endif
 	} else {
 #ifdef CONFIG_SMP
-		cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_CASC_STARTING,
-					  "AP_IRQ_ARMADA_CASC_STARTING",
+		cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_ARMADA_XP_STARTING,
+					  "irqchip/armada/cascade:starting",
 					  mpic_cascaded_starting_cpu, NULL);
 #endif
 		irq_set_chained_handler(parent_irq,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-bcm2836.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-bcm2836.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-bcm2836.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-bcm2836.c	2017-02-12 16:03:20.000000000 -0500
@@ -245,7 +245,7 @@ bcm2836_arm_irqchip_smp_init(void)
 #ifdef CONFIG_SMP
 	/* Unmask IPIs to the boot CPU. */
 	cpuhp_setup_state(CPUHP_AP_IRQ_BCM2836_STARTING,
-			  "AP_IRQ_BCM2836_STARTING", bcm2836_cpu_starting,
+			  "irqchip/bcm2836:starting", bcm2836_cpu_starting,
 			  bcm2836_cpu_dying);
 
 	set_smp_cross_call(bcm2836_arm_irqchip_send_ipi);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-bcm7038-l1.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-bcm7038-l1.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-bcm7038-l1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-bcm7038-l1.c	2017-02-12 16:03:20.000000000 -0500
@@ -215,6 +215,31 @@ static int bcm7038_l1_set_affinity(struc
 	return 0;
 }
 
+static void bcm7038_l1_cpu_offline(struct irq_data *d)
+{
+	struct cpumask *mask = irq_data_get_affinity_mask(d);
+	int cpu = smp_processor_id();
+	cpumask_t new_affinity;
+
+	/* This CPU was not on the affinity mask */
+	if (!cpumask_test_cpu(cpu, mask))
+		return;
+
+	if (cpumask_weight(mask) > 1) {
+		/*
+		 * Multiple CPU affinity, remove this CPU from the affinity
+		 * mask
+		 */
+		cpumask_copy(&new_affinity, mask);
+		cpumask_clear_cpu(cpu, &new_affinity);
+	} else {
+		/* Only CPU, put on the lowest online CPU */
+		cpumask_clear(&new_affinity);
+		cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
+	}
+	irq_set_affinity_locked(d, &new_affinity, false);
+}
+
 static int __init bcm7038_l1_init_one(struct device_node *dn,
 				      unsigned int idx,
 				      struct bcm7038_l1_chip *intc)
@@ -266,6 +291,7 @@ static struct irq_chip bcm7038_l1_irq_ch
 	.irq_mask		= bcm7038_l1_mask,
 	.irq_unmask		= bcm7038_l1_unmask,
 	.irq_set_affinity	= bcm7038_l1_set_affinity,
+	.irq_cpu_offline	= bcm7038_l1_cpu_offline,
 };
 
 static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-gic.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-gic.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-gic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-gic.c	2017-02-12 16:03:20.000000000 -0500
@@ -1191,7 +1191,7 @@ static int __init __gic_init_bases(struc
 		set_smp_cross_call(gic_raise_softirq);
 #endif
 		cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
-					  "AP_IRQ_GIC_STARTING",
+					  "irqchip/arm/gic:starting",
 					  gic_starting_cpu, NULL);
 		set_handle_irq(gic_handle_irq);
 		if (static_key_true(&supports_deactivate))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-gic-v3.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-gic-v3.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-gic-v3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-gic-v3.c	2017-02-12 16:03:20.000000000 -0500
@@ -120,11 +120,10 @@ static void gic_redist_wait_for_rwp(void
 }
 
 #ifdef CONFIG_ARM64
-static DEFINE_STATIC_KEY_FALSE(is_cavium_thunderx);
 
 static u64 __maybe_unused gic_read_iar(void)
 {
-	if (static_branch_unlikely(&is_cavium_thunderx))
+	if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_23154))
 		return gic_read_iar_cavium_thunderx();
 	else
 		return gic_read_iar_common();
@@ -633,9 +632,9 @@ static void gic_raise_softirq(const stru
 static void gic_smp_init(void)
 {
 	set_smp_cross_call(gic_raise_softirq);
-	cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GICV3_STARTING,
-				  "AP_IRQ_GICV3_STARTING", gic_starting_cpu,
-				  NULL);
+	cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_GIC_STARTING,
+				  "irqchip/arm/gicv3:starting",
+				  gic_starting_cpu, NULL);
 }
 
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
@@ -905,14 +904,6 @@ static const struct irq_domain_ops parti
 	.select = gic_irq_domain_select,
 };
 
-static void gicv3_enable_quirks(void)
-{
-#ifdef CONFIG_ARM64
-	if (cpus_have_cap(ARM64_WORKAROUND_CAVIUM_23154))
-		static_branch_enable(&is_cavium_thunderx);
-#endif
-}
-
 static int __init gic_init_bases(void __iomem *dist_base,
 				 struct redist_region *rdist_regs,
 				 u32 nr_redist_regions,
@@ -935,8 +926,6 @@ static int __init gic_init_bases(void __
 	gic_data.nr_redist_regions = nr_redist_regions;
 	gic_data.redist_stride = redist_stride;
 
-	gicv3_enable_quirks();
-
 	/*
 	 * Find out how many interrupts are supported.
 	 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-gic-v3-its.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-gic-v3-its.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-gic-v3-its.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-gic-v3-its.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,6 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/arm-gic-v3.h>
 
-#include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <asm/exception.h>
 
@@ -196,7 +195,7 @@ typedef struct its_collection *(*its_cmd
 
 static void its_encode_cmd(struct its_cmd_block *cmd, u8 cmd_nr)
 {
-	cmd->raw_cmd[0] &= ~0xffUL;
+	cmd->raw_cmd[0] &= ~0xffULL;
 	cmd->raw_cmd[0] |= cmd_nr;
 }
 
@@ -208,43 +207,43 @@ static void its_encode_devid(struct its_
 
 static void its_encode_event_id(struct its_cmd_block *cmd, u32 id)
 {
-	cmd->raw_cmd[1] &= ~0xffffffffUL;
+	cmd->raw_cmd[1] &= ~0xffffffffULL;
 	cmd->raw_cmd[1] |= id;
 }
 
 static void its_encode_phys_id(struct its_cmd_block *cmd, u32 phys_id)
 {
-	cmd->raw_cmd[1] &= 0xffffffffUL;
+	cmd->raw_cmd[1] &= 0xffffffffULL;
 	cmd->raw_cmd[1] |= ((u64)phys_id) << 32;
 }
 
 static void its_encode_size(struct its_cmd_block *cmd, u8 size)
 {
-	cmd->raw_cmd[1] &= ~0x1fUL;
+	cmd->raw_cmd[1] &= ~0x1fULL;
 	cmd->raw_cmd[1] |= size & 0x1f;
 }
 
 static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr)
 {
-	cmd->raw_cmd[2] &= ~0xffffffffffffUL;
-	cmd->raw_cmd[2] |= itt_addr & 0xffffffffff00UL;
+	cmd->raw_cmd[2] &= ~0xffffffffffffULL;
+	cmd->raw_cmd[2] |= itt_addr & 0xffffffffff00ULL;
 }
 
 static void its_encode_valid(struct its_cmd_block *cmd, int valid)
 {
-	cmd->raw_cmd[2] &= ~(1UL << 63);
+	cmd->raw_cmd[2] &= ~(1ULL << 63);
 	cmd->raw_cmd[2] |= ((u64)!!valid) << 63;
 }
 
 static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr)
 {
-	cmd->raw_cmd[2] &= ~(0xffffffffUL << 16);
-	cmd->raw_cmd[2] |= (target_addr & (0xffffffffUL << 16));
+	cmd->raw_cmd[2] &= ~(0xffffffffULL << 16);
+	cmd->raw_cmd[2] |= (target_addr & (0xffffffffULL << 16));
 }
 
 static void its_encode_collection(struct its_cmd_block *cmd, u16 col)
 {
-	cmd->raw_cmd[2] &= ~0xffffUL;
+	cmd->raw_cmd[2] &= ~0xffffULL;
 	cmd->raw_cmd[2] |= col;
 }
 
@@ -433,7 +432,7 @@ static void its_flush_cmd(struct its_nod
 	 * the ITS.
 	 */
 	if (its->flags & ITS_FLAGS_CMDQ_NEEDS_FLUSHING)
-		__flush_dcache_area(cmd, sizeof(*cmd));
+		gic_flush_dcache_to_poc(cmd, sizeof(*cmd));
 	else
 		dsb(ishst);
 }
@@ -602,7 +601,7 @@ static void lpi_set_config(struct irq_da
 	 * Humpf...
 	 */
 	if (gic_rdists->flags & RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING)
-		__flush_dcache_area(cfg, sizeof(*cfg));
+		gic_flush_dcache_to_poc(cfg, sizeof(*cfg));
 	else
 		dsb(ishst);
 	its_send_inv(its_dev, id);
@@ -657,8 +656,8 @@ static void its_irq_compose_msi_msg(stru
 	its = its_dev->its;
 	addr = its->phys_base + GITS_TRANSLATER;
 
-	msg->address_lo		= addr & ((1UL << 32) - 1);
-	msg->address_hi		= addr >> 32;
+	msg->address_lo		= lower_32_bits(addr);
+	msg->address_hi		= upper_32_bits(addr);
 	msg->data		= its_get_event_id(d);
 
 	iommu_dma_map_msi_msg(d->irq, msg);
@@ -817,7 +816,7 @@ static int __init its_alloc_lpi_tables(v
 	       LPI_PROPBASE_SZ);
 
 	/* Make sure the GIC will observe the written configuration */
-	__flush_dcache_area(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
+	gic_flush_dcache_to_poc(page_address(gic_rdists->prop_page), LPI_PROPBASE_SZ);
 
 	return 0;
 }
@@ -836,7 +835,7 @@ static u64 its_read_baser(struct its_nod
 {
 	u32 idx = baser - its->tables;
 
-	return readq_relaxed(its->base + GITS_BASER + (idx << 3));
+	return gits_read_baser(its->base + GITS_BASER + (idx << 3));
 }
 
 static void its_write_baser(struct its_node *its, struct its_baser *baser,
@@ -844,7 +843,7 @@ static void its_write_baser(struct its_n
 {
 	u32 idx = baser - its->tables;
 
-	writeq_relaxed(val, its->base + GITS_BASER + (idx << 3));
+	gits_write_baser(val, its->base + GITS_BASER + (idx << 3));
 	baser->val = its_read_baser(its, baser);
 }
 
@@ -910,7 +909,7 @@ retry_baser:
 		shr = tmp & GITS_BASER_SHAREABILITY_MASK;
 		if (!shr) {
 			cache = GITS_BASER_nC;
-			__flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
+			gic_flush_dcache_to_poc(base, PAGE_ORDER_TO_SIZE(order));
 		}
 		goto retry_baser;
 	}
@@ -935,9 +934,9 @@ retry_baser:
 	}
 
 	if (val != tmp) {
-		pr_err("ITS@%pa: %s doesn't stick: %lx %lx\n",
+		pr_err("ITS@%pa: %s doesn't stick: %llx %llx\n",
 		       &its->phys_base, its_base_type_string[type],
-		       (unsigned long) val, (unsigned long) tmp);
+		       val, tmp);
 		free_pages((unsigned long)base, order);
 		return -ENXIO;
 	}
@@ -948,7 +947,7 @@ retry_baser:
 	tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
 
 	pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
-		&its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / tmp),
+		&its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / (int)tmp),
 		its_base_type_string[type],
 		(unsigned long)virt_to_phys(base),
 		indirect ? "indirect" : "flat", (int)esz,
@@ -983,7 +982,7 @@ static bool its_parse_baser_device(struc
 			 * which is reported by ITS hardware times lvl1 table
 			 * entry size.
 			 */
-			ids -= ilog2(psz / esz);
+			ids -= ilog2(psz / (int)esz);
 			esz = GITS_LVL1_ENTRY_SIZE;
 		}
 	}
@@ -998,7 +997,7 @@ static bool its_parse_baser_device(struc
 	new_order = max_t(u32, get_order(esz << ids), new_order);
 	if (new_order >= MAX_ORDER) {
 		new_order = MAX_ORDER - 1;
-		ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / esz);
+		ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
 		pr_warn("ITS@%pa: Device Table too large, reduce ids %u->%u\n",
 			&its->phys_base, its->device_ids, ids);
 	}
@@ -1102,7 +1101,7 @@ static void its_cpu_init_lpis(void)
 		}
 
 		/* Make sure the GIC will observe the zero-ed page */
-		__flush_dcache_area(page_address(pend_page), LPI_PENDBASE_SZ);
+		gic_flush_dcache_to_poc(page_address(pend_page), LPI_PENDBASE_SZ);
 
 		paddr = page_to_phys(pend_page);
 		pr_info("CPU%d: using LPI pending table @%pa\n",
@@ -1126,8 +1125,8 @@ static void its_cpu_init_lpis(void)
 	       GICR_PROPBASER_WaWb |
 	       ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK));
 
-	writeq_relaxed(val, rbase + GICR_PROPBASER);
-	tmp = readq_relaxed(rbase + GICR_PROPBASER);
+	gicr_write_propbaser(val, rbase + GICR_PROPBASER);
+	tmp = gicr_read_propbaser(rbase + GICR_PROPBASER);
 
 	if ((tmp ^ val) & GICR_PROPBASER_SHAREABILITY_MASK) {
 		if (!(tmp & GICR_PROPBASER_SHAREABILITY_MASK)) {
@@ -1139,7 +1138,7 @@ static void its_cpu_init_lpis(void)
 			val &= ~(GICR_PROPBASER_SHAREABILITY_MASK |
 				 GICR_PROPBASER_CACHEABILITY_MASK);
 			val |= GICR_PROPBASER_nC;
-			writeq_relaxed(val, rbase + GICR_PROPBASER);
+			gicr_write_propbaser(val, rbase + GICR_PROPBASER);
 		}
 		pr_info_once("GIC: using cache flushing for LPI property table\n");
 		gic_rdists->flags |= RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING;
@@ -1150,8 +1149,8 @@ static void its_cpu_init_lpis(void)
 	       GICR_PENDBASER_InnerShareable |
 	       GICR_PENDBASER_WaWb);
 
-	writeq_relaxed(val, rbase + GICR_PENDBASER);
-	tmp = readq_relaxed(rbase + GICR_PENDBASER);
+	gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
+	tmp = gicr_read_pendbaser(rbase + GICR_PENDBASER);
 
 	if (!(tmp & GICR_PENDBASER_SHAREABILITY_MASK)) {
 		/*
@@ -1161,7 +1160,7 @@ static void its_cpu_init_lpis(void)
 		val &= ~(GICR_PENDBASER_SHAREABILITY_MASK |
 			 GICR_PENDBASER_CACHEABILITY_MASK);
 		val |= GICR_PENDBASER_nC;
-		writeq_relaxed(val, rbase + GICR_PENDBASER);
+		gicr_write_pendbaser(val, rbase + GICR_PENDBASER);
 	}
 
 	/* Enable LPIs */
@@ -1287,13 +1286,13 @@ static bool its_alloc_device_table(struc
 
 		/* Flush Lvl2 table to PoC if hw doesn't support coherency */
 		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
-			__flush_dcache_area(page_address(page), baser->psz);
+			gic_flush_dcache_to_poc(page_address(page), baser->psz);
 
 		table[idx] = cpu_to_le64(page_to_phys(page) | GITS_BASER_VALID);
 
 		/* Flush Lvl1 entry to PoC if hw doesn't support coherency */
 		if (!(baser->val & GITS_BASER_SHAREABILITY_MASK))
-			__flush_dcache_area(table + idx, GITS_LVL1_ENTRY_SIZE);
+			gic_flush_dcache_to_poc(table + idx, GITS_LVL1_ENTRY_SIZE);
 
 		/* Ensure updated table contents are visible to ITS hardware */
 		dsb(sy);
@@ -1340,7 +1339,7 @@ static struct its_device *its_create_dev
 		return NULL;
 	}
 
-	__flush_dcache_area(itt, sz);
+	gic_flush_dcache_to_poc(itt, sz);
 
 	dev->its = its;
 	dev->itt = itt;
@@ -1717,8 +1716,8 @@ static int __init its_probe_one(struct r
 		 (ITS_CMD_QUEUE_SZ / SZ_4K - 1)	|
 		 GITS_CBASER_VALID);
 
-	writeq_relaxed(baser, its->base + GITS_CBASER);
-	tmp = readq_relaxed(its->base + GITS_CBASER);
+	gits_write_cbaser(baser, its->base + GITS_CBASER);
+	tmp = gits_read_cbaser(its->base + GITS_CBASER);
 
 	if ((tmp ^ baser) & GITS_CBASER_SHAREABILITY_MASK) {
 		if (!(tmp & GITS_CBASER_SHAREABILITY_MASK)) {
@@ -1730,13 +1729,13 @@ static int __init its_probe_one(struct r
 			baser &= ~(GITS_CBASER_SHAREABILITY_MASK |
 				   GITS_CBASER_CACHEABILITY_MASK);
 			baser |= GITS_CBASER_nC;
-			writeq_relaxed(baser, its->base + GITS_CBASER);
+			gits_write_cbaser(baser, its->base + GITS_CBASER);
 		}
 		pr_info("ITS: using cache flushing for cmd queue\n");
 		its->flags |= ITS_FLAGS_CMDQ_NEEDS_FLUSHING;
 	}
 
-	writeq_relaxed(0, its->base + GITS_CWRITER);
+	gits_write_cwriter(0, its->base + GITS_CWRITER);
 	writel_relaxed(GITS_CTLR_ENABLE, its->base + GITS_CTLR);
 
 	err = its_init_domain(handle, its);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-hip04.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-hip04.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-hip04.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-hip04.c	2017-02-12 16:03:20.000000000 -0500
@@ -407,7 +407,7 @@ hip04_of_init(struct device_node *node,
 	set_handle_irq(hip04_handle_irq);
 
 	hip04_irq_dist_init(&hip04_data);
-	cpuhp_setup_state(CPUHP_AP_IRQ_HIP04_STARTING, "AP_IRQ_HIP04_STARTING",
+	cpuhp_setup_state(CPUHP_AP_IRQ_HIP04_STARTING, "irqchip/hip04:starting",
 			  hip04_irq_starting_cpu, NULL);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-keystone.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-keystone.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-keystone.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-keystone.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,9 +19,9 @@
 #include <linux/bitops.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irqchip.h>
-#include <linux/irqchip/chained_irq.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mfd/syscon.h>
@@ -39,6 +39,7 @@ struct keystone_irq_device {
 	struct irq_domain	*irqd;
 	struct regmap		*devctrl_regs;
 	u32			devctrl_offset;
+	raw_spinlock_t		wa_lock;
 };
 
 static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq)
@@ -83,17 +84,15 @@ static void keystone_irq_ack(struct irq_
 	/* nothing to do here */
 }
 
-static void keystone_irq_handler(struct irq_desc *desc)
+static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq)
 {
-	unsigned int irq = irq_desc_get_irq(desc);
-	struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc);
+	struct keystone_irq_device *kirq = keystone_irq;
+	unsigned long wa_lock_flags;
 	unsigned long pending;
 	int src, virq;
 
 	dev_dbg(kirq->dev, "start irq %d\n", irq);
 
-	chained_irq_enter(irq_desc_get_chip(desc), desc);
-
 	pending = keystone_irq_readl(kirq);
 	keystone_irq_writel(kirq, pending);
 
@@ -111,13 +110,15 @@ static void keystone_irq_handler(struct
 			if (!virq)
 				dev_warn(kirq->dev, "spurious irq detected hwirq %d, virq %d\n",
 					 src, virq);
+			raw_spin_lock_irqsave(&kirq->wa_lock, wa_lock_flags);
 			generic_handle_irq(virq);
+			raw_spin_unlock_irqrestore(&kirq->wa_lock,
+						   wa_lock_flags);
 		}
 	}
 
-	chained_irq_exit(irq_desc_get_chip(desc), desc);
-
 	dev_dbg(kirq->dev, "end irq %d\n", irq);
+	return IRQ_HANDLED;
 }
 
 static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
@@ -182,9 +183,16 @@ static int keystone_irq_probe(struct pla
 		return -ENODEV;
 	}
 
+	raw_spin_lock_init(&kirq->wa_lock);
+
 	platform_set_drvdata(pdev, kirq);
 
-	irq_set_chained_handler_and_data(kirq->irq, keystone_irq_handler, kirq);
+	ret = request_irq(kirq->irq, keystone_irq_handler,
+			  0, dev_name(dev), kirq);
+	if (ret) {
+		irq_domain_remove(kirq->irqd);
+		return ret;
+	}
 
 	/* clear all source bits */
 	keystone_irq_writel(kirq, ~0x0);
@@ -199,6 +207,8 @@ static int keystone_irq_remove(struct pl
 	struct keystone_irq_device *kirq = platform_get_drvdata(pdev);
 	int hwirq;
 
+	free_irq(kirq->irq, kirq);
+
 	for (hwirq = 0; hwirq < KEYSTONE_N_IRQ; hwirq++)
 		irq_dispose_mapping(irq_find_mapping(kirq->irqd, hwirq));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-mips-gic.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-mips-gic.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-mips-gic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-mips-gic.c	2017-02-12 16:03:20.000000000 -0500
@@ -152,12 +152,12 @@ static inline void gic_map_to_vpe(unsign
 }
 
 #ifdef CONFIG_CLKSRC_MIPS_GIC
-cycle_t gic_read_count(void)
+u64 gic_read_count(void)
 {
 	unsigned int hi, hi2, lo;
 
 	if (mips_cm_is64)
-		return (cycle_t)gic_read(GIC_REG(SHARED, GIC_SH_COUNTER));
+		return (u64)gic_read(GIC_REG(SHARED, GIC_SH_COUNTER));
 
 	do {
 		hi = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
@@ -165,7 +165,7 @@ cycle_t gic_read_count(void)
 		hi2 = gic_read32(GIC_REG(SHARED, GIC_SH_COUNTER_63_32));
 	} while (hi2 != hi);
 
-	return (((cycle_t) hi) << 32) + lo;
+	return (((u64) hi) << 32) + lo;
 }
 
 unsigned int gic_get_count_width(void)
@@ -179,7 +179,7 @@ unsigned int gic_get_count_width(void)
 	return bits;
 }
 
-void gic_write_compare(cycle_t cnt)
+void gic_write_compare(u64 cnt)
 {
 	if (mips_cm_is64) {
 		gic_write(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE), cnt);
@@ -191,7 +191,7 @@ void gic_write_compare(cycle_t cnt)
 	}
 }
 
-void gic_write_cpu_compare(cycle_t cnt, int cpu)
+void gic_write_cpu_compare(u64 cnt, int cpu)
 {
 	unsigned long flags;
 
@@ -211,17 +211,17 @@ void gic_write_cpu_compare(cycle_t cnt,
 	local_irq_restore(flags);
 }
 
-cycle_t gic_read_compare(void)
+u64 gic_read_compare(void)
 {
 	unsigned int hi, lo;
 
 	if (mips_cm_is64)
-		return (cycle_t)gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE));
+		return (u64)gic_read(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE));
 
 	hi = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI));
 	lo = gic_read32(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO));
 
-	return (((cycle_t) hi) << 32) + lo;
+	return (((u64) hi) << 32) + lo;
 }
 
 void gic_start_count(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-mxs.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-mxs.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-mxs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-mxs.c	2017-02-12 16:03:20.000000000 -0500
@@ -131,12 +131,16 @@ static struct irq_chip mxs_icoll_chip =
 	.irq_ack = icoll_ack_irq,
 	.irq_mask = icoll_mask_irq,
 	.irq_unmask = icoll_unmask_irq,
+	.flags = IRQCHIP_MASK_ON_SUSPEND |
+		 IRQCHIP_SKIP_SET_WAKE,
 };
 
 static struct irq_chip asm9260_icoll_chip = {
 	.irq_ack = icoll_ack_irq,
 	.irq_mask = asm9260_mask_irq,
 	.irq_unmask = asm9260_unmask_irq,
+	.flags = IRQCHIP_MASK_ON_SUSPEND |
+		 IRQCHIP_SKIP_SET_WAKE,
 };
 
 asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-st.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-st.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-st.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-st.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,7 +180,7 @@ static int st_irq_syscfg_probe(struct pl
 	return st_irq_syscfg_enable(pdev);
 }
 
-static int st_irq_syscfg_resume(struct device *dev)
+static int __maybe_unused st_irq_syscfg_resume(struct device *dev)
 {
 	struct st_irq_syscfg *ddata = dev_get_drvdata(dev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/irq-xilinx-intc.c linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-xilinx-intc.c
--- linux-libre-4.9-gnu/drivers/irqchip/irq-xilinx-intc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/irq-xilinx-intc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007-2013 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012-2013 Xilinx, Inc.
+ * Copyright (C) 2007-2009 PetaLogix
+ * Copyright (C) 2006 Atmark Techno, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/jump_label.h>
+#include <linux/bug.h>
+#include <linux/of_irq.h>
+
+/* No one else should require these constants, so define them locally here. */
+#define ISR 0x00			/* Interrupt Status Register */
+#define IPR 0x04			/* Interrupt Pending Register */
+#define IER 0x08			/* Interrupt Enable Register */
+#define IAR 0x0c			/* Interrupt Acknowledge Register */
+#define SIE 0x10			/* Set Interrupt Enable bits */
+#define CIE 0x14			/* Clear Interrupt Enable bits */
+#define IVR 0x18			/* Interrupt Vector Register */
+#define MER 0x1c			/* Master Enable Register */
+
+#define MER_ME (1<<0)
+#define MER_HIE (1<<1)
+
+static DEFINE_STATIC_KEY_FALSE(xintc_is_be);
+
+struct xintc_irq_chip {
+	void		__iomem *base;
+	struct		irq_domain *root_domain;
+	u32		intr_mask;
+};
+
+static struct xintc_irq_chip *xintc_irqc;
+
+static void xintc_write(int reg, u32 data)
+{
+	if (static_branch_unlikely(&xintc_is_be))
+		iowrite32be(data, xintc_irqc->base + reg);
+	else
+		iowrite32(data, xintc_irqc->base + reg);
+}
+
+static unsigned int xintc_read(int reg)
+{
+	if (static_branch_unlikely(&xintc_is_be))
+		return ioread32be(xintc_irqc->base + reg);
+	else
+		return ioread32(xintc_irqc->base + reg);
+}
+
+static void intc_enable_or_unmask(struct irq_data *d)
+{
+	unsigned long mask = 1 << d->hwirq;
+
+	pr_debug("irq-xilinx: enable_or_unmask: %ld\n", d->hwirq);
+
+	/* ack level irqs because they can't be acked during
+	 * ack function since the handle_level_irq function
+	 * acks the irq before calling the interrupt handler
+	 */
+	if (irqd_is_level_type(d))
+		xintc_write(IAR, mask);
+
+	xintc_write(SIE, mask);
+}
+
+static void intc_disable_or_mask(struct irq_data *d)
+{
+	pr_debug("irq-xilinx: disable: %ld\n", d->hwirq);
+	xintc_write(CIE, 1 << d->hwirq);
+}
+
+static void intc_ack(struct irq_data *d)
+{
+	pr_debug("irq-xilinx: ack: %ld\n", d->hwirq);
+	xintc_write(IAR, 1 << d->hwirq);
+}
+
+static void intc_mask_ack(struct irq_data *d)
+{
+	unsigned long mask = 1 << d->hwirq;
+
+	pr_debug("irq-xilinx: disable_and_ack: %ld\n", d->hwirq);
+	xintc_write(CIE, mask);
+	xintc_write(IAR, mask);
+}
+
+static struct irq_chip intc_dev = {
+	.name = "Xilinx INTC",
+	.irq_unmask = intc_enable_or_unmask,
+	.irq_mask = intc_disable_or_mask,
+	.irq_ack = intc_ack,
+	.irq_mask_ack = intc_mask_ack,
+};
+
+unsigned int xintc_get_irq(void)
+{
+	unsigned int hwirq, irq = -1;
+
+	hwirq = xintc_read(IVR);
+	if (hwirq != -1U)
+		irq = irq_find_mapping(xintc_irqc->root_domain, hwirq);
+
+	pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
+
+	return irq;
+}
+
+static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+	if (xintc_irqc->intr_mask & (1 << hw)) {
+		irq_set_chip_and_handler_name(irq, &intc_dev,
+						handle_edge_irq, "edge");
+		irq_clear_status_flags(irq, IRQ_LEVEL);
+	} else {
+		irq_set_chip_and_handler_name(irq, &intc_dev,
+						handle_level_irq, "level");
+		irq_set_status_flags(irq, IRQ_LEVEL);
+	}
+	return 0;
+}
+
+static const struct irq_domain_ops xintc_irq_domain_ops = {
+	.xlate = irq_domain_xlate_onetwocell,
+	.map = xintc_map,
+};
+
+static void xil_intc_irq_handler(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	u32 pending;
+
+	chained_irq_enter(chip, desc);
+	do {
+		pending = xintc_get_irq();
+		if (pending == -1U)
+			break;
+		generic_handle_irq(pending);
+	} while (true);
+	chained_irq_exit(chip, desc);
+}
+
+static int __init xilinx_intc_of_init(struct device_node *intc,
+					     struct device_node *parent)
+{
+	u32 nr_irq;
+	int ret, irq;
+	struct xintc_irq_chip *irqc;
+
+	if (xintc_irqc) {
+		pr_err("irq-xilinx: Multiple instances aren't supported\n");
+		return -EINVAL;
+	}
+
+	irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
+	if (!irqc)
+		return -ENOMEM;
+
+	xintc_irqc = irqc;
+
+	irqc->base = of_iomap(intc, 0);
+	BUG_ON(!irqc->base);
+
+	ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
+	if (ret < 0) {
+		pr_err("irq-xilinx: unable to read xlnx,num-intr-inputs\n");
+		goto err_alloc;
+	}
+
+	ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &irqc->intr_mask);
+	if (ret < 0) {
+		pr_warn("irq-xilinx: unable to read xlnx,kind-of-intr\n");
+		irqc->intr_mask = 0;
+	}
+
+	if (irqc->intr_mask >> nr_irq)
+		pr_warn("irq-xilinx: mismatch in kind-of-intr param\n");
+
+	pr_info("irq-xilinx: %s: num_irq=%d, edge=0x%x\n",
+		intc->full_name, nr_irq, irqc->intr_mask);
+
+
+	/*
+	 * Disable all external interrupts until they are
+	 * explicity requested.
+	 */
+	xintc_write(IER, 0);
+
+	/* Acknowledge any pending interrupts just in case. */
+	xintc_write(IAR, 0xffffffff);
+
+	/* Turn on the Master Enable. */
+	xintc_write(MER, MER_HIE | MER_ME);
+	if (!(xintc_read(MER) & (MER_HIE | MER_ME))) {
+		static_branch_enable(&xintc_is_be);
+		xintc_write(MER, MER_HIE | MER_ME);
+	}
+
+	irqc->root_domain = irq_domain_add_linear(intc, nr_irq,
+						  &xintc_irq_domain_ops, irqc);
+	if (!irqc->root_domain) {
+		pr_err("irq-xilinx: Unable to create IRQ domain\n");
+		goto err_alloc;
+	}
+
+	if (parent) {
+		irq = irq_of_parse_and_map(intc, 0);
+		if (irq) {
+			irq_set_chained_handler_and_data(irq,
+							 xil_intc_irq_handler,
+							 irqc);
+		} else {
+			pr_err("irq-xilinx: interrupts property not in DT\n");
+			ret = -EINVAL;
+			goto err_alloc;
+		}
+	} else {
+		irq_set_default_host(irqc->root_domain);
+	}
+
+	return 0;
+
+err_alloc:
+	xintc_irqc = NULL;
+	kfree(irqc);
+	return ret;
+
+}
+
+IRQCHIP_DECLARE(xilinx_intc_xps, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
+IRQCHIP_DECLARE(xilinx_intc_opb, "xlnx,opb-intc-1.00.c", xilinx_intc_of_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/Kconfig linux-libre-4.10-rc8-gnu/drivers/irqchip/Kconfig
--- linux-libre-4.9-gnu/drivers/irqchip/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -211,6 +211,10 @@ config XTENSA_MX
 	bool
 	select IRQ_DOMAIN
 
+config XILINX_INTC
+	bool
+	select IRQ_DOMAIN
+
 config IRQ_CROSSBAR
 	bool
 	help
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/irqchip/Makefile linux-libre-4.10-rc8-gnu/drivers/irqchip/Makefile
--- linux-libre-4.9-gnu/drivers/irqchip/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/irqchip/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -52,6 +52,7 @@ obj-$(CONFIG_TB10X_IRQC)		+= irq-tb10x.o
 obj-$(CONFIG_TS4800_IRQ)		+= irq-ts4800.o
 obj-$(CONFIG_XTENSA)			+= irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)			+= irq-xtensa-mx.o
+obj-$(CONFIG_XILINX_INTC)		+= irq-xilinx-intc.o
 obj-$(CONFIG_IRQ_CROSSBAR)		+= irq-crossbar.o
 obj-$(CONFIG_SOC_VF610)			+= irq-vf610-mscm-ir.o
 obj-$(CONFIG_BCM6345_L1_IRQ)		+= irq-bcm6345-l1.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/capi/kcapi.c linux-libre-4.10-rc8-gnu/drivers/isdn/capi/kcapi.c
--- linux-libre-4.9-gnu/drivers/isdn/capi/kcapi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/capi/kcapi.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/isdn/capicmd.h>
 #include <linux/isdn/capiutil.h>
 #ifdef AVMB1_COMPAT
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/gigaset/bas-gigaset.c linux-libre-4.10-rc8-gnu/drivers/isdn/gigaset/bas-gigaset.c
--- linux-libre-4.9-gnu/drivers/isdn/gigaset/bas-gigaset.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/gigaset/bas-gigaset.c	2017-02-12 16:03:20.000000000 -0500
@@ -2565,22 +2565,22 @@ static int gigaset_post_reset(struct usb
 
 
 static const struct gigaset_ops gigops = {
-	gigaset_write_cmd,
-	gigaset_write_room,
-	gigaset_chars_in_buffer,
-	gigaset_brkchars,
-	gigaset_init_bchannel,
-	gigaset_close_bchannel,
-	gigaset_initbcshw,
-	gigaset_freebcshw,
-	gigaset_reinitbcshw,
-	gigaset_initcshw,
-	gigaset_freecshw,
-	gigaset_set_modem_ctrl,
-	gigaset_baud_rate,
-	gigaset_set_line_ctrl,
-	gigaset_isoc_send_skb,
-	gigaset_isoc_input,
+	.write_cmd = gigaset_write_cmd,
+	.write_room = gigaset_write_room,
+	.chars_in_buffer = gigaset_chars_in_buffer,
+	.brkchars = gigaset_brkchars,
+	.init_bchannel = gigaset_init_bchannel,
+	.close_bchannel = gigaset_close_bchannel,
+	.initbcshw = gigaset_initbcshw,
+	.freebcshw = gigaset_freebcshw,
+	.reinitbcshw = gigaset_reinitbcshw,
+	.initcshw = gigaset_initcshw,
+	.freecshw = gigaset_freecshw,
+	.set_modem_ctrl = gigaset_set_modem_ctrl,
+	.baud_rate = gigaset_baud_rate,
+	.set_line_ctrl = gigaset_set_line_ctrl,
+	.send_skb = gigaset_isoc_send_skb,
+	.handle_input = gigaset_isoc_input,
 };
 
 /* bas_gigaset_init
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/gigaset/ser-gigaset.c linux-libre-4.10-rc8-gnu/drivers/isdn/gigaset/ser-gigaset.c
--- linux-libre-4.9-gnu/drivers/isdn/gigaset/ser-gigaset.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/gigaset/ser-gigaset.c	2017-02-12 16:03:20.000000000 -0500
@@ -445,22 +445,22 @@ static int gigaset_set_line_ctrl(struct
 }
 
 static const struct gigaset_ops ops = {
-	gigaset_write_cmd,
-	gigaset_write_room,
-	gigaset_chars_in_buffer,
-	gigaset_brkchars,
-	gigaset_init_bchannel,
-	gigaset_close_bchannel,
-	gigaset_initbcshw,
-	gigaset_freebcshw,
-	gigaset_reinitbcshw,
-	gigaset_initcshw,
-	gigaset_freecshw,
-	gigaset_set_modem_ctrl,
-	gigaset_baud_rate,
-	gigaset_set_line_ctrl,
-	gigaset_m10x_send_skb,	/* asyncdata.c */
-	gigaset_m10x_input,	/* asyncdata.c */
+	.write_cmd = gigaset_write_cmd,
+	.write_room = gigaset_write_room,
+	.chars_in_buffer = gigaset_chars_in_buffer,
+	.brkchars = gigaset_brkchars,
+	.init_bchannel = gigaset_init_bchannel,
+	.close_bchannel = gigaset_close_bchannel,
+	.initbcshw = gigaset_initbcshw,
+	.freebcshw = gigaset_freebcshw,
+	.reinitbcshw = gigaset_reinitbcshw,
+	.initcshw = gigaset_initcshw,
+	.freecshw = gigaset_freecshw,
+	.set_modem_ctrl = gigaset_set_modem_ctrl,
+	.baud_rate = gigaset_baud_rate,
+	.set_line_ctrl = gigaset_set_line_ctrl,
+	.send_skb = gigaset_m10x_send_skb,	/* asyncdata.c */
+	.handle_input = gigaset_m10x_input,	/* asyncdata.c */
 };
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/gigaset/usb-gigaset.c linux-libre-4.10-rc8-gnu/drivers/isdn/gigaset/usb-gigaset.c
--- linux-libre-4.9-gnu/drivers/isdn/gigaset/usb-gigaset.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/gigaset/usb-gigaset.c	2017-02-12 16:03:20.000000000 -0500
@@ -862,22 +862,22 @@ static int gigaset_pre_reset(struct usb_
 }
 
 static const struct gigaset_ops ops = {
-	gigaset_write_cmd,
-	gigaset_write_room,
-	gigaset_chars_in_buffer,
-	gigaset_brkchars,
-	gigaset_init_bchannel,
-	gigaset_close_bchannel,
-	gigaset_initbcshw,
-	gigaset_freebcshw,
-	gigaset_reinitbcshw,
-	gigaset_initcshw,
-	gigaset_freecshw,
-	gigaset_set_modem_ctrl,
-	gigaset_baud_rate,
-	gigaset_set_line_ctrl,
-	gigaset_m10x_send_skb,
-	gigaset_m10x_input,
+	.write_cmd = gigaset_write_cmd,
+	.write_room = gigaset_write_room,
+	.chars_in_buffer = gigaset_chars_in_buffer,
+	.brkchars = gigaset_brkchars,
+	.init_bchannel = gigaset_init_bchannel,
+	.close_bchannel = gigaset_close_bchannel,
+	.initbcshw = gigaset_initbcshw,
+	.freebcshw = gigaset_freebcshw,
+	.reinitbcshw = gigaset_reinitbcshw,
+	.initcshw = gigaset_initcshw,
+	.freecshw = gigaset_freecshw,
+	.set_modem_ctrl = gigaset_set_modem_ctrl,
+	.baud_rate = gigaset_baud_rate,
+	.set_line_ctrl = gigaset_set_line_ctrl,
+	.send_skb = gigaset_m10x_send_skb,
+	.handle_input = gigaset_m10x_input,
 };
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/avm/b1.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/avm/b1.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/avm/b1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/avm/b1.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/slab.h>
 #include <asm/io.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/netdevice.h>
 #include <linux/isdn/capilli.h>
 #include "avmcard.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/avm/b1dma.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/avm/b1dma.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/avm/b1dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/avm/b1dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/gfp.h>
 #include <asm/io.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/netdevice.h>
 #include <linux/isdn/capilli.h>
 #include "avmcard.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/avm/c4.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/avm/c4.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/avm/c4.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/avm/c4.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/init.h>
 #include <linux/gfp.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/netdevice.h>
 #include <linux/isdn/capicmd.h>
 #include <linux/isdn/capiutil.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/capimain.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/capimain.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/capimain.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/capimain.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/seq_file.h>
 #include <linux/skbuff.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divamnt.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divamnt.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divamnt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divamnt.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "platform.h"
 #include "di_defs.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divasi.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divasi.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divasi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divasi.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,7 @@
 #include <linux/proc_fs.h>
 #include <linux/skbuff.h>
 #include <linux/seq_file.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "platform.h"
 #include "di_defs.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divasmain.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divasmain.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divasmain.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divasmain.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divasproc.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divasproc.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/divasproc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/divasproc.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/list.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "platform.h"
 #include "debuglib.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/message.c linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/message.c
--- linux-libre-4.9-gnu/drivers/isdn/hardware/eicon/message.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hardware/eicon/message.c	2017-02-12 16:03:20.000000000 -0500
@@ -11297,7 +11297,8 @@ static void mixer_notify_update(PLCI *pl
 				((CAPI_MSG *) msg)->header.ncci = 0;
 				((CAPI_MSG *) msg)->info.facility_req.Selector = SELECTOR_LINE_INTERCONNECT;
 				((CAPI_MSG *) msg)->info.facility_req.structs[0] = 3;
-				PUT_WORD(&(((CAPI_MSG *) msg)->info.facility_req.structs[1]), LI_REQ_SILENT_UPDATE);
+				((CAPI_MSG *) msg)->info.facility_req.structs[1] = LI_REQ_SILENT_UPDATE & 0xff;
+				((CAPI_MSG *) msg)->info.facility_req.structs[2] = LI_REQ_SILENT_UPDATE >> 8;
 				((CAPI_MSG *) msg)->info.facility_req.structs[3] = 0;
 				w = api_put(notify_plci->appl, (CAPI_MSG *) msg);
 				if (w != _QUEUE_FULL)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hisax/config.c linux-libre-4.10-rc8-gnu/drivers/isdn/hisax/config.c
--- linux-libre-4.9-gnu/drivers/isdn/hisax/config.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hisax/config.c	2017-02-12 16:03:20.000000000 -0500
@@ -659,7 +659,7 @@ int jiftime(char *s, long mark)
 
 static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
 
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt,
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt,
 		      va_list args)
 {
 	/* if head == NULL the fmt contains the full info */
@@ -669,23 +669,24 @@ void VHiSax_putstatus(struct IsdnCardSta
 	u_char		*p;
 	isdn_ctrl	ic;
 	int		len;
+	const u_char	*data;
 
 	if (!cs) {
 		printk(KERN_WARNING "HiSax: No CardStatus for message");
 		return;
 	}
 	spin_lock_irqsave(&cs->statlock, flags);
-	p = tmpbuf;
 	if (head) {
+		p = tmpbuf;
 		p += jiftime(p, jiffies);
 		p += sprintf(p, " %s", head);
 		p += vsprintf(p, fmt, args);
 		*p++ = '\n';
 		*p = 0;
 		len = p - tmpbuf;
-		p = tmpbuf;
+		data = tmpbuf;
 	} else {
-		p = fmt;
+		data = fmt;
 		len = strlen(fmt);
 	}
 	if (len > HISAX_STATUS_BUFSIZE) {
@@ -699,13 +700,12 @@ void VHiSax_putstatus(struct IsdnCardSta
 	if (i >= len)
 		i = len;
 	len -= i;
-	memcpy(cs->status_write, p, i);
+	memcpy(cs->status_write, data, i);
 	cs->status_write += i;
 	if (cs->status_write > cs->status_end)
 		cs->status_write = cs->status_buf;
-	p += i;
 	if (len) {
-		memcpy(cs->status_write, p, len);
+		memcpy(cs->status_write, data + i, len);
 		cs->status_write += len;
 	}
 #ifdef KERNELSTACK_DEBUG
@@ -729,7 +729,7 @@ void VHiSax_putstatus(struct IsdnCardSta
 	}
 }
 
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, ...)
 {
 	va_list args;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hisax/hisax.h linux-libre-4.10-rc8-gnu/drivers/isdn/hisax/hisax.h
--- linux-libre-4.9-gnu/drivers/isdn/hisax/hisax.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hisax/hisax.h	2017-02-12 16:03:20.000000000 -0500
@@ -1288,9 +1288,9 @@ int jiftime(char *s, long mark);
 int HiSax_command(isdn_ctrl *ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
 __printf(3, 4)
-void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, ...);
 __printf(3, 0)
-void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args);
 void HiSax_reportcard(int cardnr, int sel);
 int QuickHex(char *txt, u_char *p, int cnt);
 void LogFrame(struct IsdnCardState *cs, u_char *p, int size);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hisax/q931.c linux-libre-4.10-rc8-gnu/drivers/isdn/hisax/q931.c
--- linux-libre-4.9-gnu/drivers/isdn/hisax/q931.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hisax/q931.c	2017-02-12 16:03:20.000000000 -0500
@@ -855,7 +855,7 @@ struct DTag { /* Display tags */
 	{ 0x8c, "Reason" },
 	{ 0x8d, "Calling party name" },
 	{ 0x8e, "Called party name" },
-	{ 0x8f, "Orignal called name" },
+	{ 0x8f, "Original called name" },
 	{ 0x90, "Redirecting name" },
 	{ 0x91, "Connected name" },
 	{ 0x92, "Originating restrictions" },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hysdn/hysdn_boot.c linux-libre-4.10-rc8-gnu/drivers/isdn/hysdn/hysdn_boot.c
--- linux-libre-4.9-gnu/drivers/isdn/hysdn/hysdn_boot.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hysdn/hysdn_boot.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,7 +13,7 @@
 
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "hysdn_defs.h"
 #include "hysdn_pof.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/hysdn/hysdn_net.c linux-libre-4.10-rc8-gnu/drivers/isdn/hysdn/hysdn_net.c
--- linux-libre-4.9-gnu/drivers/isdn/hysdn/hysdn_net.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/hysdn/hysdn_net.c	2017-02-12 16:03:20.000000000 -0500
@@ -232,7 +232,6 @@ static const struct net_device_ops hysdn
 	.ndo_open		= net_open,
 	.ndo_stop		= net_close,
 	.ndo_start_xmit		= net_send_packet,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/i4l/isdn_concap.c linux-libre-4.10-rc8-gnu/drivers/isdn/i4l/isdn_concap.c
--- linux-libre-4.9-gnu/drivers/isdn/i4l/isdn_concap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/i4l/isdn_concap.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,9 +80,9 @@ static int isdn_concap_dl_disconn_req(st
 }
 
 struct concap_device_ops isdn_concap_reliable_dl_dops = {
-	&isdn_concap_dl_data_req,
-	&isdn_concap_dl_connect_req,
-	&isdn_concap_dl_disconn_req
+	.data_req = &isdn_concap_dl_data_req,
+	.connect_req = &isdn_concap_dl_connect_req,
+	.disconn_req = &isdn_concap_dl_disconn_req
 };
 
 /* The following should better go into a dedicated source file such that
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/isdn/i4l/isdn_x25iface.c linux-libre-4.10-rc8-gnu/drivers/isdn/i4l/isdn_x25iface.c
--- linux-libre-4.9-gnu/drivers/isdn/i4l/isdn_x25iface.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/isdn/i4l/isdn_x25iface.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,14 +53,14 @@ static int isdn_x25iface_disconn_ind(str
 
 
 static struct concap_proto_ops ix25_pops = {
-	&isdn_x25iface_proto_new,
-	&isdn_x25iface_proto_del,
-	&isdn_x25iface_proto_restart,
-	&isdn_x25iface_proto_close,
-	&isdn_x25iface_xmit,
-	&isdn_x25iface_receive,
-	&isdn_x25iface_connect_ind,
-	&isdn_x25iface_disconn_ind
+	.proto_new = &isdn_x25iface_proto_new,
+	.proto_del = &isdn_x25iface_proto_del,
+	.restart = &isdn_x25iface_proto_restart,
+	.close = &isdn_x25iface_proto_close,
+	.encap_and_xmit = &isdn_x25iface_xmit,
+	.data_ind = &isdn_x25iface_receive,
+	.connect_ind = &isdn_x25iface_connect_ind,
+	.disconn_ind = &isdn_x25iface_disconn_ind
 };
 
 /* error message helper function */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/Kconfig linux-libre-4.10-rc8-gnu/drivers/leds/Kconfig
--- linux-libre-4.9-gnu/drivers/leds/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -645,7 +645,7 @@ config LEDS_VERSATILE
 
 config LEDS_PM8058
 	tristate "LED Support for the Qualcomm PM8058 PMIC"
-	depends on MFD_PM8921_CORE
+	depends on MFD_PM8XXX
 	depends on LEDS_CLASS
 	help
 	  Choose this option if you want to use the LED drivers in
@@ -659,6 +659,25 @@ config LEDS_MLXCPLD
 	  This option enabled support for the LEDs on the Mellanox
 	  boards. Say Y to enabled these.
 
+config LEDS_USER
+	tristate "Userspace LED support"
+	depends on LEDS_CLASS
+	help
+	  This option enables support for userspace LEDs. Say 'y' to enable this
+	  support in kernel. To compile this driver as a module, choose 'm' here:
+	  the module will be called uleds.
+
+config LEDS_NIC78BX
+	tristate "LED support for NI PXI NIC78bx devices"
+	depends on LEDS_CLASS
+	depends on X86 && ACPI
+	help
+	  This option enables support for the User1 and User2 LEDs on NI
+	  PXI NIC78bx devices.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called leds-nic78bx.
+
 comment "LED Triggers"
 source "drivers/leds/trigger/Kconfig"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/led-class.c linux-libre-4.10-rc8-gnu/drivers/leds/led-class.c
--- linux-libre-4.9-gnu/drivers/leds/led-class.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/led-class.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
+#include <uapi/linux/uleds.h>
 #include "leds.h"
 
 static struct class *leds_class;
@@ -187,7 +188,7 @@ static int led_classdev_next_name(const
  */
 int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 {
-	char name[64];
+	char name[LED_MAX_NAME_SIZE];
 	int ret;
 
 	ret = led_classdev_next_name(led_cdev->name, name, sizeof(name));
@@ -203,6 +204,7 @@ int led_classdev_register(struct device
 		dev_warn(parent, "Led %s renamed to %s due to name collision",
 				led_cdev->name, dev_name(led_cdev->dev));
 
+	led_cdev->work_flags = 0;
 #ifdef CONFIG_LEDS_TRIGGERS
 	init_rwsem(&led_cdev->trigger_lock);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/led-core.c linux-libre-4.10-rc8-gnu/drivers/leds/led-core.c
--- linux-libre-4.9-gnu/drivers/leds/led-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/led-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,30 +53,30 @@ static void led_timer_function(unsigned
 
 	if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
 		led_set_brightness_nosleep(led_cdev, LED_OFF);
-		led_cdev->flags &= ~LED_BLINK_SW;
+		clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
 		return;
 	}
 
-	if (led_cdev->flags & LED_BLINK_ONESHOT_STOP) {
-		led_cdev->flags &=  ~(LED_BLINK_ONESHOT_STOP | LED_BLINK_SW);
+	if (test_and_clear_bit(LED_BLINK_ONESHOT_STOP,
+			       &led_cdev->work_flags)) {
+		clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
 		return;
 	}
 
 	brightness = led_get_brightness(led_cdev);
 	if (!brightness) {
 		/* Time to switch the LED on. */
-		brightness = led_cdev->blink_brightness;
+		if (test_and_clear_bit(LED_BLINK_BRIGHTNESS_CHANGE,
+					&led_cdev->work_flags))
+			brightness = led_cdev->new_blink_brightness;
+		else
+			brightness = led_cdev->blink_brightness;
 		delay = led_cdev->blink_delay_on;
 	} else {
 		/* Store the current brightness value to be able
 		 * to restore it when the delay_off period is over.
-		 * Do it only if there is no pending blink brightness
-		 * change, to avoid overwriting the new value.
 		 */
-		if (!(led_cdev->flags & LED_BLINK_BRIGHTNESS_CHANGE))
-			led_cdev->blink_brightness = brightness;
-		else
-			led_cdev->flags &= ~LED_BLINK_BRIGHTNESS_CHANGE;
+		led_cdev->blink_brightness = brightness;
 		brightness = LED_OFF;
 		delay = led_cdev->blink_delay_off;
 	}
@@ -87,13 +87,15 @@ static void led_timer_function(unsigned
 	 * the final blink state so that the led is toggled each delay_on +
 	 * delay_off milliseconds in worst case.
 	 */
-	if (led_cdev->flags & LED_BLINK_ONESHOT) {
-		if (led_cdev->flags & LED_BLINK_INVERT) {
+	if (test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags)) {
+		if (test_bit(LED_BLINK_INVERT, &led_cdev->work_flags)) {
 			if (brightness)
-				led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+				set_bit(LED_BLINK_ONESHOT_STOP,
+					&led_cdev->work_flags);
 		} else {
 			if (!brightness)
-				led_cdev->flags |= LED_BLINK_ONESHOT_STOP;
+				set_bit(LED_BLINK_ONESHOT_STOP,
+					&led_cdev->work_flags);
 		}
 	}
 
@@ -106,10 +108,9 @@ static void set_brightness_delayed(struc
 		container_of(ws, struct led_classdev, set_brightness_work);
 	int ret = 0;
 
-	if (led_cdev->flags & LED_BLINK_DISABLE) {
+	if (test_and_clear_bit(LED_BLINK_DISABLE, &led_cdev->work_flags)) {
 		led_cdev->delayed_set_value = LED_OFF;
 		led_stop_software_blink(led_cdev);
-		led_cdev->flags &= ~LED_BLINK_DISABLE;
 	}
 
 	ret = __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
@@ -152,7 +153,7 @@ static void led_set_software_blink(struc
 		return;
 	}
 
-	led_cdev->flags |= LED_BLINK_SW;
+	set_bit(LED_BLINK_SW, &led_cdev->work_flags);
 	mod_timer(&led_cdev->blink_timer, jiffies + 1);
 }
 
@@ -161,7 +162,7 @@ static void led_blink_setup(struct led_c
 		     unsigned long *delay_on,
 		     unsigned long *delay_off)
 {
-	if (!(led_cdev->flags & LED_BLINK_ONESHOT) &&
+	if (!test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
 	    led_cdev->blink_set &&
 	    !led_cdev->blink_set(led_cdev, delay_on, delay_off))
 		return;
@@ -188,8 +189,8 @@ void led_blink_set(struct led_classdev *
 {
 	del_timer_sync(&led_cdev->blink_timer);
 
-	led_cdev->flags &= ~LED_BLINK_ONESHOT;
-	led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+	clear_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags);
+	clear_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags);
 
 	led_blink_setup(led_cdev, delay_on, delay_off);
 }
@@ -200,17 +201,17 @@ void led_blink_set_oneshot(struct led_cl
 			   unsigned long *delay_off,
 			   int invert)
 {
-	if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
+	if (test_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags) &&
 	     timer_pending(&led_cdev->blink_timer))
 		return;
 
-	led_cdev->flags |= LED_BLINK_ONESHOT;
-	led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
+	set_bit(LED_BLINK_ONESHOT, &led_cdev->work_flags);
+	clear_bit(LED_BLINK_ONESHOT_STOP, &led_cdev->work_flags);
 
 	if (invert)
-		led_cdev->flags |= LED_BLINK_INVERT;
+		set_bit(LED_BLINK_INVERT, &led_cdev->work_flags);
 	else
-		led_cdev->flags &= ~LED_BLINK_INVERT;
+		clear_bit(LED_BLINK_INVERT, &led_cdev->work_flags);
 
 	led_blink_setup(led_cdev, delay_on, delay_off);
 }
@@ -221,7 +222,7 @@ void led_stop_software_blink(struct led_
 	del_timer_sync(&led_cdev->blink_timer);
 	led_cdev->blink_delay_on = 0;
 	led_cdev->blink_delay_off = 0;
-	led_cdev->flags &= ~LED_BLINK_SW;
+	clear_bit(LED_BLINK_SW, &led_cdev->work_flags);
 }
 EXPORT_SYMBOL_GPL(led_stop_software_blink);
 
@@ -232,18 +233,19 @@ void led_set_brightness(struct led_class
 	 * If software blink is active, delay brightness setting
 	 * until the next timer tick.
 	 */
-	if (led_cdev->flags & LED_BLINK_SW) {
+	if (test_bit(LED_BLINK_SW, &led_cdev->work_flags)) {
 		/*
 		 * If we need to disable soft blinking delegate this to the
 		 * work queue task to avoid problems in case we are called
 		 * from hard irq context.
 		 */
 		if (brightness == LED_OFF) {
-			led_cdev->flags |= LED_BLINK_DISABLE;
+			set_bit(LED_BLINK_DISABLE, &led_cdev->work_flags);
 			schedule_work(&led_cdev->set_brightness_work);
 		} else {
-			led_cdev->flags |= LED_BLINK_BRIGHTNESS_CHANGE;
-			led_cdev->blink_brightness = brightness;
+			set_bit(LED_BLINK_BRIGHTNESS_CHANGE,
+				&led_cdev->work_flags);
+			led_cdev->new_blink_brightness = brightness;
 		}
 		return;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-cobalt-raq.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-cobalt-raq.c
--- linux-libre-4.9-gnu/drivers/leds/leds-cobalt-raq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-cobalt-raq.c	2017-02-12 16:03:20.000000000 -0500
@@ -115,8 +115,4 @@ static struct platform_driver cobalt_raq
 	},
 };
 
-static int __init cobalt_raq_led_init(void)
-{
-	return platform_driver_register(&cobalt_raq_led_driver);
-}
-device_initcall(cobalt_raq_led_init);
+builtin_platform_driver(cobalt_raq_led_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-lp3952.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-lp3952.c
--- linux-libre-4.9-gnu/drivers/leds/leds-lp3952.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-lp3952.c	2017-02-12 16:03:20.000000000 -0500
@@ -274,6 +274,7 @@ static const struct i2c_device_id lp3952
 	{LP3952_NAME, 0},
 	{}
 };
+MODULE_DEVICE_TABLE(i2c, lp3952_id);
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id lp3952_acpi_match[] = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-mc13783.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-mc13783.c
--- linux-libre-4.9-gnu/drivers/leds/leds-mc13783.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-mc13783.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,8 +84,9 @@ static int mc13xxx_led_set(struct led_cl
 	case MC13892_LED_MD:
 	case MC13892_LED_AD:
 	case MC13892_LED_KP:
-		reg = (led->id - MC13892_LED_MD) / 2;
-		shift = 3 + (led->id - MC13892_LED_MD) * 12;
+		off = led->id - MC13892_LED_MD;
+		reg = off / 2;
+		shift = 3 + (off - reg * 2) * 12;
 		break;
 	case MC13892_LED_R:
 	case MC13892_LED_G:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-mlxcpld.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-mlxcpld.c
--- linux-libre-4.9-gnu/drivers/leds/leds-mlxcpld.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-mlxcpld.c	2017-02-12 16:03:20.000000000 -0500
@@ -400,6 +400,9 @@ static int __init mlxcpld_led_init(void)
 	struct platform_device *pdev;
 	int err;
 
+	if (!dmi_match(DMI_CHASSIS_VENDOR, "Mellanox Technologies Ltd."))
+		return -ENODEV;
+
 	pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0);
 	if (IS_ERR(pdev)) {
 		pr_err("Device allocation failed\n");
@@ -426,5 +429,5 @@ module_exit(mlxcpld_led_exit);
 
 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox board LED driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("Dual BSD/GPL");
 MODULE_ALIAS("platform:leds_mlxcpld");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-netxbig.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-netxbig.c
--- linux-libre-4.9-gnu/drivers/leds/leds-netxbig.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-netxbig.c	2017-02-12 16:03:20.000000000 -0500
@@ -534,6 +534,7 @@ static const struct of_device_id of_netx
 	{ .compatible = "lacie,netxbig-leds", },
 	{},
 };
+MODULE_DEVICE_TABLE(of, of_netxbig_leds_match);
 #else
 static inline int
 netxbig_leds_get_of_pdata(struct device *dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-nic78bx.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-nic78bx.c
--- linux-libre-4.9-gnu/drivers/leds/leds-nic78bx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-nic78bx.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2016 National Instruments 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/acpi.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#define NIC78BX_USER1_LED_MASK		0x3
+#define NIC78BX_USER1_GREEN_LED		BIT(0)
+#define NIC78BX_USER1_YELLOW_LED	BIT(1)
+
+#define NIC78BX_USER2_LED_MASK		0xC
+#define NIC78BX_USER2_GREEN_LED		BIT(2)
+#define NIC78BX_USER2_YELLOW_LED	BIT(3)
+
+#define NIC78BX_LOCK_REG_OFFSET		1
+#define NIC78BX_LOCK_VALUE		0xA5
+#define NIC78BX_UNLOCK_VALUE		0x5A
+
+#define NIC78BX_USER_LED_IO_SIZE	2
+
+struct nic78bx_led_data {
+	u16 io_base;
+	spinlock_t lock;
+	struct platform_device *pdev;
+};
+
+struct nic78bx_led {
+	u8 bit;
+	u8 mask;
+	struct nic78bx_led_data *data;
+	struct led_classdev cdev;
+};
+
+static inline struct nic78bx_led *to_nic78bx_led(struct led_classdev *cdev)
+{
+	return container_of(cdev, struct nic78bx_led, cdev);
+}
+
+static void nic78bx_brightness_set(struct led_classdev *cdev,
+				  enum led_brightness brightness)
+{
+	struct nic78bx_led *nled = to_nic78bx_led(cdev);
+	unsigned long flags;
+	u8 value;
+
+	spin_lock_irqsave(&nled->data->lock, flags);
+	value = inb(nled->data->io_base);
+
+	if (brightness) {
+		value &= ~nled->mask;
+		value |= nled->bit;
+	} else {
+		value &= ~nled->bit;
+	}
+
+	outb(value, nled->data->io_base);
+	spin_unlock_irqrestore(&nled->data->lock, flags);
+}
+
+static enum led_brightness nic78bx_brightness_get(struct led_classdev *cdev)
+{
+	struct nic78bx_led *nled = to_nic78bx_led(cdev);
+	unsigned long flags;
+	u8 value;
+
+	spin_lock_irqsave(&nled->data->lock, flags);
+	value = inb(nled->data->io_base);
+	spin_unlock_irqrestore(&nled->data->lock, flags);
+
+	return (value & nled->bit) ? 1 : LED_OFF;
+}
+
+static struct nic78bx_led nic78bx_leds[] = {
+	{
+		.bit = NIC78BX_USER1_GREEN_LED,
+		.mask = NIC78BX_USER1_LED_MASK,
+		.cdev = {
+			.name = "nilrt:green:user1",
+			.max_brightness = 1,
+			.brightness_set = nic78bx_brightness_set,
+			.brightness_get = nic78bx_brightness_get,
+		}
+	},
+	{
+		.bit = NIC78BX_USER1_YELLOW_LED,
+		.mask = NIC78BX_USER1_LED_MASK,
+		.cdev = {
+			.name = "nilrt:yellow:user1",
+			.max_brightness = 1,
+			.brightness_set = nic78bx_brightness_set,
+			.brightness_get = nic78bx_brightness_get,
+		}
+	},
+	{
+		.bit = NIC78BX_USER2_GREEN_LED,
+		.mask = NIC78BX_USER2_LED_MASK,
+		.cdev = {
+			.name = "nilrt:green:user2",
+			.max_brightness = 1,
+			.brightness_set = nic78bx_brightness_set,
+			.brightness_get = nic78bx_brightness_get,
+		}
+	},
+	{
+		.bit = NIC78BX_USER2_YELLOW_LED,
+		.mask = NIC78BX_USER2_LED_MASK,
+		.cdev = {
+			.name = "nilrt:yellow:user2",
+			.max_brightness = 1,
+			.brightness_set = nic78bx_brightness_set,
+			.brightness_get = nic78bx_brightness_get,
+		}
+	}
+};
+
+static int nic78bx_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct nic78bx_led_data *led_data;
+	struct resource *io_rc;
+	int ret, i;
+
+	led_data = devm_kzalloc(dev, sizeof(*led_data), GFP_KERNEL);
+	if (!led_data)
+		return -ENOMEM;
+
+	led_data->pdev = pdev;
+	platform_set_drvdata(pdev, led_data);
+
+	io_rc = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!io_rc) {
+		dev_err(dev, "missing IO resources\n");
+		return -EINVAL;
+	}
+
+	if (resource_size(io_rc) < NIC78BX_USER_LED_IO_SIZE) {
+		dev_err(dev, "IO region too small\n");
+		return -EINVAL;
+	}
+
+	if (!devm_request_region(dev, io_rc->start, resource_size(io_rc),
+				 KBUILD_MODNAME)) {
+		dev_err(dev, "failed to get IO region\n");
+		return -EBUSY;
+	}
+
+	led_data->io_base = io_rc->start;
+	spin_lock_init(&led_data->lock);
+
+	for (i = 0; i < ARRAY_SIZE(nic78bx_leds); i++) {
+		nic78bx_leds[i].data = led_data;
+
+		ret = devm_led_classdev_register(dev, &nic78bx_leds[i].cdev);
+		if (ret)
+			return ret;
+	}
+
+	/* Unlock LED register */
+	outb(NIC78BX_UNLOCK_VALUE,
+	     led_data->io_base + NIC78BX_LOCK_REG_OFFSET);
+
+	return ret;
+}
+
+static int nic78bx_remove(struct platform_device *pdev)
+{
+	struct nic78bx_led_data *led_data = platform_get_drvdata(pdev);
+
+	/* Lock LED register */
+	outb(NIC78BX_LOCK_VALUE,
+	     led_data->io_base + NIC78BX_LOCK_REG_OFFSET);
+
+	return 0;
+}
+
+static const struct acpi_device_id led_device_ids[] = {
+	{"NIC78B3", 0},
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, led_device_ids);
+
+static struct platform_driver led_driver = {
+	.probe = nic78bx_probe,
+	.remove = nic78bx_remove,
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.acpi_match_table = ACPI_PTR(led_device_ids),
+	},
+};
+
+module_platform_driver(led_driver);
+
+MODULE_DESCRIPTION("National Instruments PXI User LEDs driver");
+MODULE_AUTHOR("Hui Chun Ong <hui.chun.ong@ni.com>");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-pca9532.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-pca9532.c
--- linux-libre-4.9-gnu/drivers/leds/leds-pca9532.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-pca9532.c	2017-02-12 16:03:20.000000000 -0500
@@ -369,7 +369,7 @@ static int pca9532_configure(struct i2c_
 			led->state = pled->state;
 			led->name = pled->name;
 			led->ldev.name = led->name;
-			led->ldev.default_trigger = led->default_trigger;
+			led->ldev.default_trigger = pled->default_trigger;
 			led->ldev.brightness = LED_OFF;
 			led->ldev.brightness_set_blocking =
 						pca9532_set_brightness;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-pca955x.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-pca955x.c
--- linux-libre-4.9-gnu/drivers/leds/leds-pca955x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-pca955x.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,6 +40,7 @@
  *  bits the chip supports.
  */
 
+#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/string.h>
@@ -100,6 +101,15 @@ static const struct i2c_device_id pca955
 };
 MODULE_DEVICE_TABLE(i2c, pca955x_id);
 
+static const struct acpi_device_id pca955x_acpi_ids[] = {
+	{ "PCA9550",  pca9550 },
+	{ "PCA9551",  pca9551 },
+	{ "PCA9552",  pca9552 },
+	{ "PCA9553",  pca9553 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, pca955x_acpi_ids);
+
 struct pca955x {
 	struct mutex lock;
 	struct pca955x_led *leds;
@@ -250,7 +260,16 @@ static int pca955x_probe(struct i2c_clie
 	struct led_platform_data *pdata;
 	int i, err;
 
-	chip = &pca955x_chipdefs[id->driver_data];
+	if (id) {
+		chip = &pca955x_chipdefs[id->driver_data];
+	} else {
+		const struct acpi_device_id *acpi_id;
+
+		acpi_id = acpi_match_device(pca955x_acpi_ids, &client->dev);
+		if (!acpi_id)
+			return -ENODEV;
+		chip = &pca955x_chipdefs[acpi_id->driver_data];
+	}
 	adapter = to_i2c_adapter(client->dev.parent);
 	pdata = dev_get_platdata(&client->dev);
 
@@ -264,7 +283,7 @@ static int pca955x_probe(struct i2c_clie
 
 	dev_info(&client->dev, "leds-pca955x: Using %s %d-bit LED driver at "
 			"slave address 0x%02x\n",
-			id->name, chip->bits, client->addr);
+			client->name, chip->bits, client->addr);
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
 		return -EIO;
@@ -358,6 +377,7 @@ static int pca955x_remove(struct i2c_cli
 static struct i2c_driver pca955x_driver = {
 	.driver = {
 		.name	= "leds-pca955x",
+		.acpi_match_table = ACPI_PTR(pca955x_acpi_ids),
 	},
 	.probe	= pca955x_probe,
 	.remove	= pca955x_remove,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/leds-pca963x.c linux-libre-4.10-rc8-gnu/drivers/leds/leds-pca963x.c
--- linux-libre-4.9-gnu/drivers/leds/leds-pca963x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/leds-pca963x.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,6 +25,7 @@
  * or by adding the 'nxp,hw-blink' property to the DTS.
  */
 
+#include <linux/acpi.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/string.h>
@@ -59,6 +60,7 @@ struct pca963x_chipdef {
 	u8			grpfreq;
 	u8			ledout_base;
 	int			n_leds;
+	unsigned int		scaling;
 };
 
 static struct pca963x_chipdef pca963x_chipdefs[] = {
@@ -95,6 +97,15 @@ static const struct i2c_device_id pca963
 };
 MODULE_DEVICE_TABLE(i2c, pca963x_id);
 
+static const struct acpi_device_id pca963x_acpi_ids[] = {
+	{ "PCA9632", pca9633 },
+	{ "PCA9633", pca9633 },
+	{ "PCA9634", pca9634 },
+	{ "PCA9635", pca9635 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, pca963x_acpi_ids);
+
 struct pca963x_led;
 
 struct pca963x {
@@ -102,6 +113,7 @@ struct pca963x {
 	struct mutex mutex;
 	struct i2c_client *client;
 	struct pca963x_led *leds;
+	unsigned long leds_on;
 };
 
 struct pca963x_led {
@@ -123,7 +135,6 @@ static int pca963x_brightness(struct pca
 	u8 mask = 0x3 << shift;
 	int ret;
 
-	mutex_lock(&pca963x->chip->mutex);
 	ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr);
 	switch (brightness) {
 	case LED_FULL:
@@ -140,14 +151,13 @@ static int pca963x_brightness(struct pca
 			PCA963X_PWM_BASE + pca963x->led_num,
 			brightness);
 		if (ret < 0)
-			goto unlock;
+			return ret;
 		ret = i2c_smbus_write_byte_data(pca963x->chip->client,
 			ledout_addr,
 			(ledout & ~mask) | (PCA963X_LED_PWM << shift));
 		break;
 	}
-unlock:
-	mutex_unlock(&pca963x->chip->mutex);
+
 	return ret;
 }
 
@@ -179,14 +189,49 @@ static void pca963x_blink(struct pca963x
 	mutex_unlock(&pca963x->chip->mutex);
 }
 
+static int pca963x_power_state(struct pca963x_led *pca963x)
+{
+	unsigned long *leds_on = &pca963x->chip->leds_on;
+	unsigned long cached_leds = pca963x->chip->leds_on;
+
+	if (pca963x->led_cdev.brightness)
+		set_bit(pca963x->led_num, leds_on);
+	else
+		clear_bit(pca963x->led_num, leds_on);
+
+	if (!(*leds_on) != !cached_leds)
+		return i2c_smbus_write_byte_data(pca963x->chip->client,
+			PCA963X_MODE1, *leds_on ? 0 : BIT(4));
+
+	return 0;
+}
+
 static int pca963x_led_set(struct led_classdev *led_cdev,
 	enum led_brightness value)
 {
 	struct pca963x_led *pca963x;
+	int ret;
 
 	pca963x = container_of(led_cdev, struct pca963x_led, led_cdev);
 
-	return pca963x_brightness(pca963x, value);
+	mutex_lock(&pca963x->chip->mutex);
+
+	ret = pca963x_brightness(pca963x, value);
+	if (ret < 0)
+		goto unlock;
+	ret = pca963x_power_state(pca963x);
+
+unlock:
+	mutex_unlock(&pca963x->chip->mutex);
+	return ret;
+}
+
+static unsigned int pca963x_period_scale(struct pca963x_led *pca963x,
+	unsigned int val)
+{
+	unsigned int scaling = pca963x->chip->chipdef->scaling;
+
+	return scaling ? DIV_ROUND_CLOSEST(val * scaling, 1000) : val;
 }
 
 static int pca963x_blink_set(struct led_classdev *led_cdev,
@@ -207,14 +252,14 @@ static int pca963x_blink_set(struct led_
 		time_off = 500;
 	}
 
-	period = time_on + time_off;
+	period = pca963x_period_scale(pca963x, time_on + time_off);
 
 	/* If period not supported by hardware, default to someting sane. */
 	if ((period < PCA963X_BLINK_PERIOD_MIN) ||
 	    (period > PCA963X_BLINK_PERIOD_MAX)) {
 		time_on = 500;
 		time_off = 500;
-		period = time_on + time_off;
+		period = pca963x_period_scale(pca963x, 1000);
 	}
 
 	/*
@@ -222,7 +267,7 @@ static int pca963x_blink_set(struct led_
 	 *	(time_on / period) = (GDC / 256) ->
 	 *		GDC = ((time_on * 256) / period)
 	 */
-	gdc = (time_on * 256) / period;
+	gdc = (pca963x_period_scale(pca963x, time_on) * 256) / period;
 
 	/*
 	 * From manual: period = ((GFRQ + 1) / 24) in seconds.
@@ -294,6 +339,9 @@ pca963x_dt_init(struct i2c_client *clien
 	else
 		pdata->blink_type = PCA963X_SW_BLINK;
 
+	if (of_property_read_u32(np, "nxp,period-scale", &chip->scaling))
+		chip->scaling = 1000;
+
 	return pdata;
 }
 
@@ -322,7 +370,16 @@ static int pca963x_probe(struct i2c_clie
 	struct pca963x_chipdef *chip;
 	int i, err;
 
-	chip = &pca963x_chipdefs[id->driver_data];
+	if (id) {
+		chip = &pca963x_chipdefs[id->driver_data];
+	} else {
+		const struct acpi_device_id *acpi_id;
+
+		acpi_id = acpi_match_device(pca963x_acpi_ids, &client->dev);
+		if (!acpi_id)
+			return -ENODEV;
+		chip = &pca963x_chipdefs[acpi_id->driver_data];
+	}
 	pdata = dev_get_platdata(&client->dev);
 
 	if (!pdata) {
@@ -391,8 +448,8 @@ static int pca963x_probe(struct i2c_clie
 			goto exit;
 	}
 
-	/* Disable LED all-call address and set normal mode */
-	i2c_smbus_write_byte_data(client, PCA963X_MODE1, 0x00);
+	/* Disable LED all-call address, and power down initially */
+	i2c_smbus_write_byte_data(client, PCA963X_MODE1, BIT(4));
 
 	if (pdata) {
 		/* Configure output: open-drain or totem pole (push-pull) */
@@ -426,6 +483,7 @@ static struct i2c_driver pca963x_driver
 	.driver = {
 		.name	= "leds-pca963x",
 		.of_match_table = of_match_ptr(of_pca963x_match),
+		.acpi_match_table = ACPI_PTR(pca963x_acpi_ids),
 	},
 	.probe	= pca963x_probe,
 	.remove	= pca963x_remove,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/Makefile linux-libre-4.10-rc8-gnu/drivers/leds/Makefile
--- linux-libre-4.9-gnu/drivers/leds/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -71,9 +71,13 @@ obj-$(CONFIG_LEDS_IS31FL319X)		+= leds-i
 obj-$(CONFIG_LEDS_IS31FL32XX)		+= leds-is31fl32xx.o
 obj-$(CONFIG_LEDS_PM8058)		+= leds-pm8058.o
 obj-$(CONFIG_LEDS_MLXCPLD)		+= leds-mlxcpld.o
+obj-$(CONFIG_LEDS_NIC78BX)		+= leds-nic78bx.o
 
 # LED SPI Drivers
 obj-$(CONFIG_LEDS_DAC124S085)		+= leds-dac124s085.o
 
+# LED Userspace Drivers
+obj-$(CONFIG_LEDS_USER)			+= uleds.o
+
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGERS)		+= trigger/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/trigger/ledtrig-cpu.c linux-libre-4.10-rc8-gnu/drivers/leds/trigger/ledtrig-cpu.c
--- linux-libre-4.9-gnu/drivers/leds/trigger/ledtrig-cpu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/trigger/ledtrig-cpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@ static DEFINE_PER_CPU(struct led_trigger
  * @evt: CPU event to be emitted
  *
  * Emit a CPU event on a CPU core, which will trigger a
- * binded LED to turn on or turn off.
+ * bound LED to turn on or turn off.
  */
 void ledtrig_cpu(enum cpu_led_event ledevt)
 {
@@ -127,7 +127,7 @@ static int __init ledtrig_cpu_init(void)
 
 	register_syscore_ops(&ledtrig_cpu_syscore_ops);
 
-	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "AP_LEDTRIG_STARTING",
+	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "leds/trigger:starting",
 				ledtrig_online_cpu, ledtrig_prepare_down_cpu);
 	if (ret < 0)
 		pr_err("CPU hotplug notifier for ledtrig-cpu could not be registered: %d\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/leds/uleds.c linux-libre-4.10-rc8-gnu/drivers/leds/uleds.c
--- linux-libre-4.9-gnu/drivers/leds/uleds.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/leds/uleds.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,235 @@
+/*
+ * Userspace driver for the LED subsystem
+ *
+ * Copyright (C) 2016 David Lechner <david@lechnology.com>
+ *
+ * Based on uinput.c: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <uapi/linux/uleds.h>
+
+#define ULEDS_NAME	"uleds"
+
+enum uleds_state {
+	ULEDS_STATE_UNKNOWN,
+	ULEDS_STATE_REGISTERED,
+};
+
+struct uleds_device {
+	struct uleds_user_dev	user_dev;
+	struct led_classdev	led_cdev;
+	struct mutex		mutex;
+	enum uleds_state	state;
+	wait_queue_head_t	waitq;
+	int			brightness;
+	bool			new_data;
+};
+
+static struct miscdevice uleds_misc;
+
+static void uleds_brightness_set(struct led_classdev *led_cdev,
+				 enum led_brightness brightness)
+{
+	struct uleds_device *udev = container_of(led_cdev, struct uleds_device,
+						 led_cdev);
+
+	if (udev->brightness != brightness) {
+		udev->brightness = brightness;
+		udev->new_data = true;
+		wake_up_interruptible(&udev->waitq);
+	}
+}
+
+static int uleds_open(struct inode *inode, struct file *file)
+{
+	struct uleds_device *udev;
+
+	udev = kzalloc(sizeof(*udev), GFP_KERNEL);
+	if (!udev)
+		return -ENOMEM;
+
+	udev->led_cdev.name = udev->user_dev.name;
+	udev->led_cdev.brightness_set = uleds_brightness_set;
+
+	mutex_init(&udev->mutex);
+	init_waitqueue_head(&udev->waitq);
+	udev->state = ULEDS_STATE_UNKNOWN;
+
+	file->private_data = udev;
+	nonseekable_open(inode, file);
+
+	return 0;
+}
+
+static ssize_t uleds_write(struct file *file, const char __user *buffer,
+			   size_t count, loff_t *ppos)
+{
+	struct uleds_device *udev = file->private_data;
+	const char *name;
+	int ret;
+
+	if (count == 0)
+		return 0;
+
+	ret = mutex_lock_interruptible(&udev->mutex);
+	if (ret)
+		return ret;
+
+	if (udev->state == ULEDS_STATE_REGISTERED) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (count != sizeof(struct uleds_user_dev)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (copy_from_user(&udev->user_dev, buffer,
+			   sizeof(struct uleds_user_dev))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	name = udev->user_dev.name;
+	if (!name[0] || !strcmp(name, ".") || !strcmp(name, "..") ||
+	    strchr(name, '/')) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (udev->user_dev.max_brightness <= 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+	udev->led_cdev.max_brightness = udev->user_dev.max_brightness;
+
+	ret = devm_led_classdev_register(uleds_misc.this_device,
+					 &udev->led_cdev);
+	if (ret < 0)
+		goto out;
+
+	udev->new_data = true;
+	udev->state = ULEDS_STATE_REGISTERED;
+	ret = count;
+
+out:
+	mutex_unlock(&udev->mutex);
+
+	return ret;
+}
+
+static ssize_t uleds_read(struct file *file, char __user *buffer, size_t count,
+			  loff_t *ppos)
+{
+	struct uleds_device *udev = file->private_data;
+	ssize_t retval;
+
+	if (count < sizeof(udev->brightness))
+		return 0;
+
+	do {
+		retval = mutex_lock_interruptible(&udev->mutex);
+		if (retval)
+			return retval;
+
+		if (udev->state != ULEDS_STATE_REGISTERED) {
+			retval = -ENODEV;
+		} else if (!udev->new_data && (file->f_flags & O_NONBLOCK)) {
+			retval = -EAGAIN;
+		} else if (udev->new_data) {
+			retval = copy_to_user(buffer, &udev->brightness,
+					      sizeof(udev->brightness));
+			udev->new_data = false;
+			retval = sizeof(udev->brightness);
+		}
+
+		mutex_unlock(&udev->mutex);
+
+		if (retval)
+			break;
+
+		if (!(file->f_flags & O_NONBLOCK))
+			retval = wait_event_interruptible(udev->waitq,
+					udev->new_data ||
+					udev->state != ULEDS_STATE_REGISTERED);
+	} while (retval == 0);
+
+	return retval;
+}
+
+static unsigned int uleds_poll(struct file *file, poll_table *wait)
+{
+	struct uleds_device *udev = file->private_data;
+
+	poll_wait(file, &udev->waitq, wait);
+
+	if (udev->new_data)
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}
+
+static int uleds_release(struct inode *inode, struct file *file)
+{
+	struct uleds_device *udev = file->private_data;
+
+	if (udev->state == ULEDS_STATE_REGISTERED) {
+		udev->state = ULEDS_STATE_UNKNOWN;
+		devm_led_classdev_unregister(uleds_misc.this_device,
+					     &udev->led_cdev);
+	}
+	kfree(udev);
+
+	return 0;
+}
+
+static const struct file_operations uleds_fops = {
+	.owner		= THIS_MODULE,
+	.open		= uleds_open,
+	.release	= uleds_release,
+	.read		= uleds_read,
+	.write		= uleds_write,
+	.poll		= uleds_poll,
+	.llseek		= no_llseek,
+};
+
+static struct miscdevice uleds_misc = {
+	.fops		= &uleds_fops,
+	.minor		= MISC_DYNAMIC_MINOR,
+	.name		= ULEDS_NAME,
+};
+
+static int __init uleds_init(void)
+{
+	return misc_register(&uleds_misc);
+}
+module_init(uleds_init);
+
+static void __exit uleds_exit(void)
+{
+	misc_deregister(&uleds_misc);
+}
+module_exit(uleds_exit);
+
+MODULE_AUTHOR("David Lechner <david@lechnology.com>");
+MODULE_DESCRIPTION("Userspace driver for the LED subsystem");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lguest/core.c linux-libre-4.10-rc8-gnu/drivers/lguest/core.c
--- linux-libre-4.9-gnu/drivers/lguest/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lguest/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
 #include <linux/slab.h>
 #include <asm/paravirt.h>
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/poll.h>
 #include <asm/asm-offsets.h>
 #include "lg.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lguest/hypercalls.c linux-libre-4.10-rc8-gnu/drivers/lguest/hypercalls.c
--- linux-libre-4.9-gnu/drivers/lguest/hypercalls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lguest/hypercalls.c	2017-02-12 16:03:20.000000000 -0500
@@ -109,10 +109,6 @@ static void do_hcall(struct lg_cpu *cpu,
 	case LHCALL_SET_CLOCKEVENT:
 		guest_set_clockevent(cpu, args->arg1);
 		break;
-	case LHCALL_TS:
-		/* This sets the TS flag, as we saw used in run_guest(). */
-		cpu->ts = args->arg1;
-		break;
 	case LHCALL_HALT:
 		/* Similarly, this sets the halted flag for run_guest(). */
 		cpu->halted = 1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lguest/lg.h linux-libre-4.10-rc8-gnu/drivers/lguest/lg.h
--- linux-libre-4.9-gnu/drivers/lguest/lg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lguest/lg.h	2017-02-12 16:03:20.000000000 -0500
@@ -43,7 +43,6 @@ struct lg_cpu {
 	struct mm_struct *mm; 	/* == tsk->mm, but that becomes NULL on exit */
 
 	u32 cr2;
-	int ts;
 	u32 esp1;
 	u16 ss1;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lguest/page_tables.c linux-libre-4.10-rc8-gnu/drivers/lguest/page_tables.c
--- linux-libre-4.9-gnu/drivers/lguest/page_tables.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lguest/page_tables.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/random.h>
 #include <linux/percpu.h>
 #include <asm/tlbflush.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "lg.h"
 
 /*M:008
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lguest/x86/core.c linux-libre-4.10-rc8-gnu/drivers/lguest/x86/core.c
--- linux-libre-4.9-gnu/drivers/lguest/x86/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lguest/x86/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,7 +45,7 @@
 #include <asm/desc.h>
 #include <asm/setup.h>
 #include <asm/lguest.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/fpu/internal.h>
 #include <asm/tlbflush.h>
 #include "../lg.h"
@@ -247,14 +247,6 @@ unsigned long *lguest_arch_regptr(struct
 void lguest_arch_run_guest(struct lg_cpu *cpu)
 {
 	/*
-	 * Remember the awfully-named TS bit?  If the Guest has asked to set it
-	 * we set it now, so we can trap and pass that trap to the Guest if it
-	 * uses the FPU.
-	 */
-	if (cpu->ts && fpregs_active())
-		stts();
-
-	/*
 	 * SYSENTER is an optimized way of doing system calls.  We can't allow
 	 * it because it always jumps to privilege level 0.  A normal Guest
 	 * won't try it because we don't advertise it in CPUID, but a malicious
@@ -282,10 +274,6 @@ void lguest_arch_run_guest(struct lg_cpu
 	 if (boot_cpu_has(X86_FEATURE_SEP))
 		wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
 
-	/* Clear the host TS bit if it was set above. */
-	if (cpu->ts && fpregs_active())
-		clts();
-
 	/*
 	 * If the Guest page faulted, then the cr2 register will tell us the
 	 * bad virtual address.  We have to grab this now, because once we
@@ -421,12 +409,7 @@ void lguest_arch_handle_trap(struct lg_c
 			kill_guest(cpu, "Writing cr2");
 		break;
 	case 7: /* We've intercepted a Device Not Available fault. */
-		/*
-		 * If the Guest doesn't want to know, we already restored the
-		 * Floating Point Unit, so we just continue without telling it.
-		 */
-		if (!cpu->ts)
-			return;
+		/* No special handling is needed here. */
 		break;
 	case 32 ... 255:
 		/* This might be a syscall. */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/core.c linux-libre-4.10-rc8-gnu/drivers/lightnvm/core.c
--- linux-libre-4.9-gnu/drivers/lightnvm/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,13 +22,11 @@
 #include <linux/types.h>
 #include <linux/sem.h>
 #include <linux/bitmap.h>
-#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/miscdevice.h>
 #include <linux/lightnvm.h>
 #include <linux/sched/sysctl.h>
 
-#include "lightnvm.h"
-
 static LIST_HEAD(nvm_tgt_types);
 static DECLARE_RWSEM(nvm_tgtt_lock);
 static LIST_HEAD(nvm_mgrs);
@@ -88,8 +86,7 @@ void *nvm_dev_dma_alloc(struct nvm_dev *
 }
 EXPORT_SYMBOL(nvm_dev_dma_alloc);
 
-void nvm_dev_dma_free(struct nvm_dev *dev, void *addr,
-							dma_addr_t dma_handler)
+void nvm_dev_dma_free(struct nvm_dev *dev, void *addr, dma_addr_t dma_handler)
 {
 	dev->ops->dev_dma_free(dev->dma_pool, addr, dma_handler);
 }
@@ -178,38 +175,133 @@ static struct nvm_dev *nvm_find_nvm_dev(
 	return NULL;
 }
 
-struct nvm_block *nvm_get_blk(struct nvm_dev *dev, struct nvm_lun *lun,
-							unsigned long flags)
+static void nvm_tgt_generic_to_addr_mode(struct nvm_tgt_dev *tgt_dev,
+					 struct nvm_rq *rqd)
 {
-	return dev->mt->get_blk(dev, lun, flags);
+	struct nvm_dev *dev = tgt_dev->parent;
+	int i;
+
+	if (rqd->nr_ppas > 1) {
+		for (i = 0; i < rqd->nr_ppas; i++) {
+			rqd->ppa_list[i] = dev->mt->trans_ppa(tgt_dev,
+					rqd->ppa_list[i], TRANS_TGT_TO_DEV);
+			rqd->ppa_list[i] = generic_to_dev_addr(dev,
+							rqd->ppa_list[i]);
+		}
+	} else {
+		rqd->ppa_addr = dev->mt->trans_ppa(tgt_dev, rqd->ppa_addr,
+						TRANS_TGT_TO_DEV);
+		rqd->ppa_addr = generic_to_dev_addr(dev, rqd->ppa_addr);
+	}
 }
-EXPORT_SYMBOL(nvm_get_blk);
 
-/* Assumes that all valid pages have already been moved on release to bm */
-void nvm_put_blk(struct nvm_dev *dev, struct nvm_block *blk)
+int nvm_set_bb_tbl(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas,
+								int type)
 {
-	return dev->mt->put_blk(dev, blk);
+	struct nvm_rq rqd;
+	int ret;
+
+	if (nr_ppas > dev->ops->max_phys_sect) {
+		pr_err("nvm: unable to update all sysblocks atomically\n");
+		return -EINVAL;
+	}
+
+	memset(&rqd, 0, sizeof(struct nvm_rq));
+
+	nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas, 1);
+	nvm_generic_to_addr_mode(dev, &rqd);
+
+	ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type);
+	nvm_free_rqd_ppalist(dev, &rqd);
+	if (ret) {
+		pr_err("nvm: sysblk failed bb mark\n");
+		return -EINVAL;
+	}
+
+	return 0;
 }
-EXPORT_SYMBOL(nvm_put_blk);
+EXPORT_SYMBOL(nvm_set_bb_tbl);
 
-void nvm_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type)
+int nvm_set_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas,
+		       int nr_ppas, int type)
 {
-	return dev->mt->mark_blk(dev, ppa, type);
+	struct nvm_dev *dev = tgt_dev->parent;
+	struct nvm_rq rqd;
+	int ret;
+
+	if (nr_ppas > dev->ops->max_phys_sect) {
+		pr_err("nvm: unable to update all blocks atomically\n");
+		return -EINVAL;
+	}
+
+	memset(&rqd, 0, sizeof(struct nvm_rq));
+
+	nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas, 1);
+	nvm_tgt_generic_to_addr_mode(tgt_dev, &rqd);
+
+	ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type);
+	nvm_free_rqd_ppalist(dev, &rqd);
+	if (ret) {
+		pr_err("nvm: sysblk failed bb mark\n");
+		return -EINVAL;
+	}
+
+	return 0;
 }
-EXPORT_SYMBOL(nvm_mark_blk);
+EXPORT_SYMBOL(nvm_set_tgt_bb_tbl);
 
-int nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
+int nvm_max_phys_sects(struct nvm_tgt_dev *tgt_dev)
 {
-	return dev->mt->submit_io(dev, rqd);
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	return dev->ops->max_phys_sect;
+}
+EXPORT_SYMBOL(nvm_max_phys_sects);
+
+int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	return dev->mt->submit_io(tgt_dev, rqd);
 }
 EXPORT_SYMBOL(nvm_submit_io);
 
-int nvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk)
+int nvm_erase_blk(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p, int flags)
 {
-	return dev->mt->erase_blk(dev, blk, 0);
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	return dev->mt->erase_blk(tgt_dev, p, flags);
 }
 EXPORT_SYMBOL(nvm_erase_blk);
 
+int nvm_get_l2p_tbl(struct nvm_tgt_dev *tgt_dev, u64 slba, u32 nlb,
+		    nvm_l2p_update_fn *update_l2p, void *priv)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	if (!dev->ops->get_l2p_tbl)
+		return 0;
+
+	return dev->ops->get_l2p_tbl(dev, slba, nlb, update_l2p, priv);
+}
+EXPORT_SYMBOL(nvm_get_l2p_tbl);
+
+int nvm_get_area(struct nvm_tgt_dev *tgt_dev, sector_t *lba, sector_t len)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	return dev->mt->get_area(dev, lba, len);
+}
+EXPORT_SYMBOL(nvm_get_area);
+
+void nvm_put_area(struct nvm_tgt_dev *tgt_dev, sector_t lba)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	dev->mt->put_area(dev, lba);
+}
+EXPORT_SYMBOL(nvm_put_area);
+
 void nvm_addr_to_generic_mode(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
 	int i;
@@ -241,10 +333,11 @@ EXPORT_SYMBOL(nvm_generic_to_addr_mode);
 int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd,
 			const struct ppa_addr *ppas, int nr_ppas, int vblk)
 {
+	struct nvm_geo *geo = &dev->geo;
 	int i, plane_cnt, pl_idx;
 	struct ppa_addr ppa;
 
-	if ((!vblk || dev->plane_mode == NVM_PLANE_SINGLE) && nr_ppas == 1) {
+	if ((!vblk || geo->plane_mode == NVM_PLANE_SINGLE) && nr_ppas == 1) {
 		rqd->nr_ppas = nr_ppas;
 		rqd->ppa_addr = ppas[0];
 
@@ -262,7 +355,7 @@ int nvm_set_rqd_ppalist(struct nvm_dev *
 		for (i = 0; i < nr_ppas; i++)
 			rqd->ppa_list[i] = ppas[i];
 	} else {
-		plane_cnt = dev->plane_mode;
+		plane_cnt = geo->plane_mode;
 		rqd->nr_ppas *= plane_cnt;
 
 		for (i = 0; i < nr_ppas; i++) {
@@ -287,7 +380,8 @@ void nvm_free_rqd_ppalist(struct nvm_dev
 }
 EXPORT_SYMBOL(nvm_free_rqd_ppalist);
 
-int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas)
+int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas,
+								int flags)
 {
 	struct nvm_rq rqd;
 	int ret;
@@ -303,6 +397,8 @@ int nvm_erase_ppa(struct nvm_dev *dev, s
 
 	nvm_generic_to_addr_mode(dev, &rqd);
 
+	rqd.flags = flags;
+
 	ret = dev->ops->erase_block(dev, &rqd);
 
 	nvm_free_rqd_ppalist(dev, &rqd);
@@ -341,7 +437,7 @@ static int __nvm_submit_ppa(struct nvm_d
 
 	nvm_generic_to_addr_mode(dev, rqd);
 
-	rqd->dev = dev;
+	rqd->dev = NULL;
 	rqd->opcode = opcode;
 	rqd->flags = flags;
 	rqd->bio = bio;
@@ -437,17 +533,18 @@ EXPORT_SYMBOL(nvm_submit_ppa);
  */
 int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks)
 {
+	struct nvm_geo *geo = &dev->geo;
 	int blk, offset, pl, blktype;
 
-	if (nr_blks != dev->blks_per_lun * dev->plane_mode)
+	if (nr_blks != geo->blks_per_lun * geo->plane_mode)
 		return -EINVAL;
 
-	for (blk = 0; blk < dev->blks_per_lun; blk++) {
-		offset = blk * dev->plane_mode;
+	for (blk = 0; blk < geo->blks_per_lun; blk++) {
+		offset = blk * geo->plane_mode;
 		blktype = blks[offset];
 
 		/* Bad blocks on any planes take precedence over other types */
-		for (pl = 0; pl < dev->plane_mode; pl++) {
+		for (pl = 0; pl < geo->plane_mode; pl++) {
 			if (blks[offset + pl] &
 					(NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) {
 				blktype = blks[offset + pl];
@@ -458,7 +555,7 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev,
 		blks[blk] = blktype;
 	}
 
-	return dev->blks_per_lun;
+	return geo->blks_per_lun;
 }
 EXPORT_SYMBOL(nvm_bb_tbl_fold);
 
@@ -470,11 +567,22 @@ int nvm_get_bb_tbl(struct nvm_dev *dev,
 }
 EXPORT_SYMBOL(nvm_get_bb_tbl);
 
+int nvm_get_tgt_bb_tbl(struct nvm_tgt_dev *tgt_dev, struct ppa_addr ppa,
+		       u8 *blks)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+
+	ppa = dev->mt->trans_ppa(tgt_dev, ppa, TRANS_TGT_TO_DEV);
+	return nvm_get_bb_tbl(dev, ppa, blks);
+}
+EXPORT_SYMBOL(nvm_get_tgt_bb_tbl);
+
 static int nvm_init_slc_tbl(struct nvm_dev *dev, struct nvm_id_group *grp)
 {
+	struct nvm_geo *geo = &dev->geo;
 	int i;
 
-	dev->lps_per_blk = dev->pgs_per_blk;
+	dev->lps_per_blk = geo->pgs_per_blk;
 	dev->lptbl = kcalloc(dev->lps_per_blk, sizeof(int), GFP_KERNEL);
 	if (!dev->lptbl)
 		return -ENOMEM;
@@ -520,29 +628,32 @@ static int nvm_core_init(struct nvm_dev
 {
 	struct nvm_id *id = &dev->identity;
 	struct nvm_id_group *grp = &id->groups[0];
+	struct nvm_geo *geo = &dev->geo;
 	int ret;
 
-	/* device values */
-	dev->nr_chnls = grp->num_ch;
-	dev->luns_per_chnl = grp->num_lun;
-	dev->pgs_per_blk = grp->num_pg;
-	dev->blks_per_lun = grp->num_blk;
-	dev->nr_planes = grp->num_pln;
-	dev->fpg_size = grp->fpg_sz;
-	dev->pfpg_size = grp->fpg_sz * grp->num_pln;
-	dev->sec_size = grp->csecs;
-	dev->oob_size = grp->sos;
-	dev->sec_per_pg = grp->fpg_sz / grp->csecs;
-	dev->mccap = grp->mccap;
-	memcpy(&dev->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
+	/* Whole device values */
+	geo->nr_chnls = grp->num_ch;
+	geo->luns_per_chnl = grp->num_lun;
 
-	dev->plane_mode = NVM_PLANE_SINGLE;
-	dev->max_rq_size = dev->ops->max_phys_sect * dev->sec_size;
+	/* Generic device values */
+	geo->pgs_per_blk = grp->num_pg;
+	geo->blks_per_lun = grp->num_blk;
+	geo->nr_planes = grp->num_pln;
+	geo->fpg_size = grp->fpg_sz;
+	geo->pfpg_size = grp->fpg_sz * grp->num_pln;
+	geo->sec_size = grp->csecs;
+	geo->oob_size = grp->sos;
+	geo->sec_per_pg = grp->fpg_sz / grp->csecs;
+	geo->mccap = grp->mccap;
+	memcpy(&geo->ppaf, &id->ppaf, sizeof(struct nvm_addr_format));
+
+	geo->plane_mode = NVM_PLANE_SINGLE;
+	geo->max_rq_size = dev->ops->max_phys_sect * geo->sec_size;
 
 	if (grp->mpos & 0x020202)
-		dev->plane_mode = NVM_PLANE_DOUBLE;
+		geo->plane_mode = NVM_PLANE_DOUBLE;
 	if (grp->mpos & 0x040404)
-		dev->plane_mode = NVM_PLANE_QUAD;
+		geo->plane_mode = NVM_PLANE_QUAD;
 
 	if (grp->mtype != 0) {
 		pr_err("nvm: memory type not supported\n");
@@ -550,13 +661,13 @@ static int nvm_core_init(struct nvm_dev
 	}
 
 	/* calculated values */
-	dev->sec_per_pl = dev->sec_per_pg * dev->nr_planes;
-	dev->sec_per_blk = dev->sec_per_pl * dev->pgs_per_blk;
-	dev->sec_per_lun = dev->sec_per_blk * dev->blks_per_lun;
-	dev->nr_luns = dev->luns_per_chnl * dev->nr_chnls;
+	geo->sec_per_pl = geo->sec_per_pg * geo->nr_planes;
+	geo->sec_per_blk = geo->sec_per_pl * geo->pgs_per_blk;
+	geo->sec_per_lun = geo->sec_per_blk * geo->blks_per_lun;
+	geo->nr_luns = geo->luns_per_chnl * geo->nr_chnls;
 
-	dev->total_secs = dev->nr_luns * dev->sec_per_lun;
-	dev->lun_map = kcalloc(BITS_TO_LONGS(dev->nr_luns),
+	dev->total_secs = geo->nr_luns * geo->sec_per_lun;
+	dev->lun_map = kcalloc(BITS_TO_LONGS(geo->nr_luns),
 					sizeof(unsigned long), GFP_KERNEL);
 	if (!dev->lun_map)
 		return -ENOMEM;
@@ -583,7 +694,7 @@ static int nvm_core_init(struct nvm_dev
 	mutex_init(&dev->mlock);
 	spin_lock_init(&dev->lock);
 
-	blk_queue_logical_block_size(dev->q, dev->sec_size);
+	blk_queue_logical_block_size(dev->q, geo->sec_size);
 
 	return 0;
 err_fmtype:
@@ -617,6 +728,7 @@ void nvm_free(struct nvm_dev *dev)
 
 static int nvm_init(struct nvm_dev *dev)
 {
+	struct nvm_geo *geo = &dev->geo;
 	int ret = -EINVAL;
 
 	if (!dev->q || !dev->ops)
@@ -648,20 +760,15 @@ static int nvm_init(struct nvm_dev *dev)
 	}
 
 	pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
-			dev->name, dev->sec_per_pg, dev->nr_planes,
-			dev->pgs_per_blk, dev->blks_per_lun, dev->nr_luns,
-			dev->nr_chnls);
+			dev->name, geo->sec_per_pg, geo->nr_planes,
+			geo->pgs_per_blk, geo->blks_per_lun,
+			geo->nr_luns, geo->nr_chnls);
 	return 0;
 err:
 	pr_err("nvm: failed to initialize nvm\n");
 	return ret;
 }
 
-static void nvm_exit(struct nvm_dev *dev)
-{
-	nvm_sysfs_unregister_dev(dev);
-}
-
 struct nvm_dev *nvm_alloc_dev(int node)
 {
 	return kzalloc_node(sizeof(struct nvm_dev), GFP_KERNEL, node);
@@ -691,10 +798,6 @@ int nvm_register(struct nvm_dev *dev)
 		}
 	}
 
-	ret = nvm_sysfs_register_dev(dev);
-	if (ret)
-		goto err_ppalist;
-
 	if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) {
 		ret = nvm_get_sysblock(dev, &dev->sb);
 		if (!ret)
@@ -711,8 +814,6 @@ int nvm_register(struct nvm_dev *dev)
 	up_write(&nvm_lock);
 
 	return 0;
-err_ppalist:
-	dev->ops->destroy_dma_pool(dev->dma_pool);
 err_init:
 	kfree(dev->lun_map);
 	return ret;
@@ -725,7 +826,7 @@ void nvm_unregister(struct nvm_dev *dev)
 	list_del(&dev->devices);
 	up_write(&nvm_lock);
 
-	nvm_exit(dev);
+	nvm_free(dev);
 }
 EXPORT_SYMBOL(nvm_unregister);
 
@@ -754,149 +855,15 @@ static int __nvm_configure_create(struct
 	}
 	s = &create->conf.s;
 
-	if (s->lun_begin > s->lun_end || s->lun_end > dev->nr_luns) {
+	if (s->lun_begin > s->lun_end || s->lun_end > dev->geo.nr_luns) {
 		pr_err("nvm: lun out of bound (%u:%u > %u)\n",
-			s->lun_begin, s->lun_end, dev->nr_luns);
+			s->lun_begin, s->lun_end, dev->geo.nr_luns);
 		return -EINVAL;
 	}
 
 	return dev->mt->create_tgt(dev, create);
 }
 
-#ifdef CONFIG_NVM_DEBUG
-static int nvm_configure_show(const char *val)
-{
-	struct nvm_dev *dev;
-	char opcode, devname[DISK_NAME_LEN];
-	int ret;
-
-	ret = sscanf(val, "%c %32s", &opcode, devname);
-	if (ret != 2) {
-		pr_err("nvm: invalid command. Use \"opcode devicename\".\n");
-		return -EINVAL;
-	}
-
-	down_write(&nvm_lock);
-	dev = nvm_find_nvm_dev(devname);
-	up_write(&nvm_lock);
-	if (!dev) {
-		pr_err("nvm: device not found\n");
-		return -EINVAL;
-	}
-
-	if (!dev->mt)
-		return 0;
-
-	dev->mt->lun_info_print(dev);
-
-	return 0;
-}
-
-static int nvm_configure_remove(const char *val)
-{
-	struct nvm_ioctl_remove remove;
-	struct nvm_dev *dev;
-	char opcode;
-	int ret = 0;
-
-	ret = sscanf(val, "%c %256s", &opcode, remove.tgtname);
-	if (ret != 2) {
-		pr_err("nvm: invalid command. Use \"d targetname\".\n");
-		return -EINVAL;
-	}
-
-	remove.flags = 0;
-
-	list_for_each_entry(dev, &nvm_devices, devices) {
-		ret = dev->mt->remove_tgt(dev, &remove);
-		if (!ret)
-			break;
-	}
-
-	return ret;
-}
-
-static int nvm_configure_create(const char *val)
-{
-	struct nvm_ioctl_create create;
-	char opcode;
-	int lun_begin, lun_end, ret;
-
-	ret = sscanf(val, "%c %256s %256s %48s %u:%u", &opcode, create.dev,
-						create.tgtname, create.tgttype,
-						&lun_begin, &lun_end);
-	if (ret != 6) {
-		pr_err("nvm: invalid command. Use \"opcode device name tgttype lun_begin:lun_end\".\n");
-		return -EINVAL;
-	}
-
-	create.flags = 0;
-	create.conf.type = NVM_CONFIG_TYPE_SIMPLE;
-	create.conf.s.lun_begin = lun_begin;
-	create.conf.s.lun_end = lun_end;
-
-	return __nvm_configure_create(&create);
-}
-
-
-/* Exposes administrative interface through /sys/module/lnvm/configure_by_str */
-static int nvm_configure_by_str_event(const char *val,
-					const struct kernel_param *kp)
-{
-	char opcode;
-	int ret;
-
-	ret = sscanf(val, "%c", &opcode);
-	if (ret != 1) {
-		pr_err("nvm: string must have the format of \"cmd ...\"\n");
-		return -EINVAL;
-	}
-
-	switch (opcode) {
-	case 'a':
-		return nvm_configure_create(val);
-	case 'd':
-		return nvm_configure_remove(val);
-	case 's':
-		return nvm_configure_show(val);
-	default:
-		pr_err("nvm: invalid command\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int nvm_configure_get(char *buf, const struct kernel_param *kp)
-{
-	int sz;
-	struct nvm_dev *dev;
-
-	sz = sprintf(buf, "available devices:\n");
-	down_write(&nvm_lock);
-	list_for_each_entry(dev, &nvm_devices, devices) {
-		if (sz > 4095 - DISK_NAME_LEN - 2)
-			break;
-		sz += sprintf(buf + sz, " %32s\n", dev->name);
-	}
-	up_write(&nvm_lock);
-
-	return sz;
-}
-
-static const struct kernel_param_ops nvm_configure_by_str_event_param_ops = {
-	.set	= nvm_configure_by_str_event,
-	.get	= nvm_configure_get,
-};
-
-#undef MODULE_PARAM_PREFIX
-#define MODULE_PARAM_PREFIX	"lnvm."
-
-module_param_cb(configure_debug, &nvm_configure_by_str_event_param_ops, NULL,
-									0644);
-
-#endif /* CONFIG_NVM_DEBUG */
-
 static long nvm_ioctl_info(struct file *file, void __user *arg)
 {
 	struct nvm_ioctl_info *info;
@@ -1162,10 +1129,4 @@ static struct miscdevice _nvm_misc = {
 	.nodename	= "lightnvm/control",
 	.fops		= &_ctl_fops,
 };
-module_misc_device(_nvm_misc);
-
-MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
-
-MODULE_AUTHOR("Matias Bjorling <m@bjorling.me>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("0.1");
+builtin_misc_device(_nvm_misc);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/gennvm.c linux-libre-4.10-rc8-gnu/drivers/lightnvm/gennvm.c
--- linux-libre-4.9-gnu/drivers/lightnvm/gennvm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/gennvm.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,165 @@ static const struct block_device_operati
 	.owner		= THIS_MODULE,
 };
 
+static int gen_reserve_luns(struct nvm_dev *dev, struct nvm_target *t,
+			    int lun_begin, int lun_end)
+{
+	int i;
+
+	for (i = lun_begin; i <= lun_end; i++) {
+		if (test_and_set_bit(i, dev->lun_map)) {
+			pr_err("nvm: lun %d already allocated\n", i);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	while (--i > lun_begin)
+		clear_bit(i, dev->lun_map);
+
+	return -EBUSY;
+}
+
+static void gen_release_luns_err(struct nvm_dev *dev, int lun_begin,
+				 int lun_end)
+{
+	int i;
+
+	for (i = lun_begin; i <= lun_end; i++)
+		WARN_ON(!test_and_clear_bit(i, dev->lun_map));
+}
+
+static void gen_remove_tgt_dev(struct nvm_tgt_dev *tgt_dev)
+{
+	struct nvm_dev *dev = tgt_dev->parent;
+	struct gen_dev_map *dev_map = tgt_dev->map;
+	int i, j;
+
+	for (i = 0; i < dev_map->nr_chnls; i++) {
+		struct gen_ch_map *ch_map = &dev_map->chnls[i];
+		int *lun_offs = ch_map->lun_offs;
+		int ch = i + ch_map->ch_off;
+
+		for (j = 0; j < ch_map->nr_luns; j++) {
+			int lun = j + lun_offs[j];
+			int lunid = (ch * dev->geo.luns_per_chnl) + lun;
+
+			WARN_ON(!test_and_clear_bit(lunid, dev->lun_map));
+		}
+
+		kfree(ch_map->lun_offs);
+	}
+
+	kfree(dev_map->chnls);
+	kfree(dev_map);
+	kfree(tgt_dev->luns);
+	kfree(tgt_dev);
+}
+
+static struct nvm_tgt_dev *gen_create_tgt_dev(struct nvm_dev *dev,
+					      int lun_begin, int lun_end)
+{
+	struct nvm_tgt_dev *tgt_dev = NULL;
+	struct gen_dev_map *dev_rmap = dev->rmap;
+	struct gen_dev_map *dev_map;
+	struct ppa_addr *luns;
+	int nr_luns = lun_end - lun_begin + 1;
+	int luns_left = nr_luns;
+	int nr_chnls = nr_luns / dev->geo.luns_per_chnl;
+	int nr_chnls_mod = nr_luns % dev->geo.luns_per_chnl;
+	int bch = lun_begin / dev->geo.luns_per_chnl;
+	int blun = lun_begin % dev->geo.luns_per_chnl;
+	int lunid = 0;
+	int lun_balanced = 1;
+	int prev_nr_luns;
+	int i, j;
+
+	nr_chnls = nr_luns / dev->geo.luns_per_chnl;
+	nr_chnls = (nr_chnls_mod == 0) ? nr_chnls : nr_chnls + 1;
+
+	dev_map = kmalloc(sizeof(struct gen_dev_map), GFP_KERNEL);
+	if (!dev_map)
+		goto err_dev;
+
+	dev_map->chnls = kcalloc(nr_chnls, sizeof(struct gen_ch_map),
+								GFP_KERNEL);
+	if (!dev_map->chnls)
+		goto err_chnls;
+
+	luns = kcalloc(nr_luns, sizeof(struct ppa_addr), GFP_KERNEL);
+	if (!luns)
+		goto err_luns;
+
+	prev_nr_luns = (luns_left > dev->geo.luns_per_chnl) ?
+					dev->geo.luns_per_chnl : luns_left;
+	for (i = 0; i < nr_chnls; i++) {
+		struct gen_ch_map *ch_rmap = &dev_rmap->chnls[i + bch];
+		int *lun_roffs = ch_rmap->lun_offs;
+		struct gen_ch_map *ch_map = &dev_map->chnls[i];
+		int *lun_offs;
+		int luns_in_chnl = (luns_left > dev->geo.luns_per_chnl) ?
+					dev->geo.luns_per_chnl : luns_left;
+
+		if (lun_balanced && prev_nr_luns != luns_in_chnl)
+			lun_balanced = 0;
+
+		ch_map->ch_off = ch_rmap->ch_off = bch;
+		ch_map->nr_luns = luns_in_chnl;
+
+		lun_offs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
+		if (!lun_offs)
+			goto err_ch;
+
+		for (j = 0; j < luns_in_chnl; j++) {
+			luns[lunid].ppa = 0;
+			luns[lunid].g.ch = i;
+			luns[lunid++].g.lun = j;
+
+			lun_offs[j] = blun;
+			lun_roffs[j + blun] = blun;
+		}
+
+		ch_map->lun_offs = lun_offs;
+
+		/* when starting a new channel, lun offset is reset */
+		blun = 0;
+		luns_left -= luns_in_chnl;
+	}
+
+	dev_map->nr_chnls = nr_chnls;
+
+	tgt_dev = kmalloc(sizeof(struct nvm_tgt_dev), GFP_KERNEL);
+	if (!tgt_dev)
+		goto err_ch;
+
+	memcpy(&tgt_dev->geo, &dev->geo, sizeof(struct nvm_geo));
+	/* Target device only owns a portion of the physical device */
+	tgt_dev->geo.nr_chnls = nr_chnls;
+	tgt_dev->geo.nr_luns = nr_luns;
+	tgt_dev->geo.luns_per_chnl = (lun_balanced) ? prev_nr_luns : -1;
+	tgt_dev->total_secs = nr_luns * tgt_dev->geo.sec_per_lun;
+	tgt_dev->q = dev->q;
+	tgt_dev->map = dev_map;
+	tgt_dev->luns = luns;
+	memcpy(&tgt_dev->identity, &dev->identity, sizeof(struct nvm_id));
+
+	tgt_dev->parent = dev;
+
+	return tgt_dev;
+err_ch:
+	while (--i > 0)
+		kfree(dev_map->chnls[i].lun_offs);
+	kfree(luns);
+err_luns:
+	kfree(dev_map->chnls);
+err_chnls:
+	kfree(dev_map);
+err_dev:
+	return tgt_dev;
+}
+
 static int gen_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create)
 {
 	struct gen_dev *gn = dev->mp;
@@ -43,6 +202,7 @@ static int gen_create_tgt(struct nvm_dev
 	struct gendisk *tdisk;
 	struct nvm_tgt_type *tt;
 	struct nvm_target *t;
+	struct nvm_tgt_dev *tgt_dev;
 	void *targetdata;
 
 	tt = nvm_find_target_type(create->tgttype, 1);
@@ -64,9 +224,18 @@ static int gen_create_tgt(struct nvm_dev
 	if (!t)
 		return -ENOMEM;
 
+	if (gen_reserve_luns(dev, t, s->lun_begin, s->lun_end))
+		goto err_t;
+
+	tgt_dev = gen_create_tgt_dev(dev, s->lun_begin, s->lun_end);
+	if (!tgt_dev) {
+		pr_err("nvm: could not create target device\n");
+		goto err_reserve;
+	}
+
 	tqueue = blk_alloc_queue_node(GFP_KERNEL, dev->q->node);
 	if (!tqueue)
-		goto err_t;
+		goto err_dev;
 	blk_queue_make_request(tqueue, tt->make_rq);
 
 	tdisk = alloc_disk(0);
@@ -80,7 +249,7 @@ static int gen_create_tgt(struct nvm_dev
 	tdisk->fops = &gen_fops;
 	tdisk->queue = tqueue;
 
-	targetdata = tt->init(dev, tdisk, s->lun_begin, s->lun_end);
+	targetdata = tt->init(tgt_dev, tdisk);
 	if (IS_ERR(targetdata))
 		goto err_init;
 
@@ -94,7 +263,7 @@ static int gen_create_tgt(struct nvm_dev
 
 	t->type = tt;
 	t->disk = tdisk;
-	t->dev = dev;
+	t->dev = tgt_dev;
 
 	mutex_lock(&gn->lock);
 	list_add_tail(&t->list, &gn->targets);
@@ -105,6 +274,10 @@ err_init:
 	put_disk(tdisk);
 err_queue:
 	blk_cleanup_queue(tqueue);
+err_dev:
+	kfree(tgt_dev);
+err_reserve:
+	gen_release_luns_err(dev, s->lun_begin, s->lun_end);
 err_t:
 	kfree(t);
 	return -ENOMEM;
@@ -122,6 +295,7 @@ static void __gen_remove_target(struct n
 	if (tt->exit)
 		tt->exit(tdisk->private_data);
 
+	gen_remove_tgt_dev(t->dev);
 	put_disk(tdisk);
 
 	list_del(&t->list);
@@ -160,10 +334,11 @@ static int gen_remove_tgt(struct nvm_dev
 
 static int gen_get_area(struct nvm_dev *dev, sector_t *lba, sector_t len)
 {
+	struct nvm_geo *geo = &dev->geo;
 	struct gen_dev *gn = dev->mp;
 	struct gen_area *area, *prev, *next;
 	sector_t begin = 0;
-	sector_t max_sectors = (dev->sec_size * dev->total_secs) >> 9;
+	sector_t max_sectors = (geo->sec_size * dev->total_secs) >> 9;
 
 	if (len > max_sectors)
 		return -EINVAL;
@@ -220,240 +395,74 @@ static void gen_put_area(struct nvm_dev
 	spin_unlock(&dev->lock);
 }
 
-static void gen_blocks_free(struct nvm_dev *dev)
-{
-	struct gen_dev *gn = dev->mp;
-	struct gen_lun *lun;
-	int i;
-
-	gen_for_each_lun(gn, lun, i) {
-		if (!lun->vlun.blocks)
-			break;
-		vfree(lun->vlun.blocks);
-	}
-}
-
-static void gen_luns_free(struct nvm_dev *dev)
-{
-	struct gen_dev *gn = dev->mp;
-
-	kfree(gn->luns);
-}
-
-static int gen_luns_init(struct nvm_dev *dev, struct gen_dev *gn)
-{
-	struct gen_lun *lun;
-	int i;
-
-	gn->luns = kcalloc(dev->nr_luns, sizeof(struct gen_lun), GFP_KERNEL);
-	if (!gn->luns)
-		return -ENOMEM;
-
-	gen_for_each_lun(gn, lun, i) {
-		spin_lock_init(&lun->vlun.lock);
-		INIT_LIST_HEAD(&lun->free_list);
-		INIT_LIST_HEAD(&lun->used_list);
-		INIT_LIST_HEAD(&lun->bb_list);
-
-		lun->reserved_blocks = 2; /* for GC only */
-		lun->vlun.id = i;
-		lun->vlun.lun_id = i % dev->luns_per_chnl;
-		lun->vlun.chnl_id = i / dev->luns_per_chnl;
-		lun->vlun.nr_free_blocks = dev->blks_per_lun;
-	}
-	return 0;
-}
-
-static int gen_block_bb(struct gen_dev *gn, struct ppa_addr ppa,
-							u8 *blks, int nr_blks)
-{
-	struct nvm_dev *dev = gn->dev;
-	struct gen_lun *lun;
-	struct nvm_block *blk;
-	int i;
-
-	nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks);
-	if (nr_blks < 0)
-		return nr_blks;
-
-	lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun];
-
-	for (i = 0; i < nr_blks; i++) {
-		if (blks[i] == 0)
-			continue;
-
-		blk = &lun->vlun.blocks[i];
-		list_move_tail(&blk->list, &lun->bb_list);
-		lun->vlun.nr_free_blocks--;
-	}
-
-	return 0;
-}
-
-static int gen_block_map(u64 slba, u32 nlb, __le64 *entries, void *private)
-{
-	struct nvm_dev *dev = private;
-	struct gen_dev *gn = dev->mp;
-	u64 elba = slba + nlb;
-	struct gen_lun *lun;
-	struct nvm_block *blk;
-	u64 i;
-	int lun_id;
-
-	if (unlikely(elba > dev->total_secs)) {
-		pr_err("gen: L2P data from device is out of bounds!\n");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < nlb; i++) {
-		u64 pba = le64_to_cpu(entries[i]);
-
-		if (unlikely(pba >= dev->total_secs && pba != U64_MAX)) {
-			pr_err("gen: L2P data entry is out of bounds!\n");
-			return -EINVAL;
-		}
-
-		/* Address zero is a special one. The first page on a disk is
-		 * protected. It often holds internal device boot
-		 * information.
-		 */
-		if (!pba)
-			continue;
-
-		/* resolve block from physical address */
-		lun_id = div_u64(pba, dev->sec_per_lun);
-		lun = &gn->luns[lun_id];
-
-		/* Calculate block offset into lun */
-		pba = pba - (dev->sec_per_lun * lun_id);
-		blk = &lun->vlun.blocks[div_u64(pba, dev->sec_per_blk)];
-
-		if (!blk->state) {
-			/* at this point, we don't know anything about the
-			 * block. It's up to the FTL on top to re-etablish the
-			 * block state. The block is assumed to be open.
-			 */
-			list_move_tail(&blk->list, &lun->used_list);
-			blk->state = NVM_BLK_ST_TGT;
-			lun->vlun.nr_free_blocks--;
-		}
-	}
-
-	return 0;
-}
-
-static int gen_blocks_init(struct nvm_dev *dev, struct gen_dev *gn)
-{
-	struct gen_lun *lun;
-	struct nvm_block *block;
-	sector_t lun_iter, blk_iter, cur_block_id = 0;
-	int ret, nr_blks;
-	u8 *blks;
-
-	nr_blks = dev->blks_per_lun * dev->plane_mode;
-	blks = kmalloc(nr_blks, GFP_KERNEL);
-	if (!blks)
-		return -ENOMEM;
-
-	gen_for_each_lun(gn, lun, lun_iter) {
-		lun->vlun.blocks = vzalloc(sizeof(struct nvm_block) *
-							dev->blks_per_lun);
-		if (!lun->vlun.blocks) {
-			kfree(blks);
-			return -ENOMEM;
-		}
-
-		for (blk_iter = 0; blk_iter < dev->blks_per_lun; blk_iter++) {
-			block = &lun->vlun.blocks[blk_iter];
-
-			INIT_LIST_HEAD(&block->list);
-
-			block->lun = &lun->vlun;
-			block->id = cur_block_id++;
-
-			/* First block is reserved for device */
-			if (unlikely(lun_iter == 0 && blk_iter == 0)) {
-				lun->vlun.nr_free_blocks--;
-				continue;
-			}
-
-			list_add_tail(&block->list, &lun->free_list);
-		}
-
-		if (dev->ops->get_bb_tbl) {
-			struct ppa_addr ppa;
-
-			ppa.ppa = 0;
-			ppa.g.ch = lun->vlun.chnl_id;
-			ppa.g.lun = lun->vlun.lun_id;
-
-			ret = nvm_get_bb_tbl(dev, ppa, blks);
-			if (ret)
-				pr_err("gen: could not get BB table\n");
-
-			ret = gen_block_bb(gn, ppa, blks, nr_blks);
-			if (ret)
-				pr_err("gen: BB table map failed\n");
-		}
-	}
-
-	if ((dev->identity.dom & NVM_RSP_L2P) && dev->ops->get_l2p_tbl) {
-		ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_secs,
-							gen_block_map, dev);
-		if (ret) {
-			pr_err("gen: could not read L2P table.\n");
-			pr_warn("gen: default block initialization");
-		}
-	}
-
-	kfree(blks);
-	return 0;
-}
-
 static void gen_free(struct nvm_dev *dev)
 {
-	gen_blocks_free(dev);
-	gen_luns_free(dev);
 	kfree(dev->mp);
+	kfree(dev->rmap);
 	dev->mp = NULL;
 }
 
 static int gen_register(struct nvm_dev *dev)
 {
 	struct gen_dev *gn;
-	int ret;
+	struct gen_dev_map *dev_rmap;
+	int i, j;
 
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
 
 	gn = kzalloc(sizeof(struct gen_dev), GFP_KERNEL);
 	if (!gn)
-		return -ENOMEM;
+		goto err_gn;
+
+	dev_rmap = kmalloc(sizeof(struct gen_dev_map), GFP_KERNEL);
+	if (!dev_rmap)
+		goto err_rmap;
+
+	dev_rmap->chnls = kcalloc(dev->geo.nr_chnls, sizeof(struct gen_ch_map),
+								GFP_KERNEL);
+	if (!dev_rmap->chnls)
+		goto err_chnls;
+
+	for (i = 0; i < dev->geo.nr_chnls; i++) {
+		struct gen_ch_map *ch_rmap;
+		int *lun_roffs;
+		int luns_in_chnl = dev->geo.luns_per_chnl;
+
+		ch_rmap = &dev_rmap->chnls[i];
+
+		ch_rmap->ch_off = -1;
+		ch_rmap->nr_luns = luns_in_chnl;
+
+		lun_roffs = kcalloc(luns_in_chnl, sizeof(int), GFP_KERNEL);
+		if (!lun_roffs)
+			goto err_ch;
+
+		for (j = 0; j < luns_in_chnl; j++)
+			lun_roffs[j] = -1;
+
+		ch_rmap->lun_offs = lun_roffs;
+	}
 
 	gn->dev = dev;
-	gn->nr_luns = dev->nr_luns;
+	gn->nr_luns = dev->geo.nr_luns;
 	INIT_LIST_HEAD(&gn->area_list);
 	mutex_init(&gn->lock);
 	INIT_LIST_HEAD(&gn->targets);
 	dev->mp = gn;
-
-	ret = gen_luns_init(dev, gn);
-	if (ret) {
-		pr_err("gen: could not initialize luns\n");
-		goto err;
-	}
-
-	ret = gen_blocks_init(dev, gn);
-	if (ret) {
-		pr_err("gen: could not initialize blocks\n");
-		goto err;
-	}
+	dev->rmap = dev_rmap;
 
 	return 1;
-err:
+err_ch:
+	while (--i >= 0)
+		kfree(dev_rmap->chnls[i].lun_offs);
+err_chnls:
+	kfree(dev_rmap);
+err_rmap:
 	gen_free(dev);
+err_gn:
 	module_put(THIS_MODULE);
-	return ret;
+	return -ENOMEM;
 }
 
 static void gen_unregister(struct nvm_dev *dev)
@@ -463,7 +472,7 @@ static void gen_unregister(struct nvm_de
 
 	mutex_lock(&gn->lock);
 	list_for_each_entry_safe(t, tmp, &gn->targets, list) {
-		if (t->dev != dev)
+		if (t->dev->parent != dev)
 			continue;
 		__gen_remove_target(t);
 	}
@@ -473,168 +482,142 @@ static void gen_unregister(struct nvm_de
 	module_put(THIS_MODULE);
 }
 
-static struct nvm_block *gen_get_blk(struct nvm_dev *dev,
-				struct nvm_lun *vlun, unsigned long flags)
+static int gen_map_to_dev(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
-	struct gen_lun *lun = container_of(vlun, struct gen_lun, vlun);
-	struct nvm_block *blk = NULL;
-	int is_gc = flags & NVM_IOTYPE_GC;
-
-	spin_lock(&vlun->lock);
-	if (list_empty(&lun->free_list)) {
-		pr_err_ratelimited("gen: lun %u have no free pages available",
-								lun->vlun.id);
-		goto out;
-	}
-
-	if (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks)
-		goto out;
-
-	blk = list_first_entry(&lun->free_list, struct nvm_block, list);
+	struct gen_dev_map *dev_map = tgt_dev->map;
+	struct gen_ch_map *ch_map = &dev_map->chnls[p->g.ch];
+	int lun_off = ch_map->lun_offs[p->g.lun];
+	struct nvm_dev *dev = tgt_dev->parent;
+	struct gen_dev_map *dev_rmap = dev->rmap;
+	struct gen_ch_map *ch_rmap;
+	int lun_roff;
 
-	list_move_tail(&blk->list, &lun->used_list);
-	blk->state = NVM_BLK_ST_TGT;
-	lun->vlun.nr_free_blocks--;
-out:
-	spin_unlock(&vlun->lock);
-	return blk;
-}
+	p->g.ch += ch_map->ch_off;
+	p->g.lun += lun_off;
 
-static void gen_put_blk(struct nvm_dev *dev, struct nvm_block *blk)
-{
-	struct nvm_lun *vlun = blk->lun;
-	struct gen_lun *lun = container_of(vlun, struct gen_lun, vlun);
+	ch_rmap = &dev_rmap->chnls[p->g.ch];
+	lun_roff = ch_rmap->lun_offs[p->g.lun];
 
-	spin_lock(&vlun->lock);
-	if (blk->state & NVM_BLK_ST_TGT) {
-		list_move_tail(&blk->list, &lun->free_list);
-		lun->vlun.nr_free_blocks++;
-		blk->state = NVM_BLK_ST_FREE;
-	} else if (blk->state & NVM_BLK_ST_BAD) {
-		list_move_tail(&blk->list, &lun->bb_list);
-		blk->state = NVM_BLK_ST_BAD;
-	} else {
-		WARN_ON_ONCE(1);
-		pr_err("gen: erroneous block type (%lu -> %u)\n",
-							blk->id, blk->state);
-		list_move_tail(&blk->list, &lun->bb_list);
+	if (unlikely(ch_rmap->ch_off < 0 || lun_roff < 0)) {
+		pr_err("nvm: corrupted device partition table\n");
+		return -EINVAL;
 	}
-	spin_unlock(&vlun->lock);
+
+	return 0;
 }
 
-static void gen_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type)
+static int gen_map_to_tgt(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p)
 {
-	struct gen_dev *gn = dev->mp;
-	struct gen_lun *lun;
-	struct nvm_block *blk;
-
-	pr_debug("gen: ppa  (ch: %u lun: %u blk: %u pg: %u) -> %u\n",
-			ppa.g.ch, ppa.g.lun, ppa.g.blk, ppa.g.pg, type);
-
-	if (unlikely(ppa.g.ch > dev->nr_chnls ||
-					ppa.g.lun > dev->luns_per_chnl ||
-					ppa.g.blk > dev->blks_per_lun)) {
-		WARN_ON_ONCE(1);
-		pr_err("gen: ppa broken (ch: %u > %u lun: %u > %u blk: %u > %u",
-				ppa.g.ch, dev->nr_chnls,
-				ppa.g.lun, dev->luns_per_chnl,
-				ppa.g.blk, dev->blks_per_lun);
-		return;
-	}
+	struct nvm_dev *dev = tgt_dev->parent;
+	struct gen_dev_map *dev_rmap = dev->rmap;
+	struct gen_ch_map *ch_rmap = &dev_rmap->chnls[p->g.ch];
+	int lun_roff = ch_rmap->lun_offs[p->g.lun];
 
-	lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun];
-	blk = &lun->vlun.blocks[ppa.g.blk];
+	p->g.ch -= ch_rmap->ch_off;
+	p->g.lun -= lun_roff;
 
-	/* will be moved to bb list on put_blk from target */
-	blk->state = type;
+	return 0;
 }
 
-/*
- * mark block bad in gen. It is expected that the target recovers separately
- */
-static void gen_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd)
+static int gen_trans_rq(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd,
+			int flag)
 {
-	int bit = -1;
-	int max_secs = dev->ops->max_phys_sect;
-	void *comp_bits = &rqd->ppa_status;
+	gen_trans_fn *f;
+	int i;
+	int ret = 0;
 
-	nvm_addr_to_generic_mode(dev, rqd);
+	f = (flag == TRANS_TGT_TO_DEV) ? gen_map_to_dev : gen_map_to_tgt;
 
-	/* look up blocks and mark them as bad */
-	if (rqd->nr_ppas == 1) {
-		gen_mark_blk(dev, rqd->ppa_addr, NVM_BLK_ST_BAD);
-		return;
+	if (rqd->nr_ppas == 1)
+		return f(tgt_dev, &rqd->ppa_addr);
+
+	for (i = 0; i < rqd->nr_ppas; i++) {
+		ret = f(tgt_dev, &rqd->ppa_list[i]);
+		if (ret)
+			goto out;
 	}
 
-	while ((bit = find_next_bit(comp_bits, max_secs, bit + 1)) < max_secs)
-		gen_mark_blk(dev, rqd->ppa_list[bit], NVM_BLK_ST_BAD);
+out:
+	return ret;
 }
 
 static void gen_end_io(struct nvm_rq *rqd)
 {
+	struct nvm_tgt_dev *tgt_dev = rqd->dev;
 	struct nvm_tgt_instance *ins = rqd->ins;
 
-	if (rqd->error == NVM_RSP_ERR_FAILWRITE)
-		gen_mark_blk_bad(rqd->dev, rqd);
+	/* Convert address space */
+	if (tgt_dev)
+		gen_trans_rq(tgt_dev, rqd, TRANS_DEV_TO_TGT);
 
 	ins->tt->end_io(rqd);
 }
 
-static int gen_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
+static int gen_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd)
 {
+	struct nvm_dev *dev = tgt_dev->parent;
+
 	if (!dev->ops->submit_io)
 		return -ENODEV;
 
 	/* Convert address space */
+	gen_trans_rq(tgt_dev, rqd, TRANS_TGT_TO_DEV);
 	nvm_generic_to_addr_mode(dev, rqd);
 
-	rqd->dev = dev;
+	rqd->dev = tgt_dev;
 	rqd->end_io = gen_end_io;
 	return dev->ops->submit_io(dev, rqd);
 }
 
-static int gen_erase_blk(struct nvm_dev *dev, struct nvm_block *blk,
-							unsigned long flags)
+static int gen_erase_blk(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *p,
+			 int flags)
 {
-	struct ppa_addr addr = block_to_ppa(dev, blk);
+	/* Convert address space */
+	gen_map_to_dev(tgt_dev, p);
 
-	return nvm_erase_ppa(dev, &addr, 1);
+	return nvm_erase_ppa(tgt_dev->parent, p, 1, flags);
 }
 
-static int gen_reserve_lun(struct nvm_dev *dev, int lunid)
+static struct ppa_addr gen_trans_ppa(struct nvm_tgt_dev *tgt_dev,
+				     struct ppa_addr p, int direction)
 {
-	return test_and_set_bit(lunid, dev->lun_map);
-}
+	gen_trans_fn *f;
+	struct ppa_addr ppa = p;
 
-static void gen_release_lun(struct nvm_dev *dev, int lunid)
-{
-	WARN_ON(!test_and_clear_bit(lunid, dev->lun_map));
+	f = (direction == TRANS_TGT_TO_DEV) ? gen_map_to_dev : gen_map_to_tgt;
+	f(tgt_dev, &ppa);
+
+	return ppa;
 }
 
-static struct nvm_lun *gen_get_lun(struct nvm_dev *dev, int lunid)
+static void gen_part_to_tgt(struct nvm_dev *dev, sector_t *entries,
+			       int len)
 {
-	struct gen_dev *gn = dev->mp;
-
-	if (unlikely(lunid >= dev->nr_luns))
-		return NULL;
+	struct nvm_geo *geo = &dev->geo;
+	struct gen_dev_map *dev_rmap = dev->rmap;
+	u64 i;
 
-	return &gn->luns[lunid].vlun;
-}
+	for (i = 0; i < len; i++) {
+		struct gen_ch_map *ch_rmap;
+		int *lun_roffs;
+		struct ppa_addr gaddr;
+		u64 pba = le64_to_cpu(entries[i]);
+		int off;
+		u64 diff;
 
-static void gen_lun_info_print(struct nvm_dev *dev)
-{
-	struct gen_dev *gn = dev->mp;
-	struct gen_lun *lun;
-	unsigned int i;
+		if (!pba)
+			continue;
 
+		gaddr = linear_to_generic_addr(geo, pba);
+		ch_rmap = &dev_rmap->chnls[gaddr.g.ch];
+		lun_roffs = ch_rmap->lun_offs;
 
-	gen_for_each_lun(gn, lun, i) {
-		spin_lock(&lun->vlun.lock);
+		off = gaddr.g.ch * geo->luns_per_chnl + gaddr.g.lun;
 
-		pr_info("%s: lun%8u\t%u\n", dev->name, i,
-						lun->vlun.nr_free_blocks);
+		diff = ((ch_rmap->ch_off * geo->luns_per_chnl) +
+				(lun_roffs[gaddr.g.lun])) * geo->sec_per_lun;
 
-		spin_unlock(&lun->vlun.lock);
+		entries[i] -= cpu_to_le64(diff);
 	}
 }
 
@@ -648,22 +631,14 @@ static struct nvmm_type gen = {
 	.create_tgt		= gen_create_tgt,
 	.remove_tgt		= gen_remove_tgt,
 
-	.get_blk		= gen_get_blk,
-	.put_blk		= gen_put_blk,
-
 	.submit_io		= gen_submit_io,
 	.erase_blk		= gen_erase_blk,
 
-	.mark_blk		= gen_mark_blk,
-
-	.get_lun		= gen_get_lun,
-	.reserve_lun		= gen_reserve_lun,
-	.release_lun		= gen_release_lun,
-	.lun_info_print		= gen_lun_info_print,
-
 	.get_area		= gen_get_area,
 	.put_area		= gen_put_area,
 
+	.trans_ppa		= gen_trans_ppa,
+	.part_to_tgt		= gen_part_to_tgt,
 };
 
 static int __init gen_module_init(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/gennvm.h linux-libre-4.10-rc8-gnu/drivers/lightnvm/gennvm.h
--- linux-libre-4.9-gnu/drivers/lightnvm/gennvm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/gennvm.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,37 +20,41 @@
 
 #include <linux/lightnvm.h>
 
-struct gen_lun {
-	struct nvm_lun vlun;
-
-	int reserved_blocks;
-	/* lun block lists */
-	struct list_head used_list;	/* In-use blocks */
-	struct list_head free_list;	/* Not used blocks i.e. released
-					 * and ready for use
-					 */
-	struct list_head bb_list;	/* Bad blocks. Mutually exclusive with
-					 * free_list and used_list
-					 */
-};
-
 struct gen_dev {
 	struct nvm_dev *dev;
 
 	int nr_luns;
-	struct gen_lun *luns;
 	struct list_head area_list;
 
 	struct mutex lock;
 	struct list_head targets;
 };
 
+/* Map between virtual and physical channel and lun */
+struct gen_ch_map {
+	int ch_off;
+	int nr_luns;
+	int *lun_offs;
+};
+
+struct gen_dev_map {
+	struct gen_ch_map *chnls;
+	int nr_chnls;
+};
+
 struct gen_area {
 	struct list_head list;
 	sector_t begin;
 	sector_t end;	/* end is excluded */
 };
 
+static inline void *ch_map_to_lun_offs(struct gen_ch_map *ch_map)
+{
+	return ch_map + 1;
+}
+
+typedef int (gen_trans_fn)(struct nvm_tgt_dev *, struct ppa_addr *);
+
 #define gen_for_each_lun(bm, lun, i) \
 		for ((i) = 0, lun = &(bm)->luns[0]; \
 			(i) < (bm)->nr_luns; (i)++, lun = &(bm)->luns[(i)])
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/lightnvm.h linux-libre-4.10-rc8-gnu/drivers/lightnvm/lightnvm.h
--- linux-libre-4.9-gnu/drivers/lightnvm/lightnvm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/lightnvm.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2016 CNEX Labs. All rights reserved.
- * Initial release: Matias Bjorling <matias@cnexlabs.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING.  If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- */
-
-#ifndef LIGHTNVM_H
-#define LIGHTNVM_H
-
-#include <linux/lightnvm.h>
-
-/* core -> sysfs.c */
-int __must_check nvm_sysfs_register_dev(struct nvm_dev *);
-void nvm_sysfs_unregister_dev(struct nvm_dev *);
-int nvm_sysfs_register(void);
-void nvm_sysfs_unregister(void);
-
-/* sysfs > core */
-void nvm_free(struct nvm_dev *);
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/Makefile linux-libre-4.10-rc8-gnu/drivers/lightnvm/Makefile
--- linux-libre-4.9-gnu/drivers/lightnvm/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,6 +2,6 @@
 # Makefile for Open-Channel SSDs.
 #
 
-obj-$(CONFIG_NVM)		:= core.o sysblk.o sysfs.o
+obj-$(CONFIG_NVM)		:= core.o sysblk.o
 obj-$(CONFIG_NVM_GENNVM) 	+= gennvm.o
 obj-$(CONFIG_NVM_RRPC)		+= rrpc.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/rrpc.c linux-libre-4.10-rc8-gnu/drivers/lightnvm/rrpc.c
--- linux-libre-4.9-gnu/drivers/lightnvm/rrpc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/rrpc.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@ static int rrpc_submit_io(struct rrpc *r
 
 static void rrpc_page_invalidate(struct rrpc *rrpc, struct rrpc_addr *a)
 {
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_block *rblk = a->rblk;
 	unsigned int pg_offset;
 
@@ -38,13 +39,13 @@ static void rrpc_page_invalidate(struct
 
 	spin_lock(&rblk->lock);
 
-	div_u64_rem(a->addr, rrpc->dev->sec_per_blk, &pg_offset);
+	div_u64_rem(a->addr, dev->geo.sec_per_blk, &pg_offset);
 	WARN_ON(test_and_set_bit(pg_offset, rblk->invalid_pages));
 	rblk->nr_invalid_pages++;
 
 	spin_unlock(&rblk->lock);
 
-	rrpc->rev_trans_map[a->addr - rrpc->poffset].addr = ADDR_EMPTY;
+	rrpc->rev_trans_map[a->addr].addr = ADDR_EMPTY;
 }
 
 static void rrpc_invalidate_range(struct rrpc *rrpc, sector_t slba,
@@ -116,62 +117,35 @@ static void rrpc_discard(struct rrpc *rr
 
 static int block_is_full(struct rrpc *rrpc, struct rrpc_block *rblk)
 {
-	return (rblk->next_page == rrpc->dev->sec_per_blk);
+	struct nvm_tgt_dev *dev = rrpc->dev;
+
+	return (rblk->next_page == dev->geo.sec_per_blk);
 }
 
 /* Calculate relative addr for the given block, considering instantiated LUNs */
 static u64 block_to_rel_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
 {
-	struct nvm_block *blk = rblk->parent;
-	int lun_blk = blk->id % (rrpc->dev->blks_per_lun * rrpc->nr_luns);
-
-	return lun_blk * rrpc->dev->sec_per_blk;
-}
-
-/* Calculate global addr for the given block */
-static u64 block_to_addr(struct rrpc *rrpc, struct rrpc_block *rblk)
-{
-	struct nvm_block *blk = rblk->parent;
-
-	return blk->id * rrpc->dev->sec_per_blk;
-}
-
-static struct ppa_addr linear_to_generic_addr(struct nvm_dev *dev,
-							struct ppa_addr r)
-{
-	struct ppa_addr l;
-	int secs, pgs, blks, luns;
-	sector_t ppa = r.ppa;
-
-	l.ppa = 0;
-
-	div_u64_rem(ppa, dev->sec_per_pg, &secs);
-	l.g.sec = secs;
-
-	sector_div(ppa, dev->sec_per_pg);
-	div_u64_rem(ppa, dev->pgs_per_blk, &pgs);
-	l.g.pg = pgs;
-
-	sector_div(ppa, dev->pgs_per_blk);
-	div_u64_rem(ppa, dev->blks_per_lun, &blks);
-	l.g.blk = blks;
-
-	sector_div(ppa, dev->blks_per_lun);
-	div_u64_rem(ppa, dev->luns_per_chnl, &luns);
-	l.g.lun = luns;
-
-	sector_div(ppa, dev->luns_per_chnl);
-	l.g.ch = ppa;
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	struct rrpc_lun *rlun = rblk->rlun;
 
-	return l;
+	return rlun->id * dev->geo.sec_per_blk;
 }
 
-static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_dev *dev, u64 addr)
+static struct ppa_addr rrpc_ppa_to_gaddr(struct nvm_tgt_dev *dev,
+					 struct rrpc_addr *gp)
 {
+	struct rrpc_block *rblk = gp->rblk;
+	struct rrpc_lun *rlun = rblk->rlun;
+	u64 addr = gp->addr;
 	struct ppa_addr paddr;
 
 	paddr.ppa = addr;
-	return linear_to_generic_addr(dev, paddr);
+	paddr = rrpc_linear_to_generic_addr(&dev->geo, paddr);
+	paddr.g.ch = rlun->bppa.g.ch;
+	paddr.g.lun = rlun->bppa.g.lun;
+	paddr.g.blk = rblk->id;
+
+	return paddr;
 }
 
 /* requires lun->lock taken */
@@ -188,21 +162,47 @@ static void rrpc_set_lun_cur(struct rrpc
 	*cur_rblk = new_rblk;
 }
 
+static struct rrpc_block *__rrpc_get_blk(struct rrpc *rrpc,
+							struct rrpc_lun *rlun)
+{
+	struct rrpc_block *rblk = NULL;
+
+	if (list_empty(&rlun->free_list))
+		goto out;
+
+	rblk = list_first_entry(&rlun->free_list, struct rrpc_block, list);
+
+	list_move_tail(&rblk->list, &rlun->used_list);
+	rblk->state = NVM_BLK_ST_TGT;
+	rlun->nr_free_blocks--;
+
+out:
+	return rblk;
+}
+
 static struct rrpc_block *rrpc_get_blk(struct rrpc *rrpc, struct rrpc_lun *rlun,
 							unsigned long flags)
 {
-	struct nvm_block *blk;
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_block *rblk;
+	int is_gc = flags & NVM_IOTYPE_GC;
 
-	blk = nvm_get_blk(rrpc->dev, rlun->parent, flags);
-	if (!blk) {
-		pr_err("nvm: rrpc: cannot get new block from media manager\n");
+	spin_lock(&rlun->lock);
+	if (!is_gc && rlun->nr_free_blocks < rlun->reserved_blocks) {
+		pr_err("nvm: rrpc: cannot give block to non GC request\n");
+		spin_unlock(&rlun->lock);
 		return NULL;
 	}
 
-	rblk = rrpc_get_rblk(rlun, blk->id);
-	blk->priv = rblk;
-	bitmap_zero(rblk->invalid_pages, rrpc->dev->sec_per_blk);
+	rblk = __rrpc_get_blk(rrpc, rlun);
+	if (!rblk) {
+		pr_err("nvm: rrpc: cannot get new block\n");
+		spin_unlock(&rlun->lock);
+		return NULL;
+	}
+	spin_unlock(&rlun->lock);
+
+	bitmap_zero(rblk->invalid_pages, dev->geo.sec_per_blk);
 	rblk->next_page = 0;
 	rblk->nr_invalid_pages = 0;
 	atomic_set(&rblk->data_cmnt_size, 0);
@@ -212,7 +212,24 @@ static struct rrpc_block *rrpc_get_blk(s
 
 static void rrpc_put_blk(struct rrpc *rrpc, struct rrpc_block *rblk)
 {
-	nvm_put_blk(rrpc->dev, rblk->parent);
+	struct rrpc_lun *rlun = rblk->rlun;
+
+	spin_lock(&rlun->lock);
+	if (rblk->state & NVM_BLK_ST_TGT) {
+		list_move_tail(&rblk->list, &rlun->free_list);
+		rlun->nr_free_blocks++;
+		rblk->state = NVM_BLK_ST_FREE;
+	} else if (rblk->state & NVM_BLK_ST_BAD) {
+		list_move_tail(&rblk->list, &rlun->bb_list);
+		rblk->state = NVM_BLK_ST_BAD;
+	} else {
+		WARN_ON_ONCE(1);
+		pr_err("rrpc: erroneous type (ch:%d,lun:%d,blk%d-> %u)\n",
+					rlun->bppa.g.ch, rlun->bppa.g.lun,
+					rblk->id, rblk->state);
+		list_move_tail(&rblk->list, &rlun->bb_list);
+	}
+	spin_unlock(&rlun->lock);
 }
 
 static void rrpc_put_blks(struct rrpc *rrpc)
@@ -280,13 +297,14 @@ static void rrpc_end_sync_bio(struct bio
  */
 static int rrpc_move_valid_pages(struct rrpc *rrpc, struct rrpc_block *rblk)
 {
-	struct request_queue *q = rrpc->dev->q;
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	struct request_queue *q = dev->q;
 	struct rrpc_rev_addr *rev;
 	struct nvm_rq *rqd;
 	struct bio *bio;
 	struct page *page;
 	int slot;
-	int nr_sec_per_blk = rrpc->dev->sec_per_blk;
+	int nr_sec_per_blk = dev->geo.sec_per_blk;
 	u64 phys_addr;
 	DECLARE_COMPLETION_ONSTACK(wait);
 
@@ -309,12 +327,12 @@ static int rrpc_move_valid_pages(struct
 					    nr_sec_per_blk)) < nr_sec_per_blk) {
 
 		/* Lock laddr */
-		phys_addr = rblk->parent->id * nr_sec_per_blk + slot;
+		phys_addr = rrpc_blk_to_ppa(rrpc, rblk) + slot;
 
 try:
 		spin_lock(&rrpc->rev_lock);
 		/* Get logical address from physical to logical table */
-		rev = &rrpc->rev_trans_map[phys_addr - rrpc->poffset];
+		rev = &rrpc->rev_trans_map[phys_addr];
 		/* already updated by previous regular write */
 		if (rev->addr == ADDR_EMPTY) {
 			spin_unlock(&rrpc->rev_lock);
@@ -396,15 +414,23 @@ static void rrpc_block_gc(struct work_st
 	struct rrpc *rrpc = gcb->rrpc;
 	struct rrpc_block *rblk = gcb->rblk;
 	struct rrpc_lun *rlun = rblk->rlun;
-	struct nvm_dev *dev = rrpc->dev;
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	struct ppa_addr ppa;
 
 	mempool_free(gcb, rrpc->gcb_pool);
-	pr_debug("nvm: block '%lu' being reclaimed\n", rblk->parent->id);
+	pr_debug("nvm: block 'ch:%d,lun:%d,blk:%d' being reclaimed\n",
+			rlun->bppa.g.ch, rlun->bppa.g.lun,
+			rblk->id);
 
 	if (rrpc_move_valid_pages(rrpc, rblk))
 		goto put_back;
 
-	if (nvm_erase_blk(dev, rblk->parent))
+	ppa.ppa = 0;
+	ppa.g.ch = rlun->bppa.g.ch;
+	ppa.g.lun = rlun->bppa.g.lun;
+	ppa.g.blk = rblk->id;
+
+	if (nvm_erase_blk(dev, &ppa, 0))
 		goto put_back;
 
 	rrpc_put_blk(rrpc, rblk);
@@ -420,7 +446,7 @@ put_back:
 /* the block with highest number of invalid pages, will be in the beginning
  * of the list
  */
-static struct rrpc_block *rblock_max_invalid(struct rrpc_block *ra,
+static struct rrpc_block *rblk_max_invalid(struct rrpc_block *ra,
 							struct rrpc_block *rb)
 {
 	if (ra->nr_invalid_pages == rb->nr_invalid_pages)
@@ -435,13 +461,13 @@ static struct rrpc_block *rblock_max_inv
 static struct rrpc_block *block_prio_find_max(struct rrpc_lun *rlun)
 {
 	struct list_head *prio_list = &rlun->prio_list;
-	struct rrpc_block *rblock, *max;
+	struct rrpc_block *rblk, *max;
 
 	BUG_ON(list_empty(prio_list));
 
 	max = list_first_entry(prio_list, struct rrpc_block, prio);
-	list_for_each_entry(rblock, prio_list, prio)
-		max = rblock_max_invalid(max, rblock);
+	list_for_each_entry(rblk, prio_list, prio)
+		max = rblk_max_invalid(max, rblk);
 
 	return max;
 }
@@ -450,36 +476,37 @@ static void rrpc_lun_gc(struct work_stru
 {
 	struct rrpc_lun *rlun = container_of(work, struct rrpc_lun, ws_gc);
 	struct rrpc *rrpc = rlun->rrpc;
-	struct nvm_lun *lun = rlun->parent;
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_block_gc *gcb;
 	unsigned int nr_blocks_need;
 
-	nr_blocks_need = rrpc->dev->blks_per_lun / GC_LIMIT_INVERSE;
+	nr_blocks_need = dev->geo.blks_per_lun / GC_LIMIT_INVERSE;
 
 	if (nr_blocks_need < rrpc->nr_luns)
 		nr_blocks_need = rrpc->nr_luns;
 
 	spin_lock(&rlun->lock);
-	while (nr_blocks_need > lun->nr_free_blocks &&
+	while (nr_blocks_need > rlun->nr_free_blocks &&
 					!list_empty(&rlun->prio_list)) {
-		struct rrpc_block *rblock = block_prio_find_max(rlun);
-		struct nvm_block *block = rblock->parent;
+		struct rrpc_block *rblk = block_prio_find_max(rlun);
 
-		if (!rblock->nr_invalid_pages)
+		if (!rblk->nr_invalid_pages)
 			break;
 
 		gcb = mempool_alloc(rrpc->gcb_pool, GFP_ATOMIC);
 		if (!gcb)
 			break;
 
-		list_del_init(&rblock->prio);
+		list_del_init(&rblk->prio);
 
-		BUG_ON(!block_is_full(rrpc, rblock));
+		WARN_ON(!block_is_full(rrpc, rblk));
 
-		pr_debug("rrpc: selected block '%lu' for GC\n", block->id);
+		pr_debug("rrpc: selected block 'ch:%d,lun:%d,blk:%d' for GC\n",
+					rlun->bppa.g.ch, rlun->bppa.g.lun,
+					rblk->id);
 
 		gcb->rrpc = rrpc;
-		gcb->rblk = rblock;
+		gcb->rblk = rblk;
 		INIT_WORK(&gcb->ws_gc, rrpc_block_gc);
 
 		queue_work(rrpc->kgc_wq, &gcb->ws_gc);
@@ -504,8 +531,9 @@ static void rrpc_gc_queue(struct work_st
 	spin_unlock(&rlun->lock);
 
 	mempool_free(gcb, rrpc->gcb_pool);
-	pr_debug("nvm: block '%lu' is full, allow GC (sched)\n",
-							rblk->parent->id);
+	pr_debug("nvm: block 'ch:%d,lun:%d,blk:%d' full, allow GC (sched)\n",
+					rlun->bppa.g.ch, rlun->bppa.g.lun,
+					rblk->id);
 }
 
 static const struct block_device_operations rrpc_fops = {
@@ -529,8 +557,7 @@ static struct rrpc_lun *rrpc_get_lun_rr(
 	 * estimate.
 	 */
 	rrpc_for_each_lun(rrpc, rlun, i) {
-		if (rlun->parent->nr_free_blocks >
-					max_free->parent->nr_free_blocks)
+		if (rlun->nr_free_blocks > max_free->nr_free_blocks)
 			max_free = rlun;
 	}
 
@@ -553,7 +580,7 @@ static struct rrpc_addr *rrpc_update_map
 	gp->addr = paddr;
 	gp->rblk = rblk;
 
-	rev = &rrpc->rev_trans_map[gp->addr - rrpc->poffset];
+	rev = &rrpc->rev_trans_map[gp->addr];
 	rev->addr = laddr;
 	spin_unlock(&rrpc->rev_lock);
 
@@ -568,7 +595,7 @@ static u64 rrpc_alloc_addr(struct rrpc *
 	if (block_is_full(rrpc, rblk))
 		goto out;
 
-	addr = block_to_addr(rrpc, rblk) + rblk->next_page;
+	addr = rblk->next_page;
 
 	rblk->next_page++;
 out:
@@ -582,20 +609,22 @@ out:
  * Returns rrpc_addr with the physical address and block. Returns NULL if no
  * blocks in the next rlun are available.
  */
-static struct rrpc_addr *rrpc_map_page(struct rrpc *rrpc, sector_t laddr,
+static struct ppa_addr rrpc_map_page(struct rrpc *rrpc, sector_t laddr,
 								int is_gc)
 {
+	struct nvm_tgt_dev *tgt_dev = rrpc->dev;
 	struct rrpc_lun *rlun;
 	struct rrpc_block *rblk, **cur_rblk;
-	struct nvm_lun *lun;
+	struct rrpc_addr *p;
+	struct ppa_addr ppa;
 	u64 paddr;
 	int gc_force = 0;
 
+	ppa.ppa = ADDR_EMPTY;
 	rlun = rrpc_get_lun_rr(rrpc, is_gc);
-	lun = rlun->parent;
 
-	if (!is_gc && lun->nr_free_blocks < rrpc->nr_luns * 4)
-		return NULL;
+	if (!is_gc && rlun->nr_free_blocks < rrpc->nr_luns * 4)
+		return ppa;
 
 	/*
 	 * page allocation steps:
@@ -652,10 +681,15 @@ new_blk:
 	}
 
 	pr_err("rrpc: failed to allocate new block\n");
-	return NULL;
+	return ppa;
 done:
 	spin_unlock(&rlun->lock);
-	return rrpc_update_map(rrpc, laddr, rblk, paddr);
+	p = rrpc_update_map(rrpc, laddr, rblk, paddr);
+	if (!p)
+		return ppa;
+
+	/* return global address */
+	return rrpc_ppa_to_gaddr(tgt_dev, p);
 }
 
 static void rrpc_run_gc(struct rrpc *rrpc, struct rrpc_block *rblk)
@@ -675,21 +709,70 @@ static void rrpc_run_gc(struct rrpc *rrp
 	queue_work(rrpc->kgc_wq, &gcb->ws_gc);
 }
 
+static struct rrpc_lun *rrpc_ppa_to_lun(struct rrpc *rrpc, struct ppa_addr p)
+{
+	struct rrpc_lun *rlun = NULL;
+	int i;
+
+	for (i = 0; i < rrpc->nr_luns; i++) {
+		if (rrpc->luns[i].bppa.g.ch == p.g.ch &&
+				rrpc->luns[i].bppa.g.lun == p.g.lun) {
+			rlun = &rrpc->luns[i];
+			break;
+		}
+	}
+
+	return rlun;
+}
+
+static void __rrpc_mark_bad_block(struct rrpc *rrpc, struct ppa_addr ppa)
+{
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	struct rrpc_lun *rlun;
+	struct rrpc_block *rblk;
+
+	rlun = rrpc_ppa_to_lun(rrpc, ppa);
+	rblk = &rlun->blocks[ppa.g.blk];
+	rblk->state = NVM_BLK_ST_BAD;
+
+	nvm_set_tgt_bb_tbl(dev, &ppa, 1, NVM_BLK_T_GRWN_BAD);
+}
+
+static void rrpc_mark_bad_block(struct rrpc *rrpc, struct nvm_rq *rqd)
+{
+	void *comp_bits = &rqd->ppa_status;
+	struct ppa_addr ppa, prev_ppa;
+	int nr_ppas = rqd->nr_ppas;
+	int bit;
+
+	if (rqd->nr_ppas == 1)
+		__rrpc_mark_bad_block(rrpc, rqd->ppa_addr);
+
+	ppa_set_empty(&prev_ppa);
+	bit = -1;
+	while ((bit = find_next_bit(comp_bits, nr_ppas, bit + 1)) < nr_ppas) {
+		ppa = rqd->ppa_list[bit];
+		if (ppa_cmp_blk(ppa, prev_ppa))
+			continue;
+
+		__rrpc_mark_bad_block(rrpc, ppa);
+	}
+}
+
 static void rrpc_end_io_write(struct rrpc *rrpc, struct rrpc_rq *rrqd,
 						sector_t laddr, uint8_t npages)
 {
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_addr *p;
 	struct rrpc_block *rblk;
-	struct nvm_lun *lun;
 	int cmnt_size, i;
 
 	for (i = 0; i < npages; i++) {
 		p = &rrpc->trans_map[laddr + i];
 		rblk = p->rblk;
-		lun = rblk->parent->lun;
 
 		cmnt_size = atomic_inc_return(&rblk->data_cmnt_size);
-		if (unlikely(cmnt_size == rrpc->dev->sec_per_blk))
+		if (unlikely(cmnt_size == dev->geo.sec_per_blk))
 			rrpc_run_gc(rrpc, rblk);
 	}
 }
@@ -697,12 +780,17 @@ static void rrpc_end_io_write(struct rrp
 static void rrpc_end_io(struct nvm_rq *rqd)
 {
 	struct rrpc *rrpc = container_of(rqd->ins, struct rrpc, instance);
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
 	uint8_t npages = rqd->nr_ppas;
 	sector_t laddr = rrpc_get_laddr(rqd->bio) - npages;
 
-	if (bio_data_dir(rqd->bio) == WRITE)
+	if (bio_data_dir(rqd->bio) == WRITE) {
+		if (rqd->error == NVM_RSP_ERR_FAILWRITE)
+			rrpc_mark_bad_block(rrpc, rqd);
+
 		rrpc_end_io_write(rrpc, rrqd, laddr, npages);
+	}
 
 	bio_put(rqd->bio);
 
@@ -712,7 +800,7 @@ static void rrpc_end_io(struct nvm_rq *r
 	rrpc_unlock_rq(rrpc, rqd);
 
 	if (npages > 1)
-		nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+		nvm_dev_dma_free(dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
 
 	mempool_free(rqd, rrpc->rq_pool);
 }
@@ -720,6 +808,7 @@ static void rrpc_end_io(struct nvm_rq *r
 static int rrpc_read_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
 			struct nvm_rq *rqd, unsigned long flags, int npages)
 {
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
 	struct rrpc_addr *gp;
 	sector_t laddr = rrpc_get_laddr(bio);
@@ -727,7 +816,7 @@ static int rrpc_read_ppalist_rq(struct r
 	int i;
 
 	if (!is_gc && rrpc_lock_rq(rrpc, bio, rqd)) {
-		nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+		nvm_dev_dma_free(dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
 		return NVM_IO_REQUEUE;
 	}
 
@@ -737,12 +826,11 @@ static int rrpc_read_ppalist_rq(struct r
 		gp = &rrpc->trans_map[laddr + i];
 
 		if (gp->rblk) {
-			rqd->ppa_list[i] = rrpc_ppa_to_gaddr(rrpc->dev,
-								gp->addr);
+			rqd->ppa_list[i] = rrpc_ppa_to_gaddr(dev, gp);
 		} else {
 			BUG_ON(is_gc);
 			rrpc_unlock_laddr(rrpc, r);
-			nvm_dev_dma_free(rrpc->dev, rqd->ppa_list,
+			nvm_dev_dma_free(dev->parent, rqd->ppa_list,
 							rqd->dma_ppa_list);
 			return NVM_IO_DONE;
 		}
@@ -756,7 +844,6 @@ static int rrpc_read_ppalist_rq(struct r
 static int rrpc_read_rq(struct rrpc *rrpc, struct bio *bio, struct nvm_rq *rqd,
 							unsigned long flags)
 {
-	struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
 	int is_gc = flags & NVM_IOTYPE_GC;
 	sector_t laddr = rrpc_get_laddr(bio);
 	struct rrpc_addr *gp;
@@ -768,7 +855,7 @@ static int rrpc_read_rq(struct rrpc *rrp
 	gp = &rrpc->trans_map[laddr];
 
 	if (gp->rblk) {
-		rqd->ppa_addr = rrpc_ppa_to_gaddr(rrpc->dev, gp->addr);
+		rqd->ppa_addr = rrpc_ppa_to_gaddr(rrpc->dev, gp);
 	} else {
 		BUG_ON(is_gc);
 		rrpc_unlock_rq(rrpc, rqd);
@@ -776,7 +863,6 @@ static int rrpc_read_rq(struct rrpc *rrp
 	}
 
 	rqd->opcode = NVM_OP_HBREAD;
-	rrqd->addr = gp;
 
 	return NVM_IO_OK;
 }
@@ -784,31 +870,31 @@ static int rrpc_read_rq(struct rrpc *rrp
 static int rrpc_write_ppalist_rq(struct rrpc *rrpc, struct bio *bio,
 			struct nvm_rq *rqd, unsigned long flags, int npages)
 {
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd);
-	struct rrpc_addr *p;
+	struct ppa_addr p;
 	sector_t laddr = rrpc_get_laddr(bio);
 	int is_gc = flags & NVM_IOTYPE_GC;
 	int i;
 
 	if (!is_gc && rrpc_lock_rq(rrpc, bio, rqd)) {
-		nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list);
+		nvm_dev_dma_free(dev->parent, rqd->ppa_list, rqd->dma_ppa_list);
 		return NVM_IO_REQUEUE;
 	}
 
 	for (i = 0; i < npages; i++) {
 		/* We assume that mapping occurs at 4KB granularity */
 		p = rrpc_map_page(rrpc, laddr + i, is_gc);
-		if (!p) {
+		if (p.ppa == ADDR_EMPTY) {
 			BUG_ON(is_gc);
 			rrpc_unlock_laddr(rrpc, r);
-			nvm_dev_dma_free(rrpc->dev, rqd->ppa_list,
+			nvm_dev_dma_free(dev->parent, rqd->ppa_list,
 							rqd->dma_ppa_list);
 			rrpc_gc_kick(rrpc);
 			return NVM_IO_REQUEUE;
 		}
 
-		rqd->ppa_list[i] = rrpc_ppa_to_gaddr(rrpc->dev,
-								p->addr);
+		rqd->ppa_list[i] = p;
 	}
 
 	rqd->opcode = NVM_OP_HBWRITE;
@@ -819,8 +905,7 @@ static int rrpc_write_ppalist_rq(struct
 static int rrpc_write_rq(struct rrpc *rrpc, struct bio *bio,
 				struct nvm_rq *rqd, unsigned long flags)
 {
-	struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd);
-	struct rrpc_addr *p;
+	struct ppa_addr p;
 	int is_gc = flags & NVM_IOTYPE_GC;
 	sector_t laddr = rrpc_get_laddr(bio);
 
@@ -828,16 +913,15 @@ static int rrpc_write_rq(struct rrpc *rr
 		return NVM_IO_REQUEUE;
 
 	p = rrpc_map_page(rrpc, laddr, is_gc);
-	if (!p) {
+	if (p.ppa == ADDR_EMPTY) {
 		BUG_ON(is_gc);
 		rrpc_unlock_rq(rrpc, rqd);
 		rrpc_gc_kick(rrpc);
 		return NVM_IO_REQUEUE;
 	}
 
-	rqd->ppa_addr = rrpc_ppa_to_gaddr(rrpc->dev, p->addr);
+	rqd->ppa_addr = p;
 	rqd->opcode = NVM_OP_HBWRITE;
-	rrqd->addr = p;
 
 	return NVM_IO_OK;
 }
@@ -845,8 +929,10 @@ static int rrpc_write_rq(struct rrpc *rr
 static int rrpc_setup_rq(struct rrpc *rrpc, struct bio *bio,
 			struct nvm_rq *rqd, unsigned long flags, uint8_t npages)
 {
+	struct nvm_tgt_dev *dev = rrpc->dev;
+
 	if (npages > 1) {
-		rqd->ppa_list = nvm_dev_dma_alloc(rrpc->dev, GFP_KERNEL,
+		rqd->ppa_list = nvm_dev_dma_alloc(dev->parent, GFP_KERNEL,
 							&rqd->dma_ppa_list);
 		if (!rqd->ppa_list) {
 			pr_err("rrpc: not able to allocate ppa list\n");
@@ -869,14 +955,15 @@ static int rrpc_setup_rq(struct rrpc *rr
 static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio,
 				struct nvm_rq *rqd, unsigned long flags)
 {
-	int err;
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_rq *rrq = nvm_rq_to_pdu(rqd);
 	uint8_t nr_pages = rrpc_get_pages(bio);
 	int bio_size = bio_sectors(bio) << 9;
+	int err;
 
-	if (bio_size < rrpc->dev->sec_size)
+	if (bio_size < dev->geo.sec_size)
 		return NVM_IO_ERR;
-	else if (bio_size > rrpc->dev->max_rq_size)
+	else if (bio_size > dev->geo.max_rq_size)
 		return NVM_IO_ERR;
 
 	err = rrpc_setup_rq(rrpc, bio, rqd, flags, nr_pages);
@@ -889,15 +976,15 @@ static int rrpc_submit_io(struct rrpc *r
 	rqd->nr_ppas = nr_pages;
 	rrq->flags = flags;
 
-	err = nvm_submit_io(rrpc->dev, rqd);
+	err = nvm_submit_io(dev, rqd);
 	if (err) {
 		pr_err("rrpc: I/O submission failed: %d\n", err);
 		bio_put(bio);
 		if (!(flags & NVM_IOTYPE_GC)) {
 			rrpc_unlock_rq(rrpc, rqd);
 			if (rqd->nr_ppas > 1)
-				nvm_dev_dma_free(rrpc->dev,
-			rqd->ppa_list, rqd->dma_ppa_list);
+				nvm_dev_dma_free(dev->parent, rqd->ppa_list,
+							rqd->dma_ppa_list);
 		}
 		return NVM_IO_ERR;
 	}
@@ -911,6 +998,8 @@ static blk_qc_t rrpc_make_rq(struct requ
 	struct nvm_rq *rqd;
 	int err;
 
+	blk_queue_split(q, &bio, q->bio_split);
+
 	if (bio_op(bio) == REQ_OP_DISCARD) {
 		rrpc_discard(rrpc, bio);
 		return BLK_QC_T_NONE;
@@ -997,25 +1086,24 @@ static void rrpc_map_free(struct rrpc *r
 static int rrpc_l2p_update(u64 slba, u32 nlb, __le64 *entries, void *private)
 {
 	struct rrpc *rrpc = (struct rrpc *)private;
-	struct nvm_dev *dev = rrpc->dev;
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_addr *addr = rrpc->trans_map + slba;
 	struct rrpc_rev_addr *raddr = rrpc->rev_trans_map;
-	u64 elba = slba + nlb;
+	struct rrpc_lun *rlun;
+	struct rrpc_block *rblk;
 	u64 i;
 
-	if (unlikely(elba > dev->total_secs)) {
-		pr_err("nvm: L2P data from device is out of bounds!\n");
-		return -EINVAL;
-	}
-
 	for (i = 0; i < nlb; i++) {
+		struct ppa_addr gaddr;
 		u64 pba = le64_to_cpu(entries[i]);
 		unsigned int mod;
+
 		/* LNVM treats address-spaces as silos, LBA and PBA are
 		 * equally large and zero-indexed.
 		 */
 		if (unlikely(pba >= dev->total_secs && pba != U64_MAX)) {
 			pr_err("nvm: L2P data entry is out of bounds!\n");
+			pr_err("nvm: Maybe loaded an old target L2P\n");
 			return -EINVAL;
 		}
 
@@ -1028,7 +1116,27 @@ static int rrpc_l2p_update(u64 slba, u32
 
 		div_u64_rem(pba, rrpc->nr_sects, &mod);
 
+		gaddr = rrpc_recov_addr(dev, pba);
+		rlun = rrpc_ppa_to_lun(rrpc, gaddr);
+		if (!rlun) {
+			pr_err("rrpc: l2p corruption on lba %llu\n",
+							slba + i);
+			return -EINVAL;
+		}
+
+		rblk = &rlun->blocks[gaddr.g.blk];
+		if (!rblk->state) {
+			/* at this point, we don't know anything about the
+			 * block. It's up to the FTL on top to re-etablish the
+			 * block state. The block is assumed to be open.
+			 */
+			list_move_tail(&rblk->list, &rlun->used_list);
+			rblk->state = NVM_BLK_ST_TGT;
+			rlun->nr_free_blocks--;
+		}
+
 		addr[i].addr = pba;
+		addr[i].rblk = rblk;
 		raddr[mod].addr = slba + i;
 	}
 
@@ -1037,7 +1145,7 @@ static int rrpc_l2p_update(u64 slba, u32
 
 static int rrpc_map_init(struct rrpc *rrpc)
 {
-	struct nvm_dev *dev = rrpc->dev;
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	sector_t i;
 	int ret;
 
@@ -1058,12 +1166,9 @@ static int rrpc_map_init(struct rrpc *rr
 		r->addr = ADDR_EMPTY;
 	}
 
-	if (!dev->ops->get_l2p_tbl)
-		return 0;
-
 	/* Bring up the mapping table from device */
-	ret = dev->ops->get_l2p_tbl(dev, rrpc->soffset, rrpc->nr_sects,
-					rrpc_l2p_update, rrpc);
+	ret = nvm_get_l2p_tbl(dev, rrpc->soffset, rrpc->nr_sects,
+							rrpc_l2p_update, rrpc);
 	if (ret) {
 		pr_err("nvm: rrpc: could not read L2P table.\n");
 		return -EINVAL;
@@ -1102,7 +1207,7 @@ static int rrpc_core_init(struct rrpc *r
 	if (!rrpc->page_pool)
 		return -ENOMEM;
 
-	rrpc->gcb_pool = mempool_create_slab_pool(rrpc->dev->nr_luns,
+	rrpc->gcb_pool = mempool_create_slab_pool(rrpc->dev->geo.nr_luns,
 								rrpc_gcb_cache);
 	if (!rrpc->gcb_pool)
 		return -ENOMEM;
@@ -1126,8 +1231,6 @@ static void rrpc_core_free(struct rrpc *
 
 static void rrpc_luns_free(struct rrpc *rrpc)
 {
-	struct nvm_dev *dev = rrpc->dev;
-	struct nvm_lun *lun;
 	struct rrpc_lun *rlun;
 	int i;
 
@@ -1136,23 +1239,74 @@ static void rrpc_luns_free(struct rrpc *
 
 	for (i = 0; i < rrpc->nr_luns; i++) {
 		rlun = &rrpc->luns[i];
-		lun = rlun->parent;
-		if (!lun)
-			break;
-		dev->mt->release_lun(dev, lun->id);
 		vfree(rlun->blocks);
 	}
 
 	kfree(rrpc->luns);
 }
 
-static int rrpc_luns_init(struct rrpc *rrpc, int lun_begin, int lun_end)
+static int rrpc_bb_discovery(struct nvm_tgt_dev *dev, struct rrpc_lun *rlun)
 {
-	struct nvm_dev *dev = rrpc->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct rrpc_block *rblk;
+	struct ppa_addr ppa;
+	u8 *blks;
+	int nr_blks;
+	int i;
+	int ret;
+
+	if (!dev->parent->ops->get_bb_tbl)
+		return 0;
+
+	nr_blks = geo->blks_per_lun * geo->plane_mode;
+	blks = kmalloc(nr_blks, GFP_KERNEL);
+	if (!blks)
+		return -ENOMEM;
+
+	ppa.ppa = 0;
+	ppa.g.ch = rlun->bppa.g.ch;
+	ppa.g.lun = rlun->bppa.g.lun;
+
+	ret = nvm_get_tgt_bb_tbl(dev, ppa, blks);
+	if (ret) {
+		pr_err("rrpc: could not get BB table\n");
+		goto out;
+	}
+
+	nr_blks = nvm_bb_tbl_fold(dev->parent, blks, nr_blks);
+	if (nr_blks < 0)
+		return nr_blks;
+
+	for (i = 0; i < nr_blks; i++) {
+		if (blks[i] == NVM_BLK_T_FREE)
+			continue;
+
+		rblk = &rlun->blocks[i];
+		list_move_tail(&rblk->list, &rlun->bb_list);
+		rblk->state = NVM_BLK_ST_BAD;
+		rlun->nr_free_blocks--;
+	}
+
+out:
+	kfree(blks);
+	return ret;
+}
+
+static void rrpc_set_lun_ppa(struct rrpc_lun *rlun, struct ppa_addr ppa)
+{
+	rlun->bppa.ppa = 0;
+	rlun->bppa.g.ch = ppa.g.ch;
+	rlun->bppa.g.lun = ppa.g.lun;
+}
+
+static int rrpc_luns_init(struct rrpc *rrpc, struct ppa_addr *luns)
+{
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	struct nvm_geo *geo = &dev->geo;
 	struct rrpc_lun *rlun;
 	int i, j, ret = -EINVAL;
 
-	if (dev->sec_per_blk > MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) {
+	if (geo->sec_per_blk > MAX_INVALID_PAGES_STORAGE * BITS_PER_LONG) {
 		pr_err("rrpc: number of pages per block too high.");
 		return -EINVAL;
 	}
@@ -1166,43 +1320,46 @@ static int rrpc_luns_init(struct rrpc *r
 
 	/* 1:1 mapping */
 	for (i = 0; i < rrpc->nr_luns; i++) {
-		int lunid = lun_begin + i;
-		struct nvm_lun *lun;
-
-		if (dev->mt->reserve_lun(dev, lunid)) {
-			pr_err("rrpc: lun %u is already allocated\n", lunid);
-			goto err;
-		}
-
-		lun = dev->mt->get_lun(dev, lunid);
-		if (!lun)
-			goto err;
-
 		rlun = &rrpc->luns[i];
-		rlun->parent = lun;
+		rlun->id = i;
+		rrpc_set_lun_ppa(rlun, luns[i]);
 		rlun->blocks = vzalloc(sizeof(struct rrpc_block) *
-						rrpc->dev->blks_per_lun);
+							geo->blks_per_lun);
 		if (!rlun->blocks) {
 			ret = -ENOMEM;
 			goto err;
 		}
 
-		for (j = 0; j < rrpc->dev->blks_per_lun; j++) {
+		INIT_LIST_HEAD(&rlun->free_list);
+		INIT_LIST_HEAD(&rlun->used_list);
+		INIT_LIST_HEAD(&rlun->bb_list);
+
+		for (j = 0; j < geo->blks_per_lun; j++) {
 			struct rrpc_block *rblk = &rlun->blocks[j];
-			struct nvm_block *blk = &lun->blocks[j];
 
-			rblk->parent = blk;
+			rblk->id = j;
 			rblk->rlun = rlun;
+			rblk->state = NVM_BLK_T_FREE;
 			INIT_LIST_HEAD(&rblk->prio);
+			INIT_LIST_HEAD(&rblk->list);
 			spin_lock_init(&rblk->lock);
+
+			list_add_tail(&rblk->list, &rlun->free_list);
 		}
 
 		rlun->rrpc = rrpc;
+		rlun->nr_free_blocks = geo->blks_per_lun;
+		rlun->reserved_blocks = 2; /* for GC only */
+
 		INIT_LIST_HEAD(&rlun->prio_list);
 		INIT_LIST_HEAD(&rlun->wblk_list);
 
 		INIT_WORK(&rlun->ws_gc, rrpc_lun_gc);
 		spin_lock_init(&rlun->lock);
+
+		if (rrpc_bb_discovery(dev, rlun))
+			goto err;
+
 	}
 
 	return 0;
@@ -1213,27 +1370,25 @@ err:
 /* returns 0 on success and stores the beginning address in *begin */
 static int rrpc_area_init(struct rrpc *rrpc, sector_t *begin)
 {
-	struct nvm_dev *dev = rrpc->dev;
-	struct nvmm_type *mt = dev->mt;
-	sector_t size = rrpc->nr_sects * dev->sec_size;
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	sector_t size = rrpc->nr_sects * dev->geo.sec_size;
 	int ret;
 
 	size >>= 9;
 
-	ret = mt->get_area(dev, begin, size);
+	ret = nvm_get_area(dev, begin, size);
 	if (!ret)
-		*begin >>= (ilog2(dev->sec_size) - 9);
+		*begin >>= (ilog2(dev->geo.sec_size) - 9);
 
 	return ret;
 }
 
 static void rrpc_area_free(struct rrpc *rrpc)
 {
-	struct nvm_dev *dev = rrpc->dev;
-	struct nvmm_type *mt = dev->mt;
-	sector_t begin = rrpc->soffset << (ilog2(dev->sec_size) - 9);
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	sector_t begin = rrpc->soffset << (ilog2(dev->geo.sec_size) - 9);
 
-	mt->put_area(dev, begin);
+	nvm_put_area(dev, begin);
 }
 
 static void rrpc_free(struct rrpc *rrpc)
@@ -1262,11 +1417,11 @@ static void rrpc_exit(void *private)
 static sector_t rrpc_capacity(void *private)
 {
 	struct rrpc *rrpc = private;
-	struct nvm_dev *dev = rrpc->dev;
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	sector_t reserved, provisioned;
 
 	/* cur, gc, and two emergency blocks for each lun */
-	reserved = rrpc->nr_luns * dev->sec_per_blk * 4;
+	reserved = rrpc->nr_luns * dev->geo.sec_per_blk * 4;
 	provisioned = rrpc->nr_sects - reserved;
 
 	if (reserved > rrpc->nr_sects) {
@@ -1285,13 +1440,13 @@ static sector_t rrpc_capacity(void *priv
  */
 static void rrpc_block_map_update(struct rrpc *rrpc, struct rrpc_block *rblk)
 {
-	struct nvm_dev *dev = rrpc->dev;
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	int offset;
 	struct rrpc_addr *laddr;
 	u64 bpaddr, paddr, pladdr;
 
 	bpaddr = block_to_rel_addr(rrpc, rblk);
-	for (offset = 0; offset < dev->sec_per_blk; offset++) {
+	for (offset = 0; offset < dev->geo.sec_per_blk; offset++) {
 		paddr = bpaddr + offset;
 
 		pladdr = rrpc->rev_trans_map[paddr].addr;
@@ -1311,6 +1466,7 @@ static void rrpc_block_map_update(struct
 
 static int rrpc_blocks_init(struct rrpc *rrpc)
 {
+	struct nvm_tgt_dev *dev = rrpc->dev;
 	struct rrpc_lun *rlun;
 	struct rrpc_block *rblk;
 	int lun_iter, blk_iter;
@@ -1318,7 +1474,7 @@ static int rrpc_blocks_init(struct rrpc
 	for (lun_iter = 0; lun_iter < rrpc->nr_luns; lun_iter++) {
 		rlun = &rrpc->luns[lun_iter];
 
-		for (blk_iter = 0; blk_iter < rrpc->dev->blks_per_lun;
+		for (blk_iter = 0; blk_iter < dev->geo.blks_per_lun;
 								blk_iter++) {
 			rblk = &rlun->blocks[blk_iter];
 			rrpc_block_map_update(rrpc, rblk);
@@ -1357,11 +1513,11 @@ err:
 
 static struct nvm_tgt_type tt_rrpc;
 
-static void *rrpc_init(struct nvm_dev *dev, struct gendisk *tdisk,
-						int lun_begin, int lun_end)
+static void *rrpc_init(struct nvm_tgt_dev *dev, struct gendisk *tdisk)
 {
 	struct request_queue *bqueue = dev->q;
 	struct request_queue *tqueue = tdisk->queue;
+	struct nvm_geo *geo = &dev->geo;
 	struct rrpc *rrpc;
 	sector_t soffset;
 	int ret;
@@ -1384,9 +1540,8 @@ static void *rrpc_init(struct nvm_dev *d
 	spin_lock_init(&rrpc->bio_lock);
 	INIT_WORK(&rrpc->ws_requeue, rrpc_requeue);
 
-	rrpc->nr_luns = lun_end - lun_begin + 1;
-	rrpc->total_blocks = (unsigned long)dev->blks_per_lun * rrpc->nr_luns;
-	rrpc->nr_sects = (unsigned long long)dev->sec_per_lun * rrpc->nr_luns;
+	rrpc->nr_luns = geo->nr_luns;
+	rrpc->nr_sects = (unsigned long long)geo->sec_per_lun * rrpc->nr_luns;
 
 	/* simple round-robin strategy */
 	atomic_set(&rrpc->next_lun, -1);
@@ -1398,15 +1553,12 @@ static void *rrpc_init(struct nvm_dev *d
 	}
 	rrpc->soffset = soffset;
 
-	ret = rrpc_luns_init(rrpc, lun_begin, lun_end);
+	ret = rrpc_luns_init(rrpc, dev->luns);
 	if (ret) {
 		pr_err("nvm: rrpc: could not initialize luns\n");
 		goto err;
 	}
 
-	rrpc->poffset = dev->sec_per_lun * lun_begin;
-	rrpc->lun_offset = lun_begin;
-
 	ret = rrpc_core_init(rrpc);
 	if (ret) {
 		pr_err("nvm: rrpc: could not initialize core\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/rrpc.h linux-libre-4.10-rc8-gnu/drivers/lightnvm/rrpc.h
--- linux-libre-4.9-gnu/drivers/lightnvm/rrpc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/rrpc.h	2017-02-12 16:03:20.000000000 -0500
@@ -48,14 +48,15 @@ struct rrpc_inflight_rq {
 
 struct rrpc_rq {
 	struct rrpc_inflight_rq inflight_rq;
-	struct rrpc_addr *addr;
 	unsigned long flags;
 };
 
 struct rrpc_block {
-	struct nvm_block *parent;
+	int id;				/* id inside of LUN */
 	struct rrpc_lun *rlun;
-	struct list_head prio;
+
+	struct list_head prio;		/* LUN CG list */
+	struct list_head list;		/* LUN free, used, bb list */
 
 #define MAX_INVALID_PAGES_STORAGE 8
 	/* Bitmap for invalid page intries */
@@ -65,21 +66,38 @@ struct rrpc_block {
 	/* number of pages that are invalid, wrt host page size */
 	unsigned int nr_invalid_pages;
 
+	int state;
+
 	spinlock_t lock;
 	atomic_t data_cmnt_size; /* data pages committed to stable storage */
 };
 
 struct rrpc_lun {
 	struct rrpc *rrpc;
-	struct nvm_lun *parent;
+
+	int id;
+	struct ppa_addr bppa;
+
 	struct rrpc_block *cur, *gc_cur;
 	struct rrpc_block *blocks;	/* Reference to block allocation */
 
 	struct list_head prio_list;	/* Blocks that may be GC'ed */
 	struct list_head wblk_list;	/* Queued blocks to be written to */
 
+	/* lun block lists */
+	struct list_head used_list;	/* In-use blocks */
+	struct list_head free_list;	/* Not used blocks i.e. released
+					 * and ready for use
+					 */
+	struct list_head bb_list;	/* Bad blocks. Mutually exclusive with
+					 * free_list and used_list
+					 */
+	unsigned int nr_free_blocks;	/* Number of unused blocks */
+
 	struct work_struct ws_gc;
 
+	int reserved_blocks;
+
 	spinlock_t lock;
 };
 
@@ -87,19 +105,16 @@ struct rrpc {
 	/* instance must be kept in top to resolve rrpc in unprep */
 	struct nvm_tgt_instance instance;
 
-	struct nvm_dev *dev;
+	struct nvm_tgt_dev *dev;
 	struct gendisk *disk;
 
 	sector_t soffset; /* logical sector offset */
-	u64 poffset; /* physical page offset */
-	int lun_offset;
 
 	int nr_luns;
 	struct rrpc_lun *luns;
 
 	/* calculated values */
 	unsigned long long nr_sects;
-	unsigned long total_blocks;
 
 	/* Write strategy variables. Move these into each for structure for each
 	 * strategy
@@ -150,13 +165,37 @@ struct rrpc_rev_addr {
 	u64 addr;
 };
 
-static inline struct rrpc_block *rrpc_get_rblk(struct rrpc_lun *rlun,
-								int blk_id)
+static inline struct ppa_addr rrpc_linear_to_generic_addr(struct nvm_geo *geo,
+							  struct ppa_addr r)
 {
-	struct rrpc *rrpc = rlun->rrpc;
-	int lun_blk = blk_id % rrpc->dev->blks_per_lun;
+	struct ppa_addr l;
+	int secs, pgs;
+	sector_t ppa = r.ppa;
 
-	return &rlun->blocks[lun_blk];
+	l.ppa = 0;
+
+	div_u64_rem(ppa, geo->sec_per_pg, &secs);
+	l.g.sec = secs;
+
+	sector_div(ppa, geo->sec_per_pg);
+	div_u64_rem(ppa, geo->pgs_per_blk, &pgs);
+	l.g.pg = pgs;
+
+	return l;
+}
+
+static inline struct ppa_addr rrpc_recov_addr(struct nvm_tgt_dev *dev, u64 pba)
+{
+	return linear_to_generic_addr(&dev->geo, pba);
+}
+
+static inline u64 rrpc_blk_to_ppa(struct rrpc *rrpc, struct rrpc_block *rblk)
+{
+	struct nvm_tgt_dev *dev = rrpc->dev;
+	struct nvm_geo *geo = &dev->geo;
+	struct rrpc_lun *rlun = rblk->rlun;
+
+	return (rlun->id * geo->sec_per_lun) + (rblk->id * geo->sec_per_blk);
 }
 
 static inline sector_t rrpc_get_laddr(struct bio *bio)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/sysblk.c linux-libre-4.10-rc8-gnu/drivers/lightnvm/sysblk.c
--- linux-libre-4.9-gnu/drivers/lightnvm/sysblk.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/sysblk.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,8 @@ static void nvm_cpu_to_sysblk(struct nvm
 
 static int nvm_setup_sysblks(struct nvm_dev *dev, struct ppa_addr *sysblk_ppas)
 {
-	int nr_rows = min_t(int, MAX_SYSBLKS, dev->nr_chnls);
+	struct nvm_geo *geo = &dev->geo;
+	int nr_rows = min_t(int, MAX_SYSBLKS, geo->nr_chnls);
 	int i;
 
 	for (i = 0; i < nr_rows; i++)
@@ -71,7 +72,7 @@ static int nvm_setup_sysblks(struct nvm_
 	/* if possible, place sysblk at first channel, middle channel and last
 	 * channel of the device. If not, create only one or two sys blocks
 	 */
-	switch (dev->nr_chnls) {
+	switch (geo->nr_chnls) {
 	case 2:
 		sysblk_ppas[1].g.ch = 1;
 		/* fall-through */
@@ -80,8 +81,8 @@ static int nvm_setup_sysblks(struct nvm_
 		break;
 	default:
 		sysblk_ppas[0].g.ch = 0;
-		sysblk_ppas[1].g.ch = dev->nr_chnls / 2;
-		sysblk_ppas[2].g.ch = dev->nr_chnls - 1;
+		sysblk_ppas[1].g.ch = geo->nr_chnls / 2;
+		sysblk_ppas[2].g.ch = geo->nr_chnls - 1;
 		break;
 	}
 
@@ -162,11 +163,12 @@ static int sysblk_get_host_blks(struct n
 static int nvm_get_all_sysblks(struct nvm_dev *dev, struct sysblk_scan *s,
 				struct ppa_addr *ppas, int get_free)
 {
+	struct nvm_geo *geo = &dev->geo;
 	int i, nr_blks, ret = 0;
 	u8 *blks;
 
 	s->nr_ppas = 0;
-	nr_blks = dev->blks_per_lun * dev->plane_mode;
+	nr_blks = geo->blks_per_lun * geo->plane_mode;
 
 	blks = kmalloc(nr_blks, GFP_KERNEL);
 	if (!blks)
@@ -210,13 +212,14 @@ err_get:
 static int nvm_scan_block(struct nvm_dev *dev, struct ppa_addr *ppa,
 						struct nvm_system_block *sblk)
 {
+	struct nvm_geo *geo = &dev->geo;
 	struct nvm_system_block *cur;
 	int pg, ret, found = 0;
 
 	/* the full buffer for a flash page is allocated. Only the first of it
 	 * contains the system block information
 	 */
-	cur = kmalloc(dev->pfpg_size, GFP_KERNEL);
+	cur = kmalloc(geo->pfpg_size, GFP_KERNEL);
 	if (!cur)
 		return -ENOMEM;
 
@@ -225,7 +228,7 @@ static int nvm_scan_block(struct nvm_dev
 		ppa->g.pg = ppa_to_slc(dev, pg);
 
 		ret = nvm_submit_ppa(dev, ppa, 1, NVM_OP_PREAD, NVM_IO_SLC_MODE,
-							cur, dev->pfpg_size);
+							cur, geo->pfpg_size);
 		if (ret) {
 			if (ret == NVM_RSP_ERR_EMPTYPAGE) {
 				pr_debug("nvm: sysblk scan empty ppa (%u %u %u %u)\n",
@@ -267,34 +270,16 @@ static int nvm_scan_block(struct nvm_dev
 	return found;
 }
 
-static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type)
+static int nvm_sysblk_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s,
+								int type)
 {
-	struct nvm_rq rqd;
-	int ret;
-
-	if (s->nr_ppas > dev->ops->max_phys_sect) {
-		pr_err("nvm: unable to update all sysblocks atomically\n");
-		return -EINVAL;
-	}
-
-	memset(&rqd, 0, sizeof(struct nvm_rq));
-
-	nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas, 1);
-	nvm_generic_to_addr_mode(dev, &rqd);
-
-	ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type);
-	nvm_free_rqd_ppalist(dev, &rqd);
-	if (ret) {
-		pr_err("nvm: sysblk failed bb mark\n");
-		return -EINVAL;
-	}
-
-	return 0;
+	return nvm_set_bb_tbl(dev, s->ppas, s->nr_ppas, type);
 }
 
 static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info,
 							struct sysblk_scan *s)
 {
+	struct nvm_geo *geo = &dev->geo;
 	struct nvm_system_block nvmsb;
 	void *buf;
 	int i, sect, ret = 0;
@@ -302,12 +287,12 @@ static int nvm_write_and_verify(struct n
 
 	nvm_cpu_to_sysblk(&nvmsb, info);
 
-	buf = kzalloc(dev->pfpg_size, GFP_KERNEL);
+	buf = kzalloc(geo->pfpg_size, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 	memcpy(buf, &nvmsb, sizeof(struct nvm_system_block));
 
-	ppas = kcalloc(dev->sec_per_pg, sizeof(struct ppa_addr), GFP_KERNEL);
+	ppas = kcalloc(geo->sec_per_pg, sizeof(struct ppa_addr), GFP_KERNEL);
 	if (!ppas) {
 		ret = -ENOMEM;
 		goto err;
@@ -324,15 +309,15 @@ static int nvm_write_and_verify(struct n
 							ppas[0].g.pg);
 
 		/* Expand to all sectors within a flash page */
-		if (dev->sec_per_pg > 1) {
-			for (sect = 1; sect < dev->sec_per_pg; sect++) {
+		if (geo->sec_per_pg > 1) {
+			for (sect = 1; sect < geo->sec_per_pg; sect++) {
 				ppas[sect].ppa = ppas[0].ppa;
 				ppas[sect].g.sec = sect;
 			}
 		}
 
-		ret = nvm_submit_ppa(dev, ppas, dev->sec_per_pg, NVM_OP_PWRITE,
-					NVM_IO_SLC_MODE, buf, dev->pfpg_size);
+		ret = nvm_submit_ppa(dev, ppas, geo->sec_per_pg, NVM_OP_PWRITE,
+					NVM_IO_SLC_MODE, buf, geo->pfpg_size);
 		if (ret) {
 			pr_err("nvm: sysblk failed program (%u %u %u)\n",
 							ppas[0].g.ch,
@@ -341,8 +326,8 @@ static int nvm_write_and_verify(struct n
 			break;
 		}
 
-		ret = nvm_submit_ppa(dev, ppas, dev->sec_per_pg, NVM_OP_PREAD,
-					NVM_IO_SLC_MODE, buf, dev->pfpg_size);
+		ret = nvm_submit_ppa(dev, ppas, geo->sec_per_pg, NVM_OP_PREAD,
+					NVM_IO_SLC_MODE, buf, geo->pfpg_size);
 		if (ret) {
 			pr_err("nvm: sysblk failed read (%u %u %u)\n",
 							ppas[0].g.ch,
@@ -379,7 +364,7 @@ static int nvm_prepare_new_sysblks(struc
 		ppa = &s->ppas[scan_ppa_idx(i, nxt_blk)];
 		ppa->g.pg = ppa_to_slc(dev, 0);
 
-		ret = nvm_erase_ppa(dev, ppa, 1);
+		ret = nvm_erase_ppa(dev, ppa, 1, 0);
 		if (ret)
 			return ret;
 
@@ -546,6 +531,7 @@ err_sysblk:
 
 int nvm_init_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info)
 {
+	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr sysblk_ppas[MAX_SYSBLKS];
 	struct sysblk_scan s;
 	int ret;
@@ -560,7 +546,7 @@ int nvm_init_sysblock(struct nvm_dev *de
 	if (!dev->ops->get_bb_tbl || !dev->ops->set_bb_tbl)
 		return -EINVAL;
 
-	if (!(dev->mccap & NVM_ID_CAP_SLC) || !dev->lps_per_blk) {
+	if (!(geo->mccap & NVM_ID_CAP_SLC) || !dev->lps_per_blk) {
 		pr_err("nvm: memory does not support SLC access\n");
 		return -EINVAL;
 	}
@@ -573,7 +559,7 @@ int nvm_init_sysblock(struct nvm_dev *de
 	if (ret)
 		goto err_mark;
 
-	ret = nvm_set_bb_tbl(dev, &s, NVM_BLK_T_HOST);
+	ret = nvm_sysblk_set_bb_tbl(dev, &s, NVM_BLK_T_HOST);
 	if (ret)
 		goto err_mark;
 
@@ -590,11 +576,11 @@ static int factory_nblks(int nblks)
 	return (nblks + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
 }
 
-static unsigned int factory_blk_offset(struct nvm_dev *dev, struct ppa_addr ppa)
+static unsigned int factory_blk_offset(struct nvm_geo *geo, struct ppa_addr ppa)
 {
-	int nblks = factory_nblks(dev->blks_per_lun);
+	int nblks = factory_nblks(geo->blks_per_lun);
 
-	return ((ppa.g.ch * dev->luns_per_chnl * nblks) + (ppa.g.lun * nblks)) /
+	return ((ppa.g.ch * geo->luns_per_chnl * nblks) + (ppa.g.lun * nblks)) /
 								BITS_PER_LONG;
 }
 
@@ -608,7 +594,7 @@ static int nvm_factory_blks(struct nvm_d
 	if (nr_blks < 0)
 		return nr_blks;
 
-	lunoff = factory_blk_offset(dev, ppa);
+	lunoff = factory_blk_offset(&dev->geo, ppa);
 
 	/* non-set bits correspond to the block must be erased */
 	for (i = 0; i < nr_blks; i++) {
@@ -637,19 +623,19 @@ static int nvm_factory_blks(struct nvm_d
 static int nvm_fact_get_blks(struct nvm_dev *dev, struct ppa_addr *erase_list,
 					int max_ppas, unsigned long *blk_bitmap)
 {
+	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr ppa;
 	int ch, lun, blkid, idx, done = 0, ppa_cnt = 0;
 	unsigned long *offset;
 
 	while (!done) {
 		done = 1;
-		nvm_for_each_lun_ppa(dev, ppa, ch, lun) {
-			idx = factory_blk_offset(dev, ppa);
+		nvm_for_each_lun_ppa(geo, ppa, ch, lun) {
+			idx = factory_blk_offset(geo, ppa);
 			offset = &blk_bitmap[idx];
 
-			blkid = find_first_zero_bit(offset,
-						dev->blks_per_lun);
-			if (blkid >= dev->blks_per_lun)
+			blkid = find_first_zero_bit(offset, geo->blks_per_lun);
+			if (blkid >= geo->blks_per_lun)
 				continue;
 			set_bit(blkid, offset);
 
@@ -674,16 +660,17 @@ static int nvm_fact_get_blks(struct nvm_
 static int nvm_fact_select_blks(struct nvm_dev *dev, unsigned long *blk_bitmap,
 								int flags)
 {
+	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr ppa;
 	int ch, lun, nr_blks, ret = 0;
 	u8 *blks;
 
-	nr_blks = dev->blks_per_lun * dev->plane_mode;
+	nr_blks = geo->blks_per_lun * geo->plane_mode;
 	blks = kmalloc(nr_blks, GFP_KERNEL);
 	if (!blks)
 		return -ENOMEM;
 
-	nvm_for_each_lun_ppa(dev, ppa, ch, lun) {
+	nvm_for_each_lun_ppa(geo, ppa, ch, lun) {
 		ret = nvm_get_bb_tbl(dev, ppa, blks);
 		if (ret)
 			pr_err("nvm: failed bb tbl for ch%u lun%u\n",
@@ -701,14 +688,15 @@ static int nvm_fact_select_blks(struct n
 
 int nvm_dev_factory(struct nvm_dev *dev, int flags)
 {
+	struct nvm_geo *geo = &dev->geo;
 	struct ppa_addr *ppas;
 	int ppa_cnt, ret = -ENOMEM;
-	int max_ppas = dev->ops->max_phys_sect / dev->nr_planes;
+	int max_ppas = dev->ops->max_phys_sect / geo->nr_planes;
 	struct ppa_addr sysblk_ppas[MAX_SYSBLKS];
 	struct sysblk_scan s;
 	unsigned long *blk_bitmap;
 
-	blk_bitmap = kzalloc(factory_nblks(dev->blks_per_lun) * dev->nr_luns,
+	blk_bitmap = kzalloc(factory_nblks(geo->blks_per_lun) * geo->nr_luns,
 								GFP_KERNEL);
 	if (!blk_bitmap)
 		return ret;
@@ -725,7 +713,7 @@ int nvm_dev_factory(struct nvm_dev *dev,
 	/* continue to erase until list of blks until empty */
 	while ((ppa_cnt =
 			nvm_fact_get_blks(dev, ppas, max_ppas, blk_bitmap)) > 0)
-		nvm_erase_ppa(dev, ppas, ppa_cnt);
+		nvm_erase_ppa(dev, ppas, ppa_cnt, 0);
 
 	/* mark host reserved blocks free */
 	if (flags & NVM_FACTORY_RESET_HOST_BLKS) {
@@ -733,7 +721,7 @@ int nvm_dev_factory(struct nvm_dev *dev,
 		mutex_lock(&dev->mlock);
 		ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0);
 		if (!ret)
-			ret = nvm_set_bb_tbl(dev, &s, NVM_BLK_T_FREE);
+			ret = nvm_sysblk_set_bb_tbl(dev, &s, NVM_BLK_T_FREE);
 		mutex_unlock(&dev->mlock);
 	}
 err_ppas:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/lightnvm/sysfs.c linux-libre-4.10-rc8-gnu/drivers/lightnvm/sysfs.c
--- linux-libre-4.9-gnu/drivers/lightnvm/sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/lightnvm/sysfs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,198 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/lightnvm.h>
-#include <linux/miscdevice.h>
-#include <linux/kobject.h>
-#include <linux/blk-mq.h>
-
-#include "lightnvm.h"
-
-static ssize_t nvm_dev_attr_show(struct device *dev,
-				 struct device_attribute *dattr, char *page)
-{
-	struct nvm_dev *ndev = container_of(dev, struct nvm_dev, dev);
-	struct nvm_id *id = &ndev->identity;
-	struct nvm_id_group *grp = &id->groups[0];
-	struct attribute *attr = &dattr->attr;
-
-	if (strcmp(attr->name, "version") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->ver_id);
-	} else if (strcmp(attr->name, "vendor_opcode") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->vmnt);
-	} else if (strcmp(attr->name, "capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->cap);
-	} else if (strcmp(attr->name, "device_mode") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", id->dom);
-	} else if (strcmp(attr->name, "media_manager") == 0) {
-		if (!ndev->mt)
-			return scnprintf(page, PAGE_SIZE, "%s\n", "none");
-		return scnprintf(page, PAGE_SIZE, "%s\n", ndev->mt->name);
-	} else if (strcmp(attr->name, "ppa_format") == 0) {
-		return scnprintf(page, PAGE_SIZE,
-			"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
-			id->ppaf.ch_offset, id->ppaf.ch_len,
-			id->ppaf.lun_offset, id->ppaf.lun_len,
-			id->ppaf.pln_offset, id->ppaf.pln_len,
-			id->ppaf.blk_offset, id->ppaf.blk_len,
-			id->ppaf.pg_offset, id->ppaf.pg_len,
-			id->ppaf.sect_offset, id->ppaf.sect_len);
-	} else if (strcmp(attr->name, "media_type") == 0) {	/* u8 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->mtype);
-	} else if (strcmp(attr->name, "flash_media_type") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->fmtype);
-	} else if (strcmp(attr->name, "num_channels") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_ch);
-	} else if (strcmp(attr->name, "num_luns") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_lun);
-	} else if (strcmp(attr->name, "num_planes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pln);
-	} else if (strcmp(attr->name, "num_blocks") == 0) {	/* u16 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_blk);
-	} else if (strcmp(attr->name, "num_pages") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->num_pg);
-	} else if (strcmp(attr->name, "page_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->fpg_sz);
-	} else if (strcmp(attr->name, "hw_sector_size") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->csecs);
-	} else if (strcmp(attr->name, "oob_sector_size") == 0) {/* u32 */
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->sos);
-	} else if (strcmp(attr->name, "read_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdt);
-	} else if (strcmp(attr->name, "read_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->trdm);
-	} else if (strcmp(attr->name, "prog_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprt);
-	} else if (strcmp(attr->name, "prog_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tprm);
-	} else if (strcmp(attr->name, "erase_typ") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbet);
-	} else if (strcmp(attr->name, "erase_max") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n", grp->tbem);
-	} else if (strcmp(attr->name, "multiplane_modes") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mpos);
-	} else if (strcmp(attr->name, "media_capabilities") == 0) {
-		return scnprintf(page, PAGE_SIZE, "0x%08x\n", grp->mccap);
-	} else if (strcmp(attr->name, "max_phys_secs") == 0) {
-		return scnprintf(page, PAGE_SIZE, "%u\n",
-				ndev->ops->max_phys_sect);
-	} else {
-		return scnprintf(page,
-				 PAGE_SIZE,
-				 "Unhandled attr(%s) in `nvm_dev_attr_show`\n",
-				 attr->name);
-	}
-}
-
-#define NVM_DEV_ATTR_RO(_name)						\
-	DEVICE_ATTR(_name, S_IRUGO, nvm_dev_attr_show, NULL)
-
-static NVM_DEV_ATTR_RO(version);
-static NVM_DEV_ATTR_RO(vendor_opcode);
-static NVM_DEV_ATTR_RO(capabilities);
-static NVM_DEV_ATTR_RO(device_mode);
-static NVM_DEV_ATTR_RO(ppa_format);
-static NVM_DEV_ATTR_RO(media_manager);
-
-static NVM_DEV_ATTR_RO(media_type);
-static NVM_DEV_ATTR_RO(flash_media_type);
-static NVM_DEV_ATTR_RO(num_channels);
-static NVM_DEV_ATTR_RO(num_luns);
-static NVM_DEV_ATTR_RO(num_planes);
-static NVM_DEV_ATTR_RO(num_blocks);
-static NVM_DEV_ATTR_RO(num_pages);
-static NVM_DEV_ATTR_RO(page_size);
-static NVM_DEV_ATTR_RO(hw_sector_size);
-static NVM_DEV_ATTR_RO(oob_sector_size);
-static NVM_DEV_ATTR_RO(read_typ);
-static NVM_DEV_ATTR_RO(read_max);
-static NVM_DEV_ATTR_RO(prog_typ);
-static NVM_DEV_ATTR_RO(prog_max);
-static NVM_DEV_ATTR_RO(erase_typ);
-static NVM_DEV_ATTR_RO(erase_max);
-static NVM_DEV_ATTR_RO(multiplane_modes);
-static NVM_DEV_ATTR_RO(media_capabilities);
-static NVM_DEV_ATTR_RO(max_phys_secs);
-
-#define NVM_DEV_ATTR(_name) (dev_attr_##_name##)
-
-static struct attribute *nvm_dev_attrs[] = {
-	&dev_attr_version.attr,
-	&dev_attr_vendor_opcode.attr,
-	&dev_attr_capabilities.attr,
-	&dev_attr_device_mode.attr,
-	&dev_attr_media_manager.attr,
-
-	&dev_attr_ppa_format.attr,
-	&dev_attr_media_type.attr,
-	&dev_attr_flash_media_type.attr,
-	&dev_attr_num_channels.attr,
-	&dev_attr_num_luns.attr,
-	&dev_attr_num_planes.attr,
-	&dev_attr_num_blocks.attr,
-	&dev_attr_num_pages.attr,
-	&dev_attr_page_size.attr,
-	&dev_attr_hw_sector_size.attr,
-	&dev_attr_oob_sector_size.attr,
-	&dev_attr_read_typ.attr,
-	&dev_attr_read_max.attr,
-	&dev_attr_prog_typ.attr,
-	&dev_attr_prog_max.attr,
-	&dev_attr_erase_typ.attr,
-	&dev_attr_erase_max.attr,
-	&dev_attr_multiplane_modes.attr,
-	&dev_attr_media_capabilities.attr,
-	&dev_attr_max_phys_secs.attr,
-	NULL,
-};
-
-static struct attribute_group nvm_dev_attr_group = {
-	.name = "lightnvm",
-	.attrs = nvm_dev_attrs,
-};
-
-static const struct attribute_group *nvm_dev_attr_groups[] = {
-	&nvm_dev_attr_group,
-	NULL,
-};
-
-static void nvm_dev_release(struct device *device)
-{
-	struct nvm_dev *dev = container_of(device, struct nvm_dev, dev);
-	struct request_queue *q = dev->q;
-
-	pr_debug("nvm/sysfs: `nvm_dev_release`\n");
-
-	blk_mq_unregister_dev(device, q);
-
-	nvm_free(dev);
-}
-
-static struct device_type nvm_type = {
-	.name		= "lightnvm",
-	.groups		= nvm_dev_attr_groups,
-	.release	= nvm_dev_release,
-};
-
-int nvm_sysfs_register_dev(struct nvm_dev *dev)
-{
-	int ret;
-
-	if (!dev->parent_dev)
-		return 0;
-
-	dev->dev.parent = dev->parent_dev;
-	dev_set_name(&dev->dev, "%s", dev->name);
-	dev->dev.type = &nvm_type;
-	device_initialize(&dev->dev);
-	ret = device_add(&dev->dev);
-
-	if (!ret)
-		blk_mq_register_dev(&dev->dev, dev->q);
-
-	return ret;
-}
-
-void nvm_sysfs_unregister_dev(struct nvm_dev *dev)
-{
-	if (dev && dev->parent_dev)
-		kobject_put(&dev->dev.kobj);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/macintosh/ans-lcd.c linux-libre-4.10-rc8-gnu/drivers/macintosh/ans-lcd.c
--- linux-libre-4.9-gnu/drivers/macintosh/ans-lcd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/macintosh/ans-lcd.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@
 #include <linux/delay.h>
 #include <linux/fs.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/sections.h>
 #include <asm/prom.h>
 #include <asm/io.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/macintosh/Kconfig linux-libre-4.10-rc8-gnu/drivers/macintosh/Kconfig
--- linux-libre-4.9-gnu/drivers/macintosh/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/macintosh/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,6 @@ config ADB_PMU_LED_DISK
 	bool "Use front LED as DISK LED by default"
 	depends on ADB_PMU_LED
 	depends on LEDS_CLASS
-	depends on IDE_GD_ATA
 	select LEDS_TRIGGERS
 	select LEDS_TRIGGER_DISK
 	help
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/macintosh/smu.c linux-libre-4.10-rc8-gnu/drivers/macintosh/smu.c
--- linux-libre-4.9-gnu/drivers/macintosh/smu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/macintosh/smu.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@
 #include <asm/pmac_feature.h>
 #include <asm/smu.h>
 #include <asm/sections.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define VERSION "0.7"
 #define AUTHOR  "(c) 2005 Benjamin Herrenschmidt, IBM Corp."
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/macintosh/via-pmu68k.c linux-libre-4.10-rc8-gnu/drivers/macintosh/via-pmu68k.c
--- linux-libre-4.9-gnu/drivers/macintosh/via-pmu68k.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/macintosh/via-pmu68k.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR	154
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/macintosh/via-pmu.c linux-libre-4.10-rc8-gnu/drivers/macintosh/via-pmu.c
--- linux-libre-4.9-gnu/drivers/macintosh/via-pmu.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/macintosh/via-pmu.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,7 +57,7 @@
 #include <asm/pmac_feature.h>
 #include <asm/pmac_pfunc.h>
 #include <asm/pmac_low_i2c.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mmu_context.h>
 #include <asm/cputable.h>
 #include <asm/time.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/bcm-pdc-mailbox.c linux-libre-4.10-rc8-gnu/drivers/mailbox/bcm-pdc-mailbox.c
--- linux-libre-4.9-gnu/drivers/mailbox/bcm-pdc-mailbox.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/bcm-pdc-mailbox.c	2017-02-12 16:03:20.000000000 -0500
@@ -60,7 +60,13 @@
 #define RING_ENTRY_SIZE   sizeof(struct dma64dd)
 
 /* # entries in PDC dma ring */
-#define PDC_RING_ENTRIES  128
+#define PDC_RING_ENTRIES  512
+/*
+ * Minimum number of ring descriptor entries that must be free to tell mailbox
+ * framework that it can submit another request
+ */
+#define PDC_RING_SPACE_MIN  15
+
 #define PDC_RING_SIZE    (PDC_RING_ENTRIES * RING_ENTRY_SIZE)
 /* Rings are 8k aligned */
 #define RING_ALIGN_ORDER  13
@@ -93,11 +99,9 @@
  * Interrupt mask and status definitions. Enable interrupts for tx and rx on
  * ring 0
  */
-#define PDC_XMTINT_0         (24 + PDC_RINGSET)
 #define PDC_RCVINT_0         (16 + PDC_RINGSET)
-#define PDC_XMTINTEN_0       BIT(PDC_XMTINT_0)
 #define PDC_RCVINTEN_0       BIT(PDC_RCVINT_0)
-#define PDC_INTMASK  (PDC_XMTINTEN_0 | PDC_RCVINTEN_0)
+#define PDC_INTMASK	     (PDC_RCVINTEN_0)
 #define PDC_LAZY_FRAMECOUNT  1
 #define PDC_LAZY_TIMEOUT     10000
 #define PDC_LAZY_INT  (PDC_LAZY_TIMEOUT | (PDC_LAZY_FRAMECOUNT << 24))
@@ -117,15 +121,16 @@
 
 /*
  * Sets the following bits for write to transmit control reg:
- *  0    - XmtEn - enable activity on the tx channel
  * 11    - PtyChkDisable - parity check is disabled
  * 20:18 - BurstLen = 3 -> 2^7 = 128 byte data reads from memory
  */
-#define PDC_TX_CTL              0x000C0801
+#define PDC_TX_CTL		0x000C0800
+
+/* Bit in tx control reg to enable tx channel */
+#define PDC_TX_ENABLE		0x1
 
 /*
  * Sets the following bits for write to receive control reg:
- * 0     - RcvEn - enable activity on the rx channel
  * 7:1   - RcvOffset - size in bytes of status region at start of rx frame buf
  * 9     - SepRxHdrDescEn - place start of new frames only in descriptors
  *                          that have StartOfFrame set
@@ -135,7 +140,10 @@
  * 11    - PtyChkDisable - parity check is disabled
  * 20:18 - BurstLen = 3 -> 2^7 = 128 byte data reads from memory
  */
-#define PDC_RX_CTL              0x000C0E01
+#define PDC_RX_CTL		0x000C0E00
+
+/* Bit in rx control reg to enable rx channel */
+#define PDC_RX_ENABLE		0x1
 
 #define CRYPTO_D64_RS0_CD_MASK   ((PDC_RING_ENTRIES * RING_ENTRY_SIZE) - 1)
 
@@ -252,11 +260,29 @@ struct pdc_ring_alloc {
 	u32	    size;    /* ring allocation size in bytes */
 };
 
+/*
+ * context associated with a receive descriptor.
+ * @rxp_ctx: opaque context associated with frame that starts at each
+ *           rx ring index.
+ * @dst_sg:  Scatterlist used to form reply frames beginning at a given ring
+ *           index. Retained in order to unmap each sg after reply is processed.
+ * @rxin_numd: Number of rx descriptors associated with the message that starts
+ *             at a descriptor index. Not set for every index. For example,
+ *             if descriptor index i points to a scatterlist with 4 entries,
+ *             then the next three descriptor indexes don't have a value set.
+ * @resp_hdr: Virtual address of buffer used to catch DMA rx status
+ * @resp_hdr_daddr: physical address of DMA rx status buffer
+ */
+struct pdc_rx_ctx {
+	void *rxp_ctx;
+	struct scatterlist *dst_sg;
+	u32  rxin_numd;
+	void *resp_hdr;
+	dma_addr_t resp_hdr_daddr;
+};
+
 /* PDC state structure */
 struct pdc_state {
-	/* synchronize access to this PDC state structure */
-	spinlock_t pdc_lock;
-
 	/* Index of the PDC whose state is in this structure instance */
 	u8 pdc_idx;
 
@@ -272,13 +298,8 @@ struct pdc_state {
 
 	unsigned int pdc_irq;
 
-	/*
-	 * Last interrupt status read from PDC device. Saved in interrupt
-	 * handler so the handler can clear the interrupt in the device,
-	 * and the interrupt thread called later can know which interrupt
-	 * bits are active.
-	 */
-	unsigned long intstatus;
+	/* tasklet for deferred processing after DMA rx interrupt */
+	struct tasklet_struct rx_tasklet;
 
 	/* Number of bytes of receive status prior to each rx frame */
 	u32 rx_status_len;
@@ -369,11 +390,7 @@ struct pdc_state {
 	/* Index of next rx descriptor to post. */
 	u32  rxout;
 
-	/*
-	 * opaque context associated with frame that starts at each
-	 * rx ring index.
-	 */
-	void *rxp_ctx[PDC_RING_ENTRIES];
+	struct pdc_rx_ctx rx_ctx[PDC_RING_ENTRIES];
 
 	/*
 	 * Scatterlists used to form request and reply frames beginning at a
@@ -381,27 +398,18 @@ struct pdc_state {
 	 * is processed
 	 */
 	struct scatterlist *src_sg[PDC_RING_ENTRIES];
-	struct scatterlist *dst_sg[PDC_RING_ENTRIES];
-
-	/*
-	 * Number of rx descriptors associated with the message that starts
-	 * at this descriptor index. Not set for every index. For example,
-	 * if descriptor index i points to a scatterlist with 4 entries, then
-	 * the next three descriptor indexes don't have a value set.
-	 */
-	u32  rxin_numd[PDC_RING_ENTRIES];
-
-	void *resp_hdr[PDC_RING_ENTRIES];
-	dma_addr_t resp_hdr_daddr[PDC_RING_ENTRIES];
 
 	struct dentry *debugfs_stats;  /* debug FS stats file for this PDC */
 
 	/* counters */
-	u32  pdc_requests;    /* number of request messages submitted */
-	u32  pdc_replies;     /* number of reply messages received */
-	u32  txnobuf;         /* count of tx ring full */
-	u32  rxnobuf;         /* count of rx ring full */
-	u32  rx_oflow;        /* count of rx overflows */
+	u32  pdc_requests;     /* number of request messages submitted */
+	u32  pdc_replies;      /* number of reply messages received */
+	u32  last_tx_not_done; /* too few tx descriptors to indicate done */
+	u32  tx_ring_full;     /* unable to accept msg because tx ring full */
+	u32  rx_ring_full;     /* unable to accept msg because rx ring full */
+	u32  txnobuf;          /* unable to create tx descriptor */
+	u32  rxnobuf;          /* unable to create rx descriptor */
+	u32  rx_oflow;         /* count of rx overflows */
 };
 
 /* Global variables */
@@ -434,20 +442,33 @@ static ssize_t pdc_debugfs_read(struct f
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
 			       "SPU %u stats:\n", pdcs->pdc_idx);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
-			       "PDC requests............%u\n",
+			       "PDC requests....................%u\n",
 			       pdcs->pdc_requests);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
-			       "PDC responses...........%u\n",
+			       "PDC responses...................%u\n",
 			       pdcs->pdc_replies);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
-			       "Tx err ring full........%u\n",
+			       "Tx not done.....................%u\n",
+			       pdcs->last_tx_not_done);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "Tx ring full....................%u\n",
+			       pdcs->tx_ring_full);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "Rx ring full....................%u\n",
+			       pdcs->rx_ring_full);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "Tx desc write fail. Ring full...%u\n",
 			       pdcs->txnobuf);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
-			       "Rx err ring full........%u\n",
+			       "Rx desc write fail. Ring full...%u\n",
 			       pdcs->rxnobuf);
 	out_offset += snprintf(buf + out_offset, out_count - out_offset,
-			       "Receive overflow........%u\n",
+			       "Receive overflow................%u\n",
 			       pdcs->rx_oflow);
+	out_offset += snprintf(buf + out_offset, out_count - out_offset,
+			       "Num frags in rx ring............%u\n",
+			       NRXDACTIVE(pdcs->rxin, pdcs->last_rx_curr,
+					  pdcs->nrxpost));
 
 	if (out_offset > out_count)
 		out_offset = out_count;
@@ -480,17 +501,16 @@ static void pdc_setup_debugfs(struct pdc
 	if (!debugfs_dir)
 		debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
 
-	pdcs->debugfs_stats = debugfs_create_file(spu_stats_name, S_IRUSR,
+	/* S_IRUSR == 0400 */
+	pdcs->debugfs_stats = debugfs_create_file(spu_stats_name, 0400,
 						  debugfs_dir, pdcs,
 						  &pdc_debugfs_stats);
 }
 
 static void pdc_free_debugfs(void)
 {
-	if (debugfs_dir && simple_empty(debugfs_dir)) {
-		debugfs_remove_recursive(debugfs_dir);
-		debugfs_dir = NULL;
-	}
+	debugfs_remove_recursive(debugfs_dir);
+	debugfs_dir = NULL;
 }
 
 /**
@@ -505,17 +525,17 @@ pdc_build_rxd(struct pdc_state *pdcs, dm
 	      u32 buf_len, u32 flags)
 {
 	struct device *dev = &pdcs->pdev->dev;
+	struct dma64dd *rxd = &pdcs->rxd_64[pdcs->rxout];
 
 	dev_dbg(dev,
 		"Writing rx descriptor for PDC %u at index %u with length %u. flags %#x\n",
 		pdcs->pdc_idx, pdcs->rxout, buf_len, flags);
 
-	iowrite32(lower_32_bits(dma_addr),
-		  (void *)&pdcs->rxd_64[pdcs->rxout].addrlow);
-	iowrite32(upper_32_bits(dma_addr),
-		  (void *)&pdcs->rxd_64[pdcs->rxout].addrhigh);
-	iowrite32(flags, (void *)&pdcs->rxd_64[pdcs->rxout].ctrl1);
-	iowrite32(buf_len, (void *)&pdcs->rxd_64[pdcs->rxout].ctrl2);
+	rxd->addrlow = cpu_to_le32(lower_32_bits(dma_addr));
+	rxd->addrhigh = cpu_to_le32(upper_32_bits(dma_addr));
+	rxd->ctrl1 = cpu_to_le32(flags);
+	rxd->ctrl2 = cpu_to_le32(buf_len);
+
 	/* bump ring index and return */
 	pdcs->rxout = NEXTRXD(pdcs->rxout, pdcs->nrxpost);
 }
@@ -533,53 +553,50 @@ pdc_build_txd(struct pdc_state *pdcs, dm
 	      u32 flags)
 {
 	struct device *dev = &pdcs->pdev->dev;
+	struct dma64dd *txd = &pdcs->txd_64[pdcs->txout];
 
 	dev_dbg(dev,
 		"Writing tx descriptor for PDC %u at index %u with length %u, flags %#x\n",
 		pdcs->pdc_idx, pdcs->txout, buf_len, flags);
 
-	iowrite32(lower_32_bits(dma_addr),
-		  (void *)&pdcs->txd_64[pdcs->txout].addrlow);
-	iowrite32(upper_32_bits(dma_addr),
-		  (void *)&pdcs->txd_64[pdcs->txout].addrhigh);
-	iowrite32(flags, (void *)&pdcs->txd_64[pdcs->txout].ctrl1);
-	iowrite32(buf_len, (void *)&pdcs->txd_64[pdcs->txout].ctrl2);
+	txd->addrlow = cpu_to_le32(lower_32_bits(dma_addr));
+	txd->addrhigh = cpu_to_le32(upper_32_bits(dma_addr));
+	txd->ctrl1 = cpu_to_le32(flags);
+	txd->ctrl2 = cpu_to_le32(buf_len);
 
 	/* bump ring index and return */
 	pdcs->txout = NEXTTXD(pdcs->txout, pdcs->ntxpost);
 }
 
 /**
- * pdc_receive() - Receive a response message from a given SPU.
+ * pdc_receive_one() - Receive a response message from a given SPU.
  * @pdcs:    PDC state for the SPU to receive from
- * @mssg:    mailbox message to be returned to client
  *
  * When the return code indicates success, the response message is available in
  * the receive buffers provided prior to submission of the request.
  *
- * Input:
- *   pdcs - PDC state structure for the SPU to be polled
- *   mssg - mailbox message to be returned to client. This function sets the
- *	    context pointer on the message to help the client associate the
- *	    response with a request.
- *
  * Return:  PDC_SUCCESS if one or more receive descriptors was processed
  *          -EAGAIN indicates that no response message is available
  *          -EIO an error occurred
  */
 static int
-pdc_receive(struct pdc_state *pdcs, struct brcm_message *mssg)
+pdc_receive_one(struct pdc_state *pdcs)
 {
 	struct device *dev = &pdcs->pdev->dev;
+	struct mbox_controller *mbc;
+	struct mbox_chan *chan;
+	struct brcm_message mssg;
 	u32 len, rx_status;
 	u32 num_frags;
-	int i;
 	u8 *resp_hdr;    /* virtual addr of start of resp message DMA header */
 	u32 frags_rdy;   /* number of fragments ready to read */
 	u32 rx_idx;      /* ring index of start of receive frame */
 	dma_addr_t resp_hdr_daddr;
+	struct pdc_rx_ctx *rx_ctx;
 
-	spin_lock(&pdcs->pdc_lock);
+	mbc = &pdcs->mbc;
+	chan = &mbc->chans[0];
+	mssg.type = BRCM_MESSAGE_SPU;
 
 	/*
 	 * return if a complete response message is not yet ready.
@@ -587,47 +604,34 @@ pdc_receive(struct pdc_state *pdcs, stru
 	 * to read.
 	 */
 	frags_rdy = NRXDACTIVE(pdcs->rxin, pdcs->last_rx_curr, pdcs->nrxpost);
-	if ((frags_rdy == 0) || (frags_rdy < pdcs->rxin_numd[pdcs->rxin])) {
-		/* See if the hw has written more fragments than we know */
-		pdcs->last_rx_curr =
-		    (ioread32((void *)&pdcs->rxregs_64->status0) &
-		     CRYPTO_D64_RS0_CD_MASK) / RING_ENTRY_SIZE;
-		frags_rdy = NRXDACTIVE(pdcs->rxin, pdcs->last_rx_curr,
-				       pdcs->nrxpost);
-		if ((frags_rdy == 0) ||
-		    (frags_rdy < pdcs->rxin_numd[pdcs->rxin])) {
-			/* No response ready */
-			spin_unlock(&pdcs->pdc_lock);
-			return -EAGAIN;
-		}
-		/* can't read descriptors/data until write index is read */
-		rmb();
-	}
+	if ((frags_rdy == 0) ||
+	    (frags_rdy < pdcs->rx_ctx[pdcs->rxin].rxin_numd))
+		/* No response ready */
+		return -EAGAIN;
 
 	num_frags = pdcs->txin_numd[pdcs->txin];
+	WARN_ON(num_frags == 0);
+
 	dma_unmap_sg(dev, pdcs->src_sg[pdcs->txin],
 		     sg_nents(pdcs->src_sg[pdcs->txin]), DMA_TO_DEVICE);
 
-	for (i = 0; i < num_frags; i++)
-		pdcs->txin = NEXTTXD(pdcs->txin, pdcs->ntxpost);
+	pdcs->txin = (pdcs->txin + num_frags) & pdcs->ntxpost;
 
 	dev_dbg(dev, "PDC %u reclaimed %d tx descriptors",
 		pdcs->pdc_idx, num_frags);
 
 	rx_idx = pdcs->rxin;
-	num_frags = pdcs->rxin_numd[rx_idx];
+	rx_ctx = &pdcs->rx_ctx[rx_idx];
+	num_frags = rx_ctx->rxin_numd;
 	/* Return opaque context with result */
-	mssg->ctx = pdcs->rxp_ctx[rx_idx];
-	pdcs->rxp_ctx[rx_idx] = NULL;
-	resp_hdr = pdcs->resp_hdr[rx_idx];
-	resp_hdr_daddr = pdcs->resp_hdr_daddr[rx_idx];
-	dma_unmap_sg(dev, pdcs->dst_sg[rx_idx],
-		     sg_nents(pdcs->dst_sg[rx_idx]), DMA_FROM_DEVICE);
-
-	for (i = 0; i < num_frags; i++)
-		pdcs->rxin = NEXTRXD(pdcs->rxin, pdcs->nrxpost);
+	mssg.ctx = rx_ctx->rxp_ctx;
+	rx_ctx->rxp_ctx = NULL;
+	resp_hdr = rx_ctx->resp_hdr;
+	resp_hdr_daddr = rx_ctx->resp_hdr_daddr;
+	dma_unmap_sg(dev, rx_ctx->dst_sg, sg_nents(rx_ctx->dst_sg),
+		     DMA_FROM_DEVICE);
 
-	spin_unlock(&pdcs->pdc_lock);
+	pdcs->rxin = (pdcs->rxin + num_frags) & pdcs->nrxpost;
 
 	dev_dbg(dev, "PDC %u reclaimed %d rx descriptors",
 		pdcs->pdc_idx, num_frags);
@@ -659,12 +663,35 @@ pdc_receive(struct pdc_state *pdcs, stru
 
 	dma_pool_free(pdcs->rx_buf_pool, resp_hdr, resp_hdr_daddr);
 
+	mbox_chan_received_data(chan, &mssg);
+
 	pdcs->pdc_replies++;
-	/* if we read one or more rx descriptors, claim success */
-	if (num_frags > 0)
-		return PDC_SUCCESS;
-	else
-		return -EIO;
+	return PDC_SUCCESS;
+}
+
+/**
+ * pdc_receive() - Process as many responses as are available in the rx ring.
+ * @pdcs:  PDC state
+ *
+ * Called within the hard IRQ.
+ * Return:
+ */
+static int
+pdc_receive(struct pdc_state *pdcs)
+{
+	int rx_status;
+
+	/* read last_rx_curr from register once */
+	pdcs->last_rx_curr =
+	    (ioread32(&pdcs->rxregs_64->status0) &
+	     CRYPTO_D64_RS0_CD_MASK) / RING_ENTRY_SIZE;
+
+	do {
+		/* Could be many frames ready */
+		rx_status = pdc_receive_one(pdcs);
+	} while (rx_status == PDC_SUCCESS);
+
+	return 0;
 }
 
 /**
@@ -766,8 +793,8 @@ static int pdc_tx_list_final(struct pdc_
 	 * before chip starts to process new request
 	 */
 	wmb();
-	iowrite32(pdcs->rxout << 4, (void *)&pdcs->rxregs_64->ptr);
-	iowrite32(pdcs->txout << 4, (void *)&pdcs->txregs_64->ptr);
+	iowrite32(pdcs->rxout << 4, &pdcs->rxregs_64->ptr);
+	iowrite32(pdcs->txout << 4, &pdcs->txregs_64->ptr);
 	pdcs->pdc_requests++;
 
 	return PDC_SUCCESS;
@@ -796,6 +823,7 @@ static int pdc_rx_list_init(struct pdc_s
 	u32 rx_pkt_cnt = 1;	/* Adding a single rx buffer */
 	dma_addr_t daddr;
 	void *vaddr;
+	struct pdc_rx_ctx *rx_ctx;
 
 	rx_avail = pdcs->nrxpost - NRXDACTIVE(pdcs->rxin, pdcs->rxout,
 					      pdcs->nrxpost);
@@ -806,7 +834,7 @@ static int pdc_rx_list_init(struct pdc_s
 
 	/* allocate a buffer for the dma rx status */
 	vaddr = dma_pool_zalloc(pdcs->rx_buf_pool, GFP_ATOMIC, &daddr);
-	if (!vaddr)
+	if (unlikely(!vaddr))
 		return -ENOMEM;
 
 	/*
@@ -819,15 +847,16 @@ static int pdc_rx_list_init(struct pdc_s
 
 	/* This is always the first descriptor in the receive sequence */
 	flags = D64_CTRL1_SOF;
-	pdcs->rxin_numd[pdcs->rx_msg_start] = 1;
+	pdcs->rx_ctx[pdcs->rx_msg_start].rxin_numd = 1;
 
 	if (unlikely(pdcs->rxout == (pdcs->nrxd - 1)))
 		flags |= D64_CTRL1_EOT;
 
-	pdcs->rxp_ctx[pdcs->rxout] = ctx;
-	pdcs->dst_sg[pdcs->rxout] = dst_sg;
-	pdcs->resp_hdr[pdcs->rxout] = vaddr;
-	pdcs->resp_hdr_daddr[pdcs->rxout] = daddr;
+	rx_ctx = &pdcs->rx_ctx[pdcs->rxout];
+	rx_ctx->rxp_ctx = ctx;
+	rx_ctx->dst_sg = dst_sg;
+	rx_ctx->resp_hdr = vaddr;
+	rx_ctx->resp_hdr_daddr = daddr;
 	pdc_build_rxd(pdcs, daddr, pdcs->pdc_resp_hdr_len, flags);
 	return PDC_SUCCESS;
 }
@@ -895,7 +924,7 @@ static int pdc_rx_list_sg_add(struct pdc
 		desc_w++;
 		sg = sg_next(sg);
 	}
-	pdcs->rxin_numd[pdcs->rx_msg_start] += desc_w;
+	pdcs->rx_ctx[pdcs->rx_msg_start].rxin_numd += desc_w;
 
 	return PDC_SUCCESS;
 }
@@ -903,7 +932,7 @@ static int pdc_rx_list_sg_add(struct pdc
 /**
  * pdc_irq_handler() - Interrupt handler called in interrupt context.
  * @irq:      Interrupt number that has fired
- * @cookie:   PDC state for DMA engine that generated the interrupt
+ * @data:     device struct for DMA engine that generated the interrupt
  *
  * We have to clear the device interrupt status flags here. So cache the
  * status for later use in the thread function. Other than that, just return
@@ -912,88 +941,39 @@ static int pdc_rx_list_sg_add(struct pdc
  * Return: IRQ_WAKE_THREAD if interrupt is ours
  *         IRQ_NONE otherwise
  */
-static irqreturn_t pdc_irq_handler(int irq, void *cookie)
+static irqreturn_t pdc_irq_handler(int irq, void *data)
 {
-	struct pdc_state *pdcs = cookie;
+	struct device *dev = (struct device *)data;
+	struct pdc_state *pdcs = dev_get_drvdata(dev);
 	u32 intstatus = ioread32(pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET);
 
-	if (intstatus & PDC_XMTINTEN_0)
-		set_bit(PDC_XMTINT_0, &pdcs->intstatus);
-	if (intstatus & PDC_RCVINTEN_0)
-		set_bit(PDC_RCVINT_0, &pdcs->intstatus);
+	if (unlikely(intstatus == 0))
+		return IRQ_NONE;
+
+	/* Disable interrupts until soft handler runs */
+	iowrite32(0, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET);
 
 	/* Clear interrupt flags in device */
 	iowrite32(intstatus, pdcs->pdc_reg_vbase + PDC_INTSTATUS_OFFSET);
 
 	/* Wakeup IRQ thread */
-	if (pdcs && (irq == pdcs->pdc_irq) && (intstatus & PDC_INTMASK))
-		return IRQ_WAKE_THREAD;
-
-	return IRQ_NONE;
+	tasklet_schedule(&pdcs->rx_tasklet);
+	return IRQ_HANDLED;
 }
 
 /**
- * pdc_irq_thread() - Function invoked on deferred thread when a DMA tx has
- * completed or data is available to receive.
- * @irq:    Interrupt number
- * @cookie: PDC state for PDC that generated the interrupt
- *
- * On DMA tx complete, notify the mailbox client. On DMA rx complete, process
- * as many SPU response messages as are available and send each to the mailbox
- * client.
- *
- * Return: IRQ_HANDLED if we recognized and handled the interrupt
- *         IRQ_NONE otherwise
+ * pdc_tasklet_cb() - Tasklet callback that runs the deferred processing after
+ * a DMA receive interrupt. Reenables the receive interrupt.
+ * @data: PDC state structure
  */
-static irqreturn_t pdc_irq_thread(int irq, void *cookie)
+static void pdc_tasklet_cb(unsigned long data)
 {
-	struct pdc_state *pdcs = cookie;
-	struct mbox_controller *mbc;
-	struct mbox_chan *chan;
-	bool tx_int;
-	bool rx_int;
-	int rx_status;
-	struct brcm_message mssg;
-
-	tx_int = test_and_clear_bit(PDC_XMTINT_0, &pdcs->intstatus);
-	rx_int = test_and_clear_bit(PDC_RCVINT_0, &pdcs->intstatus);
-
-	if (pdcs && (tx_int || rx_int)) {
-		dev_dbg(&pdcs->pdev->dev,
-			"%s() got irq %d with tx_int %s, rx_int %s",
-			__func__, irq,
-			tx_int ? "set" : "clear", rx_int ? "set" : "clear");
+	struct pdc_state *pdcs = (struct pdc_state *)data;
 
-		mbc = &pdcs->mbc;
-		chan = &mbc->chans[0];
+	pdc_receive(pdcs);
 
-		if (tx_int) {
-			dev_dbg(&pdcs->pdev->dev, "%s(): tx done", __func__);
-			/* only one frame in flight at a time */
-			mbox_chan_txdone(chan, PDC_SUCCESS);
-		}
-		if (rx_int) {
-			while (1) {
-				/* Could be many frames ready */
-				memset(&mssg, 0, sizeof(mssg));
-				mssg.type = BRCM_MESSAGE_SPU;
-				rx_status = pdc_receive(pdcs, &mssg);
-				if (rx_status >= 0) {
-					dev_dbg(&pdcs->pdev->dev,
-						"%s(): invoking client rx cb",
-						__func__);
-					mbox_chan_received_data(chan, &mssg);
-				} else {
-					dev_dbg(&pdcs->pdev->dev,
-						"%s(): no SPU response available",
-						__func__);
-					break;
-				}
-			}
-		}
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
+	/* reenable interrupts */
+	iowrite32(PDC_INTMASK, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET);
 }
 
 /**
@@ -1016,14 +996,14 @@ static int pdc_ring_init(struct pdc_stat
 
 	/* Allocate tx ring */
 	tx.vbase = dma_pool_zalloc(pdcs->ring_pool, GFP_KERNEL, &tx.dmabase);
-	if (!tx.vbase) {
+	if (unlikely(!tx.vbase)) {
 		err = -ENOMEM;
 		goto done;
 	}
 
 	/* Allocate rx ring */
 	rx.vbase = dma_pool_zalloc(pdcs->ring_pool, GFP_KERNEL, &rx.dmabase);
-	if (!rx.vbase) {
+	if (unlikely(!rx.vbase)) {
 		err = -ENOMEM;
 		goto fail_dealloc;
 	}
@@ -1033,9 +1013,6 @@ static int pdc_ring_init(struct pdc_stat
 	dev_dbg(dev, " - base DMA addr of rx ring      %pad", &rx.dmabase);
 	dev_dbg(dev, " - base virtual addr of rx ring  %p", rx.vbase);
 
-	/* lock after ring allocation to avoid scheduling while atomic */
-	spin_lock(&pdcs->pdc_lock);
-
 	memcpy(&pdcs->tx_ring_alloc, &tx, sizeof(tx));
 	memcpy(&pdcs->rx_ring_alloc, &rx, sizeof(rx));
 
@@ -1053,40 +1030,52 @@ static int pdc_ring_init(struct pdc_stat
 
 	/* Tell device the base DMA address of each ring */
 	dma_reg = &pdcs->regs->dmaregs[ringset];
+
+	/* But first disable DMA and set curptr to 0 for both TX & RX */
+	iowrite32(PDC_TX_CTL, &dma_reg->dmaxmt.control);
+	iowrite32((PDC_RX_CTL + (pdcs->rx_status_len << 1)),
+		  &dma_reg->dmarcv.control);
+	iowrite32(0, &dma_reg->dmaxmt.ptr);
+	iowrite32(0, &dma_reg->dmarcv.ptr);
+
+	/* Set base DMA addresses */
 	iowrite32(lower_32_bits(pdcs->tx_ring_alloc.dmabase),
-		  (void *)&dma_reg->dmaxmt.addrlow);
+		  &dma_reg->dmaxmt.addrlow);
 	iowrite32(upper_32_bits(pdcs->tx_ring_alloc.dmabase),
-		  (void *)&dma_reg->dmaxmt.addrhigh);
+		  &dma_reg->dmaxmt.addrhigh);
 
 	iowrite32(lower_32_bits(pdcs->rx_ring_alloc.dmabase),
-		  (void *)&dma_reg->dmarcv.addrlow);
+		  &dma_reg->dmarcv.addrlow);
 	iowrite32(upper_32_bits(pdcs->rx_ring_alloc.dmabase),
-		  (void *)&dma_reg->dmarcv.addrhigh);
+		  &dma_reg->dmarcv.addrhigh);
+
+	/* Re-enable DMA */
+	iowrite32(PDC_TX_CTL | PDC_TX_ENABLE, &dma_reg->dmaxmt.control);
+	iowrite32((PDC_RX_CTL | PDC_RX_ENABLE | (pdcs->rx_status_len << 1)),
+		  &dma_reg->dmarcv.control);
 
 	/* Initialize descriptors */
 	for (i = 0; i < PDC_RING_ENTRIES; i++) {
 		/* Every tx descriptor can be used for start of frame. */
 		if (i != pdcs->ntxpost) {
 			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOF,
-				  (void *)&pdcs->txd_64[i].ctrl1);
+				  &pdcs->txd_64[i].ctrl1);
 		} else {
 			/* Last descriptor in ringset. Set End of Table. */
 			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOF |
-				  D64_CTRL1_EOT,
-				  (void *)&pdcs->txd_64[i].ctrl1);
+				  D64_CTRL1_EOT, &pdcs->txd_64[i].ctrl1);
 		}
 
 		/* Every rx descriptor can be used for start of frame */
 		if (i != pdcs->nrxpost) {
 			iowrite32(D64_CTRL1_SOF,
-				  (void *)&pdcs->rxd_64[i].ctrl1);
+				  &pdcs->rxd_64[i].ctrl1);
 		} else {
 			/* Last descriptor in ringset. Set End of Table. */
 			iowrite32(D64_CTRL1_SOF | D64_CTRL1_EOT,
-				  (void *)&pdcs->rxd_64[i].ctrl1);
+				  &pdcs->rxd_64[i].ctrl1);
 		}
 	}
-	spin_unlock(&pdcs->pdc_lock);
 	return PDC_SUCCESS;
 
 fail_dealloc:
@@ -1111,6 +1100,80 @@ static void pdc_ring_free(struct pdc_sta
 }
 
 /**
+ * pdc_desc_count() - Count the number of DMA descriptors that will be required
+ * for a given scatterlist. Account for the max length of a DMA buffer.
+ * @sg:    Scatterlist to be DMA'd
+ * Return: Number of descriptors required
+ */
+static u32 pdc_desc_count(struct scatterlist *sg)
+{
+	u32 cnt = 0;
+
+	while (sg) {
+		cnt += ((sg->length / PDC_DMA_BUF_MAX) + 1);
+		sg = sg_next(sg);
+	}
+	return cnt;
+}
+
+/**
+ * pdc_rings_full() - Check whether the tx ring has room for tx_cnt descriptors
+ * and the rx ring has room for rx_cnt descriptors.
+ * @pdcs:  PDC state
+ * @tx_cnt: The number of descriptors required in the tx ring
+ * @rx_cnt: The number of descriptors required i the rx ring
+ *
+ * Return: true if one of the rings does not have enough space
+ *         false if sufficient space is available in both rings
+ */
+static bool pdc_rings_full(struct pdc_state *pdcs, int tx_cnt, int rx_cnt)
+{
+	u32 rx_avail;
+	u32 tx_avail;
+	bool full = false;
+
+	/* Check if the tx and rx rings are likely to have enough space */
+	rx_avail = pdcs->nrxpost - NRXDACTIVE(pdcs->rxin, pdcs->rxout,
+					      pdcs->nrxpost);
+	if (unlikely(rx_cnt > rx_avail)) {
+		pdcs->rx_ring_full++;
+		full = true;
+	}
+
+	if (likely(!full)) {
+		tx_avail = pdcs->ntxpost - NTXDACTIVE(pdcs->txin, pdcs->txout,
+						      pdcs->ntxpost);
+		if (unlikely(tx_cnt > tx_avail)) {
+			pdcs->tx_ring_full++;
+			full = true;
+		}
+	}
+	return full;
+}
+
+/**
+ * pdc_last_tx_done() - If both the tx and rx rings have at least
+ * PDC_RING_SPACE_MIN descriptors available, then indicate that the mailbox
+ * framework can submit another message.
+ * @chan:  mailbox channel to check
+ * Return: true if PDC can accept another message on this channel
+ */
+static bool pdc_last_tx_done(struct mbox_chan *chan)
+{
+	struct pdc_state *pdcs = chan->con_priv;
+	bool ret;
+
+	if (unlikely(pdc_rings_full(pdcs, PDC_RING_SPACE_MIN,
+				    PDC_RING_SPACE_MIN))) {
+		pdcs->last_tx_not_done++;
+		ret = false;
+	} else {
+		ret = true;
+	}
+	return ret;
+}
+
+/**
  * pdc_send_data() - mailbox send_data function
  * @chan:	The mailbox channel on which the data is sent. The channel
  *              corresponds to a DMA ringset.
@@ -1141,29 +1204,43 @@ static int pdc_send_data(struct mbox_cha
 	int src_nent;
 	int dst_nent;
 	int nent;
+	u32 tx_desc_req;
+	u32 rx_desc_req;
 
-	if (mssg->type != BRCM_MESSAGE_SPU)
+	if (unlikely(mssg->type != BRCM_MESSAGE_SPU))
 		return -ENOTSUPP;
 
 	src_nent = sg_nents(mssg->spu.src);
-	if (src_nent) {
+	if (likely(src_nent)) {
 		nent = dma_map_sg(dev, mssg->spu.src, src_nent, DMA_TO_DEVICE);
-		if (nent == 0)
+		if (unlikely(nent == 0))
 			return -EIO;
 	}
 
 	dst_nent = sg_nents(mssg->spu.dst);
-	if (dst_nent) {
+	if (likely(dst_nent)) {
 		nent = dma_map_sg(dev, mssg->spu.dst, dst_nent,
 				  DMA_FROM_DEVICE);
-		if (nent == 0) {
+		if (unlikely(nent == 0)) {
 			dma_unmap_sg(dev, mssg->spu.src, src_nent,
 				     DMA_TO_DEVICE);
 			return -EIO;
 		}
 	}
 
-	spin_lock(&pdcs->pdc_lock);
+	/*
+	 * Check if the tx and rx rings have enough space. Do this prior to
+	 * writing any tx or rx descriptors. Need to ensure that we do not write
+	 * a partial set of descriptors, or write just rx descriptors but
+	 * corresponding tx descriptors don't fit. Note that we want this check
+	 * and the entire sequence of descriptor to happen without another
+	 * thread getting in. The channel spin lock in the mailbox framework
+	 * ensures this.
+	 */
+	tx_desc_req = pdc_desc_count(mssg->spu.src);
+	rx_desc_req = pdc_desc_count(mssg->spu.dst);
+	if (unlikely(pdc_rings_full(pdcs, tx_desc_req, rx_desc_req + 1)))
+		return -ENOSPC;
 
 	/* Create rx descriptors to SPU catch response */
 	err = pdc_rx_list_init(pdcs, mssg->spu.dst, mssg->ctx);
@@ -1173,9 +1250,7 @@ static int pdc_send_data(struct mbox_cha
 	err |= pdc_tx_list_sg_add(pdcs, mssg->spu.src);
 	err |= pdc_tx_list_final(pdcs);	/* initiate transfer */
 
-	spin_unlock(&pdcs->pdc_lock);
-
-	if (err)
+	if (unlikely(err))
 		dev_err(&pdcs->pdev->dev,
 			"%s failed with error %d", __func__, err);
 
@@ -1224,26 +1299,29 @@ void pdc_hw_init(struct pdc_state *pdcs)
 	/* initialize data structures */
 	pdcs->regs = (struct pdc_regs *)pdcs->pdc_reg_vbase;
 	pdcs->txregs_64 = (struct dma64_regs *)
-	    (void *)(((u8 *)pdcs->pdc_reg_vbase) +
+	    (((u8 *)pdcs->pdc_reg_vbase) +
 		     PDC_TXREGS_OFFSET + (sizeof(struct dma64) * ringset));
 	pdcs->rxregs_64 = (struct dma64_regs *)
-	    (void *)(((u8 *)pdcs->pdc_reg_vbase) +
+	    (((u8 *)pdcs->pdc_reg_vbase) +
 		     PDC_RXREGS_OFFSET + (sizeof(struct dma64) * ringset));
 
 	pdcs->ntxd = PDC_RING_ENTRIES;
 	pdcs->nrxd = PDC_RING_ENTRIES;
 	pdcs->ntxpost = PDC_RING_ENTRIES - 1;
 	pdcs->nrxpost = PDC_RING_ENTRIES - 1;
-	pdcs->regs->intmask = 0;
+	iowrite32(0, &pdcs->regs->intmask);
 
 	dma_reg = &pdcs->regs->dmaregs[ringset];
-	iowrite32(0, (void *)&dma_reg->dmaxmt.ptr);
-	iowrite32(0, (void *)&dma_reg->dmarcv.ptr);
 
-	iowrite32(PDC_TX_CTL, (void *)&dma_reg->dmaxmt.control);
+	/* Configure DMA but will enable later in pdc_ring_init() */
+	iowrite32(PDC_TX_CTL, &dma_reg->dmaxmt.control);
 
 	iowrite32(PDC_RX_CTL + (pdcs->rx_status_len << 1),
-		  (void *)&dma_reg->dmarcv.control);
+		  &dma_reg->dmarcv.control);
+
+	/* Reset current index pointers after making sure DMA is disabled */
+	iowrite32(0, &dma_reg->dmaxmt.ptr);
+	iowrite32(0, &dma_reg->dmarcv.ptr);
 
 	if (pdcs->pdc_resp_hdr_len == PDC_SPU2_RESP_HDR_LEN)
 		iowrite32(PDC_CKSUM_CTRL,
@@ -1251,6 +1329,21 @@ void pdc_hw_init(struct pdc_state *pdcs)
 }
 
 /**
+ * pdc_hw_disable() - Disable the tx and rx control in the hw.
+ * @pdcs: PDC state structure
+ *
+ */
+static void pdc_hw_disable(struct pdc_state *pdcs)
+{
+	struct dma64 *dma_reg;
+
+	dma_reg = &pdcs->regs->dmaregs[PDC_RINGSET];
+	iowrite32(PDC_TX_CTL, &dma_reg->dmaxmt.control);
+	iowrite32(PDC_RX_CTL + (pdcs->rx_status_len << 1),
+		  &dma_reg->dmarcv.control);
+}
+
+/**
  * pdc_rx_buf_pool_create() - Pool of receive buffers used to catch the metadata
  * header returned with each response message.
  * @pdcs: PDC state structure
@@ -1301,8 +1394,6 @@ static int pdc_interrupts_init(struct pd
 	struct device_node *dn = pdev->dev.of_node;
 	int err;
 
-	pdcs->intstatus = 0;
-
 	/* interrupt configuration */
 	iowrite32(PDC_INTMASK, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET);
 	iowrite32(PDC_LAZY_INT, pdcs->pdc_reg_vbase + PDC_RCVLAZY0_OFFSET);
@@ -1311,11 +1402,11 @@ static int pdc_interrupts_init(struct pd
 	pdcs->pdc_irq = irq_of_parse_and_map(dn, 0);
 	dev_dbg(dev, "pdc device %s irq %u for pdcs %p",
 		dev_name(dev), pdcs->pdc_irq, pdcs);
-	err = devm_request_threaded_irq(dev, pdcs->pdc_irq,
-					pdc_irq_handler,
-					pdc_irq_thread, 0, dev_name(dev), pdcs);
+
+	err = devm_request_irq(dev, pdcs->pdc_irq, pdc_irq_handler, 0,
+			       dev_name(dev), dev);
 	if (err) {
-		dev_err(dev, "threaded tx IRQ %u request failed with err %d\n",
+		dev_err(dev, "IRQ %u request failed with err %d\n",
 			pdcs->pdc_irq, err);
 		return err;
 	}
@@ -1324,6 +1415,7 @@ static int pdc_interrupts_init(struct pd
 
 static const struct mbox_chan_ops pdc_mbox_chan_ops = {
 	.send_data = pdc_send_data,
+	.last_tx_done = pdc_last_tx_done,
 	.startup = pdc_startup,
 	.shutdown = pdc_shutdown
 };
@@ -1356,8 +1448,9 @@ static int pdc_mb_init(struct pdc_state
 	if (!mbc->chans)
 		return -ENOMEM;
 
-	mbc->txdone_irq = true;
-	mbc->txdone_poll = false;
+	mbc->txdone_irq = false;
+	mbc->txdone_poll = true;
+	mbc->txpoll_period = 1;
 	for (chan_index = 0; chan_index < mbc->num_chans; chan_index++)
 		mbc->chans[chan_index].con_priv = pdcs;
 
@@ -1427,7 +1520,6 @@ static int pdc_probe(struct platform_dev
 		goto cleanup;
 	}
 
-	spin_lock_init(&pdcs->pdc_lock);
 	pdcs->pdev = pdev;
 	platform_set_drvdata(pdev, pdcs);
 	pdcs->pdc_idx = pdcg.num_spu;
@@ -1473,6 +1565,9 @@ static int pdc_probe(struct platform_dev
 
 	pdc_hw_init(pdcs);
 
+	/* Init tasklet for deferred DMA rx processing */
+	tasklet_init(&pdcs->rx_tasklet, pdc_tasklet_cb, (unsigned long)pdcs);
+
 	err = pdc_interrupts_init(pdcs);
 	if (err)
 		goto cleanup_buf_pool;
@@ -1489,6 +1584,7 @@ static int pdc_probe(struct platform_dev
 	return PDC_SUCCESS;
 
 cleanup_buf_pool:
+	tasklet_kill(&pdcs->rx_tasklet);
 	dma_pool_destroy(pdcs->rx_buf_pool);
 
 cleanup_ring_pool:
@@ -1504,6 +1600,10 @@ static int pdc_remove(struct platform_de
 
 	pdc_free_debugfs();
 
+	tasklet_kill(&pdcs->rx_tasklet);
+
+	pdc_hw_disable(pdcs);
+
 	mbox_controller_unregister(&pdcs->mbc);
 
 	dma_pool_destroy(pdcs->rx_buf_pool);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/Kconfig linux-libre-4.10-rc8-gnu/drivers/mailbox/Kconfig
--- linux-libre-4.9-gnu/drivers/mailbox/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -124,6 +124,15 @@ config MAILBOX_TEST
 	  Test client to help with testing new Controller driver
 	  implementations.
 
+config TEGRA_HSP_MBOX
+	bool "Tegra HSP (Hardware Synchronization Primitives) Driver"
+	depends on ARCH_TEGRA_186_SOC
+	help
+	  The Tegra HSP driver is used for the interprocessor communication
+	  between different remote processors and host processors on Tegra186
+	  and later SoCs. Say Y here if you want to have this support.
+	  If unsure say N.
+
 config XGENE_SLIMPRO_MBOX
 	tristate "APM SoC X-Gene SLIMpro Mailbox Controller"
 	depends on ARCH_XGENE
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/mailbox.c linux-libre-4.10-rc8-gnu/drivers/mailbox/mailbox.c
--- linux-libre-4.9-gnu/drivers/mailbox/mailbox.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/mailbox.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,8 +87,7 @@ exit:
 
 	if (!err && (chan->txdone_method & TXDONE_BY_POLL))
 		/* kick start the timer immediately to avoid delays */
-		hrtimer_start(&chan->mbox->poll_hrt, ktime_set(0, 0),
-			      HRTIMER_MODE_REL);
+		hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
 }
 
 static void tx_tick(struct mbox_chan *chan, int r)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/mailbox-sti.c linux-libre-4.10-rc8-gnu/drivers/mailbox/mailbox-sti.c
--- linux-libre-4.9-gnu/drivers/mailbox/mailbox-sti.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/mailbox-sti.c	2017-02-12 16:03:20.000000000 -0500
@@ -403,6 +403,7 @@ static const struct of_device_id sti_mai
 	},
 	{ }
 };
+MODULE_DEVICE_TABLE(of, sti_mailbox_match);
 
 static int sti_mbox_probe(struct platform_device *pdev)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/mailbox-test.c linux-libre-4.10-rc8-gnu/drivers/mailbox/mailbox-test.c
--- linux-libre-4.9-gnu/drivers/mailbox/mailbox-test.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/mailbox-test.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,12 +11,14 @@
 
 #include <linux/debugfs.h>
 #include <linux/err.h>
+#include <linux/fs.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
@@ -39,6 +41,8 @@ struct mbox_test_device {
 	char			*signal;
 	char			*message;
 	spinlock_t		lock;
+	wait_queue_head_t	waitq;
+	struct fasync_struct	*async_queue;
 };
 
 static ssize_t mbox_test_signal_write(struct file *filp,
@@ -81,6 +85,13 @@ static const struct file_operations mbox
 	.llseek	= generic_file_llseek,
 };
 
+static int mbox_test_message_fasync(int fd, struct file *filp, int on)
+{
+	struct mbox_test_device *tdev = filp->private_data;
+
+	return fasync_helper(fd, filp, on, &tdev->async_queue);
+}
+
 static ssize_t mbox_test_message_write(struct file *filp,
 				       const char __user *userbuf,
 				       size_t count, loff_t *ppos)
@@ -138,6 +149,20 @@ out:
 	return ret < 0 ? ret : count;
 }
 
+static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
+{
+	unsigned char data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tdev->lock, flags);
+	data = tdev->rx_buffer[0];
+	spin_unlock_irqrestore(&tdev->lock, flags);
+
+	if (data != '\0')
+		return true;
+	return false;
+}
+
 static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
 				      size_t count, loff_t *ppos)
 {
@@ -147,6 +172,8 @@ static ssize_t mbox_test_message_read(st
 	int l = 0;
 	int ret;
 
+	DECLARE_WAITQUEUE(wait, current);
+
 	touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
 	if (!touser)
 		return -ENOMEM;
@@ -155,15 +182,29 @@ static ssize_t mbox_test_message_read(st
 		ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
 		ret = simple_read_from_buffer(userbuf, count, ppos,
 					      touser, ret);
-		goto out;
+		goto kfree_err;
 	}
 
-	if (tdev->rx_buffer[0] == '\0') {
-		ret = snprintf(touser, 9, "<EMPTY>\n");
-		ret = simple_read_from_buffer(userbuf, count, ppos,
-					      touser, ret);
-		goto out;
-	}
+	add_wait_queue(&tdev->waitq, &wait);
+
+	do {
+		__set_current_state(TASK_INTERRUPTIBLE);
+
+		if (mbox_test_message_data_ready(tdev))
+			break;
+
+		if (filp->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			goto waitq_err;
+		}
+
+		if (signal_pending(current)) {
+			ret = -ERESTARTSYS;
+			goto waitq_err;
+		}
+		schedule();
+
+	} while (1);
 
 	spin_lock_irqsave(&tdev->lock, flags);
 
@@ -185,14 +226,31 @@ static ssize_t mbox_test_message_read(st
 	spin_unlock_irqrestore(&tdev->lock, flags);
 
 	ret = simple_read_from_buffer(userbuf, count, ppos, touser, MBOX_HEXDUMP_MAX_LEN);
-out:
+waitq_err:
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&tdev->waitq, &wait);
+kfree_err:
 	kfree(touser);
 	return ret;
 }
 
+static unsigned int
+mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait)
+{
+	struct mbox_test_device *tdev = filp->private_data;
+
+	poll_wait(filp, &tdev->waitq, wait);
+
+	if (mbox_test_message_data_ready(tdev))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
 static const struct file_operations mbox_test_message_ops = {
 	.write	= mbox_test_message_write,
 	.read	= mbox_test_message_read,
+	.fasync	= mbox_test_message_fasync,
+	.poll	= mbox_test_message_poll,
 	.open	= simple_open,
 	.llseek	= generic_file_llseek,
 };
@@ -234,6 +292,10 @@ static void mbox_test_receive_message(st
 		memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
 	}
 	spin_unlock_irqrestore(&tdev->lock, flags);
+
+	wake_up_interruptible(&tdev->waitq);
+
+	kill_fasync(&tdev->async_queue, SIGIO, POLL_IN);
 }
 
 static void mbox_test_prepare_message(struct mbox_client *client, void *message)
@@ -290,6 +352,7 @@ static int mbox_test_probe(struct platfo
 {
 	struct mbox_test_device *tdev;
 	struct resource *res;
+	resource_size_t size;
 	int ret;
 
 	tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
@@ -298,14 +361,21 @@ static int mbox_test_probe(struct platfo
 
 	/* It's okay for MMIO to be NULL */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	size = resource_size(res);
 	tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(tdev->tx_mmio))
+	if (PTR_ERR(tdev->tx_mmio) == -EBUSY)
+		/* if reserved area in SRAM, try just ioremap */
+		tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
+	else if (IS_ERR(tdev->tx_mmio))
 		tdev->tx_mmio = NULL;
 
 	/* If specified, second reg entry is Rx MMIO */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	size = resource_size(res);
 	tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(tdev->rx_mmio))
+	if (PTR_ERR(tdev->rx_mmio) == -EBUSY)
+		tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
+	else if (IS_ERR(tdev->rx_mmio))
 		tdev->rx_mmio = tdev->tx_mmio;
 
 	tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
@@ -334,6 +404,7 @@ static int mbox_test_probe(struct platfo
 	if (ret)
 		return ret;
 
+	init_waitqueue_head(&tdev->waitq);
 	dev_info(&pdev->dev, "Successfully registered\n");
 
 	return 0;
@@ -357,6 +428,7 @@ static const struct of_device_id mbox_te
 	{ .compatible = "mailbox-test" },
 	{},
 };
+MODULE_DEVICE_TABLE(of, mbox_test_match);
 
 static struct platform_driver mbox_test_driver = {
 	.driver = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/Makefile linux-libre-4.10-rc8-gnu/drivers/mailbox/Makefile
--- linux-libre-4.9-gnu/drivers/mailbox/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -29,3 +29,5 @@ obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mail
 obj-$(CONFIG_HI6220_MBOX)	+= hi6220-mailbox.o
 
 obj-$(CONFIG_BCM_PDC_MBOX)	+= bcm-pdc-mailbox.o
+
+obj-$(CONFIG_TEGRA_HSP_MBOX)	+= tegra-hsp.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/pcc.c linux-libre-4.10-rc8-gnu/drivers/mailbox/pcc.c
--- linux-libre-4.9-gnu/drivers/mailbox/pcc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/pcc.c	2017-02-12 16:03:20.000000000 -0500
@@ -447,7 +447,6 @@ static int pcc_parse_subspace_irq(int id
  */
 static int __init acpi_pcc_probe(void)
 {
-	acpi_size pcct_tbl_header_size;
 	struct acpi_table_header *pcct_tbl;
 	struct acpi_subtable_header *pcct_entry;
 	struct acpi_table_pcct *acpi_pcct_tbl;
@@ -456,9 +455,7 @@ static int __init acpi_pcc_probe(void)
 	acpi_status status = AE_OK;
 
 	/* Search for PCCT */
-	status = acpi_get_table_with_size(ACPI_SIG_PCCT, 0,
-			&pcct_tbl,
-			&pcct_tbl_header_size);
+	status = acpi_get_table(ACPI_SIG_PCCT, 0, &pcct_tbl);
 
 	if (ACPI_FAILURE(status) || !pcct_tbl) {
 		pr_warn("PCCT header not found.\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mailbox/tegra-hsp.c linux-libre-4.10-rc8-gnu/drivers/mailbox/tegra-hsp.c
--- linux-libre-4.9-gnu/drivers/mailbox/tegra-hsp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mailbox/tegra-hsp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mailbox_controller.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/mailbox/tegra186-hsp.h>
+
+#define HSP_INT_DIMENSIONING	0x380
+#define HSP_nSM_SHIFT		0
+#define HSP_nSS_SHIFT		4
+#define HSP_nAS_SHIFT		8
+#define HSP_nDB_SHIFT		12
+#define HSP_nSI_SHIFT		16
+#define HSP_nINT_MASK		0xf
+
+#define HSP_DB_TRIGGER	0x0
+#define HSP_DB_ENABLE	0x4
+#define HSP_DB_RAW	0x8
+#define HSP_DB_PENDING	0xc
+
+#define HSP_DB_CCPLEX		1
+#define HSP_DB_BPMP		3
+#define HSP_DB_MAX		7
+
+struct tegra_hsp_channel;
+struct tegra_hsp;
+
+struct tegra_hsp_channel {
+	struct tegra_hsp *hsp;
+	struct mbox_chan *chan;
+	void __iomem *regs;
+};
+
+struct tegra_hsp_doorbell {
+	struct tegra_hsp_channel channel;
+	struct list_head list;
+	const char *name;
+	unsigned int master;
+	unsigned int index;
+};
+
+struct tegra_hsp_db_map {
+	const char *name;
+	unsigned int master;
+	unsigned int index;
+};
+
+struct tegra_hsp_soc {
+	const struct tegra_hsp_db_map *map;
+};
+
+struct tegra_hsp {
+	const struct tegra_hsp_soc *soc;
+	struct mbox_controller mbox;
+	void __iomem *regs;
+	unsigned int irq;
+	unsigned int num_sm;
+	unsigned int num_as;
+	unsigned int num_ss;
+	unsigned int num_db;
+	unsigned int num_si;
+	spinlock_t lock;
+
+	struct list_head doorbells;
+};
+
+static inline struct tegra_hsp *
+to_tegra_hsp(struct mbox_controller *mbox)
+{
+	return container_of(mbox, struct tegra_hsp, mbox);
+}
+
+static inline u32 tegra_hsp_readl(struct tegra_hsp *hsp, unsigned int offset)
+{
+	return readl(hsp->regs + offset);
+}
+
+static inline void tegra_hsp_writel(struct tegra_hsp *hsp, u32 value,
+				    unsigned int offset)
+{
+	writel(value, hsp->regs + offset);
+}
+
+static inline u32 tegra_hsp_channel_readl(struct tegra_hsp_channel *channel,
+					  unsigned int offset)
+{
+	return readl(channel->regs + offset);
+}
+
+static inline void tegra_hsp_channel_writel(struct tegra_hsp_channel *channel,
+					    u32 value, unsigned int offset)
+{
+	writel(value, channel->regs + offset);
+}
+
+static bool tegra_hsp_doorbell_can_ring(struct tegra_hsp_doorbell *db)
+{
+	u32 value;
+
+	value = tegra_hsp_channel_readl(&db->channel, HSP_DB_ENABLE);
+
+	return (value & BIT(TEGRA_HSP_DB_MASTER_CCPLEX)) != 0;
+}
+
+static struct tegra_hsp_doorbell *
+__tegra_hsp_doorbell_get(struct tegra_hsp *hsp, unsigned int master)
+{
+	struct tegra_hsp_doorbell *entry;
+
+	list_for_each_entry(entry, &hsp->doorbells, list)
+		if (entry->master == master)
+			return entry;
+
+	return NULL;
+}
+
+static struct tegra_hsp_doorbell *
+tegra_hsp_doorbell_get(struct tegra_hsp *hsp, unsigned int master)
+{
+	struct tegra_hsp_doorbell *db;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsp->lock, flags);
+	db = __tegra_hsp_doorbell_get(hsp, master);
+	spin_unlock_irqrestore(&hsp->lock, flags);
+
+	return db;
+}
+
+static irqreturn_t tegra_hsp_doorbell_irq(int irq, void *data)
+{
+	struct tegra_hsp *hsp = data;
+	struct tegra_hsp_doorbell *db;
+	unsigned long master, value;
+
+	db = tegra_hsp_doorbell_get(hsp, TEGRA_HSP_DB_MASTER_CCPLEX);
+	if (!db)
+		return IRQ_NONE;
+
+	value = tegra_hsp_channel_readl(&db->channel, HSP_DB_PENDING);
+	tegra_hsp_channel_writel(&db->channel, value, HSP_DB_PENDING);
+
+	spin_lock(&hsp->lock);
+
+	for_each_set_bit(master, &value, hsp->mbox.num_chans) {
+		struct tegra_hsp_doorbell *db;
+
+		db = __tegra_hsp_doorbell_get(hsp, master);
+		/*
+		 * Depending on the bootloader chain, the CCPLEX doorbell will
+		 * have some doorbells enabled, which means that requesting an
+		 * interrupt will immediately fire.
+		 *
+		 * In that case, db->channel.chan will still be NULL here and
+		 * cause a crash if not properly guarded.
+		 *
+		 * It remains to be seen if ignoring the doorbell in that case
+		 * is the correct solution.
+		 */
+		if (db && db->channel.chan)
+			mbox_chan_received_data(db->channel.chan, NULL);
+	}
+
+	spin_unlock(&hsp->lock);
+
+	return IRQ_HANDLED;
+}
+
+static struct tegra_hsp_channel *
+tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
+			  unsigned int master, unsigned int index)
+{
+	struct tegra_hsp_doorbell *db;
+	unsigned int offset;
+	unsigned long flags;
+
+	db = kzalloc(sizeof(*db), GFP_KERNEL);
+	if (!db)
+		return ERR_PTR(-ENOMEM);
+
+	offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) << 16;
+	offset += index * 0x100;
+
+	db->channel.regs = hsp->regs + offset;
+	db->channel.hsp = hsp;
+
+	db->name = kstrdup_const(name, GFP_KERNEL);
+	db->master = master;
+	db->index = index;
+
+	spin_lock_irqsave(&hsp->lock, flags);
+	list_add_tail(&db->list, &hsp->doorbells);
+	spin_unlock_irqrestore(&hsp->lock, flags);
+
+	return &db->channel;
+}
+
+static void __tegra_hsp_doorbell_destroy(struct tegra_hsp_doorbell *db)
+{
+	list_del(&db->list);
+	kfree_const(db->name);
+	kfree(db);
+}
+
+static int tegra_hsp_doorbell_send_data(struct mbox_chan *chan, void *data)
+{
+	struct tegra_hsp_doorbell *db = chan->con_priv;
+
+	tegra_hsp_channel_writel(&db->channel, 1, HSP_DB_TRIGGER);
+
+	return 0;
+}
+
+static int tegra_hsp_doorbell_startup(struct mbox_chan *chan)
+{
+	struct tegra_hsp_doorbell *db = chan->con_priv;
+	struct tegra_hsp *hsp = db->channel.hsp;
+	struct tegra_hsp_doorbell *ccplex;
+	unsigned long flags;
+	u32 value;
+
+	if (db->master >= hsp->mbox.num_chans) {
+		dev_err(hsp->mbox.dev,
+			"invalid master ID %u for HSP channel\n",
+			db->master);
+		return -EINVAL;
+	}
+
+	ccplex = tegra_hsp_doorbell_get(hsp, TEGRA_HSP_DB_MASTER_CCPLEX);
+	if (!ccplex)
+		return -ENODEV;
+
+	if (!tegra_hsp_doorbell_can_ring(db))
+		return -ENODEV;
+
+	spin_lock_irqsave(&hsp->lock, flags);
+
+	value = tegra_hsp_channel_readl(&ccplex->channel, HSP_DB_ENABLE);
+	value |= BIT(db->master);
+	tegra_hsp_channel_writel(&ccplex->channel, value, HSP_DB_ENABLE);
+
+	spin_unlock_irqrestore(&hsp->lock, flags);
+
+	return 0;
+}
+
+static void tegra_hsp_doorbell_shutdown(struct mbox_chan *chan)
+{
+	struct tegra_hsp_doorbell *db = chan->con_priv;
+	struct tegra_hsp *hsp = db->channel.hsp;
+	struct tegra_hsp_doorbell *ccplex;
+	unsigned long flags;
+	u32 value;
+
+	ccplex = tegra_hsp_doorbell_get(hsp, TEGRA_HSP_DB_MASTER_CCPLEX);
+	if (!ccplex)
+		return;
+
+	spin_lock_irqsave(&hsp->lock, flags);
+
+	value = tegra_hsp_channel_readl(&ccplex->channel, HSP_DB_ENABLE);
+	value &= ~BIT(db->master);
+	tegra_hsp_channel_writel(&ccplex->channel, value, HSP_DB_ENABLE);
+
+	spin_unlock_irqrestore(&hsp->lock, flags);
+}
+
+static const struct mbox_chan_ops tegra_hsp_doorbell_ops = {
+	.send_data = tegra_hsp_doorbell_send_data,
+	.startup = tegra_hsp_doorbell_startup,
+	.shutdown = tegra_hsp_doorbell_shutdown,
+};
+
+static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
+					    const struct of_phandle_args *args)
+{
+	struct tegra_hsp_channel *channel = ERR_PTR(-ENODEV);
+	struct tegra_hsp *hsp = to_tegra_hsp(mbox);
+	unsigned int type = args->args[0];
+	unsigned int master = args->args[1];
+	struct tegra_hsp_doorbell *db;
+	struct mbox_chan *chan;
+	unsigned long flags;
+	unsigned int i;
+
+	switch (type) {
+	case TEGRA_HSP_MBOX_TYPE_DB:
+		db = tegra_hsp_doorbell_get(hsp, master);
+		if (db)
+			channel = &db->channel;
+
+		break;
+
+	default:
+		break;
+	}
+
+	if (IS_ERR(channel))
+		return ERR_CAST(channel);
+
+	spin_lock_irqsave(&hsp->lock, flags);
+
+	for (i = 0; i < hsp->mbox.num_chans; i++) {
+		chan = &hsp->mbox.chans[i];
+		if (!chan->con_priv) {
+			chan->con_priv = channel;
+			channel->chan = chan;
+			break;
+		}
+
+		chan = NULL;
+	}
+
+	spin_unlock_irqrestore(&hsp->lock, flags);
+
+	return chan ?: ERR_PTR(-EBUSY);
+}
+
+static void tegra_hsp_remove_doorbells(struct tegra_hsp *hsp)
+{
+	struct tegra_hsp_doorbell *db, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsp->lock, flags);
+
+	list_for_each_entry_safe(db, tmp, &hsp->doorbells, list)
+		__tegra_hsp_doorbell_destroy(db);
+
+	spin_unlock_irqrestore(&hsp->lock, flags);
+}
+
+static int tegra_hsp_add_doorbells(struct tegra_hsp *hsp)
+{
+	const struct tegra_hsp_db_map *map = hsp->soc->map;
+	struct tegra_hsp_channel *channel;
+
+	while (map->name) {
+		channel = tegra_hsp_doorbell_create(hsp, map->name,
+						    map->master, map->index);
+		if (IS_ERR(channel)) {
+			tegra_hsp_remove_doorbells(hsp);
+			return PTR_ERR(channel);
+		}
+
+		map++;
+	}
+
+	return 0;
+}
+
+static int tegra_hsp_probe(struct platform_device *pdev)
+{
+	struct tegra_hsp *hsp;
+	struct resource *res;
+	u32 value;
+	int err;
+
+	hsp = devm_kzalloc(&pdev->dev, sizeof(*hsp), GFP_KERNEL);
+	if (!hsp)
+		return -ENOMEM;
+
+	hsp->soc = of_device_get_match_data(&pdev->dev);
+	INIT_LIST_HEAD(&hsp->doorbells);
+	spin_lock_init(&hsp->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hsp->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hsp->regs))
+		return PTR_ERR(hsp->regs);
+
+	value = tegra_hsp_readl(hsp, HSP_INT_DIMENSIONING);
+	hsp->num_sm = (value >> HSP_nSM_SHIFT) & HSP_nINT_MASK;
+	hsp->num_ss = (value >> HSP_nSS_SHIFT) & HSP_nINT_MASK;
+	hsp->num_as = (value >> HSP_nAS_SHIFT) & HSP_nINT_MASK;
+	hsp->num_db = (value >> HSP_nDB_SHIFT) & HSP_nINT_MASK;
+	hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK;
+
+	err = platform_get_irq_byname(pdev, "doorbell");
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to get doorbell IRQ: %d\n", err);
+		return err;
+	}
+
+	hsp->irq = err;
+
+	hsp->mbox.of_xlate = of_tegra_hsp_xlate;
+	hsp->mbox.num_chans = 32;
+	hsp->mbox.dev = &pdev->dev;
+	hsp->mbox.txdone_irq = false;
+	hsp->mbox.txdone_poll = false;
+	hsp->mbox.ops = &tegra_hsp_doorbell_ops;
+
+	hsp->mbox.chans = devm_kcalloc(&pdev->dev, hsp->mbox.num_chans,
+					sizeof(*hsp->mbox.chans),
+					GFP_KERNEL);
+	if (!hsp->mbox.chans)
+		return -ENOMEM;
+
+	err = tegra_hsp_add_doorbells(hsp);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to add doorbells: %d\n", err);
+		return err;
+	}
+
+	platform_set_drvdata(pdev, hsp);
+
+	err = mbox_controller_register(&hsp->mbox);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register mailbox: %d\n", err);
+		tegra_hsp_remove_doorbells(hsp);
+		return err;
+	}
+
+	err = devm_request_irq(&pdev->dev, hsp->irq, tegra_hsp_doorbell_irq,
+			       IRQF_NO_SUSPEND, dev_name(&pdev->dev), hsp);
+	if (err < 0) {
+		dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n",
+			hsp->irq, err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int tegra_hsp_remove(struct platform_device *pdev)
+{
+	struct tegra_hsp *hsp = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&hsp->mbox);
+	tegra_hsp_remove_doorbells(hsp);
+
+	return 0;
+}
+
+static const struct tegra_hsp_db_map tegra186_hsp_db_map[] = {
+	{ "ccplex", TEGRA_HSP_DB_MASTER_CCPLEX, HSP_DB_CCPLEX, },
+	{ "bpmp",   TEGRA_HSP_DB_MASTER_BPMP,   HSP_DB_BPMP,   },
+	{ /* sentinel */ }
+};
+
+static const struct tegra_hsp_soc tegra186_hsp_soc = {
+	.map = tegra186_hsp_db_map,
+};
+
+static const struct of_device_id tegra_hsp_match[] = {
+	{ .compatible = "nvidia,tegra186-hsp", .data = &tegra186_hsp_soc },
+	{ }
+};
+
+static struct platform_driver tegra_hsp_driver = {
+	.driver = {
+		.name = "tegra-hsp",
+		.of_match_table = tegra_hsp_match,
+	},
+	.probe = tegra_hsp_probe,
+	.remove = tegra_hsp_remove,
+};
+
+static int __init tegra_hsp_init(void)
+{
+	return platform_driver_register(&tegra_hsp_driver);
+}
+core_initcall(tegra_hsp_init);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/Makefile linux-libre-4.10-rc8-gnu/drivers/Makefile
--- linux-libre-4.9-gnu/drivers/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -107,7 +107,7 @@ obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_RTC_LIB)		+= rtc/
 obj-y				+= i2c/ media/
 obj-$(CONFIG_PPS)		+= pps/
-obj-$(CONFIG_PTP_1588_CLOCK)	+= ptp/
+obj-y				+= ptp/
 obj-$(CONFIG_W1)		+= w1/
 obj-y				+= power/
 obj-$(CONFIG_HWMON)		+= hwmon/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mcb/mcb-parse.c linux-libre-4.10-rc8-gnu/drivers/mcb/mcb-parse.c
--- linux-libre-4.9-gnu/drivers/mcb/mcb-parse.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mcb/mcb-parse.c	2017-02-12 16:03:20.000000000 -0500
@@ -149,7 +149,7 @@ static int chameleon_get_bar(char __iome
 		reg = readl(*base);
 
 		bar_count = BAR_CNT(reg);
-		if (bar_count <= 0 && bar_count > CHAMELEON_BAR_MAX)
+		if (bar_count <= 0 || bar_count > CHAMELEON_BAR_MAX)
 			return -ENODEV;
 
 		c = kcalloc(bar_count, sizeof(struct chameleon_bar),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/bcache.h linux-libre-4.10-rc8-gnu/drivers/md/bcache/bcache.h
--- linux-libre-4.9-gnu/drivers/md/bcache/bcache.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/bcache.h	2017-02-12 16:03:20.000000000 -0500
@@ -425,7 +425,7 @@ struct cache {
 	 * until a gc finishes - otherwise we could pointlessly burn a ton of
 	 * cpu
 	 */
-	unsigned		invalidate_needs_gc:1;
+	unsigned		invalidate_needs_gc;
 
 	bool			discard; /* Get rid of? */
 
@@ -593,8 +593,8 @@ struct cache_set {
 
 	/* Counts how many sectors bio_insert has added to the cache */
 	atomic_t		sectors_to_gc;
+	wait_queue_head_t	gc_wait;
 
-	wait_queue_head_t	moving_gc_wait;
 	struct keybuf		moving_gc_keys;
 	/* Number of moving GC bios in flight */
 	struct semaphore	moving_in_flight;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/btree.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/btree.c
--- linux-libre-4.9-gnu/drivers/md/bcache/btree.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/btree.c	2017-02-12 16:03:20.000000000 -0500
@@ -297,7 +297,7 @@ static void bch_btree_node_read(struct b
 	bio->bi_iter.bi_size = KEY_SIZE(&b->key) << 9;
 	bio->bi_end_io	= btree_node_read_endio;
 	bio->bi_private	= &cl;
-	bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC);
+	bio->bi_opf = REQ_OP_READ | REQ_META;
 
 	bch_bio_map(bio, b->keys.set[0].data);
 
@@ -393,7 +393,7 @@ static void do_btree_node_write(struct b
 	b->bio->bi_end_io	= btree_node_write_endio;
 	b->bio->bi_private	= cl;
 	b->bio->bi_iter.bi_size	= roundup(set_bytes(i), block_bytes(b->c));
-	bio_set_op_attrs(b->bio, REQ_OP_WRITE, REQ_META|WRITE_SYNC|REQ_FUA);
+	b->bio->bi_opf		= REQ_OP_WRITE | REQ_META | REQ_FUA;
 	bch_bio_map(b->bio, i);
 
 	/*
@@ -1757,32 +1757,34 @@ static void bch_btree_gc(struct cache_se
 	bch_moving_gc(c);
 }
 
-static int bch_gc_thread(void *arg)
+static bool gc_should_run(struct cache_set *c)
 {
-	struct cache_set *c = arg;
 	struct cache *ca;
 	unsigned i;
 
-	while (1) {
-again:
-		bch_btree_gc(c);
+	for_each_cache(ca, c, i)
+		if (ca->invalidate_needs_gc)
+			return true;
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (kthread_should_stop())
-			break;
+	if (atomic_read(&c->sectors_to_gc) < 0)
+		return true;
 
-		mutex_lock(&c->bucket_lock);
+	return false;
+}
 
-		for_each_cache(ca, c, i)
-			if (ca->invalidate_needs_gc) {
-				mutex_unlock(&c->bucket_lock);
-				set_current_state(TASK_RUNNING);
-				goto again;
-			}
+static int bch_gc_thread(void *arg)
+{
+	struct cache_set *c = arg;
 
-		mutex_unlock(&c->bucket_lock);
+	while (1) {
+		wait_event_interruptible(c->gc_wait,
+			   kthread_should_stop() || gc_should_run(c));
 
-		schedule();
+		if (kthread_should_stop())
+			break;
+
+		set_gc_sectors(c);
+		bch_btree_gc(c);
 	}
 
 	return 0;
@@ -1790,11 +1792,10 @@ again:
 
 int bch_gc_thread_start(struct cache_set *c)
 {
-	c->gc_thread = kthread_create(bch_gc_thread, c, "bcache_gc");
+	c->gc_thread = kthread_run(bch_gc_thread, c, "bcache_gc");
 	if (IS_ERR(c->gc_thread))
 		return PTR_ERR(c->gc_thread);
 
-	set_task_state(c->gc_thread, TASK_INTERRUPTIBLE);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/btree.h linux-libre-4.10-rc8-gnu/drivers/md/bcache/btree.h
--- linux-libre-4.9-gnu/drivers/md/bcache/btree.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/btree.h	2017-02-12 16:03:20.000000000 -0500
@@ -260,8 +260,7 @@ void bch_initial_mark_key(struct cache_s
 
 static inline void wake_up_gc(struct cache_set *c)
 {
-	if (c->gc_thread)
-		wake_up_process(c->gc_thread);
+	wake_up(&c->gc_wait);
 }
 
 #define MAP_DONE	0
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/debug.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/debug.c
--- linux-libre-4.9-gnu/drivers/md/bcache/debug.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/debug.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@ void bch_btree_verify(struct btree *b)
 	bio->bi_bdev		= PTR_CACHE(b->c, &b->key, 0)->bdev;
 	bio->bi_iter.bi_sector	= PTR_OFFSET(&b->key, 0);
 	bio->bi_iter.bi_size	= KEY_SIZE(&v->key) << 9;
-	bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC);
+	bio->bi_opf		= REQ_OP_READ | REQ_META;
 	bch_bio_map(bio, sorted);
 
 	submit_bio_wait(bio);
@@ -107,22 +107,26 @@ void bch_data_verify(struct cached_dev *
 {
 	char name[BDEVNAME_SIZE];
 	struct bio *check;
-	struct bio_vec bv;
-	struct bvec_iter iter;
+	struct bio_vec bv, cbv;
+	struct bvec_iter iter, citer = { 0 };
 
 	check = bio_clone(bio, GFP_NOIO);
 	if (!check)
 		return;
-	bio_set_op_attrs(check, REQ_OP_READ, READ_SYNC);
+	check->bi_opf = REQ_OP_READ;
 
 	if (bio_alloc_pages(check, GFP_NOIO))
 		goto out_put;
 
 	submit_bio_wait(check);
 
+	citer.bi_size = UINT_MAX;
 	bio_for_each_segment(bv, bio, iter) {
 		void *p1 = kmap_atomic(bv.bv_page);
-		void *p2 = page_address(check->bi_io_vec[iter.bi_idx].bv_page);
+		void *p2;
+
+		cbv = bio_iter_iovec(check, citer);
+		p2 = page_address(cbv.bv_page);
 
 		cache_set_err_on(memcmp(p1 + bv.bv_offset,
 					p2 + bv.bv_offset,
@@ -133,6 +137,7 @@ void bch_data_verify(struct cached_dev *
 				 (uint64_t) bio->bi_iter.bi_sector);
 
 		kunmap_atomic(p1);
+		bio_advance_iter(check, &citer, bv.bv_len);
 	}
 
 	bio_free_pages(check);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/io.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/io.c
--- linux-libre-4.9-gnu/drivers/md/bcache/io.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/io.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,9 +24,7 @@ struct bio *bch_bbio_alloc(struct cache_
 	struct bbio *b = mempool_alloc(c->bio_meta, GFP_NOIO);
 	struct bio *bio = &b->bio;
 
-	bio_init(bio);
-	bio->bi_max_vecs	 = bucket_pages(c);
-	bio->bi_io_vec		 = bio->bi_inline_vecs;
+	bio_init(bio, bio->bi_inline_vecs, bucket_pages(c));
 
 	return bio;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/journal.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/journal.c
--- linux-libre-4.9-gnu/drivers/md/bcache/journal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/journal.c	2017-02-12 16:03:20.000000000 -0500
@@ -448,13 +448,11 @@ static void do_journal_discard(struct ca
 
 		atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT);
 
-		bio_init(bio);
+		bio_init(bio, bio->bi_inline_vecs, 1);
 		bio_set_op_attrs(bio, REQ_OP_DISCARD, 0);
 		bio->bi_iter.bi_sector	= bucket_to_sector(ca->set,
 						ca->sb.d[ja->discard_idx]);
 		bio->bi_bdev		= ca->bdev;
-		bio->bi_max_vecs	= 1;
-		bio->bi_io_vec		= bio->bi_inline_vecs;
 		bio->bi_iter.bi_size	= bucket_bytes(ca);
 		bio->bi_end_io		= journal_discard_endio;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/movinggc.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/movinggc.c
--- linux-libre-4.9-gnu/drivers/md/bcache/movinggc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/movinggc.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,15 +77,13 @@ static void moving_init(struct moving_io
 {
 	struct bio *bio = &io->bio.bio;
 
-	bio_init(bio);
+	bio_init(bio, bio->bi_inline_vecs,
+		 DIV_ROUND_UP(KEY_SIZE(&io->w->key), PAGE_SECTORS));
 	bio_get(bio);
 	bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
 
 	bio->bi_iter.bi_size	= KEY_SIZE(&io->w->key) << 9;
-	bio->bi_max_vecs	= DIV_ROUND_UP(KEY_SIZE(&io->w->key),
-					       PAGE_SECTORS);
 	bio->bi_private		= &io->cl;
-	bio->bi_io_vec		= bio->bi_inline_vecs;
 	bch_bio_map(bio, NULL);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/request.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/request.c
--- linux-libre-4.9-gnu/drivers/md/bcache/request.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/request.c	2017-02-12 16:03:20.000000000 -0500
@@ -196,10 +196,8 @@ static void bch_data_insert_start(struct
 	struct data_insert_op *op = container_of(cl, struct data_insert_op, cl);
 	struct bio *bio = op->bio, *n;
 
-	if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0) {
-		set_gc_sectors(op->c);
+	if (atomic_sub_return(bio_sectors(bio), &op->c->sectors_to_gc) < 0)
 		wake_up_gc(op->c);
-	}
 
 	if (op->bypass)
 		return bch_data_invalidate(cl);
@@ -404,8 +402,8 @@ static bool check_should_bypass(struct c
 
 	if (!congested &&
 	    mode == CACHE_MODE_WRITEBACK &&
-	    op_is_write(bio_op(bio)) &&
-	    (bio->bi_opf & REQ_SYNC))
+	    op_is_write(bio->bi_opf) &&
+	    op_is_sync(bio->bi_opf))
 		goto rescale;
 
 	spin_lock(&dc->io_lock);
@@ -623,7 +621,7 @@ static void do_bio_hook(struct search *s
 {
 	struct bio *bio = &s->bio.bio;
 
-	bio_init(bio);
+	bio_init(bio, NULL, 0);
 	__bio_clone_fast(bio, orig_bio);
 	bio->bi_end_io		= request_endio;
 	bio->bi_private		= &s->cl;
@@ -923,7 +921,7 @@ static void cached_dev_write(struct cach
 			flush->bi_bdev	= bio->bi_bdev;
 			flush->bi_end_io = request_endio;
 			flush->bi_private = cl;
-			bio_set_op_attrs(flush, REQ_OP_WRITE, WRITE_FLUSH);
+			flush->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 
 			closure_bio_submit(flush, cl);
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/super.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/super.c
--- linux-libre-4.9-gnu/drivers/md/bcache/super.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/super.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,6 +58,7 @@ static wait_queue_head_t unregister_wait
 struct workqueue_struct *bcache_wq;
 
 #define BTREE_MAX_PAGES		(256 * 1024 / PAGE_SIZE)
+#define BCACHE_MINORS		16 /* partition support */
 
 /* Superblock */
 
@@ -381,7 +382,7 @@ static char *uuid_read(struct cache_set
 		return "bad uuid pointer";
 
 	bkey_copy(&c->uuid_bucket, k);
-	uuid_io(c, REQ_OP_READ, READ_SYNC, k, cl);
+	uuid_io(c, REQ_OP_READ, 0, k, cl);
 
 	if (j->version < BCACHE_JSET_VERSION_UUIDv1) {
 		struct uuid_entry_v0	*u0 = (void *) c->uuids;
@@ -600,7 +601,7 @@ static void prio_read(struct cache *ca,
 			ca->prio_last_buckets[bucket_nr] = bucket;
 			bucket_nr++;
 
-			prio_io(ca, bucket, REQ_OP_READ, READ_SYNC);
+			prio_io(ca, bucket, REQ_OP_READ, 0);
 
 			if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8))
 				pr_warn("bad csum reading priorities");
@@ -783,8 +784,10 @@ static int bcache_device_init(struct bca
 	if (minor < 0)
 		return minor;
 
+	minor *= BCACHE_MINORS;
+
 	if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||
-	    !(d->disk = alloc_disk(1))) {
+	    !(d->disk = alloc_disk(BCACHE_MINORS))) {
 		ida_simple_remove(&bcache_minor, minor);
 		return -ENOMEM;
 	}
@@ -1152,9 +1155,7 @@ static void register_bdev(struct cache_s
 	dc->bdev = bdev;
 	dc->bdev->bd_holder = dc;
 
-	bio_init(&dc->sb_bio);
-	dc->sb_bio.bi_max_vecs	= 1;
-	dc->sb_bio.bi_io_vec	= dc->sb_bio.bi_inline_vecs;
+	bio_init(&dc->sb_bio, dc->sb_bio.bi_inline_vecs, 1);
 	dc->sb_bio.bi_io_vec[0].bv_page = sb_page;
 	get_page(sb_page);
 
@@ -1491,6 +1492,7 @@ struct cache_set *bch_cache_set_alloc(st
 	mutex_init(&c->bucket_lock);
 	init_waitqueue_head(&c->btree_cache_wait);
 	init_waitqueue_head(&c->bucket_wait);
+	init_waitqueue_head(&c->gc_wait);
 	sema_init(&c->uuid_write_mutex, 1);
 
 	spin_lock_init(&c->btree_gc_time.lock);
@@ -1550,6 +1552,7 @@ static void run_cache_set(struct cache_s
 
 	for_each_cache(ca, c, i)
 		c->nbuckets += ca->sb.nbuckets;
+	set_gc_sectors(c);
 
 	if (CACHE_SYNC(&c->sb)) {
 		LIST_HEAD(journal);
@@ -1814,9 +1817,7 @@ static int cache_alloc(struct cache *ca)
 	__module_get(THIS_MODULE);
 	kobject_init(&ca->kobj, &bch_cache_ktype);
 
-	bio_init(&ca->journal.bio);
-	ca->journal.bio.bi_max_vecs = 8;
-	ca->journal.bio.bi_io_vec = ca->journal.bio.bi_inline_vecs;
+	bio_init(&ca->journal.bio, ca->journal.bio.bi_inline_vecs, 8);
 
 	free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
 
@@ -1852,9 +1853,7 @@ static int register_cache(struct cache_s
 	ca->bdev = bdev;
 	ca->bdev->bd_holder = ca;
 
-	bio_init(&ca->sb_bio);
-	ca->sb_bio.bi_max_vecs	= 1;
-	ca->sb_bio.bi_io_vec	= ca->sb_bio.bi_inline_vecs;
+	bio_init(&ca->sb_bio, ca->sb_bio.bi_inline_vecs, 1);
 	ca->sb_bio.bi_io_vec[0].bv_page = sb_page;
 	get_page(sb_page);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/writeback.c linux-libre-4.10-rc8-gnu/drivers/md/bcache/writeback.c
--- linux-libre-4.9-gnu/drivers/md/bcache/writeback.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/writeback.c	2017-02-12 16:03:20.000000000 -0500
@@ -106,14 +106,13 @@ static void dirty_init(struct keybuf_key
 	struct dirty_io *io = w->private;
 	struct bio *bio = &io->bio;
 
-	bio_init(bio);
+	bio_init(bio, bio->bi_inline_vecs,
+		 DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS));
 	if (!io->dc->writeback_percent)
 		bio_set_prio(bio, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0));
 
 	bio->bi_iter.bi_size	= KEY_SIZE(&w->key) << 9;
-	bio->bi_max_vecs	= DIV_ROUND_UP(KEY_SIZE(&w->key), PAGE_SECTORS);
 	bio->bi_private		= w;
-	bio->bi_io_vec		= bio->bi_inline_vecs;
 	bch_bio_map(bio, NULL);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bcache/writeback.h linux-libre-4.10-rc8-gnu/drivers/md/bcache/writeback.h
--- linux-libre-4.9-gnu/drivers/md/bcache/writeback.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bcache/writeback.h	2017-02-12 16:03:20.000000000 -0500
@@ -57,8 +57,7 @@ static inline bool should_writeback(stru
 	if (would_skip)
 		return false;
 
-	return bio->bi_opf & REQ_SYNC ||
-		in_use <= CUTOFF_WRITEBACK;
+	return op_is_sync(bio->bi_opf) || in_use <= CUTOFF_WRITEBACK;
 }
 
 static inline void bch_writeback_queue(struct cached_dev *dc)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/bitmap.c linux-libre-4.10-rc8-gnu/drivers/md/bitmap.c
--- linux-libre-4.9-gnu/drivers/md/bitmap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/bitmap.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/mount.h>
 #include <linux/buffer_head.h>
 #include <linux/seq_file.h>
+#include <trace/events/block.h>
 #include "md.h"
 #include "bitmap.h"
 
@@ -208,11 +209,13 @@ static struct md_rdev *next_active_rdev(
 
 static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait)
 {
-	struct md_rdev *rdev = NULL;
+	struct md_rdev *rdev;
 	struct block_device *bdev;
 	struct mddev *mddev = bitmap->mddev;
 	struct bitmap_storage *store = &bitmap->storage;
 
+restart:
+	rdev = NULL;
 	while ((rdev = next_active_rdev(rdev, mddev)) != NULL) {
 		int size = PAGE_SIZE;
 		loff_t offset = mddev->bitmap_info.offset;
@@ -268,8 +271,8 @@ static int write_sb_page(struct bitmap *
 			       page);
 	}
 
-	if (wait)
-		md_super_wait(mddev);
+	if (wait && md_super_wait(mddev) < 0)
+		goto restart;
 	return 0;
 
  bad_alignment:
@@ -405,10 +408,10 @@ static int read_page(struct file *file,
 		ret = -EIO;
 out:
 	if (ret)
-		printk(KERN_ALERT "md: bitmap read error: (%dB @ %llu): %d\n",
-			(int)PAGE_SIZE,
-			(unsigned long long)index << PAGE_SHIFT,
-			ret);
+		pr_err("md: bitmap read error: (%dB @ %llu): %d\n",
+		       (int)PAGE_SIZE,
+		       (unsigned long long)index << PAGE_SHIFT,
+		       ret);
 	return ret;
 }
 
@@ -416,6 +419,28 @@ out:
  * bitmap file superblock operations
  */
 
+/*
+ * bitmap_wait_writes() should be called before writing any bitmap
+ * blocks, to ensure previous writes, particularly from
+ * bitmap_daemon_work(), have completed.
+ */
+static void bitmap_wait_writes(struct bitmap *bitmap)
+{
+	if (bitmap->storage.file)
+		wait_event(bitmap->write_wait,
+			   atomic_read(&bitmap->pending_writes)==0);
+	else
+		/* Note that we ignore the return value.  The writes
+		 * might have failed, but that would just mean that
+		 * some bits which should be cleared haven't been,
+		 * which is safe.  The relevant bitmap blocks will
+		 * probably get written again, but there is no great
+		 * loss if they aren't.
+		 */
+		md_super_wait(bitmap->mddev);
+}
+
+
 /* update the event counter and sync the superblock to disk */
 void bitmap_update_sb(struct bitmap *bitmap)
 {
@@ -455,24 +480,24 @@ void bitmap_print_sb(struct bitmap *bitm
 	if (!bitmap || !bitmap->storage.sb_page)
 		return;
 	sb = kmap_atomic(bitmap->storage.sb_page);
-	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
-	printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
-	printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
-	printk(KERN_DEBUG "          uuid: %08x.%08x.%08x.%08x\n",
-					*(__u32 *)(sb->uuid+0),
-					*(__u32 *)(sb->uuid+4),
-					*(__u32 *)(sb->uuid+8),
-					*(__u32 *)(sb->uuid+12));
-	printk(KERN_DEBUG "        events: %llu\n",
-			(unsigned long long) le64_to_cpu(sb->events));
-	printk(KERN_DEBUG "events cleared: %llu\n",
-			(unsigned long long) le64_to_cpu(sb->events_cleared));
-	printk(KERN_DEBUG "         state: %08x\n", le32_to_cpu(sb->state));
-	printk(KERN_DEBUG "     chunksize: %d B\n", le32_to_cpu(sb->chunksize));
-	printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
-	printk(KERN_DEBUG "     sync size: %llu KB\n",
-			(unsigned long long)le64_to_cpu(sb->sync_size)/2);
-	printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind));
+	pr_debug("%s: bitmap file superblock:\n", bmname(bitmap));
+	pr_debug("         magic: %08x\n", le32_to_cpu(sb->magic));
+	pr_debug("       version: %d\n", le32_to_cpu(sb->version));
+	pr_debug("          uuid: %08x.%08x.%08x.%08x\n",
+		 *(__u32 *)(sb->uuid+0),
+		 *(__u32 *)(sb->uuid+4),
+		 *(__u32 *)(sb->uuid+8),
+		 *(__u32 *)(sb->uuid+12));
+	pr_debug("        events: %llu\n",
+		 (unsigned long long) le64_to_cpu(sb->events));
+	pr_debug("events cleared: %llu\n",
+		 (unsigned long long) le64_to_cpu(sb->events_cleared));
+	pr_debug("         state: %08x\n", le32_to_cpu(sb->state));
+	pr_debug("     chunksize: %d B\n", le32_to_cpu(sb->chunksize));
+	pr_debug("  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+	pr_debug("     sync size: %llu KB\n",
+		 (unsigned long long)le64_to_cpu(sb->sync_size)/2);
+	pr_debug("max write behind: %d\n", le32_to_cpu(sb->write_behind));
 	kunmap_atomic(sb);
 }
 
@@ -506,14 +531,14 @@ static int bitmap_new_disk_sb(struct bit
 	BUG_ON(!chunksize);
 	if (!is_power_of_2(chunksize)) {
 		kunmap_atomic(sb);
-		printk(KERN_ERR "bitmap chunksize not a power of 2\n");
+		pr_warn("bitmap chunksize not a power of 2\n");
 		return -EINVAL;
 	}
 	sb->chunksize = cpu_to_le32(chunksize);
 
 	daemon_sleep = bitmap->mddev->bitmap_info.daemon_sleep;
 	if (!daemon_sleep || (daemon_sleep > MAX_SCHEDULE_TIMEOUT)) {
-		printk(KERN_INFO "Choosing daemon_sleep default (5 sec)\n");
+		pr_debug("Choosing daemon_sleep default (5 sec)\n");
 		daemon_sleep = 5 * HZ;
 	}
 	sb->daemon_sleep = cpu_to_le32(daemon_sleep);
@@ -584,7 +609,7 @@ re_read:
 		/* to 4k blocks */
 		bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096);
 		offset = bitmap->mddev->bitmap_info.offset + (bitmap->cluster_slot * (bm_blocks << 3));
-		pr_info("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__,
+		pr_debug("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__,
 			bitmap->cluster_slot, offset);
 	}
 
@@ -634,7 +659,7 @@ re_read:
 	else if (write_behind > COUNTER_MAX)
 		reason = "write-behind limit out of range (0 - 16383)";
 	if (reason) {
-		printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
+		pr_warn("%s: invalid bitmap file superblock: %s\n",
 			bmname(bitmap), reason);
 		goto out;
 	}
@@ -648,18 +673,15 @@ re_read:
 		 * bitmap's UUID and event counter to the mddev's
 		 */
 		if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) {
-			printk(KERN_INFO
-			       "%s: bitmap superblock UUID mismatch\n",
-			       bmname(bitmap));
+			pr_warn("%s: bitmap superblock UUID mismatch\n",
+				bmname(bitmap));
 			goto out;
 		}
 		events = le64_to_cpu(sb->events);
 		if (!nodes && (events < bitmap->mddev->events)) {
-			printk(KERN_INFO
-			       "%s: bitmap file is out of date (%llu < %llu) "
-			       "-- forcing full recovery\n",
-			       bmname(bitmap), events,
-			       (unsigned long long) bitmap->mddev->events);
+			pr_warn("%s: bitmap file is out of date (%llu < %llu) -- forcing full recovery\n",
+				bmname(bitmap), events,
+				(unsigned long long) bitmap->mddev->events);
 			set_bit(BITMAP_STALE, &bitmap->flags);
 		}
 	}
@@ -679,8 +701,8 @@ out:
 	if (err == 0 && nodes && (bitmap->cluster_slot < 0)) {
 		err = md_setup_cluster(bitmap->mddev, nodes);
 		if (err) {
-			pr_err("%s: Could not setup cluster service (%d)\n",
-					bmname(bitmap), err);
+			pr_warn("%s: Could not setup cluster service (%d)\n",
+				bmname(bitmap), err);
 			goto out_no_sb;
 		}
 		bitmap->cluster_slot = md_cluster_ops->slot_number(bitmap->mddev);
@@ -847,15 +869,13 @@ static void bitmap_file_kick(struct bitm
 				ptr = file_path(bitmap->storage.file,
 					     path, PAGE_SIZE);
 
-			printk(KERN_ALERT
-			      "%s: kicking failed bitmap file %s from array!\n",
-			      bmname(bitmap), IS_ERR(ptr) ? "" : ptr);
+			pr_warn("%s: kicking failed bitmap file %s from array!\n",
+				bmname(bitmap), IS_ERR(ptr) ? "" : ptr);
 
 			kfree(path);
 		} else
-			printk(KERN_ALERT
-			       "%s: disabling internal bitmap due to errors\n",
-			       bmname(bitmap));
+			pr_warn("%s: disabling internal bitmap due to errors\n",
+				bmname(bitmap));
 	}
 }
 
@@ -983,6 +1003,7 @@ void bitmap_unplug(struct bitmap *bitmap
 {
 	unsigned long i;
 	int dirty, need_write;
+	int writing = 0;
 
 	if (!bitmap || !bitmap->storage.filemap ||
 	    test_bit(BITMAP_STALE, &bitmap->flags))
@@ -997,15 +1018,19 @@ void bitmap_unplug(struct bitmap *bitmap
 		need_write = test_and_clear_page_attr(bitmap, i,
 						      BITMAP_PAGE_NEEDWRITE);
 		if (dirty || need_write) {
+			if (!writing) {
+				bitmap_wait_writes(bitmap);
+				if (bitmap->mddev->queue)
+					blk_add_trace_msg(bitmap->mddev->queue,
+							  "md bitmap_unplug");
+			}
 			clear_page_attr(bitmap, i, BITMAP_PAGE_PENDING);
 			write_page(bitmap, bitmap->storage.filemap[i], 0);
+			writing = 1;
 		}
 	}
-	if (bitmap->storage.file)
-		wait_event(bitmap->write_wait,
-			   atomic_read(&bitmap->pending_writes)==0);
-	else
-		md_super_wait(bitmap->mddev);
+	if (writing)
+		bitmap_wait_writes(bitmap);
 
 	if (test_bit(BITMAP_WRITE_ERROR, &bitmap->flags))
 		bitmap_file_kick(bitmap);
@@ -1056,14 +1081,13 @@ static int bitmap_init_from_disk(struct
 
 	outofdate = test_bit(BITMAP_STALE, &bitmap->flags);
 	if (outofdate)
-		printk(KERN_INFO "%s: bitmap file is out of date, doing full "
-			"recovery\n", bmname(bitmap));
+		pr_warn("%s: bitmap file is out of date, doing full recovery\n", bmname(bitmap));
 
 	if (file && i_size_read(file->f_mapping->host) < store->bytes) {
-		printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
-		       bmname(bitmap),
-		       (unsigned long) i_size_read(file->f_mapping->host),
-		       store->bytes);
+		pr_warn("%s: bitmap file too short %lu < %lu\n",
+			bmname(bitmap),
+			(unsigned long) i_size_read(file->f_mapping->host),
+			store->bytes);
 		goto err;
 	}
 
@@ -1137,16 +1161,15 @@ static int bitmap_init_from_disk(struct
 		offset = 0;
 	}
 
-	printk(KERN_INFO "%s: bitmap initialized from disk: "
-	       "read %lu pages, set %lu of %lu bits\n",
-	       bmname(bitmap), store->file_pages,
-	       bit_cnt, chunks);
+	pr_debug("%s: bitmap initialized from disk: read %lu pages, set %lu of %lu bits\n",
+		 bmname(bitmap), store->file_pages,
+		 bit_cnt, chunks);
 
 	return 0;
 
  err:
-	printk(KERN_INFO "%s: bitmap initialisation failed: %d\n",
-	       bmname(bitmap), ret);
+	pr_warn("%s: bitmap initialisation failed: %d\n",
+		bmname(bitmap), ret);
 	return ret;
 }
 
@@ -1225,6 +1248,10 @@ void bitmap_daemon_work(struct mddev *md
 	}
 	bitmap->allclean = 1;
 
+	if (bitmap->mddev->queue)
+		blk_add_trace_msg(bitmap->mddev->queue,
+				  "md bitmap_daemon_work");
+
 	/* Any file-page which is PENDING now needs to be written.
 	 * So set NEEDWRITE now, then after we make any last-minute changes
 	 * we will write it.
@@ -1289,6 +1316,7 @@ void bitmap_daemon_work(struct mddev *md
 	}
 	spin_unlock_irq(&counts->lock);
 
+	bitmap_wait_writes(bitmap);
 	/* Now start writeout on any page in NEEDWRITE that isn't DIRTY.
 	 * DIRTY pages need to be written by bitmap_unplug so it can wait
 	 * for them.
@@ -1595,7 +1623,7 @@ void bitmap_cond_end_sync(struct bitmap
 		   atomic_read(&bitmap->mddev->recovery_active) == 0);
 
 	bitmap->mddev->curr_resync_completed = sector;
-	set_bit(MD_CHANGE_CLEAN, &bitmap->mddev->flags);
+	set_bit(MD_SB_CHANGE_CLEAN, &bitmap->mddev->sb_flags);
 	sector &= ~((1ULL << bitmap->counts.chunkshift) - 1);
 	s = 0;
 	while (s < sector && s < bitmap->mddev->resync_max_sectors) {
@@ -1825,8 +1853,8 @@ struct bitmap *bitmap_create(struct mdde
 	if (err)
 		goto error;
 
-	printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
-	       bitmap->counts.pages, bmname(bitmap));
+	pr_debug("created bitmap (%lu pages) for device %s\n",
+		 bitmap->counts.pages, bmname(bitmap));
 
 	err = test_bit(BITMAP_WRITE_ERROR, &bitmap->flags) ? -EIO : 0;
 	if (err)
@@ -2029,8 +2057,10 @@ int bitmap_resize(struct bitmap *bitmap,
 					   !bitmap->mddev->bitmap_info.external,
 					   mddev_is_clustered(bitmap->mddev)
 					   ? bitmap->cluster_slot : 0);
-	if (ret)
+	if (ret) {
+		bitmap_file_unmap(&store);
 		goto err;
+	}
 
 	pages = DIV_ROUND_UP(chunks, PAGE_COUNTER_RATIO);
 
@@ -2089,7 +2119,7 @@ int bitmap_resize(struct bitmap *bitmap,
 				bitmap->mddev->bitmap_info.chunksize = 1 << (old_counts.chunkshift +
 									     BITMAP_BLOCK_SHIFT);
 				blocks = old_counts.chunks << old_counts.chunkshift;
-				pr_err("Could not pre-allocate in-memory bitmap for cluster raid\n");
+				pr_warn("Could not pre-allocate in-memory bitmap for cluster raid\n");
 				break;
 			} else
 				bitmap->counts.bp[page].count += 1;
@@ -2266,7 +2296,7 @@ location_store(struct mddev *mddev, cons
 		/* Ensure new bitmap info is stored in
 		 * metadata promptly.
 		 */
-		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		md_wakeup_thread(mddev->thread);
 	}
 	rv = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-bufio.c linux-libre-4.10-rc8-gnu/drivers/md/dm-bufio.c
--- linux-libre-4.9-gnu/drivers/md/dm-bufio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-bufio.c	2017-02-12 16:03:20.000000000 -0500
@@ -611,9 +611,7 @@ static void use_inline_bio(struct dm_buf
 	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;
+	bio_init(&b->bio, b->bio_vec, DM_BUFIO_INLINE_VECS);
 	b->bio.bi_iter.bi_sector = block << b->c->sectors_per_block_bits;
 	b->bio.bi_bdev = b->c->bdev;
 	b->bio.bi_end_io = inline_endio;
@@ -822,12 +820,14 @@ enum new_flag {
 static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c, enum new_flag nf)
 {
 	struct dm_buffer *b;
+	bool tried_noio_alloc = false;
 
 	/*
 	 * 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_NOWAIT: don't wait; if we need to sleep we'll release our
+	 *		    mutex and wait ourselves.
 	 *	__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
@@ -837,7 +837,7 @@ static struct dm_buffer *__alloc_buffer_
 	 */
 	while (1) {
 		if (dm_bufio_cache_size_latch != 1) {
-			b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+			b = alloc_buffer(c, GFP_NOWAIT | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
 			if (b)
 				return b;
 		}
@@ -845,6 +845,15 @@ static struct dm_buffer *__alloc_buffer_
 		if (nf == NF_PREFETCH)
 			return NULL;
 
+		if (dm_bufio_cache_size_latch != 1 && !tried_noio_alloc) {
+			dm_bufio_unlock(c);
+			b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+			dm_bufio_lock(c);
+			if (b)
+				return b;
+			tried_noio_alloc = true;
+		}
+
 		if (!list_empty(&c->reserved_buffers)) {
 			b = list_entry(c->reserved_buffers.next,
 				       struct dm_buffer, lru_list);
@@ -1316,7 +1325,7 @@ int dm_bufio_issue_flush(struct dm_bufio
 {
 	struct dm_io_request io_req = {
 		.bi_op = REQ_OP_WRITE,
-		.bi_op_flags = WRITE_FLUSH,
+		.bi_op_flags = REQ_PREFLUSH,
 		.mem.type = DM_IO_KMEM,
 		.mem.ptr.addr = NULL,
 		.client = c->dm_io,
@@ -1587,18 +1596,9 @@ dm_bufio_shrink_scan(struct shrinker *sh
 static unsigned long
 dm_bufio_shrink_count(struct shrinker *shrink, struct shrink_control *sc)
 {
-	struct dm_bufio_client *c;
-	unsigned long count;
-
-	c = container_of(shrink, struct dm_bufio_client, shrinker);
-	if (sc->gfp_mask & __GFP_FS)
-		dm_bufio_lock(c);
-	else if (!dm_bufio_trylock(c))
-		return 0;
+	struct dm_bufio_client *c = container_of(shrink, struct dm_bufio_client, shrinker);
 
-	count = c->n_buffers[LIST_CLEAN] + c->n_buffers[LIST_DIRTY];
-	dm_bufio_unlock(c);
-	return count;
+	return ACCESS_ONCE(c->n_buffers[LIST_CLEAN]) + ACCESS_ONCE(c->n_buffers[LIST_DIRTY]);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm.c linux-libre-4.10-rc8-gnu/drivers/md/dm.c
--- linux-libre-4.9-gnu/drivers/md/dm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm.c	2017-02-12 16:03:20.000000000 -0500
@@ -1525,9 +1525,9 @@ static struct mapped_device *alloc_dev(i
 	if (!md->bdev)
 		goto bad;
 
-	bio_init(&md->flush_bio);
+	bio_init(&md->flush_bio, NULL, 0);
 	md->flush_bio.bi_bdev = md->bdev;
-	bio_set_op_attrs(&md->flush_bio, REQ_OP_WRITE, WRITE_FLUSH);
+	md->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 
 	dm_stats_init(&md->stats);
 
@@ -1886,9 +1886,7 @@ static void __dm_destroy(struct mapped_d
 	set_bit(DMF_FREEING, &md->flags);
 	spin_unlock(&_minor_lock);
 
-	spin_lock_irq(q->queue_lock);
-	queue_flag_set(QUEUE_FLAG_DYING, q);
-	spin_unlock_irq(q->queue_lock);
+	blk_set_queue_dying(q);
 
 	if (dm_request_based(md) && md->kworker_task)
 		kthread_flush_worker(&md->kworker);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-cache-block-types.h linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-block-types.h
--- linux-libre-4.9-gnu/drivers/md/dm-cache-block-types.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-block-types.h	2017-02-12 16:03:20.000000000 -0500
@@ -17,9 +17,9 @@
  * discard bitset.
  */
 
-typedef dm_block_t __bitwise__ dm_oblock_t;
-typedef uint32_t __bitwise__ dm_cblock_t;
-typedef dm_block_t __bitwise__ dm_dblock_t;
+typedef dm_block_t __bitwise dm_oblock_t;
+typedef uint32_t __bitwise dm_cblock_t;
+typedef dm_block_t __bitwise dm_dblock_t;
 
 static inline dm_oblock_t to_oblock(dm_block_t b)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-cache-metadata.c linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-metadata.c
--- linux-libre-4.9-gnu/drivers/md/dm-cache-metadata.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-metadata.c	2017-02-12 16:03:20.000000000 -0500
@@ -383,7 +383,6 @@ static int __format_metadata(struct dm_c
 		goto bad;
 
 	dm_disk_bitset_init(cmd->tm, &cmd->discard_info);
-
 	r = dm_bitset_empty(&cmd->discard_info, &cmd->discard_root);
 	if (r < 0)
 		goto bad;
@@ -789,7 +788,7 @@ static struct dm_cache_metadata *lookup_
 static bool same_params(struct dm_cache_metadata *cmd, sector_t data_block_size)
 {
 	if (cmd->data_block_size != data_block_size) {
-		DMERR("data_block_size (%llu) different from that in metadata (%llu)\n",
+		DMERR("data_block_size (%llu) different from that in metadata (%llu)",
 		      (unsigned long long) data_block_size,
 		      (unsigned long long) cmd->data_block_size);
 		return false;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-cache-policy-smq.c linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-policy-smq.c
--- linux-libre-4.9-gnu/drivers/md/dm-cache-policy-smq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-policy-smq.c	2017-02-12 16:03:20.000000000 -0500
@@ -1361,7 +1361,7 @@ static void smq_clear_dirty(struct dm_ca
 
 static unsigned random_level(dm_cblock_t cblock)
 {
-	return hash_32_generic(from_cblock(cblock), 9) & (NR_CACHE_LEVELS - 1);
+	return hash_32(from_cblock(cblock), 9) & (NR_CACHE_LEVELS - 1);
 }
 
 static int smq_load_mapping(struct dm_cache_policy *p,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-cache-target.c linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-target.c
--- linux-libre-4.9-gnu/drivers/md/dm-cache-target.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-cache-target.c	2017-02-12 16:03:20.000000000 -0500
@@ -989,7 +989,8 @@ static void set_cache_mode(struct cache
 	enum cache_metadata_mode old_mode = get_cache_mode(cache);
 
 	if (dm_cache_metadata_needs_check(cache->cmd, &needs_check)) {
-		DMERR("unable to read needs_check flag, setting failure mode");
+		DMERR("%s: unable to read needs_check flag, setting failure mode.",
+		      cache_device_name(cache));
 		new_mode = CM_FAIL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-crypt.c linux-libre-4.10-rc8-gnu/drivers/md/dm-crypt.c
--- linux-libre-4.9-gnu/drivers/md/dm-crypt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-crypt.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/key.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
 #include <linux/mempool.h>
@@ -23,12 +24,14 @@
 #include <linux/atomic.h>
 #include <linux/scatterlist.h>
 #include <linux/rbtree.h>
+#include <linux/ctype.h>
 #include <asm/page.h>
 #include <asm/unaligned.h>
 #include <crypto/hash.h>
 #include <crypto/md5.h>
 #include <crypto/algapi.h>
 #include <crypto/skcipher.h>
+#include <keys/user-type.h>
 
 #include <linux/device-mapper.h>
 
@@ -140,8 +143,9 @@ struct crypt_config {
 
 	char *cipher;
 	char *cipher_string;
+	char *key_string;
 
-	struct crypt_iv_operations *iv_gen_ops;
+	const struct crypt_iv_operations *iv_gen_ops;
 	union {
 		struct iv_essiv_private essiv;
 		struct iv_benbi_private benbi;
@@ -758,15 +762,15 @@ static int crypt_iv_tcw_post(struct cryp
 	return r;
 }
 
-static struct crypt_iv_operations crypt_iv_plain_ops = {
+static const struct crypt_iv_operations crypt_iv_plain_ops = {
 	.generator = crypt_iv_plain_gen
 };
 
-static struct crypt_iv_operations crypt_iv_plain64_ops = {
+static const struct crypt_iv_operations crypt_iv_plain64_ops = {
 	.generator = crypt_iv_plain64_gen
 };
 
-static struct crypt_iv_operations crypt_iv_essiv_ops = {
+static const struct crypt_iv_operations crypt_iv_essiv_ops = {
 	.ctr       = crypt_iv_essiv_ctr,
 	.dtr       = crypt_iv_essiv_dtr,
 	.init      = crypt_iv_essiv_init,
@@ -774,17 +778,17 @@ static struct crypt_iv_operations crypt_
 	.generator = crypt_iv_essiv_gen
 };
 
-static struct crypt_iv_operations crypt_iv_benbi_ops = {
+static const struct crypt_iv_operations crypt_iv_benbi_ops = {
 	.ctr	   = crypt_iv_benbi_ctr,
 	.dtr	   = crypt_iv_benbi_dtr,
 	.generator = crypt_iv_benbi_gen
 };
 
-static struct crypt_iv_operations crypt_iv_null_ops = {
+static const struct crypt_iv_operations crypt_iv_null_ops = {
 	.generator = crypt_iv_null_gen
 };
 
-static struct crypt_iv_operations crypt_iv_lmk_ops = {
+static const struct crypt_iv_operations crypt_iv_lmk_ops = {
 	.ctr	   = crypt_iv_lmk_ctr,
 	.dtr	   = crypt_iv_lmk_dtr,
 	.init	   = crypt_iv_lmk_init,
@@ -793,7 +797,7 @@ static struct crypt_iv_operations crypt_
 	.post	   = crypt_iv_lmk_post
 };
 
-static struct crypt_iv_operations crypt_iv_tcw_ops = {
+static const struct crypt_iv_operations crypt_iv_tcw_ops = {
 	.ctr	   = crypt_iv_tcw_ctr,
 	.dtr	   = crypt_iv_tcw_dtr,
 	.init	   = crypt_iv_tcw_init,
@@ -994,7 +998,6 @@ static struct bio *crypt_alloc_buffer(st
 	gfp_t gfp_mask = GFP_NOWAIT | __GFP_HIGHMEM;
 	unsigned i, len, remaining_size;
 	struct page *page;
-	struct bio_vec *bvec;
 
 retry:
 	if (unlikely(gfp_mask & __GFP_DIRECT_RECLAIM))
@@ -1019,12 +1022,7 @@ retry:
 
 		len = (remaining_size > PAGE_SIZE) ? PAGE_SIZE : remaining_size;
 
-		bvec = &clone->bi_io_vec[clone->bi_vcnt++];
-		bvec->bv_page = page;
-		bvec->bv_len = len;
-		bvec->bv_offset = 0;
-
-		clone->bi_iter.bi_size += len;
+		bio_add_page(clone, page, len, 0);
 
 		remaining_size -= len;
 	}
@@ -1135,7 +1133,7 @@ static void clone_init(struct dm_crypt_i
 	clone->bi_private = io;
 	clone->bi_end_io  = crypt_endio;
 	clone->bi_bdev    = cc->dev->bdev;
-	bio_set_op_attrs(clone, bio_op(io->base_bio), bio_flags(io->base_bio));
+	clone->bi_opf	  = io->base_bio->bi_opf;
 }
 
 static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
@@ -1471,7 +1469,7 @@ static int crypt_alloc_tfms(struct crypt
 	return 0;
 }
 
-static int crypt_setkey_allcpus(struct crypt_config *cc)
+static int crypt_setkey(struct crypt_config *cc)
 {
 	unsigned subkey_size;
 	int err = 0, i, r;
@@ -1490,25 +1488,157 @@ static int crypt_setkey_allcpus(struct c
 	return err;
 }
 
+#ifdef CONFIG_KEYS
+
+static bool contains_whitespace(const char *str)
+{
+	while (*str)
+		if (isspace(*str++))
+			return true;
+	return false;
+}
+
+static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string)
+{
+	char *new_key_string, *key_desc;
+	int ret;
+	struct key *key;
+	const struct user_key_payload *ukp;
+
+	/*
+	 * Reject key_string with whitespace. dm core currently lacks code for
+	 * proper whitespace escaping in arguments on DM_TABLE_STATUS path.
+	 */
+	if (contains_whitespace(key_string)) {
+		DMERR("whitespace chars not allowed in key string");
+		return -EINVAL;
+	}
+
+	/* look for next ':' separating key_type from key_description */
+	key_desc = strpbrk(key_string, ":");
+	if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
+		return -EINVAL;
+
+	if (strncmp(key_string, "logon:", key_desc - key_string + 1) &&
+	    strncmp(key_string, "user:", key_desc - key_string + 1))
+		return -EINVAL;
+
+	new_key_string = kstrdup(key_string, GFP_KERNEL);
+	if (!new_key_string)
+		return -ENOMEM;
+
+	key = request_key(key_string[0] == 'l' ? &key_type_logon : &key_type_user,
+			  key_desc + 1, NULL);
+	if (IS_ERR(key)) {
+		kzfree(new_key_string);
+		return PTR_ERR(key);
+	}
+
+	down_read(&key->sem);
+
+	ukp = user_key_payload(key);
+	if (!ukp) {
+		up_read(&key->sem);
+		key_put(key);
+		kzfree(new_key_string);
+		return -EKEYREVOKED;
+	}
+
+	if (cc->key_size != ukp->datalen) {
+		up_read(&key->sem);
+		key_put(key);
+		kzfree(new_key_string);
+		return -EINVAL;
+	}
+
+	memcpy(cc->key, ukp->data, cc->key_size);
+
+	up_read(&key->sem);
+	key_put(key);
+
+	/* clear the flag since following operations may invalidate previously valid key */
+	clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
+
+	ret = crypt_setkey(cc);
+
+	/* wipe the kernel key payload copy in each case */
+	memset(cc->key, 0, cc->key_size * sizeof(u8));
+
+	if (!ret) {
+		set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
+		kzfree(cc->key_string);
+		cc->key_string = new_key_string;
+	} else
+		kzfree(new_key_string);
+
+	return ret;
+}
+
+static int get_key_size(char **key_string)
+{
+	char *colon, dummy;
+	int ret;
+
+	if (*key_string[0] != ':')
+		return strlen(*key_string) >> 1;
+
+	/* look for next ':' in key string */
+	colon = strpbrk(*key_string + 1, ":");
+	if (!colon)
+		return -EINVAL;
+
+	if (sscanf(*key_string + 1, "%u%c", &ret, &dummy) != 2 || dummy != ':')
+		return -EINVAL;
+
+	*key_string = colon;
+
+	/* remaining key string should be :<logon|user>:<key_desc> */
+
+	return ret;
+}
+
+#else
+
+static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string)
+{
+	return -EINVAL;
+}
+
+static int get_key_size(char **key_string)
+{
+	return (*key_string[0] == ':') ? -EINVAL : strlen(*key_string) >> 1;
+}
+
+#endif
+
 static int crypt_set_key(struct crypt_config *cc, char *key)
 {
 	int r = -EINVAL;
 	int key_string_len = strlen(key);
 
-	/* The key size may not be changed. */
-	if (cc->key_size != (key_string_len >> 1))
-		goto out;
-
 	/* Hyphen (which gives a key_size of zero) means there is no key. */
 	if (!cc->key_size && strcmp(key, "-"))
 		goto out;
 
-	if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
+	/* ':' means the key is in kernel keyring, short-circuit normal key processing */
+	if (key[0] == ':') {
+		r = crypt_set_keyring_key(cc, key + 1);
 		goto out;
+	}
 
-	set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
+	/* clear the flag since following operations may invalidate previously valid key */
+	clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
-	r = crypt_setkey_allcpus(cc);
+	/* wipe references to any kernel keyring key */
+	kzfree(cc->key_string);
+	cc->key_string = NULL;
+
+	if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
+		goto out;
+
+	r = crypt_setkey(cc);
+	if (!r)
+		set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
 out:
 	/* Hex key string not needed after here, so wipe it. */
@@ -1521,8 +1651,10 @@ static int crypt_wipe_key(struct crypt_c
 {
 	clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 	memset(&cc->key, 0, cc->key_size * sizeof(u8));
+	kzfree(cc->key_string);
+	cc->key_string = NULL;
 
-	return crypt_setkey_allcpus(cc);
+	return crypt_setkey(cc);
 }
 
 static void crypt_dtr(struct dm_target *ti)
@@ -1558,6 +1690,7 @@ static void crypt_dtr(struct dm_target *
 
 	kzfree(cc->cipher);
 	kzfree(cc->cipher_string);
+	kzfree(cc->key_string);
 
 	/* Must zero key material before freeing */
 	kzfree(cc);
@@ -1726,12 +1859,13 @@ bad_mem:
 
 /*
  * Construct an encryption mapping:
- * <cipher> <key> <iv_offset> <dev_path> <start>
+ * <cipher> [<key>|:<key_size>:<user|logon>:<key_description>] <iv_offset> <dev_path> <start>
  */
 static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
 	struct crypt_config *cc;
-	unsigned int key_size, opt_params;
+	int key_size;
+	unsigned int opt_params;
 	unsigned long long tmpll;
 	int ret;
 	size_t iv_size_padding;
@@ -1748,7 +1882,11 @@ static int crypt_ctr(struct dm_target *t
 		return -EINVAL;
 	}
 
-	key_size = strlen(argv[1]) >> 1;
+	key_size = get_key_size(&argv[1]);
+	if (key_size < 0) {
+		ti->error = "Cannot parse key size";
+		return -EINVAL;
+	}
 
 	cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
 	if (!cc) {
@@ -1955,10 +2093,13 @@ static void crypt_status(struct dm_targe
 	case STATUSTYPE_TABLE:
 		DMEMIT("%s ", cc->cipher_string);
 
-		if (cc->key_size > 0)
-			for (i = 0; i < cc->key_size; i++)
-				DMEMIT("%02x", cc->key[i]);
-		else
+		if (cc->key_size > 0) {
+			if (cc->key_string)
+				DMEMIT(":%u:%s", cc->key_size, cc->key_string);
+			else
+				for (i = 0; i < cc->key_size; i++)
+					DMEMIT("%02x", cc->key[i]);
+		} else
 			DMEMIT("-");
 
 		DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
@@ -2014,7 +2155,7 @@ static void crypt_resume(struct dm_targe
 static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
 {
 	struct crypt_config *cc = ti->private;
-	int ret = -EINVAL;
+	int key_size, ret = -EINVAL;
 
 	if (argc < 2)
 		goto error;
@@ -2025,6 +2166,13 @@ static int crypt_message(struct dm_targe
 			return -EINVAL;
 		}
 		if (argc == 3 && !strcasecmp(argv[1], "set")) {
+			/* The key size may not be changed. */
+			key_size = get_key_size(&argv[2]);
+			if (key_size < 0 || cc->key_size != key_size) {
+				memset(argv[2], '0', strlen(argv[2]));
+				return -EINVAL;
+			}
+
 			ret = crypt_set_key(cc, argv[2]);
 			if (ret)
 				return ret;
@@ -2068,7 +2216,7 @@ static void crypt_io_hints(struct dm_tar
 
 static struct target_type crypt_target = {
 	.name   = "crypt",
-	.version = {1, 14, 1},
+	.version = {1, 15, 0},
 	.module = THIS_MODULE,
 	.ctr    = crypt_ctr,
 	.dtr    = crypt_dtr,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-flakey.c linux-libre-4.10-rc8-gnu/drivers/md/dm-flakey.c
--- linux-libre-4.9-gnu/drivers/md/dm-flakey.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-flakey.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,8 @@ struct flakey_c {
 };
 
 enum feature_flag_bits {
-	DROP_WRITES
+	DROP_WRITES,
+	ERROR_WRITES
 };
 
 struct per_bio_data {
@@ -76,6 +77,25 @@ static int parse_features(struct dm_arg_
 			if (test_and_set_bit(DROP_WRITES, &fc->flags)) {
 				ti->error = "Feature drop_writes duplicated";
 				return -EINVAL;
+			} else if (test_bit(ERROR_WRITES, &fc->flags)) {
+				ti->error = "Feature drop_writes conflicts with feature error_writes";
+				return -EINVAL;
+			}
+
+			continue;
+		}
+
+		/*
+		 * error_writes
+		 */
+		if (!strcasecmp(arg_name, "error_writes")) {
+			if (test_and_set_bit(ERROR_WRITES, &fc->flags)) {
+				ti->error = "Feature error_writes duplicated";
+				return -EINVAL;
+
+			} else if (test_bit(DROP_WRITES, &fc->flags)) {
+				ti->error = "Feature error_writes conflicts with feature drop_writes";
+				return -EINVAL;
 			}
 
 			continue;
@@ -135,6 +155,10 @@ static int parse_features(struct dm_arg_
 	if (test_bit(DROP_WRITES, &fc->flags) && (fc->corrupt_bio_rw == WRITE)) {
 		ti->error = "drop_writes is incompatible with corrupt_bio_byte with the WRITE flag set";
 		return -EINVAL;
+
+	} else if (test_bit(ERROR_WRITES, &fc->flags) && (fc->corrupt_bio_rw == WRITE)) {
+		ti->error = "error_writes is incompatible with corrupt_bio_byte with the WRITE flag set";
+		return -EINVAL;
 	}
 
 	return 0;
@@ -200,11 +224,13 @@ static int flakey_ctr(struct dm_target *
 
 	if (!(fc->up_interval + fc->down_interval)) {
 		ti->error = "Total (up + down) interval is zero";
+		r = -EINVAL;
 		goto bad;
 	}
 
 	if (fc->up_interval + fc->down_interval < fc->up_interval) {
 		ti->error = "Interval overflow";
+		r = -EINVAL;
 		goto bad;
 	}
 
@@ -289,22 +315,27 @@ static int flakey_map(struct dm_target *
 		pb->bio_submitted = true;
 
 		/*
-		 * Error reads if neither corrupt_bio_byte or drop_writes are set.
+		 * Error reads if neither corrupt_bio_byte or drop_writes or error_writes are set.
 		 * Otherwise, flakey_end_io() will decide if the reads should be modified.
 		 */
 		if (bio_data_dir(bio) == READ) {
-			if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags))
+			if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags) &&
+			    !test_bit(ERROR_WRITES, &fc->flags))
 				return -EIO;
 			goto map_bio;
 		}
 
 		/*
-		 * Drop writes?
+		 * Drop or error writes?
 		 */
 		if (test_bit(DROP_WRITES, &fc->flags)) {
 			bio_endio(bio);
 			return DM_MAPIO_SUBMITTED;
 		}
+		else if (test_bit(ERROR_WRITES, &fc->flags)) {
+			bio_io_error(bio);
+			return DM_MAPIO_SUBMITTED;
+		}
 
 		/*
 		 * Corrupt matching writes.
@@ -340,10 +371,11 @@ static int flakey_end_io(struct dm_targe
 			 */
 			corrupt_bio_data(bio, fc);
 
-		} else if (!test_bit(DROP_WRITES, &fc->flags)) {
+		} else if (!test_bit(DROP_WRITES, &fc->flags) &&
+			   !test_bit(ERROR_WRITES, &fc->flags)) {
 			/*
 			 * Error read during the down_interval if drop_writes
-			 * wasn't configured.
+			 * and error_writes were not configured.
 			 */
 			return -EIO;
 		}
@@ -357,7 +389,7 @@ static void flakey_status(struct dm_targ
 {
 	unsigned sz = 0;
 	struct flakey_c *fc = ti->private;
-	unsigned drop_writes;
+	unsigned drop_writes, error_writes;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -370,10 +402,13 @@ static void flakey_status(struct dm_targ
 		       fc->down_interval);
 
 		drop_writes = test_bit(DROP_WRITES, &fc->flags);
-		DMEMIT("%u ", drop_writes + (fc->corrupt_bio_byte > 0) * 5);
+		error_writes = test_bit(ERROR_WRITES, &fc->flags);
+		DMEMIT("%u ", drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5);
 
 		if (drop_writes)
 			DMEMIT("drop_writes ");
+		else if (error_writes)
+			DMEMIT("error_writes ");
 
 		if (fc->corrupt_bio_byte)
 			DMEMIT("corrupt_bio_byte %u %c %u %u ",
@@ -410,7 +445,7 @@ static int flakey_iterate_devices(struct
 
 static struct target_type flakey_target = {
 	.name   = "flakey",
-	.version = {1, 3, 1},
+	.version = {1, 4, 0},
 	.module = THIS_MODULE,
 	.ctr    = flakey_ctr,
 	.dtr    = flakey_dtr,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-io.c linux-libre-4.10-rc8-gnu/drivers/md/dm-io.c
--- linux-libre-4.9-gnu/drivers/md/dm-io.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-io.c	2017-02-12 16:03:20.000000000 -0500
@@ -162,7 +162,10 @@ struct dpages {
 			 struct page **p, unsigned long *len, unsigned *offset);
 	void (*next_page)(struct dpages *dp);
 
-	unsigned context_u;
+	union {
+		unsigned context_u;
+		struct bvec_iter context_bi;
+	};
 	void *context_ptr;
 
 	void *vma_invalidate_address;
@@ -204,25 +207,36 @@ static void list_dp_init(struct dpages *
 static void bio_get_page(struct dpages *dp, struct page **p,
 			 unsigned long *len, unsigned *offset)
 {
-	struct bio_vec *bvec = dp->context_ptr;
-	*p = bvec->bv_page;
-	*len = bvec->bv_len - dp->context_u;
-	*offset = bvec->bv_offset + dp->context_u;
+	struct bio_vec bvec = bvec_iter_bvec((struct bio_vec *)dp->context_ptr,
+					     dp->context_bi);
+
+	*p = bvec.bv_page;
+	*len = bvec.bv_len;
+	*offset = bvec.bv_offset;
+
+	/* avoid figuring it out again in bio_next_page() */
+	dp->context_bi.bi_sector = (sector_t)bvec.bv_len;
 }
 
 static void bio_next_page(struct dpages *dp)
 {
-	struct bio_vec *bvec = dp->context_ptr;
-	dp->context_ptr = bvec + 1;
-	dp->context_u = 0;
+	unsigned int len = (unsigned int)dp->context_bi.bi_sector;
+
+	bvec_iter_advance((struct bio_vec *)dp->context_ptr,
+			  &dp->context_bi, len);
 }
 
 static void bio_dp_init(struct dpages *dp, struct bio *bio)
 {
 	dp->get_page = bio_get_page;
 	dp->next_page = bio_next_page;
-	dp->context_ptr = __bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter);
-	dp->context_u = bio->bi_iter.bi_bvec_done;
+
+	/*
+	 * We just use bvec iterator to retrieve pages, so it is ok to
+	 * access the bvec table directly here
+	 */
+	dp->context_ptr = bio->bi_io_vec;
+	dp->context_bi = bio->bi_iter;
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-ioctl.c linux-libre-4.10-rc8-gnu/drivers/md/dm-ioctl.c
--- linux-libre-4.9-gnu/drivers/md/dm-ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,7 +17,7 @@
 #include <linux/hdreg.h>
 #include <linux/compat.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define DM_MSG_PREFIX "ioctl"
 #define DM_DRIVER_EMAIL "dm-devel@redhat.com"
@@ -1697,7 +1697,7 @@ static int copy_params(struct dm_ioctl _
 {
 	struct dm_ioctl *dmi;
 	int secure_data;
-	const size_t minimum_data_size = sizeof(*param_kernel) - sizeof(param_kernel->data);
+	const size_t minimum_data_size = offsetof(struct dm_ioctl, data);
 
 	if (copy_from_user(param_kernel, user, minimum_data_size))
 		return -EFAULT;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-log.c linux-libre-4.10-rc8-gnu/drivers/md/dm-log.c
--- linux-libre-4.9-gnu/drivers/md/dm-log.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-log.c	2017-02-12 16:03:20.000000000 -0500
@@ -308,7 +308,7 @@ static int flush_header(struct log_c *lc
 	};
 
 	lc->io_req.bi_op = REQ_OP_WRITE;
-	lc->io_req.bi_op_flags = WRITE_FLUSH;
+	lc->io_req.bi_op_flags = REQ_PREFLUSH;
 
 	return dm_io(&lc->io_req, 1, &null_location, NULL);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-mpath.c linux-libre-4.10-rc8-gnu/drivers/md/dm-mpath.c
--- linux-libre-4.9-gnu/drivers/md/dm-mpath.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-mpath.c	2017-02-12 16:03:20.000000000 -0500
@@ -372,16 +372,13 @@ static int __pg_init_all_paths(struct mu
 	return atomic_read(&m->pg_init_in_progress);
 }
 
-static int pg_init_all_paths(struct multipath *m)
+static void pg_init_all_paths(struct multipath *m)
 {
-	int r;
 	unsigned long flags;
 
 	spin_lock_irqsave(&m->lock, flags);
-	r = __pg_init_all_paths(m);
+	__pg_init_all_paths(m);
 	spin_unlock_irqrestore(&m->lock, flags);
-
-	return r;
 }
 
 static void __switch_pg(struct multipath *m, struct priority_group *pg)
@@ -430,7 +427,7 @@ static struct pgpath *choose_pgpath(stru
 	unsigned long flags;
 	struct priority_group *pg;
 	struct pgpath *pgpath;
-	bool bypassed = true;
+	unsigned bypassed = 1;
 
 	if (!atomic_read(&m->nr_valid_paths)) {
 		clear_bit(MPATHF_QUEUE_IO, &m->flags);
@@ -469,7 +466,7 @@ check_current_pg:
 	 */
 	do {
 		list_for_each_entry(pg, &m->priority_groups, list) {
-			if (pg->bypassed == bypassed)
+			if (pg->bypassed == !!bypassed)
 				continue;
 			pgpath = choose_path_in_pg(m, pg, nr_bytes);
 			if (!IS_ERR_OR_NULL(pgpath)) {
@@ -583,16 +580,17 @@ static int __multipath_map(struct dm_tar
 		 * .request_fn stacked on blk-mq path(s) and
 		 * blk-mq stacked on blk-mq path(s).
 		 */
-		*__clone = blk_mq_alloc_request(bdev_get_queue(bdev),
-						rq_data_dir(rq), BLK_MQ_REQ_NOWAIT);
-		if (IS_ERR(*__clone)) {
-			/* ENOMEM, requeue */
+		clone = blk_mq_alloc_request(bdev_get_queue(bdev),
+					     rq_data_dir(rq), BLK_MQ_REQ_NOWAIT);
+		if (IS_ERR(clone)) {
+			/* EBUSY, ENODEV or EWOULDBLOCK: requeue */
 			clear_request_fn_mpio(m, map_context);
 			return r;
 		}
-		(*__clone)->bio = (*__clone)->biotail = NULL;
-		(*__clone)->rq_disk = bdev->bd_disk;
-		(*__clone)->cmd_flags |= REQ_FAILFAST_TRANSPORT;
+		clone->bio = clone->biotail = NULL;
+		clone->rq_disk = bdev->bd_disk;
+		clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
+		*__clone = clone;
 	}
 
 	if (pgpath->pg->ps.type->start_io)
@@ -852,18 +850,22 @@ retain:
 		attached_handler_name = scsi_dh_attached_handler_name(q, GFP_KERNEL);
 		if (attached_handler_name) {
 			/*
+			 * Clear any hw_handler_params associated with a
+			 * handler that isn't already attached.
+			 */
+			if (m->hw_handler_name && strcmp(attached_handler_name, m->hw_handler_name)) {
+				kfree(m->hw_handler_params);
+				m->hw_handler_params = NULL;
+			}
+
+			/*
 			 * Reset hw_handler_name to match the attached handler
-			 * and clear any hw_handler_params associated with the
-			 * ignored handler.
 			 *
 			 * NB. This modifies the table line to show the actual
 			 * handler instead of the original table passed in.
 			 */
 			kfree(m->hw_handler_name);
 			m->hw_handler_name = attached_handler_name;
-
-			kfree(m->hw_handler_params);
-			m->hw_handler_params = NULL;
 		}
 	}
 
@@ -1002,6 +1004,8 @@ static int parse_hw_handler(struct dm_ar
 	}
 
 	m->hw_handler_name = kstrdup(dm_shift_arg(as), GFP_KERNEL);
+	if (!m->hw_handler_name)
+		return -EINVAL;
 
 	if (hw_argc > 1) {
 		char *p;
@@ -1362,7 +1366,7 @@ static int switch_pg_num(struct multipat
 	char dummy;
 
 	if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
-	    (pgnum > m->nr_priority_groups)) {
+	    !m->nr_priority_groups || (pgnum > m->nr_priority_groups)) {
 		DMWARN("invalid PG number supplied to switch_pg_num");
 		return -EINVAL;
 	}
@@ -1394,7 +1398,7 @@ static int bypass_pg_num(struct multipat
 	char dummy;
 
 	if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
-	    (pgnum > m->nr_priority_groups)) {
+	    !m->nr_priority_groups || (pgnum > m->nr_priority_groups)) {
 		DMWARN("invalid PG number supplied to bypass_pg");
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-raid1.c linux-libre-4.10-rc8-gnu/drivers/md/dm-raid1.c
--- linux-libre-4.9-gnu/drivers/md/dm-raid1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-raid1.c	2017-02-12 16:03:20.000000000 -0500
@@ -260,7 +260,7 @@ static int mirror_flush(struct dm_target
 	struct mirror *m;
 	struct dm_io_request io_req = {
 		.bi_op = REQ_OP_WRITE,
-		.bi_op_flags = WRITE_FLUSH,
+		.bi_op_flags = REQ_PREFLUSH,
 		.mem.type = DM_IO_KMEM,
 		.mem.ptr.addr = NULL,
 		.client = ms->io_client,
@@ -656,7 +656,7 @@ static void do_write(struct mirror_set *
 	struct mirror *m;
 	struct dm_io_request io_req = {
 		.bi_op = REQ_OP_WRITE,
-		.bi_op_flags = bio->bi_opf & WRITE_FLUSH_FUA,
+		.bi_op_flags = bio->bi_opf & (REQ_FUA | REQ_PREFLUSH),
 		.mem.type = DM_IO_BIO,
 		.mem.ptr.bio = bio,
 		.notify.fn = write_callback,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-raid.c linux-libre-4.10-rc8-gnu/drivers/md/dm-raid.c
--- linux-libre-4.9-gnu/drivers/md/dm-raid.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-raid.c	2017-02-12 16:03:20.000000000 -0500
@@ -160,7 +160,6 @@ struct raid_dev {
 				 CTR_FLAG_DAEMON_SLEEP | \
 				 CTR_FLAG_MIN_RECOVERY_RATE | \
 				 CTR_FLAG_MAX_RECOVERY_RATE | \
-				 CTR_FLAG_MAX_WRITE_BEHIND | \
 				 CTR_FLAG_STRIPE_CACHE | \
 				 CTR_FLAG_REGION_SIZE | \
 				 CTR_FLAG_DELTA_DISKS | \
@@ -171,7 +170,6 @@ struct raid_dev {
 				 CTR_FLAG_DAEMON_SLEEP | \
 				 CTR_FLAG_MIN_RECOVERY_RATE | \
 				 CTR_FLAG_MAX_RECOVERY_RATE | \
-				 CTR_FLAG_MAX_WRITE_BEHIND | \
 				 CTR_FLAG_STRIPE_CACHE | \
 				 CTR_FLAG_REGION_SIZE | \
 				 CTR_FLAG_DELTA_DISKS | \
@@ -2011,7 +2009,7 @@ static int super_load(struct md_rdev *rd
 		sb->compat_features = cpu_to_le32(FEATURE_FLAG_SUPPORTS_V190);
 
 		/* Force writing of superblocks to disk */
-		set_bit(MD_CHANGE_DEVS, &rdev->mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &rdev->mddev->sb_flags);
 
 		/* Any superblock is better than none, choose that if given */
 		return refdev ? 0 : 1;
@@ -2050,16 +2048,17 @@ static int super_init_validation(struct
 
 	mddev->reshape_position = MaxSector;
 
+	mddev->raid_disks = le32_to_cpu(sb->num_devices);
+	mddev->level = le32_to_cpu(sb->level);
+	mddev->layout = le32_to_cpu(sb->layout);
+	mddev->chunk_sectors = le32_to_cpu(sb->stripe_sectors);
+
 	/*
 	 * Reshaping is supported, e.g. reshape_position is valid
 	 * in superblock and superblock content is authoritative.
 	 */
 	if (le32_to_cpu(sb->compat_features) & FEATURE_FLAG_SUPPORTS_V190) {
 		/* Superblock is authoritative wrt given raid set layout! */
-		mddev->raid_disks = le32_to_cpu(sb->num_devices);
-		mddev->level = le32_to_cpu(sb->level);
-		mddev->layout = le32_to_cpu(sb->layout);
-		mddev->chunk_sectors = le32_to_cpu(sb->stripe_sectors);
 		mddev->new_level = le32_to_cpu(sb->new_level);
 		mddev->new_layout = le32_to_cpu(sb->new_layout);
 		mddev->new_chunk_sectors = le32_to_cpu(sb->new_stripe_sectors);
@@ -2087,38 +2086,44 @@ static int super_init_validation(struct
 		/*
 		 * No takeover/reshaping, because we don't have the extended v1.9.0 metadata
 		 */
-		if (le32_to_cpu(sb->level) != mddev->new_level) {
-			DMERR("Reshaping/takeover raid sets not yet supported. (raid level/stripes/size change)");
-			return -EINVAL;
-		}
-		if (le32_to_cpu(sb->layout) != mddev->new_layout) {
-			DMERR("Reshaping raid sets not yet supported. (raid layout change)");
-			DMERR("	 0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout);
-			DMERR("	 Old layout: %s w/ %d copies",
-			      raid10_md_layout_to_format(le32_to_cpu(sb->layout)),
-			      raid10_md_layout_to_copies(le32_to_cpu(sb->layout)));
-			DMERR("	 New layout: %s w/ %d copies",
-			      raid10_md_layout_to_format(mddev->layout),
-			      raid10_md_layout_to_copies(mddev->layout));
-			return -EINVAL;
-		}
-		if (le32_to_cpu(sb->stripe_sectors) != mddev->new_chunk_sectors) {
-			DMERR("Reshaping raid sets not yet supported. (stripe sectors change)");
-			return -EINVAL;
-		}
+		struct raid_type *rt_cur = get_raid_type_by_ll(mddev->level, mddev->layout);
+		struct raid_type *rt_new = get_raid_type_by_ll(mddev->new_level, mddev->new_layout);
 
-		/* We can only change the number of devices in raid1 with old (i.e. pre 1.0.7) metadata */
-		if (!rt_is_raid1(rs->raid_type) &&
-		    (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) {
-			DMERR("Reshaping raid sets not yet supported. (device count change from %u to %u)",
-			      sb->num_devices, mddev->raid_disks);
+		if (rs_takeover_requested(rs)) {
+			if (rt_cur && rt_new)
+				DMERR("Takeover raid sets from %s to %s not yet supported by metadata. (raid level change)",
+				      rt_cur->name, rt_new->name);
+			else
+				DMERR("Takeover raid sets not yet supported by metadata. (raid level change)");
+			return -EINVAL;
+		} else if (rs_reshape_requested(rs)) {
+			DMERR("Reshaping raid sets not yet supported by metadata. (raid layout change keeping level)");
+			if (mddev->layout != mddev->new_layout) {
+				if (rt_cur && rt_new)
+					DMERR("	 current layout %s vs new layout %s",
+					      rt_cur->name, rt_new->name);
+				else
+					DMERR("	 current layout 0x%X vs new layout 0x%X",
+					      le32_to_cpu(sb->layout), mddev->new_layout);
+			}
+			if (mddev->chunk_sectors != mddev->new_chunk_sectors)
+				DMERR("	 current stripe sectors %u vs new stripe sectors %u",
+				      mddev->chunk_sectors, mddev->new_chunk_sectors);
+			if (rs->delta_disks)
+				DMERR("	 current %u disks vs new %u disks",
+				      mddev->raid_disks, mddev->raid_disks + rs->delta_disks);
+			if (rs_is_raid10(rs)) {
+				DMERR("	 Old layout: %s w/ %u copies",
+				      raid10_md_layout_to_format(mddev->layout),
+				      raid10_md_layout_to_copies(mddev->layout));
+				DMERR("	 New layout: %s w/ %u copies",
+				      raid10_md_layout_to_format(mddev->new_layout),
+				      raid10_md_layout_to_copies(mddev->new_layout));
+			}
 			return -EINVAL;
 		}
 
 		DMINFO("Discovered old metadata format; upgrading to extended metadata format");
-
-		/* Table line is checked vs. authoritative superblock */
-		rs_set_new(rs);
 	}
 
 	if (!test_bit(__CTR_FLAG_NOSYNC, &rs->ctr_flags))
@@ -2211,7 +2216,7 @@ static int super_init_validation(struct
 				continue;
 
 			if (role != r->raid_disk) {
-				if (__is_raid10_near(mddev->layout)) {
+				if (rs_is_raid10(rs) && __is_raid10_near(mddev->layout)) {
 					if (mddev->raid_disks % __raid10_near_copies(mddev->layout) ||
 					    rs->raid_disks % rs->raid10_copies) {
 						rs->ti->error =
@@ -2994,6 +2999,9 @@ static int raid_ctr(struct dm_target *ti
 		}
 	}
 
+	/* Disable/enable discard support on raid set. */
+	configure_discard_support(rs);
+
 	mddev_unlock(&rs->md);
 	return 0;
 
@@ -3497,7 +3505,7 @@ static void rs_update_sbs(struct raid_se
 	struct mddev *mddev = &rs->md;
 	int ro = mddev->ro;
 
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 	mddev->ro = 0;
 	md_update_sb(mddev, 1);
 	mddev->ro = ro;
@@ -3580,12 +3588,6 @@ static int raid_preresume(struct dm_targ
 	if (test_bit(RT_FLAG_UPDATE_SBS, &rs->runtime_flags))
 		rs_update_sbs(rs);
 
-	/*
-	 * Disable/enable discard support on raid set after any
-	 * conversion, because devices can have been added
-	 */
-	configure_discard_support(rs);
-
 	/* Load the bitmap from disk unless raid0 */
 	r = __load_dirty_region_bitmap(rs);
 	if (r)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-rq.c linux-libre-4.10-rc8-gnu/drivers/md/dm-rq.c
--- linux-libre-4.9-gnu/drivers/md/dm-rq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-rq.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,11 +23,7 @@ static unsigned dm_mq_queue_depth = DM_M
 #define RESERVED_REQUEST_BASED_IOS	256
 static unsigned reserved_rq_based_ios = RESERVED_REQUEST_BASED_IOS;
 
-#ifdef CONFIG_DM_MQ_DEFAULT
-static bool use_blk_mq = true;
-#else
-static bool use_blk_mq = false;
-#endif
+static bool use_blk_mq = IS_ENABLED(CONFIG_DM_MQ_DEFAULT);
 
 bool dm_use_blk_mq_default(void)
 {
@@ -75,12 +71,6 @@ static void dm_old_start_queue(struct re
 
 static void dm_mq_start_queue(struct request_queue *q)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	queue_flag_clear(QUEUE_FLAG_STOPPED, q);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
 	blk_mq_start_stopped_hw_queues(q, true);
 	blk_mq_kick_requeue_list(q);
 }
@@ -105,20 +95,10 @@ static void dm_old_stop_queue(struct req
 
 static void dm_mq_stop_queue(struct request_queue *q)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	if (blk_queue_stopped(q)) {
-		spin_unlock_irqrestore(q->queue_lock, flags);
+	if (blk_mq_queue_stopped(q))
 		return;
-	}
 
-	queue_flag_set(QUEUE_FLAG_STOPPED, q);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
-	/* Avoid that requeuing could restart the queue. */
-	blk_mq_cancel_requeue_work(q);
-	blk_mq_stop_hw_queues(q);
+	blk_mq_quiesce_queue(q);
 }
 
 void dm_stop_queue(struct request_queue *q)
@@ -226,6 +206,9 @@ static void rq_end_stats(struct mapped_d
  */
 static void rq_completed(struct mapped_device *md, int rw, bool run_queue)
 {
+	struct request_queue *q = md->queue;
+	unsigned long flags;
+
 	atomic_dec(&md->pending[rw]);
 
 	/* nudge anyone waiting on suspend queue */
@@ -238,8 +221,11 @@ static void rq_completed(struct mapped_d
 	 * back into ->request_fn() could deadlock attempting to grab the
 	 * queue lock again.
 	 */
-	if (!md->queue->mq_ops && run_queue)
-		blk_run_queue_async(md->queue);
+	if (!q->mq_ops && run_queue) {
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_run_queue_async(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+	}
 
 	/*
 	 * dm_put() must be at the end of this function. See the comment above
@@ -313,7 +299,7 @@ static void dm_unprep_request(struct req
 
 	if (!rq->q->mq_ops) {
 		rq->special = NULL;
-		rq->cmd_flags &= ~REQ_DONTPREP;
+		rq->rq_flags &= ~RQF_DONTPREP;
 	}
 
 	if (clone)
@@ -338,12 +324,7 @@ static void dm_old_requeue_request(struc
 
 static void __dm_mq_kick_requeue_list(struct request_queue *q, unsigned long msecs)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	if (!blk_queue_stopped(q))
-		blk_mq_delay_kick_requeue_list(q, msecs);
-	spin_unlock_irqrestore(q->queue_lock, flags);
+	blk_mq_delay_kick_requeue_list(q, msecs);
 }
 
 void dm_mq_kick_requeue_list(struct mapped_device *md)
@@ -354,7 +335,7 @@ EXPORT_SYMBOL(dm_mq_kick_requeue_list);
 
 static void dm_mq_delay_requeue_request(struct request *rq, unsigned long msecs)
 {
-	blk_mq_requeue_request(rq);
+	blk_mq_requeue_request(rq, false);
 	__dm_mq_kick_requeue_list(rq->q, msecs);
 }
 
@@ -431,7 +412,7 @@ static void dm_softirq_done(struct reque
 		return;
 	}
 
-	if (rq->cmd_flags & REQ_FAILED)
+	if (rq->rq_flags & RQF_FAILED)
 		mapped = false;
 
 	dm_done(clone, tio->error, mapped);
@@ -460,7 +441,7 @@ static void dm_complete_request(struct r
  */
 static void dm_kill_unmapped_request(struct request *rq, int error)
 {
-	rq->cmd_flags |= REQ_FAILED;
+	rq->rq_flags |= RQF_FAILED;
 	dm_complete_request(rq, error);
 }
 
@@ -476,7 +457,7 @@ static void end_clone_request(struct req
 		 * For just cleaning up the information of the queue in which
 		 * the clone was dispatched.
 		 * The clone is *NOT* freed actually here because it is alloced
-		 * from dm own mempool (REQ_ALLOCED isn't set).
+		 * from dm own mempool (RQF_ALLOCED isn't set).
 		 */
 		__blk_put_request(clone->q, clone);
 	}
@@ -497,7 +478,7 @@ static void dm_dispatch_clone_request(st
 	int r;
 
 	if (blk_queue_io_stat(clone->q))
-		clone->cmd_flags |= REQ_IO_STAT;
+		clone->rq_flags |= RQF_IO_STAT;
 
 	clone->start_time = jiffies;
 	r = blk_insert_cloned_request(clone->q, clone);
@@ -633,7 +614,7 @@ static int dm_old_prep_fn(struct request
 		return BLKPREP_DEFER;
 
 	rq->special = tio;
-	rq->cmd_flags |= REQ_DONTPREP;
+	rq->rq_flags |= RQF_DONTPREP;
 
 	return BLKPREP_OK;
 }
@@ -798,6 +779,10 @@ static void dm_old_request_fn(struct req
 		int srcu_idx;
 		struct dm_table *map = dm_get_live_table(md, &srcu_idx);
 
+		if (unlikely(!map)) {
+			dm_put_live_table(md, srcu_idx);
+			return;
+		}
 		ti = dm_table_find_target(map, pos);
 		dm_put_live_table(md, srcu_idx);
 	}
@@ -819,7 +804,7 @@ static void dm_old_request_fn(struct req
 			pos = blk_rq_pos(rq);
 
 		if ((dm_old_request_peeked_before_merge_deadline(md) &&
-		     md_in_flight(md) && rq->bio && rq->bio->bi_vcnt == 1 &&
+		     md_in_flight(md) && rq->bio && !bio_multiple_segments(rq->bio) &&
 		     md->last_rq_pos == pos && md->last_rq_rw == rq_data_dir(rq)) ||
 		    (ti->type->busy && ti->type->busy(ti))) {
 			blk_delay_queue(q, 10);
@@ -904,17 +889,6 @@ static int dm_mq_queue_rq(struct blk_mq_
 		dm_put_live_table(md, srcu_idx);
 	}
 
-	/*
-	 * On suspend dm_stop_queue() handles stopping the blk-mq
-	 * request_queue BUT: even though the hw_queues are marked
-	 * BLK_MQ_S_STOPPED at that point there is still a race that
-	 * is allowing block/blk-mq.c to call ->queue_rq against a
-	 * hctx that it really shouldn't.  The following check guards
-	 * against this rarity (albeit _not_ race-free).
-	 */
-	if (unlikely(test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
-		return BLK_MQ_RQ_QUEUE_BUSY;
-
 	if (ti->type->busy && ti->type->busy(ti))
 		return BLK_MQ_RQ_QUEUE_BUSY;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-snap-persistent.c linux-libre-4.10-rc8-gnu/drivers/md/dm-snap-persistent.c
--- linux-libre-4.9-gnu/drivers/md/dm-snap-persistent.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-snap-persistent.c	2017-02-12 16:03:20.000000000 -0500
@@ -741,7 +741,7 @@ static void persistent_commit_exception(
 	/*
 	 * Commit exceptions to disk.
 	 */
-	if (ps->valid && area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA))
+	if (ps->valid && area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA))
 		ps->valid = 0;
 
 	/*
@@ -818,7 +818,7 @@ static int persistent_commit_merge(struc
 	for (i = 0; i < nr_merged; i++)
 		clear_exception(ps, ps->current_committed - 1 - i);
 
-	r = area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA);
+	r = area_io(ps, REQ_OP_WRITE, REQ_PREFLUSH | REQ_FUA);
 	if (r < 0)
 		return r;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-table.c linux-libre-4.10-rc8-gnu/drivers/md/dm-table.c
--- linux-libre-4.9-gnu/drivers/md/dm-table.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-table.c	2017-02-12 16:03:20.000000000 -0500
@@ -871,7 +871,7 @@ static int dm_table_determine_type(struc
 {
 	unsigned i;
 	unsigned bio_based = 0, request_based = 0, hybrid = 0;
-	bool verify_blk_mq = false;
+	unsigned sq_count = 0, mq_count = 0;
 	struct dm_target *tgt;
 	struct dm_dev_internal *dd;
 	struct list_head *devices = dm_table_get_devices(t);
@@ -924,12 +924,6 @@ static int dm_table_determine_type(struc
 
 	BUG_ON(!request_based); /* No targets in this table */
 
-	if (list_empty(devices) && __table_type_request_based(live_md_type)) {
-		/* inherit live MD type */
-		t->type = live_md_type;
-		return 0;
-	}
-
 	/*
 	 * The only way to establish DM_TYPE_MQ_REQUEST_BASED is by
 	 * having a compatible target use dm_table_set_type.
@@ -948,6 +942,19 @@ verify_rq_based:
 		return -EINVAL;
 	}
 
+	if (list_empty(devices)) {
+		int srcu_idx;
+		struct dm_table *live_table = dm_get_live_table(t->md, &srcu_idx);
+
+		/* inherit live table's type and all_blk_mq */
+		if (live_table) {
+			t->type = live_table->type;
+			t->all_blk_mq = live_table->all_blk_mq;
+		}
+		dm_put_live_table(t->md, srcu_idx);
+		return 0;
+	}
+
 	/* Non-request-stackable devices can't be used for request-based dm */
 	list_for_each_entry(dd, devices, list) {
 		struct request_queue *q = bdev_get_queue(dd->dm_dev->bdev);
@@ -959,19 +966,19 @@ verify_rq_based:
 		}
 
 		if (q->mq_ops)
-			verify_blk_mq = true;
+			mq_count++;
+		else
+			sq_count++;
 	}
+	if (sq_count && mq_count) {
+		DMERR("table load rejected: not all devices are blk-mq request-stackable");
+		return -EINVAL;
+	}
+	t->all_blk_mq = mq_count > 0;
 
-	if (verify_blk_mq) {
-		/* verify _all_ devices in the table are blk-mq devices */
-		list_for_each_entry(dd, devices, list)
-			if (!bdev_get_queue(dd->dm_dev->bdev)->mq_ops) {
-				DMERR("table load rejected: not all devices"
-				      " are blk-mq request-stackable");
-				return -EINVAL;
-			}
-
-		t->all_blk_mq = true;
+	if (t->type == DM_TYPE_MQ_REQUEST_BASED && !t->all_blk_mq) {
+		DMERR("table load rejected: all devices are not blk-mq request-stackable");
+		return -EINVAL;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/dm-verity-target.c linux-libre-4.10-rc8-gnu/drivers/md/dm-verity-target.c
--- linux-libre-4.9-gnu/drivers/md/dm-verity-target.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/dm-verity-target.c	2017-02-12 16:03:20.000000000 -0500
@@ -868,7 +868,7 @@ static int verity_ctr(struct dm_target *
 
 	r = dm_get_device(ti, argv[2], FMODE_READ, &v->hash_dev);
 	if (r) {
-		ti->error = "Data device lookup failed";
+		ti->error = "Hash device lookup failed";
 		goto bad;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/Kconfig linux-libre-4.10-rc8-gnu/drivers/md/Kconfig
--- linux-libre-4.9-gnu/drivers/md/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -240,9 +240,17 @@ config DM_BUFIO
 	 as a cache, holding recently-read blocks in memory and performing
 	 delayed writes.
 
+config DM_DEBUG_BLOCK_MANAGER_LOCKING
+       bool "Block manager locking"
+       depends on DM_BUFIO
+       ---help---
+	 Block manager locking can catch various metadata corruption issues.
+
+	 If unsure, say N.
+
 config DM_DEBUG_BLOCK_STACK_TRACING
        bool "Keep stack trace of persistent data block lock holders"
-       depends on STACKTRACE_SUPPORT && DM_BUFIO
+       depends on STACKTRACE_SUPPORT && DM_DEBUG_BLOCK_MANAGER_LOCKING
        select STACKTRACE
        ---help---
 	 Enable this for messages that may help debug problems with the
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/linear.c linux-libre-4.10-rc8-gnu/drivers/md/linear.c
--- linux-libre-4.9-gnu/drivers/md/linear.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/linear.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,7 @@
 #include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <trace/events/block.h>
 #include "md.h"
 #include "linear.h"
 
@@ -101,8 +102,8 @@ static struct linear_conf *linear_conf(s
 		sector_t sectors;
 
 		if (j < 0 || j >= raid_disks || disk->rdev) {
-			printk(KERN_ERR "md/linear:%s: disk numbering problem. Aborting!\n",
-			       mdname(mddev));
+			pr_warn("md/linear:%s: disk numbering problem. Aborting!\n",
+				mdname(mddev));
 			goto out;
 		}
 
@@ -123,8 +124,8 @@ static struct linear_conf *linear_conf(s
 			discard_supported = true;
 	}
 	if (cnt != raid_disks) {
-		printk(KERN_ERR "md/linear:%s: not enough drives present. Aborting!\n",
-		       mdname(mddev));
+		pr_warn("md/linear:%s: not enough drives present. Aborting!\n",
+			mdname(mddev));
 		goto out;
 	}
 
@@ -227,22 +228,22 @@ static void linear_make_request(struct m
 	}
 
 	do {
-		tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector);
+		sector_t bio_sector = bio->bi_iter.bi_sector;
+		tmp_dev = which_dev(mddev, bio_sector);
 		start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
 		end_sector = tmp_dev->end_sector;
 		data_offset = tmp_dev->rdev->data_offset;
 		bio->bi_bdev = tmp_dev->rdev->bdev;
 
-		if (unlikely(bio->bi_iter.bi_sector >= end_sector ||
-			     bio->bi_iter.bi_sector < start_sector))
+		if (unlikely(bio_sector >= end_sector ||
+			     bio_sector < start_sector))
 			goto out_of_bounds;
 
 		if (unlikely(bio_end_sector(bio) > end_sector)) {
 			/* This bio crosses a device boundary, so we have to
 			 * split it.
 			 */
-			split = bio_split(bio, end_sector -
-					  bio->bi_iter.bi_sector,
+			split = bio_split(bio, end_sector - bio_sector,
 					  GFP_NOIO, fs_bio_set);
 			bio_chain(split, bio);
 		} else {
@@ -256,15 +257,18 @@ static void linear_make_request(struct m
 			 !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) {
 			/* Just ignore it */
 			bio_endio(split);
-		} else
+		} else {
+			if (mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(split->bi_bdev),
+						      split, disk_devt(mddev->gendisk),
+						      bio_sector);
 			generic_make_request(split);
+		}
 	} while (split != bio);
 	return;
 
 out_of_bounds:
-	printk(KERN_ERR
-	       "md/linear:%s: make_request: Sector %llu out of bounds on "
-	       "dev %s: %llu sectors, offset %llu\n",
+	pr_err("md/linear:%s: make_request: Sector %llu out of bounds on dev %s: %llu sectors, offset %llu\n",
 	       mdname(mddev),
 	       (unsigned long long)bio->bi_iter.bi_sector,
 	       bdevname(tmp_dev->rdev->bdev, b),
@@ -275,7 +279,6 @@ out_of_bounds:
 
 static void linear_status (struct seq_file *seq, struct mddev *mddev)
 {
-
 	seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/md.c linux-libre-4.10-rc8-gnu/drivers/md/md.c
--- linux-libre-4.9-gnu/drivers/md/md.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/md.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,18 @@
    You should have received a copy of the GNU General Public License
    (for example /usr/src/linux/COPYING); if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   Errors, Warnings, etc.
+   Please use:
+     pr_crit() for error conditions that risk data loss
+     pr_err() for error conditions that are unexpected, like an IO error
+         or internal inconsistency
+     pr_warn() for error conditions that could have been predicated, like
+         adding a device to an array when it has incompatible metadata
+     pr_info() for every interesting, very rare events, like an array starting
+         or stopping, or resync starting or stopping
+     pr_debug() for everything else.
+
 */
 
 #include <linux/kthread.h>
@@ -52,6 +64,7 @@
 #include <linux/raid/md_p.h>
 #include <linux/raid/md_u.h>
 #include <linux/slab.h>
+#include <trace/events/block.h>
 #include "md.h"
 #include "bitmap.h"
 #include "md-cluster.h"
@@ -394,7 +407,7 @@ static void submit_flushes(struct work_s
 			bi->bi_end_io = md_end_flush;
 			bi->bi_private = rdev;
 			bi->bi_bdev = rdev->bdev;
-			bio_set_op_attrs(bi, REQ_OP_WRITE, WRITE_FLUSH);
+			bi->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 			atomic_inc(&mddev->flush_pending);
 			submit_bio(bi);
 			rcu_read_lock();
@@ -684,11 +697,8 @@ static inline sector_t calc_dev_sboffset
 static int alloc_disk_sb(struct md_rdev *rdev)
 {
 	rdev->sb_page = alloc_page(GFP_KERNEL);
-	if (!rdev->sb_page) {
-		printk(KERN_ALERT "md: out of memory.\n");
+	if (!rdev->sb_page)
 		return -ENOMEM;
-	}
-
 	return 0;
 }
 
@@ -715,9 +725,15 @@ static void super_written(struct bio *bi
 	struct mddev *mddev = rdev->mddev;
 
 	if (bio->bi_error) {
-		printk("md: super_written gets error=%d\n", bio->bi_error);
+		pr_err("md: super_written gets error=%d\n", bio->bi_error);
 		md_error(mddev, rdev);
-	}
+		if (!test_bit(Faulty, &rdev->flags)
+		    && (bio->bi_opf & MD_FAILFAST)) {
+			set_bit(MD_SB_NEED_REWRITE, &mddev->sb_flags);
+			set_bit(LastDev, &rdev->flags);
+		}
+	} else
+		clear_bit(LastDev, &rdev->flags);
 
 	if (atomic_dec_and_test(&mddev->pending_writes))
 		wake_up(&mddev->sb_wait);
@@ -734,7 +750,13 @@ void md_super_write(struct mddev *mddev,
 	 * if zero is reached.
 	 * If an error occurred, call md_error
 	 */
-	struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, mddev);
+	struct bio *bio;
+	int ff = 0;
+
+	if (test_bit(Faulty, &rdev->flags))
+		return;
+
+	bio = bio_alloc_mddev(GFP_NOIO, 1, mddev);
 
 	atomic_inc(&rdev->nr_pending);
 
@@ -743,16 +765,24 @@ void md_super_write(struct mddev *mddev,
 	bio_add_page(bio, page, size, 0);
 	bio->bi_private = rdev;
 	bio->bi_end_io = super_written;
-	bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH_FUA);
+
+	if (test_bit(MD_FAILFAST_SUPPORTED, &mddev->flags) &&
+	    test_bit(FailFast, &rdev->flags) &&
+	    !test_bit(LastDev, &rdev->flags))
+		ff = MD_FAILFAST;
+	bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_FUA | ff;
 
 	atomic_inc(&mddev->pending_writes);
 	submit_bio(bio);
 }
 
-void md_super_wait(struct mddev *mddev)
+int md_super_wait(struct mddev *mddev)
 {
 	/* wait for all superblock writes that were scheduled to complete */
 	wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+	if (test_and_clear_bit(MD_SB_NEED_REWRITE, &mddev->sb_flags))
+		return -EAGAIN;
+	return 0;
 }
 
 int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
@@ -795,8 +825,8 @@ static int read_disk_sb(struct md_rdev *
 	return 0;
 
 fail:
-	printk(KERN_WARNING "md: disabled device %s, could not read superblock.\n",
-		bdevname(rdev->bdev,b));
+	pr_err("md: disabled device %s, could not read superblock.\n",
+	       bdevname(rdev->bdev,b));
 	return -EINVAL;
 }
 
@@ -818,7 +848,6 @@ static int sb_equal(mdp_super_t *sb1, md
 
 	if (!tmp1 || !tmp2) {
 		ret = 0;
-		printk(KERN_INFO "md.c sb_equal(): failed to allocate memory!\n");
 		goto abort;
 	}
 
@@ -932,7 +961,7 @@ int md_check_no_bitmap(struct mddev *mdd
 {
 	if (!mddev->bitmap_info.file && !mddev->bitmap_info.offset)
 		return 0;
-	printk(KERN_ERR "%s: bitmaps are not supported for %s\n",
+	pr_warn("%s: bitmaps are not supported for %s\n",
 		mdname(mddev), mddev->pers->name);
 	return 1;
 }
@@ -956,7 +985,8 @@ static int super_90_load(struct md_rdev
 	rdev->sb_start = calc_dev_sboffset(rdev);
 
 	ret = read_disk_sb(rdev, MD_SB_BYTES);
-	if (ret) return ret;
+	if (ret)
+		return ret;
 
 	ret = -EINVAL;
 
@@ -964,17 +994,15 @@ static int super_90_load(struct md_rdev
 	sb = page_address(rdev->sb_page);
 
 	if (sb->md_magic != MD_SB_MAGIC) {
-		printk(KERN_ERR "md: invalid raid superblock magic on %s\n",
-		       b);
+		pr_warn("md: invalid raid superblock magic on %s\n", b);
 		goto abort;
 	}
 
 	if (sb->major_version != 0 ||
 	    sb->minor_version < 90 ||
 	    sb->minor_version > 91) {
-		printk(KERN_WARNING "Bad version number %d.%d on %s\n",
-			sb->major_version, sb->minor_version,
-			b);
+		pr_warn("Bad version number %d.%d on %s\n",
+			sb->major_version, sb->minor_version, b);
 		goto abort;
 	}
 
@@ -982,8 +1010,7 @@ static int super_90_load(struct md_rdev
 		goto abort;
 
 	if (md_csum_fold(calc_sb_csum(sb)) != md_csum_fold(sb->sb_csum)) {
-		printk(KERN_WARNING "md: invalid superblock checksum on %s\n",
-			b);
+		pr_warn("md: invalid superblock checksum on %s\n", b);
 		goto abort;
 	}
 
@@ -1004,14 +1031,13 @@ static int super_90_load(struct md_rdev
 		__u64 ev1, ev2;
 		mdp_super_t *refsb = page_address(refdev->sb_page);
 		if (!uuid_equal(refsb, sb)) {
-			printk(KERN_WARNING "md: %s has different UUID to %s\n",
+			pr_warn("md: %s has different UUID to %s\n",
 				b, bdevname(refdev->bdev,b2));
 			goto abort;
 		}
 		if (!sb_equal(refsb, sb)) {
-			printk(KERN_WARNING "md: %s has same UUID"
-			       " but different superblock to %s\n",
-			       b, bdevname(refdev->bdev, b2));
+			pr_warn("md: %s has same UUID but different superblock to %s\n",
+				b, bdevname(refdev->bdev, b2));
 			goto abort;
 		}
 		ev1 = md_event(sb);
@@ -1158,6 +1184,8 @@ static int super_90_validate(struct mdde
 		}
 		if (desc->state & (1<<MD_DISK_WRITEMOSTLY))
 			set_bit(WriteMostly, &rdev->flags);
+		if (desc->state & (1<<MD_DISK_FAILFAST))
+			set_bit(FailFast, &rdev->flags);
 	} else /* MULTIPATH are always insync */
 		set_bit(In_sync, &rdev->flags);
 	return 0;
@@ -1283,6 +1311,8 @@ static void super_90_sync(struct mddev *
 		}
 		if (test_bit(WriteMostly, &rdev2->flags))
 			d->state |= (1<<MD_DISK_WRITEMOSTLY);
+		if (test_bit(FailFast, &rdev2->flags))
+			d->state |= (1<<MD_DISK_FAILFAST);
 	}
 	/* now set the "removed" and "faulty" bits on any missing devices */
 	for (i=0 ; i < mddev->raid_disks ; i++) {
@@ -1324,9 +1354,10 @@ super_90_rdev_size_change(struct md_rdev
 	if (IS_ENABLED(CONFIG_LBDAF) && (u64)num_sectors >= (2ULL << 32) &&
 	    rdev->mddev->level >= 1)
 		num_sectors = (sector_t)(2ULL << 32) - 2;
-	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
+	do {
+		md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
 		       rdev->sb_page);
-	md_super_wait(rdev->mddev);
+	} while (md_super_wait(rdev->mddev) < 0);
 	return num_sectors;
 }
 
@@ -1413,13 +1444,13 @@ static int super_1_load(struct md_rdev *
 		return -EINVAL;
 
 	if (calc_sb_1_csum(sb) != sb->sb_csum) {
-		printk("md: invalid superblock checksum on %s\n",
+		pr_warn("md: invalid superblock checksum on %s\n",
 			bdevname(rdev->bdev,b));
 		return -EINVAL;
 	}
 	if (le64_to_cpu(sb->data_size) < 10) {
-		printk("md: data_size too small on %s\n",
-		       bdevname(rdev->bdev,b));
+		pr_warn("md: data_size too small on %s\n",
+			bdevname(rdev->bdev,b));
 		return -EINVAL;
 	}
 	if (sb->pad0 ||
@@ -1503,8 +1534,7 @@ static int super_1_load(struct md_rdev *
 		    sb->level != refsb->level ||
 		    sb->layout != refsb->layout ||
 		    sb->chunksize != refsb->chunksize) {
-			printk(KERN_WARNING "md: %s has strangely different"
-				" superblock to %s\n",
+			pr_warn("md: %s has strangely different superblock to %s\n",
 				bdevname(rdev->bdev,b),
 				bdevname(refdev->bdev,b2));
 			return -EINVAL;
@@ -1646,8 +1676,7 @@ static int super_1_validate(struct mddev
 		case MD_DISK_ROLE_JOURNAL: /* journal device */
 			if (!(le32_to_cpu(sb->feature_map) & MD_FEATURE_JOURNAL)) {
 				/* journal device without journal feature */
-				printk(KERN_WARNING
-				  "md: journal device provided without journal feature, ignoring the device\n");
+				pr_warn("md: journal device provided without journal feature, ignoring the device\n");
 				return -EINVAL;
 			}
 			set_bit(Journal, &rdev->flags);
@@ -1669,6 +1698,8 @@ static int super_1_validate(struct mddev
 		}
 		if (sb->devflags & WriteMostly1)
 			set_bit(WriteMostly, &rdev->flags);
+		if (sb->devflags & FailFast1)
+			set_bit(FailFast, &rdev->flags);
 		if (le32_to_cpu(sb->feature_map) & MD_FEATURE_REPLACEMENT)
 			set_bit(Replacement, &rdev->flags);
 	} else /* MULTIPATH are always insync */
@@ -1707,6 +1738,10 @@ static void super_1_sync(struct mddev *m
 	sb->chunksize = cpu_to_le32(mddev->chunk_sectors);
 	sb->level = cpu_to_le32(mddev->level);
 	sb->layout = cpu_to_le32(mddev->layout);
+	if (test_bit(FailFast, &rdev->flags))
+		sb->devflags |= FailFast1;
+	else
+		sb->devflags &= ~FailFast1;
 
 	if (test_bit(WriteMostly, &rdev->flags))
 		sb->devflags |= WriteMostly1;
@@ -1863,9 +1898,10 @@ super_1_rdev_size_change(struct md_rdev
 	sb->data_size = cpu_to_le64(num_sectors);
 	sb->super_offset = rdev->sb_start;
 	sb->sb_csum = calc_sb_1_csum(sb);
-	md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
-		       rdev->sb_page);
-	md_super_wait(rdev->mddev);
+	do {
+		md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size,
+			       rdev->sb_page);
+	} while (md_super_wait(rdev->mddev) < 0);
 	return num_sectors;
 
 }
@@ -2004,9 +2040,9 @@ int md_integrity_register(struct mddev *
 	blk_integrity_register(mddev->gendisk,
 			       bdev_get_integrity(reference->bdev));
 
-	printk(KERN_NOTICE "md: data integrity enabled on %s\n", mdname(mddev));
+	pr_debug("md: data integrity enabled on %s\n", mdname(mddev));
 	if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) {
-		printk(KERN_ERR "md: failed to create integrity pool for %s\n",
+		pr_err("md: failed to create integrity pool for %s\n",
 		       mdname(mddev));
 		return -EINVAL;
 	}
@@ -2034,8 +2070,8 @@ int md_integrity_add_rdev(struct md_rdev
 		return 0;
 
 	if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
-		printk(KERN_NOTICE "%s: incompatible integrity profile for %s\n",
-				mdname(mddev), bdevname(rdev->bdev, name));
+		pr_err("%s: incompatible integrity profile for %s\n",
+		       mdname(mddev), bdevname(rdev->bdev, name));
 		return -ENXIO;
 	}
 
@@ -2089,15 +2125,15 @@ static int bind_rdev_to_array(struct md_
 	rcu_read_unlock();
 	if (!test_bit(Journal, &rdev->flags) &&
 	    mddev->max_disks && rdev->desc_nr >= mddev->max_disks) {
-		printk(KERN_WARNING "md: %s: array is limited to %d devices\n",
-		       mdname(mddev), mddev->max_disks);
+		pr_warn("md: %s: array is limited to %d devices\n",
+			mdname(mddev), mddev->max_disks);
 		return -EBUSY;
 	}
 	bdevname(rdev->bdev,b);
 	strreplace(b, '/', '!');
 
 	rdev->mddev = mddev;
-	printk(KERN_INFO "md: bind<%s>\n", b);
+	pr_debug("md: bind<%s>\n", b);
 
 	if ((err = kobject_add(&rdev->kobj, &mddev->kobj, "dev-%s", b)))
 		goto fail;
@@ -2116,8 +2152,8 @@ static int bind_rdev_to_array(struct md_
 	return 0;
 
  fail:
-	printk(KERN_WARNING "md: failed to register dev-%s for %s\n",
-	       b, mdname(mddev));
+	pr_warn("md: failed to register dev-%s for %s\n",
+		b, mdname(mddev));
 	return err;
 }
 
@@ -2134,7 +2170,7 @@ static void unbind_rdev_from_array(struc
 
 	bd_unlink_disk_holder(rdev->bdev, rdev->mddev->gendisk);
 	list_del_rcu(&rdev->same_set);
-	printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b));
+	pr_debug("md: unbind<%s>\n", bdevname(rdev->bdev,b));
 	rdev->mddev = NULL;
 	sysfs_remove_link(&rdev->kobj, "block");
 	sysfs_put(rdev->sysfs_state);
@@ -2164,8 +2200,7 @@ static int lock_rdev(struct md_rdev *rde
 	bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL,
 				 shared ? (struct md_rdev *)lock_rdev : rdev);
 	if (IS_ERR(bdev)) {
-		printk(KERN_ERR "md: could not open %s.\n",
-			__bdevname(dev, b));
+		pr_warn("md: could not open %s.\n", __bdevname(dev, b));
 		return PTR_ERR(bdev);
 	}
 	rdev->bdev = bdev;
@@ -2185,8 +2220,7 @@ static void export_rdev(struct md_rdev *
 {
 	char b[BDEVNAME_SIZE];
 
-	printk(KERN_INFO "md: export_rdev(%s)\n",
-		bdevname(rdev->bdev,b));
+	pr_debug("md: export_rdev(%s)\n", bdevname(rdev->bdev,b));
 	md_rdev_clear(rdev);
 #ifndef MODULE
 	if (test_bit(AutoDetected, &rdev->flags))
@@ -2288,24 +2322,24 @@ void md_update_sb(struct mddev *mddev, i
 
 	if (mddev->ro) {
 		if (force_change)
-			set_bit(MD_CHANGE_DEVS, &mddev->flags);
+			set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		return;
 	}
 
 repeat:
 	if (mddev_is_clustered(mddev)) {
-		if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags))
+		if (test_and_clear_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags))
 			force_change = 1;
-		if (test_and_clear_bit(MD_CHANGE_CLEAN, &mddev->flags))
+		if (test_and_clear_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags))
 			nospares = 1;
 		ret = md_cluster_ops->metadata_update_start(mddev);
 		/* Has someone else has updated the sb */
 		if (!does_sb_need_changing(mddev)) {
 			if (ret == 0)
 				md_cluster_ops->metadata_update_cancel(mddev);
-			bit_clear_unless(&mddev->flags, BIT(MD_CHANGE_PENDING),
-							 BIT(MD_CHANGE_DEVS) |
-							 BIT(MD_CHANGE_CLEAN));
+			bit_clear_unless(&mddev->sb_flags, BIT(MD_SB_CHANGE_PENDING),
+							 BIT(MD_SB_CHANGE_DEVS) |
+							 BIT(MD_SB_CHANGE_CLEAN));
 			return;
 		}
 	}
@@ -2321,10 +2355,10 @@ repeat:
 
 	}
 	if (!mddev->persistent) {
-		clear_bit(MD_CHANGE_CLEAN, &mddev->flags);
-		clear_bit(MD_CHANGE_DEVS, &mddev->flags);
+		clear_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
+		clear_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		if (!mddev->external) {
-			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+			clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
 			rdev_for_each(rdev, mddev) {
 				if (rdev->badblocks.changed) {
 					rdev->badblocks.changed = 0;
@@ -2344,9 +2378,9 @@ repeat:
 
 	mddev->utime = ktime_get_real_seconds();
 
-	if (test_and_clear_bit(MD_CHANGE_DEVS, &mddev->flags))
+	if (test_and_clear_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags))
 		force_change = 1;
-	if (test_and_clear_bit(MD_CHANGE_CLEAN, &mddev->flags))
+	if (test_and_clear_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags))
 		/* just a clean<-> dirty transition, possibly leave spares alone,
 		 * though if events isn't the right even/odd, we will have to do
 		 * spares after all
@@ -2402,6 +2436,9 @@ repeat:
 	pr_debug("md: updating %s RAID superblock on device (in sync %d)\n",
 		 mdname(mddev), mddev->in_sync);
 
+	if (mddev->queue)
+		blk_add_trace_msg(mddev->queue, "md md_update_sb");
+rewrite:
 	bitmap_update_sb(mddev->bitmap);
 	rdev_for_each(rdev, mddev) {
 		char b[BDEVNAME_SIZE];
@@ -2433,15 +2470,16 @@ repeat:
 			/* only need to write one superblock... */
 			break;
 	}
-	md_super_wait(mddev);
-	/* if there was a failure, MD_CHANGE_DEVS was set, and we re-write super */
+	if (md_super_wait(mddev) < 0)
+		goto rewrite;
+	/* if there was a failure, MD_SB_CHANGE_DEVS was set, and we re-write super */
 
 	if (mddev_is_clustered(mddev) && ret == 0)
 		md_cluster_ops->metadata_update_finish(mddev);
 
 	if (mddev->in_sync != sync_req ||
-	    !bit_clear_unless(&mddev->flags, BIT(MD_CHANGE_PENDING),
-			       BIT(MD_CHANGE_DEVS) | BIT(MD_CHANGE_CLEAN)))
+	    !bit_clear_unless(&mddev->sb_flags, BIT(MD_SB_CHANGE_PENDING),
+			       BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_CLEAN)))
 		/* have to write it out again */
 		goto repeat;
 	wake_up(&mddev->sb_wait);
@@ -2485,7 +2523,7 @@ static int add_bound_rdev(struct md_rdev
 	}
 	sysfs_notify_dirent_safe(rdev->sysfs_state);
 
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 	if (mddev->degraded)
 		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -2523,51 +2561,41 @@ struct rdev_sysfs_entry {
 static ssize_t
 state_show(struct md_rdev *rdev, char *page)
 {
-	char *sep = "";
+	char *sep = ",";
 	size_t len = 0;
 	unsigned long flags = ACCESS_ONCE(rdev->flags);
 
 	if (test_bit(Faulty, &flags) ||
-	    rdev->badblocks.unacked_exist) {
-		len+= sprintf(page+len, "%sfaulty",sep);
-		sep = ",";
-	}
-	if (test_bit(In_sync, &flags)) {
-		len += sprintf(page+len, "%sin_sync",sep);
-		sep = ",";
-	}
-	if (test_bit(Journal, &flags)) {
-		len += sprintf(page+len, "%sjournal",sep);
-		sep = ",";
-	}
-	if (test_bit(WriteMostly, &flags)) {
-		len += sprintf(page+len, "%swrite_mostly",sep);
-		sep = ",";
-	}
+	    (!test_bit(ExternalBbl, &flags) &&
+	    rdev->badblocks.unacked_exist))
+		len += sprintf(page+len, "faulty%s", sep);
+	if (test_bit(In_sync, &flags))
+		len += sprintf(page+len, "in_sync%s", sep);
+	if (test_bit(Journal, &flags))
+		len += sprintf(page+len, "journal%s", sep);
+	if (test_bit(WriteMostly, &flags))
+		len += sprintf(page+len, "write_mostly%s", sep);
 	if (test_bit(Blocked, &flags) ||
 	    (rdev->badblocks.unacked_exist
-	     && !test_bit(Faulty, &flags))) {
-		len += sprintf(page+len, "%sblocked", sep);
-		sep = ",";
-	}
+	     && !test_bit(Faulty, &flags)))
+		len += sprintf(page+len, "blocked%s", sep);
 	if (!test_bit(Faulty, &flags) &&
 	    !test_bit(Journal, &flags) &&
-	    !test_bit(In_sync, &flags)) {
-		len += sprintf(page+len, "%sspare", sep);
-		sep = ",";
-	}
-	if (test_bit(WriteErrorSeen, &flags)) {
-		len += sprintf(page+len, "%swrite_error", sep);
-		sep = ",";
-	}
-	if (test_bit(WantReplacement, &flags)) {
-		len += sprintf(page+len, "%swant_replacement", sep);
-		sep = ",";
-	}
-	if (test_bit(Replacement, &flags)) {
-		len += sprintf(page+len, "%sreplacement", sep);
-		sep = ",";
-	}
+	    !test_bit(In_sync, &flags))
+		len += sprintf(page+len, "spare%s", sep);
+	if (test_bit(WriteErrorSeen, &flags))
+		len += sprintf(page+len, "write_error%s", sep);
+	if (test_bit(WantReplacement, &flags))
+		len += sprintf(page+len, "want_replacement%s", sep);
+	if (test_bit(Replacement, &flags))
+		len += sprintf(page+len, "replacement%s", sep);
+	if (test_bit(ExternalBbl, &flags))
+		len += sprintf(page+len, "external_bbl%s", sep);
+	if (test_bit(FailFast, &flags))
+		len += sprintf(page+len, "failfast%s", sep);
+
+	if (len)
+		len -= strlen(sep);
 
 	return len+sprintf(page+len, "\n");
 }
@@ -2587,6 +2615,7 @@ state_store(struct md_rdev *rdev, const
 	 *            so that it gets rebuilt based on bitmap
 	 *  write_error - sets WriteErrorSeen
 	 *  -write_error - clears WriteErrorSeen
+	 *  {,-}failfast - set/clear FailFast
 	 */
 	int err = -EINVAL;
 	if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
@@ -2610,8 +2639,10 @@ state_store(struct md_rdev *rdev, const
 
 			if (err == 0) {
 				md_kick_rdev_from_array(rdev);
-				if (mddev->pers)
-					md_update_sb(mddev, 1);
+				if (mddev->pers) {
+					set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
+					md_wakeup_thread(mddev->thread);
+				}
 				md_new_event(mddev);
 			}
 		}
@@ -2626,6 +2657,7 @@ state_store(struct md_rdev *rdev, const
 		err = 0;
 	} else if (cmd_match(buf, "-blocked")) {
 		if (!test_bit(Faulty, &rdev->flags) &&
+		    !test_bit(ExternalBbl, &rdev->flags) &&
 		    rdev->badblocks.unacked_exist) {
 			/* metadata handler doesn't understand badblocks,
 			 * so we need to fail the device
@@ -2642,6 +2674,12 @@ state_store(struct md_rdev *rdev, const
 	} else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
 		set_bit(In_sync, &rdev->flags);
 		err = 0;
+	} else if (cmd_match(buf, "failfast")) {
+		set_bit(FailFast, &rdev->flags);
+		err = 0;
+	} else if (cmd_match(buf, "-failfast")) {
+		clear_bit(FailFast, &rdev->flags);
+		err = 0;
 	} else if (cmd_match(buf, "-insync") && rdev->raid_disk >= 0 &&
 		   !test_bit(Journal, &rdev->flags)) {
 		if (rdev->mddev->pers == NULL) {
@@ -2708,6 +2746,13 @@ state_store(struct md_rdev *rdev, const
 			}
 		} else
 			err = -EBUSY;
+	} else if (cmd_match(buf, "external_bbl") && (rdev->mddev->external)) {
+		set_bit(ExternalBbl, &rdev->flags);
+		rdev->badblocks.shift = 0;
+		err = 0;
+	} else if (cmd_match(buf, "-external_bbl") && (rdev->mddev->external)) {
+		clear_bit(ExternalBbl, &rdev->flags);
+		err = 0;
 	}
 	if (!err)
 		sysfs_notify_dirent_safe(rdev->sysfs_state);
@@ -3211,10 +3256,8 @@ static struct md_rdev *md_import_device(
 	sector_t size;
 
 	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
-	if (!rdev) {
-		printk(KERN_ERR "md: could not alloc mem for new device!\n");
+	if (!rdev)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	err = md_rdev_init(rdev);
 	if (err)
@@ -3231,8 +3274,7 @@ static struct md_rdev *md_import_device(
 
 	size = i_size_read(rdev->bdev->bd_inode) >> BLOCK_SIZE_BITS;
 	if (!size) {
-		printk(KERN_WARNING
-			"md: %s has zero or unknown size, marking faulty!\n",
+		pr_warn("md: %s has zero or unknown size, marking faulty!\n",
 			bdevname(rdev->bdev,b));
 		err = -EINVAL;
 		goto abort_free;
@@ -3242,16 +3284,13 @@ static struct md_rdev *md_import_device(
 		err = super_types[super_format].
 			load_super(rdev, NULL, super_minor);
 		if (err == -EINVAL) {
-			printk(KERN_WARNING
-				"md: %s does not have a valid v%d.%d "
-			       "superblock, not importing!\n",
+			pr_warn("md: %s does not have a valid v%d.%d superblock, not importing!\n",
 				bdevname(rdev->bdev,b),
-			       super_format, super_minor);
+				super_format, super_minor);
 			goto abort_free;
 		}
 		if (err < 0) {
-			printk(KERN_WARNING
-				"md: could not read %s's sb, not importing!\n",
+			pr_warn("md: could not read %s's sb, not importing!\n",
 				bdevname(rdev->bdev,b));
 			goto abort_free;
 		}
@@ -3287,9 +3326,7 @@ static void analyze_sbs(struct mddev *md
 		case 0:
 			break;
 		default:
-			printk( KERN_ERR \
-				"md: fatal superblock inconsistency in %s"
-				" -- removing from array\n",
+			pr_warn("md: fatal superblock inconsistency in %s -- removing from array\n",
 				bdevname(rdev->bdev,b));
 			md_kick_rdev_from_array(rdev);
 		}
@@ -3302,18 +3339,16 @@ static void analyze_sbs(struct mddev *md
 		if (mddev->max_disks &&
 		    (rdev->desc_nr >= mddev->max_disks ||
 		     i > mddev->max_disks)) {
-			printk(KERN_WARNING
-			       "md: %s: %s: only %d devices permitted\n",
-			       mdname(mddev), bdevname(rdev->bdev, b),
-			       mddev->max_disks);
+			pr_warn("md: %s: %s: only %d devices permitted\n",
+				mdname(mddev), bdevname(rdev->bdev, b),
+				mddev->max_disks);
 			md_kick_rdev_from_array(rdev);
 			continue;
 		}
 		if (rdev != freshest) {
 			if (super_types[mddev->major_version].
 			    validate_super(mddev, rdev)) {
-				printk(KERN_WARNING "md: kicking non-fresh %s"
-					" from array!\n",
+				pr_warn("md: kicking non-fresh %s from array!\n",
 					bdevname(rdev->bdev,b));
 				md_kick_rdev_from_array(rdev);
 				continue;
@@ -3384,7 +3419,7 @@ safe_delay_store(struct mddev *mddev, co
 	unsigned long msec;
 
 	if (mddev_is_clustered(mddev)) {
-		pr_info("md: Safemode is disabled for clustered mode\n");
+		pr_warn("md: Safemode is disabled for clustered mode\n");
 		return -EINVAL;
 	}
 
@@ -3472,8 +3507,8 @@ level_store(struct mddev *mddev, const c
 
 	rv = -EINVAL;
 	if (!mddev->pers->quiesce) {
-		printk(KERN_WARNING "md: %s: %s does not support online personality change\n",
-		       mdname(mddev), mddev->pers->name);
+		pr_warn("md: %s: %s does not support online personality change\n",
+			mdname(mddev), mddev->pers->name);
 		goto out_unlock;
 	}
 
@@ -3491,7 +3526,7 @@ level_store(struct mddev *mddev, const c
 	pers = find_pers(level, clevel);
 	if (!pers || !try_module_get(pers->owner)) {
 		spin_unlock(&pers_lock);
-		printk(KERN_WARNING "md: personality %s not loaded\n", clevel);
+		pr_warn("md: personality %s not loaded\n", clevel);
 		rv = -EINVAL;
 		goto out_unlock;
 	}
@@ -3505,8 +3540,8 @@ level_store(struct mddev *mddev, const c
 	}
 	if (!pers->takeover) {
 		module_put(pers->owner);
-		printk(KERN_WARNING "md: %s: %s does not support personality takeover\n",
-		       mdname(mddev), clevel);
+		pr_warn("md: %s: %s does not support personality takeover\n",
+			mdname(mddev), clevel);
 		rv = -EINVAL;
 		goto out_unlock;
 	}
@@ -3526,8 +3561,8 @@ level_store(struct mddev *mddev, const c
 		mddev->delta_disks = 0;
 		mddev->reshape_backwards = 0;
 		module_put(pers->owner);
-		printk(KERN_WARNING "md: %s: %s would not accept array\n",
-		       mdname(mddev), clevel);
+		pr_warn("md: %s: %s would not accept array\n",
+			mdname(mddev), clevel);
 		rv = PTR_ERR(priv);
 		goto out_unlock;
 	}
@@ -3570,9 +3605,8 @@ level_store(struct mddev *mddev, const c
 	    pers->sync_request != NULL) {
 		/* need to add the md_redundancy_group */
 		if (sysfs_create_group(&mddev->kobj, &md_redundancy_group))
-			printk(KERN_WARNING
-			       "md: cannot register extra attributes for %s\n",
-			       mdname(mddev));
+			pr_warn("md: cannot register extra attributes for %s\n",
+				mdname(mddev));
 		mddev->sysfs_action = sysfs_get_dirent(mddev->kobj.sd, "sync_action");
 	}
 	if (oldpers->sync_request != NULL &&
@@ -3603,9 +3637,8 @@ level_store(struct mddev *mddev, const c
 			clear_bit(In_sync, &rdev->flags);
 		else {
 			if (sysfs_link_rdev(mddev, rdev))
-				printk(KERN_WARNING "md: cannot register rd%d"
-				       " for %s after level change\n",
-				       rdev->raid_disk, mdname(mddev));
+				pr_warn("md: cannot register rd%d for %s after level change\n",
+					rdev->raid_disk, mdname(mddev));
 		}
 	}
 
@@ -3618,7 +3651,7 @@ level_store(struct mddev *mddev, const c
 	}
 	blk_set_stacking_limits(&mddev->queue->limits);
 	pers->run(mddev);
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 	mddev_resume(mddev);
 	if (!mddev->thread)
 		md_update_sb(mddev, 1);
@@ -3813,7 +3846,7 @@ resync_start_store(struct mddev *mddev,
 	if (!err) {
 		mddev->recovery_cp = n;
 		if (mddev->pers)
-			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+			set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
 	}
 	mddev_unlock(mddev);
 	return err ?: len;
@@ -3887,7 +3920,7 @@ array_state_show(struct mddev *mddev, ch
 			st = read_auto;
 			break;
 		case 0:
-			if (test_bit(MD_CHANGE_PENDING, &mddev->flags))
+			if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
 				st = write_pending;
 			else if (mddev->in_sync)
 				st = clean;
@@ -3925,7 +3958,8 @@ array_state_store(struct mddev *mddev, c
 		spin_lock(&mddev->lock);
 		if (st == active) {
 			restart_array(mddev);
-			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+			clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
+			md_wakeup_thread(mddev->thread);
 			wake_up(&mddev->sb_wait);
 			err = 0;
 		} else /* st == clean */ {
@@ -3935,7 +3969,7 @@ array_state_store(struct mddev *mddev, c
 					mddev->in_sync = 1;
 					if (mddev->safemode == 1)
 						mddev->safemode = 0;
-					set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+					set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
 				}
 				err = 0;
 			} else
@@ -4001,7 +4035,7 @@ array_state_store(struct mddev *mddev, c
 					mddev->in_sync = 1;
 					if (mddev->safemode == 1)
 						mddev->safemode = 0;
-					set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+					set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
 				}
 				err = 0;
 			} else
@@ -4015,7 +4049,7 @@ array_state_store(struct mddev *mddev, c
 			err = restart_array(mddev);
 			if (err)
 				break;
-			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+			clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
 			wake_up(&mddev->sb_wait);
 			err = 0;
 		} else {
@@ -5071,13 +5105,13 @@ static int md_alloc(dev_t dev, char *nam
 		/* This isn't possible, but as kobject_init_and_add is marked
 		 * __must_check, we must do something with the result
 		 */
-		printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
-		       disk->disk_name);
+		pr_debug("md: cannot register %s/md - name in use\n",
+			 disk->disk_name);
 		error = 0;
 	}
 	if (mddev->kobj.sd &&
 	    sysfs_create_group(&mddev->kobj, &md_bitmap_group))
-		printk(KERN_DEBUG "pointless warning\n");
+		pr_debug("pointless warning\n");
 	mutex_unlock(&mddev->open_mutex);
  abort:
 	mutex_unlock(&disks_mutex);
@@ -5179,15 +5213,15 @@ int md_run(struct mddev *mddev)
 			if (mddev->dev_sectors &&
 			    rdev->data_offset + mddev->dev_sectors
 			    > rdev->sb_start) {
-				printk("md: %s: data overlaps metadata\n",
-				       mdname(mddev));
+				pr_warn("md: %s: data overlaps metadata\n",
+					mdname(mddev));
 				return -EINVAL;
 			}
 		} else {
 			if (rdev->sb_start + rdev->sb_size/512
 			    > rdev->data_offset) {
-				printk("md: %s: metadata overlaps data\n",
-				       mdname(mddev));
+				pr_warn("md: %s: metadata overlaps data\n",
+					mdname(mddev));
 				return -EINVAL;
 			}
 		}
@@ -5202,11 +5236,11 @@ int md_run(struct mddev *mddev)
 	if (!pers || !try_module_get(pers->owner)) {
 		spin_unlock(&pers_lock);
 		if (mddev->level != LEVEL_NONE)
-			printk(KERN_WARNING "md: personality for level %d is not loaded!\n",
-			       mddev->level);
+			pr_warn("md: personality for level %d is not loaded!\n",
+				mddev->level);
 		else
-			printk(KERN_WARNING "md: personality for level %s is not loaded!\n",
-			       mddev->clevel);
+			pr_warn("md: personality for level %s is not loaded!\n",
+				mddev->clevel);
 		return -EINVAL;
 	}
 	spin_unlock(&pers_lock);
@@ -5236,21 +5270,16 @@ int md_run(struct mddev *mddev)
 				if (rdev < rdev2 &&
 				    rdev->bdev->bd_contains ==
 				    rdev2->bdev->bd_contains) {
-					printk(KERN_WARNING
-					       "%s: WARNING: %s appears to be"
-					       " on the same physical disk as"
-					       " %s.\n",
-					       mdname(mddev),
-					       bdevname(rdev->bdev,b),
-					       bdevname(rdev2->bdev,b2));
+					pr_warn("%s: WARNING: %s appears to be on the same physical disk as %s.\n",
+						mdname(mddev),
+						bdevname(rdev->bdev,b),
+						bdevname(rdev2->bdev,b2));
 					warned = 1;
 				}
 			}
 
 		if (warned)
-			printk(KERN_WARNING
-			       "True protection against single-disk"
-			       " failure might be compromised.\n");
+			pr_warn("True protection against single-disk failure might be compromised.\n");
 	}
 
 	mddev->recovery = 0;
@@ -5262,16 +5291,21 @@ int md_run(struct mddev *mddev)
 	if (start_readonly && mddev->ro == 0)
 		mddev->ro = 2; /* read-only, but switch on first write */
 
+	/*
+	 * NOTE: some pers->run(), for example r5l_recovery_log(), wakes
+	 * up mddev->thread. It is important to initialize critical
+	 * resources for mddev->thread BEFORE calling pers->run().
+	 */
 	err = pers->run(mddev);
 	if (err)
-		printk(KERN_ERR "md: pers->run() failed ...\n");
+		pr_warn("md: pers->run() failed ...\n");
 	else if (pers->size(mddev, 0, 0) < mddev->array_sectors) {
-		WARN_ONCE(!mddev->external_size, "%s: default size too small,"
-			  " but 'external_size' not in effect?\n", __func__);
-		printk(KERN_ERR
-		       "md: invalid array_size %llu > default size %llu\n",
-		       (unsigned long long)mddev->array_sectors / 2,
-		       (unsigned long long)pers->size(mddev, 0, 0) / 2);
+		WARN_ONCE(!mddev->external_size,
+			  "%s: default size too small, but 'external_size' not in effect?\n",
+			  __func__);
+		pr_warn("md: invalid array_size %llu > default size %llu\n",
+			(unsigned long long)mddev->array_sectors / 2,
+			(unsigned long long)pers->size(mddev, 0, 0) / 2);
 		err = -EINVAL;
 	}
 	if (err == 0 && pers->sync_request &&
@@ -5281,8 +5315,8 @@ int md_run(struct mddev *mddev)
 		bitmap = bitmap_create(mddev, -1);
 		if (IS_ERR(bitmap)) {
 			err = PTR_ERR(bitmap);
-			printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
-			       mdname(mddev), err);
+			pr_warn("%s: failed to create bitmap (%d)\n",
+				mdname(mddev), err);
 		} else
 			mddev->bitmap = bitmap;
 
@@ -5318,9 +5352,8 @@ int md_run(struct mddev *mddev)
 	if (pers->sync_request) {
 		if (mddev->kobj.sd &&
 		    sysfs_create_group(&mddev->kobj, &md_redundancy_group))
-			printk(KERN_WARNING
-			       "md: cannot register extra attributes for %s\n",
-			       mdname(mddev));
+			pr_warn("md: cannot register extra attributes for %s\n",
+				mdname(mddev));
 		mddev->sysfs_action = sysfs_get_dirent_safe(mddev->kobj.sd, "sync_action");
 	} else if (mddev->ro == 2) /* auto-readonly not meaningful */
 		mddev->ro = 0;
@@ -5350,7 +5383,7 @@ int md_run(struct mddev *mddev)
 		set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 
-	if (mddev->flags & MD_UPDATE_SB_FLAGS)
+	if (mddev->sb_flags)
 		md_update_sb(mddev, 0);
 
 	md_new_event(mddev);
@@ -5421,8 +5454,7 @@ static int restart_array(struct mddev *m
 	mddev->safemode = 0;
 	mddev->ro = 0;
 	set_disk_ro(disk, 0);
-	printk(KERN_INFO "md: %s switched to read-write mode.\n",
-		mdname(mddev));
+	pr_debug("md: %s switched to read-write mode.\n", mdname(mddev));
 	/* Kick recovery or resync if necessary */
 	set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 	md_wakeup_thread(mddev->thread);
@@ -5446,6 +5478,7 @@ static void md_clean(struct mddev *mddev
 	mddev->level = LEVEL_NONE;
 	mddev->clevel[0] = 0;
 	mddev->flags = 0;
+	mddev->sb_flags = 0;
 	mddev->ro = 0;
 	mddev->metadata_type[0] = 0;
 	mddev->chunk_sectors = 0;
@@ -5490,12 +5523,15 @@ static void __md_stop_writes(struct mdde
 
 	del_timer_sync(&mddev->safemode_timer);
 
+	if (mddev->pers && mddev->pers->quiesce) {
+		mddev->pers->quiesce(mddev, 1);
+		mddev->pers->quiesce(mddev, 0);
+	}
 	bitmap_flush(mddev);
-	md_super_wait(mddev);
 
 	if (mddev->ro == 0 &&
 	    ((!mddev->in_sync && !mddev_is_clustered(mddev)) ||
-	     (mddev->flags & MD_UPDATE_SB_FLAGS))) {
+	     mddev->sb_flags)) {
 		/* mark array as shutdown cleanly */
 		if (!mddev_is_clustered(mddev))
 			mddev->in_sync = 1;
@@ -5516,8 +5552,8 @@ static void mddev_detach(struct mddev *m
 	struct bitmap *bitmap = mddev->bitmap;
 	/* wait for behind writes to complete */
 	if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
-		printk(KERN_INFO "md:%s: behind writes in progress - waiting to stop.\n",
-		       mdname(mddev));
+		pr_debug("md:%s: behind writes in progress - waiting to stop.\n",
+			 mdname(mddev));
 		/* need to kick something here to make sure I/O goes? */
 		wait_event(bitmap->behind_wait,
 			   atomic_read(&bitmap->behind_writes) == 0);
@@ -5578,20 +5614,20 @@ static int md_set_readonly(struct mddev
 		 * which will now never happen */
 		wake_up_process(mddev->sync_thread->tsk);
 
-	if (mddev->external && test_bit(MD_CHANGE_PENDING, &mddev->flags))
+	if (mddev->external && test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
 		return -EBUSY;
 	mddev_unlock(mddev);
 	wait_event(resync_wait, !test_bit(MD_RECOVERY_RUNNING,
 					  &mddev->recovery));
 	wait_event(mddev->sb_wait,
-		   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
+		   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
 	mddev_lock_nointr(mddev);
 
 	mutex_lock(&mddev->open_mutex);
 	if ((mddev->pers && atomic_read(&mddev->openers) > !!bdev) ||
 	    mddev->sync_thread ||
 	    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
-		printk("md: %s still in use.\n",mdname(mddev));
+		pr_warn("md: %s still in use.\n",mdname(mddev));
 		if (did_freeze) {
 			clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -5653,7 +5689,7 @@ static int do_md_stop(struct mddev *mdde
 	    mddev->sysfs_active ||
 	    mddev->sync_thread ||
 	    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
-		printk("md: %s still in use.\n",mdname(mddev));
+		pr_warn("md: %s still in use.\n",mdname(mddev));
 		mutex_unlock(&mddev->open_mutex);
 		if (did_freeze) {
 			clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -5690,7 +5726,7 @@ static int do_md_stop(struct mddev *mdde
 	 * Free resources if final stop
 	 */
 	if (mode == 0) {
-		printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
+		pr_info("md: %s stopped.\n", mdname(mddev));
 
 		bitmap_destroy(mddev);
 		if (mddev->bitmap_info.file) {
@@ -5722,17 +5758,17 @@ static void autorun_array(struct mddev *
 	if (list_empty(&mddev->disks))
 		return;
 
-	printk(KERN_INFO "md: running: ");
+	pr_info("md: running: ");
 
 	rdev_for_each(rdev, mddev) {
 		char b[BDEVNAME_SIZE];
-		printk("<%s>", bdevname(rdev->bdev,b));
+		pr_cont("<%s>", bdevname(rdev->bdev,b));
 	}
-	printk("\n");
+	pr_cont("\n");
 
 	err = do_md_run(mddev);
 	if (err) {
-		printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
+		pr_warn("md: do_md_run() returned %d\n", err);
 		do_md_stop(mddev, 0, NULL);
 	}
 }
@@ -5755,7 +5791,7 @@ static void autorun_devices(int part)
 	struct mddev *mddev;
 	char b[BDEVNAME_SIZE];
 
-	printk(KERN_INFO "md: autorun ...\n");
+	pr_info("md: autorun ...\n");
 	while (!list_empty(&pending_raid_disks)) {
 		int unit;
 		dev_t dev;
@@ -5763,13 +5799,12 @@ static void autorun_devices(int part)
 		rdev0 = list_entry(pending_raid_disks.next,
 					 struct md_rdev, same_set);
 
-		printk(KERN_INFO "md: considering %s ...\n",
-			bdevname(rdev0->bdev,b));
+		pr_debug("md: considering %s ...\n", bdevname(rdev0->bdev,b));
 		INIT_LIST_HEAD(&candidates);
 		rdev_for_each_list(rdev, tmp, &pending_raid_disks)
 			if (super_90_load(rdev, rdev0, 0) >= 0) {
-				printk(KERN_INFO "md:  adding %s ...\n",
-					bdevname(rdev->bdev,b));
+				pr_debug("md:  adding %s ...\n",
+					 bdevname(rdev->bdev,b));
 				list_move(&rdev->same_set, &candidates);
 			}
 		/*
@@ -5786,8 +5821,8 @@ static void autorun_devices(int part)
 			unit = MINOR(dev);
 		}
 		if (rdev0->preferred_minor != unit) {
-			printk(KERN_INFO "md: unit number in %s is bad: %d\n",
-			       bdevname(rdev0->bdev, b), rdev0->preferred_minor);
+			pr_warn("md: unit number in %s is bad: %d\n",
+				bdevname(rdev0->bdev, b), rdev0->preferred_minor);
 			break;
 		}
 
@@ -5796,21 +5831,17 @@ static void autorun_devices(int part)
 		if (!mddev || !mddev->gendisk) {
 			if (mddev)
 				mddev_put(mddev);
-			printk(KERN_ERR
-				"md: cannot allocate memory for md drive.\n");
 			break;
 		}
 		if (mddev_lock(mddev))
-			printk(KERN_WARNING "md: %s locked, cannot run\n",
-			       mdname(mddev));
+			pr_warn("md: %s locked, cannot run\n", mdname(mddev));
 		else if (mddev->raid_disks || mddev->major_version
 			 || !list_empty(&mddev->disks)) {
-			printk(KERN_WARNING
-				"md: %s already running, cannot run %s\n",
+			pr_warn("md: %s already running, cannot run %s\n",
 				mdname(mddev), bdevname(rdev0->bdev,b));
 			mddev_unlock(mddev);
 		} else {
-			printk(KERN_INFO "md: created %s\n", mdname(mddev));
+			pr_debug("md: created %s\n", mdname(mddev));
 			mddev->persistent = 1;
 			rdev_for_each_list(rdev, tmp, &candidates) {
 				list_del_init(&rdev->same_set);
@@ -5829,7 +5860,7 @@ static void autorun_devices(int part)
 		}
 		mddev_put(mddev);
 	}
-	printk(KERN_INFO "md: ... autorun DONE.\n");
+	pr_info("md: ... autorun DONE.\n");
 }
 #endif /* !MODULE */
 
@@ -5964,6 +5995,8 @@ static int get_disk_info(struct mddev *m
 			info.state |= (1<<MD_DISK_JOURNAL);
 		if (test_bit(WriteMostly, &rdev->flags))
 			info.state |= (1<<MD_DISK_WRITEMOSTLY);
+		if (test_bit(FailFast, &rdev->flags))
+			info.state |= (1<<MD_DISK_FAILFAST);
 	} else {
 		info.major = info.minor = 0;
 		info.raid_disk = -1;
@@ -5985,8 +6018,8 @@ static int add_new_disk(struct mddev *md
 
 	if (mddev_is_clustered(mddev) &&
 		!(info->state & ((1 << MD_DISK_CLUSTER_ADD) | (1 << MD_DISK_CANDIDATE)))) {
-		pr_err("%s: Cannot add to clustered mddev.\n",
-			       mdname(mddev));
+		pr_warn("%s: Cannot add to clustered mddev.\n",
+			mdname(mddev));
 		return -EINVAL;
 	}
 
@@ -5998,8 +6031,7 @@ static int add_new_disk(struct mddev *md
 		/* expecting a device which has a superblock */
 		rdev = md_import_device(dev, mddev->major_version, mddev->minor_version);
 		if (IS_ERR(rdev)) {
-			printk(KERN_WARNING
-				"md: md_import_device returned %ld\n",
+			pr_warn("md: md_import_device returned %ld\n",
 				PTR_ERR(rdev));
 			return PTR_ERR(rdev);
 		}
@@ -6010,8 +6042,7 @@ static int add_new_disk(struct mddev *md
 			err = super_types[mddev->major_version]
 				.load_super(rdev, rdev0, mddev->minor_version);
 			if (err < 0) {
-				printk(KERN_WARNING
-					"md: %s has different UUID to %s\n",
+				pr_warn("md: %s has different UUID to %s\n",
 					bdevname(rdev->bdev,b),
 					bdevname(rdev0->bdev,b2));
 				export_rdev(rdev);
@@ -6032,9 +6063,8 @@ static int add_new_disk(struct mddev *md
 	if (mddev->pers) {
 		int err;
 		if (!mddev->pers->hot_add_disk) {
-			printk(KERN_WARNING
-				"%s: personality does not support diskops!\n",
-			       mdname(mddev));
+			pr_warn("%s: personality does not support diskops!\n",
+				mdname(mddev));
 			return -EINVAL;
 		}
 		if (mddev->persistent)
@@ -6043,8 +6073,7 @@ static int add_new_disk(struct mddev *md
 		else
 			rdev = md_import_device(dev, -1, -1);
 		if (IS_ERR(rdev)) {
-			printk(KERN_WARNING
-				"md: md_import_device returned %ld\n",
+			pr_warn("md: md_import_device returned %ld\n",
 				PTR_ERR(rdev));
 			return PTR_ERR(rdev);
 		}
@@ -6075,6 +6104,10 @@ static int add_new_disk(struct mddev *md
 			set_bit(WriteMostly, &rdev->flags);
 		else
 			clear_bit(WriteMostly, &rdev->flags);
+		if (info->state & (1<<MD_DISK_FAILFAST))
+			set_bit(FailFast, &rdev->flags);
+		else
+			clear_bit(FailFast, &rdev->flags);
 
 		if (info->state & (1<<MD_DISK_JOURNAL)) {
 			struct md_rdev *rdev2;
@@ -6140,8 +6173,7 @@ static int add_new_disk(struct mddev *md
 	 * for major_version==0 superblocks
 	 */
 	if (mddev->major_version != 0) {
-		printk(KERN_WARNING "%s: ADD_NEW_DISK not supported\n",
-		       mdname(mddev));
+		pr_warn("%s: ADD_NEW_DISK not supported\n", mdname(mddev));
 		return -EINVAL;
 	}
 
@@ -6149,8 +6181,7 @@ static int add_new_disk(struct mddev *md
 		int err;
 		rdev = md_import_device(dev, -1, 0);
 		if (IS_ERR(rdev)) {
-			printk(KERN_WARNING
-				"md: error, md_import_device() returned %ld\n",
+			pr_warn("md: error, md_import_device() returned %ld\n",
 				PTR_ERR(rdev));
 			return PTR_ERR(rdev);
 		}
@@ -6166,9 +6197,11 @@ static int add_new_disk(struct mddev *md
 
 		if (info->state & (1<<MD_DISK_WRITEMOSTLY))
 			set_bit(WriteMostly, &rdev->flags);
+		if (info->state & (1<<MD_DISK_FAILFAST))
+			set_bit(FailFast, &rdev->flags);
 
 		if (!mddev->persistent) {
-			printk(KERN_INFO "md: nonpersistent superblock ...\n");
+			pr_debug("md: nonpersistent superblock ...\n");
 			rdev->sb_start = i_size_read(rdev->bdev->bd_inode) / 512;
 		} else
 			rdev->sb_start = calc_dev_sboffset(rdev);
@@ -6207,13 +6240,17 @@ kick_rdev:
 		md_cluster_ops->remove_disk(mddev, rdev);
 
 	md_kick_rdev_from_array(rdev);
-	md_update_sb(mddev, 1);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
+	if (mddev->thread)
+		md_wakeup_thread(mddev->thread);
+	else
+		md_update_sb(mddev, 1);
 	md_new_event(mddev);
 
 	return 0;
 busy:
-	printk(KERN_WARNING "md: cannot remove active disk %s from %s ...\n",
-		bdevname(rdev->bdev,b), mdname(mddev));
+	pr_debug("md: cannot remove active disk %s from %s ...\n",
+		 bdevname(rdev->bdev,b), mdname(mddev));
 	return -EBUSY;
 }
 
@@ -6227,22 +6264,19 @@ static int hot_add_disk(struct mddev *md
 		return -ENODEV;
 
 	if (mddev->major_version != 0) {
-		printk(KERN_WARNING "%s: HOT_ADD may only be used with"
-			" version-0 superblocks.\n",
+		pr_warn("%s: HOT_ADD may only be used with version-0 superblocks.\n",
 			mdname(mddev));
 		return -EINVAL;
 	}
 	if (!mddev->pers->hot_add_disk) {
-		printk(KERN_WARNING
-			"%s: personality does not support diskops!\n",
+		pr_warn("%s: personality does not support diskops!\n",
 			mdname(mddev));
 		return -EINVAL;
 	}
 
 	rdev = md_import_device(dev, -1, 0);
 	if (IS_ERR(rdev)) {
-		printk(KERN_WARNING
-			"md: error, md_import_device() returned %ld\n",
+		pr_warn("md: error, md_import_device() returned %ld\n",
 			PTR_ERR(rdev));
 		return -EINVAL;
 	}
@@ -6255,8 +6289,7 @@ static int hot_add_disk(struct mddev *md
 	rdev->sectors = rdev->sb_start;
 
 	if (test_bit(Faulty, &rdev->flags)) {
-		printk(KERN_WARNING
-			"md: can not hot-add faulty %s disk to %s!\n",
+		pr_warn("md: can not hot-add faulty %s disk to %s!\n",
 			bdevname(rdev->bdev,b), mdname(mddev));
 		err = -EINVAL;
 		goto abort_export;
@@ -6276,7 +6309,9 @@ static int hot_add_disk(struct mddev *md
 
 	rdev->raid_disk = -1;
 
-	md_update_sb(mddev, 1);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
+	if (!mddev->thread)
+		md_update_sb(mddev, 1);
 	/*
 	 * Kick recovery, maybe this spare has to be added to the
 	 * array immediately.
@@ -6312,23 +6347,23 @@ static int set_bitmap_file(struct mddev
 		f = fget(fd);
 
 		if (f == NULL) {
-			printk(KERN_ERR "%s: error: failed to get bitmap file\n",
-			       mdname(mddev));
+			pr_warn("%s: error: failed to get bitmap file\n",
+				mdname(mddev));
 			return -EBADF;
 		}
 
 		inode = f->f_mapping->host;
 		if (!S_ISREG(inode->i_mode)) {
-			printk(KERN_ERR "%s: error: bitmap file must be a regular file\n",
-			       mdname(mddev));
+			pr_warn("%s: error: bitmap file must be a regular file\n",
+				mdname(mddev));
 			err = -EBADF;
 		} else if (!(f->f_mode & FMODE_WRITE)) {
-			printk(KERN_ERR "%s: error: bitmap file must open for write\n",
-			       mdname(mddev));
+			pr_warn("%s: error: bitmap file must open for write\n",
+				mdname(mddev));
 			err = -EBADF;
 		} else if (atomic_read(&inode->i_writecount) != 1) {
-			printk(KERN_ERR "%s: error: bitmap file is already in use\n",
-			       mdname(mddev));
+			pr_warn("%s: error: bitmap file is already in use\n",
+				mdname(mddev));
 			err = -EBUSY;
 		}
 		if (err) {
@@ -6393,8 +6428,7 @@ static int set_array_info(struct mddev *
 		    info->major_version >= ARRAY_SIZE(super_types) ||
 		    super_types[info->major_version].name == NULL) {
 			/* maybe try to auto-load a module? */
-			printk(KERN_INFO
-				"md: superblock version %d not known\n",
+			pr_warn("md: superblock version %d not known\n",
 				info->major_version);
 			return -EINVAL;
 		}
@@ -6432,9 +6466,11 @@ static int set_array_info(struct mddev *
 
 	mddev->max_disks     = MD_SB_DISKS;
 
-	if (mddev->persistent)
+	if (mddev->persistent) {
 		mddev->flags         = 0;
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		mddev->sb_flags         = 0;
+	}
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 
 	mddev->bitmap_info.default_offset = MD_SB_BYTES >> 9;
 	mddev->bitmap_info.default_space = 64*2 - (MD_SB_BYTES >> 9);
@@ -6660,8 +6696,7 @@ static int update_array_info(struct mdde
 			if (mddev->bitmap_info.nodes) {
 				/* hold PW on all the bitmap lock */
 				if (md_cluster_ops->lock_all_bitmaps(mddev) <= 0) {
-					printk("md: can't change bitmap to none since the"
-					       " array is in use by more than one node\n");
+					pr_warn("md: can't change bitmap to none since the array is in use by more than one node\n");
 					rv = -EPERM;
 					md_cluster_ops->unlock_all_bitmaps(mddev);
 					goto err;
@@ -6829,7 +6864,7 @@ static int md_ioctl(struct block_device
 		/* need to ensure recovery thread has run */
 		wait_event_interruptible_timeout(mddev->sb_wait,
 						 !test_bit(MD_RECOVERY_NEEDED,
-							   &mddev->flags),
+							   &mddev->recovery),
 						 msecs_to_jiffies(5000));
 	if (cmd == STOP_ARRAY || cmd == STOP_ARRAY_RO) {
 		/* Need to flush page cache, and ensure no-one else opens
@@ -6847,9 +6882,8 @@ static int md_ioctl(struct block_device
 	}
 	err = mddev_lock(mddev);
 	if (err) {
-		printk(KERN_INFO
-			"md: ioctl lock interrupted, reason %d, cmd %d\n",
-			err, cmd);
+		pr_debug("md: ioctl lock interrupted, reason %d, cmd %d\n",
+			 err, cmd);
 		goto out;
 	}
 
@@ -6864,30 +6898,24 @@ static int md_ioctl(struct block_device
 		if (mddev->pers) {
 			err = update_array_info(mddev, &info);
 			if (err) {
-				printk(KERN_WARNING "md: couldn't update"
-				       " array info. %d\n", err);
+				pr_warn("md: couldn't update array info. %d\n", err);
 				goto unlock;
 			}
 			goto unlock;
 		}
 		if (!list_empty(&mddev->disks)) {
-			printk(KERN_WARNING
-			       "md: array %s already has disks!\n",
-			       mdname(mddev));
+			pr_warn("md: array %s already has disks!\n", mdname(mddev));
 			err = -EBUSY;
 			goto unlock;
 		}
 		if (mddev->raid_disks) {
-			printk(KERN_WARNING
-			       "md: array %s already initialised!\n",
-			       mdname(mddev));
+			pr_warn("md: array %s already initialised!\n", mdname(mddev));
 			err = -EBUSY;
 			goto unlock;
 		}
 		err = set_array_info(mddev, &info);
 		if (err) {
-			printk(KERN_WARNING "md: couldn't set"
-			       " array info. %d\n", err);
+			pr_warn("md: couldn't set array info. %d\n", err);
 			goto unlock;
 		}
 		goto unlock;
@@ -6987,11 +7015,11 @@ static int md_ioctl(struct block_device
 			/* If a device failed while we were read-only, we
 			 * need to make sure the metadata is updated now.
 			 */
-			if (test_bit(MD_CHANGE_DEVS, &mddev->flags)) {
+			if (test_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags)) {
 				mddev_unlock(mddev);
 				wait_event(mddev->sb_wait,
-					   !test_bit(MD_CHANGE_DEVS, &mddev->flags) &&
-					   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
+					   !test_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags) &&
+					   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
 				mddev_lock_nointr(mddev);
 			}
 		} else {
@@ -7092,7 +7120,8 @@ static int md_open(struct block_device *
 
 	if (test_bit(MD_CLOSING, &mddev->flags)) {
 		mutex_unlock(&mddev->open_mutex);
-		return -ENODEV;
+		err = -ENODEV;
+		goto out;
 	}
 
 	err = 0;
@@ -7101,6 +7130,8 @@ static int md_open(struct block_device *
 
 	check_disk_change(bdev);
  out:
+	if (err)
+		mddev_put(mddev);
 	return err;
 }
 
@@ -7171,10 +7202,12 @@ static int md_thread(void *arg)
 		wait_event_interruptible_timeout
 			(thread->wqueue,
 			 test_bit(THREAD_WAKEUP, &thread->flags)
-			 || kthread_should_stop(),
+			 || kthread_should_stop() || kthread_should_park(),
 			 thread->timeout);
 
 		clear_bit(THREAD_WAKEUP, &thread->flags);
+		if (kthread_should_park())
+			kthread_parkme();
 		if (!kthread_should_stop())
 			thread->run(thread);
 	}
@@ -7588,8 +7621,8 @@ static const struct file_operations md_s
 
 int register_md_personality(struct md_personality *p)
 {
-	printk(KERN_INFO "md: %s personality registered for level %d\n",
-						p->name, p->level);
+	pr_debug("md: %s personality registered for level %d\n",
+		 p->name, p->level);
 	spin_lock(&pers_lock);
 	list_add_tail(&p->list, &pers_list);
 	spin_unlock(&pers_lock);
@@ -7599,7 +7632,7 @@ EXPORT_SYMBOL(register_md_personality);
 
 int unregister_md_personality(struct md_personality *p)
 {
-	printk(KERN_INFO "md: %s personality unregistered\n", p->name);
+	pr_debug("md: %s personality unregistered\n", p->name);
 	spin_lock(&pers_lock);
 	list_del_init(&p->list);
 	spin_unlock(&pers_lock);
@@ -7639,7 +7672,7 @@ int md_setup_cluster(struct mddev *mddev
 	spin_lock(&pers_lock);
 	/* ensure module won't be unloaded */
 	if (!md_cluster_ops || !try_module_get(md_cluster_mod)) {
-		pr_err("can't find md-cluster module or get it's reference.\n");
+		pr_warn("can't find md-cluster module or get it's reference.\n");
 		spin_unlock(&pers_lock);
 		return -ENOENT;
 	}
@@ -7741,8 +7774,8 @@ void md_write_start(struct mddev *mddev,
 		spin_lock(&mddev->lock);
 		if (mddev->in_sync) {
 			mddev->in_sync = 0;
-			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
-			set_bit(MD_CHANGE_PENDING, &mddev->flags);
+			set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
+			set_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
 			md_wakeup_thread(mddev->thread);
 			did_change = 1;
 		}
@@ -7751,7 +7784,7 @@ void md_write_start(struct mddev *mddev,
 	if (did_change)
 		sysfs_notify_dirent_safe(mddev->sysfs_state);
 	wait_event(mddev->sb_wait,
-		   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
+		   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
 }
 EXPORT_SYMBOL(md_write_start);
 
@@ -7772,7 +7805,7 @@ EXPORT_SYMBOL(md_write_end);
  * attempting a GFP_KERNEL allocation while holding the mddev lock.
  * Must be called with mddev_lock held.
  *
- * In the ->external case MD_CHANGE_PENDING can not be cleared until mddev->lock
+ * In the ->external case MD_SB_CHANGE_PENDING can not be cleared until mddev->lock
  * is dropped, so return -EAGAIN after notifying userspace.
  */
 int md_allow_write(struct mddev *mddev)
@@ -7787,8 +7820,8 @@ int md_allow_write(struct mddev *mddev)
 	spin_lock(&mddev->lock);
 	if (mddev->in_sync) {
 		mddev->in_sync = 0;
-		set_bit(MD_CHANGE_CLEAN, &mddev->flags);
-		set_bit(MD_CHANGE_PENDING, &mddev->flags);
+		set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
+		set_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
 		if (mddev->safemode_delay &&
 		    mddev->safemode == 0)
 			mddev->safemode = 1;
@@ -7798,7 +7831,7 @@ int md_allow_write(struct mddev *mddev)
 	} else
 		spin_unlock(&mddev->lock);
 
-	if (test_bit(MD_CHANGE_PENDING, &mddev->flags))
+	if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
 		return -EAGAIN;
 	else
 		return 0;
@@ -7914,11 +7947,9 @@ void md_do_sync(struct md_thread *thread
 				    mddev2->curr_resync >= mddev->curr_resync) {
 					if (mddev2_minor != mddev2->md_minor) {
 						mddev2_minor = mddev2->md_minor;
-						printk(KERN_INFO "md: delaying %s of %s"
-						       " until %s has finished (they"
-						       " share one or more physical units)\n",
-						       desc, mdname(mddev),
-						       mdname(mddev2));
+						pr_info("md: delaying %s of %s until %s has finished (they share one or more physical units)\n",
+							desc, mdname(mddev),
+							mdname(mddev2));
 					}
 					mddev_put(mddev2);
 					if (signal_pending(current))
@@ -7975,12 +8006,10 @@ void md_do_sync(struct md_thread *thread
 		}
 	}
 
-	printk(KERN_INFO "md: %s of RAID array %s\n", desc, mdname(mddev));
-	printk(KERN_INFO "md: minimum _guaranteed_  speed:"
-		" %d KB/sec/disk.\n", speed_min(mddev));
-	printk(KERN_INFO "md: using maximum available idle IO bandwidth "
-	       "(but not more than %d KB/sec) for %s.\n",
-	       speed_max(mddev), desc);
+	pr_info("md: %s of RAID array %s\n", desc, mdname(mddev));
+	pr_debug("md: minimum _guaranteed_  speed: %d KB/sec/disk.\n", speed_min(mddev));
+	pr_debug("md: using maximum available idle IO bandwidth (but not more than %d KB/sec) for %s.\n",
+		 speed_max(mddev), desc);
 
 	is_mddev_idle(mddev, 1); /* this initializes IO event counters */
 
@@ -7997,16 +8026,15 @@ void md_do_sync(struct md_thread *thread
 	 * Tune reconstruction:
 	 */
 	window = 32*(PAGE_SIZE/512);
-	printk(KERN_INFO "md: using %dk window, over a total of %lluk.\n",
-		window/2, (unsigned long long)max_sectors/2);
+	pr_debug("md: using %dk window, over a total of %lluk.\n",
+		 window/2, (unsigned long long)max_sectors/2);
 
 	atomic_set(&mddev->recovery_active, 0);
 	last_check = 0;
 
 	if (j>2) {
-		printk(KERN_INFO
-		       "md: resuming %s of %s from checkpoint.\n",
-		       desc, mdname(mddev));
+		pr_debug("md: resuming %s of %s from checkpoint.\n",
+			 desc, mdname(mddev));
 		mddev->curr_resync = j;
 	} else
 		mddev->curr_resync = 3; /* no longer delayed */
@@ -8038,7 +8066,7 @@ void md_do_sync(struct md_thread *thread
 			    j > mddev->recovery_cp)
 				mddev->recovery_cp = j;
 			update_time = jiffies;
-			set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+			set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
 			sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 		}
 
@@ -8133,9 +8161,9 @@ void md_do_sync(struct md_thread *thread
 			}
 		}
 	}
-	printk(KERN_INFO "md: %s: %s %s.\n",mdname(mddev), desc,
-	       test_bit(MD_RECOVERY_INTR, &mddev->recovery)
-	       ? "interrupted" : "done");
+	pr_info("md: %s: %s %s.\n",mdname(mddev), desc,
+		test_bit(MD_RECOVERY_INTR, &mddev->recovery)
+		? "interrupted" : "done");
 	/*
 	 * this also signals 'finished resyncing' to md_stop
 	 */
@@ -8155,9 +8183,8 @@ void md_do_sync(struct md_thread *thread
 		if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
 			if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
 				if (mddev->curr_resync >= mddev->recovery_cp) {
-					printk(KERN_INFO
-					       "md: checkpointing %s of %s.\n",
-					       desc, mdname(mddev));
+					pr_debug("md: checkpointing %s of %s.\n",
+						 desc, mdname(mddev));
 					if (test_bit(MD_RECOVERY_ERROR,
 						&mddev->recovery))
 						mddev->recovery_cp =
@@ -8187,8 +8214,8 @@ void md_do_sync(struct md_thread *thread
 	/* set CHANGE_PENDING here since maybe another update is needed,
 	 * so other nodes are informed. It should be harmless for normal
 	 * raid */
-	set_mask_bits(&mddev->flags, 0,
-		      BIT(MD_CHANGE_PENDING) | BIT(MD_CHANGE_DEVS));
+	set_mask_bits(&mddev->sb_flags, 0,
+		      BIT(MD_SB_CHANGE_PENDING) | BIT(MD_SB_CHANGE_DEVS));
 
 	spin_lock(&mddev->lock);
 	if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
@@ -8288,12 +8315,12 @@ static int remove_and_add_spares(struct
 			if (!test_bit(Journal, &rdev->flags))
 				spares++;
 			md_new_event(mddev);
-			set_bit(MD_CHANGE_DEVS, &mddev->flags);
+			set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		}
 	}
 no_add:
 	if (removed)
-		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 	return spares;
 }
 
@@ -8305,8 +8332,8 @@ static void md_start_sync(struct work_st
 						mddev,
 						"resync");
 	if (!mddev->sync_thread) {
-		printk(KERN_ERR "%s: could not start resync thread...\n",
-		       mdname(mddev));
+		pr_warn("%s: could not start resync thread...\n",
+			mdname(mddev));
 		/* leave the spares where they are, it shouldn't hurt */
 		clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 		clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
@@ -8356,8 +8383,8 @@ void md_check_recovery(struct mddev *mdd
 
 	if (signal_pending(current)) {
 		if (mddev->pers->sync_request && !mddev->external) {
-			printk(KERN_INFO "md: %s in immediate safe mode\n",
-			       mdname(mddev));
+			pr_debug("md: %s in immediate safe mode\n",
+				 mdname(mddev));
 			mddev->safemode = 2;
 		}
 		flush_signals(current);
@@ -8366,7 +8393,7 @@ void md_check_recovery(struct mddev *mdd
 	if (mddev->ro && !test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
 		return;
 	if ( ! (
-		(mddev->flags & MD_UPDATE_SB_FLAGS & ~ (1<<MD_CHANGE_PENDING)) ||
+		(mddev->sb_flags & ~ (1<<MD_SB_CHANGE_PENDING)) ||
 		test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
 		test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
 		test_bit(MD_RELOAD_SB, &mddev->flags) ||
@@ -8404,7 +8431,7 @@ void md_check_recovery(struct mddev *mdd
 			md_reap_sync_thread(mddev);
 			clear_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
 			clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-			clear_bit(MD_CHANGE_PENDING, &mddev->flags);
+			clear_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags);
 			goto unlock;
 		}
 
@@ -8432,7 +8459,7 @@ void md_check_recovery(struct mddev *mdd
 			    mddev->recovery_cp == MaxSector) {
 				mddev->in_sync = 1;
 				did_change = 1;
-				set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+				set_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags);
 			}
 			if (mddev->safemode == 1)
 				mddev->safemode = 0;
@@ -8441,7 +8468,7 @@ void md_check_recovery(struct mddev *mdd
 				sysfs_notify_dirent_safe(mddev->sysfs_state);
 		}
 
-		if (mddev->flags & MD_UPDATE_SB_FLAGS)
+		if (mddev->sb_flags)
 			md_update_sb(mddev, 0);
 
 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
@@ -8537,7 +8564,7 @@ void md_reap_sync_thread(struct mddev *m
 		if (mddev->pers->spare_active(mddev)) {
 			sysfs_notify(&mddev->kobj, NULL,
 				     "degraded");
-			set_bit(MD_CHANGE_DEVS, &mddev->flags);
+			set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		}
 	}
 	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
@@ -8552,7 +8579,7 @@ void md_reap_sync_thread(struct mddev *m
 			rdev->saved_raid_disk = -1;
 
 	md_update_sb(mddev, 1);
-	/* MD_CHANGE_PENDING should be cleared by md_update_sb, so we can
+	/* MD_SB_CHANGE_PENDING should be cleared by md_update_sb, so we can
 	 * call resync_finish here if MD_CLUSTER_RESYNC_LOCKED is set by
 	 * clustered raid */
 	if (test_and_clear_bit(MD_CLUSTER_RESYNC_LOCKED, &mddev->flags))
@@ -8614,9 +8641,12 @@ int rdev_set_badblocks(struct md_rdev *r
 	rv = badblocks_set(&rdev->badblocks, s, sectors, 0);
 	if (rv == 0) {
 		/* Make sure they get written out promptly */
+		if (test_bit(ExternalBbl, &rdev->flags))
+			sysfs_notify(&rdev->kobj, NULL,
+				     "unacknowledged_bad_blocks");
 		sysfs_notify_dirent_safe(rdev->sysfs_state);
-		set_mask_bits(&mddev->flags, 0,
-			      BIT(MD_CHANGE_CLEAN) | BIT(MD_CHANGE_PENDING));
+		set_mask_bits(&mddev->sb_flags, 0,
+			      BIT(MD_SB_CHANGE_CLEAN) | BIT(MD_SB_CHANGE_PENDING));
 		md_wakeup_thread(rdev->mddev->thread);
 		return 1;
 	} else
@@ -8627,12 +8657,15 @@ EXPORT_SYMBOL_GPL(rdev_set_badblocks);
 int rdev_clear_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
 			 int is_new)
 {
+	int rv;
 	if (is_new)
 		s += rdev->new_data_offset;
 	else
 		s += rdev->data_offset;
-	return badblocks_clear(&rdev->badblocks,
-				  s, sectors);
+	rv = badblocks_clear(&rdev->badblocks, s, sectors);
+	if ((rv == 0) && test_bit(ExternalBbl, &rdev->flags))
+		sysfs_notify(&rdev->kobj, NULL, "bad_blocks");
+	return rv;
 }
 EXPORT_SYMBOL_GPL(rdev_clear_badblocks);
 
@@ -8749,7 +8782,7 @@ static void check_sb_changes(struct mdde
 				rdev2->saved_raid_disk = role;
 				ret = remove_and_add_spares(mddev, rdev2);
 				pr_info("Activated spare: %s\n",
-						bdevname(rdev2->bdev,b));
+					bdevname(rdev2->bdev,b));
 				/* wakeup mddev->thread here, so array could
 				 * perform resync with the new activated disk */
 				set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -8785,15 +8818,18 @@ static int read_rdev(struct mddev *mddev
 	 * variable in case we err in the future
 	 */
 	rdev->sb_page = NULL;
-	alloc_disk_sb(rdev);
-	ClearPageUptodate(rdev->sb_page);
-	rdev->sb_loaded = 0;
-	err = super_types[mddev->major_version].load_super(rdev, NULL, mddev->minor_version);
-
+	err = alloc_disk_sb(rdev);
+	if (err == 0) {
+		ClearPageUptodate(rdev->sb_page);
+		rdev->sb_loaded = 0;
+		err = super_types[mddev->major_version].
+			load_super(rdev, NULL, mddev->minor_version);
+	}
 	if (err < 0) {
 		pr_warn("%s: %d Could not reload rdev(%d) err: %d. Restoring old values\n",
 				__func__, __LINE__, rdev->desc_nr, err);
-		put_page(rdev->sb_page);
+		if (rdev->sb_page)
+			put_page(rdev->sb_page);
 		rdev->sb_page = swapout;
 		rdev->sb_loaded = 1;
 		return err;
@@ -8871,9 +8907,6 @@ void md_autodetect_dev(dev_t dev)
 		mutex_lock(&detected_devices_mutex);
 		list_add_tail(&node_detected_dev->list, &all_detected_devices);
 		mutex_unlock(&detected_devices_mutex);
-	} else {
-		printk(KERN_CRIT "md: md_autodetect_dev: kzalloc failed"
-			", skipping dev(%d,%d)\n", MAJOR(dev), MINOR(dev));
 	}
 }
 
@@ -8887,7 +8920,7 @@ static void autostart_arrays(int part)
 	i_scanned = 0;
 	i_passed = 0;
 
-	printk(KERN_INFO "md: Autodetecting RAID arrays.\n");
+	pr_info("md: Autodetecting RAID arrays.\n");
 
 	mutex_lock(&detected_devices_mutex);
 	while (!list_empty(&all_detected_devices) && i_scanned < INT_MAX) {
@@ -8912,8 +8945,7 @@ static void autostart_arrays(int part)
 	}
 	mutex_unlock(&detected_devices_mutex);
 
-	printk(KERN_INFO "md: Scanned %d and added %d devices.\n",
-						i_scanned, i_passed);
+	pr_debug("md: Scanned %d and added %d devices.\n", i_scanned, i_passed);
 
 	autorun_devices(part);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/md.h linux-libre-4.10-rc8-gnu/drivers/md/md.h
--- linux-libre-4.9-gnu/drivers/md/md.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/md.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,6 +30,16 @@
 #define MaxSector (~(sector_t)0)
 
 /*
+ * These flags should really be called "NO_RETRY" rather than
+ * "FAILFAST" because they don't make any promise about time lapse,
+ * only about the number of retries, which will be zero.
+ * REQ_FAILFAST_DRIVER is not included because
+ * Commit: 4a27446f3e39 ("[SCSI] modify scsi to handle new fail fast flags.")
+ * seems to suggest that the errors it avoids retrying should usually
+ * be retried.
+ */
+#define	MD_FAILFAST	(REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT)
+/*
  * MD's 'extended' device
  */
 struct md_rdev {
@@ -168,6 +178,19 @@ enum flag_bits {
 				 * so it is safe to remove without
 				 * another synchronize_rcu() call.
 				 */
+	ExternalBbl,            /* External metadata provides bad
+				 * block management for a disk
+				 */
+	FailFast,		/* Minimal retries should be attempted on
+				 * this device, so use REQ_FAILFAST_DEV.
+				 * Also don't try to repair failed reads.
+				 * It is expects that no bad block log
+				 * is present.
+				 */
+	LastDev,		/* Seems to be the last working dev as
+				 * it didn't fail, so don't use FailFast
+				 * any more for metadata
+				 */
 };
 
 static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
@@ -189,6 +212,32 @@ extern int rdev_clear_badblocks(struct m
 				int is_new);
 struct md_cluster_info;
 
+/* change UNSUPPORTED_MDDEV_FLAGS for each array type if new flag is added */
+enum mddev_flags {
+	MD_ARRAY_FIRST_USE,	/* First use of array, needs initialization */
+	MD_CLOSING,		/* If set, we are closing the array, do not open
+				 * it then */
+	MD_JOURNAL_CLEAN,	/* A raid with journal is already clean */
+	MD_HAS_JOURNAL,		/* The raid array has journal feature set */
+	MD_RELOAD_SB,		/* Reload the superblock because another node
+				 * updated it.
+				 */
+	MD_CLUSTER_RESYNC_LOCKED, /* cluster raid only, which means node
+				   * already took resync lock, need to
+				   * release the lock */
+	MD_FAILFAST_SUPPORTED,	/* Using MD_FAILFAST on metadata writes is
+				 * supported as calls to md_error() will
+				 * never cause the array to become failed.
+				 */
+};
+
+enum mddev_sb_flags {
+	MD_SB_CHANGE_DEVS,		/* Some device status has changed */
+	MD_SB_CHANGE_CLEAN,	/* transition to or from 'clean' */
+	MD_SB_CHANGE_PENDING,	/* switch from 'clean' to 'active' in progress */
+	MD_SB_NEED_REWRITE,	/* metadata write needs to be repeated */
+};
+
 struct mddev {
 	void				*private;
 	struct md_personality		*pers;
@@ -196,21 +245,7 @@ struct mddev {
 	int				md_minor;
 	struct list_head		disks;
 	unsigned long			flags;
-#define MD_CHANGE_DEVS	0	/* Some device status has changed */
-#define MD_CHANGE_CLEAN 1	/* transition to or from 'clean' */
-#define MD_CHANGE_PENDING 2	/* switch from 'clean' to 'active' in progress */
-#define MD_UPDATE_SB_FLAGS (1 | 2 | 4)	/* If these are set, md_update_sb needed */
-#define MD_ARRAY_FIRST_USE 3    /* First use of array, needs initialization */
-#define MD_CLOSING	4	/* If set, we are closing the array, do not open
-				 * it then */
-#define MD_JOURNAL_CLEAN 5	/* A raid with journal is already clean */
-#define MD_HAS_JOURNAL	6	/* The raid array has journal feature set */
-#define MD_RELOAD_SB	7	/* Reload the superblock because another node
-				 * updated it.
-				 */
-#define MD_CLUSTER_RESYNC_LOCKED 8 /* cluster raid only, which means node
-				    * already took resync lock, need to
-				    * release the lock */
+	unsigned long			sb_flags;
 
 	int				suspended;
 	atomic_t			active_io;
@@ -304,31 +339,6 @@ struct mddev {
 	int				parallel_resync;
 
 	int				ok_start_degraded;
-	/* recovery/resync flags
-	 * NEEDED:   we might need to start a resync/recover
-	 * RUNNING:  a thread is running, or about to be started
-	 * SYNC:     actually doing a resync, not a recovery
-	 * RECOVER:  doing recovery, or need to try it.
-	 * INTR:     resync needs to be aborted for some reason
-	 * DONE:     thread is done and is waiting to be reaped
-	 * REQUEST:  user-space has requested a sync (used with SYNC)
-	 * CHECK:    user-space request for check-only, no repair
-	 * RESHAPE:  A reshape is happening
-	 * ERROR:    sync-action interrupted because io-error
-	 *
-	 * If neither SYNC or RESHAPE are set, then it is a recovery.
-	 */
-#define	MD_RECOVERY_RUNNING	0
-#define	MD_RECOVERY_SYNC	1
-#define	MD_RECOVERY_RECOVER	2
-#define	MD_RECOVERY_INTR	3
-#define	MD_RECOVERY_DONE	4
-#define	MD_RECOVERY_NEEDED	5
-#define	MD_RECOVERY_REQUESTED	6
-#define	MD_RECOVERY_CHECK	7
-#define MD_RECOVERY_RESHAPE	8
-#define	MD_RECOVERY_FROZEN	9
-#define	MD_RECOVERY_ERROR	10
 
 	unsigned long			recovery;
 	/* If a RAID personality determines that recovery (of a particular
@@ -442,6 +452,23 @@ struct mddev {
 	unsigned int			good_device_nr;	/* good device num within cluster raid */
 };
 
+enum recovery_flags {
+	/*
+	 * If neither SYNC or RESHAPE are set, then it is a recovery.
+	 */
+	MD_RECOVERY_RUNNING,	/* a thread is running, or about to be started */
+	MD_RECOVERY_SYNC,	/* actually doing a resync, not a recovery */
+	MD_RECOVERY_RECOVER,	/* doing recovery, or need to try it. */
+	MD_RECOVERY_INTR,	/* resync needs to be aborted for some reason */
+	MD_RECOVERY_DONE,	/* thread is done and is waiting to be reaped */
+	MD_RECOVERY_NEEDED,	/* we might need to start a resync/recover */
+	MD_RECOVERY_REQUESTED,	/* user-space has requested a sync (used with SYNC) */
+	MD_RECOVERY_CHECK,	/* user-space request for check-only, no repair */
+	MD_RECOVERY_RESHAPE,	/* A reshape is happening */
+	MD_RECOVERY_FROZEN,	/* User request to abort, and not restart, any action */
+	MD_RECOVERY_ERROR,	/* sync-action interrupted because io-error */
+};
+
 static inline int __must_check mddev_lock(struct mddev *mddev)
 {
 	return mutex_lock_interruptible(&mddev->reconfig_mutex);
@@ -623,7 +650,7 @@ extern int mddev_congested(struct mddev
 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(struct mddev *mddev);
+extern int md_super_wait(struct mddev *mddev);
 extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
 			struct page *page, int op, int op_flags,
 			bool metadata_op);
@@ -676,4 +703,11 @@ static inline int mddev_is_clustered(str
 {
 	return mddev->cluster_info && mddev->bitmap_info.nodes > 1;
 }
+
+/* clear unsupported mddev_flags */
+static inline void mddev_clear_unsupported_flags(struct mddev *mddev,
+	unsigned long unsupported_flags)
+{
+	mddev->flags &= ~unsupported_flags;
+}
 #endif /* _MD_MD_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/multipath.c linux-libre-4.10-rc8-gnu/drivers/md/multipath.c
--- linux-libre-4.9-gnu/drivers/md/multipath.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/multipath.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@ static int multipath_map (struct mpconf
 	}
 	rcu_read_unlock();
 
-	printk(KERN_ERR "multipath_map(): no more operational IO paths?\n");
+	pr_crit_ratelimited("multipath_map(): no more operational IO paths?\n");
 	return (-1);
 }
 
@@ -97,9 +97,9 @@ static void multipath_end_request(struct
 		 */
 		char b[BDEVNAME_SIZE];
 		md_error (mp_bh->mddev, rdev);
-		printk(KERN_ERR "multipath: %s: rescheduling sector %llu\n",
-		       bdevname(rdev->bdev,b),
-		       (unsigned long long)bio->bi_iter.bi_sector);
+		pr_info("multipath: %s: rescheduling sector %llu\n",
+			bdevname(rdev->bdev,b),
+			(unsigned long long)bio->bi_iter.bi_sector);
 		multipath_reschedule_retry(mp_bh);
 	} else
 		multipath_end_bh_io(mp_bh, bio->bi_error);
@@ -130,7 +130,7 @@ static void multipath_make_request(struc
 	}
 	multipath = conf->multipaths + mp_bh->path;
 
-	bio_init(&mp_bh->bio);
+	bio_init(&mp_bh->bio, NULL, 0);
 	__bio_clone_fast(&mp_bh->bio, bio);
 
 	mp_bh->bio.bi_iter.bi_sector += multipath->rdev->data_offset;
@@ -194,8 +194,7 @@ static void multipath_error (struct mdde
 		 * first check if this is a queued request for a device
 		 * which has just failed.
 		 */
-		printk(KERN_ALERT
-		       "multipath: only one IO path left and IO error.\n");
+		pr_warn("multipath: only one IO path left and IO error.\n");
 		/* leave it active... it's all we have */
 		return;
 	}
@@ -209,11 +208,9 @@ static void multipath_error (struct mdde
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 	set_bit(Faulty, &rdev->flags);
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
-	printk(KERN_ALERT "multipath: IO failure on %s,"
-	       " disabling IO path.\n"
-	       "multipath: Operation continuing"
-	       " on %d IO paths.\n",
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
+	pr_err("multipath: IO failure on %s, disabling IO path.\n"
+	       "multipath: Operation continuing on %d IO paths.\n",
 	       bdevname(rdev->bdev, b),
 	       conf->raid_disks - mddev->degraded);
 }
@@ -223,21 +220,21 @@ static void print_multipath_conf (struct
 	int i;
 	struct multipath_info *tmp;
 
-	printk("MULTIPATH conf printout:\n");
+	pr_debug("MULTIPATH conf printout:\n");
 	if (!conf) {
-		printk("(conf==NULL)\n");
+		pr_debug("(conf==NULL)\n");
 		return;
 	}
-	printk(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
-			 conf->raid_disks);
+	pr_debug(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
+		 conf->raid_disks);
 
 	for (i = 0; i < conf->raid_disks; i++) {
 		char b[BDEVNAME_SIZE];
 		tmp = conf->multipaths + i;
 		if (tmp->rdev)
-			printk(" disk%d, o:%d, dev:%s\n",
-				i,!test_bit(Faulty, &tmp->rdev->flags),
-			       bdevname(tmp->rdev->bdev,b));
+			pr_debug(" disk%d, o:%d, dev:%s\n",
+				 i,!test_bit(Faulty, &tmp->rdev->flags),
+				 bdevname(tmp->rdev->bdev,b));
 	}
 }
 
@@ -292,8 +289,7 @@ static int multipath_remove_disk(struct
 	if (rdev == p->rdev) {
 		if (test_bit(In_sync, &rdev->flags) ||
 		    atomic_read(&rdev->nr_pending)) {
-			printk(KERN_ERR "hot-remove-disk, slot %d is identified"
-			       " but is still operational!\n", number);
+			pr_warn("hot-remove-disk, slot %d is identified but is still operational!\n", number);
 			err = -EBUSY;
 			goto abort;
 		}
@@ -346,16 +342,14 @@ static void multipathd(struct md_thread
 		bio->bi_iter.bi_sector = mp_bh->master_bio->bi_iter.bi_sector;
 
 		if ((mp_bh->path = multipath_map (conf))<0) {
-			printk(KERN_ALERT "multipath: %s: unrecoverable IO read"
-				" error for block %llu\n",
-				bdevname(bio->bi_bdev,b),
-				(unsigned long long)bio->bi_iter.bi_sector);
+			pr_err("multipath: %s: unrecoverable IO read error for block %llu\n",
+			       bdevname(bio->bi_bdev,b),
+			       (unsigned long long)bio->bi_iter.bi_sector);
 			multipath_end_bh_io(mp_bh, -EIO);
 		} else {
-			printk(KERN_ERR "multipath: %s: redirecting sector %llu"
-				" to another IO path\n",
-				bdevname(bio->bi_bdev,b),
-				(unsigned long long)bio->bi_iter.bi_sector);
+			pr_err("multipath: %s: redirecting sector %llu to another IO path\n",
+			       bdevname(bio->bi_bdev,b),
+			       (unsigned long long)bio->bi_iter.bi_sector);
 			*bio = *(mp_bh->master_bio);
 			bio->bi_iter.bi_sector +=
 				conf->multipaths[mp_bh->path].rdev->data_offset;
@@ -389,8 +383,8 @@ static int multipath_run (struct mddev *
 		return -EINVAL;
 
 	if (mddev->level != LEVEL_MULTIPATH) {
-		printk("multipath: %s: raid level not set to multipath IO (%d)\n",
-		       mdname(mddev), mddev->level);
+		pr_warn("multipath: %s: raid level not set to multipath IO (%d)\n",
+			mdname(mddev), mddev->level);
 		goto out;
 	}
 	/*
@@ -401,21 +395,13 @@ static int multipath_run (struct mddev *
 
 	conf = kzalloc(sizeof(struct mpconf), GFP_KERNEL);
 	mddev->private = conf;
-	if (!conf) {
-		printk(KERN_ERR
-			"multipath: couldn't allocate memory for %s\n",
-			mdname(mddev));
+	if (!conf)
 		goto out;
-	}
 
 	conf->multipaths = kzalloc(sizeof(struct multipath_info)*mddev->raid_disks,
 				   GFP_KERNEL);
-	if (!conf->multipaths) {
-		printk(KERN_ERR
-			"multipath: couldn't allocate memory for %s\n",
-			mdname(mddev));
+	if (!conf->multipaths)
 		goto out_free_conf;
-	}
 
 	working_disks = 0;
 	rdev_for_each(rdev, mddev) {
@@ -439,7 +425,7 @@ static int multipath_run (struct mddev *
 	INIT_LIST_HEAD(&conf->retry_list);
 
 	if (!working_disks) {
-		printk(KERN_ERR "multipath: no operational IO paths for %s\n",
+		pr_warn("multipath: no operational IO paths for %s\n",
 			mdname(mddev));
 		goto out_free_conf;
 	}
@@ -447,27 +433,17 @@ static int multipath_run (struct mddev *
 
 	conf->pool = mempool_create_kmalloc_pool(NR_RESERVED_BUFS,
 						 sizeof(struct multipath_bh));
-	if (conf->pool == NULL) {
-		printk(KERN_ERR
-			"multipath: couldn't allocate memory for %s\n",
-			mdname(mddev));
+	if (conf->pool == NULL)
 		goto out_free_conf;
-	}
 
-	{
-		mddev->thread = md_register_thread(multipathd, mddev,
-						   "multipath");
-		if (!mddev->thread) {
-			printk(KERN_ERR "multipath: couldn't allocate thread"
-				" for %s\n", mdname(mddev));
-			goto out_free_conf;
-		}
-	}
+	mddev->thread = md_register_thread(multipathd, mddev,
+					   "multipath");
+	if (!mddev->thread)
+		goto out_free_conf;
 
-	printk(KERN_INFO
-		"multipath: array %s active with %d out of %d IO paths\n",
+	pr_info("multipath: array %s active with %d out of %d IO paths\n",
 		mdname(mddev), conf->raid_disks - mddev->degraded,
-	       mddev->raid_disks);
+		mddev->raid_disks);
 	/*
 	 * Ok, everything is just fine now
 	 */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/persistent-data/dm-array.c linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-array.c
--- linux-libre-4.9-gnu/drivers/md/persistent-data/dm-array.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-array.c	2017-02-12 16:03:20.000000000 -0500
@@ -700,13 +700,11 @@ static int populate_ablock_with_values(s
 {
 	int r;
 	unsigned i;
-	uint32_t nr_entries;
 	struct dm_btree_value_type *vt = &info->value_type;
 
 	BUG_ON(le32_to_cpu(ab->nr_entries));
 	BUG_ON(new_nr > le32_to_cpu(ab->max_entries));
 
-	nr_entries = le32_to_cpu(ab->nr_entries);
 	for (i = 0; i < new_nr; i++) {
 		r = fn(base + i, element_at(info, ab, i), context);
 		if (r)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/persistent-data/dm-block-manager.c linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-block-manager.c
--- linux-libre-4.9-gnu/drivers/md/persistent-data/dm-block-manager.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-block-manager.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@
 
 /*----------------------------------------------------------------*/
 
+#ifdef CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING
+
 /*
  * This is a read/write semaphore with a couple of differences.
  *
@@ -302,6 +304,18 @@ static void report_recursive_bug(dm_bloc
 		      (unsigned long long) b);
 }
 
+#else  /* !CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING */
+
+#define bl_init(x) do { } while (0)
+#define bl_down_read(x) 0
+#define bl_down_read_nonblock(x) 0
+#define bl_up_read(x) do { } while (0)
+#define bl_down_write(x) 0
+#define bl_up_write(x) do { } while (0)
+#define report_recursive_bug(x, y) do { } while (0)
+
+#endif /* CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING */
+
 /*----------------------------------------------------------------*/
 
 /*
@@ -330,8 +344,11 @@ EXPORT_SYMBOL_GPL(dm_block_data);
 
 struct buffer_aux {
 	struct dm_block_validator *validator;
-	struct block_lock lock;
 	int write_locked;
+
+#ifdef CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING
+	struct block_lock lock;
+#endif
 };
 
 static void dm_block_manager_alloc_callback(struct dm_buffer *buf)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/persistent-data/dm-space-map-common.c linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-space-map-common.c
--- linux-libre-4.9-gnu/drivers/md/persistent-data/dm-space-map-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-space-map-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -464,7 +464,8 @@ static int sm_ll_mutate(struct ll_disk *
 		ll->nr_allocated--;
 		le32_add_cpu(&ie_disk.nr_free, 1);
 		ie_disk.none_free_before = cpu_to_le32(min(le32_to_cpu(ie_disk.none_free_before), bit));
-	}
+	} else
+		*ev = SM_NONE;
 
 	return ll->save_ie(ll, index, &ie_disk);
 }
@@ -547,7 +548,6 @@ static int metadata_ll_init_index(struct
 	if (r < 0)
 		return r;
 
-	memcpy(dm_block_data(b), &ll->mi_le, sizeof(ll->mi_le));
 	ll->bitmap_root = dm_block_location(b);
 
 	dm_tm_unlock(ll->tm, b);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/persistent-data/dm-space-map-metadata.c linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-space-map-metadata.c
--- linux-libre-4.9-gnu/drivers/md/persistent-data/dm-space-map-metadata.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/persistent-data/dm-space-map-metadata.c	2017-02-12 16:03:20.000000000 -0500
@@ -775,17 +775,15 @@ int dm_sm_metadata_create(struct dm_spac
 	memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
 
 	r = sm_ll_new_metadata(&smm->ll, tm);
+	if (!r) {
+		if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
+			nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
+		r = sm_ll_extend(&smm->ll, nr_blocks);
+	}
+	memcpy(&smm->sm, &ops, sizeof(smm->sm));
 	if (r)
 		return r;
 
-	if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
-		nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
-	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.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid0.c linux-libre-4.10-rc8-gnu/drivers/md/raid0.c
--- linux-libre-4.9-gnu/drivers/md/raid0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid0.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,10 +21,16 @@
 #include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <trace/events/block.h>
 #include "md.h"
 #include "raid0.h"
 #include "raid5.h"
 
+#define UNSUPPORTED_MDDEV_FLAGS		\
+	((1L << MD_HAS_JOURNAL) |	\
+	 (1L << MD_JOURNAL_CLEAN) |	\
+	 (1L << MD_FAILFAST_SUPPORTED))
+
 static int raid0_congested(struct mddev *mddev, int bits)
 {
 	struct r0conf *conf = mddev->private;
@@ -51,20 +57,21 @@ static void dump_zones(struct mddev *mdd
 	char b[BDEVNAME_SIZE];
 	struct r0conf *conf = mddev->private;
 	int raid_disks = conf->strip_zone[0].nb_dev;
-	printk(KERN_INFO "md: RAID0 configuration for %s - %d zone%s\n",
-	       mdname(mddev),
-	       conf->nr_strip_zones, conf->nr_strip_zones==1?"":"s");
+	pr_debug("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 "md: zone%d=[", j);
+		char line[200];
+		int len = 0;
+
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
-			printk(KERN_CONT "%s%s", k?"/":"",
-			bdevname(conf->devlist[j*raid_disks
-						+ k]->bdev, b));
-		printk(KERN_CONT "]\n");
+			len += snprintf(line+len, 200-len, "%s%s", k?"/":"",
+					bdevname(conf->devlist[j*raid_disks
+							       + k]->bdev, b));
+		pr_debug("md: zone%d=[%s]\n", j, line);
 
 		zone_size  = conf->strip_zone[j].zone_end - zone_start;
-		printk(KERN_INFO "      zone-offset=%10lluKB, "
-				"device-offset=%10lluKB, size=%10lluKB\n",
+		pr_debug("      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);
@@ -142,9 +149,9 @@ static int create_strip_zones(struct mdd
 	 * chunk size is a multiple of that sector size
 	 */
 	if ((mddev->chunk_sectors << 9) % blksize) {
-		printk(KERN_ERR "md/raid0:%s: chunk_size of %d not multiple of block size %d\n",
-		       mdname(mddev),
-		       mddev->chunk_sectors << 9, blksize);
+		pr_warn("md/raid0:%s: chunk_size of %d not multiple of block size %d\n",
+			mdname(mddev),
+			mddev->chunk_sectors << 9, blksize);
 		err = -EINVAL;
 		goto abort;
 	}
@@ -186,19 +193,18 @@ static int create_strip_zones(struct mdd
 		}
 
 		if (j < 0) {
-			printk(KERN_ERR
-			       "md/raid0:%s: remove inactive devices before converting to RAID0\n",
-			       mdname(mddev));
+			pr_warn("md/raid0:%s: remove inactive devices before converting to RAID0\n",
+				mdname(mddev));
 			goto abort;
 		}
 		if (j >= mddev->raid_disks) {
-			printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
-			       "aborting!\n", mdname(mddev), j);
+			pr_warn("md/raid0:%s: bad disk number %d - aborting!\n",
+				mdname(mddev), j);
 			goto abort;
 		}
 		if (dev[j]) {
-			printk(KERN_ERR "md/raid0:%s: multiple devices for %d - "
-			       "aborting!\n", mdname(mddev), j);
+			pr_warn("md/raid0:%s: multiple devices for %d - aborting!\n",
+				mdname(mddev), j);
 			goto abort;
 		}
 		dev[j] = rdev1;
@@ -208,8 +214,8 @@ static int create_strip_zones(struct mdd
 		cnt++;
 	}
 	if (cnt != mddev->raid_disks) {
-		printk(KERN_ERR "md/raid0:%s: too few disks (%d of %d) - "
-		       "aborting!\n", mdname(mddev), cnt, mddev->raid_disks);
+		pr_warn("md/raid0:%s: too few disks (%d of %d) - aborting!\n",
+			mdname(mddev), cnt, mddev->raid_disks);
 		goto abort;
 	}
 	zone->nb_dev = cnt;
@@ -357,8 +363,7 @@ static int raid0_run(struct mddev *mddev
 	int ret;
 
 	if (mddev->chunk_sectors == 0) {
-		printk(KERN_ERR "md/raid0:%s: chunk size must be set.\n",
-		       mdname(mddev));
+		pr_warn("md/raid0:%s: chunk size must be set.\n", mdname(mddev));
 		return -EINVAL;
 	}
 	if (md_check_no_bitmap(mddev))
@@ -399,9 +404,9 @@ static int raid0_run(struct mddev *mddev
 	/* calculate array device size */
 	md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
 
-	printk(KERN_INFO "md/raid0:%s: md_size is %llu sectors.\n",
-	       mdname(mddev),
-	       (unsigned long long)mddev->array_sectors);
+	pr_debug("md/raid0:%s: md_size is %llu sectors.\n",
+		 mdname(mddev),
+		 (unsigned long long)mddev->array_sectors);
 
 	if (mddev->queue) {
 		/* calculate the max read-ahead size.
@@ -464,7 +469,8 @@ static void raid0_make_request(struct md
 	}
 
 	do {
-		sector_t sector = bio->bi_iter.bi_sector;
+		sector_t bio_sector = bio->bi_iter.bi_sector;
+		sector_t sector = bio_sector;
 		unsigned chunk_sects = mddev->chunk_sectors;
 
 		unsigned sectors = chunk_sects -
@@ -473,7 +479,7 @@ static void raid0_make_request(struct md
 			 : sector_div(sector, chunk_sects));
 
 		/* Restore due to sector_div */
-		sector = bio->bi_iter.bi_sector;
+		sector = bio_sector;
 
 		if (sectors < bio_sectors(bio)) {
 			split = bio_split(bio, sectors, GFP_NOIO, fs_bio_set);
@@ -492,8 +498,13 @@ static void raid0_make_request(struct md
 			 !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) {
 			/* Just ignore it */
 			bio_endio(split);
-		} else
+		} else {
+			if (mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(split->bi_bdev),
+						      split, disk_devt(mddev->gendisk),
+						      bio_sector);
 			generic_make_request(split);
+		}
 	} while (split != bio);
 }
 
@@ -509,17 +520,17 @@ static void *raid0_takeover_raid45(struc
 	struct r0conf *priv_conf;
 
 	if (mddev->degraded != 1) {
-		printk(KERN_ERR "md/raid0:%s: raid5 must be degraded! Degraded disks: %d\n",
-		       mdname(mddev),
-		       mddev->degraded);
+		pr_warn("md/raid0:%s: raid5 must be degraded! Degraded disks: %d\n",
+			mdname(mddev),
+			mddev->degraded);
 		return ERR_PTR(-EINVAL);
 	}
 
 	rdev_for_each(rdev, mddev) {
 		/* check slot number for a disk */
 		if (rdev->raid_disk == mddev->raid_disks-1) {
-			printk(KERN_ERR "md/raid0:%s: raid5 must have missing parity disk!\n",
-			       mdname(mddev));
+			pr_warn("md/raid0:%s: raid5 must have missing parity disk!\n",
+				mdname(mddev));
 			return ERR_PTR(-EINVAL);
 		}
 		rdev->sectors = mddev->dev_sectors;
@@ -533,8 +544,10 @@ static void *raid0_takeover_raid45(struc
 	mddev->delta_disks = -1;
 	/* make sure it will be not marked as dirty */
 	mddev->recovery_cp = MaxSector;
+	mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
 
 	create_strip_zones(mddev, &priv_conf);
+
 	return priv_conf;
 }
 
@@ -549,19 +562,19 @@ static void *raid0_takeover_raid10(struc
 	 *  - all mirrors must be already degraded
 	 */
 	if (mddev->layout != ((1 << 8) + 2)) {
-		printk(KERN_ERR "md/raid0:%s:: Raid0 cannot takeover layout: 0x%x\n",
-		       mdname(mddev),
-		       mddev->layout);
+		pr_warn("md/raid0:%s:: Raid0 cannot takeover layout: 0x%x\n",
+			mdname(mddev),
+			mddev->layout);
 		return ERR_PTR(-EINVAL);
 	}
 	if (mddev->raid_disks & 1) {
-		printk(KERN_ERR "md/raid0:%s: Raid0 cannot takeover Raid10 with odd disk number.\n",
-		       mdname(mddev));
+		pr_warn("md/raid0:%s: Raid0 cannot takeover Raid10 with odd disk number.\n",
+			mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
 	if (mddev->degraded != (mddev->raid_disks>>1)) {
-		printk(KERN_ERR "md/raid0:%s: All mirrors must be already degraded!\n",
-		       mdname(mddev));
+		pr_warn("md/raid0:%s: All mirrors must be already degraded!\n",
+			mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -574,6 +587,7 @@ static void *raid0_takeover_raid10(struc
 	mddev->degraded = 0;
 	/* make sure it will be not marked as dirty */
 	mddev->recovery_cp = MaxSector;
+	mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
 
 	create_strip_zones(mddev, &priv_conf);
 	return priv_conf;
@@ -588,7 +602,7 @@ static void *raid0_takeover_raid1(struct
 	 *  - (N - 1) mirror drives must be already faulty
 	 */
 	if ((mddev->raid_disks - 1) != mddev->degraded) {
-		printk(KERN_ERR "md/raid0:%s: (N - 1) mirrors drives must be already faulty!\n",
+		pr_err("md/raid0:%s: (N - 1) mirrors drives must be already faulty!\n",
 		       mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
@@ -616,6 +630,7 @@ static void *raid0_takeover_raid1(struct
 	mddev->raid_disks = 1;
 	/* make sure it will be not marked as dirty */
 	mddev->recovery_cp = MaxSector;
+	mddev_clear_unsupported_flags(mddev, UNSUPPORTED_MDDEV_FLAGS);
 
 	create_strip_zones(mddev, &priv_conf);
 	return priv_conf;
@@ -631,8 +646,8 @@ static void *raid0_takeover(struct mddev
 	 */
 
 	if (mddev->bitmap) {
-		printk(KERN_ERR "md/raid0: %s: cannot takeover array with bitmap\n",
-		       mdname(mddev));
+		pr_warn("md/raid0: %s: cannot takeover array with bitmap\n",
+			mdname(mddev));
 		return ERR_PTR(-EBUSY);
 	}
 	if (mddev->level == 4)
@@ -642,8 +657,8 @@ static void *raid0_takeover(struct mddev
 		if (mddev->layout == ALGORITHM_PARITY_N)
 			return raid0_takeover_raid45(mddev);
 
-		printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",
-		       mdname(mddev), ALGORITHM_PARITY_N);
+		pr_warn("md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",
+			mdname(mddev), ALGORITHM_PARITY_N);
 	}
 
 	if (mddev->level == 10)
@@ -652,7 +667,7 @@ static void *raid0_takeover(struct mddev
 	if (mddev->level == 1)
 		return raid0_takeover_raid1(mddev);
 
-	printk(KERN_ERR "Takeover from raid%i to raid0 not supported\n",
+	pr_warn("Takeover from raid%i to raid0 not supported\n",
 		mddev->level);
 
 	return ERR_PTR(-EINVAL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid10.c linux-libre-4.10-rc8-gnu/drivers/md/raid10.c
--- linux-libre-4.9-gnu/drivers/md/raid10.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid10.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,6 +25,7 @@
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
 #include <linux/kthread.h>
+#include <trace/events/block.h>
 #include "md.h"
 #include "raid10.h"
 #include "raid0.h"
@@ -99,12 +100,16 @@ static int max_queued_requests = 1024;
 static void allow_barrier(struct r10conf *conf);
 static void lower_barrier(struct r10conf *conf);
 static int _enough(struct r10conf *conf, int previous, int ignore);
+static int enough(struct r10conf *conf, int ignore);
 static sector_t reshape_request(struct mddev *mddev, sector_t sector_nr,
 				int *skipped);
 static void reshape_request_write(struct mddev *mddev, struct r10bio *r10_bio);
 static void end_reshape_write(struct bio *bio);
 static void end_reshape(struct r10conf *conf);
 
+#define raid10_log(md, fmt, args...)				\
+	do { if ((md)->queue) blk_add_trace_msg((md)->queue, "raid10 " fmt, ##args); } while (0)
+
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct r10conf *conf = data;
@@ -404,8 +409,7 @@ static void raid10_end_read_request(stru
 		 * oops, read error - keep the refcount on the rdev
 		 */
 		char b[BDEVNAME_SIZE];
-		printk_ratelimited(KERN_ERR
-				   "md/raid10:%s: %s: rescheduling sector %llu\n",
+		pr_err_ratelimited("md/raid10:%s: %s: rescheduling sector %llu\n",
 				   mdname(conf->mddev),
 				   bdevname(rdev->bdev, b),
 				   (unsigned long long)r10_bio->sector);
@@ -447,6 +451,7 @@ static void raid10_end_write_request(str
 	struct r10conf *conf = r10_bio->mddev->private;
 	int slot, repl;
 	struct md_rdev *rdev = NULL;
+	struct bio *to_put = NULL;
 	bool discard_error;
 
 	discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD;
@@ -474,8 +479,24 @@ static void raid10_end_write_request(str
 			if (!test_and_set_bit(WantReplacement, &rdev->flags))
 				set_bit(MD_RECOVERY_NEEDED,
 					&rdev->mddev->recovery);
-			set_bit(R10BIO_WriteError, &r10_bio->state);
+
 			dec_rdev = 0;
+			if (test_bit(FailFast, &rdev->flags) &&
+			    (bio->bi_opf & MD_FAILFAST)) {
+				md_error(rdev->mddev, rdev);
+				if (!test_bit(Faulty, &rdev->flags))
+					/* This is the only remaining device,
+					 * We need to retry the write without
+					 * FailFast
+					 */
+					set_bit(R10BIO_WriteError, &r10_bio->state);
+				else {
+					r10_bio->devs[slot].bio = NULL;
+					to_put = bio;
+					dec_rdev = 1;
+				}
+			} else
+				set_bit(R10BIO_WriteError, &r10_bio->state);
 		}
 	} else {
 		/*
@@ -525,6 +546,8 @@ static void raid10_end_write_request(str
 	one_write_done(r10_bio);
 	if (dec_rdev)
 		rdev_dec_pending(rdev, conf->mddev);
+	if (to_put)
+		bio_put(to_put);
 }
 
 /*
@@ -716,6 +739,7 @@ static struct md_rdev *read_balance(stru
 	best_dist = MaxSector;
 	best_good_sectors = 0;
 	do_balance = 1;
+	clear_bit(R10BIO_FailFast, &r10_bio->state);
 	/*
 	 * Check if we can balance. We can balance on the whole
 	 * device if no resync is going on (recovery is ok), or below
@@ -780,15 +804,18 @@ static struct md_rdev *read_balance(stru
 		if (!do_balance)
 			break;
 
+		if (best_slot >= 0)
+			/* At least 2 disks to choose from so failfast is OK */
+			set_bit(R10BIO_FailFast, &r10_bio->state);
 		/* This optimisation is debatable, and completely destroys
 		 * sequential read speed for 'far copies' arrays.  So only
 		 * keep it for 'near' arrays, and review those later.
 		 */
 		if (geo->near_copies > 1 && !atomic_read(&rdev->nr_pending))
-			break;
+			new_distance = 0;
 
 		/* for far > 1 always use the lowest address */
-		if (geo->far_copies > 1)
+		else if (geo->far_copies > 1)
 			new_distance = r10_bio->devs[slot].addr;
 		else
 			new_distance = abs(r10_bio->devs[slot].addr -
@@ -859,9 +886,14 @@ static void flush_pending_writes(struct
 
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
+			struct md_rdev *rdev = (void*)bio->bi_bdev;
 			bio->bi_next = NULL;
-			if (unlikely((bio_op(bio) ==  REQ_OP_DISCARD) &&
-			    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+			bio->bi_bdev = rdev->bdev;
+			if (test_bit(Faulty, &rdev->flags)) {
+				bio->bi_error = -EIO;
+				bio_endio(bio);
+			} else if (unlikely((bio_op(bio) ==  REQ_OP_DISCARD) &&
+					    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
 				/* Just ignore it */
 				bio_endio(bio);
 			else
@@ -937,6 +969,7 @@ static void wait_barrier(struct r10conf
 		 * that queue to get the nr_pending
 		 * count down.
 		 */
+		raid10_log(conf->mddev, "wait barrier");
 		wait_event_lock_irq(conf->wait_barrier,
 				    !conf->barrier ||
 				    (atomic_read(&conf->nr_pending) &&
@@ -1037,9 +1070,14 @@ static void raid10_unplug(struct blk_plu
 
 	while (bio) { /* submit pending writes */
 		struct bio *next = bio->bi_next;
+		struct md_rdev *rdev = (void*)bio->bi_bdev;
 		bio->bi_next = NULL;
-		if (unlikely((bio_op(bio) ==  REQ_OP_DISCARD) &&
-		    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+		bio->bi_bdev = rdev->bdev;
+		if (test_bit(Faulty, &rdev->flags)) {
+			bio->bi_error = -EIO;
+			bio_endio(bio);
+		} else if (unlikely((bio_op(bio) ==  REQ_OP_DISCARD) &&
+				    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
 			/* Just ignore it */
 			bio_endio(bio);
 		else
@@ -1049,23 +1087,122 @@ static void raid10_unplug(struct blk_plu
 	kfree(plug);
 }
 
-static void __make_request(struct mddev *mddev, struct bio *bio)
+static void raid10_read_request(struct mddev *mddev, struct bio *bio,
+				struct r10bio *r10_bio)
 {
 	struct r10conf *conf = mddev->private;
-	struct r10bio *r10_bio;
 	struct bio *read_bio;
+	const int op = bio_op(bio);
+	const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
+	int sectors_handled;
+	int max_sectors;
+	sector_t sectors;
+	struct md_rdev *rdev;
+	int slot;
+
+	/*
+	 * Register the new request and wait if the reconstruction
+	 * thread has put up a bar for new requests.
+	 * Continue immediately if no resync is active currently.
+	 */
+	wait_barrier(conf);
+
+	sectors = bio_sectors(bio);
+	while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+	    bio->bi_iter.bi_sector < conf->reshape_progress &&
+	    bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
+		/*
+		 * IO spans the reshape position.  Need to wait for reshape to
+		 * pass
+		 */
+		raid10_log(conf->mddev, "wait reshape");
+		allow_barrier(conf);
+		wait_event(conf->wait_barrier,
+			   conf->reshape_progress <= bio->bi_iter.bi_sector ||
+			   conf->reshape_progress >= bio->bi_iter.bi_sector +
+			   sectors);
+		wait_barrier(conf);
+	}
+
+read_again:
+	rdev = read_balance(conf, r10_bio, &max_sectors);
+	if (!rdev) {
+		raid_end_bio_io(r10_bio);
+		return;
+	}
+	slot = r10_bio->read_slot;
+
+	read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+	bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector,
+		 max_sectors);
+
+	r10_bio->devs[slot].bio = read_bio;
+	r10_bio->devs[slot].rdev = rdev;
+
+	read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr +
+		choose_data_offset(r10_bio, rdev);
+	read_bio->bi_bdev = rdev->bdev;
+	read_bio->bi_end_io = raid10_end_read_request;
+	bio_set_op_attrs(read_bio, op, do_sync);
+	if (test_bit(FailFast, &rdev->flags) &&
+	    test_bit(R10BIO_FailFast, &r10_bio->state))
+	        read_bio->bi_opf |= MD_FAILFAST;
+	read_bio->bi_private = r10_bio;
+
+	if (mddev->gendisk)
+	        trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
+	                              read_bio, disk_devt(mddev->gendisk),
+	                              r10_bio->sector);
+	if (max_sectors < r10_bio->sectors) {
+		/*
+		 * Could not read all from this device, so we will need another
+		 * r10_bio.
+		 */
+		sectors_handled = (r10_bio->sector + max_sectors
+				   - bio->bi_iter.bi_sector);
+		r10_bio->sectors = max_sectors;
+		spin_lock_irq(&conf->device_lock);
+		if (bio->bi_phys_segments == 0)
+			bio->bi_phys_segments = 2;
+		else
+			bio->bi_phys_segments++;
+		spin_unlock_irq(&conf->device_lock);
+		/*
+		 * Cannot call generic_make_request directly as that will be
+		 * queued in __generic_make_request and subsequent
+		 * mempool_alloc might block waiting for it.  so hand bio over
+		 * to raid10d.
+		 */
+		reschedule_retry(r10_bio);
+
+		r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+		r10_bio->master_bio = bio;
+		r10_bio->sectors = bio_sectors(bio) - sectors_handled;
+		r10_bio->state = 0;
+		r10_bio->mddev = mddev;
+		r10_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
+		goto read_again;
+	} else
+		generic_make_request(read_bio);
+	return;
+}
+
+static void raid10_write_request(struct mddev *mddev, struct bio *bio,
+				 struct r10bio *r10_bio)
+{
+	struct r10conf *conf = mddev->private;
 	int i;
 	const int op = bio_op(bio);
-	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
 	const unsigned long do_fua = (bio->bi_opf & REQ_FUA);
 	unsigned long flags;
 	struct md_rdev *blocked_rdev;
 	struct blk_plug_cb *cb;
 	struct raid10_plug_cb *plug = NULL;
+	sector_t sectors;
 	int sectors_handled;
 	int max_sectors;
-	int sectors;
 
 	md_write_start(mddev, bio);
 
@@ -1080,9 +1217,11 @@ static void __make_request(struct mddev
 	while (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
 	    bio->bi_iter.bi_sector < conf->reshape_progress &&
 	    bio->bi_iter.bi_sector + sectors > conf->reshape_progress) {
-		/* IO spans the reshape position.  Need to wait for
-		 * reshape to pass
+		/*
+		 * IO spans the reshape position.  Need to wait for reshape to
+		 * pass
 		 */
+		raid10_log(conf->mddev, "wait reshape");
 		allow_barrier(conf);
 		wait_event(conf->wait_barrier,
 			   conf->reshape_progress <= bio->bi_iter.bi_sector ||
@@ -1090,8 +1229,8 @@ static void __make_request(struct mddev
 			   sectors);
 		wait_barrier(conf);
 	}
+
 	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
-	    bio_data_dir(bio) == WRITE &&
 	    (mddev->reshape_backwards
 	     ? (bio->bi_iter.bi_sector < conf->reshape_safe &&
 		bio->bi_iter.bi_sector + sectors > conf->reshape_progress)
@@ -1099,102 +1238,19 @@ static void __make_request(struct mddev
 		bio->bi_iter.bi_sector < conf->reshape_progress))) {
 		/* Need to update reshape_position in metadata */
 		mddev->reshape_position = conf->reshape_progress;
-		set_mask_bits(&mddev->flags, 0,
-			      BIT(MD_CHANGE_DEVS) | BIT(MD_CHANGE_PENDING));
+		set_mask_bits(&mddev->sb_flags, 0,
+			      BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
 		md_wakeup_thread(mddev->thread);
+		raid10_log(conf->mddev, "wait reshape metadata");
 		wait_event(mddev->sb_wait,
-			   !test_bit(MD_CHANGE_PENDING, &mddev->flags));
+			   !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
 
 		conf->reshape_safe = mddev->reshape_position;
 	}
 
-	r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
-
-	r10_bio->master_bio = bio;
-	r10_bio->sectors = sectors;
-
-	r10_bio->mddev = mddev;
-	r10_bio->sector = bio->bi_iter.bi_sector;
-	r10_bio->state = 0;
-
-	/* We might need to issue multiple reads to different
-	 * devices if there are bad blocks around, so we keep
-	 * track of the number of reads in bio->bi_phys_segments.
-	 * If this is 0, there is only one r10_bio and no locking
-	 * will be needed when the request completes.  If it is
-	 * non-zero, then it is the number of not-completed requests.
-	 */
-	bio->bi_phys_segments = 0;
-	bio_clear_flag(bio, BIO_SEG_VALID);
-
-	if (rw == READ) {
-		/*
-		 * read balancing logic:
-		 */
-		struct md_rdev *rdev;
-		int slot;
-
-read_again:
-		rdev = read_balance(conf, r10_bio, &max_sectors);
-		if (!rdev) {
-			raid_end_bio_io(r10_bio);
-			return;
-		}
-		slot = r10_bio->read_slot;
-
-		read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-		bio_trim(read_bio, r10_bio->sector - bio->bi_iter.bi_sector,
-			 max_sectors);
-
-		r10_bio->devs[slot].bio = read_bio;
-		r10_bio->devs[slot].rdev = rdev;
-
-		read_bio->bi_iter.bi_sector = r10_bio->devs[slot].addr +
-			choose_data_offset(r10_bio, rdev);
-		read_bio->bi_bdev = rdev->bdev;
-		read_bio->bi_end_io = raid10_end_read_request;
-		bio_set_op_attrs(read_bio, op, do_sync);
-		read_bio->bi_private = r10_bio;
-
-		if (max_sectors < r10_bio->sectors) {
-			/* Could not read all from this device, so we will
-			 * need another r10_bio.
-			 */
-			sectors_handled = (r10_bio->sector + max_sectors
-					   - bio->bi_iter.bi_sector);
-			r10_bio->sectors = max_sectors;
-			spin_lock_irq(&conf->device_lock);
-			if (bio->bi_phys_segments == 0)
-				bio->bi_phys_segments = 2;
-			else
-				bio->bi_phys_segments++;
-			spin_unlock_irq(&conf->device_lock);
-			/* Cannot call generic_make_request directly
-			 * as that will be queued in __generic_make_request
-			 * and subsequent mempool_alloc might block
-			 * waiting for it.  so hand bio over to raid10d.
-			 */
-			reschedule_retry(r10_bio);
-
-			r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
-
-			r10_bio->master_bio = bio;
-			r10_bio->sectors = bio_sectors(bio) - sectors_handled;
-			r10_bio->state = 0;
-			r10_bio->mddev = mddev;
-			r10_bio->sector = bio->bi_iter.bi_sector +
-				sectors_handled;
-			goto read_again;
-		} else
-			generic_make_request(read_bio);
-		return;
-	}
-
-	/*
-	 * WRITE:
-	 */
 	if (conf->pending_count >= max_queued_requests) {
 		md_wakeup_thread(mddev->thread);
+		raid10_log(mddev, "wait queued");
 		wait_event(conf->wait_barrier,
 			   conf->pending_count < max_queued_requests);
 	}
@@ -1252,8 +1308,7 @@ retry_write:
 			int bad_sectors;
 			int is_bad;
 
-			is_bad = is_badblock(rdev, dev_sector,
-					     max_sectors,
+			is_bad = is_badblock(rdev, dev_sector, max_sectors,
 					     &first_bad, &bad_sectors);
 			if (is_bad < 0) {
 				/* Mustn't write here until the bad block
@@ -1322,6 +1377,7 @@ retry_write:
 			}
 		}
 		allow_barrier(conf);
+		raid10_log(conf->mddev, "wait rdev %d blocked", blocked_rdev->raid_disk);
 		md_wait_for_blocked_rdev(blocked_rdev, mddev);
 		wait_barrier(conf);
 		goto retry_write;
@@ -1356,13 +1412,22 @@ retry_write:
 			r10_bio->devs[i].bio = mbio;
 
 			mbio->bi_iter.bi_sector	= (r10_bio->devs[i].addr+
-					   choose_data_offset(r10_bio,
-							      rdev));
+					   choose_data_offset(r10_bio, rdev));
 			mbio->bi_bdev = rdev->bdev;
 			mbio->bi_end_io	= raid10_end_write_request;
 			bio_set_op_attrs(mbio, op, do_sync | do_fua);
+			if (test_bit(FailFast, &conf->mirrors[d].rdev->flags) &&
+			    enough(conf, d))
+				mbio->bi_opf |= MD_FAILFAST;
 			mbio->bi_private = r10_bio;
 
+			if (conf->mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(mbio->bi_bdev),
+						      mbio, disk_devt(conf->mddev->gendisk),
+						      r10_bio->sector);
+			/* flush_pending_writes() needs access to the rdev so...*/
+			mbio->bi_bdev = (void*)rdev;
+
 			atomic_inc(&r10_bio->remaining);
 
 			cb = blk_check_plugged(raid10_unplug, mddev,
@@ -1398,13 +1463,19 @@ retry_write:
 			r10_bio->devs[i].repl_bio = mbio;
 
 			mbio->bi_iter.bi_sector	= (r10_bio->devs[i].addr +
-					   choose_data_offset(
-						   r10_bio, rdev));
+					   choose_data_offset(r10_bio, rdev));
 			mbio->bi_bdev = rdev->bdev;
 			mbio->bi_end_io	= raid10_end_write_request;
 			bio_set_op_attrs(mbio, op, do_sync | do_fua);
 			mbio->bi_private = r10_bio;
 
+			if (conf->mddev->gendisk)
+				trace_block_bio_remap(bdev_get_queue(mbio->bi_bdev),
+						      mbio, disk_devt(conf->mddev->gendisk),
+						      r10_bio->sector);
+			/* flush_pending_writes() needs access to the rdev so...*/
+			mbio->bi_bdev = (void*)rdev;
+
 			atomic_inc(&r10_bio->remaining);
 			spin_lock_irqsave(&conf->device_lock, flags);
 			bio_list_add(&conf->pending_bio_list, mbio);
@@ -1437,6 +1508,36 @@ retry_write:
 	one_write_done(r10_bio);
 }
 
+static void __make_request(struct mddev *mddev, struct bio *bio)
+{
+	struct r10conf *conf = mddev->private;
+	struct r10bio *r10_bio;
+
+	r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
+
+	r10_bio->master_bio = bio;
+	r10_bio->sectors = bio_sectors(bio);
+
+	r10_bio->mddev = mddev;
+	r10_bio->sector = bio->bi_iter.bi_sector;
+	r10_bio->state = 0;
+
+	/*
+	 * We might need to issue multiple reads to different devices if there
+	 * are bad blocks around, so we keep track of the number of reads in
+	 * bio->bi_phys_segments.  If this is 0, there is only one r10_bio and
+	 * no locking will be needed when the request completes.  If it is
+	 * non-zero, then it is the number of not-completed requests.
+	 */
+	bio->bi_phys_segments = 0;
+	bio_clear_flag(bio, BIO_SEG_VALID);
+
+	if (bio_data_dir(bio) == READ)
+		raid10_read_request(mddev, bio, r10_bio);
+	else
+		raid10_write_request(mddev, bio, r10_bio);
+}
+
 static void raid10_make_request(struct mddev *mddev, struct bio *bio)
 {
 	struct r10conf *conf = mddev->private;
@@ -1586,14 +1687,13 @@ static void raid10_error(struct mddev *m
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 	set_bit(Blocked, &rdev->flags);
 	set_bit(Faulty, &rdev->flags);
-	set_mask_bits(&mddev->flags, 0,
-		      BIT(MD_CHANGE_DEVS) | BIT(MD_CHANGE_PENDING));
+	set_mask_bits(&mddev->sb_flags, 0,
+		      BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
 	spin_unlock_irqrestore(&conf->device_lock, flags);
-	printk(KERN_ALERT
-	       "md/raid10:%s: Disk failure on %s, disabling device.\n"
-	       "md/raid10:%s: Operation continuing on %d devices.\n",
-	       mdname(mddev), bdevname(rdev->bdev, b),
-	       mdname(mddev), conf->geo.raid_disks - mddev->degraded);
+	pr_crit("md/raid10:%s: Disk failure on %s, disabling device.\n"
+		"md/raid10:%s: Operation continuing on %d devices.\n",
+		mdname(mddev), bdevname(rdev->bdev, b),
+		mdname(mddev), conf->geo.raid_disks - mddev->degraded);
 }
 
 static void print_conf(struct r10conf *conf)
@@ -1601,13 +1701,13 @@ static void print_conf(struct r10conf *c
 	int i;
 	struct md_rdev *rdev;
 
-	printk(KERN_DEBUG "RAID10 conf printout:\n");
+	pr_debug("RAID10 conf printout:\n");
 	if (!conf) {
-		printk(KERN_DEBUG "(!conf)\n");
+		pr_debug("(!conf)\n");
 		return;
 	}
-	printk(KERN_DEBUG " --- wd:%d rd:%d\n", conf->geo.raid_disks - conf->mddev->degraded,
-		conf->geo.raid_disks);
+	pr_debug(" --- wd:%d rd:%d\n", conf->geo.raid_disks - conf->mddev->degraded,
+		 conf->geo.raid_disks);
 
 	/* This is only called with ->reconfix_mutex held, so
 	 * rcu protection of rdev is not needed */
@@ -1615,10 +1715,10 @@ static void print_conf(struct r10conf *c
 		char b[BDEVNAME_SIZE];
 		rdev = 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),
-			        !test_bit(Faulty, &rdev->flags),
-				bdevname(rdev->bdev,b));
+			pr_debug(" disk %d, wo:%d, o:%d, dev:%s\n",
+				 i, !test_bit(In_sync, &rdev->flags),
+				 !test_bit(Faulty, &rdev->flags),
+				 bdevname(rdev->bdev,b));
 	}
 }
 
@@ -1953,6 +2053,7 @@ static void sync_request_write(struct md
 	/* now find blocks with errors */
 	for (i=0 ; i < conf->copies ; i++) {
 		int  j, d;
+		struct md_rdev *rdev;
 
 		tbio = r10_bio->devs[i].bio;
 
@@ -1960,6 +2061,8 @@ static void sync_request_write(struct md
 			continue;
 		if (i == first)
 			continue;
+		d = r10_bio->devs[i].devnum;
+		rdev = conf->mirrors[d].rdev;
 		if (!r10_bio->devs[i].bio->bi_error) {
 			/* We know that the bi_io_vec layout is the same for
 			 * both 'first' and 'i', so we just compare them.
@@ -1982,6 +2085,10 @@ static void sync_request_write(struct md
 			if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
 				/* Don't fix anything. */
 				continue;
+		} else if (test_bit(FailFast, &rdev->flags)) {
+			/* Just give up on this device */
+			md_error(rdev->mddev, rdev);
+			continue;
 		}
 		/* Ok, we need to write this bio, either to correct an
 		 * inconsistency or to correct an unreadable block.
@@ -1999,11 +2106,12 @@ static void sync_request_write(struct md
 
 		bio_copy_data(tbio, fbio);
 
-		d = r10_bio->devs[i].devnum;
 		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
 		atomic_inc(&r10_bio->remaining);
 		md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(tbio));
 
+		if (test_bit(FailFast, &conf->mirrors[d].rdev->flags))
+			tbio->bi_opf |= MD_FAILFAST;
 		tbio->bi_iter.bi_sector += conf->mirrors[d].rdev->data_offset;
 		tbio->bi_bdev = conf->mirrors[d].rdev->bdev;
 		generic_make_request(tbio);
@@ -2109,10 +2217,8 @@ static void fix_recovery_read_error(stru
 				ok = rdev_set_badblocks(rdev2, addr, s, 0);
 				if (!ok) {
 					/* just abort the recovery */
-					printk(KERN_NOTICE
-					       "md/raid10:%s: recovery aborted"
-					       " due to read error\n",
-					       mdname(mddev));
+					pr_notice("md/raid10:%s: recovery aborted due to read error\n",
+						  mdname(mddev));
 
 					conf->mirrors[dw].recovery_disabled
 						= mddev->recovery_disabled;
@@ -2259,14 +2365,11 @@ static void fix_read_error(struct r10con
 		char b[BDEVNAME_SIZE];
 		bdevname(rdev->bdev, b);
 
-		printk(KERN_NOTICE
-		       "md/raid10:%s: %s: Raid device exceeded "
-		       "read_error threshold [cur %d:max %d]\n",
-		       mdname(mddev), b,
-		       atomic_read(&rdev->read_errors), max_read_errors);
-		printk(KERN_NOTICE
-		       "md/raid10:%s: %s: Failing raid device\n",
-		       mdname(mddev), b);
+		pr_notice("md/raid10:%s: %s: Raid device exceeded read_error threshold [cur %d:max %d]\n",
+			  mdname(mddev), b,
+			  atomic_read(&rdev->read_errors), max_read_errors);
+		pr_notice("md/raid10:%s: %s: Failing raid device\n",
+			  mdname(mddev), b);
 		md_error(mddev, rdev);
 		r10_bio->devs[r10_bio->read_slot].bio = IO_BLOCKED;
 		return;
@@ -2356,20 +2459,16 @@ static void fix_read_error(struct r10con
 					     s, conf->tmppage, WRITE)
 			    == 0) {
 				/* Well, this device is dead */
-				printk(KERN_NOTICE
-				       "md/raid10:%s: read correction "
-				       "write failed"
-				       " (%d sectors at %llu on %s)\n",
-				       mdname(mddev), s,
-				       (unsigned long long)(
-					       sect +
-					       choose_data_offset(r10_bio,
-								  rdev)),
-				       bdevname(rdev->bdev, b));
-				printk(KERN_NOTICE "md/raid10:%s: %s: failing "
-				       "drive\n",
-				       mdname(mddev),
-				       bdevname(rdev->bdev, b));
+				pr_notice("md/raid10:%s: read correction write failed (%d sectors at %llu on %s)\n",
+					  mdname(mddev), s,
+					  (unsigned long long)(
+						  sect +
+						  choose_data_offset(r10_bio,
+								     rdev)),
+					  bdevname(rdev->bdev, b));
+				pr_notice("md/raid10:%s: %s: failing drive\n",
+					  mdname(mddev),
+					  bdevname(rdev->bdev, b));
 			}
 			rdev_dec_pending(rdev, mddev);
 			rcu_read_lock();
@@ -2397,24 +2496,18 @@ static void fix_read_error(struct r10con
 						 READ)) {
 			case 0:
 				/* Well, this device is dead */
-				printk(KERN_NOTICE
-				       "md/raid10:%s: unable to read back "
-				       "corrected sectors"
-				       " (%d sectors at %llu on %s)\n",
+				pr_notice("md/raid10:%s: unable to read back corrected sectors (%d sectors at %llu on %s)\n",
 				       mdname(mddev), s,
 				       (unsigned long long)(
 					       sect +
 					       choose_data_offset(r10_bio, rdev)),
 				       bdevname(rdev->bdev, b));
-				printk(KERN_NOTICE "md/raid10:%s: %s: failing "
-				       "drive\n",
+				pr_notice("md/raid10:%s: %s: failing drive\n",
 				       mdname(mddev),
 				       bdevname(rdev->bdev, b));
 				break;
 			case 1:
-				printk(KERN_INFO
-				       "md/raid10:%s: read error corrected"
-				       " (%d sectors at %llu on %s)\n",
+				pr_info("md/raid10:%s: read error corrected (%d sectors at %llu on %s)\n",
 				       mdname(mddev), s,
 				       (unsigned long long)(
 					       sect +
@@ -2503,6 +2596,8 @@ static void handle_read_error(struct mdd
 	char b[BDEVNAME_SIZE];
 	unsigned long do_sync;
 	int max_sectors;
+	dev_t bio_dev;
+	sector_t bio_last_sector;
 
 	/* we got a read error. Maybe the drive is bad.  Maybe just
 	 * the block and we can fix it.
@@ -2514,38 +2609,38 @@ static void handle_read_error(struct mdd
 	 */
 	bio = r10_bio->devs[slot].bio;
 	bdevname(bio->bi_bdev, b);
+	bio_dev = bio->bi_bdev->bd_dev;
+	bio_last_sector = r10_bio->devs[slot].addr + rdev->data_offset + r10_bio->sectors;
 	bio_put(bio);
 	r10_bio->devs[slot].bio = NULL;
 
-	if (mddev->ro == 0) {
+	if (mddev->ro)
+		r10_bio->devs[slot].bio = IO_BLOCKED;
+	else if (!test_bit(FailFast, &rdev->flags)) {
 		freeze_array(conf, 1);
 		fix_read_error(conf, mddev, r10_bio);
 		unfreeze_array(conf);
 	} else
-		r10_bio->devs[slot].bio = IO_BLOCKED;
+		md_error(mddev, rdev);
 
 	rdev_dec_pending(rdev, mddev);
 
 read_more:
 	rdev = read_balance(conf, r10_bio, &max_sectors);
 	if (rdev == NULL) {
-		printk(KERN_ALERT "md/raid10:%s: %s: unrecoverable I/O"
-		       " read error for block %llu\n",
-		       mdname(mddev), b,
-		       (unsigned long long)r10_bio->sector);
+		pr_crit_ratelimited("md/raid10:%s: %s: unrecoverable I/O read error for block %llu\n",
+				    mdname(mddev), b,
+				    (unsigned long long)r10_bio->sector);
 		raid_end_bio_io(r10_bio);
 		return;
 	}
 
 	do_sync = (r10_bio->master_bio->bi_opf & REQ_SYNC);
 	slot = r10_bio->read_slot;
-	printk_ratelimited(
-		KERN_ERR
-		"md/raid10:%s: %s: redirecting "
-		"sector %llu to another mirror\n",
-		mdname(mddev),
-		bdevname(rdev->bdev, b),
-		(unsigned long long)r10_bio->sector);
+	pr_err_ratelimited("md/raid10:%s: %s: redirecting sector %llu to another mirror\n",
+			   mdname(mddev),
+			   bdevname(rdev->bdev, b),
+			   (unsigned long long)r10_bio->sector);
 	bio = bio_clone_mddev(r10_bio->master_bio,
 			      GFP_NOIO, mddev);
 	bio_trim(bio, r10_bio->sector - bio->bi_iter.bi_sector, max_sectors);
@@ -2555,8 +2650,15 @@ read_more:
 		+ choose_data_offset(r10_bio, rdev);
 	bio->bi_bdev = rdev->bdev;
 	bio_set_op_attrs(bio, REQ_OP_READ, do_sync);
+	if (test_bit(FailFast, &rdev->flags) &&
+	    test_bit(R10BIO_FailFast, &r10_bio->state))
+		bio->bi_opf |= MD_FAILFAST;
 	bio->bi_private = r10_bio;
 	bio->bi_end_io = raid10_end_read_request;
+	trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
+			      bio, bio_dev,
+			      bio_last_sector - r10_bio->sectors);
+
 	if (max_sectors < r10_bio->sectors) {
 		/* Drat - have to split this up more */
 		struct bio *mbio = r10_bio->master_bio;
@@ -2694,10 +2796,10 @@ static void raid10d(struct md_thread *th
 	md_check_recovery(mddev);
 
 	if (!list_empty_careful(&conf->bio_end_io_list) &&
-	    !test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+	    !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
 		LIST_HEAD(tmp);
 		spin_lock_irqsave(&conf->device_lock, flags);
-		if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+		if (!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
 			while (!list_empty(&conf->bio_end_io_list)) {
 				list_move(conf->bio_end_io_list.prev, &tmp);
 				conf->nr_queued--;
@@ -2755,7 +2857,7 @@ static void raid10d(struct md_thread *th
 		}
 
 		cond_resched();
-		if (mddev->flags & ~(1<<MD_CHANGE_PENDING))
+		if (mddev->sb_flags & ~(1<<MD_SB_CHANGE_PENDING))
 			md_check_recovery(mddev);
 	}
 	blk_finish_plug(&plug);
@@ -3072,6 +3174,8 @@ static sector_t raid10_sync_request(stru
 				bio->bi_private = r10_bio;
 				bio->bi_end_io = end_sync_read;
 				bio_set_op_attrs(bio, REQ_OP_READ, 0);
+				if (test_bit(FailFast, &rdev->flags))
+					bio->bi_opf |= MD_FAILFAST;
 				from_addr = r10_bio->devs[j].addr;
 				bio->bi_iter.bi_sector = from_addr +
 					rdev->data_offset;
@@ -3160,8 +3264,7 @@ static sector_t raid10_sync_request(stru
 				if (!any_working)  {
 					if (!test_and_set_bit(MD_RECOVERY_INTR,
 							      &mddev->recovery))
-						printk(KERN_INFO "md/raid10:%s: insufficient "
-						       "working devices for recovery.\n",
+						pr_warn("md/raid10:%s: insufficient working devices for recovery.\n",
 						       mdname(mddev));
 					mirror->recovery_disabled
 						= mddev->recovery_disabled;
@@ -3178,6 +3281,23 @@ static sector_t raid10_sync_request(stru
 			rdev_dec_pending(mrdev, mddev);
 			if (mreplace)
 				rdev_dec_pending(mreplace, mddev);
+			if (r10_bio->devs[0].bio->bi_opf & MD_FAILFAST) {
+				/* Only want this if there is elsewhere to
+				 * read from. 'j' is currently the first
+				 * readable copy.
+				 */
+				int targets = 1;
+				for (; j < conf->copies; j++) {
+					int d = r10_bio->devs[j].devnum;
+					if (conf->mirrors[d].rdev &&
+					    test_bit(In_sync,
+						      &conf->mirrors[d].rdev->flags))
+						targets++;
+				}
+				if (targets == 1)
+					r10_bio->devs[0].bio->bi_opf
+						&= ~MD_FAILFAST;
+			}
 		}
 		if (biolist == NULL) {
 			while (r10_bio) {
@@ -3256,6 +3376,8 @@ static sector_t raid10_sync_request(stru
 			bio->bi_private = r10_bio;
 			bio->bi_end_io = end_sync_read;
 			bio_set_op_attrs(bio, REQ_OP_READ, 0);
+			if (test_bit(FailFast, &conf->mirrors[d].rdev->flags))
+				bio->bi_opf |= MD_FAILFAST;
 			bio->bi_iter.bi_sector = sector + rdev->data_offset;
 			bio->bi_bdev = rdev->bdev;
 			count++;
@@ -3279,6 +3401,8 @@ static sector_t raid10_sync_request(stru
 			bio->bi_private = r10_bio;
 			bio->bi_end_io = end_sync_write;
 			bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
+			if (test_bit(FailFast, &conf->mirrors[d].rdev->flags))
+				bio->bi_opf |= MD_FAILFAST;
 			bio->bi_iter.bi_sector = sector + rdev->data_offset;
 			bio->bi_bdev = rdev->bdev;
 			count++;
@@ -3489,15 +3613,14 @@ static struct r10conf *setup_conf(struct
 	copies = setup_geo(&geo, mddev, geo_new);
 
 	if (copies == -2) {
-		printk(KERN_ERR "md/raid10:%s: chunk size must be "
-		       "at least PAGE_SIZE(%ld) and be a power of 2.\n",
-		       mdname(mddev), PAGE_SIZE);
+		pr_warn("md/raid10:%s: chunk size must be at least PAGE_SIZE(%ld) and be a power of 2.\n",
+			mdname(mddev), PAGE_SIZE);
 		goto out;
 	}
 
 	if (copies < 2 || copies > mddev->raid_disks) {
-		printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
-		       mdname(mddev), mddev->new_layout);
+		pr_warn("md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
+			mdname(mddev), mddev->new_layout);
 		goto out;
 	}
 
@@ -3557,9 +3680,6 @@ static struct r10conf *setup_conf(struct
 	return conf;
 
  out:
-	if (err == -ENOMEM)
-		printk(KERN_ERR "md/raid10:%s: couldn't allocate memory.\n",
-		       mdname(mddev));
 	if (conf) {
 		mempool_destroy(conf->r10bio_pool);
 		kfree(conf->mirrors);
@@ -3656,7 +3776,7 @@ static int raid10_run(struct mddev *mdde
 	}
 	/* need to check that every block has at least one working mirror */
 	if (!enough(conf, -1)) {
-		printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
+		pr_err("md/raid10:%s: not enough operational mirrors.\n",
 		       mdname(mddev));
 		goto out_free_conf;
 	}
@@ -3698,11 +3818,9 @@ static int raid10_run(struct mddev *mdde
 	}
 
 	if (mddev->recovery_cp != MaxSector)
-		printk(KERN_NOTICE "md/raid10:%s: not clean"
-		       " -- starting background reconstruction\n",
-		       mdname(mddev));
-	printk(KERN_INFO
-		"md/raid10:%s: active with %d out of %d devices\n",
+		pr_notice("md/raid10:%s: not clean -- starting background reconstruction\n",
+			  mdname(mddev));
+	pr_info("md/raid10:%s: active with %d out of %d devices\n",
 		mdname(mddev), conf->geo.raid_disks - mddev->degraded,
 		conf->geo.raid_disks);
 	/*
@@ -3712,6 +3830,7 @@ static int raid10_run(struct mddev *mdde
 	size = raid10_size(mddev, 0, 0);
 	md_set_array_sectors(mddev, size);
 	mddev->resync_max_sectors = size;
+	set_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
 
 	if (mddev->queue) {
 		int stripe = conf->geo.raid_disks *
@@ -3739,7 +3858,7 @@ static int raid10_run(struct mddev *mdde
 
 		if (max(before_length, after_length) > min_offset_diff) {
 			/* This cannot work */
-			printk("md/raid10: offset difference not enough to continue reshape\n");
+			pr_warn("md/raid10: offset difference not enough to continue reshape\n");
 			goto out_free_conf;
 		}
 		conf->offset_diff = min_offset_diff;
@@ -3846,8 +3965,8 @@ static void *raid10_takeover_raid0(struc
 	struct r10conf *conf;
 
 	if (mddev->degraded > 0) {
-		printk(KERN_ERR "md/raid10:%s: Error: degraded raid0!\n",
-		       mdname(mddev));
+		pr_warn("md/raid10:%s: Error: degraded raid0!\n",
+			mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
 	sector_div(size, devs);
@@ -3887,9 +4006,8 @@ static void *raid10_takeover(struct mdde
 		/* for raid0 takeover only one zone is supported */
 		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));
+			pr_warn("md/raid10:%s: cannot takeover raid 0 with more than one zone.\n",
+				mdname(mddev));
 			return ERR_PTR(-EINVAL);
 		}
 		return raid10_takeover_raid0(mddev,
@@ -4078,8 +4196,8 @@ static int raid10_start_reshape(struct m
 		sector_t size = raid10_size(mddev, 0, 0);
 		if (size < mddev->array_sectors) {
 			spin_unlock_irq(&conf->device_lock);
-			printk(KERN_ERR "md/raid10:%s: array size must be reduce before number of disks\n",
-			       mdname(mddev));
+			pr_warn("md/raid10:%s: array size must be reduce before number of disks\n",
+				mdname(mddev));
 			return -EINVAL;
 		}
 		mddev->resync_max_sectors = size;
@@ -4126,7 +4244,7 @@ static int raid10_start_reshape(struct m
 	spin_unlock_irq(&conf->device_lock);
 	mddev->raid_disks = conf->geo.raid_disks;
 	mddev->reshape_position = conf->reshape_progress;
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 
 	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 	clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
@@ -4321,9 +4439,9 @@ static sector_t reshape_request(struct m
 		else
 			mddev->curr_resync_completed = conf->reshape_progress;
 		conf->reshape_checkpoint = jiffies;
-		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		md_wakeup_thread(mddev->thread);
-		wait_event(mddev->sb_wait, mddev->flags == 0 ||
+		wait_event(mddev->sb_wait, mddev->sb_flags == 0 ||
 			   test_bit(MD_RECOVERY_INTR, &mddev->recovery));
 		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
 			allow_barrier(conf);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid10.h linux-libre-4.10-rc8-gnu/drivers/md/raid10.h
--- linux-libre-4.9-gnu/drivers/md/raid10.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid10.h	2017-02-12 16:03:20.000000000 -0500
@@ -156,5 +156,7 @@ enum r10bio_state {
  * flag is set
  */
 	R10BIO_Previous,
+/* failfast devices did receive failfast requests. */
+	R10BIO_FailFast,
 };
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid1.c linux-libre-4.10-rc8-gnu/drivers/md/raid1.c
--- linux-libre-4.9-gnu/drivers/md/raid1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid1.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,10 +37,15 @@
 #include <linux/module.h>
 #include <linux/seq_file.h>
 #include <linux/ratelimit.h>
+#include <trace/events/block.h>
 #include "md.h"
 #include "raid1.h"
 #include "bitmap.h"
 
+#define UNSUPPORTED_MDDEV_FLAGS		\
+	((1L << MD_HAS_JOURNAL) |	\
+	 (1L << MD_JOURNAL_CLEAN))
+
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
  */
@@ -70,6 +75,9 @@ static void allow_barrier(struct r1conf
 			  sector_t bi_sector);
 static void lower_barrier(struct r1conf *conf);
 
+#define raid1_log(md, fmt, args...)				\
+	do { if ((md)->queue) blk_add_trace_msg((md)->queue, "raid1 " fmt, ##args); } while (0)
+
 static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct pool_info *pi = data;
@@ -325,6 +333,11 @@ static void raid1_end_read_request(struc
 
 	if (uptodate)
 		set_bit(R1BIO_Uptodate, &r1_bio->state);
+	else if (test_bit(FailFast, &rdev->flags) &&
+		 test_bit(R1BIO_FailFast, &r1_bio->state))
+		/* This was a fail-fast read so we definitely
+		 * want to retry */
+		;
 	else {
 		/* If all other devices have failed, we want to return
 		 * the error upwards rather than fail the last device.
@@ -347,13 +360,10 @@ static void raid1_end_read_request(struc
 		 * oops, read error:
 		 */
 		char b[BDEVNAME_SIZE];
-		printk_ratelimited(
-			KERN_ERR "md/raid1:%s: %s: "
-			"rescheduling sector %llu\n",
-			mdname(conf->mddev),
-			bdevname(rdev->bdev,
-				 b),
-			(unsigned long long)r1_bio->sector);
+		pr_err_ratelimited("md/raid1:%s: %s: rescheduling sector %llu\n",
+				   mdname(conf->mddev),
+				   bdevname(rdev->bdev, b),
+				   (unsigned long long)r1_bio->sector);
 		set_bit(R1BIO_ReadError, &r1_bio->state);
 		reschedule_retry(r1_bio);
 		/* don't drop the reference on read_disk yet */
@@ -416,7 +426,24 @@ static void raid1_end_write_request(stru
 			set_bit(MD_RECOVERY_NEEDED, &
 				conf->mddev->recovery);
 
-		set_bit(R1BIO_WriteError, &r1_bio->state);
+		if (test_bit(FailFast, &rdev->flags) &&
+		    (bio->bi_opf & MD_FAILFAST) &&
+		    /* We never try FailFast to WriteMostly devices */
+		    !test_bit(WriteMostly, &rdev->flags)) {
+			md_error(r1_bio->mddev, rdev);
+			if (!test_bit(Faulty, &rdev->flags))
+				/* This is the only remaining device,
+				 * We need to retry the write without
+				 * FailFast
+				 */
+				set_bit(R1BIO_WriteError, &r1_bio->state);
+			else {
+				/* Finished with this branch */
+				r1_bio->bios[mirror] = NULL;
+				to_put = bio;
+			}
+		} else
+			set_bit(R1BIO_WriteError, &r1_bio->state);
 	} else {
 		/*
 		 * Set R1BIO_Uptodate in our master bio, so that we
@@ -534,6 +561,7 @@ static int read_balance(struct r1conf *c
 	best_good_sectors = 0;
 	has_nonrot_disk = 0;
 	choose_next_idle = 0;
+	clear_bit(R1BIO_FailFast, &r1_bio->state);
 
 	if ((conf->mddev->recovery_cp < this_sector + sectors) ||
 	    (mddev_is_clustered(conf->mddev) &&
@@ -607,6 +635,10 @@ static int read_balance(struct r1conf *c
 		} else
 			best_good_sectors = sectors;
 
+		if (best_disk >= 0)
+			/* At least two disks to choose from so failfast is OK */
+			set_bit(R1BIO_FailFast, &r1_bio->state);
+
 		nonrot = blk_queue_nonrot(bdev_get_queue(rdev->bdev));
 		has_nonrot_disk |= nonrot;
 		pending = atomic_read(&rdev->nr_pending);
@@ -645,11 +677,6 @@ static int read_balance(struct r1conf *c
 			}
 			break;
 		}
-		/* If device is idle, use it */
-		if (pending == 0) {
-			best_disk = disk;
-			break;
-		}
 
 		if (choose_next_idle)
 			continue;
@@ -672,7 +699,7 @@ static int read_balance(struct r1conf *c
 	 * mixed ratation/non-rotational disks depending on workload.
 	 */
 	if (best_disk == -1) {
-		if (has_nonrot_disk)
+		if (has_nonrot_disk || min_pending == 0)
 			best_disk = best_pending_disk;
 		else
 			best_disk = best_dist_disk;
@@ -745,9 +772,14 @@ static void flush_pending_writes(struct
 
 		while (bio) { /* submit pending writes */
 			struct bio *next = bio->bi_next;
+			struct md_rdev *rdev = (void*)bio->bi_bdev;
 			bio->bi_next = NULL;
-			if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
-			    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+			bio->bi_bdev = rdev->bdev;
+			if (test_bit(Faulty, &rdev->flags)) {
+				bio->bi_error = -EIO;
+				bio_endio(bio);
+			} else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
+					    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
 				/* Just ignore it */
 				bio_endio(bio);
 			else
@@ -832,7 +864,7 @@ static bool need_to_wait_for_sync(struct
 	else if (conf->barrier && bio_data_dir(bio) == WRITE) {
 		if ((conf->mddev->curr_resync_completed
 		     >= bio_end_sector(bio)) ||
-		    (conf->next_resync + NEXT_NORMALIO_DISTANCE
+		    (conf->start_next_window + NEXT_NORMALIO_DISTANCE
 		     <= bio->bi_iter.bi_sector))
 			wait = false;
 		else
@@ -858,6 +890,7 @@ static sector_t wait_barrier(struct r1co
 		 * that queue to allow conf->start_next_window
 		 * to increase.
 		 */
+		raid1_log(conf->mddev, "wait barrier");
 		wait_event_lock_irq(conf->wait_barrier,
 				    !conf->array_frozen &&
 				    (!conf->barrier ||
@@ -937,6 +970,7 @@ static void freeze_array(struct r1conf *
 	 */
 	spin_lock_irq(&conf->resync_lock);
 	conf->array_frozen = 1;
+	raid1_log(conf->mddev, "wait freeze");
 	wait_event_lock_irq_cmd(conf->wait_barrier,
 				conf->nr_pending == conf->nr_queued+extra,
 				conf->resync_lock,
@@ -1019,9 +1053,14 @@ static void raid1_unplug(struct blk_plug
 
 	while (bio) { /* submit pending writes */
 		struct bio *next = bio->bi_next;
+		struct md_rdev *rdev = (void*)bio->bi_bdev;
 		bio->bi_next = NULL;
-		if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
-		    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
+		bio->bi_bdev = rdev->bdev;
+		if (test_bit(Faulty, &rdev->flags)) {
+			bio->bi_error = -EIO;
+			bio_endio(bio);
+		} else if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
+				    !blk_queue_discard(bdev_get_queue(bio->bi_bdev))))
 			/* Just ignore it */
 			bio_endio(bio);
 		else
@@ -1031,17 +1070,107 @@ static void raid1_unplug(struct blk_plug
 	kfree(plug);
 }
 
-static void raid1_make_request(struct mddev *mddev, struct bio * bio)
+static void raid1_read_request(struct mddev *mddev, struct bio *bio,
+				 struct r1bio *r1_bio)
 {
 	struct r1conf *conf = mddev->private;
 	struct raid1_info *mirror;
-	struct r1bio *r1_bio;
 	struct bio *read_bio;
+	struct bitmap *bitmap = mddev->bitmap;
+	const int op = bio_op(bio);
+	const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
+	int sectors_handled;
+	int max_sectors;
+	int rdisk;
+
+	wait_barrier(conf, bio);
+
+read_again:
+	rdisk = read_balance(conf, r1_bio, &max_sectors);
+
+	if (rdisk < 0) {
+		/* couldn't find anywhere to read from */
+		raid_end_bio_io(r1_bio);
+		return;
+	}
+	mirror = conf->mirrors + rdisk;
+
+	if (test_bit(WriteMostly, &mirror->rdev->flags) &&
+	    bitmap) {
+		/*
+		 * Reading from a write-mostly device must take care not to
+		 * over-take any writes that are 'behind'
+		 */
+		raid1_log(mddev, "wait behind writes");
+		wait_event(bitmap->behind_wait,
+			   atomic_read(&bitmap->behind_writes) == 0);
+	}
+	r1_bio->read_disk = rdisk;
+	r1_bio->start_next_window = 0;
+
+	read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+	bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector,
+		 max_sectors);
+
+	r1_bio->bios[rdisk] = read_bio;
+
+	read_bio->bi_iter.bi_sector = r1_bio->sector +
+		mirror->rdev->data_offset;
+	read_bio->bi_bdev = mirror->rdev->bdev;
+	read_bio->bi_end_io = raid1_end_read_request;
+	bio_set_op_attrs(read_bio, op, do_sync);
+	if (test_bit(FailFast, &mirror->rdev->flags) &&
+	    test_bit(R1BIO_FailFast, &r1_bio->state))
+	        read_bio->bi_opf |= MD_FAILFAST;
+	read_bio->bi_private = r1_bio;
+
+	if (mddev->gendisk)
+	        trace_block_bio_remap(bdev_get_queue(read_bio->bi_bdev),
+	                              read_bio, disk_devt(mddev->gendisk),
+	                              r1_bio->sector);
+
+	if (max_sectors < r1_bio->sectors) {
+		/*
+		 * could not read all from this device, so we will need another
+		 * r1_bio.
+		 */
+		sectors_handled = (r1_bio->sector + max_sectors
+				   - bio->bi_iter.bi_sector);
+		r1_bio->sectors = max_sectors;
+		spin_lock_irq(&conf->device_lock);
+		if (bio->bi_phys_segments == 0)
+			bio->bi_phys_segments = 2;
+		else
+			bio->bi_phys_segments++;
+		spin_unlock_irq(&conf->device_lock);
+
+		/*
+		 * Cannot call generic_make_request directly as that will be
+		 * queued in __make_request and subsequent mempool_alloc might
+		 * block waiting for it.  So hand bio over to raid1d.
+		 */
+		reschedule_retry(r1_bio);
+
+		r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
+
+		r1_bio->master_bio = bio;
+		r1_bio->sectors = bio_sectors(bio) - sectors_handled;
+		r1_bio->state = 0;
+		r1_bio->mddev = mddev;
+		r1_bio->sector = bio->bi_iter.bi_sector + sectors_handled;
+		goto read_again;
+	} else
+		generic_make_request(read_bio);
+}
+
+static void raid1_write_request(struct mddev *mddev, struct bio *bio,
+				struct r1bio *r1_bio)
+{
+	struct r1conf *conf = mddev->private;
 	int i, disks;
-	struct bitmap *bitmap;
+	struct bitmap *bitmap = mddev->bitmap;
 	unsigned long flags;
 	const int op = bio_op(bio);
-	const int rw = bio_data_dir(bio);
 	const unsigned long do_sync = (bio->bi_opf & REQ_SYNC);
 	const unsigned long do_flush_fua = (bio->bi_opf &
 						(REQ_PREFLUSH | REQ_FUA));
@@ -1061,15 +1190,15 @@ static void raid1_make_request(struct md
 
 	md_write_start(mddev, bio); /* wait on superblock update early */
 
-	if (bio_data_dir(bio) == WRITE &&
-	    ((bio_end_sector(bio) > mddev->suspend_lo &&
+	if ((bio_end_sector(bio) > mddev->suspend_lo &&
 	    bio->bi_iter.bi_sector < mddev->suspend_hi) ||
 	    (mddev_is_clustered(mddev) &&
 	     md_cluster_ops->area_resyncing(mddev, WRITE,
-		     bio->bi_iter.bi_sector, bio_end_sector(bio))))) {
-		/* As the suspend_* range is controlled by
-		 * userspace, we want an interruptible
-		 * wait.
+		     bio->bi_iter.bi_sector, bio_end_sector(bio)))) {
+
+		/*
+		 * As the suspend_* range is controlled by userspace, we want
+		 * an interruptible wait.
 		 */
 		DEFINE_WAIT(w);
 		for (;;) {
@@ -1080,121 +1209,18 @@ static void raid1_make_request(struct md
 			    bio->bi_iter.bi_sector >= mddev->suspend_hi ||
 			    (mddev_is_clustered(mddev) &&
 			     !md_cluster_ops->area_resyncing(mddev, WRITE,
-				     bio->bi_iter.bi_sector, bio_end_sector(bio))))
+				     bio->bi_iter.bi_sector,
+				     bio_end_sector(bio))))
 				break;
 			schedule();
 		}
 		finish_wait(&conf->wait_barrier, &w);
 	}
-
 	start_next_window = wait_barrier(conf, bio);
 
-	bitmap = mddev->bitmap;
-
-	/*
-	 * make_request() can abort the operation when read-ahead is being
-	 * used and no empty request is available.
-	 *
-	 */
-	r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
-
-	r1_bio->master_bio = bio;
-	r1_bio->sectors = bio_sectors(bio);
-	r1_bio->state = 0;
-	r1_bio->mddev = mddev;
-	r1_bio->sector = bio->bi_iter.bi_sector;
-
-	/* We might need to issue multiple reads to different
-	 * devices if there are bad blocks around, so we keep
-	 * track of the number of reads in bio->bi_phys_segments.
-	 * If this is 0, there is only one r1_bio and no locking
-	 * will be needed when requests complete.  If it is
-	 * non-zero, then it is the number of not-completed requests.
-	 */
-	bio->bi_phys_segments = 0;
-	bio_clear_flag(bio, BIO_SEG_VALID);
-
-	if (rw == READ) {
-		/*
-		 * read balancing logic:
-		 */
-		int rdisk;
-
-read_again:
-		rdisk = read_balance(conf, r1_bio, &max_sectors);
-
-		if (rdisk < 0) {
-			/* couldn't find anywhere to read from */
-			raid_end_bio_io(r1_bio);
-			return;
-		}
-		mirror = conf->mirrors + rdisk;
-
-		if (test_bit(WriteMostly, &mirror->rdev->flags) &&
-		    bitmap) {
-			/* Reading from a write-mostly device must
-			 * take care not to over-take any writes
-			 * that are 'behind'
-			 */
-			wait_event(bitmap->behind_wait,
-				   atomic_read(&bitmap->behind_writes) == 0);
-		}
-		r1_bio->read_disk = rdisk;
-		r1_bio->start_next_window = 0;
-
-		read_bio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-		bio_trim(read_bio, r1_bio->sector - bio->bi_iter.bi_sector,
-			 max_sectors);
-
-		r1_bio->bios[rdisk] = read_bio;
-
-		read_bio->bi_iter.bi_sector = r1_bio->sector +
-			mirror->rdev->data_offset;
-		read_bio->bi_bdev = mirror->rdev->bdev;
-		read_bio->bi_end_io = raid1_end_read_request;
-		bio_set_op_attrs(read_bio, op, do_sync);
-		read_bio->bi_private = r1_bio;
-
-		if (max_sectors < r1_bio->sectors) {
-			/* could not read all from this device, so we will
-			 * need another r1_bio.
-			 */
-
-			sectors_handled = (r1_bio->sector + max_sectors
-					   - bio->bi_iter.bi_sector);
-			r1_bio->sectors = max_sectors;
-			spin_lock_irq(&conf->device_lock);
-			if (bio->bi_phys_segments == 0)
-				bio->bi_phys_segments = 2;
-			else
-				bio->bi_phys_segments++;
-			spin_unlock_irq(&conf->device_lock);
-			/* Cannot call generic_make_request directly
-			 * as that will be queued in __make_request
-			 * and subsequent mempool_alloc might block waiting
-			 * for it.  So hand bio over to raid1d.
-			 */
-			reschedule_retry(r1_bio);
-
-			r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
-
-			r1_bio->master_bio = bio;
-			r1_bio->sectors = bio_sectors(bio) - sectors_handled;
-			r1_bio->state = 0;
-			r1_bio->mddev = mddev;
-			r1_bio->sector = bio->bi_iter.bi_sector +
-				sectors_handled;
-			goto read_again;
-		} else
-			generic_make_request(read_bio);
-		return;
-	}
-
-	/*
-	 * WRITE:
-	 */
 	if (conf->pending_count >= max_queued_requests) {
 		md_wakeup_thread(mddev->thread);
+		raid1_log(mddev, "wait queued");
 		wait_event(conf->wait_barrier,
 			   conf->pending_count < max_queued_requests);
 	}
@@ -1235,8 +1261,7 @@ read_again:
 			int bad_sectors;
 			int is_bad;
 
-			is_bad = is_badblock(rdev, r1_bio->sector,
-					     max_sectors,
+			is_bad = is_badblock(rdev, r1_bio->sector, max_sectors,
 					     &first_bad, &bad_sectors);
 			if (is_bad < 0) {
 				/* mustn't write here until the bad block is
@@ -1286,6 +1311,7 @@ read_again:
 				rdev_dec_pending(conf->mirrors[j].rdev, mddev);
 		r1_bio->state = 0;
 		allow_barrier(conf, start_next_window, bio->bi_iter.bi_sector);
+		raid1_log(mddev, "wait rdev %d blocked", blocked_rdev->raid_disk);
 		md_wait_for_blocked_rdev(blocked_rdev, mddev);
 		start_next_window = wait_barrier(conf, bio);
 		/*
@@ -1324,7 +1350,8 @@ read_again:
 			continue;
 
 		mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-		bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector, max_sectors);
+		bio_trim(mbio, r1_bio->sector - bio->bi_iter.bi_sector,
+			 max_sectors);
 
 		if (first_clone) {
 			/* do behind I/O ?
@@ -1363,10 +1390,21 @@ read_again:
 		mbio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		mbio->bi_end_io	= raid1_end_write_request;
 		bio_set_op_attrs(mbio, op, do_flush_fua | do_sync);
+		if (test_bit(FailFast, &conf->mirrors[i].rdev->flags) &&
+		    !test_bit(WriteMostly, &conf->mirrors[i].rdev->flags) &&
+		    conf->raid_disks - mddev->degraded > 1)
+			mbio->bi_opf |= MD_FAILFAST;
 		mbio->bi_private = r1_bio;
 
 		atomic_inc(&r1_bio->remaining);
 
+		if (mddev->gendisk)
+			trace_block_bio_remap(bdev_get_queue(mbio->bi_bdev),
+					      mbio, disk_devt(mddev->gendisk),
+					      r1_bio->sector);
+		/* flush_pending_writes() needs access to the rdev so...*/
+		mbio->bi_bdev = (void*)conf->mirrors[i].rdev;
+
 		cb = blk_check_plugged(raid1_unplug, mddev, sizeof(*plug));
 		if (cb)
 			plug = container_of(cb, struct raid1_plug_cb, cb);
@@ -1407,6 +1445,40 @@ read_again:
 	wake_up(&conf->wait_barrier);
 }
 
+static void raid1_make_request(struct mddev *mddev, struct bio *bio)
+{
+	struct r1conf *conf = mddev->private;
+	struct r1bio *r1_bio;
+
+	/*
+	 * make_request() can abort the operation when read-ahead is being
+	 * used and no empty request is available.
+	 *
+	 */
+	r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
+
+	r1_bio->master_bio = bio;
+	r1_bio->sectors = bio_sectors(bio);
+	r1_bio->state = 0;
+	r1_bio->mddev = mddev;
+	r1_bio->sector = bio->bi_iter.bi_sector;
+
+	/*
+	 * We might need to issue multiple reads to different devices if there
+	 * are bad blocks around, so we keep track of the number of reads in
+	 * bio->bi_phys_segments.  If this is 0, there is only one r1_bio and
+	 * no locking will be needed when requests complete.  If it is
+	 * non-zero, then it is the number of not-completed requests.
+	 */
+	bio->bi_phys_segments = 0;
+	bio_clear_flag(bio, BIO_SEG_VALID);
+
+	if (bio_data_dir(bio) == READ)
+		raid1_read_request(mddev, bio, r1_bio);
+	else
+		raid1_write_request(mddev, bio, r1_bio);
+}
+
 static void raid1_status(struct seq_file *seq, struct mddev *mddev)
 {
 	struct r1conf *conf = mddev->private;
@@ -1436,6 +1508,7 @@ static void raid1_error(struct mddev *md
 	 * next level up know.
 	 * else mark the drive as failed
 	 */
+	spin_lock_irqsave(&conf->device_lock, flags);
 	if (test_bit(In_sync, &rdev->flags)
 	    && (conf->raid_disks - mddev->degraded) == 1) {
 		/*
@@ -1445,10 +1518,10 @@ static void raid1_error(struct mddev *md
 		 * it is very likely to fail.
 		 */
 		conf->recovery_disabled = mddev->recovery_disabled;
+		spin_unlock_irqrestore(&conf->device_lock, flags);
 		return;
 	}
 	set_bit(Blocked, &rdev->flags);
-	spin_lock_irqsave(&conf->device_lock, flags);
 	if (test_and_clear_bit(In_sync, &rdev->flags)) {
 		mddev->degraded++;
 		set_bit(Faulty, &rdev->flags);
@@ -1459,36 +1532,35 @@ static void raid1_error(struct mddev *md
 	 * if recovery is running, make sure it aborts.
 	 */
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
-	set_mask_bits(&mddev->flags, 0,
-		      BIT(MD_CHANGE_DEVS) | BIT(MD_CHANGE_PENDING));
-	printk(KERN_ALERT
-	       "md/raid1:%s: Disk failure on %s, disabling device.\n"
-	       "md/raid1:%s: Operation continuing on %d devices.\n",
-	       mdname(mddev), bdevname(rdev->bdev, b),
-	       mdname(mddev), conf->raid_disks - mddev->degraded);
+	set_mask_bits(&mddev->sb_flags, 0,
+		      BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
+	pr_crit("md/raid1:%s: Disk failure on %s, disabling device.\n"
+		"md/raid1:%s: Operation continuing on %d devices.\n",
+		mdname(mddev), bdevname(rdev->bdev, b),
+		mdname(mddev), conf->raid_disks - mddev->degraded);
 }
 
 static void print_conf(struct r1conf *conf)
 {
 	int i;
 
-	printk(KERN_DEBUG "RAID1 conf printout:\n");
+	pr_debug("RAID1 conf printout:\n");
 	if (!conf) {
-		printk(KERN_DEBUG "(!conf)\n");
+		pr_debug("(!conf)\n");
 		return;
 	}
-	printk(KERN_DEBUG " --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
-		conf->raid_disks);
+	pr_debug(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
+		 conf->raid_disks);
 
 	rcu_read_lock();
 	for (i = 0; i < conf->raid_disks; i++) {
 		char b[BDEVNAME_SIZE];
 		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),
-			       !test_bit(Faulty, &rdev->flags),
-			       bdevname(rdev->bdev,b));
+			pr_debug(" disk %d, wo:%d, o:%d, dev:%s\n",
+				 i, !test_bit(In_sync, &rdev->flags),
+				 !test_bit(Faulty, &rdev->flags),
+				 bdevname(rdev->bdev,b));
 	}
 	rcu_read_unlock();
 }
@@ -1788,12 +1860,24 @@ static int fix_sync_read_error(struct r1
 	sector_t sect = r1_bio->sector;
 	int sectors = r1_bio->sectors;
 	int idx = 0;
+	struct md_rdev *rdev;
+
+	rdev = conf->mirrors[r1_bio->read_disk].rdev;
+	if (test_bit(FailFast, &rdev->flags)) {
+		/* Don't try recovering from here - just fail it
+		 * ... unless it is the last working device of course */
+		md_error(mddev, rdev);
+		if (test_bit(Faulty, &rdev->flags))
+			/* Don't try to read from here, but make sure
+			 * put_buf does it's thing
+			 */
+			bio->bi_end_io = end_sync_write;
+	}
 
 	while(sectors) {
 		int s = sectors;
 		int d = r1_bio->read_disk;
 		int success = 0;
-		struct md_rdev *rdev;
 		int start;
 
 		if (s > (PAGE_SIZE>>9))
@@ -1825,11 +1909,10 @@ static int fix_sync_read_error(struct r1
 			 * work just disable and interrupt the recovery.
 			 * Don't fail devices as that won't really help.
 			 */
-			printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O read error"
-			       " for block %llu\n",
-			       mdname(mddev),
-			       bdevname(bio->bi_bdev, b),
-			       (unsigned long long)r1_bio->sector);
+			pr_crit_ratelimited("md/raid1:%s: %s: unrecoverable I/O read error for block %llu\n",
+					    mdname(mddev),
+					    bdevname(bio->bi_bdev, b),
+					    (unsigned long long)r1_bio->sector);
 			for (d = 0; d < conf->raid_disks * 2; d++) {
 				rdev = conf->mirrors[d].rdev;
 				if (!rdev || test_bit(Faulty, &rdev->flags))
@@ -2013,6 +2096,9 @@ static void sync_request_write(struct md
 			continue;
 
 		bio_set_op_attrs(wbio, REQ_OP_WRITE, 0);
+		if (test_bit(FailFast, &conf->mirrors[i].rdev->flags))
+			wbio->bi_opf |= MD_FAILFAST;
+
 		wbio->bi_end_io = end_sync_write;
 		atomic_inc(&r1_bio->remaining);
 		md_sync_acct(conf->mirrors[i].rdev->bdev, bio_sectors(wbio));
@@ -2122,13 +2208,11 @@ static void fix_read_error(struct r1conf
 				if (r1_sync_page_io(rdev, sect, s,
 						    conf->tmppage, READ)) {
 					atomic_add(s, &rdev->corrected_errors);
-					printk(KERN_INFO
-					       "md/raid1:%s: read error corrected "
-					       "(%d sectors at %llu on %s)\n",
-					       mdname(mddev), s,
-					       (unsigned long long)(sect +
-								    rdev->data_offset),
-					       bdevname(rdev->bdev, b));
+					pr_info("md/raid1:%s: read error corrected (%d sectors at %llu on %s)\n",
+						mdname(mddev), s,
+						(unsigned long long)(sect +
+								     rdev->data_offset),
+						bdevname(rdev->bdev, b));
 				}
 				rdev_dec_pending(rdev, mddev);
 			} else
@@ -2287,6 +2371,8 @@ static void handle_read_error(struct r1c
 	struct bio *bio;
 	char b[BDEVNAME_SIZE];
 	struct md_rdev *rdev;
+	dev_t bio_dev;
+	sector_t bio_sector;
 
 	clear_bit(R1BIO_ReadError, &r1_bio->state);
 	/* we got a read error. Maybe the drive is bad.  Maybe just
@@ -2300,10 +2386,14 @@ static void handle_read_error(struct r1c
 
 	bio = r1_bio->bios[r1_bio->read_disk];
 	bdevname(bio->bi_bdev, b);
+	bio_dev = bio->bi_bdev->bd_dev;
+	bio_sector = conf->mirrors[r1_bio->read_disk].rdev->data_offset + r1_bio->sector;
 	bio_put(bio);
 	r1_bio->bios[r1_bio->read_disk] = NULL;
 
-	if (mddev->ro == 0) {
+	rdev = conf->mirrors[r1_bio->read_disk].rdev;
+	if (mddev->ro == 0
+	    && !test_bit(FailFast, &rdev->flags)) {
 		freeze_array(conf, 1);
 		fix_read_error(conf, r1_bio->read_disk,
 			       r1_bio->sector, r1_bio->sectors);
@@ -2312,14 +2402,13 @@ static void handle_read_error(struct r1c
 		r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED;
 	}
 
-	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
+	rdev_dec_pending(rdev, conf->mddev);
 
 read_more:
 	disk = read_balance(conf, r1_bio, &max_sectors);
 	if (disk == -1) {
-		printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O"
-		       " read error for block %llu\n",
-		       mdname(mddev), b, (unsigned long long)r1_bio->sector);
+		pr_crit_ratelimited("md/raid1:%s: %s: unrecoverable I/O read error for block %llu\n",
+				    mdname(mddev), b, (unsigned long long)r1_bio->sector);
 		raid_end_bio_io(r1_bio);
 	} else {
 		const unsigned long do_sync
@@ -2330,16 +2419,17 @@ read_more:
 			 max_sectors);
 		r1_bio->bios[r1_bio->read_disk] = bio;
 		rdev = conf->mirrors[disk].rdev;
-		printk_ratelimited(KERN_ERR
-				   "md/raid1:%s: redirecting sector %llu"
-				   " to other mirror: %s\n",
-				   mdname(mddev),
-				   (unsigned long long)r1_bio->sector,
-				   bdevname(rdev->bdev, b));
+		pr_info_ratelimited("md/raid1:%s: redirecting sector %llu to other mirror: %s\n",
+				    mdname(mddev),
+				    (unsigned long long)r1_bio->sector,
+				    bdevname(rdev->bdev, b));
 		bio->bi_iter.bi_sector = r1_bio->sector + rdev->data_offset;
 		bio->bi_bdev = rdev->bdev;
 		bio->bi_end_io = raid1_end_read_request;
 		bio_set_op_attrs(bio, REQ_OP_READ, do_sync);
+		if (test_bit(FailFast, &rdev->flags) &&
+		    test_bit(R1BIO_FailFast, &r1_bio->state))
+			bio->bi_opf |= MD_FAILFAST;
 		bio->bi_private = r1_bio;
 		if (max_sectors < r1_bio->sectors) {
 			/* Drat - have to split this up more */
@@ -2353,6 +2443,8 @@ read_more:
 			else
 				mbio->bi_phys_segments++;
 			spin_unlock_irq(&conf->device_lock);
+			trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
+					      bio, bio_dev, bio_sector);
 			generic_make_request(bio);
 			bio = NULL;
 
@@ -2367,8 +2459,11 @@ read_more:
 				sectors_handled;
 
 			goto read_more;
-		} else
+		} else {
+			trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
+					      bio, bio_dev, bio_sector);
 			generic_make_request(bio);
+		}
 	}
 }
 
@@ -2384,10 +2479,10 @@ static void raid1d(struct md_thread *thr
 	md_check_recovery(mddev);
 
 	if (!list_empty_careful(&conf->bio_end_io_list) &&
-	    !test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+	    !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
 		LIST_HEAD(tmp);
 		spin_lock_irqsave(&conf->device_lock, flags);
-		if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+		if (!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
 			while (!list_empty(&conf->bio_end_io_list)) {
 				list_move(conf->bio_end_io_list.prev, &tmp);
 				conf->nr_queued--;
@@ -2441,7 +2536,7 @@ static void raid1d(struct md_thread *thr
 			generic_make_request(r1_bio->bios[r1_bio->read_disk]);
 
 		cond_resched();
-		if (mddev->flags & ~(1<<MD_CHANGE_PENDING))
+		if (mddev->sb_flags & ~(1<<MD_SB_CHANGE_PENDING))
 			md_check_recovery(mddev);
 	}
 	blk_finish_plug(&plug);
@@ -2623,6 +2718,8 @@ static sector_t raid1_sync_request(struc
 			bio->bi_iter.bi_sector = sector_nr + rdev->data_offset;
 			bio->bi_bdev = rdev->bdev;
 			bio->bi_private = r1_bio;
+			if (test_bit(FailFast, &rdev->flags))
+				bio->bi_opf |= MD_FAILFAST;
 		}
 	}
 	rcu_read_unlock();
@@ -2642,7 +2739,7 @@ static sector_t raid1_sync_request(struc
 							min_bad, 0
 					) && ok;
 			}
-		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		*skipped = 1;
 		put_buf(r1_bio);
 
@@ -2753,6 +2850,8 @@ static sector_t raid1_sync_request(struc
 			if (bio->bi_end_io == end_sync_read) {
 				read_targets--;
 				md_sync_acct(bio->bi_bdev, nr_sectors);
+				if (read_targets == 1)
+					bio->bi_opf &= ~MD_FAILFAST;
 				generic_make_request(bio);
 			}
 		}
@@ -2760,6 +2859,8 @@ static sector_t raid1_sync_request(struc
 		atomic_set(&r1_bio->remaining, 1);
 		bio = r1_bio->bios[r1_bio->read_disk];
 		md_sync_acct(bio->bi_bdev, nr_sectors);
+		if (read_targets == 1)
+			bio->bi_opf &= ~MD_FAILFAST;
 		generic_make_request(bio);
 
 	}
@@ -2875,12 +2976,8 @@ static struct r1conf *setup_conf(struct
 
 	err = -ENOMEM;
 	conf->thread = md_register_thread(raid1d, mddev, "raid1");
-	if (!conf->thread) {
-		printk(KERN_ERR
-		       "md/raid1:%s: couldn't allocate thread\n",
-		       mdname(mddev));
+	if (!conf->thread)
 		goto abort;
-	}
 
 	return conf;
 
@@ -2905,13 +3002,13 @@ static int raid1_run(struct mddev *mddev
 	bool discard_supported = false;
 
 	if (mddev->level != 1) {
-		printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
-		       mdname(mddev), mddev->level);
+		pr_warn("md/raid1:%s: raid level not set to mirroring (%d)\n",
+			mdname(mddev), mddev->level);
 		return -EIO;
 	}
 	if (mddev->reshape_position != MaxSector) {
-		printk(KERN_ERR "md/raid1:%s: reshape_position set but not supported\n",
-		       mdname(mddev));
+		pr_warn("md/raid1:%s: reshape_position set but not supported\n",
+			mdname(mddev));
 		return -EIO;
 	}
 	/*
@@ -2950,11 +3047,9 @@ static int raid1_run(struct mddev *mddev
 		mddev->recovery_cp = MaxSector;
 
 	if (mddev->recovery_cp != MaxSector)
-		printk(KERN_NOTICE "md/raid1:%s: not clean"
-		       " -- starting background reconstruction\n",
-		       mdname(mddev));
-	printk(KERN_INFO
-		"md/raid1:%s: active with %d out of %d mirrors\n",
+		pr_info("md/raid1:%s: not clean -- starting background reconstruction\n",
+			mdname(mddev));
+	pr_info("md/raid1:%s: active with %d out of %d mirrors\n",
 		mdname(mddev), mddev->raid_disks - mddev->degraded,
 		mddev->raid_disks);
 
@@ -2964,6 +3059,7 @@ static int raid1_run(struct mddev *mddev
 	mddev->thread = conf->thread;
 	conf->thread = NULL;
 	mddev->private = conf;
+	set_bit(MD_FAILFAST_SUPPORTED, &mddev->flags);
 
 	md_set_array_sectors(mddev, raid1_size(mddev, 0, 0));
 
@@ -3107,9 +3203,8 @@ static int raid1_reshape(struct mddev *m
 			rdev->raid_disk = d2;
 			sysfs_unlink_rdev(mddev, rdev);
 			if (sysfs_link_rdev(mddev, rdev))
-				printk(KERN_WARNING
-				       "md/raid1:%s: cannot register rd%d\n",
-				       mdname(mddev), rdev->raid_disk);
+				pr_warn("md/raid1:%s: cannot register rd%d\n",
+					mdname(mddev), rdev->raid_disk);
 		}
 		if (rdev)
 			newmirrors[d2++].rdev = rdev;
@@ -3163,9 +3258,12 @@ static void *raid1_takeover(struct mddev
 		mddev->new_layout = 0;
 		mddev->new_chunk_sectors = 0;
 		conf = setup_conf(mddev);
-		if (!IS_ERR(conf))
+		if (!IS_ERR(conf)) {
 			/* Array must appear to be quiesced */
 			conf->array_frozen = 1;
+			mddev_clear_unsupported_flags(mddev,
+				UNSUPPORTED_MDDEV_FLAGS);
+		}
 		return conf;
 	}
 	return ERR_PTR(-EINVAL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid1.h linux-libre-4.10-rc8-gnu/drivers/md/raid1.h
--- linux-libre-4.9-gnu/drivers/md/raid1.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid1.h	2017-02-12 16:03:20.000000000 -0500
@@ -161,14 +161,15 @@ struct r1bio {
 };
 
 /* bits for r1bio.state */
-#define	R1BIO_Uptodate	0
-#define	R1BIO_IsSync	1
-#define	R1BIO_Degraded	2
-#define	R1BIO_BehindIO	3
+enum r1bio_state {
+	R1BIO_Uptodate,
+	R1BIO_IsSync,
+	R1BIO_Degraded,
+	R1BIO_BehindIO,
 /* Set ReadError on bios that experience a readerror so that
  * raid1d knows what to do with them.
  */
-#define R1BIO_ReadError 4
+	R1BIO_ReadError,
 /* For write-behind requests, we call bi_end_io when
  * the last non-write-behind device completes, providing
  * any write was successful.  Otherwise we call when
@@ -176,10 +177,12 @@ struct r1bio {
  * with failure when last write completes (and all failed).
  * Record that bi_end_io was called with this flag...
  */
-#define	R1BIO_Returned 6
+	R1BIO_Returned,
 /* If a write for this request means we can clear some
  * known-bad-block records, we set this flag
  */
-#define	R1BIO_MadeGood 7
-#define	R1BIO_WriteError 8
+	R1BIO_MadeGood,
+	R1BIO_WriteError,
+	R1BIO_FailFast,
+};
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid5.c linux-libre-4.10-rc8-gnu/drivers/md/raid5.c
--- linux-libre-4.9-gnu/drivers/md/raid5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid5.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,6 +62,8 @@
 #include "raid0.h"
 #include "bitmap.h"
 
+#define UNSUPPORTED_MDDEV_FLAGS	(1L << MD_FAILFAST_SUPPORTED)
+
 #define cpu_to_group(cpu) cpu_to_node(cpu)
 #define ANY_GROUP NUMA_NO_NODE
 
@@ -70,19 +72,6 @@ module_param(devices_handle_discard_safe
 MODULE_PARM_DESC(devices_handle_discard_safely,
 		 "Set to Y if all devices in each array reliably return zeroes on reads from discarded regions");
 static struct workqueue_struct *raid5_wq;
-/*
- * Stripe cache
- */
-
-#define NR_STRIPES		256
-#define STRIPE_SIZE		PAGE_SIZE
-#define STRIPE_SHIFT		(PAGE_SHIFT - 9)
-#define STRIPE_SECTORS		(STRIPE_SIZE>>9)
-#define	IO_THRESHOLD		1
-#define BYPASS_THRESHOLD	1
-#define NR_HASH			(PAGE_SIZE / sizeof(struct hlist_head))
-#define HASH_MASK		(NR_HASH - 1)
-#define MAX_STRIPE_BATCH	8
 
 static inline struct hlist_head *stripe_hash(struct r5conf *conf, sector_t sect)
 {
@@ -126,64 +115,6 @@ static inline void unlock_all_device_has
 	local_irq_enable();
 }
 
-/* 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
- * a bio could span several devices.
- * 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 function is used to determine the 'next' bio in the list, given the sector
- * of the current stripe+device
- */
-static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector)
-{
-	int sectors = bio_sectors(bio);
-	if (bio->bi_iter.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
- * bi_phys_segments, and a count of processed stripes in the upper 16 bits
- */
-static inline int raid5_bi_processed_stripes(struct bio *bio)
-{
-	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
-	return (atomic_read(segments) >> 16) & 0xffff;
-}
-
-static inline int raid5_dec_bi_active_stripes(struct bio *bio)
-{
-	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
-	return atomic_sub_return(1, segments) & 0xffff;
-}
-
-static inline void raid5_inc_bi_active_stripes(struct bio *bio)
-{
-	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
-	atomic_inc(segments);
-}
-
-static inline void raid5_set_bi_processed_stripes(struct bio *bio,
-	unsigned int cnt)
-{
-	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
-	int old, new;
-
-	do {
-		old = atomic_read(segments);
-		new = (old & 0xffff) | (cnt << 16);
-	} while (atomic_cmpxchg(segments, old, new) != old);
-}
-
-static inline void raid5_set_bi_stripes(struct bio *bio, unsigned int cnt)
-{
-	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
-	atomic_set(segments, cnt);
-}
-
 /* Find first data disk in a raid6 stripe */
 static inline int raid6_d0(struct stripe_head *sh)
 {
@@ -289,8 +220,27 @@ static void raid5_wakeup_stripe_thread(s
 static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh,
 			      struct list_head *temp_inactive_list)
 {
+	int i;
+	int injournal = 0;	/* number of date pages with R5_InJournal */
+
 	BUG_ON(!list_empty(&sh->lru));
 	BUG_ON(atomic_read(&conf->active_stripes)==0);
+
+	if (r5c_is_writeback(conf->log))
+		for (i = sh->disks; i--; )
+			if (test_bit(R5_InJournal, &sh->dev[i].flags))
+				injournal++;
+	/*
+	 * When quiesce in r5c write back, set STRIPE_HANDLE for stripes with
+	 * data in journal, so they are not released to cached lists
+	 */
+	if (conf->quiesce && r5c_is_writeback(conf->log) &&
+	    !test_bit(STRIPE_HANDLE, &sh->state) && injournal != 0) {
+		if (test_bit(STRIPE_R5C_CACHING, &sh->state))
+			r5c_make_stripe_write_out(sh);
+		set_bit(STRIPE_HANDLE, &sh->state);
+	}
+
 	if (test_bit(STRIPE_HANDLE, &sh->state)) {
 		if (test_bit(STRIPE_DELAYED, &sh->state) &&
 		    !test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
@@ -316,8 +266,30 @@ static void do_release_stripe(struct r5c
 			    < IO_THRESHOLD)
 				md_wakeup_thread(conf->mddev->thread);
 		atomic_dec(&conf->active_stripes);
-		if (!test_bit(STRIPE_EXPANDING, &sh->state))
-			list_add_tail(&sh->lru, temp_inactive_list);
+		if (!test_bit(STRIPE_EXPANDING, &sh->state)) {
+			if (!r5c_is_writeback(conf->log))
+				list_add_tail(&sh->lru, temp_inactive_list);
+			else {
+				WARN_ON(test_bit(R5_InJournal, &sh->dev[sh->pd_idx].flags));
+				if (injournal == 0)
+					list_add_tail(&sh->lru, temp_inactive_list);
+				else if (injournal == conf->raid_disks - conf->max_degraded) {
+					/* full stripe */
+					if (!test_and_set_bit(STRIPE_R5C_FULL_STRIPE, &sh->state))
+						atomic_inc(&conf->r5c_cached_full_stripes);
+					if (test_and_clear_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state))
+						atomic_dec(&conf->r5c_cached_partial_stripes);
+					list_add_tail(&sh->lru, &conf->r5c_full_stripe_list);
+					r5c_check_cached_full_stripe(conf);
+				} else {
+					/* partial stripe */
+					if (!test_and_set_bit(STRIPE_R5C_PARTIAL_STRIPE,
+							      &sh->state))
+						atomic_inc(&conf->r5c_cached_partial_stripes);
+					list_add_tail(&sh->lru, &conf->r5c_partial_stripe_list);
+				}
+			}
+		}
 	}
 }
 
@@ -541,7 +513,7 @@ retry:
 
 		if (dev->toread || dev->read || dev->towrite || dev->written ||
 		    test_bit(R5_LOCKED, &dev->flags)) {
-			printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n",
+			pr_err("sector=%llx i=%d %p %p %p %p %d\n",
 			       (unsigned long long)sh->sector, i, dev->toread,
 			       dev->read, dev->towrite, dev->written,
 			       test_bit(R5_LOCKED, &dev->flags));
@@ -584,7 +556,7 @@ static struct stripe_head *__find_stripe
  * of the two sections, and some non-in_sync devices may
  * be insync in the section most affected by failed devices.
  */
-static int calc_degraded(struct r5conf *conf)
+int raid5_calc_degraded(struct r5conf *conf)
 {
 	int degraded, degraded2;
 	int i;
@@ -647,7 +619,7 @@ static int has_failed(struct r5conf *con
 	if (conf->mddev->reshape_position == MaxSector)
 		return conf->mddev->degraded > conf->max_degraded;
 
-	degraded = calc_degraded(conf);
+	degraded = raid5_calc_degraded(conf);
 	if (degraded > conf->max_degraded)
 		return 1;
 	return 0;
@@ -680,9 +652,12 @@ raid5_get_active_stripe(struct r5conf *c
 			}
 			if (noblock && sh == NULL)
 				break;
+
+			r5c_check_stripe_cache_usage(conf);
 			if (!sh) {
 				set_bit(R5_INACTIVE_BLOCKED,
 					&conf->cache_state);
+				r5l_wake_reclaim(conf->log, 0);
 				wait_event_lock_irq(
 					conf->wait_for_stripe,
 					!list_empty(conf->inactive_list + hash) &&
@@ -901,8 +876,19 @@ static void ops_run_io(struct stripe_hea
 
 	might_sleep();
 
-	if (r5l_write_stripe(conf->log, sh) == 0)
-		return;
+	if (!test_bit(STRIPE_R5C_CACHING, &sh->state)) {
+		/* writing out phase */
+		if (s->waiting_extra_page)
+			return;
+		if (r5l_write_stripe(conf->log, sh) == 0)
+			return;
+	} else {  /* caching phase */
+		if (test_bit(STRIPE_LOG_TRAPPED, &sh->state)) {
+			r5c_cache_data(conf->log, sh, s);
+			return;
+		}
+	}
+
 	for (i = disks; i--; ) {
 		int op, op_flags = 0;
 		int replace_only = 0;
@@ -913,7 +899,7 @@ static void ops_run_io(struct stripe_hea
 		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
 			op = REQ_OP_WRITE;
 			if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags))
-				op_flags = WRITE_FUA;
+				op_flags = REQ_FUA;
 			if (test_bit(R5_Discard, &sh->dev[i].flags))
 				op = REQ_OP_DISCARD;
 		} else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
@@ -977,7 +963,7 @@ again:
 			if (bad < 0) {
 				set_bit(BlockedBadBlocks, &rdev->flags);
 				if (!conf->mddev->external &&
-				    conf->mddev->flags) {
+				    conf->mddev->sb_flags) {
 					/* It is very unlikely, but we might
 					 * still need to write out the
 					 * bad block log - better give it
@@ -1029,7 +1015,17 @@ again:
 
 			if (test_bit(R5_SkipCopy, &sh->dev[i].flags))
 				WARN_ON(test_bit(R5_UPTODATE, &sh->dev[i].flags));
-			sh->dev[i].vec.bv_page = sh->dev[i].page;
+
+			if (!op_is_write(op) &&
+			    test_bit(R5_InJournal, &sh->dev[i].flags))
+				/*
+				 * issuing read for a page in journal, this
+				 * must be preparing for prexor in rmw; read
+				 * the data into orig_page
+				 */
+				sh->dev[i].vec.bv_page = sh->dev[i].orig_page;
+			else
+				sh->dev[i].vec.bv_page = sh->dev[i].page;
 			bi->bi_vcnt = 1;
 			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
 			bi->bi_io_vec[0].bv_offset = 0;
@@ -1115,7 +1111,7 @@ again:
 static struct dma_async_tx_descriptor *
 async_copy_data(int frombio, struct bio *bio, struct page **page,
 	sector_t sector, struct dma_async_tx_descriptor *tx,
-	struct stripe_head *sh)
+	struct stripe_head *sh, int no_skipcopy)
 {
 	struct bio_vec bvl;
 	struct bvec_iter iter;
@@ -1155,7 +1151,8 @@ async_copy_data(int frombio, struct bio
 			if (frombio) {
 				if (sh->raid_conf->skip_copy &&
 				    b_offset == 0 && page_offset == 0 &&
-				    clen == STRIPE_SIZE)
+				    clen == STRIPE_SIZE &&
+				    !no_skipcopy)
 					*page = bio_page;
 				else
 					tx = async_memcpy(*page, bio_page, page_offset,
@@ -1237,7 +1234,7 @@ static void ops_run_biofill(struct strip
 			while (rbi && rbi->bi_iter.bi_sector <
 				dev->sector + STRIPE_SECTORS) {
 				tx = async_copy_data(0, rbi, &dev->page,
-					dev->sector, tx, sh);
+						     dev->sector, tx, sh, 0);
 				rbi = r5_next_bio(rbi, dev->sector);
 			}
 		}
@@ -1364,10 +1361,15 @@ static int set_syndrome_sources(struct p
 		if (i == sh->qd_idx || i == sh->pd_idx ||
 		    (srctype == SYNDROME_SRC_ALL) ||
 		    (srctype == SYNDROME_SRC_WANT_DRAIN &&
-		     test_bit(R5_Wantdrain, &dev->flags)) ||
+		     (test_bit(R5_Wantdrain, &dev->flags) ||
+		      test_bit(R5_InJournal, &dev->flags))) ||
 		    (srctype == SYNDROME_SRC_WRITTEN &&
-		     dev->written))
-			srcs[slot] = sh->dev[i].page;
+		     dev->written)) {
+			if (test_bit(R5_InJournal, &dev->flags))
+				srcs[slot] = sh->dev[i].orig_page;
+			else
+				srcs[slot] = sh->dev[i].page;
+		}
 		i = raid6_next_disk(i, disks);
 	} while (i != d0_idx);
 
@@ -1546,6 +1548,13 @@ static void ops_complete_prexor(void *st
 
 	pr_debug("%s: stripe %llu\n", __func__,
 		(unsigned long long)sh->sector);
+
+	if (r5c_is_writeback(sh->raid_conf->log))
+		/*
+		 * raid5-cache write back uses orig_page during prexor.
+		 * After prexor, it is time to free orig_page
+		 */
+		r5c_release_extra_page(sh);
 }
 
 static struct dma_async_tx_descriptor *
@@ -1567,7 +1576,9 @@ ops_run_prexor5(struct stripe_head *sh,
 	for (i = disks; i--; ) {
 		struct r5dev *dev = &sh->dev[i];
 		/* Only process blocks that are known to be uptodate */
-		if (test_bit(R5_Wantdrain, &dev->flags))
+		if (test_bit(R5_InJournal, &dev->flags))
+			xor_srcs[count++] = dev->orig_page;
+		else if (test_bit(R5_Wantdrain, &dev->flags))
 			xor_srcs[count++] = dev->page;
 	}
 
@@ -1601,6 +1612,7 @@ ops_run_prexor6(struct stripe_head *sh,
 static struct dma_async_tx_descriptor *
 ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
 {
+	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks;
 	int i;
 	struct stripe_head *head_sh = sh;
@@ -1618,6 +1630,11 @@ ops_run_biodrain(struct stripe_head *sh,
 
 again:
 			dev = &sh->dev[i];
+			/*
+			 * clear R5_InJournal, so when rewriting a page in
+			 * journal, it is not skipped by r5l_log_stripe()
+			 */
+			clear_bit(R5_InJournal, &dev->flags);
 			spin_lock_irq(&sh->stripe_lock);
 			chosen = dev->towrite;
 			dev->towrite = NULL;
@@ -1637,8 +1654,10 @@ again:
 					set_bit(R5_Discard, &dev->flags);
 				else {
 					tx = async_copy_data(1, wbi, &dev->page,
-						dev->sector, tx, sh);
-					if (dev->page != dev->orig_page) {
+							     dev->sector, tx, sh,
+							     r5c_is_writeback(conf->log));
+					if (dev->page != dev->orig_page &&
+					    !r5c_is_writeback(conf->log)) {
 						set_bit(R5_SkipCopy, &dev->flags);
 						clear_bit(R5_UPTODATE, &dev->flags);
 						clear_bit(R5_OVERWRITE, &dev->flags);
@@ -1746,7 +1765,8 @@ again:
 		xor_dest = xor_srcs[count++] = sh->dev[pd_idx].page;
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
-			if (head_sh->dev[i].written)
+			if (head_sh->dev[i].written ||
+			    test_bit(R5_InJournal, &head_sh->dev[i].flags))
 				xor_srcs[count++] = dev->page;
 		}
 	} else {
@@ -2000,17 +2020,15 @@ static struct stripe_head *alloc_stripe(
 		spin_lock_init(&sh->batch_lock);
 		INIT_LIST_HEAD(&sh->batch_list);
 		INIT_LIST_HEAD(&sh->lru);
+		INIT_LIST_HEAD(&sh->r5c);
+		INIT_LIST_HEAD(&sh->log_list);
 		atomic_set(&sh->count, 1);
+		sh->log_start = MaxSector;
 		for (i = 0; i < disks; i++) {
 			struct r5dev *dev = &sh->dev[i];
 
-			bio_init(&dev->req);
-			dev->req.bi_io_vec = &dev->vec;
-			dev->req.bi_max_vecs = 1;
-
-			bio_init(&dev->rreq);
-			dev->rreq.bi_io_vec = &dev->rvec;
-			dev->rreq.bi_max_vecs = 1;
+			bio_init(&dev->req, &dev->vec, 1);
+			bio_init(&dev->rreq, &dev->rvec, 1);
 		}
 	}
 	return sh;
@@ -2245,10 +2263,24 @@ static int resize_stripes(struct r5conf
 	 */
 	ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
 	if (ndisks) {
-		for (i=0; i<conf->raid_disks; i++)
+		for (i = 0; i < conf->pool_size; i++)
 			ndisks[i] = conf->disks[i];
-		kfree(conf->disks);
-		conf->disks = ndisks;
+
+		for (i = conf->pool_size; i < newsize; i++) {
+			ndisks[i].extra_page = alloc_page(GFP_NOIO);
+			if (!ndisks[i].extra_page)
+				err = -ENOMEM;
+		}
+
+		if (err) {
+			for (i = conf->pool_size; i < newsize; i++)
+				if (ndisks[i].extra_page)
+					put_page(ndisks[i].extra_page);
+			kfree(ndisks);
+		} else {
+			kfree(conf->disks);
+			conf->disks = ndisks;
+		}
 	} else
 		err = -ENOMEM;
 
@@ -2347,10 +2379,8 @@ static void raid5_end_read_request(struc
 			 * replacement device.  We just fail those on
 			 * any error
 			 */
-			printk_ratelimited(
-				KERN_INFO
-				"md/raid:%s: read error corrected"
-				" (%lu sectors at %llu on %s)\n",
+			pr_info_ratelimited(
+				"md/raid:%s: read error corrected (%lu sectors at %llu on %s)\n",
 				mdname(conf->mddev), STRIPE_SECTORS,
 				(unsigned long long)s,
 				bdevname(rdev->bdev, b));
@@ -2360,6 +2390,13 @@ static void raid5_end_read_request(struc
 		} else if (test_bit(R5_ReadNoMerge, &sh->dev[i].flags))
 			clear_bit(R5_ReadNoMerge, &sh->dev[i].flags);
 
+		if (test_bit(R5_InJournal, &sh->dev[i].flags))
+			/*
+			 * end read for a page in journal, this
+			 * must be preparing for prexor in rmw
+			 */
+			set_bit(R5_OrigPageUPTDODATE, &sh->dev[i].flags);
+
 		if (atomic_read(&rdev->read_errors))
 			atomic_set(&rdev->read_errors, 0);
 	} else {
@@ -2370,36 +2407,29 @@ static void raid5_end_read_request(struc
 		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
 		atomic_inc(&rdev->read_errors);
 		if (test_bit(R5_ReadRepl, &sh->dev[i].flags))
-			printk_ratelimited(
-				KERN_WARNING
-				"md/raid:%s: read error on replacement device "
-				"(sector %llu on %s).\n",
+			pr_warn_ratelimited(
+				"md/raid:%s: read error on replacement device (sector %llu on %s).\n",
 				mdname(conf->mddev),
 				(unsigned long long)s,
 				bdn);
 		else if (conf->mddev->degraded >= conf->max_degraded) {
 			set_bad = 1;
-			printk_ratelimited(
-				KERN_WARNING
-				"md/raid:%s: read error not correctable "
-				"(sector %llu on %s).\n",
+			pr_warn_ratelimited(
+				"md/raid:%s: read error not correctable (sector %llu on %s).\n",
 				mdname(conf->mddev),
 				(unsigned long long)s,
 				bdn);
 		} else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) {
 			/* Oh, no!!! */
 			set_bad = 1;
-			printk_ratelimited(
-				KERN_WARNING
-				"md/raid:%s: read error NOT corrected!! "
-				"(sector %llu on %s).\n",
+			pr_warn_ratelimited(
+				"md/raid:%s: read error NOT corrected!! (sector %llu on %s).\n",
 				mdname(conf->mddev),
 				(unsigned long long)s,
 				bdn);
 		} else if (atomic_read(&rdev->read_errors)
 			 > conf->max_nr_stripes)
-			printk(KERN_WARNING
-			       "md/raid:%s: Too many read errors, failing device %s.\n",
+			pr_warn("md/raid:%s: Too many read errors, failing device %s.\n",
 			       mdname(conf->mddev), bdn);
 		else
 			retry = 1;
@@ -2525,21 +2555,21 @@ static void raid5_error(struct mddev *md
 
 	spin_lock_irqsave(&conf->device_lock, flags);
 	clear_bit(In_sync, &rdev->flags);
-	mddev->degraded = calc_degraded(conf);
+	mddev->degraded = raid5_calc_degraded(conf);
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 
 	set_bit(Blocked, &rdev->flags);
 	set_bit(Faulty, &rdev->flags);
-	set_mask_bits(&mddev->flags, 0,
-		      BIT(MD_CHANGE_DEVS) | BIT(MD_CHANGE_PENDING));
-	printk(KERN_ALERT
-	       "md/raid:%s: Disk failure on %s, disabling device.\n"
-	       "md/raid:%s: Operation continuing on %d devices.\n",
-	       mdname(mddev),
-	       bdevname(rdev->bdev, b),
-	       mdname(mddev),
-	       conf->raid_disks - mddev->degraded);
+	set_mask_bits(&mddev->sb_flags, 0,
+		      BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
+	pr_crit("md/raid:%s: Disk failure on %s, disabling device.\n"
+		"md/raid:%s: Operation continuing on %d devices.\n",
+		mdname(mddev),
+		bdevname(rdev->bdev, b),
+		mdname(mddev),
+		conf->raid_disks - mddev->degraded);
+	r5c_update_on_rdev_error(mddev);
 }
 
 /*
@@ -2861,13 +2891,37 @@ sector_t raid5_compute_blocknr(struct st
 				     previous, &dummy1, &sh2);
 	if (check != sh->sector || dummy1 != dd_idx || sh2.pd_idx != sh->pd_idx
 		|| sh2.qd_idx != sh->qd_idx) {
-		printk(KERN_ERR "md/raid:%s: compute_blocknr: map not correct\n",
-		       mdname(conf->mddev));
+		pr_warn("md/raid:%s: compute_blocknr: map not correct\n",
+			mdname(conf->mddev));
 		return 0;
 	}
 	return r_sector;
 }
 
+/*
+ * There are cases where we want handle_stripe_dirtying() and
+ * schedule_reconstruction() to delay towrite to some dev of a stripe.
+ *
+ * This function checks whether we want to delay the towrite. Specifically,
+ * we delay the towrite when:
+ *
+ *   1. degraded stripe has a non-overwrite to the missing dev, AND this
+ *      stripe has data in journal (for other devices).
+ *
+ *      In this case, when reading data for the non-overwrite dev, it is
+ *      necessary to handle complex rmw of write back cache (prexor with
+ *      orig_page, and xor with page). To keep read path simple, we would
+ *      like to flush data in journal to RAID disks first, so complex rmw
+ *      is handled in the write patch (handle_stripe_dirtying).
+ *
+ */
+static inline bool delay_towrite(struct r5dev *dev,
+				   struct stripe_head_state *s)
+{
+	return !test_bit(R5_OVERWRITE, &dev->flags) &&
+		!test_bit(R5_Insync, &dev->flags) && s->injournal;
+}
+
 static void
 schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
 			 int rcw, int expand)
@@ -2877,16 +2931,26 @@ schedule_reconstruction(struct stripe_he
 	int level = conf->level;
 
 	if (rcw) {
+		/*
+		 * In some cases, handle_stripe_dirtying initially decided to
+		 * run rmw and allocates extra page for prexor. However, rcw is
+		 * cheaper later on. We need to free the extra page now,
+		 * because we won't be able to do that in ops_complete_prexor().
+		 */
+		r5c_release_extra_page(sh);
 
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
 
-			if (dev->towrite) {
+			if (dev->towrite && !delay_towrite(dev, s)) {
 				set_bit(R5_LOCKED, &dev->flags);
 				set_bit(R5_Wantdrain, &dev->flags);
 				if (!expand)
 					clear_bit(R5_UPTODATE, &dev->flags);
 				s->locked++;
+			} else if (test_bit(R5_InJournal, &dev->flags)) {
+				set_bit(R5_LOCKED, &dev->flags);
+				s->locked++;
 			}
 		}
 		/* if we are not expanding this is a proper write request, and
@@ -2926,6 +2990,9 @@ schedule_reconstruction(struct stripe_he
 				set_bit(R5_LOCKED, &dev->flags);
 				clear_bit(R5_UPTODATE, &dev->flags);
 				s->locked++;
+			} else if (test_bit(R5_InJournal, &dev->flags)) {
+				set_bit(R5_LOCKED, &dev->flags);
+				s->locked++;
 			}
 		}
 		if (!s->locked)
@@ -3270,13 +3337,6 @@ static int want_replace(struct stripe_he
 	return rv;
 }
 
-/* fetch_block - checks the given member device to see if its data needs
- * to be read or computed to satisfy a request.
- *
- * Returns 1 when no more member devices need to be checked, otherwise returns
- * 0 to tell the loop in handle_stripe_fill to continue
- */
-
 static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s,
 			   int disk_idx, int disks)
 {
@@ -3367,6 +3427,12 @@ static int need_this_block(struct stripe
 	return 0;
 }
 
+/* fetch_block - checks the given member device to see if its data needs
+ * to be read or computed to satisfy a request.
+ *
+ * Returns 1 when no more member devices need to be checked, otherwise returns
+ * 0 to tell the loop in handle_stripe_fill to continue
+ */
 static int fetch_block(struct stripe_head *sh, struct stripe_head_state *s,
 		       int disk_idx, int disks)
 {
@@ -3453,10 +3519,26 @@ static void handle_stripe_fill(struct st
 	 * midst of changing due to a write
 	 */
 	if (!test_bit(STRIPE_COMPUTE_RUN, &sh->state) && !sh->check_state &&
-	    !sh->reconstruct_state)
+	    !sh->reconstruct_state) {
+
+		/*
+		 * For degraded stripe with data in journal, do not handle
+		 * read requests yet, instead, flush the stripe to raid
+		 * disks first, this avoids handling complex rmw of write
+		 * back cache (prexor with orig_page, and then xor with
+		 * page) in the read path
+		 */
+		if (s->injournal && s->failed) {
+			if (test_bit(STRIPE_R5C_CACHING, &sh->state))
+				r5c_make_stripe_write_out(sh);
+			goto out;
+		}
+
 		for (i = disks; i--; )
 			if (fetch_block(sh, s, i, disks))
 				break;
+	}
+out:
 	set_bit(STRIPE_HANDLE, &sh->state);
 }
 
@@ -3569,10 +3651,25 @@ unhash:
 		break_stripe_batch_list(head_sh, STRIPE_EXPAND_SYNC_FLAGS);
 }
 
-static void handle_stripe_dirtying(struct r5conf *conf,
-				   struct stripe_head *sh,
-				   struct stripe_head_state *s,
-				   int disks)
+/*
+ * For RMW in write back cache, we need extra page in prexor to store the
+ * old data. This page is stored in dev->orig_page.
+ *
+ * This function checks whether we have data for prexor. The exact logic
+ * is:
+ *       R5_UPTODATE && (!R5_InJournal || R5_OrigPageUPTDODATE)
+ */
+static inline bool uptodate_for_rmw(struct r5dev *dev)
+{
+	return (test_bit(R5_UPTODATE, &dev->flags)) &&
+		(!test_bit(R5_InJournal, &dev->flags) ||
+		 test_bit(R5_OrigPageUPTDODATE, &dev->flags));
+}
+
+static int handle_stripe_dirtying(struct r5conf *conf,
+				  struct stripe_head *sh,
+				  struct stripe_head_state *s,
+				  int disks)
 {
 	int rmw = 0, rcw = 0, i;
 	sector_t recovery_cp = conf->mddev->recovery_cp;
@@ -3597,9 +3694,11 @@ static void handle_stripe_dirtying(struc
 	} else for (i = disks; i--; ) {
 		/* would I have to read this buffer for read_modify_write */
 		struct r5dev *dev = &sh->dev[i];
-		if ((dev->towrite || i == sh->pd_idx || i == sh->qd_idx) &&
+		if (((dev->towrite && !delay_towrite(dev, s)) ||
+		     i == sh->pd_idx || i == sh->qd_idx ||
+		     test_bit(R5_InJournal, &dev->flags)) &&
 		    !test_bit(R5_LOCKED, &dev->flags) &&
-		    !(test_bit(R5_UPTODATE, &dev->flags) ||
+		    !(uptodate_for_rmw(dev) ||
 		      test_bit(R5_Wantcompute, &dev->flags))) {
 			if (test_bit(R5_Insync, &dev->flags))
 				rmw++;
@@ -3611,13 +3710,14 @@ static void handle_stripe_dirtying(struc
 		    i != sh->pd_idx && i != sh->qd_idx &&
 		    !test_bit(R5_LOCKED, &dev->flags) &&
 		    !(test_bit(R5_UPTODATE, &dev->flags) ||
-		    test_bit(R5_Wantcompute, &dev->flags))) {
+		      test_bit(R5_Wantcompute, &dev->flags))) {
 			if (test_bit(R5_Insync, &dev->flags))
 				rcw++;
 			else
 				rcw += 2*disks;
 		}
 	}
+
 	pr_debug("for sector %llu, rmw=%d rcw=%d\n",
 		(unsigned long long)sh->sector, rmw, rcw);
 	set_bit(STRIPE_HANDLE, &sh->state);
@@ -3629,10 +3729,42 @@ static void handle_stripe_dirtying(struc
 					  (unsigned long long)sh->sector, rmw);
 		for (i = disks; i--; ) {
 			struct r5dev *dev = &sh->dev[i];
-			if ((dev->towrite || i == sh->pd_idx || i == sh->qd_idx) &&
+			if (test_bit(R5_InJournal, &dev->flags) &&
+			    dev->page == dev->orig_page &&
+			    !test_bit(R5_LOCKED, &sh->dev[sh->pd_idx].flags)) {
+				/* alloc page for prexor */
+				struct page *p = alloc_page(GFP_NOIO);
+
+				if (p) {
+					dev->orig_page = p;
+					continue;
+				}
+
+				/*
+				 * alloc_page() failed, try use
+				 * disk_info->extra_page
+				 */
+				if (!test_and_set_bit(R5C_EXTRA_PAGE_IN_USE,
+						      &conf->cache_state)) {
+					r5c_use_extra_page(sh);
+					break;
+				}
+
+				/* extra_page in use, add to delayed_list */
+				set_bit(STRIPE_DELAYED, &sh->state);
+				s->waiting_extra_page = 1;
+				return -EAGAIN;
+			}
+		}
+
+		for (i = disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			if (((dev->towrite && !delay_towrite(dev, s)) ||
+			     i == sh->pd_idx || i == sh->qd_idx ||
+			     test_bit(R5_InJournal, &dev->flags)) &&
 			    !test_bit(R5_LOCKED, &dev->flags) &&
-			    !(test_bit(R5_UPTODATE, &dev->flags) ||
-			    test_bit(R5_Wantcompute, &dev->flags)) &&
+			    !(uptodate_for_rmw(dev) ||
+			      test_bit(R5_Wantcompute, &dev->flags)) &&
 			    test_bit(R5_Insync, &dev->flags)) {
 				if (test_bit(STRIPE_PREREAD_ACTIVE,
 					     &sh->state)) {
@@ -3697,8 +3829,9 @@ static void handle_stripe_dirtying(struc
 	 */
 	if ((s->req_compute || !test_bit(STRIPE_COMPUTE_RUN, &sh->state)) &&
 	    (s->locked == 0 && (rcw == 0 || rmw == 0) &&
-	    !test_bit(STRIPE_BIT_DELAY, &sh->state)))
+	     !test_bit(STRIPE_BIT_DELAY, &sh->state)))
 		schedule_reconstruction(sh, s, rcw == 0, 0);
+	return 0;
 }
 
 static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh,
@@ -3782,7 +3915,7 @@ static void handle_parity_checks5(struct
 	case check_state_compute_run:
 		break;
 	default:
-		printk(KERN_ERR "%s: unknown check_state: %d sector: %llu\n",
+		pr_err("%s: unknown check_state: %d sector: %llu\n",
 		       __func__, sh->check_state,
 		       (unsigned long long) sh->sector);
 		BUG();
@@ -3946,9 +4079,9 @@ static void handle_parity_checks6(struct
 	case check_state_compute_run:
 		break;
 	default:
-		printk(KERN_ERR "%s: unknown check_state: %d sector: %llu\n",
-		       __func__, sh->check_state,
-		       (unsigned long long) sh->sector);
+		pr_warn("%s: unknown check_state: %d sector: %llu\n",
+			__func__, sh->check_state,
+			(unsigned long long) sh->sector);
 		BUG();
 	}
 }
@@ -4188,6 +4321,11 @@ static void analyse_stripe(struct stripe
 			if (rdev && !test_bit(Faulty, &rdev->flags))
 				do_recovery = 1;
 		}
+
+		if (test_bit(R5_InJournal, &dev->flags))
+			s->injournal++;
+		if (test_bit(R5_InJournal, &dev->flags) && dev->written)
+			s->just_cached++;
 	}
 	if (test_bit(STRIPE_SYNCING, &sh->state)) {
 		/* If there is a failed device being replaced,
@@ -4416,7 +4554,8 @@ static void handle_stripe(struct stripe_
 			struct r5dev *dev = &sh->dev[i];
 			if (test_bit(R5_LOCKED, &dev->flags) &&
 				(i == sh->pd_idx || i == sh->qd_idx ||
-				 dev->written)) {
+				 dev->written || test_bit(R5_InJournal,
+							  &dev->flags))) {
 				pr_debug("Writing block %d\n", i);
 				set_bit(R5_Wantwrite, &dev->flags);
 				if (prexor)
@@ -4456,6 +4595,10 @@ static void handle_stripe(struct stripe_
 				 test_bit(R5_Discard, &qdev->flags))))))
 		handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
 
+	if (s.just_cached)
+		r5c_handle_cached_data_endio(conf, sh, disks, &s.return_bi);
+	r5l_stripe_write_finished(sh);
+
 	/* Now we might consider reading some blocks, either to check/generate
 	 * parity, or to satisfy requests
 	 * or to load a block that is being partially written.
@@ -4467,14 +4610,51 @@ static void handle_stripe(struct stripe_
 	    || s.expanding)
 		handle_stripe_fill(sh, &s, disks);
 
-	/* Now to consider new write requests and what else, if anything
-	 * should be read.  We do not handle new writes when:
+	/*
+	 * When the stripe finishes full journal write cycle (write to journal
+	 * and raid disk), this is the clean up procedure so it is ready for
+	 * next operation.
+	 */
+	r5c_finish_stripe_write_out(conf, sh, &s);
+
+	/*
+	 * Now to consider new write requests, cache write back and what else,
+	 * if anything should be read.  We do not handle new writes when:
 	 * 1/ A 'write' operation (copy+xor) is already in flight.
 	 * 2/ A 'check' operation is in flight, as it may clobber the parity
 	 *    block.
+	 * 3/ A r5c cache log write is in flight.
 	 */
-	if (s.to_write && !sh->reconstruct_state && !sh->check_state)
-		handle_stripe_dirtying(conf, sh, &s, disks);
+
+	if (!sh->reconstruct_state && !sh->check_state && !sh->log_io) {
+		if (!r5c_is_writeback(conf->log)) {
+			if (s.to_write)
+				handle_stripe_dirtying(conf, sh, &s, disks);
+		} else { /* write back cache */
+			int ret = 0;
+
+			/* First, try handle writes in caching phase */
+			if (s.to_write)
+				ret = r5c_try_caching_write(conf, sh, &s,
+							    disks);
+			/*
+			 * If caching phase failed: ret == -EAGAIN
+			 *    OR
+			 * stripe under reclaim: !caching && injournal
+			 *
+			 * fall back to handle_stripe_dirtying()
+			 */
+			if (ret == -EAGAIN ||
+			    /* stripe under reclaim: !caching && injournal */
+			    (!test_bit(STRIPE_R5C_CACHING, &sh->state) &&
+			     s.injournal > 0)) {
+				ret = handle_stripe_dirtying(conf, sh, &s,
+							     disks);
+				if (ret == -EAGAIN)
+					goto finish;
+			}
+		}
+	}
 
 	/* maybe we need to check and possibly fix the parity for this stripe
 	 * Any reads will already have been scheduled, so we just see if enough
@@ -4645,9 +4825,7 @@ finish:
 	}
 
 	if (!bio_list_empty(&s.return_bi)) {
-		if (test_bit(MD_CHANGE_PENDING, &conf->mddev->flags) &&
-				(s.failed <= conf->max_degraded ||
-					conf->mddev->external == 0)) {
+		if (test_bit(MD_SB_CHANGE_PENDING, &conf->mddev->sb_flags)) {
 			spin_lock_irq(&conf->device_lock);
 			bio_list_merge(&conf->return_bi, &s.return_bi);
 			spin_unlock_irq(&conf->device_lock);
@@ -4703,6 +4881,10 @@ static int raid5_congested(struct mddev
 
 	if (test_bit(R5_INACTIVE_BLOCKED, &conf->cache_state))
 		return 1;
+
+	/* Also checks whether there is pressure on r5cache log space */
+	if (test_bit(R5C_LOG_TIGHT, &conf->cache_state))
+		return 1;
 	if (conf->quiesce)
 		return 1;
 	if (atomic_read(&conf->empty_inactive_list_nr))
@@ -5172,6 +5354,7 @@ static void raid5_make_request(struct md
 	int remaining;
 	DEFINE_WAIT(w);
 	bool do_prepare;
+	bool do_flush = false;
 
 	if (unlikely(bi->bi_opf & REQ_PREFLUSH)) {
 		int ret = r5l_handle_flush_request(conf->log, bi);
@@ -5183,6 +5366,11 @@ static void raid5_make_request(struct md
 			return;
 		}
 		/* ret == -EAGAIN, fallback */
+		/*
+		 * if r5l_handle_flush_request() didn't clear REQ_PREFLUSH,
+		 * we need to flush journal device
+		 */
+		do_flush = bi->bi_opf & REQ_PREFLUSH;
 	}
 
 	md_write_start(mddev, bi);
@@ -5193,6 +5381,7 @@ static void raid5_make_request(struct md
 	 * data on failed drives.
 	 */
 	if (rw == READ && mddev->degraded == 0 &&
+	    !r5c_is_writeback(conf->log) &&
 	    mddev->reshape_position == MaxSector) {
 		bi = chunk_aligned_read(mddev, bi);
 		if (!bi)
@@ -5321,6 +5510,12 @@ static void raid5_make_request(struct md
 				do_prepare = true;
 				goto retry;
 			}
+			if (do_flush) {
+				set_bit(STRIPE_R5C_PREFLUSH, &sh->state);
+				/* we only need flush for one stripe */
+				do_flush = false;
+			}
+
 			set_bit(STRIPE_HANDLE, &sh->state);
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			if ((!sh->batch_head || sh == sh->batch_head) &&
@@ -5486,9 +5681,9 @@ static sector_t reshape_request(struct m
 		mddev->reshape_position = conf->reshape_progress;
 		mddev->curr_resync_completed = sector_nr;
 		conf->reshape_checkpoint = jiffies;
-		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		md_wakeup_thread(mddev->thread);
-		wait_event(mddev->sb_wait, mddev->flags == 0 ||
+		wait_event(mddev->sb_wait, mddev->sb_flags == 0 ||
 			   test_bit(MD_RECOVERY_INTR, &mddev->recovery));
 		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
 			return 0;
@@ -5584,10 +5779,10 @@ finish:
 		mddev->reshape_position = conf->reshape_progress;
 		mddev->curr_resync_completed = sector_nr;
 		conf->reshape_checkpoint = jiffies;
-		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		md_wakeup_thread(mddev->thread);
 		wait_event(mddev->sb_wait,
-			   !test_bit(MD_CHANGE_DEVS, &mddev->flags)
+			   !test_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags)
 			   || test_bit(MD_RECOVERY_INTR, &mddev->recovery));
 		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery))
 			goto ret;
@@ -5862,10 +6057,10 @@ static void raid5d(struct md_thread *thr
 	md_check_recovery(mddev);
 
 	if (!bio_list_empty(&conf->return_bi) &&
-	    !test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+	    !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
 		struct bio_list tmp = BIO_EMPTY_LIST;
 		spin_lock_irq(&conf->device_lock);
-		if (!test_bit(MD_CHANGE_PENDING, &mddev->flags)) {
+		if (!test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags)) {
 			bio_list_merge(&tmp, &conf->return_bi);
 			bio_list_init(&conf->return_bi);
 		}
@@ -5912,7 +6107,7 @@ static void raid5d(struct md_thread *thr
 			break;
 		handled += batch_size;
 
-		if (mddev->flags & ~(1<<MD_CHANGE_PENDING)) {
+		if (mddev->sb_flags & ~(1 << MD_SB_CHANGE_PENDING)) {
 			spin_unlock_irq(&conf->device_lock);
 			md_check_recovery(mddev);
 			spin_lock_irq(&conf->device_lock);
@@ -6242,6 +6437,7 @@ static struct attribute *raid5_attrs[] =
 	&raid5_group_thread_cnt.attr,
 	&raid5_skip_copy.attr,
 	&raid5_rmw_level.attr,
+	&r5c_journal_mode.attr,
 	NULL,
 };
 static struct attribute_group raid5_attrs_group = {
@@ -6368,6 +6564,8 @@ static void raid5_free_percpu(struct r5c
 
 static void free_conf(struct r5conf *conf)
 {
+	int i;
+
 	if (conf->log)
 		r5l_exit_log(conf->log);
 	if (conf->shrinker.nr_deferred)
@@ -6376,6 +6574,9 @@ static void free_conf(struct r5conf *con
 	free_thread_groups(conf);
 	shrink_stripes(conf);
 	raid5_free_percpu(conf);
+	for (i = 0; i < conf->pool_size; i++)
+		if (conf->disks[i].extra_page)
+			put_page(conf->disks[i].extra_page);
 	kfree(conf->disks);
 	kfree(conf->stripe_hashtbl);
 	kfree(conf);
@@ -6387,8 +6588,8 @@ static int raid456_cpu_up_prepare(unsign
 	struct raid5_percpu *percpu = per_cpu_ptr(conf->percpu, cpu);
 
 	if (alloc_scratch_buffer(conf, percpu)) {
-		pr_err("%s: failed memory allocation for cpu%u\n",
-		       __func__, cpu);
+		pr_warn("%s: failed memory allocation for cpu%u\n",
+			__func__, cpu);
 		return -ENOMEM;
 	}
 	return 0;
@@ -6458,29 +6659,29 @@ static struct r5conf *setup_conf(struct
 	if (mddev->new_level != 5
 	    && mddev->new_level != 4
 	    && mddev->new_level != 6) {
-		printk(KERN_ERR "md/raid:%s: raid level not set to 4/5/6 (%d)\n",
-		       mdname(mddev), mddev->new_level);
+		pr_warn("md/raid:%s: raid level not set to 4/5/6 (%d)\n",
+			mdname(mddev), mddev->new_level);
 		return ERR_PTR(-EIO);
 	}
 	if ((mddev->new_level == 5
 	     && !algorithm_valid_raid5(mddev->new_layout)) ||
 	    (mddev->new_level == 6
 	     && !algorithm_valid_raid6(mddev->new_layout))) {
-		printk(KERN_ERR "md/raid:%s: layout %d not supported\n",
-		       mdname(mddev), mddev->new_layout);
+		pr_warn("md/raid:%s: layout %d not supported\n",
+			mdname(mddev), mddev->new_layout);
 		return ERR_PTR(-EIO);
 	}
 	if (mddev->new_level == 6 && mddev->raid_disks < 4) {
-		printk(KERN_ERR "md/raid:%s: not enough configured devices (%d, minimum 4)\n",
-		       mdname(mddev), mddev->raid_disks);
+		pr_warn("md/raid:%s: not enough configured devices (%d, minimum 4)\n",
+			mdname(mddev), mddev->raid_disks);
 		return ERR_PTR(-EINVAL);
 	}
 
 	if (!mddev->new_chunk_sectors ||
 	    (mddev->new_chunk_sectors << 9) % PAGE_SIZE ||
 	    !is_power_of_2(mddev->new_chunk_sectors)) {
-		printk(KERN_ERR "md/raid:%s: invalid chunk size %d\n",
-		       mdname(mddev), mddev->new_chunk_sectors << 9);
+		pr_warn("md/raid:%s: invalid chunk size %d\n",
+			mdname(mddev), mddev->new_chunk_sectors << 9);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -6522,9 +6723,16 @@ static struct r5conf *setup_conf(struct
 
 	conf->disks = kzalloc(max_disks * sizeof(struct disk_info),
 			      GFP_KERNEL);
+
 	if (!conf->disks)
 		goto abort;
 
+	for (i = 0; i < max_disks; i++) {
+		conf->disks[i].extra_page = alloc_page(GFP_KERNEL);
+		if (!conf->disks[i].extra_page)
+			goto abort;
+	}
+
 	conf->mddev = mddev;
 
 	if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
@@ -6545,6 +6753,11 @@ static struct r5conf *setup_conf(struct
 	for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++)
 		INIT_LIST_HEAD(conf->temp_inactive_list + i);
 
+	atomic_set(&conf->r5c_cached_full_stripes, 0);
+	INIT_LIST_HEAD(&conf->r5c_full_stripe_list);
+	atomic_set(&conf->r5c_cached_partial_stripes, 0);
+	INIT_LIST_HEAD(&conf->r5c_partial_stripe_list);
+
 	conf->level = mddev->new_level;
 	conf->chunk_sectors = mddev->new_chunk_sectors;
 	if (raid5_alloc_percpu(conf) != 0)
@@ -6571,9 +6784,8 @@ static struct r5conf *setup_conf(struct
 
 		if (test_bit(In_sync, &rdev->flags)) {
 			char b[BDEVNAME_SIZE];
-			printk(KERN_INFO "md/raid:%s: device %s operational as raid"
-			       " disk %d\n",
-			       mdname(mddev), bdevname(rdev->bdev, b), raid_disk);
+			pr_info("md/raid:%s: device %s operational as raid disk %d\n",
+				mdname(mddev), bdevname(rdev->bdev, b), raid_disk);
 		} else if (rdev->saved_raid_disk != raid_disk)
 			/* Cannot rely on bitmap to complete recovery */
 			conf->fullsync = 1;
@@ -6607,21 +6819,18 @@ static struct r5conf *setup_conf(struct
 			((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4);
 		conf->min_nr_stripes = max(NR_STRIPES, stripes);
 		if (conf->min_nr_stripes != NR_STRIPES)
-			printk(KERN_INFO
-				"md/raid:%s: force stripe size %d for reshape\n",
+			pr_info("md/raid:%s: force stripe size %d for reshape\n",
 				mdname(mddev), conf->min_nr_stripes);
 	}
 	memory = conf->min_nr_stripes * (sizeof(struct stripe_head) +
 		 max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
 	atomic_set(&conf->empty_inactive_list_nr, NR_STRIPE_HASH_LOCKS);
 	if (grow_stripes(conf, conf->min_nr_stripes)) {
-		printk(KERN_ERR
-		       "md/raid:%s: couldn't allocate %dkB for buffers\n",
-		       mdname(mddev), memory);
+		pr_warn("md/raid:%s: couldn't allocate %dkB for buffers\n",
+			mdname(mddev), memory);
 		goto abort;
 	} else
-		printk(KERN_INFO "md/raid:%s: allocated %dkB\n",
-		       mdname(mddev), memory);
+		pr_debug("md/raid:%s: allocated %dkB\n", mdname(mddev), memory);
 	/*
 	 * Losing a stripe head costs more than the time to refill it,
 	 * it reduces the queue depth and so can hurt throughput.
@@ -6633,18 +6842,16 @@ static struct r5conf *setup_conf(struct
 	conf->shrinker.batch = 128;
 	conf->shrinker.flags = 0;
 	if (register_shrinker(&conf->shrinker)) {
-		printk(KERN_ERR
-		       "md/raid:%s: couldn't register shrinker.\n",
-		       mdname(mddev));
+		pr_warn("md/raid:%s: couldn't register shrinker.\n",
+			mdname(mddev));
 		goto abort;
 	}
 
 	sprintf(pers_name, "raid%d", mddev->new_level);
 	conf->thread = md_register_thread(raid5d, mddev, pers_name);
 	if (!conf->thread) {
-		printk(KERN_ERR
-		       "md/raid:%s: couldn't allocate thread.\n",
-		       mdname(mddev));
+		pr_warn("md/raid:%s: couldn't allocate thread.\n",
+			mdname(mddev));
 		goto abort;
 	}
 
@@ -6697,9 +6904,8 @@ static int raid5_run(struct mddev *mddev
 	int first = 1;
 
 	if (mddev->recovery_cp != MaxSector)
-		printk(KERN_NOTICE "md/raid:%s: not clean"
-		       " -- starting background reconstruction\n",
-		       mdname(mddev));
+		pr_notice("md/raid:%s: not clean -- starting background reconstruction\n",
+			  mdname(mddev));
 
 	rdev_for_each(rdev, mddev) {
 		long long diff;
@@ -6742,15 +6948,14 @@ static int raid5_run(struct mddev *mddev
 		int new_data_disks;
 
 		if (journal_dev) {
-			printk(KERN_ERR "md/raid:%s: don't support reshape with journal - aborting.\n",
-			       mdname(mddev));
+			pr_warn("md/raid:%s: don't support reshape with journal - aborting.\n",
+				mdname(mddev));
 			return -EINVAL;
 		}
 
 		if (mddev->new_level != mddev->level) {
-			printk(KERN_ERR "md/raid:%s: unsupported reshape "
-			       "required - aborting.\n",
-			       mdname(mddev));
+			pr_warn("md/raid:%s: unsupported reshape required - aborting.\n",
+				mdname(mddev));
 			return -EINVAL;
 		}
 		old_disks = mddev->raid_disks - mddev->delta_disks;
@@ -6765,8 +6970,8 @@ static int raid5_run(struct mddev *mddev
 		chunk_sectors = max(mddev->chunk_sectors, mddev->new_chunk_sectors);
 		new_data_disks = mddev->raid_disks - max_degraded;
 		if (sector_div(here_new, chunk_sectors * new_data_disks)) {
-			printk(KERN_ERR "md/raid:%s: reshape_position not "
-			       "on a stripe boundary\n", mdname(mddev));
+			pr_warn("md/raid:%s: reshape_position not on a stripe boundary\n",
+				mdname(mddev));
 			return -EINVAL;
 		}
 		reshape_offset = here_new * chunk_sectors;
@@ -6787,10 +6992,8 @@ static int raid5_run(struct mddev *mddev
 			    abs(min_offset_diff) >= mddev->new_chunk_sectors)
 				/* not really in-place - so OK */;
 			else if (mddev->ro == 0) {
-				printk(KERN_ERR "md/raid:%s: in-place reshape "
-				       "must be started in read-only mode "
-				       "- aborting\n",
-				       mdname(mddev));
+				pr_warn("md/raid:%s: in-place reshape must be started in read-only mode - aborting\n",
+					mdname(mddev));
 				return -EINVAL;
 			}
 		} else if (mddev->reshape_backwards
@@ -6799,13 +7002,11 @@ static int raid5_run(struct mddev *mddev
 		    : (here_new * chunk_sectors >=
 		       here_old * chunk_sectors + (-min_offset_diff))) {
 			/* Reading from the same stripe as writing to - bad */
-			printk(KERN_ERR "md/raid:%s: reshape_position too early for "
-			       "auto-recovery - aborting.\n",
-			       mdname(mddev));
+			pr_warn("md/raid:%s: reshape_position too early for auto-recovery - aborting.\n",
+				mdname(mddev));
 			return -EINVAL;
 		}
-		printk(KERN_INFO "md/raid:%s: reshape will continue\n",
-		       mdname(mddev));
+		pr_debug("md/raid:%s: reshape will continue\n", mdname(mddev));
 		/* OK, we should be able to continue; */
 	} else {
 		BUG_ON(mddev->level != mddev->new_level);
@@ -6824,8 +7025,8 @@ static int raid5_run(struct mddev *mddev
 
 	if (test_bit(MD_HAS_JOURNAL, &mddev->flags)) {
 		if (!journal_dev) {
-			pr_err("md/raid:%s: journal disk is missing, force array readonly\n",
-			       mdname(mddev));
+			pr_warn("md/raid:%s: journal disk is missing, force array readonly\n",
+				mdname(mddev));
 			mddev->ro = 1;
 			set_disk_ro(mddev->gendisk, 1);
 		} else if (mddev->recovery_cp == MaxSector)
@@ -6852,8 +7053,7 @@ static int raid5_run(struct mddev *mddev
 		if (conf->disks[i].replacement &&
 		    conf->reshape_progress != MaxSector) {
 			/* replacements and reshape simply do not mix. */
-			printk(KERN_ERR "md: cannot handle concurrent "
-			       "replacement and reshape.\n");
+			pr_warn("md: cannot handle concurrent replacement and reshape.\n");
 			goto abort;
 		}
 		if (test_bit(In_sync, &rdev->flags)) {
@@ -6892,11 +7092,10 @@ static int raid5_run(struct mddev *mddev
 	/*
 	 * 0 for a fully functional array, 1 or 2 for a degraded array.
 	 */
-	mddev->degraded = calc_degraded(conf);
+	mddev->degraded = raid5_calc_degraded(conf);
 
 	if (has_failed(conf)) {
-		printk(KERN_ERR "md/raid:%s: not enough operational devices"
-			" (%d/%d failed)\n",
+		pr_crit("md/raid:%s: not enough operational devices (%d/%d failed)\n",
 			mdname(mddev), mddev->degraded, conf->raid_disks);
 		goto abort;
 	}
@@ -6908,29 +7107,19 @@ static int raid5_run(struct mddev *mddev
 	if (mddev->degraded > dirty_parity_disks &&
 	    mddev->recovery_cp != MaxSector) {
 		if (mddev->ok_start_degraded)
-			printk(KERN_WARNING
-			       "md/raid:%s: starting dirty degraded array"
-			       " - data corruption possible.\n",
-			       mdname(mddev));
+			pr_crit("md/raid:%s: starting dirty degraded array - data corruption possible.\n",
+				mdname(mddev));
 		else {
-			printk(KERN_ERR
-			       "md/raid:%s: cannot start dirty degraded array.\n",
-			       mdname(mddev));
+			pr_crit("md/raid:%s: cannot start dirty degraded array.\n",
+				mdname(mddev));
 			goto abort;
 		}
 	}
 
-	if (mddev->degraded == 0)
-		printk(KERN_INFO "md/raid:%s: raid level %d active with %d out of %d"
-		       " devices, algorithm %d\n", mdname(mddev), conf->level,
-		       mddev->raid_disks-mddev->degraded, mddev->raid_disks,
-		       mddev->new_layout);
-	else
-		printk(KERN_ALERT "md/raid:%s: raid level %d active with %d"
-		       " out of %d devices, algorithm %d\n",
-		       mdname(mddev), conf->level,
-		       mddev->raid_disks - mddev->degraded,
-		       mddev->raid_disks, mddev->new_layout);
+	pr_info("md/raid:%s: raid level %d active with %d out of %d devices, algorithm %d\n",
+		mdname(mddev), conf->level,
+		mddev->raid_disks-mddev->degraded, mddev->raid_disks,
+		mddev->new_layout);
 
 	print_raid5_conf(conf);
 
@@ -6950,9 +7139,8 @@ static int raid5_run(struct mddev *mddev
 		mddev->to_remove = NULL;
 	else if (mddev->kobj.sd &&
 	    sysfs_create_group(&mddev->kobj, &raid5_attrs_group))
-		printk(KERN_WARNING
-		       "raid5: failed to create sysfs attributes for %s\n",
-		       mdname(mddev));
+		pr_warn("raid5: failed to create sysfs attributes for %s\n",
+			mdname(mddev));
 	md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
 
 	if (mddev->queue) {
@@ -6984,6 +7172,15 @@ static int raid5_run(struct mddev *mddev
 			stripe = (stripe | (stripe-1)) + 1;
 		mddev->queue->limits.discard_alignment = stripe;
 		mddev->queue->limits.discard_granularity = stripe;
+
+		/*
+		 * We use 16-bit counter of active stripes in bi_phys_segments
+		 * (minus one for over-loaded initialization)
+		 */
+		blk_queue_max_hw_sectors(mddev->queue, 0xfffe * STRIPE_SECTORS);
+		blk_queue_max_discard_sectors(mddev->queue,
+					      0xfffe * STRIPE_SECTORS);
+
 		/*
 		 * unaligned part of discard request will be ignored, so can't
 		 * guarantee discard_zeroes_data
@@ -7040,9 +7237,10 @@ static int raid5_run(struct mddev *mddev
 	if (journal_dev) {
 		char b[BDEVNAME_SIZE];
 
-		printk(KERN_INFO"md/raid:%s: using device %s as journal\n",
-		       mdname(mddev), bdevname(journal_dev->bdev, b));
-		r5l_init_log(conf, journal_dev);
+		pr_debug("md/raid:%s: using device %s as journal\n",
+			 mdname(mddev), bdevname(journal_dev->bdev, b));
+		if (r5l_init_log(conf, journal_dev))
+			goto abort;
 	}
 
 	return 0;
@@ -7051,7 +7249,7 @@ abort:
 	print_raid5_conf(conf);
 	free_conf(conf);
 	mddev->private = NULL;
-	printk(KERN_ALERT "md/raid:%s: failed to run raid set.\n", mdname(mddev));
+	pr_warn("md/raid:%s: failed to run raid set.\n", mdname(mddev));
 	return -EIO;
 }
 
@@ -7085,12 +7283,12 @@ static void print_raid5_conf (struct r5c
 	int i;
 	struct disk_info *tmp;
 
-	printk(KERN_DEBUG "RAID conf printout:\n");
+	pr_debug("RAID conf printout:\n");
 	if (!conf) {
-		printk("(conf==NULL)\n");
+		pr_debug("(conf==NULL)\n");
 		return;
 	}
-	printk(KERN_DEBUG " --- level:%d rd:%d wd:%d\n", conf->level,
+	pr_debug(" --- level:%d rd:%d wd:%d\n", conf->level,
 	       conf->raid_disks,
 	       conf->raid_disks - conf->mddev->degraded);
 
@@ -7098,7 +7296,7 @@ static void print_raid5_conf (struct r5c
 		char b[BDEVNAME_SIZE];
 		tmp = conf->disks + i;
 		if (tmp->rdev)
-			printk(KERN_DEBUG " disk %d, o:%d, dev:%s\n",
+			pr_debug(" disk %d, o:%d, dev:%s\n",
 			       i, !test_bit(Faulty, &tmp->rdev->flags),
 			       bdevname(tmp->rdev->bdev, b));
 	}
@@ -7141,7 +7339,7 @@ static int raid5_spare_active(struct mdd
 		}
 	}
 	spin_lock_irqsave(&conf->device_lock, flags);
-	mddev->degraded = calc_degraded(conf);
+	mddev->degraded = raid5_calc_degraded(conf);
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 	print_raid5_conf(conf);
 	return count;
@@ -7246,8 +7444,8 @@ static int raid5_add_disk(struct mddev *
 		 * write requests running. We should be safe
 		 */
 		r5l_init_log(conf, rdev);
-		printk(KERN_INFO"md/raid:%s: using device %s as journal\n",
-		       mdname(mddev), bdevname(rdev->bdev, b));
+		pr_debug("md/raid:%s: using device %s as journal\n",
+			 mdname(mddev), bdevname(rdev->bdev, b));
 		return 0;
 	}
 	if (mddev->recovery_disabled == conf->recovery_disabled)
@@ -7351,10 +7549,10 @@ static int check_stripe_cache(struct mdd
 	    > conf->min_nr_stripes ||
 	    ((mddev->new_chunk_sectors << 9) / STRIPE_SIZE) * 4
 	    > conf->min_nr_stripes) {
-		printk(KERN_WARNING "md/raid:%s: reshape: not enough stripes.  Needed %lu\n",
-		       mdname(mddev),
-		       ((max(mddev->chunk_sectors, mddev->new_chunk_sectors) << 9)
-			/ STRIPE_SIZE)*4);
+		pr_warn("md/raid:%s: reshape: not enough stripes.  Needed %lu\n",
+			mdname(mddev),
+			((max(mddev->chunk_sectors, mddev->new_chunk_sectors) << 9)
+			 / STRIPE_SIZE)*4);
 		return 0;
 	}
 	return 1;
@@ -7435,8 +7633,8 @@ static int raid5_start_reshape(struct md
 	 */
 	if (raid5_size(mddev, 0, conf->raid_disks + mddev->delta_disks)
 	    < mddev->array_sectors) {
-		printk(KERN_ERR "md/raid:%s: array size must be reduced "
-		       "before number of disks\n", mdname(mddev));
+		pr_warn("md/raid:%s: array size must be reduced before number of disks\n",
+			mdname(mddev));
 		return -EINVAL;
 	}
 
@@ -7501,12 +7699,12 @@ static int raid5_start_reshape(struct md
 		 * pre and post number of devices.
 		 */
 		spin_lock_irqsave(&conf->device_lock, flags);
-		mddev->degraded = calc_degraded(conf);
+		mddev->degraded = raid5_calc_degraded(conf);
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 	mddev->raid_disks = conf->raid_disks;
 	mddev->reshape_position = conf->reshape_progress;
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 
 	clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
 	clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
@@ -7589,7 +7787,7 @@ static void raid5_finish_reshape(struct
 		} else {
 			int d;
 			spin_lock_irq(&conf->device_lock);
-			mddev->degraded = calc_degraded(conf);
+			mddev->degraded = raid5_calc_degraded(conf);
 			spin_unlock_irq(&conf->device_lock);
 			for (d = conf->raid_disks ;
 			     d < conf->raid_disks - mddev->delta_disks;
@@ -7624,6 +7822,7 @@ static void raid5_quiesce(struct mddev *
 		/* '2' tells resync/reshape to pause so that all
 		 * active stripes can drain
 		 */
+		r5c_flush_cache(conf, INT_MAX);
 		conf->quiesce = 2;
 		wait_event_cmd(conf->wait_for_quiescent,
 				    atomic_read(&conf->active_stripes) == 0 &&
@@ -7654,8 +7853,8 @@ static void *raid45_takeover_raid0(struc
 
 	/* for raid0 takeover only one zone is supported */
 	if (raid0_conf->nr_strip_zones > 1) {
-		printk(KERN_ERR "md/raid:%s: cannot takeover raid0 with more than one zone.\n",
-		       mdname(mddev));
+		pr_warn("md/raid:%s: cannot takeover raid0 with more than one zone.\n",
+			mdname(mddev));
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -7676,6 +7875,7 @@ static void *raid45_takeover_raid0(struc
 static void *raid5_takeover_raid1(struct mddev *mddev)
 {
 	int chunksect;
+	void *ret;
 
 	if (mddev->raid_disks != 2 ||
 	    mddev->degraded > 1)
@@ -7697,7 +7897,11 @@ static void *raid5_takeover_raid1(struct
 	mddev->new_layout = ALGORITHM_LEFT_SYMMETRIC;
 	mddev->new_chunk_sectors = chunksect;
 
-	return setup_conf(mddev);
+	ret = setup_conf(mddev);
+	if (!IS_ERR(ret))
+		mddev_clear_unsupported_flags(mddev,
+			UNSUPPORTED_MDDEV_FLAGS);
+	return ret;
 }
 
 static void *raid5_takeover_raid6(struct mddev *mddev)
@@ -7767,7 +7971,7 @@ static int raid5_check_reshape(struct md
 			conf->chunk_sectors = new_chunk ;
 			mddev->chunk_sectors = new_chunk;
 		}
-		set_bit(MD_CHANGE_DEVS, &mddev->flags);
+		set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
 		md_wakeup_thread(mddev->thread);
 	}
 	return check_reshape(mddev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid5-cache.c linux-libre-4.10-rc8-gnu/drivers/md/raid5-cache.c
--- linux-libre-4.9-gnu/drivers/md/raid5-cache.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid5-cache.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2015 Shaohua Li <shli@fb.com>
+ * Copyright (C) 2016 Song Liu <songliubraving@fb.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,
@@ -18,8 +19,10 @@
 #include <linux/raid/md_p.h>
 #include <linux/crc32c.h>
 #include <linux/random.h>
+#include <linux/kthread.h>
 #include "md.h"
 #include "raid5.h"
+#include "bitmap.h"
 
 /*
  * metadata/data stored in disk with 4k size unit (a block) regardless
@@ -28,18 +31,70 @@
 #define BLOCK_SECTORS (8)
 
 /*
- * reclaim runs every 1/4 disk size or 10G reclaimable space. This can prevent
- * recovery scans a very long log
+ * log->max_free_space is min(1/4 disk size, 10G reclaimable space).
+ *
+ * In write through mode, the reclaim runs every log->max_free_space.
+ * This can prevent the recovery scans for too long
  */
 #define RECLAIM_MAX_FREE_SPACE (10 * 1024 * 1024 * 2) /* sector */
 #define RECLAIM_MAX_FREE_SPACE_SHIFT (2)
 
+/* wake up reclaim thread periodically */
+#define R5C_RECLAIM_WAKEUP_INTERVAL (30 * HZ)
+/* start flush with these full stripes */
+#define R5C_FULL_STRIPE_FLUSH_BATCH 256
+/* reclaim stripes in groups */
+#define R5C_RECLAIM_STRIPE_GROUP (NR_STRIPE_HASH_LOCKS * 2)
+
 /*
  * We only need 2 bios per I/O unit to make progress, but ensure we
  * have a few more available to not get too tight.
  */
 #define R5L_POOL_SIZE	4
 
+/*
+ * r5c journal modes of the array: write-back or write-through.
+ * write-through mode has identical behavior as existing log only
+ * implementation.
+ */
+enum r5c_journal_mode {
+	R5C_JOURNAL_MODE_WRITE_THROUGH = 0,
+	R5C_JOURNAL_MODE_WRITE_BACK = 1,
+};
+
+static char *r5c_journal_mode_str[] = {"write-through",
+				       "write-back"};
+/*
+ * raid5 cache state machine
+ *
+ * With the RAID cache, each stripe works in two phases:
+ *	- caching phase
+ *	- writing-out phase
+ *
+ * These two phases are controlled by bit STRIPE_R5C_CACHING:
+ *   if STRIPE_R5C_CACHING == 0, the stripe is in writing-out phase
+ *   if STRIPE_R5C_CACHING == 1, the stripe is in caching phase
+ *
+ * When there is no journal, or the journal is in write-through mode,
+ * the stripe is always in writing-out phase.
+ *
+ * For write-back journal, the stripe is sent to caching phase on write
+ * (r5c_try_caching_write). r5c_make_stripe_write_out() kicks off
+ * the write-out phase by clearing STRIPE_R5C_CACHING.
+ *
+ * Stripes in caching phase do not write the raid disks. Instead, all
+ * writes are committed from the log device. Therefore, a stripe in
+ * caching phase handles writes as:
+ *	- write to log device
+ *	- return IO
+ *
+ * Stripes in writing-out phase handle writes as:
+ *	- calculate parity
+ *	- write pending data and parity to journal
+ *	- write data and parity to raid disks
+ *	- return IO for pending writes
+ */
+
 struct r5l_log {
 	struct md_rdev *rdev;
 
@@ -58,7 +113,6 @@ struct r5l_log {
 	u64 seq;			/* log head sequence */
 
 	sector_t next_checkpoint;
-	u64 next_cp_seq;
 
 	struct mutex io_mutex;
 	struct r5l_io_unit *current_io;	/* current io_unit accepting new data */
@@ -96,6 +150,20 @@ struct r5l_log {
 	spinlock_t no_space_stripes_lock;
 
 	bool need_cache_flush;
+
+	/* for r5c_cache */
+	enum r5c_journal_mode r5c_journal_mode;
+
+	/* all stripes in r5cache, in the order of seq at sh->log_start */
+	struct list_head stripe_in_journal_list;
+
+	spinlock_t stripe_in_journal_lock;
+	atomic_t stripe_in_journal_count;
+
+	/* to submit async io_units, to fulfill ordering of flush */
+	struct work_struct deferred_io_work;
+	/* to disable write back during in degraded mode */
+	struct work_struct disable_writeback_work;
 };
 
 /*
@@ -122,6 +190,18 @@ struct r5l_io_unit {
 
 	int state;
 	bool need_split_bio;
+	struct bio *split_bio;
+
+	unsigned int has_flush:1;      /* include flush request */
+	unsigned int has_fua:1;        /* include fua request */
+	unsigned int has_null_flush:1; /* include empty flush request */
+	/*
+	 * io isn't sent yet, flush/fua request can only be submitted till it's
+	 * the first IO in running_ios list
+	 */
+	unsigned int io_deferred:1;
+
+	struct bio_list flush_barriers;   /* size == 0 flush bios */
 };
 
 /* r5l_io_unit state */
@@ -133,6 +213,12 @@ enum r5l_io_unit_state {
 	IO_UNIT_STRIPE_END = 3,	/* stripes data finished writing to raid */
 };
 
+bool r5c_is_writeback(struct r5l_log *log)
+{
+	return (log != NULL &&
+		log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK);
+}
+
 static sector_t r5l_ring_add(struct r5l_log *log, sector_t start, sector_t inc)
 {
 	start += inc;
@@ -168,12 +254,235 @@ static void __r5l_set_io_unit_state(stru
 	io->state = state;
 }
 
+static void
+r5c_return_dev_pending_writes(struct r5conf *conf, struct r5dev *dev,
+			      struct bio_list *return_bi)
+{
+	struct bio *wbi, *wbi2;
+
+	wbi = dev->written;
+	dev->written = NULL;
+	while (wbi && wbi->bi_iter.bi_sector <
+	       dev->sector + STRIPE_SECTORS) {
+		wbi2 = r5_next_bio(wbi, dev->sector);
+		if (!raid5_dec_bi_active_stripes(wbi)) {
+			md_write_end(conf->mddev);
+			bio_list_add(return_bi, wbi);
+		}
+		wbi = wbi2;
+	}
+}
+
+void r5c_handle_cached_data_endio(struct r5conf *conf,
+	  struct stripe_head *sh, int disks, struct bio_list *return_bi)
+{
+	int i;
+
+	for (i = sh->disks; i--; ) {
+		if (sh->dev[i].written) {
+			set_bit(R5_UPTODATE, &sh->dev[i].flags);
+			r5c_return_dev_pending_writes(conf, &sh->dev[i],
+						      return_bi);
+			bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+					STRIPE_SECTORS,
+					!test_bit(STRIPE_DEGRADED, &sh->state),
+					0);
+		}
+	}
+}
+
+/* Check whether we should flush some stripes to free up stripe cache */
+void r5c_check_stripe_cache_usage(struct r5conf *conf)
+{
+	int total_cached;
+
+	if (!r5c_is_writeback(conf->log))
+		return;
+
+	total_cached = atomic_read(&conf->r5c_cached_partial_stripes) +
+		atomic_read(&conf->r5c_cached_full_stripes);
+
+	/*
+	 * The following condition is true for either of the following:
+	 *   - stripe cache pressure high:
+	 *          total_cached > 3/4 min_nr_stripes ||
+	 *          empty_inactive_list_nr > 0
+	 *   - stripe cache pressure moderate:
+	 *          total_cached > 1/2 min_nr_stripes
+	 */
+	if (total_cached > conf->min_nr_stripes * 1 / 2 ||
+	    atomic_read(&conf->empty_inactive_list_nr) > 0)
+		r5l_wake_reclaim(conf->log, 0);
+}
+
+/*
+ * flush cache when there are R5C_FULL_STRIPE_FLUSH_BATCH or more full
+ * stripes in the cache
+ */
+void r5c_check_cached_full_stripe(struct r5conf *conf)
+{
+	if (!r5c_is_writeback(conf->log))
+		return;
+
+	/*
+	 * wake up reclaim for R5C_FULL_STRIPE_FLUSH_BATCH cached stripes
+	 * or a full stripe (chunk size / 4k stripes).
+	 */
+	if (atomic_read(&conf->r5c_cached_full_stripes) >=
+	    min(R5C_FULL_STRIPE_FLUSH_BATCH,
+		conf->chunk_sectors >> STRIPE_SHIFT))
+		r5l_wake_reclaim(conf->log, 0);
+}
+
+/*
+ * Total log space (in sectors) needed to flush all data in cache
+ *
+ * Currently, writing-out phase automatically includes all pending writes
+ * to the same sector. So the reclaim of each stripe takes up to
+ * (conf->raid_disks + 1) pages of log space.
+ *
+ * To totally avoid deadlock due to log space, the code reserves
+ * (conf->raid_disks + 1) pages for each stripe in cache, which is not
+ * necessary in most cases.
+ *
+ * To improve this, we will need writing-out phase to be able to NOT include
+ * pending writes, which will reduce the requirement to
+ * (conf->max_degraded + 1) pages per stripe in cache.
+ */
+static sector_t r5c_log_required_to_flush_cache(struct r5conf *conf)
+{
+	struct r5l_log *log = conf->log;
+
+	if (!r5c_is_writeback(log))
+		return 0;
+
+	return BLOCK_SECTORS * (conf->raid_disks + 1) *
+		atomic_read(&log->stripe_in_journal_count);
+}
+
+/*
+ * evaluate log space usage and update R5C_LOG_TIGHT and R5C_LOG_CRITICAL
+ *
+ * R5C_LOG_TIGHT is set when free space on the log device is less than 3x of
+ * reclaim_required_space. R5C_LOG_CRITICAL is set when free space on the log
+ * device is less than 2x of reclaim_required_space.
+ */
+static inline void r5c_update_log_state(struct r5l_log *log)
+{
+	struct r5conf *conf = log->rdev->mddev->private;
+	sector_t free_space;
+	sector_t reclaim_space;
+	bool wake_reclaim = false;
+
+	if (!r5c_is_writeback(log))
+		return;
+
+	free_space = r5l_ring_distance(log, log->log_start,
+				       log->last_checkpoint);
+	reclaim_space = r5c_log_required_to_flush_cache(conf);
+	if (free_space < 2 * reclaim_space)
+		set_bit(R5C_LOG_CRITICAL, &conf->cache_state);
+	else {
+		if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state))
+			wake_reclaim = true;
+		clear_bit(R5C_LOG_CRITICAL, &conf->cache_state);
+	}
+	if (free_space < 3 * reclaim_space)
+		set_bit(R5C_LOG_TIGHT, &conf->cache_state);
+	else
+		clear_bit(R5C_LOG_TIGHT, &conf->cache_state);
+
+	if (wake_reclaim)
+		r5l_wake_reclaim(log, 0);
+}
+
+/*
+ * Put the stripe into writing-out phase by clearing STRIPE_R5C_CACHING.
+ * This function should only be called in write-back mode.
+ */
+void r5c_make_stripe_write_out(struct stripe_head *sh)
+{
+	struct r5conf *conf = sh->raid_conf;
+	struct r5l_log *log = conf->log;
+
+	BUG_ON(!r5c_is_writeback(log));
+
+	WARN_ON(!test_bit(STRIPE_R5C_CACHING, &sh->state));
+	clear_bit(STRIPE_R5C_CACHING, &sh->state);
+
+	if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
+		atomic_inc(&conf->preread_active_stripes);
+
+	if (test_and_clear_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state)) {
+		BUG_ON(atomic_read(&conf->r5c_cached_partial_stripes) == 0);
+		atomic_dec(&conf->r5c_cached_partial_stripes);
+	}
+
+	if (test_and_clear_bit(STRIPE_R5C_FULL_STRIPE, &sh->state)) {
+		BUG_ON(atomic_read(&conf->r5c_cached_full_stripes) == 0);
+		atomic_dec(&conf->r5c_cached_full_stripes);
+	}
+}
+
+static void r5c_handle_data_cached(struct stripe_head *sh)
+{
+	int i;
+
+	for (i = sh->disks; i--; )
+		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) {
+			set_bit(R5_InJournal, &sh->dev[i].flags);
+			clear_bit(R5_LOCKED, &sh->dev[i].flags);
+		}
+	clear_bit(STRIPE_LOG_TRAPPED, &sh->state);
+}
+
+/*
+ * this journal write must contain full parity,
+ * it may also contain some data pages
+ */
+static void r5c_handle_parity_cached(struct stripe_head *sh)
+{
+	int i;
+
+	for (i = sh->disks; i--; )
+		if (test_bit(R5_InJournal, &sh->dev[i].flags))
+			set_bit(R5_Wantwrite, &sh->dev[i].flags);
+}
+
+/*
+ * Setting proper flags after writing (or flushing) data and/or parity to the
+ * log device. This is called from r5l_log_endio() or r5l_log_flush_endio().
+ */
+static void r5c_finish_cache_stripe(struct stripe_head *sh)
+{
+	struct r5l_log *log = sh->raid_conf->log;
+
+	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
+		BUG_ON(test_bit(STRIPE_R5C_CACHING, &sh->state));
+		/*
+		 * Set R5_InJournal for parity dev[pd_idx]. This means
+		 * all data AND parity in the journal. For RAID 6, it is
+		 * NOT necessary to set the flag for dev[qd_idx], as the
+		 * two parities are written out together.
+		 */
+		set_bit(R5_InJournal, &sh->dev[sh->pd_idx].flags);
+	} else if (test_bit(STRIPE_R5C_CACHING, &sh->state)) {
+		r5c_handle_data_cached(sh);
+	} else {
+		r5c_handle_parity_cached(sh);
+		set_bit(R5_InJournal, &sh->dev[sh->pd_idx].flags);
+	}
+}
+
 static void r5l_io_run_stripes(struct r5l_io_unit *io)
 {
 	struct stripe_head *sh, *next;
 
 	list_for_each_entry_safe(sh, next, &io->stripe_list, log_list) {
 		list_del_init(&sh->log_list);
+
+		r5c_finish_cache_stripe(sh);
+
 		set_bit(STRIPE_HANDLE, &sh->state);
 		raid5_release_stripe(sh);
 	}
@@ -209,9 +518,11 @@ static void r5l_move_to_end_ios(struct r
 	}
 }
 
+static void __r5l_stripe_write_finished(struct r5l_io_unit *io);
 static void r5l_log_endio(struct bio *bio)
 {
 	struct r5l_io_unit *io = bio->bi_private;
+	struct r5l_io_unit *io_deferred;
 	struct r5l_log *log = io->log;
 	unsigned long flags;
 
@@ -227,18 +538,104 @@ static void r5l_log_endio(struct bio *bi
 		r5l_move_to_end_ios(log);
 	else
 		r5l_log_run_stripes(log);
+	if (!list_empty(&log->running_ios)) {
+		/*
+		 * FLUSH/FUA io_unit is deferred because of ordering, now we
+		 * can dispatch it
+		 */
+		io_deferred = list_first_entry(&log->running_ios,
+					       struct r5l_io_unit, log_sibling);
+		if (io_deferred->io_deferred)
+			schedule_work(&log->deferred_io_work);
+	}
+
 	spin_unlock_irqrestore(&log->io_list_lock, flags);
 
 	if (log->need_cache_flush)
 		md_wakeup_thread(log->rdev->mddev->thread);
+
+	if (io->has_null_flush) {
+		struct bio *bi;
+
+		WARN_ON(bio_list_empty(&io->flush_barriers));
+		while ((bi = bio_list_pop(&io->flush_barriers)) != NULL) {
+			bio_endio(bi);
+			atomic_dec(&io->pending_stripe);
+		}
+		if (atomic_read(&io->pending_stripe) == 0)
+			__r5l_stripe_write_finished(io);
+	}
+}
+
+static void r5l_do_submit_io(struct r5l_log *log, struct r5l_io_unit *io)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&log->io_list_lock, flags);
+	__r5l_set_io_unit_state(io, IO_UNIT_IO_START);
+	spin_unlock_irqrestore(&log->io_list_lock, flags);
+
+	if (io->has_flush)
+		io->current_bio->bi_opf |= REQ_PREFLUSH;
+	if (io->has_fua)
+		io->current_bio->bi_opf |= REQ_FUA;
+	submit_bio(io->current_bio);
+
+	if (!io->split_bio)
+		return;
+
+	if (io->has_flush)
+		io->split_bio->bi_opf |= REQ_PREFLUSH;
+	if (io->has_fua)
+		io->split_bio->bi_opf |= REQ_FUA;
+	submit_bio(io->split_bio);
+}
+
+/* deferred io_unit will be dispatched here */
+static void r5l_submit_io_async(struct work_struct *work)
+{
+	struct r5l_log *log = container_of(work, struct r5l_log,
+					   deferred_io_work);
+	struct r5l_io_unit *io = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&log->io_list_lock, flags);
+	if (!list_empty(&log->running_ios)) {
+		io = list_first_entry(&log->running_ios, struct r5l_io_unit,
+				      log_sibling);
+		if (!io->io_deferred)
+			io = NULL;
+		else
+			io->io_deferred = 0;
+	}
+	spin_unlock_irqrestore(&log->io_list_lock, flags);
+	if (io)
+		r5l_do_submit_io(log, io);
+}
+
+static void r5c_disable_writeback_async(struct work_struct *work)
+{
+	struct r5l_log *log = container_of(work, struct r5l_log,
+					   disable_writeback_work);
+	struct mddev *mddev = log->rdev->mddev;
+
+	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH)
+		return;
+	pr_info("md/raid:%s: Disabling writeback cache for degraded array.\n",
+		mdname(mddev));
+	mddev_suspend(mddev);
+	log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
+	mddev_resume(mddev);
 }
 
 static void r5l_submit_current_io(struct r5l_log *log)
 {
 	struct r5l_io_unit *io = log->current_io;
+	struct bio *bio;
 	struct r5l_meta_block *block;
 	unsigned long flags;
 	u32 crc;
+	bool do_submit = true;
 
 	if (!io)
 		return;
@@ -247,13 +644,20 @@ static void r5l_submit_current_io(struct
 	block->meta_size = cpu_to_le32(io->meta_offset);
 	crc = crc32c_le(log->uuid_checksum, block, PAGE_SIZE);
 	block->checksum = cpu_to_le32(crc);
+	bio = io->current_bio;
 
 	log->current_io = NULL;
 	spin_lock_irqsave(&log->io_list_lock, flags);
-	__r5l_set_io_unit_state(io, IO_UNIT_IO_START);
+	if (io->has_flush || io->has_fua) {
+		if (io != list_first_entry(&log->running_ios,
+					   struct r5l_io_unit, log_sibling)) {
+			io->io_deferred = 1;
+			do_submit = false;
+		}
+	}
 	spin_unlock_irqrestore(&log->io_list_lock, flags);
-
-	submit_bio(io->current_bio);
+	if (do_submit)
+		r5l_do_submit_io(log, io);
 }
 
 static struct bio *r5l_bio_alloc(struct r5l_log *log)
@@ -271,6 +675,7 @@ static void r5_reserve_log_entry(struct
 {
 	log->log_start = r5l_ring_add(log, log->log_start, BLOCK_SECTORS);
 
+	r5c_update_log_state(log);
 	/*
 	 * If we filled up the log device start from the beginning again,
 	 * which will require a new bio.
@@ -297,6 +702,7 @@ static struct r5l_io_unit *r5l_new_meta(
 	io->log = log;
 	INIT_LIST_HEAD(&io->log_sibling);
 	INIT_LIST_HEAD(&io->stripe_list);
+	bio_list_init(&io->flush_barriers);
 	io->state = IO_UNIT_RUNNING;
 
 	io->meta_page = mempool_alloc(log->meta_pool, GFP_NOIO);
@@ -367,12 +773,11 @@ static void r5l_append_payload_page(stru
 	struct r5l_io_unit *io = log->current_io;
 
 	if (io->need_split_bio) {
-		struct bio *prev = io->current_bio;
-
+		BUG_ON(io->split_bio);
+		io->split_bio = io->current_bio;
 		io->current_bio = r5l_bio_alloc(log);
-		bio_chain(io->current_bio, prev);
-
-		submit_bio(prev);
+		bio_chain(io->current_bio, io->split_bio);
+		io->need_split_bio = false;
 	}
 
 	if (!bio_add_page(io->current_bio, page, PAGE_SIZE, 0))
@@ -401,50 +806,85 @@ static int r5l_log_stripe(struct r5l_log
 
 	io = log->current_io;
 
+	if (test_and_clear_bit(STRIPE_R5C_PREFLUSH, &sh->state))
+		io->has_flush = 1;
+
 	for (i = 0; i < sh->disks; i++) {
-		if (!test_bit(R5_Wantwrite, &sh->dev[i].flags))
+		if (!test_bit(R5_Wantwrite, &sh->dev[i].flags) ||
+		    test_bit(R5_InJournal, &sh->dev[i].flags))
 			continue;
 		if (i == sh->pd_idx || i == sh->qd_idx)
 			continue;
+		if (test_bit(R5_WantFUA, &sh->dev[i].flags) &&
+		    log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK) {
+			io->has_fua = 1;
+			/*
+			 * we need to flush journal to make sure recovery can
+			 * reach the data with fua flag
+			 */
+			io->has_flush = 1;
+		}
 		r5l_append_payload_meta(log, R5LOG_PAYLOAD_DATA,
 					raid5_compute_blocknr(sh, i, 0),
 					sh->dev[i].log_checksum, 0, false);
 		r5l_append_payload_page(log, sh->dev[i].page);
 	}
 
-	if (sh->qd_idx >= 0) {
+	if (parity_pages == 2) {
 		r5l_append_payload_meta(log, R5LOG_PAYLOAD_PARITY,
 					sh->sector, sh->dev[sh->pd_idx].log_checksum,
 					sh->dev[sh->qd_idx].log_checksum, true);
 		r5l_append_payload_page(log, sh->dev[sh->pd_idx].page);
 		r5l_append_payload_page(log, sh->dev[sh->qd_idx].page);
-	} else {
+	} else if (parity_pages == 1) {
 		r5l_append_payload_meta(log, R5LOG_PAYLOAD_PARITY,
 					sh->sector, sh->dev[sh->pd_idx].log_checksum,
 					0, false);
 		r5l_append_payload_page(log, sh->dev[sh->pd_idx].page);
-	}
+	} else  /* Just writing data, not parity, in caching phase */
+		BUG_ON(parity_pages != 0);
 
 	list_add_tail(&sh->log_list, &io->stripe_list);
 	atomic_inc(&io->pending_stripe);
 	sh->log_io = io;
 
+	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH)
+		return 0;
+
+	if (sh->log_start == MaxSector) {
+		BUG_ON(!list_empty(&sh->r5c));
+		sh->log_start = io->log_start;
+		spin_lock_irq(&log->stripe_in_journal_lock);
+		list_add_tail(&sh->r5c,
+			      &log->stripe_in_journal_list);
+		spin_unlock_irq(&log->stripe_in_journal_lock);
+		atomic_inc(&log->stripe_in_journal_count);
+	}
 	return 0;
 }
 
-static void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
+/* add stripe to no_space_stripes, and then wake up reclaim */
+static inline void r5l_add_no_space_stripe(struct r5l_log *log,
+					   struct stripe_head *sh)
+{
+	spin_lock(&log->no_space_stripes_lock);
+	list_add_tail(&sh->log_list, &log->no_space_stripes);
+	spin_unlock(&log->no_space_stripes_lock);
+}
+
 /*
  * running in raid5d, where reclaim could wait for raid5d too (when it flushes
  * data from log to raid disks), so we shouldn't wait for reclaim here
  */
 int r5l_write_stripe(struct r5l_log *log, struct stripe_head *sh)
 {
+	struct r5conf *conf = sh->raid_conf;
 	int write_disks = 0;
 	int data_pages, parity_pages;
-	int meta_size;
 	int reserve;
 	int i;
 	int ret = 0;
+	bool wake_reclaim = false;
 
 	if (!log)
 		return -EAGAIN;
@@ -456,11 +896,15 @@ int r5l_write_stripe(struct r5l_log *log
 		return -EAGAIN;
 	}
 
+	WARN_ON(test_bit(STRIPE_R5C_CACHING, &sh->state));
+
 	for (i = 0; i < sh->disks; i++) {
 		void *addr;
 
-		if (!test_bit(R5_Wantwrite, &sh->dev[i].flags))
+		if (!test_bit(R5_Wantwrite, &sh->dev[i].flags) ||
+		    test_bit(R5_InJournal, &sh->dev[i].flags))
 			continue;
+
 		write_disks++;
 		/* checksum is already calculated in last run */
 		if (test_bit(STRIPE_LOG_TRAPPED, &sh->state))
@@ -473,15 +917,6 @@ int r5l_write_stripe(struct r5l_log *log
 	parity_pages = 1 + !!(sh->qd_idx >= 0);
 	data_pages = write_disks - parity_pages;
 
-	meta_size =
-		((sizeof(struct r5l_payload_data_parity) + sizeof(__le32))
-		 * data_pages) +
-		sizeof(struct r5l_payload_data_parity) +
-		sizeof(__le32) * parity_pages;
-	/* Doesn't work with very big raid array */
-	if (meta_size + sizeof(struct r5l_meta_block) > PAGE_SIZE)
-		return -EINVAL;
-
 	set_bit(STRIPE_LOG_TRAPPED, &sh->state);
 	/*
 	 * The stripe must enter state machine again to finish the write, so
@@ -493,22 +928,49 @@ int r5l_write_stripe(struct r5l_log *log
 	mutex_lock(&log->io_mutex);
 	/* meta + data */
 	reserve = (1 + write_disks) << (PAGE_SHIFT - 9);
-	if (!r5l_has_free_space(log, reserve)) {
-		spin_lock(&log->no_space_stripes_lock);
-		list_add_tail(&sh->log_list, &log->no_space_stripes);
-		spin_unlock(&log->no_space_stripes_lock);
 
-		r5l_wake_reclaim(log, reserve);
-	} else {
-		ret = r5l_log_stripe(log, sh, data_pages, parity_pages);
-		if (ret) {
-			spin_lock_irq(&log->io_list_lock);
-			list_add_tail(&sh->log_list, &log->no_mem_stripes);
-			spin_unlock_irq(&log->io_list_lock);
+	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
+		if (!r5l_has_free_space(log, reserve)) {
+			r5l_add_no_space_stripe(log, sh);
+			wake_reclaim = true;
+		} else {
+			ret = r5l_log_stripe(log, sh, data_pages, parity_pages);
+			if (ret) {
+				spin_lock_irq(&log->io_list_lock);
+				list_add_tail(&sh->log_list,
+					      &log->no_mem_stripes);
+				spin_unlock_irq(&log->io_list_lock);
+			}
+		}
+	} else {  /* R5C_JOURNAL_MODE_WRITE_BACK */
+		/*
+		 * log space critical, do not process stripes that are
+		 * not in cache yet (sh->log_start == MaxSector).
+		 */
+		if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) &&
+		    sh->log_start == MaxSector) {
+			r5l_add_no_space_stripe(log, sh);
+			wake_reclaim = true;
+			reserve = 0;
+		} else if (!r5l_has_free_space(log, reserve)) {
+			if (sh->log_start == log->last_checkpoint)
+				BUG();
+			else
+				r5l_add_no_space_stripe(log, sh);
+		} else {
+			ret = r5l_log_stripe(log, sh, data_pages, parity_pages);
+			if (ret) {
+				spin_lock_irq(&log->io_list_lock);
+				list_add_tail(&sh->log_list,
+					      &log->no_mem_stripes);
+				spin_unlock_irq(&log->io_list_lock);
+			}
 		}
 	}
 
 	mutex_unlock(&log->io_mutex);
+	if (wake_reclaim)
+		r5l_wake_reclaim(log, reserve);
 	return 0;
 }
 
@@ -525,17 +987,34 @@ int r5l_handle_flush_request(struct r5l_
 {
 	if (!log)
 		return -ENODEV;
-	/*
-	 * we flush log disk cache first, then write stripe data to raid disks.
-	 * So if bio is finished, the log disk cache is flushed already. The
-	 * recovery guarantees we can recovery the bio from log disk, so we
-	 * don't need to flush again
-	 */
-	if (bio->bi_iter.bi_size == 0) {
-		bio_endio(bio);
-		return 0;
+
+	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH) {
+		/*
+		 * in write through (journal only)
+		 * we flush log disk cache first, then write stripe data to
+		 * raid disks. So if bio is finished, the log disk cache is
+		 * flushed already. The recovery guarantees we can recovery
+		 * the bio from log disk, so we don't need to flush again
+		 */
+		if (bio->bi_iter.bi_size == 0) {
+			bio_endio(bio);
+			return 0;
+		}
+		bio->bi_opf &= ~REQ_PREFLUSH;
+	} else {
+		/* write back (with cache) */
+		if (bio->bi_iter.bi_size == 0) {
+			mutex_lock(&log->io_mutex);
+			r5l_get_meta(log, 0);
+			bio_list_add(&log->current_io->flush_barriers, bio);
+			log->current_io->has_flush = 1;
+			log->current_io->has_null_flush = 1;
+			atomic_inc(&log->current_io->pending_stripe);
+			r5l_submit_current_io(log);
+			mutex_unlock(&log->io_mutex);
+			return 0;
+		}
 	}
-	bio->bi_opf &= ~REQ_PREFLUSH;
 	return -EAGAIN;
 }
 
@@ -555,10 +1034,40 @@ static void r5l_run_no_space_stripes(str
 	spin_unlock(&log->no_space_stripes_lock);
 }
 
+/*
+ * calculate new last_checkpoint
+ * for write through mode, returns log->next_checkpoint
+ * for write back, returns log_start of first sh in stripe_in_journal_list
+ */
+static sector_t r5c_calculate_new_cp(struct r5conf *conf)
+{
+	struct stripe_head *sh;
+	struct r5l_log *log = conf->log;
+	sector_t new_cp;
+	unsigned long flags;
+
+	if (log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH)
+		return log->next_checkpoint;
+
+	spin_lock_irqsave(&log->stripe_in_journal_lock, flags);
+	if (list_empty(&conf->log->stripe_in_journal_list)) {
+		/* all stripes flushed */
+		spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
+		return log->next_checkpoint;
+	}
+	sh = list_first_entry(&conf->log->stripe_in_journal_list,
+			      struct stripe_head, r5c);
+	new_cp = sh->log_start;
+	spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
+	return new_cp;
+}
+
 static sector_t r5l_reclaimable_space(struct r5l_log *log)
 {
+	struct r5conf *conf = log->rdev->mddev->private;
+
 	return r5l_ring_distance(log, log->last_checkpoint,
-				 log->next_checkpoint);
+				 r5c_calculate_new_cp(conf));
 }
 
 static void r5l_run_no_mem_stripe(struct r5l_log *log)
@@ -589,7 +1098,6 @@ static bool r5l_complete_finished_ios(st
 			break;
 
 		log->next_checkpoint = io->log_start;
-		log->next_cp_seq = io->seq;
 
 		list_del(&io->log_sibling);
 		mempool_free(io, log->io_pool);
@@ -604,6 +1112,7 @@ static bool r5l_complete_finished_ios(st
 static void __r5l_stripe_write_finished(struct r5l_io_unit *io)
 {
 	struct r5l_log *log = io->log;
+	struct r5conf *conf = log->rdev->mddev->private;
 	unsigned long flags;
 
 	spin_lock_irqsave(&log->io_list_lock, flags);
@@ -614,7 +1123,8 @@ static void __r5l_stripe_write_finished(
 		return;
 	}
 
-	if (r5l_reclaimable_space(log) > log->max_free_space)
+	if (r5l_reclaimable_space(log) > log->max_free_space ||
+	    test_bit(R5C_LOG_TIGHT, &conf->cache_state))
 		r5l_wake_reclaim(log, 0);
 
 	spin_unlock_irqrestore(&log->io_list_lock, flags);
@@ -685,7 +1195,7 @@ void r5l_flush_stripe_to_raid(struct r5l
 	bio_reset(&log->flush_bio);
 	log->flush_bio.bi_bdev = log->rdev->bdev;
 	log->flush_bio.bi_end_io = r5l_log_flush_endio;
-	bio_set_op_attrs(&log->flush_bio, REQ_OP_WRITE, WRITE_FLUSH);
+	log->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 	submit_bio(&log->flush_bio);
 }
 
@@ -713,8 +1223,8 @@ static void r5l_write_super_and_discard_
 	 * there is a deadlock. We workaround this issue with a trylock.
 	 * FIXME: we could miss discard if we can't take reconfig mutex
 	 */
-	set_mask_bits(&mddev->flags, 0,
-		BIT(MD_CHANGE_DEVS) | BIT(MD_CHANGE_PENDING));
+	set_mask_bits(&mddev->sb_flags, 0,
+		BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
 	if (!mddev_trylock(mddev))
 		return;
 	md_update_sb(mddev, 1);
@@ -735,15 +1245,148 @@ static void r5l_write_super_and_discard_
 	}
 }
 
+/*
+ * r5c_flush_stripe moves stripe from cached list to handle_list. When called,
+ * the stripe must be on r5c_cached_full_stripes or r5c_cached_partial_stripes.
+ *
+ * must hold conf->device_lock
+ */
+static void r5c_flush_stripe(struct r5conf *conf, struct stripe_head *sh)
+{
+	BUG_ON(list_empty(&sh->lru));
+	BUG_ON(!test_bit(STRIPE_R5C_CACHING, &sh->state));
+	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
+
+	/*
+	 * The stripe is not ON_RELEASE_LIST, so it is safe to call
+	 * raid5_release_stripe() while holding conf->device_lock
+	 */
+	BUG_ON(test_bit(STRIPE_ON_RELEASE_LIST, &sh->state));
+	assert_spin_locked(&conf->device_lock);
+
+	list_del_init(&sh->lru);
+	atomic_inc(&sh->count);
+
+	set_bit(STRIPE_HANDLE, &sh->state);
+	atomic_inc(&conf->active_stripes);
+	r5c_make_stripe_write_out(sh);
+
+	raid5_release_stripe(sh);
+}
+
+/*
+ * if num == 0, flush all full stripes
+ * if num > 0, flush all full stripes. If less than num full stripes are
+ *             flushed, flush some partial stripes until totally num stripes are
+ *             flushed or there is no more cached stripes.
+ */
+void r5c_flush_cache(struct r5conf *conf, int num)
+{
+	int count;
+	struct stripe_head *sh, *next;
+
+	assert_spin_locked(&conf->device_lock);
+	if (!conf->log)
+		return;
+
+	count = 0;
+	list_for_each_entry_safe(sh, next, &conf->r5c_full_stripe_list, lru) {
+		r5c_flush_stripe(conf, sh);
+		count++;
+	}
+
+	if (count >= num)
+		return;
+	list_for_each_entry_safe(sh, next,
+				 &conf->r5c_partial_stripe_list, lru) {
+		r5c_flush_stripe(conf, sh);
+		if (++count >= num)
+			break;
+	}
+}
+
+static void r5c_do_reclaim(struct r5conf *conf)
+{
+	struct r5l_log *log = conf->log;
+	struct stripe_head *sh;
+	int count = 0;
+	unsigned long flags;
+	int total_cached;
+	int stripes_to_flush;
+
+	if (!r5c_is_writeback(log))
+		return;
+
+	total_cached = atomic_read(&conf->r5c_cached_partial_stripes) +
+		atomic_read(&conf->r5c_cached_full_stripes);
+
+	if (total_cached > conf->min_nr_stripes * 3 / 4 ||
+	    atomic_read(&conf->empty_inactive_list_nr) > 0)
+		/*
+		 * if stripe cache pressure high, flush all full stripes and
+		 * some partial stripes
+		 */
+		stripes_to_flush = R5C_RECLAIM_STRIPE_GROUP;
+	else if (total_cached > conf->min_nr_stripes * 1 / 2 ||
+		 atomic_read(&conf->r5c_cached_full_stripes) >
+		 R5C_FULL_STRIPE_FLUSH_BATCH)
+		/*
+		 * if stripe cache pressure moderate, or if there is many full
+		 * stripes,flush all full stripes
+		 */
+		stripes_to_flush = 0;
+	else
+		/* no need to flush */
+		stripes_to_flush = -1;
+
+	if (stripes_to_flush >= 0) {
+		spin_lock_irqsave(&conf->device_lock, flags);
+		r5c_flush_cache(conf, stripes_to_flush);
+		spin_unlock_irqrestore(&conf->device_lock, flags);
+	}
+
+	/* if log space is tight, flush stripes on stripe_in_journal_list */
+	if (test_bit(R5C_LOG_TIGHT, &conf->cache_state)) {
+		spin_lock_irqsave(&log->stripe_in_journal_lock, flags);
+		spin_lock(&conf->device_lock);
+		list_for_each_entry(sh, &log->stripe_in_journal_list, r5c) {
+			/*
+			 * stripes on stripe_in_journal_list could be in any
+			 * state of the stripe_cache state machine. In this
+			 * case, we only want to flush stripe on
+			 * r5c_cached_full/partial_stripes. The following
+			 * condition makes sure the stripe is on one of the
+			 * two lists.
+			 */
+			if (!list_empty(&sh->lru) &&
+			    !test_bit(STRIPE_HANDLE, &sh->state) &&
+			    atomic_read(&sh->count) == 0) {
+				r5c_flush_stripe(conf, sh);
+			}
+			if (count++ >= R5C_RECLAIM_STRIPE_GROUP)
+				break;
+		}
+		spin_unlock(&conf->device_lock);
+		spin_unlock_irqrestore(&log->stripe_in_journal_lock, flags);
+	}
+
+	if (!test_bit(R5C_LOG_CRITICAL, &conf->cache_state))
+		r5l_run_no_space_stripes(log);
+
+	md_wakeup_thread(conf->mddev->thread);
+}
 
 static void r5l_do_reclaim(struct r5l_log *log)
 {
+	struct r5conf *conf = log->rdev->mddev->private;
 	sector_t reclaim_target = xchg(&log->reclaim_target, 0);
 	sector_t reclaimable;
 	sector_t next_checkpoint;
-	u64 next_cp_seq;
+	bool write_super;
 
 	spin_lock_irq(&log->io_list_lock);
+	write_super = r5l_reclaimable_space(log) > log->max_free_space ||
+		reclaim_target != 0 || !list_empty(&log->no_space_stripes);
 	/*
 	 * move proper io_unit to reclaim list. We should not change the order.
 	 * reclaimable/unreclaimable io_unit can be mixed in the list, we
@@ -764,12 +1407,10 @@ static void r5l_do_reclaim(struct r5l_lo
 				    log->io_list_lock);
 	}
 
-	next_checkpoint = log->next_checkpoint;
-	next_cp_seq = log->next_cp_seq;
+	next_checkpoint = r5c_calculate_new_cp(conf);
 	spin_unlock_irq(&log->io_list_lock);
 
-	BUG_ON(reclaimable < 0);
-	if (reclaimable == 0)
+	if (reclaimable == 0 || !write_super)
 		return;
 
 	/*
@@ -781,7 +1422,7 @@ static void r5l_do_reclaim(struct r5l_lo
 
 	mutex_lock(&log->io_mutex);
 	log->last_checkpoint = next_checkpoint;
-	log->last_cp_seq = next_cp_seq;
+	r5c_update_log_state(log);
 	mutex_unlock(&log->io_mutex);
 
 	r5l_run_no_space_stripes(log);
@@ -795,14 +1436,17 @@ static void r5l_reclaim_thread(struct md
 
 	if (!log)
 		return;
+	r5c_do_reclaim(conf);
 	r5l_do_reclaim(log);
 }
 
-static void r5l_wake_reclaim(struct r5l_log *log, sector_t space)
+void r5l_wake_reclaim(struct r5l_log *log, sector_t space)
 {
 	unsigned long target;
 	unsigned long new = (unsigned long)space; /* overflow in theory */
 
+	if (!log)
+		return;
 	do {
 		target = log->reclaim_target;
 		if (new < target)
@@ -816,22 +1460,14 @@ void r5l_quiesce(struct r5l_log *log, in
 	struct mddev *mddev;
 	if (!log || state == 2)
 		return;
-	if (state == 0) {
-		/*
-		 * This is a special case for hotadd. In suspend, the array has
-		 * no journal. In resume, journal is initialized as well as the
-		 * reclaim thread.
-		 */
-		if (log->reclaim_thread)
-			return;
-		log->reclaim_thread = md_register_thread(r5l_reclaim_thread,
-					log->rdev->mddev, "reclaim");
-	} else if (state == 1) {
+	if (state == 0)
+		kthread_unpark(log->reclaim_thread->tsk);
+	else if (state == 1) {
 		/* make sure r5l_write_super_and_discard_space exits */
 		mddev = log->rdev->mddev;
 		wake_up(&mddev->sb_wait);
-		r5l_wake_reclaim(log, -1L);
-		md_unregister_thread(&log->reclaim_thread);
+		kthread_park(log->reclaim_thread->tsk);
+		r5l_wake_reclaim(log, MaxSector);
 		r5l_do_reclaim(log);
 	}
 }
@@ -857,10 +1493,13 @@ struct r5l_recovery_ctx {
 	sector_t meta_total_blocks;	/* total size of current meta and data */
 	sector_t pos;			/* recovery position */
 	u64 seq;			/* recovery position seq */
+	int data_parity_stripes;	/* number of data_parity stripes */
+	int data_only_stripes;		/* number of data_only stripes */
+	struct list_head cached_list;
 };
 
-static int r5l_read_meta_block(struct r5l_log *log,
-			       struct r5l_recovery_ctx *ctx)
+static int r5l_recovery_read_meta_block(struct r5l_log *log,
+					struct r5l_recovery_ctx *ctx)
 {
 	struct page *page = ctx->meta_page;
 	struct r5l_meta_block *mb;
@@ -892,216 +1531,700 @@ static int r5l_read_meta_block(struct r5
 	return 0;
 }
 
-static int r5l_recovery_flush_one_stripe(struct r5l_log *log,
-					 struct r5l_recovery_ctx *ctx,
-					 sector_t stripe_sect,
-					 int *offset, sector_t *log_offset)
+static void
+r5l_recovery_create_empty_meta_block(struct r5l_log *log,
+				     struct page *page,
+				     sector_t pos, u64 seq)
 {
-	struct r5conf *conf = log->rdev->mddev->private;
-	struct stripe_head *sh;
-	struct r5l_payload_data_parity *payload;
-	int disk_index;
+	struct r5l_meta_block *mb;
 
-	sh = raid5_get_active_stripe(conf, stripe_sect, 0, 0, 0);
-	while (1) {
-		payload = page_address(ctx->meta_page) + *offset;
+	mb = page_address(page);
+	clear_page(mb);
+	mb->magic = cpu_to_le32(R5LOG_MAGIC);
+	mb->version = R5LOG_VERSION;
+	mb->meta_size = cpu_to_le32(sizeof(struct r5l_meta_block));
+	mb->seq = cpu_to_le64(seq);
+	mb->position = cpu_to_le64(pos);
+}
 
-		if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_DATA) {
-			raid5_compute_sector(conf,
-					     le64_to_cpu(payload->location), 0,
-					     &disk_index, sh);
+static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos,
+					  u64 seq)
+{
+	struct page *page;
+	struct r5l_meta_block *mb;
 
-			sync_page_io(log->rdev, *log_offset, PAGE_SIZE,
-				     sh->dev[disk_index].page, REQ_OP_READ, 0,
-				     false);
-			sh->dev[disk_index].log_checksum =
-				le32_to_cpu(payload->checksum[0]);
-			set_bit(R5_Wantwrite, &sh->dev[disk_index].flags);
-			ctx->meta_total_blocks += BLOCK_SECTORS;
-		} else {
-			disk_index = sh->pd_idx;
-			sync_page_io(log->rdev, *log_offset, PAGE_SIZE,
-				     sh->dev[disk_index].page, REQ_OP_READ, 0,
-				     false);
-			sh->dev[disk_index].log_checksum =
-				le32_to_cpu(payload->checksum[0]);
-			set_bit(R5_Wantwrite, &sh->dev[disk_index].flags);
+	page = alloc_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	r5l_recovery_create_empty_meta_block(log, page, pos, seq);
+	mb = page_address(page);
+	mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum,
+					     mb, PAGE_SIZE));
+	if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE,
+			  REQ_FUA, false)) {
+		__free_page(page);
+		return -EIO;
+	}
+	__free_page(page);
+	return 0;
+}
 
-			if (sh->qd_idx >= 0) {
-				disk_index = sh->qd_idx;
-				sync_page_io(log->rdev,
-					     r5l_ring_add(log, *log_offset, BLOCK_SECTORS),
-					     PAGE_SIZE, sh->dev[disk_index].page,
-					     REQ_OP_READ, 0, false);
-				sh->dev[disk_index].log_checksum =
-					le32_to_cpu(payload->checksum[1]);
-				set_bit(R5_Wantwrite,
-					&sh->dev[disk_index].flags);
-			}
-			ctx->meta_total_blocks += BLOCK_SECTORS * conf->max_degraded;
-		}
+/*
+ * r5l_recovery_load_data and r5l_recovery_load_parity uses flag R5_Wantwrite
+ * to mark valid (potentially not flushed) data in the journal.
+ *
+ * We already verified checksum in r5l_recovery_verify_data_checksum_for_mb,
+ * so there should not be any mismatch here.
+ */
+static void r5l_recovery_load_data(struct r5l_log *log,
+				   struct stripe_head *sh,
+				   struct r5l_recovery_ctx *ctx,
+				   struct r5l_payload_data_parity *payload,
+				   sector_t log_offset)
+{
+	struct mddev *mddev = log->rdev->mddev;
+	struct r5conf *conf = mddev->private;
+	int dd_idx;
 
-		*log_offset = r5l_ring_add(log, *log_offset,
-					   le32_to_cpu(payload->size));
-		*offset += sizeof(struct r5l_payload_data_parity) +
-			sizeof(__le32) *
-			(le32_to_cpu(payload->size) >> (PAGE_SHIFT - 9));
-		if (le16_to_cpu(payload->header.type) == R5LOG_PAYLOAD_PARITY)
-			break;
+	raid5_compute_sector(conf,
+			     le64_to_cpu(payload->location), 0,
+			     &dd_idx, sh);
+	sync_page_io(log->rdev, log_offset, PAGE_SIZE,
+		     sh->dev[dd_idx].page, REQ_OP_READ, 0, false);
+	sh->dev[dd_idx].log_checksum =
+		le32_to_cpu(payload->checksum[0]);
+	ctx->meta_total_blocks += BLOCK_SECTORS;
+
+	set_bit(R5_Wantwrite, &sh->dev[dd_idx].flags);
+	set_bit(STRIPE_R5C_CACHING, &sh->state);
+}
+
+static void r5l_recovery_load_parity(struct r5l_log *log,
+				     struct stripe_head *sh,
+				     struct r5l_recovery_ctx *ctx,
+				     struct r5l_payload_data_parity *payload,
+				     sector_t log_offset)
+{
+	struct mddev *mddev = log->rdev->mddev;
+	struct r5conf *conf = mddev->private;
+
+	ctx->meta_total_blocks += BLOCK_SECTORS * conf->max_degraded;
+	sync_page_io(log->rdev, log_offset, PAGE_SIZE,
+		     sh->dev[sh->pd_idx].page, REQ_OP_READ, 0, false);
+	sh->dev[sh->pd_idx].log_checksum =
+		le32_to_cpu(payload->checksum[0]);
+	set_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags);
+
+	if (sh->qd_idx >= 0) {
+		sync_page_io(log->rdev,
+			     r5l_ring_add(log, log_offset, BLOCK_SECTORS),
+			     PAGE_SIZE, sh->dev[sh->qd_idx].page,
+			     REQ_OP_READ, 0, false);
+		sh->dev[sh->qd_idx].log_checksum =
+			le32_to_cpu(payload->checksum[1]);
+		set_bit(R5_Wantwrite, &sh->dev[sh->qd_idx].flags);
 	}
+	clear_bit(STRIPE_R5C_CACHING, &sh->state);
+}
 
-	for (disk_index = 0; disk_index < sh->disks; disk_index++) {
-		void *addr;
-		u32 checksum;
+static void r5l_recovery_reset_stripe(struct stripe_head *sh)
+{
+	int i;
 
+	sh->state = 0;
+	sh->log_start = MaxSector;
+	for (i = sh->disks; i--; )
+		sh->dev[i].flags = 0;
+}
+
+static void
+r5l_recovery_replay_one_stripe(struct r5conf *conf,
+			       struct stripe_head *sh,
+			       struct r5l_recovery_ctx *ctx)
+{
+	struct md_rdev *rdev, *rrdev;
+	int disk_index;
+	int data_count = 0;
+
+	for (disk_index = 0; disk_index < sh->disks; disk_index++) {
 		if (!test_bit(R5_Wantwrite, &sh->dev[disk_index].flags))
 			continue;
-		addr = kmap_atomic(sh->dev[disk_index].page);
-		checksum = crc32c_le(log->uuid_checksum, addr, PAGE_SIZE);
-		kunmap_atomic(addr);
-		if (checksum != sh->dev[disk_index].log_checksum)
-			goto error;
+		if (disk_index == sh->qd_idx || disk_index == sh->pd_idx)
+			continue;
+		data_count++;
 	}
 
-	for (disk_index = 0; disk_index < sh->disks; disk_index++) {
-		struct md_rdev *rdev, *rrdev;
+	/*
+	 * stripes that only have parity must have been flushed
+	 * before the crash that we are now recovering from, so
+	 * there is nothing more to recovery.
+	 */
+	if (data_count == 0)
+		goto out;
 
-		if (!test_and_clear_bit(R5_Wantwrite,
-					&sh->dev[disk_index].flags))
+	for (disk_index = 0; disk_index < sh->disks; disk_index++) {
+		if (!test_bit(R5_Wantwrite, &sh->dev[disk_index].flags))
 			continue;
 
 		/* in case device is broken */
+		rcu_read_lock();
 		rdev = rcu_dereference(conf->disks[disk_index].rdev);
-		if (rdev)
-			sync_page_io(rdev, stripe_sect, PAGE_SIZE,
+		if (rdev) {
+			atomic_inc(&rdev->nr_pending);
+			rcu_read_unlock();
+			sync_page_io(rdev, sh->sector, PAGE_SIZE,
 				     sh->dev[disk_index].page, REQ_OP_WRITE, 0,
 				     false);
+			rdev_dec_pending(rdev, rdev->mddev);
+			rcu_read_lock();
+		}
 		rrdev = rcu_dereference(conf->disks[disk_index].replacement);
-		if (rrdev)
-			sync_page_io(rrdev, stripe_sect, PAGE_SIZE,
+		if (rrdev) {
+			atomic_inc(&rrdev->nr_pending);
+			rcu_read_unlock();
+			sync_page_io(rrdev, sh->sector, PAGE_SIZE,
 				     sh->dev[disk_index].page, REQ_OP_WRITE, 0,
 				     false);
+			rdev_dec_pending(rrdev, rrdev->mddev);
+			rcu_read_lock();
+		}
+		rcu_read_unlock();
 	}
-	raid5_release_stripe(sh);
+	ctx->data_parity_stripes++;
+out:
+	r5l_recovery_reset_stripe(sh);
+}
+
+static struct stripe_head *
+r5c_recovery_alloc_stripe(struct r5conf *conf,
+			  sector_t stripe_sect)
+{
+	struct stripe_head *sh;
+
+	sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
+	if (!sh)
+		return NULL;  /* no more stripe available */
+
+	r5l_recovery_reset_stripe(sh);
+
+	return sh;
+}
+
+static struct stripe_head *
+r5c_recovery_lookup_stripe(struct list_head *list, sector_t sect)
+{
+	struct stripe_head *sh;
+
+	list_for_each_entry(sh, list, lru)
+		if (sh->sector == sect)
+			return sh;
+	return NULL;
+}
+
+static void
+r5c_recovery_drop_stripes(struct list_head *cached_stripe_list,
+			  struct r5l_recovery_ctx *ctx)
+{
+	struct stripe_head *sh, *next;
+
+	list_for_each_entry_safe(sh, next, cached_stripe_list, lru) {
+		r5l_recovery_reset_stripe(sh);
+		list_del_init(&sh->lru);
+		raid5_release_stripe(sh);
+	}
+}
+
+static void
+r5c_recovery_replay_stripes(struct list_head *cached_stripe_list,
+			    struct r5l_recovery_ctx *ctx)
+{
+	struct stripe_head *sh, *next;
+
+	list_for_each_entry_safe(sh, next, cached_stripe_list, lru)
+		if (!test_bit(STRIPE_R5C_CACHING, &sh->state)) {
+			r5l_recovery_replay_one_stripe(sh->raid_conf, sh, ctx);
+			list_del_init(&sh->lru);
+			raid5_release_stripe(sh);
+		}
+}
+
+/* if matches return 0; otherwise return -EINVAL */
+static int
+r5l_recovery_verify_data_checksum(struct r5l_log *log, struct page *page,
+				  sector_t log_offset, __le32 log_checksum)
+{
+	void *addr;
+	u32 checksum;
+
+	sync_page_io(log->rdev, log_offset, PAGE_SIZE,
+		     page, REQ_OP_READ, 0, false);
+	addr = kmap_atomic(page);
+	checksum = crc32c_le(log->uuid_checksum, addr, PAGE_SIZE);
+	kunmap_atomic(addr);
+	return (le32_to_cpu(log_checksum) == checksum) ? 0 : -EINVAL;
+}
+
+/*
+ * before loading data to stripe cache, we need verify checksum for all data,
+ * if there is mismatch for any data page, we drop all data in the mata block
+ */
+static int
+r5l_recovery_verify_data_checksum_for_mb(struct r5l_log *log,
+					 struct r5l_recovery_ctx *ctx)
+{
+	struct mddev *mddev = log->rdev->mddev;
+	struct r5conf *conf = mddev->private;
+	struct r5l_meta_block *mb = page_address(ctx->meta_page);
+	sector_t mb_offset = sizeof(struct r5l_meta_block);
+	sector_t log_offset = r5l_ring_add(log, ctx->pos, BLOCK_SECTORS);
+	struct page *page;
+	struct r5l_payload_data_parity *payload;
+
+	page = alloc_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	while (mb_offset < le32_to_cpu(mb->meta_size)) {
+		payload = (void *)mb + mb_offset;
+
+		if (payload->header.type == R5LOG_PAYLOAD_DATA) {
+			if (r5l_recovery_verify_data_checksum(
+				    log, page, log_offset,
+				    payload->checksum[0]) < 0)
+				goto mismatch;
+		} else if (payload->header.type == R5LOG_PAYLOAD_PARITY) {
+			if (r5l_recovery_verify_data_checksum(
+				    log, page, log_offset,
+				    payload->checksum[0]) < 0)
+				goto mismatch;
+			if (conf->max_degraded == 2 && /* q for RAID 6 */
+			    r5l_recovery_verify_data_checksum(
+				    log, page,
+				    r5l_ring_add(log, log_offset,
+						 BLOCK_SECTORS),
+				    payload->checksum[1]) < 0)
+				goto mismatch;
+		} else /* not R5LOG_PAYLOAD_DATA or R5LOG_PAYLOAD_PARITY */
+			goto mismatch;
+
+		log_offset = r5l_ring_add(log, log_offset,
+					  le32_to_cpu(payload->size));
+
+		mb_offset += sizeof(struct r5l_payload_data_parity) +
+			sizeof(__le32) *
+			(le32_to_cpu(payload->size) >> (PAGE_SHIFT - 9));
+	}
+
+	put_page(page);
 	return 0;
 
-error:
-	for (disk_index = 0; disk_index < sh->disks; disk_index++)
-		sh->dev[disk_index].flags = 0;
-	raid5_release_stripe(sh);
+mismatch:
+	put_page(page);
 	return -EINVAL;
 }
 
-static int r5l_recovery_flush_one_meta(struct r5l_log *log,
-				       struct r5l_recovery_ctx *ctx)
+/*
+ * Analyze all data/parity pages in one meta block
+ * Returns:
+ * 0 for success
+ * -EINVAL for unknown playload type
+ * -EAGAIN for checksum mismatch of data page
+ * -ENOMEM for run out of memory (alloc_page failed or run out of stripes)
+ */
+static int
+r5c_recovery_analyze_meta_block(struct r5l_log *log,
+				struct r5l_recovery_ctx *ctx,
+				struct list_head *cached_stripe_list)
 {
-	struct r5conf *conf = log->rdev->mddev->private;
-	struct r5l_payload_data_parity *payload;
+	struct mddev *mddev = log->rdev->mddev;
+	struct r5conf *conf = mddev->private;
 	struct r5l_meta_block *mb;
-	int offset;
+	struct r5l_payload_data_parity *payload;
+	int mb_offset;
 	sector_t log_offset;
-	sector_t stripe_sector;
+	sector_t stripe_sect;
+	struct stripe_head *sh;
+	int ret;
+
+	/*
+	 * for mismatch in data blocks, we will drop all data in this mb, but
+	 * we will still read next mb for other data with FLUSH flag, as
+	 * io_unit could finish out of order.
+	 */
+	ret = r5l_recovery_verify_data_checksum_for_mb(log, ctx);
+	if (ret == -EINVAL)
+		return -EAGAIN;
+	else if (ret)
+		return ret;   /* -ENOMEM duo to alloc_page() failed */
 
 	mb = page_address(ctx->meta_page);
-	offset = sizeof(struct r5l_meta_block);
+	mb_offset = sizeof(struct r5l_meta_block);
 	log_offset = r5l_ring_add(log, ctx->pos, BLOCK_SECTORS);
 
-	while (offset < le32_to_cpu(mb->meta_size)) {
+	while (mb_offset < le32_to_cpu(mb->meta_size)) {
 		int dd;
 
-		payload = (void *)mb + offset;
-		stripe_sector = raid5_compute_sector(conf,
-						     le64_to_cpu(payload->location), 0, &dd, NULL);
-		if (r5l_recovery_flush_one_stripe(log, ctx, stripe_sector,
-						  &offset, &log_offset))
+		payload = (void *)mb + mb_offset;
+		stripe_sect = (payload->header.type == R5LOG_PAYLOAD_DATA) ?
+			raid5_compute_sector(
+				conf, le64_to_cpu(payload->location), 0, &dd,
+				NULL)
+			: le64_to_cpu(payload->location);
+
+		sh = r5c_recovery_lookup_stripe(cached_stripe_list,
+						stripe_sect);
+
+		if (!sh) {
+			sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
+			/*
+			 * cannot get stripe from raid5_get_active_stripe
+			 * try replay some stripes
+			 */
+			if (!sh) {
+				r5c_recovery_replay_stripes(
+					cached_stripe_list, ctx);
+				sh = r5c_recovery_alloc_stripe(
+					conf, stripe_sect);
+			}
+			if (!sh) {
+				pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
+					mdname(mddev),
+					conf->min_nr_stripes * 2);
+				raid5_set_cache_size(mddev,
+						     conf->min_nr_stripes * 2);
+				sh = r5c_recovery_alloc_stripe(conf,
+							       stripe_sect);
+			}
+			if (!sh) {
+				pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
+				       mdname(mddev));
+				return -ENOMEM;
+			}
+			list_add_tail(&sh->lru, cached_stripe_list);
+		}
+
+		if (payload->header.type == R5LOG_PAYLOAD_DATA) {
+			if (!test_bit(STRIPE_R5C_CACHING, &sh->state) &&
+			    test_bit(R5_Wantwrite, &sh->dev[sh->pd_idx].flags)) {
+				r5l_recovery_replay_one_stripe(conf, sh, ctx);
+				list_move_tail(&sh->lru, cached_stripe_list);
+			}
+			r5l_recovery_load_data(log, sh, ctx, payload,
+					       log_offset);
+		} else if (payload->header.type == R5LOG_PAYLOAD_PARITY)
+			r5l_recovery_load_parity(log, sh, ctx, payload,
+						 log_offset);
+		else
 			return -EINVAL;
+
+		log_offset = r5l_ring_add(log, log_offset,
+					  le32_to_cpu(payload->size));
+
+		mb_offset += sizeof(struct r5l_payload_data_parity) +
+			sizeof(__le32) *
+			(le32_to_cpu(payload->size) >> (PAGE_SHIFT - 9));
 	}
+
 	return 0;
 }
 
-/* copy data/parity from log to raid disks */
-static void r5l_recovery_flush_log(struct r5l_log *log,
-				   struct r5l_recovery_ctx *ctx)
+/*
+ * Load the stripe into cache. The stripe will be written out later by
+ * the stripe cache state machine.
+ */
+static void r5c_recovery_load_one_stripe(struct r5l_log *log,
+					 struct stripe_head *sh)
 {
+	struct r5dev *dev;
+	int i;
+
+	for (i = sh->disks; i--; ) {
+		dev = sh->dev + i;
+		if (test_and_clear_bit(R5_Wantwrite, &dev->flags)) {
+			set_bit(R5_InJournal, &dev->flags);
+			set_bit(R5_UPTODATE, &dev->flags);
+		}
+	}
+}
+
+/*
+ * Scan through the log for all to-be-flushed data
+ *
+ * For stripes with data and parity, namely Data-Parity stripe
+ * (STRIPE_R5C_CACHING == 0), we simply replay all the writes.
+ *
+ * For stripes with only data, namely Data-Only stripe
+ * (STRIPE_R5C_CACHING == 1), we load them to stripe cache state machine.
+ *
+ * For a stripe, if we see data after parity, we should discard all previous
+ * data and parity for this stripe, as these data are already flushed to
+ * the array.
+ *
+ * At the end of the scan, we return the new journal_tail, which points to
+ * first data-only stripe on the journal device, or next invalid meta block.
+ */
+static int r5c_recovery_flush_log(struct r5l_log *log,
+				  struct r5l_recovery_ctx *ctx)
+{
+	struct stripe_head *sh;
+	int ret = 0;
+
+	/* scan through the log */
 	while (1) {
-		if (r5l_read_meta_block(log, ctx))
-			return;
-		if (r5l_recovery_flush_one_meta(log, ctx))
-			return;
+		if (r5l_recovery_read_meta_block(log, ctx))
+			break;
+
+		ret = r5c_recovery_analyze_meta_block(log, ctx,
+						      &ctx->cached_list);
+		/*
+		 * -EAGAIN means mismatch in data block, in this case, we still
+		 * try scan the next metablock
+		 */
+		if (ret && ret != -EAGAIN)
+			break;   /* ret == -EINVAL or -ENOMEM */
 		ctx->seq++;
 		ctx->pos = r5l_ring_add(log, ctx->pos, ctx->meta_total_blocks);
 	}
+
+	if (ret == -ENOMEM) {
+		r5c_recovery_drop_stripes(&ctx->cached_list, ctx);
+		return ret;
+	}
+
+	/* replay data-parity stripes */
+	r5c_recovery_replay_stripes(&ctx->cached_list, ctx);
+
+	/* load data-only stripes to stripe cache */
+	list_for_each_entry(sh, &ctx->cached_list, lru) {
+		WARN_ON(!test_bit(STRIPE_R5C_CACHING, &sh->state));
+		r5c_recovery_load_one_stripe(log, sh);
+		ctx->data_only_stripes++;
+	}
+
+	return 0;
 }
 
-static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos,
-					  u64 seq)
+/*
+ * we did a recovery. Now ctx.pos points to an invalid meta block. New
+ * log will start here. but we can't let superblock point to last valid
+ * meta block. The log might looks like:
+ * | meta 1| meta 2| meta 3|
+ * meta 1 is valid, meta 2 is invalid. meta 3 could be valid. If
+ * superblock points to meta 1, we write a new valid meta 2n.  if crash
+ * happens again, new recovery will start from meta 1. Since meta 2n is
+ * valid now, recovery will think meta 3 is valid, which is wrong.
+ * The solution is we create a new meta in meta2 with its seq == meta
+ * 1's seq + 10000 and let superblock points to meta2. The same recovery
+ * will not think meta 3 is a valid meta, because its seq doesn't match
+ */
+
+/*
+ * Before recovery, the log looks like the following
+ *
+ *   ---------------------------------------------
+ *   |           valid log        | invalid log  |
+ *   ---------------------------------------------
+ *   ^
+ *   |- log->last_checkpoint
+ *   |- log->last_cp_seq
+ *
+ * Now we scan through the log until we see invalid entry
+ *
+ *   ---------------------------------------------
+ *   |           valid log        | invalid log  |
+ *   ---------------------------------------------
+ *   ^                            ^
+ *   |- log->last_checkpoint      |- ctx->pos
+ *   |- log->last_cp_seq          |- ctx->seq
+ *
+ * From this point, we need to increase seq number by 10 to avoid
+ * confusing next recovery.
+ *
+ *   ---------------------------------------------
+ *   |           valid log        | invalid log  |
+ *   ---------------------------------------------
+ *   ^                              ^
+ *   |- log->last_checkpoint        |- ctx->pos+1
+ *   |- log->last_cp_seq            |- ctx->seq+10001
+ *
+ * However, it is not safe to start the state machine yet, because data only
+ * parities are not yet secured in RAID. To save these data only parities, we
+ * rewrite them from seq+11.
+ *
+ *   -----------------------------------------------------------------
+ *   |           valid log        | data only stripes | invalid log  |
+ *   -----------------------------------------------------------------
+ *   ^                                                ^
+ *   |- log->last_checkpoint                          |- ctx->pos+n
+ *   |- log->last_cp_seq                              |- ctx->seq+10000+n
+ *
+ * If failure happens again during this process, the recovery can safe start
+ * again from log->last_checkpoint.
+ *
+ * Once data only stripes are rewritten to journal, we move log_tail
+ *
+ *   -----------------------------------------------------------------
+ *   |     old log        |    data only stripes    | invalid log  |
+ *   -----------------------------------------------------------------
+ *                        ^                         ^
+ *                        |- log->last_checkpoint   |- ctx->pos+n
+ *                        |- log->last_cp_seq       |- ctx->seq+10000+n
+ *
+ * Then we can safely start the state machine. If failure happens from this
+ * point on, the recovery will start from new log->last_checkpoint.
+ */
+static int
+r5c_recovery_rewrite_data_only_stripes(struct r5l_log *log,
+				       struct r5l_recovery_ctx *ctx)
 {
+	struct stripe_head *sh;
+	struct mddev *mddev = log->rdev->mddev;
 	struct page *page;
-	struct r5l_meta_block *mb;
-	u32 crc;
+	sector_t next_checkpoint = MaxSector;
 
-	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-	if (!page)
+	page = alloc_page(GFP_KERNEL);
+	if (!page) {
+		pr_err("md/raid:%s: cannot allocate memory to rewrite data only stripes\n",
+		       mdname(mddev));
 		return -ENOMEM;
-	mb = page_address(page);
-	mb->magic = cpu_to_le32(R5LOG_MAGIC);
-	mb->version = R5LOG_VERSION;
-	mb->meta_size = cpu_to_le32(sizeof(struct r5l_meta_block));
-	mb->seq = cpu_to_le64(seq);
-	mb->position = cpu_to_le64(pos);
-	crc = crc32c_le(log->uuid_checksum, mb, PAGE_SIZE);
-	mb->checksum = cpu_to_le32(crc);
+	}
 
-	if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE,
-			  WRITE_FUA, false)) {
-		__free_page(page);
-		return -EIO;
+	WARN_ON(list_empty(&ctx->cached_list));
+
+	list_for_each_entry(sh, &ctx->cached_list, lru) {
+		struct r5l_meta_block *mb;
+		int i;
+		int offset;
+		sector_t write_pos;
+
+		WARN_ON(!test_bit(STRIPE_R5C_CACHING, &sh->state));
+		r5l_recovery_create_empty_meta_block(log, page,
+						     ctx->pos, ctx->seq);
+		mb = page_address(page);
+		offset = le32_to_cpu(mb->meta_size);
+		write_pos = r5l_ring_add(log, ctx->pos, BLOCK_SECTORS);
+
+		for (i = sh->disks; i--; ) {
+			struct r5dev *dev = &sh->dev[i];
+			struct r5l_payload_data_parity *payload;
+			void *addr;
+
+			if (test_bit(R5_InJournal, &dev->flags)) {
+				payload = (void *)mb + offset;
+				payload->header.type = cpu_to_le16(
+					R5LOG_PAYLOAD_DATA);
+				payload->size = BLOCK_SECTORS;
+				payload->location = cpu_to_le64(
+					raid5_compute_blocknr(sh, i, 0));
+				addr = kmap_atomic(dev->page);
+				payload->checksum[0] = cpu_to_le32(
+					crc32c_le(log->uuid_checksum, addr,
+						  PAGE_SIZE));
+				kunmap_atomic(addr);
+				sync_page_io(log->rdev, write_pos, PAGE_SIZE,
+					     dev->page, REQ_OP_WRITE, 0, false);
+				write_pos = r5l_ring_add(log, write_pos,
+							 BLOCK_SECTORS);
+				offset += sizeof(__le32) +
+					sizeof(struct r5l_payload_data_parity);
+
+			}
+		}
+		mb->meta_size = cpu_to_le32(offset);
+		mb->checksum = cpu_to_le32(crc32c_le(log->uuid_checksum,
+						     mb, PAGE_SIZE));
+		sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page,
+			     REQ_OP_WRITE, REQ_FUA, false);
+		sh->log_start = ctx->pos;
+		list_add_tail(&sh->r5c, &log->stripe_in_journal_list);
+		atomic_inc(&log->stripe_in_journal_count);
+		ctx->pos = write_pos;
+		ctx->seq += 1;
+		next_checkpoint = sh->log_start;
 	}
+	log->next_checkpoint = next_checkpoint;
 	__free_page(page);
 	return 0;
 }
 
+static void r5c_recovery_flush_data_only_stripes(struct r5l_log *log,
+						 struct r5l_recovery_ctx *ctx)
+{
+	struct mddev *mddev = log->rdev->mddev;
+	struct r5conf *conf = mddev->private;
+	struct stripe_head *sh, *next;
+
+	if (ctx->data_only_stripes == 0)
+		return;
+
+	log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_BACK;
+
+	list_for_each_entry_safe(sh, next, &ctx->cached_list, lru) {
+		r5c_make_stripe_write_out(sh);
+		set_bit(STRIPE_HANDLE, &sh->state);
+		list_del_init(&sh->lru);
+		raid5_release_stripe(sh);
+	}
+
+	md_wakeup_thread(conf->mddev->thread);
+	/* reuse conf->wait_for_quiescent in recovery */
+	wait_event(conf->wait_for_quiescent,
+		   atomic_read(&conf->active_stripes) == 0);
+
+	log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
+}
+
 static int r5l_recovery_log(struct r5l_log *log)
 {
+	struct mddev *mddev = log->rdev->mddev;
 	struct r5l_recovery_ctx ctx;
+	int ret;
+	sector_t pos;
 
 	ctx.pos = log->last_checkpoint;
 	ctx.seq = log->last_cp_seq;
 	ctx.meta_page = alloc_page(GFP_KERNEL);
+	ctx.data_only_stripes = 0;
+	ctx.data_parity_stripes = 0;
+	INIT_LIST_HEAD(&ctx.cached_list);
+
 	if (!ctx.meta_page)
 		return -ENOMEM;
 
-	r5l_recovery_flush_log(log, &ctx);
+	ret = r5c_recovery_flush_log(log, &ctx);
 	__free_page(ctx.meta_page);
 
-	/*
-	 * we did a recovery. Now ctx.pos points to an invalid meta block. New
-	 * log will start here. but we can't let superblock point to last valid
-	 * meta block. The log might looks like:
-	 * | meta 1| meta 2| meta 3|
-	 * meta 1 is valid, meta 2 is invalid. meta 3 could be valid. If
-	 * superblock points to meta 1, we write a new valid meta 2n.  if crash
-	 * happens again, new recovery will start from meta 1. Since meta 2n is
-	 * valid now, recovery will think meta 3 is valid, which is wrong.
-	 * The solution is we create a new meta in meta2 with its seq == meta
-	 * 1's seq + 10 and let superblock points to meta2. The same recovery will
-	 * not think meta 3 is a valid meta, because its seq doesn't match
-	 */
-	if (ctx.seq > log->last_cp_seq) {
-		int ret;
+	if (ret)
+		return ret;
 
-		ret = r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq + 10);
-		if (ret)
-			return ret;
-		log->seq = ctx.seq + 11;
-		log->log_start = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
-		r5l_write_super(log, ctx.pos);
-		log->last_checkpoint = ctx.pos;
+	pos = ctx.pos;
+	ctx.seq += 10000;
+
+
+	if ((ctx.data_only_stripes == 0) && (ctx.data_parity_stripes == 0))
+		pr_debug("md/raid:%s: starting from clean shutdown\n",
+			 mdname(mddev));
+	else
+		pr_debug("md/raid:%s: recovering %d data-only stripes and %d data-parity stripes\n",
+			 mdname(mddev), ctx.data_only_stripes,
+			 ctx.data_parity_stripes);
+
+	if (ctx.data_only_stripes == 0) {
 		log->next_checkpoint = ctx.pos;
-	} else {
-		log->log_start = ctx.pos;
-		log->seq = ctx.seq;
+		r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq++);
+		ctx.pos = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);
+	} else if (r5c_recovery_rewrite_data_only_stripes(log, &ctx)) {
+		pr_err("md/raid:%s: failed to rewrite stripes to journal\n",
+		       mdname(mddev));
+		return -EIO;
 	}
+
+	log->log_start = ctx.pos;
+	log->seq = ctx.seq;
+	log->last_checkpoint = pos;
+	r5l_write_super(log, pos);
+
+	r5c_recovery_flush_data_only_stripes(log, &ctx);
 	return 0;
 }
 
@@ -1110,7 +2233,306 @@ static void r5l_write_super(struct r5l_l
 	struct mddev *mddev = log->rdev->mddev;
 
 	log->rdev->journal_tail = cp;
-	set_bit(MD_CHANGE_DEVS, &mddev->flags);
+	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
+}
+
+static ssize_t r5c_journal_mode_show(struct mddev *mddev, char *page)
+{
+	struct r5conf *conf = mddev->private;
+	int ret;
+
+	if (!conf->log)
+		return 0;
+
+	switch (conf->log->r5c_journal_mode) {
+	case R5C_JOURNAL_MODE_WRITE_THROUGH:
+		ret = snprintf(
+			page, PAGE_SIZE, "[%s] %s\n",
+			r5c_journal_mode_str[R5C_JOURNAL_MODE_WRITE_THROUGH],
+			r5c_journal_mode_str[R5C_JOURNAL_MODE_WRITE_BACK]);
+		break;
+	case R5C_JOURNAL_MODE_WRITE_BACK:
+		ret = snprintf(
+			page, PAGE_SIZE, "%s [%s]\n",
+			r5c_journal_mode_str[R5C_JOURNAL_MODE_WRITE_THROUGH],
+			r5c_journal_mode_str[R5C_JOURNAL_MODE_WRITE_BACK]);
+		break;
+	default:
+		ret = 0;
+	}
+	return ret;
+}
+
+static ssize_t r5c_journal_mode_store(struct mddev *mddev,
+				      const char *page, size_t length)
+{
+	struct r5conf *conf = mddev->private;
+	struct r5l_log *log = conf->log;
+	int val = -1, i;
+	int len = length;
+
+	if (!log)
+		return -ENODEV;
+
+	if (len && page[len - 1] == '\n')
+		len -= 1;
+	for (i = 0; i < ARRAY_SIZE(r5c_journal_mode_str); i++)
+		if (strlen(r5c_journal_mode_str[i]) == len &&
+		    strncmp(page, r5c_journal_mode_str[i], len) == 0) {
+			val = i;
+			break;
+		}
+	if (val < R5C_JOURNAL_MODE_WRITE_THROUGH ||
+	    val > R5C_JOURNAL_MODE_WRITE_BACK)
+		return -EINVAL;
+
+	if (raid5_calc_degraded(conf) > 0 &&
+	    val == R5C_JOURNAL_MODE_WRITE_BACK)
+		return -EINVAL;
+
+	mddev_suspend(mddev);
+	conf->log->r5c_journal_mode = val;
+	mddev_resume(mddev);
+
+	pr_debug("md/raid:%s: setting r5c cache mode to %d: %s\n",
+		 mdname(mddev), val, r5c_journal_mode_str[val]);
+	return length;
+}
+
+struct md_sysfs_entry
+r5c_journal_mode = __ATTR(journal_mode, 0644,
+			  r5c_journal_mode_show, r5c_journal_mode_store);
+
+/*
+ * Try handle write operation in caching phase. This function should only
+ * be called in write-back mode.
+ *
+ * If all outstanding writes can be handled in caching phase, returns 0
+ * If writes requires write-out phase, call r5c_make_stripe_write_out()
+ * and returns -EAGAIN
+ */
+int r5c_try_caching_write(struct r5conf *conf,
+			  struct stripe_head *sh,
+			  struct stripe_head_state *s,
+			  int disks)
+{
+	struct r5l_log *log = conf->log;
+	int i;
+	struct r5dev *dev;
+	int to_cache = 0;
+
+	BUG_ON(!r5c_is_writeback(log));
+
+	if (!test_bit(STRIPE_R5C_CACHING, &sh->state)) {
+		/*
+		 * There are two different scenarios here:
+		 *  1. The stripe has some data cached, and it is sent to
+		 *     write-out phase for reclaim
+		 *  2. The stripe is clean, and this is the first write
+		 *
+		 * For 1, return -EAGAIN, so we continue with
+		 * handle_stripe_dirtying().
+		 *
+		 * For 2, set STRIPE_R5C_CACHING and continue with caching
+		 * write.
+		 */
+
+		/* case 1: anything injournal or anything in written */
+		if (s->injournal > 0 || s->written > 0)
+			return -EAGAIN;
+		/* case 2 */
+		set_bit(STRIPE_R5C_CACHING, &sh->state);
+	}
+
+	/*
+	 * When run in degraded mode, array is set to write-through mode.
+	 * This check helps drain pending write safely in the transition to
+	 * write-through mode.
+	 */
+	if (s->failed) {
+		r5c_make_stripe_write_out(sh);
+		return -EAGAIN;
+	}
+
+	for (i = disks; i--; ) {
+		dev = &sh->dev[i];
+		/* if non-overwrite, use writing-out phase */
+		if (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags) &&
+		    !test_bit(R5_InJournal, &dev->flags)) {
+			r5c_make_stripe_write_out(sh);
+			return -EAGAIN;
+		}
+	}
+
+	for (i = disks; i--; ) {
+		dev = &sh->dev[i];
+		if (dev->towrite) {
+			set_bit(R5_Wantwrite, &dev->flags);
+			set_bit(R5_Wantdrain, &dev->flags);
+			set_bit(R5_LOCKED, &dev->flags);
+			to_cache++;
+		}
+	}
+
+	if (to_cache) {
+		set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+		/*
+		 * set STRIPE_LOG_TRAPPED, which triggers r5c_cache_data()
+		 * in ops_run_io(). STRIPE_LOG_TRAPPED will be cleared in
+		 * r5c_handle_data_cached()
+		 */
+		set_bit(STRIPE_LOG_TRAPPED, &sh->state);
+	}
+
+	return 0;
+}
+
+/*
+ * free extra pages (orig_page) we allocated for prexor
+ */
+void r5c_release_extra_page(struct stripe_head *sh)
+{
+	struct r5conf *conf = sh->raid_conf;
+	int i;
+	bool using_disk_info_extra_page;
+
+	using_disk_info_extra_page =
+		sh->dev[0].orig_page == conf->disks[0].extra_page;
+
+	for (i = sh->disks; i--; )
+		if (sh->dev[i].page != sh->dev[i].orig_page) {
+			struct page *p = sh->dev[i].orig_page;
+
+			sh->dev[i].orig_page = sh->dev[i].page;
+			clear_bit(R5_OrigPageUPTDODATE, &sh->dev[i].flags);
+
+			if (!using_disk_info_extra_page)
+				put_page(p);
+		}
+
+	if (using_disk_info_extra_page) {
+		clear_bit(R5C_EXTRA_PAGE_IN_USE, &conf->cache_state);
+		md_wakeup_thread(conf->mddev->thread);
+	}
+}
+
+void r5c_use_extra_page(struct stripe_head *sh)
+{
+	struct r5conf *conf = sh->raid_conf;
+	int i;
+	struct r5dev *dev;
+
+	for (i = sh->disks; i--; ) {
+		dev = &sh->dev[i];
+		if (dev->orig_page != dev->page)
+			put_page(dev->orig_page);
+		dev->orig_page = conf->disks[i].extra_page;
+	}
+}
+
+/*
+ * clean up the stripe (clear R5_InJournal for dev[pd_idx] etc.) after the
+ * stripe is committed to RAID disks.
+ */
+void r5c_finish_stripe_write_out(struct r5conf *conf,
+				 struct stripe_head *sh,
+				 struct stripe_head_state *s)
+{
+	int i;
+	int do_wakeup = 0;
+
+	if (!conf->log ||
+	    !test_bit(R5_InJournal, &sh->dev[sh->pd_idx].flags))
+		return;
+
+	WARN_ON(test_bit(STRIPE_R5C_CACHING, &sh->state));
+	clear_bit(R5_InJournal, &sh->dev[sh->pd_idx].flags);
+
+	if (conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_THROUGH)
+		return;
+
+	for (i = sh->disks; i--; ) {
+		clear_bit(R5_InJournal, &sh->dev[i].flags);
+		if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+			do_wakeup = 1;
+	}
+
+	/*
+	 * analyse_stripe() runs before r5c_finish_stripe_write_out(),
+	 * We updated R5_InJournal, so we also update s->injournal.
+	 */
+	s->injournal = 0;
+
+	if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
+		if (atomic_dec_and_test(&conf->pending_full_writes))
+			md_wakeup_thread(conf->mddev->thread);
+
+	if (do_wakeup)
+		wake_up(&conf->wait_for_overlap);
+
+	spin_lock_irq(&conf->log->stripe_in_journal_lock);
+	list_del_init(&sh->r5c);
+	spin_unlock_irq(&conf->log->stripe_in_journal_lock);
+	sh->log_start = MaxSector;
+	atomic_dec(&conf->log->stripe_in_journal_count);
+	r5c_update_log_state(conf->log);
+}
+
+int
+r5c_cache_data(struct r5l_log *log, struct stripe_head *sh,
+	       struct stripe_head_state *s)
+{
+	struct r5conf *conf = sh->raid_conf;
+	int pages = 0;
+	int reserve;
+	int i;
+	int ret = 0;
+
+	BUG_ON(!log);
+
+	for (i = 0; i < sh->disks; i++) {
+		void *addr;
+
+		if (!test_bit(R5_Wantwrite, &sh->dev[i].flags))
+			continue;
+		addr = kmap_atomic(sh->dev[i].page);
+		sh->dev[i].log_checksum = crc32c_le(log->uuid_checksum,
+						    addr, PAGE_SIZE);
+		kunmap_atomic(addr);
+		pages++;
+	}
+	WARN_ON(pages == 0);
+
+	/*
+	 * The stripe must enter state machine again to call endio, so
+	 * don't delay.
+	 */
+	clear_bit(STRIPE_DELAYED, &sh->state);
+	atomic_inc(&sh->count);
+
+	mutex_lock(&log->io_mutex);
+	/* meta + data */
+	reserve = (1 + pages) << (PAGE_SHIFT - 9);
+
+	if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) &&
+	    sh->log_start == MaxSector)
+		r5l_add_no_space_stripe(log, sh);
+	else if (!r5l_has_free_space(log, reserve)) {
+		if (sh->log_start == log->last_checkpoint)
+			BUG();
+		else
+			r5l_add_no_space_stripe(log, sh);
+	} else {
+		ret = r5l_log_stripe(log, sh, pages, 0);
+		if (ret) {
+			spin_lock_irq(&log->io_list_lock);
+			list_add_tail(&sh->log_list, &log->no_mem_stripes);
+			spin_unlock_irq(&log->io_list_lock);
+		}
+	}
+
+	mutex_unlock(&log->io_mutex);
+	return 0;
 }
 
 static int r5l_load_log(struct r5l_log *log)
@@ -1121,7 +2543,7 @@ static int r5l_load_log(struct r5l_log *
 	sector_t cp = log->rdev->journal_tail;
 	u32 stored_crc, expected_crc;
 	bool create_super = false;
-	int ret;
+	int ret = 0;
 
 	/* Make sure it's valid */
 	if (cp >= rdev->sectors || round_down(cp, BLOCK_SECTORS) != cp)
@@ -1171,16 +2593,36 @@ create:
 	if (log->max_free_space > RECLAIM_MAX_FREE_SPACE)
 		log->max_free_space = RECLAIM_MAX_FREE_SPACE;
 	log->last_checkpoint = cp;
-	log->next_checkpoint = cp;
 
 	__free_page(page);
 
-	return r5l_recovery_log(log);
+	if (create_super) {
+		log->log_start = r5l_ring_add(log, cp, BLOCK_SECTORS);
+		log->seq = log->last_cp_seq + 1;
+		log->next_checkpoint = cp;
+	} else
+		ret = r5l_recovery_log(log);
+
+	r5c_update_log_state(log);
+	return ret;
 ioerr:
 	__free_page(page);
 	return ret;
 }
 
+void r5c_update_on_rdev_error(struct mddev *mddev)
+{
+	struct r5conf *conf = mddev->private;
+	struct r5l_log *log = conf->log;
+
+	if (!log)
+		return;
+
+	if (raid5_calc_degraded(conf) > 0 &&
+	    conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
+		schedule_work(&log->disable_writeback_work);
+}
+
 int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev)
 {
 	struct request_queue *q = bdev_get_queue(rdev->bdev);
@@ -1188,6 +2630,22 @@ int r5l_init_log(struct r5conf *conf, st
 
 	if (PAGE_SIZE != 4096)
 		return -EINVAL;
+
+	/*
+	 * The PAGE_SIZE must be big enough to hold 1 r5l_meta_block and
+	 * raid_disks r5l_payload_data_parity.
+	 *
+	 * Write journal and cache does not work for very big array
+	 * (raid_disks > 203)
+	 */
+	if (sizeof(struct r5l_meta_block) +
+	    ((sizeof(struct r5l_payload_data_parity) + sizeof(__le32)) *
+	     conf->raid_disks) > PAGE_SIZE) {
+		pr_err("md/raid:%s: write journal/cache doesn't work for array with %d disks\n",
+		       mdname(conf->mddev), conf->raid_disks);
+		return -EINVAL;
+	}
+
 	log = kzalloc(sizeof(*log), GFP_KERNEL);
 	if (!log)
 		return -ENOMEM;
@@ -1205,7 +2663,7 @@ int r5l_init_log(struct r5conf *conf, st
 	INIT_LIST_HEAD(&log->io_end_ios);
 	INIT_LIST_HEAD(&log->flushing_ios);
 	INIT_LIST_HEAD(&log->finished_ios);
-	bio_init(&log->flush_bio);
+	bio_init(&log->flush_bio, NULL, 0);
 
 	log->io_kc = KMEM_CACHE(r5l_io_unit, 0);
 	if (!log->io_kc)
@@ -1227,6 +2685,8 @@ int r5l_init_log(struct r5conf *conf, st
 						 log->rdev->mddev, "reclaim");
 	if (!log->reclaim_thread)
 		goto reclaim_thread;
+	log->reclaim_thread->timeout = R5C_RECLAIM_WAKEUP_INTERVAL;
+
 	init_waitqueue_head(&log->iounit_wait);
 
 	INIT_LIST_HEAD(&log->no_mem_stripes);
@@ -1234,14 +2694,24 @@ int r5l_init_log(struct r5conf *conf, st
 	INIT_LIST_HEAD(&log->no_space_stripes);
 	spin_lock_init(&log->no_space_stripes_lock);
 
+	INIT_WORK(&log->deferred_io_work, r5l_submit_io_async);
+	INIT_WORK(&log->disable_writeback_work, r5c_disable_writeback_async);
+
+	log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
+	INIT_LIST_HEAD(&log->stripe_in_journal_list);
+	spin_lock_init(&log->stripe_in_journal_lock);
+	atomic_set(&log->stripe_in_journal_count, 0);
+
+	rcu_assign_pointer(conf->log, log);
+
 	if (r5l_load_log(log))
 		goto error;
 
-	rcu_assign_pointer(conf->log, log);
 	set_bit(MD_HAS_JOURNAL, &conf->mddev->flags);
 	return 0;
 
 error:
+	rcu_assign_pointer(conf->log, NULL);
 	md_unregister_thread(&log->reclaim_thread);
 reclaim_thread:
 	mempool_destroy(log->meta_pool);
@@ -1258,6 +2728,7 @@ io_kc:
 
 void r5l_exit_log(struct r5l_log *log)
 {
+	flush_work(&log->disable_writeback_work);
 	md_unregister_thread(&log->reclaim_thread);
 	mempool_destroy(log->meta_pool);
 	bioset_free(log->bs);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/md/raid5.h linux-libre-4.10-rc8-gnu/drivers/md/raid5.h
--- linux-libre-4.9-gnu/drivers/md/raid5.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/md/raid5.h	2017-02-12 16:03:20.000000000 -0500
@@ -226,6 +226,8 @@ struct stripe_head {
 
 	struct r5l_io_unit	*log_io;
 	struct list_head	log_list;
+	sector_t		log_start; /* first meta block on the journal */
+	struct list_head	r5c; /* for r5c_cache->stripe_in_journal */
 	/**
 	 * struct stripe_operations
 	 * @target - STRIPE_OP_COMPUTE_BLK target
@@ -264,6 +266,7 @@ struct stripe_head_state {
 	int syncing, expanding, expanded, replacing;
 	int locked, uptodate, to_read, to_write, failed, written;
 	int to_fill, compute, req_compute, non_overwrite;
+	int injournal, just_cached;
 	int failed_num[2];
 	int p_failed, q_failed;
 	int dec_preread_active;
@@ -273,6 +276,7 @@ struct stripe_head_state {
 	struct md_rdev *blocked_rdev;
 	int handle_bad_blocks;
 	int log_failed;
+	int waiting_extra_page;
 };
 
 /* Flags for struct r5dev.flags */
@@ -313,6 +317,16 @@ enum r5dev_flags {
 			 */
 	R5_Discard,	/* Discard the stripe */
 	R5_SkipCopy,	/* Don't copy data from bio to stripe cache */
+	R5_InJournal,	/* data being written is in the journal device.
+			 * if R5_InJournal is set for parity pd_idx, all the
+			 * data and parity being written are in the journal
+			 * device
+			 */
+	R5_OrigPageUPTDODATE,	/* with write back cache, we read old data into
+				 * dev->orig_page for prexor. When this flag is
+				 * set, orig_page contains latest data in the
+				 * raid disk.
+				 */
 };
 
 /*
@@ -345,7 +359,30 @@ enum {
 	STRIPE_BITMAP_PENDING,	/* Being added to bitmap, don't add
 				 * to batch yet.
 				 */
-	STRIPE_LOG_TRAPPED, /* trapped into log */
+	STRIPE_LOG_TRAPPED,	/* trapped into log (see raid5-cache.c)
+				 * this bit is used in two scenarios:
+				 *
+				 * 1. write-out phase
+				 *  set in first entry of r5l_write_stripe
+				 *  clear in second entry of r5l_write_stripe
+				 *  used to bypass logic in handle_stripe
+				 *
+				 * 2. caching phase
+				 *  set in r5c_try_caching_write()
+				 *  clear when journal write is done
+				 *  used to initiate r5c_cache_data()
+				 *  also used to bypass logic in handle_stripe
+				 */
+	STRIPE_R5C_CACHING,	/* the stripe is in caching phase
+				 * see more detail in the raid5-cache.c
+				 */
+	STRIPE_R5C_PARTIAL_STRIPE,	/* in r5c cache (to-be/being handled or
+					 * in conf->r5c_partial_stripe_list)
+					 */
+	STRIPE_R5C_FULL_STRIPE,	/* in r5c cache (to-be/being handled or
+				 * in conf->r5c_full_stripe_list)
+				 */
+	STRIPE_R5C_PREFLUSH,	/* need to flush journal device */
 };
 
 #define STRIPE_EXPAND_SYNC_FLAGS \
@@ -408,8 +445,86 @@ enum {
 
 struct disk_info {
 	struct md_rdev	*rdev, *replacement;
+	struct page	*extra_page; /* extra page to use in prexor */
 };
 
+/*
+ * Stripe cache
+ */
+
+#define NR_STRIPES		256
+#define STRIPE_SIZE		PAGE_SIZE
+#define STRIPE_SHIFT		(PAGE_SHIFT - 9)
+#define STRIPE_SECTORS		(STRIPE_SIZE>>9)
+#define	IO_THRESHOLD		1
+#define BYPASS_THRESHOLD	1
+#define NR_HASH			(PAGE_SIZE / sizeof(struct hlist_head))
+#define HASH_MASK		(NR_HASH - 1)
+#define MAX_STRIPE_BATCH	8
+
+/* 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
+ * a bio could span several devices.
+ * 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 function is used to determine the 'next' bio in the list, given the
+ * sector of the current stripe+device
+ */
+static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector)
+{
+	int sectors = bio_sectors(bio);
+
+	if (bio->bi_iter.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
+ * bi_phys_segments, and a count of processed stripes in the upper 16 bits
+ */
+static inline int raid5_bi_processed_stripes(struct bio *bio)
+{
+	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
+
+	return (atomic_read(segments) >> 16) & 0xffff;
+}
+
+static inline int raid5_dec_bi_active_stripes(struct bio *bio)
+{
+	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
+
+	return atomic_sub_return(1, segments) & 0xffff;
+}
+
+static inline void raid5_inc_bi_active_stripes(struct bio *bio)
+{
+	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
+
+	atomic_inc(segments);
+}
+
+static inline void raid5_set_bi_processed_stripes(struct bio *bio,
+	unsigned int cnt)
+{
+	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
+	int old, new;
+
+	do {
+		old = atomic_read(segments);
+		new = (old & 0xffff) | (cnt << 16);
+	} while (atomic_cmpxchg(segments, old, new) != old);
+}
+
+static inline void raid5_set_bi_stripes(struct bio *bio, unsigned int cnt)
+{
+	atomic_t *segments = (atomic_t *)&bio->bi_phys_segments;
+
+	atomic_set(segments, cnt);
+}
+
 /* NOTE NR_STRIPE_HASH_LOCKS must remain below 64.
  * This is because we sometimes take all the spinlocks
  * and creating that much locking depth can cause
@@ -432,6 +547,30 @@ struct r5worker_group {
 	int stripes_cnt;
 };
 
+enum r5_cache_state {
+	R5_INACTIVE_BLOCKED,	/* release of inactive stripes blocked,
+				 * waiting for 25% to be free
+				 */
+	R5_ALLOC_MORE,		/* It might help to allocate another
+				 * stripe.
+				 */
+	R5_DID_ALLOC,		/* A stripe was allocated, don't allocate
+				 * more until at least one has been
+				 * released.  This avoids flooding
+				 * the cache.
+				 */
+	R5C_LOG_TIGHT,		/* log device space tight, need to
+				 * prioritize stripes at last_checkpoint
+				 */
+	R5C_LOG_CRITICAL,	/* log device is running out of space,
+				 * only process stripes that are already
+				 * occupying the log
+				 */
+	R5C_EXTRA_PAGE_IN_USE,	/* a stripe is using disk_info.extra_page
+				 * for prexor
+				 */
+};
+
 struct r5conf {
 	struct hlist_head	*stripe_hashtbl;
 	/* only protect corresponding hash list and inactive_list */
@@ -519,23 +658,18 @@ struct r5conf {
 	 */
 	atomic_t		active_stripes;
 	struct list_head	inactive_list[NR_STRIPE_HASH_LOCKS];
+
+	atomic_t		r5c_cached_full_stripes;
+	struct list_head	r5c_full_stripe_list;
+	atomic_t		r5c_cached_partial_stripes;
+	struct list_head	r5c_partial_stripe_list;
+
 	atomic_t		empty_inactive_list_nr;
 	struct llist_head	released_stripes;
 	wait_queue_head_t	wait_for_quiescent;
 	wait_queue_head_t	wait_for_stripe;
 	wait_queue_head_t	wait_for_overlap;
 	unsigned long		cache_state;
-#define R5_INACTIVE_BLOCKED	1	/* release of inactive stripes blocked,
-					 * waiting for 25% to be free
-					 */
-#define R5_ALLOC_MORE		2	/* It might help to allocate another
-					 * stripe.
-					 */
-#define R5_DID_ALLOC		4	/* A stripe was allocated, don't allocate
-					 * more until at least one has been
-					 * released.  This avoids flooding
-					 * the cache.
-					 */
 	struct shrinker		shrinker;
 	int			pool_size; /* number of disks in stripeheads in pool */
 	spinlock_t		device_lock;
@@ -624,6 +758,7 @@ extern sector_t raid5_compute_sector(str
 extern struct stripe_head *
 raid5_get_active_stripe(struct r5conf *conf, sector_t sector,
 			int previous, int noblock, int noquiesce);
+extern int raid5_calc_degraded(struct r5conf *conf);
 extern int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev);
 extern void r5l_exit_log(struct r5l_log *log);
 extern int r5l_write_stripe(struct r5l_log *log, struct stripe_head *head_sh);
@@ -633,4 +768,24 @@ extern void r5l_stripe_write_finished(st
 extern int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio);
 extern void r5l_quiesce(struct r5l_log *log, int state);
 extern bool r5l_log_disk_error(struct r5conf *conf);
+extern bool r5c_is_writeback(struct r5l_log *log);
+extern int
+r5c_try_caching_write(struct r5conf *conf, struct stripe_head *sh,
+		      struct stripe_head_state *s, int disks);
+extern void
+r5c_finish_stripe_write_out(struct r5conf *conf, struct stripe_head *sh,
+			    struct stripe_head_state *s);
+extern void r5c_release_extra_page(struct stripe_head *sh);
+extern void r5c_use_extra_page(struct stripe_head *sh);
+extern void r5l_wake_reclaim(struct r5l_log *log, sector_t space);
+extern void r5c_handle_cached_data_endio(struct r5conf *conf,
+	struct stripe_head *sh, int disks, struct bio_list *return_bi);
+extern int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh,
+			  struct stripe_head_state *s);
+extern void r5c_make_stripe_write_out(struct stripe_head *sh);
+extern void r5c_flush_cache(struct r5conf *conf, int num);
+extern void r5c_check_stripe_cache_usage(struct r5conf *conf);
+extern void r5c_check_cached_full_stripe(struct r5conf *conf);
+extern struct md_sysfs_entry r5c_journal_mode;
+extern void r5c_update_on_rdev_error(struct mddev *mddev);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/cec/cec-adap.c linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-adap.c
--- linux-libre-4.9-gnu/drivers/media/cec/cec-adap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-adap.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1881 @@
+/*
+ * cec-adap.c - HDMI Consumer Electronics Control framework - CEC adapter
+ *
+ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. 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/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "cec-priv.h"
+
+static void cec_fill_msg_report_features(struct cec_adapter *adap,
+					 struct cec_msg *msg,
+					 unsigned int la_idx);
+
+/*
+ * 400 ms is the time it takes for one 16 byte message to be
+ * transferred and 5 is the maximum number of retries. Add
+ * another 100 ms as a margin. So if the transmit doesn't
+ * finish before that time something is really wrong and we
+ * have to time out.
+ *
+ * This is a sign that something it really wrong and a warning
+ * will be issued.
+ */
+#define CEC_XFER_TIMEOUT_MS (5 * 400 + 100)
+
+#define call_op(adap, op, arg...) \
+	(adap->ops->op ? adap->ops->op(adap, ## arg) : 0)
+
+#define call_void_op(adap, op, arg...)			\
+	do {						\
+		if (adap->ops->op)			\
+			adap->ops->op(adap, ## arg);	\
+	} while (0)
+
+static int cec_log_addr2idx(const struct cec_adapter *adap, u8 log_addr)
+{
+	int i;
+
+	for (i = 0; i < adap->log_addrs.num_log_addrs; i++)
+		if (adap->log_addrs.log_addr[i] == log_addr)
+			return i;
+	return -1;
+}
+
+static unsigned int cec_log_addr2dev(const struct cec_adapter *adap, u8 log_addr)
+{
+	int i = cec_log_addr2idx(adap, log_addr);
+
+	return adap->log_addrs.primary_device_type[i < 0 ? 0 : i];
+}
+
+/*
+ * Queue a new event for this filehandle. If ts == 0, then set it
+ * to the current time.
+ *
+ * The two events that are currently defined do not need to keep track
+ * of intermediate events, so no actual queue of events is needed,
+ * instead just store the latest state and the total number of lost
+ * messages.
+ *
+ * Should new events be added in the future that require intermediate
+ * results to be queued as well, then a proper queue data structure is
+ * required. But until then, just keep it simple.
+ */
+void cec_queue_event_fh(struct cec_fh *fh,
+			const struct cec_event *new_ev, u64 ts)
+{
+	struct cec_event *ev = &fh->events[new_ev->event - 1];
+
+	if (ts == 0)
+		ts = ktime_get_ns();
+
+	mutex_lock(&fh->lock);
+	if (new_ev->event == CEC_EVENT_LOST_MSGS &&
+	    fh->pending_events & (1 << new_ev->event)) {
+		/*
+		 * If there is already a lost_msgs event, then just
+		 * update the lost_msgs count. This effectively
+		 * merges the old and new events into one.
+		 */
+		ev->lost_msgs.lost_msgs += new_ev->lost_msgs.lost_msgs;
+		goto unlock;
+	}
+
+	/*
+	 * Intermediate states are not interesting, so just
+	 * overwrite any older event.
+	 */
+	*ev = *new_ev;
+	ev->ts = ts;
+	fh->pending_events |= 1 << new_ev->event;
+
+unlock:
+	mutex_unlock(&fh->lock);
+	wake_up_interruptible(&fh->wait);
+}
+
+/* Queue a new event for all open filehandles. */
+static void cec_queue_event(struct cec_adapter *adap,
+			    const struct cec_event *ev)
+{
+	u64 ts = ktime_get_ns();
+	struct cec_fh *fh;
+
+	mutex_lock(&adap->devnode.lock);
+	list_for_each_entry(fh, &adap->devnode.fhs, list)
+		cec_queue_event_fh(fh, ev, ts);
+	mutex_unlock(&adap->devnode.lock);
+}
+
+/*
+ * Queue a new message for this filehandle. If there is no more room
+ * in the queue, then send the LOST_MSGS event instead.
+ */
+static void cec_queue_msg_fh(struct cec_fh *fh, const struct cec_msg *msg)
+{
+	static const struct cec_event ev_lost_msg = {
+		.ts = 0,
+		.event = CEC_EVENT_LOST_MSGS,
+		.flags = 0,
+		{
+			.lost_msgs.lost_msgs = 1,
+		},
+	};
+	struct cec_msg_entry *entry;
+
+	mutex_lock(&fh->lock);
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		goto lost_msgs;
+
+	entry->msg = *msg;
+	/* Add new msg at the end of the queue */
+	list_add_tail(&entry->list, &fh->msgs);
+
+	/*
+	 * if the queue now has more than CEC_MAX_MSG_RX_QUEUE_SZ
+	 * messages, drop the oldest one and send a lost message event.
+	 */
+	if (fh->queued_msgs == CEC_MAX_MSG_RX_QUEUE_SZ) {
+		list_del(&entry->list);
+		goto lost_msgs;
+	}
+	fh->queued_msgs++;
+	mutex_unlock(&fh->lock);
+	wake_up_interruptible(&fh->wait);
+	return;
+
+lost_msgs:
+	mutex_unlock(&fh->lock);
+	cec_queue_event_fh(fh, &ev_lost_msg, 0);
+}
+
+/*
+ * Queue the message for those filehandles that are in monitor mode.
+ * If valid_la is true (this message is for us or was sent by us),
+ * then pass it on to any monitoring filehandle. If this message
+ * isn't for us or from us, then only give it to filehandles that
+ * are in MONITOR_ALL mode.
+ *
+ * This can only happen if the CEC_CAP_MONITOR_ALL capability is
+ * set and the CEC adapter was placed in 'monitor all' mode.
+ */
+static void cec_queue_msg_monitor(struct cec_adapter *adap,
+				  const struct cec_msg *msg,
+				  bool valid_la)
+{
+	struct cec_fh *fh;
+	u32 monitor_mode = valid_la ? CEC_MODE_MONITOR :
+				      CEC_MODE_MONITOR_ALL;
+
+	mutex_lock(&adap->devnode.lock);
+	list_for_each_entry(fh, &adap->devnode.fhs, list) {
+		if (fh->mode_follower >= monitor_mode)
+			cec_queue_msg_fh(fh, msg);
+	}
+	mutex_unlock(&adap->devnode.lock);
+}
+
+/*
+ * Queue the message for follower filehandles.
+ */
+static void cec_queue_msg_followers(struct cec_adapter *adap,
+				    const struct cec_msg *msg)
+{
+	struct cec_fh *fh;
+
+	mutex_lock(&adap->devnode.lock);
+	list_for_each_entry(fh, &adap->devnode.fhs, list) {
+		if (fh->mode_follower == CEC_MODE_FOLLOWER)
+			cec_queue_msg_fh(fh, msg);
+	}
+	mutex_unlock(&adap->devnode.lock);
+}
+
+/* Notify userspace of an adapter state change. */
+static void cec_post_state_event(struct cec_adapter *adap)
+{
+	struct cec_event ev = {
+		.event = CEC_EVENT_STATE_CHANGE,
+	};
+
+	ev.state_change.phys_addr = adap->phys_addr;
+	ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
+	cec_queue_event(adap, &ev);
+}
+
+/*
+ * A CEC transmit (and a possible wait for reply) completed.
+ * If this was in blocking mode, then complete it, otherwise
+ * queue the message for userspace to dequeue later.
+ *
+ * This function is called with adap->lock held.
+ */
+static void cec_data_completed(struct cec_data *data)
+{
+	/*
+	 * Delete this transmit from the filehandle's xfer_list since
+	 * we're done with it.
+	 *
+	 * Note that if the filehandle is closed before this transmit
+	 * finished, then the release() function will set data->fh to NULL.
+	 * Without that we would be referring to a closed filehandle.
+	 */
+	if (data->fh)
+		list_del(&data->xfer_list);
+
+	if (data->blocking) {
+		/*
+		 * Someone is blocking so mark the message as completed
+		 * and call complete.
+		 */
+		data->completed = true;
+		complete(&data->c);
+	} else {
+		/*
+		 * No blocking, so just queue the message if needed and
+		 * free the memory.
+		 */
+		if (data->fh)
+			cec_queue_msg_fh(data->fh, &data->msg);
+		kfree(data);
+	}
+}
+
+/*
+ * A pending CEC transmit needs to be cancelled, either because the CEC
+ * adapter is disabled or the transmit takes an impossibly long time to
+ * finish.
+ *
+ * This function is called with adap->lock held.
+ */
+static void cec_data_cancel(struct cec_data *data)
+{
+	/*
+	 * It's either the current transmit, or it is a pending
+	 * transmit. Take the appropriate action to clear it.
+	 */
+	if (data->adap->transmitting == data) {
+		data->adap->transmitting = NULL;
+	} else {
+		list_del_init(&data->list);
+		if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
+			data->adap->transmit_queue_sz--;
+	}
+
+	/* Mark it as an error */
+	data->msg.tx_ts = ktime_get_ns();
+	data->msg.tx_status |= CEC_TX_STATUS_ERROR |
+			       CEC_TX_STATUS_MAX_RETRIES;
+	data->msg.tx_error_cnt++;
+	data->attempts = 0;
+	/* Queue transmitted message for monitoring purposes */
+	cec_queue_msg_monitor(data->adap, &data->msg, 1);
+
+	cec_data_completed(data);
+}
+
+/*
+ * Main CEC state machine
+ *
+ * Wait until the thread should be stopped, or we are not transmitting and
+ * a new transmit message is queued up, in which case we start transmitting
+ * that message. When the adapter finished transmitting the message it will
+ * call cec_transmit_done().
+ *
+ * If the adapter is disabled, then remove all queued messages instead.
+ *
+ * If the current transmit times out, then cancel that transmit.
+ */
+int cec_thread_func(void *_adap)
+{
+	struct cec_adapter *adap = _adap;
+
+	for (;;) {
+		unsigned int signal_free_time;
+		struct cec_data *data;
+		bool timeout = false;
+		u8 attempts;
+
+		if (adap->transmitting) {
+			int err;
+
+			/*
+			 * We are transmitting a message, so add a timeout
+			 * to prevent the state machine to get stuck waiting
+			 * for this message to finalize and add a check to
+			 * see if the adapter is disabled in which case the
+			 * transmit should be canceled.
+			 */
+			err = wait_event_interruptible_timeout(adap->kthread_waitq,
+				kthread_should_stop() ||
+				(!adap->is_configured && !adap->is_configuring) ||
+				(!adap->transmitting &&
+				 !list_empty(&adap->transmit_queue)),
+				msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
+			timeout = err == 0;
+		} else {
+			/* Otherwise we just wait for something to happen. */
+			wait_event_interruptible(adap->kthread_waitq,
+				kthread_should_stop() ||
+				(!adap->transmitting &&
+				 !list_empty(&adap->transmit_queue)));
+		}
+
+		mutex_lock(&adap->lock);
+
+		if ((!adap->is_configured && !adap->is_configuring) ||
+		    kthread_should_stop()) {
+			/*
+			 * If the adapter is disabled, or we're asked to stop,
+			 * then cancel any pending transmits.
+			 */
+			while (!list_empty(&adap->transmit_queue)) {
+				data = list_first_entry(&adap->transmit_queue,
+							struct cec_data, list);
+				cec_data_cancel(data);
+			}
+			if (adap->transmitting)
+				cec_data_cancel(adap->transmitting);
+
+			/*
+			 * Cancel the pending timeout work. We have to unlock
+			 * the mutex when flushing the work since
+			 * cec_wait_timeout() will take it. This is OK since
+			 * no new entries can be added to wait_queue as long
+			 * as adap->transmitting is NULL, which it is due to
+			 * the cec_data_cancel() above.
+			 */
+			while (!list_empty(&adap->wait_queue)) {
+				data = list_first_entry(&adap->wait_queue,
+							struct cec_data, list);
+
+				if (!cancel_delayed_work(&data->work)) {
+					mutex_unlock(&adap->lock);
+					flush_scheduled_work();
+					mutex_lock(&adap->lock);
+				}
+				cec_data_cancel(data);
+			}
+			goto unlock;
+		}
+
+		if (adap->transmitting && timeout) {
+			/*
+			 * If we timeout, then log that. This really shouldn't
+			 * happen and is an indication of a faulty CEC adapter
+			 * driver, or the CEC bus is in some weird state.
+			 */
+			dprintk(0, "message %*ph timed out!\n",
+				adap->transmitting->msg.len,
+				adap->transmitting->msg.msg);
+			/* Just give up on this. */
+			cec_data_cancel(adap->transmitting);
+			goto unlock;
+		}
+
+		/*
+		 * If we are still transmitting, or there is nothing new to
+		 * transmit, then just continue waiting.
+		 */
+		if (adap->transmitting || list_empty(&adap->transmit_queue))
+			goto unlock;
+
+		/* Get a new message to transmit */
+		data = list_first_entry(&adap->transmit_queue,
+					struct cec_data, list);
+		list_del_init(&data->list);
+		adap->transmit_queue_sz--;
+		/* Make this the current transmitting message */
+		adap->transmitting = data;
+
+		/*
+		 * Suggested number of attempts as per the CEC 2.0 spec:
+		 * 4 attempts is the default, except for 'secondary poll
+		 * messages', i.e. poll messages not sent during the adapter
+		 * configuration phase when it allocates logical addresses.
+		 */
+		if (data->msg.len == 1 && adap->is_configured)
+			attempts = 2;
+		else
+			attempts = 4;
+
+		/* Set the suggested signal free time */
+		if (data->attempts) {
+			/* should be >= 3 data bit periods for a retry */
+			signal_free_time = CEC_SIGNAL_FREE_TIME_RETRY;
+		} else if (data->new_initiator) {
+			/* should be >= 5 data bit periods for new initiator */
+			signal_free_time = CEC_SIGNAL_FREE_TIME_NEW_INITIATOR;
+		} else {
+			/*
+			 * should be >= 7 data bit periods for sending another
+			 * frame immediately after another.
+			 */
+			signal_free_time = CEC_SIGNAL_FREE_TIME_NEXT_XFER;
+		}
+		if (data->attempts == 0)
+			data->attempts = attempts;
+
+		/* Tell the adapter to transmit, cancel on error */
+		if (adap->ops->adap_transmit(adap, data->attempts,
+					     signal_free_time, &data->msg))
+			cec_data_cancel(data);
+
+unlock:
+		mutex_unlock(&adap->lock);
+
+		if (kthread_should_stop())
+			break;
+	}
+	return 0;
+}
+
+/*
+ * Called by the CEC adapter if a transmit finished.
+ */
+void cec_transmit_done(struct cec_adapter *adap, u8 status, u8 arb_lost_cnt,
+		       u8 nack_cnt, u8 low_drive_cnt, u8 error_cnt)
+{
+	struct cec_data *data;
+	struct cec_msg *msg;
+	u64 ts = ktime_get_ns();
+
+	dprintk(2, "cec_transmit_done %02x\n", status);
+	mutex_lock(&adap->lock);
+	data = adap->transmitting;
+	if (!data) {
+		/*
+		 * This can happen if a transmit was issued and the cable is
+		 * unplugged while the transmit is ongoing. Ignore this
+		 * transmit in that case.
+		 */
+		dprintk(1, "cec_transmit_done without an ongoing transmit!\n");
+		goto unlock;
+	}
+
+	msg = &data->msg;
+
+	/* Drivers must fill in the status! */
+	WARN_ON(status == 0);
+	msg->tx_ts = ts;
+	msg->tx_status |= status;
+	msg->tx_arb_lost_cnt += arb_lost_cnt;
+	msg->tx_nack_cnt += nack_cnt;
+	msg->tx_low_drive_cnt += low_drive_cnt;
+	msg->tx_error_cnt += error_cnt;
+
+	/* Mark that we're done with this transmit */
+	adap->transmitting = NULL;
+
+	/*
+	 * If there are still retry attempts left and there was an error and
+	 * the hardware didn't signal that it retried itself (by setting
+	 * CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves.
+	 */
+	if (data->attempts > 1 &&
+	    !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) {
+		/* Retry this message */
+		data->attempts--;
+		/* Add the message in front of the transmit queue */
+		list_add(&data->list, &adap->transmit_queue);
+		adap->transmit_queue_sz++;
+		goto wake_thread;
+	}
+
+	data->attempts = 0;
+
+	/* Always set CEC_TX_STATUS_MAX_RETRIES on error */
+	if (!(status & CEC_TX_STATUS_OK))
+		msg->tx_status |= CEC_TX_STATUS_MAX_RETRIES;
+
+	/* Queue transmitted message for monitoring purposes */
+	cec_queue_msg_monitor(adap, msg, 1);
+
+	if ((status & CEC_TX_STATUS_OK) && adap->is_configured &&
+	    msg->timeout) {
+		/*
+		 * Queue the message into the wait queue if we want to wait
+		 * for a reply.
+		 */
+		list_add_tail(&data->list, &adap->wait_queue);
+		schedule_delayed_work(&data->work,
+				      msecs_to_jiffies(msg->timeout));
+	} else {
+		/* Otherwise we're done */
+		cec_data_completed(data);
+	}
+
+wake_thread:
+	/*
+	 * Wake up the main thread to see if another message is ready
+	 * for transmitting or to retry the current message.
+	 */
+	wake_up_interruptible(&adap->kthread_waitq);
+unlock:
+	mutex_unlock(&adap->lock);
+}
+EXPORT_SYMBOL_GPL(cec_transmit_done);
+
+/*
+ * Called when waiting for a reply times out.
+ */
+static void cec_wait_timeout(struct work_struct *work)
+{
+	struct cec_data *data = container_of(work, struct cec_data, work.work);
+	struct cec_adapter *adap = data->adap;
+
+	mutex_lock(&adap->lock);
+	/*
+	 * Sanity check in case the timeout and the arrival of the message
+	 * happened at the same time.
+	 */
+	if (list_empty(&data->list))
+		goto unlock;
+
+	/* Mark the message as timed out */
+	list_del_init(&data->list);
+	data->msg.rx_ts = ktime_get_ns();
+	data->msg.rx_status = CEC_RX_STATUS_TIMEOUT;
+	cec_data_completed(data);
+unlock:
+	mutex_unlock(&adap->lock);
+}
+
+/*
+ * Transmit a message. The fh argument may be NULL if the transmit is not
+ * associated with a specific filehandle.
+ *
+ * This function is called with adap->lock held.
+ */
+int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
+			struct cec_fh *fh, bool block)
+{
+	struct cec_data *data;
+	u8 last_initiator = 0xff;
+	unsigned int timeout;
+	int res = 0;
+
+	msg->rx_ts = 0;
+	msg->tx_ts = 0;
+	msg->rx_status = 0;
+	msg->tx_status = 0;
+	msg->tx_arb_lost_cnt = 0;
+	msg->tx_nack_cnt = 0;
+	msg->tx_low_drive_cnt = 0;
+	msg->tx_error_cnt = 0;
+	msg->sequence = ++adap->sequence;
+	if (!msg->sequence)
+		msg->sequence = ++adap->sequence;
+
+	if (msg->reply && msg->timeout == 0) {
+		/* Make sure the timeout isn't 0. */
+		msg->timeout = 1000;
+	}
+	if (msg->timeout)
+		msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS;
+	else
+		msg->flags = 0;
+
+	/* Sanity checks */
+	if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) {
+		dprintk(1, "cec_transmit_msg: invalid length %d\n", msg->len);
+		return -EINVAL;
+	}
+	if (msg->timeout && msg->len == 1) {
+		dprintk(1, "cec_transmit_msg: can't reply for poll msg\n");
+		return -EINVAL;
+	}
+	memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len);
+	if (msg->len == 1) {
+		if (cec_msg_initiator(msg) != 0xf ||
+		    cec_msg_destination(msg) == 0xf) {
+			dprintk(1, "cec_transmit_msg: invalid poll message\n");
+			return -EINVAL;
+		}
+		if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
+			/*
+			 * If the destination is a logical address our adapter
+			 * has already claimed, then just NACK this.
+			 * It depends on the hardware what it will do with a
+			 * POLL to itself (some OK this), so it is just as
+			 * easy to handle it here so the behavior will be
+			 * consistent.
+			 */
+			msg->tx_ts = ktime_get_ns();
+			msg->tx_status = CEC_TX_STATUS_NACK |
+					 CEC_TX_STATUS_MAX_RETRIES;
+			msg->tx_nack_cnt = 1;
+			return 0;
+		}
+	}
+	if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
+	    cec_has_log_addr(adap, cec_msg_destination(msg))) {
+		dprintk(1, "cec_transmit_msg: destination is the adapter itself\n");
+		return -EINVAL;
+	}
+	if (cec_msg_initiator(msg) != 0xf &&
+	    !cec_has_log_addr(adap, cec_msg_initiator(msg))) {
+		dprintk(1, "cec_transmit_msg: initiator has unknown logical address %d\n",
+			cec_msg_initiator(msg));
+		return -EINVAL;
+	}
+	if (!adap->is_configured && !adap->is_configuring)
+		return -ENONET;
+
+	if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ)
+		return -EBUSY;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	if (msg->len > 1 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
+		msg->msg[2] = adap->phys_addr >> 8;
+		msg->msg[3] = adap->phys_addr & 0xff;
+	}
+
+	if (msg->timeout)
+		dprintk(2, "cec_transmit_msg: %*ph (wait for 0x%02x%s)\n",
+			msg->len, msg->msg, msg->reply, !block ? ", nb" : "");
+	else
+		dprintk(2, "cec_transmit_msg: %*ph%s\n",
+			msg->len, msg->msg, !block ? " (nb)" : "");
+
+	data->msg = *msg;
+	data->fh = fh;
+	data->adap = adap;
+	data->blocking = block;
+
+	/*
+	 * Determine if this message follows a message from the same
+	 * initiator. Needed to determine the free signal time later on.
+	 */
+	if (msg->len > 1) {
+		if (!(list_empty(&adap->transmit_queue))) {
+			const struct cec_data *last;
+
+			last = list_last_entry(&adap->transmit_queue,
+					       const struct cec_data, list);
+			last_initiator = cec_msg_initiator(&last->msg);
+		} else if (adap->transmitting) {
+			last_initiator =
+				cec_msg_initiator(&adap->transmitting->msg);
+		}
+	}
+	data->new_initiator = last_initiator != cec_msg_initiator(msg);
+	init_completion(&data->c);
+	INIT_DELAYED_WORK(&data->work, cec_wait_timeout);
+
+	if (fh)
+		list_add_tail(&data->xfer_list, &fh->xfer_list);
+	list_add_tail(&data->list, &adap->transmit_queue);
+	adap->transmit_queue_sz++;
+	if (!adap->transmitting)
+		wake_up_interruptible(&adap->kthread_waitq);
+
+	/* All done if we don't need to block waiting for completion */
+	if (!block)
+		return 0;
+
+	/*
+	 * If we don't get a completion before this time something is really
+	 * wrong and we time out.
+	 */
+	timeout = CEC_XFER_TIMEOUT_MS;
+	/* Add the requested timeout if we have to wait for a reply as well */
+	if (msg->timeout)
+		timeout += msg->timeout;
+
+	/*
+	 * Release the lock and wait, retake the lock afterwards.
+	 */
+	mutex_unlock(&adap->lock);
+	res = wait_for_completion_killable_timeout(&data->c,
+						   msecs_to_jiffies(timeout));
+	mutex_lock(&adap->lock);
+
+	if (data->completed) {
+		/* The transmit completed (possibly with an error) */
+		*msg = data->msg;
+		kfree(data);
+		return 0;
+	}
+	/*
+	 * The wait for completion timed out or was interrupted, so mark this
+	 * as non-blocking and disconnect from the filehandle since it is
+	 * still 'in flight'. When it finally completes it will just drop the
+	 * result silently.
+	 */
+	data->blocking = false;
+	if (data->fh)
+		list_del(&data->xfer_list);
+	data->fh = NULL;
+
+	if (res == 0) { /* timed out */
+		/* Check if the reply or the transmit failed */
+		if (msg->timeout && (msg->tx_status & CEC_TX_STATUS_OK))
+			msg->rx_status = CEC_RX_STATUS_TIMEOUT;
+		else
+			msg->tx_status = CEC_TX_STATUS_MAX_RETRIES;
+	}
+	return res > 0 ? 0 : res;
+}
+
+/* Helper function to be used by drivers and this framework. */
+int cec_transmit_msg(struct cec_adapter *adap, struct cec_msg *msg,
+		     bool block)
+{
+	int ret;
+
+	mutex_lock(&adap->lock);
+	ret = cec_transmit_msg_fh(adap, msg, NULL, block);
+	mutex_unlock(&adap->lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cec_transmit_msg);
+
+/*
+ * I don't like forward references but without this the low-level
+ * cec_received_msg() function would come after a bunch of high-level
+ * CEC protocol handling functions. That was very confusing.
+ */
+static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
+			      bool is_reply);
+
+#define DIRECTED	0x80
+#define BCAST1_4	0x40
+#define BCAST2_0	0x20	/* broadcast only allowed for >= 2.0 */
+#define BCAST		(BCAST1_4 | BCAST2_0)
+#define BOTH		(BCAST | DIRECTED)
+
+/*
+ * Specify minimum length and whether the message is directed, broadcast
+ * or both. Messages that do not match the criteria are ignored as per
+ * the CEC specification.
+ */
+static const u8 cec_msg_size[256] = {
+	[CEC_MSG_ACTIVE_SOURCE] = 4 | BCAST,
+	[CEC_MSG_IMAGE_VIEW_ON] = 2 | DIRECTED,
+	[CEC_MSG_TEXT_VIEW_ON] = 2 | DIRECTED,
+	[CEC_MSG_INACTIVE_SOURCE] = 4 | DIRECTED,
+	[CEC_MSG_REQUEST_ACTIVE_SOURCE] = 2 | BCAST,
+	[CEC_MSG_ROUTING_CHANGE] = 6 | BCAST,
+	[CEC_MSG_ROUTING_INFORMATION] = 4 | BCAST,
+	[CEC_MSG_SET_STREAM_PATH] = 4 | BCAST,
+	[CEC_MSG_STANDBY] = 2 | BOTH,
+	[CEC_MSG_RECORD_OFF] = 2 | DIRECTED,
+	[CEC_MSG_RECORD_ON] = 3 | DIRECTED,
+	[CEC_MSG_RECORD_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_RECORD_TV_SCREEN] = 2 | DIRECTED,
+	[CEC_MSG_CLEAR_ANALOGUE_TIMER] = 13 | DIRECTED,
+	[CEC_MSG_CLEAR_DIGITAL_TIMER] = 16 | DIRECTED,
+	[CEC_MSG_CLEAR_EXT_TIMER] = 13 | DIRECTED,
+	[CEC_MSG_SET_ANALOGUE_TIMER] = 13 | DIRECTED,
+	[CEC_MSG_SET_DIGITAL_TIMER] = 16 | DIRECTED,
+	[CEC_MSG_SET_EXT_TIMER] = 13 | DIRECTED,
+	[CEC_MSG_SET_TIMER_PROGRAM_TITLE] = 2 | DIRECTED,
+	[CEC_MSG_TIMER_CLEARED_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_TIMER_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_CEC_VERSION] = 3 | DIRECTED,
+	[CEC_MSG_GET_CEC_VERSION] = 2 | DIRECTED,
+	[CEC_MSG_GIVE_PHYSICAL_ADDR] = 2 | DIRECTED,
+	[CEC_MSG_GET_MENU_LANGUAGE] = 2 | DIRECTED,
+	[CEC_MSG_REPORT_PHYSICAL_ADDR] = 5 | BCAST,
+	[CEC_MSG_SET_MENU_LANGUAGE] = 5 | BCAST,
+	[CEC_MSG_REPORT_FEATURES] = 6 | BCAST,
+	[CEC_MSG_GIVE_FEATURES] = 2 | DIRECTED,
+	[CEC_MSG_DECK_CONTROL] = 3 | DIRECTED,
+	[CEC_MSG_DECK_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_GIVE_DECK_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_PLAY] = 3 | DIRECTED,
+	[CEC_MSG_GIVE_TUNER_DEVICE_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_SELECT_ANALOGUE_SERVICE] = 6 | DIRECTED,
+	[CEC_MSG_SELECT_DIGITAL_SERVICE] = 9 | DIRECTED,
+	[CEC_MSG_TUNER_DEVICE_STATUS] = 7 | DIRECTED,
+	[CEC_MSG_TUNER_STEP_DECREMENT] = 2 | DIRECTED,
+	[CEC_MSG_TUNER_STEP_INCREMENT] = 2 | DIRECTED,
+	[CEC_MSG_DEVICE_VENDOR_ID] = 5 | BCAST,
+	[CEC_MSG_GIVE_DEVICE_VENDOR_ID] = 2 | DIRECTED,
+	[CEC_MSG_VENDOR_COMMAND] = 2 | DIRECTED,
+	[CEC_MSG_VENDOR_COMMAND_WITH_ID] = 5 | BOTH,
+	[CEC_MSG_VENDOR_REMOTE_BUTTON_DOWN] = 2 | BOTH,
+	[CEC_MSG_VENDOR_REMOTE_BUTTON_UP] = 2 | BOTH,
+	[CEC_MSG_SET_OSD_STRING] = 3 | DIRECTED,
+	[CEC_MSG_GIVE_OSD_NAME] = 2 | DIRECTED,
+	[CEC_MSG_SET_OSD_NAME] = 2 | DIRECTED,
+	[CEC_MSG_MENU_REQUEST] = 3 | DIRECTED,
+	[CEC_MSG_MENU_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_USER_CONTROL_PRESSED] = 3 | DIRECTED,
+	[CEC_MSG_USER_CONTROL_RELEASED] = 2 | DIRECTED,
+	[CEC_MSG_GIVE_DEVICE_POWER_STATUS] = 2 | DIRECTED,
+	[CEC_MSG_REPORT_POWER_STATUS] = 3 | DIRECTED | BCAST2_0,
+	[CEC_MSG_FEATURE_ABORT] = 4 | DIRECTED,
+	[CEC_MSG_ABORT] = 2 | DIRECTED,
+	[CEC_MSG_GIVE_AUDIO_STATUS] = 2 | DIRECTED,
+	[CEC_MSG_GIVE_SYSTEM_AUDIO_MODE_STATUS] = 2 | DIRECTED,
+	[CEC_MSG_REPORT_AUDIO_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_REPORT_SHORT_AUDIO_DESCRIPTOR] = 2 | DIRECTED,
+	[CEC_MSG_REQUEST_SHORT_AUDIO_DESCRIPTOR] = 2 | DIRECTED,
+	[CEC_MSG_SET_SYSTEM_AUDIO_MODE] = 3 | BOTH,
+	[CEC_MSG_SYSTEM_AUDIO_MODE_REQUEST] = 2 | DIRECTED,
+	[CEC_MSG_SYSTEM_AUDIO_MODE_STATUS] = 3 | DIRECTED,
+	[CEC_MSG_SET_AUDIO_RATE] = 3 | DIRECTED,
+	[CEC_MSG_INITIATE_ARC] = 2 | DIRECTED,
+	[CEC_MSG_REPORT_ARC_INITIATED] = 2 | DIRECTED,
+	[CEC_MSG_REPORT_ARC_TERMINATED] = 2 | DIRECTED,
+	[CEC_MSG_REQUEST_ARC_INITIATION] = 2 | DIRECTED,
+	[CEC_MSG_REQUEST_ARC_TERMINATION] = 2 | DIRECTED,
+	[CEC_MSG_TERMINATE_ARC] = 2 | DIRECTED,
+	[CEC_MSG_REQUEST_CURRENT_LATENCY] = 4 | BCAST,
+	[CEC_MSG_REPORT_CURRENT_LATENCY] = 6 | BCAST,
+	[CEC_MSG_CDC_MESSAGE] = 2 | BCAST,
+};
+
+/* Called by the CEC adapter if a message is received */
+void cec_received_msg(struct cec_adapter *adap, struct cec_msg *msg)
+{
+	struct cec_data *data;
+	u8 msg_init = cec_msg_initiator(msg);
+	u8 msg_dest = cec_msg_destination(msg);
+	u8 cmd = msg->msg[1];
+	bool is_reply = false;
+	bool valid_la = true;
+	u8 min_len = 0;
+
+	if (WARN_ON(!msg->len || msg->len > CEC_MAX_MSG_SIZE))
+		return;
+
+	/*
+	 * Some CEC adapters will receive the messages that they transmitted.
+	 * This test filters out those messages by checking if we are the
+	 * initiator, and just returning in that case.
+	 *
+	 * Note that this won't work if this is an Unregistered device.
+	 *
+	 * It is bad practice if the hardware receives the message that it
+	 * transmitted and luckily most CEC adapters behave correctly in this
+	 * respect.
+	 */
+	if (msg_init != CEC_LOG_ADDR_UNREGISTERED &&
+	    cec_has_log_addr(adap, msg_init))
+		return;
+
+	msg->rx_ts = ktime_get_ns();
+	msg->rx_status = CEC_RX_STATUS_OK;
+	msg->sequence = msg->reply = msg->timeout = 0;
+	msg->tx_status = 0;
+	msg->tx_ts = 0;
+	msg->tx_arb_lost_cnt = 0;
+	msg->tx_nack_cnt = 0;
+	msg->tx_low_drive_cnt = 0;
+	msg->tx_error_cnt = 0;
+	msg->flags = 0;
+	memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len);
+
+	mutex_lock(&adap->lock);
+	dprintk(2, "cec_received_msg: %*ph\n", msg->len, msg->msg);
+
+	/* Check if this message was for us (directed or broadcast). */
+	if (!cec_msg_is_broadcast(msg))
+		valid_la = cec_has_log_addr(adap, msg_dest);
+
+	/*
+	 * Check if the length is not too short or if the message is a
+	 * broadcast message where a directed message was expected or
+	 * vice versa. If so, then the message has to be ignored (according
+	 * to section CEC 7.3 and CEC 12.2).
+	 */
+	if (valid_la && msg->len > 1 && cec_msg_size[cmd]) {
+		u8 dir_fl = cec_msg_size[cmd] & BOTH;
+
+		min_len = cec_msg_size[cmd] & 0x1f;
+		if (msg->len < min_len)
+			valid_la = false;
+		else if (!cec_msg_is_broadcast(msg) && !(dir_fl & DIRECTED))
+			valid_la = false;
+		else if (cec_msg_is_broadcast(msg) && !(dir_fl & BCAST1_4))
+			valid_la = false;
+		else if (cec_msg_is_broadcast(msg) &&
+			 adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0 &&
+			 !(dir_fl & BCAST2_0))
+			valid_la = false;
+	}
+	if (valid_la && min_len) {
+		/* These messages have special length requirements */
+		switch (cmd) {
+		case CEC_MSG_TIMER_STATUS:
+			if (msg->msg[2] & 0x10) {
+				switch (msg->msg[2] & 0xf) {
+				case CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE:
+				case CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE:
+					if (msg->len < 5)
+						valid_la = false;
+					break;
+				}
+			} else if ((msg->msg[2] & 0xf) == CEC_OP_PROG_ERROR_DUPLICATE) {
+				if (msg->len < 5)
+					valid_la = false;
+			}
+			break;
+		case CEC_MSG_RECORD_ON:
+			switch (msg->msg[2]) {
+			case CEC_OP_RECORD_SRC_OWN:
+				break;
+			case CEC_OP_RECORD_SRC_DIGITAL:
+				if (msg->len < 10)
+					valid_la = false;
+				break;
+			case CEC_OP_RECORD_SRC_ANALOG:
+				if (msg->len < 7)
+					valid_la = false;
+				break;
+			case CEC_OP_RECORD_SRC_EXT_PLUG:
+				if (msg->len < 4)
+					valid_la = false;
+				break;
+			case CEC_OP_RECORD_SRC_EXT_PHYS_ADDR:
+				if (msg->len < 5)
+					valid_la = false;
+				break;
+			}
+			break;
+		}
+	}
+
+	/* It's a valid message and not a poll or CDC message */
+	if (valid_la && msg->len > 1 && cmd != CEC_MSG_CDC_MESSAGE) {
+		bool abort = cmd == CEC_MSG_FEATURE_ABORT;
+
+		/* The aborted command is in msg[2] */
+		if (abort)
+			cmd = msg->msg[2];
+
+		/*
+		 * Walk over all transmitted messages that are waiting for a
+		 * reply.
+		 */
+		list_for_each_entry(data, &adap->wait_queue, list) {
+			struct cec_msg *dst = &data->msg;
+
+			/*
+			 * The *only* CEC message that has two possible replies
+			 * is CEC_MSG_INITIATE_ARC.
+			 * In this case allow either of the two replies.
+			 */
+			if (!abort && dst->msg[1] == CEC_MSG_INITIATE_ARC &&
+			    (cmd == CEC_MSG_REPORT_ARC_INITIATED ||
+			     cmd == CEC_MSG_REPORT_ARC_TERMINATED) &&
+			    (dst->reply == CEC_MSG_REPORT_ARC_INITIATED ||
+			     dst->reply == CEC_MSG_REPORT_ARC_TERMINATED))
+				dst->reply = cmd;
+
+			/* Does the command match? */
+			if ((abort && cmd != dst->msg[1]) ||
+			    (!abort && cmd != dst->reply))
+				continue;
+
+			/* Does the addressing match? */
+			if (msg_init != cec_msg_destination(dst) &&
+			    !cec_msg_is_broadcast(dst))
+				continue;
+
+			/* We got a reply */
+			memcpy(dst->msg, msg->msg, msg->len);
+			dst->len = msg->len;
+			dst->rx_ts = msg->rx_ts;
+			dst->rx_status = msg->rx_status;
+			if (abort)
+				dst->rx_status |= CEC_RX_STATUS_FEATURE_ABORT;
+			msg->flags = dst->flags;
+			/* Remove it from the wait_queue */
+			list_del_init(&data->list);
+
+			/* Cancel the pending timeout work */
+			if (!cancel_delayed_work(&data->work)) {
+				mutex_unlock(&adap->lock);
+				flush_scheduled_work();
+				mutex_lock(&adap->lock);
+			}
+			/*
+			 * Mark this as a reply, provided someone is still
+			 * waiting for the answer.
+			 */
+			if (data->fh)
+				is_reply = true;
+			cec_data_completed(data);
+			break;
+		}
+	}
+	mutex_unlock(&adap->lock);
+
+	/* Pass the message on to any monitoring filehandles */
+	cec_queue_msg_monitor(adap, msg, valid_la);
+
+	/* We're done if it is not for us or a poll message */
+	if (!valid_la || msg->len <= 1)
+		return;
+
+	if (adap->log_addrs.log_addr_mask == 0)
+		return;
+
+	/*
+	 * Process the message on the protocol level. If is_reply is true,
+	 * then cec_receive_notify() won't pass on the reply to the listener(s)
+	 * since that was already done by cec_data_completed() above.
+	 */
+	cec_receive_notify(adap, msg, is_reply);
+}
+EXPORT_SYMBOL_GPL(cec_received_msg);
+
+/* Logical Address Handling */
+
+/*
+ * Attempt to claim a specific logical address.
+ *
+ * This function is called with adap->lock held.
+ */
+static int cec_config_log_addr(struct cec_adapter *adap,
+			       unsigned int idx,
+			       unsigned int log_addr)
+{
+	struct cec_log_addrs *las = &adap->log_addrs;
+	struct cec_msg msg = { };
+	int err;
+
+	if (cec_has_log_addr(adap, log_addr))
+		return 0;
+
+	/* Send poll message */
+	msg.len = 1;
+	msg.msg[0] = 0xf0 | log_addr;
+	err = cec_transmit_msg_fh(adap, &msg, NULL, true);
+
+	/*
+	 * While trying to poll the physical address was reset
+	 * and the adapter was unconfigured, so bail out.
+	 */
+	if (!adap->is_configuring)
+		return -EINTR;
+
+	if (err)
+		return err;
+
+	if (msg.tx_status & CEC_TX_STATUS_OK)
+		return 0;
+
+	/*
+	 * Message not acknowledged, so this logical
+	 * address is free to use.
+	 */
+	err = adap->ops->adap_log_addr(adap, log_addr);
+	if (err)
+		return err;
+
+	las->log_addr[idx] = log_addr;
+	las->log_addr_mask |= 1 << log_addr;
+	adap->phys_addrs[log_addr] = adap->phys_addr;
+
+	dprintk(2, "claimed addr %d (%d)\n", log_addr,
+		las->primary_device_type[idx]);
+	return 1;
+}
+
+/*
+ * Unconfigure the adapter: clear all logical addresses and send
+ * the state changed event.
+ *
+ * This function is called with adap->lock held.
+ */
+static void cec_adap_unconfigure(struct cec_adapter *adap)
+{
+	WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
+	adap->log_addrs.log_addr_mask = 0;
+	adap->is_configuring = false;
+	adap->is_configured = false;
+	memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
+	wake_up_interruptible(&adap->kthread_waitq);
+	cec_post_state_event(adap);
+}
+
+/*
+ * Attempt to claim the required logical addresses.
+ */
+static int cec_config_thread_func(void *arg)
+{
+	/* The various LAs for each type of device */
+	static const u8 tv_log_addrs[] = {
+		CEC_LOG_ADDR_TV, CEC_LOG_ADDR_SPECIFIC,
+		CEC_LOG_ADDR_INVALID
+	};
+	static const u8 record_log_addrs[] = {
+		CEC_LOG_ADDR_RECORD_1, CEC_LOG_ADDR_RECORD_2,
+		CEC_LOG_ADDR_RECORD_3,
+		CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
+		CEC_LOG_ADDR_INVALID
+	};
+	static const u8 tuner_log_addrs[] = {
+		CEC_LOG_ADDR_TUNER_1, CEC_LOG_ADDR_TUNER_2,
+		CEC_LOG_ADDR_TUNER_3, CEC_LOG_ADDR_TUNER_4,
+		CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
+		CEC_LOG_ADDR_INVALID
+	};
+	static const u8 playback_log_addrs[] = {
+		CEC_LOG_ADDR_PLAYBACK_1, CEC_LOG_ADDR_PLAYBACK_2,
+		CEC_LOG_ADDR_PLAYBACK_3,
+		CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
+		CEC_LOG_ADDR_INVALID
+	};
+	static const u8 audiosystem_log_addrs[] = {
+		CEC_LOG_ADDR_AUDIOSYSTEM,
+		CEC_LOG_ADDR_INVALID
+	};
+	static const u8 specific_use_log_addrs[] = {
+		CEC_LOG_ADDR_SPECIFIC,
+		CEC_LOG_ADDR_BACKUP_1, CEC_LOG_ADDR_BACKUP_2,
+		CEC_LOG_ADDR_INVALID
+	};
+	static const u8 *type2addrs[6] = {
+		[CEC_LOG_ADDR_TYPE_TV] = tv_log_addrs,
+		[CEC_LOG_ADDR_TYPE_RECORD] = record_log_addrs,
+		[CEC_LOG_ADDR_TYPE_TUNER] = tuner_log_addrs,
+		[CEC_LOG_ADDR_TYPE_PLAYBACK] = playback_log_addrs,
+		[CEC_LOG_ADDR_TYPE_AUDIOSYSTEM] = audiosystem_log_addrs,
+		[CEC_LOG_ADDR_TYPE_SPECIFIC] = specific_use_log_addrs,
+	};
+	static const u16 type2mask[] = {
+		[CEC_LOG_ADDR_TYPE_TV] = CEC_LOG_ADDR_MASK_TV,
+		[CEC_LOG_ADDR_TYPE_RECORD] = CEC_LOG_ADDR_MASK_RECORD,
+		[CEC_LOG_ADDR_TYPE_TUNER] = CEC_LOG_ADDR_MASK_TUNER,
+		[CEC_LOG_ADDR_TYPE_PLAYBACK] = CEC_LOG_ADDR_MASK_PLAYBACK,
+		[CEC_LOG_ADDR_TYPE_AUDIOSYSTEM] = CEC_LOG_ADDR_MASK_AUDIOSYSTEM,
+		[CEC_LOG_ADDR_TYPE_SPECIFIC] = CEC_LOG_ADDR_MASK_SPECIFIC,
+	};
+	struct cec_adapter *adap = arg;
+	struct cec_log_addrs *las = &adap->log_addrs;
+	int err;
+	int i, j;
+
+	mutex_lock(&adap->lock);
+	dprintk(1, "physical address: %x.%x.%x.%x, claim %d logical addresses\n",
+		cec_phys_addr_exp(adap->phys_addr), las->num_log_addrs);
+	las->log_addr_mask = 0;
+
+	if (las->log_addr_type[0] == CEC_LOG_ADDR_TYPE_UNREGISTERED)
+		goto configured;
+
+	for (i = 0; i < las->num_log_addrs; i++) {
+		unsigned int type = las->log_addr_type[i];
+		const u8 *la_list;
+		u8 last_la;
+
+		/*
+		 * The TV functionality can only map to physical address 0.
+		 * For any other address, try the Specific functionality
+		 * instead as per the spec.
+		 */
+		if (adap->phys_addr && type == CEC_LOG_ADDR_TYPE_TV)
+			type = CEC_LOG_ADDR_TYPE_SPECIFIC;
+
+		la_list = type2addrs[type];
+		last_la = las->log_addr[i];
+		las->log_addr[i] = CEC_LOG_ADDR_INVALID;
+		if (last_la == CEC_LOG_ADDR_INVALID ||
+		    last_la == CEC_LOG_ADDR_UNREGISTERED ||
+		    !((1 << last_la) & type2mask[type]))
+			last_la = la_list[0];
+
+		err = cec_config_log_addr(adap, i, last_la);
+		if (err > 0) /* Reused last LA */
+			continue;
+
+		if (err < 0)
+			goto unconfigure;
+
+		for (j = 0; la_list[j] != CEC_LOG_ADDR_INVALID; j++) {
+			/* Tried this one already, skip it */
+			if (la_list[j] == last_la)
+				continue;
+			/* The backup addresses are CEC 2.0 specific */
+			if ((la_list[j] == CEC_LOG_ADDR_BACKUP_1 ||
+			     la_list[j] == CEC_LOG_ADDR_BACKUP_2) &&
+			    las->cec_version < CEC_OP_CEC_VERSION_2_0)
+				continue;
+
+			err = cec_config_log_addr(adap, i, la_list[j]);
+			if (err == 0) /* LA is in use */
+				continue;
+			if (err < 0)
+				goto unconfigure;
+			/* Done, claimed an LA */
+			break;
+		}
+
+		if (la_list[j] == CEC_LOG_ADDR_INVALID)
+			dprintk(1, "could not claim LA %d\n", i);
+	}
+
+	if (adap->log_addrs.log_addr_mask == 0 &&
+	    !(las->flags & CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK))
+		goto unconfigure;
+
+configured:
+	if (adap->log_addrs.log_addr_mask == 0) {
+		/* Fall back to unregistered */
+		las->log_addr[0] = CEC_LOG_ADDR_UNREGISTERED;
+		las->log_addr_mask = 1 << las->log_addr[0];
+		for (i = 1; i < las->num_log_addrs; i++)
+			las->log_addr[i] = CEC_LOG_ADDR_INVALID;
+	}
+	for (i = las->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++)
+		las->log_addr[i] = CEC_LOG_ADDR_INVALID;
+	adap->is_configured = true;
+	adap->is_configuring = false;
+	cec_post_state_event(adap);
+
+	/*
+	 * Now post the Report Features and Report Physical Address broadcast
+	 * messages. Note that these are non-blocking transmits, meaning that
+	 * they are just queued up and once adap->lock is unlocked the main
+	 * thread will kick in and start transmitting these.
+	 *
+	 * If after this function is done (but before one or more of these
+	 * messages are actually transmitted) the CEC adapter is unconfigured,
+	 * then any remaining messages will be dropped by the main thread.
+	 */
+	for (i = 0; i < las->num_log_addrs; i++) {
+		struct cec_msg msg = {};
+
+		if (las->log_addr[i] == CEC_LOG_ADDR_INVALID ||
+		    (las->flags & CEC_LOG_ADDRS_FL_CDC_ONLY))
+			continue;
+
+		msg.msg[0] = (las->log_addr[i] << 4) | 0x0f;
+
+		/* Report Features must come first according to CEC 2.0 */
+		if (las->log_addr[i] != CEC_LOG_ADDR_UNREGISTERED &&
+		    adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0) {
+			cec_fill_msg_report_features(adap, &msg, i);
+			cec_transmit_msg_fh(adap, &msg, NULL, false);
+		}
+
+		/* Report Physical Address */
+		cec_msg_report_physical_addr(&msg, adap->phys_addr,
+					     las->primary_device_type[i]);
+		dprintk(2, "config: la %d pa %x.%x.%x.%x\n",
+			las->log_addr[i],
+			cec_phys_addr_exp(adap->phys_addr));
+		cec_transmit_msg_fh(adap, &msg, NULL, false);
+	}
+	adap->kthread_config = NULL;
+	complete(&adap->config_completion);
+	mutex_unlock(&adap->lock);
+	return 0;
+
+unconfigure:
+	for (i = 0; i < las->num_log_addrs; i++)
+		las->log_addr[i] = CEC_LOG_ADDR_INVALID;
+	cec_adap_unconfigure(adap);
+	adap->kthread_config = NULL;
+	mutex_unlock(&adap->lock);
+	complete(&adap->config_completion);
+	return 0;
+}
+
+/*
+ * Called from either __cec_s_phys_addr or __cec_s_log_addrs to claim the
+ * logical addresses.
+ *
+ * This function is called with adap->lock held.
+ */
+static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
+{
+	if (WARN_ON(adap->is_configuring || adap->is_configured))
+		return;
+
+	init_completion(&adap->config_completion);
+
+	/* Ready to kick off the thread */
+	adap->is_configuring = true;
+	adap->kthread_config = kthread_run(cec_config_thread_func, adap,
+					   "ceccfg-%s", adap->name);
+	if (IS_ERR(adap->kthread_config)) {
+		adap->kthread_config = NULL;
+	} else if (block) {
+		mutex_unlock(&adap->lock);
+		wait_for_completion(&adap->config_completion);
+		mutex_lock(&adap->lock);
+	}
+}
+
+/* Set a new physical address and send an event notifying userspace of this.
+ *
+ * This function is called with adap->lock held.
+ */
+void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
+{
+	if (phys_addr == adap->phys_addr || adap->devnode.unregistered)
+		return;
+
+	if (phys_addr == CEC_PHYS_ADDR_INVALID ||
+	    adap->phys_addr != CEC_PHYS_ADDR_INVALID) {
+		adap->phys_addr = CEC_PHYS_ADDR_INVALID;
+		cec_post_state_event(adap);
+		cec_adap_unconfigure(adap);
+		/* Disabling monitor all mode should always succeed */
+		if (adap->monitor_all_cnt)
+			WARN_ON(call_op(adap, adap_monitor_all_enable, false));
+		WARN_ON(adap->ops->adap_enable(adap, false));
+		if (phys_addr == CEC_PHYS_ADDR_INVALID)
+			return;
+	}
+
+	if (adap->ops->adap_enable(adap, true))
+		return;
+
+	if (adap->monitor_all_cnt &&
+	    call_op(adap, adap_monitor_all_enable, true)) {
+		WARN_ON(adap->ops->adap_enable(adap, false));
+		return;
+	}
+	adap->phys_addr = phys_addr;
+	cec_post_state_event(adap);
+	if (adap->log_addrs.num_log_addrs)
+		cec_claim_log_addrs(adap, block);
+}
+
+void cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
+{
+	if (IS_ERR_OR_NULL(adap))
+		return;
+
+	mutex_lock(&adap->lock);
+	__cec_s_phys_addr(adap, phys_addr, block);
+	mutex_unlock(&adap->lock);
+}
+EXPORT_SYMBOL_GPL(cec_s_phys_addr);
+
+/*
+ * Called from either the ioctl or a driver to set the logical addresses.
+ *
+ * This function is called with adap->lock held.
+ */
+int __cec_s_log_addrs(struct cec_adapter *adap,
+		      struct cec_log_addrs *log_addrs, bool block)
+{
+	u16 type_mask = 0;
+	int i;
+
+	if (adap->devnode.unregistered)
+		return -ENODEV;
+
+	if (!log_addrs || log_addrs->num_log_addrs == 0) {
+		adap->log_addrs.num_log_addrs = 0;
+		cec_adap_unconfigure(adap);
+		return 0;
+	}
+
+	if (log_addrs->flags & CEC_LOG_ADDRS_FL_CDC_ONLY) {
+		/*
+		 * Sanitize log_addrs fields if a CDC-Only device is
+		 * requested.
+		 */
+		log_addrs->num_log_addrs = 1;
+		log_addrs->osd_name[0] = '\0';
+		log_addrs->vendor_id = CEC_VENDOR_ID_NONE;
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
+		/*
+		 * This is just an internal convention since a CDC-Only device
+		 * doesn't have to be a switch. But switches already use
+		 * unregistered, so it makes some kind of sense to pick this
+		 * as the primary device. Since a CDC-Only device never sends
+		 * any 'normal' CEC messages this primary device type is never
+		 * sent over the CEC bus.
+		 */
+		log_addrs->primary_device_type[0] = CEC_OP_PRIM_DEVTYPE_SWITCH;
+		log_addrs->all_device_types[0] = 0;
+		log_addrs->features[0][0] = 0;
+		log_addrs->features[0][1] = 0;
+	}
+
+	/* Ensure the osd name is 0-terminated */
+	log_addrs->osd_name[sizeof(log_addrs->osd_name) - 1] = '\0';
+
+	/* Sanity checks */
+	if (log_addrs->num_log_addrs > adap->available_log_addrs) {
+		dprintk(1, "num_log_addrs > %d\n", adap->available_log_addrs);
+		return -EINVAL;
+	}
+
+	/*
+	 * Vendor ID is a 24 bit number, so check if the value is
+	 * within the correct range.
+	 */
+	if (log_addrs->vendor_id != CEC_VENDOR_ID_NONE &&
+	    (log_addrs->vendor_id & 0xff000000) != 0)
+		return -EINVAL;
+
+	if (log_addrs->cec_version != CEC_OP_CEC_VERSION_1_4 &&
+	    log_addrs->cec_version != CEC_OP_CEC_VERSION_2_0)
+		return -EINVAL;
+
+	if (log_addrs->num_log_addrs > 1)
+		for (i = 0; i < log_addrs->num_log_addrs; i++)
+			if (log_addrs->log_addr_type[i] ==
+					CEC_LOG_ADDR_TYPE_UNREGISTERED) {
+				dprintk(1, "num_log_addrs > 1 can't be combined with unregistered LA\n");
+				return -EINVAL;
+			}
+
+	for (i = 0; i < log_addrs->num_log_addrs; i++) {
+		const u8 feature_sz = ARRAY_SIZE(log_addrs->features[0]);
+		u8 *features = log_addrs->features[i];
+		bool op_is_dev_features = false;
+		unsigned j;
+
+		log_addrs->log_addr[i] = CEC_LOG_ADDR_INVALID;
+		if (type_mask & (1 << log_addrs->log_addr_type[i])) {
+			dprintk(1, "duplicate logical address type\n");
+			return -EINVAL;
+		}
+		type_mask |= 1 << log_addrs->log_addr_type[i];
+		if ((type_mask & (1 << CEC_LOG_ADDR_TYPE_RECORD)) &&
+		    (type_mask & (1 << CEC_LOG_ADDR_TYPE_PLAYBACK))) {
+			/* Record already contains the playback functionality */
+			dprintk(1, "invalid record + playback combination\n");
+			return -EINVAL;
+		}
+		if (log_addrs->primary_device_type[i] >
+					CEC_OP_PRIM_DEVTYPE_PROCESSOR) {
+			dprintk(1, "unknown primary device type\n");
+			return -EINVAL;
+		}
+		if (log_addrs->primary_device_type[i] == 2) {
+			dprintk(1, "invalid primary device type\n");
+			return -EINVAL;
+		}
+		if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) {
+			dprintk(1, "unknown logical address type\n");
+			return -EINVAL;
+		}
+		for (j = 0; j < feature_sz; j++) {
+			if ((features[j] & 0x80) == 0) {
+				if (op_is_dev_features)
+					break;
+				op_is_dev_features = true;
+			}
+		}
+		if (!op_is_dev_features || j == feature_sz) {
+			dprintk(1, "malformed features\n");
+			return -EINVAL;
+		}
+		/* Zero unused part of the feature array */
+		memset(features + j + 1, 0, feature_sz - j - 1);
+	}
+
+	if (log_addrs->cec_version >= CEC_OP_CEC_VERSION_2_0) {
+		if (log_addrs->num_log_addrs > 2) {
+			dprintk(1, "CEC 2.0 allows no more than 2 logical addresses\n");
+			return -EINVAL;
+		}
+		if (log_addrs->num_log_addrs == 2) {
+			if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_AUDIOSYSTEM) |
+					   (1 << CEC_LOG_ADDR_TYPE_TV)))) {
+				dprintk(1, "Two LAs is only allowed for audiosystem and TV\n");
+				return -EINVAL;
+			}
+			if (!(type_mask & ((1 << CEC_LOG_ADDR_TYPE_PLAYBACK) |
+					   (1 << CEC_LOG_ADDR_TYPE_RECORD)))) {
+				dprintk(1, "An audiosystem/TV can only be combined with record or playback\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* Zero unused LAs */
+	for (i = log_addrs->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++) {
+		log_addrs->primary_device_type[i] = 0;
+		log_addrs->log_addr_type[i] = 0;
+		log_addrs->all_device_types[i] = 0;
+		memset(log_addrs->features[i], 0,
+		       sizeof(log_addrs->features[i]));
+	}
+
+	log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask;
+	adap->log_addrs = *log_addrs;
+	if (adap->phys_addr != CEC_PHYS_ADDR_INVALID)
+		cec_claim_log_addrs(adap, block);
+	return 0;
+}
+
+int cec_s_log_addrs(struct cec_adapter *adap,
+		    struct cec_log_addrs *log_addrs, bool block)
+{
+	int err;
+
+	mutex_lock(&adap->lock);
+	err = __cec_s_log_addrs(adap, log_addrs, block);
+	mutex_unlock(&adap->lock);
+	return err;
+}
+EXPORT_SYMBOL_GPL(cec_s_log_addrs);
+
+/* High-level core CEC message handling */
+
+/* Fill in the Report Features message */
+static void cec_fill_msg_report_features(struct cec_adapter *adap,
+					 struct cec_msg *msg,
+					 unsigned int la_idx)
+{
+	const struct cec_log_addrs *las = &adap->log_addrs;
+	const u8 *features = las->features[la_idx];
+	bool op_is_dev_features = false;
+	unsigned int idx;
+
+	/* Report Features */
+	msg->msg[0] = (las->log_addr[la_idx] << 4) | 0x0f;
+	msg->len = 4;
+	msg->msg[1] = CEC_MSG_REPORT_FEATURES;
+	msg->msg[2] = adap->log_addrs.cec_version;
+	msg->msg[3] = las->all_device_types[la_idx];
+
+	/* Write RC Profiles first, then Device Features */
+	for (idx = 0; idx < ARRAY_SIZE(las->features[0]); idx++) {
+		msg->msg[msg->len++] = features[idx];
+		if ((features[idx] & CEC_OP_FEAT_EXT) == 0) {
+			if (op_is_dev_features)
+				break;
+			op_is_dev_features = true;
+		}
+	}
+}
+
+/* Transmit the Feature Abort message */
+static int cec_feature_abort_reason(struct cec_adapter *adap,
+				    struct cec_msg *msg, u8 reason)
+{
+	struct cec_msg tx_msg = { };
+
+	/*
+	 * Don't reply with CEC_MSG_FEATURE_ABORT to a CEC_MSG_FEATURE_ABORT
+	 * message!
+	 */
+	if (msg->msg[1] == CEC_MSG_FEATURE_ABORT)
+		return 0;
+	cec_msg_set_reply_to(&tx_msg, msg);
+	cec_msg_feature_abort(&tx_msg, msg->msg[1], reason);
+	return cec_transmit_msg(adap, &tx_msg, false);
+}
+
+static int cec_feature_abort(struct cec_adapter *adap, struct cec_msg *msg)
+{
+	return cec_feature_abort_reason(adap, msg,
+					CEC_OP_ABORT_UNRECOGNIZED_OP);
+}
+
+static int cec_feature_refused(struct cec_adapter *adap, struct cec_msg *msg)
+{
+	return cec_feature_abort_reason(adap, msg,
+					CEC_OP_ABORT_REFUSED);
+}
+
+/*
+ * Called when a CEC message is received. This function will do any
+ * necessary core processing. The is_reply bool is true if this message
+ * is a reply to an earlier transmit.
+ *
+ * The message is either a broadcast message or a valid directed message.
+ */
+static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
+			      bool is_reply)
+{
+	bool is_broadcast = cec_msg_is_broadcast(msg);
+	u8 dest_laddr = cec_msg_destination(msg);
+	u8 init_laddr = cec_msg_initiator(msg);
+	u8 devtype = cec_log_addr2dev(adap, dest_laddr);
+	int la_idx = cec_log_addr2idx(adap, dest_laddr);
+	bool from_unregistered = init_laddr == 0xf;
+	struct cec_msg tx_cec_msg = { };
+
+	dprintk(1, "cec_receive_notify: %*ph\n", msg->len, msg->msg);
+
+	/* If this is a CDC-Only device, then ignore any non-CDC messages */
+	if (cec_is_cdc_only(&adap->log_addrs) &&
+	    msg->msg[1] != CEC_MSG_CDC_MESSAGE)
+		return 0;
+
+	if (adap->ops->received) {
+		/* Allow drivers to process the message first */
+		if (adap->ops->received(adap, msg) != -ENOMSG)
+			return 0;
+	}
+
+	/*
+	 * REPORT_PHYSICAL_ADDR, CEC_MSG_USER_CONTROL_PRESSED and
+	 * CEC_MSG_USER_CONTROL_RELEASED messages always have to be
+	 * handled by the CEC core, even if the passthrough mode is on.
+	 * The others are just ignored if passthrough mode is on.
+	 */
+	switch (msg->msg[1]) {
+	case CEC_MSG_GET_CEC_VERSION:
+	case CEC_MSG_GIVE_DEVICE_VENDOR_ID:
+	case CEC_MSG_ABORT:
+	case CEC_MSG_GIVE_DEVICE_POWER_STATUS:
+	case CEC_MSG_GIVE_PHYSICAL_ADDR:
+	case CEC_MSG_GIVE_OSD_NAME:
+	case CEC_MSG_GIVE_FEATURES:
+		/*
+		 * Skip processing these messages if the passthrough mode
+		 * is on.
+		 */
+		if (adap->passthrough)
+			goto skip_processing;
+		/* Ignore if addressing is wrong */
+		if (is_broadcast || from_unregistered)
+			return 0;
+		break;
+
+	case CEC_MSG_USER_CONTROL_PRESSED:
+	case CEC_MSG_USER_CONTROL_RELEASED:
+		/* Wrong addressing mode: don't process */
+		if (is_broadcast || from_unregistered)
+			goto skip_processing;
+		break;
+
+	case CEC_MSG_REPORT_PHYSICAL_ADDR:
+		/*
+		 * This message is always processed, regardless of the
+		 * passthrough setting.
+		 *
+		 * Exception: don't process if wrong addressing mode.
+		 */
+		if (!is_broadcast)
+			goto skip_processing;
+		break;
+
+	default:
+		break;
+	}
+
+	cec_msg_set_reply_to(&tx_cec_msg, msg);
+
+	switch (msg->msg[1]) {
+	/* The following messages are processed but still passed through */
+	case CEC_MSG_REPORT_PHYSICAL_ADDR: {
+		u16 pa = (msg->msg[2] << 8) | msg->msg[3];
+
+		if (!from_unregistered)
+			adap->phys_addrs[init_laddr] = pa;
+		dprintk(1, "Reported physical address %x.%x.%x.%x for logical address %d\n",
+			cec_phys_addr_exp(pa), init_laddr);
+		break;
+	}
+
+	case CEC_MSG_USER_CONTROL_PRESSED:
+		if (!(adap->capabilities & CEC_CAP_RC) ||
+		    !(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU))
+			break;
+
+#if IS_REACHABLE(CONFIG_RC_CORE)
+		switch (msg->msg[2]) {
+		/*
+		 * Play function, this message can have variable length
+		 * depending on the specific play function that is used.
+		 */
+		case 0x60:
+			if (msg->len == 2)
+				rc_keydown(adap->rc, RC_TYPE_CEC,
+					   msg->msg[2], 0);
+			else
+				rc_keydown(adap->rc, RC_TYPE_CEC,
+					   msg->msg[2] << 8 | msg->msg[3], 0);
+			break;
+		/*
+		 * Other function messages that are not handled.
+		 * Currently the RC framework does not allow to supply an
+		 * additional parameter to a keypress. These "keys" contain
+		 * other information such as channel number, an input number
+		 * etc.
+		 * For the time being these messages are not processed by the
+		 * framework and are simply forwarded to the user space.
+		 */
+		case 0x56: case 0x57:
+		case 0x67: case 0x68: case 0x69: case 0x6a:
+			break;
+		default:
+			rc_keydown(adap->rc, RC_TYPE_CEC, msg->msg[2], 0);
+			break;
+		}
+#endif
+		break;
+
+	case CEC_MSG_USER_CONTROL_RELEASED:
+		if (!(adap->capabilities & CEC_CAP_RC) ||
+		    !(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU))
+			break;
+#if IS_REACHABLE(CONFIG_RC_CORE)
+		rc_keyup(adap->rc);
+#endif
+		break;
+
+	/*
+	 * The remaining messages are only processed if the passthrough mode
+	 * is off.
+	 */
+	case CEC_MSG_GET_CEC_VERSION:
+		cec_msg_cec_version(&tx_cec_msg, adap->log_addrs.cec_version);
+		return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+	case CEC_MSG_GIVE_PHYSICAL_ADDR:
+		/* Do nothing for CEC switches using addr 15 */
+		if (devtype == CEC_OP_PRIM_DEVTYPE_SWITCH && dest_laddr == 15)
+			return 0;
+		cec_msg_report_physical_addr(&tx_cec_msg, adap->phys_addr, devtype);
+		return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+	case CEC_MSG_GIVE_DEVICE_VENDOR_ID:
+		if (adap->log_addrs.vendor_id == CEC_VENDOR_ID_NONE)
+			return cec_feature_abort(adap, msg);
+		cec_msg_device_vendor_id(&tx_cec_msg, adap->log_addrs.vendor_id);
+		return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+	case CEC_MSG_ABORT:
+		/* Do nothing for CEC switches */
+		if (devtype == CEC_OP_PRIM_DEVTYPE_SWITCH)
+			return 0;
+		return cec_feature_refused(adap, msg);
+
+	case CEC_MSG_GIVE_OSD_NAME: {
+		if (adap->log_addrs.osd_name[0] == 0)
+			return cec_feature_abort(adap, msg);
+		cec_msg_set_osd_name(&tx_cec_msg, adap->log_addrs.osd_name);
+		return cec_transmit_msg(adap, &tx_cec_msg, false);
+	}
+
+	case CEC_MSG_GIVE_FEATURES:
+		if (adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0)
+			return cec_feature_abort(adap, msg);
+		cec_fill_msg_report_features(adap, &tx_cec_msg, la_idx);
+		return cec_transmit_msg(adap, &tx_cec_msg, false);
+
+	default:
+		/*
+		 * Unprocessed messages are aborted if userspace isn't doing
+		 * any processing either.
+		 */
+		if (!is_broadcast && !is_reply && !adap->follower_cnt &&
+		    !adap->cec_follower && msg->msg[1] != CEC_MSG_FEATURE_ABORT)
+			return cec_feature_abort(adap, msg);
+		break;
+	}
+
+skip_processing:
+	/* If this was a reply, then we're done, unless otherwise specified */
+	if (is_reply && !(msg->flags & CEC_MSG_FL_REPLY_TO_FOLLOWERS))
+		return 0;
+
+	/*
+	 * Send to the exclusive follower if there is one, otherwise send
+	 * to all followers.
+	 */
+	if (adap->cec_follower)
+		cec_queue_msg_fh(adap->cec_follower, msg);
+	else
+		cec_queue_msg_followers(adap, msg);
+	return 0;
+}
+
+/*
+ * Helper functions to keep track of the 'monitor all' use count.
+ *
+ * These functions are called with adap->lock held.
+ */
+int cec_monitor_all_cnt_inc(struct cec_adapter *adap)
+{
+	int ret = 0;
+
+	if (adap->monitor_all_cnt == 0)
+		ret = call_op(adap, adap_monitor_all_enable, 1);
+	if (ret == 0)
+		adap->monitor_all_cnt++;
+	return ret;
+}
+
+void cec_monitor_all_cnt_dec(struct cec_adapter *adap)
+{
+	adap->monitor_all_cnt--;
+	if (adap->monitor_all_cnt == 0)
+		WARN_ON(call_op(adap, adap_monitor_all_enable, 0));
+}
+
+#ifdef CONFIG_MEDIA_CEC_DEBUG
+/*
+ * Log the current state of the CEC adapter.
+ * Very useful for debugging.
+ */
+int cec_adap_status(struct seq_file *file, void *priv)
+{
+	struct cec_adapter *adap = dev_get_drvdata(file->private);
+	struct cec_data *data;
+
+	mutex_lock(&adap->lock);
+	seq_printf(file, "configured: %d\n", adap->is_configured);
+	seq_printf(file, "configuring: %d\n", adap->is_configuring);
+	seq_printf(file, "phys_addr: %x.%x.%x.%x\n",
+		   cec_phys_addr_exp(adap->phys_addr));
+	seq_printf(file, "number of LAs: %d\n", adap->log_addrs.num_log_addrs);
+	seq_printf(file, "LA mask: 0x%04x\n", adap->log_addrs.log_addr_mask);
+	if (adap->cec_follower)
+		seq_printf(file, "has CEC follower%s\n",
+			   adap->passthrough ? " (in passthrough mode)" : "");
+	if (adap->cec_initiator)
+		seq_puts(file, "has CEC initiator\n");
+	if (adap->monitor_all_cnt)
+		seq_printf(file, "file handles in Monitor All mode: %u\n",
+			   adap->monitor_all_cnt);
+	data = adap->transmitting;
+	if (data)
+		seq_printf(file, "transmitting message: %*ph (reply: %02x, timeout: %ums)\n",
+			   data->msg.len, data->msg.msg, data->msg.reply,
+			   data->msg.timeout);
+	seq_printf(file, "pending transmits: %u\n", adap->transmit_queue_sz);
+	list_for_each_entry(data, &adap->transmit_queue, list) {
+		seq_printf(file, "queued tx message: %*ph (reply: %02x, timeout: %ums)\n",
+			   data->msg.len, data->msg.msg, data->msg.reply,
+			   data->msg.timeout);
+	}
+	list_for_each_entry(data, &adap->wait_queue, list) {
+		seq_printf(file, "message waiting for reply: %*ph (reply: %02x, timeout: %ums)\n",
+			   data->msg.len, data->msg.msg, data->msg.reply,
+			   data->msg.timeout);
+	}
+
+	call_void_op(adap, adap_status, file);
+	mutex_unlock(&adap->lock);
+	return 0;
+}
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/cec/cec-api.c linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-api.c
--- linux-libre-4.9-gnu/drivers/media/cec/cec-api.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-api.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,588 @@
+/*
+ * cec-api.c - HDMI Consumer Electronics Control framework - API
+ *
+ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. 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/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+
+#include "cec-priv.h"
+
+static inline struct cec_devnode *cec_devnode_data(struct file *filp)
+{
+	struct cec_fh *fh = filp->private_data;
+
+	return &fh->adap->devnode;
+}
+
+/* CEC file operations */
+
+static unsigned int cec_poll(struct file *filp,
+			     struct poll_table_struct *poll)
+{
+	struct cec_devnode *devnode = cec_devnode_data(filp);
+	struct cec_fh *fh = filp->private_data;
+	struct cec_adapter *adap = fh->adap;
+	unsigned int res = 0;
+
+	if (!devnode->registered)
+		return POLLERR | POLLHUP;
+	mutex_lock(&adap->lock);
+	if (adap->is_configured &&
+	    adap->transmit_queue_sz < CEC_MAX_MSG_TX_QUEUE_SZ)
+		res |= POLLOUT | POLLWRNORM;
+	if (fh->queued_msgs)
+		res |= POLLIN | POLLRDNORM;
+	if (fh->pending_events)
+		res |= POLLPRI;
+	poll_wait(filp, &fh->wait, poll);
+	mutex_unlock(&adap->lock);
+	return res;
+}
+
+static bool cec_is_busy(const struct cec_adapter *adap,
+			const struct cec_fh *fh)
+{
+	bool valid_initiator = adap->cec_initiator && adap->cec_initiator == fh;
+	bool valid_follower = adap->cec_follower && adap->cec_follower == fh;
+
+	/*
+	 * Exclusive initiators and followers can always access the CEC adapter
+	 */
+	if (valid_initiator || valid_follower)
+		return false;
+	/*
+	 * All others can only access the CEC adapter if there is no
+	 * exclusive initiator and they are in INITIATOR mode.
+	 */
+	return adap->cec_initiator ||
+	       fh->mode_initiator == CEC_MODE_NO_INITIATOR;
+}
+
+static long cec_adap_g_caps(struct cec_adapter *adap,
+			    struct cec_caps __user *parg)
+{
+	struct cec_caps caps = {};
+
+	strlcpy(caps.driver, adap->devnode.dev.parent->driver->name,
+		sizeof(caps.driver));
+	strlcpy(caps.name, adap->name, sizeof(caps.name));
+	caps.available_log_addrs = adap->available_log_addrs;
+	caps.capabilities = adap->capabilities;
+	caps.version = LINUX_VERSION_CODE;
+	if (copy_to_user(parg, &caps, sizeof(caps)))
+		return -EFAULT;
+	return 0;
+}
+
+static long cec_adap_g_phys_addr(struct cec_adapter *adap,
+				 __u16 __user *parg)
+{
+	u16 phys_addr;
+
+	mutex_lock(&adap->lock);
+	phys_addr = adap->phys_addr;
+	mutex_unlock(&adap->lock);
+	if (copy_to_user(parg, &phys_addr, sizeof(phys_addr)))
+		return -EFAULT;
+	return 0;
+}
+
+static long cec_adap_s_phys_addr(struct cec_adapter *adap, struct cec_fh *fh,
+				 bool block, __u16 __user *parg)
+{
+	u16 phys_addr;
+	long err;
+
+	if (!(adap->capabilities & CEC_CAP_PHYS_ADDR))
+		return -ENOTTY;
+	if (copy_from_user(&phys_addr, parg, sizeof(phys_addr)))
+		return -EFAULT;
+
+	err = cec_phys_addr_validate(phys_addr, NULL, NULL);
+	if (err)
+		return err;
+	mutex_lock(&adap->lock);
+	if (cec_is_busy(adap, fh))
+		err = -EBUSY;
+	else
+		__cec_s_phys_addr(adap, phys_addr, block);
+	mutex_unlock(&adap->lock);
+	return err;
+}
+
+static long cec_adap_g_log_addrs(struct cec_adapter *adap,
+				 struct cec_log_addrs __user *parg)
+{
+	struct cec_log_addrs log_addrs;
+
+	mutex_lock(&adap->lock);
+	log_addrs = adap->log_addrs;
+	if (!adap->is_configured)
+		memset(log_addrs.log_addr, CEC_LOG_ADDR_INVALID,
+		       sizeof(log_addrs.log_addr));
+	mutex_unlock(&adap->lock);
+
+	if (copy_to_user(parg, &log_addrs, sizeof(log_addrs)))
+		return -EFAULT;
+	return 0;
+}
+
+static long cec_adap_s_log_addrs(struct cec_adapter *adap, struct cec_fh *fh,
+				 bool block, struct cec_log_addrs __user *parg)
+{
+	struct cec_log_addrs log_addrs;
+	long err = -EBUSY;
+
+	if (!(adap->capabilities & CEC_CAP_LOG_ADDRS))
+		return -ENOTTY;
+	if (copy_from_user(&log_addrs, parg, sizeof(log_addrs)))
+		return -EFAULT;
+	log_addrs.flags &= CEC_LOG_ADDRS_FL_ALLOW_UNREG_FALLBACK |
+			   CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU |
+			   CEC_LOG_ADDRS_FL_CDC_ONLY;
+	mutex_lock(&adap->lock);
+	if (!adap->is_configuring &&
+	    (!log_addrs.num_log_addrs || !adap->is_configured) &&
+	    !cec_is_busy(adap, fh)) {
+		err = __cec_s_log_addrs(adap, &log_addrs, block);
+		if (!err)
+			log_addrs = adap->log_addrs;
+	}
+	mutex_unlock(&adap->lock);
+	if (err)
+		return err;
+	if (copy_to_user(parg, &log_addrs, sizeof(log_addrs)))
+		return -EFAULT;
+	return 0;
+}
+
+static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh,
+			 bool block, struct cec_msg __user *parg)
+{
+	struct cec_msg msg = {};
+	long err = 0;
+
+	if (!(adap->capabilities & CEC_CAP_TRANSMIT))
+		return -ENOTTY;
+	if (copy_from_user(&msg, parg, sizeof(msg)))
+		return -EFAULT;
+
+	/* A CDC-Only device can only send CDC messages */
+	if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) &&
+	    (msg.len == 1 || msg.msg[1] != CEC_MSG_CDC_MESSAGE))
+		return -EINVAL;
+
+	mutex_lock(&adap->lock);
+	if (!adap->is_configured)
+		err = -ENONET;
+	else if (cec_is_busy(adap, fh))
+		err = -EBUSY;
+	else
+		err = cec_transmit_msg_fh(adap, &msg, fh, block);
+	mutex_unlock(&adap->lock);
+	if (err)
+		return err;
+	if (copy_to_user(parg, &msg, sizeof(msg)))
+		return -EFAULT;
+	return 0;
+}
+
+/* Called by CEC_RECEIVE: wait for a message to arrive */
+static int cec_receive_msg(struct cec_fh *fh, struct cec_msg *msg, bool block)
+{
+	u32 timeout = msg->timeout;
+	int res;
+
+	do {
+		mutex_lock(&fh->lock);
+		/* Are there received messages queued up? */
+		if (fh->queued_msgs) {
+			/* Yes, return the first one */
+			struct cec_msg_entry *entry =
+				list_first_entry(&fh->msgs,
+						 struct cec_msg_entry, list);
+
+			list_del(&entry->list);
+			*msg = entry->msg;
+			kfree(entry);
+			fh->queued_msgs--;
+			mutex_unlock(&fh->lock);
+			/* restore original timeout value */
+			msg->timeout = timeout;
+			return 0;
+		}
+
+		/* No, return EAGAIN in non-blocking mode or wait */
+		mutex_unlock(&fh->lock);
+
+		/* Return when in non-blocking mode */
+		if (!block)
+			return -EAGAIN;
+
+		if (msg->timeout) {
+			/* The user specified a timeout */
+			res = wait_event_interruptible_timeout(fh->wait,
+							       fh->queued_msgs,
+				msecs_to_jiffies(msg->timeout));
+			if (res == 0)
+				res = -ETIMEDOUT;
+			else if (res > 0)
+				res = 0;
+		} else {
+			/* Wait indefinitely */
+			res = wait_event_interruptible(fh->wait,
+						       fh->queued_msgs);
+		}
+		/* Exit on error, otherwise loop to get the new message */
+	} while (!res);
+	return res;
+}
+
+static long cec_receive(struct cec_adapter *adap, struct cec_fh *fh,
+			bool block, struct cec_msg __user *parg)
+{
+	struct cec_msg msg = {};
+	long err = 0;
+
+	if (copy_from_user(&msg, parg, sizeof(msg)))
+		return -EFAULT;
+	mutex_lock(&adap->lock);
+	if (!adap->is_configured && fh->mode_follower < CEC_MODE_MONITOR)
+		err = -ENONET;
+	mutex_unlock(&adap->lock);
+	if (err)
+		return err;
+
+	err = cec_receive_msg(fh, &msg, block);
+	if (err)
+		return err;
+	msg.flags = 0;
+	if (copy_to_user(parg, &msg, sizeof(msg)))
+		return -EFAULT;
+	return 0;
+}
+
+static long cec_dqevent(struct cec_adapter *adap, struct cec_fh *fh,
+			bool block, struct cec_event __user *parg)
+{
+	struct cec_event *ev = NULL;
+	u64 ts = ~0ULL;
+	unsigned int i;
+	long err = 0;
+
+	mutex_lock(&fh->lock);
+	while (!fh->pending_events && block) {
+		mutex_unlock(&fh->lock);
+		err = wait_event_interruptible(fh->wait, fh->pending_events);
+		if (err)
+			return err;
+		mutex_lock(&fh->lock);
+	}
+
+	/* Find the oldest event */
+	for (i = 0; i < CEC_NUM_EVENTS; i++) {
+		if (fh->pending_events & (1 << (i + 1)) &&
+		    fh->events[i].ts <= ts) {
+			ev = &fh->events[i];
+			ts = ev->ts;
+		}
+	}
+	if (!ev) {
+		err = -EAGAIN;
+		goto unlock;
+	}
+
+	if (copy_to_user(parg, ev, sizeof(*ev))) {
+		err = -EFAULT;
+		goto unlock;
+	}
+
+	fh->pending_events &= ~(1 << ev->event);
+
+unlock:
+	mutex_unlock(&fh->lock);
+	return err;
+}
+
+static long cec_g_mode(struct cec_adapter *adap, struct cec_fh *fh,
+		       u32 __user *parg)
+{
+	u32 mode = fh->mode_initiator | fh->mode_follower;
+
+	if (copy_to_user(parg, &mode, sizeof(mode)))
+		return -EFAULT;
+	return 0;
+}
+
+static long cec_s_mode(struct cec_adapter *adap, struct cec_fh *fh,
+		       u32 __user *parg)
+{
+	u32 mode;
+	u8 mode_initiator;
+	u8 mode_follower;
+	long err = 0;
+
+	if (copy_from_user(&mode, parg, sizeof(mode)))
+		return -EFAULT;
+	if (mode & ~(CEC_MODE_INITIATOR_MSK | CEC_MODE_FOLLOWER_MSK))
+		return -EINVAL;
+
+	mode_initiator = mode & CEC_MODE_INITIATOR_MSK;
+	mode_follower = mode & CEC_MODE_FOLLOWER_MSK;
+
+	if (mode_initiator > CEC_MODE_EXCL_INITIATOR ||
+	    mode_follower > CEC_MODE_MONITOR_ALL)
+		return -EINVAL;
+
+	if (mode_follower == CEC_MODE_MONITOR_ALL &&
+	    !(adap->capabilities & CEC_CAP_MONITOR_ALL))
+		return -EINVAL;
+
+	/* Follower modes should always be able to send CEC messages */
+	if ((mode_initiator == CEC_MODE_NO_INITIATOR ||
+	     !(adap->capabilities & CEC_CAP_TRANSMIT)) &&
+	    mode_follower >= CEC_MODE_FOLLOWER &&
+	    mode_follower <= CEC_MODE_EXCL_FOLLOWER_PASSTHRU)
+		return -EINVAL;
+
+	/* Monitor modes require CEC_MODE_NO_INITIATOR */
+	if (mode_initiator && mode_follower >= CEC_MODE_MONITOR)
+		return -EINVAL;
+
+	/* Monitor modes require CAP_NET_ADMIN */
+	if (mode_follower >= CEC_MODE_MONITOR && !capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&adap->lock);
+	/*
+	 * You can't become exclusive follower if someone else already
+	 * has that job.
+	 */
+	if ((mode_follower == CEC_MODE_EXCL_FOLLOWER ||
+	     mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) &&
+	    adap->cec_follower && adap->cec_follower != fh)
+		err = -EBUSY;
+	/*
+	 * You can't become exclusive initiator if someone else already
+	 * has that job.
+	 */
+	if (mode_initiator == CEC_MODE_EXCL_INITIATOR &&
+	    adap->cec_initiator && adap->cec_initiator != fh)
+		err = -EBUSY;
+
+	if (!err) {
+		bool old_mon_all = fh->mode_follower == CEC_MODE_MONITOR_ALL;
+		bool new_mon_all = mode_follower == CEC_MODE_MONITOR_ALL;
+
+		if (old_mon_all != new_mon_all) {
+			if (new_mon_all)
+				err = cec_monitor_all_cnt_inc(adap);
+			else
+				cec_monitor_all_cnt_dec(adap);
+		}
+	}
+
+	if (err) {
+		mutex_unlock(&adap->lock);
+		return err;
+	}
+
+	if (fh->mode_follower == CEC_MODE_FOLLOWER)
+		adap->follower_cnt--;
+	if (mode_follower == CEC_MODE_FOLLOWER)
+		adap->follower_cnt++;
+	if (mode_follower == CEC_MODE_EXCL_FOLLOWER ||
+	    mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU) {
+		adap->passthrough =
+			mode_follower == CEC_MODE_EXCL_FOLLOWER_PASSTHRU;
+		adap->cec_follower = fh;
+	} else if (adap->cec_follower == fh) {
+		adap->passthrough = false;
+		adap->cec_follower = NULL;
+	}
+	if (mode_initiator == CEC_MODE_EXCL_INITIATOR)
+		adap->cec_initiator = fh;
+	else if (adap->cec_initiator == fh)
+		adap->cec_initiator = NULL;
+	fh->mode_initiator = mode_initiator;
+	fh->mode_follower = mode_follower;
+	mutex_unlock(&adap->lock);
+	return 0;
+}
+
+static long cec_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct cec_devnode *devnode = cec_devnode_data(filp);
+	struct cec_fh *fh = filp->private_data;
+	struct cec_adapter *adap = fh->adap;
+	bool block = !(filp->f_flags & O_NONBLOCK);
+	void __user *parg = (void __user *)arg;
+
+	if (!devnode->registered)
+		return -ENODEV;
+
+	switch (cmd) {
+	case CEC_ADAP_G_CAPS:
+		return cec_adap_g_caps(adap, parg);
+
+	case CEC_ADAP_G_PHYS_ADDR:
+		return cec_adap_g_phys_addr(adap, parg);
+
+	case CEC_ADAP_S_PHYS_ADDR:
+		return cec_adap_s_phys_addr(adap, fh, block, parg);
+
+	case CEC_ADAP_G_LOG_ADDRS:
+		return cec_adap_g_log_addrs(adap, parg);
+
+	case CEC_ADAP_S_LOG_ADDRS:
+		return cec_adap_s_log_addrs(adap, fh, block, parg);
+
+	case CEC_TRANSMIT:
+		return cec_transmit(adap, fh, block, parg);
+
+	case CEC_RECEIVE:
+		return cec_receive(adap, fh, block, parg);
+
+	case CEC_DQEVENT:
+		return cec_dqevent(adap, fh, block, parg);
+
+	case CEC_G_MODE:
+		return cec_g_mode(adap, fh, parg);
+
+	case CEC_S_MODE:
+		return cec_s_mode(adap, fh, parg);
+
+	default:
+		return -ENOTTY;
+	}
+}
+
+static int cec_open(struct inode *inode, struct file *filp)
+{
+	struct cec_devnode *devnode =
+		container_of(inode->i_cdev, struct cec_devnode, cdev);
+	struct cec_adapter *adap = to_cec_adapter(devnode);
+	struct cec_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+	/*
+	 * Initial events that are automatically sent when the cec device is
+	 * opened.
+	 */
+	struct cec_event ev_state = {
+		.event = CEC_EVENT_STATE_CHANGE,
+		.flags = CEC_EVENT_FL_INITIAL_STATE,
+	};
+	int err;
+
+	if (!fh)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&fh->msgs);
+	INIT_LIST_HEAD(&fh->xfer_list);
+	mutex_init(&fh->lock);
+	init_waitqueue_head(&fh->wait);
+
+	fh->mode_initiator = CEC_MODE_INITIATOR;
+	fh->adap = adap;
+
+	err = cec_get_device(devnode);
+	if (err) {
+		kfree(fh);
+		return err;
+	}
+
+	filp->private_data = fh;
+
+	mutex_lock(&devnode->lock);
+	/* Queue up initial state events */
+	ev_state.state_change.phys_addr = adap->phys_addr;
+	ev_state.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
+	cec_queue_event_fh(fh, &ev_state, 0);
+
+	list_add(&fh->list, &devnode->fhs);
+	mutex_unlock(&devnode->lock);
+
+	return 0;
+}
+
+/* Override for the release function */
+static int cec_release(struct inode *inode, struct file *filp)
+{
+	struct cec_devnode *devnode = cec_devnode_data(filp);
+	struct cec_adapter *adap = to_cec_adapter(devnode);
+	struct cec_fh *fh = filp->private_data;
+
+	mutex_lock(&adap->lock);
+	if (adap->cec_initiator == fh)
+		adap->cec_initiator = NULL;
+	if (adap->cec_follower == fh) {
+		adap->cec_follower = NULL;
+		adap->passthrough = false;
+	}
+	if (fh->mode_follower == CEC_MODE_FOLLOWER)
+		adap->follower_cnt--;
+	if (fh->mode_follower == CEC_MODE_MONITOR_ALL)
+		cec_monitor_all_cnt_dec(adap);
+	mutex_unlock(&adap->lock);
+
+	mutex_lock(&devnode->lock);
+	list_del(&fh->list);
+	mutex_unlock(&devnode->lock);
+
+	/* Unhook pending transmits from this filehandle. */
+	mutex_lock(&adap->lock);
+	while (!list_empty(&fh->xfer_list)) {
+		struct cec_data *data =
+			list_first_entry(&fh->xfer_list, struct cec_data, xfer_list);
+
+		data->blocking = false;
+		data->fh = NULL;
+		list_del(&data->xfer_list);
+	}
+	mutex_unlock(&adap->lock);
+	while (!list_empty(&fh->msgs)) {
+		struct cec_msg_entry *entry =
+			list_first_entry(&fh->msgs, struct cec_msg_entry, list);
+
+		list_del(&entry->list);
+		kfree(entry);
+	}
+	kfree(fh);
+
+	cec_put_device(devnode);
+	filp->private_data = NULL;
+	return 0;
+}
+
+const struct file_operations cec_devnode_fops = {
+	.owner = THIS_MODULE,
+	.open = cec_open,
+	.unlocked_ioctl = cec_ioctl,
+	.release = cec_release,
+	.poll = cec_poll,
+	.llseek = no_llseek,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/cec/cec-core.c linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-core.c
--- linux-libre-4.9-gnu/drivers/media/cec/cec-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,413 @@
+/*
+ * cec-core.c - HDMI Consumer Electronics Control framework - Core
+ *
+ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. 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/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "cec-priv.h"
+
+#define CEC_NUM_DEVICES	256
+#define CEC_NAME	"cec"
+
+int cec_debug;
+module_param_named(debug, cec_debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-2)");
+
+static dev_t cec_dev_t;
+
+/* Active devices */
+static DEFINE_MUTEX(cec_devnode_lock);
+static DECLARE_BITMAP(cec_devnode_nums, CEC_NUM_DEVICES);
+
+static struct dentry *top_cec_dir;
+
+/* dev to cec_devnode */
+#define to_cec_devnode(cd) container_of(cd, struct cec_devnode, dev)
+
+int cec_get_device(struct cec_devnode *devnode)
+{
+	/*
+	 * Check if the cec device is available. This needs to be done with
+	 * the devnode->lock held to prevent an open/unregister race:
+	 * without the lock, the device could be unregistered and freed between
+	 * the devnode->registered check and get_device() calls, leading to
+	 * a crash.
+	 */
+	mutex_lock(&devnode->lock);
+	/*
+	 * return ENXIO if the cec device has been removed
+	 * already or if it is not registered anymore.
+	 */
+	if (!devnode->registered) {
+		mutex_unlock(&devnode->lock);
+		return -ENXIO;
+	}
+	/* and increase the device refcount */
+	get_device(&devnode->dev);
+	mutex_unlock(&devnode->lock);
+	return 0;
+}
+
+void cec_put_device(struct cec_devnode *devnode)
+{
+	put_device(&devnode->dev);
+}
+
+/* Called when the last user of the cec device exits. */
+static void cec_devnode_release(struct device *cd)
+{
+	struct cec_devnode *devnode = to_cec_devnode(cd);
+
+	mutex_lock(&cec_devnode_lock);
+	/* Mark device node number as free */
+	clear_bit(devnode->minor, cec_devnode_nums);
+	mutex_unlock(&cec_devnode_lock);
+
+	cec_delete_adapter(to_cec_adapter(devnode));
+}
+
+static struct bus_type cec_bus_type = {
+	.name = CEC_NAME,
+};
+
+/*
+ * Register a cec device node
+ *
+ * The registration code assigns minor numbers and registers the new device node
+ * with the kernel. An error is returned if no free minor number can be found,
+ * or if the registration of the device node fails.
+ *
+ * Zero is returned on success.
+ *
+ * Note that if the cec_devnode_register call fails, the release() callback of
+ * the cec_devnode structure is *not* called, so the caller is responsible for
+ * freeing any data.
+ */
+static int __must_check cec_devnode_register(struct cec_devnode *devnode,
+					     struct module *owner)
+{
+	int minor;
+	int ret;
+
+	/* Initialization */
+	INIT_LIST_HEAD(&devnode->fhs);
+	mutex_init(&devnode->lock);
+
+	/* Part 1: Find a free minor number */
+	mutex_lock(&cec_devnode_lock);
+	minor = find_next_zero_bit(cec_devnode_nums, CEC_NUM_DEVICES, 0);
+	if (minor == CEC_NUM_DEVICES) {
+		mutex_unlock(&cec_devnode_lock);
+		pr_err("could not get a free minor\n");
+		return -ENFILE;
+	}
+
+	set_bit(minor, cec_devnode_nums);
+	mutex_unlock(&cec_devnode_lock);
+
+	devnode->minor = minor;
+	devnode->dev.bus = &cec_bus_type;
+	devnode->dev.devt = MKDEV(MAJOR(cec_dev_t), minor);
+	devnode->dev.release = cec_devnode_release;
+	dev_set_name(&devnode->dev, "cec%d", devnode->minor);
+	device_initialize(&devnode->dev);
+
+	/* Part 2: Initialize and register the character device */
+	cdev_init(&devnode->cdev, &cec_devnode_fops);
+	devnode->cdev.kobj.parent = &devnode->dev.kobj;
+	devnode->cdev.owner = owner;
+
+	ret = cdev_add(&devnode->cdev, devnode->dev.devt, 1);
+	if (ret < 0) {
+		pr_err("%s: cdev_add failed\n", __func__);
+		goto clr_bit;
+	}
+
+	ret = device_add(&devnode->dev);
+	if (ret)
+		goto cdev_del;
+
+	devnode->registered = true;
+	return 0;
+
+cdev_del:
+	cdev_del(&devnode->cdev);
+clr_bit:
+	mutex_lock(&cec_devnode_lock);
+	clear_bit(devnode->minor, cec_devnode_nums);
+	mutex_unlock(&cec_devnode_lock);
+	return ret;
+}
+
+/*
+ * Unregister a cec device node
+ *
+ * This unregisters the passed device. Future open calls will be met with
+ * errors.
+ *
+ * This function can safely be called if the device node has never been
+ * registered or has already been unregistered.
+ */
+static void cec_devnode_unregister(struct cec_devnode *devnode)
+{
+	struct cec_fh *fh;
+
+	mutex_lock(&devnode->lock);
+
+	/* Check if devnode was never registered or already unregistered */
+	if (!devnode->registered || devnode->unregistered) {
+		mutex_unlock(&devnode->lock);
+		return;
+	}
+
+	list_for_each_entry(fh, &devnode->fhs, list)
+		wake_up_interruptible(&fh->wait);
+
+	devnode->registered = false;
+	devnode->unregistered = true;
+	mutex_unlock(&devnode->lock);
+
+	device_del(&devnode->dev);
+	cdev_del(&devnode->cdev);
+	put_device(&devnode->dev);
+}
+
+struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
+					 void *priv, const char *name, u32 caps,
+					 u8 available_las)
+{
+	struct cec_adapter *adap;
+	int res;
+
+	if (WARN_ON(!caps))
+		return ERR_PTR(-EINVAL);
+	if (WARN_ON(!ops))
+		return ERR_PTR(-EINVAL);
+	if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS))
+		return ERR_PTR(-EINVAL);
+	adap = kzalloc(sizeof(*adap), GFP_KERNEL);
+	if (!adap)
+		return ERR_PTR(-ENOMEM);
+	strlcpy(adap->name, name, sizeof(adap->name));
+	adap->phys_addr = CEC_PHYS_ADDR_INVALID;
+	adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0;
+	adap->log_addrs.vendor_id = CEC_VENDOR_ID_NONE;
+	adap->capabilities = caps;
+	adap->available_log_addrs = available_las;
+	adap->sequence = 0;
+	adap->ops = ops;
+	adap->priv = priv;
+	memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
+	mutex_init(&adap->lock);
+	INIT_LIST_HEAD(&adap->transmit_queue);
+	INIT_LIST_HEAD(&adap->wait_queue);
+	init_waitqueue_head(&adap->kthread_waitq);
+
+	adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);
+	if (IS_ERR(adap->kthread)) {
+		pr_err("cec-%s: kernel_thread() failed\n", name);
+		res = PTR_ERR(adap->kthread);
+		kfree(adap);
+		return ERR_PTR(res);
+	}
+
+	if (!(caps & CEC_CAP_RC))
+		return adap;
+
+#if IS_REACHABLE(CONFIG_RC_CORE)
+	/* Prepare the RC input device */
+	adap->rc = rc_allocate_device();
+	if (!adap->rc) {
+		pr_err("cec-%s: failed to allocate memory for rc_dev\n",
+		       name);
+		kthread_stop(adap->kthread);
+		kfree(adap);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	snprintf(adap->input_name, sizeof(adap->input_name),
+		 "RC for %s", name);
+	snprintf(adap->input_phys, sizeof(adap->input_phys),
+		 "%s/input0", name);
+
+	adap->rc->input_name = adap->input_name;
+	adap->rc->input_phys = adap->input_phys;
+	adap->rc->input_id.bustype = BUS_CEC;
+	adap->rc->input_id.vendor = 0;
+	adap->rc->input_id.product = 0;
+	adap->rc->input_id.version = 1;
+	adap->rc->driver_type = RC_DRIVER_SCANCODE;
+	adap->rc->driver_name = CEC_NAME;
+	adap->rc->allowed_protocols = RC_BIT_CEC;
+	adap->rc->priv = adap;
+	adap->rc->map_name = RC_MAP_CEC;
+	adap->rc->timeout = MS_TO_NS(100);
+#else
+	adap->capabilities &= ~CEC_CAP_RC;
+#endif
+	return adap;
+}
+EXPORT_SYMBOL_GPL(cec_allocate_adapter);
+
+int cec_register_adapter(struct cec_adapter *adap,
+			 struct device *parent)
+{
+	int res;
+
+	if (IS_ERR_OR_NULL(adap))
+		return 0;
+
+	if (WARN_ON(!parent))
+		return -EINVAL;
+
+	adap->owner = parent->driver->owner;
+	adap->devnode.dev.parent = parent;
+
+#if IS_REACHABLE(CONFIG_RC_CORE)
+	adap->rc->dev.parent = parent;
+	if (adap->capabilities & CEC_CAP_RC) {
+		res = rc_register_device(adap->rc);
+
+		if (res) {
+			pr_err("cec-%s: failed to prepare input device\n",
+			       adap->name);
+			rc_free_device(adap->rc);
+			adap->rc = NULL;
+			return res;
+		}
+	}
+#endif
+
+	res = cec_devnode_register(&adap->devnode, adap->owner);
+	if (res) {
+#if IS_REACHABLE(CONFIG_RC_CORE)
+		/* Note: rc_unregister also calls rc_free */
+		rc_unregister_device(adap->rc);
+		adap->rc = NULL;
+#endif
+		return res;
+	}
+
+	dev_set_drvdata(&adap->devnode.dev, adap);
+#ifdef CONFIG_MEDIA_CEC_DEBUG
+	if (!top_cec_dir)
+		return 0;
+
+	adap->cec_dir = debugfs_create_dir(dev_name(&adap->devnode.dev), top_cec_dir);
+	if (IS_ERR_OR_NULL(adap->cec_dir)) {
+		pr_warn("cec-%s: Failed to create debugfs dir\n", adap->name);
+		return 0;
+	}
+	adap->status_file = debugfs_create_devm_seqfile(&adap->devnode.dev,
+		"status", adap->cec_dir, cec_adap_status);
+	if (IS_ERR_OR_NULL(adap->status_file)) {
+		pr_warn("cec-%s: Failed to create status file\n", adap->name);
+		debugfs_remove_recursive(adap->cec_dir);
+		adap->cec_dir = NULL;
+	}
+#endif
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cec_register_adapter);
+
+void cec_unregister_adapter(struct cec_adapter *adap)
+{
+	if (IS_ERR_OR_NULL(adap))
+		return;
+
+#if IS_REACHABLE(CONFIG_RC_CORE)
+	/* Note: rc_unregister also calls rc_free */
+	rc_unregister_device(adap->rc);
+	adap->rc = NULL;
+#endif
+	debugfs_remove_recursive(adap->cec_dir);
+	cec_devnode_unregister(&adap->devnode);
+}
+EXPORT_SYMBOL_GPL(cec_unregister_adapter);
+
+void cec_delete_adapter(struct cec_adapter *adap)
+{
+	if (IS_ERR_OR_NULL(adap))
+		return;
+	mutex_lock(&adap->lock);
+	__cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false);
+	mutex_unlock(&adap->lock);
+	kthread_stop(adap->kthread);
+	if (adap->kthread_config)
+		kthread_stop(adap->kthread_config);
+#if IS_REACHABLE(CONFIG_RC_CORE)
+	rc_free_device(adap->rc);
+#endif
+	kfree(adap);
+}
+EXPORT_SYMBOL_GPL(cec_delete_adapter);
+
+/*
+ *	Initialise cec for linux
+ */
+static int __init cec_devnode_init(void)
+{
+	int ret;
+
+	pr_info("Linux cec interface: v0.10\n");
+	ret = alloc_chrdev_region(&cec_dev_t, 0, CEC_NUM_DEVICES,
+				  CEC_NAME);
+	if (ret < 0) {
+		pr_warn("cec: unable to allocate major\n");
+		return ret;
+	}
+
+#ifdef CONFIG_MEDIA_CEC_DEBUG
+	top_cec_dir = debugfs_create_dir("cec", NULL);
+	if (IS_ERR_OR_NULL(top_cec_dir)) {
+		pr_warn("cec: Failed to create debugfs cec dir\n");
+		top_cec_dir = NULL;
+	}
+#endif
+
+	ret = bus_register(&cec_bus_type);
+	if (ret < 0) {
+		unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES);
+		pr_warn("cec: bus_register failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void __exit cec_devnode_exit(void)
+{
+	debugfs_remove_recursive(top_cec_dir);
+	bus_unregister(&cec_bus_type);
+	unregister_chrdev_region(cec_dev_t, CEC_NUM_DEVICES);
+}
+
+subsys_initcall(cec_devnode_init);
+module_exit(cec_devnode_exit)
+
+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_DESCRIPTION("Device node registration for cec drivers");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/cec/cec-priv.h linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-priv.h
--- linux-libre-4.9-gnu/drivers/media/cec/cec-priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/cec/cec-priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * cec-priv.h - HDMI Consumer Electronics Control internal header
+ *
+ * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. 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 _CEC_PRIV_H
+#define _CEC_PRIV_H
+
+#include <linux/cec-funcs.h>
+#include <media/cec.h>
+
+#define dprintk(lvl, fmt, arg...)					\
+	do {								\
+		if (lvl <= cec_debug)					\
+			pr_info("cec-%s: " fmt, adap->name, ## arg);	\
+	} while (0)
+
+/* devnode to cec_adapter */
+#define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
+
+/* cec-core.c */
+extern int cec_debug;
+int cec_get_device(struct cec_devnode *devnode);
+void cec_put_device(struct cec_devnode *devnode);
+
+/* cec-adap.c */
+int cec_monitor_all_cnt_inc(struct cec_adapter *adap);
+void cec_monitor_all_cnt_dec(struct cec_adapter *adap);
+int cec_adap_status(struct seq_file *file, void *priv);
+int cec_thread_func(void *_adap);
+void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block);
+int __cec_s_log_addrs(struct cec_adapter *adap,
+		      struct cec_log_addrs *log_addrs, bool block);
+int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
+			struct cec_fh *fh, bool block);
+void cec_queue_event_fh(struct cec_fh *fh,
+			const struct cec_event *new_ev, u64 ts);
+
+/* cec-api.c */
+extern const struct file_operations cec_devnode_fops;
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/cec/Makefile linux-libre-4.10-rc8-gnu/drivers/media/cec/Makefile
--- linux-libre-4.9-gnu/drivers/media/cec/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/cec/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,5 @@
+cec-objs := cec-core.o cec-adap.o cec-api.o
+
+ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y)
+  obj-$(CONFIG_MEDIA_SUPPORT) += cec.o
+endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop.c linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop.c
--- linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,8 +46,7 @@ int b2c2_flexcop_debug;
 EXPORT_SYMBOL_GPL(b2c2_flexcop_debug);
 module_param_named(debug, b2c2_flexcop_debug,  int, 0644);
 MODULE_PARM_DESC(debug,
-		"set debug level (1=info,2=tuner,4=i2c,8=ts,"
-		"16=sram,32=reg (|-able))."
+		"set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))."
 		DEBSTATUS);
 #undef DEBSTATUS
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-common.h linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-common.h
--- linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-common.h	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,6 @@
 
 #include "dmxdev.h"
 #include "dvb_demux.h"
-#include "dvb_filter.h"
 #include "dvb_net.h"
 #include "dvb_frontend.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-eeprom.c linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-eeprom.c
--- linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-eeprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-eeprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -136,8 +136,7 @@ int flexcop_eeprom_check_mac_addr(struct
 
 	if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) {
 		if (extended != 0) {
-			err("TODO: extended (EUI64) MAC addresses aren't "
-				"completely supported yet");
+			err("TODO: extended (EUI64) MAC addresses aren't completely supported yet");
 			ret = -EINVAL;
 		} else
 			memcpy(fc->dvb_adapter.proposed_mac,buf,6);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-i2c.c
--- linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,8 +33,8 @@ static int flexcop_i2c_operation(struct
 			return -EREMOTEIO;
 		}
 	}
-	deb_i2c("tried %d times i2c operation, "
-			"never finished or too many ack errors.\n", i);
+	deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",
+		i);
 	return -EREMOTEIO;
 }
 
@@ -124,10 +124,10 @@ int flexcop_i2c_request(struct flexcop_i
 #ifdef DUMP_I2C_MESSAGES
 	printk(KERN_DEBUG "%d ", i2c->port);
 	if (op == FC_READ)
-		printk("rd(");
+		printk(KERN_CONT "rd(");
 	else
-		printk("wr(");
-	printk("%02x): %02x ", chipaddr, addr);
+		printk(KERN_CONT "wr(");
+	printk(KERN_CONT "%02x): %02x ", chipaddr, addr);
 #endif
 
 	/* in that case addr is the only value ->
@@ -151,7 +151,7 @@ int flexcop_i2c_request(struct flexcop_i
 
 #ifdef DUMP_I2C_MESSAGES
 		for (i = 0; i < bytes_to_transfer; i++)
-			printk("%02x ", buf[i]);
+			printk(KERN_CONT "%02x ", buf[i]);
 #endif
 
 		if (ret < 0)
@@ -163,7 +163,7 @@ int flexcop_i2c_request(struct flexcop_i
 	}
 
 #ifdef DUMP_I2C_MESSAGES
-	printk("\n");
+	printk(KERN_CONT "\n");
 #endif
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-misc.c linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-misc.c
--- linux-libre-4.9-gnu/drivers/media/common/b2c2/flexcop-misc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/b2c2/flexcop-misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,18 +23,15 @@ void flexcop_determine_revision(struct f
 		fc->rev = FLEXCOP_III;
 		break;
 	default:
-		err("unknown FlexCop Revision: %x. Please report this to "
-				"linux-dvb@linuxtv.org.",
+		err("unknown FlexCop Revision: %x. Please report this to linux-dvb@linuxtv.org.",
 				v.misc_204.Rev_N_sig_revision_hi);
 		break;
 	}
 
 	if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps))
-		deb_info("this FlexCop has "
-				"the additional 32 hardware pid filter.\n");
+		deb_info("this FlexCop has the additional 32 hardware pid filter.\n");
 	else
-		deb_info("this FlexCop has "
-				"the 6 basic main hardware pid filter.\n");
+		deb_info("this FlexCop has the 6 basic main hardware pid filter.\n");
 	/* bus parts have to decide if hw pid filtering is used or not. */
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/cx2341x.c linux-libre-4.10-rc8-gnu/drivers/media/common/cx2341x.c
--- linux-libre-4.9-gnu/drivers/media/common/cx2341x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/cx2341x.c	2017-02-12 16:03:20.000000000 -0500
@@ -1190,8 +1190,8 @@ void cx2341x_log_status(const struct cx2
 		prefix,
 		cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
 	if (p->stream_insert_nav_packets)
-		printk(" (with navigation packets)");
-	printk("\n");
+		printk(KERN_CONT " (with navigation packets)");
+	printk(KERN_CONT "\n");
 	printk(KERN_INFO "%s: VBI Format: %s\n",
 		prefix,
 		cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_VBI_FMT));
@@ -1209,8 +1209,8 @@ void cx2341x_log_status(const struct cx2
 		cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
 		p->video_bitrate);
 	if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
-		printk(", Peak %d", p->video_bitrate_peak);
-	printk("\n");
+		printk(KERN_CONT ", Peak %d", p->video_bitrate_peak);
+	printk(KERN_CONT "\n");
 	printk(KERN_INFO
 		"%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure\n",
 		prefix,
@@ -1232,9 +1232,9 @@ void cx2341x_log_status(const struct cx2
 		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE),
 		p->audio_mute ? " (muted)" : "");
 	if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
-		printk(", %s", cx2341x_menu_item(p,
+		printk(KERN_CONT ", %s", cx2341x_menu_item(p,
 				V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
-	printk(", %s, %s\n",
+	printk(KERN_CONT ", %s, %s\n",
 		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
 		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/saa7146/saa7146_video.c linux-libre-4.10-rc8-gnu/drivers/media/common/saa7146/saa7146_video.c
--- linux-libre-4.9-gnu/drivers/media/common/saa7146/saa7146_video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/saa7146/saa7146_video.c	2017-02-12 16:03:20.000000000 -0500
@@ -390,6 +390,7 @@ static int video_end(struct saa7146_fh *
 {
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_vv *vv = dev->vv_data;
+	struct saa7146_dmaqueue *q = &vv->video_dmaq;
 	struct saa7146_format *fmt = NULL;
 	unsigned long flags;
 	unsigned int resource;
@@ -428,6 +429,9 @@ static int video_end(struct saa7146_fh *
 	/* shut down all used video dma transfers */
 	saa7146_write(dev, MC1, dmas);
 
+	if (q->curr)
+		saa7146_buffer_finish(dev, q, VIDEOBUF_DONE);
+
 	spin_unlock_irqrestore(&dev->slock, flags);
 
 	vv->video_fh = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/siano/smsdvb-main.c linux-libre-4.10-rc8-gnu/drivers/media/common/siano/smsdvb-main.c
--- linux-libre-4.9-gnu/drivers/media/common/siano/smsdvb-main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/siano/smsdvb-main.c	2017-02-12 16:03:20.000000000 -0500
@@ -1044,7 +1044,7 @@ static void smsdvb_release(struct dvb_fr
 	/* do nothing */
 }
 
-static struct dvb_frontend_ops smsdvb_fe_ops = {
+static const struct dvb_frontend_ops smsdvb_fe_ops = {
 	.info = {
 		.name			= "Siano Mobile Digital MDTV Receiver",
 		.frequency_min		= 44250000,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/tveeprom.c linux-libre-4.10-rc8-gnu/drivers/media/common/tveeprom.c
--- linux-libre-4.9-gnu/drivers/media/common/tveeprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/tveeprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -45,22 +46,9 @@ MODULE_DESCRIPTION("i2c Hauppauge eeprom
 MODULE_AUTHOR("John Klar");
 MODULE_LICENSE("GPL");
 
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-1)");
-
 #define STRM(array, i) \
 	(i < sizeof(array) / sizeof(char *) ? array[i] : "unknown")
 
-#define tveeprom_info(fmt, arg...) \
-	v4l_printk(KERN_INFO, "tveeprom", c->adapter, c->addr, fmt , ## arg)
-#define tveeprom_warn(fmt, arg...) \
-	v4l_printk(KERN_WARNING, "tveeprom", c->adapter, c->addr, fmt , ## arg)
-#define tveeprom_dbg(fmt, arg...) do { \
-	if (debug) \
-		v4l_printk(KERN_DEBUG, "tveeprom", \
-				c->adapter, c->addr, fmt , ## arg); \
-	} while (0)
 
 /*
  * The Hauppauge eeprom uses an 8bit field to determine which
@@ -510,19 +498,13 @@ void tveeprom_hauppauge_analog(struct i2
 			len = eeprom_data[i] & 0x07;
 			++i;
 		} else {
-			tveeprom_warn("Encountered bad packet header [%02x]. "
-				"Corrupt or not a Hauppauge eeprom.\n",
+			pr_warn("Encountered bad packet header [%02x]. Corrupt or not a Hauppauge eeprom.\n",
 				eeprom_data[i]);
 			return;
 		}
 
-		if (debug) {
-			tveeprom_info("Tag [%02x] + %d bytes:",
-					eeprom_data[i], len - 1);
-			for (j = 1; j < len; j++)
-				printk(KERN_CONT " %02x", eeprom_data[i + j]);
-			printk(KERN_CONT "\n");
-		}
+		pr_debug("Tag [%02x] + %d bytes: %*ph\n",
+			eeprom_data[i], len - 1, len, &eeprom_data[i]);
 
 		/* process by tag */
 		tag = eeprom_data[i];
@@ -662,14 +644,14 @@ void tveeprom_hauppauge_analog(struct i2
 		/* case 0x12: tag 'InfoBits' */
 
 		default:
-			tveeprom_dbg("Not sure what to do with tag [%02x]\n",
+			pr_debug("Not sure what to do with tag [%02x]\n",
 					tag);
 			/* dump the rest of the packet? */
 		}
 	}
 
 	if (!done) {
-		tveeprom_warn("Ran out of data!\n");
+		pr_warn("Ran out of data!\n");
 		return;
 	}
 
@@ -682,8 +664,8 @@ void tveeprom_hauppauge_analog(struct i2
 	}
 
 	if (hasRadioTuner(tuner1) && !tvee->has_radio) {
-		tveeprom_info("The eeprom says no radio is present, but the tuner type\n");
-		tveeprom_info("indicates otherwise. I will assume that radio is present.\n");
+		pr_info("The eeprom says no radio is present, but the tuner type\n");
+		pr_info("indicates otherwise. I will assume that radio is present.\n");
 		tvee->has_radio = 1;
 	}
 
@@ -718,46 +700,46 @@ void tveeprom_hauppauge_analog(struct i2
 		}
 	}
 
-	tveeprom_info("Hauppauge model %d, rev %s, serial# %u\n",
+	pr_info("Hauppauge model %d, rev %s, serial# %u\n",
 		tvee->model, tvee->rev_str, tvee->serial_number);
 	if (tvee->has_MAC_address == 1)
-		tveeprom_info("MAC address is %pM\n", tvee->MAC_address);
-	tveeprom_info("tuner model is %s (idx %d, type %d)\n",
+		pr_info("MAC address is %pM\n", tvee->MAC_address);
+	pr_info("tuner model is %s (idx %d, type %d)\n",
 		t_name1, tuner1, tvee->tuner_type);
-	tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+	pr_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
 		t_fmt_name1[0], t_fmt_name1[1], t_fmt_name1[2],
 		t_fmt_name1[3],	t_fmt_name1[4], t_fmt_name1[5],
 		t_fmt_name1[6], t_fmt_name1[7],	t_format1);
 	if (tuner2)
-		tveeprom_info("second tuner model is %s (idx %d, type %d)\n",
+		pr_info("second tuner model is %s (idx %d, type %d)\n",
 					t_name2, tuner2, tvee->tuner2_type);
 	if (t_format2)
-		tveeprom_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
+		pr_info("TV standards%s%s%s%s%s%s%s%s (eeprom 0x%02x)\n",
 			t_fmt_name2[0], t_fmt_name2[1], t_fmt_name2[2],
 			t_fmt_name2[3],	t_fmt_name2[4], t_fmt_name2[5],
 			t_fmt_name2[6], t_fmt_name2[7], t_format2);
 	if (audioic < 0) {
-		tveeprom_info("audio processor is unknown (no idx)\n");
+		pr_info("audio processor is unknown (no idx)\n");
 		tvee->audio_processor = TVEEPROM_AUDPROC_OTHER;
 	} else {
 		if (audioic < ARRAY_SIZE(audio_ic))
-			tveeprom_info("audio processor is %s (idx %d)\n",
+			pr_info("audio processor is %s (idx %d)\n",
 					audio_ic[audioic].name, audioic);
 		else
-			tveeprom_info("audio processor is unknown (idx %d)\n",
+			pr_info("audio processor is unknown (idx %d)\n",
 								audioic);
 	}
 	if (tvee->decoder_processor)
-		tveeprom_info("decoder processor is %s (idx %d)\n",
+		pr_info("decoder processor is %s (idx %d)\n",
 			STRM(decoderIC, tvee->decoder_processor),
 			tvee->decoder_processor);
 	if (tvee->has_ir)
-		tveeprom_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
+		pr_info("has %sradio, has %sIR receiver, has %sIR transmitter\n",
 				tvee->has_radio ? "" : "no ",
 				(tvee->has_ir & 2) ? "" : "no ",
 				(tvee->has_ir & 4) ? "" : "no ");
 	else
-		tveeprom_info("has %sradio\n",
+		pr_info("has %sradio\n",
 				tvee->has_radio ? "" : "no ");
 }
 EXPORT_SYMBOL(tveeprom_hauppauge_analog);
@@ -773,26 +755,17 @@ int tveeprom_read(struct i2c_client *c,
 	buf = 0;
 	err = i2c_master_send(c, &buf, 1);
 	if (err != 1) {
-		tveeprom_info("Huh, no eeprom present (err=%d)?\n", err);
+		pr_info("Huh, no eeprom present (err=%d)?\n", err);
 		return -1;
 	}
 	err = i2c_master_recv(c, eedata, len);
 	if (err != len) {
-		tveeprom_warn("i2c eeprom read error (err=%d)\n", err);
+		pr_warn("i2c eeprom read error (err=%d)\n", err);
 		return -1;
 	}
-	if (debug) {
-		int i;
 
-		tveeprom_info("full 256-byte eeprom dump:\n");
-		for (i = 0; i < len; i++) {
-			if (0 == (i % 16))
-				tveeprom_info("%02x:", i);
-			printk(KERN_CONT " %02x", eedata[i]);
-			if (15 == (i % 16))
-				printk(KERN_CONT "\n");
-		}
-	}
+	print_hex_dump_debug("full 256-byte eeprom dump:", DUMP_PREFIX_NONE,
+			     16, 1, eedata, len, true);
 	return 0;
 }
 EXPORT_SYMBOL(tveeprom_read);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c linux-libre-4.10-rc8-gnu/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
--- linux-libre-4.9-gnu/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -117,6 +117,7 @@ void tpg_init(struct tpg_data *tpg, unsi
 	tpg_s_fourcc(tpg, V4L2_PIX_FMT_RGB24);
 	tpg->colorspace = V4L2_COLORSPACE_SRGB;
 	tpg->perc_fill = 100;
+	tpg->hsv_enc = V4L2_HSV_ENC_180;
 }
 EXPORT_SYMBOL_GPL(tpg_init);
 
@@ -234,16 +235,18 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 	case V4L2_PIX_FMT_XBGR32:
 	case V4L2_PIX_FMT_ARGB32:
 	case V4L2_PIX_FMT_ABGR32:
+		tpg->color_enc = TGP_COLOR_ENC_RGB;
+		break;
 	case V4L2_PIX_FMT_GREY:
 	case V4L2_PIX_FMT_Y16:
 	case V4L2_PIX_FMT_Y16_BE:
-		tpg->is_yuv = false;
+		tpg->color_enc = TGP_COLOR_ENC_LUMA;
 		break;
 	case V4L2_PIX_FMT_YUV444:
 	case V4L2_PIX_FMT_YUV555:
 	case V4L2_PIX_FMT_YUV565:
 	case V4L2_PIX_FMT_YUV32:
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
 		break;
 	case V4L2_PIX_FMT_YUV420M:
 	case V4L2_PIX_FMT_YVU420M:
@@ -256,7 +259,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 		tpg->hdownsampling[1] = 2;
 		tpg->hdownsampling[2] = 2;
 		tpg->planes = 3;
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
 		break;
 	case V4L2_PIX_FMT_YUV422M:
 	case V4L2_PIX_FMT_YVU422M:
@@ -268,7 +271,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 		tpg->hdownsampling[1] = 2;
 		tpg->hdownsampling[2] = 2;
 		tpg->planes = 3;
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
 		break;
 	case V4L2_PIX_FMT_NV16M:
 	case V4L2_PIX_FMT_NV61M:
@@ -280,7 +283,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 		tpg->hdownsampling[1] = 1;
 		tpg->hmask[1] = ~1;
 		tpg->planes = 2;
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
 		break;
 	case V4L2_PIX_FMT_NV12M:
 	case V4L2_PIX_FMT_NV21M:
@@ -292,7 +295,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 		tpg->hdownsampling[1] = 1;
 		tpg->hmask[1] = ~1;
 		tpg->planes = 2;
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
 		break;
 	case V4L2_PIX_FMT_YUV444M:
 	case V4L2_PIX_FMT_YVU444M:
@@ -302,21 +305,25 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 		tpg->vdownsampling[2] = 1;
 		tpg->hdownsampling[1] = 1;
 		tpg->hdownsampling[2] = 1;
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
 		break;
 	case V4L2_PIX_FMT_NV24:
 	case V4L2_PIX_FMT_NV42:
 		tpg->vdownsampling[1] = 1;
 		tpg->hdownsampling[1] = 1;
 		tpg->planes = 2;
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
 		break;
 	case V4L2_PIX_FMT_YUYV:
 	case V4L2_PIX_FMT_UYVY:
 	case V4L2_PIX_FMT_YVYU:
 	case V4L2_PIX_FMT_VYUY:
 		tpg->hmask[0] = ~1;
-		tpg->is_yuv = true;
+		tpg->color_enc = TGP_COLOR_ENC_YCBCR;
+		break;
+	case V4L2_PIX_FMT_HSV24:
+	case V4L2_PIX_FMT_HSV32:
+		tpg->color_enc = TGP_COLOR_ENC_HSV;
 		break;
 	default:
 		return false;
@@ -351,6 +358,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 		break;
 	case V4L2_PIX_FMT_RGB24:
 	case V4L2_PIX_FMT_BGR24:
+	case V4L2_PIX_FMT_HSV24:
 		tpg->twopixelsize[0] = 2 * 3;
 		break;
 	case V4L2_PIX_FMT_BGR666:
@@ -361,6 +369,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg,
 	case V4L2_PIX_FMT_ARGB32:
 	case V4L2_PIX_FMT_ABGR32:
 	case V4L2_PIX_FMT_YUV32:
+	case V4L2_PIX_FMT_HSV32:
 		tpg->twopixelsize[0] = 2 * 4;
 		break;
 	case V4L2_PIX_FMT_NV12:
@@ -490,6 +499,71 @@ static inline int linear_to_rec709(int v
 	return tpg_linear_to_rec709[v];
 }
 
+static void color_to_hsv(struct tpg_data *tpg, int r, int g, int b,
+			   int *h, int *s, int *v)
+{
+	int max_rgb, min_rgb, diff_rgb;
+	int aux;
+	int third;
+	int third_size;
+
+	r >>= 4;
+	g >>= 4;
+	b >>= 4;
+
+	/* Value */
+	max_rgb = max3(r, g, b);
+	*v = max_rgb;
+	if (!max_rgb) {
+		*h = 0;
+		*s = 0;
+		return;
+	}
+
+	/* Saturation */
+	min_rgb = min3(r, g, b);
+	diff_rgb = max_rgb - min_rgb;
+	aux = 255 * diff_rgb;
+	aux += max_rgb / 2;
+	aux /= max_rgb;
+	*s = aux;
+	if (!aux) {
+		*h = 0;
+		return;
+	}
+
+	third_size = (tpg->real_hsv_enc == V4L2_HSV_ENC_180) ? 60 : 85;
+
+	/* Hue */
+	if (max_rgb == r) {
+		aux =  g - b;
+		third = 0;
+	} else if (max_rgb == g) {
+		aux =  b - r;
+		third = third_size;
+	} else {
+		aux =  r - g;
+		third = third_size * 2;
+	}
+
+	aux *= third_size / 2;
+	aux += diff_rgb / 2;
+	aux /= diff_rgb;
+	aux += third;
+
+	/* Clamp Hue */
+	if (tpg->real_hsv_enc == V4L2_HSV_ENC_180) {
+		if (aux < 0)
+			aux += 180;
+		else if (aux > 180)
+			aux -= 180;
+	} else {
+		aux = aux & 0xff;
+	}
+
+	*h = aux;
+}
+
 static void rgb2ycbcr(const int m[3][3], int r, int g, int b,
 			int y_offset, int *y, int *cb, int *cr)
 {
@@ -729,6 +803,8 @@ static void precalculate_color(struct tp
 	int r = tpg_colors[col].r;
 	int g = tpg_colors[col].g;
 	int b = tpg_colors[col].b;
+	int y, cb, cr;
+	bool ycbcr_valid = false;
 
 	if (k == TPG_COLOR_TEXTBG) {
 		col = tpg_get_textbg_color(tpg);
@@ -759,9 +835,9 @@ static void precalculate_color(struct tp
 		g <<= 4;
 		b <<= 4;
 	}
-	if (tpg->qual == TPG_QUAL_GRAY || tpg->fourcc == V4L2_PIX_FMT_GREY ||
-	    tpg->fourcc == V4L2_PIX_FMT_Y16 ||
-	    tpg->fourcc == V4L2_PIX_FMT_Y16_BE) {
+
+	if (tpg->qual == TPG_QUAL_GRAY ||
+	    tpg->color_enc ==  TGP_COLOR_ENC_LUMA) {
 		/* Rec. 709 Luma function */
 		/* (0.2126, 0.7152, 0.0722) * (255 * 256) */
 		r = g = b = (13879 * r + 46688 * g + 4713 * b) >> 16;
@@ -775,7 +851,8 @@ static void precalculate_color(struct tp
 	 * Remember that r, g and b are still in the 0 - 0xff0 range.
 	 */
 	if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED &&
-	    tpg->rgb_range == V4L2_DV_RGB_RANGE_FULL && !tpg->is_yuv) {
+	    tpg->rgb_range == V4L2_DV_RGB_RANGE_FULL &&
+	    tpg->color_enc == TGP_COLOR_ENC_RGB) {
 		/*
 		 * Convert from full range (which is what r, g and b are)
 		 * to limited range (which is the 'real' RGB range), which
@@ -785,7 +862,9 @@ static void precalculate_color(struct tp
 		g = (g * 219) / 255 + (16 << 4);
 		b = (b * 219) / 255 + (16 << 4);
 	} else if (tpg->real_rgb_range != V4L2_DV_RGB_RANGE_LIMITED &&
-		   tpg->rgb_range == V4L2_DV_RGB_RANGE_LIMITED && !tpg->is_yuv) {
+		   tpg->rgb_range == V4L2_DV_RGB_RANGE_LIMITED &&
+		   tpg->color_enc == TGP_COLOR_ENC_RGB) {
+
 		/*
 		 * Clamp r, g and b to the limited range and convert to full
 		 * range since that's what we deliver.
@@ -798,10 +877,10 @@ static void precalculate_color(struct tp
 		b = (b - (16 << 4)) * 255 / 219;
 	}
 
-	if (tpg->brightness != 128 || tpg->contrast != 128 ||
-	    tpg->saturation != 128 || tpg->hue) {
+	if ((tpg->brightness != 128 || tpg->contrast != 128 ||
+	     tpg->saturation != 128 || tpg->hue) &&
+	    tpg->color_enc != TGP_COLOR_ENC_LUMA) {
 		/* Implement these operations */
-		int y, cb, cr;
 		int tmp_cb, tmp_cr;
 
 		/* First convert to YCbCr */
@@ -818,29 +897,45 @@ static void precalculate_color(struct tp
 
 		cb = (128 << 4) + (tmp_cb * tpg->contrast * tpg->saturation) / (128 * 128);
 		cr = (128 << 4) + (tmp_cr * tpg->contrast * tpg->saturation) / (128 * 128);
-		if (tpg->is_yuv) {
-			tpg->colors[k][0] = clamp(y >> 4, 1, 254);
-			tpg->colors[k][1] = clamp(cb >> 4, 1, 254);
-			tpg->colors[k][2] = clamp(cr >> 4, 1, 254);
-			return;
-		}
-		ycbcr_to_color(tpg, y, cb, cr, &r, &g, &b);
+		if (tpg->color_enc == TGP_COLOR_ENC_YCBCR)
+			ycbcr_valid = true;
+		else
+			ycbcr_to_color(tpg, y, cb, cr, &r, &g, &b);
+	} else if ((tpg->brightness != 128 || tpg->contrast != 128) &&
+		   tpg->color_enc == TGP_COLOR_ENC_LUMA) {
+		r = (16 << 4) + ((r - (16 << 4)) * tpg->contrast) / 128;
+		r += (tpg->brightness << 4) - (128 << 4);
 	}
 
-	if (tpg->is_yuv) {
-		/* Convert to YCbCr */
-		int y, cb, cr;
+	switch (tpg->color_enc) {
+	case TGP_COLOR_ENC_HSV:
+	{
+		int h, s, v;
 
-		color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
+		color_to_hsv(tpg, r, g, b, &h, &s, &v);
+		tpg->colors[k][0] = h;
+		tpg->colors[k][1] = s;
+		tpg->colors[k][2] = v;
+		break;
+	}
+	case TGP_COLOR_ENC_YCBCR:
+	{
+		/* Convert to YCbCr */
+		if (!ycbcr_valid)
+			color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
 
+		y >>= 4;
+		cb >>= 4;
+		cr >>= 4;
 		if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
-			y = clamp(y, 16 << 4, 235 << 4);
-			cb = clamp(cb, 16 << 4, 240 << 4);
-			cr = clamp(cr, 16 << 4, 240 << 4);
+			y = clamp(y, 16, 235);
+			cb = clamp(cb, 16, 240);
+			cr = clamp(cr, 16, 240);
+		} else {
+			y = clamp(y, 1, 254);
+			cb = clamp(cb, 1, 254);
+			cr = clamp(cr, 1, 254);
 		}
-		y = clamp(y >> 4, 1, 254);
-		cb = clamp(cb >> 4, 1, 254);
-		cr = clamp(cr >> 4, 1, 254);
 		switch (tpg->fourcc) {
 		case V4L2_PIX_FMT_YUV444:
 			y >>= 4;
@@ -861,7 +956,15 @@ static void precalculate_color(struct tp
 		tpg->colors[k][0] = y;
 		tpg->colors[k][1] = cb;
 		tpg->colors[k][2] = cr;
-	} else {
+		break;
+	}
+	case TGP_COLOR_ENC_LUMA:
+	{
+		tpg->colors[k][0] = r >> 4;
+		break;
+	}
+	case TGP_COLOR_ENC_RGB:
+	{
 		if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
 			r = (r * 219) / 255 + (16 << 4);
 			g = (g * 219) / 255 + (16 << 4);
@@ -911,6 +1014,8 @@ static void precalculate_color(struct tp
 		tpg->colors[k][0] = r;
 		tpg->colors[k][1] = g;
 		tpg->colors[k][2] = b;
+		break;
+	}
 	}
 }
 
@@ -928,7 +1033,7 @@ static void gen_twopix(struct tpg_data *
 {
 	unsigned offset = odd * tpg->twopixelsize[0] / 2;
 	u8 alpha = tpg->alpha_component;
-	u8 r_y, g_u, b_v;
+	u8 r_y_h, g_u_s, b_v;
 
 	if (tpg->alpha_red_only && color != TPG_COLOR_CSC_RED &&
 				   color != TPG_COLOR_100_RED &&
@@ -936,161 +1041,161 @@ static void gen_twopix(struct tpg_data *
 		alpha = 0;
 	if (color == TPG_COLOR_RANDOM)
 		precalculate_color(tpg, color);
-	r_y = tpg->colors[color][0]; /* R or precalculated Y */
-	g_u = tpg->colors[color][1]; /* G or precalculated U */
+	r_y_h = tpg->colors[color][0]; /* R or precalculated Y, H */
+	g_u_s = tpg->colors[color][1]; /* G or precalculated U, V */
 	b_v = tpg->colors[color][2]; /* B or precalculated V */
 
 	switch (tpg->fourcc) {
 	case V4L2_PIX_FMT_GREY:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		break;
 	case V4L2_PIX_FMT_Y16:
 		/*
-		 * Ideally both bytes should be set to r_y, but then you won't
+		 * Ideally both bytes should be set to r_y_h, but then you won't
 		 * be able to detect endian problems. So keep it 0 except for
-		 * the corner case where r_y is 0xff so white really will be
+		 * the corner case where r_y_h is 0xff so white really will be
 		 * white (0xffff).
 		 */
-		buf[0][offset] = r_y == 0xff ? r_y : 0;
-		buf[0][offset+1] = r_y;
+		buf[0][offset] = r_y_h == 0xff ? r_y_h : 0;
+		buf[0][offset+1] = r_y_h;
 		break;
 	case V4L2_PIX_FMT_Y16_BE:
 		/* See comment for V4L2_PIX_FMT_Y16 above */
-		buf[0][offset] = r_y;
-		buf[0][offset+1] = r_y == 0xff ? r_y : 0;
+		buf[0][offset] = r_y_h;
+		buf[0][offset+1] = r_y_h == 0xff ? r_y_h : 0;
 		break;
 	case V4L2_PIX_FMT_YUV422M:
 	case V4L2_PIX_FMT_YUV422P:
 	case V4L2_PIX_FMT_YUV420:
 	case V4L2_PIX_FMT_YUV420M:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		if (odd) {
-			buf[1][0] = (buf[1][0] + g_u) / 2;
+			buf[1][0] = (buf[1][0] + g_u_s) / 2;
 			buf[2][0] = (buf[2][0] + b_v) / 2;
 			buf[1][1] = buf[1][0];
 			buf[2][1] = buf[2][0];
 			break;
 		}
-		buf[1][0] = g_u;
+		buf[1][0] = g_u_s;
 		buf[2][0] = b_v;
 		break;
 	case V4L2_PIX_FMT_YVU422M:
 	case V4L2_PIX_FMT_YVU420:
 	case V4L2_PIX_FMT_YVU420M:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		if (odd) {
 			buf[1][0] = (buf[1][0] + b_v) / 2;
-			buf[2][0] = (buf[2][0] + g_u) / 2;
+			buf[2][0] = (buf[2][0] + g_u_s) / 2;
 			buf[1][1] = buf[1][0];
 			buf[2][1] = buf[2][0];
 			break;
 		}
 		buf[1][0] = b_v;
-		buf[2][0] = g_u;
+		buf[2][0] = g_u_s;
 		break;
 
 	case V4L2_PIX_FMT_NV12:
 	case V4L2_PIX_FMT_NV12M:
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV16M:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		if (odd) {
-			buf[1][0] = (buf[1][0] + g_u) / 2;
+			buf[1][0] = (buf[1][0] + g_u_s) / 2;
 			buf[1][1] = (buf[1][1] + b_v) / 2;
 			break;
 		}
-		buf[1][0] = g_u;
+		buf[1][0] = g_u_s;
 		buf[1][1] = b_v;
 		break;
 	case V4L2_PIX_FMT_NV21:
 	case V4L2_PIX_FMT_NV21M:
 	case V4L2_PIX_FMT_NV61:
 	case V4L2_PIX_FMT_NV61M:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		if (odd) {
 			buf[1][0] = (buf[1][0] + b_v) / 2;
-			buf[1][1] = (buf[1][1] + g_u) / 2;
+			buf[1][1] = (buf[1][1] + g_u_s) / 2;
 			break;
 		}
 		buf[1][0] = b_v;
-		buf[1][1] = g_u;
+		buf[1][1] = g_u_s;
 		break;
 
 	case V4L2_PIX_FMT_YUV444M:
-		buf[0][offset] = r_y;
-		buf[1][offset] = g_u;
+		buf[0][offset] = r_y_h;
+		buf[1][offset] = g_u_s;
 		buf[2][offset] = b_v;
 		break;
 
 	case V4L2_PIX_FMT_YVU444M:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		buf[1][offset] = b_v;
-		buf[2][offset] = g_u;
+		buf[2][offset] = g_u_s;
 		break;
 
 	case V4L2_PIX_FMT_NV24:
-		buf[0][offset] = r_y;
-		buf[1][2 * offset] = g_u;
+		buf[0][offset] = r_y_h;
+		buf[1][2 * offset] = g_u_s;
 		buf[1][2 * offset + 1] = b_v;
 		break;
 
 	case V4L2_PIX_FMT_NV42:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		buf[1][2 * offset] = b_v;
-		buf[1][2 * offset + 1] = g_u;
+		buf[1][2 * offset + 1] = g_u_s;
 		break;
 
 	case V4L2_PIX_FMT_YUYV:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		if (odd) {
-			buf[0][1] = (buf[0][1] + g_u) / 2;
+			buf[0][1] = (buf[0][1] + g_u_s) / 2;
 			buf[0][3] = (buf[0][3] + b_v) / 2;
 			break;
 		}
-		buf[0][1] = g_u;
+		buf[0][1] = g_u_s;
 		buf[0][3] = b_v;
 		break;
 	case V4L2_PIX_FMT_UYVY:
-		buf[0][offset + 1] = r_y;
+		buf[0][offset + 1] = r_y_h;
 		if (odd) {
-			buf[0][0] = (buf[0][0] + g_u) / 2;
+			buf[0][0] = (buf[0][0] + g_u_s) / 2;
 			buf[0][2] = (buf[0][2] + b_v) / 2;
 			break;
 		}
-		buf[0][0] = g_u;
+		buf[0][0] = g_u_s;
 		buf[0][2] = b_v;
 		break;
 	case V4L2_PIX_FMT_YVYU:
-		buf[0][offset] = r_y;
+		buf[0][offset] = r_y_h;
 		if (odd) {
 			buf[0][1] = (buf[0][1] + b_v) / 2;
-			buf[0][3] = (buf[0][3] + g_u) / 2;
+			buf[0][3] = (buf[0][3] + g_u_s) / 2;
 			break;
 		}
 		buf[0][1] = b_v;
-		buf[0][3] = g_u;
+		buf[0][3] = g_u_s;
 		break;
 	case V4L2_PIX_FMT_VYUY:
-		buf[0][offset + 1] = r_y;
+		buf[0][offset + 1] = r_y_h;
 		if (odd) {
 			buf[0][0] = (buf[0][0] + b_v) / 2;
-			buf[0][2] = (buf[0][2] + g_u) / 2;
+			buf[0][2] = (buf[0][2] + g_u_s) / 2;
 			break;
 		}
 		buf[0][0] = b_v;
-		buf[0][2] = g_u;
+		buf[0][2] = g_u_s;
 		break;
 	case V4L2_PIX_FMT_RGB332:
-		buf[0][offset] = (r_y << 5) | (g_u << 2) | b_v;
+		buf[0][offset] = (r_y_h << 5) | (g_u_s << 2) | b_v;
 		break;
 	case V4L2_PIX_FMT_YUV565:
 	case V4L2_PIX_FMT_RGB565:
-		buf[0][offset] = (g_u << 5) | b_v;
-		buf[0][offset + 1] = (r_y << 3) | (g_u >> 3);
+		buf[0][offset] = (g_u_s << 5) | b_v;
+		buf[0][offset + 1] = (r_y_h << 3) | (g_u_s >> 3);
 		break;
 	case V4L2_PIX_FMT_RGB565X:
-		buf[0][offset] = (r_y << 3) | (g_u >> 3);
-		buf[0][offset + 1] = (g_u << 5) | b_v;
+		buf[0][offset] = (r_y_h << 3) | (g_u_s >> 3);
+		buf[0][offset + 1] = (g_u_s << 5) | b_v;
 		break;
 	case V4L2_PIX_FMT_RGB444:
 	case V4L2_PIX_FMT_XRGB444:
@@ -1098,8 +1203,8 @@ static void gen_twopix(struct tpg_data *
 		/* fall through */
 	case V4L2_PIX_FMT_YUV444:
 	case V4L2_PIX_FMT_ARGB444:
-		buf[0][offset] = (g_u << 4) | b_v;
-		buf[0][offset + 1] = (alpha & 0xf0) | r_y;
+		buf[0][offset] = (g_u_s << 4) | b_v;
+		buf[0][offset + 1] = (alpha & 0xf0) | r_y_h;
 		break;
 	case V4L2_PIX_FMT_RGB555:
 	case V4L2_PIX_FMT_XRGB555:
@@ -1107,42 +1212,45 @@ static void gen_twopix(struct tpg_data *
 		/* fall through */
 	case V4L2_PIX_FMT_YUV555:
 	case V4L2_PIX_FMT_ARGB555:
-		buf[0][offset] = (g_u << 5) | b_v;
-		buf[0][offset + 1] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
+		buf[0][offset] = (g_u_s << 5) | b_v;
+		buf[0][offset + 1] = (alpha & 0x80) | (r_y_h << 2)
+						    | (g_u_s >> 3);
 		break;
 	case V4L2_PIX_FMT_RGB555X:
 	case V4L2_PIX_FMT_XRGB555X:
 		alpha = 0;
 		/* fall through */
 	case V4L2_PIX_FMT_ARGB555X:
-		buf[0][offset] = (alpha & 0x80) | (r_y << 2) | (g_u >> 3);
-		buf[0][offset + 1] = (g_u << 5) | b_v;
+		buf[0][offset] = (alpha & 0x80) | (r_y_h << 2) | (g_u_s >> 3);
+		buf[0][offset + 1] = (g_u_s << 5) | b_v;
 		break;
 	case V4L2_PIX_FMT_RGB24:
-		buf[0][offset] = r_y;
-		buf[0][offset + 1] = g_u;
+	case V4L2_PIX_FMT_HSV24:
+		buf[0][offset] = r_y_h;
+		buf[0][offset + 1] = g_u_s;
 		buf[0][offset + 2] = b_v;
 		break;
 	case V4L2_PIX_FMT_BGR24:
 		buf[0][offset] = b_v;
-		buf[0][offset + 1] = g_u;
-		buf[0][offset + 2] = r_y;
+		buf[0][offset + 1] = g_u_s;
+		buf[0][offset + 2] = r_y_h;
 		break;
 	case V4L2_PIX_FMT_BGR666:
-		buf[0][offset] = (b_v << 2) | (g_u >> 4);
-		buf[0][offset + 1] = (g_u << 4) | (r_y >> 2);
-		buf[0][offset + 2] = r_y << 6;
+		buf[0][offset] = (b_v << 2) | (g_u_s >> 4);
+		buf[0][offset + 1] = (g_u_s << 4) | (r_y_h >> 2);
+		buf[0][offset + 2] = r_y_h << 6;
 		buf[0][offset + 3] = 0;
 		break;
 	case V4L2_PIX_FMT_RGB32:
 	case V4L2_PIX_FMT_XRGB32:
+	case V4L2_PIX_FMT_HSV32:
 		alpha = 0;
 		/* fall through */
 	case V4L2_PIX_FMT_YUV32:
 	case V4L2_PIX_FMT_ARGB32:
 		buf[0][offset] = alpha;
-		buf[0][offset + 1] = r_y;
-		buf[0][offset + 2] = g_u;
+		buf[0][offset + 1] = r_y_h;
+		buf[0][offset + 2] = g_u_s;
 		buf[0][offset + 3] = b_v;
 		break;
 	case V4L2_PIX_FMT_BGR32:
@@ -1151,87 +1259,87 @@ static void gen_twopix(struct tpg_data *
 		/* fall through */
 	case V4L2_PIX_FMT_ABGR32:
 		buf[0][offset] = b_v;
-		buf[0][offset + 1] = g_u;
-		buf[0][offset + 2] = r_y;
+		buf[0][offset + 1] = g_u_s;
+		buf[0][offset + 2] = r_y_h;
 		buf[0][offset + 3] = alpha;
 		break;
 	case V4L2_PIX_FMT_SBGGR8:
-		buf[0][offset] = odd ? g_u : b_v;
-		buf[1][offset] = odd ? r_y : g_u;
+		buf[0][offset] = odd ? g_u_s : b_v;
+		buf[1][offset] = odd ? r_y_h : g_u_s;
 		break;
 	case V4L2_PIX_FMT_SGBRG8:
-		buf[0][offset] = odd ? b_v : g_u;
-		buf[1][offset] = odd ? g_u : r_y;
+		buf[0][offset] = odd ? b_v : g_u_s;
+		buf[1][offset] = odd ? g_u_s : r_y_h;
 		break;
 	case V4L2_PIX_FMT_SGRBG8:
-		buf[0][offset] = odd ? r_y : g_u;
-		buf[1][offset] = odd ? g_u : b_v;
+		buf[0][offset] = odd ? r_y_h : g_u_s;
+		buf[1][offset] = odd ? g_u_s : b_v;
 		break;
 	case V4L2_PIX_FMT_SRGGB8:
-		buf[0][offset] = odd ? g_u : r_y;
-		buf[1][offset] = odd ? b_v : g_u;
+		buf[0][offset] = odd ? g_u_s : r_y_h;
+		buf[1][offset] = odd ? b_v : g_u_s;
 		break;
 	case V4L2_PIX_FMT_SBGGR10:
-		buf[0][offset] = odd ? g_u << 2 : b_v << 2;
-		buf[0][offset + 1] = odd ? g_u >> 6 : b_v >> 6;
-		buf[1][offset] = odd ? r_y << 2 : g_u << 2;
-		buf[1][offset + 1] = odd ? r_y >> 6 : g_u >> 6;
+		buf[0][offset] = odd ? g_u_s << 2 : b_v << 2;
+		buf[0][offset + 1] = odd ? g_u_s >> 6 : b_v >> 6;
+		buf[1][offset] = odd ? r_y_h << 2 : g_u_s << 2;
+		buf[1][offset + 1] = odd ? r_y_h >> 6 : g_u_s >> 6;
 		buf[0][offset] |= (buf[0][offset] >> 2) & 3;
 		buf[1][offset] |= (buf[1][offset] >> 2) & 3;
 		break;
 	case V4L2_PIX_FMT_SGBRG10:
-		buf[0][offset] = odd ? b_v << 2 : g_u << 2;
-		buf[0][offset + 1] = odd ? b_v >> 6 : g_u >> 6;
-		buf[1][offset] = odd ? g_u << 2 : r_y << 2;
-		buf[1][offset + 1] = odd ? g_u >> 6 : r_y >> 6;
+		buf[0][offset] = odd ? b_v << 2 : g_u_s << 2;
+		buf[0][offset + 1] = odd ? b_v >> 6 : g_u_s >> 6;
+		buf[1][offset] = odd ? g_u_s << 2 : r_y_h << 2;
+		buf[1][offset + 1] = odd ? g_u_s >> 6 : r_y_h >> 6;
 		buf[0][offset] |= (buf[0][offset] >> 2) & 3;
 		buf[1][offset] |= (buf[1][offset] >> 2) & 3;
 		break;
 	case V4L2_PIX_FMT_SGRBG10:
-		buf[0][offset] = odd ? r_y << 2 : g_u << 2;
-		buf[0][offset + 1] = odd ? r_y >> 6 : g_u >> 6;
-		buf[1][offset] = odd ? g_u << 2 : b_v << 2;
-		buf[1][offset + 1] = odd ? g_u >> 6 : b_v >> 6;
+		buf[0][offset] = odd ? r_y_h << 2 : g_u_s << 2;
+		buf[0][offset + 1] = odd ? r_y_h >> 6 : g_u_s >> 6;
+		buf[1][offset] = odd ? g_u_s << 2 : b_v << 2;
+		buf[1][offset + 1] = odd ? g_u_s >> 6 : b_v >> 6;
 		buf[0][offset] |= (buf[0][offset] >> 2) & 3;
 		buf[1][offset] |= (buf[1][offset] >> 2) & 3;
 		break;
 	case V4L2_PIX_FMT_SRGGB10:
-		buf[0][offset] = odd ? g_u << 2 : r_y << 2;
-		buf[0][offset + 1] = odd ? g_u >> 6 : r_y >> 6;
-		buf[1][offset] = odd ? b_v << 2 : g_u << 2;
-		buf[1][offset + 1] = odd ? b_v >> 6 : g_u >> 6;
+		buf[0][offset] = odd ? g_u_s << 2 : r_y_h << 2;
+		buf[0][offset + 1] = odd ? g_u_s >> 6 : r_y_h >> 6;
+		buf[1][offset] = odd ? b_v << 2 : g_u_s << 2;
+		buf[1][offset + 1] = odd ? b_v >> 6 : g_u_s >> 6;
 		buf[0][offset] |= (buf[0][offset] >> 2) & 3;
 		buf[1][offset] |= (buf[1][offset] >> 2) & 3;
 		break;
 	case V4L2_PIX_FMT_SBGGR12:
-		buf[0][offset] = odd ? g_u << 4 : b_v << 4;
-		buf[0][offset + 1] = odd ? g_u >> 4 : b_v >> 4;
-		buf[1][offset] = odd ? r_y << 4 : g_u << 4;
-		buf[1][offset + 1] = odd ? r_y >> 4 : g_u >> 4;
+		buf[0][offset] = odd ? g_u_s << 4 : b_v << 4;
+		buf[0][offset + 1] = odd ? g_u_s >> 4 : b_v >> 4;
+		buf[1][offset] = odd ? r_y_h << 4 : g_u_s << 4;
+		buf[1][offset + 1] = odd ? r_y_h >> 4 : g_u_s >> 4;
 		buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
 		buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
 		break;
 	case V4L2_PIX_FMT_SGBRG12:
-		buf[0][offset] = odd ? b_v << 4 : g_u << 4;
-		buf[0][offset + 1] = odd ? b_v >> 4 : g_u >> 4;
-		buf[1][offset] = odd ? g_u << 4 : r_y << 4;
-		buf[1][offset + 1] = odd ? g_u >> 4 : r_y >> 4;
+		buf[0][offset] = odd ? b_v << 4 : g_u_s << 4;
+		buf[0][offset + 1] = odd ? b_v >> 4 : g_u_s >> 4;
+		buf[1][offset] = odd ? g_u_s << 4 : r_y_h << 4;
+		buf[1][offset + 1] = odd ? g_u_s >> 4 : r_y_h >> 4;
 		buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
 		buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
 		break;
 	case V4L2_PIX_FMT_SGRBG12:
-		buf[0][offset] = odd ? r_y << 4 : g_u << 4;
-		buf[0][offset + 1] = odd ? r_y >> 4 : g_u >> 4;
-		buf[1][offset] = odd ? g_u << 4 : b_v << 4;
-		buf[1][offset + 1] = odd ? g_u >> 4 : b_v >> 4;
+		buf[0][offset] = odd ? r_y_h << 4 : g_u_s << 4;
+		buf[0][offset + 1] = odd ? r_y_h >> 4 : g_u_s >> 4;
+		buf[1][offset] = odd ? g_u_s << 4 : b_v << 4;
+		buf[1][offset + 1] = odd ? g_u_s >> 4 : b_v >> 4;
 		buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
 		buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
 		break;
 	case V4L2_PIX_FMT_SRGGB12:
-		buf[0][offset] = odd ? g_u << 4 : r_y << 4;
-		buf[0][offset + 1] = odd ? g_u >> 4 : r_y >> 4;
-		buf[1][offset] = odd ? b_v << 4 : g_u << 4;
-		buf[1][offset + 1] = odd ? b_v >> 4 : g_u >> 4;
+		buf[0][offset] = odd ? g_u_s << 4 : r_y_h << 4;
+		buf[0][offset + 1] = odd ? g_u_s >> 4 : r_y_h >> 4;
+		buf[1][offset] = odd ? b_v << 4 : g_u_s << 4;
+		buf[1][offset + 1] = odd ? b_v >> 4 : g_u_s >> 4;
 		buf[0][offset] |= (buf[0][offset] >> 4) & 0xf;
 		buf[1][offset] |= (buf[1][offset] >> 4) & 0xf;
 		break;
@@ -1828,6 +1936,7 @@ static void tpg_recalc(struct tpg_data *
 		tpg->recalc_lines = true;
 		tpg->real_xfer_func = tpg->xfer_func;
 		tpg->real_ycbcr_enc = tpg->ycbcr_enc;
+		tpg->real_hsv_enc = tpg->hsv_enc;
 		tpg->real_quantization = tpg->quantization;
 
 		if (tpg->xfer_func == V4L2_XFER_FUNC_DEFAULT)
@@ -1840,7 +1949,8 @@ static void tpg_recalc(struct tpg_data *
 
 		if (tpg->quantization == V4L2_QUANTIZATION_DEFAULT)
 			tpg->real_quantization =
-				V4L2_MAP_QUANTIZATION_DEFAULT(!tpg->is_yuv,
+				V4L2_MAP_QUANTIZATION_DEFAULT(
+					tpg->color_enc != TGP_COLOR_ENC_YCBCR,
 					tpg->colorspace, tpg->real_ycbcr_enc);
 
 		tpg_precalculate_colors(tpg);
@@ -1887,11 +1997,28 @@ static int tpg_pattern_avg(const struct
 	return -1;
 }
 
+static const char *tpg_color_enc_str(enum tgp_color_enc
+						 color_enc)
+{
+	switch (color_enc) {
+	case TGP_COLOR_ENC_HSV:
+		return "HSV";
+	case TGP_COLOR_ENC_YCBCR:
+		return "Y'CbCr";
+	case TGP_COLOR_ENC_LUMA:
+		return "Luma";
+	case TGP_COLOR_ENC_RGB:
+	default:
+		return "R'G'B";
+
+	}
+}
+
 void tpg_log_status(struct tpg_data *tpg)
 {
 	pr_info("tpg source WxH: %ux%u (%s)\n",
-			tpg->src_width, tpg->src_height,
-			tpg->is_yuv ? "YCbCr" : "RGB");
+		tpg->src_width, tpg->src_height,
+		tpg_color_enc_str(tpg->color_enc));
 	pr_info("tpg field: %u\n", tpg->field);
 	pr_info("tpg crop: %ux%u@%dx%d\n", tpg->crop.width, tpg->crop.height,
 			tpg->crop.left, tpg->crop.top);
@@ -1900,6 +2027,7 @@ void tpg_log_status(struct tpg_data *tpg
 	pr_info("tpg colorspace: %d\n", tpg->colorspace);
 	pr_info("tpg transfer function: %d/%d\n", tpg->xfer_func, tpg->real_xfer_func);
 	pr_info("tpg Y'CbCr encoding: %d/%d\n", tpg->ycbcr_enc, tpg->real_ycbcr_enc);
+	pr_info("tpg HSV encoding: %d/%d\n", tpg->hsv_enc, tpg->real_hsv_enc);
 	pr_info("tpg quantization: %d/%d\n", tpg->quantization, tpg->real_quantization);
 	pr_info("tpg RGB range: %d/%d\n", tpg->rgb_range, tpg->real_rgb_range);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/demux.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/demux.h
--- linux-libre-4.9-gnu/drivers/media/dvb-core/demux.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/demux.h	2017-02-12 16:03:20.000000000 -0500
@@ -103,7 +103,6 @@ struct dmx_ts_feed {
 		   u16 pid,
 		   int type,
 		   enum dmx_ts_pes pes_type,
-		   size_t circular_buffer_size,
 		   ktime_t timeout);
 	int (*start_filtering)(struct dmx_ts_feed *feed);
 	int (*stop_filtering)(struct dmx_ts_feed *feed);
@@ -181,7 +180,6 @@ struct dmx_section_feed {
 	/* public: */
 	int (*set)(struct dmx_section_feed *feed,
 		   u16 pid,
-		   size_t circular_buffer_size,
 		   int check_crc);
 	int (*allocate_filter)(struct dmx_section_feed *feed,
 			       struct dmx_section_filter **filter);
@@ -206,8 +204,7 @@ struct dmx_section_feed {
  * the &dmx_demux.
  * Any TS packets that match the filter settings are copied to a circular
  * buffer. The filtered TS packets are delivered to the client using this
- * callback function. The size of the circular buffer is controlled by the
- * circular_buffer_size parameter of the &dmx_ts_feed.@set function.
+ * callback function.
  * It is expected that the @buffer1 and @buffer2 callback parameters point to
  * addresses within the circular buffer, but other implementations are also
  * possible. Note that the called party should not try to free the memory
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dmxdev.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dmxdev.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dmxdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dmxdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,6 +20,8 @@
  *
  */
 
+#define pr_fmt(fmt) "dmxdev: " fmt
+
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -28,7 +30,7 @@
 #include <linux/poll.h>
 #include <linux/ioctl.h>
 #include <linux/wait.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include "dmxdev.h"
 
 static int debug;
@@ -36,7 +38,11 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
 
-#define dprintk	if (debug) printk
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+			__func__, ##arg);				\
+} while (0)
 
 static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf,
 				   const u8 *src, size_t len)
@@ -50,7 +56,7 @@ static int dvb_dmxdev_buffer_write(struc
 
 	free = dvb_ringbuffer_free(buf);
 	if (len > free) {
-		dprintk("dmxdev: buffer overflow\n");
+		dprintk("buffer overflow\n");
 		return -EOVERFLOW;
 	}
 
@@ -126,7 +132,7 @@ static int dvb_dvr_open(struct inode *in
 	struct dmxdev *dmxdev = dvbdev->priv;
 	struct dmx_frontend *front;
 
-	dprintk("function : %s\n", __func__);
+	dprintk("%s\n", __func__);
 
 	if (mutex_lock_interruptible(&dmxdev->mutex))
 		return -ERESTARTSYS;
@@ -258,7 +264,7 @@ static int dvb_dvr_set_buffer_size(struc
 	void *newmem;
 	void *oldmem;
 
-	dprintk("function : %s\n", __func__);
+	dprintk("%s\n", __func__);
 
 	if (buf->size == size)
 		return 0;
@@ -367,7 +373,7 @@ static int dvb_dmxdev_section_callback(c
 		return 0;
 	}
 	del_timer(&dmxdevfilter->timer);
-	dprintk("dmxdev: section callback %*ph\n", 6, buffer1);
+	dprintk("section callback %*ph\n", 6, buffer1);
 	ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
 				      buffer1_len);
 	if (ret == buffer1_len) {
@@ -556,7 +562,7 @@ static int dvb_dmxdev_start_feed(struct
 				 struct dmxdev_filter *filter,
 				 struct dmxdev_feed *feed)
 {
-	ktime_t timeout = ktime_set(0, 0);
+	ktime_t timeout = 0;
 	struct dmx_pes_filter_params *para = &filter->params.pes;
 	dmx_output_t otype;
 	int ret;
@@ -589,7 +595,7 @@ static int dvb_dmxdev_start_feed(struct
 	tsfeed = feed->ts;
 	tsfeed->priv = filter;
 
-	ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, 32768, timeout);
+	ret = tsfeed->set(tsfeed, feed->pid, ts_type, ts_pes, timeout);
 	if (ret < 0) {
 		dmxdev->demux->release_ts_feed(dmxdev->demux, tsfeed);
 		return ret;
@@ -655,15 +661,15 @@ static int dvb_dmxdev_filter_start(struc
 								   secfeed,
 								   dvb_dmxdev_section_callback);
 			if (ret < 0) {
-				printk("DVB (%s): could not alloc feed\n",
+				pr_err("DVB (%s): could not alloc feed\n",
 				       __func__);
 				return ret;
 			}
 
-			ret = (*secfeed)->set(*secfeed, para->pid, 32768,
+			ret = (*secfeed)->set(*secfeed, para->pid,
 					      (para->flags & DMX_CHECK_CRC) ? 1 : 0);
 			if (ret < 0) {
-				printk("DVB (%s): could not set feed\n",
+				pr_err("DVB (%s): could not set feed\n",
 				       __func__);
 				dvb_dmxdev_feed_restart(filter);
 				return ret;
@@ -844,7 +850,7 @@ static int dvb_dmxdev_filter_set(struct
 				 struct dmxdev_filter *dmxdevfilter,
 				 struct dmx_sct_filter_params *params)
 {
-	dprintk("function : %s, PID=0x%04x, flags=%02x, timeout=%d\n",
+	dprintk("%s: PID=0x%04x, flags=%02x, timeout=%d\n",
 		__func__, params->pid, params->flags, params->timeout);
 
 	dvb_dmxdev_filter_stop(dmxdevfilter);
@@ -1184,7 +1190,7 @@ static unsigned int dvb_dvr_poll(struct
 	struct dmxdev *dmxdev = dvbdev->priv;
 	unsigned int mask = 0;
 
-	dprintk("function : %s\n", __func__);
+	dprintk("%s\n", __func__);
 
 	if (dmxdev->exit)
 		return POLLERR;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_ca_en50221.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_ca_en50221.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_ca_en50221.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_ca_en50221.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,8 @@
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  */
 
+#define pr_fmt(fmt) "dvb_ca_en50221: " fmt
+
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/list.h>
@@ -46,7 +48,10 @@ static int dvb_ca_en50221_debug;
 module_param_named(cam_debug, dvb_ca_en50221_debug, int, 0644);
 MODULE_PARM_DESC(cam_debug, "enable verbose debug messages");
 
-#define dprintk if (dvb_ca_en50221_debug) printk
+#define dprintk(fmt, arg...) do {					\
+	if (dvb_ca_en50221_debug)					\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg);\
+} while (0)
 
 #define INIT_TIMEOUT_SECS 10
 
@@ -166,7 +171,7 @@ static void dvb_ca_private_free(struct d
 {
 	unsigned int i;
 
-	dvb_unregister_device(ca->dvbdev);
+	dvb_free_device(ca->dvbdev);
 	for (i = 0; i < ca->slot_count; i++)
 		vfree(ca->slot_info[i].rx_buffer.data);
 
@@ -298,7 +303,8 @@ static int dvb_ca_en50221_wait_if_status
 
 		/* if we got the flags, it was successful! */
 		if (res & waitfor) {
-			dprintk("%s succeeded timeout:%lu\n", __func__, jiffies - start);
+			dprintk("%s succeeded timeout:%lu\n",
+				__func__, jiffies - start);
 			return 0;
 		}
 
@@ -519,8 +525,9 @@ static int dvb_ca_en50221_parse_attribut
 
 	/* is it a version we support? */
 	if (strncmp(dvb_str + 8, "1.00", 4)) {
-		printk("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n",
-		       ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9], dvb_str[10], dvb_str[11]);
+		pr_err("dvb_ca adapter %d: Unsupported DVB CAM module version %c%c%c%c\n",
+		       ca->dvbdev->adapter->num, dvb_str[8], dvb_str[9],
+		       dvb_str[10], dvb_str[11]);
 		return -EINVAL;
 	}
 
@@ -557,8 +564,8 @@ static int dvb_ca_en50221_parse_attribut
 			break;
 
 		default:	/* Unknown tuple type - just skip this tuple and move to the next one */
-			dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType,
-				tupleLength);
+			dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n",
+				tupleType, tupleLength);
 			break;
 		}
 	}
@@ -567,7 +574,8 @@ static int dvb_ca_en50221_parse_attribut
 		return -EINVAL;
 
 	dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n",
-		manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option);
+		manfid, devid, ca->slot_info[slot].config_base,
+		ca->slot_info[slot].config_option);
 
 	// success!
 	return 0;
@@ -661,14 +669,15 @@ static int dvb_ca_en50221_read_data(stru
 	/* check it will fit */
 	if (ebuf == NULL) {
 		if (bytes_read > ca->slot_info[slot].link_buf_size) {
-			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
-			       ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size);
+			pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
+			       ca->dvbdev->adapter->num, bytes_read,
+			       ca->slot_info[slot].link_buf_size);
 			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
 			status = -EIO;
 			goto exit;
 		}
 		if (bytes_read < 2) {
-			printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n",
+			pr_err("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n",
 			       ca->dvbdev->adapter->num);
 			ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
 			status = -EIO;
@@ -676,7 +685,7 @@ static int dvb_ca_en50221_read_data(stru
 		}
 	} else {
 		if (bytes_read > ecount) {
-			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
+			pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
 			       ca->dvbdev->adapter->num);
 			status = -EIO;
 			goto exit;
@@ -1062,7 +1071,7 @@ static int dvb_ca_en50221_thread(void *d
 
 			case DVB_CA_SLOTSTATE_WAITREADY:
 				if (time_after(jiffies, ca->slot_info[slot].timeout)) {
-					printk("dvb_ca adaptor %d: PC card did not respond :(\n",
+					pr_err("dvb_ca adaptor %d: PC card did not respond :(\n",
 					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
@@ -1084,14 +1093,14 @@ static int dvb_ca_en50221_thread(void *d
 						}
 					}
 
-					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
+					pr_err("dvb_ca adapter %d: Invalid PC card inserted :(\n",
 					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
 					break;
 				}
 				if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
-					printk("dvb_ca adapter %d: Unable to initialise CAM :(\n",
+					pr_err("dvb_ca adapter %d: Unable to initialise CAM :(\n",
 					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
@@ -1099,7 +1108,7 @@ static int dvb_ca_en50221_thread(void *d
 				}
 				if (ca->pub->write_cam_control(ca->pub, slot,
 							       CTRLIF_COMMAND, CMDREG_RS) != 0) {
-					printk("dvb_ca adapter %d: Unable to reset CAM IF\n",
+					pr_err("dvb_ca adapter %d: Unable to reset CAM IF\n",
 					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
@@ -1114,7 +1123,7 @@ static int dvb_ca_en50221_thread(void *d
 
 			case DVB_CA_SLOTSTATE_WAITFR:
 				if (time_after(jiffies, ca->slot_info[slot].timeout)) {
-					printk("dvb_ca adapter %d: DVB CAM did not respond :(\n",
+					pr_err("dvb_ca adapter %d: DVB CAM did not respond :(\n",
 					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
@@ -1141,7 +1150,8 @@ static int dvb_ca_en50221_thread(void *d
 						}
 					}
 
-					printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
+					pr_err("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n",
+					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
 					break;
@@ -1150,7 +1160,8 @@ static int dvb_ca_en50221_thread(void *d
 				if (ca->slot_info[slot].rx_buffer.data == NULL) {
 					rxbuf = vmalloc(RX_BUFFER_SIZE);
 					if (rxbuf == NULL) {
-						printk("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", ca->dvbdev->adapter->num);
+						pr_err("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n",
+						       ca->dvbdev->adapter->num);
 						ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 						dvb_ca_en50221_thread_update_delay(ca);
 						break;
@@ -1161,7 +1172,8 @@ static int dvb_ca_en50221_thread(void *d
 				ca->pub->slot_ts_enable(ca->pub, slot);
 				ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
 				dvb_ca_en50221_thread_update_delay(ca);
-				printk("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", ca->dvbdev->adapter->num);
+				pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
+				       ca->dvbdev->adapter->num);
 				break;
 
 			case DVB_CA_SLOTSTATE_RUNNING:
@@ -1497,7 +1509,8 @@ static ssize_t dvb_ca_en50221_io_read(st
 	pktlen = 2;
 	do {
 		if (idx == -1) {
-			printk("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n", ca->dvbdev->adapter->num);
+			pr_err("dvb_ca adapter %d: BUG: read packet ended before last_fragment encountered\n",
+			       ca->dvbdev->adapter->num);
 			status = -EIO;
 			goto exit;
 		}
@@ -1755,8 +1768,8 @@ int dvb_ca_en50221_init(struct dvb_adapt
 				 ca->dvbdev->adapter->num, ca->dvbdev->id);
 	if (IS_ERR(ca->thread)) {
 		ret = PTR_ERR(ca->thread);
-		printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
-			ret);
+		pr_err("dvb_ca_init: failed to start kernel_thread (%d)\n",
+		       ret);
 		goto unregister_device;
 	}
 	return 0;
@@ -1794,6 +1807,7 @@ void dvb_ca_en50221_release(struct dvb_c
 	for (i = 0; i < ca->slot_count; i++) {
 		dvb_ca_en50221_slot_shutdown(ca, i);
 	}
+	dvb_remove_device(ca->dvbdev);
 	dvb_ca_private_put(ca);
 	pubca->private = NULL;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_demux.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_demux.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_demux.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_demux.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@
  *
  */
 
+#define pr_fmt(fmt) "dvb_demux: " fmt
+
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -29,17 +31,11 @@
 #include <linux/poll.h>
 #include <linux/string.h>
 #include <linux/crc32.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/div64.h>
 
 #include "dvb_demux.h"
 
-#define NOBUFS
-/*
-** #define DVB_DEMUX_SECTION_LOSS_LOG to monitor payload loss in the syslog
-*/
-// #define DVB_DEMUX_SECTION_LOSS_LOG
-
 static int dvb_demux_tscheck;
 module_param(dvb_demux_tscheck, int, 0644);
 MODULE_PARM_DESC(dvb_demux_tscheck,
@@ -55,10 +51,13 @@ module_param(dvb_demux_feed_err_pkts, in
 MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
 		 "when set to 0, drop packets with the TEI bit set (1 by default)");
 
-#define dprintk_tscheck(x...) do {                              \
-		if (dvb_demux_tscheck && printk_ratelimit())    \
-			printk(x);                              \
-	} while (0)
+#define dprintk(fmt, arg...) \
+	printk(KERN_DEBUG pr_fmt("%s: " fmt),  __func__, ##arg)
+
+#define dprintk_tscheck(x...) do {			\
+	if (dvb_demux_tscheck && printk_ratelimit())	\
+		dprintk(x);				\
+} while (0)
 
 /******************************************************************************
  * static inlined helper functions
@@ -109,21 +108,23 @@ static inline int dvb_dmx_swfilter_paylo
 {
 	int count = payload(buf);
 	int p;
-	//int ccok;
-	//u8 cc;
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
+	int ccok;
+	u8 cc;
+#endif
 
 	if (count == 0)
 		return -1;
 
 	p = 188 - count;
 
-	/*
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 	cc = buf[3] & 0x0f;
 	ccok = ((feed->cc + 1) & 0x0f) == cc;
 	feed->cc = cc;
 	if (!ccok)
-		printk("missed packet!\n");
-	*/
+		dprintk("missed packet!\n");
+#endif
 
 	if (buf[1] & 0x40)	// PUSI ?
 		feed->peslen = 0xfffa;
@@ -189,7 +190,7 @@ static void dvb_dmx_swfilter_section_new
 {
 	struct dmx_section_feed *sec = &feed->feed.sec;
 
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 	if (sec->secbufp < sec->tsfeedp) {
 		int i, n = sec->tsfeedp - sec->secbufp;
 
@@ -199,12 +200,12 @@ static void dvb_dmx_swfilter_section_new
 		 * but just first and last.
 		 */
 		if (sec->secbuf[0] != 0xff || sec->secbuf[n - 1] != 0xff) {
-			printk("dvb_demux.c section ts padding loss: %d/%d\n",
+			dprintk("dvb_demux.c section ts padding loss: %d/%d\n",
 			       n, sec->tsfeedp);
-			printk("dvb_demux.c pad data:");
+			dprintk("dvb_demux.c pad data:");
 			for (i = 0; i < n; i++)
-				printk(" %02x", sec->secbuf[i]);
-			printk("\n");
+				pr_cont(" %02x", sec->secbuf[i]);
+			pr_cont("\n");
 		}
 	}
 #endif
@@ -242,8 +243,8 @@ static int dvb_dmx_swfilter_section_copy
 		return 0;
 
 	if (sec->tsfeedp + len > DMX_MAX_SECFEED_SIZE) {
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
-		printk("dvb_demux.c section buffer full loss: %d/%d\n",
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
+		dprintk("dvb_demux.c section buffer full loss: %d/%d\n",
 		       sec->tsfeedp + len - DMX_MAX_SECFEED_SIZE,
 		       DMX_MAX_SECFEED_SIZE);
 #endif
@@ -276,9 +277,9 @@ static int dvb_dmx_swfilter_section_copy
 		/* dump [secbuf .. secbuf+seclen) */
 		if (feed->pusi_seen)
 			dvb_dmx_swfilter_section_feed(feed);
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 		else
-			printk("dvb_demux.c pusi not seen, discarding section data\n");
+			dprintk("dvb_demux.c pusi not seen, discarding section data\n");
 #endif
 		sec->secbufp += seclen;	/* secbufp and secbuf moving together is */
 		sec->secbuf += seclen;	/* redundant but saves pointer arithmetic */
@@ -312,9 +313,9 @@ static int dvb_dmx_swfilter_section_pack
 	}
 
 	if (!ccok || dc_i) {
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
-		printk("dvb_demux.c discontinuity detected %d bytes lost\n",
-		       count);
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
+		dprintk("dvb_demux.c discontinuity detected %d bytes lost\n",
+			count);
 		/*
 		 * those bytes under sume circumstances will again be reported
 		 * in the following dvb_dmx_swfilter_section_new
@@ -344,9 +345,10 @@ static int dvb_dmx_swfilter_section_pack
 			dvb_dmx_swfilter_section_copy_dump(feed, after,
 							   after_len);
 		}
-#ifdef DVB_DEMUX_SECTION_LOSS_LOG
+#ifdef CONFIG_DVB_DEMUX_SECTION_LOSS_LOG
 		else if (count > 0)
-			printk("dvb_demux.c PUSI=1 but %d bytes lost\n", count);
+			dprintk("dvb_demux.c PUSI=1 but %d bytes lost\n",
+				count);
 #endif
 	} else {
 		/* PUSI=0 (is not set), no section boundary */
@@ -415,9 +417,9 @@ static void dvb_dmx_swfilter_packet(stru
 						1024);
 				speed_timedelta = ktime_ms_delta(cur_time,
 							demux->speed_last_time);
-				printk(KERN_INFO "TS speed %llu Kbits/sec \n",
-						div64_u64(speed_bytes,
-							speed_timedelta));
+				dprintk("TS speed %llu Kbits/sec \n",
+					div64_u64(speed_bytes,
+						  speed_timedelta));
 			}
 
 			demux->speed_last_time = cur_time;
@@ -426,8 +428,7 @@ static void dvb_dmx_swfilter_packet(stru
 	}
 
 	if (buf[1] & 0x80) {
-		dprintk_tscheck("TEI detected. "
-				"PID=0x%x data1=0x%x\n",
+		dprintk_tscheck("TEI detected. PID=0x%x data1=0x%x\n",
 				pid, buf[1]);
 		/* data in this packet can't be trusted - drop it unless
 		 * module option dvb_demux_feed_err_pkts is set */
@@ -635,7 +636,7 @@ static void dvb_demux_feed_add(struct dv
 {
 	spin_lock_irq(&feed->demux->lock);
 	if (dvb_demux_feed_find(feed)) {
-		printk(KERN_ERR "%s: feed already in list (type=%x state=%x pid=%x)\n",
+		pr_err("%s: feed already in list (type=%x state=%x pid=%x)\n",
 		       __func__, feed->type, feed->state, feed->pid);
 		goto out;
 	}
@@ -649,7 +650,7 @@ static void dvb_demux_feed_del(struct dv
 {
 	spin_lock_irq(&feed->demux->lock);
 	if (!(dvb_demux_feed_find(feed))) {
-		printk(KERN_ERR "%s: feed not in list (type=%x state=%x pid=%x)\n",
+		pr_err("%s: feed not in list (type=%x state=%x pid=%x)\n",
 		       __func__, feed->type, feed->state, feed->pid);
 		goto out;
 	}
@@ -660,8 +661,7 @@ out:
 }
 
 static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
-			   enum dmx_ts_pes pes_type,
-			   size_t circular_buffer_size, ktime_t timeout)
+			   enum dmx_ts_pes pes_type, ktime_t timeout)
 {
 	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
 	struct dvb_demux *demux = feed->demux;
@@ -691,23 +691,10 @@ static int dmx_ts_feed_set(struct dmx_ts
 	dvb_demux_feed_add(feed);
 
 	feed->pid = pid;
-	feed->buffer_size = circular_buffer_size;
 	feed->timeout = timeout;
 	feed->ts_type = ts_type;
 	feed->pes_type = pes_type;
 
-	if (feed->buffer_size) {
-#ifdef NOBUFS
-		feed->buffer = NULL;
-#else
-		feed->buffer = vmalloc(feed->buffer_size);
-		if (!feed->buffer) {
-			mutex_unlock(&demux->mutex);
-			return -ENOMEM;
-		}
-#endif
-	}
-
 	feed->state = DMX_STATE_READY;
 	mutex_unlock(&demux->mutex);
 
@@ -796,7 +783,6 @@ static int dvbdmx_allocate_ts_feed(struc
 	feed->demux = demux;
 	feed->pid = 0xffff;
 	feed->peslen = 0xfffa;
-	feed->buffer = NULL;
 
 	(*ts_feed) = &feed->feed.ts;
 	(*ts_feed)->parent = dmx;
@@ -833,10 +819,6 @@ static int dvbdmx_release_ts_feed(struct
 		mutex_unlock(&demux->mutex);
 		return -EINVAL;
 	}
-#ifndef NOBUFS
-	vfree(feed->buffer);
-	feed->buffer = NULL;
-#endif
 
 	feed->state = DMX_STATE_FREE;
 	feed->filter->state = DMX_STATE_FREE;
@@ -888,8 +870,7 @@ static int dmx_section_feed_allocate_fil
 }
 
 static int dmx_section_feed_set(struct dmx_section_feed *feed,
-				u16 pid, size_t circular_buffer_size,
-				int check_crc)
+				u16 pid, int check_crc)
 {
 	struct dvb_demux_feed *dvbdmxfeed = (struct dvb_demux_feed *)feed;
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
@@ -903,19 +884,8 @@ static int dmx_section_feed_set(struct d
 	dvb_demux_feed_add(dvbdmxfeed);
 
 	dvbdmxfeed->pid = pid;
-	dvbdmxfeed->buffer_size = circular_buffer_size;
 	dvbdmxfeed->feed.sec.check_crc = check_crc;
 
-#ifdef NOBUFS
-	dvbdmxfeed->buffer = NULL;
-#else
-	dvbdmxfeed->buffer = vmalloc(dvbdmxfeed->buffer_size);
-	if (!dvbdmxfeed->buffer) {
-		mutex_unlock(&dvbdmx->mutex);
-		return -ENOMEM;
-	}
-#endif
-
 	dvbdmxfeed->state = DMX_STATE_READY;
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
@@ -1074,7 +1044,6 @@ static int dvbdmx_allocate_section_feed(
 	dvbdmxfeed->feed.sec.secbufp = dvbdmxfeed->feed.sec.seclen = 0;
 	dvbdmxfeed->feed.sec.tsfeedp = 0;
 	dvbdmxfeed->filter = NULL;
-	dvbdmxfeed->buffer = NULL;
 
 	(*feed) = &dvbdmxfeed->feed.sec;
 	(*feed)->is_filtering = 0;
@@ -1103,10 +1072,6 @@ static int dvbdmx_release_section_feed(s
 		mutex_unlock(&dvbdmx->mutex);
 		return -EINVAL;
 	}
-#ifndef NOBUFS
-	vfree(dvbdmxfeed->buffer);
-	dvbdmxfeed->buffer = NULL;
-#endif
 	dvbdmxfeed->state = DMX_STATE_FREE;
 
 	dvb_demux_feed_del(dvbdmxfeed);
@@ -1268,7 +1233,7 @@ int dvb_dmx_init(struct dvb_demux *dvbde
 
 	dvbdemux->cnt_storage = vmalloc(MAX_PID + 1);
 	if (!dvbdemux->cnt_storage)
-		printk(KERN_WARNING "Couldn't allocate memory for TS/TEI check. Disabling it\n");
+		pr_warn("Couldn't allocate memory for TS/TEI check. Disabling it\n");
 
 	INIT_LIST_HEAD(&dvbdemux->frontend_list);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_demux.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_demux.h
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_demux.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_demux.h	2017-02-12 16:03:20.000000000 -0500
@@ -80,8 +80,6 @@ struct dvb_demux_feed {
 	int type;
 	int state;
 	u16 pid;
-	u8 *buffer;
-	int buffer_size;
 
 	ktime_t timeout;
 	struct dvb_demux_filter *filter;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvbdev.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvbdev.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvbdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvbdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@
  *
  */
 
+#define pr_fmt(fmt) "dvbdev: " fmt
+
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/string.h>
@@ -43,7 +45,11 @@ static int dvbdev_debug;
 module_param(dvbdev_debug, int, 0644);
 MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
 
-#define dprintk if (dvbdev_debug) printk
+#define dprintk(fmt, arg...) do {					\
+	if (dvbdev_debug)						\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 static LIST_HEAD(dvb_adapter_list);
 static DEFINE_MUTEX(dvbdev_register_lock);
@@ -354,7 +360,7 @@ static int dvb_create_media_entity(struc
 	if (ret)
 		return ret;
 
-	printk(KERN_DEBUG "%s: media entity '%s' registered.\n",
+	pr_info("%s: media entity '%s' registered.\n",
 		__func__, dvbdev->entity->name);
 
 	return 0;
@@ -438,7 +444,7 @@ int dvb_register_device(struct dvb_adapt
 	if ((id = dvbdev_get_free_id (adap, type)) < 0){
 		mutex_unlock(&dvbdev_register_lock);
 		*pdvbdev = NULL;
-		printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
+		pr_err("%s: couldn't find free device id\n", __func__);
 		return -ENFILE;
 	}
 
@@ -493,8 +499,7 @@ int dvb_register_device(struct dvb_adapt
 
 	ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
 	if (ret) {
-		printk(KERN_ERR
-		      "%s: dvb_register_media_device failed to create the mediagraph\n",
+		pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
 		      __func__);
 
 		dvb_media_device_free(dvbdev);
@@ -511,11 +516,11 @@ int dvb_register_device(struct dvb_adapt
 			       MKDEV(DVB_MAJOR, minor),
 			       dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
 	if (IS_ERR(clsdev)) {
-		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
+		pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
 		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
 		return PTR_ERR(clsdev);
 	}
-	dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
+	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 		adap->num, dnames[type], id, minor, minor);
 
 	return 0;
@@ -523,7 +528,7 @@ int dvb_register_device(struct dvb_adapt
 EXPORT_SYMBOL(dvb_register_device);
 
 
-void dvb_unregister_device(struct dvb_device *dvbdev)
+void dvb_remove_device(struct dvb_device *dvbdev)
 {
 	if (!dvbdev)
 		return;
@@ -537,9 +542,26 @@ void dvb_unregister_device(struct dvb_de
 	device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
 
 	list_del (&dvbdev->list_head);
+}
+EXPORT_SYMBOL(dvb_remove_device);
+
+
+void dvb_free_device(struct dvb_device *dvbdev)
+{
+	if (!dvbdev)
+		return;
+
 	kfree (dvbdev->fops);
 	kfree (dvbdev);
 }
+EXPORT_SYMBOL(dvb_free_device);
+
+
+void dvb_unregister_device(struct dvb_device *dvbdev)
+{
+	dvb_remove_device(dvbdev);
+	dvb_free_device(dvbdev);
+}
 EXPORT_SYMBOL(dvb_unregister_device);
 
 
@@ -808,7 +830,7 @@ int dvb_register_adapter(struct dvb_adap
 	memset (adap, 0, sizeof(struct dvb_adapter));
 	INIT_LIST_HEAD (&adap->device_list);
 
-	printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
+	pr_info("DVB: registering new adapter (%s)\n", name);
 
 	adap->num = num;
 	adap->name = name;
@@ -926,13 +948,13 @@ static int __init init_dvbdev(void)
 	dev_t dev = MKDEV(DVB_MAJOR, 0);
 
 	if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
-		printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
+		pr_err("dvb-core: unable to get major %d\n", DVB_MAJOR);
 		return retval;
 	}
 
 	cdev_init(&dvb_device_cdev, &dvb_device_fops);
 	if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
-		printk(KERN_ERR "dvb-core: unable register character device\n");
+		pr_err("dvb-core: unable register character device\n");
 		goto error;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvbdev.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvbdev.h
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvbdev.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvbdev.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #if defined(CONFIG_DVB_MAX_ADAPTERS) && CONFIG_DVB_MAX_ADAPTERS > 0
   #define DVB_MAX_ADAPTERS CONFIG_DVB_MAX_ADAPTERS
 #else
-  #define DVB_MAX_ADAPTERS 8
+  #define DVB_MAX_ADAPTERS 16
 #endif
 
 #define DVB_UNSET (-1)
@@ -212,8 +212,31 @@ int dvb_register_device(struct dvb_adapt
 			int demux_sink_pads);
 
 /**
+ * dvb_remove_device - Remove a registered DVB device
+ *
+ * This does not free memory.  To do that, call dvb_free_device().
+ *
+ * @dvbdev:	pointer to struct dvb_device
+ */
+void dvb_remove_device(struct dvb_device *dvbdev);
+
+/**
+ * dvb_free_device - Free memory occupied by a DVB device.
+ *
+ * Call dvb_unregister_device() before calling this function.
+ *
+ * @dvbdev:	pointer to struct dvb_device
+ */
+void dvb_free_device(struct dvb_device *dvbdev);
+
+/**
  * dvb_unregister_device - Unregisters a DVB device
  *
+ * This is a combination of dvb_remove_device() and dvb_free_device().
+ * Using this function is usually a mistake, and is often an indicator
+ * for a use-after-free bug (when a userspace process keeps a file
+ * handle to a detached device).
+ *
  * @dvbdev:	pointer to struct dvb_device
  */
 void dvb_unregister_device(struct dvb_device *dvbdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_filter.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_filter.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_filter.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_filter.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,603 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include "dvb_filter.h"
-
-#if 0
-static unsigned int bitrates[3][16] =
-{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
- {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
- {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
-#endif
-
-static u32 freq[4] = {480, 441, 320, 0};
-
-static unsigned int ac3_bitrates[32] =
-    {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
-     0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-static u32 ac3_frames[3][32] =
-    {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
-      1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
-     {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
-      1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
-     {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
-      1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
-
-
-
-#if 0
-static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv,
-		  void (*pes_write)(u8 *buf, int count, void *data),
-		  void *priv)
-{
-	dvb_filter_ipack_init(pa, IPACKS, pes_write);
-	dvb_filter_ipack_init(pv, IPACKS, pes_write);
-	pa->pid = pida;
-	pv->pid = pidv;
-	pa->data = priv;
-	pv->data = priv;
-}
-#endif
-
-#if 0
-static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188)
-{
-	u8 off = 0;
-
-	if (!buf || !p ){
-		printk("NULL POINTER IDIOT\n");
-		return;
-	}
-	if (buf[1]&PAY_START) {
-		if (p->plength == MMAX_PLENGTH-6 && p->found>6){
-			p->plength = p->found-6;
-			p->found = 0;
-			send_ipack(p);
-			dvb_filter_ipack_reset(p);
-		}
-	}
-	if (buf[3] & ADAPT_FIELD) {  // adaptation field?
-		off = buf[4] + 1;
-		if (off+4 > 187) return;
-	}
-	dvb_filter_instant_repack(buf+4+off, TS_SIZE-4-off, p);
-}
-#endif
-
-#if 0
-/* needs 5 byte input, returns picture coding type*/
-static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr)
-{
-	u8 pct;
-
-	if (pr) printk( "Pic header: ");
-	pic->temporal_reference[field] = (( headr[0] << 2 ) |
-					  (headr[1] & 0x03) )& 0x03ff;
-	if (pr) printk( " temp ref: 0x%04x", pic->temporal_reference[field]);
-
-	pct = ( headr[1] >> 2 ) & 0x07;
-	pic->picture_coding_type[field] = pct;
-	if (pr) {
-		switch(pct){
-			case I_FRAME:
-				printk( "  I-FRAME");
-				break;
-			case B_FRAME:
-				printk( "  B-FRAME");
-				break;
-			case P_FRAME:
-				printk( "  P-FRAME");
-				break;
-		}
-	}
-
-
-	pic->vinfo.vbv_delay  = (( headr[1] >> 5 ) | ( headr[2] << 3) |
-				 ( (headr[3] & 0x1F) << 11) ) & 0xffff;
-
-	if (pr) printk( " vbv delay: 0x%04x", pic->vinfo.vbv_delay);
-
-	pic->picture_header_parameter = ( headr[3] & 0xe0 ) |
-		((headr[4] & 0x80) >> 3);
-
-	if ( pct == B_FRAME ){
-		pic->picture_header_parameter |= ( headr[4] >> 3 ) & 0x0f;
-	}
-	if (pr) printk( " pic head param: 0x%x",
-			pic->picture_header_parameter);
-
-	return pct;
-}
-#endif
-
-#if 0
-/* needs 4 byte input */
-static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr)
-{
-	if (pr) printk("GOP header: ");
-
-	pic->time_code  = (( headr[0] << 17 ) | ( headr[1] << 9) |
-			   ( headr[2] << 1 ) | (headr[3] &0x01)) & 0x1ffffff;
-
-	if (pr) printk(" time: %d:%d.%d ", (headr[0]>>2)& 0x1F,
-		       ((headr[0]<<4)& 0x30)| ((headr[1]>>4)& 0x0F),
-		       ((headr[1]<<3)& 0x38)| ((headr[2]>>5)& 0x0F));
-
-	if ( ( headr[3] & 0x40 ) != 0 ){
-		pic->closed_gop = 1;
-	} else {
-		pic->closed_gop = 0;
-	}
-	if (pr) printk("closed: %d", pic->closed_gop);
-
-	if ( ( headr[3] & 0x20 ) != 0 ){
-		pic->broken_link = 1;
-	} else {
-		pic->broken_link = 0;
-	}
-	if (pr) printk(" broken: %d\n", pic->broken_link);
-
-	return 0;
-}
-#endif
-
-#if 0
-/* needs 8 byte input */
-static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr)
-{
-	int sw;
-	int form = -1;
-
-	if (pr) printk("Reading sequence header\n");
-
-	vi->horizontal_size	= ((headr[1] &0xF0) >> 4) | (headr[0] << 4);
-	vi->vertical_size	= ((headr[1] &0x0F) << 8) | (headr[2]);
-
-	sw = (int)((headr[3]&0xF0) >> 4) ;
-
-	switch( sw ){
-	case 1:
-		if (pr)
-			printk("Videostream: ASPECT: 1:1");
-		vi->aspect_ratio = 100;
-		break;
-	case 2:
-		if (pr)
-			printk("Videostream: ASPECT: 4:3");
-		vi->aspect_ratio = 133;
-		break;
-	case 3:
-		if (pr)
-			printk("Videostream: ASPECT: 16:9");
-		vi->aspect_ratio = 177;
-		break;
-	case 4:
-		if (pr)
-			printk("Videostream: ASPECT: 2.21:1");
-		vi->aspect_ratio = 221;
-		break;
-
-	case 5 ... 15:
-		if (pr)
-			printk("Videostream: ASPECT: reserved");
-		vi->aspect_ratio = 0;
-		break;
-
-	default:
-		vi->aspect_ratio = 0;
-		return -1;
-	}
-
-	if (pr)
-		printk("  Size = %dx%d",vi->horizontal_size,vi->vertical_size);
-
-	sw = (int)(headr[3]&0x0F);
-
-	switch ( sw ) {
-	case 1:
-		if (pr)
-			printk("  FRate: 23.976 fps");
-		vi->framerate = 23976;
-		form = -1;
-		break;
-	case 2:
-		if (pr)
-			printk("  FRate: 24 fps");
-		vi->framerate = 24000;
-		form = -1;
-		break;
-	case 3:
-		if (pr)
-			printk("  FRate: 25 fps");
-		vi->framerate = 25000;
-		form = VIDEO_MODE_PAL;
-		break;
-	case 4:
-		if (pr)
-			printk("  FRate: 29.97 fps");
-		vi->framerate = 29970;
-		form = VIDEO_MODE_NTSC;
-		break;
-	case 5:
-		if (pr)
-			printk("  FRate: 30 fps");
-		vi->framerate = 30000;
-		form = VIDEO_MODE_NTSC;
-		break;
-	case 6:
-		if (pr)
-			printk("  FRate: 50 fps");
-		vi->framerate = 50000;
-		form = VIDEO_MODE_PAL;
-		break;
-	case 7:
-		if (pr)
-			printk("  FRate: 60 fps");
-		vi->framerate = 60000;
-		form = VIDEO_MODE_NTSC;
-		break;
-	}
-
-	vi->bit_rate = (headr[4] << 10) | (headr[5] << 2) | (headr[6] & 0x03);
-
-	vi->vbv_buffer_size
-		= (( headr[6] & 0xF8) >> 3 ) | (( headr[7] & 0x1F )<< 5);
-
-	if (pr){
-		printk("  BRate: %d Mbit/s",4*(vi->bit_rate)/10000);
-		printk("  vbvbuffer %d",16*1024*(vi->vbv_buffer_size));
-		printk("\n");
-	}
-
-	vi->video_format = form;
-
-	return 0;
-}
-#endif
-
-
-#if 0
-static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr)
-{
-	u8 *headr;
-	int found = 0;
-	int c = 0;
-
-	while (found < 4 && c+4 < count){
-		u8 *b;
-
-		b = mbuf+c;
-		if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01
-		     && b[3] == 0xb3) found = 4;
-		else {
-			c++;
-		}
-	}
-
-	if (! found) return -1;
-	c += 4;
-	if (c+12 >= count) return -1;
-	headr = mbuf+c;
-	if (read_sequence_header(headr, vi, pr) < 0) return -1;
-	vi->off = c-4;
-	return 0;
-}
-#endif
-
-
-#if 0
-static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
-{
-	u8 *headr;
-	int found = 0;
-	int c = 0;
-	int fr = 0;
-
-	while (found < 2 && c < count){
-		u8 b[2];
-		memcpy( b, mbuf+c, 2);
-
-		if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8)
-			found = 2;
-		else {
-			c++;
-		}
-	}
-
-	if (!found) return -1;
-
-	if (c+3 >= count) return -1;
-	headr = mbuf+c;
-
-	ai->layer = (headr[1] & 0x06) >> 1;
-
-	if (pr)
-		printk("Audiostream: Layer: %d", 4-ai->layer);
-
-
-	ai->bit_rate = bitrates[(3-ai->layer)][(headr[2] >> 4 )]*1000;
-
-	if (pr){
-		if (ai->bit_rate == 0)
-			printk("  Bit rate: free");
-		else if (ai->bit_rate == 0xf)
-			printk("  BRate: reserved");
-		else
-			printk("  BRate: %d kb/s", ai->bit_rate/1000);
-	}
-
-	fr = (headr[2] & 0x0c ) >> 2;
-	ai->frequency = freq[fr]*100;
-	if (pr){
-		if (ai->frequency == 3)
-			printk("  Freq: reserved\n");
-		else
-			printk("  Freq: %d kHz\n",ai->frequency);
-
-	}
-	ai->off = c;
-	return 0;
-}
-#endif
-
-
-int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
-{
-	u8 *headr;
-	int found = 0;
-	int c = 0;
-	u8 frame = 0;
-	int fr = 0;
-
-	while ( !found  && c < count){
-		u8 *b = mbuf+c;
-
-		if ( b[0] == 0x0b &&  b[1] == 0x77 )
-			found = 1;
-		else {
-			c++;
-		}
-	}
-
-	if (!found) return -1;
-	if (pr)
-		printk("Audiostream: AC3");
-
-	ai->off = c;
-	if (c+5 >= count) return -1;
-
-	ai->layer = 0;  // 0 for AC3
-	headr = mbuf+c+2;
-
-	frame = (headr[2]&0x3f);
-	ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
-
-	if (pr)
-		printk("  BRate: %d kb/s", (int) ai->bit_rate/1000);
-
-	ai->frequency = (headr[2] & 0xc0 ) >> 6;
-	fr = (headr[2] & 0xc0 ) >> 6;
-	ai->frequency = freq[fr]*100;
-	if (pr) printk ("  Freq: %d Hz\n", (int) ai->frequency);
-
-
-	ai->framesize = ac3_frames[fr][frame >> 1];
-	if ((frame & 1) &&  (fr == 1)) ai->framesize++;
-	ai->framesize = ai->framesize << 1;
-	if (pr) printk ("  Framesize %d\n",(int) ai->framesize);
-
-
-	return 0;
-}
-EXPORT_SYMBOL(dvb_filter_get_ac3info);
-
-
-#if 0
-static u8 *skip_pes_header(u8 **bufp)
-{
-	u8 *inbuf = *bufp;
-	u8 *buf = inbuf;
-	u8 *pts = NULL;
-	int skip = 0;
-
-	static const int mpeg1_skip_table[16] = {
-		1, 0xffff,      5,     10, 0xffff, 0xffff, 0xffff, 0xffff,
-		0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
-	};
-
-
-	if ((inbuf[6] & 0xc0) == 0x80){ /* mpeg2 */
-		if (buf[7] & PTS_ONLY)
-			pts = buf+9;
-		else pts = NULL;
-		buf = inbuf + 9 + inbuf[8];
-	} else {        /* mpeg1 */
-		for (buf = inbuf + 6; *buf == 0xff; buf++)
-			if (buf == inbuf + 6 + 16) {
-				break;
-			}
-		if ((*buf & 0xc0) == 0x40)
-			buf += 2;
-		skip = mpeg1_skip_table [*buf >> 4];
-		if (skip == 5 || skip == 10) pts = buf;
-		else pts = NULL;
-
-		buf += mpeg1_skip_table [*buf >> 4];
-	}
-
-	*bufp = buf;
-	return pts;
-}
-#endif
-
-#if 0
-static void initialize_quant_matrix( u32 *matrix )
-{
-	int i;
-
-	matrix[0]  = 0x08101013;
-	matrix[1]  = 0x10131616;
-	matrix[2]  = 0x16161616;
-	matrix[3]  = 0x1a181a1b;
-	matrix[4]  = 0x1b1b1a1a;
-	matrix[5]  = 0x1a1a1b1b;
-	matrix[6]  = 0x1b1d1d1d;
-	matrix[7]  = 0x2222221d;
-	matrix[8]  = 0x1d1d1b1b;
-	matrix[9]  = 0x1d1d2020;
-	matrix[10] = 0x22222526;
-	matrix[11] = 0x25232322;
-	matrix[12] = 0x23262628;
-	matrix[13] = 0x28283030;
-	matrix[14] = 0x2e2e3838;
-	matrix[15] = 0x3a454553;
-
-	for ( i = 16 ; i < 32 ; i++ )
-		matrix[i] = 0x10101010;
-}
-#endif
-
-#if 0
-static void initialize_mpg_picture(struct mpg_picture *pic)
-{
-	int i;
-
-	/* set MPEG1 */
-	pic->mpeg1_flag = 1;
-	pic->profile_and_level = 0x4A ;        /* MP@LL */
-	pic->progressive_sequence = 1;
-	pic->low_delay = 0;
-
-	pic->sequence_display_extension_flag = 0;
-	for ( i = 0 ; i < 4 ; i++ ){
-		pic->frame_centre_horizontal_offset[i] = 0;
-		pic->frame_centre_vertical_offset[i] = 0;
-	}
-	pic->last_frame_centre_horizontal_offset = 0;
-	pic->last_frame_centre_vertical_offset = 0;
-
-	pic->picture_display_extension_flag[0] = 0;
-	pic->picture_display_extension_flag[1] = 0;
-	pic->sequence_header_flag = 0;
-	pic->gop_flag = 0;
-	pic->sequence_end_flag = 0;
-}
-#endif
-
-#if 0
-static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic )
-{
-	int16_t last_h_offset;
-	int16_t last_v_offset;
-
-	int16_t *p_h_offset;
-	int16_t *p_v_offset;
-
-	if ( pic->mpeg1_flag ){
-		pic->picture_structure[field_type] = VIDEO_FRAME_PICTURE;
-		pic->top_field_first = 0;
-		pic->repeat_first_field = 0;
-		pic->progressive_frame = 1;
-		pic->picture_coding_parameter = 0x000010;
-	}
-
-	/* Reset flag */
-	pic->picture_display_extension_flag[field_type] = 0;
-
-	last_h_offset = pic->last_frame_centre_horizontal_offset;
-	last_v_offset = pic->last_frame_centre_vertical_offset;
-	if ( field_type == FIRST_FIELD ){
-		p_h_offset = pic->frame_centre_horizontal_offset;
-		p_v_offset = pic->frame_centre_vertical_offset;
-		*p_h_offset = last_h_offset;
-		*(p_h_offset + 1) = last_h_offset;
-		*(p_h_offset + 2) = last_h_offset;
-		*p_v_offset = last_v_offset;
-		*(p_v_offset + 1) = last_v_offset;
-		*(p_v_offset + 2) = last_v_offset;
-	} else {
-		pic->frame_centre_horizontal_offset[3] = last_h_offset;
-		pic->frame_centre_vertical_offset[3] = last_v_offset;
-	}
-}
-#endif
-
-#if 0
-static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type)
-{
-	pic->picture_header = 0;
-	pic->sequence_header_data
-		= ( INIT_HORIZONTAL_SIZE << 20 )
-			| ( INIT_VERTICAL_SIZE << 8 )
-			| ( INIT_ASPECT_RATIO << 4 )
-			| ( INIT_FRAME_RATE );
-	pic->mpeg1_flag = 0;
-	pic->vinfo.horizontal_size
-		= INIT_DISP_HORIZONTAL_SIZE;
-	pic->vinfo.vertical_size
-		= INIT_DISP_VERTICAL_SIZE;
-	pic->picture_display_extension_flag[field_type]
-		= 0;
-	pic->pts_flag[field_type] = 0;
-
-	pic->sequence_gop_header = 0;
-	pic->picture_header = 0;
-	pic->sequence_header_flag = 0;
-	pic->gop_flag = 0;
-	pic->sequence_end_flag = 0;
-	pic->sequence_display_extension_flag = 0;
-	pic->last_frame_centre_horizontal_offset = 0;
-	pic->last_frame_centre_vertical_offset = 0;
-	pic->channel = chan;
-}
-#endif
-
-void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
-			    dvb_filter_pes2ts_cb_t *cb, void *priv)
-{
-	unsigned char *buf=p2ts->buf;
-
-	buf[0]=0x47;
-	buf[1]=(pid>>8);
-	buf[2]=pid&0xff;
-	p2ts->cc=0;
-	p2ts->cb=cb;
-	p2ts->priv=priv;
-}
-EXPORT_SYMBOL(dvb_filter_pes2ts_init);
-
-int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
-		      int len, int payload_start)
-{
-	unsigned char *buf=p2ts->buf;
-	int ret=0, rest;
-
-	//len=6+((pes[4]<<8)|pes[5]);
-
-	if (payload_start)
-		buf[1]|=0x40;
-	else
-		buf[1]&=~0x40;
-	while (len>=184) {
-		buf[3]=0x10|((p2ts->cc++)&0x0f);
-		memcpy(buf+4, pes, 184);
-		if ((ret=p2ts->cb(p2ts->priv, buf)))
-			return ret;
-		len-=184; pes+=184;
-		buf[1]&=~0x40;
-	}
-	if (!len)
-		return 0;
-	buf[3]=0x30|((p2ts->cc++)&0x0f);
-	rest=183-len;
-	if (rest) {
-		buf[5]=0x00;
-		if (rest-1)
-			memset(buf+6, 0xff, rest-1);
-	}
-	buf[4]=rest;
-	memcpy(buf+5+rest, pes, len);
-	return p2ts->cb(p2ts->priv, buf);
-}
-EXPORT_SYMBOL(dvb_filter_pes2ts);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_filter.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_filter.h
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_filter.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_filter.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,246 +0,0 @@
-/*
- * dvb_filter.h
- *
- * Copyright (C) 2003 Convergence GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public 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 _DVB_FILTER_H_
-#define _DVB_FILTER_H_
-
-#include <linux/slab.h>
-
-#include "demux.h"
-
-typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
-
-struct dvb_filter_pes2ts {
-	unsigned char buf[188];
-	unsigned char cc;
-	dvb_filter_pes2ts_cb_t *cb;
-	void *priv;
-};
-
-void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
-			    dvb_filter_pes2ts_cb_t *cb, void *priv);
-
-int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
-		      int len, int payload_start);
-
-
-#define PROG_STREAM_MAP  0xBC
-#define PRIVATE_STREAM1  0xBD
-#define PADDING_STREAM   0xBE
-#define PRIVATE_STREAM2  0xBF
-#define AUDIO_STREAM_S   0xC0
-#define AUDIO_STREAM_E   0xDF
-#define VIDEO_STREAM_S   0xE0
-#define VIDEO_STREAM_E   0xEF
-#define ECM_STREAM       0xF0
-#define EMM_STREAM       0xF1
-#define DSM_CC_STREAM    0xF2
-#define ISO13522_STREAM  0xF3
-#define PROG_STREAM_DIR  0xFF
-
-#define DVB_PICTURE_START    0x00
-#define DVB_USER_START       0xb2
-#define DVB_SEQUENCE_HEADER  0xb3
-#define DVB_SEQUENCE_ERROR   0xb4
-#define DVB_EXTENSION_START  0xb5
-#define DVB_SEQUENCE_END     0xb7
-#define DVB_GOP_START        0xb8
-#define DVB_EXCEPT_SLICE     0xb0
-
-#define SEQUENCE_EXTENSION           0x01
-#define SEQUENCE_DISPLAY_EXTENSION   0x02
-#define PICTURE_CODING_EXTENSION     0x08
-#define QUANT_MATRIX_EXTENSION       0x03
-#define PICTURE_DISPLAY_EXTENSION    0x07
-
-#define I_FRAME 0x01
-#define B_FRAME 0x02
-#define P_FRAME 0x03
-
-/* Initialize sequence_data */
-#define INIT_HORIZONTAL_SIZE        720
-#define INIT_VERTICAL_SIZE          576
-#define INIT_ASPECT_RATIO          0x02
-#define INIT_FRAME_RATE            0x03
-#define INIT_DISP_HORIZONTAL_SIZE   540
-#define INIT_DISP_VERTICAL_SIZE     576
-
-
-//flags2
-#define PTS_DTS_FLAGS    0xC0
-#define ESCR_FLAG        0x20
-#define ES_RATE_FLAG     0x10
-#define DSM_TRICK_FLAG   0x08
-#define ADD_CPY_FLAG     0x04
-#define PES_CRC_FLAG     0x02
-#define PES_EXT_FLAG     0x01
-
-//pts_dts flags
-#define PTS_ONLY         0x80
-#define PTS_DTS          0xC0
-
-#define TS_SIZE        188
-#define TRANS_ERROR    0x80
-#define PAY_START      0x40
-#define TRANS_PRIO     0x20
-#define PID_MASK_HI    0x1F
-//flags
-#define TRANS_SCRMBL1  0x80
-#define TRANS_SCRMBL2  0x40
-#define ADAPT_FIELD    0x20
-#define PAYLOAD        0x10
-#define COUNT_MASK     0x0F
-
-// adaptation flags
-#define DISCON_IND     0x80
-#define RAND_ACC_IND   0x40
-#define ES_PRI_IND     0x20
-#define PCR_FLAG       0x10
-#define OPCR_FLAG      0x08
-#define SPLICE_FLAG    0x04
-#define TRANS_PRIV     0x02
-#define ADAP_EXT_FLAG  0x01
-
-// adaptation extension flags
-#define LTW_FLAG       0x80
-#define PIECE_RATE     0x40
-#define SEAM_SPLICE    0x20
-
-
-#define MAX_PLENGTH 0xFFFF
-#define MMAX_PLENGTH (256*MAX_PLENGTH)
-
-#ifndef IPACKS
-#define IPACKS 2048
-#endif
-
-struct ipack {
-	int size;
-	int found;
-	u8 *buf;
-	u8 cid;
-	u32 plength;
-	u8 plen[2];
-	u8 flag1;
-	u8 flag2;
-	u8 hlength;
-	u8 pts[5];
-	u16 *pid;
-	int mpeg;
-	u8 check;
-	int which;
-	int done;
-	void *data;
-	void (*func)(u8 *buf,  int size, void *priv);
-	int count;
-	int repack_subids;
-};
-
-struct dvb_video_info {
-	u32 horizontal_size;
-	u32 vertical_size;
-	u32 aspect_ratio;
-	u32 framerate;
-	u32 video_format;
-	u32 bit_rate;
-	u32 comp_bit_rate;
-	u32 vbv_buffer_size;
-	s16 vbv_delay;
-	u32 CSPF;
-	u32 off;
-};
-
-#define OFF_SIZE 4
-#define FIRST_FIELD 0
-#define SECOND_FIELD 1
-#define VIDEO_FRAME_PICTURE 0x03
-
-struct mpg_picture {
-	int       channel;
-	struct dvb_video_info vinfo;
-	u32      *sequence_gop_header;
-	u32      *picture_header;
-	s32       time_code;
-	int       low_delay;
-	int       closed_gop;
-	int       broken_link;
-	int       sequence_header_flag;
-	int       gop_flag;
-	int       sequence_end_flag;
-
-	u8        profile_and_level;
-	s32       picture_coding_parameter;
-	u32       matrix[32];
-	s8        matrix_change_flag;
-
-	u8        picture_header_parameter;
-  /* bit 0 - 2: bwd f code
-     bit 3    : fpb vector
-     bit 4 - 6: fwd f code
-     bit 7    : fpf vector */
-
-	int       mpeg1_flag;
-	int       progressive_sequence;
-	int       sequence_display_extension_flag;
-	u32       sequence_header_data;
-	s16       last_frame_centre_horizontal_offset;
-	s16       last_frame_centre_vertical_offset;
-
-	u32       pts[2]; /* [0] 1st field, [1] 2nd field */
-	int       top_field_first;
-	int       repeat_first_field;
-	int       progressive_frame;
-	int       bank;
-	int       forward_bank;
-	int       backward_bank;
-	int       compress;
-	s16       frame_centre_horizontal_offset[OFF_SIZE];
-		  /* [0-2] 1st field, [3] 2nd field */
-	s16       frame_centre_vertical_offset[OFF_SIZE];
-		  /* [0-2] 1st field, [3] 2nd field */
-	s16       temporal_reference[2];
-		  /* [0] 1st field, [1] 2nd field */
-
-	s8        picture_coding_type[2];
-		  /* [0] 1st field, [1] 2nd field */
-	s8        picture_structure[2];
-		  /* [0] 1st field, [1] 2nd field */
-	s8        picture_display_extension_flag[2];
-		  /* [0] 1st field, [1] 2nd field */
-		  /* picture_display_extenion() 0:no 1:exit*/
-	s8        pts_flag[2];
-		  /* [0] 1st field, [1] 2nd field */
-};
-
-struct dvb_audio_info {
-	int layer;
-	u32 bit_rate;
-	u32 frequency;
-	u32 mode;
-	u32 mode_extension ;
-	u32 emphasis;
-	u32 framesize;
-	u32 off;
-};
-
-int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
-
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_frontend.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_frontend.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_frontend.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_frontend.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,8 @@
 /* Enables DVBv3 compatibility bits at the headers */
 #define __DVB_CORE__
 
+#define pr_fmt(fmt) "dvb_frontend: " fmt
+
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -67,6 +69,9 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep,
 module_param(dvb_mfe_wait_time, int, 0644);
 MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
 
+#define dprintk(fmt, arg...) \
+	printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg)
+
 #define FESTATE_IDLE 1
 #define FESTATE_RETUNE 2
 #define FESTATE_TUNING_FAST 4
@@ -99,8 +104,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wai
 static DEFINE_MUTEX(frontend_mutex);
 
 struct dvb_frontend_private {
-	struct kref refcount;
-
 	/* thread/frontend values */
 	struct dvb_device *dvbdev;
 	struct dvb_frontend_parameters parameters_out;
@@ -138,21 +141,30 @@ struct dvb_frontend_private {
 #endif
 };
 
-static void dvb_frontend_private_free(struct kref *ref)
+static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
+					void (*release)(struct dvb_frontend *fe));
+
+static void dvb_frontend_free(struct kref *ref)
 {
-	struct dvb_frontend_private *fepriv =
-		container_of(ref, struct dvb_frontend_private, refcount);
+	struct dvb_frontend *fe =
+		container_of(ref, struct dvb_frontend, refcount);
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	dvb_free_device(fepriv->dvbdev);
+
+	dvb_frontend_invoke_release(fe, fe->ops.release);
+
 	kfree(fepriv);
 }
 
-static void dvb_frontend_private_put(struct dvb_frontend_private *fepriv)
+static void dvb_frontend_put(struct dvb_frontend *fe)
 {
-	kref_put(&fepriv->refcount, dvb_frontend_private_free);
+	kref_put(&fe->refcount, dvb_frontend_free);
 }
 
-static void dvb_frontend_private_get(struct dvb_frontend_private *fepriv)
+static void dvb_frontend_get(struct dvb_frontend *fe)
 {
-	kref_get(&fepriv->refcount);
+	kref_get(&fe->refcount);
 }
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -1515,12 +1527,8 @@ static int dtv_set_frontend(struct dvb_f
 
 static bool is_dvbv3_delsys(u32 delsys)
 {
-	bool status;
-
-	status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
-		 (delsys == SYS_DVBS) || (delsys == SYS_ATSC);
-
-	return status;
+	return (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
+	       (delsys == SYS_DVBS) || (delsys == SYS_ATSC);
 }
 
 /**
@@ -2356,7 +2364,8 @@ static int dvb_frontend_ioctl_legacy(str
 			int i;
 			u8 last = 1;
 			if (dvb_frontend_debug)
-				printk("%s switch command: 0x%04lx\n", __func__, swcmd);
+				dprintk("%s switch command: 0x%04lx\n",
+					__func__, swcmd);
 			nexttime = ktime_get_boottime();
 			if (dvb_frontend_debug)
 				tv[0] = nexttime;
@@ -2379,10 +2388,10 @@ static int dvb_frontend_ioctl_legacy(str
 					dvb_frontend_sleep_until(&nexttime, 8000);
 			}
 			if (dvb_frontend_debug) {
-				printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
+				dprintk("%s(%d): switch delay (should be 32k followed by all 8k)\n",
 					__func__, fe->dvb->num);
 				for (i = 1; i < 10; i++)
-					printk("%d: %d\n", i,
+					pr_info("%d: %d\n", i,
 					(int) ktime_us_delta(tv[i], tv[i-1]));
 			}
 			err = 0;
@@ -2545,7 +2554,7 @@ static int dvb_frontend_open(struct inod
 		fepriv->events.eventr = fepriv->events.eventw = 0;
 	}
 
-	dvb_frontend_private_get(fepriv);
+	dvb_frontend_get(fe);
 
 	if (adapter->mfe_shared)
 		mutex_unlock (&adapter->mfe_lock);
@@ -2595,7 +2604,7 @@ static int dvb_frontend_release(struct i
 			fe->ops.ts_bus_ctrl(fe, 0);
 	}
 
-	dvb_frontend_private_put(fepriv);
+	dvb_frontend_put(fe);
 
 	return ret;
 }
@@ -2685,7 +2694,14 @@ int dvb_register_frontend(struct dvb_ada
 	}
 	fepriv = fe->frontend_priv;
 
-	kref_init(&fepriv->refcount);
+	kref_init(&fe->refcount);
+
+	/*
+	 * After initialization, there need to be two references: one
+	 * for dvb_unregister_frontend(), and another one for
+	 * dvb_frontend_detach().
+	 */
+	dvb_frontend_get(fe);
 
 	sema_init(&fepriv->sem, 1);
 	init_waitqueue_head (&fepriv->wait_queue);
@@ -2720,50 +2736,33 @@ int dvb_unregister_frontend(struct dvb_f
 	dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
 	mutex_lock(&frontend_mutex);
-	dvb_frontend_stop (fe);
-	dvb_unregister_device (fepriv->dvbdev);
+	dvb_frontend_stop(fe);
+	dvb_remove_device(fepriv->dvbdev);
 
 	/* fe is invalid now */
 	mutex_unlock(&frontend_mutex);
-	dvb_frontend_private_put(fepriv);
+	dvb_frontend_put(fe);
 	return 0;
 }
 EXPORT_SYMBOL(dvb_unregister_frontend);
 
-#ifdef CONFIG_MEDIA_ATTACH
-void dvb_frontend_detach(struct dvb_frontend* fe)
+static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
+					void (*release)(struct dvb_frontend *fe))
 {
-	void *ptr;
-
-	if (fe->ops.release_sec) {
-		fe->ops.release_sec(fe);
-		dvb_detach(fe->ops.release_sec);
-	}
-	if (fe->ops.tuner_ops.release) {
-		fe->ops.tuner_ops.release(fe);
-		dvb_detach(fe->ops.tuner_ops.release);
-	}
-	if (fe->ops.analog_ops.release) {
-		fe->ops.analog_ops.release(fe);
-		dvb_detach(fe->ops.analog_ops.release);
-	}
-	ptr = (void*)fe->ops.release;
-	if (ptr) {
-		fe->ops.release(fe);
-		dvb_detach(ptr);
+	if (release) {
+		release(fe);
+#ifdef CONFIG_MEDIA_ATTACH
+		dvb_detach(release);
+#endif
 	}
 }
-#else
+
 void dvb_frontend_detach(struct dvb_frontend* fe)
 {
-	if (fe->ops.release_sec)
-		fe->ops.release_sec(fe);
-	if (fe->ops.tuner_ops.release)
-		fe->ops.tuner_ops.release(fe);
-	if (fe->ops.analog_ops.release)
-		fe->ops.analog_ops.release(fe);
-	if (fe->ops.release)
-		fe->ops.release(fe);
+	dvb_frontend_invoke_release(fe, fe->ops.release_sec);
+	dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release);
+	dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release);
+	dvb_frontend_invoke_release(fe, fe->ops.detach);
+	dvb_frontend_put(fe);
 }
-#endif
 EXPORT_SYMBOL(dvb_frontend_detach);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_frontend.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_frontend.h
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_frontend.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_frontend.h	2017-02-12 16:03:20.000000000 -0500
@@ -225,7 +225,7 @@ struct dvb_tuner_ops {
 
 	struct dvb_tuner_info info;
 
-	int (*release)(struct dvb_frontend *fe);
+	void (*release)(struct dvb_frontend *fe);
 	int (*init)(struct dvb_frontend *fe);
 	int (*sleep)(struct dvb_frontend *fe);
 	int (*suspend)(struct dvb_frontend *fe);
@@ -323,7 +323,11 @@ struct dtv_frontend_properties;
  *
  * @info:		embedded struct dvb_tuner_info with tuner properties
  * @delsys:		Delivery systems supported by the frontend
- * @release:		callback function called when frontend is dettached.
+ * @detach:		callback function called when frontend is detached.
+ *			drivers should clean up, but not yet free the struct
+ *			dvb_frontend allocation.
+ * @release:		callback function called when frontend is ready to be
+ *			freed.
  *			drivers should free any allocated memory.
  * @release_sec:	callback function requesting that the Satelite Equipment
  *			Control (SEC) driver to release and free any memory
@@ -408,6 +412,7 @@ struct dvb_frontend_ops {
 
 	u8 delsys[MAX_DELSYS];
 
+	void (*detach)(struct dvb_frontend *fe);
 	void (*release)(struct dvb_frontend* fe);
 	void (*release_sec)(struct dvb_frontend* fe);
 
@@ -655,6 +660,7 @@ struct dtv_frontend_properties {
  */
 
 struct dvb_frontend {
+	struct kref refcount;
 	struct dvb_frontend_ops ops;
 	struct dvb_adapter *dvb;
 	void *demodulator_priv;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_net.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_net.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_net.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_net.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,13 +54,15 @@
  *
  */
 
+#define pr_fmt(fmt) "dvb_net: " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/dvb/net.h>
 #include <linux/uio.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/crc32.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
@@ -309,451 +311,584 @@ static inline void reset_ule( struct dvb
  * Decode ULE SNDUs according to draft-ietf-ipdvb-ule-03.txt from a sequence of
  * TS cells of a single PID.
  */
-static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
-{
-	struct dvb_net_priv *priv = netdev_priv(dev);
-	unsigned long skipped = 0L;
-	const u8 *ts, *ts_end, *from_where = NULL;
-	u8 ts_remain = 0, how_much = 0, new_ts = 1;
-	struct ethhdr *ethh = NULL;
-	bool error = false;
 
+struct dvb_net_ule_handle {
+	struct net_device *dev;
+	struct dvb_net_priv *priv;
+	struct ethhdr *ethh;
+	const u8 *buf;
+	size_t buf_len;
+	unsigned long skipped;
+	const u8 *ts, *ts_end, *from_where;
+	u8 ts_remain, how_much, new_ts;
+	bool error;
 #ifdef ULE_DEBUG
-	/* The code inside ULE_DEBUG keeps a history of the last 100 TS cells processed. */
+	/*
+	 * The code inside ULE_DEBUG keeps a history of the
+	 * last 100 TS cells processed.
+	 */
 	static unsigned char ule_hist[100*TS_SZ];
 	static unsigned char *ule_where = ule_hist, ule_dump;
 #endif
+};
 
-	/* For all TS cells in current buffer.
-	 * Appearently, we are called for every single TS cell.
-	 */
-	for (ts = buf, ts_end = buf + buf_len; ts < ts_end; /* no default incr. */ ) {
-
-		if (new_ts) {
-			/* We are about to process a new TS cell. */
+static int dvb_net_ule_new_ts_cell(struct dvb_net_ule_handle *h)
+{
+	/* We are about to process a new TS cell. */
 
 #ifdef ULE_DEBUG
-			if (ule_where >= &ule_hist[100*TS_SZ]) ule_where = ule_hist;
-			memcpy( ule_where, ts, TS_SZ );
-			if (ule_dump) {
-				hexdump( ule_where, TS_SZ );
-				ule_dump = 0;
-			}
-			ule_where += TS_SZ;
+	if (h->ule_where >= &h->ule_hist[100*TS_SZ])
+		h->ule_where = h->ule_hist;
+	memcpy(h->ule_where, h->ts, TS_SZ);
+	if (h->ule_dump) {
+		hexdump(h->ule_where, TS_SZ);
+		h->ule_dump = 0;
+	}
+	h->ule_where += TS_SZ;
 #endif
 
-			/* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */
-			if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) {
-				printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
-				       priv->ts_count, ts[0],
-				       (ts[1] & TS_TEI) >> 7,
-				       (ts[3] & TS_SC) >> 6);
+	/*
+	 * Check TS h->error conditions: sync_byte, transport_error_indicator,
+	 * scrambling_control .
+	 */
+	if ((h->ts[0] != TS_SYNC) || (h->ts[1] & TS_TEI) ||
+	    ((h->ts[3] & TS_SC) != 0)) {
+		pr_warn("%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
+			h->priv->ts_count, h->ts[0],
+			(h->ts[1] & TS_TEI) >> 7,
+			(h->ts[3] & TS_SC) >> 6);
 
-				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
-				if (priv->ule_skb) {
-					dev_kfree_skb( priv->ule_skb );
-					/* Prepare for next SNDU. */
-					dev->stats.rx_errors++;
-					dev->stats.rx_frame_errors++;
-				}
-				reset_ule(priv);
-				priv->need_pusi = 1;
+		/* Drop partly decoded SNDU, reset state, resync on PUSI. */
+		if (h->priv->ule_skb) {
+			dev_kfree_skb(h->priv->ule_skb);
+			/* Prepare for next SNDU. */
+			h->dev->stats.rx_errors++;
+			h->dev->stats.rx_frame_errors++;
+		}
+		reset_ule(h->priv);
+		h->priv->need_pusi = 1;
 
-				/* Continue with next TS cell. */
-				ts += TS_SZ;
-				priv->ts_count++;
-				continue;
-			}
+		/* Continue with next TS cell. */
+		h->ts += TS_SZ;
+		h->priv->ts_count++;
+		return 1;
+	}
 
-			ts_remain = 184;
-			from_where = ts + 4;
+	h->ts_remain = 184;
+	h->from_where = h->ts + 4;
+
+	return 0;
+}
+
+static int dvb_net_ule_ts_pusi(struct dvb_net_ule_handle *h)
+{
+	if (h->ts[1] & TS_PUSI) {
+		/* Find beginning of first ULE SNDU in current TS cell. */
+		/* Synchronize continuity counter. */
+		h->priv->tscc = h->ts[3] & 0x0F;
+		/* There is a pointer field here. */
+		if (h->ts[4] > h->ts_remain) {
+			pr_err("%lu: Invalid ULE packet (pointer field %d)\n",
+				h->priv->ts_count, h->ts[4]);
+			h->ts += TS_SZ;
+			h->priv->ts_count++;
+			return 1;
 		}
-		/* Synchronize on PUSI, if required. */
-		if (priv->need_pusi) {
-			if (ts[1] & TS_PUSI) {
-				/* Find beginning of first ULE SNDU in current TS cell. */
-				/* Synchronize continuity counter. */
-				priv->tscc = ts[3] & 0x0F;
-				/* There is a pointer field here. */
-				if (ts[4] > ts_remain) {
-					printk(KERN_ERR "%lu: Invalid ULE packet "
-					       "(pointer field %d)\n", priv->ts_count, ts[4]);
-					ts += TS_SZ;
-					priv->ts_count++;
-					continue;
-				}
-				/* Skip to destination of pointer field. */
-				from_where = &ts[5] + ts[4];
-				ts_remain -= 1 + ts[4];
-				skipped = 0;
-			} else {
-				skipped++;
-				ts += TS_SZ;
-				priv->ts_count++;
-				continue;
-			}
+		/* Skip to destination of pointer field. */
+		h->from_where = &h->ts[5] + h->ts[4];
+		h->ts_remain -= 1 + h->ts[4];
+		h->skipped = 0;
+	} else {
+		h->skipped++;
+		h->ts += TS_SZ;
+		h->priv->ts_count++;
+		return 1;
+	}
+
+	return 0;
+}
+
+static int dvb_net_ule_new_ts(struct dvb_net_ule_handle *h)
+{
+	/* Check continuity counter. */
+	if ((h->ts[3] & 0x0F) == h->priv->tscc)
+		h->priv->tscc = (h->priv->tscc + 1) & 0x0F;
+	else {
+		/* TS discontinuity handling: */
+		pr_warn("%lu: TS discontinuity: got %#x, expected %#x.\n",
+			h->priv->ts_count, h->ts[3] & 0x0F,
+			h->priv->tscc);
+		/* Drop partly decoded SNDU, reset state, resync on PUSI. */
+		if (h->priv->ule_skb) {
+			dev_kfree_skb(h->priv->ule_skb);
+			/* Prepare for next SNDU. */
+			// reset_ule(h->priv);  moved to below.
+			h->dev->stats.rx_errors++;
+			h->dev->stats.rx_frame_errors++;
 		}
+		reset_ule(h->priv);
+		/* skip to next PUSI. */
+		h->priv->need_pusi = 1;
+		return 1;
+	}
+	/*
+	 * If we still have an incomplete payload, but PUSI is
+	 * set; some TS cells are missing.
+	 * This is only possible here, if we missed exactly 16 TS
+	 * cells (continuity counter wrap).
+	 */
+	if (h->ts[1] & TS_PUSI) {
+		if (!h->priv->need_pusi) {
+			if (!(*h->from_where < (h->ts_remain-1)) ||
+			    *h->from_where != h->priv->ule_sndu_remain) {
+				/*
+				 * Pointer field is invalid.
+				 * Drop this TS cell and any started ULE SNDU.
+				 */
+				pr_warn("%lu: Invalid pointer field: %u.\n",
+					h->priv->ts_count,
+					*h->from_where);
 
-		if (new_ts) {
-			/* Check continuity counter. */
-			if ((ts[3] & 0x0F) == priv->tscc)
-				priv->tscc = (priv->tscc + 1) & 0x0F;
-			else {
-				/* TS discontinuity handling: */
-				printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
-				       "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
-				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
-				if (priv->ule_skb) {
-					dev_kfree_skb( priv->ule_skb );
-					/* Prepare for next SNDU. */
-					// reset_ule(priv);  moved to below.
-					dev->stats.rx_errors++;
-					dev->stats.rx_frame_errors++;
+				/*
+				 * Drop partly decoded SNDU, reset state,
+				 * resync on PUSI.
+				 */
+				if (h->priv->ule_skb) {
+					h->error = true;
+					dev_kfree_skb(h->priv->ule_skb);
 				}
-				reset_ule(priv);
-				/* skip to next PUSI. */
-				priv->need_pusi = 1;
-				continue;
+
+				if (h->error || h->priv->ule_sndu_remain) {
+					h->dev->stats.rx_errors++;
+					h->dev->stats.rx_frame_errors++;
+					h->error = false;
+				}
+
+				reset_ule(h->priv);
+				h->priv->need_pusi = 1;
+				return 1;
 			}
-			/* If we still have an incomplete payload, but PUSI is
-			 * set; some TS cells are missing.
-			 * This is only possible here, if we missed exactly 16 TS
-			 * cells (continuity counter wrap). */
-			if (ts[1] & TS_PUSI) {
-				if (! priv->need_pusi) {
-					if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
-						/* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */
-						printk(KERN_WARNING "%lu: Invalid pointer "
-						       "field: %u.\n", priv->ts_count, *from_where);
+			/*
+			 * Skip pointer field (we're processing a
+			 * packed payload).
+			 */
+			h->from_where += 1;
+			h->ts_remain -= 1;
+		} else
+			h->priv->need_pusi = 0;
 
-						/* Drop partly decoded SNDU, reset state, resync on PUSI. */
-						if (priv->ule_skb) {
-							error = true;
-							dev_kfree_skb(priv->ule_skb);
-						}
+		if (h->priv->ule_sndu_remain > 183) {
+			/*
+			 * Current SNDU lacks more data than there
+			 * could be available in the current TS cell.
+			 */
+			h->dev->stats.rx_errors++;
+			h->dev->stats.rx_length_errors++;
+			pr_warn("%lu: Expected %d more SNDU bytes, but got PUSI (pf %d, h->ts_remain %d).  Flushing incomplete payload.\n",
+				h->priv->ts_count,
+				h->priv->ule_sndu_remain,
+				h->ts[4], h->ts_remain);
+			dev_kfree_skb(h->priv->ule_skb);
+			/* Prepare for next SNDU. */
+			reset_ule(h->priv);
+			/*
+			 * Resync: go to where pointer field points to:
+			 * start of next ULE SNDU.
+			 */
+			h->from_where += h->ts[4];
+			h->ts_remain -= h->ts[4];
+		}
+	}
+	return 0;
+}
 
-						if (error || priv->ule_sndu_remain) {
-							dev->stats.rx_errors++;
-							dev->stats.rx_frame_errors++;
-							error = false;
-						}
 
-						reset_ule(priv);
-						priv->need_pusi = 1;
-						continue;
-					}
-					/* Skip pointer field (we're processing a
-					 * packed payload). */
-					from_where += 1;
-					ts_remain -= 1;
-				} else
-					priv->need_pusi = 0;
+/*
+ * Start a new payload with skb.
+ * Find ULE header.  It is only guaranteed that the
+ * length field (2 bytes) is contained in the current
+ * TS.
+ * Check h.ts_remain has to be >= 2 here.
+ */
+static int dvb_net_ule_new_payload(struct dvb_net_ule_handle *h)
+{
+	if (h->ts_remain < 2) {
+		pr_warn("Invalid payload packing: only %d bytes left in TS.  Resyncing.\n",
+			h->ts_remain);
+		h->priv->ule_sndu_len = 0;
+		h->priv->need_pusi = 1;
+		h->ts += TS_SZ;
+		return 1;
+	}
 
-				if (priv->ule_sndu_remain > 183) {
-					/* Current SNDU lacks more data than there could be available in the
-					 * current TS cell. */
-					dev->stats.rx_errors++;
-					dev->stats.rx_length_errors++;
-					printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
-					       "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n",
-					       priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
-					dev_kfree_skb(priv->ule_skb);
-					/* Prepare for next SNDU. */
-					reset_ule(priv);
-					/* Resync: go to where pointer field points to: start of next ULE SNDU. */
-					from_where += ts[4];
-					ts_remain -= ts[4];
-				}
-			}
+	if (!h->priv->ule_sndu_len) {
+		/* Got at least two bytes, thus extrace the SNDU length. */
+		h->priv->ule_sndu_len = h->from_where[0] << 8 |
+					h->from_where[1];
+		if (h->priv->ule_sndu_len & 0x8000) {
+			/* D-Bit is set: no dest mac present. */
+			h->priv->ule_sndu_len &= 0x7FFF;
+			h->priv->ule_dbit = 1;
+		} else
+			h->priv->ule_dbit = 0;
+
+		if (h->priv->ule_sndu_len < 5) {
+			pr_warn("%lu: Invalid ULE SNDU length %u. Resyncing.\n",
+				h->priv->ts_count,
+				h->priv->ule_sndu_len);
+			h->dev->stats.rx_errors++;
+			h->dev->stats.rx_length_errors++;
+			h->priv->ule_sndu_len = 0;
+			h->priv->need_pusi = 1;
+			h->new_ts = 1;
+			h->ts += TS_SZ;
+			h->priv->ts_count++;
+			return 1;
 		}
+		h->ts_remain -= 2;	/* consume the 2 bytes SNDU length. */
+		h->from_where += 2;
+	}
 
-		/* Check if new payload needs to be started. */
-		if (priv->ule_skb == NULL) {
-			/* Start a new payload with skb.
-			 * Find ULE header.  It is only guaranteed that the
-			 * length field (2 bytes) is contained in the current
-			 * TS.
-			 * Check ts_remain has to be >= 2 here. */
-			if (ts_remain < 2) {
-				printk(KERN_WARNING "Invalid payload packing: only %d "
-				       "bytes left in TS.  Resyncing.\n", ts_remain);
-				priv->ule_sndu_len = 0;
-				priv->need_pusi = 1;
-				ts += TS_SZ;
-				continue;
-			}
+	h->priv->ule_sndu_remain = h->priv->ule_sndu_len + 2;
+	/*
+	 * State of current TS:
+	 *   h->ts_remain (remaining bytes in the current TS cell)
+	 *   0	ule_type is not available now, we need the next TS cell
+	 *   1	the first byte of the ule_type is present
+	 * >=2	full ULE header present, maybe some payload data as well.
+	 */
+	switch (h->ts_remain) {
+	case 1:
+		h->priv->ule_sndu_remain--;
+		h->priv->ule_sndu_type = h->from_where[0] << 8;
 
-			if (! priv->ule_sndu_len) {
-				/* Got at least two bytes, thus extrace the SNDU length. */
-				priv->ule_sndu_len = from_where[0] << 8 | from_where[1];
-				if (priv->ule_sndu_len & 0x8000) {
-					/* D-Bit is set: no dest mac present. */
-					priv->ule_sndu_len &= 0x7FFF;
-					priv->ule_dbit = 1;
-				} else
-					priv->ule_dbit = 0;
+		/* first byte of ule_type is set. */
+		h->priv->ule_sndu_type_1 = 1;
+		h->ts_remain -= 1;
+		h->from_where += 1;
+		/* fallthrough */
+	case 0:
+		h->new_ts = 1;
+		h->ts += TS_SZ;
+		h->priv->ts_count++;
+		return 1;
 
-				if (priv->ule_sndu_len < 5) {
-					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
-					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
-					dev->stats.rx_errors++;
-					dev->stats.rx_length_errors++;
-					priv->ule_sndu_len = 0;
-					priv->need_pusi = 1;
-					new_ts = 1;
-					ts += TS_SZ;
-					priv->ts_count++;
-					continue;
-				}
-				ts_remain -= 2;	/* consume the 2 bytes SNDU length. */
-				from_where += 2;
-			}
+	default: /* complete ULE header is present in current TS. */
+		/* Extract ULE type field. */
+		if (h->priv->ule_sndu_type_1) {
+			h->priv->ule_sndu_type_1 = 0;
+			h->priv->ule_sndu_type |= h->from_where[0];
+			h->from_where += 1; /* points to payload start. */
+			h->ts_remain -= 1;
+		} else {
+			/* Complete type is present in new TS. */
+			h->priv->ule_sndu_type = h->from_where[0] << 8 |
+						 h->from_where[1];
+			h->from_where += 2; /* points to payload start. */
+			h->ts_remain -= 2;
+		}
+		break;
+	}
 
-			priv->ule_sndu_remain = priv->ule_sndu_len + 2;
+	/*
+	 * Allocate the skb (decoder target buffer) with the correct size,
+	 * as follows:
+	 *
+	 * prepare for the largest case: bridged SNDU with MAC address
+	 * (dbit = 0).
+	 */
+	h->priv->ule_skb = dev_alloc_skb(h->priv->ule_sndu_len +
+					 ETH_HLEN + ETH_ALEN);
+	if (!h->priv->ule_skb) {
+		pr_notice("%s: Memory squeeze, dropping packet.\n",
+			  h->dev->name);
+		h->dev->stats.rx_dropped++;
+		return -1;
+	}
+
+	/* This includes the CRC32 _and_ dest mac, if !dbit. */
+	h->priv->ule_sndu_remain = h->priv->ule_sndu_len;
+	h->priv->ule_skb->dev = h->dev;
+	/*
+	 * Leave space for Ethernet or bridged SNDU header
+	 * (eth hdr plus one MAC addr).
+	 */
+	skb_reserve(h->priv->ule_skb, ETH_HLEN + ETH_ALEN);
+
+	return 0;
+}
+
+
+static int dvb_net_ule_should_drop(struct dvb_net_ule_handle *h)
+{
+	static const u8 bc_addr[ETH_ALEN] = { [0 ... ETH_ALEN - 1] = 0xff };
+
+	/*
+	 * The destination MAC address is the next data in the skb.  It comes
+	 * before any extension headers.
+	 *
+	 * Check if the payload of this SNDU should be passed up the stack.
+	 */
+	if (h->priv->rx_mode == RX_MODE_PROMISC)
+		return 0;
+
+	if (h->priv->ule_skb->data[0] & 0x01) {
+		/* multicast or broadcast */
+		if (!ether_addr_equal(h->priv->ule_skb->data, bc_addr)) {
+			/* multicast */
+			if (h->priv->rx_mode == RX_MODE_MULTI) {
+				int i;
+
+				for (i = 0; i < h->priv->multi_num &&
+				     !ether_addr_equal(h->priv->ule_skb->data,
+						       h->priv->multi_macs[i]);
+				     i++)
+					;
+				if (i == h->priv->multi_num)
+					return 1;
+			} else if (h->priv->rx_mode != RX_MODE_ALL_MULTI)
+				return 1; /* no broadcast; */
 			/*
-			 * State of current TS:
-			 *   ts_remain (remaining bytes in the current TS cell)
-			 *   0	ule_type is not available now, we need the next TS cell
-			 *   1	the first byte of the ule_type is present
-			 * >=2	full ULE header present, maybe some payload data as well.
+			 * else:
+			 * all multicast mode: accept all multicast packets
 			 */
-			switch (ts_remain) {
-				case 1:
-					priv->ule_sndu_remain--;
-					priv->ule_sndu_type = from_where[0] << 8;
-					priv->ule_sndu_type_1 = 1; /* first byte of ule_type is set. */
-					ts_remain -= 1; from_where += 1;
-					/* Continue w/ next TS. */
-				case 0:
-					new_ts = 1;
-					ts += TS_SZ;
-					priv->ts_count++;
-					continue;
+		}
+		/* else: broadcast */
+	} else if (!ether_addr_equal(h->priv->ule_skb->data, h->dev->dev_addr))
+		return 1;
 
-				default: /* complete ULE header is present in current TS. */
-					/* Extract ULE type field. */
-					if (priv->ule_sndu_type_1) {
-						priv->ule_sndu_type_1 = 0;
-						priv->ule_sndu_type |= from_where[0];
-						from_where += 1; /* points to payload start. */
-						ts_remain -= 1;
-					} else {
-						/* Complete type is present in new TS. */
-						priv->ule_sndu_type = from_where[0] << 8 | from_where[1];
-						from_where += 2; /* points to payload start. */
-						ts_remain -= 2;
-					}
-					break;
-			}
+	return 0;
+}
 
-			/* Allocate the skb (decoder target buffer) with the correct size, as follows:
-			 * prepare for the largest case: bridged SNDU with MAC address (dbit = 0). */
-			priv->ule_skb = dev_alloc_skb( priv->ule_sndu_len + ETH_HLEN + ETH_ALEN );
-			if (priv->ule_skb == NULL) {
-				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
-				       dev->name);
-				dev->stats.rx_dropped++;
-				return;
-			}
 
-			/* This includes the CRC32 _and_ dest mac, if !dbit. */
-			priv->ule_sndu_remain = priv->ule_sndu_len;
-			priv->ule_skb->dev = dev;
-			/* Leave space for Ethernet or bridged SNDU header (eth hdr plus one MAC addr). */
-			skb_reserve( priv->ule_skb, ETH_HLEN + ETH_ALEN );
+static void dvb_net_ule_check_crc(struct dvb_net_ule_handle *h,
+				  u32 ule_crc, u32 expected_crc)
+{
+	u8 dest_addr[ETH_ALEN];
+
+	if (ule_crc != expected_crc) {
+		pr_warn("%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n",
+			h->priv->ts_count, ule_crc, expected_crc,
+			h->priv->ule_sndu_len, h->priv->ule_sndu_type,
+			h->ts_remain,
+			h->ts_remain > 2 ?
+				*(unsigned short *)h->from_where : 0);
+
+	#ifdef ULE_DEBUG
+		hexdump(iov[0].iov_base, iov[0].iov_len);
+		hexdump(iov[1].iov_base, iov[1].iov_len);
+		hexdump(iov[2].iov_base, iov[2].iov_len);
+
+		if (h->ule_where == h->ule_hist) {
+			hexdump(&h->ule_hist[98*TS_SZ], TS_SZ);
+			hexdump(&h->ule_hist[99*TS_SZ], TS_SZ);
+		} else if (h->ule_where == &h->ule_hist[TS_SZ]) {
+			hexdump(&h->ule_hist[99*TS_SZ], TS_SZ);
+			hexdump(h->ule_hist, TS_SZ);
+		} else {
+			hexdump(h->ule_where - TS_SZ - TS_SZ, TS_SZ);
+			hexdump(h->ule_where - TS_SZ, TS_SZ);
+		}
+		h->ule_dump = 1;
+	#endif
+
+		h->dev->stats.rx_errors++;
+		h->dev->stats.rx_crc_errors++;
+		dev_kfree_skb(h->priv->ule_skb);
+
+		return;
+	}
+
+	/* CRC32 verified OK. */
+
+	/* CRC32 was OK, so remove it from skb. */
+	h->priv->ule_skb->tail -= 4;
+	h->priv->ule_skb->len -= 4;
+
+	if (!h->priv->ule_dbit) {
+		if (dvb_net_ule_should_drop(h)) {
+#ifdef ULE_DEBUG
+			netdev_dbg(h->dev,
+				   "Dropping SNDU: MAC destination address does not match: dest addr: %pM, h->dev addr: %pM\n",
+				   h->priv->ule_skb->data, h->dev->dev_addr);
+#endif
+			dev_kfree_skb(h->priv->ule_skb);
+			return;
+		}
+
+		skb_copy_from_linear_data(h->priv->ule_skb, dest_addr,
+					  ETH_ALEN);
+		skb_pull(h->priv->ule_skb, ETH_ALEN);
+	} else {
+		/* dest_addr buffer is only valid if h->priv->ule_dbit == 0 */
+		eth_zero_addr(dest_addr);
+	}
+
+	/* Handle ULE Extension Headers. */
+	if (h->priv->ule_sndu_type < ETH_P_802_3_MIN) {
+		/* There is an extension header.  Handle it accordingly. */
+		int l = handle_ule_extensions(h->priv);
+
+		if (l < 0) {
+			/*
+			 * Mandatory extension header unknown or TEST SNDU.
+			 * Drop it.
+			 */
+
+			// pr_warn("Dropping SNDU, extension headers.\n" );
+			dev_kfree_skb(h->priv->ule_skb);
+			return;
+		}
+		skb_pull(h->priv->ule_skb, l);
+	}
+
+	/*
+	 * Construct/assure correct ethernet header.
+	 * Note: in bridged mode (h->priv->ule_bridged != 0)
+	 * we already have the (original) ethernet
+	 * header at the start of the payload (after
+	 * optional dest. address and any extension
+	 * headers).
+	 */
+	if (!h->priv->ule_bridged) {
+		skb_push(h->priv->ule_skb, ETH_HLEN);
+		h->ethh = (struct ethhdr *)h->priv->ule_skb->data;
+		memcpy(h->ethh->h_dest, dest_addr, ETH_ALEN);
+		eth_zero_addr(h->ethh->h_source);
+		h->ethh->h_proto = htons(h->priv->ule_sndu_type);
+	}
+	/* else:  skb is in correct state; nothing to do. */
+	h->priv->ule_bridged = 0;
+
+	/* Stuff into kernel's protocol stack. */
+	h->priv->ule_skb->protocol = dvb_net_eth_type_trans(h->priv->ule_skb,
+							   h->dev);
+	/*
+	 * If D-bit is set (i.e. destination MAC address not present),
+	 * receive the packet anyhow.
+	 */
+#if 0
+	if (h->priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
+		h->priv->ule_skb->pkt_type = PACKET_HOST;
+#endif
+	h->dev->stats.rx_packets++;
+	h->dev->stats.rx_bytes += h->priv->ule_skb->len;
+	netif_rx(h->priv->ule_skb);
+}
+
+static void dvb_net_ule(struct net_device *dev, const u8 *buf, size_t buf_len)
+{
+	int ret;
+	struct dvb_net_ule_handle h = {
+		.dev = dev,
+		.buf = buf,
+		.buf_len = buf_len,
+		.skipped = 0L,
+		.ts = NULL,
+		.ts_end = NULL,
+		.from_where = NULL,
+		.ts_remain = 0,
+		.how_much = 0,
+		.new_ts = 1,
+		.ethh = NULL,
+		.error = false,
+#ifdef ULE_DEBUG
+		.ule_where = ule_hist,
+#endif
+	};
+
+	/*
+	 * For all TS cells in current buffer.
+	 * Appearently, we are called for every single TS cell.
+	 */
+	for (h.ts = h.buf, h.ts_end = h.buf + h.buf_len;
+	     h.ts < h.ts_end; /* no incr. */) {
+		if (h.new_ts) {
+			/* We are about to process a new TS cell. */
+			if (dvb_net_ule_new_ts_cell(&h))
+				continue;
+		}
+
+		/* Synchronize on PUSI, if required. */
+		if (h.priv->need_pusi) {
+			if (dvb_net_ule_ts_pusi(&h))
+				continue;
+		}
+
+		if (h.new_ts) {
+			if (dvb_net_ule_new_ts(&h))
+				continue;
+		}
+
+		/* Check if new payload needs to be started. */
+		if (h.priv->ule_skb == NULL) {
+			ret = dvb_net_ule_new_payload(&h);
+			if (ret < 0)
+				return;
+			if (ret)
+				continue;
 		}
 
 		/* Copy data into our current skb. */
-		how_much = min(priv->ule_sndu_remain, (int)ts_remain);
-		memcpy(skb_put(priv->ule_skb, how_much), from_where, how_much);
-		priv->ule_sndu_remain -= how_much;
-		ts_remain -= how_much;
-		from_where += how_much;
+		h.how_much = min(h.priv->ule_sndu_remain, (int)h.ts_remain);
+		memcpy(skb_put(h.priv->ule_skb, h.how_much),
+		       h.from_where, h.how_much);
+		h.priv->ule_sndu_remain -= h.how_much;
+		h.ts_remain -= h.how_much;
+		h.from_where += h.how_much;
 
 		/* Check for complete payload. */
-		if (priv->ule_sndu_remain <= 0) {
+		if (h.priv->ule_sndu_remain <= 0) {
 			/* Check CRC32, we've got it in our skb already. */
-			__be16 ulen = htons(priv->ule_sndu_len);
-			__be16 utype = htons(priv->ule_sndu_type);
+			__be16 ulen = htons(h.priv->ule_sndu_len);
+			__be16 utype = htons(h.priv->ule_sndu_type);
 			const u8 *tail;
 			struct kvec iov[3] = {
 				{ &ulen, sizeof ulen },
 				{ &utype, sizeof utype },
-				{ priv->ule_skb->data, priv->ule_skb->len - 4 }
+				{ h.priv->ule_skb->data,
+				  h.priv->ule_skb->len - 4 }
 			};
 			u32 ule_crc = ~0L, expected_crc;
-			if (priv->ule_dbit) {
+			if (h.priv->ule_dbit) {
 				/* Set D-bit for CRC32 verification,
 				 * if it was set originally. */
 				ulen |= htons(0x8000);
 			}
 
 			ule_crc = iov_crc32(ule_crc, iov, 3);
-			tail = skb_tail_pointer(priv->ule_skb);
+			tail = skb_tail_pointer(h.priv->ule_skb);
 			expected_crc = *(tail - 4) << 24 |
 				       *(tail - 3) << 16 |
 				       *(tail - 2) << 8 |
 				       *(tail - 1);
-			if (ule_crc != expected_crc) {
-				printk(KERN_WARNING "%lu: CRC32 check FAILED: %08x / %08x, SNDU len %d type %#x, ts_remain %d, next 2: %x.\n",
-				       priv->ts_count, ule_crc, expected_crc, priv->ule_sndu_len, priv->ule_sndu_type, ts_remain, ts_remain > 2 ? *(unsigned short *)from_where : 0);
-
-#ifdef ULE_DEBUG
-				hexdump( iov[0].iov_base, iov[0].iov_len );
-				hexdump( iov[1].iov_base, iov[1].iov_len );
-				hexdump( iov[2].iov_base, iov[2].iov_len );
-
-				if (ule_where == ule_hist) {
-					hexdump( &ule_hist[98*TS_SZ], TS_SZ );
-					hexdump( &ule_hist[99*TS_SZ], TS_SZ );
-				} else if (ule_where == &ule_hist[TS_SZ]) {
-					hexdump( &ule_hist[99*TS_SZ], TS_SZ );
-					hexdump( ule_hist, TS_SZ );
-				} else {
-					hexdump( ule_where - TS_SZ - TS_SZ, TS_SZ );
-					hexdump( ule_where - TS_SZ, TS_SZ );
-				}
-				ule_dump = 1;
-#endif
-
-				dev->stats.rx_errors++;
-				dev->stats.rx_crc_errors++;
-				dev_kfree_skb(priv->ule_skb);
-			} else {
-				/* CRC32 verified OK. */
-				u8 dest_addr[ETH_ALEN];
-				static const u8 bc_addr[ETH_ALEN] =
-					{ [ 0 ... ETH_ALEN-1] = 0xff };
-
-				/* CRC32 was OK. Remove it from skb. */
-				priv->ule_skb->tail -= 4;
-				priv->ule_skb->len -= 4;
-
-				if (!priv->ule_dbit) {
-					/*
-					 * The destination MAC address is the
-					 * next data in the skb.  It comes
-					 * before any extension headers.
-					 *
-					 * Check if the payload of this SNDU
-					 * should be passed up the stack.
-					 */
-					register int drop = 0;
-					if (priv->rx_mode != RX_MODE_PROMISC) {
-						if (priv->ule_skb->data[0] & 0x01) {
-							/* multicast or broadcast */
-							if (!ether_addr_equal(priv->ule_skb->data, bc_addr)) {
-								/* multicast */
-								if (priv->rx_mode == RX_MODE_MULTI) {
-									int i;
-									for(i = 0; i < priv->multi_num &&
-									    !ether_addr_equal(priv->ule_skb->data,
-											      priv->multi_macs[i]); i++)
-										;
-									if (i == priv->multi_num)
-										drop = 1;
-								} else if (priv->rx_mode != RX_MODE_ALL_MULTI)
-									drop = 1; /* no broadcast; */
-								/* else: all multicast mode: accept all multicast packets */
-							}
-							/* else: broadcast */
-						}
-						else if (!ether_addr_equal(priv->ule_skb->data, dev->dev_addr))
-							drop = 1;
-						/* else: destination address matches the MAC address of our receiver device */
-					}
-					/* else: promiscuous mode; pass everything up the stack */
-
-					if (drop) {
-#ifdef ULE_DEBUG
-						netdev_dbg(dev, "Dropping SNDU: MAC destination address does not match: dest addr: %pM, dev addr: %pM\n",
-							   priv->ule_skb->data, dev->dev_addr);
-#endif
-						dev_kfree_skb(priv->ule_skb);
-						goto sndu_done;
-					}
-					else
-					{
-						skb_copy_from_linear_data(priv->ule_skb,
-							      dest_addr,
-							      ETH_ALEN);
-						skb_pull(priv->ule_skb, ETH_ALEN);
-					}
-				}
-
-				/* Handle ULE Extension Headers. */
-				if (priv->ule_sndu_type < ETH_P_802_3_MIN) {
-					/* There is an extension header.  Handle it accordingly. */
-					int l = handle_ule_extensions(priv);
-					if (l < 0) {
-						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */
-						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
-						dev_kfree_skb(priv->ule_skb);
-						goto sndu_done;
-					}
-					skb_pull(priv->ule_skb, l);
-				}
-
-				/*
-				 * Construct/assure correct ethernet header.
-				 * Note: in bridged mode (priv->ule_bridged !=
-				 * 0) we already have the (original) ethernet
-				 * header at the start of the payload (after
-				 * optional dest. address and any extension
-				 * headers).
-				 */
 
-				if (!priv->ule_bridged) {
-					skb_push(priv->ule_skb, ETH_HLEN);
-					ethh = (struct ethhdr *)priv->ule_skb->data;
-					if (!priv->ule_dbit) {
-						 /* dest_addr buffer is only valid if priv->ule_dbit == 0 */
-						memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
-						eth_zero_addr(ethh->h_source);
-					}
-					else /* zeroize source and dest */
-						memset( ethh, 0, ETH_ALEN*2 );
-
-					ethh->h_proto = htons(priv->ule_sndu_type);
-				}
-				/* else:  skb is in correct state; nothing to do. */
-				priv->ule_bridged = 0;
+			dvb_net_ule_check_crc(&h, ule_crc, expected_crc);
 
-				/* Stuff into kernel's protocol stack. */
-				priv->ule_skb->protocol = dvb_net_eth_type_trans(priv->ule_skb, dev);
-				/* If D-bit is set (i.e. destination MAC address not present),
-				 * receive the packet anyhow. */
-				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
-					priv->ule_skb->pkt_type = PACKET_HOST; */
-				dev->stats.rx_packets++;
-				dev->stats.rx_bytes += priv->ule_skb->len;
-				netif_rx(priv->ule_skb);
-			}
-			sndu_done:
 			/* Prepare for next SNDU. */
-			reset_ule(priv);
+			reset_ule(h.priv);
 		}
 
 		/* More data in current TS (look at the bytes following the CRC32)? */
-		if (ts_remain >= 2 && *((unsigned short *)from_where) != 0xFFFF) {
+		if (h.ts_remain >= 2 && *((unsigned short *)h.from_where) != 0xFFFF) {
 			/* Next ULE SNDU starts right there. */
-			new_ts = 0;
-			priv->ule_skb = NULL;
-			priv->ule_sndu_type_1 = 0;
-			priv->ule_sndu_len = 0;
-			// printk(KERN_WARNING "More data in current TS: [%#x %#x %#x %#x]\n",
-			//	*(from_where + 0), *(from_where + 1),
-			//	*(from_where + 2), *(from_where + 3));
-			// printk(KERN_WARNING "ts @ %p, stopped @ %p:\n", ts, from_where + 0);
-			// hexdump(ts, 188);
+			h.new_ts = 0;
+			h.priv->ule_skb = NULL;
+			h.priv->ule_sndu_type_1 = 0;
+			h.priv->ule_sndu_len = 0;
+			// pr_warn("More data in current TS: [%#x %#x %#x %#x]\n",
+			//	*(h.from_where + 0), *(h.from_where + 1),
+			//	*(h.from_where + 2), *(h.from_where + 3));
+			// pr_warn("h.ts @ %p, stopped @ %p:\n", h.ts, h.from_where + 0);
+			// hexdump(h.ts, 188);
 		} else {
-			new_ts = 1;
-			ts += TS_SZ;
-			priv->ts_count++;
-			if (priv->ule_skb == NULL) {
-				priv->need_pusi = 1;
-				priv->ule_sndu_type_1 = 0;
-				priv->ule_sndu_len = 0;
+			h.new_ts = 1;
+			h.ts += TS_SZ;
+			h.priv->ts_count++;
+			if (h.priv->ule_skb == NULL) {
+				h.priv->need_pusi = 1;
+				h.priv->ule_sndu_type_1 = 0;
+				h.priv->ule_sndu_len = 0;
 			}
 		}
 	}	/* for all available TS cells */
@@ -766,10 +901,10 @@ static int dvb_net_ts_callback(const u8
 	struct net_device *dev = feed->priv;
 
 	if (buffer2)
-		printk(KERN_WARNING "buffer2 not NULL: %p.\n", buffer2);
+		pr_warn("buffer2 not NULL: %p.\n", buffer2);
 	if (buffer1_len > 32768)
-		printk(KERN_WARNING "length > 32k: %zu.\n", buffer1_len);
-	/* printk("TS callback: %u bytes, %u TS cells @ %p.\n",
+		pr_warn("length > 32k: %zu.\n", buffer1_len);
+	/* pr_info("TS callback: %u bytes, %u TS cells @ %p.\n",
 		  buffer1_len, buffer1_len / TS_SZ, buffer1); */
 	dvb_net_ule(dev, buffer1, buffer1_len);
 	return 0;
@@ -786,7 +921,7 @@ static void dvb_net_sec(struct net_devic
 
 	/* note: pkt_len includes a 32bit checksum */
 	if (pkt_len < 16) {
-		printk("%s: IP/MPE packet length = %d too small.\n",
+		pr_warn("%s: IP/MPE packet length = %d too small.\n",
 			dev->name, pkt_len);
 		stats->rx_errors++;
 		stats->rx_length_errors++;
@@ -824,7 +959,7 @@ static void dvb_net_sec(struct net_devic
 	 * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP
 	 */
 	if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) {
-		//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+		//pr_notice("%s: Memory squeeze, dropping packet.\n", dev->name);
 		stats->rx_dropped++;
 		return;
 	}
@@ -903,7 +1038,7 @@ static int dvb_net_filter_sec_set(struct
 	*secfilter=NULL;
 	ret = priv->secfeed->allocate_filter(priv->secfeed, secfilter);
 	if (ret<0) {
-		printk("%s: could not get filter\n", dev->name);
+		pr_err("%s: could not get filter\n", dev->name);
 		return ret;
 	}
 
@@ -944,7 +1079,7 @@ static int dvb_net_feed_start(struct net
 	netdev_dbg(dev, "rx_mode %i\n", priv->rx_mode);
 	mutex_lock(&priv->mutex);
 	if (priv->tsfeed || priv->secfeed || priv->secfilter || priv->multi_secfilter[0])
-		printk("%s: BUG %d\n", __func__, __LINE__);
+		pr_err("%s: BUG %d\n", __func__, __LINE__);
 
 	priv->secfeed=NULL;
 	priv->secfilter=NULL;
@@ -955,14 +1090,15 @@ static int dvb_net_feed_start(struct net
 		ret=demux->allocate_section_feed(demux, &priv->secfeed,
 					 dvb_net_sec_callback);
 		if (ret<0) {
-			printk("%s: could not allocate section feed\n", dev->name);
+			pr_err("%s: could not allocate section feed\n",
+			       dev->name);
 			goto error;
 		}
 
-		ret = priv->secfeed->set(priv->secfeed, priv->pid, 32768, 1);
+		ret = priv->secfeed->set(priv->secfeed, priv->pid, 1);
 
 		if (ret<0) {
-			printk("%s: could not set section feed\n", dev->name);
+			pr_err("%s: could not set section feed\n", dev->name);
 			priv->demux->release_section_feed(priv->demux, priv->secfeed);
 			priv->secfeed=NULL;
 			goto error;
@@ -1003,7 +1139,7 @@ static int dvb_net_feed_start(struct net
 		netdev_dbg(dev, "alloc tsfeed\n");
 		ret = demux->allocate_ts_feed(demux, &priv->tsfeed, dvb_net_ts_callback);
 		if (ret < 0) {
-			printk("%s: could not allocate ts feed\n", dev->name);
+			pr_err("%s: could not allocate ts feed\n", dev->name);
 			goto error;
 		}
 
@@ -1013,12 +1149,11 @@ static int dvb_net_feed_start(struct net
 					priv->pid, /* pid */
 					TS_PACKET, /* type */
 					DMX_PES_OTHER, /* pes type */
-					32768,     /* circular buffer size */
 					timeout    /* timeout */
 					);
 
 		if (ret < 0) {
-			printk("%s: could not set ts feed\n", dev->name);
+			pr_err("%s: could not set ts feed\n", dev->name);
 			priv->demux->release_ts_feed(priv->demux, priv->tsfeed);
 			priv->tsfeed = NULL;
 			goto error;
@@ -1067,7 +1202,7 @@ static int dvb_net_feed_stop(struct net_
 			priv->demux->release_section_feed(priv->demux, priv->secfeed);
 			priv->secfeed = NULL;
 		} else
-			printk("%s: no feed to stop\n", dev->name);
+			pr_err("%s: no feed to stop\n", dev->name);
 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
 		if (priv->tsfeed) {
 			if (priv->tsfeed->is_filtering) {
@@ -1078,7 +1213,7 @@ static int dvb_net_feed_stop(struct net_
 			priv->tsfeed = NULL;
 		}
 		else
-			printk("%s: no ts feed to stop\n", dev->name);
+			pr_err("%s: no ts feed to stop\n", dev->name);
 	} else
 		ret = -EINVAL;
 	mutex_unlock(&priv->mutex);
@@ -1198,7 +1333,6 @@ static const struct net_device_ops dvb_n
 	.ndo_start_xmit		= dvb_net_tx,
 	.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,
 };
 
@@ -1209,6 +1343,7 @@ static void dvb_net_setup(struct net_dev
 	dev->header_ops		= &dvb_header_ops;
 	dev->netdev_ops		= &dvb_netdev_ops;
 	dev->mtu		= 4096;
+	dev->max_mtu		= 4096;
 
 	dev->flags |= IFF_NOARP;
 }
@@ -1279,7 +1414,7 @@ static int dvb_net_add_if(struct dvb_net
 		free_netdev(net);
 		return result;
 	}
-	printk("dvb_net: created network interface %s\n", net->name);
+	pr_info("created network interface %s\n", net->name);
 
 	return if_num;
 }
@@ -1298,7 +1433,7 @@ static int dvb_net_remove_if(struct dvb_
 	dvb_net_stop(net);
 	flush_work(&priv->set_multicast_list_wq);
 	flush_work(&priv->restart_net_feed_wq);
-	printk("dvb_net: removed network interface %s\n", net->name);
+	pr_info("removed network interface %s\n", net->name);
 	unregister_netdev(net);
 	dvbnet->state[num]=0;
 	dvbnet->device[num] = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_ringbuffer.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_ringbuffer.c
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb_ringbuffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb_ringbuffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/string.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "dvb_ringbuffer.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/dvb-usb-ids.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb-usb-ids.h
--- linux-libre-4.9-gnu/drivers/media/dvb-core/dvb-usb-ids.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/dvb-usb-ids.h	2017-02-12 16:03:20.000000000 -0500
@@ -262,6 +262,7 @@
 #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI		0x3012
 #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2	0x3015
 #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400		0x3014
+#define USB_PID_TECHNOTREND_CONNECT_S2_4650_CI		0x3017
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2	0x0081
 #define USB_PID_TERRATEC_CINERGY_HT_USB_XE		0x0058
@@ -411,4 +412,5 @@
 #define USB_PID_SVEON_STV27                             0xd3af
 #define USB_PID_TURBOX_DTT_2000                         0xd3a4
 #define USB_PID_WINTV_SOLOHD                            0x0264
+#define USB_PID_EVOLVEO_XTRATV_STICK                   0xa115
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/Kconfig
--- linux-libre-4.9-gnu/drivers/media/dvb-core/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 config DVB_MAX_ADAPTERS
 	int "maximum number of DVB/ATSC adapters"
 	depends on DVB_CORE
-	default 8
+	default 16
 	range 1 255
 	help
 	  Maximum number of DVB/ATSC adapters. Increasing this number
@@ -13,7 +13,7 @@ config DVB_MAX_ADAPTERS
 	  if a much lower number of DVB/ATSC adapters is present.
 	  Only values in the range 4-32 are tested.
 
-	  If you are unsure about this, use the default value 8
+	  If you are unsure about this, use the default value 16
 
 config DVB_DYNAMIC_MINORS
 	bool "Dynamic DVB minor allocation"
@@ -27,3 +27,16 @@ config DVB_DYNAMIC_MINORS
 	  will be required to manage the device nodes.
 
 	  If you are unsure about this, say N here.
+
+config DVB_DEMUX_SECTION_LOSS_LOG
+	bool "Enable DVB demux section packet loss log"
+	depends on DVB_CORE
+	default n
+	help
+	  Enable extra log messages meant to detect packet loss
+	  inside the Kernel.
+
+	  Should not be enabled on normal cases, as logs can
+	  be very verbose.
+
+	  If you are unsure about this, say N here.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-core/Makefile linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/Makefile
--- linux-libre-4.9-gnu/drivers/media/dvb-core/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-core/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
 
 dvb-net-$(CONFIG_DVB_NET) := dvb_net.o
 
-dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
+dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o		 	\
 		 dvb_ca_en50221.o dvb_frontend.o 		\
 		 $(dvb-net-y) dvb_ringbuffer.o dvb_math.o
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/af9013.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/af9013.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/af9013.c	2016-12-11 17:45:15.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/af9013.c	2017-02-12 17:30:44.000000000 -0500
@@ -1351,7 +1351,7 @@ static void af9013_release(struct dvb_fr
 	kfree(state);
 }
 
-static struct dvb_frontend_ops af9013_ops;
+static const struct dvb_frontend_ops af9013_ops;
 
 static int af9013_download_firmware(struct af9013_state *state)
 {
@@ -1516,7 +1516,7 @@ err:
 }
 EXPORT_SYMBOL(af9013_attach);
 
-static struct dvb_frontend_ops af9013_ops = {
+static const struct dvb_frontend_ops af9013_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "Afatech AF9013",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/af9033.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/af9033.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/af9033.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/af9033.c	2017-02-12 16:03:20.000000000 -0500
@@ -1198,7 +1198,7 @@ err:
 	return ret;
 }
 
-static struct dvb_frontend_ops af9033_ops = {
+static const struct dvb_frontend_ops af9033_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "Afatech AF9033 (DVB-T)",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/as102_fe.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/as102_fe.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/as102_fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/as102_fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -415,7 +415,7 @@ static void as102_fe_release(struct dvb_
 }
 
 
-static struct dvb_frontend_ops as102_fe_ops = {
+static const struct dvb_frontend_ops as102_fe_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "Abilis AS102 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/ascot2e.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ascot2e.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/ascot2e.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ascot2e.c	2017-02-12 16:03:20.000000000 -0500
@@ -254,14 +254,13 @@ static int ascot2e_init(struct dvb_front
 	return ascot2e_leave_power_save(priv);
 }
 
-static int ascot2e_release(struct dvb_frontend *fe)
+static void ascot2e_release(struct dvb_frontend *fe)
 {
 	struct ascot2e_priv *priv = fe->tuner_priv;
 
 	dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int ascot2e_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/atbm8830.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/atbm8830.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/atbm8830.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/atbm8830.c	2017-02-12 16:03:20.000000000 -0500
@@ -428,7 +428,7 @@ static int atbm8830_i2c_gate_ctrl(struct
 	return atbm8830_write_reg(priv, REG_I2C_GATE, enable ? 1 : 0);
 }
 
-static struct dvb_frontend_ops atbm8830_ops = {
+static const struct dvb_frontend_ops atbm8830_ops = {
 	.delsys = { SYS_DTMB },
 	.info = {
 		.name = "AltoBeam ATBM8830/8831 DMB-TH",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/au8522_common.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/au8522_common.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/au8522_common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/au8522_common.c	2017-02-12 16:03:20.000000000 -0500
@@ -50,8 +50,8 @@ int au8522_writereg(struct au8522_state
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, "
-		       "ret == %i)\n", __func__, reg, data, ret);
+		printk("%s: writereg error (reg == 0x%02x, val == 0x%04x, ret == %i)\n",
+		       __func__, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/au8522_dig.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/au8522_dig.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/au8522_dig.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/au8522_dig.c	2017-02-12 16:03:20.000000000 -0500
@@ -834,7 +834,7 @@ static int au8522_get_tune_settings(stru
 	return 0;
 }
 
-static struct dvb_frontend_ops au8522_ops;
+static const struct dvb_frontend_ops au8522_ops;
 
 
 static void au8522_release(struct dvb_frontend *fe)
@@ -894,7 +894,7 @@ error:
 }
 EXPORT_SYMBOL(au8522_attach);
 
-static struct dvb_frontend_ops au8522_ops = {
+static const struct dvb_frontend_ops au8522_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name			= "Auvitek AU8522 QAM/8VSB Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/bcm3510.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/bcm3510.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/bcm3510.c	2016-12-11 17:45:17.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/bcm3510.c	2017-02-12 17:30:50.000000000 -0500
@@ -786,7 +786,7 @@ static int bcm3510_init(struct dvb_front
 }
 
 
-static struct dvb_frontend_ops bcm3510_ops;
+static const struct dvb_frontend_ops bcm3510_ops;
 
 struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
 				   struct i2c_adapter *i2c)
@@ -832,7 +832,7 @@ error:
 }
 EXPORT_SYMBOL(bcm3510_attach);
 
-static struct dvb_frontend_ops bcm3510_ops = {
+static const struct dvb_frontend_ops bcm3510_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name = "Broadcom BCM3510 VSB/QAM frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx22700.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx22700.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx22700.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx22700.c	2017-02-12 16:03:20.000000000 -0500
@@ -380,7 +380,7 @@ static void cx22700_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops cx22700_ops;
+static const struct dvb_frontend_ops cx22700_ops;
 
 struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
 				    struct i2c_adapter* i2c)
@@ -408,7 +408,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops cx22700_ops = {
+static const struct dvb_frontend_ops cx22700_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "Conexant CX22700 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24110.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24110.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24110.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24110.c	2017-02-12 16:03:20.000000000 -0500
@@ -120,8 +120,8 @@ static int cx24110_writereg (struct cx24
 	int err;
 
 	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		dprintk ("%s: writereg error (err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, err, reg, data);
+		dprintk("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n",
+			__func__, err, reg, data);
 		return -EREMOTEIO;
 	}
 
@@ -592,7 +592,7 @@ static void cx24110_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops cx24110_ops;
+static const struct dvb_frontend_ops cx24110_ops;
 
 struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
 				    struct i2c_adapter* i2c)
@@ -625,7 +625,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops cx24110_ops = {
+static const struct dvb_frontend_ops cx24110_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name = "Conexant CX24110 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24113.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24113.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24113.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24113.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,8 +108,8 @@ static int cx24113_writereg(struct cx241
 		.flags = 0, .buf = buf, .len = 2 };
 	int err = i2c_transfer(state->i2c, &msg, 1);
 	if (err != 1) {
-		printk(KERN_DEBUG "%s: writereg error(err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, err, reg, data);
+		printk(KERN_DEBUG "%s: writereg error(err == %i, reg == 0x%02x, data == 0x%02x)\n",
+		       __func__, err, reg, data);
 		return err;
 	}
 
@@ -527,13 +527,12 @@ static int cx24113_get_frequency(struct
 	return 0;
 }
 
-static int cx24113_release(struct dvb_frontend *fe)
+static void cx24113_release(struct dvb_frontend *fe)
 {
 	struct cx24113_state *state = fe->tuner_priv;
 	dprintk("\n");
 	fe->tuner_priv = NULL;
 	kfree(state);
-	return 0;
 }
 
 static const struct dvb_tuner_ops cx24113_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24116.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24116.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24116.c	2016-12-11 17:45:17.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24116.c	2017-02-12 17:30:52.000000000 -0500
@@ -209,8 +209,8 @@ static int cx24116_writereg(struct cx241
 
 	err = i2c_transfer(state->i2c, &msg, 1);
 	if (err != 1) {
-		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
-			 " value == 0x%02x)\n", __func__, err, reg, data);
+		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n",
+		       __func__, err, reg, data);
 		return -EREMOTEIO;
 	}
 
@@ -498,8 +498,8 @@ static int cx24116_firmware_ondemand(str
 		printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n",
 			__func__);
 		if (ret) {
-			printk(KERN_ERR "%s: No firmware uploaded "
-				"(timeout or file not found?)\n", __func__);
+			printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",
+			       __func__);
 			return ret;
 		}
 
@@ -1116,7 +1116,7 @@ static void cx24116_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops cx24116_ops;
+static const struct dvb_frontend_ops cx24116_ops;
 
 struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
 	struct i2c_adapter *i2c)
@@ -1467,7 +1467,7 @@ static int cx24116_get_algo(struct dvb_f
 	return DVBFE_ALGO_HW;
 }
 
-static struct dvb_frontend_ops cx24116_ops = {
+static const struct dvb_frontend_ops cx24116_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name = "Conexant CX24116/CX24118",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24117.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24117.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24117.c	2016-12-11 17:45:20.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24117.c	2017-02-12 17:30:56.000000000 -0500
@@ -474,8 +474,8 @@ static int cx24117_firmware_ondemand(str
 			"%s: Waiting for firmware upload(2)...\n", __func__);
 		if (ret) {
 			dev_err(&state->priv->i2c->dev,
-				"%s: No firmware uploaded "
-				"(timeout or file not found?)\n", __func__);
+				"%s: No firmware uploaded (timeout or file not found?)\n",
+__func__);
 			return ret;
 		}
 
@@ -1164,7 +1164,7 @@ static void cx24117_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops cx24117_ops;
+static const struct dvb_frontend_ops cx24117_ops;
 
 struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
 	struct i2c_adapter *i2c)
@@ -1618,7 +1618,7 @@ static int cx24117_get_frontend(struct d
 	return 0;
 }
 
-static struct dvb_frontend_ops cx24117_ops = {
+static const struct dvb_frontend_ops cx24117_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name = "Conexant CX24117/CX24132",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24120.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24120.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24120.c	2016-12-11 17:45:23.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24120.c	2017-02-12 17:31:02.000000000 -0500
@@ -267,7 +267,7 @@ out:
 	return ret;
 }
 
-static struct dvb_frontend_ops cx24120_ops;
+static const struct dvb_frontend_ops cx24120_ops;
 
 struct dvb_frontend *cx24120_attach(const struct cx24120_config *config,
 				    struct i2c_adapter *i2c)
@@ -1154,8 +1154,7 @@ static int cx24120_set_frontend(struct d
 		dev_dbg(&state->i2c->dev,
 			"delivery system(%d) not supported\n",
 			c->delivery_system);
-		ret = -EINVAL;
-		break;
+		return -EINVAL;
 	}
 
 	state->dnxt.delsys = c->delivery_system;
@@ -1552,7 +1551,7 @@ static int cx24120_read_ucblocks(struct
 	return 0;
 }
 
-static struct dvb_frontend_ops cx24120_ops = {
+static const struct dvb_frontend_ops cx24120_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name = "Conexant CX24120/CX24118",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24123.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24123.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cx24123.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cx24123.c	2017-02-12 16:03:20.000000000 -0500
@@ -255,8 +255,8 @@ static int cx24123_i2c_writereg(struct c
 
 	err = i2c_transfer(state->i2c, &msg, 1);
 	if (err != 1) {
-		printk("%s: writereg error(err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, err, reg, data);
+		printk("%s: writereg error(err == %i, reg == 0x%02x, data == 0x%02x)\n",
+		       __func__, err, reg, data);
 		return err;
 	}
 
@@ -1049,7 +1049,7 @@ struct i2c_adapter *
 }
 EXPORT_SYMBOL(cx24123_get_tuner_i2c_adapter);
 
-static struct dvb_frontend_ops cx24123_ops;
+static const struct dvb_frontend_ops cx24123_ops;
 
 struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
 				    struct i2c_adapter *i2c)
@@ -1111,7 +1111,7 @@ error:
 }
 EXPORT_SYMBOL(cx24123_attach);
 
-static struct dvb_frontend_ops cx24123_ops = {
+static const struct dvb_frontend_ops cx24123_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name = "Conexant CX24123/CX24109",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/cxd2841er.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cxd2841er.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/cxd2841er.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/cxd2841er.c	2017-02-12 16:03:20.000000000 -0500
@@ -3719,7 +3719,7 @@ static int cxd2841er_init_tc(struct dvb_
 	return 0;
 }
 
-static struct dvb_frontend_ops cxd2841er_dvbs_s2_ops;
+static const struct dvb_frontend_ops cxd2841er_dvbs_s2_ops;
 static struct dvb_frontend_ops cxd2841er_t_c_ops;
 
 static struct dvb_frontend *cxd2841er_attach(struct cxd2841er_config *cfg,
@@ -3801,7 +3801,7 @@ struct dvb_frontend *cxd2841er_attach_t_
 }
 EXPORT_SYMBOL(cxd2841er_attach_t_c);
 
-static struct dvb_frontend_ops cxd2841er_dvbs_s2_ops = {
+static const struct dvb_frontend_ops cxd2841er_dvbs_s2_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name		= "Sony CXD2841ER DVB-S/S2 demodulator",
@@ -3829,7 +3829,7 @@ static struct dvb_frontend_ops cxd2841er
 	.tune = cxd2841er_tune_s
 };
 
-static struct  dvb_frontend_ops cxd2841er_t_c_ops = {
+static struct dvb_frontend_ops cxd2841er_t_c_ops = {
 	.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
 	.info = {
 		.name	= "", /* will set in attach function */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib0070.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib0070.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib0070.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib0070.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -38,12 +40,10 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-#define dprintk(args...) do { \
-	if (debug) { \
-		printk(KERN_DEBUG "DiB0070: "); \
-		printk(args); \
-		printk("\n"); \
-	} \
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
 } while (0)
 
 #define DIB0070_P1D  0x00
@@ -87,7 +87,7 @@ static u16 dib0070_read_reg(struct dib00
 	u16 ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -104,7 +104,7 @@ static u16 dib0070_read_reg(struct dib00
 	state->msg[1].len = 2;
 
 	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
-		printk(KERN_WARNING "DiB0070 I2C read failed\n");
+		pr_warn("DiB0070 I2C read failed\n");
 		ret = 0;
 	} else
 		ret = (state->i2c_read_buffer[0] << 8)
@@ -119,7 +119,7 @@ static int dib0070_write_reg(struct dib0
 	int ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 	state->i2c_write_buffer[0] = reg;
@@ -133,7 +133,7 @@ static int dib0070_write_reg(struct dib0
 	state->msg[0].len = 3;
 
 	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0070 I2C write failed\n");
+		pr_warn("DiB0070 I2C write failed\n");
 		ret = -EREMOTEIO;
 	} else
 		ret = 0;
@@ -205,7 +205,7 @@ static int dib0070_captrim(struct dib007
 
 		adc = dib0070_read_reg(state, 0x19);
 
-		dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
+		dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV\n", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
 
 		if (adc >= 400) {
 			adc -= 400;
@@ -216,7 +216,7 @@ static int dib0070_captrim(struct dib007
 		}
 
 		if (adc < state->adc_diff) {
-			dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff);
+			dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)\n", state->captrim, adc, state->adc_diff);
 			state->adc_diff = adc;
 			state->fcaptrim = state->captrim;
 		}
@@ -241,7 +241,7 @@ static int dib0070_set_ctrl_lo5(struct d
 	struct dib0070_state *state = fe->tuner_priv;
 	u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
 
-	dprintk("CTRL_LO5: 0x%x", lo5);
+	dprintk("CTRL_LO5: 0x%x\n", lo5);
 	return dib0070_write_reg(state, 0x15, lo5);
 }
 
@@ -256,7 +256,7 @@ void dib0070_ctrl_agc_filter(struct dvb_
 		dib0070_write_reg(state, 0x1b, 0x4112);
 		if (state->cfg->vga_filter != 0) {
 			dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
-			dprintk("vga filter register is set to %x", state->cfg->vga_filter);
+			dprintk("vga filter register is set to %x\n", state->cfg->vga_filter);
 		} else
 			dib0070_write_reg(state, 0x1a, 0x0009);
 	}
@@ -380,7 +380,7 @@ static int dib0070_tune_digital(struct d
 	}
 
 	if (*tune_state == CT_TUNER_START) {
-		dprintk("Tuning for Band: %hd (%d kHz)", band, freq);
+		dprintk("Tuning for Band: %hd (%d kHz)\n", band, freq);
 		if (state->current_rf != freq) {
 			u8 REFDIV;
 			u32 FBDiv, Rest, FREF, VCOF_kHz;
@@ -458,12 +458,12 @@ static int dib0070_tune_digital(struct d
 			dib0070_write_reg(state, 0x20,
 				0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
 
-			dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF);
-			dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest);
-			dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
-			dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv);
-			dprintk("VCO = %hd", state->current_tune_table_index->vco_band);
-			dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
+			dprintk("REFDIV: %hd, FREF: %d\n", REFDIV, FREF);
+			dprintk("FBDIV: %d, Rest: %d\n", FBDiv, Rest);
+			dprintk("Num: %hd, Den: %hd, SD: %hd\n", (u16) Rest, Den, (state->lo4 >> 12) & 0x1);
+			dprintk("HFDIV code: %hd\n", state->current_tune_table_index->hfdiv);
+			dprintk("VCO = %hd\n", state->current_tune_table_index->vco_band);
+			dprintk("VCOF: ((%hd*%d) << 1))\n", state->current_tune_table_index->vco_multi, freq);
 
 			*tune_state = CT_TUNER_STEP_0;
 		} else { /* we are already tuned to this frequency - the configuration is correct  */
@@ -625,7 +625,7 @@ static void dib0070_wbd_offset_calibrati
 	u8 gain;
 	for (gain = 6; gain < 8; gain++) {
 		state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
-		dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
+		dprintk("Gain: %d, WBDOffset (3.3V) = %hd\n", gain, state->wbd_offset_3_3[gain-6]);
 	}
 }
 
@@ -665,10 +665,10 @@ static int dib0070_reset(struct dvb_fron
 	state->revision = DIB0070S_P1A;
 
 	/* P1F or not */
-	dprintk("Revision: %x", state->revision);
+	dprintk("Revision: %x\n", state->revision);
 
 	if (state->revision == DIB0070_P1D) {
-		dprintk("Error: this driver is not to be used meant for P1D or earlier");
+		dprintk("Error: this driver is not to be used meant for P1D or earlier\n");
 		return -EINVAL;
 	}
 
@@ -722,11 +722,10 @@ static int dib0070_get_frequency(struct
 	return 0;
 }
 
-static int dib0070_release(struct dvb_frontend *fe)
+static void dib0070_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops dib0070_ops = {
@@ -761,7 +760,7 @@ struct dvb_frontend *dib0070_attach(stru
 	if (dib0070_reset(fe) != 0)
 		goto free_mem;
 
-	printk(KERN_INFO "DiB0070: successfully identified\n");
+	pr_info("DiB0070: successfully identified\n");
 	memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
 
 	fe->tuner_priv = state;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib0090.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib0090.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib0090.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib0090.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,6 +24,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -38,12 +40,10 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-#define dprintk(args...) do { \
-	if (debug) { \
-		printk(KERN_DEBUG "DiB0090: "); \
-		printk(args); \
-		printk("\n"); \
-	} \
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
 } while (0)
 
 #define CONFIG_SYS_DVBT
@@ -218,7 +218,7 @@ static u16 dib0090_read_reg(struct dib00
 	u16 ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -235,7 +235,7 @@ static u16 dib0090_read_reg(struct dib00
 	state->msg[1].len = 2;
 
 	if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
-		printk(KERN_WARNING "DiB0090 I2C read failed\n");
+		pr_warn("DiB0090 I2C read failed\n");
 		ret = 0;
 	} else
 		ret = (state->i2c_read_buffer[0] << 8)
@@ -250,7 +250,7 @@ static int dib0090_write_reg(struct dib0
 	int ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -265,7 +265,7 @@ static int dib0090_write_reg(struct dib0
 	state->msg[0].len = 3;
 
 	if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0090 I2C write failed\n");
+		pr_warn("DiB0090 I2C write failed\n");
 		ret = -EREMOTEIO;
 	} else
 		ret = 0;
@@ -279,7 +279,7 @@ static u16 dib0090_fw_read_reg(struct di
 	u16 ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -291,7 +291,7 @@ static u16 dib0090_fw_read_reg(struct di
 	state->msg.buf = state->i2c_read_buffer;
 	state->msg.len = 2;
 	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0090 I2C read failed\n");
+		pr_warn("DiB0090 I2C read failed\n");
 		ret = 0;
 	} else
 		ret = (state->i2c_read_buffer[0] << 8)
@@ -306,7 +306,7 @@ static int dib0090_fw_write_reg(struct d
 	int ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -319,7 +319,7 @@ static int dib0090_fw_write_reg(struct d
 	state->msg.buf = state->i2c_write_buffer;
 	state->msg.len = 2;
 	if (i2c_transfer(state->i2c, &state->msg, 1) != 1) {
-		printk(KERN_WARNING "DiB0090 I2C write failed\n");
+		pr_warn("DiB0090 I2C write failed\n");
 		ret = -EREMOTEIO;
 	} else
 		ret = 0;
@@ -351,7 +351,7 @@ static int dib0090_identify(struct dvb_f
 	identity->p1g = 0;
 	identity->in_soc = 0;
 
-	dprintk("Tuner identification (Version = 0x%04x)", v);
+	dprintk("Tuner identification (Version = 0x%04x)\n", v);
 
 	/* without PLL lock info */
 	v &= ~KROSUS_PLL_LOCKED;
@@ -366,19 +366,19 @@ static int dib0090_identify(struct dvb_f
 		identity->in_soc = 1;
 		switch (identity->version) {
 		case SOC_8090_P1G_11R1:
-			dprintk("SOC 8090 P1-G11R1 Has been detected");
+			dprintk("SOC 8090 P1-G11R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		case SOC_8090_P1G_21R1:
-			dprintk("SOC 8090 P1-G21R1 Has been detected");
+			dprintk("SOC 8090 P1-G21R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		case SOC_7090_P1G_11R1:
-			dprintk("SOC 7090 P1-G11R1 Has been detected");
+			dprintk("SOC 7090 P1-G11R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		case SOC_7090_P1G_21R1:
-			dprintk("SOC 7090 P1-G21R1 Has been detected");
+			dprintk("SOC 7090 P1-G21R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		default:
@@ -387,16 +387,16 @@ static int dib0090_identify(struct dvb_f
 	} else {
 		switch ((identity->version >> 5) & 0x7) {
 		case MP001:
-			dprintk("MP001 : 9090/8096");
+			dprintk("MP001 : 9090/8096\n");
 			break;
 		case MP005:
-			dprintk("MP005 : Single Sband");
+			dprintk("MP005 : Single Sband\n");
 			break;
 		case MP008:
-			dprintk("MP008 : diversity VHF-UHF-LBAND");
+			dprintk("MP008 : diversity VHF-UHF-LBAND\n");
 			break;
 		case MP009:
-			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
+			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
 			break;
 		default:
 			goto identification_error;
@@ -404,21 +404,21 @@ static int dib0090_identify(struct dvb_f
 
 		switch (identity->version & 0x1f) {
 		case P1G_21R2:
-			dprintk("P1G_21R2 detected");
+			dprintk("P1G_21R2 detected\n");
 			identity->p1g = 1;
 			break;
 		case P1G:
-			dprintk("P1G detected");
+			dprintk("P1G detected\n");
 			identity->p1g = 1;
 			break;
 		case P1D_E_F:
-			dprintk("P1D/E/F detected");
+			dprintk("P1D/E/F detected\n");
 			break;
 		case P1C:
-			dprintk("P1C detected");
+			dprintk("P1C detected\n");
 			break;
 		case P1A_B:
-			dprintk("P1-A/B detected: driver is deactivated - not available");
+			dprintk("P1-A/B detected: driver is deactivated - not available\n");
 			goto identification_error;
 			break;
 		default:
@@ -441,7 +441,7 @@ static int dib0090_fw_identify(struct dv
 	identity->p1g = 0;
 	identity->in_soc = 0;
 
-	dprintk("FE: Tuner identification (Version = 0x%04x)", v);
+	dprintk("FE: Tuner identification (Version = 0x%04x)\n", v);
 
 	/* without PLL lock info */
 	v &= ~KROSUS_PLL_LOCKED;
@@ -456,19 +456,19 @@ static int dib0090_fw_identify(struct dv
 		identity->in_soc = 1;
 		switch (identity->version) {
 		case SOC_8090_P1G_11R1:
-			dprintk("SOC 8090 P1-G11R1 Has been detected");
+			dprintk("SOC 8090 P1-G11R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		case SOC_8090_P1G_21R1:
-			dprintk("SOC 8090 P1-G21R1 Has been detected");
+			dprintk("SOC 8090 P1-G21R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		case SOC_7090_P1G_11R1:
-			dprintk("SOC 7090 P1-G11R1 Has been detected");
+			dprintk("SOC 7090 P1-G11R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		case SOC_7090_P1G_21R1:
-			dprintk("SOC 7090 P1-G21R1 Has been detected");
+			dprintk("SOC 7090 P1-G21R1 Has been detected\n");
 			identity->p1g = 1;
 			break;
 		default:
@@ -477,16 +477,16 @@ static int dib0090_fw_identify(struct dv
 	} else {
 		switch ((identity->version >> 5) & 0x7) {
 		case MP001:
-			dprintk("MP001 : 9090/8096");
+			dprintk("MP001 : 9090/8096\n");
 			break;
 		case MP005:
-			dprintk("MP005 : Single Sband");
+			dprintk("MP005 : Single Sband\n");
 			break;
 		case MP008:
-			dprintk("MP008 : diversity VHF-UHF-LBAND");
+			dprintk("MP008 : diversity VHF-UHF-LBAND\n");
 			break;
 		case MP009:
-			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
+			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND\n");
 			break;
 		default:
 			goto identification_error;
@@ -494,21 +494,21 @@ static int dib0090_fw_identify(struct dv
 
 		switch (identity->version & 0x1f) {
 		case P1G_21R2:
-			dprintk("P1G_21R2 detected");
+			dprintk("P1G_21R2 detected\n");
 			identity->p1g = 1;
 			break;
 		case P1G:
-			dprintk("P1G detected");
+			dprintk("P1G detected\n");
 			identity->p1g = 1;
 			break;
 		case P1D_E_F:
-			dprintk("P1D/E/F detected");
+			dprintk("P1D/E/F detected\n");
 			break;
 		case P1C:
-			dprintk("P1C detected");
+			dprintk("P1C detected\n");
 			break;
 		case P1A_B:
-			dprintk("P1-A/B detected: driver is deactivated - not available");
+			dprintk("P1-A/B detected: driver is deactivated - not available\n");
 			goto identification_error;
 			break;
 		default:
@@ -574,7 +574,7 @@ static void dib0090_reset_digital(struct
 		} while (--i);
 
 		if (i == 0) {
-			dprintk("Pll: Unable to lock Pll");
+			dprintk("Pll: Unable to lock Pll\n");
 			return;
 		}
 
@@ -596,7 +596,7 @@ static int dib0090_fw_reset_digital(stru
 	u16 v;
 	int i;
 
-	dprintk("fw reset digital");
+	dprintk("fw reset digital\n");
 	HARD_RESET(state);
 
 	dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
@@ -645,7 +645,7 @@ static int dib0090_fw_reset_digital(stru
 		} while (--i);
 
 		if (i == 0) {
-			dprintk("Pll: Unable to lock Pll");
+			dprintk("Pll: Unable to lock Pll\n");
 			return -EIO;
 		}
 
@@ -922,7 +922,7 @@ static void dib0090_wbd_target(struct di
 #endif
 
 	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
-	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
+	dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
 }
 
 static const int gain_reg_addr[4] = {
@@ -1019,7 +1019,7 @@ static void dib0090_gain_apply(struct di
 	gain_reg[3] |= ((bb % 10) * 100) / 125;
 
 #ifdef DEBUG_AGC
-	dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb,
+	dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x\n", rf, bb, rf + bb,
 		gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
 #endif
 
@@ -1050,7 +1050,7 @@ static void dib0090_set_rframp_pwm(struc
 
 	dib0090_write_reg(state, 0x2a, 0xffff);
 
-	dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
+	dprintk("total RF gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
 
 	dib0090_write_regs(state, 0x2c, cfg + 3, 6);
 	dib0090_write_regs(state, 0x3e, cfg + 9, 2);
@@ -1069,7 +1069,7 @@ static void dib0090_set_bbramp_pwm(struc
 	dib0090_set_boost(state, cfg[0] > 500);	/* we want the boost if the gain is higher that 50dB */
 
 	dib0090_write_reg(state, 0x33, 0xffff);
-	dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
+	dprintk("total BB gain: %ddB, step: %d\n", (u32) cfg[0], dib0090_read_reg(state, 0x33));
 	dib0090_write_regs(state, 0x35, cfg + 3, 4);
 }
 
@@ -1122,7 +1122,7 @@ void dib0090_pwm_gain_reset(struct dvb_f
 
 		/* activate the ramp generator using PWM control */
 		if (state->rf_ramp)
-			dprintk("ramp RF gain = %d BAND = %s version = %d",
+			dprintk("ramp RF gain = %d BAND = %s version = %d\n",
 				state->rf_ramp[0],
 				(state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND",
 				state->identity.version & 0x1f);
@@ -1130,10 +1130,10 @@ void dib0090_pwm_gain_reset(struct dvb_f
 		if (rf_ramp && ((state->rf_ramp && state->rf_ramp[0] == 0) ||
 		    (state->current_band == BAND_CBAND &&
 		    (state->identity.version & 0x1f) <= P1D_E_F))) {
-			dprintk("DE-Engage mux for direct gain reg control");
+			dprintk("DE-Engage mux for direct gain reg control\n");
 			en_pwm_rf_mux = 0;
 		} else
-			dprintk("Engage mux for PWM control");
+			dprintk("Engage mux for PWM control\n");
 
 		dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
 
@@ -1352,7 +1352,7 @@ u16 dib0090_get_wbd_target(struct dvb_fr
 	while (f_MHz > wbd->max_freq)
 		wbd++;
 
-	dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
+	dprintk("using wbd-table-entry with max freq %d\n", wbd->max_freq);
 
 	if (current_temp < 0)
 		current_temp = 0;
@@ -1373,8 +1373,8 @@ u16 dib0090_get_wbd_target(struct dvb_fr
 	wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
 
 	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
-	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
-	dprintk("wbd offset applied is %d", wbd_tcold);
+	dprintk("wbd-target: %d dB\n", (u32) state->wbd_target);
+	dprintk("wbd offset applied is %d\n", wbd_tcold);
 
 	return state->wbd_offset + wbd_tcold;
 }
@@ -1415,7 +1415,7 @@ int dib0090_update_rframp_7090(struct dv
 	if ((!state->identity.p1g) || (!state->identity.in_soc)
 			|| ((state->identity.version != SOC_7090_P1G_21R1)
 				&& (state->identity.version != SOC_7090_P1G_11R1))) {
-		dprintk("%s() function can only be used for dib7090P", __func__);
+		dprintk("%s() function can only be used for dib7090P\n", __func__);
 		return -ENODEV;
 	}
 
@@ -1598,7 +1598,7 @@ static int dib0090_reset(struct dvb_fron
 		dib0090_write_reg(state, 0x14, 1);
 	else
 		dib0090_write_reg(state, 0x14, 2);
-	dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
+	dprintk("Pll lock : %d\n", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
 
 	state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL;	/* enable iq-offset-calibration and wbd-calibration when tuning next time */
 
@@ -1711,7 +1711,8 @@ static int dib0090_dc_offset_calibration
 
 		/* fall through */
 	case CT_TUNER_STEP_0:
-		dprintk("Start/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
+		dprintk("Start/continue DC calibration for %s path\n",
+			(state->dc->i == 1) ? "I" : "Q");
 		dib0090_write_reg(state, 0x01, state->dc->bb1);
 		dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
 
@@ -1733,13 +1734,13 @@ static int dib0090_dc_offset_calibration
 		break;
 
 	case CT_TUNER_STEP_5:	/* found an offset */
-		dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
+		dprintk("adc_diff = %d, current step= %d\n", (u32) state->adc_diff, state->step);
 		if (state->step == 0 && state->adc_diff < 0) {
 			state->min_adc_diff = -1023;
-			dprintk("Change of sign of the minimum adc diff");
+			dprintk("Change of sign of the minimum adc diff\n");
 		}
 
-		dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
+		dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d\n", state->adc_diff, state->min_adc_diff, state->step);
 
 		/* first turn for this frequency */
 		if (state->step == 0) {
@@ -1758,12 +1759,12 @@ static int dib0090_dc_offset_calibration
 		} else {
 			/* the minimum was what we have seen in the step before */
 			if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
-				dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
+				dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step\n", state->adc_diff, state->min_adc_diff);
 				state->step--;
 			}
 
 			dib0090_set_trim(state);
-			dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
+			dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd\n", state->dc->addr, state->adc_diff, state->step);
 
 			state->dc++;
 			if (state->dc->addr == 0)	/* done */
@@ -1819,7 +1820,7 @@ static int dib0090_wbd_calibration(struc
 
 	case CT_TUNER_STEP_0:
 		state->wbd_offset = dib0090_get_slow_adc_val(state);
-		dprintk("WBD calibration offset = %d", state->wbd_offset);
+		dprintk("WBD calibration offset = %d\n", state->wbd_offset);
 		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
 		state->calibrate &= ~WBD_CAL;
 		break;
@@ -2064,7 +2065,7 @@ int dib0090_update_tuning_table_7090(str
 	if ((!state->identity.p1g) || (!state->identity.in_soc)
 			|| ((state->identity.version != SOC_7090_P1G_21R1)
 				&& (state->identity.version != SOC_7090_P1G_11R1))) {
-		dprintk("%s() function can only be used for dib7090", __func__);
+		dprintk("%s() function can only be used for dib7090\n", __func__);
 		return -ENODEV;
 	}
 
@@ -2098,7 +2099,8 @@ static int dib0090_captrim_search(struct
 		force_soft_search = 1;
 
 	if (*tune_state == CT_TUNER_START) {
-		dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
+		dprintk("Start Captrim search : %s\n",
+			(force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
 		dib0090_write_reg(state, 0x10, 0x2B1);
 		dib0090_write_reg(state, 0x1e, 0x0032);
 
@@ -2140,13 +2142,13 @@ static int dib0090_captrim_search(struct
 			dib0090_read_reg(state, 0x40);
 
 			state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
-			dprintk("***Final Captrim= 0x%x", state->fcaptrim);
+			dprintk("***Final Captrim= 0x%x\n", state->fcaptrim);
 			*tune_state = CT_TUNER_STEP_3;
 
 		} else {
 			/* MERGE for all krosus before P1G */
 			adc = dib0090_get_slow_adc_val(state);
-			dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
+			dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV\n", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
 
 			if (state->rest == 0 || state->identity.in_soc) {	/* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
 				adc_target = 200;
@@ -2162,7 +2164,7 @@ static int dib0090_captrim_search(struct
 			}
 
 			if (adc < state->adc_diff) {
-				dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
+				dprintk("CAPTRIM=%d is closer to target (%d/%d)\n", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
 				state->adc_diff = adc;
 				state->fcaptrim = state->captrim;
 			}
@@ -2216,7 +2218,7 @@ static int dib0090_get_temperature(struc
 		val = dib0090_get_slow_adc_val(state);
 		state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
 
-		dprintk("temperature: %d C", state->temperature - 30);
+		dprintk("temperature: %d C\n", state->temperature - 30);
 
 		*tune_state = CT_TUNER_STEP_2;
 		break;
@@ -2478,13 +2480,13 @@ static int dib0090_tune(struct dvb_front
 			wbd++;
 
 		dib0090_write_reg(state, 0x1e, 0x07ff);
-		dprintk("Final Captrim: %d", (u32) state->fcaptrim);
-		dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
-		dprintk("VCO = %d", (u32) pll->vco_band);
-		dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
-		dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
-		dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
-		dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
+		dprintk("Final Captrim: %d\n", (u32) state->fcaptrim);
+		dprintk("HFDIV code: %d\n", (u32) pll->hfdiv_code);
+		dprintk("VCO = %d\n", (u32) pll->vco_band);
+		dprintk("VCOF in kHz: %d ((%d*%d) << 1))\n", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
+		dprintk("REFDIV: %d, FREF: %d\n", (u32) 1, (u32) state->config->io.clock_khz);
+		dprintk("FBDIV: %d, Rest: %d\n", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
+		dprintk("Num: %d, Den: %d, SD: %d\n", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
 			(u32) dib0090_read_reg(state, 0x1c) & 0x3);
 
 #define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
@@ -2498,7 +2500,7 @@ static int dib0090_tune(struct dvb_front
 		dib0090_write_reg(state, 0x10, state->wbdmux);
 
 		if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
-			dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
+			dprintk("P1G : The cable band is selected and lna_tune = %d\n", tune->lna_tune);
 			dib0090_write_reg(state, 0x09, tune->lna_bias);
 			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
 		} else
@@ -2524,11 +2526,10 @@ static int dib0090_tune(struct dvb_front
 	return ret;
 }
 
-static int dib0090_release(struct dvb_frontend *fe)
+static void dib0090_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
@@ -2643,7 +2644,7 @@ struct dvb_frontend *dib0090_register(st
 	if (dib0090_reset(fe) != 0)
 		goto free_mem;
 
-	printk(KERN_INFO "DiB0090: successfully identified\n");
+	pr_info("DiB0090: successfully identified\n");
 	memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
 
 	return fe;
@@ -2670,7 +2671,7 @@ struct dvb_frontend *dib0090_fw_register
 	if (dib0090_fw_reset_digital(fe, st->config) != 0)
 		goto free_mem;
 
-	dprintk("DiB0090 FW: successfully identified");
+	dprintk("DiB0090 FW: successfully identified\n");
 	memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
 
 	return fe;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib3000mb.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib3000mb.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib3000mb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib3000mb.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -42,13 +44,13 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
 
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_i2c(args...)  dprintk(0x02,args)
-#define deb_srch(args...) dprintk(0x04,args)
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_xfer(args...) dprintk(0x02,args)
-#define deb_setf(args...) dprintk(0x04,args)
-#define deb_getf(args...) dprintk(0x08,args)
+#define deb_info(args...) dprintk(0x01, args)
+#define deb_i2c(args...)  dprintk(0x02, args)
+#define deb_srch(args...) dprintk(0x04, args)
+#define deb_info(args...) dprintk(0x01, args)
+#define deb_xfer(args...) dprintk(0x02, args)
+#define deb_setf(args...) dprintk(0x04, args)
+#define deb_getf(args...) dprintk(0x08, args)
 
 static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
 {
@@ -126,103 +128,96 @@ static int dib3000mb_set_frontend(struct
 		fe->ops.tuner_ops.set_params(fe);
 		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
-		deb_setf("bandwidth: ");
 		switch (c->bandwidth_hz) {
 			case 8000000:
-				deb_setf("8 MHz\n");
 				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[2]);
 				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_8mhz);
 				break;
 			case 7000000:
-				deb_setf("7 MHz\n");
 				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[1]);
 				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_7mhz);
 				break;
 			case 6000000:
-				deb_setf("6 MHz\n");
 				wr_foreach(dib3000mb_reg_timing_freq, dib3000mb_timing_freq[0]);
 				wr_foreach(dib3000mb_reg_bandwidth, dib3000mb_bandwidth_6mhz);
 				break;
 			case 0:
 				return -EOPNOTSUPP;
 			default:
-				err("unknown bandwidth value.");
+				pr_err("unknown bandwidth value.\n");
 				return -EINVAL;
 		}
+		deb_setf("bandwidth: %d MHZ\n", c->bandwidth_hz / 1000000);
 	}
 	wr(DIB3000MB_REG_LOCK1_MASK, DIB3000MB_LOCK1_SEARCH_4);
 
-	deb_setf("transmission mode: ");
 	switch (c->transmission_mode) {
 		case TRANSMISSION_MODE_2K:
-			deb_setf("2k\n");
+			deb_setf("transmission mode: 2k\n");
 			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_2K);
 			break;
 		case TRANSMISSION_MODE_8K:
-			deb_setf("8k\n");
+			deb_setf("transmission mode: 8k\n");
 			wr(DIB3000MB_REG_FFT, DIB3000_TRANSMISSION_MODE_8K);
 			break;
 		case TRANSMISSION_MODE_AUTO:
-			deb_setf("auto\n");
+			deb_setf("transmission mode: auto\n");
 			break;
 		default:
 			return -EINVAL;
 	}
 
-	deb_setf("guard: ");
 	switch (c->guard_interval) {
 		case GUARD_INTERVAL_1_32:
-			deb_setf("1_32\n");
+			deb_setf("guard 1_32\n");
 			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_32);
 			break;
 		case GUARD_INTERVAL_1_16:
-			deb_setf("1_16\n");
+			deb_setf("guard 1_16\n");
 			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_16);
 			break;
 		case GUARD_INTERVAL_1_8:
-			deb_setf("1_8\n");
+			deb_setf("guard 1_8\n");
 			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_8);
 			break;
 		case GUARD_INTERVAL_1_4:
-			deb_setf("1_4\n");
+			deb_setf("guard 1_4\n");
 			wr(DIB3000MB_REG_GUARD_TIME, DIB3000_GUARD_TIME_1_4);
 			break;
 		case GUARD_INTERVAL_AUTO:
-			deb_setf("auto\n");
+			deb_setf("guard auto\n");
 			break;
 		default:
 			return -EINVAL;
 	}
 
-	deb_setf("inversion: ");
 	switch (c->inversion) {
 		case INVERSION_OFF:
-			deb_setf("off\n");
+			deb_setf("inversion off\n");
 			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_OFF);
 			break;
 		case INVERSION_AUTO:
-			deb_setf("auto ");
+			deb_setf("inversion auto\n");
 			break;
 		case INVERSION_ON:
-			deb_setf("on\n");
+			deb_setf("inversion on\n");
 			wr(DIB3000MB_REG_DDS_INV, DIB3000_DDS_INVERSION_ON);
 			break;
 		default:
 			return -EINVAL;
 	}
 
-	deb_setf("modulation: ");
 	switch (c->modulation) {
 		case QPSK:
-			deb_setf("qpsk\n");
+			deb_setf("modulation: qpsk\n");
 			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_QPSK);
 			break;
 		case QAM_16:
-			deb_setf("qam16\n");
+			deb_setf("modulation: qam16\n");
 			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_16QAM);
 			break;
 		case QAM_64:
-			deb_setf("qam64\n");
+			deb_setf("modulation: qam64\n");
 			wr(DIB3000MB_REG_QAM, DIB3000_CONSTELLATION_64QAM);
 			break;
 		case QAM_AUTO:
@@ -230,69 +225,64 @@ static int dib3000mb_set_frontend(struct
 		default:
 			return -EINVAL;
 	}
-	deb_setf("hierarchy: ");
 	switch (c->hierarchy) {
 		case HIERARCHY_NONE:
-			deb_setf("none ");
+			deb_setf("hierarchy: none\n");
 			/* fall through */
 		case HIERARCHY_1:
-			deb_setf("alpha=1\n");
+			deb_setf("hierarchy: alpha=1\n");
 			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1);
 			break;
 		case HIERARCHY_2:
-			deb_setf("alpha=2\n");
+			deb_setf("hierarchy: alpha=2\n");
 			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_2);
 			break;
 		case HIERARCHY_4:
-			deb_setf("alpha=4\n");
+			deb_setf("hierarchy: alpha=4\n");
 			wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_4);
 			break;
 		case HIERARCHY_AUTO:
-			deb_setf("alpha=auto\n");
+			deb_setf("hierarchy: alpha=auto\n");
 			break;
 		default:
 			return -EINVAL;
 	}
 
-	deb_setf("hierarchy: ");
 	if (c->hierarchy == HIERARCHY_NONE) {
-		deb_setf("none\n");
 		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_OFF);
 		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_HP);
 		fe_cr = c->code_rate_HP;
 	} else if (c->hierarchy != HIERARCHY_AUTO) {
-		deb_setf("on\n");
 		wr(DIB3000MB_REG_VIT_HRCH, DIB3000_HRCH_ON);
 		wr(DIB3000MB_REG_VIT_HP, DIB3000_SELECT_LP);
 		fe_cr = c->code_rate_LP;
 	}
-	deb_setf("fec: ");
 	switch (fe_cr) {
 		case FEC_1_2:
-			deb_setf("1_2\n");
+			deb_setf("fec: 1_2\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_1_2);
 			break;
 		case FEC_2_3:
-			deb_setf("2_3\n");
+			deb_setf("fec: 2_3\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_2_3);
 			break;
 		case FEC_3_4:
-			deb_setf("3_4\n");
+			deb_setf("fec: 3_4\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_3_4);
 			break;
 		case FEC_5_6:
-			deb_setf("5_6\n");
+			deb_setf("fec: 5_6\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_5_6);
 			break;
 		case FEC_7_8:
-			deb_setf("7_8\n");
+			deb_setf("fec: 7_8\n");
 			wr(DIB3000MB_REG_VIT_CODE_RATE, DIB3000_FEC_7_8);
 			break;
 		case FEC_NONE:
-			deb_setf("none ");
+			deb_setf("fec: none\n");
 			break;
 		case FEC_AUTO:
-			deb_setf("auto\n");
+			deb_setf("fec: auto\n");
 			break;
 		default:
 			return -EINVAL;
@@ -357,7 +347,8 @@ static int dib3000mb_set_frontend(struct
 					rd(DIB3000MB_REG_LOCK2_VALUE))) < 0 && as_count++ < 100)
 			msleep(1);
 
-		deb_setf("search_state after autosearch %d after %d checks\n",search_state,as_count);
+		deb_setf("search_state after autosearch %d after %d checks\n",
+			 search_state, as_count);
 
 		if (search_state == 1) {
 			if (dib3000mb_get_frontend(fe, c) == 0) {
@@ -464,7 +455,7 @@ static int dib3000mb_get_frontend(struct
 		return 0;
 
 	dds_val = ((rd(DIB3000MB_REG_DDS_VALUE_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_VALUE_LSB);
-	deb_getf("DDS_VAL: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));
+	deb_getf("DDS_VAL: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_VALUE_MSB), rd(DIB3000MB_REG_DDS_VALUE_LSB));
 	if (dds_val < threshold)
 		inv_test1 = 0;
 	else if (dds_val == threshold)
@@ -473,7 +464,7 @@ static int dib3000mb_get_frontend(struct
 		inv_test1 = 2;
 
 	dds_val = ((rd(DIB3000MB_REG_DDS_FREQ_MSB) & 0xff) << 16) + rd(DIB3000MB_REG_DDS_FREQ_LSB);
-	deb_getf("DDS_FREQ: %x %x %x",dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));
+	deb_getf("DDS_FREQ: %x %x %x\n", dds_val, rd(DIB3000MB_REG_DDS_FREQ_MSB), rd(DIB3000MB_REG_DDS_FREQ_LSB));
 	if (dds_val < threshold)
 		inv_test2 = 0;
 	else if (dds_val == threshold)
@@ -490,19 +481,19 @@ static int dib3000mb_get_frontend(struct
 
 	switch ((tps_val = rd(DIB3000MB_REG_TPS_QAM))) {
 		case DIB3000_CONSTELLATION_QPSK:
-			deb_getf("QPSK ");
+			deb_getf("QPSK\n");
 			c->modulation = QPSK;
 			break;
 		case DIB3000_CONSTELLATION_16QAM:
-			deb_getf("QAM16 ");
+			deb_getf("QAM16\n");
 			c->modulation = QAM_16;
 			break;
 		case DIB3000_CONSTELLATION_64QAM:
-			deb_getf("QAM64 ");
+			deb_getf("QAM64\n");
 			c->modulation = QAM_64;
 			break;
 		default:
-			err("Unexpected constellation returned by TPS (%d)", tps_val);
+			pr_err("Unexpected constellation returned by TPS (%d)\n", tps_val);
 			break;
 	}
 	deb_getf("TPS: %d\n", tps_val);
@@ -513,23 +504,23 @@ static int dib3000mb_get_frontend(struct
 		c->code_rate_HP = FEC_NONE;
 		switch ((tps_val = rd(DIB3000MB_REG_TPS_VIT_ALPHA))) {
 			case DIB3000_ALPHA_0:
-				deb_getf("HIERARCHY_NONE ");
+				deb_getf("HIERARCHY_NONE\n");
 				c->hierarchy = HIERARCHY_NONE;
 				break;
 			case DIB3000_ALPHA_1:
-				deb_getf("HIERARCHY_1 ");
+				deb_getf("HIERARCHY_1\n");
 				c->hierarchy = HIERARCHY_1;
 				break;
 			case DIB3000_ALPHA_2:
-				deb_getf("HIERARCHY_2 ");
+				deb_getf("HIERARCHY_2\n");
 				c->hierarchy = HIERARCHY_2;
 				break;
 			case DIB3000_ALPHA_4:
-				deb_getf("HIERARCHY_4 ");
+				deb_getf("HIERARCHY_4\n");
 				c->hierarchy = HIERARCHY_4;
 				break;
 			default:
-				err("Unexpected ALPHA value returned by TPS (%d)", tps_val);
+				pr_err("Unexpected ALPHA value returned by TPS (%d)\n", tps_val);
 				break;
 		}
 		deb_getf("TPS: %d\n", tps_val);
@@ -546,65 +537,65 @@ static int dib3000mb_get_frontend(struct
 
 	switch (tps_val) {
 		case DIB3000_FEC_1_2:
-			deb_getf("FEC_1_2 ");
+			deb_getf("FEC_1_2\n");
 			*cr = FEC_1_2;
 			break;
 		case DIB3000_FEC_2_3:
-			deb_getf("FEC_2_3 ");
+			deb_getf("FEC_2_3\n");
 			*cr = FEC_2_3;
 			break;
 		case DIB3000_FEC_3_4:
-			deb_getf("FEC_3_4 ");
+			deb_getf("FEC_3_4\n");
 			*cr = FEC_3_4;
 			break;
 		case DIB3000_FEC_5_6:
-			deb_getf("FEC_5_6 ");
+			deb_getf("FEC_5_6\n");
 			*cr = FEC_4_5;
 			break;
 		case DIB3000_FEC_7_8:
-			deb_getf("FEC_7_8 ");
+			deb_getf("FEC_7_8\n");
 			*cr = FEC_7_8;
 			break;
 		default:
-			err("Unexpected FEC returned by TPS (%d)", tps_val);
+			pr_err("Unexpected FEC returned by TPS (%d)\n", tps_val);
 			break;
 	}
 	deb_getf("TPS: %d\n",tps_val);
 
 	switch ((tps_val = rd(DIB3000MB_REG_TPS_GUARD_TIME))) {
 		case DIB3000_GUARD_TIME_1_32:
-			deb_getf("GUARD_INTERVAL_1_32 ");
+			deb_getf("GUARD_INTERVAL_1_32\n");
 			c->guard_interval = GUARD_INTERVAL_1_32;
 			break;
 		case DIB3000_GUARD_TIME_1_16:
-			deb_getf("GUARD_INTERVAL_1_16 ");
+			deb_getf("GUARD_INTERVAL_1_16\n");
 			c->guard_interval = GUARD_INTERVAL_1_16;
 			break;
 		case DIB3000_GUARD_TIME_1_8:
-			deb_getf("GUARD_INTERVAL_1_8 ");
+			deb_getf("GUARD_INTERVAL_1_8\n");
 			c->guard_interval = GUARD_INTERVAL_1_8;
 			break;
 		case DIB3000_GUARD_TIME_1_4:
-			deb_getf("GUARD_INTERVAL_1_4 ");
+			deb_getf("GUARD_INTERVAL_1_4\n");
 			c->guard_interval = GUARD_INTERVAL_1_4;
 			break;
 		default:
-			err("Unexpected Guard Time returned by TPS (%d)", tps_val);
+			pr_err("Unexpected Guard Time returned by TPS (%d)\n", tps_val);
 			break;
 	}
 	deb_getf("TPS: %d\n", tps_val);
 
 	switch ((tps_val = rd(DIB3000MB_REG_TPS_FFT))) {
 		case DIB3000_TRANSMISSION_MODE_2K:
-			deb_getf("TRANSMISSION_MODE_2K ");
+			deb_getf("TRANSMISSION_MODE_2K\n");
 			c->transmission_mode = TRANSMISSION_MODE_2K;
 			break;
 		case DIB3000_TRANSMISSION_MODE_8K:
-			deb_getf("TRANSMISSION_MODE_8K ");
+			deb_getf("TRANSMISSION_MODE_8K\n");
 			c->transmission_mode = TRANSMISSION_MODE_8K;
 			break;
 		default:
-			err("unexpected transmission mode return by TPS (%d)", tps_val);
+			pr_err("unexpected transmission mode return by TPS (%d)\n", tps_val);
 			break;
 	}
 	deb_getf("TPS: %d\n", tps_val);
@@ -751,7 +742,7 @@ static int dib3000mb_tuner_pass_ctrl(str
 	return 0;
 }
 
-static struct dvb_frontend_ops dib3000mb_ops;
+static const struct dvb_frontend_ops dib3000mb_ops;
 
 struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
 				      struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
@@ -791,7 +782,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops dib3000mb_ops = {
+static const struct dvb_frontend_ops dib3000mb_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "DiBcom 3000M-B DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib3000mb_priv.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib3000mb_priv.h
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib3000mb_priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib3000mb_priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -13,20 +13,15 @@
 #ifndef __DIB3000MB_PRIV_H_INCLUDED__
 #define __DIB3000MB_PRIV_H_INCLUDED__
 
-/* info and err, taken from usb.h, if there is anything available like by default. */
-#define err(format, arg...)  printk(KERN_ERR     "dib3000: " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO    "dib3000: " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg)
-
 /* handy shortcuts */
 #define rd(reg) dib3000_read_reg(state,reg)
 
 #define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \
-	{ err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; }
+	{ pr_err("while sending 0x%04x to 0x%04x.", val, reg); return -EREMOTEIO; }
 
 #define wr_foreach(a,v) { int i; \
 	if (sizeof(a) != sizeof(v)) \
-		err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\
+		pr_err("sizeof: %zu %zu is different", sizeof(a), sizeof(v));\
 	for (i=0; i < sizeof(a)/sizeof(u16); i++) \
 		wr(a[i],v[i]); \
 	}
@@ -37,8 +32,11 @@
 
 /* debug */
 
-#define dprintk(level,args...) \
-    do { if ((debug & level)) { printk(args); } } while (0)
+#define dprintk(level, fmt, arg...) do {				\
+	if (debug & level)						\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 /* mask for enabling a specific pid for the pid_filter */
 #define DIB3000_ACTIVATE_PID_FILTERING	(0x2000)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib3000mc.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib3000mc.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib3000mc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib3000mc.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,6 +11,8 @@
  *	published by the Free Software Foundation, version 2.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -27,7 +29,11 @@ static int buggy_sfn_workaround;
 module_param(buggy_sfn_workaround, int, 0644);
 MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
 
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); printk("\n"); } } while (0)
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 struct dib3000mc_state {
 	struct dvb_frontend demod;
@@ -873,7 +879,7 @@ int dib3000mc_i2c_enumeration(struct i2c
 }
 EXPORT_SYMBOL(dib3000mc_i2c_enumeration);
 
-static struct dvb_frontend_ops dib3000mc_ops;
+static const struct dvb_frontend_ops dib3000mc_ops;
 
 struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
 {
@@ -906,7 +912,7 @@ error:
 }
 EXPORT_SYMBOL(dib3000mc_attach);
 
-static struct dvb_frontend_ops dib3000mc_ops = {
+static const struct dvb_frontend_ops dib3000mc_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "DiBcom 3000MC/P",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib7000m.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib7000m.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib7000m.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib7000m.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,9 @@
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -21,7 +24,11 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M: "); printk(args); printk("\n"); } } while (0)
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 struct dib7000m_state {
 	struct dvb_frontend demod;
@@ -74,7 +81,7 @@ static u16 dib7000m_read_word(struct dib
 	u16 ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -92,7 +99,7 @@ static u16 dib7000m_read_word(struct dib
 	state->msg[1].len = 2;
 
 	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
-		dprintk("i2c read error on %d",reg);
+		dprintk("i2c read error on %d\n", reg);
 
 	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 	mutex_unlock(&state->i2c_buffer_lock);
@@ -105,7 +112,7 @@ static int dib7000m_write_word(struct di
 	int ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -154,7 +161,7 @@ static int dib7000m_set_output_mode(stru
 	fifo_threshold = 1792;
 	smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1);
 
-	dprintk( "setting output mode for demod %p to %d", &state->demod, mode);
+	dprintk("setting output mode for demod %p to %d\n", &state->demod, mode);
 
 	switch (mode) {
 		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
@@ -181,7 +188,7 @@ static int dib7000m_set_output_mode(stru
 			outreg = 0;
 			break;
 		default:
-			dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
+			dprintk("Unhandled output_mode passed to be set for demod %p\n", &state->demod);
 			break;
 	}
 
@@ -302,7 +309,7 @@ static int dib7000m_set_adc_state(struct
 			break;
 	}
 
-//	dprintk( "913: %x, 914: %x", reg_913, reg_914);
+//	dprintk("913: %x, 914: %x\n", reg_913, reg_914);
 	ret |= dib7000m_write_word(state, 913, reg_913);
 	ret |= dib7000m_write_word(state, 914, reg_914);
 
@@ -320,10 +327,10 @@ static int dib7000m_set_bandwidth(struct
 	state->current_bandwidth = bw;
 
 	if (state->timf == 0) {
-		dprintk( "using default timf");
+		dprintk("using default timf\n");
 		timf = state->timf_default;
 	} else {
-		dprintk( "using updated timf");
+		dprintk("using updated timf\n");
 		timf = state->timf;
 	}
 
@@ -340,7 +347,7 @@ static int dib7000m_set_diversity_in(str
 	struct dib7000m_state *state = demod->demodulator_priv;
 
 	if (state->div_force_off) {
-		dprintk( "diversity combination deactivated - forced by COFDM parameters");
+		dprintk("diversity combination deactivated - forced by COFDM parameters\n");
 		onoff = 0;
 	}
 	state->div_state = (u8)onoff;
@@ -580,10 +587,10 @@ static int dib7000m_demod_reset(struct d
 		dib7000mc_reset_pll(state);
 
 	if (dib7000m_reset_gpio(state) != 0)
-		dprintk( "GPIO reset was not successful.");
+		dprintk("GPIO reset was not successful.\n");
 
 	if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
-		dprintk( "OUTPUT_MODE could not be reset.");
+		dprintk("OUTPUT_MODE could not be reset.\n");
 
 	/* unforce divstr regardless whether i2c enumeration was done or not */
 	dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) );
@@ -650,7 +657,7 @@ static int dib7000m_agc_soft_split(struc
 			(agc - state->current_agc->split.min_thres) /
 			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
 
-	dprintk( "AGC split_offset: %d",split_offset);
+	dprintk("AGC split_offset: %d\n", split_offset);
 
 	// P_agc_force_split and P_agc_split_offset
 	return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset);
@@ -687,7 +694,7 @@ static int dib7000m_set_agc_config(struc
 		}
 
 	if (agc == NULL) {
-		dprintk( "no valid AGC configuration found for band 0x%02x",band);
+		dprintk("no valid AGC configuration found for band 0x%02x\n", band);
 		return -EINVAL;
 	}
 
@@ -703,7 +710,7 @@ static int dib7000m_set_agc_config(struc
 	dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp);
 	dib7000m_write_word(state, 99, (agc->beta_mant  << 6) | agc->beta_exp);
 
-	dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
 		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
 
 	/* AGC continued */
@@ -724,7 +731,7 @@ static int dib7000m_set_agc_config(struc
 
 	if (state->revision > 0x4000) { // settings for the MC
 		dib7000m_write_word(state, 71,   agc->agc1_pt3);
-//		dprintk( "929: %x %d %d",
+//		dprintk("929: %x %d %d\n",
 //			(dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel);
 		dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
 	} else {
@@ -742,7 +749,7 @@ static void dib7000m_update_timf(struct
 	state->timf = timf * 160 / (state->current_bandwidth / 50);
 	dib7000m_write_word(state, 23, (u16) (timf >> 16));
 	dib7000m_write_word(state, 24, (u16) (timf & 0xffff));
-	dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->timf_default);
+	dprintk("updated timf_frequency: %d (default: %d)\n", state->timf, state->timf_default);
 }
 
 static int dib7000m_agc_startup(struct dvb_frontend *demod)
@@ -804,7 +811,7 @@ static int dib7000m_agc_startup(struct d
 
 			dib7000m_restart_agc(state);
 
-			dprintk( "SPLIT %p: %hd", demod, agc_split);
+			dprintk("SPLIT %p: %hd\n", demod, agc_split);
 
 			(*agc_state)++;
 			ret = 5;
@@ -1013,12 +1020,12 @@ static int dib7000m_autosearch_irq(struc
 	u16 irq_pending = dib7000m_read_word(state, reg);
 
 	if (irq_pending & 0x1) { // failed
-		dprintk( "autosearch failed");
+		dprintk("autosearch failed\n");
 		return 1;
 	}
 
 	if (irq_pending & 0x2) { // succeeded
-		dprintk( "autosearch succeeded");
+		dprintk("autosearch succeeded\n");
 		return 2;
 	}
 	return 0; // still pending
@@ -1102,7 +1109,7 @@ static int dib7000m_wakeup(struct dvb_fr
 	dib7000m_set_power_mode(state, DIB7000M_POWER_ALL);
 
 	if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
-		dprintk( "could not start Slow ADC");
+		dprintk("could not start Slow ADC\n");
 
 	return 0;
 }
@@ -1121,7 +1128,7 @@ static int dib7000m_identify(struct dib7
 	u16 value;
 
 	if ((value = dib7000m_read_word(state, 896)) != 0x01b3) {
-		dprintk( "wrong Vendor ID (0x%x)",value);
+		dprintk("wrong Vendor ID (0x%x)\n", value);
 		return -EREMOTEIO;
 	}
 
@@ -1130,21 +1137,21 @@ static int dib7000m_identify(struct dib7
 		state->revision != 0x4001 &&
 		state->revision != 0x4002 &&
 		state->revision != 0x4003) {
-		dprintk( "wrong Device ID (0x%x)",value);
+		dprintk("wrong Device ID (0x%x)\n", value);
 		return -EREMOTEIO;
 	}
 
 	/* protect this driver to be used with 7000PC */
 	if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) {
-		dprintk( "this driver does not work with DiB7000PC");
+		dprintk("this driver does not work with DiB7000PC\n");
 		return -EREMOTEIO;
 	}
 
 	switch (state->revision) {
-		case 0x4000: dprintk( "found DiB7000MA/PA/MB/PB"); break;
-		case 0x4001: state->reg_offs = 1; dprintk( "found DiB7000HC"); break;
-		case 0x4002: state->reg_offs = 1; dprintk( "found DiB7000MC"); break;
-		case 0x4003: state->reg_offs = 1; dprintk( "found DiB9000"); break;
+	case 0x4000: dprintk("found DiB7000MA/PA/MB/PB\n"); break;
+	case 0x4001: state->reg_offs = 1; dprintk("found DiB7000HC\n"); break;
+	case 0x4002: state->reg_offs = 1; dprintk("found DiB7000MC\n"); break;
+	case 0x4003: state->reg_offs = 1; dprintk("found DiB9000\n"); break;
 	}
 
 	return 0;
@@ -1242,7 +1249,7 @@ static int dib7000m_set_frontend(struct
 			found = dib7000m_autosearch_is_irq(fe);
 		} while (found == 0 && i--);
 
-		dprintk("autosearch returns: %d",found);
+		dprintk("autosearch returns: %d\n", found);
 		if (found == 0 || found == 1)
 			return 0; // no channel found
 
@@ -1330,7 +1337,7 @@ int dib7000m_pid_filter_ctrl(struct dvb_
 	struct dib7000m_state *state = fe->demodulator_priv;
 	u16 val = dib7000m_read_word(state, 294 + state->reg_offs) & 0xffef;
 	val |= (onoff & 0x1) << 4;
-	dprintk("PID filter enabled %d", onoff);
+	dprintk("PID filter enabled %d\n", onoff);
 	return dib7000m_write_word(state, 294 + state->reg_offs, val);
 }
 EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
@@ -1338,7 +1345,7 @@ EXPORT_SYMBOL(dib7000m_pid_filter_ctrl);
 int dib7000m_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
 	struct dib7000m_state *state = fe->demodulator_priv;
-	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
+	dprintk("PID filter: index %x, PID %d, OnOff %d\n", id, pid, onoff);
 	return dib7000m_write_word(state, 300 + state->reg_offs + id,
 			onoff ? (1 << 13) | pid : 0);
 }
@@ -1362,7 +1369,7 @@ int dib7000m_i2c_enumeration(struct i2c_
 		if (dib7000m_identify(&st) != 0) {
 			st.i2c_addr = default_addr;
 			if (dib7000m_identify(&st) != 0) {
-				dprintk("DiB7000M #%d: not identified", k);
+				dprintk("DiB7000M #%d: not identified\n", k);
 				return -EIO;
 			}
 		}
@@ -1375,7 +1382,7 @@ int dib7000m_i2c_enumeration(struct i2c_
 		/* set new i2c address and force divstart */
 		dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2);
 
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+		dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
 	}
 
 	for (k = 0; k < no_of_demods; k++) {
@@ -1394,7 +1401,7 @@ int dib7000m_i2c_enumeration(struct i2c_
 EXPORT_SYMBOL(dib7000m_i2c_enumeration);
 #endif
 
-static struct dvb_frontend_ops dib7000m_ops;
+static const struct dvb_frontend_ops dib7000m_ops;
 struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg)
 {
 	struct dvb_frontend *demod;
@@ -1432,7 +1439,7 @@ error:
 }
 EXPORT_SYMBOL(dib7000m_attach);
 
-static struct dvb_frontend_ops dib7000m_ops = {
+static const struct dvb_frontend_ops dib7000m_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "DiBcom 7000MA/MB/PA/PB/MC",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib7000p.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib7000p.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib7000p.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib7000p.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,9 @@
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -26,7 +29,11 @@ static int buggy_sfn_workaround;
 module_param(buggy_sfn_workaround, int, 0644);
 MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
 
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 struct i2c_device {
 	struct i2c_adapter *i2c_adap;
@@ -98,7 +105,7 @@ static u16 dib7000p_read_word(struct dib
 	u16 ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -116,7 +123,7 @@ static u16 dib7000p_read_word(struct dib
 	state->msg[1].len = 2;
 
 	if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
+		dprintk("i2c read error on %d\n", reg);
 
 	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 	mutex_unlock(&state->i2c_buffer_lock);
@@ -128,7 +135,7 @@ static int dib7000p_write_word(struct di
 	int ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -174,7 +181,7 @@ static int dib7000p_set_output_mode(stru
 	fifo_threshold = 1792;
 	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
 
-	dprintk("setting output mode for demod %p to %d", &state->demod, mode);
+	dprintk("setting output mode for demod %p to %d\n", &state->demod, mode);
 
 	switch (mode) {
 	case OUTMODE_MPEG2_PAR_GATED_CLK:
@@ -204,7 +211,7 @@ static int dib7000p_set_output_mode(stru
 		outreg = 0;
 		break;
 	default:
-		dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
+		dprintk("Unhandled output_mode passed to be set for demod %p\n", &state->demod);
 		break;
 	}
 
@@ -224,7 +231,7 @@ static int dib7000p_set_diversity_in(str
 	struct dib7000p_state *state = demod->demodulator_priv;
 
 	if (state->div_force_off) {
-		dprintk("diversity combination deactivated - forced by COFDM parameters");
+		dprintk("diversity combination deactivated - forced by COFDM parameters\n");
 		onoff = 0;
 		dib7000p_write_word(state, 207, 0);
 	} else
@@ -374,10 +381,10 @@ static int dib7000p_set_bandwidth(struct
 	state->current_bandwidth = bw;
 
 	if (state->timf == 0) {
-		dprintk("using default timf");
+		dprintk("using default timf\n");
 		timf = state->cfg.bw->timf;
 	} else {
-		dprintk("using updated timf");
+		dprintk("using updated timf\n");
 		timf = state->timf;
 	}
 
@@ -494,7 +501,7 @@ static int dib7000p_update_pll(struct dv
 	loopdiv = (reg_1856 >> 6) & 0x3f;
 
 	if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
-		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
+		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)\n", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
 		reg_1856 &= 0xf000;
 		reg_1857 = dib7000p_read_word(state, 1857);
 		dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
@@ -511,7 +518,7 @@ static int dib7000p_update_pll(struct dv
 		dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
 
 		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
-			dprintk("Waiting for PLL to lock");
+			dprintk("Waiting for PLL to lock\n");
 
 		return 0;
 	}
@@ -521,7 +528,7 @@ static int dib7000p_update_pll(struct dv
 static int dib7000p_reset_gpio(struct dib7000p_state *st)
 {
 	/* reset the GPIOs */
-	dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
+	dprintk("gpio dir: %x: val: %x, pwm_pos: %x\n", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
 
 	dib7000p_write_word(st, 1029, st->gpio_dir);
 	dib7000p_write_word(st, 1030, st->gpio_val);
@@ -669,7 +676,7 @@ static int dib7000p_demod_reset(struct d
 	dib7000p_reset_pll(state);
 
 	if (dib7000p_reset_gpio(state) != 0)
-		dprintk("GPIO reset was not successful.");
+		dprintk("GPIO reset was not successful.\n");
 
 	if (state->version == SOC7090) {
 		dib7000p_write_word(state, 899, 0);
@@ -681,7 +688,7 @@ static int dib7000p_demod_reset(struct d
 		dib7000p_write_word(state, 273, (0<<6) | 30);
 	}
 	if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
-		dprintk("OUTPUT_MODE could not be reset.");
+		dprintk("OUTPUT_MODE could not be reset.\n");
 
 	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
 	dib7000p_sad_calib(state);
@@ -759,7 +766,7 @@ static int dib7000p_set_agc_config(struc
 		}
 
 	if (agc == NULL) {
-		dprintk("no valid AGC configuration found for band 0x%02x", band);
+		dprintk("no valid AGC configuration found for band 0x%02x\n", band);
 		return -EINVAL;
 	}
 
@@ -776,7 +783,7 @@ static int dib7000p_set_agc_config(struc
 	dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
 
 	/* AGC continued */
-	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
 		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
 
 	if (state->wbd_ref != 0)
@@ -806,7 +813,7 @@ static void dib7000p_set_dds(struct dib7
 	u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
 	u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
 
-	dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
+	dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d\n", offset_khz, internal, invert);
 
 	if (offset_khz < 0)
 		unit_khz_dds_val *= -1;
@@ -902,7 +909,7 @@ static int dib7000p_agc_startup(struct d
 
 		dib7000p_restart_agc(state);
 
-		dprintk("SPLIT %p: %hd", demod, agc_split);
+		dprintk("SPLIT %p: %hd\n", demod, agc_split);
 
 		(*agc_state)++;
 		ret = 5;
@@ -934,7 +941,7 @@ static void dib7000p_update_timf(struct
 	state->timf = timf * 160 / (state->current_bandwidth / 50);
 	dib7000p_write_word(state, 23, (u16) (timf >> 16));
 	dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
-	dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
+	dprintk("updated timf_frequency: %d (default: %d)\n", state->timf, state->cfg.bw->timf);
 
 }
 
@@ -1202,7 +1209,7 @@ static void dib7000p_spur_protect(struct
 	int bw_khz = bw;
 	u32 pha;
 
-	dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
+	dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)\n", f_rel, rf_khz, xtal);
 
 	if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
 		return;
@@ -1252,7 +1259,7 @@ static void dib7000p_spur_protect(struct
 			coef_im[k] = (1 << 24) - 1;
 		coef_im[k] /= (1 << 15);
 
-		dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
+		dprintk("PALF COEF: %d re: %d im: %d\n", k, coef_re[k], coef_im[k]);
 
 		dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
 		dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
@@ -1280,7 +1287,7 @@ static int dib7000p_tune(struct dvb_fron
 	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
 	tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
 	if (state->sfn_workaround_active) {
-		dprintk("SFN workaround is active");
+		dprintk("SFN workaround is active\n");
 		tmp |= (1 << 9);
 		dib7000p_write_word(state, 166, 0x4000);
 	} else {
@@ -1390,15 +1397,15 @@ static int dib7000p_sleep(struct dvb_fro
 static int dib7000p_identify(struct dib7000p_state *st)
 {
 	u16 value;
-	dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
+	dprintk("checking demod on I2C address: %d (%x)\n", st->i2c_addr, st->i2c_addr);
 
 	if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
-		dprintk("wrong Vendor ID (read=0x%x)", value);
+		dprintk("wrong Vendor ID (read=0x%x)\n", value);
 		return -EREMOTEIO;
 	}
 
 	if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
-		dprintk("wrong Device ID (%x)", value);
+		dprintk("wrong Device ID (%x)\n", value);
 		return -EREMOTEIO;
 	}
 
@@ -1536,7 +1543,7 @@ static int dib7000p_set_frontend(struct
 			found = dib7000p_autosearch_is_irq(fe);
 		} while (found == 0 && i--);
 
-		dprintk("autosearch returns: %d", found);
+		dprintk("autosearch returns: %d\n", found);
 		if (found == 0 || found == 1)
 			return 0;
 
@@ -1951,7 +1958,7 @@ static int dib7000p_get_stats(struct dvb
 		time_us = dib7000p_get_time_us(demod);
 		state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
 
-		dprintk("Next all layers stats available in %u us.", time_us);
+		dprintk("Next all layers stats available in %u us.\n", time_us);
 
 		dib7000p_read_ber(demod, &val);
 		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
@@ -2019,7 +2026,7 @@ static int dib7000pc_detection(struct i2
 
 	if (i2c_transfer(i2c_adap, msg, 2) == 2)
 		if (rx[0] == 0x01 && rx[1] == 0xb3) {
-			dprintk("-D-  DiB7000PC detected");
+			dprintk("-D-  DiB7000PC detected\n");
 			return 1;
 		}
 
@@ -2027,11 +2034,11 @@ static int dib7000pc_detection(struct i2
 
 	if (i2c_transfer(i2c_adap, msg, 2) == 2)
 		if (rx[0] == 0x01 && rx[1] == 0xb3) {
-			dprintk("-D-  DiB7000PC detected");
+			dprintk("-D-  DiB7000PC detected\n");
 			return 1;
 		}
 
-	dprintk("-D-  DiB7000PC not detected");
+	dprintk("-D-  DiB7000PC not detected\n");
 
 	kfree(rx);
 rx_memory_error:
@@ -2050,14 +2057,14 @@ static int dib7000p_pid_filter_ctrl(stru
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 val = dib7000p_read_word(state, 235) & 0xffef;
 	val |= (onoff & 0x1) << 4;
-	dprintk("PID filter enabled %d", onoff);
+	dprintk("PID filter enabled %d\n", onoff);
 	return dib7000p_write_word(state, 235, val);
 }
 
 static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
-	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
+	dprintk("PID filter: index %x, PID %d, OnOff %d\n", id, pid, onoff);
 	return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
 }
 
@@ -2100,7 +2107,7 @@ static int dib7000p_i2c_enumeration(stru
 		/* set new i2c address and force divstart */
 		dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
 
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+		dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
 	}
 
 	for (k = 0; k < no_of_demods; k++) {
@@ -2136,21 +2143,21 @@ static s32 dib7000p_get_adc_power(struct
 	buf[0] = dib7000p_read_word(state, 0x184);
 	buf[1] = dib7000p_read_word(state, 0x185);
 	pow_i = (buf[0] << 16) | buf[1];
-	dprintk("raw pow_i = %d", pow_i);
+	dprintk("raw pow_i = %d\n", pow_i);
 
 	tmp_val = pow_i;
 	while (tmp_val >>= 1)
 		exp++;
 
 	mant = (pow_i * 1000 / (1 << exp));
-	dprintk(" mant = %d exp = %d", mant / 1000, exp);
+	dprintk(" mant = %d exp = %d\n", mant / 1000, exp);
 
 	ix = (u8) ((mant - 1000) / 100);	/* index of the LUT */
-	dprintk(" ix = %d", ix);
+	dprintk(" ix = %d\n", ix);
 
 	pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
 	pow_i = (pow_i << 8) / 1000;
-	dprintk(" pow_i = %d", pow_i);
+	dprintk(" pow_i = %d\n", pow_i);
 
 	return pow_i;
 }
@@ -2185,7 +2192,7 @@ static int w7090p_tuner_write_serpar(str
 		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
 		i--;
 		if (i == 0)
-			dprintk("Tuner ITF: write busy (overflow)");
+			dprintk("Tuner ITF: write busy (overflow)\n");
 	}
 	dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
 	dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
@@ -2205,7 +2212,7 @@ static int w7090p_tuner_read_serpar(stru
 		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
 		i--;
 		if (i == 0)
-			dprintk("TunerITF: read busy (overflow)");
+			dprintk("TunerITF: read busy (overflow)\n");
 	}
 	dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
 
@@ -2214,7 +2221,7 @@ static int w7090p_tuner_read_serpar(stru
 		n_empty = dib7000p_read_word(state, 1984) & 0x1;
 		i--;
 		if (i == 0)
-			dprintk("TunerITF: read busy (empty)");
+			dprintk("TunerITF: read busy (empty)\n");
 	}
 	read_word = dib7000p_read_word(state, 1987);
 	msg[1].buf[0] = (read_word >> 8) & 0xff;
@@ -2435,7 +2442,7 @@ static u32 dib7090_calcSyncFreq(u32 P_Ki
 
 static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
 {
-	dprintk("Configure DibStream Tx");
+	dprintk("Configure DibStream Tx\n");
 
 	dib7000p_write_word(state, 1615, 1);
 	dib7000p_write_word(state, 1603, P_Kin);
@@ -2455,7 +2462,7 @@ static int dib7090_cfg_DibRx(struct dib7
 {
 	u32 syncFreq;
 
-	dprintk("Configure DibStream Rx");
+	dprintk("Configure DibStream Rx\n");
 	if ((P_Kin != 0) && (P_Kout != 0)) {
 		syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
 		dib7000p_write_word(state, 1542, syncFreq);
@@ -2492,7 +2499,7 @@ static void dib7090_enMpegMux(struct dib
 static void dib7090_configMpegMux(struct dib7000p_state *state,
 		u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
 {
-	dprintk("Enable Mpeg mux");
+	dprintk("Enable Mpeg mux\n");
 
 	dib7090_enMpegMux(state, 0);
 
@@ -2513,17 +2520,17 @@ static void dib7090_setDibTxMux(struct d
 
 	switch (mode) {
 	case MPEG_ON_DIBTX:
-			dprintk("SET MPEG ON DIBSTREAM TX");
+			dprintk("SET MPEG ON DIBSTREAM TX\n");
 			dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
 			reg_1288 |= (1<<9);
 			break;
 	case DIV_ON_DIBTX:
-			dprintk("SET DIV_OUT ON DIBSTREAM TX");
+			dprintk("SET DIV_OUT ON DIBSTREAM TX\n");
 			dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
 			reg_1288 |= (1<<8);
 			break;
 	case ADC_ON_DIBTX:
-			dprintk("SET ADC_OUT ON DIBSTREAM TX");
+			dprintk("SET ADC_OUT ON DIBSTREAM TX\n");
 			dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
 			reg_1288 |= (1<<7);
 			break;
@@ -2539,17 +2546,17 @@ static void dib7090_setHostBusMux(struct
 
 	switch (mode) {
 	case DEMOUT_ON_HOSTBUS:
-			dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+			dprintk("SET DEM OUT OLD INTERF ON HOST BUS\n");
 			dib7090_enMpegMux(state, 0);
 			reg_1288 |= (1<<6);
 			break;
 	case DIBTX_ON_HOSTBUS:
-			dprintk("SET DIBSTREAM TX ON HOST BUS");
+			dprintk("SET DIBSTREAM TX ON HOST BUS\n");
 			dib7090_enMpegMux(state, 0);
 			reg_1288 |= (1<<5);
 			break;
 	case MPEG_ON_HOSTBUS:
-			dprintk("SET MPEG MUX ON HOST BUS");
+			dprintk("SET MPEG MUX ON HOST BUS\n");
 			reg_1288 |= (1<<4);
 			break;
 	default:
@@ -2565,7 +2572,7 @@ static int dib7090_set_diversity_in(stru
 
 	switch (onoff) {
 	case 0: /* only use the internal way - not the diversity input */
-			dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
+			dprintk("%s mode OFF : by default Enable Mpeg INPUT\n", __func__);
 			dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
 
 			/* Do not divide the serial clock of MPEG MUX */
@@ -2581,7 +2588,7 @@ static int dib7090_set_diversity_in(stru
 			break;
 	case 1: /* both ways */
 	case 2: /* only the diversity input */
-			dprintk("%s ON : Enable diversity INPUT", __func__);
+			dprintk("%s ON : Enable diversity INPUT\n", __func__);
 			dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
 			state->input_mode_mpeg = 0;
 			break;
@@ -2612,11 +2619,11 @@ static int dib7090_set_output_mode(struc
 
 	case OUTMODE_MPEG2_SERIAL:
 		if (prefer_mpeg_mux_use) {
-			dprintk("setting output mode TS_SERIAL using Mpeg Mux");
+			dprintk("setting output mode TS_SERIAL using Mpeg Mux\n");
 			dib7090_configMpegMux(state, 3, 1, 1);
 			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
 		} else {/* Use Smooth block */
-			dprintk("setting output mode TS_SERIAL using Smooth bloc");
+			dprintk("setting output mode TS_SERIAL using Smooth bloc\n");
 			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
 			outreg |= (2<<6) | (0 << 1);
 		}
@@ -2624,24 +2631,24 @@ static int dib7090_set_output_mode(struc
 
 	case OUTMODE_MPEG2_PAR_GATED_CLK:
 		if (prefer_mpeg_mux_use) {
-			dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+			dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux\n");
 			dib7090_configMpegMux(state, 2, 0, 0);
 			dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
 		} else { /* Use Smooth block */
-			dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
+			dprintk("setting output mode TS_PARALLEL_GATED using Smooth block\n");
 			dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
 			outreg |= (0<<6);
 		}
 		break;
 
 	case OUTMODE_MPEG2_PAR_CONT_CLK:	/* Using Smooth block only */
-		dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
+		dprintk("setting output mode TS_PARALLEL_CONT using Smooth block\n");
 		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
 		outreg |= (1<<6);
 		break;
 
 	case OUTMODE_MPEG2_FIFO:	/* Using Smooth block because not supported by new Mpeg Mux bloc */
-		dprintk("setting output mode TS_FIFO using Smooth block");
+		dprintk("setting output mode TS_FIFO using Smooth block\n");
 		dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
 		outreg |= (5<<6);
 		smo_mode |= (3 << 1);
@@ -2649,13 +2656,13 @@ static int dib7090_set_output_mode(struc
 		break;
 
 	case OUTMODE_DIVERSITY:
-		dprintk("setting output mode MODE_DIVERSITY");
+		dprintk("setting output mode MODE_DIVERSITY\n");
 		dib7090_setDibTxMux(state, DIV_ON_DIBTX);
 		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
 		break;
 
 	case OUTMODE_ANALOG_ADC:
-		dprintk("setting output mode MODE_ANALOG_ADC");
+		dprintk("setting output mode MODE_ANALOG_ADC\n");
 		dib7090_setDibTxMux(state, ADC_ON_DIBTX);
 		dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
 		break;
@@ -2678,7 +2685,7 @@ static int dib7090_tuner_sleep(struct dv
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 en_cur_state;
 
-	dprintk("sleep dib7090: %d", onoff);
+	dprintk("sleep dib7090: %d\n", onoff);
 
 	en_cur_state = dib7000p_read_word(state, 1922);
 
@@ -2714,7 +2721,7 @@ static int dib7090_slave_reset(struct dv
 	return 0;
 }
 
-static struct dvb_frontend_ops dib7000p_ops;
+static const struct dvb_frontend_ops dib7000p_ops;
 static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
 {
 	struct dvb_frontend *demod;
@@ -2804,7 +2811,7 @@ void *dib7000p_attach(struct dib7000p_op
 }
 EXPORT_SYMBOL(dib7000p_attach);
 
-static struct dvb_frontend_ops dib7000p_ops = {
+static const struct dvb_frontend_ops dib7000p_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		 .name = "DiBcom 7000PC",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib8000.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib8000.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib8000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib8000.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,9 @@
  *  modify it under the terms of the GNU General Public License as
  *  published by the Free Software Foundation, version 2.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -31,7 +34,11 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 struct i2c_device {
 	struct i2c_adapter *adap;
@@ -147,7 +154,7 @@ static u16 dib8000_i2c_read16(struct i2c
 	};
 
 	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -157,7 +164,7 @@ static u16 dib8000_i2c_read16(struct i2c
 	msg[1].buf    = i2c->i2c_read_buffer;
 
 	if (i2c_transfer(i2c->adap, msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
+		dprintk("i2c read error on %d\n", reg);
 
 	ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
 	mutex_unlock(i2c->i2c_buffer_lock);
@@ -182,7 +189,7 @@ static u16 __dib8000_read_word(struct di
 	state->msg[1].len = 2;
 
 	if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
+		dprintk("i2c read error on %d\n", reg);
 
 	ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
 
@@ -194,7 +201,7 @@ static u16 dib8000_read_word(struct dib8
 	u16 ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -210,7 +217,7 @@ static u32 dib8000_read32(struct dib8000
 	u16 rw[2];
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -228,7 +235,7 @@ static int dib8000_i2c_write16(struct i2
 	int ret = 0;
 
 	if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -249,7 +256,7 @@ static int dib8000_write_word(struct dib
 	int ret;
 
 	if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -395,7 +402,7 @@ static void dib8000_set_acquisition_mode
 {
 	u16 nud = dib8000_read_word(state, 298);
 	nud |= (1 << 3) | (1 << 0);
-	dprintk("acquisition mode activated");
+	dprintk("acquisition mode activated\n");
 	dib8000_write_word(state, 298, nud);
 }
 static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
@@ -408,7 +415,7 @@ static int dib8000_set_output_mode(struc
 	fifo_threshold = 1792;
 	smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
 
-	dprintk("-I-	Setting output mode for demod %p to %d",
+	dprintk("-I-	Setting output mode for demod %p to %d\n",
 			&state->fe[0], mode);
 
 	switch (mode) {
@@ -443,7 +450,7 @@ static int dib8000_set_output_mode(struc
 		break;
 
 	default:
-		dprintk("Unhandled output_mode passed to be set for demod %p",
+		dprintk("Unhandled output_mode passed to be set for demod %p\n",
 				&state->fe[0]);
 		return -EINVAL;
 	}
@@ -464,7 +471,7 @@ static int dib8000_set_diversity_in(stru
 	struct dib8000_state *state = fe->demodulator_priv;
 	u16 tmp, sync_wait = dib8000_read_word(state, 273) & 0xfff0;
 
-	dprintk("set diversity input to %i", onoff);
+	dprintk("set diversity input to %i\n", onoff);
 	if (!state->differential_constellation) {
 		dib8000_write_word(state, 272, 1 << 9);	//dvsy_off_lmod4 = 1
 		dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2);	// sync_enable = 1; comb_mode = 2
@@ -531,7 +538,7 @@ static void dib8000_set_power_mode(struc
 		break;
 	}
 
-	dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280);
+	dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x\n", reg_774, reg_775, reg_776, reg_900, reg_1280);
 	dib8000_write_word(state, 774, reg_774);
 	dib8000_write_word(state, 775, reg_775);
 	dib8000_write_word(state, 776, reg_776);
@@ -619,10 +626,10 @@ static int dib8000_set_bandwidth(struct
 		bw = 6000;
 
 	if (state->timf == 0) {
-		dprintk("using default timf");
+		dprintk("using default timf\n");
 		timf = state->timf_default;
 	} else {
-		dprintk("using updated timf");
+		dprintk("using updated timf\n");
 		timf = state->timf;
 	}
 
@@ -667,7 +674,7 @@ static int dib8000_set_wbd_ref(struct dv
 
 static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
 {
-	dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
+	dprintk("ifreq: %d %x, inversion: %d\n", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
 	if (state->revision != 0x8090) {
 		dib8000_write_word(state, 23,
 				(u16) (((bw->internal * 1000) >> 16) & 0xffff));
@@ -704,7 +711,7 @@ static void dib8000_reset_pll(struct dib
 		clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
 		dib8000_write_word(state, 902, clk_cfg1);
 
-		dprintk("clk_cfg1: 0x%04x", clk_cfg1);
+		dprintk("clk_cfg1: 0x%04x\n", clk_cfg1);
 
 		/* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
 		if (state->cfg.pll->ADClkSrc == 0)
@@ -754,7 +761,7 @@ static int dib8000_update_pll(struct dvb
 				pll->pll_ratio == loopdiv))
 		return -EINVAL;
 
-	dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
+	dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)\n", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
 	if (state->revision == 0x8090) {
 		reg_1856 &= 0xf000;
 		reg_1857 = dib8000_read_word(state, 1857);
@@ -767,11 +774,11 @@ static int dib8000_update_pll(struct dvb
 
 		/* write new system clk into P_sec_len */
 		internal = dib8000_read32(state, 23) / 1000;
-		dprintk("Old Internal = %d", internal);
+		dprintk("Old Internal = %d\n", internal);
 		xtal = 2 * (internal / loopdiv) * prediv;
 		internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio;
-		dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000);
-		dprintk("New Internal = %d", internal);
+		dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d\n", xtal, internal/1000, internal/2000, internal/8000);
+		dprintk("New Internal = %d\n", internal);
 
 		dib8000_write_word(state, 23,
 				(u16) (((internal / 2) >> 16) & 0xffff));
@@ -780,22 +787,22 @@ static int dib8000_update_pll(struct dvb
 		dib8000_write_word(state, 1857, reg_1857 | (1 << 15));
 
 		while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1)
-			dprintk("Waiting for PLL to lock");
+			dprintk("Waiting for PLL to lock\n");
 
 		/* verify */
 		reg_1856 = dib8000_read_word(state, 1856);
-		dprintk("PLL Updated with prediv = %d and loopdiv = %d",
+		dprintk("PLL Updated with prediv = %d and loopdiv = %d\n",
 				reg_1856&0x3f, (reg_1856>>6)&0x3f);
 	} else {
 		if (bw != state->current_demod_bw) {
 			/** Bandwidth change => force PLL update **/
-			dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv);
+			dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)\n", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv);
 
 			if (state->cfg.pll->pll_prediv != oldprediv) {
 				/** Full PLL change only if prediv is changed **/
 
 				/** full update => bypass and reconfigure **/
-				dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio);
+				dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)\n", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio);
 				dib8000_write_word(state, 902, dib8000_read_word(state, 902) | (1<<3)); /* bypass PLL */
 				dib8000_reset_pll(state);
 				dib8000_write_word(state, 898, 0x0004); /* sad */
@@ -807,7 +814,7 @@ static int dib8000_update_pll(struct dvb
 
 		if (ratio != 0) {
 			/** ratio update => only change ratio **/
-			dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio);
+			dprintk("PLL: Update ratio (prediv: %d, ratio: %d)\n", state->cfg.pll->pll_prediv, ratio);
 			dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */
 		}
 	}
@@ -841,7 +848,7 @@ static int dib8000_cfg_gpio(struct dib80
 	st->cfg.gpio_val |= (val & 0x01) << num;	/* set the new value */
 	dib8000_write_word(st, 1030, st->cfg.gpio_val);
 
-	dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val);
+	dprintk("gpio dir: %x: gpio val: %x\n", st->cfg.gpio_dir, st->cfg.gpio_val);
 
 	return 0;
 }
@@ -958,29 +965,29 @@ static u16 dib8000_identify(struct i2c_d
 	value = dib8000_i2c_read16(client, 896);
 
 	if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) {
-		dprintk("wrong Vendor ID (read=0x%x)", value);
+		dprintk("wrong Vendor ID (read=0x%x)\n", value);
 		return 0;
 	}
 
 	value = dib8000_i2c_read16(client, 897);
 	if (value != 0x8000 && value != 0x8001 &&
 			value != 0x8002 && value != 0x8090) {
-		dprintk("wrong Device ID (%x)", value);
+		dprintk("wrong Device ID (%x)\n", value);
 		return 0;
 	}
 
 	switch (value) {
 	case 0x8000:
-		dprintk("found DiB8000A");
+		dprintk("found DiB8000A\n");
 		break;
 	case 0x8001:
-		dprintk("found DiB8000B");
+		dprintk("found DiB8000B\n");
 		break;
 	case 0x8002:
-		dprintk("found DiB8000C");
+		dprintk("found DiB8000C\n");
 		break;
 	case 0x8090:
-		dprintk("found DiB8096P");
+		dprintk("found DiB8096P\n");
 		break;
 	}
 	return value;
@@ -1037,7 +1044,7 @@ static int dib8000_reset(struct dvb_fron
 		dib8000_write_word(state, 1287, 0x0003);
 
 	if (state->revision == 0x8000)
-		dprintk("error : dib8000 MA not supported");
+		dprintk("error : dib8000 MA not supported\n");
 
 	dibx000_reset_i2c_master(&state->i2c_master);
 
@@ -1069,7 +1076,7 @@ static int dib8000_reset(struct dvb_fron
 		if (state->cfg.drives)
 			dib8000_write_word(state, 906, state->cfg.drives);
 		else {
-			dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.");
+			dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.\n");
 			/* min drive SDRAM - not optimal - adjust */
 			dib8000_write_word(state, 906, 0x2d98);
 		}
@@ -1080,11 +1087,11 @@ static int dib8000_reset(struct dvb_fron
 		dib8000_write_word(state, 898, 0x0004);
 
 	if (dib8000_reset_gpio(state) != 0)
-		dprintk("GPIO reset was not successful.");
+		dprintk("GPIO reset was not successful.\n");
 
 	if ((state->revision != 0x8090) &&
 			(dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0))
-		dprintk("OUTPUT_MODE could not be resetted.");
+		dprintk("OUTPUT_MODE could not be resetted.\n");
 
 	state->current_agc = NULL;
 
@@ -1176,7 +1183,7 @@ static int dib8000_set_agc_config(struct
 		}
 
 	if (agc == NULL) {
-		dprintk("no valid AGC configuration found for band 0x%02x", band);
+		dprintk("no valid AGC configuration found for band 0x%02x\n", band);
 		return -EINVAL;
 	}
 
@@ -1192,7 +1199,7 @@ static int dib8000_set_agc_config(struct
 	dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp);
 	dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp);
 
-	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
 		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
 
 	/* AGC continued */
@@ -1251,7 +1258,7 @@ static int dib8000_agc_soft_split(struct
 			(agc - state->current_agc->split.min_thres) /
 			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
 
-	dprintk("AGC split_offset: %d", split_offset);
+	dprintk("AGC split_offset: %d\n", split_offset);
 
 	// P_agc_force_split and P_agc_split_offset
 	dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset);
@@ -1395,7 +1402,7 @@ static void dib8096p_cfg_DibTx(struct di
 		u32 P_Kout, u32 insertExtSynchro, u32 synchroMode,
 		u32 syncWord, u32 syncSize)
 {
-	dprintk("Configure DibStream Tx");
+	dprintk("Configure DibStream Tx\n");
 
 	dib8000_write_word(state, 1615, 1);
 	dib8000_write_word(state, 1603, P_Kin);
@@ -1414,7 +1421,7 @@ static void dib8096p_cfg_DibRx(struct di
 {
 	u32 syncFreq;
 
-	dprintk("Configure DibStream Rx synchroMode = %d", synchroMode);
+	dprintk("Configure DibStream Rx synchroMode = %d\n", synchroMode);
 
 	if ((P_Kin != 0) && (P_Kout != 0)) {
 		syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout,
@@ -1456,7 +1463,7 @@ static void dib8096p_configMpegMux(struc
 {
 	u16 reg_1287;
 
-	dprintk("Enable Mpeg mux");
+	dprintk("Enable Mpeg mux\n");
 
 	dib8096p_enMpegMux(state, 0);
 
@@ -1477,15 +1484,15 @@ static void dib8096p_setDibTxMux(struct
 
 	switch (mode) {
 	case MPEG_ON_DIBTX:
-			dprintk("SET MPEG ON DIBSTREAM TX");
+			dprintk("SET MPEG ON DIBSTREAM TX\n");
 			dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
 			reg_1288 |= (1 << 9); break;
 	case DIV_ON_DIBTX:
-			dprintk("SET DIV_OUT ON DIBSTREAM TX");
+			dprintk("SET DIV_OUT ON DIBSTREAM TX\n");
 			dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
 			reg_1288 |= (1 << 8); break;
 	case ADC_ON_DIBTX:
-			dprintk("SET ADC_OUT ON DIBSTREAM TX");
+			dprintk("SET ADC_OUT ON DIBSTREAM TX\n");
 			dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
 			reg_1288 |= (1 << 7); break;
 	default:
@@ -1500,17 +1507,17 @@ static void dib8096p_setHostBusMux(struc
 
 	switch (mode) {
 	case DEMOUT_ON_HOSTBUS:
-			dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
+			dprintk("SET DEM OUT OLD INTERF ON HOST BUS\n");
 			dib8096p_enMpegMux(state, 0);
 			reg_1288 |= (1 << 6);
 			break;
 	case DIBTX_ON_HOSTBUS:
-			dprintk("SET DIBSTREAM TX ON HOST BUS");
+			dprintk("SET DIBSTREAM TX ON HOST BUS\n");
 			dib8096p_enMpegMux(state, 0);
 			reg_1288 |= (1 << 5);
 			break;
 	case MPEG_ON_HOSTBUS:
-			dprintk("SET MPEG MUX ON HOST BUS");
+			dprintk("SET MPEG MUX ON HOST BUS\n");
 			reg_1288 |= (1 << 4);
 			break;
 	default:
@@ -1526,7 +1533,7 @@ static int dib8096p_set_diversity_in(str
 
 	switch (onoff) {
 	case 0: /* only use the internal way - not the diversity input */
-			dprintk("%s mode OFF : by default Enable Mpeg INPUT",
+			dprintk("%s mode OFF : by default Enable Mpeg INPUT\n",
 					__func__);
 			/* outputRate = 8 */
 			dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
@@ -1544,7 +1551,7 @@ static int dib8096p_set_diversity_in(str
 			break;
 	case 1: /* both ways */
 	case 2: /* only the diversity input */
-			dprintk("%s ON : Enable diversity INPUT", __func__);
+			dprintk("%s ON : Enable diversity INPUT\n", __func__);
 			dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
 			state->input_mode_mpeg = 0;
 			break;
@@ -1576,11 +1583,11 @@ static int dib8096p_set_output_mode(stru
 
 	case OUTMODE_MPEG2_SERIAL:
 			if (prefer_mpeg_mux_use) {
-				dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux");
+				dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux\n");
 				dib8096p_configMpegMux(state, 3, 1, 1);
 				dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
 			} else {/* Use Smooth block */
-				dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc");
+				dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc\n");
 				dib8096p_setHostBusMux(state,
 						DEMOUT_ON_HOSTBUS);
 				outreg |= (2 << 6) | (0 << 1);
@@ -1589,11 +1596,11 @@ static int dib8096p_set_output_mode(stru
 
 	case OUTMODE_MPEG2_PAR_GATED_CLK:
 			if (prefer_mpeg_mux_use) {
-				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux\n");
 				dib8096p_configMpegMux(state, 2, 0, 0);
 				dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
 			} else { /* Use Smooth block */
-				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block");
+				dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block\n");
 				dib8096p_setHostBusMux(state,
 						DEMOUT_ON_HOSTBUS);
 				outreg |= (0 << 6);
@@ -1601,7 +1608,7 @@ static int dib8096p_set_output_mode(stru
 			break;
 
 	case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
-			dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block");
+			dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block\n");
 			dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
 			outreg |= (1 << 6);
 			break;
@@ -1609,7 +1616,7 @@ static int dib8096p_set_output_mode(stru
 	case OUTMODE_MPEG2_FIFO:
 			/* Using Smooth block because not supported
 			   by new Mpeg Mux bloc */
-			dprintk("dib8096P setting output mode TS_FIFO using Smooth block");
+			dprintk("dib8096P setting output mode TS_FIFO using Smooth block\n");
 			dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
 			outreg |= (5 << 6);
 			smo_mode |= (3 << 1);
@@ -1617,13 +1624,13 @@ static int dib8096p_set_output_mode(stru
 			break;
 
 	case OUTMODE_DIVERSITY:
-			dprintk("dib8096P setting output mode MODE_DIVERSITY");
+			dprintk("dib8096P setting output mode MODE_DIVERSITY\n");
 			dib8096p_setDibTxMux(state, DIV_ON_DIBTX);
 			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
 			break;
 
 	case OUTMODE_ANALOG_ADC:
-			dprintk("dib8096P setting output mode MODE_ANALOG_ADC");
+			dprintk("dib8096P setting output mode MODE_ANALOG_ADC\n");
 			dib8096p_setDibTxMux(state, ADC_ON_DIBTX);
 			dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
 			break;
@@ -1632,7 +1639,7 @@ static int dib8096p_set_output_mode(stru
 	if (mode != OUTMODE_HIGH_Z)
 		outreg |= (1<<10);
 
-	dprintk("output_mpeg2_in_188_bytes = %d",
+	dprintk("output_mpeg2_in_188_bytes = %d\n",
 			state->cfg.output_mpeg2_in_188_bytes);
 	if (state->cfg.output_mpeg2_in_188_bytes)
 		smo_mode |= (1 << 5);
@@ -1678,7 +1685,7 @@ static int dib8096p_tuner_write_serpar(s
 		n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
 		i--;
 		if (i == 0)
-			dprintk("Tuner ITF: write busy (overflow)");
+			dprintk("Tuner ITF: write busy (overflow)\n");
 	}
 	dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
 	dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
@@ -1699,7 +1706,7 @@ static int dib8096p_tuner_read_serpar(st
 		n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
 		i--;
 		if (i == 0)
-			dprintk("TunerITF: read busy (overflow)");
+			dprintk("TunerITF: read busy (overflow)\n");
 	}
 	dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f));
 
@@ -1708,7 +1715,7 @@ static int dib8096p_tuner_read_serpar(st
 		n_empty = dib8000_read_word(state, 1984)&0x1;
 		i--;
 		if (i == 0)
-			dprintk("TunerITF: read busy (empty)");
+			dprintk("TunerITF: read busy (empty)\n");
 	}
 
 	read_word = dib8000_read_word(state, 1987);
@@ -1889,7 +1896,7 @@ static int dib8096p_tuner_sleep(struct d
 	struct dib8000_state *state = fe->demodulator_priv;
 	u16 en_cur_state;
 
-	dprintk("sleep dib8096p: %d", onoff);
+	dprintk("sleep dib8096p: %d\n", onoff);
 
 	en_cur_state = dib8000_read_word(state, 1922);
 
@@ -1958,7 +1965,7 @@ static void dib8000_update_timf(struct d
 
 	dib8000_write_word(state, 29, (u16) (timf >> 16));
 	dib8000_write_word(state, 30, (u16) (timf & 0xffff));
-	dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
+	dprintk("Updated timing frequency: %d (default: %d)\n", state->timf, state->timf_default);
 }
 
 static u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
@@ -2118,7 +2125,7 @@ static u16 dib8000_get_init_prbs(struct
 	int sub_channel_prbs_group = 0;
 
 	sub_channel_prbs_group = (subchannel / 3) + 1;
-	dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
+	dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
 
 	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
 	case TRANSMISSION_MODE_2K:
@@ -2604,7 +2611,7 @@ static int dib8000_autosearch_start(stru
 					slist = 0;
 			}
 		}
-		dprintk("Using list for autosearch : %d", slist);
+		dprintk("Using list for autosearch : %d\n", slist);
 
 		dib8000_set_isdbt_common_channel(state, slist, 1);
 
@@ -2638,17 +2645,17 @@ static int dib8000_autosearch_irq(struct
 	if ((state->revision >= 0x8002) &&
 	    (state->autosearch_state == AS_SEARCHING_FFT)) {
 		if (irq_pending & 0x1) {
-			dprintk("dib8000_autosearch_irq: max correlation result available");
+			dprintk("dib8000_autosearch_irq: max correlation result available\n");
 			return 3;
 		}
 	} else {
 		if (irq_pending & 0x1) {	/* failed */
-			dprintk("dib8000_autosearch_irq failed");
+			dprintk("dib8000_autosearch_irq failed\n");
 			return 1;
 		}
 
 		if (irq_pending & 0x2) {	/* succeeded */
-			dprintk("dib8000_autosearch_irq succeeded");
+			dprintk("dib8000_autosearch_irq succeeded\n");
 			return 2;
 		}
 	}
@@ -2699,7 +2706,7 @@ static void dib8000_set_dds(struct dib80
 			dds += abs_offset_khz * unit_khz_dds_val;
 	}
 
-	dprintk("setting a DDS frequency offset of %c%dkHz", invert ? '-' : ' ', dds / unit_khz_dds_val);
+	dprintk("setting a DDS frequency offset of %c%dkHz\n", invert ? '-' : ' ', dds / unit_khz_dds_val);
 
 	if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) {
 		/* Max dds offset is the half of the demod freq */
@@ -2738,7 +2745,7 @@ static void dib8000_set_frequency_offset
 		}
 	}
 
-	dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d", c->frequency - current_rf, c->frequency, current_rf, total_dds_offset_khz);
+	dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d\n", c->frequency - current_rf, c->frequency, current_rf, total_dds_offset_khz);
 
 	/* apply dds offset now */
 	dib8000_set_dds(state, total_dds_offset_khz);
@@ -2890,7 +2897,7 @@ static u16 dib8000_read_lock(struct dvb_
 static int dib8090p_init_sdram(struct dib8000_state *state)
 {
 	u16 reg = 0;
-	dprintk("init sdram");
+	dprintk("init sdram\n");
 
 	reg = dib8000_read_word(state, 274) & 0xfff0;
 	dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */
@@ -2931,7 +2938,7 @@ static int is_manual_mode(struct dtv_fro
 	 * Transmission mode is only detected on auto mode, currently
 	 */
 	if (c->transmission_mode == TRANSMISSION_MODE_AUTO) {
-		dprintk("transmission mode auto");
+		dprintk("transmission mode auto\n");
 		return 0;
 	}
 
@@ -2939,7 +2946,7 @@ static int is_manual_mode(struct dtv_fro
 	 * Guard interval is only detected on auto mode, currently
 	 */
 	if (c->guard_interval == GUARD_INTERVAL_AUTO) {
-		dprintk("guard interval auto");
+		dprintk("guard interval auto\n");
 		return 0;
 	}
 
@@ -2948,7 +2955,7 @@ static int is_manual_mode(struct dtv_fro
 	 * layer should be enabled
 	 */
 	if (!c->isdbt_layer_enabled) {
-		dprintk("no layer modulation specified");
+		dprintk("no layer modulation specified\n");
 		return 0;
 	}
 
@@ -2970,7 +2977,7 @@ static int is_manual_mode(struct dtv_fro
 
 		if ((c->layer[i].modulation == QAM_AUTO) ||
 		    (c->layer[i].fec == FEC_AUTO)) {
-			dprintk("layer %c has either modulation or FEC auto",
+			dprintk("layer %c has either modulation or FEC auto\n",
 				'A' + i);
 			return 0;
 		}
@@ -2981,7 +2988,7 @@ static int is_manual_mode(struct dtv_fro
 	 *	fallback to auto mode.
 	 */
 	if (n_segs == 0 || n_segs > 13) {
-		dprintk("number of segments is invalid");
+		dprintk("number of segments is invalid\n");
 		return 0;
 	}
 
@@ -3009,7 +3016,7 @@ static int dib8000_tune(struct dvb_front
 
 #if 0
 	if (*tune_state < CT_DEMOD_STOP)
-		dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu",
+		dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu\n",
 			state->channel_parameters_set, *tune_state, state->autosearch_state, now);
 #endif
 
@@ -3022,7 +3029,7 @@ static int dib8000_tune(struct dvb_front
 		state->status = FE_STATUS_TUNE_PENDING;
 		state->channel_parameters_set = is_manual_mode(c);
 
-		dprintk("Tuning channel on %s search mode",
+		dprintk("Tuning channel on %s search mode\n",
 			state->channel_parameters_set ? "manual" : "auto");
 
 		dib8000_viterbi_state(state, 0); /* force chan dec in restart */
@@ -3102,7 +3109,7 @@ static int dib8000_tune(struct dvb_front
 				corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
 				corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
 			}
-			/* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
+			/* dprintk("corm fft: %u %u %u\n", corm[0], corm[1], corm[2]); */
 
 			max_value = 0;
 			for (find_index = 1 ; find_index < 3 ; find_index++) {
@@ -3122,7 +3129,7 @@ static int dib8000_tune(struct dvb_front
 				state->found_nfft = TRANSMISSION_MODE_8K;
 				break;
 			}
-			/* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
+			/* dprintk("Autosearch FFT has found Mode %d\n", max_value + 1); */
 
 			*tune_state = CT_DEMOD_SEARCH_NEXT;
 			state->autosearch_state = AS_SEARCHING_GUARD;
@@ -3137,7 +3144,7 @@ static int dib8000_tune(struct dvb_front
 				state->found_guard = dib8000_read_word(state, 572) & 0x3;
 			else
 				state->found_guard = dib8000_read_word(state, 570) & 0x3;
-			/* dprintk("guard interval found=%i", state->found_guard); */
+			/* dprintk("guard interval found=%i\n", state->found_guard); */
 
 			*tune_state = CT_DEMOD_STEP_3;
 			break;
@@ -3233,7 +3240,7 @@ static int dib8000_tune(struct dvb_front
 			/* defines timeout for mpeg lock depending on interleaver length of longest layer */
 			for (i = 0; i < 3; i++) {
 				if (c->layer[i].interleaving >= deeper_interleaver) {
-					dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
+					dprintk("layer%i: time interleaver = %d\n", i, c->layer[i].interleaving);
 					if (c->layer[i].segment_count > 0) { /* valid layer */
 						deeper_interleaver = c->layer[0].interleaving;
 						state->longest_intlv_layer = i;
@@ -3252,7 +3259,7 @@ static int dib8000_tune(struct dvb_front
 				locks *= 2;
 
 			*timeout = now + msecs_to_jiffies(200 * locks); /* give the mpeg lock 800ms if sram is present */
-			dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %ld",
+			dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %ld\n",
 				deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
 
 			*tune_state = CT_DEMOD_STEP_10;
@@ -3263,7 +3270,7 @@ static int dib8000_tune(struct dvb_front
 	case CT_DEMOD_STEP_10: /* 40 */
 		locks = dib8000_read_lock(fe);
 		if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
-			dprintk("ISDB-T layer locks: Layer A %s, Layer B %s, Layer C %s",
+			dprintk("ISDB-T layer locks: Layer A %s, Layer B %s, Layer C %s\n",
 				c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
 				c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
 				c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
@@ -3283,7 +3290,7 @@ static int dib8000_tune(struct dvb_front
 				*tune_state = CT_DEMOD_STEP_11;
 			} else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
 				if (locks & (0x7 << 5)) {
-					dprintk("Not all ISDB-T layers locked in %d ms: Layer A %s, Layer B %s, Layer C %s",
+					dprintk("Not all ISDB-T layers locked in %d ms: Layer A %s, Layer B %s, Layer C %s\n",
 						jiffies_to_msecs(now - *timeout),
 						c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
 						c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
@@ -3348,7 +3355,7 @@ static int dib8000_wakeup(struct dvb_fro
 	dib8000_set_power_mode(state, DIB8000_POWER_ALL);
 	dib8000_set_adc_state(state, DIBX000_ADC_ON);
 	if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
-		dprintk("could not start Slow ADC");
+		dprintk("could not start Slow ADC\n");
 
 	if (state->revision == 0x8090)
 		dib8000_sad_calib(state);
@@ -3401,11 +3408,11 @@ static int dib8000_get_frontend(struct d
 	if (!(stat & FE_HAS_SYNC))
 		return 0;
 
-	dprintk("dib8000_get_frontend: TMCC lock");
+	dprintk("dib8000_get_frontend: TMCC lock\n");
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
 		if (stat&FE_HAS_SYNC) {
-			dprintk("TMCC lock on the slave%i", index_frontend);
+			dprintk("TMCC lock on the slave%i\n", index_frontend);
 			/* synchronize the cache with the other frontends */
 			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c);
 			for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
@@ -3437,41 +3444,41 @@ static int dib8000_get_frontend(struct d
 	switch ((val & 0x30) >> 4) {
 	case 1:
 		c->transmission_mode = TRANSMISSION_MODE_2K;
-		dprintk("dib8000_get_frontend: transmission mode 2K");
+		dprintk("dib8000_get_frontend: transmission mode 2K\n");
 		break;
 	case 2:
 		c->transmission_mode = TRANSMISSION_MODE_4K;
-		dprintk("dib8000_get_frontend: transmission mode 4K");
+		dprintk("dib8000_get_frontend: transmission mode 4K\n");
 		break;
 	case 3:
 	default:
 		c->transmission_mode = TRANSMISSION_MODE_8K;
-		dprintk("dib8000_get_frontend: transmission mode 8K");
+		dprintk("dib8000_get_frontend: transmission mode 8K\n");
 		break;
 	}
 
 	switch (val & 0x3) {
 	case 0:
 		c->guard_interval = GUARD_INTERVAL_1_32;
-		dprintk("dib8000_get_frontend: Guard Interval = 1/32 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/32\n");
 		break;
 	case 1:
 		c->guard_interval = GUARD_INTERVAL_1_16;
-		dprintk("dib8000_get_frontend: Guard Interval = 1/16 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/16\n");
 		break;
 	case 2:
-		dprintk("dib8000_get_frontend: Guard Interval = 1/8 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/8\n");
 		c->guard_interval = GUARD_INTERVAL_1_8;
 		break;
 	case 3:
-		dprintk("dib8000_get_frontend: Guard Interval = 1/4 ");
+		dprintk("dib8000_get_frontend: Guard Interval = 1/4\n");
 		c->guard_interval = GUARD_INTERVAL_1_4;
 		break;
 	}
 
 	val = dib8000_read_word(state, 505);
 	c->isdbt_partial_reception = val & 1;
-	dprintk("dib8000_get_frontend: partial_reception = %d ", c->isdbt_partial_reception);
+	dprintk("dib8000_get_frontend: partial_reception = %d\n", c->isdbt_partial_reception);
 
 	for (i = 0; i < 3; i++) {
 		int show;
@@ -3485,7 +3492,7 @@ static int dib8000_get_frontend(struct d
 			show = 1;
 
 		if (show)
-			dprintk("dib8000_get_frontend: Layer %d segments = %d ",
+			dprintk("dib8000_get_frontend: Layer %d segments = %d\n",
 				i, c->layer[i].segment_count);
 
 		val = dib8000_read_word(state, 499 + i) & 0x3;
@@ -3494,7 +3501,7 @@ static int dib8000_get_frontend(struct d
 			val = 4;
 		c->layer[i].interleaving = val;
 		if (show)
-			dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ",
+			dprintk("dib8000_get_frontend: Layer %d time_intlv = %d\n",
 				i, c->layer[i].interleaving);
 
 		val = dib8000_read_word(state, 481 + i);
@@ -3502,27 +3509,27 @@ static int dib8000_get_frontend(struct d
 		case 1:
 			c->layer[i].fec = FEC_1_2;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i);
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2\n", i);
 			break;
 		case 2:
 			c->layer[i].fec = FEC_2_3;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i);
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3\n", i);
 			break;
 		case 3:
 			c->layer[i].fec = FEC_3_4;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i);
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4\n", i);
 			break;
 		case 5:
 			c->layer[i].fec = FEC_5_6;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i);
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6\n", i);
 			break;
 		default:
 			c->layer[i].fec = FEC_7_8;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i);
+				dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8\n", i);
 			break;
 		}
 
@@ -3531,23 +3538,23 @@ static int dib8000_get_frontend(struct d
 		case 0:
 			c->layer[i].modulation = DQPSK;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d DQPSK ", i);
+				dprintk("dib8000_get_frontend: Layer %d DQPSK\n", i);
 			break;
 		case 1:
 			c->layer[i].modulation = QPSK;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d QPSK ", i);
+				dprintk("dib8000_get_frontend: Layer %d QPSK\n", i);
 			break;
 		case 2:
 			c->layer[i].modulation = QAM_16;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d QAM16 ", i);
+				dprintk("dib8000_get_frontend: Layer %d QAM16\n", i);
 			break;
 		case 3:
 		default:
 			c->layer[i].modulation = QAM_64;
 			if (show)
-				dprintk("dib8000_get_frontend: Layer %d QAM64 ", i);
+				dprintk("dib8000_get_frontend: Layer %d QAM64\n", i);
 			break;
 		}
 	}
@@ -3578,12 +3585,12 @@ static int dib8000_set_frontend(struct d
 	unsigned long delay, callback_time;
 
 	if (c->frequency == 0) {
-		dprintk("dib8000: must at least specify frequency ");
+		dprintk("dib8000: must at least specify frequency\n");
 		return 0;
 	}
 
 	if (c->bandwidth_hz == 0) {
-		dprintk("dib8000: no bandwidth specified, set to default ");
+		dprintk("dib8000: no bandwidth specified, set to default\n");
 		c->bandwidth_hz = 6000000;
 	}
 
@@ -3671,7 +3678,7 @@ static int dib8000_set_frontend(struct d
 			/* we are in autosearch */
 			if (state->channel_parameters_set == 0) { /* searching */
 				if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) {
-					dprintk("autosearch succeeded on fe%i", index_frontend);
+					dprintk("autosearch succeeded on fe%i\n", index_frontend);
 					dib8000_get_frontend(state->fe[index_frontend], c); /* we read the channel parameters from the frontend which was successful */
 					state->channel_parameters_set = 1;
 
@@ -3708,11 +3715,11 @@ static int dib8000_set_frontend(struct d
 					active = 1;
 			}
 			if (active == 0)
-				dprintk("tuning done with status %d", dib8000_get_status(state->fe[0]));
+				dprintk("tuning done with status %d\n", dib8000_get_status(state->fe[0]));
 		}
 
 		if ((active == 1) && (callback_time == 0)) {
-			dprintk("strange callback time something went wrong");
+			dprintk("strange callback time something went wrong\n");
 			active = 0;
 		}
 
@@ -4172,7 +4179,7 @@ static int dib8000_get_stats(struct dvb_
 		time_us = dib8000_get_time_us(fe, -1);
 		state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
 
-		dprintk("Next all layers stats available in %u us.", time_us);
+		dprintk("Next all layers stats available in %u us.\n", time_us);
 
 		dib8000_read_ber(fe, &val);
 		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
@@ -4239,12 +4246,12 @@ static int dib8000_set_slave_frontend(st
 	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
 		index_frontend++;
 	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
-		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
+		dprintk("set slave fe %p to index %i\n", fe_slave, index_frontend);
 		state->fe[index_frontend] = fe_slave;
 		return 0;
 	}
 
-	dprintk("too many slave frontend");
+	dprintk("too many slave frontend\n");
 	return -ENOMEM;
 }
 
@@ -4256,12 +4263,12 @@ static int dib8000_remove_slave_frontend
 	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
 		index_frontend++;
 	if (index_frontend != 1) {
-		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1);
+		dprintk("remove slave fe %p (index %i)\n", state->fe[index_frontend-1], index_frontend-1);
 		state->fe[index_frontend] = NULL;
 		return 0;
 	}
 
-	dprintk("no frontend to be removed");
+	dprintk("no frontend to be removed\n");
 	return -ENODEV;
 }
 
@@ -4283,18 +4290,18 @@ static int dib8000_i2c_enumeration(struc
 
 	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
 	if (!client.i2c_write_buffer) {
-		dprintk("%s: not enough memory", __func__);
+		dprintk("%s: not enough memory\n", __func__);
 		return -ENOMEM;
 	}
 	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
 	if (!client.i2c_read_buffer) {
-		dprintk("%s: not enough memory", __func__);
+		dprintk("%s: not enough memory\n", __func__);
 		ret = -ENOMEM;
 		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__);
+		dprintk("%s: not enough memory\n", __func__);
 		ret = -ENOMEM;
 		goto error_memory_lock;
 	}
@@ -4313,7 +4320,7 @@ static int dib8000_i2c_enumeration(struc
 				dib8000_i2c_write16(&client, 1287, 0x0003);
 			client.addr = default_addr;
 			if (dib8000_identify(&client) == 0) {
-				dprintk("#%d: not identified", k);
+				dprintk("#%d: not identified\n", k);
 				ret  = -EINVAL;
 				goto error;
 			}
@@ -4327,7 +4334,7 @@ static int dib8000_i2c_enumeration(struc
 		client.addr = new_addr;
 		dib8000_identify(&client);
 
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+		dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
 	}
 
 	for (k = 0; k < no_of_demods; k++) {
@@ -4385,14 +4392,14 @@ static int dib8000_pid_filter_ctrl(struc
 	u16 val = dib8000_read_word(st, 299) & 0xffef;
 	val |= (onoff & 0x1) << 4;
 
-	dprintk("pid filter enabled %d", onoff);
+	dprintk("pid filter enabled %d\n", onoff);
 	return dib8000_write_word(st, 299, val);
 }
 
 static int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
 	struct dib8000_state *st = fe->demodulator_priv;
-	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+	dprintk("Index %x, PID %d, OnOff %d\n", id, pid, onoff);
 	return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
 }
 
@@ -4431,7 +4438,7 @@ static struct dvb_frontend *dib8000_init
 	struct dvb_frontend *fe;
 	struct dib8000_state *state;
 
-	dprintk("dib8000_init");
+	dprintk("dib8000_init\n");
 
 	state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
 	if (state == NULL)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib9000.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib9000.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dib9000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dib9000.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,9 @@
  *	modify it under the terms of the GNU General Public License as
  *	published by the Free Software Foundation, version 2.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
@@ -21,7 +24,12 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB9000: "); printk(args); printk("\n"); } } while (0)
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
+
 #define MAX_NUMBER_OF_FRONTENDS 6
 
 struct i2c_device {
@@ -258,7 +266,7 @@ static int dib9000_read16_attr(struct di
 		state->msg[1].buf = b;
 		ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
 		if (ret != 0) {
-			dprintk("i2c read error on %d", reg);
+			dprintk("i2c read error on %d\n", reg);
 			return -EREMOTEIO;
 		}
 
@@ -285,7 +293,7 @@ static u16 dib9000_i2c_read16(struct i2c
 	i2c->i2c_write_buffer[1] = reg & 0xff;
 
 	if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
-		dprintk("read register %x error", reg);
+		dprintk("read register %x error\n", reg);
 		return 0;
 	}
 
@@ -440,7 +448,7 @@ static int dib9000_risc_mem_read(struct
 		return -EIO;
 
 	if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	dib9000_risc_mem_setup(state, cmd | 0x80);
@@ -456,7 +464,7 @@ static int dib9000_risc_mem_write(struct
 		return -EIO;
 
 	if (mutex_lock_interruptible(&state->platform.risc.mem_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	dib9000_risc_mem_setup(state, cmd);
@@ -479,13 +487,13 @@ static int dib9000_firmware_download(str
 	dib9000_write_word(state, 1025 + offs, 0);
 	dib9000_write_word(state, 1031 + offs, key);
 
-	dprintk("going to download %dB of microcode", len);
+	dprintk("going to download %dB of microcode\n", len);
 	if (dib9000_write16_noinc(state, 1026 + offs, (u8 *) code, (u16) len) != 0) {
-		dprintk("error while downloading microcode for RISC %c", 'A' + risc_id);
+		dprintk("error while downloading microcode for RISC %c\n", 'A' + risc_id);
 		return -EIO;
 	}
 
-	dprintk("Microcode for RISC %c loaded", 'A' + risc_id);
+	dprintk("Microcode for RISC %c loaded\n", 'A' + risc_id);
 
 	return 0;
 }
@@ -511,10 +519,10 @@ static int dib9000_mbx_host_init(struct
 	} while ((reset_reg & 0x8000) && --tries);
 
 	if (reset_reg & 0x8000) {
-		dprintk("MBX: init ERROR, no response from RISC %c", 'A' + risc_id);
+		dprintk("MBX: init ERROR, no response from RISC %c\n", 'A' + risc_id);
 		return -EIO;
 	}
-	dprintk("MBX: initialized");
+	dprintk("MBX: initialized\n");
 	return 0;
 }
 
@@ -531,30 +539,27 @@ static int dib9000_mbx_send_attr(struct
 		return -EINVAL;
 
 	if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	tmp = MAX_MAILBOX_TRY;
 	do {
 		size = dib9000_read_word_attr(state, 1043, attr) & 0xff;
 		if ((size + len + 1) > MBX_MAX_WORDS && --tmp) {
-			dprintk("MBX: RISC mbx full, retrying");
+			dprintk("MBX: RISC mbx full, retrying\n");
 			msleep(100);
 		} else
 			break;
 	} while (1);
 
-	/*dprintk( "MBX: size: %d", size); */
+	/*dprintk( "MBX: size: %d\n", size); */
 
 	if (tmp == 0) {
 		ret = -EINVAL;
 		goto out;
 	}
 #ifdef DUMP_MSG
-	dprintk("--> %02x %d ", id, len + 1);
-	for (i = 0; i < len; i++)
-		dprintk("%04x ", data[i]);
-	dprintk("\n");
+	dprintk("--> %02x %d %*ph\n", id, len + 1, len, data);
 #endif
 
 	/* byte-order conversion - works on big (where it is not necessary) or little endian */
@@ -596,7 +601,7 @@ static u8 dib9000_mbx_read(struct dib900
 		return 0;
 
 	if (mutex_lock_interruptible(&state->platform.risc.mbx_if_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return 0;
 	}
 	if (risc_id == 1)
@@ -622,13 +627,13 @@ static u8 dib9000_mbx_read(struct dib900
 		}
 
 #ifdef DUMP_MSG
-		dprintk("<-- ");
+		dprintk("<--\n");
 		for (i = 0; i < size + 1; i++)
-			dprintk("%04x ", d[i]);
+			dprintk("%04x\n", d[i]);
 		dprintk("\n");
 #endif
 	} else {
-		dprintk("MBX: message is too big for message cache (%d), flushing message", size);
+		dprintk("MBX: message is too big for message cache (%d), flushing message\n", size);
 		size--;		/* Initial word already read */
 		while (size--)
 			dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, 2, attr);
@@ -649,9 +654,11 @@ static int dib9000_risc_debug_buf(struct
 	b[2 * (size - 2) - 1] = '\0';	/* Bullet proof the buffer */
 	if (*b == '~') {
 		b++;
-		dprintk("%s", b);
+		dprintk("%s\n", b);
 	} else
-		dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<empty>");
+		dprintk("RISC%d: %d.%04d %s\n",
+			state->fe_id,
+			ts / 10000, ts % 10000, *b ? b : "<empty>");
 	return 1;
 }
 
@@ -666,7 +673,7 @@ static int dib9000_mbx_fetch_to_cache(st
 		if (*block == 0) {
 			size = dib9000_mbx_read(state, block, 1, attr);
 
-/*                      dprintk( "MBX: fetched %04x message to cache", *block); */
+/*                      dprintk( "MBX: fetched %04x message to cache\n", *block); */
 
 			switch (*block >> 8) {
 			case IN_MSG_DEBUG_BUF:
@@ -686,7 +693,7 @@ static int dib9000_mbx_fetch_to_cache(st
 			return 1;
 		}
 	}
-	dprintk("MBX: no free cache-slot found for new message...");
+	dprintk("MBX: no free cache-slot found for new message...\n");
 	return -1;
 }
 
@@ -706,7 +713,7 @@ static int dib9000_mbx_process(struct di
 		return -1;
 
 	if (mutex_lock_interruptible(&state->platform.risc.mbx_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -1;
 	}
 
@@ -715,7 +722,7 @@ static int dib9000_mbx_process(struct di
 
 	dib9000_read_word_attr(state, 1229, attr);	/* Clear the IRQ */
 /*      if (tmp) */
-/*              dprintk( "cleared IRQ: %x", tmp); */
+/*              dprintk( "cleared IRQ: %x\n", tmp); */
 	mutex_unlock(&state->platform.risc.mbx_lock);
 
 	return ret;
@@ -750,7 +757,7 @@ static int dib9000_mbx_get_message_attr(
 	} while (--timeout);
 
 	if (timeout == 0) {
-		dprintk("waiting for message %d timed out", id);
+		dprintk("waiting for message %d timed out\n", id);
 		return -1;
 	}
 
@@ -770,7 +777,7 @@ static int dib9000_risc_check_version(st
 		return -EIO;
 
 	fw_version = (r[0] << 8) | r[1];
-	dprintk("RISC: ver: %d.%02d (IC: %d)", fw_version >> 10, fw_version & 0x3ff, (r[2] << 8) | r[3]);
+	dprintk("RISC: ver: %d.%02d (IC: %d)\n", fw_version >> 10, fw_version & 0x3ff, (r[2] << 8) | r[3]);
 
 	if ((fw_version >> 10) != 7)
 		return -EINVAL;
@@ -850,40 +857,40 @@ static u16 dib9000_identify(struct i2c_d
 
 	value = dib9000_i2c_read16(client, 896);
 	if (value != 0x01b3) {
-		dprintk("wrong Vendor ID (0x%x)", value);
+		dprintk("wrong Vendor ID (0x%x)\n", value);
 		return 0;
 	}
 
 	value = dib9000_i2c_read16(client, 897);
 	if (value != 0x4000 && value != 0x4001 && value != 0x4002 && value != 0x4003 && value != 0x4004 && value != 0x4005) {
-		dprintk("wrong Device ID (0x%x)", value);
+		dprintk("wrong Device ID (0x%x)\n", value);
 		return 0;
 	}
 
 	/* protect this driver to be used with 7000PC */
 	if (value == 0x4000 && dib9000_i2c_read16(client, 769) == 0x4000) {
-		dprintk("this driver does not work with DiB7000PC");
+		dprintk("this driver does not work with DiB7000PC\n");
 		return 0;
 	}
 
 	switch (value) {
 	case 0x4000:
-		dprintk("found DiB7000MA/PA/MB/PB");
+		dprintk("found DiB7000MA/PA/MB/PB\n");
 		break;
 	case 0x4001:
-		dprintk("found DiB7000HC");
+		dprintk("found DiB7000HC\n");
 		break;
 	case 0x4002:
-		dprintk("found DiB7000MC");
+		dprintk("found DiB7000MC\n");
 		break;
 	case 0x4003:
-		dprintk("found DiB9000A");
+		dprintk("found DiB9000A\n");
 		break;
 	case 0x4004:
-		dprintk("found DiB9000H");
+		dprintk("found DiB9000H\n");
 		break;
 	case 0x4005:
-		dprintk("found DiB9000M");
+		dprintk("found DiB9000M\n");
 		break;
 	}
 
@@ -1013,7 +1020,7 @@ static int dib9000_risc_apb_access_read(
 	if (address >= 1024 || !state->platform.risc.fw_is_running)
 		return -EINVAL;
 
-	/* dprintk( "APB access thru rd fw %d %x", address, attribute); */
+	/* dprintk( "APB access thru rd fw %d %x\n", address, attribute); */
 
 	mb[0] = (u16) address;
 	mb[1] = len / 2;
@@ -1043,7 +1050,7 @@ static int dib9000_risc_apb_access_write
 	if (len > 18)
 		return -EINVAL;
 
-	/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
+	/* dprintk( "APB access thru wr fw %d %x\n", address, attribute); */
 
 	mb[0] = (u16)address;
 	for (i = 0; i + 1 < len; i += 2)
@@ -1191,7 +1198,7 @@ static int dib9000_fw_get_channel(struct
 	int ret = 0;
 
 	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
@@ -1534,7 +1541,7 @@ static int dib9000_fw_set_output_mode(st
 	struct dib9000_state *state = fe->demodulator_priv;
 	u16 outreg, smo_mode;
 
-	dprintk("setting output mode for demod %p to %d", fe, mode);
+	dprintk("setting output mode for demod %p to %d\n", fe, mode);
 
 	switch (mode) {
 	case OUTMODE_MPEG2_PAR_GATED_CLK:
@@ -1556,7 +1563,7 @@ static int dib9000_fw_set_output_mode(st
 		outreg = 0;
 		break;
 	default:
-		dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe[0]);
+		dprintk("Unhandled output_mode passed to be set for demod %p\n", &state->fe[0]);
 		return -EINVAL;
 	}
 
@@ -1590,7 +1597,7 @@ static int dib9000_tuner_xfer(struct i2c
 				len = 16;
 
 			if (dib9000_read_word(state, 790) != 0)
-				dprintk("TunerITF: read busy");
+				dprintk("TunerITF: read busy\n");
 
 			dib9000_write_word(state, 784, (u16) (msg[index_msg].addr));
 			dib9000_write_word(state, 787, (len / 2) - 1);
@@ -1601,7 +1608,7 @@ static int dib9000_tuner_xfer(struct i2c
 				i--;
 
 			if (i == 0)
-				dprintk("TunerITF: read failed");
+				dprintk("TunerITF: read failed\n");
 
 			for (i = 0; i < len; i += 2) {
 				t = dib9000_read_word(state, 785);
@@ -1609,13 +1616,13 @@ static int dib9000_tuner_xfer(struct i2c
 				msg[index_msg].buf[i + 1] = (t) & 0xff;
 			}
 			if (dib9000_read_word(state, 790) != 0)
-				dprintk("TunerITF: read more data than expected");
+				dprintk("TunerITF: read more data than expected\n");
 		} else {
 			i = 1000;
 			while (dib9000_read_word(state, 789) && i)
 				i--;
 			if (i == 0)
-				dprintk("TunerITF: write busy");
+				dprintk("TunerITF: write busy\n");
 
 			len = msg[index_msg].len;
 			if (len > 16)
@@ -1631,7 +1638,7 @@ static int dib9000_tuner_xfer(struct i2c
 			while (dib9000_read_word(state, 791) > 0 && i)
 				i--;
 			if (i == 0)
-				dprintk("TunerITF: write failed");
+				dprintk("TunerITF: write failed\n");
 		}
 	}
 	return num;
@@ -1676,7 +1683,7 @@ static int dib9000_fw_component_bus_xfer
 	}
 
 	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return 0;
 	}
 
@@ -1759,7 +1766,7 @@ static int dib9000_cfg_gpio(struct dib90
 	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
 	dib9000_write_word(st, 774, st->gpio_val);
 
-	dprintk("gpio dir: %04x: gpio val: %04x", st->gpio_dir, st->gpio_val);
+	dprintk("gpio dir: %04x: gpio val: %04x\n", st->gpio_dir, st->gpio_val);
 
 	return 0;
 }
@@ -1779,7 +1786,7 @@ int dib9000_fw_pid_filter_ctrl(struct dv
 
 	if ((state->pid_ctrl_index != -2) && (state->pid_ctrl_index < 9)) {
 		/* postpone the pid filtering cmd */
-		dprintk("pid filter cmd postpone");
+		dprintk("pid filter cmd postpone\n");
 		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;
@@ -1787,14 +1794,14 @@ int dib9000_fw_pid_filter_ctrl(struct dv
 	}
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 
 	val = dib9000_read_word(state, 294 + 1) & 0xffef;
 	val |= (onoff & 0x1) << 4;
 
-	dprintk("PID filter enabled %d", onoff);
+	dprintk("PID filter enabled %d\n", onoff);
 	ret = dib9000_write_word(state, 294 + 1, val);
 	mutex_unlock(&state->demod_lock);
 	return ret;
@@ -1809,7 +1816,7 @@ int dib9000_fw_pid_filter(struct dvb_fro
 
 	if (state->pid_ctrl_index != -2) {
 		/* postpone the pid filtering cmd */
-		dprintk("pid filter postpone");
+		dprintk("pid filter postpone\n");
 		if (state->pid_ctrl_index < 9) {
 			state->pid_ctrl_index++;
 			state->pid_ctrl[state->pid_ctrl_index].cmd = DIB9000_PID_FILTER;
@@ -1817,15 +1824,15 @@ int dib9000_fw_pid_filter(struct dvb_fro
 			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");
+			dprintk("can not add any more pid ctrl cmd\n");
 		return 0;
 	}
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
-	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+	dprintk("Index %x, PID %d, OnOff %d\n", id, pid, onoff);
 	ret = dib9000_write_word(state, 300 + 1 + id,
 			onoff ? (1 << 13) | pid : 0);
 	mutex_unlock(&state->demod_lock);
@@ -1868,7 +1875,7 @@ static int dib9000_sleep(struct dvb_fron
 	int ret = 0;
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
@@ -1899,7 +1906,7 @@ static int dib9000_get_frontend(struct d
 
 	if (state->get_frontend_internal == 0) {
 		if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-			dprintk("could not get the lock");
+			dprintk("could not get the lock\n");
 			return -EINTR;
 		}
 	}
@@ -1907,7 +1914,7 @@ static int dib9000_get_frontend(struct d
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
 		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
 		if (stat & FE_HAS_SYNC) {
-			dprintk("TPS lock on the slave%i", index_frontend);
+			dprintk("TPS lock on the slave%i\n", index_frontend);
 
 			/* synchronize the cache with the other frontends */
 			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c);
@@ -1995,18 +2002,18 @@ static int dib9000_set_frontend(struct d
 
 	/* check that the correct parameters are set */
 	if (state->fe[0]->dtv_property_cache.frequency == 0) {
-		dprintk("dib9000: must specify frequency ");
+		dprintk("dib9000: must specify frequency\n");
 		return 0;
 	}
 
 	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
-		dprintk("dib9000: must specify bandwidth ");
+		dprintk("dib9000: must specify bandwidth\n");
 		return 0;
 	}
 
 	state->pid_ctrl_index = -1; /* postpone the pid filtering cmd */
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return 0;
 	}
 
@@ -2073,14 +2080,14 @@ static int dib9000_set_frontend(struct d
 
 	/* check the tune result */
 	if (exit_condition == 1) {	/* tune failed */
-		dprintk("tune failed");
+		dprintk("tune failed\n");
 		mutex_unlock(&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);
+	dprintk("tune success on frontend%i\n", index_frontend_success);
 
 	/* synchronize all the channel cache */
 	state->get_frontend_internal = 1;
@@ -2169,7 +2176,7 @@ static int dib9000_read_status(struct dv
 	u16 lock = 0, lock_slave = 0;
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
@@ -2202,11 +2209,11 @@ static int dib9000_read_ber(struct dvb_f
 	int ret = 0;
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		ret = -EINTR;
 		goto error;
 	}
@@ -2237,7 +2244,7 @@ static int dib9000_read_signal_strength(
 	int ret = 0;
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	*strength = 0;
@@ -2250,7 +2257,7 @@ static int dib9000_read_signal_strength(
 	}
 
 	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		ret = -EINTR;
 		goto error;
 	}
@@ -2281,7 +2288,7 @@ static u32 dib9000_get_snr(struct dvb_fr
 	u16 val;
 
 	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return 0;
 	}
 	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
@@ -2320,7 +2327,7 @@ static int dib9000_read_snr(struct dvb_f
 	u32 snr_master;
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	snr_master = dib9000_get_snr(fe);
@@ -2345,11 +2352,11 @@ static int dib9000_read_unc_blocks(struc
 	int ret = 0;
 
 	if (mutex_lock_interruptible(&state->demod_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		return -EINTR;
 	}
 	if (mutex_lock_interruptible(&state->platform.risc.mem_mbx_lock) < 0) {
-		dprintk("could not get the lock");
+		dprintk("could not get the lock\n");
 		ret = -EINTR;
 		goto error;
 	}
@@ -2376,12 +2383,12 @@ int dib9000_i2c_enumeration(struct i2c_a
 
 	client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
 	if (!client.i2c_write_buffer) {
-		dprintk("%s: not enough memory", __func__);
+		dprintk("%s: not enough memory\n", __func__);
 		return -ENOMEM;
 	}
 	client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
 	if (!client.i2c_read_buffer) {
-		dprintk("%s: not enough memory", __func__);
+		dprintk("%s: not enough memory\n", __func__);
 		ret = -ENOMEM;
 		goto error_memory;
 	}
@@ -2408,7 +2415,7 @@ int dib9000_i2c_enumeration(struct i2c_a
 		if (dib9000_identify(&client) == 0) {
 			client.i2c_addr = default_addr;
 			if (dib9000_identify(&client) == 0) {
-				dprintk("DiB9000 #%d: not identified", k);
+				dprintk("DiB9000 #%d: not identified\n", k);
 				ret = -EIO;
 				goto error;
 			}
@@ -2417,7 +2424,7 @@ int dib9000_i2c_enumeration(struct i2c_a
 		dib9000_i2c_write16(&client, 1795, (1 << 10) | (4 << 6));
 		dib9000_i2c_write16(&client, 1794, (new_addr << 2) | 2);
 
-		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+		dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
 	}
 
 	for (k = 0; k < no_of_demods; k++) {
@@ -2445,12 +2452,12 @@ int dib9000_set_slave_frontend(struct dv
 	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
 		index_frontend++;
 	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
-		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
+		dprintk("set slave fe %p to index %i\n", fe_slave, index_frontend);
 		state->fe[index_frontend] = fe_slave;
 		return 0;
 	}
 
-	dprintk("too many slave frontend");
+	dprintk("too many slave frontend\n");
 	return -ENOMEM;
 }
 EXPORT_SYMBOL(dib9000_set_slave_frontend);
@@ -2463,12 +2470,12 @@ int dib9000_remove_slave_frontend(struct
 	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
 		index_frontend++;
 	if (index_frontend != 1) {
-		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend - 1], index_frontend - 1);
+		dprintk("remove slave fe %p (index %i)\n", state->fe[index_frontend - 1], index_frontend - 1);
 		state->fe[index_frontend] = NULL;
 		return 0;
 	}
 
-	dprintk("no frontend to be removed");
+	dprintk("no frontend to be removed\n");
 	return -ENODEV;
 }
 EXPORT_SYMBOL(dib9000_remove_slave_frontend);
@@ -2483,7 +2490,7 @@ struct dvb_frontend *dib9000_get_slave_f
 }
 EXPORT_SYMBOL(dib9000_get_slave_frontend);
 
-static struct dvb_frontend_ops dib9000_ops;
+static const struct dvb_frontend_ops dib9000_ops;
 struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg)
 {
 	struct dvb_frontend *fe;
@@ -2560,7 +2567,7 @@ error:
 }
 EXPORT_SYMBOL(dib9000_attach);
 
-static struct dvb_frontend_ops dib9000_ops = {
+static const struct dvb_frontend_ops dib9000_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		 .name = "DiBcom 9000",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dibx000_common.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dibx000_common.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dibx000_common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dibx000_common.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/i2c.h>
 #include <linux/mutex.h>
 #include <linux/module.h>
@@ -8,14 +10,18 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
 
-#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 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");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -41,7 +47,7 @@ static u16 dibx000_read_word(struct dibx
 	u16 ret;
 
 	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return 0;
 	}
 
@@ -59,7 +65,7 @@ static u16 dibx000_read_word(struct dibx
 	mst->msg[1].len = 2;
 
 	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
-		dprintk("i2c read error on %d", reg);
+		dprintk("i2c read error on %d\n", reg);
 
 	ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
 	mutex_unlock(&mst->i2c_buffer_lock);
@@ -192,7 +198,7 @@ static int dibx000_i2c_select_interface(
 					enum dibx000_i2c_interface intf)
 {
 	if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
-		dprintk("selecting interface: %d", intf);
+		dprintk("selecting interface: %d\n", intf);
 		mst->selected_interface = intf;
 		return dibx000_write_word(mst, mst->base_reg + 4, intf);
 	}
@@ -290,7 +296,7 @@ static int dibx000_i2c_gated_gpio67_xfer
 	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");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 
@@ -337,7 +343,7 @@ static int dibx000_i2c_gated_tuner_xfer(
 	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
 
 	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
@@ -391,7 +397,7 @@ struct i2c_adapter *dibx000_get_i2c_adap
 			i2c = &mst->master_i2c_adap_gpio67;
 		break;
 	default:
-		printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
+		pr_err("incorrect I2C interface selected\n");
 		break;
 	}
 
@@ -434,7 +440,7 @@ int dibx000_init_i2c_master(struct dibx0
 
 	mutex_init(&mst->i2c_buffer_lock);
 	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
-		dprintk("could not acquire lock");
+		dprintk("could not acquire lock\n");
 		return -EINVAL;
 	}
 	memset(mst->msg, 0, sizeof(struct i2c_msg));
@@ -456,29 +462,25 @@ int dibx000_init_i2c_master(struct dibx0
 	if (i2c_adapter_init
 			(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
 			 "DiBX000 tuner I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the tuner i2c_adapter\n");
+		pr_err("could not initialize the tuner i2c_adapter\n");
 
 	mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;
 	if (i2c_adapter_init
 			(&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,
 			 "DiBX000 master GPIO12 I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the master i2c_adapter\n");
+		pr_err("could not initialize the master i2c_adapter\n");
 
 	mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;
 	if (i2c_adapter_init
 			(&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,
 			 "DiBX000 master GPIO34 I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the master i2c_adapter\n");
+		pr_err("could not initialize the master i2c_adapter\n");
 
 	mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;
 	if (i2c_adapter_init
 			(&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,
 			 "DiBX000 master GPIO67 I2C bus", mst) != 0)
-		printk(KERN_ERR
-				"DiBX000: could not initialize the master i2c_adapter\n");
+		pr_err("could not initialize the master i2c_adapter\n");
 
 	/* initialize the i2c-master by closing the gate */
 	dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
@@ -500,16 +502,6 @@ void dibx000_exit_i2c_master(struct dibx
 }
 EXPORT_SYMBOL(dibx000_exit_i2c_master);
 
-
-u32 systime(void)
-{
-	struct timespec t;
-
-	t = current_kernel_time();
-	return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
-}
-EXPORT_SYMBOL(systime);
-
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
 MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dibx000_common.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dibx000_common.h
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dibx000_common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dibx000_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -47,8 +47,6 @@ extern void dibx000_exit_i2c_master(stru
 extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
 extern int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed);
 
-extern u32 systime(void);
-
 #define BAND_LBAND 0x01
 #define BAND_UHF   0x02
 #define BAND_VHF   0x04
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c	2016-12-11 17:45:35.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/drx39xyj/drxj.c	2017-02-12 17:31:21.000000000 -0500
@@ -12264,7 +12264,7 @@ static void drx39xxj_release(struct dvb_
 	kfree(state);
 }
 
-static struct dvb_frontend_ops drx39xxj_ops;
+static const struct dvb_frontend_ops drx39xxj_ops;
 
 struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
 {
@@ -12363,7 +12363,7 @@ error:
 }
 EXPORT_SYMBOL(drx39xxj_attach);
 
-static struct dvb_frontend_ops drx39xxj_ops = {
+static const struct dvb_frontend_ops drx39xxj_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		 .name = "Micronas DRX39xxj family Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/drxd_hard.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/drxd_hard.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/drxd_hard.c	2016-12-11 17:46:27.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/drxd_hard.c	2017-02-12 17:32:51.000000000 -0500
@@ -2912,7 +2912,7 @@ static void drxd_release(struct dvb_fron
 	kfree(state);
 }
 
-static struct dvb_frontend_ops drxd_ops = {
+static const struct dvb_frontend_ops drxd_ops = {
 	.delsys = { SYS_DVBT},
 	.info = {
 		 .name = "Micronas DRXD DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/drxk_hard.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/drxk_hard.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/drxk_hard.c	2016-12-11 17:46:28.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/drxk_hard.c	2017-02-12 17:32:52.000000000 -0500
@@ -6737,7 +6737,7 @@ static int drxk_get_tune_settings(struct
 	}
 }
 
-static struct dvb_frontend_ops drxk_ops = {
+static const struct dvb_frontend_ops drxk_ops = {
 	/* .delsys will be filled dynamically */
 	.info = {
 		.name = "DRXK",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/ds3000.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ds3000.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/ds3000.c	2016-12-11 17:45:26.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ds3000.c	2017-02-12 17:31:06.000000000 -0500
@@ -246,8 +246,8 @@ static int ds3000_writereg(struct ds3000
 
 	err = i2c_transfer(state->i2c, &msg, 1);
 	if (err != 1) {
-		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
-			 " value == 0x%02x)\n", __func__, err, reg, data);
+		printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n",
+		       __func__, err, reg, data);
 		return -EREMOTEIO;
 	}
 
@@ -294,8 +294,8 @@ static int ds3000_writeFW(struct ds3000_
 
 		ret = i2c_transfer(state->i2c, &msg, 1);
 		if (ret != 1) {
-			printk(KERN_ERR "%s: write error(err == %i, "
-				"reg == 0x%02x\n", __func__, ret, reg);
+			printk(KERN_ERR "%s: write error(err == %i, reg == 0x%02x\n",
+			       __func__, ret, reg);
 			ret = -EREMOTEIO;
 			goto error;
 		}
@@ -362,8 +362,8 @@ static int ds3000_firmware_ondemand(stru
 				state->i2c->dev.parent);
 	printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__);
 	if (ret) {
-		printk(KERN_ERR "%s: No firmware uploaded (timeout or file not "
-				"found?)\n", __func__);
+		printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n",
+		       __func__);
 		return ret;
 	}
 
@@ -828,7 +828,7 @@ static void ds3000_release(struct dvb_fr
 	kfree(state);
 }
 
-static struct dvb_frontend_ops ds3000_ops;
+static const struct dvb_frontend_ops ds3000_ops;
 
 struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 				    struct i2c_adapter *i2c)
@@ -1102,7 +1102,7 @@ static int ds3000_initfe(struct dvb_fron
 	return 0;
 }
 
-static struct dvb_frontend_ops ds3000_ops = {
+static const struct dvb_frontend_ops ds3000_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name = "Montage Technology DS3000",
@@ -1142,8 +1142,7 @@ static struct dvb_frontend_ops ds3000_op
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
 
-MODULE_DESCRIPTION("DVB Frontend module for Montage Technology "
-			"DS3000 hardware");
+MODULE_DESCRIPTION("DVB Frontend module for Montage Technology DS3000 hardware");
 MODULE_AUTHOR("Konstantin Dimitrov <kosio.dimitrov@gmail.com>");
 MODULE_LICENSE("GPL");
 /*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dvb_dummy_fe.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dvb_dummy_fe.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dvb_dummy_fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dvb_dummy_fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -119,7 +119,7 @@ static void dvb_dummy_fe_release(struct
 	kfree(state);
 }
 
-static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops;
+static const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops;
 
 struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
 {
@@ -136,7 +136,7 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_a
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
+static const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops;
 
 struct dvb_frontend *dvb_dummy_fe_qpsk_attach(void)
 {
@@ -153,7 +153,7 @@ struct dvb_frontend *dvb_dummy_fe_qpsk_a
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
+static const struct dvb_frontend_ops dvb_dummy_fe_qam_ops;
 
 struct dvb_frontend *dvb_dummy_fe_qam_attach(void)
 {
@@ -170,7 +170,7 @@ struct dvb_frontend *dvb_dummy_fe_qam_at
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
+static const struct dvb_frontend_ops dvb_dummy_fe_ofdm_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "Dummy DVB-T",
@@ -201,7 +201,7 @@ static struct dvb_frontend_ops dvb_dummy
 	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
 };
 
-static struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
+static const struct dvb_frontend_ops dvb_dummy_fe_qam_ops = {
 	.delsys = { SYS_DVBC_ANNEX_A },
 	.info = {
 		.name			= "Dummy DVB-C",
@@ -230,7 +230,7 @@ static struct dvb_frontend_ops dvb_dummy
 	.read_ucblocks = dvb_dummy_fe_read_ucblocks,
 };
 
-static struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
+static const struct dvb_frontend_ops dvb_dummy_fe_qpsk_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "Dummy DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/dvb-pll.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dvb-pll.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/dvb-pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/dvb-pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/dvb/frontend.h>
@@ -25,6 +27,9 @@
 
 #include "dvb-pll.h"
 
+#define dprintk(fmt, arg...) \
+	printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg)
+
 struct dvb_pll_priv {
 	/* pll number */
 	int nr;
@@ -362,7 +367,7 @@ static void opera1_bw(struct dvb_fronten
 
 	result = i2c_transfer(priv->i2c, &msg, 1);
 	if (result != 1)
-		printk(KERN_ERR "%s: i2c_transfer failed:%d",
+		pr_err("%s: i2c_transfer failed:%d",
 			__func__, result);
 
 	if (b_w <= 10000)
@@ -432,7 +437,7 @@ static void samsung_dtos403ih102a_set(st
 
 	result = i2c_transfer(priv->i2c, &msg, 1);
 	if (result != 1)
-		printk(KERN_ERR "%s: i2c_transfer failed:%d",
+		pr_err("%s: i2c_transfer failed:%d",
 			__func__, result);
 
 	buf[2] = 0x9e;
@@ -578,7 +583,7 @@ static int dvb_pll_configure(struct dvb_
 	}
 
 	if (debug)
-		printk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
+		dprintk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
 		       frequency, i, desc->count);
 	if (i == desc->count)
 		return -EINVAL;
@@ -594,18 +599,17 @@ static int dvb_pll_configure(struct dvb_
 		desc->set(fe, buf);
 
 	if (debug)
-		printk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
+		dprintk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
 		       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
 
 	// calculate the frequency we set it to
 	return (div * desc->entries[i].stepsize) - desc->iffreq;
 }
 
-static int dvb_pll_release(struct dvb_frontend *fe)
+static void dvb_pll_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int dvb_pll_sleep(struct dvb_frontend *fe)
@@ -803,10 +807,10 @@ struct dvb_frontend *dvb_pll_attach(stru
 	fe->tuner_priv = priv;
 
 	if ((debug) || (id[priv->nr] == pll_desc_id)) {
-		printk("dvb-pll[%d]", priv->nr);
+		dprintk("dvb-pll[%d]", priv->nr);
 		if (i2c != NULL)
-			printk(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
-		printk(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
+			pr_cont(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
+		pr_cont(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
 		       id[priv->nr] == pll_desc_id ?
 				"insmod option" : "autodetected");
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/ec100.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ec100.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/ec100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ec100.c	2017-02-12 16:03:20.000000000 -0500
@@ -280,7 +280,7 @@ static void ec100_release(struct dvb_fro
 	kfree(state);
 }
 
-static struct dvb_frontend_ops ec100_ops;
+static const struct dvb_frontend_ops ec100_ops;
 
 struct dvb_frontend *ec100_attach(const struct ec100_config *config,
 	struct i2c_adapter *i2c)
@@ -315,7 +315,7 @@ error:
 }
 EXPORT_SYMBOL(ec100_attach);
 
-static struct dvb_frontend_ops ec100_ops = {
+static const struct dvb_frontend_ops ec100_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "E3C EC100 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/gp8psk-fe.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/gp8psk-fe.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/gp8psk-fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/gp8psk-fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -323,7 +323,7 @@ static void gp8psk_fe_release(struct dvb
 	kfree(st);
 }
 
-static struct dvb_frontend_ops gp8psk_fe_ops;
+static const struct dvb_frontend_ops gp8psk_fe_ops;
 
 struct dvb_frontend *gp8psk_fe_attach(const struct gp8psk_fe_ops *ops,
 				      void *priv, bool is_rev1)
@@ -351,7 +351,7 @@ struct dvb_frontend *gp8psk_fe_attach(co
 }
 EXPORT_SYMBOL_GPL(gp8psk_fe_attach);
 
-static struct dvb_frontend_ops gp8psk_fe_ops = {
+static const struct dvb_frontend_ops gp8psk_fe_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "Genpix DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/hd29l2.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/hd29l2.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/hd29l2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/hd29l2.c	2017-02-12 16:03:20.000000000 -0500
@@ -793,7 +793,7 @@ static void hd29l2_release(struct dvb_fr
 	kfree(priv);
 }
 
-static struct dvb_frontend_ops hd29l2_ops;
+static const struct dvb_frontend_ops hd29l2_ops;
 
 struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
 	struct i2c_adapter *i2c)
@@ -828,7 +828,7 @@ err:
 }
 EXPORT_SYMBOL(hd29l2_attach);
 
-static struct dvb_frontend_ops hd29l2_ops = {
+static const struct dvb_frontend_ops hd29l2_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "HDIC HD29L2 DMB-TH",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/helene.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/helene.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/helene.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/helene.c	2017-02-12 16:03:20.000000000 -0500
@@ -434,14 +434,13 @@ static int helene_init(struct dvb_fronte
 	return helene_leave_power_save(priv);
 }
 
-static int helene_release(struct dvb_frontend *fe)
+static void helene_release(struct dvb_frontend *fe)
 {
 	struct helene_priv *priv = fe->tuner_priv;
 
 	dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int helene_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/horus3a.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/horus3a.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/horus3a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/horus3a.c	2017-02-12 16:03:20.000000000 -0500
@@ -151,14 +151,13 @@ static int horus3a_init(struct dvb_front
 	return 0;
 }
 
-static int horus3a_release(struct dvb_frontend *fe)
+static void horus3a_release(struct dvb_frontend *fe)
 {
 	struct horus3a_priv *priv = fe->tuner_priv;
 
 	dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int horus3a_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/itd1000.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/itd1000.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/itd1000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/itd1000.c	2017-02-12 16:03:20.000000000 -0500
@@ -348,11 +348,10 @@ static int itd1000_sleep(struct dvb_fron
 	return 0;
 }
 
-static int itd1000_release(struct dvb_frontend *fe)
+static void itd1000_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops itd1000_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/ix2505v.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ix2505v.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/ix2505v.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ix2505v.c	2017-02-12 16:03:20.000000000 -0500
@@ -94,14 +94,13 @@ static int ix2505v_write(struct ix2505v_
 	return 0;
 }
 
-static int ix2505v_release(struct dvb_frontend *fe)
+static void ix2505v_release(struct dvb_frontend *fe)
 {
 	struct ix2505v_state *state = fe->tuner_priv;
 
 	fe->tuner_priv = NULL;
 	kfree(state);
 
-	return 0;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/Kconfig
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -642,7 +642,7 @@ config DVB_S5H1409
 	  to support this frontend.
 
 config DVB_AU8522
-	depends on I2C
+	depends on DVB_CORE && I2C
 	tristate
 
 config DVB_AU8522_DTV
@@ -656,7 +656,7 @@ config DVB_AU8522_DTV
 
 config DVB_AU8522_V4L
 	tristate "Auvitek AU8522 based ATV demod"
-	depends on VIDEO_V4L2 && I2C
+	depends on VIDEO_V4L2 && DVB_CORE && I2C
 	select DVB_AU8522
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
@@ -722,7 +722,7 @@ config DVB_PLL
 
 config DVB_TUNER_DIB0070
 	tristate "DiBcom DiB0070 silicon base-band tuner"
-	depends on I2C
+	depends on DVB_CORE && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  A driver for the silicon baseband tuner DiB0070 from DiBcom.
@@ -731,7 +731,7 @@ config DVB_TUNER_DIB0070
 
 config DVB_TUNER_DIB0090
 	tristate "DiBcom DiB0090 silicon base-band tuner"
-	depends on I2C
+	depends on DVB_CORE && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	  A driver for the silicon baseband tuner DiB0090 from DiBcom.
@@ -879,5 +879,6 @@ comment "Tools to develop new frontends"
 
 config DVB_DUMMY_FE
 	tristate "Dummy frontend driver"
+	depends on DVB_CORE
 	default n
 endmenu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/l64781.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/l64781.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/l64781.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/l64781.c	2017-02-12 16:03:20.000000000 -0500
@@ -496,7 +496,7 @@ static void l64781_release(struct dvb_fr
 	kfree(state);
 }
 
-static struct dvb_frontend_ops l64781_ops;
+static const struct dvb_frontend_ops l64781_ops;
 
 struct dvb_frontend* l64781_attach(const struct l64781_config* config,
 				   struct i2c_adapter* i2c)
@@ -571,7 +571,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops l64781_ops = {
+static const struct dvb_frontend_ops l64781_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "LSI L64781 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/lg2160.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lg2160.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/lg2160.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lg2160.c	2017-02-12 16:03:20.000000000 -0500
@@ -1359,7 +1359,7 @@ static void lg216x_release(struct dvb_fr
 	kfree(state);
 }
 
-static struct dvb_frontend_ops lg2160_ops = {
+static const struct dvb_frontend_ops lg2160_ops = {
 	.delsys = { SYS_ATSCMH },
 	.info = {
 		.name = "LG Electronics LG2160 ATSC/MH Frontend",
@@ -1387,7 +1387,7 @@ static struct dvb_frontend_ops lg2160_op
 	.release              = lg216x_release,
 };
 
-static struct dvb_frontend_ops lg2161_ops = {
+static const struct dvb_frontend_ops lg2161_ops = {
 	.delsys = { SYS_ATSCMH },
 	.info = {
 		.name = "LG Electronics LG2161 ATSC/MH Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgdt3305.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgdt3305.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgdt3305.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgdt3305.c	2017-02-12 16:03:20.000000000 -0500
@@ -1103,8 +1103,8 @@ static void lgdt3305_release(struct dvb_
 	kfree(state);
 }
 
-static struct dvb_frontend_ops lgdt3304_ops;
-static struct dvb_frontend_ops lgdt3305_ops;
+static const struct dvb_frontend_ops lgdt3304_ops;
+static const struct dvb_frontend_ops lgdt3305_ops;
 
 struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
 				     struct i2c_adapter *i2c_adap)
@@ -1164,7 +1164,7 @@ fail:
 }
 EXPORT_SYMBOL(lgdt3305_attach);
 
-static struct dvb_frontend_ops lgdt3304_ops = {
+static const struct dvb_frontend_ops lgdt3304_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name = "LG Electronics LGDT3304 VSB/QAM Frontend",
@@ -1187,7 +1187,7 @@ static struct dvb_frontend_ops lgdt3304_
 	.release              = lgdt3305_release,
 };
 
-static struct dvb_frontend_ops lgdt3305_ops = {
+static const struct dvb_frontend_ops lgdt3305_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgdt3306a.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgdt3306a.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgdt3306a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgdt3306a.c	2017-02-12 16:03:20.000000000 -0500
@@ -1767,7 +1767,7 @@ static void lgdt3306a_release(struct dvb
 	kfree(state);
 }
 
-static struct dvb_frontend_ops lgdt3306a_ops;
+static const struct dvb_frontend_ops lgdt3306a_ops;
 
 struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
 				      struct i2c_adapter *i2c_adap)
@@ -2103,7 +2103,7 @@ static void lgdt3306a_DumpRegs(struct lg
 
 
 
-static struct dvb_frontend_ops lgdt3306a_ops = {
+static const struct dvb_frontend_ops lgdt3306a_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name = "LG Electronics LGDT3306A VSB/QAM Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgdt330x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgdt330x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgdt330x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgdt330x.c	2017-02-12 16:03:20.000000000 -0500
@@ -405,8 +405,7 @@ static int lgdt330x_set_parameters(struc
 			return -1;
 		}
 		if (err < 0)
-			printk(KERN_WARNING "lgdt330x: %s: error blasting "
-			       "bytes to lgdt3303 for modulation type(%d)\n",
+			printk(KERN_WARNING "lgdt330x: %s: error blasting bytes to lgdt3303 for modulation type(%d)\n",
 			       __func__, p->modulation);
 
 		/*
@@ -729,8 +728,8 @@ static void lgdt330x_release(struct dvb_
 	kfree(state);
 }
 
-static struct dvb_frontend_ops lgdt3302_ops;
-static struct dvb_frontend_ops lgdt3303_ops;
+static const struct dvb_frontend_ops lgdt3302_ops;
+static const struct dvb_frontend_ops lgdt3303_ops;
 
 struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
 				     struct i2c_adapter* i2c)
@@ -775,7 +774,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops lgdt3302_ops = {
+static const struct dvb_frontend_ops lgdt3302_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name= "LG Electronics LGDT3302 VSB/QAM Frontend",
@@ -798,7 +797,7 @@ static struct dvb_frontend_ops lgdt3302_
 	.release              = lgdt330x_release,
 };
 
-static struct dvb_frontend_ops lgdt3303_ops = {
+static const struct dvb_frontend_ops lgdt3303_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name= "LG Electronics LGDT3303 VSB/QAM Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgs8gl5.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgs8gl5.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgs8gl5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgs8gl5.c	2017-02-12 16:03:20.000000000 -0500
@@ -376,7 +376,7 @@ lgs8gl5_release(struct dvb_frontend *fe)
 }
 
 
-static struct dvb_frontend_ops lgs8gl5_ops;
+static const struct dvb_frontend_ops lgs8gl5_ops;
 
 
 struct dvb_frontend*
@@ -412,7 +412,7 @@ error:
 EXPORT_SYMBOL(lgs8gl5_attach);
 
 
-static struct dvb_frontend_ops lgs8gl5_ops = {
+static const struct dvb_frontend_ops lgs8gl5_ops = {
 	.delsys = { SYS_DTMB },
 	.info = {
 		.name			= "Legend Silicon LGS-8GL5 DMB-TH",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgs8gxx.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgs8gxx.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/lgs8gxx.c	2016-12-11 17:45:38.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/lgs8gxx.c	2017-02-12 17:31:26.000000000 -0500
@@ -985,7 +985,7 @@ static int lgs8gxx_i2c_gate_ctrl(struct
 	return lgs8gxx_write_reg(priv, 0x01, 0);
 }
 
-static struct dvb_frontend_ops lgs8gxx_ops = {
+static const struct dvb_frontend_ops lgs8gxx_ops = {
 	.delsys = { SYS_DTMB },
 	.info = {
 		.name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/m88ds3103.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/m88ds3103.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/m88ds3103.c	2016-12-11 17:45:41.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/m88ds3103.c	2017-02-12 17:31:34.000000000 -0500
@@ -16,7 +16,7 @@
 
 #include "m88ds3103_priv.h"
 
-static struct dvb_frontend_ops m88ds3103_ops;
+static const struct dvb_frontend_ops m88ds3103_ops;
 
 /* write single register with mask */
 static int m88ds3103_update_bits(struct m88ds3103_dev *dev,
@@ -1295,7 +1295,7 @@ struct dvb_frontend *m88ds3103_attach(co
 }
 EXPORT_SYMBOL(m88ds3103_attach);
 
-static struct dvb_frontend_ops m88ds3103_ops = {
+static const struct dvb_frontend_ops m88ds3103_ops = {
 	.delsys = {SYS_DVBS, SYS_DVBS2},
 	.info = {
 		.name = "Montage Technology M88DS3103",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/m88rs2000.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/m88rs2000.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/m88rs2000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/m88rs2000.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,8 +75,8 @@ static int m88rs2000_writereg(struct m88
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
+		deb_info("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			 __func__, reg, data, ret);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -618,10 +618,9 @@ static int m88rs2000_set_frontend(struct
 	state->no_lock_count = 0;
 
 	if (c->delivery_system != SYS_DVBS) {
-			deb_info("%s: unsupported delivery "
-				"system selected (%d)\n",
-				__func__, c->delivery_system);
-			return -EOPNOTSUPP;
+		deb_info("%s: unsupported delivery system selected (%d)\n",
+			 __func__, c->delivery_system);
+		return -EOPNOTSUPP;
 	}
 
 	/* Set Tuner */
@@ -753,7 +752,7 @@ static void m88rs2000_release(struct dvb
 	kfree(state);
 }
 
-static struct dvb_frontend_ops m88rs2000_ops = {
+static const struct dvb_frontend_ops m88rs2000_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "M88RS2000 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/mb86a16.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mb86a16.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/mb86a16.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mb86a16.c	2017-02-12 16:03:20.000000000 -0500
@@ -1816,7 +1816,7 @@ static enum dvbfe_algo mb86a16_frontend_
 	return DVBFE_ALGO_CUSTOM;
 }
 
-static struct dvb_frontend_ops mb86a16_ops = {
+static const struct dvb_frontend_ops mb86a16_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "Fujitsu MB86A16 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/mb86a20s.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mb86a20s.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/mb86a20s.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mb86a20s.c	2017-02-12 16:03:20.000000000 -0500
@@ -1967,6 +1967,7 @@ static int mb86a20s_read_status_and_stat
 	if (status_nr < 0) {
 		dev_err(&state->i2c->dev,
 			"%s: Can't read frontend lock status\n", __func__);
+		rc = status_nr;
 		goto error;
 	}
 
@@ -2059,7 +2060,7 @@ static int mb86a20s_get_frontend_algo(st
         return DVBFE_ALGO_HW;
 }
 
-static struct dvb_frontend_ops mb86a20s_ops;
+static const struct dvb_frontend_ops mb86a20s_ops;
 
 struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
 				    struct i2c_adapter *i2c)
@@ -2107,7 +2108,7 @@ error:
 }
 EXPORT_SYMBOL(mb86a20s_attach);
 
-static struct dvb_frontend_ops mb86a20s_ops = {
+static const struct dvb_frontend_ops mb86a20s_ops = {
 	.delsys = { SYS_ISDBT },
 	/* Use dib8000 values per default */
 	.info = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/mn88472.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mn88472.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/mn88472.c	2016-12-11 17:46:30.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mn88472.c	2017-02-12 17:32:57.000000000 -0500
@@ -411,7 +411,7 @@ err:
 	return ret;
 }
 
-static struct dvb_frontend_ops mn88472_ops = {
+static const struct dvb_frontend_ops mn88472_ops = {
 	.delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
 	.info = {
 		.name = "Panasonic MN88472",
@@ -488,18 +488,6 @@ static int mn88472_probe(struct i2c_clie
 		goto err_kfree;
 	}
 
-	/* Check demod answers with correct chip id */
-	ret = regmap_read(dev->regmap[0], 0xff, &utmp);
-	if (ret)
-		goto err_regmap_0_regmap_exit;
-
-	dev_dbg(&client->dev, "chip id=%02x\n", utmp);
-
-	if (utmp != 0x02) {
-		ret = -ENODEV;
-		goto err_regmap_0_regmap_exit;
-	}
-
 	/*
 	 * Chip has three I2C addresses for different register banks. Used
 	 * addresses are 0x18, 0x1a and 0x1c. We register two dummy clients,
@@ -536,6 +524,18 @@ static int mn88472_probe(struct i2c_clie
 	}
 	i2c_set_clientdata(dev->client[2], dev);
 
+	/* Check demod answers with correct chip id */
+	ret = regmap_read(dev->regmap[2], 0xff, &utmp);
+	if (ret)
+		goto err_regmap_2_regmap_exit;
+
+	dev_dbg(&client->dev, "chip id=%02x\n", utmp);
+
+	if (utmp != 0x02) {
+		ret = -ENODEV;
+		goto err_regmap_2_regmap_exit;
+	}
+
 	/* Sleep because chip is active by default */
 	ret = regmap_write(dev->regmap[2], 0x05, 0x3e);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/mn88473.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mn88473.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/mn88473.c	2016-12-11 17:46:35.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mn88473.c	2017-02-12 17:33:04.000000000 -0500
@@ -239,62 +239,68 @@ static int mn88473_read_status(struct dv
 	struct i2c_client *client = fe->demodulator_priv;
 	struct mn88473_dev *dev = i2c_get_clientdata(client);
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int ret;
-	unsigned int uitmp;
+	int ret, i, stmp;
+	unsigned int utmp, utmp1, utmp2;
+	u8 buf[5];
 
 	if (!dev->active) {
 		ret = -EAGAIN;
 		goto err;
 	}
 
-	*status = 0;
-
+	/* Lock detection */
 	switch (c->delivery_system) {
 	case SYS_DVBT:
-		ret = regmap_read(dev->regmap[0], 0x62, &uitmp);
+		ret = regmap_read(dev->regmap[0], 0x62, &utmp);
 		if (ret)
 			goto err;
 
-		if (!(uitmp & 0xa0)) {
-			if ((uitmp & 0x0f) >= 0x09)
+		if (!(utmp & 0xa0)) {
+			if ((utmp & 0x0f) >= 0x09)
 				*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 					  FE_HAS_VITERBI | FE_HAS_SYNC |
 					  FE_HAS_LOCK;
-			else if ((uitmp & 0x0f) >= 0x03)
+			else if ((utmp & 0x0f) >= 0x03)
 				*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
+		} else {
+			*status = 0;
 		}
 		break;
 	case SYS_DVBT2:
-		ret = regmap_read(dev->regmap[2], 0x8b, &uitmp);
+		ret = regmap_read(dev->regmap[2], 0x8b, &utmp);
 		if (ret)
 			goto err;
 
-		if (!(uitmp & 0x40)) {
-			if ((uitmp & 0x0f) >= 0x0d)
+		if (!(utmp & 0x40)) {
+			if ((utmp & 0x0f) >= 0x0d)
 				*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 					  FE_HAS_VITERBI | FE_HAS_SYNC |
 					  FE_HAS_LOCK;
-			else if ((uitmp & 0x0f) >= 0x0a)
+			else if ((utmp & 0x0f) >= 0x0a)
 				*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
 					  FE_HAS_VITERBI;
-			else if ((uitmp & 0x0f) >= 0x07)
+			else if ((utmp & 0x0f) >= 0x07)
 				*status = FE_HAS_SIGNAL | FE_HAS_CARRIER;
+		} else {
+			*status = 0;
 		}
 		break;
 	case SYS_DVBC_ANNEX_A:
-		ret = regmap_read(dev->regmap[1], 0x85, &uitmp);
+		ret = regmap_read(dev->regmap[1], 0x85, &utmp);
 		if (ret)
 			goto err;
 
-		if (!(uitmp & 0x40)) {
-			ret = regmap_read(dev->regmap[1], 0x89, &uitmp);
+		if (!(utmp & 0x40)) {
+			ret = regmap_read(dev->regmap[1], 0x89, &utmp);
 			if (ret)
 				goto err;
 
-			if (uitmp & 0x01)
+			if (utmp & 0x01)
 				*status = FE_HAS_SIGNAL | FE_HAS_CARRIER |
-					  FE_HAS_VITERBI | FE_HAS_SYNC |
-					  FE_HAS_LOCK;
+						FE_HAS_VITERBI | FE_HAS_SYNC |
+						FE_HAS_LOCK;
+		} else {
+			*status = 0;
 		}
 		break;
 	default:
@@ -302,6 +308,148 @@ static int mn88473_read_status(struct dv
 		goto err;
 	}
 
+	/* Signal strength */
+	if (*status & FE_HAS_SIGNAL) {
+		for (i = 0; i < 2; i++) {
+			ret = regmap_bulk_read(dev->regmap[2], 0x86 + i,
+					       &buf[i], 1);
+			if (ret)
+				goto err;
+		}
+
+		/* AGCRD[15:6] gives us a 10bit value ([5:0] are always 0) */
+		utmp1 = buf[0] << 8 | buf[1] << 0 | buf[0] >> 2;
+		dev_dbg(&client->dev, "strength=%u\n", utmp1);
+
+		c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+		c->strength.stat[0].uvalue = utmp1;
+	} else {
+		c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	/* CNR */
+	if (*status & FE_HAS_VITERBI && c->delivery_system == SYS_DVBT) {
+		/* DVB-T CNR */
+		ret = regmap_bulk_read(dev->regmap[0], 0x8f, buf, 2);
+		if (ret)
+			goto err;
+
+		utmp = buf[0] << 8 | buf[1] << 0;
+		if (utmp) {
+			/* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */
+			/* log10(65536) = 80807124, 0.2 = 3355443 */
+			stmp = div_u64(((u64)80807124 - intlog10(utmp)
+					+ 3355443) * 10000, 1 << 24);
+			dev_dbg(&client->dev, "cnr=%d value=%u\n", stmp, utmp);
+		} else {
+			stmp = 0;
+		}
+
+		c->cnr.stat[0].svalue = stmp;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+	} else if (*status & FE_HAS_VITERBI &&
+		   c->delivery_system == SYS_DVBT2) {
+		/* DVB-T2 CNR */
+		for (i = 0; i < 3; i++) {
+			ret = regmap_bulk_read(dev->regmap[2], 0xb7 + i,
+					       &buf[i], 1);
+			if (ret)
+				goto err;
+		}
+
+		utmp = buf[1] << 8 | buf[2] << 0;
+		utmp1 = (buf[0] >> 2) & 0x01; /* 0=SISO, 1=MISO */
+		if (utmp) {
+			if (utmp1) {
+				/* CNR[dB]: 10 * (log10(16384 / value) - 0.6) */
+				/* log10(16384) = 70706234, 0.6 = 10066330 */
+				stmp = div_u64(((u64)70706234 - intlog10(utmp)
+						- 10066330) * 10000, 1 << 24);
+				dev_dbg(&client->dev, "cnr=%d value=%u MISO\n",
+					stmp, utmp);
+			} else {
+				/* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */
+				/* log10(65536) = 80807124, 0.2 = 3355443 */
+				stmp = div_u64(((u64)80807124 - intlog10(utmp)
+						+ 3355443) * 10000, 1 << 24);
+				dev_dbg(&client->dev, "cnr=%d value=%u SISO\n",
+					stmp, utmp);
+			}
+		} else {
+			stmp = 0;
+		}
+
+		c->cnr.stat[0].svalue = stmp;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+	} else if (*status & FE_HAS_VITERBI &&
+		   c->delivery_system == SYS_DVBC_ANNEX_A) {
+		/* DVB-C CNR */
+		ret = regmap_bulk_read(dev->regmap[1], 0xa1, buf, 4);
+		if (ret)
+			goto err;
+
+		utmp1 = buf[0] << 8 | buf[1] << 0; /* signal */
+		utmp2 = buf[2] << 8 | buf[3] << 0; /* noise */
+		if (utmp1 && utmp2) {
+			/* CNR[dB]: 10 * log10(8 * (signal / noise)) */
+			/* log10(8) = 15151336 */
+			stmp = div_u64(((u64)15151336 + intlog10(utmp1)
+					- intlog10(utmp2)) * 10000, 1 << 24);
+			dev_dbg(&client->dev, "cnr=%d signal=%u noise=%u\n",
+				stmp, utmp1, utmp2);
+		} else {
+			stmp = 0;
+		}
+
+		c->cnr.stat[0].svalue = stmp;
+		c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+	} else {
+		c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	/* BER */
+	if (*status & FE_HAS_LOCK && (c->delivery_system == SYS_DVBT ||
+				      c->delivery_system == SYS_DVBC_ANNEX_A)) {
+		/* DVB-T & DVB-C BER */
+		ret = regmap_bulk_read(dev->regmap[0], 0x92, buf, 5);
+		if (ret)
+			goto err;
+
+		utmp1 = buf[0] << 16 | buf[1] << 8 | buf[2] << 0;
+		utmp2 = buf[3] << 8 | buf[4] << 0;
+		utmp2 = utmp2 * 8 * 204;
+		dev_dbg(&client->dev, "post_bit_error=%u post_bit_count=%u\n",
+			utmp1, utmp2);
+
+		c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_error.stat[0].uvalue += utmp1;
+		c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+		c->post_bit_count.stat[0].uvalue += utmp2;
+	} else {
+		c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
+	/* PER */
+	if (*status & FE_HAS_LOCK) {
+		ret = regmap_bulk_read(dev->regmap[0], 0xdd, buf, 4);
+		if (ret)
+			goto err;
+
+		utmp1 = buf[0] << 8 | buf[1] << 0;
+		utmp2 = buf[2] << 8 | buf[3] << 0;
+		dev_dbg(&client->dev, "block_error=%u block_count=%u\n",
+			utmp1, utmp2);
+
+		c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->block_error.stat[0].uvalue += utmp1;
+		c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+		c->block_count.stat[0].uvalue += utmp2;
+	} else {
+		c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+		c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	}
+
 	return 0;
 err:
 	dev_dbg(&client->dev, "failed=%d\n", ret);
@@ -312,6 +460,7 @@ static int mn88473_init(struct dvb_front
 {
 	struct i2c_client *client = fe->demodulator_priv;
 	struct mn88473_dev *dev = i2c_get_clientdata(client);
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret, len, remain;
 	unsigned int uitmp;
 	const struct firmware *fw;
@@ -378,6 +527,20 @@ warm:
 
 	dev->active = true;
 
+	/* init stats here to indicate which stats are supported */
+	c->strength.len = 1;
+	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->cnr.len = 1;
+	c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_error.len = 1;
+	c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->post_bit_count.len = 1;
+	c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->block_error.len = 1;
+	c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+	c->block_count.len = 1;
+	c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
 	return 0;
 err_release_firmware:
 	release_firmware(fw);
@@ -485,18 +648,6 @@ static int mn88473_probe(struct i2c_clie
 		goto err_kfree;
 	}
 
-	/* Check demod answers with correct chip id */
-	ret = regmap_read(dev->regmap[0], 0xff, &uitmp);
-	if (ret)
-		goto err_regmap_0_regmap_exit;
-
-	dev_dbg(&client->dev, "chip id=%02x\n", uitmp);
-
-	if (uitmp != 0x03) {
-		ret = -ENODEV;
-		goto err_regmap_0_regmap_exit;
-	}
-
 	/*
 	 * Chip has three I2C addresses for different register banks. Used
 	 * addresses are 0x18, 0x1a and 0x1c. We register two dummy clients,
@@ -533,6 +684,18 @@ static int mn88473_probe(struct i2c_clie
 	}
 	i2c_set_clientdata(dev->client[2], dev);
 
+	/* Check demod answers with correct chip id */
+	ret = regmap_read(dev->regmap[2], 0xff, &uitmp);
+	if (ret)
+		goto err_regmap_2_regmap_exit;
+
+	dev_dbg(&client->dev, "chip id=%02x\n", uitmp);
+
+	if (uitmp != 0x03) {
+		ret = -ENODEV;
+		goto err_regmap_2_regmap_exit;
+	}
+
 	/* Sleep because chip is active by default */
 	ret = regmap_write(dev->regmap[2], 0x05, 0x3e);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/mn88473_priv.h linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mn88473_priv.h
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/mn88473_priv.h	2016-12-11 17:46:37.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mn88473_priv.h	2017-02-12 17:33:07.000000000 -0500
@@ -18,7 +18,9 @@
 #define MN88473_PRIV_H
 
 #include "dvb_frontend.h"
+#include "dvb_math.h"
 #include "mn88473.h"
+#include <linux/math64.h>
 #include <linux/firmware.h>
 #include <linux/regmap.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/mt312.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mt312.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/mt312.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mt312.c	2017-02-12 16:03:20.000000000 -0500
@@ -457,8 +457,8 @@ static int mt312_read_status(struct dvb_
 	if (ret < 0)
 		return ret;
 
-	dprintk("QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x,"
-		" FEC_STATUS: 0x%02x\n", status[0], status[1], status[2]);
+	dprintk("QPSK_STAT_H: 0x%02x, QPSK_STAT_L: 0x%02x, FEC_STATUS: 0x%02x\n",
+		status[0], status[1], status[2]);
 
 	if (status[0] & 0xc0)
 		*s |= FE_HAS_SIGNAL;	/* signal noise ratio */
@@ -748,7 +748,7 @@ static void mt312_release(struct dvb_fro
 }
 
 #define MT312_SYS_CLK		90000000UL	/* 90 MHz */
-static struct dvb_frontend_ops mt312_ops = {
+static const struct dvb_frontend_ops mt312_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name = "Zarlink ???? DVB-S",
@@ -827,8 +827,7 @@ struct dvb_frontend *mt312_attach(const
 		state->freq_mult = 9;
 		break;
 	default:
-		printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313"
-			" are supported chips.\n");
+		printk(KERN_WARNING "Only Zarlink VP310/MT312/ZL10313 are supported chips.\n");
 		goto error;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/mt352.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mt352.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/mt352.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/mt352.c	2017-02-12 16:03:20.000000000 -0500
@@ -538,7 +538,7 @@ static void mt352_release(struct dvb_fro
 	kfree(state);
 }
 
-static struct dvb_frontend_ops mt352_ops;
+static const struct dvb_frontend_ops mt352_ops;
 
 struct dvb_frontend* mt352_attach(const struct mt352_config* config,
 				  struct i2c_adapter* i2c)
@@ -566,7 +566,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops mt352_ops = {
+static const struct dvb_frontend_ops mt352_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "Zarlink MT352 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/nxt200x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/nxt200x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/nxt200x.c	2016-12-11 17:45:46.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/nxt200x.c	2017-02-12 17:31:45.000000000 -0500
@@ -275,8 +275,7 @@ static void nxt200x_microcontroller_stop
 		counter++;
 	}
 
-	pr_warn("Timeout waiting for nxt200x to stop. This is ok after "
-		"firmware upload.\n");
+	pr_warn("Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n");
 	return;
 }
 
@@ -879,8 +878,8 @@ static int nxt2002_init(struct dvb_front
 			       state->i2c->dev.parent);
 	pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
 	if (ret) {
-		pr_err("%s: No firmware uploaded (timeout or file not found?)"
-		       "\n", __func__);
+		pr_err("%s: No firmware uploaded (timeout or file not found?)\n",
+		       __func__);
 		return ret;
 	}
 
@@ -946,8 +945,8 @@ static int nxt2004_init(struct dvb_front
 			       state->i2c->dev.parent);
 	pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
 	if (ret) {
-		pr_err("%s: No firmware uploaded (timeout or file not found?)"
-		       "\n", __func__);
+		pr_err("%s: No firmware uploaded (timeout or file not found?)\n",
+		       __func__);
 		return ret;
 	}
 
@@ -1136,7 +1135,7 @@ static void nxt200x_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops nxt200x_ops;
+static const struct dvb_frontend_ops nxt200x_ops;
 
 struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
 				   struct i2c_adapter* i2c)
@@ -1199,7 +1198,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops nxt200x_ops = {
+static const struct dvb_frontend_ops nxt200x_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name = "Nextwave NXT200X VSB/QAM frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/nxt6000.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/nxt6000.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/nxt6000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/nxt6000.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,8 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -39,7 +41,11 @@ struct nxt6000_state {
 };
 
 static int debug;
-#define dprintk if (debug) printk
+#define dprintk(fmt, arg...) do {					\
+	if (debug)							\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
+} while (0)
 
 static int nxt6000_writereg(struct nxt6000_state* state, u8 reg, u8 data)
 {
@@ -215,119 +221,129 @@ static void nxt6000_dump_status(struct n
 {
 	u8 val;
 
-/*
-	printk("RS_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, RS_COR_STAT));
-	printk("VIT_SYNC_STATUS: 0x%02X\n", nxt6000_readreg(fe, VIT_SYNC_STATUS));
-	printk("OFDM_COR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_COR_STAT));
-	printk("OFDM_SYR_STAT: 0x%02X\n", nxt6000_readreg(fe, OFDM_SYR_STAT));
-	printk("OFDM_TPS_RCVD_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
-	printk("OFDM_TPS_RCVD_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
-	printk("OFDM_TPS_RCVD_3: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
-	printk("OFDM_TPS_RCVD_4: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
-	printk("OFDM_TPS_RESERVED_1: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
-	printk("OFDM_TPS_RESERVED_2: 0x%02X\n", nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
-*/
-	printk("NXT6000 status:");
+#if 0
+	pr_info("RS_COR_STAT: 0x%02X\n",
+		nxt6000_readreg(fe, RS_COR_STAT));
+	pr_info("VIT_SYNC_STATUS: 0x%02X\n",
+		nxt6000_readreg(fe, VIT_SYNC_STATUS));
+	pr_info("OFDM_COR_STAT: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_COR_STAT));
+	pr_info("OFDM_SYR_STAT: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_SYR_STAT));
+	pr_info("OFDM_TPS_RCVD_1: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_TPS_RCVD_1));
+	pr_info("OFDM_TPS_RCVD_2: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_TPS_RCVD_2));
+	pr_info("OFDM_TPS_RCVD_3: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_TPS_RCVD_3));
+	pr_info("OFDM_TPS_RCVD_4: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_TPS_RCVD_4));
+	pr_info("OFDM_TPS_RESERVED_1: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_TPS_RESERVED_1));
+	pr_info("OFDM_TPS_RESERVED_2: 0x%02X\n",
+		nxt6000_readreg(fe, OFDM_TPS_RESERVED_2));
+#endif
+	pr_info("NXT6000 status:");
 
 	val = nxt6000_readreg(state, RS_COR_STAT);
 
-	printk(" DATA DESCR LOCK: %d,", val & 0x01);
-	printk(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01);
+	pr_cont(" DATA DESCR LOCK: %d,", val & 0x01);
+	pr_cont(" DATA SYNC LOCK: %d,", (val >> 1) & 0x01);
 
 	val = nxt6000_readreg(state, VIT_SYNC_STATUS);
 
-	printk(" VITERBI LOCK: %d,", (val >> 7) & 0x01);
+	pr_cont(" VITERBI LOCK: %d,", (val >> 7) & 0x01);
 
 	switch ((val >> 4) & 0x07) {
 
 	case 0x00:
-		printk(" VITERBI CODERATE: 1/2,");
+		pr_cont(" VITERBI CODERATE: 1/2,");
 		break;
 
 	case 0x01:
-		printk(" VITERBI CODERATE: 2/3,");
+		pr_cont(" VITERBI CODERATE: 2/3,");
 		break;
 
 	case 0x02:
-		printk(" VITERBI CODERATE: 3/4,");
+		pr_cont(" VITERBI CODERATE: 3/4,");
 		break;
 
 	case 0x03:
-		printk(" VITERBI CODERATE: 5/6,");
+		pr_cont(" VITERBI CODERATE: 5/6,");
 		break;
 
 	case 0x04:
-		printk(" VITERBI CODERATE: 7/8,");
+		pr_cont(" VITERBI CODERATE: 7/8,");
 		break;
 
 	default:
-		printk(" VITERBI CODERATE: Reserved,");
+		pr_cont(" VITERBI CODERATE: Reserved,");
 
 	}
 
 	val = nxt6000_readreg(state, OFDM_COR_STAT);
 
-	printk(" CHCTrack: %d,", (val >> 7) & 0x01);
-	printk(" TPSLock: %d,", (val >> 6) & 0x01);
-	printk(" SYRLock: %d,", (val >> 5) & 0x01);
-	printk(" AGCLock: %d,", (val >> 4) & 0x01);
+	pr_cont(" CHCTrack: %d,", (val >> 7) & 0x01);
+	pr_cont(" TPSLock: %d,", (val >> 6) & 0x01);
+	pr_cont(" SYRLock: %d,", (val >> 5) & 0x01);
+	pr_cont(" AGCLock: %d,", (val >> 4) & 0x01);
 
 	switch (val & 0x0F) {
 
 	case 0x00:
-		printk(" CoreState: IDLE,");
+		pr_cont(" CoreState: IDLE,");
 		break;
 
 	case 0x02:
-		printk(" CoreState: WAIT_AGC,");
+		pr_cont(" CoreState: WAIT_AGC,");
 		break;
 
 	case 0x03:
-		printk(" CoreState: WAIT_SYR,");
+		pr_cont(" CoreState: WAIT_SYR,");
 		break;
 
 	case 0x04:
-		printk(" CoreState: WAIT_PPM,");
+		pr_cont(" CoreState: WAIT_PPM,");
 		break;
 
 	case 0x01:
-		printk(" CoreState: WAIT_TRL,");
+		pr_cont(" CoreState: WAIT_TRL,");
 		break;
 
 	case 0x05:
-		printk(" CoreState: WAIT_TPS,");
+		pr_cont(" CoreState: WAIT_TPS,");
 		break;
 
 	case 0x06:
-		printk(" CoreState: MONITOR_TPS,");
+		pr_cont(" CoreState: MONITOR_TPS,");
 		break;
 
 	default:
-		printk(" CoreState: Reserved,");
+		pr_cont(" CoreState: Reserved,");
 
 	}
 
 	val = nxt6000_readreg(state, OFDM_SYR_STAT);
 
-	printk(" SYRLock: %d,", (val >> 4) & 0x01);
-	printk(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K");
+	pr_cont(" SYRLock: %d,", (val >> 4) & 0x01);
+	pr_cont(" SYRMode: %s,", (val >> 2) & 0x01 ? "8K" : "2K");
 
 	switch ((val >> 4) & 0x03) {
 
 	case 0x00:
-		printk(" SYRGuard: 1/32,");
+		pr_cont(" SYRGuard: 1/32,");
 		break;
 
 	case 0x01:
-		printk(" SYRGuard: 1/16,");
+		pr_cont(" SYRGuard: 1/16,");
 		break;
 
 	case 0x02:
-		printk(" SYRGuard: 1/8,");
+		pr_cont(" SYRGuard: 1/8,");
 		break;
 
 	case 0x03:
-		printk(" SYRGuard: 1/4,");
+		pr_cont(" SYRGuard: 1/4,");
 		break;
 	}
 
@@ -336,77 +352,77 @@ static void nxt6000_dump_status(struct n
 	switch ((val >> 4) & 0x07) {
 
 	case 0x00:
-		printk(" TPSLP: 1/2,");
+		pr_cont(" TPSLP: 1/2,");
 		break;
 
 	case 0x01:
-		printk(" TPSLP: 2/3,");
+		pr_cont(" TPSLP: 2/3,");
 		break;
 
 	case 0x02:
-		printk(" TPSLP: 3/4,");
+		pr_cont(" TPSLP: 3/4,");
 		break;
 
 	case 0x03:
-		printk(" TPSLP: 5/6,");
+		pr_cont(" TPSLP: 5/6,");
 		break;
 
 	case 0x04:
-		printk(" TPSLP: 7/8,");
+		pr_cont(" TPSLP: 7/8,");
 		break;
 
 	default:
-		printk(" TPSLP: Reserved,");
+		pr_cont(" TPSLP: Reserved,");
 
 	}
 
 	switch (val & 0x07) {
 
 	case 0x00:
-		printk(" TPSHP: 1/2,");
+		pr_cont(" TPSHP: 1/2,");
 		break;
 
 	case 0x01:
-		printk(" TPSHP: 2/3,");
+		pr_cont(" TPSHP: 2/3,");
 		break;
 
 	case 0x02:
-		printk(" TPSHP: 3/4,");
+		pr_cont(" TPSHP: 3/4,");
 		break;
 
 	case 0x03:
-		printk(" TPSHP: 5/6,");
+		pr_cont(" TPSHP: 5/6,");
 		break;
 
 	case 0x04:
-		printk(" TPSHP: 7/8,");
+		pr_cont(" TPSHP: 7/8,");
 		break;
 
 	default:
-		printk(" TPSHP: Reserved,");
+		pr_cont(" TPSHP: Reserved,");
 
 	}
 
 	val = nxt6000_readreg(state, OFDM_TPS_RCVD_4);
 
-	printk(" TPSMode: %s,", val & 0x01 ? "8K" : "2K");
+	pr_cont(" TPSMode: %s,", val & 0x01 ? "8K" : "2K");
 
 	switch ((val >> 4) & 0x03) {
 
 	case 0x00:
-		printk(" TPSGuard: 1/32,");
+		pr_cont(" TPSGuard: 1/32,");
 		break;
 
 	case 0x01:
-		printk(" TPSGuard: 1/16,");
+		pr_cont(" TPSGuard: 1/16,");
 		break;
 
 	case 0x02:
-		printk(" TPSGuard: 1/8,");
+		pr_cont(" TPSGuard: 1/8,");
 		break;
 
 	case 0x03:
-		printk(" TPSGuard: 1/4,");
+		pr_cont(" TPSGuard: 1/4,");
 		break;
 
 	}
@@ -416,8 +432,8 @@ static void nxt6000_dump_status(struct n
 	val = nxt6000_readreg(state, RF_AGC_STATUS);
 	val = nxt6000_readreg(state, RF_AGC_STATUS);
 
-	printk(" RF AGC LOCK: %d,", (val >> 4) & 0x01);
-	printk("\n");
+	pr_cont(" RF AGC LOCK: %d,", (val >> 4) & 0x01);
+	pr_cont("\n");
 }
 
 static int nxt6000_read_status(struct dvb_frontend *fe, enum fe_status *status)
@@ -548,7 +564,7 @@ static int nxt6000_i2c_gate_ctrl(struct
 	}
 }
 
-static struct dvb_frontend_ops nxt6000_ops;
+static const struct dvb_frontend_ops nxt6000_ops;
 
 struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
 				    struct i2c_adapter* i2c)
@@ -576,7 +592,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops nxt6000_ops = {
+static const struct dvb_frontend_ops nxt6000_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "NxtWave NXT6000 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/or51132.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/or51132.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/or51132.c	2016-12-11 17:45:49.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/or51132.c	2017-02-12 17:31:48.000000000 -0500
@@ -337,15 +337,13 @@ static int or51132_set_parameters(struct
 		       fwname);
 		ret = reject_firmware(&fw, fwname, state->i2c->dev.parent);
 		if (ret) {
-			printk(KERN_WARNING "or51132: No firmware up"
-			       "loaded(timeout or file not found?)\n");
+			printk(KERN_WARNING "or51132: No firmware uploaded(timeout or file not found?)\n");
 			return ret;
 		}
 		ret = or51132_load_firmware(fe, fw);
 		release_firmware(fw);
 		if (ret) {
-			printk(KERN_WARNING "or51132: Writing firmware to "
-			       "device failed!\n");
+			printk(KERN_WARNING "or51132: Writing firmware to device failed!\n");
 			return ret;
 		}
 		printk("or51132: Firmware upload complete.\n");
@@ -556,7 +554,7 @@ static void or51132_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops or51132_ops;
+static const struct dvb_frontend_ops or51132_ops;
 
 struct dvb_frontend* or51132_attach(const struct or51132_config* config,
 				    struct i2c_adapter* i2c)
@@ -580,7 +578,7 @@ struct dvb_frontend* or51132_attach(cons
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops or51132_ops = {
+static const struct dvb_frontend_ops or51132_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name			= "Oren OR51132 VSB/QAM Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/or51211.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/or51211.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/or51211.c	2016-12-11 17:45:51.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/or51211.c	2017-02-12 17:31:53.000000000 -0500
@@ -371,8 +371,7 @@ static int or51211_init(struct dvb_front
 					       "/*(DEBLOBBED)*/");
 		pr_info("Got Hotplug firmware\n");
 		if (ret) {
-			pr_warn("No firmware uploaded "
-				"(timeout or file not found?)\n");
+			pr_warn("No firmware uploaded (timeout or file not found?)\n");
 			return ret;
 		}
 
@@ -502,7 +501,7 @@ static void or51211_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops or51211_ops;
+static const struct dvb_frontend_ops or51211_ops;
 
 struct dvb_frontend* or51211_attach(const struct or51211_config* config,
 				    struct i2c_adapter* i2c)
@@ -526,7 +525,7 @@ struct dvb_frontend* or51211_attach(cons
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops or51211_ops = {
+static const struct dvb_frontend_ops or51211_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name               = "Oren OR51211 VSB Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/rtl2830.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/rtl2830.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/rtl2830.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/rtl2830.c	2017-02-12 16:03:20.000000000 -0500
@@ -548,7 +548,7 @@ static int rtl2830_read_signal_strength(
 	return 0;
 }
 
-static struct dvb_frontend_ops rtl2830_ops = {
+static const struct dvb_frontend_ops rtl2830_ops = {
 	.delsys = {SYS_DVBT},
 	.info = {
 		.name = "Realtek RTL2830 (DVB-T)",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/rtl2832.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/rtl2832.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/rtl2832.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/rtl2832.c	2017-02-12 16:03:20.000000000 -0500
@@ -837,7 +837,7 @@ static int rtl2832_deselect(struct i2c_m
 	return 0;
 }
 
-static struct dvb_frontend_ops rtl2832_ops = {
+static const struct dvb_frontend_ops rtl2832_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "Realtek RTL2832 (DVB-T)",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1409.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1409.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1409.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1409.c	2017-02-12 16:03:20.000000000 -0500
@@ -321,8 +321,8 @@ static int s5h1409_writereg(struct s5h14
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		printk(KERN_ERR "%s: error (reg == 0x%02x, val == 0x%04x, "
-		       "ret == %i)\n", __func__, reg, data, ret);
+		printk(KERN_ERR "%s: error (reg == 0x%02x, val == 0x%04x, ret == %i)\n",
+		       __func__, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
 }
@@ -949,7 +949,7 @@ static void s5h1409_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops s5h1409_ops;
+static const struct dvb_frontend_ops s5h1409_ops;
 
 struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
 				    struct i2c_adapter *i2c)
@@ -995,7 +995,7 @@ error:
 }
 EXPORT_SYMBOL(s5h1409_attach);
 
-static struct dvb_frontend_ops s5h1409_ops = {
+static const struct dvb_frontend_ops s5h1409_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name			= "Samsung S5H1409 QAM/8VSB Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1411.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1411.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1411.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1411.c	2017-02-12 16:03:20.000000000 -0500
@@ -350,8 +350,8 @@ static int s5h1411_writereg(struct s5h14
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
-		       "ret == %i)\n", __func__, addr, reg, data, ret);
+		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, ret == %i)\n",
+		       __func__, addr, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
 }
@@ -864,7 +864,7 @@ static void s5h1411_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops s5h1411_ops;
+static const struct dvb_frontend_ops s5h1411_ops;
 
 struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
 				    struct i2c_adapter *i2c)
@@ -914,7 +914,7 @@ error:
 }
 EXPORT_SYMBOL(s5h1411_attach);
 
-static struct dvb_frontend_ops s5h1411_ops = {
+static const struct dvb_frontend_ops s5h1411_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
 	.info = {
 		.name			= "Samsung S5H1411 QAM/8VSB Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1420.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1420.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1420.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1420.c	2017-02-12 16:03:20.000000000 -0500
@@ -880,7 +880,7 @@ struct i2c_adapter *s5h1420_get_tuner_i2
 }
 EXPORT_SYMBOL(s5h1420_get_tuner_i2c_adapter);
 
-static struct dvb_frontend_ops s5h1420_ops;
+static const struct dvb_frontend_ops s5h1420_ops;
 
 struct dvb_frontend *s5h1420_attach(const struct s5h1420_config *config,
 				    struct i2c_adapter *i2c)
@@ -934,7 +934,7 @@ error:
 }
 EXPORT_SYMBOL(s5h1420_attach);
 
-static struct dvb_frontend_ops s5h1420_ops = {
+static const struct dvb_frontend_ops s5h1420_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name     = "Samsung S5H1420/PnpNetwork PN1010 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1432.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1432.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/s5h1432.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s5h1432.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,8 +63,8 @@ static int s5h1432_writereg(struct s5h14
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, "
-		       "ret == %i)\n", __func__, addr, reg, data, ret);
+		printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, ret == %i)\n",
+		       __func__, addr, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
 }
@@ -341,7 +341,7 @@ static void s5h1432_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops s5h1432_ops;
+static const struct dvb_frontend_ops s5h1432_ops;
 
 struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
 				    struct i2c_adapter *i2c)
@@ -370,7 +370,7 @@ struct dvb_frontend *s5h1432_attach(cons
 }
 EXPORT_SYMBOL(s5h1432_attach);
 
-static struct dvb_frontend_ops s5h1432_ops = {
+static const struct dvb_frontend_ops s5h1432_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		 .name = "Samsung s5h1432 DVB-T Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/s921.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s921.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/s921.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/s921.c	2017-02-12 16:03:20.000000000 -0500
@@ -214,8 +214,8 @@ static int s921_i2c_writereg(struct s921
 
 	rc = i2c_transfer(state->i2c, &msg, 1);
 	if (rc != 1) {
-		printk("%s: writereg rcor(rc == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __func__, rc, reg, data);
+		printk("%s: writereg rcor(rc == %i, reg == 0x%02x, data == 0x%02x)\n",
+		       __func__, rc, reg, data);
 		return rc;
 	}
 
@@ -477,7 +477,7 @@ static void s921_release(struct dvb_fron
 	kfree(state);
 }
 
-static struct dvb_frontend_ops s921_ops;
+static const struct dvb_frontend_ops s921_ops;
 
 struct dvb_frontend *s921_attach(const struct s921_config *config,
 				    struct i2c_adapter *i2c)
@@ -505,7 +505,7 @@ struct dvb_frontend *s921_attach(const s
 }
 EXPORT_SYMBOL(s921_attach);
 
-static struct dvb_frontend_ops s921_ops = {
+static const struct dvb_frontend_ops s921_ops = {
 	.delsys = { SYS_ISDBT },
 	/* Use dib8000 values per default */
 	.info = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/si2165.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/si2165.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/si2165.c	2016-12-11 17:45:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/si2165.c	2017-02-12 17:31:58.000000000 -0500
@@ -978,7 +978,7 @@ static int si2165_set_frontend(struct dv
 	return 0;
 }
 
-static struct dvb_frontend_ops si2165_ops = {
+static const struct dvb_frontend_ops si2165_ops = {
 	.info = {
 		.name = "Silicon Labs ",
 		 /* For DVB-C */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/si21xx.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/si21xx.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/si21xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/si21xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -245,8 +245,8 @@ static int si21_writeregs(struct si21xx_
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
-			"ret == %i)\n", __func__, reg1, data[0], ret);
+		dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, ret == %i)\n",
+			__func__, reg1, data[0], ret);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -265,8 +265,8 @@ static int si21_writereg(struct si21xx_s
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
+		dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, ret == %i)\n",
+			__func__, reg, data, ret);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -866,7 +866,7 @@ static void si21xx_release(struct dvb_fr
 	kfree(state);
 }
 
-static struct dvb_frontend_ops si21xx_ops = {
+static const struct dvb_frontend_ops si21xx_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "SL SI21XX DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/sp8870.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/sp8870.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/sp8870.c	2016-12-11 17:46:04.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/sp8870.c	2017-02-12 17:32:10.000000000 -0500
@@ -545,7 +545,7 @@ static void sp8870_release(struct dvb_fr
 	kfree(state);
 }
 
-static struct dvb_frontend_ops sp8870_ops;
+static const struct dvb_frontend_ops sp8870_ops;
 
 struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
 				   struct i2c_adapter* i2c)
@@ -574,7 +574,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops sp8870_ops = {
+static const struct dvb_frontend_ops sp8870_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "Spase SP8870 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/sp887x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/sp887x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/sp887x.c	2016-12-11 17:46:06.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/sp887x.c	2017-02-12 17:32:14.000000000 -0500
@@ -57,8 +57,7 @@ static int sp887x_writereg (struct sp887
 		if (!(reg == 0xf1a && data == 0x000 &&
 			(ret == -EREMOTEIO || ret == -EFAULT)))
 		{
-			printk("%s: writereg error "
-			       "(reg %03x, data %03x, ret == %i)\n",
+			printk("%s: writereg error (reg %03x, data %03x, ret == %i)\n",
 			       __func__, reg & 0xffff, data & 0xffff, ret);
 			return ret;
 		}
@@ -556,7 +555,7 @@ static void sp887x_release(struct dvb_fr
 	kfree(state);
 }
 
-static struct dvb_frontend_ops sp887x_ops;
+static const struct dvb_frontend_ops sp887x_ops;
 
 struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
 				   struct i2c_adapter* i2c)
@@ -585,7 +584,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops sp887x_ops = {
+static const struct dvb_frontend_ops sp887x_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "Spase SP887x DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stb0899_drv.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stb0899_drv.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stb0899_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stb0899_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -485,15 +485,8 @@ int stb0899_read_regs(struct stb0899_sta
 	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
 		_stb0899_read_reg(state, (reg | 0x00ff));
 
-	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
-		int i;
-
-		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
-		for (i = 0; i < count; i++) {
-			printk(" %02x", buf[i]);
-		}
-		printk("\n");
-	}
+	dprintk(state->verbose, FE_DEBUGREG, 1,
+		"%s [0x%04x]: %*ph", __func__, reg, count, buf);
 
 	return 0;
 err:
@@ -522,14 +515,8 @@ int stb0899_write_regs(struct stb0899_st
 	buf[1] = reg & 0xff;
 	memcpy(&buf[2], data, count);
 
-	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
-		int i;
-
-		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
-		for (i = 0; i < count; i++)
-			printk(" %02x", data[i]);
-		printk("\n");
-	}
+	dprintk(state->verbose, FE_DEBUGREG, 1,
+		"%s [0x%04x]: %*ph", __func__, reg, count, data);
 	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
 
 	/*
@@ -614,13 +601,19 @@ static int stb0899_postproc(struct stb08
 	return 0;
 }
 
-static void stb0899_release(struct dvb_frontend *fe)
+static void stb0899_detach(struct dvb_frontend *fe)
 {
 	struct stb0899_state *state = fe->demodulator_priv;
 
-	dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
 	/* post process event */
 	stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+}
+
+static void stb0899_release(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
 	kfree(state);
 }
 
@@ -1586,7 +1579,7 @@ static enum dvbfe_algo stb0899_frontend_
 	return DVBFE_ALGO_CUSTOM;
 }
 
-static struct dvb_frontend_ops stb0899_ops = {
+static const struct dvb_frontend_ops stb0899_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
 	.info = {
 		.name 			= "STB0899 Multistandard",
@@ -1603,6 +1596,7 @@ static struct dvb_frontend_ops stb0899_o
 					  FE_CAN_QPSK
 	},
 
+	.detach				= stb0899_detach,
 	.release			= stb0899_release,
 	.init				= stb0899_init,
 	.sleep				= stb0899_sleep,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stb6000.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stb6000.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stb6000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stb6000.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,11 +41,10 @@ struct stb6000_priv {
 	u32 frequency;
 };
 
-static int stb6000_release(struct dvb_frontend *fe)
+static void stb6000_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int stb6000_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stb6100.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stb6100.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stb6100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stb6100.c	2017-02-12 16:03:20.000000000 -0500
@@ -61,7 +61,7 @@ struct stb6100_lkup {
 	u8   reg;
 };
 
-static int stb6100_release(struct dvb_frontend *fe);
+static void stb6100_release(struct dvb_frontend *fe);
 
 static const struct stb6100_lkup lkup[] = {
 	{       0,  950000, 0x0a },
@@ -560,14 +560,12 @@ struct dvb_frontend *stb6100_attach(stru
 	return fe;
 }
 
-static int stb6100_release(struct dvb_frontend *fe)
+static void stb6100_release(struct dvb_frontend *fe)
 {
 	struct stb6100_state *state = fe->tuner_priv;
 
 	fe->tuner_priv = NULL;
 	kfree(state);
-
-	return 0;
 }
 
 EXPORT_SYMBOL(stb6100_attach);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0288.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0288.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0288.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0288.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,8 +74,8 @@ static int stv0288_writeregI(struct stv0
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
+		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			__func__, reg, data, ret);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -465,10 +465,9 @@ static int stv0288_set_frontend(struct d
 	dprintk("%s : FE_SET_FRONTEND\n", __func__);
 
 	if (c->delivery_system != SYS_DVBS) {
-			dprintk("%s: unsupported delivery "
-				"system selected (%d)\n",
-				__func__, c->delivery_system);
-			return -EOPNOTSUPP;
+		dprintk("%s: unsupported delivery system selected (%d)\n",
+			__func__, c->delivery_system);
+		return -EOPNOTSUPP;
 	}
 
 	if (state->config->set_ts_params)
@@ -536,7 +535,7 @@ static void stv0288_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops stv0288_ops = {
+static const struct dvb_frontend_ops stv0288_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "ST STV0288 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0297.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0297.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0297.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0297.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,8 +57,8 @@ static int stv0297_writereg(struct stv02
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
+		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			__func__, reg, data, ret);
 
 	return (ret != 1) ? -1 : 0;
 }
@@ -658,7 +658,7 @@ static void stv0297_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops stv0297_ops;
+static const struct dvb_frontend_ops stv0297_ops;
 
 struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
 				    struct i2c_adapter *i2c)
@@ -690,7 +690,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops stv0297_ops = {
+static const struct dvb_frontend_ops stv0297_ops = {
 	.delsys = { SYS_DVBC_ANNEX_A },
 	.info = {
 		 .name = "ST STV0297 DVB-C",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0299.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0299.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0299.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0299.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,8 +88,8 @@ static int stv0299_writeregI (struct stv
 	ret = i2c_transfer (state->i2c, &msg, 1);
 
 	if (ret != 1)
-		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
-			"ret == %i)\n", __func__, reg, data, ret);
+		dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+			__func__, reg, data, ret);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -673,7 +673,7 @@ static void stv0299_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops stv0299_ops;
+static const struct dvb_frontend_ops stv0299_ops;
 
 struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
 				    struct i2c_adapter* i2c)
@@ -713,7 +713,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops stv0299_ops = {
+static const struct dvb_frontend_ops stv0299_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "ST STV0299 DVB-S",
@@ -761,8 +761,7 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 
 MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver");
-MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
-	      "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
+MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(stv0299_attach);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0367.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0367.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0367.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0367.c	2017-02-12 16:03:20.000000000 -0500
@@ -2272,7 +2272,7 @@ static void stv0367_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops stv0367ter_ops = {
+static const struct dvb_frontend_ops stv0367ter_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "ST STV0367 DVB-T",
@@ -3390,7 +3390,7 @@ static int stv0367cab_read_ucblcks(struc
 	return 0;
 };
 
-static struct dvb_frontend_ops stv0367cab_ops = {
+static const struct dvb_frontend_ops stv0367cab_ops = {
 	.delsys = { SYS_DVBC_ANNEX_A },
 	.info = {
 		.name = "ST STV0367 DVB-C",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0900_core.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0900_core.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0900_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0900_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1875,7 +1875,7 @@ static int stv0900_get_frontend(struct d
 	return 0;
 }
 
-static struct dvb_frontend_ops stv0900_ops = {
+static const struct dvb_frontend_ops stv0900_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
 	.info = {
 		.name			= "STV0900 frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0900_sw.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0900_sw.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv0900_sw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv0900_sw.c	2017-02-12 16:03:20.000000000 -0500
@@ -1485,8 +1485,7 @@ static u32 stv0900_search_srate_coarse(s
 		current_step++;
 		direction *= -1;
 
-		dprintk("lock: I2C_DEMOD_MODE_FIELD =0. Search started."
-			" tuner freq=%d agc2=0x%x srate_coarse=%d tmg_cpt=%d\n",
+		dprintk("lock: I2C_DEMOD_MODE_FIELD =0. Search started. tuner freq=%d agc2=0x%x srate_coarse=%d tmg_cpt=%d\n",
 			tuner_freq, agc2_integr, coarse_srate, timingcpt);
 
 		if ((timingcpt >= 5) &&
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv090x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv090x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv090x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv090x.c	2017-02-12 16:03:20.000000000 -0500
@@ -739,14 +739,8 @@ static int stv090x_write_regs(struct stv
 	buf[1] = reg & 0xff;
 	memcpy(&buf[2], data, count);
 
-	if (unlikely(*state->verbose >= FE_DEBUGREG)) {
-		int i;
-
-		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
-		for (i = 0; i < count; i++)
-			printk(" %02x", data[i]);
-		printk("\n");
-	}
+	dprintk(FE_DEBUGREG, 1, "%s [0x%04x]: %*ph",
+		__func__, reg, count, data);
 
 	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
 	if (ret != 1) {
@@ -3698,9 +3692,12 @@ static int stv090x_read_cnr(struct dvb_f
 			}
 			val /= 16;
 			last = ARRAY_SIZE(stv090x_s2cn_tab) - 1;
-			div = stv090x_s2cn_tab[0].read -
-			      stv090x_s2cn_tab[last].read;
-			*cnr = 0xFFFF - ((val * 0xFFFF) / div);
+			div = stv090x_s2cn_tab[last].real -
+			      stv090x_s2cn_tab[3].real;
+			val = stv090x_table_lookup(stv090x_s2cn_tab, last, val);
+			if (val < 0)
+				val = 0;
+			*cnr = val * 0xFFFF / div;
 		}
 		break;
 
@@ -3720,9 +3717,10 @@ static int stv090x_read_cnr(struct dvb_f
 			}
 			val /= 16;
 			last = ARRAY_SIZE(stv090x_s1cn_tab) - 1;
-			div = stv090x_s1cn_tab[0].read -
-			      stv090x_s1cn_tab[last].read;
-			*cnr = 0xFFFF - ((val * 0xFFFF) / div);
+			div = stv090x_s1cn_tab[last].real -
+			      stv090x_s1cn_tab[0].real;
+			val = stv090x_table_lookup(stv090x_s1cn_tab, last, val);
+			*cnr = val * 0xFFFF / div;
 		}
 		break;
 	default:
@@ -4886,7 +4884,7 @@ static int stv090x_set_gpio(struct dvb_f
 	return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
 }
 
-static struct dvb_frontend_ops stv090x_ops = {
+static const struct dvb_frontend_ops stv090x_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
 	.info = {
 		.name			= "STV090x Multistandard",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv6110.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv6110.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv6110.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv6110.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,11 +59,10 @@ static s32 abssub(s32 a, s32 b)
 		return b - a;
 };
 
-static int stv6110_release(struct dvb_frontend *fe)
+static void stv6110_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int stv6110_write_regs(struct dvb_frontend *fe, u8 buf[],
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv6110x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv6110x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/stv6110x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/stv6110x.c	2017-02-12 16:03:20.000000000 -0500
@@ -335,14 +335,12 @@ static int stv6110x_get_status(struct dv
 }
 
 
-static int stv6110x_release(struct dvb_frontend *fe)
+static void stv6110x_release(struct dvb_frontend *fe)
 {
 	struct stv6110x_state *stv6110x = fe->tuner_priv;
 
 	fe->tuner_priv = NULL;
 	kfree(stv6110x);
-
-	return 0;
 }
 
 static const struct dvb_tuner_ops stv6110x_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tc90522.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tc90522.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tc90522.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tc90522.c	2017-02-12 16:03:20.000000000 -0500
@@ -656,7 +656,7 @@ tc90522_master_xfer(struct i2c_adapter *
 	for (i = 0; i < num; i++)
 		if (msgs[i].flags & I2C_M_RD)
 			rd_num++;
-	new_msgs = kmalloc(sizeof(*new_msgs) * (num + rd_num), GFP_KERNEL);
+	new_msgs = kmalloc_array(num + rd_num, sizeof(*new_msgs), GFP_KERNEL);
 	if (!new_msgs)
 		return -ENOMEM;
 
@@ -794,14 +794,13 @@ static int tc90522_probe(struct i2c_clie
 	i2c_set_adapdata(adap, state);
 	ret = i2c_add_adapter(adap);
 	if (ret < 0)
-		goto err;
+		goto free_state;
 	cfg->tuner_i2c = state->cfg.tuner_i2c = adap;
 
 	i2c_set_clientdata(client, &state->cfg);
 	dev_info(&client->dev, "Toshiba TC90522 attached.\n");
 	return 0;
-
-err:
+free_state:
 	kfree(state);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10021.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10021.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10021.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10021.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,8 +77,7 @@ static int _tda10021_writereg (struct td
 
 	ret = i2c_transfer (state->i2c, &msg, 1);
 	if (ret != 1)
-		printk("DVB: TDA10021(%d): %s, writereg error "
-			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+		printk("DVB: TDA10021(%d): %s, writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
 			state->frontend.dvb->num, __func__, reg, data, ret);
 
 	msleep(10);
@@ -444,7 +443,7 @@ static void tda10021_release(struct dvb_
 	kfree(state);
 }
 
-static struct dvb_frontend_ops tda10021_ops;
+static const struct dvb_frontend_ops tda10021_ops;
 
 struct dvb_frontend* tda10021_attach(const struct tda1002x_config* config,
 				     struct i2c_adapter* i2c,
@@ -484,7 +483,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops tda10021_ops = {
+static const struct dvb_frontend_ops tda10021_ops = {
 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
 	.info = {
 		.name = "Philips TDA10021 DVB-C",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10023.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10023.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10023.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10023.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,8 +72,7 @@ static u8 tda10023_readreg (struct tda10
 	ret = i2c_transfer (state->i2c, msg, 2);
 	if (ret != 2) {
 		int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
-		printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error "
-			"(reg == 0x%02x, ret == %i)\n",
+		printk(KERN_ERR "DVB: TDA10023(%d): %s: readreg error (reg == 0x%02x, ret == %i)\n",
 			num, __func__, reg, ret);
 	}
 	return b1[0];
@@ -88,8 +87,7 @@ static int tda10023_writereg (struct tda
 	ret = i2c_transfer (state->i2c, &msg, 1);
 	if (ret != 1) {
 		int num = state->frontend.dvb ? state->frontend.dvb->num : -1;
-		printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error "
-			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+		printk(KERN_ERR "DVB: TDA10023(%d): %s, writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
 			num, __func__, reg, data, ret);
 	}
 	return (ret != 1) ? -EREMOTEIO : 0;
@@ -516,7 +514,7 @@ static void tda10023_release(struct dvb_
 	kfree(state);
 }
 
-static struct dvb_frontend_ops tda10023_ops;
+static const struct dvb_frontend_ops tda10023_ops;
 
 struct dvb_frontend *tda10023_attach(const struct tda10023_config *config,
 				     struct i2c_adapter *i2c,
@@ -573,7 +571,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops tda10023_ops = {
+static const struct dvb_frontend_ops tda10023_ops = {
 	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C },
 	.info = {
 		.name = "Philips TDA10023 DVB-C",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10048.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10048.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10048.c	2016-12-11 17:46:06.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10048.c	2017-02-12 17:32:17.000000000 -0500
@@ -1063,38 +1063,34 @@ static void tda10048_establish_defaults(
 	/* Validate/default the config */
 	if (config->dtv6_if_freq_khz == 0) {
 		config->dtv6_if_freq_khz = TDA10048_IF_4300;
-		printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz "
-			"is not set (defaulting to %d)\n",
+		printk(KERN_WARNING "%s() tda10048_config.dtv6_if_freq_khz is not set (defaulting to %d)\n",
 			__func__,
 			config->dtv6_if_freq_khz);
 	}
 
 	if (config->dtv7_if_freq_khz == 0) {
 		config->dtv7_if_freq_khz = TDA10048_IF_4300;
-		printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz "
-			"is not set (defaulting to %d)\n",
+		printk(KERN_WARNING "%s() tda10048_config.dtv7_if_freq_khz is not set (defaulting to %d)\n",
 			__func__,
 			config->dtv7_if_freq_khz);
 	}
 
 	if (config->dtv8_if_freq_khz == 0) {
 		config->dtv8_if_freq_khz = TDA10048_IF_4300;
-		printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz "
-			"is not set (defaulting to %d)\n",
+		printk(KERN_WARNING "%s() tda10048_config.dtv8_if_freq_khz is not set (defaulting to %d)\n",
 			__func__,
 			config->dtv8_if_freq_khz);
 	}
 
 	if (config->clk_freq_khz == 0) {
 		config->clk_freq_khz = TDA10048_CLK_16000;
-		printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz "
-			"is not set (defaulting to %d)\n",
+		printk(KERN_WARNING "%s() tda10048_config.clk_freq_khz is not set (defaulting to %d)\n",
 			__func__,
 			config->clk_freq_khz);
 	}
 }
 
-static struct dvb_frontend_ops tda10048_ops;
+static const struct dvb_frontend_ops tda10048_ops;
 
 struct dvb_frontend *tda10048_attach(const struct tda10048_config *config,
 	struct i2c_adapter *i2c)
@@ -1156,7 +1152,7 @@ error:
 }
 EXPORT_SYMBOL(tda10048_attach);
 
-static struct dvb_frontend_ops tda10048_ops = {
+static const struct dvb_frontend_ops tda10048_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "NXP TDA10048HN DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda1004x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda1004x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda1004x.c	2016-12-11 17:46:09.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda1004x.c	2017-02-12 17:32:22.000000000 -0500
@@ -1237,7 +1237,7 @@ static void tda1004x_release(struct dvb_
 	kfree(state);
 }
 
-static struct dvb_frontend_ops tda10045_ops = {
+static const struct dvb_frontend_ops tda10045_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "Philips TDA10045H DVB-T",
@@ -1307,7 +1307,7 @@ struct dvb_frontend* tda10045_attach(con
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops tda10046_ops = {
+static const struct dvb_frontend_ops tda10046_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "Philips TDA10046H DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10071.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10071.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10071.c	2016-12-11 17:46:12.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10071.c	2017-02-12 17:32:27.000000000 -0500
@@ -20,7 +20,7 @@
 
 #include "tda10071_priv.h"
 
-static struct dvb_frontend_ops tda10071_ops;
+static const struct dvb_frontend_ops tda10071_ops;
 
 /*
  * XXX: regmap_update_bits() does not fit our needs as it does not support
@@ -1102,7 +1102,7 @@ static int tda10071_get_tune_settings(st
 	return 0;
 }
 
-static struct dvb_frontend_ops tda10071_ops = {
+static const struct dvb_frontend_ops tda10071_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2 },
 	.info = {
 		.name = "NXP TDA10071",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10086.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10086.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda10086.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda10086.c	2017-02-12 16:03:20.000000000 -0500
@@ -706,7 +706,7 @@ static void tda10086_release(struct dvb_
 	kfree(state);
 }
 
-static struct dvb_frontend_ops tda10086_ops = {
+static const struct dvb_frontend_ops tda10086_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name     = "Philips TDA10086 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda18271c2dd.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda18271c2dd.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda18271c2dd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda18271c2dd.c	2017-02-12 16:03:20.000000000 -0500
@@ -1126,11 +1126,10 @@ static int init(struct dvb_frontend *fe)
 	return 0;
 }
 
-static int release(struct dvb_frontend *fe)
+static void release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda665x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda665x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda665x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda665x.c	2017-02-12 16:03:20.000000000 -0500
@@ -197,13 +197,12 @@ static int tda665x_set_params(struct dvb
 	return 0;
 }
 
-static int tda665x_release(struct dvb_frontend *fe)
+static void tda665x_release(struct dvb_frontend *fe)
 {
 	struct tda665x_state *state = fe->tuner_priv;
 
 	fe->tuner_priv = NULL;
 	kfree(state);
-	return 0;
 }
 
 static const struct dvb_tuner_ops tda665x_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda8083.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda8083.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda8083.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda8083.c	2017-02-12 16:03:20.000000000 -0500
@@ -421,7 +421,7 @@ static void tda8083_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops tda8083_ops;
+static const struct dvb_frontend_ops tda8083_ops;
 
 struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
 				    struct i2c_adapter* i2c)
@@ -449,7 +449,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops tda8083_ops = {
+static const struct dvb_frontend_ops tda8083_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "Philips TDA8083 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda8261.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda8261.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda8261.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda8261.c	2017-02-12 16:03:20.000000000 -0500
@@ -152,13 +152,12 @@ static int tda8261_set_params(struct dvb
 	return 0;
 }
 
-static int tda8261_release(struct dvb_frontend *fe)
+static void tda8261_release(struct dvb_frontend *fe)
 {
 	struct tda8261_state *state = fe->tuner_priv;
 
 	fe->tuner_priv = NULL;
 	kfree(state);
-	return 0;
 }
 
 static const struct dvb_tuner_ops tda8261_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda826x.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda826x.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tda826x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tda826x.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,11 +41,10 @@ struct tda826x_priv {
 	u32 frequency;
 };
 
-static int tda826x_release(struct dvb_frontend *fe)
+static void tda826x_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int tda826x_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/ts2020.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ts2020.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/ts2020.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ts2020.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ struct ts2020_reg_val {
 
 static void ts2020_stat_work(struct work_struct *work);
 
-static int ts2020_release(struct dvb_frontend *fe)
+static void ts2020_release(struct dvb_frontend *fe)
 {
 	struct ts2020_priv *priv = fe->tuner_priv;
 	struct i2c_client *client = priv->client;
@@ -64,7 +64,6 @@ static int ts2020_release(struct dvb_fro
 	dev_dbg(&client->dev, "\n");
 
 	i2c_unregister_device(client);
-	return 0;
 }
 
 static int ts2020_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/tua6100.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tua6100.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/tua6100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/tua6100.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,11 +42,10 @@ struct tua6100_priv {
 	u32 frequency;
 };
 
-static int tua6100_release(struct dvb_frontend *fe)
+static void tua6100_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int tua6100_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/ves1820.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ves1820.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/ves1820.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ves1820.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,8 +65,8 @@ static int ves1820_writereg(struct ves18
 	ret = i2c_transfer(state->i2c, &msg, 1);
 
 	if (ret != 1)
-		printk("ves1820: %s(): writereg error (reg == 0x%02x, "
-			"val == 0x%02x, ret == %i)\n", __func__, reg, data, ret);
+		printk("ves1820: %s(): writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n",
+		       __func__, reg, data, ret);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
@@ -84,8 +84,8 @@ static u8 ves1820_readreg(struct ves1820
 	ret = i2c_transfer(state->i2c, msg, 2);
 
 	if (ret != 2)
-		printk("ves1820: %s(): readreg error (reg == 0x%02x, "
-		"ret == %i)\n", __func__, reg, ret);
+		printk("ves1820: %s(): readreg error (reg == 0x%02x, ret == %i)\n",
+		       __func__, reg, ret);
 
 	return b1[0];
 }
@@ -369,7 +369,7 @@ static void ves1820_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops ves1820_ops;
+static const struct dvb_frontend_ops ves1820_ops;
 
 struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
 				    struct i2c_adapter* i2c,
@@ -408,7 +408,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops ves1820_ops = {
+static const struct dvb_frontend_ops ves1820_ops = {
 	.delsys = { SYS_DVBC_ANNEX_A },
 	.info = {
 		.name = "VLSI VES1820 DVB-C",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/ves1x93.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ves1x93.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/ves1x93.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/ves1x93.c	2017-02-12 16:03:20.000000000 -0500
@@ -454,7 +454,7 @@ static int ves1x93_i2c_gate_ctrl(struct
 	}
 }
 
-static struct dvb_frontend_ops ves1x93_ops;
+static const struct dvb_frontend_ops ves1x93_ops;
 
 struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
 				    struct i2c_adapter* i2c)
@@ -512,7 +512,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops ves1x93_ops = {
+static const struct dvb_frontend_ops ves1x93_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "VLSI VES1x93 DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/zl10036.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/zl10036.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/zl10036.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/zl10036.c	2017-02-12 16:03:20.000000000 -0500
@@ -85,8 +85,8 @@ static int zl10036_read_status_reg(struc
 	deb_i2c("R(status): %02x  [FL=%d]\n", status,
 		(status & STATUS_FL) ? 1 : 0);
 	if (status & STATUS_POR)
-		deb_info("%s: Power-On-Reset bit enabled - "
-			"need to initialize the tuner\n", __func__);
+		deb_info("%s: Power-On-Reset bit enabled - need to initialize the tuner\n",
+			 __func__);
 
 	return status;
 }
@@ -134,14 +134,12 @@ static int zl10036_write(struct zl10036_
 	return 0;
 }
 
-static int zl10036_release(struct dvb_frontend *fe)
+static void zl10036_release(struct dvb_frontend *fe)
 {
 	struct zl10036_state *state = fe->tuner_priv;
 
 	fe->tuner_priv = NULL;
 	kfree(state);
-
-	return 0;
 }
 
 static int zl10036_sleep(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/zl10039.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/zl10039.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/zl10039.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/zl10039.c	2017-02-12 16:03:20.000000000 -0500
@@ -152,8 +152,7 @@ static int zl10039_init(struct dvb_front
 	/* Reset logic */
 	ret = zl10039_writereg(state, GENERAL, 0x40);
 	if (ret < 0) {
-		dprintk("Note: i2c write error normal when resetting the "
-			"tuner\n");
+		dprintk("Note: i2c write error normal when resetting the tuner\n");
 	}
 	/* Wake up */
 	ret = zl10039_writereg(state, GENERAL, 0x01);
@@ -245,14 +244,13 @@ error:
 	return ret;
 }
 
-static int zl10039_release(struct dvb_frontend *fe)
+static void zl10039_release(struct dvb_frontend *fe)
 {
 	struct zl10039_state *state = fe->tuner_priv;
 
 	dprintk("%s\n", __func__);
 	kfree(state);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops zl10039_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/dvb-frontends/zl10353.c linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/zl10353.c
--- linux-libre-4.9-gnu/drivers/media/dvb-frontends/zl10353.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/dvb-frontends/zl10353.c	2017-02-12 16:03:20.000000000 -0500
@@ -602,7 +602,7 @@ static void zl10353_release(struct dvb_f
 	kfree(state);
 }
 
-static struct dvb_frontend_ops zl10353_ops;
+static const struct dvb_frontend_ops zl10353_ops;
 
 struct dvb_frontend *zl10353_attach(const struct zl10353_config *config,
 				    struct i2c_adapter *i2c)
@@ -634,7 +634,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops zl10353_ops = {
+static const struct dvb_frontend_ops zl10353_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "Zarlink ZL10353 DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/firewire/firedtv-avc.c linux-libre-4.10-rc8-gnu/drivers/media/firewire/firedtv-avc.c
--- linux-libre-4.9-gnu/drivers/media/firewire/firedtv-avc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/firewire/firedtv-avc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1181,8 +1181,8 @@ int avc_ca_pmt(struct firedtv *fdtv, cha
 		if (es_info_length > 0) {
 			pmt_cmd_id = msg[read_pos++];
 			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
-				dev_err(fdtv->device, "invalid pmt_cmd_id %d "
-					"at stream level\n", pmt_cmd_id);
+				dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",
+					pmt_cmd_id);
 
 			if (es_info_length > sizeof(c->operand) - 4 -
 					     write_pos) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/firewire/firedtv-rc.c linux-libre-4.10-rc8-gnu/drivers/media/firewire/firedtv-rc.c
--- linux-libre-4.9-gnu/drivers/media/firewire/firedtv-rc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/firewire/firedtv-rc.c	2017-02-12 16:03:20.000000000 -0500
@@ -184,8 +184,9 @@ void fdtv_handle_rc(struct firedtv *fdtv
 	else if (code >= 0x4540 && code <= 0x4542)
 		code = oldtable[code - 0x4521];
 	else {
-		printk(KERN_DEBUG "firedtv: invalid key code 0x%04x "
-		       "from remote control\n", code);
+		dev_dbg(fdtv->device,
+			"invalid key code 0x%04x from remote control\n",
+			code);
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/ad5820.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/ad5820.c
--- linux-libre-4.9-gnu/drivers/media/i2c/ad5820.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/ad5820.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,16 +65,17 @@ static int ad5820_write(struct ad5820_de
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&coil->subdev);
 	struct i2c_msg msg;
+	__be16 be_data;
 	int r;
 
 	if (!client->adapter)
 		return -ENODEV;
 
-	data = cpu_to_be16(data);
+	be_data = cpu_to_be16(data);
 	msg.addr  = client->addr;
 	msg.flags = 0;
 	msg.len   = 2;
-	msg.buf   = (u8 *)&data;
+	msg.buf   = (u8 *)&be_data;
 
 	r = i2c_transfer(client->adapter, &msg, 1);
 	if (r < 0) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/adv7170.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7170.c
--- linux-libre-4.9-gnu/drivers/media/i2c/adv7170.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7170.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/adv7175.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7175.c
--- linux-libre-4.9-gnu/drivers/media/i2c/adv7175.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7175.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/adv7511.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7511.c
--- linux-libre-4.9-gnu/drivers/media/i2c/adv7511.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7511.c	2017-02-12 16:03:20.000000000 -0500
@@ -1732,9 +1732,10 @@ static bool adv7511_check_edid_status(st
 static int adv7511_registered(struct v4l2_subdev *sd)
 {
 	struct adv7511_state *state = get_adv7511_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int err;
 
-	err = cec_register_adapter(state->cec_adap);
+	err = cec_register_adapter(state->cec_adap, &client->dev);
 	if (err)
 		cec_delete_adapter(state->cec_adap);
 	return err;
@@ -1928,7 +1929,7 @@ static int adv7511_probe(struct i2c_clie
 	state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
 		state, dev_name(&client->dev), CEC_CAP_TRANSMIT |
 		CEC_CAP_LOG_ADDRS | CEC_CAP_PASSTHROUGH | CEC_CAP_RC,
-		ADV7511_MAX_ADDRS, &client->dev);
+		ADV7511_MAX_ADDRS);
 	err = PTR_ERR_OR_ZERO(state->cec_adap);
 	if (err) {
 		destroy_workqueue(state->work_queue);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/adv7604.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7604.c
--- linux-libre-4.9-gnu/drivers/media/i2c/adv7604.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7604.c	2017-02-12 16:03:20.000000000 -0500
@@ -1566,10 +1566,24 @@ static int adv76xx_query_dv_timings(stru
 		V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
 
 	if (is_digital_input(sd)) {
+		bool hdmi_signal = hdmi_read(sd, 0x05) & 0x80;
+		u8 vic = 0;
+		u32 w, h;
+
+		w = hdmi_read16(sd, 0x07, info->linewidth_mask);
+		h = hdmi_read16(sd, 0x09, info->field0_height_mask);
+
+		if (hdmi_signal && (io_read(sd, 0x60) & 1))
+			vic = infoframe_read(sd, 0x04);
+
+		if (vic && v4l2_find_dv_timings_cea861_vic(timings, vic) &&
+		    bt->width == w && bt->height == h)
+			goto found;
+
 		timings->type = V4L2_DV_BT_656_1120;
 
-		bt->width = hdmi_read16(sd, 0x07, info->linewidth_mask);
-		bt->height = hdmi_read16(sd, 0x09, info->field0_height_mask);
+		bt->width = w;
+		bt->height = h;
 		bt->pixelclock = info->read_hdmi_pixelclock(sd);
 		bt->hfrontporch = hdmi_read16(sd, 0x20, info->hfrontporch_mask);
 		bt->hsync = hdmi_read16(sd, 0x22, info->hsync_mask);
@@ -2617,9 +2631,10 @@ static int adv76xx_subscribe_event(struc
 static int adv76xx_registered(struct v4l2_subdev *sd)
 {
 	struct adv76xx_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int err;
 
-	err = cec_register_adapter(state->cec_adap);
+	err = cec_register_adapter(state->cec_adap, &client->dev);
 	if (err)
 		cec_delete_adapter(state->cec_adap);
 	return err;
@@ -3074,13 +3089,13 @@ static int adv76xx_parse_dt(struct adv76
 		return ret;
 	}
 
-	if (!of_property_read_u32(endpoint, "default-input", &v))
+	of_node_put(endpoint);
+
+	if (!of_property_read_u32(np, "default-input", &v))
 		state->pdata.default_input = v;
 	else
 		state->pdata.default_input = -1;
 
-	of_node_put(endpoint);
-
 	flags = bus_cfg.bus.parallel.flags;
 
 	if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
@@ -3497,8 +3512,7 @@ static int adv76xx_probe(struct i2c_clie
 	state->cec_adap = cec_allocate_adapter(&adv76xx_cec_adap_ops,
 		state, dev_name(&client->dev),
 		CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
-		CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV76XX_MAX_ADDRS,
-		&client->dev);
+		CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV76XX_MAX_ADDRS);
 	err = PTR_ERR_OR_ZERO(state->cec_adap);
 	if (err)
 		goto err_entity;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/adv7842.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7842.c
--- linux-libre-4.9-gnu/drivers/media/i2c/adv7842.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/adv7842.c	2017-02-12 16:03:20.000000000 -0500
@@ -3250,9 +3250,10 @@ static int adv7842_subscribe_event(struc
 static int adv7842_registered(struct v4l2_subdev *sd)
 {
 	struct adv7842_state *state = to_state(sd);
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	int err;
 
-	err = cec_register_adapter(state->cec_adap);
+	err = cec_register_adapter(state->cec_adap, &client->dev);
 	if (err)
 		cec_delete_adapter(state->cec_adap);
 	return err;
@@ -3568,8 +3569,7 @@ static int adv7842_probe(struct i2c_clie
 	state->cec_adap = cec_allocate_adapter(&adv7842_cec_adap_ops,
 		state, dev_name(&client->dev),
 		CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS |
-		CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV7842_MAX_ADDRS,
-		&client->dev);
+		CEC_CAP_PASSTHROUGH | CEC_CAP_RC, ADV7842_MAX_ADDRS);
 	err = PTR_ERR_OR_ZERO(state->cec_adap);
 	if (err)
 		goto err_entity;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/bt856.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/bt856.c
--- linux-libre-4.9-gnu/drivers/media/i2c/bt856.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/bt856.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/bt866.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/bt866.c
--- linux-libre-4.9-gnu/drivers/media/i2c/bt866.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/bt866.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/cs53l32a.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/cs53l32a.c
--- linux-libre-4.9-gnu/drivers/media/i2c/cs53l32a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/cs53l32a.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/cx25840/cx25840-core.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/cx25840/cx25840-core.c
--- linux-libre-4.9-gnu/drivers/media/i2c/cx25840/cx25840-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/cx25840/cx25840-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -873,10 +873,7 @@ void cx25840_std_setup(struct i2c_client
 					"Chroma sub-carrier freq = %d.%06d MHz\n",
 					fsc / 1000000, fsc % 1000000);
 
-			v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
-				"vblank %i, vactive %i, vblank656 %i, src_dec %i, "
-				"burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, "
-				"sc 0x%06x\n",
+			v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, vblank %i, vactive %i, vblank656 %i, src_dec %i, burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, sc 0x%06x\n",
 				hblank, hactive, vblank, vactive, vblank656,
 				src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
 		}
@@ -5169,11 +5166,9 @@ static int cx25840_probe(struct i2c_clie
 		id = CX2310X_AV;
 	} else if ((device_id & 0xff) == (device_id >> 8)) {
 		v4l_err(client,
-			"likely a confused/unresponsive cx2388[578] A/V decoder"
-			" found @ 0x%x (%s)\n",
+			"likely a confused/unresponsive cx2388[578] A/V decoder found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
-		v4l_err(client, "A method to reset it from the cx25840 driver"
-			" software is not known at this time\n");
+		v4l_err(client, "A method to reset it from the cx25840 driver software is not known at this time\n");
 		return -ENODEV;
 	} else {
 		v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/cx25840/cx25840-ir.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/cx25840/cx25840-ir.c
--- linux-libre-4.9-gnu/drivers/media/i2c/cx25840/cx25840-ir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/cx25840/cx25840-ir.c	2017-02-12 16:03:20.000000000 -0500
@@ -1113,8 +1113,8 @@ int cx25840_ir_log_status(struct v4l2_su
 			j = 0;
 			break;
 		}
-		v4l2_info(sd, "\tNext carrier edge window:          16 clocks "
-			  "-%1d/+%1d, %u to %u Hz\n", i, j,
+		v4l2_info(sd, "\tNext carrier edge window:	    16 clocks -%1d/+%1d, %u to %u Hz\n",
+			  i, j,
 			  clock_divider_to_freq(rxclk, 16 + j),
 			  clock_divider_to_freq(rxclk, 16 - i));
 	}
@@ -1124,8 +1124,7 @@ int cx25840_ir_log_status(struct v4l2_su
 	v4l2_info(sd, "\tLow pass filter:                   %s\n",
 		  filtr ? "enabled" : "disabled");
 	if (filtr)
-		v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, "
-			  "%u ns\n",
+		v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, %u ns\n",
 			  lpf_count_to_us(filtr),
 			  lpf_count_to_ns(filtr));
 	v4l2_info(sd, "\tPulse width timer timed-out:       %s\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/i2c/Kconfig
--- linux-libre-4.9-gnu/drivers/media/i2c/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -221,7 +221,7 @@ config VIDEO_ADV7604
 
 config VIDEO_ADV7604_CEC
 	bool "Enable Analog Devices ADV7604 CEC support"
-	depends on VIDEO_ADV7604 && MEDIA_CEC
+	depends on VIDEO_ADV7604 && MEDIA_CEC_SUPPORT
 	---help---
 	  When selected the adv7604 will support the optional
 	  HDMI CEC feature.
@@ -242,7 +242,7 @@ config VIDEO_ADV7842
 
 config VIDEO_ADV7842_CEC
 	bool "Enable Analog Devices ADV7842 CEC support"
-	depends on VIDEO_ADV7842 && MEDIA_CEC
+	depends on VIDEO_ADV7842 && MEDIA_CEC_SUPPORT
 	---help---
 	  When selected the adv7842 will support the optional
 	  HDMI CEC feature.
@@ -481,7 +481,7 @@ config VIDEO_ADV7511
 
 config VIDEO_ADV7511_CEC
 	bool "Enable Analog Devices ADV7511 CEC support"
-	depends on VIDEO_ADV7511 && MEDIA_CEC
+	depends on VIDEO_ADV7511 && MEDIA_CEC_SUPPORT
 	---help---
 	  When selected the adv7511 will support the optional
 	  HDMI CEC feature.
@@ -655,6 +655,7 @@ config VIDEO_S5K6A3
 config VIDEO_S5K4ECGX
         tristate "Samsung S5K4ECGX sensor support"
         depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	select CRC32
         ---help---
           This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M
           camera sensor with an embedded SoC image signal processor.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/m52790.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/m52790.c
--- linux-libre-4.9-gnu/drivers/media/i2c/m52790.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/m52790.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,7 +24,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/i2c/m52790.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/msp3400-driver.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/msp3400-driver.c
--- linux-libre-4.9-gnu/drivers/media/i2c/msp3400-driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/msp3400-driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -146,11 +146,11 @@ int msp_reset(struct i2c_client *client)
 		},
 	};
 
-	v4l_dbg(3, msp_debug, client, "msp_reset\n");
+	dev_dbg_lvl(&client->dev, 3, msp_debug, "msp_reset\n");
 	if (i2c_transfer(client->adapter, &reset[0], 1) != 1 ||
 	    i2c_transfer(client->adapter, &reset[1], 1) != 1 ||
 	    i2c_transfer(client->adapter, test, 2) != 2) {
-		v4l_err(client, "chip reset failed\n");
+		dev_err(&client->dev, "chip reset failed\n");
 		return -1;
 	}
 	return 0;
@@ -182,17 +182,17 @@ static int msp_read(struct i2c_client *c
 	for (err = 0; err < 3; err++) {
 		if (i2c_transfer(client->adapter, msgs, 2) == 2)
 			break;
-		v4l_warn(client, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
+		dev_warn(&client->dev, "I/O error #%d (read 0x%02x/0x%02x)\n", err,
 		       dev, addr);
 		schedule_timeout_interruptible(msecs_to_jiffies(10));
 	}
 	if (err == 3) {
-		v4l_warn(client, "resetting chip, sound will go off.\n");
+		dev_warn(&client->dev, "resetting chip, sound will go off.\n");
 		msp_reset(client);
 		return -1;
 	}
 	retval = read[0] << 8 | read[1];
-	v4l_dbg(3, msp_debug, client, "msp_read(0x%x, 0x%x): 0x%x\n",
+	dev_dbg_lvl(&client->dev, 3, msp_debug, "msp_read(0x%x, 0x%x): 0x%x\n",
 			dev, addr, retval);
 	return retval;
 }
@@ -218,17 +218,17 @@ static int msp_write(struct i2c_client *
 	buffer[3] = val  >> 8;
 	buffer[4] = val  &  0xff;
 
-	v4l_dbg(3, msp_debug, client, "msp_write(0x%x, 0x%x, 0x%x)\n",
+	dev_dbg_lvl(&client->dev, 3, msp_debug, "msp_write(0x%x, 0x%x, 0x%x)\n",
 			dev, addr, val);
 	for (err = 0; err < 3; err++) {
 		if (i2c_master_send(client, buffer, 5) == 5)
 			break;
-		v4l_warn(client, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
+		dev_warn(&client->dev, "I/O error #%d (write 0x%02x/0x%02x)\n", err,
 		       dev, addr);
 		schedule_timeout_interruptible(msecs_to_jiffies(10));
 	}
 	if (err == 3) {
-		v4l_warn(client, "resetting chip, sound will go off.\n");
+		dev_warn(&client->dev, "resetting chip, sound will go off.\n");
 		msp_reset(client);
 		return -1;
 	}
@@ -301,7 +301,7 @@ void msp_set_scart(struct i2c_client *cl
 	} else
 		state->acb = 0xf60; /* Mute Input and SCART 1 Output */
 
-	v4l_dbg(1, msp_debug, client, "scart switch: %s => %d (ACB=0x%04x)\n",
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "scart switch: %s => %d (ACB=0x%04x)\n",
 					scart_names[in], out, state->acb);
 	msp_write_dsp(client, 0x13, state->acb);
 
@@ -359,7 +359,7 @@ static int msp_s_ctrl(struct v4l2_ctrl *
 		if (!reallymuted)
 			val = (val * 0x7f / 65535) << 8;
 
-		v4l_dbg(1, msp_debug, client, "mute=%s scanning=%s volume=%d\n",
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "mute=%s scanning=%s volume=%d\n",
 				state->muted->val ? "on" : "off",
 				state->scan_in_progress ? "yes" : "no",
 				state->volume->val);
@@ -426,7 +426,7 @@ static int msp_s_radio(struct v4l2_subde
 	if (state->radio)
 		return 0;
 	state->radio = 1;
-	v4l_dbg(1, msp_debug, client, "switching to radio mode\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "switching to radio mode\n");
 	state->watch_stereo = 0;
 	switch (state->opmode) {
 	case OPMODE_MANUAL:
@@ -461,7 +461,7 @@ static int msp_querystd(struct v4l2_subd
 
 	*id &= state->detected_std;
 
-	v4l_dbg(2, msp_debug, client,
+	dev_dbg_lvl(&client->dev, 2, msp_debug,
 		"detected standard: %s(0x%08Lx)\n",
 		msp_standard_std_name(state->std), state->detected_std);
 
@@ -555,7 +555,7 @@ static int msp_s_i2s_clock_freq(struct v
 	struct msp_state *state = to_state(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	v4l_dbg(1, msp_debug, client, "Setting I2S speed to %d\n", freq);
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "Setting I2S speed to %d\n", freq);
 
 	switch (freq) {
 		case 1024000:
@@ -579,7 +579,7 @@ static int msp_log_status(struct v4l2_su
 
 	if (state->opmode == OPMODE_AUTOSELECT)
 		msp_detect_stereo(client);
-	v4l_info(client, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
+	dev_info(&client->dev, "%s rev1 = 0x%04x rev2 = 0x%04x\n",
 			client->name, state->rev1, state->rev2);
 	snprintf(prefix, sizeof(prefix), "%s: Audio:    ", sd->name);
 	v4l2_ctrl_handler_log_status(&state->hdl, prefix);
@@ -596,23 +596,23 @@ static int msp_log_status(struct v4l2_su
 		default: p = "unknown"; break;
 	}
 	if (state->mode == MSP_MODE_EXTERN) {
-		v4l_info(client, "Mode:     %s\n", p);
+		dev_info(&client->dev, "Mode:     %s\n", p);
 	} else if (state->opmode == OPMODE_MANUAL) {
-		v4l_info(client, "Mode:     %s (%s%s)\n", p,
+		dev_info(&client->dev, "Mode:     %s (%s%s)\n", p,
 				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
 				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
 	} else {
 		if (state->opmode == OPMODE_AUTODETECT)
-			v4l_info(client, "Mode:     %s\n", p);
-		v4l_info(client, "Standard: %s (%s%s)\n",
+			dev_info(&client->dev, "Mode:     %s\n", p);
+		dev_info(&client->dev, "Standard: %s (%s%s)\n",
 				msp_standard_std_name(state->std),
 				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
 				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
 	}
-	v4l_info(client, "Audmode:  0x%04x\n", state->audmode);
-	v4l_info(client, "Routing:  0x%08x (input) 0x%08x (output)\n",
+	dev_info(&client->dev, "Audmode:  0x%04x\n", state->audmode);
+	dev_info(&client->dev, "Routing:  0x%08x (input) 0x%08x (output)\n",
 			state->route_in, state->route_out);
-	v4l_info(client, "ACB:      0x%04x\n", state->acb);
+	dev_info(&client->dev, "ACB:      0x%04x\n", state->acb);
 	return 0;
 }
 
@@ -620,7 +620,7 @@ static int msp_log_status(struct v4l2_su
 static int msp_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	v4l_dbg(1, msp_debug, client, "suspend\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "suspend\n");
 	msp_reset(client);
 	return 0;
 }
@@ -628,7 +628,7 @@ static int msp_suspend(struct device *de
 static int msp_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	v4l_dbg(1, msp_debug, client, "resume\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "resume\n");
 	msp_wake_thread(client);
 	return 0;
 }
@@ -670,6 +670,13 @@ static const struct v4l2_subdev_ops msp_
 
 /* ----------------------------------------------------------------------- */
 
+
+static const char * const opmode_str[] = {
+	[OPMODE_MANUAL] = "manual",
+	[OPMODE_AUTODETECT] = "autodetect",
+	[OPMODE_AUTOSELECT] = "autodetect and autoselect",
+};
+
 static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct msp_state *state;
@@ -689,7 +696,7 @@ static int msp_probe(struct i2c_client *
 		strlcpy(client->name, "msp3400", sizeof(client->name));
 
 	if (msp_reset(client) == -1) {
-		v4l_dbg(1, msp_debug, client, "msp3400 not found\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "msp3400 not found\n");
 		return -ENODEV;
 	}
 
@@ -724,10 +731,10 @@ static int msp_probe(struct i2c_client *
 	state->rev1 = msp_read_dsp(client, 0x1e);
 	if (state->rev1 != -1)
 		state->rev2 = msp_read_dsp(client, 0x1f);
-	v4l_dbg(1, msp_debug, client, "rev1=0x%04x, rev2=0x%04x\n",
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "rev1=0x%04x, rev2=0x%04x\n",
 			state->rev1, state->rev2);
 	if (state->rev1 == -1 || (state->rev1 == 0 && state->rev2 == 0)) {
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 				"not an msp3400 (cannot read chip version)\n");
 		return -ENODEV;
 	}
@@ -791,7 +798,8 @@ static int msp_probe(struct i2c_client *
 		msp_family == 3 && msp_revision == 'G' && msp_prod_hi == 3;
 
 	state->opmode = opmode;
-	if (state->opmode == OPMODE_AUTO) {
+	if (state->opmode < OPMODE_MANUAL
+	    || state->opmode > OPMODE_AUTOSELECT) {
 		/* MSP revision G and up have both autodetect and autoselect */
 		if (msp_revision >= 'G')
 			state->opmode = OPMODE_AUTOSELECT;
@@ -829,43 +837,35 @@ static int msp_probe(struct i2c_client *
 	v4l2_ctrl_cluster(2, &state->volume);
 	v4l2_ctrl_handler_setup(hdl);
 
-	/* hello world :-) */
-	v4l_info(client, "MSP%d4%02d%c-%c%d found @ 0x%x (%s)\n",
-			msp_family, msp_product,
-			msp_revision, msp_hard, msp_rom,
-			client->addr << 1, client->adapter->name);
-	v4l_info(client, "%s ", client->name);
-	if (state->has_nicam && state->has_radio)
-		printk(KERN_CONT "supports nicam and radio, ");
-	else if (state->has_nicam)
-		printk(KERN_CONT "supports nicam, ");
-	else if (state->has_radio)
-		printk(KERN_CONT "supports radio, ");
-	printk(KERN_CONT "mode is ");
+	dev_info(&client->dev,
+		 "MSP%d4%02d%c-%c%d found on %s: supports %s%s%s, mode is %s\n",
+		 msp_family, msp_product,
+		 msp_revision, msp_hard, msp_rom,
+		 client->adapter->name,
+		 (state->has_nicam) ? "nicam" : "",
+		 (state->has_nicam && state->has_radio) ? " and " : "",
+		 (state->has_radio) ? "radio" : "",
+		 opmode_str[state->opmode]);
 
 	/* version-specific initialization */
 	switch (state->opmode) {
 	case OPMODE_MANUAL:
-		printk(KERN_CONT "manual");
 		thread_func = msp3400c_thread;
 		break;
 	case OPMODE_AUTODETECT:
-		printk(KERN_CONT "autodetect");
 		thread_func = msp3410d_thread;
 		break;
 	case OPMODE_AUTOSELECT:
-		printk(KERN_CONT "autodetect and autoselect");
 		thread_func = msp34xxg_thread;
 		break;
 	}
-	printk(KERN_CONT "\n");
 
 	/* startup control thread if needed */
 	if (thread_func) {
 		state->kthread = kthread_run(thread_func, client, "msp34xx");
 
 		if (IS_ERR(state->kthread))
-			v4l_warn(client, "kernel_thread() failed\n");
+			dev_warn(&client->dev, "kernel_thread() failed\n");
 		msp_wake_thread(client);
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/msp3400-kthreads.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/msp3400-kthreads.c
--- linux-libre-4.9-gnu/drivers/media/i2c/msp3400-kthreads.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/msp3400-kthreads.c	2017-02-12 16:03:20.000000000 -0500
@@ -220,7 +220,7 @@ void msp3400c_set_mode(struct i2c_client
 	int tuner = (state->route_in >> 3) & 1;
 	int i;
 
-	v4l_dbg(1, msp_debug, client, "set_mode: %d\n", mode);
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "set_mode: %d\n", mode);
 	state->mode = mode;
 	state->rxsubchans = V4L2_TUNER_SUB_MONO;
 
@@ -266,7 +266,7 @@ static void msp3400c_set_audmode(struct
 		/* this method would break everything, let's make sure
 		 * it's never called
 		 */
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"set_audmode called with mode=%d instead of set_source (ignored)\n",
 			state->audmode);
 		return;
@@ -295,7 +295,7 @@ static void msp3400c_set_audmode(struct
 	/* switch demodulator */
 	switch (state->mode) {
 	case MSP_MODE_FM_TERRA:
-		v4l_dbg(1, msp_debug, client, "FM set_audmode: %s\n", modestr);
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "FM set_audmode: %s\n", modestr);
 		switch (audmode) {
 		case V4L2_TUNER_MODE_STEREO:
 			msp_write_dsp(client, 0x000e, 0x3001);
@@ -309,7 +309,7 @@ static void msp3400c_set_audmode(struct
 		}
 		break;
 	case MSP_MODE_FM_SAT:
-		v4l_dbg(1, msp_debug, client, "SAT set_audmode: %s\n", modestr);
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "SAT set_audmode: %s\n", modestr);
 		switch (audmode) {
 		case V4L2_TUNER_MODE_MONO:
 			msp3400c_set_carrier(client, MSP_CARRIER(6.5), MSP_CARRIER(6.5));
@@ -329,31 +329,31 @@ static void msp3400c_set_audmode(struct
 	case MSP_MODE_FM_NICAM1:
 	case MSP_MODE_FM_NICAM2:
 	case MSP_MODE_AM_NICAM:
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"NICAM set_audmode: %s\n", modestr);
 		if (state->nicam_on)
 			src = 0x0100;  /* NICAM */
 		break;
 	case MSP_MODE_BTSC:
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"BTSC set_audmode: %s\n", modestr);
 		break;
 	case MSP_MODE_EXTERN:
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"extern set_audmode: %s\n", modestr);
 		src = 0x0200;  /* SCART */
 		break;
 	case MSP_MODE_FM_RADIO:
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"FM-Radio set_audmode: %s\n", modestr);
 		break;
 	default:
-		v4l_dbg(1, msp_debug, client, "mono set_audmode\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "mono set_audmode\n");
 		return;
 	}
 
 	/* switch audio */
-	v4l_dbg(1, msp_debug, client, "set audmode %d\n", audmode);
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "set audmode %d\n", audmode);
 	switch (audmode) {
 	case V4L2_TUNER_MODE_STEREO:
 	case V4L2_TUNER_MODE_LANG1_LANG2:
@@ -361,7 +361,7 @@ static void msp3400c_set_audmode(struct
 		break;
 	case V4L2_TUNER_MODE_MONO:
 		if (state->mode == MSP_MODE_AM_NICAM) {
-			v4l_dbg(1, msp_debug, client, "switching to AM mono\n");
+			dev_dbg_lvl(&client->dev, 1, msp_debug, "switching to AM mono\n");
 			/* AM mono decoding is handled by tuner, not MSP chip */
 			/* SCART switching control register */
 			msp_set_scart(client, SCART_MONO, 0);
@@ -377,7 +377,7 @@ static void msp3400c_set_audmode(struct
 		src |= 0x0010;
 		break;
 	}
-	v4l_dbg(1, msp_debug, client,
+	dev_dbg_lvl(&client->dev, 1, msp_debug,
 		"set_audmode final source/matrix = 0x%x\n", src);
 
 	msp_set_source(client, src);
@@ -388,23 +388,23 @@ static void msp3400c_print_mode(struct i
 	struct msp_state *state = to_state(i2c_get_clientdata(client));
 
 	if (state->main == state->second)
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"mono sound carrier: %d.%03d MHz\n",
 			state->main / 910000, (state->main / 910) % 1000);
 	else
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"main sound carrier: %d.%03d MHz\n",
 			state->main / 910000, (state->main / 910) % 1000);
 	if (state->mode == MSP_MODE_FM_NICAM1 || state->mode == MSP_MODE_FM_NICAM2)
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"NICAM/FM carrier  : %d.%03d MHz\n",
 			state->second / 910000, (state->second/910) % 1000);
 	if (state->mode == MSP_MODE_AM_NICAM)
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"NICAM/AM carrier  : %d.%03d MHz\n",
 			state->second / 910000, (state->second / 910) % 1000);
 	if (state->mode == MSP_MODE_FM_TERRA && state->main != state->second) {
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"FM-stereo carrier : %d.%03d MHz\n",
 			state->second / 910000, (state->second / 910) % 1000);
 	}
@@ -425,7 +425,7 @@ static int msp3400c_detect_stereo(struct
 		val = msp_read_dsp(client, 0x18);
 		if (val > 32767)
 			val -= 65536;
-		v4l_dbg(2, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 2, msp_debug,
 			"stereo detect register: %d\n", val);
 		if (val > 8192) {
 			rxsubchans = V4L2_TUNER_SUB_STEREO;
@@ -440,7 +440,7 @@ static int msp3400c_detect_stereo(struct
 	case MSP_MODE_FM_NICAM2:
 	case MSP_MODE_AM_NICAM:
 		val = msp_read_dem(client, 0x23);
-		v4l_dbg(2, msp_debug, client, "nicam sync=%d, mode=%d\n",
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "nicam sync=%d, mode=%d\n",
 			val & 1, (val & 0x1e) >> 1);
 
 		if (val & 1) {
@@ -471,14 +471,14 @@ static int msp3400c_detect_stereo(struct
 	}
 	if (rxsubchans != state->rxsubchans) {
 		update = 1;
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"watch: rxsubchans %02x => %02x\n",
 			state->rxsubchans, rxsubchans);
 		state->rxsubchans = rxsubchans;
 	}
 	if (newnicam != state->nicam_on) {
 		update = 1;
-		v4l_dbg(1, msp_debug, client, "watch: nicam %d => %d\n",
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "watch: nicam %d => %d\n",
 			state->nicam_on, newnicam);
 		state->nicam_on = newnicam;
 	}
@@ -508,23 +508,23 @@ int msp3400c_thread(void *data)
 	struct msp3400c_carrier_detect *cd;
 	int count, max1, max2, val1, val2, val, i;
 
-	v4l_dbg(1, msp_debug, client, "msp3400 daemon started\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "msp3400 daemon started\n");
 	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
-		v4l_dbg(2, msp_debug, client, "msp3400 thread: sleep\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3400 thread: sleep\n");
 		msp_sleep(state, -1);
-		v4l_dbg(2, msp_debug, client, "msp3400 thread: wakeup\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3400 thread: wakeup\n");
 
 restart:
-		v4l_dbg(2, msp_debug, client, "thread: restart scan\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "thread: restart scan\n");
 		state->restart = 0;
 		if (kthread_should_stop())
 			break;
 
 		if (state->radio || MSP_MODE_EXTERN == state->mode) {
 			/* no carrier scan, just unmute */
-			v4l_dbg(1, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 1, msp_debug,
 				"thread: no carrier scan\n");
 			state->scan_in_progress = 0;
 			msp_update_volume(state);
@@ -553,7 +553,7 @@ restart:
 			/* autodetect doesn't work well with AM ... */
 			max1 = 3;
 			count = 0;
-			v4l_dbg(1, msp_debug, client, "AM sound override\n");
+			dev_dbg_lvl(&client->dev, 1, msp_debug, "AM sound override\n");
 		}
 
 		for (i = 0; i < count; i++) {
@@ -565,7 +565,7 @@ restart:
 				val -= 65536;
 			if (val1 < val)
 				val1 = val, max1 = i;
-			v4l_dbg(1, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 1, msp_debug,
 				"carrier1 val: %5d / %s\n", val, cd[i].name);
 		}
 
@@ -602,7 +602,7 @@ restart:
 				val -= 65536;
 			if (val2 < val)
 				val2 = val, max2 = i;
-			v4l_dbg(1, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 1, msp_debug,
 				"carrier2 val: %5d / %s\n", val, cd[i].name);
 		}
 
@@ -687,7 +687,7 @@ no_second:
 			watch_stereo(client);
 		}
 	}
-	v4l_dbg(1, msp_debug, client, "thread: exit\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: exit\n");
 	return 0;
 }
 
@@ -698,23 +698,23 @@ int msp3410d_thread(void *data)
 	struct msp_state *state = to_state(i2c_get_clientdata(client));
 	int val, i, std, count;
 
-	v4l_dbg(1, msp_debug, client, "msp3410 daemon started\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "msp3410 daemon started\n");
 	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
-		v4l_dbg(2, msp_debug, client, "msp3410 thread: sleep\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3410 thread: sleep\n");
 		msp_sleep(state, -1);
-		v4l_dbg(2, msp_debug, client, "msp3410 thread: wakeup\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "msp3410 thread: wakeup\n");
 
 restart:
-		v4l_dbg(2, msp_debug, client, "thread: restart scan\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "thread: restart scan\n");
 		state->restart = 0;
 		if (kthread_should_stop())
 			break;
 
 		if (state->mode == MSP_MODE_EXTERN) {
 			/* no carrier scan needed, just unmute */
-			v4l_dbg(1, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 1, msp_debug,
 				"thread: no carrier scan\n");
 			state->scan_in_progress = 0;
 			msp_update_volume(state);
@@ -740,7 +740,7 @@ restart:
 			goto restart;
 
 		if (msp_debug)
-			v4l_dbg(2, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 2, msp_debug,
 				"setting standard: %s (0x%04x)\n",
 				msp_standard_std_name(std), std);
 
@@ -758,14 +758,14 @@ restart:
 				val = msp_read_dem(client, 0x7e);
 				if (val < 0x07ff)
 					break;
-				v4l_dbg(2, msp_debug, client,
+				dev_dbg_lvl(&client->dev, 2, msp_debug,
 					"detection still in progress\n");
 			}
 		}
 		for (i = 0; msp_stdlist[i].name != NULL; i++)
 			if (msp_stdlist[i].retval == val)
 				break;
-		v4l_dbg(1, msp_debug, client, "current standard: %s (0x%04x)\n",
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "current standard: %s (0x%04x)\n",
 			msp_standard_std_name(val), val);
 		state->main   = msp_stdlist[i].main;
 		state->second = msp_stdlist[i].second;
@@ -775,8 +775,7 @@ restart:
 		if (msp_amsound && !state->radio &&
 		    (state->v4l2_std & V4L2_STD_SECAM) && (val != 0x0009)) {
 			/* autodetection has failed, let backup */
-			v4l_dbg(1, msp_debug, client, "autodetection failed,"
-				" switching to backup standard: %s (0x%04x)\n",
+			dev_dbg_lvl(&client->dev, 1, msp_debug, "autodetection failed, switching to backup standard: %s (0x%04x)\n",
 				msp_stdlist[8].name ?
 					msp_stdlist[8].name : "unknown", val);
 			state->std = val = 0x0009;
@@ -850,7 +849,7 @@ restart:
 			watch_stereo(client);
 		}
 	}
-	v4l_dbg(1, msp_debug, client, "thread: exit\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: exit\n");
 	return 0;
 }
 
@@ -867,23 +866,23 @@ static int msp34xxg_modus(struct i2c_cli
 	struct msp_state *state = to_state(i2c_get_clientdata(client));
 
 	if (state->radio) {
-		v4l_dbg(1, msp_debug, client, "selected radio modus\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "selected radio modus\n");
 		return 0x0001;
 	}
 	if (state->v4l2_std == V4L2_STD_NTSC_M_JP) {
-		v4l_dbg(1, msp_debug, client, "selected M (EIA-J) modus\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "selected M (EIA-J) modus\n");
 		return 0x4001;
 	}
 	if (state->v4l2_std == V4L2_STD_NTSC_M_KR) {
-		v4l_dbg(1, msp_debug, client, "selected M (A2) modus\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "selected M (A2) modus\n");
 		return 0x0001;
 	}
 	if (state->v4l2_std == V4L2_STD_SECAM_L) {
-		v4l_dbg(1, msp_debug, client, "selected SECAM-L modus\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "selected SECAM-L modus\n");
 		return 0x6001;
 	}
 	if (state->v4l2_std & V4L2_STD_MN) {
-		v4l_dbg(1, msp_debug, client, "selected M (BTSC) modus\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "selected M (BTSC) modus\n");
 		return 0x2001;
 	}
 	return 0x7001;
@@ -927,7 +926,7 @@ static void msp34xxg_set_source(struct i
 	else
 		source = (in << 8) | matrix;
 
-	v4l_dbg(1, msp_debug, client,
+	dev_dbg_lvl(&client->dev, 1, msp_debug,
 		"set source to %d (0x%x) for output %02x\n", in, source, reg);
 	msp_write_dsp(client, reg, source);
 }
@@ -996,23 +995,23 @@ int msp34xxg_thread(void *data)
 	struct msp_state *state = to_state(i2c_get_clientdata(client));
 	int val, i;
 
-	v4l_dbg(1, msp_debug, client, "msp34xxg daemon started\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "msp34xxg daemon started\n");
 	state->detected_std = V4L2_STD_ALL;
 	set_freezable();
 	for (;;) {
-		v4l_dbg(2, msp_debug, client, "msp34xxg thread: sleep\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "msp34xxg thread: sleep\n");
 		msp_sleep(state, -1);
-		v4l_dbg(2, msp_debug, client, "msp34xxg thread: wakeup\n");
+		dev_dbg_lvl(&client->dev, 2, msp_debug, "msp34xxg thread: wakeup\n");
 
 restart:
-		v4l_dbg(1, msp_debug, client, "thread: restart scan\n");
+		dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: restart scan\n");
 		state->restart = 0;
 		if (kthread_should_stop())
 			break;
 
 		if (state->mode == MSP_MODE_EXTERN) {
 			/* no carrier scan needed, just unmute */
-			v4l_dbg(1, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 1, msp_debug,
 				"thread: no carrier scan\n");
 			state->scan_in_progress = 0;
 			msp_update_volume(state);
@@ -1029,7 +1028,7 @@ restart:
 			goto unmute;
 
 		/* watch autodetect */
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"started autodetect, waiting for result\n");
 		for (i = 0; i < 10; i++) {
 			if (msp_sleep(state, 100))
@@ -1041,17 +1040,17 @@ restart:
 				state->std = val;
 				break;
 			}
-			v4l_dbg(2, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 2, msp_debug,
 				"detection still in progress\n");
 		}
 		if (state->std == 1) {
-			v4l_dbg(1, msp_debug, client,
+			dev_dbg_lvl(&client->dev, 1, msp_debug,
 				"detection still in progress after 10 tries. giving up.\n");
 			continue;
 		}
 
 unmute:
-		v4l_dbg(1, msp_debug, client,
+		dev_dbg_lvl(&client->dev, 1, msp_debug,
 			"detected standard: %s (0x%04x)\n",
 			msp_standard_std_name(state->std), state->std);
 		state->detected_std = msp_standard_std(state->std);
@@ -1084,7 +1083,7 @@ unmute:
 				goto restart;
 		}
 	}
-	v4l_dbg(1, msp_debug, client, "thread: exit\n");
+	dev_dbg_lvl(&client->dev, 1, msp_debug, "thread: exit\n");
 	return 0;
 }
 
@@ -1111,7 +1110,7 @@ static int msp34xxg_detect_stereo(struct
 			state->rxsubchans =
 				V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
 	}
-	v4l_dbg(1, msp_debug, client,
+	dev_dbg_lvl(&client->dev, 1, msp_debug,
 		"status=0x%x, stereo=%d, bilingual=%d -> rxsubchans=%d\n",
 		status, is_stereo, is_bilingual, state->rxsubchans);
 	return (oldrx != state->rxsubchans);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/saa6588.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/saa6588.c
--- linux-libre-4.9-gnu/drivers/media/i2c/saa6588.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/saa6588.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/wait.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <media/i2c/saa6588.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/saa7110.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/saa7110.c
--- linux-libre-4.9-gnu/drivers/media/i2c/saa7110.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/saa7110.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/saa7185.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/saa7185.c
--- linux-libre-4.9-gnu/drivers/media/i2c/saa7185.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/saa7185.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/smiapp/smiapp-core.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp/smiapp-core.c
--- linux-libre-4.9-gnu/drivers/media/i2c/smiapp/smiapp-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp/smiapp-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/smiapp.h>
@@ -68,10 +69,9 @@ static int smiapp_read_frame_fmt(struct
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 	u32 fmt_model_type, fmt_model_subtype, ncol_desc, nrow_desc;
 	unsigned int i;
-	int rval;
+	int pixel_count = 0;
 	int line_count = 0;
-	int embedded_start = -1, embedded_end = -1;
-	int image_start = 0;
+	int rval;
 
 	rval = smiapp_read(sensor, SMIAPP_REG_U8_FRAME_FORMAT_MODEL_TYPE,
 			   &fmt_model_type);
@@ -101,12 +101,11 @@ static int smiapp_read_frame_fmt(struct
 		u32 pixels;
 		char *which;
 		char *what;
+		u32 reg;
 
 		if (fmt_model_type == SMIAPP_FRAME_FORMAT_MODEL_TYPE_2BYTE) {
-			rval = smiapp_read(
-				sensor,
-				SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(i),
-				&desc);
+			reg = SMIAPP_REG_U16_FRAME_FORMAT_DESCRIPTOR_2(i);
+			rval = smiapp_read(sensor, reg,	&desc);
 			if (rval)
 				return rval;
 
@@ -117,10 +116,8 @@ static int smiapp_read_frame_fmt(struct
 			pixels = desc & SMIAPP_FRAME_FORMAT_DESC_2_PIXELS_MASK;
 		} else if (fmt_model_type
 			   == SMIAPP_FRAME_FORMAT_MODEL_TYPE_4BYTE) {
-			rval = smiapp_read(
-				sensor,
-				SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(i),
-				&desc);
+			reg = SMIAPP_REG_U32_FRAME_FORMAT_DESCRIPTOR_4(i);
+			rval = smiapp_read(sensor, reg, &desc);
 			if (rval)
 				return rval;
 
@@ -159,40 +156,47 @@ static int smiapp_read_frame_fmt(struct
 			break;
 		default:
 			what = "invalid";
-			dev_dbg(&client->dev, "pixelcode %d\n", pixelcode);
 			break;
 		}
 
-		dev_dbg(&client->dev, "%s pixels: %d %s\n",
-			what, pixels, which);
+		dev_dbg(&client->dev,
+			"0x%8.8x %s pixels: %d %s (pixelcode %u)\n", reg,
+			what, pixels, which, pixelcode);
 
-		if (i < ncol_desc)
+		if (i < ncol_desc) {
+			if (pixelcode ==
+			    SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE)
+				sensor->visible_pixel_start = pixel_count;
+			pixel_count += pixels;
 			continue;
+		}
 
 		/* Handle row descriptors */
-		if (pixelcode
-		    == SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED) {
-			embedded_start = line_count;
-		} else {
-			if (pixelcode == SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE
-			    || pixels >= sensor->limits[SMIAPP_LIMIT_MIN_FRAME_LENGTH_LINES] / 2)
-				image_start = line_count;
-			if (embedded_start != -1 && embedded_end == -1)
-				embedded_end = line_count;
+		switch (pixelcode) {
+		case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_EMBEDDED:
+			if (sensor->embedded_end)
+				break;
+			sensor->embedded_start = line_count;
+			sensor->embedded_end = line_count + pixels;
+			break;
+		case SMIAPP_FRAME_FORMAT_DESC_PIXELCODE_VISIBLE:
+			sensor->image_start = line_count;
+			break;
 		}
 		line_count += pixels;
 	}
 
-	if (embedded_start == -1 || embedded_end == -1) {
-		embedded_start = 0;
-		embedded_end = 0;
+	if (sensor->embedded_end > sensor->image_start) {
+		dev_dbg(&client->dev,
+			"adjusting image start line to %u (was %u)\n",
+			sensor->embedded_end, sensor->image_start);
+		sensor->image_start = sensor->embedded_end;
 	}
 
-	sensor->image_start = image_start;
-
 	dev_dbg(&client->dev, "embedded data from lines %d to %d\n",
-		embedded_start, embedded_end);
-	dev_dbg(&client->dev, "image data starts at line %d\n", image_start);
+		sensor->embedded_start, sensor->embedded_end);
+	dev_dbg(&client->dev, "image data starts at line %d\n",
+		sensor->image_start);
 
 	return 0;
 }
@@ -443,8 +447,7 @@ static int smiapp_set_ctrl(struct v4l2_c
 			orient |= SMIAPP_IMAGE_ORIENTATION_VFLIP;
 
 		orient ^= sensor->hvflip_inv_mask;
-		rval = smiapp_write(sensor,
-				    SMIAPP_REG_U8_IMAGE_ORIENTATION,
+		rval = smiapp_write(sensor, SMIAPP_REG_U8_IMAGE_ORIENTATION,
 				    orient);
 		if (rval < 0)
 			return rval;
@@ -459,10 +462,8 @@ static int smiapp_set_ctrl(struct v4l2_c
 		__smiapp_update_exposure_limits(sensor);
 
 		if (exposure > sensor->exposure->maximum) {
-			sensor->exposure->val =
-				sensor->exposure->maximum;
-			rval = smiapp_set_ctrl(
-				sensor->exposure);
+			sensor->exposure->val =	sensor->exposure->maximum;
+			rval = smiapp_set_ctrl(sensor->exposure);
 			if (rval < 0)
 				return rval;
 		}
@@ -621,7 +622,7 @@ static int smiapp_init_controls(struct s
 static int smiapp_init_late_controls(struct smiapp_sensor *sensor)
 {
 	unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
-		sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE];
+		sensor->csi_format->compressed - sensor->compressed_min_bpp];
 	unsigned int max, i;
 
 	for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++) {
@@ -754,6 +755,7 @@ static int smiapp_get_mbus_formats(struc
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 	struct smiapp_pll *pll = &sensor->pll;
+	u8 compressed_max_bpp = 0;
 	unsigned int type, n;
 	unsigned int i, pixel_order;
 	int rval;
@@ -826,16 +828,27 @@ static int smiapp_get_mbus_formats(struc
 	pll->scale_m = sensor->scale_m;
 
 	for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
+		sensor->compressed_min_bpp =
+			min(smiapp_csi_data_formats[i].compressed,
+			    sensor->compressed_min_bpp);
+		compressed_max_bpp =
+			max(smiapp_csi_data_formats[i].compressed,
+			    compressed_max_bpp);
+	}
+
+	sensor->valid_link_freqs = devm_kcalloc(
+		&client->dev,
+		compressed_max_bpp - sensor->compressed_min_bpp + 1,
+		sizeof(*sensor->valid_link_freqs), GFP_KERNEL);
+
+	for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
 		const struct smiapp_csi_data_format *f =
 			&smiapp_csi_data_formats[i];
 		unsigned long *valid_link_freqs =
 			&sensor->valid_link_freqs[
-				f->compressed - SMIAPP_COMPRESSED_BASE];
+				f->compressed - sensor->compressed_min_bpp];
 		unsigned int j;
 
-		BUG_ON(f->compressed < SMIAPP_COMPRESSED_BASE);
-		BUG_ON(f->compressed > SMIAPP_COMPRESSED_MAX);
-
 		if (!(sensor->default_mbus_frame_fmts & 1 << i))
 			continue;
 
@@ -914,12 +927,6 @@ static int smiapp_update_mode(struct smi
 	unsigned int binning_mode;
 	int rval;
 
-	dev_dbg(&client->dev, "frame size: %dx%d\n",
-		sensor->src->crop[SMIAPP_PAD_SRC].width,
-		sensor->src->crop[SMIAPP_PAD_SRC].height);
-	dev_dbg(&client->dev, "csi format width: %d\n",
-		sensor->csi_format->width);
-
 	/* Binning has to be set up here; it affects limits */
 	if (sensor->binning_horizontal == 1 &&
 	    sensor->binning_vertical == 1) {
@@ -1196,9 +1203,17 @@ out:
  * Power management
  */
 
-static int smiapp_power_on(struct smiapp_sensor *sensor)
+static int smiapp_power_on(struct device *dev)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	/*
+	 * The sub-device related to the I2C device is always the
+	 * source one, i.e. ssds[0].
+	 */
+	struct smiapp_sensor *sensor =
+		container_of(ssd, struct smiapp_sensor, ssds[0]);
 	unsigned int sleep;
 	int rval;
 
@@ -1307,8 +1322,7 @@ static int smiapp_power_on(struct smiapp
 	if (!sensor->pixel_array)
 		return 0;
 
-	rval = v4l2_ctrl_handler_setup(
-		&sensor->pixel_array->ctrl_handler);
+	rval = v4l2_ctrl_handler_setup(&sensor->pixel_array->ctrl_handler);
 	if (rval)
 		goto out_cci_addr_fail;
 
@@ -1325,16 +1339,24 @@ static int smiapp_power_on(struct smiapp
 	return 0;
 
 out_cci_addr_fail:
+
 	gpiod_set_value(sensor->xshutdown, 0);
 	clk_disable_unprepare(sensor->ext_clk);
 
 out_xclk_fail:
 	regulator_disable(sensor->vana);
+
 	return rval;
 }
 
-static void smiapp_power_off(struct smiapp_sensor *sensor)
+static int smiapp_power_off(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
+	struct smiapp_sensor *sensor =
+		container_of(ssd, struct smiapp_sensor, ssds[0]);
+
 	/*
 	 * Currently power/clock to lens are enable/disabled separately
 	 * but they are essentially the same signals. So if the sensor is
@@ -1352,31 +1374,31 @@ static void smiapp_power_off(struct smia
 	usleep_range(5000, 5000);
 	regulator_disable(sensor->vana);
 	sensor->streaming = false;
+
+	return 0;
 }
 
 static int smiapp_set_power(struct v4l2_subdev *subdev, int on)
 {
-	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
-	int ret = 0;
+	int rval;
 
-	mutex_lock(&sensor->power_mutex);
+	if (!on) {
+		pm_runtime_mark_last_busy(subdev->dev);
+		pm_runtime_put_autosuspend(subdev->dev);
 
-	if (on && !sensor->power_count) {
-		/* Power on and perform initialisation. */
-		ret = smiapp_power_on(sensor);
-		if (ret < 0)
-			goto out;
-	} else if (!on && sensor->power_count == 1) {
-		smiapp_power_off(sensor);
+		return 0;
 	}
 
-	/* Update the power count. */
-	sensor->power_count += on ? 1 : -1;
-	WARN_ON(sensor->power_count < 0);
+	rval = pm_runtime_get_sync(subdev->dev);
+	if (rval >= 0)
+		return 0;
 
-out:
-	mutex_unlock(&sensor->power_mutex);
-	return ret;
+	if (rval != -EBUSY && rval != -EAGAIN)
+		pm_runtime_set_active(subdev->dev);
+
+	pm_runtime_put(subdev->dev);
+
+	return rval;
 }
 
 /* -----------------------------------------------------------------------------
@@ -1614,7 +1636,8 @@ static int __smiapp_get_format(struct v4
 	struct smiapp_subdev *ssd = to_smiapp_subdev(subdev);
 
 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-		fmt->format = *v4l2_subdev_get_try_format(subdev, cfg, fmt->pad);
+		fmt->format = *v4l2_subdev_get_try_format(subdev, cfg,
+							  fmt->pad);
 	} else {
 		struct v4l2_rect *r;
 
@@ -1714,7 +1737,6 @@ static void smiapp_propagate(struct v4l2
 static const struct smiapp_csi_data_format
 *smiapp_validate_csi_data_format(struct smiapp_sensor *sensor, u32 code)
 {
-	const struct smiapp_csi_data_format *csi_format = sensor->csi_format;
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
@@ -1723,7 +1745,7 @@ static const struct smiapp_csi_data_form
 			return &smiapp_csi_data_formats[i];
 	}
 
-	return csi_format;
+	return sensor->csi_format;
 }
 
 static int smiapp_set_format_source(struct v4l2_subdev *subdev,
@@ -1769,7 +1791,7 @@ static int smiapp_set_format_source(stru
 
 	valid_link_freqs = 
 		&sensor->valid_link_freqs[sensor->csi_format->compressed
-					  - SMIAPP_COMPRESSED_BASE];
+					  - sensor->compressed_min_bpp];
 
 	__v4l2_ctrl_modify_range(
 		sensor->link_freq, 0,
@@ -2057,8 +2079,7 @@ static int smiapp_set_compose(struct v4l
 		smiapp_set_compose_scaler(subdev, cfg, sel, crops, comp);
 
 	*comp = sel->r;
-	smiapp_propagate(subdev, cfg, sel->which,
-			 V4L2_SEL_TGT_COMPOSE);
+	smiapp_propagate(subdev, cfg, sel->which, V4L2_SEL_TGT_COMPOSE);
 
 	if (sel->which == V4L2_SUBDEV_FORMAT_ACTIVE)
 		return smiapp_update_mode(sensor);
@@ -2135,9 +2156,8 @@ static int smiapp_set_crop(struct v4l2_s
 				->height;
 			src_size = &_r;
 		} else {
-			src_size =
-				v4l2_subdev_get_try_compose(
-					subdev, cfg, ssd->sink_pad);
+			src_size = v4l2_subdev_get_try_compose(
+				subdev, cfg, ssd->sink_pad);
 		}
 	}
 
@@ -2161,6 +2181,15 @@ static int smiapp_set_crop(struct v4l2_s
 	return 0;
 }
 
+static void smiapp_get_native_size(struct smiapp_subdev *ssd,
+				    struct v4l2_rect *r)
+{
+	r->top = 0;
+	r->left = 0;
+	r->width = ssd->sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
+	r->height = ssd->sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
+}
+
 static int __smiapp_get_selection(struct v4l2_subdev *subdev,
 				  struct v4l2_subdev_pad_config *cfg,
 				  struct v4l2_subdev_selection *sel)
@@ -2192,17 +2221,12 @@ static int __smiapp_get_selection(struct
 	switch (sel->target) {
 	case V4L2_SEL_TGT_CROP_BOUNDS:
 	case V4L2_SEL_TGT_NATIVE_SIZE:
-		if (ssd == sensor->pixel_array) {
-			sel->r.left = sel->r.top = 0;
-			sel->r.width =
-				sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
-			sel->r.height =
-				sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
-		} else if (sel->pad == ssd->sink_pad) {
+		if (ssd == sensor->pixel_array)
+			smiapp_get_native_size(ssd, &sel->r);
+		else if (sel->pad == ssd->sink_pad)
 			sel->r = sink_fmt;
-		} else {
+		else
 			sel->r = *comp;
-		}
 		break;
 	case V4L2_SEL_TGT_CROP:
 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
@@ -2303,15 +2327,26 @@ smiapp_sysfs_nvm_read(struct device *dev
 		return -EBUSY;
 
 	if (!sensor->nvm_size) {
+		int rval;
+
 		/* NVM not read yet - read it now */
 		sensor->nvm_size = sensor->hwcfg->nvm_size;
-		if (smiapp_set_power(subdev, 1) < 0)
+
+		rval = pm_runtime_get_sync(&client->dev);
+		if (rval < 0) {
+			if (rval != -EBUSY && rval != -EAGAIN)
+				pm_runtime_set_active(&client->dev);
+			pm_runtime_put(&client->dev);
 			return -ENODEV;
+		}
+
 		if (smiapp_read_nvm(sensor, sensor->nvm)) {
 			dev_err(&client->dev, "nvm read failed\n");
 			return -ENODEV;
 		}
-		smiapp_set_power(subdev, 0);
+
+		pm_runtime_mark_last_busy(&client->dev);
+		pm_runtime_put_autosuspend(&client->dev);
 	}
 	/*
 	 * NVM is still way below a PAGE_SIZE, so we can safely
@@ -2475,383 +2510,160 @@ static const struct v4l2_subdev_ops smia
 static const struct v4l2_subdev_internal_ops smiapp_internal_ops;
 static const struct media_entity_operations smiapp_entity_ops;
 
-static int smiapp_register_subdevs(struct smiapp_sensor *sensor)
+static int smiapp_register_subdev(struct smiapp_sensor *sensor,
+				  struct smiapp_subdev *ssd,
+				  struct smiapp_subdev *sink_ssd,
+				  u16 source_pad, u16 sink_pad, u32 link_flags)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-	struct smiapp_subdev *ssds[] = {
-		sensor->scaler,
-		sensor->binner,
-		sensor->pixel_array,
-	};
-	unsigned int i;
 	int rval;
 
-	for (i = 0; i < SMIAPP_SUBDEVS - 1; i++) {
-		struct smiapp_subdev *this = ssds[i + 1];
-		struct smiapp_subdev *last = ssds[i];
-
-		if (!last)
-			continue;
+	if (!sink_ssd)
+		return 0;
 
-		rval = media_entity_pads_init(&this->sd.entity,
-					 this->npads, this->pads);
-		if (rval) {
-			dev_err(&client->dev,
-				"media_entity_pads_init failed\n");
-			return rval;
-		}
+	rval = media_entity_pads_init(&ssd->sd.entity,
+				      ssd->npads, ssd->pads);
+	if (rval) {
+		dev_err(&client->dev,
+			"media_entity_pads_init failed\n");
+		return rval;
+	}
 
-		rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
-						   &this->sd);
-		if (rval) {
-			dev_err(&client->dev,
-				"v4l2_device_register_subdev failed\n");
-			return rval;
-		}
+	rval = v4l2_device_register_subdev(sensor->src->sd.v4l2_dev,
+					   &ssd->sd);
+	if (rval) {
+		dev_err(&client->dev,
+			"v4l2_device_register_subdev failed\n");
+		return rval;
+	}
 
-		rval = media_create_pad_link(&this->sd.entity,
-					     this->source_pad,
-					     &last->sd.entity,
-					     last->sink_pad,
-					     MEDIA_LNK_FL_ENABLED |
-					     MEDIA_LNK_FL_IMMUTABLE);
-		if (rval) {
-			dev_err(&client->dev,
-				"media_create_pad_link failed\n");
-			return rval;
-		}
+	rval = media_create_pad_link(&ssd->sd.entity, source_pad,
+				     &sink_ssd->sd.entity, sink_pad,
+				     link_flags);
+	if (rval) {
+		dev_err(&client->dev,
+			"media_create_pad_link failed\n");
+		v4l2_device_unregister_subdev(&ssd->sd);
+		return rval;
 	}
 
 	return 0;
 }
 
-static void smiapp_cleanup(struct smiapp_sensor *sensor)
+static void smiapp_unregistered(struct v4l2_subdev *subdev)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-
-	device_remove_file(&client->dev, &dev_attr_nvm);
-	device_remove_file(&client->dev, &dev_attr_ident);
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	unsigned int i;
 
-	smiapp_free_controls(sensor);
+	for (i = 1; i < sensor->ssds_used; i++)
+		v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
 }
 
-static int smiapp_init(struct smiapp_sensor *sensor)
+static int smiapp_registered(struct v4l2_subdev *subdev)
 {
-	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-	struct smiapp_pll *pll = &sensor->pll;
-	struct smiapp_subdev *last = NULL;
-	unsigned int i;
+	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
 	int rval;
 
-	sensor->vana = devm_regulator_get(&client->dev, "vana");
-	if (IS_ERR(sensor->vana)) {
-		dev_err(&client->dev, "could not get regulator for vana\n");
-		return PTR_ERR(sensor->vana);
-	}
-
-	sensor->ext_clk = devm_clk_get(&client->dev, NULL);
-	if (IS_ERR(sensor->ext_clk)) {
-		dev_err(&client->dev, "could not get clock (%ld)\n",
-			PTR_ERR(sensor->ext_clk));
-		return -EPROBE_DEFER;
-	}
-
-	rval = clk_set_rate(sensor->ext_clk,
-			    sensor->hwcfg->ext_clk);
-	if (rval < 0) {
-		dev_err(&client->dev,
-			"unable to set clock freq to %u\n",
-			sensor->hwcfg->ext_clk);
-		return rval;
+	if (sensor->scaler) {
+		rval = smiapp_register_subdev(
+			sensor, sensor->binner, sensor->scaler,
+			SMIAPP_PAD_SRC, SMIAPP_PAD_SINK,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+		if (rval < 0)
+			return rval;
 	}
 
-	sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown",
-						    GPIOD_OUT_LOW);
-	if (IS_ERR(sensor->xshutdown))
-		return PTR_ERR(sensor->xshutdown);
-
-	rval = smiapp_power_on(sensor);
+	rval = smiapp_register_subdev(
+		sensor, sensor->pixel_array, sensor->binner,
+		SMIAPP_PA_PAD_SRC, SMIAPP_PAD_SINK,
+		MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
 	if (rval)
-		return -ENODEV;
-
-	rval = smiapp_identify_module(sensor);
-	if (rval) {
-		rval = -ENODEV;
-		goto out_power_off;
-	}
-
-	rval = smiapp_get_all_limits(sensor);
-	if (rval) {
-		rval = -ENODEV;
-		goto out_power_off;
-	}
-
-	/*
-	 * Handle Sensor Module orientation on the board.
-	 *
-	 * The application of H-FLIP and V-FLIP on the sensor is modified by
-	 * the sensor orientation on the board.
-	 *
-	 * For SMIAPP_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
-	 * both H-FLIP and V-FLIP for normal operation which also implies
-	 * that a set/unset operation for user space HFLIP and VFLIP v4l2
-	 * controls will need to be internally inverted.
-	 *
-	 * Rotation also changes the bayer pattern.
-	 */
-	if (sensor->hwcfg->module_board_orient ==
-	    SMIAPP_MODULE_BOARD_ORIENT_180)
-		sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |
-					  SMIAPP_IMAGE_ORIENTATION_VFLIP;
-
-	rval = smiapp_call_quirk(sensor, limits);
-	if (rval) {
-		dev_err(&client->dev, "limits quirks failed\n");
-		goto out_power_off;
-	}
-
-	if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
-		u32 val;
-
-		rval = smiapp_read(sensor,
-				   SMIAPP_REG_U8_BINNING_SUBTYPES, &val);
-		if (rval < 0) {
-			rval = -ENODEV;
-			goto out_power_off;
-		}
-		sensor->nbinning_subtypes = min_t(u8, val,
-						  SMIAPP_BINNING_SUBTYPES);
-
-		for (i = 0; i < sensor->nbinning_subtypes; i++) {
-			rval = smiapp_read(
-				sensor, SMIAPP_REG_U8_BINNING_TYPE_n(i), &val);
-			if (rval < 0) {
-				rval = -ENODEV;
-				goto out_power_off;
-			}
-			sensor->binning_subtypes[i] =
-				*(struct smiapp_binning_subtype *)&val;
-
-			dev_dbg(&client->dev, "binning %xx%x\n",
-				sensor->binning_subtypes[i].horizontal,
-				sensor->binning_subtypes[i].vertical);
-		}
-	}
-	sensor->binning_horizontal = 1;
-	sensor->binning_vertical = 1;
-
-	if (device_create_file(&client->dev, &dev_attr_ident) != 0) {
-		dev_err(&client->dev, "sysfs ident entry creation failed\n");
-		rval = -ENOENT;
-		goto out_power_off;
-	}
-	/* SMIA++ NVM initialization - it will be read from the sensor
-	 * when it is first requested by userspace.
-	 */
-	if (sensor->minfo.smiapp_version && sensor->hwcfg->nvm_size) {
-		sensor->nvm = devm_kzalloc(&client->dev,
-				sensor->hwcfg->nvm_size, GFP_KERNEL);
-		if (sensor->nvm == NULL) {
-			dev_err(&client->dev, "nvm buf allocation failed\n");
-			rval = -ENOMEM;
-			goto out_cleanup;
-		}
-
-		if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
-			dev_err(&client->dev, "sysfs nvm entry failed\n");
-			rval = -EBUSY;
-			goto out_cleanup;
-		}
-	}
-
-	/* We consider this as profile 0 sensor if any of these are zero. */
-	if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] ||
-	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] ||
-	    !sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV] ||
-	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV]) {
-		sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0;
-	} else if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
-		   != SMIAPP_SCALING_CAPABILITY_NONE) {
-		if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
-		    == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
-			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1;
-		else
-			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2;
-		sensor->scaler = &sensor->ssds[sensor->ssds_used];
-		sensor->ssds_used++;
-	} else if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
-		   == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
-		sensor->scaler = &sensor->ssds[sensor->ssds_used];
-		sensor->ssds_used++;
-	}
-	sensor->binner = &sensor->ssds[sensor->ssds_used];
-	sensor->ssds_used++;
-	sensor->pixel_array = &sensor->ssds[sensor->ssds_used];
-	sensor->ssds_used++;
-
-	sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
-
-	/* prepare PLL configuration input values */
-	pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
-	pll->csi2.lanes = sensor->hwcfg->lanes;
-	pll->ext_clk_freq_hz = sensor->hwcfg->ext_clk;
-	pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
-	/* Profile 0 sensors have no separate OP clock branch. */
-	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
-		pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
-
-	for (i = 0; i < SMIAPP_SUBDEVS; i++) {
-		struct {
-			struct smiapp_subdev *ssd;
-			char *name;
-		} const __this[] = {
-			{ sensor->scaler, "scaler", },
-			{ sensor->binner, "binner", },
-			{ sensor->pixel_array, "pixel array", },
-		}, *_this = &__this[i];
-		struct smiapp_subdev *this = _this->ssd;
-
-		if (!this)
-			continue;
-
-		if (this != sensor->src)
-			v4l2_subdev_init(&this->sd, &smiapp_ops);
-
-		this->sensor = sensor;
+		goto out_err;
 
-		if (this == sensor->pixel_array) {
-			this->npads = 1;
-		} else {
-			this->npads = 2;
-			this->source_pad = 1;
-		}
+	return 0;
 
-		snprintf(this->sd.name,
-			 sizeof(this->sd.name), "%s %s %d-%4.4x",
-			 sensor->minfo.name, _this->name,
-			 i2c_adapter_id(client->adapter), client->addr);
+out_err:
+	smiapp_unregistered(subdev);
 
-		this->sink_fmt.width =
-			sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
-		this->sink_fmt.height =
-			sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
-		this->compose.width = this->sink_fmt.width;
-		this->compose.height = this->sink_fmt.height;
-		this->crop[this->source_pad] = this->compose;
-		this->pads[this->source_pad].flags = MEDIA_PAD_FL_SOURCE;
-		if (this != sensor->pixel_array) {
-			this->crop[this->sink_pad] = this->compose;
-			this->pads[this->sink_pad].flags = MEDIA_PAD_FL_SINK;
-		}
+	return rval;
+}
 
-		this->sd.entity.ops = &smiapp_entity_ops;
+static void smiapp_cleanup(struct smiapp_sensor *sensor)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 
-		if (last == NULL) {
-			last = this;
-			continue;
-		}
+	device_remove_file(&client->dev, &dev_attr_nvm);
+	device_remove_file(&client->dev, &dev_attr_ident);
 
-		this->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-		this->sd.internal_ops = &smiapp_internal_ops;
-		this->sd.owner = THIS_MODULE;
-		v4l2_set_subdevdata(&this->sd, client);
+	smiapp_free_controls(sensor);
+}
 
-		last = this;
-	}
+static void smiapp_create_subdev(struct smiapp_sensor *sensor,
+				 struct smiapp_subdev *ssd, const char *name,
+				 unsigned short num_pads)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 
-	dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile);
+	if (!ssd)
+		return;
 
-	sensor->pixel_array->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+	if (ssd != sensor->src)
+		v4l2_subdev_init(&ssd->sd, &smiapp_ops);
 
-	/* final steps */
-	smiapp_read_frame_fmt(sensor);
-	rval = smiapp_init_controls(sensor);
-	if (rval < 0)
-		goto out_cleanup;
+	ssd->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	ssd->sensor = sensor;
 
-	rval = smiapp_call_quirk(sensor, init);
-	if (rval)
-		goto out_cleanup;
+	ssd->npads = num_pads;
+	ssd->source_pad = num_pads - 1;
 
-	rval = smiapp_get_mbus_formats(sensor);
-	if (rval) {
-		rval = -ENODEV;
-		goto out_cleanup;
-	}
+	snprintf(ssd->sd.name,
+		 sizeof(ssd->sd.name), "%s %s %d-%4.4x", sensor->minfo.name,
+		 name, i2c_adapter_id(client->adapter), client->addr);
 
-	rval = smiapp_init_late_controls(sensor);
-	if (rval) {
-		rval = -ENODEV;
-		goto out_cleanup;
-	}
+	smiapp_get_native_size(ssd, &ssd->sink_fmt);
 
-	mutex_lock(&sensor->mutex);
-	rval = smiapp_update_mode(sensor);
-	mutex_unlock(&sensor->mutex);
-	if (rval) {
-		dev_err(&client->dev, "update mode failed\n");
-		goto out_cleanup;
+	ssd->compose.width = ssd->sink_fmt.width;
+	ssd->compose.height = ssd->sink_fmt.height;
+	ssd->crop[ssd->source_pad] = ssd->compose;
+	ssd->pads[ssd->source_pad].flags = MEDIA_PAD_FL_SOURCE;
+	if (ssd != sensor->pixel_array) {
+		ssd->crop[ssd->sink_pad] = ssd->compose;
+		ssd->pads[ssd->sink_pad].flags = MEDIA_PAD_FL_SINK;
 	}
 
-	sensor->streaming = false;
-	sensor->dev_init_done = true;
-
-	smiapp_power_off(sensor);
-
-	return 0;
-
-out_cleanup:
-	smiapp_cleanup(sensor);
-
-out_power_off:
-	smiapp_power_off(sensor);
-	return rval;
-}
-
-static int smiapp_registered(struct v4l2_subdev *subdev)
-{
-	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
-	struct i2c_client *client = v4l2_get_subdevdata(subdev);
-	int rval;
-
-	if (!client->dev.of_node) {
-		rval = smiapp_init(sensor);
-		if (rval)
-			return rval;
-	}
+	ssd->sd.entity.ops = &smiapp_entity_ops;
 
-	rval = smiapp_register_subdevs(sensor);
-	if (rval)
-		smiapp_cleanup(sensor);
+	if (ssd == sensor->src)
+		return;
 
-	return rval;
+	ssd->sd.internal_ops = &smiapp_internal_ops;
+	ssd->sd.owner = THIS_MODULE;
+	ssd->sd.dev = &client->dev;
+	v4l2_set_subdevdata(&ssd->sd, client);
 }
 
 static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
 	struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
 	struct smiapp_sensor *sensor = ssd->sensor;
-	u32 mbus_code =
-		smiapp_csi_data_formats[smiapp_pixel_order(sensor)].code;
 	unsigned int i;
+	int rval;
 
 	mutex_lock(&sensor->mutex);
 
 	for (i = 0; i < ssd->npads; i++) {
 		struct v4l2_mbus_framefmt *try_fmt =
 			v4l2_subdev_get_try_format(sd, fh->pad, i);
-		struct v4l2_rect *try_crop = v4l2_subdev_get_try_crop(sd, fh->pad, i);
+		struct v4l2_rect *try_crop =
+			v4l2_subdev_get_try_crop(sd, fh->pad, i);
 		struct v4l2_rect *try_comp;
 
-		try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
-		try_fmt->height = sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
-		try_fmt->code = mbus_code;
-		try_fmt->field = V4L2_FIELD_NONE;
+		smiapp_get_native_size(ssd, try_crop);
 
-		try_crop->top = 0;
-		try_crop->left = 0;
-		try_crop->width = try_fmt->width;
-		try_crop->height = try_fmt->height;
+		try_fmt->width = try_crop->width;
+		try_fmt->height = try_crop->height;
+		try_fmt->code = sensor->internal_csi_format->code;
+		try_fmt->field = V4L2_FIELD_NONE;
 
 		if (ssd != sensor->pixel_array)
 			continue;
@@ -2862,12 +2674,23 @@ static int smiapp_open(struct v4l2_subde
 
 	mutex_unlock(&sensor->mutex);
 
-	return smiapp_set_power(sd, 1);
+	rval = pm_runtime_get_sync(sd->dev);
+	if (rval >= 0)
+		return 0;
+
+	if (rval != -EBUSY && rval != -EAGAIN)
+		pm_runtime_set_active(sd->dev);
+	pm_runtime_put(sd->dev);
+
+	return rval;
 }
 
 static int smiapp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
-	return smiapp_set_power(sd, 0);
+	pm_runtime_mark_last_busy(sd->dev);
+	pm_runtime_put_autosuspend(sd->dev);
+
+	return 0;
 }
 
 static const struct v4l2_subdev_video_ops smiapp_video_ops = {
@@ -2904,6 +2727,7 @@ static const struct media_entity_operati
 
 static const struct v4l2_subdev_internal_ops smiapp_internal_src_ops = {
 	.registered = smiapp_registered,
+	.unregistered = smiapp_unregistered,
 	.open = smiapp_open,
 	.close = smiapp_close,
 };
@@ -2917,46 +2741,39 @@ static const struct v4l2_subdev_internal
  * I2C Driver
  */
 
-#ifdef CONFIG_PM
-
-static int smiapp_suspend(struct device *dev)
+static int __maybe_unused smiapp_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
-	bool streaming;
-
-	BUG_ON(mutex_is_locked(&sensor->mutex));
+	bool streaming = sensor->streaming;
+	int rval;
 
-	if (sensor->power_count == 0)
-		return 0;
+	rval = pm_runtime_get_sync(dev);
+	if (rval < 0) {
+		if (rval != -EBUSY && rval != -EAGAIN)
+			pm_runtime_set_active(&client->dev);
+		pm_runtime_put(dev);
+		return -EAGAIN;
+	}
 
 	if (sensor->streaming)
 		smiapp_stop_streaming(sensor);
 
-	streaming = sensor->streaming;
-
-	smiapp_power_off(sensor);
-
 	/* save state for resume */
 	sensor->streaming = streaming;
 
 	return 0;
 }
 
-static int smiapp_resume(struct device *dev)
+static int __maybe_unused smiapp_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
-	int rval;
-
-	if (sensor->power_count == 0)
-		return 0;
+	int rval = 0;
 
-	rval = smiapp_power_on(sensor);
-	if (rval)
-		return rval;
+	pm_runtime_put(dev);
 
 	if (sensor->streaming)
 		rval = smiapp_start_streaming(sensor);
@@ -2964,13 +2781,6 @@ static int smiapp_resume(struct device *
 	return rval;
 }
 
-#else
-
-#define smiapp_suspend	NULL
-#define smiapp_resume	NULL
-
-#endif /* CONFIG_PM */
-
 static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
 {
 	struct smiapp_hwconfig *hwcfg;
@@ -3051,6 +2861,7 @@ static int smiapp_probe(struct i2c_clien
 {
 	struct smiapp_sensor *sensor;
 	struct smiapp_hwconfig *hwcfg = smiapp_get_hwconfig(&client->dev);
+	unsigned int i;
 	int rval;
 
 	if (hwcfg == NULL)
@@ -3062,35 +2873,238 @@ static int smiapp_probe(struct i2c_clien
 
 	sensor->hwcfg = hwcfg;
 	mutex_init(&sensor->mutex);
-	mutex_init(&sensor->power_mutex);
 	sensor->src = &sensor->ssds[sensor->ssds_used];
 
 	v4l2_i2c_subdev_init(&sensor->src->sd, client, &smiapp_ops);
 	sensor->src->sd.internal_ops = &smiapp_internal_src_ops;
-	sensor->src->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-	sensor->src->sensor = sensor;
 
-	sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;
-	rval = media_entity_pads_init(&sensor->src->sd.entity, 2,
-				 sensor->src->pads);
+	sensor->vana = devm_regulator_get(&client->dev, "vana");
+	if (IS_ERR(sensor->vana)) {
+		dev_err(&client->dev, "could not get regulator for vana\n");
+		return PTR_ERR(sensor->vana);
+	}
+
+	sensor->ext_clk = devm_clk_get(&client->dev, NULL);
+	if (IS_ERR(sensor->ext_clk)) {
+		dev_err(&client->dev, "could not get clock (%ld)\n",
+			PTR_ERR(sensor->ext_clk));
+		return -EPROBE_DEFER;
+	}
+
+	rval = clk_set_rate(sensor->ext_clk, sensor->hwcfg->ext_clk);
+	if (rval < 0) {
+		dev_err(&client->dev,
+			"unable to set clock freq to %u\n",
+			sensor->hwcfg->ext_clk);
+		return rval;
+	}
+
+	sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown",
+						    GPIOD_OUT_LOW);
+	if (IS_ERR(sensor->xshutdown))
+		return PTR_ERR(sensor->xshutdown);
+
+	rval = smiapp_power_on(&client->dev);
 	if (rval < 0)
 		return rval;
 
-	if (client->dev.of_node) {
-		rval = smiapp_init(sensor);
-		if (rval)
-			goto out_media_entity_cleanup;
+	rval = smiapp_identify_module(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_power_off;
+	}
+
+	rval = smiapp_get_all_limits(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_power_off;
+	}
+
+	rval = smiapp_read_frame_fmt(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_power_off;
+	}
+
+	/*
+	 * Handle Sensor Module orientation on the board.
+	 *
+	 * The application of H-FLIP and V-FLIP on the sensor is modified by
+	 * the sensor orientation on the board.
+	 *
+	 * For SMIAPP_BOARD_SENSOR_ORIENT_180 the default behaviour is to set
+	 * both H-FLIP and V-FLIP for normal operation which also implies
+	 * that a set/unset operation for user space HFLIP and VFLIP v4l2
+	 * controls will need to be internally inverted.
+	 *
+	 * Rotation also changes the bayer pattern.
+	 */
+	if (sensor->hwcfg->module_board_orient ==
+	    SMIAPP_MODULE_BOARD_ORIENT_180)
+		sensor->hvflip_inv_mask = SMIAPP_IMAGE_ORIENTATION_HFLIP |
+					  SMIAPP_IMAGE_ORIENTATION_VFLIP;
+
+	rval = smiapp_call_quirk(sensor, limits);
+	if (rval) {
+		dev_err(&client->dev, "limits quirks failed\n");
+		goto out_power_off;
+	}
+
+	if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
+		u32 val;
+
+		rval = smiapp_read(sensor,
+				   SMIAPP_REG_U8_BINNING_SUBTYPES, &val);
+		if (rval < 0) {
+			rval = -ENODEV;
+			goto out_power_off;
+		}
+		sensor->nbinning_subtypes = min_t(u8, val,
+						  SMIAPP_BINNING_SUBTYPES);
+
+		for (i = 0; i < sensor->nbinning_subtypes; i++) {
+			rval = smiapp_read(
+				sensor, SMIAPP_REG_U8_BINNING_TYPE_n(i), &val);
+			if (rval < 0) {
+				rval = -ENODEV;
+				goto out_power_off;
+			}
+			sensor->binning_subtypes[i] =
+				*(struct smiapp_binning_subtype *)&val;
+
+			dev_dbg(&client->dev, "binning %xx%x\n",
+				sensor->binning_subtypes[i].horizontal,
+				sensor->binning_subtypes[i].vertical);
+		}
 	}
+	sensor->binning_horizontal = 1;
+	sensor->binning_vertical = 1;
+
+	if (device_create_file(&client->dev, &dev_attr_ident) != 0) {
+		dev_err(&client->dev, "sysfs ident entry creation failed\n");
+		rval = -ENOENT;
+		goto out_power_off;
+	}
+	/* SMIA++ NVM initialization - it will be read from the sensor
+	 * when it is first requested by userspace.
+	 */
+	if (sensor->minfo.smiapp_version && sensor->hwcfg->nvm_size) {
+		sensor->nvm = devm_kzalloc(&client->dev,
+				sensor->hwcfg->nvm_size, GFP_KERNEL);
+		if (sensor->nvm == NULL) {
+			rval = -ENOMEM;
+			goto out_cleanup;
+		}
+
+		if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
+			dev_err(&client->dev, "sysfs nvm entry failed\n");
+			rval = -EBUSY;
+			goto out_cleanup;
+		}
+	}
+
+	/* We consider this as profile 0 sensor if any of these are zero. */
+	if (!sensor->limits[SMIAPP_LIMIT_MIN_OP_SYS_CLK_DIV] ||
+	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_SYS_CLK_DIV] ||
+	    !sensor->limits[SMIAPP_LIMIT_MIN_OP_PIX_CLK_DIV] ||
+	    !sensor->limits[SMIAPP_LIMIT_MAX_OP_PIX_CLK_DIV]) {
+		sensor->minfo.smiapp_profile = SMIAPP_PROFILE_0;
+	} else if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
+		   != SMIAPP_SCALING_CAPABILITY_NONE) {
+		if (sensor->limits[SMIAPP_LIMIT_SCALING_CAPABILITY]
+		    == SMIAPP_SCALING_CAPABILITY_HORIZONTAL)
+			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_1;
+		else
+			sensor->minfo.smiapp_profile = SMIAPP_PROFILE_2;
+		sensor->scaler = &sensor->ssds[sensor->ssds_used];
+		sensor->ssds_used++;
+	} else if (sensor->limits[SMIAPP_LIMIT_DIGITAL_CROP_CAPABILITY]
+		   == SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP) {
+		sensor->scaler = &sensor->ssds[sensor->ssds_used];
+		sensor->ssds_used++;
+	}
+	sensor->binner = &sensor->ssds[sensor->ssds_used];
+	sensor->ssds_used++;
+	sensor->pixel_array = &sensor->ssds[sensor->ssds_used];
+	sensor->ssds_used++;
+
+	sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+
+	/* prepare PLL configuration input values */
+	sensor->pll.bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
+	sensor->pll.csi2.lanes = sensor->hwcfg->lanes;
+	sensor->pll.ext_clk_freq_hz = sensor->hwcfg->ext_clk;
+	sensor->pll.scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+	/* Profile 0 sensors have no separate OP clock branch. */
+	if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
+		sensor->pll.flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+
+	smiapp_create_subdev(sensor, sensor->scaler, "scaler", 2);
+	smiapp_create_subdev(sensor, sensor->binner, "binner", 2);
+	smiapp_create_subdev(sensor, sensor->pixel_array, "pixel_array", 1);
+
+	dev_dbg(&client->dev, "profile %d\n", sensor->minfo.smiapp_profile);
+
+	sensor->pixel_array->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+
+	rval = smiapp_init_controls(sensor);
+	if (rval < 0)
+		goto out_cleanup;
+
+	rval = smiapp_call_quirk(sensor, init);
+	if (rval)
+		goto out_cleanup;
+
+	rval = smiapp_get_mbus_formats(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_cleanup;
+	}
+
+	rval = smiapp_init_late_controls(sensor);
+	if (rval) {
+		rval = -ENODEV;
+		goto out_cleanup;
+	}
+
+	mutex_lock(&sensor->mutex);
+	rval = smiapp_update_mode(sensor);
+	mutex_unlock(&sensor->mutex);
+	if (rval) {
+		dev_err(&client->dev, "update mode failed\n");
+		goto out_cleanup;
+	}
+
+	sensor->streaming = false;
+	sensor->dev_init_done = true;
+
+	rval = media_entity_pads_init(&sensor->src->sd.entity, 2,
+				 sensor->src->pads);
+	if (rval < 0)
+		goto out_media_entity_cleanup;
 
 	rval = v4l2_async_register_subdev(&sensor->src->sd);
 	if (rval < 0)
 		goto out_media_entity_cleanup;
 
+	pm_runtime_set_active(&client->dev);
+	pm_runtime_get_noresume(&client->dev);
+	pm_runtime_enable(&client->dev);
+	pm_runtime_set_autosuspend_delay(&client->dev, 1000);
+	pm_runtime_use_autosuspend(&client->dev);
+	pm_runtime_put_autosuspend(&client->dev);
+
 	return 0;
 
 out_media_entity_cleanup:
 	media_entity_cleanup(&sensor->src->sd.entity);
 
+out_cleanup:
+	smiapp_cleanup(sensor);
+
+out_power_off:
+	smiapp_power_off(&client->dev);
+
 	return rval;
 }
 
@@ -3102,11 +3116,10 @@ static int smiapp_remove(struct i2c_clie
 
 	v4l2_async_unregister_subdev(subdev);
 
-	if (sensor->power_count) {
-		gpiod_set_value(sensor->xshutdown, 0);
-		clk_disable_unprepare(sensor->ext_clk);
-		sensor->power_count = 0;
-	}
+	pm_runtime_disable(&client->dev);
+	if (!pm_runtime_status_suspended(&client->dev))
+		smiapp_power_off(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
 
 	for (i = 0; i < sensor->ssds_used; i++) {
 		v4l2_device_unregister_subdev(&sensor->ssds[i].sd);
@@ -3130,8 +3143,8 @@ static const struct i2c_device_id smiapp
 MODULE_DEVICE_TABLE(i2c, smiapp_id_table);
 
 static const struct dev_pm_ops smiapp_pm_ops = {
-	.suspend	= smiapp_suspend,
-	.resume		= smiapp_resume,
+	SET_SYSTEM_SLEEP_PM_OPS(smiapp_suspend, smiapp_resume)
+	SET_RUNTIME_PM_OPS(smiapp_power_off, smiapp_power_on, NULL)
 };
 
 static struct i2c_driver smiapp_i2c_driver = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/smiapp/smiapp.h linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp/smiapp.h
--- linux-libre-4.9-gnu/drivers/media/i2c/smiapp/smiapp.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp/smiapp.h	2017-02-12 16:03:20.000000000 -0500
@@ -150,11 +150,6 @@ struct smiapp_csi_data_format {
 #define SMIAPP_PAD_SRC			1
 #define SMIAPP_PADS			2
 
-#define SMIAPP_COMPRESSED_BASE		8
-#define SMIAPP_COMPRESSED_MAX		16
-#define SMIAPP_NR_OF_COMPRESSED		(SMIAPP_COMPRESSED_MAX - \
-					 SMIAPP_COMPRESSED_BASE + 1)
-
 struct smiapp_binning_subtype {
 	u8 horizontal:4;
 	u8 vertical:4;
@@ -162,9 +157,9 @@ struct smiapp_binning_subtype {
 
 struct smiapp_subdev {
 	struct v4l2_subdev sd;
-	struct media_pad pads[2];
+	struct media_pad pads[SMIAPP_PADS];
 	struct v4l2_rect sink_fmt;
-	struct v4l2_rect crop[2];
+	struct v4l2_rect crop[SMIAPP_PADS];
 	struct v4l2_rect compose; /* compose on sink */
 	unsigned short sink_pad;
 	unsigned short source_pad;
@@ -181,16 +176,9 @@ struct smiapp_sensor {
 	 * "mutex" is used to serialise access to all fields here
 	 * except v4l2_ctrls at the end of the struct. "mutex" is also
 	 * used to serialise access to file handle specific
-	 * information. The exception to this rule is the power_mutex
-	 * below.
+	 * information.
 	 */
 	struct mutex mutex;
-	/*
-	 * power_mutex is used to serialise power management related
-	 * activities. Acquiring "mutex" at that time isn't necessary
-	 * since there are no other users anyway.
-	 */
-	struct mutex power_mutex;
 	struct smiapp_subdev ssds[SMIAPP_SUBDEVS];
 	u32 ssds_used;
 	struct smiapp_subdev *src;
@@ -218,12 +206,14 @@ struct smiapp_sensor {
 
 	u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
 	u8 frame_skip;
-	u16 image_start;	/* Offset to first line after metadata lines */
-
-	int power_count;
+	u16 embedded_start; /* embedded data start line */
+	u16 embedded_end;
+	u16 image_start; /* image data start line */
+	u16 visible_pixel_start; /* start pixel of the visible image */
 
 	bool streaming;
 	bool dev_init_done;
+	u8 compressed_min_bpp;
 
 	u8 *nvm;		/* nvm memory buffer */
 	unsigned int nvm_size;	/* bytes */
@@ -233,7 +223,7 @@ struct smiapp_sensor {
 	struct smiapp_pll pll;
 
 	/* Is a default format supported for a given BPP? */
-	unsigned long valid_link_freqs[SMIAPP_NR_OF_COMPRESSED];
+	unsigned long *valid_link_freqs;
 
 	/* Pixel array controls */
 	struct v4l2_ctrl *analog_gain;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/smiapp/smiapp-regs.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp/smiapp-regs.c
--- linux-libre-4.9-gnu/drivers/media/i2c/smiapp/smiapp-regs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp/smiapp-regs.c	2017-02-12 16:03:20.000000000 -0500
@@ -268,8 +268,8 @@ int smiapp_write_no_quirk(struct smiapp_
 		if (r == 1) {
 			if (retries)
 				dev_err(&client->dev,
-					"sensor i2c stall encountered. "
-					"retries: %d\n", retries);
+					"sensor i2c stall encountered. retries: %d\n",
+					retries);
 			return 0;
 		}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/smiapp-pll.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp-pll.c
--- linux-libre-4.9-gnu/drivers/media/i2c/smiapp-pll.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/smiapp-pll.c	2017-02-12 16:03:20.000000000 -0500
@@ -479,7 +479,8 @@ int smiapp_pll_calculate(struct device *
 		return 0;
 	}
 
-	dev_info(dev, "unable to compute pre_pll divisor\n");
+	dev_dbg(dev, "unable to compute pre_pll divisor\n");
+
 	return rval;
 }
 EXPORT_SYMBOL_GPL(smiapp_pll_calculate);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/soc_camera/ov772x.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/soc_camera/ov772x.c
--- linux-libre-4.9-gnu/drivers/media/i2c/soc_camera/ov772x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/soc_camera/ov772x.c	2017-02-12 16:03:20.000000000 -0500
@@ -1064,8 +1064,7 @@ static int ov772x_probe(struct i2c_clien
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&adapter->dev,
-			"I2C-Adapter doesn't support "
-			"I2C_FUNC_SMBUS_BYTE_DATA\n");
+			"I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE_DATA\n");
 		return -EIO;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/soc_camera/ov9740.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/soc_camera/ov9740.c
--- linux-libre-4.9-gnu/drivers/media/i2c/soc_camera/ov9740.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/soc_camera/ov9740.c	2017-02-12 16:03:20.000000000 -0500
@@ -881,8 +881,7 @@ static int ov9740_video_probe(struct i2c
 		goto done;
 	}
 
-	dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, "
-		 "Manufacturer 0x%02x, SMIA Version 0x%02x\n",
+	dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, Manufacturer 0x%02x, SMIA Version 0x%02x\n",
 		 priv->model, priv->revision, priv->manid, priv->smiaver);
 
 	ret = v4l2_ctrl_handler_setup(&priv->hdl);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/soc_camera/tw9910.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/soc_camera/tw9910.c
--- linux-libre-4.9-gnu/drivers/media/i2c/soc_camera/tw9910.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/soc_camera/tw9910.c	2017-02-12 16:03:20.000000000 -0500
@@ -947,8 +947,7 @@ static int tw9910_probe(struct i2c_clien
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&client->dev,
-			"I2C-Adapter doesn't support "
-			"I2C_FUNC_SMBUS_BYTE_DATA\n");
+			"I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE_DATA\n");
 		return -EIO;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/tlv320aic23b.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/tlv320aic23b.c
--- linux-libre-4.9-gnu/drivers/media/i2c/tlv320aic23b.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/tlv320aic23b.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/tvaudio.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvaudio.c
--- linux-libre-4.9-gnu/drivers/media/i2c/tvaudio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvaudio.c	2017-02-12 16:03:20.000000000 -0500
@@ -1894,8 +1894,9 @@ static int tvaudio_probe(struct i2c_clie
 		printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n");
 		printk(KERN_INFO "tvaudio: known chips: ");
 		for (desc = chiplist; desc->name != NULL; desc++)
-			printk("%s%s", (desc == chiplist) ? "" : ", ", desc->name);
-		printk("\n");
+			printk(KERN_CONT "%s%s",
+			       (desc == chiplist) ? "" : ", ", desc->name);
+		printk(KERN_CONT "\n");
 	}
 
 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/tvp514x.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvp514x.c
--- linux-libre-4.9-gnu/drivers/media/i2c/tvp514x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvp514x.c	2017-02-12 16:03:20.000000000 -0500
@@ -894,7 +894,7 @@ static int tvp514x_enum_mbus_code(struct
 	if (index != 0)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_YUYV8_2X8;
+	code->code = MEDIA_BUS_FMT_UYVY8_2X8;
 
 	return 0;
 }
@@ -922,7 +922,7 @@ static int tvp514x_get_pad_format(struct
 		return 0;
 	}
 
-	format->format.code = MEDIA_BUS_FMT_YUYV8_2X8;
+	format->format.code = MEDIA_BUS_FMT_UYVY8_2X8;
 	format->format.width = tvp514x_std_list[decoder->current_std].width;
 	format->format.height = tvp514x_std_list[decoder->current_std].height;
 	format->format.colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -946,7 +946,7 @@ static int tvp514x_set_pad_format(struct
 	struct tvp514x_decoder *decoder = to_decoder(sd);
 
 	if (fmt->format.field != V4L2_FIELD_INTERLACED ||
-	    fmt->format.code != MEDIA_BUS_FMT_YUYV8_2X8 ||
+	    fmt->format.code != MEDIA_BUS_FMT_UYVY8_2X8 ||
 	    fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M ||
 	    fmt->format.width != tvp514x_std_list[decoder->current_std].width ||
 	    fmt->format.height != tvp514x_std_list[decoder->current_std].height)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/tvp5150.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvp5150.c
--- linux-libre-4.9-gnu/drivers/media/i2c/tvp5150.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvp5150.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,8 @@ static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
+#define dprintk0(__dev, __arg...) dev_dbg_lvl(__dev, 0, 0, __arg)
+
 struct tvp5150 {
 	struct v4l2_subdev sd;
 #ifdef CONFIG_MEDIA_CONTROLLER
@@ -74,11 +76,11 @@ static int tvp5150_read(struct v4l2_subd
 
 	rc = i2c_smbus_read_byte_data(c, addr);
 	if (rc < 0) {
-		v4l2_err(sd, "i2c i/o error: rc == %d\n", rc);
+		dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc);
 		return rc;
 	}
 
-	v4l2_dbg(2, debug, sd, "tvp5150: read 0x%02x = 0x%02x\n", addr, rc);
+	dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: read 0x%02x = %02x\n", addr, rc);
 
 	return rc;
 }
@@ -89,10 +91,10 @@ static int tvp5150_write(struct v4l2_sub
 	struct i2c_client *c = v4l2_get_subdevdata(sd);
 	int rc;
 
-	v4l2_dbg(2, debug, sd, "tvp5150: writing 0x%02x 0x%02x\n", addr, value);
+	dev_dbg_lvl(sd->dev, 2, debug, "tvp5150: writing %02x %02x\n", addr, value);
 	rc = i2c_smbus_write_byte_data(c, addr, value);
 	if (rc < 0)
-		v4l2_err(sd, "i2c i/o error: rc == %d\n", rc);
+		dev_err(sd->dev, "i2c i/o error: rc == %d\n", rc);
 
 	return rc;
 }
@@ -100,138 +102,140 @@ static int tvp5150_write(struct v4l2_sub
 static void dump_reg_range(struct v4l2_subdev *sd, char *s, u8 init,
 				const u8 end, int max_line)
 {
-	int i = 0;
+	u8 buf[16];
+	int i = 0, j, len;
 
-	while (init != (u8)(end + 1)) {
-		if ((i % max_line) == 0) {
-			if (i > 0)
-				printk("\n");
-			printk("tvp5150: %s reg 0x%02x = ", s, init);
-		}
-		printk("%02x ", tvp5150_read(sd, init));
+	if (max_line > 16) {
+		dprintk0(sd->dev, "too much data to dump\n");
+		return;
+	}
 
-		init++;
-		i++;
+	for (i = init; i < end; i += max_line) {
+		len = (end - i > max_line) ? max_line : end - i;
+
+		for (j = 0; j < len; j++)
+			buf[j] = tvp5150_read(sd, i + j);
+
+		dprintk0(sd->dev, "%s reg %02x = %*ph\n", s, i, len, buf);
 	}
-	printk("\n");
 }
 
 static int tvp5150_log_status(struct v4l2_subdev *sd)
 {
-	printk("tvp5150: Video input source selection #1 = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_VD_IN_SRC_SEL_1));
-	printk("tvp5150: Analog channel controls = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_ANAL_CHL_CTL));
-	printk("tvp5150: Operation mode controls = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_OP_MODE_CTL));
-	printk("tvp5150: Miscellaneous controls = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_MISC_CTL));
-	printk("tvp5150: Autoswitch mask= 0x%02x\n",
-			tvp5150_read(sd, TVP5150_AUTOSW_MSK));
-	printk("tvp5150: Color killer threshold control = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_COLOR_KIL_THSH_CTL));
-	printk("tvp5150: Luminance processing controls #1 #2 and #3 = %02x %02x %02x\n",
-			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_1),
-			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_2),
-			tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_3));
-	printk("tvp5150: Brightness control = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_BRIGHT_CTL));
-	printk("tvp5150: Color saturation control = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_SATURATION_CTL));
-	printk("tvp5150: Hue control = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_HUE_CTL));
-	printk("tvp5150: Contrast control = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_CONTRAST_CTL));
-	printk("tvp5150: Outputs and data rates select = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_DATA_RATE_SEL));
-	printk("tvp5150: Configuration shared pins = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_CONF_SHARED_PIN));
-	printk("tvp5150: Active video cropping start = 0x%02x%02x\n",
-			tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_MSB),
-			tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_LSB));
-	printk("tvp5150: Active video cropping stop  = 0x%02x%02x\n",
-			tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_MSB),
-			tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_LSB));
-	printk("tvp5150: Genlock/RTC = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_GENLOCK));
-	printk("tvp5150: Horizontal sync start = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_HORIZ_SYNC_START));
-	printk("tvp5150: Vertical blanking start = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_VERT_BLANKING_START));
-	printk("tvp5150: Vertical blanking stop = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_VERT_BLANKING_STOP));
-	printk("tvp5150: Chrominance processing control #1 and #2 = %02x %02x\n",
-			tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_1),
-			tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_2));
-	printk("tvp5150: Interrupt reset register B = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INT_RESET_REG_B));
-	printk("tvp5150: Interrupt enable register B = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INT_ENABLE_REG_B));
-	printk("tvp5150: Interrupt configuration register B = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INTT_CONFIG_REG_B));
-	printk("tvp5150: Video standard = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_VIDEO_STD));
-	printk("tvp5150: Chroma gain factor: Cb=0x%02x Cr=0x%02x\n",
-			tvp5150_read(sd, TVP5150_CB_GAIN_FACT),
-			tvp5150_read(sd, TVP5150_CR_GAIN_FACTOR));
-	printk("tvp5150: Macrovision on counter = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_MACROVISION_ON_CTR));
-	printk("tvp5150: Macrovision off counter = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_MACROVISION_OFF_CTR));
-	printk("tvp5150: ITU-R BT.656.%d timing(TVP5150AM1 only)\n",
-			(tvp5150_read(sd, TVP5150_REV_SELECT) & 1) ? 3 : 4);
-	printk("tvp5150: Device ID = %02x%02x\n",
-			tvp5150_read(sd, TVP5150_MSB_DEV_ID),
-			tvp5150_read(sd, TVP5150_LSB_DEV_ID));
-	printk("tvp5150: ROM version = (hex) %02x.%02x\n",
-			tvp5150_read(sd, TVP5150_ROM_MAJOR_VER),
-			tvp5150_read(sd, TVP5150_ROM_MINOR_VER));
-	printk("tvp5150: Vertical line count = 0x%02x%02x\n",
-			tvp5150_read(sd, TVP5150_VERT_LN_COUNT_MSB),
-			tvp5150_read(sd, TVP5150_VERT_LN_COUNT_LSB));
-	printk("tvp5150: Interrupt status register B = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INT_STATUS_REG_B));
-	printk("tvp5150: Interrupt active register B = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INT_ACTIVE_REG_B));
-	printk("tvp5150: Status regs #1 to #5 = %02x %02x %02x %02x %02x\n",
-			tvp5150_read(sd, TVP5150_STATUS_REG_1),
-			tvp5150_read(sd, TVP5150_STATUS_REG_2),
-			tvp5150_read(sd, TVP5150_STATUS_REG_3),
-			tvp5150_read(sd, TVP5150_STATUS_REG_4),
-			tvp5150_read(sd, TVP5150_STATUS_REG_5));
+	dprintk0(sd->dev, "tvp5150: Video input source selection #1 = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_VD_IN_SRC_SEL_1));
+	dprintk0(sd->dev, "tvp5150: Analog channel controls = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_ANAL_CHL_CTL));
+	dprintk0(sd->dev, "tvp5150: Operation mode controls = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_OP_MODE_CTL));
+	dprintk0(sd->dev, "tvp5150: Miscellaneous controls = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_MISC_CTL));
+	dprintk0(sd->dev, "tvp5150: Autoswitch mask= 0x%02x\n",
+		tvp5150_read(sd, TVP5150_AUTOSW_MSK));
+	dprintk0(sd->dev, "tvp5150: Color killer threshold control = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_COLOR_KIL_THSH_CTL));
+	dprintk0(sd->dev, "tvp5150: Luminance processing controls #1 #2 and #3 = %02x %02x %02x\n",
+		tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_1),
+		tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_2),
+		tvp5150_read(sd, TVP5150_LUMA_PROC_CTL_3));
+	dprintk0(sd->dev, "tvp5150: Brightness control = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_BRIGHT_CTL));
+	dprintk0(sd->dev, "tvp5150: Color saturation control = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_SATURATION_CTL));
+	dprintk0(sd->dev, "tvp5150: Hue control = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_HUE_CTL));
+	dprintk0(sd->dev, "tvp5150: Contrast control = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_CONTRAST_CTL));
+	dprintk0(sd->dev, "tvp5150: Outputs and data rates select = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_DATA_RATE_SEL));
+	dprintk0(sd->dev, "tvp5150: Configuration shared pins = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_CONF_SHARED_PIN));
+	dprintk0(sd->dev, "tvp5150: Active video cropping start = 0x%02x%02x\n",
+		tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_MSB),
+		tvp5150_read(sd, TVP5150_ACT_VD_CROP_ST_LSB));
+	dprintk0(sd->dev, "tvp5150: Active video cropping stop  = 0x%02x%02x\n",
+		tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_MSB),
+		tvp5150_read(sd, TVP5150_ACT_VD_CROP_STP_LSB));
+	dprintk0(sd->dev, "tvp5150: Genlock/RTC = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_GENLOCK));
+	dprintk0(sd->dev, "tvp5150: Horizontal sync start = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_HORIZ_SYNC_START));
+	dprintk0(sd->dev, "tvp5150: Vertical blanking start = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_VERT_BLANKING_START));
+	dprintk0(sd->dev, "tvp5150: Vertical blanking stop = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_VERT_BLANKING_STOP));
+	dprintk0(sd->dev, "tvp5150: Chrominance processing control #1 and #2 = %02x %02x\n",
+		tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_1),
+		tvp5150_read(sd, TVP5150_CHROMA_PROC_CTL_2));
+	dprintk0(sd->dev, "tvp5150: Interrupt reset register B = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INT_RESET_REG_B));
+	dprintk0(sd->dev, "tvp5150: Interrupt enable register B = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INT_ENABLE_REG_B));
+	dprintk0(sd->dev, "tvp5150: Interrupt configuration register B = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INTT_CONFIG_REG_B));
+	dprintk0(sd->dev, "tvp5150: Video standard = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_VIDEO_STD));
+	dprintk0(sd->dev, "tvp5150: Chroma gain factor: Cb=0x%02x Cr=0x%02x\n",
+		tvp5150_read(sd, TVP5150_CB_GAIN_FACT),
+		tvp5150_read(sd, TVP5150_CR_GAIN_FACTOR));
+	dprintk0(sd->dev, "tvp5150: Macrovision on counter = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_MACROVISION_ON_CTR));
+	dprintk0(sd->dev, "tvp5150: Macrovision off counter = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_MACROVISION_OFF_CTR));
+	dprintk0(sd->dev, "tvp5150: ITU-R BT.656.%d timing(TVP5150AM1 only)\n",
+		(tvp5150_read(sd, TVP5150_REV_SELECT) & 1) ? 3 : 4);
+	dprintk0(sd->dev, "tvp5150: Device ID = %02x%02x\n",
+		tvp5150_read(sd, TVP5150_MSB_DEV_ID),
+		tvp5150_read(sd, TVP5150_LSB_DEV_ID));
+	dprintk0(sd->dev, "tvp5150: ROM version = (hex) %02x.%02x\n",
+		tvp5150_read(sd, TVP5150_ROM_MAJOR_VER),
+		tvp5150_read(sd, TVP5150_ROM_MINOR_VER));
+	dprintk0(sd->dev, "tvp5150: Vertical line count = 0x%02x%02x\n",
+		tvp5150_read(sd, TVP5150_VERT_LN_COUNT_MSB),
+		tvp5150_read(sd, TVP5150_VERT_LN_COUNT_LSB));
+	dprintk0(sd->dev, "tvp5150: Interrupt status register B = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INT_STATUS_REG_B));
+	dprintk0(sd->dev, "tvp5150: Interrupt active register B = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INT_ACTIVE_REG_B));
+	dprintk0(sd->dev, "tvp5150: Status regs #1 to #5 = %02x %02x %02x %02x %02x\n",
+		tvp5150_read(sd, TVP5150_STATUS_REG_1),
+		tvp5150_read(sd, TVP5150_STATUS_REG_2),
+		tvp5150_read(sd, TVP5150_STATUS_REG_3),
+		tvp5150_read(sd, TVP5150_STATUS_REG_4),
+		tvp5150_read(sd, TVP5150_STATUS_REG_5));
 
 	dump_reg_range(sd, "Teletext filter 1",   TVP5150_TELETEXT_FIL1_INI,
 			TVP5150_TELETEXT_FIL1_END, 8);
 	dump_reg_range(sd, "Teletext filter 2",   TVP5150_TELETEXT_FIL2_INI,
 			TVP5150_TELETEXT_FIL2_END, 8);
 
-	printk("tvp5150: Teletext filter enable = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_TELETEXT_FIL_ENA));
-	printk("tvp5150: Interrupt status register A = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INT_STATUS_REG_A));
-	printk("tvp5150: Interrupt enable register A = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INT_ENABLE_REG_A));
-	printk("tvp5150: Interrupt configuration = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_INT_CONF));
-	printk("tvp5150: VDP status register = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_VDP_STATUS_REG));
-	printk("tvp5150: FIFO word count = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_FIFO_WORD_COUNT));
-	printk("tvp5150: FIFO interrupt threshold = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_FIFO_INT_THRESHOLD));
-	printk("tvp5150: FIFO reset = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_FIFO_RESET));
-	printk("tvp5150: Line number interrupt = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_LINE_NUMBER_INT));
-	printk("tvp5150: Pixel alignment register = 0x%02x%02x\n",
-			tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_HIGH),
-			tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_LOW));
-	printk("tvp5150: FIFO output control = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_FIFO_OUT_CTRL));
-	printk("tvp5150: Full field enable = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_FULL_FIELD_ENA));
-	printk("tvp5150: Full field mode register = 0x%02x\n",
-			tvp5150_read(sd, TVP5150_FULL_FIELD_MODE_REG));
+	dprintk0(sd->dev, "tvp5150: Teletext filter enable = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_TELETEXT_FIL_ENA));
+	dprintk0(sd->dev, "tvp5150: Interrupt status register A = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INT_STATUS_REG_A));
+	dprintk0(sd->dev, "tvp5150: Interrupt enable register A = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INT_ENABLE_REG_A));
+	dprintk0(sd->dev, "tvp5150: Interrupt configuration = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_INT_CONF));
+	dprintk0(sd->dev, "tvp5150: VDP status register = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_VDP_STATUS_REG));
+	dprintk0(sd->dev, "tvp5150: FIFO word count = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_FIFO_WORD_COUNT));
+	dprintk0(sd->dev, "tvp5150: FIFO interrupt threshold = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_FIFO_INT_THRESHOLD));
+	dprintk0(sd->dev, "tvp5150: FIFO reset = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_FIFO_RESET));
+	dprintk0(sd->dev, "tvp5150: Line number interrupt = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_LINE_NUMBER_INT));
+	dprintk0(sd->dev, "tvp5150: Pixel alignment register = 0x%02x%02x\n",
+		tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_HIGH),
+		tvp5150_read(sd, TVP5150_PIX_ALIGN_REG_LOW));
+	dprintk0(sd->dev, "tvp5150: FIFO output control = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_FIFO_OUT_CTRL));
+	dprintk0(sd->dev, "tvp5150: Full field enable = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_FULL_FIELD_ENA));
+	dprintk0(sd->dev, "tvp5150: Full field mode register = 0x%02x\n",
+		tvp5150_read(sd, TVP5150_FULL_FIELD_MODE_REG));
 
 	dump_reg_range(sd, "CC   data",   TVP5150_CC_DATA_INI,
 			TVP5150_CC_DATA_END, 8);
@@ -254,7 +258,7 @@ static int tvp5150_log_status(struct v4l
 			Basic functions
  ****************************************************************************/
 
-static inline void tvp5150_selmux(struct v4l2_subdev *sd)
+static void tvp5150_selmux(struct v4l2_subdev *sd)
 {
 	int opmode = 0;
 	struct tvp5150 *decoder = to_tvp5150(sd);
@@ -280,27 +284,30 @@ static inline void tvp5150_selmux(struct
 		break;
 	}
 
-	v4l2_dbg(1, debug, sd, "Selecting video route: route input=%i, output=%i "
-			"=> tvp5150 input=%i, opmode=%i\n",
+	dev_dbg_lvl(sd->dev, 1, debug, "Selecting video route: route input=%i, output=%i => tvp5150 input=%i, opmode=%i\n",
 			decoder->input, decoder->output,
 			input, opmode);
 
 	tvp5150_write(sd, TVP5150_OP_MODE_CTL, opmode);
 	tvp5150_write(sd, TVP5150_VD_IN_SRC_SEL_1, input);
 
-	/* Svideo should enable YCrCb output and disable GPCL output
-	 * For Composite and TV, it should be the reverse
+	/*
+	 * Setup the FID/GLCO/VLK/HVLK and INTREQ/GPCL/VBLK output signals. For
+	 * S-Video we output the vertical lock (VLK) signal on FID/GLCO/VLK/HVLK
+	 * and set INTREQ/GPCL/VBLK to logic 0. For composite we output the
+	 * field indicator (FID) signal on FID/GLCO/VLK/HVLK and set
+	 * INTREQ/GPCL/VBLK to logic 1.
 	 */
 	val = tvp5150_read(sd, TVP5150_MISC_CTL);
 	if (val < 0) {
-		v4l2_err(sd, "%s: failed with error = %d\n", __func__, val);
+		dev_err(sd->dev, "%s: failed with error = %d\n", __func__, val);
 		return;
 	}
 
 	if (decoder->input == TVP5150_SVIDEO)
-		val = (val & ~0x40) | 0x10;
+		val = (val & ~TVP5150_MISC_CTL_GPCL) | TVP5150_MISC_CTL_HVLK;
 	else
-		val = (val & ~0x10) | 0x40;
+		val = (val & ~TVP5150_MISC_CTL_HVLK) | TVP5150_MISC_CTL_GPCL;
 	tvp5150_write(sd, TVP5150_MISC_CTL, val);
 };
 
@@ -452,7 +459,12 @@ static const struct i2c_reg_value tvp515
 	},{	/* Automatic offset and AGC enabled */
 		TVP5150_ANAL_CHL_CTL, 0x15
 	},{	/* Activate YCrCb output 0x9 or 0xd ? */
-		TVP5150_MISC_CTL, 0x6f
+		TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL |
+				  TVP5150_MISC_CTL_INTREQ_OE |
+				  TVP5150_MISC_CTL_YCBCR_OE |
+				  TVP5150_MISC_CTL_SYNC_OE |
+				  TVP5150_MISC_CTL_VBLANK |
+				  TVP5150_MISC_CTL_CLOCK_OE,
 	},{	/* Activates video std autodetection for all standards */
 		TVP5150_AUTOSW_MSK, 0x0
 	},{	/* Default format: 0x47. For 4:2:2: 0x40 */
@@ -611,7 +623,7 @@ static int tvp5150_g_sliced_vbi_cap(stru
 	const struct i2c_vbi_ram_value *regs = vbi_ram_default;
 	int line;
 
-	v4l2_dbg(1, debug, sd, "g_sliced_vbi_cap\n");
+	dev_dbg_lvl(sd->dev, 1, debug, "g_sliced_vbi_cap\n");
 	memset(cap, 0, sizeof *cap);
 
 	while (regs->reg != (u16)-1 ) {
@@ -649,7 +661,7 @@ static int tvp5150_set_vbi(struct v4l2_s
 	int pos=0;
 
 	if (std == V4L2_STD_ALL) {
-		v4l2_err(sd, "VBI can't be configured without knowing number of lines\n");
+		dev_err(sd->dev, "VBI can't be configured without knowing number of lines\n");
 		return 0;
 	} else if (std & V4L2_STD_625_50) {
 		/* Don't follow NTSC Line number convension */
@@ -697,7 +709,7 @@ static int tvp5150_get_vbi(struct v4l2_s
 	int i, ret = 0;
 
 	if (std == V4L2_STD_ALL) {
-		v4l2_err(sd, "VBI can't be configured without knowing number of lines\n");
+		dev_err(sd->dev, "VBI can't be configured without knowing number of lines\n");
 		return 0;
 	} else if (std & V4L2_STD_625_50) {
 		/* Don't follow NTSC Line number convension */
@@ -712,7 +724,7 @@ static int tvp5150_get_vbi(struct v4l2_s
 	for (i = 0; i <= 1; i++) {
 		ret = tvp5150_read(sd, reg + i);
 		if (ret < 0) {
-			v4l2_err(sd, "%s: failed with error = %d\n",
+			dev_err(sd->dev, "%s: failed with error = %d\n",
 				 __func__, ret);
 			return 0;
 		}
@@ -749,7 +761,7 @@ static int tvp5150_set_std(struct v4l2_s
 			fmt = VIDEO_STD_SECAM_BIT;
 	}
 
-	v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt);
+	dev_dbg_lvl(sd->dev, 1, debug, "Set video std register to %d.\n", fmt);
 	tvp5150_write(sd, TVP5150_VIDEO_STD, fmt);
 	return 0;
 }
@@ -815,6 +827,7 @@ static int tvp5150_s_ctrl(struct v4l2_ct
 		return 0;
 	case V4L2_CID_HUE:
 		tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val);
+		break;
 	case V4L2_CID_TEST_PATTERN:
 		decoder->enable = ctrl->val ? false : true;
 		tvp5150_selmux(sd);
@@ -857,8 +870,6 @@ static int tvp5150_fill_fmt(struct v4l2_
 
 	f = &format->format;
 
-	tvp5150_reset(sd, 0);
-
 	f->width = decoder->rect.width;
 	f->height = decoder->rect.height / 2;
 
@@ -866,7 +877,7 @@ static int tvp5150_fill_fmt(struct v4l2_
 	f->field = V4L2_FIELD_ALTERNATE;
 	f->colorspace = V4L2_COLORSPACE_SMPTE170M;
 
-	v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width,
+	dev_dbg_lvl(sd->dev, 1, debug, "width = %d, height = %d\n", f->width,
 			f->height);
 	return 0;
 }
@@ -884,7 +895,7 @@ static int tvp5150_set_selection(struct
 	    sel->target != V4L2_SEL_TGT_CROP)
 		return -EINVAL;
 
-	v4l2_dbg(1, debug, sd, "%s left=%d, top=%d, width=%d, height=%d\n",
+	dev_dbg_lvl(sd->dev, 1, debug, "%s left=%d, top=%d, width=%d, height=%d\n",
 		__func__, rect.left, rect.top, rect.width, rect.height);
 
 	/* tvp5150 has some special limits */
@@ -1010,11 +1021,11 @@ static int tvp5150_enum_frame_size(struc
 			Media entity ops
  ****************************************************************************/
 
+#ifdef CONFIG_MEDIA_CONTROLLER
 static int tvp5150_link_setup(struct media_entity *entity,
 			      const struct media_pad *local,
 			      const struct media_pad *remote, u32 flags)
 {
-#ifdef CONFIG_MEDIA_CONTROLLER
 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
 	struct tvp5150 *decoder = to_tvp5150(sd);
 	int i;
@@ -1031,7 +1042,6 @@ static int tvp5150_link_setup(struct med
 	decoder->input = i;
 
 	tvp5150_selmux(sd);
-#endif
 
 	return 0;
 }
@@ -1039,6 +1049,7 @@ static int tvp5150_link_setup(struct med
 static const struct media_entity_operations tvp5150_sd_media_ops = {
 	.link_setup = tvp5150_link_setup,
 };
+#endif
 
 /****************************************************************************
 			I2C Command
@@ -1047,21 +1058,27 @@ static const struct media_entity_operati
 static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
-	/* Output format: 8-bit ITU-R BT.656 with embedded syncs */
-	int val = 0x09;
+	int val;
 
-	/* Output format: 8-bit 4:2:2 YUV with discrete sync */
-	if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
-		val = 0x0d;
+	/* Enable or disable the video output signals. */
+	val = tvp5150_read(sd, TVP5150_MISC_CTL);
+	if (val < 0)
+		return val;
 
-	/* Initializes TVP5150 to its default values */
-	/* # set PCLK (27MHz) */
-	tvp5150_write(sd, TVP5150_CONF_SHARED_PIN, 0x00);
+	val &= ~(TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
+		 TVP5150_MISC_CTL_CLOCK_OE);
 
-	if (enable)
-		tvp5150_write(sd, TVP5150_MISC_CTL, val);
-	else
-		tvp5150_write(sd, TVP5150_MISC_CTL, 0x00);
+	if (enable) {
+		/*
+		 * Enable the YCbCr and clock outputs. In discrete sync mode
+		 * (non-BT.656) additionally enable the the sync outputs.
+		 */
+		val |= TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
+		if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
+			val |= TVP5150_MISC_CTL_SYNC_OE;
+	}
+
+	tvp5150_write(sd, TVP5150_MISC_CTL, val);
 
 	return 0;
 }
@@ -1148,7 +1165,7 @@ static int tvp5150_g_register(struct v4l
 
 	res = tvp5150_read(sd, reg->reg & 0xff);
 	if (res < 0) {
-		v4l2_err(sd, "%s: failed with error = %d\n", __func__, res);
+		dev_err(sd->dev, "%s: failed with error = %d\n", __func__, res);
 		return res;
 	}
 
@@ -1288,21 +1305,21 @@ static int tvp5150_detect_version(struct
 	core->dev_id = (regs[0] << 8) | regs[1];
 	core->rom_ver = (regs[2] << 8) | regs[3];
 
-	v4l2_info(sd, "tvp%04x (%u.%u) chip found @ 0x%02x (%s)\n",
+	dev_info(sd->dev, "tvp%04x (%u.%u) chip found @ 0x%02x (%s)\n",
 		  core->dev_id, regs[2], regs[3], c->addr << 1,
 		  c->adapter->name);
 
 	if (core->dev_id == 0x5150 && core->rom_ver == 0x0321) {
-		v4l2_info(sd, "tvp5150a detected.\n");
+		dev_info(sd->dev, "tvp5150a detected.\n");
 	} else if (core->dev_id == 0x5150 && core->rom_ver == 0x0400) {
-		v4l2_info(sd, "tvp5150am1 detected.\n");
+		dev_info(sd->dev, "tvp5150am1 detected.\n");
 
 		/* ITU-T BT.656.4 timing */
 		tvp5150_write(sd, TVP5150_REV_SELECT, 0);
 	} else if (core->dev_id == 0x5151 && core->rom_ver == 0x0100) {
-		v4l2_info(sd, "tvp5151 detected.\n");
+		dev_info(sd->dev, "tvp5151 detected.\n");
 	} else {
-		v4l2_info(sd, "*** unknown tvp%04x chip detected.\n",
+		dev_info(sd->dev, "*** unknown tvp%04x chip detected.\n",
 			  core->dev_id);
 	}
 
@@ -1381,7 +1398,7 @@ static int tvp5150_parse_dt(struct tvp51
 	for_each_available_child_of_node(connectors, child) {
 		ret = of_property_read_u32(child, "input", &input_type);
 		if (ret) {
-			v4l2_err(&decoder->sd,
+			dev_err(decoder->sd.dev,
 				 "missing type property in node %s\n",
 				 child->name);
 			goto err_connector;
@@ -1396,7 +1413,7 @@ static int tvp5150_parse_dt(struct tvp51
 
 		/* Each input connector can only be defined once */
 		if (input->name) {
-			v4l2_err(&decoder->sd,
+			dev_err(decoder->sd.dev,
 				 "input %s with same type already exists\n",
 				 input->name);
 			ret = -EINVAL;
@@ -1417,7 +1434,7 @@ static int tvp5150_parse_dt(struct tvp51
 
 		ret = of_property_read_string(child, "label", &name);
 		if (ret < 0) {
-			v4l2_err(&decoder->sd,
+			dev_err(decoder->sd.dev,
 				 "missing label property in node %s\n",
 				 child->name);
 			goto err_connector;
@@ -1465,7 +1482,7 @@ static int tvp5150_probe(struct i2c_clie
 	if (IS_ENABLED(CONFIG_OF) && np) {
 		res = tvp5150_parse_dt(core, np);
 		if (res) {
-			v4l2_err(sd, "DT parsing error: %d\n", res);
+			dev_err(sd->dev, "DT parsing error: %d\n", res);
 			return res;
 		}
 	} else {
@@ -1520,7 +1537,6 @@ static int tvp5150_probe(struct i2c_clie
 		res = core->hdl.error;
 		goto err;
 	}
-	v4l2_ctrl_handler_setup(&core->hdl);
 
 	/* Default is no cropping */
 	core->rect.top = 0;
@@ -1531,6 +1547,8 @@ static int tvp5150_probe(struct i2c_clie
 	core->rect.left = 0;
 	core->rect.width = TVP5150_H_MAX;
 
+	tvp5150_reset(sd, 0);	/* Calls v4l2_ctrl_handler_setup() */
+
 	res = v4l2_async_register_subdev(sd);
 	if (res < 0)
 		goto err;
@@ -1549,7 +1567,7 @@ static int tvp5150_remove(struct i2c_cli
 	struct v4l2_subdev *sd = i2c_get_clientdata(c);
 	struct tvp5150 *decoder = to_tvp5150(sd);
 
-	v4l2_dbg(1, debug, sd,
+	dev_dbg_lvl(sd->dev, 1, debug,
 		"tvp5150.c: removing tvp5150 adapter on address 0x%x\n",
 		c->addr << 1);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/tvp5150_reg.h linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvp5150_reg.h
--- linux-libre-4.9-gnu/drivers/media/i2c/tvp5150_reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/tvp5150_reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -9,6 +9,15 @@
 #define TVP5150_ANAL_CHL_CTL         0x01 /* Analog channel controls */
 #define TVP5150_OP_MODE_CTL          0x02 /* Operation mode controls */
 #define TVP5150_MISC_CTL             0x03 /* Miscellaneous controls */
+#define TVP5150_MISC_CTL_VBLK_GPCL	BIT(7)
+#define TVP5150_MISC_CTL_GPCL		BIT(6)
+#define TVP5150_MISC_CTL_INTREQ_OE	BIT(5)
+#define TVP5150_MISC_CTL_HVLK		BIT(4)
+#define TVP5150_MISC_CTL_YCBCR_OE	BIT(3)
+#define TVP5150_MISC_CTL_SYNC_OE	BIT(2)
+#define TVP5150_MISC_CTL_VBLANK		BIT(1)
+#define TVP5150_MISC_CTL_CLOCK_OE	BIT(0)
+
 #define TVP5150_AUTOSW_MSK           0x04 /* Autoswitch mask: TVP5150A / TVP5150AM */
 
 /* Reserved 05h */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/vp27smpx.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/vp27smpx.c
--- linux-libre-4.9-gnu/drivers/media/i2c/vp27smpx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/vp27smpx.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/vpx3220.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/vpx3220.c
--- linux-libre-4.9-gnu/drivers/media/i2c/vpx3220.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/vpx3220.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/wm8739.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/wm8739.c
--- linux-libre-4.9-gnu/drivers/media/i2c/wm8739.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/wm8739.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/i2c/wm8775.c linux-libre-4.10-rc8-gnu/drivers/media/i2c/wm8775.c
--- linux-libre-4.9-gnu/drivers/media/i2c/wm8775.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/i2c/wm8775.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,7 +29,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/ioctl.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/Kconfig
--- linux-libre-4.9-gnu/drivers/media/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -80,6 +80,22 @@ config MEDIA_RC_SUPPORT
 
 	  Say Y when you have a TV or an IR device.
 
+config MEDIA_CEC_SUPPORT
+	bool "HDMI CEC support"
+	select MEDIA_CEC_EDID
+	---help---
+	  Enable support for HDMI CEC (Consumer Electronics Control),
+	  which is an optional HDMI feature.
+
+	  Say Y when you have an HDMI receiver, transmitter or a USB CEC
+	  adapter that supports HDMI CEC.
+
+config MEDIA_CEC_DEBUG
+	bool "HDMI CEC debugfs interface"
+	depends on MEDIA_CEC_SUPPORT && DEBUG_FS
+	---help---
+	  Turns on the DebugFS interface for CEC devices.
+
 config MEDIA_CEC_EDID
 	bool
 
@@ -99,7 +115,7 @@ config MEDIA_CONTROLLER
 
 config MEDIA_CONTROLLER_DVB
 	bool "Enable Media controller for DVB (EXPERIMENTAL)"
-	depends on MEDIA_CONTROLLER
+	depends on MEDIA_CONTROLLER && DVB_CORE
 	---help---
 	  Enable the media controller API support for DVB.
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/Makefile linux-libre-4.10-rc8-gnu/drivers/media/Makefile
--- linux-libre-4.9-gnu/drivers/media/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,10 @@ ifeq ($(CONFIG_MEDIA_CEC_EDID),y)
   obj-$(CONFIG_MEDIA_SUPPORT) += cec-edid.o
 endif
 
+ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y)
+  obj-$(CONFIG_MEDIA_SUPPORT) += cec/
+endif
+
 media-objs	:= media-device.o media-devnode.o media-entity.o
 
 #
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/media-device.c linux-libre-4.10-rc8-gnu/drivers/media/media-device.c
--- linux-libre-4.9-gnu/drivers/media/media-device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/media-device.c	2017-02-12 16:03:20.000000000 -0500
@@ -801,9 +801,13 @@ void media_device_unregister(struct medi
 	/* Remove all interfaces from the media device */
 	list_for_each_entry_safe(intf, tmp_intf, &mdev->interfaces,
 				 graph_obj.list) {
+		/*
+		 * Unlink the interface, but don't free it here; the
+		 * module which created it is responsible for freeing
+		 * it
+		 */
 		__media_remove_intf_links(intf);
 		media_gobj_destroy(&intf->graph_obj);
-		kfree(intf);
 	}
 
 	mutex_unlock(&mdev->graph_mutex);
@@ -817,32 +821,6 @@ void media_device_unregister(struct medi
 }
 EXPORT_SYMBOL_GPL(media_device_unregister);
 
-static void media_device_release_devres(struct device *dev, void *res)
-{
-}
-
-struct media_device *media_device_get_devres(struct device *dev)
-{
-	struct media_device *mdev;
-
-	mdev = devres_find(dev, media_device_release_devres, NULL, NULL);
-	if (mdev)
-		return mdev;
-
-	mdev = devres_alloc(media_device_release_devres,
-				sizeof(struct media_device), GFP_KERNEL);
-	if (!mdev)
-		return NULL;
-	return devres_get(dev, mdev, NULL, NULL);
-}
-EXPORT_SYMBOL_GPL(media_device_get_devres);
-
-struct media_device *media_device_find_devres(struct device *dev)
-{
-	return devres_find(dev, media_device_release_devres, NULL, NULL);
-}
-EXPORT_SYMBOL_GPL(media_device_find_devres);
-
 #if IS_ENABLED(CONFIG_PCI)
 void media_device_pci_init(struct media_device *mdev,
 			   struct pci_dev *pci_dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/media-entity.c linux-libre-4.10-rc8-gnu/drivers/media/media-entity.c
--- linux-libre-4.9-gnu/drivers/media/media-entity.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/media-entity.c	2017-02-12 16:03:20.000000000 -0500
@@ -205,10 +205,16 @@ void media_gobj_destroy(struct media_gob
 {
 	dev_dbg_obj(__func__, gobj);
 
+	/* Do nothing if the object is not linked. */
+	if (gobj->mdev == NULL)
+		return;
+
 	gobj->mdev->topology_version++;
 
 	/* Remove the object from mdev list */
 	list_del(&gobj->list);
+
+	gobj->mdev = NULL;
 }
 
 int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/b2c2/flexcop-dma.c linux-libre-4.10-rc8-gnu/drivers/media/pci/b2c2/flexcop-dma.c
--- linux-libre-4.9-gnu/drivers/media/pci/b2c2/flexcop-dma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/b2c2/flexcop-dma.c	2017-02-12 16:03:20.000000000 -0500
@@ -57,8 +57,7 @@ int flexcop_dma_config(struct flexcop_de
 		fc->write_ibi_reg(fc,dma2_014,v0x4);
 		fc->write_ibi_reg(fc,dma2_01c,v0xc);
 	} else {
-		err("either DMA1 or DMA2 can be configured within one "
-			"flexcop_dma_config call.");
+		err("either DMA1 or DMA2 can be configured within one flexcop_dma_config call.");
 		return -EINVAL;
 	}
 
@@ -82,8 +81,7 @@ int flexcop_dma_xfer_control(struct flex
 		r0x0 = dma2_010;
 		r0xc = dma2_01c;
 	} else {
-		err("either transfer DMA1 or DMA2 can be started within one "
-			"flexcop_dma_xfer_control call.");
+		err("either transfer DMA1 or DMA2 can be started within one flexcop_dma_xfer_control call.");
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/b2c2/flexcop-pci.c linux-libre-4.10-rc8-gnu/drivers/media/pci/b2c2/flexcop-pci.c
--- linux-libre-4.9-gnu/drivers/media/pci/b2c2/flexcop-pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/b2c2/flexcop-pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -185,8 +185,7 @@ static irqreturn_t flexcop_pci_isr(int i
 			fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
 		u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
 
-		deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, "
-			"last_cur_pos: %08x ",
+		deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
 				jiffies_to_usecs(jiffies - fc_pci->last_irq),
 				v.raw, (unsigned long long)cur_addr, cur_pos,
 				fc_pci->last_dma1_cur_pos);
@@ -220,8 +219,8 @@ static irqreturn_t flexcop_pci_isr(int i
 		fc_pci->last_dma1_cur_pos = cur_pos;
 		fc_pci->count++;
 	} else {
-		deb_irq("isr for flexcop called, "
-			"apparently without reason (%08x)\n", v.raw);
+		deb_irq("isr for flexcop called, apparently without reason (%08x)\n",
+			v.raw);
 		ret = IRQ_NONE;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/bt8xx/btcx-risc.c linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/btcx-risc.c
--- linux-libre-4.9-gnu/drivers/media/pci/bt8xx/btcx-risc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/btcx-risc.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,8 @@
 
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -36,6 +38,13 @@ static unsigned int btcx_debug;
 module_param(btcx_debug, int, 0644);
 MODULE_PARM_DESC(btcx_debug,"debug messages, default is 0 (no)");
 
+#define dprintk(fmt, arg...) do {				\
+	if (btcx_debug)						\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),		\
+		       __func__, ##arg);			\
+} while (0)
+
+
 /* ---------------------------------------------------------- */
 /* allocate/free risc memory                                  */
 
@@ -46,11 +55,11 @@ void btcx_riscmem_free(struct pci_dev *p
 {
 	if (NULL == risc->cpu)
 		return;
-	if (btcx_debug) {
-		memcnt--;
-		printk("btcx: riscmem free [%d] dma=%lx\n",
-		       memcnt, (unsigned long)risc->dma);
-	}
+
+	memcnt--;
+	dprintk("btcx: riscmem free [%d] dma=%lx\n",
+		memcnt, (unsigned long)risc->dma);
+
 	pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
 	memset(risc,0,sizeof(*risc));
 }
@@ -71,11 +80,10 @@ int btcx_riscmem_alloc(struct pci_dev *p
 		risc->cpu  = cpu;
 		risc->dma  = dma;
 		risc->size = size;
-		if (btcx_debug) {
-			memcnt++;
-			printk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
-			       memcnt, (unsigned long)dma, cpu, size);
-		}
+
+		memcnt++;
+		dprintk("btcx: riscmem alloc [%d] dma=%lx cpu=%p size=%d\n",
+			memcnt, (unsigned long)dma, cpu, size);
 	}
 	memset(risc->cpu,0,risc->size);
 	return 0;
@@ -137,9 +145,8 @@ btcx_align(struct v4l2_rect *win, struct
 	dx = nx - win->left;
 	win->left  = nx;
 	win->width = nw;
-	if (btcx_debug)
-		printk(KERN_DEBUG "btcx: window align %dx%d+%d+%d [dx=%d]\n",
-		       win->width, win->height, win->left, win->top, dx);
+	dprintk("btcx: window align %dx%d+%d+%d [dx=%d]\n",
+	       win->width, win->height, win->left, win->top, dx);
 
 	/* fixup clips */
 	for (i = 0; i < n; i++) {
@@ -149,10 +156,9 @@ btcx_align(struct v4l2_rect *win, struct
 			nw += mask+1;
 		clips[i].c.left  = nx;
 		clips[i].c.width = nw;
-		if (btcx_debug)
-			printk(KERN_DEBUG "btcx:   clip align %dx%d+%d+%d\n",
-			       clips[i].c.width, clips[i].c.height,
-			       clips[i].c.left, clips[i].c.top);
+		dprintk("btcx:   clip align %dx%d+%d+%d\n",
+		       clips[i].c.width, clips[i].c.height,
+		       clips[i].c.left, clips[i].c.top);
 	}
 	return 0;
 }
@@ -228,10 +234,10 @@ btcx_calc_skips(int line, int width, int
 	*maxy = maxline;
 
 	if (btcx_debug) {
-		printk(KERN_DEBUG "btcx: skips line %d-%d:",line,maxline);
+		dprintk("btcx: skips line %d-%d:", line, maxline);
 		for (skip = 0; skip < *nskips; skip++) {
-			printk(" %d-%d",skips[skip].start,skips[skip].end);
+			pr_cont(" %d-%d", skips[skip].start, skips[skip].end);
 		}
-		printk("\n");
+		pr_cont("\n");
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-cards.c linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-cards.c
--- linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-cards.c	2016-12-11 17:47:03.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-cards.c	2017-02-12 17:33:57.000000000 -0500
@@ -125,10 +125,8 @@ module_param_array(remote,   int, NULL,
 module_param_array(audiodev, int, NULL, 0444);
 module_param_array(audiomux, int, NULL, 0444);
 
-MODULE_PARM_DESC(triton1,"set ETBF pci config bit "
-		 "[enable bug compatibility for triton1 + others]");
-MODULE_PARM_DESC(vsfx,"set VSFX pci config bit "
-		 "[yet another chipset flaw workaround]");
+MODULE_PARM_DESC(triton1, "set ETBF pci config bit [enable bug compatibility for triton1 + others]");
+MODULE_PARM_DESC(vsfx, "set VSFX pci config bit [yet another chipset flaw workaround]");
 MODULE_PARM_DESC(latency,"pci latency timer");
 MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
 MODULE_PARM_DESC(pll, "specify installed crystal (0=none, 28=28 MHz, 35=35 MHz, 14=14 MHz)");
@@ -141,8 +139,7 @@ MODULE_PARM_DESC(audiodev, "specify audi
 		"\t\t 2 = tda7432\n"
 		"\t\t 3 = tvaudio");
 MODULE_PARM_DESC(saa6588, "if 1, then load the saa6588 RDS module, default (0) is to use the card definition.");
-MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
-		" [some VIA/SIS chipsets are known to have problem with overlay]");
+MODULE_PARM_DESC(no_overlay, "allow override overlay default (0 disables, 1 enables) [some VIA/SIS chipsets are known to have problem with overlay]");
 
 /* ----------------------------------------------------------------------- */
 /* list of card IDs for bt878+ cards                                       */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-driver.c linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-driver.c
--- linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -148,8 +148,7 @@ MODULE_PARM_DESC(irq_debug, "irq handler
 MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
 MODULE_PARM_DESC(gbuffers, "number of capture buffers. range 2-32, default 8");
 MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 0x208000");
-MODULE_PARM_DESC(reset_crop, "reset cropping parameters at open(), default "
-		 "is 1 (yes) for compatibility with older applications");
+MODULE_PARM_DESC(reset_crop, "reset cropping parameters at open(), default is 1 (yes) for compatibility with older applications");
 MODULE_PARM_DESC(automute, "mute audio on bad/missing video signal, default is 1 (yes)");
 MODULE_PARM_DESC(chroma_agc, "enables the AGC of chroma signal, default is 0 (no)");
 MODULE_PARM_DESC(agc_crush, "enables the luminance AGC crush, default is 1 (yes)");
@@ -3506,8 +3505,7 @@ static void bttv_irq_debug_low_latency(s
 		(unsigned long)rc);
 
 	if (0 == (btread(BT848_DSTATUS) & BT848_DSTATUS_HLOC)) {
-		pr_notice("%d: Oh, there (temporarily?) is no input signal. "
-			  "Ok, then this is harmless, don't worry ;)\n",
+		pr_notice("%d: Oh, there (temporarily?) is no input signal. Ok, then this is harmless, don't worry ;)\n",
 			  btv->c.nr);
 		return;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-i2c.c
--- linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,15 +44,13 @@ static int i2c_scan;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug, "configure i2c debug level");
 module_param(i2c_hw,    int, 0444);
-MODULE_PARM_DESC(i2c_hw,"force use of hardware i2c support, "
-			"instead of software bitbang");
+MODULE_PARM_DESC(i2c_hw, "force use of hardware i2c support, instead of software bitbang");
 module_param(i2c_scan,  int, 0444);
 MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
 
 static unsigned int i2c_udelay = 5;
 module_param(i2c_udelay, int, 0444);
-MODULE_PARM_DESC(i2c_udelay,"soft i2c delay at insmod time, in usecs "
-		"(should be 5 or higher). Lower value means higher bus speed.");
+MODULE_PARM_DESC(i2c_udelay, "soft i2c delay at insmod time, in usecs (should be 5 or higher). Lower value means higher bus speed.");
 
 /* ----------------------------------------------------------------------- */
 /* I2C functions - bitbanging adapter (software i2c)                       */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-input.c linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-input.c
--- linux-libre-4.9-gnu/drivers/media/pci/bt8xx/bttv-input.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/bttv-input.c	2017-02-12 16:03:20.000000000 -0500
@@ -185,8 +185,8 @@ static u32 bttv_rc5_decode(unsigned int
 			return 0;
 		}
 	}
-	dprintk("code=%x, rc5=%x, start=%x, toggle=%x, address=%x, "
-		"instr=%x\n", rc5, org_code, RC5_START(rc5),
+	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;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/bt8xx/dst.c linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/dst.c
--- linux-libre-4.9-gnu/drivers/media/pci/bt8xx/dst.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/dst.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@
 	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -30,9 +32,9 @@
 #include "dst_priv.h"
 #include "dst_common.h"
 
-static unsigned int verbose = 1;
+static unsigned int verbose;
 module_param(verbose, int, 0644);
-MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+MODULE_PARM_DESC(verbose, "verbosity level (0 to 3)");
 
 static unsigned int dst_addons;
 module_param(dst_addons, int, 0644);
@@ -46,29 +48,10 @@ MODULE_PARM_DESC(dst_algo, "tuning algo:
 #define ATTEMPT_TUNE		2
 #define HAS_POWER		4
 
-#define DST_ERROR		0
-#define DST_NOTICE		1
-#define DST_INFO		2
-#define DST_DEBUG		3
-
-#define dprintk(x, y, z, format, arg...) do {				\
-	if (z) {							\
-		if	((x > DST_ERROR) && (x > y))			\
-			printk(KERN_ERR "dst(%d) %s: " format "\n",	\
-				state->bt->nr, __func__ , ##arg);	\
-		else if	((x > DST_NOTICE) && (x > y))			\
-			printk(KERN_NOTICE "dst(%d) %s: " format "\n",  \
-				state->bt->nr, __func__ , ##arg);	\
-		else if ((x > DST_INFO) && (x > y))			\
-			printk(KERN_INFO "dst(%d) %s: " format "\n",	\
-				state->bt->nr, __func__ , ##arg);	\
-		else if ((x > DST_DEBUG) && (x > y))			\
-			printk(KERN_DEBUG "dst(%d) %s: " format "\n",	\
-				state->bt->nr,  __func__ , ##arg);	\
-	} else {							\
-		if (x > y)						\
-			printk(format, ##arg);				\
-	}								\
+#define dprintk(level, fmt, arg...) do {				\
+	if (level >= verbose)						\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\
+		       __func__, ##arg);				\
 } while(0)
 
 static int dst_command(struct dst_state *state, u8 *data, u8 len);
@@ -91,9 +74,11 @@ static int dst_gpio_outb(struct dst_stat
 	enb.enb.mask = mask;
 	enb.enb.enable = enbb;
 
-	dprintk(verbose, DST_INFO, 1, "mask=[%04x], enbb=[%04x], outhigh=[%04x]", mask, enbb, outhigh);
+	dprintk(2, "mask=[%04x], enbb=[%04x], outhigh=[%04x]\n",
+		mask, enbb, outhigh);
 	if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
-		dprintk(verbose, DST_INFO, 1, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)", err, mask, enbb);
+		dprintk(2, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n",
+			err, mask, enbb);
 		return -EREMOTEIO;
 	}
 	udelay(1000);
@@ -105,7 +90,8 @@ static int dst_gpio_outb(struct dst_stat
 	bits.outp.mask = enbb;
 	bits.outp.highvals = outhigh;
 	if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
-		dprintk(verbose, DST_INFO, 1, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)", err, enbb, outhigh);
+		dprintk(2, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n",
+			err, enbb, outhigh);
 		return -EREMOTEIO;
 	}
 
@@ -119,7 +105,7 @@ static int dst_gpio_inb(struct dst_state
 
 	*result = 0;
 	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
+		pr_err("dst_gpio_inb error (err == %i)\n", err);
 		return -EREMOTEIO;
 	}
 	*result = (u8) rd_packet.rd.value;
@@ -129,14 +115,14 @@ static int dst_gpio_inb(struct dst_state
 
 int rdc_reset_state(struct dst_state *state)
 {
-	dprintk(verbose, DST_INFO, 1, "Resetting state machine");
+	dprintk(2, "Resetting state machine\n");
 	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		pr_err("dst_gpio_outb ERROR !\n");
 		return -1;
 	}
 	msleep(10);
 	if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		pr_err("dst_gpio_outb ERROR !\n");
 		msleep(10);
 		return -1;
 	}
@@ -147,14 +133,14 @@ EXPORT_SYMBOL(rdc_reset_state);
 
 static int rdc_8820_reset(struct dst_state *state)
 {
-	dprintk(verbose, DST_DEBUG, 1, "Resetting DST");
+	dprintk(3, "Resetting DST\n");
 	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		pr_err("dst_gpio_outb ERROR !\n");
 		return -1;
 	}
 	udelay(1000);
 	if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		pr_err("dst_gpio_outb ERROR !\n");
 		return -1;
 	}
 
@@ -164,7 +150,7 @@ static int rdc_8820_reset(struct dst_sta
 static int dst_pio_enable(struct dst_state *state)
 {
 	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		pr_err("dst_gpio_outb ERROR !\n");
 		return -1;
 	}
 	udelay(1000);
@@ -175,7 +161,7 @@ static int dst_pio_enable(struct dst_sta
 int dst_pio_disable(struct dst_state *state)
 {
 	if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_outb ERROR !");
+		pr_err("dst_gpio_outb ERROR !\n");
 		return -1;
 	}
 	if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -192,16 +178,16 @@ int dst_wait_dst_ready(struct dst_state
 
 	for (i = 0; i < 200; i++) {
 		if (dst_gpio_inb(state, &reply) < 0) {
-			dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb ERROR !");
+			pr_err("dst_gpio_inb ERROR !\n");
 			return -1;
 		}
 		if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
-			dprintk(verbose, DST_INFO, 1, "dst wait ready after %d", i);
+			dprintk(2, "dst wait ready after %d\n", i);
 			return 1;
 		}
 		msleep(10);
 	}
-	dprintk(verbose, DST_NOTICE, 1, "dst wait NOT ready after %d", i);
+	dprintk(1, "dst wait NOT ready after %d\n", i);
 
 	return 0;
 }
@@ -209,7 +195,7 @@ EXPORT_SYMBOL(dst_wait_dst_ready);
 
 int dst_error_recovery(struct dst_state *state)
 {
-	dprintk(verbose, DST_NOTICE, 1, "Trying to return from previous errors.");
+	dprintk(1, "Trying to return from previous errors.\n");
 	dst_pio_disable(state);
 	msleep(10);
 	dst_pio_enable(state);
@@ -221,7 +207,7 @@ EXPORT_SYMBOL(dst_error_recovery);
 
 int dst_error_bailout(struct dst_state *state)
 {
-	dprintk(verbose, DST_INFO, 1, "Trying to bailout from previous error.");
+	dprintk(2, "Trying to bailout from previous error.\n");
 	rdc_8820_reset(state);
 	dst_pio_disable(state);
 	msleep(10);
@@ -232,13 +218,13 @@ EXPORT_SYMBOL(dst_error_bailout);
 
 int dst_comm_init(struct dst_state *state)
 {
-	dprintk(verbose, DST_INFO, 1, "Initializing DST.");
+	dprintk(2, "Initializing DST.\n");
 	if ((dst_pio_enable(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "PIO Enable Failed");
+		pr_err("PIO Enable Failed\n");
 		return -1;
 	}
 	if ((rdc_reset_state(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "RDC 8820 State RESET Failed.");
+		pr_err("RDC 8820 State RESET Failed.\n");
 		return -1;
 	}
 	if (state->type_flags & DST_TYPE_HAS_FW_1)
@@ -260,23 +246,21 @@ int write_dst(struct dst_state *state, u
 	};
 
 	int err;
-	u8 cnt, i;
+	u8 cnt;
 
-	dprintk(verbose, DST_NOTICE, 0, "writing [ ");
-	for (i = 0; i < len; i++)
-		dprintk(verbose, DST_NOTICE, 0, "%02x ", data[i]);
-	dprintk(verbose, DST_NOTICE, 0, "]\n");
+	dprintk(1, "writing [ %*ph ]\n", len, data);
 
 	for (cnt = 0; cnt < 2; cnt++) {
 		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, data[0]);
+			dprintk(2, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n",
+				err, len, data[0]);
 			dst_error_recovery(state);
 			continue;
 		} else
 			break;
 	}
 	if (cnt >= 2) {
-		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
+		dprintk(2, "RDC 8820 RESET\n");
 		dst_error_bailout(state);
 
 		return -1;
@@ -300,23 +284,20 @@ int read_dst(struct dst_state *state, u8
 
 	for (cnt = 0; cnt < 2; cnt++) {
 		if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)", err, len, ret[0]);
+			dprintk(2, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n",
+				err, len, ret[0]);
 			dst_error_recovery(state);
 			continue;
 		} else
 			break;
 	}
 	if (cnt >= 2) {
-		dprintk(verbose, DST_INFO, 1, "RDC 8820 RESET");
+		dprintk(2, "RDC 8820 RESET\n");
 		dst_error_bailout(state);
 
 		return -1;
 	}
-	dprintk(verbose, DST_DEBUG, 1, "reply is 0x%x", ret[0]);
-	for (err = 1; err < len; err++)
-		dprintk(verbose, DST_DEBUG, 0, " 0x%x", ret[err]);
-	if (err > 1)
-		dprintk(verbose, DST_DEBUG, 0, "\n");
+	dprintk(3, "reply is %*ph\n", len, ret);
 
 	return 0;
 }
@@ -326,11 +307,11 @@ static int dst_set_polarization(struct d
 {
 	switch (state->voltage) {
 	case SEC_VOLTAGE_13:	/*	Vertical	*/
-		dprintk(verbose, DST_INFO, 1, "Polarization=[Vertical]");
+		dprintk(2, "Polarization=[Vertical]\n");
 		state->tx_tuna[8] &= ~0x40;
 		break;
 	case SEC_VOLTAGE_18:	/*	Horizontal	*/
-		dprintk(verbose, DST_INFO, 1, "Polarization=[Horizontal]");
+		dprintk(2, "Polarization=[Horizontal]\n");
 		state->tx_tuna[8] |= 0x40;
 		break;
 	case SEC_VOLTAGE_OFF:
@@ -343,7 +324,7 @@ static int dst_set_polarization(struct d
 static int dst_set_freq(struct dst_state *state, u32 freq)
 {
 	state->frequency = freq;
-	dprintk(verbose, DST_INFO, 1, "set Frequency %u", freq);
+	dprintk(2, "set Frequency %u\n", freq);
 
 	if (state->dst_type == DST_TYPE_IS_SAT) {
 		freq = freq / 1000;
@@ -463,7 +444,7 @@ static int dst_set_symbolrate(struct dst
 	if (state->dst_type == DST_TYPE_IS_TERR) {
 		return -EOPNOTSUPP;
 	}
-	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
+	dprintk(2, "set symrate %u\n", srate);
 	srate /= 1000;
 	if (state->dst_type == DST_TYPE_IS_SAT) {
 		if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
@@ -471,7 +452,7 @@ static int dst_set_symbolrate(struct dst
 			sval <<= 20;
 			do_div(sval, 88000);
 			symcalc = (u32) sval;
-			dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+			dprintk(2, "set symcalc %u\n", symcalc);
 			state->tx_tuna[5] = (u8) (symcalc >> 12);
 			state->tx_tuna[6] = (u8) (symcalc >> 4);
 			state->tx_tuna[7] = (u8) (symcalc << 4);
@@ -486,7 +467,7 @@ static int dst_set_symbolrate(struct dst
 				state->tx_tuna[8] |= 0x20;
 		}
 	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
-		dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
+		dprintk(3, "%s\n", state->fw_name);
 		if (!strncmp(state->fw_name, "DCTNEW", 6)) {
 			state->tx_tuna[5] = (u8) (srate >> 8);
 			state->tx_tuna[6] = (u8) srate;
@@ -561,24 +542,24 @@ static void dst_type_flags_print(struct
 {
 	u32 type_flags = state->type_flags;
 
-	dprintk(verbose, DST_ERROR, 0, "DST type flags :");
+	pr_err("DST type flags :\n");
 	if (type_flags & DST_TYPE_HAS_TS188)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
+		pr_err(" 0x%x newtuner\n", DST_TYPE_HAS_TS188);
 	if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
+		pr_err(" 0x%x newtuner 2\n", DST_TYPE_HAS_NEWTUNE_2);
 	if (type_flags & DST_TYPE_HAS_TS204)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
+		pr_err(" 0x%x ts204\n", DST_TYPE_HAS_TS204);
 	if (type_flags & DST_TYPE_HAS_VLF)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
+		pr_err(" 0x%x VLF\n", DST_TYPE_HAS_VLF);
 	if (type_flags & DST_TYPE_HAS_SYMDIV)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+		pr_err(" 0x%x symdiv\n", DST_TYPE_HAS_SYMDIV);
 	if (type_flags & DST_TYPE_HAS_FW_1)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
+		pr_err(" 0x%x firmware version = 1\n", DST_TYPE_HAS_FW_1);
 	if (type_flags & DST_TYPE_HAS_FW_2)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
+		pr_err(" 0x%x firmware version = 2\n", DST_TYPE_HAS_FW_2);
 	if (type_flags & DST_TYPE_HAS_FW_3)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
-	dprintk(verbose, DST_ERROR, 0, "\n");
+		pr_err(" 0x%x firmware version = 3\n", DST_TYPE_HAS_FW_3);
+	pr_err("\n");
 }
 
 
@@ -603,10 +584,10 @@ static int dst_type_print(struct dst_sta
 		break;
 
 	default:
-		dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
+		dprintk(2, "invalid dst type %d\n", type);
 		return -EINVAL;
 	}
-	dprintk(verbose, DST_INFO, 1, "DST type: %s", otype);
+	dprintk(2, "DST type: %s\n", otype);
 
 	return 0;
 }
@@ -914,12 +895,12 @@ static int dst_get_mac(struct dst_state
 	u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	get_mac[7] = dst_check_sum(get_mac, 7);
 	if (dst_command(state, get_mac, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		dprintk(2, "Unsupported Command\n");
 		return -1;
 	}
 	memset(&state->mac_address, '\0', 8);
 	memcpy(&state->mac_address, &state->rxbuffer, 6);
-	dprintk(verbose, DST_ERROR, 1, "MAC Address=[%pM]", state->mac_address);
+	pr_err("MAC Address=[%pM]\n", state->mac_address);
 
 	return 0;
 }
@@ -929,11 +910,11 @@ static int dst_fw_ver(struct dst_state *
 	u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	get_ver[7] = dst_check_sum(get_ver, 7);
 	if (dst_command(state, get_ver, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		dprintk(2, "Unsupported Command\n");
 		return -1;
 	}
 	memcpy(&state->fw_version, &state->rxbuffer, 8);
-	dprintk(verbose, DST_ERROR, 1, "Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x",
+	pr_err("Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x\n",
 		state->fw_version[0] >> 4, state->fw_version[0] & 0x0f,
 		state->fw_version[1],
 		state->fw_version[5], state->fw_version[6],
@@ -950,17 +931,17 @@ static int dst_card_type(struct dst_stat
 	u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	get_type[7] = dst_check_sum(get_type, 7);
 	if (dst_command(state, get_type, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		dprintk(2, "Unsupported Command\n");
 		return -1;
 	}
 	memset(&state->card_info, '\0', 8);
 	memcpy(&state->card_info, &state->rxbuffer, 7);
-	dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
+	pr_err("Device Model=[%s]\n", &state->card_info[0]);
 
 	for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
 		if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
 			state->tuner_type = p_tuner_list->tuner_type;
-			dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
+			pr_err("DST has [%s] tuner, tuner type=[%d]\n",
 				p_tuner_list->tuner_name, p_tuner_list->tuner_type);
 		}
 	}
@@ -973,26 +954,19 @@ static int dst_get_vendor(struct dst_sta
 	u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	get_vendor[7] = dst_check_sum(get_vendor, 7);
 	if (dst_command(state, get_vendor, 8) < 0) {
-		dprintk(verbose, DST_INFO, 1, "Unsupported Command");
+		dprintk(2, "Unsupported Command\n");
 		return -1;
 	}
 	memset(&state->vendor, '\0', 8);
 	memcpy(&state->vendor, &state->rxbuffer, 7);
-	dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
+	pr_err("Vendor=[%s]\n", &state->vendor[0]);
 
 	return 0;
 }
 
 static void debug_dst_buffer(struct dst_state *state)
 {
-	int i;
-
-	if (verbose > 2) {
-		printk("%s: [", __func__);
-		for (i = 0; i < 8; i++)
-			printk(" %02x", state->rxbuffer[i]);
-		printk("]\n");
-	}
+	dprintk(3, "%s: [ %*ph ]\n", __func__, 8, state->rxbuffer);
 }
 
 static int dst_check_stv0299(struct dst_state *state)
@@ -1001,13 +975,13 @@ static int dst_check_stv0299(struct dst_
 
 	check_stv0299[7] = dst_check_sum(check_stv0299, 7);
 	if (dst_command(state, check_stv0299, 8) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
+		pr_err("Cmd=[0x04] failed\n");
 		return -1;
 	}
 	debug_dst_buffer(state);
 
 	if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
-		dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
+		pr_err("Found a STV0299 NIM\n");
 		state->tuner_type = TUNER_TYPE_STV0299;
 		return 0;
 	}
@@ -1021,13 +995,13 @@ static int dst_check_mb86a15(struct dst_
 
 	check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
 	if (dst_command(state, check_mb86a15, 8) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
+		pr_err("Cmd=[0x10], failed\n");
 		return -1;
 	}
 	debug_dst_buffer(state);
 
 	if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
+		pr_err("Found a MB86A15 NIM\n");
 		state->tuner_type = TUNER_TYPE_MB86A15;
 		return 0;
 	}
@@ -1042,21 +1016,21 @@ static int dst_get_tuner_info(struct dst
 
 	get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
 	get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
-	dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
+	pr_err("DST TYpe = MULTI FE\n");
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
 		if (dst_command(state, get_tuner_1, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
+			dprintk(2, "Cmd=[0x13], Unsupported\n");
 			goto force;
 		}
 	} else {
 		if (dst_command(state, get_tuner_2, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
+			dprintk(2, "Cmd=[0xb], Unsupported\n");
 			goto force;
 		}
 	}
 	memcpy(&state->board_info, &state->rxbuffer, 8);
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-		dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
+		pr_err("DST type has TS=188\n");
 	}
 	if (state->board_info[0] == 0xbc) {
 		if (state->dst_type != DST_TYPE_IS_ATSC)
@@ -1066,7 +1040,7 @@ static int dst_get_tuner_info(struct dst
 
 		if (state->board_info[1] == 0x01) {
 			state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
-			dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
+			pr_err("DST has Daughterboard\n");
 		}
 	}
 
@@ -1074,7 +1048,7 @@ static int dst_get_tuner_info(struct dst
 force:
 	if (!strncmp(state->fw_name, "DCT-CI", 6)) {
 		state->type_flags |= DST_TYPE_HAS_TS204;
-		dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
+		pr_err("Forcing [%s] to TS188\n", state->fw_name);
 	}
 
 	return -1;
@@ -1103,7 +1077,7 @@ static int dst_get_device_id(struct dst_
 	if (read_dst(state, &reply, GET_ACK))
 		return -1;		/*	Read failure		*/
 	if (reply != ACK) {
-		dprintk(verbose, DST_INFO, 1, "Write not Acknowledged! [Reply=0x%02x]", reply);
+		dprintk(2, "Write not Acknowledged! [Reply=0x%02x]\n", reply);
 		return -1;		/*	Unack'd write		*/
 	}
 	if (!dst_wait_dst_ready(state, DEVICE_INIT))
@@ -1113,7 +1087,7 @@ static int dst_get_device_id(struct dst_
 
 	dst_pio_disable(state);
 	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
-		dprintk(verbose, DST_INFO, 1, "Checksum failure!");
+		dprintk(2, "Checksum failure!\n");
 		return -1;		/*	Checksum failure	*/
 	}
 	state->rxbuffer[7] = '\0';
@@ -1125,7 +1099,7 @@ static int dst_get_device_id(struct dst_
 
 			/*	Card capabilities	*/
 			state->dst_hw_cap = p_dst_type->dst_feature;
-			dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
+			pr_err("Recognise [%s]\n", p_dst_type->device_id);
 			strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
 			/*	Multiple tuners		*/
 			if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
@@ -1133,7 +1107,7 @@ static int dst_get_device_id(struct dst_
 				case DST_TYPE_IS_SAT:
 					/*	STV0299 check	*/
 					if (dst_check_stv0299(state) < 0) {
-						dprintk(verbose, DST_ERROR, 1, "Unsupported");
+						pr_err("Unsupported\n");
 						state->tuner_type = TUNER_TYPE_MB86A15;
 					}
 					break;
@@ -1141,7 +1115,7 @@ static int dst_get_device_id(struct dst_
 					break;
 				}
 				if (dst_check_mb86a15(state) < 0)
-					dprintk(verbose, DST_ERROR, 1, "Unsupported");
+					pr_err("Unsupported\n");
 			/*	Single tuner		*/
 			} else {
 				state->tuner_type = p_dst_type->tuner_type;
@@ -1149,7 +1123,7 @@ static int dst_get_device_id(struct dst_
 			for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
 				if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
 					p_tuner_list->tuner_type == state->tuner_type) {
-					dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
+					pr_err("[%s] has a [%s]\n",
 						p_dst_type->device_id, p_tuner_list->tuner_name);
 				}
 			}
@@ -1158,8 +1132,8 @@ static int dst_get_device_id(struct dst_
 	}
 
 	if (i >= ARRAY_SIZE(dst_tlist)) {
-		dprintk(verbose, DST_ERROR, 1, "Unable to recognize %s or %s", &state->rxbuffer[0], &state->rxbuffer[1]);
-		dprintk(verbose, DST_ERROR, 1, "please email linux-dvb@linuxtv.org with this type in");
+		pr_err("Unable to recognize %s or %s\n", &state->rxbuffer[0], &state->rxbuffer[1]);
+		pr_err("please email linux-dvb@linuxtv.org with this type in");
 		use_dst_type = DST_TYPE_IS_SAT;
 		use_type_flags = DST_TYPE_HAS_SYMDIV;
 	}
@@ -1176,7 +1150,7 @@ static int dst_probe(struct dst_state *s
 	mutex_init(&state->dst_mutex);
 	if (dst_addons & DST_TYPE_HAS_CA) {
 		if ((rdc_8820_reset(state)) < 0) {
-			dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
+			pr_err("RDC 8820 RESET Failed.\n");
 			return -1;
 		}
 		msleep(4000);
@@ -1184,35 +1158,35 @@ static int dst_probe(struct dst_state *s
 		msleep(100);
 	}
 	if ((dst_comm_init(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
+		pr_err("DST Initialization Failed.\n");
 		return -1;
 	}
 	msleep(100);
 	if (dst_get_device_id(state) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "unknown device.");
+		pr_err("unknown device.\n");
 		return -1;
 	}
 	if (dst_get_mac(state) < 0) {
-		dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
+		dprintk(2, "MAC: Unsupported command\n");
 	}
 	if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
 		if (dst_get_tuner_info(state) < 0)
-			dprintk(verbose, DST_INFO, 1, "Tuner: Unsupported command");
+			dprintk(2, "Tuner: Unsupported command\n");
 	}
 	if (state->type_flags & DST_TYPE_HAS_TS204) {
 		dst_packsize(state, 204);
 	}
 	if (state->type_flags & DST_TYPE_HAS_FW_BUILD) {
 		if (dst_fw_ver(state) < 0) {
-			dprintk(verbose, DST_INFO, 1, "FW: Unsupported command");
+			dprintk(2, "FW: Unsupported command\n");
 			return 0;
 		}
 		if (dst_card_type(state) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Card: Unsupported command");
+			dprintk(2, "Card: Unsupported command\n");
 			return 0;
 		}
 		if (dst_get_vendor(state) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Vendor: Unsupported command");
+			dprintk(2, "Vendor: Unsupported command\n");
 			return 0;
 		}
 	}
@@ -1226,33 +1200,33 @@ static int dst_command(struct dst_state
 
 	mutex_lock(&state->dst_mutex);
 	if ((dst_comm_init(state)) < 0) {
-		dprintk(verbose, DST_NOTICE, 1, "DST Communication Initialization Failed.");
+		dprintk(1, "DST Communication Initialization Failed.\n");
 		goto error;
 	}
 	if (write_dst(state, data, len)) {
-		dprintk(verbose, DST_INFO, 1, "Trying to recover.. ");
+		dprintk(2, "Trying to recover..\n");
 		if ((dst_error_recovery(state)) < 0) {
-			dprintk(verbose, DST_ERROR, 1, "Recovery Failed.");
+			pr_err("Recovery Failed.\n");
 			goto error;
 		}
 		goto error;
 	}
 	if ((dst_pio_disable(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "PIO Disable Failed.");
+		pr_err("PIO Disable Failed.\n");
 		goto error;
 	}
 	if (state->type_flags & DST_TYPE_HAS_FW_1)
 		mdelay(3);
 	if (read_dst(state, &reply, GET_ACK)) {
-		dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
+		dprintk(3, "Trying to recover..\n");
 		if ((dst_error_recovery(state)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Recovery Failed.");
+			dprintk(2, "Recovery Failed.\n");
 			goto error;
 		}
 		goto error;
 	}
 	if (reply != ACK) {
-		dprintk(verbose, DST_INFO, 1, "write not acknowledged 0x%02x ", reply);
+		dprintk(2, "write not acknowledged 0x%02x\n", reply);
 		goto error;
 	}
 	if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
@@ -1264,15 +1238,15 @@ static int dst_command(struct dst_state
 	if (!dst_wait_dst_ready(state, NO_DELAY))
 		goto error;
 	if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
-		dprintk(verbose, DST_DEBUG, 1, "Trying to recover.. ");
+		dprintk(3, "Trying to recover..\n");
 		if ((dst_error_recovery(state)) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Recovery failed.");
+			dprintk(2, "Recovery failed.\n");
 			goto error;
 		}
 		goto error;
 	}
 	if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
-		dprintk(verbose, DST_INFO, 1, "checksum failure");
+		dprintk(2, "checksum failure\n");
 		goto error;
 	}
 	mutex_unlock(&state->dst_mutex);
@@ -1348,19 +1322,19 @@ static int dst_get_tuna(struct dst_state
 	else
 		retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
 	if (retval < 0) {
-		dprintk(verbose, DST_DEBUG, 1, "read not successful");
+		dprintk(3, "read not successful\n");
 		return retval;
 	}
 	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
 	   !(state->dst_type == DST_TYPE_IS_ATSC)) {
 
 		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
-			dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
+			dprintk(2, "checksum failure ?\n");
 			return -EIO;
 		}
 	} else {
 		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) {
-			dprintk(verbose, DST_INFO, 1, "checksum failure? ");
+			dprintk(2, "checksum failure?\n");
 			return -EIO;
 		}
 	}
@@ -1387,7 +1361,7 @@ static int dst_write_tuna(struct dvb_fro
 	int retval;
 	u8 reply;
 
-	dprintk(verbose, DST_INFO, 1, "type_flags 0x%x ", state->type_flags);
+	dprintk(2, "type_flags 0x%x\n", state->type_flags);
 	state->decode_freq = 0;
 	state->decode_lock = state->decode_strength = state->decode_snr = 0;
 	if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -1397,7 +1371,7 @@ static int dst_write_tuna(struct dvb_fro
 	state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
 	mutex_lock(&state->dst_mutex);
 	if ((dst_comm_init(state)) < 0) {
-		dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
+		dprintk(3, "DST Communication initialization failed.\n");
 		goto error;
 	}
 //	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
@@ -1412,19 +1386,19 @@ static int dst_write_tuna(struct dvb_fro
 	}
 	if (retval < 0) {
 		dst_pio_disable(state);
-		dprintk(verbose, DST_DEBUG, 1, "write not successful");
+		dprintk(3, "write not successful\n");
 		goto werr;
 	}
 	if ((dst_pio_disable(state)) < 0) {
-		dprintk(verbose, DST_DEBUG, 1, "DST PIO disable failed !");
+		dprintk(3, "DST PIO disable failed !\n");
 		goto error;
 	}
 	if ((read_dst(state, &reply, GET_ACK) < 0)) {
-		dprintk(verbose, DST_DEBUG, 1, "read verify not successful.");
+		dprintk(3, "read verify not successful.\n");
 		goto error;
 	}
 	if (reply != ACK) {
-		dprintk(verbose, DST_DEBUG, 1, "write not acknowledged 0x%02x ", reply);
+		dprintk(3, "write not acknowledged 0x%02x\n", reply);
 		goto error;
 	}
 	state->diseq_flags |= ATTEMPT_TUNE;
@@ -1622,7 +1596,7 @@ static int dst_set_frontend(struct dvb_f
 		retval = dst_set_freq(state, p->frequency);
 		if(retval != 0)
 			return retval;
-		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+		dprintk(3, "Set Frequency=[%d]\n", p->frequency);
 
 		if (state->dst_type == DST_TYPE_IS_SAT) {
 			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
@@ -1630,7 +1604,7 @@ static int dst_set_frontend(struct dvb_f
 			dst_set_fec(state, p->fec_inner);
 			dst_set_symbolrate(state, p->symbol_rate);
 			dst_set_polarization(state);
-			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
+			dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate);
 
 		} else if (state->dst_type == DST_TYPE_IS_TERR)
 			dst_set_bandwidth(state, p->bandwidth_hz);
@@ -1656,7 +1630,7 @@ static int dst_tune_frontend(struct dvb_
 
 	if (re_tune) {
 		dst_set_freq(state, p->frequency);
-		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+		dprintk(3, "Set Frequency=[%d]\n", p->frequency);
 
 		if (state->dst_type == DST_TYPE_IS_SAT) {
 			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
@@ -1664,7 +1638,7 @@ static int dst_tune_frontend(struct dvb_
 			dst_set_fec(state, p->fec_inner);
 			dst_set_symbolrate(state, p->symbol_rate);
 			dst_set_polarization(state);
-			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->symbol_rate);
+			dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate);
 
 		} else if (state->dst_type == DST_TYPE_IS_TERR)
 			dst_set_bandwidth(state, p->bandwidth_hz);
@@ -1722,10 +1696,10 @@ static void bt8xx_dst_release(struct dvb
 	kfree(state);
 }
 
-static struct dvb_frontend_ops dst_dvbt_ops;
-static struct dvb_frontend_ops dst_dvbs_ops;
-static struct dvb_frontend_ops dst_dvbc_ops;
-static struct dvb_frontend_ops dst_atsc_ops;
+static const struct dvb_frontend_ops dst_dvbt_ops;
+static const struct dvb_frontend_ops dst_dvbs_ops;
+static const struct dvb_frontend_ops dst_dvbc_ops;
+static const struct dvb_frontend_ops dst_atsc_ops;
 
 struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
 {
@@ -1750,7 +1724,7 @@ struct dst_state *dst_attach(struct dst_
 		memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
 		break;
 	default:
-		dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
+		pr_err("unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n");
 		kfree(state);
 		return NULL;
 	}
@@ -1761,7 +1735,7 @@ struct dst_state *dst_attach(struct dst_
 
 EXPORT_SYMBOL(dst_attach);
 
-static struct dvb_frontend_ops dst_dvbt_ops = {
+static const struct dvb_frontend_ops dst_dvbt_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name = "DST DVB-T",
@@ -1790,7 +1764,7 @@ static struct dvb_frontend_ops dst_dvbt_
 	.read_snr = dst_read_snr,
 };
 
-static struct dvb_frontend_ops dst_dvbs_ops = {
+static const struct dvb_frontend_ops dst_dvbs_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name = "DST DVB-S",
@@ -1819,7 +1793,7 @@ static struct dvb_frontend_ops dst_dvbs_
 	.set_tone = dst_set_tone,
 };
 
-static struct dvb_frontend_ops dst_dvbc_ops = {
+static const struct dvb_frontend_ops dst_dvbc_ops = {
 	.delsys = { SYS_DVBC_ANNEX_A },
 	.info = {
 		.name = "DST DVB-C",
@@ -1848,7 +1822,7 @@ static struct dvb_frontend_ops dst_dvbc_
 	.read_snr = dst_read_snr,
 };
 
-static struct dvb_frontend_ops dst_atsc_ops = {
+static const struct dvb_frontend_ops dst_atsc_ops = {
 	.delsys = { SYS_ATSC },
 	.info = {
 		.name = "DST ATSC",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/bt8xx/dvb-bt8xx.c linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/dvb-bt8xx.c
--- linux-libre-4.9-gnu/drivers/media/pci/bt8xx/dvb-bt8xx.c	2016-12-11 17:43:53.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/bt8xx/dvb-bt8xx.c	2017-02-12 17:28:34.000000000 -0500
@@ -19,7 +19,7 @@
  *
  */
 
-#define pr_fmt(fmt) "dvb_bt8xx: " fmt
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/bitops.h>
 #include <linux/module.h>
@@ -44,10 +44,12 @@ MODULE_PARM_DESC(debug, "Turn on/off deb
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-#define dprintk( args... ) \
-	do { \
-		if (debug) printk(KERN_DEBUG args); \
-	} while (0)
+#define dprintk(fmt, arg...) do {				\
+	if (debug)						\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt),		\
+		       __func__, ##arg);			\
+} while (0)
+
 
 #define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 
@@ -55,7 +57,7 @@ static void dvb_bt8xx_task(unsigned long
 {
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *)data;
 
-	//printk("%d ", card->bt->finished_block);
+	dprintk("%d\n", card->bt->finished_block);
 
 	while (card->bt->last_block != card->bt->finished_block) {
 		(card->bt->TS_Size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
@@ -443,7 +445,7 @@ static void or51211_reset(struct dvb_fro
 	/* reset & PRM1,2&4 are outputs */
 	int ret = bttv_gpio_enable(bt->bttv_nr, 0x001F, 0x001F);
 	if (ret != 0)
-		printk(KERN_WARNING "or51211: Init Error - Can't Reset DVR (%i)\n", ret);
+		pr_warn("or51211: Init Error - Can't Reset DVR (%i)\n", ret);
 	bttv_write_gpio(bt->bttv_nr, 0x001F, 0x0000);   /* Reset */
 	msleep(20);
 	/* Now set for normal operation */
@@ -560,7 +562,8 @@ static void digitv_alps_tded4_reset(stru
 
 	int ret = bttv_gpio_enable(bt->bttv_nr, 0x08, 0x08);
 	if (ret != 0)
-		printk(KERN_WARNING "digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n", ret);
+		pr_warn("digitv_alps_tded4: Init Error - Can't Reset DVR (%i)\n",
+			ret);
 
 	/* Pulse the reset line */
 	bttv_write_gpio(bt->bttv_nr, 0x08, 0x08); /* High */
@@ -620,7 +623,7 @@ static void frontend_init(struct dvb_bt8
 			dvb_attach(simple_tuner_attach, card->fe,
 				   card->i2c_adapter, 0x61,
 				   TUNER_LG_TDVS_H06XF);
-			dprintk ("dvb_bt8xx: lgdt330x detected\n");
+			dprintk("dvb_bt8xx: lgdt330x detected\n");
 		}
 		break;
 
@@ -635,7 +638,7 @@ static void frontend_init(struct dvb_bt8
 		card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);
 		if (card->fe != NULL) {
 			card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
-			dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
+			dprintk("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
 			break;
 		}
 
@@ -645,7 +648,7 @@ static void frontend_init(struct dvb_bt8
 
 		if (card->fe != NULL) {
 			card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
-			dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
+			dprintk("dvb_bt8xx: an mt352 was detected on your digitv card\n");
 		}
 		break;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cobalt/cobalt-driver.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cobalt/cobalt-driver.c
--- linux-libre-4.9-gnu/drivers/media/pci/cobalt/cobalt-driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cobalt/cobalt-driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -308,9 +308,7 @@ static void cobalt_pci_iounmap(struct co
 static void cobalt_free_msi(struct cobalt *cobalt, struct pci_dev *pci_dev)
 {
 	free_irq(pci_dev->irq, (void *)cobalt);
-
-	if (cobalt->msi_enabled)
-		pci_disable_msi(pci_dev);
+	pci_free_irq_vectors(pci_dev);
 }
 
 static int cobalt_setup_pci(struct cobalt *cobalt, struct pci_dev *pci_dev,
@@ -387,14 +385,12 @@ static int cobalt_setup_pci(struct cobal
 	   from being generated. */
 	cobalt_set_interrupt(cobalt, false);
 
-	if (pci_enable_msi_range(pci_dev, 1, 1) < 1) {
+	if (pci_alloc_irq_vectors(pci_dev, 1, 1, PCI_IRQ_MSI) < 1) {
 		cobalt_err("Could not enable MSI\n");
-		cobalt->msi_enabled = false;
 		ret = -EIO;
 		goto err_release;
 	}
 	msi_config_show(cobalt, pci_dev);
-	cobalt->msi_enabled = true;
 
 	/* Register IRQ */
 	if (request_irq(pci_dev->irq, cobalt_irq_handler, IRQF_SHARED,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cobalt/cobalt-driver.h linux-libre-4.10-rc8-gnu/drivers/media/pci/cobalt/cobalt-driver.h
--- linux-libre-4.9-gnu/drivers/media/pci/cobalt/cobalt-driver.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cobalt/cobalt-driver.h	2017-02-12 16:03:20.000000000 -0500
@@ -287,8 +287,6 @@ struct cobalt {
 	u32 irq_none;
 	u32 irq_full_fifo;
 
-	bool msi_enabled;
-
 	/* omnitek dma */
 	int dma_channels;
 	int first_fifo_channel;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cobalt/cobalt-v4l2.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cobalt/cobalt-v4l2.c
--- linux-libre-4.9-gnu/drivers/media/pci/cobalt/cobalt-v4l2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cobalt/cobalt-v4l2.c	2017-02-12 16:03:20.000000000 -0500
@@ -527,7 +527,7 @@ static void cobalt_video_input_status_sh
 	cvi_ctrl = ioread32(&cvi->control);
 	cvi_stat = ioread32(&cvi->status);
 	vmr_ctrl = ioread32(&vmr->control);
-	vmr_stat = ioread32(&vmr->control);
+	vmr_stat = ioread32(&vmr->status);
 	cobalt_info("rx%d: cvi resolution: %dx%d\n", rx,
 		    ioread32(&cvi->frame_width), ioread32(&cvi->frame_height));
 	cobalt_info("rx%d: cvi control: %s%s%s\n", rx,
@@ -1084,12 +1084,33 @@ static int cobalt_g_parm(struct file *fi
 	return 0;
 }
 
+static int cobalt_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cc)
+{
+	struct cobalt_stream *s = video_drvdata(file);
+	struct v4l2_dv_timings timings;
+	int err = 0;
+
+	if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (s->input == 1)
+		timings = cea1080p60;
+	else
+		err = v4l2_subdev_call(s->sd, video, g_dv_timings, &timings);
+	if (!err) {
+		cc->bounds.width = cc->defrect.width = timings.bt.width;
+		cc->bounds.height = cc->defrect.height = timings.bt.height;
+		cc->pixelaspect = v4l2_dv_timings_aspect_ratio(&timings);
+	}
+	return err;
+}
+
 static const struct v4l2_ioctl_ops cobalt_ioctl_ops = {
 	.vidioc_querycap		= cobalt_querycap,
 	.vidioc_g_parm			= cobalt_g_parm,
 	.vidioc_log_status		= cobalt_log_status,
 	.vidioc_streamon		= vb2_ioctl_streamon,
 	.vidioc_streamoff		= vb2_ioctl_streamoff,
+	.vidioc_cropcap			= cobalt_cropcap,
 	.vidioc_enum_input		= cobalt_enum_input,
 	.vidioc_g_input			= cobalt_g_input,
 	.vidioc_s_input			= cobalt_s_input,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-alsa-main.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-alsa-main.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-alsa-main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-alsa-main.c	2017-02-12 16:03:20.000000000 -0500
@@ -217,8 +217,8 @@ static int cx18_alsa_load(struct cx18 *c
 
 	s = &cx->streams[CX18_ENC_STREAM_TYPE_PCM];
 	if (s->video_dev.v4l2_dev == NULL) {
-		CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
-				     "skipping\n", __func__);
+		CX18_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - skipping\n",
+				     __func__);
 		return 0;
 	}
 
@@ -232,8 +232,8 @@ static int cx18_alsa_load(struct cx18 *c
 		CX18_ALSA_ERR("%s: failed to create struct snd_cx18_card\n",
 			      __func__);
 	} else {
-		CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance "
-				     "\n", __func__);
+		CX18_DEBUG_ALSA_INFO("%s: created cx18 ALSA interface instance\n",
+				     __func__);
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-av-core.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-av-core.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-av-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-av-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -468,21 +468,19 @@ void cx18_av_std_setup(struct cx18 *cx)
 		CX18_DEBUG_INFO_DEV(sd, "Pixel rate = %d.%06d Mpixel/sec\n",
 				    pll / 8000000, (pll / 8) % 1000000);
 
-		CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio "
-				    "= %d.%03d\n", src_decimation / 256,
+		CX18_DEBUG_INFO_DEV(sd, "ADC XTAL/pixel clock decimation ratio = %d.%03d\n",
+				    src_decimation / 256,
 				    ((src_decimation % 256) * 1000) / 256);
 
 		tmp = 28636360 * (u64) sc;
 		do_div(tmp, src_decimation);
 		fsc = tmp >> 13;
 		CX18_DEBUG_INFO_DEV(sd,
-				    "Chroma sub-carrier initial freq = %d.%06d "
-				    "MHz\n", fsc / 1000000, fsc % 1000000);
+				    "Chroma sub-carrier initial freq = %d.%06d MHz\n",
+				    fsc / 1000000, fsc % 1000000);
 
-		CX18_DEBUG_INFO_DEV(sd, "hblank %i, hactive %i, vblank %i, "
-				    "vactive %i, vblank656 %i, src_dec %i, "
-				    "burst 0x%02x, luma_lpf %i, uv_lpf %i, "
-				    "comb 0x%02x, sc 0x%06x\n",
+		CX18_DEBUG_INFO_DEV(sd,
+				    "hblank %i, hactive %i, vblank %i, vactive %i, vblank656 %i, src_dec %i, burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x, sc 0x%06x\n",
 				    hblank, hactive, vblank, vactive, vblank656,
 				    src_decimation, burst, luma_lpf, uv_lpf,
 				    comb, sc);
@@ -1069,8 +1067,7 @@ static void log_video_status(struct cx18
 		CX18_INFO_DEV(sd, "Specified video input:     Composite %d\n",
 			      vid_input - CX18_AV_COMPOSITE1 + 1);
 	} else {
-		CX18_INFO_DEV(sd, "Specified video input:     "
-			      "S-Video (Luma In%d, Chroma In%d)\n",
+		CX18_INFO_DEV(sd, "Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
 			      (vid_input & 0xf0) >> 4,
 			      (vid_input & 0xf00) >> 8);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-av-firmware.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-av-firmware.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-av-firmware.c	2016-12-11 17:47:18.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-av-firmware.c	2017-02-12 17:34:20.000000000 -0500
@@ -61,8 +61,7 @@ static int cx18_av_verifyfw(struct cx18
 		dl_control &= 0xffff3fff; /* ignore top 2 bits of address */
 		expected = 0x0f000000 | ((u32)data[addr] << 16) | addr;
 		if (expected != dl_control) {
-			CX18_ERR_DEV(sd, "verification of %s firmware load "
-				     "failed: expected %#010x got %#010x\n",
+			CX18_ERR_DEV(sd, "verification of %s firmware load failed: expected %#010x got %#010x\n",
 				     FWFILE, expected, dl_control);
 			ret = -EIO;
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-controls.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-controls.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-controls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-controls.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,8 +44,7 @@ static int cx18_s_stream_vbi_fmt(struct
 	      type == V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD)) {
 		/* Only IVTV fmt VBI insertion & only MPEG-2 PS type streams */
 		cx->vbi.insert_mpeg = V4L2_MPEG_STREAM_VBI_FMT_NONE;
-		CX18_DEBUG_INFO("disabled insertion of sliced VBI data into "
-				"the MPEG stream\n");
+		CX18_DEBUG_INFO("disabled insertion of sliced VBI data into the MPEG stream\n");
 		return 0;
 	}
 
@@ -63,16 +62,14 @@ static int cx18_s_stream_vbi_fmt(struct
 				}
 				cx->vbi.insert_mpeg =
 						  V4L2_MPEG_STREAM_VBI_FMT_NONE;
-				CX18_WARN("Unable to allocate buffers for "
-					  "sliced VBI data insertion\n");
+				CX18_WARN("Unable to allocate buffers for sliced VBI data insertion\n");
 				return -ENOMEM;
 			}
 		}
 	}
 
 	cx->vbi.insert_mpeg = fmt;
-	CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS,"
-			"when sliced VBI is enabled\n");
+	CX18_DEBUG_INFO("enabled insertion of sliced VBI data into the MPEG PS,when sliced VBI is enabled\n");
 
 	/*
 	 * If our current settings have no lines set for capture, store a valid,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-driver.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-driver.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-driver.c	2016-12-11 17:47:26.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-driver.c	2017-02-12 17:34:32.000000000 -0500
@@ -405,8 +405,8 @@ static void cx18_process_eeprom(struct c
 		CX18_ERR("Invalid EEPROM\n");
 		return;
 	default:
-		CX18_ERR("Unknown model %d, defaulting to original HVR-1600 "
-			 "(cardtype=1)\n", tv.model);
+		CX18_ERR("Unknown model %d, defaulting to original HVR-1600 (cardtype=1)\n",
+			 tv.model);
 		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 		break;
 	}
@@ -635,8 +635,8 @@ static void cx18_process_options(struct
 			/* convert from kB to bytes */
 			cx->stream_buf_size[i] *= 1024;
 		}
-		CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, "
-				"%d bytes\n", i, cx->options.megabytes[i],
+		CX18_DEBUG_INFO("Stream type %d options: %d MB, %d buffers, %d bytes\n",
+				i, cx->options.megabytes[i],
 				cx->stream_buffers[i], cx->stream_buf_size[i]);
 	}
 
@@ -838,14 +838,13 @@ static int cx18_setup_pci(struct cx18 *c
 	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
 
 	if (pci_latency < 64 && cx18_pci_latency) {
-		CX18_INFO("Unreasonably low latency timer, "
-			       "setting to 64 (was %d)\n", pci_latency);
+		CX18_INFO("Unreasonably low latency timer, setting to 64 (was %d)\n",
+			  pci_latency);
 		pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, 64);
 		pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &pci_latency);
 	}
 
-	CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
-		   "irq: %d, latency: %d, memory: 0x%llx\n",
+	CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, irq: %d, latency: %d, memory: 0x%llx\n",
 		   cx->pci_dev->device, cx->card_rev, pci_dev->bus->number,
 		   PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn),
 		   cx->pci_dev->irq, pci_latency, (u64)cx->base_addr);
@@ -910,8 +909,8 @@ static int cx18_probe(struct pci_dev *pc
 	/* FIXME - module parameter arrays constrain max instances */
 	i = atomic_inc_return(&cx18_instance) - 1;
 	if (i >= CX18_MAX_CARDS) {
-		printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
-		       "limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
+		printk(KERN_ERR "cx18: cannot manage card %d, driver has a limit of 0 - %d\n",
+		       i, CX18_MAX_CARDS - 1);
 		return -ENOMEM;
 	}
 
@@ -926,8 +925,8 @@ static int cx18_probe(struct pci_dev *pc
 
 	retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev);
 	if (retval) {
-		printk(KERN_ERR "cx18: v4l2_device_register of card %d failed"
-		       "\n", cx->instance);
+		printk(KERN_ERR "cx18: v4l2_device_register of card %d failed\n",
+		       cx->instance);
 		kfree(cx);
 		return retval;
 	}
@@ -958,13 +957,10 @@ static int cx18_probe(struct pci_dev *pc
 	cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
 				       CX18_MEM_SIZE);
 	if (!cx->enc_mem) {
-		CX18_ERR("ioremap failed. Can't get a window into CX23418 "
-			 "memory and register space\n");
-		CX18_ERR("Each capture card with a CX23418 needs 64 MB of "
-			 "vmalloc address space for the window\n");
+		CX18_ERR("ioremap failed. Can't get a window into CX23418 memory and register space\n");
+		CX18_ERR("Each capture card with a CX23418 needs 64 MB of vmalloc address space for the window\n");
 		CX18_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
-		CX18_ERR("Use the vmalloc= kernel command line option to set "
-			 "VmallocTotal to a larger value\n");
+		CX18_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
 		retval = -ENOMEM;
 		goto free_mem;
 	}
@@ -1000,8 +996,7 @@ static int cx18_probe(struct pci_dev *pc
 	/* Initialize GPIO Reset Controller to do chip resets during i2c init */
 	if (cx->card->hw_all & CX18_HW_GPIO_RESET_CTRL) {
 		if (cx18_gpio_register(cx, CX18_HW_GPIO_RESET_CTRL) != 0)
-			CX18_WARN("Could not register GPIO reset controller"
-				  "subdevice; proceeding anyway.\n");
+			CX18_WARN("Could not register GPIO reset controllersubdevice; proceeding anyway.\n");
 		else
 			cx->hw_flags |= CX18_HW_GPIO_RESET_CTRL;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-dvb.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-dvb.c	2016-12-11 17:47:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-dvb.c	2017-02-12 17:34:25.000000000 -0500
@@ -155,10 +155,8 @@ static int yuan_mpc718_mt352_reqfw(struc
 	}
 
 	if (ret) {
-		CX18_ERR("The MPC718 board variant with the MT352 DVB-T"
-			  "demodualtor will not work without it\n");
-		CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware "
-			  "mpc718' if you need the firmware\n");
+		CX18_ERR("The MPC718 board variant with the MT352 DVB-Tdemodualtor will not work without it\n");
+		CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware mpc718' if you need the firmware\n");
 	}
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-fileops.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-fileops.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-fileops.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-fileops.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,8 +49,7 @@ int cx18_claim_stream(struct cx18_open_i
 
 	/* Nothing should ever try to directly claim the IDX stream */
 	if (type == CX18_ENC_STREAM_TYPE_IDX) {
-		CX18_WARN("MPEG Index stream cannot be claimed "
-			  "directly, but something tried.\n");
+		CX18_WARN("MPEG Index stream cannot be claimed directly, but something tried.\n");
 		return -EINVAL;
 	}
 
@@ -728,8 +727,7 @@ void cx18_stop_capture(struct cx18_open_
 			/* Stop internal use associated VBI and IDX streams */
 			if (test_bit(CX18_F_S_STREAMING, &s_vbi->s_flags) &&
 			    !test_bit(CX18_F_S_APPL_IO, &s_vbi->s_flags)) {
-				CX18_DEBUG_INFO("close stopping embedded VBI "
-						"capture\n");
+				CX18_DEBUG_INFO("close stopping embedded VBI capture\n");
 				cx18_stop_v4l2_encode_stream(s_vbi, 0);
 			}
 			if (test_bit(CX18_F_S_STREAMING, &s_idx->s_flags)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-ioctl.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-ioctl.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -951,8 +951,7 @@ static int cx18_encoder_cmd(struct file
 			return 0;
 		h = cx18_find_handle(cx);
 		if (h == CX18_INVALID_TASK_HANDLE) {
-			CX18_ERR("Can't find valid task handle for "
-				 "V4L2_ENC_CMD_PAUSE\n");
+			CX18_ERR("Can't find valid task handle for V4L2_ENC_CMD_PAUSE\n");
 			return -EBADFD;
 		}
 		cx18_mute(cx);
@@ -968,8 +967,7 @@ static int cx18_encoder_cmd(struct file
 			return 0;
 		h = cx18_find_handle(cx);
 		if (h == CX18_INVALID_TASK_HANDLE) {
-			CX18_ERR("Can't find valid task handle for "
-				 "V4L2_ENC_CMD_RESUME\n");
+			CX18_ERR("Can't find valid task handle for V4L2_ENC_CMD_RESUME\n");
 			return -EBADFD;
 		}
 		cx18_vapi(cx, CX18_CPU_CAPTURE_RESUME, 1, h);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-irq.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-irq.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -59,8 +59,8 @@ irqreturn_t cx18_irq_handler(int irq, vo
 		cx18_write_reg_expect(cx, hw2, HW2_INT_CLR_STATUS, ~hw2, hw2);
 
 	if (sw1 || sw2 || hw2)
-		CX18_DEBUG_HI_IRQ("received interrupts "
-				  "SW1: %x  SW2: %x  HW2: %x\n", sw1, sw2, hw2);
+		CX18_DEBUG_HI_IRQ("received interrupts SW1: %x	SW2: %x  HW2: %x\n",
+				  sw1, sw2, hw2);
 
 	/*
 	 * SW1 responses have to happen first.  The sending XPU times out the
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-mailbox.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-mailbox.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-mailbox.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-mailbox.c	2017-02-12 16:03:20.000000000 -0500
@@ -123,8 +123,8 @@ static void dump_mb(struct cx18 *cx, str
 	if (!(cx18_debug & CX18_DBGFLG_API))
 		return;
 
-	CX18_DEBUG_API("%s: req %#010x ack %#010x cmd %#010x err %#010x args%s"
-		       "\n", name, mb->request, mb->ack, mb->cmd, mb->error,
+	CX18_DEBUG_API("%s: req %#010x ack %#010x cmd %#010x err %#010x args%s\n",
+		       name, mb->request, mb->ack, mb->cmd, mb->error,
 		       u32arr2hex(mb->args, MAX_MB_ARGUMENTS, argstr));
 }
 
@@ -255,8 +255,8 @@ static void epu_dma_done(struct cx18 *cx
 	s = cx18_handle_to_stream(cx, handle);
 
 	if (s == NULL) {
-		CX18_WARN("Got DMA done notification for unknown/inactive"
-			  " handle %d, %s mailbox seq no %d\n", handle,
+		CX18_WARN("Got DMA done notification for unknown/inactive handle %d, %s mailbox seq no %d\n",
+			  handle,
 			  (order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) ?
 			  "stale" : "good", mb->request);
 		return;
@@ -290,9 +290,8 @@ static void epu_dma_done(struct cx18 *cx
 		if ((order->flags & CX18_F_EWO_MB_STALE_UPON_RECEIPT) &&
 		    !(id >= s->mdl_base_idx &&
 		      id < (s->mdl_base_idx + s->buffers))) {
-			CX18_WARN("Fell behind! Ignoring stale mailbox with "
-				  " inconsistent data. Lost MDL for mailbox "
-				  "seq no %d\n", mb->request);
+			CX18_WARN("Fell behind! Ignoring stale mailbox with  inconsistent data. Lost MDL for mailbox seq no %d\n",
+				  mb->request);
 			break;
 		}
 		mdl = cx18_queue_get_mdl(s, id, mdl_ack->data_used);
@@ -418,9 +417,7 @@ static void mb_ack_irq(struct cx18 *cx,
 	/* Don't ack if the RPU has gotten impatient and timed us out */
 	if (req != cx18_readl(cx, &ack_mb->request) ||
 	    req == cx18_readl(cx, &ack_mb->ack)) {
-		CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
-				"incoming %s to EPU mailbox (sequence no. %u) "
-				"while processing\n",
+		CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our incoming %s to EPU mailbox (sequence no. %u) while processing\n",
 				rpu_str[order->rpu], rpu_str[order->rpu], req);
 		order->flags |= CX18_F_EWO_MB_STALE_WHILE_PROC;
 		return;
@@ -555,8 +552,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *c
 
 	order = alloc_in_work_order_irq(cx);
 	if (order == NULL) {
-		CX18_WARN("Unable to find blank work order form to schedule "
-			  "incoming mailbox command processing\n");
+		CX18_WARN("Unable to find blank work order form to schedule incoming mailbox command processing\n");
 		return;
 	}
 
@@ -573,9 +569,7 @@ void cx18_api_epu_cmd_irq(struct cx18 *c
 		(&order_mb->request)[i] = cx18_readl(cx, &mb->request + i);
 
 	if (order_mb->request == order_mb->ack) {
-		CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our "
-				"incoming %s to EPU mailbox (sequence no. %u)"
-				"\n",
+		CX18_DEBUG_WARN("Possibly falling behind: %s self-ack'ed our incoming %s to EPU mailbox (sequence no. %u)\n",
 				rpu_str[rpu], rpu_str[rpu], order_mb->request);
 		if (cx18_debug & CX18_DBGFLG_WARN)
 			dump_mb(cx, order_mb, "incoming");
@@ -663,8 +657,8 @@ static int cx18_api_call(struct cx18 *cx
 	if (req != ack) {
 		/* waited long enough, make the mbox "not busy" from our end */
 		cx18_writel(cx, req, &mb->ack);
-		CX18_ERR("mbox was found stuck busy when setting up for %s; "
-			 "clearing busy and trying to proceed\n", info->name);
+		CX18_ERR("mbox was found stuck busy when setting up for %s; clearing busy and trying to proceed\n",
+			 info->name);
 	} else if (ret != timeout)
 		CX18_DEBUG_API("waited %u msecs for busy mbox to be acked\n",
 			       jiffies_to_msecs(timeout-ret));
@@ -707,14 +701,10 @@ static int cx18_api_call(struct cx18 *cx
 		mutex_unlock(mb_lock);
 		if (ret >= timeout) {
 			/* Timed out */
-			CX18_DEBUG_WARN("sending %s timed out waiting %d msecs "
-					"for RPU acknowledgement\n",
+			CX18_DEBUG_WARN("sending %s timed out waiting %d msecs for RPU acknowledgment\n",
 					info->name, jiffies_to_msecs(ret));
 		} else {
-			CX18_DEBUG_WARN("woken up before mailbox ack was ready "
-					"after submitting %s to RPU.  only "
-					"waited %d msecs on req %u but awakened"
-					" with unmatched ack %u\n",
+			CX18_DEBUG_WARN("woken up before mailbox ack was ready after submitting %s to RPU.  only waited %d msecs on req %u but awakened with unmatched ack %u\n",
 					info->name,
 					jiffies_to_msecs(ret),
 					req, ack);
@@ -723,8 +713,7 @@ static int cx18_api_call(struct cx18 *cx
 	}
 
 	if (ret >= timeout)
-		CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment "
-				"sending %s; timed out waiting %d msecs\n",
+		CX18_DEBUG_WARN("failed to be awakened upon RPU acknowledgment sending %s; timed out waiting %d msecs\n",
 				info->name, jiffies_to_msecs(ret));
 	else
 		CX18_DEBUG_HI_API("waited %u msecs for %s to be acked\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-queue.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-queue.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-queue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-queue.c	2017-02-12 16:03:20.000000000 -0500
@@ -164,9 +164,8 @@ struct cx18_mdl *cx18_queue_get_mdl(stru
 			mdl->skipped++;
 			if (mdl->skipped >= atomic_read(&s->q_busy.depth)-1) {
 				/* mdl must have fallen out of rotation */
-				CX18_WARN("Skipped %s, MDL %d, %d "
-					  "times - it must have dropped out of "
-					  "rotation\n", s->name, mdl->id,
+				CX18_WARN("Skipped %s, MDL %d, %d times - it must have dropped out of rotation\n",
+					  s->name, mdl->id,
 					  mdl->skipped);
 				/* Sweep it up to put it back into rotation */
 				list_move_tail(&mdl->list, &sweep_up);
@@ -352,8 +351,7 @@ int cx18_stream_alloc(struct cx18_stream
 	if (s->buffers == 0)
 		return 0;
 
-	CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers "
-			"(%d.%02d kB total)\n",
+	CX18_DEBUG_INFO("Allocate %s stream: %d x %d buffers (%d.%02d kB total)\n",
 		s->name, s->buffers, s->buf_size,
 		s->buffers * s->buf_size / 1024,
 		(s->buffers * s->buf_size * 100 / 1024) % 100);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-streams.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-streams.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx18/cx18-streams.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx18/cx18-streams.c	2017-02-12 16:03:20.000000000 -0500
@@ -353,8 +353,8 @@ static int cx18_prep_dev(struct cx18 *cx
 		if (cx->card->hw_all & CX18_HW_DVB) {
 			s->dvb = kzalloc(sizeof(struct cx18_dvb), GFP_KERNEL);
 			if (s->dvb == NULL) {
-				CX18_ERR("Couldn't allocate cx18_dvb structure"
-					 " for %s\n", s->name);
+				CX18_ERR("Couldn't allocate cx18_dvb structure for %s\n",
+					 s->name);
 				return -ENOMEM;
 			}
 		} else {
@@ -462,8 +462,7 @@ static int cx18_reg_dev(struct cx18 *cx,
 
 	case VFL_TYPE_VBI:
 		if (cx->stream_buffers[type])
-			CX18_INFO("Registered device %s for %s "
-				  "(%d x %d bytes)\n",
+			CX18_INFO("Registered device %s for %s (%d x %d bytes)\n",
 				  name, s->name, cx->stream_buffers[type],
 				  cx->stream_buf_size[type]);
 		else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/altera-ci.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/altera-ci.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/altera-ci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/altera-ci.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,9 @@
  * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
  * +-------+-------+-------+-------+-------+-------+-------+-------+
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <dvb_demux.h>
 #include <dvb_frontend.h>
 #include "altera-ci.h"
@@ -84,16 +87,18 @@ MODULE_DESCRIPTION("altera FPGA CI modul
 MODULE_AUTHOR("Igor M. Liplianin  <liplianin@netup.ru>");
 MODULE_LICENSE("GPL");
 
-#define ci_dbg_print(args...) \
+#define ci_dbg_print(fmt, args...) \
 	do { \
 		if (ci_dbg) \
-			printk(KERN_DEBUG args); \
+			printk(KERN_DEBUG pr_fmt("%s: " fmt), \
+			       __func__, ##args); \
 	} while (0)
 
-#define pid_dbg_print(args...) \
+#define pid_dbg_print(fmt, args...) \
 	do { \
 		if (pid_dbg) \
-			printk(KERN_DEBUG args); \
+			printk(KERN_DEBUG pr_fmt("%s: " fmt), \
+			       __func__, ##args); \
 	} while (0)
 
 struct altera_ci_state;
@@ -718,7 +723,7 @@ int altera_ci_init(struct altera_ci_conf
 	if (temp_int != NULL) {
 		inter = temp_int->internal;
 		(inter->cis_used)++;
-                inter->fpga_rw = config->fpga_rw;
+		inter->fpga_rw = config->fpga_rw;
 		ci_dbg_print("%s: Find Internal Structure!\n", __func__);
 	} else {
 		inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/altera-ci.h linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/altera-ci.h
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/altera-ci.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/altera-ci.h	2017-02-12 16:03:20.000000000 -0500
@@ -48,24 +48,24 @@ extern int altera_ci_tuner_reset(void *d
 
 static inline int altera_ci_init(struct altera_ci_config *config, int ci_nr)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 	return 0;
 }
 
 static inline void altera_ci_release(void *dev, int ci_nr)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 }
 
 static inline int altera_ci_irq(void *dev)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 	return 0;
 }
 
 static inline int altera_ci_tuner_reset(void *dev, int ci_nr)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 	return 0;
 }
 
@@ -74,19 +74,19 @@ static inline int altera_ci_tuner_reset(
 static inline int altera_hw_filt_init(struct altera_ci_config *config,
 							int hw_filt_nr)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 	return 0;
 }
 
 static inline void altera_hw_filt_release(void *dev, int filt_nr)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 }
 
 static inline int altera_pid_feed_control(void *dev, int filt_nr,
 		struct dvb_demux_feed *dvbdmxfeed, int onoff)
 {
-	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	pr_warn("%s: driver disabled by Kconfig\n", __func__);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cimax2.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cimax2.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cimax2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cimax2.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,10 +65,11 @@ static unsigned int ci_irq_enable;
 module_param(ci_irq_enable, int, 0644);
 MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM");
 
-#define ci_dbg_print(args...) \
+#define ci_dbg_print(fmt, args...) \
 	do { \
 		if (ci_dbg) \
-			printk(KERN_DEBUG args); \
+			printk(KERN_DEBUG pr_fmt("%s: " fmt), \
+			       __func__, ##args); \
 	} while (0)
 
 #define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0)
@@ -135,8 +136,7 @@ static int netup_write_i2c(struct i2c_ad
 	};
 
 	if (1 + len > sizeof(buffer)) {
-		printk(KERN_WARNING
-		       "%s: i2c wr reg=%04x: len=%d is too big!\n",
+		pr_warn("%s: i2c wr reg=%04x: len=%d is too big!\n",
 		       KBUILD_MODNAME, reg, len);
 		return -EINVAL;
 	}
@@ -365,11 +365,8 @@ static void netup_read_ci_status(struct
 		if (ret != 0)
 			return;
 
-		ci_dbg_print("%s: Slot Status Addr=[0x%04x], "
-				"Reg=[0x%02x], data=%02x, "
-				"TS config = %02x\n", __func__,
-				state->ci_i2c_addr, 0, buf[0],
-				buf[0]);
+		ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, TS config = %02x\n",
+			     __func__,	state->ci_i2c_addr, 0, buf[0], buf[0]);
 
 
 		if (buf[0] & 1)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-417.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-417.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-417.c	2016-12-11 17:47:33.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-417.c	2017-02-12 17:34:42.000000000 -0500
@@ -20,6 +20,9 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+#include "cx23885-ioctl.h"
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -32,9 +35,6 @@
 #include <media/v4l2-ioctl.h>
 #include <media/drv-intf/cx2341x.h>
 
-#include "cx23885.h"
-#include "cx23885-ioctl.h"
-
 #define CX23885_FIRM_IMAGE_SIZE 376836
 #define CX23885_FIRM_IMAGE_NAME "/*(DEBLOBBED)*/"
 
@@ -55,8 +55,8 @@ MODULE_PARM_DESC(v4l_debug, "enable V4L
 
 #define dprintk(level, fmt, arg...)\
 	do { if (v4l_debug >= level) \
-		printk(KERN_DEBUG "%s: " fmt, \
-		(dev) ? dev->name : "cx23885[?]", ## arg); \
+		printk(KERN_DEBUG pr_fmt("%s: 417:" fmt), \
+			__func__, ##arg); \
 	} while (0)
 
 static struct cx23885_tvnorm cx23885_tvnorms[] = {
@@ -769,10 +769,8 @@ static int cx23885_mbox_func(void *priv,
 	   without side effects */
 	mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
 	if (value != 0x12345678) {
-		printk(KERN_ERR
-			"Firmware and/or mailbox pointer not initialized "
-			"or corrupted, signature = 0x%x, cmd = %s\n", value,
-			cmd_to_str(command));
+		pr_err("Firmware and/or mailbox pointer not initialized or corrupted, signature = 0x%x, cmd = %s\n",
+			value, cmd_to_str(command));
 		return -1;
 	}
 
@@ -781,8 +779,8 @@ static int cx23885_mbox_func(void *priv,
 	 */
 	mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
 	if (flag) {
-		printk(KERN_ERR "ERROR: Mailbox appears to be in use "
-			"(%x), cmd = %s\n", flag, cmd_to_str(command));
+		pr_err("ERROR: Mailbox appears to be in use (%x), cmd = %s\n",
+		       flag, cmd_to_str(command));
 		return -1;
 	}
 
@@ -811,7 +809,7 @@ static int cx23885_mbox_func(void *priv,
 		if (0 != (flag & 4))
 			break;
 		if (time_after(jiffies, timeout)) {
-			printk(KERN_ERR "ERROR: API Mailbox timeout\n");
+			pr_err("ERROR: API Mailbox timeout\n");
 			return -1;
 		}
 		udelay(10);
@@ -888,7 +886,7 @@ static int cx23885_find_mailbox(struct c
 			return i+1;
 		}
 	}
-	printk(KERN_ERR "Mailbox signature values not found!\n");
+	pr_err("Mailbox signature values not found!\n");
 	return -1;
 }
 
@@ -923,7 +921,7 @@ static int cx23885_load_firmware(struct
 		IVTV_REG_APU, 0);
 
 	if (retval != 0) {
-		printk(KERN_ERR "%s: Error with mc417_register_write\n",
+		pr_err("%s: Error with mc417_register_write\n",
 			__func__);
 		return -1;
 	}
@@ -932,25 +930,21 @@ static int cx23885_load_firmware(struct
 				  &dev->pci->dev);
 
 	if (retval != 0) {
-		printk(KERN_ERR
-			"ERROR: Hotplug firmware request failed (%s).\n",
-			CX23885_FIRM_IMAGE_NAME);
-		printk(KERN_ERR "Please fix your hotplug setup, the board will "
-			"not work without firmware loaded!\n");
+		pr_err("ERROR: Hotplug firmware request failed (%s).\n",
+		       CX23885_FIRM_IMAGE_NAME);
+		pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
 		return -1;
 	}
 
 	if (firmware->size != CX23885_FIRM_IMAGE_SIZE) {
-		printk(KERN_ERR "ERROR: Firmware size mismatch "
-			"(have %zu, expected %d)\n",
-			firmware->size, CX23885_FIRM_IMAGE_SIZE);
+		pr_err("ERROR: Firmware size mismatch (have %zu, expected %d)\n",
+		       firmware->size, CX23885_FIRM_IMAGE_SIZE);
 		release_firmware(firmware);
 		return -1;
 	}
 
 	if (0 != memcmp(firmware->data, magic, 8)) {
-		printk(KERN_ERR
-			"ERROR: Firmware magic mismatch, wrong file?\n");
+		pr_err("ERROR: Firmware magic mismatch, wrong file?\n");
 		release_firmware(firmware);
 		return -1;
 	}
@@ -962,7 +956,7 @@ static int cx23885_load_firmware(struct
 		value = *dataptr;
 		checksum += ~value;
 		if (mc417_memory_write(dev, i, value) != 0) {
-			printk(KERN_ERR "ERROR: Loading firmware failed!\n");
+			pr_err("ERROR: Loading firmware failed!\n");
 			release_firmware(firmware);
 			return -1;
 		}
@@ -973,15 +967,14 @@ static int cx23885_load_firmware(struct
 	dprintk(1, "Verifying firmware ...\n");
 	for (i--; i >= 0; i--) {
 		if (mc417_memory_read(dev, i, &value) != 0) {
-			printk(KERN_ERR "ERROR: Reading firmware failed!\n");
+			pr_err("ERROR: Reading firmware failed!\n");
 			release_firmware(firmware);
 			return -1;
 		}
 		checksum -= ~value;
 	}
 	if (checksum) {
-		printk(KERN_ERR
-			"ERROR: Firmware load failed (checksum mismatch).\n");
+		pr_err("ERROR: Firmware load failed (checksum mismatch).\n");
 		release_firmware(firmware);
 		return -1;
 	}
@@ -1006,7 +999,7 @@ static int cx23885_load_firmware(struct
 	mc417_register_read(dev, 0x900C, &gpio_value);
 
 	if (retval < 0)
-		printk(KERN_ERR "%s: Error with mc417_register_write\n",
+		pr_err("%s: Error with mc417_register_write\n",
 			__func__);
 	return 0;
 }
@@ -1058,27 +1051,25 @@ static int cx23885_initialize_codec(stru
 		dprintk(2, "%s() PING OK\n", __func__);
 		retval = cx23885_load_firmware(dev);
 		if (retval < 0) {
-			printk(KERN_ERR "%s() f/w load failed\n", __func__);
+			pr_err("%s() f/w load failed\n", __func__);
 			return retval;
 		}
 		retval = cx23885_find_mailbox(dev);
 		if (retval < 0) {
-			printk(KERN_ERR "%s() mailbox < 0, error\n",
+			pr_err("%s() mailbox < 0, error\n",
 				__func__);
 			return -1;
 		}
 		dev->cx23417_mailbox = retval;
 		retval = cx23885_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
 		if (retval < 0) {
-			printk(KERN_ERR
-				"ERROR: cx23417 firmware ping failed!\n");
+			pr_err("ERROR: cx23417 firmware ping failed!\n");
 			return -1;
 		}
 		retval = cx23885_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
 			&version);
 		if (retval < 0) {
-			printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
-				"version failed!\n");
+			pr_err("ERROR: cx23417 firmware get encoder :version failed!\n");
 			return -1;
 		}
 		dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
@@ -1563,11 +1554,11 @@ int cx23885_417_register(struct cx23885_
 	err = video_register_device(dev->v4l_device,
 		VFL_TYPE_GRABBER, -1);
 	if (err < 0) {
-		printk(KERN_INFO "%s: can't register mpeg device\n", dev->name);
+		pr_info("%s: can't register mpeg device\n", dev->name);
 		return err;
 	}
 
-	printk(KERN_INFO "%s: registered device %s [mpeg]\n",
+	pr_info("%s: registered device %s [mpeg]\n",
 	       dev->name, video_device_node_name(dev->v4l_device));
 
 	/* ST: Configure the encoder paramaters, but don't begin
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-alsa.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-alsa.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-alsa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-alsa.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,9 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+#include "cx23885-reg.h"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -35,20 +38,14 @@
 
 #include <sound/tlv.h>
 
-
-#include "cx23885.h"
-#include "cx23885-reg.h"
-
 #define AUDIO_SRAM_CHANNEL	SRAM_CH07
 
 #define dprintk(level, fmt, arg...) do {				\
 	if (audio_debug + 1 > level)					\
-		printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg);	\
+		printk(KERN_DEBUG pr_fmt("%s: alsa: " fmt), \
+			chip->dev->name, ##arg); \
 } while(0)
 
-#define dprintk_core(level, fmt, arg...)	if (audio_debug >= level) \
-	printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg)
-
 /****************************************************************************
 			Module global static vars
  ****************************************************************************/
@@ -186,8 +183,8 @@ static int cx23885_start_audio_dma(struc
 	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,
+	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 */
@@ -247,7 +244,7 @@ int cx23885_audio_irq(struct cx23885_dev
 
 	/* risc op code error */
 	if (status & AUD_INT_OPC_ERR) {
-		printk(KERN_WARNING "%s/1: Audio risc op code error\n",
+		pr_warn("%s/1: Audio risc op code error\n",
 			dev->name);
 		cx_clear(AUD_INT_DMA_CTL, 0x11);
 		cx23885_sram_channel_dump(dev,
@@ -327,8 +324,7 @@ static int snd_cx23885_pcm_open(struct s
 	int err;
 
 	if (!chip) {
-		printk(KERN_ERR "BUG: cx23885 can't find device struct."
-				" Can't proceed with open\n");
+		pr_err("BUG: cx23885 can't find device struct. Can't proceed with open\n");
 		return -ENODEV;
 	}
 
@@ -555,8 +551,8 @@ struct cx23885_audio_dev *cx23885_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__);
+		pr_warn("%s(): Missing SRAM channel configuration for analog TV Audio\n",
+		       __func__);
 		return NULL;
 	}
 
@@ -590,8 +586,8 @@ struct cx23885_audio_dev *cx23885_audio_
 
 error:
 	snd_card_free(card);
-	printk(KERN_ERR "%s(): Failed to register analog "
-			"audio adapter\n", __func__);
+	pr_err("%s(): Failed to register analog audio adapter\n",
+	       __func__);
 
 	return NULL;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-cards.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-cards.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-cards.c	2016-12-11 17:47:37.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-cards.c	2017-02-12 17:34:46.000000000 -0500
@@ -15,6 +15,8 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -23,7 +25,6 @@
 #include <linux/firmware.h>
 #include <misc/altera.h>
 
-#include "cx23885.h"
 #include "tuner-xc2028.h"
 #include "netup-eeprom.h"
 #include "netup-init.h"
@@ -1096,26 +1097,24 @@ void cx23885_card_list(struct cx23885_de
 
 	if (0 == dev->pci->subsystem_vendor &&
 	    0 == dev->pci->subsystem_device) {
-		printk(KERN_INFO
-			"%s: Board has no valid PCIe Subsystem ID and can't\n"
-		       "%s: be autodetected. Pass card=<n> insmod option\n"
-		       "%s: to workaround that. Redirect complaints to the\n"
-		       "%s: vendor of the TV card.  Best regards,\n"
-		       "%s:         -- tux\n",
-		       dev->name, dev->name, dev->name, dev->name, dev->name);
+		pr_info("%s: Board has no valid PCIe Subsystem ID and can't\n"
+			"%s: be autodetected. Pass card=<n> insmod option\n"
+			"%s: to workaround that. Redirect complaints to the\n"
+			"%s: vendor of the TV card.  Best regards,\n"
+			"%s:         -- tux\n",
+			dev->name, dev->name, dev->name, dev->name, dev->name);
 	} else {
-		printk(KERN_INFO
-			"%s: Your board isn't known (yet) to the driver.\n"
-		       "%s: Try to pick one of the existing card configs via\n"
-		       "%s: card=<n> insmod option.  Updating to the latest\n"
-		       "%s: version might help as well.\n",
-		       dev->name, dev->name, dev->name, dev->name);
+		pr_info("%s: Your board isn't known (yet) to the driver.\n"
+			"%s: Try to pick one of the existing card configs via\n"
+			"%s: card=<n> insmod option.  Updating to the latest\n"
+			"%s: version might help as well.\n",
+			dev->name, dev->name, dev->name, dev->name);
 	}
-	printk(KERN_INFO "%s: Here is a list of valid choices for the card=<n> insmod option:\n",
+	pr_info("%s: Here is a list of valid choices for the card=<n> insmod option:\n",
 	       dev->name);
 	for (i = 0; i < cx23885_bcount; i++)
-		printk(KERN_INFO "%s:    card=%d -> %s\n",
-		       dev->name, i, cx23885_boards[i].name);
+		pr_info("%s:    card=%d -> %s\n",
+			dev->name, i, cx23885_boards[i].name);
 }
 
 static void viewcast_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
@@ -1304,14 +1303,13 @@ static void hauppauge_eeprom(struct cx23
 		 */
 		break;
 	default:
-		printk(KERN_WARNING "%s: warning: "
-			"unknown hauppauge model #%d\n",
+		pr_warn("%s: warning: unknown hauppauge model #%d\n",
 			dev->name, tv.model);
 		break;
 	}
 
-	printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
-			dev->name, tv.model);
+	pr_info("%s: hauppauge eeprom: model=%d\n",
+		dev->name, tv.model);
 }
 
 /* Some TBS cards require initing a chip using a bitbanged SPI attached
@@ -1353,8 +1351,8 @@ int cx23885_tuner_callback(void *priv, i
 		return 0;
 
 	if (command != 0) {
-		printk(KERN_ERR "%s(): Unknown command 0x%x.\n",
-			__func__, command);
+		pr_err("%s(): Unknown command 0x%x.\n",
+		       __func__, command);
 		return -EINVAL;
 	}
 
@@ -2337,14 +2335,13 @@ void cx23885_card_setup(struct cx23885_d
 			filename = "/*(DEBLOBBED)*/";
 			break;
 		}
-		printk(KERN_INFO "NetUP card rev=0x%x fw_filename=%s\n",
-				cinfo.rev, filename);
+		pr_info("NetUP card rev=0x%x fw_filename=%s\n",
+			cinfo.rev, filename);
 
 		ret = reject_firmware(&fw, filename, &dev->pci->dev);
 		if (ret != 0)
-			printk(KERN_ERR "did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details "
-			"on firmware-problems.", filename);
+			pr_err("did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems.",
+			       filename);
 		else
 			altera_init(&netup_config, fw);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-core.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-core.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,8 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -27,7 +29,6 @@
 #include <asm/div64.h>
 #include <linux/firmware.h>
 
-#include "cx23885.h"
 #include "cimax2.h"
 #include "altera-ci.h"
 #include "cx23888-ir.h"
@@ -50,7 +51,8 @@ MODULE_PARM_DESC(card, "card type");
 
 #define dprintk(level, fmt, arg...)\
 	do { if (debug >= level)\
-		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt), \
+		       __func__, ##arg); \
 	} while (0)
 
 static unsigned int cx23885_devcount;
@@ -407,19 +409,18 @@ static int cx23885_risc_decode(u32 risc)
 	};
 	int i;
 
-	printk("0x%08x [ %s", risc,
+	printk(KERN_DEBUG "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;
 }
 
 static void cx23885_wakeup(struct cx23885_tsport *port,
 			   struct cx23885_dmaqueue *q, u32 count)
 {
-	struct cx23885_dev *dev = port->dev;
 	struct cx23885_buffer *buf;
 
 	if (list_empty(&q->active))
@@ -530,44 +531,44 @@ void cx23885_sram_channel_dump(struct cx
 	u32 risc;
 	unsigned int i, j, n;
 
-	printk(KERN_WARNING "%s: %s - dma channel status dump\n",
-	       dev->name, ch->name);
+	pr_warn("%s: %s - dma channel status dump\n",
+		dev->name, ch->name);
 	for (i = 0; i < ARRAY_SIZE(name); i++)
-		printk(KERN_WARNING "%s:   cmds: %-15s: 0x%08x\n",
-		       dev->name, name[i],
-		       cx_read(ch->cmds_start + 4*i));
+		pr_warn("%s:   cmds: %-15s: 0x%08x\n",
+			dev->name, name[i],
+			cx_read(ch->cmds_start + 4*i));
 
 	for (i = 0; i < 4; i++) {
 		risc = cx_read(ch->cmds_start + 4 * (i + 14));
-		printk(KERN_WARNING "%s:   risc%d: ", dev->name, i);
+		pr_warn("%s:   risc%d: ", dev->name, i);
 		cx23885_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 */
 
-		printk(KERN_WARNING "%s:   (0x%08x) iq %x: ", dev->name,
-		       ch->ctrl_start + 4 * i, i);
+		pr_warn("%s:   (0x%08x) iq %x: ", dev->name,
+			ch->ctrl_start + 4 * i, i);
 		n = cx23885_risc_decode(risc);
 		for (j = 1; j < n; j++) {
 			risc = cx_read(ch->ctrl_start + 4 * (i + j));
-			printk(KERN_WARNING "%s:   iq %x: 0x%08x [ arg #%d ]\n",
-			       dev->name, i+j, risc, j);
+			pr_warn("%s:   iq %x: 0x%08x [ arg #%d ]\n",
+				dev->name, i+j, risc, j);
 		}
 	}
 
-	printk(KERN_WARNING "%s: fifo: 0x%08x -> 0x%x\n",
-	       dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
-	printk(KERN_WARNING "%s: ctrl: 0x%08x -> 0x%x\n",
-	       dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
-	printk(KERN_WARNING "%s:   ptr1_reg: 0x%08x\n",
-	       dev->name, cx_read(ch->ptr1_reg));
-	printk(KERN_WARNING "%s:   ptr2_reg: 0x%08x\n",
-	       dev->name, cx_read(ch->ptr2_reg));
-	printk(KERN_WARNING "%s:   cnt1_reg: 0x%08x\n",
-	       dev->name, cx_read(ch->cnt1_reg));
-	printk(KERN_WARNING "%s:   cnt2_reg: 0x%08x\n",
-	       dev->name, cx_read(ch->cnt2_reg));
+	pr_warn("%s: fifo: 0x%08x -> 0x%x\n",
+		dev->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
+	pr_warn("%s: ctrl: 0x%08x -> 0x%x\n",
+		dev->name, ch->ctrl_start, ch->ctrl_start + 6*16);
+	pr_warn("%s:   ptr1_reg: 0x%08x\n",
+		dev->name, cx_read(ch->ptr1_reg));
+	pr_warn("%s:   ptr2_reg: 0x%08x\n",
+		dev->name, cx_read(ch->ptr2_reg));
+	pr_warn("%s:   cnt1_reg: 0x%08x\n",
+		dev->name, cx_read(ch->cnt1_reg));
+	pr_warn("%s:   cnt2_reg: 0x%08x\n",
+		dev->name, cx_read(ch->cnt2_reg));
 }
 
 static void cx23885_risc_disasm(struct cx23885_tsport *port,
@@ -576,14 +577,14 @@ static void cx23885_risc_disasm(struct c
 	struct cx23885_dev *dev = port->dev;
 	unsigned int i, j, n;
 
-	printk(KERN_INFO "%s: risc disasm: %p [dma=0x%08lx]\n",
+	pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
 	       dev->name, risc->cpu, (unsigned long)risc->dma);
 	for (i = 0; i < (risc->size >> 2); i += n) {
-		printk(KERN_INFO "%s:   %04d: ", dev->name, i);
+		pr_info("%s:   %04d: ", dev->name, i);
 		n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
 		for (j = 1; j < n; j++)
-			printk(KERN_INFO "%s:   %04d: 0x%08x [ arg #%d ]\n",
-			       dev->name, i + j, risc->cpu[i + j], j);
+			pr_info("%s:   %04d: 0x%08x [ arg #%d ]\n",
+				dev->name, i + j, risc->cpu[i + j], j);
 		if (risc->cpu[i] == cpu_to_le32(RISC_JUMP))
 			break;
 	}
@@ -674,8 +675,8 @@ static int get_resources(struct cx23885_
 			       dev->name))
 		return 0;
 
-	printk(KERN_ERR "%s: can't get MMIO memory @ 0x%llx\n",
-		dev->name, (unsigned long long)pci_resource_start(dev->pci, 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;
 }
@@ -793,15 +794,15 @@ static void cx23885_dev_checkrevision(st
 		dev->hwrevision = 0xb1;
 		break;
 	default:
-		printk(KERN_ERR "%s() New hardware revision found 0x%x\n",
-			__func__, dev->hwrevision);
+		pr_err("%s() New hardware revision found 0x%x\n",
+		       __func__, dev->hwrevision);
 	}
 	if (dev->hwrevision)
-		printk(KERN_INFO "%s() Hardware revision = 0x%02x\n",
+		pr_info("%s() Hardware revision = 0x%02x\n",
 			__func__, dev->hwrevision);
 	else
-		printk(KERN_ERR "%s() Hardware revision unknown 0x%x\n",
-			__func__, dev->hwrevision);
+		pr_err("%s() Hardware revision unknown 0x%x\n",
+		       __func__, dev->hwrevision);
 }
 
 /* Find the first v4l2_subdev member of the group id in hw */
@@ -915,8 +916,7 @@ static int cx23885_dev_setup(struct cx23
 		cx23885_init_tsport(dev, &dev->ts2, 2);
 
 	if (get_resources(dev) < 0) {
-		printk(KERN_ERR "CORE %s No more PCIe resources for "
-		       "subsystem: %04x:%04x\n",
+		pr_err("CORE %s No more PCIe resources for subsystem: %04x:%04x\n",
 		       dev->name, dev->pci->subsystem_vendor,
 		       dev->pci->subsystem_device);
 
@@ -930,11 +930,11 @@ static int cx23885_dev_setup(struct cx23
 
 	dev->bmmio = (u8 __iomem *)dev->lmmio;
 
-	printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
-	       dev->name, dev->pci->subsystem_vendor,
-	       dev->pci->subsystem_device, cx23885_boards[dev->board].name,
-	       dev->board, card[dev->nr] == dev->board ?
-	       "insmod option" : "autodetected");
+	pr_info("CORE %s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
+		dev->name, dev->pci->subsystem_vendor,
+		dev->pci->subsystem_device, cx23885_boards[dev->board].name,
+		dev->board, card[dev->nr] == dev->board ?
+		"insmod option" : "autodetected");
 
 	cx23885_pci_quirks(dev);
 
@@ -980,8 +980,8 @@ static int cx23885_dev_setup(struct cx23
 
 	if (cx23885_boards[dev->board].porta == CX23885_ANALOG_VIDEO) {
 		if (cx23885_video_register(dev) < 0) {
-			printk(KERN_ERR "%s() Failed to register analog "
-				"video adapters on VID_A\n", __func__);
+			pr_err("%s() Failed to register analog video adapters on VID_A\n",
+			       __func__);
 		}
 	}
 
@@ -990,14 +990,13 @@ static int cx23885_dev_setup(struct cx23
 			dev->ts1.num_frontends =
 				cx23885_boards[dev->board].num_fds_portb;
 		if (cx23885_dvb_register(&dev->ts1) < 0) {
-			printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
+			pr_err("%s() Failed to register dvb adapters on VID_B\n",
 			       __func__);
 		}
 	} else
 	if (cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER) {
 		if (cx23885_417_register(dev) < 0) {
-			printk(KERN_ERR
-				"%s() Failed to register 417 on VID_B\n",
+			pr_err("%s() Failed to register 417 on VID_B\n",
 			       __func__);
 		}
 	}
@@ -1007,15 +1006,13 @@ static int cx23885_dev_setup(struct cx23
 			dev->ts2.num_frontends =
 				cx23885_boards[dev->board].num_fds_portc;
 		if (cx23885_dvb_register(&dev->ts2) < 0) {
-			printk(KERN_ERR
-				"%s() Failed to register dvb on VID_C\n",
+			pr_err("%s() Failed to register dvb on VID_C\n",
 			       __func__);
 		}
 	} else
 	if (cx23885_boards[dev->board].portc == CX23885_MPEG_ENCODER) {
 		if (cx23885_417_register(dev) < 0) {
-			printk(KERN_ERR
-				"%s() Failed to register 417 on VID_C\n",
+			pr_err("%s() Failed to register 417 on VID_C\n",
 			       __func__);
 		}
 	}
@@ -1344,7 +1341,7 @@ int cx23885_start_dma(struct cx23885_tsp
 
 	if ((!(cx23885_boards[dev->board].portb & CX23885_MPEG_DVB)) &&
 		(!(cx23885_boards[dev->board].portc & CX23885_MPEG_DVB))) {
-		printk("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
+		pr_err("%s() Unsupported .portb/c (0x%08x)/(0x%08x)\n",
 			__func__,
 			cx23885_boards[dev->board].portb,
 			cx23885_boards[dev->board].portc);
@@ -1531,7 +1528,6 @@ void cx23885_buf_queue(struct cx23885_ts
 
 static void do_cancel_buffers(struct cx23885_tsport *port, char *reason)
 {
-	struct cx23885_dev *dev = port->dev;
 	struct cx23885_dmaqueue *q = &port->mpegq;
 	struct cx23885_buffer *buf;
 	unsigned long flags;
@@ -1551,8 +1547,6 @@ static void do_cancel_buffers(struct cx2
 
 void cx23885_cancel_buffers(struct cx23885_tsport *port)
 {
-	struct cx23885_dev *dev = port->dev;
-
 	dprintk(1, "%s()\n", __func__);
 	cx23885_stop_dma(port);
 	do_cancel_buffers(port, "cancel");
@@ -1579,8 +1573,8 @@ int cx23885_irq_417(struct cx23885_dev *
 		(status & VID_B_MSK_VBI_SYNC)    ||
 		(status & VID_B_MSK_OF)          ||
 		(status & VID_B_MSK_VBI_OF)) {
-		printk(KERN_ERR "%s: V4L mpeg risc op code error, status "
-			"= 0x%x\n", dev->name, status);
+		pr_err("%s: V4L mpeg risc op code error, status = 0x%x\n",
+		       dev->name, status);
 		if (status & VID_B_MSK_BAD_PKT)
 			dprintk(1, "        VID_B_MSK_BAD_PKT\n");
 		if (status & VID_B_MSK_OPC_ERR)
@@ -1641,7 +1635,7 @@ static int cx23885_irq_ts(struct cx23885
 			dprintk(7, " (VID_BC_MSK_OF      0x%08x)\n",
 				VID_BC_MSK_OF);
 
-		printk(KERN_ERR "%s: mpeg risc op code error\n", dev->name);
+		pr_err("%s: mpeg risc op code error\n", dev->name);
 
 		cx_clear(port->reg_dma_ctl, port->dma_ctl_val);
 		cx23885_sram_channel_dump(dev,
@@ -1881,15 +1875,14 @@ void cx23885_gpio_set(struct cx23885_dev
 
 	if (mask & 0x0007fff8) {
 		if (encoder_on_portb(dev) || encoder_on_portc(dev))
-			printk(KERN_ERR
-				"%s: Setting GPIO on encoder ports\n",
+			pr_err("%s: Setting GPIO on encoder ports\n",
 				dev->name);
 		cx_set(MC417_RWD, (mask & 0x0007fff8) >> 3);
 	}
 
 	/* TODO: 23-19 */
 	if (mask & 0x00f80000)
-		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+		pr_info("%s: Unsupported\n", dev->name);
 }
 
 void cx23885_gpio_clear(struct cx23885_dev *dev, u32 mask)
@@ -1899,15 +1892,14 @@ void cx23885_gpio_clear(struct cx23885_d
 
 	if (mask & 0x0007fff8) {
 		if (encoder_on_portb(dev) || encoder_on_portc(dev))
-			printk(KERN_ERR
-				"%s: Clearing GPIO moving on encoder ports\n",
+			pr_err("%s: Clearing GPIO moving on encoder ports\n",
 				dev->name);
 		cx_clear(MC417_RWD, (mask & 0x7fff8) >> 3);
 	}
 
 	/* TODO: 23-19 */
 	if (mask & 0x00f80000)
-		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+		pr_info("%s: Unsupported\n", dev->name);
 }
 
 u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask)
@@ -1917,15 +1909,14 @@ u32 cx23885_gpio_get(struct cx23885_dev
 
 	if (mask & 0x0007fff8) {
 		if (encoder_on_portb(dev) || encoder_on_portc(dev))
-			printk(KERN_ERR
-				"%s: Reading GPIO moving on encoder ports\n",
+			pr_err("%s: Reading GPIO moving on encoder ports\n",
 				dev->name);
 		return (cx_read(MC417_RWD) & ((mask & 0x7fff8) >> 3)) << 3;
 	}
 
 	/* TODO: 23-19 */
 	if (mask & 0x00f80000)
-		printk(KERN_INFO "%s: Unsupported\n", dev->name);
+		pr_info("%s: Unsupported\n", dev->name);
 
 	return 0;
 }
@@ -1939,8 +1930,7 @@ void cx23885_gpio_enable(struct cx23885_
 
 	if (mask & 0x0007fff8) {
 		if (encoder_on_portb(dev) || encoder_on_portc(dev))
-			printk(KERN_ERR
-				"%s: Enabling GPIO on encoder ports\n",
+			pr_err("%s: Enabling GPIO on encoder ports\n",
 				dev->name);
 	}
 
@@ -1995,8 +1985,8 @@ static int cx23885_initdev(struct pci_de
 	/* print pci info */
 	dev->pci_rev = pci_dev->revision;
 	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
-	       "latency: %d, mmio: 0x%llx\n", dev->name,
+	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)pci_resource_start(pci_dev, 0));
@@ -2004,14 +1994,14 @@ static int cx23885_initdev(struct pci_de
 	pci_set_master(pci_dev);
 	err = pci_set_dma_mask(pci_dev, 0xffffffff);
 	if (err) {
-		printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
+		pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
 		goto fail_ctrl;
 	}
 
 	err = request_irq(pci_dev->irq, cx23885_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err < 0) {
-		printk(KERN_ERR "%s: can't get IRQ %d\n",
+		pr_err("%s: can't get IRQ %d\n",
 		       dev->name, pci_dev->irq);
 		goto fail_irq;
 	}
@@ -2097,7 +2087,7 @@ static struct pci_driver cx23885_pci_dri
 
 static int __init cx23885_init(void)
 {
-	printk(KERN_INFO "cx23885 driver version %s loaded\n",
+	pr_info("cx23885 driver version %s loaded\n",
 		CX23885_VERSION);
 	return pci_register_driver(&cx23885_pci_driver);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-dvb.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-dvb.c	2016-12-11 17:43:41.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-dvb.c	2017-02-12 17:28:08.000000000 -0500
@@ -15,6 +15,8 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -23,7 +25,6 @@
 #include <linux/file.h>
 #include <linux/suspend.h>
 
-#include "cx23885.h"
 #include <media/v4l2-common.h>
 
 #include "dvb_ca_en50221.h"
@@ -80,7 +81,8 @@ static unsigned int debug;
 
 #define dprintk(level, fmt, arg...)\
 	do { if (debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG pr_fmt("%s dvb: " fmt), \
+			__func__, ##arg); \
 	} while (0)
 
 /* ------------------------------------------------------------------ */
@@ -1101,7 +1103,7 @@ static int dvb_register_ci_mac(struct cx
 		netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
 		memcpy(port->frontends.adapter.proposed_mac,
 				cinfo.port[port->nr - 1].mac, 6);
-		printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
+		pr_info("NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
 			port->nr, port->frontends.adapter.proposed_mac);
 
 		netup_ci_init(port);
@@ -1127,7 +1129,7 @@ static int dvb_register_ci_mac(struct cx
 		/* Read entire EEPROM */
 		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
 		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
-		printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
+		pr_info("TeVii S470 MAC= %pM\n", eeprom + 0xa0);
 		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
 		return 0;
 		}
@@ -1144,7 +1146,7 @@ static int dvb_register_ci_mac(struct cx
 		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
 		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
 				sizeof(eeprom));
-		printk(KERN_INFO "%s port %d MAC address: %pM\n",
+		pr_info("%s port %d MAC address: %pM\n",
 			cx23885_boards[dev->board].name, port->nr,
 			eeprom + 0xc0 + (port->nr-1) * 8);
 		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
@@ -1185,7 +1187,7 @@ static int dvb_register_ci_mac(struct cx
 		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
 		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
 				sizeof(eeprom));
-		printk(KERN_INFO "%s MAC address: %pM\n",
+		pr_info("%s MAC address: %pM\n",
 			cx23885_boards[dev->board].name, eeprom + 0xc0);
 		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6);
 		return 0;
@@ -1464,7 +1466,7 @@ static int dvb_register(struct cx23885_t
 			return -ENODEV;
 
 		if (dib7000p_ops.i2c_enumeration(&i2c_bus->i2c_adap, 1, 0x12, &dib7070p_dib7000p_config) < 0) {
-			printk(KERN_WARNING "Unable to enumerate dib7000p\n");
+			pr_warn("Unable to enumerate dib7000p\n");
 			return -ENODEV;
 		}
 		fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap, 0x80, &dib7070p_dib7000p_config);
@@ -1524,7 +1526,7 @@ static int dvb_register(struct cx23885_t
 			fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
 					&dev->i2c_bus[1].i2c_adap, &cfg);
 			if (!fe) {
-				printk(KERN_ERR "%s/2: xc4000 attach failed\n",
+				pr_err("%s/2: xc4000 attach failed\n",
 				       dev->name);
 				goto frontend_detach;
 			}
@@ -1597,8 +1599,7 @@ static int dvb_register(struct cx23885_t
 							&i2c_bus->i2c_adap,
 							LNBH24_PCL | LNBH24_TTX,
 							LNBH24_TEN, 0x09))
-						printk(KERN_ERR
-							"No LNBH24 found!\n");
+						pr_err("No LNBH24 found!\n");
 
 				}
 			}
@@ -1618,8 +1619,7 @@ static int dvb_register(struct cx23885_t
 							&i2c_bus->i2c_adap,
 							LNBH24_PCL | LNBH24_TTX,
 							LNBH24_TEN, 0x0a))
-						printk(KERN_ERR
-							"No LNBH24 found!\n");
+						pr_err("No LNBH24 found!\n");
 
 				}
 			}
@@ -2482,14 +2482,13 @@ static int dvb_register(struct cx23885_t
 		break;
 
 	default:
-		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
-		       " isn't supported yet\n",
-		       dev->name);
+		pr_info("%s: The frontend of your DVB/ATSC card  isn't supported yet\n",
+			dev->name);
 		break;
 	}
 
 	if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
-		printk(KERN_ERR "%s: frontend initialization failed\n",
+		pr_err("%s: frontend initialization failed\n",
 		       dev->name);
 		goto frontend_detach;
 	}
@@ -2570,7 +2569,7 @@ int cx23885_dvb_register(struct cx23885_
 	 * are for safety, and should provide a good foundation for the
 	 * future addition of any multi-frontend cx23885 based boards.
 	 */
-	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
+	pr_info("%s() allocating %d frontend(s)\n", __func__,
 		port->num_frontends);
 
 	for (i = 1; i <= port->num_frontends; i++) {
@@ -2578,7 +2577,7 @@ int cx23885_dvb_register(struct cx23885_
 
 		if (vb2_dvb_alloc_frontend(
 			&port->frontends, i) == NULL) {
-			printk(KERN_ERR "%s() failed to alloc\n", __func__);
+			pr_err("%s() failed to alloc\n", __func__);
 			return -ENOMEM;
 		}
 
@@ -2597,7 +2596,7 @@ int cx23885_dvb_register(struct cx23885_
 
 		/* dvb stuff */
 		/* We have to init the queue for each frontend on a port. */
-		printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
+		pr_info("%s: cx23885 based dvb card\n", dev->name);
 		q = &fe0->dvb.dvbq;
 		q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
@@ -2617,8 +2616,8 @@ int cx23885_dvb_register(struct cx23885_
 	}
 	err = dvb_register(port);
 	if (err != 0)
-		printk(KERN_ERR "%s() dvb_register failed err = %d\n",
-			__func__, err);
+		pr_err("%s() dvb_register failed err = %d\n",
+		       __func__, err);
 
 	return err;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-f300.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-f300.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-f300.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-f300.c	2017-02-12 16:03:20.000000000 -0500
@@ -122,7 +122,7 @@ static u8 f300_xfer(struct dvb_frontend
 	}
 
 	if (i > 7) {
-		printk(KERN_ERR "%s: timeout, the slave no response\n",
+		pr_err("%s: timeout, the slave no response\n",
 								__func__);
 		ret = 1; /* timeout, the slave no response */
 	} else { /* the slave not busy, prepare for getting data */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885.h linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885.h
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885.h	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,8 @@
  *  GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/pci.h>
 #include <linux/i2c.h>
 #include <linux/kdev_t.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-i2c.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,14 +15,14 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <asm/io.h>
 
-#include "cx23885.h"
-
 #include <media/v4l2-common.h>
 
 static unsigned int i2c_debug;
@@ -35,7 +35,8 @@ MODULE_PARM_DESC(i2c_scan, "scan i2c bus
 
 #define dprintk(level, fmt, arg...)\
 	do { if (i2c_debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG pr_fmt("%s: i2c:" fmt), \
+			__func__, ##arg); \
 	} while (0)
 
 #define I2C_WAIT_DELAY 32
@@ -119,9 +120,9 @@ static int i2c_sendbytes(struct i2c_adap
 	if (!i2c_wait_done(i2c_adap))
 		goto eio;
 	if (i2c_debug) {
-		printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]);
+		printk(KERN_DEBUG " <W %02x %02x", msg->addr << 1, msg->buf[0]);
 		if (!(ctrl & I2C_NOSTOP))
-			printk(" >\n");
+			pr_cont(" >\n");
 	}
 
 	for (cnt = 1; cnt < msg->len; cnt++) {
@@ -141,9 +142,9 @@ static int i2c_sendbytes(struct i2c_adap
 		if (!i2c_wait_done(i2c_adap))
 			goto eio;
 		if (i2c_debug) {
-			dprintk(1, " %02x", msg->buf[cnt]);
+			pr_cont(" %02x", msg->buf[cnt]);
 			if (!(ctrl & I2C_NOSTOP))
-				dprintk(1, " >\n");
+				pr_cont(" >\n");
 		}
 	}
 	return msg->len;
@@ -151,7 +152,7 @@ static int i2c_sendbytes(struct i2c_adap
  eio:
 	retval = -EIO;
 	if (i2c_debug)
-		printk(KERN_ERR " ERR: %d\n", retval);
+		pr_err(" ERR: %d\n", retval);
 	return retval;
 }
 
@@ -212,15 +213,13 @@ static int i2c_readbytes(struct i2c_adap
  eio:
 	retval = -EIO;
 	if (i2c_debug)
-		printk(KERN_ERR " ERR: %d\n", retval);
+		pr_err(" ERR: %d\n", retval);
 	return retval;
 }
 
 static int i2c_xfer(struct i2c_adapter *i2c_adap,
 		    struct i2c_msg *msgs, int num)
 {
-	struct cx23885_i2c *bus = i2c_adap->algo_data;
-	struct cx23885_dev *dev = bus->dev;
 	int i, retval = 0;
 
 	dprintk(1, "%s(num = %d)\n", __func__, num);
@@ -302,7 +301,7 @@ static void do_i2c_scan(char *name, stru
 		rc = i2c_master_recv(c, &buf, 0);
 		if (rc < 0)
 			continue;
-		printk(KERN_INFO "%s: i2c scan: found device @ 0x%04x  [%s]\n",
+		pr_info("%s: i2c scan: found device @ 0x%04x  [%s]\n",
 		       name, i, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 }
@@ -330,12 +329,12 @@ int cx23885_i2c_register(struct cx23885_
 	if (0 == bus->i2c_rc) {
 		dprintk(1, "%s: i2c bus %d registered\n", dev->name, bus->nr);
 		if (i2c_scan) {
-			printk(KERN_INFO "%s: scan bus %d:\n",
+			pr_info("%s: scan bus %d:\n",
 					dev->name, bus->nr);
 			do_i2c_scan(dev->name, &bus->i2c_client);
 		}
 	} else
-		printk(KERN_WARNING "%s: i2c bus %d register FAILED\n",
+		pr_warn("%s: i2c bus %d register FAILED\n",
 			dev->name, bus->nr);
 
 	/* Instantiate the IR receiver device, if present */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-input.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-input.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-input.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-input.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,13 +30,13 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+#include "cx23885-input.h"
+
 #include <linux/slab.h>
 #include <media/rc-core.h>
 #include <media/v4l2-subdev.h>
 
-#include "cx23885.h"
-#include "cx23885-input.h"
-
 #define MODULE_NAME "cx23885"
 
 static void cx23885_input_process_measurements(struct cx23885_dev *dev,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-ir.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-ir.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-ir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-ir.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,12 +16,12 @@
  *  GNU General Public License for more details.
  */
 
-#include <media/v4l2-device.h>
-
 #include "cx23885.h"
 #include "cx23885-ir.h"
 #include "cx23885-input.h"
 
+#include <media/v4l2-device.h>
+
 #define CX23885_IR_RX_FIFO_SERVICE_REQ		0
 #define CX23885_IR_RX_END_OF_RX_DETECTED	1
 #define CX23885_IR_RX_HW_FIFO_OVERRUN		2
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-vbi.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-vbi.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-vbi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-vbi.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,13 +15,13 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 
-#include "cx23885.h"
-
 static unsigned int vbibufs = 4;
 module_param(vbibufs, int, 0644);
 MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
@@ -32,7 +32,8 @@ MODULE_PARM_DESC(vbi_debug, "enable debu
 
 #define dprintk(level, fmt, arg...)\
 	do { if (vbi_debug >= level)\
-		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG pr_fmt("%s: vbi:" fmt), \
+			__func__, ##arg); \
 	} while (0)
 
 /* ------------------------------------------------------------------ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-video.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-video.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23885-video.c	2016-12-11 17:47:40.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23885-video.c	2017-02-12 17:34:49.000000000 -0500
@@ -15,6 +15,9 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+#include "cx23885-video.h"
+
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -27,8 +30,6 @@
 #include <linux/kthread.h>
 #include <asm/div64.h>
 
-#include "cx23885.h"
-#include "cx23885-video.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-event.h>
@@ -66,7 +67,8 @@ MODULE_PARM_DESC(vid_limit, "capture mem
 
 #define dprintk(level, fmt, arg...)\
 	do { if (video_debug >= level)\
-		printk(KERN_DEBUG "%s: " fmt, dev->name, ## arg);\
+		printk(KERN_DEBUG pr_fmt("%s: video:" fmt), \
+			__func__, ##arg); \
 	} while (0)
 
 /* ------------------------------------------------------------------- */
@@ -194,7 +196,7 @@ u8 cx23885_flatiron_read(struct cx23885_
 
 	ret = i2c_transfer(&dev->i2c_bus[2].i2c_adap, &msg[0], 2);
 	if (ret != 2)
-		printk(KERN_ERR "%s() error\n", __func__);
+		pr_err("%s() error\n", __func__);
 
 	return b1[0];
 }
@@ -811,7 +813,6 @@ static int vidioc_log_status(struct file
 static int cx23885_query_audinput(struct file *file, void *priv,
 	struct v4l2_audio *i)
 {
-	struct cx23885_dev *dev = video_drvdata(file);
 	static const char *iname[] = {
 		[0] = "Baseband L/R 1",
 		[1] = "Baseband L/R 2",
@@ -1000,7 +1001,7 @@ static int cx23885_set_freq_via_ops(stru
 		fe->ops.tuner_ops.set_analog_params(fe, &params);
 	}
 	else
-		printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
+		pr_err("%s() No analog tuner, aborting\n", __func__);
 
 	/* When changing channels it is required to reset TVAUDIO */
 	msleep(100);
@@ -1058,15 +1059,14 @@ int cx23885_video_irq(struct cx23885_dev
 		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",
+			pr_warn("%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",
+			dprintk(7, " (VID_BC_MSK_SYNC 0x%08x) video lines miss-match\n",
 				VID_BC_MSK_SYNC);
 
 		if (status & VID_BC_MSK_OF)
@@ -1297,11 +1297,11 @@ int cx23885_video_register(struct cx2388
 	err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
 				    video_nr[dev->nr]);
 	if (err < 0) {
-		printk(KERN_INFO "%s: can't register video device\n",
+		pr_info("%s: can't register video device\n",
 			dev->name);
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s: registered device %s [v4l2]\n",
+	pr_info("%s: registered device %s [v4l2]\n",
 	       dev->name, video_device_node_name(dev->video_dev));
 
 	/* register VBI device */
@@ -1311,11 +1311,11 @@ int cx23885_video_register(struct cx2388
 	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",
+		pr_info("%s: can't register vbi device\n",
 			dev->name);
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s: registered device %s\n",
+	pr_info("%s: registered device %s\n",
 	       dev->name, video_device_node_name(dev->vbi_dev));
 
 	/* Register ALSA audio device */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23888-ir.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23888-ir.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/cx23888-ir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/cx23888-ir.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,15 +16,15 @@
  *  GNU General Public License for more details.
  */
 
+#include "cx23885.h"
+#include "cx23888-ir.h"
+
 #include <linux/kfifo.h>
 #include <linux/slab.h>
 
 #include <media/v4l2-device.h>
 #include <media/rc-core.h>
 
-#include "cx23885.h"
-#include "cx23888-ir.h"
-
 static unsigned int ir_888_debug;
 module_param(ir_888_debug, int, 0644);
 MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]");
@@ -1015,8 +1015,8 @@ static int cx23888_ir_log_status(struct
 			j = 0;
 			break;
 		}
-		v4l2_info(sd, "\tNext carrier edge window:          16 clocks "
-			  "-%1d/+%1d, %u to %u Hz\n", i, j,
+		v4l2_info(sd, "\tNext carrier edge window:	    16 clocks -%1d/+%1d, %u to %u Hz\n",
+			  i, j,
 			  clock_divider_to_freq(rxclk, 16 + j),
 			  clock_divider_to_freq(rxclk, 16 - i));
 	}
@@ -1026,8 +1026,7 @@ static int cx23888_ir_log_status(struct
 	v4l2_info(sd, "\tLow pass filter:                   %s\n",
 		  filtr ? "enabled" : "disabled");
 	if (filtr)
-		v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, "
-			  "%u ns\n",
+		v4l2_info(sd, "\tMin acceptable pulse width (LPF):  %u us, %u ns\n",
 			  lpf_count_to_us(filtr),
 			  lpf_count_to_ns(filtr));
 	v4l2_info(sd, "\tPulse width timer timed-out:       %s\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/netup-eeprom.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/netup-eeprom.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/netup-eeprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/netup-eeprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,7 +52,7 @@ int netup_eeprom_read(struct i2c_adapter
 	ret = i2c_transfer(i2c_adap, msg, 2);
 
 	if (ret != 2) {
-		printk(KERN_ERR "eeprom i2c read error, status=%d\n", ret);
+		pr_err("eeprom i2c read error, status=%d\n", ret);
 		return -1;
 	}
 
@@ -80,7 +80,7 @@ int netup_eeprom_write(struct i2c_adapte
 	ret = i2c_transfer(i2c_adap, msg, 1);
 
 	if (ret != 1) {
-		printk(KERN_ERR "eeprom i2c write error, status=%d\n", ret);
+		pr_err("eeprom i2c write error, status=%d\n", ret);
 		return -1;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx23885/netup-init.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/netup-init.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx23885/netup-init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx23885/netup-init.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@ static void i2c_av_write(struct i2c_adap
 	ret = i2c_transfer(i2c, &msg, 1);
 
 	if (ret != 1)
-		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+		pr_err("%s: i2c write error!\n", __func__);
 }
 
 static void i2c_av_write4(struct i2c_adapter *i2c, u16 reg, u32 val)
@@ -64,7 +64,7 @@ static void i2c_av_write4(struct i2c_ada
 	ret = i2c_transfer(i2c, &msg, 1);
 
 	if (ret != 1)
-		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+		pr_err("%s: i2c write error!\n", __func__);
 }
 
 static u8 i2c_av_read(struct i2c_adapter *i2c, u16 reg)
@@ -84,7 +84,7 @@ static u8 i2c_av_read(struct i2c_adapter
 	ret = i2c_transfer(i2c, &msg, 1);
 
 	if (ret != 1)
-		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+		pr_err("%s: i2c write error!\n", __func__);
 
 	msg.flags = I2C_M_RD;
 	msg.len = 1;
@@ -92,7 +92,7 @@ static u8 i2c_av_read(struct i2c_adapter
 	ret = i2c_transfer(i2c, &msg, 1);
 
 	if (ret != 1)
-		printk(KERN_ERR "%s: i2c read error!\n", __func__);
+		pr_err("%s: i2c read error!\n", __func__);
 
 	return buf[0];
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-alsa.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-alsa.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-alsa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-alsa.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,4 @@
 /*
- *
  *  Support for audio capture
  *  PCI function #1 of the cx2388x.
  *
@@ -18,14 +17,14 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 "cx88.h"
+#include "cx88-reg.h"
+
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/vmalloc.h>
@@ -33,7 +32,6 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 
-#include <asm/delay.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
@@ -42,22 +40,15 @@
 #include <sound/tlv.h>
 #include <media/i2c/wm8775.h>
 
-#include "cx88.h"
-#include "cx88-reg.h"
-
 #define dprintk(level, fmt, arg...) do {				\
 	if (debug + 1 > level)						\
-		printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg);\
-} while(0)
-
-#define dprintk_core(level, fmt, arg...) do {				\
-	if (debug + 1 > level)						\
-		printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg);\
-} while(0)
+		printk(KERN_DEBUG pr_fmt("%s: alsa: " fmt),		\
+			chip->core->name, ##arg);			\
+} while (0)
 
-/****************************************************************************
-	Data type declarations - Can be moded to a header file later
- ****************************************************************************/
+/*
+ * Data type declarations - Can be moded to a header file later
+ */
 
 struct cx88_audio_buffer {
 	unsigned int               bpl;
@@ -91,13 +82,10 @@ struct cx88_audio_dev {
 
 	struct snd_pcm_substream   *substream;
 };
-typedef struct cx88_audio_dev snd_cx88_card_t;
-
-
 
-/****************************************************************************
-			Module global static vars
- ****************************************************************************/
+/*
+ * Module global static vars
+ */
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -109,10 +97,9 @@ MODULE_PARM_DESC(enable, "Enable cx88x s
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
 
-
-/****************************************************************************
-				Module macros
- ****************************************************************************/
+/*
+ * Module macros
+ */
 
 MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Ricardo Cerqueira");
@@ -120,25 +107,23 @@ MODULE_AUTHOR("Mauro Carvalho Chehab <mc
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CX88_VERSION);
 
-MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
-			"{{Conexant,23882},"
-			"{{Conexant,23883}");
+MODULE_SUPPORTED_DEVICE("{{Conexant,23881},{{Conexant,23882},{{Conexant,23883}");
 static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages");
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
 
-/****************************************************************************
-			Module specific funtions
- ****************************************************************************/
+/*
+ * Module specific functions
+ */
 
 /*
  * BOARD Specific: Sets audio DMA
  */
 
-static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_start_audio_dma(struct cx88_audio_dev *chip)
 {
 	struct cx88_audio_buffer *buf = chip->buf;
-	struct cx88_core *core=chip->core;
+	struct cx88_core *core = chip->core;
 	const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
 
 	/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
@@ -154,8 +139,9 @@ static int _cx88_start_audio_dma(snd_cx8
 	cx_write(MO_AUDD_GPCNTRL, 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 + 8)>>1,
+	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 + 8) >> 1,
 		chip->num_periods, buf->bpl * chip->num_periods);
 
 	/* Enables corresponding bits at AUD_INT_STAT */
@@ -169,8 +155,11 @@ static int _cx88_start_audio_dma(snd_cx8
 	cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT);
 
 	/* start dma */
-	cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */
-	cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */
+
+	/* Enables Risc Processor */
+	cx_set(MO_DEV_CNTRL2, (1 << 5));
+	/* audio downstream FIFO and RISC enable */
+	cx_set(MO_AUD_DMACNTRL, 0x11);
 
 	if (debug)
 		cx88_sram_channel_dump(chip->core, audio_ch);
@@ -181,9 +170,10 @@ static int _cx88_start_audio_dma(snd_cx8
 /*
  * BOARD Specific: Resets audio DMA
  */
-static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
+static int _cx88_stop_audio_dma(struct cx88_audio_dev *chip)
 {
-	struct cx88_core *core=chip->core;
+	struct cx88_core *core = chip->core;
+
 	dprintk(1, "Stopping audio DMA\n");
 
 	/* stop dma */
@@ -195,7 +185,8 @@ static int _cx88_stop_audio_dma(snd_cx88
 				AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
 
 	if (debug)
-		cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]);
+		cx88_sram_channel_dump(chip->core,
+				       &cx88_sram_channels[SRAM_CH25]);
 
 	return 0;
 }
@@ -221,7 +212,7 @@ static const char *cx88_aud_irqs[32] = {
 /*
  * BOARD Specific: Threats IRQ audio specific calls
  */
-static void cx8801_aud_irq(snd_cx88_card_t *chip)
+static void cx8801_aud_irq(struct cx88_audio_dev *chip)
 {
 	struct cx88_core *core = chip->core;
 	u32 status, mask;
@@ -232,12 +223,12 @@ static void cx8801_aud_irq(snd_cx88_card
 		return;
 	cx_write(MO_AUD_INTSTAT, status);
 	if (debug > 1  ||  (status & mask & ~0xff))
-		cx88_print_irqbits(core->name, "irq aud",
+		cx88_print_irqbits("irq aud",
 				   cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs),
 				   status, mask);
 	/* risc op code error */
 	if (status & AUD_INT_OPC_ERR) {
-		printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name);
+		pr_warn("Audio risc op code error\n");
 		cx_clear(MO_AUD_DMACNTRL, 0x11);
 		cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
 	}
@@ -259,7 +250,7 @@ static void cx8801_aud_irq(snd_cx88_card
  */
 static irqreturn_t cx8801_irq(int irq, void *dev_id)
 {
-	snd_cx88_card_t *chip = dev_id;
+	struct cx88_audio_dev *chip = dev_id;
 	struct cx88_core *core = chip->core;
 	u32 status;
 	int loop, handled = 0;
@@ -267,7 +258,7 @@ static irqreturn_t cx8801_irq(int irq, v
 	for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
 		status = cx_read(MO_PCI_INTSTAT) &
 			(core->pci_irqmask | PCI_INT_AUDINT);
-		if (0 == status)
+		if (status == 0)
 			goto out;
 		dprintk(3, "cx8801_irq loop %d/%d, status %x\n",
 			loop, MAX_IRQ_LOOP, status);
@@ -280,10 +271,8 @@ static irqreturn_t cx8801_irq(int irq, v
 			cx8801_aud_irq(chip);
 	}
 
-	if (MAX_IRQ_LOOP == loop) {
-		printk(KERN_ERR
-		       "%s/1: IRQ loop detected, disabling interrupts\n",
-		       core->name);
+	if (loop == MAX_IRQ_LOOP) {
+		pr_err("IRQ loop detected, disabling interrupts\n");
 		cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
 	}
 
@@ -298,26 +287,25 @@ static int cx88_alsa_dma_init(struct cx8
 	int i;
 
 	buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
-	if (NULL == buf->vaddr) {
+	if (!buf->vaddr) {
 		dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
 		return -ENOMEM;
 	}
 
 	dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
-				(unsigned long)buf->vaddr,
-				nr_pages << PAGE_SHIFT);
+		(unsigned long)buf->vaddr, nr_pages << PAGE_SHIFT);
 
 	memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
 	buf->nr_pages = nr_pages;
 
 	buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
-	if (NULL == buf->sglist)
+	if (!buf->sglist)
 		goto vzalloc_err;
 
 	sg_init_table(buf->sglist, buf->nr_pages);
 	for (i = 0; i < buf->nr_pages; i++) {
 		pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
-		if (NULL == pg)
+		if (!pg)
 			goto vmalloc_to_page_err;
 		sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
 	}
@@ -339,7 +327,7 @@ static int cx88_alsa_dma_map(struct cx88
 	buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
 			buf->nr_pages, PCI_DMA_FROMDEVICE);
 
-	if (0 == buf->sglen) {
+	if (buf->sglen == 0) {
 		pr_warn("%s: cx88_alsa_map_sg failed\n", __func__);
 		return -ENOMEM;
 	}
@@ -353,7 +341,8 @@ static int cx88_alsa_dma_unmap(struct cx
 	if (!buf->sglen)
 		return 0;
 
-	dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE);
+	dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen,
+		     PCI_DMA_FROMDEVICE);
 	buf->sglen = 0;
 	return 0;
 }
@@ -367,18 +356,18 @@ static int cx88_alsa_dma_free(struct cx8
 	return 0;
 }
 
-
-static int dsp_buffer_free(snd_cx88_card_t *chip)
+static int dsp_buffer_free(struct cx88_audio_dev *chip)
 {
 	struct cx88_riscmem *risc = &chip->buf->risc;
 
-	BUG_ON(!chip->dma_size);
+	WARN_ON(!chip->dma_size);
 
-	dprintk(2,"Freeing buffer\n");
+	dprintk(2, "Freeing buffer\n");
 	cx88_alsa_dma_unmap(chip);
 	cx88_alsa_dma_free(chip->buf);
 	if (risc->cpu)
-		pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma);
+		pci_free_consistent(chip->pci, risc->size,
+				    risc->cpu, risc->dma);
 	kfree(chip->buf);
 
 	chip->buf = NULL;
@@ -386,9 +375,9 @@ static int dsp_buffer_free(snd_cx88_card
 	return 0;
 }
 
-/****************************************************************************
-				ALSA PCM Interface
- ****************************************************************************/
+/*
+ * ALSA PCM Interface
+ */
 
 /*
  * Digital hardware definition
@@ -406,13 +395,15 @@ static const struct snd_pcm_hardware snd
 	.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,
+	/*
+	 * 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),
+	.buffer_bytes_max = (1024 * 1024),
 };
 
 /*
@@ -420,17 +411,17 @@ static const struct snd_pcm_hardware snd
  */
 static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
 {
-	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	int err;
 
 	if (!chip) {
-		printk(KERN_ERR "BUG: cx88 can't find device struct."
-				" Can't proceed with open\n");
+		pr_err("BUG: cx88 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);
+	err = snd_pcm_hw_constraint_pow2(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_PERIODS);
 	if (err < 0)
 		goto _error;
 
@@ -440,6 +431,7 @@ static int snd_cx88_pcm_open(struct snd_
 
 	if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) {
 		unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
+
 		bpl &= ~7; /* must be multiple of 8 */
 		runtime->hw.period_bytes_min = bpl;
 		runtime->hw.period_bytes_max = bpl;
@@ -447,7 +439,7 @@ static int snd_cx88_pcm_open(struct snd_
 
 	return 0;
 _error:
-	dprintk(1,"Error opening PCM!\n");
+	dprintk(1, "Error opening PCM!\n");
 	return err;
 }
 
@@ -462,10 +454,10 @@ static int snd_cx88_close(struct snd_pcm
 /*
  * hw_params callback
  */
-static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
-			      struct snd_pcm_hw_params * hw_params)
+static int snd_cx88_hw_params(struct snd_pcm_substream *substream,
+			      struct snd_pcm_hw_params *hw_params)
 {
-	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream);
 
 	struct cx88_audio_buffer *buf;
 	int ret;
@@ -479,18 +471,18 @@ static int snd_cx88_hw_params(struct snd
 	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));
+	WARN_ON(!chip->dma_size);
+	WARN_ON(chip->num_periods & (chip->num_periods - 1));
 
 	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
-	if (NULL == buf)
+	if (!buf)
 		return -ENOMEM;
 
 	chip->buf = buf;
 	buf->bpl = chip->period_size;
 
 	ret = cx88_alsa_dma_init(chip,
-			(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
+				 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
 	if (ret < 0)
 		goto error;
 
@@ -504,7 +496,7 @@ static int snd_cx88_hw_params(struct snd
 		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[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
 	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
 
 	substream->runtime->dma_area = chip->buf->vaddr;
@@ -520,10 +512,9 @@ error:
 /*
  * hw free callback
  */
-static int snd_cx88_hw_free(struct snd_pcm_substream * substream)
+static int snd_cx88_hw_free(struct snd_pcm_substream *substream)
 {
-
-	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream);
 
 	if (substream->runtime->dma_area) {
 		dsp_buffer_free(chip);
@@ -546,7 +537,7 @@ static int snd_cx88_prepare(struct snd_p
  */
 static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream);
 	int err;
 
 	/* Local interrupts are already disabled by ALSA */
@@ -554,13 +545,13 @@ static int snd_cx88_card_trigger(struct
 
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		err=_cx88_start_audio_dma(chip);
+		err = _cx88_start_audio_dma(chip);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		err=_cx88_stop_audio_dma(chip);
+		err = _cx88_stop_audio_dma(chip);
 		break;
 	default:
-		err=-EINVAL;
+		err =  -EINVAL;
 		break;
 	}
 
@@ -574,7 +565,7 @@ static int snd_cx88_card_trigger(struct
  */
 static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
 {
-	snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+	struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	u16 count;
 
@@ -583,16 +574,17 @@ static snd_pcm_uframes_t snd_cx88_pointe
 //	dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__,
 //		count, new, count & (runtime->periods-1),
 //		runtime->period_size * (count & (runtime->periods-1)));
-	return runtime->period_size * (count & (runtime->periods-1));
+	return runtime->period_size * (count & (runtime->periods - 1));
 }
 
 /*
  * page callback (needed for mmap)
  */
 static struct page *snd_cx88_page(struct snd_pcm_substream *substream,
-				unsigned long offset)
+				  unsigned long offset)
 {
 	void *pageptr = substream->runtime->dma_area + offset;
+
 	return vmalloc_to_page(pageptr);
 }
 
@@ -614,7 +606,8 @@ static const struct snd_pcm_ops snd_cx88
 /*
  * create a PCM device
  */
-static int snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name)
+static int snd_cx88_pcm(struct cx88_audio_dev *chip, int device,
+			const char *name)
 {
 	int err;
 	struct snd_pcm *pcm;
@@ -629,9 +622,9 @@ static int snd_cx88_pcm(snd_cx88_card_t
 	return 0;
 }
 
-/****************************************************************************
-				CONTROL INTERFACE
- ****************************************************************************/
+/*
+ * CONTROL INTERFACE
+ */
 static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_info *info)
 {
@@ -646,8 +639,8 @@ static int snd_cx88_volume_info(struct s
 static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *value)
 {
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-	struct cx88_core *core=chip->core;
+	struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
 	int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f),
 	    bal = cx_read(AUD_BAL_CTL);
 
@@ -659,9 +652,9 @@ static int snd_cx88_volume_get(struct sn
 }
 
 static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *value)
+				       struct snd_ctl_elem_value *value)
 {
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol);
 	struct cx88_core *core = chip->core;
 	int left = value->value.integer.value[0];
 	int right = value->value.integer.value[1];
@@ -683,8 +676,8 @@ static void snd_cx88_wm8775_volume_put(s
 static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *value)
 {
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-	struct cx88_core *core=chip->core;
+	struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
 	int left, right, v, b;
 	int changed = 0;
 	u32 old;
@@ -733,7 +726,7 @@ static const struct snd_kcontrol_new snd
 static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *value)
 {
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol);
 	struct cx88_core *core = chip->core;
 	u32 bit = kcontrol->private_value;
 
@@ -742,9 +735,9 @@ static int snd_cx88_switch_get(struct sn
 }
 
 static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *value)
+			       struct snd_ctl_elem_value *value)
 {
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol);
 	struct cx88_core *core = chip->core;
 	u32 bit = kcontrol->private_value;
 	int ret = 0;
@@ -756,8 +749,9 @@ static int snd_cx88_switch_put(struct sn
 		vol ^= bit;
 		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
 		/* Pass mute onto any WM8775 */
-		if (core->sd_wm8775 && ((1<<6) == bit))
-			wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
+		if (core->sd_wm8775 && ((1 << 6) == bit))
+			wm8775_s_ctrl(core,
+				      V4L2_CID_AUDIO_MUTE, 0 != (vol & bit));
 		ret = 1;
 	}
 	spin_unlock_irq(&chip->reg_lock);
@@ -770,7 +764,7 @@ static const struct snd_kcontrol_new snd
 	.info = snd_ctl_boolean_mono_info,
 	.get = snd_cx88_switch_get,
 	.put = snd_cx88_switch_put,
-	.private_value = (1<<8),
+	.private_value = (1 << 8),
 };
 
 static const struct snd_kcontrol_new snd_cx88_source_switch = {
@@ -779,13 +773,13 @@ static const struct snd_kcontrol_new snd
 	.info = snd_ctl_boolean_mono_info,
 	.get = snd_cx88_switch_get,
 	.put = snd_cx88_switch_put,
-	.private_value = (1<<6),
+	.private_value = (1 << 6),
 };
 
 static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
-			       struct snd_ctl_elem_value *value)
+			    struct snd_ctl_elem_value *value)
 {
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol);
 	struct cx88_core *core = chip->core;
 	s32 val;
 
@@ -795,9 +789,9 @@ static int snd_cx88_alc_get(struct snd_k
 }
 
 static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *value)
+			    struct snd_ctl_elem_value *value)
 {
-	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol);
 	struct cx88_core *core = chip->core;
 
 	wm8775_s_ctrl(core, V4L2_CID_AUDIO_LOUDNESS,
@@ -813,9 +807,9 @@ static struct snd_kcontrol_new snd_cx88_
 	.put = snd_cx88_alc_put,
 };
 
-/****************************************************************************
-			Basic Flow for Sound Devices
- ****************************************************************************/
+/*
+ * Basic Flow for Sound Devices
+ */
 
 /*
  * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio
@@ -823,8 +817,8 @@ static struct snd_kcontrol_new snd_cx88_
  */
 
 static const struct pci_device_id cx88_audio_pci_tbl[] = {
-	{0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
-	{0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+	{0x14f1, 0x8801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x14f1, 0x8811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0, }
 };
 MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl);
@@ -833,13 +827,12 @@ MODULE_DEVICE_TABLE(pci, cx88_audio_pci_
  * Chip-specific destructor
  */
 
-static int snd_cx88_free(snd_cx88_card_t *chip)
+static int snd_cx88_free(struct cx88_audio_dev *chip)
 {
-
 	if (chip->irq >= 0)
 		free_irq(chip->irq, chip);
 
-	cx88_core_put(chip->core,chip->pci);
+	cx88_core_put(chip->core, chip->pci);
 
 	pci_disable_device(chip->pci);
 	return 0;
@@ -848,27 +841,26 @@ static int snd_cx88_free(snd_cx88_card_t
 /*
  * Component Destructor
  */
-static void snd_cx88_dev_free(struct snd_card * card)
+static void snd_cx88_dev_free(struct snd_card *card)
 {
-	snd_cx88_card_t *chip = card->private_data;
+	struct cx88_audio_dev *chip = card->private_data;
 
 	snd_cx88_free(chip);
 }
 
-
 /*
  * Alsa Constructor - Component probe
  */
 
 static int devno;
 static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci,
-			   snd_cx88_card_t **rchip,
+			   struct cx88_audio_dev **rchip,
 			   struct cx88_core **core_ptr)
 {
-	snd_cx88_card_t   *chip;
-	struct cx88_core  *core;
-	int               err;
-	unsigned char     pci_lat;
+	struct cx88_audio_dev	*chip;
+	struct cx88_core	*core;
+	int			err;
+	unsigned char		pci_lat;
 
 	*rchip = NULL;
 
@@ -881,19 +873,18 @@ static int snd_cx88_create(struct snd_ca
 	chip = card->private_data;
 
 	core = cx88_core_get(pci);
-	if (NULL == core) {
+	if (!core) {
 		err = -EINVAL;
 		return err;
 	}
 
-	err = pci_set_dma_mask(pci,DMA_BIT_MASK(32));
+	err = pci_set_dma_mask(pci, DMA_BIT_MASK(32));
 	if (err) {
-		dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
+		dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n", core->name);
 		cx88_core_put(core, pci);
 		return err;
 	}
 
-
 	/* pci init */
 	chip->card = card;
 	chip->pci = pci;
@@ -907,17 +898,18 @@ static int snd_cx88_create(struct snd_ca
 			  IRQF_SHARED, chip->core->name, chip);
 	if (err < 0) {
 		dprintk(0, "%s: can't get IRQ %d\n",
-		       chip->core->name, chip->pci->irq);
+			chip->core->name, chip->pci->irq);
 		return err;
 	}
 
 	/* print pci info */
 	pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat);
 
-	dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, "
-	       "latency: %d, mmio: 0x%llx\n", core->name, devno,
-	       pci_name(pci), pci->revision, pci->irq,
-	       pci_lat, (unsigned long long)pci_resource_start(pci,0));
+	dprintk(1,
+		"ALSA %s/%i: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
+		core->name, devno,
+		pci_name(pci), pci->revision, pci->irq,
+		pci_lat, (unsigned long long)pci_resource_start(pci, 0));
 
 	chip->irq = pci->irq;
 	synchronize_irq(chip->irq);
@@ -931,10 +923,10 @@ static int snd_cx88_create(struct snd_ca
 static int cx88_audio_initdev(struct pci_dev *pci,
 			      const struct pci_device_id *pci_id)
 {
-	struct snd_card  *card;
-	snd_cx88_card_t  *chip;
-	struct cx88_core *core = NULL;
-	int              err;
+	struct snd_card		*card;
+	struct cx88_audio_dev	*chip;
+	struct cx88_core	*core = NULL;
+	int			err;
 
 	if (devno >= SNDRV_CARDS)
 		return (-ENODEV);
@@ -945,7 +937,7 @@ static int cx88_audio_initdev(struct pci
 	}
 
 	err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE,
-			   sizeof(snd_cx88_card_t), &card);
+			   sizeof(struct cx88_audio_dev), &card);
 	if (err < 0)
 		return err;
 
@@ -973,19 +965,20 @@ static int cx88_audio_initdev(struct pci
 	if (core->sd_wm8775)
 		snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
 
-	strcpy (card->driver, "CX88x");
+	strcpy(card->driver, "CX88x");
 	sprintf(card->shortname, "Conexant CX%x", pci->device);
 	sprintf(card->longname, "%s at %#llx",
-		card->shortname,(unsigned long long)pci_resource_start(pci, 0));
-	strcpy (card->mixername, "CX88");
+		card->shortname,
+		(unsigned long long)pci_resource_start(pci, 0));
+	strcpy(card->mixername, "CX88");
 
-	dprintk (0, "%s/%i: ALSA support for cx2388x boards\n",
-	       card->driver,devno);
+	dprintk(0, "%s/%i: ALSA support for cx2388x boards\n",
+		card->driver, devno);
 
 	err = snd_card_register(card);
 	if (err < 0)
 		goto error;
-	pci_set_drvdata(pci,card);
+	pci_set_drvdata(pci, card);
 
 	devno++;
 	return 0;
@@ -994,6 +987,7 @@ error:
 	snd_card_free(card);
 	return err;
 }
+
 /*
  * ALSA destructor
  */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-blackbird.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-blackbird.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-blackbird.c	2016-12-11 17:47:42.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-blackbird.c	2017-02-12 17:34:59.000000000 -0500
@@ -1,5 +1,4 @@
 /*
- *
  *  Support for a cx23416 mpeg encoder via cx2388x host port.
  *  "blackbird" reference design.
  *
@@ -20,12 +19,10 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 "cx88.h"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -38,21 +35,20 @@
 #include <media/v4l2-event.h>
 #include <media/drv-intf/cx2341x.h>
 
-#include "cx88.h"
-
 MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
 MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(CX88_VERSION);
 
 static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [blackbird]");
 
-#define dprintk(level, fmt, arg...) do {				      \
-	if (debug + 1 > level)						      \
-		printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg); \
-} while(0)
+#define dprintk(level, fmt, arg...) do {				\
+	if (debug + 1 > level)						\
+		printk(KERN_DEBUG pr_fmt("%s: blackbird:" fmt),		\
+			__func__, ##arg);				\
+} while (0)
 
 /* ------------------------------------------------------------------ */
 
@@ -70,6 +66,7 @@ enum blackbird_capture_type {
 	BLACKBIRD_RAW_CAPTURE,
 	BLACKBIRD_RAW_PASSTHRU_CAPTURE
 };
+
 enum blackbird_capture_bits {
 	BLACKBIRD_RAW_BITS_NONE             = 0x00,
 	BLACKBIRD_RAW_BITS_YUV_CAPTURE      = 0x01,
@@ -78,33 +75,40 @@ enum blackbird_capture_bits {
 	BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
 	BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
 };
+
 enum blackbird_capture_end {
 	BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
 	BLACKBIRD_END_NOW, /* stop immediately, no irq */
 };
+
 enum blackbird_framerate {
 	BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
 	BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
 };
+
 enum blackbird_stream_port {
 	BLACKBIRD_OUTPUT_PORT_MEMORY,
 	BLACKBIRD_OUTPUT_PORT_STREAMING,
 	BLACKBIRD_OUTPUT_PORT_SERIAL
 };
+
 enum blackbird_data_xfer_status {
 	BLACKBIRD_MORE_BUFFERS_FOLLOW,
 	BLACKBIRD_LAST_BUFFER,
 };
+
 enum blackbird_picture_mask {
 	BLACKBIRD_PICTURE_MASK_NONE,
 	BLACKBIRD_PICTURE_MASK_I_FRAMES,
 	BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
 	BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
 };
+
 enum blackbird_vbi_mode_bits {
 	BLACKBIRD_VBI_BITS_SLICED,
 	BLACKBIRD_VBI_BITS_RAW,
 };
+
 enum blackbird_vbi_insertion_bits {
 	BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
 	BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
@@ -112,56 +116,69 @@ enum blackbird_vbi_insertion_bits {
 	BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
 	BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
 };
+
 enum blackbird_dma_unit {
 	BLACKBIRD_DMA_BYTES,
 	BLACKBIRD_DMA_FRAMES,
 };
+
 enum blackbird_dma_transfer_status_bits {
 	BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
 	BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
 	BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
 };
+
 enum blackbird_pause {
 	BLACKBIRD_PAUSE_ENCODING,
 	BLACKBIRD_RESUME_ENCODING,
 };
+
 enum blackbird_copyright {
 	BLACKBIRD_COPYRIGHT_OFF,
 	BLACKBIRD_COPYRIGHT_ON,
 };
+
 enum blackbird_notification_type {
 	BLACKBIRD_NOTIFICATION_REFRESH,
 };
+
 enum blackbird_notification_status {
 	BLACKBIRD_NOTIFICATION_OFF,
 	BLACKBIRD_NOTIFICATION_ON,
 };
+
 enum blackbird_notification_mailbox {
 	BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
 };
+
 enum blackbird_field1_lines {
 	BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
 	BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
 	BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
 };
+
 enum blackbird_field2_lines {
 	BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
 	BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
 	BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
 };
+
 enum blackbird_custom_data_type {
 	BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
 	BLACKBIRD_CUSTOM_PRIVATE_PACKET,
 };
+
 enum blackbird_mute {
 	BLACKBIRD_UNMUTE,
 	BLACKBIRD_MUTE,
 };
+
 enum blackbird_mute_video_mask {
 	BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
 	BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
 	BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
 };
+
 enum blackbird_mute_video_shift {
 	BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
 	BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
@@ -215,14 +232,14 @@ static void host_setup(struct cx88_core
 static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(1);
-	u32 gpio0,need;
+	u32 gpio0, need;
 
 	need = state ? 2 : 0;
 	for (;;) {
 		gpio0 = cx_read(MO_GP0_IO) & 2;
 		if (need == gpio0)
 			return 0;
-		if (time_after(jiffies,timeout))
+		if (time_after(jiffies, timeout))
 			return -1;
 		udelay(1);
 	}
@@ -241,7 +258,7 @@ static int memory_write(struct cx88_core
 	cx_read(P1_MDATA0);
 	cx_read(P1_MADDR0);
 
-	return wait_ready_gpio0_bit1(core,1);
+	return wait_ready_gpio0_bit1(core, 1);
 }
 
 static int memory_read(struct cx88_core *core, u32 address, u32 *value)
@@ -255,7 +272,7 @@ static int memory_read(struct cx88_core
 	cx_writeb(P1_MADDR0, (unsigned int)address);
 	cx_read(P1_MADDR0);
 
-	retval = wait_ready_gpio0_bit1(core,1);
+	retval = wait_ready_gpio0_bit1(core, 1);
 
 	cx_writeb(P1_MDATA3, 0);
 	val     = (unsigned char)cx_read(P1_MDATA3) << 24;
@@ -282,10 +299,9 @@ static int register_write(struct cx88_co
 	cx_read(P1_RDATA0);
 	cx_read(P1_RADDR0);
 
-	return wait_ready_gpio0_bit1(core,1);
+	return wait_ready_gpio0_bit1(core, 1);
 }
 
-
 static int register_read(struct cx88_core *core, u32 address, u32 *value)
 {
 	int retval;
@@ -296,7 +312,7 @@ static int register_read(struct cx88_cor
 	cx_writeb(P1_RRDWR, 0);
 	cx_read(P1_RADDR0);
 
-	retval  = wait_ready_gpio0_bit1(core,1);
+	retval  = wait_ready_gpio0_bit1(core, 1);
 	val     = (unsigned char)cx_read(P1_RDATA0);
 	val    |= (unsigned char)cx_read(P1_RDATA1) << 8;
 	val    |= (unsigned char)cx_read(P1_RDATA2) << 16;
@@ -308,20 +324,24 @@ static int register_read(struct cx88_cor
 
 /* ------------------------------------------------------------------ */
 
-static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
+static int blackbird_mbox_func(void *priv, u32 command, int in,
+			       int out, u32 data[CX2341X_MBOX_MAX_DATA])
 {
 	struct cx8802_dev *dev = priv;
 	unsigned long timeout;
 	u32 value, flag, retval;
 	int i;
 
-	dprintk(1,"%s: 0x%X\n", __func__, command);
+	dprintk(1, "%s: 0x%X\n", __func__, command);
 
-	/* this may not be 100% safe if we can't read any memory location
-	   without side effects */
+	/*
+	 * this may not be 100% safe if we can't read any memory location
+	 * without side effects
+	 */
 	memory_read(dev->core, dev->mailbox - 4, &value);
 	if (value != 0x12345678) {
-		dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
+		dprintk(0,
+			"Firmware and/or mailbox pointer not initialized or corrupted\n");
 		return -EIO;
 	}
 
@@ -336,7 +356,8 @@ static int blackbird_mbox_func(void *pri
 
 	/* write command + args + fill remaining with zeros */
 	memory_write(dev->core, dev->mailbox + 1, command); /* command code */
-	memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
+	/* timeout */
+	memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT);
 	for (i = 0; i < in; i++) {
 		memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
 		dprintk(1, "API Input %d = %d\n", i, data[i]);
@@ -353,7 +374,7 @@ static int blackbird_mbox_func(void *pri
 		memory_read(dev->core, dev->mailbox, &flag);
 		if (0 != (flag & 4))
 			break;
-		if (time_after(jiffies,timeout)) {
+		if (time_after(jiffies, timeout)) {
 			dprintk(0, "ERROR: API Mailbox timeout %x\n", command);
 			return -EIO;
 		}
@@ -367,15 +388,19 @@ static int blackbird_mbox_func(void *pri
 	}
 
 	memory_read(dev->core, dev->mailbox + 2, &retval);
-	dprintk(1, "API result = %d\n",retval);
+	dprintk(1, "API result = %d\n", retval);
 
 	flag = 0;
 	memory_write(dev->core, dev->mailbox, flag);
 	return retval;
 }
+
 /* ------------------------------------------------------------------ */
 
-/* We don't need to call the API often, so using just one mailbox will probably suffice */
+/*
+ * We don't need to call the API often, so using just one mailbox
+ * will probably suffice
+ */
 static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
 			     u32 inputcnt, u32 outputcnt, ...)
 {
@@ -385,9 +410,9 @@ static int blackbird_api_cmd(struct cx88
 
 	va_start(vargs, outputcnt);
 
-	for (i = 0; i < inputcnt; i++) {
+	for (i = 0; i < inputcnt; i++)
 		data[i] = va_arg(vargs, int);
-	}
+
 	err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data);
 	for (i = 0; i < outputcnt; i++) {
 		int *vptr = va_arg(vargs, int *);
@@ -399,8 +424,8 @@ static int blackbird_api_cmd(struct cx88
 
 static int blackbird_find_mailbox(struct cx8802_dev *dev)
 {
-	u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
-	int signaturecnt=0;
+	u32 signature[4] = {0x12345678, 0x34567812, 0x56781234, 0x78123456};
+	int signaturecnt = 0;
 	u32 value;
 	int i;
 
@@ -410,9 +435,9 @@ static int blackbird_find_mailbox(struct
 			signaturecnt++;
 		else
 			signaturecnt = 0;
-		if (4 == signaturecnt) {
+		if (signaturecnt == 4) {
 			dprintk(1, "Mailbox signature found\n");
-			return i+1;
+			return i + 1;
 		}
 	}
 	dprintk(0, "Mailbox signature values not found!\n");
@@ -431,10 +456,13 @@ static int blackbird_load_firmware(struc
 	__le32 *dataptr;
 
 	retval  = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
-	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
-	retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
-	retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
-	msleep(1);
+	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS,
+				 IVTV_CMD_HW_BLOCKS_RST);
+	retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH,
+				 0x80000640);
+	retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE,
+				 0x1A);
+	usleep_range(10000, 20000);
 	retval |= register_write(dev->core, IVTV_REG_APU, 0);
 
 	if (retval < 0)
@@ -443,29 +471,28 @@ static int blackbird_load_firmware(struc
 	retval = reject_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
 				  &dev->pci->dev);
 
-
 	if (retval != 0) {
 		pr_err("Hotplug firmware request failed (%s).\n",
-			CX2341X_FIRM_ENC_FILENAME);
+		       CX2341X_FIRM_ENC_FILENAME);
 		pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
 		return -EIO;
 	}
 
 	if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
 		pr_err("Firmware size mismatch (have %zd, expected %d)\n",
-			firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
+		       firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
 		release_firmware(firmware);
 		return -EINVAL;
 	}
 
-	if (0 != memcmp(firmware->data, magic, 8)) {
+	if (memcmp(firmware->data, magic, 8) != 0) {
 		pr_err("Firmware magic mismatch, wrong file?\n");
 		release_firmware(firmware);
 		return -EINVAL;
 	}
 
 	/* transfer to the chip */
-	dprintk(1,"Loading firmware ...\n");
+	dprintk(1, "Loading firmware ...\n");
 	dataptr = (__le32 *)firmware->data;
 	for (i = 0; i < (firmware->size >> 2); i++) {
 		value = le32_to_cpu(*dataptr);
@@ -486,10 +513,11 @@ static int blackbird_load_firmware(struc
 	}
 	dprintk(0, "Firmware upload successful.\n");
 
-	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+	retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS,
+				 IVTV_CMD_HW_BLOCKS_RST);
 	retval |= register_read(dev->core, IVTV_REG_SPU, &value);
 	retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
-	msleep(1);
+	usleep_range(10000, 20000);
 
 	retval |= register_read(dev->core, IVTV_REG_VPU, &value);
 	retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
@@ -499,19 +527,19 @@ static int blackbird_load_firmware(struc
 	return 0;
 }
 
-/**
- Settings used by the windows tv app for PVR2000:
-=================================================================================================================
-Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
------------------------------------------------------------------------------------------------------------------
-MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
-=================================================================================================================
-*DB: "DirectBurn"
-*/
+/*
+ * Settings used by the windows tv app for PVR2000:
+ * =================================================================================================================
+ * Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
+ * -----------------------------------------------------------------------------------------------------------------
+ * MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+ * MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+ * VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+ * DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+ * DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+ * =================================================================================================================
+ * [*] DB: "DirectBurn"
+ */
 
 static void blackbird_codec_settings(struct cx8802_dev *dev)
 {
@@ -519,11 +547,12 @@ static void blackbird_codec_settings(str
 
 	/* assign frame size */
 	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-				core->height, core->width);
+			  core->height, core->width);
 
 	dev->cxhdl.width = core->width;
 	dev->cxhdl.height = core->height;
-	cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
+	cx2341x_handler_set_50hz(&dev->cxhdl,
+				 dev->core->tvnorm & V4L2_STD_625_50);
 	cx2341x_handler_setup(&dev->cxhdl);
 }
 
@@ -533,7 +562,7 @@ static int blackbird_initialize_codec(st
 	int version;
 	int retval;
 
-	dprintk(1,"Initialize codec\n");
+	dprintk(1, "Initialize codec\n");
 	retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
 	if (retval < 0) {
 		/* ping was not successful, reset and upload firmware */
@@ -549,15 +578,18 @@ static int blackbird_initialize_codec(st
 
 		dev->mailbox = retval;
 
-		retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+		/* ping */
+		retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
 		if (retval < 0) {
 			dprintk(0, "ERROR: Firmware ping failed!\n");
 			return -1;
 		}
 
-		retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
+		retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION,
+					   0, 1, &version);
 		if (retval < 0) {
-			dprintk(0, "ERROR: Firmware get encoder version failed!\n");
+			dprintk(0,
+				"ERROR: Firmware get encoder version failed!\n");
 			return -1;
 		}
 		dprintk(0, "Firmware version is 0x%08x\n", version);
@@ -571,13 +603,11 @@ static int blackbird_initialize_codec(st
 	blackbird_codec_settings(dev);
 
 	blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
-			BLACKBIRD_FIELD1_SAA7115,
-			BLACKBIRD_FIELD2_SAA7115
-		);
+			  BLACKBIRD_FIELD1_SAA7115, BLACKBIRD_FIELD2_SAA7115);
 
 	blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
-			BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
-			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+			  BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
+			  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
 	return 0;
 }
@@ -615,9 +645,7 @@ static int blackbird_start_codec(struct
 
 	/* start capturing to the host interface */
 	blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
-			BLACKBIRD_MPEG_CAPTURE,
-			BLACKBIRD_RAW_BITS_NONE
-		);
+			  BLACKBIRD_MPEG_CAPTURE, BLACKBIRD_RAW_BITS_NONE);
 
 	return 0;
 }
@@ -625,10 +653,9 @@ static int blackbird_start_codec(struct
 static int blackbird_stop_codec(struct cx8802_dev *dev)
 {
 	blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-			BLACKBIRD_END_NOW,
-			BLACKBIRD_MPEG_CAPTURE,
-			BLACKBIRD_RAW_BITS_NONE
-		);
+			  BLACKBIRD_END_NOW,
+			  BLACKBIRD_MPEG_CAPTURE,
+			  BLACKBIRD_RAW_BITS_NONE);
 
 	cx2341x_handler_set_busy(&dev->cxhdl, 0);
 
@@ -638,8 +665,8 @@ static int blackbird_stop_codec(struct c
 /* ------------------------------------------------------------------ */
 
 static int queue_setup(struct vb2_queue *q,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], struct device *alloc_devs[])
+		       unsigned int *num_buffers, unsigned int *num_planes,
+		       unsigned int sizes[], struct device *alloc_devs[])
 {
 	struct cx8802_dev *dev = q->drv_priv;
 
@@ -699,7 +726,8 @@ static int start_streaming(struct vb2_qu
 
 	err = drv->request_acquire(drv);
 	if (err != 0) {
-		dprintk(1, "%s: Unable to acquire hardware, %d\n", __func__, err);
+		dprintk(1, "%s: Unable to acquire hardware, %d\n", __func__,
+			err);
 		goto fail;
 	}
 
@@ -770,7 +798,7 @@ static const struct vb2_ops blackbird_qo
 /* ------------------------------------------------------------------ */
 
 static int vidioc_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *cap)
+			   struct v4l2_capability *cap)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -781,8 +809,8 @@ static int vidioc_querycap(struct file *
 	return 0;
 }
 
-static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
-					struct v4l2_fmtdesc *f)
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+				   struct v4l2_fmtdesc *f)
 {
 	if (f->index != 0)
 		return -EINVAL;
@@ -794,7 +822,7 @@ static int vidioc_enum_fmt_vid_cap (stru
 }
 
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-					struct v4l2_format *f)
+				struct v4l2_format *f)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -810,11 +838,11 @@ static int vidioc_g_fmt_vid_cap(struct f
 }
 
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-			struct v4l2_format *f)
+				  struct v4l2_format *f)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
-	unsigned maxw, maxh;
+	unsigned int maxw, maxh;
 	enum v4l2_field field;
 
 	f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
@@ -850,7 +878,7 @@ static int vidioc_try_fmt_vid_cap(struct
 }
 
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-					struct v4l2_format *f)
+				struct v4l2_format *f)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core  *core = dev->core;
@@ -864,20 +892,21 @@ static int vidioc_s_fmt_vid_cap(struct f
 	core->width = f->fmt.pix.width;
 	core->height = f->fmt.pix.height;
 	core->field = f->fmt.pix.field;
-	cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
+	cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height,
+		       f->fmt.pix.field);
 	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-				f->fmt.pix.height, f->fmt.pix.width);
+			  f->fmt.pix.height, f->fmt.pix.width);
 	return 0;
 }
 
-static int vidioc_s_frequency (struct file *file, void *priv,
-				const struct v4l2_frequency *f)
+static int vidioc_s_frequency(struct file *file, void *priv,
+			      const struct v4l2_frequency *f)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 	bool streaming;
 
-	if (unlikely(UNSET == core->board.tuner_type))
+	if (unlikely(core->board.tuner_type == UNSET))
 		return -EINVAL;
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
@@ -885,16 +914,15 @@ static int vidioc_s_frequency (struct fi
 	if (streaming)
 		blackbird_stop_codec(dev);
 
-	cx88_set_freq (core,f);
+	cx88_set_freq(core, f);
 	blackbird_initialize_codec(dev);
-	cx88_set_scale(core, core->width, core->height,
-			core->field);
+	cx88_set_scale(core, core->width, core->height, core->field);
 	if (streaming)
 		blackbird_start_codec(dev);
 	return 0;
 }
 
-static int vidioc_log_status (struct file *file, void *priv)
+static int vidioc_log_status(struct file *file, void *priv)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -906,21 +934,22 @@ static int vidioc_log_status (struct fil
 	return 0;
 }
 
-static int vidioc_enum_input (struct file *file, void *priv,
-				struct v4l2_input *i)
+static int vidioc_enum_input(struct file *file, void *priv,
+			     struct v4l2_input *i)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
-	return cx88_enum_input (core,i);
+
+	return cx88_enum_input(core, i);
 }
 
-static int vidioc_g_frequency (struct file *file, void *priv,
-				struct v4l2_frequency *f)
+static int vidioc_g_frequency(struct file *file, void *priv,
+			      struct v4l2_frequency *f)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 
-	if (unlikely(UNSET == core->board.tuner_type))
+	if (unlikely(core->board.tuner_type == UNSET))
 		return -EINVAL;
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
@@ -931,7 +960,7 @@ static int vidioc_g_frequency (struct fi
 	return 0;
 }
 
-static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -940,31 +969,31 @@ static int vidioc_g_input (struct file *
 	return 0;
 }
 
-static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 
 	if (i >= 4)
 		return -EINVAL;
-	if (0 == INPUT(i).type)
+	if (!INPUT(i).type)
 		return -EINVAL;
 
 	cx88_newstation(core);
-	cx88_video_mux(core,i);
+	cx88_video_mux(core, i);
 	return 0;
 }
 
-static int vidioc_g_tuner (struct file *file, void *priv,
-				struct v4l2_tuner *t)
+static int vidioc_g_tuner(struct file *file, void *priv,
+			  struct v4l2_tuner *t)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 	u32 reg;
 
-	if (unlikely(UNSET == core->board.tuner_type))
+	if (unlikely(core->board.tuner_type == UNSET))
 		return -EINVAL;
-	if (0 != t->index)
+	if (t->index != 0)
 		return -EINVAL;
 
 	strcpy(t->name, "Television");
@@ -972,21 +1001,21 @@ static int vidioc_g_tuner (struct file *
 	t->rangehigh  = 0xffffffffUL;
 	call_all(core, tuner, g_tuner, t);
 
-	cx88_get_stereo(core ,t);
+	cx88_get_stereo(core, t);
 	reg = cx_read(MO_DEVICE_STATUS);
-	t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+	t->signal = (reg & (1 << 5)) ? 0xffff : 0x0000;
 	return 0;
 }
 
-static int vidioc_s_tuner (struct file *file, void *priv,
-				const struct v4l2_tuner *t)
+static int vidioc_s_tuner(struct file *file, void *priv,
+			  const struct v4l2_tuner *t)
 {
 	struct cx8802_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 
-	if (UNSET == core->board.tuner_type)
+	if (core->board.tuner_type == UNSET)
 		return -EINVAL;
-	if (0 != t->index)
+	if (t->index != 0)
 		return -EINVAL;
 
 	cx88_set_stereo(core, t->audmode, 1);
@@ -1010,8 +1039,7 @@ static int vidioc_s_std(struct file *fil
 	return cx88_set_tvnorm(core, id);
 }
 
-static const struct v4l2_file_operations mpeg_fops =
-{
+static const struct v4l2_file_operations mpeg_fops = {
 	.owner	       = THIS_MODULE,
 	.open	       = v4l2_fh_open,
 	.release       = vb2_fop_release,
@@ -1050,7 +1078,7 @@ static const struct v4l2_ioctl_ops mpeg_
 static struct video_device cx8802_mpeg_template = {
 	.name                 = "cx8802",
 	.fops                 = &mpeg_fops,
-	.ioctl_ops 	      = &mpeg_ioctl_ops,
+	.ioctl_ops	      = &mpeg_ioctl_ops,
 	.tvnorms              = CX88_NORMS,
 };
 
@@ -1064,7 +1092,9 @@ static int cx8802_blackbird_advise_acqui
 
 	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
-		/* By default, core setup will leave the cx22702 out of reset, on the bus.
+		/*
+		 * By default, core setup will leave the cx22702 out of reset,
+		 * on the bus.
 		 * We left the hardware on power up with the cx22702 active.
 		 * We're being given access to re-arrange the GPIOs.
 		 * Take the bus off the cx22702 and put the cx23416 on it.
@@ -1118,12 +1148,11 @@ static int blackbird_register_video(stru
 	dev->mpeg_dev.queue = &dev->vb2_mpegq;
 	err = video_register_device(&dev->mpeg_dev, VFL_TYPE_GRABBER, -1);
 	if (err < 0) {
-		printk(KERN_INFO "%s/2: can't register mpeg device\n",
-		       dev->core->name);
+		pr_info("can't register mpeg device\n");
 		return err;
 	}
-	printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
-	       dev->core->name, video_device_node_name(&dev->mpeg_dev));
+	pr_info("registered device %s [mpeg]\n",
+		video_device_node_name(&dev->mpeg_dev));
 	return 0;
 }
 
@@ -1136,8 +1165,8 @@ static int cx8802_blackbird_probe(struct
 	struct vb2_queue *q;
 	int err;
 
-	dprintk( 1, "%s\n", __func__);
-	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+	dprintk(1, "%s\n", __func__);
+	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
 		core->boardnr,
 		core->name,
 		core->pci_bus,
@@ -1158,16 +1187,15 @@ static int cx8802_blackbird_probe(struct
 	v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL);
 
 	/* blackbird stuff */
-	printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
-	       core->name);
+	pr_info("cx23416 based mpeg encoder (blackbird reference design)\n");
 	host_setup(dev->core);
 
 	blackbird_initialize_codec(dev);
 
 	/* initial device configuration: needed ? */
 //	init_controls(core);
-	cx88_set_tvnorm(core,core->tvnorm);
-	cx88_video_mux(core,0);
+	cx88_set_tvnorm(core, core->tvnorm);
+	cx88_video_mux(core, 0);
 	cx2341x_handler_set_50hz(&dev->cxhdl, core->height == 576);
 	cx2341x_handler_setup(&dev->cxhdl);
 
@@ -1219,8 +1247,8 @@ static struct cx8802_driver cx8802_black
 
 static int __init blackbird_init(void)
 {
-	printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
-	       CX88_VERSION);
+	pr_info("cx2388x blackbird driver version %s loaded\n",
+		CX88_VERSION);
 	return cx8802_register_driver(&cx8802_blackbird_driver);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-cards.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-cards.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-cards.c	2016-12-11 17:43:41.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-cards.c	2017-02-12 17:28:09.000000000 -0500
@@ -1,5 +1,4 @@
 /*
- *
  * device driver for Conexant 2388x based TV cards
  * card-specific stuff.
  *
@@ -14,22 +13,18 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 "cx88.h"
+#include "tea5767.h"
+#include "xc4000.h"
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 
-#include "cx88.h"
-#include "tea5767.h"
-#include "xc4000.h"
-
 static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 static unsigned int card[]  = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
@@ -38,32 +33,23 @@ module_param_array(tuner, int, NULL, 044
 module_param_array(radio, int, NULL, 0444);
 module_param_array(card,  int, NULL, 0444);
 
-MODULE_PARM_DESC(tuner,"tuner type");
-MODULE_PARM_DESC(radio,"radio tuner type");
-MODULE_PARM_DESC(card,"card type");
+MODULE_PARM_DESC(tuner, "tuner type");
+MODULE_PARM_DESC(radio, "radio tuner type");
+MODULE_PARM_DESC(card, "card type");
 
 static unsigned int latency = UNSET;
-module_param(latency,int,0444);
-MODULE_PARM_DESC(latency,"pci latency timer");
+module_param(latency, int, 0444);
+MODULE_PARM_DESC(latency, "pci latency timer");
 
 static int disable_ir;
 module_param(disable_ir, int, 0444);
 MODULE_PARM_DESC(disable_ir, "Disable IR support");
 
-#define info_printk(core, fmt, arg...) \
-	printk(KERN_INFO "%s: " fmt, core->name , ## arg)
-
-#define warn_printk(core, fmt, arg...) \
-	printk(KERN_WARNING "%s: " fmt, core->name , ## arg)
-
-#define err_printk(core, fmt, arg...) \
-	printk(KERN_ERR "%s: " fmt, core->name , ## arg)
-
-#define dprintk(level,fmt, arg...)	do {				\
+#define dprintk(level, fmt, arg...)	do {				\
 	if (cx88_core_debug >= level)					\
-		printk(KERN_DEBUG "%s: " fmt, core->name , ## arg);	\
-	} while(0)
-
+		printk(KERN_DEBUG pr_fmt("%s: core:" fmt),		\
+			__func__, ##arg);				\
+} while (0)
 
 /* ------------------------------------------------------------------ */
 /* board config info                                                  */
@@ -291,7 +277,6 @@ static const struct cx88_board cx88_boar
 			.gpio2  = 0x0035e700,
 			.gpio3  = 0x02000000,
 		}, {
-
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
 			.gpio0  = 0x0035c700,
@@ -505,22 +490,22 @@ static const struct cx88_board cx88_boar
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
 		/*
-		   GPIO[0] resets DT3302 DTV receiver
-		    0 - reset asserted
-		    1 - normal operation
-		   GPIO[1] mutes analog audio output connector
-		    0 - enable selected source
-		    1 - mute
-		   GPIO[2] selects source for analog audio output connector
-		    0 - analog audio input connector on tab
-		    1 - analog DAC output from CX23881 chip
-		   GPIO[3] selects RF input connector on tuner module
-		    0 - RF connector labeled CABLE
-		    1 - RF connector labeled ANT
-		   GPIO[4] selects high RF for QAM256 mode
-		    0 - normal RF
-		    1 - high RF
-		*/
+		 * GPIO[0] resets DT3302 DTV receiver
+		 *     0 - reset asserted
+		 *     1 - normal operation
+		 * GPIO[1] mutes analog audio output connector
+		 *     0 - enable selected source
+		 *     1 - mute
+		 * GPIO[2] selects source for analog audio output connector
+		 *     0 - analog audio input connector on tab
+		 *     1 - analog DAC output from CX23881 chip
+		 * GPIO[3] selects RF input connector on tuner module
+		 *     0 - RF connector labeled CABLE
+		 *     1 - RF connector labeled ANT
+		 * GPIO[4] selects high RF for QAM256 mode
+		 *     0 - normal RF
+		 *     1 - high RF
+		 */
 		.input          = { {
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -743,7 +728,10 @@ static const struct cx88_board cx88_boar
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		/* Some variants use a tda9874 and so need the tvaudio module. */
+		/*
+		 * Some variants use a tda9874 and so need the
+		 * tvaudio module.
+		 */
 		.audio_chip     = CX88_AUDIO_TVAUDIO,
 		.input          = { {
 			.type   = CX88_VMUX_TELEVISION,
@@ -1209,8 +1197,10 @@ static const struct cx88_board cx88_boar
 		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_KWORLD_MCE200_DELUXE] = {
-		/* FIXME: tested TV input only, disabled composite,
-		   svideo and radio until they can be tested also. */
+		/*
+		 * FIXME: tested TV input only, disabled composite,
+		 * svideo and radio until they can be tested also.
+		 */
 		.name           = "Kworld MCE 200 Deluxe",
 		.tuner_type     = TUNER_TENA_9533_DI,
 		.radio_type     = UNSET,
@@ -1721,16 +1711,24 @@ static const struct cx88_board cx88_boar
 		},
 	},
 	[CX88_BOARD_POWERCOLOR_REAL_ANGEL] = {
-		.name           = "PowerColor RA330",	/* Long names may confuse LIRC. */
+		/* Long names may confuse LIRC. */
+		.name           = "PowerColor RA330",
 		.tuner_type     = TUNER_XC2028,
 		.tuner_addr     = 0x61,
 		.input          = { {
+			/*
+			 * Due to the way the cx88 driver is written,
+			 * there is no way to deactivate audio pass-
+			 * through without this entry. Furthermore, if
+			 * the TV mux entry is first, you get audio
+			 * from the tuner on boot for a little while.
+			 */
 			.type   = CX88_VMUX_DEBUG,
-			.vmux   = 3,		/* Due to the way the cx88 driver is written,	*/
-			.gpio0 = 0x00ff,	/* there is no way to deactivate audio pass-	*/
-			.gpio1 = 0xf39d,	/* through without this entry. Furthermore, if	*/
-			.gpio3 = 0x0000,	/* the TV mux entry is first, you get audio	*/
-		}, {				/* from the tuner on boot for a little while.	*/
+			.vmux   = 3,
+			.gpio0 = 0x00ff,
+			.gpio1 = 0xf39d,
+			.gpio3 = 0x0000,
+		}, {
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
 			.gpio0 = 0x00ff,
@@ -1883,11 +1881,12 @@ static const struct cx88_board cx88_boar
 			.gpio2 = 0x0cf7,
 		},
 	},
-	/* Both radio, analog and ATSC work with this board.
-	   However, for analog to work, s5h1409 gate should be open,
-	   otherwise, tuner-xc3028 won't be detected.
-	   A proper fix require using the newer i2c methods to add
-	   tuner-xc3028 without doing an i2c probe.
+	/*
+	 * Both radio, analog and ATSC work with this board.
+	 * However, for analog to work, s5h1409 gate should be open,
+	 * otherwise, tuner-xc3028 won't be detected.
+	 * A proper fix require using the newer i2c methods to add
+	 * tuner-xc3028 without doing an i2c probe.
 	 */
 	[CX88_BOARD_KWORLD_ATSC_120] = {
 		.name           = "Kworld PlusTV HD PCI 120 (ATSC 120)",
@@ -2821,15 +2820,15 @@ static const struct cx88_subid cx88_subi
 	},
 };
 
-/* ----------------------------------------------------------------------- */
-/* some leadtek specific stuff                                             */
-
+/*
+ * some leadtek specific stuff
+ */
 static void leadtek_eeprom(struct cx88_core *core, u8 *eeprom_data)
 {
 	if (eeprom_data[4] != 0x7d ||
 	    eeprom_data[5] != 0x10 ||
 	    eeprom_data[7] != 0x66) {
-		warn_printk(core, "Leadtek eeprom invalid.\n");
+		pr_warn("Leadtek eeprom invalid.\n");
 		return;
 	}
 
@@ -2847,9 +2846,8 @@ static void leadtek_eeprom(struct cx88_c
 		break;
 	}
 
-	info_printk(core, "Leadtek Winfast 2000XP Expert config: "
-		    "tuner=%d, eeprom[0]=0x%02x\n",
-		    core->board.tuner_type, eeprom_data[0]);
+	pr_info("Leadtek Winfast 2000XP Expert config: tuner=%d, eeprom[0]=0x%02x\n",
+		core->board.tuner_type, eeprom_data[0]);
 }
 
 static void hauppauge_eeprom(struct cx88_core *core, u8 *eeprom_data)
@@ -2863,8 +2861,7 @@ static void hauppauge_eeprom(struct cx88
 	core->model = tv.model;
 
 	/* Make sure we support the board model */
-	switch (tv.model)
-	{
+	switch (tv.model) {
 	case 14009: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in) */
 	case 14019: /* WinTV-HVR3000 (Retail, IR Blaster, b/panel video, 3.5mm audio in) */
 	case 14029: /* WinTV-HVR3000 (Retail, IR, b/panel video, 3.5mm audio in - 880 bridge) */
@@ -2905,50 +2902,50 @@ static void hauppauge_eeprom(struct cx88
 		cx_set(MO_GP0_IO, 0x008989FF);
 		break;
 	default:
-		warn_printk(core, "warning: unknown hauppauge model #%d\n",
-			    tv.model);
+		pr_warn("warning: unknown hauppauge model #%d\n", tv.model);
 		break;
 	}
 
-	info_printk(core, "hauppauge eeprom: model=%d\n", tv.model);
+	pr_info("hauppauge eeprom: model=%d\n", tv.model);
 }
 
-/* ----------------------------------------------------------------------- */
-/* some GDI (was: Modular Technology) specific stuff                       */
+/*
+ * some GDI (was: Modular Technology) specific stuff
+ */
 
 static const struct {
 	int  id;
 	int  fm;
 	const char *name;
 } gdi_tuner[] = {
-	[ 0x01 ] = { .id   = UNSET,
-		     .name = "NTSC_M" },
-	[ 0x02 ] = { .id   = UNSET,
-		     .name = "PAL_B" },
-	[ 0x03 ] = { .id   = UNSET,
-		     .name = "PAL_I" },
-	[ 0x04 ] = { .id   = UNSET,
-		     .name = "PAL_D" },
-	[ 0x05 ] = { .id   = UNSET,
-		     .name = "SECAM" },
+	[0x01] = { .id   = UNSET,
+		   .name = "NTSC_M" },
+	[0x02] = { .id   = UNSET,
+		   .name = "PAL_B" },
+	[0x03] = { .id   = UNSET,
+		   .name = "PAL_I" },
+	[0x04] = { .id   = UNSET,
+		   .name = "PAL_D" },
+	[0x05] = { .id   = UNSET,
+		   .name = "SECAM" },
 
-	[ 0x10 ] = { .id   = UNSET,
-		     .fm   = 1,
-		     .name = "TEMIC_4049" },
-	[ 0x11 ] = { .id   = TUNER_TEMIC_4136FY5,
-		     .name = "TEMIC_4136" },
-	[ 0x12 ] = { .id   = UNSET,
-		     .name = "TEMIC_4146" },
+	[0x10] = { .id   = UNSET,
+		   .fm   = 1,
+		   .name = "TEMIC_4049" },
+	[0x11] = { .id   = TUNER_TEMIC_4136FY5,
+		   .name = "TEMIC_4136" },
+	[0x12] = { .id   = UNSET,
+		   .name = "TEMIC_4146" },
 
-	[ 0x20 ] = { .id   = TUNER_PHILIPS_FQ1216ME,
-		     .fm   = 1,
-		     .name = "PHILIPS_FQ1216_MK3" },
-	[ 0x21 ] = { .id   = UNSET, .fm = 1,
-		     .name = "PHILIPS_FQ1236_MK3" },
-	[ 0x22 ] = { .id   = UNSET,
-		     .name = "PHILIPS_FI1236_MK3" },
-	[ 0x23 ] = { .id   = UNSET,
-		     .name = "PHILIPS_FI1216_MK3" },
+	[0x20] = { .id   = TUNER_PHILIPS_FQ1216ME,
+		   .fm   = 1,
+		   .name = "PHILIPS_FQ1216_MK3" },
+	[0x21] = { .id   = UNSET, .fm = 1,
+		   .name = "PHILIPS_FQ1236_MK3" },
+	[0x22] = { .id   = UNSET,
+		   .name = "PHILIPS_FI1236_MK3" },
+	[0x23] = { .id   = UNSET,
+		   .name = "PHILIPS_FI1216_MK3" },
 };
 
 static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data)
@@ -2956,16 +2953,17 @@ static void gdi_eeprom(struct cx88_core
 	const char *name = (eeprom_data[0x0d] < ARRAY_SIZE(gdi_tuner))
 		? gdi_tuner[eeprom_data[0x0d]].name : NULL;
 
-	info_printk(core, "GDI: tuner=%s\n", name ? name : "unknown");
-	if (NULL == name)
+	pr_info("GDI: tuner=%s\n", name ? name : "unknown");
+	if (!name)
 		return;
 	core->board.tuner_type = gdi_tuner[eeprom_data[0x0d]].id;
 	core->board.radio.type = gdi_tuner[eeprom_data[0x0d]].fm ?
 		CX88_RADIO : 0;
 }
 
-/* ------------------------------------------------------------------- */
-/* some Divco specific stuff                                           */
+/*
+ * some Divco specific stuff
+ */
 static int cx88_dvico_xc2028_callback(struct cx88_core *core,
 				      int command, int arg)
 {
@@ -2994,9 +2992,9 @@ static int cx88_dvico_xc2028_callback(st
 	return 0;
 }
 
-
-/* ----------------------------------------------------------------------- */
-/* some Geniatech specific stuff                                           */
+/*
+ * some Geniatech specific stuff
+ */
 
 static int cx88_xc3028_geniatech_tuner_callback(struct cx88_core *core,
 						int command, int mode)
@@ -3059,8 +3057,9 @@ static int cx88_xc4000_winfast2000h_plus
 	return -EINVAL;
 }
 
-/* ------------------------------------------------------------------- */
-/* some Divco specific stuff                                           */
+/*
+ * some Divco specific stuff
+ */
 static int cx88_pv_8000gt_callback(struct cx88_core *core,
 				   int command, int arg)
 {
@@ -3079,8 +3078,9 @@ static int cx88_pv_8000gt_callback(struc
 	return 0;
 }
 
-/* ----------------------------------------------------------------------- */
-/* some DViCO specific stuff                                               */
+/*
+ * some DViCO specific stuff
+ */
 
 static void dvico_fusionhdtv_hybrid_init(struct cx88_core *core)
 {
@@ -3107,8 +3107,8 @@ static void dvico_fusionhdtv_hybrid_init
 		msg.len = (i != 12 ? 5 : 2);
 		err = i2c_transfer(&core->i2c_adap, &msg, 1);
 		if (err != 1) {
-			warn_printk(core, "dvico_fusionhdtv_hybrid_init buf %d "
-					  "failed (err = %d)!\n", i, err);
+			pr_warn("dvico_fusionhdtv_hybrid_init buf %d failed (err = %d)!\n",
+				i, err);
 			return;
 		}
 	}
@@ -3176,11 +3176,11 @@ static int cx88_xc4000_tuner_callback(st
 	return -EINVAL;
 }
 
-/* ----------------------------------------------------------------------- */
-/* Tuner callback function. Currently only needed for the Pinnacle 	   *
- * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both	   *
- * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)    */
-
+/*
+ * Tuner callback function. Currently only needed for the Pinnacle
+ * PCTV HD 800i with an xc5000 sillicon tuner. This is used for both
+ * analog tuner attach (tuner-core.c) and dvb tuner attach (cx88-dvb.c)
+ */
 static int cx88_xc5000_tuner_callback(struct cx88_core *core,
 				      int command, int arg)
 {
@@ -3188,38 +3188,38 @@ static int cx88_xc5000_tuner_callback(st
 	case CX88_BOARD_PINNACLE_PCTV_HD_800i:
 		if (command == 0) { /* This is the reset command from xc5000 */
 
-			/* djh - According to the engineer at PCTV Systems,
-			   the xc5000 reset pin is supposed to be on GPIO12.
-			   However, despite three nights of effort, pulling
-			   that GPIO low didn't reset the xc5000.  While
-			   pulling MO_SRST_IO low does reset the xc5000, this
-			   also resets in the s5h1409 being reset as well.
-			   This causes tuning to always fail since the internal
-			   state of the s5h1409 does not match the driver's
-			   state.  Given that the only two conditions in which
-			   the driver performs a reset is during firmware load
-			   and powering down the chip, I am taking out the
-			   reset.  We know that the chip is being reset
-			   when the cx88 comes online, and not being able to
-			   do power management for this board is worse than
-			   not having any tuning at all. */
+			/*
+			 * djh - According to the engineer at PCTV Systems,
+			 * the xc5000 reset pin is supposed to be on GPIO12.
+			 * However, despite three nights of effort, pulling
+			 * that GPIO low didn't reset the xc5000.  While
+			 * pulling MO_SRST_IO low does reset the xc5000, this
+			 * also resets in the s5h1409 being reset as well.
+			 * This causes tuning to always fail since the internal
+			 * state of the s5h1409 does not match the driver's
+			 * state.  Given that the only two conditions in which
+			 * the driver performs a reset is during firmware load
+			 * and powering down the chip, I am taking out the
+			 * reset.  We know that the chip is being reset
+			 * when the cx88 comes online, and not being able to
+			 * do power management for this board is worse than
+			 * not having any tuning at all.
+			 */
 			return 0;
-		} else {
-			dprintk(1, "xc5000: unknown tuner callback command.\n");
-			return -EINVAL;
 		}
-		break;
+
+		dprintk(1, "xc5000: unknown tuner callback command.\n");
+		return -EINVAL;
 	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
 		if (command == 0) { /* This is the reset command from xc5000 */
 			cx_clear(MO_GP0_IO, 0x00000010);
-			msleep(10);
+			usleep_range(10000, 20000);
 			cx_set(MO_GP0_IO, 0x00000010);
 			return 0;
-		} else {
-			dprintk(1, "xc5000: unknown tuner callback command.\n");
-			return -EINVAL;
 		}
-		break;
+
+		dprintk(1, "xc5000: unknown tuner callback command.\n");
+		return -EINVAL;
 	}
 	return 0; /* Should never be here */
 }
@@ -3230,14 +3230,14 @@ int cx88_tuner_callback(void *priv, int
 	struct cx88_core *core;
 
 	if (!i2c_algo) {
-		printk(KERN_ERR "cx88: Error - i2c private data undefined.\n");
+		pr_err("Error - i2c private data undefined.\n");
 		return -EINVAL;
 	}
 
 	core = i2c_algo->data;
 
 	if (!core) {
-		printk(KERN_ERR "cx88: Error - device struct undefined.\n");
+		pr_err("Error - device struct undefined.\n");
 		return -EINVAL;
 	}
 
@@ -3245,18 +3245,18 @@ int cx88_tuner_callback(void *priv, int
 		return -EINVAL;
 
 	switch (core->board.tuner_type) {
-		case TUNER_XC2028:
-			dprintk(1, "Calling XC2028/3028 callback\n");
-			return cx88_xc2028_tuner_callback(core, command, arg);
-		case TUNER_XC4000:
-			dprintk(1, "Calling XC4000 callback\n");
-			return cx88_xc4000_tuner_callback(core, command, arg);
-		case TUNER_XC5000:
-			dprintk(1, "Calling XC5000 callback\n");
-			return cx88_xc5000_tuner_callback(core, command, arg);
+	case TUNER_XC2028:
+		dprintk(1, "Calling XC2028/3028 callback\n");
+		return cx88_xc2028_tuner_callback(core, command, arg);
+	case TUNER_XC4000:
+		dprintk(1, "Calling XC4000 callback\n");
+		return cx88_xc4000_tuner_callback(core, command, arg);
+	case TUNER_XC5000:
+		dprintk(1, "Calling XC5000 callback\n");
+		return cx88_xc5000_tuner_callback(core, command, arg);
 	}
-	err_printk(core, "Error: Calling callback for tuner %d\n",
-		   core->board.tuner_type);
+	pr_err("Error: Calling callback for tuner %d\n",
+	       core->board.tuner_type);
 	return -EINVAL;
 }
 EXPORT_SYMBOL(cx88_tuner_callback);
@@ -3267,28 +3267,20 @@ static void cx88_card_list(struct cx88_c
 {
 	int i;
 
-	if (0 == pci->subsystem_vendor &&
-	    0 == pci->subsystem_device) {
-		printk(KERN_ERR
-		       "%s: Your board has no valid PCI Subsystem ID and thus can't\n"
-		       "%s: be autodetected.  Please pass card=<n> insmod option to\n"
-		       "%s: workaround that.  Redirect complaints to the vendor of\n"
-		       "%s: the TV card.  Best regards,\n"
-		       "%s:         -- tux\n",
-		       core->name,core->name,core->name,core->name,core->name);
+	if (!pci->subsystem_vendor && !pci->subsystem_device) {
+		pr_err("Your board has no valid PCI Subsystem ID and thus can't\n");
+		pr_err("be autodetected.  Please pass card=<n> insmod option to\n");
+		pr_err("workaround that.  Redirect complaints to the vendor of\n");
+		pr_err("the TV card\n");
 	} else {
-		printk(KERN_ERR
-		       "%s: Your board isn't known (yet) to the driver.  You can\n"
-		       "%s: try to pick one of the existing card configs via\n"
-		       "%s: card=<n> insmod option.  Updating to the latest\n"
-		       "%s: version might help as well.\n",
-		       core->name,core->name,core->name,core->name);
+		pr_err("Your board isn't known (yet) to the driver.  You can\n");
+		pr_err("try to pick one of the existing card configs via\n");
+		pr_err("card=<n> insmod option.  Updating to the latest\n");
+		pr_err("version might help as well.\n");
 	}
-	err_printk(core, "Here is a list of valid choices for the card=<n> "
-		   "insmod option:\n");
+	pr_err("Here is a list of valid choices for the card=<n> insmod option:\n");
 	for (i = 0; i < ARRAY_SIZE(cx88_boards); i++)
-		printk(KERN_ERR "%s:    card=%d -> %s\n",
-		       core->name, i, cx88_boards[i].name);
+		pr_err("    card=%d -> %s\n", i, cx88_boards[i].name);
 }
 
 static void cx88_card_setup_pre_i2c(struct cx88_core *core)
@@ -3296,7 +3288,9 @@ static void cx88_card_setup_pre_i2c(stru
 	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
 		/*
-		 * Bring the 702 demod up before i2c scanning/attach or devices are hidden
+		 * Bring the 702 demod up before i2c scanning/attach or
+		 * devices are hidden.
+		 *
 		 * We leave here with the 702 on the bus
 		 *
 		 * "reset the IR receiver on GPIO[3]"
@@ -3317,7 +3311,7 @@ static void cx88_card_setup_pre_i2c(stru
 		cx_write(MO_GP2_IO, 0xef5);
 		mdelay(50);
 		cx_write(MO_GP2_IO, 0xcf7);
-		msleep(10);
+		usleep_range(10000, 20000);
 		break;
 
 	case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD:
@@ -3353,7 +3347,7 @@ static void cx88_card_setup_pre_i2c(stru
 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
 		cx_write(MO_GP0_IO, 0x00003230);
 		cx_write(MO_GP0_IO, 0x00003210);
-		msleep(1);
+		usleep_range(10000, 20000);
 		cx_write(MO_GP0_IO, 0x00001230);
 		break;
 	}
@@ -3384,11 +3378,13 @@ void cx88_setup_xc3028(struct cx88_core
 		ctl->demod = XC3028_FE_OREN538;
 		break;
 	case CX88_BOARD_GENIATECH_X8000_MT:
-		/* FIXME: For this board, the xc3028 never recovers after being
-		   powered down (the reset GPIO probably is not set properly).
-		   We don't have access to the hardware so we cannot determine
-		   which GPIO is used for xc3028, so just disable power xc3028
-		   power management for now */
+		/*
+		 * FIXME: For this board, the xc3028 never recovers after being
+		 * powered down (the reset GPIO probably is not set properly).
+		 * We don't have access to the hardware so we cannot determine
+		 * which GPIO is used for xc3028, so just disable power xc3028
+		 * power management for now
+		 */
 		ctl->disable_power_mgmt = 1;
 		break;
 	case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL:
@@ -3418,7 +3414,7 @@ static void cx88_card_setup(struct cx88_
 
 	memset(&tun_setup, 0, sizeof(tun_setup));
 
-	if (0 == core->i2c_rc) {
+	if (!core->i2c_rc) {
 		core->i2c_client.addr = 0xa0 >> 1;
 		tveeprom_read(&core->i2c_client, eeprom, sizeof(eeprom));
 	}
@@ -3426,17 +3422,17 @@ static void cx88_card_setup(struct cx88_
 	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE:
 	case CX88_BOARD_HAUPPAUGE_ROSLYN:
-		if (0 == core->i2c_rc)
-			hauppauge_eeprom(core, eeprom+8);
+		if (!core->i2c_rc)
+			hauppauge_eeprom(core, eeprom + 8);
 		break;
 	case CX88_BOARD_GDI:
-		if (0 == core->i2c_rc)
+		if (!core->i2c_rc)
 			gdi_eeprom(core, eeprom);
 		break;
 	case CX88_BOARD_LEADTEK_PVR2000:
 	case CX88_BOARD_WINFAST_DV2000:
 	case CX88_BOARD_WINFAST2000XP_EXPERT:
-		if (0 == core->i2c_rc)
+		if (!core->i2c_rc)
 			leadtek_eeprom(core, eeprom);
 		break;
 	case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
@@ -3449,7 +3445,7 @@ static void cx88_card_setup(struct cx88_
 	case CX88_BOARD_HAUPPAUGE_HVR4000:
 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
 	case CX88_BOARD_HAUPPAUGE_IRONLY:
-		if (0 == core->i2c_rc)
+		if (!core->i2c_rc)
 			hauppauge_eeprom(core, eeprom);
 		break;
 	case CX88_BOARD_KWORLD_DVBS_100:
@@ -3460,7 +3456,7 @@ static void cx88_card_setup(struct cx88_
 		/* GPIO0:0 is hooked to demod reset */
 		/* GPIO0:4 is hooked to xc3028 reset */
 		cx_write(MO_GP0_IO, 0x00111100);
-		msleep(1);
+		usleep_range(10000, 20000);
 		cx_write(MO_GP0_IO, 0x00111111);
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
@@ -3476,9 +3472,9 @@ static void cx88_card_setup(struct cx88_
 		/* GPIO0:0 is hooked to mt352 reset pin */
 		cx_set(MO_GP0_IO, 0x00000101);
 		cx_clear(MO_GP0_IO, 0x00000001);
-		msleep(1);
+		usleep_range(10000, 20000);
 		cx_set(MO_GP0_IO, 0x00000101);
-		if (0 == core->i2c_rc &&
+		if (!core->i2c_rc &&
 		    core->boardnr == CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID)
 			dvico_fusionhdtv_hybrid_init(core);
 		break;
@@ -3487,7 +3483,7 @@ static void cx88_card_setup(struct cx88_
 		cx_set(MO_GP0_IO, 0x00000707);
 		cx_set(MO_GP2_IO, 0x00000101);
 		cx_clear(MO_GP2_IO, 0x00000001);
-		msleep(1);
+		usleep_range(10000, 20000);
 		cx_clear(MO_GP0_IO, 0x00000007);
 		cx_set(MO_GP2_IO, 0x00000101);
 		break;
@@ -3495,23 +3491,23 @@ static void cx88_card_setup(struct cx88_
 		cx_write(MO_GP0_IO, 0x00080808);
 		break;
 	case CX88_BOARD_ATI_HDTVWONDER:
-		if (0 == core->i2c_rc) {
+		if (!core->i2c_rc) {
 			/* enable tuner */
 			int i;
-			static const u8 buffer [][2] = {
-				{0x10,0x12},
-				{0x13,0x04},
-				{0x16,0x00},
-				{0x14,0x04},
-				{0x17,0x00}
+			static const u8 buffer[][2] = {
+				{0x10, 0x12},
+				{0x13, 0x04},
+				{0x16, 0x00},
+				{0x14, 0x04},
+				{0x17, 0x00}
 			};
 			core->i2c_client.addr = 0x0a;
 
 			for (i = 0; i < ARRAY_SIZE(buffer); i++)
-				if (2 != i2c_master_send(&core->i2c_client,
-							buffer[i],2))
-					warn_printk(core, "Unable to enable "
-						    "tuner(%i).\n", i);
+				if (i2c_master_send(&core->i2c_client,
+						    buffer[i], 2) != 2)
+					pr_warn("Unable to enable tuner(%i).\n",
+						i);
 		}
 		break;
 	case CX88_BOARD_MSI_TVANYWHERE_MASTER:
@@ -3545,7 +3541,7 @@ static void cx88_card_setup(struct cx88_
 		cx_write(MO_GP0_IO, 0x8000);
 		msleep(100);
 		cx_write(MO_SRST_IO, 0);
-		msleep(10);
+		usleep_range(10000, 20000);
 		cx_write(MO_GP0_IO, 0x8080);
 		msleep(100);
 		cx_write(MO_SRST_IO, 1);
@@ -3553,9 +3549,8 @@ static void cx88_card_setup(struct cx88_
 		break;
 	} /*end switch() */
 
-
 	/* Setup tuners */
-	if ((core->board.radio_type != UNSET)) {
+	if (core->board.radio_type != UNSET) {
 		tun_setup.mode_mask      = T_RADIO;
 		tun_setup.type           = core->board.radio_type;
 		tun_setup.addr           = core->board.radio_addr;
@@ -3610,35 +3605,30 @@ static int cx88_pci_quirks(const char *n
 
 	/* check pci quirks */
 	if (pci_pci_problems & PCIPCI_TRITON) {
-		printk(KERN_INFO "%s: quirk: PCIPCI_TRITON -- set TBFX\n",
-		       name);
+		pr_info("quirk: PCIPCI_TRITON -- set TBFX\n");
 		ctrl |= CX88X_EN_TBFX;
 	}
 	if (pci_pci_problems & PCIPCI_NATOMA) {
-		printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA -- set TBFX\n",
-		       name);
+		pr_info("quirk: PCIPCI_NATOMA -- set TBFX\n");
 		ctrl |= CX88X_EN_TBFX;
 	}
 	if (pci_pci_problems & PCIPCI_VIAETBF) {
-		printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF -- set TBFX\n",
-		       name);
+		pr_info("quirk: PCIPCI_VIAETBF -- set TBFX\n");
 		ctrl |= CX88X_EN_TBFX;
 	}
 	if (pci_pci_problems & PCIPCI_VSFX) {
-		printk(KERN_INFO "%s: quirk: PCIPCI_VSFX -- set VSFX\n",
-		       name);
+		pr_info("quirk: PCIPCI_VSFX -- set VSFX\n");
 		ctrl |= CX88X_EN_VSFX;
 	}
 #ifdef PCIPCI_ALIMAGIK
 	if (pci_pci_problems & PCIPCI_ALIMAGIK) {
-		printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
-		       name);
+		pr_info("quirk: PCIPCI_ALIMAGIK -- latency fixup\n");
 		lat = 0x0A;
 	}
 #endif
 
 	/* check insmod options */
-	if (UNSET != latency)
+	if (latency != UNSET)
 		lat = latency;
 
 	/* apply stuff */
@@ -3647,9 +3637,8 @@ static int cx88_pci_quirks(const char *n
 		value |= ctrl;
 		pci_write_config_byte(pci, CX88X_DEVCTRL, value);
 	}
-	if (UNSET != lat) {
-		printk(KERN_INFO "%s: setting pci latency timer to %d\n",
-		       name, latency);
+	if (lat != UNSET) {
+		pr_info("setting pci latency timer to %d\n", latency);
 		pci_write_config_byte(pci, PCI_LATENCY_TIMER, latency);
 	}
 	return 0;
@@ -3657,27 +3646,28 @@ static int cx88_pci_quirks(const char *n
 
 int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci)
 {
-	if (request_mem_region(pci_resource_start(pci,0),
-			       pci_resource_len(pci,0),
+	if (request_mem_region(pci_resource_start(pci, 0),
+			       pci_resource_len(pci, 0),
 			       core->name))
 		return 0;
-	printk(KERN_ERR
-	       "%s/%d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n",
-	       core->name, PCI_FUNC(pci->devfn),
+	pr_err("func %d: Can't get MMIO memory @ 0x%llx, subsystem: %04x:%04x\n",
+	       PCI_FUNC(pci->devfn),
 	       (unsigned long long)pci_resource_start(pci, 0),
 	       pci->subsystem_vendor, pci->subsystem_device);
 	return -EBUSY;
 }
 
-/* Allocate and initialize the cx88 core struct.  One should hold the
- * devlist mutex before calling this.  */
+/*
+ * Allocate and initialize the cx88 core struct.  One should hold the
+ * devlist mutex before calling this.
+ */
 struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
 {
 	struct cx88_core *core;
 	int i;
 
 	core = kzalloc(sizeof(*core), GFP_KERNEL);
-	if (core == NULL)
+	if (!core)
 		return NULL;
 
 	atomic_inc(&core->refcount);
@@ -3715,7 +3705,7 @@ struct cx88_core *cx88_core_create(struc
 		return NULL;
 	}
 
-	if (0 != cx88_get_resources(core, pci)) {
+	if (cx88_get_resources(core, pci) != 0) {
 		v4l2_ctrl_handler_free(&core->video_hdl);
 		v4l2_ctrl_handler_free(&core->audio_hdl);
 		v4l2_device_unregister(&core->v4l2_dev);
@@ -3729,9 +3719,9 @@ struct cx88_core *cx88_core_create(struc
 			      pci_resource_len(pci, 0));
 	core->bmmio = (u8 __iomem *)core->lmmio;
 
-	if (core->lmmio == NULL) {
+	if (!core->lmmio) {
 		release_mem_region(pci_resource_start(pci, 0),
-			   pci_resource_len(pci, 0));
+				   pci_resource_len(pci, 0));
 		v4l2_ctrl_handler_free(&core->video_hdl);
 		v4l2_ctrl_handler_free(&core->audio_hdl);
 		v4l2_device_unregister(&core->v4l2_dev);
@@ -3743,11 +3733,11 @@ struct cx88_core *cx88_core_create(struc
 	core->boardnr = UNSET;
 	if (card[core->nr] < ARRAY_SIZE(cx88_boards))
 		core->boardnr = card[core->nr];
-	for (i = 0; UNSET == core->boardnr && i < ARRAY_SIZE(cx88_subids); i++)
+	for (i = 0; core->boardnr == UNSET && i < ARRAY_SIZE(cx88_subids); i++)
 		if (pci->subsystem_vendor == cx88_subids[i].subvendor &&
 		    pci->subsystem_device == cx88_subids[i].subdevice)
 			core->boardnr = cx88_subids[i].card;
-	if (UNSET == core->boardnr) {
+	if (core->boardnr == UNSET) {
 		core->boardnr = CX88_BOARD_UNKNOWN;
 		cx88_card_list(core, pci);
 	}
@@ -3757,7 +3747,7 @@ struct cx88_core *cx88_core_create(struc
 	if (!core->board.num_frontends && (core->board.mpeg & CX88_MPEG_DVB))
 		core->board.num_frontends = 1;
 
-	info_printk(core, "subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
+	pr_info("subsystem: %04x:%04x, board: %s [card=%d,%s], frontend(s): %d\n",
 		pci->subsystem_vendor, pci->subsystem_device, core->board.name,
 		core->boardnr, card[core->nr] == core->boardnr ?
 		"insmod option" : "autodetected",
@@ -3777,10 +3767,12 @@ struct cx88_core *cx88_core_create(struc
 	cx88_i2c_init(core, pci);
 
 	/* load tuner module, if needed */
-	if (UNSET != core->board.tuner_type) {
-		/* Ignore 0x6b and 0x6f on cx88 boards.
+	if (core->board.tuner_type != UNSET) {
+		/*
+		 * Ignore 0x6b and 0x6f on cx88 boards.
 		 * FusionHDTV5 RT Gold has an ir receiver at 0x6b
-		 * and an RTC at 0x6f which can get corrupted if probed. */
+		 * and an RTC at 0x6f which can get corrupted if probed.
+		 */
 		static const unsigned short tv_addrs[] = {
 			0x42, 0x43, 0x4a, 0x4b,		/* tda8290 */
 			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
@@ -3789,24 +3781,27 @@ struct cx88_core *cx88_core_create(struc
 		};
 		int has_demod = (core->board.tda9887_conf & TDA9887_PRESENT);
 
-		/* I don't trust the radio_type as is stored in the card
-		   definitions, so we just probe for it.
-		   The radio_type is sometimes missing, or set to UNSET but
-		   later code configures a tea5767.
+		/*
+		 * I don't trust the radio_type as is stored in the card
+		 * definitions, so we just probe for it.
+		 * The radio_type is sometimes missing, or set to UNSET but
+		 * later code configures a tea5767.
 		 */
 		v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-				"tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_RADIO));
+				    "tuner", 0,
+				    v4l2_i2c_tuner_addrs(ADDRS_RADIO));
 		if (has_demod)
 			v4l2_i2c_new_subdev(&core->v4l2_dev,
-				&core->i2c_adap, "tuner",
+					    &core->i2c_adap, "tuner",
 				0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
 		if (core->board.tuner_addr == ADDR_UNSET) {
 			v4l2_i2c_new_subdev(&core->v4l2_dev,
-				&core->i2c_adap, "tuner",
+					    &core->i2c_adap, "tuner",
 				0, has_demod ? tv_addrs + 4 : tv_addrs);
 		} else {
 			v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-				"tuner", core->board.tuner_addr, NULL);
+					    "tuner", core->board.tuner_addr,
+					    NULL);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-core.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-core.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,4 @@
 /*
- *
  * device driver for Conexant 2388x based TV cards
  * driver core
  *
@@ -19,12 +18,10 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 "cx88.h"
+
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -38,7 +35,6 @@
 #include <linux/videodev2.h>
 #include <linux/mutex.h>
 
-#include "cx88.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 
@@ -53,17 +49,22 @@ module_param_named(core_debug, cx88_core
 MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
 
 static unsigned int nicam;
-module_param(nicam,int,0644);
-MODULE_PARM_DESC(nicam,"tv audio is nicam");
+module_param(nicam, int, 0644);
+MODULE_PARM_DESC(nicam, "tv audio is nicam");
 
 static unsigned int nocomb;
-module_param(nocomb,int,0644);
-MODULE_PARM_DESC(nocomb,"disable comb filter");
+module_param(nocomb, int, 0644);
+MODULE_PARM_DESC(nocomb, "disable comb filter");
 
-#define dprintk(level,fmt, arg...)	do {				\
-	if (cx88_core_debug >= level)					\
-		printk(KERN_DEBUG "%s: " fmt, core->name , ## arg);	\
-	} while(0)
+#define dprintk0(fmt, arg...)				\
+	printk(KERN_DEBUG pr_fmt("%s: core:" fmt),	\
+		__func__, ##arg)			\
+
+#define dprintk(level, fmt, arg...)	do {			\
+	if (cx88_core_debug >= level)				\
+		printk(KERN_DEBUG pr_fmt("%s: core:" fmt),	\
+		       __func__, ##arg);			\
+} while (0)
 
 static unsigned int cx88_devcount;
 static LIST_HEAD(cx88_devlist);
@@ -71,15 +72,17 @@ static DEFINE_MUTEX(devlist);
 
 #define NO_SYNC_LINE (-1U)
 
-/* @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
-	 generated _after_ lpi lines are transferred. */
-static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
-			    unsigned int offset, u32 sync_line,
-			    unsigned int bpl, unsigned int padding,
-			    unsigned int lines, unsigned int lpi, bool jump)
+/*
+ * @lpi: lines per IRQ, or 0 to not generate irqs. Note: IRQ to be
+ * generated _after_ lpi lines are transferred.
+ */
+static __le32 *cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
+			       unsigned int offset, u32 sync_line,
+			       unsigned int bpl, unsigned int padding,
+			       unsigned int lines, unsigned int lpi, bool jump)
 {
 	struct scatterlist *sg;
-	unsigned int line,todo,sol;
+	unsigned int line, todo, sol;
 
 	if (jump) {
 		(*rp++) = cpu_to_le32(RISC_JUMP);
@@ -97,33 +100,34 @@ static __le32* cx88_risc_field(__le32 *r
 			offset -= sg_dma_len(sg);
 			sg = sg_next(sg);
 		}
-		if (lpi && line>0 && !(line % lpi))
+		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) {
+		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);
-			offset+=bpl;
+			*(rp++) = cpu_to_le32(RISC_WRITE | sol |
+					      RISC_EOL | bpl);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			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);
-			todo -= (sg_dma_len(sg)-offset);
+			*(rp++) = cpu_to_le32(RISC_WRITE | sol |
+					      (sg_dma_len(sg) - offset));
+			*(rp++) = cpu_to_le32(sg_dma_address(sg) + offset);
+			todo -= (sg_dma_len(sg) - offset);
 			offset = 0;
 			sg = sg_next(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(RISC_WRITE |
+						      sg_dma_len(sg));
+				*(rp++) = cpu_to_le32(sg_dma_address(sg));
 				todo -= sg_dma_len(sg);
 				sg = sg_next(sg);
 			}
-			*(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
-			*(rp++)=cpu_to_le32(sg_dma_address(sg));
+			*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
+			*(rp++) = cpu_to_le32(sg_dma_address(sg));
 			offset += todo;
 		}
 		offset += padding;
@@ -137,41 +141,46 @@ int cx88_risc_buffer(struct pci_dev *pci
 		     unsigned int top_offset, unsigned int bottom_offset,
 		     unsigned int bpl, unsigned int padding, unsigned int lines)
 {
-	u32 instructions,fields;
+	u32 instructions, fields;
 	__le32 *rp;
 
 	fields = 0;
-	if (UNSET != top_offset)
+	if (top_offset != UNSET)
 		fields++;
-	if (UNSET != bottom_offset)
+	if (bottom_offset != UNSET)
 		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 */
-	instructions  = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
+	/*
+	 * 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
+	 */
+	instructions  = fields * (1 + ((bpl + padding) * lines) /
+				  PAGE_SIZE + lines);
 	instructions += 4;
 	risc->size = instructions * 8;
 	risc->dma = 0;
 	risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
-	if (NULL == risc->cpu)
+	if (!risc->cpu)
 		return -ENOMEM;
 
 	/* write risc instructions */
 	rp = risc->cpu;
-	if (UNSET != top_offset)
+	if (top_offset != UNSET)
 		rp = cx88_risc_field(rp, sglist, top_offset, 0,
 				     bpl, padding, lines, 0, true);
-	if (UNSET != bottom_offset)
+	if (bottom_offset != UNSET)
 		rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
-				     bpl, padding, lines, 0, top_offset == UNSET);
+				     bpl, padding, lines, 0,
+				     top_offset == UNSET);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
-	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+	WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
 	return 0;
 }
+EXPORT_SYMBOL(cx88_risc_buffer);
 
 int cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
 			 struct scatterlist *sglist, unsigned int bpl,
@@ -180,32 +189,38 @@ int cx88_risc_databuffer(struct pci_dev
 	u32 instructions;
 	__le32 *rp;
 
-	/* 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 */
+	/*
+	 * 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
+	 */
 	instructions  = 1 + (bpl * lines) / PAGE_SIZE + lines;
 	instructions += 3;
 	risc->size = instructions * 8;
 	risc->dma = 0;
 	risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
-	if (NULL == risc->cpu)
+	if (!risc->cpu)
 		return -ENOMEM;
 
 	/* write risc instructions */
 	rp = risc->cpu;
-	rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi, !lpi);
+	rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0,
+			     lines, lpi, !lpi);
 
 	/* save pointer to jmp instruction address */
 	risc->jmp = rp;
-	BUG_ON((risc->jmp - risc->cpu + 2) * sizeof (*risc->cpu) > risc->size);
+	WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
 	return 0;
 }
+EXPORT_SYMBOL(cx88_risc_databuffer);
 
-/* ------------------------------------------------------------------ */
-/* our SRAM memory layout                                             */
+/*
+ * our SRAM memory layout
+ */
 
-/* we are going to put all thr risc programs into host memory, so we
+/*
+ * we are going to put all thr risc programs into host memory, so we
  * can use the whole SDRAM for the DMA fifos.  To simplify things, we
  * use a static memory layout.  That surely will waste memory in case
  * we don't use all DMA channels at the same time (which will be the
@@ -329,12 +344,13 @@ const struct sram_channel cx88_sram_chan
 		.cnt2_reg   = MO_DMA27_CNT2,
 	},
 };
+EXPORT_SYMBOL(cx88_sram_channels);
 
 int cx88_sram_channel_setup(struct cx88_core *core,
 			    const struct sram_channel *ch,
 			    unsigned int bpl, u32 risc)
 {
-	unsigned int i,lines;
+	unsigned int i, lines;
 	u32 cdt;
 
 	bpl   = (bpl + 7) & ~7; /* alignment */
@@ -342,16 +358,16 @@ int cx88_sram_channel_setup(struct cx88_
 	lines = ch->fifo_size / bpl;
 	if (lines > 6)
 		lines = 6;
-	BUG_ON(lines < 2);
+	WARN_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, ch->fifo_start + bpl * i);
 
 	/* write CMDS */
 	cx_write(ch->cmds_start +  0, risc);
 	cx_write(ch->cmds_start +  4, cdt);
-	cx_write(ch->cmds_start +  8, (lines*16) >> 3);
+	cx_write(ch->cmds_start +  8, (lines * 16) >> 3);
 	cx_write(ch->cmds_start + 12, ch->ctrl_start);
 	cx_write(ch->cmds_start + 16, 64 >> 2);
 	for (i = 20; i < 64; i += 4)
@@ -360,12 +376,13 @@ int cx88_sram_channel_setup(struct cx88_
 	/* fill registers */
 	cx_write(ch->ptr1_reg, ch->fifo_start);
 	cx_write(ch->ptr2_reg, cdt);
-	cx_write(ch->cnt1_reg, (bpl >> 3) -1);
-	cx_write(ch->cnt2_reg, (lines*16) >> 3);
+	cx_write(ch->cnt1_reg, (bpl >> 3) - 1);
+	cx_write(ch->cnt2_reg, (lines * 16) >> 3);
 
-	dprintk(2,"sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
+	dprintk(2, "sram setup %s: bpl=%d lines=%d\n", ch->name, bpl, lines);
 	return 0;
 }
+EXPORT_SYMBOL(cx88_sram_channel_setup);
 
 /* ------------------------------------------------------------------ */
 /* debug helper code                                                  */
@@ -373,23 +390,23 @@ int cx88_sram_channel_setup(struct cx88_
 static int cx88_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",
+		[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 int const incr[16] = {
-		[ RISC_WRITE   >> 28 ] = 2,
-		[ RISC_JUMP    >> 28 ] = 2,
-		[ RISC_WRITERM >> 28 ] = 3,
-		[ RISC_WRITECM >> 28 ] = 3,
-		[ RISC_WRITECR >> 28 ] = 4,
+		[RISC_WRITE   >> 28] = 2,
+		[RISC_JUMP    >> 28] = 2,
+		[RISC_WRITERM >> 28] = 3,
+		[RISC_WRITECM >> 28] = 3,
+		[RISC_WRITECR >> 28] = 4,
 	};
 	static const char * const bits[] = {
 		"12",   "13",   "14",   "resync",
@@ -399,16 +416,15 @@ static int cx88_risc_decode(u32 risc)
 	};
 	int i;
 
-	printk("0x%08x [ %s", risc,
-	       instr[risc >> 28] ? instr[risc >> 28] : "INVALID");
-	for (i = ARRAY_SIZE(bits)-1; i >= 0; i--)
+	dprintk0("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;
 }
 
-
 void cx88_sram_channel_dump(struct cx88_core *core,
 			    const struct sram_channel *ch)
 {
@@ -426,46 +442,41 @@ void cx88_sram_channel_dump(struct cx88_
 		"line / byte",
 	};
 	u32 risc;
-	unsigned int i,j,n;
+	unsigned int i, j, n;
 
-	printk("%s: %s - dma channel status dump\n",
-	       core->name,ch->name);
+	dprintk0("%s - dma channel status dump\n", ch->name);
 	for (i = 0; i < ARRAY_SIZE(name); i++)
-		printk("%s:   cmds: %-12s: 0x%08x\n",
-		       core->name,name[i],
-		       cx_read(ch->cmds_start + 4*i));
+		dprintk0("   cmds: %-12s: 0x%08x\n",
+			 name[i], cx_read(ch->cmds_start + 4 * i));
 	for (n = 1, i = 0; i < 4; i++) {
-		risc = cx_read(ch->cmds_start + 4 * (i+11));
-		printk("%s:   risc%d: ", core->name, i);
+		risc = cx_read(ch->cmds_start + 4 * (i + 11));
+		pr_cont("  risc%d: ", i);
 		if (--n)
-			printk("0x%08x [ arg #%d ]\n", risc, n);
+			pr_cont("0x%08x [ arg #%d ]\n", risc, n);
 		else
 			n = cx88_risc_decode(risc);
 	}
 	for (i = 0; i < 16; i += n) {
 		risc = cx_read(ch->ctrl_start + 4 * i);
-		printk("%s:   iq %x: ", core->name, i);
+		dprintk0("  iq %x: ", i);
 		n = cx88_risc_decode(risc);
 		for (j = 1; j < n; j++) {
-			risc = cx_read(ch->ctrl_start + 4 * (i+j));
-			printk("%s:   iq %x: 0x%08x [ arg #%d ]\n",
-			       core->name, i+j, risc, j);
+			risc = cx_read(ch->ctrl_start + 4 * (i + j));
+			pr_cont("  iq %x: 0x%08x [ arg #%d ]\n",
+				i + j, risc, j);
 		}
 	}
 
-	printk("%s: fifo: 0x%08x -> 0x%x\n",
-	       core->name, ch->fifo_start, ch->fifo_start+ch->fifo_size);
-	printk("%s: ctrl: 0x%08x -> 0x%x\n",
-	       core->name, ch->ctrl_start, ch->ctrl_start+6*16);
-	printk("%s:   ptr1_reg: 0x%08x\n",
-	       core->name,cx_read(ch->ptr1_reg));
-	printk("%s:   ptr2_reg: 0x%08x\n",
-	       core->name,cx_read(ch->ptr2_reg));
-	printk("%s:   cnt1_reg: 0x%08x\n",
-	       core->name,cx_read(ch->cnt1_reg));
-	printk("%s:   cnt2_reg: 0x%08x\n",
-	       core->name,cx_read(ch->cnt2_reg));
+	dprintk0("fifo: 0x%08x -> 0x%x\n",
+		 ch->fifo_start, ch->fifo_start + ch->fifo_size);
+	dprintk0("ctrl: 0x%08x -> 0x%x\n",
+		 ch->ctrl_start, ch->ctrl_start + 6 * 16);
+	dprintk0("  ptr1_reg: 0x%08x\n", cx_read(ch->ptr1_reg));
+	dprintk0("  ptr2_reg: 0x%08x\n", cx_read(ch->ptr2_reg));
+	dprintk0("  cnt1_reg: 0x%08x\n", cx_read(ch->cnt1_reg));
+	dprintk0("  cnt2_reg: 0x%08x\n", cx_read(ch->cnt2_reg));
 }
+EXPORT_SYMBOL(cx88_sram_channel_dump);
 
 static const char *cx88_pci_irqs[32] = {
 	"vid", "aud", "ts", "vip", "hst", "5", "6", "tm1",
@@ -474,25 +485,26 @@ static const char *cx88_pci_irqs[32] = {
 	"i2c", "i2c_rack", "ir_smp", "gpio0", "gpio1"
 };
 
-void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
+void cx88_print_irqbits(const char *tag, const char *strings[],
 			int len, u32 bits, u32 mask)
 {
 	unsigned int i;
 
-	printk(KERN_DEBUG "%s: %s [0x%x]", name, tag, bits);
+	dprintk0("%s [0x%x]", tag, bits);
 	for (i = 0; i < len; i++) {
 		if (!(bits & (1 << i)))
 			continue;
 		if (strings[i])
-			printk(" %s", strings[i]);
+			pr_cont(" %s", strings[i]);
 		else
-			printk(" %d", i);
+			pr_cont(" %d", i);
 		if (!(mask & (1 << i)))
 			continue;
-		printk("*");
+		pr_cont("*");
 	}
-	printk("\n");
+	pr_cont("\n");
 }
+EXPORT_SYMBOL(cx88_print_irqbits);
 
 /* ------------------------------------------------------------------ */
 
@@ -505,11 +517,12 @@ int cx88_core_irq(struct cx88_core *core
 		handled++;
 	}
 	if (!handled)
-		cx88_print_irqbits(core->name, "irq pci",
+		cx88_print_irqbits("irq pci",
 				   cx88_pci_irqs, ARRAY_SIZE(cx88_pci_irqs),
 				   status, core->pci_irqmask);
 	return handled;
 }
+EXPORT_SYMBOL(cx88_core_irq);
 
 void cx88_wakeup(struct cx88_core *core,
 		 struct cx88_dmaqueue *q, u32 count)
@@ -524,6 +537,7 @@ void cx88_wakeup(struct cx88_core *core,
 	list_del(&buf->list);
 	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
 }
+EXPORT_SYMBOL(cx88_wakeup);
 
 void cx88_shutdown(struct cx88_core *core)
 {
@@ -548,10 +562,11 @@ void cx88_shutdown(struct cx88_core *cor
 	/* stop capturing */
 	cx_write(VID_CAPTURE_CONTROL, 0);
 }
+EXPORT_SYMBOL(cx88_shutdown);
 
 int cx88_reset(struct cx88_core *core)
 {
-	dprintk(1,"%s\n",__func__);
+	dprintk(1, "");
 	cx88_shutdown(core);
 
 	/* clear irq status */
@@ -563,13 +578,15 @@ int cx88_reset(struct cx88_core *core)
 	msleep(100);
 
 	/* init sram */
-	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], 720*4, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
+				720 * 4, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH22], 128, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH23], 128, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH24], 128, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH25], 128, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH26], 128, 0);
-	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28], 188*4, 0);
+	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
+				188 * 4, 0);
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH27], 128, 0);
 
 	/* misc init ... */
@@ -597,11 +614,12 @@ int cx88_reset(struct cx88_core *core)
 
 	/* Reset on-board parts */
 	cx_write(MO_SRST_IO, 0);
-	msleep(10);
+	usleep_range(10000, 20000);
 	cx_write(MO_SRST_IO, 1);
 
 	return 0;
 }
+EXPORT_SYMBOL(cx88_reset);
 
 /* ------------------------------------------------------------------ */
 
@@ -631,10 +649,11 @@ static inline unsigned int norm_fsc8(v4l
 	if (norm & V4L2_STD_NTSC) // All NTSC/M and variants
 		return 28636360;      // 3.57954545 MHz +/- 10 Hz
 
-	/* SECAM have also different sub carrier for chroma,
-	   but step_db and step_dr, at cx88_set_tvnorm already handles that.
-
-	   The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
+	/*
+	 * SECAM have also different sub carrier for chroma,
+	 * but step_db and step_dr, at cx88_set_tvnorm already handles that.
+	 *
+	 * The same FSC applies to PAL/BGDKIH, PAL/60, NTSC/4.43 and PAL/N
 	 */
 
 	return 35468950;      // 4.43361875 MHz +/- 5 Hz
@@ -642,13 +661,12 @@ static inline unsigned int norm_fsc8(v4l
 
 static inline unsigned int norm_htotal(v4l2_std_id norm)
 {
-
-	unsigned int fsc4=norm_fsc8(norm)/2;
+	unsigned int fsc4 = norm_fsc8(norm) / 2;
 
 	/* returns 4*FSC / vtotal / frames per seconds */
 	return (norm & V4L2_STD_625_50) ?
-				((fsc4+312)/625+12)/25 :
-				((fsc4+262)/525*1001+15000)/30000;
+				((fsc4 + 312) / 625 + 12) / 25 :
+				((fsc4 + 262) / 525 * 1001 + 15000) / 30000;
 }
 
 static inline unsigned int norm_vbipack(v4l2_std_id norm)
@@ -656,14 +674,14 @@ static inline unsigned int norm_vbipack(
 	return (norm & V4L2_STD_625_50) ? 511 : 400;
 }
 
-int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
-		   enum v4l2_field field)
+int cx88_set_scale(struct cx88_core *core, unsigned int width,
+		   unsigned int height, enum v4l2_field field)
 {
 	unsigned int swidth  = norm_swidth(core->tvnorm);
 	unsigned int sheight = norm_maxh(core->tvnorm);
 	u32 value;
 
-	dprintk(1,"set_scale: %dx%d [%s%s,%s]\n", width, height,
+	dprintk(1, "set_scale: %dx%d [%s%s,%s]\n", width, height,
 		V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
 		V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
 		v4l2_norm_to_name(core->tvnorm));
@@ -675,30 +693,30 @@ int cx88_set_scale(struct cx88_core *cor
 	value &= 0x3fe;
 	cx_write(MO_HDELAY_EVEN,  value);
 	cx_write(MO_HDELAY_ODD,   value);
-	dprintk(1,"set_scale: hdelay  0x%04x (width %d)\n", value,swidth);
+	dprintk(1, "set_scale: hdelay  0x%04x (width %d)\n", value, swidth);
 
 	value = (swidth * 4096 / width) - 4096;
 	cx_write(MO_HSCALE_EVEN,  value);
 	cx_write(MO_HSCALE_ODD,   value);
-	dprintk(1,"set_scale: hscale  0x%04x\n", value);
+	dprintk(1, "set_scale: hscale  0x%04x\n", value);
 
 	cx_write(MO_HACTIVE_EVEN, width);
 	cx_write(MO_HACTIVE_ODD,  width);
-	dprintk(1,"set_scale: hactive 0x%04x\n", width);
+	dprintk(1, "set_scale: hactive 0x%04x\n", width);
 
 	// recalc V scale Register (delay is constant)
 	cx_write(MO_VDELAY_EVEN, norm_vdelay(core->tvnorm));
 	cx_write(MO_VDELAY_ODD,  norm_vdelay(core->tvnorm));
-	dprintk(1,"set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
+	dprintk(1, "set_scale: vdelay  0x%04x\n", norm_vdelay(core->tvnorm));
 
 	value = (0x10000 - (sheight * 512 / height - 512)) & 0x1fff;
 	cx_write(MO_VSCALE_EVEN,  value);
 	cx_write(MO_VSCALE_ODD,   value);
-	dprintk(1,"set_scale: vscale  0x%04x\n", value);
+	dprintk(1, "set_scale: vscale  0x%04x\n", value);
 
 	cx_write(MO_VACTIVE_EVEN, sheight);
 	cx_write(MO_VACTIVE_ODD,  sheight);
-	dprintk(1,"set_scale: vactive 0x%04x\n", sheight);
+	dprintk(1, "set_scale: vactive 0x%04x\n", sheight);
 
 	// setup filters
 	value = 0;
@@ -709,7 +727,7 @@ int cx88_set_scale(struct cx88_core *cor
 	}
 	if (INPUT(core->input).type == CX88_VMUX_SVIDEO)
 		value |= (1 << 13) | (1 << 5);
-	if (V4L2_FIELD_INTERLACED == field)
+	if (field == V4L2_FIELD_INTERLACED)
 		value |= (1 << 3); // VINT (interlaced vertical scaling)
 	if (width < 385)
 		value |= (1 << 0); // 3-tap interpolation
@@ -720,10 +738,11 @@ int cx88_set_scale(struct cx88_core *cor
 
 	cx_andor(MO_FILTER_EVEN,  0x7ffc7f, value); /* preserve PEAKEN, PSEL */
 	cx_andor(MO_FILTER_ODD,   0x7ffc7f, value);
-	dprintk(1,"set_scale: filter  0x%04x\n", value);
+	dprintk(1, "set_scale: filter  0x%04x\n", value);
 
 	return 0;
 }
+EXPORT_SYMBOL(cx88_set_scale);
 
 static const u32 xtal = 28636363;
 
@@ -740,36 +759,36 @@ static int set_pll(struct cx88_core *cor
 		prescale = 5;
 
 	pll = ofreq * 8 * prescale * (u64)(1 << 20);
-	do_div(pll,xtal);
+	do_div(pll, xtal);
 	reg = (pll & 0x3ffffff) | (pre[prescale] << 26);
 	if (((reg >> 20) & 0x3f) < 14) {
-		printk("%s/0: pll out of range\n",core->name);
+		pr_err("pll out of range\n");
 		return -1;
 	}
 
-	dprintk(1,"set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
+	dprintk(1, "set_pll:    MO_PLL_REG       0x%08x [old=0x%08x,freq=%d]\n",
 		reg, cx_read(MO_PLL_REG), ofreq);
 	cx_write(MO_PLL_REG, reg);
 	for (i = 0; i < 100; i++) {
 		reg = cx_read(MO_DEVICE_STATUS);
-		if (reg & (1<<2)) {
-			dprintk(1,"pll locked [pre=%d,ofreq=%d]\n",
-				prescale,ofreq);
+		if (reg & (1 << 2)) {
+			dprintk(1, "pll locked [pre=%d,ofreq=%d]\n",
+				prescale, ofreq);
 			return 0;
 		}
-		dprintk(1,"pll not locked yet, waiting ...\n");
-		msleep(10);
+		dprintk(1, "pll not locked yet, waiting ...\n");
+		usleep_range(10000, 20000);
 	}
-	dprintk(1,"pll NOT locked [pre=%d,ofreq=%d]\n",prescale,ofreq);
+	dprintk(1, "pll NOT locked [pre=%d,ofreq=%d]\n", prescale, ofreq);
 	return -1;
 }
 
 int cx88_start_audio_dma(struct cx88_core *core)
 {
 	/* constant 128 made buzz in analog Nicam-stereo for bigger fifo_size */
-	int bpl = cx88_sram_channels[SRAM_CH25].fifo_size/4;
+	int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
 
-	int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size/AUD_RDS_LINES;
+	int rds_bpl = cx88_sram_channels[SRAM_CH27].fifo_size / AUD_RDS_LINES;
 
 	/* If downstream RISC is enabled, bail out; ALSA is managing DMA */
 	if (cx_read(MO_AUD_DMACNTRL) & 0x10)
@@ -806,8 +825,8 @@ static int set_tvaudio(struct cx88_core
 {
 	v4l2_std_id norm = core->tvnorm;
 
-	if (CX88_VMUX_TELEVISION != INPUT(core->input).type &&
-	    CX88_VMUX_CABLE != INPUT(core->input).type)
+	if (INPUT(core->input).type != CX88_VMUX_TELEVISION &&
+	    INPUT(core->input).type != CX88_VMUX_CABLE)
 		return 0;
 
 	if (V4L2_STD_PAL_BG & norm) {
@@ -822,7 +841,8 @@ static int set_tvaudio(struct cx88_core
 	} else if (V4L2_STD_SECAM_L & norm) {
 		core->tvaudio = WW_L;
 
-	} else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) & norm) {
+	} else if ((V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H) &
+		   norm) {
 		core->tvaudio = WW_BG;
 
 	} else if (V4L2_STD_SECAM_DK & norm) {
@@ -836,8 +856,8 @@ static int set_tvaudio(struct cx88_core
 		core->tvaudio = WW_EIAJ;
 
 	} else {
-		printk("%s/0: tvaudio support needs work for this tv norm [%s], sorry\n",
-		       core->name, v4l2_norm_to_name(core->tvnorm));
+		pr_info("tvaudio support needs work for this tv norm [%s], sorry\n",
+			v4l2_norm_to_name(core->tvnorm));
 		core->tvaudio = WW_NONE;
 		return 0;
 	}
@@ -847,23 +867,21 @@ static int set_tvaudio(struct cx88_core
 	/* cx88_set_stereo(dev,V4L2_TUNER_MODE_STEREO); */
 
 /*
-   This should be needed only on cx88-alsa. It seems that some cx88 chips have
-   bugs and does require DMA enabled for it to work.
+ * This should be needed only on cx88-alsa. It seems that some cx88 chips have
+ * bugs and does require DMA enabled for it to work.
  */
 	cx88_start_audio_dma(core);
 	return 0;
 }
 
-
-
 int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm)
 {
 	u32 fsc8;
 	u32 adc_clock;
 	u32 vdec_clock;
-	u32 step_db,step_dr;
+	u32 step_db, step_dr;
 	u64 tmp64;
-	u32 bdelay,agcdelay,htotal;
+	u32 bdelay, agcdelay, htotal;
 	u32 cxiformat, cxoformat;
 
 	if (norm == core->tvnorm)
@@ -912,62 +930,67 @@ int cx88_set_tvnorm(struct cx88_core *co
 		cxoformat = 0x181f0008;
 	}
 
-	dprintk(1,"set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
+	dprintk(1, "set_tvnorm: \"%s\" fsc8=%d adc=%d vdec=%d db/dr=%d/%d\n",
 		v4l2_norm_to_name(core->tvnorm), fsc8, adc_clock, vdec_clock,
 		step_db, step_dr);
-	set_pll(core,2,vdec_clock);
+	set_pll(core, 2, vdec_clock);
 
-	dprintk(1,"set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
+	dprintk(1, "set_tvnorm: MO_INPUT_FORMAT  0x%08x [old=0x%08x]\n",
 		cxiformat, cx_read(MO_INPUT_FORMAT) & 0x0f);
-	/* Chroma AGC must be disabled if SECAM is used, we enable it
-	   by default on PAL and NTSC */
+	/*
+	 * Chroma AGC must be disabled if SECAM is used, we enable it
+	 * by default on PAL and NTSC
+	 */
 	cx_andor(MO_INPUT_FORMAT, 0x40f,
 		 norm & V4L2_STD_SECAM ? cxiformat : cxiformat | 0x400);
 
 	// FIXME: as-is from DScaler
-	dprintk(1,"set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
+	dprintk(1, "set_tvnorm: MO_OUTPUT_FORMAT 0x%08x [old=0x%08x]\n",
 		cxoformat, cx_read(MO_OUTPUT_FORMAT));
 	cx_write(MO_OUTPUT_FORMAT, cxoformat);
 
 	// MO_SCONV_REG = adc clock / video dec clock * 2^17
 	tmp64  = adc_clock * (u64)(1 << 17);
 	do_div(tmp64, vdec_clock);
-	dprintk(1,"set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
+	dprintk(1, "set_tvnorm: MO_SCONV_REG     0x%08x [old=0x%08x]\n",
 		(u32)tmp64, cx_read(MO_SCONV_REG));
 	cx_write(MO_SCONV_REG, (u32)tmp64);
 
 	// MO_SUB_STEP = 8 * fsc / video dec clock * 2^22
 	tmp64  = step_db * (u64)(1 << 22);
 	do_div(tmp64, vdec_clock);
-	dprintk(1,"set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
+	dprintk(1, "set_tvnorm: MO_SUB_STEP      0x%08x [old=0x%08x]\n",
 		(u32)tmp64, cx_read(MO_SUB_STEP));
 	cx_write(MO_SUB_STEP, (u32)tmp64);
 
 	// MO_SUB_STEP_DR = 8 * 4406250 / video dec clock * 2^22
 	tmp64  = step_dr * (u64)(1 << 22);
 	do_div(tmp64, vdec_clock);
-	dprintk(1,"set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
+	dprintk(1, "set_tvnorm: MO_SUB_STEP_DR   0x%08x [old=0x%08x]\n",
 		(u32)tmp64, cx_read(MO_SUB_STEP_DR));
 	cx_write(MO_SUB_STEP_DR, (u32)tmp64);
 
 	// bdelay + agcdelay
 	bdelay   = vdec_clock * 65 / 20000000 + 21;
 	agcdelay = vdec_clock * 68 / 20000000 + 15;
-	dprintk(1,"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
-		(bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST), bdelay, agcdelay);
+	dprintk(1,
+		"set_tvnorm: MO_AGC_BURST     0x%08x [old=0x%08x,bdelay=%d,agcdelay=%d]\n",
+		(bdelay << 8) | agcdelay, cx_read(MO_AGC_BURST),
+		bdelay, agcdelay);
 	cx_write(MO_AGC_BURST, (bdelay << 8) | agcdelay);
 
 	// htotal
 	tmp64 = norm_htotal(norm) * (u64)vdec_clock;
 	do_div(tmp64, fsc8);
 	htotal = (u32)tmp64;
-	dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
+	dprintk(1,
+		"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
 		htotal, cx_read(MO_HTOTAL), (u32)tmp64);
 	cx_andor(MO_HTOTAL, 0x07ff, htotal);
 
 	// vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
 	// the effective vbi offset ~244 samples, the same as the Bt8x8
-	cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
+	cx_write(MO_VBI_PACKET, (10 << 11) | norm_vbipack(norm));
 
 	// this is needed as well to set all tvnorm parameter
 	cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
@@ -978,12 +1001,16 @@ int cx88_set_tvnorm(struct cx88_core *co
 	// tell i2c chips
 	call_all(core, video, s_std, norm);
 
-	/* The chroma_agc control should be inaccessible if the video format is SECAM */
+	/*
+	 * The chroma_agc control should be inaccessible
+	 * if the video format is SECAM
+	 */
 	v4l2_ctrl_grab(core->chroma_agc, cxiformat == VideoFormatSECAM);
 
 	// done
 	return 0;
 }
+EXPORT_SYMBOL(cx88_set_tvnorm);
 
 /* ------------------------------------------------------------------ */
 
@@ -1008,8 +1035,9 @@ void cx88_vdev_init(struct cx88_core *co
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
 		 core->name, type, core->board.name);
 }
+EXPORT_SYMBOL(cx88_vdev_init);
 
-struct cx88_core* cx88_core_get(struct pci_dev *pci)
+struct cx88_core *cx88_core_get(struct pci_dev *pci)
 {
 	struct cx88_core *core;
 
@@ -1020,7 +1048,7 @@ struct cx88_core* cx88_core_get(struct p
 		if (PCI_SLOT(pci->devfn) != core->pci_slot)
 			continue;
 
-		if (0 != cx88_get_resources(core, pci)) {
+		if (cx88_get_resources(core, pci) != 0) {
 			mutex_unlock(&devlist);
 			return NULL;
 		}
@@ -1030,7 +1058,7 @@ struct cx88_core* cx88_core_get(struct p
 	}
 
 	core = cx88_core_create(pci, cx88_devcount);
-	if (NULL != core) {
+	if (core) {
 		cx88_devcount++;
 		list_add_tail(&core->devlist, &cx88_devlist);
 	}
@@ -1038,18 +1066,19 @@ struct cx88_core* cx88_core_get(struct p
 	mutex_unlock(&devlist);
 	return core;
 }
+EXPORT_SYMBOL(cx88_core_get);
 
 void cx88_core_put(struct cx88_core *core, struct pci_dev *pci)
 {
-	release_mem_region(pci_resource_start(pci,0),
-			   pci_resource_len(pci,0));
+	release_mem_region(pci_resource_start(pci, 0),
+			   pci_resource_len(pci, 0));
 
 	if (!atomic_dec_and_test(&core->refcount))
 		return;
 
 	mutex_lock(&devlist);
 	cx88_ir_fini(core);
-	if (0 == core->i2c_rc) {
+	if (core->i2c_rc == 0) {
 		if (core->i2c_rtc)
 			i2c_unregister_device(core->i2c_rtc);
 		i2c_del_adapter(&core->i2c_adap);
@@ -1063,29 +1092,4 @@ void cx88_core_put(struct cx88_core *cor
 	v4l2_device_unregister(&core->v4l2_dev);
 	kfree(core);
 }
-
-/* ------------------------------------------------------------------ */
-
-EXPORT_SYMBOL(cx88_print_irqbits);
-
-EXPORT_SYMBOL(cx88_core_irq);
-EXPORT_SYMBOL(cx88_wakeup);
-EXPORT_SYMBOL(cx88_reset);
-EXPORT_SYMBOL(cx88_shutdown);
-
-EXPORT_SYMBOL(cx88_risc_buffer);
-EXPORT_SYMBOL(cx88_risc_databuffer);
-
-EXPORT_SYMBOL(cx88_sram_channels);
-EXPORT_SYMBOL(cx88_sram_channel_setup);
-EXPORT_SYMBOL(cx88_sram_channel_dump);
-
-EXPORT_SYMBOL(cx88_set_tvnorm);
-EXPORT_SYMBOL(cx88_set_scale);
-
-EXPORT_SYMBOL(cx88_vdev_init);
-EXPORT_SYMBOL(cx88_core_get);
 EXPORT_SYMBOL(cx88_core_put);
-
-EXPORT_SYMBOL(cx88_ir_start);
-EXPORT_SYMBOL(cx88_ir_stop);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-dsp.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-dsp.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-dsp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-dsp.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,4 @@
 /*
- *
  *  Stereo and SAP detection for cx88
  *
  *  Copyright (c) 2009 Marton Balint <cus@fazekas.hu>
@@ -13,41 +12,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., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "cx88.h"
+#include "cx88-reg.h"
+
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <asm/div64.h>
 
-#include "cx88.h"
-#include "cx88-reg.h"
-
 #define INT_PI			((s32)(3.141592653589 * 32768.0))
 
 #define compat_remainder(a, b) \
-	 ((float)(((s32)((a)*100))%((s32)((b)*100)))/100.0)
+	 ((float)(((s32)((a) * 100)) % ((s32)((b) * 100))) / 100.0)
 
 #define baseband_freq(carrier, srate, tone) ((s32)( \
 	 (compat_remainder(carrier + tone, srate)) / srate * 2 * INT_PI))
 
-/* We calculate the baseband frequencies of the carrier and the pilot tones
- * based on the the sampling rate of the audio rds fifo. */
+/*
+ * We calculate the baseband frequencies of the carrier and the pilot tones
+ * based on the the sampling rate of the audio rds fifo.
+ */
 
 #define FREQ_A2_CARRIER         baseband_freq(54687.5, 2689.36, 0.0)
 #define FREQ_A2_DUAL            baseband_freq(54687.5, 2689.36, 274.1)
 #define FREQ_A2_STEREO          baseband_freq(54687.5, 2689.36, 117.5)
 
-/* The frequencies below are from the reference driver. They probably need
+/*
+ * The frequencies below are from the reference driver. They probably need
  * further adjustments, because they are not tested at all. You may even need
  * to play a bit with the registers of the chip to select the proper signal
  * for the input of the audio rds fifo, and measure it's sampling rate to
- * calculate the proper baseband frequencies... */
+ * calculate the proper baseband frequencies...
+ */
 
 #define FREQ_A2M_CARRIER	((s32)(2.114516 * 32768.0))
 #define FREQ_A2M_DUAL		((s32)(2.754916 * 32768.0))
@@ -71,43 +70,52 @@ static unsigned int dsp_debug;
 module_param(dsp_debug, int, 0644);
 MODULE_PARM_DESC(dsp_debug, "enable audio dsp debug messages");
 
-#define dprintk(level, fmt, arg...)	if (dsp_debug >= level) \
-	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+#define dprintk(level, fmt, arg...) do {				\
+	if (dsp_debug >= level)						\
+		printk(KERN_DEBUG pr_fmt("%s: dsp:" fmt),		\
+			__func__, ##arg);				\
+} while (0)
 
 static s32 int_cos(u32 x)
 {
 	u32 t2, t4, t6, t8;
 	s32 ret;
 	u16 period = x / INT_PI;
+
 	if (period % 2)
 		return -int_cos(x - INT_PI);
 	x = x % INT_PI;
-	if (x > INT_PI/2)
-		return -int_cos(INT_PI/2 - (x % (INT_PI/2)));
-	/* Now x is between 0 and INT_PI/2.
-	 * To calculate cos(x) we use it's Taylor polinom. */
-	t2 = x*x/32768/2;
-	t4 = t2*x/32768*x/32768/3/4;
-	t6 = t4*x/32768*x/32768/5/6;
-	t8 = t6*x/32768*x/32768/7/8;
-	ret = 32768-t2+t4-t6+t8;
+	if (x > INT_PI / 2)
+		return -int_cos(INT_PI / 2 - (x % (INT_PI / 2)));
+	/*
+	 * Now x is between 0 and INT_PI/2.
+	 * To calculate cos(x) we use it's Taylor polinom.
+	 */
+	t2 = x * x / 32768 / 2;
+	t4 = t2 * x / 32768 * x / 32768 / 3 / 4;
+	t6 = t4 * x / 32768 * x / 32768 / 5 / 6;
+	t8 = t6 * x / 32768 * x / 32768 / 7 / 8;
+	ret = 32768 - t2 + t4 - t6 + t8;
 	return ret;
 }
 
 static u32 int_goertzel(s16 x[], u32 N, u32 freq)
 {
-	/* We use the Goertzel algorithm to determine the power of the
-	 * given frequency in the signal */
+	/*
+	 * We use the Goertzel algorithm to determine the power of the
+	 * given frequency in the signal
+	 */
 	s32 s_prev = 0;
 	s32 s_prev2 = 0;
-	s32 coeff = 2*int_cos(freq);
+	s32 coeff = 2 * int_cos(freq);
 	u32 i;
 
 	u64 tmp;
 	u32 divisor;
 
 	for (i = 0; i < N; i++) {
-		s32 s = x[i] + ((s64)coeff*s_prev/32768) - s_prev2;
+		s32 s = x[i] + ((s64)coeff * s_prev / 32768) - s_prev2;
+
 		s_prev2 = s_prev;
 		s_prev = s;
 	}
@@ -115,17 +123,20 @@ static u32 int_goertzel(s16 x[], u32 N,
 	tmp = (s64)s_prev2 * s_prev2 + (s64)s_prev * s_prev -
 		      (s64)coeff * s_prev2 * s_prev / 32768;
 
-	/* XXX: N must be low enough so that N*N fits in s32.
-	 * Else we need two divisions. */
+	/*
+	 * XXX: N must be low enough so that N*N fits in s32.
+	 * Else we need two divisions.
+	 */
 	divisor = N * N;
 	do_div(tmp, divisor);
 
-	return (u32) tmp;
+	return (u32)tmp;
 }
 
 static u32 freq_magnitude(s16 x[], u32 N, u32 freq)
 {
 	u32 sum = int_goertzel(x, N, freq);
+
 	return (u32)int_sqrt(sum);
 }
 
@@ -138,7 +149,7 @@ static u32 noise_magnitude(s16 x[], u32
 
 	if (N > 192) {
 		/* The last 192 samples are enough for noise detection */
-		x += (N-192);
+		x += (N - 192);
 		N = 192;
 	}
 
@@ -176,8 +187,8 @@ static s32 detect_a2_a2m_eiaj(struct cx8
 		dual_freq = FREQ_EIAJ_DUAL;
 		break;
 	default:
-		printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
-		       core->name, core->tvaudio, __func__);
+		pr_warn("unsupported audio mode %d for %s\n",
+			core->tvaudio, __func__);
 		return UNSET;
 	}
 
@@ -186,8 +197,9 @@ static s32 detect_a2_a2m_eiaj(struct cx8
 	dual    = freq_magnitude(x, N, dual_freq);
 	noise   = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);
 
-	dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
-		   "noise=%d\n", carrier, stereo, dual, noise);
+	dprintk(1,
+		"detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, noise=%d\n",
+		carrier, stereo, dual, noise);
 
 	if (stereo > dual)
 		ret = V4L2_TUNER_SUB_STEREO;
@@ -196,20 +208,22 @@ static s32 detect_a2_a2m_eiaj(struct cx8
 
 	if (core->tvaudio == WW_EIAJ) {
 		/* EIAJ checks may need adjustments */
-		if ((carrier > max(stereo, dual)*2) &&
-		    (carrier < max(stereo, dual)*6) &&
+		if ((carrier > max(stereo, dual) * 2) &&
+		    (carrier < max(stereo, dual) * 6) &&
 		    (carrier > 20 && carrier < 200) &&
 		    (max(stereo, dual) > min(stereo, dual))) {
-			/* For EIAJ the carrier is always present,
-			   so we probably don't need noise detection */
+			/*
+			 * For EIAJ the carrier is always present,
+			 * so we probably don't need noise detection
+			 */
 			return ret;
 		}
 	} else {
-		if ((carrier > max(stereo, dual)*2) &&
-		    (carrier < max(stereo, dual)*8) &&
+		if ((carrier > max(stereo, dual) * 2) &&
+		    (carrier < max(stereo, dual) * 8) &&
 		    (carrier > 20 && carrier < 200) &&
 		    (noise < 10) &&
-		    (max(stereo, dual) > min(stereo, dual)*2)) {
+		    (max(stereo, dual) > min(stereo, dual) * 2)) {
 			return ret;
 		}
 	}
@@ -222,8 +236,9 @@ static s32 detect_btsc(struct cx88_core
 	s32 sap = freq_magnitude(x, N, FREQ_BTSC_SAP);
 	s32 dual_ref = freq_magnitude(x, N, FREQ_BTSC_DUAL_REF);
 	s32 dual = freq_magnitude(x, N, FREQ_BTSC_DUAL);
-	dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d"
-		   "\n", dual_ref, dual, sap_ref, sap);
+
+	dprintk(1, "detect btsc: dual_ref=%d, dual=%d, sap_ref=%d, sap=%d\n",
+		dual_ref, dual, sap_ref, sap);
 	/* FIXME: Currently not supported */
 	return UNSET;
 }
@@ -234,36 +249,31 @@ static s16 *read_rds_samples(struct cx88
 	s16 *samples;
 
 	unsigned int i;
-	unsigned int bpl = srch->fifo_size/AUD_RDS_LINES;
-	unsigned int spl = bpl/4;
-	unsigned int sample_count = spl*(AUD_RDS_LINES-1);
+	unsigned int bpl = srch->fifo_size / AUD_RDS_LINES;
+	unsigned int spl = bpl / 4;
+	unsigned int sample_count = spl * (AUD_RDS_LINES - 1);
 
 	u32 current_address = cx_read(srch->ptr1_reg);
 	u32 offset = (current_address - srch->fifo_start + bpl);
 
-	dprintk(1, "read RDS samples: current_address=%08x (offset=%08x), "
-		"sample_count=%d, aud_intstat=%08x\n", current_address,
+	dprintk(1,
+		"read RDS samples: current_address=%08x (offset=%08x), sample_count=%d, aud_intstat=%08x\n",
+		current_address,
 		current_address - srch->fifo_start, sample_count,
 		cx_read(MO_AUD_INTSTAT));
-
-	samples = kmalloc(sizeof(s16)*sample_count, GFP_KERNEL);
+	samples = kmalloc_array(sample_count, sizeof(*samples), GFP_KERNEL);
 	if (!samples)
 		return NULL;
 
 	*N = sample_count;
 
 	for (i = 0; i < sample_count; i++)  {
-		offset = offset % (AUD_RDS_LINES*bpl);
+		offset = offset % (AUD_RDS_LINES * bpl);
 		samples[i] = cx_read(srch->fifo_start + offset);
 		offset += 4;
 	}
 
-	if (dsp_debug >= 2) {
-		dprintk(2, "RDS samples dump: ");
-		for (i = 0; i < sample_count; i++)
-			printk("%hd ", samples[i]);
-		printk(".\n");
-	}
+	dprintk(2, "RDS samples dump: %*ph\n", sample_count, samples);
 
 	return samples;
 }
@@ -310,11 +320,11 @@ s32 cx88_dsp_detect_stereo_sap(struct cx
 
 	kfree(samples);
 
-	if (UNSET != ret)
+	if (ret != UNSET)
 		dprintk(1, "stereo/sap detection result:%s%s%s\n",
-			   (ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
-			   (ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
-			   (ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
+			(ret & V4L2_TUNER_SUB_MONO) ? " mono" : "",
+			(ret & V4L2_TUNER_SUB_STEREO) ? " stereo" : "",
+			(ret & V4L2_TUNER_SUB_LANG2) ? " dual" : "");
 
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-dvb.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-dvb.c	2016-12-11 17:43:41.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-dvb.c	2017-02-12 17:28:08.000000000 -0500
@@ -1,5 +1,4 @@
 /*
- *
  * device driver for Conexant 2388x based TV cards
  * MPEG Transport Stream (DVB) routines
  *
@@ -15,12 +14,11 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 "cx88.h"
+#include "dvb-pll.h"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -29,8 +27,6 @@
 #include <linux/file.h>
 #include <linux/suspend.h>
 
-#include "cx88.h"
-#include "dvb-pll.h"
 #include <media/v4l2-common.h>
 
 #include "mt352.h"
@@ -69,7 +65,7 @@ MODULE_VERSION(CX88_VERSION);
 
 static unsigned int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug,"enable debug messages [dvb]");
+MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
 
 static unsigned int dvb_buf_tscnt = 32;
 module_param(dvb_buf_tscnt, int, 0644);
@@ -77,14 +73,17 @@ MODULE_PARM_DESC(dvb_buf_tscnt, "DVB Buf
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-#define dprintk(level,fmt, arg...)	if (debug >= level) \
-	printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg)
+#define dprintk(level, fmt, arg...) do {				\
+	if (debug >= level)						\
+		printk(KERN_DEBUG pr_fmt("%s: dvb:" fmt),		\
+			__func__, ##arg);				\
+} while (0)
 
 /* ------------------------------------------------------------------ */
 
 static int queue_setup(struct vb2_queue *q,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], struct device *alloc_devs[])
+		       unsigned int *num_buffers, unsigned int *num_planes,
+		       unsigned int sizes[], struct device *alloc_devs[])
 {
 	struct cx8802_dev *dev = q->drv_priv;
 
@@ -169,23 +168,23 @@ static const struct vb2_ops dvb_qops = {
 
 /* ------------------------------------------------------------------ */
 
-static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
+static int cx88_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
 	struct cx8802_driver *drv = NULL;
 	int ret = 0;
 	int fe_id;
 
 	fe_id = vb2_dvb_find_frontend(&dev->frontends, fe);
 	if (!fe_id) {
-		printk(KERN_ERR "%s() No frontend found\n", __func__);
+		pr_err("%s() No frontend found\n", __func__);
 		return -EINVAL;
 	}
 
 	mutex_lock(&dev->core->lock);
 	drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
 	if (drv) {
-		if (acquire){
+		if (acquire) {
 			dev->frontends.active_fe_id = fe_id;
 			ret = drv->request_acquire(drv);
 		} else {
@@ -222,13 +221,13 @@ static void cx88_dvb_gate_ctrl(struct cx
 
 /* ------------------------------------------------------------------ */
 
-static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
+static int dvico_fusionhdtv_demod_init(struct dvb_frontend *fe)
 {
-	static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
-	static const u8 reset []         = { RESET,      0x80 };
-	static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
-	static const u8 agc_cfg []       = { AGC_TARGET, 0x24, 0x20 };
-	static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+	static const u8 clock_config[]  = { CLOCK_CTL,  0x38, 0x39 };
+	static const u8 reset[]         = { RESET,      0x80 };
+	static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1,  0x40 };
+	static const u8 agc_cfg[]       = { AGC_TARGET, 0x24, 0x20 };
+	static const u8 gpp_ctl_cfg[]   = { GPP_CTL,    0x33 };
 	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
 
 	mt352_write(fe, clock_config,   sizeof(clock_config));
@@ -244,11 +243,11 @@ static int dvico_fusionhdtv_demod_init(s
 
 static int dvico_dual_demod_init(struct dvb_frontend *fe)
 {
-	static const u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
-	static const u8 reset []         = { RESET,      0x80 };
-	static const u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
-	static const u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
-	static const u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+	static const u8 clock_config[]  = { CLOCK_CTL,  0x38, 0x38 };
+	static const u8 reset[]         = { RESET,      0x80 };
+	static const u8 adc_ctl_1_cfg[] = { ADC_CTL_1,  0x40 };
+	static const u8 agc_cfg[]       = { AGC_TARGET, 0x28, 0x20 };
+	static const u8 gpp_ctl_cfg[]   = { GPP_CTL,    0x33 };
 	static const u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
 
 	mt352_write(fe, clock_config,   sizeof(clock_config));
@@ -263,12 +262,12 @@ static int dvico_dual_demod_init(struct
 	return 0;
 }
 
-static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
+static int dntv_live_dvbt_demod_init(struct dvb_frontend *fe)
 {
-	static const u8 clock_config []  = { 0x89, 0x38, 0x39 };
-	static const u8 reset []         = { 0x50, 0x80 };
-	static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-	static const u8 agc_cfg []       = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
+	static const u8 clock_config[]  = { 0x89, 0x38, 0x39 };
+	static const u8 reset[]         = { 0x50, 0x80 };
+	static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 };
+	static const u8 agc_cfg[]       = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
 				       0x00, 0xFF, 0x00, 0x40, 0x40 };
 	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
 	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
@@ -312,12 +311,12 @@ static struct mb86a16_config twinhan_vp1
 };
 
 #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054)
-static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
+static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend *fe)
 {
-	static const u8 clock_config []  = { 0x89, 0x38, 0x38 };
-	static const u8 reset []         = { 0x50, 0x80 };
-	static const u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
-	static const u8 agc_cfg []       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
+	static const u8 clock_config[]  = { 0x89, 0x38, 0x38 };
+	static const u8 reset[]         = { 0x50, 0x80 };
+	static const u8 adc_ctl_1_cfg[] = { 0x8E, 0x40 };
+	static const u8 agc_cfg[]       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
 				       0x00, 0xFF, 0x00, 0x40, 0x40 };
 	static const u8 dntv_extra[]     = { 0xB5, 0x7A };
 	static const u8 capt_range_cfg[] = { 0x75, 0x32 };
@@ -374,9 +373,10 @@ static const struct cx22702_config haupp
 	.output_mode   = CX22702_SERIAL_OUTPUT,
 };
 
-static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+static int or51132_set_ts_param(struct dvb_frontend *fe, int is_punctured)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
+
 	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
 	return 0;
 }
@@ -386,9 +386,9 @@ static const struct or51132_config pchdt
 	.set_ts_params = or51132_set_ts_param,
 };
 
-static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
+static int lgdt330x_pll_rf_set(struct dvb_frontend *fe, int index)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
 	struct cx88_core *core = dev->core;
 
 	dprintk(1, "%s: index = %d\n", __func__, index);
@@ -399,9 +399,10 @@ static int lgdt330x_pll_rf_set(struct dv
 	return 0;
 }
 
-static int lgdt330x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+static int lgdt330x_set_ts_param(struct dvb_frontend *fe, int is_punctured)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
+
 	if (is_punctured)
 		dev->ts_gen_cntrl |= 0x04;
 	else
@@ -430,9 +431,10 @@ static const struct lgdt330x_config pchd
 	.set_ts_params = lgdt330x_set_ts_param,
 };
 
-static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
+static int nxt200x_set_ts_param(struct dvb_frontend *fe, int is_punctured)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
+
 	dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
 	return 0;
 }
@@ -442,18 +444,19 @@ static const struct nxt200x_config ati_h
 	.set_ts_params = nxt200x_set_ts_param,
 };
 
-static int cx24123_set_ts_param(struct dvb_frontend* fe,
-	int is_punctured)
+static int cx24123_set_ts_param(struct dvb_frontend *fe,
+				int is_punctured)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
+
 	dev->ts_gen_cntrl = 0x02;
 	return 0;
 }
 
-static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
+static int kworld_dvbs_100_set_voltage(struct dvb_frontend *fe,
 				       enum fe_sec_voltage voltage)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
 	struct cx88_core *core = dev->core;
 
 	if (voltage == SEC_VOLTAGE_OFF)
@@ -469,11 +472,11 @@ static int kworld_dvbs_100_set_voltage(s
 static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe,
 				      enum fe_sec_voltage voltage)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
 	struct cx88_core *core = dev->core;
 
 	if (voltage == SEC_VOLTAGE_OFF) {
-		dprintk(1,"LNB Voltage OFF\n");
+		dprintk(1, "LNB Voltage OFF\n");
 		cx_write(MO_GP0_IO, 0x0000efff);
 	}
 
@@ -485,7 +488,7 @@ static int geniatech_dvbs_set_voltage(st
 static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
 				  enum fe_sec_voltage voltage)
 {
-	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx8802_dev *dev = fe->dvb->priv;
 	struct cx88_core *core = dev->core;
 
 	cx_set(MO_GP0_IO, 0x6040);
@@ -625,9 +628,7 @@ static int attach_xc3028(u8 addr, struct
 		return -EINVAL;
 
 	if (!fe0->dvb.frontend) {
-		printk(KERN_ERR "%s/2: dvb frontend not attached. "
-				"Can't attach xc3028\n",
-		       dev->core->name);
+		pr_err("dvb frontend not attached. Can't attach xc3028\n");
 		return -EINVAL;
 	}
 
@@ -640,16 +641,14 @@ static int attach_xc3028(u8 addr, struct
 
 	fe = dvb_attach(xc2028_attach, fe0->dvb.frontend, &cfg);
 	if (!fe) {
-		printk(KERN_ERR "%s/2: xc3028 attach failed\n",
-		       dev->core->name);
+		pr_err("xc3028 attach failed\n");
 		dvb_frontend_detach(fe0->dvb.frontend);
 		dvb_unregister_frontend(fe0->dvb.frontend);
 		fe0->dvb.frontend = NULL;
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "%s/2: xc3028 attached\n",
-	       dev->core->name);
+	pr_info("xc3028 attached\n");
 
 	return 0;
 }
@@ -665,41 +664,40 @@ static int attach_xc4000(struct cx8802_d
 		return -EINVAL;
 
 	if (!fe0->dvb.frontend) {
-		printk(KERN_ERR "%s/2: dvb frontend not attached. "
-				"Can't attach xc4000\n",
-		       dev->core->name);
+		pr_err("dvb frontend not attached. Can't attach xc4000\n");
 		return -EINVAL;
 	}
 
 	fe = dvb_attach(xc4000_attach, fe0->dvb.frontend, &dev->core->i2c_adap,
 			cfg);
 	if (!fe) {
-		printk(KERN_ERR "%s/2: xc4000 attach failed\n",
-		       dev->core->name);
+		pr_err("xc4000 attach failed\n");
 		dvb_frontend_detach(fe0->dvb.frontend);
 		dvb_unregister_frontend(fe0->dvb.frontend);
 		fe0->dvb.frontend = NULL;
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO "%s/2: xc4000 attached\n", dev->core->name);
+	pr_info("xc4000 attached\n");
 
 	return 0;
 }
 
 static int cx24116_set_ts_param(struct dvb_frontend *fe,
-	int is_punctured)
+				int is_punctured)
 {
 	struct cx8802_dev *dev = fe->dvb->priv;
+
 	dev->ts_gen_cntrl = 0x2;
 
 	return 0;
 }
 
 static int stv0900_set_ts_param(struct dvb_frontend *fe,
-	int is_punctured)
+				int is_punctured)
 {
 	struct cx8802_dev *dev = fe->dvb->priv;
+
 	dev->ts_gen_cntrl = 0;
 
 	return 0;
@@ -713,10 +711,10 @@ static int cx24116_reset_device(struct d
 	/* Reset the part */
 	/* Put the cx24116 into reset */
 	cx_write(MO_SRST_IO, 0);
-	msleep(10);
+	usleep_range(10000, 20000);
 	/* Take the cx24116 out of reset */
 	cx_write(MO_SRST_IO, 1);
-	msleep(10);
+	usleep_range(10000, 20000);
 
 	return 0;
 }
@@ -734,9 +732,10 @@ static const struct cx24116_config tevii
 };
 
 static int ds3000_set_ts_param(struct dvb_frontend *fe,
-	int is_punctured)
+			       int is_punctured)
 {
 	struct cx8802_dev *dev = fe->dvb->priv;
+
 	dev->ts_gen_cntrl = 4;
 
 	return 0;
@@ -800,12 +799,12 @@ static int cx8802_alloc_frontends(struct
 	if (!core->board.num_frontends)
 		return -ENODEV;
 
-	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
-			 core->board.num_frontends);
+	pr_info("%s: allocating %d frontend(s)\n", __func__,
+		core->board.num_frontends);
 	for (i = 1; i <= core->board.num_frontends; i++) {
 		fe = vb2_dvb_alloc_frontend(&dev->frontends, i);
 		if (!fe) {
-			printk(KERN_ERR "%s() failed to alloc\n", __func__);
+			pr_err("%s() failed to alloc\n", __func__);
 			vb2_dvb_dealloc_frontends(&dev->frontends);
 			return -ENOMEM;
 		}
@@ -813,8 +812,6 @@ static int cx8802_alloc_frontends(struct
 	return 0;
 }
 
-
-
 static const u8 samsung_smt_7020_inittab[] = {
 	     0x01, 0x15,
 	     0x02, 0x00,
@@ -866,7 +863,6 @@ static const u8 samsung_smt_7020_inittab
 	     0xff, 0xff,
 };
 
-
 static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe)
 {
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -899,7 +895,7 @@ static int samsung_smt_7020_tuner_set_pa
 }
 
 static int samsung_smt_7020_set_tone(struct dvb_frontend *fe,
-	enum fe_sec_tone_mode tone)
+				     enum fe_sec_tone_mode tone)
 {
 	struct cx8802_dev *dev = fe->dvb->priv;
 	struct cx88_core *core = dev->core;
@@ -954,7 +950,7 @@ static int samsung_smt_7020_set_voltage(
 }
 
 static int samsung_smt_7020_stv0299_set_symbol_rate(struct dvb_frontend *fe,
-	u32 srate, u32 ratio)
+						    u32 srate, u32 ratio)
 {
 	u8 aclk = 0;
 	u8 bclk = 0;
@@ -988,7 +984,6 @@ static int samsung_smt_7020_stv0299_set_
 	return 0;
 }
 
-
 static const struct stv0299_config samsung_stv0299_config = {
 	.demod_address = 0x68,
 	.inittab = samsung_smt_7020_inittab,
@@ -1008,8 +1003,8 @@ static int dvb_register(struct cx8802_de
 	int mfe_shared = 0; /* bus not shared by default */
 	int res = -EINVAL;
 
-	if (0 != core->i2c_rc) {
-		printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name);
+	if (core->i2c_rc != 0) {
+		pr_err("no i2c-bus available, cannot attach dvb drivers\n");
 		goto frontend_detach;
 	}
 
@@ -1030,7 +1025,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
 					       &connexant_refboard_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, &core->i2c_adap,
 					DVB_PLL_THOMSON_DTT759X))
@@ -1044,7 +1039,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
 					       &connexant_refboard_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x60, &core->i2c_adap,
 					DVB_PLL_THOMSON_DTT7579))
@@ -1058,10 +1053,10 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
 					       &hauppauge_hvr_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-				   &core->i2c_adap, 0x61,
-				   TUNER_PHILIPS_FMD1216ME_MK3))
+					&core->i2c_adap, 0x61,
+					TUNER_PHILIPS_FMD1216ME_MK3))
 				goto frontend_detach;
 		}
 		break;
@@ -1069,10 +1064,10 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(cx22702_attach,
 					       &hauppauge_hvr_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-				   &core->i2c_adap, 0x61,
-				   TUNER_PHILIPS_FMD1216MEX_MK3))
+					&core->i2c_adap, 0x61,
+					TUNER_PHILIPS_FMD1216MEX_MK3))
 				goto frontend_detach;
 		}
 		break;
@@ -1082,8 +1077,8 @@ static int dvb_register(struct cx8802_de
 		dev->frontends.gate = 2;
 		/* DVB-S init */
 		fe0->dvb.frontend = dvb_attach(cx24123_attach,
-					&hauppauge_novas_config,
-					&dev->core->i2c_adap);
+					       &hauppauge_novas_config,
+					       &dev->core->i2c_adap);
 		if (fe0->dvb.frontend) {
 			if (!dvb_attach(isl6421_attach,
 					fe0->dvb.frontend,
@@ -1097,8 +1092,8 @@ static int dvb_register(struct cx8802_de
 			goto frontend_detach;
 		/* DVB-T init */
 		fe1->dvb.frontend = dvb_attach(cx22702_attach,
-					&hauppauge_hvr_config,
-					&dev->core->i2c_adap);
+					       &hauppauge_hvr_config,
+					       &dev->core->i2c_adap);
 		if (fe1->dvb.frontend) {
 			fe1->dvb.frontend->id = 1;
 			if (!dvb_attach(simple_tuner_attach,
@@ -1112,7 +1107,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dvico_fusionhdtv,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
@@ -1122,19 +1117,21 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_plus_v1_1,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x60, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
 		}
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
-		/* The tin box says DEE1601, but it seems to be DTT7579
-		 * compatible, with a slightly different MT352 AGC gain. */
+		/*
+		 * The tin box says DEE1601, but it seems to be DTT7579
+		 * compatible, with a slightly different MT352 AGC gain.
+		 */
 		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dvico_fusionhdtv_dual,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
@@ -1144,7 +1141,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_plus_v1_1,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_THOMSON_DTT7579))
 				goto frontend_detach;
@@ -1154,7 +1151,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dvico_fusionhdtv,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_LG_Z201))
 				goto frontend_detach;
@@ -1166,7 +1163,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(mt352_attach,
 					       &dntv_live_dvbt_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend,
 					0x61, NULL, DVB_PLL_UNKNOWN_1))
 				goto frontend_detach;
@@ -1175,27 +1172,27 @@ static int dvb_register(struct cx8802_de
 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 #if IS_ENABLED(CONFIG_VIDEO_CX88_VP3054)
 		/* MT352 is on a secondary I2C bus made from some GPIO lines */
-		fe0->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
+		fe0->dvb.frontend = dvb_attach(mt352_attach,
+					       &dntv_live_dvbt_pro_config,
 					       &dev->vp3054->adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_PHILIPS_FMD1216ME_MK3))
 				goto frontend_detach;
 		}
 #else
-		printk(KERN_ERR "%s/2: built without vp3054 support\n",
-				core->name);
+		pr_err("built without vp3054 support\n");
 #endif
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_hybrid,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
-				   &core->i2c_adap, 0x61,
-				   TUNER_THOMSON_FE6600))
+					&core->i2c_adap, 0x61,
+					TUNER_THOMSON_FE6600))
 				goto frontend_detach;
 		}
 		break;
@@ -1203,7 +1200,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(zl10353_attach,
 					       &dvico_fusionhdtv_xc3028,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend == NULL)
+		if (!fe0->dvb.frontend)
 			fe0->dvb.frontend = dvb_attach(mt352_attach,
 						&dvico_fusionhdtv_mt352_xc3028,
 						&core->i2c_adap);
@@ -1220,7 +1217,7 @@ static int dvb_register(struct cx8802_de
 	case CX88_BOARD_PCHDTV_HD3000:
 		fe0->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_THOMSON_DTT761X))
@@ -1241,7 +1238,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &fusionhdtv_3_gold,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_MICROTUNE_4042FI5))
@@ -1259,7 +1256,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &fusionhdtv_3_gold,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_THOMSON_DTT761X))
@@ -1277,13 +1274,13 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &fusionhdtv_5_gold,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_LG_TDVS_H06XF))
 				goto frontend_detach;
 			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
-				   &core->i2c_adap, 0x43))
+					&core->i2c_adap, 0x43))
 				goto frontend_detach;
 		}
 		break;
@@ -1298,13 +1295,13 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
 					       &pchdtv_hd5500,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_LG_TDVS_H06XF))
 				goto frontend_detach;
 			if (!dvb_attach(tda9887_attach, fe0->dvb.frontend,
-				   &core->i2c_adap, 0x43))
+					&core->i2c_adap, 0x43))
 				goto frontend_detach;
 		}
 		break;
@@ -1312,7 +1309,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(nxt200x_attach,
 					       &ati_hdtvwonder,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
 					&core->i2c_adap, 0x61,
 					TUNER_PHILIPS_TUV1236D))
@@ -1333,8 +1330,8 @@ static int dvb_register(struct cx8802_de
 				override_tone = false;
 
 			if (!dvb_attach(isl6421_attach, fe0->dvb.frontend,
-					&core->i2c_adap, 0x08, ISL6421_DCL, 0x00,
-					override_tone))
+					&core->i2c_adap, 0x08, ISL6421_DCL,
+					0x00, override_tone))
 				goto frontend_detach;
 		}
 		break;
@@ -1360,7 +1357,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 					       &pinnacle_pctv_hd_800i_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
 					&core->i2c_adap,
 					&pinnacle_pctv_hd_800i_tuner_config))
@@ -1369,9 +1366,9 @@ static int dvb_register(struct cx8802_de
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO:
 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
-						&dvico_hdtv5_pci_nano_config,
-						&core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+					       &dvico_hdtv5_pci_nano_config,
+					       &core->i2c_adap);
+		if (fe0->dvb.frontend) {
 			struct dvb_frontend *fe;
 			struct xc2028_config cfg = {
 				.i2c_adap  = &core->i2c_adap,
@@ -1385,7 +1382,7 @@ static int dvb_register(struct cx8802_de
 
 			fe = dvb_attach(xc2028_attach,
 					fe0->dvb.frontend, &cfg);
-			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
+			if (fe && fe->ops.tuner_ops.set_config)
 				fe->ops.tuner_ops.set_config(fe, &ctl);
 		}
 		break;
@@ -1427,7 +1424,7 @@ static int dvb_register(struct cx8802_de
 		if (attach_xc3028(0x61, dev) < 0)
 			goto frontend_detach;
 		break;
-	 case CX88_BOARD_KWORLD_ATSC_120:
+	case CX88_BOARD_KWORLD_ATSC_120:
 		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
 					       &kworld_atsc_120_config,
 					       &core->i2c_adap);
@@ -1438,7 +1435,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
 					       &dvico_fusionhdtv7_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(xc5000_attach, fe0->dvb.frontend,
 					&core->i2c_adap,
 					&dvico_fusionhdtv7_tuner_config))
@@ -1451,8 +1448,8 @@ static int dvb_register(struct cx8802_de
 		dev->frontends.gate = 2;
 		/* DVB-S/S2 Init */
 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
-					&hauppauge_hvr4000_config,
-					&dev->core->i2c_adap);
+					       &hauppauge_hvr4000_config,
+					       &dev->core->i2c_adap);
 		if (fe0->dvb.frontend) {
 			if (!dvb_attach(isl6421_attach,
 					fe0->dvb.frontend,
@@ -1466,8 +1463,8 @@ static int dvb_register(struct cx8802_de
 			goto frontend_detach;
 		/* DVB-T Init */
 		fe1->dvb.frontend = dvb_attach(cx22702_attach,
-					&hauppauge_hvr_config,
-					&dev->core->i2c_adap);
+					       &hauppauge_hvr_config,
+					       &dev->core->i2c_adap);
 		if (fe1->dvb.frontend) {
 			fe1->dvb.frontend->id = 1;
 			if (!dvb_attach(simple_tuner_attach,
@@ -1479,8 +1476,8 @@ static int dvb_register(struct cx8802_de
 		break;
 	case CX88_BOARD_HAUPPAUGE_HVR4000LITE:
 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
-					&hauppauge_hvr4000_config,
-					&dev->core->i2c_adap);
+					       &hauppauge_hvr4000_config,
+					       &dev->core->i2c_adap);
 		if (fe0->dvb.frontend) {
 			if (!dvb_attach(isl6421_attach,
 					fe0->dvb.frontend,
@@ -1495,7 +1492,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(stv0299_attach,
 						&tevii_tuner_sharp_config,
 						&core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
 					&core->i2c_adap, DVB_PLL_OPERA1))
 				goto frontend_detach;
@@ -1506,8 +1503,9 @@ static int dvb_register(struct cx8802_de
 			fe0->dvb.frontend = dvb_attach(stv0288_attach,
 							    &tevii_tuner_earda_config,
 							    &core->i2c_adap);
-			if (fe0->dvb.frontend != NULL) {
-				if (!dvb_attach(stb6000_attach, fe0->dvb.frontend, 0x61,
+			if (fe0->dvb.frontend) {
+				if (!dvb_attach(stb6000_attach,
+						fe0->dvb.frontend, 0x61,
 						&core->i2c_adap))
 					goto frontend_detach;
 				core->prev_set_voltage = fe0->dvb.frontend->ops.set_voltage;
@@ -1519,16 +1517,16 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
 					       &tevii_s460_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL)
+		if (fe0->dvb.frontend)
 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 		break;
 	case CX88_BOARD_TEVII_S464:
 		fe0->dvb.frontend = dvb_attach(ds3000_attach,
 						&tevii_ds3000_config,
 						&core->i2c_adap);
-		if (fe0->dvb.frontend != NULL) {
+		if (fe0->dvb.frontend) {
 			dvb_attach(ts2020_attach, fe0->dvb.frontend,
-				&tevii_ts2020_config, &core->i2c_adap);
+				   &tevii_ts2020_config, &core->i2c_adap);
 			fe0->dvb.frontend->ops.set_voltage =
 							tevii_dvbs_set_voltage;
 		}
@@ -1540,7 +1538,7 @@ static int dvb_register(struct cx8802_de
 		fe0->dvb.frontend = dvb_attach(cx24116_attach,
 					       &hauppauge_hvr4000_config,
 					       &core->i2c_adap);
-		if (fe0->dvb.frontend != NULL)
+		if (fe0->dvb.frontend)
 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 		break;
 	case CX88_BOARD_TERRATEC_CINERGY_HT_PCI_MKII:
@@ -1557,9 +1555,9 @@ static int dvb_register(struct cx8802_de
 		struct dvb_tuner_ops *tuner_ops = NULL;
 
 		fe0->dvb.frontend = dvb_attach(stv0900_attach,
-						&prof_7301_stv0900_config,
-						&core->i2c_adap, 0);
-		if (fe0->dvb.frontend != NULL) {
+					       &prof_7301_stv0900_config,
+					       &core->i2c_adap, 0);
+		if (fe0->dvb.frontend) {
 			if (!dvb_attach(stb6100_attach, fe0->dvb.frontend,
 					&prof_7301_stb6100_config,
 					&core->i2c_adap))
@@ -1589,8 +1587,8 @@ static int dvb_register(struct cx8802_de
 		mdelay(200);
 
 		fe0->dvb.frontend = dvb_attach(stv0299_attach,
-					&samsung_stv0299_config,
-					&dev->core->i2c_adap);
+					       &samsung_stv0299_config,
+					       &dev->core->i2c_adap);
 		if (fe0->dvb.frontend) {
 			fe0->dvb.frontend->ops.tuner_ops.set_params =
 				samsung_smt_7020_tuner_set_params;
@@ -1606,8 +1604,8 @@ static int dvb_register(struct cx8802_de
 	case CX88_BOARD_TWINHAN_VP1027_DVBS:
 		dev->ts_gen_cntrl = 0x00;
 		fe0->dvb.frontend = dvb_attach(mb86a16_attach,
-						&twinhan_vp1027,
-						&core->i2c_adap);
+					       &twinhan_vp1027,
+					       &core->i2c_adap);
 		if (fe0->dvb.frontend) {
 			core->prev_set_voltage =
 					fe0->dvb.frontend->ops.set_voltage;
@@ -1617,15 +1615,12 @@ static int dvb_register(struct cx8802_de
 		break;
 
 	default:
-		printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
-		       core->name);
+		pr_err("The frontend of your DVB/ATSC card isn't supported yet\n");
 		break;
 	}
 
-	if ( (NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend) ) {
-		printk(KERN_ERR
-		       "%s/2: frontend initialization failed\n",
-		       core->name);
+	if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
+		pr_err("frontend initialization failed\n");
 		goto frontend_detach;
 	}
 	/* define general-purpose callback pointer */
@@ -1660,7 +1655,8 @@ static int cx8802_dvb_advise_acquire(str
 {
 	struct cx88_core *core = drv->core;
 	int err = 0;
-	dprintk( 1, "%s\n", __func__);
+
+	dprintk(1, "%s\n", __func__);
 
 	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -1724,7 +1720,8 @@ static int cx8802_dvb_advise_release(str
 {
 	struct cx88_core *core = drv->core;
 	int err = 0;
-	dprintk( 1, "%s\n", __func__);
+
+	dprintk(1, "%s\n", __func__);
 
 	switch (core->boardnr) {
 	case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -1747,8 +1744,8 @@ static int cx8802_dvb_probe(struct cx880
 	struct vb2_dvb_frontend *fe;
 	int i;
 
-	dprintk( 1, "%s\n", __func__);
-	dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
+	dprintk(1, "%s\n", __func__);
+	dprintk(1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
 		core->boardnr,
 		core->name,
 		core->pci_bus,
@@ -1760,25 +1757,25 @@ static int cx8802_dvb_probe(struct cx880
 
 	/* If vp3054 isn't enabled, a stub will just return 0 */
 	err = vp3054_i2c_probe(dev);
-	if (0 != err)
+	if (err != 0)
 		goto fail_core;
 
 	/* dvb stuff */
-	printk(KERN_INFO "%s/2: cx2388x based DVB/ATSC card\n", core->name);
+	pr_info("cx2388x based DVB/ATSC card\n");
 	dev->ts_gen_cntrl = 0x0c;
 
 	err = cx8802_alloc_frontends(dev);
 	if (err)
 		goto fail_core;
 
-	err = -ENODEV;
 	for (i = 1; i <= core->board.num_frontends; i++) {
 		struct vb2_queue *q;
 
 		fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i);
-		if (fe == NULL) {
-			printk(KERN_ERR "%s() failed to get frontend(%d)\n",
-					__func__, i);
+		if (!fe) {
+			pr_err("%s() failed to get frontend(%d)\n",
+			       __func__, i);
+			err = -ENODEV;
 			goto fail_probe;
 		}
 		q = &fe->dvb.dvbq;
@@ -1805,8 +1802,7 @@ static int cx8802_dvb_probe(struct cx880
 	err = dvb_register(dev);
 	if (err)
 		/* frontends/adapter de-allocated in dvb_register */
-		printk(KERN_ERR "%s/2: dvb_register failed (err = %d)\n",
-		       core->name, err);
+		pr_err("dvb_register failed (err = %d)\n", err);
 	return err;
 fail_probe:
 	vb2_dvb_dealloc_frontends(&core->dvbdev->frontends);
@@ -1819,7 +1815,7 @@ static int cx8802_dvb_remove(struct cx88
 	struct cx88_core *core = drv->core;
 	struct cx8802_dev *dev = drv->core->dvbdev;
 
-	dprintk( 1, "%s\n", __func__);
+	dprintk(1, "%s\n", __func__);
 
 	vb2_dvb_unregister_bus(&dev->frontends);
 
@@ -1841,8 +1837,7 @@ static struct cx8802_driver cx8802_dvb_d
 
 static int __init dvb_init(void)
 {
-	printk(KERN_INFO "cx88/2: cx2388x dvb driver version %s loaded\n",
-	       CX88_VERSION);
+	pr_info("cx2388x dvb driver version %s loaded\n", CX88_VERSION);
 	return cx8802_register_driver(&cx8802_dvb_driver);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88.h linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88.h
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,4 @@
 /*
- *
  * v4l2 device driver for cx2388x based TV cards
  *
  * (c) 2003,04 Gerd Knorr <kraxel@bytesex.org> [SUSE Labs]
@@ -13,12 +12,13 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 CX88_H
+#define CX88_H
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/pci.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
@@ -53,7 +53,7 @@
 /* defines and enums                                           */
 
 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM/LC */
-#define CX88_NORMS (V4L2_STD_ALL 		\
+#define CX88_NORMS (V4L2_STD_ALL		\
 		    & ~V4L2_STD_PAL_H		\
 		    & ~V4L2_STD_NTSC_M_KR	\
 		    & ~V4L2_STD_SECAM_LC)
@@ -98,7 +98,6 @@ static inline unsigned int norm_maxw(v4l
 	return 720;
 }
 
-
 static inline unsigned int norm_maxh(v4l2_std_id norm)
 {
 	return (norm & V4L2_STD_525_60) ? 480 : 576;
@@ -140,6 +139,7 @@ struct sram_channel {
 	u32  cnt1_reg;
 	u32  cnt2_reg;
 };
+
 extern const struct sram_channel cx88_sram_channels[];
 
 /* ----------------------------------------------------------- */
@@ -361,12 +361,12 @@ struct cx88_core {
 	u32                        i2c_state, i2c_rc;
 
 	/* config info -- analog */
-	struct v4l2_device 	   v4l2_dev;
+	struct v4l2_device	   v4l2_dev;
 	struct v4l2_ctrl_handler   video_hdl;
 	struct v4l2_ctrl	   *chroma_agc;
 	struct v4l2_ctrl_handler   audio_hdl;
 	struct v4l2_subdev	   *sd_wm8775;
-	struct i2c_client 	   *i2c_rtc;
+	struct i2c_client	   *i2c_rtc;
 	unsigned int               boardnr;
 	struct cx88_board	   board;
 
@@ -383,8 +383,8 @@ struct cx88_core {
 	/* state info */
 	struct task_struct         *kthread;
 	v4l2_std_id                tvnorm;
-	unsigned		   width, height;
-	unsigned		   field;
+	unsigned int		   width, height;
+	unsigned int		   field;
 	enum cx88_tvaudio          tvaudio;
 	u32                        audiomode_manual;
 	u32                        audiomode_current;
@@ -427,7 +427,8 @@ static inline struct cx88_core *to_core(
 		if (!core->i2c_rc) {				\
 			if (core->gate_ctrl)			\
 				core->gate_ctrl(core, 1);	\
-			v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
+			v4l2_device_call_all(&core->v4l2_dev,	\
+					     grpid, o, f, ##args); \
 			if (core->gate_ctrl)			\
 				core->gate_ctrl(core, 0);	\
 		}						\
@@ -438,31 +439,31 @@ static inline struct cx88_core *to_core(
 #define WM8775_GID      (1 << 0)
 
 #define wm8775_s_ctrl(core, id, val) \
-	do {									\
-		struct v4l2_ctrl *ctrl_ =					\
-			v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);	\
-		if (ctrl_ && !core->i2c_rc) {					\
-			if (core->gate_ctrl)					\
-				core->gate_ctrl(core, 1);			\
-			v4l2_ctrl_s_ctrl(ctrl_, val);				\
-			if (core->gate_ctrl)					\
-				core->gate_ctrl(core, 0);			\
-		}								\
+	do {								\
+		struct v4l2_ctrl *ctrl_ =				\
+			v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);\
+		if (ctrl_ && !core->i2c_rc) {				\
+			if (core->gate_ctrl)				\
+				core->gate_ctrl(core, 1);		\
+			v4l2_ctrl_s_ctrl(ctrl_, val);			\
+			if (core->gate_ctrl)				\
+				core->gate_ctrl(core, 0);		\
+		}							\
 	} while (0)
 
 #define wm8775_g_ctrl(core, id) \
-	({									\
-		struct v4l2_ctrl *ctrl_ =					\
-			v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);	\
-		s32 val = 0;							\
-		if (ctrl_ && !core->i2c_rc) {					\
-			if (core->gate_ctrl)					\
-				core->gate_ctrl(core, 1);			\
-			val = v4l2_ctrl_g_ctrl(ctrl_);				\
-			if (core->gate_ctrl)					\
-				core->gate_ctrl(core, 0);			\
-		}								\
-		val;								\
+	({								\
+		struct v4l2_ctrl *ctrl_ =				\
+			v4l2_ctrl_find(core->sd_wm8775->ctrl_handler, id);\
+		s32 val = 0;						\
+		if (ctrl_ && !core->i2c_rc) {				\
+			if (core->gate_ctrl)				\
+				core->gate_ctrl(core, 1);		\
+			val = v4l2_ctrl_g_ctrl(ctrl_);			\
+			if (core->gate_ctrl)				\
+				core->gate_ctrl(core, 0);		\
+		}							\
+		val;							\
 	})
 
 /* ----------------------------------------------------------- */
@@ -484,7 +485,7 @@ struct cx8800_dev {
 
 	/* pci i/o */
 	struct pci_dev             *pci;
-	unsigned char              pci_rev,pci_lat;
+	unsigned char              pci_rev, pci_lat;
 
 	const struct cx8800_fmt    *fmt;
 
@@ -504,7 +505,6 @@ struct cx8800_dev {
 /* function 1: audio/alsa stuff                                */
 /* =============> moved to cx88-alsa.c <====================== */
 
-
 /* ----------------------------------------------------------- */
 /* function 2: mpeg stuff                                      */
 
@@ -547,7 +547,7 @@ struct cx8802_dev {
 
 	/* pci i/o */
 	struct pci_dev             *pci;
-	unsigned char              pci_rev,pci_lat;
+	unsigned char              pci_rev, pci_lat;
 
 	/* dma queues */
 	struct cx88_dmaqueue       mpegq;
@@ -566,6 +566,7 @@ struct cx8802_dev {
 
 	/* mpeg params */
 	struct cx2341x_handler     cxhdl;
+
 #endif
 
 #if IS_ENABLED(CONFIG_VIDEO_CX88_DVB)
@@ -588,40 +589,42 @@ struct cx8802_dev {
 
 /* ----------------------------------------------------------- */
 
-#define cx_read(reg)             readl(core->lmmio + ((reg)>>2))
-#define cx_write(reg,value)      writel((value), core->lmmio + ((reg)>>2))
-#define cx_writeb(reg,value)     writeb((value), core->bmmio + (reg))
+#define cx_read(reg)             readl(core->lmmio + ((reg) >> 2))
+#define cx_write(reg, value)     writel((value), core->lmmio + ((reg) >> 2))
+#define cx_writeb(reg, value)    writeb((value), core->bmmio + (reg))
 
-#define cx_andor(reg,mask,value) \
-  writel((readl(core->lmmio+((reg)>>2)) & ~(mask)) |\
-  ((value) & (mask)), core->lmmio+((reg)>>2))
-#define cx_set(reg,bit)          cx_andor((reg),(bit),(bit))
-#define cx_clear(reg,bit)        cx_andor((reg),(bit),0)
+#define cx_andor(reg, mask, value) \
+	writel((readl(core->lmmio + ((reg) >> 2)) & ~(mask)) |\
+	((value) & (mask)), core->lmmio + ((reg) >> 2))
+#define cx_set(reg, bit)         cx_andor((reg), (bit), (bit))
+#define cx_clear(reg, bit)       cx_andor((reg), (bit), 0)
 
 #define cx_wait(d) { if (need_resched()) schedule(); else udelay(d); }
 
 /* shadow registers */
 #define cx_sread(sreg)		    (core->shadow[sreg])
-#define cx_swrite(sreg,reg,value) \
-  (core->shadow[sreg] = value, \
-   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
-#define cx_sandor(sreg,reg,mask,value) \
-  (core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | ((value) & (mask)), \
-   writel(core->shadow[sreg], core->lmmio + ((reg)>>2)))
+#define cx_swrite(sreg, reg, value) \
+	(core->shadow[sreg] = value, \
+	writel(core->shadow[sreg], core->lmmio + ((reg) >> 2)))
+#define cx_sandor(sreg, reg, mask, value) \
+	(core->shadow[sreg] = (core->shadow[sreg] & ~(mask)) | \
+			       ((value) & (mask)), \
+				writel(core->shadow[sreg], \
+				       core->lmmio + ((reg) >> 2)))
 
 /* ----------------------------------------------------------- */
 /* cx88-core.c                                                 */
 
 extern unsigned int cx88_core_debug;
 
-extern void cx88_print_irqbits(const char *name, const char *tag, const char *strings[],
-			       int len, u32 bits, u32 mask);
+void cx88_print_irqbits(const char *tag, const char *strings[],
+			int len, u32 bits, u32 mask);
 
-extern int cx88_core_irq(struct cx88_core *core, u32 status);
-extern void cx88_wakeup(struct cx88_core *core,
-			struct cx88_dmaqueue *q, u32 count);
-extern void cx88_shutdown(struct cx88_core *core);
-extern int cx88_reset(struct cx88_core *core);
+int cx88_core_irq(struct cx88_core *core, u32 status);
+void cx88_wakeup(struct cx88_core *core,
+		 struct cx88_dmaqueue *q, u32 count);
+void cx88_shutdown(struct cx88_core *core);
+int cx88_reset(struct cx88_core *core);
 
 extern int
 cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
@@ -633,43 +636,37 @@ cx88_risc_databuffer(struct pci_dev *pci
 		     struct scatterlist *sglist, unsigned int bpl,
 		     unsigned int lines, unsigned int lpi);
 
-extern void cx88_risc_disasm(struct cx88_core *core,
-			     struct cx88_riscmem *risc);
-extern int cx88_sram_channel_setup(struct cx88_core *core,
-				   const struct sram_channel *ch,
-				   unsigned int bpl, u32 risc);
-extern void cx88_sram_channel_dump(struct cx88_core *core,
-				   const struct sram_channel *ch);
-
-extern int cx88_set_scale(struct cx88_core *core, unsigned int width,
-			  unsigned int height, enum v4l2_field field);
-extern int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
+void cx88_risc_disasm(struct cx88_core *core,
+		      struct cx88_riscmem *risc);
+int cx88_sram_channel_setup(struct cx88_core *core,
+			    const struct sram_channel *ch,
+			    unsigned int bpl, u32 risc);
+void cx88_sram_channel_dump(struct cx88_core *core,
+			    const struct sram_channel *ch);
 
-extern void cx88_vdev_init(struct cx88_core *core,
-			   struct pci_dev *pci,
-			   struct video_device *vfd,
-			   const struct video_device *template_,
-			   const char *type);
-extern struct cx88_core *cx88_core_get(struct pci_dev *pci);
-extern void cx88_core_put(struct cx88_core *core,
-			  struct pci_dev *pci);
+int cx88_set_scale(struct cx88_core *core, unsigned int width,
+		   unsigned int height, enum v4l2_field field);
+int cx88_set_tvnorm(struct cx88_core *core, v4l2_std_id norm);
 
-extern int cx88_start_audio_dma(struct cx88_core *core);
-extern int cx88_stop_audio_dma(struct cx88_core *core);
+void cx88_vdev_init(struct cx88_core *core,
+		    struct pci_dev *pci,
+		    struct video_device *vfd,
+		    const struct video_device *template_,
+		    const char *type);
+struct cx88_core *cx88_core_get(struct pci_dev *pci);
+void cx88_core_put(struct cx88_core *core,
+		   struct pci_dev *pci);
 
+int cx88_start_audio_dma(struct cx88_core *core);
+int cx88_stop_audio_dma(struct cx88_core *core);
 
 /* ----------------------------------------------------------- */
 /* cx88-vbi.c                                                  */
 
 /* Can be used as g_vbi_fmt, try_vbi_fmt and s_vbi_fmt */
-int cx8800_vbi_fmt (struct file *file, void *priv,
-					struct v4l2_format *f);
+int cx8800_vbi_fmt(struct file *file, void *priv,
+		   struct v4l2_format *f);
 
-/*
-int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
-			 struct cx88_dmaqueue *q,
-			 struct cx88_buffer   *buf);
-*/
 void cx8800_stop_vbi_dma(struct cx8800_dev *dev);
 int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q);
 
@@ -678,17 +675,16 @@ extern const struct vb2_ops cx8800_vbi_q
 /* ----------------------------------------------------------- */
 /* cx88-i2c.c                                                  */
 
-extern int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
-
+int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci);
 
 /* ----------------------------------------------------------- */
 /* cx88-cards.c                                                */
 
-extern int cx88_tuner_callback(void *dev, int component, int command, int arg);
-extern int cx88_get_resources(const struct cx88_core *core,
-			      struct pci_dev *pci);
-extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
-extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
+int cx88_tuner_callback(void *dev, int component, int command, int arg);
+int cx88_get_resources(const struct cx88_core *core,
+		       struct pci_dev *pci);
+struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr);
+void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl);
 
 /* ----------------------------------------------------------- */
 /* cx88-tvaudio.c                                              */
@@ -703,7 +699,8 @@ int cx8802_register_driver(struct cx8802
 int cx8802_unregister_driver(struct cx8802_driver *drv);
 
 /* Caller must hold core->lock */
-struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
+struct cx8802_driver *cx8802_get_driver(struct cx8802_dev *dev,
+					enum cx88_board_type btype);
 
 /* ----------------------------------------------------------- */
 /* cx88-dsp.c                                                  */
@@ -718,18 +715,18 @@ int cx88_ir_fini(struct cx88_core *core)
 void cx88_ir_irq(struct cx88_core *core);
 int cx88_ir_start(struct cx88_core *core);
 void cx88_ir_stop(struct cx88_core *core);
-extern void cx88_i2c_init_ir(struct cx88_core *core);
+void cx88_i2c_init_ir(struct cx88_core *core);
 
 /* ----------------------------------------------------------- */
 /* cx88-mpeg.c                                                 */
 
 int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
-			struct cx88_buffer *buf);
+		       struct cx88_buffer *buf);
 void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
 void cx8802_cancel_buffers(struct cx8802_dev *dev);
 int cx8802_start_dma(struct cx8802_dev    *dev,
-			    struct cx88_dmaqueue *q,
-			    struct cx88_buffer   *buf);
+		     struct cx88_dmaqueue *q,
+		     struct cx88_buffer   *buf);
 
 /* ----------------------------------------------------------- */
 /* cx88-video.c*/
@@ -737,4 +734,6 @@ int cx88_enum_input(struct cx88_core *co
 int cx88_set_freq(struct cx88_core  *core, const struct v4l2_frequency *f);
 int cx88_video_mux(struct cx88_core *core, unsigned int input);
 void cx88_querycap(struct file *file, struct cx88_core *core,
-		struct v4l2_capability *cap);
+		   struct v4l2_capability *cap);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-i2c.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,55 +1,53 @@
 
 /*
+ *
+ * cx88-i2c.c  --  all the i2c code is here
+ *
+ * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
+ *			   & Marcus Metzler (mocm@thp.uni-koeln.de)
+ * (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
+ * (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
+ *
+ * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *	- Multituner support and i2c address binding
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-    cx88-i2c.c  --  all the i2c code is here
-
-    Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
-			   & Marcus Metzler (mocm@thp.uni-koeln.de)
-    (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
-    (c) 1999-2003 Gerd Knorr <kraxel@bytesex.org>
-
-    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
-	- Multituner support and i2c address binding
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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 "cx88.h"
 
-#include <linux/module.h>
 #include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
 
-#include <asm/io.h>
-
-#include "cx88.h"
 #include <media/v4l2-common.h>
 
 static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
+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");
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
 static unsigned int i2c_udelay = 5;
 module_param(i2c_udelay, int, 0644);
-MODULE_PARM_DESC(i2c_udelay,"i2c delay at insmod time, in usecs "
-		"(should be 5 or higher). Lower value means higher bus speed.");
+MODULE_PARM_DESC(i2c_udelay,
+		 "i2c delay at insmod time, in usecs (should be 5 or higher). Lower value means higher bus speed.");
 
-#define dprintk(level,fmt, arg...)	if (i2c_debug >= level) \
-	printk(KERN_DEBUG "%s: " fmt, core->name , ## arg)
+#define dprintk(level, fmt, arg...) do {				\
+	if (i2c_debug >= level)						\
+		printk(KERN_DEBUG pr_fmt("%s: i2c:" fmt),		\
+			__func__, ##arg);				\
+} while (0)
 
 /* ----------------------------------------------------------------------- */
 
@@ -109,26 +107,26 @@ static const struct i2c_algo_bit_data cx
 /* ----------------------------------------------------------------------- */
 
 static const char * const i2c_devs[128] = {
-	[ 0x1c >> 1 ] = "lgdt330x",
-	[ 0x86 >> 1 ] = "tda9887/cx22702",
-	[ 0xa0 >> 1 ] = "eeprom",
-	[ 0xc0 >> 1 ] = "tuner (analog)",
-	[ 0xc2 >> 1 ] = "tuner (analog/dvb)",
-	[ 0xc8 >> 1 ] = "xc5000",
+	[0x1c >> 1] = "lgdt330x",
+	[0x86 >> 1] = "tda9887/cx22702",
+	[0xa0 >> 1] = "eeprom",
+	[0xc0 >> 1] = "tuner (analog)",
+	[0xc2 >> 1] = "tuner (analog/dvb)",
+	[0xc8 >> 1] = "xc5000",
 };
 
 static void do_i2c_scan(const char *name, struct i2c_client *c)
 {
 	unsigned char buf;
-	int i,rc;
+	int i, rc;
 
 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
 		c->addr = i;
-		rc = i2c_master_recv(c,&buf,0);
+		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("i2c scan: found device @ 0x%x  [%s]\n",
+			i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 }
 
@@ -136,14 +134,13 @@ static void do_i2c_scan(const char *name
 int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci)
 {
 	/* Prevents usage of invalid delay values */
-	if (i2c_udelay<5)
-		i2c_udelay=5;
+	if (i2c_udelay < 5)
+		i2c_udelay = 5;
 
 	core->i2c_algo = cx8800_i2c_algo_template;
 
-
 	core->i2c_adap.dev.parent = &pci->dev;
-	strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name));
+	strlcpy(core->i2c_adap.name, core->name, sizeof(core->i2c_adap.name));
 	core->i2c_adap.owner = THIS_MODULE;
 	core->i2c_algo.udelay = i2c_udelay;
 	core->i2c_algo.data = core;
@@ -152,32 +149,35 @@ int cx88_i2c_init(struct cx88_core *core
 	core->i2c_client.adapter = &core->i2c_adap;
 	strlcpy(core->i2c_client.name, "cx88xx internal", I2C_NAME_SIZE);
 
-	cx8800_bit_setscl(core,1);
-	cx8800_bit_setsda(core,1);
+	cx8800_bit_setscl(core, 1);
+	cx8800_bit_setsda(core, 1);
 
 	core->i2c_rc = i2c_bit_add_bus(&core->i2c_adap);
-	if (0 == core->i2c_rc) {
-		static u8 tuner_data[] =
-			{ 0x0b, 0xdc, 0x86, 0x52 };
-		static struct i2c_msg tuner_msg =
-			{ .flags = 0, .addr = 0xc2 >> 1, .buf = tuner_data, .len = 4 };
+	if (core->i2c_rc == 0) {
+		static u8 tuner_data[] = {
+			0x0b, 0xdc, 0x86, 0x52 };
+		static struct i2c_msg tuner_msg = {
+			.flags = 0,
+			.addr = 0xc2 >> 1,
+			.buf = tuner_data,
+			.len = 4
+		};
 
 		dprintk(1, "i2c register ok\n");
-		switch( core->boardnr ) {
-			case CX88_BOARD_HAUPPAUGE_HVR1300:
-			case CX88_BOARD_HAUPPAUGE_HVR3000:
-			case CX88_BOARD_HAUPPAUGE_HVR4000:
-				printk("%s: i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n",
-					core->name);
-				i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
-				break;
-			default:
-				break;
+		switch (core->boardnr) {
+		case CX88_BOARD_HAUPPAUGE_HVR1300:
+		case CX88_BOARD_HAUPPAUGE_HVR3000:
+		case CX88_BOARD_HAUPPAUGE_HVR4000:
+			pr_info("i2c init: enabling analog demod on HVR1300/3000/4000 tuner\n");
+			i2c_transfer(core->i2c_client.adapter, &tuner_msg, 1);
+			break;
+		default:
+			break;
 		}
 		if (i2c_scan)
-			do_i2c_scan(core->name,&core->i2c_client);
+			do_i2c_scan(core->name, &core->i2c_client);
 	} else
-		printk("%s: i2c register FAILED\n", core->name);
+		pr_err("i2c register FAILED\n");
 
 	return core->i2c_rc;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-input.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-input.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-input.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-input.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,19 +16,16 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 "cx88.h"
+
 #include <linux/init.h>
 #include <linux/hrtimer.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 
-#include "cx88.h"
 #include <media/rc-core.h>
 
 #define MODULE_NAME "cx88xx"
@@ -57,7 +54,7 @@ struct cx88_IR {
 	u32 mask_keyup;
 };
 
-static unsigned ir_samplerate = 4;
+static unsigned int ir_samplerate = 4;
 module_param(ir_samplerate, uint, 0444);
 MODULE_PARM_DESC(ir_samplerate, "IR samplerate in kHz, 1 - 20, default 4");
 
@@ -65,11 +62,15 @@ static int ir_debug;
 module_param(ir_debug, int, 0644);	/* debug level [IR] */
 MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
 
-#define ir_dprintk(fmt, arg...)	if (ir_debug) \
-	printk(KERN_DEBUG "%s IR: " fmt , ir->core->name , ##arg)
+#define ir_dprintk(fmt, arg...)	do {					\
+	if (ir_debug)							\
+		printk(KERN_DEBUG "%s IR: " fmt, ir->core->name, ##arg);\
+} while (0)
 
-#define dprintk(fmt, arg...)	if (ir_debug) \
-	printk(KERN_DEBUG "cx88 IR: " fmt , ##arg)
+#define dprintk(fmt, arg...) do {					\
+	if (ir_debug)							\
+		printk(KERN_DEBUG "cx88 IR: " fmt, ##arg);		\
+} while (0)
 
 /* ---------------------------------------------------------------------- */
 
@@ -82,21 +83,22 @@ static void cx88_ir_handle_key(struct cx
 	gpio = cx_read(ir->gpio_addr);
 	switch (core->boardnr) {
 	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
-		/* This board apparently uses a combination of 2 GPIO
-		   to represent the keys. Additionally, the second GPIO
-		   can be used for parity.
-
-		   Example:
-
-		   for key "5"
-			gpio = 0x758, auxgpio = 0xe5 or 0xf5
-		   for key "Power"
-			gpio = 0x758, auxgpio = 0xed or 0xfd
+		/*
+		 * This board apparently uses a combination of 2 GPIO
+		 * to represent the keys. Additionally, the second GPIO
+		 * can be used for parity.
+		 *
+		 * Example:
+		 *
+		 * for key "5"
+		 *	gpio = 0x758, auxgpio = 0xe5 or 0xf5
+		 * for key "Power"
+		 *	gpio = 0x758, auxgpio = 0xed or 0xfd
 		 */
 
 		auxgpio = cx_read(MO_GP1_IO);
 		/* Take out the parity part */
-		gpio=(gpio & 0x7fd) + (auxgpio & 0xef);
+		gpio = (gpio & 0x7fd) + (auxgpio & 0xef);
 		break;
 	case CX88_BOARD_WINFAST_DTV1000:
 	case CX88_BOARD_WINFAST_DTV1800H:
@@ -145,7 +147,7 @@ static void cx88_ir_handle_key(struct cx
 
 		if (0 == (gpio & ir->mask_keyup))
 			rc_keydown_notimeout(ir->dev, RC_TYPE_NECX, scancode,
-									0);
+					     0);
 		else
 			rc_keyup(ir->dev);
 
@@ -176,8 +178,7 @@ static enum hrtimer_restart cx88_ir_work
 	struct cx88_IR *ir = container_of(timer, struct cx88_IR, timer);
 
 	cx88_ir_handle_key(ir);
-	missed = hrtimer_forward_now(&ir->timer,
-				     ktime_set(0, ir->polling * 1000000));
+	missed = hrtimer_forward_now(&ir->timer, ir->polling * 1000000);
 	if (missed > 1)
 		ir_dprintk("Missed ticks %ld\n", missed - 1);
 
@@ -197,8 +198,7 @@ static int __cx88_ir_start(void *priv)
 	if (ir->polling) {
 		hrtimer_init(&ir->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 		ir->timer.function = cx88_ir_work;
-		hrtimer_start(&ir->timer,
-			      ktime_set(0, ir->polling * 1000000),
+		hrtimer_start(&ir->timer, ir->polling * 1000000,
 			      HRTIMER_MODE_REL);
 	}
 	if (ir->sampling) {
@@ -234,12 +234,14 @@ int cx88_ir_start(struct cx88_core *core
 
 	return 0;
 }
+EXPORT_SYMBOL(cx88_ir_start);
 
 void cx88_ir_stop(struct cx88_core *core)
 {
 	if (core->ir->users)
 		__cx88_ir_stop(core);
 }
+EXPORT_SYMBOL(cx88_ir_stop);
 
 static int cx88_ir_open(struct rc_dev *rc)
 {
@@ -511,7 +513,7 @@ int cx88_ir_fini(struct cx88_core *core)
 	struct cx88_IR *ir = core->ir;
 
 	/* skip detach on non attached boards */
-	if (NULL == ir)
+	if (!ir)
 		return 0;
 
 	cx88_ir_stop(core);
@@ -529,7 +531,7 @@ void cx88_ir_irq(struct cx88_core *core)
 {
 	struct cx88_IR *ir = core->ir;
 	u32 samples;
-	unsigned todo, bits;
+	unsigned int todo, bits;
 	struct ir_raw_event ev;
 
 	if (!ir || !ir->sampling)
@@ -579,7 +581,7 @@ static int get_key_pvr2000(struct IR_i2c
 	}
 
 	dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
-		   code & 0xff, flags & 0xff);
+		code & 0xff, flags & 0xff);
 
 	*protocol = RC_TYPE_UNKNOWN;
 	*scancode = code & 0xff;
@@ -601,7 +603,7 @@ void cx88_i2c_init_ir(struct cx88_core *
 	const unsigned short *addr_list = default_addr_list;
 	const unsigned short *addrp;
 	/* Instantiate the IR receiver device, if present */
-	if (0 != core->i2c_rc)
+	if (core->i2c_rc != 0)
 		return;
 
 	memset(&info, 0, sizeof(struct i2c_board_info));
@@ -639,8 +641,8 @@ void cx88_i2c_init_ir(struct cx88_core *
 			info.platform_data = &core->init_data;
 		}
 		if (i2c_smbus_xfer(&core->i2c_adap, *addrp, 0,
-					I2C_SMBUS_READ, 0,
-					I2C_SMBUS_QUICK, NULL) >= 0) {
+				   I2C_SMBUS_READ, 0,
+				   I2C_SMBUS_QUICK, NULL) >= 0) {
 			info.addr = *addrp;
 			i2c_new_device(&core->i2c_adap, &info);
 			break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-mpeg.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-mpeg.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-mpeg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-mpeg.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,21 +16,17 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 "cx88.h"
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
-#include <asm/delay.h>
-
-#include "cx88.h"
+#include <linux/delay.h>
 
 /* ------------------------------------------------------------------ */
 
@@ -42,23 +38,20 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(CX88_VERSION);
 
 static unsigned int debug;
-module_param(debug,int,0644);
-MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
-
-#define dprintk(level, fmt, arg...) do {				       \
-	if (debug + 1 > level)						       \
-		printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg); \
-} while(0)
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [mpeg]");
 
-#define mpeg_dbg(level, fmt, arg...) do {				  \
-	if (debug + 1 > level)						  \
-		printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg); \
-} while(0)
+#define dprintk(level, fmt, arg...) do {				\
+	if (debug + 1 > level)						\
+		printk(KERN_DEBUG pr_fmt("%s: mpeg:" fmt),		\
+			__func__, ##arg);				\
+} while (0)
 
 #if defined(CONFIG_MODULES) && defined(MODULE)
 static void request_module_async(struct work_struct *work)
 {
-	struct cx8802_dev *dev=container_of(work, struct cx8802_dev, request_module_wk);
+	struct cx8802_dev *dev = container_of(work, struct cx8802_dev,
+					      request_module_wk);
 
 	if (dev->core->board.mpeg & CX88_MPEG_DVB)
 		request_module("cx88-dvb");
@@ -81,18 +74,17 @@ static void flush_request_modules(struct
 #define flush_request_modules(dev)
 #endif /* CONFIG_MODULES */
 
-
 static LIST_HEAD(cx8802_devlist);
 static DEFINE_MUTEX(cx8802_mutex);
 /* ------------------------------------------------------------------ */
 
 int cx8802_start_dma(struct cx8802_dev    *dev,
-			    struct cx88_dmaqueue *q,
-			    struct cx88_buffer   *buf)
+		     struct cx88_dmaqueue *q,
+		     struct cx88_buffer   *buf)
 {
 	struct cx88_core *core = dev->core;
 
-	dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
+	dprintk(1, "w: %d, h: %d, f: %d\n",
 		core->width, core->height, core->field);
 
 	/* setup fifo + format */
@@ -102,33 +94,35 @@ int cx8802_start_dma(struct cx8802_dev
 	/* write TS length to chip */
 	cx_write(MO_TS_LNGTH, dev->ts_packet_size);
 
-	/* FIXME: this needs a review.
-	 * also: move to cx88-blackbird + cx88-dvb source files? */
-
-	dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
+	/*
+	 * FIXME: this needs a review.
+	 * also: move to cx88-blackbird + cx88-dvb source files?
+	 */
 
-	if ( (core->active_type_id == CX88_MPEG_DVB) &&
-		(core->board.mpeg & CX88_MPEG_DVB) ) {
+	dprintk(1, "core->active_type_id = 0x%08x\n", core->active_type_id);
 
-		dprintk( 1, "cx8802_start_dma doing .dvb\n");
+	if ((core->active_type_id == CX88_MPEG_DVB) &&
+	    (core->board.mpeg & CX88_MPEG_DVB)) {
+		dprintk(1, "cx8802_start_dma doing .dvb\n");
 		/* negedge driven & software reset */
 		cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
 		udelay(100);
 		cx_write(MO_PINMUX_IO, 0x00);
-		cx_write(TS_HW_SOP_CNTRL, 0x47<<16|188<<4|0x01);
+		cx_write(TS_HW_SOP_CNTRL, 0x47 << 16 | 188 << 4 | 0x01);
 		switch (core->boardnr) {
 		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
 		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
 		case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
 		case CX88_BOARD_PCHDTV_HD5500:
-			cx_write(TS_SOP_STAT, 1<<13);
+			cx_write(TS_SOP_STAT, 1 << 13);
 			break;
 		case CX88_BOARD_SAMSUNG_SMT_7020:
 			cx_write(TS_SOP_STAT, 0x00);
 			break;
 		case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
 		case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-			cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
+			/* Enable MPEG parallel IO and video signal pins */
+			cx_write(MO_PINMUX_IO, 0x88);
 			udelay(100);
 			break;
 		case CX88_BOARD_HAUPPAUGE_HVR1300:
@@ -152,22 +146,24 @@ int cx8802_start_dma(struct cx8802_dev
 		}
 		cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
 		udelay(100);
-	} else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
-		(core->board.mpeg & CX88_MPEG_BLACKBIRD) ) {
-		dprintk( 1, "cx8802_start_dma doing .blackbird\n");
+	} else if ((core->active_type_id == CX88_MPEG_BLACKBIRD) &&
+		(core->board.mpeg & CX88_MPEG_BLACKBIRD)) {
+		dprintk(1, "cx8802_start_dma doing .blackbird\n");
 		cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
 
-		cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
+		/* punctured clock TS & posedge driven & software reset */
+		cx_write(TS_GEN_CNTRL, 0x46);
 		udelay(100);
 
 		cx_write(TS_HW_SOP_CNTRL, 0x408); /* mpeg start byte */
 		cx_write(TS_VALERR_CNTRL, 0x2000);
 
-		cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
+		/* punctured clock TS & posedge driven */
+		cx_write(TS_GEN_CNTRL, 0x06);
 		udelay(100);
 	} else {
-		printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __func__,
-			core->board.mpeg );
+		pr_err("%s() Failed. Unsupported value in .mpeg (0x%08x)\n",
+		       __func__, core->board.mpeg);
 		return -EINVAL;
 	}
 
@@ -176,20 +172,22 @@ int cx8802_start_dma(struct cx8802_dev
 	q->count = 0;
 
 	/* enable irqs */
-	dprintk( 1, "setting the interrupt mask\n" );
+	dprintk(1, "setting the interrupt mask\n");
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
 	cx_set(MO_TS_INTMSK,  0x1f0011);
 
 	/* start dma */
-	cx_set(MO_DEV_CNTRL2, (1<<5));
+	cx_set(MO_DEV_CNTRL2, (1 << 5));
 	cx_set(MO_TS_DMACNTRL, 0x11);
 	return 0;
 }
+EXPORT_SYMBOL(cx8802_start_dma);
 
 static int cx8802_stop_dma(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
-	dprintk( 1, "cx8802_stop_dma\n" );
+
+	dprintk(1, "\n");
 
 	/* stop dma */
 	cx_clear(MO_TS_DMACNTRL, 0x11);
@@ -208,12 +206,12 @@ static int cx8802_restart_queue(struct c
 {
 	struct cx88_buffer *buf;
 
-	dprintk( 1, "cx8802_restart_queue\n" );
+	dprintk(1, "\n");
 	if (list_empty(&q->active))
 		return 0;
 
 	buf = list_entry(q->active.next, struct cx88_buffer, list);
-	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+	dprintk(2, "restart_queue [%p/%d]: restart dma\n",
 		buf, buf->vb.vb2_buf.index);
 	cx8802_start_dma(dev, q, buf);
 	return 0;
@@ -222,7 +220,7 @@ static int cx8802_restart_queue(struct c
 /* ------------------------------------------------------------------ */
 
 int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
-			struct cx88_buffer *buf)
+		       struct cx88_buffer *buf)
 {
 	int size = dev->ts_packet_size * dev->ts_packet_count;
 	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
@@ -234,43 +232,46 @@ int cx8802_buf_prepare(struct vb2_queue
 	vb2_set_plane_payload(&buf->vb.vb2_buf, 0, size);
 
 	rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl,
-			     dev->ts_packet_size, dev->ts_packet_count, 0);
+				  dev->ts_packet_size, dev->ts_packet_count, 0);
 	if (rc) {
 		if (risc->cpu)
-			pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
+			pci_free_consistent(dev->pci, risc->size,
+					    risc->cpu, risc->dma);
 		memset(risc, 0, sizeof(*risc));
 		return rc;
 	}
 	return 0;
 }
+EXPORT_SYMBOL(cx8802_buf_prepare);
 
 void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
 {
 	struct cx88_buffer    *prev;
 	struct cx88_dmaqueue  *cx88q = &dev->mpegq;
 
-	dprintk( 1, "cx8802_buf_queue\n" );
+	dprintk(1, "\n");
 	/* add jump to start */
 	buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
 	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
 	buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
 
 	if (list_empty(&cx88q->active)) {
-		dprintk( 1, "queue is empty - first active\n" );
+		dprintk(1, "queue is empty - first active\n");
 		list_add_tail(&buf->list, &cx88q->active);
-		dprintk(1,"[%p/%d] %s - first active\n",
+		dprintk(1, "[%p/%d] %s - first active\n",
 			buf, buf->vb.vb2_buf.index, __func__);
 
 	} else {
 		buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
-		dprintk( 1, "queue is not empty - append to active\n" );
+		dprintk(1, "queue is not empty - append to active\n");
 		prev = list_entry(cx88q->active.prev, struct cx88_buffer, list);
 		list_add_tail(&buf->list, &cx88q->active);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-		dprintk( 1, "[%p/%d] %s - append to active\n",
+		dprintk(1, "[%p/%d] %s - append to active\n",
 			buf, buf->vb.vb2_buf.index, __func__);
 	}
 }
+EXPORT_SYMBOL(cx8802_buf_queue);
 
 /* ----------------------------------------------------------- */
 
@@ -280,23 +281,24 @@ static void do_cancel_buffers(struct cx8
 	struct cx88_buffer *buf;
 	unsigned long flags;
 
-	spin_lock_irqsave(&dev->slock,flags);
+	spin_lock_irqsave(&dev->slock, flags);
 	while (!list_empty(&q->active)) {
 		buf = list_entry(q->active.next, struct cx88_buffer, list);
 		list_del(&buf->list);
 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
 	}
-	spin_unlock_irqrestore(&dev->slock,flags);
+	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
 void cx8802_cancel_buffers(struct cx8802_dev *dev)
 {
-	dprintk( 1, "cx8802_cancel_buffers" );
+	dprintk(1, "\n");
 	cx8802_stop_dma(dev);
 	do_cancel_buffers(dev);
 }
+EXPORT_SYMBOL(cx8802_cancel_buffers);
 
-static const char * cx88_mpeg_irqs[32] = {
+static const char *cx88_mpeg_irqs[32] = {
 	"ts_risci1", NULL, NULL, NULL,
 	"ts_risci2", NULL, NULL, NULL,
 	"ts_oflow",  NULL, NULL, NULL,
@@ -310,7 +312,7 @@ static void cx8802_mpeg_irq(struct cx880
 	struct cx88_core *core = dev->core;
 	u32 status, mask, count;
 
-	dprintk( 1, "cx8802_mpeg_irq\n" );
+	dprintk(1, "\n");
 	status = cx_read(MO_TS_INTSTAT);
 	mask   = cx_read(MO_TS_INTMSK);
 	if (0 == (status & mask))
@@ -319,20 +321,21 @@ static void cx8802_mpeg_irq(struct cx880
 	cx_write(MO_TS_INTSTAT, status);
 
 	if (debug || (status & mask & ~0xff))
-		cx88_print_irqbits(core->name, "irq mpeg ",
+		cx88_print_irqbits("irq mpeg ",
 				   cx88_mpeg_irqs, ARRAY_SIZE(cx88_mpeg_irqs),
 				   status, mask);
 
 	/* risc op code error */
 	if (status & (1 << 16)) {
-		printk(KERN_WARNING "%s: mpeg risc op code error\n",core->name);
+		pr_warn("mpeg risc op code error\n");
 		cx_clear(MO_TS_DMACNTRL, 0x11);
-		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+		cx88_sram_channel_dump(dev->core,
+				       &cx88_sram_channels[SRAM_CH28]);
 	}
 
 	/* risc1 y */
 	if (status & 0x01) {
-		dprintk( 1, "wake up\n" );
+		dprintk(1, "wake up\n");
 		spin_lock(&dev->slock);
 		count = cx_read(MO_TS_GPCNT);
 		cx88_wakeup(dev->core, &dev->mpegq, count);
@@ -341,7 +344,7 @@ static void cx8802_mpeg_irq(struct cx880
 
 	/* other general errors */
 	if (status & 0x1f0100) {
-		dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
+		dprintk(0, "general errors: 0x%08x\n", status & 0x1f0100);
 		spin_lock(&dev->slock);
 		cx8802_stop_dma(dev);
 		spin_unlock(&dev->slock);
@@ -360,24 +363,23 @@ static irqreturn_t cx8802_irq(int irq, v
 	for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
 		status = cx_read(MO_PCI_INTSTAT) &
 			(core->pci_irqmask | PCI_INT_TSINT);
-		if (0 == status)
+		if (status == 0)
 			goto out;
-		dprintk( 1, "cx8802_irq\n" );
-		dprintk( 1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP );
-		dprintk( 1, "    status: %d\n", status );
+		dprintk(1, "cx8802_irq\n");
+		dprintk(1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP);
+		dprintk(1, "    status: %d\n", status);
 		handled = 1;
 		cx_write(MO_PCI_INTSTAT, status);
 
 		if (status & core->pci_irqmask)
-			cx88_core_irq(core,status);
+			cx88_core_irq(core, status);
 		if (status & PCI_INT_TSINT)
 			cx8802_mpeg_irq(dev);
 	}
-	if (MAX_IRQ_LOOP == loop) {
-		dprintk( 0, "clearing mask\n" );
-		printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
-		       core->name);
-		cx_write(MO_PCI_INTMSK,0);
+	if (loop == MAX_IRQ_LOOP) {
+		dprintk(0, "clearing mask\n");
+		pr_warn("irq loop -- clearing mask\n");
+		cx_write(MO_PCI_INTMSK, 0);
 	}
 
  out:
@@ -393,18 +395,18 @@ static int cx8802_init_common(struct cx8
 	if (pci_enable_device(dev->pci))
 		return -EIO;
 	pci_set_master(dev->pci);
-	err = pci_set_dma_mask(dev->pci,DMA_BIT_MASK(32));
+	err = pci_set_dma_mask(dev->pci, DMA_BIT_MASK(32));
 	if (err) {
-		printk("%s/2: Oops: no 32bit PCI DMA ???\n",dev->core->name);
+		pr_err("Oops: no 32bit PCI DMA ???\n");
 		return -EIO;
 	}
 
 	dev->pci_rev = dev->pci->revision;
 	pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER,  &dev->pci_lat);
-	printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, "
-	       "latency: %d, mmio: 0x%llx\n", dev->core->name,
-	       pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
-	       dev->pci_lat,(unsigned long long)pci_resource_start(dev->pci,0));
+	pr_info("found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
+		pci_name(dev->pci), dev->pci_rev, dev->pci->irq,
+		dev->pci_lat,
+		(unsigned long long)pci_resource_start(dev->pci, 0));
 
 	/* initialize driver struct */
 	spin_lock_init(&dev->slock);
@@ -416,20 +418,19 @@ static int cx8802_init_common(struct cx8
 	err = request_irq(dev->pci->irq, cx8802_irq,
 			  IRQF_SHARED, dev->core->name, dev);
 	if (err < 0) {
-		printk(KERN_ERR "%s: can't get IRQ %d\n",
-		       dev->core->name, dev->pci->irq);
+		pr_err("can't get IRQ %d\n", dev->pci->irq);
 		return err;
 	}
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask);
 
 	/* everything worked */
-	pci_set_drvdata(dev->pci,dev);
+	pci_set_drvdata(dev->pci, dev);
 	return 0;
 }
 
 static void cx8802_fini_common(struct cx8802_dev *dev)
 {
-	dprintk( 2, "cx8802_fini_common\n" );
+	dprintk(2, "\n");
 	cx8802_stop_dma(dev);
 	pci_disable_device(dev->pci);
 
@@ -442,14 +443,13 @@ static void cx8802_fini_common(struct cx
 static int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
 {
 	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-	struct cx88_core *core = dev->core;
 	unsigned long flags;
 
 	/* stop mpeg dma */
 	spin_lock_irqsave(&dev->slock, flags);
 	if (!list_empty(&dev->mpegq.active)) {
-		dprintk( 2, "suspend\n" );
-		printk("%s: suspend mpeg\n", core->name);
+		dprintk(2, "suspend\n");
+		pr_info("suspend mpeg\n");
 		cx8802_stop_dma(dev);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
@@ -458,7 +458,8 @@ static int cx8802_suspend_common(struct
 	cx88_shutdown(dev->core);
 
 	pci_save_state(pci_dev);
-	if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+	if (pci_set_power_state(pci_dev,
+				pci_choose_state(pci_dev, state)) != 0) {
 		pci_disable_device(pci_dev);
 		dev->state.disabled = 1;
 	}
@@ -468,23 +469,20 @@ static int cx8802_suspend_common(struct
 static int cx8802_resume_common(struct pci_dev *pci_dev)
 {
 	struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
-	struct cx88_core *core = dev->core;
 	unsigned long flags;
 	int err;
 
 	if (dev->state.disabled) {
-		err=pci_enable_device(pci_dev);
+		err = pci_enable_device(pci_dev);
 		if (err) {
-			printk(KERN_ERR "%s: can't enable device\n",
-					       dev->core->name);
+			pr_err("can't enable device\n");
 			return err;
 		}
 		dev->state.disabled = 0;
 	}
-	err=pci_set_power_state(pci_dev, PCI_D0);
+	err = pci_set_power_state(pci_dev, PCI_D0);
 	if (err) {
-		printk(KERN_ERR "%s: can't enable device\n",
-					       dev->core->name);
+		pr_err("can't enable device\n");
 		pci_disable_device(pci_dev);
 		dev->state.disabled = 1;
 
@@ -498,15 +496,16 @@ static int cx8802_resume_common(struct p
 	/* restart video+vbi capture */
 	spin_lock_irqsave(&dev->slock, flags);
 	if (!list_empty(&dev->mpegq.active)) {
-		printk("%s: resume mpeg\n", core->name);
-		cx8802_restart_queue(dev,&dev->mpegq);
+		pr_info("resume mpeg\n");
+		cx8802_restart_queue(dev, &dev->mpegq);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 
 	return 0;
 }
 
-struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
+struct cx8802_driver *cx8802_get_driver(struct cx8802_dev *dev,
+					enum cx88_board_type btype)
 {
 	struct cx8802_driver *d;
 
@@ -516,6 +515,7 @@ struct cx8802_driver * cx8802_get_driver
 
 	return NULL;
 }
+EXPORT_SYMBOL(cx8802_get_driver);
 
 /* Driver asked for hardware access. */
 static int cx8802_request_acquire(struct cx8802_driver *drv)
@@ -533,7 +533,8 @@ static int cx8802_request_acquire(struct
 		core->last_analog_input = core->input;
 		core->input = 0;
 		for (i = 0;
-		     i < (sizeof(core->board.input) / sizeof(struct cx88_input));
+		     i < (sizeof(core->board.input) /
+			  sizeof(struct cx88_input));
 		     i++) {
 			if (core->board.input[i].type == CX88_VMUX_DVB) {
 				core->input = i;
@@ -542,15 +543,14 @@ static int cx8802_request_acquire(struct
 		}
 	}
 
-	if (drv->advise_acquire)
-	{
+	if (drv->advise_acquire) {
 		core->active_ref++;
 		if (core->active_type_id == CX88_BOARD_NONE) {
 			core->active_type_id = drv->type_id;
 			drv->advise_acquire(drv);
 		}
 
-		mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+		dprintk(1, "Post acquire GPIO=%x\n", cx_read(MO_GP0_IO));
 	}
 
 	return 0;
@@ -561,17 +561,18 @@ static int cx8802_request_release(struct
 {
 	struct cx88_core *core = drv->core;
 
-	if (drv->advise_release && --core->active_ref == 0)
-	{
+	if (drv->advise_release && --core->active_ref == 0) {
 		if (drv->type_id == CX88_MPEG_DVB) {
-			/* If the DVB driver is releasing, reset the input
-			   state to the last configured analog input */
+			/*
+			 * If the DVB driver is releasing, reset the input
+			 * state to the last configured analog input
+			 */
 			core->input = core->last_analog_input;
 		}
 
 		drv->advise_release(drv);
 		core->active_type_id = CX88_BOARD_NONE;
-		mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+		dprintk(1, "Post release GPIO=%x\n", cx_read(MO_GP0_IO));
 	}
 
 	return 0;
@@ -579,21 +580,21 @@ static int cx8802_request_release(struct
 
 static int cx8802_check_driver(struct cx8802_driver *drv)
 {
-	if (drv == NULL)
+	if (!drv)
 		return -ENODEV;
 
 	if ((drv->type_id != CX88_MPEG_DVB) &&
-		(drv->type_id != CX88_MPEG_BLACKBIRD))
+	    (drv->type_id != CX88_MPEG_BLACKBIRD))
 		return -EINVAL;
 
 	if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
-		(drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
+	    (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
 		return -EINVAL;
 
-	if ((drv->probe == NULL) ||
-		(drv->remove == NULL) ||
-		(drv->advise_acquire == NULL) ||
-		(drv->advise_release == NULL))
+	if ((!drv->probe) ||
+	    (!drv->remove) ||
+	    (!drv->advise_acquire) ||
+	    (!drv->advise_release))
 		return -EINVAL;
 
 	return 0;
@@ -605,28 +606,28 @@ int cx8802_register_driver(struct cx8802
 	struct cx8802_driver *driver;
 	int err, i = 0;
 
-	printk(KERN_INFO
-	       "cx88/2: registering cx8802 driver, type: %s access: %s\n",
-	       drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
-	       drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+	pr_info("registering cx8802 driver, type: %s access: %s\n",
+		drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+		drv->hw_access == CX8802_DRVCTL_SHARED ?
+				  "shared" : "exclusive");
 
-	if ((err = cx8802_check_driver(drv)) != 0) {
-		printk(KERN_ERR "cx88/2: cx8802_driver is invalid\n");
+	err = cx8802_check_driver(drv);
+	if (err) {
+		pr_err("cx8802_driver is invalid\n");
 		return err;
 	}
 
 	mutex_lock(&cx8802_mutex);
 
 	list_for_each_entry(dev, &cx8802_devlist, devlist) {
-		printk(KERN_INFO
-		       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
-		       dev->core->name, dev->pci->subsystem_vendor,
-		       dev->pci->subsystem_device, dev->core->board.name,
-		       dev->core->boardnr);
+		pr_info("subsystem: %04x:%04x, board: %s [card=%d]\n",
+			dev->pci->subsystem_vendor,
+			dev->pci->subsystem_device, dev->core->board.name,
+			dev->core->boardnr);
 
 		/* Bring up a new struct for each driver instance */
-		driver = kzalloc(sizeof(*drv),GFP_KERNEL);
-		if (driver == NULL) {
+		driver = kzalloc(sizeof(*drv), GFP_KERNEL);
+		if (!driver) {
 			err = -ENOMEM;
 			goto out;
 		}
@@ -645,9 +646,7 @@ int cx8802_register_driver(struct cx8802
 			i++;
 			list_add_tail(&driver->drvlist, &dev->drvlist);
 		} else {
-			printk(KERN_ERR
-			       "%s/2: cx8802 probe failed, err = %d\n",
-			       dev->core->name, err);
+			pr_err("cx8802 probe failed, err = %d\n", err);
 		}
 		mutex_unlock(&drv->core->lock);
 	}
@@ -657,6 +656,7 @@ out:
 	mutex_unlock(&cx8802_mutex);
 	return err;
 }
+EXPORT_SYMBOL(cx8802_register_driver);
 
 int cx8802_unregister_driver(struct cx8802_driver *drv)
 {
@@ -664,19 +664,18 @@ int cx8802_unregister_driver(struct cx88
 	struct cx8802_driver *d, *dtmp;
 	int err = 0;
 
-	printk(KERN_INFO
-	       "cx88/2: unregistering cx8802 driver, type: %s access: %s\n",
-	       drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
-	       drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
+	pr_info("unregistering cx8802 driver, type: %s access: %s\n",
+		drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
+		drv->hw_access == CX8802_DRVCTL_SHARED ?
+				  "shared" : "exclusive");
 
 	mutex_lock(&cx8802_mutex);
 
 	list_for_each_entry(dev, &cx8802_devlist, devlist) {
-		printk(KERN_INFO
-		       "%s/2: subsystem: %04x:%04x, board: %s [card=%d]\n",
-		       dev->core->name, dev->pci->subsystem_vendor,
-		       dev->pci->subsystem_device, dev->core->board.name,
-		       dev->core->boardnr);
+		pr_info("subsystem: %04x:%04x, board: %s [card=%d]\n",
+			dev->pci->subsystem_vendor,
+			dev->pci->subsystem_device, dev->core->board.name,
+			dev->core->boardnr);
 
 		mutex_lock(&dev->core->lock);
 
@@ -690,8 +689,8 @@ int cx8802_unregister_driver(struct cx88
 				list_del(&d->drvlist);
 				kfree(d);
 			} else
-				printk(KERN_ERR "%s/2: cx8802 driver remove "
-				       "failed (%d)\n", dev->core->name, err);
+				pr_err("cx8802 driver remove failed (%d)\n",
+				       err);
 		}
 
 		mutex_unlock(&dev->core->lock);
@@ -701,6 +700,7 @@ int cx8802_unregister_driver(struct cx88
 
 	return err;
 }
+EXPORT_SYMBOL(cx8802_unregister_driver);
 
 /* ----------------------------------------------------------- */
 static int cx8802_probe(struct pci_dev *pci_dev,
@@ -712,18 +712,18 @@ static int cx8802_probe(struct pci_dev *
 
 	/* general setup */
 	core = cx88_core_get(pci_dev);
-	if (NULL == core)
+	if (!core)
 		return -EINVAL;
 
-	printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
+	pr_info("cx2388x 8802 Driver Manager\n");
 
 	err = -ENODEV;
 	if (!core->board.mpeg)
 		goto fail_core;
 
 	err = -ENOMEM;
-	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
-	if (NULL == dev)
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
 		goto fail_core;
 	dev->pci = pci_dev;
 	dev->core = core;
@@ -737,7 +737,7 @@ static int cx8802_probe(struct pci_dev *
 
 	INIT_LIST_HEAD(&dev->drvlist);
 	mutex_lock(&cx8802_mutex);
-	list_add_tail(&dev->devlist,&cx8802_devlist);
+	list_add_tail(&dev->devlist, &cx8802_devlist);
 	mutex_unlock(&cx8802_mutex);
 
 	/* now autoload cx88-dvb or cx88-blackbird */
@@ -748,7 +748,7 @@ static int cx8802_probe(struct pci_dev *
 	kfree(dev);
  fail_core:
 	core->dvbdev = NULL;
-	cx88_core_put(core,pci_dev);
+	cx88_core_put(core, pci_dev);
 	return err;
 }
 
@@ -758,7 +758,7 @@ static void cx8802_remove(struct pci_dev
 
 	dev = pci_get_drvdata(pci_dev);
 
-	dprintk( 1, "%s\n", __func__);
+	dprintk(1, "%s\n", __func__);
 
 	flush_request_modules(dev);
 
@@ -768,17 +768,15 @@ static void cx8802_remove(struct pci_dev
 		struct cx8802_driver *drv, *tmp;
 		int err;
 
-		printk(KERN_WARNING "%s/2: Trying to remove cx8802 driver "
-		       "while cx8802 sub-drivers still loaded?!\n",
-		       dev->core->name);
+		pr_warn("Trying to remove cx8802 driver while cx8802 sub-drivers still loaded?!\n");
 
 		list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
 			err = drv->remove(drv);
 			if (err == 0) {
 				list_del(&drv->drvlist);
 			} else
-				printk(KERN_ERR "%s/2: cx8802 driver remove "
-				       "failed (%d)\n", dev->core->name, err);
+				pr_err("cx8802 driver remove failed (%d)\n",
+				       err);
 			kfree(drv);
 		}
 	}
@@ -790,7 +788,7 @@ static void cx8802_remove(struct pci_dev
 
 	/* common */
 	cx8802_fini_common(dev);
-	cx88_core_put(dev->core,dev->pci);
+	cx88_core_put(dev->core, dev->pci);
 	kfree(dev);
 }
 
@@ -800,7 +798,7 @@ static const struct pci_device_id cx8802
 		.device       = 0x8802,
 		.subvendor    = PCI_ANY_ID,
 		.subdevice    = PCI_ANY_ID,
-	},{
+	}, {
 		/* --- end of list --- */
 	}
 };
@@ -814,12 +812,3 @@ static struct pci_driver cx8802_pci_driv
 };
 
 module_pci_driver(cx8802_pci_driver);
-
-EXPORT_SYMBOL(cx8802_buf_prepare);
-EXPORT_SYMBOL(cx8802_buf_queue);
-EXPORT_SYMBOL(cx8802_cancel_buffers);
-EXPORT_SYMBOL(cx8802_start_dma);
-
-EXPORT_SYMBOL(cx8802_register_driver);
-EXPORT_SYMBOL(cx8802_unregister_driver);
-EXPORT_SYMBOL(cx8802_get_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-reg.h linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-reg.h
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,32 +1,28 @@
 /*
-
-    cx88x-hw.h - CX2388x register offsets
-
-    Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
-		  2001 Michael Eskin
-		  2002 Yurij Sysoev <yurij@naturesoft.net>
-		  2003 Gerd Knorr <kraxel@bytesex.org>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * cx88x-hw.h - CX2388x register offsets
+ *
+ * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
+ *		  2001 Michael Eskin
+ *		  2002 Yurij Sysoev <yurij@naturesoft.net>
+ *		  2003 Gerd Knorr <kraxel@bytesex.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
 #ifndef _CX88_REG_H_
 #define _CX88_REG_H_
 
-/* ---------------------------------------------------------------------- */
-/* PCI IDs and config space                                               */
+/*
+ * PCI IDs and config space
+ */
 
 #ifndef PCI_VENDOR_ID_CONEXANT
 # define PCI_VENDOR_ID_CONEXANT		0x14F1
@@ -39,8 +35,9 @@
 #define CX88X_EN_TBFX 0x02
 #define CX88X_EN_VSFX 0x04
 
-/* ---------------------------------------------------------------------- */
-/* PCI controller registers                                               */
+/*
+ * PCI controller registers
+ */
 
 /* Command and Status Register */
 #define F0_CMD_STAT_MM      0x2f0004
@@ -63,8 +60,9 @@
 #define F3_BAR0_MM          0x2f0310
 #define F4_BAR0_MM          0x2f0410
 
-/* ---------------------------------------------------------------------- */
-/* DMA Controller registers                                               */
+/*
+ * DMA Controller registers
+ */
 
 #define MO_PDMA_STHRSH      0x200000 // Source threshold
 #define MO_PDMA_STADRS      0x200004 // Source target address
@@ -157,9 +155,9 @@
 #define MO_DMA31_CNT2       0x300168 // {11}RW* DMA Table Size : Ch#31
 #define MO_DMA32_CNT2       0x30016C // {11}RW* DMA Table Size : Ch#32
 
-
-/* ---------------------------------------------------------------------- */
-/* Video registers                                                        */
+/*
+ * Video registers
+ */
 
 #define MO_VIDY_DMA         0x310000 // {64}RWp Video Y
 #define MO_VIDU_DMA         0x310008 // {64}RWp Video U
@@ -217,9 +215,9 @@
 #define MO_VID_DMACNTRL     0x31C040 // {8}RW Video DMA control
 #define MO_VID_XFR_STAT     0x31C044 // {1}RO Video transfer status
 
-
-/* ---------------------------------------------------------------------- */
-/* audio registers                                                        */
+/*
+ * audio registers
+ */
 
 #define MO_AUDD_DMA         0x320000 // {64}RWp Audio downstream
 #define MO_AUDU_DMA         0x320008 // {64}RWp Audio upstream
@@ -437,9 +435,9 @@
 #define AUD_PHACC_FREQ_8LSB      0x320d2b
 #define AUD_QAM_MODE             0x320d04
 
-
-/* ---------------------------------------------------------------------- */
-/* transport stream registers                                             */
+/*
+ * transport stream registers
+ */
 
 #define MO_TS_DMA           0x330000 // {64}RWp Transport stream downstream
 #define MO_TS_GPCNT         0x33C020 // {16}RO TS general purpose counter
@@ -455,9 +453,9 @@
 #define TS_FIFO_OVFL_STAT   0x33C05C
 #define TS_VALERR_CNTRL     0x33C060
 
-
-/* ---------------------------------------------------------------------- */
-/* VIP registers                                                          */
+/*
+ * VIP registers
+ */
 
 #define MO_VIPD_DMA         0x340000 // {64}RWp VIP downstream
 #define MO_VIPU_DMA         0x340008 // {64}RWp VIP upstream
@@ -475,9 +473,9 @@
 #define MO_VIP_INTCNTRL     0x34C05C // VIP Interrupt Control
 #define MO_VIP_XFTERM       0x340060 // VIP transfer terminate
 
-
-/* ---------------------------------------------------------------------- */
-/* misc registers                                                         */
+/*
+ * misc registers
+ */
 
 #define MO_M2M_DMA          0x350000 // {64}RWp Mem2Mem DMA Bfr
 #define MO_GP0_IO           0x350010 // {32}RW* GPIOoutput enablesdata I/O
@@ -509,9 +507,9 @@
 #define MO_INT1_STAT        0x35C064 // DMA RISC interrupt status
 #define MO_INT1_MSTAT       0x35C068 // DMA RISC interrupt masked status
 
-
-/* ---------------------------------------------------------------------- */
-/* i2c bus registers                                                      */
+/*
+ * i2c bus registers
+ */
 
 #define MO_I2C              0x368000 // I2C data/control
 #define MO_I2C_DIV          (0xf<<4)
@@ -521,9 +519,11 @@
 #define MO_I2C_SDA          (1<<0)
 
 
-/* ---------------------------------------------------------------------- */
-/* general purpose host registers                                         */
-/* FIXME: tyops?  s/0x35/0x38/ ??                                         */
+/*
+ * general purpose host registers
+ *
+ * FIXME: tyops?  s/0x35/0x38/ ??
+ */
 
 #define MO_GPHSTD_DMA       0x350000 // {64}RWp Host downstream
 #define MO_GPHSTU_DMA       0x350008 // {64}RWp Host upstream
@@ -545,9 +545,9 @@
 #define MO_GPHST_XFR_STAT   0x38C044 // Host transfer status
 #define MO_GPHST_SOFT_RST   0x38C06C // Host software reset
 
-
-/* ---------------------------------------------------------------------- */
-/* RISC instructions                                                      */
+/*
+ * RISC instructions
+ */
 
 #define RISC_SYNC		 0x80000000
 #define RISC_SYNC_ODD		 0x80000000
@@ -576,11 +576,11 @@
 #define RISC_CNT_INC		 0x00010000
 #define RISC_CNT_RSVR		 0x00020000
 #define RISC_CNT_RESET		 0x00030000
-#define RISC_JMP_SRP         	 0x01
-
+#define RISC_JMP_SRP		 0x01
 
-/* ---------------------------------------------------------------------- */
-/* various constants                                                      */
+/*
+ * various constants
+ */
 
 // DMA
 /* Interrupt mask/status */
@@ -822,15 +822,4 @@
 #define DEFAULT_SAT_U_NTSC			0x7F
 #define DEFAULT_SAT_V_NTSC			0x5A
 
-typedef enum
-{
-	SOURCE_TUNER = 0,
-	SOURCE_COMPOSITE,
-	SOURCE_SVIDEO,
-	SOURCE_OTHER1,
-	SOURCE_OTHER2,
-	SOURCE_COMPVIASVIDEO,
-	SOURCE_CCIR656
-} VIDEOSOURCETYPE;
-
 #endif /* _CX88_REG_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-tvaudio.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-tvaudio.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-tvaudio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-tvaudio.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,39 +1,36 @@
 /*
+ * cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
+ *
+ *  (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
+ *  (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
+ *  (c) 2003 Gerd Knorr <kraxel@bytesex.org>
+ *
+ * -----------------------------------------------------------------------
+ *
+ * Lot of voodoo here.  Even the data sheet doesn't help to
+ * understand what is going on here, the documentation for the audio
+ * part of the cx2388x chip is *very* bad.
+ *
+ * Some of this comes from party done linux driver sources I got from
+ * [undocumented].
+ *
+ * Some comes from the dscaler sources, one of the dscaler driver guy works
+ * for Conexant ...
+ *
+ * -----------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-    cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
-
-     (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version]
-     (c) 2002 Yurij Sysoev <yurij@naturesoft.net>
-     (c) 2003 Gerd Knorr <kraxel@bytesex.org>
-
-    -----------------------------------------------------------------------
-
-    Lot of voodoo here.  Even the data sheet doesn't help to
-    understand what is going on here, the documentation for the audio
-    part of the cx2388x chip is *very* bad.
-
-    Some of this comes from party done linux driver sources I got from
-    [undocumented].
-
-    Some comes from the dscaler sources, one of the dscaler driver guy works
-    for Conexant ...
-
-    -----------------------------------------------------------------------
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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 "cx88.h"
 
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -50,24 +47,24 @@
 #include <linux/delay.h>
 #include <linux/kthread.h>
 
-#include "cx88.h"
-
 static unsigned int audio_debug;
 module_param(audio_debug, int, 0644);
 MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
 
 static unsigned int always_analog;
-module_param(always_analog,int,0644);
-MODULE_PARM_DESC(always_analog,"force analog audio out");
+module_param(always_analog, int, 0644);
+MODULE_PARM_DESC(always_analog, "force analog audio out");
 
 static unsigned int radio_deemphasis;
-module_param(radio_deemphasis,int,0644);
-MODULE_PARM_DESC(radio_deemphasis, "Radio deemphasis time constant, "
-		 "0=None, 1=50us (elsewhere), 2=75us (USA)");
-
-#define dprintk(fmt, arg...)	if (audio_debug) \
-	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+module_param(radio_deemphasis, int, 0644);
+MODULE_PARM_DESC(radio_deemphasis,
+		 "Radio deemphasis time constant, 0=None, 1=50us (elsewhere), 2=75us (USA)");
 
+#define dprintk(fmt, arg...) do {				\
+	if (audio_debug)						\
+		printk(KERN_DEBUG pr_fmt("%s: tvaudio:" fmt),		\
+			__func__, ##arg);				\
+} while (0)
 /* ----------------------------------------------------------- */
 
 static const char * const aud_ctl_names[64] = {
@@ -145,7 +142,10 @@ static void set_audio_finish(struct cx88
 	if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
 		cx_write(AUD_I2SINPUTCNTL, 4);
 		cx_write(AUD_BAUDRATE, 1);
-		/* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
+		/*
+		 * 'pass-thru mode': this enables the i2s
+		 * output to the mpeg encoder
+		 */
 		cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
 		cx_write(AUD_I2SOUTPUTCNTL, 1);
 		cx_write(AUD_I2SCNTL, 0);
@@ -349,7 +349,7 @@ static void set_audio_standard_NICAM(str
 		{ /* end of list */ },
 	};
 
-	set_audio_start(core,SEL_NICAM);
+	set_audio_start(core, SEL_NICAM);
 	switch (core->tvaudio) {
 	case WW_L:
 		dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
@@ -638,7 +638,6 @@ static void set_audio_standard_A2(struct
 	case WW_M:
 		dprintk("%s Warning: wrong value\n", __func__);
 		return;
-		break;
 	}
 
 	mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
@@ -695,13 +694,15 @@ static void set_audio_standard_FM(struct
 		{ /* end of list */ },
 	};
 
-	/* It is enough to leave default values? */
-	/* No, it's not!  The deemphasis registers are reset to the 75us
+	/*
+	 * It is enough to leave default values?
+	 *
+	 * No, it's not!  The deemphasis registers are reset to the 75us
 	 * values by default.  Analyzing the spectrum of the decoded audio
 	 * reveals that "no deemphasis" is the same as 75 us, while the 50 us
-	 * setting results in less deemphasis.  */
+	 * setting results in less deemphasis.
+	 */
 	static const struct rlist fm_no_deemph[] = {
-
 		{AUD_POLYPH80SCALEFAC, 0x0003},
 		{ /* end of list */ },
 	};
@@ -745,7 +746,7 @@ static int cx88_detect_nicam(struct cx88
 		}
 
 		/* wait a little bit for next reading status */
-		msleep(10);
+		usleep_range(10000, 20000);
 	}
 
 	dprintk("nicam is not detected.\n");
@@ -766,10 +767,12 @@ void cx88_set_tvaudio(struct cx88_core *
 		/* prepare all dsp registers */
 		set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
 
-		/* set nicam mode - otherwise
-		   AUD_NICAM_STATUS2 contains wrong values */
+		/*
+		 * set nicam mode - otherwise
+		 * AUD_NICAM_STATUS2 contains wrong values
+		 */
 		set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
-		if (0 == cx88_detect_nicam(core)) {
+		if (cx88_detect_nicam(core) == 0) {
 			/* fall back to fm / am mono */
 			set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
 			core->audiomode_current = V4L2_TUNER_MODE_MONO;
@@ -798,23 +801,25 @@ void cx88_set_tvaudio(struct cx88_core *
 		break;
 	case WW_NONE:
 	case WW_I2SPT:
-		printk("%s/0: unknown tv audio mode [%d]\n",
-		       core->name, core->tvaudio);
+		pr_info("unknown tv audio mode [%d]\n", core->tvaudio);
 		break;
 	}
-	return;
 }
+EXPORT_SYMBOL(cx88_set_tvaudio);
 
 void cx88_newstation(struct cx88_core *core)
 {
 	core->audiomode_manual = UNSET;
 	core->last_change = jiffies;
 }
+EXPORT_SYMBOL(cx88_newstation);
 
 void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
 {
-	static const char * const m[] = { "stereo", "dual mono", "mono", "sap" };
-	static const char * const p[] = { "no pilot", "pilot c1", "pilot c2", "?" };
+	static const char * const m[] = { "stereo", "dual mono",
+					  "mono",   "sap" };
+	static const char * const p[] = { "no pilot", "pilot c1",
+					  "pilot c2", "?" };
 	u32 reg, mode, pilot;
 
 	reg = cx_read(AUD_STATUS);
@@ -869,15 +874,18 @@ void cx88_get_stereo(struct cx88_core *c
 	}
 
 	/* If software stereo detection is not supported... */
-	if (UNSET == t->rxsubchans) {
+	if (t->rxsubchans == UNSET) {
 		t->rxsubchans = V4L2_TUNER_SUB_MONO;
-		/* If the hardware itself detected stereo, also return
-		   stereo as an available subchannel */
-		if (V4L2_TUNER_MODE_STEREO == t->audmode)
+		/*
+		 * If the hardware itself detected stereo, also return
+		 * stereo as an available subchannel
+		 */
+		if (t->audmode == V4L2_TUNER_MODE_STEREO)
 			t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
 	}
-	return;
 }
+EXPORT_SYMBOL(cx88_get_stereo);
+
 
 void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
 {
@@ -887,7 +895,7 @@ void cx88_set_stereo(struct cx88_core *c
 	if (manual) {
 		core->audiomode_manual = mode;
 	} else {
-		if (UNSET != core->audiomode_manual)
+		if (core->audiomode_manual != UNSET)
 			return;
 	}
 	core->audiomode_current = mode;
@@ -915,7 +923,7 @@ void cx88_set_stereo(struct cx88_core *c
 	case WW_M:
 	case WW_I:
 	case WW_L:
-		if (1 == core->use_nicam) {
+		if (core->use_nicam == 1) {
 			switch (mode) {
 			case V4L2_TUNER_MODE_MONO:
 			case V4L2_TUNER_MODE_LANG1:
@@ -933,7 +941,8 @@ void cx88_set_stereo(struct cx88_core *c
 				break;
 			}
 		} else {
-			if ((core->tvaudio == WW_I) || (core->tvaudio == WW_L)) {
+			if ((core->tvaudio == WW_I) ||
+			    (core->tvaudio == WW_L)) {
 				/* fall back to fm / am mono */
 				set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
 			} else {
@@ -975,15 +984,14 @@ void cx88_set_stereo(struct cx88_core *c
 		break;
 	}
 
-	if (UNSET != ctl) {
-		dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x "
-			"[status=0x%x,ctl=0x%x,vol=0x%x]\n",
+	if (ctl != UNSET) {
+		dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x [status=0x%x,ctl=0x%x,vol=0x%x]\n",
 			mask, ctl, cx_read(AUD_STATUS),
 			cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
 		cx_andor(AUD_CTL, mask, ctl);
 	}
-	return;
 }
+EXPORT_SYMBOL(cx88_set_stereo);
 
 int cx88_audio_thread(void *data)
 {
@@ -1012,7 +1020,7 @@ int cx88_audio_thread(void *data)
 			memset(&t, 0, sizeof(t));
 			cx88_get_stereo(core, &t);
 
-			if (UNSET != core->audiomode_manual)
+			if (core->audiomode_manual != UNSET)
 				/* manually set, don't do anything. */
 				continue;
 
@@ -1033,8 +1041,10 @@ int cx88_audio_thread(void *data)
 		case WW_FM:
 		case WW_I2SADC:
 hw_autodetect:
-			/* stereo autodetection is supported by hardware so
-			   we don't need to do it manually. Do nothing. */
+			/*
+			 * stereo autodetection is supported by hardware so
+			 * we don't need to do it manually. Do nothing.
+			 */
 			break;
 		}
 	}
@@ -1042,11 +1052,4 @@ hw_autodetect:
 	dprintk("cx88: tvaudio thread exiting\n");
 	return 0;
 }
-
-/* ----------------------------------------------------------- */
-
-EXPORT_SYMBOL(cx88_set_tvaudio);
-EXPORT_SYMBOL(cx88_newstation);
-EXPORT_SYMBOL(cx88_set_stereo);
-EXPORT_SYMBOL(cx88_get_stereo);
 EXPORT_SYMBOL(cx88_audio_thread);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-vbi.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-vbi.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-vbi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-vbi.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,22 +1,26 @@
 /*
  */
+
+#include "cx88.h"
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
-#include "cx88.h"
-
 static unsigned int vbi_debug;
-module_param(vbi_debug,int,0644);
-MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
+module_param(vbi_debug, int, 0644);
+MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
 
-#define dprintk(level,fmt, arg...)	if (vbi_debug >= level) \
-	printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
+#define dprintk(level, fmt, arg...) do {			\
+	if (vbi_debug >= level)					\
+		printk(KERN_DEBUG pr_fmt("%s: vbi:" fmt),	\
+			__func__, ##arg);			\
+} while (0)
 
 /* ------------------------------------------------------------------ */
 
-int cx8800_vbi_fmt (struct file *file, void *priv,
-					struct v4l2_format *f)
+int cx8800_vbi_fmt(struct file *file, void *priv,
+		   struct v4l2_format *f)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 
@@ -44,8 +48,8 @@ int cx8800_vbi_fmt (struct file *file, v
 }
 
 static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
-			 struct cx88_dmaqueue *q,
-			 struct cx88_buffer   *buf)
+				struct cx88_dmaqueue *q,
+				struct cx88_buffer   *buf)
 {
 	struct cx88_core *core = dev->core;
 
@@ -53,9 +57,9 @@ static int cx8800_start_vbi_dma(struct c
 	cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
 				VBI_LINE_LENGTH, buf->risc.dma);
 
-	cx_write(MO_VBOS_CONTROL, ( (1 << 18) |  // comb filter delay fixup
-				    (1 << 15) |  // enable vbi capture
-				    (1 << 11) ));
+	cx_write(MO_VBOS_CONTROL, (1 << 18) |  /* comb filter delay fixup */
+				  (1 << 15) |  /* enable vbi capture */
+				  (1 << 11));
 
 	/* reset counter */
 	cx_write(MO_VBI_GPCNTRL, GP_COUNT_CONTROL_RESET);
@@ -66,10 +70,10 @@ static int cx8800_start_vbi_dma(struct c
 	cx_set(MO_VID_INTMSK, 0x0f0088);
 
 	/* enable capture */
-	cx_set(VID_CAPTURE_CONTROL,0x18);
+	cx_set(VID_CAPTURE_CONTROL, 0x18);
 
 	/* start dma */
-	cx_set(MO_DEV_CNTRL2, (1<<5));
+	cx_set(MO_DEV_CNTRL2, (1 << 5));
 	cx_set(MO_VID_DMACNTRL, 0x88);
 
 	return 0;
@@ -83,7 +87,7 @@ void cx8800_stop_vbi_dma(struct cx8800_d
 	cx_clear(MO_VID_DMACNTRL, 0x88);
 
 	/* disable capture */
-	cx_clear(VID_CAPTURE_CONTROL,0x18);
+	cx_clear(VID_CAPTURE_CONTROL, 0x18);
 
 	/* disable irqs */
 	cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
@@ -99,7 +103,7 @@ int cx8800_restart_vbi_queue(struct cx88
 		return 0;
 
 	buf = list_entry(q->active.next, struct cx88_buffer, list);
-	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+	dprintk(2, "restart_queue [%p/%d]: restart dma\n",
 		buf, buf->vb.vb2_buf.index);
 	cx8800_start_vbi_dma(dev, q, buf);
 	return 0;
@@ -108,8 +112,8 @@ int cx8800_restart_vbi_queue(struct cx88
 /* ------------------------------------------------------------------ */
 
 static int queue_setup(struct vb2_queue *q,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], struct device *alloc_devs[])
+		       unsigned int *num_buffers, unsigned int *num_planes,
+		       unsigned int sizes[], struct device *alloc_devs[])
 {
 	struct cx8800_dev *dev = q->drv_priv;
 
@@ -121,7 +125,6 @@ static int queue_setup(struct vb2_queue
 	return 0;
 }
 
-
 static int buffer_prepare(struct vb2_buffer *vb)
 {
 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -175,7 +178,7 @@ static void buffer_queue(struct vb2_buff
 	if (list_empty(&q->active)) {
 		list_add_tail(&buf->list, &q->active);
 		cx8800_start_vbi_dma(dev, q, buf);
-		dprintk(2,"[%p/%d] vbi_queue - first active\n",
+		dprintk(2, "[%p/%d] vbi_queue - first active\n",
 			buf, buf->vb.vb2_buf.index);
 
 	} else {
@@ -183,7 +186,7 @@ static void buffer_queue(struct vb2_buff
 		prev = list_entry(q->active.prev, struct cx88_buffer, list);
 		list_add_tail(&buf->list, &q->active);
 		prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
-		dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+		dprintk(2, "[%p/%d] buffer_queue - append to active\n",
 			buf, buf->vb.vb2_buf.index);
 	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-video.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-video.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,12 +19,10 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *
- *  You 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 "cx88.h"
+
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -37,7 +35,6 @@
 #include <linux/kthread.h>
 #include <asm/div64.h>
 
-#include "cx88.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-event.h>
@@ -58,20 +55,23 @@ module_param_array(video_nr, int, NULL,
 module_param_array(vbi_nr,   int, NULL, 0444);
 module_param_array(radio_nr, int, NULL, 0444);
 
-MODULE_PARM_DESC(video_nr,"video device numbers");
-MODULE_PARM_DESC(vbi_nr,"vbi device numbers");
-MODULE_PARM_DESC(radio_nr,"radio device numbers");
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
 
 static unsigned int video_debug;
-module_param(video_debug,int,0644);
-MODULE_PARM_DESC(video_debug,"enable debug messages [video]");
+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]");
+module_param(irq_debug, int, 0644);
+MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]");
 
-#define dprintk(level,fmt, arg...)	if (video_debug >= level) \
-	printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
+#define dprintk(level, fmt, arg...) do {			\
+	if (video_debug >= level)				\
+		printk(KERN_DEBUG pr_fmt("%s: video:" fmt),	\
+			__func__, ##arg);			\
+} while (0)
 
 /* ------------------------------------------------------------------- */
 /* static data                                                         */
@@ -83,55 +83,56 @@ static const struct cx8800_fmt formats[]
 		.cxformat = ColorFormatY8,
 		.depth    = 8,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "15 bpp RGB, le",
 		.fourcc   = V4L2_PIX_FMT_RGB555,
 		.cxformat = ColorFormatRGB15,
 		.depth    = 16,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "15 bpp RGB, be",
 		.fourcc   = V4L2_PIX_FMT_RGB555X,
 		.cxformat = ColorFormatRGB15 | ColorFormatBSWAP,
 		.depth    = 16,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "16 bpp RGB, le",
 		.fourcc   = V4L2_PIX_FMT_RGB565,
 		.cxformat = ColorFormatRGB16,
 		.depth    = 16,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "16 bpp RGB, be",
 		.fourcc   = V4L2_PIX_FMT_RGB565X,
 		.cxformat = ColorFormatRGB16 | ColorFormatBSWAP,
 		.depth    = 16,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "24 bpp RGB, le",
 		.fourcc   = V4L2_PIX_FMT_BGR24,
 		.cxformat = ColorFormatRGB24,
 		.depth    = 24,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "32 bpp RGB, le",
 		.fourcc   = V4L2_PIX_FMT_BGR32,
 		.cxformat = ColorFormatRGB32,
 		.depth    = 32,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "32 bpp RGB, be",
 		.fourcc   = V4L2_PIX_FMT_RGB32,
-		.cxformat = ColorFormatRGB32 | ColorFormatBSWAP | ColorFormatWSWAP,
+		.cxformat = ColorFormatRGB32 | ColorFormatBSWAP |
+			    ColorFormatWSWAP,
 		.depth    = 32,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "4:2:2, packed, YUYV",
 		.fourcc   = V4L2_PIX_FMT_YUYV,
 		.cxformat = ColorFormatYUY2,
 		.depth    = 16,
 		.flags    = FORMAT_FLAGS_PACKED,
-	},{
+	}, {
 		.name     = "4:2:2, packed, UYVY",
 		.fourcc   = V4L2_PIX_FMT_UYVY,
 		.cxformat = ColorFormatYUY2 | ColorFormatBSWAP,
@@ -140,13 +141,13 @@ static const struct cx8800_fmt formats[]
 	},
 };
 
-static const struct cx8800_fmt* format_by_fourcc(unsigned int fourcc)
+static const struct cx8800_fmt *format_by_fourcc(unsigned int fourcc)
 {
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(formats); i++)
 		if (formats[i].fourcc == fourcc)
-			return formats+i;
+			return formats + i;
 	return NULL;
 }
 
@@ -180,7 +181,7 @@ static const struct cx88_ctrl cx8800_vid
 		.reg           = MO_CONTR_BRIGHT,
 		.mask          = 0x00ff,
 		.shift         = 0,
-	},{
+	}, {
 		.id            = V4L2_CID_CONTRAST,
 		.minimum       = 0,
 		.maximum       = 0xff,
@@ -190,7 +191,7 @@ static const struct cx88_ctrl cx8800_vid
 		.reg           = MO_CONTR_BRIGHT,
 		.mask          = 0xff00,
 		.shift         = 8,
-	},{
+	}, {
 		.id            = V4L2_CID_HUE,
 		.minimum       = 0,
 		.maximum       = 0xff,
@@ -200,7 +201,7 @@ static const struct cx88_ctrl cx8800_vid
 		.reg           = MO_HUE,
 		.mask          = 0x00ff,
 		.shift         = 0,
-	},{
+	}, {
 		/* strictly, this only describes only U saturation.
 		 * V saturation is handled specially through code.
 		 */
@@ -220,8 +221,10 @@ static const struct cx88_ctrl cx8800_vid
 		.step          = 1,
 		.default_value = 0x0,
 		.off           = 0,
-		/* NOTE: the value is converted and written to both even
-		   and odd registers in the code */
+		/*
+		 * NOTE: the value is converted and written to both even
+		 * and odd registers in the code
+		 */
 		.reg           = MO_FILTER_ODD,
 		.mask          = 7 << 7,
 		.shift         = 7,
@@ -265,7 +268,7 @@ static const struct cx88_ctrl cx8800_aud
 		.sreg          = SHADOW_AUD_VOL_CTL,
 		.mask          = (1 << 6),
 		.shift         = 6,
-	},{
+	}, {
 		.id            = V4L2_CID_AUDIO_VOLUME,
 		.minimum       = 0,
 		.maximum       = 0x3f,
@@ -275,7 +278,7 @@ static const struct cx88_ctrl cx8800_aud
 		.sreg          = SHADOW_AUD_VOL_CTL,
 		.mask          = 0x3f,
 		.shift         = 0,
-	},{
+	}, {
 		.id            = V4L2_CID_AUDIO_BALANCE,
 		.minimum       = 0,
 		.maximum       = 0x7f,
@@ -299,10 +302,10 @@ int cx88_video_mux(struct cx88_core *cor
 {
 	/* struct cx88_core *core = dev->core; */
 
-	dprintk(1,"video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
+	dprintk(1, "video_mux: %d [vmux=%d,gpio=0x%x,0x%x,0x%x,0x%x]\n",
 		input, INPUT(input).vmux,
-		INPUT(input).gpio0,INPUT(input).gpio1,
-		INPUT(input).gpio2,INPUT(input).gpio3);
+		INPUT(input).gpio0, INPUT(input).gpio1,
+		INPUT(input).gpio2, INPUT(input).gpio3);
 	core->input = input;
 	cx_andor(MO_INPUT_FORMAT, 0x03 << 14, INPUT(input).vmux << 14);
 	cx_write(MO_GP3_IO, INPUT(input).gpio3);
@@ -325,19 +328,25 @@ int cx88_video_mux(struct cx88_core *cor
 		break;
 	}
 
-	/* if there are audioroutes defined, we have an external
-	   ADC to deal with audio */
+	/*
+	 * if there are audioroutes defined, we have an external
+	 * ADC to deal with audio
+	 */
 	if (INPUT(input).audioroute) {
-		/* The wm8775 module has the "2" route hardwired into
-		   the initialization. Some boards may use different
-		   routes for different inputs. HVR-1300 surely does */
+		/*
+		 * The wm8775 module has the "2" route hardwired into
+		 * the initialization. Some boards may use different
+		 * routes for different inputs. HVR-1300 surely does
+		 */
 		if (core->sd_wm8775) {
 			call_all(core, audio, s_routing,
 				 INPUT(input).audioroute, 0, 0);
 		}
-		/* cx2388's C-ADC is connected to the tuner only.
-		   When used with S-Video, that ADC is busy dealing with
-		   chroma, so an external must be used for baseband audio */
+		/*
+		 * cx2388's C-ADC is connected to the tuner only.
+		 * When used with S-Video, that ADC is busy dealing with
+		 * chroma, so an external must be used for baseband audio
+		 */
 		if (INPUT(input).type != CX88_VMUX_TELEVISION &&
 		    INPUT(input).type != CX88_VMUX_CABLE) {
 			/* "I2S ADC mode" */
@@ -369,26 +378,27 @@ static int start_video_dma(struct cx8800
 	cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma);
 
 	/* reset counter */
-	cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
+	cx_write(MO_VIDY_GPCNTRL, GP_COUNT_CONTROL_RESET);
 	q->count = 0;
 
 	/* enable irqs */
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_VIDINT);
 
-	/* Enables corresponding bits at PCI_INT_STAT:
-		bits 0 to 4: video, audio, transport stream, VIP, Host
-		bit 7: timer
-		bits 8 and 9: DMA complete for: SRC, DST
-		bits 10 and 11: BERR signal asserted for RISC: RD, WR
-		bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
+	/*
+	 * Enables corresponding bits at PCI_INT_STAT:
+	 *	bits 0 to 4: video, audio, transport stream, VIP, Host
+	 *	bit 7: timer
+	 *	bits 8 and 9: DMA complete for: SRC, DST
+	 *	bits 10 and 11: BERR signal asserted for RISC: RD, WR
+	 *	bits 12 to 15: BERR signal asserted for: BRDG, SRC, DST, IPB
 	 */
 	cx_set(MO_VID_INTMSK, 0x0f0011);
 
 	/* enable capture */
-	cx_set(VID_CAPTURE_CONTROL,0x06);
+	cx_set(VID_CAPTURE_CONTROL, 0x06);
 
 	/* start dma */
-	cx_set(MO_DEV_CNTRL2, (1<<5));
+	cx_set(MO_DEV_CNTRL2, (1 << 5));
 	cx_set(MO_VID_DMACNTRL, 0x11); /* Planar Y and packed FIFO and RISC enable */
 
 	return 0;
@@ -403,7 +413,7 @@ static int stop_video_dma(struct cx8800_
 	cx_clear(MO_VID_DMACNTRL, 0x11);
 
 	/* disable capture */
-	cx_clear(VID_CAPTURE_CONTROL,0x06);
+	cx_clear(VID_CAPTURE_CONTROL, 0x06);
 
 	/* disable irqs */
 	cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
@@ -414,12 +424,11 @@ static int stop_video_dma(struct cx8800_
 static int restart_video_queue(struct cx8800_dev    *dev,
 			       struct cx88_dmaqueue *q)
 {
-	struct cx88_core *core = dev->core;
 	struct cx88_buffer *buf;
 
 	if (!list_empty(&q->active)) {
 		buf = list_entry(q->active.next, struct cx88_buffer, list);
-		dprintk(2,"restart_queue [%p/%d]: restart dma\n",
+		dprintk(2, "restart_queue [%p/%d]: restart dma\n",
 			buf, buf->vb.vb2_buf.index);
 		start_video_dma(dev, q, buf);
 	}
@@ -430,8 +439,8 @@ static int restart_video_queue(struct cx
 /* ------------------------------------------------------------------ */
 
 static int queue_setup(struct vb2_queue *q,
-			   unsigned int *num_buffers, unsigned int *num_planes,
-			   unsigned int sizes[], struct device *alloc_devs[])
+		       unsigned int *num_buffers, unsigned int *num_planes,
+		       unsigned int sizes[], struct device *alloc_devs[])
 {
 	struct cx8800_dev *dev = q->drv_priv;
 	struct cx88_core *core = dev->core;
@@ -488,7 +497,8 @@ static int buffer_prepare(struct vb2_buf
 				 core->height >> 1);
 		break;
 	}
-	dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
+	dprintk(2,
+		"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
 		buf, buf->vb.vb2_buf.index,
 		core->width, core->height, dev->fmt->depth, dev->fmt->name,
 		(unsigned long)buf->risc.dma);
@@ -513,7 +523,6 @@ static void buffer_queue(struct vb2_buff
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx88_buffer    *buf = container_of(vbuf, struct cx88_buffer, vb);
 	struct cx88_buffer    *prev;
-	struct cx88_core      *core = dev->core;
 	struct cx88_dmaqueue  *q    = &dev->vidq;
 
 	/* add jump to start */
@@ -523,7 +532,7 @@ static void buffer_queue(struct vb2_buff
 
 	if (list_empty(&q->active)) {
 		list_add_tail(&buf->list, &q->active);
-		dprintk(2,"[%p/%d] buffer_queue - first active\n",
+		dprintk(2, "[%p/%d] buffer_queue - first active\n",
 			buf, buf->vb.vb2_buf.index);
 
 	} else {
@@ -596,7 +605,7 @@ static int radio_open(struct file *file)
 	if (core->board.radio.audioroute) {
 		if (core->sd_wm8775) {
 			call_all(core, audio, s_routing,
-					core->board.radio.audioroute, 0, 0);
+				 core->board.radio.audioroute, 0, 0);
 		}
 		/* "I2S ADC mode" */
 		core->tvaudio = WW_I2SADC;
@@ -650,9 +659,10 @@ static int cx8800_s_vid_ctrl(struct v4l2
 		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
 		break;
 	}
-	dprintk(1, "set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
-				ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
-				mask, cc->sreg ? " [shadowed]" : "");
+	dprintk(1,
+		"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+		ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
+		mask, cc->sreg ? " [shadowed]" : "");
 	if (cc->sreg)
 		cx_sandor(cc->sreg, cc->reg, mask, value);
 	else
@@ -665,7 +675,7 @@ static int cx8800_s_aud_ctrl(struct v4l2
 	struct cx88_core *core =
 		container_of(ctrl->handler, struct cx88_core, audio_hdl);
 	const struct cx88_ctrl *cc = ctrl->priv;
-	u32 value,mask;
+	u32 value, mask;
 
 	/* Pass changes onto any WM8775 */
 	if (core->sd_wm8775) {
@@ -688,7 +698,8 @@ static int cx8800_s_aud_ctrl(struct v4l2
 	mask = cc->mask;
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_BALANCE:
-		value = (ctrl->val < 0x40) ? (0x7f - ctrl->val) : (ctrl->val - 0x40);
+		value = (ctrl->val < 0x40) ?
+			(0x7f - ctrl->val) : (ctrl->val - 0x40);
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
 		value = 0x3f - (ctrl->val & 0x3f);
@@ -697,9 +708,10 @@ static int cx8800_s_aud_ctrl(struct v4l2
 		value = ((ctrl->val - cc->off) << cc->shift) & cc->mask;
 		break;
 	}
-	dprintk(1,"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
-				ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
-				mask, cc->sreg ? " [shadowed]" : "");
+	dprintk(1,
+		"set_control id=0x%X(%s) ctrl=0x%02x, reg=0x%02x val=0x%02x (mask 0x%02x)%s\n",
+		ctrl->id, ctrl->name, ctrl->val, cc->reg, value,
+		mask, cc->sreg ? " [shadowed]" : "");
 	if (cc->sreg)
 		cx_sandor(cc->sreg, cc->reg, mask, value);
 	else
@@ -711,7 +723,7 @@ static int cx8800_s_aud_ctrl(struct v4l2
 /* VIDEO IOCTLS                                                       */
 
 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-					struct v4l2_format *f)
+				struct v4l2_format *f)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -729,7 +741,7 @@ static int vidioc_g_fmt_vid_cap(struct f
 }
 
 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-			struct v4l2_format *f)
+				  struct v4l2_format *f)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -738,7 +750,7 @@ static int vidioc_try_fmt_vid_cap(struct
 	unsigned int      maxw, maxh;
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-	if (NULL == fmt)
+	if (!fmt)
 		return -EINVAL;
 
 	maxw = norm_maxw(core->tvnorm);
@@ -775,13 +787,13 @@ static int vidioc_try_fmt_vid_cap(struct
 }
 
 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-					struct v4l2_format *f)
+				struct v4l2_format *f)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
-	int err = vidioc_try_fmt_vid_cap (file,priv,f);
+	int err = vidioc_try_fmt_vid_cap(file, priv, f);
 
-	if (0 != err)
+	if (err != 0)
 		return err;
 	if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq))
 		return -EBUSY;
@@ -795,13 +807,13 @@ static int vidioc_s_fmt_vid_cap(struct f
 }
 
 void cx88_querycap(struct file *file, struct cx88_core *core,
-		struct v4l2_capability *cap)
+		   struct v4l2_capability *cap)
 {
 	struct video_device *vdev = video_devdata(file);
 
 	strlcpy(cap->card, core->board.name, sizeof(cap->card));
 	cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-	if (UNSET != core->board.tuner_type)
+	if (core->board.tuner_type != UNSET)
 		cap->device_caps |= V4L2_CAP_TUNER;
 	switch (vdev->vfl_type) {
 	case VFL_TYPE_RADIO:
@@ -822,7 +834,7 @@ void cx88_querycap(struct file *file, st
 EXPORT_SYMBOL(cx88_querycap);
 
 static int vidioc_querycap(struct file *file, void  *priv,
-					struct v4l2_capability *cap)
+			   struct v4l2_capability *cap)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -833,13 +845,13 @@ static int vidioc_querycap(struct file *
 	return 0;
 }
 
-static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
-					struct v4l2_fmtdesc *f)
+static int 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));
+	strlcpy(f->description, formats[f->index].name, sizeof(f->description));
 	f->pixelformat = formats[f->index].fourcc;
 
 	return 0;
@@ -863,45 +875,46 @@ static int vidioc_s_std(struct file *fil
 }
 
 /* only one input in this sample driver */
-int cx88_enum_input (struct cx88_core  *core,struct v4l2_input *i)
+int cx88_enum_input(struct cx88_core  *core, struct v4l2_input *i)
 {
 	static const char * const iname[] = {
-		[ CX88_VMUX_COMPOSITE1 ] = "Composite1",
-		[ CX88_VMUX_COMPOSITE2 ] = "Composite2",
-		[ CX88_VMUX_COMPOSITE3 ] = "Composite3",
-		[ CX88_VMUX_COMPOSITE4 ] = "Composite4",
-		[ CX88_VMUX_SVIDEO     ] = "S-Video",
-		[ CX88_VMUX_TELEVISION ] = "Television",
-		[ CX88_VMUX_CABLE      ] = "Cable TV",
-		[ CX88_VMUX_DVB        ] = "DVB",
-		[ CX88_VMUX_DEBUG      ] = "for debug only",
+		[CX88_VMUX_COMPOSITE1] = "Composite1",
+		[CX88_VMUX_COMPOSITE2] = "Composite2",
+		[CX88_VMUX_COMPOSITE3] = "Composite3",
+		[CX88_VMUX_COMPOSITE4] = "Composite4",
+		[CX88_VMUX_SVIDEO] = "S-Video",
+		[CX88_VMUX_TELEVISION] = "Television",
+		[CX88_VMUX_CABLE] = "Cable TV",
+		[CX88_VMUX_DVB] = "DVB",
+		[CX88_VMUX_DEBUG] = "for debug only",
 	};
 	unsigned int n = i->index;
 
 	if (n >= 4)
 		return -EINVAL;
-	if (0 == INPUT(n).type)
+	if (!INPUT(n).type)
 		return -EINVAL;
 	i->type  = V4L2_INPUT_TYPE_CAMERA;
-	strcpy(i->name,iname[INPUT(n).type]);
-	if ((CX88_VMUX_TELEVISION == INPUT(n).type) ||
-	    (CX88_VMUX_CABLE      == INPUT(n).type)) {
+	strcpy(i->name, iname[INPUT(n).type]);
+	if ((INPUT(n).type == CX88_VMUX_TELEVISION) ||
+	    (INPUT(n).type == CX88_VMUX_CABLE))
 		i->type = V4L2_INPUT_TYPE_TUNER;
-	}
+
 	i->std = CX88_NORMS;
 	return 0;
 }
 EXPORT_SYMBOL(cx88_enum_input);
 
-static int vidioc_enum_input (struct file *file, void *priv,
-				struct v4l2_input *i)
+static int vidioc_enum_input(struct file *file, void *priv,
+			     struct v4l2_input *i)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
-	return cx88_enum_input (core,i);
+
+	return cx88_enum_input(core, i);
 }
 
-static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -910,31 +923,31 @@ static int vidioc_g_input (struct file *
 	return 0;
 }
 
-static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 
 	if (i >= 4)
 		return -EINVAL;
-	if (0 == INPUT(i).type)
+	if (!INPUT(i).type)
 		return -EINVAL;
 
 	cx88_newstation(core);
-	cx88_video_mux(core,i);
+	cx88_video_mux(core, i);
 	return 0;
 }
 
-static int vidioc_g_tuner (struct file *file, void *priv,
-				struct v4l2_tuner *t)
+static int vidioc_g_tuner(struct file *file, void *priv,
+			  struct v4l2_tuner *t)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 	u32 reg;
 
-	if (unlikely(UNSET == core->board.tuner_type))
+	if (unlikely(core->board.tuner_type == UNSET))
 		return -EINVAL;
-	if (0 != t->index)
+	if (t->index != 0)
 		return -EINVAL;
 
 	strcpy(t->name, "Television");
@@ -942,34 +955,34 @@ static int vidioc_g_tuner (struct file *
 	t->rangehigh  = 0xffffffffUL;
 	call_all(core, tuner, g_tuner, t);
 
-	cx88_get_stereo(core ,t);
+	cx88_get_stereo(core, t);
 	reg = cx_read(MO_DEVICE_STATUS);
-	t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
+	t->signal = (reg & (1 << 5)) ? 0xffff : 0x0000;
 	return 0;
 }
 
-static int vidioc_s_tuner (struct file *file, void *priv,
-				const struct v4l2_tuner *t)
+static int vidioc_s_tuner(struct file *file, void *priv,
+			  const struct v4l2_tuner *t)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 
-	if (UNSET == core->board.tuner_type)
+	if (core->board.tuner_type == UNSET)
 		return -EINVAL;
-	if (0 != t->index)
+	if (t->index != 0)
 		return -EINVAL;
 
 	cx88_set_stereo(core, t->audmode, 1);
 	return 0;
 }
 
-static int vidioc_g_frequency (struct file *file, void *priv,
-				struct v4l2_frequency *f)
+static int vidioc_g_frequency(struct file *file, void *priv,
+			      struct v4l2_frequency *f)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 
-	if (unlikely(UNSET == core->board.tuner_type))
+	if (unlikely(core->board.tuner_type == UNSET))
 		return -EINVAL;
 	if (f->tuner)
 		return -EINVAL;
@@ -981,12 +994,12 @@ static int vidioc_g_frequency (struct fi
 	return 0;
 }
 
-int cx88_set_freq (struct cx88_core  *core,
-				const struct v4l2_frequency *f)
+int cx88_set_freq(struct cx88_core  *core,
+		  const struct v4l2_frequency *f)
 {
 	struct v4l2_frequency new_freq = *f;
 
-	if (unlikely(UNSET == core->board.tuner_type))
+	if (unlikely(core->board.tuner_type == UNSET))
 		return -EINVAL;
 	if (unlikely(f->tuner != 0))
 		return -EINVAL;
@@ -997,15 +1010,15 @@ int cx88_set_freq (struct cx88_core  *co
 	core->freq = new_freq.frequency;
 
 	/* When changing channels it is required to reset TVAUDIO */
-	msleep (10);
+	usleep_range(10000, 20000);
 	cx88_set_tvaudio(core);
 
 	return 0;
 }
 EXPORT_SYMBOL(cx88_set_freq);
 
-static int vidioc_s_frequency (struct file *file, void *priv,
-				const struct v4l2_frequency *f)
+static int vidioc_s_frequency(struct file *file, void *priv,
+			      const struct v4l2_frequency *f)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -1014,8 +1027,8 @@ static int vidioc_s_frequency (struct fi
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register (struct file *file, void *fh,
-				struct v4l2_dbg_register *reg)
+static int vidioc_g_register(struct file *file, void *fh,
+			     struct v4l2_dbg_register *reg)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -1026,8 +1039,8 @@ static int vidioc_g_register (struct fil
 	return 0;
 }
 
-static int vidioc_s_register (struct file *file, void *fh,
-				const struct v4l2_dbg_register *reg)
+static int vidioc_s_register(struct file *file, void *fh,
+			     const struct v4l2_dbg_register *reg)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -1041,8 +1054,8 @@ static int vidioc_s_register (struct fil
 /* RADIO ESPECIFIC IOCTLS                                      */
 /* ----------------------------------------------------------- */
 
-static int radio_g_tuner (struct file *file, void *priv,
-				struct v4l2_tuner *t)
+static int radio_g_tuner(struct file *file, void *priv,
+			 struct v4l2_tuner *t)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
@@ -1056,13 +1069,13 @@ static int radio_g_tuner (struct file *f
 	return 0;
 }
 
-static int radio_s_tuner (struct file *file, void *priv,
-				const struct v4l2_tuner *t)
+static int radio_s_tuner(struct file *file, void *priv,
+			 const struct v4l2_tuner *t)
 {
 	struct cx8800_dev *dev = video_drvdata(file);
 	struct cx88_core *core = dev->core;
 
-	if (0 != t->index)
+	if (t->index != 0)
 		return -EINVAL;
 
 	call_all(core, tuner, s_tuner, t);
@@ -1090,13 +1103,13 @@ static void cx8800_vid_irq(struct cx8800
 		return;
 	cx_write(MO_VID_INTSTAT, status);
 	if (irq_debug  ||  (status & mask & ~0xff))
-		cx88_print_irqbits(core->name, "irq vid",
+		cx88_print_irqbits("irq vid",
 				   cx88_vid_irqs, ARRAY_SIZE(cx88_vid_irqs),
 				   status, mask);
 
 	/* risc op code error */
 	if (status & (1 << 16)) {
-		printk(KERN_WARNING "%s/0: video risc op code error\n",core->name);
+		pr_warn("video risc op code error\n");
 		cx_clear(MO_VID_DMACNTRL, 0x11);
 		cx_clear(VID_CAPTURE_CONTROL, 0x06);
 		cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
@@ -1129,20 +1142,19 @@ static irqreturn_t cx8800_irq(int irq, v
 	for (loop = 0; loop < 10; loop++) {
 		status = cx_read(MO_PCI_INTSTAT) &
 			(core->pci_irqmask | PCI_INT_VIDINT);
-		if (0 == status)
+		if (status == 0)
 			goto out;
 		cx_write(MO_PCI_INTSTAT, status);
 		handled = 1;
 
 		if (status & core->pci_irqmask)
-			cx88_core_irq(core,status);
+			cx88_core_irq(core, status);
 		if (status & PCI_INT_VIDINT)
 			cx8800_vid_irq(dev);
 	}
-	if (10 == loop) {
-		printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
-		       core->name);
-		cx_write(MO_PCI_INTMSK,0);
+	if (loop == 10) {
+		pr_warn("irq loop -- clearing mask\n");
+		cx_write(MO_PCI_INTMSK, 0);
 	}
 
  out:
@@ -1152,8 +1164,7 @@ static irqreturn_t cx8800_irq(int irq, v
 /* ----------------------------------------------------------- */
 /* exported stuff                                              */
 
-static const struct v4l2_file_operations video_fops =
-{
+static const struct v4l2_file_operations video_fops = {
 	.owner	       = THIS_MODULE,
 	.open	       = v4l2_fh_open,
 	.release       = vb2_fop_release,
@@ -1195,7 +1206,7 @@ static const struct v4l2_ioctl_ops video
 static const struct video_device cx8800_video_template = {
 	.name                 = "cx8800-video",
 	.fops                 = &video_fops,
-	.ioctl_ops 	      = &video_ioctl_ops,
+	.ioctl_ops	      = &video_ioctl_ops,
 	.tvnorms              = CX88_NORMS,
 };
 
@@ -1232,8 +1243,7 @@ static const struct video_device cx8800_
 	.tvnorms              = CX88_NORMS,
 };
 
-static const struct v4l2_file_operations radio_fops =
-{
+static const struct v4l2_file_operations radio_fops = {
 	.owner         = THIS_MODULE,
 	.open          = radio_open,
 	.poll          = v4l2_ctrl_poll,
@@ -1258,7 +1268,7 @@ static const struct v4l2_ioctl_ops radio
 static const struct video_device cx8800_radio_template = {
 	.name                 = "cx8800-radio",
 	.fops                 = &radio_fops,
-	.ioctl_ops 	      = &radio_ioctl_ops,
+	.ioctl_ops	      = &radio_ioctl_ops,
 };
 
 static const struct v4l2_ctrl_ops cx8800_ctrl_vid_ops = {
@@ -1287,8 +1297,8 @@ static int cx8800_initdev(struct pci_dev
 	int err;
 	int i;
 
-	dev = kzalloc(sizeof(*dev),GFP_KERNEL);
-	if (NULL == dev)
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
 		return -ENOMEM;
 
 	/* pci init */
@@ -1298,7 +1308,7 @@ static int cx8800_initdev(struct pci_dev
 		goto fail_free;
 	}
 	core = cx88_core_get(dev->pci);
-	if (NULL == core) {
+	if (!core) {
 		err = -EINVAL;
 		goto fail_free;
 	}
@@ -1307,15 +1317,15 @@ static int cx8800_initdev(struct pci_dev
 	/* print pci info */
 	dev->pci_rev = pci_dev->revision;
 	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
-	       "latency: %d, mmio: 0x%llx\n", core->name,
-	       pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
-	       dev->pci_lat,(unsigned long long)pci_resource_start(pci_dev,0));
+	pr_info("found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n",
+		pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
+		dev->pci_lat,
+		(unsigned long long)pci_resource_start(pci_dev, 0));
 
 	pci_set_master(pci_dev);
-	err = pci_set_dma_mask(pci_dev,DMA_BIT_MASK(32));
+	err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
 	if (err) {
-		printk("%s/0: Oops: no 32bit PCI DMA ???\n",core->name);
+		pr_err("Oops: no 32bit PCI DMA ???\n");
 		goto fail_core;
 	}
 
@@ -1332,8 +1342,7 @@ static int cx8800_initdev(struct pci_dev
 	err = request_irq(pci_dev->irq, cx8800_irq,
 			  IRQF_SHARED, core->name, dev);
 	if (err < 0) {
-		printk(KERN_ERR "%s/0: can't get IRQ %d\n",
-		       core->name,pci_dev->irq);
+		pr_err("can't get IRQ %d\n", pci_dev->irq);
 		goto fail_core;
 	}
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask);
@@ -1343,8 +1352,9 @@ static int cx8800_initdev(struct pci_dev
 		struct v4l2_ctrl *vc;
 
 		vc = v4l2_ctrl_new_std(&core->audio_hdl, &cx8800_ctrl_aud_ops,
-			cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
-		if (vc == NULL) {
+				       cc->id, cc->minimum, cc->maximum,
+				       cc->step, cc->default_value);
+		if (!vc) {
 			err = core->audio_hdl.error;
 			goto fail_core;
 		}
@@ -1356,8 +1366,9 @@ static int cx8800_initdev(struct pci_dev
 		struct v4l2_ctrl *vc;
 
 		vc = v4l2_ctrl_new_std(&core->video_hdl, &cx8800_ctrl_vid_ops,
-			cc->id, cc->minimum, cc->maximum, cc->step, cc->default_value);
-		if (vc == NULL) {
+				       cc->id, cc->minimum, cc->maximum,
+				       cc->step, cc->default_value);
+		if (!vc) {
 			err = core->video_hdl.error;
 			goto fail_core;
 		}
@@ -1383,18 +1394,20 @@ static int cx8800_initdev(struct pci_dev
 			core->wm8775_data.is_nova_s = false;
 
 		sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
-				&wm8775_info, NULL);
-		if (sd != NULL) {
+					       &wm8775_info, NULL);
+		if (sd) {
 			core->sd_wm8775 = sd;
 			sd->grp_id = WM8775_GID;
 		}
 	}
 
 	if (core->board.audio_chip == CX88_AUDIO_TVAUDIO) {
-		/* This probes for a tda9874 as is used on some
-		   Pixelview Ultra boards. */
+		/*
+		 * This probes for a tda9874 as is used on some
+		 * Pixelview Ultra boards.
+		 */
 		v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-				"tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
+				    "tvaudio", 0, I2C_ADDRS(0xb0 >> 1));
 	}
 
 	switch (core->boardnr) {
@@ -1470,12 +1483,11 @@ static int cx8800_initdev(struct pci_dev
 	err = video_register_device(&dev->video_dev, VFL_TYPE_GRABBER,
 				    video_nr[core->nr]);
 	if (err < 0) {
-		printk(KERN_ERR "%s/0: can't register video device\n",
-		       core->name);
+		pr_err("can't register video device\n");
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s/0: registered device %s [v4l2]\n",
-	       core->name, video_device_node_name(&dev->video_dev));
+	pr_info("registered device %s [v4l2]\n",
+		video_device_node_name(&dev->video_dev));
 
 	cx88_vdev_init(core, dev->pci, &dev->vbi_dev,
 		       &cx8800_vbi_template, "vbi");
@@ -1484,12 +1496,11 @@ static int cx8800_initdev(struct pci_dev
 	err = video_register_device(&dev->vbi_dev, VFL_TYPE_VBI,
 				    vbi_nr[core->nr]);
 	if (err < 0) {
-		printk(KERN_ERR "%s/0: can't register vbi device\n",
-		       core->name);
+		pr_err("can't register vbi device\n");
 		goto fail_unreg;
 	}
-	printk(KERN_INFO "%s/0: registered device %s\n",
-	       core->name, video_device_node_name(&dev->vbi_dev));
+	pr_info("registered device %s\n",
+		video_device_node_name(&dev->vbi_dev));
 
 	if (core->board.radio.type == CX88_RADIO) {
 		cx88_vdev_init(core, dev->pci, &dev->radio_dev,
@@ -1499,21 +1510,21 @@ static int cx8800_initdev(struct pci_dev
 		err = video_register_device(&dev->radio_dev, VFL_TYPE_RADIO,
 					    radio_nr[core->nr]);
 		if (err < 0) {
-			printk(KERN_ERR "%s/0: can't register radio device\n",
-			       core->name);
+			pr_err("can't register radio device\n");
 			goto fail_unreg;
 		}
-		printk(KERN_INFO "%s/0: registered device %s\n",
-		       core->name, video_device_node_name(&dev->radio_dev));
+		pr_info("registered device %s\n",
+			video_device_node_name(&dev->radio_dev));
 	}
 
 	/* start tvaudio thread */
 	if (core->board.tuner_type != UNSET) {
-		core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
+		core->kthread = kthread_run(cx88_audio_thread,
+					    core, "cx88 tvaudio");
 		if (IS_ERR(core->kthread)) {
 			err = PTR_ERR(core->kthread);
-			printk(KERN_ERR "%s/0: failed to create cx88 audio thread, err=%d\n",
-			       core->name, err);
+			pr_err("failed to create cx88 audio thread, err=%d\n",
+			       err);
 		}
 	}
 	mutex_unlock(&core->lock);
@@ -1526,7 +1537,7 @@ fail_unreg:
 	mutex_unlock(&core->lock);
 fail_core:
 	core->v4ldev = NULL;
-	cx88_core_put(core,dev->pci);
+	cx88_core_put(core, dev->pci);
 fail_free:
 	kfree(dev);
 	return err;
@@ -1557,7 +1568,7 @@ static void cx8800_finidev(struct pci_de
 	core->v4ldev = NULL;
 
 	/* free memory */
-	cx88_core_put(core,dev->pci);
+	cx88_core_put(core, dev->pci);
 	kfree(dev);
 }
 
@@ -1571,11 +1582,11 @@ static int cx8800_suspend(struct pci_dev
 	/* stop video+vbi capture */
 	spin_lock_irqsave(&dev->slock, flags);
 	if (!list_empty(&dev->vidq.active)) {
-		printk("%s/0: suspend video\n", core->name);
+		pr_info("suspend video\n");
 		stop_video_dma(dev);
 	}
 	if (!list_empty(&dev->vbiq.active)) {
-		printk("%s/0: suspend vbi\n", core->name);
+		pr_info("suspend vbi\n");
 		cx8800_stop_vbi_dma(dev);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
@@ -1586,7 +1597,8 @@ static int cx8800_suspend(struct pci_dev
 	cx88_shutdown(core);
 
 	pci_save_state(pci_dev);
-	if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
+	if (pci_set_power_state(pci_dev,
+				pci_choose_state(pci_dev, state)) != 0) {
 		pci_disable_device(pci_dev);
 		dev->state.disabled = 1;
 	}
@@ -1601,18 +1613,17 @@ static int cx8800_resume(struct pci_dev
 	int err;
 
 	if (dev->state.disabled) {
-		err=pci_enable_device(pci_dev);
+		err = pci_enable_device(pci_dev);
 		if (err) {
-			printk(KERN_ERR "%s/0: can't enable device\n",
-			       core->name);
+			pr_err("can't enable device\n");
 			return err;
 		}
 
 		dev->state.disabled = 0;
 	}
-	err= pci_set_power_state(pci_dev, PCI_D0);
+	err = pci_set_power_state(pci_dev, PCI_D0);
 	if (err) {
-		printk(KERN_ERR "%s/0: can't set power state\n", core->name);
+		pr_err("can't set power state\n");
 		pci_disable_device(pci_dev);
 		dev->state.disabled = 1;
 
@@ -1630,12 +1641,12 @@ static int cx8800_resume(struct pci_dev
 	/* restart video+vbi capture */
 	spin_lock_irqsave(&dev->slock, flags);
 	if (!list_empty(&dev->vidq.active)) {
-		printk("%s/0: resume video\n", core->name);
-		restart_video_queue(dev,&dev->vidq);
+		pr_info("resume video\n");
+		restart_video_queue(dev, &dev->vidq);
 	}
 	if (!list_empty(&dev->vbiq.active)) {
-		printk("%s/0: resume vbi\n", core->name);
-		cx8800_restart_vbi_queue(dev,&dev->vbiq);
+		pr_info("resume vbi\n");
+		cx8800_restart_vbi_queue(dev, &dev->vbiq);
 	}
 	spin_unlock_irqrestore(&dev->slock, flags);
 
@@ -1651,7 +1662,7 @@ static const struct pci_device_id cx8800
 		.device       = 0x8800,
 		.subvendor    = PCI_ANY_ID,
 		.subdevice    = PCI_ANY_ID,
-	},{
+	}, {
 		/* --- end of list --- */
 	}
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.c
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,35 +1,28 @@
 /*
+ * cx88-vp3054-i2c.c -- support for the secondary I2C bus of the
+ *			DNTV Live! DVB-T Pro (VP-3054), wired as:
+ *			GPIO[0] -> SCL, GPIO[1] -> SDA
+ *
+ * (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
-    cx88-vp3054-i2c.c  --  support for the secondary I2C bus of the
-			   DNTV Live! DVB-T Pro (VP-3054), wired as:
-			   GPIO[0] -> SCL, GPIO[1] -> SDA
-
-    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.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.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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 "cx88.h"
+#include "cx88-vp3054-i2c.h"
 
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-
-#include <asm/io.h>
-
-#include "cx88.h"
-#include "cx88-vp3054-i2c.h"
+#include <linux/io.h>
 
 MODULE_DESCRIPTION("driver for cx2388x VP3054 design");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -114,7 +107,7 @@ int vp3054_i2c_probe(struct cx8802_dev *
 		return 0;
 
 	vp3054_i2c = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
-	if (vp3054_i2c == NULL)
+	if (!vp3054_i2c)
 		return -ENOMEM;
 	dev->vp3054 = vp3054_i2c;
 
@@ -128,12 +121,12 @@ int vp3054_i2c_probe(struct cx8802_dev *
 	i2c_set_adapdata(&vp3054_i2c->adap, dev);
 	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
 
-	vp3054_bit_setscl(dev,1);
-	vp3054_bit_setsda(dev,1);
+	vp3054_bit_setscl(dev, 1);
+	vp3054_bit_setsda(dev, 1);
 
 	rc = i2c_bit_add_bus(&vp3054_i2c->adap);
-	if (0 != rc) {
-		printk("%s: vp3054_i2c register FAILED\n", core->name);
+	if (rc != 0) {
+		pr_err("vp3054_i2c register FAILED\n");
 
 		kfree(dev->vp3054);
 		dev->vp3054 = NULL;
@@ -141,18 +134,17 @@ int vp3054_i2c_probe(struct cx8802_dev *
 
 	return rc;
 }
+EXPORT_SYMBOL(vp3054_i2c_probe);
 
 void vp3054_i2c_remove(struct cx8802_dev *dev)
 {
 	struct vp3054_i2c_state *vp3054_i2c = dev->vp3054;
 
-	if (vp3054_i2c == NULL ||
+	if (!vp3054_i2c ||
 	    dev->core->boardnr != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
 		return;
 
 	i2c_del_adapter(&vp3054_i2c->adap);
 	kfree(vp3054_i2c);
 }
-
-EXPORT_SYMBOL(vp3054_i2c_probe);
 EXPORT_SYMBOL(vp3054_i2c_remove);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.h linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.h
--- linux-libre-4.9-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/cx88/cx88-vp3054-i2c.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,26 +1,20 @@
 /*
-
-    cx88-vp3054-i2c.h  --  support for the secondary I2C bus of the
-			   DNTV Live! DVB-T Pro (VP-3054), wired as:
-			   GPIO[0] -> SCL, GPIO[1] -> SDA
-
-    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.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.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You 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.
-
-*/
+ * cx88-vp3054-i2c.h  --  support for the secondary I2C bus of the
+ *			  DNTV Live! DVB-T Pro (VP-3054), wired as:
+ *			  GPIO[0] -> SCL, GPIO[1] -> SDA
+ *
+ * (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
 
 /* ----------------------------------------------------------------------- */
 struct vp3054_i2c_state {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ddbridge/ddbridge-core.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ddbridge/ddbridge-core.c
--- linux-libre-4.9-gnu/drivers/media/pci/ddbridge/ddbridge-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ddbridge/ddbridge-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -824,8 +824,7 @@ static int dvb_input_attach(struct ddb_i
 				   &input->port->dev->pdev->dev,
 				   adapter_nr);
 	if (ret < 0) {
-		printk(KERN_ERR "ddbridge: Could not register adapter."
-		       "Check if you enabled enough adapters in dvb-core!\n");
+		printk(KERN_ERR "ddbridge: Could not register adapter.Check if you enabled enough adapters in dvb-core!\n");
 		return ret;
 	}
 	input->attached = 1;
@@ -1730,8 +1729,7 @@ static __init int module_init_ddbridge(v
 {
 	int ret;
 
-	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
-	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
+	printk(KERN_INFO "Digital Devices PCIE bridge driver, Copyright (C) 2010-11 Digital Devices GmbH\n");
 
 	ret = ddb_class_create();
 	if (ret < 0)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/dm1105/dm1105.c linux-libre-4.10-rc8-gnu/drivers/media/pci/dm1105/dm1105.c
--- linux-libre-4.9-gnu/drivers/media/pci/dm1105/dm1105.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/dm1105/dm1105.c	2017-02-12 16:03:20.000000000 -0500
@@ -315,8 +315,7 @@ static void dm1105_card_list(struct pci_
 			"dm1105: Updating to the latest version might help\n"
 			"dm1105: as well.\n");
 	}
-	printk(KERN_ERR "Here is a list of valid choices for the card=<n> "
-		   "insmod option:\n");
+	printk(KERN_ERR "Here is a list of valid choices for the card=<n> insmod option:\n");
 	for (i = 0; i < ARRAY_SIZE(dm1105_boards); i++)
 		printk(KERN_ERR "dm1105:    card=%d -> %s\n",
 				i, dm1105_boards[i].name);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-alsa-main.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-alsa-main.c
--- linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-alsa-main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-alsa-main.c	2017-02-12 16:03:20.000000000 -0500
@@ -177,8 +177,8 @@ static int snd_ivtv_init(struct v4l2_dev
 #if 0
 	ret = snd_ivtv_mixer_create(itvsc);
 	if (ret) {
-		IVTV_ALSA_WARN("%s: snd_ivtv_mixer_create() failed with err %d:"
-			       " proceeding anyway\n", __func__, ret);
+		IVTV_ALSA_WARN("%s: snd_ivtv_mixer_create() failed with err %d: proceeding anyway\n",
+			       __func__, ret);
 	}
 #endif
 
@@ -235,8 +235,8 @@ static int ivtv_alsa_load(struct ivtv *i
 
 	s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
 	if (s->vdev.v4l2_dev == NULL) {
-		IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
-				     "skipping\n", __func__);
+		IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - skipping\n",
+				     __func__);
 		return 0;
 	}
 
@@ -250,8 +250,8 @@ static int ivtv_alsa_load(struct ivtv *i
 		IVTV_ALSA_ERR("%s: failed to create struct snd_ivtv_card\n",
 			      __func__);
 	} else {
-		IVTV_DEBUG_ALSA_INFO("%s: created ivtv ALSA interface instance "
-				     "\n", __func__);
+		IVTV_DEBUG_ALSA_INFO("%s: created ivtv ALSA interface instance \n",
+				     __func__);
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-driver.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-driver.c
--- linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-driver.c	2016-12-11 17:43:41.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-driver.c	2017-02-12 17:28:07.000000000 -0500
@@ -885,8 +885,8 @@ static int ivtv_setup_pci(struct ivtv *i
 	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 
 	if (pci_latency < 64 && ivtv_pci_latency) {
-		IVTV_INFO("Unreasonably low latency timer, "
-			       "setting to 64 (was %d)\n", pci_latency);
+		IVTV_INFO("Unreasonably low latency timer, setting to 64 (was %d)\n",
+			  pci_latency);
 		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 		pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
 	}
@@ -896,8 +896,7 @@ static int ivtv_setup_pci(struct ivtv *i
 	   these problems. */
 	pci_write_config_dword(pdev, 0x40, 0xffff);
 
-	IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, "
-		   "irq: %d, latency: %d, memory: 0x%llx\n",
+	IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, irq: %d, latency: %d, memory: 0x%llx\n",
 		   pdev->device, pdev->revision, pdev->bus->number,
 		   PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
 		   pdev->irq, pci_latency, (u64)itv->base_addr);
@@ -1047,13 +1046,10 @@ static int ivtv_probe(struct pci_dev *pd
 	itv->enc_mem = ioremap_nocache(itv->base_addr + IVTV_ENCODER_OFFSET,
 				       IVTV_ENCODER_SIZE);
 	if (!itv->enc_mem) {
-		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
-			 "encoder memory\n");
-		IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of "
-			 "vmalloc address space for this window\n");
+		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n");
+		IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n");
 		IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
-		IVTV_ERR("Use the vmalloc= kernel command line option to set "
-			 "VmallocTotal to a larger value\n");
+		IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
 		retval = -ENOMEM;
 		goto free_mem;
 	}
@@ -1064,14 +1060,10 @@ static int ivtv_probe(struct pci_dev *pd
 		itv->dec_mem = ioremap_nocache(itv->base_addr + IVTV_DECODER_OFFSET,
 				IVTV_DECODER_SIZE);
 		if (!itv->dec_mem) {
-			IVTV_ERR("ioremap failed. Can't get a window into "
-				 "CX23415 decoder memory\n");
-			IVTV_ERR("Each capture card with a CX23415 needs 8 MB "
-				 "of vmalloc address space for this window\n");
-			IVTV_ERR("Check the output of 'grep Vmalloc "
-				 "/proc/meminfo'\n");
-			IVTV_ERR("Use the vmalloc= kernel command line option "
-				 "to set VmallocTotal to a larger value\n");
+			IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n");
+			IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n");
+			IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
+			IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
 			retval = -ENOMEM;
 			goto free_mem;
 		}
@@ -1086,13 +1078,10 @@ static int ivtv_probe(struct pci_dev *pd
 	itv->reg_mem =
 	    ioremap_nocache(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
 	if (!itv->reg_mem) {
-		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 "
-			 "register space\n");
-		IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of "
-			 "vmalloc address space for this window\n");
+		IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n");
+		IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n");
 		IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
-		IVTV_ERR("Use the vmalloc= kernel command line option to set "
-			 "VmallocTotal to a larger value\n");
+		IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
 		retval = -ENOMEM;
 		goto free_io;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-driver.h linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-driver.h
--- linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-driver.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-driver.h	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/byteorder.h>
 
 #include <linux/dvb/video.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtvfb.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtvfb.c
--- linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtvfb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtvfb.c	2017-02-12 16:03:20.000000000 -0500
@@ -293,8 +293,7 @@ static int ivtvfb_prep_dec_dma_to_device
 	/* Map User DMA */
 	if (ivtv_udma_setup(itv, ivtv_dest_addr, userbuf, size_in_bytes) <= 0) {
 		mutex_unlock(&itv->udma.lock);
-		IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, "
-			       "Error with get_user_pages: %d bytes, %d pages returned\n",
+		IVTVFB_WARN("ivtvfb_prep_dec_dma_to_device, Error with get_user_pages: %d bytes, %d pages returned\n",
 			       size_in_bytes, itv->udma.page_count);
 
 		/* get_user_pages must have failed completely */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-firmware.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-firmware.c
--- linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-firmware.c	2016-12-11 17:47:51.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-firmware.c	2017-02-12 17:35:14.000000000 -0500
@@ -376,8 +376,8 @@ int ivtv_firmware_check(struct ivtv *itv
 	/* If something failed & currently idle, try to reload */
 	if (res && !atomic_read(&itv->capturing) &&
 						!atomic_read(&itv->decoding)) {
-		IVTV_INFO("Detected in %s that firmware had failed - "
-			  "Reloading\n", where);
+		IVTV_INFO("Detected in %s that firmware had failed - Reloading\n",
+			  where);
 		res = ivtv_firmware_restart(itv);
 		/*
 		 * Even if restarted ok, still signal a problem had occurred.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-yuv.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-yuv.c
--- linux-libre-4.9-gnu/drivers/media/pci/ivtv/ivtv-yuv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ivtv/ivtv-yuv.c	2017-02-12 16:03:20.000000000 -0500
@@ -89,8 +89,8 @@ static int ivtv_yuv_prep_user_dma(struct
 
 		if (y_pages == y_dma.page_count) {
 			IVTV_DEBUG_WARN
-				("failed to map uv user pages, returned %d "
-				 "expecting %d\n", uv_pages, uv_dma.page_count);
+				("failed to map uv user pages, returned %d expecting %d\n",
+				 uv_pages, uv_dma.page_count);
 
 			if (uv_pages >= 0) {
 				for (i = 0; i < uv_pages; i++)
@@ -101,8 +101,8 @@ static int ivtv_yuv_prep_user_dma(struct
 			}
 		} else {
 			IVTV_DEBUG_WARN
-				("failed to map y user pages, returned %d "
-				 "expecting %d\n", y_pages, y_dma.page_count);
+				("failed to map y user pages, returned %d expecting %d\n",
+				 y_pages, y_dma.page_count);
 		}
 		if (y_pages >= 0) {
 			for (i = 0; i < y_pages; i++)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/meye/meye.c linux-libre-4.10-rc8-gnu/drivers/media/pci/meye/meye.c
--- linux-libre-4.9-gnu/drivers/media/pci/meye/meye.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/meye/meye.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
@@ -60,8 +60,7 @@ MODULE_PARM_DESC(gbuffers, "number of ca
 /* size of a grab buffer */
 static unsigned int gbufsize = MEYE_MAX_BUFSIZE;
 module_param(gbufsize, int, 0444);
-MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400"
-		 " (will be rounded up to a page multiple)");
+MODULE_PARM_DESC(gbufsize, "size of the capture buffers, default is 614400 (will be rounded up to a page multiple)");
 
 /* /dev/videoX registration number */
 static int video_nr = -1;
@@ -587,10 +586,7 @@ static void mchip_hic_stop(void)
 /* get the next ready frame from the dma engine */
 static u32 mchip_get_frame(void)
 {
-	u32 v;
-
-	v = mchip_read(MCHIP_MM_FIR(meye.mchip_fnum));
-	return v;
+	return mchip_read(MCHIP_MM_FIR(meye.mchip_fnum));
 }
 
 /* frees the current frame from the dma engine */
@@ -1261,8 +1257,7 @@ static int vidioc_reqbufs(struct file *f
 	meye.grab_fbuffer = rvmalloc(gbuffers * gbufsize);
 
 	if (!meye.grab_fbuffer) {
-		printk(KERN_ERR "meye: v4l framebuffer allocation"
-				" failed\n");
+		printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");
 		mutex_unlock(&meye.lock);
 		return -ENOMEM;
 	}
@@ -1659,8 +1654,7 @@ static int meye_probe(struct pci_dev *pc
 	ret = -EIO;
 	if ((ret = sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 1))) {
 		v4l2_err(v4l2_dev, "meye: unable to power on the camera\n");
-		v4l2_err(v4l2_dev, "meye: did you enable the camera in "
-				"sonypi using the module options ?\n");
+		v4l2_err(v4l2_dev, "meye: did you enable the camera in sonypi using the module options ?\n");
 		goto outsonypienable;
 	}
 
@@ -1834,8 +1828,7 @@ static int __init meye_init(void)
 	if (gbufsize > MEYE_MAX_BUFSIZE)
 		gbufsize = MEYE_MAX_BUFSIZE;
 	gbufsize = PAGE_ALIGN(gbufsize);
-	printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) "
-			 "for capture\n",
+	printk(KERN_INFO "meye: using %d buffers with %dk (%dk total) for capture\n",
 			 gbuffers,
 			 gbufsize / 1024, gbuffers * gbufsize / 1024);
 	return pci_register_driver(&meye_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/netup_unidvb/netup_unidvb_core.c linux-libre-4.10-rc8-gnu/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
--- linux-libre-4.9-gnu/drivers/media/pci/netup_unidvb/netup_unidvb_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/netup_unidvb/netup_unidvb_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1030,15 +1030,4 @@ static struct pci_driver netup_unidvb_pc
 	.resume   = NULL,
 };
 
-static int __init netup_unidvb_init(void)
-{
-	return pci_register_driver(&netup_unidvb_pci_driver);
-}
-
-static void __exit netup_unidvb_fini(void)
-{
-	pci_unregister_driver(&netup_unidvb_pci_driver);
-}
-
-module_init(netup_unidvb_init);
-module_exit(netup_unidvb_fini);
+module_pci_driver(netup_unidvb_pci_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/pluto2/pluto2.c linux-libre-4.10-rc8-gnu/drivers/media/pci/pluto2/pluto2.c
--- linux-libre-4.9-gnu/drivers/media/pci/pluto2/pluto2.c	2016-12-11 17:46:40.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/pluto2/pluto2.c	2017-02-12 17:33:13.000000000 -0500
@@ -577,12 +577,12 @@ static int pluto_read_serial(struct plut
 		for (j = 0; j < 32; j += 8) {
 			if ((val & 0xff) == 0xff)
 				goto out;
-			printk("%c", val & 0xff);
+			printk(KERN_CONT "%c", val & 0xff);
 			val >>= 8;
 		}
 	}
 out:
-	printk("\n");
+	printk(KERN_CONT "\n");
 	pci_iounmap(pdev, cis);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/pt1/pt1.c linux-libre-4.10-rc8-gnu/drivers/media/pci/pt1/pt1.c
--- linux-libre-4.9-gnu/drivers/media/pci/pt1/pt1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/pt1/pt1.c	2017-02-12 16:03:20.000000000 -0500
@@ -282,13 +282,12 @@ static int pt1_filter(struct pt1 *pt1, s
 			continue;
 
 		if (upacket >> 24 & 1)
-			printk_ratelimited(KERN_INFO "earth-pt1: device "
-				"buffer overflowing. table[%d] buf[%d]\n",
+			printk_ratelimited(KERN_INFO "earth-pt1: device buffer overflowing. table[%d] buf[%d]\n",
 				pt1->table_index, pt1->buf_index);
 		sc = upacket >> 26 & 0x7;
 		if (adap->st_count != -1 && sc != ((adap->st_count + 1) & 0x7))
-			printk_ratelimited(KERN_INFO "earth-pt1: data loss"
-				" in streamID(adapter)[%d]\n", index);
+			printk_ratelimited(KERN_INFO "earth-pt1: data loss in streamID(adapter)[%d]\n",
+					   index);
 		adap->st_count = sc;
 
 		buf = adap->buf;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/pt1/va1j5jf8007s.c linux-libre-4.10-rc8-gnu/drivers/media/pci/pt1/va1j5jf8007s.c
--- linux-libre-4.9-gnu/drivers/media/pci/pt1/va1j5jf8007s.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/pt1/va1j5jf8007s.c	2017-02-12 16:03:20.000000000 -0500
@@ -578,7 +578,7 @@ static void va1j5jf8007s_release(struct
 	kfree(state);
 }
 
-static struct dvb_frontend_ops va1j5jf8007s_ops = {
+static const struct dvb_frontend_ops va1j5jf8007s_ops = {
 	.delsys = { SYS_ISDBS },
 	.info = {
 		.name = "VA1J5JF8007/VA1J5JF8011 ISDB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/pt1/va1j5jf8007t.c linux-libre-4.10-rc8-gnu/drivers/media/pci/pt1/va1j5jf8007t.c
--- linux-libre-4.9-gnu/drivers/media/pci/pt1/va1j5jf8007t.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/pt1/va1j5jf8007t.c	2017-02-12 16:03:20.000000000 -0500
@@ -427,7 +427,7 @@ static void va1j5jf8007t_release(struct
 	kfree(state);
 }
 
-static struct dvb_frontend_ops va1j5jf8007t_ops = {
+static const struct dvb_frontend_ops va1j5jf8007t_ops = {
 	.delsys = { SYS_ISDBT },
 	.info = {
 		.name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/pt3/pt3.c linux-libre-4.10-rc8-gnu/drivers/media/pci/pt3/pt3.c
--- linux-libre-4.9-gnu/drivers/media/pci/pt3/pt3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/pt3/pt3.c	2017-02-12 16:03:20.000000000 -0500
@@ -463,7 +463,7 @@ static int pt3_fetch_thread(void *data)
 
 		pt3_proc_dma(adap);
 
-		delay = ktime_set(0, PT3_FETCH_DELAY * NSEC_PER_MSEC);
+		delay = PT3_FETCH_DELAY * NSEC_PER_MSEC;
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		freezable_schedule_hrtimeout_range(&delay,
 					PT3_FETCH_DELAY_DELTA * NSEC_PER_MSEC,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-alsa.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-alsa.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-alsa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-alsa.c	2017-02-12 16:03:20.000000000 -0500
@@ -813,8 +813,7 @@ static int snd_card_saa7134_capture_open
 	int amux, err;
 
 	if (!saa7134) {
-		pr_err("BUG: saa7134 can't find device struct."
-				" Can't proceed with open\n");
+		pr_err("BUG: saa7134 can't find device struct. Can't proceed with open\n");
 		return -ENODEV;
 	}
 	dev = saa7134->dev;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-cards.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-cards.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-cards.c	2016-12-11 17:43:41.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-cards.c	2017-02-12 17:28:07.000000000 -0500
@@ -7341,8 +7341,8 @@ static void hauppauge_eeprom(struct saa7
 	case 67659: /* WinTV-HVR1110 (OEM, no IR, hybrid, FM, SVid/Comp, RCA aud) */
 		break;
 	default:
-		pr_warn("%s: warning: "
-		       "unknown hauppauge model #%d\n", dev->name, tv.model);
+		pr_warn("%s: warning: unknown hauppauge model #%d\n",
+			dev->name, tv.model);
 		break;
 	}
 
@@ -7920,8 +7920,8 @@ int saa7134_board_init2(struct saa7134_d
 		msg.addr = 0x0b;
 		msg.len = 1;
 		if (1 != i2c_transfer(&dev->i2c_adap, &msg, 1)) {
-			pr_warn("%s: send wake up byte to pic16C505"
-					"(IR chip) failed\n", dev->name);
+			pr_warn("%s: send wake up byte to pic16C505(IR chip) failed\n",
+				dev->name);
 		} else {
 			msg.flags = I2C_M_RD;
 			rc = i2c_transfer(&dev->i2c_adap, &msg, 1);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-core.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-core.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,8 +66,7 @@ MODULE_PARM_DESC(latency,"pci latency ti
 
 int saa7134_no_overlay=-1;
 module_param_named(no_overlay, saa7134_no_overlay, int, 0444);
-MODULE_PARM_DESC(no_overlay,"allow override overlay default (0 disables, 1 enables)"
-		" [some VIA/SIS chipsets are known to have problem with overlay]");
+MODULE_PARM_DESC(no_overlay, "allow override overlay default (0 disables, 1 enables) [some VIA/SIS chipsets are known to have problem with overlay]");
 
 bool saa7134_userptr;
 module_param(saa7134_userptr, bool, 0644);
@@ -619,25 +618,25 @@ static irqreturn_t saa7134_irq(int irq,
 		print_irqstatus(dev,loop,report,status);
 		if (report & SAA7134_IRQ_REPORT_PE) {
 			/* disable all parity error */
-			pr_warn("%s/irq: looping -- "
-			       "clearing PE (parity error!) enable bit\n",dev->name);
+			pr_warn("%s/irq: looping -- clearing PE (parity error!) enable bit\n",
+				dev->name);
 			saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
 		} else if (report & SAA7134_IRQ_REPORT_GPIO16) {
 			/* disable gpio16 IRQ */
-			pr_warn("%s/irq: looping -- "
-			       "clearing GPIO16 enable bit\n",dev->name);
+			pr_warn("%s/irq: looping -- clearing GPIO16 enable bit\n",
+				dev->name);
 			saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_P);
 			saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO16_N);
 		} else if (report & SAA7134_IRQ_REPORT_GPIO18) {
 			/* disable gpio18 IRQs */
-			pr_warn("%s/irq: looping -- "
-			       "clearing GPIO18 enable bit\n",dev->name);
+			pr_warn("%s/irq: looping -- clearing GPIO18 enable bit\n",
+				dev->name);
 			saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_P);
 			saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18_N);
 		} else {
 			/* disable all irqs */
-			pr_warn("%s/irq: looping -- "
-			       "clearing all enable bits\n",dev->name);
+			pr_warn("%s/irq: looping -- clearing all enable bits\n",
+				dev->name);
 			saa_writel(SAA7134_IRQ1,0);
 			saa_writel(SAA7134_IRQ2,0);
 		}
@@ -1081,18 +1080,14 @@ static int saa7134_initdev(struct pci_de
 		}
 #endif
 		if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL)) {
-			pr_info("%s: quirk: this driver and your "
-					"chipset may not work together"
-					" in overlay mode.\n",dev->name);
+			pr_info("%s: quirk: this driver and your chipset may not work together in overlay mode.\n",
+				dev->name);
 			if (!saa7134_no_overlay) {
-				pr_info("%s: quirk: overlay "
-						"mode will be disabled.\n",
+				pr_info("%s: quirk: overlay mode will be disabled.\n",
 						dev->name);
 				saa7134_no_overlay = 1;
 			} else {
-				pr_info("%s: quirk: overlay "
-						"mode will be forced. Use this"
-						" option at your own risk.\n",
+				pr_info("%s: quirk: overlay mode will be forced. Use this option at your own risk.\n",
 						dev->name);
 			}
 		}
@@ -1106,10 +1101,10 @@ static int saa7134_initdev(struct pci_de
 	/* print pci info */
 	dev->pci_rev = pci_dev->revision;
 	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-	pr_info("%s: 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)pci_resource_start(pci_dev,0));
+	pr_info("%s: 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)pci_resource_start(pci_dev, 0));
 	pci_set_master(pci_dev);
 	err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
 	if (err) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-dvb.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-dvb.c	2016-12-11 17:48:07.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-dvb.c	2017-02-12 17:35:39.000000000 -0500
@@ -1449,8 +1449,8 @@ static int dvb_init(struct saa7134_dev *
 
 				if (dvb_attach(tda826x_attach, fe0->dvb.frontend,
 						0x60, &dev->i2c_adap, 0) == NULL) {
-					pr_warn("%s: Medion Quadro, no tda826x "
-						"found !\n", __func__);
+					pr_warn("%s: Medion Quadro, no tda826x found !\n",
+						__func__);
 					goto detach_frontend;
 				}
 				if (dev_id != 0x08) {
@@ -1458,8 +1458,8 @@ static int dvb_init(struct saa7134_dev *
 					fe->ops.i2c_gate_ctrl(fe, 1);
 					if (dvb_attach(isl6405_attach, fe,
 							&dev->i2c_adap, 0x08, 0, 0) == NULL) {
-						pr_warn("%s: Medion Quadro, no ISL6405 "
-							"found !\n", __func__);
+						pr_warn("%s: Medion Quadro, no ISL6405 found !\n",
+							__func__);
 						goto detach_frontend;
 					}
 					if (dev_id == 0x07) {
@@ -1629,8 +1629,8 @@ static int dvb_init(struct saa7134_dev *
 			struct dvb_frontend *fe;
 			if (dvb_attach(dvb_pll_attach, fe0->dvb.frontend, 0x60,
 				  &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) {
-				pr_warn("%s: MD7134 DVB-S, no SD1878 "
-					"found !\n", __func__);
+				pr_warn("%s: MD7134 DVB-S, no SD1878 found !\n",
+					__func__);
 				goto detach_frontend;
 			}
 			/* we need to open the i2c gate (we know it exists) */
@@ -1638,8 +1638,8 @@ static int dvb_init(struct saa7134_dev *
 			fe->ops.i2c_gate_ctrl(fe, 1);
 			if (dvb_attach(isl6405_attach, fe,
 					&dev->i2c_adap, 0x08, 0, 0) == NULL) {
-				pr_warn("%s: MD7134 DVB-S, no ISL6405 "
-					"found !\n", __func__);
+				pr_warn("%s: MD7134 DVB-S, no ISL6405 found !\n",
+					__func__);
 				goto detach_frontend;
 			}
 			fe->ops.i2c_gate_ctrl(fe, 0);
@@ -1670,14 +1670,14 @@ static int dvb_init(struct saa7134_dev *
 				if (dvb_attach(tda826x_attach,
 						fe0->dvb.frontend, 0x60,
 						&dev->i2c_adap, 0) == NULL) {
-					pr_warn("%s: Asus Tiger 3in1, no "
-						"tda826x found!\n", __func__);
+					pr_warn("%s: Asus Tiger 3in1, no tda826x found!\n",
+						__func__);
 					goto detach_frontend;
 				}
 				if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
 						&dev->i2c_adap, 0, 0) == NULL) {
-					pr_warn("%s: Asus Tiger 3in1, no lnbp21"
-						" found!\n", __func__);
+					pr_warn("%s: Asus Tiger 3in1, no lnbp21 found!\n",
+						__func__);
 					goto detach_frontend;
 			       }
 		       }
@@ -1695,14 +1695,14 @@ static int dvb_init(struct saa7134_dev *
 				if (dvb_attach(tda826x_attach,
 					       fe0->dvb.frontend, 0x60,
 					       &dev->i2c_adap, 0) == NULL) {
-					pr_warn("%s: Asus My Cinema PS3-100, no "
-						"tda826x found!\n", __func__);
+					pr_warn("%s: Asus My Cinema PS3-100, no tda826x found!\n",
+						__func__);
 					goto detach_frontend;
 				}
 				if (dvb_attach(lnbp21_attach, fe0->dvb.frontend,
 					       &dev->i2c_adap, 0, 0) == NULL) {
-					pr_warn("%s: Asus My Cinema PS3-100, no lnbp21"
-						" found!\n", __func__);
+					pr_warn("%s: Asus My Cinema PS3-100, no lnbp21 found!\n",
+						__func__);
 					goto detach_frontend;
 				}
 			}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-i2c.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -355,12 +355,43 @@ static struct i2c_client saa7134_client_
 
 /* ----------------------------------------------------------- */
 
+/* On Medion 7134 reading EEPROM needs DVB-T demod i2c gate open */
+static void saa7134_i2c_eeprom_md7134_gate(struct saa7134_dev *dev)
+{
+	u8 subaddr = 0x7, dmdregval;
+	u8 data[2];
+	int ret;
+	struct i2c_msg i2cgatemsg_r[] = { {.addr = 0x08, .flags = 0,
+					   .buf = &subaddr, .len = 1},
+					  {.addr = 0x08,
+					   .flags = I2C_M_RD,
+					   .buf = &dmdregval, .len = 1}
+					};
+	struct i2c_msg i2cgatemsg_w[] = { {.addr = 0x08, .flags = 0,
+					   .buf = data, .len = 2} };
+
+	ret = i2c_transfer(&dev->i2c_adap, i2cgatemsg_r, 2);
+	if ((ret == 2) && (dmdregval & 0x2)) {
+		pr_debug("%s: DVB-T demod i2c gate was left closed\n",
+			 dev->name);
+
+		data[0] = subaddr;
+		data[1] = (dmdregval & ~0x2);
+		if (i2c_transfer(&dev->i2c_adap, i2cgatemsg_w, 1) != 1)
+			pr_err("%s: EEPROM i2c gate open failure\n",
+			  dev->name);
+	}
+}
+
 static int
 saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
 {
 	unsigned char buf;
 	int i,err;
 
+	if (dev->board == SAA7134_BOARD_MD7134)
+		saa7134_i2c_eeprom_md7134_gate(dev);
+
 	dev->i2c_client.addr = 0xa0 >> 1;
 	buf = 0;
 	if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-input.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-input.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7134/saa7134-input.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7134/saa7134-input.c	2017-02-12 16:03:20.000000000 -0500
@@ -123,8 +123,7 @@ static int get_key_flydvb_trio(struct IR
 	struct saa7134_dev *dev = ir->c->adapter->algo_data;
 
 	if (dev == NULL) {
-		ir_dbg(ir, "get_key_flydvb_trio: "
-			   "ir->c->adapter->algo_data is NULL!\n");
+		ir_dbg(ir, "get_key_flydvb_trio: ir->c->adapter->algo_data is NULL!\n");
 		return -EIO;
 	}
 
@@ -150,8 +149,8 @@ static int get_key_flydvb_trio(struct IR
 			msleep(10);
 			continue;
 		}
-		ir_dbg(ir, "send wake up byte to pic16C505 (IR chip)"
-			   "failed %dx\n", attempt);
+		ir_dbg(ir, "send wake up byte to pic16C505 (IR chip)failed %dx\n",
+		       attempt);
 		return -EIO;
 	}
 	if (1 != i2c_master_recv(ir->c, &b, 1)) {
@@ -174,8 +173,7 @@ static int get_key_msi_tvanywhere_plus(s
 	/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
 	struct saa7134_dev *dev = ir->c->adapter->algo_data;
 	if (dev == NULL) {
-		ir_dbg(ir, "get_key_msi_tvanywhere_plus: "
-			   "ir->c->adapter->algo_data is NULL!\n");
+		ir_dbg(ir, "get_key_msi_tvanywhere_plus: ir->c->adapter->algo_data is NULL!\n");
 		return -EIO;
 	}
 
@@ -223,8 +221,7 @@ static int get_key_kworld_pc150u(struct
 	/* <dev> is needed to access GPIO. Used by the saa_readl macro. */
 	struct saa7134_dev *dev = ir->c->adapter->algo_data;
 	if (dev == NULL) {
-		ir_dbg(ir, "get_key_kworld_pc150u: "
-			   "ir->c->adapter->algo_data is NULL!\n");
+		ir_dbg(ir, "get_key_kworld_pc150u: ir->c->adapter->algo_data is NULL!\n");
 		return -EIO;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-buffer.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-buffer.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-buffer.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-buffer.c	2017-02-12 16:03:20.000000000 -0500
@@ -218,8 +218,7 @@ int saa7164_buffer_activate(struct saa71
 	saa7164_writel(port->bufptr32h + ((sizeof(u32) * 2) * i), buf->pt_dma);
 	saa7164_writel(port->bufptr32l + ((sizeof(u32) * 2) * i), 0);
 
-	dprintk(DBGLVL_BUF, "   buf[%d] offset 0x%llx (0x%x) "
-		"buf 0x%llx/%llx (0x%x/%x) nr=%d\n",
+	dprintk(DBGLVL_BUF, "	buf[%d] offset 0x%llx (0x%x) buf 0x%llx/%llx (0x%x/%x) nr=%d\n",
 		buf->idx,
 		(u64)port->bufoffset + (i * sizeof(u32)),
 		saa7164_readl(port->bufoffset + (sizeof(u32) * i)),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-bus.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-bus.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -427,8 +427,8 @@ int saa7164_bus_get(struct saa7164_dev *
 		write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp;
 
 	if (bytes_to_read > write_distance) {
-		printk(KERN_ERR "%s() Invalid bus state, missing msg "
-			"or mangled ring, faulty H/W / bad code?\n", __func__);
+		printk(KERN_ERR "%s() Invalid bus state, missing msg or mangled ring, faulty H/W / bad code?\n",
+		       __func__);
 		ret = SAA_ERR_INVALID_COMMAND;
 		goto out;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-cards.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-cards.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-cards.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-cards.c	2017-02-12 16:03:20.000000000 -0500
@@ -726,8 +726,8 @@ void saa7164_card_list(struct saa7164_de
 			dev->name, dev->name, dev->name, dev->name);
 	}
 
-	printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod "
-		"option:\n", dev->name);
+	printk(KERN_ERR "%s: Here are valid choices for the card=<n> insmod option:\n",
+	       dev->name);
 
 	for (i = 0; i < saa7164_bcount; i++)
 		printk(KERN_ERR "%s:    card=%d -> %s\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-cmd.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-cmd.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -301,8 +301,8 @@ static int saa7164_cmd_wait(struct saa71
 			else
 				saa7164_cmd_timeout_seqno(dev, seqno);
 
-			dprintk(DBGLVL_CMD, "%s(seqno=%d) Waiting res = %d "
-				"(signalled=%d)\n", __func__, seqno, r,
+			dprintk(DBGLVL_CMD, "%s(seqno=%d) Waiting res = %d (signalled=%d)\n",
+				__func__, seqno, r,
 				dev->cmds[seqno].signalled);
 		} else
 			ret = SAA_OK;
@@ -353,8 +353,8 @@ int saa7164_cmd_send(struct saa7164_dev
 	int ret;
 	int safety = 0;
 
-	dprintk(DBGLVL_CMD, "%s(unitid = %s (%d) , command = 0x%x, "
-		"sel = 0x%x)\n", __func__, saa7164_unitid_name(dev, id), id,
+	dprintk(DBGLVL_CMD, "%s(unitid = %s (%d) , command = 0x%x, sel = 0x%x)\n",
+		__func__, saa7164_unitid_name(dev, id), id,
 		command, controlselector);
 
 	if ((size == 0) || (buf == NULL)) {
@@ -452,9 +452,7 @@ int saa7164_cmd_send(struct saa7164_dev
 		if (presponse_t->seqno != pcommand_t->seqno) {
 
 			dprintk(DBGLVL_CMD,
-				"wrong event: seqno = %d, "
-				"expected seqno = %d, "
-				"will dequeue regardless\n",
+				"wrong event: seqno = %d, expected seqno = %d, will dequeue regardless\n",
 				presponse_t->seqno, pcommand_t->seqno);
 
 			ret = saa7164_cmd_dequeue(dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-core.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-core.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -710,9 +710,7 @@ static irqreturn_t saa7164_irq(int irq,
 				} else {
 					/* Find the function */
 					dprintk(DBGLVL_IRQ,
-						"%s() unhandled interrupt "
-						"reg 0x%x bit 0x%x "
-						"intid = 0x%x\n",
+						"%s() unhandled interrupt reg 0x%x bit 0x%x intid = 0x%x\n",
 						__func__, i, bit, intid);
 				}
 			}
@@ -767,13 +765,11 @@ void saa7164_dumpregs(struct saa7164_dev
 {
 	int i;
 
-	dprintk(1, "--------------------> "
-		"00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
+	dprintk(1, "--------------------> 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
 
 	for (i = 0; i < 0x100; i += 16)
-		dprintk(1, "region0[0x%08x] = "
-			"%02x %02x %02x %02x %02x %02x %02x %02x"
-			" %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
+		dprintk(1, "region0[0x%08x] = %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			i,
 			(u8)saa7164_readb(addr + i + 0),
 			(u8)saa7164_readb(addr + i + 1),
 			(u8)saa7164_readb(addr + i + 2),
@@ -825,8 +821,7 @@ static void saa7164_dump_hwdesc(struct s
 
 static void saa7164_dump_intfdesc(struct saa7164_dev *dev)
 {
-	dprintk(1, "@0x%p intfdesc "
-		"sizeof(struct tmComResInterfaceDescr) = %d bytes\n",
+	dprintk(1, "@0x%p intfdesc sizeof(struct tmComResInterfaceDescr) = %d bytes\n",
 		&dev->intfdesc, (u32)sizeof(struct tmComResInterfaceDescr));
 
 	dprintk(1, " .bLength = 0x%x\n", dev->intfdesc.bLength);
@@ -1011,8 +1006,7 @@ static int saa7164_dev_setup(struct saa7
 	saa7164_port_init(dev, SAA7164_PORT_VBI2);
 
 	if (get_resources(dev) < 0) {
-		printk(KERN_ERR "CORE %s No more PCIe resources for "
-		       "subsystem: %04x:%04x\n",
+		printk(KERN_ERR "CORE %s No more PCIe resources for subsystem: %04x:%04x\n",
 		       dev->name, dev->pci->subsystem_vendor,
 		       dev->pci->subsystem_device);
 
@@ -1204,8 +1198,8 @@ static bool saa7164_enable_msi(struct pc
 	err = pci_enable_msi(pci_dev);
 
 	if (err) {
-		printk(KERN_ERR "%s() Failed to enable MSI interrupt."
-			" Falling back to a shared IRQ\n", __func__);
+		printk(KERN_ERR "%s() Failed to enable MSI interrupt. Falling back to a shared IRQ\n",
+		       __func__);
 		return false;
 	}
 
@@ -1215,8 +1209,8 @@ static bool saa7164_enable_msi(struct pc
 
 	if (err) {
 		/* fall back to legacy interrupt */
-		printk(KERN_ERR "%s() Failed to get an MSI interrupt."
-		       " Falling back to a shared IRQ\n", __func__);
+		printk(KERN_ERR "%s() Failed to get an MSI interrupt. Falling back to a shared IRQ\n",
+		       __func__);
 		pci_disable_msi(pci_dev);
 		return false;
 	}
@@ -1256,8 +1250,8 @@ static int saa7164_initdev(struct pci_de
 	/* print pci info */
 	dev->pci_rev = pci_dev->revision;
 	pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER,  &dev->pci_lat);
-	printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, "
-	       "latency: %d, mmio: 0x%llx\n", dev->name,
+	printk(KERN_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)pci_resource_start(pci_dev, 0));
@@ -1307,8 +1301,7 @@ static int saa7164_initdev(struct pci_de
 		err = saa7164_downloadfirmware(dev);
 		if (err < 0) {
 			printk(KERN_ERR
-				"Failed to boot firmware, no features "
-				"registered\n");
+				"Failed to boot firmware, no features registered\n");
 			goto fail_fw;
 		}
 
@@ -1327,8 +1320,7 @@ static int saa7164_initdev(struct pci_de
 		 */
 		version = 0;
 		if (saa7164_api_get_fw_version(dev, &version) == SAA_OK)
-			dprintk(1, "Bus is operating correctly using "
-				"version %d.%d.%d.%d (0x%x)\n",
+			dprintk(1, "Bus is operating correctly using version %d.%d.%d.%d (0x%x)\n",
 				(version & 0x0000fc00) >> 10,
 				(version & 0x000003e0) >> 5,
 				(version & 0x0000001f),
@@ -1356,45 +1348,43 @@ static int saa7164_initdev(struct pci_de
 		/* Begin to create the video sub-systems and register funcs */
 		if (saa7164_boards[dev->board].porta == SAA7164_MPEG_DVB) {
 			if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS1]) < 0) {
-				printk(KERN_ERR "%s() Failed to register "
-					"dvb adapters on porta\n",
+				printk(KERN_ERR "%s() Failed to register dvb adapters on porta\n",
 					__func__);
 			}
 		}
 
 		if (saa7164_boards[dev->board].portb == SAA7164_MPEG_DVB) {
 			if (saa7164_dvb_register(&dev->ports[SAA7164_PORT_TS2]) < 0) {
-				printk(KERN_ERR"%s() Failed to register "
-					"dvb adapters on portb\n",
+				printk(KERN_ERR"%s() Failed to register dvb adapters on portb\n",
 					__func__);
 			}
 		}
 
 		if (saa7164_boards[dev->board].portc == SAA7164_MPEG_ENCODER) {
 			if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC1]) < 0) {
-				printk(KERN_ERR"%s() Failed to register "
-					"mpeg encoder\n", __func__);
+				printk(KERN_ERR"%s() Failed to register mpeg encoder\n",
+				       __func__);
 			}
 		}
 
 		if (saa7164_boards[dev->board].portd == SAA7164_MPEG_ENCODER) {
 			if (saa7164_encoder_register(&dev->ports[SAA7164_PORT_ENC2]) < 0) {
-				printk(KERN_ERR"%s() Failed to register "
-					"mpeg encoder\n", __func__);
+				printk(KERN_ERR"%s() Failed to register mpeg encoder\n",
+				       __func__);
 			}
 		}
 
 		if (saa7164_boards[dev->board].porte == SAA7164_MPEG_VBI) {
 			if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI1]) < 0) {
-				printk(KERN_ERR"%s() Failed to register "
-					"vbi device\n", __func__);
+				printk(KERN_ERR"%s() Failed to register vbi device\n",
+				       __func__);
 			}
 		}
 
 		if (saa7164_boards[dev->board].portf == SAA7164_MPEG_VBI) {
 			if (saa7164_vbi_register(&dev->ports[SAA7164_PORT_VBI2]) < 0) {
-				printk(KERN_ERR"%s() Failed to register "
-					"vbi device\n", __func__);
+				printk(KERN_ERR"%s() Failed to register vbi device\n",
+				       __func__);
 			}
 		}
 		saa7164_api_set_debug(dev, fw_debug);
@@ -1404,15 +1394,15 @@ static int saa7164_initdev(struct pci_de
 				"saa7164 debug");
 			if (IS_ERR(dev->kthread)) {
 				dev->kthread = NULL;
-				printk(KERN_ERR "%s() Failed to create "
-					"debug kernel thread\n", __func__);
+				printk(KERN_ERR "%s() Failed to create debug kernel thread\n",
+				       __func__);
 			}
 		}
 
 	} /* != BOARD_UNKNOWN */
 	else
-		printk(KERN_ERR "%s() Unsupported board detected, "
-			"registering without firmware\n", __func__);
+		printk(KERN_ERR "%s() Unsupported board detected, registering without firmware\n",
+		       __func__);
 
 	dprintk(1, "%s() parameter debug = %d\n", __func__, saa_debug);
 	dprintk(1, "%s() parameter waitsecs = %d\n", __func__, waitsecs);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-dvb.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-dvb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-dvb.c	2017-02-12 16:03:20.000000000 -0500
@@ -244,8 +244,8 @@ static int saa7164_dvb_start_port(struct
 		/* Stop the hardware, regardless */
 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-			printk(KERN_ERR "%s() acquire/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() acquire/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 		ret = -EIO;
 		goto out;
@@ -261,8 +261,8 @@ static int saa7164_dvb_start_port(struct
 		/* Stop the hardware, regardless */
 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-			printk(KERN_ERR "%s() pause/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 
 		ret = -EIO;
@@ -279,8 +279,8 @@ static int saa7164_dvb_start_port(struct
 		/* Stop the hardware, regardless */
 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-			printk(KERN_ERR "%s() run/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 
 		ret = -EIO;
@@ -357,8 +357,7 @@ static int dvb_register(struct saa7164_p
 	/* Sanity check that the PCI configuration space is active */
 	if (port->hwcfg.BARLocation == 0) {
 		result = -ENOMEM;
-		printk(KERN_ERR "%s: dvb_register_adapter failed "
-		       "(errno = %d), NO PCI configuration\n",
+		printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d), NO PCI configuration\n",
 			DRIVER_NAME, result);
 		goto fail_adapter;
 	}
@@ -386,8 +385,7 @@ static int dvb_register(struct saa7164_p
 
 		if (!buf) {
 			result = -ENOMEM;
-			printk(KERN_ERR "%s: dvb_register_adapter failed "
-			       "(errno = %d), unable to allocate buffers\n",
+			printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d), unable to allocate buffers\n",
 				DRIVER_NAME, result);
 			goto fail_adapter;
 		}
@@ -401,8 +399,8 @@ static int dvb_register(struct saa7164_p
 	result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
 			&dev->pci->dev, adapter_nr);
 	if (result < 0) {
-		printk(KERN_ERR "%s: dvb_register_adapter failed "
-		       "(errno = %d)\n", DRIVER_NAME, result);
+		printk(KERN_ERR "%s: dvb_register_adapter failed (errno = %d)\n",
+		       DRIVER_NAME, result);
 		goto fail_adapter;
 	}
 	dvb->adapter.priv = port;
@@ -410,8 +408,8 @@ static int dvb_register(struct saa7164_p
 	/* register frontend */
 	result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
 	if (result < 0) {
-		printk(KERN_ERR "%s: dvb_register_frontend failed "
-		       "(errno = %d)\n", DRIVER_NAME, result);
+		printk(KERN_ERR "%s: dvb_register_frontend failed (errno = %d)\n",
+		       DRIVER_NAME, result);
 		goto fail_frontend;
 	}
 
@@ -444,16 +442,16 @@ static int dvb_register(struct saa7164_p
 	dvb->fe_hw.source = DMX_FRONTEND_0;
 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 	if (result < 0) {
-		printk(KERN_ERR "%s: add_frontend failed "
-		       "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
+		printk(KERN_ERR "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+		       DRIVER_NAME, result);
 		goto fail_fe_hw;
 	}
 
 	dvb->fe_mem.source = DMX_MEMORY_FE;
 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 	if (result < 0) {
-		printk(KERN_ERR "%s: add_frontend failed "
-		       "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
+		printk(KERN_ERR "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+		       DRIVER_NAME, result);
 		goto fail_fe_mem;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-encoder.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-encoder.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-encoder.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-encoder.c	2017-02-12 16:03:20.000000000 -0500
@@ -157,8 +157,7 @@ static int saa7164_encoder_buffers_alloc
 			params->pitch);
 
 		if (!buf) {
-			printk(KERN_ERR "%s() failed "
-			       "(errno = %d), unable to allocate buffer\n",
+			printk(KERN_ERR "%s() failed (errno = %d), unable to allocate buffer\n",
 				__func__, result);
 			result = -ENOMEM;
 			goto failed;
@@ -681,8 +680,8 @@ static int saa7164_encoder_start_streami
 		/* Stop the hardware, regardless */
 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-			printk(KERN_ERR "%s() acquire/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() acquire/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 		ret = -EIO;
 		goto out;
@@ -698,8 +697,8 @@ static int saa7164_encoder_start_streami
 		/* Stop the hardware, regardless */
 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-			printk(KERN_ERR "%s() pause/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 
 		ret = -EIO;
@@ -716,8 +715,8 @@ static int saa7164_encoder_start_streami
 		/* Stop the hardware, regardless */
 		result = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 		if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
-			printk(KERN_ERR "%s() run/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 
 		ret = -EIO;
@@ -1026,8 +1025,7 @@ int saa7164_encoder_register(struct saa7
 
 	/* Sanity check that the PCI configuration space is active */
 	if (port->hwcfg.BARLocation == 0) {
-		printk(KERN_ERR "%s() failed "
-		       "(errno = %d), NO PCI configuration\n",
+		printk(KERN_ERR "%s() failed (errno = %d), NO PCI configuration\n",
 			__func__, result);
 		result = -ENOMEM;
 		goto failed;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-fw.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-fw.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-fw.c	2016-12-11 17:48:12.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-fw.c	2017-02-12 17:35:48.000000000 -0500
@@ -421,8 +421,8 @@ int saa7164_downloadfirmware(struct saa7
 
 		ret = reject_firmware(&fw, fwname, &dev->pci->dev);
 		if (ret) {
-			printk(KERN_ERR "%s() Upload failed. "
-				"(file not found?)\n", __func__);
+			printk(KERN_ERR "%s() Upload failed. (file not found?)\n",
+			       __func__);
 			return -ENOMEM;
 		}
 
@@ -478,15 +478,13 @@ int saa7164_downloadfirmware(struct saa7
 				0x03) && (saa7164_readl(SAA_DATAREADY_FLAG_ACK)
 				== 0x00) && (version == 0x00)) {
 
-				dprintk(DBGLVL_FW, "BootLoader version in  "
-					"rom %d.%d.%d.%d\n",
+				dprintk(DBGLVL_FW, "BootLoader version in  rom %d.%d.%d.%d\n",
 					(bootloaderversion & 0x0000fc00) >> 10,
 					(bootloaderversion & 0x000003e0) >> 5,
 					(bootloaderversion & 0x0000001f),
 					(bootloaderversion & 0xffff0000) >> 16
 					);
-				dprintk(DBGLVL_FW, "BootLoader version "
-					"in file %d.%d.%d.%d\n",
+				dprintk(DBGLVL_FW, "BootLoader version in file %d.%d.%d.%d\n",
 					(boothdr->version & 0x0000fc00) >> 10,
 					(boothdr->version & 0x000003e0) >> 5,
 					(boothdr->version & 0x0000001f),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-vbi.c linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-vbi.c
--- linux-libre-4.9-gnu/drivers/media/pci/saa7164/saa7164-vbi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/saa7164/saa7164-vbi.c	2017-02-12 16:03:20.000000000 -0500
@@ -110,8 +110,7 @@ static int saa7164_vbi_buffers_alloc(str
 			params->pitch);
 
 		if (!buf) {
-			printk(KERN_ERR "%s() failed "
-			       "(errno = %d), unable to allocate buffer\n",
+			printk(KERN_ERR "%s() failed (errno = %d), unable to allocate buffer\n",
 				__func__, result);
 			result = -ENOMEM;
 			goto failed;
@@ -384,8 +383,8 @@ static int saa7164_vbi_start_streaming(s
 		/* Stop the hardware, regardless */
 		result = saa7164_vbi_stop_port(port);
 		if (result != SAA_OK) {
-			printk(KERN_ERR "%s() pause/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 
 		ret = -EIO;
@@ -403,8 +402,8 @@ static int saa7164_vbi_start_streaming(s
 		result = saa7164_vbi_acquire_port(port);
 		result = saa7164_vbi_stop_port(port);
 		if (result != SAA_OK) {
-			printk(KERN_ERR "%s() run/forced stop transition "
-				"failed, res = 0x%x\n", __func__, result);
+			printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n",
+			       __func__, result);
 		}
 
 		ret = -EIO;
@@ -728,8 +727,7 @@ int saa7164_vbi_register(struct saa7164_
 
 	/* Sanity check that the PCI configuration space is active */
 	if (port->hwcfg.BARLocation == 0) {
-		printk(KERN_ERR "%s() failed "
-		       "(errno = %d), NO PCI configuration\n",
+		printk(KERN_ERR "%s() failed (errno = %d), NO PCI configuration\n",
 			__func__, result);
 		result = -ENOMEM;
 		goto failed;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/solo6x10/solo6x10.h linux-libre-4.10-rc8-gnu/drivers/media/pci/solo6x10/solo6x10.h
--- linux-libre-4.9-gnu/drivers/media/pci/solo6x10/solo6x10.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/solo6x10/solo6x10.h	2017-02-12 16:03:20.000000000 -0500
@@ -284,7 +284,10 @@ static inline u32 solo_reg_read(struct s
 static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
 				  u32 data)
 {
+	u16 val;
+
 	writel(data, solo_dev->reg_base + reg);
+	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
 }
 
 static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c linux-libre-4.10-rc8-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c
--- linux-libre-4.9-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/solo6x10/solo6x10-v4l2.c	2017-02-12 16:03:20.000000000 -0500
@@ -702,8 +702,8 @@ int solo_v4l2_init(struct solo_dev *solo
 	snprintf(solo_dev->vfd->name, sizeof(solo_dev->vfd->name), "%s (%i)",
 		 SOLO6X10_NAME, solo_dev->vfd->num);
 
-	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with "
-		 "%d inputs (%d extended)\n", solo_dev->vfd->num,
+	dev_info(&solo_dev->pdev->dev, "Display as /dev/video%d with %d inputs (%d extended)\n",
+		 solo_dev->vfd->num,
 		 solo_dev->nr_chans, solo_dev->nr_ext);
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/av7110.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/av7110.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/av7110.c	2016-12-11 17:46:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/av7110.c	2017-02-12 17:32:38.000000000 -0500
@@ -100,8 +100,7 @@ MODULE_PARM_DESC(adac,"audio DAC type: 0
 module_param(hw_sections, int, 0444);
 MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");
 module_param(rgb_on, int, 0444);
-MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"
-		" signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
+MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");
 module_param(volume, int, 0444);
 MODULE_PARM_DESC(volume, "initial volume: default 255 (range 0-255)");
 module_param(budgetpatch, int, 0444);
@@ -444,21 +443,6 @@ static void debiirq(unsigned long cookie
 
 	case DATA_COMMON_INTERFACE:
 		CI_handle(av7110, (u8 *)av7110->debi_virt, av7110->debilen);
-#if 0
-	{
-		int i;
-
-		printk("av7110%d: ", av7110->num);
-		printk("%02x ", *(u8 *)av7110->debi_virt);
-		printk("%02x ", *(1+(u8 *)av7110->debi_virt));
-		for (i = 2; i < av7110->debilen; i++)
-			printk("%02x ", (*(i+(unsigned char *)av7110->debi_virt)));
-		for (i = 2; i < av7110->debilen; i++)
-			printk("%c", chtrans(*(i+(unsigned char *)av7110->debi_virt)));
-
-		printk("\n");
-	}
-#endif
 		xfer = RX_BUFF;
 		break;
 
@@ -833,8 +817,7 @@ static int StartHWFilter(struct dvb_demu
 
 	ret = av7110_fw_request(av7110, buf, 20, &handle, 1);
 	if (ret != 0 || handle >= 32) {
-		printk("dvb-ttpci: %s error  buf %04x %04x %04x %04x  "
-				"ret %d  handle %04x\n",
+		printk(KERN_ERR "dvb-ttpci: %s error  buf %04x %04x %04x %04x  ret %d  handle %04x\n",
 				__func__, buf[0], buf[1], buf[2], buf[3],
 				ret, handle);
 		dvbdmxfilter->hw_handle = 0xffff;
@@ -876,8 +859,7 @@ static int StopHWFilter(struct dvb_demux
 	buf[2] = handle;
 	ret = av7110_fw_request(av7110, buf, 3, answ, 2);
 	if (ret != 0 || answ[1] != handle) {
-		printk("dvb-ttpci: %s error  cmd %04x %04x %04x  ret %x  "
-				"resp %04x %04x  pid %d\n",
+		printk(KERN_ERR "dvb-ttpci: %s error  cmd %04x %04x %04x  ret %x  resp %04x %04x  pid %d\n",
 				__func__, buf[0], buf[1], buf[2], ret,
 				answ[0], answ[1], dvbdmxfilter->feed->pid);
 		if (!ret)
@@ -1532,15 +1514,12 @@ static int get_firmware(struct av7110* a
 	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/", &av7110->dev->pci->dev);
 	if (ret) {
 		if (ret == -ENOENT) {
-			printk(KERN_ERR "dvb-ttpci: could not load firmware,"
-			       " file not found: /*(DEBLOBBED)*/\n");
-			printk(KERN_ERR "dvb-ttpci: usually this should be in "
-			       "/usr/lib/hotplug/firmware or /lib/firmware\n");
-			printk(KERN_ERR "dvb-ttpci: and can be downloaded from"
-			       " https://linuxtv.org/download/dvb/firmware/\n");
+			printk(KERN_ERR "dvb-ttpci: could not load firmware, file not found: /*(DEBLOBBED)*/\n");
+			printk(KERN_ERR "dvb-ttpci: usually this should be in /usr/lib/hotplug/firmware or /lib/firmware\n");
+			printk(KERN_ERR "dvb-ttpci: and can be downloaded from /*(DEBLOBBED)*/");
 		} else
-			printk(KERN_ERR "dvb-ttpci: cannot request firmware"
-			       " (error %i)\n", ret);
+			printk(KERN_ERR "dvb-ttpci: cannot request firmware (error %i)\n",
+			       ret);
 		return -EINVAL;
 	}
 
@@ -2700,8 +2679,9 @@ static int av7110_attach(struct saa7146_
 		goto err_stop_arm_9;
 
 	if (FW_VERSION(av7110->arm_app)<0x2501)
-		printk ("dvb-ttpci: Warning, firmware version 0x%04x is too old. "
-			"System might be unstable!\n", FW_VERSION(av7110->arm_app));
+		printk(KERN_WARNING
+		       "dvb-ttpci: Warning, firmware version 0x%04x is too old. System might be unstable!\n",
+		       FW_VERSION(av7110->arm_app));
 
 	thread = kthread_run(arm_thread, (void *) av7110, "arm_mon");
 	if (IS_ERR(thread)) {
@@ -2930,9 +2910,7 @@ static struct saa7146_extension av7110_e
 
 static int __init av7110_init(void)
 {
-	int retval;
-	retval = saa7146_register_extension(&av7110_extension_driver);
-	return retval;
+	return saa7146_register_extension(&av7110_extension_driver);
 }
 
 
@@ -2944,7 +2922,6 @@ static void __exit av7110_exit(void)
 module_init(av7110_init);
 module_exit(av7110_exit);
 
-MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "
-		   "Siemens, Technotrend, Hauppauge");
+MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by Siemens, Technotrend, Hauppauge");
 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/av7110.h linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/av7110.h
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/av7110.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/av7110.h	2017-02-12 16:03:20.000000000 -0500
@@ -40,8 +40,11 @@
 
 extern int av7110_debug;
 
-#define dprintk(level,args...) \
-	    do { if ((av7110_debug & level)) { printk("dvb-ttpci: %s(): ", __func__); printk(args); } } while (0)
+#define dprintk(level, fmt, arg...) do {				\
+	if (level & av7110_debug)					\
+		printk(KERN_DEBUG KBUILD_MODNAME ": %s(): " fmt,	\
+		       __func__, ##arg);				\
+} while (0)
 
 #define MAXFILT 32
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/av7110_hw.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/av7110_hw.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/av7110_hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/av7110_hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -235,8 +235,7 @@ int av7110_bootarm(struct av7110 *av7110
 	iwdebi(av7110, DEBISWAP, DPRAM_BASE, 0x76543210, 4);
 
 	if ((ret=irdebi(av7110, DEBINOSWAP, DPRAM_BASE, 0, 4)) != 0x10325476) {
-		printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: "
-		       "%08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
+		printk(KERN_ERR "dvb-ttpci: debi test in av7110_bootarm() failed: %08x != %08x (check your BIOS 'Plug&Play OS' settings)\n",
 		       ret, 0x10325476);
 		return -1;
 	}
@@ -262,8 +261,7 @@ int av7110_bootarm(struct av7110 *av7110
 	iwdebi(av7110, DEBINOSWAP, AV7110_BOOT_STATE, BOOTSTATE_BUFFER_FULL, 2);
 
 	if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
-		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
-		       "saa7146_wait_for_debi_done() timed out\n");
+		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out\n");
 		return -ETIMEDOUT;
 	}
 	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
@@ -271,8 +269,7 @@ int av7110_bootarm(struct av7110 *av7110
 
 	dprintk(1, "load dram code\n");
 	if (load_dram(av7110, (u32 *)av7110->bin_root, av7110->size_root) < 0) {
-		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
-		       "load_dram() failed\n");
+		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): load_dram() failed\n");
 		return -1;
 	}
 
@@ -283,8 +280,7 @@ int av7110_bootarm(struct av7110 *av7110
 	mwdebi(av7110, DEBISWAB, DPRAM_BASE, av7110->bin_dpram, av7110->size_dpram);
 
 	if (saa7146_wait_for_debi_done(av7110->dev, 1)) {
-		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): "
-		       "saa7146_wait_for_debi_done() timed out after loading DRAM\n");
+		printk(KERN_ERR "dvb-ttpci: av7110_bootarm(): saa7146_wait_for_debi_done() timed out after loading DRAM\n");
 		return -ETIMEDOUT;
 	}
 	saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget-av.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget-av.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget-av.c	2016-12-11 17:46:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget-av.c	2017-02-12 17:32:40.000000000 -0500
@@ -1636,5 +1636,4 @@ module_exit(budget_av_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
-		   "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
+MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget.c	2016-12-11 17:46:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget.c	2017-02-12 17:32:40.000000000 -0500
@@ -897,5 +897,4 @@ module_exit(budget_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
-		   "budget PCI DVB cards by Siemens, Technotrend, Hauppauge");
+MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards by Siemens, Technotrend, Hauppauge");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget-ci.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget-ci.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget-ci.c	2016-12-11 17:46:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget-ci.c	2017-02-12 17:32:41.000000000 -0500
@@ -1586,6 +1586,4 @@ module_exit(budget_ci_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
-MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
-		   "budget PCI DVB cards w/ CI-module produced by "
-		   "Siemens, Technotrend, Hauppauge");
+MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB cards w/ CI-module produced by Siemens, Technotrend, Hauppauge");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget.h linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget.h
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,8 +21,12 @@ extern int budget_debug;
 #undef dprintk
 #endif
 
-#define dprintk(level,args...) \
-	    do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __func__); printk(args); } } while (0)
+#define dprintk(level, fmt, arg...) do {				\
+	if (level & budget_debug)					\
+		printk(KERN_DEBUG KBUILD_MODNAME ": %s(): " fmt,	\
+		       __func__, ##arg);				\
+} while (0)
+
 
 struct budget_info {
 	char *name;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget-patch.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget-patch.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/budget-patch.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/budget-patch.c	2017-02-12 16:03:20.000000000 -0500
@@ -679,5 +679,4 @@ module_exit(budget_patch_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Emard, Roberto Deza, Holger Waechtler, Michael Hunold, others");
-MODULE_DESCRIPTION("Driver for full TS modified DVB-S SAA7146+AV7110 "
-		   "based so-called Budget Patch cards");
+MODULE_DESCRIPTION("Driver for full TS modified DVB-S SAA7146+AV7110 based so-called Budget Patch cards");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/dvb_filter.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/dvb_filter.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/dvb_filter.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/dvb_filter.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,114 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include "dvb_filter.h"
+
+static u32 freq[4] = {480, 441, 320, 0};
+
+static unsigned int ac3_bitrates[32] =
+    {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
+     0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+static u32 ac3_frames[3][32] =
+    {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
+      1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
+      1253,1393,0,0,0,0,0,0,0,0,0,0,0,0,0},
+     {96,120,144,168,192,240,288,336,384,480,576,672,768,960,1152,1344,
+      1536,1728,1920,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+
+int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr)
+{
+	u8 *headr;
+	int found = 0;
+	int c = 0;
+	u8 frame = 0;
+	int fr = 0;
+
+	while ( !found  && c < count){
+		u8 *b = mbuf+c;
+
+		if ( b[0] == 0x0b &&  b[1] == 0x77 )
+			found = 1;
+		else {
+			c++;
+		}
+	}
+
+	if (!found) return -1;
+	if (pr)
+		printk(KERN_DEBUG "Audiostream: AC3");
+
+	ai->off = c;
+	if (c+5 >= count) return -1;
+
+	ai->layer = 0;  // 0 for AC3
+	headr = mbuf+c+2;
+
+	frame = (headr[2]&0x3f);
+	ai->bit_rate = ac3_bitrates[frame >> 1]*1000;
+
+	if (pr)
+		printk(KERN_CONT "  BRate: %d kb/s", (int) ai->bit_rate/1000);
+
+	ai->frequency = (headr[2] & 0xc0 ) >> 6;
+	fr = (headr[2] & 0xc0 ) >> 6;
+	ai->frequency = freq[fr]*100;
+	if (pr)
+		printk(KERN_CONT "  Freq: %d Hz\n", (int) ai->frequency);
+
+	ai->framesize = ac3_frames[fr][frame >> 1];
+	if ((frame & 1) &&  (fr == 1)) ai->framesize++;
+	ai->framesize = ai->framesize << 1;
+	if (pr)
+		printk(KERN_DEBUG "  Framesize %d\n", (int) ai->framesize);
+
+	return 0;
+}
+
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+			    dvb_filter_pes2ts_cb_t *cb, void *priv)
+{
+	unsigned char *buf=p2ts->buf;
+
+	buf[0]=0x47;
+	buf[1]=(pid>>8);
+	buf[2]=pid&0xff;
+	p2ts->cc=0;
+	p2ts->cb=cb;
+	p2ts->priv=priv;
+}
+
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+		      int len, int payload_start)
+{
+	unsigned char *buf=p2ts->buf;
+	int ret=0, rest;
+
+	//len=6+((pes[4]<<8)|pes[5]);
+
+	if (payload_start)
+		buf[1]|=0x40;
+	else
+		buf[1]&=~0x40;
+	while (len>=184) {
+		buf[3]=0x10|((p2ts->cc++)&0x0f);
+		memcpy(buf+4, pes, 184);
+		if ((ret=p2ts->cb(p2ts->priv, buf)))
+			return ret;
+		len-=184; pes+=184;
+		buf[1]&=~0x40;
+	}
+	if (!len)
+		return 0;
+	buf[3]=0x30|((p2ts->cc++)&0x0f);
+	rest=183-len;
+	if (rest) {
+		buf[5]=0x00;
+		if (rest-1)
+			memset(buf+6, 0xff, rest-1);
+	}
+	buf[4]=rest;
+	memcpy(buf+5+rest, pes, len);
+	return p2ts->cb(p2ts->priv, buf);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/dvb_filter.h linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/dvb_filter.h
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/dvb_filter.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/dvb_filter.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,246 @@
+/*
+ * dvb_filter.h
+ *
+ * Copyright (C) 2003 Convergence GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public 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 _DVB_FILTER_H_
+#define _DVB_FILTER_H_
+
+#include <linux/slab.h>
+
+#include "demux.h"
+
+typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
+
+struct dvb_filter_pes2ts {
+	unsigned char buf[188];
+	unsigned char cc;
+	dvb_filter_pes2ts_cb_t *cb;
+	void *priv;
+};
+
+void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid,
+			    dvb_filter_pes2ts_cb_t *cb, void *priv);
+
+int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
+		      int len, int payload_start);
+
+
+#define PROG_STREAM_MAP  0xBC
+#define PRIVATE_STREAM1  0xBD
+#define PADDING_STREAM   0xBE
+#define PRIVATE_STREAM2  0xBF
+#define AUDIO_STREAM_S   0xC0
+#define AUDIO_STREAM_E   0xDF
+#define VIDEO_STREAM_S   0xE0
+#define VIDEO_STREAM_E   0xEF
+#define ECM_STREAM       0xF0
+#define EMM_STREAM       0xF1
+#define DSM_CC_STREAM    0xF2
+#define ISO13522_STREAM  0xF3
+#define PROG_STREAM_DIR  0xFF
+
+#define DVB_PICTURE_START    0x00
+#define DVB_USER_START       0xb2
+#define DVB_SEQUENCE_HEADER  0xb3
+#define DVB_SEQUENCE_ERROR   0xb4
+#define DVB_EXTENSION_START  0xb5
+#define DVB_SEQUENCE_END     0xb7
+#define DVB_GOP_START        0xb8
+#define DVB_EXCEPT_SLICE     0xb0
+
+#define SEQUENCE_EXTENSION           0x01
+#define SEQUENCE_DISPLAY_EXTENSION   0x02
+#define PICTURE_CODING_EXTENSION     0x08
+#define QUANT_MATRIX_EXTENSION       0x03
+#define PICTURE_DISPLAY_EXTENSION    0x07
+
+#define I_FRAME 0x01
+#define B_FRAME 0x02
+#define P_FRAME 0x03
+
+/* Initialize sequence_data */
+#define INIT_HORIZONTAL_SIZE        720
+#define INIT_VERTICAL_SIZE          576
+#define INIT_ASPECT_RATIO          0x02
+#define INIT_FRAME_RATE            0x03
+#define INIT_DISP_HORIZONTAL_SIZE   540
+#define INIT_DISP_VERTICAL_SIZE     576
+
+
+//flags2
+#define PTS_DTS_FLAGS    0xC0
+#define ESCR_FLAG        0x20
+#define ES_RATE_FLAG     0x10
+#define DSM_TRICK_FLAG   0x08
+#define ADD_CPY_FLAG     0x04
+#define PES_CRC_FLAG     0x02
+#define PES_EXT_FLAG     0x01
+
+//pts_dts flags
+#define PTS_ONLY         0x80
+#define PTS_DTS          0xC0
+
+#define TS_SIZE        188
+#define TRANS_ERROR    0x80
+#define PAY_START      0x40
+#define TRANS_PRIO     0x20
+#define PID_MASK_HI    0x1F
+//flags
+#define TRANS_SCRMBL1  0x80
+#define TRANS_SCRMBL2  0x40
+#define ADAPT_FIELD    0x20
+#define PAYLOAD        0x10
+#define COUNT_MASK     0x0F
+
+// adaptation flags
+#define DISCON_IND     0x80
+#define RAND_ACC_IND   0x40
+#define ES_PRI_IND     0x20
+#define PCR_FLAG       0x10
+#define OPCR_FLAG      0x08
+#define SPLICE_FLAG    0x04
+#define TRANS_PRIV     0x02
+#define ADAP_EXT_FLAG  0x01
+
+// adaptation extension flags
+#define LTW_FLAG       0x80
+#define PIECE_RATE     0x40
+#define SEAM_SPLICE    0x20
+
+
+#define MAX_PLENGTH 0xFFFF
+#define MMAX_PLENGTH (256*MAX_PLENGTH)
+
+#ifndef IPACKS
+#define IPACKS 2048
+#endif
+
+struct ipack {
+	int size;
+	int found;
+	u8 *buf;
+	u8 cid;
+	u32 plength;
+	u8 plen[2];
+	u8 flag1;
+	u8 flag2;
+	u8 hlength;
+	u8 pts[5];
+	u16 *pid;
+	int mpeg;
+	u8 check;
+	int which;
+	int done;
+	void *data;
+	void (*func)(u8 *buf,  int size, void *priv);
+	int count;
+	int repack_subids;
+};
+
+struct dvb_video_info {
+	u32 horizontal_size;
+	u32 vertical_size;
+	u32 aspect_ratio;
+	u32 framerate;
+	u32 video_format;
+	u32 bit_rate;
+	u32 comp_bit_rate;
+	u32 vbv_buffer_size;
+	s16 vbv_delay;
+	u32 CSPF;
+	u32 off;
+};
+
+#define OFF_SIZE 4
+#define FIRST_FIELD 0
+#define SECOND_FIELD 1
+#define VIDEO_FRAME_PICTURE 0x03
+
+struct mpg_picture {
+	int       channel;
+	struct dvb_video_info vinfo;
+	u32      *sequence_gop_header;
+	u32      *picture_header;
+	s32       time_code;
+	int       low_delay;
+	int       closed_gop;
+	int       broken_link;
+	int       sequence_header_flag;
+	int       gop_flag;
+	int       sequence_end_flag;
+
+	u8        profile_and_level;
+	s32       picture_coding_parameter;
+	u32       matrix[32];
+	s8        matrix_change_flag;
+
+	u8        picture_header_parameter;
+  /* bit 0 - 2: bwd f code
+     bit 3    : fpb vector
+     bit 4 - 6: fwd f code
+     bit 7    : fpf vector */
+
+	int       mpeg1_flag;
+	int       progressive_sequence;
+	int       sequence_display_extension_flag;
+	u32       sequence_header_data;
+	s16       last_frame_centre_horizontal_offset;
+	s16       last_frame_centre_vertical_offset;
+
+	u32       pts[2]; /* [0] 1st field, [1] 2nd field */
+	int       top_field_first;
+	int       repeat_first_field;
+	int       progressive_frame;
+	int       bank;
+	int       forward_bank;
+	int       backward_bank;
+	int       compress;
+	s16       frame_centre_horizontal_offset[OFF_SIZE];
+		  /* [0-2] 1st field, [3] 2nd field */
+	s16       frame_centre_vertical_offset[OFF_SIZE];
+		  /* [0-2] 1st field, [3] 2nd field */
+	s16       temporal_reference[2];
+		  /* [0] 1st field, [1] 2nd field */
+
+	s8        picture_coding_type[2];
+		  /* [0] 1st field, [1] 2nd field */
+	s8        picture_structure[2];
+		  /* [0] 1st field, [1] 2nd field */
+	s8        picture_display_extension_flag[2];
+		  /* [0] 1st field, [1] 2nd field */
+		  /* picture_display_extenion() 0:no 1:exit*/
+	s8        pts_flag[2];
+		  /* [0] 1st field, [1] 2nd field */
+};
+
+struct dvb_audio_info {
+	int layer;
+	u32 bit_rate;
+	u32 frequency;
+	u32 mode;
+	u32 mode_extension ;
+	u32 emphasis;
+	u32 framesize;
+	u32 off;
+};
+
+int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr);
+
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/Makefile linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/Makefile
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
 # and the AV7110 DVB device driver
 #
 
-dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o
+dvb-ttpci-objs := av7110_hw.o av7110_v4l.o av7110_av.o av7110_ca.o av7110.o av7110_ipack.o dvb_filter.o
 
 ifdef CONFIG_DVB_AV7110_IR
 dvb-ttpci-objs += av7110_ir.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/ttpci/ttpci-eeprom.c linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/ttpci-eeprom.c
--- linux-libre-4.9-gnu/drivers/media/pci/ttpci/ttpci-eeprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/ttpci/ttpci-eeprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -171,5 +171,4 @@ EXPORT_SYMBOL(ttpci_eeprom_parse_mac);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");
-MODULE_DESCRIPTION("Decode dvb_net MAC address from EEPROM of PCI DVB cards "
-		"made by Siemens, Technotrend, Hauppauge");
+MODULE_DESCRIPTION("Decode dvb_net MAC address from EEPROM of PCI DVB cards made by Siemens, Technotrend, Hauppauge");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/tw5864/tw5864-reg.h linux-libre-4.10-rc8-gnu/drivers/media/pci/tw5864/tw5864-reg.h
--- linux-libre-4.9-gnu/drivers/media/pci/tw5864/tw5864-reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/tw5864/tw5864-reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -1879,6 +1879,14 @@
 #define TW5864_INDIR_IN_PIC_HEIGHT(channel) (0x201 + 4 * channel)
 #define TW5864_INDIR_OUT_PIC_WIDTH(channel) (0x202 + 4 * channel)
 #define TW5864_INDIR_OUT_PIC_HEIGHT(channel) (0x203 + 4 * channel)
+
+/* Some registers skipped */
+
+#define TW5864_INDIR_CROP_ETC 0x260
+/* Define controls in register TW5864_INDIR_CROP_ETC */
+/* Enable cropping from 720 to 704 */
+#define TW5864_INDIR_CROP_ETC_CROP_EN 0x4
+
 /*
  * Interrupt status register from the front-end. Write "1" to each bit to clear
  * the interrupt
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/tw5864/tw5864-video.c linux-libre-4.10-rc8-gnu/drivers/media/pci/tw5864/tw5864-video.c
--- linux-libre-4.9-gnu/drivers/media/pci/tw5864/tw5864-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/tw5864/tw5864-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -330,6 +330,15 @@ static int tw5864_enable_input(struct tw
 	tw_indir_writeb(TW5864_INDIR_OUT_PIC_WIDTH(nr), input->width / 4);
 	tw_indir_writeb(TW5864_INDIR_OUT_PIC_HEIGHT(nr), input->height / 4);
 
+	/*
+	 * Crop width from 720 to 704.
+	 * Above register settings need value 720 involved.
+	 */
+	input->width = 704;
+	tw_indir_writeb(TW5864_INDIR_CROP_ETC,
+			tw_indir_readb(TW5864_INDIR_CROP_ETC) |
+			TW5864_INDIR_CROP_ETC_CROP_EN);
+
 	tw_writel(TW5864_DSP_PIC_MAX_MB,
 		  ((input->width / 16) << 8) | (input->height / 16));
 
@@ -532,7 +541,7 @@ static int tw5864_fmt_vid_cap(struct fil
 {
 	struct tw5864_input *input = video_drvdata(file);
 
-	f->fmt.pix.width = 720;
+	f->fmt.pix.width = 704;
 	switch (input->std) {
 	default:
 		WARN_ON_ONCE(1);
@@ -738,7 +747,7 @@ static int tw5864_enum_framesizes(struct
 		return -EINVAL;
 
 	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-	fsize->discrete.width = 720;
+	fsize->discrete.width = 704;
 	fsize->discrete.height = input->std == STD_NTSC ? 480 : 576;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/tw68/tw68-video.c linux-libre-4.10-rc8-gnu/drivers/media/pci/tw68/tw68-video.c
--- linux-libre-4.9-gnu/drivers/media/pci/tw68/tw68-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/tw68/tw68-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -279,9 +279,8 @@ static int tw68_set_scale(struct tw68_de
 		height /= 2;		/* we must set for 1-frame */
 
 	pr_debug("%s: width=%d, height=%d, both=%d\n"
-		 "  tvnorm h_delay=%d, h_start=%d, h_stop=%d, "
-		 "v_delay=%d, v_start=%d, v_stop=%d\n" , __func__,
-		width, height, V4L2_FIELD_HAS_BOTH(field),
+		 "  tvnorm h_delay=%d, h_start=%d, h_stop=%d, v_delay=%d, v_start=%d, v_stop=%d\n",
+		__func__, width, height, V4L2_FIELD_HAS_BOTH(field),
 		norm->h_delay, norm->h_start, norm->h_stop,
 		norm->v_delay, norm->video_v_start,
 		norm->video_v_stop);
@@ -309,16 +308,15 @@ static int tw68_set_scale(struct tw68_de
 		V4L2_FIELD_HAS_TOP(field)    ? "T" : "",
 		V4L2_FIELD_HAS_BOTTOM(field) ? "B" : "",
 		v4l2_norm_to_name(dev->tvnorm->id));
-	pr_debug("%s: hactive=%d, hdelay=%d, hscale=%d; "
-		"vactive=%d, vdelay=%d, vscale=%d\n", __func__,
+	pr_debug("%s: hactive=%d, hdelay=%d, hscale=%d; vactive=%d, vdelay=%d, vscale=%d\n",
+		 __func__,
 		hactive, hdelay, hscale, vactive, vdelay, vscale);
 
 	comb =	((vdelay & 0x300)  >> 2) |
 		((vactive & 0x300) >> 4) |
 		((hdelay & 0x300)  >> 6) |
 		((hactive & 0x300) >> 8);
-	pr_debug("%s: setting CROP_HI=%02x, VDELAY_LO=%02x, "
-		"VACTIVE_LO=%02x, HDELAY_LO=%02x, HACTIVE_LO=%02x\n",
+	pr_debug("%s: setting CROP_HI=%02x, VDELAY_LO=%02x, VACTIVE_LO=%02x, HDELAY_LO=%02x, HACTIVE_LO=%02x\n",
 		__func__, comb, vdelay, vactive, hdelay, hactive);
 	tw_writeb(TW68_CROP_HI, comb);
 	tw_writeb(TW68_VDELAY_LO, vdelay & 0xff);
@@ -327,8 +325,8 @@ static int tw68_set_scale(struct tw68_de
 	tw_writeb(TW68_HACTIVE_LO, hactive & 0xff);
 
 	comb = ((vscale & 0xf00) >> 4) | ((hscale & 0xf00) >> 8);
-	pr_debug("%s: setting SCALE_HI=%02x, VSCALE_LO=%02x, "
-		"HSCALE_LO=%02x\n", __func__, comb, vscale, hscale);
+	pr_debug("%s: setting SCALE_HI=%02x, VSCALE_LO=%02x, HSCALE_LO=%02x\n",
+		 __func__, comb, vscale, hscale);
 	tw_writeb(TW68_SCALE_HI, comb);
 	tw_writeb(TW68_VSCALE_LO, vscale);
 	tw_writeb(TW68_HSCALE_LO, hscale);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/zoran/videocodec.c linux-libre-4.10-rc8-gnu/drivers/media/pci/zoran/videocodec.c
--- linux-libre-4.9-gnu/drivers/media/pci/zoran/videocodec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/zoran/videocodec.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #endif
 
 #include "videocodec.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/zoran/zoran_device.c linux-libre-4.10-rc8-gnu/drivers/media/pci/zoran/zoran_device.c
--- linux-libre-4.9-gnu/drivers/media/pci/zoran/zoran_device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/zoran/zoran_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -173,12 +173,8 @@ dump_guests (struct zoran *zr)
 			guest[i] = post_office_read(zr, i, 0);
 		}
 
-		printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
-
-		for (i = 1; i < 8; i++) {
-			printk(" 0x%02x", guest[i]);
-		}
-		printk("\n");
+		printk(KERN_INFO "%s: Guests: %*ph\n",
+		       ZR_DEVNAME(zr), 8, guest);
 	}
 }
 
@@ -216,12 +212,9 @@ detect_guest_activity (struct zoran *zr)
 		if (j >= 8)
 			break;
 	}
-	printk(KERN_INFO "%s: Guests:", ZR_DEVNAME(zr));
 
-	for (i = 1; i < 8; i++) {
-		printk(" 0x%02x", guest0[i]);
-	}
-	printk("\n");
+	printk(KERN_INFO "%s: Guests: %*ph\n", ZR_DEVNAME(zr), 8, guest0);
+
 	if (j == 0) {
 		printk(KERN_INFO "%s: No activity detected.\n", ZR_DEVNAME(zr));
 		return;
@@ -822,39 +815,39 @@ print_interrupts (struct zoran *zr)
 
 	printk(KERN_INFO "%s: interrupts received:", ZR_DEVNAME(zr));
 	if ((res = zr->field_counter) < -1 || res > 1) {
-		printk(" FD:%d", res);
+		printk(KERN_CONT " FD:%d", res);
 	}
 	if ((res = zr->intr_counter_GIRQ1) != 0) {
-		printk(" GIRQ1:%d", res);
+		printk(KERN_CONT " GIRQ1:%d", res);
 		noerr++;
 	}
 	if ((res = zr->intr_counter_GIRQ0) != 0) {
-		printk(" GIRQ0:%d", res);
+		printk(KERN_CONT " GIRQ0:%d", res);
 		noerr++;
 	}
 	if ((res = zr->intr_counter_CodRepIRQ) != 0) {
-		printk(" CodRepIRQ:%d", res);
+		printk(KERN_CONT " CodRepIRQ:%d", res);
 		noerr++;
 	}
 	if ((res = zr->intr_counter_JPEGRepIRQ) != 0) {
-		printk(" JPEGRepIRQ:%d", res);
+		printk(KERN_CONT " JPEGRepIRQ:%d", res);
 		noerr++;
 	}
 	if (zr->JPEG_max_missed) {
-		printk(" JPEG delays: max=%d min=%d", zr->JPEG_max_missed,
+		printk(KERN_CONT " JPEG delays: max=%d min=%d", zr->JPEG_max_missed,
 		       zr->JPEG_min_missed);
 	}
 	if (zr->END_event_missed) {
-		printk(" ENDs missed: %d", zr->END_event_missed);
+		printk(KERN_CONT " ENDs missed: %d", zr->END_event_missed);
 	}
 	//if (zr->jpg_queued_num) {
-	printk(" queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail,
+	printk(KERN_CONT " queue_state=%ld/%ld/%ld/%ld", zr->jpg_que_tail,
 	       zr->jpg_dma_tail, zr->jpg_dma_head, zr->jpg_que_head);
 	//}
 	if (!noerr) {
-		printk(": no interrupts detected.");
+		printk(KERN_CONT ": no interrupts detected.");
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 
 void
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/pci/zoran/zoran_driver.c linux-libre-4.10-rc8-gnu/drivers/media/pci/zoran/zoran_driver.c
--- linux-libre-4.9-gnu/drivers/media/pci/zoran/zoran_driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/pci/zoran/zoran_driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,7 +66,7 @@
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/proc_fs.h>
 
 #include <linux/mutex.h>
@@ -1488,7 +1488,7 @@ zoran_set_input (struct zoran *zr,
 	if (input < 0 || input >= zr->card.inputs) {
 		dprintk(1,
 			KERN_ERR
-			"%s: %s - unnsupported input %d\n",
+			"%s: %s - unsupported input %d\n",
 			ZR_DEVNAME(zr), __func__, input);
 		return -EINVAL;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/arv.c linux-libre-4.10-rc8-gnu/drivers/media/platform/arv.c
--- linux-libre-4.9-gnu/drivers/media/platform/arv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/arv.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <media/v4l2-fh.h>
 #include <linux/mutex.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/m32r.h>
 #include <asm/io.h>
 #include <asm/dma.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/atmel/atmel-isc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/atmel/atmel-isc.c
--- linux-libre-4.9-gnu/drivers/media/platform/atmel/atmel-isc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/atmel/atmel-isc.c	2017-02-12 16:03:20.000000000 -0500
@@ -617,7 +617,13 @@ static void isc_buffer_queue(struct vb2_
 	unsigned long flags;
 
 	spin_lock_irqsave(&isc->dma_queue_lock, flags);
-	list_add_tail(&buf->list, &isc->dma_queue);
+	if (!isc->cur_frm && list_empty(&isc->dma_queue) &&
+		vb2_is_streaming(vb->vb2_queue)) {
+		isc->cur_frm = buf;
+		isc_start_dma(isc->regmap, isc->cur_frm,
+			isc->current_fmt->reg_dctrl_dview);
+	} else
+		list_add_tail(&buf->list, &isc->dma_queue);
 	spin_unlock_irqrestore(&isc->dma_queue_lock, flags);
 }
 
@@ -1418,6 +1424,7 @@ static int atmel_isc_probe(struct platfo
 
 	if (list_empty(&isc->subdev_entities)) {
 		dev_err(dev, "no subdev found\n");
+		ret = -ENODEV;
 		goto unregister_v4l2_device;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/blackfin/bfin_capture.c linux-libre-4.10-rc8-gnu/drivers/media/platform/blackfin/bfin_capture.c
--- linux-libre-4.9-gnu/drivers/media/platform/blackfin/bfin_capture.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/blackfin/bfin_capture.c	2017-02-12 16:03:20.000000000 -0500
@@ -169,7 +169,7 @@ static int bcap_init_sensor_formats(stru
 	if (!num_formats)
 		return -ENXIO;
 
-	sf = kzalloc(num_formats * sizeof(*sf), GFP_KERNEL);
+	sf = kcalloc(num_formats, sizeof(*sf), GFP_KERNEL);
 	if (!sf)
 		return -ENOMEM;
 
@@ -802,10 +802,8 @@ static int bcap_probe(struct platform_de
 	}
 
 	bcap_dev = kzalloc(sizeof(*bcap_dev), GFP_KERNEL);
-	if (!bcap_dev) {
-		v4l2_err(pdev->dev.driver, "Unable to alloc bcap_dev\n");
+	if (!bcap_dev)
 		return -ENOMEM;
-	}
 
 	bcap_dev->cfg = config;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/blackfin/ppi.c linux-libre-4.10-rc8-gnu/drivers/media/platform/blackfin/ppi.c
--- linux-libre-4.9-gnu/drivers/media/platform/blackfin/ppi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/blackfin/ppi.c	2017-02-12 16:03:20.000000000 -0500
@@ -214,6 +214,8 @@ static int ppi_set_params(struct ppi_if
 	if (params->dlen > 24 || params->dlen <= 0)
 		return -EINVAL;
 	pctrl = devm_pinctrl_get(ppi->dev);
+	if (IS_ERR(pctrl))
+		return PTR_ERR(pctrl);
 	pstate = pinctrl_lookup_state(pctrl,
 				      pin_state[(params->dlen + 7) / 8 - 1]);
 	if (pinctrl_select_state(pctrl, pstate))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/coda/coda-common.c linux-libre-4.10-rc8-gnu/drivers/media/platform/coda/coda-common.c
--- linux-libre-4.9-gnu/drivers/media/platform/coda/coda-common.c	2016-12-11 17:47:10.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/coda/coda-common.c	2017-02-12 17:34:07.000000000 -0500
@@ -2295,8 +2295,13 @@ static int coda_probe(struct platform_de
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
-	return coda_firmware_request(dev);
+	ret = coda_firmware_request(dev);
+	if (ret)
+		goto err_alloc_workqueue;
+	return 0;
 
+err_alloc_workqueue:
+	destroy_workqueue(dev->workqueue);
 err_v4l2_register:
 	v4l2_device_unregister(&dev->v4l2_dev);
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/coda/coda-h264.c linux-libre-4.10-rc8-gnu/drivers/media/platform/coda/coda-h264.c
--- linux-libre-4.9-gnu/drivers/media/platform/coda/coda-h264.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/coda/coda-h264.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <coda.h>
 
 static const u8 coda_filler_nal[14] = { 0x00, 0x00, 0x00, 0x01, 0x0c, 0xff,
 			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/davinci/dm355_ccdc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/dm355_ccdc.c
--- linux-libre-4.9-gnu/drivers/media/platform/davinci/dm355_ccdc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/dm355_ccdc.c	2017-02-12 16:03:20.000000000 -0500
@@ -334,8 +334,8 @@ static int ccdc_set_params(void __user *
 
 	x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
 	if (x) {
-		dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdc"
-			"params, %d\n", x);
+		dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdcparams, %d\n",
+			x);
 		return -EFAULT;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/davinci/dm644x_ccdc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/dm644x_ccdc.c
--- linux-libre-4.9-gnu/drivers/media/platform/davinci/dm644x_ccdc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/dm644x_ccdc.c	2017-02-12 16:03:20.000000000 -0500
@@ -354,8 +354,8 @@ static int ccdc_set_params(void __user *
 
 	x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params));
 	if (x) {
-		dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying"
-			   "ccdc params, %d\n", x);
+		dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copyingccdc params, %d\n",
+			x);
 		return -EFAULT;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/davinci/vpbe.c linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpbe.c
--- linux-libre-4.9-gnu/drivers/media/platform/davinci/vpbe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpbe.c	2017-02-12 16:03:20.000000000 -0500
@@ -107,7 +107,7 @@ static int vpbe_find_encoder_sd_index(st
 static int vpbe_g_cropcap(struct vpbe_device *vpbe_dev,
 			  struct v4l2_cropcap *cropcap)
 {
-	if (NULL == cropcap)
+	if (!cropcap)
 		return -EINVAL;
 	cropcap->bounds.left = 0;
 	cropcap->bounds.top = 0;
@@ -149,7 +149,7 @@ static int vpbe_get_mode_info(struct vpb
 	int curr_output = output_index;
 	int i;
 
-	if (NULL == mode)
+	if (!mode)
 		return -EINVAL;
 
 	for (i = 0; i < cfg->outputs[curr_output].num_modes; i++) {
@@ -166,7 +166,7 @@ static int vpbe_get_mode_info(struct vpb
 static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
 				      struct vpbe_enc_mode_info *mode_info)
 {
-	if (NULL == mode_info)
+	if (!mode_info)
 		return -EINVAL;
 
 	*mode_info = vpbe_dev->current_timings;
@@ -227,10 +227,9 @@ static int vpbe_set_output(struct vpbe_d
 			vpbe_current_encoder_info(vpbe_dev);
 	struct vpbe_config *cfg = vpbe_dev->cfg;
 	struct venc_platform_data *venc_device = vpbe_dev->venc_device;
-	u32 if_params;
 	int enc_out_index;
 	int sd_index;
-	int ret = 0;
+	int ret;
 
 	if (index >= cfg->num_outputs)
 		return -EINVAL;
@@ -254,20 +253,19 @@ static int vpbe_set_output(struct vpbe_d
 		sd_index = vpbe_find_encoder_sd_index(cfg, index);
 		if (sd_index < 0) {
 			ret = -EINVAL;
-			goto out;
+			goto unlock;
 		}
 
-		if_params = cfg->outputs[index].if_params;
-		venc_device->setup_if_config(if_params);
+		ret = venc_device->setup_if_config(cfg->outputs[index].if_params);
 		if (ret)
-			goto out;
+			goto unlock;
 	}
 
 	/* Set output at the encoder */
 	ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
 				       s_routing, 0, enc_out_index, 0);
 	if (ret)
-		goto out;
+		goto unlock;
 
 	/*
 	 * It is assumed that venc or extenal encoder will set a default
@@ -289,7 +287,7 @@ static int vpbe_set_output(struct vpbe_d
 		vpbe_dev->current_sd_index = sd_index;
 		vpbe_dev->current_out_index = index;
 	}
-out:
+unlock:
 	mutex_unlock(&vpbe_dev->lock);
 	return ret;
 }
@@ -297,19 +295,19 @@ out:
 static int vpbe_set_default_output(struct vpbe_device *vpbe_dev)
 {
 	struct vpbe_config *cfg = vpbe_dev->cfg;
-	int ret = 0;
 	int i;
 
 	for (i = 0; i < cfg->num_outputs; i++) {
 		if (!strcmp(def_output,
 			    cfg->outputs[i].output.name)) {
-			ret = vpbe_set_output(vpbe_dev, i);
+			int ret = vpbe_set_output(vpbe_dev, i);
+
 			if (!ret)
 				vpbe_dev->current_out_index = i;
 			return ret;
 		}
 	}
-	return ret;
+	return 0;
 }
 
 /**
@@ -356,7 +354,7 @@ static int vpbe_s_dv_timings(struct vpbe
 
 	ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
 					s_dv_timings, dv_timings);
-	if (!ret && (vpbe_dev->amp != NULL)) {
+	if (!ret && vpbe_dev->amp) {
 		/* Call amplifier subdevice */
 		ret = v4l2_subdev_call(vpbe_dev->amp, video,
 				s_dv_timings, dv_timings);
@@ -509,10 +507,9 @@ static int vpbe_set_mode(struct vpbe_dev
 	struct v4l2_dv_timings dv_timings;
 	struct osd_state *osd_device;
 	int out_index = vpbe_dev->current_out_index;
-	int ret = 0;
 	int i;
 
-	if ((NULL == mode_info) || (NULL == mode_info->name))
+	if (!mode_info || !mode_info->name)
 		return -EINVAL;
 
 	for (i = 0; i < cfg->outputs[out_index].num_modes; i++) {
@@ -536,7 +533,7 @@ static int vpbe_set_mode(struct vpbe_dev
 	}
 
 	/* Only custom timing should reach here */
-	if (preset_mode == NULL)
+	if (!preset_mode)
 		return -EINVAL;
 
 	mutex_lock(&vpbe_dev->lock);
@@ -549,8 +546,7 @@ static int vpbe_set_mode(struct vpbe_dev
 		vpbe_dev->current_timings.upper_margin);
 
 	mutex_unlock(&vpbe_dev->lock);
-
-	return ret;
+	return 0;
 }
 
 static int vpbe_set_default_mode(struct vpbe_device *vpbe_dev)
@@ -570,9 +566,9 @@ static int platform_device_get(struct de
 	struct platform_device *pdev = to_platform_device(dev);
 	struct vpbe_device *vpbe_dev = data;
 
-	if (strstr(pdev->name, "vpbe-osd") != NULL)
+	if (strstr(pdev->name, "vpbe-osd"))
 		vpbe_dev->osd_device = platform_get_drvdata(pdev);
-	if (strstr(pdev->name, "vpbe-venc") != NULL)
+	if (strstr(pdev->name, "vpbe-venc"))
 		vpbe_dev->venc_device = dev_get_platdata(&pdev->dev);
 
 	return 0;
@@ -606,7 +602,7 @@ static int vpbe_initialize(struct device
 	 * from the platform device by iteration of platform drivers and
 	 * matching with device name
 	 */
-	if (NULL == vpbe_dev || NULL == dev) {
+	if (!vpbe_dev || !dev) {
 		printk(KERN_ERR "Null device pointers.\n");
 		return -ENODEV;
 	}
@@ -652,7 +648,7 @@ static int vpbe_initialize(struct device
 	vpbe_dev->venc = venc_sub_dev_init(&vpbe_dev->v4l2_dev,
 					   vpbe_dev->cfg->venc.module_name);
 	/* register venc sub device */
-	if (vpbe_dev->venc == NULL) {
+	if (!vpbe_dev->venc) {
 		v4l2_err(&vpbe_dev->v4l2_dev,
 			"vpbe unable to init venc sub device\n");
 		ret = -ENODEV;
@@ -660,8 +656,7 @@ static int vpbe_initialize(struct device
 	}
 	/* initialize osd device */
 	osd_device = vpbe_dev->osd_device;
-
-	if (NULL != osd_device->ops.initialize) {
+	if (osd_device->ops.initialize) {
 		err = osd_device->ops.initialize(osd_device);
 		if (err) {
 			v4l2_err(&vpbe_dev->v4l2_dev,
@@ -676,12 +671,10 @@ static int vpbe_initialize(struct device
 	 * store venc sd index.
 	 */
 	num_encoders = vpbe_dev->cfg->num_ext_encoders + 1;
-	vpbe_dev->encoders = kmalloc(
-				sizeof(struct v4l2_subdev *)*num_encoders,
-				GFP_KERNEL);
-	if (NULL == vpbe_dev->encoders) {
-		v4l2_err(&vpbe_dev->v4l2_dev,
-			"unable to allocate memory for encoders sub devices");
+	vpbe_dev->encoders = kmalloc_array(num_encoders,
+					   sizeof(*vpbe_dev->encoders),
+					   GFP_KERNEL);
+	if (!vpbe_dev->encoders) {
 		ret = -ENOMEM;
 		goto fail_dev_unregister;
 	}
@@ -705,19 +698,17 @@ static int vpbe_initialize(struct device
 					  "v4l2 sub device %s registered\n",
 					  enc_info->module_name);
 			else {
-				v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s"
-					 " failed to register",
+				v4l2_err(&vpbe_dev->v4l2_dev, "encoder %s failed to register",
 					 enc_info->module_name);
 				ret = -ENODEV;
 				goto fail_kfree_encoders;
 			}
 		} else
-			v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders"
-				 " currently not supported");
+			v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders currently not supported");
 	}
 	/* Add amplifier subdevice for dm365 */
 	if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) &&
-			vpbe_dev->cfg->amp != NULL) {
+	   vpbe_dev->cfg->amp) {
 		amp_info = vpbe_dev->cfg->amp;
 		if (amp_info->is_i2c) {
 			vpbe_dev->amp = v4l2_i2c_new_subdev_board(
@@ -735,8 +726,7 @@ static int vpbe_initialize(struct device
 					  amp_info->module_name);
 		} else {
 			    vpbe_dev->amp = NULL;
-			    v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers"
-			    " currently not supported");
+			    v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers currently not supported");
 		}
 	} else {
 	    vpbe_dev->amp = NULL;
@@ -824,9 +814,8 @@ static int vpbe_probe(struct platform_de
 {
 	struct vpbe_device *vpbe_dev;
 	struct vpbe_config *cfg;
-	int ret = -EINVAL;
 
-	if (pdev->dev.platform_data == NULL) {
+	if (!pdev->dev.platform_data) {
 		v4l2_err(pdev->dev.driver, "No platform data\n");
 		return -ENODEV;
 	}
@@ -835,17 +824,14 @@ static int vpbe_probe(struct platform_de
 	if (!cfg->module_name[0] ||
 	    !cfg->osd.module_name[0] ||
 	    !cfg->venc.module_name[0]) {
-		v4l2_err(pdev->dev.driver, "vpbe display module names not"
-			 " defined\n");
-		return ret;
+		v4l2_err(pdev->dev.driver, "vpbe display module names not defined\n");
+		return -EINVAL;
 	}
 
 	vpbe_dev = kzalloc(sizeof(*vpbe_dev), GFP_KERNEL);
-	if (vpbe_dev == NULL) {
-		v4l2_err(pdev->dev.driver, "Unable to allocate memory"
-			 " for vpbe_device\n");
+	if (!vpbe_dev)
 		return -ENOMEM;
-	}
+
 	vpbe_dev->cfg = cfg;
 	vpbe_dev->ops = vpbe_dev_ops;
 	vpbe_dev->pdev = &pdev->dev;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/davinci/vpfe_capture.c linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpfe_capture.c
--- linux-libre-4.9-gnu/drivers/media/platform/davinci/vpfe_capture.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpfe_capture.c	2017-02-12 16:03:20.000000000 -0500
@@ -229,7 +229,7 @@ int vpfe_register_ccdc_device(struct ccd
 	BUG_ON(!dev->hw_ops.getfid);
 
 	mutex_lock(&ccdc_lock);
-	if (NULL == ccdc_cfg) {
+	if (!ccdc_cfg) {
 		/*
 		 * TODO. Will this ever happen? if so, we need to fix it.
 		 * Proabably we need to add the request to a linked list and
@@ -265,7 +265,7 @@ EXPORT_SYMBOL(vpfe_register_ccdc_device)
  */
 void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev)
 {
-	if (NULL == dev) {
+	if (!dev) {
 		printk(KERN_ERR "invalid ccdc device ptr\n");
 		return;
 	}
@@ -281,7 +281,6 @@ void vpfe_unregister_ccdc_device(struct
 	mutex_lock(&ccdc_lock);
 	ccdc_dev = NULL;
 	mutex_unlock(&ccdc_lock);
-	return;
 }
 EXPORT_SYMBOL(vpfe_unregister_ccdc_device);
 
@@ -384,7 +383,7 @@ static int vpfe_config_image_format(stru
 	};
 	struct v4l2_mbus_framefmt *mbus_fmt = &fmt.format;
 	struct v4l2_pix_format *pix = &vpfe_dev->fmt.fmt.pix;
-	int i, ret = 0;
+	int i, ret;
 
 	for (i = 0; i < ARRAY_SIZE(vpfe_standards); i++) {
 		if (vpfe_standards[i].std_id & std_id) {
@@ -453,7 +452,7 @@ static int vpfe_config_image_format(stru
 
 static int vpfe_initialize_device(struct vpfe_device *vpfe_dev)
 {
-	int ret = 0;
+	int ret;
 
 	/* set first input of current subdevice as the current input */
 	vpfe_dev->current_input = 0;
@@ -469,7 +468,7 @@ static int vpfe_initialize_device(struct
 
 	/* now open the ccdc device to initialize it */
 	mutex_lock(&ccdc_lock);
-	if (NULL == ccdc_dev) {
+	if (!ccdc_dev) {
 		v4l2_err(&vpfe_dev->v4l2_dev, "ccdc device not registered\n");
 		ret = -ENODEV;
 		goto unlock;
@@ -511,12 +510,10 @@ static int vpfe_open(struct file *file)
 	}
 
 	/* Allocate memory for the file handle object */
-	fh = kmalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
-	if (NULL == fh) {
-		v4l2_err(&vpfe_dev->v4l2_dev,
-			"unable to allocate memory for file handle object\n");
+	fh = kmalloc(sizeof(*fh), GFP_KERNEL);
+	if (!fh)
 		return -ENOMEM;
-	}
+
 	/* store pointer to fh in private_data member of file */
 	file->private_data = fh;
 	fh->vpfe_dev = vpfe_dev;
@@ -584,7 +581,7 @@ static irqreturn_t vpfe_isr(int irq, voi
 		goto clear_intr;
 
 	/* only for 6446 this will be applicable */
-	if (NULL != ccdc_dev->hw_ops.reset)
+	if (ccdc_dev->hw_ops.reset)
 		ccdc_dev->hw_ops.reset();
 
 	if (field == V4L2_FIELD_NONE) {
@@ -617,9 +614,8 @@ static irqreturn_t vpfe_isr(int irq, voi
 			 * interleavely or separately in memory, reconfigure
 			 * the CCDC memory address
 			 */
-			if (field == V4L2_FIELD_SEQ_TB) {
+			if (field == V4L2_FIELD_SEQ_TB)
 				vpfe_schedule_bottom_field(vpfe_dev);
-			}
 			goto clear_intr;
 		}
 		/*
@@ -824,7 +820,7 @@ static const struct vpfe_pixel_format *
 	int temp, found;
 
 	vpfe_pix_fmt = vpfe_lookup_pix_format(pixfmt->pixelformat);
-	if (NULL == vpfe_pix_fmt) {
+	if (!vpfe_pix_fmt) {
 		/*
 		 * use current pixel format in the vpfe device. We
 		 * will find this pix format in the table
@@ -919,8 +915,7 @@ static const struct vpfe_pixel_format *
 	else
 		pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height;
 
-	v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height ="
-		 " %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",
+	v4l2_info(&vpfe_dev->v4l2_dev, "adjusted width = %d, height = %d, bpp = %d, bytesperline = %d, sizeimage = %d\n",
 		 pixfmt->width, pixfmt->height, vpfe_pix_fmt->bpp,
 		 pixfmt->bytesperline, pixfmt->sizeimage);
 	return vpfe_pix_fmt;
@@ -967,7 +962,7 @@ static int vpfe_enum_fmt_vid_cap(struct
 
 	/* Fill in the information about format */
 	pix_fmt = vpfe_lookup_pix_format(pix);
-	if (NULL != pix_fmt) {
+	if (pix_fmt) {
 		temp_index = fmt->index;
 		*fmt = pix_fmt->fmtdesc;
 		fmt->index = temp_index;
@@ -981,7 +976,7 @@ static int vpfe_s_fmt_vid_cap(struct fil
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	const struct vpfe_pixel_format *pix_fmts;
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt_vid_cap\n");
 
@@ -993,8 +988,7 @@ static int vpfe_s_fmt_vid_cap(struct fil
 
 	/* Check for valid frame format */
 	pix_fmts = vpfe_check_format(vpfe_dev, &fmt->fmt.pix);
-
-	if (NULL == pix_fmts)
+	if (!pix_fmts)
 		return -EINVAL;
 
 	/* store the pixel format in the device  object */
@@ -1020,7 +1014,7 @@ static int vpfe_try_fmt_vid_cap(struct f
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt_vid_cap\n");
 
 	pix_fmts = vpfe_check_format(vpfe_dev, &f->fmt.pix);
-	if (NULL == pix_fmts)
+	if (!pix_fmts)
 		return -EINVAL;
 	return 0;
 }
@@ -1088,12 +1082,11 @@ static int vpfe_enum_input(struct file *
 					&subdev,
 					&index,
 					inp->index) < 0) {
-		v4l2_err(&vpfe_dev->v4l2_dev, "input information not found"
-			 " for the subdev\n");
+		v4l2_err(&vpfe_dev->v4l2_dev, "input information not found for the subdev\n");
 		return -EINVAL;
 	}
 	sdinfo = &vpfe_dev->cfg->sub_devs[subdev];
-	memcpy(inp, &sdinfo->inputs[index], sizeof(struct v4l2_input));
+	*inp = sdinfo->inputs[index];
 	return 0;
 }
 
@@ -1114,8 +1107,8 @@ static int vpfe_s_input(struct file *fil
 	struct vpfe_subdev_info *sdinfo;
 	int subdev_index, inp_index;
 	struct vpfe_route *route;
-	u32 input = 0, output = 0;
-	int ret = -EINVAL;
+	u32 input, output;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
 
@@ -1147,6 +1140,9 @@ static int vpfe_s_input(struct file *fil
 	if (route && sdinfo->can_route) {
 		input = route->input;
 		output = route->output;
+	} else {
+		input = 0;
+		output = 0;
 	}
 
 	if (sd)
@@ -1181,7 +1177,7 @@ static int vpfe_querystd(struct file *fi
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	struct vpfe_subdev_info *sdinfo;
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
 
@@ -1200,7 +1196,7 @@ static int vpfe_s_std(struct file *file,
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	struct vpfe_subdev_info *sdinfo;
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
 
@@ -1349,7 +1345,7 @@ static int vpfe_reqbufs(struct file *fil
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	struct vpfe_fh *fh = file->private_data;
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
 
@@ -1481,7 +1477,7 @@ static int vpfe_streamon(struct file *fi
 	struct vpfe_fh *fh = file->private_data;
 	struct vpfe_subdev_info *sdinfo;
 	unsigned long addr;
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
 
@@ -1564,7 +1560,7 @@ static int vpfe_streamoff(struct file *f
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	struct vpfe_fh *fh = file->private_data;
 	struct vpfe_subdev_info *sdinfo;
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
 
@@ -1650,7 +1646,7 @@ static int vpfe_s_selection(struct file
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	struct v4l2_rect rect = sel->r;
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_selection\n");
 
@@ -1708,7 +1704,7 @@ static long vpfe_param_handler(struct fi
 		bool valid_prio, unsigned int cmd, void *param)
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
-	int ret = 0;
+	int ret;
 
 	v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n");
 
@@ -1821,7 +1817,7 @@ static int vpfe_probe(struct platform_de
 	struct vpfe_device *vpfe_dev;
 	struct i2c_adapter *i2c_adap;
 	struct video_device *vfd;
-	int ret = -ENOMEM, i, j;
+	int ret, i, j;
 	int num_subdevs = 0;
 
 	/* Get the pointer to the device object */
@@ -1830,12 +1826,12 @@ static int vpfe_probe(struct platform_de
 	if (!vpfe_dev) {
 		v4l2_err(pdev->dev.driver,
 			"Failed to allocate memory for vpfe_dev\n");
-		return ret;
+		return -ENOMEM;
 	}
 
 	vpfe_dev->pdev = &pdev->dev;
 
-	if (NULL == pdev->dev.platform_data) {
+	if (!pdev->dev.platform_data) {
 		v4l2_err(pdev->dev.driver, "Unable to get vpfe config\n");
 		ret = -ENODEV;
 		goto probe_free_dev_mem;
@@ -1843,19 +1839,16 @@ static int vpfe_probe(struct platform_de
 
 	vpfe_cfg = pdev->dev.platform_data;
 	vpfe_dev->cfg = vpfe_cfg;
-	if (NULL == vpfe_cfg->ccdc ||
-	    NULL == vpfe_cfg->card_name ||
-	    NULL == vpfe_cfg->sub_devs) {
+	if (!vpfe_cfg->ccdc || !vpfe_cfg->card_name || !vpfe_cfg->sub_devs) {
 		v4l2_err(pdev->dev.driver, "null ptr in vpfe_cfg\n");
 		ret = -ENOENT;
 		goto probe_free_dev_mem;
 	}
 
 	/* Allocate memory for ccdc configuration */
-	ccdc_cfg = kmalloc(sizeof(struct ccdc_config), GFP_KERNEL);
-	if (NULL == ccdc_cfg) {
-		v4l2_err(pdev->dev.driver,
-			 "Memory allocation failed for ccdc_cfg\n");
+	ccdc_cfg = kmalloc(sizeof(*ccdc_cfg), GFP_KERNEL);
+	if (!ccdc_cfg) {
+		ret = -ENOMEM;
 		goto probe_free_dev_mem;
 	}
 
@@ -1940,11 +1933,10 @@ static int vpfe_probe(struct platform_de
 	video_set_drvdata(&vpfe_dev->video_dev, vpfe_dev);
 	i2c_adap = i2c_get_adapter(vpfe_cfg->i2c_adapter_id);
 	num_subdevs = vpfe_cfg->num_subdevs;
-	vpfe_dev->sd = kmalloc(sizeof(struct v4l2_subdev *) * num_subdevs,
-				GFP_KERNEL);
-	if (NULL == vpfe_dev->sd) {
-		v4l2_err(&vpfe_dev->v4l2_dev,
-			"unable to allocate memory for subdevice pointers\n");
+	vpfe_dev->sd = kmalloc_array(num_subdevs,
+				     sizeof(*vpfe_dev->sd),
+				     GFP_KERNEL);
+	if (!vpfe_dev->sd) {
 		ret = -ENOMEM;
 		goto probe_out_video_unregister;
 	}
@@ -1974,6 +1966,7 @@ static int vpfe_probe(struct platform_de
 			v4l2_info(&vpfe_dev->v4l2_dev,
 				  "v4l2 sub device %s register fails\n",
 				  sdinfo->name);
+			ret = -ENXIO;
 			goto probe_sd_out;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/davinci/vpif_capture.c linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpif_capture.c
--- linux-libre-4.9-gnu/drivers/media/platform/davinci/vpif_capture.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpif_capture.c	2017-02-12 16:03:20.000000000 -0500
@@ -291,10 +291,10 @@ static void vpif_stop_streaming(struct v
 		vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
 				VB2_BUF_STATE_ERROR);
 	} else {
-		if (common->cur_frm != NULL)
+		if (common->cur_frm)
 			vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
-		if (common->next_frm != NULL)
+		if (common->next_frm)
 			vb2_buffer_done(&common->next_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 	}
@@ -375,7 +375,7 @@ static irqreturn_t vpif_channel_isr(int
 	struct vpif_device *dev = &vpif_obj;
 	struct common_obj *common;
 	struct channel_obj *ch;
-	int channel_id = 0;
+	int channel_id;
 	int fid = -1, i;
 
 	channel_id = *(int *)(dev_id);
@@ -648,7 +648,7 @@ static int vpif_input_to_subdev(
 	vpif_dbg(2, debug, "vpif_input_to_subdev\n");
 
 	subdev_name = chan_cfg->inputs[input_index].subdev_name;
-	if (subdev_name == NULL)
+	if (!subdev_name)
 		return -1;
 
 	/* loop through the sub device list to get the sub device info */
@@ -731,7 +731,7 @@ static int vpif_querystd(struct file *fi
 {
 	struct video_device *vdev = video_devdata(file);
 	struct channel_obj *ch = video_get_drvdata(vdev);
-	int ret = 0;
+	int ret;
 
 	vpif_dbg(2, debug, "vpif_querystd\n");
 
@@ -764,7 +764,7 @@ static int vpif_g_std(struct file *file,
 
 	vpif_dbg(2, debug, "vpif_g_std\n");
 
-	if (config->chan_config[ch->channel_id].inputs == NULL)
+	if (!config->chan_config[ch->channel_id].inputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -794,7 +794,7 @@ static int vpif_s_std(struct file *file,
 
 	vpif_dbg(2, debug, "vpif_s_std\n");
 
-	if (config->chan_config[ch->channel_id].inputs == NULL)
+	if (!config->chan_config[ch->channel_id].inputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -1050,7 +1050,7 @@ vpif_enum_dv_timings(struct file *file,
 	struct v4l2_input input;
 	int ret;
 
-	if (config->chan_config[ch->channel_id].inputs == NULL)
+	if (!config->chan_config[ch->channel_id].inputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -1084,7 +1084,7 @@ vpif_query_dv_timings(struct file *file,
 	struct v4l2_input input;
 	int ret;
 
-	if (config->chan_config[ch->channel_id].inputs == NULL)
+	if (!config->chan_config[ch->channel_id].inputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -1120,7 +1120,7 @@ static int vpif_s_dv_timings(struct file
 	struct v4l2_input input;
 	int ret;
 
-	if (config->chan_config[ch->channel_id].inputs == NULL)
+	if (!config->chan_config[ch->channel_id].inputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -1152,11 +1152,7 @@ static int vpif_s_dv_timings(struct file
 				timings->bt.vfrontporch &&
 				(timings->bt.vbackporch ||
 				 timings->bt.vsync))) {
-		vpif_dbg(2, debug, "Timings for width, height, "
-				"horizontal back porch, horizontal sync, "
-				"horizontal front porch, vertical back porch, "
-				"vertical sync and vertical back porch "
-				"must be defined\n");
+		vpif_dbg(2, debug, "Timings for width, height, horizontal back porch, horizontal sync, horizontal front porch, vertical back porch, vertical sync and vertical back porch must be defined\n");
 		return -EINVAL;
 	}
 
@@ -1181,8 +1177,7 @@ static int vpif_s_dv_timings(struct file
 			std_info->l11 = std_info->vsize -
 				(bt->il_vfrontporch - 1);
 		} else {
-			vpif_dbg(2, debug, "Required timing values for "
-					"interlaced BT format missing\n");
+			vpif_dbg(2, debug, "Required timing values for interlaced BT format missing\n");
 			return -EINVAL;
 		}
 	} else {
@@ -1218,7 +1213,7 @@ static int vpif_g_dv_timings(struct file
 	struct vpif_capture_chan_config *chan_cfg;
 	struct v4l2_input input;
 
-	if (config->chan_config[ch->channel_id].inputs == NULL)
+	if (!config->chan_config[ch->channel_id].inputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -1464,10 +1459,8 @@ static __init int vpif_probe(struct plat
 	vpif_obj.config = pdev->dev.platform_data;
 
 	subdev_count = vpif_obj.config->subdev_count;
-	vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
-				GFP_KERNEL);
-	if (vpif_obj.sd == NULL) {
-		vpif_err("unable to allocate memory for subdevice pointers\n");
+	vpif_obj.sd = kcalloc(subdev_count, sizeof(*vpif_obj.sd), GFP_KERNEL);
+	if (!vpif_obj.sd) {
 		err = -ENOMEM;
 		goto vpif_unregister;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/davinci/vpif_display.c linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpif_display.c
--- linux-libre-4.9-gnu/drivers/media/platform/davinci/vpif_display.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpif_display.c	2017-02-12 16:03:20.000000000 -0500
@@ -271,10 +271,10 @@ static void vpif_stop_streaming(struct v
 		vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
 				VB2_BUF_STATE_ERROR);
 	} else {
-		if (common->cur_frm != NULL)
+		if (common->cur_frm)
 			vb2_buffer_done(&common->cur_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
-		if (common->next_frm != NULL)
+		if (common->next_frm)
 			vb2_buffer_done(&common->next_frm->vb.vb2_buf,
 					VB2_BUF_STATE_ERROR);
 	}
@@ -301,7 +301,7 @@ static struct vb2_ops video_qops = {
 
 static void process_progressive_mode(struct common_obj *common)
 {
-	unsigned long addr = 0;
+	unsigned long addr;
 
 	spin_lock(&common->irqlock);
 	/* Get the next buffer from buffer queue */
@@ -363,7 +363,7 @@ static irqreturn_t vpif_channel_isr(int
 	struct channel_obj *ch;
 	struct common_obj *common;
 	int fid = -1, i;
-	int channel_id = 0;
+	int channel_id;
 
 	channel_id = *(int *)(dev_id);
 	if (!vpif_intr_status(channel_id + 2))
@@ -686,7 +686,7 @@ static int vpif_s_std(struct file *file,
 	struct v4l2_output output;
 	int ret;
 
-	if (config->chan_config[ch->channel_id].outputs == NULL)
+	if (!config->chan_config[ch->channel_id].outputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -732,7 +732,7 @@ static int vpif_g_std(struct file *file,
 	struct vpif_display_chan_config *chan_cfg;
 	struct v4l2_output output;
 
-	if (config->chan_config[ch->channel_id].outputs == NULL)
+	if (!config->chan_config[ch->channel_id].outputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -783,11 +783,11 @@ vpif_output_to_subdev(struct vpif_displa
 
 	vpif_dbg(2, debug, "vpif_output_to_subdev\n");
 
-	if (chan_cfg->outputs == NULL)
+	if (!chan_cfg->outputs)
 		return -1;
 
 	subdev_name = chan_cfg->outputs[index].subdev_name;
-	if (subdev_name == NULL)
+	if (!subdev_name)
 		return -1;
 
 	/* loop through the sub device list to get the sub device info */
@@ -833,7 +833,7 @@ static int vpif_set_output(struct vpif_d
 	}
 	ch->output_idx = index;
 	ch->sd = sd;
-	if (chan_cfg->outputs != NULL)
+	if (chan_cfg->outputs)
 		/* update tvnorms from the sub device output info */
 		ch->video_dev.tvnorms = chan_cfg->outputs[index].output.std;
 	return 0;
@@ -885,7 +885,7 @@ vpif_enum_dv_timings(struct file *file,
 	struct v4l2_output output;
 	int ret;
 
-	if (config->chan_config[ch->channel_id].outputs == NULL)
+	if (!config->chan_config[ch->channel_id].outputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -922,7 +922,7 @@ static int vpif_s_dv_timings(struct file
 	struct v4l2_output output;
 	int ret;
 
-	if (config->chan_config[ch->channel_id].outputs == NULL)
+	if (!config->chan_config[ch->channel_id].outputs)
 		return -ENODATA;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -954,11 +954,7 @@ static int vpif_s_dv_timings(struct file
 				timings->bt.vfrontporch &&
 				(timings->bt.vbackporch ||
 				 timings->bt.vsync))) {
-		vpif_dbg(2, debug, "Timings for width, height, "
-				"horizontal back porch, horizontal sync, "
-				"horizontal front porch, vertical back porch, "
-				"vertical sync and vertical back porch "
-				"must be defined\n");
+		vpif_dbg(2, debug, "Timings for width, height, horizontal back porch, horizontal sync, horizontal front porch, vertical back porch, vertical sync and vertical back porch must be defined\n");
 		return -EINVAL;
 	}
 
@@ -983,8 +979,7 @@ static int vpif_s_dv_timings(struct file
 			std_info->l11 = std_info->vsize -
 				(bt->il_vfrontporch - 1);
 		} else {
-			vpif_dbg(2, debug, "Required timing values for "
-					"interlaced BT format missing\n");
+			vpif_dbg(2, debug, "Required timing values for interlaced BT format missing\n");
 			return -EINVAL;
 		}
 	} else {
@@ -1021,7 +1016,7 @@ static int vpif_g_dv_timings(struct file
 	struct video_obj *vid_ch = &ch->video;
 	struct v4l2_output output;
 
-	if (config->chan_config[ch->channel_id].outputs == NULL)
+	if (!config->chan_config[ch->channel_id].outputs)
 		goto error;
 
 	chan_cfg = &config->chan_config[ch->channel_id];
@@ -1279,10 +1274,8 @@ static __init int vpif_probe(struct plat
 	vpif_obj.config = pdev->dev.platform_data;
 	subdev_count = vpif_obj.config->subdev_count;
 	subdevdata = vpif_obj.config->subdevinfo;
-	vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
-								GFP_KERNEL);
-	if (vpif_obj.sd == NULL) {
-		vpif_err("unable to allocate memory for subdevice pointers\n");
+	vpif_obj.sd = kcalloc(subdev_count, sizeof(*vpif_obj.sd), GFP_KERNEL);
+	if (!vpif_obj.sd) {
 		err = -ENOMEM;
 		goto vpif_unregister;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/davinci/vpss.c linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpss.c
--- linux-libre-4.9-gnu/drivers/media/platform/davinci/vpss.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/davinci/vpss.c	2017-02-12 16:03:20.000000000 -0500
@@ -261,8 +261,8 @@ static int dm355_enable_clock(enum vpss_
 		shift = 6;
 		break;
 	default:
-		printk(KERN_ERR "dm355_enable_clock:"
-				" Invalid selector: %d\n", clock_sel);
+		printk(KERN_ERR "dm355_enable_clock: Invalid selector: %d\n",
+		       clock_sel);
 		return -EINVAL;
 	}
 
@@ -421,8 +421,7 @@ static int vpss_probe(struct platform_de
 	else if (!strcmp(platform_name, "dm644x_vpss"))
 		oper_cfg.platform = DM644X;
 	else {
-		dev_err(&pdev->dev, "vpss driver not supported on"
-			" this platform\n");
+		dev_err(&pdev->dev, "vpss driver not supported on this platform\n");
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/exynos4-is/fimc-core.c linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos4-is/fimc-core.c
--- linux-libre-4.9-gnu/drivers/media/platform/exynos4-is/fimc-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos4-is/fimc-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -736,6 +736,7 @@ void fimc_adjust_mplane_format(struct fi
 	for (i = 0; i < pix->num_planes; ++i) {
 		struct v4l2_plane_pix_format *plane_fmt = &pix->plane_fmt[i];
 		u32 bpl = plane_fmt->bytesperline;
+		u32 sizeimage;
 
 		if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
 			bpl = pix->width; /* Planar */
@@ -755,8 +756,17 @@ void fimc_adjust_mplane_format(struct fi
 			bytesperline /= 2;
 
 		plane_fmt->bytesperline = bytesperline;
-		plane_fmt->sizeimage = max((pix->width * pix->height *
-				   fmt->depth[i]) / 8, plane_fmt->sizeimage);
+		sizeimage = pix->width * pix->height * fmt->depth[i] / 8;
+
+		/* Ensure full last row for tiled formats */
+		if (tiled_fmt(fmt)) {
+			/* 64 * 32 * plane_fmt->bytesperline / 64 */
+			u32 row_size = plane_fmt->bytesperline * 32;
+
+			sizeimage = roundup(sizeimage, row_size);
+		}
+
+		plane_fmt->sizeimage = max(sizeimage, plane_fmt->sizeimage);
 	}
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/exynos4-is/media-dev.c linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos4-is/media-dev.c
--- linux-libre-4.9-gnu/drivers/media/platform/exynos4-is/media-dev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos4-is/media-dev.c	2017-02-12 16:03:20.000000000 -0500
@@ -938,8 +938,7 @@ static int fimc_md_create_links(struct f
 
 			csis = fmd->csis[pdata->mux_id].sd;
 			if (WARN(csis == NULL,
-				 "MIPI-CSI interface specified "
-				 "but s5p-csis module is not loaded!\n"))
+				 "MIPI-CSI interface specified but s5p-csis module is not loaded!\n"))
 				return -EINVAL;
 
 			pad = sensor->entity.num_pads - 1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/exynos-gsc/gsc-core.c linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos-gsc/gsc-core.c
--- linux-libre-4.9-gnu/drivers/media/platform/exynos-gsc/gsc-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos-gsc/gsc-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,12 +24,11 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <media/v4l2-ioctl.h>
 
 #include "gsc-core.h"
 
-#define GSC_CLOCK_GATE_NAME	"gscl"
-
 static const struct gsc_fmt gsc_formats[] = {
 	{
 		.name		= "RGB565",
@@ -39,8 +38,8 @@ static const struct gsc_fmt gsc_formats[
 		.num_planes	= 1,
 		.num_comp	= 1,
 	}, {
-		.name		= "XRGB-8-8-8-8, 32 bpp",
-		.pixelformat	= V4L2_PIX_FMT_RGB32,
+		.name		= "BGRX-8-8-8-8, 32 bpp",
+		.pixelformat	= V4L2_PIX_FMT_BGR32,
 		.depth		= { 32 },
 		.color		= GSC_RGB,
 		.num_planes	= 1,
@@ -441,7 +440,7 @@ int gsc_try_fmt_mplane(struct gsc_ctx *c
 	v4l_bound_align_image(&pix_mp->width, min_w, max_w, mod_x,
 		&pix_mp->height, min_h, max_h, mod_y, 0);
 	if (tmp_w != pix_mp->width || tmp_h != pix_mp->height)
-		pr_info("Image size has been modified from %dx%d to %dx%d",
+		pr_debug("Image size has been modified from %dx%d to %dx%d\n",
 			 tmp_w, tmp_h, pix_mp->width, pix_mp->height);
 
 	pix_mp->num_planes = fmt->num_planes;
@@ -451,12 +450,25 @@ int gsc_try_fmt_mplane(struct gsc_ctx *c
 	else /* SD */
 		pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
 
-
 	for (i = 0; i < pix_mp->num_planes; ++i) {
-		int bpl = (pix_mp->width * fmt->depth[i]) >> 3;
-		pix_mp->plane_fmt[i].bytesperline = bpl;
-		pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height;
+		struct v4l2_plane_pix_format *plane_fmt = &pix_mp->plane_fmt[i];
+		u32 bpl = plane_fmt->bytesperline;
 
+		if (fmt->num_comp == 1 && /* Packed */
+		    (bpl == 0 || (bpl * 8 / fmt->depth[i]) < pix_mp->width))
+			bpl = pix_mp->width * fmt->depth[i] / 8;
+
+		if (fmt->num_comp > 1 && /* Planar */
+		    (bpl == 0 || bpl < pix_mp->width))
+			bpl = pix_mp->width;
+
+		if (i != 0 && fmt->num_comp == 3)
+			bpl /= 2;
+
+		plane_fmt->bytesperline = bpl;
+		plane_fmt->sizeimage = max(pix_mp->width * pix_mp->height *
+					   fmt->depth[i] / 8,
+					   plane_fmt->sizeimage);
 		pr_debug("[%d]: bpl: %d, sizeimage: %d",
 				i, bpl, pix_mp->plane_fmt[i].sizeimage);
 	}
@@ -964,7 +976,19 @@ static struct gsc_driverdata gsc_v_100_d
 		[3] = &gsc_v_100_variant,
 	},
 	.num_entities = 4,
-	.lclk_frequency = 266000000UL,
+	.clk_names = { "gscl" },
+	.num_clocks = 1,
+};
+
+static struct gsc_driverdata gsc_5433_drvdata = {
+	.variant = {
+		[0] = &gsc_v_100_variant,
+		[1] = &gsc_v_100_variant,
+		[2] = &gsc_v_100_variant,
+	},
+	.num_entities = 3,
+	.clk_names = { "pclk", "aclk", "aclk_xiu", "aclk_gsclbend" },
+	.num_clocks = 4,
 };
 
 static const struct of_device_id exynos_gsc_match[] = {
@@ -972,98 +996,22 @@ static const struct of_device_id exynos_
 		.compatible = "samsung,exynos5-gsc",
 		.data = &gsc_v_100_drvdata,
 	},
+	{
+		.compatible = "samsung,exynos5433-gsc",
+		.data = &gsc_5433_drvdata,
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(of, exynos_gsc_match);
 
-static void *gsc_get_drv_data(struct platform_device *pdev)
-{
-	struct gsc_driverdata *driver_data = NULL;
-	const struct of_device_id *match;
-
-	match = of_match_node(exynos_gsc_match, pdev->dev.of_node);
-	if (match)
-		driver_data = (struct gsc_driverdata *)match->data;
-
-	return driver_data;
-}
-
-static void gsc_clk_put(struct gsc_dev *gsc)
-{
-	if (!IS_ERR(gsc->clock))
-		clk_unprepare(gsc->clock);
-}
-
-static int gsc_clk_get(struct gsc_dev *gsc)
-{
-	int ret;
-
-	dev_dbg(&gsc->pdev->dev, "gsc_clk_get Called\n");
-
-	gsc->clock = devm_clk_get(&gsc->pdev->dev, GSC_CLOCK_GATE_NAME);
-	if (IS_ERR(gsc->clock)) {
-		dev_err(&gsc->pdev->dev, "failed to get clock~~~: %s\n",
-			GSC_CLOCK_GATE_NAME);
-		return PTR_ERR(gsc->clock);
-	}
-
-	ret = clk_prepare(gsc->clock);
-	if (ret < 0) {
-		dev_err(&gsc->pdev->dev, "clock prepare failed for clock: %s\n",
-			GSC_CLOCK_GATE_NAME);
-		gsc->clock = ERR_PTR(-EINVAL);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int gsc_m2m_suspend(struct gsc_dev *gsc)
-{
-	unsigned long flags;
-	int timeout;
-
-	spin_lock_irqsave(&gsc->slock, flags);
-	if (!gsc_m2m_pending(gsc)) {
-		spin_unlock_irqrestore(&gsc->slock, flags);
-		return 0;
-	}
-	clear_bit(ST_M2M_SUSPENDED, &gsc->state);
-	set_bit(ST_M2M_SUSPENDING, &gsc->state);
-	spin_unlock_irqrestore(&gsc->slock, flags);
-
-	timeout = wait_event_timeout(gsc->irq_queue,
-			     test_bit(ST_M2M_SUSPENDED, &gsc->state),
-			     GSC_SHUTDOWN_TIMEOUT);
-
-	clear_bit(ST_M2M_SUSPENDING, &gsc->state);
-	return timeout == 0 ? -EAGAIN : 0;
-}
-
-static int gsc_m2m_resume(struct gsc_dev *gsc)
-{
-	struct gsc_ctx *ctx;
-	unsigned long flags;
-
-	spin_lock_irqsave(&gsc->slock, flags);
-	/* Clear for full H/W setup in first run after resume */
-	ctx = gsc->m2m.ctx;
-	gsc->m2m.ctx = NULL;
-	spin_unlock_irqrestore(&gsc->slock, flags);
-
-	if (test_and_clear_bit(ST_M2M_SUSPENDED, &gsc->state))
-		gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
-
-	return 0;
-}
-
 static int gsc_probe(struct platform_device *pdev)
 {
 	struct gsc_dev *gsc;
 	struct resource *res;
-	struct gsc_driverdata *drv_data = gsc_get_drv_data(pdev);
 	struct device *dev = &pdev->dev;
+	const struct gsc_driverdata *drv_data = of_device_get_match_data(dev);
 	int ret;
+	int i;
 
 	gsc = devm_kzalloc(dev, sizeof(struct gsc_dev), GFP_KERNEL);
 	if (!gsc)
@@ -1079,13 +1027,13 @@ static int gsc_probe(struct platform_dev
 		return -EINVAL;
 	}
 
+	gsc->num_clocks = drv_data->num_clocks;
 	gsc->variant = drv_data->variant[gsc->id];
 	gsc->pdev = pdev;
 
 	init_waitqueue_head(&gsc->irq_queue);
 	spin_lock_init(&gsc->slock);
 	mutex_init(&gsc->lock);
-	gsc->clock = ERR_PTR(-EINVAL);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	gsc->regs = devm_ioremap_resource(dev, res);
@@ -1098,9 +1046,25 @@ static int gsc_probe(struct platform_dev
 		return -ENXIO;
 	}
 
-	ret = gsc_clk_get(gsc);
-	if (ret)
-		return ret;
+	for (i = 0; i < gsc->num_clocks; i++) {
+		gsc->clock[i] = devm_clk_get(dev, drv_data->clk_names[i]);
+		if (IS_ERR(gsc->clock[i])) {
+			dev_err(dev, "failed to get clock: %s\n",
+				drv_data->clk_names[i]);
+			return PTR_ERR(gsc->clock[i]);
+		}
+	}
+
+	for (i = 0; i < gsc->num_clocks; i++) {
+		ret = clk_prepare_enable(gsc->clock[i]);
+		if (ret) {
+			dev_err(dev, "clock prepare failed for clock: %s\n",
+				drv_data->clk_names[i]);
+			while (--i >= 0)
+				clk_disable_unprepare(gsc->clock[i]);
+			return ret;
+		}
+	}
 
 	ret = devm_request_irq(dev, res->start, gsc_irq_handler,
 				0, pdev->name, gsc);
@@ -1118,114 +1082,131 @@ static int gsc_probe(struct platform_dev
 		goto err_v4l2;
 
 	platform_set_drvdata(pdev, gsc);
-	pm_runtime_enable(dev);
-	ret = pm_runtime_get_sync(&pdev->dev);
-	if (ret < 0)
-		goto err_m2m;
+
+	gsc_hw_set_sw_reset(gsc);
+	gsc_wait_reset(gsc);
 
 	vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
 	dev_dbg(dev, "gsc-%d registered successfully\n", gsc->id);
 
-	pm_runtime_put(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
 	return 0;
 
-err_m2m:
-	gsc_unregister_m2m_device(gsc);
 err_v4l2:
 	v4l2_device_unregister(&gsc->v4l2_dev);
 err_clk:
-	gsc_clk_put(gsc);
+	for (i = gsc->num_clocks - 1; i >= 0; i--)
+		clk_disable_unprepare(gsc->clock[i]);
 	return ret;
 }
 
 static int gsc_remove(struct platform_device *pdev)
 {
 	struct gsc_dev *gsc = platform_get_drvdata(pdev);
+	int i;
+
+	pm_runtime_get_sync(&pdev->dev);
 
 	gsc_unregister_m2m_device(gsc);
 	v4l2_device_unregister(&gsc->v4l2_dev);
 
 	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
-	gsc_clk_put(gsc);
+	for (i = 0; i < gsc->num_clocks; i++)
+		clk_disable_unprepare(gsc->clock[i]);
+
+	pm_runtime_put_noidle(&pdev->dev);
 
 	dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
 	return 0;
 }
 
-static int gsc_runtime_resume(struct device *dev)
+#ifdef CONFIG_PM
+static int gsc_m2m_suspend(struct gsc_dev *gsc)
 {
-	struct gsc_dev *gsc = dev_get_drvdata(dev);
-	int ret = 0;
-
-	pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
+	unsigned long flags;
+	int timeout;
 
-	ret = clk_enable(gsc->clock);
-	if (ret)
-		return ret;
+	spin_lock_irqsave(&gsc->slock, flags);
+	if (!gsc_m2m_pending(gsc)) {
+		spin_unlock_irqrestore(&gsc->slock, flags);
+		return 0;
+	}
+	clear_bit(ST_M2M_SUSPENDED, &gsc->state);
+	set_bit(ST_M2M_SUSPENDING, &gsc->state);
+	spin_unlock_irqrestore(&gsc->slock, flags);
 
-	gsc_hw_set_sw_reset(gsc);
-	gsc_wait_reset(gsc);
+	timeout = wait_event_timeout(gsc->irq_queue,
+			     test_bit(ST_M2M_SUSPENDED, &gsc->state),
+			     GSC_SHUTDOWN_TIMEOUT);
 
-	return gsc_m2m_resume(gsc);
+	clear_bit(ST_M2M_SUSPENDING, &gsc->state);
+	return timeout == 0 ? -EAGAIN : 0;
 }
 
-static int gsc_runtime_suspend(struct device *dev)
+static void gsc_m2m_resume(struct gsc_dev *gsc)
 {
-	struct gsc_dev *gsc = dev_get_drvdata(dev);
-	int ret = 0;
+	struct gsc_ctx *ctx;
+	unsigned long flags;
 
-	ret = gsc_m2m_suspend(gsc);
-	if (!ret)
-		clk_disable(gsc->clock);
+	spin_lock_irqsave(&gsc->slock, flags);
+	/* Clear for full H/W setup in first run after resume */
+	ctx = gsc->m2m.ctx;
+	gsc->m2m.ctx = NULL;
+	spin_unlock_irqrestore(&gsc->slock, flags);
 
-	pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
-	return ret;
+	if (test_and_clear_bit(ST_M2M_SUSPENDED, &gsc->state))
+		gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
 }
 
-static int gsc_resume(struct device *dev)
+static int gsc_runtime_resume(struct device *dev)
 {
 	struct gsc_dev *gsc = dev_get_drvdata(dev);
-	unsigned long flags;
+	int ret = 0;
+	int i;
 
-	pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
+	pr_debug("gsc%d: state: 0x%lx\n", gsc->id, gsc->state);
 
-	/* Do not resume if the device was idle before system suspend */
-	spin_lock_irqsave(&gsc->slock, flags);
-	if (!test_and_clear_bit(ST_SUSPEND, &gsc->state) ||
-	    !gsc_m2m_opened(gsc)) {
-		spin_unlock_irqrestore(&gsc->slock, flags);
-		return 0;
+	for (i = 0; i < gsc->num_clocks; i++) {
+		ret = clk_prepare_enable(gsc->clock[i]);
+		if (ret) {
+			while (--i >= 0)
+				clk_disable_unprepare(gsc->clock[i]);
+			return ret;
+		}
 	}
-	spin_unlock_irqrestore(&gsc->slock, flags);
 
-	if (!pm_runtime_suspended(dev))
-		return gsc_runtime_resume(dev);
+	gsc_hw_set_sw_reset(gsc);
+	gsc_wait_reset(gsc);
+	gsc_m2m_resume(gsc);
 
 	return 0;
 }
 
-static int gsc_suspend(struct device *dev)
+static int gsc_runtime_suspend(struct device *dev)
 {
 	struct gsc_dev *gsc = dev_get_drvdata(dev);
+	int ret = 0;
+	int i;
 
-	pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
-
-	if (test_and_set_bit(ST_SUSPEND, &gsc->state))
-		return 0;
+	ret = gsc_m2m_suspend(gsc);
+	if (ret)
+		return ret;
 
-	if (!pm_runtime_suspended(dev))
-		return gsc_runtime_suspend(dev);
+	for (i = gsc->num_clocks - 1; i >= 0; i--)
+		clk_disable_unprepare(gsc->clock[i]);
 
-	return 0;
+	pr_debug("gsc%d: state: 0x%lx\n", gsc->id, gsc->state);
+	return ret;
 }
+#endif
 
 static const struct dev_pm_ops gsc_pm_ops = {
-	.suspend		= gsc_suspend,
-	.resume			= gsc_resume,
-	.runtime_suspend	= gsc_runtime_suspend,
-	.runtime_resume		= gsc_runtime_resume,
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(gsc_runtime_suspend, gsc_runtime_resume, NULL)
 };
 
 static struct platform_driver gsc_driver = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/exynos-gsc/gsc-core.h linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos-gsc/gsc-core.h
--- linux-libre-4.9-gnu/drivers/media/platform/exynos-gsc/gsc-core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos-gsc/gsc-core.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,6 +33,7 @@
 
 #define GSC_SHUTDOWN_TIMEOUT		((100*HZ)/1000)
 #define GSC_MAX_DEVS			4
+#define GSC_MAX_CLOCKS			4
 #define GSC_M2M_BUF_NUM			0
 #define GSC_MAX_CTRL_NUM		10
 #define GSC_SC_ALIGN_4			4
@@ -48,9 +49,6 @@
 #define	GSC_CTX_ABORT			(1 << 7)
 
 enum gsc_dev_flags {
-	/* for global */
-	ST_SUSPEND,
-
 	/* for m2m node */
 	ST_M2M_OPEN,
 	ST_M2M_RUN,
@@ -306,12 +304,12 @@ struct gsc_variant {
  * struct gsc_driverdata - per device type driver data for init time.
  *
  * @variant: the variant information for this driver.
- * @lclk_frequency: G-Scaler clock frequency
  * @num_entities: the number of g-scalers
  */
 struct gsc_driverdata {
 	struct gsc_variant *variant[GSC_MAX_DEVS];
-	unsigned long	lclk_frequency;
+	const char	*clk_names[GSC_MAX_CLOCKS];
+	int		num_clocks;
 	int		num_entities;
 };
 
@@ -335,7 +333,8 @@ struct gsc_dev {
 	struct platform_device		*pdev;
 	struct gsc_variant		*variant;
 	u16				id;
-	struct clk			*clock;
+	int				num_clocks;
+	struct clk			*clock[GSC_MAX_CLOCKS];
 	void __iomem			*regs;
 	wait_queue_head_t		irq_queue;
 	struct gsc_m2m_device		m2m;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/exynos-gsc/gsc-m2m.c linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos-gsc/gsc-m2m.c
--- linux-libre-4.9-gnu/drivers/media/platform/exynos-gsc/gsc-m2m.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/exynos-gsc/gsc-m2m.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,12 +66,29 @@ static int gsc_m2m_start_streaming(struc
 	return ret > 0 ? 0 : ret;
 }
 
+static void __gsc_m2m_cleanup_queue(struct gsc_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *src_vb, *dst_vb;
+
+	while (v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0) {
+		src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
+	}
+
+	while (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0) {
+		dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
+	}
+}
+
 static void gsc_m2m_stop_streaming(struct vb2_queue *q)
 {
 	struct gsc_ctx *ctx = q->drv_priv;
 
 	__gsc_m2m_job_abort(ctx);
 
+	__gsc_m2m_cleanup_queue(ctx);
+
 	pm_runtime_put(&ctx->gsc_dev->pdev->dev);
 }
 
@@ -365,14 +382,8 @@ static int gsc_m2m_reqbufs(struct file *
 
 	max_cnt = (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
 		gsc->variant->in_buf_cnt : gsc->variant->out_buf_cnt;
-	if (reqbufs->count > max_cnt) {
+	if (reqbufs->count > max_cnt)
 		return -EINVAL;
-	} else if (reqbufs->count == 0) {
-		if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-			gsc_ctx_state_lock_clear(GSC_SRC_FMT, ctx);
-		else
-			gsc_ctx_state_lock_clear(GSC_DST_FMT, ctx);
-	}
 
 	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
 }
@@ -766,30 +777,29 @@ int gsc_register_m2m_device(struct gsc_d
 	gsc->m2m.m2m_dev = v4l2_m2m_init(&gsc_m2m_ops);
 	if (IS_ERR(gsc->m2m.m2m_dev)) {
 		dev_err(&pdev->dev, "failed to initialize v4l2-m2m device\n");
-		ret = PTR_ERR(gsc->m2m.m2m_dev);
-		goto err_m2m_r1;
+		return PTR_ERR(gsc->m2m.m2m_dev);
 	}
 
 	ret = video_register_device(&gsc->vdev, VFL_TYPE_GRABBER, -1);
 	if (ret) {
 		dev_err(&pdev->dev,
 			 "%s(): failed to register video device\n", __func__);
-		goto err_m2m_r2;
+		goto err_m2m_release;
 	}
 
 	pr_debug("gsc m2m driver registered as /dev/video%d", gsc->vdev.num);
 	return 0;
 
-err_m2m_r2:
+err_m2m_release:
 	v4l2_m2m_release(gsc->m2m.m2m_dev);
-err_m2m_r1:
-	video_device_release(gsc->m2m.vfd);
 
 	return ret;
 }
 
 void gsc_unregister_m2m_device(struct gsc_dev *gsc)
 {
-	if (gsc)
+	if (gsc) {
 		v4l2_m2m_release(gsc->m2m.m2m_dev);
+		video_unregister_device(&gsc->vdev);
+	}
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/platform/Kconfig
--- linux-libre-4.9-gnu/drivers/media/platform/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -93,7 +93,7 @@ config VIDEO_OMAP3_DEBUG
 
 config VIDEO_PXA27x
 	tristate "PXA27x Quick Capture Interface driver"
-	depends on VIDEO_DEV && HAS_DMA
+	depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
 	depends on PXA27x || COMPILE_TEST
 	select VIDEOBUF2_DMA_SG
 	select SG_SPLIT
@@ -175,6 +175,23 @@ config VIDEO_MEDIATEK_VPU
 	    To compile this driver as a module, choose M here: the
 	    module will be called mtk-vpu.
 
+config VIDEO_MEDIATEK_MDP
+	tristate "Mediatek MDP driver"
+	depends on MTK_IOMMU || COMPILE_TEST
+	depends on VIDEO_DEV && VIDEO_V4L2
+	depends on ARCH_MEDIATEK || COMPILE_TEST
+	depends on HAS_DMA
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_MEM2MEM_DEV
+	select VIDEO_MEDIATEK_VPU
+	default n
+	---help---
+	    It is a v4l2 driver and present in Mediatek MT8173 SoCs.
+	    The driver supports for scaling and color space conversion.
+
+	    To compile this driver as a module, choose M here: the
+	    module will be called mtk-mdp.
+
 config VIDEO_MEDIATEK_VCODEC
 	tristate "Mediatek Video Codec driver"
 	depends on MTK_IOMMU || COMPILE_TEST
@@ -249,7 +266,7 @@ config VIDEO_MX2_EMMAPRP
 config VIDEO_SAMSUNG_EXYNOS_GSC
 	tristate "Samsung Exynos G-Scaler driver"
 	depends on VIDEO_DEV && VIDEO_V4L2
-	depends on ARCH_EXYNOS5 || COMPILE_TEST
+	depends on ARCH_EXYNOS || COMPILE_TEST
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
@@ -290,6 +307,20 @@ config VIDEO_SH_VEU
 	    Support for the Video Engine Unit (VEU) on SuperH and
 	    SH-Mobile SoCs.
 
+config VIDEO_RENESAS_FDP1
+	tristate "Renesas Fine Display Processor"
+	depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
+	depends on ARCH_SHMOBILE || COMPILE_TEST
+	depends on (!ARCH_RENESAS && !VIDEO_RENESAS_FCP) || VIDEO_RENESAS_FCP
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_MEM2MEM_DEV
+	---help---
+	  This is a V4L2 driver for the Renesas Fine Display Processor
+	  providing colour space conversion, and de-interlacing features.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called rcar_fdp1.
+
 config VIDEO_RENESAS_JPU
 	tristate "Renesas JPEG Processing Unit"
 	depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA
@@ -334,6 +365,9 @@ config VIDEO_TI_VPE
 	depends on HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
+	select VIDEO_TI_VPDMA
+	select VIDEO_TI_SC
+	select VIDEO_TI_CSC
 	default n
 	---help---
 	  Support for the TI VPE(Video Processing Engine) block
@@ -347,6 +381,17 @@ config VIDEO_TI_VPE_DEBUG
 
 endif # V4L_MEM2MEM_DRIVERS
 
+# TI VIDEO PORT Helper Modules
+# These will be selected by VPE and VIP
+config VIDEO_TI_VPDMA
+	tristate
+
+config VIDEO_TI_SC
+	tristate
+
+config VIDEO_TI_CSC
+	tristate
+
 menuconfig V4L_TEST_DRIVERS
 	bool "Media test drivers"
 	depends on MEDIA_CAMERA_SUPPORT
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/Makefile linux-libre-4.10-rc8-gnu/drivers/media/platform/Makefile
--- linux-libre-4.9-gnu/drivers/media/platform/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,7 @@ obj-$(CONFIG_VIDEO_SH_VOU)		+= sh_vou.o
 obj-$(CONFIG_SOC_CAMERA)		+= soc_camera/
 
 obj-$(CONFIG_VIDEO_RENESAS_FCP) 	+= rcar-fcp.o
+obj-$(CONFIG_VIDEO_RENESAS_FDP1)	+= rcar_fdp1.o
 obj-$(CONFIG_VIDEO_RENESAS_JPU) 	+= rcar_jpu.o
 obj-$(CONFIG_VIDEO_RENESAS_VSP1)	+= vsp1/
 
@@ -66,3 +67,5 @@ ccflags-y += -I$(srctree)/drivers/media/
 obj-$(CONFIG_VIDEO_MEDIATEK_VPU)	+= mtk-vpu/
 
 obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC)	+= mtk-vcodec/
+
+obj-$(CONFIG_VIDEO_MEDIATEK_MDP)	+= mtk-mdp/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/marvell-ccic/mcam-core.c linux-libre-4.10-rc8-gnu/drivers/media/platform/marvell-ccic/mcam-core.c
--- linux-libre-4.9-gnu/drivers/media/platform/marvell-ccic/mcam-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/marvell-ccic/mcam-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,24 +49,17 @@
 static bool alloc_bufs_at_read;
 module_param(alloc_bufs_at_read, bool, 0444);
 MODULE_PARM_DESC(alloc_bufs_at_read,
-		"Non-zero value causes DMA buffers to be allocated when the "
-		"video capture device is read, rather than at module load "
-		"time.  This saves memory, but decreases the chances of "
-		"successfully getting those buffers.  This parameter is "
-		"only used in the vmalloc buffer mode");
+		"Non-zero value causes DMA buffers to be allocated when the video capture device is read, rather than at module load time.  This saves memory, but decreases the chances of successfully getting those buffers.  This parameter is only used in the vmalloc buffer mode");
 
 static int n_dma_bufs = 3;
 module_param(n_dma_bufs, uint, 0644);
 MODULE_PARM_DESC(n_dma_bufs,
-		"The number of DMA buffers to allocate.  Can be either two "
-		"(saves memory, makes timing tighter) or three.");
+		"The number of DMA buffers to allocate.  Can be either two (saves memory, makes timing tighter) or three.");
 
 static int dma_buf_size = VGA_WIDTH * VGA_HEIGHT * 2;  /* Worst case */
 module_param(dma_buf_size, uint, 0444);
 MODULE_PARM_DESC(dma_buf_size,
-		"The size of the allocated DMA buffers.  If actual operating "
-		"parameters require larger buffers, an attempt to reallocate "
-		"will be made.");
+		"The size of the allocated DMA buffers.  If actual operating parameters require larger buffers, an attempt to reallocate will be made.");
 #else /* MCAM_MODE_VMALLOC */
 static const bool alloc_bufs_at_read;
 static const int n_dma_bufs = 3;  /* Used by S/G_PARM */
@@ -75,15 +68,12 @@ static const int n_dma_bufs = 3;  /* Use
 static bool flip;
 module_param(flip, bool, 0444);
 MODULE_PARM_DESC(flip,
-		"If set, the sensor will be instructed to flip the image "
-		"vertically.");
+		"If set, the sensor will be instructed to flip the image vertically.");
 
 static int buffer_mode = -1;
 module_param(buffer_mode, int, 0444);
 MODULE_PARM_DESC(buffer_mode,
-		"Set the buffer mode to be used; default is to go with what "
-		"the platform driver asks for.  Set to 0 for vmalloc, 1 for "
-		"DMA contiguous.");
+		"Set the buffer mode to be used; default is to go with what the platform driver asks for.  Set to 0 for vmalloc, 1 for DMA contiguous.");
 
 /*
  * Status flags.  Always manipulated with bit operations.
@@ -1759,8 +1749,7 @@ int mccic_register(struct mcam_camera *c
 		cam->buffer_mode = buffer_mode;
 	if (cam->buffer_mode == B_DMA_sg &&
 			cam->chip_id == MCAM_CAFE) {
-		printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, "
-			"attempting vmalloc mode instead\n");
+		printk(KERN_ERR "marvell-cam: Cafe can't do S/G I/O, attempting vmalloc mode instead\n");
 		cam->buffer_mode = B_vmalloc;
 	}
 	if (!mcam_buffer_mode_supported(cam->buffer_mode)) {
@@ -1828,8 +1817,7 @@ int mccic_register(struct mcam_camera *c
 	 */
 	if (cam->buffer_mode == B_vmalloc && !alloc_bufs_at_read) {
 		if (mcam_alloc_dma_bufs(cam, 1))
-			cam_warn(cam, "Unable to alloc DMA buffers at load"
-					" will try again later.");
+			cam_warn(cam, "Unable to alloc DMA buffers at load will try again later.");
 	}
 
 	mutex_unlock(&cam->s_mutex);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/Makefile linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/Makefile
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,9 @@
+mtk-mdp-y += mtk_mdp_core.o
+mtk-mdp-y += mtk_mdp_comp.o
+mtk-mdp-y += mtk_mdp_m2m.o
+mtk-mdp-y += mtk_mdp_regs.o
+mtk-mdp-y += mtk_mdp_vpu.o
+
+obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp.o
+
+ccflags-y += -I$(srctree)/drivers/media/platform/mtk-vpu
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.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/clk.h>
+#include <linux/device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_mdp_comp.h"
+
+
+static const char * const mtk_mdp_comp_stem[MTK_MDP_COMP_TYPE_MAX] = {
+	"mdp_rdma",
+	"mdp_rsz",
+	"mdp_wdma",
+	"mdp_wrot",
+};
+
+struct mtk_mdp_comp_match {
+	enum mtk_mdp_comp_type type;
+	int alias_id;
+};
+
+static const struct mtk_mdp_comp_match mtk_mdp_matches[MTK_MDP_COMP_ID_MAX] = {
+	{ MTK_MDP_RDMA,	0 },
+	{ MTK_MDP_RDMA,	1 },
+	{ MTK_MDP_RSZ,	0 },
+	{ MTK_MDP_RSZ,	1 },
+	{ MTK_MDP_RSZ,	2 },
+	{ MTK_MDP_WDMA,	0 },
+	{ MTK_MDP_WROT,	0 },
+	{ MTK_MDP_WROT,	1 },
+};
+
+int mtk_mdp_comp_get_id(struct device *dev, struct device_node *node,
+			enum mtk_mdp_comp_type comp_type)
+{
+	int id = of_alias_get_id(node, mtk_mdp_comp_stem[comp_type]);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mtk_mdp_matches); i++) {
+		if (comp_type == mtk_mdp_matches[i].type &&
+		    id == mtk_mdp_matches[i].alias_id)
+			return i;
+	}
+
+	dev_err(dev, "Failed to get id. type: %d, id: %d\n", comp_type, id);
+
+	return -EINVAL;
+}
+
+void mtk_mdp_comp_clock_on(struct device *dev, struct mtk_mdp_comp *comp)
+{
+	int i, err;
+
+	if (comp->larb_dev) {
+		err = mtk_smi_larb_get(comp->larb_dev);
+		if (err)
+			dev_err(dev,
+				"failed to get larb, err %d. type:%d id:%d\n",
+				err, comp->type, comp->id);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
+		if (!comp->clk[i])
+			continue;
+		err = clk_prepare_enable(comp->clk[i]);
+		if (err)
+			dev_err(dev,
+			"failed to enable clock, err %d. type:%d id:%d i:%d\n",
+				err, comp->type, comp->id, i);
+	}
+}
+
+void mtk_mdp_comp_clock_off(struct device *dev, struct mtk_mdp_comp *comp)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
+		if (!comp->clk[i])
+			continue;
+		clk_disable_unprepare(comp->clk[i]);
+	}
+
+	if (comp->larb_dev)
+		mtk_smi_larb_put(comp->larb_dev);
+}
+
+int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
+		      struct mtk_mdp_comp *comp, enum mtk_mdp_comp_id comp_id)
+{
+	struct device_node *larb_node;
+	struct platform_device *larb_pdev;
+	int i;
+
+	if (comp_id < 0 || comp_id >= MTK_MDP_COMP_ID_MAX) {
+		dev_err(dev, "Invalid comp_id %d\n", comp_id);
+		return -EINVAL;
+	}
+
+	comp->dev_node = of_node_get(node);
+	comp->id = comp_id;
+	comp->type = mtk_mdp_matches[comp_id].type;
+	comp->regs = of_iomap(node, 0);
+
+	for (i = 0; i < ARRAY_SIZE(comp->clk); i++) {
+		comp->clk[i] = of_clk_get(node, i);
+
+		/* Only RDMA needs two clocks */
+		if (comp->type != MTK_MDP_RDMA)
+			break;
+	}
+
+	/* Only DMA capable components need the LARB property */
+	comp->larb_dev = NULL;
+	if (comp->type != MTK_MDP_RDMA &&
+	    comp->type != MTK_MDP_WDMA &&
+	    comp->type != MTK_MDP_WROT)
+		return 0;
+
+	larb_node = of_parse_phandle(node, "mediatek,larb", 0);
+	if (!larb_node) {
+		dev_err(dev,
+			"Missing mediadek,larb phandle in %s node\n",
+			node->full_name);
+		return -EINVAL;
+	}
+
+	larb_pdev = of_find_device_by_node(larb_node);
+	if (!larb_pdev) {
+		dev_warn(dev, "Waiting for larb device %s\n",
+			 larb_node->full_name);
+		of_node_put(larb_node);
+		return -EPROBE_DEFER;
+	}
+	of_node_put(larb_node);
+
+	comp->larb_dev = &larb_pdev->dev;
+
+	return 0;
+}
+
+void mtk_mdp_comp_deinit(struct device *dev, struct mtk_mdp_comp *comp)
+{
+	of_node_put(comp->dev_node);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_comp.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_COMP_H__
+#define __MTK_MDP_COMP_H__
+
+/**
+ * enum mtk_mdp_comp_type - the MDP component
+ * @MTK_MDP_RDMA:	Read DMA
+ * @MTK_MDP_RSZ:	Riszer
+ * @MTK_MDP_WDMA:	Write DMA
+ * @MTK_MDP_WROT:	Write DMA with rotation
+ */
+enum mtk_mdp_comp_type {
+	MTK_MDP_RDMA,
+	MTK_MDP_RSZ,
+	MTK_MDP_WDMA,
+	MTK_MDP_WROT,
+	MTK_MDP_COMP_TYPE_MAX,
+};
+
+enum mtk_mdp_comp_id {
+	MTK_MDP_COMP_RDMA0,
+	MTK_MDP_COMP_RDMA1,
+	MTK_MDP_COMP_RSZ0,
+	MTK_MDP_COMP_RSZ1,
+	MTK_MDP_COMP_RSZ2,
+	MTK_MDP_COMP_WDMA,
+	MTK_MDP_COMP_WROT0,
+	MTK_MDP_COMP_WROT1,
+	MTK_MDP_COMP_ID_MAX,
+};
+
+/**
+ * struct mtk_mdp_comp - the MDP's function component data
+ * @dev_node:	component device node
+ * @clk:	clocks required for component
+ * @regs:	Mapped address of component registers.
+ * @larb_dev:	SMI device required for component
+ * @type:	component type
+ * @id:		component ID
+ */
+struct mtk_mdp_comp {
+	struct device_node	*dev_node;
+	struct clk		*clk[2];
+	void __iomem		*regs;
+	struct device		*larb_dev;
+	enum mtk_mdp_comp_type	type;
+	enum mtk_mdp_comp_id	id;
+};
+
+int mtk_mdp_comp_init(struct device *dev, struct device_node *node,
+		      struct mtk_mdp_comp *comp, enum mtk_mdp_comp_id comp_id);
+void mtk_mdp_comp_deinit(struct device *dev, struct mtk_mdp_comp *comp);
+int mtk_mdp_comp_get_id(struct device *dev, struct device_node *node,
+			enum mtk_mdp_comp_type comp_type);
+void mtk_mdp_comp_clock_on(struct device *dev, struct mtk_mdp_comp *comp);
+void mtk_mdp_comp_clock_off(struct device *dev, struct mtk_mdp_comp *comp);
+
+
+#endif /* __MTK_MDP_COMP_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.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/clk.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_mdp_core.h"
+#include "mtk_mdp_m2m.h"
+#include "mtk_vpu.h"
+
+/* MDP debug log level (0-3). 3 shows all the logs. */
+int mtk_mdp_dbg_level;
+EXPORT_SYMBOL(mtk_mdp_dbg_level);
+
+module_param(mtk_mdp_dbg_level, int, 0644);
+
+static const struct of_device_id mtk_mdp_comp_dt_ids[] = {
+	{
+		.compatible = "mediatek,mt8173-mdp-rdma",
+		.data = (void *)MTK_MDP_RDMA
+	}, {
+		.compatible = "mediatek,mt8173-mdp-rsz",
+		.data = (void *)MTK_MDP_RSZ
+	}, {
+		.compatible = "mediatek,mt8173-mdp-wdma",
+		.data = (void *)MTK_MDP_WDMA
+	}, {
+		.compatible = "mediatek,mt8173-mdp-wrot",
+		.data = (void *)MTK_MDP_WROT
+	},
+	{ },
+};
+
+static const struct of_device_id mtk_mdp_of_ids[] = {
+	{ .compatible = "mediatek,mt8173-mdp", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, mtk_mdp_of_ids);
+
+static void mtk_mdp_clock_on(struct mtk_mdp_dev *mdp)
+{
+	struct device *dev = &mdp->pdev->dev;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+		mtk_mdp_comp_clock_on(dev, mdp->comp[i]);
+}
+
+static void mtk_mdp_clock_off(struct mtk_mdp_dev *mdp)
+{
+	struct device *dev = &mdp->pdev->dev;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+		mtk_mdp_comp_clock_off(dev, mdp->comp[i]);
+}
+
+static void mtk_mdp_wdt_worker(struct work_struct *work)
+{
+	struct mtk_mdp_dev *mdp =
+			container_of(work, struct mtk_mdp_dev, wdt_work);
+	struct mtk_mdp_ctx *ctx;
+
+	mtk_mdp_err("Watchdog timeout");
+
+	list_for_each_entry(ctx, &mdp->ctx_list, list) {
+		mtk_mdp_dbg(0, "[%d] Change as state error", ctx->id);
+		mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_CTX_ERROR);
+	}
+}
+
+static void mtk_mdp_reset_handler(void *priv)
+{
+	struct mtk_mdp_dev *mdp = priv;
+
+	queue_work(mdp->wdt_wq, &mdp->wdt_work);
+}
+
+static int mtk_mdp_probe(struct platform_device *pdev)
+{
+	struct mtk_mdp_dev *mdp;
+	struct device *dev = &pdev->dev;
+	struct device_node *node;
+	int i, ret = 0;
+
+	mdp = devm_kzalloc(dev, sizeof(*mdp), GFP_KERNEL);
+	if (!mdp)
+		return -ENOMEM;
+
+	mdp->id = pdev->id;
+	mdp->pdev = pdev;
+	INIT_LIST_HEAD(&mdp->ctx_list);
+
+	mutex_init(&mdp->lock);
+	mutex_init(&mdp->vpulock);
+
+	/* Iterate over sibling MDP function blocks */
+	for_each_child_of_node(dev->of_node, node) {
+		const struct of_device_id *of_id;
+		enum mtk_mdp_comp_type comp_type;
+		int comp_id;
+		struct mtk_mdp_comp *comp;
+
+		of_id = of_match_node(mtk_mdp_comp_dt_ids, node);
+		if (!of_id)
+			continue;
+
+		if (!of_device_is_available(node)) {
+			dev_err(dev, "Skipping disabled component %s\n",
+				node->full_name);
+			continue;
+		}
+
+		comp_type = (enum mtk_mdp_comp_type)of_id->data;
+		comp_id = mtk_mdp_comp_get_id(dev, node, comp_type);
+		if (comp_id < 0) {
+			dev_warn(dev, "Skipping unknown component %s\n",
+				 node->full_name);
+			continue;
+		}
+
+		comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
+		if (!comp) {
+			ret = -ENOMEM;
+			goto err_comp;
+		}
+		mdp->comp[comp_id] = comp;
+
+		ret = mtk_mdp_comp_init(dev, node, comp, comp_id);
+		if (ret)
+			goto err_comp;
+	}
+
+	mdp->job_wq = create_singlethread_workqueue(MTK_MDP_MODULE_NAME);
+	if (!mdp->job_wq) {
+		dev_err(&pdev->dev, "unable to alloc job workqueue\n");
+		ret = -ENOMEM;
+		goto err_alloc_job_wq;
+	}
+
+	mdp->wdt_wq = create_singlethread_workqueue("mdp_wdt_wq");
+	if (!mdp->wdt_wq) {
+		dev_err(&pdev->dev, "unable to alloc wdt workqueue\n");
+		ret = -ENOMEM;
+		goto err_alloc_wdt_wq;
+	}
+	INIT_WORK(&mdp->wdt_work, mtk_mdp_wdt_worker);
+
+	ret = v4l2_device_register(dev, &mdp->v4l2_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register v4l2 device\n");
+		ret = -EINVAL;
+		goto err_dev_register;
+	}
+
+	ret = mtk_mdp_register_m2m_device(mdp);
+	if (ret) {
+		v4l2_err(&mdp->v4l2_dev, "Failed to init mem2mem device\n");
+		goto err_m2m_register;
+	}
+
+	mdp->vpu_dev = vpu_get_plat_device(pdev);
+	vpu_wdt_reg_handler(mdp->vpu_dev, mtk_mdp_reset_handler, mdp,
+			    VPU_RST_MDP);
+
+	platform_set_drvdata(pdev, mdp);
+
+	vb2_dma_contig_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
+
+	pm_runtime_enable(dev);
+	dev_dbg(dev, "mdp-%d registered successfully\n", mdp->id);
+
+	return 0;
+
+err_m2m_register:
+	v4l2_device_unregister(&mdp->v4l2_dev);
+
+err_dev_register:
+	destroy_workqueue(mdp->wdt_wq);
+
+err_alloc_wdt_wq:
+	destroy_workqueue(mdp->job_wq);
+
+err_alloc_job_wq:
+
+err_comp:
+	for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+		mtk_mdp_comp_deinit(dev, mdp->comp[i]);
+
+	dev_dbg(dev, "err %d\n", ret);
+	return ret;
+}
+
+static int mtk_mdp_remove(struct platform_device *pdev)
+{
+	struct mtk_mdp_dev *mdp = platform_get_drvdata(pdev);
+	int i;
+
+	pm_runtime_disable(&pdev->dev);
+	vb2_dma_contig_clear_max_seg_size(&pdev->dev);
+	mtk_mdp_unregister_m2m_device(mdp);
+	v4l2_device_unregister(&mdp->v4l2_dev);
+
+	flush_workqueue(mdp->job_wq);
+	destroy_workqueue(mdp->job_wq);
+
+	for (i = 0; i < ARRAY_SIZE(mdp->comp); i++)
+		mtk_mdp_comp_deinit(&pdev->dev, mdp->comp[i]);
+
+	dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
+	return 0;
+}
+
+static int __maybe_unused mtk_mdp_pm_suspend(struct device *dev)
+{
+	struct mtk_mdp_dev *mdp = dev_get_drvdata(dev);
+
+	mtk_mdp_clock_off(mdp);
+
+	return 0;
+}
+
+static int __maybe_unused mtk_mdp_pm_resume(struct device *dev)
+{
+	struct mtk_mdp_dev *mdp = dev_get_drvdata(dev);
+
+	mtk_mdp_clock_on(mdp);
+
+	return 0;
+}
+
+static int __maybe_unused mtk_mdp_suspend(struct device *dev)
+{
+	if (pm_runtime_suspended(dev))
+		return 0;
+
+	return mtk_mdp_pm_suspend(dev);
+}
+
+static int __maybe_unused mtk_mdp_resume(struct device *dev)
+{
+	if (pm_runtime_suspended(dev))
+		return 0;
+
+	return mtk_mdp_pm_resume(dev);
+}
+
+static const struct dev_pm_ops mtk_mdp_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mtk_mdp_suspend, mtk_mdp_resume)
+	SET_RUNTIME_PM_OPS(mtk_mdp_pm_suspend, mtk_mdp_pm_resume, NULL)
+};
+
+static struct platform_driver mtk_mdp_driver = {
+	.probe		= mtk_mdp_probe,
+	.remove		= mtk_mdp_remove,
+	.driver = {
+		.name	= MTK_MDP_MODULE_NAME,
+		.pm	= &mtk_mdp_pm_ops,
+		.of_match_table = mtk_mdp_of_ids,
+	}
+};
+
+module_platform_driver(mtk_mdp_driver);
+
+MODULE_AUTHOR("Houlong Wei <houlong.wei@mediatek.com>");
+MODULE_DESCRIPTION("Mediatek image processor driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_core.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_CORE_H__
+#define __MTK_MDP_CORE_H__
+
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_mdp_vpu.h"
+#include "mtk_mdp_comp.h"
+
+
+#define MTK_MDP_MODULE_NAME		"mtk-mdp"
+
+#define MTK_MDP_SHUTDOWN_TIMEOUT	((100*HZ)/1000) /* 100ms */
+#define MTK_MDP_MAX_CTRL_NUM		10
+
+#define MTK_MDP_FMT_FLAG_OUTPUT		BIT(0)
+#define MTK_MDP_FMT_FLAG_CAPTURE	BIT(1)
+
+#define MTK_MDP_VPU_INIT		BIT(0)
+#define MTK_MDP_SRC_FMT			BIT(1)
+#define MTK_MDP_DST_FMT			BIT(2)
+#define MTK_MDP_CTX_ERROR		BIT(5)
+
+/**
+ *  struct mtk_mdp_pix_align - alignement of image
+ *  @org_w: source alignment of width
+ *  @org_h: source alignment of height
+ *  @target_w: dst alignment of width
+ *  @target_h: dst alignment of height
+ */
+struct mtk_mdp_pix_align {
+	u16 org_w;
+	u16 org_h;
+	u16 target_w;
+	u16 target_h;
+};
+
+/**
+ * struct mtk_mdp_fmt - the driver's internal color format data
+ * @pixelformat: the fourcc code for this format, 0 if not applicable
+ * @num_planes: number of physically non-contiguous data planes
+ * @num_comp: number of logical data planes
+ * @depth: per plane driver's private 'number of bits per pixel'
+ * @row_depth: per plane driver's private 'number of bits per pixel per row'
+ * @flags: flags indicating which operation mode format applies to
+	   MTK_MDP_FMT_FLAG_OUTPUT is used in OUTPUT stream
+	   MTK_MDP_FMT_FLAG_CAPTURE is used in CAPTURE stream
+ * @align: pointer to a pixel alignment struct, NULL if using default value
+ */
+struct mtk_mdp_fmt {
+	u32	pixelformat;
+	u16	num_planes;
+	u16	num_comp;
+	u8	depth[VIDEO_MAX_PLANES];
+	u8	row_depth[VIDEO_MAX_PLANES];
+	u32	flags;
+	struct mtk_mdp_pix_align *align;
+};
+
+/**
+ * struct mtk_mdp_addr - the image processor physical address set
+ * @addr:	address of planes
+ */
+struct mtk_mdp_addr {
+	dma_addr_t addr[MTK_MDP_MAX_NUM_PLANE];
+};
+
+/* struct mtk_mdp_ctrls - the image processor control set
+ * @rotate: rotation degree
+ * @hflip: horizontal flip
+ * @vflip: vertical flip
+ * @global_alpha: the alpha value of current frame
+ */
+struct mtk_mdp_ctrls {
+	struct v4l2_ctrl *rotate;
+	struct v4l2_ctrl *hflip;
+	struct v4l2_ctrl *vflip;
+	struct v4l2_ctrl *global_alpha;
+};
+
+/**
+ * struct mtk_mdp_frame - source/target frame properties
+ * @width:	SRC : SRCIMG_WIDTH, DST : OUTPUTDMA_WHOLE_IMG_WIDTH
+ * @height:	SRC : SRCIMG_HEIGHT, DST : OUTPUTDMA_WHOLE_IMG_HEIGHT
+ * @crop:	cropped(source)/scaled(destination) size
+ * @payload:	image size in bytes (w x h x bpp)
+ * @pitch:	bytes per line of image in memory
+ * @addr:	image frame buffer physical addresses
+ * @fmt:	color format pointer
+ * @alpha:	frame's alpha value
+ */
+struct mtk_mdp_frame {
+	u32				width;
+	u32				height;
+	struct v4l2_rect		crop;
+	unsigned long			payload[VIDEO_MAX_PLANES];
+	unsigned int			pitch[VIDEO_MAX_PLANES];
+	struct mtk_mdp_addr		addr;
+	const struct mtk_mdp_fmt	*fmt;
+	u8				alpha;
+};
+
+/**
+ * struct mtk_mdp_variant - image processor variant information
+ * @pix_max:		maximum limit of image size
+ * @pix_min:		minimun limit of image size
+ * @pix_align:		alignement of image
+ * @h_scale_up_max:	maximum scale-up in horizontal
+ * @v_scale_up_max:	maximum scale-up in vertical
+ * @h_scale_down_max:	maximum scale-down in horizontal
+ * @v_scale_down_max:	maximum scale-down in vertical
+ */
+struct mtk_mdp_variant {
+	struct mtk_mdp_pix_limit	*pix_max;
+	struct mtk_mdp_pix_limit	*pix_min;
+	struct mtk_mdp_pix_align	*pix_align;
+	u16				h_scale_up_max;
+	u16				v_scale_up_max;
+	u16				h_scale_down_max;
+	u16				v_scale_down_max;
+};
+
+/**
+ * struct mtk_mdp_dev - abstraction for image processor entity
+ * @lock:	the mutex protecting this data structure
+ * @vpulock:	the mutex protecting the communication with VPU
+ * @pdev:	pointer to the image processor platform device
+ * @variant:	the IP variant information
+ * @id:		image processor device index (0..MTK_MDP_MAX_DEVS)
+ * @comp:	MDP function components
+ * @m2m_dev:	v4l2 memory-to-memory device data
+ * @ctx_list:	list of struct mtk_mdp_ctx
+ * @vdev:	video device for image processor driver
+ * @v4l2_dev:	V4L2 device to register video devices for.
+ * @job_wq:	processor work queue
+ * @vpu_dev:	VPU platform device
+ * @ctx_num:	counter of active MTK MDP context
+ * @id_counter:	An integer id given to the next opened context
+ * @wdt_wq:	work queue for VPU watchdog
+ * @wdt_work:	worker for VPU watchdog
+ */
+struct mtk_mdp_dev {
+	struct mutex			lock;
+	struct mutex			vpulock;
+	struct platform_device		*pdev;
+	struct mtk_mdp_variant		*variant;
+	u16				id;
+	struct mtk_mdp_comp		*comp[MTK_MDP_COMP_ID_MAX];
+	struct v4l2_m2m_dev		*m2m_dev;
+	struct list_head		ctx_list;
+	struct video_device		*vdev;
+	struct v4l2_device		v4l2_dev;
+	struct workqueue_struct		*job_wq;
+	struct platform_device		*vpu_dev;
+	int				ctx_num;
+	unsigned long			id_counter;
+	struct workqueue_struct		*wdt_wq;
+	struct work_struct		wdt_work;
+};
+
+/**
+ * mtk_mdp_ctx - the device context data
+ * @list:		link to ctx_list of mtk_mdp_dev
+ * @s_frame:		source frame properties
+ * @d_frame:		destination frame properties
+ * @id:			index of the context that this structure describes
+ * @flags:		additional flags for image conversion
+ * @state:		flags to keep track of user configuration
+			Protected by slock
+ * @rotation:		rotates the image by specified angle
+ * @hflip:		mirror the picture horizontally
+ * @vflip:		mirror the picture vertically
+ * @mdp_dev:		the image processor device this context applies to
+ * @m2m_ctx:		memory-to-memory device context
+ * @fh:			v4l2 file handle
+ * @ctrl_handler:	v4l2 controls handler
+ * @ctrls		image processor control set
+ * @ctrls_rdy:		true if the control handler is initialized
+ * @colorspace:		enum v4l2_colorspace; supplemental to pixelformat
+ * @ycbcr_enc:		enum v4l2_ycbcr_encoding, Y'CbCr encoding
+ * @xfer_func:		enum v4l2_xfer_func, colorspace transfer function
+ * @quant:		enum v4l2_quantization, colorspace quantization
+ * @vpu:		VPU instance
+ * @slock:		the mutex protecting mtp_mdp_ctx.state
+ * @work:		worker for image processing
+ */
+struct mtk_mdp_ctx {
+	struct list_head		list;
+	struct mtk_mdp_frame		s_frame;
+	struct mtk_mdp_frame		d_frame;
+	u32				flags;
+	u32				state;
+	int				id;
+	int				rotation;
+	u32				hflip:1;
+	u32				vflip:1;
+	struct mtk_mdp_dev		*mdp_dev;
+	struct v4l2_m2m_ctx		*m2m_ctx;
+	struct v4l2_fh			fh;
+	struct v4l2_ctrl_handler	ctrl_handler;
+	struct mtk_mdp_ctrls		ctrls;
+	bool				ctrls_rdy;
+	enum v4l2_colorspace		colorspace;
+	enum v4l2_ycbcr_encoding	ycbcr_enc;
+	enum v4l2_xfer_func		xfer_func;
+	enum v4l2_quantization		quant;
+
+	struct mtk_mdp_vpu		vpu;
+	struct mutex			slock;
+	struct work_struct		work;
+};
+
+extern int mtk_mdp_dbg_level;
+
+#if defined(DEBUG)
+
+#define mtk_mdp_dbg(level, fmt, args...)				 \
+	do {								 \
+		if (mtk_mdp_dbg_level >= level)				 \
+			pr_info("[MTK_MDP] level=%d %s(),%d: " fmt "\n", \
+				level, __func__, __LINE__, ##args);	 \
+	} while (0)
+
+#define mtk_mdp_err(fmt, args...)					\
+	pr_err("[MTK_MDP][ERROR] %s:%d: " fmt "\n", __func__, __LINE__, \
+	       ##args)
+
+
+#define mtk_mdp_dbg_enter()  mtk_mdp_dbg(3, "+")
+#define mtk_mdp_dbg_leave()  mtk_mdp_dbg(3, "-")
+
+#else
+
+#define mtk_mdp_dbg(level, fmt, args...) {}
+#define mtk_mdp_err(fmt, args...)
+#define mtk_mdp_dbg_enter()
+#define mtk_mdp_dbg_leave()
+
+#endif
+
+#endif /* __MTK_MDP_CORE_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_IPI_H__
+#define __MTK_MDP_IPI_H__
+
+#define MTK_MDP_MAX_NUM_PLANE		3
+
+enum mdp_ipi_msgid {
+	AP_MDP_INIT		= 0xd000,
+	AP_MDP_DEINIT		= 0xd001,
+	AP_MDP_PROCESS		= 0xd002,
+
+	VPU_MDP_INIT_ACK	= 0xe000,
+	VPU_MDP_DEINIT_ACK	= 0xe001,
+	VPU_MDP_PROCESS_ACK	= 0xe002
+};
+
+#pragma pack(push, 4)
+
+/**
+ * struct mdp_ipi_init - for AP_MDP_INIT
+ * @msg_id   : AP_MDP_INIT
+ * @ipi_id   : IPI_MDP
+ * @ap_inst  : AP mtk_mdp_vpu address
+ */
+struct mdp_ipi_init {
+	uint32_t msg_id;
+	uint32_t ipi_id;
+	uint64_t ap_inst;
+};
+
+/**
+ * struct mdp_ipi_comm - for AP_MDP_PROCESS, AP_MDP_DEINIT
+ * @msg_id        : AP_MDP_PROCESS, AP_MDP_DEINIT
+ * @ipi_id        : IPI_MDP
+ * @ap_inst       : AP mtk_mdp_vpu address
+ * @vpu_inst_addr : VPU MDP instance address
+ */
+struct mdp_ipi_comm {
+	uint32_t msg_id;
+	uint32_t ipi_id;
+	uint64_t ap_inst;
+	uint32_t vpu_inst_addr;
+};
+
+/**
+ * struct mdp_ipi_comm_ack - for VPU_MDP_DEINIT_ACK, VPU_MDP_PROCESS_ACK
+ * @msg_id        : VPU_MDP_DEINIT_ACK, VPU_MDP_PROCESS_ACK
+ * @ipi_id        : IPI_MDP
+ * @ap_inst       : AP mtk_mdp_vpu address
+ * @vpu_inst_addr : VPU MDP instance address
+ * @status        : VPU exeuction result
+ */
+struct mdp_ipi_comm_ack {
+	uint32_t msg_id;
+	uint32_t ipi_id;
+	uint64_t ap_inst;
+	uint32_t vpu_inst_addr;
+	int32_t status;
+};
+
+/**
+ * struct mdp_config - configured for source/destination image
+ * @x        : left
+ * @y        : top
+ * @w        : width
+ * @h        : height
+ * @w_stride : bytes in horizontal
+ * @h_stride : bytes in vertical
+ * @crop_x   : cropped left
+ * @crop_y   : cropped top
+ * @crop_w   : cropped width
+ * @crop_h   : cropped height
+ * @format   : color format
+ */
+struct mdp_config {
+	int32_t x;
+	int32_t y;
+	int32_t w;
+	int32_t h;
+	int32_t w_stride;
+	int32_t h_stride;
+	int32_t crop_x;
+	int32_t crop_y;
+	int32_t crop_w;
+	int32_t crop_h;
+	int32_t format;
+};
+
+struct mdp_buffer {
+	uint64_t addr_mva[MTK_MDP_MAX_NUM_PLANE];
+	int32_t plane_size[MTK_MDP_MAX_NUM_PLANE];
+	int32_t plane_num;
+};
+
+struct mdp_config_misc {
+	int32_t orientation; /* 0, 90, 180, 270 */
+	int32_t hflip; /* 1 will enable the flip */
+	int32_t vflip; /* 1 will enable the flip */
+	int32_t alpha; /* global alpha */
+};
+
+struct mdp_process_vsi {
+	struct mdp_config src_config;
+	struct mdp_buffer src_buffer;
+	struct mdp_config dst_config;
+	struct mdp_buffer dst_buffer;
+	struct mdp_config_misc misc;
+};
+
+#pragma pack(pop)
+
+#endif /* __MTK_MDP_IPI_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1286 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.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/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+
+#include "mtk_mdp_core.h"
+#include "mtk_mdp_m2m.h"
+#include "mtk_mdp_regs.h"
+#include "mtk_vpu.h"
+
+
+/**
+ *  struct mtk_mdp_pix_limit - image pixel size limits
+ *  @org_w: source pixel width
+ *  @org_h: source pixel height
+ *  @target_rot_dis_w: pixel dst scaled width with the rotator is off
+ *  @target_rot_dis_h: pixel dst scaled height with the rotator is off
+ *  @target_rot_en_w: pixel dst scaled width with the rotator is on
+ *  @target_rot_en_h: pixel dst scaled height with the rotator is on
+ */
+struct mtk_mdp_pix_limit {
+	u16 org_w;
+	u16 org_h;
+	u16 target_rot_dis_w;
+	u16 target_rot_dis_h;
+	u16 target_rot_en_w;
+	u16 target_rot_en_h;
+};
+
+static struct mtk_mdp_pix_align mtk_mdp_size_align = {
+	.org_w			= 16,
+	.org_h			= 16,
+	.target_w		= 2,
+	.target_h		= 2,
+};
+
+static const struct mtk_mdp_fmt mtk_mdp_formats[] = {
+	{
+		.pixelformat	= V4L2_PIX_FMT_MT21C,
+		.depth		= { 8, 4 },
+		.row_depth	= { 8, 8 },
+		.num_planes	= 2,
+		.num_comp	= 2,
+		.align		= &mtk_mdp_size_align,
+		.flags		= MTK_MDP_FMT_FLAG_OUTPUT,
+	}, {
+		.pixelformat	= V4L2_PIX_FMT_NV12M,
+		.depth		= { 8, 4 },
+		.row_depth	= { 8, 8 },
+		.num_planes	= 2,
+		.num_comp	= 2,
+		.flags		= MTK_MDP_FMT_FLAG_OUTPUT |
+				  MTK_MDP_FMT_FLAG_CAPTURE,
+	}, {
+		.pixelformat	= V4L2_PIX_FMT_YUV420M,
+		.depth		= { 8, 2, 2 },
+		.row_depth	= { 8, 4, 4 },
+		.num_planes	= 3,
+		.num_comp	= 3,
+		.flags		= MTK_MDP_FMT_FLAG_OUTPUT |
+				  MTK_MDP_FMT_FLAG_CAPTURE,
+	}, {
+		.pixelformat	= V4L2_PIX_FMT_YVU420,
+		.depth		= { 12 },
+		.row_depth	= { 8 },
+		.num_planes	= 1,
+		.num_comp	= 3,
+		.flags		= MTK_MDP_FMT_FLAG_OUTPUT |
+				  MTK_MDP_FMT_FLAG_CAPTURE,
+	}
+};
+
+static struct mtk_mdp_pix_limit mtk_mdp_size_max = {
+	.target_rot_dis_w	= 4096,
+	.target_rot_dis_h	= 4096,
+	.target_rot_en_w	= 4096,
+	.target_rot_en_h	= 4096,
+};
+
+static struct mtk_mdp_pix_limit mtk_mdp_size_min = {
+	.org_w			= 16,
+	.org_h			= 16,
+	.target_rot_dis_w	= 16,
+	.target_rot_dis_h	= 16,
+	.target_rot_en_w	= 16,
+	.target_rot_en_h	= 16,
+};
+
+/* align size for normal raster scan pixel format */
+static struct mtk_mdp_pix_align mtk_mdp_rs_align = {
+	.org_w			= 2,
+	.org_h			= 2,
+	.target_w		= 2,
+	.target_h		= 2,
+};
+
+static struct mtk_mdp_variant mtk_mdp_default_variant = {
+	.pix_max		= &mtk_mdp_size_max,
+	.pix_min		= &mtk_mdp_size_min,
+	.pix_align		= &mtk_mdp_rs_align,
+	.h_scale_up_max		= 32,
+	.v_scale_up_max		= 32,
+	.h_scale_down_max	= 32,
+	.v_scale_down_max	= 128,
+};
+
+static const struct mtk_mdp_fmt *mtk_mdp_find_fmt(u32 pixelformat, u32 type)
+{
+	u32 i, flag;
+
+	flag = V4L2_TYPE_IS_OUTPUT(type) ? MTK_MDP_FMT_FLAG_OUTPUT :
+					   MTK_MDP_FMT_FLAG_CAPTURE;
+
+	for (i = 0; i < ARRAY_SIZE(mtk_mdp_formats); ++i) {
+		if (!(mtk_mdp_formats[i].flags & flag))
+			continue;
+		if (mtk_mdp_formats[i].pixelformat == pixelformat)
+			return &mtk_mdp_formats[i];
+	}
+	return NULL;
+}
+
+static const struct mtk_mdp_fmt *mtk_mdp_find_fmt_by_index(u32 index, u32 type)
+{
+	u32 i, flag, num = 0;
+
+	flag = V4L2_TYPE_IS_OUTPUT(type) ? MTK_MDP_FMT_FLAG_OUTPUT :
+					   MTK_MDP_FMT_FLAG_CAPTURE;
+
+	for (i = 0; i < ARRAY_SIZE(mtk_mdp_formats); ++i) {
+		if (!(mtk_mdp_formats[i].flags & flag))
+			continue;
+		if (index == num)
+			return &mtk_mdp_formats[i];
+		num++;
+	}
+	return NULL;
+}
+
+static void mtk_mdp_bound_align_image(u32 *w, unsigned int wmin,
+				      unsigned int wmax, unsigned int align_w,
+				      u32 *h, unsigned int hmin,
+				      unsigned int hmax, unsigned int align_h)
+{
+	int org_w, org_h, step_w, step_h;
+	int walign, halign;
+
+	org_w = *w;
+	org_h = *h;
+	walign = ffs(align_w) - 1;
+	halign = ffs(align_h) - 1;
+	v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0);
+
+	step_w = 1 << walign;
+	step_h = 1 << halign;
+	if (*w < org_w && (*w + step_w) <= wmax)
+		*w += step_w;
+	if (*h < org_h && (*h + step_h) <= hmax)
+		*h += step_h;
+}
+
+static const struct mtk_mdp_fmt *mtk_mdp_try_fmt_mplane(struct mtk_mdp_ctx *ctx,
+							struct v4l2_format *f)
+{
+	struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+	struct mtk_mdp_variant *variant = mdp->variant;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	const struct mtk_mdp_fmt *fmt;
+	u32 max_w, max_h, align_w, align_h;
+	u32 min_w, min_h, org_w, org_h;
+	int i;
+
+	fmt = mtk_mdp_find_fmt(pix_mp->pixelformat, f->type);
+	if (!fmt)
+		fmt = mtk_mdp_find_fmt_by_index(0, f->type);
+	if (!fmt) {
+		dev_dbg(&ctx->mdp_dev->pdev->dev,
+			"pixelformat format 0x%X invalid\n",
+			pix_mp->pixelformat);
+		return NULL;
+	}
+
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->pixelformat = fmt->pixelformat;
+	if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
+		pix_mp->colorspace = ctx->colorspace;
+		pix_mp->xfer_func = ctx->xfer_func;
+		pix_mp->ycbcr_enc = ctx->ycbcr_enc;
+		pix_mp->quantization = ctx->quant;
+	}
+	memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
+
+	max_w = variant->pix_max->target_rot_dis_w;
+	max_h = variant->pix_max->target_rot_dis_h;
+
+	if (fmt->align == NULL) {
+		/* use default alignment */
+		align_w = variant->pix_align->org_w;
+		align_h = variant->pix_align->org_h;
+	} else {
+		align_w = fmt->align->org_w;
+		align_h = fmt->align->org_h;
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		min_w = variant->pix_min->org_w;
+		min_h = variant->pix_min->org_h;
+	} else {
+		min_w = variant->pix_min->target_rot_dis_w;
+		min_h = variant->pix_min->target_rot_dis_h;
+	}
+
+	mtk_mdp_dbg(2, "[%d] type:%d, wxh:%ux%u, align:%ux%u, max:%ux%u",
+		    ctx->id, f->type, pix_mp->width, pix_mp->height,
+		    align_w, align_h, max_w, max_h);
+	/*
+	 * To check if image size is modified to adjust parameter against
+	 * hardware abilities
+	 */
+	org_w = pix_mp->width;
+	org_h = pix_mp->height;
+
+	mtk_mdp_bound_align_image(&pix_mp->width, min_w, max_w, align_w,
+				  &pix_mp->height, min_h, max_h, align_h);
+
+	if (org_w != pix_mp->width || org_h != pix_mp->height)
+		mtk_mdp_dbg(1, "[%d] size change:%ux%u to %ux%u", ctx->id,
+			    org_w, org_h, pix_mp->width, pix_mp->height);
+	pix_mp->num_planes = fmt->num_planes;
+
+	for (i = 0; i < pix_mp->num_planes; ++i) {
+		int bpl = (pix_mp->width * fmt->row_depth[i]) / 8;
+		int sizeimage = (pix_mp->width * pix_mp->height *
+			fmt->depth[i]) / 8;
+
+		pix_mp->plane_fmt[i].bytesperline = bpl;
+		if (pix_mp->plane_fmt[i].sizeimage < sizeimage)
+			pix_mp->plane_fmt[i].sizeimage = sizeimage;
+		memset(pix_mp->plane_fmt[i].reserved, 0,
+		       sizeof(pix_mp->plane_fmt[i].reserved));
+		mtk_mdp_dbg(2, "[%d] p%d, bpl:%d, sizeimage:%u (%u)", ctx->id,
+			    i, bpl, pix_mp->plane_fmt[i].sizeimage, sizeimage);
+	}
+
+	return fmt;
+}
+
+static struct mtk_mdp_frame *mtk_mdp_ctx_get_frame(struct mtk_mdp_ctx *ctx,
+					    enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->s_frame;
+	return &ctx->d_frame;
+}
+
+static void mtk_mdp_check_crop_change(u32 new_w, u32 new_h, u32 *w, u32 *h)
+{
+	if (new_w != *w || new_h != *h) {
+		mtk_mdp_dbg(1, "size change:%dx%d to %dx%d",
+			    *w, *h, new_w, new_h);
+
+		*w = new_w;
+		*h = new_h;
+	}
+}
+
+static int mtk_mdp_try_crop(struct mtk_mdp_ctx *ctx, u32 type,
+			    struct v4l2_rect *r)
+{
+	struct mtk_mdp_frame *frame;
+	struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+	struct mtk_mdp_variant *variant = mdp->variant;
+	u32 align_w, align_h, new_w, new_h;
+	u32 min_w, min_h, max_w, max_h;
+
+	if (r->top < 0 || r->left < 0) {
+		dev_err(&ctx->mdp_dev->pdev->dev,
+			"doesn't support negative values for top & left\n");
+		return -EINVAL;
+	}
+
+	mtk_mdp_dbg(2, "[%d] type:%d, set wxh:%dx%d", ctx->id, type,
+		    r->width, r->height);
+
+	frame = mtk_mdp_ctx_get_frame(ctx, type);
+	max_w = frame->width;
+	max_h = frame->height;
+	new_w = r->width;
+	new_h = r->height;
+
+	if (V4L2_TYPE_IS_OUTPUT(type)) {
+		align_w = 1;
+		align_h = 1;
+		min_w = 64;
+		min_h = 32;
+	} else {
+		align_w = variant->pix_align->target_w;
+		align_h = variant->pix_align->target_h;
+		if (ctx->ctrls.rotate->val == 90 ||
+		    ctx->ctrls.rotate->val == 270) {
+			max_w = frame->height;
+			max_h = frame->width;
+			min_w = variant->pix_min->target_rot_en_w;
+			min_h = variant->pix_min->target_rot_en_h;
+			new_w = r->height;
+			new_h = r->width;
+		} else {
+			min_w = variant->pix_min->target_rot_dis_w;
+			min_h = variant->pix_min->target_rot_dis_h;
+		}
+	}
+
+	mtk_mdp_dbg(2, "[%d] align:%dx%d, min:%dx%d, new:%dx%d", ctx->id,
+		    align_w, align_h, min_w, min_h, new_w, new_h);
+
+	mtk_mdp_bound_align_image(&new_w, min_w, max_w, align_w,
+				  &new_h, min_h, max_h, align_h);
+
+	if (!V4L2_TYPE_IS_OUTPUT(type) &&
+		(ctx->ctrls.rotate->val == 90 ||
+		ctx->ctrls.rotate->val == 270))
+		mtk_mdp_check_crop_change(new_h, new_w,
+					  &r->width, &r->height);
+	else
+		mtk_mdp_check_crop_change(new_w, new_h,
+					  &r->width, &r->height);
+
+	/* adjust left/top if cropping rectangle is out of bounds */
+	/* Need to add code to algin left value with 2's multiple */
+	if (r->left + new_w > max_w)
+		r->left = max_w - new_w;
+	if (r->top + new_h > max_h)
+		r->top = max_h - new_h;
+
+	if (r->left & 1)
+		r->left -= 1;
+
+	mtk_mdp_dbg(2, "[%d] crop l,t,w,h:%d,%d,%d,%d, max:%dx%d", ctx->id,
+		    r->left, r->top, r->width,
+		    r->height, max_w, max_h);
+	return 0;
+}
+
+static inline struct mtk_mdp_ctx *fh_to_ctx(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct mtk_mdp_ctx, fh);
+}
+
+static inline struct mtk_mdp_ctx *ctrl_to_ctx(struct v4l2_ctrl *ctrl)
+{
+	return container_of(ctrl->handler, struct mtk_mdp_ctx, ctrl_handler);
+}
+
+void mtk_mdp_ctx_state_lock_set(struct mtk_mdp_ctx *ctx, u32 state)
+{
+	mutex_lock(&ctx->slock);
+	ctx->state |= state;
+	mutex_unlock(&ctx->slock);
+}
+
+static void mtk_mdp_ctx_state_lock_clear(struct mtk_mdp_ctx *ctx, u32 state)
+{
+	mutex_lock(&ctx->slock);
+	ctx->state &= ~state;
+	mutex_unlock(&ctx->slock);
+}
+
+static bool mtk_mdp_ctx_state_is_set(struct mtk_mdp_ctx *ctx, u32 mask)
+{
+	bool ret;
+
+	mutex_lock(&ctx->slock);
+	ret = (ctx->state & mask) == mask;
+	mutex_unlock(&ctx->slock);
+	return ret;
+}
+
+static void mtk_mdp_ctx_lock(struct vb2_queue *vq)
+{
+	struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vq);
+
+	mutex_lock(&ctx->mdp_dev->lock);
+}
+
+static void mtk_mdp_ctx_unlock(struct vb2_queue *vq)
+{
+	struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vq);
+
+	mutex_unlock(&ctx->mdp_dev->lock);
+}
+
+static void mtk_mdp_set_frame_size(struct mtk_mdp_frame *frame, int width,
+				   int height)
+{
+	frame->width = width;
+	frame->height = height;
+	frame->crop.width = width;
+	frame->crop.height = height;
+	frame->crop.left = 0;
+	frame->crop.top = 0;
+}
+
+static int mtk_mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct mtk_mdp_ctx *ctx = q->drv_priv;
+	int ret;
+
+	ret = pm_runtime_get_sync(&ctx->mdp_dev->pdev->dev);
+	if (ret < 0)
+		mtk_mdp_dbg(1, "[%d] pm_runtime_get_sync failed:%d",
+			    ctx->id, ret);
+
+	return 0;
+}
+
+static void *mtk_mdp_m2m_buf_remove(struct mtk_mdp_ctx *ctx,
+				    enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+	else
+		return v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+}
+
+static void mtk_mdp_m2m_stop_streaming(struct vb2_queue *q)
+{
+	struct mtk_mdp_ctx *ctx = q->drv_priv;
+	struct vb2_buffer *vb;
+
+	vb = mtk_mdp_m2m_buf_remove(ctx, q->type);
+	while (vb != NULL) {
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(vb), VB2_BUF_STATE_ERROR);
+		vb = mtk_mdp_m2m_buf_remove(ctx, q->type);
+	}
+
+	pm_runtime_put(&ctx->mdp_dev->pdev->dev);
+}
+
+static void mtk_mdp_m2m_job_abort(void *priv)
+{
+}
+
+/* The color format (num_planes) must be already configured. */
+static void mtk_mdp_prepare_addr(struct mtk_mdp_ctx *ctx,
+				 struct vb2_buffer *vb,
+				 struct mtk_mdp_frame *frame,
+				 struct mtk_mdp_addr *addr)
+{
+	u32 pix_size, planes, i;
+
+	pix_size = frame->width * frame->height;
+	planes = min_t(u32, frame->fmt->num_planes, ARRAY_SIZE(addr->addr));
+	for (i = 0; i < planes; i++)
+		addr->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
+
+	if (planes == 1) {
+		if (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) {
+			addr->addr[1] = (dma_addr_t)(addr->addr[0] + pix_size);
+			addr->addr[2] = (dma_addr_t)(addr->addr[1] +
+					(pix_size >> 2));
+		} else {
+			dev_err(&ctx->mdp_dev->pdev->dev,
+				"Invalid pixelformat:0x%x\n",
+				frame->fmt->pixelformat);
+		}
+	}
+	mtk_mdp_dbg(3, "[%d] planes:%d, size:%d, addr:%p,%p,%p",
+		    ctx->id, planes, pix_size, (void *)addr->addr[0],
+		    (void *)addr->addr[1], (void *)addr->addr[2]);
+}
+
+static void mtk_mdp_m2m_get_bufs(struct mtk_mdp_ctx *ctx)
+{
+	struct mtk_mdp_frame *s_frame, *d_frame;
+	struct vb2_buffer *src_vb, *dst_vb;
+	struct vb2_v4l2_buffer *src_vbuf, *dst_vbuf;
+
+	s_frame = &ctx->s_frame;
+	d_frame = &ctx->d_frame;
+
+	src_vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	mtk_mdp_prepare_addr(ctx, src_vb, s_frame, &s_frame->addr);
+
+	dst_vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	mtk_mdp_prepare_addr(ctx, dst_vb, d_frame, &d_frame->addr);
+
+	src_vbuf = to_vb2_v4l2_buffer(src_vb);
+	dst_vbuf = to_vb2_v4l2_buffer(dst_vb);
+	dst_vbuf->vb2_buf.timestamp = src_vbuf->vb2_buf.timestamp;
+}
+
+static void mtk_mdp_process_done(void *priv, int vb_state)
+{
+	struct mtk_mdp_dev *mdp = priv;
+	struct mtk_mdp_ctx *ctx;
+	struct vb2_buffer *src_vb, *dst_vb;
+	struct vb2_v4l2_buffer *src_vbuf = NULL, *dst_vbuf = NULL;
+
+	ctx = v4l2_m2m_get_curr_priv(mdp->m2m_dev);
+	if (!ctx)
+		return;
+
+	src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+	src_vbuf = to_vb2_v4l2_buffer(src_vb);
+	dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+	dst_vbuf = to_vb2_v4l2_buffer(dst_vb);
+
+	dst_vbuf->vb2_buf.timestamp = src_vbuf->vb2_buf.timestamp;
+	dst_vbuf->timecode = src_vbuf->timecode;
+	dst_vbuf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	dst_vbuf->flags |= src_vbuf->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+
+	v4l2_m2m_buf_done(src_vbuf, vb_state);
+	v4l2_m2m_buf_done(dst_vbuf, vb_state);
+	v4l2_m2m_job_finish(ctx->mdp_dev->m2m_dev, ctx->m2m_ctx);
+}
+
+static void mtk_mdp_m2m_worker(struct work_struct *work)
+{
+	struct mtk_mdp_ctx *ctx =
+				container_of(work, struct mtk_mdp_ctx, work);
+	struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+	enum vb2_buffer_state buf_state = VB2_BUF_STATE_ERROR;
+	int ret;
+
+	if (mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_CTX_ERROR)) {
+		dev_err(&mdp->pdev->dev, "ctx is in error state");
+		goto worker_end;
+	}
+
+	mtk_mdp_m2m_get_bufs(ctx);
+
+	mtk_mdp_hw_set_input_addr(ctx, &ctx->s_frame.addr);
+	mtk_mdp_hw_set_output_addr(ctx, &ctx->d_frame.addr);
+
+	mtk_mdp_hw_set_in_size(ctx);
+	mtk_mdp_hw_set_in_image_format(ctx);
+
+	mtk_mdp_hw_set_out_size(ctx);
+	mtk_mdp_hw_set_out_image_format(ctx);
+
+	mtk_mdp_hw_set_rotation(ctx);
+	mtk_mdp_hw_set_global_alpha(ctx);
+
+	ret = mtk_mdp_vpu_process(&ctx->vpu);
+	if (ret) {
+		dev_err(&mdp->pdev->dev, "processing failed: %d", ret);
+		goto worker_end;
+	}
+
+	buf_state = VB2_BUF_STATE_DONE;
+
+worker_end:
+	mtk_mdp_process_done(mdp, buf_state);
+}
+
+static void mtk_mdp_m2m_device_run(void *priv)
+{
+	struct mtk_mdp_ctx *ctx = priv;
+
+	queue_work(ctx->mdp_dev->job_wq, &ctx->work);
+}
+
+static int mtk_mdp_m2m_queue_setup(struct vb2_queue *vq,
+			unsigned int *num_buffers, unsigned int *num_planes,
+			unsigned int sizes[], struct device *alloc_devs[])
+{
+	struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vq);
+	struct mtk_mdp_frame *frame;
+	int i;
+
+	frame = mtk_mdp_ctx_get_frame(ctx, vq->type);
+	*num_planes = frame->fmt->num_planes;
+	for (i = 0; i < frame->fmt->num_planes; i++)
+		sizes[i] = frame->payload[i];
+	mtk_mdp_dbg(2, "[%d] type:%d, planes:%d, buffers:%d, size:%u,%u",
+		    ctx->id, vq->type, *num_planes, *num_buffers,
+		    sizes[0], sizes[1]);
+	return 0;
+}
+
+static int mtk_mdp_m2m_buf_prepare(struct vb2_buffer *vb)
+{
+	struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_mdp_frame *frame;
+	int i;
+
+	frame = mtk_mdp_ctx_get_frame(ctx, vb->vb2_queue->type);
+
+	if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+		for (i = 0; i < frame->fmt->num_planes; i++)
+			vb2_set_plane_payload(vb, i, frame->payload[i]);
+	}
+
+	return 0;
+}
+
+static void mtk_mdp_m2m_buf_queue(struct vb2_buffer *vb)
+{
+	struct mtk_mdp_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	v4l2_m2m_buf_queue(ctx->m2m_ctx, to_vb2_v4l2_buffer(vb));
+}
+
+static struct vb2_ops mtk_mdp_m2m_qops = {
+	.queue_setup	 = mtk_mdp_m2m_queue_setup,
+	.buf_prepare	 = mtk_mdp_m2m_buf_prepare,
+	.buf_queue	 = mtk_mdp_m2m_buf_queue,
+	.wait_prepare	 = mtk_mdp_ctx_unlock,
+	.wait_finish	 = mtk_mdp_ctx_lock,
+	.stop_streaming	 = mtk_mdp_m2m_stop_streaming,
+	.start_streaming = mtk_mdp_m2m_start_streaming,
+};
+
+static int mtk_mdp_m2m_querycap(struct file *file, void *fh,
+				struct v4l2_capability *cap)
+{
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+	struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+
+	strlcpy(cap->driver, MTK_MDP_MODULE_NAME, sizeof(cap->driver));
+	strlcpy(cap->card, mdp->pdev->name, sizeof(cap->card));
+	strlcpy(cap->bus_info, "platform:mt8173", sizeof(cap->bus_info));
+
+	return 0;
+}
+
+static int mtk_mdp_enum_fmt_mplane(struct v4l2_fmtdesc *f, u32 type)
+{
+	const struct mtk_mdp_fmt *fmt;
+
+	fmt = mtk_mdp_find_fmt_by_index(f->index, type);
+	if (!fmt)
+		return -EINVAL;
+
+	f->pixelformat = fmt->pixelformat;
+
+	return 0;
+}
+
+static int mtk_mdp_m2m_enum_fmt_mplane_vid_cap(struct file *file, void *priv,
+				       struct v4l2_fmtdesc *f)
+{
+	return mtk_mdp_enum_fmt_mplane(f, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+}
+
+static int mtk_mdp_m2m_enum_fmt_mplane_vid_out(struct file *file, void *priv,
+				       struct v4l2_fmtdesc *f)
+{
+	return mtk_mdp_enum_fmt_mplane(f, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+}
+
+static int mtk_mdp_m2m_g_fmt_mplane(struct file *file, void *fh,
+				    struct v4l2_format *f)
+{
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+	struct mtk_mdp_frame *frame;
+	struct v4l2_pix_format_mplane *pix_mp;
+	int i;
+
+	mtk_mdp_dbg(2, "[%d] type:%d", ctx->id, f->type);
+
+	frame = mtk_mdp_ctx_get_frame(ctx, f->type);
+	pix_mp = &f->fmt.pix_mp;
+
+	pix_mp->width = frame->width;
+	pix_mp->height = frame->height;
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->pixelformat = frame->fmt->pixelformat;
+	pix_mp->num_planes = frame->fmt->num_planes;
+	pix_mp->colorspace = ctx->colorspace;
+	pix_mp->xfer_func = ctx->xfer_func;
+	pix_mp->ycbcr_enc = ctx->ycbcr_enc;
+	pix_mp->quantization = ctx->quant;
+	mtk_mdp_dbg(2, "[%d] wxh:%dx%d", ctx->id,
+		    pix_mp->width, pix_mp->height);
+
+	for (i = 0; i < pix_mp->num_planes; ++i) {
+		pix_mp->plane_fmt[i].bytesperline = (frame->width *
+			frame->fmt->row_depth[i]) / 8;
+		pix_mp->plane_fmt[i].sizeimage = (frame->width *
+			frame->height * frame->fmt->depth[i]) / 8;
+
+		mtk_mdp_dbg(2, "[%d] p%d, bpl:%d, sizeimage:%d", ctx->id, i,
+			    pix_mp->plane_fmt[i].bytesperline,
+			    pix_mp->plane_fmt[i].sizeimage);
+	}
+
+	return 0;
+}
+
+static int mtk_mdp_m2m_try_fmt_mplane(struct file *file, void *fh,
+				      struct v4l2_format *f)
+{
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+
+	if (!mtk_mdp_try_fmt_mplane(ctx, f))
+		return -EINVAL;
+	return 0;
+}
+
+static int mtk_mdp_m2m_s_fmt_mplane(struct file *file, void *fh,
+				    struct v4l2_format *f)
+{
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+	struct vb2_queue *vq;
+	struct mtk_mdp_frame *frame;
+	struct v4l2_pix_format_mplane *pix_mp;
+	const struct mtk_mdp_fmt *fmt;
+	int i;
+
+	mtk_mdp_dbg(2, "[%d] type:%d", ctx->id, f->type);
+
+	frame = mtk_mdp_ctx_get_frame(ctx, f->type);
+	fmt = mtk_mdp_try_fmt_mplane(ctx, f);
+	if (!fmt) {
+		mtk_mdp_err("[%d] try_fmt failed, type:%d", ctx->id, f->type);
+		return -EINVAL;
+	}
+	frame->fmt = fmt;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (vb2_is_streaming(vq)) {
+		dev_info(&ctx->mdp_dev->pdev->dev, "queue %d busy", f->type);
+		return -EBUSY;
+	}
+
+	pix_mp = &f->fmt.pix_mp;
+	for (i = 0; i < frame->fmt->num_planes; i++) {
+		frame->payload[i] = pix_mp->plane_fmt[i].sizeimage;
+		frame->pitch[i] = pix_mp->plane_fmt[i].bytesperline;
+	}
+
+	mtk_mdp_set_frame_size(frame, pix_mp->width, pix_mp->height);
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		ctx->colorspace = pix_mp->colorspace;
+		ctx->xfer_func = pix_mp->xfer_func;
+		ctx->ycbcr_enc = pix_mp->ycbcr_enc;
+		ctx->quant = pix_mp->quantization;
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type))
+		mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_SRC_FMT);
+	else
+		mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_DST_FMT);
+
+	mtk_mdp_dbg(2, "[%d] type:%d, frame:%dx%d", ctx->id, f->type,
+		    frame->width, frame->height);
+
+	return 0;
+}
+
+static int mtk_mdp_m2m_reqbufs(struct file *file, void *fh,
+			       struct v4l2_requestbuffers *reqbufs)
+{
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+
+	if (reqbufs->count == 0) {
+		if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+			mtk_mdp_ctx_state_lock_clear(ctx, MTK_MDP_SRC_FMT);
+		else
+			mtk_mdp_ctx_state_lock_clear(ctx, MTK_MDP_DST_FMT);
+	}
+
+	return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int mtk_mdp_m2m_streamon(struct file *file, void *fh,
+				enum v4l2_buf_type type)
+{
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+	int ret;
+
+	/* The source and target color format need to be set */
+	if (V4L2_TYPE_IS_OUTPUT(type)) {
+		if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_SRC_FMT))
+			return -EINVAL;
+	} else if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_DST_FMT)) {
+		return -EINVAL;
+	}
+
+	if (!mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_VPU_INIT)) {
+		ret = mtk_mdp_vpu_init(&ctx->vpu);
+		if (ret < 0) {
+			dev_err(&ctx->mdp_dev->pdev->dev,
+				"vpu init failed %d\n",
+				ret);
+			return -EINVAL;
+		}
+		mtk_mdp_ctx_state_lock_set(ctx, MTK_MDP_VPU_INIT);
+	}
+
+	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static inline bool mtk_mdp_is_target_compose(u32 target)
+{
+	if (target == V4L2_SEL_TGT_COMPOSE_DEFAULT
+	    || target == V4L2_SEL_TGT_COMPOSE_BOUNDS
+	    || target == V4L2_SEL_TGT_COMPOSE)
+		return true;
+	return false;
+}
+
+static inline bool mtk_mdp_is_target_crop(u32 target)
+{
+	if (target == V4L2_SEL_TGT_CROP_DEFAULT
+	    || target == V4L2_SEL_TGT_CROP_BOUNDS
+	    || target == V4L2_SEL_TGT_CROP)
+		return true;
+	return false;
+}
+
+static int mtk_mdp_m2m_g_selection(struct file *file, void *fh,
+				       struct v4l2_selection *s)
+{
+	struct mtk_mdp_frame *frame;
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+	bool valid = false;
+
+	if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		if (mtk_mdp_is_target_compose(s->target))
+			valid = true;
+	} else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		if (mtk_mdp_is_target_crop(s->target))
+			valid = true;
+	}
+	if (!valid) {
+		mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
+			    s->target);
+		return -EINVAL;
+	}
+
+	frame = mtk_mdp_ctx_get_frame(ctx, s->type);
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = frame->width;
+		s->r.height = frame->height;
+		return 0;
+
+	case V4L2_SEL_TGT_COMPOSE:
+	case V4L2_SEL_TGT_CROP:
+		s->r.left = frame->crop.left;
+		s->r.top = frame->crop.top;
+		s->r.width = frame->crop.width;
+		s->r.height = frame->crop.height;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int mtk_mdp_check_scaler_ratio(struct mtk_mdp_variant *var, int src_w,
+				      int src_h, int dst_w, int dst_h, int rot)
+{
+	int tmp_w, tmp_h;
+
+	if (rot == 90 || rot == 270) {
+		tmp_w = dst_h;
+		tmp_h = dst_w;
+	} else {
+		tmp_w = dst_w;
+		tmp_h = dst_h;
+	}
+
+	if ((src_w / tmp_w) > var->h_scale_down_max ||
+	    (src_h / tmp_h) > var->v_scale_down_max ||
+	    (tmp_w / src_w) > var->h_scale_up_max ||
+	    (tmp_h / src_h) > var->v_scale_up_max)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int mtk_mdp_m2m_s_selection(struct file *file, void *fh,
+				   struct v4l2_selection *s)
+{
+	struct mtk_mdp_frame *frame;
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(fh);
+	struct v4l2_rect new_r;
+	struct mtk_mdp_variant *variant = ctx->mdp_dev->variant;
+	int ret;
+	bool valid = false;
+
+	if (s->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		if (s->target == V4L2_SEL_TGT_COMPOSE)
+			valid = true;
+	} else if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		if (s->target == V4L2_SEL_TGT_CROP)
+			valid = true;
+	}
+	if (!valid) {
+		mtk_mdp_dbg(1, "[%d] invalid type:%d,%u", ctx->id, s->type,
+			    s->target);
+		return -EINVAL;
+	}
+
+	new_r = s->r;
+	ret = mtk_mdp_try_crop(ctx, s->type, &new_r);
+	if (ret)
+		return ret;
+
+	if (mtk_mdp_is_target_crop(s->target))
+		frame = &ctx->s_frame;
+	else
+		frame = &ctx->d_frame;
+
+	/* Check to see if scaling ratio is within supported range */
+	if (mtk_mdp_ctx_state_is_set(ctx, MTK_MDP_DST_FMT | MTK_MDP_SRC_FMT)) {
+		if (V4L2_TYPE_IS_OUTPUT(s->type)) {
+			ret = mtk_mdp_check_scaler_ratio(variant, new_r.width,
+				new_r.height, ctx->d_frame.crop.width,
+				ctx->d_frame.crop.height,
+				ctx->ctrls.rotate->val);
+		} else {
+			ret = mtk_mdp_check_scaler_ratio(variant,
+				ctx->s_frame.crop.width,
+				ctx->s_frame.crop.height, new_r.width,
+				new_r.height, ctx->ctrls.rotate->val);
+		}
+
+		if (ret) {
+			dev_info(&ctx->mdp_dev->pdev->dev,
+				"Out of scaler range");
+			return -EINVAL;
+		}
+	}
+
+	s->r = new_r;
+	frame->crop = new_r;
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops mtk_mdp_m2m_ioctl_ops = {
+	.vidioc_querycap		= mtk_mdp_m2m_querycap,
+	.vidioc_enum_fmt_vid_cap_mplane	= mtk_mdp_m2m_enum_fmt_mplane_vid_cap,
+	.vidioc_enum_fmt_vid_out_mplane	= mtk_mdp_m2m_enum_fmt_mplane_vid_out,
+	.vidioc_g_fmt_vid_cap_mplane	= mtk_mdp_m2m_g_fmt_mplane,
+	.vidioc_g_fmt_vid_out_mplane	= mtk_mdp_m2m_g_fmt_mplane,
+	.vidioc_try_fmt_vid_cap_mplane	= mtk_mdp_m2m_try_fmt_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= mtk_mdp_m2m_try_fmt_mplane,
+	.vidioc_s_fmt_vid_cap_mplane	= mtk_mdp_m2m_s_fmt_mplane,
+	.vidioc_s_fmt_vid_out_mplane	= mtk_mdp_m2m_s_fmt_mplane,
+	.vidioc_reqbufs			= mtk_mdp_m2m_reqbufs,
+	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
+	.vidioc_subscribe_event		= v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
+	.vidioc_streamon		= mtk_mdp_m2m_streamon,
+	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
+	.vidioc_g_selection		= mtk_mdp_m2m_g_selection,
+	.vidioc_s_selection		= mtk_mdp_m2m_s_selection
+};
+
+static int mtk_mdp_m2m_queue_init(void *priv, struct vb2_queue *src_vq,
+				  struct vb2_queue *dst_vq)
+{
+	struct mtk_mdp_ctx *ctx = priv;
+	int ret;
+
+	memset(src_vq, 0, sizeof(*src_vq));
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->drv_priv = ctx;
+	src_vq->ops = &mtk_mdp_m2m_qops;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->dev = &ctx->mdp_dev->pdev->dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	memset(dst_vq, 0, sizeof(*dst_vq));
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->ops = &mtk_mdp_m2m_qops;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->dev = &ctx->mdp_dev->pdev->dev;
+
+	return vb2_queue_init(dst_vq);
+}
+
+static int mtk_mdp_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mtk_mdp_ctx *ctx = ctrl_to_ctx(ctrl);
+	struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+	struct mtk_mdp_variant *variant = mdp->variant;
+	u32 state = MTK_MDP_DST_FMT | MTK_MDP_SRC_FMT;
+	int ret = 0;
+
+	if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_HFLIP:
+		ctx->hflip = ctrl->val;
+		break;
+	case V4L2_CID_VFLIP:
+		ctx->vflip = ctrl->val;
+		break;
+	case V4L2_CID_ROTATE:
+		if (mtk_mdp_ctx_state_is_set(ctx, state)) {
+			ret = mtk_mdp_check_scaler_ratio(variant,
+					ctx->s_frame.crop.width,
+					ctx->s_frame.crop.height,
+					ctx->d_frame.crop.width,
+					ctx->d_frame.crop.height,
+					ctx->ctrls.rotate->val);
+
+			if (ret)
+				return -EINVAL;
+		}
+
+		ctx->rotation = ctrl->val;
+		break;
+	case V4L2_CID_ALPHA_COMPONENT:
+		ctx->d_frame.alpha = ctrl->val;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops mtk_mdp_ctrl_ops = {
+	.s_ctrl = mtk_mdp_s_ctrl,
+};
+
+static int mtk_mdp_ctrls_create(struct mtk_mdp_ctx *ctx)
+{
+	v4l2_ctrl_handler_init(&ctx->ctrl_handler, MTK_MDP_MAX_CTRL_NUM);
+
+	ctx->ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+			&mtk_mdp_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0);
+	ctx->ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+					     &mtk_mdp_ctrl_ops,
+					     V4L2_CID_HFLIP,
+					     0, 1, 1, 0);
+	ctx->ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+					     &mtk_mdp_ctrl_ops,
+					     V4L2_CID_VFLIP,
+					     0, 1, 1, 0);
+	ctx->ctrls.global_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+						    &mtk_mdp_ctrl_ops,
+						    V4L2_CID_ALPHA_COMPONENT,
+						    0, 255, 1, 0);
+	ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
+
+	if (ctx->ctrl_handler.error) {
+		int err = ctx->ctrl_handler.error;
+
+		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+		dev_err(&ctx->mdp_dev->pdev->dev,
+			"Failed to create control handlers\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static void mtk_mdp_set_default_params(struct mtk_mdp_ctx *ctx)
+{
+	struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+	struct mtk_mdp_frame *frame;
+
+	frame = mtk_mdp_ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+	frame->fmt = mtk_mdp_find_fmt_by_index(0,
+					V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+	frame->width = mdp->variant->pix_min->org_w;
+	frame->height = mdp->variant->pix_min->org_h;
+	frame->payload[0] = frame->width * frame->height;
+	frame->payload[1] = frame->payload[0] / 2;
+
+	frame = mtk_mdp_ctx_get_frame(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+	frame->fmt = mtk_mdp_find_fmt_by_index(0,
+					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+	frame->width = mdp->variant->pix_min->target_rot_dis_w;
+	frame->height = mdp->variant->pix_min->target_rot_dis_h;
+	frame->payload[0] = frame->width * frame->height;
+	frame->payload[1] = frame->payload[0] / 2;
+
+}
+
+static int mtk_mdp_m2m_open(struct file *file)
+{
+	struct mtk_mdp_dev *mdp = video_drvdata(file);
+	struct video_device *vfd = video_devdata(file);
+	struct mtk_mdp_ctx *ctx = NULL;
+	int ret;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	if (mutex_lock_interruptible(&mdp->lock)) {
+		ret = -ERESTARTSYS;
+		goto err_lock;
+	}
+
+	mutex_init(&ctx->slock);
+	ctx->id = mdp->id_counter++;
+	v4l2_fh_init(&ctx->fh, vfd);
+	file->private_data = &ctx->fh;
+	ret = mtk_mdp_ctrls_create(ctx);
+	if (ret)
+		goto error_ctrls;
+
+	/* Use separate control handler per file handle */
+	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+	v4l2_fh_add(&ctx->fh);
+	INIT_LIST_HEAD(&ctx->list);
+
+	ctx->mdp_dev = mdp;
+	mtk_mdp_set_default_params(ctx);
+
+	INIT_WORK(&ctx->work, mtk_mdp_m2m_worker);
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(mdp->m2m_dev, ctx,
+					 mtk_mdp_m2m_queue_init);
+	if (IS_ERR(ctx->m2m_ctx)) {
+		dev_err(&mdp->pdev->dev, "Failed to initialize m2m context");
+		ret = PTR_ERR(ctx->m2m_ctx);
+		goto error_m2m_ctx;
+	}
+	ctx->fh.m2m_ctx = ctx->m2m_ctx;
+	if (mdp->ctx_num++ == 0) {
+		ret = vpu_load_firmware(mdp->vpu_dev);
+		if (ret < 0) {
+			dev_err(&mdp->pdev->dev,
+				"vpu_load_firmware failed %d\n", ret);
+			goto err_load_vpu;
+		}
+
+		ret = mtk_mdp_vpu_register(mdp->pdev);
+		if (ret < 0) {
+			dev_err(&mdp->pdev->dev,
+				"mdp_vpu register failed %d\n", ret);
+			goto err_load_vpu;
+		}
+	}
+
+	list_add(&ctx->list, &mdp->ctx_list);
+	mutex_unlock(&mdp->lock);
+
+	mtk_mdp_dbg(0, "%s [%d]", dev_name(&mdp->pdev->dev), ctx->id);
+
+	return 0;
+
+err_load_vpu:
+	mdp->ctx_num--;
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+error_m2m_ctx:
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+error_ctrls:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	mutex_unlock(&mdp->lock);
+err_lock:
+	kfree(ctx);
+
+	return ret;
+}
+
+static int mtk_mdp_m2m_release(struct file *file)
+{
+	struct mtk_mdp_ctx *ctx = fh_to_ctx(file->private_data);
+	struct mtk_mdp_dev *mdp = ctx->mdp_dev;
+
+	flush_workqueue(mdp->job_wq);
+	mutex_lock(&mdp->lock);
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	mtk_mdp_vpu_deinit(&ctx->vpu);
+	mdp->ctx_num--;
+	list_del_init(&ctx->list);
+
+	mtk_mdp_dbg(0, "%s [%d]", dev_name(&mdp->pdev->dev), ctx->id);
+
+	mutex_unlock(&mdp->lock);
+	kfree(ctx);
+
+	return 0;
+}
+
+static const struct v4l2_file_operations mtk_mdp_m2m_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mtk_mdp_m2m_open,
+	.release	= mtk_mdp_m2m_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static struct v4l2_m2m_ops mtk_mdp_m2m_ops = {
+	.device_run	= mtk_mdp_m2m_device_run,
+	.job_abort	= mtk_mdp_m2m_job_abort,
+};
+
+int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp)
+{
+	struct device *dev = &mdp->pdev->dev;
+	int ret;
+
+	mdp->variant = &mtk_mdp_default_variant;
+	mdp->vdev = video_device_alloc();
+	if (!mdp->vdev) {
+		dev_err(dev, "failed to allocate video device\n");
+		ret = -ENOMEM;
+		goto err_video_alloc;
+	}
+	mdp->vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	mdp->vdev->fops = &mtk_mdp_m2m_fops;
+	mdp->vdev->ioctl_ops = &mtk_mdp_m2m_ioctl_ops;
+	mdp->vdev->release = video_device_release;
+	mdp->vdev->lock = &mdp->lock;
+	mdp->vdev->vfl_dir = VFL_DIR_M2M;
+	mdp->vdev->v4l2_dev = &mdp->v4l2_dev;
+	snprintf(mdp->vdev->name, sizeof(mdp->vdev->name), "%s:m2m",
+		 MTK_MDP_MODULE_NAME);
+	video_set_drvdata(mdp->vdev, mdp);
+
+	mdp->m2m_dev = v4l2_m2m_init(&mtk_mdp_m2m_ops);
+	if (IS_ERR(mdp->m2m_dev)) {
+		dev_err(dev, "failed to initialize v4l2-m2m device\n");
+		ret = PTR_ERR(mdp->m2m_dev);
+		goto err_m2m_init;
+	}
+
+	ret = video_register_device(mdp->vdev, VFL_TYPE_GRABBER, 2);
+	if (ret) {
+		dev_err(dev, "failed to register video device\n");
+		goto err_vdev_register;
+	}
+
+	v4l2_info(&mdp->v4l2_dev, "driver registered as /dev/video%d",
+		  mdp->vdev->num);
+	return 0;
+
+err_vdev_register:
+	v4l2_m2m_release(mdp->m2m_dev);
+err_m2m_init:
+	video_device_release(mdp->vdev);
+err_video_alloc:
+
+	return ret;
+}
+
+void mtk_mdp_unregister_m2m_device(struct mtk_mdp_dev *mdp)
+{
+	video_unregister_device(mdp->vdev);
+	v4l2_m2m_release(mdp->m2m_dev);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_M2M_H__
+#define __MTK_MDP_M2M_H__
+
+void mtk_mdp_ctx_state_lock_set(struct mtk_mdp_ctx *ctx, u32 state);
+int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp);
+void mtk_mdp_unregister_m2m_device(struct mtk_mdp_dev *mdp);
+
+#endif /* __MTK_MDP_M2M_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.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/platform_device.h>
+
+#include "mtk_mdp_core.h"
+#include "mtk_mdp_regs.h"
+
+
+#define MDP_COLORFMT_PACK(VIDEO, PLANE, COPLANE, HF, VF, BITS, GROUP, SWAP, ID)\
+	(((VIDEO) << 27) | ((PLANE) << 24) | ((COPLANE) << 22) |\
+	((HF) << 20) | ((VF) << 18) | ((BITS) << 8) | ((GROUP) << 6) |\
+	((SWAP) << 5) | ((ID) << 0))
+
+enum MDP_COLOR_ENUM {
+	MDP_COLOR_UNKNOWN = 0,
+	MDP_COLOR_NV12 = MDP_COLORFMT_PACK(0, 2, 1, 1, 1, 8, 1, 0, 12),
+	MDP_COLOR_I420 = MDP_COLORFMT_PACK(0, 3, 0, 1, 1, 8, 1, 0, 8),
+	MDP_COLOR_YV12 = MDP_COLORFMT_PACK(0, 3, 0, 1, 1, 8, 1, 1, 8),
+	/* Mediatek proprietary format */
+	MDP_COLOR_420_MT21 = MDP_COLORFMT_PACK(5, 2, 1, 1, 1, 256, 1, 0, 12),
+};
+
+static int32_t mtk_mdp_map_color_format(int v4l2_format)
+{
+	switch (v4l2_format) {
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV12:
+		return MDP_COLOR_NV12;
+	case V4L2_PIX_FMT_MT21C:
+		return MDP_COLOR_420_MT21;
+	case V4L2_PIX_FMT_YUV420M:
+	case V4L2_PIX_FMT_YUV420:
+		return MDP_COLOR_I420;
+	case V4L2_PIX_FMT_YVU420:
+		return MDP_COLOR_YV12;
+	}
+
+	mtk_mdp_err("Unknown format 0x%x", v4l2_format);
+
+	return MDP_COLOR_UNKNOWN;
+}
+
+void mtk_mdp_hw_set_input_addr(struct mtk_mdp_ctx *ctx,
+			       struct mtk_mdp_addr *addr)
+{
+	struct mdp_buffer *src_buf = &ctx->vpu.vsi->src_buffer;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(addr->addr); i++)
+		src_buf->addr_mva[i] = (uint64_t)addr->addr[i];
+}
+
+void mtk_mdp_hw_set_output_addr(struct mtk_mdp_ctx *ctx,
+				struct mtk_mdp_addr *addr)
+{
+	struct mdp_buffer *dst_buf = &ctx->vpu.vsi->dst_buffer;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(addr->addr); i++)
+		dst_buf->addr_mva[i] = (uint64_t)addr->addr[i];
+}
+
+void mtk_mdp_hw_set_in_size(struct mtk_mdp_ctx *ctx)
+{
+	struct mtk_mdp_frame *frame = &ctx->s_frame;
+	struct mdp_config *config = &ctx->vpu.vsi->src_config;
+
+	/* Set input pixel offset */
+	config->crop_x = frame->crop.left;
+	config->crop_y = frame->crop.top;
+
+	/* Set input cropped size */
+	config->crop_w = frame->crop.width;
+	config->crop_h = frame->crop.height;
+
+	/* Set input original size */
+	config->x = 0;
+	config->y = 0;
+	config->w = frame->width;
+	config->h = frame->height;
+}
+
+void mtk_mdp_hw_set_in_image_format(struct mtk_mdp_ctx *ctx)
+{
+	unsigned int i;
+	struct mtk_mdp_frame *frame = &ctx->s_frame;
+	struct mdp_config *config = &ctx->vpu.vsi->src_config;
+	struct mdp_buffer *src_buf = &ctx->vpu.vsi->src_buffer;
+
+	src_buf->plane_num = frame->fmt->num_comp;
+	config->format = mtk_mdp_map_color_format(frame->fmt->pixelformat);
+	config->w_stride = 0; /* MDP will calculate it by color format. */
+	config->h_stride = 0; /* MDP will calculate it by color format. */
+
+	for (i = 0; i < src_buf->plane_num; i++)
+		src_buf->plane_size[i] = frame->payload[i];
+}
+
+void mtk_mdp_hw_set_out_size(struct mtk_mdp_ctx *ctx)
+{
+	struct mtk_mdp_frame *frame = &ctx->d_frame;
+	struct mdp_config *config = &ctx->vpu.vsi->dst_config;
+
+	config->crop_x = frame->crop.left;
+	config->crop_y = frame->crop.top;
+	config->crop_w = frame->crop.width;
+	config->crop_h = frame->crop.height;
+	config->x = 0;
+	config->y = 0;
+	config->w = frame->width;
+	config->h = frame->height;
+}
+
+void mtk_mdp_hw_set_out_image_format(struct mtk_mdp_ctx *ctx)
+{
+	unsigned int i;
+	struct mtk_mdp_frame *frame = &ctx->d_frame;
+	struct mdp_config *config = &ctx->vpu.vsi->dst_config;
+	struct mdp_buffer *dst_buf = &ctx->vpu.vsi->dst_buffer;
+
+	dst_buf->plane_num = frame->fmt->num_comp;
+	config->format = mtk_mdp_map_color_format(frame->fmt->pixelformat);
+	config->w_stride = 0; /* MDP will calculate it by color format. */
+	config->h_stride = 0; /* MDP will calculate it by color format. */
+	for (i = 0; i < dst_buf->plane_num; i++)
+		dst_buf->plane_size[i] = frame->payload[i];
+}
+
+void mtk_mdp_hw_set_rotation(struct mtk_mdp_ctx *ctx)
+{
+	struct mdp_config_misc *misc = &ctx->vpu.vsi->misc;
+
+	misc->orientation = ctx->ctrls.rotate->val;
+	misc->hflip = ctx->ctrls.hflip->val;
+	misc->vflip = ctx->ctrls.vflip->val;
+}
+
+void mtk_mdp_hw_set_global_alpha(struct mtk_mdp_ctx *ctx)
+{
+	struct mdp_config_misc *misc = &ctx->vpu.vsi->misc;
+
+	misc->alpha = ctx->ctrls.global_alpha->val;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_REGS_H__
+#define __MTK_MDP_REGS_H__
+
+
+void mtk_mdp_hw_set_input_addr(struct mtk_mdp_ctx *ctx,
+			       struct mtk_mdp_addr *addr);
+void mtk_mdp_hw_set_output_addr(struct mtk_mdp_ctx *ctx,
+				struct mtk_mdp_addr *addr);
+void mtk_mdp_hw_set_in_size(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_in_image_format(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_out_size(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_out_image_format(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_rotation(struct mtk_mdp_ctx *ctx);
+void mtk_mdp_hw_set_global_alpha(struct mtk_mdp_ctx *ctx);
+
+
+#endif /* __MTK_MDP_REGS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.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 "mtk_mdp_core.h"
+#include "mtk_mdp_vpu.h"
+#include "mtk_vpu.h"
+
+
+static inline struct mtk_mdp_ctx *vpu_to_ctx(struct mtk_mdp_vpu *vpu)
+{
+	return container_of(vpu, struct mtk_mdp_ctx, vpu);
+}
+
+static void mtk_mdp_vpu_handle_init_ack(struct mdp_ipi_comm_ack *msg)
+{
+	struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)
+					(unsigned long)msg->ap_inst;
+
+	/* mapping VPU address to kernel virtual address */
+	vpu->vsi = (struct mdp_process_vsi *)
+			vpu_mapping_dm_addr(vpu->pdev, msg->vpu_inst_addr);
+	vpu->inst_addr = msg->vpu_inst_addr;
+}
+
+static void mtk_mdp_vpu_ipi_handler(void *data, unsigned int len, void *priv)
+{
+	unsigned int msg_id = *(unsigned int *)data;
+	struct mdp_ipi_comm_ack *msg = (struct mdp_ipi_comm_ack *)data;
+	struct mtk_mdp_vpu *vpu = (struct mtk_mdp_vpu *)
+					(unsigned long)msg->ap_inst;
+	struct mtk_mdp_ctx *ctx;
+
+	vpu->failure = msg->status;
+	if (!vpu->failure) {
+		switch (msg_id) {
+		case VPU_MDP_INIT_ACK:
+			mtk_mdp_vpu_handle_init_ack(data);
+			break;
+		case VPU_MDP_DEINIT_ACK:
+		case VPU_MDP_PROCESS_ACK:
+			break;
+		default:
+			ctx = vpu_to_ctx(vpu);
+			dev_err(&ctx->mdp_dev->pdev->dev,
+				"handle unknown ipi msg:0x%x\n",
+				msg_id);
+			break;
+		}
+	} else {
+		ctx = vpu_to_ctx(vpu);
+		mtk_mdp_dbg(0, "[%d]:msg 0x%x, failure:%d", ctx->id,
+			    msg_id, vpu->failure);
+	}
+}
+
+int mtk_mdp_vpu_register(struct platform_device *pdev)
+{
+	struct mtk_mdp_dev *mdp = platform_get_drvdata(pdev);
+	int err;
+
+	err = vpu_ipi_register(mdp->vpu_dev, IPI_MDP,
+			       mtk_mdp_vpu_ipi_handler, "mdp_vpu", NULL);
+	if (err)
+		dev_err(&mdp->pdev->dev,
+			"vpu_ipi_registration fail status=%d\n", err);
+
+	return err;
+}
+
+static int mtk_mdp_vpu_send_msg(void *msg, int len, struct mtk_mdp_vpu *vpu,
+				int id)
+{
+	struct mtk_mdp_ctx *ctx = vpu_to_ctx(vpu);
+	int err;
+
+	if (!vpu->pdev) {
+		mtk_mdp_dbg(1, "[%d]:vpu pdev is NULL", ctx->id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&ctx->mdp_dev->vpulock);
+	err = vpu_ipi_send(vpu->pdev, (enum ipi_id)id, msg, len);
+	if (err)
+		dev_err(&ctx->mdp_dev->pdev->dev,
+			"vpu_ipi_send fail status %d\n", err);
+	mutex_unlock(&ctx->mdp_dev->vpulock);
+
+	return err;
+}
+
+static int mtk_mdp_vpu_send_ap_ipi(struct mtk_mdp_vpu *vpu, uint32_t msg_id)
+{
+	int err;
+	struct mdp_ipi_comm msg;
+
+	msg.msg_id = msg_id;
+	msg.ipi_id = IPI_MDP;
+	msg.vpu_inst_addr = vpu->inst_addr;
+	msg.ap_inst = (unsigned long)vpu;
+	err = mtk_mdp_vpu_send_msg((void *)&msg, sizeof(msg), vpu, IPI_MDP);
+	if (!err && vpu->failure)
+		err = -EINVAL;
+
+	return err;
+}
+
+int mtk_mdp_vpu_init(struct mtk_mdp_vpu *vpu)
+{
+	int err;
+	struct mdp_ipi_init msg;
+	struct mtk_mdp_ctx *ctx = vpu_to_ctx(vpu);
+
+	vpu->pdev = ctx->mdp_dev->vpu_dev;
+
+	msg.msg_id = AP_MDP_INIT;
+	msg.ipi_id = IPI_MDP;
+	msg.ap_inst = (unsigned long)vpu;
+	err = mtk_mdp_vpu_send_msg((void *)&msg, sizeof(msg), vpu, IPI_MDP);
+	if (!err && vpu->failure)
+		err = -EINVAL;
+
+	return err;
+}
+
+int mtk_mdp_vpu_deinit(struct mtk_mdp_vpu *vpu)
+{
+	return mtk_mdp_vpu_send_ap_ipi(vpu, AP_MDP_DEINIT);
+}
+
+int mtk_mdp_vpu_process(struct mtk_mdp_vpu *vpu)
+{
+	return mtk_mdp_vpu_send_ap_ipi(vpu, AP_MDP_PROCESS);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-mdp/mtk_mdp_vpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Houlong Wei <houlong.wei@mediatek.com>
+ *         Ming Hsiu Tsai <minghsiu.tsai@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MTK_MDP_VPU_H__
+#define __MTK_MDP_VPU_H__
+
+#include "mtk_mdp_ipi.h"
+
+
+/**
+ * struct mtk_mdp_vpu - VPU instance for MDP
+ * @pdev	: pointer to the VPU platform device
+ * @inst_addr	: VPU MDP instance address
+ * @failure	: VPU execution result status
+ * @vsi		: VPU shared information
+ */
+struct mtk_mdp_vpu {
+	struct platform_device	*pdev;
+	uint32_t		inst_addr;
+	int32_t			failure;
+	struct mdp_process_vsi	*vsi;
+};
+
+int mtk_mdp_vpu_register(struct platform_device *pdev);
+int mtk_mdp_vpu_init(struct mtk_mdp_vpu *vpu);
+int mtk_mdp_vpu_deinit(struct mtk_mdp_vpu *vpu);
+int mtk_mdp_vpu_process(struct mtk_mdp_vpu *vpu);
+
+#endif /* __MTK_MDP_VPU_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/Makefile linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/Makefile
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,16 @@
 
+obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-dec.o \
+				       mtk-vcodec-enc.o \
+				       mtk-vcodec-common.o
 
-obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec-enc.o mtk-vcodec-common.o
-
+mtk-vcodec-dec-y := vdec/vdec_h264_if.o \
+		vdec/vdec_vp8_if.o \
+		vdec/vdec_vp9_if.o \
+		mtk_vcodec_dec_drv.o \
+		vdec_drv_if.o \
+		vdec_vpu_if.o \
+		mtk_vcodec_dec.o \
+		mtk_vcodec_dec_pm.o \
 
 
 mtk-vcodec-enc-y := venc/venc_vp8_if.o \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1451 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *         Tiffany Lin <tiffany.lin@mediatek.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 <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "vdec_drv_if.h"
+#include "mtk_vcodec_dec_pm.h"
+
+#define OUT_FMT_IDX	0
+#define CAP_FMT_IDX	3
+
+#define MTK_VDEC_MIN_W	64U
+#define MTK_VDEC_MIN_H	64U
+#define DFT_CFG_WIDTH	MTK_VDEC_MIN_W
+#define DFT_CFG_HEIGHT	MTK_VDEC_MIN_H
+
+static struct mtk_video_fmt mtk_video_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP8,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.type = MTK_FMT_DEC,
+		.num_planes = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MT21C,
+		.type = MTK_FMT_FRAME,
+		.num_planes = 2,
+	},
+};
+
+static const struct mtk_codec_framesizes mtk_vdec_framesizes[] = {
+	{
+		.fourcc	= V4L2_PIX_FMT_H264,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc	= V4L2_PIX_FMT_VP8,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_VP9,
+		.stepwise = {  MTK_VDEC_MIN_W, MTK_VDEC_MAX_W, 16,
+				MTK_VDEC_MIN_H, MTK_VDEC_MAX_H, 16 },
+	},
+};
+
+#define NUM_SUPPORTED_FRAMESIZE ARRAY_SIZE(mtk_vdec_framesizes)
+#define NUM_FORMATS ARRAY_SIZE(mtk_video_formats)
+
+static struct mtk_video_fmt *mtk_vdec_find_format(struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < NUM_FORMATS; k++) {
+		fmt = &mtk_video_formats[k];
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static struct mtk_q_data *mtk_vdec_get_q_data(struct mtk_vcodec_ctx *ctx,
+					      enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->q_data[MTK_Q_DATA_SRC];
+
+	return &ctx->q_data[MTK_Q_DATA_DST];
+}
+
+/*
+ * This function tries to clean all display buffers, the buffers will return
+ * in display order.
+ * Note the buffers returned from codec driver may still be in driver's
+ * reference list.
+ */
+static struct vb2_buffer *get_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vdec_fb *disp_frame_buffer = NULL;
+	struct mtk_video_dec_buf *dstbuf;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	if (vdec_if_get_param(ctx,
+			GET_PARAM_DISP_FRAME_BUFFER,
+			&disp_frame_buffer)) {
+		mtk_v4l2_err("[%d]Cannot get param : GET_PARAM_DISP_FRAME_BUFFER",
+			ctx->id);
+		return NULL;
+	}
+
+	if (disp_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, "No display frame buffer");
+		return NULL;
+	}
+
+	dstbuf = container_of(disp_frame_buffer, struct mtk_video_dec_buf,
+				frame_buffer);
+	mutex_lock(&ctx->lock);
+	if (dstbuf->used) {
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 0,
+					ctx->picinfo.y_bs_sz);
+		vb2_set_plane_payload(&dstbuf->vb.vb2_buf, 1,
+					ctx->picinfo.c_bs_sz);
+
+		dstbuf->ready_to_display = true;
+
+		mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to done_list %d",
+				ctx->id, disp_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+
+		v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
+		ctx->decoded_frame_cnt++;
+	}
+	mutex_unlock(&ctx->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+/*
+ * This function tries to clean all capture buffers that are not used as
+ * reference buffers by codec driver any more
+ * In this case, we need re-queue buffer to vb2 buffer if user space
+ * already returns this buffer to v4l2 or this buffer is just the output of
+ * previous sps/pps/resolution change decode, or do nothing if user
+ * space still owns this buffer
+ */
+static struct vb2_buffer *get_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_video_dec_buf *dstbuf;
+	struct vdec_fb *free_frame_buffer = NULL;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_FREE_FRAME_BUFFER,
+				&free_frame_buffer)) {
+		mtk_v4l2_err("[%d] Error!! Cannot get param", ctx->id);
+		return NULL;
+	}
+	if (free_frame_buffer == NULL) {
+		mtk_v4l2_debug(3, " No free frame buffer");
+		return NULL;
+	}
+
+	mtk_v4l2_debug(3, "[%d] tmp_frame_addr = 0x%p",
+			ctx->id, free_frame_buffer);
+
+	dstbuf = container_of(free_frame_buffer, struct mtk_video_dec_buf,
+				frame_buffer);
+
+	mutex_lock(&ctx->lock);
+	if (dstbuf->used) {
+		if ((dstbuf->queued_in_vb2) &&
+		    (dstbuf->queued_in_v4l2) &&
+		    (free_frame_buffer->status == FB_ST_FREE)) {
+			/*
+			 * After decode sps/pps or non-display buffer, we don't
+			 * need to return capture buffer to user space, but
+			 * just re-queue this capture buffer to vb2 queue.
+			 * This reduce overheads that dq/q unused capture
+			 * buffer. In this case, queued_in_vb2 = true.
+			 */
+			mtk_v4l2_debug(2,
+				"[%d]status=%x queue id=%d to rdy_queue %d",
+				ctx->id, free_frame_buffer->status,
+				dstbuf->vb.vb2_buf.index,
+				dstbuf->queued_in_vb2);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+		} else if ((dstbuf->queued_in_vb2 == false) &&
+			   (dstbuf->queued_in_v4l2 == true)) {
+			/*
+			 * If buffer in v4l2 driver but not in vb2 queue yet,
+			 * and we get this buffer from free_list, it means
+			 * that codec driver do not use this buffer as
+			 * reference buffer anymore. We should q buffer to vb2
+			 * queue, so later work thread could get this buffer
+			 * for decode. In this case, queued_in_vb2 = false
+			 * means this buffer is not from previous decode
+			 * output.
+			 */
+			mtk_v4l2_debug(2,
+					"[%d]status=%x queue id=%d to rdy_queue",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index);
+			v4l2_m2m_buf_queue(ctx->m2m_ctx, &dstbuf->vb);
+			dstbuf->queued_in_vb2 = true;
+		} else {
+			/*
+			 * Codec driver do not need to reference this capture
+			 * buffer and this buffer is not in v4l2 driver.
+			 * Then we don't need to do any thing, just add log when
+			 * we need to debug buffer flow.
+			 * When this buffer q from user space, it could
+			 * directly q to vb2 buffer
+			 */
+			mtk_v4l2_debug(3, "[%d]status=%x err queue id=%d %d %d",
+					ctx->id, free_frame_buffer->status,
+					dstbuf->vb.vb2_buf.index,
+					dstbuf->queued_in_vb2,
+					dstbuf->queued_in_v4l2);
+		}
+		dstbuf->used = false;
+	}
+	mutex_unlock(&ctx->lock);
+	return &dstbuf->vb.vb2_buf;
+}
+
+static void clean_display_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_display_buffer(ctx);
+	} while (framptr);
+}
+
+static void clean_free_buffer(struct mtk_vcodec_ctx *ctx)
+{
+	struct vb2_buffer *framptr;
+
+	do {
+		framptr = get_free_buffer(ctx);
+	} while (framptr);
+}
+
+static void mtk_vdec_queue_res_chg_event(struct mtk_vcodec_ctx *ctx)
+{
+	static const struct v4l2_event ev_src_ch = {
+		.type = V4L2_EVENT_SOURCE_CHANGE,
+		.u.src_change.changes =
+		V4L2_EVENT_SRC_CH_RESOLUTION,
+	};
+
+	mtk_v4l2_debug(1, "[%d]", ctx->id);
+	v4l2_event_queue_fh(&ctx->fh, &ev_src_ch);
+}
+
+static void mtk_vdec_flush_decoder(struct mtk_vcodec_ctx *ctx)
+{
+	bool res_chg;
+	int ret = 0;
+
+	ret = vdec_if_decode(ctx, NULL, NULL, &res_chg);
+	if (ret)
+		mtk_v4l2_err("DecodeFinal failed, ret=%d", ret);
+
+	clean_display_buffer(ctx);
+	clean_free_buffer(ctx);
+}
+
+static void mtk_vdec_pic_info_update(struct mtk_vcodec_ctx *ctx)
+{
+	unsigned int dpbsize = 0;
+	int ret;
+
+	if (vdec_if_get_param(ctx,
+				GET_PARAM_PIC_INFO,
+				&ctx->last_decoded_picinfo)) {
+		mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+				ctx->id);
+		return;
+	}
+
+	if (ctx->last_decoded_picinfo.pic_w == 0 ||
+		ctx->last_decoded_picinfo.pic_h == 0 ||
+		ctx->last_decoded_picinfo.buf_w == 0 ||
+		ctx->last_decoded_picinfo.buf_h == 0) {
+		mtk_v4l2_err("Cannot get correct pic info");
+		return;
+	}
+
+	if ((ctx->last_decoded_picinfo.pic_w == ctx->picinfo.pic_w) ||
+	    (ctx->last_decoded_picinfo.pic_h == ctx->picinfo.pic_h))
+		return;
+
+	mtk_v4l2_debug(1,
+			"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
+			ctx->id, ctx->last_decoded_picinfo.pic_w,
+			ctx->last_decoded_picinfo.pic_h,
+			ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+			ctx->last_decoded_picinfo.buf_w,
+			ctx->last_decoded_picinfo.buf_h);
+
+	ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
+	if (dpbsize == 0)
+		mtk_v4l2_err("Incorrect dpb size, ret=%d", ret);
+
+	ctx->dpb_size = dpbsize;
+}
+
+static void mtk_vdec_worker(struct work_struct *work)
+{
+	struct mtk_vcodec_ctx *ctx = container_of(work, struct mtk_vcodec_ctx,
+				decode_work);
+	struct mtk_vcodec_dev *dev = ctx->dev;
+	struct vb2_buffer *src_buf, *dst_buf;
+	struct mtk_vcodec_mem buf;
+	struct vdec_fb *pfb;
+	bool res_chg = false;
+	int ret;
+	struct mtk_video_dec_buf *dst_buf_info, *src_buf_info;
+	struct vb2_v4l2_buffer *dst_vb2_v4l2, *src_vb2_v4l2;
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	if (src_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] src_buf empty!!", ctx->id);
+		return;
+	}
+
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	if (dst_buf == NULL) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_debug(1, "[%d] dst_buf empty!!", ctx->id);
+		return;
+	}
+
+	src_vb2_v4l2 = container_of(src_buf, struct vb2_v4l2_buffer, vb2_buf);
+	src_buf_info = container_of(src_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	dst_vb2_v4l2 = container_of(dst_buf, struct vb2_v4l2_buffer, vb2_buf);
+	dst_buf_info = container_of(dst_vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	buf.va = vb2_plane_vaddr(src_buf, 0);
+	buf.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+	buf.size = (size_t)src_buf->planes[0].bytesused;
+	if (!buf.va) {
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		mtk_v4l2_err("[%d] id=%d src_addr is NULL!!",
+				ctx->id, src_buf->index);
+		return;
+	}
+
+	pfb = &dst_buf_info->frame_buffer;
+	pfb->base_y.va = vb2_plane_vaddr(dst_buf, 0);
+	pfb->base_y.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+	pfb->base_y.size = ctx->picinfo.y_bs_sz + ctx->picinfo.y_len_sz;
+
+	pfb->base_c.va = vb2_plane_vaddr(dst_buf, 1);
+	pfb->base_c.dma_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 1);
+	pfb->base_c.size = ctx->picinfo.c_bs_sz + ctx->picinfo.c_len_sz;
+	pfb->status = 0;
+	mtk_v4l2_debug(3, "===>[%d] vdec_if_decode() ===>", ctx->id);
+	mtk_v4l2_debug(3, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p",
+			ctx->id, buf.va, &buf.dma_addr, buf.size, src_buf);
+
+	mtk_v4l2_debug(3,
+			"id=%d Framebuf  pfb=%p VA=%p Y_DMA=%pad C_DMA=%pad Size=%zx",
+			dst_buf->index, pfb,
+			pfb->base_y.va, &pfb->base_y.dma_addr,
+			&pfb->base_c.dma_addr, pfb->base_y.size);
+
+	if (src_buf_info->lastframe) {
+		/* update src buf status */
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		src_buf_info->lastframe = false;
+		v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
+
+		/* update dst buf status */
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+		dst_buf_info->used = false;
+
+		vdec_if_decode(ctx, NULL, NULL, &res_chg);
+		clean_display_buffer(ctx);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 0, 0);
+		vb2_set_plane_payload(&dst_buf_info->vb.vb2_buf, 1, 0);
+		v4l2_m2m_buf_done(&dst_buf_info->vb, VB2_BUF_STATE_DONE);
+		clean_free_buffer(ctx);
+		v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+		return;
+	}
+	dst_buf_info->vb.vb2_buf.timestamp
+			= src_buf_info->vb.vb2_buf.timestamp;
+	dst_buf_info->vb.timecode
+			= src_buf_info->vb.timecode;
+	mutex_lock(&ctx->lock);
+	dst_buf_info->used = true;
+	mutex_unlock(&ctx->lock);
+	src_buf_info->used = true;
+
+	ret = vdec_if_decode(ctx, &buf, pfb, &res_chg);
+
+	if (ret) {
+		mtk_v4l2_err(
+			" <===[%d], src_buf[%d]%d sz=0x%zx pts=%llu dst_buf[%d] vdec_if_decode() ret=%d res_chg=%d===>",
+			ctx->id,
+			src_buf->index,
+			src_buf_info->lastframe,
+			buf.size,
+			src_buf_info->vb.vb2_buf.timestamp,
+			dst_buf->index,
+			ret, res_chg);
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_ERROR);
+	} else if (res_chg == false) {
+		/*
+		 * we only return src buffer with VB2_BUF_STATE_DONE
+		 * when decode success without resolution change
+		 */
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(&src_buf_info->vb, VB2_BUF_STATE_DONE);
+	}
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+	clean_display_buffer(ctx);
+	clean_free_buffer(ctx);
+
+	if (!ret && res_chg) {
+		mtk_vdec_pic_info_update(ctx);
+		/*
+		 * On encountering a resolution change in the stream.
+		 * The driver must first process and decode all
+		 * remaining buffers from before the resolution change
+		 * point, so call flush decode here
+		 */
+		mtk_vdec_flush_decoder(ctx);
+		/*
+		 * After all buffers containing decoded frames from
+		 * before the resolution change point ready to be
+		 * dequeued on the CAPTURE queue, the driver sends a
+		 * V4L2_EVENT_SOURCE_CHANGE event for source change
+		 * type V4L2_EVENT_SRC_CH_RESOLUTION
+		 */
+		mtk_vdec_queue_res_chg_event(ctx);
+	}
+	v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+}
+
+void mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx)
+{
+	mutex_unlock(&ctx->dev->dec_mutex);
+}
+
+void mtk_vdec_lock(struct mtk_vcodec_ctx *ctx)
+{
+	mutex_lock(&ctx->dev->dec_mutex);
+}
+
+void mtk_vcodec_dec_release(struct mtk_vcodec_ctx *ctx)
+{
+	vdec_if_deinit(ctx);
+	ctx->state = MTK_STATE_FREE;
+}
+
+void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx)
+{
+	struct mtk_q_data *q_data;
+
+	ctx->m2m_ctx->q_lock = &ctx->dev->dev_mutex;
+	ctx->fh.m2m_ctx = ctx->m2m_ctx;
+	ctx->fh.ctrl_handler = &ctx->ctrl_hdl;
+	INIT_WORK(&ctx->decode_work, mtk_vdec_worker);
+	ctx->colorspace = V4L2_COLORSPACE_REC709;
+	ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_SRC];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &mtk_video_formats[OUT_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+
+	q_data->sizeimage[0] = DFT_CFG_WIDTH * DFT_CFG_HEIGHT;
+	q_data->bytesperline[0] = 0;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_DST];
+	memset(q_data, 0, sizeof(struct mtk_q_data));
+	q_data->visible_width = DFT_CFG_WIDTH;
+	q_data->visible_height = DFT_CFG_HEIGHT;
+	q_data->coded_width = DFT_CFG_WIDTH;
+	q_data->coded_height = DFT_CFG_HEIGHT;
+	q_data->fmt = &mtk_video_formats[CAP_FMT_IDX];
+	q_data->field = V4L2_FIELD_NONE;
+
+	v4l_bound_align_image(&q_data->coded_width,
+				MTK_VDEC_MIN_W,
+				MTK_VDEC_MAX_W, 4,
+				&q_data->coded_height,
+				MTK_VDEC_MIN_H,
+				MTK_VDEC_MAX_H, 5, 6);
+
+	q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
+	q_data->bytesperline[0] = q_data->coded_width;
+	q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
+	q_data->bytesperline[1] = q_data->coded_width;
+}
+
+static int vidioc_vdec_qbuf(struct file *file, void *priv,
+			    struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct vb2_queue *vq;
+	struct vb2_buffer *vb;
+	struct mtk_video_dec_buf *mtkbuf;
+	struct vb2_v4l2_buffer	*vb2_v4l2;
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on QBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
+	if (buf->index >= vq->num_buffers) {
+		mtk_v4l2_debug(1, "buffer index %d out of range", buf->index);
+		return -EINVAL;
+	}
+	vb = vq->bufs[buf->index];
+	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+	mtkbuf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+
+	if ((buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    (buf->m.planes[0].bytesused == 0)) {
+		mtkbuf->lastframe = true;
+		mtk_v4l2_debug(1, "[%d] (%d) id=%d lastframe=%d (%d,%d, %d) vb=%p",
+			 ctx->id, buf->type, buf->index,
+			 mtkbuf->lastframe, buf->bytesused,
+			 buf->m.planes[0].bytesused, buf->length,
+			 vb);
+	}
+
+	return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_vdec_dqbuf(struct file *file, void *priv,
+			     struct v4l2_buffer *buf)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (ctx->state == MTK_STATE_ABORT) {
+		mtk_v4l2_err("[%d] Call on DQBUF after unrecoverable error",
+				ctx->id);
+		return -EIO;
+	}
+
+	return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_vdec_querycap(struct file *file, void *priv,
+				struct v4l2_capability *cap)
+{
+	strlcpy(cap->driver, MTK_VCODEC_DEC_NAME, sizeof(cap->driver));
+	strlcpy(cap->bus_info, MTK_PLATFORM_STR, sizeof(cap->bus_info));
+	strlcpy(cap->card, MTK_PLATFORM_STR, sizeof(cap->card));
+
+	return 0;
+}
+
+static int vidioc_vdec_subscribe_evt(struct v4l2_fh *fh,
+				     const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 2, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return v4l2_src_change_event_subscribe(fh, sub);
+	default:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	}
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f, struct mtk_video_fmt *fmt)
+{
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+	int i;
+
+	pix_fmt_mp->field = V4L2_FIELD_NONE;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		pix_fmt_mp->num_planes = 1;
+		pix_fmt_mp->plane_fmt[0].bytesperline = 0;
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		int tmp_w, tmp_h;
+
+		pix_fmt_mp->height = clamp(pix_fmt_mp->height,
+					MTK_VDEC_MIN_H,
+					MTK_VDEC_MAX_H);
+		pix_fmt_mp->width = clamp(pix_fmt_mp->width,
+					MTK_VDEC_MIN_W,
+					MTK_VDEC_MAX_W);
+
+		/*
+		 * Find next closer width align 64, heign align 64, size align
+		 * 64 rectangle
+		 * Note: This only get default value, the real HW needed value
+		 *       only available when ctx in MTK_STATE_HEADER state
+		 */
+		tmp_w = pix_fmt_mp->width;
+		tmp_h = pix_fmt_mp->height;
+		v4l_bound_align_image(&pix_fmt_mp->width,
+					MTK_VDEC_MIN_W,
+					MTK_VDEC_MAX_W, 6,
+					&pix_fmt_mp->height,
+					MTK_VDEC_MIN_H,
+					MTK_VDEC_MAX_H, 6, 9);
+
+		if (pix_fmt_mp->width < tmp_w &&
+			(pix_fmt_mp->width + 64) <= MTK_VDEC_MAX_W)
+			pix_fmt_mp->width += 64;
+		if (pix_fmt_mp->height < tmp_h &&
+			(pix_fmt_mp->height + 64) <= MTK_VDEC_MAX_H)
+			pix_fmt_mp->height += 64;
+
+		mtk_v4l2_debug(0,
+			"before resize width=%d, height=%d, after resize width=%d, height=%d, sizeimage=%d",
+			tmp_w, tmp_h, pix_fmt_mp->width,
+			pix_fmt_mp->height,
+			pix_fmt_mp->width * pix_fmt_mp->height);
+
+		pix_fmt_mp->num_planes = fmt->num_planes;
+		pix_fmt_mp->plane_fmt[0].sizeimage =
+				pix_fmt_mp->width * pix_fmt_mp->height;
+		pix_fmt_mp->plane_fmt[0].bytesperline = pix_fmt_mp->width;
+
+		if (pix_fmt_mp->num_planes == 2) {
+			pix_fmt_mp->plane_fmt[1].sizeimage =
+				(pix_fmt_mp->width * pix_fmt_mp->height) / 2;
+			pix_fmt_mp->plane_fmt[1].bytesperline =
+				pix_fmt_mp->width;
+		}
+	}
+
+	for (i = 0; i < pix_fmt_mp->num_planes; i++)
+		memset(&(pix_fmt_mp->plane_fmt[i].reserved[0]), 0x0,
+			   sizeof(pix_fmt_mp->plane_fmt[0].reserved));
+
+	pix_fmt_mp->flags = 0;
+	memset(&pix_fmt_mp->reserved, 0x0, sizeof(pix_fmt_mp->reserved));
+	return 0;
+}
+
+static int vidioc_try_fmt_vid_cap_mplane(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct mtk_video_fmt *fmt;
+
+	fmt = mtk_vdec_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[CAP_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
+	}
+
+	return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_try_fmt_vid_out_mplane(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
+	struct mtk_video_fmt *fmt;
+
+	fmt = mtk_vdec_find_format(f);
+	if (!fmt) {
+		f->fmt.pix.pixelformat = mtk_video_formats[OUT_FMT_IDX].fourcc;
+		fmt = mtk_vdec_find_format(f);
+	}
+
+	if (pix_fmt_mp->plane_fmt[0].sizeimage == 0) {
+		mtk_v4l2_err("sizeimage of output format must be given");
+		return -EINVAL;
+	}
+
+	return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_vdec_g_selection(struct file *file, void *priv,
+			struct v4l2_selection *s)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct mtk_q_data *q_data;
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	q_data = &ctx->q_data[MTK_Q_DATA_DST];
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.pic_w;
+		s->r.height = ctx->picinfo.pic_h;
+		break;
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.buf_w;
+		s->r.height = ctx->picinfo.buf_h;
+		break;
+	case V4L2_SEL_TGT_COMPOSE:
+		if (vdec_if_get_param(ctx, GET_PARAM_CROP_INFO, &(s->r))) {
+			/* set to default value if header info not ready yet*/
+			s->r.left = 0;
+			s->r.top = 0;
+			s->r.width = q_data->visible_width;
+			s->r.height = q_data->visible_height;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ctx->state < MTK_STATE_HEADER) {
+		/* set to default value if header info not ready yet*/
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = q_data->visible_width;
+		s->r.height = q_data->visible_height;
+		return 0;
+	}
+
+	return 0;
+}
+
+static int vidioc_vdec_s_selection(struct file *file, void *priv,
+				struct v4l2_selection *s)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->picinfo.pic_w;
+		s->r.height = ctx->picinfo.pic_h;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vidioc_vdec_s_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp;
+	struct mtk_q_data *q_data;
+	int ret = 0;
+	struct mtk_video_fmt *fmt;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	q_data = mtk_vdec_get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	pix_mp = &f->fmt.pix_mp;
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) &&
+	    vb2_is_busy(&ctx->m2m_ctx->out_q_ctx.q)) {
+		mtk_v4l2_err("out_q_ctx buffers already requested");
+		ret = -EBUSY;
+	}
+
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+	    vb2_is_busy(&ctx->m2m_ctx->cap_q_ctx.q)) {
+		mtk_v4l2_err("cap_q_ctx buffers already requested");
+		ret = -EBUSY;
+	}
+
+	fmt = mtk_vdec_find_format(f);
+	if (fmt == NULL) {
+		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+			f->fmt.pix.pixelformat =
+				mtk_video_formats[OUT_FMT_IDX].fourcc;
+			fmt = mtk_vdec_find_format(f);
+		} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+			f->fmt.pix.pixelformat =
+				mtk_video_formats[CAP_FMT_IDX].fourcc;
+			fmt = mtk_vdec_find_format(f);
+		}
+	}
+
+	q_data->fmt = fmt;
+	vidioc_try_fmt(f, q_data->fmt);
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+		q_data->coded_width = pix_mp->width;
+		q_data->coded_height = pix_mp->height;
+
+		ctx->colorspace = f->fmt.pix_mp.colorspace;
+		ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+		ctx->quantization = f->fmt.pix_mp.quantization;
+		ctx->xfer_func = f->fmt.pix_mp.xfer_func;
+
+		if (ctx->state == MTK_STATE_FREE) {
+			ret = vdec_if_init(ctx, q_data->fmt->fourcc);
+			if (ret) {
+				mtk_v4l2_err("[%d]: vdec_if_init() fail ret=%d",
+					ctx->id, ret);
+				return -EINVAL;
+			}
+			ctx->state = MTK_STATE_INIT;
+		}
+	}
+
+	return 0;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+				struct v4l2_frmsizeenum *fsize)
+{
+	int i = 0;
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	for (i = 0; i < NUM_SUPPORTED_FRAMESIZE; ++i) {
+		if (fsize->pixel_format != mtk_vdec_framesizes[i].fourcc)
+			continue;
+
+		fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+		fsize->stepwise = mtk_vdec_framesizes[i].stepwise;
+		if (!(ctx->dev->dec_capability &
+				VCODEC_CAPABILITY_4K_DISABLED)) {
+			mtk_v4l2_debug(3, "4K is enabled");
+			fsize->stepwise.max_width =
+					VCODEC_DEC_4K_CODED_WIDTH;
+			fsize->stepwise.max_height =
+					VCODEC_DEC_4K_CODED_HEIGHT;
+		}
+		mtk_v4l2_debug(1, "%x, %d %d %d %d %d %d",
+				ctx->dev->dec_capability,
+				fsize->stepwise.min_width,
+				fsize->stepwise.max_width,
+				fsize->stepwise.step_width,
+				fsize->stepwise.min_height,
+				fsize->stepwise.max_height,
+				fsize->stepwise.step_height);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int vidioc_enum_fmt(struct v4l2_fmtdesc *f, bool output_queue)
+{
+	struct mtk_video_fmt *fmt;
+	int i, j = 0;
+
+	for (i = 0; i < NUM_FORMATS; i++) {
+		if (output_queue && (mtk_video_formats[i].type != MTK_FMT_DEC))
+			continue;
+		if (!output_queue &&
+			(mtk_video_formats[i].type != MTK_FMT_FRAME))
+			continue;
+
+		if (j == f->index)
+			break;
+		++j;
+	}
+
+	if (i == NUM_FORMATS)
+		return -EINVAL;
+
+	fmt = &mtk_video_formats[i];
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int vidioc_vdec_enum_fmt_vid_cap_mplane(struct file *file, void *pirv,
+					       struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, false);
+}
+
+static int vidioc_vdec_enum_fmt_vid_out_mplane(struct file *file, void *priv,
+					       struct v4l2_fmtdesc *f)
+{
+	return vidioc_enum_fmt(f, true);
+}
+
+static int vidioc_vdec_g_fmt(struct file *file, void *priv,
+			     struct v4l2_format *f)
+{
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct vb2_queue *vq;
+	struct mtk_q_data *q_data;
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+	if (!vq) {
+		mtk_v4l2_err("no vb2 queue for type=%d", f->type);
+		return -EINVAL;
+	}
+
+	q_data = mtk_vdec_get_q_data(ctx, f->type);
+
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->colorspace = ctx->colorspace;
+	pix_mp->ycbcr_enc = ctx->ycbcr_enc;
+	pix_mp->quantization = ctx->quantization;
+	pix_mp->xfer_func = ctx->xfer_func;
+
+	if ((f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+	    (ctx->state >= MTK_STATE_HEADER)) {
+		/* Until STREAMOFF is called on the CAPTURE queue
+		 * (acknowledging the event), the driver operates as if
+		 * the resolution hasn't changed yet.
+		 * So we just return picinfo yet, and update picinfo in
+		 * stop_streaming hook function
+		 */
+		q_data->sizeimage[0] = ctx->picinfo.y_bs_sz +
+					ctx->picinfo.y_len_sz;
+		q_data->sizeimage[1] = ctx->picinfo.c_bs_sz +
+					ctx->picinfo.c_len_sz;
+		q_data->bytesperline[0] = ctx->last_decoded_picinfo.buf_w;
+		q_data->bytesperline[1] = ctx->last_decoded_picinfo.buf_w;
+		q_data->coded_width = ctx->picinfo.buf_w;
+		q_data->coded_height = ctx->picinfo.buf_h;
+
+		/*
+		 * Width and height are set to the dimensions
+		 * of the movie, the buffer is bigger and
+		 * further processing stages should crop to this
+		 * rectangle.
+		 */
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
+
+		/*
+		 * Set pixelformat to the format in which mt vcodec
+		 * outputs the decoded frame
+		 */
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		/*
+		 * This is run on OUTPUT
+		 * The buffer contains compressed image
+		 * so width and height have no meaning.
+		 * Assign value here to pass v4l2-compliance test
+		 */
+		pix_mp->width = q_data->visible_width;
+		pix_mp->height = q_data->visible_height;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->num_planes = q_data->fmt->num_planes;
+	} else {
+		pix_mp->width = q_data->coded_width;
+		pix_mp->height = q_data->coded_height;
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+		pix_mp->plane_fmt[1].bytesperline = q_data->bytesperline[1];
+		pix_mp->plane_fmt[1].sizeimage = q_data->sizeimage[1];
+
+		mtk_v4l2_debug(1, "[%d] type=%d state=%d Format information could not be read, not ready yet!",
+				ctx->id, f->type, ctx->state);
+	}
+
+	return 0;
+}
+
+static int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
+				unsigned int *nbuffers,
+				unsigned int *nplanes,
+				unsigned int sizes[],
+				struct device *alloc_devs[])
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct mtk_q_data *q_data;
+	unsigned int i;
+
+	q_data = mtk_vdec_get_q_data(ctx, vq->type);
+
+	if (q_data == NULL) {
+		mtk_v4l2_err("vq->type=%d err\n", vq->type);
+		return -EINVAL;
+	}
+
+	if (*nplanes) {
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < q_data->sizeimage[i])
+				return -EINVAL;
+		}
+	} else {
+		if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+			*nplanes = 2;
+		else
+			*nplanes = 1;
+
+		for (i = 0; i < *nplanes; i++)
+			sizes[i] = q_data->sizeimage[i];
+	}
+
+	mtk_v4l2_debug(1,
+			"[%d]\t type = %d, get %d plane(s), %d buffer(s) of size 0x%x 0x%x ",
+			ctx->id, vq->type, *nplanes, *nbuffers,
+			sizes[0], sizes[1]);
+
+	return 0;
+}
+
+static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct mtk_q_data *q_data;
+	int i;
+
+	mtk_v4l2_debug(3, "[%d] (%d) id=%d",
+			ctx->id, vb->vb2_queue->type, vb->index);
+
+	q_data = mtk_vdec_get_q_data(ctx, vb->vb2_queue->type);
+
+	for (i = 0; i < q_data->fmt->num_planes; i++) {
+		if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) {
+			mtk_v4l2_err("data will not fit into plane %d (%lu < %d)",
+				i, vb2_plane_size(vb, i),
+				q_data->sizeimage[i]);
+		}
+	}
+
+	return 0;
+}
+
+static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_buffer *src_buf;
+	struct mtk_vcodec_mem src_mem;
+	bool res_chg = false;
+	int ret = 0;
+	unsigned int dpbsize = 1;
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+				struct vb2_v4l2_buffer, vb2_buf);
+	struct mtk_video_dec_buf *buf = container_of(vb2_v4l2,
+				struct mtk_video_dec_buf, vb);
+
+	mtk_v4l2_debug(3, "[%d] (%d) id=%d, vb=%p",
+			ctx->id, vb->vb2_queue->type,
+			vb->index, vb);
+	/*
+	 * check if this buffer is ready to be used after decode
+	 */
+	if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		mutex_lock(&ctx->lock);
+		if (buf->used == false) {
+			v4l2_m2m_buf_queue(ctx->m2m_ctx,
+					to_vb2_v4l2_buffer(vb));
+			buf->queued_in_vb2 = true;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		} else {
+			buf->queued_in_vb2 = false;
+			buf->queued_in_v4l2 = true;
+			buf->ready_to_display = false;
+		}
+		mutex_unlock(&ctx->lock);
+		return;
+	}
+
+	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
+
+	if (ctx->state != MTK_STATE_INIT) {
+		mtk_v4l2_debug(3, "[%d] already init driver %d",
+				ctx->id, ctx->state);
+		return;
+	}
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+	if (!src_buf) {
+		mtk_v4l2_err("No src buffer");
+		return;
+	}
+
+	src_mem.va = vb2_plane_vaddr(src_buf, 0);
+	src_mem.dma_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+	src_mem.size = (size_t)src_buf->planes[0].bytesused;
+	mtk_v4l2_debug(2,
+			"[%d] buf id=%d va=%p dma=%pad size=%zx",
+			ctx->id, src_buf->index,
+			src_mem.va, &src_mem.dma_addr,
+			src_mem.size);
+
+	ret = vdec_if_decode(ctx, &src_mem, NULL, &res_chg);
+	if (ret || !res_chg) {
+		/*
+		 * fb == NULL menas to parse SPS/PPS header or
+		 * resolution info in src_mem. Decode can fail
+		 * if there is no SPS header or picture info
+		 * in bs
+		 */
+		int log_level = ret ? 0 : 1;
+
+		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+					VB2_BUF_STATE_DONE);
+		mtk_v4l2_debug(log_level,
+				"[%d] vdec_if_decode() src_buf=%d, size=%zu, fail=%d, res_chg=%d",
+				ctx->id, src_buf->index,
+				src_mem.size, ret, res_chg);
+		return;
+	}
+
+	if (vdec_if_get_param(ctx, GET_PARAM_PIC_INFO, &ctx->picinfo)) {
+		mtk_v4l2_err("[%d]Error!! Cannot get param : GET_PARAM_PICTURE_INFO ERR",
+				ctx->id);
+		return;
+	}
+
+	ctx->last_decoded_picinfo = ctx->picinfo;
+	ctx->q_data[MTK_Q_DATA_DST].sizeimage[0] =
+						ctx->picinfo.y_bs_sz +
+						ctx->picinfo.y_len_sz;
+	ctx->q_data[MTK_Q_DATA_DST].bytesperline[0] =
+						ctx->picinfo.buf_w;
+	ctx->q_data[MTK_Q_DATA_DST].sizeimage[1] =
+						ctx->picinfo.c_bs_sz +
+						ctx->picinfo.c_len_sz;
+	ctx->q_data[MTK_Q_DATA_DST].bytesperline[1] = ctx->picinfo.buf_w;
+	mtk_v4l2_debug(2, "[%d] vdec_if_init() OK wxh=%dx%d pic wxh=%dx%d sz[0]=0x%x sz[1]=0x%x",
+			ctx->id,
+			ctx->picinfo.buf_w, ctx->picinfo.buf_h,
+			ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[0],
+			ctx->q_data[MTK_Q_DATA_DST].sizeimage[1]);
+
+	ret = vdec_if_get_param(ctx, GET_PARAM_DPB_SIZE, &dpbsize);
+	if (dpbsize == 0)
+		mtk_v4l2_err("[%d] GET_PARAM_DPB_SIZE fail=%d", ctx->id, ret);
+
+	ctx->dpb_size = dpbsize;
+	ctx->state = MTK_STATE_HEADER;
+	mtk_v4l2_debug(1, "[%d] dpbsize=%d", ctx->id, ctx->dpb_size);
+}
+
+static void vb2ops_vdec_buf_finish(struct vb2_buffer *vb)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2;
+	struct mtk_video_dec_buf *buf;
+
+	if (vb->vb2_queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return;
+
+	vb2_v4l2 = container_of(vb, struct vb2_v4l2_buffer, vb2_buf);
+	buf = container_of(vb2_v4l2, struct mtk_video_dec_buf, vb);
+	mutex_lock(&ctx->lock);
+	buf->queued_in_v4l2 = false;
+	buf->queued_in_vb2 = false;
+	mutex_unlock(&ctx->lock);
+}
+
+static int vb2ops_vdec_buf_init(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vb2_v4l2 = container_of(vb,
+					struct vb2_v4l2_buffer, vb2_buf);
+	struct mtk_video_dec_buf *buf = container_of(vb2_v4l2,
+					struct mtk_video_dec_buf, vb);
+
+	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		buf->used = false;
+		buf->ready_to_display = false;
+		buf->queued_in_v4l2 = false;
+	} else {
+		buf->lastframe = false;
+	}
+
+	return 0;
+}
+
+static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+
+	if (ctx->state == MTK_STATE_FLUSH)
+		ctx->state = MTK_STATE_HEADER;
+
+	return 0;
+}
+
+static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
+{
+	struct vb2_buffer *src_buf = NULL, *dst_buf = NULL;
+	struct mtk_vcodec_ctx *ctx = vb2_get_drv_priv(q);
+
+	mtk_v4l2_debug(3, "[%d] (%d) state=(%x) ctx->decoded_frame_cnt=%d",
+			ctx->id, q->type, ctx->state, ctx->decoded_frame_cnt);
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
+			v4l2_m2m_buf_done(to_vb2_v4l2_buffer(src_buf),
+					VB2_BUF_STATE_ERROR);
+		return;
+	}
+
+	if (ctx->state >= MTK_STATE_HEADER) {
+
+		/* Until STREAMOFF is called on the CAPTURE queue
+		 * (acknowledging the event), the driver operates
+		 * as if the resolution hasn't changed yet, i.e.
+		 * VIDIOC_G_FMT< etc. return previous resolution.
+		 * So we update picinfo here
+		 */
+		ctx->picinfo = ctx->last_decoded_picinfo;
+
+		mtk_v4l2_debug(2,
+				"[%d]-> new(%d,%d), old(%d,%d), real(%d,%d)",
+				ctx->id, ctx->last_decoded_picinfo.pic_w,
+				ctx->last_decoded_picinfo.pic_h,
+				ctx->picinfo.pic_w, ctx->picinfo.pic_h,
+				ctx->last_decoded_picinfo.buf_w,
+				ctx->last_decoded_picinfo.buf_h);
+
+		mtk_vdec_flush_decoder(ctx);
+	}
+	ctx->state = MTK_STATE_FLUSH;
+
+	while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx))) {
+		vb2_set_plane_payload(dst_buf, 0, 0);
+		vb2_set_plane_payload(dst_buf, 1, 0);
+		v4l2_m2m_buf_done(to_vb2_v4l2_buffer(dst_buf),
+					VB2_BUF_STATE_ERROR);
+	}
+
+}
+
+static void m2mops_vdec_device_run(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	struct mtk_vcodec_dev *dev = ctx->dev;
+
+	queue_work(dev->decode_workqueue, &ctx->decode_work);
+}
+
+static int m2mops_vdec_job_ready(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	if (ctx->state == MTK_STATE_ABORT)
+		return 0;
+
+	if ((ctx->last_decoded_picinfo.pic_w != ctx->picinfo.pic_w) ||
+	    (ctx->last_decoded_picinfo.pic_h != ctx->picinfo.pic_h))
+		return 0;
+
+	if (ctx->state != MTK_STATE_HEADER)
+		return 0;
+
+	return 1;
+}
+
+static void m2mops_vdec_job_abort(void *priv)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+
+	ctx->state = MTK_STATE_ABORT;
+}
+
+static int mtk_vdec_g_v_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct mtk_vcodec_ctx *ctx = ctrl_to_ctx(ctrl);
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+		if (ctx->state >= MTK_STATE_HEADER) {
+			ctrl->val = ctx->dpb_size;
+		} else {
+			mtk_v4l2_debug(0, "Seqinfo not ready");
+			ctrl->val = 0;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops mtk_vcodec_dec_ctrl_ops = {
+	.g_volatile_ctrl = mtk_vdec_g_v_ctrl,
+};
+
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx)
+{
+	struct v4l2_ctrl *ctrl;
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_hdl, 1);
+
+	ctrl = v4l2_ctrl_new_std(&ctx->ctrl_hdl,
+				&mtk_vcodec_dec_ctrl_ops,
+				V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+				0, 32, 1, 1);
+	ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	if (ctx->ctrl_hdl.error) {
+		mtk_v4l2_err("Adding control failed %d",
+				ctx->ctrl_hdl.error);
+		return ctx->ctrl_hdl.error;
+	}
+
+	v4l2_ctrl_handler_setup(&ctx->ctrl_hdl);
+	return 0;
+}
+
+static void m2mops_vdec_lock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	mutex_lock(&ctx->dev->dev_mutex);
+}
+
+static void m2mops_vdec_unlock(void *m2m_priv)
+{
+	struct mtk_vcodec_ctx *ctx = m2m_priv;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+	mutex_unlock(&ctx->dev->dev_mutex);
+}
+
+const struct v4l2_m2m_ops mtk_vdec_m2m_ops = {
+	.device_run	= m2mops_vdec_device_run,
+	.job_ready	= m2mops_vdec_job_ready,
+	.job_abort	= m2mops_vdec_job_abort,
+	.lock		= m2mops_vdec_lock,
+	.unlock		= m2mops_vdec_unlock,
+};
+
+static const struct vb2_ops mtk_vdec_vb2_ops = {
+	.queue_setup	= vb2ops_vdec_queue_setup,
+	.buf_prepare	= vb2ops_vdec_buf_prepare,
+	.buf_queue	= vb2ops_vdec_buf_queue,
+	.wait_prepare	= vb2_ops_wait_prepare,
+	.wait_finish	= vb2_ops_wait_finish,
+	.buf_init	= vb2ops_vdec_buf_init,
+	.buf_finish	= vb2ops_vdec_buf_finish,
+	.start_streaming	= vb2ops_vdec_start_streaming,
+	.stop_streaming	= vb2ops_vdec_stop_streaming,
+};
+
+const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops = {
+	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
+	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
+	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_qbuf		= vidioc_vdec_qbuf,
+	.vidioc_dqbuf		= vidioc_vdec_dqbuf,
+
+	.vidioc_try_fmt_vid_cap_mplane	= vidioc_try_fmt_vid_cap_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= vidioc_try_fmt_vid_out_mplane,
+
+	.vidioc_s_fmt_vid_cap_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_s_fmt_vid_out_mplane	= vidioc_vdec_s_fmt,
+	.vidioc_g_fmt_vid_cap_mplane	= vidioc_vdec_g_fmt,
+	.vidioc_g_fmt_vid_out_mplane	= vidioc_vdec_g_fmt,
+
+	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
+
+	.vidioc_enum_fmt_vid_cap_mplane	= vidioc_vdec_enum_fmt_vid_cap_mplane,
+	.vidioc_enum_fmt_vid_out_mplane	= vidioc_vdec_enum_fmt_vid_out_mplane,
+	.vidioc_enum_framesizes	= vidioc_enum_framesizes,
+
+	.vidioc_querycap		= vidioc_vdec_querycap,
+	.vidioc_subscribe_event		= vidioc_vdec_subscribe_evt,
+	.vidioc_unsubscribe_event	= v4l2_event_unsubscribe,
+	.vidioc_g_selection             = vidioc_vdec_g_selection,
+	.vidioc_s_selection             = vidioc_vdec_s_selection,
+};
+
+int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq)
+{
+	struct mtk_vcodec_ctx *ctx = priv;
+	int ret = 0;
+
+	mtk_v4l2_debug(3, "[%d]", ctx->id);
+
+	src_vq->type		= V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
+	src_vq->drv_priv	= ctx;
+	src_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
+	src_vq->ops		= &mtk_vdec_vb2_ops;
+	src_vq->mem_ops		= &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock		= &ctx->dev->dev_mutex;
+	src_vq->dev             = &ctx->dev->plat_dev->dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret) {
+		mtk_v4l2_err("Failed to initialize videobuf2 queue(output)");
+		return ret;
+	}
+	dst_vq->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes	= VB2_DMABUF | VB2_MMAP;
+	dst_vq->drv_priv	= ctx;
+	dst_vq->buf_struct_size = sizeof(struct mtk_video_dec_buf);
+	dst_vq->ops		= &mtk_vdec_vb2_ops;
+	dst_vq->mem_ops		= &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock		= &ctx->dev->dev_mutex;
+	dst_vq->dev             = &ctx->dev->plat_dev->dev;
+
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		mtk_v4l2_err("Failed to initialize videobuf2 queue(capture)");
+	}
+
+	return ret;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *         Tiffany Lin <tiffany.lin@mediatek.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/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_intr.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+#define VDEC_HW_ACTIVE	0x10
+#define VDEC_IRQ_CFG	0x11
+#define VDEC_IRQ_CLR	0x10
+#define VDEC_IRQ_CFG_REG	0xa4
+
+module_param(mtk_v4l2_dbg_level, int, 0644);
+module_param(mtk_vcodec_dbg, bool, 0644);
+
+/* Wake up context wait_queue */
+static void wake_up_ctx(struct mtk_vcodec_ctx *ctx)
+{
+	ctx->int_cond = 1;
+	wake_up_interruptible(&ctx->queue);
+}
+
+static irqreturn_t mtk_vcodec_dec_irq_handler(int irq, void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+	u32 cg_status = 0;
+	unsigned int dec_done_status = 0;
+	void __iomem *vdec_misc_addr = dev->reg_base[VDEC_MISC] +
+					VDEC_IRQ_CFG_REG;
+
+	ctx = mtk_vcodec_get_curr_ctx(dev);
+
+	/* check if HW active or not */
+	cg_status = readl(dev->reg_base[0]);
+	if ((cg_status & VDEC_HW_ACTIVE) != 0) {
+		mtk_v4l2_err("DEC ISR, VDEC active is not 0x0 (0x%08x)",
+			     cg_status);
+		return IRQ_HANDLED;
+	}
+
+	dec_done_status = readl(vdec_misc_addr);
+	ctx->irq_status = dec_done_status;
+	if ((dec_done_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS) !=
+		MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+		return IRQ_HANDLED;
+
+	/* clear interrupt */
+	writel((readl(vdec_misc_addr) | VDEC_IRQ_CFG),
+		dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
+	writel((readl(vdec_misc_addr) & ~VDEC_IRQ_CLR),
+		dev->reg_base[VDEC_MISC] + VDEC_IRQ_CFG_REG);
+
+	wake_up_ctx(ctx);
+
+	mtk_v4l2_debug(3,
+			"mtk_vcodec_dec_irq_handler :wake up ctx %d, dec_done_status=%x",
+			ctx->id, dec_done_status);
+
+	return IRQ_HANDLED;
+}
+
+static void mtk_vcodec_dec_reset_handler(void *priv)
+{
+	struct mtk_vcodec_dev *dev = priv;
+	struct mtk_vcodec_ctx *ctx;
+
+	mtk_v4l2_err("Watchdog timeout!!");
+
+	mutex_lock(&dev->dev_mutex);
+	list_for_each_entry(ctx, &dev->ctx_list, list) {
+		ctx->state = MTK_STATE_ABORT;
+		mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ERROR",
+				ctx->id);
+	}
+	mutex_unlock(&dev->dev_mutex);
+}
+
+static int fops_vcodec_open(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = NULL;
+	int ret = 0;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mutex_lock(&dev->dev_mutex);
+	ctx->id = dev->id_counter++;
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
+	INIT_LIST_HEAD(&ctx->list);
+	ctx->dev = dev;
+	init_waitqueue_head(&ctx->queue);
+	mutex_init(&ctx->lock);
+
+	ctx->type = MTK_INST_DECODER;
+	ret = mtk_vcodec_dec_ctrls_setup(ctx);
+	if (ret) {
+		mtk_v4l2_err("Failed to setup mt vcodec controls");
+		goto err_ctrls_setup;
+	}
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx,
+		&mtk_vcodec_dec_queue_init);
+	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
+		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
+		mtk_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)",
+			ret);
+		goto err_m2m_ctx_init;
+	}
+	mtk_vcodec_dec_set_default_params(ctx);
+
+	if (v4l2_fh_is_singular(&ctx->fh)) {
+		mtk_vcodec_dec_pw_on(&dev->pm);
+		/*
+		 * vpu_load_firmware checks if it was loaded already and
+		 * does nothing in that case
+		 */
+		ret = vpu_load_firmware(dev->vpu_plat_dev);
+		if (ret < 0) {
+			/*
+			 * Return 0 if downloading firmware successfully,
+			 * otherwise it is failed
+			 */
+			mtk_v4l2_err("vpu_load_firmware failed!");
+			goto err_load_fw;
+		}
+
+		dev->dec_capability =
+			vpu_get_vdec_hw_capa(dev->vpu_plat_dev);
+		mtk_v4l2_debug(0, "decoder capability %x", dev->dec_capability);
+	}
+
+	list_add(&ctx->list, &dev->ctx_list);
+
+	mutex_unlock(&dev->dev_mutex);
+	mtk_v4l2_debug(0, "%s decoder [%d]", dev_name(&dev->plat_dev->dev),
+			ctx->id);
+	return ret;
+
+	/* Deinit when failure occurred */
+err_load_fw:
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+err_m2m_ctx_init:
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+err_ctrls_setup:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+
+	return ret;
+}
+
+static int fops_vcodec_release(struct file *file)
+{
+	struct mtk_vcodec_dev *dev = video_drvdata(file);
+	struct mtk_vcodec_ctx *ctx = fh_to_ctx(file->private_data);
+
+	mtk_v4l2_debug(0, "[%d] decoder", ctx->id);
+	mutex_lock(&dev->dev_mutex);
+
+	/*
+	 * Call v4l2_m2m_ctx_release before mtk_vcodec_dec_release. First, it
+	 * makes sure the worker thread is not running after vdec_if_deinit.
+	 * Second, the decoder will be flushed and all the buffers will be
+	 * returned in stop_streaming.
+	 */
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	mtk_vcodec_dec_release(ctx);
+
+	if (v4l2_fh_is_singular(&ctx->fh))
+		mtk_vcodec_dec_pw_off(&dev->pm);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+
+	list_del_init(&ctx->list);
+	kfree(ctx);
+	mutex_unlock(&dev->dev_mutex);
+	return 0;
+}
+
+static const struct v4l2_file_operations mtk_vcodec_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fops_vcodec_open,
+	.release	= fops_vcodec_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static int mtk_vcodec_probe(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev;
+	struct video_device *vfd_dec;
+	struct resource *res;
+	int i, ret;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&dev->ctx_list);
+	dev->plat_dev = pdev;
+
+	dev->vpu_plat_dev = vpu_get_plat_device(dev->plat_dev);
+	if (dev->vpu_plat_dev == NULL) {
+		mtk_v4l2_err("[VPU] vpu device in not ready");
+		return -EPROBE_DEFER;
+	}
+
+	vpu_wdt_reg_handler(dev->vpu_plat_dev, mtk_vcodec_dec_reset_handler,
+			dev, VPU_RST_DEC);
+
+	ret = mtk_vcodec_init_dec_pm(dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to get mt vcodec clock source");
+		return ret;
+	}
+
+	for (i = 0; i < NUM_MAX_VDEC_REG_BASE; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (res == NULL) {
+			dev_err(&pdev->dev, "get memory resource failed.");
+			ret = -ENXIO;
+			goto err_res;
+		}
+		dev->reg_base[i] = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR((__force void *)dev->reg_base[i])) {
+			ret = PTR_ERR((__force void *)dev->reg_base[i]);
+			goto err_res;
+		}
+		mtk_v4l2_debug(2, "reg[%d] base=%p", i, dev->reg_base[i]);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get irq resource");
+		ret = -ENOENT;
+		goto err_res;
+	}
+
+	dev->dec_irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(&pdev->dev, dev->dec_irq,
+			mtk_vcodec_dec_irq_handler, 0, pdev->name, dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to install dev->dec_irq %d (%d)",
+			dev->dec_irq,
+			ret);
+		goto err_res;
+	}
+
+	disable_irq(dev->dec_irq);
+	mutex_init(&dev->dec_mutex);
+	mutex_init(&dev->dev_mutex);
+	spin_lock_init(&dev->irqlock);
+
+	snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
+		"[/MTK_V4L2_VDEC]");
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		mtk_v4l2_err("v4l2_device_register err=%d", ret);
+		goto err_res;
+	}
+
+	init_waitqueue_head(&dev->queue);
+
+	vfd_dec = video_device_alloc();
+	if (!vfd_dec) {
+		mtk_v4l2_err("Failed to allocate video device");
+		ret = -ENOMEM;
+		goto err_dec_alloc;
+	}
+	vfd_dec->fops		= &mtk_vcodec_fops;
+	vfd_dec->ioctl_ops	= &mtk_vdec_ioctl_ops;
+	vfd_dec->release	= video_device_release;
+	vfd_dec->lock		= &dev->dev_mutex;
+	vfd_dec->v4l2_dev	= &dev->v4l2_dev;
+	vfd_dec->vfl_dir	= VFL_DIR_M2M;
+	vfd_dec->device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE |
+			V4L2_CAP_STREAMING;
+
+	snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
+		MTK_VCODEC_DEC_NAME);
+	video_set_drvdata(vfd_dec, dev);
+	dev->vfd_dec = vfd_dec;
+	platform_set_drvdata(pdev, dev);
+
+	dev->m2m_dev_dec = v4l2_m2m_init(&mtk_vdec_m2m_ops);
+	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
+		mtk_v4l2_err("Failed to init mem2mem dec device");
+		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
+		goto err_dec_mem_init;
+	}
+
+	dev->decode_workqueue =
+		alloc_ordered_workqueue(MTK_VCODEC_DEC_NAME,
+			WQ_MEM_RECLAIM | WQ_FREEZABLE);
+	if (!dev->decode_workqueue) {
+		mtk_v4l2_err("Failed to create decode workqueue");
+		ret = -EINVAL;
+		goto err_event_workq;
+	}
+
+	ret = video_register_device(vfd_dec, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		mtk_v4l2_err("Failed to register video device");
+		goto err_dec_reg;
+	}
+
+	mtk_v4l2_debug(0, "decoder registered as /dev/video%d",
+		vfd_dec->num);
+
+	return 0;
+
+err_dec_reg:
+	destroy_workqueue(dev->decode_workqueue);
+err_event_workq:
+	v4l2_m2m_release(dev->m2m_dev_dec);
+err_dec_mem_init:
+	video_unregister_device(vfd_dec);
+err_dec_alloc:
+	v4l2_device_unregister(&dev->v4l2_dev);
+err_res:
+	mtk_vcodec_release_dec_pm(dev);
+	return ret;
+}
+
+static const struct of_device_id mtk_vcodec_match[] = {
+	{.compatible = "mediatek,mt8173-vcodec-dec",},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mtk_vcodec_match);
+
+static int mtk_vcodec_dec_remove(struct platform_device *pdev)
+{
+	struct mtk_vcodec_dev *dev = platform_get_drvdata(pdev);
+
+	flush_workqueue(dev->decode_workqueue);
+	destroy_workqueue(dev->decode_workqueue);
+	if (dev->m2m_dev_dec)
+		v4l2_m2m_release(dev->m2m_dev_dec);
+
+	if (dev->vfd_dec)
+		video_unregister_device(dev->vfd_dec);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+	mtk_vcodec_release_dec_pm(dev);
+	return 0;
+}
+
+static struct platform_driver mtk_vcodec_dec_driver = {
+	.probe	= mtk_vcodec_probe,
+	.remove	= mtk_vcodec_dec_remove,
+	.driver	= {
+		.name	= MTK_VCODEC_DEC_NAME,
+		.of_match_table = mtk_vcodec_match,
+	},
+};
+
+module_platform_driver(mtk_vcodec_dec_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Mediatek video codec V4L2 decoder driver");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *         Tiffany Lin <tiffany.lin@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_VCODEC_DEC_H_
+#define _MTK_VCODEC_DEC_H_
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-v4l2.h>
+
+#define VCODEC_CAPABILITY_4K_DISABLED	0x10
+#define VCODEC_DEC_4K_CODED_WIDTH	4096U
+#define VCODEC_DEC_4K_CODED_HEIGHT	2304U
+#define MTK_VDEC_MAX_W	2048U
+#define MTK_VDEC_MAX_H	1088U
+
+#define MTK_VDEC_IRQ_STATUS_DEC_SUCCESS        0x10000
+
+/**
+ * struct vdec_fb  - decoder frame buffer
+ * @base_y	: Y plane memory info
+ * @base_c	: C plane memory info
+ * @status      : frame buffer status (vdec_fb_status)
+ */
+struct vdec_fb {
+	struct mtk_vcodec_mem	base_y;
+	struct mtk_vcodec_mem	base_c;
+	unsigned int	status;
+};
+
+/**
+ * struct mtk_video_dec_buf - Private data related to each VB2 buffer.
+ * @b:		VB2 buffer
+ * @list:	link list
+ * @used:	Capture buffer contain decoded frame data and keep in
+ *			codec data structure
+ * @ready_to_display:	Capture buffer not display yet
+ * @queued_in_vb2:	Capture buffer is queue in vb2
+ * @queued_in_v4l2:	Capture buffer is in v4l2 driver, but not in vb2
+ *			queue yet
+ * @lastframe:		Intput buffer is last buffer - EOS
+ * @frame_buffer:	Decode status, and buffer information of Capture buffer
+ *
+ * Note : These status information help us track and debug buffer state
+ */
+struct mtk_video_dec_buf {
+	struct vb2_v4l2_buffer	vb;
+	struct list_head	list;
+
+	bool	used;
+	bool	ready_to_display;
+	bool	queued_in_vb2;
+	bool	queued_in_v4l2;
+	bool	lastframe;
+	struct vdec_fb	frame_buffer;
+};
+
+extern const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops;
+extern const struct v4l2_m2m_ops mtk_vdec_m2m_ops;
+
+
+/*
+ * mtk_vdec_lock/mtk_vdec_unlock are for ctx instance to
+ * get/release lock before/after access decoder hw.
+ * mtk_vdec_lock get decoder hw lock and set curr_ctx
+ * to ctx instance that get lock
+ */
+void mtk_vdec_unlock(struct mtk_vcodec_ctx *ctx);
+void mtk_vdec_lock(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
+			   struct vb2_queue *dst_vq);
+void mtk_vcodec_dec_set_default_params(struct mtk_vcodec_ctx *ctx);
+void mtk_vcodec_dec_release(struct mtk_vcodec_ctx *ctx);
+int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx);
+
+
+#endif /* _MTK_VCODEC_DEC_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Tiffany Lin <tiffany.lin@mediatek.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/clk.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <soc/mediatek/smi.h>
+
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vcodec_util.h"
+#include "mtk_vpu.h"
+
+int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev)
+{
+	struct device_node *node;
+	struct platform_device *pdev;
+	struct mtk_vcodec_pm *pm;
+	int ret = 0;
+
+	pdev = mtkdev->plat_dev;
+	pm = &mtkdev->pm;
+	pm->mtkdev = mtkdev;
+	node = of_parse_phandle(pdev->dev.of_node, "mediatek,larb", 0);
+	if (!node) {
+		mtk_v4l2_err("of_parse_phandle mediatek,larb fail!");
+		return -1;
+	}
+
+	pdev = of_find_device_by_node(node);
+	if (WARN_ON(!pdev)) {
+		of_node_put(node);
+		return -1;
+	}
+	pm->larbvdec = &pdev->dev;
+	pdev = mtkdev->plat_dev;
+	pm->dev = &pdev->dev;
+
+	pm->vcodecpll = devm_clk_get(&pdev->dev, "vcodecpll");
+	if (IS_ERR(pm->vcodecpll)) {
+		mtk_v4l2_err("devm_clk_get vcodecpll fail");
+		ret = PTR_ERR(pm->vcodecpll);
+	}
+
+	pm->univpll_d2 = devm_clk_get(&pdev->dev, "univpll_d2");
+	if (IS_ERR(pm->univpll_d2)) {
+		mtk_v4l2_err("devm_clk_get univpll_d2 fail");
+		ret = PTR_ERR(pm->univpll_d2);
+	}
+
+	pm->clk_cci400_sel = devm_clk_get(&pdev->dev, "clk_cci400_sel");
+	if (IS_ERR(pm->clk_cci400_sel)) {
+		mtk_v4l2_err("devm_clk_get clk_cci400_sel fail");
+		ret = PTR_ERR(pm->clk_cci400_sel);
+	}
+
+	pm->vdec_sel = devm_clk_get(&pdev->dev, "vdec_sel");
+	if (IS_ERR(pm->vdec_sel)) {
+		mtk_v4l2_err("devm_clk_get vdec_sel fail");
+		ret = PTR_ERR(pm->vdec_sel);
+	}
+
+	pm->vdecpll = devm_clk_get(&pdev->dev, "vdecpll");
+	if (IS_ERR(pm->vdecpll)) {
+		mtk_v4l2_err("devm_clk_get vdecpll fail");
+		ret = PTR_ERR(pm->vdecpll);
+	}
+
+	pm->vencpll = devm_clk_get(&pdev->dev, "vencpll");
+	if (IS_ERR(pm->vencpll)) {
+		mtk_v4l2_err("devm_clk_get vencpll fail");
+		ret = PTR_ERR(pm->vencpll);
+	}
+
+	pm->venc_lt_sel = devm_clk_get(&pdev->dev, "venc_lt_sel");
+	if (IS_ERR(pm->venc_lt_sel)) {
+		mtk_v4l2_err("devm_clk_get venc_lt_sel fail");
+		ret = PTR_ERR(pm->venc_lt_sel);
+	}
+
+	pm->vdec_bus_clk_src = devm_clk_get(&pdev->dev, "vdec_bus_clk_src");
+	if (IS_ERR(pm->vdec_bus_clk_src)) {
+		mtk_v4l2_err("devm_clk_get vdec_bus_clk_src");
+		ret = PTR_ERR(pm->vdec_bus_clk_src);
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	return ret;
+}
+
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
+{
+	pm_runtime_disable(dev->pm.dev);
+}
+
+void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = pm_runtime_get_sync(pm->dev);
+	if (ret)
+		mtk_v4l2_err("pm_runtime_get_sync fail %d", ret);
+}
+
+void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = pm_runtime_put_sync(pm->dev);
+	if (ret)
+		mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
+}
+
+void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)
+{
+	int ret;
+
+	ret = clk_set_rate(pm->vcodecpll, 1482 * 1000000);
+	if (ret)
+		mtk_v4l2_err("clk_set_rate vcodecpll fail %d", ret);
+
+	ret = clk_set_rate(pm->vencpll, 800 * 1000000);
+	if (ret)
+		mtk_v4l2_err("clk_set_rate vencpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vcodecpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vcodecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vencpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vencpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdec_bus_clk_src);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdec_bus_clk_src fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->venc_lt_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable venc_lt_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->venc_lt_sel, pm->vdec_bus_clk_src);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent venc_lt_sel vdec_bus_clk_src fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable univpll_d2 fail %d", ret);
+
+	ret = clk_prepare_enable(pm->clk_cci400_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable clk_cci400_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->clk_cci400_sel, pm->univpll_d2);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent clk_cci400_sel univpll_d2 fail %d",
+				ret);
+
+	ret = clk_prepare_enable(pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdecpll fail %d", ret);
+
+	ret = clk_prepare_enable(pm->vdec_sel);
+	if (ret)
+		mtk_v4l2_err("clk_prepare_enable vdec_sel fail %d", ret);
+
+	ret = clk_set_parent(pm->vdec_sel, pm->vdecpll);
+	if (ret)
+		mtk_v4l2_err("clk_set_parent vdec_sel vdecpll fail %d", ret);
+
+	ret = mtk_smi_larb_get(pm->larbvdec);
+	if (ret)
+		mtk_v4l2_err("mtk_smi_larb_get larbvdec fail %d", ret);
+
+}
+
+void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm)
+{
+	mtk_smi_larb_put(pm->larbvdec);
+	clk_disable_unprepare(pm->vdec_sel);
+	clk_disable_unprepare(pm->vdecpll);
+	clk_disable_unprepare(pm->univpll_d2);
+	clk_disable_unprepare(pm->clk_cci400_sel);
+	clk_disable_unprepare(pm->venc_lt_sel);
+	clk_disable_unprepare(pm->vdec_bus_clk_src);
+	clk_disable_unprepare(pm->vencpll);
+	clk_disable_unprepare(pm->vcodecpll);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Tiffany Lin <tiffany.lin@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_VCODEC_DEC_PM_H_
+#define _MTK_VCODEC_DEC_PM_H_
+
+#include "mtk_vcodec_drv.h"
+
+int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
+void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
+
+void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm);
+void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm);
+
+#endif /* _MTK_VCODEC_DEC_PM_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_drv.h	2017-02-12 16:03:20.000000000 -0500
@@ -22,13 +22,13 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/videobuf2-core.h>
-
+#include "mtk_vcodec_util.h"
 
 #define MTK_VCODEC_DRV_NAME	"mtk_vcodec_drv"
+#define MTK_VCODEC_DEC_NAME	"mtk-vcodec-dec"
 #define MTK_VCODEC_ENC_NAME	"mtk-vcodec-enc"
 #define MTK_PLATFORM_STR	"platform:mt8173"
 
-
 #define MTK_VCODEC_MAX_PLANES	3
 #define MTK_V4L2_BENCHMARK	0
 #define WAIT_INTR_TIMEOUT_MS	1000
@@ -179,6 +179,9 @@ struct mtk_enc_params {
  * struct mtk_vcodec_pm - Power management data structure
  */
 struct mtk_vcodec_pm {
+	struct clk	*vdec_bus_clk_src;
+	struct clk	*vencpll;
+
 	struct clk	*vcodecpll;
 	struct clk	*univpll_d2;
 	struct clk	*clk_cci400_sel;
@@ -196,6 +199,32 @@ struct mtk_vcodec_pm {
 };
 
 /**
+ * struct vdec_pic_info  - picture size information
+ * @pic_w: picture width
+ * @pic_h: picture height
+ * @buf_w: picture buffer width (64 aligned up from pic_w)
+ * @buf_h: picture buffer heiht (64 aligned up from pic_h)
+ * @y_bs_sz: Y bitstream size
+ * @c_bs_sz: CbCr bitstream size
+ * @y_len_sz: additional size required to store decompress information for y
+ *		plane
+ * @c_len_sz: additional size required to store decompress information for cbcr
+ *		plane
+ * E.g. suppose picture size is 176x144,
+ *      buffer size will be aligned to 176x160.
+ */
+struct vdec_pic_info {
+	unsigned int pic_w;
+	unsigned int pic_h;
+	unsigned int buf_w;
+	unsigned int buf_h;
+	unsigned int y_bs_sz;
+	unsigned int c_bs_sz;
+	unsigned int y_len_sz;
+	unsigned int c_len_sz;
+};
+
+/**
  * struct mtk_vcodec_ctx - Context (instance) private data.
  *
  * @type: type of the instance - decoder or encoder
@@ -209,9 +238,12 @@ struct mtk_vcodec_pm {
  * @state: state of the context
  * @param_change: indicate encode parameter type
  * @enc_params: encoding parameters
+ * @dec_if: hooked decoder driver interface
  * @enc_if: hoooked encoder driver interface
  * @drv_handle: driver handle for specific decode/encode instance
  *
+ * @picinfo: store picture info after header parsing
+ * @dpb_size: store dpb count after header parsing
  * @int_cond: variable used by the waitqueue
  * @int_type: type of the last interrupt
  * @queue: waitqueue that can be used to wait for this context to
@@ -219,12 +251,16 @@ struct mtk_vcodec_pm {
  * @irq_status: irq status
  *
  * @ctrl_hdl: handler for v4l2 framework
+ * @decode_work: worker for the decoding
  * @encode_work: worker for the encoding
+ * @last_decoded_picinfo: pic information get from latest decode
  *
  * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
  * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
  * @quantization: enum v4l2_quantization, colorspace quantization
  * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
+ * @lock: protect variables accessed by V4L2 threads and worker thread such as
+ *	  mtk_video_dec_buf.
  */
 struct mtk_vcodec_ctx {
 	enum mtk_instance_type type;
@@ -239,28 +275,40 @@ struct mtk_vcodec_ctx {
 	enum mtk_encode_param param_change;
 	struct mtk_enc_params enc_params;
 
+	const struct vdec_common_if *dec_if;
 	const struct venc_common_if *enc_if;
 	unsigned long drv_handle;
 
+	struct vdec_pic_info picinfo;
+	int dpb_size;
+
 	int int_cond;
 	int int_type;
 	wait_queue_head_t queue;
 	unsigned int irq_status;
 
 	struct v4l2_ctrl_handler ctrl_hdl;
+	struct work_struct decode_work;
 	struct work_struct encode_work;
+	struct vdec_pic_info last_decoded_picinfo;
 
 	enum v4l2_colorspace colorspace;
 	enum v4l2_ycbcr_encoding ycbcr_enc;
 	enum v4l2_quantization quantization;
 	enum v4l2_xfer_func xfer_func;
+
+	int decoded_frame_cnt;
+	struct mutex lock;
+
 };
 
 /**
  * struct mtk_vcodec_dev - driver data
  * @v4l2_dev: V4L2 device to register video devices for.
+ * @vfd_dec: Video device for decoder
  * @vfd_enc: Video device for encoder.
  *
+ * @m2m_dev_dec: m2m device for decoder
  * @m2m_dev_enc: m2m device for encoder.
  * @plat_dev: platform device
  * @vpu_plat_dev: mtk vpu platform device
@@ -271,7 +319,6 @@ struct mtk_vcodec_ctx {
  * @reg_base: Mapped address of MTK Vcodec registers.
  *
  * @id_counter: used to identify current opened instance
- * @num_instances: counter of active MTK Vcodec instances
  *
  * @encode_workqueue: encode work queue
  *
@@ -280,9 +327,11 @@ struct mtk_vcodec_ctx {
  * @dev_mutex: video_device lock
  * @queue: waitqueue for waiting for completion of device commands
  *
+ * @dec_irq: decoder irq resource
  * @enc_irq: h264 encoder irq resource
  * @enc_lt_irq: vp8 encoder irq resource
  *
+ * @dec_mutex: decoder hardware lock
  * @enc_mutex: encoder hardware lock.
  *
  * @pm: power management control
@@ -291,8 +340,10 @@ struct mtk_vcodec_ctx {
  */
 struct mtk_vcodec_dev {
 	struct v4l2_device v4l2_dev;
+	struct video_device *vfd_dec;
 	struct video_device *vfd_enc;
 
+	struct v4l2_m2m_dev *m2m_dev_dec;
 	struct v4l2_m2m_dev *m2m_dev_enc;
 	struct platform_device *plat_dev;
 	struct platform_device *vpu_plat_dev;
@@ -302,18 +353,19 @@ struct mtk_vcodec_dev {
 	void __iomem *reg_base[NUM_MAX_VCODEC_REG_BASE];
 
 	unsigned long id_counter;
-	int num_instances;
 
+	struct workqueue_struct *decode_workqueue;
 	struct workqueue_struct *encode_workqueue;
-
 	int int_cond;
 	int int_type;
 	struct mutex dev_mutex;
 	wait_queue_head_t queue;
 
+	int dec_irq;
 	int enc_irq;
 	int enc_lt_irq;
 
+	struct mutex dec_mutex;
 	struct mutex enc_mutex;
 
 	struct mtk_vcodec_pm pm;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -188,7 +188,6 @@ static int fops_vcodec_open(struct file
 	mtk_v4l2_debug(2, "Create instance [%d]@%p m2m_ctx=%p ",
 			ctx->id, ctx, ctx->m2m_ctx);
 
-	dev->num_instances++;
 	list_add(&ctx->list, &dev->ctx_list);
 
 	mutex_unlock(&dev->dev_mutex);
@@ -218,18 +217,13 @@ static int fops_vcodec_release(struct fi
 	mtk_v4l2_debug(1, "[%d] encoder", ctx->id);
 	mutex_lock(&dev->dev_mutex);
 
-	/*
-	 * Call v4l2_m2m_ctx_release to make sure the worker thread is not
-	 * running after venc_if_deinit.
-	 */
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 	mtk_vcodec_enc_release(ctx);
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 
 	list_del_init(&ctx->list);
-	dev->num_instances--;
 	kfree(ctx);
 	mutex_unlock(&dev->dev_mutex);
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_intr.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,8 +30,7 @@ int mtk_vcodec_wait_for_done_ctx(struct
 	timeout_jiff = msecs_to_jiffies(timeout_ms);
 
 	ret = wait_event_interruptible_timeout(*waitqueue,
-				(ctx->int_cond &&
-				(ctx->int_type == command)),
+				ctx->int_cond,
 				timeout_jiff);
 
 	if (!ret) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,14 +81,37 @@ void mtk_vcodec_mem_free(struct mtk_vcod
 		return;
 	}
 
-	dma_free_coherent(dev, size, mem->va, mem->dma_addr);
-	mem->va = NULL;
-	mem->dma_addr = 0;
-	mem->size = 0;
-
 	mtk_v4l2_debug(3, "[%d]  - va      = %p", ctx->id, mem->va);
 	mtk_v4l2_debug(3, "[%d]  - dma     = 0x%lx", ctx->id,
 		       (unsigned long)mem->dma_addr);
 	mtk_v4l2_debug(3, "[%d]    size = 0x%lx", ctx->id, size);
+
+	dma_free_coherent(dev, size, mem->va, mem->dma_addr);
+	mem->va = NULL;
+	mem->dma_addr = 0;
+	mem->size = 0;
 }
 EXPORT_SYMBOL(mtk_vcodec_mem_free);
+
+void mtk_vcodec_set_curr_ctx(struct mtk_vcodec_dev *dev,
+	struct mtk_vcodec_ctx *ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	dev->curr_ctx = ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+}
+EXPORT_SYMBOL(mtk_vcodec_set_curr_ctx);
+
+struct mtk_vcodec_ctx *mtk_vcodec_get_curr_ctx(struct mtk_vcodec_dev *dev)
+{
+	unsigned long flags;
+	struct mtk_vcodec_ctx *ctx;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	ctx = dev->curr_ctx;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+	return ctx;
+}
+EXPORT_SYMBOL(mtk_vcodec_get_curr_ctx);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/mtk_vcodec_util.h	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,7 @@ struct mtk_vcodec_mem {
 };
 
 struct mtk_vcodec_ctx;
+struct mtk_vcodec_dev;
 
 extern int mtk_v4l2_dbg_level;
 extern bool mtk_vcodec_dbg;
@@ -84,4 +85,8 @@ int mtk_vcodec_mem_alloc(struct mtk_vcod
 				struct mtk_vcodec_mem *mem);
 void mtk_vcodec_mem_free(struct mtk_vcodec_ctx *data,
 				struct mtk_vcodec_mem *mem);
+void mtk_vcodec_set_curr_ctx(struct mtk_vcodec_dev *dev,
+	struct mtk_vcodec_ctx *ctx);
+struct mtk_vcodec_ctx *mtk_vcodec_get_curr_ctx(struct mtk_vcodec_dev *dev);
+
 #endif /* _MTK_VCODEC_UTIL_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_h264_if.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.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/slab.h>
+
+#include "../vdec_drv_if.h"
+#include "../mtk_vcodec_util.h"
+#include "../mtk_vcodec_dec.h"
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_vpu_if.h"
+#include "../vdec_drv_base.h"
+
+#define NAL_NON_IDR_SLICE			0x01
+#define NAL_IDR_SLICE				0x05
+#define NAL_H264_PPS				0x08
+#define NAL_TYPE(value)				((value) & 0x1F)
+
+#define BUF_PREDICTION_SZ			(32 * 1024)
+
+#define MB_UNIT_LEN				16
+
+/* motion vector size (bytes) for every macro block */
+#define HW_MB_STORE_SZ				64
+
+#define H264_MAX_FB_NUM				17
+#define HDR_PARSING_BUF_SZ			1024
+
+/**
+ * struct h264_fb - h264 decode frame buffer information
+ * @vdec_fb_va  : virtual address of struct vdec_fb
+ * @y_fb_dma    : dma address of Y frame buffer (luma)
+ * @c_fb_dma    : dma address of C frame buffer (chroma)
+ * @poc         : picture order count of frame buffer
+ * @reserved    : for 8 bytes alignment
+ */
+struct h264_fb {
+	uint64_t vdec_fb_va;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	int32_t poc;
+	uint32_t reserved;
+};
+
+/**
+ * struct h264_ring_fb_list - ring frame buffer list
+ * @fb_list   : frame buffer arrary
+ * @read_idx  : read index
+ * @write_idx : write index
+ * @count     : buffer count in list
+ */
+struct h264_ring_fb_list {
+	struct h264_fb fb_list[H264_MAX_FB_NUM];
+	unsigned int read_idx;
+	unsigned int write_idx;
+	unsigned int count;
+	unsigned int reserved;
+};
+
+/**
+ * struct vdec_h264_dec_info - decode information
+ * @dpb_sz		: decoding picture buffer size
+ * @resolution_changed  : resoltion change happen
+ * @realloc_mv_buf	: flag to notify driver to re-allocate mv buffer
+ * @reserved		: for 8 bytes alignment
+ * @bs_dma		: Input bit-stream buffer dma address
+ * @y_fb_dma		: Y frame buffer dma address
+ * @c_fb_dma		: C frame buffer dma address
+ * @vdec_fb_va		: VDEC frame buffer struct virtual address
+ */
+struct vdec_h264_dec_info {
+	uint32_t dpb_sz;
+	uint32_t resolution_changed;
+	uint32_t realloc_mv_buf;
+	uint32_t reserved;
+	uint64_t bs_dma;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+	uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_h264_vsi - shared memory for decode information exchange
+ *                        between VPU and Host.
+ *                        The memory is allocated by VPU then mapping to Host
+ *                        in vpu_dec_init() and freed in vpu_dec_deinit()
+ *                        by VPU.
+ *                        AP-W/R : AP is writer/reader on this item
+ *                        VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf      : Header parsing buffer (AP-W, VPU-R)
+ * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R)
+ * @mv_buf_dma   : HW working motion vector buffer dma address (AP-W, VPU-R)
+ * @list_free    : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp    : display frame buffer ring list (AP-R, VPU-W)
+ * @dec          : decode information (AP-R, VPU-W)
+ * @pic          : picture information (AP-R, VPU-W)
+ * @crop         : crop information (AP-R, VPU-W)
+ */
+struct vdec_h264_vsi {
+	unsigned char hdr_buf[HDR_PARSING_BUF_SZ];
+	uint64_t pred_buf_dma;
+	uint64_t mv_buf_dma[H264_MAX_FB_NUM];
+	struct h264_ring_fb_list list_free;
+	struct h264_ring_fb_list list_disp;
+	struct vdec_h264_dec_info dec;
+	struct vdec_pic_info pic;
+	struct v4l2_rect crop;
+};
+
+/**
+ * struct vdec_h264_inst - h264 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx      : point to mtk_vcodec_ctx
+ * @pred_buf : HW working predication buffer
+ * @mv_buf   : HW working motion vector buffer
+ * @vpu      : VPU instance
+ * @vsi      : VPU shared information
+ */
+struct vdec_h264_inst {
+	unsigned int num_nalu;
+	struct mtk_vcodec_ctx *ctx;
+	struct mtk_vcodec_mem pred_buf;
+	struct mtk_vcodec_mem mv_buf[H264_MAX_FB_NUM];
+	struct vdec_vpu_inst vpu;
+	struct vdec_h264_vsi *vsi;
+};
+
+static unsigned int get_mv_buf_size(unsigned int width, unsigned int height)
+{
+	return HW_MB_STORE_SZ * (width/MB_UNIT_LEN) * (height/MB_UNIT_LEN);
+}
+
+static int allocate_predication_buf(struct vdec_h264_inst *inst)
+{
+	int err = 0;
+
+	inst->pred_buf.size = BUF_PREDICTION_SZ;
+	err = mtk_vcodec_mem_alloc(inst->ctx, &inst->pred_buf);
+	if (err) {
+		mtk_vcodec_err(inst, "failed to allocate ppl buf");
+		return err;
+	}
+
+	inst->vsi->pred_buf_dma = inst->pred_buf.dma_addr;
+	return 0;
+}
+
+static void free_predication_buf(struct vdec_h264_inst *inst)
+{
+	struct mtk_vcodec_mem *mem = NULL;
+
+	mtk_vcodec_debug_enter(inst);
+
+	inst->vsi->pred_buf_dma = 0;
+	mem = &inst->pred_buf;
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+}
+
+static int alloc_mv_buf(struct vdec_h264_inst *inst, struct vdec_pic_info *pic)
+{
+	int i;
+	int err;
+	struct mtk_vcodec_mem *mem = NULL;
+	unsigned int buf_sz = get_mv_buf_size(pic->buf_w, pic->buf_h);
+
+	for (i = 0; i < H264_MAX_FB_NUM; i++) {
+		mem = &inst->mv_buf[i];
+		if (mem->va)
+			mtk_vcodec_mem_free(inst->ctx, mem);
+		mem->size = buf_sz;
+		err = mtk_vcodec_mem_alloc(inst->ctx, mem);
+		if (err) {
+			mtk_vcodec_err(inst, "failed to allocate mv buf");
+			return err;
+		}
+		inst->vsi->mv_buf_dma[i] = mem->dma_addr;
+	}
+
+	return 0;
+}
+
+static void free_mv_buf(struct vdec_h264_inst *inst)
+{
+	int i;
+	struct mtk_vcodec_mem *mem = NULL;
+
+	for (i = 0; i < H264_MAX_FB_NUM; i++) {
+		inst->vsi->mv_buf_dma[i] = 0;
+		mem = &inst->mv_buf[i];
+		if (mem->va)
+			mtk_vcodec_mem_free(inst->ctx, mem);
+	}
+}
+
+static int check_list_validity(struct vdec_h264_inst *inst, bool disp_list)
+{
+	struct h264_ring_fb_list *list;
+
+	list = disp_list ? &inst->vsi->list_disp : &inst->vsi->list_free;
+
+	if (list->count > H264_MAX_FB_NUM ||
+	    list->read_idx >= H264_MAX_FB_NUM ||
+	    list->write_idx >= H264_MAX_FB_NUM) {
+		mtk_vcodec_err(inst, "%s list err: cnt=%d r_idx=%d w_idx=%d",
+			       disp_list ? "disp" : "free", list->count,
+			       list->read_idx, list->write_idx);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void put_fb_to_free(struct vdec_h264_inst *inst, struct vdec_fb *fb)
+{
+	struct h264_ring_fb_list *list;
+
+	if (fb) {
+		if (check_list_validity(inst, false))
+			return;
+
+		list = &inst->vsi->list_free;
+		if (list->count == H264_MAX_FB_NUM) {
+			mtk_vcodec_err(inst, "[FB] put fb free_list full");
+			return;
+		}
+
+		mtk_vcodec_debug(inst, "[FB] put fb into free_list @(%p, %llx)",
+				 fb->base_y.va, (u64)fb->base_y.dma_addr);
+
+		list->fb_list[list->write_idx].vdec_fb_va = (u64)(uintptr_t)fb;
+		list->write_idx = (list->write_idx == H264_MAX_FB_NUM - 1) ?
+				  0 : list->write_idx + 1;
+		list->count++;
+	}
+}
+
+static void get_pic_info(struct vdec_h264_inst *inst,
+			 struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = inst->vsi->crop.left;
+	cr->top = inst->vsi->crop.top;
+	cr->width = inst->vsi->crop.width;
+	cr->height = inst->vsi->crop.height;
+
+	mtk_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz)
+{
+	*dpb_sz = inst->vsi->dec.dpb_sz;
+	mtk_vcodec_debug(inst, "sz=%d", *dpb_sz);
+}
+
+static int vdec_h264_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_h264_inst *inst = NULL;
+	int err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_H264;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	err = vpu_dec_init(&inst->vpu);
+	if (err) {
+		mtk_vcodec_err(inst, "vdec_h264 init err=%d", err);
+		goto error_free_inst;
+	}
+
+	inst->vsi = (struct vdec_h264_vsi *)inst->vpu.vsi;
+	err = allocate_predication_buf(inst);
+	if (err)
+		goto error_deinit;
+
+	mtk_vcodec_debug(inst, "H264 Instance >> %p", inst);
+
+	*h_vdec = (unsigned long)inst;
+	return 0;
+
+error_deinit:
+	vpu_dec_deinit(&inst->vpu);
+
+error_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static void vdec_h264_deinit(unsigned long h_vdec)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	mtk_vcodec_debug_enter(inst);
+
+	vpu_dec_deinit(&inst->vpu);
+	free_predication_buf(inst);
+	free_mv_buf(inst);
+
+	kfree(inst);
+}
+
+static int find_start_code(unsigned char *data, unsigned int data_sz)
+{
+	if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
+		return 3;
+
+	if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 &&
+	    data[3] == 1)
+		return 4;
+
+	return -1;
+}
+
+static int vdec_h264_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			    struct vdec_fb *fb, bool *res_chg)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	int nal_start_idx = 0;
+	int err = 0;
+	unsigned int nal_start;
+	unsigned int nal_type;
+	unsigned char *buf;
+	unsigned int buf_sz;
+	unsigned int data[2];
+	uint64_t vdec_fb_va = (u64)(uintptr_t)fb;
+	uint64_t y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	uint64_t c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
+
+	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx va=%p",
+			 ++inst->num_nalu, y_fb_dma, c_fb_dma, fb);
+
+	/* bs NULL means flush decoder */
+	if (bs == NULL)
+		return vpu_dec_reset(vpu);
+
+	buf = (unsigned char *)bs->va;
+	buf_sz = bs->size;
+	nal_start_idx = find_start_code(buf, buf_sz);
+	if (nal_start_idx < 0)
+		goto err_free_fb_out;
+
+	nal_start = buf[nal_start_idx];
+	nal_type = NAL_TYPE(buf[nal_start_idx]);
+	mtk_vcodec_debug(inst, "\n + NALU[%d] type %d +\n", inst->num_nalu,
+			 nal_type);
+
+	if (nal_type == NAL_H264_PPS) {
+		buf_sz -= nal_start_idx;
+		if (buf_sz > HDR_PARSING_BUF_SZ) {
+			err = -EILSEQ;
+			goto err_free_fb_out;
+		}
+		memcpy(inst->vsi->hdr_buf, buf + nal_start_idx, buf_sz);
+	}
+
+	inst->vsi->dec.bs_dma = (uint64_t)bs->dma_addr;
+	inst->vsi->dec.y_fb_dma = y_fb_dma;
+	inst->vsi->dec.c_fb_dma = c_fb_dma;
+	inst->vsi->dec.vdec_fb_va = vdec_fb_va;
+
+	data[0] = buf_sz;
+	data[1] = nal_start;
+	err = vpu_dec_start(vpu, data, 2);
+	if (err)
+		goto err_free_fb_out;
+
+	*res_chg = inst->vsi->dec.resolution_changed;
+	if (*res_chg) {
+		struct vdec_pic_info pic;
+
+		mtk_vcodec_debug(inst, "- resolution changed -");
+		get_pic_info(inst, &pic);
+
+		if (inst->vsi->dec.realloc_mv_buf) {
+			err = alloc_mv_buf(inst, &pic);
+			if (err)
+				goto err_free_fb_out;
+		}
+	}
+
+	if (nal_type == NAL_NON_IDR_SLICE || nal_type == NAL_IDR_SLICE) {
+		/* wait decoder done interrupt */
+		err = mtk_vcodec_wait_for_done_ctx(inst->ctx,
+						   MTK_INST_IRQ_RECEIVED,
+						   WAIT_INTR_TIMEOUT_MS);
+		if (err)
+			goto err_free_fb_out;
+
+		vpu_dec_end(vpu);
+	}
+
+	mtk_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu,
+			 nal_type);
+	return 0;
+
+err_free_fb_out:
+	put_fb_to_free(inst, fb);
+	mtk_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err);
+	return err;
+}
+
+static void vdec_h264_get_fb(struct vdec_h264_inst *inst,
+			     struct h264_ring_fb_list *list,
+			     bool disp_list, struct vdec_fb **out_fb)
+{
+	struct vdec_fb *fb;
+
+	if (check_list_validity(inst, disp_list))
+		return;
+
+	if (list->count == 0) {
+		mtk_vcodec_debug(inst, "[FB] there is no %s fb",
+				 disp_list ? "disp" : "free");
+		*out_fb = NULL;
+		return;
+	}
+
+	fb = (struct vdec_fb *)
+		(uintptr_t)list->fb_list[list->read_idx].vdec_fb_va;
+	fb->status |= (disp_list ? FB_ST_DISPLAY : FB_ST_FREE);
+
+	*out_fb = fb;
+	mtk_vcodec_debug(inst, "[FB] get %s fb st=%d poc=%d %llx",
+			 disp_list ? "disp" : "free",
+			 fb->status, list->fb_list[list->read_idx].poc,
+			 list->fb_list[list->read_idx].vdec_fb_va);
+
+	list->read_idx = (list->read_idx == H264_MAX_FB_NUM - 1) ?
+			 0 : list->read_idx + 1;
+	list->count--;
+}
+
+static int vdec_h264_get_param(unsigned long h_vdec,
+			       enum vdec_get_param_type type, void *out)
+{
+	struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		vdec_h264_get_fb(inst, &inst->vsi->list_disp, true, out);
+		break;
+
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		vdec_h264_get_fb(inst, &inst->vsi->list_free, false, out);
+		break;
+
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		get_dpb_size(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	default:
+		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct vdec_common_if vdec_h264_if = {
+	vdec_h264_init,
+	vdec_h264_decode,
+	vdec_h264_get_param,
+	vdec_h264_deinit,
+};
+
+struct vdec_common_if *get_h264_dec_comm_if(void);
+
+struct vdec_common_if *get_h264_dec_comm_if(void)
+{
+	return &vdec_h264_if;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp8_if.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Jungchang Tsao <jungchang.tsao@mediatek.com>
+ *	   PC Chen <pc.chen@mediatek.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/slab.h>
+#include "../vdec_drv_if.h"
+#include "../mtk_vcodec_util.h"
+#include "../mtk_vcodec_dec.h"
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_vpu_if.h"
+#include "../vdec_drv_base.h"
+
+/* Decoding picture buffer size (3 reference frames plus current frame) */
+#define VP8_DPB_SIZE			4
+
+/* HW working buffer size (bytes) */
+#define VP8_WORKING_BUF_SZ		(45 * 4096)
+
+/* HW control register address */
+#define VP8_SEGID_DRAM_ADDR		0x3c
+#define VP8_HW_VLD_ADDR			0x93C
+#define VP8_HW_VLD_VALUE		0x940
+#define VP8_BSASET			0x100
+#define VP8_BSDSET			0x104
+#define VP8_RW_CKEN_SET			0x0
+#define VP8_RW_DCM_CON			0x18
+#define VP8_WO_VLD_SRST			0x108
+#define VP8_RW_MISC_SYS_SEL		0x84
+#define VP8_RW_MISC_SPEC_CON		0xC8
+#define VP8_WO_VLD_SRST			0x108
+#define VP8_RW_VP8_CTRL			0xA4
+#define VP8_RW_MISC_DCM_CON		0xEC
+#define VP8_RW_MISC_SRST		0xF4
+#define VP8_RW_MISC_FUNC_CON		0xCC
+
+#define VP8_MAX_FRM_BUF_NUM		5
+#define VP8_MAX_FRM_BUF_NODE_NUM	(VP8_MAX_FRM_BUF_NUM * 2)
+
+/* required buffer size (bytes) to store decode information */
+#define VP8_HW_SEGMENT_DATA_SZ		272
+#define VP8_HW_SEGMENT_UINT		4
+
+#define VP8_DEC_TABLE_PROC_LOOP		96
+#define VP8_DEC_TABLE_UNIT		3
+#define VP8_DEC_TABLE_SZ		300
+#define VP8_DEC_TABLE_OFFSET		2
+#define VP8_DEC_TABLE_RW_UNIT		4
+
+/**
+ * struct vdec_vp8_dec_info - decode misc information
+ * @working_buf_dma   : working buffer dma address
+ * @prev_y_dma        : previous decoded frame buffer Y plane address
+ * @cur_y_fb_dma      : current plane Y frame buffer dma address
+ * @cur_c_fb_dma      : current plane C frame buffer dma address
+ * @bs_dma	      : bitstream dma address
+ * @bs_sz	      : bitstream size
+ * @resolution_changed: resolution change flag 1 - changed,  0 - not change
+ * @show_frame	      : display this frame or not
+ * @wait_key_frame    : wait key frame coming
+ */
+struct vdec_vp8_dec_info {
+	uint64_t working_buf_dma;
+	uint64_t prev_y_dma;
+	uint64_t cur_y_fb_dma;
+	uint64_t cur_c_fb_dma;
+	uint64_t bs_dma;
+	uint32_t bs_sz;
+	uint32_t resolution_changed;
+	uint32_t show_frame;
+	uint32_t wait_key_frame;
+};
+
+/**
+ * struct vdec_vp8_vsi - VPU shared information
+ * @dec			: decoding information
+ * @pic			: picture information
+ * @dec_table		: decoder coefficient table
+ * @segment_buf		: segmentation buffer
+ * @load_data		: flag to indicate reload decode data
+ */
+struct vdec_vp8_vsi {
+	struct vdec_vp8_dec_info dec;
+	struct vdec_pic_info pic;
+	uint32_t dec_table[VP8_DEC_TABLE_SZ];
+	uint32_t segment_buf[VP8_HW_SEGMENT_DATA_SZ][VP8_HW_SEGMENT_UINT];
+	uint32_t load_data;
+};
+
+/**
+ * struct vdec_vp8_hw_reg_base - HW register base
+ * @sys		: base address for sys
+ * @misc	: base address for misc
+ * @ld		: base address for ld
+ * @top		: base address for top
+ * @cm		: base address for cm
+ * @hwd		: base address for hwd
+ * @hwb		: base address for hwb
+ */
+struct vdec_vp8_hw_reg_base {
+	void __iomem *sys;
+	void __iomem *misc;
+	void __iomem *ld;
+	void __iomem *top;
+	void __iomem *cm;
+	void __iomem *hwd;
+	void __iomem *hwb;
+};
+
+/**
+ * struct vdec_vp8_vpu_inst - VPU instance for VP8 decode
+ * @wq_hd	: Wait queue to wait VPU message ack
+ * @signaled	: 1 - Host has received ack message from VPU, 0 - not recevie
+ * @failure	: VPU execution result status 0 - success, others - fail
+ * @inst_addr	: VPU decoder instance address
+ */
+struct vdec_vp8_vpu_inst {
+	wait_queue_head_t wq_hd;
+	int signaled;
+	int failure;
+	uint32_t inst_addr;
+};
+
+/* frame buffer (fb) list
+ * [available_fb_node_list]  - decode fb are initialized to 0 and populated in
+ * [fb_use_list]  - fb is set after decode and is moved to this list
+ * [fb_free_list] - fb is not needed for reference will be moved from
+ *		     [fb_use_list] to [fb_free_list] and
+ *		     once user remove fb from [fb_free_list],
+ *		     it is circulated back to [available_fb_node_list]
+ * [fb_disp_list] - fb is set after decode and is moved to this list
+ *                   once user remove fb from [fb_disp_list] it is
+ *                   circulated back to [available_fb_node_list]
+ */
+
+/**
+ * struct vdec_vp8_inst - VP8 decoder instance
+ * @cur_fb		   : current frame buffer
+ * @dec_fb		   : decode frame buffer node
+ * @available_fb_node_list : list to store available frame buffer node
+ * @fb_use_list		   : list to store frame buffer in use
+ * @fb_free_list	   : list to store free frame buffer
+ * @fb_disp_list	   : list to store display ready frame buffer
+ * @working_buf		   : HW decoder working buffer
+ * @reg_base		   : HW register base address
+ * @frm_cnt		   : decode frame count
+ * @ctx			   : V4L2 context
+ * @dev			   : platform device
+ * @vpu			   : VPU instance for decoder
+ * @vsi			   : VPU share information
+ */
+struct vdec_vp8_inst {
+	struct vdec_fb *cur_fb;
+	struct vdec_fb_node dec_fb[VP8_MAX_FRM_BUF_NODE_NUM];
+	struct list_head available_fb_node_list;
+	struct list_head fb_use_list;
+	struct list_head fb_free_list;
+	struct list_head fb_disp_list;
+	struct mtk_vcodec_mem working_buf;
+	struct vdec_vp8_hw_reg_base reg_base;
+	unsigned int frm_cnt;
+	struct mtk_vcodec_ctx *ctx;
+	struct vdec_vpu_inst vpu;
+	struct vdec_vp8_vsi *vsi;
+};
+
+static void get_hw_reg_base(struct vdec_vp8_inst *inst)
+{
+	inst->reg_base.top = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_TOP);
+	inst->reg_base.cm = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_CM);
+	inst->reg_base.hwd = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWD);
+	inst->reg_base.sys = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_SYS);
+	inst->reg_base.misc = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_MISC);
+	inst->reg_base.ld = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_LD);
+	inst->reg_base.hwb = mtk_vcodec_get_reg_addr(inst->ctx, VDEC_HWB);
+}
+
+static void write_hw_segmentation_data(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 seg_id_addr;
+	u32 val;
+	void __iomem *cm = inst->reg_base.cm;
+	struct vdec_vp8_vsi *vsi = inst->vsi;
+
+	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
+		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
+			val = (1 << 16) + ((seg_id_addr + i) << 2) + j;
+			writel(val, cm + VP8_HW_VLD_ADDR);
+
+			val = vsi->segment_buf[i][j];
+			writel(val, cm + VP8_HW_VLD_VALUE);
+		}
+	}
+}
+
+static void read_hw_segmentation_data(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 seg_id_addr;
+	u32 val;
+	void __iomem *cm = inst->reg_base.cm;
+	struct vdec_vp8_vsi *vsi = inst->vsi;
+
+	seg_id_addr = readl(inst->reg_base.top + VP8_SEGID_DRAM_ADDR) >> 4;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->segment_buf); i++) {
+		for (j = ARRAY_SIZE(vsi->segment_buf[i]) - 1; j >= 0; j--) {
+			val = ((seg_id_addr + i) << 2) + j;
+			writel(val, cm + VP8_HW_VLD_ADDR);
+
+			val = readl(cm + VP8_HW_VLD_VALUE);
+			vsi->segment_buf[i][j] = val;
+		}
+	}
+}
+
+/* reset HW and enable HW read/write data function */
+static void enable_hw_rw_function(struct vdec_vp8_inst *inst)
+{
+	u32 val = 0;
+	void __iomem *sys = inst->reg_base.sys;
+	void __iomem *misc = inst->reg_base.misc;
+	void __iomem *ld = inst->reg_base.ld;
+	void __iomem *hwb = inst->reg_base.hwb;
+	void __iomem *hwd = inst->reg_base.hwd;
+
+	writel(0x1, sys + VP8_RW_CKEN_SET);
+	writel(0x101, ld + VP8_WO_VLD_SRST);
+	writel(0x101, hwb + VP8_WO_VLD_SRST);
+
+	writel(1, sys);
+	val = readl(misc + VP8_RW_MISC_SRST);
+	writel((val & 0xFFFFFFFE), misc + VP8_RW_MISC_SRST);
+
+	writel(0x1, misc + VP8_RW_MISC_SYS_SEL);
+	writel(0x17F, misc + VP8_RW_MISC_SPEC_CON);
+	writel(0x71201100, misc + VP8_RW_MISC_FUNC_CON);
+	writel(0x0, ld + VP8_WO_VLD_SRST);
+	writel(0x0, hwb + VP8_WO_VLD_SRST);
+	writel(0x1, sys + VP8_RW_DCM_CON);
+	writel(0x1, misc + VP8_RW_MISC_DCM_CON);
+	writel(0x1, hwd + VP8_RW_VP8_CTRL);
+}
+
+static void store_dec_table(struct vdec_vp8_inst *inst)
+{
+	int i, j;
+	u32 addr = 0, val = 0;
+	void __iomem *hwd = inst->reg_base.hwd;
+	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
+
+	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
+		writel(addr, hwd + VP8_BSASET);
+		for (j = 0; j < VP8_DEC_TABLE_UNIT ; j++) {
+			val = *p++;
+			writel(val, hwd + VP8_BSDSET);
+		}
+		addr += VP8_DEC_TABLE_RW_UNIT;
+	}
+}
+
+static void load_dec_table(struct vdec_vp8_inst *inst)
+{
+	int i;
+	u32 addr = 0;
+	u32 *p = &inst->vsi->dec_table[VP8_DEC_TABLE_OFFSET];
+	void __iomem *hwd = inst->reg_base.hwd;
+
+	for (i = 0; i < VP8_DEC_TABLE_PROC_LOOP; i++) {
+		writel(addr, hwd + VP8_BSASET);
+		/* read total 11 bytes */
+		*p++ = readl(hwd + VP8_BSDSET);
+		*p++ = readl(hwd + VP8_BSDSET);
+		*p++ = readl(hwd + VP8_BSDSET) & 0xFFFFFF;
+		addr += VP8_DEC_TABLE_RW_UNIT;
+	}
+}
+
+static void get_pic_info(struct vdec_vp8_inst *inst, struct vdec_pic_info *pic)
+{
+	*pic = inst->vsi->pic;
+
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+			 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+			 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void vp8_dec_finish(struct vdec_vp8_inst *inst)
+{
+	struct vdec_fb_node *node;
+	uint64_t prev_y_dma = inst->vsi->dec.prev_y_dma;
+
+	mtk_vcodec_debug(inst, "prev fb base dma=%llx", prev_y_dma);
+
+	/* put last decode ok frame to fb_free_list */
+	if (prev_y_dma != 0) {
+		list_for_each_entry(node, &inst->fb_use_list, list) {
+			struct vdec_fb *fb = (struct vdec_fb *)node->fb;
+
+			if (prev_y_dma == (uint64_t)fb->base_y.dma_addr) {
+				list_move_tail(&node->list,
+					       &inst->fb_free_list);
+				break;
+			}
+		}
+	}
+
+	/* available_fb_node_list -> fb_use_list */
+	node = list_first_entry(&inst->available_fb_node_list,
+				struct vdec_fb_node, list);
+	node->fb = inst->cur_fb;
+	list_move_tail(&node->list, &inst->fb_use_list);
+
+	/* available_fb_node_list -> fb_disp_list */
+	if (inst->vsi->dec.show_frame) {
+		node = list_first_entry(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+		node->fb = inst->cur_fb;
+		list_move_tail(&node->list, &inst->fb_disp_list);
+	}
+}
+
+static void move_fb_list_use_to_free(struct vdec_vp8_inst *inst)
+{
+	struct vdec_fb_node *node, *tmp;
+
+	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
+		list_move_tail(&node->list, &inst->fb_free_list);
+}
+
+static void init_list(struct vdec_vp8_inst *inst)
+{
+	int i;
+
+	INIT_LIST_HEAD(&inst->available_fb_node_list);
+	INIT_LIST_HEAD(&inst->fb_use_list);
+	INIT_LIST_HEAD(&inst->fb_free_list);
+	INIT_LIST_HEAD(&inst->fb_disp_list);
+
+	for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
+		INIT_LIST_HEAD(&inst->dec_fb[i].list);
+		inst->dec_fb[i].fb = NULL;
+		list_add_tail(&inst->dec_fb[i].list,
+			      &inst->available_fb_node_list);
+	}
+}
+
+static void add_fb_to_free_list(struct vdec_vp8_inst *inst, void *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (fb) {
+		node = list_first_entry(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_free_list);
+	}
+}
+
+static int alloc_working_buf(struct vdec_vp8_inst *inst)
+{
+	int err;
+	struct mtk_vcodec_mem *mem = &inst->working_buf;
+
+	mem->size = VP8_WORKING_BUF_SZ;
+	err = mtk_vcodec_mem_alloc(inst->ctx, mem);
+	if (err) {
+		mtk_vcodec_err(inst, "Cannot allocate working buffer");
+		return err;
+	}
+
+	inst->vsi->dec.working_buf_dma = (uint64_t)mem->dma_addr;
+	return 0;
+}
+
+static void free_working_buf(struct vdec_vp8_inst *inst)
+{
+	struct mtk_vcodec_mem *mem = &inst->working_buf;
+
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	inst->vsi->dec.working_buf_dma = 0;
+}
+
+static int vdec_vp8_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_vp8_inst *inst;
+	int err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return  -ENOMEM;
+
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_VP8;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	err = vpu_dec_init(&inst->vpu);
+	if (err) {
+		mtk_vcodec_err(inst, "vdec_vp8 init err=%d", err);
+		goto error_free_inst;
+	}
+
+	inst->vsi = (struct vdec_vp8_vsi *)inst->vpu.vsi;
+	init_list(inst);
+	err = alloc_working_buf(inst);
+	if (err)
+		goto error_deinit;
+
+	get_hw_reg_base(inst);
+	mtk_vcodec_debug(inst, "VP8 Instance >> %p", inst);
+
+	*h_vdec = (unsigned long)inst;
+	return 0;
+
+error_deinit:
+	vpu_dec_deinit(&inst->vpu);
+error_free_inst:
+	kfree(inst);
+	return err;
+}
+
+static int vdec_vp8_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+			   struct vdec_fb *fb, bool *res_chg)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+	struct vdec_vp8_dec_info *dec = &inst->vsi->dec;
+	struct vdec_vpu_inst *vpu = &inst->vpu;
+	unsigned char *bs_va;
+	unsigned int data;
+	int err = 0;
+	uint64_t y_fb_dma;
+	uint64_t c_fb_dma;
+
+	/* bs NULL means flush decoder */
+	if (bs == NULL) {
+		move_fb_list_use_to_free(inst);
+		return vpu_dec_reset(vpu);
+	}
+
+	y_fb_dma = fb ? (u64)fb->base_y.dma_addr : 0;
+	c_fb_dma = fb ? (u64)fb->base_c.dma_addr : 0;
+
+	mtk_vcodec_debug(inst, "+ [%d] FB y_dma=%llx c_dma=%llx fb=%p",
+			 inst->frm_cnt, y_fb_dma, c_fb_dma, fb);
+
+	inst->cur_fb = fb;
+	dec->bs_dma = (unsigned long)bs->dma_addr;
+	dec->bs_sz = bs->size;
+	dec->cur_y_fb_dma = y_fb_dma;
+	dec->cur_c_fb_dma = c_fb_dma;
+
+	mtk_vcodec_debug(inst, "\n + FRAME[%d] +\n", inst->frm_cnt);
+
+	write_hw_segmentation_data(inst);
+	enable_hw_rw_function(inst);
+	store_dec_table(inst);
+
+	bs_va = (unsigned char *)bs->va;
+
+	/* retrieve width/hight and scale info from header */
+	data = (*(bs_va + 9) << 24) | (*(bs_va + 8) << 16) |
+	       (*(bs_va + 7) << 8) | *(bs_va + 6);
+	err = vpu_dec_start(vpu, &data, 1);
+	if (err) {
+		add_fb_to_free_list(inst, fb);
+		if (dec->wait_key_frame) {
+			mtk_vcodec_debug(inst, "wait key frame !");
+			return 0;
+		}
+
+		goto error;
+	}
+
+	if (dec->resolution_changed) {
+		mtk_vcodec_debug(inst, "- resolution_changed -");
+		*res_chg = true;
+		add_fb_to_free_list(inst, fb);
+		return 0;
+	}
+
+	/* wait decoder done interrupt */
+	mtk_vcodec_wait_for_done_ctx(inst->ctx, MTK_INST_IRQ_RECEIVED,
+				     WAIT_INTR_TIMEOUT_MS);
+
+	if (inst->vsi->load_data)
+		load_dec_table(inst);
+
+	vp8_dec_finish(inst);
+	read_hw_segmentation_data(inst);
+
+	err = vpu_dec_end(vpu);
+	if (err)
+		goto error;
+
+	mtk_vcodec_debug(inst, "\n - FRAME[%d] - show=%d\n", inst->frm_cnt,
+			 dec->show_frame);
+	inst->frm_cnt++;
+	*res_chg = false;
+	return 0;
+
+error:
+	mtk_vcodec_err(inst, "\n - FRAME[%d] - err=%d\n", inst->frm_cnt, err);
+	return err;
+}
+
+static void get_disp_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb;
+
+	node = list_first_entry_or_null(&inst->fb_disp_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_DISPLAY;
+		mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		fb = NULL;
+		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void get_free_fb(struct vdec_vp8_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb;
+
+	node = list_first_entry_or_null(&inst->fb_free_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_FREE;
+		mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		fb = NULL;
+		mtk_vcodec_debug(inst, "[FB] there is no free fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void get_crop_info(struct vdec_vp8_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = 0;
+	cr->top = 0;
+	cr->width = inst->vsi->pic.pic_w;
+	cr->height = inst->vsi->pic.pic_h;
+	mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_vp8_get_param(unsigned long h_vdec,
+			      enum vdec_get_param_type type, void *out)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		get_disp_fb(inst, out);
+		break;
+
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		get_free_fb(inst, out);
+		break;
+
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+
+	case GET_PARAM_DPB_SIZE:
+		*((unsigned int *)out) = VP8_DPB_SIZE;
+		break;
+
+	default:
+		mtk_vcodec_err(inst, "invalid get parameter type=%d", type);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void vdec_vp8_deinit(unsigned long h_vdec)
+{
+	struct vdec_vp8_inst *inst = (struct vdec_vp8_inst *)h_vdec;
+
+	mtk_vcodec_debug_enter(inst);
+
+	vpu_dec_deinit(&inst->vpu);
+	free_working_buf(inst);
+	kfree(inst);
+}
+
+static struct vdec_common_if vdec_vp8_if = {
+	vdec_vp8_init,
+	vdec_vp8_decode,
+	vdec_vp8_get_param,
+	vdec_vp8_deinit,
+};
+
+struct vdec_common_if *get_vp8_dec_comm_if(void);
+
+struct vdec_common_if *get_vp8_dec_comm_if(void)
+{
+	return &vdec_vp8_if;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,967 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Daniel Hsiao <daniel.hsiao@mediatek.com>
+ *	Kai-Sean Yang <kai-sean.yang@mediatek.com>
+ *	Tiffany Lin <tiffany.lin@mediatek.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/fs.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+
+#include "../mtk_vcodec_intr.h"
+#include "../vdec_drv_base.h"
+#include "../vdec_vpu_if.h"
+
+#define VP9_SUPER_FRAME_BS_SZ 64
+#define MAX_VP9_DPB_SIZE	9
+
+#define REFS_PER_FRAME 3
+#define MAX_NUM_REF_FRAMES 8
+#define VP9_MAX_FRM_BUF_NUM 9
+#define VP9_MAX_FRM_BUF_NODE_NUM (VP9_MAX_FRM_BUF_NUM * 2)
+
+/**
+ * struct vp9_dram_buf - contains buffer info for vpu
+ * @va : cpu address
+ * @pa : iova address
+ * @sz : buffer size
+ * @padding : for 64 bytes alignment
+ */
+struct vp9_dram_buf {
+	unsigned long va;
+	unsigned long pa;
+	unsigned int sz;
+	unsigned int padding;
+};
+
+/**
+ * struct vp9_fb_info - contains frame buffer info
+ * @fb : frmae buffer
+ * @reserved : reserved field used by vpu
+ */
+struct vp9_fb_info {
+	struct vdec_fb *fb;
+	unsigned int reserved[32];
+};
+
+/**
+ * struct vp9_ref_cnt_buf - contains reference buffer information
+ * @buf : referenced frame buffer
+ * @ref_cnt : referenced frame buffer's reference count.
+ *	When reference count=0, remove it from reference list
+ */
+struct vp9_ref_cnt_buf {
+	struct vp9_fb_info buf;
+	unsigned int ref_cnt;
+};
+
+/**
+ * struct vp9_fb_info - contains current frame's reference buffer information
+ * @buf : reference buffer
+ * @idx : reference buffer index to frm_bufs
+ * @reserved : reserved field used by vpu
+ */
+struct vp9_ref_buf {
+	struct vp9_fb_info *buf;
+	unsigned int idx;
+	unsigned int reserved[6];
+};
+
+/**
+ * struct vp9_fb_info - contains frame buffer info
+ * @fb : super frame reference frame buffer
+ * @used : this reference frame info entry is used
+ * @padding : for 64 bytes size align
+ */
+struct vp9_sf_ref_fb {
+	struct vdec_fb fb;
+	int used;
+	int padding;
+};
+
+/*
+ * struct vdec_vp9_vsi - shared buffer between host and VPU firmware
+ *	AP-W/R : AP is writer/reader on this item
+ *	VPU-W/R: VPU is write/reader on this item
+ * @sf_bs_buf : super frame backup buffer (AP-W, VPU-R)
+ * @sf_ref_fb : record supoer frame reference buffer information
+ *	(AP-R/W, VPU-R/W)
+ * @sf_next_ref_fb_idx : next available super frame (AP-W, VPU-R)
+ * @sf_frm_cnt : super frame count, filled by vpu (AP-R, VPU-W)
+ * @sf_frm_offset : super frame offset, filled by vpu (AP-R, VPU-W)
+ * @sf_frm_sz : super frame size, filled by vpu (AP-R, VPU-W)
+ * @sf_frm_idx : current super frame (AP-R, VPU-W)
+ * @sf_init : inform super frame info already parsed by vpu (AP-R, VPU-W)
+ * @fb : capture buffer (AP-W, VPU-R)
+ * @bs : bs buffer (AP-W, VPU-R)
+ * @cur_fb : current show capture buffer (AP-R/W, VPU-R/W)
+ * @pic_w : picture width (AP-R, VPU-W)
+ * @pic_h : picture height (AP-R, VPU-W)
+ * @buf_w : codec width (AP-R, VPU-W)
+ * @buf_h : coded height (AP-R, VPU-W)
+ * @buf_sz_y_bs : ufo compressed y plane size (AP-R, VPU-W)
+ * @buf_sz_c_bs : ufo compressed cbcr plane size (AP-R, VPU-W)
+ * @buf_len_sz_y : size used to store y plane ufo info (AP-R, VPU-W)
+ * @buf_len_sz_c : size used to store cbcr plane ufo info (AP-R, VPU-W)
+
+ * @profile : profile sparsed from vpu (AP-R, VPU-W)
+ * @show_frame : display this frame or not (AP-R, VPU-W)
+ * @show_existing_frame : inform this frame is show existing frame
+ *	(AP-R, VPU-W)
+ * @frm_to_show_idx : index to show frame (AP-R, VPU-W)
+
+ * @refresh_frm_flags : indicate when frame need to refine reference count
+ *	(AP-R, VPU-W)
+ * @resolution_changed : resolution change in this frame (AP-R, VPU-W)
+
+ * @frm_bufs : maintain reference buffer info (AP-R/W, VPU-R/W)
+ * @ref_frm_map : maintain reference buffer map info (AP-R/W, VPU-R/W)
+ * @new_fb_idx : index to frm_bufs array (AP-R, VPU-W)
+ * @frm_num : decoded frame number, include sub-frame count (AP-R, VPU-W)
+ * @mv_buf : motion vector working buffer (AP-W, VPU-R)
+ * @frm_refs : maintain three reference buffer info (AP-R/W, VPU-R/W)
+ */
+struct vdec_vp9_vsi {
+	unsigned char sf_bs_buf[VP9_SUPER_FRAME_BS_SZ];
+	struct vp9_sf_ref_fb sf_ref_fb[VP9_MAX_FRM_BUF_NUM-1];
+	int sf_next_ref_fb_idx;
+	unsigned int sf_frm_cnt;
+	unsigned int sf_frm_offset[VP9_MAX_FRM_BUF_NUM-1];
+	unsigned int sf_frm_sz[VP9_MAX_FRM_BUF_NUM-1];
+	unsigned int sf_frm_idx;
+	unsigned int sf_init;
+	struct vdec_fb fb;
+	struct mtk_vcodec_mem bs;
+	struct vdec_fb cur_fb;
+	unsigned int pic_w;
+	unsigned int pic_h;
+	unsigned int buf_w;
+	unsigned int buf_h;
+	unsigned int buf_sz_y_bs;
+	unsigned int buf_sz_c_bs;
+	unsigned int buf_len_sz_y;
+	unsigned int buf_len_sz_c;
+	unsigned int profile;
+	unsigned int show_frame;
+	unsigned int show_existing_frame;
+	unsigned int frm_to_show_idx;
+	unsigned int refresh_frm_flags;
+	unsigned int resolution_changed;
+
+	struct vp9_ref_cnt_buf frm_bufs[VP9_MAX_FRM_BUF_NUM];
+	int ref_frm_map[MAX_NUM_REF_FRAMES];
+	unsigned int new_fb_idx;
+	unsigned int frm_num;
+	struct vp9_dram_buf mv_buf;
+
+	struct vp9_ref_buf frm_refs[REFS_PER_FRAME];
+};
+
+/*
+ * struct vdec_vp9_inst - vp9 decode instance
+ * @mv_buf : working buffer for mv
+ * @dec_fb : vdec_fb node to link fb to different fb_xxx_list
+ * @available_fb_node_list : current available vdec_fb node
+ * @fb_use_list : current used or referenced vdec_fb
+ * @fb_free_list : current available to free vdec_fb
+ * @fb_disp_list : current available to display vdec_fb
+ * @cur_fb : current frame buffer
+ * @ctx : current decode context
+ * @vpu : vpu instance information
+ * @vsi : shared buffer between host and VPU firmware
+ * @total_frm_cnt : total frame count, it do not include sub-frames in super
+ *	    frame
+ * @mem : instance memory information
+ */
+struct vdec_vp9_inst {
+	struct mtk_vcodec_mem mv_buf;
+
+	struct vdec_fb_node dec_fb[VP9_MAX_FRM_BUF_NODE_NUM];
+	struct list_head available_fb_node_list;
+	struct list_head fb_use_list;
+	struct list_head fb_free_list;
+	struct list_head fb_disp_list;
+	struct vdec_fb *cur_fb;
+	struct mtk_vcodec_ctx *ctx;
+	struct vdec_vpu_inst vpu;
+	struct vdec_vp9_vsi *vsi;
+	unsigned int total_frm_cnt;
+	struct mtk_vcodec_mem mem;
+};
+
+static bool vp9_is_sf_ref_fb(struct vdec_vp9_inst *inst, struct vdec_fb *fb)
+{
+	int i;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
+		if (fb == &vsi->sf_ref_fb[i].fb)
+			return true;
+	}
+	return false;
+}
+
+static struct vdec_fb *vp9_rm_from_fb_use_list(struct vdec_vp9_inst
+					*inst, void *addr)
+{
+	struct vdec_fb *fb = NULL;
+	struct vdec_fb_node *node;
+
+	list_for_each_entry(node, &inst->fb_use_list, list) {
+		fb = (struct vdec_fb *)node->fb;
+		if (fb->base_y.va == addr) {
+			list_move_tail(&node->list,
+				       &inst->available_fb_node_list);
+			break;
+		}
+	}
+	return fb;
+}
+
+static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst,
+			     struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (fb) {
+		node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+
+		if (node) {
+			node->fb = fb;
+			list_move_tail(&node->list, &inst->fb_free_list);
+		}
+	} else {
+		mtk_vcodec_debug(inst, "No free fb node");
+	}
+}
+
+static void vp9_free_sf_ref_fb(struct vdec_fb *fb)
+{
+	struct vp9_sf_ref_fb *sf_ref_fb =
+		container_of(fb, struct vp9_sf_ref_fb, fb);
+
+	sf_ref_fb->used = 0;
+}
+
+static void vp9_ref_cnt_fb(struct vdec_vp9_inst *inst, int *idx,
+			   int new_idx)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	int ref_idx = *idx;
+
+	if (ref_idx >= 0 && vsi->frm_bufs[ref_idx].ref_cnt > 0) {
+		vsi->frm_bufs[ref_idx].ref_cnt--;
+
+		if (vsi->frm_bufs[ref_idx].ref_cnt == 0) {
+			if (!vp9_is_sf_ref_fb(inst,
+					      vsi->frm_bufs[ref_idx].buf.fb)) {
+				struct vdec_fb *fb;
+
+				fb = vp9_rm_from_fb_use_list(inst,
+				     vsi->frm_bufs[ref_idx].buf.fb->base_y.va);
+				vp9_add_to_fb_free_list(inst, fb);
+			} else
+				vp9_free_sf_ref_fb(
+					vsi->frm_bufs[ref_idx].buf.fb);
+		}
+	}
+
+	*idx = new_idx;
+	vsi->frm_bufs[new_idx].ref_cnt++;
+}
+
+static void vp9_free_all_sf_ref_fb(struct vdec_vp9_inst *inst)
+{
+	int i;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (i = 0; i < ARRAY_SIZE(vsi->sf_ref_fb); i++) {
+		if (vsi->sf_ref_fb[i].fb.base_y.va) {
+			mtk_vcodec_mem_free(inst->ctx,
+				&vsi->sf_ref_fb[i].fb.base_y);
+			mtk_vcodec_mem_free(inst->ctx,
+				&vsi->sf_ref_fb[i].fb.base_c);
+			vsi->sf_ref_fb[i].used = 0;
+		}
+	}
+}
+
+/* For each sub-frame except the last one, the driver will dynamically
+ * allocate reference buffer by calling vp9_get_sf_ref_fb()
+ * The last sub-frame will use the original fb provided by the
+ * vp9_dec_decode() interface
+ */
+static int vp9_get_sf_ref_fb(struct vdec_vp9_inst *inst)
+{
+	int idx;
+	struct mtk_vcodec_mem *mem_basy_y;
+	struct mtk_vcodec_mem *mem_basy_c;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	for (idx = 0;
+		idx < ARRAY_SIZE(vsi->sf_ref_fb);
+		idx++) {
+		if (vsi->sf_ref_fb[idx].fb.base_y.va &&
+		    vsi->sf_ref_fb[idx].used == 0) {
+			return idx;
+		}
+	}
+
+	for (idx = 0;
+		idx < ARRAY_SIZE(vsi->sf_ref_fb);
+		idx++) {
+		if (vsi->sf_ref_fb[idx].fb.base_y.va == NULL)
+			break;
+	}
+
+	if (idx == ARRAY_SIZE(vsi->sf_ref_fb)) {
+		mtk_vcodec_err(inst, "List Full");
+		return -1;
+	}
+
+	mem_basy_y = &vsi->sf_ref_fb[idx].fb.base_y;
+	mem_basy_y->size = vsi->buf_sz_y_bs +
+		vsi->buf_len_sz_y;
+
+	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_y)) {
+		mtk_vcodec_err(inst, "Cannot allocate sf_ref_buf y_buf");
+		return -1;
+	}
+
+	mem_basy_c = &vsi->sf_ref_fb[idx].fb.base_c;
+	mem_basy_c->size = vsi->buf_sz_c_bs +
+		vsi->buf_len_sz_c;
+
+	if (mtk_vcodec_mem_alloc(inst->ctx, mem_basy_c)) {
+		mtk_vcodec_err(inst, "Cannot allocate sf_ref_fb c_buf");
+		return -1;
+	}
+	vsi->sf_ref_fb[idx].used = 0;
+
+	return idx;
+}
+
+static bool vp9_alloc_work_buf(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	int result;
+	struct mtk_vcodec_mem *mem;
+
+	unsigned int max_pic_w;
+	unsigned int max_pic_h;
+
+
+	if (!(inst->ctx->dev->dec_capability &
+		VCODEC_CAPABILITY_4K_DISABLED)) {
+		max_pic_w = VCODEC_DEC_4K_CODED_WIDTH;
+		max_pic_h = VCODEC_DEC_4K_CODED_HEIGHT;
+	} else {
+		max_pic_w = MTK_VDEC_MAX_W;
+		max_pic_h = MTK_VDEC_MAX_H;
+	}
+
+	if ((vsi->pic_w > max_pic_w) ||
+		(vsi->pic_h > max_pic_h)) {
+		mtk_vcodec_err(inst, "Invalid w/h %d/%d",
+				vsi->pic_w, vsi->pic_h);
+		return false;
+	}
+
+	mtk_vcodec_debug(inst, "BUF CHG(%d): w/h/sb_w/sb_h=%d/%d/%d/%d",
+			vsi->resolution_changed,
+			vsi->pic_w,
+			vsi->pic_h,
+			vsi->buf_w,
+			vsi->buf_h);
+
+	mem = &inst->mv_buf;
+
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	mem->size = ((vsi->buf_w / 64) *
+		    (vsi->buf_h / 64) + 2) * 36 * 16;
+
+	result = mtk_vcodec_mem_alloc(inst->ctx, mem);
+	if (result) {
+		mem->size = 0;
+		mtk_vcodec_err(inst, "Cannot allocate mv_buf");
+		return false;
+	}
+	/* Set the va again */
+	vsi->mv_buf.va = (unsigned long)mem->va;
+	vsi->mv_buf.pa = (unsigned long)mem->dma_addr;
+	vsi->mv_buf.sz = (unsigned int)mem->size;
+
+	vp9_free_all_sf_ref_fb(inst);
+	vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+
+	return true;
+}
+
+static bool vp9_add_to_fb_disp_list(struct vdec_vp9_inst *inst,
+			     struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (!fb) {
+		mtk_vcodec_err(inst, "fb == NULL");
+		return false;
+	}
+
+	node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_disp_list);
+	} else {
+		mtk_vcodec_err(inst, "No available fb node");
+		return false;
+	}
+
+	return true;
+}
+
+/* If any buffer updating is signaled it should be done here. */
+static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	struct vp9_fb_info *frm_to_show;
+	int ref_index = 0, mask;
+
+	for (mask = vsi->refresh_frm_flags; mask; mask >>= 1) {
+		if (mask & 1)
+			vp9_ref_cnt_fb(inst, &vsi->ref_frm_map[ref_index],
+				       vsi->new_fb_idx);
+		++ref_index;
+	}
+
+	frm_to_show = &vsi->frm_bufs[vsi->new_fb_idx].buf;
+	vsi->frm_bufs[vsi->new_fb_idx].ref_cnt--;
+
+	if (frm_to_show->fb != inst->cur_fb) {
+		/* This frame is show exist frame and no decode output
+		 * copy frame data from frm_to_show to current CAPTURE
+		 * buffer
+		 */
+		if ((frm_to_show->fb != NULL) &&
+			(inst->cur_fb->base_y.size >=
+			frm_to_show->fb->base_y.size)) {
+			memcpy((void *)inst->cur_fb->base_y.va,
+				(void *)frm_to_show->fb->base_y.va,
+				vsi->buf_w *
+				vsi->buf_h);
+			memcpy((void *)inst->cur_fb->base_c.va,
+				(void *)frm_to_show->fb->base_c.va,
+				vsi->buf_w *
+				vsi->buf_h / 2);
+		} else {
+			/* After resolution change case, current CAPTURE buffer
+			 * may have less buffer size than frm_to_show buffer
+			 * size
+			 */
+			if (frm_to_show->fb != NULL)
+				mtk_vcodec_err(inst,
+					"inst->cur_fb->base_y.size=%zu, frm_to_show->fb.base_y.size=%zu",
+					inst->cur_fb->base_y.size,
+					frm_to_show->fb->base_y.size);
+		}
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
+			if (vsi->show_frame)
+				vp9_add_to_fb_disp_list(inst, inst->cur_fb);
+		}
+	} else {
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb)) {
+			if (vsi->show_frame)
+				vp9_add_to_fb_disp_list(inst, frm_to_show->fb);
+		}
+	}
+
+	/* when ref_cnt ==0, move this fb to fb_free_list. v4l2 driver will
+	 * clean fb_free_list
+	 */
+	if (vsi->frm_bufs[vsi->new_fb_idx].ref_cnt == 0) {
+		if (!vp9_is_sf_ref_fb(
+			inst, vsi->frm_bufs[vsi->new_fb_idx].buf.fb)) {
+			struct vdec_fb *fb;
+
+			fb = vp9_rm_from_fb_use_list(inst,
+			vsi->frm_bufs[vsi->new_fb_idx].buf.fb->base_y.va);
+
+			vp9_add_to_fb_free_list(inst, fb);
+		} else {
+			vp9_free_sf_ref_fb(
+				vsi->frm_bufs[vsi->new_fb_idx].buf.fb);
+		}
+	}
+
+	/* if this super frame and it is not last sub-frame, get next fb for
+	 * sub-frame decode
+	 */
+	if (vsi->sf_frm_cnt > 0 && vsi->sf_frm_idx != vsi->sf_frm_cnt - 1)
+		vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+}
+
+static bool vp9_wait_dec_end(struct vdec_vp9_inst *inst)
+{
+	struct mtk_vcodec_ctx *ctx = inst->ctx;
+
+	mtk_vcodec_wait_for_done_ctx(inst->ctx,
+			MTK_INST_IRQ_RECEIVED,
+			WAIT_INTR_TIMEOUT_MS);
+
+	if (ctx->irq_status & MTK_VDEC_IRQ_STATUS_DEC_SUCCESS)
+		return true;
+	else
+		return false;
+}
+
+static struct vdec_vp9_inst *vp9_alloc_inst(struct mtk_vcodec_ctx *ctx)
+{
+	int result;
+	struct mtk_vcodec_mem mem;
+	struct vdec_vp9_inst *inst;
+
+	memset(&mem, 0, sizeof(mem));
+	mem.size = sizeof(struct vdec_vp9_inst);
+	result = mtk_vcodec_mem_alloc(ctx, &mem);
+	if (result)
+		return NULL;
+
+	inst = mem.va;
+	inst->mem = mem;
+
+	return inst;
+}
+
+static void vp9_free_inst(struct vdec_vp9_inst *inst)
+{
+	struct mtk_vcodec_mem mem;
+
+	mem = inst->mem;
+	if (mem.va)
+		mtk_vcodec_mem_free(inst->ctx, &mem);
+}
+
+static bool vp9_decode_end_proc(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	bool ret = false;
+
+	if (!vsi->show_existing_frame) {
+		ret = vp9_wait_dec_end(inst);
+		if (!ret) {
+			mtk_vcodec_err(inst, "Decode failed, Decode Timeout @[%d]",
+				vsi->frm_num);
+			return false;
+		}
+
+		if (vpu_dec_end(&inst->vpu)) {
+			mtk_vcodec_err(inst, "vp9_dec_vpu_end failed");
+			return false;
+		}
+		mtk_vcodec_debug(inst, "Decode Ok @%d (%d/%d)", vsi->frm_num,
+				vsi->pic_w, vsi->pic_h);
+	} else {
+		mtk_vcodec_debug(inst, "Decode Ok @%d (show_existing_frame)",
+				vsi->frm_num);
+	}
+
+	vp9_swap_frm_bufs(inst);
+	vsi->frm_num++;
+	return true;
+}
+
+static bool vp9_is_last_sub_frm(struct vdec_vp9_inst *inst)
+{
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+
+	if (vsi->sf_frm_cnt <= 0 || vsi->sf_frm_idx == vsi->sf_frm_cnt)
+		return true;
+
+	return false;
+}
+
+static struct vdec_fb *vp9_rm_from_fb_disp_list(struct vdec_vp9_inst *inst)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb = NULL;
+
+	node = list_first_entry_or_null(&inst->fb_disp_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_DISPLAY;
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		mtk_vcodec_debug(inst, "[FB] get disp fb %p st=%d",
+				 node->fb, fb->status);
+	} else
+		mtk_vcodec_debug(inst, "[FB] there is no disp fb");
+
+	return fb;
+}
+
+static bool vp9_add_to_fb_use_list(struct vdec_vp9_inst *inst,
+			    struct vdec_fb *fb)
+{
+	struct vdec_fb_node *node;
+
+	if (!fb) {
+		mtk_vcodec_debug(inst, "fb == NULL");
+		return false;
+	}
+
+	node = list_first_entry_or_null(&inst->available_fb_node_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		node->fb = fb;
+		list_move_tail(&node->list, &inst->fb_use_list);
+	} else {
+		mtk_vcodec_err(inst, "No free fb node");
+		return false;
+	}
+	return true;
+}
+
+static void vp9_reset(struct vdec_vp9_inst *inst)
+{
+	struct vdec_fb_node *node, *tmp;
+
+	list_for_each_entry_safe(node, tmp, &inst->fb_use_list, list)
+		list_move_tail(&node->list, &inst->fb_free_list);
+
+	vp9_free_all_sf_ref_fb(inst);
+	inst->vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst);
+
+	if (vpu_dec_reset(&inst->vpu))
+		mtk_vcodec_err(inst, "vp9_dec_vpu_reset failed");
+
+	/* Set the va again, since vpu_dec_reset will clear mv_buf in vpu */
+	inst->vsi->mv_buf.va = (unsigned long)inst->mv_buf.va;
+	inst->vsi->mv_buf.pa = (unsigned long)inst->mv_buf.dma_addr;
+	inst->vsi->mv_buf.sz = (unsigned long)inst->mv_buf.size;
+}
+
+static void init_all_fb_lists(struct vdec_vp9_inst *inst)
+{
+	int i;
+
+	INIT_LIST_HEAD(&inst->available_fb_node_list);
+	INIT_LIST_HEAD(&inst->fb_use_list);
+	INIT_LIST_HEAD(&inst->fb_free_list);
+	INIT_LIST_HEAD(&inst->fb_disp_list);
+
+	for (i = 0; i < ARRAY_SIZE(inst->dec_fb); i++) {
+		INIT_LIST_HEAD(&inst->dec_fb[i].list);
+		inst->dec_fb[i].fb = NULL;
+		list_add_tail(&inst->dec_fb[i].list,
+			      &inst->available_fb_node_list);
+	}
+}
+
+static void get_pic_info(struct vdec_vp9_inst *inst, struct vdec_pic_info *pic)
+{
+	pic->y_bs_sz = inst->vsi->buf_sz_y_bs;
+	pic->c_bs_sz = inst->vsi->buf_sz_c_bs;
+	pic->y_len_sz = inst->vsi->buf_len_sz_y;
+	pic->c_len_sz = inst->vsi->buf_len_sz_c;
+
+	pic->pic_w = inst->vsi->pic_w;
+	pic->pic_h = inst->vsi->pic_h;
+	pic->buf_w = inst->vsi->buf_w;
+	pic->buf_h = inst->vsi->buf_h;
+
+	mtk_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+		 pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
+	mtk_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+		 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_disp_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
+{
+
+	*out_fb = vp9_rm_from_fb_disp_list(inst);
+	if (*out_fb)
+		(*out_fb)->status |= FB_ST_DISPLAY;
+}
+
+static void get_free_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb)
+{
+	struct vdec_fb_node *node;
+	struct vdec_fb *fb = NULL;
+
+	node = list_first_entry_or_null(&inst->fb_free_list,
+					struct vdec_fb_node, list);
+	if (node) {
+		list_move_tail(&node->list, &inst->available_fb_node_list);
+		fb = (struct vdec_fb *)node->fb;
+		fb->status |= FB_ST_FREE;
+		mtk_vcodec_debug(inst, "[FB] get free fb %p st=%d",
+				 node->fb, fb->status);
+	} else {
+		mtk_vcodec_debug(inst, "[FB] there is no free fb");
+	}
+
+	*out_fb = fb;
+}
+
+static void vdec_vp9_deinit(unsigned long h_vdec)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct mtk_vcodec_mem *mem;
+	int ret = 0;
+
+	ret = vpu_dec_deinit(&inst->vpu);
+	if (ret)
+		mtk_vcodec_err(inst, "vpu_dec_deinit failed");
+
+	mem = &inst->mv_buf;
+	if (mem->va)
+		mtk_vcodec_mem_free(inst->ctx, mem);
+
+	vp9_free_all_sf_ref_fb(inst);
+	vp9_free_inst(inst);
+}
+
+static int vdec_vp9_init(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+	struct vdec_vp9_inst *inst;
+
+	inst = vp9_alloc_inst(ctx);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->total_frm_cnt = 0;
+	inst->ctx = ctx;
+
+	inst->vpu.id = IPI_VDEC_VP9;
+	inst->vpu.dev = ctx->dev->vpu_plat_dev;
+	inst->vpu.ctx = ctx;
+	inst->vpu.handler = vpu_dec_ipi_handler;
+
+	if (vpu_dec_init(&inst->vpu)) {
+		mtk_vcodec_err(inst, "vp9_dec_vpu_init failed");
+		goto err_deinit_inst;
+	}
+
+	inst->vsi = (struct vdec_vp9_vsi *)inst->vpu.vsi;
+	init_all_fb_lists(inst);
+
+	(*h_vdec) = (unsigned long)inst;
+	return 0;
+
+err_deinit_inst:
+	vp9_free_inst(inst);
+
+	return -EINVAL;
+}
+
+static int vdec_vp9_decode(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg)
+{
+	int ret = 0;
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	struct vdec_vp9_vsi *vsi = inst->vsi;
+	u32 data[3];
+	int i;
+
+	*res_chg = false;
+
+	if ((bs == NULL) && (fb == NULL)) {
+		mtk_vcodec_debug(inst, "[EOS]");
+		vp9_reset(inst);
+		return ret;
+	}
+
+	if (bs == NULL) {
+		mtk_vcodec_err(inst, "bs == NULL");
+		return -EINVAL;
+	}
+
+	mtk_vcodec_debug(inst, "Input BS Size = %zu", bs->size);
+
+	while (1) {
+		struct vdec_fb *cur_fb = NULL;
+
+		data[0] = *((unsigned int *)bs->va);
+		data[1] = *((unsigned int *)(bs->va + 4));
+		data[2] = *((unsigned int *)(bs->va + 8));
+
+		vsi->bs = *bs;
+
+		if (fb)
+			vsi->fb = *fb;
+
+		if (!vsi->sf_init) {
+			unsigned int sf_bs_sz;
+			unsigned int sf_bs_off;
+			unsigned char *sf_bs_src;
+			unsigned char *sf_bs_dst;
+
+			sf_bs_sz = bs->size > VP9_SUPER_FRAME_BS_SZ ?
+					VP9_SUPER_FRAME_BS_SZ : bs->size;
+			sf_bs_off = VP9_SUPER_FRAME_BS_SZ - sf_bs_sz;
+			sf_bs_src = bs->va + bs->size - sf_bs_sz;
+			sf_bs_dst = vsi->sf_bs_buf + sf_bs_off;
+			memcpy(sf_bs_dst, sf_bs_src, sf_bs_sz);
+		} else {
+			if ((vsi->sf_frm_cnt > 0) &&
+				(vsi->sf_frm_idx < vsi->sf_frm_cnt)) {
+				unsigned int idx = vsi->sf_frm_idx;
+
+				memcpy((void *)bs->va,
+					(void *)(bs->va +
+					vsi->sf_frm_offset[idx]),
+					vsi->sf_frm_sz[idx]);
+			}
+		}
+		ret = vpu_dec_start(&inst->vpu, data, 3);
+		if (ret) {
+			mtk_vcodec_err(inst, "vpu_dec_start failed");
+			goto DECODE_ERROR;
+		}
+
+		if (vsi->resolution_changed) {
+			if (!vp9_alloc_work_buf(inst)) {
+				ret = -EINVAL;
+				goto DECODE_ERROR;
+			}
+		}
+
+		if (vsi->sf_frm_cnt > 0) {
+			cur_fb = &vsi->sf_ref_fb[vsi->sf_next_ref_fb_idx].fb;
+
+			if (vsi->sf_frm_idx < vsi->sf_frm_cnt)
+				inst->cur_fb = cur_fb;
+			else
+				inst->cur_fb = fb;
+		} else {
+			inst->cur_fb = fb;
+		}
+
+		vsi->frm_bufs[vsi->new_fb_idx].buf.fb = inst->cur_fb;
+		if (!vp9_is_sf_ref_fb(inst, inst->cur_fb))
+			vp9_add_to_fb_use_list(inst, inst->cur_fb);
+
+		mtk_vcodec_debug(inst, "[#pic %d]", vsi->frm_num);
+
+		if (vsi->show_existing_frame)
+			mtk_vcodec_debug(inst,
+				"drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
+				vsi->new_fb_idx, vsi->frm_to_show_idx);
+
+		if (vsi->show_existing_frame && (vsi->frm_to_show_idx <
+					VP9_MAX_FRM_BUF_NUM)) {
+			mtk_vcodec_err(inst,
+				"Skip Decode drv->new_fb_idx=%d, drv->frm_to_show_idx=%d",
+				vsi->new_fb_idx, vsi->frm_to_show_idx);
+
+			vp9_ref_cnt_fb(inst, &vsi->new_fb_idx,
+					vsi->frm_to_show_idx);
+			ret = -EINVAL;
+			goto DECODE_ERROR;
+		}
+
+		/* VPU assign the buffer pointer in its address space,
+		 * reassign here
+		 */
+		for (i = 0; i < ARRAY_SIZE(vsi->frm_refs); i++) {
+			unsigned int idx = vsi->frm_refs[i].idx;
+
+			vsi->frm_refs[i].buf = &vsi->frm_bufs[idx].buf;
+		}
+
+		if (vsi->resolution_changed) {
+			*res_chg = true;
+			mtk_vcodec_debug(inst, "VDEC_ST_RESOLUTION_CHANGED");
+
+			ret = 0;
+			goto DECODE_ERROR;
+		}
+
+		if (vp9_decode_end_proc(inst) != true) {
+			mtk_vcodec_err(inst, "vp9_decode_end_proc");
+			ret = -EINVAL;
+			goto DECODE_ERROR;
+		}
+
+		if (vp9_is_last_sub_frm(inst))
+			break;
+
+	}
+	inst->total_frm_cnt++;
+
+DECODE_ERROR:
+	if (ret < 0)
+		vp9_add_to_fb_free_list(inst, fb);
+
+	return ret;
+}
+
+static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
+{
+	cr->left = 0;
+	cr->top = 0;
+	cr->width = inst->vsi->pic_w;
+	cr->height = inst->vsi->pic_h;
+	mtk_vcodec_debug(inst, "get crop info l=%d, t=%d, w=%d, h=%d\n",
+			 cr->left, cr->top, cr->width, cr->height);
+}
+
+static int vdec_vp9_get_param(unsigned long h_vdec,
+		enum vdec_get_param_type type, void *out)
+{
+	struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
+	int ret = 0;
+
+	switch (type) {
+	case GET_PARAM_DISP_FRAME_BUFFER:
+		get_disp_fb(inst, out);
+		break;
+	case GET_PARAM_FREE_FRAME_BUFFER:
+		get_free_fb(inst, out);
+		break;
+	case GET_PARAM_PIC_INFO:
+		get_pic_info(inst, out);
+		break;
+	case GET_PARAM_DPB_SIZE:
+		*((unsigned int *)out) = MAX_VP9_DPB_SIZE;
+		break;
+	case GET_PARAM_CROP_INFO:
+		get_crop_info(inst, out);
+		break;
+	default:
+		mtk_vcodec_err(inst, "not supported param type %d", type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static struct vdec_common_if vdec_vp9_if = {
+	vdec_vp9_init,
+	vdec_vp9_decode,
+	vdec_vp9_get_param,
+	vdec_vp9_deinit,
+};
+
+struct vdec_common_if *get_vp9_dec_comm_if(void);
+
+struct vdec_common_if *get_vp9_dec_comm_if(void)
+{
+	return &vdec_vp9_if;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_base.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_base.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_base.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_base.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_DRV_BASE_
+#define _VDEC_DRV_BASE_
+
+#include "mtk_vcodec_drv.h"
+
+#include "vdec_drv_if.h"
+
+struct vdec_common_if {
+	/**
+	 * (*init)() - initialize decode driver
+	 * @ctx     : [in] mtk v4l2 context
+	 * @h_vdec  : [out] driver handle
+	 */
+	int (*init)(struct mtk_vcodec_ctx *ctx, unsigned long *h_vdec);
+
+	/**
+	 * (*decode)() - trigger decode
+	 * @h_vdec  : [in] driver handle
+	 * @bs      : [in] input bitstream
+	 * @fb      : [in] frame buffer to store decoded frame
+	 * @res_chg : [out] resolution change happen
+	 */
+	int (*decode)(unsigned long h_vdec, struct mtk_vcodec_mem *bs,
+		      struct vdec_fb *fb, bool *res_chg);
+
+	/**
+	 * (*get_param)() - get driver's parameter
+	 * @h_vdec : [in] driver handle
+	 * @type   : [in] input parameter type
+	 * @out    : [out] buffer to store query result
+	 */
+	int (*get_param)(unsigned long h_vdec, enum vdec_get_param_type type,
+			 void *out);
+
+	/**
+	 * (*deinit)() - deinitialize driver.
+	 * @h_vdec : [in] driver handle to be deinit
+	 */
+	void (*deinit)(unsigned long h_vdec);
+};
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *         Tiffany Lin <tiffany.lin@mediatek.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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "vdec_drv_if.h"
+#include "mtk_vcodec_dec.h"
+#include "vdec_drv_base.h"
+#include "mtk_vcodec_dec_pm.h"
+#include "mtk_vpu.h"
+
+const struct vdec_common_if *get_h264_dec_comm_if(void);
+const struct vdec_common_if *get_vp8_dec_comm_if(void);
+const struct vdec_common_if *get_vp9_dec_comm_if(void);
+
+int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc)
+{
+	int ret = 0;
+
+	switch (fourcc) {
+	case V4L2_PIX_FMT_H264:
+		ctx->dec_if = get_h264_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_VP8:
+		ctx->dec_if = get_vp8_dec_comm_if();
+		break;
+	case V4L2_PIX_FMT_VP9:
+		ctx->dec_if = get_vp9_dec_comm_if();
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mtk_vdec_lock(ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	ret = ctx->dec_if->init(ctx, &ctx->drv_handle);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg)
+{
+	int ret = 0;
+
+	if (bs) {
+		if ((bs->dma_addr & 63) != 0) {
+			mtk_v4l2_err("bs dma_addr should 64 byte align");
+			return -EINVAL;
+		}
+	}
+
+	if (fb) {
+		if (((fb->base_y.dma_addr & 511) != 0) ||
+		    ((fb->base_c.dma_addr & 511) != 0)) {
+			mtk_v4l2_err("frame buffer dma_addr should 512 byte align");
+			return -EINVAL;
+		}
+	}
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	mtk_vdec_lock(ctx);
+
+	mtk_vcodec_set_curr_ctx(ctx->dev, ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	enable_irq(ctx->dev->dec_irq);
+	ret = ctx->dec_if->decode(ctx->drv_handle, bs, fb, res_chg);
+	disable_irq(ctx->dev->dec_irq);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vcodec_set_curr_ctx(ctx->dev, NULL);
+
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
+		      void *out)
+{
+	int ret = 0;
+
+	if (ctx->drv_handle == 0)
+		return -EIO;
+
+	mtk_vdec_lock(ctx);
+	ret = ctx->dec_if->get_param(ctx->drv_handle, type, out);
+	mtk_vdec_unlock(ctx);
+
+	return ret;
+}
+
+void vdec_if_deinit(struct mtk_vcodec_ctx *ctx)
+{
+	if (ctx->drv_handle == 0)
+		return;
+
+	mtk_vdec_lock(ctx);
+	mtk_vcodec_dec_clock_on(&ctx->dev->pm);
+	ctx->dec_if->deinit(ctx->drv_handle);
+	mtk_vcodec_dec_clock_off(&ctx->dev->pm);
+	mtk_vdec_unlock(ctx);
+
+	ctx->drv_handle = 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_drv_if.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *		   Tiffany Lin <tiffany.lin@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_DRV_IF_H_
+#define _VDEC_DRV_IF_H_
+
+#include "mtk_vcodec_drv.h"
+#include "mtk_vcodec_dec.h"
+#include "mtk_vcodec_util.h"
+
+
+/**
+ * struct vdec_fb_status  - decoder frame buffer status
+ * @FB_ST_NORMAL	: initial state
+ * @FB_ST_DISPLAY	: frmae buffer is ready to be displayed
+ * @FB_ST_FREE		: frame buffer is not used by decoder any more
+ */
+enum vdec_fb_status {
+	FB_ST_NORMAL		= 0,
+	FB_ST_DISPLAY		= (1 << 0),
+	FB_ST_FREE		= (1 << 1)
+};
+
+/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER,
+ * the caller does not own the returned buffer. The buffer will not be
+ *				released before vdec_if_deinit.
+ * GET_PARAM_DISP_FRAME_BUFFER	: get next displayable frame buffer,
+ *				struct vdec_fb**
+ * GET_PARAM_FREE_FRAME_BUFFER	: get non-referenced framebuffer, vdec_fb**
+ * GET_PARAM_PIC_INFO		: get picture info, struct vdec_pic_info*
+ * GET_PARAM_CROP_INFO		: get crop info, struct v4l2_crop*
+ * GET_PARAM_DPB_SIZE		: get dpb size, unsigned int*
+ */
+enum vdec_get_param_type {
+	GET_PARAM_DISP_FRAME_BUFFER,
+	GET_PARAM_FREE_FRAME_BUFFER,
+	GET_PARAM_PIC_INFO,
+	GET_PARAM_CROP_INFO,
+	GET_PARAM_DPB_SIZE
+};
+
+/**
+ * struct vdec_fb_node  - decoder frame buffer node
+ * @list	: list to hold this node
+ * @fb	: point to frame buffer (vdec_fb), fb could point to frame buffer and
+ *	working buffer this is for maintain buffers in different state
+ */
+struct vdec_fb_node {
+	struct list_head list;
+	struct vdec_fb *fb;
+};
+
+/**
+ * vdec_if_init() - initialize decode driver
+ * @ctx	: [in] v4l2 context
+ * @fourcc	: [in] video format fourcc, V4L2_PIX_FMT_H264/VP8/VP9..
+ */
+int vdec_if_init(struct mtk_vcodec_ctx *ctx, unsigned int fourcc);
+
+/**
+ * vdec_if_deinit() - deinitialize decode driver
+ * @ctx	: [in] v4l2 context
+ *
+ */
+void vdec_if_deinit(struct mtk_vcodec_ctx *ctx);
+
+/**
+ * vdec_if_decode() - trigger decode
+ * @ctx	: [in] v4l2 context
+ * @bs	: [in] input bitstream
+ * @fb	: [in] frame buffer to store decoded frame, when null menas parse
+ *	header only
+ * @res_chg	: [out] resolution change happens if current bs have different
+ *	picture width/height
+ * Note: To flush the decoder when reaching EOF, set input bitstream as NULL.
+ */
+int vdec_if_decode(struct mtk_vcodec_ctx *ctx, struct mtk_vcodec_mem *bs,
+		   struct vdec_fb *fb, bool *res_chg);
+
+/**
+ * vdec_if_get_param() - get driver's parameter
+ * @ctx	: [in] v4l2 context
+ * @type	: [in] input parameter type
+ * @out	: [out] buffer to store query result
+ */
+int vdec_if_get_param(struct mtk_vcodec_ctx *ctx, enum vdec_get_param_type type,
+		      void *out);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_ipi_msg.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_IPI_MSG_H_
+#define _VDEC_IPI_MSG_H_
+
+/**
+ * enum vdec_ipi_msgid - message id between AP and VPU
+ * @AP_IPIMSG_XXX	: AP to VPU cmd message id
+ * @VPU_IPIMSG_XXX_ACK	: VPU ack AP cmd message id
+ */
+enum vdec_ipi_msgid {
+	AP_IPIMSG_DEC_INIT = 0xA000,
+	AP_IPIMSG_DEC_START = 0xA001,
+	AP_IPIMSG_DEC_END = 0xA002,
+	AP_IPIMSG_DEC_DEINIT = 0xA003,
+	AP_IPIMSG_DEC_RESET = 0xA004,
+
+	VPU_IPIMSG_DEC_INIT_ACK = 0xB000,
+	VPU_IPIMSG_DEC_START_ACK = 0xB001,
+	VPU_IPIMSG_DEC_END_ACK = 0xB002,
+	VPU_IPIMSG_DEC_DEINIT_ACK = 0xB003,
+	VPU_IPIMSG_DEC_RESET_ACK = 0xB004,
+};
+
+/**
+ * struct vdec_ap_ipi_cmd - generic AP to VPU ipi command format
+ * @msg_id	: vdec_ipi_msgid
+ * @vpu_inst_addr	: VPU decoder instance address
+ */
+struct vdec_ap_ipi_cmd {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+};
+
+/**
+ * struct vdec_vpu_ipi_ack - generic VPU to AP ipi command format
+ * @msg_id	: vdec_ipi_msgid
+ * @status	: VPU exeuction result
+ * @ap_inst_addr	: AP video decoder instance address
+ */
+struct vdec_vpu_ipi_ack {
+	uint32_t msg_id;
+	int32_t status;
+	uint64_t ap_inst_addr;
+};
+
+/**
+ * struct vdec_ap_ipi_init - for AP_IPIMSG_DEC_INIT
+ * @msg_id	: AP_IPIMSG_DEC_INIT
+ * @reserved	: Reserved field
+ * @ap_inst_addr	: AP video decoder instance address
+ */
+struct vdec_ap_ipi_init {
+	uint32_t msg_id;
+	uint32_t reserved;
+	uint64_t ap_inst_addr;
+};
+
+/**
+ * struct vdec_ap_ipi_dec_start - for AP_IPIMSG_DEC_START
+ * @msg_id	: AP_IPIMSG_DEC_START
+ * @vpu_inst_addr	: VPU decoder instance address
+ * @data	: Header info
+ *	H264 decoder [0]:buf_sz [1]:nal_start
+ *	VP8 decoder  [0]:width/height
+ *	VP9 decoder  [0]:profile, [1][2] width/height
+ * @reserved	: Reserved field
+ */
+struct vdec_ap_ipi_dec_start {
+	uint32_t msg_id;
+	uint32_t vpu_inst_addr;
+	uint32_t data[3];
+	uint32_t reserved;
+};
+
+/**
+ * struct vdec_vpu_ipi_init_ack - for VPU_IPIMSG_DEC_INIT_ACK
+ * @msg_id	: VPU_IPIMSG_DEC_INIT_ACK
+ * @status	: VPU exeuction result
+ * @ap_inst_addr	: AP vcodec_vpu_inst instance address
+ * @vpu_inst_addr	: VPU decoder instance address
+ */
+struct vdec_vpu_ipi_init_ack {
+	uint32_t msg_id;
+	int32_t status;
+	uint64_t ap_inst_addr;
+	uint32_t vpu_inst_addr;
+};
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.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 "mtk_vcodec_drv.h"
+#include "mtk_vcodec_util.h"
+#include "vdec_ipi_msg.h"
+#include "vdec_vpu_if.h"
+
+static void handle_init_ack_msg(struct vdec_vpu_ipi_init_ack *msg)
+{
+	struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *)
+					(unsigned long)msg->ap_inst_addr;
+
+	mtk_vcodec_debug(vpu, "+ ap_inst_addr = 0x%llx", msg->ap_inst_addr);
+
+	/* mapping VPU address to kernel virtual address */
+	/* the content in vsi is initialized to 0 in VPU */
+	vpu->vsi = vpu_mapping_dm_addr(vpu->dev, msg->vpu_inst_addr);
+	vpu->inst_addr = msg->vpu_inst_addr;
+
+	mtk_vcodec_debug(vpu, "- vpu_inst_addr = 0x%x", vpu->inst_addr);
+}
+
+/*
+ * This function runs in interrupt context and it means there's an IPI MSG
+ * from VPU.
+ */
+void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv)
+{
+	struct vdec_vpu_ipi_ack *msg = data;
+	struct vdec_vpu_inst *vpu = (struct vdec_vpu_inst *)
+					(unsigned long)msg->ap_inst_addr;
+
+	mtk_vcodec_debug(vpu, "+ id=%X", msg->msg_id);
+
+	if (msg->status == 0) {
+		switch (msg->msg_id) {
+		case VPU_IPIMSG_DEC_INIT_ACK:
+			handle_init_ack_msg(data);
+			break;
+
+		case VPU_IPIMSG_DEC_START_ACK:
+		case VPU_IPIMSG_DEC_END_ACK:
+		case VPU_IPIMSG_DEC_DEINIT_ACK:
+		case VPU_IPIMSG_DEC_RESET_ACK:
+			break;
+
+		default:
+			mtk_vcodec_err(vpu, "invalid msg=%X", msg->msg_id);
+			break;
+		}
+	}
+
+	mtk_vcodec_debug(vpu, "- id=%X", msg->msg_id);
+	vpu->failure = msg->status;
+	vpu->signaled = 1;
+}
+
+static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len)
+{
+	int err;
+	uint32_t msg_id = *(uint32_t *)msg;
+
+	mtk_vcodec_debug(vpu, "id=%X", msg_id);
+
+	vpu->failure = 0;
+	vpu->signaled = 0;
+
+	err = vpu_ipi_send(vpu->dev, vpu->id, msg, len);
+	if (err) {
+		mtk_vcodec_err(vpu, "send fail vpu_id=%d msg_id=%X status=%d",
+			       vpu->id, msg_id, err);
+		return err;
+	}
+
+	return vpu->failure;
+}
+
+static int vcodec_send_ap_ipi(struct vdec_vpu_inst *vpu, unsigned int msg_id)
+{
+	struct vdec_ap_ipi_cmd msg;
+	int err = 0;
+
+	mtk_vcodec_debug(vpu, "+ id=%X", msg_id);
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = msg_id;
+	msg.vpu_inst_addr = vpu->inst_addr;
+
+	err = vcodec_vpu_send_msg(vpu, &msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- id=%X ret=%d", msg_id, err);
+	return err;
+}
+
+int vpu_dec_init(struct vdec_vpu_inst *vpu)
+{
+	struct vdec_ap_ipi_init msg;
+	int err;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	init_waitqueue_head(&vpu->wq);
+
+	err = vpu_ipi_register(vpu->dev, vpu->id, vpu->handler, "vdec", NULL);
+	if (err != 0) {
+		mtk_vcodec_err(vpu, "vpu_ipi_register fail status=%d", err);
+		return err;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = AP_IPIMSG_DEC_INIT;
+	msg.ap_inst_addr = (unsigned long)vpu;
+
+	mtk_vcodec_debug(vpu, "vdec_inst=%p", vpu);
+
+	err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- ret=%d", err);
+	return err;
+}
+
+int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len)
+{
+	struct vdec_ap_ipi_dec_start msg;
+	int i;
+	int err = 0;
+
+	mtk_vcodec_debug_enter(vpu);
+
+	if (len > ARRAY_SIZE(msg.data)) {
+		mtk_vcodec_err(vpu, "invalid len = %d\n", len);
+		return -EINVAL;
+	}
+
+	memset(&msg, 0, sizeof(msg));
+	msg.msg_id = AP_IPIMSG_DEC_START;
+	msg.vpu_inst_addr = vpu->inst_addr;
+
+	for (i = 0; i < len; i++)
+		msg.data[i] = data[i];
+
+	err = vcodec_vpu_send_msg(vpu, (void *)&msg, sizeof(msg));
+	mtk_vcodec_debug(vpu, "- ret=%d", err);
+	return err;
+}
+
+int vpu_dec_end(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_END);
+}
+
+int vpu_dec_deinit(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_DEINIT);
+}
+
+int vpu_dec_reset(struct vdec_vpu_inst *vpu)
+{
+	return vcodec_send_ap_ipi(vpu, AP_IPIMSG_DEC_RESET);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vcodec/vdec_vpu_if.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: PC Chen <pc.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VDEC_VPU_IF_H_
+#define _VDEC_VPU_IF_H_
+
+#include "mtk_vpu.h"
+
+/**
+ * struct vdec_vpu_inst - VPU instance for video codec
+ * @ipi_id      : ipi id for each decoder
+ * @vsi         : driver structure allocated by VPU side and shared to AP side
+ *                for control and info share
+ * @failure     : VPU execution result status, 0: success, others: fail
+ * @inst_addr	: VPU decoder instance address
+ * @signaled    : 1 - Host has received ack message from VPU, 0 - not received
+ * @ctx         : context for v4l2 layer integration
+ * @dev	        : platform device of VPU
+ * @wq          : wait queue to wait VPU message ack
+ * @handler     : ipi handler for each decoder
+ */
+struct vdec_vpu_inst {
+	enum ipi_id id;
+	void *vsi;
+	int32_t failure;
+	uint32_t inst_addr;
+	unsigned int signaled;
+	struct mtk_vcodec_ctx *ctx;
+	struct platform_device *dev;
+	wait_queue_head_t wq;
+	ipi_handler_t handler;
+};
+
+/**
+ * vpu_dec_init - init decoder instance and allocate required resource in VPU.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_init(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_start - start decoding, basically the function will be invoked once
+ *                 every frame.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ * @data: meta data to pass bitstream info to VPU decoder
+ * @len : meta data length
+ */
+int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len);
+
+/**
+ * vpu_dec_end - end decoding, basically the function will be invoked once
+ *               when HW decoding done interrupt received successfully. The
+ *               decoder in VPU will continute to do referene frame management
+ *               and check if there is a new decoded frame available to display.
+ *
+ * @vpu : instance for vdec_vpu_inst
+ */
+int vpu_dec_end(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_deinit - deinit decoder instance and resource freed in VPU.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_deinit(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_reset - reset decoder, use for flush decoder when end of stream or
+ *                 seek. Remainig non displayed frame will be pushed to display.
+ *
+ * @vpu: instance for vdec_vpu_inst
+ */
+int vpu_dec_reset(struct vdec_vpu_inst *vpu);
+
+/**
+ * vpu_dec_ipi_handler - Handler for VPU ipi message.
+ *
+ * @data: ipi message
+ * @len : length of ipi message
+ * @priv: callback private data which is passed by decoder when register.
+ */
+void vpu_dec_ipi_handler(void *data, unsigned int len, void *priv);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.c
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.c	2016-12-11 17:47:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.c	2017-02-12 17:35:17.000000000 -0500
@@ -134,6 +134,8 @@ struct vpu_wdt {
  *
  * @signaled:		the signal of vpu initialization completed
  * @fw_ver:		VPU firmware version
+ * @dec_capability:	decoder capability which is not used for now and
+ *			the value is reserved for future use
  * @enc_capability:	encoder capability which is not used for now and
  *			the value is reserved for future use
  * @wq:			wait queue for VPU initialization status
@@ -141,6 +143,7 @@ struct vpu_wdt {
 struct vpu_run {
 	u32 signaled;
 	char fw_ver[VPU_FW_VER_LEN];
+	unsigned int	dec_capability;
 	unsigned int	enc_capability;
 	wait_queue_head_t wq;
 };
@@ -415,6 +418,14 @@ int vpu_wdt_reg_handler(struct platform_
 }
 EXPORT_SYMBOL_GPL(vpu_wdt_reg_handler);
 
+unsigned int vpu_get_vdec_hw_capa(struct platform_device *pdev)
+{
+	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+
+	return vpu->run.dec_capability;
+}
+EXPORT_SYMBOL_GPL(vpu_get_vdec_hw_capa);
+
 unsigned int vpu_get_venc_hw_capa(struct platform_device *pdev)
 {
 	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
@@ -523,9 +534,9 @@ static int load_requested_vpu(struct mtk
 
 int vpu_load_firmware(struct platform_device *pdev)
 {
-	struct mtk_vpu *vpu = platform_get_drvdata(pdev);
+	struct mtk_vpu *vpu;
 	struct device *dev = &pdev->dev;
-	struct vpu_run *run = &vpu->run;
+	struct vpu_run *run;
 	const struct firmware *vpu_fw = NULL;
 	int ret;
 
@@ -534,6 +545,9 @@ int vpu_load_firmware(struct platform_de
 		return -EINVAL;
 	}
 
+	vpu = platform_get_drvdata(pdev);
+	run = &vpu->run;
+
 	mutex_lock(&vpu->vpu_mutex);
 	if (vpu->fw_loaded) {
 		mutex_unlock(&vpu->vpu_mutex);
@@ -600,6 +614,7 @@ static void vpu_init_ipi_handler(void *d
 
 	vpu->run.signaled = run->signaled;
 	strncpy(vpu->run.fw_ver, run->fw_ver, VPU_FW_VER_LEN);
+	vpu->run.dec_capability = run->dec_capability;
 	vpu->run.enc_capability = run->enc_capability;
 	wake_up_interruptible(&vpu->run.wq);
 }
@@ -674,7 +689,7 @@ static int vpu_alloc_ext_mem(struct mtk_
 					       GFP_KERNEL);
 	if (!vpu->extmem[fw_type].va) {
 		dev_err(dev, "Failed to allocate the extended program memory\n");
-		return PTR_ERR(vpu->extmem[fw_type].va);
+		return -ENOMEM;
 	}
 
 	/* Disable extend0. Enable extend1 */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.h linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.h
--- linux-libre-4.9-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mtk-vpu/mtk_vpu.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,23 +31,41 @@ typedef void (*ipi_handler_t) (void *dat
  * enum ipi_id - the id of inter-processor interrupt
  *
  * @IPI_VPU_INIT:	 The interrupt from vpu is to notfiy kernel
-			 VPU initialization completed.
-			 IPI_VPU_INIT is sent from VPU when firmware is
-			 loaded. AP doesn't need to send IPI_VPU_INIT
-			 command to VPU.
-			 For other IPI below, AP should send the request
-			 to VPU to trigger the interrupt.
+ *			 VPU initialization completed.
+ *			 IPI_VPU_INIT is sent from VPU when firmware is
+ *			 loaded. AP doesn't need to send IPI_VPU_INIT
+ *			 command to VPU.
+ *			 For other IPI below, AP should send the request
+ *			 to VPU to trigger the interrupt.
+ * @IPI_VDEC_H264:	 The interrupt from vpu is to notify kernel to
+ *			 handle H264 vidoe decoder job, and vice versa.
+ *			 Decode output format is always MT21 no matter what
+ *			 the input format is.
+ * @IPI_VDEC_VP8:	 The interrupt from is to notify kernel to
+ *			 handle VP8 video decoder job, and vice versa.
+ *			 Decode output format is always MT21 no matter what
+ *			 the input format is.
+ * @IPI_VDEC_VP9:	 The interrupt from vpu is to notify kernel to
+ *			 handle VP9 video decoder job, and vice versa.
+ *			 Decode output format is always MT21 no matter what
+ *			 the input format is.
  * @IPI_VENC_H264:	 The interrupt from vpu is to notify kernel to
-			 handle H264 video encoder job, and vice versa.
+ *			 handle H264 video encoder job, and vice versa.
  * @IPI_VENC_VP8:	 The interrupt fro vpu is to notify kernel to
-			 handle VP8 video encoder job,, and vice versa.
+ *			 handle VP8 video encoder job,, and vice versa.
+ * @IPI_MDP:		 The interrupt from vpu is to notify kernel to
+ *			 handle MDP (Media Data Path) job, and vice versa.
  * @IPI_MAX:		 The maximum IPI number
  */
 
 enum ipi_id {
 	IPI_VPU_INIT = 0,
+	IPI_VDEC_H264,
+	IPI_VDEC_VP8,
+	IPI_VDEC_VP9,
 	IPI_VENC_H264,
 	IPI_VENC_VP8,
+	IPI_MDP,
 	IPI_MAX,
 };
 
@@ -55,10 +73,14 @@ enum ipi_id {
  * enum rst_id - reset id to register reset function for VPU watchdog timeout
  *
  * @VPU_RST_ENC: encoder reset id
+ * @VPU_RST_DEC: decoder reset id
+ * @VPU_RST_MDP: MDP (Media Data Path) reset id
  * @VPU_RST_MAX: maximum reset id
  */
 enum rst_id {
 	VPU_RST_ENC,
+	VPU_RST_DEC,
+	VPU_RST_MDP,
 	VPU_RST_MAX,
 };
 
@@ -125,6 +147,16 @@ struct platform_device *vpu_get_plat_dev
 int vpu_wdt_reg_handler(struct platform_device *pdev,
 			void vpu_wdt_reset_func(void *),
 			void *priv, enum rst_id id);
+
+/**
+ * vpu_get_vdec_hw_capa - get video decoder hardware capability
+ *
+ * @pdev:	VPU platform device
+ *
+ * Return: video decoder hardware capability
+ **/
+unsigned int vpu_get_vdec_hw_capa(struct platform_device *pdev);
+
 /**
  * vpu_get_venc_hw_capa - get video encoder hardware capability
  *
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/mx2_emmaprp.c linux-libre-4.10-rc8-gnu/drivers/media/platform/mx2_emmaprp.c
--- linux-libre-4.9-gnu/drivers/media/platform/mx2_emmaprp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/mx2_emmaprp.c	2017-02-12 16:03:20.000000000 -0500
@@ -724,10 +724,10 @@ static int emmaprp_buf_prepare(struct vb
 	q_data = get_q_data(ctx, vb->vb2_queue->type);
 
 	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
-		dprintk(ctx->dev, "%s data will not fit into plane"
-				  "(%lu < %lu)\n", __func__,
-				  vb2_plane_size(vb, 0),
-				  (long)q_data->sizeimage);
+		dprintk(ctx->dev,
+			"%s data will not fit into plane(%lu < %lu)\n",
+			__func__, vb2_plane_size(vb, 0),
+			(long)q_data->sizeimage);
 		return -EINVAL;
 	}
 
@@ -937,7 +937,7 @@ static int emmaprp_probe(struct platform
 	snprintf(vfd->name, sizeof(vfd->name), "%s", emmaprp_videodev.name);
 	pcdev->vfd = vfd;
 	v4l2_info(&pcdev->v4l2_dev, EMMAPRP_MODULE_NAME
-			" Device registered as /dev/video%d\n", vfd->num);
+		  " Device registered as /dev/video%d\n", vfd->num);
 
 	platform_set_drvdata(pdev, pcdev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap/omap_vout.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap/omap_vout.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap/omap_vout.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap/omap_vout.c	2017-02-12 16:03:20.000000000 -0500
@@ -408,8 +408,8 @@ static int omapvid_setup_overlay(struct
 	v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
 		"%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
 		"rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
-		"out_height=%d rotation_type=%d screen_width=%d\n",
-		__func__, ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
+		"out_height=%d rotation_type=%d screen_width=%d\n", __func__,
+		ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
 		info.color_mode, info.rotation, info.mirror, info.pos_x,
 		info.pos_y, info.out_width, info.out_height, info.rotation_type,
 		info.screen_width);
@@ -791,7 +791,8 @@ static int omap_vout_buffer_prepare(stru
 		dma_addr = dma_map_single(vout->vid_dev->v4l2_dev.dev, (void *) addr,
 				size, DMA_TO_DEVICE);
 		if (dma_mapping_error(vout->vid_dev->v4l2_dev.dev, dma_addr))
-			v4l2_err(&vout->vid_dev->v4l2_dev, "dma_map_single failed\n");
+			v4l2_err(&vout->vid_dev->v4l2_dev,
+				 "dma_map_single failed\n");
 
 		vout->queued_buf_addr[vb->i] = (u8 *)vout->buf_phy_addr[vb->i];
 	}
@@ -1657,8 +1658,8 @@ static int vidioc_streamoff(struct file
 	/* Turn of the pipeline */
 	ret = omapvid_apply_changes(vout);
 	if (ret)
-		v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode in"
-				" streamoff\n");
+		v4l2_err(&vout->vid_dev->v4l2_dev,
+			 "failed to change mode in streamoff\n");
 
 	INIT_LIST_HEAD(&vout->dma_queue);
 	ret = videobuf_streamoff(&vout->vbq);
@@ -1858,8 +1859,8 @@ static int __init omap_vout_setup_video_
 	vfd = vout->vfd = video_device_alloc();
 
 	if (!vfd) {
-		printk(KERN_ERR VOUT_NAME ": could not allocate"
-				" video device struct\n");
+		printk(KERN_ERR VOUT_NAME
+		       ": could not allocate video device struct\n");
 		v4l2_ctrl_handler_free(hdl);
 		return -ENOMEM;
 	}
@@ -1984,16 +1985,17 @@ static int __init omap_vout_create_video
 		 */
 		vfd = vout->vfd;
 		if (video_register_device(vfd, VFL_TYPE_GRABBER, -1) < 0) {
-			dev_err(&pdev->dev, ": Could not register "
-					"Video for Linux device\n");
+			dev_err(&pdev->dev,
+				": Could not register Video for Linux device\n");
 			vfd->minor = -1;
 			ret = -ENODEV;
 			goto error2;
 		}
 		video_set_drvdata(vfd, vout);
 
-		dev_info(&pdev->dev, ": registered and initialized"
-				" video device %d\n", vfd->minor);
+		dev_info(&pdev->dev,
+			 ": registered and initialized video device %d\n",
+			 vfd->minor);
 		if (k == (pdev->num_resources - 1))
 			return 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap/omap_vout_vrfb.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap/omap_vout_vrfb.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap/omap_vout_vrfb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap/omap_vout_vrfb.c	2017-02-12 16:03:20.000000000 -0500
@@ -139,8 +139,9 @@ int omap_vout_setup_vrfb_bufs(struct pla
 			(void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch);
 	if (ret < 0) {
 		vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED;
-		dev_info(&pdev->dev, ": failed to allocate DMA Channel for"
-				" video%d\n", vfd->minor);
+		dev_info(&pdev->dev,
+			 ": failed to allocate DMA Channel for video%d\n",
+			 vfd->minor);
 	}
 	init_waitqueue_head(&vout->vrfb_dma_tx.wait);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isp.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isp.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isp.c	2017-02-12 16:03:20.000000000 -0500
@@ -480,8 +480,8 @@ void omap3isp_hist_dma_done(struct isp_d
 	    omap3isp_stat_pcr_busy(&isp->isp_hist)) {
 		/* Histogram cannot be enabled in this frame anymore */
 		atomic_set(&isp->isp_hist.buf_err, 1);
-		dev_dbg(isp->dev, "hist: Out of synchronization with "
-				  "CCDC. Ignoring next buffer.\n");
+		dev_dbg(isp->dev,
+			"hist: Out of synchronization with CCDC. Ignoring next buffer.\n");
 	}
 }
 
@@ -2117,23 +2117,18 @@ static int isp_of_parse_nodes(struct dev
 		struct isp_async_subdev *isd;
 
 		isd = devm_kzalloc(dev, sizeof(*isd), GFP_KERNEL);
-		if (!isd) {
-			of_node_put(node);
-			return -ENOMEM;
-		}
+		if (!isd)
+			goto error;
 
 		notifier->subdevs[notifier->num_subdevs] = &isd->asd;
 
-		if (isp_of_parse_node(dev, node, isd)) {
-			of_node_put(node);
-			return -EINVAL;
-		}
+		if (isp_of_parse_node(dev, node, isd))
+			goto error;
 
 		isd->asd.match.of.node = of_graph_get_remote_port_parent(node);
-		of_node_put(node);
 		if (!isd->asd.match.of.node) {
 			dev_warn(dev, "bad remote port parent\n");
-			return -EINVAL;
+			goto error;
 		}
 
 		isd->asd.match_type = V4L2_ASYNC_MATCH_OF;
@@ -2141,6 +2136,10 @@ static int isp_of_parse_nodes(struct dev
 	}
 
 	return notifier->num_subdevs;
+
+error:
+	of_node_put(node);
+	return -EINVAL;
 }
 
 static int isp_subdev_notifier_bound(struct v4l2_async_notifier *async,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispccdc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispccdc.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispccdc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispccdc.c	2017-02-12 16:03:20.000000000 -0500
@@ -151,8 +151,8 @@ static int ccdc_lsc_validate_config(stru
 	}
 
 	if (lsc_cfg->offset & 3) {
-		dev_dbg(isp->dev, "CCDC: LSC: Offset must be a multiple of "
-			"4\n");
+		dev_dbg(isp->dev,
+			"CCDC: LSC: Offset must be a multiple of 4\n");
 		return -EINVAL;
 	}
 
@@ -416,8 +416,9 @@ static int ccdc_lsc_config(struct isp_cc
 		return 0;
 
 	if (update != (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC)) {
-		dev_dbg(to_device(ccdc), "%s: Both LSC configuration and table "
-			"need to be supplied\n", __func__);
+		dev_dbg(to_device(ccdc),
+			"%s: Both LSC configuration and table need to be supplied\n",
+			__func__);
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispcsi2.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispcsi2.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispcsi2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispcsi2.c	2017-02-12 16:03:20.000000000 -0500
@@ -753,8 +753,8 @@ void omap3isp_csi2_isr(struct isp_csi2_d
 						 ISPCSI2_PHY_IRQSTATUS);
 		isp_reg_writel(isp, cpxio1_irqstatus,
 			       csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
-		dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
-			"%x\n", cpxio1_irqstatus);
+		dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ %x\n",
+			cpxio1_irqstatus);
 		pipe->error = true;
 	}
 
@@ -763,13 +763,8 @@ void omap3isp_csi2_isr(struct isp_csi2_d
 			      ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
 			      ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
 			      ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)) {
-		dev_dbg(isp->dev, "CSI2 Err:"
-			" OCP:%d,"
-			" Short_pack:%d,"
-			" ECC:%d,"
-			" CPXIO2:%d,"
-			" FIFO_OVF:%d,"
-			"\n",
+		dev_dbg(isp->dev,
+			"CSI2 Err: OCP:%d, Short_pack:%d, ECC:%d, CPXIO2:%d, FIFO_OVF:%d,\n",
 			(csi2_irqstatus &
 			 ISPCSI2_IRQSTATUS_OCP_ERR_IRQ) ? 1 : 0,
 			(csi2_irqstatus &
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispcsiphy.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispcsiphy.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispcsiphy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispcsiphy.c	2017-02-12 16:03:20.000000000 -0500
@@ -267,8 +267,8 @@ int omap3isp_csiphy_acquire(struct isp_c
 	int rval;
 
 	if (phy->vdd == NULL) {
-		dev_err(phy->isp->dev, "Power regulator for CSI PHY not "
-			"available\n");
+		dev_err(phy->isp->dev,
+			"Power regulator for CSI PHY not available\n");
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isph3a_aewb.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isph3a_aewb.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isph3a_aewb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isph3a_aewb.c	2017-02-12 16:03:20.000000000 -0500
@@ -304,8 +304,8 @@ int omap3isp_h3a_aewb_init(struct isp_de
 	aewb_recover_cfg = devm_kzalloc(isp->dev, sizeof(*aewb_recover_cfg),
 					GFP_KERNEL);
 	if (!aewb_recover_cfg) {
-		dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for "
-					"recover configuration.\n");
+		dev_err(aewb->isp->dev,
+			"AEWB: cannot allocate memory for recover configuration.\n");
 		return -ENOMEM;
 	}
 
@@ -321,8 +321,8 @@ int omap3isp_h3a_aewb_init(struct isp_de
 	aewb_recover_cfg->subsample_hor_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
 
 	if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
-		dev_err(aewb->isp->dev, "AEWB: recover configuration is "
-					"invalid.\n");
+		dev_err(aewb->isp->dev,
+			"AEWB: recover configuration is invalid.\n");
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isph3a_af.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isph3a_af.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isph3a_af.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isph3a_af.c	2017-02-12 16:03:20.000000000 -0500
@@ -367,8 +367,8 @@ int omap3isp_h3a_af_init(struct isp_devi
 	af_recover_cfg = devm_kzalloc(isp->dev, sizeof(*af_recover_cfg),
 				      GFP_KERNEL);
 	if (!af_recover_cfg) {
-		dev_err(af->isp->dev, "AF: cannot allocate memory for recover "
-				      "configuration.\n");
+		dev_err(af->isp->dev,
+			"AF: cannot allocate memory for recover configuration.\n");
 		return -ENOMEM;
 	}
 
@@ -379,8 +379,8 @@ int omap3isp_h3a_af_init(struct isp_devi
 	af_recover_cfg->paxel.v_cnt = OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN;
 	af_recover_cfg->paxel.line_inc = OMAP3ISP_AF_PAXEL_INCREMENT_MIN;
 	if (h3a_af_validate_params(af, af_recover_cfg)) {
-		dev_err(af->isp->dev, "AF: recover configuration is "
-				      "invalid.\n");
+		dev_err(af->isp->dev,
+			"AF: recover configuration is invalid.\n");
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isphist.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isphist.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/isphist.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/isphist.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,6 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dmaengine.h>
-#include <linux/omap-dmaengine.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
@@ -486,27 +485,30 @@ int omap3isp_hist_init(struct isp_device
 	hist->isp = isp;
 
 	if (HIST_CONFIG_DMA) {
-		struct platform_device *pdev = to_platform_device(isp->dev);
-		struct resource *res;
-		unsigned int sig = 0;
 		dma_cap_mask_t mask;
 
+		/*
+		 * We need slave capable channel without DMA request line for
+		 * reading out the data.
+		 * For this we can use dma_request_chan_by_mask() as we are
+		 * happy with any channel as long as it is capable of slave
+		 * configuration.
+		 */
 		dma_cap_zero(mask);
 		dma_cap_set(DMA_SLAVE, mask);
+		hist->dma_ch = dma_request_chan_by_mask(&mask);
+		if (IS_ERR(hist->dma_ch)) {
+			ret = PTR_ERR(hist->dma_ch);
+			if (ret == -EPROBE_DEFER)
+				return ret;
 
-		res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
-						   "hist");
-		if (res)
-			sig = res->start;
-
-		hist->dma_ch = dma_request_slave_channel_compat(mask,
-				omap_dma_filter_fn, &sig, isp->dev, "hist");
-		if (!hist->dma_ch)
+			hist->dma_ch = NULL;
 			dev_warn(isp->dev,
 				 "hist: DMA channel request failed, using PIO\n");
-		else
+		} else {
 			dev_dbg(isp->dev, "hist: using DMA channel %s\n",
 				dma_chan_name(hist->dma_ch));
+		}
 	}
 
 	hist->ops = &hist_ops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispstat.c linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispstat.c
--- linux-libre-4.9-gnu/drivers/media/platform/omap3isp/ispstat.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/omap3isp/ispstat.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,8 +113,9 @@ static int isp_stat_buf_check_magic(stru
 			ret = 0;
 
 	if (ret) {
-		dev_dbg(stat->isp->dev, "%s: beginning magic check does not "
-					"match.\n", stat->subdev.name);
+		dev_dbg(stat->isp->dev,
+			"%s: beginning magic check does not match.\n",
+			stat->subdev.name);
 		return ret;
 	}
 
@@ -122,8 +123,9 @@ static int isp_stat_buf_check_magic(stru
 	for (w = buf->virt_addr + buf_size, end = w + MAGIC_SIZE;
 	     w < end; w++) {
 		if (unlikely(*w != MAGIC_NUM)) {
-			dev_dbg(stat->isp->dev, "%s: ending magic check does "
-				"not match.\n", stat->subdev.name);
+			dev_dbg(stat->isp->dev,
+				"%s: ending magic check does not match.\n",
+				stat->subdev.name);
 			return -EINVAL;
 		}
 	}
@@ -256,9 +258,9 @@ static void isp_stat_buf_next(struct isp
 {
 	if (unlikely(stat->active_buf))
 		/* Overwriting unused active buffer */
-		dev_dbg(stat->isp->dev, "%s: new buffer requested without "
-					"queuing active one.\n",
-					stat->subdev.name);
+		dev_dbg(stat->isp->dev,
+			"%s: new buffer requested without queuing active one.\n",
+			stat->subdev.name);
 	else
 		stat->active_buf = isp_stat_buf_find_oldest_or_empty(stat);
 }
@@ -292,8 +294,9 @@ static struct ispstat_buffer *isp_stat_b
 			return ERR_PTR(-EBUSY);
 		}
 		if (isp_stat_buf_check_magic(stat, buf)) {
-			dev_dbg(stat->isp->dev, "%s: current buffer has "
-				"corrupted data\n.", stat->subdev.name);
+			dev_dbg(stat->isp->dev,
+				"%s: current buffer has corrupted data\n.",
+				stat->subdev.name);
 			/* Mark empty because it doesn't have valid data. */
 			buf->empty = 1;
 		} else {
@@ -307,8 +310,9 @@ static struct ispstat_buffer *isp_stat_b
 	spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
 
 	if (buf->buf_size > data->buf_size) {
-		dev_warn(stat->isp->dev, "%s: userspace's buffer size is "
-					 "not enough.\n", stat->subdev.name);
+		dev_warn(stat->isp->dev,
+			 "%s: userspace's buffer size is not enough.\n",
+			 stat->subdev.name);
 		isp_stat_buf_release(stat);
 		return ERR_PTR(-EINVAL);
 	}
@@ -531,20 +535,22 @@ int omap3isp_stat_config(struct ispstat
 
 	mutex_lock(&stat->ioctl_lock);
 
-	dev_dbg(stat->isp->dev, "%s: configuring module with buffer "
-		"size=0x%08lx\n", stat->subdev.name, (unsigned long)buf_size);
+	dev_dbg(stat->isp->dev,
+		"%s: configuring module with buffer size=0x%08lx\n",
+		stat->subdev.name, (unsigned long)buf_size);
 
 	ret = stat->ops->validate_params(stat, new_conf);
 	if (ret) {
 		mutex_unlock(&stat->ioctl_lock);
-		dev_dbg(stat->isp->dev, "%s: configuration values are "
-					"invalid.\n", stat->subdev.name);
+		dev_dbg(stat->isp->dev, "%s: configuration values are invalid.\n",
+			stat->subdev.name);
 		return ret;
 	}
 
 	if (buf_size != user_cfg->buf_size)
-		dev_dbg(stat->isp->dev, "%s: driver has corrected buffer size "
-			"request to 0x%08lx\n", stat->subdev.name,
+		dev_dbg(stat->isp->dev,
+			"%s: driver has corrected buffer size request to 0x%08lx\n",
+			stat->subdev.name,
 			(unsigned long)user_cfg->buf_size);
 
 	/*
@@ -595,8 +601,9 @@ int omap3isp_stat_config(struct ispstat
 
 	/* Module has a valid configuration. */
 	stat->configured = 1;
-	dev_dbg(stat->isp->dev, "%s: module has been successfully "
-		"configured.\n", stat->subdev.name);
+	dev_dbg(stat->isp->dev,
+		"%s: module has been successfully configured.\n",
+		stat->subdev.name);
 
 	mutex_unlock(&stat->ioctl_lock);
 
@@ -762,8 +769,8 @@ int omap3isp_stat_enable(struct ispstat
 	if (!stat->configured && enable) {
 		spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
 		mutex_unlock(&stat->ioctl_lock);
-		dev_dbg(stat->isp->dev, "%s: cannot enable module as it's "
-			"never been successfully configured so far.\n",
+		dev_dbg(stat->isp->dev,
+			"%s: cannot enable module as it's never been successfully configured so far.\n",
 			stat->subdev.name);
 		return -EINVAL;
 	}
@@ -859,8 +866,8 @@ static void __stat_isr(struct ispstat *s
 		if (stat->state == ISPSTAT_ENABLED) {
 			spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
 			dev_err(stat->isp->dev,
-				"%s: interrupt occurred when module was still "
-				"processing a buffer.\n", stat->subdev.name);
+				"%s: interrupt occurred when module was still processing a buffer.\n",
+				stat->subdev.name);
 			ret = STAT_NO_BUF;
 			goto out;
 		} else {
@@ -964,8 +971,9 @@ static void __stat_isr(struct ispstat *s
 			atomic_set(&stat->buf_err, 1);
 
 		ret = STAT_NO_BUF;
-		dev_dbg(stat->isp->dev, "%s: cannot process buffer, "
-					"device is busy.\n", stat->subdev.name);
+		dev_dbg(stat->isp->dev,
+			"%s: cannot process buffer, device is busy.\n",
+			stat->subdev.name);
 	}
 
 out:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/pxa_camera.c linux-libre-4.10-rc8-gnu/drivers/media/platform/pxa_camera.c
--- linux-libre-4.9-gnu/drivers/media/platform/pxa_camera.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/pxa_camera.c	2017-02-12 16:03:20.000000000 -0500
@@ -2125,17 +2125,22 @@ static int pxa_camera_sensor_bound(struc
 				    pix->bytesperline, pix->height);
 	pix->pixelformat = pcdev->current_fmt->host_fmt->fourcc;
 	v4l2_fill_mbus_format(mf, pix, pcdev->current_fmt->code);
-	err = sensor_call(pcdev, pad, set_fmt, NULL, &format);
+
+	err = sensor_call(pcdev, core, s_power, 1);
 	if (err)
 		goto out;
 
+	err = sensor_call(pcdev, pad, set_fmt, NULL, &format);
+	if (err)
+		goto out_sensor_poweroff;
+
 	v4l2_fill_pix_format(pix, mf);
 	pr_info("%s(): colorspace=0x%x pixfmt=0x%x\n",
 		__func__, pix->colorspace, pix->pixelformat);
 
 	err = pxa_camera_init_videobuf2(pcdev);
 	if (err)
-		goto out;
+		goto out_sensor_poweroff;
 
 	err = video_register_device(&pcdev->vdev, VFL_TYPE_GRABBER, -1);
 	if (err) {
@@ -2146,6 +2151,9 @@ static int pxa_camera_sensor_bound(struc
 			 "PXA Camera driver attached to camera %s\n",
 			 subdev->name);
 	}
+
+out_sensor_poweroff:
+	err = sensor_call(pcdev, core, s_power, 0);
 out:
 	mutex_unlock(&pcdev->mlock);
 	return err;
@@ -2347,8 +2355,7 @@ static int pxa_camera_probe(struct platf
 		 * Platform hasn't set available data widths. This is bad.
 		 * Warn and use a default.
 		 */
-		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available "
-			 "data widths, using default 10 bit\n");
+		dev_warn(&pdev->dev, "WARNING! Platform hasn't set available data widths, using default 10 bit\n");
 		pcdev->platform_flags |= PXA_CAMERA_DATAWIDTH_10;
 	}
 	if (pcdev->platform_flags & PXA_CAMERA_DATAWIDTH_8)
@@ -2359,8 +2366,7 @@ static int pxa_camera_probe(struct platf
 		pcdev->width_flags |= 1 << 9;
 	if (!pcdev->mclk) {
 		dev_warn(&pdev->dev,
-			 "mclk == 0! Please, fix your platform data. "
-			 "Using default 20MHz\n");
+			 "mclk == 0! Please, fix your platform data. Using default 20MHz\n");
 		pcdev->mclk = 20000000;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/rcar-fcp.c linux-libre-4.10-rc8-gnu/drivers/media/platform/rcar-fcp.c
--- linux-libre-4.9-gnu/drivers/media/platform/rcar-fcp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/rcar-fcp.c	2017-02-12 16:03:20.000000000 -0500
@@ -169,6 +169,7 @@ static const struct of_device_id rcar_fc
 	{ .compatible = "renesas,fcpv" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, rcar_fcp_of_match);
 
 static struct platform_driver rcar_fcp_platform_driver = {
 	.probe		= rcar_fcp_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/rcar_fdp1.c linux-libre-4.10-rc8-gnu/drivers/media/platform/rcar_fdp1.c
--- linux-libre-4.9-gnu/drivers/media/platform/rcar_fdp1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/rcar_fdp1.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2445 @@
+/*
+ * Renesas RCar Fine Display Processor
+ *
+ * Video format converter and frame deinterlacer device.
+ *
+ * Author: Kieran Bingham, <kieran@bingham.xyz>
+ * Copyright (c) 2016 Renesas Electronics Corporation.
+ *
+ * This code is developed and inspired from the vim2m, rcar_jpu,
+ * m2m-deinterlace, and vsp1 drivers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <media/rcar-fcp.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activate debug info");
+
+/* Minimum and maximum frame width/height */
+#define FDP1_MIN_W		80U
+#define FDP1_MIN_H		80U
+
+#define FDP1_MAX_W		3840U
+#define FDP1_MAX_H		2160U
+
+#define FDP1_MAX_PLANES		3U
+#define FDP1_MAX_STRIDE		8190U
+
+/* Flags that indicate a format can be used for capture/output */
+#define FDP1_CAPTURE		BIT(0)
+#define FDP1_OUTPUT		BIT(1)
+
+#define DRIVER_NAME		"rcar_fdp1"
+
+/* Number of Job's to have available on the processing queue */
+#define FDP1_NUMBER_JOBS 8
+
+#define dprintk(fdp1, fmt, arg...) \
+	v4l2_dbg(1, debug, &fdp1->v4l2_dev, "%s: " fmt, __func__, ## arg)
+
+/*
+ * FDP1 registers and bits
+ */
+
+/* FDP1 start register - Imm */
+#define FD1_CTL_CMD			0x0000
+#define FD1_CTL_CMD_STRCMD		BIT(0)
+
+/* Sync generator register - Imm */
+#define FD1_CTL_SGCMD			0x0004
+#define FD1_CTL_SGCMD_SGEN		BIT(0)
+
+/* Register set end register - Imm */
+#define FD1_CTL_REGEND			0x0008
+#define FD1_CTL_REGEND_REGEND		BIT(0)
+
+/* Channel activation register - Vupdt */
+#define FD1_CTL_CHACT			0x000c
+#define FD1_CTL_CHACT_SMW		BIT(9)
+#define FD1_CTL_CHACT_WR		BIT(8)
+#define FD1_CTL_CHACT_SMR		BIT(3)
+#define FD1_CTL_CHACT_RD2		BIT(2)
+#define FD1_CTL_CHACT_RD1		BIT(1)
+#define FD1_CTL_CHACT_RD0		BIT(0)
+
+/* Operation Mode Register - Vupdt */
+#define FD1_CTL_OPMODE			0x0010
+#define FD1_CTL_OPMODE_PRG		BIT(4)
+#define FD1_CTL_OPMODE_VIMD_INTERRUPT	(0 << 0)
+#define FD1_CTL_OPMODE_VIMD_BESTEFFORT	(1 << 0)
+#define FD1_CTL_OPMODE_VIMD_NOINTERRUPT	(2 << 0)
+
+#define FD1_CTL_VPERIOD			0x0014
+#define FD1_CTL_CLKCTRL			0x0018
+#define FD1_CTL_CLKCTRL_CSTP_N		BIT(0)
+
+/* Software reset register */
+#define FD1_CTL_SRESET			0x001c
+#define FD1_CTL_SRESET_SRST		BIT(0)
+
+/* Control status register (V-update-status) */
+#define FD1_CTL_STATUS			0x0024
+#define FD1_CTL_STATUS_VINT_CNT_MASK	GENMASK(31, 16)
+#define FD1_CTL_STATUS_VINT_CNT_SHIFT	16
+#define FD1_CTL_STATUS_SGREGSET		BIT(10)
+#define FD1_CTL_STATUS_SGVERR		BIT(9)
+#define FD1_CTL_STATUS_SGFREND		BIT(8)
+#define FD1_CTL_STATUS_BSY		BIT(0)
+
+#define FD1_CTL_VCYCLE_STAT		0x0028
+
+/* Interrupt enable register */
+#define FD1_CTL_IRQENB			0x0038
+/* Interrupt status register */
+#define FD1_CTL_IRQSTA			0x003c
+/* Interrupt control register */
+#define FD1_CTL_IRQFSET			0x0040
+
+/* Common IRQ Bit settings */
+#define FD1_CTL_IRQ_VERE		BIT(16)
+#define FD1_CTL_IRQ_VINTE		BIT(4)
+#define FD1_CTL_IRQ_FREE		BIT(0)
+#define FD1_CTL_IRQ_MASK		(FD1_CTL_IRQ_VERE | \
+					 FD1_CTL_IRQ_VINTE | \
+					 FD1_CTL_IRQ_FREE)
+
+/* RPF */
+#define FD1_RPF_SIZE			0x0060
+#define FD1_RPF_SIZE_MASK		GENMASK(12, 0)
+#define FD1_RPF_SIZE_H_SHIFT		16
+#define FD1_RPF_SIZE_V_SHIFT		0
+
+#define FD1_RPF_FORMAT			0x0064
+#define FD1_RPF_FORMAT_CIPM		BIT(16)
+#define FD1_RPF_FORMAT_RSPYCS		BIT(13)
+#define FD1_RPF_FORMAT_RSPUVS		BIT(12)
+#define FD1_RPF_FORMAT_CF		BIT(8)
+
+#define FD1_RPF_PSTRIDE			0x0068
+#define FD1_RPF_PSTRIDE_Y_SHIFT		16
+#define FD1_RPF_PSTRIDE_C_SHIFT		0
+
+/* RPF0 Source Component Y Address register */
+#define FD1_RPF0_ADDR_Y			0x006c
+
+/* RPF1 Current Picture Registers */
+#define FD1_RPF1_ADDR_Y			0x0078
+#define FD1_RPF1_ADDR_C0		0x007c
+#define FD1_RPF1_ADDR_C1		0x0080
+
+/* RPF2 next picture register */
+#define FD1_RPF2_ADDR_Y			0x0084
+
+#define FD1_RPF_SMSK_ADDR		0x0090
+#define FD1_RPF_SWAP			0x0094
+
+/* WPF */
+#define FD1_WPF_FORMAT			0x00c0
+#define FD1_WPF_FORMAT_PDV_SHIFT	24
+#define FD1_WPF_FORMAT_FCNL		BIT(20)
+#define FD1_WPF_FORMAT_WSPYCS		BIT(15)
+#define FD1_WPF_FORMAT_WSPUVS		BIT(14)
+#define FD1_WPF_FORMAT_WRTM_601_16	(0 << 9)
+#define FD1_WPF_FORMAT_WRTM_601_0	(1 << 9)
+#define FD1_WPF_FORMAT_WRTM_709_16	(2 << 9)
+#define FD1_WPF_FORMAT_CSC		BIT(8)
+
+#define FD1_WPF_RNDCTL			0x00c4
+#define FD1_WPF_RNDCTL_CBRM		BIT(28)
+#define FD1_WPF_RNDCTL_CLMD_NOCLIP	(0 << 12)
+#define FD1_WPF_RNDCTL_CLMD_CLIP_16_235	(1 << 12)
+#define FD1_WPF_RNDCTL_CLMD_CLIP_1_254	(2 << 12)
+
+#define FD1_WPF_PSTRIDE			0x00c8
+#define FD1_WPF_PSTRIDE_Y_SHIFT		16
+#define FD1_WPF_PSTRIDE_C_SHIFT		0
+
+/* WPF Destination picture */
+#define FD1_WPF_ADDR_Y			0x00cc
+#define FD1_WPF_ADDR_C0			0x00d0
+#define FD1_WPF_ADDR_C1			0x00d4
+#define FD1_WPF_SWAP			0x00d8
+#define FD1_WPF_SWAP_OSWAP_SHIFT	0
+#define FD1_WPF_SWAP_SSWAP_SHIFT	4
+
+/* WPF/RPF Common */
+#define FD1_RWPF_SWAP_BYTE		BIT(0)
+#define FD1_RWPF_SWAP_WORD		BIT(1)
+#define FD1_RWPF_SWAP_LWRD		BIT(2)
+#define FD1_RWPF_SWAP_LLWD		BIT(3)
+
+/* IPC */
+#define FD1_IPC_MODE			0x0100
+#define FD1_IPC_MODE_DLI		BIT(8)
+#define FD1_IPC_MODE_DIM_ADAPT2D3D	(0 << 0)
+#define FD1_IPC_MODE_DIM_FIXED2D	(1 << 0)
+#define FD1_IPC_MODE_DIM_FIXED3D	(2 << 0)
+#define FD1_IPC_MODE_DIM_PREVFIELD	(3 << 0)
+#define FD1_IPC_MODE_DIM_NEXTFIELD	(4 << 0)
+
+#define FD1_IPC_SMSK_THRESH		0x0104
+#define FD1_IPC_SMSK_THRESH_CONST	0x00010002
+
+#define FD1_IPC_COMB_DET		0x0108
+#define FD1_IPC_COMB_DET_CONST		0x00200040
+
+#define FD1_IPC_MOTDEC			0x010c
+#define FD1_IPC_MOTDEC_CONST		0x00008020
+
+/* DLI registers */
+#define FD1_IPC_DLI_BLEND		0x0120
+#define FD1_IPC_DLI_BLEND_CONST		0x0080ff02
+
+#define FD1_IPC_DLI_HGAIN		0x0124
+#define FD1_IPC_DLI_HGAIN_CONST		0x001000ff
+
+#define FD1_IPC_DLI_SPRS		0x0128
+#define FD1_IPC_DLI_SPRS_CONST		0x009004ff
+
+#define FD1_IPC_DLI_ANGLE		0x012c
+#define FD1_IPC_DLI_ANGLE_CONST		0x0004080c
+
+#define FD1_IPC_DLI_ISOPIX0		0x0130
+#define FD1_IPC_DLI_ISOPIX0_CONST	0xff10ff10
+
+#define FD1_IPC_DLI_ISOPIX1		0x0134
+#define FD1_IPC_DLI_ISOPIX1_CONST	0x0000ff10
+
+/* Sensor registers */
+#define FD1_IPC_SENSOR_TH0		0x0140
+#define FD1_IPC_SENSOR_TH0_CONST	0x20208080
+
+#define FD1_IPC_SENSOR_TH1		0x0144
+#define FD1_IPC_SENSOR_TH1_CONST	0
+
+#define FD1_IPC_SENSOR_CTL0		0x0170
+#define FD1_IPC_SENSOR_CTL0_CONST	0x00002201
+
+#define FD1_IPC_SENSOR_CTL1		0x0174
+#define FD1_IPC_SENSOR_CTL1_CONST	0
+
+#define FD1_IPC_SENSOR_CTL2		0x0178
+#define FD1_IPC_SENSOR_CTL2_X_SHIFT	16
+#define FD1_IPC_SENSOR_CTL2_Y_SHIFT	0
+
+#define FD1_IPC_SENSOR_CTL3		0x017c
+#define FD1_IPC_SENSOR_CTL3_0_SHIFT	16
+#define FD1_IPC_SENSOR_CTL3_1_SHIFT	0
+
+/* Line memory pixel number register */
+#define FD1_IPC_LMEM			0x01e0
+#define FD1_IPC_LMEM_LINEAR		1024
+#define FD1_IPC_LMEM_TILE		960
+
+/* Internal Data (HW Version) */
+#define FD1_IP_INTDATA			0x0800
+#define FD1_IP_H3			0x02010101
+#define FD1_IP_M3W			0x02010202
+
+/* LUTs */
+#define FD1_LUT_DIF_ADJ			0x1000
+#define FD1_LUT_SAD_ADJ			0x1400
+#define FD1_LUT_BLD_GAIN		0x1800
+#define FD1_LUT_DIF_GAIN		0x1c00
+#define FD1_LUT_MDET			0x2000
+
+/**
+ * struct fdp1_fmt - The FDP1 internal format data
+ * @fourcc: the fourcc code, to match the V4L2 API
+ * @bpp: bits per pixel per plane
+ * @num_planes: number of planes
+ * @hsub: horizontal subsampling factor
+ * @vsub: vertical subsampling factor
+ * @fmt: 7-bit format code for the fdp1 hardware
+ * @swap_yc: the Y and C components are swapped (Y comes before C)
+ * @swap_uv: the U and V components are swapped (V comes before U)
+ * @swap: swap register control
+ * @types: types of queue this format is applicable to
+ */
+struct fdp1_fmt {
+	u32	fourcc;
+	u8	bpp[3];
+	u8	num_planes;
+	u8	hsub;
+	u8	vsub;
+	u8	fmt;
+	bool	swap_yc;
+	bool	swap_uv;
+	u8	swap;
+	u8	types;
+};
+
+static const struct fdp1_fmt fdp1_formats[] = {
+	/* RGB formats are only supported by the Write Pixel Formatter */
+
+	{ V4L2_PIX_FMT_RGB332, { 8, 0, 0 }, 1, 1, 1, 0x00, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_XRGB444, { 16, 0, 0 }, 1, 1, 1, 0x01, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_XRGB555, { 16, 0, 0 }, 1, 1, 1, 0x04, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_RGB565, { 16, 0, 0 }, 1, 1, 1, 0x06, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_ABGR32, { 32, 0, 0 }, 1, 1, 1, 0x13, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_XBGR32, { 32, 0, 0 }, 1, 1, 1, 0x13, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_ARGB32, { 32, 0, 0 }, 1, 1, 1, 0x13, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_XRGB32, { 32, 0, 0 }, 1, 1, 1, 0x13, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_RGB24, { 24, 0, 0 }, 1, 1, 1, 0x15, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_BGR24, { 24, 0, 0 }, 1, 1, 1, 0x18, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_ARGB444, { 16, 0, 0 }, 1, 1, 1, 0x19, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD,
+	  FDP1_CAPTURE },
+	{ V4L2_PIX_FMT_ARGB555, { 16, 0, 0 }, 1, 1, 1, 0x1b, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD,
+	  FDP1_CAPTURE },
+
+	/* YUV Formats are supported by Read and Write Pixel Formatters */
+
+	{ V4L2_PIX_FMT_NV16M, { 8, 16, 0 }, 2, 2, 1, 0x41, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_NV61M, { 8, 16, 0 }, 2, 2, 1, 0x41, false, true,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_NV12M, { 8, 16, 0 }, 2, 2, 2, 0x42, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_NV21M, { 8, 16, 0 }, 2, 2, 2, 0x42, false, true,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_UYVY, { 16, 0, 0 }, 1, 2, 1, 0x47, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_VYUY, { 16, 0, 0 }, 1, 2, 1, 0x47, false, true,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YUYV, { 16, 0, 0 }, 1, 2, 1, 0x47, true, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YVYU, { 16, 0, 0 }, 1, 2, 1, 0x47, true, true,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YUV444M, { 8, 8, 8 }, 3, 1, 1, 0x4a, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YVU444M, { 8, 8, 8 }, 3, 1, 1, 0x4a, false, true,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YUV422M, { 8, 8, 8 }, 3, 2, 1, 0x4b, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YVU422M, { 8, 8, 8 }, 3, 2, 1, 0x4b, false, true,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YUV420M, { 8, 8, 8 }, 3, 2, 2, 0x4c, false, false,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+	{ V4L2_PIX_FMT_YVU420M, { 8, 8, 8 }, 3, 2, 2, 0x4c, false, true,
+	  FD1_RWPF_SWAP_LLWD | FD1_RWPF_SWAP_LWRD |
+	  FD1_RWPF_SWAP_WORD | FD1_RWPF_SWAP_BYTE,
+	  FDP1_CAPTURE | FDP1_OUTPUT },
+};
+
+static int fdp1_fmt_is_rgb(const struct fdp1_fmt *fmt)
+{
+	return fmt->fmt <= 0x1b; /* Last RGB code */
+}
+
+/*
+ * FDP1 Lookup tables range from 0...255 only
+ *
+ * Each table must be less than 256 entries, and all tables
+ * are padded out to 256 entries by duplicating the last value.
+ */
+static const u8 fdp1_diff_adj[] = {
+	0x00, 0x24, 0x43, 0x5e, 0x76, 0x8c, 0x9e, 0xaf,
+	0xbd, 0xc9, 0xd4, 0xdd, 0xe4, 0xea, 0xef, 0xf3,
+	0xf6, 0xf9, 0xfb, 0xfc, 0xfd, 0xfe, 0xfe, 0xff,
+};
+
+static const u8 fdp1_sad_adj[] = {
+	0x00, 0x24, 0x43, 0x5e, 0x76, 0x8c, 0x9e, 0xaf,
+	0xbd, 0xc9, 0xd4, 0xdd, 0xe4, 0xea, 0xef, 0xf3,
+	0xf6, 0xf9, 0xfb, 0xfc, 0xfd, 0xfe, 0xfe, 0xff,
+};
+
+static const u8 fdp1_bld_gain[] = {
+	0x80,
+};
+
+static const u8 fdp1_dif_gain[] = {
+	0x80,
+};
+
+static const u8 fdp1_mdet[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2a, 0x2b, 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, 0x45, 0x46, 0x47,
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
+/* Per-queue, driver-specific private data */
+struct fdp1_q_data {
+	const struct fdp1_fmt		*fmt;
+	struct v4l2_pix_format_mplane	format;
+
+	unsigned int			vsize;
+	unsigned int			stride_y;
+	unsigned int			stride_c;
+};
+
+static const struct fdp1_fmt *fdp1_find_format(u32 pixelformat)
+{
+	const struct fdp1_fmt *fmt;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(fdp1_formats); i++) {
+		fmt = &fdp1_formats[i];
+		if (fmt->fourcc == pixelformat)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+enum fdp1_deint_mode {
+	FDP1_PROGRESSIVE = 0, /* Must be zero when !deinterlacing */
+	FDP1_ADAPT2D3D,
+	FDP1_FIXED2D,
+	FDP1_FIXED3D,
+	FDP1_PREVFIELD,
+	FDP1_NEXTFIELD,
+};
+
+#define FDP1_DEINT_MODE_USES_NEXT(mode) \
+	(mode == FDP1_ADAPT2D3D || \
+	 mode == FDP1_FIXED3D   || \
+	 mode == FDP1_NEXTFIELD)
+
+#define FDP1_DEINT_MODE_USES_PREV(mode) \
+	(mode == FDP1_ADAPT2D3D || \
+	 mode == FDP1_FIXED3D   || \
+	 mode == FDP1_PREVFIELD)
+
+/*
+ * FDP1 operates on potentially 3 fields, which are tracked
+ * from the VB buffers using this context structure.
+ * Will always be a field or a full frame, never two fields.
+ */
+struct fdp1_field_buffer {
+	struct vb2_v4l2_buffer		*vb;
+	dma_addr_t			addrs[3];
+
+	/* Should be NONE:TOP:BOTTOM only */
+	enum v4l2_field			field;
+
+	/* Flag to indicate this is the last field in the vb */
+	bool				last_field;
+
+	/* Buffer queue lists */
+	struct list_head		list;
+};
+
+struct fdp1_buffer {
+	struct v4l2_m2m_buffer		m2m_buf;
+	struct fdp1_field_buffer	fields[2];
+	unsigned int			num_fields;
+};
+
+static inline struct fdp1_buffer *to_fdp1_buffer(struct vb2_v4l2_buffer *vb)
+{
+	return container_of(vb, struct fdp1_buffer, m2m_buf.vb);
+}
+
+struct fdp1_job {
+	struct fdp1_field_buffer	*previous;
+	struct fdp1_field_buffer	*active;
+	struct fdp1_field_buffer	*next;
+	struct fdp1_field_buffer	*dst;
+
+	/* A job can only be on one list at a time */
+	struct list_head		list;
+};
+
+struct fdp1_dev {
+	struct v4l2_device		v4l2_dev;
+	struct video_device		vfd;
+
+	struct mutex			dev_mutex;
+	spinlock_t			irqlock;
+	spinlock_t			device_process_lock;
+
+	void __iomem			*regs;
+	unsigned int			irq;
+	struct device			*dev;
+
+	/* Job Queues */
+	struct fdp1_job			jobs[FDP1_NUMBER_JOBS];
+	struct list_head		free_job_list;
+	struct list_head		queued_job_list;
+	struct list_head		hw_job_list;
+
+	unsigned int			clk_rate;
+
+	struct rcar_fcp_device		*fcp;
+	struct v4l2_m2m_dev		*m2m_dev;
+};
+
+struct fdp1_ctx {
+	struct v4l2_fh			fh;
+	struct fdp1_dev			*fdp1;
+
+	struct v4l2_ctrl_handler	hdl;
+	unsigned int			sequence;
+
+	/* Processed buffers in this transaction */
+	u8				num_processed;
+
+	/* Transaction length (i.e. how many buffers per transaction) */
+	u32				translen;
+
+	/* Abort requested by m2m */
+	int				aborting;
+
+	/* Deinterlace processing mode */
+	enum fdp1_deint_mode		deint_mode;
+
+	/*
+	 * Adaptive 2D/3D mode uses a shared mask
+	 * This is allocated at streamon, if the ADAPT2D3D mode
+	 * is requested
+	 */
+	unsigned int			smsk_size;
+	dma_addr_t			smsk_addr[2];
+	void				*smsk_cpu;
+
+	/* Capture pipeline, can specify an alpha value
+	 * for supported formats. 0-255 only
+	 */
+	unsigned char			alpha;
+
+	/* Source and destination queue data */
+	struct fdp1_q_data		out_q; /* HW Source */
+	struct fdp1_q_data		cap_q; /* HW Destination */
+
+	/*
+	 * Field Queues
+	 * Interlaced fields are used on 3 occasions, and tracked in this list.
+	 *
+	 * V4L2 Buffers are tracked inside the fdp1_buffer
+	 * and released when the last 'field' completes
+	 */
+	struct list_head		fields_queue;
+	unsigned int			buffers_queued;
+
+	/*
+	 * For de-interlacing we need to track our previous buffer
+	 * while preparing our job lists.
+	 */
+	struct fdp1_field_buffer	*previous;
+};
+
+static inline struct fdp1_ctx *fh_to_ctx(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct fdp1_ctx, fh);
+}
+
+static struct fdp1_q_data *get_q_data(struct fdp1_ctx *ctx,
+					 enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->out_q;
+	else
+		return &ctx->cap_q;
+}
+
+/*
+ * list_remove_job: Take the first item off the specified job list
+ *
+ * Returns: pointer to a job, or NULL if the list is empty.
+ */
+static struct fdp1_job *list_remove_job(struct fdp1_dev *fdp1,
+					 struct list_head *list)
+{
+	struct fdp1_job *job;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fdp1->irqlock, flags);
+	job = list_first_entry_or_null(list, struct fdp1_job, list);
+	if (job)
+		list_del(&job->list);
+	spin_unlock_irqrestore(&fdp1->irqlock, flags);
+
+	return job;
+}
+
+/*
+ * list_add_job: Add a job to the specified job list
+ *
+ * Returns: void - always succeeds
+ */
+static void list_add_job(struct fdp1_dev *fdp1,
+			 struct list_head *list,
+			 struct fdp1_job *job)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&fdp1->irqlock, flags);
+	list_add_tail(&job->list, list);
+	spin_unlock_irqrestore(&fdp1->irqlock, flags);
+}
+
+static struct fdp1_job *fdp1_job_alloc(struct fdp1_dev *fdp1)
+{
+	return list_remove_job(fdp1, &fdp1->free_job_list);
+}
+
+static void fdp1_job_free(struct fdp1_dev *fdp1, struct fdp1_job *job)
+{
+	/* Ensure that all residue from previous jobs is gone */
+	memset(job, 0, sizeof(struct fdp1_job));
+
+	list_add_job(fdp1, &fdp1->free_job_list, job);
+}
+
+static void queue_job(struct fdp1_dev *fdp1, struct fdp1_job *job)
+{
+	list_add_job(fdp1, &fdp1->queued_job_list, job);
+}
+
+static struct fdp1_job *get_queued_job(struct fdp1_dev *fdp1)
+{
+	return list_remove_job(fdp1, &fdp1->queued_job_list);
+}
+
+static void queue_hw_job(struct fdp1_dev *fdp1, struct fdp1_job *job)
+{
+	list_add_job(fdp1, &fdp1->hw_job_list, job);
+}
+
+static struct fdp1_job *get_hw_queued_job(struct fdp1_dev *fdp1)
+{
+	return list_remove_job(fdp1, &fdp1->hw_job_list);
+}
+
+/*
+ * Buffer lists handling
+ */
+static void fdp1_field_complete(struct fdp1_ctx *ctx,
+				struct fdp1_field_buffer *fbuf)
+{
+	/* job->previous may be on the first field */
+	if (!fbuf)
+		return;
+
+	if (fbuf->last_field)
+		v4l2_m2m_buf_done(fbuf->vb, VB2_BUF_STATE_DONE);
+}
+
+static void fdp1_queue_field(struct fdp1_ctx *ctx,
+			     struct fdp1_field_buffer *fbuf)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->fdp1->irqlock, flags);
+	list_add_tail(&fbuf->list, &ctx->fields_queue);
+	spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags);
+
+	ctx->buffers_queued++;
+}
+
+static struct fdp1_field_buffer *fdp1_dequeue_field(struct fdp1_ctx *ctx)
+{
+	struct fdp1_field_buffer *fbuf;
+	unsigned long flags;
+
+	ctx->buffers_queued--;
+
+	spin_lock_irqsave(&ctx->fdp1->irqlock, flags);
+	fbuf = list_first_entry_or_null(&ctx->fields_queue,
+					struct fdp1_field_buffer, list);
+	if (fbuf)
+		list_del(&fbuf->list);
+	spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags);
+
+	return fbuf;
+}
+
+/*
+ * Return the next field in the queue - or NULL,
+ * without removing the item from the list
+ */
+static struct fdp1_field_buffer *fdp1_peek_queued_field(struct fdp1_ctx *ctx)
+{
+	struct fdp1_field_buffer *fbuf;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->fdp1->irqlock, flags);
+	fbuf = list_first_entry_or_null(&ctx->fields_queue,
+					struct fdp1_field_buffer, list);
+	spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags);
+
+	return fbuf;
+}
+
+static u32 fdp1_read(struct fdp1_dev *fdp1, unsigned int reg)
+{
+	u32 value = ioread32(fdp1->regs + reg);
+
+	if (debug >= 2)
+		dprintk(fdp1, "Read 0x%08x from 0x%04x\n", value, reg);
+
+	return value;
+}
+
+static void fdp1_write(struct fdp1_dev *fdp1, u32 val, unsigned int reg)
+{
+	if (debug >= 2)
+		dprintk(fdp1, "Write 0x%08x to 0x%04x\n", val, reg);
+
+	iowrite32(val, fdp1->regs + reg);
+}
+
+/* IPC registers are to be programmed with constant values */
+static void fdp1_set_ipc_dli(struct fdp1_ctx *ctx)
+{
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+
+	fdp1_write(fdp1, FD1_IPC_SMSK_THRESH_CONST,	FD1_IPC_SMSK_THRESH);
+	fdp1_write(fdp1, FD1_IPC_COMB_DET_CONST,	FD1_IPC_COMB_DET);
+	fdp1_write(fdp1, FD1_IPC_MOTDEC_CONST,	FD1_IPC_MOTDEC);
+
+	fdp1_write(fdp1, FD1_IPC_DLI_BLEND_CONST,	FD1_IPC_DLI_BLEND);
+	fdp1_write(fdp1, FD1_IPC_DLI_HGAIN_CONST,	FD1_IPC_DLI_HGAIN);
+	fdp1_write(fdp1, FD1_IPC_DLI_SPRS_CONST,	FD1_IPC_DLI_SPRS);
+	fdp1_write(fdp1, FD1_IPC_DLI_ANGLE_CONST,	FD1_IPC_DLI_ANGLE);
+	fdp1_write(fdp1, FD1_IPC_DLI_ISOPIX0_CONST,	FD1_IPC_DLI_ISOPIX0);
+	fdp1_write(fdp1, FD1_IPC_DLI_ISOPIX1_CONST,	FD1_IPC_DLI_ISOPIX1);
+}
+
+
+static void fdp1_set_ipc_sensor(struct fdp1_ctx *ctx)
+{
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+	struct fdp1_q_data *src_q_data = &ctx->out_q;
+	unsigned int x0, x1;
+	unsigned int hsize = src_q_data->format.width;
+	unsigned int vsize = src_q_data->format.height;
+
+	x0 = hsize / 3;
+	x1 = 2 * hsize / 3;
+
+	fdp1_write(fdp1, FD1_IPC_SENSOR_TH0_CONST, FD1_IPC_SENSOR_TH0);
+	fdp1_write(fdp1, FD1_IPC_SENSOR_TH1_CONST, FD1_IPC_SENSOR_TH1);
+	fdp1_write(fdp1, FD1_IPC_SENSOR_CTL0_CONST, FD1_IPC_SENSOR_CTL0);
+	fdp1_write(fdp1, FD1_IPC_SENSOR_CTL1_CONST, FD1_IPC_SENSOR_CTL1);
+
+	fdp1_write(fdp1, ((hsize - 1) << FD1_IPC_SENSOR_CTL2_X_SHIFT) |
+			 ((vsize - 1) << FD1_IPC_SENSOR_CTL2_Y_SHIFT),
+			 FD1_IPC_SENSOR_CTL2);
+
+	fdp1_write(fdp1, (x0 << FD1_IPC_SENSOR_CTL3_0_SHIFT) |
+			 (x1 << FD1_IPC_SENSOR_CTL3_1_SHIFT),
+			 FD1_IPC_SENSOR_CTL3);
+}
+
+/*
+ * fdp1_write_lut: Write a padded LUT to the hw
+ *
+ * FDP1 uses constant data for de-interlacing processing,
+ * with large tables. These hardware tables are all 256 bytes
+ * long, however they often contain repeated data at the end.
+ *
+ * The last byte of the table is written to all remaining entries.
+ */
+static void fdp1_write_lut(struct fdp1_dev *fdp1, const u8 *lut,
+			   unsigned int len, unsigned int base)
+{
+	unsigned int i;
+	u8 pad;
+
+	/* Tables larger than the hw are clipped */
+	len = min(len, 256u);
+
+	for (i = 0; i < len; i++)
+		fdp1_write(fdp1, lut[i], base + (i*4));
+
+	/* Tables are padded with the last entry */
+	pad = lut[i-1];
+
+	for (; i < 256; i++)
+		fdp1_write(fdp1, pad, base + (i*4));
+}
+
+static void fdp1_set_lut(struct fdp1_dev *fdp1)
+{
+	fdp1_write_lut(fdp1, fdp1_diff_adj, ARRAY_SIZE(fdp1_diff_adj),
+			FD1_LUT_DIF_ADJ);
+	fdp1_write_lut(fdp1, fdp1_sad_adj,  ARRAY_SIZE(fdp1_sad_adj),
+			FD1_LUT_SAD_ADJ);
+	fdp1_write_lut(fdp1, fdp1_bld_gain, ARRAY_SIZE(fdp1_bld_gain),
+			FD1_LUT_BLD_GAIN);
+	fdp1_write_lut(fdp1, fdp1_dif_gain, ARRAY_SIZE(fdp1_dif_gain),
+			FD1_LUT_DIF_GAIN);
+	fdp1_write_lut(fdp1, fdp1_mdet, ARRAY_SIZE(fdp1_mdet),
+			FD1_LUT_MDET);
+}
+
+static void fdp1_configure_rpf(struct fdp1_ctx *ctx,
+			       struct fdp1_job *job)
+{
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+	u32 picture_size;
+	u32 pstride;
+	u32 format;
+	u32 smsk_addr;
+
+	struct fdp1_q_data *q_data = &ctx->out_q;
+
+	/* Picture size is common to Source and Destination frames */
+	picture_size = (q_data->format.width << FD1_RPF_SIZE_H_SHIFT)
+		     | (q_data->vsize << FD1_RPF_SIZE_V_SHIFT);
+
+	/* Strides */
+	pstride = q_data->stride_y << FD1_RPF_PSTRIDE_Y_SHIFT;
+	if (q_data->format.num_planes > 1)
+		pstride |= q_data->stride_c << FD1_RPF_PSTRIDE_C_SHIFT;
+
+	/* Format control */
+	format = q_data->fmt->fmt;
+	if (q_data->fmt->swap_yc)
+		format |= FD1_RPF_FORMAT_RSPYCS;
+
+	if (q_data->fmt->swap_uv)
+		format |= FD1_RPF_FORMAT_RSPUVS;
+
+	if (job->active->field == V4L2_FIELD_BOTTOM) {
+		format |= FD1_RPF_FORMAT_CF; /* Set for Bottom field */
+		smsk_addr = ctx->smsk_addr[0];
+	} else {
+		smsk_addr = ctx->smsk_addr[1];
+	}
+
+	/* Deint mode is non-zero when deinterlacing */
+	if (ctx->deint_mode)
+		format |= FD1_RPF_FORMAT_CIPM;
+
+	fdp1_write(fdp1, format, FD1_RPF_FORMAT);
+	fdp1_write(fdp1, q_data->fmt->swap, FD1_RPF_SWAP);
+	fdp1_write(fdp1, picture_size, FD1_RPF_SIZE);
+	fdp1_write(fdp1, pstride, FD1_RPF_PSTRIDE);
+	fdp1_write(fdp1, smsk_addr, FD1_RPF_SMSK_ADDR);
+
+	/* Previous Field Channel (CH0) */
+	if (job->previous)
+		fdp1_write(fdp1, job->previous->addrs[0], FD1_RPF0_ADDR_Y);
+
+	/* Current Field Channel (CH1) */
+	fdp1_write(fdp1, job->active->addrs[0], FD1_RPF1_ADDR_Y);
+	fdp1_write(fdp1, job->active->addrs[1], FD1_RPF1_ADDR_C0);
+	fdp1_write(fdp1, job->active->addrs[2], FD1_RPF1_ADDR_C1);
+
+	/* Next Field  Channel (CH2) */
+	if (job->next)
+		fdp1_write(fdp1, job->next->addrs[0], FD1_RPF2_ADDR_Y);
+}
+
+static void fdp1_configure_wpf(struct fdp1_ctx *ctx,
+			       struct fdp1_job *job)
+{
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+	struct fdp1_q_data *src_q_data = &ctx->out_q;
+	struct fdp1_q_data *q_data = &ctx->cap_q;
+	u32 pstride;
+	u32 format;
+	u32 swap;
+	u32 rndctl;
+
+	pstride = q_data->format.plane_fmt[0].bytesperline
+			<< FD1_WPF_PSTRIDE_Y_SHIFT;
+
+	if (q_data->format.num_planes > 1)
+		pstride |= q_data->format.plane_fmt[1].bytesperline
+			<< FD1_WPF_PSTRIDE_C_SHIFT;
+
+	format = q_data->fmt->fmt; /* Output Format Code */
+
+	if (q_data->fmt->swap_yc)
+		format |= FD1_WPF_FORMAT_WSPYCS;
+
+	if (q_data->fmt->swap_uv)
+		format |= FD1_WPF_FORMAT_WSPUVS;
+
+	if (fdp1_fmt_is_rgb(q_data->fmt)) {
+		/* Enable Colour Space conversion */
+		format |= FD1_WPF_FORMAT_CSC;
+
+		/* Set WRTM */
+		if (src_q_data->format.ycbcr_enc == V4L2_YCBCR_ENC_709)
+			format |= FD1_WPF_FORMAT_WRTM_709_16;
+		else if (src_q_data->format.quantization ==
+				V4L2_QUANTIZATION_FULL_RANGE)
+			format |= FD1_WPF_FORMAT_WRTM_601_0;
+		else
+			format |= FD1_WPF_FORMAT_WRTM_601_16;
+	}
+
+	/* Set an alpha value into the Pad Value */
+	format |= ctx->alpha << FD1_WPF_FORMAT_PDV_SHIFT;
+
+	/* Determine picture rounding and clipping */
+	rndctl = FD1_WPF_RNDCTL_CBRM; /* Rounding Off */
+	rndctl |= FD1_WPF_RNDCTL_CLMD_NOCLIP;
+
+	/* WPF Swap needs both ISWAP and OSWAP setting */
+	swap = q_data->fmt->swap << FD1_WPF_SWAP_OSWAP_SHIFT;
+	swap |= src_q_data->fmt->swap << FD1_WPF_SWAP_SSWAP_SHIFT;
+
+	fdp1_write(fdp1, format, FD1_WPF_FORMAT);
+	fdp1_write(fdp1, rndctl, FD1_WPF_RNDCTL);
+	fdp1_write(fdp1, swap, FD1_WPF_SWAP);
+	fdp1_write(fdp1, pstride, FD1_WPF_PSTRIDE);
+
+	fdp1_write(fdp1, job->dst->addrs[0], FD1_WPF_ADDR_Y);
+	fdp1_write(fdp1, job->dst->addrs[1], FD1_WPF_ADDR_C0);
+	fdp1_write(fdp1, job->dst->addrs[2], FD1_WPF_ADDR_C1);
+}
+
+static void fdp1_configure_deint_mode(struct fdp1_ctx *ctx,
+				      struct fdp1_job *job)
+{
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+	u32 opmode = FD1_CTL_OPMODE_VIMD_NOINTERRUPT;
+	u32 ipcmode = FD1_IPC_MODE_DLI; /* Always set */
+	u32 channels = FD1_CTL_CHACT_WR | FD1_CTL_CHACT_RD1; /* Always on */
+
+	/* De-interlacing Mode */
+	switch (ctx->deint_mode) {
+	default:
+	case FDP1_PROGRESSIVE:
+		dprintk(fdp1, "Progressive Mode\n");
+		opmode |= FD1_CTL_OPMODE_PRG;
+		ipcmode |= FD1_IPC_MODE_DIM_FIXED2D;
+		break;
+	case FDP1_ADAPT2D3D:
+		dprintk(fdp1, "Adapt2D3D Mode\n");
+		if (ctx->sequence == 0 || ctx->aborting)
+			ipcmode |= FD1_IPC_MODE_DIM_FIXED2D;
+		else
+			ipcmode |= FD1_IPC_MODE_DIM_ADAPT2D3D;
+
+		if (ctx->sequence > 1) {
+			channels |= FD1_CTL_CHACT_SMW;
+			channels |= FD1_CTL_CHACT_RD0 | FD1_CTL_CHACT_RD2;
+		}
+
+		if (ctx->sequence > 2)
+			channels |= FD1_CTL_CHACT_SMR;
+
+		break;
+	case FDP1_FIXED3D:
+		dprintk(fdp1, "Fixed 3D Mode\n");
+		ipcmode |= FD1_IPC_MODE_DIM_FIXED3D;
+		/* Except for first and last frame, enable all channels */
+		if (!(ctx->sequence == 0 || ctx->aborting))
+			channels |= FD1_CTL_CHACT_RD0 | FD1_CTL_CHACT_RD2;
+		break;
+	case FDP1_FIXED2D:
+		dprintk(fdp1, "Fixed 2D Mode\n");
+		ipcmode |= FD1_IPC_MODE_DIM_FIXED2D;
+		/* No extra channels enabled */
+		break;
+	case FDP1_PREVFIELD:
+		dprintk(fdp1, "Previous Field Mode\n");
+		ipcmode |= FD1_IPC_MODE_DIM_PREVFIELD;
+		channels |= FD1_CTL_CHACT_RD0; /* Previous */
+		break;
+	case FDP1_NEXTFIELD:
+		dprintk(fdp1, "Next Field Mode\n");
+		ipcmode |= FD1_IPC_MODE_DIM_NEXTFIELD;
+		channels |= FD1_CTL_CHACT_RD2; /* Next */
+		break;
+	}
+
+	fdp1_write(fdp1, channels,	FD1_CTL_CHACT);
+	fdp1_write(fdp1, opmode,	FD1_CTL_OPMODE);
+	fdp1_write(fdp1, ipcmode,	FD1_IPC_MODE);
+}
+
+/*
+ * fdp1_device_process() - Run the hardware
+ *
+ * Configure and start the hardware to generate a single frame
+ * of output given our input parameters.
+ */
+static int fdp1_device_process(struct fdp1_ctx *ctx)
+
+{
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+	struct fdp1_job *job;
+	unsigned long flags;
+
+	spin_lock_irqsave(&fdp1->device_process_lock, flags);
+
+	/* Get a job to process */
+	job = get_queued_job(fdp1);
+	if (!job) {
+		/*
+		 * VINT can call us to see if we can queue another job.
+		 * If we have no work to do, we simply return.
+		 */
+		spin_unlock_irqrestore(&fdp1->device_process_lock, flags);
+		return 0;
+	}
+
+	/* First Frame only? ... */
+	fdp1_write(fdp1, FD1_CTL_CLKCTRL_CSTP_N, FD1_CTL_CLKCTRL);
+
+	/* Set the mode, and configuration */
+	fdp1_configure_deint_mode(ctx, job);
+
+	/* DLI Static Configuration */
+	fdp1_set_ipc_dli(ctx);
+
+	/* Sensor Configuration */
+	fdp1_set_ipc_sensor(ctx);
+
+	/* Setup the source picture */
+	fdp1_configure_rpf(ctx, job);
+
+	/* Setup the destination picture */
+	fdp1_configure_wpf(ctx, job);
+
+	/* Line Memory Pixel Number Register for linear access */
+	fdp1_write(fdp1, FD1_IPC_LMEM_LINEAR, FD1_IPC_LMEM);
+
+	/* Enable Interrupts */
+	fdp1_write(fdp1, FD1_CTL_IRQ_MASK, FD1_CTL_IRQENB);
+
+	/* Finally, the Immediate Registers */
+
+	/* This job is now in the HW queue */
+	queue_hw_job(fdp1, job);
+
+	/* Start the command */
+	fdp1_write(fdp1, FD1_CTL_CMD_STRCMD, FD1_CTL_CMD);
+
+	/* Registers will update to HW at next VINT */
+	fdp1_write(fdp1, FD1_CTL_REGEND_REGEND, FD1_CTL_REGEND);
+
+	/* Enable VINT Generator */
+	fdp1_write(fdp1, FD1_CTL_SGCMD_SGEN, FD1_CTL_SGCMD);
+
+	spin_unlock_irqrestore(&fdp1->device_process_lock, flags);
+
+	return 0;
+}
+
+/*
+ * mem2mem callbacks
+ */
+
+/**
+ * job_ready() - check whether an instance is ready to be scheduled to run
+ */
+static int fdp1_m2m_job_ready(void *priv)
+{
+	struct fdp1_ctx *ctx = priv;
+	struct fdp1_q_data *src_q_data = &ctx->out_q;
+	int srcbufs = 1;
+	int dstbufs = 1;
+
+	dprintk(ctx->fdp1, "+ Src: %d : Dst: %d\n",
+			v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx),
+			v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx));
+
+	/* One output buffer is required for each field */
+	if (V4L2_FIELD_HAS_BOTH(src_q_data->format.field))
+		dstbufs = 2;
+
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < srcbufs
+	    || v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < dstbufs) {
+		dprintk(ctx->fdp1, "Not enough buffers available\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static void fdp1_m2m_job_abort(void *priv)
+{
+	struct fdp1_ctx *ctx = priv;
+
+	dprintk(ctx->fdp1, "+\n");
+
+	/* Will cancel the transaction in the next interrupt handler */
+	ctx->aborting = 1;
+
+	/* Immediate abort sequence */
+	fdp1_write(ctx->fdp1, 0, FD1_CTL_SGCMD);
+	fdp1_write(ctx->fdp1, FD1_CTL_SRESET_SRST, FD1_CTL_SRESET);
+}
+
+/*
+ * fdp1_prepare_job: Prepare and queue a new job for a single action of work
+ *
+ * Prepare the next field, (or frame in progressive) and an output
+ * buffer for the hardware to perform a single operation.
+ */
+static struct fdp1_job *fdp1_prepare_job(struct fdp1_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *vbuf;
+	struct fdp1_buffer *fbuf;
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+	struct fdp1_job *job;
+	unsigned int buffers_required = 1;
+
+	dprintk(fdp1, "+\n");
+
+	if (FDP1_DEINT_MODE_USES_NEXT(ctx->deint_mode))
+		buffers_required = 2;
+
+	if (ctx->buffers_queued < buffers_required)
+		return NULL;
+
+	job = fdp1_job_alloc(fdp1);
+	if (!job) {
+		dprintk(fdp1, "No free jobs currently available\n");
+		return NULL;
+	}
+
+	job->active = fdp1_dequeue_field(ctx);
+	if (!job->active) {
+		/* Buffer check should prevent this ever happening */
+		dprintk(fdp1, "No input buffers currently available\n");
+
+		fdp1_job_free(fdp1, job);
+		return NULL;
+	}
+
+	dprintk(fdp1, "+ Buffer en-route...\n");
+
+	/* Source buffers have been prepared on our buffer_queue
+	 * Prepare our Output buffer
+	 */
+	vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	fbuf = to_fdp1_buffer(vbuf);
+	job->dst = &fbuf->fields[0];
+
+	job->active->vb->sequence = ctx->sequence;
+	job->dst->vb->sequence = ctx->sequence;
+	ctx->sequence++;
+
+	if (FDP1_DEINT_MODE_USES_PREV(ctx->deint_mode)) {
+		job->previous = ctx->previous;
+
+		/* Active buffer becomes the next job's previous buffer */
+		ctx->previous = job->active;
+	}
+
+	if (FDP1_DEINT_MODE_USES_NEXT(ctx->deint_mode)) {
+		/* Must be called after 'active' is dequeued */
+		job->next = fdp1_peek_queued_field(ctx);
+	}
+
+	/* Transfer timestamps and flags from src->dst */
+
+	job->dst->vb->vb2_buf.timestamp = job->active->vb->vb2_buf.timestamp;
+
+	job->dst->vb->flags = job->active->vb->flags &
+				V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+
+	/* Ideally, the frame-end function will just 'check' to see
+	 * if there are more jobs instead
+	 */
+	ctx->translen++;
+
+	/* Finally, Put this job on the processing queue */
+	queue_job(fdp1, job);
+
+	dprintk(fdp1, "Job Queued translen = %d\n", ctx->translen);
+
+	return job;
+}
+
+/* fdp1_m2m_device_run() - prepares and starts the device for an M2M task
+ *
+ * A single input buffer is taken and serialised into our fdp1_buffer
+ * queue. The queue is then processed to create as many jobs as possible
+ * from our available input.
+ */
+static void fdp1_m2m_device_run(void *priv)
+{
+	struct fdp1_ctx *ctx = priv;
+	struct fdp1_dev *fdp1 = ctx->fdp1;
+	struct vb2_v4l2_buffer *src_vb;
+	struct fdp1_buffer *buf;
+	unsigned int i;
+
+	dprintk(fdp1, "+\n");
+
+	ctx->translen = 0;
+
+	/* Get our incoming buffer of either one or two fields, or one frame */
+	src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	buf = to_fdp1_buffer(src_vb);
+
+	for (i = 0; i < buf->num_fields; i++) {
+		struct fdp1_field_buffer *fbuf = &buf->fields[i];
+
+		fdp1_queue_field(ctx, fbuf);
+		dprintk(fdp1, "Queued Buffer [%d] last_field:%d\n",
+				i, fbuf->last_field);
+	}
+
+	/* Queue as many jobs as our data provides for */
+	while (fdp1_prepare_job(ctx))
+		;
+
+	if (ctx->translen == 0) {
+		dprintk(fdp1, "No jobs were processed. M2M action complete\n");
+		v4l2_m2m_job_finish(fdp1->m2m_dev, ctx->fh.m2m_ctx);
+		return;
+	}
+
+	/* Kick the job processing action */
+	fdp1_device_process(ctx);
+}
+
+/*
+ * device_frame_end:
+ *
+ * Handles the M2M level after a buffer completion event.
+ */
+static void device_frame_end(struct fdp1_dev *fdp1,
+			     enum vb2_buffer_state state)
+{
+	struct fdp1_ctx *ctx;
+	unsigned long flags;
+	struct fdp1_job *job = get_hw_queued_job(fdp1);
+
+	dprintk(fdp1, "+\n");
+
+	ctx = v4l2_m2m_get_curr_priv(fdp1->m2m_dev);
+
+	if (ctx == NULL) {
+		v4l2_err(&fdp1->v4l2_dev,
+			"Instance released before the end of transaction\n");
+		return;
+	}
+
+	ctx->num_processed++;
+
+	/*
+	 * fdp1_field_complete will call buf_done only when the last vb2_buffer
+	 * reference is complete
+	 */
+	if (FDP1_DEINT_MODE_USES_PREV(ctx->deint_mode))
+		fdp1_field_complete(ctx, job->previous);
+	else
+		fdp1_field_complete(ctx, job->active);
+
+	spin_lock_irqsave(&fdp1->irqlock, flags);
+	v4l2_m2m_buf_done(job->dst->vb, state);
+	job->dst = NULL;
+	spin_unlock_irqrestore(&fdp1->irqlock, flags);
+
+	/* Move this job back to the free job list */
+	fdp1_job_free(fdp1, job);
+
+	dprintk(fdp1, "curr_ctx->num_processed %d curr_ctx->translen %d\n",
+			ctx->num_processed, ctx->translen);
+
+	if (ctx->num_processed == ctx->translen ||
+			ctx->aborting) {
+		dprintk(ctx->fdp1, "Finishing transaction\n");
+		ctx->num_processed = 0;
+		v4l2_m2m_job_finish(fdp1->m2m_dev, ctx->fh.m2m_ctx);
+	} else {
+		/*
+		 * For pipelined performance support, this would
+		 * be called from a VINT handler
+		 */
+		fdp1_device_process(ctx);
+	}
+}
+
+/*
+ * video ioctls
+ */
+static int fdp1_vidioc_querycap(struct file *file, void *priv,
+			   struct v4l2_capability *cap)
+{
+	strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver));
+	strlcpy(cap->card, DRIVER_NAME, sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info),
+			"platform:%s", DRIVER_NAME);
+	return 0;
+}
+
+static int fdp1_enum_fmt(struct v4l2_fmtdesc *f, u32 type)
+{
+	unsigned int i, num;
+
+	num = 0;
+
+	for (i = 0; i < ARRAY_SIZE(fdp1_formats); ++i) {
+		if (fdp1_formats[i].types & type) {
+			if (num == f->index)
+				break;
+			++num;
+		}
+	}
+
+	/* Format not found */
+	if (i >= ARRAY_SIZE(fdp1_formats))
+		return -EINVAL;
+
+	/* Format found */
+	f->pixelformat = fdp1_formats[i].fourcc;
+
+	return 0;
+}
+
+static int fdp1_enum_fmt_vid_cap(struct file *file, void *priv,
+				 struct v4l2_fmtdesc *f)
+{
+	return fdp1_enum_fmt(f, FDP1_CAPTURE);
+}
+
+static int fdp1_enum_fmt_vid_out(struct file *file, void *priv,
+				   struct v4l2_fmtdesc *f)
+{
+	return fdp1_enum_fmt(f, FDP1_OUTPUT);
+}
+
+static int fdp1_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct fdp1_q_data *q_data;
+	struct fdp1_ctx *ctx = fh_to_ctx(priv);
+
+	if (!v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type))
+		return -EINVAL;
+
+	q_data = get_q_data(ctx, f->type);
+	f->fmt.pix_mp = q_data->format;
+
+	return 0;
+}
+
+static void fdp1_compute_stride(struct v4l2_pix_format_mplane *pix,
+				const struct fdp1_fmt *fmt)
+{
+	unsigned int i;
+
+	/* Compute and clamp the stride and image size. */
+	for (i = 0; i < min_t(unsigned int, fmt->num_planes, 2U); ++i) {
+		unsigned int hsub = i > 0 ? fmt->hsub : 1;
+		unsigned int vsub = i > 0 ? fmt->vsub : 1;
+		 /* From VSP : TODO: Confirm alignment limits for FDP1 */
+		unsigned int align = 128;
+		unsigned int bpl;
+
+		bpl = clamp_t(unsigned int, pix->plane_fmt[i].bytesperline,
+			      pix->width / hsub * fmt->bpp[i] / 8,
+			      round_down(FDP1_MAX_STRIDE, align));
+
+		pix->plane_fmt[i].bytesperline = round_up(bpl, align);
+		pix->plane_fmt[i].sizeimage = pix->plane_fmt[i].bytesperline
+					    * pix->height / vsub;
+
+		memset(pix->plane_fmt[i].reserved, 0,
+		       sizeof(pix->plane_fmt[i].reserved));
+	}
+
+	if (fmt->num_planes == 3) {
+		/* The two chroma planes must have the same stride. */
+		pix->plane_fmt[2].bytesperline = pix->plane_fmt[1].bytesperline;
+		pix->plane_fmt[2].sizeimage = pix->plane_fmt[1].sizeimage;
+
+		memset(pix->plane_fmt[2].reserved, 0,
+		       sizeof(pix->plane_fmt[2].reserved));
+	}
+}
+
+static void fdp1_try_fmt_output(struct fdp1_ctx *ctx,
+				const struct fdp1_fmt **fmtinfo,
+				struct v4l2_pix_format_mplane *pix)
+{
+	const struct fdp1_fmt *fmt;
+	unsigned int width;
+	unsigned int height;
+
+	/* Validate the pixel format to ensure the output queue supports it. */
+	fmt = fdp1_find_format(pix->pixelformat);
+	if (!fmt || !(fmt->types & FDP1_OUTPUT))
+		fmt = fdp1_find_format(V4L2_PIX_FMT_YUYV);
+
+	if (fmtinfo)
+		*fmtinfo = fmt;
+
+	pix->pixelformat = fmt->fourcc;
+	pix->num_planes = fmt->num_planes;
+
+	/*
+	 * Progressive video and all interlaced field orders are acceptable.
+	 * Default to V4L2_FIELD_INTERLACED.
+	 */
+	if (pix->field != V4L2_FIELD_NONE &&
+	    pix->field != V4L2_FIELD_ALTERNATE &&
+	    !V4L2_FIELD_HAS_BOTH(pix->field))
+		pix->field = V4L2_FIELD_INTERLACED;
+
+	/*
+	 * The deinterlacer doesn't care about the colorspace, accept all values
+	 * and default to V4L2_COLORSPACE_SMPTE170M. The YUV to RGB conversion
+	 * at the output of the deinterlacer supports a subset of encodings and
+	 * quantization methods and will only be available when the colorspace
+	 * allows it.
+	 */
+	if (pix->colorspace == V4L2_COLORSPACE_DEFAULT)
+		pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+	/*
+	 * Align the width and height for YUV 4:2:2 and 4:2:0 formats and clamp
+	 * them to the supported frame size range. The height boundary are
+	 * related to the full frame, divide them by two when the format passes
+	 * fields in separate buffers.
+	 */
+	width = round_down(pix->width, fmt->hsub);
+	pix->width = clamp(width, FDP1_MIN_W, FDP1_MAX_W);
+
+	height = round_down(pix->height, fmt->vsub);
+	if (pix->field == V4L2_FIELD_ALTERNATE)
+		pix->height = clamp(height, FDP1_MIN_H / 2, FDP1_MAX_H / 2);
+	else
+		pix->height = clamp(height, FDP1_MIN_H, FDP1_MAX_H);
+
+	fdp1_compute_stride(pix, fmt);
+}
+
+static void fdp1_try_fmt_capture(struct fdp1_ctx *ctx,
+				 const struct fdp1_fmt **fmtinfo,
+				 struct v4l2_pix_format_mplane *pix)
+{
+	struct fdp1_q_data *src_data = &ctx->out_q;
+	enum v4l2_colorspace colorspace;
+	enum v4l2_ycbcr_encoding ycbcr_enc;
+	enum v4l2_quantization quantization;
+	const struct fdp1_fmt *fmt;
+	bool allow_rgb;
+
+	/*
+	 * Validate the pixel format. We can only accept RGB output formats if
+	 * the input encoding and quantization are compatible with the format
+	 * conversions supported by the hardware. The supported combinations are
+	 *
+	 * V4L2_YCBCR_ENC_601 + V4L2_QUANTIZATION_LIM_RANGE
+	 * V4L2_YCBCR_ENC_601 + V4L2_QUANTIZATION_FULL_RANGE
+	 * V4L2_YCBCR_ENC_709 + V4L2_QUANTIZATION_LIM_RANGE
+	 */
+	colorspace = src_data->format.colorspace;
+
+	ycbcr_enc = src_data->format.ycbcr_enc;
+	if (ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
+		ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(colorspace);
+
+	quantization = src_data->format.quantization;
+	if (quantization == V4L2_QUANTIZATION_DEFAULT)
+		quantization = V4L2_MAP_QUANTIZATION_DEFAULT(false, colorspace,
+							     ycbcr_enc);
+
+	allow_rgb = ycbcr_enc == V4L2_YCBCR_ENC_601 ||
+		    (ycbcr_enc == V4L2_YCBCR_ENC_709 &&
+		     quantization == V4L2_QUANTIZATION_LIM_RANGE);
+
+	fmt = fdp1_find_format(pix->pixelformat);
+	if (!fmt || (!allow_rgb && fdp1_fmt_is_rgb(fmt)))
+		fmt = fdp1_find_format(V4L2_PIX_FMT_YUYV);
+
+	if (fmtinfo)
+		*fmtinfo = fmt;
+
+	pix->pixelformat = fmt->fourcc;
+	pix->num_planes = fmt->num_planes;
+	pix->field = V4L2_FIELD_NONE;
+
+	/*
+	 * The colorspace on the capture queue is copied from the output queue
+	 * as the hardware can't change the colorspace. It can convert YCbCr to
+	 * RGB though, in which case the encoding and quantization are set to
+	 * default values as anything else wouldn't make sense.
+	 */
+	pix->colorspace = src_data->format.colorspace;
+	pix->xfer_func = src_data->format.xfer_func;
+
+	if (fdp1_fmt_is_rgb(fmt)) {
+		pix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+		pix->quantization = V4L2_QUANTIZATION_DEFAULT;
+	} else {
+		pix->ycbcr_enc = src_data->format.ycbcr_enc;
+		pix->quantization = src_data->format.quantization;
+	}
+
+	/*
+	 * The frame width is identical to the output queue, and the height is
+	 * either doubled or identical depending on whether the output queue
+	 * field order contains one or two fields per frame.
+	 */
+	pix->width = src_data->format.width;
+	if (src_data->format.field == V4L2_FIELD_ALTERNATE)
+		pix->height = 2 * src_data->format.height;
+	else
+		pix->height = src_data->format.height;
+
+	fdp1_compute_stride(pix, fmt);
+}
+
+static int fdp1_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct fdp1_ctx *ctx = fh_to_ctx(priv);
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		fdp1_try_fmt_output(ctx, NULL, &f->fmt.pix_mp);
+	else
+		fdp1_try_fmt_capture(ctx, NULL, &f->fmt.pix_mp);
+
+	dprintk(ctx->fdp1, "Try %s format: %4s (0x%08x) %ux%u field %u\n",
+		V4L2_TYPE_IS_OUTPUT(f->type) ? "output" : "capture",
+		(char *)&f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.pixelformat,
+		f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.field);
+
+	return 0;
+}
+
+static void fdp1_set_format(struct fdp1_ctx *ctx,
+			    struct v4l2_pix_format_mplane *pix,
+			    enum v4l2_buf_type type)
+{
+	struct fdp1_q_data *q_data = get_q_data(ctx, type);
+	const struct fdp1_fmt *fmtinfo;
+
+	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		fdp1_try_fmt_output(ctx, &fmtinfo, pix);
+	else
+		fdp1_try_fmt_capture(ctx, &fmtinfo, pix);
+
+	q_data->fmt = fmtinfo;
+	q_data->format = *pix;
+
+	q_data->vsize = pix->height;
+	if (pix->field != V4L2_FIELD_NONE)
+		q_data->vsize /= 2;
+
+	q_data->stride_y = pix->plane_fmt[0].bytesperline;
+	q_data->stride_c = pix->plane_fmt[1].bytesperline;
+
+	/* Adjust strides for interleaved buffers */
+	if (pix->field == V4L2_FIELD_INTERLACED ||
+	    pix->field == V4L2_FIELD_INTERLACED_TB ||
+	    pix->field == V4L2_FIELD_INTERLACED_BT) {
+		q_data->stride_y *= 2;
+		q_data->stride_c *= 2;
+	}
+
+	/* Propagate the format from the output node to the capture node. */
+	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		struct fdp1_q_data *dst_data = &ctx->cap_q;
+
+		/*
+		 * Copy the format, clear the per-plane bytes per line and image
+		 * size, override the field and double the height if needed.
+		 */
+		dst_data->format = q_data->format;
+		memset(dst_data->format.plane_fmt, 0,
+		       sizeof(dst_data->format.plane_fmt));
+
+		dst_data->format.field = V4L2_FIELD_NONE;
+		if (pix->field == V4L2_FIELD_ALTERNATE)
+			dst_data->format.height *= 2;
+
+		fdp1_try_fmt_capture(ctx, &dst_data->fmt, &dst_data->format);
+
+		dst_data->vsize = dst_data->format.height;
+		dst_data->stride_y = dst_data->format.plane_fmt[0].bytesperline;
+		dst_data->stride_c = dst_data->format.plane_fmt[1].bytesperline;
+	}
+}
+
+static int fdp1_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct fdp1_ctx *ctx = fh_to_ctx(priv);
+	struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
+	struct vb2_queue *vq = v4l2_m2m_get_vq(m2m_ctx, f->type);
+
+	if (vb2_is_busy(vq)) {
+		v4l2_err(&ctx->fdp1->v4l2_dev, "%s queue busy\n", __func__);
+		return -EBUSY;
+	}
+
+	fdp1_set_format(ctx, &f->fmt.pix_mp, f->type);
+
+	dprintk(ctx->fdp1, "Set %s format: %4s (0x%08x) %ux%u field %u\n",
+		V4L2_TYPE_IS_OUTPUT(f->type) ? "output" : "capture",
+		(char *)&f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.pixelformat,
+		f->fmt.pix_mp.width, f->fmt.pix_mp.height, f->fmt.pix_mp.field);
+
+	return 0;
+}
+
+static int fdp1_g_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct fdp1_ctx *ctx =
+		container_of(ctrl->handler, struct fdp1_ctx, hdl);
+	struct fdp1_q_data *src_q_data = &ctx->out_q;
+
+	switch (ctrl->id) {
+	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+		if (V4L2_FIELD_HAS_BOTH(src_q_data->format.field))
+			ctrl->val = 2;
+		else
+			ctrl->val = 1;
+		return 0;
+	}
+
+	return 1;
+}
+
+static int fdp1_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct fdp1_ctx *ctx =
+		container_of(ctrl->handler, struct fdp1_ctx, hdl);
+
+	switch (ctrl->id) {
+	case V4L2_CID_ALPHA_COMPONENT:
+		ctx->alpha = ctrl->val;
+		break;
+
+	case V4L2_CID_DEINTERLACING_MODE:
+		ctx->deint_mode = ctrl->val;
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops fdp1_ctrl_ops = {
+	.s_ctrl = fdp1_s_ctrl,
+	.g_volatile_ctrl = fdp1_g_ctrl,
+};
+
+static const char * const fdp1_ctrl_deint_menu[] = {
+	"Progressive",
+	"Adaptive 2D/3D",
+	"Fixed 2D",
+	"Fixed 3D",
+	"Previous field",
+	"Next field",
+	NULL
+};
+
+static const struct v4l2_ioctl_ops fdp1_ioctl_ops = {
+	.vidioc_querycap	= fdp1_vidioc_querycap,
+
+	.vidioc_enum_fmt_vid_cap_mplane = fdp1_enum_fmt_vid_cap,
+	.vidioc_enum_fmt_vid_out_mplane = fdp1_enum_fmt_vid_out,
+	.vidioc_g_fmt_vid_cap_mplane	= fdp1_g_fmt,
+	.vidioc_g_fmt_vid_out_mplane	= fdp1_g_fmt,
+	.vidioc_try_fmt_vid_cap_mplane	= fdp1_try_fmt,
+	.vidioc_try_fmt_vid_out_mplane	= fdp1_try_fmt,
+	.vidioc_s_fmt_vid_cap_mplane	= fdp1_s_fmt,
+	.vidioc_s_fmt_vid_out_mplane	= fdp1_s_fmt,
+
+	.vidioc_reqbufs		= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf		= v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf		= v4l2_m2m_ioctl_dqbuf,
+	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
+	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
+
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/*
+ * Queue operations
+ */
+
+static int fdp1_queue_setup(struct vb2_queue *vq,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[],
+				struct device *alloc_ctxs[])
+{
+	struct fdp1_ctx *ctx = vb2_get_drv_priv(vq);
+	struct fdp1_q_data *q_data;
+	unsigned int i;
+
+	q_data = get_q_data(ctx, vq->type);
+
+	if (*nplanes) {
+		if (*nplanes > FDP1_MAX_PLANES)
+			return -EINVAL;
+
+		return 0;
+	}
+
+	*nplanes = q_data->format.num_planes;
+
+	for (i = 0; i < *nplanes; i++)
+		sizes[i] = q_data->format.plane_fmt[i].sizeimage;
+
+	return 0;
+}
+
+static void fdp1_buf_prepare_field(struct fdp1_q_data *q_data,
+				   struct vb2_v4l2_buffer *vbuf,
+				   unsigned int field_num)
+{
+	struct fdp1_buffer *buf = to_fdp1_buffer(vbuf);
+	struct fdp1_field_buffer *fbuf = &buf->fields[field_num];
+	unsigned int num_fields;
+	unsigned int i;
+
+	num_fields = V4L2_FIELD_HAS_BOTH(vbuf->field) ? 2 : 1;
+
+	fbuf->vb = vbuf;
+	fbuf->last_field = (field_num + 1) == num_fields;
+
+	for (i = 0; i < vbuf->vb2_buf.num_planes; ++i)
+		fbuf->addrs[i] = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, i);
+
+	switch (vbuf->field) {
+	case V4L2_FIELD_INTERLACED:
+		/*
+		 * Interlaced means bottom-top for 60Hz TV standards (NTSC) and
+		 * top-bottom for 50Hz. As TV standards are not applicable to
+		 * the mem-to-mem API, use the height as a heuristic.
+		 */
+		fbuf->field = (q_data->format.height < 576) == field_num
+			    ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+		break;
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_SEQ_TB:
+		fbuf->field = field_num ? V4L2_FIELD_BOTTOM : V4L2_FIELD_TOP;
+		break;
+	case V4L2_FIELD_INTERLACED_BT:
+	case V4L2_FIELD_SEQ_BT:
+		fbuf->field = field_num ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+		break;
+	default:
+		fbuf->field = vbuf->field;
+		break;
+	}
+
+	/* Buffer is completed */
+	if (!field_num)
+		return;
+
+	/* Adjust buffer addresses for second field */
+	switch (vbuf->field) {
+	case V4L2_FIELD_INTERLACED:
+	case V4L2_FIELD_INTERLACED_TB:
+	case V4L2_FIELD_INTERLACED_BT:
+		for (i = 0; i < vbuf->vb2_buf.num_planes; i++)
+			fbuf->addrs[i] +=
+				(i == 0 ? q_data->stride_y : q_data->stride_c);
+		break;
+	case V4L2_FIELD_SEQ_TB:
+	case V4L2_FIELD_SEQ_BT:
+		for (i = 0; i < vbuf->vb2_buf.num_planes; i++)
+			fbuf->addrs[i] += q_data->vsize *
+				(i == 0 ? q_data->stride_y : q_data->stride_c);
+		break;
+	}
+}
+
+static int fdp1_buf_prepare(struct vb2_buffer *vb)
+{
+	struct fdp1_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct fdp1_q_data *q_data = get_q_data(ctx, vb->vb2_queue->type);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct fdp1_buffer *buf = to_fdp1_buffer(vbuf);
+	unsigned int i;
+
+	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+		bool field_valid = true;
+
+		/* Validate the buffer field. */
+		switch (q_data->format.field) {
+		case V4L2_FIELD_NONE:
+			if (vbuf->field != V4L2_FIELD_NONE)
+				field_valid = false;
+			break;
+
+		case V4L2_FIELD_ALTERNATE:
+			if (vbuf->field != V4L2_FIELD_TOP &&
+			    vbuf->field != V4L2_FIELD_BOTTOM)
+				field_valid = false;
+			break;
+
+		case V4L2_FIELD_INTERLACED:
+		case V4L2_FIELD_SEQ_TB:
+		case V4L2_FIELD_SEQ_BT:
+		case V4L2_FIELD_INTERLACED_TB:
+		case V4L2_FIELD_INTERLACED_BT:
+			if (vbuf->field != q_data->format.field)
+				field_valid = false;
+			break;
+		}
+
+		if (!field_valid) {
+			dprintk(ctx->fdp1,
+				"buffer field %u invalid for format field %u\n",
+				vbuf->field, q_data->format.field);
+			return -EINVAL;
+		}
+	} else {
+		vbuf->field = V4L2_FIELD_NONE;
+	}
+
+	/* Validate the planes sizes. */
+	for (i = 0; i < q_data->format.num_planes; i++) {
+		unsigned long size = q_data->format.plane_fmt[i].sizeimage;
+
+		if (vb2_plane_size(vb, i) < size) {
+			dprintk(ctx->fdp1,
+				"data will not fit into plane [%u/%u] (%lu < %lu)\n",
+				i, q_data->format.num_planes,
+				vb2_plane_size(vb, i), size);
+			return -EINVAL;
+		}
+
+		/* We have known size formats all around */
+		vb2_set_plane_payload(vb, i, size);
+	}
+
+	buf->num_fields = V4L2_FIELD_HAS_BOTH(vbuf->field) ? 2 : 1;
+	for (i = 0; i < buf->num_fields; ++i)
+		fdp1_buf_prepare_field(q_data, vbuf, i);
+
+	return 0;
+}
+
+static void fdp1_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct fdp1_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int fdp1_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct fdp1_ctx *ctx = vb2_get_drv_priv(q);
+	struct fdp1_q_data *q_data = get_q_data(ctx, q->type);
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		/*
+		 * Force our deint_mode when we are progressive,
+		 * ignoring any setting on the device from the user,
+		 * Otherwise, lock in the requested de-interlace mode.
+		 */
+		if (q_data->format.field == V4L2_FIELD_NONE)
+			ctx->deint_mode = FDP1_PROGRESSIVE;
+
+		if (ctx->deint_mode == FDP1_ADAPT2D3D) {
+			u32 stride;
+			dma_addr_t smsk_base;
+			const u32 bpp = 2; /* bytes per pixel */
+
+			stride = round_up(q_data->format.width, 8);
+
+			ctx->smsk_size = bpp * stride * q_data->vsize;
+
+			ctx->smsk_cpu = dma_alloc_coherent(ctx->fdp1->dev,
+				ctx->smsk_size, &smsk_base, GFP_KERNEL);
+
+			if (ctx->smsk_cpu == NULL) {
+				dprintk(ctx->fdp1, "Failed to alloc smsk\n");
+				return -ENOMEM;
+			}
+
+			ctx->smsk_addr[0] = smsk_base;
+			ctx->smsk_addr[1] = smsk_base + (ctx->smsk_size/2);
+		}
+	}
+
+	return 0;
+}
+
+static void fdp1_stop_streaming(struct vb2_queue *q)
+{
+	struct fdp1_ctx *ctx = vb2_get_drv_priv(q);
+	struct vb2_v4l2_buffer *vbuf;
+	unsigned long flags;
+
+	while (1) {
+		if (V4L2_TYPE_IS_OUTPUT(q->type))
+			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		else
+			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+		if (vbuf == NULL)
+			break;
+		spin_lock_irqsave(&ctx->fdp1->irqlock, flags);
+		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+		spin_unlock_irqrestore(&ctx->fdp1->irqlock, flags);
+	}
+
+	/* Empty Output queues */
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		/* Empty our internal queues */
+		struct fdp1_field_buffer *fbuf;
+
+		/* Free any queued buffers */
+		fbuf = fdp1_dequeue_field(ctx);
+		while (fbuf != NULL) {
+			fdp1_field_complete(ctx, fbuf);
+			fbuf = fdp1_dequeue_field(ctx);
+		}
+
+		/* Free smsk_data */
+		if (ctx->smsk_cpu) {
+			dma_free_coherent(ctx->fdp1->dev, ctx->smsk_size,
+					ctx->smsk_cpu, ctx->smsk_addr[0]);
+			ctx->smsk_addr[0] = ctx->smsk_addr[1] = 0;
+			ctx->smsk_cpu = NULL;
+		}
+
+		WARN(!list_empty(&ctx->fields_queue),
+				"Buffer queue not empty");
+	} else {
+		/* Empty Capture queues (Jobs) */
+		struct fdp1_job *job;
+
+		job = get_queued_job(ctx->fdp1);
+		while (job) {
+			if (FDP1_DEINT_MODE_USES_PREV(ctx->deint_mode))
+				fdp1_field_complete(ctx, job->previous);
+			else
+				fdp1_field_complete(ctx, job->active);
+
+			v4l2_m2m_buf_done(job->dst->vb, VB2_BUF_STATE_ERROR);
+			job->dst = NULL;
+
+			job = get_queued_job(ctx->fdp1);
+		}
+
+		/* Free any held buffer in the ctx */
+		fdp1_field_complete(ctx, ctx->previous);
+
+		WARN(!list_empty(&ctx->fdp1->queued_job_list),
+				"Queued Job List not empty");
+
+		WARN(!list_empty(&ctx->fdp1->hw_job_list),
+				"HW Job list not empty");
+	}
+}
+
+static struct vb2_ops fdp1_qops = {
+	.queue_setup	 = fdp1_queue_setup,
+	.buf_prepare	 = fdp1_buf_prepare,
+	.buf_queue	 = fdp1_buf_queue,
+	.start_streaming = fdp1_start_streaming,
+	.stop_streaming  = fdp1_stop_streaming,
+	.wait_prepare	 = vb2_ops_wait_prepare,
+	.wait_finish	 = vb2_ops_wait_finish,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+		      struct vb2_queue *dst_vq)
+{
+	struct fdp1_ctx *ctx = priv;
+	int ret;
+
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	src_vq->drv_priv = ctx;
+	src_vq->buf_struct_size = sizeof(struct fdp1_buffer);
+	src_vq->ops = &fdp1_qops;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = &ctx->fdp1->dev_mutex;
+	src_vq->dev = ctx->fdp1->dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->buf_struct_size = sizeof(struct fdp1_buffer);
+	dst_vq->ops = &fdp1_qops;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = &ctx->fdp1->dev_mutex;
+	dst_vq->dev = ctx->fdp1->dev;
+
+	return vb2_queue_init(dst_vq);
+}
+
+/*
+ * File operations
+ */
+static int fdp1_open(struct file *file)
+{
+	struct fdp1_dev *fdp1 = video_drvdata(file);
+	struct v4l2_pix_format_mplane format;
+	struct fdp1_ctx *ctx = NULL;
+	struct v4l2_ctrl *ctrl;
+	int ret = 0;
+
+	if (mutex_lock_interruptible(&fdp1->dev_mutex))
+		return -ERESTARTSYS;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	ctx->fdp1 = fdp1;
+
+	/* Initialise Queues */
+	INIT_LIST_HEAD(&ctx->fields_queue);
+
+	ctx->translen = 1;
+	ctx->sequence = 0;
+
+	/* Initialise controls */
+
+	v4l2_ctrl_handler_init(&ctx->hdl, 3);
+	v4l2_ctrl_new_std_menu_items(&ctx->hdl, &fdp1_ctrl_ops,
+				     V4L2_CID_DEINTERLACING_MODE,
+				     FDP1_NEXTFIELD, BIT(0), FDP1_FIXED3D,
+				     fdp1_ctrl_deint_menu);
+
+	ctrl = v4l2_ctrl_new_std(&ctx->hdl, &fdp1_ctrl_ops,
+			V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 2, 1, 1);
+	if (ctrl)
+		ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+
+	v4l2_ctrl_new_std(&ctx->hdl, &fdp1_ctrl_ops,
+			  V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
+
+	if (ctx->hdl.error) {
+		ret = ctx->hdl.error;
+		v4l2_ctrl_handler_free(&ctx->hdl);
+		goto done;
+	}
+
+	ctx->fh.ctrl_handler = &ctx->hdl;
+	v4l2_ctrl_handler_setup(&ctx->hdl);
+
+	/* Configure default parameters. */
+	memset(&format, 0, sizeof(format));
+	fdp1_set_format(ctx, &format, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(fdp1->m2m_dev, ctx, &queue_init);
+
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		ret = PTR_ERR(ctx->fh.m2m_ctx);
+
+		v4l2_ctrl_handler_free(&ctx->hdl);
+		kfree(ctx);
+		goto done;
+	}
+
+	/* Perform any power management required */
+	pm_runtime_get_sync(fdp1->dev);
+
+	v4l2_fh_add(&ctx->fh);
+
+	dprintk(fdp1, "Created instance: %p, m2m_ctx: %p\n",
+		ctx, ctx->fh.m2m_ctx);
+
+done:
+	mutex_unlock(&fdp1->dev_mutex);
+	return ret;
+}
+
+static int fdp1_release(struct file *file)
+{
+	struct fdp1_dev *fdp1 = video_drvdata(file);
+	struct fdp1_ctx *ctx = fh_to_ctx(file->private_data);
+
+	dprintk(fdp1, "Releasing instance %p\n", ctx);
+
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_ctrl_handler_free(&ctx->hdl);
+	mutex_lock(&fdp1->dev_mutex);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+	mutex_unlock(&fdp1->dev_mutex);
+	kfree(ctx);
+
+	pm_runtime_put(fdp1->dev);
+
+	return 0;
+}
+
+static const struct v4l2_file_operations fdp1_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fdp1_open,
+	.release	= fdp1_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static const struct video_device fdp1_videodev = {
+	.name		= DRIVER_NAME,
+	.vfl_dir	= VFL_DIR_M2M,
+	.fops		= &fdp1_fops,
+	.device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
+	.ioctl_ops	= &fdp1_ioctl_ops,
+	.minor		= -1,
+	.release	= video_device_release_empty,
+};
+
+static const struct v4l2_m2m_ops m2m_ops = {
+	.device_run	= fdp1_m2m_device_run,
+	.job_ready	= fdp1_m2m_job_ready,
+	.job_abort	= fdp1_m2m_job_abort,
+};
+
+static irqreturn_t fdp1_irq_handler(int irq, void *dev_id)
+{
+	struct fdp1_dev *fdp1 = dev_id;
+	u32 int_status;
+	u32 ctl_status;
+	u32 vint_cnt;
+	u32 cycles;
+
+	int_status = fdp1_read(fdp1, FD1_CTL_IRQSTA);
+	cycles = fdp1_read(fdp1, FD1_CTL_VCYCLE_STAT);
+	ctl_status = fdp1_read(fdp1, FD1_CTL_STATUS);
+	vint_cnt = (ctl_status & FD1_CTL_STATUS_VINT_CNT_MASK) >>
+			FD1_CTL_STATUS_VINT_CNT_SHIFT;
+
+	/* Clear interrupts */
+	fdp1_write(fdp1, ~(int_status) & FD1_CTL_IRQ_MASK, FD1_CTL_IRQSTA);
+
+	if (debug >= 2) {
+		dprintk(fdp1, "IRQ: 0x%x %s%s%s\n", int_status,
+			int_status & FD1_CTL_IRQ_VERE ? "[Error]" : "[!E]",
+			int_status & FD1_CTL_IRQ_VINTE ? "[VSync]" : "[!V]",
+			int_status & FD1_CTL_IRQ_FREE ? "[FrameEnd]" : "[!F]");
+
+		dprintk(fdp1, "CycleStatus = %d (%dms)\n",
+			cycles, cycles/(fdp1->clk_rate/1000));
+
+		dprintk(fdp1,
+			"Control Status = 0x%08x : VINT_CNT = %d %s:%s:%s:%s\n",
+			ctl_status, vint_cnt,
+			ctl_status & FD1_CTL_STATUS_SGREGSET ? "RegSet" : "",
+			ctl_status & FD1_CTL_STATUS_SGVERR ? "Vsync Error" : "",
+			ctl_status & FD1_CTL_STATUS_SGFREND ? "FrameEnd" : "",
+			ctl_status & FD1_CTL_STATUS_BSY ? "Busy" : "");
+		dprintk(fdp1, "***********************************\n");
+	}
+
+	/* Spurious interrupt */
+	if (!(FD1_CTL_IRQ_MASK & int_status))
+		return IRQ_NONE;
+
+	/* Work completed, release the frame */
+	if (FD1_CTL_IRQ_VERE & int_status)
+		device_frame_end(fdp1, VB2_BUF_STATE_ERROR);
+	else if (FD1_CTL_IRQ_FREE & int_status)
+		device_frame_end(fdp1, VB2_BUF_STATE_DONE);
+
+	return IRQ_HANDLED;
+}
+
+static int fdp1_probe(struct platform_device *pdev)
+{
+	struct fdp1_dev *fdp1;
+	struct video_device *vfd;
+	struct device_node *fcp_node;
+	struct resource *res;
+	struct clk *clk;
+	unsigned int i;
+
+	int ret;
+	int hw_version;
+
+	fdp1 = devm_kzalloc(&pdev->dev, sizeof(*fdp1), GFP_KERNEL);
+	if (!fdp1)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&fdp1->free_job_list);
+	INIT_LIST_HEAD(&fdp1->queued_job_list);
+	INIT_LIST_HEAD(&fdp1->hw_job_list);
+
+	/* Initialise the jobs on the free list */
+	for (i = 0; i < ARRAY_SIZE(fdp1->jobs); i++)
+		list_add(&fdp1->jobs[i].list, &fdp1->free_job_list);
+
+	mutex_init(&fdp1->dev_mutex);
+
+	spin_lock_init(&fdp1->irqlock);
+	spin_lock_init(&fdp1->device_process_lock);
+	fdp1->dev = &pdev->dev;
+	platform_set_drvdata(pdev, fdp1);
+
+	/* Memory-mapped registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	fdp1->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fdp1->regs))
+		return PTR_ERR(fdp1->regs);
+
+	/* Interrupt service routine registration */
+	fdp1->irq = ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "cannot find IRQ\n");
+		return ret;
+	}
+
+	ret = devm_request_irq(&pdev->dev, fdp1->irq, fdp1_irq_handler, 0,
+			       dev_name(&pdev->dev), fdp1);
+	if (ret) {
+		dev_err(&pdev->dev, "cannot claim IRQ %d\n", fdp1->irq);
+		return ret;
+	}
+
+	/* FCP */
+	fcp_node = of_parse_phandle(pdev->dev.of_node, "renesas,fcp", 0);
+	if (fcp_node) {
+		fdp1->fcp = rcar_fcp_get(fcp_node);
+		of_node_put(fcp_node);
+		if (IS_ERR(fdp1->fcp)) {
+			dev_err(&pdev->dev, "FCP not found (%ld)\n",
+				PTR_ERR(fdp1->fcp));
+			return PTR_ERR(fdp1->fcp);
+		}
+	}
+
+	/* Determine our clock rate */
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	fdp1->clk_rate = clk_get_rate(clk);
+	clk_put(clk);
+
+	/* V4L2 device registration */
+	ret = v4l2_device_register(&pdev->dev, &fdp1->v4l2_dev);
+	if (ret) {
+		v4l2_err(&fdp1->v4l2_dev, "Failed to register video device\n");
+		return ret;
+	}
+
+	/* M2M registration */
+	fdp1->m2m_dev = v4l2_m2m_init(&m2m_ops);
+	if (IS_ERR(fdp1->m2m_dev)) {
+		v4l2_err(&fdp1->v4l2_dev, "Failed to init mem2mem device\n");
+		ret = PTR_ERR(fdp1->m2m_dev);
+		goto unreg_dev;
+	}
+
+	/* Video registration */
+	fdp1->vfd = fdp1_videodev;
+	vfd = &fdp1->vfd;
+	vfd->lock = &fdp1->dev_mutex;
+	vfd->v4l2_dev = &fdp1->v4l2_dev;
+	video_set_drvdata(vfd, fdp1);
+	strlcpy(vfd->name, fdp1_videodev.name, sizeof(vfd->name));
+
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		v4l2_err(&fdp1->v4l2_dev, "Failed to register video device\n");
+		goto release_m2m;
+	}
+
+	v4l2_info(&fdp1->v4l2_dev,
+			"Device registered as /dev/video%d\n", vfd->num);
+
+	/* Power up the cells to read HW */
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_sync(fdp1->dev);
+
+	hw_version = fdp1_read(fdp1, FD1_IP_INTDATA);
+	switch (hw_version) {
+	case FD1_IP_H3:
+		dprintk(fdp1, "FDP1 Version R-Car H3\n");
+		break;
+	case FD1_IP_M3W:
+		dprintk(fdp1, "FDP1 Version R-Car M3-W\n");
+		break;
+	default:
+		dev_err(fdp1->dev, "FDP1 Unidentifiable (0x%08x)\n",
+				hw_version);
+	}
+
+	/* Allow the hw to sleep until an open call puts it to use */
+	pm_runtime_put(fdp1->dev);
+
+	return 0;
+
+release_m2m:
+	v4l2_m2m_release(fdp1->m2m_dev);
+
+unreg_dev:
+	v4l2_device_unregister(&fdp1->v4l2_dev);
+
+	return ret;
+}
+
+static int fdp1_remove(struct platform_device *pdev)
+{
+	struct fdp1_dev *fdp1 = platform_get_drvdata(pdev);
+
+	v4l2_m2m_release(fdp1->m2m_dev);
+	video_unregister_device(&fdp1->vfd);
+	v4l2_device_unregister(&fdp1->v4l2_dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static int __maybe_unused fdp1_pm_runtime_suspend(struct device *dev)
+{
+	struct fdp1_dev *fdp1 = dev_get_drvdata(dev);
+
+	rcar_fcp_disable(fdp1->fcp);
+
+	return 0;
+}
+
+static int __maybe_unused fdp1_pm_runtime_resume(struct device *dev)
+{
+	struct fdp1_dev *fdp1 = dev_get_drvdata(dev);
+
+	/* Program in the static LUTs */
+	fdp1_set_lut(fdp1);
+
+	return rcar_fcp_enable(fdp1->fcp);
+}
+
+static const struct dev_pm_ops fdp1_pm_ops = {
+	SET_RUNTIME_PM_OPS(fdp1_pm_runtime_suspend,
+			   fdp1_pm_runtime_resume,
+			   NULL)
+};
+
+static const struct of_device_id fdp1_dt_ids[] = {
+	{ .compatible = "renesas,fdp1" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, fdp1_dt_ids);
+
+static struct platform_driver fdp1_pdrv = {
+	.probe		= fdp1_probe,
+	.remove		= fdp1_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.of_match_table = fdp1_dt_ids,
+		.pm	= &fdp1_pm_ops,
+	},
+};
+
+module_platform_driver(fdp1_pdrv);
+
+MODULE_DESCRIPTION("Renesas R-Car Fine Display Processor Driver");
+MODULE_AUTHOR("Kieran Bingham <kieran@bingham.xyz>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-jpeg/jpeg-hw-exynos4.c	2017-02-12 16:03:20.000000000 -0500
@@ -178,20 +178,12 @@ void exynos4_jpeg_set_interrupt(void __i
 
 unsigned int exynos4_jpeg_get_int_status(void __iomem *base)
 {
-	unsigned int	int_status;
-
-	int_status = readl(base + EXYNOS4_INT_STATUS_REG);
-
-	return int_status;
+	return readl(base + EXYNOS4_INT_STATUS_REG);
 }
 
 unsigned int exynos4_jpeg_get_fifo_status(void __iomem *base)
 {
-	unsigned int fifo_status;
-
-	fifo_status = readl(base + EXYNOS4_FIFO_STATUS_REG);
-
-	return fifo_status;
+	return readl(base + EXYNOS4_FIFO_STATUS_REG);
 }
 
 void exynos4_jpeg_set_huf_table_enable(void __iomem *base, int value)
@@ -296,10 +288,7 @@ void exynos4_jpeg_set_encode_hoff_cnt(vo
 
 unsigned int exynos4_jpeg_get_stream_size(void __iomem *base)
 {
-	unsigned int size;
-
-	size = readl(base + EXYNOS4_BITSTREAM_SIZE_REG);
-	return size;
+	return readl(base + EXYNOS4_BITSTREAM_SIZE_REG);
 }
 
 void exynos4_jpeg_set_dec_bitstream_size(void __iomem *base, unsigned int size)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/regs-mfc.h linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/regs-mfc.h
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/regs-mfc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/regs-mfc.h	2017-02-12 16:03:20.000000000 -0500
@@ -393,6 +393,9 @@
 #define S5P_FIMV_REG_CLEAR_COUNT		0
 
 /* Error handling defines */
+#define S5P_FIMV_ERR_NO_VALID_SEQ_HDR		67
+#define S5P_FIMV_ERR_INCOMPLETE_FRAME		124
+#define S5P_FIMV_ERR_TIMEOUT			140
 #define S5P_FIMV_ERR_WARNINGS_START		145
 #define S5P_FIMV_ERR_DEC_MASK			0xFFFF
 #define S5P_FIMV_ERR_DEC_SHIFT			0
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v6.h linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v6.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v6.h	2017-02-12 16:03:20.000000000 -0500
@@ -386,7 +386,8 @@
 			((w) * 144 + 8192 * (h) + 49216 + 1048576)
 #define S5P_FIMV_SCRATCH_BUF_SIZE_VC1_DEC_V6(w, h) \
 						(2096 * ((w) + (h) + 1))
-#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h)	((w) * 400)
+#define S5P_FIMV_SCRATCH_BUF_SIZE_H263_DEC_V6(w, h)	\
+			S5P_FIMV_SCRATCH_BUF_SIZE_MPEG4_DEC_V6(w, h)
 #define S5P_FIMV_SCRATCH_BUF_SIZE_VP8_DEC_V6(w, h) \
 			((w) * 32 + (h) * 128 + (((w) + 1) / 2) * 64 + 2112)
 #define S5P_FIMV_SCRATCH_BUF_SIZE_H264_ENC_V6(w, h) \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v8.h linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v8.h
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v8.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/regs-mfc-v8.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,7 +90,7 @@
 #define S5P_FIMV_E_H264_OPTIONS_V8		0xfb54
 
 /* MFCv8 Context buffer sizes */
-#define MFC_CTX_BUF_SIZE_V8		(30 * SZ_1K)	/*  30KB */
+#define MFC_CTX_BUF_SIZE_V8		(36 * SZ_1K)	/*  36KB */
 #define MFC_H264_DEC_CTX_BUF_SIZE_V8	(2 * SZ_1M)	/*  2MB */
 #define MFC_OTHER_DEC_CTX_BUF_SIZE_V8	(20 * SZ_1K)	/*  20KB */
 #define MFC_H264_ENC_CTX_BUF_SIZE_V8	(100 * SZ_1K)	/* 100KB */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c	2016-12-11 17:48:24.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc.c	2017-02-12 17:36:08.000000000 -0500
@@ -641,8 +641,11 @@ static irqreturn_t s5p_mfc_irq(int irq,
 	case S5P_MFC_R2H_CMD_ERR_RET:
 		/* An error has occurred */
 		if (ctx->state == MFCINST_RUNNING &&
-			s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
-				dev->warn_start)
+			(s5p_mfc_hw_call(dev->mfc_ops, err_dec, err) >=
+				dev->warn_start ||
+				err == S5P_FIMV_ERR_NO_VALID_SEQ_HDR ||
+				err == S5P_FIMV_ERR_INCOMPLETE_FRAME ||
+				err == S5P_FIMV_ERR_TIMEOUT))
 			s5p_mfc_handle_frame(ctx, reason, err);
 		else
 			s5p_mfc_handle_error(dev, ctx, reason, err);
@@ -848,6 +851,11 @@ static int s5p_mfc_open(struct file *fil
 		ret = -ENOENT;
 		goto err_queue_init;
 	}
+	/*
+	 * We'll do mostly sequential access, so sacrifice TLB efficiency for
+	 * faster allocation.
+	 */
+	q->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	ret = vb2_queue_init(q);
@@ -878,6 +886,12 @@ static int s5p_mfc_open(struct file *fil
 	 * will keep the value of bytesused intact.
 	 */
 	q->allow_zero_bytesused = 1;
+
+	/*
+	 * We'll do mostly sequential access, so sacrifice TLB efficiency for
+	 * faster allocation.
+	 */
+	q->dma_attrs = DMA_ATTR_ALLOC_SINGLE_PAGES;
 	q->mem_ops = &vb2_dma_contig_memops;
 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
 	ret = vb2_queue_init(q);
@@ -926,10 +940,11 @@ static int s5p_mfc_release(struct file *
 	mfc_debug_enter();
 	if (dev)
 		mutex_lock(&dev->mfc_mutex);
-	s5p_mfc_clock_on();
 	vb2_queue_release(&ctx->vq_src);
 	vb2_queue_release(&ctx->vq_dst);
 	if (dev) {
+		s5p_mfc_clock_on();
+
 		/* Mark context as idle */
 		clear_work_bit_irqsave(ctx);
 		/*
@@ -948,12 +963,14 @@ static int s5p_mfc_release(struct file *
 			mfc_debug(2, "Last instance\n");
 			s5p_mfc_deinit_hw(dev);
 			del_timer_sync(&dev->watchdog_timer);
+			s5p_mfc_clock_off();
 			if (s5p_mfc_power_off() < 0)
 				mfc_err("Power off failed\n");
+		} else {
+			mfc_debug(2, "Shutting down clock\n");
+			s5p_mfc_clock_off();
 		}
 	}
-	mfc_debug(2, "Shutting down clock\n");
-	s5p_mfc_clock_off();
 	if (dev)
 		dev->ctx[ctx->num] = NULL;
 	s5p_mfc_dec_ctrls_delete(ctx);
@@ -1082,6 +1099,7 @@ static struct device *s5p_mfc_alloc_memd
 							 idx);
 		if (ret == 0)
 			return child;
+		device_del(child);
 	}
 
 	put_device(child);
@@ -1387,31 +1405,9 @@ static int s5p_mfc_resume(struct device
 }
 #endif
 
-#ifdef CONFIG_PM
-static int s5p_mfc_runtime_suspend(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
-
-	atomic_set(&m_dev->pm.power, 0);
-	return 0;
-}
-
-static int s5p_mfc_runtime_resume(struct device *dev)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct s5p_mfc_dev *m_dev = platform_get_drvdata(pdev);
-
-	atomic_set(&m_dev->pm.power, 1);
-	return 0;
-}
-#endif
-
 /* Power management */
 static const struct dev_pm_ops s5p_mfc_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(s5p_mfc_suspend, s5p_mfc_resume)
-	SET_RUNTIME_PM_OPS(s5p_mfc_runtime_suspend, s5p_mfc_runtime_resume,
-			   NULL)
 };
 
 static struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
@@ -1438,6 +1434,9 @@ static struct s5p_mfc_variant mfc_drvdat
 	.buf_size	= &buf_size_v5,
 	.buf_align	= &mfc_buf_align_v5,
 	.fw_name[0]	= "/*(DEBLOBBED)*/",
+	.clk_names	= {"mfc", "sclk_mfc"},
+	.num_clocks	= 2,
+	.use_clock_gating = true,
 };
 
 static struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
@@ -1470,6 +1469,8 @@ static struct s5p_mfc_variant mfc_drvdat
 	 * for init buffer command
 	 */
 	.fw_name[1]     = "/*(DEBLOBBED)*/",
+	.clk_names	= {"mfc"},
+	.num_clocks	= 1,
 };
 
 static struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
@@ -1497,6 +1498,8 @@ static struct s5p_mfc_variant mfc_drvdat
 	.buf_size	= &buf_size_v7,
 	.buf_align	= &mfc_buf_align_v7,
 	.fw_name[0]     = "/*(DEBLOBBED)*/",
+	.clk_names	= {"mfc", "sclk_mfc"},
+	.num_clocks	= 2,
 };
 
 static struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
@@ -1524,6 +1527,19 @@ static struct s5p_mfc_variant mfc_drvdat
 	.buf_size	= &buf_size_v8,
 	.buf_align	= &mfc_buf_align_v8,
 	.fw_name[0]     = "/*(DEBLOBBED)*/",
+	.clk_names	= {"mfc"},
+	.num_clocks	= 1,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v8_5433 = {
+	.version	= MFC_VERSION_V8,
+	.version_bit	= MFC_V8_BIT,
+	.port_num	= MFC_NUM_PORTS_V8,
+	.buf_size	= &buf_size_v8,
+	.buf_align	= &mfc_buf_align_v8,
+	.fw_name[0]     = "/*(DEBLOBBED)*/",
+	.clk_names	= {"pclk", "aclk", "aclk_xiu"},
+	.num_clocks	= 3,
 };
 
 static const struct of_device_id exynos_mfc_match[] = {
@@ -1539,6 +1555,9 @@ static const struct of_device_id exynos_
 	}, {
 		.compatible = "samsung,mfc-v8",
 		.data = &mfc_drvdata_v8,
+	}, {
+		.compatible = "samsung,exynos5433-mfc",
+		.data = &mfc_drvdata_v8_5433,
 	},
 	{},
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -104,6 +104,8 @@ static inline dma_addr_t s5p_mfc_mem_coo
 #define S5P_MFC_R2H_CMD_ENC_BUFFER_FUL_RET	16
 #define S5P_MFC_R2H_CMD_ERR_RET			32
 
+#define MFC_MAX_CLOCKS		4
+
 #define mfc_read(dev, offset)		readl(dev->regs_base + (offset))
 #define mfc_write(dev, data, offset)	writel((data), dev->regs_base + \
 								(offset))
@@ -197,9 +199,12 @@ struct s5p_mfc_buf {
  * struct s5p_mfc_pm - power management data structure
  */
 struct s5p_mfc_pm {
-	struct clk	*clock;
 	struct clk	*clock_gate;
-	atomic_t	power;
+	const char	**clk_names;
+	struct clk	*clocks[MFC_MAX_CLOCKS];
+	int		num_clocks;
+	bool		use_clock_gating;
+
 	struct device	*device;
 };
 
@@ -235,6 +240,9 @@ struct s5p_mfc_variant {
 	struct s5p_mfc_buf_size *buf_size;
 	struct s5p_mfc_buf_align *buf_align;
 	char	*fw_name[MFC_FW_MAX_VERSIONS];
+	const char	*clk_names[MFC_MAX_CLOCKS];
+	int		num_clocks;
+	bool		use_clock_gating;
 };
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_debug.h	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,12 @@ extern int mfc_debug_level;
 		       __func__, __LINE__, ##args);	\
 	} while (0)
 
+#define mfc_err_limited(fmt, args...)			\
+	do {						\
+		printk_ratelimited(KERN_ERR "%s:%d: " fmt,	\
+		       __func__, __LINE__, ##args);	\
+	} while (0)
+
 #define mfc_info(fmt, args...)				\
 	do {						\
 		printk(KERN_INFO "%s:%d: " fmt,		\
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c	2017-02-12 16:03:20.000000000 -0500
@@ -642,7 +642,7 @@ static int vidioc_dqbuf(struct file *fil
 	int ret;
 
 	if (ctx->state == MFCINST_ERROR) {
-		mfc_err("Call on DQBUF after unrecoverable error\n");
+		mfc_err_limited("Call on DQBUF after unrecoverable error\n");
 		return -EIO;
 	}
 
@@ -793,18 +793,17 @@ static int vidioc_g_crop(struct file *fi
 		cr->c.top = top;
 		cr->c.width = ctx->img_width - left - right;
 		cr->c.height = ctx->img_height - top - bottom;
-		mfc_debug(2, "Cropping info [h264]: l=%d t=%d "
-			"w=%d h=%d (r=%d b=%d fw=%d fh=%d\n", left, top,
-			cr->c.width, cr->c.height, right, bottom,
-			ctx->buf_width, ctx->buf_height);
+		mfc_debug(2, "Cropping info [h264]: l=%d t=%d w=%d h=%d (r=%d b=%d fw=%d fh=%d\n",
+			  left, top, cr->c.width, cr->c.height, right, bottom,
+			  ctx->buf_width, ctx->buf_height);
 	} else {
 		cr->c.left = 0;
 		cr->c.top = 0;
 		cr->c.width = ctx->img_width;
 		cr->c.height = ctx->img_height;
-		mfc_debug(2, "Cropping info: w=%d h=%d fw=%d "
-			"fh=%d\n", cr->c.width,	cr->c.height, ctx->buf_width,
-							ctx->buf_height);
+		mfc_debug(2, "Cropping info: w=%d h=%d fw=%d fh=%d\n",
+			  cr->c.width,	cr->c.height, ctx->buf_width,
+			  ctx->buf_height);
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1268,7 +1268,7 @@ static int vidioc_dqbuf(struct file *fil
 	int ret;
 
 	if (ctx->state == MFCINST_ERROR) {
-		mfc_err("Call on DQBUF after unrecoverable error\n");
+		mfc_err_limited("Call on DQBUF after unrecoverable error\n");
 		return -EIO;
 	}
 	if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr.c	2017-02-12 16:03:20.000000000 -0500
@@ -45,13 +45,13 @@ int s5p_mfc_alloc_priv_buf(struct device
 	b->virt = dma_alloc_coherent(dev, b->size, &b->dma, GFP_KERNEL);
 
 	if (!b->virt) {
-		mfc_err("Allocating private buffer failed\n");
+		mfc_err("Allocating private buffer of size %zu failed\n",
+			b->size);
 		return -ENOMEM;
 	}
 
 	if (b->dma < base) {
-		mfc_err("Invaling memory configuration!\n");
-		mfc_err("Allocated buffer (%pad) is lower than memory base address (%pad)\n",
+		mfc_err("Invalid memory configuration - buffer (%pad) is below base memory address(%pad)\n",
 			&b->dma, &base);
 		dma_free_coherent(dev, b->size, b->virt, b->dma);
 		return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c	2017-02-12 16:03:20.000000000 -0500
@@ -1293,14 +1293,11 @@ static int s5p_mfc_run_init_dec_buffers(
 	 * First set the output frame buffers
 	 */
 	if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
-		mfc_err("It seems that not all destionation buffers were "
-			"mmaped\nMFC requires that all destination are mmaped "
-			"before starting processing\n");
+		mfc_err("It seems that not all destionation buffers were mmaped\nMFC requires that all destination are mmaped before starting processing\n");
 		return -EAGAIN;
 	}
 	if (list_empty(&ctx->src_queue)) {
-		mfc_err("Header has been deallocated in the middle of"
-			" initialization\n");
+		mfc_err("Header has been deallocated in the middle of initialization\n");
 		return -EIO;
 	}
 	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
--- linux-libre-4.9-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,129 +18,101 @@
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_pm.h"
 
-#define MFC_GATE_CLK_NAME	"mfc"
-#define MFC_SCLK_NAME		"sclk_mfc"
-#define MFC_SCLK_RATE		(200 * 1000000)
-
-#define CLK_DEBUG
-
 static struct s5p_mfc_pm *pm;
 static struct s5p_mfc_dev *p_dev;
-
-#ifdef CLK_DEBUG
 static atomic_t clk_ref;
-#endif
 
 int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
 {
-	int ret = 0;
+	int i;
 
 	pm = &dev->pm;
 	p_dev = dev;
-	pm->clock_gate = clk_get(&dev->plat_dev->dev, MFC_GATE_CLK_NAME);
-	if (IS_ERR(pm->clock_gate)) {
-		mfc_err("Failed to get clock-gating control\n");
-		ret = PTR_ERR(pm->clock_gate);
-		goto err_g_ip_clk;
-	}
 
-	ret = clk_prepare(pm->clock_gate);
-	if (ret) {
-		mfc_err("Failed to prepare clock-gating control\n");
-		goto err_p_ip_clk;
-	}
+	pm->num_clocks = dev->variant->num_clocks;
+	pm->clk_names = dev->variant->clk_names;
+	pm->device = &dev->plat_dev->dev;
+	pm->clock_gate = NULL;
 
-	if (dev->variant->version != MFC_VERSION_V6) {
-		pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME);
-		if (IS_ERR(pm->clock)) {
-			mfc_info("Failed to get MFC special clock control\n");
-			pm->clock = NULL;
-		} else {
-			clk_set_rate(pm->clock, MFC_SCLK_RATE);
-			ret = clk_prepare_enable(pm->clock);
-			if (ret) {
-				mfc_err("Failed to enable MFC special clock\n");
-				goto err_s_clk;
-			}
+	/* clock control */
+	for (i = 0; i < pm->num_clocks; i++) {
+		pm->clocks[i] = devm_clk_get(pm->device, pm->clk_names[i]);
+		if (IS_ERR(pm->clocks[i])) {
+			mfc_err("Failed to get clock: %s\n",
+				pm->clk_names[i]);
+			return PTR_ERR(pm->clocks[i]);
 		}
 	}
 
-	atomic_set(&pm->power, 0);
-#ifdef CONFIG_PM
-	pm->device = &dev->plat_dev->dev;
+	if (dev->variant->use_clock_gating)
+		pm->clock_gate = pm->clocks[0];
+
 	pm_runtime_enable(pm->device);
-#endif
-#ifdef CLK_DEBUG
 	atomic_set(&clk_ref, 0);
-#endif
 	return 0;
-
-err_s_clk:
-	clk_put(pm->clock);
-	pm->clock = NULL;
-err_p_ip_clk:
-	clk_put(pm->clock_gate);
-	pm->clock_gate = NULL;
-err_g_ip_clk:
-	return ret;
 }
 
 void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
 {
-	if (dev->variant->version != MFC_VERSION_V6 &&
-	    pm->clock) {
-		clk_disable_unprepare(pm->clock);
-		clk_put(pm->clock);
-		pm->clock = NULL;
-	}
-	clk_unprepare(pm->clock_gate);
-	clk_put(pm->clock_gate);
-	pm->clock_gate = NULL;
-#ifdef CONFIG_PM
 	pm_runtime_disable(pm->device);
-#endif
 }
 
 int s5p_mfc_clock_on(void)
 {
-	int ret = 0;
-#ifdef CLK_DEBUG
 	atomic_inc(&clk_ref);
 	mfc_debug(3, "+ %d\n", atomic_read(&clk_ref));
-#endif
-	if (!IS_ERR_OR_NULL(pm->clock_gate))
-		ret = clk_enable(pm->clock_gate);
-	return ret;
+
+	return clk_enable(pm->clock_gate);
 }
 
 void s5p_mfc_clock_off(void)
 {
-#ifdef CLK_DEBUG
 	atomic_dec(&clk_ref);
 	mfc_debug(3, "- %d\n", atomic_read(&clk_ref));
-#endif
-	if (!IS_ERR_OR_NULL(pm->clock_gate))
-		clk_disable(pm->clock_gate);
+
+	clk_disable(pm->clock_gate);
 }
 
 int s5p_mfc_power_on(void)
 {
-#ifdef CONFIG_PM
-	return pm_runtime_get_sync(pm->device);
-#else
-	atomic_set(&pm->power, 1);
+	int i, ret = 0;
+
+	ret = pm_runtime_get_sync(pm->device);
+	if (ret < 0)
+		return ret;
+
+	/* clock control */
+	for (i = 0; i < pm->num_clocks; i++) {
+		ret = clk_prepare_enable(pm->clocks[i]);
+		if (ret < 0) {
+			mfc_err("clock prepare failed for clock: %s\n",
+				pm->clk_names[i]);
+			i++;
+			goto err;
+		}
+	}
+
+	/* prepare for software clock gating */
+	clk_disable(pm->clock_gate);
+
 	return 0;
-#endif
+err:
+	while (--i > 0)
+		clk_disable_unprepare(pm->clocks[i]);
+	pm_runtime_put(pm->device);
+	return ret;
 }
 
 int s5p_mfc_power_off(void)
 {
-#ifdef CONFIG_PM
+	int i;
+
+	/* finish software clock gating */
+	clk_enable(pm->clock_gate);
+
+	for (i = 0; i < pm->num_clocks; i++)
+		clk_disable_unprepare(pm->clocks[i]);
+
 	return pm_runtime_put_sync(pm->device);
-#else
-	atomic_set(&pm->power, 0);
-	return 0;
-#endif
 }
 
-
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/sti/bdisp/bdisp-v4l2.c linux-libre-4.10-rc8-gnu/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
--- linux-libre-4.9-gnu/drivers/media/platform/sti/bdisp/bdisp-v4l2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/sti/bdisp/bdisp-v4l2.c	2017-02-12 16:03:20.000000000 -0500
@@ -1337,6 +1337,7 @@ static int bdisp_probe(struct platform_d
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
 		dev_err(dev, "failed to get IRQ resource\n");
+		ret = -EINVAL;
 		goto err_clk;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c linux-libre-4.10-rc8-gnu/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
--- linux-libre-4.9-gnu/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c	2016-12-11 17:46:24.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c	2017-02-12 17:32:46.000000000 -0500
@@ -112,8 +112,7 @@ static void channel_swdemux_tsklet(unsig
 	buf = (u8 *) channel->back_buffer_aligned;
 
 	dev_dbg(fei->dev,
-		"chan=%d channel=%p num_packets = %d, buf = %p, pos = 0x%x\n\t"
-		"rp=0x%lx, wp=0x%lx\n",
+		"chan=%d channel=%p num_packets = %d, buf = %p, pos = 0x%x\n\trp=0x%lx, wp=0x%lx\n",
 		channel->tsin_id, channel, num_packets, buf, pos, rp, wp);
 
 	for (n = 0; n < num_packets; n++) {
@@ -789,8 +788,7 @@ static int c8sectpfe_probe(struct platfo
 		/* sanity check value */
 		if (tsin->tsin_id > fei->hw_stats.num_ib) {
 			dev_err(&pdev->dev,
-				"tsin-num %d specified greater than number\n\t"
-				"of input block hw in SoC! (%d)",
+				"tsin-num %d specified greater than number\n\tof input block hw in SoC! (%d)",
 				tsin->tsin_id, fei->hw_stats.num_ib);
 			ret = -EINVAL;
 			goto err_clk_disable;
@@ -815,6 +813,7 @@ static int c8sectpfe_probe(struct platfo
 		i2c_bus = of_parse_phandle(child, "i2c-bus", 0);
 		if (!i2c_bus) {
 			dev_err(&pdev->dev, "No i2c-bus found\n");
+			ret = -ENODEV;
 			goto err_clk_disable;
 		}
 		tsin->i2c_adapter =
@@ -822,6 +821,7 @@ static int c8sectpfe_probe(struct platfo
 		if (!tsin->i2c_adapter) {
 			dev_err(&pdev->dev, "No i2c adapter found\n");
 			of_node_put(i2c_bus);
+			ret = -ENODEV;
 			goto err_clk_disable;
 		}
 		of_node_put(i2c_bus);
@@ -855,8 +855,7 @@ static int c8sectpfe_probe(struct platfo
 		tsin->demux_mapping = index;
 
 		dev_dbg(fei->dev,
-			"channel=%p n=%d tsin_num=%d, invert-ts-clk=%d\n\t"
-			"serial-not-parallel=%d pkt-clk-valid=%d dvb-card=%d\n",
+			"channel=%p n=%d tsin_num=%d, invert-ts-clk=%d\n\tserial-not-parallel=%d pkt-clk-valid=%d dvb-card=%d\n",
 			fei->channel_data[index], index,
 			tsin->tsin_id, tsin->invert_ts_clk,
 			tsin->serial_not_parallel, tsin->async_not_sync,
@@ -888,8 +887,7 @@ static int c8sectpfe_probe(struct platfo
 	return 0;
 
 err_clk_disable:
-	/* TODO uncomment when upstream has taken a reference on this clk */
-	/*clk_disable_unprepare(fei->c8sectpfeclk);*/
+	clk_disable_unprepare(fei->c8sectpfeclk);
 	return ret;
 }
 
@@ -924,11 +922,8 @@ static int c8sectpfe_remove(struct platf
 	if (readl(fei->io + SYS_OTHER_CLKEN))
 		writel(0, fei->io + SYS_OTHER_CLKEN);
 
-	/* TODO uncomment when upstream has taken a reference on this clk */
-	/*
 	if (fei->c8sectpfeclk)
 		clk_disable_unprepare(fei->c8sectpfeclk);
-	*/
 
 	return 0;
 }
@@ -1045,8 +1040,8 @@ static void load_imem_segment(struct c8s
 	 */
 
 	dev_dbg(fei->dev,
-		"Loading IMEM segment %d 0x%08x\n\t"
-		" (0x%x bytes) -> 0x%p (0x%x bytes)\n", seg_num,
+		"Loading IMEM segment %d 0x%08x\n\t (0x%x bytes) -> 0x%p (0x%x bytes)\n",
+seg_num,
 		phdr->p_paddr, phdr->p_filesz,
 		dest, phdr->p_memsz + phdr->p_memsz / 3);
 
@@ -1075,8 +1070,7 @@ static void load_dmem_segment(struct c8s
 	 */
 
 	dev_dbg(fei->dev,
-		"Loading DMEM segment %d 0x%08x\n\t"
-		"(0x%x bytes) -> 0x%p (0x%x bytes)\n",
+		"Loading DMEM segment %d 0x%08x\n\t(0x%x bytes) -> 0x%p (0x%x bytes)\n",
 		seg_num, phdr->p_paddr, phdr->p_filesz,
 		dst, phdr->p_memsz);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/sti/hva/hva-hw.c linux-libre-4.10-rc8-gnu/drivers/media/platform/sti/hva/hva-hw.c
--- linux-libre-4.9-gnu/drivers/media/platform/sti/hva/hva-hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/sti/hva/hva-hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -245,7 +245,7 @@ static irqreturn_t hva_hw_err_irq_thread
 		ctx->hw_err = true;
 	}
 
-	if (hva->lmi_err_reg) {
+	if (hva->emi_err_reg) {
 		dev_err(dev, "%s     external memory interface error: 0x%08x\n",
 			ctx->name, hva->emi_err_reg);
 		ctx->hw_err = true;
@@ -305,16 +305,16 @@ int hva_hw_probe(struct platform_device
 	/* get memory for registers */
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	hva->regs = devm_ioremap_resource(dev, regs);
-	if (IS_ERR_OR_NULL(hva->regs)) {
+	if (IS_ERR(hva->regs)) {
 		dev_err(dev, "%s     failed to get regs\n", HVA_PREFIX);
 		return PTR_ERR(hva->regs);
 	}
 
 	/* get memory for esram */
 	esram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (IS_ERR_OR_NULL(esram)) {
+	if (!esram) {
 		dev_err(dev, "%s     failed to get esram\n", HVA_PREFIX);
-		return PTR_ERR(esram);
+		return -ENODEV;
 	}
 	hva->esram_addr = esram->start;
 	hva->esram_size = resource_size(esram);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/cal.c linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/cal.c
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/cal.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/cal.c	2017-02-12 16:03:20.000000000 -0500
@@ -483,11 +483,7 @@ static void cal_get_hwinfo(struct cal_de
 
 static inline int cal_runtime_get(struct cal_dev *dev)
 {
-	int r;
-
-	r = pm_runtime_get_sync(&dev->pdev->dev);
-
-	return r;
+	return pm_runtime_get_sync(&dev->pdev->dev);
 }
 
 static inline void cal_runtime_put(struct cal_dev *dev)
@@ -1749,13 +1745,13 @@ static int of_cal_create_instance(struct
 	}
 
 cleanup_exit:
-	if (!remote_ep)
+	if (remote_ep)
 		of_node_put(remote_ep);
-	if (!sensor_node)
+	if (sensor_node)
 		of_node_put(sensor_node);
-	if (!ep_node)
+	if (ep_node)
 		of_node_put(ep_node);
-	if (!port)
+	if (port)
 		of_node_put(port);
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/csc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/csc.c
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/csc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/csc.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
@@ -96,6 +97,8 @@ void csc_dump_regs(struct csc_data *csc)
 #define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, \
 	ioread32(csc->base + CSC_##r))
 
+	dev_dbg(dev, "CSC Registers @ %pa:\n", &csc->res->start);
+
 	DUMPREG(CSC00);
 	DUMPREG(CSC01);
 	DUMPREG(CSC02);
@@ -105,11 +108,13 @@ void csc_dump_regs(struct csc_data *csc)
 
 #undef DUMPREG
 }
+EXPORT_SYMBOL(csc_dump_regs);
 
 void csc_set_coeff_bypass(struct csc_data *csc, u32 *csc_reg5)
 {
 	*csc_reg5 |= CSC_BYPASS;
 }
+EXPORT_SYMBOL(csc_set_coeff_bypass);
 
 /*
  * set the color space converter coefficient shadow register values
@@ -160,8 +165,9 @@ void csc_set_coeff(struct csc_data *csc,
 	for (; coeff < end_coeff; coeff += 2)
 		*shadow_csc++ = (*(coeff + 1) << 16) | *coeff;
 }
+EXPORT_SYMBOL(csc_set_coeff);
 
-struct csc_data *csc_create(struct platform_device *pdev)
+struct csc_data *csc_create(struct platform_device *pdev, const char *res_name)
 {
 	struct csc_data *csc;
 
@@ -176,9 +182,10 @@ struct csc_data *csc_create(struct platf
 	csc->pdev = pdev;
 
 	csc->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-			"csc");
+						res_name);
 	if (csc->res == NULL) {
-		dev_err(&pdev->dev, "missing platform resources data\n");
+		dev_err(&pdev->dev, "missing '%s' platform resources data\n",
+			res_name);
 		return ERR_PTR(-ENODEV);
 	}
 
@@ -190,3 +197,8 @@ struct csc_data *csc_create(struct platf
 
 	return csc;
 }
+EXPORT_SYMBOL(csc_create);
+
+MODULE_DESCRIPTION("TI VIP/VPE Color Space Converter");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/csc.h linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/csc.h
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/csc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/csc.h	2017-02-12 16:03:20.000000000 -0500
@@ -63,6 +63,6 @@ void csc_set_coeff_bypass(struct csc_dat
 void csc_set_coeff(struct csc_data *csc, u32 *csc_reg0,
 		enum v4l2_colorspace src_colorspace,
 		enum v4l2_colorspace dst_colorspace);
-struct csc_data *csc_create(struct platform_device *pdev);
+struct csc_data *csc_create(struct platform_device *pdev, const char *res_name);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/Makefile linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/Makefile
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,12 @@
 obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe.o
+obj-$(CONFIG_VIDEO_TI_VPDMA) += ti-vpdma.o
+obj-$(CONFIG_VIDEO_TI_SC) += ti-sc.o
+obj-$(CONFIG_VIDEO_TI_CSC) += ti-csc.o
 
-ti-vpe-y := vpe.o sc.o csc.o vpdma.o
+ti-vpe-y := vpe.o
+ti-vpdma-y := vpdma.o
+ti-sc-y := sc.o
+ti-csc-y := csc.o
 
 ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/sc.c linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/sc.c
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/sc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/sc.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
 
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
@@ -27,6 +28,8 @@ void sc_dump_regs(struct sc_data *sc)
 #define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, \
 	ioread32(sc->base + CFG_##r))
 
+	dev_dbg(dev, "SC Registers @ %pa:\n", &sc->res->start);
+
 	DUMPREG(SC0);
 	DUMPREG(SC1);
 	DUMPREG(SC2);
@@ -52,6 +55,7 @@ void sc_dump_regs(struct sc_data *sc)
 
 #undef DUMPREG
 }
+EXPORT_SYMBOL(sc_dump_regs);
 
 /*
  * set the horizontal scaler coefficients according to the ratio of output to
@@ -84,9 +88,6 @@ void sc_set_hs_coeffs(struct sc_data *sc
 		}
 	}
 
-	if (idx == sc->hs_index)
-		return;
-
 	cp = scaler_hs_coeffs[idx];
 
 	for (i = 0; i < SC_NUM_PHASES * 2; i++) {
@@ -101,10 +102,9 @@ void sc_set_hs_coeffs(struct sc_data *sc
 		coeff_h += SC_NUM_TAPS_MEM_ALIGN - SC_H_NUM_TAPS;
 	}
 
-	sc->hs_index = idx;
-
 	sc->load_coeff_h = true;
 }
+EXPORT_SYMBOL(sc_set_hs_coeffs);
 
 /*
  * set the vertical scaler coefficients according to the ratio of output to
@@ -130,9 +130,6 @@ void sc_set_vs_coeffs(struct sc_data *sc
 		idx = VS_LT_9_16_SCALE + sixteenths - 8;
 	}
 
-	if (idx == sc->vs_index)
-		return;
-
 	cp = scaler_vs_coeffs[idx];
 
 	for (i = 0; i < SC_NUM_PHASES * 2; i++) {
@@ -146,9 +143,9 @@ void sc_set_vs_coeffs(struct sc_data *sc
 		coeff_v += SC_NUM_TAPS_MEM_ALIGN - SC_V_NUM_TAPS;
 	}
 
-	sc->vs_index = idx;
 	sc->load_coeff_v = true;
 }
+EXPORT_SYMBOL(sc_set_vs_coeffs);
 
 void sc_config_scaler(struct sc_data *sc, u32 *sc_reg0, u32 *sc_reg8,
 		u32 *sc_reg17, unsigned int src_w, unsigned int src_h,
@@ -276,8 +273,9 @@ void sc_config_scaler(struct sc_data *sc
 
 	*sc_reg24 = (src_w << CFG_ORG_W_SHIFT) | (src_h << CFG_ORG_H_SHIFT);
 }
+EXPORT_SYMBOL(sc_config_scaler);
 
-struct sc_data *sc_create(struct platform_device *pdev)
+struct sc_data *sc_create(struct platform_device *pdev, const char *res_name)
 {
 	struct sc_data *sc;
 
@@ -291,9 +289,10 @@ struct sc_data *sc_create(struct platfor
 
 	sc->pdev = pdev;
 
-	sc->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sc");
+	sc->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
 	if (!sc->res) {
-		dev_err(&pdev->dev, "missing platform resources data\n");
+		dev_err(&pdev->dev, "missing '%s' platform resources data\n",
+			res_name);
 		return ERR_PTR(-ENODEV);
 	}
 
@@ -305,3 +304,8 @@ struct sc_data *sc_create(struct platfor
 
 	return sc;
 }
+EXPORT_SYMBOL(sc_create);
+
+MODULE_DESCRIPTION("TI VIP/VPE Scaler");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/sc.h linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/sc.h
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/sc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/sc.h	2017-02-12 16:03:20.000000000 -0500
@@ -173,6 +173,12 @@
 /* number of taps expected by the scaler in it's coefficient memory */
 #define SC_NUM_TAPS_MEM_ALIGN		8
 
+/* Maximum frame width the scaler can handle (in pixels) */
+#define SC_MAX_PIXEL_WIDTH		2047
+
+/* Maximum frame height the scaler can handle (in lines) */
+#define SC_MAX_PIXEL_HEIGHT		2047
+
 /*
  * coefficient memory size in bytes:
  * num phases x num sets(luma and chroma) x num taps(aligned) x coeff size
@@ -189,9 +195,6 @@ struct sc_data {
 	bool			load_coeff_h;	/* have new h SC coeffs */
 	bool			load_coeff_v;	/* have new v SC coeffs */
 
-	unsigned int		hs_index;	/* h SC coeffs selector */
-	unsigned int		vs_index;	/* v SC coeffs selector */
-
 	struct platform_device *pdev;
 };
 
@@ -203,6 +206,6 @@ void sc_set_vs_coeffs(struct sc_data *sc
 void sc_config_scaler(struct sc_data *sc, u32 *sc_reg0, u32 *sc_reg8,
 		u32 *sc_reg17, unsigned int src_w, unsigned int src_h,
 		unsigned int dst_w, unsigned int dst_h);
-struct sc_data *sc_create(struct platform_device *pdev);
+struct sc_data *sc_create(struct platform_device *pdev, const char *res_name);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpdma.c linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpdma.c
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpdma.c	2016-12-11 17:48:33.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpdma.c	2017-02-12 17:36:26.000000000 -0500
@@ -59,9 +59,9 @@ const struct vpdma_data_format vpdma_yuv
 		.data_type	= DATA_TYPE_C420,
 		.depth		= 4,
 	},
-	[VPDMA_DATA_FMT_YC422] = {
+	[VPDMA_DATA_FMT_YCR422] = {
 		.type		= VPDMA_DATA_FMT_TYPE_YUV,
-		.data_type	= DATA_TYPE_YC422,
+		.data_type	= DATA_TYPE_YCR422,
 		.depth		= 16,
 	},
 	[VPDMA_DATA_FMT_YC444] = {
@@ -69,12 +69,23 @@ const struct vpdma_data_format vpdma_yuv
 		.data_type	= DATA_TYPE_YC444,
 		.depth		= 24,
 	},
-	[VPDMA_DATA_FMT_CY422] = {
+	[VPDMA_DATA_FMT_CRY422] = {
 		.type		= VPDMA_DATA_FMT_TYPE_YUV,
-		.data_type	= DATA_TYPE_CY422,
+		.data_type	= DATA_TYPE_CRY422,
+		.depth		= 16,
+	},
+	[VPDMA_DATA_FMT_CBY422] = {
+		.type		= VPDMA_DATA_FMT_TYPE_YUV,
+		.data_type	= DATA_TYPE_CBY422,
+		.depth		= 16,
+	},
+	[VPDMA_DATA_FMT_YCB422] = {
+		.type		= VPDMA_DATA_FMT_TYPE_YUV,
+		.data_type	= DATA_TYPE_YCB422,
 		.depth		= 16,
 	},
 };
+EXPORT_SYMBOL(vpdma_yuv_fmts);
 
 const struct vpdma_data_format vpdma_rgb_fmts[] = {
 	[VPDMA_DATA_FMT_RGB565] = {
@@ -178,6 +189,30 @@ const struct vpdma_data_format vpdma_rgb
 		.depth		= 32,
 	},
 };
+EXPORT_SYMBOL(vpdma_rgb_fmts);
+
+/*
+ * To handle RAW format we are re-using the CBY422
+ * vpdma data type so that we use the vpdma to re-order
+ * the incoming bytes, as the parser assumes that the
+ * first byte presented on the bus is the MSB of a 2
+ * bytes value.
+ * RAW8 handles from 1 to 8 bits
+ * RAW16 handles from 9 to 16 bits
+ */
+const struct vpdma_data_format vpdma_raw_fmts[] = {
+	[VPDMA_DATA_FMT_RAW8] = {
+		.type		= VPDMA_DATA_FMT_TYPE_YUV,
+		.data_type	= DATA_TYPE_CBY422,
+		.depth		= 8,
+	},
+	[VPDMA_DATA_FMT_RAW16] = {
+		.type		= VPDMA_DATA_FMT_TYPE_YUV,
+		.data_type	= DATA_TYPE_CBY422,
+		.depth		= 16,
+	},
+};
+EXPORT_SYMBOL(vpdma_raw_fmts);
 
 const struct vpdma_data_format vpdma_misc_fmts[] = {
 	[VPDMA_DATA_FMT_MV] = {
@@ -186,6 +221,7 @@ const struct vpdma_data_format vpdma_mis
 		.depth		= 4,
 	},
 };
+EXPORT_SYMBOL(vpdma_misc_fmts);
 
 struct vpdma_channel_info {
 	int num;		/* VPDMA channel number */
@@ -317,6 +353,7 @@ void vpdma_dump_regs(struct vpdma_data *
 	DUMPREG(VIP_UP_UV_CSTAT);
 	DUMPREG(VPI_CTL_CSTAT);
 }
+EXPORT_SYMBOL(vpdma_dump_regs);
 
 /*
  * Allocate a DMA buffer
@@ -333,6 +370,7 @@ int vpdma_alloc_desc_buf(struct vpdma_bu
 
 	return 0;
 }
+EXPORT_SYMBOL(vpdma_alloc_desc_buf);
 
 void vpdma_free_desc_buf(struct vpdma_buf *buf)
 {
@@ -341,6 +379,7 @@ void vpdma_free_desc_buf(struct vpdma_bu
 	buf->addr = NULL;
 	buf->size = 0;
 }
+EXPORT_SYMBOL(vpdma_free_desc_buf);
 
 /*
  * map descriptor/payload DMA buffer, enabling DMA access
@@ -351,7 +390,7 @@ int vpdma_map_desc_buf(struct vpdma_data
 
 	WARN_ON(buf->mapped);
 	buf->dma_addr = dma_map_single(dev, buf->addr, buf->size,
-				DMA_TO_DEVICE);
+				DMA_BIDIRECTIONAL);
 	if (dma_mapping_error(dev, buf->dma_addr)) {
 		dev_err(dev, "failed to map buffer\n");
 		return -EINVAL;
@@ -361,6 +400,7 @@ int vpdma_map_desc_buf(struct vpdma_data
 
 	return 0;
 }
+EXPORT_SYMBOL(vpdma_map_desc_buf);
 
 /*
  * unmap descriptor/payload DMA buffer, disabling DMA access and
@@ -371,10 +411,62 @@ void vpdma_unmap_desc_buf(struct vpdma_d
 	struct device *dev = &vpdma->pdev->dev;
 
 	if (buf->mapped)
-		dma_unmap_single(dev, buf->dma_addr, buf->size, DMA_TO_DEVICE);
+		dma_unmap_single(dev, buf->dma_addr, buf->size,
+				DMA_BIDIRECTIONAL);
 
 	buf->mapped = false;
 }
+EXPORT_SYMBOL(vpdma_unmap_desc_buf);
+
+/*
+ * Cleanup all pending descriptors of a list
+ * First, stop the current list being processed.
+ * If the VPDMA was busy, this step makes vpdma to accept post lists.
+ * To cleanup the internal FSM, post abort list descriptor for all the
+ * channels from @channels array of size @size.
+ */
+int vpdma_list_cleanup(struct vpdma_data *vpdma, int list_num,
+		int *channels, int size)
+{
+	struct vpdma_desc_list abort_list;
+	int i, ret, timeout = 500;
+
+	write_reg(vpdma, VPDMA_LIST_ATTR,
+			(list_num << VPDMA_LIST_NUM_SHFT) |
+			(1 << VPDMA_LIST_STOP_SHFT));
+
+	if (size <= 0 || !channels)
+		return 0;
+
+	ret = vpdma_create_desc_list(&abort_list,
+		size * sizeof(struct vpdma_dtd), VPDMA_LIST_TYPE_NORMAL);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < size; i++)
+		vpdma_add_abort_channel_ctd(&abort_list, channels[i]);
+
+	ret = vpdma_map_desc_buf(vpdma, &abort_list.buf);
+	if (ret)
+		return ret;
+	ret = vpdma_submit_descs(vpdma, &abort_list, list_num);
+	if (ret)
+		return ret;
+
+	while (vpdma_list_busy(vpdma, list_num) && timeout--)
+		;
+
+	if (timeout == 0) {
+		dev_err(&vpdma->pdev->dev, "Timed out cleaning up VPDMA list\n");
+		return -EBUSY;
+	}
+
+	vpdma_unmap_desc_buf(vpdma, &abort_list.buf);
+	vpdma_free_desc_buf(&abort_list.buf);
+
+	return 0;
+}
+EXPORT_SYMBOL(vpdma_list_cleanup);
 
 /*
  * create a descriptor list, the user of this list will append configuration,
@@ -396,6 +488,7 @@ int vpdma_create_desc_list(struct vpdma_
 
 	return 0;
 }
+EXPORT_SYMBOL(vpdma_create_desc_list);
 
 /*
  * once a descriptor list is parsed by VPDMA, we reset the list by emptying it,
@@ -405,6 +498,7 @@ void vpdma_reset_desc_list(struct vpdma_
 {
 	list->next = list->buf.addr;
 }
+EXPORT_SYMBOL(vpdma_reset_desc_list);
 
 /*
  * free the buffer allocated fot the VPDMA descriptor list, this should be
@@ -416,20 +510,22 @@ void vpdma_free_desc_list(struct vpdma_d
 
 	list->next = NULL;
 }
+EXPORT_SYMBOL(vpdma_free_desc_list);
 
-static bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num)
+bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num)
 {
 	return read_reg(vpdma, VPDMA_LIST_STAT_SYNC) & BIT(list_num + 16);
 }
+EXPORT_SYMBOL(vpdma_list_busy);
 
 /*
  * submit a list of DMA descriptors to the VPE VPDMA, do not wait for completion
  */
-int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list)
+int vpdma_submit_descs(struct vpdma_data *vpdma,
+			struct vpdma_desc_list *list, int list_num)
 {
-	/* we always use the first list */
-	int list_num = 0;
 	int list_size;
+	unsigned long flags;
 
 	if (vpdma_list_busy(vpdma, list_num))
 		return -EBUSY;
@@ -437,15 +533,68 @@ int vpdma_submit_descs(struct vpdma_data
 	/* 16-byte granularity */
 	list_size = (list->next - list->buf.addr) >> 4;
 
+	spin_lock_irqsave(&vpdma->lock, flags);
 	write_reg(vpdma, VPDMA_LIST_ADDR, (u32) list->buf.dma_addr);
 
 	write_reg(vpdma, VPDMA_LIST_ATTR,
 			(list_num << VPDMA_LIST_NUM_SHFT) |
 			(list->type << VPDMA_LIST_TYPE_SHFT) |
 			list_size);
+	spin_unlock_irqrestore(&vpdma->lock, flags);
 
 	return 0;
 }
+EXPORT_SYMBOL(vpdma_submit_descs);
+
+static void dump_dtd(struct vpdma_dtd *dtd);
+
+void vpdma_update_dma_addr(struct vpdma_data *vpdma,
+	struct vpdma_desc_list *list, dma_addr_t dma_addr,
+	void *write_dtd, int drop, int idx)
+{
+	struct vpdma_dtd *dtd = list->buf.addr;
+	dma_addr_t write_desc_addr;
+	int offset;
+
+	dtd += idx;
+	vpdma_unmap_desc_buf(vpdma, &list->buf);
+
+	dtd->start_addr = dma_addr;
+
+	/* Calculate write address from the offset of write_dtd from start
+	 * of the list->buf
+	 */
+	offset = (void *)write_dtd - list->buf.addr;
+	write_desc_addr = list->buf.dma_addr + offset;
+
+	if (drop)
+		dtd->desc_write_addr = dtd_desc_write_addr(write_desc_addr,
+							   1, 1, 0);
+	else
+		dtd->desc_write_addr = dtd_desc_write_addr(write_desc_addr,
+							   1, 0, 0);
+
+	vpdma_map_desc_buf(vpdma, &list->buf);
+
+	dump_dtd(dtd);
+}
+EXPORT_SYMBOL(vpdma_update_dma_addr);
+
+void vpdma_set_max_size(struct vpdma_data *vpdma, int reg_addr,
+			u32 width, u32 height)
+{
+	if (reg_addr != VPDMA_MAX_SIZE1 && reg_addr != VPDMA_MAX_SIZE2 &&
+	    reg_addr != VPDMA_MAX_SIZE3)
+		reg_addr = VPDMA_MAX_SIZE1;
+
+	write_field_reg(vpdma, reg_addr, width - 1,
+			VPDMA_MAX_SIZE_WIDTH_MASK, VPDMA_MAX_SIZE_WIDTH_SHFT);
+
+	write_field_reg(vpdma, reg_addr, height - 1,
+			VPDMA_MAX_SIZE_HEIGHT_MASK, VPDMA_MAX_SIZE_HEIGHT_SHFT);
+
+}
+EXPORT_SYMBOL(vpdma_set_max_size);
 
 static void dump_cfd(struct vpdma_cfd *cfd)
 {
@@ -466,10 +615,10 @@ static void dump_cfd(struct vpdma_cfd *c
 
 	pr_debug("word2: payload_addr = 0x%08x\n", cfd->payload_addr);
 
-	pr_debug("word3: pkt_type = %d, direct = %d, class = %d, dest = %d, "
-		"payload_len = %d\n", cfd_get_pkt_type(cfd),
-		cfd_get_direct(cfd), class, cfd_get_dest(cfd),
-		cfd_get_payload_len(cfd));
+	pr_debug("word3: pkt_type = %d, direct = %d, class = %d, dest = %d, payload_len = %d\n",
+		 cfd_get_pkt_type(cfd),
+		 cfd_get_direct(cfd), class, cfd_get_dest(cfd),
+		 cfd_get_payload_len(cfd));
 }
 
 /*
@@ -498,6 +647,7 @@ void vpdma_add_cfd_block(struct vpdma_de
 
 	dump_cfd(cfd);
 }
+EXPORT_SYMBOL(vpdma_add_cfd_block);
 
 /*
  * append a configuration descriptor to the given descriptor list, where the
@@ -526,6 +676,7 @@ void vpdma_add_cfd_adb(struct vpdma_desc
 
 	dump_cfd(cfd);
 };
+EXPORT_SYMBOL(vpdma_add_cfd_adb);
 
 /*
  * control descriptor format change based on what type of control descriptor it
@@ -563,6 +714,32 @@ void vpdma_add_sync_on_channel_ctd(struc
 
 	dump_ctd(ctd);
 }
+EXPORT_SYMBOL(vpdma_add_sync_on_channel_ctd);
+
+/*
+ * append an 'abort_channel' type control descriptor to the given descriptor
+ * list, this descriptor aborts any DMA transaction happening using the
+ * specified channel
+ */
+void vpdma_add_abort_channel_ctd(struct vpdma_desc_list *list,
+		int chan_num)
+{
+	struct vpdma_ctd *ctd;
+
+	ctd = list->next;
+	WARN_ON((void *)(ctd + 1) > (list->buf.addr + list->buf.size));
+
+	ctd->w0 = 0;
+	ctd->w1 = 0;
+	ctd->w2 = 0;
+	ctd->type_source_ctl = ctd_type_source_ctl(chan_num,
+				CTD_TYPE_ABORT_CHANNEL);
+
+	list->next = ctd + 1;
+
+	dump_ctd(ctd);
+}
+EXPORT_SYMBOL(vpdma_add_abort_channel_ctd);
 
 static void dump_dtd(struct vpdma_dtd *dtd)
 {
@@ -574,8 +751,7 @@ static void dump_dtd(struct vpdma_dtd *d
 	pr_debug("%s data transfer descriptor for channel %d\n",
 		dir == DTD_DIR_OUT ? "outbound" : "inbound", chan);
 
-	pr_debug("word0: data_type = %d, notify = %d, field = %d, 1D = %d, "
-		"even_ln_skp = %d, odd_ln_skp = %d, line_stride = %d\n",
+	pr_debug("word0: data_type = %d, notify = %d, field = %d, 1D = %d, even_ln_skp = %d, odd_ln_skp = %d, line_stride = %d\n",
 		dtd_get_data_type(dtd), dtd_get_notify(dtd), dtd_get_field(dtd),
 		dtd_get_1d(dtd), dtd_get_even_line_skip(dtd),
 		dtd_get_odd_line_skip(dtd), dtd_get_line_stride(dtd));
@@ -586,17 +762,16 @@ static void dump_dtd(struct vpdma_dtd *d
 
 	pr_debug("word2: start_addr = %pad\n", &dtd->start_addr);
 
-	pr_debug("word3: pkt_type = %d, mode = %d, dir = %d, chan = %d, "
-		"pri = %d, next_chan = %d\n", dtd_get_pkt_type(dtd),
-		dtd_get_mode(dtd), dir, chan, dtd_get_priority(dtd),
-		dtd_get_next_chan(dtd));
+	pr_debug("word3: pkt_type = %d, mode = %d, dir = %d, chan = %d, pri = %d, next_chan = %d\n",
+		 dtd_get_pkt_type(dtd),
+		 dtd_get_mode(dtd), dir, chan, dtd_get_priority(dtd),
+		 dtd_get_next_chan(dtd));
 
 	if (dir == DTD_DIR_IN)
 		pr_debug("word4: frame_width = %d, frame_height = %d\n",
 			dtd_get_frame_width(dtd), dtd_get_frame_height(dtd));
 	else
-		pr_debug("word4: desc_write_addr = 0x%08x, write_desc = %d, "
-			"drp_data = %d, use_desc_reg = %d\n",
+		pr_debug("word4: desc_write_addr = 0x%08x, write_desc = %d, drp_data = %d, use_desc_reg = %d\n",
 			dtd_get_desc_write_addr(dtd), dtd_get_write_desc(dtd),
 			dtd_get_drop_data(dtd), dtd_get_use_desc(dtd));
 
@@ -620,13 +795,25 @@ static void dump_dtd(struct vpdma_dtd *d
  * @c_rect: compose params of output image
  * @fmt: vpdma data format of the buffer
  * dma_addr: dma address as seen by VPDMA
+ * max_width: enum for maximum width of data transfer
+ * max_height: enum for maximum height of data transfer
  * chan: VPDMA channel
  * flags: VPDMA flags to configure some descriptor fileds
  */
 void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width,
 		const struct v4l2_rect *c_rect,
 		const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
-		enum vpdma_channel chan, u32 flags)
+		int max_w, int max_h, enum vpdma_channel chan, u32 flags)
+{
+	vpdma_rawchan_add_out_dtd(list, width, c_rect, fmt, dma_addr,
+				  max_w, max_h, chan_info[chan].num, flags);
+}
+EXPORT_SYMBOL(vpdma_add_out_dtd);
+
+void vpdma_rawchan_add_out_dtd(struct vpdma_desc_list *list, int width,
+		const struct v4l2_rect *c_rect,
+		const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
+		int max_w, int max_h, int raw_vpdma_chan, u32 flags)
 {
 	int priority = 0;
 	int field = 0;
@@ -637,7 +824,7 @@ void vpdma_add_out_dtd(struct vpdma_desc
 	int stride;
 	struct vpdma_dtd *dtd;
 
-	channel = next_chan = chan_info[chan].num;
+	channel = next_chan = raw_vpdma_chan;
 
 	if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV &&
 			fmt->data_type == DATA_TYPE_C420) {
@@ -665,8 +852,7 @@ void vpdma_add_out_dtd(struct vpdma_desc
 	dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED),
 				DTD_DIR_OUT, channel, priority, next_chan);
 	dtd->desc_write_addr = dtd_desc_write_addr(0, 0, 0, 0);
-	dtd->max_width_height = dtd_max_width_height(MAX_OUT_WIDTH_1920,
-					MAX_OUT_HEIGHT_1080);
+	dtd->max_width_height = dtd_max_width_height(max_w, max_h);
 	dtd->client_attr0 = 0;
 	dtd->client_attr1 = 0;
 
@@ -674,6 +860,7 @@ void vpdma_add_out_dtd(struct vpdma_desc
 
 	dump_dtd(dtd);
 }
+EXPORT_SYMBOL(vpdma_rawchan_add_out_dtd);
 
 /*
  * append an inbound data transfer descriptor to the given descriptor list,
@@ -747,27 +934,105 @@ void vpdma_add_in_dtd(struct vpdma_desc_
 
 	dump_dtd(dtd);
 }
+EXPORT_SYMBOL(vpdma_add_in_dtd);
+
+int vpdma_hwlist_alloc(struct vpdma_data *vpdma, void *priv)
+{
+	int i, list_num = -1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vpdma->lock, flags);
+	for (i = 0; i < VPDMA_MAX_NUM_LIST &&
+	    vpdma->hwlist_used[i] == true; i++)
+		;
+
+	if (i < VPDMA_MAX_NUM_LIST) {
+		list_num = i;
+		vpdma->hwlist_used[i] = true;
+		vpdma->hwlist_priv[i] = priv;
+	}
+	spin_unlock_irqrestore(&vpdma->lock, flags);
+
+	return list_num;
+}
+EXPORT_SYMBOL(vpdma_hwlist_alloc);
+
+void *vpdma_hwlist_get_priv(struct vpdma_data *vpdma, int list_num)
+{
+	if (!vpdma || list_num >= VPDMA_MAX_NUM_LIST)
+		return NULL;
+
+	return vpdma->hwlist_priv[list_num];
+}
+EXPORT_SYMBOL(vpdma_hwlist_get_priv);
+
+void *vpdma_hwlist_release(struct vpdma_data *vpdma, int list_num)
+{
+	void *priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&vpdma->lock, flags);
+	vpdma->hwlist_used[list_num] = false;
+	priv = vpdma->hwlist_priv;
+	spin_unlock_irqrestore(&vpdma->lock, flags);
+
+	return priv;
+}
+EXPORT_SYMBOL(vpdma_hwlist_release);
 
 /* set or clear the mask for list complete interrupt */
-void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
-		bool enable)
+void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int irq_num,
+		int list_num, bool enable)
 {
+	u32 reg_addr = VPDMA_INT_LIST0_MASK + VPDMA_INTX_OFFSET * irq_num;
 	u32 val;
 
-	val = read_reg(vpdma, VPDMA_INT_LIST0_MASK);
+	val = read_reg(vpdma, reg_addr);
 	if (enable)
 		val |= (1 << (list_num * 2));
 	else
 		val &= ~(1 << (list_num * 2));
-	write_reg(vpdma, VPDMA_INT_LIST0_MASK, val);
+	write_reg(vpdma, reg_addr, val);
+}
+EXPORT_SYMBOL(vpdma_enable_list_complete_irq);
+
+/* get the LIST_STAT register */
+unsigned int vpdma_get_list_stat(struct vpdma_data *vpdma, int irq_num)
+{
+	u32 reg_addr = VPDMA_INT_LIST0_STAT + VPDMA_INTX_OFFSET * irq_num;
+
+	return read_reg(vpdma, reg_addr);
+}
+EXPORT_SYMBOL(vpdma_get_list_stat);
+
+/* get the LIST_MASK register */
+unsigned int vpdma_get_list_mask(struct vpdma_data *vpdma, int irq_num)
+{
+	u32 reg_addr = VPDMA_INT_LIST0_MASK + VPDMA_INTX_OFFSET * irq_num;
+
+	return read_reg(vpdma, reg_addr);
 }
+EXPORT_SYMBOL(vpdma_get_list_mask);
 
 /* clear previosuly occured list intterupts in the LIST_STAT register */
-void vpdma_clear_list_stat(struct vpdma_data *vpdma)
+void vpdma_clear_list_stat(struct vpdma_data *vpdma, int irq_num,
+			   int list_num)
 {
-	write_reg(vpdma, VPDMA_INT_LIST0_STAT,
-		read_reg(vpdma, VPDMA_INT_LIST0_STAT));
+	u32 reg_addr = VPDMA_INT_LIST0_STAT + VPDMA_INTX_OFFSET * irq_num;
+
+	write_reg(vpdma, reg_addr, 3 << (list_num * 2));
+}
+EXPORT_SYMBOL(vpdma_clear_list_stat);
+
+void vpdma_set_bg_color(struct vpdma_data *vpdma,
+		struct vpdma_data_format *fmt, u32 color)
+{
+	if (fmt->type == VPDMA_DATA_FMT_TYPE_RGB)
+		write_reg(vpdma, VPDMA_BG_RGB, color);
+	else if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV)
+		write_reg(vpdma, VPDMA_BG_YUV, color);
 }
+EXPORT_SYMBOL(vpdma_set_bg_color);
 
 /*
  * configures the output mode of the line buffer for the given client, the
@@ -782,6 +1047,7 @@ void vpdma_set_line_mode(struct vpdma_da
 	write_field_reg(vpdma, client_cstat, line_mode,
 		VPDMA_CSTAT_LINE_MODE_MASK, VPDMA_CSTAT_LINE_MODE_SHIFT);
 }
+EXPORT_SYMBOL(vpdma_set_line_mode);
 
 /*
  * configures the event which should trigger VPDMA transfer for the given
@@ -796,6 +1062,7 @@ void vpdma_set_frame_start_event(struct
 	write_field_reg(vpdma, client_cstat, fs_event,
 		VPDMA_CSTAT_FRAME_START_MASK, VPDMA_CSTAT_FRAME_START_SHIFT);
 }
+EXPORT_SYMBOL(vpdma_set_frame_start_event);
 
 static void vpdma_firmware_cb(const struct firmware *f, void *context)
 {
@@ -871,42 +1138,40 @@ static int vpdma_load_firmware(struct vp
 	return 0;
 }
 
-struct vpdma_data *vpdma_create(struct platform_device *pdev,
+int vpdma_create(struct platform_device *pdev, struct vpdma_data *vpdma,
 		void (*cb)(struct platform_device *pdev))
 {
 	struct resource *res;
-	struct vpdma_data *vpdma;
 	int r;
 
 	dev_dbg(&pdev->dev, "vpdma_create\n");
 
-	vpdma = devm_kzalloc(&pdev->dev, sizeof(*vpdma), GFP_KERNEL);
-	if (!vpdma) {
-		dev_err(&pdev->dev, "couldn't alloc vpdma_dev\n");
-		return ERR_PTR(-ENOMEM);
-	}
-
 	vpdma->pdev = pdev;
 	vpdma->cb = cb;
+	spin_lock_init(&vpdma->lock);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma");
 	if (res == NULL) {
 		dev_err(&pdev->dev, "missing platform resources data\n");
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 	}
 
 	vpdma->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
 	if (!vpdma->base) {
 		dev_err(&pdev->dev, "failed to ioremap\n");
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	}
 
 	r = vpdma_load_firmware(vpdma);
 	if (r) {
 		pr_err("failed to load firmware %s\n", VPDMA_FIRMWARE);
-		return ERR_PTR(r);
+		return r;
 	}
 
-	return vpdma;
+	return 0;
 }
+EXPORT_SYMBOL(vpdma_create);
+
+MODULE_AUTHOR("Texas Instruments Inc.");
 /*(DEBLOBBED)*/
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpdma.h linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpdma.h
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpdma.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpdma.h	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@
 #ifndef __TI_VPDMA_H_
 #define __TI_VPDMA_H_
 
+#define VPDMA_MAX_NUM_LIST		8
 /*
  * A vpdma_buf tracks the size, DMA address and mapping status of each
  * driver DMA area.
@@ -35,6 +36,9 @@ struct vpdma_data {
 
 	struct platform_device	*pdev;
 
+	spinlock_t		lock;
+	bool			hwlist_used[VPDMA_MAX_NUM_LIST];
+	void			*hwlist_priv[VPDMA_MAX_NUM_LIST];
 	/* callback to VPE driver when the firmware is loaded */
 	void (*cb)(struct platform_device *pdev);
 };
@@ -70,9 +74,11 @@ enum vpdma_yuv_formats {
 	VPDMA_DATA_FMT_C444,
 	VPDMA_DATA_FMT_C422,
 	VPDMA_DATA_FMT_C420,
-	VPDMA_DATA_FMT_YC422,
+	VPDMA_DATA_FMT_YCR422,
 	VPDMA_DATA_FMT_YC444,
-	VPDMA_DATA_FMT_CY422,
+	VPDMA_DATA_FMT_CRY422,
+	VPDMA_DATA_FMT_CBY422,
+	VPDMA_DATA_FMT_YCB422,
 };
 
 enum vpdma_rgb_formats {
@@ -98,12 +104,18 @@ enum vpdma_rgb_formats {
 	VPDMA_DATA_FMT_BGRA32,
 };
 
+enum vpdma_raw_formats {
+	VPDMA_DATA_FMT_RAW8 = 0,
+	VPDMA_DATA_FMT_RAW16,
+};
+
 enum vpdma_misc_formats {
 	VPDMA_DATA_FMT_MV = 0,
 };
 
 extern const struct vpdma_data_format vpdma_yuv_fmts[];
 extern const struct vpdma_data_format vpdma_rgb_fmts[];
+extern const struct vpdma_data_format vpdma_raw_fmts[];
 extern const struct vpdma_data_format vpdma_misc_fmts[];
 
 enum vpdma_frame_start_event {
@@ -117,6 +129,30 @@ enum vpdma_frame_start_event {
 	VPDMA_FSEVENT_CHANNEL_ACTIVE,
 };
 
+/* max width configurations */
+enum vpdma_max_width {
+	MAX_OUT_WIDTH_UNLIMITED = 0,
+	MAX_OUT_WIDTH_REG1,
+	MAX_OUT_WIDTH_REG2,
+	MAX_OUT_WIDTH_REG3,
+	MAX_OUT_WIDTH_352,
+	MAX_OUT_WIDTH_768,
+	MAX_OUT_WIDTH_1280,
+	MAX_OUT_WIDTH_1920,
+};
+
+/* max height configurations */
+enum vpdma_max_height {
+	MAX_OUT_HEIGHT_UNLIMITED = 0,
+	MAX_OUT_HEIGHT_REG1,
+	MAX_OUT_HEIGHT_REG2,
+	MAX_OUT_HEIGHT_REG3,
+	MAX_OUT_HEIGHT_288,
+	MAX_OUT_HEIGHT_576,
+	MAX_OUT_HEIGHT_720,
+	MAX_OUT_HEIGHT_1080,
+};
+
 /*
  * VPDMA channel numbers
  */
@@ -134,6 +170,13 @@ enum vpdma_channel {
 	VPE_CHAN_RGB_OUT,
 };
 
+#define VIP_CHAN_VIP2_OFFSET		70
+#define VIP_CHAN_MULT_PORTB_OFFSET	16
+#define VIP_CHAN_YUV_PORTB_OFFSET	2
+#define VIP_CHAN_RGB_PORTB_OFFSET	1
+
+#define VPDMA_MAX_CHANNELS		256
+
 /* flags for VPDMA data descriptors */
 #define VPDMA_DATA_ODD_LINE_SKIP	(1 << 0)
 #define VPDMA_DATA_EVEN_LINE_SKIP	(1 << 1)
@@ -177,7 +220,17 @@ void vpdma_unmap_desc_buf(struct vpdma_d
 int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type);
 void vpdma_reset_desc_list(struct vpdma_desc_list *list);
 void vpdma_free_desc_list(struct vpdma_desc_list *list);
-int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list);
+int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list,
+		       int list_num);
+bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num);
+void vpdma_update_dma_addr(struct vpdma_data *vpdma,
+	struct vpdma_desc_list *list, dma_addr_t dma_addr,
+	void *write_dtd, int drop, int idx);
+
+/* VPDMA hardware list funcs */
+int vpdma_hwlist_alloc(struct vpdma_data *vpdma, void *priv);
+void *vpdma_hwlist_get_priv(struct vpdma_data *vpdma, int list_num);
+void *vpdma_hwlist_release(struct vpdma_data *vpdma, int list_num);
 
 /* helpers for creating vpdma descriptors */
 void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client,
@@ -186,31 +239,47 @@ void vpdma_add_cfd_adb(struct vpdma_desc
 		struct vpdma_buf *adb);
 void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list,
 		enum vpdma_channel chan);
+void vpdma_add_abort_channel_ctd(struct vpdma_desc_list *list,
+		int chan_num);
 void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width,
 		const struct v4l2_rect *c_rect,
 		const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
-		enum vpdma_channel chan, u32 flags);
+		int max_w, int max_h, enum vpdma_channel chan, u32 flags);
+void vpdma_rawchan_add_out_dtd(struct vpdma_desc_list *list, int width,
+		const struct v4l2_rect *c_rect,
+		const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
+		int max_w, int max_h, int raw_vpdma_chan, u32 flags);
+
 void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width,
 		const struct v4l2_rect *c_rect,
 		const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
 		enum vpdma_channel chan, int field, u32 flags, int frame_width,
 		int frame_height, int start_h, int start_v);
+int vpdma_list_cleanup(struct vpdma_data *vpdma, int list_num,
+		int *channels, int size);
 
 /* vpdma list interrupt management */
-void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
-		bool enable);
-void vpdma_clear_list_stat(struct vpdma_data *vpdma);
+void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int irq_num,
+		int list_num, bool enable);
+void vpdma_clear_list_stat(struct vpdma_data *vpdma, int irq_num,
+			   int list_num);
+unsigned int vpdma_get_list_stat(struct vpdma_data *vpdma, int irq_num);
+unsigned int vpdma_get_list_mask(struct vpdma_data *vpdma, int irq_num);
 
 /* vpdma client configuration */
 void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode,
 		enum vpdma_channel chan);
 void vpdma_set_frame_start_event(struct vpdma_data *vpdma,
 		enum vpdma_frame_start_event fs_event, enum vpdma_channel chan);
+void vpdma_set_max_size(struct vpdma_data *vpdma, int reg_addr,
+			u32 width, u32 height);
 
+void vpdma_set_bg_color(struct vpdma_data *vpdma,
+			struct vpdma_data_format *fmt, u32 color);
 void vpdma_dump_regs(struct vpdma_data *vpdma);
 
 /* initialize vpdma, passed with VPE's platform device pointer */
-struct vpdma_data *vpdma_create(struct platform_device *pdev,
+int vpdma_create(struct platform_device *pdev, struct vpdma_data *vpdma,
 		void (*cb)(struct platform_device *pdev));
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpdma_priv.h linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpdma_priv.h
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpdma_priv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpdma_priv.h	2017-02-12 16:03:20.000000000 -0500
@@ -28,6 +28,10 @@
 #define VPDMA_MAX_SIZE1		0x34
 #define VPDMA_MAX_SIZE2		0x38
 #define VPDMA_MAX_SIZE3		0x3c
+#define VPDMA_MAX_SIZE_WIDTH_MASK	0xffff
+#define VPDMA_MAX_SIZE_WIDTH_SHFT	16
+#define VPDMA_MAX_SIZE_HEIGHT_MASK	0xffff
+#define VPDMA_MAX_SIZE_HEIGHT_SHFT	0
 
 /* Interrupts */
 #define VPDMA_INT_CHAN_STAT(grp)	(0x40 + grp * 8)
@@ -39,9 +43,11 @@
 #define VPDMA_INT_LIST0_STAT		0x88
 #define VPDMA_INT_LIST0_MASK		0x8c
 
+#define VPDMA_INTX_OFFSET		0x50
+
 #define VPDMA_PERFMON(i)		(0x200 + i * 4)
 
-/* VPE specific client registers */
+/* VIP/VPE client registers */
 #define VPDMA_DEI_CHROMA1_CSTAT		0x0300
 #define VPDMA_DEI_LUMA1_CSTAT		0x0304
 #define VPDMA_DEI_LUMA2_CSTAT		0x0308
@@ -50,6 +56,8 @@
 #define VPDMA_DEI_CHROMA3_CSTAT		0x0314
 #define VPDMA_DEI_MV_IN_CSTAT		0x0330
 #define VPDMA_DEI_MV_OUT_CSTAT		0x033c
+#define VPDMA_VIP_LO_Y_CSTAT		0x0388
+#define VPDMA_VIP_LO_UV_CSTAT		0x038c
 #define VPDMA_VIP_UP_Y_CSTAT		0x0390
 #define VPDMA_VIP_UP_UV_CSTAT		0x0394
 #define VPDMA_VPI_CTL_CSTAT		0x03d0
@@ -69,41 +77,63 @@
 #define VPDMA_LIST_TYPE_SHFT		16
 #define VPDMA_LIST_SIZE_MASK		0xffff
 
-/* VPDMA data type values for data formats */
+/*
+ * The YUV data type definition below are taken from
+ * both the TRM and i839 Errata information.
+ * Use the correct data type considering byte
+ * reordering of components.
+ *
+ * Also since the single use of "C" in the 422 case
+ * to mean "Cr" (i.e. V component). It was decided
+ * to explicitly label them CR to remove any confusion.
+ * Bear in mind that the type label refer to the memory
+ * packed order (LSB - MSB).
+ */
 #define DATA_TYPE_Y444				0x0
 #define DATA_TYPE_Y422				0x1
 #define DATA_TYPE_Y420				0x2
 #define DATA_TYPE_C444				0x4
 #define DATA_TYPE_C422				0x5
 #define DATA_TYPE_C420				0x6
-#define DATA_TYPE_YC422				0x7
 #define DATA_TYPE_YC444				0x8
-#define DATA_TYPE_CY422				0x27
+#define DATA_TYPE_YCB422			0x7
+#define DATA_TYPE_YCR422			0x17
+#define DATA_TYPE_CBY422			0x27
+#define DATA_TYPE_CRY422			0x37
 
-#define DATA_TYPE_RGB16_565			0x0
-#define DATA_TYPE_ARGB_1555			0x1
-#define DATA_TYPE_ARGB_4444			0x2
-#define DATA_TYPE_RGBA_5551			0x3
-#define DATA_TYPE_RGBA_4444			0x4
-#define DATA_TYPE_ARGB24_6666			0x5
-#define DATA_TYPE_RGB24_888			0x6
-#define DATA_TYPE_ARGB32_8888			0x7
-#define DATA_TYPE_RGBA24_6666			0x8
-#define DATA_TYPE_RGBA32_8888			0x9
-#define DATA_TYPE_BGR16_565			0x10
-#define DATA_TYPE_ABGR_1555			0x11
-#define DATA_TYPE_ABGR_4444			0x12
-#define DATA_TYPE_BGRA_5551			0x13
-#define DATA_TYPE_BGRA_4444			0x14
-#define DATA_TYPE_ABGR24_6666			0x15
-#define DATA_TYPE_BGR24_888			0x16
-#define DATA_TYPE_ABGR32_8888			0x17
-#define DATA_TYPE_BGRA24_6666			0x18
-#define DATA_TYPE_BGRA32_8888			0x19
+/*
+ * The RGB data type definition below are defined
+ * to follow Errata i819.
+ * The initial values were taken from:
+ * VPDMA_data_type_mapping_v0.2vayu_c.pdf
+ * But some of the ARGB definition appeared to be wrong
+ * in the document also. As they would yield RGBA instead.
+ * They have been corrected based on experimentation.
+ */
+#define DATA_TYPE_RGB16_565			0x10
+#define DATA_TYPE_ARGB_1555			0x13
+#define DATA_TYPE_ARGB_4444			0x14
+#define DATA_TYPE_RGBA_5551			0x11
+#define DATA_TYPE_RGBA_4444			0x12
+#define DATA_TYPE_ARGB24_6666			0x18
+#define DATA_TYPE_RGB24_888			0x16
+#define DATA_TYPE_ARGB32_8888			0x17
+#define DATA_TYPE_RGBA24_6666			0x15
+#define DATA_TYPE_RGBA32_8888			0x19
+#define DATA_TYPE_BGR16_565			0x0
+#define DATA_TYPE_ABGR_1555			0x3
+#define DATA_TYPE_ABGR_4444			0x4
+#define DATA_TYPE_BGRA_5551			0x1
+#define DATA_TYPE_BGRA_4444			0x2
+#define DATA_TYPE_ABGR24_6666			0x8
+#define DATA_TYPE_BGR24_888			0x6
+#define DATA_TYPE_ABGR32_8888			0x7
+#define DATA_TYPE_BGRA24_6666			0x5
+#define DATA_TYPE_BGRA32_8888			0x9
 
 #define DATA_TYPE_MV				0x3
 
-/* VPDMA channel numbers(only VPE channels for now) */
+/* VPDMA channel numbers, some are common between VIP/VPE and appear twice */
 #define	VPE_CHAN_NUM_LUMA1_IN		0
 #define	VPE_CHAN_NUM_CHROMA1_IN		1
 #define	VPE_CHAN_NUM_LUMA2_IN		2
@@ -112,10 +142,15 @@
 #define	VPE_CHAN_NUM_CHROMA3_IN		5
 #define	VPE_CHAN_NUM_MV_IN		12
 #define	VPE_CHAN_NUM_MV_OUT		15
+#define VIP1_CHAN_NUM_MULT_PORT_A_SRC0	38
+#define VIP1_CHAN_NUM_MULT_ANC_A_SRC0	70
 #define	VPE_CHAN_NUM_LUMA_OUT		102
 #define	VPE_CHAN_NUM_CHROMA_OUT		103
+#define VIP1_CHAN_NUM_PORT_A_LUMA	102
+#define VIP1_CHAN_NUM_PORT_A_CHROMA	103
 #define	VPE_CHAN_NUM_RGB_OUT		106
-
+#define VIP1_CHAN_NUM_PORT_A_RGB	106
+#define VIP1_CHAN_NUM_PORT_B_RGB	107
 /*
  * a VPDMA address data block payload for a configuration descriptor needs to
  * have each sub block length as a multiple of 16 bytes. Therefore, the overall
@@ -203,6 +238,7 @@ struct vpdma_dtd {
 #define DTD_V_START_MASK	0xffff
 #define DTD_V_START_SHFT	0
 
+#define DTD_DESC_START_MASK	0xffffffe0
 #define DTD_DESC_START_SHIFT	5
 #define DTD_WRITE_DESC_MASK	0x01
 #define DTD_WRITE_DESC_SHIFT	2
@@ -217,42 +253,6 @@ struct vpdma_dtd {
 #define DTD_MAX_HEIGHT_MASK	0x07
 #define DTD_MAX_HEIGHT_SHFT	0
 
-/* max width configurations */
- /* unlimited width */
-#define	MAX_OUT_WIDTH_UNLIMITED		0
-/* as specified in max_size1 reg */
-#define MAX_OUT_WIDTH_REG1		1
-/* as specified in max_size2 reg */
-#define MAX_OUT_WIDTH_REG2		2
-/* as specified in max_size3 reg */
-#define	MAX_OUT_WIDTH_REG3		3
-/* maximum of 352 pixels as width */
-#define MAX_OUT_WIDTH_352		4
-/* maximum of 768 pixels as width */
-#define	MAX_OUT_WIDTH_768		5
-/* maximum of 1280 pixels width */
-#define	MAX_OUT_WIDTH_1280		6
-/* maximum of 1920 pixels as width */
-#define	MAX_OUT_WIDTH_1920		7
-
-/* max height configurations */
- /* unlimited height */
-#define	MAX_OUT_HEIGHT_UNLIMITED	0
-/* as specified in max_size1 reg */
-#define MAX_OUT_HEIGHT_REG1		1
-/* as specified in max_size2 reg */
-#define MAX_OUT_HEIGHT_REG2		2
-/* as specified in max_size3 reg */
-#define	MAX_OUT_HEIGHT_REG3		3
-/* maximum of 288 lines as height */
-#define MAX_OUT_HEIGHT_288		4
-/* maximum of 576 lines as height */
-#define	MAX_OUT_HEIGHT_576		5
-/* maximum of 720 lines as height */
-#define	MAX_OUT_HEIGHT_720		6
-/* maximum of 1080 lines as height */
-#define	MAX_OUT_HEIGHT_1080		7
-
 static inline u32 dtd_type_ctl_stride(int type, bool notify, int field,
 			bool one_d, bool even_line_skip, bool odd_line_skip,
 			int line_stride)
@@ -285,7 +285,7 @@ static inline u32 dtd_frame_width_height
 static inline u32 dtd_desc_write_addr(unsigned int addr, bool write_desc,
 			bool drop_data, bool use_desc)
 {
-	return (addr << DTD_DESC_START_SHIFT) |
+	return (addr & DTD_DESC_START_MASK) |
 		(write_desc << DTD_WRITE_DESC_SHIFT) |
 		(drop_data << DTD_DROP_DATA_SHIFT) |
 		use_desc;
@@ -390,7 +390,7 @@ static inline int dtd_get_frame_height(s
 
 static inline int dtd_get_desc_write_addr(struct vpdma_dtd *dtd)
 {
-	return dtd->desc_write_addr >> DTD_DESC_START_SHIFT;
+	return dtd->desc_write_addr & DTD_DESC_START_MASK;
 }
 
 static inline bool dtd_get_write_desc(struct vpdma_dtd *dtd)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpe.c linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpe.c
--- linux-libre-4.9-gnu/drivers/media/platform/ti-vpe/vpe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/ti-vpe/vpe.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,7 @@
 #include <media/videobuf2-dma-contig.h>
 
 #include "vpdma.h"
+#include "vpdma_priv.h"
 #include "vpe_regs.h"
 #include "sc.h"
 #include "csc.h"
@@ -53,8 +54,8 @@
 /* minimum and maximum frame sizes */
 #define MIN_W		32
 #define MIN_H		32
-#define MAX_W		1920
-#define MAX_H		1080
+#define MAX_W		2048
+#define MAX_H		1184
 
 /* required alignments */
 #define S_ALIGN		0	/* multiple of 1 */
@@ -141,7 +142,7 @@ struct vpe_dei_regs {
  */
 static const struct vpe_dei_regs dei_regs = {
 	.mdt_spacial_freq_thr_reg = 0x020C0804u,
-	.edi_config_reg = 0x0118100Fu,
+	.edi_config_reg = 0x0118100Cu,
 	.edi_lut_reg0 = 0x08040200u,
 	.edi_lut_reg1 = 0x1010100Cu,
 	.edi_lut_reg2 = 0x10101010u,
@@ -236,7 +237,7 @@ struct vpe_fmt {
 
 static struct vpe_fmt vpe_formats[] = {
 	{
-		.name		= "YUV 422 co-planar",
+		.name		= "NV16 YUV 422 co-planar",
 		.fourcc		= V4L2_PIX_FMT_NV16,
 		.types		= VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
 		.coplanar	= 1,
@@ -245,7 +246,7 @@ static struct vpe_fmt vpe_formats[] = {
 				  },
 	},
 	{
-		.name		= "YUV 420 co-planar",
+		.name		= "NV12 YUV 420 co-planar",
 		.fourcc		= V4L2_PIX_FMT_NV12,
 		.types		= VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
 		.coplanar	= 1,
@@ -258,7 +259,7 @@ static struct vpe_fmt vpe_formats[] = {
 		.fourcc		= V4L2_PIX_FMT_YUYV,
 		.types		= VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
 		.coplanar	= 0,
-		.vpdma_fmt	= { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YC422],
+		.vpdma_fmt	= { &vpdma_yuv_fmts[VPDMA_DATA_FMT_YCB422],
 				  },
 	},
 	{
@@ -266,7 +267,7 @@ static struct vpe_fmt vpe_formats[] = {
 		.fourcc		= V4L2_PIX_FMT_UYVY,
 		.types		= VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
 		.coplanar	= 0,
-		.vpdma_fmt	= { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CY422],
+		.vpdma_fmt	= { &vpdma_yuv_fmts[VPDMA_DATA_FMT_CBY422],
 				  },
 	},
 	{
@@ -301,6 +302,22 @@ static struct vpe_fmt vpe_formats[] = {
 		.vpdma_fmt	= { &vpdma_rgb_fmts[VPDMA_DATA_FMT_ABGR32],
 				  },
 	},
+	{
+		.name		= "RGB565",
+		.fourcc		= V4L2_PIX_FMT_RGB565,
+		.types		= VPE_FMT_TYPE_CAPTURE,
+		.coplanar	= 0,
+		.vpdma_fmt	= { &vpdma_rgb_fmts[VPDMA_DATA_FMT_RGB565],
+				  },
+	},
+	{
+		.name		= "RGB5551",
+		.fourcc		= V4L2_PIX_FMT_RGB555,
+		.types		= VPE_FMT_TYPE_CAPTURE,
+		.coplanar	= 0,
+		.vpdma_fmt	= { &vpdma_rgb_fmts[VPDMA_DATA_FMT_RGBA16_5551],
+				  },
+	},
 };
 
 /*
@@ -310,6 +327,7 @@ static struct vpe_fmt vpe_formats[] = {
 struct vpe_q_data {
 	unsigned int		width;				/* frame width */
 	unsigned int		height;				/* frame height */
+	unsigned int		nplanes;			/* Current number of planes */
 	unsigned int		bytesperline[VPE_MAX_PLANES];	/* bytes per line in memory */
 	enum v4l2_colorspace	colorspace;
 	enum v4l2_field		field;				/* supported field value */
@@ -320,9 +338,13 @@ struct vpe_q_data {
 };
 
 /* vpe_q_data flag bits */
-#define	Q_DATA_FRAME_1D		(1 << 0)
-#define	Q_DATA_MODE_TILED	(1 << 1)
-#define	Q_DATA_INTERLACED	(1 << 2)
+#define	Q_DATA_FRAME_1D			BIT(0)
+#define	Q_DATA_MODE_TILED		BIT(1)
+#define	Q_DATA_INTERLACED_ALTERNATE	BIT(2)
+#define	Q_DATA_INTERLACED_SEQ_TB	BIT(3)
+
+#define Q_IS_INTERLACED		(Q_DATA_INTERLACED_ALTERNATE | \
+				Q_DATA_INTERLACED_SEQ_TB)
 
 enum {
 	Q_DATA_SRC = 0,
@@ -362,6 +384,7 @@ struct vpe_dev {
 	void __iomem		*base;
 	struct resource		*res;
 
+	struct vpdma_data	vpdma_data;
 	struct vpdma_data	*vpdma;		/* vpdma data handle */
 	struct sc_data		*sc;		/* scaler data handle */
 	struct csc_data		*csc;		/* csc data handle */
@@ -416,7 +439,7 @@ static struct vpe_q_data *get_q_data(str
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		return &ctx->q_data[Q_DATA_DST];
 	default:
-		BUG();
+		return NULL;
 	}
 	return NULL;
 }
@@ -584,7 +607,10 @@ static void free_vbs(struct vpe_ctx *ctx
 	spin_lock_irqsave(&dev->lock, flags);
 	if (ctx->src_vbs[2]) {
 		v4l2_m2m_buf_done(ctx->src_vbs[2], VB2_BUF_STATE_DONE);
-		v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_DONE);
+		if (ctx->src_vbs[1] && (ctx->src_vbs[1] != ctx->src_vbs[2]))
+			v4l2_m2m_buf_done(ctx->src_vbs[1], VB2_BUF_STATE_DONE);
+		ctx->src_vbs[2] = NULL;
+		ctx->src_vbs[1] = NULL;
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
@@ -638,7 +664,7 @@ static void set_us_coefficients(struct v
 
 	cp = &us_coeffs[0].anchor_fid0_c0;
 
-	if (s_q_data->flags & Q_DATA_INTERLACED)	/* interlaced */
+	if (s_q_data->flags & Q_IS_INTERLACED)		/* interlaced */
 		cp += sizeof(us_coeffs[0]) / sizeof(*cp);
 
 	end_cp = cp + sizeof(us_coeffs[0]) / sizeof(*cp);
@@ -655,14 +681,13 @@ static void set_us_coefficients(struct v
 /*
  * Set the upsampler config mode and the VPDMA line mode in the shadow MMRs.
  */
-static void set_cfg_and_line_modes(struct vpe_ctx *ctx)
+static void set_cfg_modes(struct vpe_ctx *ctx)
 {
 	struct vpe_fmt *fmt = ctx->q_data[Q_DATA_SRC].fmt;
 	struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr;
 	u32 *us1_reg0 = &mmr_adb->us1_regs[0];
 	u32 *us2_reg0 = &mmr_adb->us2_regs[0];
 	u32 *us3_reg0 = &mmr_adb->us3_regs[0];
-	int line_mode = 1;
 	int cfg_mode = 1;
 
 	/*
@@ -670,15 +695,24 @@ static void set_cfg_and_line_modes(struc
 	 * Cfg Mode 1: YUV422 source, disable upsampler, DEI is de-interlacing.
 	 */
 
-	if (fmt->fourcc == V4L2_PIX_FMT_NV12) {
+	if (fmt->fourcc == V4L2_PIX_FMT_NV12)
 		cfg_mode = 0;
-		line_mode = 0;		/* double lines to line buffer */
-	}
 
 	write_field(us1_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT);
 	write_field(us2_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT);
 	write_field(us3_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT);
 
+	ctx->load_mmrs = true;
+}
+
+static void set_line_modes(struct vpe_ctx *ctx)
+{
+	struct vpe_fmt *fmt = ctx->q_data[Q_DATA_SRC].fmt;
+	int line_mode = 1;
+
+	if (fmt->fourcc == V4L2_PIX_FMT_NV12)
+		line_mode = 0;		/* double lines to line buffer */
+
 	/* regs for now */
 	vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA1_IN);
 	vpdma_set_line_mode(ctx->dev->vpdma, line_mode, VPE_CHAN_CHROMA2_IN);
@@ -703,8 +737,6 @@ static void set_cfg_and_line_modes(struc
 	/* frame start for MV in client */
 	vpdma_set_frame_start_event(ctx->dev->vpdma, VPDMA_FSEVENT_CHANNEL_ACTIVE,
 		VPE_CHAN_MV_IN);
-
-	ctx->load_mmrs = true;
 }
 
 /*
@@ -727,9 +759,11 @@ static void set_dst_registers(struct vpe
 	struct vpe_fmt *fmt = ctx->q_data[Q_DATA_DST].fmt;
 	u32 val = 0;
 
-	if (clrspc == V4L2_COLORSPACE_SRGB)
+	if (clrspc == V4L2_COLORSPACE_SRGB) {
 		val |= VPE_RGB_OUT_SELECT;
-	else if (fmt->fourcc == V4L2_PIX_FMT_NV16)
+		vpdma_set_bg_color(ctx->dev->vpdma,
+			(struct vpdma_data_format *)fmt->vpdma_fmt[0], 0xff);
+	} else if (fmt->fourcc == V4L2_PIX_FMT_NV16)
 		val |= VPE_COLOR_SEPARATE_422;
 
 	/*
@@ -765,8 +799,7 @@ static void set_dei_regs(struct vpe_ctx
 	 * for both progressive and interlace content in interlace bypass mode.
 	 * It has been recommended not to use progressive bypass mode.
 	 */
-	if ((!ctx->deinterlacing && (s_q_data->flags & Q_DATA_INTERLACED)) ||
-			!(s_q_data->flags & Q_DATA_INTERLACED)) {
+	if (!(s_q_data->flags & Q_IS_INTERLACED) || !ctx->deinterlacing) {
 		deinterlace = false;
 		val = VPE_DEI_INTERLACE_BYPASS;
 	}
@@ -798,6 +831,23 @@ static void set_dei_shadow_registers(str
 	ctx->load_mmrs = true;
 }
 
+static void config_edi_input_mode(struct vpe_ctx *ctx, int mode)
+{
+	struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr;
+	u32 *edi_config_reg = &mmr_adb->dei_regs[3];
+
+	if (mode & 0x2)
+		write_field(edi_config_reg, 1, 1, 2);	/* EDI_ENABLE_3D */
+
+	if (mode & 0x3)
+		write_field(edi_config_reg, 1, 1, 3);	/* EDI_CHROMA_3D  */
+
+	write_field(edi_config_reg, mode, VPE_EDI_INP_MODE_MASK,
+		VPE_EDI_INP_MODE_SHIFT);
+
+	ctx->load_mmrs = true;
+}
+
 /*
  * Set the shadow registers whose values are modified when either the
  * source or destination format is changed.
@@ -817,8 +867,8 @@ static int set_srcdst_params(struct vpe_
 	ctx->sequence = 0;
 	ctx->field = V4L2_FIELD_TOP;
 
-	if ((s_q_data->flags & Q_DATA_INTERLACED) &&
-			!(d_q_data->flags & Q_DATA_INTERLACED)) {
+	if ((s_q_data->flags & Q_IS_INTERLACED) &&
+			!(d_q_data->flags & Q_IS_INTERLACED)) {
 		int bytes_per_line;
 		const struct vpdma_data_format *mv =
 			&vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
@@ -842,12 +892,13 @@ static int set_srcdst_params(struct vpe_
 	}
 
 	free_vbs(ctx);
+	ctx->src_vbs[2] = ctx->src_vbs[1] = ctx->src_vbs[0] = NULL;
 
 	ret = realloc_mv_buffers(ctx, mv_buf_size);
 	if (ret)
 		return ret;
 
-	set_cfg_and_line_modes(ctx);
+	set_cfg_modes(ctx);
 	set_dei_regs(ctx);
 
 	csc_set_coeff(ctx->dev->csc, &mmr_adb->csc_regs[0],
@@ -881,15 +932,14 @@ static struct vpe_ctx *file2ctx(struct f
 static int job_ready(void *priv)
 {
 	struct vpe_ctx *ctx = priv;
-	int needed = ctx->bufs_per_job;
-
-	if (ctx->deinterlacing && ctx->src_vbs[2] == NULL)
-		needed += 2;	/* need additional two most recent fields */
-
-	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < needed)
-		return 0;
 
-	if (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < needed)
+	/*
+	 * This check is needed as this might be called directly from driver
+	 * When called by m2m framework, this will always satisfy, but when
+	 * called from vpe_irq, this might fail. (src stream with zero buffers)
+	 */
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) <= 0 ||
+		v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) <= 0)
 		return 0;
 
 	return 1;
@@ -993,22 +1043,38 @@ static void add_out_dtd(struct vpe_ctx *
 	int mv_buf_selector = !ctx->src_mv_buf_selector;
 	dma_addr_t dma_addr;
 	u32 flags = 0;
+	u32 offset = 0;
 
 	if (port == VPE_PORT_MV_OUT) {
 		vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
 		dma_addr = ctx->mv_buf_dma[mv_buf_selector];
+		q_data = &ctx->q_data[Q_DATA_SRC];
 	} else {
 		/* to incorporate interleaved formats */
 		int plane = fmt->coplanar ? p_data->vb_part : 0;
 
 		vpdma_fmt = fmt->vpdma_fmt[plane];
-		dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
+		/*
+		 * If we are using a single plane buffer and
+		 * we need to set a separate vpdma chroma channel.
+		 */
+		if (q_data->nplanes == 1 && plane) {
+			dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+			/* Compute required offset */
+			offset = q_data->bytesperline[0] * q_data->height;
+		} else {
+			dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
+			/* Use address as is, no offset */
+			offset = 0;
+		}
 		if (!dma_addr) {
 			vpe_err(ctx->dev,
 				"acquiring output buffer(%d) dma_addr failed\n",
 				port);
 			return;
 		}
+		/* Apply the offset */
+		dma_addr += offset;
 	}
 
 	if (q_data->flags & Q_DATA_FRAME_1D)
@@ -1016,8 +1082,12 @@ static void add_out_dtd(struct vpe_ctx *
 	if (q_data->flags & Q_DATA_MODE_TILED)
 		flags |= VPDMA_DATA_MODE_TILED;
 
+	vpdma_set_max_size(ctx->dev->vpdma, VPDMA_MAX_SIZE1,
+			   MAX_W, MAX_H);
+
 	vpdma_add_out_dtd(&ctx->desc_list, q_data->width, &q_data->c_rect,
-		vpdma_fmt, dma_addr, p_data->channel, flags);
+			  vpdma_fmt, dma_addr, MAX_OUT_WIDTH_REG1,
+			  MAX_OUT_HEIGHT_REG1, p_data->channel, flags);
 }
 
 static void add_in_dtd(struct vpe_ctx *ctx, int port)
@@ -1033,6 +1103,7 @@ static void add_in_dtd(struct vpe_ctx *c
 	int frame_width, frame_height;
 	dma_addr_t dma_addr;
 	u32 flags = 0;
+	u32 offset = 0;
 
 	if (port == VPE_PORT_MV_IN) {
 		vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
@@ -1042,14 +1113,49 @@ static void add_in_dtd(struct vpe_ctx *c
 		int plane = fmt->coplanar ? p_data->vb_part : 0;
 
 		vpdma_fmt = fmt->vpdma_fmt[plane];
-
-		dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
+		/*
+		 * If we are using a single plane buffer and
+		 * we need to set a separate vpdma chroma channel.
+		 */
+		if (q_data->nplanes == 1 && plane) {
+			dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+			/* Compute required offset */
+			offset = q_data->bytesperline[0] * q_data->height;
+		} else {
+			dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
+			/* Use address as is, no offset */
+			offset = 0;
+		}
 		if (!dma_addr) {
 			vpe_err(ctx->dev,
-				"acquiring input buffer(%d) dma_addr failed\n",
+				"acquiring output buffer(%d) dma_addr failed\n",
 				port);
 			return;
 		}
+		/* Apply the offset */
+		dma_addr += offset;
+
+		if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB) {
+			/*
+			 * Use top or bottom field from same vb alternately
+			 * f,f-1,f-2 = TBT when seq is even
+			 * f,f-1,f-2 = BTB when seq is odd
+			 */
+			field = (p_data->vb_index + (ctx->sequence % 2)) % 2;
+
+			if (field) {
+				/*
+				 * bottom field of a SEQ_TB buffer
+				 * Skip the top field data by
+				 */
+				int height = q_data->height / 2;
+				int bpp = fmt->fourcc == V4L2_PIX_FMT_NV12 ?
+						1 : (vpdma_fmt->depth >> 3);
+				if (plane)
+					height /= 2;
+				dma_addr += q_data->width * height * bpp;
+			}
+		}
 	}
 
 	if (q_data->flags & Q_DATA_FRAME_1D)
@@ -1077,7 +1183,7 @@ static void enable_irqs(struct vpe_ctx *
 	write_reg(ctx->dev, VPE_INT0_ENABLE1_SET, VPE_DEI_ERROR_INT |
 				VPE_DS1_UV_ERROR_INT);
 
-	vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, true);
+	vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, 0, true);
 }
 
 static void disable_irqs(struct vpe_ctx *ctx)
@@ -1085,7 +1191,7 @@ static void disable_irqs(struct vpe_ctx
 	write_reg(ctx->dev, VPE_INT0_ENABLE0_CLR, 0xffffffff);
 	write_reg(ctx->dev, VPE_INT0_ENABLE1_CLR, 0xffffffff);
 
-	vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, false);
+	vpdma_enable_list_complete_irq(ctx->dev->vpdma, 0, 0, false);
 }
 
 /* device_run() - prepares and starts the device
@@ -1098,23 +1204,49 @@ static void device_run(void *priv)
 	struct vpe_ctx *ctx = priv;
 	struct sc_data *sc = ctx->dev->sc;
 	struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST];
+	struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC];
 
-	if (ctx->deinterlacing && ctx->src_vbs[2] == NULL) {
-		ctx->src_vbs[2] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-		WARN_ON(ctx->src_vbs[2] == NULL);
-		ctx->src_vbs[1] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-		WARN_ON(ctx->src_vbs[1] == NULL);
+	if (ctx->deinterlacing && s_q_data->flags & Q_DATA_INTERLACED_SEQ_TB &&
+		ctx->sequence % 2 == 0) {
+		/* When using SEQ_TB buffers, When using it first time,
+		 * No need to remove the buffer as the next field is present
+		 * in the same buffer. (so that job_ready won't fail)
+		 * It will be removed when using bottom field
+		 */
+		ctx->src_vbs[0] = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+		WARN_ON(ctx->src_vbs[0] == NULL);
+	} else {
+		ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		WARN_ON(ctx->src_vbs[0] == NULL);
 	}
 
-	ctx->src_vbs[0] = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	WARN_ON(ctx->src_vbs[0] == NULL);
 	ctx->dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
 	WARN_ON(ctx->dst_vb == NULL);
 
+	if (ctx->deinterlacing) {
+
+		if (ctx->src_vbs[2] == NULL) {
+			ctx->src_vbs[2] = ctx->src_vbs[0];
+			WARN_ON(ctx->src_vbs[2] == NULL);
+			ctx->src_vbs[1] = ctx->src_vbs[0];
+			WARN_ON(ctx->src_vbs[1] == NULL);
+		}
+
+		/*
+		 * we have output the first 2 frames through line average, we
+		 * now switch to EDI de-interlacer
+		 */
+		if (ctx->sequence == 2)
+			config_edi_input_mode(ctx, 0x3); /* EDI (Y + UV) */
+	}
+
 	/* config descriptors */
 	if (ctx->dev->loaded_mmrs != ctx->mmr_adb.dma_addr || ctx->load_mmrs) {
 		vpdma_map_desc_buf(ctx->dev->vpdma, &ctx->mmr_adb);
 		vpdma_add_cfd_adb(&ctx->desc_list, CFD_MMR_CLIENT, &ctx->mmr_adb);
+
+		set_line_modes(ctx);
+
 		ctx->dev->loaded_mmrs = ctx->mmr_adb.dma_addr;
 		ctx->load_mmrs = false;
 	}
@@ -1202,7 +1334,7 @@ static void device_run(void *priv)
 	enable_irqs(ctx);
 
 	vpdma_map_desc_buf(ctx->dev->vpdma, &ctx->desc_list.buf);
-	vpdma_submit_descs(ctx->dev->vpdma, &ctx->desc_list);
+	vpdma_submit_descs(ctx->dev->vpdma, &ctx->desc_list, 0);
 }
 
 static void dei_error(struct vpe_ctx *ctx)
@@ -1225,6 +1357,7 @@ static irqreturn_t vpe_irq(int irq_vpe,
 	struct vb2_v4l2_buffer *s_vb, *d_vb;
 	unsigned long flags;
 	u32 irqst0, irqst1;
+	bool list_complete = false;
 
 	irqst0 = read_reg(dev, VPE_INT0_STATUS0);
 	if (irqst0) {
@@ -1257,17 +1390,24 @@ static irqreturn_t vpe_irq(int irq_vpe,
 
 	if (irqst0) {
 		if (irqst0 & VPE_INT0_LIST0_COMPLETE)
-			vpdma_clear_list_stat(ctx->dev->vpdma);
+			vpdma_clear_list_stat(ctx->dev->vpdma, 0, 0);
 
 		irqst0 &= ~(VPE_INT0_LIST0_COMPLETE);
+		list_complete = true;
 	}
 
 	if (irqst0 | irqst1) {
-		dev_warn(dev->v4l2_dev.dev, "Unexpected interrupt: "
-			"INT0_STATUS0 = 0x%08x, INT0_STATUS1 = 0x%08x\n",
+		dev_warn(dev->v4l2_dev.dev, "Unexpected interrupt: INT0_STATUS0 = 0x%08x, INT0_STATUS1 = 0x%08x\n",
 			irqst0, irqst1);
 	}
 
+	/*
+	 * Setup next operation only when list complete IRQ occurs
+	 * otherwise, skip the following code
+	 */
+	if (!list_complete)
+		goto handled;
+
 	disable_irqs(ctx);
 
 	vpdma_unmap_desc_buf(dev->vpdma, &ctx->desc_list.buf);
@@ -1295,7 +1435,7 @@ static irqreturn_t vpe_irq(int irq_vpe,
 	d_vb->sequence = ctx->sequence;
 
 	d_q_data = &ctx->q_data[Q_DATA_DST];
-	if (d_q_data->flags & Q_DATA_INTERLACED) {
+	if (d_q_data->flags & Q_IS_INTERLACED) {
 		d_vb->field = ctx->field;
 		if (ctx->field == V4L2_FIELD_BOTTOM) {
 			ctx->sequence++;
@@ -1309,12 +1449,28 @@ static irqreturn_t vpe_irq(int irq_vpe,
 		ctx->sequence++;
 	}
 
-	if (ctx->deinterlacing)
-		s_vb = ctx->src_vbs[2];
+	if (ctx->deinterlacing) {
+		/*
+		 * Allow source buffer to be dequeued only if it won't be used
+		 * in the next iteration. All vbs are initialized to first
+		 * buffer and we are shifting buffers every iteration, for the
+		 * first two iterations, no buffer will be dequeued.
+		 * This ensures that driver will keep (n-2)th (n-1)th and (n)th
+		 * field when deinterlacing is enabled
+		 */
+		if (ctx->src_vbs[2] != ctx->src_vbs[1])
+			s_vb = ctx->src_vbs[2];
+		else
+			s_vb = NULL;
+	}
 
 	spin_lock_irqsave(&dev->lock, flags);
-	v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_DONE);
+
+	if (s_vb)
+		v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_DONE);
+
 	v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_DONE);
+
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	if (ctx->deinterlacing) {
@@ -1322,8 +1478,16 @@ static irqreturn_t vpe_irq(int irq_vpe,
 		ctx->src_vbs[1] = ctx->src_vbs[0];
 	}
 
+	/*
+	 * Since the vb2_buf_done has already been called fir therse
+	 * buffer we can now NULL them out so that we won't try
+	 * to clean out stray pointer later on.
+	*/
+	ctx->src_vbs[0] = NULL;
+	ctx->dst_vb = NULL;
+
 	ctx->bufs_completed++;
-	if (ctx->bufs_completed < ctx->bufs_per_job) {
+	if (ctx->bufs_completed < ctx->bufs_per_job && job_ready(ctx)) {
 		device_run(ctx);
 		goto handled;
 	}
@@ -1414,7 +1578,7 @@ static int vpe_g_fmt(struct file *file,
 		pix->colorspace = s_q_data->colorspace;
 	}
 
-	pix->num_planes = q_data->fmt->coplanar ? 2 : 1;
+	pix->num_planes = q_data->nplanes;
 
 	for (i = 0; i < pix->num_planes; i++) {
 		pix->plane_fmt[i].bytesperline = q_data->bytesperline[i];
@@ -1430,7 +1594,7 @@ static int __vpe_try_fmt(struct vpe_ctx
 	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
 	struct v4l2_plane_pix_format *plane_fmt;
 	unsigned int w_align;
-	int i, depth, depth_bytes;
+	int i, depth, depth_bytes, height;
 
 	if (!fmt || !(fmt->types & type)) {
 		vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n",
@@ -1438,7 +1602,8 @@ static int __vpe_try_fmt(struct vpe_ctx
 		return -EINVAL;
 	}
 
-	if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE)
+	if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE
+			&& pix->field != V4L2_FIELD_SEQ_TB)
 		pix->field = V4L2_FIELD_NONE;
 
 	depth = fmt->vpdma_fmt[VPE_LUMA]->depth;
@@ -1450,28 +1615,53 @@ static int __vpe_try_fmt(struct vpe_ctx
 	 */
 	depth_bytes = depth >> 3;
 
-	if (depth_bytes == 3)
+	if (depth_bytes == 3) {
 		/*
 		 * if bpp is 3(as in some RGB formats), the pixel width doesn't
 		 * really help in ensuring line stride is 16 byte aligned
 		 */
 		w_align = 4;
-	else
+	} else {
 		/*
 		 * for the remainder bpp(4, 2 and 1), the pixel width alignment
 		 * can ensure a line stride alignment of 16 bytes. For example,
 		 * if bpp is 2, then the line stride can be 16 byte aligned if
 		 * the width is 8 byte aligned
 		 */
-		w_align = order_base_2(VPDMA_DESC_ALIGN / depth_bytes);
+
+		/*
+		 * HACK: using order_base_2() here causes lots of asm output
+		 * errors with smatch, on i386:
+		 * ./arch/x86/include/asm/bitops.h:457:22:
+		 *		 warning: asm output is not an lvalue
+		 * Perhaps some gcc optimization is doing the wrong thing
+		 * there.
+		 * Let's get rid of them by doing the calculus on two steps
+		 */
+		w_align = roundup_pow_of_two(VPDMA_DESC_ALIGN / depth_bytes);
+		w_align = ilog2(w_align);
+	}
 
 	v4l_bound_align_image(&pix->width, MIN_W, MAX_W, w_align,
 			      &pix->height, MIN_H, MAX_H, H_ALIGN,
 			      S_ALIGN);
 
-	pix->num_planes = fmt->coplanar ? 2 : 1;
+	if (!pix->num_planes)
+		pix->num_planes = fmt->coplanar ? 2 : 1;
+	else if (pix->num_planes > 1 && !fmt->coplanar)
+		pix->num_planes = 1;
+
 	pix->pixelformat = fmt->fourcc;
 
+	/*
+	 * For the actual image parameters, we need to consider the field
+	 * height of the image for SEQ_TB buffers.
+	 */
+	if (pix->field == V4L2_FIELD_SEQ_TB)
+		height = pix->height / 2;
+	else
+		height = pix->height;
+
 	if (!pix->colorspace) {
 		if (fmt->fourcc == V4L2_PIX_FMT_RGB24 ||
 				fmt->fourcc == V4L2_PIX_FMT_BGR24 ||
@@ -1479,7 +1669,7 @@ static int __vpe_try_fmt(struct vpe_ctx
 				fmt->fourcc == V4L2_PIX_FMT_BGR32) {
 			pix->colorspace = V4L2_COLORSPACE_SRGB;
 		} else {
-			if (pix->height > 1280)	/* HD */
+			if (height > 1280)	/* HD */
 				pix->colorspace = V4L2_COLORSPACE_REC709;
 			else			/* SD */
 				pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -1496,6 +1686,8 @@ static int __vpe_try_fmt(struct vpe_ctx
 		else
 			plane_fmt->bytesperline = pix->width;
 
+		if (pix->num_planes == 1 && fmt->coplanar)
+			depth += fmt->vpdma_fmt[VPE_CHROMA]->depth;
 		plane_fmt->sizeimage =
 				(pix->height * pix->width * depth) >> 3;
 
@@ -1542,6 +1734,7 @@ static int __vpe_s_fmt(struct vpe_ctx *c
 	q_data->height		= pix->height;
 	q_data->colorspace	= pix->colorspace;
 	q_data->field		= pix->field;
+	q_data->nplanes		= pix->num_planes;
 
 	for (i = 0; i < pix->num_planes; i++) {
 		plane_fmt = &pix->plane_fmt[i];
@@ -1556,14 +1749,20 @@ static int __vpe_s_fmt(struct vpe_ctx *c
 	q_data->c_rect.height	= q_data->height;
 
 	if (q_data->field == V4L2_FIELD_ALTERNATE)
-		q_data->flags |= Q_DATA_INTERLACED;
+		q_data->flags |= Q_DATA_INTERLACED_ALTERNATE;
+	else if (q_data->field == V4L2_FIELD_SEQ_TB)
+		q_data->flags |= Q_DATA_INTERLACED_SEQ_TB;
 	else
-		q_data->flags &= ~Q_DATA_INTERLACED;
+		q_data->flags &= ~Q_IS_INTERLACED;
+
+	/* the crop height is halved for the case of SEQ_TB buffers */
+	if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB)
+		q_data->c_rect.height /= 2;
 
 	vpe_dbg(ctx->dev, "Setting format for type %d, wxh: %dx%d, fmt: %d bpl_y %d",
 		f->type, q_data->width, q_data->height, q_data->fmt->fourcc,
 		q_data->bytesperline[VPE_LUMA]);
-	if (q_data->fmt->coplanar)
+	if (q_data->nplanes == 2)
 		vpe_dbg(ctx->dev, " bpl_uv %d\n",
 			q_data->bytesperline[VPE_CHROMA]);
 
@@ -1594,6 +1793,7 @@ static int vpe_s_fmt(struct file *file,
 static int __vpe_try_selection(struct vpe_ctx *ctx, struct v4l2_selection *s)
 {
 	struct vpe_q_data *q_data;
+	int height;
 
 	if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
 	    (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT))
@@ -1628,13 +1828,22 @@ static int __vpe_try_selection(struct vp
 		return -EINVAL;
 	}
 
+	/*
+	 * For SEQ_TB buffers, crop height should be less than the height of
+	 * the field height, not the buffer height
+	 */
+	if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB)
+		height = q_data->height / 2;
+	else
+		height = q_data->height;
+
 	if (s->r.top < 0 || s->r.left < 0) {
 		vpe_err(ctx->dev, "negative values for top and left\n");
 		s->r.top = s->r.left = 0;
 	}
 
 	v4l_bound_align_image(&s->r.width, MIN_W, q_data->width, 1,
-		&s->r.height, MIN_H, q_data->height, H_ALIGN, S_ALIGN);
+		&s->r.height, MIN_H, height, H_ALIGN, S_ALIGN);
 
 	/* adjust left/top if cropping rectangle is out of bounds */
 	if (s->r.left + s->r.width > q_data->width)
@@ -1784,6 +1993,7 @@ static const struct v4l2_ioctl_ops vpe_i
 	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
 	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
 	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
+	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
 	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
 	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
 
@@ -1804,14 +2014,14 @@ static int vpe_queue_setup(struct vb2_qu
 
 	q_data = get_q_data(ctx, vq->type);
 
-	*nplanes = q_data->fmt->coplanar ? 2 : 1;
+	*nplanes = q_data->nplanes;
 
 	for (i = 0; i < *nplanes; i++)
 		sizes[i] = q_data->sizeimage[i];
 
 	vpe_dbg(ctx->dev, "get %d buffer(s) of size %d", *nbuffers,
 		sizes[VPE_LUMA]);
-	if (q_data->fmt->coplanar)
+	if (q_data->nplanes == 2)
 		vpe_dbg(ctx->dev, " and %d\n", sizes[VPE_CHROMA]);
 
 	return 0;
@@ -1827,14 +2037,15 @@ static int vpe_buf_prepare(struct vb2_bu
 	vpe_dbg(ctx->dev, "type: %d\n", vb->vb2_queue->type);
 
 	q_data = get_q_data(ctx, vb->vb2_queue->type);
-	num_planes = q_data->fmt->coplanar ? 2 : 1;
+	num_planes = q_data->nplanes;
 
 	if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		if (!(q_data->flags & Q_DATA_INTERLACED)) {
+		if (!(q_data->flags & Q_IS_INTERLACED)) {
 			vbuf->field = V4L2_FIELD_NONE;
 		} else {
 			if (vbuf->field != V4L2_FIELD_TOP &&
-					vbuf->field != V4L2_FIELD_BOTTOM)
+			    vbuf->field != V4L2_FIELD_BOTTOM &&
+			    vbuf->field != V4L2_FIELD_SEQ_TB)
 				return -EINVAL;
 		}
 	}
@@ -1863,9 +2074,98 @@ static void vpe_buf_queue(struct vb2_buf
 	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
 }
 
+static int check_srcdst_sizes(struct vpe_ctx *ctx)
+{
+	struct vpe_q_data *s_q_data =  &ctx->q_data[Q_DATA_SRC];
+	struct vpe_q_data *d_q_data =  &ctx->q_data[Q_DATA_DST];
+	unsigned int src_w = s_q_data->c_rect.width;
+	unsigned int src_h = s_q_data->c_rect.height;
+	unsigned int dst_w = d_q_data->c_rect.width;
+	unsigned int dst_h = d_q_data->c_rect.height;
+
+	if (src_w == dst_w && src_h == dst_h)
+		return 0;
+
+	if (src_h <= SC_MAX_PIXEL_HEIGHT &&
+	    src_w <= SC_MAX_PIXEL_WIDTH &&
+	    dst_h <= SC_MAX_PIXEL_HEIGHT &&
+	    dst_w <= SC_MAX_PIXEL_WIDTH)
+		return 0;
+
+	return -1;
+}
+
+static void vpe_return_all_buffers(struct vpe_ctx *ctx,  struct vb2_queue *q,
+				   enum vb2_buffer_state state)
+{
+	struct vb2_v4l2_buffer *vb;
+	unsigned long flags;
+
+	for (;;) {
+		if (V4L2_TYPE_IS_OUTPUT(q->type))
+			vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		else
+			vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+		if (!vb)
+			break;
+		spin_lock_irqsave(&ctx->dev->lock, flags);
+		v4l2_m2m_buf_done(vb, state);
+		spin_unlock_irqrestore(&ctx->dev->lock, flags);
+	}
+
+	/*
+	 * Cleanup the in-transit vb2 buffers that have been
+	 * removed from their respective queue already but for
+	 * which procecessing has not been completed yet.
+	 */
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		spin_lock_irqsave(&ctx->dev->lock, flags);
+
+		if (ctx->src_vbs[2])
+			v4l2_m2m_buf_done(ctx->src_vbs[2], state);
+
+		if (ctx->src_vbs[1] && (ctx->src_vbs[1] != ctx->src_vbs[2]))
+			v4l2_m2m_buf_done(ctx->src_vbs[1], state);
+
+		if (ctx->src_vbs[0] &&
+		    (ctx->src_vbs[0] != ctx->src_vbs[1]) &&
+		    (ctx->src_vbs[0] != ctx->src_vbs[2]))
+			v4l2_m2m_buf_done(ctx->src_vbs[0], state);
+
+		ctx->src_vbs[2] = NULL;
+		ctx->src_vbs[1] = NULL;
+		ctx->src_vbs[0] = NULL;
+
+		spin_unlock_irqrestore(&ctx->dev->lock, flags);
+	} else {
+		if (ctx->dst_vb) {
+			spin_lock_irqsave(&ctx->dev->lock, flags);
+
+			v4l2_m2m_buf_done(ctx->dst_vb, state);
+			ctx->dst_vb = NULL;
+			spin_unlock_irqrestore(&ctx->dev->lock, flags);
+		}
+	}
+}
+
 static int vpe_start_streaming(struct vb2_queue *q, unsigned int count)
 {
-	/* currently we do nothing here */
+	struct vpe_ctx *ctx = vb2_get_drv_priv(q);
+
+	/* Check any of the size exceed maximum scaling sizes */
+	if (check_srcdst_sizes(ctx)) {
+		vpe_err(ctx->dev,
+			"Conversion setup failed, check source and destination parameters\n"
+			);
+		vpe_return_all_buffers(ctx, q, VB2_BUF_STATE_QUEUED);
+		return -EINVAL;
+	}
+
+	if (ctx->deinterlacing)
+		config_edi_input_mode(ctx, 0x0);
+
+	if (ctx->sequence != 0)
+		set_srcdst_params(ctx);
 
 	return 0;
 }
@@ -1876,6 +2176,8 @@ static void vpe_stop_streaming(struct vb
 
 	vpe_dump_regs(ctx->dev);
 	vpdma_dump_regs(ctx->dev->vpdma);
+
+	vpe_return_all_buffers(ctx, q, VB2_BUF_STATE_ERROR);
 }
 
 static const struct vb2_ops vpe_qops = {
@@ -1995,6 +2297,7 @@ static int vpe_open(struct file *file)
 	s_q_data->fmt = &vpe_formats[2];
 	s_q_data->width = 1920;
 	s_q_data->height = 1080;
+	s_q_data->nplanes = 1;
 	s_q_data->bytesperline[VPE_LUMA] = (s_q_data->width *
 			s_q_data->fmt->vpdma_fmt[VPE_LUMA]->depth) >> 3;
 	s_q_data->sizeimage[VPE_LUMA] = (s_q_data->bytesperline[VPE_LUMA] *
@@ -2068,11 +2371,13 @@ static int vpe_release(struct file *file
 	vpe_dbg(dev, "releasing instance %p\n", ctx);
 
 	mutex_lock(&dev->dev_mutex);
-	free_vbs(ctx);
 	free_mv_buffers(ctx);
 	vpdma_free_desc_list(&ctx->desc_list);
 	vpdma_free_desc_buf(&ctx->mmr_adb);
 
+	vpdma_free_desc_buf(&ctx->sc_coeff_v);
+	vpdma_free_desc_buf(&ctx->sc_coeff_h);
+
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	v4l2_ctrl_handler_free(&ctx->hdl);
@@ -2235,23 +2540,22 @@ static int vpe_probe(struct platform_dev
 
 	vpe_top_vpdma_reset(dev);
 
-	dev->sc = sc_create(pdev);
+	dev->sc = sc_create(pdev, "sc");
 	if (IS_ERR(dev->sc)) {
 		ret = PTR_ERR(dev->sc);
 		goto runtime_put;
 	}
 
-	dev->csc = csc_create(pdev);
+	dev->csc = csc_create(pdev, "csc");
 	if (IS_ERR(dev->csc)) {
 		ret = PTR_ERR(dev->csc);
 		goto runtime_put;
 	}
 
-	dev->vpdma = vpdma_create(pdev, vpe_fw_cb);
-	if (IS_ERR(dev->vpdma)) {
-		ret = PTR_ERR(dev->vpdma);
+	dev->vpdma = &dev->vpdma_data;
+	ret = vpdma_create(pdev, dev->vpdma, vpe_fw_cb);
+	if (ret)
 		goto runtime_put;
-	}
 
 	return 0;
 
@@ -2290,6 +2594,7 @@ static const struct of_device_id vpe_of_
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, vpe_of_match);
 #endif
 
 static struct platform_driver vpe_pdrv = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/via-camera.c linux-libre-4.10-rc8-gnu/drivers/media/platform/via-camera.c
--- linux-libre-4.9-gnu/drivers/media/platform/via-camera.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/via-camera.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,15 +39,12 @@ MODULE_LICENSE("GPL");
 static bool flip_image;
 module_param(flip_image, bool, 0444);
 MODULE_PARM_DESC(flip_image,
-		"If set, the sensor will be instructed to flip the image "
-		"vertically.");
+		"If set, the sensor will be instructed to flip the image vertically.");
 
 static bool override_serial;
 module_param(override_serial, bool, 0444);
 MODULE_PARM_DESC(override_serial,
-		"The camera driver will normally refuse to load if "
-		"the XO 1.5 serial port is enabled.  Set this option "
-		"to force-enable the camera.");
+		"The camera driver will normally refuse to load if the XO 1.5 serial port is enabled.  Set this option to force-enable the camera.");
 
 /*
  * The structure describing our camera.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/Kconfig
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@ config VIDEO_VIVID
 
 config VIDEO_VIVID_CEC
 	bool "Enable CEC emulation support"
-	depends on VIDEO_VIVID && MEDIA_CEC
+	depends on VIDEO_VIVID && MEDIA_CEC_SUPPORT
 	---help---
 	  When selected the vivid module will emulate the optional
 	  HDMI CEC feature.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-cec.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-cec.c
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-cec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-cec.c	2017-02-12 16:03:20.000000000 -0500
@@ -216,7 +216,6 @@ static const struct cec_adap_ops vivid_c
 
 struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
 					 unsigned int idx,
-					 struct device *parent,
 					 bool is_source)
 {
 	char name[sizeof(dev->vid_out_dev.name) + 2];
@@ -227,5 +226,5 @@ struct cec_adapter *vivid_cec_alloc_adap
 		 is_source ? dev->vid_out_dev.name : dev->vid_cap_dev.name,
 		 idx);
 	return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
-		name, caps, 1, parent);
+		name, caps, 1);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-cec.h linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-cec.h
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-cec.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-cec.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,6 @@
 #ifdef CONFIG_VIDEO_VIVID_CEC
 struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
 					 unsigned int idx,
-					 struct device *parent,
 					 bool is_source);
 void vivid_cec_bus_free_work(struct vivid_dev *dev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-core.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-core.c
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -183,7 +183,7 @@ static const u8 vivid_hdmi_edid[256] = {
 	0x5e, 0x5d, 0x10, 0x1f, 0x04, 0x13, 0x22, 0x21,
 	0x20, 0x05, 0x14, 0x02, 0x11, 0x01, 0x23, 0x09,
 	0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x6d, 0x03,
-	0x0c, 0x00, 0x10, 0x00, 0x00, 0x78, 0x21, 0x00,
+	0x0c, 0x00, 0x10, 0x00, 0x00, 0x3c, 0x21, 0x00,
 	0x60, 0x01, 0x02, 0x03, 0x67, 0xd8, 0x5d, 0xc4,
 	0x01, 0x78, 0x00, 0x00, 0xe2, 0x00, 0xea, 0xe3,
 	0x05, 0x00, 0x00, 0xe3, 0x06, 0x01, 0x00, 0x4d,
@@ -194,7 +194,7 @@ static const u8 vivid_hdmi_edid[256] = {
 	0x00, 0x00, 0x1a, 0x1a, 0x1d, 0x00, 0x80, 0x51,
 	0xd0, 0x1c, 0x20, 0x40, 0x80, 0x35, 0x00, 0xc0,
 	0x1c, 0x32, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x27,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
 };
 
 static int vidioc_querycap(struct file *file, void  *priv,
@@ -1167,12 +1167,12 @@ static int vivid_create_instance(struct
 		if (in_type_counter[HDMI]) {
 			struct cec_adapter *adap;
 
-			adap = vivid_cec_alloc_adap(dev, 0, &pdev->dev, false);
+			adap = vivid_cec_alloc_adap(dev, 0, false);
 			ret = PTR_ERR_OR_ZERO(adap);
 			if (ret < 0)
 				goto unreg_dev;
 			dev->cec_rx_adap = adap;
-			ret = cec_register_adapter(adap);
+			ret = cec_register_adapter(adap, &pdev->dev);
 			if (ret < 0) {
 				cec_delete_adapter(adap);
 				dev->cec_rx_adap = NULL;
@@ -1222,13 +1222,12 @@ static int vivid_create_instance(struct
 			if (dev->output_type[i] != HDMI)
 				continue;
 			dev->cec_output2bus_map[i] = bus_cnt;
-			adap = vivid_cec_alloc_adap(dev, bus_cnt,
-						     &pdev->dev, true);
+			adap = vivid_cec_alloc_adap(dev, bus_cnt, true);
 			ret = PTR_ERR_OR_ZERO(adap);
 			if (ret < 0)
 				goto unreg_dev;
 			dev->cec_tx_adap[bus_cnt] = adap;
-			ret = cec_register_adapter(adap);
+			ret = cec_register_adapter(adap, &pdev->dev);
 			if (ret < 0) {
 				cec_delete_adapter(adap);
 				dev->cec_tx_adap[bus_cnt] = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-core.h linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-core.h
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-core.h	2017-02-12 16:03:20.000000000 -0500
@@ -80,7 +80,7 @@ extern unsigned vivid_debug;
 
 struct vivid_fmt {
 	u32	fourcc;          /* v4l2 format id */
-	bool	is_yuv;
+	enum	tgp_color_enc color_enc;
 	bool	can_do_overlay;
 	u8	vdownsampling[TPG_MAX_PLANES];
 	u32	alpha_mask;
@@ -346,6 +346,7 @@ struct vivid_dev {
 	struct v4l2_dv_timings		dv_timings_out;
 	u32				colorspace_out;
 	u32				ycbcr_enc_out;
+	u32				hsv_enc_out;
 	u32				quantization_out;
 	u32				xfer_func_out;
 	u32				service_set_out;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-ctrls.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-ctrls.c
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-ctrls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-ctrls.c	2017-02-12 16:03:20.000000000 -0500
@@ -79,6 +79,7 @@
 #define VIVID_CID_MAX_EDID_BLOCKS	(VIVID_CID_VIVID_BASE + 40)
 #define VIVID_CID_PERCENTAGE_FILL	(VIVID_CID_VIVID_BASE + 41)
 #define VIVID_CID_REDUCED_FPS		(VIVID_CID_VIVID_BASE + 42)
+#define VIVID_CID_HSV_ENC		(VIVID_CID_VIVID_BASE + 43)
 
 #define VIVID_CID_STD_SIGNAL_MODE	(VIVID_CID_VIVID_BASE + 60)
 #define VIVID_CID_STANDARD		(VIVID_CID_VIVID_BASE + 61)
@@ -378,6 +379,14 @@ static int vivid_vid_cap_s_ctrl(struct v
 		vivid_send_source_change(dev, HDMI);
 		vivid_send_source_change(dev, WEBCAM);
 		break;
+	case VIVID_CID_HSV_ENC:
+		tpg_s_hsv_enc(&dev->tpg, ctrl->val ? V4L2_HSV_ENC_256 :
+						     V4L2_HSV_ENC_180);
+		vivid_send_source_change(dev, TV);
+		vivid_send_source_change(dev, SVID);
+		vivid_send_source_change(dev, HDMI);
+		vivid_send_source_change(dev, WEBCAM);
+		break;
 	case VIVID_CID_QUANTIZATION:
 		tpg_s_quantization(&dev->tpg, ctrl->val);
 		vivid_send_source_change(dev, TV);
@@ -778,6 +787,21 @@ static const struct v4l2_ctrl_config viv
 	.qmenu = vivid_ctrl_ycbcr_enc_strings,
 };
 
+static const char * const vivid_ctrl_hsv_enc_strings[] = {
+	"Hue 0-179",
+	"Hue 0-256",
+	NULL,
+};
+
+static const struct v4l2_ctrl_config vivid_ctrl_hsv_enc = {
+	.ops = &vivid_vid_cap_ctrl_ops,
+	.id = VIVID_CID_HSV_ENC,
+	.name = "HSV Encoding",
+	.type = V4L2_CTRL_TYPE_MENU,
+	.max = ARRAY_SIZE(vivid_ctrl_hsv_enc_strings) - 2,
+	.qmenu = vivid_ctrl_hsv_enc_strings,
+};
+
 static const char * const vivid_ctrl_quantization_strings[] = {
 	"Default",
 	"Full Range",
@@ -1454,6 +1478,7 @@ int vivid_create_controls(struct vivid_d
 			&vivid_ctrl_colorspace, NULL);
 		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_xfer_func, NULL);
 		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
+		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_hsv_enc, NULL);
 		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
 		v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-vid-cap.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-vid-cap.c
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-vid-cap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-vid-cap.c	2017-02-12 16:03:20.000000000 -0500
@@ -510,6 +510,13 @@ static unsigned vivid_ycbcr_enc_cap(stru
 	return dev->ycbcr_enc_out;
 }
 
+static unsigned int vivid_hsv_enc_cap(struct vivid_dev *dev)
+{
+	if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
+		return tpg_g_hsv_enc(&dev->tpg);
+	return dev->hsv_enc_out;
+}
+
 static unsigned vivid_quantization_cap(struct vivid_dev *dev)
 {
 	if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
@@ -530,7 +537,10 @@ int vivid_g_fmt_vid_cap(struct file *fil
 	mp->pixelformat  = dev->fmt_cap->fourcc;
 	mp->colorspace   = vivid_colorspace_cap(dev);
 	mp->xfer_func    = vivid_xfer_func_cap(dev);
-	mp->ycbcr_enc    = vivid_ycbcr_enc_cap(dev);
+	if (dev->fmt_cap->color_enc == TGP_COLOR_ENC_HSV)
+		mp->hsv_enc    = vivid_hsv_enc_cap(dev);
+	else
+		mp->ycbcr_enc    = vivid_ycbcr_enc_cap(dev);
 	mp->quantization = vivid_quantization_cap(dev);
 	mp->num_planes = dev->fmt_cap->buffers;
 	for (p = 0; p < mp->num_planes; p++) {
@@ -618,7 +628,10 @@ int vivid_try_fmt_vid_cap(struct file *f
 		memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
 	}
 	mp->colorspace = vivid_colorspace_cap(dev);
-	mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
+	if (fmt->color_enc == TGP_COLOR_ENC_HSV)
+		mp->hsv_enc = vivid_hsv_enc_cap(dev);
+	else
+		mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
 	mp->xfer_func = vivid_xfer_func_cap(dev);
 	mp->quantization = vivid_quantization_cap(dev);
 	memset(mp->reserved, 0, sizeof(mp->reserved));
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-vid-common.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-vid-common.c
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-vid-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-vid-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,7 +48,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YUYV,
 		.vdownsampling = { 1 },
 		.bit_depth = { 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 1,
 		.buffers = 1,
 		.data_offset = { PLANE0_DATA_OFFSET },
@@ -57,7 +57,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_UYVY,
 		.vdownsampling = { 1 },
 		.bit_depth = { 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 1,
 		.buffers = 1,
 	},
@@ -65,7 +65,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YVYU,
 		.vdownsampling = { 1 },
 		.bit_depth = { 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 1,
 		.buffers = 1,
 	},
@@ -73,7 +73,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_VYUY,
 		.vdownsampling = { 1 },
 		.bit_depth = { 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 1,
 		.buffers = 1,
 	},
@@ -81,7 +81,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YUV422P,
 		.vdownsampling = { 1, 1, 1 },
 		.bit_depth = { 8, 4, 4 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 1,
 	},
@@ -89,7 +89,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YUV420,
 		.vdownsampling = { 1, 2, 2 },
 		.bit_depth = { 8, 4, 4 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 1,
 	},
@@ -97,7 +97,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YVU420,
 		.vdownsampling = { 1, 2, 2 },
 		.bit_depth = { 8, 4, 4 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 1,
 	},
@@ -105,7 +105,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV12,
 		.vdownsampling = { 1, 2 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 1,
 	},
@@ -113,7 +113,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV21,
 		.vdownsampling = { 1, 2 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 1,
 	},
@@ -121,7 +121,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV16,
 		.vdownsampling = { 1, 1 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 1,
 	},
@@ -129,7 +129,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV61,
 		.vdownsampling = { 1, 1 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 1,
 	},
@@ -137,7 +137,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV24,
 		.vdownsampling = { 1, 1 },
 		.bit_depth = { 8, 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 1,
 	},
@@ -145,7 +145,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV42,
 		.vdownsampling = { 1, 1 },
 		.bit_depth = { 8, 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 1,
 	},
@@ -184,7 +184,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_GREY,
 		.vdownsampling = { 1 },
 		.bit_depth = { 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_LUMA,
 		.planes   = 1,
 		.buffers = 1,
 	},
@@ -192,7 +192,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_Y16,
 		.vdownsampling = { 1 },
 		.bit_depth = { 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_LUMA,
 		.planes   = 1,
 		.buffers = 1,
 	},
@@ -200,7 +200,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_Y16_BE,
 		.vdownsampling = { 1 },
 		.bit_depth = { 16 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_LUMA,
 		.planes   = 1,
 		.buffers = 1,
 	},
@@ -445,6 +445,22 @@ struct vivid_fmt vivid_formats[] = {
 		.planes   = 1,
 		.buffers = 1,
 	},
+	{
+		.fourcc   = V4L2_PIX_FMT_HSV24, /* HSV 24bits */
+		.color_enc = TGP_COLOR_ENC_HSV,
+		.vdownsampling = { 1 },
+		.bit_depth = { 24 },
+		.planes   = 1,
+		.buffers = 1,
+	},
+	{
+		.fourcc   = V4L2_PIX_FMT_HSV32, /* HSV 32bits */
+		.color_enc = TGP_COLOR_ENC_HSV,
+		.vdownsampling = { 1 },
+		.bit_depth = { 32 },
+		.planes   = 1,
+		.buffers = 1,
+	},
 
 	/* Multiplanar formats */
 
@@ -452,7 +468,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV16M,
 		.vdownsampling = { 1, 1 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 2,
 		.data_offset = { PLANE0_DATA_OFFSET, 0 },
@@ -461,7 +477,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV61M,
 		.vdownsampling = { 1, 1 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 2,
 		.data_offset = { 0, PLANE0_DATA_OFFSET },
@@ -470,7 +486,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YUV420M,
 		.vdownsampling = { 1, 2, 2 },
 		.bit_depth = { 8, 4, 4 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 3,
 	},
@@ -478,7 +494,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YVU420M,
 		.vdownsampling = { 1, 2, 2 },
 		.bit_depth = { 8, 4, 4 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 3,
 	},
@@ -486,7 +502,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV12M,
 		.vdownsampling = { 1, 2 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 2,
 	},
@@ -494,7 +510,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_NV21M,
 		.vdownsampling = { 1, 2 },
 		.bit_depth = { 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 2,
 		.buffers = 2,
 	},
@@ -502,7 +518,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YUV422M,
 		.vdownsampling = { 1, 1, 1 },
 		.bit_depth = { 8, 4, 4 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 3,
 	},
@@ -510,7 +526,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YVU422M,
 		.vdownsampling = { 1, 1, 1 },
 		.bit_depth = { 8, 4, 4 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 3,
 	},
@@ -518,7 +534,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YUV444M,
 		.vdownsampling = { 1, 1, 1 },
 		.bit_depth = { 8, 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 3,
 	},
@@ -526,7 +542,7 @@ struct vivid_fmt vivid_formats[] = {
 		.fourcc   = V4L2_PIX_FMT_YVU444M,
 		.vdownsampling = { 1, 1, 1 },
 		.bit_depth = { 8, 8, 8 },
-		.is_yuv   = true,
+		.color_enc = TGP_COLOR_ENC_YCBCR,
 		.planes   = 3,
 		.buffers = 3,
 	},
@@ -616,6 +632,7 @@ void fmt_sp2mp(const struct v4l2_format
 	mp->field = pix->field;
 	mp->colorspace = pix->colorspace;
 	mp->xfer_func = pix->xfer_func;
+	/* Also copies hsv_enc */
 	mp->ycbcr_enc = pix->ycbcr_enc;
 	mp->quantization = pix->quantization;
 	mp->num_planes = 1;
@@ -645,6 +662,7 @@ int fmt_sp2mp_func(struct file *file, vo
 	pix->field = mp->field;
 	pix->colorspace = mp->colorspace;
 	pix->xfer_func = mp->xfer_func;
+	/* Also copies hsv_enc */
 	pix->ycbcr_enc = mp->ycbcr_enc;
 	pix->quantization = mp->quantization;
 	pix->sizeimage = ppix->sizeimage;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-vid-out.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-vid-out.c
--- linux-libre-4.9-gnu/drivers/media/platform/vivid/vivid-vid-out.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vivid/vivid-vid-out.c	2017-02-12 16:03:20.000000000 -0500
@@ -256,6 +256,7 @@ void vivid_update_format_out(struct vivi
 	}
 	dev->xfer_func_out = V4L2_XFER_FUNC_DEFAULT;
 	dev->ycbcr_enc_out = V4L2_YCBCR_ENC_DEFAULT;
+	dev->hsv_enc_out = V4L2_HSV_ENC_180;
 	dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
 	dev->compose_out = dev->sink_rect;
 	dev->compose_bounds_out = dev->sink_rect;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_drv.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_drv.c
--- linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -770,6 +770,7 @@ static const struct of_device_id vsp1_of
 	{ .compatible = "renesas,vsp2" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, vsp1_of_match);
 
 static struct platform_driver vsp1_platform_driver = {
 	.probe		= vsp1_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_pipe.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_pipe.c
--- linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_pipe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_pipe.c	2017-02-12 16:03:20.000000000 -0500
@@ -78,6 +78,14 @@ static const struct vsp1_format_info vsp
 	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
 	  1, { 32, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_HSV24, MEDIA_BUS_FMT_AHSV8888_1X32,
+	  VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 24, 0, 0 }, false, false, 1, 1, false },
+	{ V4L2_PIX_FMT_HSV32, MEDIA_BUS_FMT_AHSV8888_1X32,
+	  VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+	  1, { 32, 0, 0 }, false, false, 1, 1, false },
 	{ V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
 	  VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
 	  VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_rwpf.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_rwpf.c
--- linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_rwpf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_rwpf.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@ static int vsp1_rwpf_enum_mbus_code(stru
 {
 	static const unsigned int codes[] = {
 		MEDIA_BUS_FMT_ARGB8888_1X32,
+		MEDIA_BUS_FMT_AHSV8888_1X32,
 		MEDIA_BUS_FMT_AYUV8_1X32,
 	};
 
@@ -78,6 +79,7 @@ static int vsp1_rwpf_set_format(struct v
 
 	/* Default to YUV if the requested format is not supported. */
 	if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
+	    fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
 	    fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
 		fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_video.c linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_video.c
--- linux-libre-4.9-gnu/drivers/media/platform/vsp1/vsp1_video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/platform/vsp1/vsp1_video.c	2017-02-12 16:03:20.000000000 -0500
@@ -124,6 +124,11 @@ static int __vsp1_video_try_format(struc
 	pix->pixelformat = info->fourcc;
 	pix->colorspace = V4L2_COLORSPACE_SRGB;
 	pix->field = V4L2_FIELD_NONE;
+
+	if (info->fourcc == V4L2_PIX_FMT_HSV24 ||
+	    info->fourcc == V4L2_PIX_FMT_HSV32)
+		pix->hsv_enc = V4L2_HSV_ENC_256;
+
 	memset(pix->reserved, 0, sizeof(pix->reserved));
 
 	/* Align the width and height for YUV 4:2:2 and 4:2:0 formats. */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/radio/radio-gemtek.c linux-libre-4.10-rc8-gnu/drivers/media/radio/radio-gemtek.c
--- linux-libre-4.9-gnu/drivers/media/radio/radio-gemtek.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/radio/radio-gemtek.c	2017-02-12 16:03:20.000000000 -0500
@@ -67,14 +67,10 @@ module_param(probe, bool, 0444);
 MODULE_PARM_DESC(probe, "Enable automatic device probing.");
 
 module_param(hardmute, bool, 0644);
-MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may "
-	 "reduce static noise.");
+MODULE_PARM_DESC(hardmute, "Enable 'hard muting' by shutting down PLL, may reduce static noise.");
 
 module_param_array(io, int, NULL, 0444);
-MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic "
-	 "probing is disabled or fails. The most common I/O ports are: 0x20c "
-	 "0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to "
-	 "work for the combined sound/radiocard).");
+MODULE_PARM_DESC(io, "Force I/O ports for the GemTek Radio card if automatic probing is disabled or fails. The most common I/O ports are: 0x20c 0x30c, 0x24c or 0x34c (0x20c, 0x248 and 0x28c have been reported to work for the combined sound/radiocard).");
 
 module_param_array(radio_nr, int, NULL, 0444);
 MODULE_PARM_DESC(radio_nr, "Radio device numbers");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/radio/radio-wl1273.c linux-libre-4.10-rc8-gnu/drivers/media/radio/radio-wl1273.c
--- linux-libre-4.9-gnu/drivers/media/radio/radio-wl1273.c	2016-12-11 17:48:36.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/radio/radio-wl1273.c	2017-02-12 17:36:30.000000000 -0500
@@ -2068,8 +2068,7 @@ static int wl1273_fm_radio_probe(struct
 			goto err_request_irq;
 		}
 	} else {
-		dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ"
-			" not configured");
+		dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ not configured");
 		r = -EINVAL;
 		goto pdata_err;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/radio/si470x/radio-si470x-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/radio/si470x/radio-si470x-i2c.c
--- linux-libre-4.9-gnu/drivers/media/radio/si470x/radio-si470x-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/radio/si470x/radio-si470x-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -387,8 +387,8 @@ static int si470x_i2c_probe(struct i2c_c
 			radio->registers[DEVICEID], radio->registers[SI_CHIPID]);
 	if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
 		dev_warn(&client->dev,
-			"This driver is known to work with "
-			"firmware version %hu,\n", RADIO_FW_VERSION);
+			"This driver is known to work with firmware version %hu,\n",
+			RADIO_FW_VERSION);
 		dev_warn(&client->dev,
 			"but the device has firmware version %hu.\n",
 			radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE);
@@ -400,8 +400,7 @@ static int si470x_i2c_probe(struct i2c_c
 		dev_warn(&client->dev,
 			"If you have some trouble using this driver,\n");
 		dev_warn(&client->dev,
-			"please report to V4L ML at "
-			"linux-media@vger.kernel.org\n");
+			"please report to V4L ML at linux-media@vger.kernel.org\n");
 	}
 
 	/* set initial frequency */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/radio/si470x/radio-si470x-usb.c linux-libre-4.10-rc8-gnu/drivers/media/radio/si470x/radio-si470x-usb.c
--- linux-libre-4.9-gnu/drivers/media/radio/si470x/radio-si470x-usb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/radio/si470x/radio-si470x-usb.c	2017-02-12 16:03:20.000000000 -0500
@@ -351,8 +351,8 @@ static int si470x_get_scratch_page_versi
 	retval = si470x_get_report(radio, radio->usb_buf, SCRATCH_REPORT_SIZE);
 
 	if (retval < 0)
-		dev_warn(&radio->intf->dev, "si470x_get_scratch: "
-			"si470x_get_report returned %d\n", retval);
+		dev_warn(&radio->intf->dev, "si470x_get_scratch: si470x_get_report returned %d\n",
+			 retval);
 	else {
 		radio->software_version = radio->usb_buf[1];
 		radio->hardware_version = radio->usb_buf[2];
@@ -688,8 +688,8 @@ static int si470x_usb_driver_probe(struc
 			radio->registers[DEVICEID], radio->registers[SI_CHIPID]);
 	if ((radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE) < RADIO_FW_VERSION) {
 		dev_warn(&intf->dev,
-			"This driver is known to work with "
-			"firmware version %hu,\n", RADIO_FW_VERSION);
+			"This driver is known to work with firmware version %hu,\n",
+			RADIO_FW_VERSION);
 		dev_warn(&intf->dev,
 			"but the device has firmware version %hu.\n",
 			radio->registers[SI_CHIPID] & SI_CHIPID_FIRMWARE);
@@ -705,8 +705,8 @@ static int si470x_usb_driver_probe(struc
 			radio->software_version, radio->hardware_version);
 	if (radio->hardware_version < RADIO_HW_VERSION) {
 		dev_warn(&intf->dev,
-			"This driver is known to work with "
-			"hardware version %hu,\n", RADIO_HW_VERSION);
+			"This driver is known to work with hardware version %hu,\n",
+			RADIO_HW_VERSION);
 		dev_warn(&intf->dev,
 			"but the device has hardware version %hu.\n",
 			radio->hardware_version);
@@ -718,8 +718,7 @@ static int si470x_usb_driver_probe(struc
 		dev_warn(&intf->dev,
 			"If you have some trouble using this driver,\n");
 		dev_warn(&intf->dev,
-			"please report to V4L ML at "
-			"linux-media@vger.kernel.org\n");
+			"please report to V4L ML at linux-media@vger.kernel.org\n");
 	}
 
 	/* set led to connect state */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/radio/si4713/si4713.c linux-libre-4.10-rc8-gnu/drivers/media/radio/si4713/si4713.c
--- linux-libre-4.9-gnu/drivers/media/radio/si4713/si4713.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/radio/si4713/si4713.c	2017-02-12 16:03:20.000000000 -0500
@@ -716,9 +716,9 @@ static int si4713_tx_tune_status(struct
 		*power = val[5];
 		*antcap = val[6];
 		*noise = val[7];
-		v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz "
-				"(power %d, antcap %d, rnl %d)\n", __func__,
-				*frequency, *power, *antcap, *noise);
+		v4l2_dbg(1, debug, &sdev->sd,
+			 "%s: response: %d x 10 kHz (power %d, antcap %d, rnl %d)\n",
+			 __func__, *frequency, *power, *antcap, *noise);
 	}
 
 	return err;
@@ -758,10 +758,9 @@ static int si4713_tx_rds_buff(struct si4
 		v4l2_dbg(1, debug, &sdev->sd,
 			"%s: status=0x%02x\n", __func__, val[0]);
 		*cbleft = (s8)val[2] - val[3];
-		v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts"
-				" 0x%02x cb avail: %d cb used %d fifo avail"
-				" %d fifo used %d\n", __func__, val[1],
-				val[2], val[3], val[4], val[5]);
+		v4l2_dbg(1, debug, &sdev->sd,
+			 "%s: response: interrupts 0x%02x cb avail: %d cb used %d fifo avail %d fifo used %d\n",
+			 __func__, val[1], val[2], val[3], val[4], val[5]);
 	}
 
 	return err;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/radio/wl128x/fmdrv_common.c linux-libre-4.10-rc8-gnu/drivers/media/radio/wl128x/fmdrv_common.c
--- linux-libre-4.9-gnu/drivers/media/radio/wl128x/fmdrv_common.c	2016-12-11 17:48:42.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/radio/wl128x/fmdrv_common.c	2017-02-12 17:36:45.000000000 -0500
@@ -212,14 +212,14 @@ inline void dump_tx_skb_data(struct sk_b
 
 	len_org = skb->len - FM_CMD_MSG_HDR_SIZE;
 	if (len_org > 0) {
-		printk("\n   data(%d): ", cmd_hdr->dlen);
+		printk(KERN_CONT "\n   data(%d): ", cmd_hdr->dlen);
 		len = min(len_org, 14);
 		for (index = 0; index < len; index++)
-			printk("%x ",
+			printk(KERN_CONT "%x ",
 			       skb->data[FM_CMD_MSG_HDR_SIZE + index]);
-		printk("%s", (len_org > 14) ? ".." : "");
+		printk(KERN_CONT "%s", (len_org > 14) ? ".." : "");
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 
  /* To dump incoming FM Channel-8 packets */
@@ -230,21 +230,21 @@ inline void dump_rx_skb_data(struct sk_b
 	struct fm_event_msg_hdr *evt_hdr;
 
 	evt_hdr = (struct fm_event_msg_hdr *)skb->data;
-	printk(KERN_INFO ">> hdr:%02x len:%02x sts:%02x numhci:%02x "
-	    "opcode:%02x type:%s dlen:%02x", evt_hdr->hdr, evt_hdr->len,
-	    evt_hdr->status, evt_hdr->num_fm_hci_cmds, evt_hdr->op,
-	    (evt_hdr->rd_wr) ? "RD" : "WR", evt_hdr->dlen);
+	printk(KERN_INFO ">> hdr:%02x len:%02x sts:%02x numhci:%02x opcode:%02x type:%s dlen:%02x",
+	       evt_hdr->hdr, evt_hdr->len,
+	       evt_hdr->status, evt_hdr->num_fm_hci_cmds, evt_hdr->op,
+	       (evt_hdr->rd_wr) ? "RD" : "WR", evt_hdr->dlen);
 
 	len_org = skb->len - FM_EVT_MSG_HDR_SIZE;
 	if (len_org > 0) {
-		printk("\n   data(%d): ", evt_hdr->dlen);
+		printk(KERN_CONT "\n   data(%d): ", evt_hdr->dlen);
 		len = min(len_org, 14);
 		for (index = 0; index < len; index++)
-			printk("%x ",
+			printk(KERN_CONT "%x ",
 			       skb->data[FM_EVT_MSG_HDR_SIZE + index]);
-		printk("%s", (len_org > 14) ? ".." : "");
+		printk(KERN_CONT "%s", (len_org > 14) ? ".." : "");
 	}
-	printk("\n");
+	printk(KERN_CONT "\n");
 }
 #endif
 
@@ -271,9 +271,9 @@ static void recv_tasklet(unsigned long a
 	/* Process all packets in the RX queue */
 	while ((skb = skb_dequeue(&fmdev->rx_q))) {
 		if (skb->len < sizeof(struct fm_event_msg_hdr)) {
-			fmerr("skb(%p) has only %d bytes, "
-				"at least need %zu bytes to decode\n", skb,
-				skb->len, sizeof(struct fm_event_msg_hdr));
+			fmerr("skb(%p) has only %d bytes, at least need %zu bytes to decode\n",
+			      skb,
+			      skb->len, sizeof(struct fm_event_msg_hdr));
 			kfree_skb(skb);
 			continue;
 		}
@@ -472,8 +472,7 @@ int fmc_send_cmd(struct fmdev *fmdev, u8
 
 	if (!wait_for_completion_timeout(&fmdev->maintask_comp,
 					 FM_DRV_TX_TIMEOUT)) {
-		fmerr("Timeout(%d sec),didn't get reg"
-			   "completion signal from RX tasklet\n",
+		fmerr("Timeout(%d sec),didn't get regcompletion signal from RX tasklet\n",
 			   jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
 		return -ETIMEDOUT;
 	}
@@ -523,8 +522,7 @@ static inline int check_cmdresp_status(s
 
 	fm_evt_hdr = (void *)(*skb)->data;
 	if (fm_evt_hdr->status != 0) {
-		fmerr("irq: opcode %x response status is not zero "
-				"Initiating irq recovery process\n",
+		fmerr("irq: opcode %x response status is not zero Initiating irq recovery process\n",
 				fm_evt_hdr->op);
 
 		mod_timer(&fmdev->irq_info.timer, jiffies + FM_DRV_TX_TIMEOUT);
@@ -564,8 +562,7 @@ static void int_timeout_handler(unsigned
 		 * reset stage index & retry count values */
 		fmirq->stage = 0;
 		fmirq->retry = 0;
-		fmerr("Recovery action failed during"
-				"irq processing, max retry reached\n");
+		fmerr("Recovery action failed duringirq processing, max retry reached\n");
 		return;
 	}
 	fm_irq_call_stage(fmdev, FM_SEND_INTMSK_CMD_IDX);
@@ -1516,14 +1513,13 @@ int fmc_prepare(struct fmdev *fmdev)
 
 		if (!wait_for_completion_timeout(&wait_for_fmdrv_reg_comp,
 						 FM_ST_REG_TIMEOUT)) {
-			fmerr("Timeout(%d sec), didn't get reg "
-					"completion signal from ST\n",
+			fmerr("Timeout(%d sec), didn't get reg completion signal from ST\n",
 					jiffies_to_msecs(FM_ST_REG_TIMEOUT) / 1000);
 			return -ETIMEDOUT;
 		}
 		if (fmdev->streg_cbdata != 0) {
-			fmerr("ST reg comp CB called with error "
-					"status %d\n", fmdev->streg_cbdata);
+			fmerr("ST reg comp CB called with error status %d\n",
+			      fmdev->streg_cbdata);
 			return -EAGAIN;
 		}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/radio/wl128x/fmdrv_rx.c linux-libre-4.10-rc8-gnu/drivers/media/radio/wl128x/fmdrv_rx.c
--- linux-libre-4.9-gnu/drivers/media/radio/wl128x/fmdrv_rx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/radio/wl128x/fmdrv_rx.c	2017-02-12 16:03:20.000000000 -0500
@@ -120,8 +120,8 @@ int fm_rx_set_freq(struct fmdev *fmdev,
 	curr_frq_in_khz = (fmdev->rx.region.bot_freq + ((u32)curr_frq * FM_FREQ_MUL));
 
 	if (curr_frq_in_khz != freq) {
-		pr_info("Frequency is set to (%d) but "
-			   "requested freq is (%d)\n", curr_frq_in_khz, freq);
+		pr_info("Frequency is set to (%d) but requested freq is (%d)\n",
+			curr_frq_in_khz, freq);
 	}
 
 	/* Update local cache  */
@@ -390,8 +390,8 @@ int fm_rx_set_region(struct fmdev *fmdev
 		new_frq = fmdev->rx.region.top_freq;
 
 	if (new_frq) {
-		fmdbg("Current freq is not within band limit boundary,"
-				"switching to %d KHz\n", new_frq);
+		fmdbg("Current freq is not within band limit boundary,switching to %d KHz\n",
+		      new_frq);
 		 /* Current RX frequency is not in range. So, update it */
 		ret = fm_rx_set_freq(fmdev, new_frq);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/ati_remote.c linux-libre-4.10-rc8-gnu/drivers/media/rc/ati_remote.c
--- linux-libre-4.9-gnu/drivers/media/rc/ati_remote.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/ati_remote.c	2017-02-12 16:03:20.000000000 -0500
@@ -527,8 +527,7 @@ static void ati_remote_input_report(stru
 	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, "
-			"mask= 0x%02lx\n",
+			"Masked input from channel 0x%02x: data %02x, mask= 0x%02lx\n",
 			remote_num, data[2], channel_mask);
 		return;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/ene_ir.c linux-libre-4.10-rc8-gnu/drivers/media/rc/ene_ir.c
--- linux-libre-4.9-gnu/drivers/media/rc/ene_ir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/ene_ir.c	2017-02-12 16:03:20.000000000 -0500
@@ -1210,8 +1210,7 @@ MODULE_PARM_DESC(txsim,
 
 MODULE_DEVICE_TABLE(pnp, ene_ids);
 MODULE_DESCRIPTION
-	("Infrared input driver for KB3926B/C/D/E/F "
-	"(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
+	("Infrared input driver for KB3926B/C/D/E/F (aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
 
 MODULE_AUTHOR("Maxim Levitsky");
 MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/fintek-cir.c linux-libre-4.10-rc8-gnu/drivers/media/rc/fintek-cir.c
--- linux-libre-4.9-gnu/drivers/media/rc/fintek-cir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/fintek-cir.c	2017-02-12 16:03:20.000000000 -0500
@@ -104,11 +104,7 @@ static inline void fintek_cir_reg_write(
 /* read val from cir config register */
 static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
 {
-	u8 val;
-
-	val = inb(fintek->cir_addr + offset);
-
-	return val;
+	return inb(fintek->cir_addr + offset);
 }
 
 /* dump current cir register contents */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/imon.c linux-libre-4.10-rc8-gnu/drivers/media/rc/imon.c
--- linux-libre-4.9-gnu/drivers/media/rc/imon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/imon.c	2017-02-12 16:03:20.000000000 -0500
@@ -441,13 +441,11 @@ MODULE_PARM_DESC(debug, "Debug messages:
 /* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
 static int display_type;
 module_param(display_type, int, S_IRUGO);
-MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, "
-		 "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
+MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, 1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)");
 
 static int pad_stabilize = 1;
 module_param(pad_stabilize, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD "
-		 "presses in arrow key mode. 0=disable, 1=enable (default).");
+MODULE_PARM_DESC(pad_stabilize, "Apply stabilization algorithm to iMON PAD presses in arrow key mode. 0=disable, 1=enable (default).");
 
 /*
  * In certain use cases, mouse mode isn't really helpful, and could actually
@@ -455,14 +453,12 @@ MODULE_PARM_DESC(pad_stabilize, "Apply s
  */
 static bool nomouse;
 module_param(nomouse, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is "
-		 "open. 0=don't disable, 1=disable. (default: don't disable)");
+MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is open. 0=don't disable, 1=disable. (default: don't disable)");
 
 /* threshold at which a pad push registers as an arrow key in kbd mode */
 static int pad_thresh;
 module_param(pad_thresh, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an "
-		 "arrow key in kbd mode (default: 28)");
+MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an arrow key in kbd mode (default: 28)");
 
 
 static void free_imon_context(struct imon_context *ictx)
@@ -611,7 +607,7 @@ static int send_packet(struct imon_conte
 		ictx->tx_urb->actual_length = 0;
 	}
 
-	init_completion(&ictx->tx.finished);
+	reinit_completion(&ictx->tx.finished);
 	ictx->tx.busy = true;
 	smp_rmb(); /* ensure later readers know we're busy */
 
@@ -785,9 +781,7 @@ static ssize_t show_associate_remote(str
 	else
 		strcpy(buf, "closed\n");
 
-	dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for "
-		 "instructions on how to associate your iMON 2.4G DT/LT "
-		 "remote\n");
+	dev_info(d, "Visit http://www.lirc.org/html/imon-24g.html for instructions on how to associate your iMON 2.4G DT/LT remote\n");
 	mutex_unlock(&ictx->lock);
 	return strlen(buf);
 }
@@ -1115,8 +1109,7 @@ static int imon_ir_change_protocol(struc
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
 	if (*rc_type && !(*rc_type & rc->allowed_protocols))
-		dev_warn(dev, "Looks like you're trying to use an IR protocol "
-			 "this device does not support\n");
+		dev_warn(dev, "Looks like you're trying to use an IR protocol this device does not support\n");
 
 	if (*rc_type & RC_BIT_RC6_MCE) {
 		dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
@@ -1129,8 +1122,7 @@ static int imon_ir_change_protocol(struc
 		/* ir_proto_packet[0] = 0x00; // already the default */
 		*rc_type = RC_BIT_OTHER;
 	} else {
-		dev_warn(dev, "Unsupported IR protocol specified, overriding "
-			 "to iMON IR protocol\n");
+		dev_warn(dev, "Unsupported IR protocol specified, overriding to iMON IR protocol\n");
 		if (!pad_stabilize)
 			dev_dbg(dev, "PAD stabilize functionality disabled\n");
 		/* ir_proto_packet[0] = 0x00; // already the default */
@@ -1593,7 +1585,6 @@ static void imon_incoming_packet(struct
 	struct device *dev = ictx->dev;
 	unsigned long flags;
 	u32 kc;
-	int i;
 	u64 scancode;
 	int press_type = 0;
 	int msec;
@@ -1664,10 +1655,8 @@ static void imon_incoming_packet(struct
 	}
 
 	if (debug) {
-		printk(KERN_INFO "intf%d decoded packet: ", intf);
-		for (i = 0; i < len; ++i)
-			printk("%02x ", buf[i]);
-		printk("\n");
+		printk(KERN_INFO "intf%d decoded packet: %*ph\n",
+		       intf, len, buf);
 	}
 
 	press_type = imon_parse_press_type(ictx, buf, ktype);
@@ -1722,8 +1711,8 @@ static void imon_incoming_packet(struct
 
 not_input_data:
 	if (len != 8) {
-		dev_warn(dev, "imon %s: invalid incoming packet "
-			 "size (len = %d, intf%d)\n", __func__, len, intf);
+		dev_warn(dev, "imon %s: invalid incoming packet size (len = %d, intf%d)\n",
+			 __func__, len, intf);
 		return;
 	}
 
@@ -1879,8 +1868,7 @@ static void imon_get_ffdc_type(struct im
 		allowed_protos = RC_BIT_RC6_MCE;
 		break;
 	default:
-		dev_info(ictx->dev, "Unknown 0xffdc device, "
-			 "defaulting to VFD and iMON IR");
+		dev_info(ictx->dev, "Unknown 0xffdc device, defaulting to VFD and iMON IR");
 		detected_display_type = IMON_DISPLAY_TYPE_VFD;
 		/* We don't know which one it is, allow user to set the
 		 * RC6 one from userspace if OTHER wasn't correct. */
@@ -1937,8 +1925,8 @@ static void imon_set_display_type(struct
 			ictx->display_supported = false;
 		else
 			ictx->display_supported = true;
-		dev_info(ictx->dev, "%s: overriding display type to %d via "
-			 "modparam\n", __func__, display_type);
+		dev_info(ictx->dev, "%s: overriding display type to %d via modparam\n",
+			 __func__, display_type);
 	}
 
 	ictx->display_type = configured_display_type;
@@ -2159,8 +2147,8 @@ static bool imon_find_endpoints(struct i
 	if (!display_ep_found) {
 		tx_control = true;
 		display_ep_found = true;
-		dev_dbg(ictx->dev, "%s: device uses control endpoint, not "
-			"interface OUT endpoint\n", __func__);
+		dev_dbg(ictx->dev, "%s: device uses control endpoint, not interface OUT endpoint\n",
+			__func__);
 	}
 
 	/*
@@ -2228,6 +2216,8 @@ static struct imon_context *imon_init_in
 	ictx->tx_urb = tx_urb;
 	ictx->rf_device = false;
 
+	init_completion(&ictx->tx.finished);
+
 	ictx->vendor  = le16_to_cpu(ictx->usbdev_intf0->descriptor.idVendor);
 	ictx->product = le16_to_cpu(ictx->usbdev_intf0->descriptor.idProduct);
 
@@ -2369,8 +2359,8 @@ static void imon_init_display(struct imo
 	/* set up sysfs entry for built-in clock */
 	ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group);
 	if (ret)
-		dev_err(ictx->dev, "Could not create display sysfs "
-			"entries(%d)", ret);
+		dev_err(ictx->dev, "Could not create display sysfs entries(%d)",
+			ret);
 
 	if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
 		ret = usb_register_dev(intf, &imon_lcd_class);
@@ -2378,8 +2368,7 @@ static void imon_init_display(struct imo
 		ret = usb_register_dev(intf, &imon_vfd_class);
 	if (ret)
 		/* Not a fatal error, so ignore */
-		dev_info(ictx->dev, "could not get a minor number for "
-			 "display\n");
+		dev_info(ictx->dev, "could not get a minor number for display\n");
 
 }
 
@@ -2459,8 +2448,8 @@ static int imon_probe(struct usb_interfa
 		mutex_unlock(&ictx->lock);
 	}
 
-	dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
-		 "usb<%d:%d> initialized\n", vendor, product, ifnum,
+	dev_info(dev, "iMON device (%04x:%04x, intf%d) on usb<%d:%d> initialized\n",
+		 vendor, product, ifnum,
 		 usbdev->bus->busnum, usbdev->devnum);
 
 	mutex_unlock(&driver_lock);
@@ -2504,7 +2493,7 @@ static void imon_disconnect(struct usb_i
 	/* Abort ongoing write */
 	if (ictx->tx.busy) {
 		usb_kill_urb(ictx->tx_urb);
-		complete_all(&ictx->tx.finished);
+		complete(&ictx->tx.finished);
 	}
 
 	if (ifnum == 0) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/ir-hix5hd2.c linux-libre-4.10-rc8-gnu/drivers/media/rc/ir-hix5hd2.c
--- linux-libre-4.9-gnu/drivers/media/rc/ir-hix5hd2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/ir-hix5hd2.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,15 +75,22 @@ static void hix5hd2_ir_enable(struct hix
 {
 	u32 val;
 
-	regmap_read(dev->regmap, IR_CLK, &val);
-	if (on) {
-		val &= ~IR_CLK_RESET;
-		val |= IR_CLK_ENABLE;
+	if (dev->regmap) {
+		regmap_read(dev->regmap, IR_CLK, &val);
+		if (on) {
+			val &= ~IR_CLK_RESET;
+			val |= IR_CLK_ENABLE;
+		} else {
+			val &= ~IR_CLK_ENABLE;
+			val |= IR_CLK_RESET;
+		}
+		regmap_write(dev->regmap, IR_CLK, val);
 	} else {
-		val &= ~IR_CLK_ENABLE;
-		val |= IR_CLK_RESET;
+		if (on)
+			clk_prepare_enable(dev->clock);
+		else
+			clk_disable_unprepare(dev->clock);
 	}
-	regmap_write(dev->regmap, IR_CLK, val);
 }
 
 static int hix5hd2_ir_config(struct hix5hd2_ir_priv *priv)
@@ -207,8 +214,8 @@ static int hix5hd2_ir_probe(struct platf
 	priv->regmap = syscon_regmap_lookup_by_phandle(node,
 						       "hisilicon,power-syscon");
 	if (IS_ERR(priv->regmap)) {
-		dev_err(dev, "no power-reg\n");
-		return -EINVAL;
+		dev_info(dev, "no power-reg\n");
+		priv->regmap = NULL;
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/ir-rx51.c linux-libre-4.10-rc8-gnu/drivers/media/rc/ir-rx51.c
--- linux-libre-4.9-gnu/drivers/media/rc/ir-rx51.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/ir-rx51.c	2017-02-12 16:03:20.000000000 -0500
@@ -109,7 +109,7 @@ static enum hrtimer_restart lirc_rx51_ti
 
 		now = timer->base->get_time();
 
-	} while (hrtimer_get_expires_tv64(timer) < now.tv64);
+	} while (hrtimer_get_expires_tv64(timer) < now);
 
 	return HRTIMER_RESTART;
 end:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/ir-sanyo-decoder.c linux-libre-4.10-rc8-gnu/drivers/media/rc/ir-sanyo-decoder.c
--- linux-libre-4.9-gnu/drivers/media/rc/ir-sanyo-decoder.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/ir-sanyo-decoder.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,8 @@ static int ir_sanyo_decode(struct rc_dev
 {
 	struct sanyo_dec *data = &dev->raw->sanyo;
 	u32 scancode;
-	u8 address, command, not_command;
+	u16 address;
+	u8 command, not_command;
 
 	if (!is_timing_event(ev)) {
 		if (ev.reset) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/ite-cir.c linux-libre-4.10-rc8-gnu/drivers/media/rc/ite-cir.c
--- linux-libre-4.9-gnu/drivers/media/rc/ite-cir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/ite-cir.c	2017-02-12 16:03:20.000000000 -0500
@@ -55,14 +55,12 @@ MODULE_PARM_DESC(debug, "Enable debuggin
 /* low limit for RX carrier freq, Hz, 0 for no RX demodulation */
 static int rx_low_carrier_freq;
 module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, "
-		 "0 for no RX demodulation");
+MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, 0 for no RX demodulation");
 
 /* high limit for RX carrier freq, Hz, 0 for no RX demodulation */
 static int rx_high_carrier_freq;
 module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, "
-		 "Hz, 0 for no RX demodulation");
+MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, Hz, 0 for no RX demodulation");
 
 /* override tx carrier frequency */
 static int tx_carrier_freq;
@@ -263,6 +261,8 @@ static void ite_set_carrier_params(struc
 
 			if (allowance > ITE_RXDCR_MAX)
 				allowance = ITE_RXDCR_MAX;
+
+			use_demodulator = true;
 		}
 	}
 
@@ -1484,8 +1484,7 @@ static int ite_probe(struct pnp_dev *pde
 
 	if (model_number >= 0 && model_number < ARRAY_SIZE(ite_dev_descs)) {
 		model_no = model_number;
-		ite_pr(KERN_NOTICE, "The model has been fixed by a module "
-			"parameter.");
+		ite_pr(KERN_NOTICE, "The model has been fixed by a module parameter.");
 	}
 
 	ite_pr(KERN_NOTICE, "Using model: %s\n", ite_dev_descs[model_no].model);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/rc/Kconfig
--- linux-libre-4.9-gnu/drivers/media/rc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -389,4 +389,21 @@ config IR_SUNXI
 	   To compile this driver as a module, choose M here: the module will
 	   be called sunxi-ir.
 
+config IR_SERIAL
+	tristate "Homebrew Serial Port Receiver"
+	depends on RC_CORE
+	---help---
+	   Say Y if you want to use Homebrew Serial Port Receivers and
+	   Transceivers.
+
+	   To compile this driver as a module, choose M here: the module will
+	   be called serial-ir.
+
+config IR_SERIAL_TRANSMITTER
+	bool "Serial Port Transmitter"
+	default y
+	depends on IR_SERIAL
+	---help---
+	   Serial Port Transmitter support
+
 endif #RC_DEVICES
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/lirc_dev.c linux-libre-4.10-rc8-gnu/drivers/media/rc/lirc_dev.c
--- linux-libre-4.9-gnu/drivers/media/rc/lirc_dev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/lirc_dev.c	2017-02-12 16:03:20.000000000 -0500
@@ -150,9 +150,6 @@ static const struct file_operations lirc
 	.write		= lirc_dev_fop_write,
 	.poll		= lirc_dev_fop_poll,
 	.unlocked_ioctl	= lirc_dev_fop_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= lirc_dev_fop_ioctl,
-#endif
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
 	.llseek		= noop_llseek,
@@ -160,19 +157,19 @@ static const struct file_operations lirc
 
 static int lirc_cdev_add(struct irctl *ir)
 {
-	int retval = -ENOMEM;
 	struct lirc_driver *d = &ir->d;
 	struct cdev *cdev;
+	int retval;
 
-	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
+	cdev = cdev_alloc();
 	if (!cdev)
-		goto err_out;
+		return -ENOMEM;
 
 	if (d->fops) {
-		cdev_init(cdev, d->fops);
+		cdev->ops = d->fops;
 		cdev->owner = d->owner;
 	} else {
-		cdev_init(cdev, &lirc_dev_fops);
+		cdev->ops = &lirc_dev_fops;
 		cdev->owner = THIS_MODULE;
 	}
 	retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
@@ -180,17 +177,15 @@ static int lirc_cdev_add(struct irctl *i
 		goto err_out;
 
 	retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
-	if (retval) {
-		kobject_put(&cdev->kobj);
+	if (retval)
 		goto err_out;
-	}
 
 	ir->cdev = cdev;
 
 	return 0;
 
 err_out:
-	kfree(cdev);
+	cdev_del(cdev);
 	return retval;
 }
 
@@ -420,7 +415,6 @@ int lirc_unregister_driver(int minor)
 	} else {
 		lirc_irctl_cleanup(ir);
 		cdev_del(cdev);
-		kfree(cdev);
 		kfree(ir);
 		irctls[minor] = NULL;
 	}
@@ -521,7 +515,6 @@ int lirc_dev_fop_close(struct inode *ino
 		lirc_irctl_cleanup(ir);
 		cdev_del(cdev);
 		irctls[ir->d.minor] = NULL;
-		kfree(cdev);
 		kfree(ir);
 	}
 
@@ -684,7 +677,6 @@ ssize_t lirc_dev_fop_read(struct file *f
 	 * between while condition checking and scheduling)
 	 */
 	add_wait_queue(&ir->buf->wait_poll, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
 
 	/*
 	 * while we didn't provide 'length' bytes, device is opened in blocking
@@ -709,19 +701,19 @@ ssize_t lirc_dev_fop_read(struct file *f
 			}
 
 			mutex_unlock(&ir->irctl_lock);
-			schedule();
 			set_current_state(TASK_INTERRUPTIBLE);
+			schedule();
+			set_current_state(TASK_RUNNING);
 
 			if (mutex_lock_interruptible(&ir->irctl_lock)) {
 				ret = -ERESTARTSYS;
 				remove_wait_queue(&ir->buf->wait_poll, &wait);
-				set_current_state(TASK_RUNNING);
 				goto out_unlocked;
 			}
 
 			if (!ir->attached) {
 				ret = -ENODEV;
-				break;
+				goto out_locked;
 			}
 		} else {
 			lirc_buffer_read(ir->buf, buf);
@@ -735,7 +727,6 @@ ssize_t lirc_dev_fop_read(struct file *f
 	}
 
 	remove_wait_queue(&ir->buf->wait_poll, &wait);
-	set_current_state(TASK_RUNNING);
 
 out_locked:
 	mutex_unlock(&ir->irctl_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/Makefile linux-libre-4.10-rc8-gnu/drivers/media/rc/Makefile
--- linux-libre-4.9-gnu/drivers/media/rc/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -37,3 +37,4 @@ obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
 obj-$(CONFIG_RC_ST) += st_rc.o
 obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
 obj-$(CONFIG_IR_IMG) += img-ir/
+obj-$(CONFIG_IR_SERIAL) += serial_ir.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/mceusb.c linux-libre-4.10-rc8-gnu/drivers/media/rc/mceusb.c
--- linux-libre-4.9-gnu/drivers/media/rc/mceusb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/mceusb.c	2017-02-12 16:03:20.000000000 -0500
@@ -153,15 +153,6 @@
 #define MCE_COMMAND_IRDATA	0x80
 #define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
 
-/* general constants */
-#define SEND_FLAG_IN_PROGRESS	1
-#define SEND_FLAG_COMPLETE	2
-#define RECV_FLAG_IN_PROGRESS	3
-#define RECV_FLAG_COMPLETE	4
-
-#define MCEUSB_RX		1
-#define MCEUSB_TX		2
-
 #define VENDOR_PHILIPS		0x0471
 #define VENDOR_SMK		0x0609
 #define VENDOR_TATUNG		0x1460
@@ -422,7 +413,6 @@ struct mceusb_dev {
 	struct rc_dev *rc;
 
 	/* optional features we can enable */
-	bool carrier_report_enabled;
 	bool learning_enabled;
 
 	/* core device bits */
@@ -455,7 +445,6 @@ struct mceusb_dev {
 	} flags;
 
 	/* transmit support */
-	int send_flags;
 	u32 carrier;
 	unsigned char tx_mask;
 
@@ -604,9 +593,7 @@ static void mceusb_dev_printdata(struct
 			break;
 		case MCE_RSP_EQWAKEVERSION:
 			if (!out)
-				dev_dbg(dev, "Wake version, proto: 0x%02x, "
-					 "payload: 0x%02x, address: 0x%02x, "
-					 "version: 0x%02x",
+				dev_dbg(dev, "Wake version, proto: 0x%02x, payload: 0x%02x, address: 0x%02x, version: 0x%02x",
 					 data1, data2, data3, data4);
 			break;
 		case MCE_RSP_GETPORTSTATUS:
@@ -740,52 +727,40 @@ static void mce_async_callback(struct ur
 
 /* request incoming or send outgoing usb packet - used to initialize remote */
 static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
-			       int size, int urb_type)
+								int size)
 {
 	int res, pipe;
 	struct urb *async_urb;
 	struct device *dev = ir->dev;
 	unsigned char *async_buf;
 
-	if (urb_type == MCEUSB_TX) {
-		async_urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (unlikely(!async_urb)) {
-			dev_err(dev, "Error, couldn't allocate urb!\n");
-			return;
-		}
-
-		async_buf = kzalloc(size, GFP_KERNEL);
-		if (!async_buf) {
-			dev_err(dev, "Error, couldn't allocate buf!\n");
-			usb_free_urb(async_urb);
-			return;
-		}
-
-		/* outbound data */
-		if (usb_endpoint_xfer_int(ir->usb_ep_out)) {
-			pipe = usb_sndintpipe(ir->usbdev,
-					 ir->usb_ep_out->bEndpointAddress);
-			usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf,
-					 size, mce_async_callback, ir,
-					 ir->usb_ep_out->bInterval);
-		} else {
-			pipe = usb_sndbulkpipe(ir->usbdev,
-					 ir->usb_ep_out->bEndpointAddress);
-			usb_fill_bulk_urb(async_urb, ir->usbdev, pipe,
-					 async_buf, size, mce_async_callback,
-					 ir);
-		}
-		memcpy(async_buf, data, size);
+	async_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (unlikely(!async_urb)) {
+		dev_err(dev, "Error, couldn't allocate urb!\n");
+		return;
+	}
 
-	} else if (urb_type == MCEUSB_RX) {
-		/* standard request */
-		async_urb = ir->urb_in;
-		ir->send_flags = RECV_FLAG_IN_PROGRESS;
+	async_buf = kmalloc(size, GFP_KERNEL);
+	if (!async_buf) {
+		usb_free_urb(async_urb);
+		return;
+	}
 
+	/* outbound data */
+	if (usb_endpoint_xfer_int(ir->usb_ep_out)) {
+		pipe = usb_sndintpipe(ir->usbdev,
+				 ir->usb_ep_out->bEndpointAddress);
+		usb_fill_int_urb(async_urb, ir->usbdev, pipe, async_buf,
+				 size, mce_async_callback, ir,
+				 ir->usb_ep_out->bInterval);
 	} else {
-		dev_err(dev, "Error! Unknown urb type %d\n", urb_type);
-		return;
+		pipe = usb_sndbulkpipe(ir->usbdev,
+				 ir->usb_ep_out->bEndpointAddress);
+		usb_fill_bulk_urb(async_urb, ir->usbdev, pipe,
+				 async_buf, size, mce_async_callback,
+				 ir);
 	}
+	memcpy(async_buf, data, size);
 
 	dev_dbg(dev, "receive request called (size=%#x)", size);
 
@@ -806,19 +781,14 @@ static void mce_async_out(struct mceusb_
 
 	if (ir->need_reset) {
 		ir->need_reset = false;
-		mce_request_packet(ir, DEVICE_RESUME, rsize, MCEUSB_TX);
+		mce_request_packet(ir, DEVICE_RESUME, rsize);
 		msleep(10);
 	}
 
-	mce_request_packet(ir, data, size, MCEUSB_TX);
+	mce_request_packet(ir, data, size);
 	msleep(10);
 }
 
-static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
-{
-	mce_request_packet(ir, NULL, size, MCEUSB_RX);
-}
-
 /* Send data out the IR blaster port(s) */
 static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 {
@@ -1062,7 +1032,6 @@ static void mceusb_process_ir_data(struc
 static void mceusb_dev_recv(struct urb *urb)
 {
 	struct mceusb_dev *ir;
-	int buf_len;
 
 	if (!urb)
 		return;
@@ -1073,18 +1042,10 @@ static void mceusb_dev_recv(struct urb *
 		return;
 	}
 
-	buf_len = urb->actual_length;
-
-	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
-		ir->send_flags = SEND_FLAG_COMPLETE;
-		dev_dbg(ir->dev, "setup answer received %d bytes\n",
-			buf_len);
-	}
-
 	switch (urb->status) {
 	/* success */
 	case 0:
-		mceusb_process_ir_data(ir, buf_len);
+		mceusb_process_ir_data(ir, urb->actual_length);
 		break;
 
 	case -ECONNRESET:
@@ -1285,7 +1246,7 @@ static int mceusb_dev_probe(struct usb_i
 	struct usb_endpoint_descriptor *ep_in = NULL;
 	struct usb_endpoint_descriptor *ep_out = NULL;
 	struct mceusb_dev *ir = NULL;
-	int pipe, maxp, i;
+	int pipe, maxp, i, res;
 	char buf[63], name[128] = "";
 	enum mceusb_model_type model = id->driver_info;
 	bool is_gen3;
@@ -1388,7 +1349,9 @@ static int mceusb_dev_probe(struct usb_i
 
 	/* flush buffers on the device */
 	dev_dbg(&intf->dev, "Flushing receive buffers\n");
-	mce_flush_rx_buffer(ir, maxp);
+	res = usb_submit_urb(ir->urb_in, GFP_KERNEL);
+	if (res)
+		dev_err(&intf->dev, "failed to flush buffers: %d\n", res);
 
 	/* figure out which firmware/emulator version this hardware has */
 	mceusb_get_emulator_version(ir);
@@ -1423,6 +1386,7 @@ static int mceusb_dev_probe(struct usb_i
 	/* Error-handling path */
 rc_dev_fail:
 	usb_put_dev(ir->usbdev);
+	usb_kill_urb(ir->urb_in);
 	usb_free_urb(ir->urb_in);
 urb_in_alloc_fail:
 	usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/meson-ir.c linux-libre-4.10-rc8-gnu/drivers/media/rc/meson-ir.c
--- linux-libre-4.9-gnu/drivers/media/rc/meson-ir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/meson-ir.c	2017-02-12 16:03:20.000000000 -0500
@@ -218,6 +218,7 @@ static const struct of_device_id meson_i
 	{ .compatible = "amlogic,meson-gxbb-ir" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, meson_ir_match);
 
 static struct platform_driver meson_ir_driver = {
 	.probe		= meson_ir_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/nuvoton-cir.c linux-libre-4.10-rc8-gnu/drivers/media/rc/nuvoton-cir.c
--- linux-libre-4.9-gnu/drivers/media/rc/nuvoton-cir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/nuvoton-cir.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,6 +48,11 @@ static const struct nvt_chip nvt_chips[]
 	{ "NCT6779D", NVT_6779D },
 };
 
+static inline struct device *nvt_get_dev(const struct nvt_dev *nvt)
+{
+	return nvt->rdev->dev.parent;
+}
+
 static inline bool is_w83667hg(struct nvt_dev *nvt)
 {
 	return nvt->chip_ver == NVT_W83667HG;
@@ -182,7 +187,7 @@ static ssize_t wakeup_data_show(struct d
 	ssize_t buf_len = 0;
 	int i;
 
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 
 	fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
 	fifo_len = min(fifo_len, WAKEUP_MAX_SIZE);
@@ -199,7 +204,7 @@ static ssize_t wakeup_data_show(struct d
 	}
 	buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len, "\n");
 
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 
 	return buf_len;
 }
@@ -243,7 +248,7 @@ static ssize_t wakeup_data_store(struct
 	/* hardcode the tolerance to 10% */
 	tolerance = DIV_ROUND_UP(count, 10);
 
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 
 	nvt_clear_cir_wake_fifo(nvt);
 	nvt_cir_wake_reg_write(nvt, count, CIR_WAKE_FIFO_CMP_DEEP);
@@ -260,7 +265,7 @@ static ssize_t wakeup_data_store(struct
 
 	nvt_cir_wake_reg_write(nvt, config, CIR_WAKE_IRCON);
 
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 
 	ret = len;
 out:
@@ -385,6 +390,7 @@ static inline const char *nvt_find_chip(
 /* detect hardware features */
 static int nvt_hw_detect(struct nvt_dev *nvt)
 {
+	struct device *dev = nvt_get_dev(nvt);
 	const char *chip_name;
 	int chip_id;
 
@@ -405,8 +411,7 @@ static int nvt_hw_detect(struct nvt_dev
 
 	chip_id = nvt->chip_major << 8 | nvt->chip_minor;
 	if (chip_id == NVT_INVALID) {
-		dev_err(&nvt->pdev->dev,
-			"No device found on either EFM port\n");
+		dev_err(dev, "No device found on either EFM port\n");
 		return -ENODEV;
 	}
 
@@ -414,12 +419,11 @@ static int nvt_hw_detect(struct nvt_dev
 
 	/* warn, but still let the driver load, if we don't know this chip */
 	if (!chip_name)
-		dev_warn(&nvt->pdev->dev,
+		dev_warn(dev,
 			 "unknown chip, id: 0x%02x 0x%02x, it may not work...",
 			 nvt->chip_major, nvt->chip_minor);
 	else
-		dev_info(&nvt->pdev->dev,
-			 "found %s or compatible: chip id: 0x%02x 0x%02x",
+		dev_info(dev, "found %s or compatible: chip id: 0x%02x 0x%02x",
 			 chip_name, nvt->chip_major, nvt->chip_minor);
 
 	return 0;
@@ -586,7 +590,7 @@ static void nvt_enable_wake(struct nvt_d
 
 	nvt_efm_disable(nvt);
 
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 
 	nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
 			       CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
@@ -595,11 +599,11 @@ static void nvt_enable_wake(struct nvt_d
 	nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
 	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
 
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 }
 
 #if 0 /* Currently unused */
-/* rx carrier detect only works in learning mode, must be called w/nvt_lock */
+/* rx carrier detect only works in learning mode, must be called w/lock */
 static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
 {
 	u32 count, carrier, duration = 0;
@@ -616,7 +620,7 @@ static u32 nvt_rx_carrier_detect(struct
 	duration *= SAMPLE_PERIOD;
 
 	if (!count || !duration) {
-		dev_notice(&nvt->pdev->dev,
+		dev_notice(nvt_get_dev(nvt),
 			   "Unable to determine carrier! (c:%u, d:%u)",
 			   count, duration);
 		return 0;
@@ -684,7 +688,7 @@ static int nvt_tx_ir(struct rc_dev *dev,
 	u8 iren;
 	int ret;
 
-	spin_lock_irqsave(&nvt->tx.lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 
 	ret = min((unsigned)(TX_BUF_LEN / sizeof(unsigned)), n);
 	nvt->tx.buf_count = (ret * sizeof(unsigned));
@@ -708,13 +712,13 @@ static int nvt_tx_ir(struct rc_dev *dev,
 	for (i = 0; i < 9; i++)
 		nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
 
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 
 	wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
 
-	spin_lock_irqsave(&nvt->tx.lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 	nvt->tx.tx_state = ST_TX_NONE;
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 
 	/* restore enabled interrupts to prior state */
 	nvt_cir_reg_write(nvt, iren, CIR_IREN);
@@ -781,7 +785,7 @@ static void nvt_process_rx_ir_data(struc
 
 static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
 {
-	dev_warn(&nvt->pdev->dev, "RX FIFO overrun detected, flushing data!");
+	dev_warn(nvt_get_dev(nvt), "RX FIFO overrun detected, flushing data!");
 
 	nvt->pkts = 0;
 	nvt_clear_cir_fifo(nvt);
@@ -828,14 +832,7 @@ static void nvt_cir_log_irqs(u8 status,
 
 static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
 {
-	unsigned long flags;
-	u8 tx_state;
-
-	spin_lock_irqsave(&nvt->tx.lock, flags);
-	tx_state = nvt->tx.tx_state;
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
-	return tx_state == ST_TX_NONE;
+	return nvt->tx.tx_state == ST_TX_NONE;
 }
 
 /* interrupt service routine for incoming and outgoing CIR data */
@@ -843,11 +840,10 @@ static irqreturn_t nvt_cir_isr(int irq,
 {
 	struct nvt_dev *nvt = data;
 	u8 status, iren;
-	unsigned long flags;
 
 	nvt_dbg_verbose("%s firing", __func__);
 
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	spin_lock(&nvt->lock);
 
 	/*
 	 * Get IR Status register contents. Write 1 to ack/clear
@@ -869,7 +865,7 @@ static irqreturn_t nvt_cir_isr(int irq,
 	 * logical device is being disabled.
 	 */
 	if (status == 0xff && iren == 0xff) {
-		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+		spin_unlock(&nvt->lock);
 		nvt_dbg_verbose("Spurious interrupt detected");
 		return IRQ_HANDLED;
 	}
@@ -878,7 +874,7 @@ static irqreturn_t nvt_cir_isr(int irq,
 	 * status bit whether the related interrupt source is enabled
 	 */
 	if (!(status & iren)) {
-		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+		spin_unlock(&nvt->lock);
 		nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
 		return IRQ_NONE;
 	}
@@ -898,8 +894,6 @@ static irqreturn_t nvt_cir_isr(int irq,
 			nvt_get_rx_ir_data(nvt);
 	}
 
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
 	if (status & CIR_IRSTS_TE)
 		nvt_clear_tx_fifo(nvt);
 
@@ -907,8 +901,6 @@ static irqreturn_t nvt_cir_isr(int irq,
 		unsigned int pos, count;
 		u8 tmp;
 
-		spin_lock_irqsave(&nvt->tx.lock, flags);
-
 		pos = nvt->tx.cur_buf_num;
 		count = nvt->tx.buf_count;
 
@@ -921,20 +913,17 @@ static irqreturn_t nvt_cir_isr(int irq,
 			tmp = nvt_cir_reg_read(nvt, CIR_IREN);
 			nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN);
 		}
-
-		spin_unlock_irqrestore(&nvt->tx.lock, flags);
-
 	}
 
 	if (status & CIR_IRSTS_TFU) {
-		spin_lock_irqsave(&nvt->tx.lock, flags);
 		if (nvt->tx.tx_state == ST_TX_REPLY) {
 			nvt->tx.tx_state = ST_TX_REQUEST;
 			wake_up(&nvt->tx.queue);
 		}
-		spin_unlock_irqrestore(&nvt->tx.lock, flags);
 	}
 
+	spin_unlock(&nvt->lock);
+
 	nvt_dbg_verbose("%s done", __func__);
 	return IRQ_HANDLED;
 }
@@ -943,7 +932,7 @@ static void nvt_disable_cir(struct nvt_d
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 
 	/* disable CIR interrupts */
 	nvt_cir_reg_write(nvt, 0, CIR_IREN);
@@ -958,7 +947,7 @@ static void nvt_disable_cir(struct nvt_d
 	nvt_clear_cir_fifo(nvt);
 	nvt_clear_tx_fifo(nvt);
 
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 
 	/* disable the CIR logical device */
 	nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
@@ -969,7 +958,7 @@ static int nvt_open(struct rc_dev *dev)
 	struct nvt_dev *nvt = dev->priv;
 	unsigned long flags;
 
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 
 	/* set function enable flags */
 	nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
@@ -982,7 +971,7 @@ static int nvt_open(struct rc_dev *dev)
 	/* enable interrupts */
 	nvt_set_cir_iren(nvt);
 
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 
 	/* enable the CIR logical device */
 	nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
@@ -1002,40 +991,41 @@ static int nvt_probe(struct pnp_dev *pde
 {
 	struct nvt_dev *nvt;
 	struct rc_dev *rdev;
-	int ret = -ENOMEM;
+	int ret;
 
 	nvt = devm_kzalloc(&pdev->dev, sizeof(struct nvt_dev), GFP_KERNEL);
 	if (!nvt)
-		return ret;
+		return -ENOMEM;
 
 	/* input device for IR remote (and tx) */
-	rdev = rc_allocate_device();
-	if (!rdev)
-		goto exit_free_dev_rdev;
+	nvt->rdev = devm_rc_allocate_device(&pdev->dev);
+	if (!nvt->rdev)
+		return -ENOMEM;
+	rdev = nvt->rdev;
 
-	ret = -ENODEV;
 	/* activate pnp device */
-	if (pnp_activate_dev(pdev) < 0) {
+	ret = pnp_activate_dev(pdev);
+	if (ret) {
 		dev_err(&pdev->dev, "Could not activate PNP device!\n");
-		goto exit_free_dev_rdev;
+		return ret;
 	}
 
 	/* validate pnp resources */
 	if (!pnp_port_valid(pdev, 0) ||
 	    pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
 		dev_err(&pdev->dev, "IR PNP Port not valid!\n");
-		goto exit_free_dev_rdev;
+		return -EINVAL;
 	}
 
 	if (!pnp_irq_valid(pdev, 0)) {
 		dev_err(&pdev->dev, "PNP IRQ not valid!\n");
-		goto exit_free_dev_rdev;
+		return -EINVAL;
 	}
 
 	if (!pnp_port_valid(pdev, 1) ||
 	    pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
 		dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
-		goto exit_free_dev_rdev;
+		return -EINVAL;
 	}
 
 	nvt->cir_addr = pnp_port_start(pdev, 0);
@@ -1046,17 +1036,15 @@ static int nvt_probe(struct pnp_dev *pde
 	nvt->cr_efir = CR_EFIR;
 	nvt->cr_efdr = CR_EFDR;
 
-	spin_lock_init(&nvt->nvt_lock);
-	spin_lock_init(&nvt->tx.lock);
+	spin_lock_init(&nvt->lock);
 
 	pnp_set_drvdata(pdev, nvt);
-	nvt->pdev = pdev;
 
 	init_waitqueue_head(&nvt->tx.queue);
 
 	ret = nvt_hw_detect(nvt);
 	if (ret)
-		goto exit_free_dev_rdev;
+		return ret;
 
 	/* Initialize CIR & CIR Wake Logical Devices */
 	nvt_efm_enable(nvt);
@@ -1085,7 +1073,6 @@ static int nvt_probe(struct pnp_dev *pde
 	rdev->input_id.vendor = PCI_VENDOR_ID_WINBOND2;
 	rdev->input_id.product = nvt->chip_major;
 	rdev->input_id.version = nvt->chip_minor;
-	rdev->dev.parent = &pdev->dev;
 	rdev->driver_name = NVT_DRIVER_NAME;
 	rdev->map_name = RC_MAP_RC6_MCE;
 	rdev->timeout = MS_TO_NS(100);
@@ -1097,29 +1084,27 @@ static int nvt_probe(struct pnp_dev *pde
 	/* tx bits */
 	rdev->tx_resolution = XYZ;
 #endif
-	nvt->rdev = rdev;
-
-	ret = rc_register_device(rdev);
+	ret = devm_rc_register_device(&pdev->dev, rdev);
 	if (ret)
-		goto exit_free_dev_rdev;
+		return ret;
 
-	ret = -EBUSY;
 	/* now claim resources */
 	if (!devm_request_region(&pdev->dev, nvt->cir_addr,
 			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
-		goto exit_unregister_device;
+		return -EBUSY;
 
-	if (devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr,
-			     IRQF_SHARED, NVT_DRIVER_NAME, (void *)nvt))
-		goto exit_unregister_device;
+	ret = devm_request_irq(&pdev->dev, nvt->cir_irq, nvt_cir_isr,
+			       IRQF_SHARED, NVT_DRIVER_NAME, nvt);
+	if (ret)
+		return ret;
 
 	if (!devm_request_region(&pdev->dev, nvt->cir_wake_addr,
 			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME "-wake"))
-		goto exit_unregister_device;
+		return -EBUSY;
 
 	ret = device_create_file(&rdev->dev, &dev_attr_wakeup_data);
 	if (ret)
-		goto exit_unregister_device;
+		return ret;
 
 	device_init_wakeup(&pdev->dev, true);
 
@@ -1130,14 +1115,6 @@ static int nvt_probe(struct pnp_dev *pde
 	}
 
 	return 0;
-
-exit_unregister_device:
-	rc_unregister_device(rdev);
-	rdev = NULL;
-exit_free_dev_rdev:
-	rc_free_device(rdev);
-
-	return ret;
 }
 
 static void nvt_remove(struct pnp_dev *pdev)
@@ -1150,8 +1127,6 @@ static void nvt_remove(struct pnp_dev *p
 
 	/* enable CIR Wake (for IR power-on) */
 	nvt_enable_wake(nvt);
-
-	rc_unregister_device(nvt->rdev);
 }
 
 static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
@@ -1161,16 +1136,14 @@ static int nvt_suspend(struct pnp_dev *p
 
 	nvt_dbg("%s called", __func__);
 
-	spin_lock_irqsave(&nvt->tx.lock, flags);
-	nvt->tx.tx_state = ST_TX_NONE;
-	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+	spin_lock_irqsave(&nvt->lock, flags);
 
-	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->tx.tx_state = ST_TX_NONE;
 
 	/* disable all CIR interrupts */
 	nvt_cir_reg_write(nvt, 0, CIR_IREN);
 
-	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	spin_unlock_irqrestore(&nvt->lock, flags);
 
 	/* disable cir logical dev */
 	nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/nuvoton-cir.h linux-libre-4.10-rc8-gnu/drivers/media/rc/nuvoton-cir.h
--- linux-libre-4.9-gnu/drivers/media/rc/nuvoton-cir.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/nuvoton-cir.h	2017-02-12 16:03:20.000000000 -0500
@@ -78,17 +78,15 @@ struct nvt_chip {
 };
 
 struct nvt_dev {
-	struct pnp_dev *pdev;
 	struct rc_dev *rdev;
 
-	spinlock_t nvt_lock;
+	spinlock_t lock;
 
 	/* for rx */
 	u8 buf[RX_BUF_LEN];
 	unsigned int pkts;
 
 	struct {
-		spinlock_t lock;
 		u8 buf[TX_BUF_LEN];
 		unsigned int buf_count;
 		unsigned int cur_buf_num;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/rc-ir-raw.c linux-libre-4.10-rc8-gnu/drivers/media/rc/rc-ir-raw.c
--- linux-libre-4.9-gnu/drivers/media/rc/rc-ir-raw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/rc-ir-raw.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,8 +26,7 @@ static LIST_HEAD(ir_raw_client_list);
 /* Used to handle IR raw handler extensions */
 static DEFINE_MUTEX(ir_raw_handler_lock);
 static LIST_HEAD(ir_raw_handler_list);
-static DEFINE_MUTEX(available_protocols_lock);
-static u64 available_protocols;
+static atomic64_t available_protocols = ATOMIC64_INIT(0);
 
 static int ir_raw_event_thread(void *data)
 {
@@ -234,11 +233,7 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 u64
 ir_raw_get_allowed_protocols(void)
 {
-	u64 protocols;
-	mutex_lock(&available_protocols_lock);
-	protocols = available_protocols;
-	mutex_unlock(&available_protocols_lock);
-	return protocols;
+	return atomic64_read(&available_protocols);
 }
 
 static int change_protocol(struct rc_dev *dev, u64 *rc_type)
@@ -331,9 +326,7 @@ int ir_raw_handler_register(struct ir_ra
 	if (ir_raw_handler->raw_register)
 		list_for_each_entry(raw, &ir_raw_client_list, list)
 			ir_raw_handler->raw_register(raw->dev);
-	mutex_lock(&available_protocols_lock);
-	available_protocols |= ir_raw_handler->protocols;
-	mutex_unlock(&available_protocols_lock);
+	atomic64_or(ir_raw_handler->protocols, &available_protocols);
 	mutex_unlock(&ir_raw_handler_lock);
 
 	return 0;
@@ -352,9 +345,7 @@ void ir_raw_handler_unregister(struct ir
 		if (ir_raw_handler->raw_unregister)
 			ir_raw_handler->raw_unregister(raw->dev);
 	}
-	mutex_lock(&available_protocols_lock);
-	available_protocols &= ~protocols;
-	mutex_unlock(&available_protocols_lock);
+	atomic64_andnot(protocols, &available_protocols);
 	mutex_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/rc-main.c linux-libre-4.10-rc8-gnu/drivers/media/rc/rc-main.c
--- linux-libre-4.9-gnu/drivers/media/rc/rc-main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/rc-main.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,6 +12,8 @@
  *  GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <media/rc-core.h>
 #include <linux/atomic.h>
 #include <linux/spinlock.h>
@@ -66,7 +68,7 @@ struct rc_map *rc_map_get(const char *na
 	if (!map) {
 		int rc = request_module("%s", name);
 		if (rc < 0) {
-			printk(KERN_ERR "Couldn't load IR keymap %s\n", name);
+			pr_err("Couldn't load IR keymap %s\n", name);
 			return NULL;
 		}
 		msleep(20);	/* Give some time for IR to register */
@@ -75,7 +77,7 @@ struct rc_map *rc_map_get(const char *na
 	}
 #endif
 	if (!map) {
-		printk(KERN_ERR "IR keymap %s not found\n", name);
+		pr_err("IR keymap %s not found\n", name);
 		return NULL;
 	}
 
@@ -159,6 +161,7 @@ static void ir_free_table(struct rc_map
 {
 	rc_map->size = 0;
 	kfree(rc_map->name);
+	rc_map->name = NULL;
 	kfree(rc_map->scan);
 	rc_map->scan = NULL;
 }
@@ -660,8 +663,7 @@ static void ir_do_keydown(struct rc_dev
 		dev->last_toggle = toggle;
 		dev->last_keycode = keycode;
 
-		IR_dprintk(1, "%s: key down event, "
-			   "key 0x%04x, protocol 0x%04x, scancode 0x%08x\n",
+		IR_dprintk(1, "%s: key down event, key 0x%04x, protocol 0x%04x, scancode 0x%08x\n",
 			   dev->input_name, keycode, protocol, scancode);
 		input_report_key(dev->input_dev, keycode, 1);
 
@@ -1403,6 +1405,34 @@ void rc_free_device(struct rc_dev *dev)
 }
 EXPORT_SYMBOL_GPL(rc_free_device);
 
+static void devm_rc_alloc_release(struct device *dev, void *res)
+{
+	rc_free_device(*(struct rc_dev **)res);
+}
+
+struct rc_dev *devm_rc_allocate_device(struct device *dev)
+{
+	struct rc_dev **dr, *rc;
+
+	dr = devres_alloc(devm_rc_alloc_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return NULL;
+
+	rc = rc_allocate_device();
+	if (!rc) {
+		devres_free(dr);
+		return NULL;
+	}
+
+	rc->dev.parent = dev;
+	rc->managed_alloc = true;
+	*dr = rc;
+	devres_add(dev, dr);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(devm_rc_allocate_device);
+
 int rc_register_device(struct rc_dev *dev)
 {
 	static bool raw_init = false; /* raw decoders loaded? */
@@ -1531,6 +1561,33 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(rc_register_device);
 
+static void devm_rc_release(struct device *dev, void *res)
+{
+	rc_unregister_device(*(struct rc_dev **)res);
+}
+
+int devm_rc_register_device(struct device *parent, struct rc_dev *dev)
+{
+	struct rc_dev **dr;
+	int ret;
+
+	dr = devres_alloc(devm_rc_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	ret = rc_register_device(dev);
+	if (ret) {
+		devres_free(dr);
+		return ret;
+	}
+
+	*dr = dev;
+	devres_add(parent, dr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_rc_register_device);
+
 void rc_unregister_device(struct rc_dev *dev)
 {
 	if (!dev)
@@ -1552,7 +1609,8 @@ void rc_unregister_device(struct rc_dev
 
 	ida_simple_remove(&rc_ida, dev->minor);
 
-	rc_free_device(dev);
+	if (!dev->managed_alloc)
+		rc_free_device(dev);
 }
 
 EXPORT_SYMBOL_GPL(rc_unregister_device);
@@ -1565,7 +1623,7 @@ static int __init rc_core_init(void)
 {
 	int rc = class_register(&rc_class);
 	if (rc) {
-		printk(KERN_ERR "rc_core: unable to register rc class\n");
+		pr_err("rc_core: unable to register rc class\n");
 		return rc;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/redrat3.c linux-libre-4.10-rc8-gnu/drivers/media/rc/redrat3.c
--- linux-libre-4.9-gnu/drivers/media/rc/redrat3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/redrat3.c	2017-02-12 16:03:20.000000000 -0500
@@ -81,6 +81,8 @@
 #define RR3_RC_DET_ENABLE	0xbb
 /* Stop capture with the RC receiver */
 #define RR3_RC_DET_DISABLE	0xbc
+/* Start capture with the wideband receiver */
+#define RR3_MODSIG_CAPTURE     0xb2
 /* Return the status of RC detector capture */
 #define RR3_RC_DET_STATUS	0xbd
 /* Reset redrat */
@@ -105,11 +107,13 @@
 #define RR3_CLK_PER_COUNT	12
 /* (RR3_CLK / RR3_CLK_PER_COUNT) */
 #define RR3_CLK_CONV_FACTOR	2000000
-/* USB bulk-in IR data endpoint address */
-#define RR3_BULK_IN_EP_ADDR	0x82
+/* USB bulk-in wideband IR data endpoint address */
+#define RR3_WIDE_IN_EP_ADDR	0x81
+/* USB bulk-in narrowband IR data endpoint address */
+#define RR3_NARROW_IN_EP_ADDR	0x82
 
 /* Size of the fixed-length portion of the signal */
-#define RR3_DRIVER_MAXLENS	128
+#define RR3_DRIVER_MAXLENS	255
 #define RR3_MAX_SIG_SIZE	512
 #define RR3_TIME_UNIT		50
 #define RR3_END_OF_SIGNAL	0x7f
@@ -207,15 +211,22 @@ struct redrat3_dev {
 	struct urb *flash_urb;
 	u8 flash_in_buf;
 
+	/* learning */
+	bool wideband;
+	struct usb_ctrlrequest learn_control;
+	struct urb *learn_urb;
+	u8 learn_buf;
+
 	/* save off the usb device pointer */
 	struct usb_device *udev;
 
 	/* the receive endpoint */
-	struct usb_endpoint_descriptor *ep_in;
+	struct usb_endpoint_descriptor *ep_narrow;
 	/* the buffer to receive data */
 	void *bulk_in_buf;
 	/* urb used to read ir data */
-	struct urb *read_urb;
+	struct urb *narrow_urb;
+	struct urb *wide_urb;
 
 	/* the send endpoint */
 	struct usb_endpoint_descriptor *ep_out;
@@ -236,23 +247,6 @@ struct redrat3_dev {
 	char phys[64];
 };
 
-/*
- * redrat3_issue_async
- *
- *  Issues an async read to the ir data in port..
- *  sets the callback to be redrat3_handle_async
- */
-static void redrat3_issue_async(struct redrat3_dev *rr3)
-{
-	int res;
-
-	res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
-	if (res)
-		dev_dbg(rr3->dev,
-			"%s: receive request FAILED! (res %d, len %d)\n",
-			__func__, res, rr3->read_urb->transfer_buffer_length);
-}
-
 static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
 {
 	if (!rr3->transmitting && (code != 0x40))
@@ -265,8 +259,7 @@ static void redrat3_dump_fw_error(struct
 
 	/* Codes 0x20 through 0x2f are IR Firmware Errors */
 	case 0x20:
-		pr_cont("Initial signal pulse not long enough "
-			"to measure carrier frequency\n");
+		pr_cont("Initial signal pulse not long enough to measure carrier frequency\n");
 		break;
 	case 0x21:
 		pr_cont("Not enough length values allocated for signal\n");
@@ -278,18 +271,15 @@ static void redrat3_dump_fw_error(struct
 		pr_cont("Too many signal repeats\n");
 		break;
 	case 0x28:
-		pr_cont("Insufficient memory available for IR signal "
-			"data memory allocation\n");
+		pr_cont("Insufficient memory available for IR signal data memory allocation\n");
 		break;
 	case 0x29:
-		pr_cont("Insufficient memory available "
-			"for IrDa signal data memory allocation\n");
+		pr_cont("Insufficient memory available for IrDa signal data memory allocation\n");
 		break;
 
 	/* Codes 0x30 through 0x3f are USB Firmware Errors */
 	case 0x30:
-		pr_cont("Insufficient memory available for bulk "
-			"transfer structure\n");
+		pr_cont("Insufficient memory available for bulk transfer structure\n");
 		break;
 
 	/*
@@ -301,8 +291,7 @@ static void redrat3_dump_fw_error(struct
 			pr_cont("Signal capture has been terminated\n");
 		break;
 	case 0x41:
-		pr_cont("Attempt to set/get and unknown signal I/O "
-			"algorithm parameter\n");
+		pr_cont("Attempt to set/get and unknown signal I/O algorithm parameter\n");
 		break;
 	case 0x42:
 		pr_cont("Signal capture already started\n");
@@ -368,15 +357,18 @@ static void redrat3_process_ir_data(stru
 	unsigned int i, sig_size, single_len, offset, val;
 	u32 mod_freq;
 
-	if (!rr3) {
-		pr_err("%s called with no context!\n", __func__);
-		return;
-	}
-
 	dev = rr3->dev;
 
 	mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
 	dev_dbg(dev, "Got mod_freq of %u\n", mod_freq);
+	if (mod_freq && rr3->wideband) {
+		DEFINE_IR_RAW_EVENT(ev);
+
+		ev.carrier_report = 1;
+		ev.carrier = mod_freq;
+
+		ir_raw_event_store(rr3->rc, &ev);
+	}
 
 	/* process each rr3 encoded byte into an int */
 	sig_size = be16_to_cpu(rr3->irdata.sig_size);
@@ -459,19 +451,31 @@ static int redrat3_enable_detector(struc
 		return -EIO;
 	}
 
-	redrat3_issue_async(rr3);
+	ret = usb_submit_urb(rr3->narrow_urb, GFP_KERNEL);
+	if (ret) {
+		dev_err(rr3->dev, "narrow band urb failed: %d", ret);
+		return ret;
+	}
 
-	return 0;
+	ret = usb_submit_urb(rr3->wide_urb, GFP_KERNEL);
+	if (ret)
+		dev_err(rr3->dev, "wide band urb failed: %d", ret);
+
+	return ret;
 }
 
 static inline void redrat3_delete(struct redrat3_dev *rr3,
 				  struct usb_device *udev)
 {
-	usb_kill_urb(rr3->read_urb);
+	usb_kill_urb(rr3->narrow_urb);
+	usb_kill_urb(rr3->wide_urb);
 	usb_kill_urb(rr3->flash_urb);
-	usb_free_urb(rr3->read_urb);
+	usb_kill_urb(rr3->learn_urb);
+	usb_free_urb(rr3->narrow_urb);
+	usb_free_urb(rr3->wide_urb);
 	usb_free_urb(rr3->flash_urb);
-	usb_free_coherent(udev, le16_to_cpu(rr3->ep_in->wMaxPacketSize),
+	usb_free_urb(rr3->learn_urb);
+	usb_free_coherent(udev, le16_to_cpu(rr3->ep_narrow->wMaxPacketSize),
 			  rr3->bulk_in_buf, rr3->dma_in);
 
 	kfree(rr3);
@@ -485,10 +489,8 @@ static u32 redrat3_get_timeout(struct re
 
 	len = sizeof(*tmp);
 	tmp = kzalloc(len, GFP_KERNEL);
-	if (!tmp) {
-		dev_warn(rr3->dev, "Memory allocation faillure\n");
+	if (!tmp)
 		return timeout;
-	}
 
 	pipe = usb_rcvctrlpipe(rr3->udev, 0);
 	ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
@@ -543,16 +545,14 @@ static void redrat3_reset(struct redrat3
 	struct device *dev = rr3->dev;
 	int rc, rxpipe, txpipe;
 	u8 *val;
-	int len = sizeof(u8);
+	size_t const len = sizeof(*val);
 
 	rxpipe = usb_rcvctrlpipe(udev, 0);
 	txpipe = usb_sndctrlpipe(udev, 0);
 
 	val = kmalloc(len, GFP_KERNEL);
-	if (!val) {
-		dev_err(dev, "Memory allocation failure\n");
+	if (!val)
 		return;
-	}
 
 	*val = 0x01;
 	rc = usb_control_msg(udev, rxpipe, RR3_RESET,
@@ -590,14 +590,12 @@ static void redrat3_reset(struct redrat3
 
 static void redrat3_get_firmware_rev(struct redrat3_dev *rr3)
 {
-	int rc = 0;
+	int rc;
 	char *buffer;
 
-	buffer = kzalloc(sizeof(char) * (RR3_FW_VERSION_LEN + 1), GFP_KERNEL);
-	if (!buffer) {
-		dev_err(rr3->dev, "Memory allocation failure\n");
+	buffer = kcalloc(RR3_FW_VERSION_LEN + 1, sizeof(*buffer), GFP_KERNEL);
+	if (!buffer)
 		return;
-	}
 
 	rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0),
 			     RR3_FW_VERSION,
@@ -704,25 +702,25 @@ out:
 /* callback function from USB when async USB request has completed */
 static void redrat3_handle_async(struct urb *urb)
 {
-	struct redrat3_dev *rr3;
+	struct redrat3_dev *rr3 = urb->context;
 	int ret;
 
-	if (!urb)
-		return;
-
-	rr3 = urb->context;
-	if (!rr3) {
-		pr_err("%s called with invalid context!\n", __func__);
-		usb_unlink_urb(urb);
-		return;
-	}
-
 	switch (urb->status) {
 	case 0:
 		ret = redrat3_get_ir_data(rr3, urb->actual_length);
+		if (!ret && rr3->wideband && !rr3->learn_urb->hcpriv) {
+			ret = usb_submit_urb(rr3->learn_urb, GFP_ATOMIC);
+			if (ret)
+				dev_err(rr3->dev, "Failed to submit learning urb: %d",
+									ret);
+		}
+
 		if (!ret) {
 			/* no error, prepare to read more */
-			redrat3_issue_async(rr3);
+			ret = usb_submit_urb(urb, GFP_ATOMIC);
+			if (ret)
+				dev_err(rr3->dev, "Failed to resubmit urb: %d",
+									ret);
 		}
 		break;
 
@@ -785,11 +783,11 @@ static int redrat3_transmit_ir(struct rc
 	/* rr3 will disable rc detector on transmit */
 	rr3->transmitting = true;
 
-	sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
-	if (!sample_lens) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	sample_lens = kcalloc(RR3_DRIVER_MAXLENS,
+			      sizeof(*sample_lens),
+			      GFP_KERNEL);
+	if (!sample_lens)
+		return -ENOMEM;
 
 	irdata = kzalloc(sizeof(*irdata), GFP_KERNEL);
 	if (!irdata) {
@@ -857,8 +855,8 @@ static int redrat3_transmit_ir(struct rc
 		ret = count;
 
 out:
-	kfree(sample_lens);
 	kfree(irdata);
+	kfree(sample_lens);
 
 	rr3->transmitting = false;
 	/* rr3 re-enables rc detector because it was enabled before */
@@ -882,6 +880,42 @@ static void redrat3_brightness_set(struc
 	}
 }
 
+static int redrat3_wideband_receiver(struct rc_dev *rcdev, int enable)
+{
+	struct redrat3_dev *rr3 = rcdev->priv;
+	int ret = 0;
+
+	rr3->wideband = enable != 0;
+
+	if (enable) {
+		ret = usb_submit_urb(rr3->learn_urb, GFP_KERNEL);
+		if (ret)
+			dev_err(rr3->dev, "Failed to submit learning urb: %d",
+									ret);
+	}
+
+	return ret;
+}
+
+static void redrat3_learn_complete(struct urb *urb)
+{
+	struct redrat3_dev *rr3 = urb->context;
+
+	switch (urb->status) {
+	case 0:
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		usb_unlink_urb(urb);
+		return;
+	case -EPIPE:
+	default:
+		dev_err(rr3->dev, "Error: learn urb status = %d", urb->status);
+		break;
+	}
+}
+
 static void redrat3_led_complete(struct urb *urb)
 {
 	struct redrat3_dev *rr3 = urb->context;
@@ -908,19 +942,16 @@ static struct rc_dev *redrat3_init_rc_de
 {
 	struct device *dev = rr3->dev;
 	struct rc_dev *rc;
-	int ret = -ENODEV;
+	int ret;
 	u16 prod = le16_to_cpu(rr3->udev->descriptor.idProduct);
 
 	rc = rc_allocate_device();
-	if (!rc) {
-		dev_err(dev, "remote input dev allocation failed\n");
-		goto out;
-	}
+	if (!rc)
+		return NULL;
 
-	snprintf(rr3->name, sizeof(rr3->name), "RedRat3%s "
-		 "Infrared Remote Transceiver (%04x:%04x)",
-		 prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "",
-		 le16_to_cpu(rr3->udev->descriptor.idVendor), prod);
+	snprintf(rr3->name, sizeof(rr3->name),
+		 "RedRat3%s Infrared Remote Transceiver",
+		 prod == USB_RR3IIUSB_PRODUCT_ID ? "-II" : "");
 
 	usb_make_path(rr3->udev, rr3->phys, sizeof(rr3->phys));
 
@@ -937,6 +968,7 @@ static struct rc_dev *redrat3_init_rc_de
 	rc->s_timeout = redrat3_set_timeout;
 	rc->tx_ir = redrat3_transmit_ir;
 	rc->s_tx_carrier = redrat3_set_tx_carrier;
+	rc->s_carrier_report = redrat3_wideband_receiver;
 	rc->driver_name = DRIVER_NAME;
 	rc->rx_resolution = US_TO_NS(2);
 	rc->map_name = RC_MAP_HAUPPAUGE;
@@ -962,7 +994,8 @@ static int redrat3_dev_probe(struct usb_
 	struct usb_host_interface *uhi;
 	struct redrat3_dev *rr3;
 	struct usb_endpoint_descriptor *ep;
-	struct usb_endpoint_descriptor *ep_in = NULL;
+	struct usb_endpoint_descriptor *ep_narrow = NULL;
+	struct usb_endpoint_descriptor *ep_wide = NULL;
 	struct usb_endpoint_descriptor *ep_out = NULL;
 	u8 addr, attrs;
 	int pipe, i;
@@ -976,15 +1009,16 @@ static int redrat3_dev_probe(struct usb_
 		addr = ep->bEndpointAddress;
 		attrs = ep->bmAttributes;
 
-		if ((ep_in == NULL) &&
-		    ((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
+		if (((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
 		    ((attrs & USB_ENDPOINT_XFERTYPE_MASK) ==
 		     USB_ENDPOINT_XFER_BULK)) {
 			dev_dbg(dev, "found bulk-in endpoint at 0x%02x\n",
 				ep->bEndpointAddress);
-			/* data comes in on 0x82, 0x81 is for other data... */
-			if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR)
-				ep_in = ep;
+			/* data comes in on 0x82, 0x81 is for learning */
+			if (ep->bEndpointAddress == RR3_NARROW_IN_EP_ADDR)
+				ep_narrow = ep;
+			if (ep->bEndpointAddress == RR3_WIDE_IN_EP_ADDR)
+				ep_wide = ep;
 		}
 
 		if ((ep_out == NULL) &&
@@ -997,68 +1031,76 @@ static int redrat3_dev_probe(struct usb_
 		}
 	}
 
-	if (!ep_in || !ep_out) {
-		dev_err(dev, "Couldn't find both in and out endpoints\n");
+	if (!ep_narrow || !ep_out || !ep_wide) {
+		dev_err(dev, "Couldn't find all endpoints\n");
 		retval = -ENODEV;
 		goto no_endpoints;
 	}
 
 	/* allocate memory for our device state and initialize it */
 	rr3 = kzalloc(sizeof(*rr3), GFP_KERNEL);
-	if (rr3 == NULL) {
-		dev_err(dev, "Memory allocation failure\n");
+	if (!rr3)
 		goto no_endpoints;
-	}
 
 	rr3->dev = &intf->dev;
+	rr3->ep_narrow = ep_narrow;
+	rr3->ep_out = ep_out;
+	rr3->udev = udev;
 
 	/* set up bulk-in endpoint */
-	rr3->read_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!rr3->read_urb)
-		goto error;
+	rr3->narrow_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!rr3->narrow_urb)
+		goto redrat_free;
+
+	rr3->wide_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!rr3->wide_urb)
+		goto redrat_free;
 
-	rr3->ep_in = ep_in;
 	rr3->bulk_in_buf = usb_alloc_coherent(udev,
-		le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
-	if (!rr3->bulk_in_buf) {
-		dev_err(dev, "Read buffer allocation failure\n");
-		goto error;
-	}
+		le16_to_cpu(ep_narrow->wMaxPacketSize),
+		GFP_KERNEL, &rr3->dma_in);
+	if (!rr3->bulk_in_buf)
+		goto redrat_free;
 
-	pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
-	usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
-		le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3);
-	rr3->read_urb->transfer_dma = rr3->dma_in;
-	rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	pipe = usb_rcvbulkpipe(udev, ep_narrow->bEndpointAddress);
+	usb_fill_bulk_urb(rr3->narrow_urb, udev, pipe, rr3->bulk_in_buf,
+		le16_to_cpu(ep_narrow->wMaxPacketSize),
+		redrat3_handle_async, rr3);
+	rr3->narrow_urb->transfer_dma = rr3->dma_in;
+	rr3->narrow_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
-	rr3->ep_out = ep_out;
-	rr3->udev = udev;
+	pipe = usb_rcvbulkpipe(udev, ep_wide->bEndpointAddress);
+	usb_fill_bulk_urb(rr3->wide_urb, udev, pipe, rr3->bulk_in_buf,
+		le16_to_cpu(ep_narrow->wMaxPacketSize),
+		redrat3_handle_async, rr3);
+	rr3->wide_urb->transfer_dma = rr3->dma_in;
+	rr3->wide_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	redrat3_reset(rr3);
 	redrat3_get_firmware_rev(rr3);
 
-	/* might be all we need to do? */
-	retval = redrat3_enable_detector(rr3);
-	if (retval < 0)
-		goto error;
-
 	/* default.. will get overridden by any sends with a freq defined */
 	rr3->carrier = 38000;
 
-	/* led control */
-	rr3->led.name = "redrat3:red:feedback";
-	rr3->led.default_trigger = "rc-feedback";
-	rr3->led.brightness_set = redrat3_brightness_set;
-	retval = led_classdev_register(&intf->dev, &rr3->led);
-	if (retval)
-		goto error;
-
 	atomic_set(&rr3->flash, 0);
 	rr3->flash_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!rr3->flash_urb) {
-		retval = -ENOMEM;
-		goto led_free_error;
-	}
+	if (!rr3->flash_urb)
+		goto redrat_free;
+
+	/* learn urb */
+	rr3->learn_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!rr3->learn_urb)
+		goto redrat_free;
+
+	/* setup packet is 'c0 b2 0000 0000 0001' */
+	rr3->learn_control.bRequestType = 0xc0;
+	rr3->learn_control.bRequest = RR3_MODSIG_CAPTURE;
+	rr3->learn_control.wLength = cpu_to_le16(1);
+
+	usb_fill_control_urb(rr3->learn_urb, udev, usb_rcvctrlpipe(udev, 0),
+			(unsigned char *)&rr3->learn_control,
+			&rr3->learn_buf, sizeof(rr3->learn_buf),
+			redrat3_learn_complete, rr3);
 
 	/* setup packet is 'c0 b9 0000 0000 0001' */
 	rr3->flash_control.bRequestType = 0xc0;
@@ -1070,25 +1112,36 @@ static int redrat3_dev_probe(struct usb_
 			&rr3->flash_in_buf, sizeof(rr3->flash_in_buf),
 			redrat3_led_complete, rr3);
 
+	/* led control */
+	rr3->led.name = "redrat3:red:feedback";
+	rr3->led.default_trigger = "rc-feedback";
+	rr3->led.brightness_set = redrat3_brightness_set;
+	retval = led_classdev_register(&intf->dev, &rr3->led);
+	if (retval)
+		goto redrat_free;
+
 	rr3->rc = redrat3_init_rc_dev(rr3);
 	if (!rr3->rc) {
 		retval = -ENOMEM;
-		goto led_free_error;
+		goto led_free;
 	}
 
+	/* might be all we need to do? */
+	retval = redrat3_enable_detector(rr3);
+	if (retval < 0)
+		goto led_free;
+
 	/* we can register the device now, as it is ready */
 	usb_set_intfdata(intf, rr3);
 
 	return 0;
 
-led_free_error:
+led_free:
 	led_classdev_unregister(&rr3->led);
-error:
+redrat_free:
 	redrat3_delete(rr3, rr3->udev);
 
 no_endpoints:
-	dev_err(dev, "%s: retval = %x", __func__, retval);
-
 	return retval;
 }
 
@@ -1097,9 +1150,6 @@ static void redrat3_dev_disconnect(struc
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct redrat3_dev *rr3 = usb_get_intfdata(intf);
 
-	if (!rr3)
-		return;
-
 	usb_set_intfdata(intf, NULL);
 	rc_unregister_device(rr3->rc);
 	led_classdev_unregister(&rr3->led);
@@ -1111,7 +1161,8 @@ static int redrat3_dev_suspend(struct us
 	struct redrat3_dev *rr3 = usb_get_intfdata(intf);
 
 	led_classdev_suspend(&rr3->led);
-	usb_kill_urb(rr3->read_urb);
+	usb_kill_urb(rr3->narrow_urb);
+	usb_kill_urb(rr3->wide_urb);
 	usb_kill_urb(rr3->flash_urb);
 	return 0;
 }
@@ -1120,7 +1171,9 @@ static int redrat3_dev_resume(struct usb
 {
 	struct redrat3_dev *rr3 = usb_get_intfdata(intf);
 
-	if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC))
+	if (usb_submit_urb(rr3->narrow_urb, GFP_ATOMIC))
+		return -EIO;
+	if (usb_submit_urb(rr3->wide_urb, GFP_ATOMIC))
 		return -EIO;
 	led_classdev_resume(&rr3->led);
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/serial_ir.c linux-libre-4.10-rc8-gnu/drivers/media/rc/serial_ir.c
--- linux-libre-4.9-gnu/drivers/media/rc/serial_ir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/serial_ir.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,844 @@
+/*
+ * serial_ir.c
+ *
+ * serial_ir - Device driver that records pulse- and pause-lengths
+ *	       (space-lengths) between DDCD event on a serial port.
+ *
+ * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de>
+ * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
+ * Copyright (C) 1998 Ben Pfaff <blp@gnu.org>
+ * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de>
+ * Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support)
+ * Copyright (C) 2016 Sean Young <sean@mess.org> (port to rc-core)
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <media/rc-core.h>
+
+struct serial_ir_hw {
+	int signal_pin;
+	int signal_pin_change;
+	u8 on;
+	u8 off;
+	unsigned set_send_carrier:1;
+	unsigned set_duty_cycle:1;
+	void (*send_pulse)(unsigned int length, ktime_t edge);
+	void (*send_space)(void);
+	spinlock_t lock;
+};
+
+#define IR_HOMEBREW	0
+#define IR_IRDEO	1
+#define IR_IRDEO_REMOTE	2
+#define IR_ANIMAX	3
+#define IR_IGOR		4
+
+/* module parameters */
+static int type;
+static int io;
+static int irq;
+static bool iommap;
+static int ioshift;
+static bool softcarrier = true;
+static bool share_irq;
+static int sense = -1;	/* -1 = auto, 0 = active high, 1 = active low */
+static bool txsense;	/* 0 = active high, 1 = active low */
+
+/* forward declarations */
+static void send_pulse_irdeo(unsigned int length, ktime_t edge);
+static void send_space_irdeo(void);
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+static void send_pulse_homebrew(unsigned int length, ktime_t edge);
+static void send_space_homebrew(void);
+#endif
+
+static struct serial_ir_hw hardware[] = {
+	[IR_HOMEBREW] = {
+		.lock = __SPIN_LOCK_UNLOCKED(hardware[IR_HOMEBREW].lock),
+		.signal_pin	   = UART_MSR_DCD,
+		.signal_pin_change = UART_MSR_DDCD,
+		.on  = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
+		.off = (UART_MCR_RTS | UART_MCR_OUT2),
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+		.send_pulse = send_pulse_homebrew,
+		.send_space = send_space_homebrew,
+		.set_send_carrier = true,
+		.set_duty_cycle = true,
+#endif
+	},
+
+	[IR_IRDEO] = {
+		.lock = __SPIN_LOCK_UNLOCKED(hardware[IR_IRDEO].lock),
+		.signal_pin	   = UART_MSR_DSR,
+		.signal_pin_change = UART_MSR_DDSR,
+		.on  = UART_MCR_OUT2,
+		.off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+		.send_pulse = send_pulse_irdeo,
+		.send_space = send_space_irdeo,
+		.set_duty_cycle = true,
+	},
+
+	[IR_IRDEO_REMOTE] = {
+		.lock = __SPIN_LOCK_UNLOCKED(hardware[IR_IRDEO_REMOTE].lock),
+		.signal_pin	   = UART_MSR_DSR,
+		.signal_pin_change = UART_MSR_DDSR,
+		.on  = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+		.off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+		.send_pulse = send_pulse_irdeo,
+		.send_space = send_space_irdeo,
+		.set_duty_cycle = true,
+	},
+
+	[IR_ANIMAX] = {
+		.lock = __SPIN_LOCK_UNLOCKED(hardware[IR_ANIMAX].lock),
+		.signal_pin	   = UART_MSR_DCD,
+		.signal_pin_change = UART_MSR_DDCD,
+		.on  = 0,
+		.off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2),
+	},
+
+	[IR_IGOR] = {
+		.lock = __SPIN_LOCK_UNLOCKED(hardware[IR_IGOR].lock),
+		.signal_pin	   = UART_MSR_DSR,
+		.signal_pin_change = UART_MSR_DDSR,
+		.on  = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR),
+		.off = (UART_MCR_RTS | UART_MCR_OUT2),
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+		.send_pulse = send_pulse_homebrew,
+		.send_space = send_space_homebrew,
+		.set_send_carrier = true,
+		.set_duty_cycle = true,
+#endif
+	},
+};
+
+#define RS_ISR_PASS_LIMIT 256
+
+struct serial_ir {
+	ktime_t lastkt;
+	struct rc_dev *rcdev;
+	struct platform_device *pdev;
+
+	unsigned int freq;
+	unsigned int duty_cycle;
+
+	unsigned int pulse_width, space_width;
+};
+
+static struct serial_ir serial_ir;
+
+/* fetch serial input packet (1 byte) from register offset */
+static u8 sinp(int offset)
+{
+	if (iommap)
+		/* the register is memory-mapped */
+		offset <<= ioshift;
+
+	return inb(io + offset);
+}
+
+/* write serial output packet (1 byte) of value to register offset */
+static void soutp(int offset, u8 value)
+{
+	if (iommap)
+		/* the register is memory-mapped */
+		offset <<= ioshift;
+
+	outb(value, io + offset);
+}
+
+static void on(void)
+{
+	if (txsense)
+		soutp(UART_MCR, hardware[type].off);
+	else
+		soutp(UART_MCR, hardware[type].on);
+}
+
+static void off(void)
+{
+	if (txsense)
+		soutp(UART_MCR, hardware[type].on);
+	else
+		soutp(UART_MCR, hardware[type].off);
+}
+
+static void init_timing_params(unsigned int new_duty_cycle,
+			       unsigned int new_freq)
+{
+	serial_ir.duty_cycle = new_duty_cycle;
+	serial_ir.freq = new_freq;
+
+	serial_ir.pulse_width = DIV_ROUND_CLOSEST(
+		new_duty_cycle * NSEC_PER_SEC, new_freq * 100l);
+	serial_ir.space_width = DIV_ROUND_CLOSEST(
+		(100l - new_duty_cycle) * NSEC_PER_SEC, new_freq * 100l);
+}
+
+static void send_pulse_irdeo(unsigned int length, ktime_t target)
+{
+	long rawbits;
+	int i;
+	unsigned char output;
+	unsigned char chunk, shifted;
+
+	/* how many bits have to be sent ? */
+	rawbits = length * 1152 / 10000;
+	if (serial_ir.duty_cycle > 50)
+		chunk = 3;
+	else
+		chunk = 1;
+	for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) {
+		shifted = chunk << (i * 3);
+		shifted >>= 1;
+		output &= (~shifted);
+		i++;
+		if (i == 3) {
+			soutp(UART_TX, output);
+			while (!(sinp(UART_LSR) & UART_LSR_THRE))
+				;
+			output = 0x7f;
+			i = 0;
+		}
+	}
+	if (i != 0) {
+		soutp(UART_TX, output);
+		while (!(sinp(UART_LSR) & UART_LSR_TEMT))
+			;
+	}
+}
+
+static void send_space_irdeo(void)
+{
+}
+
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+static void send_pulse_homebrew_softcarrier(unsigned int length, ktime_t edge)
+{
+	ktime_t now, target = ktime_add_us(edge, length);
+	/*
+	 * delta should never exceed 4 seconds and on m68k
+	 * ndelay(s64) does not compile; so use s32 rather than s64.
+	 */
+	s32 delta;
+
+	for (;;) {
+		now = ktime_get();
+		if (ktime_compare(now, target) >= 0)
+			break;
+		on();
+		edge = ktime_add_ns(edge, serial_ir.pulse_width);
+		delta = ktime_to_ns(ktime_sub(edge, now));
+		if (delta > 0)
+			ndelay(delta);
+		now = ktime_get();
+		off();
+		if (ktime_compare(now, target) >= 0)
+			break;
+		edge = ktime_add_ns(edge, serial_ir.space_width);
+		delta = ktime_to_ns(ktime_sub(edge, now));
+		if (delta > 0)
+			ndelay(delta);
+	}
+}
+
+static void send_pulse_homebrew(unsigned int length, ktime_t edge)
+{
+	if (softcarrier)
+		send_pulse_homebrew_softcarrier(length, edge);
+	else
+		on();
+}
+
+static void send_space_homebrew(void)
+{
+	off();
+}
+#endif
+
+static void frbwrite(unsigned int l, bool is_pulse)
+{
+	/* simple noise filter */
+	static unsigned int ptr, pulse, space;
+	DEFINE_IR_RAW_EVENT(ev);
+
+	if (ptr > 0 && is_pulse) {
+		pulse += l;
+		if (pulse > 250000) {
+			ev.duration = space;
+			ev.pulse = false;
+			ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+			ev.duration = pulse;
+			ev.pulse = true;
+			ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+			ptr = 0;
+			pulse = 0;
+		}
+		return;
+	}
+	if (!is_pulse) {
+		if (ptr == 0) {
+			if (l > 20000000) {
+				space = l;
+				ptr++;
+				return;
+			}
+		} else {
+			if (l > 20000000) {
+				space += pulse;
+				if (space > IR_MAX_DURATION)
+					space = IR_MAX_DURATION;
+				space += l;
+				if (space > IR_MAX_DURATION)
+					space = IR_MAX_DURATION;
+				pulse = 0;
+				return;
+			}
+
+			ev.duration = space;
+			ev.pulse = false;
+			ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+			ev.duration = pulse;
+			ev.pulse = true;
+			ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+			ptr = 0;
+			pulse = 0;
+		}
+	}
+
+	ev.duration = l;
+	ev.pulse = is_pulse;
+	ir_raw_event_store_with_filter(serial_ir.rcdev, &ev);
+}
+
+static irqreturn_t serial_ir_irq_handler(int i, void *blah)
+{
+	ktime_t kt;
+	int counter, dcd;
+	u8 status;
+	ktime_t delkt;
+	unsigned int data;
+	static int last_dcd = -1;
+
+	if ((sinp(UART_IIR) & UART_IIR_NO_INT)) {
+		/* not our interrupt */
+		return IRQ_NONE;
+	}
+
+	counter = 0;
+	do {
+		counter++;
+		status = sinp(UART_MSR);
+		if (counter > RS_ISR_PASS_LIMIT) {
+			dev_err(&serial_ir.pdev->dev, "Trapped in interrupt");
+			break;
+		}
+		if ((status & hardware[type].signal_pin_change) &&
+		    sense != -1) {
+			/* get current time */
+			kt = ktime_get();
+
+			/*
+			 * The driver needs to know if your receiver is
+			 * active high or active low, or the space/pulse
+			 * sense could be inverted.
+			 */
+
+			/* calc time since last interrupt in nanoseconds */
+			dcd = (status & hardware[type].signal_pin) ? 1 : 0;
+
+			if (dcd == last_dcd) {
+				dev_err(&serial_ir.pdev->dev,
+					"ignoring spike: %d %d %lldns %lldns\n",
+					dcd, sense, ktime_to_ns(kt),
+					ktime_to_ns(serial_ir.lastkt));
+				continue;
+			}
+
+			delkt = ktime_sub(kt, serial_ir.lastkt);
+			if (ktime_compare(delkt, ktime_set(15, 0)) > 0) {
+				data = IR_MAX_DURATION; /* really long time */
+				if (!(dcd ^ sense)) {
+					/* sanity check */
+					dev_err(&serial_ir.pdev->dev,
+						"dcd unexpected: %d %d %lldns %lldns\n",
+						dcd, sense, ktime_to_ns(kt),
+						ktime_to_ns(serial_ir.lastkt));
+					/*
+					 * detecting pulse while this
+					 * MUST be a space!
+					 */
+					sense = sense ? 0 : 1;
+				}
+			} else {
+				data = ktime_to_ns(delkt);
+			}
+			frbwrite(data, !(dcd ^ sense));
+			serial_ir.lastkt = kt;
+			last_dcd = dcd;
+			ir_raw_event_handle(serial_ir.rcdev);
+		}
+	} while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */
+	return IRQ_HANDLED;
+}
+
+static int hardware_init_port(void)
+{
+	u8 scratch, scratch2, scratch3;
+
+	/*
+	 * This is a simple port existence test, borrowed from the autoconfig
+	 * function in drivers/tty/serial/8250/8250_port.c
+	 */
+	scratch = sinp(UART_IER);
+	soutp(UART_IER, 0);
+#ifdef __i386__
+	outb(0xff, 0x080);
+#endif
+	scratch2 = sinp(UART_IER) & 0x0f;
+	soutp(UART_IER, 0x0f);
+#ifdef __i386__
+	outb(0x00, 0x080);
+#endif
+	scratch3 = sinp(UART_IER) & 0x0f;
+	soutp(UART_IER, scratch);
+	if (scratch2 != 0 || scratch3 != 0x0f) {
+		/* we fail, there's nothing here */
+		pr_err("port existence test failed, cannot continue\n");
+		return -ENODEV;
+	}
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* First of all, disable all interrupts */
+	soutp(UART_IER, sinp(UART_IER) &
+	      (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));
+
+	/* Clear registers. */
+	sinp(UART_LSR);
+	sinp(UART_RX);
+	sinp(UART_IIR);
+	sinp(UART_MSR);
+
+	/* Set line for power source */
+	off();
+
+	/* Clear registers again to be sure. */
+	sinp(UART_LSR);
+	sinp(UART_RX);
+	sinp(UART_IIR);
+	sinp(UART_MSR);
+
+	switch (type) {
+	case IR_IRDEO:
+	case IR_IRDEO_REMOTE:
+		/* setup port to 7N1 @ 115200 Baud */
+		/* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */
+
+		/* Set DLAB 1. */
+		soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB);
+		/* Set divisor to 1 => 115200 Baud */
+		soutp(UART_DLM, 0);
+		soutp(UART_DLL, 1);
+		/* Set DLAB 0 +  7N1 */
+		soutp(UART_LCR, UART_LCR_WLEN7);
+		/* THR interrupt already disabled at this point */
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int serial_ir_probe(struct platform_device *dev)
+{
+	int i, nlow, nhigh, result;
+
+	result = devm_request_irq(&dev->dev, irq, serial_ir_irq_handler,
+				  share_irq ? IRQF_SHARED : 0,
+				  KBUILD_MODNAME, &hardware);
+	if (result < 0) {
+		if (result == -EBUSY)
+			dev_err(&dev->dev, "IRQ %d busy\n", irq);
+		else if (result == -EINVAL)
+			dev_err(&dev->dev, "Bad irq number or handler\n");
+		return result;
+	}
+
+	/* Reserve io region. */
+	if ((iommap &&
+	     (devm_request_mem_region(&dev->dev, iommap, 8 << ioshift,
+				      KBUILD_MODNAME) == NULL)) ||
+	     (!iommap && (devm_request_region(&dev->dev, io, 8,
+			  KBUILD_MODNAME) == NULL))) {
+		dev_err(&dev->dev, "port %04x already in use\n", io);
+		dev_warn(&dev->dev, "use 'setserial /dev/ttySX uart none'\n");
+		dev_warn(&dev->dev,
+			 "or compile the serial port driver as module and\n");
+		dev_warn(&dev->dev, "make sure this module is loaded first\n");
+		return -EBUSY;
+	}
+
+	result = hardware_init_port();
+	if (result < 0)
+		return result;
+
+	/* Initialize pulse/space widths */
+	init_timing_params(50, 38000);
+
+	/* If pin is high, then this must be an active low receiver. */
+	if (sense == -1) {
+		/* wait 1/2 sec for the power supply */
+		msleep(500);
+
+		/*
+		 * probe 9 times every 0.04s, collect "votes" for
+		 * active high/low
+		 */
+		nlow = 0;
+		nhigh = 0;
+		for (i = 0; i < 9; i++) {
+			if (sinp(UART_MSR) & hardware[type].signal_pin)
+				nlow++;
+			else
+				nhigh++;
+			msleep(40);
+		}
+		sense = nlow >= nhigh ? 1 : 0;
+		dev_info(&dev->dev, "auto-detected active %s receiver\n",
+			 sense ? "low" : "high");
+	} else
+		dev_info(&dev->dev, "Manually using active %s receiver\n",
+			 sense ? "low" : "high");
+
+	dev_dbg(&dev->dev, "Interrupt %d, port %04x obtained\n", irq, io);
+	return 0;
+}
+
+static int serial_ir_open(struct rc_dev *rcdev)
+{
+	unsigned long flags;
+
+	/* initialize timestamp */
+	serial_ir.lastkt = ktime_get();
+
+	spin_lock_irqsave(&hardware[type].lock, flags);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	soutp(UART_IER, sinp(UART_IER) | UART_IER_MSI);
+
+	spin_unlock_irqrestore(&hardware[type].lock, flags);
+
+	return 0;
+}
+
+static void serial_ir_close(struct rc_dev *rcdev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hardware[type].lock, flags);
+
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* First of all, disable all interrupts */
+	soutp(UART_IER, sinp(UART_IER) &
+	      (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));
+	spin_unlock_irqrestore(&hardware[type].lock, flags);
+}
+
+static int serial_ir_tx(struct rc_dev *dev, unsigned int *txbuf,
+			unsigned int count)
+{
+	unsigned long flags;
+	ktime_t edge;
+	s64 delta;
+	int i;
+
+	spin_lock_irqsave(&hardware[type].lock, flags);
+	if (type == IR_IRDEO) {
+		/* DTR, RTS down */
+		on();
+	}
+
+	edge = ktime_get();
+	for (i = 0; i < count; i++) {
+		if (i % 2)
+			hardware[type].send_space();
+		else
+			hardware[type].send_pulse(txbuf[i], edge);
+
+		edge = ktime_add_us(edge, txbuf[i]);
+		delta = ktime_us_delta(edge, ktime_get());
+		if (delta > 25) {
+			spin_unlock_irqrestore(&hardware[type].lock, flags);
+			usleep_range(delta - 25, delta + 25);
+			spin_lock_irqsave(&hardware[type].lock, flags);
+		} else if (delta > 0) {
+			udelay(delta);
+		}
+	}
+	off();
+	spin_unlock_irqrestore(&hardware[type].lock, flags);
+	return count;
+}
+
+static int serial_ir_tx_duty_cycle(struct rc_dev *dev, u32 cycle)
+{
+	init_timing_params(cycle, serial_ir.freq);
+	return 0;
+}
+
+static int serial_ir_tx_carrier(struct rc_dev *dev, u32 carrier)
+{
+	if (carrier > 500000 || carrier < 20000)
+		return -EINVAL;
+
+	init_timing_params(serial_ir.duty_cycle, carrier);
+	return 0;
+}
+
+static int serial_ir_suspend(struct platform_device *dev,
+			     pm_message_t state)
+{
+	/* Set DLAB 0. */
+	soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
+
+	/* Disable all interrupts */
+	soutp(UART_IER, sinp(UART_IER) &
+	      (~(UART_IER_MSI | UART_IER_RLSI | UART_IER_THRI | UART_IER_RDI)));
+
+	/* Clear registers. */
+	sinp(UART_LSR);
+	sinp(UART_RX);
+	sinp(UART_IIR);
+	sinp(UART_MSR);
+
+	return 0;
+}
+
+static int serial_ir_resume(struct platform_device *dev)
+{
+	unsigned long flags;
+	int result;
+
+	result = hardware_init_port();
+	if (result < 0)
+		return result;
+
+	spin_lock_irqsave(&hardware[type].lock, flags);
+	/* Enable Interrupt */
+	serial_ir.lastkt = ktime_get();
+	soutp(UART_IER, sinp(UART_IER) | UART_IER_MSI);
+	off();
+
+	spin_unlock_irqrestore(&hardware[type].lock, flags);
+
+	return 0;
+}
+
+static struct platform_driver serial_ir_driver = {
+	.probe		= serial_ir_probe,
+	.suspend	= serial_ir_suspend,
+	.resume		= serial_ir_resume,
+	.driver		= {
+		.name	= "serial_ir",
+	},
+};
+
+static int __init serial_ir_init(void)
+{
+	int result;
+
+	result = platform_driver_register(&serial_ir_driver);
+	if (result)
+		return result;
+
+	serial_ir.pdev = platform_device_alloc("serial_ir", 0);
+	if (!serial_ir.pdev) {
+		result = -ENOMEM;
+		goto exit_driver_unregister;
+	}
+
+	result = platform_device_add(serial_ir.pdev);
+	if (result)
+		goto exit_device_put;
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(serial_ir.pdev);
+exit_driver_unregister:
+	platform_driver_unregister(&serial_ir_driver);
+	return result;
+}
+
+static void serial_ir_exit(void)
+{
+	platform_device_unregister(serial_ir.pdev);
+	platform_driver_unregister(&serial_ir_driver);
+}
+
+static int __init serial_ir_init_module(void)
+{
+	struct rc_dev *rcdev;
+	int result;
+
+	switch (type) {
+	case IR_HOMEBREW:
+	case IR_IRDEO:
+	case IR_IRDEO_REMOTE:
+	case IR_ANIMAX:
+	case IR_IGOR:
+		/* if nothing specified, use ttyS0/com1 and irq 4 */
+		io = io ? io : 0x3f8;
+		irq = irq ? irq : 4;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (!softcarrier) {
+		switch (type) {
+		case IR_HOMEBREW:
+		case IR_IGOR:
+			hardware[type].set_send_carrier = false;
+			hardware[type].set_duty_cycle = false;
+			break;
+		}
+	}
+
+	/* make sure sense is either -1, 0, or 1 */
+	if (sense != -1)
+		sense = !!sense;
+
+	result = serial_ir_init();
+	if (result)
+		return result;
+
+	rcdev = devm_rc_allocate_device(&serial_ir.pdev->dev);
+	if (!rcdev) {
+		result = -ENOMEM;
+		goto serial_cleanup;
+	}
+
+	if (hardware[type].send_pulse && hardware[type].send_space)
+		rcdev->tx_ir = serial_ir_tx;
+	if (hardware[type].set_send_carrier)
+		rcdev->s_tx_carrier = serial_ir_tx_carrier;
+	if (hardware[type].set_duty_cycle)
+		rcdev->s_tx_duty_cycle = serial_ir_tx_duty_cycle;
+
+	switch (type) {
+	case IR_HOMEBREW:
+		rcdev->input_name = "Serial IR type home-brew";
+		break;
+	case IR_IRDEO:
+		rcdev->input_name = "Serial IR type IRdeo";
+		break;
+	case IR_IRDEO_REMOTE:
+		rcdev->input_name = "Serial IR type IRdeo remote";
+		break;
+	case IR_ANIMAX:
+		rcdev->input_name = "Serial IR type AnimaX";
+		break;
+	case IR_IGOR:
+		rcdev->input_name = "Serial IR type IgorPlug";
+		break;
+	}
+
+	rcdev->input_phys = KBUILD_MODNAME "/input0";
+	rcdev->input_id.bustype = BUS_HOST;
+	rcdev->input_id.vendor = 0x0001;
+	rcdev->input_id.product = 0x0001;
+	rcdev->input_id.version = 0x0100;
+	rcdev->open = serial_ir_open;
+	rcdev->close = serial_ir_close;
+	rcdev->dev.parent = &serial_ir.pdev->dev;
+	rcdev->driver_type = RC_DRIVER_IR_RAW;
+	rcdev->allowed_protocols = RC_BIT_ALL;
+	rcdev->driver_name = KBUILD_MODNAME;
+	rcdev->map_name = RC_MAP_RC6_MCE;
+	rcdev->timeout = IR_DEFAULT_TIMEOUT;
+	rcdev->rx_resolution = 250000;
+
+	serial_ir.rcdev = rcdev;
+
+	result = rc_register_device(rcdev);
+
+	if (!result)
+		return 0;
+serial_cleanup:
+	serial_ir_exit();
+	return result;
+}
+
+static void __exit serial_ir_exit_module(void)
+{
+	rc_unregister_device(serial_ir.rcdev);
+	serial_ir_exit();
+}
+
+module_init(serial_ir_init_module);
+module_exit(serial_ir_exit_module);
+
+MODULE_DESCRIPTION("Infra-red receiver driver for serial ports.");
+MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, Christoph Bartelmus, Andrei Tanas");
+MODULE_LICENSE("GPL");
+
+module_param(type, int, 0444);
+MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo, 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug");
+
+module_param(io, int, 0444);
+MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
+
+/* some architectures (e.g. intel xscale) have memory mapped registers */
+module_param(iommap, bool, 0444);
+MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O (0 = no memory mapped io)");
+
+/*
+ * some architectures (e.g. intel xscale) align the 8bit serial registers
+ * on 32bit word boundaries.
+ * See linux-kernel/drivers/tty/serial/8250/8250.c serial_in()/out()
+ */
+module_param(ioshift, int, 0444);
+MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)");
+
+module_param(irq, int, 0444);
+MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
+
+module_param(share_irq, bool, 0444);
+MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)");
+
+module_param(sense, int, 0444);
+MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit (0 = active high, 1 = active low )");
+
+#ifdef CONFIG_IR_SERIAL_TRANSMITTER
+module_param(txsense, bool, 0444);
+MODULE_PARM_DESC(txsense, "Sense of transmitter circuit (0 = active high, 1 = active low )");
+#endif
+
+module_param(softcarrier, bool, 0444);
+MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/streamzap.c linux-libre-4.10-rc8-gnu/drivers/media/rc/streamzap.c
--- linux-libre-4.9-gnu/drivers/media/rc/streamzap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/streamzap.c	2017-02-12 16:03:20.000000000 -0500
@@ -297,8 +297,7 @@ static struct rc_dev *streamzap_init_rc_
 		goto out;
 	}
 
-	snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared "
-		 "Receiver (%04x:%04x)",
+	snprintf(sz->name, sizeof(sz->name), "Streamzap PC Remote Infrared Receiver (%04x:%04x)",
 		 le16_to_cpu(sz->usbdev->descriptor.idVendor),
 		 le16_to_cpu(sz->usbdev->descriptor.idProduct));
 	usb_make_path(sz->usbdev, sz->phys, sizeof(sz->phys));
@@ -364,15 +363,15 @@ static int streamzap_probe(struct usb_in
 
 	sz->endpoint = &(iface_host->endpoint[0].desc);
 	if (!usb_endpoint_dir_in(sz->endpoint)) {
-		dev_err(&intf->dev, "%s: endpoint doesn't match input device "
-			"02%02x\n", __func__, sz->endpoint->bEndpointAddress);
+		dev_err(&intf->dev, "%s: endpoint doesn't match input device 02%02x\n",
+			__func__, sz->endpoint->bEndpointAddress);
 		retval = -ENODEV;
 		goto free_sz;
 	}
 
 	if (!usb_endpoint_xfer_int(sz->endpoint)) {
-		dev_err(&intf->dev, "%s: endpoint attributes don't match xfer "
-			"02%02x\n", __func__, sz->endpoint->bmAttributes);
+		dev_err(&intf->dev, "%s: endpoint attributes don't match xfer 02%02x\n",
+			__func__, sz->endpoint->bmAttributes);
 		retval = -ENODEV;
 		goto free_sz;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/rc/winbond-cir.c linux-libre-4.10-rc8-gnu/drivers/media/rc/winbond-cir.c
--- linux-libre-4.9-gnu/drivers/media/rc/winbond-cir.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/rc/winbond-cir.c	2017-02-12 16:03:20.000000000 -0500
@@ -227,8 +227,7 @@ struct wbcir_data {
 
 static enum wbcir_protocol protocol = IR_PROTOCOL_RC6;
 module_param(protocol, uint, 0444);
-MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command "
-		 "(0 = RC5, 1 = NEC, 2 = RC6A, default)");
+MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command (0 = RC5, 1 = NEC, 2 = RC6A, default)");
 
 static bool invert; /* default = 0 */
 module_param(invert, bool, 0444);
@@ -244,8 +243,7 @@ MODULE_PARM_DESC(wake_sc, "Scancode of t
 
 static unsigned int wake_rc6mode = 6;
 module_param(wake_rc6mode, uint, 0644);
-MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command "
-		 "(0 = 0, 6 = 6A, default)");
+MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command (0 = 0, 6 = 6A, default)");
 
 
 
@@ -660,7 +658,7 @@ wbcir_tx(struct rc_dev *dev, unsigned *b
 	unsigned i;
 	unsigned long flags;
 
-	buf = kmalloc(count * sizeof(*b), GFP_KERNEL);
+	buf = kmalloc_array(count, sizeof(*b), GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
@@ -1050,8 +1048,7 @@ wbcir_probe(struct pnp_dev *device, cons
 		goto exit_free_data;
 	}
 
-	dev_dbg(&device->dev, "Found device "
-		"(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
+	dev_dbg(&device->dev, "Found device (w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
 		data->wbase, data->ebase, data->sbase, data->irq);
 
 	data->led.name = "cir::activity";
@@ -1188,7 +1185,7 @@ static const struct pnp_device_id wbcir_
 MODULE_DEVICE_TABLE(pnp, wbcir_ids);
 
 static struct pnp_driver wbcir_driver = {
-	.name     = WBCIR_NAME,
+	.name     = DRVNAME,
 	.id_table = wbcir_ids,
 	.probe    = wbcir_probe,
 	.remove   = wbcir_remove,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/spi/gs1662.c linux-libre-4.10-rc8-gnu/drivers/media/spi/gs1662.c
--- linux-libre-4.9-gnu/drivers/media/spi/gs1662.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/spi/gs1662.c	2017-02-12 16:03:20.000000000 -0500
@@ -453,17 +453,15 @@ static int gs_probe(struct spi_device *s
 static int gs_remove(struct spi_device *spi)
 {
 	struct v4l2_subdev *sd = spi_get_drvdata(spi);
-	struct gs *gs = to_gs(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	kfree(gs);
+
 	return 0;
 }
 
 static struct spi_driver gs_driver = {
 	.driver = {
 		.name		= "gs1662",
-		.owner		= THIS_MODULE,
 	},
 
 	.probe		= gs_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/fc0011.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/fc0011.c
--- linux-libre-4.9-gnu/drivers/media/tuners/fc0011.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/fc0011.c	2017-02-12 16:03:20.000000000 -0500
@@ -112,12 +112,10 @@ static int fc0011_readreg(struct fc0011_
 	return 0;
 }
 
-static int fc0011_release(struct dvb_frontend *fe)
+static void fc0011_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int fc0011_init(struct dvb_frontend *fe)
@@ -262,8 +260,7 @@ static int fc0011_set_params(struct dvb_
 		regs[FC11_REG_VCOSEL] |= FC11_VCOSEL_BW7M;
 		break;
 	default:
-		dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. "
-			 "Using 6000 kHz.\n",
+		dev_warn(&priv->i2c->dev, "Unsupported bandwidth %u kHz. Using 6000 kHz.\n",
 			 bandwidth);
 		bandwidth = 6000;
 		/* fallthrough */
@@ -435,9 +432,7 @@ static int fc0011_set_params(struct dvb_
 	if (err)
 		return err;
 
-	dev_dbg(&priv->i2c->dev, "Tuned to "
-		"fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X "
-		"vcocal=%02X(%u) bw=%u\n",
+	dev_dbg(&priv->i2c->dev, "Tuned to fa=%02X fp=%02X xin=%02X%02X vco=%02X vcosel=%02X vcocal=%02X(%u) bw=%u\n",
 		(unsigned int)regs[FC11_REG_FA],
 		(unsigned int)regs[FC11_REG_FP],
 		(unsigned int)regs[FC11_REG_XINHI],
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/fc0012.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/fc0012.c
--- linux-libre-4.9-gnu/drivers/media/tuners/fc0012.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/fc0012.c	2017-02-12 16:03:20.000000000 -0500
@@ -55,11 +55,10 @@ static int fc0012_readreg(struct fc0012_
 	return 0;
 }
 
-static int fc0012_release(struct dvb_frontend *fe)
+static void fc0012_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int fc0012_init(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/fc0013.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/fc0013.c
--- linux-libre-4.9-gnu/drivers/media/tuners/fc0013.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/fc0013.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,11 +52,10 @@ static int fc0013_readreg(struct fc0013_
 	return 0;
 }
 
-static int fc0013_release(struct dvb_frontend *fe)
+static void fc0013_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int fc0013_init(struct dvb_frontend *fe)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/max2165.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/max2165.c
--- linux-libre-4.9-gnu/drivers/media/tuners/max2165.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/max2165.c	2017-02-12 16:03:20.000000000 -0500
@@ -370,15 +370,13 @@ static int max2165_init(struct dvb_front
 	return 0;
 }
 
-static int max2165_release(struct dvb_frontend *fe)
+static void max2165_release(struct dvb_frontend *fe)
 {
 	struct max2165_priv *priv = fe->tuner_priv;
 	dprintk("%s()\n", __func__);
 
 	kfree(priv);
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static const struct dvb_tuner_ops max2165_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mc44s803.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mc44s803.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mc44s803.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mc44s803.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,14 +80,12 @@ static int mc44s803_readreg(struct mc44s
 	return 0;
 }
 
-static int mc44s803_release(struct dvb_frontend *fe)
+static void mc44s803_release(struct dvb_frontend *fe)
 {
 	struct mc44s803_priv *priv = fe->tuner_priv;
 
 	fe->tuner_priv = NULL;
 	kfree(priv);
-
-	return 0;
 }
 
 static int mc44s803_init(struct dvb_frontend *fe)
@@ -349,8 +347,8 @@ struct dvb_frontend *mc44s803_attach(str
 	id = MC44S803_REG_MS(reg, MC44S803_ID);
 
 	if (id != 0x14) {
-		mc_printk(KERN_ERR, "unsupported ID "
-		       "(%x should be 0x14)\n", id);
+		mc_printk(KERN_ERR, "unsupported ID (%x should be 0x14)\n",
+			  id);
 		goto error;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mt2060.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2060.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mt2060.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2060.c	2017-02-12 16:03:20.000000000 -0500
@@ -332,11 +332,10 @@ static int mt2060_sleep(struct dvb_front
 	return ret;
 }
 
-static int mt2060_release(struct dvb_frontend *fe)
+static void mt2060_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops mt2060_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mt2063.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2063.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mt2063.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2063.c	2017-02-12 16:03:20.000000000 -0500
@@ -2019,7 +2019,7 @@ static int mt2063_get_status(struct dvb_
 	return 0;
 }
 
-static int mt2063_release(struct dvb_frontend *fe)
+static void mt2063_release(struct dvb_frontend *fe)
 {
 	struct mt2063_state *state = fe->tuner_priv;
 
@@ -2027,8 +2027,6 @@ static int mt2063_release(struct dvb_fro
 
 	fe->tuner_priv = NULL;
 	kfree(state);
-
-	return 0;
 }
 
 static int mt2063_set_analog_params(struct dvb_frontend *fe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mt20xx.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt20xx.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mt20xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt20xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,12 +49,10 @@ struct microtune_priv {
 	u32 frequency;
 };
 
-static int microtune_release(struct dvb_frontend *fe)
+static void microtune_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int microtune_get_frequency(struct dvb_frontend *fe, u32 *frequency)
@@ -487,13 +485,8 @@ static void mt2050_set_if_freq(struct dv
 	buf[5]=div2a;
 	if(num2!=0) buf[5]=buf[5]|0x40;
 
-	if (debug > 1) {
-		int i;
-		tuner_dbg("bufs is: ");
-		for(i=0;i<6;i++)
-			printk("%x ",buf[i]);
-		printk("\n");
-	}
+	if (debug > 1)
+		tuner_dbg("bufs is: %*ph\n", 6, buf);
 
 	ret=tuner_i2c_xfer_send(&priv->i2c_props,buf,6);
 	if (ret!=6)
@@ -619,15 +612,9 @@ struct dvb_frontend *microtune_attach(st
 
 	tuner_i2c_xfer_send(&priv->i2c_props,buf,1);
 	tuner_i2c_xfer_recv(&priv->i2c_props,buf,21);
-	if (debug) {
-		int i;
-		tuner_dbg("MT20xx hexdump:");
-		for(i=0;i<21;i++) {
-			printk(" %02x",buf[i]);
-			if(((i+1)%8)==0) printk(" ");
-		}
-		printk("\n");
-	}
+	if (debug)
+		tuner_dbg("MT20xx hexdump: %*ph\n", 21, buf);
+
 	company_code = buf[0x11] << 8 | buf[0x12];
 	tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
 		   company_code,buf[0x13],buf[0x14]);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mt2131.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2131.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mt2131.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2131.c	2017-02-12 16:03:20.000000000 -0500
@@ -230,12 +230,11 @@ static int mt2131_init(struct dvb_fronte
 	return ret;
 }
 
-static int mt2131_release(struct dvb_frontend *fe)
+static void mt2131_release(struct dvb_frontend *fe)
 {
 	dprintk(1, "%s()\n", __func__);
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops mt2131_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mt2266.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2266.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mt2266.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mt2266.c	2017-02-12 16:03:20.000000000 -0500
@@ -296,11 +296,10 @@ static int mt2266_sleep(struct dvb_front
 	return 0;
 }
 
-static int mt2266_release(struct dvb_frontend *fe)
+static void mt2266_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops mt2266_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mxl5005s.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mxl5005s.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mxl5005s.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mxl5005s.c	2017-02-12 16:03:20.000000000 -0500
@@ -4063,12 +4063,11 @@ static int mxl5005s_get_if_frequency(str
 	return 0;
 }
 
-static int mxl5005s_release(struct dvb_frontend *fe)
+static void mxl5005s_release(struct dvb_frontend *fe)
 {
 	dprintk(1, "%s()\n", __func__);
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops mxl5005s_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/mxl5007t.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/mxl5007t.c
--- linux-libre-4.9-gnu/drivers/media/tuners/mxl5007t.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/mxl5007t.c	2017-02-12 16:03:20.000000000 -0500
@@ -776,7 +776,7 @@ static int mxl5007t_get_if_frequency(str
 	return 0;
 }
 
-static int mxl5007t_release(struct dvb_frontend *fe)
+static void mxl5007t_release(struct dvb_frontend *fe)
 {
 	struct mxl5007t_state *state = fe->tuner_priv;
 
@@ -788,8 +788,6 @@ static int mxl5007t_release(struct dvb_f
 	mutex_unlock(&mxl5007t_list_mutex);
 
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 /* ------------------------------------------------------------------------- */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/qt1010.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/qt1010.c
--- linux-libre-4.9-gnu/drivers/media/tuners/qt1010.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/qt1010.c	2017-02-12 16:03:20.000000000 -0500
@@ -377,11 +377,10 @@ static int qt1010_init(struct dvb_fronte
 	return qt1010_set_params(fe);
 }
 
-static int qt1010_release(struct dvb_frontend *fe)
+static void qt1010_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int qt1010_get_frequency(struct dvb_frontend *fe, u32 *frequency)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/r820t.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/r820t.c
--- linux-libre-4.9-gnu/drivers/media/tuners/r820t.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/r820t.c	2017-02-12 16:03:20.000000000 -0500
@@ -2286,7 +2286,7 @@ static int r820t_get_if_frequency(struct
 	return 0;
 }
 
-static int r820t_release(struct dvb_frontend *fe)
+static void r820t_release(struct dvb_frontend *fe)
 {
 	struct r820t_priv *priv = fe->tuner_priv;
 
@@ -2300,8 +2300,6 @@ static int r820t_release(struct dvb_fron
 	mutex_unlock(&r820t_list_mutex);
 
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static const struct dvb_tuner_ops r820t_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tda18218.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18218.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tda18218.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18218.c	2017-02-12 16:03:20.000000000 -0500
@@ -265,11 +265,10 @@ static int tda18218_init(struct dvb_fron
 	return ret;
 }
 
-static int tda18218_release(struct dvb_frontend *fe)
+static void tda18218_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static const struct dvb_tuner_ops tda18218_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tda18271-common.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18271-common.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tda18271-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18271-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -251,8 +251,8 @@ static int __tda18271_write_regs(struct
 	}
 
 	if (ret != 1)
-		tda_err("ERROR: idx = 0x%x, len = %d, "
-			"i2c_transfer returned: %d\n", idx, max, ret);
+		tda_err("ERROR: idx = 0x%x, len = %d, i2c_transfer returned: %d\n",
+			idx, max, ret);
 
 	return (ret == 1 ? 0 : ret);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tda18271-fe.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18271-fe.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tda18271-fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18271-fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,8 +26,7 @@
 
 int tda18271_debug;
 module_param_named(debug, tda18271_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level "
-		 "(info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
+MODULE_PARM_DESC(debug, "set debug level (info=1, map=2, reg=4, adv=8, cal=16 (or-able))");
 
 static int tda18271_cal_on_startup = -1;
 module_param_named(cal, tda18271_cal_on_startup, int, 0644);
@@ -1049,7 +1048,7 @@ fail:
 	return ret;
 }
 
-static int tda18271_release(struct dvb_frontend *fe)
+static void tda18271_release(struct dvb_frontend *fe)
 {
 	struct tda18271_priv *priv = fe->tuner_priv;
 
@@ -1061,8 +1060,6 @@ static int tda18271_release(struct dvb_f
 	mutex_unlock(&tda18271_list_mutex);
 
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int tda18271_get_frequency(struct dvb_frontend *fe, u32 *frequency)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tda18271-maps.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18271-maps.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tda18271-maps.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda18271-maps.c	2017-02-12 16:03:20.000000000 -0500
@@ -1024,11 +1024,7 @@ int tda18271_lookup_rf_band(struct dvb_f
 
 	while ((map[i].rfmax * 1000) < *freq) {
 		if (tda18271_debug & DBG_ADV)
-			tda_map("(%d) rfmax = %d < freq = %d, "
-				"rf1_def = %d, rf2_def = %d, rf3_def = %d, "
-				"rf1 = %d, rf2 = %d, rf3 = %d, "
-				"rf_a1 = %d, rf_a2 = %d, "
-				"rf_b1 = %d, rf_b2 = %d\n",
+			tda_map("(%d) rfmax = %d < freq = %d, rf1_def = %d, rf2_def = %d, rf3_def = %d, rf1 = %d, rf2 = %d, rf3 = %d, rf_a1 = %d, rf_a2 = %d, rf_b1 = %d, rf_b2 = %d\n",
 				i, map[i].rfmax * 1000, *freq,
 				map[i].rf1_def, map[i].rf2_def, map[i].rf3_def,
 				map[i].rf1, map[i].rf2, map[i].rf3,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tda827x.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda827x.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tda827x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda827x.c	2017-02-12 16:03:20.000000000 -0500
@@ -767,11 +767,10 @@ static void tda827xa_agcf(struct dvb_fro
 
 /* ------------------------------------------------------------------ */
 
-static int tda827x_release(struct dvb_frontend *fe)
+static void tda827x_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-	return 0;
 }
 
 static int tda827x_get_frequency(struct dvb_frontend *fe, u32 *frequency)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tda8290.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda8290.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tda8290.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda8290.c	2017-02-12 16:03:20.000000000 -0500
@@ -617,8 +617,8 @@ static int tda829x_find_tuner(struct dvb
 
 	if (tuner_addrs == 0) {
 		tuner_addrs = 0x60;
-		tuner_info("could not clearly identify tuner address, "
-			   "defaulting to %x\n", tuner_addrs);
+		tuner_info("could not clearly identify tuner address, defaulting to %x\n",
+			   tuner_addrs);
 	} else {
 		tuner_addrs = tuner_addrs & 0xff;
 		tuner_info("setting tuner address to %x\n", tuner_addrs);
@@ -721,7 +721,7 @@ static int tda8295_probe(struct tuner_i2
 	return -ENODEV;
 }
 
-static struct analog_demod_ops tda8290_ops = {
+static const struct analog_demod_ops tda8290_ops = {
 	.set_params     = tda8290_set_params,
 	.has_signal     = tda8290_has_signal,
 	.standby        = tda8290_standby,
@@ -729,7 +729,7 @@ static struct analog_demod_ops tda8290_o
 	.i2c_gate_ctrl  = tda8290_i2c_bridge,
 };
 
-static struct analog_demod_ops tda8295_ops = {
+static const struct analog_demod_ops tda8295_ops = {
 	.set_params     = tda8295_set_params,
 	.has_signal     = tda8295_has_signal,
 	.standby        = tda8295_standby,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tda9887.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda9887.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tda9887.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tda9887.c	2017-02-12 16:03:20.000000000 -0500
@@ -659,7 +659,7 @@ static void tda9887_release(struct dvb_f
 	fe->analog_demod_priv = NULL;
 }
 
-static struct analog_demod_ops tda9887_ops = {
+static const struct analog_demod_ops tda9887_ops = {
 	.info		= {
 		.name	= "tda9887",
 	},
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tea5761.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tea5761.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tea5761.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tea5761.c	2017-02-12 16:03:20.000000000 -0500
@@ -274,24 +274,20 @@ int tea5761_autodetection(struct i2c_ada
 	}
 
 	if ((buffer[13] != 0x2b) || (buffer[14] != 0x57) || (buffer[15] != 0x061)) {
-		printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x."
-				    " It is not a TEA5761\n",
+		printk(KERN_WARNING "Manufacturer ID= 0x%02x, Chip ID = %02x%02x. It is not a TEA5761\n",
 				    buffer[13], buffer[14], buffer[15]);
 		return -EINVAL;
 	}
-	printk(KERN_WARNING "tea5761: TEA%02x%02x detected. "
-			    "Manufacturer ID= 0x%02x\n",
+	printk(KERN_WARNING "tea5761: TEA%02x%02x detected. Manufacturer ID= 0x%02x\n",
 			    buffer[14], buffer[15], buffer[13]);
 
 	return 0;
 }
 
-static int tea5761_release(struct dvb_frontend *fe)
+static void tea5761_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int tea5761_get_frequency(struct dvb_frontend *fe, u32 *frequency)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tea5767.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tea5767.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tea5767.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tea5767.c	2017-02-12 16:03:20.000000000 -0500
@@ -401,12 +401,10 @@ int tea5767_autodetection(struct i2c_ada
 	return 0;
 }
 
-static int tea5767_release(struct dvb_frontend *fe)
+static void tea5767_release(struct dvb_frontend *fe)
 {
 	kfree(fe->tuner_priv);
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int tea5767_get_frequency(struct dvb_frontend *fe, u32 *frequency)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tuner-simple.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tuner-simple.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tuner-simple.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tuner-simple.c	2017-02-12 16:03:20.000000000 -0500
@@ -275,8 +275,7 @@ static int simple_config_lookup(struct d
 	*config = t_params->ranges[i].config;
 	*cb     = t_params->ranges[i].cb;
 
-	tuner_dbg("freq = %d.%02d (%d), range = %d, "
-		  "config = 0x%02x, cb = 0x%02x\n",
+	tuner_dbg("freq = %d.%02d (%d), range = %d, config = 0x%02x, cb = 0x%02x\n",
 		  *frequency / 16, *frequency % 16 * 100 / 16, *frequency,
 		  i, *config, *cb);
 
@@ -404,12 +403,12 @@ static int simple_std_setup(struct dvb_f
 		i2c.addr = 0x0a;
 		rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2);
 		if (2 != rc)
-			tuner_warn("i2c i/o error: rc == %d "
-				   "(should be 2)\n", rc);
+			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",
+				   rc);
 		rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2);
 		if (2 != rc)
-			tuner_warn("i2c i/o error: rc == %d "
-				   "(should be 2)\n", rc);
+			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",
+				   rc);
 		break;
 	}
 	}
@@ -463,8 +462,8 @@ static int simple_post_tune(struct dvb_f
 			rc = tuner_i2c_xfer_recv(&priv->i2c_props,
 						 &status_byte, 1);
 			if (1 != rc) {
-				tuner_warn("i2c i/o read error: rc == %d "
-					   "(should be 1)\n", rc);
+				tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",
+					   rc);
 				break;
 			}
 			if (status_byte & TUNER_PLL_LOCKED)
@@ -483,8 +482,8 @@ static int simple_post_tune(struct dvb_f
 
 		rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4);
 		if (4 != rc)
-			tuner_warn("i2c i/o error: rc == %d "
-				   "(should be 4)\n", rc);
+			tuner_warn("i2c i/o error: rc == %d (should be 4)\n",
+				   rc);
 		break;
 	}
 	}
@@ -499,8 +498,7 @@ static int simple_radio_bandswitch(struc
 	switch (priv->type) {
 	case TUNER_TENA_9533_DI:
 	case TUNER_YMEC_TVF_5533MF:
-		tuner_dbg("This tuner doesn't have FM. "
-			  "Most cards have a TEA5767 for FM\n");
+		tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
 		return 0;
 	case TUNER_PHILIPS_FM1216ME_MK3:
 	case TUNER_PHILIPS_FM1236_MK3:
@@ -586,8 +584,7 @@ static int simple_set_tv_freq(struct dvb
 
 	div = params->frequency + IFPCoff + offset;
 
-	tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, "
-		  "Offset=%d.%02d MHz, div=%0d\n",
+	tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, Offset=%d.%02d MHz, div=%0d\n",
 		  params->frequency / 16, params->frequency % 16 * 100 / 16,
 		  IFPCoff / 16, IFPCoff % 16 * 100 / 16,
 		  offset / 16, offset % 16 * 100 / 16, div);
@@ -858,8 +855,7 @@ static u32 simple_dvb_configure(struct d
 	if (!tun->stepsize) {
 		/* tuner-core was loaded before the digital tuner was
 		 * configured and somehow picked the wrong tuner type */
-		tuner_err("attempt to treat tuner %d (%s) as digital tuner "
-			  "without stepsize defined.\n",
+		tuner_err("attempt to treat tuner %d (%s) as digital tuner without stepsize defined.\n",
 			  priv->type, priv->tun->name);
 		return 0; /* failure */
 	}
@@ -1005,7 +1001,7 @@ static int simple_sleep(struct dvb_front
 	return 0;
 }
 
-static int simple_release(struct dvb_frontend *fe)
+static void simple_release(struct dvb_frontend *fe)
 {
 	struct tuner_simple_priv *priv = fe->tuner_priv;
 
@@ -1017,8 +1013,6 @@ static int simple_release(struct dvb_fro
 	mutex_unlock(&tuner_simple_list_mutex);
 
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency)
@@ -1077,8 +1071,7 @@ struct dvb_frontend *simple_tuner_attach
 			fe->ops.i2c_gate_ctrl(fe, 1);
 
 		if (1 != i2c_transfer(i2c_adap, &msg, 1))
-			printk(KERN_WARNING "tuner-simple %d-%04x: "
-			       "unable to probe %s, proceeding anyway.",
+			printk(KERN_WARNING "tuner-simple %d-%04x: unable to probe %s, proceeding anyway.",
 			       i2c_adapter_id(i2c_adap), i2c_addr,
 			       tuners[type].name);
 
@@ -1123,18 +1116,16 @@ struct dvb_frontend *simple_tuner_attach
 	if ((debug) || ((atv_input[priv->nr] > 0) ||
 			(dtv_input[priv->nr] > 0))) {
 		if (0 == atv_input[priv->nr])
-			tuner_info("tuner %d atv rf input will be "
-				   "autoselected\n", priv->nr);
+			tuner_info("tuner %d atv rf input will be autoselected\n",
+				   priv->nr);
 		else
-			tuner_info("tuner %d atv rf input will be "
-				   "set to input %d (insmod option)\n",
+			tuner_info("tuner %d atv rf input will be set to input %d (insmod option)\n",
 				   priv->nr, atv_input[priv->nr]);
 		if (0 == dtv_input[priv->nr])
-			tuner_info("tuner %d dtv rf input will be "
-				   "autoselected\n", priv->nr);
+			tuner_info("tuner %d dtv rf input will be autoselected\n",
+				   priv->nr);
 		else
-			tuner_info("tuner %d dtv rf input will be "
-				   "set to input %d (insmod option)\n",
+			tuner_info("tuner %d dtv rf input will be set to input %d (insmod option)\n",
 				   priv->nr, dtv_input[priv->nr]);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/tuner-xc2028.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/tuner-xc2028.c
--- linux-libre-4.9-gnu/drivers/media/tuners/tuner-xc2028.c	2016-12-11 17:43:44.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/tuner-xc2028.c	2017-02-12 17:28:13.000000000 -0500
@@ -56,8 +56,7 @@ MODULE_PARM_DESC(no_poweroff, "0 (defaul
 static char audio_std[8];
 module_param_string(audio_std, audio_std, sizeof(audio_std), 0);
 MODULE_PARM_DESC(audio_std,
-	"Audio standard. XC3028 audio decoder explicitly "
-	"needs to know what audio\n"
+	"Audio standard. XC3028 audio decoder explicitly needs to know what audio\n"
 	"standard is needed for some video standards with audio A2 or NICAM.\n"
 	"The valid values are:\n"
 	"A2\n"
@@ -69,8 +68,8 @@ MODULE_PARM_DESC(audio_std,
 
 static char firmware_name[30];
 module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
-MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
-				"default firmware name\n");
+MODULE_PARM_DESC(firmware_name,
+		 "Firmware file name. Allows overriding the default firmware name\n");
 
 static LIST_HEAD(hybrid_tuner_instance_list);
 static DEFINE_MUTEX(xc2028_list_mutex);
@@ -179,67 +178,67 @@ static int xc2028_get_reg(struct xc2028_
 static void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq)
 {
 	if (type & BASE)
-		printk("BASE ");
+		printk(KERN_CONT "BASE ");
 	if (type & INIT1)
-		printk("INIT1 ");
+		printk(KERN_CONT "INIT1 ");
 	if (type & F8MHZ)
-		printk("F8MHZ ");
+		printk(KERN_CONT "F8MHZ ");
 	if (type & MTS)
-		printk("MTS ");
+		printk(KERN_CONT "MTS ");
 	if (type & D2620)
-		printk("D2620 ");
+		printk(KERN_CONT "D2620 ");
 	if (type & D2633)
-		printk("D2633 ");
+		printk(KERN_CONT "D2633 ");
 	if (type & DTV6)
-		printk("DTV6 ");
+		printk(KERN_CONT "DTV6 ");
 	if (type & QAM)
-		printk("QAM ");
+		printk(KERN_CONT "QAM ");
 	if (type & DTV7)
-		printk("DTV7 ");
+		printk(KERN_CONT "DTV7 ");
 	if (type & DTV78)
-		printk("DTV78 ");
+		printk(KERN_CONT "DTV78 ");
 	if (type & DTV8)
-		printk("DTV8 ");
+		printk(KERN_CONT "DTV8 ");
 	if (type & FM)
-		printk("FM ");
+		printk(KERN_CONT "FM ");
 	if (type & INPUT1)
-		printk("INPUT1 ");
+		printk(KERN_CONT "INPUT1 ");
 	if (type & LCD)
-		printk("LCD ");
+		printk(KERN_CONT "LCD ");
 	if (type & NOGD)
-		printk("NOGD ");
+		printk(KERN_CONT "NOGD ");
 	if (type & MONO)
-		printk("MONO ");
+		printk(KERN_CONT "MONO ");
 	if (type & ATSC)
-		printk("ATSC ");
+		printk(KERN_CONT "ATSC ");
 	if (type & IF)
-		printk("IF ");
+		printk(KERN_CONT "IF ");
 	if (type & LG60)
-		printk("LG60 ");
+		printk(KERN_CONT "LG60 ");
 	if (type & ATI638)
-		printk("ATI638 ");
+		printk(KERN_CONT "ATI638 ");
 	if (type & OREN538)
-		printk("OREN538 ");
+		printk(KERN_CONT "OREN538 ");
 	if (type & OREN36)
-		printk("OREN36 ");
+		printk(KERN_CONT "OREN36 ");
 	if (type & TOYOTA388)
-		printk("TOYOTA388 ");
+		printk(KERN_CONT "TOYOTA388 ");
 	if (type & TOYOTA794)
-		printk("TOYOTA794 ");
+		printk(KERN_CONT "TOYOTA794 ");
 	if (type & DIBCOM52)
-		printk("DIBCOM52 ");
+		printk(KERN_CONT "DIBCOM52 ");
 	if (type & ZARLINK456)
-		printk("ZARLINK456 ");
+		printk(KERN_CONT "ZARLINK456 ");
 	if (type & CHINA)
-		printk("CHINA ");
+		printk(KERN_CONT "CHINA ");
 	if (type & F6MHZ)
-		printk("F6MHZ ");
+		printk(KERN_CONT "F6MHZ ");
 	if (type & INPUT2)
-		printk("INPUT2 ");
+		printk(KERN_CONT "INPUT2 ");
 	if (type & SCODE)
-		printk("SCODE ");
+		printk(KERN_CONT "SCODE ");
 	if (type & HAS_IF)
-		printk("HAS_IF_%d ", int_freq);
+		printk(KERN_CONT "HAS_IF_%d ", int_freq);
 }
 
 static  v4l2_std_id parse_audio_std_option(void)
@@ -351,8 +350,7 @@ static int load_all_firmwares(struct dvb
 
 		n++;
 		if (n >= n_array) {
-			tuner_err("More firmware images in file than "
-				  "were expected!\n");
+			tuner_err("More firmware images in file than were expected!\n");
 			goto corrupt;
 		}
 
@@ -379,8 +377,8 @@ static int load_all_firmwares(struct dvb
 		if (!size || size > endp - p) {
 			tuner_err("Firmware type ");
 			dump_firm_type(type);
-			printk("(%x), id %llx is corrupted "
-			       "(size=%d, expected %d)\n",
+			printk(KERN_CONT
+			       "(%x), id %llx is corrupted (size=%d, expected %d)\n",
 			       type, (unsigned long long)id,
 			       (unsigned)(endp - p), size);
 			goto corrupt;
@@ -395,7 +393,7 @@ static int load_all_firmwares(struct dvb
 		tuner_dbg("Reading firmware type ");
 		if (debug) {
 			dump_firm_type_and_int_freq(type, int_freq);
-			printk("(%x), id %llx, size=%d.\n",
+			printk(KERN_CONT "(%x), id %llx, size=%d.\n",
 			       type, (unsigned long long)id, size);
 		}
 
@@ -444,7 +442,8 @@ static int seek_firmware(struct dvb_fron
 	tuner_dbg("%s called, want type=", __func__);
 	if (debug) {
 		dump_firm_type(type);
-		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+		printk(KERN_CONT "(%x), id %016llx.\n",
+		       type, (unsigned long long)*id);
 	}
 
 	if (!priv->firm) {
@@ -500,10 +499,11 @@ static int seek_firmware(struct dvb_fron
 	}
 
 	if (best_nr_matches > 0) {
-		tuner_dbg("Selecting best matching firmware (%d bits) for "
-			  "type=", best_nr_matches);
+		tuner_dbg("Selecting best matching firmware (%d bits) for type=",
+			  best_nr_matches);
 		dump_firm_type(type);
-		printk("(%x), id %016llx:\n", type, (unsigned long long)*id);
+		printk(KERN_CONT
+		       "(%x), id %016llx:\n", type, (unsigned long long)*id);
 		i = best_i;
 		goto found;
 	}
@@ -520,7 +520,8 @@ ret:
 	tuner_dbg("%s firmware for type=", (i < 0) ? "Can't find" : "Found");
 	if (debug) {
 		dump_firm_type(type);
-		printk("(%x), id %016llx.\n", type, (unsigned long long)*id);
+		printk(KERN_CONT "(%x), id %016llx.\n",
+		       type, (unsigned long long)*id);
 	}
 	return i;
 }
@@ -560,8 +561,8 @@ static int load_firmware(struct dvb_fron
 
 	tuner_info("Loading firmware for type=");
 	dump_firm_type(priv->firm[pos].type);
-	printk("(%x), id %016llx.\n", priv->firm[pos].type,
-	       (unsigned long long)*id);
+	printk(KERN_CONT "(%x), id %016llx.\n",
+	       priv->firm[pos].type, (unsigned long long)*id);
 
 	p = priv->firm[pos].ptr;
 	endp = p + priv->firm[pos].size;
@@ -694,7 +695,7 @@ static int load_scode(struct dvb_fronten
 	tuner_info("Loading SCODE for type=");
 	dump_firm_type_and_int_freq(priv->firm[pos].type,
 				    priv->firm[pos].int_freq);
-	printk("(%x), id %016llx.\n", priv->firm[pos].type,
+	printk(KERN_CONT "(%x), id %016llx.\n", priv->firm[pos].type,
 	       (unsigned long long)*id);
 
 	if (priv->firm_version < 0x0202)
@@ -746,15 +747,15 @@ retry:
 	tuner_dbg("checking firmware, user requested type=");
 	if (debug) {
 		dump_firm_type(new_fw.type);
-		printk("(%x), id %016llx, ", new_fw.type,
+		printk(KERN_CONT "(%x), id %016llx, ", new_fw.type,
 		       (unsigned long long)new_fw.std_req);
 		if (!int_freq) {
-			printk("scode_tbl ");
+			printk(KERN_CONT "scode_tbl ");
 			dump_firm_type(priv->ctrl.scode_table);
-			printk("(%x), ", priv->ctrl.scode_table);
+			printk(KERN_CONT "(%x), ", priv->ctrl.scode_table);
 		} else
-			printk("int_freq %d, ", new_fw.int_freq);
-		printk("scode_nr %d\n", new_fw.scode_nr);
+			printk(KERN_CONT "int_freq %d, ", new_fw.int_freq);
+		printk(KERN_CONT "scode_nr %d\n", new_fw.scode_nr);
 	}
 
 	/*
@@ -842,8 +843,7 @@ check_device:
 		goto fail;
 	}
 
-	tuner_dbg("Device is Xceive %d version %d.%d, "
-		  "firmware version %d.%d\n",
+	tuner_dbg("Device is Xceive %d version %d.%d, firmware version %d.%d\n",
 		  hwmodel, (version & 0xf000) >> 12, (version & 0xf00) >> 8,
 		  (version & 0xf0) >> 4, version & 0xf);
 
@@ -857,8 +857,7 @@ check_device:
 			tuner_err("Incorrect readback of firmware version.\n");
 			goto fail;
 		} else {
-			tuner_err("Returned an incorrect version. However, "
-				  "read is not reliable enough. Ignoring it.\n");
+			tuner_err("Returned an incorrect version. However, read is not reliable enough. Ignoring it.\n");
 			hwmodel = 3028;
 		}
 	}
@@ -869,8 +868,7 @@ check_device:
 		priv->hwvers  = version & 0xff00;
 	} else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
 		   priv->hwvers != (version & 0xff00)) {
-		tuner_err("Read invalid device hardware information - tuner "
-			  "hung?\n");
+		tuner_err("Read invalid device hardware information - tuner hung?\n");
 		goto fail;
 	}
 
@@ -1327,7 +1325,7 @@ static int xc2028_sleep(struct dvb_front
 	return rc;
 }
 
-static int xc2028_dvb_release(struct dvb_frontend *fe)
+static void xc2028_dvb_release(struct dvb_frontend *fe)
 {
 	struct xc2028_data *priv = fe->tuner_priv;
 
@@ -1345,8 +1343,6 @@ static int xc2028_dvb_release(struct dvb
 	mutex_unlock(&xc2028_list_mutex);
 
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int xc2028_get_frequency(struct dvb_frontend *fe, u32 *frequency)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/xc4000.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/xc4000.c
--- linux-libre-4.9-gnu/drivers/media/tuners/xc4000.c	2016-12-11 17:43:50.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/xc4000.c	2017-02-12 17:28:21.000000000 -0500
@@ -43,14 +43,11 @@ MODULE_PARM_DESC(debug, "Debugging level
 
 static int no_poweroff;
 module_param(no_poweroff, int, 0644);
-MODULE_PARM_DESC(no_poweroff, "Power management (1: disabled, 2: enabled, "
-	"0 (default): use device-specific default mode).");
+MODULE_PARM_DESC(no_poweroff, "Power management (1: disabled, 2: enabled, 0 (default): use device-specific default mode).");
 
 static int audio_std;
 module_param(audio_std, int, 0644);
-MODULE_PARM_DESC(audio_std, "Audio standard. XC4000 audio decoder explicitly "
-	"needs to know what audio standard is needed for some video standards "
-	"with audio A2 or NICAM. The valid settings are a sum of:\n"
+MODULE_PARM_DESC(audio_std, "Audio standard. XC4000 audio decoder explicitly needs to know what audio standard is needed for some video standards with audio A2 or NICAM. The valid settings are a sum of:\n"
 	" 1: use NICAM/B or A2/B instead of NICAM/A or A2/A\n"
 	" 2: use A2 instead of NICAM or BTSC\n"
 	" 4: use SECAM/K3 instead of K1\n"
@@ -60,8 +57,7 @@ MODULE_PARM_DESC(audio_std, "Audio stand
 
 static char firmware_name[30];
 module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
-MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
-	"default firmware name.");
+MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the default firmware name.");
 
 static DEFINE_MUTEX(xc4000_list_mutex);
 static LIST_HEAD(hybrid_tuner_instance_list);
@@ -290,8 +286,7 @@ static int xc4000_tuner_reset(struct dvb
 			return -EREMOTEIO;
 		}
 	} else {
-		printk(KERN_ERR "xc4000: no tuner reset callback function, "
-				"fatal\n");
+		printk(KERN_ERR "xc4000: no tuner reset callback function, fatal\n");
 		return -EINVAL;
 	}
 	return 0;
@@ -679,8 +674,7 @@ static int seek_firmware(struct dvb_fron
 
 	if (best_nr_diffs > 0U) {
 		printk(KERN_WARNING
-		       "Selecting best matching firmware (%u bits differ) for "
-		       "type=(%x), id %016llx:\n",
+		       "Selecting best matching firmware (%u bits differ) for type=(%x), id %016llx:\n",
 		       best_nr_diffs, type, (unsigned long long)*id);
 		i = best_i;
 	}
@@ -800,8 +794,7 @@ static int xc4000_fwupload(struct dvb_fr
 
 		n++;
 		if (n >= n_array) {
-			printk(KERN_ERR "More firmware images in file than "
-			       "were expected!\n");
+			printk(KERN_ERR "More firmware images in file than were expected!\n");
 			goto corrupt;
 		}
 
@@ -1055,8 +1048,7 @@ check_device:
 		goto fail;
 	}
 
-	dprintk(1, "Device is Xceive %d version %d.%d, "
-		"firmware version %d.%d\n",
+	dprintk(1, "Device is Xceive %d version %d.%d, firmware version %d.%d\n",
 		hwmodel, hw_major, hw_minor, fw_major, fw_minor);
 
 	/* Check firmware version against what we downloaded. */
@@ -1076,8 +1068,7 @@ check_device:
 	} else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel ||
 		   priv->hwvers != ((hw_major << 8) | hw_minor)) {
 		printk(KERN_WARNING
-		       "Read invalid device hardware information - tuner "
-		       "hung?\n");
+		       "Read invalid device hardware information - tuner hung?\n");
 		goto fail;
 	}
 
@@ -1627,7 +1618,7 @@ static int xc4000_init(struct dvb_fronte
 	return 0;
 }
 
-static int xc4000_release(struct dvb_frontend *fe)
+static void xc4000_release(struct dvb_frontend *fe)
 {
 	struct xc4000_priv *priv = fe->tuner_priv;
 
@@ -1641,8 +1632,6 @@ static int xc4000_release(struct dvb_fro
 	mutex_unlock(&xc4000_list_mutex);
 
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static const struct dvb_tuner_ops xc4000_tuner_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/tuners/xc5000.c linux-libre-4.10-rc8-gnu/drivers/media/tuners/xc5000.c
--- linux-libre-4.9-gnu/drivers/media/tuners/xc5000.c	2016-12-11 17:43:53.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/tuners/xc5000.c	2017-02-12 17:28:29.000000000 -0500
@@ -1326,7 +1326,7 @@ static int xc5000_init(struct dvb_fronte
 	return 0;
 }
 
-static int xc5000_release(struct dvb_frontend *fe)
+static void xc5000_release(struct dvb_frontend *fe)
 {
 	struct xc5000_priv *priv = fe->tuner_priv;
 
@@ -1346,8 +1346,6 @@ static int xc5000_release(struct dvb_fro
 	mutex_unlock(&xc5000_list_mutex);
 
 	fe->tuner_priv = NULL;
-
-	return 0;
 }
 
 static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/au0828/au0828-video.c linux-libre-4.10-rc8-gnu/drivers/media/usb/au0828/au0828-video.c
--- linux-libre-4.9-gnu/drivers/media/usb/au0828/au0828-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/au0828/au0828-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -253,8 +253,7 @@ static int au0828_init_isoc(struct au082
 		dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
 			sb_size, GFP_KERNEL, &urb->transfer_dma);
 		if (!dev->isoc_ctl.transfer_buffer[i]) {
-			printk("unable to allocate %i bytes for transfer"
-					" buffer %i%s\n",
+			printk("unable to allocate %i bytes for transfer buffer %i%s\n",
 					sb_size, i,
 					in_interrupt() ? " while in int" : "");
 			au0828_uninit_isoc(dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/b2c2/flexcop-usb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/b2c2/flexcop-usb.c
--- linux-libre-4.9-gnu/drivers/media/usb/b2c2/flexcop-usb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/b2c2/flexcop-usb.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,8 +33,7 @@
 
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,"
-		"ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
 #undef DEBSTATUS
 
 #define deb_info(args...) dprintk(0x01, args)
@@ -433,8 +432,8 @@ static int flexcop_usb_transfer_init(str
 		frame_size, i, j, ret;
 	int buffer_offset = 0;
 
-	deb_ts("creating %d iso-urbs with %d frames "
-			"each of %d bytes size = %d.\n", B2C2_USB_NUM_ISO_URB,
+	deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n",
+	       B2C2_USB_NUM_ISO_URB,
 			B2C2_USB_FRAMES_PER_ISO, frame_size, bufsize);
 
 	fc_usb->iso_buffer = usb_alloc_coherent(fc_usb->udev,
@@ -459,8 +458,8 @@ static int flexcop_usb_transfer_init(str
 	for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
 		int frame_offset = 0;
 		struct urb *urb = fc_usb->iso_urb[i];
-		deb_ts("initializing and submitting urb no. %d "
-			"(buf_offset: %d).\n", i, buffer_offset);
+		deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",
+		       i, buffer_offset);
 
 		urb->dev = fc_usb->udev;
 		urb->context = fc_usb;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/cpia2/cpia2_usb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/cpia2/cpia2_usb.c
--- linux-libre-4.9-gnu/drivers/media/usb/cpia2/cpia2_usb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/cpia2/cpia2_usb.c	2017-02-12 16:03:20.000000000 -0500
@@ -759,9 +759,7 @@ int cpia2_usb_stream_start(struct camera
 		cam->params.camera_state.stream_mode = old_alt;
 		ret2 = set_alternate(cam, USBIF_CMDONLY);
 		if (ret2 < 0) {
-			ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already "
-			    "failed. Then tried to call "
-			    "set_alternate(USBIF_CMDONLY) = %d.\n",
+			ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already failed. Then tried to call set_alternate(USBIF_CMDONLY) = %d.\n",
 			    alternate, ret, ret2);
 		}
 	} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/cx231xx/cx231xx-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/cx231xx/cx231xx-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/cx231xx/cx231xx-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/cx231xx/cx231xx-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -241,8 +241,7 @@ static int __usb_control_msg(struct cx23
 	int rc, i;
 
 	if (reg_debug) {
-		printk(KERN_DEBUG "%s: (pipe 0x%08x): "
-				"%s:  %02x %02x %02x %02x %02x %02x %02x %02x ",
+		printk(KERN_DEBUG "%s: (pipe 0x%08x): %s:  %02x %02x %02x %02x %02x %02x %02x %02x ",
 				dev->name,
 				pipe,
 				(requesttype & USB_DIR_IN) ? "IN" : "OUT",
@@ -441,8 +440,7 @@ int cx231xx_write_ctrl_reg(struct cx231x
 	if (reg_debug) {
 		int byte;
 
-		cx231xx_isocdbg("(pipe 0x%08x): "
-			"OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
+		cx231xx_isocdbg("(pipe 0x%08x): OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
 			pipe,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			req, 0, val, reg & 0xff,
@@ -600,8 +598,8 @@ int cx231xx_set_alt_setting(struct cx231
 			return -1;
 	}
 
-	cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u,"
-			"Interface = %d\n", alt, max_pkt_size,
+	cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u,Interface = %d\n",
+			alt, max_pkt_size,
 			usb_interface_index);
 
 	if (usb_interface_index > 0) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c
--- linux-libre-4.9-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/cx231xx/cx231xx-dvb.c	2017-02-12 16:03:20.000000000 -0500
@@ -377,8 +377,8 @@ static int attach_xc5000(u8 addr, struct
 	cfg.i2c_addr = addr;
 
 	if (!dev->dvb->frontend) {
-		dev_err(dev->dev, "%s/2: dvb frontend not attached. "
-		       "Can't attach xc5000\n", dev->name);
+		dev_err(dev->dev, "%s/2: dvb frontend not attached. Can't attach xc5000\n",
+			dev->name);
 		return -EINVAL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/af9005.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/af9005.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/af9005.c	2016-12-11 17:44:01.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/af9005.c	2017-02-12 17:28:48.000000000 -0500
@@ -826,7 +826,6 @@ static int af9005_frontend_attach(struct
 		printk("EEPROM DUMP\n");
 		for (i = 0; i < 255; i += 8) {
 			af9005_read_eeprom(adap->dev, i, buf, 8);
-			printk("ADDR %x ", i);
 			debug_dump(buf, 8, printk);
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/af9005-fe.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/af9005-fe.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/af9005-fe.c	2016-12-11 17:43:58.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/af9005-fe.c	2017-02-12 17:28:42.000000000 -0500
@@ -1409,7 +1409,7 @@ static void af9005_fe_release(struct dvb
 	kfree(state);
 }
 
-static struct dvb_frontend_ops af9005_fe_ops;
+static const struct dvb_frontend_ops af9005_fe_ops;
 
 struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d)
 {
@@ -1434,7 +1434,7 @@ struct dvb_frontend *af9005_fe_attach(st
 	return NULL;
 }
 
-static struct dvb_frontend_ops af9005_fe_ops = {
+static const struct dvb_frontend_ops af9005_fe_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		 .name = "AF9005 USB DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cinergyT2-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cinergyT2-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cinergyT2-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cinergyT2-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,8 +34,7 @@
 int dvb_usb_cinergyt2_debug;
 
 module_param_named(debug, dvb_usb_cinergyt2_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 "
-		"(or-able)).");
+MODULE_PARM_DESC(debug, "set debugging level (1=info, xfer=2, rc=4 (or-able)).");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -93,8 +92,7 @@ static int cinergyt2_frontend_attach(str
 
 	ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
 	if (ret < 0) {
-		deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "
-			"state info\n");
+		deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep state info\n");
 	}
 	mutex_unlock(&d->data_mutex);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cinergyT2-fe.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cinergyT2-fe.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cinergyT2-fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cinergyT2-fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -278,7 +278,7 @@ static void cinergyt2_fe_release(struct
 	kfree(state);
 }
 
-static struct dvb_frontend_ops cinergyt2_fe_ops;
+static const struct dvb_frontend_ops cinergyt2_fe_ops;
 
 struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)
 {
@@ -295,7 +295,7 @@ struct dvb_frontend *cinergyt2_fe_attach
 }
 
 
-static struct dvb_frontend_ops cinergyt2_fe_ops = {
+static const struct dvb_frontend_ops cinergyt2_fe_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= DRIVER_NAME,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cxusb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cxusb.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cxusb.c	2016-12-11 17:44:21.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cxusb.c	2017-02-12 17:29:16.000000000 -0500
@@ -369,6 +369,26 @@ static int cxusb_aver_streaming_ctrl(str
 	return 0;
 }
 
+static int cxusb_read_status(struct dvb_frontend *fe,
+				  enum fe_status *status)
+{
+	struct dvb_usb_adapter *adap = (struct dvb_usb_adapter *)fe->dvb->priv;
+	struct cxusb_state *state = (struct cxusb_state *)adap->dev->priv;
+	int ret;
+
+	ret = state->fe_read_status(fe, status);
+
+	/* it need resync slave fifo when signal change from unlock to lock.*/
+	if ((*status & FE_HAS_LOCK) && (!state->last_lock)) {
+		mutex_lock(&state->stream_mutex);
+		cxusb_streaming_ctrl(adap, 1);
+		mutex_unlock(&state->stream_mutex);
+	}
+
+	state->last_lock = (*status & FE_HAS_LOCK) ? 1 : 0;
+	return ret;
+}
+
 static void cxusb_d680_dmb_drain_message(struct dvb_usb_device *d)
 {
 	int       ep = d->props.generic_bulk_ctrl_endpoint;
@@ -1372,6 +1392,12 @@ static int cxusb_mygica_t230_frontend_at
 
 	st->i2c_client_tuner = client_tuner;
 
+	/* hook fe: need to resync the slave fifo when signal locks. */
+	mutex_init(&st->stream_mutex);
+	st->last_lock = 0;
+	st->fe_read_status = adap->fe_adap[0].fe->ops.read_status;
+	adap->fe_adap[0].fe->ops.read_status = cxusb_read_status;
+
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cxusb.h linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cxusb.h
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/cxusb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/cxusb.h	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,11 @@ struct cxusb_state {
 	struct i2c_client *i2c_client_tuner;
 
 	unsigned char data[MAX_XFER_SIZE];
+
+	struct mutex stream_mutex;
+	u8 last_lock;
+	int (*fe_read_status)(struct dvb_frontend *fe,
+		enum fe_status *status);
 };
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dib0700_core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dib0700_core.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dib0700_core.c	2016-12-11 17:44:29.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dib0700_core.c	2017-02-12 17:29:28.000000000 -0500
@@ -16,10 +16,7 @@ MODULE_PARM_DESC(debug, "set debugging l
 static int nb_packet_buffer_size = 21;
 module_param(nb_packet_buffer_size, int, 0644);
 MODULE_PARM_DESC(nb_packet_buffer_size,
-	"Set the dib0700 driver data buffer size. This parameter "
-	"corresponds to the number of TS packets. The actual size of "
-	"the data buffer corresponds to this parameter "
-	"multiplied by 188 (default: 21)");
+	"Set the dib0700 driver data buffer size. This parameter corresponds to the number of TS packets. The actual size of the data buffer corresponds to this parameter multiplied by 188 (default: 21)");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c	2016-12-11 17:44:26.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dib0700_devices.c	2017-02-12 17:29:21.000000000 -0500
@@ -26,8 +26,7 @@
 
 static int force_lna_activation;
 module_param(force_lna_activation, int, 0644);
-MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
-		"if applicable for the device (default: 0=automatic/off).");
+MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), if applicable for the device (default: 0=automatic/off).");
 
 struct dib0700_adapter_state {
 	int (*set_param_save) (struct dvb_frontend *);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dibusb-common.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dibusb-common.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dibusb-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dibusb-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -382,9 +382,9 @@ int dibusb_rc_query(struct dvb_usb_devic
 	if (buf[0] != 0)
 		deb_info("key: %*ph\n", 5, buf);
 
+ret:
 	kfree(buf);
 
-ret:
 	return ret;
 }
 EXPORT_SYMBOL(dibusb_rc_query);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dibusb-mc-common.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dibusb-mc-common.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dibusb-mc-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dibusb-mc-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,7 +9,6 @@
  * see Documentation/dvb/README.dvb-usb for more information
  */
 
-#include <linux/kconfig.h>
 #include "dibusb.h"
 
 /* 3000MC/P stuff */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dtt200u-fe.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dtt200u-fe.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dtt200u-fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dtt200u-fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -202,7 +202,7 @@ static void dtt200u_fe_release(struct dv
 	kfree(state);
 }
 
-static struct dvb_frontend_ops dtt200u_fe_ops;
+static const struct dvb_frontend_ops dtt200u_fe_ops;
 
 struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
 {
@@ -226,7 +226,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops dtt200u_fe_ops = {
+static const struct dvb_frontend_ops dtt200u_fe_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "WideView USB DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dvb-usb-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dvb-usb-dvb.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dvb-usb-dvb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dvb-usb-dvb.c	2017-02-12 16:03:20.000000000 -0500
@@ -277,8 +277,7 @@ int dvb_usb_adapter_frontend_init(struct
 	for (i = 0; i < adap->props.num_frontends; i++) {
 
 		if (adap->props.fe[i].frontend_attach == NULL) {
-			err("strange: '%s' #%d,%d "
-			    "doesn't want to attach a frontend.",
+			err("strange: '%s' #%d,%d doesn't want to attach a frontend.",
 			    adap->dev->desc->name, adap->id, i);
 
 			return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dvb-usb-firmware.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dvb-usb-firmware.c	2016-12-11 17:43:53.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dvb-usb-firmware.c	2017-02-12 17:28:30.000000000 -0500
@@ -49,8 +49,7 @@ int usb_cypress_load_firmware(struct usb
 		ret = usb_cypress_writemem(udev,hx.addr,hx.data,hx.len);
 
 		if (ret != hx.len) {
-			err("error while transferring firmware "
-				"(transferred size: %d, block size: %d)",
+			err("error while transferring firmware (transferred size: %d, block size: %d)",
 				ret,hx.len);
 			ret = -EINVAL;
 			break;
@@ -81,8 +80,7 @@ int dvb_usb_download_firmware(struct usb
 	const struct firmware *fw = NULL;
 
 	if ((ret = reject_firmware(&fw, props->firmware, &udev->dev)) != 0) {
-		err("did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+		err("did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
 			props->firmware,ret);
 		return ret;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dvb-usb.h linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dvb-usb.h
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dvb-usb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dvb-usb.h	2017-02-12 16:03:20.000000000 -0500
@@ -467,8 +467,10 @@ extern int dvb_usb_device_init(struct us
 extern void dvb_usb_device_exit(struct usb_interface *);
 
 /* the generic read/write method for device control */
-extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int);
-extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
+extern int __must_check
+dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16, int);
+extern int __must_check
+dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
 
 /* commonly used remote control parsing */
 extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dw2102.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dw2102.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/dw2102.c	2016-12-11 17:44:42.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/dw2102.c	2017-02-12 17:29:50.000000000 -0500
@@ -86,8 +86,7 @@ MODULE_PARM_DESC(debug, "set debugging l
 /* demod probe */
 static int demod_probe = 1;
 module_param_named(demod, demod_probe, int, 0644);
-MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 "
-			"4=stv0903+stb6100(or-able)).");
+MODULE_PARM_DESC(demod, "demod to probe (1=cx24116 2=stv0903+stv6110 4=stv0903+stb6100(or-able)).");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -1642,6 +1641,7 @@ enum dw2102_table_entry {
 	TEVII_S632,
 	TERRATEC_CINERGY_S2_R2,
 	TERRATEC_CINERGY_S2_R3,
+	TERRATEC_CINERGY_S2_R4,
 	GOTVIEW_SAT_HD,
 	GENIATECH_T220,
 	TECHNOTREND_S2_4600,
@@ -1671,6 +1671,7 @@ static struct usb_device_id dw2102_table
 	[TEVII_S632] = {USB_DEVICE(0x9022, USB_PID_TEVII_S632)},
 	[TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R2)},
 	[TERRATEC_CINERGY_S2_R3] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R3)},
+	[TERRATEC_CINERGY_S2_R4] = {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_S2_R4)},
 	[GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)},
 	[GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)},
 	[TECHNOTREND_S2_4600] = {USB_DEVICE(USB_VID_TECHNOTREND,
@@ -2343,12 +2344,7 @@ static struct usb_driver dw2102_driver =
 module_usb_driver(dw2102_driver);
 
 MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
-MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
-			" DVB-C 3101 USB2.0,"
-			" TeVii S421, S480, S482, S600, S630, S632, S650,"
-			" TeVii S660, S662, Prof 1100, 7500 USB2.0,"
-			" Geniatech SU3000, T220,"
-			" TechnoTrend S2-4600, Terratec Cinergy S2 devices");
+MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101 USB2.0, TeVii S421, S480, S482, S600, S630, S632, S650, TeVii S660, S662, Prof 1100, 7500 USB2.0, Geniatech SU3000, T220, TechnoTrend S2-4600, Terratec Cinergy S2 devices");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
 /*(DEBLOBBED)*/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/friio.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/friio.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/friio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/friio.c	2017-02-12 16:03:20.000000000 -0500
@@ -320,8 +320,8 @@ restart:
  */
 	if (rbuf[0] & 0x80) {	/* still in PowerOnReset state? */
 		if (++retry > 3) {
-			deb_info("failed to get the correct"
-				 " FE demod status:0x%02x\n", rbuf[0]);
+			deb_info("failed to get the correct FE demod status:0x%02x\n",
+				 rbuf[0]);
 			goto error;
 		}
 		msleep(100);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/friio-fe.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/friio-fe.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/friio-fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/friio-fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -401,7 +401,7 @@ static void jdvbt90502_release(struct dv
 }
 
 
-static struct dvb_frontend_ops jdvbt90502_ops;
+static const struct dvb_frontend_ops jdvbt90502_ops;
 
 struct dvb_frontend *jdvbt90502_attach(struct dvb_usb_device *d)
 {
@@ -432,7 +432,7 @@ error:
 	return NULL;
 }
 
-static struct dvb_frontend_ops jdvbt90502_ops = {
+static const struct dvb_frontend_ops jdvbt90502_ops = {
 	.delsys = { SYS_ISDBT },
 	.info = {
 		.name			= "Comtech JDVBT90502 ISDB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/gp8psk.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/gp8psk.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/gp8psk.c	2016-12-11 17:44:49.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/gp8psk.c	2017-02-12 17:30:04.000000000 -0500
@@ -135,8 +135,7 @@ static int gp8psk_load_bcm4500fw(struct
 	u8 *buf;
 	if ((ret = reject_firmware(&fw, bcm4500_firmware,
 					&d->udev->dev)) != 0) {
-		err("did not find the bcm4500 firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+		err("did not find the bcm4500 firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
 			bcm4500_firmware,ret);
 		return ret;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/m920x.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/m920x.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/m920x.c	2016-12-11 17:44:55.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/m920x.c	2017-02-12 17:30:16.000000000 -0500
@@ -55,13 +55,9 @@ static inline int m920x_read(struct usb_
 static inline int m920x_write(struct usb_device *udev, u8 request,
 			      u16 value, u16 index)
 {
-	int ret;
-
-	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-			      request, USB_TYPE_VENDOR | USB_DIR_OUT,
-			      value, index, NULL, 0, 2000);
-
-	return ret;
+	return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request,
+			       USB_TYPE_VENDOR | USB_DIR_OUT, value, index,
+			       NULL, 0, 2000);
 }
 
 static inline int m920x_write_seq(struct usb_device *udev, u8 request,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/opera1.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/opera1.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/opera1.c	2016-12-11 17:45:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/opera1.c	2017-02-12 17:30:22.000000000 -0500
@@ -453,8 +453,7 @@ static int opera1_xilinx_load_firmware(s
 	info("start downloading fpga firmware %s",filename);
 
 	if ((ret = reject_firmware(&fw, filename, &dev->dev)) != 0) {
-		err("did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
+		err("did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems.",
 			filename);
 		return ret;
 	} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/pctv452e.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/pctv452e.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/pctv452e.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/pctv452e.c	2017-02-12 16:03:20.000000000 -0500
@@ -97,14 +97,13 @@ struct pctv452e_state {
 	u8 c;	   /* transaction counter, wraps around...  */
 	u8 initialized; /* set to 1 if 0x15 has been sent */
 	u16 last_rc_key;
-
-	unsigned char data[80];
 };
 
 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;
 	u8 id;
 	unsigned int rlen;
 	int ret;
@@ -114,36 +113,39 @@ static int tt3650_ci_msg(struct dvb_usb_
 		return -EIO;
 	}
 
-	mutex_lock(&state->ca_mutex);
+	buf = kmalloc(64, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	id = state->c++;
 
-	state->data[0] = SYNC_BYTE_OUT;
-	state->data[1] = id;
-	state->data[2] = cmd;
-	state->data[3] = write_len;
+	buf[0] = SYNC_BYTE_OUT;
+	buf[1] = id;
+	buf[2] = cmd;
+	buf[3] = write_len;
 
-	memcpy(state->data + 4, data, write_len);
+	memcpy(buf + 4, data, write_len);
 
 	rlen = (read_len > 0) ? 64 : 0;
-	ret = dvb_usb_generic_rw(d, state->data, 4 + write_len,
-				  state->data, rlen, /* delay_ms */ 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 != state->data[0] || id != state->data[1])
+	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
 		goto failed;
 
-	memcpy(data, state->data + 4, read_len);
+	memcpy(data, buf + 4, read_len);
 
-	mutex_unlock(&state->ca_mutex);
+	kfree(buf);
 	return 0;
 
 failed:
 	err("CI error %d; %02X %02X %02X -> %*ph.",
-	     ret, SYNC_BYTE_OUT, id, cmd, 3, state->data);
+	     ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
 
-	mutex_unlock(&state->ca_mutex);
+	kfree(buf);
 	return ret;
 }
 
@@ -410,53 +412,57 @@ static int pctv452e_i2c_msg(struct dvb_u
 				u8 *rcv_buf, u8 rcv_len)
 {
 	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 *buf;
 	u8 id;
 	int ret;
 
-	mutex_lock(&state->ca_mutex);
+	buf = kmalloc(64, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	id = state->c++;
 
 	ret = -EINVAL;
 	if (snd_len > 64 - 7 || rcv_len > 64 - 7)
 		goto failed;
 
-	state->data[0] = SYNC_BYTE_OUT;
-	state->data[1] = id;
-	state->data[2] = PCTV_CMD_I2C;
-	state->data[3] = snd_len + 3;
-	state->data[4] = addr << 1;
-	state->data[5] = snd_len;
-	state->data[6] = rcv_len;
+	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(state->data + 7, snd_buf, snd_len);
+	memcpy(buf + 7, snd_buf, snd_len);
 
-	ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len,
-				  state->data, /* rcv_len */ 64,
+	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 != state->data[0] || id != state->data[1])
+	if (SYNC_BYTE_IN != buf[0] || id != buf[1])
 		goto failed;
 
 	/* I2C device didn't respond as expected. */
 	ret = -EREMOTEIO;
-	if (state->data[5] < snd_len || state->data[6] < rcv_len)
+	if (buf[5] < snd_len || buf[6] < rcv_len)
 		goto failed;
 
-	memcpy(rcv_buf, state->data + 7, rcv_len);
-	mutex_unlock(&state->ca_mutex);
+	memcpy(rcv_buf, buf + 7, rcv_len);
 
+	kfree(buf);
 	return rcv_len;
 
 failed:
 	err("I2C error %d; %02X %02X  %02X %02X %02X -> %*ph",
 	     ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len,
-	     7, state->data);
+	     7, buf);
 
-	mutex_unlock(&state->ca_mutex);
+	kfree(buf);
 	return ret;
 }
 
@@ -505,7 +511,7 @@ static u32 pctv452e_i2c_func(struct i2c_
 static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)
 {
 	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
-	u8 *rx;
+	u8 *b0, *rx;
 	int ret;
 
 	info("%s: %d\n", __func__, i);
@@ -516,11 +522,12 @@ static int pctv452e_power_ctrl(struct dv
 	if (state->initialized)
 		return 0;
 
-	rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL);
-	if (!rx)
+	b0 = kmalloc(5 + PCTV_ANSWER_LEN, GFP_KERNEL);
+	if (!b0)
 		return -ENOMEM;
 
-	mutex_lock(&state->ca_mutex);
+	rx = b0 + 5;
+
 	/* hmm where shoud this should go? */
 	ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);
 	if (ret != 0)
@@ -528,66 +535,70 @@ static int pctv452e_power_ctrl(struct dv
 			__func__, ret);
 
 	/* this is a one-time initialization, dont know where to put */
-	state->data[0] = 0xaa;
-	state->data[1] = state->c++;
-	state->data[2] = PCTV_CMD_RESET;
-	state->data[3] = 1;
-	state->data[4] = 0;
+	b0[0] = 0xaa;
+	b0[1] = state->c++;
+	b0[2] = PCTV_CMD_RESET;
+	b0[3] = 1;
+	b0[4] = 0;
 	/* reset board */
-	ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
+	ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
 	if (ret)
 		goto ret;
 
-	state->data[1] = state->c++;
-	state->data[4] = 1;
+	b0[1] = state->c++;
+	b0[4] = 1;
 	/* reset board (again?) */
-	ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);
+	ret = dvb_usb_generic_rw(d, b0, 5, rx, PCTV_ANSWER_LEN, 0);
 	if (ret)
 		goto ret;
 
 	state->initialized = 1;
 
 ret:
-	mutex_unlock(&state->ca_mutex);
-	kfree(rx);
+	kfree(b0);
 	return ret;
 }
 
 static int pctv452e_rc_query(struct dvb_usb_device *d)
 {
 	struct pctv452e_state *state = (struct pctv452e_state *)d->priv;
+	u8 *b, *rx;
 	int ret, i;
 	u8 id;
 
-	mutex_lock(&state->ca_mutex);
+	b = kmalloc(CMD_BUFFER_SIZE + PCTV_ANSWER_LEN, GFP_KERNEL);
+	if (!b)
+		return -ENOMEM;
+
+	rx = b + CMD_BUFFER_SIZE;
+
 	id = state->c++;
 
 	/* prepare command header  */
-	state->data[0] = SYNC_BYTE_OUT;
-	state->data[1] = id;
-	state->data[2] = PCTV_CMD_IR;
-	state->data[3] = 0;
+	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, state->data, 4,
-				 state->data, PCTV_ANSWER_LEN, 0);
+	ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0);
 	if (ret != 0)
 		goto ret;
 
 	if (debug > 3) {
-		info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data);
-		for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++)
-			info(" %02x", state->data[i + 3]);
+		info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
+		for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
+			info(" %02x", rx[i+3]);
 
 		info("\n");
 	}
 
-	if ((state->data[3] == 9) &&  (state->data[12] & 0x01)) {
+	if ((rx[3] == 9) &&  (rx[12] & 0x01)) {
 		/* got a "press" event */
-		state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]);
+		state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]);
 		if (debug > 2)
 			info("%s: cmd=0x%02x sys=0x%02x\n",
-				__func__, state->data[6], state->data[7]);
+				__func__, rx[6], rx[7]);
 
 		rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);
 	} else if (state->last_rc_key) {
@@ -595,7 +606,7 @@ static int pctv452e_rc_query(struct dvb_
 		state->last_rc_key = 0;
 	}
 ret:
-	mutex_unlock(&state->ca_mutex);
+	kfree(b);
 	return ret;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c	2016-12-11 17:45:02.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/technisat-usb2.c	2017-02-12 17:30:25.000000000 -0500
@@ -50,8 +50,7 @@ MODULE_PARM_DESC(debug,
 static int disable_led_control;
 module_param(disable_led_control, int, 0444);
 MODULE_PARM_DESC(disable_led_control,
-		"disable LED control of the device "
-		"(default: 0 - LED control is active).");
+		"disable LED control of the device (default: 0 - LED control is active).");
 
 /* device private data */
 struct technisat_usb2_state {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/vp702x-fe.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/vp702x-fe.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/vp702x-fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/vp702x-fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -323,7 +323,7 @@ static void vp702x_fe_release(struct dvb
 	kfree(st);
 }
 
-static struct dvb_frontend_ops vp702x_fe_ops;
+static const struct dvb_frontend_ops vp702x_fe_ops;
 
 struct dvb_frontend * vp702x_fe_attach(struct dvb_usb_device *d)
 {
@@ -345,7 +345,7 @@ error:
 }
 
 
-static struct dvb_frontend_ops vp702x_fe_ops = {
+static const struct dvb_frontend_ops vp702x_fe_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name           = "Twinhan DST-like frontend (VP7021/VP7020) DVB-S",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/vp7045-fe.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/vp7045-fe.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb/vp7045-fe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb/vp7045-fe.c	2017-02-12 16:03:20.000000000 -0500
@@ -140,7 +140,7 @@ static void vp7045_fe_release(struct dvb
 	kfree(state);
 }
 
-static struct dvb_frontend_ops vp7045_fe_ops;
+static const struct dvb_frontend_ops vp7045_fe_ops;
 
 struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
 {
@@ -158,7 +158,7 @@ error:
 }
 
 
-static struct dvb_frontend_ops vp7045_fe_ops = {
+static const struct dvb_frontend_ops vp7045_fe_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "Twinhan VP7045/46 USB DVB-T",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/af9015.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/af9015.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/af9015.c	2016-12-11 17:44:07.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/af9015.c	2017-02-12 17:28:56.000000000 -0500
@@ -1455,7 +1455,7 @@ static const struct usb_device_id af9015
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU,
 		&af9015_props, "Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810,
-		&af9015_props, "KWorld Digial MC-810", NULL) },
+		&af9015_props, "KWorld Digital MC-810", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03,
 		&af9015_props, "Genius TVGo DVB-T03", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/af9035.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/af9035.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/af9035.c	2016-12-11 17:44:12.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/af9035.c	2017-02-12 17:29:05.000000000 -0500
@@ -2095,6 +2095,8 @@ static const struct usb_device_id af9035
 		&af9035_props, "TerraTec Cinergy T Stick (rev. 2)", NULL) },
 	{ DVB_USB_DEVICE(USB_VID_AVERMEDIA, 0x0337,
 		&af9035_props, "AVerMedia HD Volar (A867)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_EVOLVEO_XTRATV_STICK,
+	       &af9035_props, "EVOLVEO XtraTV stick", NULL) },
 
 	/* IT9135 devices */
 	{ DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/dvbsky.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/dvbsky.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/dvbsky.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/dvbsky.c	2017-02-12 16:03:20.000000000 -0500
@@ -851,6 +851,10 @@ static const struct usb_device_id dvbsky
 		USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI_2,
 		&dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI v1.1",
 		RC_MAP_TT_1500) },
+	{ DVB_USB_DEVICE(USB_VID_TECHNOTREND,
+		USB_PID_TECHNOTREND_CONNECT_S2_4650_CI,
+		&dvbsky_s960c_props, "TechnoTrend TT-connect S2-4650 CI",
+		RC_MAP_TT_1500) },
 	{ DVB_USB_DEVICE(USB_VID_TERRATEC,
 		USB_PID_TERRATEC_H7_3,
 		&dvbsky_t680c_props, "Terratec H7 Rev.4",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c	2016-12-11 17:44:52.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/lmedm04.c	2017-02-12 17:30:08.000000000 -0500
@@ -156,21 +156,19 @@ struct lme2510_state {
 static int lme2510_bulk_write(struct usb_device *dev,
 				u8 *snd, int len, u8 pipe)
 {
-	int ret, actual_l;
+	int actual_l;
 
-	ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
-				snd, len , &actual_l, 100);
-	return ret;
+	return usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
+			    snd, len, &actual_l, 100);
 }
 
 static int lme2510_bulk_read(struct usb_device *dev,
 				u8 *rev, int len, u8 pipe)
 {
-	int ret, actual_l;
+	int actual_l;
 
-	ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
-				 rev, len , &actual_l, 200);
-	return ret;
+	return usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
+			    rev, len, &actual_l, 200);
 }
 
 static int lme2510_usb_talk(struct dvb_usb_device *d,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,8 +29,7 @@
 
 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)).");
+MODULE_PARM_DESC(debug, "set debugging level (1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
 
 static int dvb_usb_mxl111sf_isoc;
 module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
@@ -137,8 +136,8 @@ int mxl111sf_write_reg_mask(struct mxl11
 #if 1
 		/* dont know why this usually errors out on the first try */
 		if (mxl_fail(ret))
-			pr_err("error writing addr: 0x%02x, mask: 0x%02x, "
-			    "data: 0x%02x, retrying...", addr, mask, data);
+			pr_err("error writing addr: 0x%02x, mask: 0x%02x, data: 0x%02x, retrying...",
+			       addr, mask, data);
 
 		ret = mxl111sf_read_reg(state, addr, &val);
 #endif
@@ -946,8 +945,7 @@ static int mxl111sf_init(struct dvb_usb_
 	case 138001:
 		break;
 	default:
-		printk(KERN_WARNING "%s: warning: "
-		       "unknown hauppauge model #%d\n",
+		printk(KERN_WARNING "%s: warning: unknown hauppauge model #%d\n",
 		       __func__, state->tv.model);
 	}
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c	2017-02-12 16:03:20.000000000 -0500
@@ -549,7 +549,7 @@ static void mxl111sf_demod_release(struc
 	fe->demodulator_priv = NULL;
 }
 
-static struct dvb_frontend_ops mxl111sf_demod_ops = {
+static const struct dvb_frontend_ops mxl111sf_demod_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name               = "MaxLinear MxL111SF DVB-T demodulator",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -666,8 +666,8 @@ static int mxl111sf_i2c_hw_xfer_msg(stru
 
 				if (rd_status[i] == 0x04) {
 					if (i < 7) {
-						mxl_i2c("i2c fifo empty!"
-							" @ %d", i);
+						mxl_i2c("i2c fifo empty! @ %d",
+							i);
 						msg->buf[(index*8)+i] =
 							i2c_r_data[(i*3)+1];
 						/* read again */
@@ -692,8 +692,7 @@ static int mxl111sf_i2c_hw_xfer_msg(stru
 							}
 							goto stop_copy;
 						} else {
-							mxl_i2c("readagain "
-								"ERROR!");
+							mxl_i2c("readagain ERROR!");
 						}
 					} else {
 						msg->buf[(index*8)+i] =
@@ -827,9 +826,8 @@ int mxl111sf_i2c_xfer(struct i2c_adapter
 			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,
+			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);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
--- linux-libre-4.9-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c	2017-02-12 16:03:20.000000000 -0500
@@ -455,13 +455,12 @@ static int mxl111sf_tuner_get_if_frequen
 	return 0;
 }
 
-static int mxl111sf_tuner_release(struct dvb_frontend *fe)
+static void 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;
 }
 
 /* ------------------------------------------------------------------------- */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-audio.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-audio.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-audio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-audio.c	2017-02-12 16:03:20.000000000 -0500
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
  *
- *  Copyright (C) 2007-2014 Mauro Carvalho Chehab
+ *  Copyright (C) 2007-2016 Mauro Carvalho Chehab
  *	- Port to work with the in-kernel driver
  *	- Cleanups, fixes, alsa-controls, etc.
  *
@@ -25,6 +25,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "em28xx.h"
+
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/init.h>
@@ -44,7 +46,6 @@
 #include <sound/tlv.h>
 #include <sound/ac97_codec.h>
 #include <media/v4l2-common.h>
-#include "em28xx.h"
 
 static int debug;
 module_param(debug, int, 0644);
@@ -54,10 +55,10 @@ MODULE_PARM_DESC(debug, "activates debug
 #define EM28XX_MIN_AUDIO_PACKETS	64
 
 #define dprintk(fmt, arg...) do {					\
-	    if (debug)							\
-		printk(KERN_INFO "em28xx-audio %s: " fmt,		\
-				  __func__, ##arg);		\
-	} while (0)
+	if (debug)						\
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "video: %s: " fmt, __func__, ## arg);	\
+} while (0)
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 
@@ -91,7 +92,8 @@ static void em28xx_audio_isocirq(struct
 	struct snd_pcm_runtime   *runtime;
 
 	if (dev->disconnected) {
-		dprintk("device disconnected while streaming. URB status=%d.\n", urb->status);
+		dprintk("device disconnected while streaming. URB status=%d.\n",
+			urb->status);
 		atomic_set(&dev->adev.stream_started, 0);
 		return;
 	}
@@ -164,8 +166,9 @@ static void em28xx_audio_isocirq(struct
 
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status < 0)
-		em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
-			      status);
+		dev_err(&dev->intf->dev,
+			"resubmit of audio urb failed (error=%i)\n",
+			status);
 	return;
 }
 
@@ -182,8 +185,9 @@ static int em28xx_init_audio_isoc(struct
 
 		errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
 		if (errCode) {
-			em28xx_errdev("submit of audio urb failed (error=%i)\n",
-				      errCode);
+			dev_err(&dev->intf->dev,
+				"submit of audio urb failed (error=%i)\n",
+				errCode);
 			em28xx_deinit_isoc_audio(dev);
 			atomic_set(&dev->adev.stream_started, 0);
 			return errCode;
@@ -197,6 +201,7 @@ static int em28xx_init_audio_isoc(struct
 static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
 					size_t size)
 {
+	struct em28xx *dev = snd_pcm_substream_chip(subs);
 	struct snd_pcm_runtime *runtime = subs->runtime;
 
 	dprintk("Allocating vbuffer\n");
@@ -254,8 +259,7 @@ static int snd_em28xx_capture_open(struc
 	int nonblock, ret = 0;
 
 	if (!dev) {
-		em28xx_err("BUG: em28xx can't find device struct."
-				" Can't proceed with open\n");
+		pr_err("em28xx-audio: BUG: em28xx can't find device struct. Can't proceed with open\n");
 		return -ENODEV;
 	}
 
@@ -275,6 +279,8 @@ static int snd_em28xx_capture_open(struc
 
 	if (dev->adev.users == 0) {
 		if (dev->alt == 0 || dev->is_audio_only) {
+			struct usb_device *udev = interface_to_usbdev(dev->intf);
+
 			if (dev->is_audio_only)
 				/* audio is on a separate interface */
 				dev->alt = 1;
@@ -292,7 +298,7 @@ static int snd_em28xx_capture_open(struc
 				 */
 			dprintk("changing alternate number on interface %d to %d\n",
 				dev->ifnum, dev->alt);
-			usb_set_interface(dev->udev, dev->ifnum, dev->alt);
+			usb_set_interface(udev, dev->ifnum, dev->alt);
 		}
 
 		/* Sets volume, mute, etc */
@@ -318,7 +324,8 @@ static int snd_em28xx_capture_open(struc
 err:
 	mutex_unlock(&dev->lock);
 
-	em28xx_err("Error while configuring em28xx mixer\n");
+	dev_err(&dev->intf->dev,
+		"Error while configuring em28xx mixer\n");
 	return ret;
 }
 
@@ -709,6 +716,7 @@ static const struct snd_pcm_ops snd_em28
 
 static void em28xx_audio_free_urb(struct em28xx *dev)
 {
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int i;
 
 	for (i = 0; i < dev->adev.num_urb; i++) {
@@ -717,7 +725,7 @@ static void em28xx_audio_free_urb(struct
 		if (!urb)
 			continue;
 
-		usb_free_coherent(dev->udev, urb->transfer_buffer_length,
+		usb_free_coherent(udev, urb->transfer_buffer_length,
 				  dev->adev.transfer_buffer[i],
 				  urb->transfer_dma);
 
@@ -744,6 +752,7 @@ static int em28xx_audio_urb_init(struct
 {
 	struct usb_interface *intf;
 	struct usb_endpoint_descriptor *e, *ep = NULL;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int                 i, ep_size, interval, num_urb, npackets;
 	int		    urb_size, bytes_per_transfer;
 	u8 alt;
@@ -753,10 +762,10 @@ static int em28xx_audio_urb_init(struct
 	else
 		alt = 7;
 
-	intf = usb_ifnum_to_if(dev->udev, dev->ifnum);
+	intf = usb_ifnum_to_if(udev, dev->ifnum);
 
 	if (intf->num_altsetting <= alt) {
-		em28xx_errdev("alt %d doesn't exist on interface %d\n",
+		dev_err(&dev->intf->dev, "alt %d doesn't exist on interface %d\n",
 			      dev->ifnum, alt);
 		return -ENODEV;
 	}
@@ -772,18 +781,17 @@ static int em28xx_audio_urb_init(struct
 	}
 
 	if (!ep) {
-		em28xx_errdev("Couldn't find an audio endpoint");
+		dev_err(&dev->intf->dev, "Couldn't find an audio endpoint");
 		return -ENODEV;
 	}
 
-	ep_size = em28xx_audio_ep_packet_size(dev->udev, ep);
+	ep_size = em28xx_audio_ep_packet_size(udev, ep);
 	interval = 1 << (ep->bInterval - 1);
 
-	em28xx_info("Endpoint 0x%02x %s on intf %d alt %d interval = %d, size %d\n",
-		    EM28XX_EP_AUDIO, usb_speed_string(dev->udev->speed),
-		     dev->ifnum, alt,
-		     interval,
-		     ep_size);
+	dev_info(&dev->intf->dev,
+		 "Endpoint 0x%02x %s on intf %d alt %d interval = %d, size %d\n",
+		 EM28XX_EP_AUDIO, usb_speed_string(udev->speed),
+		 dev->ifnum, alt, interval, ep_size);
 
 	/* Calculate the number and size of URBs to better fit the audio samples */
 
@@ -820,8 +828,9 @@ static int em28xx_audio_urb_init(struct
 	if (urb_size > ep_size * npackets)
 		npackets = DIV_ROUND_UP(urb_size, ep_size);
 
-	em28xx_info("Number of URBs: %d, with %d packets and %d size\n",
-		    num_urb, npackets, urb_size);
+	dev_info(&dev->intf->dev,
+		 "Number of URBs: %d, with %d packets and %d size\n",
+		 num_urb, npackets, urb_size);
 
 	/* Estimate the bytes per period */
 	dev->adev.period = urb_size * npackets;
@@ -855,18 +864,19 @@ static int em28xx_audio_urb_init(struct
 		}
 		dev->adev.urb[i] = urb;
 
-		buf = usb_alloc_coherent(dev->udev, npackets * ep_size, GFP_ATOMIC,
+		buf = usb_alloc_coherent(udev, npackets * ep_size, GFP_ATOMIC,
 					 &urb->transfer_dma);
 		if (!buf) {
-			em28xx_errdev("usb_alloc_coherent failed!\n");
+			dev_err(&dev->intf->dev,
+				"usb_alloc_coherent failed!\n");
 			em28xx_audio_free_urb(dev);
 			return -ENOMEM;
 		}
 		dev->adev.transfer_buffer[i] = buf;
 
-		urb->dev = dev->udev;
+		urb->dev = udev;
 		urb->context = dev;
-		urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO);
+		urb->pipe = usb_rcvisocpipe(udev, EM28XX_EP_AUDIO);
 		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 		urb->transfer_buffer = buf;
 		urb->interval = interval;
@@ -886,6 +896,7 @@ static int em28xx_audio_urb_init(struct
 static int em28xx_audio_init(struct em28xx *dev)
 {
 	struct em28xx_audio *adev = &dev->adev;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	struct snd_pcm      *pcm;
 	struct snd_card     *card;
 	static int          devnr;
@@ -898,23 +909,23 @@ static int em28xx_audio_init(struct em28
 		return 0;
 	}
 
-	em28xx_info("Binding audio extension\n");
+	dev_info(&dev->intf->dev, "Binding audio extension\n");
 
 	kref_get(&dev->ref);
 
-	printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
-			 "Rechberger\n");
-	printk(KERN_INFO
-	       "em28xx-audio.c: Copyright (C) 2007-2014 Mauro Carvalho Chehab\n");
+	dev_info(&dev->intf->dev,
+		 "em28xx-audio.c: Copyright (C) 2006 Markus Rechberger\n");
+	dev_info(&dev->intf->dev,
+		 "em28xx-audio.c: Copyright (C) 2007-2016 Mauro Carvalho Chehab\n");
 
-	err = snd_card_new(&dev->udev->dev, index[devnr], "Em28xx Audio",
+	err = snd_card_new(&dev->intf->dev, index[devnr], "Em28xx Audio",
 			   THIS_MODULE, 0, &card);
 	if (err < 0)
 		return err;
 
 	spin_lock_init(&adev->slock);
 	adev->sndcard = card;
-	adev->udev = dev->udev;
+	adev->udev = udev;
 
 	err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
 	if (err < 0)
@@ -955,7 +966,7 @@ static int em28xx_audio_init(struct em28
 	if (err < 0)
 		goto urb_free;
 
-	em28xx_info("Audio extension successfully initialized\n");
+	dev_info(&dev->intf->dev, "Audio extension successfully initialized\n");
 	return 0;
 
 urb_free:
@@ -980,7 +991,7 @@ static int em28xx_audio_fini(struct em28
 		return 0;
 	}
 
-	em28xx_info("Closing audio extension\n");
+	dev_info(&dev->intf->dev, "Closing audio extension\n");
 
 	if (dev->adev.sndcard) {
 		snd_card_disconnect(dev->adev.sndcard);
@@ -1004,7 +1015,7 @@ static int em28xx_audio_suspend(struct e
 	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
 		return 0;
 
-	em28xx_info("Suspending audio extension\n");
+	dev_info(&dev->intf->dev, "Suspending audio extension\n");
 	em28xx_deinit_isoc_audio(dev);
 	atomic_set(&dev->adev.stream_started, 0);
 	return 0;
@@ -1018,7 +1029,7 @@ static int em28xx_audio_resume(struct em
 	if (dev->usb_audio_type != EM28XX_USB_AUDIO_VENDOR)
 		return 0;
 
-	em28xx_info("Resuming audio extension\n");
+	dev_info(&dev->intf->dev, "Resuming audio extension\n");
 	/* Nothing to do other than schedule_work() ?? */
 	schedule_work(&dev->adev.wq_trigger);
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-camera.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-camera.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-camera.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-camera.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,14 +19,15 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "em28xx.h"
+
 #include <linux/i2c.h>
+#include <linux/usb.h>
 #include <media/soc_camera.h>
 #include <media/i2c/mt9v011.h>
 #include <media/v4l2-clk.h>
 #include <media/v4l2-common.h>
 
-#include "em28xx.h"
-
 /* Possible i2c addresses of Micron sensors */
 static unsigned short micron_sensor_addrs[] = {
 	0xb8 >> 1,   /* MT9V111, MT9V403 */
@@ -120,14 +121,16 @@ static int em28xx_probe_sensor_micron(st
 		ret = i2c_master_send(&client, &reg, 1);
 		if (ret < 0) {
 			if (ret != -ENXIO)
-				em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-					      client.addr << 1, ret);
+				dev_err(&dev->intf->dev,
+					"couldn't read from i2c device 0x%02x: error %i\n",
+				       client.addr << 1, ret);
 			continue;
 		}
 		ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
 		if (ret < 0) {
-			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-				      client.addr << 1, ret);
+			dev_err(&dev->intf->dev,
+				"couldn't read from i2c device 0x%02x: error %i\n",
+				client.addr << 1, ret);
 			continue;
 		}
 		id = be16_to_cpu(id_be);
@@ -135,14 +138,16 @@ static int em28xx_probe_sensor_micron(st
 		reg = 0xff;
 		ret = i2c_master_send(&client, &reg, 1);
 		if (ret < 0) {
-			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-				      client.addr << 1, ret);
+			dev_err(&dev->intf->dev,
+				"couldn't read from i2c device 0x%02x: error %i\n",
+				client.addr << 1, ret);
 			continue;
 		}
 		ret = i2c_master_recv(&client, (u8 *)&id_be, 2);
 		if (ret < 0) {
-			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-				      client.addr << 1, ret);
+			dev_err(&dev->intf->dev,
+				"couldn't read from i2c device 0x%02x: error %i\n",
+				client.addr << 1, ret);
 			continue;
 		}
 		/* Validate chip ID to be sure we have a Micron device */
@@ -180,15 +185,17 @@ static int em28xx_probe_sensor_micron(st
 			dev->em28xx_sensor = EM28XX_MT9M001;
 			break;
 		default:
-			em28xx_info("unknown Micron sensor detected: 0x%04x\n",
-				    id);
+			dev_info(&dev->intf->dev,
+				 "unknown Micron sensor detected: 0x%04x\n", id);
 			return 0;
 		}
 
 		if (dev->em28xx_sensor == EM28XX_NOSENSOR)
-			em28xx_info("unsupported sensor detected: %s\n", name);
+			dev_info(&dev->intf->dev,
+				 "unsupported sensor detected: %s\n", name);
 		else
-			em28xx_info("sensor %s detected\n", name);
+			dev_info(&dev->intf->dev,
+				 "sensor %s detected\n", name);
 
 		dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
 		return 0;
@@ -218,16 +225,18 @@ static int em28xx_probe_sensor_omnivisio
 		ret = i2c_smbus_read_byte_data(&client, reg);
 		if (ret < 0) {
 			if (ret != -ENXIO)
-				em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-					      client.addr << 1, ret);
+				dev_err(&dev->intf->dev,
+					"couldn't read from i2c device 0x%02x: error %i\n",
+					client.addr << 1, ret);
 			continue;
 		}
 		id = ret << 8;
 		reg = 0x1d;
 		ret = i2c_smbus_read_byte_data(&client, reg);
 		if (ret < 0) {
-			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-				      client.addr << 1, ret);
+			dev_err(&dev->intf->dev,
+				"couldn't read from i2c device 0x%02x: error %i\n",
+				client.addr << 1, ret);
 			continue;
 		}
 		id += ret;
@@ -238,16 +247,18 @@ static int em28xx_probe_sensor_omnivisio
 		reg = 0x0a;
 		ret = i2c_smbus_read_byte_data(&client, reg);
 		if (ret < 0) {
-			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-				      client.addr << 1, ret);
+			dev_err(&dev->intf->dev,
+				"couldn't read from i2c device 0x%02x: error %i\n",
+				client.addr << 1, ret);
 			continue;
 		}
 		id = ret << 8;
 		reg = 0x0b;
 		ret = i2c_smbus_read_byte_data(&client, reg);
 		if (ret < 0) {
-			em28xx_errdev("couldn't read from i2c device 0x%02x: error %i\n",
-				      client.addr << 1, ret);
+			dev_err(&dev->intf->dev,
+				"couldn't read from i2c device 0x%02x: error %i\n",
+				client.addr << 1, ret);
 			continue;
 		}
 		id += ret;
@@ -285,15 +296,18 @@ static int em28xx_probe_sensor_omnivisio
 			name = "OV9655";
 			break;
 		default:
-			em28xx_info("unknown OmniVision sensor detected: 0x%04x\n",
-				    id);
+			dev_info(&dev->intf->dev,
+				 "unknown OmniVision sensor detected: 0x%04x\n",
+				id);
 			return 0;
 		}
 
 		if (dev->em28xx_sensor == EM28XX_NOSENSOR)
-			em28xx_info("unsupported sensor detected: %s\n", name);
+			dev_info(&dev->intf->dev,
+				 "unsupported sensor detected: %s\n", name);
 		else
-			em28xx_info("sensor %s detected\n", name);
+			dev_info(&dev->intf->dev,
+				 "sensor %s detected\n", name);
 
 		dev->i2c_client[dev->def_i2c_bus].addr = client.addr;
 		return 0;
@@ -317,7 +331,8 @@ int em28xx_detect_sensor(struct em28xx *
 	 */
 
 	if (dev->em28xx_sensor == EM28XX_NOSENSOR && ret < 0) {
-		em28xx_info("No sensor detected\n");
+		dev_info(&dev->intf->dev,
+			 "No sensor detected\n");
 		return -ENODEV;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-cards.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-cards.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-cards.c	2016-12-11 17:43:41.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-cards.c	2017-02-12 17:28:09.000000000 -0500
@@ -23,6 +23,8 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "em28xx.h"
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -39,7 +41,6 @@
 #include <media/v4l2-common.h>
 #include <sound/ac97_codec.h>
 
-#include "em28xx.h"
 
 #define DRIVER_NAME         "em28xx"
 
@@ -1560,8 +1561,7 @@ struct em28xx_board em28xx_boards[] = {
 		} },
 	},
 	[EM2820_BOARD_PINNACLE_DVC_90] = {
-		.name         = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker "
-			       "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U",
+		.name	      = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker / Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U",
 		.tuner_type   = TUNER_ABSENT, /* capture only board */
 		.decoder      = EM28XX_SAA711X,
 		.input        = { {
@@ -2677,7 +2677,7 @@ static int em28xx_wait_until_ac97_featur
 		msleep(50);
 	}
 
-	em28xx_warn("AC97 registers access is not reliable !\n");
+	dev_warn(&dev->intf->dev, "AC97 registers access is not reliable !\n");
 	return -ETIMEDOUT;
 }
 
@@ -2831,16 +2831,14 @@ static int em28xx_hint_board(struct em28
 			dev->model = em28xx_eeprom_hash[i].model;
 			dev->tuner_type = em28xx_eeprom_hash[i].tuner;
 
-			em28xx_errdev("Your board has no unique USB ID.\n");
-			em28xx_errdev("A hint were successfully done, "
-				      "based on eeprom hash.\n");
-			em28xx_errdev("This method is not 100%% failproof.\n");
-			em28xx_errdev("If the board were missdetected, "
-				      "please email this log to:\n");
-			em28xx_errdev("\tV4L Mailing List "
-				      " <linux-media@vger.kernel.org>\n");
-			em28xx_errdev("Board detected as %s\n",
-				      em28xx_boards[dev->model].name);
+			dev_err(&dev->intf->dev,
+				"Your board has no unique USB ID.\n"
+				"A hint were successfully done, based on eeprom hash.\n"
+				"This method is not 100%% failproof.\n"
+				"If the board were missdetected, please email this log to:\n"
+				"\tV4L Mailing List  <linux-media@vger.kernel.org>\n"
+				"Board detected as %s\n",
+			       em28xx_boards[dev->model].name);
 
 			return 0;
 		}
@@ -2863,35 +2861,33 @@ static int em28xx_hint_board(struct em28
 		if (dev->i2c_hash == em28xx_i2c_hash[i].hash) {
 			dev->model = em28xx_i2c_hash[i].model;
 			dev->tuner_type = em28xx_i2c_hash[i].tuner;
-			em28xx_errdev("Your board has no unique USB ID.\n");
-			em28xx_errdev("A hint were successfully done, "
-				      "based on i2c devicelist hash.\n");
-			em28xx_errdev("This method is not 100%% failproof.\n");
-			em28xx_errdev("If the board were missdetected, "
-				      "please email this log to:\n");
-			em28xx_errdev("\tV4L Mailing List "
-				      " <linux-media@vger.kernel.org>\n");
-			em28xx_errdev("Board detected as %s\n",
-				      em28xx_boards[dev->model].name);
+			dev_err(&dev->intf->dev,
+				"Your board has no unique USB ID.\n"
+				"A hint were successfully done, based on i2c devicelist hash.\n"
+				"This method is not 100%% failproof.\n"
+				"If the board were missdetected, please email this log to:\n"
+				"\tV4L Mailing List  <linux-media@vger.kernel.org>\n"
+				"Board detected as %s\n",
+				em28xx_boards[dev->model].name);
 
 			return 0;
 		}
 	}
 
-	em28xx_errdev("Your board has no unique USB ID and thus need a "
-		      "hint to be detected.\n");
-	em28xx_errdev("You may try to use card=<n> insmod option to "
-		      "workaround that.\n");
-	em28xx_errdev("Please send an email with this log to:\n");
-	em28xx_errdev("\tV4L Mailing List <linux-media@vger.kernel.org>\n");
-	em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash);
-	em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash);
+	dev_err(&dev->intf->dev,
+		"Your board has no unique USB ID and thus need a hint to be detected.\n"
+		"You may try to use card=<n> insmod option to workaround that.\n"
+		"Please send an email with this log to:\n"
+		"\tV4L Mailing List <linux-media@vger.kernel.org>\n"
+		"Board eeprom hash is 0x%08lx\n"
+		"Board i2c devicelist hash is 0x%08lx\n",
+		dev->hash, dev->i2c_hash);
 
-	em28xx_errdev("Here is a list of valid choices for the card=<n>"
-		      " insmod option:\n");
+	dev_err(&dev->intf->dev,
+		"Here is a list of valid choices for the card=<n> insmod option:\n");
 	for (i = 0; i < em28xx_bcount; i++) {
-		em28xx_errdev("    card=%d -> %s\n",
-			      i, em28xx_boards[i].name);
+		dev_err(&dev->intf->dev,
+			"    card=%d -> %s\n", i, em28xx_boards[i].name);
 	}
 	return -1;
 }
@@ -2925,7 +2921,7 @@ static void em28xx_card_setup(struct em2
 		 * hash identities which has not been determined as yet.
 		 */
 		if (em28xx_hint_board(dev) < 0)
-			em28xx_errdev("Board not discovered\n");
+			dev_err(&dev->intf->dev, "Board not discovered\n");
 		else {
 			em28xx_set_model(dev);
 			em28xx_pre_card_setup(dev);
@@ -2935,8 +2931,8 @@ static void em28xx_card_setup(struct em2
 		em28xx_set_model(dev);
 	}
 
-	em28xx_info("Identified as %s (card=%d)\n",
-		    dev->board.name, dev->model);
+	dev_info(&dev->intf->dev, "Identified as %s (card=%d)\n",
+		dev->board.name, dev->model);
 
 	dev->tuner_type = em28xx_boards[dev->model].tuner_type;
 
@@ -3034,12 +3030,11 @@ static void em28xx_card_setup(struct em2
 	}
 
 	if (dev->board.valid == EM28XX_BOARD_NOT_VALIDATED) {
-		em28xx_errdev("\n\n");
-		em28xx_errdev("The support for this board weren't "
-			      "valid yet.\n");
-		em28xx_errdev("Please send a report of having this working\n");
-		em28xx_errdev("not to V4L mailing list (and/or to other "
-				"addresses)\n\n");
+		dev_err(&dev->intf->dev,
+			"\n\n"
+			"The support for this board weren't valid yet.\n"
+			"Please send a report of having this working\n"
+			"not to V4L mailing list (and/or to other addresses)\n\n");
 	}
 
 	/* Free eeprom data memory */
@@ -3166,7 +3161,7 @@ static int em28xx_media_device_init(stru
 	else if (udev->manufacturer)
 		media_device_usb_init(mdev, udev, udev->manufacturer);
 	else
-		media_device_usb_init(mdev, udev, dev->name);
+		media_device_usb_init(mdev, udev, dev_name(&dev->intf->dev));
 
 	dev->media_dev = mdev;
 #endif
@@ -3193,6 +3188,8 @@ static void em28xx_unregister_media_devi
 */
 static void em28xx_release_resources(struct em28xx *dev)
 {
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
+
 	/*FIXME: I2C IR should be disconnected */
 
 	mutex_lock(&dev->lock);
@@ -3203,7 +3200,7 @@ static void em28xx_release_resources(str
 		em28xx_i2c_unregister(dev, 1);
 	em28xx_i2c_unregister(dev, 0);
 
-	usb_put_dev(dev->udev);
+	usb_put_dev(udev);
 
 	/* Mark device as unused */
 	clear_bit(dev->devno, em28xx_devused);
@@ -3222,7 +3219,7 @@ void em28xx_free_device(struct kref *ref
 {
 	struct em28xx *dev = kref_to_dev(ref);
 
-	em28xx_info("Freeing device\n");
+	dev_info(&dev->intf->dev, "Freeing device\n");
 
 	if (!dev->disconnected)
 		em28xx_release_resources(dev);
@@ -3241,10 +3238,9 @@ static int em28xx_init_dev(struct em28xx
 			   int minor)
 {
 	int retval;
-	static const char *default_chip_name = "em28xx";
-	const char *chip_name = default_chip_name;
+	const char *chip_name = NULL;
 
-	dev->udev = udev;
+	dev->intf = interface;
 	mutex_init(&dev->ctrl_urb_lock);
 	spin_lock_init(&dev->slock);
 
@@ -3282,9 +3278,8 @@ static int em28xx_init_dev(struct em28xx
 			break;
 		case CHIP_ID_EM2820:
 			chip_name = "em2710/2820";
-			if (le16_to_cpu(dev->udev->descriptor.idVendor)
-								    == 0xeb1a) {
-				__le16 idProd = dev->udev->descriptor.idProduct;
+			if (le16_to_cpu(udev->descriptor.idVendor) == 0xeb1a) {
+				__le16 idProd = udev->descriptor.idProduct;
 
 				if (le16_to_cpu(idProd) == 0x2710)
 					chip_name = "em2710";
@@ -3327,21 +3322,13 @@ static int em28xx_init_dev(struct em28xx
 			dev->wait_after_write = 0;
 			dev->eeprom_addrwidth_16bit = 1;
 			break;
-		default:
-			printk(KERN_INFO DRIVER_NAME
-			       ": unknown em28xx chip ID (%d)\n", dev->chip_id);
 		}
 	}
-
-	if (chip_name != default_chip_name)
-		printk(KERN_INFO DRIVER_NAME
-		       ": chip ID is %s\n", chip_name);
-
-	/*
-	 * For em2820/em2710, the name may change latter, after checking
-	 * if the device has a sensor (so, it is em2710) or not.
-	 */
-	snprintf(dev->name, sizeof(dev->name), "%s #%d", chip_name, dev->devno);
+	if (!chip_name)
+		dev_info(&dev->intf->dev,
+			 "unknown em28xx chip ID (%d)\n", dev->chip_id);
+	else
+		dev_info(&dev->intf->dev, "chip ID is %s\n", chip_name);
 
 	em28xx_media_device_init(dev, udev);
 
@@ -3360,9 +3347,9 @@ static int em28xx_init_dev(struct em28xx
 		/* Resets I2C speed */
 		retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
 		if (retval < 0) {
-			em28xx_errdev("%s: em28xx_write_reg failed!"
-				      " retval [%d]\n",
-				      __func__, retval);
+			dev_err(&dev->intf->dev,
+			       "%s: em28xx_write_reg failed! retval [%d]\n",
+			       __func__, retval);
 			return retval;
 		}
 	}
@@ -3375,8 +3362,9 @@ static int em28xx_init_dev(struct em28xx
 	else
 		retval = em28xx_i2c_register(dev, 0, EM28XX_I2C_ALGO_EM28XX);
 	if (retval < 0) {
-		em28xx_errdev("%s: em28xx_i2c_register bus 0 - error [%d]!\n",
-			      __func__, retval);
+		dev_err(&dev->intf->dev,
+			"%s: em28xx_i2c_register bus 0 - error [%d]!\n",
+		       __func__, retval);
 		return retval;
 	}
 
@@ -3389,8 +3377,9 @@ static int em28xx_init_dev(struct em28xx
 			retval = em28xx_i2c_register(dev, 1,
 						     EM28XX_I2C_ALGO_EM28XX);
 		if (retval < 0) {
-			em28xx_errdev("%s: em28xx_i2c_register bus 1 - error [%d]!\n",
-				      __func__, retval);
+			dev_err(&dev->intf->dev,
+			       "%s: em28xx_i2c_register bus 1 - error [%d]!\n",
+			       __func__, retval);
 
 			em28xx_i2c_unregister(dev, 0);
 
@@ -3429,7 +3418,8 @@ static int em28xx_usb_probe(struct usb_i
 		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",
+			dev_err(&interface->dev,
+				"Driver supports up to %i em28xx boards.\n",
 			       EM28XX_MAXBOARDS);
 			retval = -ENOMEM;
 			goto err_no_slot;
@@ -3438,8 +3428,8 @@ static int em28xx_usb_probe(struct usb_i
 
 	/* Don't register audio interfaces */
 	if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
-		em28xx_err(DRIVER_NAME " audio device (%04x:%04x): "
-			"interface %i, class %i\n",
+		dev_err(&interface->dev,
+			"audio device (%04x:%04x): interface %i, class %i\n",
 			le16_to_cpu(udev->descriptor.idVendor),
 			le16_to_cpu(udev->descriptor.idProduct),
 			ifnum,
@@ -3452,7 +3442,6 @@ static int em28xx_usb_probe(struct usb_i
 	/* 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");
 		retval = -ENOMEM;
 		goto err;
 	}
@@ -3462,7 +3451,6 @@ static int em28xx_usb_probe(struct usb_i
 				kmalloc(sizeof(dev->alt_max_pkt_size_isoc[0]) *
 					interface->num_altsetting, GFP_KERNEL);
 	if (dev->alt_max_pkt_size_isoc == NULL) {
-		em28xx_errdev("out of memory!\n");
 		kfree(dev);
 		retval = -ENOMEM;
 		goto err;
@@ -3501,8 +3489,8 @@ static int em28xx_usb_probe(struct usb_i
 					if (usb_endpoint_xfer_isoc(e)) {
 						has_vendor_audio = true;
 					} else {
-						printk(KERN_INFO DRIVER_NAME
-						": error: skipping audio endpoint 0x83, because it uses bulk transfers !\n");
+						dev_err(&interface->dev,
+							"error: skipping audio endpoint 0x83, because it uses bulk transfers !\n");
 					}
 					break;
 				case 0x84:
@@ -3575,9 +3563,8 @@ static int em28xx_usb_probe(struct usb_i
 		speed = "unknown";
 	}
 
-	printk(KERN_INFO DRIVER_NAME
-		": New device %s %s @ %s Mbps "
-		"(%04x:%04x, interface %d, class %d)\n",
+	dev_err(&interface->dev,
+		"New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n",
 		udev->manufacturer ? udev->manufacturer : "",
 		udev->product ? udev->product : "",
 		speed,
@@ -3592,9 +3579,9 @@ static int em28xx_usb_probe(struct usb_i
 	 * not enough even for most Digital TV streams.
 	 */
 	if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
-		printk(DRIVER_NAME ": Device initialization failed.\n");
-		printk(DRIVER_NAME ": Device must be connected to a high-speed"
-		       " USB 2.0 port.\n");
+		dev_err(&interface->dev, "Device initialization failed.\n");
+		dev_err(&interface->dev,
+			"Device must be connected to a high-speed USB 2.0 port.\n");
 		retval = -ENODEV;
 		goto err_free;
 	}
@@ -3607,8 +3594,8 @@ static int em28xx_usb_probe(struct usb_i
 	dev->ifnum = ifnum;
 
 	if (has_vendor_audio) {
-		printk(KERN_INFO DRIVER_NAME ": Audio interface %i found %s\n",
-		       ifnum, "(Vendor Class)");
+		dev_err(&interface->dev,
+			"Audio interface %i found (Vendor Class)\n", ifnum);
 		dev->usb_audio_type = EM28XX_USB_AUDIO_VENDOR;
 	}
 	/* Checks if audio is provided by a USB Audio Class interface */
@@ -3617,25 +3604,24 @@ static int em28xx_usb_probe(struct usb_i
 
 		if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
 			if (has_vendor_audio)
-				em28xx_err("em28xx: device seems to have vendor AND usb audio class interfaces !\n"
-					   "\t\tThe vendor interface will be ignored. Please contact the developers <linux-media@vger.kernel.org>\n");
+				dev_err(&interface->dev,
+					"em28xx: device seems to have vendor AND usb audio class interfaces !\n"
+				       "\t\tThe vendor interface will be ignored. Please contact the developers <linux-media@vger.kernel.org>\n");
 			dev->usb_audio_type = EM28XX_USB_AUDIO_CLASS;
 			break;
 		}
 	}
 
 	if (has_video)
-		printk(KERN_INFO DRIVER_NAME
-		       ": Video interface %i found:%s%s\n",
-		       ifnum,
-		       dev->analog_ep_bulk ? " bulk" : "",
-		       dev->analog_ep_isoc ? " isoc" : "");
+		dev_err(&interface->dev, "Video interface %i found:%s%s\n",
+			ifnum,
+			dev->analog_ep_bulk ? " bulk" : "",
+			dev->analog_ep_isoc ? " isoc" : "");
 	if (has_dvb)
-		printk(KERN_INFO DRIVER_NAME
-		       ": DVB interface %i found:%s%s\n",
-		       ifnum,
-		       dev->dvb_ep_bulk ? " bulk" : "",
-		       dev->dvb_ep_isoc ? " isoc" : "");
+		dev_err(&interface->dev, "DVB interface %i found:%s%s\n",
+			ifnum,
+			dev->dvb_ep_bulk ? " bulk" : "",
+			dev->dvb_ep_isoc ? " isoc" : "");
 
 	dev->num_alt = interface->num_altsetting;
 
@@ -3664,8 +3650,8 @@ static int em28xx_usb_probe(struct usb_i
 	/* Disable V4L2 if the device doesn't have a decoder */
 	if (has_video &&
 	    dev->board.decoder == EM28XX_NODECODER && !dev->board.is_webcam) {
-		printk(DRIVER_NAME
-		       ": Currently, V4L2 is not supported on this model\n");
+		dev_err(&interface->dev,
+			"Currently, V4L2 is not supported on this model\n");
 		has_video = false;
 		dev->has_video = false;
 	}
@@ -3674,14 +3660,14 @@ static int em28xx_usb_probe(struct usb_i
 	if (has_video) {
 		if (!dev->analog_ep_isoc || (try_bulk && dev->analog_ep_bulk))
 			dev->analog_xfer_bulk = 1;
-		em28xx_info("analog set to %s mode.\n",
-			    dev->analog_xfer_bulk ? "bulk" : "isoc");
+		dev_err(&interface->dev, "analog set to %s mode.\n",
+			dev->analog_xfer_bulk ? "bulk" : "isoc");
 	}
 	if (has_dvb) {
 		if (!dev->dvb_ep_isoc || (try_bulk && dev->dvb_ep_bulk))
 			dev->dvb_xfer_bulk = 1;
-		em28xx_info("dvb set to %s mode.\n",
-			    dev->dvb_xfer_bulk ? "bulk" : "isoc");
+		dev_err(&interface->dev, "dvb set to %s mode.\n",
+			dev->dvb_xfer_bulk ? "bulk" : "isoc");
 	}
 
 	kref_init(&dev->ref);
@@ -3728,7 +3714,7 @@ static void em28xx_usb_disconnect(struct
 
 	dev->disconnected = 1;
 
-	em28xx_info("Disconnecting %s\n", dev->name);
+	dev_err(&dev->intf->dev, "Disconnecting\n");
 
 	flush_request_modules(dev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,8 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "em28xx.h"
+
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/list.h>
@@ -32,8 +34,6 @@
 #include <sound/ac97_codec.h>
 #include <media/v4l2-common.h>
 
-#include "em28xx.h"
-
 #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
 		      "Markus Rechberger <mrechberger@gmail.com>, " \
 		      "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
@@ -48,27 +48,31 @@ MODULE_VERSION(EM28XX_VERSION);
 
 static unsigned int core_debug;
 module_param(core_debug, int, 0644);
-MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
+MODULE_PARM_DESC(core_debug, "enable debug messages [core and isoc]");
 
-#define em28xx_coredbg(fmt, arg...) do {\
-	if (core_debug) \
-		printk(KERN_INFO "%s %s :"fmt, \
-			 dev->name, __func__ , ##arg); } while (0)
+#define em28xx_coredbg(fmt, arg...) do {				\
+	if (core_debug)							\
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "core: %s: " fmt, __func__, ## arg);		\
+} while (0)
 
 static unsigned int reg_debug;
 module_param(reg_debug, int, 0644);
 MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
 
-#define em28xx_regdbg(fmt, arg...) do {\
-	if (reg_debug) \
-		printk(KERN_INFO "%s %s :"fmt, \
-			 dev->name, __func__ , ##arg); } while (0)
 
-/* FIXME */
-#define em28xx_isocdbg(fmt, arg...) do {\
-	if (core_debug) \
-		printk(KERN_INFO "%s %s :"fmt, \
-			 dev->name, __func__ , ##arg); } while (0)
+#define em28xx_regdbg(fmt, arg...) do {				\
+	if (reg_debug)							\
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "reg: %s: " fmt, __func__, ## arg);		\
+} while (0)
+
+/* FIXME: don't abuse core_debug */
+#define em28xx_isocdbg(fmt, arg...) do {				\
+	if (core_debug)							\
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "core: %s: " fmt, __func__, ## arg);		\
+} while (0)
 
 /*
  * em28xx_read_reg_req()
@@ -78,7 +82,8 @@ int em28xx_read_reg_req_len(struct em28x
 			    char *buf, int len)
 {
 	int ret;
-	int pipe = usb_rcvctrlpipe(dev->udev, 0);
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
+	int pipe = usb_rcvctrlpipe(udev, 0);
 
 	if (dev->disconnected)
 		return -ENODEV;
@@ -86,23 +91,22 @@ int em28xx_read_reg_req_len(struct em28x
 	if (len > URB_MAX_CTRL_SIZE)
 		return -EINVAL;
 
-	if (reg_debug) {
-		printk(KERN_DEBUG "(pipe 0x%08x): "
-			"IN:  %02x %02x %02x %02x %02x %02x %02x %02x ",
-			pipe,
-			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			req, 0, 0,
-			reg & 0xff, reg >> 8,
-			len & 0xff, len >> 8);
-	}
+	em28xx_regdbg("(pipe 0x%08x): IN:  %02x %02x %02x %02x %02x %02x %02x %02x ",
+		     pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		     req, 0, 0,
+		     reg & 0xff, reg >> 8,
+		     len & 0xff, len >> 8);
 
 	mutex_lock(&dev->ctrl_urb_lock);
-	ret = usb_control_msg(dev->udev, pipe, req,
+	ret = usb_control_msg(udev, pipe, req,
 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x0000, reg, dev->urb_buf, len, HZ);
 	if (ret < 0) {
-		if (reg_debug)
-			printk(" failed!\n");
+		em28xx_regdbg("(pipe 0x%08x): IN:  %02x %02x %02x %02x %02x %02x %02x %02x  failed\n",
+			     pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			     req, 0, 0,
+			     reg & 0xff, reg >> 8,
+			     len & 0xff, len >> 8);
 		mutex_unlock(&dev->ctrl_urb_lock);
 		return usb_translate_errors(ret);
 	}
@@ -112,14 +116,11 @@ int em28xx_read_reg_req_len(struct em28x
 
 	mutex_unlock(&dev->ctrl_urb_lock);
 
-	if (reg_debug) {
-		int byte;
-
-		printk("<<<");
-		for (byte = 0; byte < len; byte++)
-			printk(" %02x", (unsigned char)buf[byte]);
-		printk("\n");
-	}
+	em28xx_regdbg("(pipe 0x%08x): IN:  %02x %02x %02x %02x %02x %02x %02x %02x  failed <<< %*ph\n",
+		     pipe, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		     req, 0, 0,
+		     reg & 0xff, reg >> 8,
+		     len & 0xff, len >> 8, len, buf);
 
 	return ret;
 }
@@ -154,7 +155,8 @@ int em28xx_write_regs_req(struct em28xx
 			  int len)
 {
 	int ret;
-	int pipe = usb_sndctrlpipe(dev->udev, 0);
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
+	int pipe = usb_sndctrlpipe(udev, 0);
 
 	if (dev->disconnected)
 		return -ENODEV;
@@ -162,25 +164,16 @@ int em28xx_write_regs_req(struct em28xx
 	if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
 		return -EINVAL;
 
-	if (reg_debug) {
-		int byte;
-
-		printk(KERN_DEBUG "(pipe 0x%08x): "
-			"OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
-			pipe,
-			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			req, 0, 0,
-			reg & 0xff, reg >> 8,
-			len & 0xff, len >> 8);
-
-		for (byte = 0; byte < len; byte++)
-			printk(" %02x", (unsigned char)buf[byte]);
-		printk("\n");
-	}
+	em28xx_regdbg("(pipe 0x%08x): OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>> %*ph\n",
+		      pipe,
+		      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		      req, 0, 0,
+		      reg & 0xff, reg >> 8,
+		      len & 0xff, len >> 8, len, buf);
 
 	mutex_lock(&dev->ctrl_urb_lock);
 	memcpy(dev->urb_buf, buf, len);
-	ret = usb_control_msg(dev->udev, pipe, req,
+	ret = usb_control_msg(udev, pipe, req,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      0x0000, reg, dev->urb_buf, len, HZ);
 	mutex_unlock(&dev->ctrl_urb_lock);
@@ -267,7 +260,8 @@ static int em28xx_is_ac97_ready(struct e
 		msleep(5);
 	}
 
-	em28xx_warn("AC97 command still being executed: not handled properly!\n");
+	dev_warn(&dev->intf->dev,
+		 "AC97 command still being executed: not handled properly!\n");
 	return -EBUSY;
 }
 
@@ -360,8 +354,9 @@ static int set_ac97_input(struct em28xx
 			ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000);
 
 		if (ret < 0)
-			em28xx_warn("couldn't setup AC97 register %d\n",
-				    inputs[i].reg);
+			dev_warn(&dev->intf->dev,
+				 "couldn't setup AC97 register %d\n",
+				 inputs[i].reg);
 	}
 	return 0;
 }
@@ -444,8 +439,9 @@ int em28xx_audio_analog_set(struct em28x
 		for (i = 0; i < ARRAY_SIZE(outputs); i++) {
 			ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000);
 			if (ret < 0)
-				em28xx_warn("couldn't setup AC97 register %d\n",
-					    outputs[i].reg);
+				dev_warn(&dev->intf->dev,
+					 "couldn't setup AC97 register %d\n",
+					 outputs[i].reg);
 		}
 	}
 
@@ -482,8 +478,9 @@ int em28xx_audio_analog_set(struct em28x
 				ret = em28xx_write_ac97(dev, outputs[i].reg,
 							vol);
 			if (ret < 0)
-				em28xx_warn("couldn't setup AC97 register %d\n",
-					    outputs[i].reg);
+				dev_warn(&dev->intf->dev,
+					 "couldn't setup AC97 register %d\n",
+					 outputs[i].reg);
 		}
 
 		if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
@@ -519,7 +516,7 @@ int em28xx_audio_setup(struct em28xx *de
 
 	/* See how this device is configured */
 	cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG);
-	em28xx_info("Config register raw data: 0x%02x\n", cfg);
+	dev_info(&dev->intf->dev, "Config register raw data: 0x%02x\n", cfg);
 	if (cfg < 0) { /* Register read error */
 		/* Be conservative */
 		dev->int_audio_type = EM28XX_INT_AUDIO_AC97;
@@ -540,8 +537,8 @@ int em28xx_audio_setup(struct em28xx *de
 			i2s_samplerates = 5;
 		else
 			i2s_samplerates = 3;
-		em28xx_info("I2S Audio (%d sample rate(s))\n",
-			    i2s_samplerates);
+		dev_info(&dev->intf->dev, "I2S Audio (%d sample rate(s))\n",
+			i2s_samplerates);
 		/* Skip the code that does AC97 vendor detection */
 		dev->audio_mode.ac97 = EM28XX_NO_AC97;
 		goto init_audio;
@@ -558,7 +555,8 @@ int em28xx_audio_setup(struct em28xx *de
 		 * Note: (some) em2800 devices without eeprom reports 0x91 on
 		 *	 CHIPCFG register, even not having an AC97 chip
 		 */
-		em28xx_warn("AC97 chip type couldn't be determined\n");
+		dev_warn(&dev->intf->dev,
+			 "AC97 chip type couldn't be determined\n");
 		dev->audio_mode.ac97 = EM28XX_NO_AC97;
 		if (dev->usb_audio_type == EM28XX_USB_AUDIO_VENDOR)
 			dev->usb_audio_type = EM28XX_USB_AUDIO_NONE;
@@ -571,13 +569,13 @@ int em28xx_audio_setup(struct em28xx *de
 		goto init_audio;
 
 	vid = vid1 << 16 | vid2;
-	em28xx_warn("AC97 vendor ID = 0x%08x\n", vid);
+	dev_warn(&dev->intf->dev, "AC97 vendor ID = 0x%08x\n", vid);
 
 	feat = em28xx_read_ac97(dev, AC97_RESET);
 	if (feat < 0)
 		goto init_audio;
 
-	em28xx_warn("AC97 features = 0x%04x\n", feat);
+	dev_warn(&dev->intf->dev, "AC97 features = 0x%04x\n", feat);
 
 	/* Try to identify what audio processor we have */
 	if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90))
@@ -589,17 +587,20 @@ init_audio:
 	/* Reports detected AC97 processor */
 	switch (dev->audio_mode.ac97) {
 	case EM28XX_NO_AC97:
-		em28xx_info("No AC97 audio processor\n");
+		dev_info(&dev->intf->dev, "No AC97 audio processor\n");
 		break;
 	case EM28XX_AC97_EM202:
-		em28xx_info("Empia 202 AC97 audio processor detected\n");
+		dev_info(&dev->intf->dev,
+			 "Empia 202 AC97 audio processor detected\n");
 		break;
 	case EM28XX_AC97_SIGMATEL:
-		em28xx_info("Sigmatel audio processor detected (stac 97%02x)\n",
-			    vid & 0xff);
+		dev_info(&dev->intf->dev,
+			 "Sigmatel audio processor detected (stac 97%02x)\n",
+			 vid & 0xff);
 		break;
 	case EM28XX_AC97_OTHER:
-		em28xx_warn("Unknown AC97 audio processor detected!\n");
+		dev_warn(&dev->intf->dev,
+			 "Unknown AC97 audio processor detected!\n");
 		break;
 	default:
 		break;
@@ -798,6 +799,7 @@ void em28xx_uninit_usb_xfer(struct em28x
 {
 	struct urb *urb;
 	struct em28xx_usb_bufs *usb_bufs;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int i;
 
 	em28xx_isocdbg("em28xx: called em28xx_uninit_usb_xfer in mode %d\n",
@@ -817,7 +819,7 @@ void em28xx_uninit_usb_xfer(struct em28x
 				usb_unlink_urb(urb);
 
 			if (usb_bufs->transfer_buffer[i]) {
-				usb_free_coherent(dev->udev,
+				usb_free_coherent(udev,
 						  urb->transfer_buffer_length,
 						  usb_bufs->transfer_buffer[i],
 						  urb->transfer_dma);
@@ -871,9 +873,10 @@ int em28xx_alloc_urbs(struct em28xx *dev
 		      int num_bufs, int max_pkt_size, int packet_multiplier)
 {
 	struct em28xx_usb_bufs *usb_bufs;
+	struct urb *urb;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int i;
 	int sb_size, pipe;
-	struct urb *urb;
 	int j, k;
 
 	em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode);
@@ -883,21 +886,23 @@ int em28xx_alloc_urbs(struct em28xx *dev
 	if (mode == EM28XX_DIGITAL_MODE) {
 		if ((xfer_bulk && !dev->dvb_ep_bulk) ||
 		    (!xfer_bulk && !dev->dvb_ep_isoc)) {
-			em28xx_errdev("no endpoint for DVB mode and transfer type %d\n",
-				      xfer_bulk > 0);
+			dev_err(&dev->intf->dev,
+				"no endpoint for DVB mode and transfer type %d\n",
+				xfer_bulk > 0);
 			return -EINVAL;
 		}
 		usb_bufs = &dev->usb_ctl.digital_bufs;
 	} else if (mode == EM28XX_ANALOG_MODE) {
 		if ((xfer_bulk && !dev->analog_ep_bulk) ||
 		    (!xfer_bulk && !dev->analog_ep_isoc)) {
-			em28xx_errdev("no endpoint for analog mode and transfer type %d\n",
-				      xfer_bulk > 0);
+			dev_err(&dev->intf->dev,
+				"no endpoint for analog mode and transfer type %d\n",
+				xfer_bulk > 0);
 			return -EINVAL;
 		}
 		usb_bufs = &dev->usb_ctl.analog_bufs;
 	} else {
-		em28xx_errdev("invalid mode selected\n");
+		dev_err(&dev->intf->dev, "invalid mode selected\n");
 		return -EINVAL;
 	}
 
@@ -907,15 +912,12 @@ int em28xx_alloc_urbs(struct em28xx *dev
 	usb_bufs->num_bufs = num_bufs;
 
 	usb_bufs->urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
-	if (!usb_bufs->urb) {
-		em28xx_errdev("cannot alloc memory for usb buffers\n");
+	if (!usb_bufs->urb)
 		return -ENOMEM;
-	}
 
 	usb_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
 					     GFP_KERNEL);
 	if (!usb_bufs->transfer_buffer) {
-		em28xx_errdev("cannot allocate memory for usb transfer\n");
 		kfree(usb_bufs->urb);
 		return -ENOMEM;
 	}
@@ -939,33 +941,33 @@ int em28xx_alloc_urbs(struct em28xx *dev
 		}
 		usb_bufs->urb[i] = urb;
 
-		usb_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+		usb_bufs->transfer_buffer[i] = usb_alloc_coherent(udev,
 			sb_size, GFP_KERNEL, &urb->transfer_dma);
 		if (!usb_bufs->transfer_buffer[i]) {
-			em28xx_err("unable to allocate %i bytes for transfer"
-					" buffer %i%s\n",
-					sb_size, i,
-					in_interrupt() ? " while in int" : "");
+			dev_err(&dev->intf->dev,
+				"unable to allocate %i bytes for transfer buffer %i%s\n",
+			       sb_size, i,
+			       in_interrupt() ? " while in int" : "");
 			em28xx_uninit_usb_xfer(dev, mode);
 			return -ENOMEM;
 		}
 		memset(usb_bufs->transfer_buffer[i], 0, sb_size);
 
 		if (xfer_bulk) { /* bulk */
-			pipe = usb_rcvbulkpipe(dev->udev,
+			pipe = usb_rcvbulkpipe(udev,
 					       mode == EM28XX_ANALOG_MODE ?
 					       dev->analog_ep_bulk :
 					       dev->dvb_ep_bulk);
-			usb_fill_bulk_urb(urb, dev->udev, pipe,
+			usb_fill_bulk_urb(urb, udev, pipe,
 					  usb_bufs->transfer_buffer[i], sb_size,
 					  em28xx_irq_callback, dev);
 			urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
 		} else { /* isoc */
-			pipe = usb_rcvisocpipe(dev->udev,
+			pipe = usb_rcvisocpipe(udev,
 					       mode == EM28XX_ANALOG_MODE ?
 					       dev->analog_ep_isoc :
 					       dev->dvb_ep_isoc);
-			usb_fill_int_urb(urb, dev->udev, pipe,
+			usb_fill_int_urb(urb, udev, pipe,
 					 usb_bufs->transfer_buffer[i], sb_size,
 					 em28xx_irq_callback, dev, 1);
 			urb->transfer_flags = URB_ISO_ASAP |
@@ -997,6 +999,7 @@ int em28xx_init_usb_xfer(struct em28xx *
 	struct em28xx_dmaqueue *dma_q = &dev->vidq;
 	struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
 	struct em28xx_usb_bufs *usb_bufs;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int i;
 	int rc;
 	int alloc;
@@ -1023,10 +1026,11 @@ int em28xx_init_usb_xfer(struct em28xx *
 	}
 
 	if (xfer_bulk) {
-		rc = usb_clear_halt(dev->udev, usb_bufs->urb[0]->pipe);
+		rc = usb_clear_halt(udev, usb_bufs->urb[0]->pipe);
 		if (rc < 0) {
-			em28xx_err("failed to clear USB bulk endpoint stall/halt condition (error=%i)\n",
-				   rc);
+			dev_err(&dev->intf->dev,
+				"failed to clear USB bulk endpoint stall/halt condition (error=%i)\n",
+			       rc);
 			em28xx_uninit_usb_xfer(dev, mode);
 			return rc;
 		}
@@ -1041,8 +1045,8 @@ int em28xx_init_usb_xfer(struct em28xx *
 	for (i = 0; i < usb_bufs->num_bufs; i++) {
 		rc = usb_submit_urb(usb_bufs->urb[i], GFP_ATOMIC);
 		if (rc) {
-			em28xx_err("submit of urb %i failed (error=%i)\n", i,
-				   rc);
+			dev_err(&dev->intf->dev,
+				"submit of urb %i failed (error=%i)\n", i, rc);
 			em28xx_uninit_usb_xfer(dev, mode);
 			return rc;
 		}
@@ -1075,7 +1079,7 @@ int em28xx_register_extension(struct em2
 		ops->init(dev);
 	}
 	mutex_unlock(&em28xx_devlist_mutex);
-	printk(KERN_INFO "em28xx: Registered (%s) extension\n", ops->name);
+	pr_info("em28xx: Registered (%s) extension\n", ops->name);
 	return 0;
 }
 EXPORT_SYMBOL(em28xx_register_extension);
@@ -1090,7 +1094,7 @@ void em28xx_unregister_extension(struct
 	}
 	list_del(&ops->next);
 	mutex_unlock(&em28xx_devlist_mutex);
-	printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
+	pr_info("em28xx: Removed (%s) extension\n", ops->name);
 }
 EXPORT_SYMBOL(em28xx_unregister_extension);
 
@@ -1124,7 +1128,7 @@ int em28xx_suspend_extension(struct em28
 {
 	const struct em28xx_ops *ops = NULL;
 
-	em28xx_info("Suspending extensions\n");
+	dev_info(&dev->intf->dev, "Suspending extensions\n");
 	mutex_lock(&em28xx_devlist_mutex);
 	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
 		if (ops->suspend)
@@ -1138,7 +1142,7 @@ int em28xx_resume_extension(struct em28x
 {
 	const struct em28xx_ops *ops = NULL;
 
-	em28xx_info("Resuming extensions\n");
+	dev_info(&dev->intf->dev, "Resuming extensions\n");
 	mutex_lock(&em28xx_devlist_mutex);
 	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
 		if (ops->resume)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-dvb.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-dvb.c	2016-12-11 17:47:46.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-dvb.c	2017-02-12 17:35:04.000000000 -0500
@@ -21,11 +21,12 @@
  the Free Software Foundation; either version 2 of the License.
  */
 
+#include "em28xx.h"
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 
-#include "em28xx.h"
 #include <media/v4l2-common.h>
 #include <dvb_demux.h>
 #include <dvb_net.h>
@@ -72,9 +73,10 @@ MODULE_PARM_DESC(debug, "enable debug me
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-#define dprintk(level, fmt, arg...) do {			\
-if (debug >= level)						\
-	printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg);	\
+#define dprintk(level, fmt, arg...) do {				\
+	if (debug >= level)						\
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "dvb: " fmt, ## arg);			\
 } while (0)
 
 struct em28xx_dvb {
@@ -196,6 +198,7 @@ static int em28xx_start_streaming(struct
 	int rc;
 	struct em28xx_i2c_bus *i2c_bus = dvb->adapter.priv;
 	struct em28xx *dev = i2c_bus->dev;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int dvb_max_packet_size, packet_multiplier, dvb_alt;
 
 	if (dev->dvb_xfer_bulk) {
@@ -214,7 +217,7 @@ static int em28xx_start_streaming(struct
 		dvb_alt = dev->dvb_alt_isoc;
 	}
 
-	usb_set_interface(dev->udev, dev->ifnum, dvb_alt);
+	usb_set_interface(udev, dev->ifnum, dvb_alt);
 	rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
 	if (rc < 0)
 		return rc;
@@ -734,13 +737,13 @@ static int em28xx_pctv_290e_set_lna(stru
 
 	ret = gpio_request_one(dvb->lna_gpio, flags, NULL);
 	if (ret)
-		em28xx_errdev("gpio request failed %d\n", ret);
+		dev_err(&dev->intf->dev, "gpio request failed %d\n", ret);
 	else
 		gpio_free(dvb->lna_gpio);
 
 	return ret;
 #else
-	dev_warn(&dev->udev->dev, "%s: LNA control is disabled (lna=%u)\n",
+	dev_warn(&dev->intf->dev, "%s: LNA control is disabled (lna=%u)\n",
 		 KBUILD_MODNAME, c->lna);
 	return 0;
 #endif
@@ -934,20 +937,20 @@ static int em28xx_attach_xc3028(u8 addr,
 	cfg.ctrl  = &ctl;
 
 	if (!dev->dvb->fe[0]) {
-		em28xx_errdev("/2: dvb frontend not attached. "
-				"Can't attach xc3028\n");
+		dev_err(&dev->intf->dev,
+			"dvb frontend not attached. Can't attach xc3028\n");
 		return -EINVAL;
 	}
 
 	fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg);
 	if (!fe) {
-		em28xx_errdev("/2: xc3028 attach failed\n");
+		dev_err(&dev->intf->dev, "xc3028 attach failed\n");
 		dvb_frontend_detach(dev->dvb->fe[0]);
 		dev->dvb->fe[0] = NULL;
 		return -EINVAL;
 	}
 
-	em28xx_info("%s/2: xc3028 attached\n", dev->name);
+	dev_info(&dev->intf->dev, "xc3028 attached\n");
 
 	return 0;
 }
@@ -963,11 +966,13 @@ static int em28xx_register_dvb(struct em
 	mutex_init(&dvb->lock);
 
 	/* register adapter */
-	result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
-				      adapter_nr);
+	result = dvb_register_adapter(&dvb->adapter,
+				      dev_name(&dev->intf->dev), module,
+				      device, adapter_nr);
 	if (result < 0) {
-		printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
-		       dev->name, result);
+		dev_warn(&dev->intf->dev,
+			 "dvb_register_adapter failed (errno = %d)\n",
+			 result);
 		goto fail_adapter;
 	}
 #ifdef CONFIG_MEDIA_CONTROLLER_DVB
@@ -984,8 +989,9 @@ static int em28xx_register_dvb(struct em
 	/* register frontend */
 	result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]);
 	if (result < 0) {
-		printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
-		       dev->name, result);
+		dev_warn(&dev->intf->dev,
+			 "dvb_register_frontend failed (errno = %d)\n",
+			 result);
 		goto fail_frontend0;
 	}
 
@@ -993,8 +999,9 @@ static int em28xx_register_dvb(struct em
 	if (dvb->fe[1]) {
 		result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
 		if (result < 0) {
-			printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n",
-			       dev->name, result);
+			dev_warn(&dev->intf->dev,
+				 "2nd dvb_register_frontend failed (errno = %d)\n",
+				 result);
 			goto fail_frontend1;
 		}
 	}
@@ -1011,8 +1018,9 @@ static int em28xx_register_dvb(struct em
 
 	result = dvb_dmx_init(&dvb->demux);
 	if (result < 0) {
-		printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
-		       dev->name, result);
+		dev_warn(&dev->intf->dev,
+			 "dvb_dmx_init failed (errno = %d)\n",
+			 result);
 		goto fail_dmx;
 	}
 
@@ -1021,31 +1029,35 @@ static int em28xx_register_dvb(struct em
 	dvb->dmxdev.capabilities = 0;
 	result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
 	if (result < 0) {
-		printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
-		       dev->name, result);
+		dev_warn(&dev->intf->dev,
+			 "dvb_dmxdev_init failed (errno = %d)\n",
+			 result);
 		goto fail_dmxdev;
 	}
 
 	dvb->fe_hw.source = DMX_FRONTEND_0;
 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 	if (result < 0) {
-		printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
-		       dev->name, result);
+		dev_warn(&dev->intf->dev,
+			 "add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+			 result);
 		goto fail_fe_hw;
 	}
 
 	dvb->fe_mem.source = DMX_MEMORY_FE;
 	result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
 	if (result < 0) {
-		printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
-		       dev->name, result);
+		dev_warn(&dev->intf->dev,
+			 "add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+			 result);
 		goto fail_fe_mem;
 	}
 
 	result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
 	if (result < 0) {
-		printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
-		       dev->name, result);
+		dev_warn(&dev->intf->dev,
+			 "connect_frontend failed (errno = %d)\n",
+			 result);
 		goto fail_fe_conn;
 	}
 
@@ -1117,13 +1129,12 @@ static int em28xx_dvb_init(struct em28xx
 		return 0;
 	}
 
-	em28xx_info("Binding DVB extension\n");
+	dev_info(&dev->intf->dev, "Binding DVB extension\n");
 
 	dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
-	if (dvb == NULL) {
-		em28xx_info("em28xx_dvb: memory allocation failed\n");
+	if (!dvb)
 		return -ENOMEM;
-	}
+
 	dev->dvb = dvb;
 	dvb->fe[0] = dvb->fe[1] = NULL;
 
@@ -1142,7 +1153,8 @@ static int em28xx_dvb_init(struct em28xx
 					   EM28XX_DVB_NUM_ISOC_PACKETS);
 	}
 	if (result) {
-		em28xx_errdev("em28xx_dvb: failed to pre-allocate USB transfer buffers for DVB.\n");
+		dev_err(&dev->intf->dev,
+			"failed to pre-allocate USB transfer buffers for DVB.\n");
 		kfree(dvb);
 		dev->dvb = NULL;
 		return result;
@@ -1259,7 +1271,8 @@ static int em28xx_dvb_init(struct em28xx
 	case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
 	case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
 		dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
-					   &dev->i2c_adap[dev->def_i2c_bus], &dev->udev->dev);
+					&dev->i2c_adap[dev->def_i2c_bus],
+					&dev->intf->dev);
 		if (em28xx_attach_xc3028(0x61, dev) < 0) {
 			result = -EINVAL;
 			goto out_free;
@@ -1321,8 +1334,9 @@ static int em28xx_dvb_init(struct em28xx
 			result = gpio_request_one(dvb->lna_gpio,
 						  GPIOF_OUT_INIT_LOW, NULL);
 			if (result)
-				em28xx_errdev("gpio request failed %d\n",
-					      result);
+				dev_err(&dev->intf->dev,
+					"gpio request failed %d\n",
+					result);
 			else
 				gpio_free(dvb->lna_gpio);
 
@@ -1937,12 +1951,12 @@ static int em28xx_dvb_init(struct em28xx
 		}
 		break;
 	default:
-		em28xx_errdev("/2: The frontend of your DVB/ATSC card"
-				" isn't supported yet\n");
+		dev_err(&dev->intf->dev,
+			"The frontend of your DVB/ATSC card isn't supported yet\n");
 		break;
 	}
 	if (NULL == dvb->fe[0]) {
-		em28xx_errdev("/2: frontend initialization failed\n");
+		dev_err(&dev->intf->dev, "frontend initialization failed\n");
 		result = -EINVAL;
 		goto out_free;
 	}
@@ -1952,12 +1966,12 @@ static int em28xx_dvb_init(struct em28xx
 		dvb->fe[1]->callback = em28xx_tuner_callback;
 
 	/* register everything */
-	result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+	result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->intf->dev);
 
 	if (result < 0)
 		goto out_free;
 
-	em28xx_info("DVB extension successfully initialized\n");
+	dev_info(&dev->intf->dev, "DVB extension successfully initialized\n");
 
 	kref_get(&dev->ref);
 
@@ -1997,7 +2011,7 @@ static int em28xx_dvb_fini(struct em28xx
 	if (!dev->dvb)
 		return 0;
 
-	em28xx_info("Closing DVB extension\n");
+	dev_info(&dev->intf->dev, "Closing DVB extension\n");
 
 	dvb = dev->dvb;
 
@@ -2055,17 +2069,17 @@ static int em28xx_dvb_suspend(struct em2
 	if (!dev->board.has_dvb)
 		return 0;
 
-	em28xx_info("Suspending DVB extension\n");
+	dev_info(&dev->intf->dev, "Suspending DVB extension\n");
 	if (dev->dvb) {
 		struct em28xx_dvb *dvb = dev->dvb;
 
 		if (dvb->fe[0]) {
 			ret = dvb_frontend_suspend(dvb->fe[0]);
-			em28xx_info("fe0 suspend %d\n", ret);
+			dev_info(&dev->intf->dev, "fe0 suspend %d\n", ret);
 		}
 		if (dvb->fe[1]) {
 			dvb_frontend_suspend(dvb->fe[1]);
-			em28xx_info("fe1 suspend %d\n", ret);
+			dev_info(&dev->intf->dev, "fe1 suspend %d\n", ret);
 		}
 	}
 
@@ -2082,18 +2096,18 @@ static int em28xx_dvb_resume(struct em28
 	if (!dev->board.has_dvb)
 		return 0;
 
-	em28xx_info("Resuming DVB extension\n");
+	dev_info(&dev->intf->dev, "Resuming DVB extension\n");
 	if (dev->dvb) {
 		struct em28xx_dvb *dvb = dev->dvb;
 
 		if (dvb->fe[0]) {
 			ret = dvb_frontend_resume(dvb->fe[0]);
-			em28xx_info("fe0 resume %d\n", ret);
+			dev_info(&dev->intf->dev, "fe0 resume %d\n", ret);
 		}
 
 		if (dvb->fe[1]) {
 			ret = dvb_frontend_resume(dvb->fe[1]);
-			em28xx_info("fe1 resume %d\n", ret);
+			dev_info(&dev->intf->dev, "fe1 resume %d\n", ret);
 		}
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx.h linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx.h
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx.h	2017-02-12 16:03:20.000000000 -0500
@@ -610,7 +610,6 @@ struct em28xx {
 	struct em28xx_IR *ir;
 
 	/* 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 em28xx_chip_id chip_id;
@@ -678,7 +677,7 @@ struct em28xx {
 	spinlock_t slock;
 
 	/* usb transfer */
-	struct usb_device *udev;	/* the usb device */
+	struct usb_interface *intf;	/* the usb interface */
 	u8 ifnum;		/* number of the assigned usb interface */
 	u8 analog_ep_isoc;	/* address of isoc endpoint for analog */
 	u8 analog_ep_bulk;	/* address of bulk endpoint for analog */
@@ -797,20 +796,4 @@ void em28xx_free_device(struct kref *ref
 int em28xx_detect_sensor(struct em28xx *dev);
 int em28xx_init_camera(struct em28xx *dev);
 
-/* printk macros */
-
-#define em28xx_err(fmt, arg...) do {\
-	printk(KERN_ERR fmt , ##arg); } while (0)
-
-#define em28xx_errdev(fmt, arg...) do {\
-	printk(KERN_ERR "%s: "fmt,\
-			dev->name , ##arg); } while (0)
-
-#define em28xx_info(fmt, arg...) do {\
-	printk(KERN_INFO "%s: "fmt,\
-			dev->name , ##arg); } while (0)
-#define em28xx_warn(fmt, arg...) do {\
-	printk(KERN_WARNING "%s: "fmt,\
-			dev->name , ##arg); } while (0)
-
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-i2c.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,13 +22,14 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "em28xx.h"
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/usb.h>
 #include <linux/i2c.h>
 #include <linux/jiffies.h>
 
-#include "em28xx.h"
 #include "tuner-xc2028.h"
 #include <media/v4l2-common.h>
 #include <media/tuner.h>
@@ -43,6 +44,13 @@ static unsigned int i2c_debug;
 module_param(i2c_debug, int, 0644);
 MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I2C transfers)");
 
+#define dprintk(level, fmt, arg...) do {				\
+	if (i2c_debug > level)						\
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "i2c: %s: " fmt, __func__, ## arg);		\
+} while (0)
+
+
 /*
  * em2800_i2c_send_bytes()
  * send up to 4 bytes to the em2800 i2c device
@@ -70,7 +78,8 @@ static int em2800_i2c_send_bytes(struct
 	/* trigger write */
 	ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
 	if (ret != 2 + len) {
-		em28xx_warn("failed to trigger write to i2c address 0x%x (error=%i)\n",
+		dev_warn(&dev->intf->dev,
+			 "failed to trigger write to i2c address 0x%x (error=%i)\n",
 			    addr, ret);
 		return (ret < 0) ? ret : -EIO;
 	}
@@ -80,20 +89,18 @@ static int em2800_i2c_send_bytes(struct
 		if (ret == 0x80 + len - 1)
 			return len;
 		if (ret == 0x94 + len - 1) {
-			if (i2c_debug == 1)
-				em28xx_warn("R05 returned 0x%02x: I2C ACK error\n",
-					    ret);
+			dprintk(1, "R05 returned 0x%02x: I2C ACK error\n", ret);
 			return -ENXIO;
 		}
 		if (ret < 0) {
-			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
-				    ret);
+			dev_warn(&dev->intf->dev,
+				 "failed to get i2c transfer status from bridge register (error=%i)\n",
+				ret);
 			return ret;
 		}
 		msleep(5);
 	}
-	if (i2c_debug)
-		em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
+	dprintk(0, "write to i2c device at 0x%x timed out\n", addr);
 	return -ETIMEDOUT;
 }
 
@@ -116,8 +123,9 @@ static int em2800_i2c_recv_bytes(struct
 	buf2[0] = addr;
 	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
 	if (ret != 2) {
-		em28xx_warn("failed to trigger read from i2c address 0x%x (error=%i)\n",
-			    addr, ret);
+		dev_warn(&dev->intf->dev,
+			 "failed to trigger read from i2c address 0x%x (error=%i)\n",
+			 addr, ret);
 		return (ret < 0) ? ret : -EIO;
 	}
 
@@ -127,29 +135,28 @@ static int em2800_i2c_recv_bytes(struct
 		if (ret == 0x84 + len - 1)
 			break;
 		if (ret == 0x94 + len - 1) {
-			if (i2c_debug == 1)
-				em28xx_warn("R05 returned 0x%02x: I2C ACK error\n",
-					    ret);
+			dprintk(1, "R05 returned 0x%02x: I2C ACK error\n",
+				ret);
 			return -ENXIO;
 		}
 		if (ret < 0) {
-			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
-				    ret);
+			dev_warn(&dev->intf->dev,
+				 "failed to get i2c transfer status from bridge register (error=%i)\n",
+				 ret);
 			return ret;
 		}
 		msleep(5);
 	}
 	if (ret != 0x84 + len - 1) {
-		if (i2c_debug)
-			em28xx_warn("read from i2c device at 0x%x timed out\n",
-				    addr);
+		dprintk(0, "read from i2c device at 0x%x timed out\n", addr);
 	}
 
 	/* get the received message */
 	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
 	if (ret != len) {
-		em28xx_warn("reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
-			    addr, ret);
+		dev_warn(&dev->intf->dev,
+			 "reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
+			 addr, ret);
 		return (ret < 0) ? ret : -EIO;
 	}
 	for (i = 0; i < len; i++)
@@ -193,12 +200,14 @@ static int em28xx_i2c_send_bytes(struct
 	ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
 	if (ret != len) {
 		if (ret < 0) {
-			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
-				    addr, ret);
+			dev_warn(&dev->intf->dev,
+				 "writing to i2c device at 0x%x failed (error=%i)\n",
+				 addr, ret);
 			return ret;
 		} else {
-			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
-				    len, addr, ret);
+			dev_warn(&dev->intf->dev,
+				 "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
+				 len, addr, ret);
 			return -EIO;
 		}
 	}
@@ -209,14 +218,14 @@ static int em28xx_i2c_send_bytes(struct
 		if (ret == 0) /* success */
 			return len;
 		if (ret == 0x10) {
-			if (i2c_debug == 1)
-				em28xx_warn("I2C ACK error on writing to addr 0x%02x\n",
-					    addr);
+			dprintk(1, "I2C ACK error on writing to addr 0x%02x\n",
+				addr);
 			return -ENXIO;
 		}
 		if (ret < 0) {
-			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
-				    ret);
+			dev_warn(&dev->intf->dev,
+				 "failed to get i2c transfer status from bridge register (error=%i)\n",
+				 ret);
 			return ret;
 		}
 		msleep(5);
@@ -229,14 +238,15 @@ static int em28xx_i2c_send_bytes(struct
 
 	if (ret == 0x02 || ret == 0x04) {
 		/* NOTE: these errors seem to be related to clock stretching */
-		if (i2c_debug)
-			em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n",
-				    addr, ret);
+		dprintk(0,
+			"write to i2c device at 0x%x timed out (status=%i)\n",
+			addr, ret);
 		return -ETIMEDOUT;
 	}
 
-	em28xx_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n",
-		    addr, ret);
+	dev_warn(&dev->intf->dev,
+		 "write to i2c device at 0x%x failed with unknown error (status=%i)\n",
+		 addr, ret);
 	return -EIO;
 }
 
@@ -258,8 +268,9 @@ static int em28xx_i2c_recv_bytes(struct
 	/* Read data from i2c device */
 	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
 	if (ret < 0) {
-		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
-			    addr, ret);
+		dev_warn(&dev->intf->dev,
+			 "reading from i2c device at 0x%x failed (error=%i)\n",
+			 addr, ret);
 		return ret;
 	}
 	/*
@@ -276,27 +287,28 @@ static int em28xx_i2c_recv_bytes(struct
 	if (ret == 0) /* success */
 		return len;
 	if (ret < 0) {
-		em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
-			    ret);
+		dev_warn(&dev->intf->dev,
+			 "failed to get i2c transfer status from bridge register (error=%i)\n",
+			 ret);
 		return ret;
 	}
 	if (ret == 0x10) {
-		if (i2c_debug == 1)
-			em28xx_warn("I2C ACK error on writing to addr 0x%02x\n",
-				    addr);
+		dprintk(1, "I2C ACK error on writing to addr 0x%02x\n",
+			addr);
 		return -ENXIO;
 	}
 
 	if (ret == 0x02 || ret == 0x04) {
 		/* NOTE: these errors seem to be related to clock stretching */
-		if (i2c_debug)
-			em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n",
-				    addr, ret);
+		dprintk(0,
+			"write to i2c device at 0x%x timed out (status=%i)\n",
+			addr, ret);
 		return -ETIMEDOUT;
 	}
 
-	em28xx_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n",
-		    addr, ret);
+	dev_warn(&dev->intf->dev,
+		 "write to i2c device at 0x%x failed with unknown error (status=%i)\n",
+		 addr, ret);
 	return -EIO;
 }
 
@@ -335,12 +347,14 @@ static int em25xx_bus_B_send_bytes(struc
 	ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len);
 	if (ret != len) {
 		if (ret < 0) {
-			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
-				    addr, ret);
+			dev_warn(&dev->intf->dev,
+				 "writing to i2c device at 0x%x failed (error=%i)\n",
+				 addr, ret);
 			return ret;
 		} else {
-			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
-				    len, addr, ret);
+			dev_warn(&dev->intf->dev,
+				 "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
+				 len, addr, ret);
 			return -EIO;
 		}
 	}
@@ -353,9 +367,7 @@ static int em25xx_bus_B_send_bytes(struc
 	if (!ret)
 		return len;
 	else if (ret > 0) {
-		if (i2c_debug == 1)
-			em28xx_warn("Bus B R08 returned 0x%02x: I2C ACK error\n",
-				    ret);
+		dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret);
 		return -ENXIO;
 	}
 
@@ -386,8 +398,9 @@ static int em25xx_bus_B_recv_bytes(struc
 	/* Read value */
 	ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len);
 	if (ret < 0) {
-		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
-			    addr, ret);
+		dev_warn(&dev->intf->dev,
+			 "reading from i2c device at 0x%x failed (error=%i)\n",
+			 addr, ret);
 		return ret;
 	}
 	/*
@@ -408,9 +421,7 @@ static int em25xx_bus_B_recv_bytes(struc
 	if (!ret)
 		return len;
 	else if (ret > 0) {
-		if (i2c_debug == 1)
-			em28xx_warn("Bus B R08 returned 0x%02x: I2C ACK error\n",
-				    ret);
+		dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret);
 		return -ENXIO;
 	}
 
@@ -528,57 +539,46 @@ static int em28xx_i2c_xfer(struct i2c_ad
 	}
 	for (i = 0; i < num; i++) {
 		addr = msgs[i].addr << 1;
-		if (i2c_debug > 1)
-			printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:",
-			       dev->name, __func__ ,
-			       (msgs[i].flags & I2C_M_RD) ? "read" : "write",
-			       i == num - 1 ? "stop" : "nonstop",
-			       addr, msgs[i].len);
 		if (!msgs[i].len) {
 			/*
 			 * no len: check only for device presence
 			 * This code is only called during device probe.
 			 */
 			rc = i2c_check_for_device(i2c_bus, addr);
-			if (rc < 0) {
-				if (rc == -ENXIO) {
-					if (i2c_debug > 1)
-						printk(KERN_CONT " no device\n");
-					rc = -ENODEV;
-				} else {
-					if (i2c_debug > 1)
-						printk(KERN_CONT " ERROR: %i\n", rc);
-				}
-				rt_mutex_unlock(&dev->i2c_bus_lock);
-				return rc;
-			}
+
+			if (rc == -ENXIO)
+				rc = -ENODEV;
 		} else if (msgs[i].flags & I2C_M_RD) {
 			/* read bytes */
 			rc = i2c_recv_bytes(i2c_bus, msgs[i]);
-
-			if (i2c_debug > 1 && rc >= 0)
-				printk(KERN_CONT " %*ph",
-				       msgs[i].len, msgs[i].buf);
 		} else {
-			if (i2c_debug > 1)
-				printk(KERN_CONT " %*ph",
-				       msgs[i].len, msgs[i].buf);
-
 			/* write bytes */
 			rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1);
 		}
-		if (rc < 0) {
-			if (i2c_debug > 1)
-				printk(KERN_CONT " ERROR: %i\n", rc);
-			rt_mutex_unlock(&dev->i2c_bus_lock);
-			return rc;
-		}
-		if (i2c_debug > 1)
-			printk(KERN_CONT "\n");
+
+		if (rc < 0)
+			goto error;
+
+		dprintk(2, "%s %s addr=%02x len=%d: %*ph\n",
+			(msgs[i].flags & I2C_M_RD) ? "read" : "write",
+			i == num - 1 ? "stop" : "nonstop",
+			addr, msgs[i].len,
+			msgs[i].len, msgs[i].buf);
 	}
 
 	rt_mutex_unlock(&dev->i2c_bus_lock);
 	return num;
+
+error:
+	dprintk(2, "%s %s addr=%02x len=%d: %sERROR: %i\n",
+		(msgs[i].flags & I2C_M_RD) ? "read" : "write",
+		i == num - 1 ? "stop" : "nonstop",
+		addr, msgs[i].len,
+		(rc == -ENODEV) ? "no device " : "",
+		rc);
+
+	rt_mutex_unlock(&dev->i2c_bus_lock);
+	return rc;
 }
 
 /*
@@ -672,7 +672,7 @@ static int em28xx_i2c_eeprom(struct em28
 	/* Check if board has eeprom */
 	err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
 	if (err < 0) {
-		em28xx_info("board has no eeprom\n");
+		dev_info(&dev->intf->dev, "board has no eeprom\n");
 		return -ENODEV;
 	}
 
@@ -685,17 +685,19 @@ static int em28xx_i2c_eeprom(struct em28
 				    dev->eeprom_addrwidth_16bit,
 				    len, data);
 	if (err != len) {
-		em28xx_errdev("failed to read eeprom (err=%d)\n", err);
+		dev_err(&dev->intf->dev,
+			"failed to read eeprom (err=%d)\n", err);
 		goto error;
 	}
 
 	if (i2c_debug) {
 		/* Display eeprom content */
-		print_hex_dump(KERN_INFO, "eeprom ", DUMP_PREFIX_OFFSET,
+		print_hex_dump(KERN_DEBUG, "em28xx eeprom ", DUMP_PREFIX_OFFSET,
 			       16, 1, data, len, true);
 
 		if (dev->eeprom_addrwidth_16bit)
-			em28xx_info("eeprom %06x: ... (skipped)\n", 256);
+			dev_info(&dev->intf->dev,
+				 "eeprom %06x: ... (skipped)\n", 256);
 	}
 
 	if (dev->eeprom_addrwidth_16bit &&
@@ -707,11 +709,14 @@ static int em28xx_i2c_eeprom(struct em28
 		dev->hash = em28xx_hash_mem(data, len, 32);
 		mc_start = (data[1] << 8) + 4;	/* usually 0x0004 */
 
-		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
-			    data[0], data[1], data[2], data[3], dev->hash);
-		em28xx_info("EEPROM info:\n");
-		em28xx_info("\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
-			    mc_start, data[2]);
+		dev_info(&dev->intf->dev,
+			 "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
+			 data[0], data[1], data[2], data[3], dev->hash);
+		dev_info(&dev->intf->dev,
+			 "EEPROM info:\n");
+		dev_info(&dev->intf->dev,
+			 "\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
+			 mc_start, data[2]);
 		/*
 		 * boot configuration (address 0x0002):
 		 * [0]   microcode download speed: 1 = 400 kHz; 0 = 100 kHz
@@ -729,8 +734,9 @@ static int em28xx_i2c_eeprom(struct em28
 		err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2,
 					    data);
 		if (err != 2) {
-			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
-				      err);
+			dev_err(&dev->intf->dev,
+				"failed to read hardware configuration data from eeprom (err=%d)\n",
+				err);
 			goto error;
 		}
 
@@ -747,8 +753,9 @@ static int em28xx_i2c_eeprom(struct em28
 		err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len,
 					    data);
 		if (err != len) {
-			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
-				      err);
+			dev_err(&dev->intf->dev,
+				"failed to read hardware configuration data from eeprom (err=%d)\n",
+				err);
 			goto error;
 		}
 
@@ -756,7 +763,8 @@ static int em28xx_i2c_eeprom(struct em28
 		/* NOTE: not all devices provide this type of dataset */
 		if (data[0] != 0x1a || data[1] != 0xeb ||
 		    data[2] != 0x67 || data[3] != 0x95) {
-			em28xx_info("\tno hardware configuration dataset found in eeprom\n");
+			dev_info(&dev->intf->dev,
+				 "\tno hardware configuration dataset found in eeprom\n");
 			kfree(data);
 			return 0;
 		}
@@ -767,11 +775,14 @@ static int em28xx_i2c_eeprom(struct em28
 		   data[0] == 0x1a && data[1] == 0xeb &&
 		   data[2] == 0x67 && data[3] == 0x95) {
 		dev->hash = em28xx_hash_mem(data, len, 32);
-		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
-			    data[0], data[1], data[2], data[3], dev->hash);
-		em28xx_info("EEPROM info:\n");
+		dev_info(&dev->intf->dev,
+			 "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
+			 data[0], data[1], data[2], data[3], dev->hash);
+		dev_info(&dev->intf->dev,
+			 "EEPROM info:\n");
 	} else {
-		em28xx_info("unknown eeprom format or eeprom corrupted !\n");
+		dev_info(&dev->intf->dev,
+			 "unknown eeprom format or eeprom corrupted !\n");
 		err = -ENODEV;
 		goto error;
 	}
@@ -782,50 +793,55 @@ static int em28xx_i2c_eeprom(struct em28
 
 	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
 	case 0:
-		em28xx_info("\tNo audio on board.\n");
+		dev_info(&dev->intf->dev, "\tNo audio on board.\n");
 		break;
 	case 1:
-		em28xx_info("\tAC97 audio (5 sample rates)\n");
+		dev_info(&dev->intf->dev, "\tAC97 audio (5 sample rates)\n");
 		break;
 	case 2:
 		if (dev->chip_id < CHIP_ID_EM2860)
-			em28xx_info("\tI2S audio, sample rate=32k\n");
+			dev_info(&dev->intf->dev,
+				 "\tI2S audio, sample rate=32k\n");
 		else
-			em28xx_info("\tI2S audio, 3 sample rates\n");
+			dev_info(&dev->intf->dev,
+				 "\tI2S audio, 3 sample rates\n");
 		break;
 	case 3:
 		if (dev->chip_id < CHIP_ID_EM2860)
-			em28xx_info("\tI2S audio, 3 sample rates\n");
+			dev_info(&dev->intf->dev,
+				 "\tI2S audio, 3 sample rates\n");
 		else
-			em28xx_info("\tI2S audio, 5 sample rates\n");
+			dev_info(&dev->intf->dev,
+				 "\tI2S audio, 5 sample rates\n");
 		break;
 	}
 
 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 3)
-		em28xx_info("\tUSB Remote wakeup capable\n");
+		dev_info(&dev->intf->dev, "\tUSB Remote wakeup capable\n");
 
 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 2)
-		em28xx_info("\tUSB Self power capable\n");
+		dev_info(&dev->intf->dev, "\tUSB Self power capable\n");
 
 	switch (le16_to_cpu(dev_config->chip_conf) & 0x3) {
 	case 0:
-		em28xx_info("\t500mA max power\n");
+		dev_info(&dev->intf->dev, "\t500mA max power\n");
 		break;
 	case 1:
-		em28xx_info("\t400mA max power\n");
+		dev_info(&dev->intf->dev, "\t400mA max power\n");
 		break;
 	case 2:
-		em28xx_info("\t300mA max power\n");
+		dev_info(&dev->intf->dev, "\t300mA max power\n");
 		break;
 	case 3:
-		em28xx_info("\t200mA max power\n");
+		dev_info(&dev->intf->dev, "\t200mA max power\n");
 		break;
 	}
-	em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
-		    dev_config->string_idx_table,
-		    le16_to_cpu(dev_config->string1),
-		    le16_to_cpu(dev_config->string2),
-		    le16_to_cpu(dev_config->string3));
+	dev_info(&dev->intf->dev,
+		 "\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
+		 dev_config->string_idx_table,
+		 le16_to_cpu(dev_config->string1),
+		 le16_to_cpu(dev_config->string2),
+		 le16_to_cpu(dev_config->string3));
 
 	return 0;
 
@@ -914,8 +930,9 @@ void em28xx_do_i2c_scan(struct em28xx *d
 		if (rc < 0)
 			continue;
 		i2c_devicelist[i] = i;
-		em28xx_info("found i2c device @ 0x%x on bus %d [%s]\n",
-			    i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
+		dev_info(&dev->intf->dev,
+			 "found i2c device @ 0x%x on bus %d [%s]\n",
+			 i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
 	}
 
 	if (bus == dev->def_i2c_bus)
@@ -939,8 +956,8 @@ int em28xx_i2c_register(struct em28xx *d
 		return -ENODEV;
 
 	dev->i2c_adap[bus] = em28xx_adap_template;
-	dev->i2c_adap[bus].dev.parent = &dev->udev->dev;
-	strcpy(dev->i2c_adap[bus].name, dev->name);
+	dev->i2c_adap[bus].dev.parent = &dev->intf->dev;
+	strcpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev));
 
 	dev->i2c_bus[bus].bus = bus;
 	dev->i2c_bus[bus].algo_type = algo_type;
@@ -949,8 +966,9 @@ int em28xx_i2c_register(struct em28xx *d
 
 	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
 	if (retval < 0) {
-		em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
-			      __func__, retval);
+		dev_err(&dev->intf->dev,
+			"%s: i2c_add_adapter failed! retval [%d]\n",
+			__func__, retval);
 		return retval;
 	}
 
@@ -961,8 +979,9 @@ int em28xx_i2c_register(struct em28xx *d
 	if (!bus) {
 		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
 		if ((retval < 0) && (retval != -ENODEV)) {
-			em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
-				      __func__, retval);
+			dev_err(&dev->intf->dev,
+				"%s: em28xx_i2_eeprom failed! retval [%d]\n",
+				__func__, retval);
 
 			return retval;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-input.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-input.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-input.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-input.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
+#include "em28xx.h"
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -29,8 +31,6 @@
 #include <linux/slab.h>
 #include <linux/bitrev.h>
 
-#include "em28xx.h"
-
 #define EM28XX_SNAPSHOT_KEY				KEY_CAMERA
 #define EM28XX_BUTTONS_DEBOUNCED_QUERY_INTERVAL		500 /* [ms] */
 #define EM28XX_BUTTONS_VOLATILE_QUERY_INTERVAL		100 /* [ms] */
@@ -41,10 +41,11 @@ MODULE_PARM_DESC(ir_debug, "enable debug
 
 #define MODULE_NAME "em28xx"
 
-#define dprintk(fmt, arg...) \
-	if (ir_debug) { \
-		printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
-	}
+#define dprintk( fmt, arg...) do {					\
+	if (ir_debug)							\
+		dev_printk(KERN_DEBUG, &ir->dev->intf->dev,		\
+			   "input: %s: " fmt, __func__, ## arg);	\
+} while (0)
 
 /**********************************************************
  Polling structure used by em28xx IR's
@@ -458,8 +459,9 @@ static int em28xx_ir_change_protocol(str
 	case CHIP_ID_EM28178:
 		return em2874_ir_change_protocol(rc_dev, rc_type);
 	default:
-		printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
-		       dev->chip_id);
+		dev_err(&ir->dev->intf->dev,
+			"Unrecognized em28xx chip id 0x%02x: IR not supported\n",
+			dev->chip_id);
 		return -EINVAL;
 	}
 }
@@ -564,15 +566,16 @@ static void em28xx_query_buttons(struct
 
 static int em28xx_register_snapshot_button(struct em28xx *dev)
 {
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	struct input_dev *input_dev;
 	int err;
 
-	em28xx_info("Registering snapshot button...\n");
+	dev_info(&dev->intf->dev, "Registering snapshot button...\n");
 	input_dev = input_allocate_device();
 	if (!input_dev)
 		return -ENOMEM;
 
-	usb_make_path(dev->udev, dev->snapshot_button_path,
+	usb_make_path(udev, dev->snapshot_button_path,
 		      sizeof(dev->snapshot_button_path));
 	strlcat(dev->snapshot_button_path, "/sbutton",
 		sizeof(dev->snapshot_button_path));
@@ -584,14 +587,14 @@ static int em28xx_register_snapshot_butt
 	input_dev->keycodesize = 0;
 	input_dev->keycodemax = 0;
 	input_dev->id.bustype = BUS_USB;
-	input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-	input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+	input_dev->id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+	input_dev->id.product = le16_to_cpu(udev->descriptor.idProduct);
 	input_dev->id.version = 1;
-	input_dev->dev.parent = &dev->udev->dev;
+	input_dev->dev.parent = &dev->intf->dev;
 
 	err = input_register_device(input_dev);
 	if (err) {
-		em28xx_errdev("input_register_device failed\n");
+		dev_err(&dev->intf->dev, "input_register_device failed\n");
 		input_free_device(input_dev);
 		return err;
 	}
@@ -631,7 +634,8 @@ static void em28xx_init_buttons(struct e
 		} else if (button->role == EM28XX_BUTTON_ILLUMINATION) {
 			/* Check sanity */
 			if (!em28xx_find_led(dev, EM28XX_LED_ILLUMINATION)) {
-				em28xx_errdev("BUG: illumination button defined, but no illumination LED.\n");
+				dev_err(&dev->intf->dev,
+					"BUG: illumination button defined, but no illumination LED.\n");
 				goto next_button;
 			}
 		}
@@ -667,7 +671,7 @@ static void em28xx_shutdown_buttons(stru
 	dev->num_button_polling_addresses = 0;
 	/* Deregister input devices */
 	if (dev->sbutton_input_dev != NULL) {
-		em28xx_info("Deregistering snapshot button\n");
+		dev_info(&dev->intf->dev, "Deregistering snapshot button\n");
 		input_unregister_device(dev->sbutton_input_dev);
 		dev->sbutton_input_dev = NULL;
 	}
@@ -675,6 +679,7 @@ static void em28xx_shutdown_buttons(stru
 
 static int em28xx_ir_init(struct em28xx *dev)
 {
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	struct em28xx_IR *ir;
 	struct rc_dev *rc;
 	int err = -ENOMEM;
@@ -696,19 +701,20 @@ static int em28xx_ir_init(struct em28xx
 		i2c_rc_dev_addr = em28xx_probe_i2c_ir(dev);
 		if (!i2c_rc_dev_addr) {
 			dev->board.has_ir_i2c = 0;
-			em28xx_warn("No i2c IR remote control device found.\n");
+			dev_warn(&dev->intf->dev,
+				 "No i2c IR remote control device found.\n");
 			return -ENODEV;
 		}
 	}
 
 	if (dev->board.ir_codes == NULL && !dev->board.has_ir_i2c) {
 		/* No remote control support */
-		em28xx_warn("Remote control support is not available for "
-				"this card.\n");
+		dev_warn(&dev->intf->dev,
+			 "Remote control support is not available for this card.\n");
 		return 0;
 	}
 
-	em28xx_info("Registering input extension\n");
+	dev_info(&dev->intf->dev, "Registering input extension\n");
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
 	if (!ir)
@@ -792,18 +798,19 @@ static int em28xx_ir_init(struct em28xx
 	ir->polling = 100; /* ms */
 
 	/* init input device */
-	snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)", dev->name);
+	snprintf(ir->name, sizeof(ir->name), "%s IR",
+		 dev_name(&dev->intf->dev));
 
-	usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
+	usb_make_path(udev, ir->phys, sizeof(ir->phys));
 	strlcat(ir->phys, "/input0", sizeof(ir->phys));
 
 	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->dev.parent = &dev->udev->dev;
+	rc->input_id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+	rc->input_id.product = le16_to_cpu(udev->descriptor.idProduct);
+	rc->dev.parent = &dev->intf->dev;
 	rc->driver_name = MODULE_NAME;
 
 	/* all done */
@@ -811,7 +818,7 @@ static int em28xx_ir_init(struct em28xx
 	if (err)
 		goto error;
 
-	em28xx_info("Input extension successfully initalized\n");
+	dev_info(&dev->intf->dev, "Input extension successfully initalized\n");
 
 	return 0;
 
@@ -832,7 +839,7 @@ static int em28xx_ir_fini(struct em28xx
 		return 0;
 	}
 
-	em28xx_info("Closing input extension\n");
+	dev_info(&dev->intf->dev, "Closing input extension\n");
 
 	em28xx_shutdown_buttons(dev);
 
@@ -861,7 +868,7 @@ static int em28xx_ir_suspend(struct em28
 	if (dev->is_audio_only)
 		return 0;
 
-	em28xx_info("Suspending input extension\n");
+	dev_info(&dev->intf->dev, "Suspending input extension\n");
 	if (ir)
 		cancel_delayed_work_sync(&ir->work);
 	cancel_delayed_work_sync(&dev->buttons_query_work);
@@ -878,7 +885,7 @@ static int em28xx_ir_resume(struct em28x
 	if (dev->is_audio_only)
 		return 0;
 
-	em28xx_info("Resuming input extension\n");
+	dev_info(&dev->intf->dev, "Resuming input extension\n");
 	/* if suspend calls ir_raw_event_unregister(), the should call
 	   ir_raw_event_register() */
 	if (ir)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-vbi.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-vbi.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-vbi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-vbi.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,12 +21,14 @@
    02110-1301, USA.
  */
 
+#include "em28xx.h"
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/hardirq.h>
 #include <linux/init.h>
+#include <linux/usb.h>
 
-#include "em28xx.h"
 #include "em28xx-v4l.h"
 
 /* ------------------------------------------------------------------ */
@@ -63,8 +65,9 @@ static int vbi_buffer_prepare(struct vb2
 	size = v4l2->vbi_width * v4l2->vbi_height * 2;
 
 	if (vb2_plane_size(vb, 0) < size) {
-		printk(KERN_INFO "%s data will not fit into plane (%lu < %lu)\n",
-		       __func__, vb2_plane_size(vb, 0), size);
+		dev_info(&dev->intf->dev,
+			 "%s data will not fit into plane (%lu < %lu)\n",
+			 __func__, vb2_plane_size(vb, 0), size);
 		return -EINVAL;
 	}
 	vb2_set_plane_payload(vb, 0, size);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-video.c linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-video.c
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/em28xx-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/em28xx-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,6 +26,8 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "em28xx.h"
+
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -37,7 +39,6 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 
-#include "em28xx.h"
 #include "em28xx-v4l.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
@@ -63,18 +64,17 @@ static int alt;
 module_param(alt, int, 0644);
 MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
 
-#define em28xx_videodbg(fmt, arg...) do {\
-	if (video_debug) \
-		printk(KERN_INFO "%s %s :"fmt, \
-			 dev->name, __func__ , ##arg); } while (0)
+#define em28xx_videodbg(fmt, arg...) do {				\
+	if (video_debug)						\
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "video: %s: " fmt, __func__, ## arg);	\
+} while (0)
 
-#define em28xx_isocdbg(fmt, arg...) \
-do {\
-	if (isoc_debug) { \
-		printk(KERN_INFO "%s %s :"fmt, \
-			 dev->name, __func__ , ##arg); \
-	} \
-  } while (0)
+#define em28xx_isocdbg(fmt, arg...) do {\
+	if (isoc_debug) \
+		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
+			   "isoc: %s: " fmt, __func__, ## arg);		\
+} while (0)
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC " - v4l2 interface");
@@ -360,6 +360,7 @@ static int em28xx_resolution_set(struct
 static int em28xx_set_alternate(struct em28xx *dev)
 {
 	struct em28xx_v4l2 *v4l2 = dev->v4l2;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int errCode;
 	int i;
 	unsigned int min_pkt_size = v4l2->width * 2 + 4;
@@ -411,10 +412,11 @@ set_alt:
 	}
 	em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
 			dev->alt, dev->max_pkt_size);
-	errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
+	errCode = usb_set_interface(udev, dev->ifnum, dev->alt);
 	if (errCode < 0) {
-		em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
-			      dev->alt, errCode);
+		dev_err(&dev->intf->dev,
+			"cannot change alternate number to %d (error=%i)\n",
+			dev->alt, errCode);
 		return errCode;
 	}
 	return 0;
@@ -505,8 +507,7 @@ static void em28xx_copy_video(struct em2
 
 		if ((char *)startwrite + lencopy > (char *)buf->vb_buf +
 		    buf->length) {
-			em28xx_isocdbg("Overflow of %zu bytes past buffer end"
-				       "(2)\n",
+			em28xx_isocdbg("Overflow of %zu bytes past buffer end(2)\n",
 				       ((char *)startwrite + lencopy) -
 				       ((char *)buf->vb_buf + buf->length));
 			lencopy = remain = (char *)buf->vb_buf + buf->length -
@@ -926,10 +927,11 @@ static int em28xx_enable_analog_tuner(st
 
 		ret = media_entity_setup_link(link, flags);
 		if (ret) {
-			pr_err("Couldn't change link %s->%s to %s. Error %d\n",
-			       source->name, sink->name,
-			       flags ? "enabled" : "disabled",
-			       ret);
+			dev_err(&dev->intf->dev,
+				"Couldn't change link %s->%s to %s. Error %d\n",
+				source->name, sink->name,
+				flags ? "enabled" : "disabled",
+				ret);
 			return ret;
 		} else
 			em28xx_videodbg("link %s->%s was %s\n",
@@ -957,14 +959,16 @@ static void em28xx_v4l2_create_entities(
 	v4l2->video_pad.flags = MEDIA_PAD_FL_SINK;
 	ret = media_entity_pads_init(&v4l2->vdev.entity, 1, &v4l2->video_pad);
 	if (ret < 0)
-		pr_err("failed to initialize video media entity!\n");
+		dev_err(&dev->intf->dev,
+			"failed to initialize video media entity!\n");
 
 	if (em28xx_vbi_supported(dev)) {
 		v4l2->vbi_pad.flags = MEDIA_PAD_FL_SINK;
 		ret = media_entity_pads_init(&v4l2->vbi_dev.entity, 1,
 					     &v4l2->vbi_pad);
 		if (ret < 0)
-			pr_err("failed to initialize vbi media entity!\n");
+			dev_err(&dev->intf->dev,
+				"failed to initialize vbi media entity!\n");
 	}
 
 	/* Webcams don't have input connectors */
@@ -997,11 +1001,13 @@ static void em28xx_v4l2_create_entities(
 
 		ret = media_entity_pads_init(ent, 1, &dev->input_pad[i]);
 		if (ret < 0)
-			pr_err("failed to initialize input pad[%d]!\n", i);
+			dev_err(&dev->intf->dev,
+				"failed to initialize input pad[%d]!\n", i);
 
 		ret = media_device_register_entity(dev->media_dev, ent);
 		if (ret < 0)
-			pr_err("failed to register input entity %d!\n", i);
+			dev_err(&dev->intf->dev,
+				"failed to register input entity %d!\n", i);
 	}
 #endif
 }
@@ -1854,10 +1860,11 @@ static int vidioc_querycap(struct file *
 	struct video_device   *vdev = video_devdata(file);
 	struct em28xx         *dev  = video_drvdata(file);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 
 	strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
 	strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
-	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+	usb_make_path(udev, cap->bus_info, sizeof(cap->bus_info));
 
 	if (vdev->vfl_type == VFL_TYPE_GRABBER)
 		cap->device_caps = V4L2_CAP_READWRITE |
@@ -2048,8 +2055,9 @@ static int em28xx_v4l2_open(struct file
 
 	ret = v4l2_fh_open(filp);
 	if (ret) {
-		em28xx_errdev("%s: v4l2_fh_open() returned error %d\n",
-			      __func__, ret);
+		dev_err(&dev->intf->dev,
+			"%s: v4l2_fh_open() returned error %d\n",
+		       __func__, ret);
 		mutex_unlock(&dev->lock);
 		return ret;
 	}
@@ -2103,7 +2111,7 @@ static int em28xx_v4l2_fini(struct em28x
 	if (v4l2 == NULL)
 		return 0;
 
-	em28xx_info("Closing video extension\n");
+	dev_info(&dev->intf->dev, "Closing video extension\n");
 
 	mutex_lock(&dev->lock);
 
@@ -2114,18 +2122,18 @@ static int em28xx_v4l2_fini(struct em28x
 	em28xx_v4l2_media_release(dev);
 
 	if (video_is_registered(&v4l2->radio_dev)) {
-		em28xx_info("V4L2 device %s deregistered\n",
-			    video_device_node_name(&v4l2->radio_dev));
+		dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
+			video_device_node_name(&v4l2->radio_dev));
 		video_unregister_device(&v4l2->radio_dev);
 	}
 	if (video_is_registered(&v4l2->vbi_dev)) {
-		em28xx_info("V4L2 device %s deregistered\n",
-			    video_device_node_name(&v4l2->vbi_dev));
+		dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
+			video_device_node_name(&v4l2->vbi_dev));
 		video_unregister_device(&v4l2->vbi_dev);
 	}
 	if (video_is_registered(&v4l2->vdev)) {
-		em28xx_info("V4L2 device %s deregistered\n",
-			    video_device_node_name(&v4l2->vdev));
+		dev_info(&dev->intf->dev, "V4L2 device %s deregistered\n",
+			video_device_node_name(&v4l2->vdev));
 		video_unregister_device(&v4l2->vdev);
 	}
 
@@ -2154,7 +2162,7 @@ static int em28xx_v4l2_suspend(struct em
 	if (!dev->has_video)
 		return 0;
 
-	em28xx_info("Suspending video extension\n");
+	dev_info(&dev->intf->dev, "Suspending video extension\n");
 	em28xx_stop_urbs(dev);
 	return 0;
 }
@@ -2167,7 +2175,7 @@ static int em28xx_v4l2_resume(struct em2
 	if (!dev->has_video)
 		return 0;
 
-	em28xx_info("Resuming video extension\n");
+	dev_info(&dev->intf->dev, "Resuming video extension\n");
 	/* what do we do here */
 	return 0;
 }
@@ -2181,6 +2189,7 @@ static int em28xx_v4l2_close(struct file
 {
 	struct em28xx         *dev  = video_drvdata(filp);
 	struct em28xx_v4l2    *v4l2 = dev->v4l2;
+	struct usb_device *udev = interface_to_usbdev(dev->intf);
 	int              errCode;
 
 	em28xx_videodbg("users=%d\n", v4l2->users);
@@ -2202,10 +2211,11 @@ static int em28xx_v4l2_close(struct file
 		/* set alternate 0 */
 		dev->alt = 0;
 		em28xx_videodbg("setting alternate 0\n");
-		errCode = usb_set_interface(dev->udev, 0, 0);
+		errCode = usb_set_interface(udev, 0, 0);
 		if (errCode < 0) {
-			em28xx_errdev("cannot change alternate number to "
-					"0 (error=%i)\n", errCode);
+			dev_err(&dev->intf->dev,
+				"cannot change alternate number to 0 (error=%i)\n",
+				errCode);
 		}
 	}
 
@@ -2338,7 +2348,7 @@ static void em28xx_vdev_init(struct em28
 		vfd->tvnorms = 0;
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s %s",
-		 dev->name, type_name);
+		 dev_name(&dev->intf->dev), type_name);
 
 	video_set_drvdata(vfd, dev);
 }
@@ -2422,13 +2432,12 @@ static int em28xx_v4l2_init(struct em28x
 		return 0;
 	}
 
-	em28xx_info("Registering V4L2 extension\n");
+	dev_info(&dev->intf->dev, "Registering V4L2 extension\n");
 
 	mutex_lock(&dev->lock);
 
 	v4l2 = kzalloc(sizeof(struct em28xx_v4l2), GFP_KERNEL);
-	if (v4l2 == NULL) {
-		em28xx_info("em28xx_v4l: memory allocation failed\n");
+	if (!v4l2) {
 		mutex_unlock(&dev->lock);
 		return -ENOMEM;
 	}
@@ -2439,9 +2448,10 @@ static int em28xx_v4l2_init(struct em28x
 #ifdef CONFIG_MEDIA_CONTROLLER
 	v4l2->v4l2_dev.mdev = dev->media_dev;
 #endif
-	ret = v4l2_device_register(&dev->udev->dev, &v4l2->v4l2_dev);
+	ret = v4l2_device_register(&dev->intf->dev, &v4l2->v4l2_dev);
 	if (ret < 0) {
-		em28xx_errdev("Call to v4l2_device_register() failed!\n");
+		dev_err(&dev->intf->dev,
+			"Call to v4l2_device_register() failed!\n");
 		goto err;
 	}
 
@@ -2525,8 +2535,9 @@ static int em28xx_v4l2_init(struct em28x
 	/* Configure audio */
 	ret = em28xx_audio_setup(dev);
 	if (ret < 0) {
-		em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
-			      __func__, ret);
+		dev_err(&dev->intf->dev,
+			"%s: Error while setting audio - error [%d]!\n",
+			__func__, ret);
 		goto unregister_dev;
 	}
 	if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
@@ -2553,16 +2564,18 @@ static int em28xx_v4l2_init(struct em28x
 		/* Send a reset to other chips via gpio */
 		ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xf7);
 		if (ret < 0) {
-			em28xx_errdev("%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
-				      __func__, ret);
+			dev_err(&dev->intf->dev,
+				"%s: em28xx_write_reg - msp34xx(1) failed! error [%d]\n",
+				__func__, ret);
 			goto unregister_dev;
 		}
 		msleep(3);
 
 		ret = em28xx_write_reg(dev, EM2820_R08_GPIO_CTRL, 0xff);
 		if (ret < 0) {
-			em28xx_errdev("%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
-				      __func__, ret);
+			dev_err(&dev->intf->dev,
+				"%s: em28xx_write_reg - msp34xx(2) failed! error [%d]\n",
+				__func__, ret);
 			goto unregister_dev;
 		}
 		msleep(3);
@@ -2663,8 +2676,8 @@ static int em28xx_v4l2_init(struct em28x
 	ret = video_register_device(&v4l2->vdev, VFL_TYPE_GRABBER,
 				    video_nr[dev->devno]);
 	if (ret) {
-		em28xx_errdev("unable to register video device (error=%i).\n",
-			      ret);
+		dev_err(&dev->intf->dev,
+			"unable to register video device (error=%i).\n", ret);
 		goto unregister_dev;
 	}
 
@@ -2693,7 +2706,8 @@ static int em28xx_v4l2_init(struct em28x
 		ret = video_register_device(&v4l2->vbi_dev, VFL_TYPE_VBI,
 					    vbi_nr[dev->devno]);
 		if (ret < 0) {
-			em28xx_errdev("unable to register vbi device\n");
+			dev_err(&dev->intf->dev,
+				"unable to register vbi device\n");
 			goto unregister_dev;
 		}
 	}
@@ -2704,11 +2718,13 @@ static int em28xx_v4l2_init(struct em28x
 		ret = video_register_device(&v4l2->radio_dev, VFL_TYPE_RADIO,
 					    radio_nr[dev->devno]);
 		if (ret < 0) {
-			em28xx_errdev("can't register radio device\n");
+			dev_err(&dev->intf->dev,
+				"can't register radio device\n");
 			goto unregister_dev;
 		}
-		em28xx_info("Registered radio device as %s\n",
-			    video_device_node_name(&v4l2->radio_dev));
+		dev_info(&dev->intf->dev,
+			 "Registered radio device as %s\n",
+			 video_device_node_name(&v4l2->radio_dev));
 	}
 
 	/* Init entities at the Media Controller */
@@ -2717,18 +2733,21 @@ static int em28xx_v4l2_init(struct em28x
 #ifdef CONFIG_MEDIA_CONTROLLER
 	ret = v4l2_mc_create_media_graph(dev->media_dev);
 	if (ret) {
-		em28xx_errdev("failed to create media graph\n");
+		dev_err(&dev->intf->dev,
+			"failed to create media graph\n");
 		em28xx_v4l2_media_release(dev);
 		goto unregister_dev;
 	}
 #endif
 
-	em28xx_info("V4L2 video device registered as %s\n",
-		    video_device_node_name(&v4l2->vdev));
+	dev_info(&dev->intf->dev,
+		 "V4L2 video device registered as %s\n",
+		 video_device_node_name(&v4l2->vdev));
 
 	if (video_is_registered(&v4l2->vbi_dev))
-		em28xx_info("V4L2 VBI device registered as %s\n",
-			    video_device_node_name(&v4l2->vbi_dev));
+		dev_info(&dev->intf->dev,
+			 "V4L2 VBI device registered as %s\n",
+			 video_device_node_name(&v4l2->vbi_dev));
 
 	/* Save some power by putting tuner to sleep */
 	v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0);
@@ -2736,7 +2755,8 @@ static int em28xx_v4l2_init(struct em28x
 	/* initialize videobuf2 stuff */
 	em28xx_vb2_setup(dev);
 
-	em28xx_info("V4L2 extension successfully initialized\n");
+	dev_info(&dev->intf->dev,
+		 "V4L2 extension successfully initialized\n");
 
 	kref_get(&dev->ref);
 
@@ -2745,18 +2765,21 @@ static int em28xx_v4l2_init(struct em28x
 
 unregister_dev:
 	if (video_is_registered(&v4l2->radio_dev)) {
-		em28xx_info("V4L2 device %s deregistered\n",
-			    video_device_node_name(&v4l2->radio_dev));
+		dev_info(&dev->intf->dev,
+			 "V4L2 device %s deregistered\n",
+			 video_device_node_name(&v4l2->radio_dev));
 		video_unregister_device(&v4l2->radio_dev);
 	}
 	if (video_is_registered(&v4l2->vbi_dev)) {
-		em28xx_info("V4L2 device %s deregistered\n",
-			    video_device_node_name(&v4l2->vbi_dev));
+		dev_info(&dev->intf->dev,
+			 "V4L2 device %s deregistered\n",
+			 video_device_node_name(&v4l2->vbi_dev));
 		video_unregister_device(&v4l2->vbi_dev);
 	}
 	if (video_is_registered(&v4l2->vdev)) {
-		em28xx_info("V4L2 device %s deregistered\n",
-			    video_device_node_name(&v4l2->vdev));
+		dev_info(&dev->intf->dev,
+			 "V4L2 device %s deregistered\n",
+			 video_device_node_name(&v4l2->vdev));
 		video_unregister_device(&v4l2->vdev);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/em28xx/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/Kconfig
--- linux-libre-4.9-gnu/drivers/media/usb/em28xx/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/em28xx/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@ config VIDEO_EM28XX_V4L2
 	select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_TVP5150 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
-	select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT
 
 	---help---
 	  This is a video4linux driver for Empia 28xx based TV cards.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/go7007/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/usb/go7007/Kconfig
--- linux-libre-4.9-gnu/drivers/media/usb/go7007/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/go7007/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -11,7 +11,7 @@ config VIDEO_GO7007
 	select VIDEO_TW2804 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_TW9903 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_TW9906 if MEDIA_SUBDRV_AUTOSELECT
-	select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT
+	select VIDEO_OV7640 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_CAMERA_SUPPORT
 	select VIDEO_UDA1342 if MEDIA_SUBDRV_AUTOSELECT
 	---help---
 	  This is a video4linux driver for the WIS GO7007 MPEG
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/gspca.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/gspca.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/gspca.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/gspca.c	2017-02-12 16:03:20.000000000 -0500
@@ -201,8 +201,7 @@ static int alloc_and_submit_int_urb(stru
 
 	buffer_len = le16_to_cpu(ep->wMaxPacketSize);
 	interval = ep->bInterval;
-	PDEBUG(D_CONF, "found int in endpoint: 0x%x, "
-		"buffer_len=%u, interval=%u",
+	PDEBUG(D_CONF, "found int in endpoint: 0x%x, buffer_len=%u, interval=%u",
 		ep->bEndpointAddress, buffer_len, interval);
 
 	dev = gspca_dev->dev;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/jl2005bcd.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/jl2005bcd.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/jl2005bcd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/jl2005bcd.c	2017-02-12 16:03:20.000000000 -0500
@@ -299,10 +299,7 @@ static int jl2005c_stream_start_cif_smal
 
 static int jl2005c_stop(struct gspca_dev *gspca_dev)
 {
-	int retval;
-
-	retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00);
-	return retval;
+	return jl2005c_write_reg(gspca_dev, 0x07, 0x00);
 }
 
 /*
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/m5602/m5602_core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/m5602/m5602_core.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/m5602/m5602_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/m5602/m5602_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -154,8 +154,8 @@ int m5602_read_sensor(struct sd *sd, con
 
 		err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
 
-		PDEBUG(D_CONF, "Reading sensor register "
-			       "0x%x containing 0x%x ", address, *i2c_data);
+		PDEBUG(D_CONF, "Reading sensor register 0x%x containing 0x%x ",
+		       address, *i2c_data);
 	}
 	return err;
 }
@@ -441,13 +441,10 @@ MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 module_param(force_sensor, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(force_sensor,
-		"forces detection of a sensor, "
-		"1 = OV9650, 2 = S5K83A, 3 = S5K4AA, "
-		"4 = MT9M111, 5 = PO1030, 6 = OV7660");
+		"forces detection of a sensor, 1 = OV9650, 2 = S5K83A, 3 = S5K4AA, 4 = MT9M111, 5 = PO1030, 6 = OV7660");
 
 module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
 
 module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
-		"at startup providing a sensor is found");
+MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers at startup providing a sensor is found");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/mr97310a.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/mr97310a.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/mr97310a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/mr97310a.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,8 +72,7 @@
 #define MR97310A_MIN_CLOCKDIV_MAX	8
 #define MR97310A_MIN_CLOCKDIV_DEFAULT	3
 
-MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
-	      "Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,Theodore Kilgore <kilgota@auburn.edu>");
 MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
 MODULE_LICENSE("GPL");
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/ov519.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/ov519.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/ov519.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/ov519.c	2017-02-12 16:03:20.000000000 -0500
@@ -4326,8 +4326,7 @@ static void ov511_pkt_scan(struct gspca_
 			/* Frame end */
 			if ((in[9] + 1) * 8 != gspca_dev->pixfmt.width ||
 			    (in[10] + 1) * 8 != gspca_dev->pixfmt.height) {
-				PERR("Invalid frame size, got: %dx%d,"
-					" requested: %dx%d\n",
+				PERR("Invalid frame size, got: %dx%d, requested: %dx%d\n",
 					(in[9] + 1) * 8, (in[10] + 1) * 8,
 					gspca_dev->pixfmt.width,
 					gspca_dev->pixfmt.height);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/pac207.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/pac207.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/pac207.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/pac207.c	2017-02-12 16:03:20.000000000 -0500
@@ -179,8 +179,8 @@ static int sd_config(struct gspca_dev *g
 	}
 
 	PDEBUG(D_PROBE,
-		"Pixart PAC207BCA Image Processor and Control Chip detected"
-		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+		"Pixart PAC207BCA Image Processor and Control Chip detected (vid/pid 0x%04X:0x%04X)",
+		id->idVendor, id->idProduct);
 
 	cam = &gspca_dev->cam;
 	cam->cam_mode = sif_mode;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/pac7302.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/pac7302.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/pac7302.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/pac7302.c	2017-02-12 16:03:20.000000000 -0500
@@ -105,8 +105,7 @@
 #define PAC7302_EXPOSURE_DEFAULT	 66 /* 33 ms / 30 fps */
 #define PAC7302_EXPOSURE_KNEE		133 /* 66 ms / 15 fps */
 
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
-		"Thomas Kaiser thomas@kaiser-linux.li");
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, Thomas Kaiser thomas@kaiser-linux.li");
 MODULE_DESCRIPTION("Pixart PAC7302");
 MODULE_LICENSE("GPL");
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/sn9c20x.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sn9c20x.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/sn9c20x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sn9c20x.c	2017-02-12 16:03:20.000000000 -0500
@@ -29,8 +29,7 @@
 
 #include <linux/dmi.h>
 
-MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
-		"microdia project <microdia@googlegroups.com>");
+MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, microdia project <microdia@googlegroups.com>");
 MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
 MODULE_LICENSE("GPL");
 
@@ -1948,8 +1947,7 @@ static int sd_isoc_init(struct gspca_dev
 		intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
 
 		if (intf->num_altsetting != 9) {
-			pr_warn("sn9c20x camera with unknown number of alt "
-				"settings (%d), please report!\n",
+			pr_warn("sn9c20x camera with unknown number of alt settings (%d), please report!\n",
 				intf->num_altsetting);
 			gspca_dev->alt = intf->num_altsetting;
 			return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/spca506.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/spca506.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/spca506.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/spca506.c	2017-02-12 16:03:20.000000000 -0500
@@ -581,8 +581,7 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x06e1, 0xa190)},
-/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
-	{USB_DEVICE(0x0733, 0x0430)}, */
+/*	{USB_DEVICE(0x0733, 0x0430)}, FIXME: may be IntelPCCameraPro BRIDGE_SPCA505 */
 	{USB_DEVICE(0x0734, 0x043b)},
 	{USB_DEVICE(0x99fa, 0x8988)},
 	{}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/sq905.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sq905.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/sq905.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sq905.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,8 +41,7 @@
 #include <linux/slab.h>
 #include "gspca.h"
 
-MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
-		"Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, Theodore Kilgore <kilgota@auburn.edu>");
 MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
 MODULE_LICENSE("GPL");
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/sq905c.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sq905c.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/sq905c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sq905c.c	2017-02-12 16:03:20.000000000 -0500
@@ -210,8 +210,8 @@ static int sd_config(struct gspca_dev *g
 	int ret;
 
 	PDEBUG(D_PROBE,
-		"SQ9050 camera detected"
-		" (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+	       "SQ9050 camera detected (vid/pid 0x%04X:0x%04X)",
+	       id->idVendor, id->idProduct);
 
 	ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
 	if (ret < 0) {
@@ -257,11 +257,8 @@ static void sd_stop0(struct gspca_dev *g
 /* this function is called at probe and resume time */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
-	int ret;
-
 	/* connect to the camera and reset it. */
-	ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
-	return ret;
+	return sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
 }
 
 /* Set up for getting frames. */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/stv06xx/stv06xx.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/stv06xx/stv06xx.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/stv06xx/stv06xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/stv06xx/stv06xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -412,8 +412,7 @@ static void stv06xx_pkt_scan(struct gspc
 		len -= 4;
 
 		if (len < chunk_len) {
-			PERR("URB packet length is smaller"
-				" than the specified chunk length");
+			PERR("URB packet length is smaller than the specified chunk length");
 			gspca_dev->last_packet_type = DISCARD_PACKET;
 			return;
 		}
@@ -455,8 +454,7 @@ frame_data:
 				sd->to_skip = gspca_dev->pixfmt.width * 4;
 
 			if (chunk_len)
-				PERR("Chunk length is "
-					      "non-zero on a SOF");
+				PERR("Chunk length is non-zero on a SOF");
 			break;
 
 		case 0x8002:
@@ -469,8 +467,7 @@ frame_data:
 					NULL, 0);
 
 			if (chunk_len)
-				PERR("Chunk length is "
-					      "non-zero on a EOF");
+				PERR("Chunk length is non-zero on a EOF");
 			break;
 
 		case 0x0005:
@@ -582,18 +579,12 @@ static int stv06xx_config(struct gspca_d
 
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
-	/* QuickCam Express */
-	{USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
-	/* LEGO cam / QuickCam Web */
-	{USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
-	/* Dexxa WebCam USB */
-	{USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
-	/* QuickCam Messenger */
-	{USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
-	/* QuickCam Communicate */
-	{USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
-	/* QuickCam Messenger (new) */
-	{USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
+	{USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 }, 	/* QuickCam Express */
+	{USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },	/* LEGO cam / QuickCam Web */
+	{USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },	/* Dexxa WebCam USB */
+	{USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },	/* QuickCam Messenger */
+	{USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },	/* QuickCam Communicate */
+	{USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },	/* QuickCam Messenger (new) */
 	{}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/sunplus.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sunplus.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/sunplus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/sunplus.c	2017-02-12 16:03:20.000000000 -0500
@@ -368,8 +368,7 @@ static void spca504_read_info(struct gsp
 		info[i] = gspca_dev->usb_buf[0];
 	}
 	PDEBUG(D_STREAM,
-		"Read info: %d %d %d %d %d %d."
-		" Should be 1,0,2,2,0,0",
+		"Read info: %d %d %d %d %d %d. Should be 1,0,2,2,0,0",
 		info[0], info[1], info[2],
 		info[3], info[4], info[5]);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/topro.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/topro.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/topro.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/topro.c	2017-02-12 16:03:20.000000000 -0500
@@ -24,8 +24,7 @@
 #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_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, Anders Blomdell <anders.blomdell@control.lth.se>");
 MODULE_LICENSE("GPL");
 
 static int force_sensor = -1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/gspca/zc3xx.c linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/zc3xx.c
--- linux-libre-4.9-gnu/drivers/media/usb/gspca/zc3xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/gspca/zc3xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,8 +25,7 @@
 #include "gspca.h"
 #include "jpeg.h"
 
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
-		"Serge A. Suchkov <Serge.A.S@tochka.ru>");
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, Serge A. Suchkov <Serge.A.S@tochka.ru>");
 MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
 MODULE_LICENSE("GPL");
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/hdpvr/hdpvr-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/hdpvr/hdpvr-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/hdpvr/hdpvr-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/hdpvr/hdpvr-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,13 +41,11 @@ MODULE_PARM_DESC(hdpvr_debug, "enable de
 
 static uint default_video_input = HDPVR_VIDEO_INPUTS;
 module_param(default_video_input, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / "
-		 "1=S-Video / 2=Composite");
+MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / 1=S-Video / 2=Composite");
 
 static uint default_audio_input = HDPVR_AUDIO_INPUTS;
 module_param(default_audio_input, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / "
-		 "1=RCA front / 2=S/PDIF");
+MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / 1=RCA front / 2=S/PDIF");
 
 static bool boost_audio;
 module_param(boost_audio, bool, S_IRUGO|S_IWUSR);
@@ -165,8 +163,7 @@ static int device_authorization(struct h
 		dev->flags |= HDPVR_FLAG_AC3_CAP;
 		break;
 	default:
-		v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might"
-			  " not work.\n");
+		v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might not work.\n");
 		if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3)
 			dev->flags |= HDPVR_FLAG_AC3_CAP;
 		else
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/hdpvr/hdpvr-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/usb/hdpvr/hdpvr-i2c.c
--- linux-libre-4.9-gnu/drivers/media/usb/hdpvr/hdpvr-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/hdpvr/hdpvr-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -145,15 +145,14 @@ static int hdpvr_transfer(struct i2c_ada
 						 msgs[0].len);
 	} else if (num == 2) {
 		if (msgs[0].addr != msgs[1].addr) {
-			v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer "
-				  "with conflicting target addresses\n");
+			v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer with conflicting target addresses\n");
 			retval = -EINVAL;
 			goto out;
 		}
 
 		if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
-			v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with "
-				  "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD,
+			v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with r0=%d, r1=%d\n",
+				  msgs[0].flags & I2C_M_RD,
 				  msgs[1].flags & I2C_M_RD);
 			retval = -EINVAL;
 			goto out;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/hdpvr/hdpvr-video.c linux-libre-4.10-rc8-gnu/drivers/media/usb/hdpvr/hdpvr-video.c
--- linux-libre-4.9-gnu/drivers/media/usb/hdpvr/hdpvr-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/hdpvr/hdpvr-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -336,9 +336,7 @@ static int hdpvr_stop_streaming(struct h
 
 	buf = kmalloc(dev->bulk_in_size, GFP_KERNEL);
 	if (!buf)
-		v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer "
-			 "for emptying the internal device buffer. "
-			 "Next capture start will be slow\n");
+		v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer for emptying the internal device buffer. Next capture start will be slow\n");
 
 	dev->status = STATUS_SHUTTING_DOWN;
 	hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00);
@@ -451,6 +449,7 @@ static ssize_t hdpvr_read(struct file *f
 
 		if (buf->status != BUFSTAT_READY &&
 		    dev->status != STATUS_DISCONNECTED) {
+			int err;
 			/* return nonblocking */
 			if (file->f_flags & O_NONBLOCK) {
 				if (!ret)
@@ -458,9 +457,24 @@ static ssize_t hdpvr_read(struct file *f
 				goto err;
 			}
 
-			if (wait_event_interruptible(dev->wait_data,
-					      buf->status == BUFSTAT_READY))
-				return -ERESTARTSYS;
+			err = wait_event_interruptible_timeout(dev->wait_data,
+				buf->status == BUFSTAT_READY,
+				msecs_to_jiffies(1000));
+			if (err < 0) {
+				ret = err;
+				goto err;
+			}
+			if (!err) {
+				v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+					"timeout: restart streaming\n");
+				hdpvr_stop_streaming(dev);
+				msecs_to_jiffies(4000);
+				err = hdpvr_start_streaming(dev);
+				if (err) {
+					ret = err;
+					goto err;
+				}
+			}
 		}
 
 		if (buf->status != BUFSTAT_READY)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/usb/Kconfig
--- linux-libre-4.9-gnu/drivers/media/usb/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -60,5 +60,10 @@ source "drivers/media/usb/hackrf/Kconfig
 source "drivers/media/usb/msi2500/Kconfig"
 endif
 
+if MEDIA_CEC_SUPPORT
+	comment "USB HDMI CEC adapters"
+source "drivers/media/usb/pulse8-cec/Kconfig"
+endif
+
 endif #MEDIA_USB_SUPPORT
 endif #USB
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/Makefile linux-libre-4.10-rc8-gnu/drivers/media/usb/Makefile
--- linux-libre-4.9-gnu/drivers/media/usb/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -24,3 +24,4 @@ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_USBTV) += usbtv/
 obj-$(CONFIG_VIDEO_GO7007) += go7007/
 obj-$(CONFIG_DVB_AS102) += as102/
+obj-$(CONFIG_USB_PULSE8_CEC) += pulse8-cec/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pulse8-cec/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/usb/pulse8-cec/Kconfig
--- linux-libre-4.9-gnu/drivers/media/usb/pulse8-cec/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pulse8-cec/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+config USB_PULSE8_CEC
+	tristate "Pulse Eight HDMI CEC"
+	depends on USB_ACM && MEDIA_CEC_SUPPORT
+	select SERIO
+	select SERIO_SERPORT
+	---help---
+	  This is a cec driver for the Pulse Eight HDMI CEC device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pulse8-cec.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pulse8-cec/Makefile linux-libre-4.10-rc8-gnu/drivers/media/usb/pulse8-cec/Makefile
--- linux-libre-4.9-gnu/drivers/media/usb/pulse8-cec/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pulse8-cec/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_PULSE8_CEC) += pulse8-cec.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pulse8-cec/pulse8-cec.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pulse8-cec/pulse8-cec.c
--- linux-libre-4.9-gnu/drivers/media/usb/pulse8-cec/pulse8-cec.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pulse8-cec/pulse8-cec.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,761 @@
+/*
+ * Pulse Eight HDMI CEC driver
+ *
+ * Copyright 2016 Hans Verkuil <hverkuil@xs4all.nl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version of 2 of the License, or (at your
+ * option) any later version. See the file COPYING in the main directory of
+ * this archive for more details.
+ */
+
+/*
+ * Notes:
+ *
+ * - Devices with firmware version < 2 do not store their configuration in
+ *   EEPROM.
+ *
+ * - In autonomous mode, only messages from a TV will be acknowledged, even
+ *   polling messages. Upon receiving a message from a TV, the dongle will
+ *   respond to messages from any logical address.
+ *
+ * - In autonomous mode, the dongle will by default reply Feature Abort
+ *   [Unrecognized Opcode] when it receives Give Device Vendor ID. It will
+ *   however observe vendor ID's reported by other devices and possibly
+ *   alter this behavior. When TV's (and TV's only) report that their vendor ID
+ *   is LG (0x00e091), the dongle will itself reply that it has the same vendor
+ *   ID, and it will respond to at least one vendor specific command.
+ *
+ * - In autonomous mode, the dongle is known to attempt wakeup if it receives
+ *   <User Control Pressed> ["Power On"], ["Power] or ["Power Toggle"], or if it
+ *   receives <Set Stream Path> with its own physical address. It also does this
+ *   if it receives <Vendor Specific Command> [0x03 0x00] from an LG TV.
+ */
+
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <media/cec.h>
+
+MODULE_AUTHOR("Hans Verkuil <hverkuil@xs4all.nl>");
+MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver");
+MODULE_LICENSE("GPL");
+
+static int debug;
+static int persistent_config = 1;
+module_param(debug, int, 0644);
+module_param(persistent_config, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-1)");
+MODULE_PARM_DESC(persistent_config, "read config from persistent memory (0-1)");
+
+enum pulse8_msgcodes {
+	MSGCODE_NOTHING = 0,
+	MSGCODE_PING,
+	MSGCODE_TIMEOUT_ERROR,
+	MSGCODE_HIGH_ERROR,
+	MSGCODE_LOW_ERROR,
+	MSGCODE_FRAME_START,
+	MSGCODE_FRAME_DATA,
+	MSGCODE_RECEIVE_FAILED,
+	MSGCODE_COMMAND_ACCEPTED,	/* 0x08 */
+	MSGCODE_COMMAND_REJECTED,
+	MSGCODE_SET_ACK_MASK,
+	MSGCODE_TRANSMIT,
+	MSGCODE_TRANSMIT_EOM,
+	MSGCODE_TRANSMIT_IDLETIME,
+	MSGCODE_TRANSMIT_ACK_POLARITY,
+	MSGCODE_TRANSMIT_LINE_TIMEOUT,
+	MSGCODE_TRANSMIT_SUCCEEDED,	/* 0x10 */
+	MSGCODE_TRANSMIT_FAILED_LINE,
+	MSGCODE_TRANSMIT_FAILED_ACK,
+	MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA,
+	MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE,
+	MSGCODE_FIRMWARE_VERSION,
+	MSGCODE_START_BOOTLOADER,
+	MSGCODE_GET_BUILDDATE,
+	MSGCODE_SET_CONTROLLED,		/* 0x18 */
+	MSGCODE_GET_AUTO_ENABLED,
+	MSGCODE_SET_AUTO_ENABLED,
+	MSGCODE_GET_DEFAULT_LOGICAL_ADDRESS,
+	MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS,
+	MSGCODE_GET_LOGICAL_ADDRESS_MASK,
+	MSGCODE_SET_LOGICAL_ADDRESS_MASK,
+	MSGCODE_GET_PHYSICAL_ADDRESS,
+	MSGCODE_SET_PHYSICAL_ADDRESS,	/* 0x20 */
+	MSGCODE_GET_DEVICE_TYPE,
+	MSGCODE_SET_DEVICE_TYPE,
+	MSGCODE_GET_HDMI_VERSION,
+	MSGCODE_SET_HDMI_VERSION,
+	MSGCODE_GET_OSD_NAME,
+	MSGCODE_SET_OSD_NAME,
+	MSGCODE_WRITE_EEPROM,
+	MSGCODE_GET_ADAPTER_TYPE,	/* 0x28 */
+	MSGCODE_SET_ACTIVE_SOURCE,
+
+	MSGCODE_FRAME_EOM = 0x80,
+	MSGCODE_FRAME_ACK = 0x40,
+};
+
+#define MSGSTART	0xff
+#define MSGEND		0xfe
+#define MSGESC		0xfd
+#define MSGOFFSET	3
+
+#define DATA_SIZE 256
+
+#define PING_PERIOD	(15 * HZ)
+
+struct pulse8 {
+	struct device *dev;
+	struct serio *serio;
+	struct cec_adapter *adap;
+	unsigned int vers;
+	struct completion cmd_done;
+	struct work_struct work;
+	struct delayed_work ping_eeprom_work;
+	struct cec_msg rx_msg;
+	u8 data[DATA_SIZE];
+	unsigned int len;
+	u8 buf[DATA_SIZE];
+	unsigned int idx;
+	bool escape;
+	bool started;
+	struct mutex config_lock;
+	struct mutex write_lock;
+	bool config_pending;
+	bool restoring_config;
+	bool autonomous;
+};
+
+static void pulse8_ping_eeprom_work_handler(struct work_struct *work);
+
+static void pulse8_irq_work_handler(struct work_struct *work)
+{
+	struct pulse8 *pulse8 =
+		container_of(work, struct pulse8, work);
+
+	switch (pulse8->data[0] & 0x3f) {
+	case MSGCODE_FRAME_DATA:
+		cec_received_msg(pulse8->adap, &pulse8->rx_msg);
+		break;
+	case MSGCODE_TRANSMIT_SUCCEEDED:
+		cec_transmit_done(pulse8->adap, CEC_TX_STATUS_OK,
+				  0, 0, 0, 0);
+		break;
+	case MSGCODE_TRANSMIT_FAILED_ACK:
+		cec_transmit_done(pulse8->adap, CEC_TX_STATUS_NACK,
+				  0, 1, 0, 0);
+		break;
+	case MSGCODE_TRANSMIT_FAILED_LINE:
+	case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
+	case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
+		cec_transmit_done(pulse8->adap, CEC_TX_STATUS_ERROR,
+				  0, 0, 0, 1);
+		break;
+	}
+}
+
+static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data,
+				    unsigned int flags)
+{
+	struct pulse8 *pulse8 = serio_get_drvdata(serio);
+
+	if (!pulse8->started && data != MSGSTART)
+		return IRQ_HANDLED;
+	if (data == MSGESC) {
+		pulse8->escape = true;
+		return IRQ_HANDLED;
+	}
+	if (pulse8->escape) {
+		data += MSGOFFSET;
+		pulse8->escape = false;
+	} else if (data == MSGEND) {
+		struct cec_msg *msg = &pulse8->rx_msg;
+
+		if (debug)
+			dev_info(pulse8->dev, "received: %*ph\n",
+				 pulse8->idx, pulse8->buf);
+		pulse8->data[0] = pulse8->buf[0];
+		switch (pulse8->buf[0] & 0x3f) {
+		case MSGCODE_FRAME_START:
+			msg->len = 1;
+			msg->msg[0] = pulse8->buf[1];
+			break;
+		case MSGCODE_FRAME_DATA:
+			if (msg->len == CEC_MAX_MSG_SIZE)
+				break;
+			msg->msg[msg->len++] = pulse8->buf[1];
+			if (pulse8->buf[0] & MSGCODE_FRAME_EOM)
+				schedule_work(&pulse8->work);
+			break;
+		case MSGCODE_TRANSMIT_SUCCEEDED:
+		case MSGCODE_TRANSMIT_FAILED_LINE:
+		case MSGCODE_TRANSMIT_FAILED_ACK:
+		case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
+		case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
+			schedule_work(&pulse8->work);
+			break;
+		case MSGCODE_HIGH_ERROR:
+		case MSGCODE_LOW_ERROR:
+		case MSGCODE_RECEIVE_FAILED:
+		case MSGCODE_TIMEOUT_ERROR:
+			break;
+		case MSGCODE_COMMAND_ACCEPTED:
+		case MSGCODE_COMMAND_REJECTED:
+		default:
+			if (pulse8->idx == 0)
+				break;
+			memcpy(pulse8->data, pulse8->buf, pulse8->idx);
+			pulse8->len = pulse8->idx;
+			complete(&pulse8->cmd_done);
+			break;
+		}
+		pulse8->idx = 0;
+		pulse8->started = false;
+		return IRQ_HANDLED;
+	} else if (data == MSGSTART) {
+		pulse8->idx = 0;
+		pulse8->started = true;
+		return IRQ_HANDLED;
+	}
+
+	if (pulse8->idx >= DATA_SIZE) {
+		dev_dbg(pulse8->dev,
+			"throwing away %d bytes of garbage\n", pulse8->idx);
+		pulse8->idx = 0;
+	}
+	pulse8->buf[pulse8->idx++] = data;
+	return IRQ_HANDLED;
+}
+
+static void pulse8_disconnect(struct serio *serio)
+{
+	struct pulse8 *pulse8 = serio_get_drvdata(serio);
+
+	cec_unregister_adapter(pulse8->adap);
+	cancel_delayed_work_sync(&pulse8->ping_eeprom_work);
+	dev_info(&serio->dev, "disconnected\n");
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	kfree(pulse8);
+}
+
+static int pulse8_send(struct serio *serio, const u8 *command, u8 cmd_len)
+{
+	int err = 0;
+
+	err = serio_write(serio, MSGSTART);
+	if (err)
+		return err;
+	for (; !err && cmd_len; command++, cmd_len--) {
+		if (*command >= MSGESC) {
+			err = serio_write(serio, MSGESC);
+			if (!err)
+				err = serio_write(serio, *command - MSGOFFSET);
+		} else {
+			err = serio_write(serio, *command);
+		}
+	}
+	if (!err)
+		err = serio_write(serio, MSGEND);
+
+	return err;
+}
+
+static int pulse8_send_and_wait_once(struct pulse8 *pulse8,
+				     const u8 *cmd, u8 cmd_len,
+				     u8 response, u8 size)
+{
+	int err;
+
+	/*dev_info(pulse8->dev, "transmit: %*ph\n", cmd_len, cmd);*/
+	init_completion(&pulse8->cmd_done);
+
+	err = pulse8_send(pulse8->serio, cmd, cmd_len);
+	if (err)
+		return err;
+
+	if (!wait_for_completion_timeout(&pulse8->cmd_done, HZ))
+		return -ETIMEDOUT;
+	if ((pulse8->data[0] & 0x3f) == MSGCODE_COMMAND_REJECTED &&
+	    cmd[0] != MSGCODE_SET_CONTROLLED &&
+	    cmd[0] != MSGCODE_SET_AUTO_ENABLED &&
+	    cmd[0] != MSGCODE_GET_BUILDDATE)
+		return -ENOTTY;
+	if (response &&
+	    ((pulse8->data[0] & 0x3f) != response || pulse8->len < size + 1)) {
+		dev_info(pulse8->dev, "transmit: failed %02x\n",
+			 pulse8->data[0] & 0x3f);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int pulse8_send_and_wait(struct pulse8 *pulse8,
+				const u8 *cmd, u8 cmd_len, u8 response, u8 size)
+{
+	u8 cmd_sc[2];
+	int err;
+
+	mutex_lock(&pulse8->write_lock);
+	err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len, response, size);
+
+	if (err == -ENOTTY) {
+		cmd_sc[0] = MSGCODE_SET_CONTROLLED;
+		cmd_sc[1] = 1;
+		err = pulse8_send_and_wait_once(pulse8, cmd_sc, 2,
+						MSGCODE_COMMAND_ACCEPTED, 1);
+		if (err)
+			goto unlock;
+		err = pulse8_send_and_wait_once(pulse8, cmd, cmd_len,
+						response, size);
+	}
+
+unlock:
+	mutex_unlock(&pulse8->write_lock);
+	return err == -ENOTTY ? -EIO : err;
+}
+
+static int pulse8_setup(struct pulse8 *pulse8, struct serio *serio,
+			struct cec_log_addrs *log_addrs, u16 *pa)
+{
+	u8 *data = pulse8->data + 1;
+	u8 cmd[2];
+	int err;
+	struct tm tm;
+	time_t date;
+
+	pulse8->vers = 0;
+
+	cmd[0] = MSGCODE_FIRMWARE_VERSION;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
+	if (err)
+		return err;
+	pulse8->vers = (data[0] << 8) | data[1];
+	dev_info(pulse8->dev, "Firmware version %04x\n", pulse8->vers);
+	if (pulse8->vers < 2) {
+		*pa = CEC_PHYS_ADDR_INVALID;
+		return 0;
+	}
+
+	cmd[0] = MSGCODE_GET_BUILDDATE;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 4);
+	if (err)
+		return err;
+	date = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+	time_to_tm(date, 0, &tm);
+	dev_info(pulse8->dev, "Firmware build date %04ld.%02d.%02d %02d:%02d:%02d\n",
+		 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+		 tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+	dev_dbg(pulse8->dev, "Persistent config:\n");
+	cmd[0] = MSGCODE_GET_AUTO_ENABLED;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
+	if (err)
+		return err;
+	pulse8->autonomous = data[0];
+	dev_dbg(pulse8->dev, "Autonomous mode: %s",
+		data[0] ? "on" : "off");
+
+	cmd[0] = MSGCODE_GET_DEVICE_TYPE;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
+	if (err)
+		return err;
+	log_addrs->primary_device_type[0] = data[0];
+	dev_dbg(pulse8->dev, "Primary device type: %d\n", data[0]);
+	switch (log_addrs->primary_device_type[0]) {
+	case CEC_OP_PRIM_DEVTYPE_TV:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TV;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TV;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_RECORD:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_RECORD;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_RECORD;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_TUNER:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_TUNER;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_TUNER;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_PLAYBACK;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_PLAYBACK;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_AUDIOSYSTEM;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_SWITCH:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_SPECIFIC;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
+		break;
+	default:
+		log_addrs->log_addr_type[0] = CEC_LOG_ADDR_TYPE_UNREGISTERED;
+		log_addrs->all_device_types[0] = CEC_OP_ALL_DEVTYPE_SWITCH;
+		dev_info(pulse8->dev, "Unknown Primary Device Type: %d\n",
+			 log_addrs->primary_device_type[0]);
+		break;
+	}
+
+	cmd[0] = MSGCODE_GET_LOGICAL_ADDRESS_MASK;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 2);
+	if (err)
+		return err;
+	log_addrs->log_addr_mask = (data[0] << 8) | data[1];
+	dev_dbg(pulse8->dev, "Logical address ACK mask: %x\n",
+		log_addrs->log_addr_mask);
+	if (log_addrs->log_addr_mask)
+		log_addrs->num_log_addrs = 1;
+
+	cmd[0] = MSGCODE_GET_PHYSICAL_ADDRESS;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
+	if (err)
+		return err;
+	*pa = (data[0] << 8) | data[1];
+	dev_dbg(pulse8->dev, "Physical address: %x.%x.%x.%x\n",
+		cec_phys_addr_exp(*pa));
+
+	cmd[0] = MSGCODE_GET_HDMI_VERSION;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 1);
+	if (err)
+		return err;
+	log_addrs->cec_version = data[0];
+	dev_dbg(pulse8->dev, "CEC version: %d\n", log_addrs->cec_version);
+
+	cmd[0] = MSGCODE_GET_OSD_NAME;
+	err = pulse8_send_and_wait(pulse8, cmd, 1, cmd[0], 0);
+	if (err)
+		return err;
+	strncpy(log_addrs->osd_name, data, 13);
+	dev_dbg(pulse8->dev, "OSD name: %s\n", log_addrs->osd_name);
+
+	return 0;
+}
+
+static int pulse8_apply_persistent_config(struct pulse8 *pulse8,
+					  struct cec_log_addrs *log_addrs,
+					  u16 pa)
+{
+	int err;
+
+	err = cec_s_log_addrs(pulse8->adap, log_addrs, false);
+	if (err)
+		return err;
+
+	cec_s_phys_addr(pulse8->adap, pa, false);
+
+	return 0;
+}
+
+static int pulse8_cec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+	struct pulse8 *pulse8 = adap->priv;
+	u8 cmd[16];
+	int err;
+
+	cmd[0] = MSGCODE_SET_CONTROLLED;
+	cmd[1] = enable;
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 1);
+	return enable ? err : 0;
+}
+
+static int pulse8_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
+{
+	struct pulse8 *pulse8 = adap->priv;
+	u16 mask = 0;
+	u16 pa = adap->phys_addr;
+	u8 cmd[16];
+	int err = 0;
+
+	mutex_lock(&pulse8->config_lock);
+	if (log_addr != CEC_LOG_ADDR_INVALID)
+		mask = 1 << log_addr;
+	cmd[0] = MSGCODE_SET_ACK_MASK;
+	cmd[1] = mask >> 8;
+	cmd[2] = mask & 0xff;
+	err = pulse8_send_and_wait(pulse8, cmd, 3,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if ((err && mask != 0) || pulse8->restoring_config)
+		goto unlock;
+
+	cmd[0] = MSGCODE_SET_AUTO_ENABLED;
+	cmd[1] = log_addr == CEC_LOG_ADDR_INVALID ? 0 : 1;
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if (err)
+		goto unlock;
+	pulse8->autonomous = cmd[1];
+	if (log_addr == CEC_LOG_ADDR_INVALID)
+		goto unlock;
+
+	cmd[0] = MSGCODE_SET_DEVICE_TYPE;
+	cmd[1] = adap->log_addrs.primary_device_type[0];
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if (err)
+		goto unlock;
+
+	switch (adap->log_addrs.primary_device_type[0]) {
+	case CEC_OP_PRIM_DEVTYPE_TV:
+		mask = CEC_LOG_ADDR_MASK_TV;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_RECORD:
+		mask = CEC_LOG_ADDR_MASK_RECORD;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_TUNER:
+		mask = CEC_LOG_ADDR_MASK_TUNER;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_PLAYBACK:
+		mask = CEC_LOG_ADDR_MASK_PLAYBACK;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_AUDIOSYSTEM:
+		mask = CEC_LOG_ADDR_MASK_AUDIOSYSTEM;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_SWITCH:
+		mask = CEC_LOG_ADDR_MASK_UNREGISTERED;
+		break;
+	case CEC_OP_PRIM_DEVTYPE_PROCESSOR:
+		mask = CEC_LOG_ADDR_MASK_SPECIFIC;
+		break;
+	default:
+		mask = 0;
+		break;
+	}
+	cmd[0] = MSGCODE_SET_LOGICAL_ADDRESS_MASK;
+	cmd[1] = mask >> 8;
+	cmd[2] = mask & 0xff;
+	err = pulse8_send_and_wait(pulse8, cmd, 3,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if (err)
+		goto unlock;
+
+	cmd[0] = MSGCODE_SET_DEFAULT_LOGICAL_ADDRESS;
+	cmd[1] = log_addr;
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if (err)
+		goto unlock;
+
+	cmd[0] = MSGCODE_SET_PHYSICAL_ADDRESS;
+	cmd[1] = pa >> 8;
+	cmd[2] = pa & 0xff;
+	err = pulse8_send_and_wait(pulse8, cmd, 3,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if (err)
+		goto unlock;
+
+	cmd[0] = MSGCODE_SET_HDMI_VERSION;
+	cmd[1] = adap->log_addrs.cec_version;
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 0);
+	if (err)
+		goto unlock;
+
+	if (adap->log_addrs.osd_name[0]) {
+		size_t osd_len = strlen(adap->log_addrs.osd_name);
+		char *osd_str = cmd + 1;
+
+		cmd[0] = MSGCODE_SET_OSD_NAME;
+		strncpy(cmd + 1, adap->log_addrs.osd_name, 13);
+		if (osd_len < 4) {
+			memset(osd_str + osd_len, ' ', 4 - osd_len);
+			osd_len = 4;
+			osd_str[osd_len] = '\0';
+			strcpy(adap->log_addrs.osd_name, osd_str);
+		}
+		err = pulse8_send_and_wait(pulse8, cmd, 1 + osd_len,
+					   MSGCODE_COMMAND_ACCEPTED, 0);
+		if (err)
+			goto unlock;
+	}
+
+unlock:
+	if (pulse8->restoring_config)
+		pulse8->restoring_config = false;
+	else
+		pulse8->config_pending = true;
+	mutex_unlock(&pulse8->config_lock);
+	return err;
+}
+
+static int pulse8_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
+				    u32 signal_free_time, struct cec_msg *msg)
+{
+	struct pulse8 *pulse8 = adap->priv;
+	u8 cmd[2];
+	unsigned int i;
+	int err;
+
+	cmd[0] = MSGCODE_TRANSMIT_IDLETIME;
+	cmd[1] = signal_free_time;
+	err = pulse8_send_and_wait(pulse8, cmd, 2,
+				   MSGCODE_COMMAND_ACCEPTED, 1);
+	cmd[0] = MSGCODE_TRANSMIT_ACK_POLARITY;
+	cmd[1] = cec_msg_is_broadcast(msg);
+	if (!err)
+		err = pulse8_send_and_wait(pulse8, cmd, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+	cmd[0] = msg->len == 1 ? MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
+	cmd[1] = msg->msg[0];
+	if (!err)
+		err = pulse8_send_and_wait(pulse8, cmd, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+	if (!err && msg->len > 1) {
+		cmd[0] = msg->len == 2 ? MSGCODE_TRANSMIT_EOM :
+					 MSGCODE_TRANSMIT;
+		cmd[1] = msg->msg[1];
+		err = pulse8_send_and_wait(pulse8, cmd, 2,
+					   MSGCODE_COMMAND_ACCEPTED, 1);
+		for (i = 0; !err && i + 2 < msg->len; i++) {
+			cmd[0] = (i + 2 == msg->len - 1) ?
+				MSGCODE_TRANSMIT_EOM : MSGCODE_TRANSMIT;
+			cmd[1] = msg->msg[i + 2];
+			err = pulse8_send_and_wait(pulse8, cmd, 2,
+						   MSGCODE_COMMAND_ACCEPTED, 1);
+		}
+	}
+
+	return err;
+}
+
+static int pulse8_received(struct cec_adapter *adap, struct cec_msg *msg)
+{
+	return -ENOMSG;
+}
+
+static const struct cec_adap_ops pulse8_cec_adap_ops = {
+	.adap_enable = pulse8_cec_adap_enable,
+	.adap_log_addr = pulse8_cec_adap_log_addr,
+	.adap_transmit = pulse8_cec_adap_transmit,
+	.received = pulse8_received,
+};
+
+static int pulse8_connect(struct serio *serio, struct serio_driver *drv)
+{
+	u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | CEC_CAP_PHYS_ADDR |
+		CEC_CAP_PASSTHROUGH | CEC_CAP_RC | CEC_CAP_MONITOR_ALL;
+	struct pulse8 *pulse8;
+	int err = -ENOMEM;
+	struct cec_log_addrs log_addrs = {};
+	u16 pa = CEC_PHYS_ADDR_INVALID;
+
+	pulse8 = kzalloc(sizeof(*pulse8), GFP_KERNEL);
+
+	if (!pulse8)
+		return -ENOMEM;
+
+	pulse8->serio = serio;
+	pulse8->adap = cec_allocate_adapter(&pulse8_cec_adap_ops, pulse8,
+		"HDMI CEC", caps, 1);
+	err = PTR_ERR_OR_ZERO(pulse8->adap);
+	if (err < 0)
+		goto free_device;
+
+	pulse8->dev = &serio->dev;
+	serio_set_drvdata(serio, pulse8);
+	INIT_WORK(&pulse8->work, pulse8_irq_work_handler);
+	mutex_init(&pulse8->write_lock);
+	mutex_init(&pulse8->config_lock);
+	pulse8->config_pending = false;
+
+	err = serio_open(serio, drv);
+	if (err)
+		goto delete_adap;
+
+	err = pulse8_setup(pulse8, serio, &log_addrs, &pa);
+	if (err)
+		goto close_serio;
+
+	err = cec_register_adapter(pulse8->adap, &serio->dev);
+	if (err < 0)
+		goto close_serio;
+
+	pulse8->dev = &pulse8->adap->devnode.dev;
+
+	if (persistent_config && pulse8->autonomous) {
+		err = pulse8_apply_persistent_config(pulse8, &log_addrs, pa);
+		if (err)
+			goto close_serio;
+		pulse8->restoring_config = true;
+	}
+
+	INIT_DELAYED_WORK(&pulse8->ping_eeprom_work,
+			  pulse8_ping_eeprom_work_handler);
+	schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
+
+	return 0;
+
+close_serio:
+	serio_close(serio);
+delete_adap:
+	cec_delete_adapter(pulse8->adap);
+	serio_set_drvdata(serio, NULL);
+free_device:
+	kfree(pulse8);
+	return err;
+}
+
+static void pulse8_ping_eeprom_work_handler(struct work_struct *work)
+{
+	struct pulse8 *pulse8 =
+		container_of(work, struct pulse8, ping_eeprom_work.work);
+	u8 cmd;
+
+	schedule_delayed_work(&pulse8->ping_eeprom_work, PING_PERIOD);
+	cmd = MSGCODE_PING;
+	pulse8_send_and_wait(pulse8, &cmd, 1,
+			     MSGCODE_COMMAND_ACCEPTED, 0);
+
+	if (pulse8->vers < 2)
+		return;
+
+	mutex_lock(&pulse8->config_lock);
+	if (pulse8->config_pending && persistent_config) {
+		dev_dbg(pulse8->dev, "writing pending config to EEPROM\n");
+		cmd = MSGCODE_WRITE_EEPROM;
+		if (pulse8_send_and_wait(pulse8, &cmd, 1,
+					 MSGCODE_COMMAND_ACCEPTED, 0))
+			dev_info(pulse8->dev, "failed to write pending config to EEPROM\n");
+		else
+			pulse8->config_pending = false;
+	}
+	mutex_unlock(&pulse8->config_lock);
+}
+
+static struct serio_device_id pulse8_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_PULSE8_CEC,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, pulse8_serio_ids);
+
+static struct serio_driver pulse8_drv = {
+	.driver		= {
+		.name	= "pulse8-cec",
+	},
+	.description	= "Pulse Eight HDMI CEC driver",
+	.id_table	= pulse8_serio_ids,
+	.interrupt	= pulse8_interrupt,
+	.connect	= pulse8_connect,
+	.disconnect	= pulse8_disconnect,
+};
+
+module_serio_driver(pulse8_drv);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-audio.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-audio.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-audio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-audio.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,9 +74,7 @@ void pvr2_msp3400_subdev_update(struct p
 			input = sp->def[hdw->input_val];
 		} else {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "*** WARNING *** subdev msp3400 set_input:"
-				   " Invalid routing scheme (%u)"
-				   " and/or input (%d)",
+				   "*** WARNING *** subdev msp3400 set_input: Invalid routing scheme (%u) and/or input (%d)",
 				   sid, hdw->input_val);
 			return;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,9 +72,7 @@ void pvr2_cs53l32a_subdev_update(struct
 		    (hdw->input_val < 0) ||
 		    (hdw->input_val >= sp->cnt)) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "*** WARNING *** subdev v4l2 set_input:"
-				   " Invalid routing scheme (%u)"
-				   " and/or input (%d)",
+				   "*** WARNING *** subdev v4l2 set_input: Invalid routing scheme (%u) and/or input (%d)",
 				   sid, hdw->input_val);
 			return;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c	2017-02-12 16:03:20.000000000 -0500
@@ -137,9 +137,7 @@ void pvr2_cx25840_subdev_update(struct p
 		    (hdw->input_val < 0) ||
 		    (hdw->input_val >= sp->cnt)) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "*** WARNING *** subdev cx2584x set_input:"
-				   " Invalid routing scheme (%u)"
-				   " and/or input (%d)",
+				   "*** WARNING *** subdev cx2584x set_input: Invalid routing scheme (%u) and/or input (%d)",
 				   sid, hdw->input_val);
 			return;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c	2017-02-12 16:03:20.000000000 -0500
@@ -176,9 +176,7 @@ int pvr2_debugifc_print_status(struct pv
 		pvr2_stream_get_stats(sp, &stats, 0);
 		ccnt = scnprintf(
 			buf,acnt,
-			"Bytes streamed=%u"
-			" URBs: queued=%u idle=%u ready=%u"
-			" processed=%u failed=%u\n",
+			"Bytes streamed=%u URBs: queued=%u idle=%u ready=%u processed=%u failed=%u\n",
 			stats.bytes_processed,
 			stats.buffers_in_queue,
 			stats.buffers_in_idle,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,8 +56,7 @@ static u8 *pvr2_eeprom_fetch(struct pvr2
 	eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
 	if (!eeprom) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Failed to allocate memory"
-			   " required to read eeprom");
+			   "Failed to allocate memory required to read eeprom");
 		return NULL;
 	}
 
@@ -74,8 +73,8 @@ static u8 *pvr2_eeprom_fetch(struct pvr2
 	   strange but it's what they do) */
 	mode16 = (addr & 1);
 	eepromSize = (mode16 ? 4096 : 256);
-	trace_eeprom("Examining %d byte eeprom at location 0x%x"
-		     " using %d bit addressing",eepromSize,addr,
+	trace_eeprom("Examining %d byte eeprom at location 0x%x using %d bit addressing",
+		     eepromSize, addr,
 		     mode16 ? 16 : 8);
 
 	msg[0].addr = addr;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-encoder.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-encoder.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-encoder.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-encoder.c	2017-02-12 16:03:20.000000000 -0500
@@ -188,9 +188,7 @@ static int pvr2_encoder_cmd(void *ctxt,
 	if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
-			"Failed to write cx23416 command"
-			" - too many input arguments"
-			" (was given %u limit %lu)",
+			"Failed to write cx23416 command - too many input arguments (was given %u limit %lu)",
 			arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
 		return -EINVAL;
 	}
@@ -198,9 +196,7 @@ static int pvr2_encoder_cmd(void *ctxt,
 	if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
-			"Failed to write cx23416 command"
-			" - too many return arguments"
-			" (was given %u limit %lu)",
+			"Failed to write cx23416 command - too many return arguments (was given %u limit %lu)",
 			arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
 		return -EINVAL;
 	}
@@ -248,14 +244,12 @@ static int pvr2_encoder_cmd(void *ctxt,
 				retry_flag = !0;
 				pvr2_trace(
 					PVR2_TRACE_ERROR_LEGS,
-					"Encoder timed out waiting for us"
-					"; arranging to retry");
+					"Encoder timed out waiting for us; arranging to retry");
 			} else {
 				pvr2_trace(
 					PVR2_TRACE_ERROR_LEGS,
-					"***WARNING*** device's encoder"
-					" appears to be stuck"
-					" (status=0x%08x)",rdData[0]);
+					"***WARNING*** device's encoder appears to be stuck (status=0x%08x)",
+rdData[0]);
 			}
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
@@ -293,11 +287,7 @@ static int pvr2_encoder_cmd(void *ctxt,
 			}
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
-				"Giving up on command."
-				"  This is normally recovered via a firmware"
-				" reload and re-initialization; concern"
-				" is only warranted if this happens repeatedly"
-				" and rapidly.");
+				"Giving up on command.  This is normally recovered via a firmware reload and re-initialization; concern is only warranted if this happens repeatedly and rapidly.");
 			break;
 		}
 		wrData[0] = 0x7;
@@ -325,9 +315,7 @@ static int pvr2_encoder_vcmd(struct pvr2
 	if (args > ARRAY_SIZE(data)) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
-			"Failed to write cx23416 command"
-			" - too many arguments"
-			" (was given %u limit %lu)",
+			"Failed to write cx23416 command - too many arguments (was given %u limit %lu)",
 			args, (long unsigned) ARRAY_SIZE(data));
 		return -EINVAL;
 	}
@@ -433,8 +421,7 @@ int pvr2_encoder_configure(struct pvr2_h
 {
 	int ret;
 	int val;
-	pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
-		   " (cx2341x module)");
+	pvr2_trace(PVR2_TRACE_ENCODER, "pvr2_encoder_configure (cx2341x module)");
 	hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
 	hdw->enc_ctl_state.width = hdw->res_hor_val;
 	hdw->enc_ctl_state.height = hdw->res_ver_val;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-hdw.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-hdw.c	2016-12-11 17:47:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-hdw.c	2017-02-12 17:35:20.000000000 -0500
@@ -1371,8 +1371,7 @@ static int pvr2_locate_firmware(struct p
 				       fwnames[idx],
 				       &hdw->usb_dev->dev);
 		if (!ret) {
-			trace_firmware("Located %s firmware: %s;"
-				       " uploading...",
+			trace_firmware("Located %s firmware: %s; uploading...",
 				       fwtypename,
 				       fwnames[idx]);
 			return idx;
@@ -1383,21 +1382,17 @@ static int pvr2_locate_firmware(struct p
 		return ret;
 	}
 	pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-		   "***WARNING***"
-		   " Device %s firmware"
-		   " seems to be missing.",
+		   "***WARNING*** Device %s firmware seems to be missing.",
 		   fwtypename);
 	pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-		   "Did you install the pvrusb2 firmware files"
-		   " in their proper location?");
+		   "Did you install the pvrusb2 firmware files in their proper location?");
 	if (fwcount == 1) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 			   "request_firmware unable to locate %s file %s",
 			   fwtypename,fwnames[0]);
 	} else {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "request_firmware unable to locate"
-			   " one of the following %s files:",
+			   "request_firmware unable to locate one of the following %s files:",
 			   fwtypename);
 		for (idx = 0; idx < fwcount; idx++) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
@@ -1431,8 +1426,7 @@ static int pvr2_upload_firmware1(struct
 	if (!hdw->hdw_desc->fx2_firmware.cnt) {
 		hdw->fw1_state = FW1_STATE_OK;
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Connected device type defines"
-			   " no firmware to upload; ignoring firmware");
+			   "Connected device type defines no firmware to upload; ignoring firmware");
 		return -ENOTTY;
 	}
 
@@ -1457,13 +1451,11 @@ static int pvr2_upload_firmware1(struct
 	    (!(hdw->hdw_desc->flag_fx2_16kb && (fwsize == 0x4000)))) {
 		if (hdw->hdw_desc->flag_fx2_16kb) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "Wrong fx2 firmware size"
-				   " (expected 8192 or 16384, got %u)",
+				   "Wrong fx2 firmware size (expected 8192 or 16384, got %u)",
 				   fwsize);
 		} else {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "Wrong fx2 firmware size"
-				   " (expected 8192, got %u)",
+				   "Wrong fx2 firmware size (expected 8192, got %u)",
 				   fwsize);
 		}
 		release_firmware(fw_entry);
@@ -1585,8 +1577,7 @@ int pvr2_upload_firmware2(struct pvr2_hd
 
 	if (fw_len % sizeof(u32)) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "size of %s firmware"
-			   " must be a multiple of %zu bytes",
+			   "size of %s firmware must be a multiple of %zu bytes",
 			   fw_files[fwidx],sizeof(u32));
 		release_firmware(fw_entry);
 		ret = -EINVAL;
@@ -1887,8 +1878,7 @@ static void pvr2_hdw_setup_std(struct pv
 
 	bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
 	pvr2_trace(PVR2_TRACE_STD,
-		   "Supported video standard(s) reported available"
-		   " in hardware: %.*s",
+		   "Supported video standard(s) reported available in hardware: %.*s",
 		   bcnt,buf);
 
 	hdw->std_mask_avail = hdw->std_mask_eeprom;
@@ -1897,8 +1887,7 @@ static void pvr2_hdw_setup_std(struct pv
 	if (std2) {
 		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
 		pvr2_trace(PVR2_TRACE_STD,
-			   "Expanding supported video standards"
-			   " to include: %.*s",
+			   "Expanding supported video standards to include: %.*s",
 			   bcnt,buf);
 		hdw->std_mask_avail |= std2;
 	}
@@ -1917,8 +1906,8 @@ static void pvr2_hdw_setup_std(struct pv
 	if (std3) {
 		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std3);
 		pvr2_trace(PVR2_TRACE_STD,
-			   "Initial video standard"
-			   " (determined by device type): %.*s",bcnt,buf);
+			   "Initial video standard (determined by device type): %.*s",
+			   bcnt, buf);
 		hdw->std_mask_cur = std3;
 		hdw->std_dirty = !0;
 		return;
@@ -1980,8 +1969,7 @@ static void pvr2_hdw_cx25840_vbi_hack(st
 	}
 
 	pvr2_trace(PVR2_TRACE_INIT,
-		   "Module ID %u:"
-		   " Executing cx25840 VBI hack",
+		   "Module ID %u: Executing cx25840 VBI hack",
 		   hdw->decoder_client_id);
 	memset(&fmt, 0, sizeof(fmt));
 	fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
@@ -2007,8 +1995,7 @@ static int pvr2_hdw_load_subdev(struct p
 	fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL;
 	if (!fname) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Module ID %u for device %s has no name?"
-			   "  The driver might have a configuration problem.",
+			   "Module ID %u for device %s has no name?  The driver might have a configuration problem.",
 			   mid,
 			   hdw->hdw_desc->description);
 		return -EINVAL;
@@ -2027,32 +2014,27 @@ static int pvr2_hdw_load_subdev(struct p
 						 ARRAY_SIZE(i2caddr));
 		if (i2ccnt) {
 			pvr2_trace(PVR2_TRACE_INIT,
-				   "Module ID %u:"
-				   " Using default i2c address list",
+				   "Module ID %u: Using default i2c address list",
 				   mid);
 		}
 	}
 
 	if (!i2ccnt) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Module ID %u (%s) for device %s:"
-			   " No i2c addresses."
-			   "  The driver might have a configuration problem.",
+			   "Module ID %u (%s) for device %s: No i2c addresses.	The driver might have a configuration problem.",
 			   mid, fname, hdw->hdw_desc->description);
 		return -EINVAL;
 	}
 
 	if (i2ccnt == 1) {
 		pvr2_trace(PVR2_TRACE_INIT,
-			   "Module ID %u:"
-			   " Setting up with specified i2c address 0x%x",
+			   "Module ID %u: Setting up with specified i2c address 0x%x",
 			   mid, i2caddr[0]);
 		sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
 					 fname, i2caddr[0], NULL);
 	} else {
 		pvr2_trace(PVR2_TRACE_INIT,
-			   "Module ID %u:"
-			   " Setting up with address probe list",
+			   "Module ID %u: Setting up with address probe list",
 			   mid);
 		sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
 					 fname, 0, i2caddr);
@@ -2060,9 +2042,7 @@ static int pvr2_hdw_load_subdev(struct p
 
 	if (!sd) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Module ID %u (%s) for device %s failed to load."
-			   "  Possible missing sub-device kernel module or"
-			   " initialization failure within module.",
+			   "Module ID %u (%s) for device %s failed to load.  Possible missing sub-device kernel module or initialization failure within module.",
 			   mid, fname, hdw->hdw_desc->description);
 		return -EIO;
 	}
@@ -2124,18 +2104,14 @@ static void pvr2_hdw_setup_low(struct pv
 				 == 0);
 			if (reloadFl) {
 				pvr2_trace(PVR2_TRACE_INIT,
-					   "USB endpoint config looks strange"
-					   "; possibly firmware needs to be"
-					   " loaded");
+					   "USB endpoint config looks strange; possibly firmware needs to be loaded");
 			}
 		}
 		if (!reloadFl) {
 			reloadFl = !pvr2_hdw_check_firmware(hdw);
 			if (reloadFl) {
 				pvr2_trace(PVR2_TRACE_INIT,
-					   "Check for FX2 firmware failed"
-					   "; possibly firmware needs to be"
-					   " loaded");
+					   "Check for FX2 firmware failed; possibly firmware needs to be loaded");
 			}
 		}
 		if (reloadFl) {
@@ -2200,8 +2176,7 @@ static void pvr2_hdw_setup_low(struct pv
 		if (!pvr2_hdw_dev_ok(hdw)) return;
 		if (ret < 0) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "Unable to determine location of eeprom,"
-				   " skipping");
+				   "Unable to determine location of eeprom, skipping");
 		} else {
 			hdw->eeprom_addr = ret;
 			pvr2_eeprom_analyze(hdw);
@@ -2254,8 +2229,7 @@ static void pvr2_hdw_setup_low(struct pv
 		idx = get_default_error_tolerance(hdw);
 		if (idx) {
 			pvr2_trace(PVR2_TRACE_INIT,
-				   "pvr2_hdw_setup: video stream %p"
-				   " setting tolerance %u",
+				   "pvr2_hdw_setup: video stream %p setting tolerance %u",
 				   hdw->vid_stream,idx);
 		}
 		pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,
@@ -2285,16 +2259,13 @@ static void pvr2_hdw_setup(struct pvr2_h
 			if (hdw->flag_init_ok) {
 				pvr2_trace(
 					PVR2_TRACE_INFO,
-					"Device initialization"
-					" completed successfully.");
+					"Device initialization completed successfully.");
 				break;
 			}
 			if (hdw->fw1_state == FW1_STATE_RELOAD) {
 				pvr2_trace(
 					PVR2_TRACE_INFO,
-					"Device microcontroller firmware"
-					" (re)loaded; it should now reset"
-					" and reconnect.");
+					"Device microcontroller firmware (re)loaded; it should now reset and reconnect.");
 				break;
 			}
 			pvr2_trace(
@@ -2303,48 +2274,35 @@ static void pvr2_hdw_setup(struct pvr2_h
 			if (hdw->fw1_state == FW1_STATE_MISSING) {
 				pvr2_trace(
 					PVR2_TRACE_ERROR_LEGS,
-					"Giving up since device"
-					" microcontroller firmware"
-					" appears to be missing.");
+					"Giving up since device microcontroller firmware appears to be missing.");
 				break;
 			}
 		}
 		if (hdw->flag_modulefail) {
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
-				"***WARNING*** pvrusb2 driver initialization"
-				" failed due to the failure of one or more"
-				" sub-device kernel modules.");
+				"***WARNING*** pvrusb2 driver initialization failed due to the failure of one or more sub-device kernel modules.");
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
-				"You need to resolve the failing condition"
-				" before this driver can function.  There"
-				" should be some earlier messages giving more"
-				" information about the problem.");
+				"You need to resolve the failing condition before this driver can function.  There should be some earlier messages giving more information about the problem.");
 			break;
 		}
 		if (procreload) {
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
-				"Attempting pvrusb2 recovery by reloading"
-				" primary firmware.");
+				"Attempting pvrusb2 recovery by reloading primary firmware.");
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
-				"If this works, device should disconnect"
-				" and reconnect in a sane state.");
+				"If this works, device should disconnect and reconnect in a sane state.");
 			hdw->fw1_state = FW1_STATE_UNKNOWN;
 			pvr2_upload_firmware1(hdw);
 		} else {
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
-				"***WARNING*** pvrusb2 device hardware"
-				" appears to be jammed"
-				" and I can't clear it.");
+				"***WARNING*** pvrusb2 device hardware appears to be jammed and I can't clear it.");
 			pvr2_trace(
 				PVR2_TRACE_ERROR_LEGS,
-				"You might need to power cycle"
-				" the pvrusb2 device"
-				" in order to recover.");
+				"You might need to power cycle the pvrusb2 device in order to recover.");
 		}
 	} while (0);
 	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);
@@ -2396,12 +2354,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct
 	hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
 
 	if (hdw_desc == NULL) {
-		pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:"
-			   " No device description pointer,"
-			   " unable to continue.");
-		pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type,"
-			   " please contact Mike Isely <isely@pobox.com>"
-			   " to get it included in the driver\n");
+		pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create: No device description pointer, unable to continue.");
+		pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type, please contact Mike Isely <isely@pobox.com> to get it included in the driver\n");
 		goto fail;
 	}
 
@@ -2413,14 +2367,12 @@ struct pvr2_hdw *pvr2_hdw_create(struct
 	if (hdw_desc->flag_is_experimental) {
 		pvr2_trace(PVR2_TRACE_INFO, "**********");
 		pvr2_trace(PVR2_TRACE_INFO,
-			   "WARNING: Support for this device (%s) is"
-			   " experimental.", hdw_desc->description);
+			   "WARNING: Support for this device (%s) is experimental.",
+							      hdw_desc->description);
 		pvr2_trace(PVR2_TRACE_INFO,
-			   "Important functionality might not be"
-			   " entirely working.");
+			   "Important functionality might not be entirely working.");
 		pvr2_trace(PVR2_TRACE_INFO,
-			   "Please consider contacting the driver author to"
-			   " help with further stabilization of the driver.");
+			   "Please consider contacting the driver author to help with further stabilization of the driver.");
 		pvr2_trace(PVR2_TRACE_INFO, "**********");
 	}
 	if (!hdw) goto fail;
@@ -3375,8 +3327,7 @@ static u8 *pvr2_full_eeprom_fetch(struct
 	eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
 	if (!eeprom) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Failed to allocate memory"
-			   " required to read eeprom");
+			   "Failed to allocate memory required to read eeprom");
 		return NULL;
 	}
 
@@ -3393,8 +3344,8 @@ static u8 *pvr2_full_eeprom_fetch(struct
 	   strange but it's what they do) */
 	mode16 = (addr & 1);
 	eepromSize = (mode16 ? EEPROM_SIZE : 256);
-	trace_eeprom("Examining %d byte eeprom at location 0x%x"
-		     " using %d bit addressing",eepromSize,addr,
+	trace_eeprom("Examining %d byte eeprom at location 0x%x using %d bit addressing",
+		     eepromSize, addr,
 		     mode16 ? 16 : 8);
 
 	msg[0].addr = addr;
@@ -3461,8 +3412,8 @@ void pvr2_hdw_cpufw_set_enabled(struct p
 		if (hdw->fw_cpu_flag) {
 			hdw->fw_size = (mode == 1) ? 0x4000 : 0x2000;
 			pvr2_trace(PVR2_TRACE_FIRMWARE,
-				   "Preparing to suck out CPU firmware"
-				   " (size=%u)", hdw->fw_size);
+				   "Preparing to suck out CPU firmware (size=%u)",
+				   hdw->fw_size);
 			hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL);
 			if (!hdw->fw_buffer) {
 				hdw->fw_size = 0;
@@ -3620,21 +3571,18 @@ static int pvr2_send_request_ex(struct p
 	struct timer_list timer;
 	if (!hdw->ctl_lock_held) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Attempted to execute control transfer"
-			   " without lock!!");
+			   "Attempted to execute control transfer without lock!!");
 		return -EDEADLK;
 	}
 	if (!hdw->flag_ok && !probe_fl) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Attempted to execute control transfer"
-			   " when device not ok");
+			   "Attempted to execute control transfer when device not ok");
 		return -EIO;
 	}
 	if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) {
 		if (!probe_fl) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "Attempted to execute control transfer"
-				   " when USB is disconnected");
+				   "Attempted to execute control transfer when USB is disconnected");
 		}
 		return -ENOTTY;
 	}
@@ -3645,16 +3593,14 @@ static int pvr2_send_request_ex(struct p
 	if (write_len > PVR2_CTL_BUFFSIZE) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
-			"Attempted to execute %d byte"
-			" control-write transfer (limit=%d)",
+			"Attempted to execute %d byte control-write transfer (limit=%d)",
 			write_len,PVR2_CTL_BUFFSIZE);
 		return -EINVAL;
 	}
 	if (read_len > PVR2_CTL_BUFFSIZE) {
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
-			"Attempted to execute %d byte"
-			" control-read transfer (limit=%d)",
+			"Attempted to execute %d byte control-read transfer (limit=%d)",
 			write_len,PVR2_CTL_BUFFSIZE);
 		return -EINVAL;
 	}
@@ -3703,8 +3649,8 @@ static int pvr2_send_request_ex(struct p
 		status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL);
 		if (status < 0) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "Failed to submit write-control"
-				   " URB status=%d",status);
+				   "Failed to submit write-control URB status=%d",
+status);
 			hdw->ctl_write_pend_flag = 0;
 			goto done;
 		}
@@ -3727,8 +3673,8 @@ static int pvr2_send_request_ex(struct p
 		status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL);
 		if (status < 0) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "Failed to submit read-control"
-				   " URB status=%d",status);
+				   "Failed to submit read-control URB status=%d",
+status);
 			hdw->ctl_read_pend_flag = 0;
 			goto done;
 		}
@@ -3770,8 +3716,7 @@ static int pvr2_send_request_ex(struct p
 			status = hdw->ctl_write_urb->status;
 			if (!probe_fl) {
 				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-					   "control-write URB failure,"
-					   " status=%d",
+					   "control-write URB failure, status=%d",
 					   status);
 			}
 			goto done;
@@ -3781,8 +3726,7 @@ static int pvr2_send_request_ex(struct p
 			status = -EIO;
 			if (!probe_fl) {
 				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-					   "control-write URB short,"
-					   " expected=%d got=%d",
+					   "control-write URB short, expected=%d got=%d",
 					   write_len,
 					   hdw->ctl_write_urb->actual_length);
 			}
@@ -3800,8 +3744,7 @@ static int pvr2_send_request_ex(struct p
 			status = hdw->ctl_read_urb->status;
 			if (!probe_fl) {
 				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-					   "control-read URB failure,"
-					   " status=%d",
+					   "control-read URB failure, status=%d",
 					   status);
 			}
 			goto done;
@@ -3811,8 +3754,7 @@ static int pvr2_send_request_ex(struct p
 			status = -EIO;
 			if (!probe_fl) {
 				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-					   "control-read URB short,"
-					   " expected=%d got=%d",
+					   "control-read URB short, expected=%d got=%d",
 					   read_len,
 					   hdw->ctl_read_urb->actual_length);
 			}
@@ -4799,9 +4741,7 @@ static unsigned int pvr2_hdw_report_unlo
 				      0);
 		return scnprintf(
 			buf,acnt,
-			"Bytes streamed=%u"
-			" URBs: queued=%u idle=%u ready=%u"
-			" processed=%u failed=%u",
+			"Bytes streamed=%u URBs: queued=%u idle=%u ready=%u processed=%u failed=%u",
 			stats.bytes_processed,
 			stats.buffers_in_queue,
 			stats.buffers_in_idle,
@@ -5013,8 +4953,7 @@ int pvr2_hdw_gpio_chg_dir(struct pvr2_hd
 		if (ret) return ret;
 		nval = (cval & ~msk) | (val & msk);
 		pvr2_trace(PVR2_TRACE_GPIO,
-			   "GPIO direction changing 0x%x:0x%x"
-			   " from 0x%x to 0x%x",
+			   "GPIO direction changing 0x%x:0x%x from 0x%x to 0x%x",
 			   msk,val,cval,nval);
 	} else {
 		nval = val;
@@ -5057,9 +4996,7 @@ void pvr2_hdw_status_poll(struct pvr2_hd
 	   now.  (Of course, no sub-drivers seem to implement it either.
 	   But now it's a a chicken and egg problem...) */
 	v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, vtp);
-	pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll"
-		   " type=%u strength=%u audio=0x%x cap=0x%x"
-		   " low=%u hi=%u",
+	pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll type=%u strength=%u audio=0x%x cap=0x%x low=%u hi=%u",
 		   vtp->type,
 		   vtp->signal, vtp->rxsubchans, vtp->capability,
 		   vtp->rangelow, vtp->rangehigh);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,8 +62,7 @@ static int pvr2_i2c_write(struct pvr2_hd
 	if (!data) length = 0;
 	if (length > (sizeof(hdw->cmd_buffer) - 3)) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Killing an I2C write to %u that is too large"
-			   " (desired=%u limit=%u)",
+			   "Killing an I2C write to %u that is too large (desired=%u limit=%u)",
 			   i2c_addr,
 			   length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3));
 		return -ENOTSUPP;
@@ -90,8 +89,7 @@ static int pvr2_i2c_write(struct pvr2_hd
 		if (hdw->cmd_buffer[0] != 8) {
 			ret = -EIO;
 			if (hdw->cmd_buffer[0] != 7) {
-				trace_i2c("unexpected status"
-					  " from i2_write[%d]: %d",
+				trace_i2c("unexpected status from i2_write[%d]: %d",
 					  i2c_addr,hdw->cmd_buffer[0]);
 			}
 		}
@@ -116,16 +114,14 @@ static int pvr2_i2c_read(struct pvr2_hdw
 	if (!data) dlen = 0;
 	if (dlen > (sizeof(hdw->cmd_buffer) - 4)) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Killing an I2C read to %u that has wlen too large"
-			   " (desired=%u limit=%u)",
+			   "Killing an I2C read to %u that has wlen too large (desired=%u limit=%u)",
 			   i2c_addr,
 			   dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4));
 		return -ENOTSUPP;
 	}
 	if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "Killing an I2C read to %u that has rlen too large"
-			   " (desired=%u limit=%u)",
+			   "Killing an I2C read to %u that has rlen too large (desired=%u limit=%u)",
 			   i2c_addr,
 			   rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1));
 		return -ENOTSUPP;
@@ -154,8 +150,7 @@ static int pvr2_i2c_read(struct pvr2_hdw
 		if (hdw->cmd_buffer[0] != 8) {
 			ret = -EIO;
 			if (hdw->cmd_buffer[0] != 7) {
-				trace_i2c("unexpected status"
-					  " from i2_read[%d]: %d",
+				trace_i2c("unexpected status from i2_read[%d]: %d",
 					  i2c_addr,hdw->cmd_buffer[0]);
 			}
 		}
@@ -352,13 +347,11 @@ static int i2c_hack_cx25840(struct pvr2_
 
 	if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "WARNING: Detected a wedged cx25840 chip;"
-			   " the device will not work.");
+			   "WARNING: Detected a wedged cx25840 chip; the device will not work.");
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 			   "WARNING: Try power cycling the pvrusb2 device.");
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-			   "WARNING: Disabling further access to the device"
-			   " to prevent other foul-ups.");
+			   "WARNING: Disabling further access to the device to prevent other foul-ups.");
 		// This blocks all further communication with the part.
 		hdw->i2c_func[0x44] = NULL;
 		pvr2_hdw_render_useless(hdw);
@@ -444,8 +437,7 @@ static int pvr2_i2c_xfer(struct i2c_adap
 		}
 	} else if (num == 2) {
 		if (msgs[0].addr != msgs[1].addr) {
-			trace_i2c("i2c refusing 2 phase transfer with"
-				  " conflicting target addresses");
+			trace_i2c("i2c refusing 2 phase transfer with conflicting target addresses");
 			ret = -ENOTSUPP;
 			goto done;
 		}
@@ -477,8 +469,7 @@ static int pvr2_i2c_xfer(struct i2c_adap
 			ret = 2;
 			goto done;
 		} else {
-			trace_i2c("i2c refusing complex transfer"
-				  " read0=%d read1=%d",
+			trace_i2c("i2c refusing complex transfer read0=%d read1=%d",
 				  (msgs[0].flags & I2C_M_RD),
 				  (msgs[1].flags & I2C_M_RD));
 		}
@@ -492,8 +483,7 @@ static int pvr2_i2c_xfer(struct i2c_adap
 		for (idx = 0; idx < num; idx++) {
 			cnt = msgs[idx].len;
 			printk(KERN_INFO
-			       "pvrusb2 i2c xfer %u/%u:"
-			       " addr=0x%x len=%d %s",
+			       "pvrusb2 i2c xfer %u/%u: addr=0x%x len=%d %s",
 			       idx+1,num,
 			       msgs[idx].addr,
 			       cnt,
@@ -501,18 +491,18 @@ static int pvr2_i2c_xfer(struct i2c_adap
 				"read" : "write"));
 			if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
 				if (cnt > 8) cnt = 8;
-				printk(" [");
+				printk(KERN_CONT " [");
 				for (offs = 0; offs < (cnt>8?8:cnt); offs++) {
-					if (offs) printk(" ");
-					printk("%02x",msgs[idx].buf[offs]);
+					if (offs) printk(KERN_CONT " ");
+					printk(KERN_CONT "%02x",msgs[idx].buf[offs]);
 				}
-				if (offs < cnt) printk(" ...");
-				printk("]");
+				if (offs < cnt) printk(KERN_CONT " ...");
+				printk(KERN_CONT "]");
 			}
 			if (idx+1 == num) {
-				printk(" result=%d",ret);
+				printk(KERN_CONT " result=%d",ret);
 			}
-			printk("\n");
+			printk(KERN_CONT "\n");
 		}
 		if (!num) {
 			printk(KERN_INFO
@@ -668,8 +658,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw
 		   the emulated IR receiver. */
 		if (do_i2c_probe(hdw, 0x71)) {
 			pvr2_trace(PVR2_TRACE_INFO,
-				   "Device has newer IR hardware;"
-				   " disabling unneeded virtual IR device");
+				   "Device has newer IR hardware; disabling unneeded virtual IR device");
 			hdw->i2c_func[0x18] = NULL;
 			/* Remember that this is a different device... */
 			hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-io.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-io.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-io.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-io.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,8 +113,7 @@ static const char *pvr2_buffer_state_dec
 static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
 {
 	pvr2_trace(PVR2_TRACE_INFO,
-		   "buffer%s%s %p state=%s id=%d status=%d"
-		   " stream=%p purb=%p sig=0x%x",
+		   "buffer%s%s %p state=%s id=%d status=%d stream=%p purb=%p sig=0x%x",
 		   (msg ? " " : ""),
 		   (msg ? msg : ""),
 		   bp,
@@ -156,8 +155,7 @@ static void pvr2_buffer_remove(struct pv
 	(*cnt)--;
 	(*bcnt) -= ccnt;
 	pvr2_trace(PVR2_TRACE_BUF_FLOW,
-		   "/*---TRACE_FLOW---*/"
-		   " bufferPool     %8s dec cap=%07d cnt=%02d",
+		   "/*---TRACE_FLOW---*/ bufferPool	%8s dec cap=%07d cnt=%02d",
 		   pvr2_buffer_state_decode(bp->state),*bcnt,*cnt);
 	bp->state = pvr2_buffer_state_none;
 }
@@ -198,8 +196,7 @@ static int pvr2_buffer_set_ready(struct
 	(sp->r_count)++;
 	sp->r_bcount += bp->used_count;
 	pvr2_trace(PVR2_TRACE_BUF_FLOW,
-		   "/*---TRACE_FLOW---*/"
-		   " bufferPool     %8s inc cap=%07d cnt=%02d",
+		   "/*---TRACE_FLOW---*/ bufferPool	%8s inc cap=%07d cnt=%02d",
 		   pvr2_buffer_state_decode(bp->state),
 		   sp->r_bcount,sp->r_count);
 	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
@@ -224,8 +221,7 @@ static void pvr2_buffer_set_idle(struct
 	(sp->i_count)++;
 	sp->i_bcount += bp->max_count;
 	pvr2_trace(PVR2_TRACE_BUF_FLOW,
-		   "/*---TRACE_FLOW---*/"
-		   " bufferPool     %8s inc cap=%07d cnt=%02d",
+		   "/*---TRACE_FLOW---*/ bufferPool	%8s inc cap=%07d cnt=%02d",
 		   pvr2_buffer_state_decode(bp->state),
 		   sp->i_bcount,sp->i_count);
 	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
@@ -249,8 +245,7 @@ static void pvr2_buffer_set_queued(struc
 	(sp->q_count)++;
 	sp->q_bcount += bp->max_count;
 	pvr2_trace(PVR2_TRACE_BUF_FLOW,
-		   "/*---TRACE_FLOW---*/"
-		   " bufferPool     %8s inc cap=%07d cnt=%02d",
+		   "/*---TRACE_FLOW---*/ bufferPool	%8s inc cap=%07d cnt=%02d",
 		   pvr2_buffer_state_decode(bp->state),
 		   sp->q_bcount,sp->q_count);
 	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
@@ -293,8 +288,8 @@ static void pvr2_buffer_done(struct pvr2
 	bp->signature = 0;
 	bp->stream = NULL;
 	usb_free_urb(bp->purb);
-	pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
-		   " bufferDone     %p",bp);
+	pvr2_trace(PVR2_TRACE_BUF_POOL, "/*---TRACE_FLOW---*/ bufferDone     %p",
+		   bp);
 }
 
 static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
@@ -306,8 +301,7 @@ static int pvr2_stream_buffer_count(stru
 	if (cnt == sp->buffer_total_count) return 0;
 
 	pvr2_trace(PVR2_TRACE_BUF_POOL,
-		   "/*---TRACE_FLOW---*/ poolResize    "
-		   " stream=%p cur=%d adj=%+d",
+		   "/*---TRACE_FLOW---*/ poolResize	stream=%p cur=%d adj=%+d",
 		   sp,
 		   sp->buffer_total_count,
 		   cnt-sp->buffer_total_count);
@@ -374,8 +368,7 @@ static int pvr2_stream_achieve_buffer_co
 	if (sp->buffer_total_count == sp->buffer_target_count) return 0;
 
 	pvr2_trace(PVR2_TRACE_BUF_POOL,
-		   "/*---TRACE_FLOW---*/"
-		   " poolCheck      stream=%p cur=%d tgt=%d",
+		   "/*---TRACE_FLOW---*/ poolCheck	stream=%p cur=%d tgt=%d",
 		   sp,sp->buffer_total_count,sp->buffer_target_count);
 
 	if (sp->buffer_total_count < sp->buffer_target_count) {
@@ -454,8 +447,8 @@ static void buffer_complete(struct urb *
 		bp->used_count = urb->actual_length;
 		if (sp->fail_count) {
 			pvr2_trace(PVR2_TRACE_TOLERANCE,
-				   "stream %p transfer ok"
-				   " - fail count reset",sp);
+				   "stream %p transfer ok - fail count reset",
+				   sp);
 			sp->fail_count = 0;
 		}
 	} else if (sp->fail_count < sp->fail_tolerance) {
@@ -464,8 +457,7 @@ static void buffer_complete(struct urb *
 		(sp->fail_count)++;
 		(sp->buffers_failed)++;
 		pvr2_trace(PVR2_TRACE_TOLERANCE,
-			   "stream %p ignoring error %d"
-			   " - fail count increased to %u",
+			   "stream %p ignoring error %d - fail count increased to %u",
 			   sp,urb->status,sp->fail_count);
 	} else {
 		(sp->buffers_failed)++;
@@ -666,8 +658,7 @@ int pvr2_buffer_set_buffer(struct pvr2_b
 			bp->max_count = cnt;
 			bp->stream->i_bcount += bp->max_count;
 			pvr2_trace(PVR2_TRACE_BUF_FLOW,
-				   "/*---TRACE_FLOW---*/ bufferPool    "
-				   " %8s cap cap=%07d cnt=%02d",
+				   "/*---TRACE_FLOW---*/ bufferPool	%8s cap cap=%07d cnt=%02d",
 				   pvr2_buffer_state_decode(
 					   pvr2_buffer_state_idle),
 				   bp->stream->i_bcount,bp->stream->i_count);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-ioread.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-ioread.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-ioread.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-ioread.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define BUFFER_COUNT 32
 #define BUFFER_SIZE PAGE_ALIGN(0x4000)
@@ -169,9 +169,7 @@ static int pvr2_ioread_start(struct pvr2
 		stat = pvr2_buffer_queue(bp);
 		if (stat < 0) {
 			pvr2_trace(PVR2_TRACE_DATA_FLOW,
-				   "/*---TRACE_READ---*/"
-				   " pvr2_ioread_start id=%p"
-				   " error=%d",
+				   "/*---TRACE_READ---*/ pvr2_ioread_start id=%p error=%d",
 				   cp,stat);
 			pvr2_ioread_stop(cp);
 			return stat;
@@ -209,8 +207,8 @@ int pvr2_ioread_setup(struct pvr2_ioread
 	do {
 		if (cp->stream) {
 			pvr2_trace(PVR2_TRACE_START_STOP,
-				   "/*---TRACE_READ---*/"
-				   " pvr2_ioread_setup (tear-down) id=%p",cp);
+				   "/*---TRACE_READ---*/ pvr2_ioread_setup (tear-down) id=%p",
+				   cp);
 			pvr2_ioread_stop(cp);
 			pvr2_stream_kill(cp->stream);
 			if (pvr2_stream_get_buffer_count(cp->stream)) {
@@ -220,8 +218,8 @@ int pvr2_ioread_setup(struct pvr2_ioread
 		}
 		if (sp) {
 			pvr2_trace(PVR2_TRACE_START_STOP,
-				   "/*---TRACE_READ---*/"
-				   " pvr2_ioread_setup (setup) id=%p",cp);
+				   "/*---TRACE_READ---*/ pvr2_ioread_setup (setup) id=%p",
+				   cp);
 			pvr2_stream_kill(sp);
 			ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT);
 			if (ret < 0) {
@@ -270,9 +268,7 @@ static int pvr2_ioread_get_buffer(struct
 			if (stat < 0) {
 				// Streaming error...
 				pvr2_trace(PVR2_TRACE_DATA_FLOW,
-					   "/*---TRACE_READ---*/"
-					   " pvr2_ioread_read id=%p"
-					   " queue_error=%d",
+					   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p queue_error=%d",
 					   cp,stat);
 				pvr2_ioread_stop(cp);
 				return 0;
@@ -292,9 +288,7 @@ static int pvr2_ioread_get_buffer(struct
 			if (stat < 0) {
 				// Streaming error...
 				pvr2_trace(PVR2_TRACE_DATA_FLOW,
-					   "/*---TRACE_READ---*/"
-					   " pvr2_ioread_read id=%p"
-					   " buffer_error=%d",
+					   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p buffer_error=%d",
 					   cp,stat);
 				pvr2_ioread_stop(cp);
 				// Give up.
@@ -347,8 +341,7 @@ static void pvr2_ioread_filter(struct pv
 		if (cp->sync_buf_offs >= cp->sync_key_len) {
 			cp->sync_trashed_count -= cp->sync_key_len;
 			pvr2_trace(PVR2_TRACE_DATA_FLOW,
-				   "/*---TRACE_READ---*/"
-				   " sync_state <== 2 (skipped %u bytes)",
+				   "/*---TRACE_READ---*/ sync_state <== 2 (skipped %u bytes)",
 				   cp->sync_trashed_count);
 			cp->sync_state = 2;
 			cp->sync_buf_offs = 0;
@@ -358,8 +351,7 @@ static void pvr2_ioread_filter(struct pv
 		if (cp->c_data_offs < cp->c_data_len) {
 			// Sanity check - should NEVER get here
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "ERROR: pvr2_ioread filter sync problem"
-				   " len=%u offs=%u",
+				   "ERROR: pvr2_ioread filter sync problem len=%u offs=%u",
 				   cp->c_data_len,cp->c_data_offs);
 			// Get out so we don't get stuck in an infinite
 			// loop.
@@ -418,8 +410,8 @@ int pvr2_ioread_read(struct pvr2_ioread
 
 	if (!cnt) {
 		pvr2_trace(PVR2_TRACE_TRAP,
-			   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p"
-			   " ZERO Request? Returning zero.",cp);
+			   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p ZERO Request? Returning zero.",
+cp);
 		return 0;
 	}
 
@@ -477,8 +469,7 @@ int pvr2_ioread_read(struct pvr2_ioread
 					// Consumed entire key; switch mode
 					// to normal.
 					pvr2_trace(PVR2_TRACE_DATA_FLOW,
-						   "/*---TRACE_READ---*/"
-						   " sync_state <== 0");
+						   "/*---TRACE_READ---*/ sync_state <== 0");
 					cp->sync_state = 0;
 				}
 			} else {
@@ -502,8 +493,7 @@ int pvr2_ioread_read(struct pvr2_ioread
 	}
 
 	pvr2_trace(PVR2_TRACE_DATA_FLOW,
-		   "/*---TRACE_READ---*/ pvr2_ioread_read"
-		   " id=%p request=%d result=%d",
+		   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p request=%d result=%d",
 		   cp,req_cnt,ret);
 	return ret;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-std.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-std.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-std.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-std.c	2017-02-12 16:03:20.000000000 -0500
@@ -357,8 +357,7 @@ struct v4l2_standard *pvr2_std_create_en
 		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
 		pvr2_trace(
 			PVR2_TRACE_ERROR_LEGS,
-			"WARNING:"
-			" Failed to classify the following standard(s): %.*s",
+			"WARNING: Failed to classify the following standard(s): %.*s",
 			bcnt,buf);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -116,7 +116,6 @@ static ssize_t show_type(struct device *
 	}
 	pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
 			 cip->chptr, cip->ctl_id, name);
-	if (!name) return -EINVAL;
 	return scnprintf(buf, PAGE_SIZE, "%s\n", name);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c	2017-02-12 16:03:20.000000000 -0500
@@ -949,8 +949,8 @@ static long pvr2_v4l2_ioctl(struct file
 	if (ret < 0) {
 		if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
 			pvr2_trace(PVR2_TRACE_V4LIOCTL,
-				   "pvr2_v4l2_do_ioctl failure, ret=%ld"
-				   " command was:", ret);
+				   "pvr2_v4l2_do_ioctl failure, ret=%ld command was:",
+ret);
 			v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
 		}
 	} else {
@@ -1254,8 +1254,7 @@ static void pvr2_v4l2_dev_init(struct pv
 		nr_ptr = video_nr;
 		if (!dip->stream) {
 			pr_err(KBUILD_MODNAME
-				": Failed to set up pvrusb2 v4l video dev"
-				" due to missing stream instance\n");
+				": Failed to set up pvrusb2 v4l video dev due to missing stream instance\n");
 			return;
 		}
 		break;
@@ -1272,8 +1271,7 @@ static void pvr2_v4l2_dev_init(struct pv
 		break;
 	default:
 		/* Bail out (this should be impossible) */
-		pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
-		    " due to unrecognized config\n");
+		pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev due to unrecognized config\n");
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c	2017-02-12 16:03:20.000000000 -0500
@@ -91,9 +91,7 @@ void pvr2_saa7115_subdev_update(struct p
 		    (hdw->input_val < 0) ||
 		    (hdw->input_val >= sp->cnt)) {
 			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-				   "*** WARNING *** subdev v4l2 set_input:"
-				   " Invalid routing scheme (%u)"
-				   " and/or input (%d)",
+				   "*** WARNING *** subdev v4l2 set_input: Invalid routing scheme (%u) and/or input (%d)",
 				   sid, hdw->input_val);
 			return;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c
--- linux-libre-4.9-gnu/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pvrusb2/pvrusb2-wm8775.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,8 +49,7 @@ void pvr2_wm8775_subdev_update(struct pv
 			input = 2;
 			break;
 		}
-		pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775"
-			   " set_input(val=%d route=0x%x)",
+		pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775 set_input(val=%d route=0x%x)",
 			   hdw->input_val, input);
 
 		sd->ops->audio->s_routing(sd, input, 0, 0);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pwc/pwc-ctrl.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pwc/pwc-ctrl.c
--- linux-libre-4.9-gnu/drivers/media/usb/pwc/pwc-ctrl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pwc/pwc-ctrl.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,7 +39,7 @@
 /* Control functions for the cam; brightness, contrast, video mode, etc. */
 
 #ifdef __KERNEL__
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #endif
 #include <asm/errno.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pwc/pwc-if.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pwc/pwc-if.c
--- linux-libre-4.9-gnu/drivers/media/usb/pwc/pwc-if.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pwc/pwc-if.c	2017-02-12 16:03:20.000000000 -0500
@@ -238,8 +238,8 @@ static void pwc_frame_complete(struct pw
 	} else {
 		/* Check for underflow first */
 		if (fbuf->filled < pdev->frame_total_size) {
-			PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
-				       " discarded.\n", fbuf->filled);
+			PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes); discarded.\n",
+				       fbuf->filled);
 		} else {
 			fbuf->vb.field = V4L2_FIELD_NONE;
 			fbuf->vb.sequence = pdev->vframe_count;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/pwc/pwc-v4l.c linux-libre-4.10-rc8-gnu/drivers/media/usb/pwc/pwc-v4l.c
--- linux-libre-4.9-gnu/drivers/media/usb/pwc/pwc-v4l.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/pwc/pwc-v4l.c	2017-02-12 16:03:20.000000000 -0500
@@ -406,8 +406,7 @@ static void pwc_vidioc_fill_fmt(struct v
 	f->fmt.pix.bytesperline = f->fmt.pix.width;
 	f->fmt.pix.sizeimage	= f->fmt.pix.height * f->fmt.pix.width * 3 / 2;
 	f->fmt.pix.colorspace	= V4L2_COLORSPACE_SRGB;
-	PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
-			"width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
+	PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
 			f->fmt.pix.width,
 			f->fmt.pix.height,
 			f->fmt.pix.bytesperline,
@@ -473,8 +472,7 @@ static int pwc_s_fmt_vid_cap(struct file
 
 	pixelformat = f->fmt.pix.pixelformat;
 
-	PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
-			"format=%c%c%c%c\n",
+	PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d format=%c%c%c%c\n",
 			f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
 			(pixelformat)&255,
 			(pixelformat>>8)&255,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/siano/smsusb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/siano/smsusb.c
--- linux-libre-4.9-gnu/drivers/media/usb/siano/smsusb.c	2016-12-11 17:46:49.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/siano/smsusb.c	2017-02-12 17:33:30.000000000 -0500
@@ -604,8 +604,8 @@ static int smsusb_resume(struct usb_inte
 				       intf->cur_altsetting->desc.
 				       bInterfaceNumber, 0);
 		if (rc < 0) {
-			printk(KERN_INFO "%s usb_set_interface failed, "
-			       "rc %d\n", __func__, rc);
+			printk(KERN_INFO "%s usb_set_interface failed, rc %d\n",
+			       __func__, rc);
 			return rc;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/stkwebcam/stk-sensor.c linux-libre-4.10-rc8-gnu/drivers/media/usb/stkwebcam/stk-sensor.c
--- linux-libre-4.9-gnu/drivers/media/usb/stkwebcam/stk-sensor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/stkwebcam/stk-sensor.c	2017-02-12 16:03:20.000000000 -0500
@@ -228,7 +228,7 @@
 static int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val)
 {
 	int i = 0;
-	int tmpval = 0;
+	u8 tmpval = 0;
 
 	if (stk_camera_write_reg(dev, STK_IIC_TX_INDEX, reg))
 		return 1;
@@ -253,7 +253,7 @@ static int stk_sensor_outb(struct stk_ca
 static int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val)
 {
 	int i = 0;
-	int tmpval = 0;
+	u8 tmpval = 0;
 
 	if (stk_camera_write_reg(dev, STK_IIC_RX_INDEX, reg))
 		return 1;
@@ -274,7 +274,7 @@ static int stk_sensor_inb(struct stk_cam
 	if (stk_camera_read_reg(dev, STK_IIC_RX_VALUE, &tmpval))
 		return 1;
 
-	*val = (u8) tmpval;
+	*val = tmpval;
 	return 0;
 }
 
@@ -391,8 +391,8 @@ int stk_sensor_init(struct stk_camera *d
 	}
 	stk_sensor_write_regvals(dev, ov_initvals);
 	msleep(10);
-	STK_INFO("OmniVision sensor detected, id %02X%02X"
-		" at address %x\n", idh, idl, SENSOR_ADDRESS);
+	STK_INFO("OmniVision sensor detected, id %02X%02X at address %x\n",
+		 idh, idl, SENSOR_ADDRESS);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/stkwebcam/stk-webcam.c linux-libre-4.10-rc8-gnu/drivers/media/usb/stkwebcam/stk-webcam.c
--- linux-libre-4.9-gnu/drivers/media/usb/stkwebcam/stk-webcam.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/stkwebcam/stk-webcam.c	2017-02-12 16:03:20.000000000 -0500
@@ -144,7 +144,7 @@ int stk_camera_write_reg(struct stk_came
 		return 0;
 }
 
-int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value)
+int stk_camera_read_reg(struct stk_camera *dev, u16 index, u8 *value)
 {
 	struct usb_device *udev = dev->udev;
 	unsigned char *buf;
@@ -163,7 +163,7 @@ int stk_camera_read_reg(struct stk_camer
 			sizeof(u8),
 			500);
 	if (ret >= 0)
-		memcpy(value, buf, sizeof(u8));
+		*value = *buf;
 
 	kfree(buf);
 	return ret;
@@ -171,9 +171,10 @@ int stk_camera_read_reg(struct stk_camer
 
 static int stk_start_stream(struct stk_camera *dev)
 {
-	int value;
+	u8 value;
 	int i, ret;
-	int value_116, value_117;
+	u8 value_116, value_117;
+
 
 	if (!is_present(dev))
 		return -ENODEV;
@@ -213,7 +214,7 @@ static int stk_start_stream(struct stk_c
 
 static int stk_stop_stream(struct stk_camera *dev)
 {
-	int value;
+	u8 value;
 	int i;
 	if (is_present(dev)) {
 		stk_camera_read_reg(dev, 0x0100, &value);
@@ -372,8 +373,7 @@ static void stk_isoc_handler(struct urb
 			if (fb->v4lbuf.bytesused != 0
 				&& fb->v4lbuf.bytesused != dev->frame_size) {
 				(void) (printk_ratelimit() &&
-				STK_ERROR("frame %d, "
-					"bytesused=%d, skipping\n",
+				STK_ERROR("frame %d, bytesused=%d, skipping\n",
 					i, fb->v4lbuf.bytesused));
 				fb->v4lbuf.bytesused = 0;
 				fill = fb->buffer;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/stkwebcam/stk-webcam.h linux-libre-4.10-rc8-gnu/drivers/media/usb/stkwebcam/stk-webcam.h
--- linux-libre-4.9-gnu/drivers/media/usb/stkwebcam/stk-webcam.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/stkwebcam/stk-webcam.h	2017-02-12 16:03:20.000000000 -0500
@@ -129,7 +129,7 @@ struct stk_camera {
 #define vdev_to_camera(d) container_of(d, struct stk_camera, vdev)
 
 int stk_camera_write_reg(struct stk_camera *, u16, u8);
-int stk_camera_read_reg(struct stk_camera *, u16, int *);
+int stk_camera_read_reg(struct stk_camera *, u16, u8 *);
 
 int stk_sensor_init(struct stk_camera *);
 int stk_sensor_configure(struct stk_camera *);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-alsa.c linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-alsa.c
--- linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-alsa.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-alsa.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,9 +58,7 @@ MODULE_PARM_DESC(index, "Index value for
 MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards");
 MODULE_AUTHOR("Mauro Carvalho Chehab");
 MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Trident,tm5600},"
-			"{{Trident,tm6000},"
-			"{{Trident,tm6010}");
+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");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -602,8 +602,8 @@ int tm6000_init(struct tm6000_core *dev)
 	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,
+			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;
 		}
@@ -761,9 +761,8 @@ int tm6000_tvaudio_set_mute(struct tm600
 		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);
+			printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has SIF audio inputs. Please check the %s configuration.\n",
+			       dev->name);
 			return -EINVAL;
 		}
 		break;
@@ -822,9 +821,8 @@ void tm6000_set_volume(struct tm6000_cor
 		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);
+			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:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-dvb.c linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-dvb.c
--- linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-dvb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-dvb.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,9 +35,7 @@ MODULE_DESCRIPTION("DVB driver extension
 MODULE_AUTHOR("Mauro Carvalho Chehab");
 MODULE_LICENSE("GPL");
 
-MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},"
-			"{{Trident, tm6000},"
-			"{{Trident, tm6010}");
+MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},{{Trident, tm6000},{{Trident, tm6010}");
 
 static int debug;
 
@@ -292,13 +290,11 @@ static int register_dvb(struct tm6000_co
 			}
 
 			if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
-				printk(KERN_ERR "tm6000: couldn't register "
-						"frontend (xc3028)\n");
+				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");
+			printk(KERN_INFO "tm6000: XC2028/3028 asked to be attached to frontend!\n");
 			break;
 			}
 		case TUNER_XC5000: {
@@ -315,13 +311,11 @@ static int register_dvb(struct tm6000_co
 			}
 
 			if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
-				printk(KERN_ERR "tm6000: couldn't register "
-						"frontend (xc5000)\n");
+				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");
+			printk(KERN_INFO "tm6000: XC5000 asked to be attached to frontend!\n");
 			break;
 			}
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-i2c.c linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-i2c.c
--- linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -173,8 +173,7 @@ static int tm6000_i2c_xfer(struct i2c_ad
 			 * 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");
+			i2c_dprintk(2, " read without preceding write not supported");
 			rc = -EOPNOTSUPP;
 			goto err;
 		} else if (i + 1 < num && msgs[i].len <= 2 &&
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-stds.c linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-stds.c
--- linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-stds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-stds.c	2017-02-12 16:03:20.000000000 -0500
@@ -464,8 +464,7 @@ static int tm6000_load_std(struct tm6000
 	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",
+			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;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-video.c linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-video.c
--- linux-libre-4.9-gnu/drivers/media/usb/tm6000/tm6000-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/tm6000/tm6000-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -615,8 +615,7 @@ static int tm6000_prepare_isoc(struct tm
 		return -ENOMEM;
 	}
 
-	dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets"
-		    " (%d bytes) of %d bytes each to handle %u size\n",
+	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);
 
@@ -939,8 +938,8 @@ static int vidioc_try_fmt_vid_cap(struct
 
 	fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 	if (NULL == fmt) {
-		dprintk(dev, 2, "Fourcc format (0x%08x)"
-				" invalid.\n", f->fmt.pix.pixelformat);
+		dprintk(dev, 2, "Fourcc format (0x%08x) invalid.\n",
+			f->fmt.pix.pixelformat);
 		return -EINVAL;
 	}
 
@@ -1366,14 +1365,13 @@ static int __tm6000_open(struct file *fi
 	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",
+	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));
+	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);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c linux-libre-4.10-rc8-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c
--- linux-libre-4.9-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c	2016-12-11 17:46:53.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c	2017-02-12 17:33:36.000000000 -0500
@@ -767,8 +767,7 @@ static void ttusb_iso_irq(struct urb *ur
 		for (i = 0; i < urb->number_of_packets; ++i) {
 			numpkt++;
 			if (time_after_eq(jiffies, lastj + HZ)) {
-				dprintk("frames/s: %lu (ts: %d, stuff %d, "
-					"sec: %d, invalid: %d, all: %d)\n",
+				dprintk("frames/s: %lu (ts: %d, stuff %d, sec: %d, invalid: %d, all: %d)\n",
 					numpkt * HZ / (jiffies - lastj),
 					numts, numstuff, numsec, numinvalid,
 					numts + numstuff + numsec + numinvalid);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c linux-libre-4.10-rc8-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c
--- linux-libre-4.9-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c	2016-12-11 17:46:56.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/ttusb-dec/ttusb_dec.c	2017-02-12 17:33:44.000000000 -0500
@@ -36,7 +36,6 @@
 
 #include "dmxdev.h"
 #include "dvb_demux.h"
-#include "dvb_filter.h"
 #include "dvb_frontend.h"
 #include "dvb_net.h"
 #include "ttusbdecfe.h"
@@ -92,6 +91,15 @@ enum ttusb_dec_interface {
 	TTUSB_DEC_INTERFACE_OUT
 };
 
+typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *);
+
+struct dvb_filter_pes2ts {
+	unsigned char buf[188];
+	unsigned char cc;
+	dvb_filter_pes2ts_cb_t *cb;
+	void *priv;
+};
+
 struct ttusb_dec {
 	enum ttusb_dec_model		model;
 	char				*model_name;
@@ -201,6 +209,54 @@ static u16 rc_keys[] = {
 	KEY_RADIO
 };
 
+static void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts,
+				   unsigned short pid,
+				   dvb_filter_pes2ts_cb_t *cb, void *priv)
+{
+	unsigned char *buf=p2ts->buf;
+
+	buf[0]=0x47;
+	buf[1]=(pid>>8);
+	buf[2]=pid&0xff;
+	p2ts->cc=0;
+	p2ts->cb=cb;
+	p2ts->priv=priv;
+}
+
+static int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts,
+			     unsigned char *pes, int len, int payload_start)
+{
+	unsigned char *buf=p2ts->buf;
+	int ret=0, rest;
+
+	//len=6+((pes[4]<<8)|pes[5]);
+
+	if (payload_start)
+		buf[1]|=0x40;
+	else
+		buf[1]&=~0x40;
+	while (len>=184) {
+		buf[3]=0x10|((p2ts->cc++)&0x0f);
+		memcpy(buf+4, pes, 184);
+		if ((ret=p2ts->cb(p2ts->priv, buf)))
+			return ret;
+		len-=184; pes+=184;
+		buf[1]&=~0x40;
+	}
+	if (!len)
+		return 0;
+	buf[3]=0x30|((p2ts->cc++)&0x0f);
+	rest=183-len;
+	if (rest) {
+		buf[5]=0x00;
+		if (rest-1)
+			memset(buf+6, 0xff, rest-1);
+	}
+	buf[4]=rest;
+	memcpy(buf+5+rest, pes, len);
+	return p2ts->cb(p2ts->priv, buf);
+}
+
 static void ttusb_dec_set_model(struct ttusb_dec *dec,
 				enum ttusb_dec_model model);
 
@@ -273,7 +329,7 @@ static int ttusb_dec_send_command(struct
 				  int param_length, const u8 params[],
 				  int *result_length, u8 cmd_result[])
 {
-	int result, actual_len, i;
+	int result, actual_len;
 	u8 *b;
 
 	dprintk("%s\n", __func__);
@@ -297,10 +353,8 @@ static int ttusb_dec_send_command(struct
 		memcpy(&b[4], params, param_length);
 
 	if (debug) {
-		printk("%s: command: ", __func__);
-		for (i = 0; i < param_length + 4; i++)
-			printk("0x%02X ", b[i]);
-		printk("\n");
+		printk(KERN_DEBUG "%s: command: %*ph\n",
+		       __func__, param_length, b);
 	}
 
 	result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
@@ -325,10 +379,8 @@ static int ttusb_dec_send_command(struct
 		return result;
 	} else {
 		if (debug) {
-			printk("%s: result: ", __func__);
-			for (i = 0; i < actual_len; i++)
-				printk("0x%02X ", b[i]);
-			printk("\n");
+			printk(KERN_DEBUG "%s: result: %*ph\n",
+			       __func__, actual_len, b);
 		}
 
 		if (result_length)
@@ -652,8 +704,8 @@ static void ttusb_dec_process_urb_frame(
 					dec->packet_payload_length = 2;
 					dec->packet_state = 7;
 				} else {
-					printk("%s: unknown packet type: "
-					       "%02x%02x\n", __func__,
+					printk("%s: unknown packet type: %02x%02x\n",
+					       __func__,
 					       dec->packet[0], dec->packet[1]);
 					dec->packet_state = 0;
 				}
@@ -905,8 +957,8 @@ static int ttusb_dec_start_iso_xfer(stru
 		for (i = 0; i < ISO_BUF_COUNT; i++) {
 			if ((result = usb_submit_urb(dec->iso_urb[i],
 						     GFP_ATOMIC))) {
-				printk("%s: failed urb submission %d: "
-				       "error %d\n", __func__, i, result);
+				printk("%s: failed urb submission %d: error %d\n",
+				       __func__, i, result);
 
 				while (i) {
 					usb_kill_urb(dec->iso_urb[i - 1]);
@@ -1319,8 +1371,7 @@ static int ttusb_dec_boot_dsp(struct ttu
 	memcpy(&tmp, &firmware[56], 4);
 	crc32_check = ntohl(tmp);
 	if (crc32_csum != crc32_check) {
-		printk("%s: crc32 check of DSP code failed (calculated "
-		       "0x%08x != 0x%08x in file), file invalid.\n",
+		printk("%s: crc32 check of DSP code failed (calculated 0x%08x != 0x%08x in file), file invalid.\n",
 			__func__, crc32_csum, crc32_check);
 		release_firmware(fw_entry);
 		return -ENOENT;
@@ -1397,11 +1448,9 @@ static int ttusb_dec_init_stb(struct ttu
 
 	if (!mode) {
 		if (version == 0xABCDEFAB)
-			printk(KERN_INFO "ttusb_dec: no version "
-			       "info in Firmware\n");
+			printk(KERN_INFO "ttusb_dec: no version info in Firmware\n");
 		else
-			printk(KERN_INFO "ttusb_dec: Firmware "
-			       "%x.%02x%c%c\n",
+			printk(KERN_INFO "ttusb_dec: Firmware %x.%02x%c%c\n",
 			       version >> 24, (version >> 16) & 0xff,
 			       (version >> 8) & 0xff, version & 0xff);
 
@@ -1425,8 +1474,7 @@ static int ttusb_dec_init_stb(struct ttu
 			ttusb_dec_set_model(dec, TTUSB_DEC2540T);
 			break;
 		default:
-			printk(KERN_ERR "%s: unknown model returned "
-			       "by firmware (%08x) - please report\n",
+			printk(KERN_ERR "%s: unknown model returned by firmware (%08x) - please report\n",
 			       __func__, model);
 			return -ENOENT;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/ttusb-dec/ttusbdecfe.c linux-libre-4.10-rc8-gnu/drivers/media/usb/ttusb-dec/ttusbdecfe.c
--- linux-libre-4.9-gnu/drivers/media/usb/ttusb-dec/ttusbdecfe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/ttusb-dec/ttusbdecfe.c	2017-02-12 16:03:20.000000000 -0500
@@ -205,7 +205,7 @@ static void ttusbdecfe_release(struct dv
 	kfree(state);
 }
 
-static struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
+static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops;
 
 struct dvb_frontend* ttusbdecfe_dvbt_attach(const struct ttusbdecfe_config* config)
 {
@@ -225,7 +225,7 @@ struct dvb_frontend* ttusbdecfe_dvbt_att
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
+static const struct dvb_frontend_ops ttusbdecfe_dvbs_ops;
 
 struct dvb_frontend* ttusbdecfe_dvbs_attach(const struct ttusbdecfe_config* config)
 {
@@ -247,7 +247,7 @@ struct dvb_frontend* ttusbdecfe_dvbs_att
 	return &state->frontend;
 }
 
-static struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
+static const struct dvb_frontend_ops ttusbdecfe_dvbt_ops = {
 	.delsys = { SYS_DVBT },
 	.info = {
 		.name			= "TechnoTrend/Hauppauge DEC2000-t Frontend",
@@ -270,7 +270,7 @@ static struct dvb_frontend_ops ttusbdecf
 	.read_status = ttusbdecfe_dvbt_read_status,
 };
 
-static struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
+static const struct dvb_frontend_ops ttusbdecfe_dvbs_ops = {
 	.delsys = { SYS_DVBS },
 	.info = {
 		.name			= "TechnoTrend/Hauppauge DEC3000-s Frontend",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/usbtv/usbtv-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/usbtv/usbtv-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/usbtv/usbtv-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/usbtv/usbtv-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,6 +71,7 @@ static int usbtv_probe(struct usb_interf
 	int size;
 	struct device *dev = &intf->dev;
 	struct usbtv *usbtv;
+	struct usb_host_endpoint *ep;
 
 	/* Checks that the device is what we think it is. */
 	if (intf->num_altsetting != 2)
@@ -78,10 +79,12 @@ static int usbtv_probe(struct usb_interf
 	if (intf->altsetting[1].desc.bNumEndpoints != 4)
 		return -ENODEV;
 
+	ep = &intf->altsetting[1].endpoint[0];
+
 	/* Packet size is split into 11 bits of base size and count of
 	 * extra multiplies of it.*/
-	size = usb_endpoint_maxp(&intf->altsetting[1].endpoint[0].desc);
-	size = (size & 0x07ff) * (((size & 0x1800) >> 11) + 1);
+	size = usb_endpoint_maxp(&ep->desc);
+	size = (size & 0x07ff) * usb_endpoint_maxp_mult(&ep->desc);
 
 	/* Device structure */
 	usbtv = kzalloc(sizeof(struct usbtv), GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/usbtv/usbtv.h linux-libre-4.10-rc8-gnu/drivers/media/usb/usbtv/usbtv.h
--- linux-libre-4.9-gnu/drivers/media/usb/usbtv/usbtv.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/usbtv/usbtv.h	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,7 @@
 #include <linux/usb.h>
 
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 #include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 
@@ -45,6 +46,7 @@
 #define USBTV_VIDEO_ENDP	0x81
 #define USBTV_AUDIO_ENDP	0x83
 #define USBTV_BASE		0xc000
+#define USBTV_CONTROL_REG	11
 #define USBTV_REQUEST_REG	12
 
 /* Number of concurrent isochronous urbs submitted.
@@ -87,6 +89,7 @@ struct usbtv {
 
 	/* video */
 	struct v4l2_device v4l2_dev;
+	struct v4l2_ctrl_handler ctrl;
 	struct video_device vdev;
 	struct vb2_queue vb2q;
 	struct mutex v4l2_lock;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/usbtv/usbtv-video.c linux-libre-4.10-rc8-gnu/drivers/media/usb/usbtv/usbtv-video.c
--- linux-libre-4.9-gnu/drivers/media/usb/usbtv/usbtv-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/usbtv/usbtv-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Lubomir Rintel
+ * Copyright (c) 2013,2016 Lubomir Rintel
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -259,6 +259,10 @@ static int usbtv_setup_capture(struct us
 	if (ret)
 		return ret;
 
+	ret = v4l2_ctrl_handler_setup(&usbtv->ctrl);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
@@ -696,11 +700,91 @@ static const struct vb2_ops usbtv_vb2_op
 	.stop_streaming = usbtv_stop_streaming,
 };
 
+static int usbtv_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct usbtv *usbtv = container_of(ctrl->handler, struct usbtv,
+								ctrl);
+	u8 *data;
+	u16 index, size;
+	int ret;
+
+	data = kmalloc(3, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/*
+	 * Read in the current brightness/contrast registers. We need them
+	 * both, because the values are for some reason interleaved.
+	 */
+	if (ctrl->id == V4L2_CID_BRIGHTNESS || ctrl->id == V4L2_CID_CONTRAST) {
+		ret = usb_control_msg(usbtv->udev,
+			usb_sndctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0, USBTV_BASE + 0x0244, (void *)data, 3, 0);
+		if (ret < 0)
+			goto error;
+	}
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		index = USBTV_BASE + 0x0244;
+		size = 3;
+		data[0] &= 0xf0;
+		data[0] |= (ctrl->val >> 8) & 0xf;
+		data[2] = ctrl->val & 0xff;
+		break;
+	case V4L2_CID_CONTRAST:
+		index = USBTV_BASE + 0x0244;
+		size = 3;
+		data[0] &= 0x0f;
+		data[0] |= (ctrl->val >> 4) & 0xf0;
+		data[1] = ctrl->val & 0xff;
+		break;
+	case V4L2_CID_SATURATION:
+		index = USBTV_BASE + 0x0242;
+		data[0] = ctrl->val >> 8;
+		data[1] = ctrl->val & 0xff;
+		size = 2;
+		break;
+	case V4L2_CID_HUE:
+		index = USBTV_BASE + 0x0240;
+		size = 2;
+		if (ctrl->val > 0) {
+			data[0] = 0x92 + (ctrl->val >> 8);
+			data[1] = ctrl->val & 0xff;
+		} else {
+			data[0] = 0x82 + (-ctrl->val >> 8);
+			data[1] = -ctrl->val & 0xff;
+		}
+		break;
+	default:
+		kfree(data);
+		return -EINVAL;
+	}
+
+	ret = usb_control_msg(usbtv->udev, usb_sndctrlpipe(usbtv->udev, 0),
+			USBTV_CONTROL_REG,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0, index, (void *)data, size, 0);
+
+error:
+	if (ret < 0)
+		dev_warn(usbtv->dev, "Failed to submit a control request.\n");
+
+	kfree(data);
+	return ret;
+}
+
+static const struct v4l2_ctrl_ops usbtv_ctrl_ops = {
+	.s_ctrl = usbtv_s_ctrl,
+};
+
 static void usbtv_release(struct v4l2_device *v4l2_dev)
 {
 	struct usbtv *usbtv = container_of(v4l2_dev, struct usbtv, v4l2_dev);
 
 	v4l2_device_unregister(&usbtv->v4l2_dev);
+	v4l2_ctrl_handler_free(&usbtv->ctrl);
 	vb2_queue_release(&usbtv->vb2q);
 	kfree(usbtv);
 }
@@ -731,7 +815,24 @@ int usbtv_video_init(struct usbtv *usbtv
 		return ret;
 	}
 
+	/* controls */
+	v4l2_ctrl_handler_init(&usbtv->ctrl, 4);
+	v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 0x3ff, 1, 0x1d0);
+	v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 0x3ff, 1, 0x1c0);
+	v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 0x3ff, 1, 0x200);
+	v4l2_ctrl_new_std(&usbtv->ctrl, &usbtv_ctrl_ops,
+			V4L2_CID_HUE, -0xdff, 0xdff, 1, 0x000);
+	ret = usbtv->ctrl.error;
+	if (ret < 0) {
+		dev_warn(usbtv->dev, "Could not initialize controls\n");
+		goto ctrl_fail;
+	}
+
 	/* v4l2 structure */
+	usbtv->v4l2_dev.ctrl_handler = &usbtv->ctrl;
 	usbtv->v4l2_dev.release = usbtv_release;
 	ret = v4l2_device_register(usbtv->dev, &usbtv->v4l2_dev);
 	if (ret < 0) {
@@ -760,6 +861,8 @@ int usbtv_video_init(struct usbtv *usbtv
 vdev_fail:
 	v4l2_device_unregister(&usbtv->v4l2_dev);
 v4l2_fail:
+ctrl_fail:
+	v4l2_ctrl_handler_free(&usbtv->ctrl);
 	vb2_queue_release(&usbtv->vb2q);
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/usbvision/usbvision-core.c linux-libre-4.10-rc8-gnu/drivers/media/usb/usbvision/usbvision-core.c
--- linux-libre-4.9-gnu/drivers/media/usb/usbvision/usbvision-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/usbvision/usbvision-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1656,8 +1656,8 @@ static int usbvision_set_video_format(st
 			     (__u16) USBVISION_FILT_CONT, value, 2, HZ);
 
 	if (rc < 0) {
-		printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - "
-		       "reconnect or reload driver.\n", proc, rc);
+		printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - reconnect or reload driver.\n",
+		       proc, rc);
 	}
 	usbvision->isoc_mode = format;
 	return rc;
@@ -1890,8 +1890,8 @@ static int usbvision_set_compress_params
 			     (__u16) USBVISION_INTRA_CYC, value, 5, HZ);
 
 	if (rc < 0) {
-		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-		       "reconnect or reload driver.\n", proc, rc);
+		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - reconnect or reload driver.\n",
+		       proc, rc);
 		return rc;
 	}
 
@@ -1921,8 +1921,8 @@ static int usbvision_set_compress_params
 			     (__u16) USBVISION_PCM_THR1, value, 6, HZ);
 
 	if (rc < 0) {
-		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-		       "reconnect or reload driver.\n", proc, rc);
+		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - reconnect or reload driver.\n",
+		       proc, rc);
 	}
 	return rc;
 }
@@ -1960,8 +1960,8 @@ int usbvision_set_input(struct usb_usbvi
 
 	rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]);
 	if (rc < 0) {
-		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-		       "reconnect or reload driver.\n", proc, rc);
+		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - reconnect or reload driver.\n",
+		       proc, rc);
 		return rc;
 	}
 
@@ -2026,8 +2026,8 @@ int usbvision_set_input(struct usb_usbvi
 			     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0,
 			     (__u16) USBVISION_LXSIZE_I, value, 8, HZ);
 	if (rc < 0) {
-		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-		       "reconnect or reload driver.\n", proc, rc);
+		printk(KERN_ERR "%sERROR=%d. USBVISION stopped - reconnect or reload driver.\n",
+		       proc, rc);
 		return rc;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/usbvision/usbvision-video.c linux-libre-4.10-rc8-gnu/drivers/media/usb/usbvision/usbvision-video.c
--- linux-libre-4.9-gnu/drivers/media/usb/usbvision/usbvision-video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/usbvision/usbvision-video.c	2017-02-12 16:03:20.000000000 -0500
@@ -1456,8 +1456,8 @@ static int usbvision_probe(struct usb_in
 	}
 
 	if (interface->desc.bNumEndpoints < 2) {
-		dev_err(&intf->dev, "interface %d has %d endpoints, but must"
-		    " have minimum 2\n", ifnum, interface->desc.bNumEndpoints);
+		dev_err(&intf->dev, "interface %d has %d endpoints, but must have minimum 2\n",
+			ifnum, interface->desc.bNumEndpoints);
 		ret = -ENODEV;
 		goto err_usb;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/uvc/uvc_driver.c linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvc_driver.c
--- linux-libre-4.9-gnu/drivers/media/usb/uvc/uvc_driver.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvc_driver.c	2017-02-12 16:03:20.000000000 -0500
@@ -168,6 +168,26 @@ static struct uvc_format_desc uvc_fmts[]
 		.guid		= UVC_GUID_FORMAT_RW10,
 		.fcc		= V4L2_PIX_FMT_SRGGB10P,
 	},
+	{
+		.name		= "Bayer 16-bit (SBGGR16)",
+		.guid		= UVC_GUID_FORMAT_BG16,
+		.fcc		= V4L2_PIX_FMT_SBGGR16,
+	},
+	{
+		.name		= "Bayer 16-bit (SGBRG16)",
+		.guid		= UVC_GUID_FORMAT_GB16,
+		.fcc		= V4L2_PIX_FMT_SGBRG16,
+	},
+	{
+		.name		= "Bayer 16-bit (SRGGB16)",
+		.guid		= UVC_GUID_FORMAT_RG16,
+		.fcc		= V4L2_PIX_FMT_SRGGB16,
+	},
+	{
+		.name		= "Bayer 16-bit (SGRBG16)",
+		.guid		= UVC_GUID_FORMAT_GR16,
+		.fcc		= V4L2_PIX_FMT_SGRBG16,
+	},
 };
 
 /* ------------------------------------------------------------------------
@@ -1309,7 +1329,7 @@ static int uvc_scan_chain_entity(struct
 	switch (UVC_ENTITY_TYPE(entity)) {
 	case UVC_VC_EXTENSION_UNIT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
-			printk(" <- XU %d", entity->id);
+			printk(KERN_CONT " <- XU %d", entity->id);
 
 		if (entity->bNrInPins != 1) {
 			uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
@@ -1321,7 +1341,7 @@ static int uvc_scan_chain_entity(struct
 
 	case UVC_VC_PROCESSING_UNIT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
-			printk(" <- PU %d", entity->id);
+			printk(KERN_CONT " <- PU %d", entity->id);
 
 		if (chain->processing != NULL) {
 			uvc_trace(UVC_TRACE_DESCR, "Found multiple "
@@ -1334,7 +1354,7 @@ static int uvc_scan_chain_entity(struct
 
 	case UVC_VC_SELECTOR_UNIT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
-			printk(" <- SU %d", entity->id);
+			printk(KERN_CONT " <- SU %d", entity->id);
 
 		/* Single-input selector units are ignored. */
 		if (entity->bNrInPins == 1)
@@ -1353,7 +1373,7 @@ static int uvc_scan_chain_entity(struct
 	case UVC_ITT_CAMERA:
 	case UVC_ITT_MEDIA_TRANSPORT_INPUT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
-			printk(" <- IT %d\n", entity->id);
+			printk(KERN_CONT " <- IT %d\n", entity->id);
 
 		break;
 
@@ -1361,17 +1381,17 @@ static int uvc_scan_chain_entity(struct
 	case UVC_OTT_DISPLAY:
 	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
 		if (uvc_trace_param & UVC_TRACE_PROBE)
-			printk(" OT %d", entity->id);
+			printk(KERN_CONT " OT %d", entity->id);
 
 		break;
 
 	case UVC_TT_STREAMING:
 		if (UVC_ENTITY_IS_ITERM(entity)) {
 			if (uvc_trace_param & UVC_TRACE_PROBE)
-				printk(" <- IT %d\n", entity->id);
+				printk(KERN_CONT " <- IT %d\n", entity->id);
 		} else {
 			if (uvc_trace_param & UVC_TRACE_PROBE)
-				printk(" OT %d", entity->id);
+				printk(KERN_CONT " OT %d", entity->id);
 		}
 
 		break;
@@ -1416,9 +1436,9 @@ static int uvc_scan_chain_forward(struct
 			list_add_tail(&forward->chain, &chain->entities);
 			if (uvc_trace_param & UVC_TRACE_PROBE) {
 				if (!found)
-					printk(" (->");
+					printk(KERN_CONT " (->");
 
-				printk(" XU %d", forward->id);
+				printk(KERN_CONT " XU %d", forward->id);
 				found = 1;
 			}
 			break;
@@ -1436,16 +1456,16 @@ static int uvc_scan_chain_forward(struct
 			list_add_tail(&forward->chain, &chain->entities);
 			if (uvc_trace_param & UVC_TRACE_PROBE) {
 				if (!found)
-					printk(" (->");
+					printk(KERN_CONT " (->");
 
-				printk(" OT %d", forward->id);
+				printk(KERN_CONT " OT %d", forward->id);
 				found = 1;
 			}
 			break;
 		}
 	}
 	if (found)
-		printk(")");
+		printk(KERN_CONT ")");
 
 	return 0;
 }
@@ -1471,7 +1491,7 @@ static int uvc_scan_chain_backward(struc
 		}
 
 		if (uvc_trace_param & UVC_TRACE_PROBE)
-			printk(" <- IT");
+			printk(KERN_CONT " <- IT");
 
 		chain->selector = entity;
 		for (i = 0; i < entity->bNrInPins; ++i) {
@@ -1485,14 +1505,14 @@ static int uvc_scan_chain_backward(struc
 			}
 
 			if (uvc_trace_param & UVC_TRACE_PROBE)
-				printk(" %d", term->id);
+				printk(KERN_CONT " %d", term->id);
 
 			list_add_tail(&term->chain, &chain->entities);
 			uvc_scan_chain_forward(chain, term, entity);
 		}
 
 		if (uvc_trace_param & UVC_TRACE_PROBE)
-			printk("\n");
+			printk(KERN_CONT "\n");
 
 		id = 0;
 		break;
@@ -1595,6 +1615,114 @@ static const char *uvc_print_chain(struc
 	return buffer;
 }
 
+static struct uvc_video_chain *uvc_alloc_chain(struct uvc_device *dev)
+{
+	struct uvc_video_chain *chain;
+
+	chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+	if (chain == NULL)
+		return NULL;
+
+	INIT_LIST_HEAD(&chain->entities);
+	mutex_init(&chain->ctrl_mutex);
+	chain->dev = dev;
+	v4l2_prio_init(&chain->prio);
+
+	return chain;
+}
+
+/*
+ * Fallback heuristic for devices that don't connect units and terminals in a
+ * valid chain.
+ *
+ * Some devices have invalid baSourceID references, causing uvc_scan_chain()
+ * to fail, but if we just take the entities we can find and put them together
+ * in the most sensible chain we can think of, turns out they do work anyway.
+ * Note: This heuristic assumes there is a single chain.
+ *
+ * At the time of writing, devices known to have such a broken chain are
+ *  - Acer Integrated Camera (5986:055a)
+ *  - Realtek rtl157a7 (0bda:57a7)
+ */
+static int uvc_scan_fallback(struct uvc_device *dev)
+{
+	struct uvc_video_chain *chain;
+	struct uvc_entity *iterm = NULL;
+	struct uvc_entity *oterm = NULL;
+	struct uvc_entity *entity;
+	struct uvc_entity *prev;
+
+	/*
+	 * Start by locating the input and output terminals. We only support
+	 * devices with exactly one of each for now.
+	 */
+	list_for_each_entry(entity, &dev->entities, list) {
+		if (UVC_ENTITY_IS_ITERM(entity)) {
+			if (iterm)
+				return -EINVAL;
+			iterm = entity;
+		}
+
+		if (UVC_ENTITY_IS_OTERM(entity)) {
+			if (oterm)
+				return -EINVAL;
+			oterm = entity;
+		}
+	}
+
+	if (iterm == NULL || oterm == NULL)
+		return -EINVAL;
+
+	/* Allocate the chain and fill it. */
+	chain = uvc_alloc_chain(dev);
+	if (chain == NULL)
+		return -ENOMEM;
+
+	if (uvc_scan_chain_entity(chain, oterm) < 0)
+		goto error;
+
+	prev = oterm;
+
+	/*
+	 * Add all Processing and Extension Units with two pads. The order
+	 * doesn't matter much, use reverse list traversal to connect units in
+	 * UVC descriptor order as we build the chain from output to input. This
+	 * leads to units appearing in the order meant by the manufacturer for
+	 * the cameras known to require this heuristic.
+	 */
+	list_for_each_entry_reverse(entity, &dev->entities, list) {
+		if (entity->type != UVC_VC_PROCESSING_UNIT &&
+		    entity->type != UVC_VC_EXTENSION_UNIT)
+			continue;
+
+		if (entity->num_pads != 2)
+			continue;
+
+		if (uvc_scan_chain_entity(chain, entity) < 0)
+			goto error;
+
+		prev->baSourceID[0] = entity->id;
+		prev = entity;
+	}
+
+	if (uvc_scan_chain_entity(chain, iterm) < 0)
+		goto error;
+
+	prev->baSourceID[0] = iterm->id;
+
+	list_add_tail(&chain->list, &dev->chains);
+
+	uvc_trace(UVC_TRACE_PROBE,
+		  "Found a video chain by fallback heuristic (%s).\n",
+		  uvc_print_chain(chain));
+
+	return 0;
+
+error:
+	kfree(chain);
+	return -EINVAL;
+}
+
 /*
  * Scan the device for video chains and register video devices.
  *
@@ -1617,15 +1745,10 @@ static int uvc_scan_device(struct uvc_de
 		if (term->chain.next || term->chain.prev)
 			continue;
 
-		chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+		chain = uvc_alloc_chain(dev);
 		if (chain == NULL)
 			return -ENOMEM;
 
-		INIT_LIST_HEAD(&chain->entities);
-		mutex_init(&chain->ctrl_mutex);
-		chain->dev = dev;
-		v4l2_prio_init(&chain->prio);
-
 		term->flags |= UVC_ENTITY_FLAG_DEFAULT;
 
 		if (uvc_scan_chain(chain, term) < 0) {
@@ -1639,6 +1762,9 @@ static int uvc_scan_device(struct uvc_de
 		list_add_tail(&chain->list, &dev->chains);
 	}
 
+	if (list_empty(&dev->chains))
+		uvc_scan_fallback(dev);
+
 	if (list_empty(&dev->chains)) {
 		uvc_printk(KERN_INFO, "No valid video chain found.\n");
 		return -1;
@@ -2564,6 +2690,15 @@ static struct usb_device_id uvc_ids[] =
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_QUIRK_FORCE_Y8 },
+	/* Oculus VR Rift Sensor */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x2833,
+	  .idProduct		= 0x0211,
+	  .bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_QUIRK_FORCE_Y8 },
 	/* Generic USB Video Class */
 	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
 	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/uvc/uvc_v4l2.c linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvc_v4l2.c
--- linux-libre-4.9-gnu/drivers/media/usb/uvc/uvc_v4l2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvc_v4l2.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,19 +66,14 @@ static int uvc_ioctl_ctrl_map(struct uvc
 		if (xmap->menu_count == 0 ||
 		    xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
 			ret = -EINVAL;
-			goto done;
+			goto free_map;
 		}
 
 		size = xmap->menu_count * sizeof(*map->menu_info);
-		map->menu_info = kmalloc(size, GFP_KERNEL);
-		if (map->menu_info == NULL) {
-			ret = -ENOMEM;
-			goto done;
-		}
-
-		if (copy_from_user(map->menu_info, xmap->menu_info, size)) {
-			ret = -EFAULT;
-			goto done;
+		map->menu_info = memdup_user(xmap->menu_info, size);
+		if (IS_ERR(map->menu_info)) {
+			ret = PTR_ERR(map->menu_info);
+			goto free_map;
 		}
 
 		map->menu_count = xmap->menu_count;
@@ -88,13 +83,13 @@ static int uvc_ioctl_ctrl_map(struct uvc
 		uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type "
 			  "%u.\n", xmap->v4l2_type);
 		ret = -ENOTTY;
-		goto done;
+		goto free_map;
 	}
 
 	ret = uvc_ctrl_add_mapping(chain, map);
 
-done:
 	kfree(map->menu_info);
+free_map:
 	kfree(map);
 
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/uvc/uvc_video.c linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvc_video.c
--- linux-libre-4.9-gnu/drivers/media/usb/uvc/uvc_video.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvc_video.c	2017-02-12 16:03:20.000000000 -0500
@@ -1467,6 +1467,7 @@ static unsigned int uvc_endpoint_max_bpi
 					 struct usb_host_endpoint *ep)
 {
 	u16 psize;
+	u16 mult;
 
 	switch (dev->speed) {
 	case USB_SPEED_SUPER:
@@ -1474,7 +1475,8 @@ static unsigned int uvc_endpoint_max_bpi
 		return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval);
 	case USB_SPEED_HIGH:
 		psize = usb_endpoint_maxp(&ep->desc);
-		return (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+		mult = usb_endpoint_maxp_mult(&ep->desc);
+		return (psize & 0x07ff) * mult;
 	case USB_SPEED_WIRELESS:
 		psize = usb_endpoint_maxp(&ep->desc);
 		return psize;
@@ -1551,7 +1553,7 @@ static int uvc_init_video_bulk(struct uv
 	u16 psize;
 	u32 size;
 
-	psize = usb_endpoint_maxp(&ep->desc) & 0x7ff;
+	psize = usb_endpoint_maxp(&ep->desc);
 	size = stream->ctrl.dwMaxPayloadTransferSize;
 	stream->bulk.max_payload_size = size;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/uvc/uvcvideo.h linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvcvideo.h
--- linux-libre-4.9-gnu/drivers/media/usb/uvc/uvcvideo.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/uvc/uvcvideo.h	2017-02-12 16:03:20.000000000 -0500
@@ -106,6 +106,18 @@
 #define UVC_GUID_FORMAT_RGGB \
 	{ 'R',  'G',  'G',  'B', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_BG16 \
+	{ 'B',  'G',  '1',  '6', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_GB16 \
+	{ 'G',  'B',  '1',  '6', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_RG16 \
+	{ 'R',  'G',  '1',  '6', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_GR16 \
+	{ 'G',  'R',  '1',  '6', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 #define UVC_GUID_FORMAT_RGBP \
 	{ 'R',  'G',  'B',  'P', 0x00, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/usb/zr364xx/zr364xx.c linux-libre-4.10-rc8-gnu/drivers/media/usb/zr364xx/zr364xx.c
--- linux-libre-4.9-gnu/drivers/media/usb/zr364xx/zr364xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/usb/zr364xx/zr364xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -633,8 +633,7 @@ static int zr364xx_read_video_callback(s
 	} else {
 		if (frm->cur_size + purb->actual_length > MAX_FRAME_SIZE) {
 			dev_info(&cam->udev->dev,
-				 "%s: buffer (%d bytes) too small to hold "
-				 "frame data. Discarding frame data.\n",
+				 "%s: buffer (%d bytes) too small to hold frame data. Discarding frame data.\n",
 				 __func__, MAX_FRAME_SIZE);
 		} else {
 			pdest += frm->cur_size;
@@ -1373,8 +1372,7 @@ static int zr364xx_board_init(struct zr3
 			&cam->buffer.frame[i], i,
 			cam->buffer.frame[i].lpvbits);
 		if (cam->buffer.frame[i].lpvbits == NULL) {
-			printk(KERN_INFO KBUILD_MODNAME ": out of memory. "
-			       "Using less frames\n");
+			printk(KERN_INFO KBUILD_MODNAME ": out of memory. Using less frames\n");
 			break;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/Kconfig linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/Kconfig
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -6,6 +6,7 @@
 config VIDEO_V4L2
 	tristate
 	depends on (I2C || I2C=n) && VIDEO_DEV
+	select RATIONAL
 	default (I2C || I2C=n) && VIDEO_DEV
 
 config VIDEO_ADV_DEBUG
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/tuner-core.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/tuner-core.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/tuner-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/tuner-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,30 +84,16 @@ static const struct v4l2_subdev_ops tune
  * Debug macros
  */
 
-#define tuner_warn(fmt, arg...) do {			\
-	printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
-	       i2c_adapter_id(t->i2c->adapter),		\
-	       t->i2c->addr, ##arg);			\
-	 } while (0)
+#undef pr_fmt
 
-#define tuner_info(fmt, arg...) do {			\
-	printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX,	\
-	       i2c_adapter_id(t->i2c->adapter),		\
-	       t->i2c->addr, ##arg);			\
-	 } while (0)
+#define pr_fmt(fmt) KBUILD_MODNAME ": %d-%04x: " fmt,		\
+	i2c_adapter_id(t->i2c->adapter), t->i2c->addr
 
-#define tuner_err(fmt, arg...) do {			\
-	printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX,	\
-	       i2c_adapter_id(t->i2c->adapter),		\
-	       t->i2c->addr, ##arg);			\
-	 } while (0)
 
-#define tuner_dbg(fmt, arg...) do {				\
-	if (tuner_debug)					\
-		printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX,	\
-		       i2c_adapter_id(t->i2c->adapter),		\
-		       t->i2c->addr, ##arg);			\
-	 } while (0)
+#define dprintk(fmt, arg...) do {					\
+	if (tuner_debug)						\
+		printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg);	\
+} while (0)
 
 /*
  * Internal struct used inside the driver
@@ -208,7 +194,7 @@ static void fe_set_params(struct dvb_fro
 	struct tuner *t = fe->analog_demod_priv;
 
 	if (NULL == fe_tuner_ops->set_analog_params) {
-		tuner_warn("Tuner frontend module has no way to set freq\n");
+		pr_warn("Tuner frontend module has no way to set freq\n");
 		return;
 	}
 	fe_tuner_ops->set_analog_params(fe, params);
@@ -230,7 +216,7 @@ static int fe_set_config(struct dvb_fron
 	if (fe_tuner_ops->set_config)
 		return fe_tuner_ops->set_config(fe, priv_cfg);
 
-	tuner_warn("Tuner frontend module has no way to set config\n");
+	pr_warn("Tuner frontend module has no way to set config\n");
 
 	return 0;
 }
@@ -273,14 +259,14 @@ static void set_type(struct i2c_client *
 	int tune_now = 1;
 
 	if (type == UNSET || type == TUNER_ABSENT) {
-		tuner_dbg("tuner 0x%02x: Tuner type absent\n", c->addr);
+		dprintk("tuner 0x%02x: Tuner type absent\n", c->addr);
 		return;
 	}
 
 	t->type = type;
 	t->config = new_config;
 	if (tuner_callback != NULL) {
-		tuner_dbg("defining GPIO callback\n");
+		dprintk("defining GPIO callback\n");
 		t->fe.callback = tuner_callback;
 	}
 
@@ -442,7 +428,7 @@ static void set_type(struct i2c_client *
 	t->sd.entity.name = t->name;
 #endif
 
-	tuner_dbg("type set to %s\n", t->name);
+	dprintk("type set to %s\n", t->name);
 
 	t->mode_mask = new_mode_mask;
 
@@ -459,13 +445,13 @@ static void set_type(struct i2c_client *
 			set_tv_freq(c, t->tv_freq);
 	}
 
-	tuner_dbg("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
+	dprintk("%s %s I2C addr 0x%02x with type %d used for 0x%02x\n",
 		  c->adapter->name, c->dev.driver->name, c->addr << 1, type,
 		  t->mode_mask);
 	return;
 
 attach_failed:
-	tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
+	dprintk("Tuner attach for type = %d failed.\n", t->type);
 	t->type = TUNER_ABSENT;
 
 	return;
@@ -491,7 +477,7 @@ static int tuner_s_type_addr(struct v4l2
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *c = v4l2_get_subdevdata(sd);
 
-	tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=%p\n",
+	dprintk("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=%p\n",
 			tun_setup->type,
 			tun_setup->addr,
 			tun_setup->mode_mask,
@@ -503,8 +489,7 @@ static int tuner_s_type_addr(struct v4l2
 		set_type(c, tun_setup->type, tun_setup->mode_mask,
 			 tun_setup->config, tun_setup->tuner_callback);
 	} else
-		tuner_dbg("set addr discarded for type %i, mask %x. "
-			  "Asked to change tuner at addr 0x%02x, with mask %x\n",
+		dprintk("set addr discarded for type %i, mask %x. Asked to change tuner at addr 0x%02x, with mask %x\n",
 			  t->type, t->mode_mask,
 			  tun_setup->addr, tun_setup->mode_mask);
 
@@ -534,7 +519,7 @@ static int tuner_s_config(struct v4l2_su
 		return 0;
 	}
 
-	tuner_dbg("Tuner frontend module has no way to set config\n");
+	dprintk("Tuner frontend module has no way to set config\n");
 	return 0;
 }
 
@@ -618,14 +603,12 @@ static int tuner_probe(struct i2c_client
 
 	if (show_i2c) {
 		unsigned char buffer[16];
-		int i, rc;
+		int rc;
 
 		memset(buffer, 0, sizeof(buffer));
 		rc = i2c_master_recv(client, buffer, sizeof(buffer));
-		tuner_info("I2C RECV = ");
-		for (i = 0; i < rc; i++)
-			printk(KERN_CONT "%02x ", buffer[i]);
-		printk("\n");
+		if (rc >= 0)
+			pr_info("I2C RECV = %*ph\n", rc, buffer);
 	}
 
 	/* autodetection code based on the i2c addr */
@@ -653,7 +636,7 @@ static int tuner_probe(struct i2c_client
 			   since it can be tda9887*/
 			if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
 					       t->i2c->addr) >= 0) {
-				tuner_dbg("tda829x detected\n");
+				dprintk("tda829x detected\n");
 			} else {
 				/* Default is being tda9887 */
 				t->type = TUNER_TDA9887;
@@ -690,7 +673,7 @@ static int tuner_probe(struct i2c_client
 		t->mode_mask = T_ANALOG_TV;
 		if (radio == NULL)
 			t->mode_mask |= T_RADIO;
-		tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask);
+		dprintk("Setting mode_mask to 0x%02x\n", t->mode_mask);
 	}
 
 	/* Should be just before return */
@@ -719,7 +702,7 @@ register_client:
 	}
 
 	if (ret < 0) {
-		tuner_err("failed to initialize media entity!\n");
+		pr_err("failed to initialize media entity!\n");
 		kfree(t);
 		return ret;
 	}
@@ -732,7 +715,7 @@ register_client:
 	set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
 	list_add_tail(&t->list, &tuner_list);
 
-	tuner_info("Tuner %d found with type(s)%s%s.\n",
+	pr_info("Tuner %d found with type(s)%s%s.\n",
 		   t->type,
 		   t->mode_mask & T_RADIO ? " Radio" : "",
 		   t->mode_mask & T_ANALOG_TV ? " TV" : "");
@@ -809,15 +792,15 @@ static int set_mode(struct tuner *t, enu
 
 	if (mode != t->mode) {
 		if (check_mode(t, mode) == -EINVAL) {
-			tuner_dbg("Tuner doesn't support mode %d. "
-				  "Putting tuner to sleep\n", mode);
+			dprintk("Tuner doesn't support mode %d. Putting tuner to sleep\n",
+				  mode);
 			t->standby = true;
 			if (analog_ops->standby)
 				analog_ops->standby(&t->fe);
 			return -EINVAL;
 		}
 		t->mode = mode;
-		tuner_dbg("Changing to mode %d\n", mode);
+		dprintk("Changing to mode %d\n", mode);
 	}
 	return 0;
 }
@@ -864,15 +847,15 @@ static void set_tv_freq(struct i2c_clien
 	};
 
 	if (t->type == UNSET) {
-		tuner_warn("tuner type not set\n");
+		pr_warn("tuner type not set\n");
 		return;
 	}
 	if (NULL == analog_ops->set_params) {
-		tuner_warn("Tuner has no way to set tv freq\n");
+		pr_warn("Tuner has no way to set tv freq\n");
 		return;
 	}
 	if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
-		tuner_dbg("TV freq (%d.%02d) out of range (%d-%d)\n",
+		dprintk("TV freq (%d.%02d) out of range (%d-%d)\n",
 			   freq / 16, freq % 16 * 100 / 16, tv_range[0],
 			   tv_range[1]);
 		/* V4L2 spec: if the freq is not possible then the closest
@@ -883,7 +866,7 @@ static void set_tv_freq(struct i2c_clien
 			freq = tv_range[1] * 16;
 	}
 	params.frequency = freq;
-	tuner_dbg("tv freq set to %d.%02d\n",
+	dprintk("tv freq set to %d.%02d\n",
 			freq / 16, freq % 16 * 100 / 16);
 	t->tv_freq = freq;
 	t->standby = false;
@@ -933,7 +916,7 @@ static v4l2_std_id tuner_fixup_std(struc
 				return V4L2_STD_PAL_Nc;
 			return V4L2_STD_PAL_N;
 		default:
-			tuner_warn("pal= argument not recognised\n");
+			pr_warn("pal= argument not recognised\n");
 			break;
 		}
 	}
@@ -959,7 +942,7 @@ static v4l2_std_id tuner_fixup_std(struc
 				return V4L2_STD_SECAM_LC;
 			return V4L2_STD_SECAM_L;
 		default:
-			tuner_warn("secam= argument not recognised\n");
+			pr_warn("secam= argument not recognised\n");
 			break;
 		}
 	}
@@ -976,7 +959,7 @@ static v4l2_std_id tuner_fixup_std(struc
 		case 'K':
 			return V4L2_STD_NTSC_M_KR;
 		default:
-			tuner_info("ntsc= argument not recognised\n");
+			pr_info("ntsc= argument not recognised\n");
 			break;
 		}
 	}
@@ -1005,15 +988,15 @@ static void set_radio_freq(struct i2c_cl
 	};
 
 	if (t->type == UNSET) {
-		tuner_warn("tuner type not set\n");
+		pr_warn("tuner type not set\n");
 		return;
 	}
 	if (NULL == analog_ops->set_params) {
-		tuner_warn("tuner has no way to set radio frequency\n");
+		pr_warn("tuner has no way to set radio frequency\n");
 		return;
 	}
 	if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
-		tuner_dbg("radio freq (%d.%02d) out of range (%d-%d)\n",
+		dprintk("radio freq (%d.%02d) out of range (%d-%d)\n",
 			   freq / 16000, freq % 16000 * 100 / 16000,
 			   radio_range[0], radio_range[1]);
 		/* V4L2 spec: if the freq is not possible then the closest
@@ -1024,7 +1007,7 @@ static void set_radio_freq(struct i2c_cl
 			freq = radio_range[1] * 16000;
 	}
 	params.frequency = freq;
-	tuner_dbg("radio freq set to %d.%02d\n",
+	dprintk("radio freq set to %d.%02d\n",
 			freq / 16000, freq % 16000 * 100 / 16000);
 	t->radio_freq = freq;
 	t->standby = false;
@@ -1075,10 +1058,10 @@ static void tuner_status(struct dvb_fron
 		freq = t->tv_freq / 16;
 		freq_fraction = (t->tv_freq % 16) * 100 / 16;
 	}
-	tuner_info("Tuner mode:      %s%s\n", p,
+	pr_info("Tuner mode:      %s%s\n", p,
 		   t->standby ? " on standby mode" : "");
-	tuner_info("Frequency:       %lu.%02lu MHz\n", freq, freq_fraction);
-	tuner_info("Standard:        0x%08lx\n", (unsigned long)t->std);
+	pr_info("Frequency:       %lu.%02lu MHz\n", freq, freq_fraction);
+	pr_info("Standard:        0x%08lx\n", (unsigned long)t->std);
 	if (t->mode != V4L2_TUNER_RADIO)
 		return;
 	if (fe_tuner_ops->get_status) {
@@ -1086,15 +1069,15 @@ static void tuner_status(struct dvb_fron
 
 		fe_tuner_ops->get_status(&t->fe, &tuner_status);
 		if (tuner_status & TUNER_STATUS_LOCKED)
-			tuner_info("Tuner is locked.\n");
+			pr_info("Tuner is locked.\n");
 		if (tuner_status & TUNER_STATUS_STEREO)
-			tuner_info("Stereo:          yes\n");
+			pr_info("Stereo:          yes\n");
 	}
 	if (analog_ops->has_signal) {
 		u16 signal;
 
 		if (!analog_ops->has_signal(fe, &signal))
-			tuner_info("Signal strength: %hu\n", signal);
+			pr_info("Signal strength: %hu\n", signal);
 	}
 }
 
@@ -1127,13 +1110,13 @@ static int tuner_s_power(struct v4l2_sub
 
 	if (on) {
 		if (t->standby && set_mode(t, t->mode) == 0) {
-			tuner_dbg("Waking up tuner\n");
+			dprintk("Waking up tuner\n");
 			set_freq(t, 0);
 		}
 		return 0;
 	}
 
-	tuner_dbg("Putting tuner to sleep\n");
+	dprintk("Putting tuner to sleep\n");
 	t->standby = true;
 	if (analog_ops->standby)
 		analog_ops->standby(&t->fe);
@@ -1149,7 +1132,7 @@ static int tuner_s_std(struct v4l2_subde
 
 	t->std = tuner_fixup_std(t, std);
 	if (t->std != std)
-		tuner_dbg("Fixup standard %llx to %llx\n", std, t->std);
+		dprintk("Fixup standard %llx to %llx\n", std, t->std);
 	set_freq(t, 0);
 	return 0;
 }
@@ -1298,7 +1281,7 @@ static int tuner_suspend(struct device *
 	struct tuner *t = to_tuner(i2c_get_clientdata(c));
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 
-	tuner_dbg("suspend\n");
+	dprintk("suspend\n");
 
 	if (t->fe.ops.tuner_ops.suspend)
 		t->fe.ops.tuner_ops.suspend(&t->fe);
@@ -1313,7 +1296,7 @@ static int tuner_resume(struct device *d
 	struct i2c_client *c = to_i2c_client(dev);
 	struct tuner *t = to_tuner(i2c_get_clientdata(c));
 
-	tuner_dbg("resume\n");
+	dprintk("resume\n");
 
 	if (t->fe.ops.tuner_ops.resume)
 		t->fe.ops.tuner_ops.resume(&t->fe);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-common.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-common.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-common.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 #if defined(CONFIG_SPI)
 #include <linux/spi/spi.h>
 #endif
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/div64.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-compat-ioctl32.c	2017-02-12 16:03:20.000000000 -0500
@@ -409,7 +409,6 @@ static int get_v4l2_buffer32(struct v4l2
 	struct v4l2_plane32 __user *uplane32;
 	struct v4l2_plane __user *uplane;
 	compat_caddr_t p;
-	int num_planes;
 	int ret;
 
 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
@@ -429,12 +428,15 @@ static int get_v4l2_buffer32(struct v4l2
 			return -EFAULT;
 
 	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
-		num_planes = kp->length;
-		if (num_planes == 0) {
+		unsigned int num_planes;
+
+		if (kp->length == 0) {
 			kp->m.planes = NULL;
 			/* num_planes == 0 is legal, e.g. when userspace doesn't
 			 * need planes array on DQBUF*/
 			return 0;
+		} else if (kp->length > VIDEO_MAX_PLANES) {
+			return -EINVAL;
 		}
 
 		if (get_user(p, &up->m.planes))
@@ -442,16 +444,16 @@ static int get_v4l2_buffer32(struct v4l2
 
 		uplane32 = compat_ptr(p);
 		if (!access_ok(VERIFY_READ, uplane32,
-				num_planes * sizeof(struct v4l2_plane32)))
+				kp->length * sizeof(struct v4l2_plane32)))
 			return -EFAULT;
 
 		/* We don't really care if userspace decides to kill itself
 		 * by passing a very big num_planes value */
-		uplane = compat_alloc_user_space(num_planes *
-						sizeof(struct v4l2_plane));
+		uplane = compat_alloc_user_space(kp->length *
+						 sizeof(struct v4l2_plane));
 		kp->m.planes = (__force struct v4l2_plane *)uplane;
 
-		while (--num_planes >= 0) {
+		for (num_planes = 0; num_planes < kp->length; num_planes++) {
 			ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
 			if (ret)
 				return ret;
@@ -665,7 +667,7 @@ static int get_v4l2_ext_controls32(struc
 {
 	struct v4l2_ext_control32 __user *ucontrols;
 	struct v4l2_ext_control __user *kcontrols;
-	int n;
+	unsigned int n;
 	compat_caddr_t p;
 
 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
@@ -675,20 +677,22 @@ static int get_v4l2_ext_controls32(struc
 		copy_from_user(kp->reserved, up->reserved,
 			       sizeof(kp->reserved)))
 			return -EFAULT;
-	n = kp->count;
-	if (n == 0) {
+	if (kp->count == 0) {
 		kp->controls = NULL;
 		return 0;
+	} else if (kp->count > V4L2_CID_MAX_CTRLS) {
+		return -EINVAL;
 	}
 	if (get_user(p, &up->controls))
 		return -EFAULT;
 	ucontrols = compat_ptr(p);
 	if (!access_ok(VERIFY_READ, ucontrols,
-			n * sizeof(struct v4l2_ext_control32)))
+			kp->count * sizeof(struct v4l2_ext_control32)))
 		return -EFAULT;
-	kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
+	kcontrols = compat_alloc_user_space(kp->count *
+					    sizeof(struct v4l2_ext_control));
 	kp->controls = (__force struct v4l2_ext_control *)kcontrols;
-	while (--n >= 0) {
+	for (n = 0; n < kp->count; n++) {
 		u32 id;
 
 		if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-ctrls.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-ctrls.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-ctrls.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-ctrls.c	2017-02-12 16:03:20.000000000 -0500
@@ -885,6 +885,7 @@ const char *v4l2_ctrl_get_name(u32 id)
 	case V4L2_CID_LINK_FREQ:		return "Link Frequency";
 	case V4L2_CID_PIXEL_RATE:		return "Pixel Rate";
 	case V4L2_CID_TEST_PATTERN:		return "Test Pattern";
+	case V4L2_CID_DEINTERLACING_MODE:	return "Deinterlacing Mode";
 
 	/* DV controls */
 	/* Keep the order of the 'case's the same as in v4l2-controls.h! */
@@ -1058,6 +1059,7 @@ void v4l2_ctrl_fill(u32 id, const char *
 	case V4L2_CID_DV_RX_RGB_RANGE:
 	case V4L2_CID_DV_RX_IT_CONTENT_TYPE:
 	case V4L2_CID_TEST_PATTERN:
+	case V4L2_CID_DEINTERLACING_MODE:
 	case V4L2_CID_TUNE_DEEMPHASIS:
 	case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
 	case V4L2_CID_DETECT_MD_MODE:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-dev.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-dev.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-dev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-dev.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/init.h>
 #include <linux/kmod.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-dv-timings.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-dv-timings.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-dv-timings.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-dv-timings.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/rational.h>
 #include <linux/videodev2.h>
 #include <linux/v4l2-dv-timings.h>
 #include <media/v4l2-dv-timings.h>
@@ -224,6 +225,24 @@ bool v4l2_find_dv_timings_cap(struct v4l
 }
 EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cap);
 
+bool v4l2_find_dv_timings_cea861_vic(struct v4l2_dv_timings *t, u8 vic)
+{
+	unsigned int i;
+
+	for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
+		const struct v4l2_bt_timings *bt =
+			&v4l2_dv_timings_presets[i].bt;
+
+		if ((bt->flags & V4L2_DV_FL_HAS_CEA861_VIC) &&
+		    bt->cea861_vic == vic) {
+			*t = v4l2_dv_timings_presets[i];
+			return true;
+		}
+	}
+	return false;
+}
+EXPORT_SYMBOL_GPL(v4l2_find_dv_timings_cea861_vic);
+
 /**
  * v4l2_match_dv_timings - check if two timings match
  * @t1 - compare this v4l2_dv_timings struct...
@@ -306,7 +325,8 @@ void v4l2_print_dv_timings(const char *d
 			(bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
 			bt->il_vsync, bt->il_vbackporch);
 	pr_info("%s: pixelclock: %llu\n", dev_prefix, bt->pixelclock);
-	pr_info("%s: flags (0x%x):%s%s%s%s%s%s%s\n", dev_prefix, bt->flags,
+	pr_info("%s: flags (0x%x):%s%s%s%s%s%s%s%s%s%s\n",
+			dev_prefix, bt->flags,
 			(bt->flags & V4L2_DV_FL_REDUCED_BLANKING) ?
 			" REDUCED_BLANKING" : "",
 			((bt->flags & V4L2_DV_FL_REDUCED_BLANKING) &&
@@ -320,16 +340,51 @@ void v4l2_print_dv_timings(const char *d
 			(bt->flags & V4L2_DV_FL_IS_CE_VIDEO) ?
 			" CE_VIDEO" : "",
 			(bt->flags & V4L2_DV_FL_FIRST_FIELD_EXTRA_LINE) ?
-			" FIRST_FIELD_EXTRA_LINE" : "");
+			" FIRST_FIELD_EXTRA_LINE" : "",
+			(bt->flags & V4L2_DV_FL_HAS_PICTURE_ASPECT) ?
+			" HAS_PICTURE_ASPECT" : "",
+			(bt->flags & V4L2_DV_FL_HAS_CEA861_VIC) ?
+			" HAS_CEA861_VIC" : "",
+			(bt->flags & V4L2_DV_FL_HAS_HDMI_VIC) ?
+			" HAS_HDMI_VIC" : "");
 	pr_info("%s: standards (0x%x):%s%s%s%s%s\n", dev_prefix, bt->standards,
 			(bt->standards & V4L2_DV_BT_STD_CEA861) ?  " CEA" : "",
 			(bt->standards & V4L2_DV_BT_STD_DMT) ?  " DMT" : "",
 			(bt->standards & V4L2_DV_BT_STD_CVT) ?  " CVT" : "",
 			(bt->standards & V4L2_DV_BT_STD_GTF) ?  " GTF" : "",
 			(bt->standards & V4L2_DV_BT_STD_SDI) ?  " SDI" : "");
+	if (bt->flags & V4L2_DV_FL_HAS_PICTURE_ASPECT)
+		pr_info("%s: picture aspect (hor:vert): %u:%u\n", dev_prefix,
+			bt->picture_aspect.numerator,
+			bt->picture_aspect.denominator);
+	if (bt->flags & V4L2_DV_FL_HAS_CEA861_VIC)
+		pr_info("%s: CEA-861 VIC: %u\n", dev_prefix, bt->cea861_vic);
+	if (bt->flags & V4L2_DV_FL_HAS_HDMI_VIC)
+		pr_info("%s: HDMI VIC: %u\n", dev_prefix, bt->hdmi_vic);
 }
 EXPORT_SYMBOL_GPL(v4l2_print_dv_timings);
 
+struct v4l2_fract v4l2_dv_timings_aspect_ratio(const struct v4l2_dv_timings *t)
+{
+	struct v4l2_fract ratio = { 1, 1 };
+	unsigned long n, d;
+
+	if (t->type != V4L2_DV_BT_656_1120)
+		return ratio;
+	if (!(t->bt.flags & V4L2_DV_FL_HAS_PICTURE_ASPECT))
+		return ratio;
+
+	ratio.numerator = t->bt.width * t->bt.picture_aspect.denominator;
+	ratio.denominator = t->bt.height * t->bt.picture_aspect.numerator;
+
+	rational_best_approximation(ratio.numerator, ratio.denominator,
+				    ratio.numerator, ratio.denominator, &n, &d);
+	ratio.numerator = n;
+	ratio.denominator = d;
+	return ratio;
+}
+EXPORT_SYMBOL_GPL(v4l2_dv_timings_aspect_ratio);
+
 /*
  * CVT defines
  * Based on Coordinated Video Timings Standard
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-flash-led-class.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-flash-led-class.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-flash-led-class.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-flash-led-class.c	2017-02-12 16:03:20.000000000 -0500
@@ -638,7 +638,7 @@ struct v4l2_flash *v4l2_flash_init(
 	v4l2_flash->iled_cdev = iled_cdev;
 	v4l2_flash->ops = ops;
 	sd->dev = dev;
-	sd->of_node = of_node;
+	sd->of_node = of_node ? of_node : led_cdev->dev->of_node;
 	v4l2_subdev_init(sd, &v4l2_flash_subdev_ops);
 	sd->internal_ops = &v4l2_flash_subdev_internal_ops;
 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -654,10 +654,7 @@ struct v4l2_flash *v4l2_flash_init(
 	if (ret < 0)
 		goto err_init_controls;
 
-	if (sd->of_node)
-		of_node_get(sd->of_node);
-	else
-		of_node_get(led_cdev->dev->of_node);
+	of_node_get(sd->of_node);
 
 	ret = v4l2_async_register_subdev(sd);
 	if (ret < 0)
@@ -666,7 +663,7 @@ struct v4l2_flash *v4l2_flash_init(
 	return v4l2_flash;
 
 err_async_register_sd:
-	of_node_put(led_cdev->dev->of_node);
+	of_node_put(sd->of_node);
 	v4l2_ctrl_handler_free(sd->ctrl_handler);
 err_init_controls:
 	media_entity_cleanup(&sd->entity);
@@ -678,20 +675,15 @@ EXPORT_SYMBOL_GPL(v4l2_flash_init);
 void v4l2_flash_release(struct v4l2_flash *v4l2_flash)
 {
 	struct v4l2_subdev *sd;
-	struct led_classdev *led_cdev;
 
 	if (IS_ERR_OR_NULL(v4l2_flash))
 		return;
 
 	sd = &v4l2_flash->sd;
-	led_cdev = &v4l2_flash->fled_cdev->led_cdev;
 
 	v4l2_async_unregister_subdev(sd);
 
-	if (sd->of_node)
-		of_node_put(sd->of_node);
-	else
-		of_node_put(led_cdev->dev->of_node);
+	of_node_put(sd->of_node);
 
 	v4l2_ctrl_handler_free(sd->ctrl_handler);
 	media_entity_cleanup(&sd->entity);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-ioctl.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-ioctl.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/v4l2-ioctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/v4l2-ioctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -174,8 +174,7 @@ static void v4l_print_querycap(const voi
 {
 	const struct v4l2_capability *p = arg;
 
-	pr_cont("driver=%.*s, card=%.*s, bus=%.*s, version=0x%08x, "
-		"capabilities=0x%08x, device_caps=0x%08x\n",
+	pr_cont("driver=%.*s, card=%.*s, bus=%.*s, version=0x%08x, capabilities=0x%08x, device_caps=0x%08x\n",
 		(int)sizeof(p->driver), p->driver,
 		(int)sizeof(p->card), p->card,
 		(int)sizeof(p->bus_info), p->bus_info,
@@ -186,8 +185,7 @@ static void v4l_print_enuminput(const vo
 {
 	const struct v4l2_input *p = arg;
 
-	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, tuner=%u, "
-		"std=0x%08Lx, status=0x%x, capabilities=0x%x\n",
+	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, tuner=%u, std=0x%08Lx, status=0x%x, capabilities=0x%x\n",
 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
 		p->tuner, (unsigned long long)p->std, p->status,
 		p->capabilities);
@@ -197,8 +195,7 @@ static void v4l_print_enumoutput(const v
 {
 	const struct v4l2_output *p = arg;
 
-	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, "
-		"modulator=%u, std=0x%08Lx, capabilities=0x%x\n",
+	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, modulator=%u, std=0x%08Lx, capabilities=0x%x\n",
 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
 		p->modulator, (unsigned long long)p->std, p->capabilities);
 }
@@ -256,11 +253,7 @@ static void v4l_print_format(const void
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		pix = &p->fmt.pix;
-		pr_cont(", width=%u, height=%u, "
-			"pixelformat=%c%c%c%c, field=%s, "
-			"bytesperline=%u, sizeimage=%u, colorspace=%d, "
-			"flags=0x%x, ycbcr_enc=%u, quantization=%u, "
-			"xfer_func=%u\n",
+		pr_cont(", width=%u, height=%u, pixelformat=%c%c%c%c, field=%s, bytesperline=%u, sizeimage=%u, colorspace=%d, flags=0x%x, ycbcr_enc=%u, quantization=%u, xfer_func=%u\n",
 			pix->width, pix->height,
 			(pix->pixelformat & 0xff),
 			(pix->pixelformat >>  8) & 0xff,
@@ -274,10 +267,7 @@ static void v4l_print_format(const void
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		mp = &p->fmt.pix_mp;
-		pr_cont(", width=%u, height=%u, "
-			"format=%c%c%c%c, field=%s, "
-			"colorspace=%d, num_planes=%u, flags=0x%x, "
-			"ycbcr_enc=%u, quantization=%u, xfer_func=%u\n",
+		pr_cont(", width=%u, height=%u, format=%c%c%c%c, field=%s, colorspace=%d, num_planes=%u, flags=0x%x, ycbcr_enc=%u, quantization=%u, xfer_func=%u\n",
 			mp->width, mp->height,
 			(mp->pixelformat & 0xff),
 			(mp->pixelformat >>  8) & 0xff,
@@ -306,8 +296,7 @@ static void v4l_print_format(const void
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_VBI_OUTPUT:
 		vbi = &p->fmt.vbi;
-		pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, "
-			"sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n",
+		pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n",
 			vbi->sampling_rate, vbi->offset,
 			vbi->samples_per_line,
 			(vbi->sample_format & 0xff),
@@ -343,9 +332,7 @@ static void v4l_print_framebuffer(const
 {
 	const struct v4l2_framebuffer *p = arg;
 
-	pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, "
-		"height=%u, pixelformat=%c%c%c%c, "
-		"bytesperline=%u, sizeimage=%u, colorspace=%d\n",
+	pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, height=%u, pixelformat=%c%c%c%c, bytesperline=%u, sizeimage=%u, colorspace=%d\n",
 			p->capability, p->flags, p->base,
 			p->fmt.width, p->fmt.height,
 			(p->fmt.pixelformat & 0xff),
@@ -368,8 +355,7 @@ static void v4l_print_modulator(const vo
 	if (write_only)
 		pr_cont("index=%u, txsubchans=0x%x\n", p->index, p->txsubchans);
 	else
-		pr_cont("index=%u, name=%.*s, capability=0x%x, "
-			"rangelow=%u, rangehigh=%u, txsubchans=0x%x\n",
+		pr_cont("index=%u, name=%.*s, capability=0x%x, rangelow=%u, rangehigh=%u, txsubchans=0x%x\n",
 			p->index, (int)sizeof(p->name), p->name, p->capability,
 			p->rangelow, p->rangehigh, p->txsubchans);
 }
@@ -381,9 +367,7 @@ static void v4l_print_tuner(const void *
 	if (write_only)
 		pr_cont("index=%u, audmode=%u\n", p->index, p->audmode);
 	else
-		pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, "
-			"rangelow=%u, rangehigh=%u, signal=%u, afc=%d, "
-			"rxsubchans=0x%x, audmode=%u\n",
+		pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, rangelow=%u, rangehigh=%u, signal=%u, afc=%d, rxsubchans=0x%x, audmode=%u\n",
 			p->index, (int)sizeof(p->name), p->name, p->type,
 			p->capability, p->rangelow,
 			p->rangehigh, p->signal, p->afc,
@@ -402,8 +386,8 @@ static void v4l_print_standard(const voi
 {
 	const struct v4l2_standard *p = arg;
 
-	pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, "
-		"framelines=%u\n", p->index,
+	pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, framelines=%u\n",
+		p->index,
 		(unsigned long long)p->id, (int)sizeof(p->name), p->name,
 		p->frameperiod.numerator,
 		p->frameperiod.denominator,
@@ -419,8 +403,7 @@ static void v4l_print_hw_freq_seek(const
 {
 	const struct v4l2_hw_freq_seek *p = arg;
 
-	pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, "
-		"rangelow=%u, rangehigh=%u\n",
+	pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, rangelow=%u, rangehigh=%u\n",
 		p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing,
 		p->rangelow, p->rangehigh);
 }
@@ -442,8 +425,7 @@ static void v4l_print_buffer(const void
 	const struct v4l2_plane *plane;
 	int i;
 
-	pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, "
-		"flags=0x%08x, field=%s, sequence=%d, memory=%s",
+	pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s",
 			p->timestamp.tv_sec / 3600,
 			(int)(p->timestamp.tv_sec / 60) % 60,
 			(int)(p->timestamp.tv_sec % 60),
@@ -458,8 +440,7 @@ static void v4l_print_buffer(const void
 		for (i = 0; i < p->length; ++i) {
 			plane = &p->m.planes[i];
 			printk(KERN_DEBUG
-				"plane %d: bytesused=%d, data_offset=0x%08x, "
-				"offset/userptr=0x%lx, length=%d\n",
+				"plane %d: bytesused=%d, data_offset=0x%08x, offset/userptr=0x%lx, length=%d\n",
 				i, plane->bytesused, plane->data_offset,
 				plane->m.userptr, plane->length);
 		}
@@ -468,8 +449,7 @@ static void v4l_print_buffer(const void
 			p->bytesused, p->m.userptr, p->length);
 	}
 
-	printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, "
-		"flags=0x%08x, frames=%d, userbits=0x%08x\n",
+	printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, flags=0x%08x, frames=%d, userbits=0x%08x\n",
 			tc->hours, tc->minutes, tc->seconds,
 			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
 }
@@ -503,8 +483,7 @@ static void v4l_print_streamparm(const v
 	    p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		const struct v4l2_captureparm *c = &p->parm.capture;
 
-		pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, "
-			"extendedmode=%d, readbuffers=%d\n",
+		pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, extendedmode=%d, readbuffers=%d\n",
 			c->capability, c->capturemode,
 			c->timeperframe.numerator, c->timeperframe.denominator,
 			c->extendedmode, c->readbuffers);
@@ -512,8 +491,7 @@ static void v4l_print_streamparm(const v
 		   p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		const struct v4l2_outputparm *c = &p->parm.output;
 
-		pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, "
-			"extendedmode=%d, writebuffers=%d\n",
+		pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, extendedmode=%d, writebuffers=%d\n",
 			c->capability, c->outputmode,
 			c->timeperframe.numerator, c->timeperframe.denominator,
 			c->extendedmode, c->writebuffers);
@@ -526,8 +504,7 @@ static void v4l_print_queryctrl(const vo
 {
 	const struct v4l2_queryctrl *p = arg;
 
-	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, "
-		"step=%d, default=%d, flags=0x%08x\n",
+	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, step=%d, default=%d, flags=0x%08x\n",
 			p->id, p->type, (int)sizeof(p->name), p->name,
 			p->minimum, p->maximum,
 			p->step, p->default_value, p->flags);
@@ -537,9 +514,7 @@ static void v4l_print_query_ext_ctrl(con
 {
 	const struct v4l2_query_ext_ctrl *p = arg;
 
-	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, "
-		"step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, "
-		"nr_of_dims=%u, dims=%u,%u,%u,%u\n",
+	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, nr_of_dims=%u, dims=%u,%u,%u,%u\n",
 			p->id, p->type, (int)sizeof(p->name), p->name,
 			p->minimum, p->maximum,
 			p->step, p->default_value, p->flags,
@@ -583,9 +558,7 @@ static void v4l_print_cropcap(const void
 {
 	const struct v4l2_cropcap *p = arg;
 
-	pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, "
-		"defrect wxh=%dx%d, x,y=%d,%d, "
-		"pixelaspect %d/%d\n",
+	pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, defrect wxh=%dx%d, x,y=%d,%d, pixelaspect %d/%d\n",
 		prt_names(p->type, v4l2_type_names),
 		p->bounds.width, p->bounds.height,
 		p->bounds.left, p->bounds.top,
@@ -618,8 +591,7 @@ static void v4l_print_jpegcompression(co
 {
 	const struct v4l2_jpegcompression *p = arg;
 
-	pr_cont("quality=%d, APPn=%d, APP_len=%d, "
-		"COM_len=%d, jpeg_markers=0x%x\n",
+	pr_cont("quality=%d, APPn=%d, APP_len=%d, COM_len=%d, jpeg_markers=0x%x\n",
 		p->quality, p->APPn, p->APP_len,
 		p->COM_len, p->jpeg_markers);
 }
@@ -686,14 +658,7 @@ static void v4l_print_dv_timings(const v
 
 	switch (p->type) {
 	case V4L2_DV_BT_656_1120:
-		pr_cont("type=bt-656/1120, interlaced=%u, "
-			"pixelclock=%llu, "
-			"width=%u, height=%u, polarities=0x%x, "
-			"hfrontporch=%u, hsync=%u, "
-			"hbackporch=%u, vfrontporch=%u, "
-			"vsync=%u, vbackporch=%u, "
-			"il_vfrontporch=%u, il_vsync=%u, "
-			"il_vbackporch=%u, standards=0x%x, flags=0x%x\n",
+		pr_cont("type=bt-656/1120, interlaced=%u, pixelclock=%llu, width=%u, height=%u, polarities=0x%x, hfrontporch=%u, hsync=%u, hbackporch=%u, vfrontporch=%u, vsync=%u, vbackporch=%u, il_vfrontporch=%u, il_vsync=%u, il_vbackporch=%u, standards=0x%x, flags=0x%x\n",
 				p->bt.interlaced, p->bt.pixelclock,
 				p->bt.width, p->bt.height,
 				p->bt.polarities, p->bt.hfrontporch,
@@ -723,8 +688,7 @@ static void v4l_print_dv_timings_cap(con
 
 	switch (p->type) {
 	case V4L2_DV_BT_656_1120:
-		pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, "
-			"pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n",
+		pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n",
 			p->bt.min_width, p->bt.max_width,
 			p->bt.min_height, p->bt.max_height,
 			p->bt.min_pixelclock, p->bt.max_pixelclock,
@@ -805,8 +769,7 @@ static void v4l_print_event(const void *
 	const struct v4l2_event *p = arg;
 	const struct v4l2_event_ctrl *c;
 
-	pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, "
-		"timestamp=%lu.%9.9lu\n",
+	pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, timestamp=%lu.%9.9lu\n",
 			p->type, p->pending, p->sequence, p->id,
 			p->timestamp.tv_sec, p->timestamp.tv_nsec);
 	switch (p->type) {
@@ -822,8 +785,7 @@ static void v4l_print_event(const void *
 			pr_cont("value64=%lld, ", c->value64);
 		else
 			pr_cont("value=%d, ", c->value);
-		pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d, "
-			"default_value=%d\n",
+		pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d, default_value=%d\n",
 			c->flags, c->minimum, c->maximum,
 			c->step, c->default_value);
 		break;
@@ -859,8 +821,7 @@ static void v4l_print_freq_band(const vo
 {
 	const struct v4l2_frequency_band *p = arg;
 
-	pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, "
-		"rangelow=%u, rangehigh=%u, modulation=0x%x\n",
+	pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, rangelow=%u, rangehigh=%u, modulation=0x%x\n",
 			p->tuner, p->type, p->index,
 			p->capability, p->rangelow,
 			p->rangehigh, p->modulation);
@@ -1167,6 +1128,9 @@ static void v4l_fill_fmtdesc(struct v4l2
 	case V4L2_PIX_FMT_Y16:		descr = "16-bit Greyscale"; break;
 	case V4L2_PIX_FMT_Y16_BE:	descr = "16-bit Greyscale BE"; break;
 	case V4L2_PIX_FMT_Y10BPACK:	descr = "10-bit Greyscale (Packed)"; break;
+	case V4L2_PIX_FMT_Y8I:		descr = "Interleaved 8-bit Greyscale"; break;
+	case V4L2_PIX_FMT_Y12I:		descr = "Interleaved 12-bit Greyscale"; break;
+	case V4L2_PIX_FMT_Z16:		descr = "16-bit Depth"; break;
 	case V4L2_PIX_FMT_PAL8:		descr = "8-bit Palette"; break;
 	case V4L2_PIX_FMT_UV8:		descr = "8-bit Chrominance UV 4-4"; break;
 	case V4L2_PIX_FMT_YVU410:	descr = "Planar YVU 4:1:0"; break;
@@ -1230,7 +1194,10 @@ static void v4l_fill_fmtdesc(struct v4l2
 	case V4L2_PIX_FMT_SGBRG10DPCM8:	descr = "8-bit Bayer GBGB/RGRG (DPCM)"; break;
 	case V4L2_PIX_FMT_SGRBG10DPCM8:	descr = "8-bit Bayer GRGR/BGBG (DPCM)"; break;
 	case V4L2_PIX_FMT_SRGGB10DPCM8:	descr = "8-bit Bayer RGRG/GBGB (DPCM)"; break;
-	case V4L2_PIX_FMT_SBGGR16:	descr = "16-bit Bayer BGBG/GRGR (Exp.)"; break;
+	case V4L2_PIX_FMT_SBGGR16:	descr = "16-bit Bayer BGBG/GRGR"; break;
+	case V4L2_PIX_FMT_SGBRG16:	descr = "16-bit Bayer GBGB/RGRG"; break;
+	case V4L2_PIX_FMT_SGRBG16:	descr = "16-bit Bayer GRGR/BGBG"; break;
+	case V4L2_PIX_FMT_SRGGB16:	descr = "16-bit Bayer RGRG/GBGB"; break;
 	case V4L2_PIX_FMT_SN9C20X_I420:	descr = "GSPCA SN9C20X I420"; break;
 	case V4L2_PIX_FMT_SPCA501:	descr = "GSPCA SPCA501"; break;
 	case V4L2_PIX_FMT_SPCA505:	descr = "GSPCA SPCA505"; break;
@@ -1239,6 +1206,8 @@ static void v4l_fill_fmtdesc(struct v4l2
 	case V4L2_PIX_FMT_TM6000:	descr = "A/V + VBI Mux Packet"; break;
 	case V4L2_PIX_FMT_CIT_YYVYUY:	descr = "GSPCA CIT YYVYUY"; break;
 	case V4L2_PIX_FMT_KONICA420:	descr = "GSPCA KONICA420"; break;
+	case V4L2_PIX_FMT_HSV24:	descr = "24-bit HSV 8-8-8"; break;
+	case V4L2_PIX_FMT_HSV32:	descr = "32-bit XHSV 8-8-8-8"; break;
 	case V4L2_SDR_FMT_CU8:		descr = "Complex U8"; break;
 	case V4L2_SDR_FMT_CU16LE:	descr = "Complex U16LE"; break;
 	case V4L2_SDR_FMT_CS8:		descr = "Complex S8"; break;
@@ -1269,6 +1238,7 @@ static void v4l_fill_fmtdesc(struct v4l2
 		case V4L2_PIX_FMT_VC1_ANNEX_G:	descr = "VC-1 (SMPTE 412M Annex G)"; break;
 		case V4L2_PIX_FMT_VC1_ANNEX_L:	descr = "VC-1 (SMPTE 412M Annex L)"; break;
 		case V4L2_PIX_FMT_VP8:		descr = "VP8"; break;
+		case V4L2_PIX_FMT_VP9:		descr = "VP9"; break;
 		case V4L2_PIX_FMT_CPIA1:	descr = "GSPCA CPiA YUV"; break;
 		case V4L2_PIX_FMT_WNVA:		descr = "WNVA"; break;
 		case V4L2_PIX_FMT_SN9C10X:	descr = "GSPCA SN9C10X"; break;
@@ -1287,6 +1257,7 @@ static void v4l_fill_fmtdesc(struct v4l2
 		case V4L2_PIX_FMT_JPGL:		descr = "JPEG Lite"; break;
 		case V4L2_PIX_FMT_SE401:	descr = "GSPCA SE401"; break;
 		case V4L2_PIX_FMT_S5C_UYVY_JPG:	descr = "S5C73MX interleaved UYVY/JPEG"; break;
+		case V4L2_PIX_FMT_MT21C:	descr = "Mediatek Compressed Format"; break;
 		default:
 			WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat);
 			if (fmt->description[0])
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf2-core.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf2-core.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf2-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf2-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -358,8 +358,8 @@ static int __vb2_queue_alloc(struct vb2_
 		if (memory == VB2_MEMORY_MMAP) {
 			ret = __vb2_buf_mem_alloc(vb);
 			if (ret) {
-				dprintk(1, "failed allocating memory for "
-						"buffer %d\n", buffer);
+				dprintk(1, "failed allocating memory for buffer %d\n",
+					buffer);
 				q->bufs[vb->index] = NULL;
 				kfree(vb);
 				break;
@@ -372,8 +372,8 @@ static int __vb2_queue_alloc(struct vb2_
 			 */
 			ret = call_vb_qop(vb, buf_init, vb);
 			if (ret) {
-				dprintk(1, "buffer %d %p initialization"
-					" failed\n", buffer, vb);
+				dprintk(1, "buffer %d %p initialization failed\n",
+					buffer, vb);
 				__vb2_buf_mem_free(vb);
 				q->bufs[vb->index] = NULL;
 				kfree(vb);
@@ -997,13 +997,12 @@ static int __qbuf_userptr(struct vb2_buf
 			&& vb->planes[plane].length == planes[plane].length)
 			continue;
 
-		dprintk(3, "userspace address for plane %d changed, "
-				"reacquiring memory\n", plane);
+		dprintk(3, "userspace address for plane %d changed, reacquiring memory\n",
+			plane);
 
 		/* Check if the provided plane buffer is large enough */
 		if (planes[plane].length < vb->planes[plane].min_length) {
-			dprintk(1, "provided buffer size %u is less than "
-						"setup size %u for plane %d\n",
+			dprintk(1, "provided buffer size %u is less than setup size %u for plane %d\n",
 						planes[plane].length,
 						vb->planes[plane].min_length,
 						plane);
@@ -1032,8 +1031,8 @@ static int __qbuf_userptr(struct vb2_buf
 				planes[plane].m.userptr,
 				planes[plane].length, dma_dir);
 		if (IS_ERR(mem_priv)) {
-			dprintk(1, "failed acquiring userspace "
-						"memory for plane %d\n", plane);
+			dprintk(1, "failed acquiring userspace memory for plane %d\n",
+				plane);
 			ret = PTR_ERR(mem_priv);
 			goto err;
 		}
@@ -1123,8 +1122,7 @@ static int __qbuf_dmabuf(struct vb2_buff
 			planes[plane].length = dbuf->size;
 
 		if (planes[plane].length < vb->planes[plane].min_length) {
-			dprintk(1, "invalid dmabuf length %u for plane %d, "
-				"minimum length %u\n",
+			dprintk(1, "invalid dmabuf length %u for plane %d, minimum length %u\n",
 				planes[plane].length, plane,
 				vb->planes[plane].min_length);
 			dma_buf_put(dbuf);
@@ -1472,8 +1470,7 @@ static int __vb2_wait_for_done_vb(struct
 		}
 
 		if (nonblocking) {
-			dprintk(1, "nonblocking and no buffers to dequeue, "
-								"will not wait\n");
+			dprintk(1, "nonblocking and no buffers to dequeue, will not wait\n");
 			return -EAGAIN;
 		}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf2-v4l2.c	2017-02-12 16:03:20.000000000 -0500
@@ -60,14 +60,13 @@ static int __verify_planes_array(struct
 
 	/* Is memory for copying plane information present? */
 	if (b->m.planes == NULL) {
-		dprintk(1, "multi-planar buffer passed but "
-			   "planes array not provided\n");
+		dprintk(1, "multi-planar buffer passed but planes array not provided\n");
 		return -EINVAL;
 	}
 
 	if (b->length < vb->num_planes || b->length > VB2_MAX_PLANES) {
-		dprintk(1, "incorrect planes array length, "
-			   "expected %d, got %d\n", vb->num_planes, b->length);
+		dprintk(1, "incorrect planes array length, expected %d, got %d\n",
+			vb->num_planes, b->length);
 		return -EINVAL;
 	}
 
@@ -316,8 +315,7 @@ static int __fill_vb2_buffer(struct vb2_
 		 * that just says that it is either a top or a bottom field,
 		 * but not which of the two it is.
 		 */
-		dprintk(1, "the field is incorrectly set to ALTERNATE "
-					"for an output buffer\n");
+		dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n");
 		return -EINVAL;
 	}
 	vb->timestamp = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf2-vmalloc.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf2-vmalloc.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf2-vmalloc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf2-vmalloc.c	2017-02-12 16:03:20.000000000 -0500
@@ -151,8 +151,7 @@ static void *vb2_vmalloc_vaddr(void *buf
 	struct vb2_vmalloc_buf *buf = buf_priv;
 
 	if (!buf->vaddr) {
-		pr_err("Address of an unallocated plane requested "
-		       "or cannot map user pointer\n");
+		pr_err("Address of an unallocated plane requested or cannot map user pointer\n");
 		return NULL;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf-core.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf-core.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -572,8 +572,7 @@ int videobuf_qbuf(struct videobuf_queue
 	switch (b->memory) {
 	case V4L2_MEMORY_MMAP:
 		if (0 == buf->baddr) {
-			dprintk(1, "qbuf: mmap requested "
-				   "but buffer addr is zero!\n");
+			dprintk(1, "qbuf: mmap requested but buffer addr is zero!\n");
 			goto done;
 		}
 		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c
--- linux-libre-4.9-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/media/v4l2-core/videobuf-dma-sg.c	2017-02-12 16:03:20.000000000 -0500
@@ -439,13 +439,12 @@ static int videobuf_vm_fault(struct vm_a
 	struct page *page;
 
 	dprintk(3, "fault: fault @ %08lx [vma %08lx-%08lx]\n",
-		(unsigned long)vmf->virtual_address,
-		vma->vm_start, vma->vm_end);
+		vmf->address, vma->vm_start, vma->vm_end);
 
 	page = alloc_page(GFP_USER | __GFP_DMA32);
 	if (!page)
 		return VM_FAULT_OOM;
-	clear_user_highpage(page, (unsigned long)vmf->virtual_address);
+	clear_user_highpage(page, vmf->address);
 	vmf->page = page;
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memory/atmel-ebi.c linux-libre-4.10-rc8-gnu/drivers/memory/atmel-ebi.c
--- linux-libre-4.9-gnu/drivers/memory/atmel-ebi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memory/atmel-ebi.c	2017-02-12 16:03:20.000000000 -0500
@@ -657,7 +657,7 @@ static int at91_ebi_dev_disable(struct a
 		return -ENOMEM;
 
 	newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL);
-	if (!newprop->name)
+	if (!newprop->value)
 		return -ENOMEM;
 
 	newprop->length = sizeof("disabled");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memory/atmel-sdramc.c linux-libre-4.10-rc8-gnu/drivers/memory/atmel-sdramc.c
--- linux-libre-4.9-gnu/drivers/memory/atmel-sdramc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memory/atmel-sdramc.c	2017-02-12 16:03:20.000000000 -0500
@@ -85,8 +85,4 @@ static struct platform_driver atmel_ramc
 	},
 };
 
-static int __init atmel_ramc_init(void)
-{
-	return platform_driver_register(&atmel_ramc_driver);
-}
-device_initcall(atmel_ramc_init);
+builtin_platform_driver(atmel_ramc_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memory/da8xx-ddrctl.c linux-libre-4.10-rc8-gnu/drivers/memory/da8xx-ddrctl.c
--- linux-libre-4.9-gnu/drivers/memory/da8xx-ddrctl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memory/da8xx-ddrctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,173 @@
+/*
+ * TI da8xx DDR2/mDDR controller driver
+ *
+ * Copyright (C) 2016 BayLibre SAS
+ *
+ * Author:
+ *   Bartosz Golaszewski <bgolaszewski@baylibre.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/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+/*
+ * REVISIT: Linux doesn't have a good framework for the kind of performance
+ * knobs this driver controls. We can't use device tree properties as it deals
+ * with hardware configuration rather than description. We also don't want to
+ * commit to maintaining some random sysfs attributes.
+ *
+ * For now we just hardcode the register values for the boards that need
+ * some changes (as is the case for the LCD controller on da850-lcdk - the
+ * first board we support here). When linux gets an appropriate framework,
+ * we'll easily convert the driver to it.
+ */
+
+struct da8xx_ddrctl_config_knob {
+	const char *name;
+	u32 reg;
+	u32 mask;
+	u32 shift;
+};
+
+static const struct da8xx_ddrctl_config_knob da8xx_ddrctl_knobs[] = {
+	{
+		.name = "da850-pbbpr",
+		.reg = 0x20,
+		.mask = 0xffffff00,
+		.shift = 0,
+	},
+};
+
+struct da8xx_ddrctl_setting {
+	const char *name;
+	u32 val;
+};
+
+struct da8xx_ddrctl_board_settings {
+	const char *board;
+	const struct da8xx_ddrctl_setting *settings;
+};
+
+static const struct da8xx_ddrctl_setting da850_lcdk_ddrctl_settings[] = {
+	{
+		.name = "da850-pbbpr",
+		.val = 0x20,
+	},
+	{ }
+};
+
+static const struct da8xx_ddrctl_board_settings da8xx_ddrctl_board_confs[] = {
+	{
+		.board = "ti,da850-lcdk",
+		.settings = da850_lcdk_ddrctl_settings,
+	},
+};
+
+static const struct da8xx_ddrctl_config_knob *
+da8xx_ddrctl_match_knob(const struct da8xx_ddrctl_setting *setting)
+{
+	const struct da8xx_ddrctl_config_knob *knob;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(da8xx_ddrctl_knobs); i++) {
+		knob = &da8xx_ddrctl_knobs[i];
+
+		if (strcmp(knob->name, setting->name) == 0)
+			return knob;
+	}
+
+	return NULL;
+}
+
+static const struct da8xx_ddrctl_setting *da8xx_ddrctl_get_board_settings(void)
+{
+	const struct da8xx_ddrctl_board_settings *board_settings;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(da8xx_ddrctl_board_confs); i++) {
+		board_settings = &da8xx_ddrctl_board_confs[i];
+
+		if (of_machine_is_compatible(board_settings->board))
+			return board_settings->settings;
+	}
+
+	return NULL;
+}
+
+static int da8xx_ddrctl_probe(struct platform_device *pdev)
+{
+	const struct da8xx_ddrctl_config_knob *knob;
+	const struct da8xx_ddrctl_setting *setting;
+	struct device_node *node;
+	struct resource *res;
+	void __iomem *ddrctl;
+	struct device *dev;
+	u32 reg;
+
+	dev = &pdev->dev;
+	node = dev->of_node;
+
+	setting = da8xx_ddrctl_get_board_settings();
+	if (!setting) {
+		dev_err(dev, "no settings defined for this board\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	ddrctl = devm_ioremap_resource(dev, res);
+	if (IS_ERR(ddrctl)) {
+		dev_err(dev, "unable to map memory controller registers\n");
+		return PTR_ERR(ddrctl);
+	}
+
+	for (; setting->name; setting++) {
+		knob = da8xx_ddrctl_match_knob(setting);
+		if (!knob) {
+			dev_warn(dev,
+				 "no such config option: %s\n", setting->name);
+			continue;
+		}
+
+		if (knob->reg + sizeof(u32) > resource_size(res)) {
+			dev_warn(dev,
+				 "register offset of '%s' exceeds mapped memory size\n",
+				 knob->name);
+			continue;
+		}
+
+		reg = readl(ddrctl + knob->reg);
+		reg &= knob->mask;
+		reg |= setting->val << knob->shift;
+
+		dev_dbg(dev, "writing 0x%08x to %s\n", reg, setting->name);
+
+		writel(reg, ddrctl + knob->reg);
+	}
+
+	return 0;
+}
+
+static const struct of_device_id da8xx_ddrctl_of_match[] = {
+	{ .compatible = "ti,da850-ddr-controller", },
+	{ },
+};
+
+static struct platform_driver da8xx_ddrctl_driver = {
+	.probe = da8xx_ddrctl_probe,
+	.driver = {
+		.name = "da850-ddr-controller",
+		.of_match_table = da8xx_ddrctl_of_match,
+	},
+};
+module_platform_driver(da8xx_ddrctl_driver);
+
+MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
+MODULE_DESCRIPTION("TI da8xx DDR2/mDDR controller driver");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memory/Kconfig linux-libre-4.10-rc8-gnu/drivers/memory/Kconfig
--- linux-libre-4.9-gnu/drivers/memory/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memory/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -134,6 +134,14 @@ config MTK_SMI
 	  mainly help enable/disable iommu and control the power domain and
 	  clocks for each local arbiter.
 
+config DA8XX_DDRCTL
+	bool "Texas Instruments da8xx DDR2/mDDR driver"
+	depends on ARCH_DAVINCI_DA8XX
+	help
+	  This driver is for the DDR2/mDDR Memory Controller present on
+	  Texas Instruments da8xx SoCs. It's used to tweak various memory
+	  controller configuration options.
+
 source "drivers/memory/samsung/Kconfig"
 source "drivers/memory/tegra/Kconfig"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memory/Makefile linux-libre-4.10-rc8-gnu/drivers/memory/Makefile
--- linux-libre-4.9-gnu/drivers/memory/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memory/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@ obj-$(CONFIG_MVEBU_DEVBUS)	+= mvebu-devb
 obj-$(CONFIG_TEGRA20_MC)	+= tegra20-mc.o
 obj-$(CONFIG_JZ4780_NEMC)	+= jz4780-nemc.o
 obj-$(CONFIG_MTK_SMI)		+= mtk-smi.o
+obj-$(CONFIG_DA8XX_DDRCTL)	+= da8xx-ddrctl.o
 
 obj-$(CONFIG_SAMSUNG_MC)	+= samsung/
 obj-$(CONFIG_TEGRA_MC)		+= tegra/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memstick/core/memstick.c linux-libre-4.10-rc8-gnu/drivers/memstick/core/memstick.c
--- linux-libre-4.9-gnu/drivers/memstick/core/memstick.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memstick/core/memstick.c	2017-02-12 16:03:20.000000000 -0500
@@ -330,7 +330,7 @@ static int h_memstick_read_dev_id(struct
 	struct ms_id_register id_reg;
 
 	if (!(*mrq)) {
-		memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL,
+		memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, &id_reg,
 				  sizeof(struct ms_id_register));
 		*mrq = &card->current_mrq;
 		return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memstick/core/ms_block.c linux-libre-4.10-rc8-gnu/drivers/memstick/core/ms_block.c
--- linux-libre-4.9-gnu/drivers/memstick/core/ms_block.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memstick/core/ms_block.c	2017-02-12 16:03:20.000000000 -0500
@@ -2006,7 +2006,7 @@ static int msb_prepare_req(struct reques
 		blk_dump_rq_flags(req, "MS unsupported request");
 		return BLKPREP_KILL;
 	}
-	req->cmd_flags |= REQ_DONTPREP;
+	req->rq_flags |= RQF_DONTPREP;
 	return BLKPREP_OK;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/memstick/core/mspro_block.c linux-libre-4.10-rc8-gnu/drivers/memstick/core/mspro_block.c
--- linux-libre-4.9-gnu/drivers/memstick/core/mspro_block.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/memstick/core/mspro_block.c	2017-02-12 16:03:20.000000000 -0500
@@ -834,7 +834,7 @@ static int mspro_block_prepare_req(struc
 		return BLKPREP_KILL;
 	}
 
-	req->cmd_flags |= REQ_DONTPREP;
+	req->rq_flags |= RQF_DONTPREP;
 
 	return BLKPREP_OK;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/message/fusion/mptbase.c linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptbase.c
--- linux-libre-4.9-gnu/drivers/message/fusion/mptbase.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptbase.c	2017-02-12 16:03:20.000000000 -0500
@@ -2585,10 +2585,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u3
 				(void) GetLanConfigPages(ioc);
 				a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
 				dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
-					"LanAddr = %02X:%02X:%02X"
-					":%02X:%02X:%02X\n",
-					ioc->name, a[5], a[4],
-					a[3], a[2], a[1], a[0]));
+					"LanAddr = %pMR\n", ioc->name, a));
 			}
 			break;
 
@@ -2868,21 +2865,21 @@ MptDisplayIocCapabilities(MPT_ADAPTER *i
 
 	printk(KERN_INFO "%s: ", ioc->name);
 	if (ioc->prod_name)
-		printk("%s: ", ioc->prod_name);
-	printk("Capabilities={");
+		pr_cont("%s: ", ioc->prod_name);
+	pr_cont("Capabilities={");
 
 	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
-		printk("Initiator");
+		pr_cont("Initiator");
 		i++;
 	}
 
 	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
-		printk("%sTarget", i ? "," : "");
+		pr_cont("%sTarget", i ? "," : "");
 		i++;
 	}
 
 	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
-		printk("%sLAN", i ? "," : "");
+		pr_cont("%sLAN", i ? "," : "");
 		i++;
 	}
 
@@ -2891,12 +2888,12 @@ MptDisplayIocCapabilities(MPT_ADAPTER *i
 	 *  This would probably evoke more questions than it's worth
 	 */
 	if (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
-		printk("%sLogBusAddr", i ? "," : "");
+		pr_cont("%sLogBusAddr", i ? "," : "");
 		i++;
 	}
 #endif
 
-	printk("}\n");
+	pr_cont("}\n");
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -6783,8 +6780,7 @@ static int mpt_iocinfo_proc_show(struct
 		if (ioc->bus_type == FC) {
 			if (ioc->pfacts[p].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) {
 				u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
-				seq_printf(m, "    LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-						a[5], a[4], a[3], a[2], a[1], a[0]);
+				seq_printf(m, "    LanAddr = %pMR\n", a);
 			}
 			seq_printf(m, "    WWN = %08X%08X:%08X%08X\n",
 					ioc->fc_port_page0[p].WWNN.High,
@@ -6861,8 +6857,7 @@ mpt_print_ioc_summary(MPT_ADAPTER *ioc,
 
 	if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
 		u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
-		y += sprintf(buffer+len+y, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
-			a[5], a[4], a[3], a[2], a[1], a[0]);
+		y += sprintf(buffer+len+y, ", LanAddr=%pMR", a);
 	}
 
 	y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
@@ -6896,8 +6891,7 @@ static void seq_mpt_print_ioc_summary(MP
 
 	if (showlan && (ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
 		u8 *a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow;
-		seq_printf(m, ", LanAddr=%02X:%02X:%02X:%02X:%02X:%02X",
-			a[5], a[4], a[3], a[2], a[1], a[0]);
+		seq_printf(m, ", LanAddr=%pMR", a);
 	}
 
 	seq_printf(m, ", IRQ=%d", ioc->pci_irq);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/message/fusion/mptctl.c linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptctl.c
--- linux-libre-4.9-gnu/drivers/message/fusion/mptctl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptctl.c	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,7 @@
 #include <linux/compat.h>
 
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/message/fusion/mptlan.c linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptlan.c
--- linux-libre-4.9-gnu/drivers/message/fusion/mptlan.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptlan.c	2017-02-12 16:03:20.000000000 -0500
@@ -549,16 +549,6 @@ mpt_lan_close(struct net_device *dev)
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
-mpt_lan_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if ((new_mtu < MPT_LAN_MIN_MTU) || (new_mtu > MPT_LAN_MAX_MTU))
-		return -EINVAL;
-	dev->mtu = new_mtu;
-	return 0;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /* Tx timeout handler. */
 static void
 mpt_lan_tx_timeout(struct net_device *dev)
@@ -1304,7 +1294,6 @@ static const struct net_device_ops mpt_n
 	.ndo_open       = mpt_lan_open,
 	.ndo_stop       = mpt_lan_close,
 	.ndo_start_xmit = mpt_lan_sdu_send,
-	.ndo_change_mtu = mpt_lan_change_mtu,
 	.ndo_tx_timeout = mpt_lan_tx_timeout,
 };
 
@@ -1375,6 +1364,10 @@ mpt_register_lan_device (MPT_ADAPTER *mp
 	dev->netdev_ops = &mpt_netdev_ops;
 	dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT;
 
+	/* MTU range: 96 - 65280 */
+	dev->min_mtu = MPT_LAN_MIN_MTU;
+	dev->max_mtu = MPT_LAN_MAX_MTU;
+
 	dlprintk((KERN_INFO MYNAM ": Finished registering dev "
 		"and setting initial values\n"));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/message/fusion/mptlan.h linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptlan.h
--- linux-libre-4.9-gnu/drivers/message/fusion/mptlan.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptlan.h	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,7 @@
 #include <linux/workqueue.h>
 #include <linux/delay.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
     /* Override mptbase.h by pre-defining these! */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/message/fusion/mptscsih.c linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptscsih.c
--- linux-libre-4.9-gnu/drivers/message/fusion/mptscsih.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/message/fusion/mptscsih.c	2017-02-12 16:03:20.000000000 -0500
@@ -1366,15 +1366,10 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt)
 	/* Default to untagged. Once a target structure has been allocated,
 	 * use the Inquiry data to determine if device supports tagged.
 	 */
-	if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)
-	    && (SCpnt->device->tagged_supported)) {
+	if ((vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) &&
+	    SCpnt->device->tagged_supported)
 		scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ;
-		if (SCpnt->request && SCpnt->request->ioprio) {
-			if (((SCpnt->request->ioprio & 0x7) == 1) ||
-				!(SCpnt->request->ioprio & 0x7))
-				scsictl |= MPI_SCSIIO_CONTROL_HEADOFQ;
-		}
-	} else
+	else
 		scsictl = scsidir | MPI_SCSIIO_CONTROL_UNTAGGED;
 
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/88pm860x-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/88pm860x-core.c
--- linux-libre-4.9-gnu/drivers/mfd/88pm860x-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/88pm860x-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1132,8 +1132,7 @@ static int pm860x_dt_init(struct device_
 	return 0;
 }
 
-static int pm860x_probe(struct i2c_client *client,
-				  const struct i2c_device_id *id)
+static int pm860x_probe(struct i2c_client *client)
 {
 	struct pm860x_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct device_node *node = client->dev.of_node;
@@ -1259,7 +1258,7 @@ static struct i2c_driver pm860x_driver =
 		.pm     = &pm860x_pm_ops,
 		.of_match_table	= pm860x_dt_ids,
 	},
-	.probe		= pm860x_probe,
+	.probe_new	= pm860x_probe,
 	.remove		= pm860x_remove,
 	.id_table	= pm860x_id_table,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/ab3100-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/ab3100-core.c
--- linux-libre-4.9-gnu/drivers/mfd/ab3100-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/ab3100-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -12,7 +12,7 @@
 #include <linux/notifier.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
@@ -628,20 +628,10 @@ static void ab3100_setup_debugfs(struct
  exit_no_debugfs:
 	return;
 }
-static inline void ab3100_remove_debugfs(void)
-{
-	debugfs_remove(ab3100_set_reg_file);
-	debugfs_remove(ab3100_get_reg_file);
-	debugfs_remove(ab3100_reg_file);
-	debugfs_remove(ab3100_dir);
-}
 #else
 static inline void ab3100_setup_debugfs(struct ab3100 *ab3100)
 {
 }
-static inline void ab3100_remove_debugfs(void)
-{
-}
 #endif
 
 /*
@@ -949,45 +939,22 @@ static int ab3100_probe(struct i2c_clien
 	return err;
 }
 
-static int ab3100_remove(struct i2c_client *client)
-{
-	struct ab3100 *ab3100 = i2c_get_clientdata(client);
-
-	/* Unregister subdevices */
-	mfd_remove_devices(&client->dev);
-	ab3100_remove_debugfs();
-	i2c_unregister_device(ab3100->testreg_client);
-	return 0;
-}
-
 static const struct i2c_device_id ab3100_id[] = {
 	{ "ab3100", 0 },
 	{ }
 };
-MODULE_DEVICE_TABLE(i2c, ab3100_id);
 
 static struct i2c_driver ab3100_driver = {
 	.driver = {
-		.name	= "ab3100",
+		.name			= "ab3100",
+		.suppress_bind_attrs	= true,
 	},
 	.id_table	= ab3100_id,
 	.probe		= ab3100_probe,
-	.remove		= ab3100_remove,
 };
 
 static int __init ab3100_i2c_init(void)
 {
 	return i2c_add_driver(&ab3100_driver);
 }
-
-static void __exit ab3100_i2c_exit(void)
-{
-	i2c_del_driver(&ab3100_driver);
-}
-
 subsys_initcall(ab3100_i2c_init);
-module_exit(ab3100_i2c_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-MODULE_DESCRIPTION("AB3100 core driver");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/ab8500-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-core.c
--- linux-libre-4.9-gnu/drivers/mfd/ab8500-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@
 #include <linux/irqdomain.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
@@ -123,6 +123,10 @@ static DEFINE_SPINLOCK(on_stat_lock);
 static u8 turn_on_stat_mask = 0xFF;
 static u8 turn_on_stat_set;
 static bool no_bm; /* No battery management */
+/*
+ * not really modular, but the easiest way to keep compat with existing
+ * bootargs behaviour is to continue using module_param here.
+ */
 module_param(no_bm, bool, S_IRUGO);
 
 #define AB9540_MODEM_CTRL2_REG			0x23
@@ -1324,25 +1328,6 @@ static int ab8500_probe(struct platform_
 	return ret;
 }
 
-static int ab8500_remove(struct platform_device *pdev)
-{
-	struct ab8500 *ab8500 = platform_get_drvdata(pdev);
-
-	if (((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
-			ab8500->chip_id >= AB8500_CUT2P0) || is_ab8540(ab8500))
-		sysfs_remove_group(&ab8500->dev->kobj, &ab9540_attr_group);
-	else
-		sysfs_remove_group(&ab8500->dev->kobj, &ab8500_attr_group);
-
-	if ((is_ab8505(ab8500) || is_ab9540(ab8500)) &&
-			ab8500->chip_id >= AB8500_CUT2P0)
-		sysfs_remove_group(&ab8500->dev->kobj, &ab8505_attr_group);
-
-	mfd_remove_devices(ab8500->dev);
-
-	return 0;
-}
-
 static const struct platform_device_id ab8500_id[] = {
 	{ "ab8500-core", AB8500_VERSION_AB8500 },
 	{ "ab8505-i2c", AB8500_VERSION_AB8505 },
@@ -1354,9 +1339,9 @@ static const struct platform_device_id a
 static struct platform_driver ab8500_core_driver = {
 	.driver = {
 		.name = "ab8500-core",
+		.suppress_bind_attrs = true,
 	},
 	.probe	= ab8500_probe,
-	.remove	= ab8500_remove,
 	.id_table = ab8500_id,
 };
 
@@ -1364,14 +1349,4 @@ static int __init ab8500_core_init(void)
 {
 	return platform_driver_register(&ab8500_core_driver);
 }
-
-static void __exit ab8500_core_exit(void)
-{
-	platform_driver_unregister(&ab8500_core_driver);
-}
 core_initcall(ab8500_core_init);
-module_exit(ab8500_core_exit);
-
-MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
-MODULE_DESCRIPTION("AB8500 MFD core");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/ab8500-debugfs.c linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-debugfs.c
--- linux-libre-4.9-gnu/drivers/mfd/ab8500-debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -74,7 +74,7 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/debugfs.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
@@ -3234,33 +3234,16 @@ err:
 	return -ENOMEM;
 }
 
-static int ab8500_debug_remove(struct platform_device *plf)
-{
-	debugfs_remove_recursive(ab8500_dir);
-
-	return 0;
-}
-
 static struct platform_driver ab8500_debug_driver = {
 	.driver = {
 		.name = "ab8500-debug",
+		.suppress_bind_attrs = true,
 	},
 	.probe  = ab8500_debug_probe,
-	.remove = ab8500_debug_remove
 };
 
 static int __init ab8500_debug_init(void)
 {
 	return platform_driver_register(&ab8500_debug_driver);
 }
-
-static void __exit ab8500_debug_exit(void)
-{
-	platform_driver_unregister(&ab8500_debug_driver);
-}
 subsys_initcall(ab8500_debug_init);
-module_exit(ab8500_debug_exit);
-
-MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
-MODULE_DESCRIPTION("AB8500 DEBUG");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/ab8500-gpadc.c linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-gpadc.c
--- linux-libre-4.9-gnu/drivers/mfd/ab8500-gpadc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-gpadc.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,9 +5,9 @@
  * Author: Arun R Murthy <arun.murthy@stericsson.com>
  * Author: Daniel Willerud <daniel.willerud@stericsson.com>
  * Author: Johan Palsson <johan.palsson@stericsson.com>
+ * Author: M'boumba Cedric Madianga
  */
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
@@ -1054,11 +1054,7 @@ static int __init ab8500_gpadc_init(void
 {
 	return platform_driver_register(&ab8500_gpadc_driver);
 }
-
-static void __exit ab8500_gpadc_exit(void)
-{
-	platform_driver_unregister(&ab8500_gpadc_driver);
-}
+subsys_initcall_sync(ab8500_gpadc_init);
 
 /**
  * ab8540_gpadc_get_otp() - returns OTP values
@@ -1077,14 +1073,3 @@ void ab8540_gpadc_get_otp(struct ab8500_
 	*ibat_l  = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_lo;
 	*ibat_h  = gpadc->cal_data[ADC_INPUT_IBAT].otp_calib_hi;
 }
-
-subsys_initcall_sync(ab8500_gpadc_init);
-module_exit(ab8500_gpadc_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Arun R Murthy");
-MODULE_AUTHOR("Daniel Willerud");
-MODULE_AUTHOR("Johan Palsson");
-MODULE_AUTHOR("M'boumba Cedric Madianga");
-MODULE_ALIAS("platform:ab8500_gpadc");
-MODULE_DESCRIPTION("AB8500 GPADC driver");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/ab8500-sysctrl.c linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-sysctrl.c
--- linux-libre-4.9-gnu/drivers/mfd/ab8500-sysctrl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/ab8500-sysctrl.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,11 +1,14 @@
 /*
+ * AB8500 system control driver
+ *
  * Copyright (C) ST-Ericsson SA 2010
  * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST Ericsson.
  * License terms: GNU General Public License (GPL) version 2
  */
 
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/reboot.h>
@@ -158,7 +161,3 @@ static int __init ab8500_sysctrl_init(vo
 	return platform_driver_register(&ab8500_sysctrl_driver);
 }
 arch_initcall(ab8500_sysctrl_init);
-
-MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com");
-MODULE_DESCRIPTION("AB8500 system control driver");
-MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/abx500-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/abx500-core.c
--- linux-libre-4.9-gnu/drivers/mfd/abx500-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/abx500-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,8 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/export.h>
 #include <linux/mfd/abx500.h>
 
 static LIST_HEAD(abx500_list);
@@ -150,7 +151,3 @@ int abx500_startup_irq_enabled(struct de
 		return -ENOTSUPP;
 }
 EXPORT_SYMBOL(abx500_startup_irq_enabled);
-
-MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
-MODULE_DESCRIPTION("ABX500 core driver");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/arizona-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/arizona-core.c
--- linux-libre-4.9-gnu/drivers/mfd/arizona-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/arizona-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1553,6 +1553,7 @@ EXPORT_SYMBOL_GPL(arizona_dev_init);
 
 int arizona_dev_exit(struct arizona *arizona)
 {
+	disable_irq(arizona->irq);
 	pm_runtime_disable(arizona->dev);
 
 	regulator_disable(arizona->dcvdd);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/arizona-irq.c linux-libre-4.10-rc8-gnu/drivers/mfd/arizona-irq.c
--- linux-libre-4.9-gnu/drivers/mfd/arizona-irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/arizona-irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -398,10 +398,10 @@ err_ctrlif:
 err_boot_done:
 	free_irq(arizona->irq, arizona);
 err_main_irq:
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
+	regmap_del_irq_chip(irq_find_mapping(arizona->virq, 1),
 			    arizona->irq_chip);
 err_aod:
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
+	regmap_del_irq_chip(irq_find_mapping(arizona->virq, 0),
 			    arizona->aod_irq_chip);
 err:
 	return ret;
@@ -413,9 +413,9 @@ int arizona_irq_exit(struct arizona *ari
 		free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_CTRLIF_ERR),
 			 arizona);
 	free_irq(arizona_map_irq(arizona, ARIZONA_IRQ_BOOT_DONE), arizona);
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 1),
+	regmap_del_irq_chip(irq_find_mapping(arizona->virq, 1),
 			    arizona->irq_chip);
-	regmap_del_irq_chip(irq_create_mapping(arizona->virq, 0),
+	regmap_del_irq_chip(irq_find_mapping(arizona->virq, 0),
 			    arizona->aod_irq_chip);
 	free_irq(arizona->irq, arizona);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/axp20x.c linux-libre-4.10-rc8-gnu/drivers/mfd/axp20x.c
--- linux-libre-4.9-gnu/drivers/mfd/axp20x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/axp20x.c	2017-02-12 16:03:20.000000000 -0500
@@ -98,6 +98,7 @@ static const struct regmap_range axp22x_
 	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
 	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP22X_PMIC_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
 	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
 };
 
@@ -135,6 +136,7 @@ static const struct regmap_range axp806_
 	regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN),
 	regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
+	regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
 };
 
 static const struct regmap_range axp806_volatile_ranges[] = {
@@ -305,7 +307,7 @@ static const struct regmap_config axp806
 	.val_bits	= 8,
 	.wr_table	= &axp806_writeable_table,
 	.volatile_table	= &axp806_volatile_table,
-	.max_register	= AXP806_VREF_TEMP_WARN_L,
+	.max_register	= AXP806_REG_ADDR_EXT,
 	.cache_type	= REGCACHE_RBTREE,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/axp20x-i2c.c linux-libre-4.10-rc8-gnu/drivers/mfd/axp20x-i2c.c
--- linux-libre-4.9-gnu/drivers/mfd/axp20x-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/axp20x-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -69,10 +69,11 @@ static const struct of_device_id axp20x_
 };
 MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
 
-/*
- * This is useless for OF-enabled devices, but it is needed by I2C subsystem
- */
 static const struct i2c_device_id axp20x_i2c_id[] = {
+	{ "axp152", 0 },
+	{ "axp202", 0 },
+	{ "axp209", 0 },
+	{ "axp221", 0 },
 	{ },
 };
 MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/bcm590xx.c linux-libre-4.10-rc8-gnu/drivers/mfd/bcm590xx.c
--- linux-libre-4.9-gnu/drivers/mfd/bcm590xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/bcm590xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -67,7 +67,7 @@ static int bcm590xx_i2c_probe(struct i2c
 	/* Secondary I2C slave address is the base address with A(2) asserted */
 	bcm590xx->i2c_sec = i2c_new_dummy(i2c_pri->adapter,
 					  i2c_pri->addr | BIT(2));
-	if (IS_ERR_OR_NULL(bcm590xx->i2c_sec)) {
+	if (!bcm590xx->i2c_sec) {
 		dev_err(&i2c_pri->dev, "failed to add secondary I2C device\n");
 		return -ENODEV;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/cs47l24-tables.c linux-libre-4.10-rc8-gnu/drivers/mfd/cs47l24-tables.c
--- linux-libre-4.9-gnu/drivers/mfd/cs47l24-tables.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/cs47l24-tables.c	2017-02-12 16:03:20.000000000 -0500
@@ -292,6 +292,7 @@ static const struct reg_default cs47l24_
 	{ 0x00000502, 0x0000 },    /* R1282  - AIF1 Rx Pin Ctrl */
 	{ 0x00000503, 0x0000 },    /* R1283  - AIF1 Rate Ctrl */
 	{ 0x00000504, 0x0000 },    /* R1284  - AIF1 Format */
+	{ 0x00000505, 0x0040 },    /* R1285  - AIF1 Tx BCLK Rate */
 	{ 0x00000506, 0x0040 },    /* R1286  - AIF1 Rx BCLK Rate */
 	{ 0x00000507, 0x1818 },    /* R1287  - AIF1 Frame Ctrl 1 */
 	{ 0x00000508, 0x1818 },    /* R1288  - AIF1 Frame Ctrl 2 */
@@ -318,6 +319,7 @@ static const struct reg_default cs47l24_
 	{ 0x00000542, 0x0000 },    /* R1346  - AIF2 Rx Pin Ctrl */
 	{ 0x00000543, 0x0000 },    /* R1347  - AIF2 Rate Ctrl */
 	{ 0x00000544, 0x0000 },    /* R1348  - AIF2 Format */
+	{ 0x00000545, 0x0040 },    /* R1349  - AIF2 Tx BCLK Rate */
 	{ 0x00000546, 0x0040 },    /* R1350  - AIF2 Rx BCLK Rate */
 	{ 0x00000547, 0x1818 },    /* R1351  - AIF2 Frame Ctrl 1 */
 	{ 0x00000548, 0x1818 },    /* R1352  - AIF2 Frame Ctrl 2 */
@@ -340,6 +342,7 @@ static const struct reg_default cs47l24_
 	{ 0x00000582, 0x0000 },    /* R1410  - AIF3 Rx Pin Ctrl */
 	{ 0x00000583, 0x0000 },    /* R1411  - AIF3 Rate Ctrl */
 	{ 0x00000584, 0x0000 },    /* R1412  - AIF3 Format */
+	{ 0x00000585, 0x0040 },    /* R1413  - AIF3 Tx BCLK Rate */
 	{ 0x00000586, 0x0040 },    /* R1414  - AIF3 Rx BCLK Rate */
 	{ 0x00000587, 0x1818 },    /* R1415  - AIF3 Frame Ctrl 1 */
 	{ 0x00000588, 0x1818 },    /* R1416  - AIF3 Frame Ctrl 2 */
@@ -923,6 +926,7 @@ static bool cs47l24_readable_register(st
 	case ARIZONA_AIF1_RX_PIN_CTRL:
 	case ARIZONA_AIF1_RATE_CTRL:
 	case ARIZONA_AIF1_FORMAT:
+	case ARIZONA_AIF1_TX_BCLK_RATE:
 	case ARIZONA_AIF1_RX_BCLK_RATE:
 	case ARIZONA_AIF1_FRAME_CTRL_1:
 	case ARIZONA_AIF1_FRAME_CTRL_2:
@@ -949,6 +953,7 @@ static bool cs47l24_readable_register(st
 	case ARIZONA_AIF2_RX_PIN_CTRL:
 	case ARIZONA_AIF2_RATE_CTRL:
 	case ARIZONA_AIF2_FORMAT:
+	case ARIZONA_AIF2_TX_BCLK_RATE:
 	case ARIZONA_AIF2_RX_BCLK_RATE:
 	case ARIZONA_AIF2_FRAME_CTRL_1:
 	case ARIZONA_AIF2_FRAME_CTRL_2:
@@ -971,6 +976,7 @@ static bool cs47l24_readable_register(st
 	case ARIZONA_AIF3_RX_PIN_CTRL:
 	case ARIZONA_AIF3_RATE_CTRL:
 	case ARIZONA_AIF3_FORMAT:
+	case ARIZONA_AIF3_TX_BCLK_RATE:
 	case ARIZONA_AIF3_RX_BCLK_RATE:
 	case ARIZONA_AIF3_FRAME_CTRL_1:
 	case ARIZONA_AIF3_FRAME_CTRL_2:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/davinci_voicecodec.c linux-libre-4.10-rc8-gnu/drivers/mfd/davinci_voicecodec.c
--- linux-libre-4.9-gnu/drivers/mfd/davinci_voicecodec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/davinci_voicecodec.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,6 +32,7 @@
 #include <sound/pcm.h>
 
 #include <linux/mfd/davinci_voicecodec.h>
+#include <mach/hardware.h>
 
 static const struct regmap_config davinci_vc_regmap = {
 	.reg_bits = 32,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/fsl-imx25-tsadc.c linux-libre-4.10-rc8-gnu/drivers/mfd/fsl-imx25-tsadc.c
--- linux-libre-4.9-gnu/drivers/mfd/fsl-imx25-tsadc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/fsl-imx25-tsadc.c	2017-02-12 16:03:20.000000000 -0500
@@ -187,6 +187,7 @@ static const struct of_device_id mx25_ts
 	{ .compatible = "fsl,imx25-tsadc" },
 	{ /* Sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, mx25_tsadc_ids);
 
 static struct platform_driver mx25_tsadc_driver = {
 	.driver = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/hi655x-pmic.c linux-libre-4.10-rc8-gnu/drivers/mfd/hi655x-pmic.c
--- linux-libre-4.9-gnu/drivers/mfd/hi655x-pmic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/hi655x-pmic.c	2017-02-12 16:03:20.000000000 -0500
@@ -169,6 +169,7 @@ static const struct of_device_id hi655x_
 	{ .compatible = "hisilicon,hi655x-pmic", },
 	{},
 };
+MODULE_DEVICE_TABLE(of, hi655x_pmic_match);
 
 static struct platform_driver hi655x_pmic_driver = {
 	.driver	= {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/intel-lpss-pci.c linux-libre-4.10-rc8-gnu/drivers/mfd/intel-lpss-pci.c
--- linux-libre-4.9-gnu/drivers/mfd/intel-lpss-pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/intel-lpss-pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,7 @@ static int intel_lpss_pci_probe(struct p
 
 	/* Probably it is enough to set this for iDMA capable devices only */
 	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
 
 	ret = intel_lpss_probe(&pdev->dev, info);
 	if (ret)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/intel_soc_pmic_bxtwc.c linux-libre-4.10-rc8-gnu/drivers/mfd/intel_soc_pmic_bxtwc.c
--- linux-libre-4.9-gnu/drivers/mfd/intel_soc_pmic_bxtwc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/intel_soc_pmic_bxtwc.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,7 @@
 #define BXTWC_GPIOIRQ0		0x4E0B
 #define BXTWC_GPIOIRQ1		0x4E0C
 #define BXTWC_CRITIRQ		0x4E0D
+#define BXTWC_TMUIRQ		0x4FB6
 
 /* Interrupt MASK Registers */
 #define BXTWC_MIRQLVL1		0x4E0E
@@ -59,6 +60,7 @@
 #define BXTWC_MGPIO0IRQ		0x4E19
 #define BXTWC_MGPIO1IRQ		0x4E1A
 #define BXTWC_MCRITIRQ		0x4E1B
+#define BXTWC_MTMUIRQ		0x4FB7
 
 /* Whiskey Cove PMIC share same ACPI ID between different platforms */
 #define BROXTON_PMIC_WC_HRV	4
@@ -92,6 +94,7 @@ enum bxtwc_irqs_level2 {
 	BXTWC_GPIO0_IRQ,
 	BXTWC_GPIO1_IRQ,
 	BXTWC_CRIT_IRQ,
+	BXTWC_TMU_IRQ,
 };
 
 static const struct regmap_irq bxtwc_regmap_irqs[] = {
@@ -120,6 +123,10 @@ static const struct regmap_irq bxtwc_reg
 	REGMAP_IRQ_REG(BXTWC_CRIT_IRQ, 9, 0x03),
 };
 
+static const struct regmap_irq bxtwc_regmap_irqs_tmu[] = {
+	REGMAP_IRQ_REG(BXTWC_TMU_IRQ, 0, 0x06),
+};
+
 static struct regmap_irq_chip bxtwc_regmap_irq_chip = {
 	.name = "bxtwc_irq_chip",
 	.status_base = BXTWC_IRQLVL1,
@@ -138,6 +145,15 @@ static struct regmap_irq_chip bxtwc_regm
 	.num_regs = 10,
 };
 
+static struct regmap_irq_chip bxtwc_regmap_irq_chip_tmu = {
+	.name = "bxtwc_irq_chip_tmu",
+	.status_base = BXTWC_TMUIRQ,
+	.mask_base = BXTWC_MTMUIRQ,
+	.irqs = bxtwc_regmap_irqs_tmu,
+	.num_irqs = ARRAY_SIZE(bxtwc_regmap_irqs_tmu),
+	.num_regs = 1,
+};
+
 static struct resource gpio_resources[] = {
 	DEFINE_RES_IRQ_NAMED(BXTWC_GPIO0_IRQ, "GPIO0"),
 	DEFINE_RES_IRQ_NAMED(BXTWC_GPIO1_IRQ, "GPIO1"),
@@ -166,6 +182,10 @@ static struct resource bcu_resources[] =
 	DEFINE_RES_IRQ_NAMED(BXTWC_BCU_IRQ, "BCU"),
 };
 
+static struct resource tmu_resources[] = {
+	DEFINE_RES_IRQ_NAMED(BXTWC_TMU_IRQ, "TMU"),
+};
+
 static struct mfd_cell bxt_wc_dev[] = {
 	{
 		.name = "bxt_wcove_gpadc",
@@ -193,6 +213,12 @@ static struct mfd_cell bxt_wc_dev[] = {
 		.resources = bcu_resources,
 	},
 	{
+		.name = "bxt_wcove_tmu",
+		.num_resources = ARRAY_SIZE(tmu_resources),
+		.resources = tmu_resources,
+	},
+
+	{
 		.name = "bxt_wcove_gpio",
 		.num_resources = ARRAY_SIZE(gpio_resources),
 		.resources = gpio_resources,
@@ -402,6 +428,15 @@ static int bxtwc_probe(struct platform_d
 		goto err_irq_chip_level2;
 	}
 
+	ret = regmap_add_irq_chip(pmic->regmap, pmic->irq,
+				  IRQF_ONESHOT | IRQF_SHARED,
+				  0, &bxtwc_regmap_irq_chip_tmu,
+				  &pmic->irq_chip_data_tmu);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add TMU IRQ chip\n");
+		goto err_irq_chip_tmu;
+	}
+
 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev,
 			      ARRAY_SIZE(bxt_wc_dev), NULL, 0,
 			      NULL);
@@ -431,6 +466,8 @@ static int bxtwc_probe(struct platform_d
 err_sysfs:
 	mfd_remove_devices(&pdev->dev);
 err_mfd:
+	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_tmu);
+err_irq_chip_tmu:
 	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
 err_irq_chip_level2:
 	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
@@ -446,6 +483,7 @@ static int bxtwc_remove(struct platform_
 	mfd_remove_devices(&pdev->dev);
 	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
 	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_level2);
+	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data_tmu);
 
 	return 0;
 }
@@ -481,7 +519,7 @@ static const struct acpi_device_id bxtwc
 	{ "INT34D3", },
 	{ }
 };
-MODULE_DEVICE_TABLE(acpi, pmic_acpi_ids);
+MODULE_DEVICE_TABLE(acpi, bxtwc_acpi_ids);
 
 static struct platform_driver bxtwc_driver = {
 	.probe = bxtwc_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/Kconfig linux-libre-4.10-rc8-gnu/drivers/mfd/Kconfig
--- linux-libre-4.9-gnu/drivers/mfd/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -40,6 +40,22 @@ config MFD_ACT8945A
 	  linear regulators, along with a complete ActivePath battery
 	  charger.
 
+config MFD_SUN4I_GPADC
+	tristate "Allwinner sunxi platforms' GPADC MFD driver"
+	select MFD_CORE
+	select REGMAP_MMIO
+	select REGMAP_IRQ
+	depends on ARCH_SUNXI || COMPILE_TEST
+	help
+	  Select this to get support for Allwinner SoCs (A10, A13 and A31) ADC.
+	  This driver will only map the hardware interrupt and registers, you
+	  have to select individual drivers based on this MFD to be able to use
+	  the ADC or the thermal sensor. This will try to probe the ADC driver
+	  sun4i-gpadc-iio and the hwmon driver iio_hwmon.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called sun4i-gpadc.
+
 config MFD_AS3711
 	bool "AMS AS3711"
 	select MFD_CORE
@@ -293,6 +309,7 @@ config MFD_DLN2
 
 config MFD_EXYNOS_LPASS
 	tristate "Samsung Exynos SoC Low Power Audio Subsystem"
+	depends on ARCH_EXYNOS || COMPILE_TEST
 	select MFD_CORE
 	select REGMAP_MMIO
 	help
@@ -563,7 +580,7 @@ config MFD_MAX14577
 config MFD_MAX77620
 	bool "Maxim Semiconductor MAX77620 and MAX20024 PMIC Support"
 	depends on I2C=y
-	depends on OF
+	depends on OF || COMPILE_TEST
 	select MFD_CORE
 	select REGMAP_I2C
 	select REGMAP_IRQ
@@ -578,7 +595,7 @@ config MFD_MAX77620
 config MFD_MAX77686
 	tristate "Maxim Semiconductor MAX77686/802 PMIC Support"
 	depends on I2C
-	depends on OF
+	depends on OF || COMPILE_TEST
 	select MFD_CORE
 	select REGMAP_I2C
 	select REGMAP_IRQ
@@ -756,24 +773,20 @@ config UCB1400_CORE
 	  module will be called ucb1400_core.
 
 config MFD_PM8XXX
-	tristate
-
-config MFD_PM8921_CORE
-	tristate "Qualcomm PM8921 PMIC chip"
+	tristate "Qualcomm PM8xxx PMIC chips driver"
 	depends on (ARM || HEXAGON)
 	select IRQ_DOMAIN
 	select MFD_CORE
-	select MFD_PM8XXX
 	select REGMAP
 	help
 	  If you say yes to this option, support will be included for the
-	  built-in PM8921 PMIC chip.
+	  built-in PM8xxx PMIC chips.
 
-	  This is required if your board has a PM8921 and uses its features,
+	  This is required if your board has a PM8xxx and uses its features,
 	  such as: MPPs, GPIOs, regulators, interrupts, and PWM.
 
-	  Say M here if you want to include support for PM8921 chip as a module.
-	  This will build a module called "pm8921-core".
+	  Say M here if you want to include support for PM8xxx chips as a
+	  module. This will build a module called "pm8xxx-core".
 
 config MFD_QCOM_RPM
 	tristate "Qualcomm Resource Power Manager (RPM)"
@@ -881,7 +894,8 @@ config MFD_RN5T618
 	select MFD_CORE
 	select REGMAP_I2C
 	help
-	  Say yes here to add support for the Ricoh RN5T567 or R5T618 PMIC.
+	  Say yes here to add support for the Ricoh RN5T567,
+          RN5T618, RC5T619 PMIC.
 	  This driver provides common support for accessing the device,
 	  additional drivers must be enabled in order to use the
 	  functionality of the device.
@@ -955,7 +969,7 @@ config MFD_SMSC
 
 config ABX500_CORE
 	bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions"
-	default y if ARCH_U300 || ARCH_U8500
+	default y if ARCH_U300 || ARCH_U8500 || COMPILE_TEST
 	help
 	  Say yes here if you have the ABX500 Mixed Signal IC family
 	  chips. This core driver expose register access functions.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/lpc_ich.c linux-libre-4.10-rc8-gnu/drivers/mfd/lpc_ich.c
--- linux-libre-4.9-gnu/drivers/mfd/lpc_ich.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/lpc_ich.c	2017-02-12 16:03:20.000000000 -0500
@@ -493,6 +493,7 @@ static struct lpc_ich_info lpc_chipset_i
 	[LPC_LPT] = {
 		.name = "Lynx Point",
 		.iTCO_version = 2,
+		.gpio_version = ICH_V5_GPIO,
 	},
 	[LPC_LPT_LP] = {
 		.name = "Lynx Point_LP",
@@ -530,6 +531,7 @@ static struct lpc_ich_info lpc_chipset_i
 	[LPC_9S] = {
 		.name = "9 Series",
 		.iTCO_version = 2,
+		.gpio_version = ICH_V5_GPIO,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/Makefile linux-libre-4.10-rc8-gnu/drivers/mfd/Makefile
--- linux-libre-4.9-gnu/drivers/mfd/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -172,7 +172,7 @@ obj-$(CONFIG_MFD_SI476X_CORE)	+= si476x-
 
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
-obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o ssbi.o
+obj-$(CONFIG_MFD_PM8XXX) 	+= qcom-pm8xxx.o ssbi.o
 obj-$(CONFIG_MFD_QCOM_RPM)	+= qcom_rpm.o
 obj-$(CONFIG_MFD_SPMI_PMIC)	+= qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
@@ -211,3 +211,4 @@ obj-$(CONFIG_INTEL_SOC_PMIC)	+= intel-so
 obj-$(CONFIG_MFD_MT6397)	+= mt6397-core.o
 
 obj-$(CONFIG_MFD_ALTERA_A10SR)	+= altera-a10sr.o
+obj-$(CONFIG_MFD_SUN4I_GPADC)	+= sun4i-gpadc.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/max77620.c linux-libre-4.10-rc8-gnu/drivers/mfd/max77620.c
--- linux-libre-4.9-gnu/drivers/mfd/max77620.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/max77620.c	2017-02-12 16:03:20.000000000 -0500
@@ -461,7 +461,7 @@ static int max77620_probe(struct i2c_cli
 	chip->rmap = devm_regmap_init_i2c(client, rmap_config);
 	if (IS_ERR(chip->rmap)) {
 		ret = PTR_ERR(chip->rmap);
-		dev_err(chip->dev, "Failed to intialise regmap: %d\n", ret);
+		dev_err(chip->dev, "Failed to initialise regmap: %d\n", ret);
 		return ret;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/palmas.c linux-libre-4.10-rc8-gnu/drivers/mfd/palmas.c
--- linux-libre-4.9-gnu/drivers/mfd/palmas.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/palmas.c	2017-02-12 16:03:20.000000000 -0500
@@ -431,9 +431,6 @@ static void palmas_power_off(void)
 	unsigned int addr;
 	int ret, slave;
 
-	if (!palmas_dev)
-		return;
-
 	slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE);
 	addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/pm8921-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/pm8921-core.c
--- linux-libre-4.9-gnu/drivers/mfd/pm8921-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/pm8921-core.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,429 +0,0 @@
-/*
- * 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.
- */
-
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include <linux/ssbi.h>
-#include <linux/regmap.h>
-#include <linux/of_platform.h>
-#include <linux/mfd/core.h>
-
-#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
-
-#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
-#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
-#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
-#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
-#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
-#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
-
-#define	PM_IRQF_LVL_SEL			0x01	/* level select */
-#define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
-#define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
-#define	PM_IRQF_CLR			0x08	/* clear interrupt */
-#define	PM_IRQF_BITS_MASK		0x70
-#define	PM_IRQF_BITS_SHIFT		4
-#define	PM_IRQF_WRITE			0x80
-
-#define	PM_IRQF_MASK_ALL		(PM_IRQF_MASK_FE | \
-					PM_IRQF_MASK_RE)
-
-#define REG_HWREV		0x002  /* PMIC4 revision */
-#define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
-
-#define PM8921_NR_IRQS		256
-
-struct pm_irq_chip {
-	struct regmap		*regmap;
-	spinlock_t		pm_irq_lock;
-	struct irq_domain	*irqdomain;
-	unsigned int		num_irqs;
-	unsigned int		num_blocks;
-	unsigned int		num_masters;
-	u8			config[0];
-};
-
-static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
-				 unsigned int *ip)
-{
-	int	rc;
-
-	spin_lock(&chip->pm_irq_lock);
-	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
-	if (rc) {
-		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
-		goto bail;
-	}
-
-	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
-	if (rc)
-		pr_err("Failed Reading Status rc=%d\n", rc);
-bail:
-	spin_unlock(&chip->pm_irq_lock);
-	return rc;
-}
-
-static int
-pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
-{
-	int	rc;
-
-	spin_lock(&chip->pm_irq_lock);
-	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
-	if (rc) {
-		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
-		goto bail;
-	}
-
-	cp |= PM_IRQF_WRITE;
-	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
-	if (rc)
-		pr_err("Failed Configuring IRQ rc=%d\n", rc);
-bail:
-	spin_unlock(&chip->pm_irq_lock);
-	return rc;
-}
-
-static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
-{
-	int pmirq, irq, i, ret = 0;
-	unsigned int bits;
-
-	ret = pm8xxx_read_block_irq(chip, block, &bits);
-	if (ret) {
-		pr_err("Failed reading %d block ret=%d", block, ret);
-		return ret;
-	}
-	if (!bits) {
-		pr_err("block bit set in master but no irqs: %d", block);
-		return 0;
-	}
-
-	/* Check IRQ bits */
-	for (i = 0; i < 8; i++) {
-		if (bits & (1 << i)) {
-			pmirq = block * 8 + i;
-			irq = irq_find_mapping(chip->irqdomain, pmirq);
-			generic_handle_irq(irq);
-		}
-	}
-	return 0;
-}
-
-static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
-{
-	unsigned int blockbits;
-	int block_number, i, ret = 0;
-
-	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
-			  &blockbits);
-	if (ret) {
-		pr_err("Failed to read master %d ret=%d\n", master, ret);
-		return ret;
-	}
-	if (!blockbits) {
-		pr_err("master bit set in root but no blocks: %d", master);
-		return 0;
-	}
-
-	for (i = 0; i < 8; i++)
-		if (blockbits & (1 << i)) {
-			block_number = master * 8 + i;	/* block # */
-			ret |= pm8xxx_irq_block_handler(chip, block_number);
-		}
-	return ret;
-}
-
-static void pm8xxx_irq_handler(struct irq_desc *desc)
-{
-	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
-	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
-	unsigned int root;
-	int	i, ret, masters = 0;
-
-	chained_irq_enter(irq_chip, desc);
-
-	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
-	if (ret) {
-		pr_err("Can't read root status ret=%d\n", ret);
-		return;
-	}
-
-	/* on pm8xxx series masters start from bit 1 of the root */
-	masters = root >> 1;
-
-	/* Read allowed masters for blocks. */
-	for (i = 0; i < chip->num_masters; i++)
-		if (masters & (1 << i))
-			pm8xxx_irq_master_handler(chip, i);
-
-	chained_irq_exit(irq_chip, desc);
-}
-
-static void pm8xxx_irq_mask_ack(struct irq_data *d)
-{
-	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = irqd_to_hwirq(d);
-	u8	block, config;
-
-	block = pmirq / 8;
-
-	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
-	pm8xxx_config_irq(chip, block, config);
-}
-
-static void pm8xxx_irq_unmask(struct irq_data *d)
-{
-	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = irqd_to_hwirq(d);
-	u8	block, config;
-
-	block = pmirq / 8;
-
-	config = chip->config[pmirq];
-	pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
-{
-	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = irqd_to_hwirq(d);
-	int irq_bit;
-	u8 block, config;
-
-	block = pmirq / 8;
-	irq_bit  = pmirq % 8;
-
-	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
-							| PM_IRQF_MASK_ALL;
-	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
-		if (flow_type & IRQF_TRIGGER_RISING)
-			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
-		if (flow_type & IRQF_TRIGGER_FALLING)
-			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
-	} else {
-		chip->config[pmirq] |= PM_IRQF_LVL_SEL;
-
-		if (flow_type & IRQF_TRIGGER_HIGH)
-			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
-		else
-			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
-	}
-
-	config = chip->config[pmirq] | PM_IRQF_CLR;
-	return pm8xxx_config_irq(chip, block, config);
-}
-
-static int pm8xxx_irq_get_irqchip_state(struct irq_data *d,
-					enum irqchip_irq_state which,
-					bool *state)
-{
-	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
-	unsigned int pmirq = irqd_to_hwirq(d);
-	unsigned int bits;
-	int irq_bit;
-	u8 block;
-	int rc;
-
-	if (which != IRQCHIP_STATE_LINE_LEVEL)
-		return -EINVAL;
-
-	block = pmirq / 8;
-	irq_bit = pmirq % 8;
-
-	spin_lock(&chip->pm_irq_lock);
-	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
-	if (rc) {
-		pr_err("Failed Selecting Block %d rc=%d\n", block, rc);
-		goto bail;
-	}
-
-	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
-	if (rc) {
-		pr_err("Failed Reading Status rc=%d\n", rc);
-		goto bail;
-	}
-
-	*state = !!(bits & BIT(irq_bit));
-bail:
-	spin_unlock(&chip->pm_irq_lock);
-
-	return rc;
-}
-
-static struct irq_chip pm8xxx_irq_chip = {
-	.name		= "pm8xxx",
-	.irq_mask_ack	= pm8xxx_irq_mask_ack,
-	.irq_unmask	= pm8xxx_irq_unmask,
-	.irq_set_type	= pm8xxx_irq_set_type,
-	.irq_get_irqchip_state = pm8xxx_irq_get_irqchip_state,
-	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
-};
-
-static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
-				   irq_hw_number_t hwirq)
-{
-	struct pm_irq_chip *chip = d->host_data;
-
-	irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq);
-	irq_set_chip_data(irq, chip);
-	irq_set_noprobe(irq);
-
-	return 0;
-}
-
-static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
-	.xlate = irq_domain_xlate_twocell,
-	.map = pm8xxx_irq_domain_map,
-};
-
-static const struct regmap_config ssbi_regmap_config = {
-	.reg_bits = 16,
-	.val_bits = 8,
-	.max_register = 0x3ff,
-	.fast_io = true,
-	.reg_read = ssbi_reg_read,
-	.reg_write = ssbi_reg_write
-};
-
-static const struct of_device_id pm8921_id_table[] = {
-	{ .compatible = "qcom,pm8018", },
-	{ .compatible = "qcom,pm8058", },
-	{ .compatible = "qcom,pm8921", },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, pm8921_id_table);
-
-static int pm8921_probe(struct platform_device *pdev)
-{
-	struct regmap *regmap;
-	int irq, rc;
-	unsigned int val;
-	u32 rev;
-	struct pm_irq_chip *chip;
-	unsigned int nirqs = PM8921_NR_IRQS;
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
-				  &ssbi_regmap_config);
-	if (IS_ERR(regmap))
-		return PTR_ERR(regmap);
-
-	/* Read PMIC chip revision */
-	rc = regmap_read(regmap, REG_HWREV, &val);
-	if (rc) {
-		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
-		return rc;
-	}
-	pr_info("PMIC revision 1: %02X\n", val);
-	rev = val;
-
-	/* Read PMIC chip revision 2 */
-	rc = regmap_read(regmap, REG_HWREV_2, &val);
-	if (rc) {
-		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
-			REG_HWREV_2, rc);
-		return rc;
-	}
-	pr_info("PMIC revision 2: %02X\n", val);
-	rev |= val << BITS_PER_BYTE;
-
-	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
-					sizeof(chip->config[0]) * nirqs,
-					GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, chip);
-	chip->regmap = regmap;
-	chip->num_irqs = nirqs;
-	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
-	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
-	spin_lock_init(&chip->pm_irq_lock);
-
-	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
-						&pm8xxx_irq_domain_ops,
-						chip);
-	if (!chip->irqdomain)
-		return -ENODEV;
-
-	irq_set_chained_handler_and_data(irq, pm8xxx_irq_handler, chip);
-	irq_set_irq_wake(irq, 1);
-
-	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
-	if (rc) {
-		irq_set_chained_handler_and_data(irq, NULL, NULL);
-		irq_domain_remove(chip->irqdomain);
-	}
-
-	return rc;
-}
-
-static int pm8921_remove_child(struct device *dev, void *unused)
-{
-	platform_device_unregister(to_platform_device(dev));
-	return 0;
-}
-
-static int pm8921_remove(struct platform_device *pdev)
-{
-	int irq = platform_get_irq(pdev, 0);
-	struct pm_irq_chip *chip = platform_get_drvdata(pdev);
-
-	device_for_each_child(&pdev->dev, NULL, pm8921_remove_child);
-	irq_set_chained_handler_and_data(irq, NULL, NULL);
-	irq_domain_remove(chip->irqdomain);
-
-	return 0;
-}
-
-static struct platform_driver pm8921_driver = {
-	.probe		= pm8921_probe,
-	.remove		= pm8921_remove,
-	.driver		= {
-		.name	= "pm8921-core",
-		.of_match_table = pm8921_id_table,
-	},
-};
-
-static int __init pm8921_init(void)
-{
-	return platform_driver_register(&pm8921_driver);
-}
-subsys_initcall(pm8921_init);
-
-static void __exit pm8921_exit(void)
-{
-	platform_driver_unregister(&pm8921_driver);
-}
-module_exit(pm8921_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("PMIC 8921 core driver");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:pm8921-core");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/qcom-pm8xxx.c linux-libre-4.10-rc8-gnu/drivers/mfd/qcom-pm8xxx.c
--- linux-libre-4.9-gnu/drivers/mfd/qcom-pm8xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/qcom-pm8xxx.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,640 @@
+/*
+ * 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/ssbi.h>
+#include <linux/regmap.h>
+#include <linux/of_platform.h>
+#include <linux/mfd/core.h>
+
+#define	SSBI_REG_ADDR_IRQ_BASE		0x1BB
+
+#define	SSBI_REG_ADDR_IRQ_ROOT		(SSBI_REG_ADDR_IRQ_BASE + 0)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS1	(SSBI_REG_ADDR_IRQ_BASE + 1)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS2	(SSBI_REG_ADDR_IRQ_BASE + 2)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS3	(SSBI_REG_ADDR_IRQ_BASE + 3)
+#define	SSBI_REG_ADDR_IRQ_M_STATUS4	(SSBI_REG_ADDR_IRQ_BASE + 4)
+#define	SSBI_REG_ADDR_IRQ_BLK_SEL	(SSBI_REG_ADDR_IRQ_BASE + 5)
+#define	SSBI_REG_ADDR_IRQ_IT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 6)
+#define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
+#define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
+
+#define	PM8821_SSBI_REG_ADDR_IRQ_BASE	0x100
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
+#define	PM8821_SSBI_REG(m, b, offset) \
+			((m == 0) ? \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
+#define	PM8821_SSBI_ADDR_IRQ_ROOT(m, b)		PM8821_SSBI_REG(m, b, 0x0)
+#define	PM8821_SSBI_ADDR_IRQ_CLEAR(m, b)	PM8821_SSBI_REG(m, b, 0x01)
+#define	PM8821_SSBI_ADDR_IRQ_MASK(m, b)		PM8821_SSBI_REG(m, b, 0x08)
+#define	PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b)	PM8821_SSBI_REG(m, b, 0x0f)
+
+#define	PM8821_BLOCKS_PER_MASTER	7
+
+#define	PM_IRQF_LVL_SEL			0x01	/* level select */
+#define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
+#define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
+#define	PM_IRQF_CLR			0x08	/* clear interrupt */
+#define	PM_IRQF_BITS_MASK		0x70
+#define	PM_IRQF_BITS_SHIFT		4
+#define	PM_IRQF_WRITE			0x80
+
+#define	PM_IRQF_MASK_ALL		(PM_IRQF_MASK_FE | \
+					PM_IRQF_MASK_RE)
+
+#define REG_HWREV		0x002  /* PMIC4 revision */
+#define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
+
+#define PM8XXX_NR_IRQS		256
+#define PM8821_NR_IRQS		112
+
+struct pm_irq_chip {
+	struct regmap		*regmap;
+	spinlock_t		pm_irq_lock;
+	struct irq_domain	*irqdomain;
+	unsigned int		num_irqs;
+	unsigned int		num_blocks;
+	unsigned int		num_masters;
+	u8			config[0];
+};
+
+struct pm_irq_data {
+	int num_irqs;
+	const struct irq_domain_ops  *irq_domain_ops;
+	void (*irq_handler)(struct irq_desc *desc);
+};
+
+static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
+				 unsigned int *ip)
+{
+	int	rc;
+
+	spin_lock(&chip->pm_irq_lock);
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	if (rc) {
+		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+		goto bail;
+	}
+
+	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_IT_STATUS, ip);
+	if (rc)
+		pr_err("Failed Reading Status rc=%d\n", rc);
+bail:
+	spin_unlock(&chip->pm_irq_lock);
+	return rc;
+}
+
+static int
+pm8xxx_config_irq(struct pm_irq_chip *chip, unsigned int bp, unsigned int cp)
+{
+	int	rc;
+
+	spin_lock(&chip->pm_irq_lock);
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, bp);
+	if (rc) {
+		pr_err("Failed Selecting Block %d rc=%d\n", bp, rc);
+		goto bail;
+	}
+
+	cp |= PM_IRQF_WRITE;
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_CONFIG, cp);
+	if (rc)
+		pr_err("Failed Configuring IRQ rc=%d\n", rc);
+bail:
+	spin_unlock(&chip->pm_irq_lock);
+	return rc;
+}
+
+static int pm8xxx_irq_block_handler(struct pm_irq_chip *chip, int block)
+{
+	int pmirq, irq, i, ret = 0;
+	unsigned int bits;
+
+	ret = pm8xxx_read_block_irq(chip, block, &bits);
+	if (ret) {
+		pr_err("Failed reading %d block ret=%d", block, ret);
+		return ret;
+	}
+	if (!bits) {
+		pr_err("block bit set in master but no irqs: %d", block);
+		return 0;
+	}
+
+	/* Check IRQ bits */
+	for (i = 0; i < 8; i++) {
+		if (bits & (1 << i)) {
+			pmirq = block * 8 + i;
+			irq = irq_find_mapping(chip->irqdomain, pmirq);
+			generic_handle_irq(irq);
+		}
+	}
+	return 0;
+}
+
+static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master)
+{
+	unsigned int blockbits;
+	int block_number, i, ret = 0;
+
+	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_M_STATUS1 + master,
+			  &blockbits);
+	if (ret) {
+		pr_err("Failed to read master %d ret=%d\n", master, ret);
+		return ret;
+	}
+	if (!blockbits) {
+		pr_err("master bit set in root but no blocks: %d", master);
+		return 0;
+	}
+
+	for (i = 0; i < 8; i++)
+		if (blockbits & (1 << i)) {
+			block_number = master * 8 + i;	/* block # */
+			ret |= pm8xxx_irq_block_handler(chip, block_number);
+		}
+	return ret;
+}
+
+static void pm8xxx_irq_handler(struct irq_desc *desc)
+{
+	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+	unsigned int root;
+	int	i, ret, masters = 0;
+
+	chained_irq_enter(irq_chip, desc);
+
+	ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root);
+	if (ret) {
+		pr_err("Can't read root status ret=%d\n", ret);
+		return;
+	}
+
+	/* on pm8xxx series masters start from bit 1 of the root */
+	masters = root >> 1;
+
+	/* Read allowed masters for blocks. */
+	for (i = 0; i < chip->num_masters; i++)
+		if (masters & (1 << i))
+			pm8xxx_irq_master_handler(chip, i);
+
+	chained_irq_exit(irq_chip, desc);
+}
+
+static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
+				     int master, int block)
+{
+	int pmirq, irq, i, ret;
+	unsigned int bits;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
+	if (ret) {
+		pr_err("Reading block %d failed ret=%d", block, ret);
+		return;
+	}
+
+	/* Convert block offset to global block number */
+	block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
+
+	/* Check IRQ bits */
+	for (i = 0; i < 8; i++) {
+		if (bits & BIT(i)) {
+			pmirq = block * 8 + i;
+			irq = irq_find_mapping(chip->irqdomain, pmirq);
+			generic_handle_irq(irq);
+		}
+	}
+}
+
+static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
+					     int master, u8 master_val)
+{
+	int block;
+
+	for (block = 1; block < 8; block++)
+		if (master_val & BIT(block))
+			pm8821_irq_block_handler(chip, master, block);
+}
+
+static void pm8821_irq_handler(struct irq_desc *desc)
+{
+	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+	unsigned int master;
+	int ret;
+
+	chained_irq_enter(irq_chip, desc);
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
+	if (ret) {
+		pr_err("Failed to read master 0 ret=%d\n", ret);
+		goto done;
+	}
+
+	/* bits 1 through 7 marks the first 7 blocks in master 0 */
+	if (master & GENMASK(7, 1))
+		pm8821_irq_master_handler(chip, 0, master);
+
+	/* bit 0 marks if master 1 contains any bits */
+	if (!(master & BIT(0)))
+		goto done;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
+	if (ret) {
+		pr_err("Failed to read master 1 ret=%d\n", ret);
+		goto done;
+	}
+
+	pm8821_irq_master_handler(chip, 1, master);
+
+done:
+	chained_irq_exit(irq_chip, desc);
+}
+
+static void pm8xxx_irq_mask_ack(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	u8	block, config;
+
+	block = pmirq / 8;
+
+	config = chip->config[pmirq] | PM_IRQF_MASK_ALL | PM_IRQF_CLR;
+	pm8xxx_config_irq(chip, block, config);
+}
+
+static void pm8xxx_irq_unmask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	u8	block, config;
+
+	block = pmirq / 8;
+
+	config = chip->config[pmirq];
+	pm8xxx_config_irq(chip, block, config);
+}
+
+static int pm8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int irq_bit;
+	u8 block, config;
+
+	block = pmirq / 8;
+	irq_bit  = pmirq % 8;
+
+	chip->config[pmirq] = (irq_bit << PM_IRQF_BITS_SHIFT)
+							| PM_IRQF_MASK_ALL;
+	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
+		if (flow_type & IRQF_TRIGGER_RISING)
+			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+		if (flow_type & IRQF_TRIGGER_FALLING)
+			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+	} else {
+		chip->config[pmirq] |= PM_IRQF_LVL_SEL;
+
+		if (flow_type & IRQF_TRIGGER_HIGH)
+			chip->config[pmirq] &= ~PM_IRQF_MASK_RE;
+		else
+			chip->config[pmirq] &= ~PM_IRQF_MASK_FE;
+	}
+
+	config = chip->config[pmirq] | PM_IRQF_CLR;
+	return pm8xxx_config_irq(chip, block, config);
+}
+
+static int pm8xxx_irq_get_irqchip_state(struct irq_data *d,
+					enum irqchip_irq_state which,
+					bool *state)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	unsigned int bits;
+	int irq_bit;
+	u8 block;
+	int rc;
+
+	if (which != IRQCHIP_STATE_LINE_LEVEL)
+		return -EINVAL;
+
+	block = pmirq / 8;
+	irq_bit = pmirq % 8;
+
+	spin_lock(&chip->pm_irq_lock);
+	rc = regmap_write(chip->regmap, SSBI_REG_ADDR_IRQ_BLK_SEL, block);
+	if (rc) {
+		pr_err("Failed Selecting Block %d rc=%d\n", block, rc);
+		goto bail;
+	}
+
+	rc = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_RT_STATUS, &bits);
+	if (rc) {
+		pr_err("Failed Reading Status rc=%d\n", rc);
+		goto bail;
+	}
+
+	*state = !!(bits & BIT(irq_bit));
+bail:
+	spin_unlock(&chip->pm_irq_lock);
+
+	return rc;
+}
+
+static struct irq_chip pm8xxx_irq_chip = {
+	.name		= "pm8xxx",
+	.irq_mask_ack	= pm8xxx_irq_mask_ack,
+	.irq_unmask	= pm8xxx_irq_unmask,
+	.irq_set_type	= pm8xxx_irq_set_type,
+	.irq_get_irqchip_state = pm8xxx_irq_get_irqchip_state,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hwirq)
+{
+	struct pm_irq_chip *chip = d->host_data;
+
+	irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq);
+	irq_set_chip_data(irq, chip);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
+	.xlate = irq_domain_xlate_twocell,
+	.map = pm8xxx_irq_domain_map,
+};
+
+static void pm8821_irq_mask_ack(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	u8 block, master;
+	int irq_bit, rc;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+	if (rc) {
+		pr_err("Failed to mask IRQ:%d rc=%d\n", pmirq, rc);
+		return;
+	}
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+	if (rc)
+		pr_err("Failed to CLEAR IRQ:%d rc=%d\n", pmirq, rc);
+}
+
+static void pm8821_irq_unmask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int irq_bit, rc;
+	u8 block, master;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), ~BIT(irq_bit));
+	if (rc)
+		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
+
+}
+
+static int pm8821_irq_get_irqchip_state(struct irq_data *d,
+					enum irqchip_irq_state which,
+					bool *state)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	int rc, pmirq = irqd_to_hwirq(d);
+	u8 block, irq_bit, master;
+	unsigned int bits;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_read(chip->regmap,
+		PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
+	if (rc) {
+		pr_err("Reading Status of IRQ %d failed rc=%d\n", pmirq, rc);
+		return rc;
+	}
+
+	*state = !!(bits & BIT(irq_bit));
+
+	return rc;
+}
+
+static struct irq_chip pm8821_irq_chip = {
+	.name		= "pm8821",
+	.irq_mask_ack	= pm8821_irq_mask_ack,
+	.irq_unmask	= pm8821_irq_unmask,
+	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hwirq)
+{
+	struct pm_irq_chip *chip = d->host_data;
+
+	irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
+	irq_set_chip_data(irq, chip);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops pm8821_irq_domain_ops = {
+	.xlate = irq_domain_xlate_twocell,
+	.map = pm8821_irq_domain_map,
+};
+
+static const struct regmap_config ssbi_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.max_register = 0x3ff,
+	.fast_io = true,
+	.reg_read = ssbi_reg_read,
+	.reg_write = ssbi_reg_write
+};
+
+static const struct pm_irq_data pm8xxx_data = {
+	.num_irqs = PM8XXX_NR_IRQS,
+	.irq_domain_ops = &pm8xxx_irq_domain_ops,
+	.irq_handler = pm8xxx_irq_handler,
+};
+
+static const struct pm_irq_data pm8821_data = {
+	.num_irqs = PM8821_NR_IRQS,
+	.irq_domain_ops = &pm8821_irq_domain_ops,
+	.irq_handler = pm8821_irq_handler,
+};
+
+static const struct of_device_id pm8xxx_id_table[] = {
+	{ .compatible = "qcom,pm8018", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8821", .data = &pm8821_data},
+	{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
+
+static int pm8xxx_probe(struct platform_device *pdev)
+{
+	const struct pm_irq_data *data;
+	struct regmap *regmap;
+	int irq, rc;
+	unsigned int val;
+	u32 rev;
+	struct pm_irq_chip *chip;
+
+	data = of_device_get_match_data(&pdev->dev);
+	if (!data) {
+		dev_err(&pdev->dev, "No matching driver data found\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	regmap = devm_regmap_init(&pdev->dev, NULL, pdev->dev.parent,
+				  &ssbi_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	/* Read PMIC chip revision */
+	rc = regmap_read(regmap, REG_HWREV, &val);
+	if (rc) {
+		pr_err("Failed to read hw rev reg %d:rc=%d\n", REG_HWREV, rc);
+		return rc;
+	}
+	pr_info("PMIC revision 1: %02X\n", val);
+	rev = val;
+
+	/* Read PMIC chip revision 2 */
+	rc = regmap_read(regmap, REG_HWREV_2, &val);
+	if (rc) {
+		pr_err("Failed to read hw rev 2 reg %d:rc=%d\n",
+			REG_HWREV_2, rc);
+		return rc;
+	}
+	pr_info("PMIC revision 2: %02X\n", val);
+	rev |= val << BITS_PER_BYTE;
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
+			    sizeof(chip->config[0]) * data->num_irqs,
+			    GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, chip);
+	chip->regmap = regmap;
+	chip->num_irqs = data->num_irqs;
+	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
+	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
+	spin_lock_init(&chip->pm_irq_lock);
+
+	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
+						data->num_irqs,
+						data->irq_domain_ops,
+						chip);
+	if (!chip->irqdomain)
+		return -ENODEV;
+
+	irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
+	irq_set_irq_wake(irq, 1);
+
+	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (rc) {
+		irq_set_chained_handler_and_data(irq, NULL, NULL);
+		irq_domain_remove(chip->irqdomain);
+	}
+
+	return rc;
+}
+
+static int pm8xxx_remove_child(struct device *dev, void *unused)
+{
+	platform_device_unregister(to_platform_device(dev));
+	return 0;
+}
+
+static int pm8xxx_remove(struct platform_device *pdev)
+{
+	int irq = platform_get_irq(pdev, 0);
+	struct pm_irq_chip *chip = platform_get_drvdata(pdev);
+
+	device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child);
+	irq_set_chained_handler_and_data(irq, NULL, NULL);
+	irq_domain_remove(chip->irqdomain);
+
+	return 0;
+}
+
+static struct platform_driver pm8xxx_driver = {
+	.probe		= pm8xxx_probe,
+	.remove		= pm8xxx_remove,
+	.driver		= {
+		.name	= "pm8xxx-core",
+		.of_match_table = pm8xxx_id_table,
+	},
+};
+
+static int __init pm8xxx_init(void)
+{
+	return platform_driver_register(&pm8xxx_driver);
+}
+subsys_initcall(pm8xxx_init);
+
+static void __exit pm8xxx_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_driver);
+}
+module_exit(pm8xxx_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("PMIC 8xxx core driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:pm8xxx-core");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/rk808.c linux-libre-4.10-rc8-gnu/drivers/mfd/rk808.c
--- linux-libre-4.9-gnu/drivers/mfd/rk808.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/rk808.c	2017-02-12 16:03:20.000000000 -0500
@@ -290,6 +290,24 @@ static void rk808_device_shutdown(void)
 		dev_err(&rk808_i2c_client->dev, "power off error!\n");
 }
 
+static void rk818_device_shutdown(void)
+{
+	int ret;
+	struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
+
+	if (!rk808) {
+		dev_warn(&rk808_i2c_client->dev,
+			 "have no rk818, so do nothing here\n");
+		return;
+	}
+
+	ret = regmap_update_bits(rk808->regmap,
+				 RK818_DEVCTRL_REG,
+				 DEV_OFF, DEV_OFF);
+	if (ret)
+		dev_err(&rk808_i2c_client->dev, "power off error!\n");
+}
+
 static const struct of_device_id rk808_of_match[] = {
 	{ .compatible = "rockchip,rk808" },
 	{ .compatible = "rockchip,rk818" },
@@ -304,6 +322,7 @@ static int rk808_probe(struct i2c_client
 	struct rk808 *rk808;
 	const struct rk808_reg_data *pre_init_reg;
 	const struct mfd_cell *cells;
+	void (*pm_pwroff_fn)(void);
 	int nr_pre_init_regs;
 	int nr_cells;
 	int pm_off = 0;
@@ -331,6 +350,7 @@ static int rk808_probe(struct i2c_client
 		nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
 		cells = rk808s;
 		nr_cells = ARRAY_SIZE(rk808s);
+		pm_pwroff_fn = rk808_device_shutdown;
 		break;
 	case RK818_ID:
 		rk808->regmap_cfg = &rk818_regmap_config;
@@ -339,6 +359,7 @@ static int rk808_probe(struct i2c_client
 		nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
 		cells = rk818s;
 		nr_cells = ARRAY_SIZE(rk818s);
+		pm_pwroff_fn = rk818_device_shutdown;
 		break;
 	default:
 		dev_err(&client->dev, "Unsupported RK8XX ID %lu\n",
@@ -393,7 +414,7 @@ static int rk808_probe(struct i2c_client
 				"rockchip,system-power-controller");
 	if (pm_off && !pm_power_off) {
 		rk808_i2c_client = client;
-		pm_power_off = rk808_device_shutdown;
+		pm_power_off = pm_pwroff_fn;
 	}
 
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/rn5t618.c linux-libre-4.10-rc8-gnu/drivers/mfd/rn5t618.c
--- linux-libre-4.9-gnu/drivers/mfd/rn5t618.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/rn5t618.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,6 +87,7 @@ static int rn5t618_restart(struct notifi
 static const struct of_device_id rn5t618_of_match[] = {
 	{ .compatible = "ricoh,rn5t567", .data = (void *)RN5T567 },
 	{ .compatible = "ricoh,rn5t618", .data = (void *)RN5T618 },
+	{ .compatible = "ricoh,rc5t619", .data = (void *)RC5T619 },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, rn5t618_of_match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/si476x-i2c.c linux-libre-4.10-rc8-gnu/drivers/mfd/si476x-i2c.c
--- linux-libre-4.9-gnu/drivers/mfd/si476x-i2c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/si476x-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -753,7 +753,7 @@ static int si476x_core_probe(struct i2c_
 				       ARRAY_SIZE(core->supplies),
 				       core->supplies);
 	if (rval) {
-		dev_err(&client->dev, "Failet to gett all of the regulators\n");
+		dev_err(&client->dev, "Failed to get all of the regulators\n");
 		goto free_gpio;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/sun4i-gpadc.c linux-libre-4.10-rc8-gnu/drivers/mfd/sun4i-gpadc.c
--- linux-libre-4.9-gnu/drivers/mfd/sun4i-gpadc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/sun4i-gpadc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,181 @@
+/* ADC MFD core driver for sunxi platforms
+ *
+ * Copyright (c) 2016 Quentin Schulz <quentin.schulz@free-electrons.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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/sun4i-gpadc.h>
+
+#define ARCH_SUN4I_A10 0
+#define ARCH_SUN5I_A13 1
+#define ARCH_SUN6I_A31 2
+
+static struct resource adc_resources[] = {
+	DEFINE_RES_IRQ_NAMED(SUN4I_GPADC_IRQ_FIFO_DATA, "FIFO_DATA_PENDING"),
+	DEFINE_RES_IRQ_NAMED(SUN4I_GPADC_IRQ_TEMP_DATA, "TEMP_DATA_PENDING"),
+};
+
+static const struct regmap_irq sun4i_gpadc_regmap_irq[] = {
+	REGMAP_IRQ_REG(SUN4I_GPADC_IRQ_FIFO_DATA, 0,
+		       SUN4I_GPADC_INT_FIFOC_TP_DATA_IRQ_EN),
+	REGMAP_IRQ_REG(SUN4I_GPADC_IRQ_TEMP_DATA, 0,
+		       SUN4I_GPADC_INT_FIFOC_TEMP_IRQ_EN),
+};
+
+static const struct regmap_irq_chip sun4i_gpadc_regmap_irq_chip = {
+	.name = "sun4i_gpadc_irq_chip",
+	.status_base = SUN4I_GPADC_INT_FIFOS,
+	.ack_base = SUN4I_GPADC_INT_FIFOS,
+	.mask_base = SUN4I_GPADC_INT_FIFOC,
+	.init_ack_masked = true,
+	.mask_invert = true,
+	.irqs = sun4i_gpadc_regmap_irq,
+	.num_irqs = ARRAY_SIZE(sun4i_gpadc_regmap_irq),
+	.num_regs = 1,
+};
+
+static struct mfd_cell sun4i_gpadc_cells[] = {
+	{
+		.name	= "sun4i-a10-gpadc-iio",
+		.resources = adc_resources,
+		.num_resources = ARRAY_SIZE(adc_resources),
+	},
+	{ .name = "iio_hwmon" }
+};
+
+static struct mfd_cell sun5i_gpadc_cells[] = {
+	{
+		.name	= "sun5i-a13-gpadc-iio",
+		.resources = adc_resources,
+		.num_resources = ARRAY_SIZE(adc_resources),
+	},
+	{ .name = "iio_hwmon" },
+};
+
+static struct mfd_cell sun6i_gpadc_cells[] = {
+	{
+		.name	= "sun6i-a31-gpadc-iio",
+		.resources = adc_resources,
+		.num_resources = ARRAY_SIZE(adc_resources),
+	},
+	{ .name = "iio_hwmon" },
+};
+
+static const struct regmap_config sun4i_gpadc_regmap_config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.fast_io = true,
+};
+
+static const struct of_device_id sun4i_gpadc_of_match[] = {
+	{
+		.compatible = "allwinner,sun4i-a10-ts",
+		.data = (void *)ARCH_SUN4I_A10,
+	}, {
+		.compatible = "allwinner,sun5i-a13-ts",
+		.data = (void *)ARCH_SUN5I_A13,
+	}, {
+		.compatible = "allwinner,sun6i-a31-ts",
+		.data = (void *)ARCH_SUN6I_A31,
+	}, { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_match);
+
+static int sun4i_gpadc_probe(struct platform_device *pdev)
+{
+	struct sun4i_gpadc_dev *dev;
+	struct resource *mem;
+	const struct of_device_id *of_id;
+	const struct mfd_cell *cells;
+	unsigned int irq, size;
+	int ret;
+
+	of_id = of_match_node(sun4i_gpadc_of_match, pdev->dev.of_node);
+	if (!of_id)
+		return -EINVAL;
+
+	switch ((long)of_id->data) {
+	case ARCH_SUN4I_A10:
+		cells = sun4i_gpadc_cells;
+		size = ARRAY_SIZE(sun4i_gpadc_cells);
+		break;
+	case ARCH_SUN5I_A13:
+		cells = sun5i_gpadc_cells;
+		size = ARRAY_SIZE(sun5i_gpadc_cells);
+		break;
+	case ARCH_SUN6I_A31:
+		cells = sun6i_gpadc_cells;
+		size = ARRAY_SIZE(sun6i_gpadc_cells);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dev->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(dev->base))
+		return PTR_ERR(dev->base);
+
+	dev->dev = &pdev->dev;
+	dev_set_drvdata(dev->dev, dev);
+
+	dev->regmap = devm_regmap_init_mmio(dev->dev, dev->base,
+					    &sun4i_gpadc_regmap_config);
+	if (IS_ERR(dev->regmap)) {
+		ret = PTR_ERR(dev->regmap);
+		dev_err(&pdev->dev, "failed to init regmap: %d\n", ret);
+		return ret;
+	}
+
+	/* Disable all interrupts */
+	regmap_write(dev->regmap, SUN4I_GPADC_INT_FIFOC, 0);
+
+	irq = platform_get_irq(pdev, 0);
+	ret = devm_regmap_add_irq_chip(&pdev->dev, dev->regmap, irq,
+				       IRQF_ONESHOT, 0,
+				       &sun4i_gpadc_regmap_irq_chip,
+				       &dev->regmap_irqc);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add irq chip: %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_mfd_add_devices(dev->dev, 0, cells, size, NULL, 0, NULL);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add MFD devices: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver sun4i_gpadc_driver = {
+	.driver = {
+		.name = "sun4i-gpadc",
+		.of_match_table = of_match_ptr(sun4i_gpadc_of_match),
+	},
+	.probe = sun4i_gpadc_probe,
+};
+
+module_platform_driver(sun4i_gpadc_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi platforms' GPADC MFD core driver");
+MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/tc3589x.c linux-libre-4.10-rc8-gnu/drivers/mfd/tc3589x.c
--- linux-libre-4.9-gnu/drivers/mfd/tc3589x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/tc3589x.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@ int tc3589x_reg_read(struct tc3589x *tc3
 EXPORT_SYMBOL_GPL(tc3589x_reg_read);
 
 /**
- * tc3589x_reg_read() - write a single TC3589x register
+ * tc3589x_reg_write() - write a single TC3589x register
  * @tc3589x:	Device to write to
  * @reg:	Register to read
  * @data:	Value to write
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(tc3589x_block_write);
  * @tc3589x:	Device to write to
  * @reg:	Register to write
  * @mask:	Mask of bits to set
- * @values:	Value to set
+ * @val:	Value to set
  */
 int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/ti_am335x_tscadc.c linux-libre-4.10-rc8-gnu/drivers/mfd/ti_am335x_tscadc.c
--- linux-libre-4.9-gnu/drivers/mfd/ti_am335x_tscadc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/ti_am335x_tscadc.c	2017-02-12 16:03:20.000000000 -0500
@@ -183,6 +183,7 @@ static	int ti_tscadc_probe(struct platfo
 		tscadc->irq = err;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tscadc->tscadc_phys_base = res->start;
 	tscadc->tscadc_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(tscadc->tscadc_base))
 		return PTR_ERR(tscadc->tscadc_base);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/tps65217.c linux-libre-4.10-rc8-gnu/drivers/mfd/tps65217.c
--- linux-libre-4.9-gnu/drivers/mfd/tps65217.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/tps65217.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,26 +42,6 @@ static struct resource pb_resources[] =
 	DEFINE_RES_IRQ_NAMED(TPS65217_IRQ_PB, "PB"),
 };
 
-struct tps65217_irq {
-	int mask;
-	int interrupt;
-};
-
-static const struct tps65217_irq tps65217_irqs[] = {
-	[TPS65217_IRQ_PB] = {
-		.mask = TPS65217_INT_PBM,
-		.interrupt = TPS65217_INT_PBI,
-	},
-	[TPS65217_IRQ_AC] = {
-		.mask = TPS65217_INT_ACM,
-		.interrupt = TPS65217_INT_ACI,
-	},
-	[TPS65217_IRQ_USB] = {
-		.mask = TPS65217_INT_USBM,
-		.interrupt = TPS65217_INT_USBI,
-	},
-};
-
 static void tps65217_irq_lock(struct irq_data *data)
 {
 	struct tps65217 *tps = irq_data_get_irq_chip_data(data);
@@ -74,37 +54,32 @@ static void tps65217_irq_sync_unlock(str
 	struct tps65217 *tps = irq_data_get_irq_chip_data(data);
 	int ret;
 
-	ret = tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask,
-				TPS65217_PROTECT_NONE);
+	ret = tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
+				tps->irq_mask, TPS65217_PROTECT_NONE);
 	if (ret != 0)
 		dev_err(tps->dev, "Failed to sync IRQ masks\n");
 
 	mutex_unlock(&tps->irq_lock);
 }
 
-static inline const struct tps65217_irq *
-irq_to_tps65217_irq(struct tps65217 *tps, struct irq_data *data)
-{
-	return &tps65217_irqs[data->hwirq];
-}
-
 static void tps65217_irq_enable(struct irq_data *data)
 {
 	struct tps65217 *tps = irq_data_get_irq_chip_data(data);
-	const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data);
+	u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT;
 
-	tps->irq_mask &= ~irq_data->mask;
+	tps->irq_mask &= ~mask;
 }
 
 static void tps65217_irq_disable(struct irq_data *data)
 {
 	struct tps65217 *tps = irq_data_get_irq_chip_data(data);
-	const struct tps65217_irq *irq_data = irq_to_tps65217_irq(tps, data);
+	u8 mask = BIT(data->hwirq) << TPS65217_INT_SHIFT;
 
-	tps->irq_mask |= irq_data->mask;
+	tps->irq_mask |= mask;
 }
 
 static struct irq_chip tps65217_irq_chip = {
+	.name			= "tps65217",
 	.irq_bus_lock		= tps65217_irq_lock,
 	.irq_bus_sync_unlock	= tps65217_irq_sync_unlock,
 	.irq_enable		= tps65217_irq_enable,
@@ -149,8 +124,8 @@ static irqreturn_t tps65217_irq_thread(i
 		return IRQ_NONE;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(tps65217_irqs); i++) {
-		if (status & tps65217_irqs[i].interrupt) {
+	for (i = 0; i < TPS65217_NUM_IRQ; i++) {
+		if (status & BIT(i)) {
 			handle_nested_irq(irq_find_mapping(tps->irq_domain, i));
 			handled = true;
 		}
@@ -188,10 +163,9 @@ static int tps65217_irq_init(struct tps6
 	tps->irq = irq;
 
 	/* Mask all interrupt sources */
-	tps->irq_mask = (TPS65217_INT_RESERVEDM | TPS65217_INT_PBM
-			| TPS65217_INT_ACM | TPS65217_INT_USBM);
-	tps65217_reg_write(tps, TPS65217_REG_INT, tps->irq_mask,
-			TPS65217_PROTECT_NONE);
+	tps->irq_mask = TPS65217_INT_MASK;
+	tps65217_set_bits(tps, TPS65217_REG_INT, TPS65217_INT_MASK,
+			  TPS65217_INT_MASK, TPS65217_PROTECT_NONE);
 
 	tps->irq_domain = irq_domain_add_linear(tps->dev->of_node,
 		TPS65217_NUM_IRQ, &tps65217_irq_domain_ops, tps);
@@ -209,6 +183,8 @@ static int tps65217_irq_init(struct tps6
 		return ret;
 	}
 
+	enable_irq_wake(irq);
+
 	return 0;
 }
 
@@ -424,6 +400,24 @@ static int tps65217_probe(struct i2c_cli
 	return 0;
 }
 
+static int tps65217_remove(struct i2c_client *client)
+{
+	struct tps65217 *tps = i2c_get_clientdata(client);
+	unsigned int virq;
+	int i;
+
+	for (i = 0; i < TPS65217_NUM_IRQ; i++) {
+		virq = irq_find_mapping(tps->irq_domain, i);
+		if (virq)
+			irq_dispose_mapping(virq);
+	}
+
+	irq_domain_remove(tps->irq_domain);
+	tps->irq_domain = NULL;
+
+	return 0;
+}
+
 static const struct i2c_device_id tps65217_id_table[] = {
 	{"tps65217", TPS65217},
 	{ /* sentinel */ }
@@ -437,6 +431,7 @@ static struct i2c_driver tps65217_driver
 	},
 	.id_table	= tps65217_id_table,
 	.probe		= tps65217_probe,
+	.remove		= tps65217_remove,
 };
 
 static int __init tps65217_init(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/tps65218.c linux-libre-4.10-rc8-gnu/drivers/mfd/tps65218.c
--- linux-libre-4.9-gnu/drivers/mfd/tps65218.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/tps65218.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,19 +33,17 @@
 
 #define TPS65218_PASSWORD_REGS_UNLOCK   0x7D
 
-/**
- * tps65218_reg_read: Read a single tps65218 register.
- *
- * @tps: Device to read from.
- * @reg: Register to read.
- * @val: Contians the value
- */
-int tps65218_reg_read(struct tps65218 *tps, unsigned int reg,
-			unsigned int *val)
-{
-	return regmap_read(tps->regmap, reg, val);
-}
-EXPORT_SYMBOL_GPL(tps65218_reg_read);
+static const struct mfd_cell tps65218_cells[] = {
+	{
+		.name = "tps65218-pwrbutton",
+		.of_compatible = "ti,tps65218-pwrbutton",
+	},
+	{
+		.name = "tps65218-gpio",
+		.of_compatible = "ti,tps65218-gpio",
+	},
+	{ .name = "tps65218-regulator", },
+};
 
 /**
  * tps65218_reg_write: Write a single tps65218 register.
@@ -93,7 +91,7 @@ static int tps65218_update_bits(struct t
 	int ret;
 	unsigned int data;
 
-	ret = tps65218_reg_read(tps, reg, &data);
+	ret = regmap_read(tps->regmap, reg, &data);
 	if (ret) {
 		dev_err(tps->dev, "Read from reg 0x%x failed\n", reg);
 		return ret;
@@ -251,7 +249,7 @@ static int tps65218_probe(struct i2c_cli
 	if (ret < 0)
 		return ret;
 
-	ret = tps65218_reg_read(tps, TPS65218_REG_CHIPID, &chipid);
+	ret = regmap_read(tps->regmap, TPS65218_REG_CHIPID, &chipid);
 	if (ret) {
 		dev_err(tps->dev, "Failed to read chipid: %d\n", ret);
 		return ret;
@@ -259,8 +257,10 @@ static int tps65218_probe(struct i2c_cli
 
 	tps->rev = chipid & TPS65218_CHIPID_REV_MASK;
 
-	ret = of_platform_populate(client->dev.of_node, NULL, NULL,
-				   &client->dev);
+	ret = mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO, tps65218_cells,
+			      ARRAY_SIZE(tps65218_cells), NULL, 0,
+			      regmap_irq_get_domain(tps->irq_data));
+
 	if (ret < 0)
 		goto err_irq;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/tps65912-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/tps65912-core.c
--- linux-libre-4.9-gnu/drivers/mfd/tps65912-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/tps65912-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,6 +77,23 @@ static struct regmap_irq_chip tps65912_i
 	.init_ack_masked = true,
 };
 
+static const struct regmap_range tps65912_yes_ranges[] = {
+	regmap_reg_range(TPS65912_INT_STS, TPS65912_GPIO5),
+};
+
+static const struct regmap_access_table tps65912_volatile_table = {
+	.yes_ranges = tps65912_yes_ranges,
+	.n_yes_ranges = ARRAY_SIZE(tps65912_yes_ranges),
+};
+
+const struct regmap_config tps65912_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.volatile_table = &tps65912_volatile_table,
+};
+EXPORT_SYMBOL_GPL(tps65912_regmap_config);
+
 int tps65912_device_init(struct tps65912 *tps)
 {
 	int ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/wm5102-tables.c linux-libre-4.10-rc8-gnu/drivers/mfd/wm5102-tables.c
--- linux-libre-4.9-gnu/drivers/mfd/wm5102-tables.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/wm5102-tables.c	2017-02-12 16:03:20.000000000 -0500
@@ -244,752 +244,752 @@ const struct regmap_irq_chip wm5102_irq
 };
 
 static const struct reg_default wm5102_reg_default[] = {
-	{ 0x00000008, 0x0019 },   /* R8     - Ctrl IF SPI CFG 1 */ 
-	{ 0x00000009, 0x0001 },   /* R9     - Ctrl IF I2C1 CFG 1 */ 
-	{ 0x00000020, 0x0000 },   /* R32    - Tone Generator 1 */ 
-	{ 0x00000021, 0x1000 },   /* R33    - Tone Generator 2 */ 
-	{ 0x00000022, 0x0000 },   /* R34    - Tone Generator 3 */ 
-	{ 0x00000023, 0x1000 },   /* R35    - Tone Generator 4 */ 
-	{ 0x00000024, 0x0000 },   /* R36    - Tone Generator 5 */ 
-	{ 0x00000030, 0x0000 },   /* R48    - PWM Drive 1 */ 
-	{ 0x00000031, 0x0100 },   /* R49    - PWM Drive 2 */ 
-	{ 0x00000032, 0x0100 },   /* R50    - PWM Drive 3 */ 
-	{ 0x00000040, 0x0000 },   /* R64    - Wake control */ 
-	{ 0x00000041, 0x0000 },   /* R65    - Sequence control */ 
-	{ 0x00000061, 0x01FF },   /* R97    - Sample Rate Sequence Select 1 */ 
-	{ 0x00000062, 0x01FF },   /* R98    - Sample Rate Sequence Select 2 */ 
-	{ 0x00000063, 0x01FF },   /* R99    - Sample Rate Sequence Select 3 */ 
-	{ 0x00000064, 0x01FF },   /* R100   - Sample Rate Sequence Select 4 */ 
+	{ 0x00000008, 0x0019 },   /* R8     - Ctrl IF SPI CFG 1 */
+	{ 0x00000009, 0x0001 },   /* R9     - Ctrl IF I2C1 CFG 1 */
+	{ 0x00000020, 0x0000 },   /* R32    - Tone Generator 1 */
+	{ 0x00000021, 0x1000 },   /* R33    - Tone Generator 2 */
+	{ 0x00000022, 0x0000 },   /* R34    - Tone Generator 3 */
+	{ 0x00000023, 0x1000 },   /* R35    - Tone Generator 4 */
+	{ 0x00000024, 0x0000 },   /* R36    - Tone Generator 5 */
+	{ 0x00000030, 0x0000 },   /* R48    - PWM Drive 1 */
+	{ 0x00000031, 0x0100 },   /* R49    - PWM Drive 2 */
+	{ 0x00000032, 0x0100 },   /* R50    - PWM Drive 3 */
+	{ 0x00000040, 0x0000 },   /* R64    - Wake control */
+	{ 0x00000041, 0x0000 },   /* R65    - Sequence control */
+	{ 0x00000061, 0x01FF },   /* R97    - Sample Rate Sequence Select 1 */
+	{ 0x00000062, 0x01FF },   /* R98    - Sample Rate Sequence Select 2 */
+	{ 0x00000063, 0x01FF },   /* R99    - Sample Rate Sequence Select 3 */
+	{ 0x00000064, 0x01FF },   /* R100   - Sample Rate Sequence Select 4 */
 	{ 0x00000066, 0x01FF },   /* R102   - Always On Triggers Sequence Select 1 */
 	{ 0x00000067, 0x01FF },   /* R103   - Always On Triggers Sequence Select 2 */
 	{ 0x00000068, 0x01FF },   /* R104   - Always On Triggers Sequence Select 3 */
 	{ 0x00000069, 0x01FF },   /* R105   - Always On Triggers Sequence Select 4 */
 	{ 0x0000006A, 0x01FF },   /* R106   - Always On Triggers Sequence Select 5 */
 	{ 0x0000006B, 0x01FF },   /* R107   - Always On Triggers Sequence Select 6 */
-	{ 0x00000070, 0x0000 },   /* R112   - Comfort Noise Generator */ 
-	{ 0x00000090, 0x0000 },   /* R144   - Haptics Control 1 */ 
-	{ 0x00000091, 0x7FFF },   /* R145   - Haptics Control 2 */ 
-	{ 0x00000092, 0x0000 },   /* R146   - Haptics phase 1 intensity */ 
-	{ 0x00000093, 0x0000 },   /* R147   - Haptics phase 1 duration */ 
-	{ 0x00000094, 0x0000 },   /* R148   - Haptics phase 2 intensity */ 
-	{ 0x00000095, 0x0000 },   /* R149   - Haptics phase 2 duration */ 
-	{ 0x00000096, 0x0000 },   /* R150   - Haptics phase 3 intensity */ 
-	{ 0x00000097, 0x0000 },   /* R151   - Haptics phase 3 duration */ 
+	{ 0x00000070, 0x0000 },   /* R112   - Comfort Noise Generator */
+	{ 0x00000090, 0x0000 },   /* R144   - Haptics Control 1 */
+	{ 0x00000091, 0x7FFF },   /* R145   - Haptics Control 2 */
+	{ 0x00000092, 0x0000 },   /* R146   - Haptics phase 1 intensity */
+	{ 0x00000093, 0x0000 },   /* R147   - Haptics phase 1 duration */
+	{ 0x00000094, 0x0000 },   /* R148   - Haptics phase 2 intensity */
+	{ 0x00000095, 0x0000 },   /* R149   - Haptics phase 2 duration */
+	{ 0x00000096, 0x0000 },   /* R150   - Haptics phase 3 intensity */
+	{ 0x00000097, 0x0000 },   /* R151   - Haptics phase 3 duration */
 	{ 0x00000100, 0x0002 },   /* R256   - Clock 32k 1 */
-	{ 0x00000101, 0x0304 },   /* R257   - System Clock 1 */ 
-	{ 0x00000102, 0x0011 },   /* R258   - Sample rate 1 */ 
-	{ 0x00000103, 0x0011 },   /* R259   - Sample rate 2 */ 
-	{ 0x00000104, 0x0011 },   /* R260   - Sample rate 3 */ 
-	{ 0x00000112, 0x0305 },   /* R274   - Async clock 1 */ 
-	{ 0x00000113, 0x0011 },   /* R275   - Async sample rate 1 */ 
+	{ 0x00000101, 0x0304 },   /* R257   - System Clock 1 */
+	{ 0x00000102, 0x0011 },   /* R258   - Sample rate 1 */
+	{ 0x00000103, 0x0011 },   /* R259   - Sample rate 2 */
+	{ 0x00000104, 0x0011 },   /* R260   - Sample rate 3 */
+	{ 0x00000112, 0x0305 },   /* R274   - Async clock 1 */
+	{ 0x00000113, 0x0011 },   /* R275   - Async sample rate 1 */
 	{ 0x00000114, 0x0011 },   /* R276   - Async sample rate 2 */
-	{ 0x00000149, 0x0000 },   /* R329   - Output system clock */ 
-	{ 0x0000014A, 0x0000 },   /* R330   - Output async clock */ 
-	{ 0x00000152, 0x0000 },   /* R338   - Rate Estimator 1 */ 
-	{ 0x00000153, 0x0000 },   /* R339   - Rate Estimator 2 */ 
-	{ 0x00000154, 0x0000 },   /* R340   - Rate Estimator 3 */ 
-	{ 0x00000155, 0x0000 },   /* R341   - Rate Estimator 4 */ 
-	{ 0x00000156, 0x0000 },   /* R342   - Rate Estimator 5 */ 
-	{ 0x00000161, 0x0000 },   /* R353   - Dynamic Frequency Scaling 1 */ 
+	{ 0x00000149, 0x0000 },   /* R329   - Output system clock */
+	{ 0x0000014A, 0x0000 },   /* R330   - Output async clock */
+	{ 0x00000152, 0x0000 },   /* R338   - Rate Estimator 1 */
+	{ 0x00000153, 0x0000 },   /* R339   - Rate Estimator 2 */
+	{ 0x00000154, 0x0000 },   /* R340   - Rate Estimator 3 */
+	{ 0x00000155, 0x0000 },   /* R341   - Rate Estimator 4 */
+	{ 0x00000156, 0x0000 },   /* R342   - Rate Estimator 5 */
+	{ 0x00000161, 0x0000 },   /* R353   - Dynamic Frequency Scaling 1 */
 	{ 0x00000171, 0x0000 },   /* R369   - FLL1 Control 1 */
-	{ 0x00000172, 0x0008 },   /* R370   - FLL1 Control 2 */ 
-	{ 0x00000173, 0x0018 },   /* R371   - FLL1 Control 3 */ 
-	{ 0x00000174, 0x007D },   /* R372   - FLL1 Control 4 */ 
-	{ 0x00000175, 0x0004 },   /* R373   - FLL1 Control 5 */ 
-	{ 0x00000176, 0x0000 },   /* R374   - FLL1 Control 6 */ 
+	{ 0x00000172, 0x0008 },   /* R370   - FLL1 Control 2 */
+	{ 0x00000173, 0x0018 },   /* R371   - FLL1 Control 3 */
+	{ 0x00000174, 0x007D },   /* R372   - FLL1 Control 4 */
+	{ 0x00000175, 0x0004 },   /* R373   - FLL1 Control 5 */
+	{ 0x00000176, 0x0000 },   /* R374   - FLL1 Control 6 */
 	{ 0x00000179, 0x0000 },   /* R377   - FLL1 Control 7 */
-	{ 0x00000181, 0x0000 },   /* R385   - FLL1 Synchroniser 1 */ 
-	{ 0x00000182, 0x0000 },   /* R386   - FLL1 Synchroniser 2 */ 
-	{ 0x00000183, 0x0000 },   /* R387   - FLL1 Synchroniser 3 */ 
-	{ 0x00000184, 0x0000 },   /* R388   - FLL1 Synchroniser 4 */ 
-	{ 0x00000185, 0x0000 },   /* R389   - FLL1 Synchroniser 5 */ 
-	{ 0x00000186, 0x0000 },   /* R390   - FLL1 Synchroniser 6 */ 
+	{ 0x00000181, 0x0000 },   /* R385   - FLL1 Synchroniser 1 */
+	{ 0x00000182, 0x0000 },   /* R386   - FLL1 Synchroniser 2 */
+	{ 0x00000183, 0x0000 },   /* R387   - FLL1 Synchroniser 3 */
+	{ 0x00000184, 0x0000 },   /* R388   - FLL1 Synchroniser 4 */
+	{ 0x00000185, 0x0000 },   /* R389   - FLL1 Synchroniser 5 */
+	{ 0x00000186, 0x0000 },   /* R390   - FLL1 Synchroniser 6 */
 	{ 0x00000187, 0x0001 },   /* R391   - FLL1 Synchroniser 7 */
-	{ 0x00000189, 0x0000 },   /* R393   - FLL1 Spread Spectrum */ 
-	{ 0x0000018A, 0x0004 },   /* R394   - FLL1 GPIO Clock */ 
-	{ 0x00000191, 0x0000 },   /* R401   - FLL2 Control 1 */ 
-	{ 0x00000192, 0x0008 },   /* R402   - FLL2 Control 2 */ 
-	{ 0x00000193, 0x0018 },   /* R403   - FLL2 Control 3 */ 
-	{ 0x00000194, 0x007D },   /* R404   - FLL2 Control 4 */ 
-	{ 0x00000195, 0x0004 },   /* R405   - FLL2 Control 5 */ 
-	{ 0x00000196, 0x0000 },   /* R406   - FLL2 Control 6 */ 
+	{ 0x00000189, 0x0000 },   /* R393   - FLL1 Spread Spectrum */
+	{ 0x0000018A, 0x0004 },   /* R394   - FLL1 GPIO Clock */
+	{ 0x00000191, 0x0000 },   /* R401   - FLL2 Control 1 */
+	{ 0x00000192, 0x0008 },   /* R402   - FLL2 Control 2 */
+	{ 0x00000193, 0x0018 },   /* R403   - FLL2 Control 3 */
+	{ 0x00000194, 0x007D },   /* R404   - FLL2 Control 4 */
+	{ 0x00000195, 0x0004 },   /* R405   - FLL2 Control 5 */
+	{ 0x00000196, 0x0000 },   /* R406   - FLL2 Control 6 */
 	{ 0x00000199, 0x0000 },   /* R409   - FLL2 Control 7 */
-	{ 0x000001A1, 0x0000 },   /* R417   - FLL2 Synchroniser 1 */ 
-	{ 0x000001A2, 0x0000 },   /* R418   - FLL2 Synchroniser 2 */ 
-	{ 0x000001A3, 0x0000 },   /* R419   - FLL2 Synchroniser 3 */ 
-	{ 0x000001A4, 0x0000 },   /* R420   - FLL2 Synchroniser 4 */ 
-	{ 0x000001A5, 0x0000 },   /* R421   - FLL2 Synchroniser 5 */ 
-	{ 0x000001A6, 0x0000 },   /* R422   - FLL2 Synchroniser 6 */ 
+	{ 0x000001A1, 0x0000 },   /* R417   - FLL2 Synchroniser 1 */
+	{ 0x000001A2, 0x0000 },   /* R418   - FLL2 Synchroniser 2 */
+	{ 0x000001A3, 0x0000 },   /* R419   - FLL2 Synchroniser 3 */
+	{ 0x000001A4, 0x0000 },   /* R420   - FLL2 Synchroniser 4 */
+	{ 0x000001A5, 0x0000 },   /* R421   - FLL2 Synchroniser 5 */
+	{ 0x000001A6, 0x0000 },   /* R422   - FLL2 Synchroniser 6 */
 	{ 0x000001A7, 0x0001 },   /* R423   - FLL2 Synchroniser 7 */
-	{ 0x000001A9, 0x0000 },   /* R425   - FLL2 Spread Spectrum */ 
-	{ 0x000001AA, 0x0004 },   /* R426   - FLL2 GPIO Clock */ 
-	{ 0x00000200, 0x0006 },   /* R512   - Mic Charge Pump 1 */ 
-	{ 0x00000210, 0x00D4 },   /* R528   - LDO1 Control 1 */ 
+	{ 0x000001A9, 0x0000 },   /* R425   - FLL2 Spread Spectrum */
+	{ 0x000001AA, 0x0004 },   /* R426   - FLL2 GPIO Clock */
+	{ 0x00000200, 0x0006 },   /* R512   - Mic Charge Pump 1 */
+	{ 0x00000210, 0x00D4 },   /* R528   - LDO1 Control 1 */
 	{ 0x00000212, 0x0000 },   /* R530   - LDO1 Control 2 */
-	{ 0x00000213, 0x0344 },   /* R531   - LDO2 Control 1 */ 
-	{ 0x00000218, 0x01A6 },   /* R536   - Mic Bias Ctrl 1 */ 
-	{ 0x00000219, 0x01A6 },   /* R537   - Mic Bias Ctrl 2 */ 
-	{ 0x0000021A, 0x01A6 },   /* R538   - Mic Bias Ctrl 3 */ 
-	{ 0x00000293, 0x0000 },   /* R659   - Accessory Detect Mode 1 */ 
-	{ 0x0000029B, 0x0020 },   /* R667   - Headphone Detect 1 */ 
+	{ 0x00000213, 0x0344 },   /* R531   - LDO2 Control 1 */
+	{ 0x00000218, 0x01A6 },   /* R536   - Mic Bias Ctrl 1 */
+	{ 0x00000219, 0x01A6 },   /* R537   - Mic Bias Ctrl 2 */
+	{ 0x0000021A, 0x01A6 },   /* R538   - Mic Bias Ctrl 3 */
+	{ 0x00000293, 0x0000 },   /* R659   - Accessory Detect Mode 1 */
+	{ 0x0000029B, 0x0020 },   /* R667   - Headphone Detect 1 */
 	{ 0x000002A2, 0x0000 },   /* R674   - Micd clamp control */
-	{ 0x000002A3, 0x1102 },   /* R675   - Mic Detect 1 */ 
-	{ 0x000002A4, 0x009F },   /* R676   - Mic Detect 2 */ 
+	{ 0x000002A3, 0x1102 },   /* R675   - Mic Detect 1 */
+	{ 0x000002A4, 0x009F },   /* R676   - Mic Detect 2 */
 	{ 0x000002A6, 0x3737 },   /* R678   - Mic Detect Level 1 */
 	{ 0x000002A7, 0x2C37 },   /* R679   - Mic Detect Level 2 */
 	{ 0x000002A8, 0x1422 },   /* R680   - Mic Detect Level 3 */
 	{ 0x000002A9, 0x030A },   /* R681   - Mic Detect Level 4 */
-	{ 0x000002C3, 0x0000 },   /* R707   - Mic noise mix control 1 */ 
-	{ 0x000002CB, 0x0000 },   /* R715   - Isolation control */ 
-	{ 0x000002D3, 0x0000 },   /* R723   - Jack detect analogue */ 
-	{ 0x00000300, 0x0000 },   /* R768   - Input Enables */ 
-	{ 0x00000308, 0x0000 },   /* R776   - Input Rate */ 
-	{ 0x00000309, 0x0022 },   /* R777   - Input Volume Ramp */ 
-	{ 0x00000310, 0x2080 },   /* R784   - IN1L Control */ 
-	{ 0x00000311, 0x0180 },   /* R785   - ADC Digital Volume 1L */ 
-	{ 0x00000312, 0x0000 },   /* R786   - DMIC1L Control */ 
-	{ 0x00000314, 0x0080 },   /* R788   - IN1R Control */ 
-	{ 0x00000315, 0x0180 },   /* R789   - ADC Digital Volume 1R */ 
-	{ 0x00000316, 0x0000 },   /* R790   - DMIC1R Control */ 
-	{ 0x00000318, 0x2080 },   /* R792   - IN2L Control */ 
-	{ 0x00000319, 0x0180 },   /* R793   - ADC Digital Volume 2L */ 
-	{ 0x0000031A, 0x0000 },   /* R794   - DMIC2L Control */ 
-	{ 0x0000031C, 0x0080 },   /* R796   - IN2R Control */ 
-	{ 0x0000031D, 0x0180 },   /* R797   - ADC Digital Volume 2R */ 
-	{ 0x0000031E, 0x0000 },   /* R798   - DMIC2R Control */ 
-	{ 0x00000320, 0x2080 },   /* R800   - IN3L Control */ 
-	{ 0x00000321, 0x0180 },   /* R801   - ADC Digital Volume 3L */ 
-	{ 0x00000322, 0x0000 },   /* R802   - DMIC3L Control */ 
-	{ 0x00000324, 0x0080 },   /* R804   - IN3R Control */ 
-	{ 0x00000325, 0x0180 },   /* R805   - ADC Digital Volume 3R */ 
-	{ 0x00000326, 0x0000 },   /* R806   - DMIC3R Control */ 
-	{ 0x00000400, 0x0000 },   /* R1024  - Output Enables 1 */ 
-	{ 0x00000408, 0x0000 },   /* R1032  - Output Rate 1 */ 
-	{ 0x00000409, 0x0022 },   /* R1033  - Output Volume Ramp */ 
+	{ 0x000002C3, 0x0000 },   /* R707   - Mic noise mix control 1 */
+	{ 0x000002CB, 0x0000 },   /* R715   - Isolation control */
+	{ 0x000002D3, 0x0000 },   /* R723   - Jack detect analogue */
+	{ 0x00000300, 0x0000 },   /* R768   - Input Enables */
+	{ 0x00000308, 0x0000 },   /* R776   - Input Rate */
+	{ 0x00000309, 0x0022 },   /* R777   - Input Volume Ramp */
+	{ 0x00000310, 0x2080 },   /* R784   - IN1L Control */
+	{ 0x00000311, 0x0180 },   /* R785   - ADC Digital Volume 1L */
+	{ 0x00000312, 0x0000 },   /* R786   - DMIC1L Control */
+	{ 0x00000314, 0x0080 },   /* R788   - IN1R Control */
+	{ 0x00000315, 0x0180 },   /* R789   - ADC Digital Volume 1R */
+	{ 0x00000316, 0x0000 },   /* R790   - DMIC1R Control */
+	{ 0x00000318, 0x2080 },   /* R792   - IN2L Control */
+	{ 0x00000319, 0x0180 },   /* R793   - ADC Digital Volume 2L */
+	{ 0x0000031A, 0x0000 },   /* R794   - DMIC2L Control */
+	{ 0x0000031C, 0x0080 },   /* R796   - IN2R Control */
+	{ 0x0000031D, 0x0180 },   /* R797   - ADC Digital Volume 2R */
+	{ 0x0000031E, 0x0000 },   /* R798   - DMIC2R Control */
+	{ 0x00000320, 0x2080 },   /* R800   - IN3L Control */
+	{ 0x00000321, 0x0180 },   /* R801   - ADC Digital Volume 3L */
+	{ 0x00000322, 0x0000 },   /* R802   - DMIC3L Control */
+	{ 0x00000324, 0x0080 },   /* R804   - IN3R Control */
+	{ 0x00000325, 0x0180 },   /* R805   - ADC Digital Volume 3R */
+	{ 0x00000326, 0x0000 },   /* R806   - DMIC3R Control */
+	{ 0x00000400, 0x0000 },   /* R1024  - Output Enables 1 */
+	{ 0x00000408, 0x0000 },   /* R1032  - Output Rate 1 */
+	{ 0x00000409, 0x0022 },   /* R1033  - Output Volume Ramp */
 	{ 0x00000410, 0x6080 },   /* R1040  - Output Path Config 1L */
-	{ 0x00000411, 0x0180 },   /* R1041  - DAC Digital Volume 1L */ 
+	{ 0x00000411, 0x0180 },   /* R1041  - DAC Digital Volume 1L */
 	{ 0x00000412, 0x0081 },   /* R1042  - DAC Volume Limit 1L */
-	{ 0x00000413, 0x0001 },   /* R1043  - Noise Gate Select 1L */ 
-	{ 0x00000414, 0x0080 },   /* R1044  - Output Path Config 1R */ 
-	{ 0x00000415, 0x0180 },   /* R1045  - DAC Digital Volume 1R */ 
+	{ 0x00000413, 0x0001 },   /* R1043  - Noise Gate Select 1L */
+	{ 0x00000414, 0x0080 },   /* R1044  - Output Path Config 1R */
+	{ 0x00000415, 0x0180 },   /* R1045  - DAC Digital Volume 1R */
 	{ 0x00000416, 0x0081 },   /* R1046  - DAC Volume Limit 1R */
-	{ 0x00000417, 0x0002 },   /* R1047  - Noise Gate Select 1R */ 
+	{ 0x00000417, 0x0002 },   /* R1047  - Noise Gate Select 1R */
 	{ 0x00000418, 0xA080 },   /* R1048  - Output Path Config 2L */
-	{ 0x00000419, 0x0180 },   /* R1049  - DAC Digital Volume 2L */ 
+	{ 0x00000419, 0x0180 },   /* R1049  - DAC Digital Volume 2L */
 	{ 0x0000041A, 0x0081 },   /* R1050  - DAC Volume Limit 2L */
-	{ 0x0000041B, 0x0004 },   /* R1051  - Noise Gate Select 2L */ 
-	{ 0x0000041C, 0x0080 },   /* R1052  - Output Path Config 2R */ 
-	{ 0x0000041D, 0x0180 },   /* R1053  - DAC Digital Volume 2R */ 
+	{ 0x0000041B, 0x0004 },   /* R1051  - Noise Gate Select 2L */
+	{ 0x0000041C, 0x0080 },   /* R1052  - Output Path Config 2R */
+	{ 0x0000041D, 0x0180 },   /* R1053  - DAC Digital Volume 2R */
 	{ 0x0000041E, 0x0081 },   /* R1054  - DAC Volume Limit 2R */
-	{ 0x0000041F, 0x0008 },   /* R1055  - Noise Gate Select 2R */ 
+	{ 0x0000041F, 0x0008 },   /* R1055  - Noise Gate Select 2R */
 	{ 0x00000420, 0xA080 },   /* R1056  - Output Path Config 3L */
-	{ 0x00000421, 0x0180 },   /* R1057  - DAC Digital Volume 3L */ 
+	{ 0x00000421, 0x0180 },   /* R1057  - DAC Digital Volume 3L */
 	{ 0x00000422, 0x0081 },   /* R1058  - DAC Volume Limit 3L */
-	{ 0x00000423, 0x0010 },   /* R1059  - Noise Gate Select 3L */ 
+	{ 0x00000423, 0x0010 },   /* R1059  - Noise Gate Select 3L */
 	{ 0x00000428, 0xE000 },   /* R1064  - Output Path Config 4L */
-	{ 0x00000429, 0x0180 },   /* R1065  - DAC Digital Volume 4L */ 
+	{ 0x00000429, 0x0180 },   /* R1065  - DAC Digital Volume 4L */
 	{ 0x0000042A, 0x0081 },   /* R1066  - Out Volume 4L */
-	{ 0x0000042B, 0x0040 },   /* R1067  - Noise Gate Select 4L */ 
-	{ 0x0000042D, 0x0180 },   /* R1069  - DAC Digital Volume 4R */ 
+	{ 0x0000042B, 0x0040 },   /* R1067  - Noise Gate Select 4L */
+	{ 0x0000042D, 0x0180 },   /* R1069  - DAC Digital Volume 4R */
 	{ 0x0000042E, 0x0081 },   /* R1070  - Out Volume 4R */
-	{ 0x0000042F, 0x0080 },   /* R1071  - Noise Gate Select 4R */ 
-	{ 0x00000430, 0x0000 },   /* R1072  - Output Path Config 5L */ 
-	{ 0x00000431, 0x0180 },   /* R1073  - DAC Digital Volume 5L */ 
+	{ 0x0000042F, 0x0080 },   /* R1071  - Noise Gate Select 4R */
+	{ 0x00000430, 0x0000 },   /* R1072  - Output Path Config 5L */
+	{ 0x00000431, 0x0180 },   /* R1073  - DAC Digital Volume 5L */
 	{ 0x00000432, 0x0081 },   /* R1074  - DAC Volume Limit 5L */
-	{ 0x00000433, 0x0100 },   /* R1075  - Noise Gate Select 5L */ 
-	{ 0x00000435, 0x0180 },   /* R1077  - DAC Digital Volume 5R */ 
+	{ 0x00000433, 0x0100 },   /* R1075  - Noise Gate Select 5L */
+	{ 0x00000435, 0x0180 },   /* R1077  - DAC Digital Volume 5R */
 	{ 0x00000436, 0x0081 },   /* R1078  - DAC Volume Limit 5R */
 	{ 0x00000437, 0x0200 },   /* R1079  - Noise Gate Select 5R */
 	{ 0x00000440, 0x0FFF },   /* R1088  - DRE Enable */
 	{ 0x00000442, 0x3F0A },   /* R1090  - DRE Control 2 */
 	{ 0x00000443, 0xDC1F },   /* R1090  - DRE Control 3 */
-	{ 0x00000450, 0x0000 },   /* R1104  - DAC AEC Control 1 */ 
+	{ 0x00000450, 0x0000 },   /* R1104  - DAC AEC Control 1 */
 	{ 0x00000458, 0x000B },   /* R1112  - Noise Gate Control */
-	{ 0x00000490, 0x0069 },   /* R1168  - PDM SPK1 CTRL 1 */ 
-	{ 0x00000491, 0x0000 },   /* R1169  - PDM SPK1 CTRL 2 */ 
-	{ 0x00000500, 0x000C },   /* R1280  - AIF1 BCLK Ctrl */ 
-	{ 0x00000501, 0x0008 },   /* R1281  - AIF1 Tx Pin Ctrl */ 
-	{ 0x00000502, 0x0000 },   /* R1282  - AIF1 Rx Pin Ctrl */ 
-	{ 0x00000503, 0x0000 },   /* R1283  - AIF1 Rate Ctrl */ 
-	{ 0x00000504, 0x0000 },   /* R1284  - AIF1 Format */ 
-	{ 0x00000505, 0x0040 },   /* R1285  - AIF1 Tx BCLK Rate */ 
-	{ 0x00000506, 0x0040 },   /* R1286  - AIF1 Rx BCLK Rate */ 
-	{ 0x00000507, 0x1818 },   /* R1287  - AIF1 Frame Ctrl 1 */ 
-	{ 0x00000508, 0x1818 },   /* R1288  - AIF1 Frame Ctrl 2 */ 
-	{ 0x00000509, 0x0000 },   /* R1289  - AIF1 Frame Ctrl 3 */ 
-	{ 0x0000050A, 0x0001 },   /* R1290  - AIF1 Frame Ctrl 4 */ 
-	{ 0x0000050B, 0x0002 },   /* R1291  - AIF1 Frame Ctrl 5 */ 
-	{ 0x0000050C, 0x0003 },   /* R1292  - AIF1 Frame Ctrl 6 */ 
-	{ 0x0000050D, 0x0004 },   /* R1293  - AIF1 Frame Ctrl 7 */ 
-	{ 0x0000050E, 0x0005 },   /* R1294  - AIF1 Frame Ctrl 8 */ 
-	{ 0x0000050F, 0x0006 },   /* R1295  - AIF1 Frame Ctrl 9 */ 
-	{ 0x00000510, 0x0007 },   /* R1296  - AIF1 Frame Ctrl 10 */ 
-	{ 0x00000511, 0x0000 },   /* R1297  - AIF1 Frame Ctrl 11 */ 
-	{ 0x00000512, 0x0001 },   /* R1298  - AIF1 Frame Ctrl 12 */ 
-	{ 0x00000513, 0x0002 },   /* R1299  - AIF1 Frame Ctrl 13 */ 
-	{ 0x00000514, 0x0003 },   /* R1300  - AIF1 Frame Ctrl 14 */ 
-	{ 0x00000515, 0x0004 },   /* R1301  - AIF1 Frame Ctrl 15 */ 
-	{ 0x00000516, 0x0005 },   /* R1302  - AIF1 Frame Ctrl 16 */ 
-	{ 0x00000517, 0x0006 },   /* R1303  - AIF1 Frame Ctrl 17 */ 
-	{ 0x00000518, 0x0007 },   /* R1304  - AIF1 Frame Ctrl 18 */ 
-	{ 0x00000519, 0x0000 },   /* R1305  - AIF1 Tx Enables */ 
-	{ 0x0000051A, 0x0000 },   /* R1306  - AIF1 Rx Enables */ 
-	{ 0x00000540, 0x000C },   /* R1344  - AIF2 BCLK Ctrl */ 
-	{ 0x00000541, 0x0008 },   /* R1345  - AIF2 Tx Pin Ctrl */ 
-	{ 0x00000542, 0x0000 },   /* R1346  - AIF2 Rx Pin Ctrl */ 
-	{ 0x00000543, 0x0000 },   /* R1347  - AIF2 Rate Ctrl */ 
-	{ 0x00000544, 0x0000 },   /* R1348  - AIF2 Format */ 
-	{ 0x00000545, 0x0040 },   /* R1349  - AIF2 Tx BCLK Rate */ 
-	{ 0x00000546, 0x0040 },   /* R1350  - AIF2 Rx BCLK Rate */ 
-	{ 0x00000547, 0x1818 },   /* R1351  - AIF2 Frame Ctrl 1 */ 
-	{ 0x00000548, 0x1818 },   /* R1352  - AIF2 Frame Ctrl 2 */ 
-	{ 0x00000549, 0x0000 },   /* R1353  - AIF2 Frame Ctrl 3 */ 
-	{ 0x0000054A, 0x0001 },   /* R1354  - AIF2 Frame Ctrl 4 */ 
-	{ 0x00000551, 0x0000 },   /* R1361  - AIF2 Frame Ctrl 11 */ 
-	{ 0x00000552, 0x0001 },   /* R1362  - AIF2 Frame Ctrl 12 */ 
-	{ 0x00000559, 0x0000 },   /* R1369  - AIF2 Tx Enables */ 
-	{ 0x0000055A, 0x0000 },   /* R1370  - AIF2 Rx Enables */ 
-	{ 0x00000580, 0x000C },   /* R1408  - AIF3 BCLK Ctrl */ 
-	{ 0x00000581, 0x0008 },   /* R1409  - AIF3 Tx Pin Ctrl */ 
-	{ 0x00000582, 0x0000 },   /* R1410  - AIF3 Rx Pin Ctrl */ 
-	{ 0x00000583, 0x0000 },   /* R1411  - AIF3 Rate Ctrl */ 
-	{ 0x00000584, 0x0000 },   /* R1412  - AIF3 Format */ 
-	{ 0x00000585, 0x0040 },   /* R1413  - AIF3 Tx BCLK Rate */ 
-	{ 0x00000586, 0x0040 },   /* R1414  - AIF3 Rx BCLK Rate */ 
-	{ 0x00000587, 0x1818 },   /* R1415  - AIF3 Frame Ctrl 1 */ 
-	{ 0x00000588, 0x1818 },   /* R1416  - AIF3 Frame Ctrl 2 */ 
-	{ 0x00000589, 0x0000 },   /* R1417  - AIF3 Frame Ctrl 3 */ 
-	{ 0x0000058A, 0x0001 },   /* R1418  - AIF3 Frame Ctrl 4 */ 
-	{ 0x00000591, 0x0000 },   /* R1425  - AIF3 Frame Ctrl 11 */ 
-	{ 0x00000592, 0x0001 },   /* R1426  - AIF3 Frame Ctrl 12 */ 
-	{ 0x00000599, 0x0000 },   /* R1433  - AIF3 Tx Enables */ 
-	{ 0x0000059A, 0x0000 },   /* R1434  - AIF3 Rx Enables */ 
-	{ 0x000005E3, 0x0004 },   /* R1507  - SLIMbus Framer Ref Gear */ 
-	{ 0x000005E5, 0x0000 },   /* R1509  - SLIMbus Rates 1 */ 
-	{ 0x000005E6, 0x0000 },   /* R1510  - SLIMbus Rates 2 */ 
-	{ 0x000005E7, 0x0000 },   /* R1511  - SLIMbus Rates 3 */ 
-	{ 0x000005E8, 0x0000 },   /* R1512  - SLIMbus Rates 4 */ 
-	{ 0x000005E9, 0x0000 },   /* R1513  - SLIMbus Rates 5 */ 
-	{ 0x000005EA, 0x0000 },   /* R1514  - SLIMbus Rates 6 */ 
-	{ 0x000005EB, 0x0000 },   /* R1515  - SLIMbus Rates 7 */ 
-	{ 0x000005EC, 0x0000 },   /* R1516  - SLIMbus Rates 8 */ 
-	{ 0x000005F5, 0x0000 },   /* R1525  - SLIMbus RX Channel Enable */ 
-	{ 0x000005F6, 0x0000 },   /* R1526  - SLIMbus TX Channel Enable */ 
-	{ 0x00000640, 0x0000 },   /* R1600  - PWM1MIX Input 1 Source */ 
-	{ 0x00000641, 0x0080 },   /* R1601  - PWM1MIX Input 1 Volume */ 
-	{ 0x00000642, 0x0000 },   /* R1602  - PWM1MIX Input 2 Source */ 
-	{ 0x00000643, 0x0080 },   /* R1603  - PWM1MIX Input 2 Volume */ 
-	{ 0x00000644, 0x0000 },   /* R1604  - PWM1MIX Input 3 Source */ 
-	{ 0x00000645, 0x0080 },   /* R1605  - PWM1MIX Input 3 Volume */ 
-	{ 0x00000646, 0x0000 },   /* R1606  - PWM1MIX Input 4 Source */ 
-	{ 0x00000647, 0x0080 },   /* R1607  - PWM1MIX Input 4 Volume */ 
-	{ 0x00000648, 0x0000 },   /* R1608  - PWM2MIX Input 1 Source */ 
-	{ 0x00000649, 0x0080 },   /* R1609  - PWM2MIX Input 1 Volume */ 
-	{ 0x0000064A, 0x0000 },   /* R1610  - PWM2MIX Input 2 Source */ 
-	{ 0x0000064B, 0x0080 },   /* R1611  - PWM2MIX Input 2 Volume */ 
-	{ 0x0000064C, 0x0000 },   /* R1612  - PWM2MIX Input 3 Source */ 
-	{ 0x0000064D, 0x0080 },   /* R1613  - PWM2MIX Input 3 Volume */ 
-	{ 0x0000064E, 0x0000 },   /* R1614  - PWM2MIX Input 4 Source */ 
-	{ 0x0000064F, 0x0080 },   /* R1615  - PWM2MIX Input 4 Volume */ 
-	{ 0x00000660, 0x0000 },   /* R1632  - MICMIX Input 1 Source */ 
-	{ 0x00000661, 0x0080 },   /* R1633  - MICMIX Input 1 Volume */ 
-	{ 0x00000662, 0x0000 },   /* R1634  - MICMIX Input 2 Source */ 
-	{ 0x00000663, 0x0080 },   /* R1635  - MICMIX Input 2 Volume */ 
-	{ 0x00000664, 0x0000 },   /* R1636  - MICMIX Input 3 Source */ 
-	{ 0x00000665, 0x0080 },   /* R1637  - MICMIX Input 3 Volume */ 
-	{ 0x00000666, 0x0000 },   /* R1638  - MICMIX Input 4 Source */ 
-	{ 0x00000667, 0x0080 },   /* R1639  - MICMIX Input 4 Volume */ 
-	{ 0x00000668, 0x0000 },   /* R1640  - NOISEMIX Input 1 Source */ 
-	{ 0x00000669, 0x0080 },   /* R1641  - NOISEMIX Input 1 Volume */ 
-	{ 0x0000066A, 0x0000 },   /* R1642  - NOISEMIX Input 2 Source */ 
-	{ 0x0000066B, 0x0080 },   /* R1643  - NOISEMIX Input 2 Volume */ 
-	{ 0x0000066C, 0x0000 },   /* R1644  - NOISEMIX Input 3 Source */ 
-	{ 0x0000066D, 0x0080 },   /* R1645  - NOISEMIX Input 3 Volume */ 
-	{ 0x0000066E, 0x0000 },   /* R1646  - NOISEMIX Input 4 Source */ 
-	{ 0x0000066F, 0x0080 },   /* R1647  - NOISEMIX Input 4 Volume */ 
-	{ 0x00000680, 0x0000 },   /* R1664  - OUT1LMIX Input 1 Source */ 
-	{ 0x00000681, 0x0080 },   /* R1665  - OUT1LMIX Input 1 Volume */ 
-	{ 0x00000682, 0x0000 },   /* R1666  - OUT1LMIX Input 2 Source */ 
-	{ 0x00000683, 0x0080 },   /* R1667  - OUT1LMIX Input 2 Volume */ 
-	{ 0x00000684, 0x0000 },   /* R1668  - OUT1LMIX Input 3 Source */ 
-	{ 0x00000685, 0x0080 },   /* R1669  - OUT1LMIX Input 3 Volume */ 
-	{ 0x00000686, 0x0000 },   /* R1670  - OUT1LMIX Input 4 Source */ 
-	{ 0x00000687, 0x0080 },   /* R1671  - OUT1LMIX Input 4 Volume */ 
-	{ 0x00000688, 0x0000 },   /* R1672  - OUT1RMIX Input 1 Source */ 
-	{ 0x00000689, 0x0080 },   /* R1673  - OUT1RMIX Input 1 Volume */ 
-	{ 0x0000068A, 0x0000 },   /* R1674  - OUT1RMIX Input 2 Source */ 
-	{ 0x0000068B, 0x0080 },   /* R1675  - OUT1RMIX Input 2 Volume */ 
-	{ 0x0000068C, 0x0000 },   /* R1676  - OUT1RMIX Input 3 Source */ 
-	{ 0x0000068D, 0x0080 },   /* R1677  - OUT1RMIX Input 3 Volume */ 
-	{ 0x0000068E, 0x0000 },   /* R1678  - OUT1RMIX Input 4 Source */ 
-	{ 0x0000068F, 0x0080 },   /* R1679  - OUT1RMIX Input 4 Volume */ 
-	{ 0x00000690, 0x0000 },   /* R1680  - OUT2LMIX Input 1 Source */ 
-	{ 0x00000691, 0x0080 },   /* R1681  - OUT2LMIX Input 1 Volume */ 
-	{ 0x00000692, 0x0000 },   /* R1682  - OUT2LMIX Input 2 Source */ 
-	{ 0x00000693, 0x0080 },   /* R1683  - OUT2LMIX Input 2 Volume */ 
-	{ 0x00000694, 0x0000 },   /* R1684  - OUT2LMIX Input 3 Source */ 
-	{ 0x00000695, 0x0080 },   /* R1685  - OUT2LMIX Input 3 Volume */ 
-	{ 0x00000696, 0x0000 },   /* R1686  - OUT2LMIX Input 4 Source */ 
-	{ 0x00000697, 0x0080 },   /* R1687  - OUT2LMIX Input 4 Volume */ 
-	{ 0x00000698, 0x0000 },   /* R1688  - OUT2RMIX Input 1 Source */ 
-	{ 0x00000699, 0x0080 },   /* R1689  - OUT2RMIX Input 1 Volume */ 
-	{ 0x0000069A, 0x0000 },   /* R1690  - OUT2RMIX Input 2 Source */ 
-	{ 0x0000069B, 0x0080 },   /* R1691  - OUT2RMIX Input 2 Volume */ 
-	{ 0x0000069C, 0x0000 },   /* R1692  - OUT2RMIX Input 3 Source */ 
-	{ 0x0000069D, 0x0080 },   /* R1693  - OUT2RMIX Input 3 Volume */ 
-	{ 0x0000069E, 0x0000 },   /* R1694  - OUT2RMIX Input 4 Source */ 
-	{ 0x0000069F, 0x0080 },   /* R1695  - OUT2RMIX Input 4 Volume */ 
-	{ 0x000006A0, 0x0000 },   /* R1696  - OUT3LMIX Input 1 Source */ 
-	{ 0x000006A1, 0x0080 },   /* R1697  - OUT3LMIX Input 1 Volume */ 
-	{ 0x000006A2, 0x0000 },   /* R1698  - OUT3LMIX Input 2 Source */ 
-	{ 0x000006A3, 0x0080 },   /* R1699  - OUT3LMIX Input 2 Volume */ 
-	{ 0x000006A4, 0x0000 },   /* R1700  - OUT3LMIX Input 3 Source */ 
-	{ 0x000006A5, 0x0080 },   /* R1701  - OUT3LMIX Input 3 Volume */ 
-	{ 0x000006A6, 0x0000 },   /* R1702  - OUT3LMIX Input 4 Source */ 
-	{ 0x000006A7, 0x0080 },   /* R1703  - OUT3LMIX Input 4 Volume */ 
-	{ 0x000006B0, 0x0000 },   /* R1712  - OUT4LMIX Input 1 Source */ 
-	{ 0x000006B1, 0x0080 },   /* R1713  - OUT4LMIX Input 1 Volume */ 
-	{ 0x000006B2, 0x0000 },   /* R1714  - OUT4LMIX Input 2 Source */ 
-	{ 0x000006B3, 0x0080 },   /* R1715  - OUT4LMIX Input 2 Volume */ 
-	{ 0x000006B4, 0x0000 },   /* R1716  - OUT4LMIX Input 3 Source */ 
-	{ 0x000006B5, 0x0080 },   /* R1717  - OUT4LMIX Input 3 Volume */ 
-	{ 0x000006B6, 0x0000 },   /* R1718  - OUT4LMIX Input 4 Source */ 
-	{ 0x000006B7, 0x0080 },   /* R1719  - OUT4LMIX Input 4 Volume */ 
-	{ 0x000006B8, 0x0000 },   /* R1720  - OUT4RMIX Input 1 Source */ 
-	{ 0x000006B9, 0x0080 },   /* R1721  - OUT4RMIX Input 1 Volume */ 
-	{ 0x000006BA, 0x0000 },   /* R1722  - OUT4RMIX Input 2 Source */ 
-	{ 0x000006BB, 0x0080 },   /* R1723  - OUT4RMIX Input 2 Volume */ 
-	{ 0x000006BC, 0x0000 },   /* R1724  - OUT4RMIX Input 3 Source */ 
-	{ 0x000006BD, 0x0080 },   /* R1725  - OUT4RMIX Input 3 Volume */ 
-	{ 0x000006BE, 0x0000 },   /* R1726  - OUT4RMIX Input 4 Source */ 
-	{ 0x000006BF, 0x0080 },   /* R1727  - OUT4RMIX Input 4 Volume */ 
-	{ 0x000006C0, 0x0000 },   /* R1728  - OUT5LMIX Input 1 Source */ 
-	{ 0x000006C1, 0x0080 },   /* R1729  - OUT5LMIX Input 1 Volume */ 
-	{ 0x000006C2, 0x0000 },   /* R1730  - OUT5LMIX Input 2 Source */ 
-	{ 0x000006C3, 0x0080 },   /* R1731  - OUT5LMIX Input 2 Volume */ 
-	{ 0x000006C4, 0x0000 },   /* R1732  - OUT5LMIX Input 3 Source */ 
-	{ 0x000006C5, 0x0080 },   /* R1733  - OUT5LMIX Input 3 Volume */ 
-	{ 0x000006C6, 0x0000 },   /* R1734  - OUT5LMIX Input 4 Source */ 
-	{ 0x000006C7, 0x0080 },   /* R1735  - OUT5LMIX Input 4 Volume */ 
-	{ 0x000006C8, 0x0000 },   /* R1736  - OUT5RMIX Input 1 Source */ 
-	{ 0x000006C9, 0x0080 },   /* R1737  - OUT5RMIX Input 1 Volume */ 
-	{ 0x000006CA, 0x0000 },   /* R1738  - OUT5RMIX Input 2 Source */ 
-	{ 0x000006CB, 0x0080 },   /* R1739  - OUT5RMIX Input 2 Volume */ 
-	{ 0x000006CC, 0x0000 },   /* R1740  - OUT5RMIX Input 3 Source */ 
-	{ 0x000006CD, 0x0080 },   /* R1741  - OUT5RMIX Input 3 Volume */ 
-	{ 0x000006CE, 0x0000 },   /* R1742  - OUT5RMIX Input 4 Source */ 
-	{ 0x000006CF, 0x0080 },   /* R1743  - OUT5RMIX Input 4 Volume */ 
-	{ 0x00000700, 0x0000 },   /* R1792  - AIF1TX1MIX Input 1 Source */ 
-	{ 0x00000701, 0x0080 },   /* R1793  - AIF1TX1MIX Input 1 Volume */ 
-	{ 0x00000702, 0x0000 },   /* R1794  - AIF1TX1MIX Input 2 Source */ 
-	{ 0x00000703, 0x0080 },   /* R1795  - AIF1TX1MIX Input 2 Volume */ 
-	{ 0x00000704, 0x0000 },   /* R1796  - AIF1TX1MIX Input 3 Source */ 
-	{ 0x00000705, 0x0080 },   /* R1797  - AIF1TX1MIX Input 3 Volume */ 
-	{ 0x00000706, 0x0000 },   /* R1798  - AIF1TX1MIX Input 4 Source */ 
-	{ 0x00000707, 0x0080 },   /* R1799  - AIF1TX1MIX Input 4 Volume */ 
-	{ 0x00000708, 0x0000 },   /* R1800  - AIF1TX2MIX Input 1 Source */ 
-	{ 0x00000709, 0x0080 },   /* R1801  - AIF1TX2MIX Input 1 Volume */ 
-	{ 0x0000070A, 0x0000 },   /* R1802  - AIF1TX2MIX Input 2 Source */ 
-	{ 0x0000070B, 0x0080 },   /* R1803  - AIF1TX2MIX Input 2 Volume */ 
-	{ 0x0000070C, 0x0000 },   /* R1804  - AIF1TX2MIX Input 3 Source */ 
-	{ 0x0000070D, 0x0080 },   /* R1805  - AIF1TX2MIX Input 3 Volume */ 
-	{ 0x0000070E, 0x0000 },   /* R1806  - AIF1TX2MIX Input 4 Source */ 
-	{ 0x0000070F, 0x0080 },   /* R1807  - AIF1TX2MIX Input 4 Volume */ 
-	{ 0x00000710, 0x0000 },   /* R1808  - AIF1TX3MIX Input 1 Source */ 
-	{ 0x00000711, 0x0080 },   /* R1809  - AIF1TX3MIX Input 1 Volume */ 
-	{ 0x00000712, 0x0000 },   /* R1810  - AIF1TX3MIX Input 2 Source */ 
-	{ 0x00000713, 0x0080 },   /* R1811  - AIF1TX3MIX Input 2 Volume */ 
-	{ 0x00000714, 0x0000 },   /* R1812  - AIF1TX3MIX Input 3 Source */ 
-	{ 0x00000715, 0x0080 },   /* R1813  - AIF1TX3MIX Input 3 Volume */ 
-	{ 0x00000716, 0x0000 },   /* R1814  - AIF1TX3MIX Input 4 Source */ 
-	{ 0x00000717, 0x0080 },   /* R1815  - AIF1TX3MIX Input 4 Volume */ 
-	{ 0x00000718, 0x0000 },   /* R1816  - AIF1TX4MIX Input 1 Source */ 
-	{ 0x00000719, 0x0080 },   /* R1817  - AIF1TX4MIX Input 1 Volume */ 
-	{ 0x0000071A, 0x0000 },   /* R1818  - AIF1TX4MIX Input 2 Source */ 
-	{ 0x0000071B, 0x0080 },   /* R1819  - AIF1TX4MIX Input 2 Volume */ 
-	{ 0x0000071C, 0x0000 },   /* R1820  - AIF1TX4MIX Input 3 Source */ 
-	{ 0x0000071D, 0x0080 },   /* R1821  - AIF1TX4MIX Input 3 Volume */ 
-	{ 0x0000071E, 0x0000 },   /* R1822  - AIF1TX4MIX Input 4 Source */ 
-	{ 0x0000071F, 0x0080 },   /* R1823  - AIF1TX4MIX Input 4 Volume */ 
-	{ 0x00000720, 0x0000 },   /* R1824  - AIF1TX5MIX Input 1 Source */ 
-	{ 0x00000721, 0x0080 },   /* R1825  - AIF1TX5MIX Input 1 Volume */ 
-	{ 0x00000722, 0x0000 },   /* R1826  - AIF1TX5MIX Input 2 Source */ 
-	{ 0x00000723, 0x0080 },   /* R1827  - AIF1TX5MIX Input 2 Volume */ 
-	{ 0x00000724, 0x0000 },   /* R1828  - AIF1TX5MIX Input 3 Source */ 
-	{ 0x00000725, 0x0080 },   /* R1829  - AIF1TX5MIX Input 3 Volume */ 
-	{ 0x00000726, 0x0000 },   /* R1830  - AIF1TX5MIX Input 4 Source */ 
-	{ 0x00000727, 0x0080 },   /* R1831  - AIF1TX5MIX Input 4 Volume */ 
-	{ 0x00000728, 0x0000 },   /* R1832  - AIF1TX6MIX Input 1 Source */ 
-	{ 0x00000729, 0x0080 },   /* R1833  - AIF1TX6MIX Input 1 Volume */ 
-	{ 0x0000072A, 0x0000 },   /* R1834  - AIF1TX6MIX Input 2 Source */ 
-	{ 0x0000072B, 0x0080 },   /* R1835  - AIF1TX6MIX Input 2 Volume */ 
-	{ 0x0000072C, 0x0000 },   /* R1836  - AIF1TX6MIX Input 3 Source */ 
-	{ 0x0000072D, 0x0080 },   /* R1837  - AIF1TX6MIX Input 3 Volume */ 
-	{ 0x0000072E, 0x0000 },   /* R1838  - AIF1TX6MIX Input 4 Source */ 
-	{ 0x0000072F, 0x0080 },   /* R1839  - AIF1TX6MIX Input 4 Volume */ 
-	{ 0x00000730, 0x0000 },   /* R1840  - AIF1TX7MIX Input 1 Source */ 
-	{ 0x00000731, 0x0080 },   /* R1841  - AIF1TX7MIX Input 1 Volume */ 
-	{ 0x00000732, 0x0000 },   /* R1842  - AIF1TX7MIX Input 2 Source */ 
-	{ 0x00000733, 0x0080 },   /* R1843  - AIF1TX7MIX Input 2 Volume */ 
-	{ 0x00000734, 0x0000 },   /* R1844  - AIF1TX7MIX Input 3 Source */ 
-	{ 0x00000735, 0x0080 },   /* R1845  - AIF1TX7MIX Input 3 Volume */ 
-	{ 0x00000736, 0x0000 },   /* R1846  - AIF1TX7MIX Input 4 Source */ 
-	{ 0x00000737, 0x0080 },   /* R1847  - AIF1TX7MIX Input 4 Volume */ 
-	{ 0x00000738, 0x0000 },   /* R1848  - AIF1TX8MIX Input 1 Source */ 
-	{ 0x00000739, 0x0080 },   /* R1849  - AIF1TX8MIX Input 1 Volume */ 
-	{ 0x0000073A, 0x0000 },   /* R1850  - AIF1TX8MIX Input 2 Source */ 
-	{ 0x0000073B, 0x0080 },   /* R1851  - AIF1TX8MIX Input 2 Volume */ 
-	{ 0x0000073C, 0x0000 },   /* R1852  - AIF1TX8MIX Input 3 Source */ 
-	{ 0x0000073D, 0x0080 },   /* R1853  - AIF1TX8MIX Input 3 Volume */ 
-	{ 0x0000073E, 0x0000 },   /* R1854  - AIF1TX8MIX Input 4 Source */ 
-	{ 0x0000073F, 0x0080 },   /* R1855  - AIF1TX8MIX Input 4 Volume */ 
-	{ 0x00000740, 0x0000 },   /* R1856  - AIF2TX1MIX Input 1 Source */ 
-	{ 0x00000741, 0x0080 },   /* R1857  - AIF2TX1MIX Input 1 Volume */ 
-	{ 0x00000742, 0x0000 },   /* R1858  - AIF2TX1MIX Input 2 Source */ 
-	{ 0x00000743, 0x0080 },   /* R1859  - AIF2TX1MIX Input 2 Volume */ 
-	{ 0x00000744, 0x0000 },   /* R1860  - AIF2TX1MIX Input 3 Source */ 
-	{ 0x00000745, 0x0080 },   /* R1861  - AIF2TX1MIX Input 3 Volume */ 
-	{ 0x00000746, 0x0000 },   /* R1862  - AIF2TX1MIX Input 4 Source */ 
-	{ 0x00000747, 0x0080 },   /* R1863  - AIF2TX1MIX Input 4 Volume */ 
-	{ 0x00000748, 0x0000 },   /* R1864  - AIF2TX2MIX Input 1 Source */ 
-	{ 0x00000749, 0x0080 },   /* R1865  - AIF2TX2MIX Input 1 Volume */ 
-	{ 0x0000074A, 0x0000 },   /* R1866  - AIF2TX2MIX Input 2 Source */ 
-	{ 0x0000074B, 0x0080 },   /* R1867  - AIF2TX2MIX Input 2 Volume */ 
-	{ 0x0000074C, 0x0000 },   /* R1868  - AIF2TX2MIX Input 3 Source */ 
-	{ 0x0000074D, 0x0080 },   /* R1869  - AIF2TX2MIX Input 3 Volume */ 
-	{ 0x0000074E, 0x0000 },   /* R1870  - AIF2TX2MIX Input 4 Source */ 
-	{ 0x0000074F, 0x0080 },   /* R1871  - AIF2TX2MIX Input 4 Volume */ 
-	{ 0x00000780, 0x0000 },   /* R1920  - AIF3TX1MIX Input 1 Source */ 
-	{ 0x00000781, 0x0080 },   /* R1921  - AIF3TX1MIX Input 1 Volume */ 
-	{ 0x00000782, 0x0000 },   /* R1922  - AIF3TX1MIX Input 2 Source */ 
-	{ 0x00000783, 0x0080 },   /* R1923  - AIF3TX1MIX Input 2 Volume */ 
-	{ 0x00000784, 0x0000 },   /* R1924  - AIF3TX1MIX Input 3 Source */ 
-	{ 0x00000785, 0x0080 },   /* R1925  - AIF3TX1MIX Input 3 Volume */ 
-	{ 0x00000786, 0x0000 },   /* R1926  - AIF3TX1MIX Input 4 Source */ 
-	{ 0x00000787, 0x0080 },   /* R1927  - AIF3TX1MIX Input 4 Volume */ 
-	{ 0x00000788, 0x0000 },   /* R1928  - AIF3TX2MIX Input 1 Source */ 
-	{ 0x00000789, 0x0080 },   /* R1929  - AIF3TX2MIX Input 1 Volume */ 
-	{ 0x0000078A, 0x0000 },   /* R1930  - AIF3TX2MIX Input 2 Source */ 
-	{ 0x0000078B, 0x0080 },   /* R1931  - AIF3TX2MIX Input 2 Volume */ 
-	{ 0x0000078C, 0x0000 },   /* R1932  - AIF3TX2MIX Input 3 Source */ 
-	{ 0x0000078D, 0x0080 },   /* R1933  - AIF3TX2MIX Input 3 Volume */ 
-	{ 0x0000078E, 0x0000 },   /* R1934  - AIF3TX2MIX Input 4 Source */ 
-	{ 0x0000078F, 0x0080 },   /* R1935  - AIF3TX2MIX Input 4 Volume */ 
-	{ 0x000007C0, 0x0000 },   /* R1984  - SLIMTX1MIX Input 1 Source */ 
-	{ 0x000007C1, 0x0080 },   /* R1985  - SLIMTX1MIX Input 1 Volume */ 
-	{ 0x000007C2, 0x0000 },   /* R1986  - SLIMTX1MIX Input 2 Source */ 
-	{ 0x000007C3, 0x0080 },   /* R1987  - SLIMTX1MIX Input 2 Volume */ 
-	{ 0x000007C4, 0x0000 },   /* R1988  - SLIMTX1MIX Input 3 Source */ 
-	{ 0x000007C5, 0x0080 },   /* R1989  - SLIMTX1MIX Input 3 Volume */ 
-	{ 0x000007C6, 0x0000 },   /* R1990  - SLIMTX1MIX Input 4 Source */ 
-	{ 0x000007C7, 0x0080 },   /* R1991  - SLIMTX1MIX Input 4 Volume */ 
-	{ 0x000007C8, 0x0000 },   /* R1992  - SLIMTX2MIX Input 1 Source */ 
-	{ 0x000007C9, 0x0080 },   /* R1993  - SLIMTX2MIX Input 1 Volume */ 
-	{ 0x000007CA, 0x0000 },   /* R1994  - SLIMTX2MIX Input 2 Source */ 
-	{ 0x000007CB, 0x0080 },   /* R1995  - SLIMTX2MIX Input 2 Volume */ 
-	{ 0x000007CC, 0x0000 },   /* R1996  - SLIMTX2MIX Input 3 Source */ 
-	{ 0x000007CD, 0x0080 },   /* R1997  - SLIMTX2MIX Input 3 Volume */ 
-	{ 0x000007CE, 0x0000 },   /* R1998  - SLIMTX2MIX Input 4 Source */ 
-	{ 0x000007CF, 0x0080 },   /* R1999  - SLIMTX2MIX Input 4 Volume */ 
-	{ 0x000007D0, 0x0000 },   /* R2000  - SLIMTX3MIX Input 1 Source */ 
-	{ 0x000007D1, 0x0080 },   /* R2001  - SLIMTX3MIX Input 1 Volume */ 
-	{ 0x000007D2, 0x0000 },   /* R2002  - SLIMTX3MIX Input 2 Source */ 
-	{ 0x000007D3, 0x0080 },   /* R2003  - SLIMTX3MIX Input 2 Volume */ 
-	{ 0x000007D4, 0x0000 },   /* R2004  - SLIMTX3MIX Input 3 Source */ 
-	{ 0x000007D5, 0x0080 },   /* R2005  - SLIMTX3MIX Input 3 Volume */ 
-	{ 0x000007D6, 0x0000 },   /* R2006  - SLIMTX3MIX Input 4 Source */ 
-	{ 0x000007D7, 0x0080 },   /* R2007  - SLIMTX3MIX Input 4 Volume */ 
-	{ 0x000007D8, 0x0000 },   /* R2008  - SLIMTX4MIX Input 1 Source */ 
-	{ 0x000007D9, 0x0080 },   /* R2009  - SLIMTX4MIX Input 1 Volume */ 
-	{ 0x000007DA, 0x0000 },   /* R2010  - SLIMTX4MIX Input 2 Source */ 
-	{ 0x000007DB, 0x0080 },   /* R2011  - SLIMTX4MIX Input 2 Volume */ 
-	{ 0x000007DC, 0x0000 },   /* R2012  - SLIMTX4MIX Input 3 Source */ 
-	{ 0x000007DD, 0x0080 },   /* R2013  - SLIMTX4MIX Input 3 Volume */ 
-	{ 0x000007DE, 0x0000 },   /* R2014  - SLIMTX4MIX Input 4 Source */ 
-	{ 0x000007DF, 0x0080 },   /* R2015  - SLIMTX4MIX Input 4 Volume */ 
-	{ 0x000007E0, 0x0000 },   /* R2016  - SLIMTX5MIX Input 1 Source */ 
-	{ 0x000007E1, 0x0080 },   /* R2017  - SLIMTX5MIX Input 1 Volume */ 
-	{ 0x000007E2, 0x0000 },   /* R2018  - SLIMTX5MIX Input 2 Source */ 
-	{ 0x000007E3, 0x0080 },   /* R2019  - SLIMTX5MIX Input 2 Volume */ 
-	{ 0x000007E4, 0x0000 },   /* R2020  - SLIMTX5MIX Input 3 Source */ 
-	{ 0x000007E5, 0x0080 },   /* R2021  - SLIMTX5MIX Input 3 Volume */ 
-	{ 0x000007E6, 0x0000 },   /* R2022  - SLIMTX5MIX Input 4 Source */ 
-	{ 0x000007E7, 0x0080 },   /* R2023  - SLIMTX5MIX Input 4 Volume */ 
-	{ 0x000007E8, 0x0000 },   /* R2024  - SLIMTX6MIX Input 1 Source */ 
-	{ 0x000007E9, 0x0080 },   /* R2025  - SLIMTX6MIX Input 1 Volume */ 
-	{ 0x000007EA, 0x0000 },   /* R2026  - SLIMTX6MIX Input 2 Source */ 
-	{ 0x000007EB, 0x0080 },   /* R2027  - SLIMTX6MIX Input 2 Volume */ 
-	{ 0x000007EC, 0x0000 },   /* R2028  - SLIMTX6MIX Input 3 Source */ 
-	{ 0x000007ED, 0x0080 },   /* R2029  - SLIMTX6MIX Input 3 Volume */ 
-	{ 0x000007EE, 0x0000 },   /* R2030  - SLIMTX6MIX Input 4 Source */ 
-	{ 0x000007EF, 0x0080 },   /* R2031  - SLIMTX6MIX Input 4 Volume */ 
-	{ 0x000007F0, 0x0000 },   /* R2032  - SLIMTX7MIX Input 1 Source */ 
-	{ 0x000007F1, 0x0080 },   /* R2033  - SLIMTX7MIX Input 1 Volume */ 
-	{ 0x000007F2, 0x0000 },   /* R2034  - SLIMTX7MIX Input 2 Source */ 
-	{ 0x000007F3, 0x0080 },   /* R2035  - SLIMTX7MIX Input 2 Volume */ 
-	{ 0x000007F4, 0x0000 },   /* R2036  - SLIMTX7MIX Input 3 Source */ 
-	{ 0x000007F5, 0x0080 },   /* R2037  - SLIMTX7MIX Input 3 Volume */ 
-	{ 0x000007F6, 0x0000 },   /* R2038  - SLIMTX7MIX Input 4 Source */ 
-	{ 0x000007F7, 0x0080 },   /* R2039  - SLIMTX7MIX Input 4 Volume */ 
-	{ 0x000007F8, 0x0000 },   /* R2040  - SLIMTX8MIX Input 1 Source */ 
-	{ 0x000007F9, 0x0080 },   /* R2041  - SLIMTX8MIX Input 1 Volume */ 
-	{ 0x000007FA, 0x0000 },   /* R2042  - SLIMTX8MIX Input 2 Source */ 
-	{ 0x000007FB, 0x0080 },   /* R2043  - SLIMTX8MIX Input 2 Volume */ 
-	{ 0x000007FC, 0x0000 },   /* R2044  - SLIMTX8MIX Input 3 Source */ 
-	{ 0x000007FD, 0x0080 },   /* R2045  - SLIMTX8MIX Input 3 Volume */ 
-	{ 0x000007FE, 0x0000 },   /* R2046  - SLIMTX8MIX Input 4 Source */ 
-	{ 0x000007FF, 0x0080 },   /* R2047  - SLIMTX8MIX Input 4 Volume */ 
-	{ 0x00000880, 0x0000 },   /* R2176  - EQ1MIX Input 1 Source */ 
-	{ 0x00000881, 0x0080 },   /* R2177  - EQ1MIX Input 1 Volume */ 
-	{ 0x00000882, 0x0000 },   /* R2178  - EQ1MIX Input 2 Source */ 
-	{ 0x00000883, 0x0080 },   /* R2179  - EQ1MIX Input 2 Volume */ 
-	{ 0x00000884, 0x0000 },   /* R2180  - EQ1MIX Input 3 Source */ 
-	{ 0x00000885, 0x0080 },   /* R2181  - EQ1MIX Input 3 Volume */ 
-	{ 0x00000886, 0x0000 },   /* R2182  - EQ1MIX Input 4 Source */ 
-	{ 0x00000887, 0x0080 },   /* R2183  - EQ1MIX Input 4 Volume */ 
-	{ 0x00000888, 0x0000 },   /* R2184  - EQ2MIX Input 1 Source */ 
-	{ 0x00000889, 0x0080 },   /* R2185  - EQ2MIX Input 1 Volume */ 
-	{ 0x0000088A, 0x0000 },   /* R2186  - EQ2MIX Input 2 Source */ 
-	{ 0x0000088B, 0x0080 },   /* R2187  - EQ2MIX Input 2 Volume */ 
-	{ 0x0000088C, 0x0000 },   /* R2188  - EQ2MIX Input 3 Source */ 
-	{ 0x0000088D, 0x0080 },   /* R2189  - EQ2MIX Input 3 Volume */ 
-	{ 0x0000088E, 0x0000 },   /* R2190  - EQ2MIX Input 4 Source */ 
-	{ 0x0000088F, 0x0080 },   /* R2191  - EQ2MIX Input 4 Volume */ 
-	{ 0x00000890, 0x0000 },   /* R2192  - EQ3MIX Input 1 Source */ 
-	{ 0x00000891, 0x0080 },   /* R2193  - EQ3MIX Input 1 Volume */ 
-	{ 0x00000892, 0x0000 },   /* R2194  - EQ3MIX Input 2 Source */ 
-	{ 0x00000893, 0x0080 },   /* R2195  - EQ3MIX Input 2 Volume */ 
-	{ 0x00000894, 0x0000 },   /* R2196  - EQ3MIX Input 3 Source */ 
-	{ 0x00000895, 0x0080 },   /* R2197  - EQ3MIX Input 3 Volume */ 
-	{ 0x00000896, 0x0000 },   /* R2198  - EQ3MIX Input 4 Source */ 
-	{ 0x00000897, 0x0080 },   /* R2199  - EQ3MIX Input 4 Volume */ 
-	{ 0x00000898, 0x0000 },   /* R2200  - EQ4MIX Input 1 Source */ 
-	{ 0x00000899, 0x0080 },   /* R2201  - EQ4MIX Input 1 Volume */ 
-	{ 0x0000089A, 0x0000 },   /* R2202  - EQ4MIX Input 2 Source */ 
-	{ 0x0000089B, 0x0080 },   /* R2203  - EQ4MIX Input 2 Volume */ 
-	{ 0x0000089C, 0x0000 },   /* R2204  - EQ4MIX Input 3 Source */ 
-	{ 0x0000089D, 0x0080 },   /* R2205  - EQ4MIX Input 3 Volume */ 
-	{ 0x0000089E, 0x0000 },   /* R2206  - EQ4MIX Input 4 Source */ 
-	{ 0x0000089F, 0x0080 },   /* R2207  - EQ4MIX Input 4 Volume */ 
-	{ 0x000008C0, 0x0000 },   /* R2240  - DRC1LMIX Input 1 Source */ 
-	{ 0x000008C1, 0x0080 },   /* R2241  - DRC1LMIX Input 1 Volume */ 
-	{ 0x000008C2, 0x0000 },   /* R2242  - DRC1LMIX Input 2 Source */ 
-	{ 0x000008C3, 0x0080 },   /* R2243  - DRC1LMIX Input 2 Volume */ 
-	{ 0x000008C4, 0x0000 },   /* R2244  - DRC1LMIX Input 3 Source */ 
-	{ 0x000008C5, 0x0080 },   /* R2245  - DRC1LMIX Input 3 Volume */ 
-	{ 0x000008C6, 0x0000 },   /* R2246  - DRC1LMIX Input 4 Source */ 
-	{ 0x000008C7, 0x0080 },   /* R2247  - DRC1LMIX Input 4 Volume */ 
-	{ 0x000008C8, 0x0000 },   /* R2248  - DRC1RMIX Input 1 Source */ 
-	{ 0x000008C9, 0x0080 },   /* R2249  - DRC1RMIX Input 1 Volume */ 
-	{ 0x000008CA, 0x0000 },   /* R2250  - DRC1RMIX Input 2 Source */ 
-	{ 0x000008CB, 0x0080 },   /* R2251  - DRC1RMIX Input 2 Volume */ 
-	{ 0x000008CC, 0x0000 },   /* R2252  - DRC1RMIX Input 3 Source */ 
-	{ 0x000008CD, 0x0080 },   /* R2253  - DRC1RMIX Input 3 Volume */ 
-	{ 0x000008CE, 0x0000 },   /* R2254  - DRC1RMIX Input 4 Source */ 
-	{ 0x000008CF, 0x0080 },   /* R2255  - DRC1RMIX Input 4 Volume */ 
-	{ 0x00000900, 0x0000 },   /* R2304  - HPLP1MIX Input 1 Source */ 
-	{ 0x00000901, 0x0080 },   /* R2305  - HPLP1MIX Input 1 Volume */ 
-	{ 0x00000902, 0x0000 },   /* R2306  - HPLP1MIX Input 2 Source */ 
-	{ 0x00000903, 0x0080 },   /* R2307  - HPLP1MIX Input 2 Volume */ 
-	{ 0x00000904, 0x0000 },   /* R2308  - HPLP1MIX Input 3 Source */ 
-	{ 0x00000905, 0x0080 },   /* R2309  - HPLP1MIX Input 3 Volume */ 
-	{ 0x00000906, 0x0000 },   /* R2310  - HPLP1MIX Input 4 Source */ 
-	{ 0x00000907, 0x0080 },   /* R2311  - HPLP1MIX Input 4 Volume */ 
-	{ 0x00000908, 0x0000 },   /* R2312  - HPLP2MIX Input 1 Source */ 
-	{ 0x00000909, 0x0080 },   /* R2313  - HPLP2MIX Input 1 Volume */ 
-	{ 0x0000090A, 0x0000 },   /* R2314  - HPLP2MIX Input 2 Source */ 
-	{ 0x0000090B, 0x0080 },   /* R2315  - HPLP2MIX Input 2 Volume */ 
-	{ 0x0000090C, 0x0000 },   /* R2316  - HPLP2MIX Input 3 Source */ 
-	{ 0x0000090D, 0x0080 },   /* R2317  - HPLP2MIX Input 3 Volume */ 
-	{ 0x0000090E, 0x0000 },   /* R2318  - HPLP2MIX Input 4 Source */ 
-	{ 0x0000090F, 0x0080 },   /* R2319  - HPLP2MIX Input 4 Volume */ 
-	{ 0x00000910, 0x0000 },   /* R2320  - HPLP3MIX Input 1 Source */ 
-	{ 0x00000911, 0x0080 },   /* R2321  - HPLP3MIX Input 1 Volume */ 
-	{ 0x00000912, 0x0000 },   /* R2322  - HPLP3MIX Input 2 Source */ 
-	{ 0x00000913, 0x0080 },   /* R2323  - HPLP3MIX Input 2 Volume */ 
-	{ 0x00000914, 0x0000 },   /* R2324  - HPLP3MIX Input 3 Source */ 
-	{ 0x00000915, 0x0080 },   /* R2325  - HPLP3MIX Input 3 Volume */ 
-	{ 0x00000916, 0x0000 },   /* R2326  - HPLP3MIX Input 4 Source */ 
-	{ 0x00000917, 0x0080 },   /* R2327  - HPLP3MIX Input 4 Volume */ 
-	{ 0x00000918, 0x0000 },   /* R2328  - HPLP4MIX Input 1 Source */ 
-	{ 0x00000919, 0x0080 },   /* R2329  - HPLP4MIX Input 1 Volume */ 
-	{ 0x0000091A, 0x0000 },   /* R2330  - HPLP4MIX Input 2 Source */ 
-	{ 0x0000091B, 0x0080 },   /* R2331  - HPLP4MIX Input 2 Volume */ 
-	{ 0x0000091C, 0x0000 },   /* R2332  - HPLP4MIX Input 3 Source */ 
-	{ 0x0000091D, 0x0080 },   /* R2333  - HPLP4MIX Input 3 Volume */ 
-	{ 0x0000091E, 0x0000 },   /* R2334  - HPLP4MIX Input 4 Source */ 
-	{ 0x0000091F, 0x0080 },   /* R2335  - HPLP4MIX Input 4 Volume */ 
-	{ 0x00000940, 0x0000 },   /* R2368  - DSP1LMIX Input 1 Source */ 
-	{ 0x00000941, 0x0080 },   /* R2369  - DSP1LMIX Input 1 Volume */ 
-	{ 0x00000942, 0x0000 },   /* R2370  - DSP1LMIX Input 2 Source */ 
-	{ 0x00000943, 0x0080 },   /* R2371  - DSP1LMIX Input 2 Volume */ 
-	{ 0x00000944, 0x0000 },   /* R2372  - DSP1LMIX Input 3 Source */ 
-	{ 0x00000945, 0x0080 },   /* R2373  - DSP1LMIX Input 3 Volume */ 
-	{ 0x00000946, 0x0000 },   /* R2374  - DSP1LMIX Input 4 Source */ 
-	{ 0x00000947, 0x0080 },   /* R2375  - DSP1LMIX Input 4 Volume */ 
-	{ 0x00000948, 0x0000 },   /* R2376  - DSP1RMIX Input 1 Source */ 
-	{ 0x00000949, 0x0080 },   /* R2377  - DSP1RMIX Input 1 Volume */ 
-	{ 0x0000094A, 0x0000 },   /* R2378  - DSP1RMIX Input 2 Source */ 
-	{ 0x0000094B, 0x0080 },   /* R2379  - DSP1RMIX Input 2 Volume */ 
-	{ 0x0000094C, 0x0000 },   /* R2380  - DSP1RMIX Input 3 Source */ 
-	{ 0x0000094D, 0x0080 },   /* R2381  - DSP1RMIX Input 3 Volume */ 
-	{ 0x0000094E, 0x0000 },   /* R2382  - DSP1RMIX Input 4 Source */ 
-	{ 0x0000094F, 0x0080 },   /* R2383  - DSP1RMIX Input 4 Volume */ 
-	{ 0x00000950, 0x0000 },   /* R2384  - DSP1AUX1MIX Input 1 Source */ 
-	{ 0x00000958, 0x0000 },   /* R2392  - DSP1AUX2MIX Input 1 Source */ 
-	{ 0x00000960, 0x0000 },   /* R2400  - DSP1AUX3MIX Input 1 Source */ 
-	{ 0x00000968, 0x0000 },   /* R2408  - DSP1AUX4MIX Input 1 Source */ 
-	{ 0x00000970, 0x0000 },   /* R2416  - DSP1AUX5MIX Input 1 Source */ 
-	{ 0x00000978, 0x0000 },   /* R2424  - DSP1AUX6MIX Input 1 Source */ 
-	{ 0x00000A80, 0x0000 },   /* R2688  - ASRC1LMIX Input 1 Source */ 
-	{ 0x00000A88, 0x0000 },   /* R2696  - ASRC1RMIX Input 1 Source */ 
-	{ 0x00000A90, 0x0000 },   /* R2704  - ASRC2LMIX Input 1 Source */ 
-	{ 0x00000A98, 0x0000 },   /* R2712  - ASRC2RMIX Input 1 Source */ 
-	{ 0x00000B00, 0x0000 },   /* R2816  - ISRC1DEC1MIX Input 1 Source */ 
-	{ 0x00000B08, 0x0000 },   /* R2824  - ISRC1DEC2MIX Input 1 Source */ 
-	{ 0x00000B20, 0x0000 },   /* R2848  - ISRC1INT1MIX Input 1 Source */ 
-	{ 0x00000B28, 0x0000 },   /* R2856  - ISRC1INT2MIX Input 1 Source */ 
-	{ 0x00000B40, 0x0000 },   /* R2880  - ISRC2DEC1MIX Input 1 Source */ 
-	{ 0x00000B48, 0x0000 },   /* R2888  - ISRC2DEC2MIX Input 1 Source */ 
-	{ 0x00000B60, 0x0000 },   /* R2912  - ISRC2INT1MIX Input 1 Source */ 
-	{ 0x00000B68, 0x0000 },   /* R2920  - ISRC2INT2MIX Input 1 Source */ 
-	{ 0x00000C00, 0xA101 },   /* R3072  - GPIO1 CTRL */ 
-	{ 0x00000C01, 0xA101 },   /* R3073  - GPIO2 CTRL */ 
-	{ 0x00000C02, 0xA101 },   /* R3074  - GPIO3 CTRL */ 
-	{ 0x00000C03, 0xA101 },   /* R3075  - GPIO4 CTRL */ 
-	{ 0x00000C04, 0xA101 },   /* R3076  - GPIO5 CTRL */ 
-	{ 0x00000C0F, 0x0400 },   /* R3087  - IRQ CTRL 1 */ 
-	{ 0x00000C10, 0x1000 },   /* R3088  - GPIO Debounce Config */ 
-	{ 0x00000C20, 0x8002 },   /* R3104  - Misc Pad Ctrl 1 */ 
+	{ 0x00000490, 0x0069 },   /* R1168  - PDM SPK1 CTRL 1 */
+	{ 0x00000491, 0x0000 },   /* R1169  - PDM SPK1 CTRL 2 */
+	{ 0x00000500, 0x000C },   /* R1280  - AIF1 BCLK Ctrl */
+	{ 0x00000501, 0x0008 },   /* R1281  - AIF1 Tx Pin Ctrl */
+	{ 0x00000502, 0x0000 },   /* R1282  - AIF1 Rx Pin Ctrl */
+	{ 0x00000503, 0x0000 },   /* R1283  - AIF1 Rate Ctrl */
+	{ 0x00000504, 0x0000 },   /* R1284  - AIF1 Format */
+	{ 0x00000505, 0x0040 },   /* R1285  - AIF1 Tx BCLK Rate */
+	{ 0x00000506, 0x0040 },   /* R1286  - AIF1 Rx BCLK Rate */
+	{ 0x00000507, 0x1818 },   /* R1287  - AIF1 Frame Ctrl 1 */
+	{ 0x00000508, 0x1818 },   /* R1288  - AIF1 Frame Ctrl 2 */
+	{ 0x00000509, 0x0000 },   /* R1289  - AIF1 Frame Ctrl 3 */
+	{ 0x0000050A, 0x0001 },   /* R1290  - AIF1 Frame Ctrl 4 */
+	{ 0x0000050B, 0x0002 },   /* R1291  - AIF1 Frame Ctrl 5 */
+	{ 0x0000050C, 0x0003 },   /* R1292  - AIF1 Frame Ctrl 6 */
+	{ 0x0000050D, 0x0004 },   /* R1293  - AIF1 Frame Ctrl 7 */
+	{ 0x0000050E, 0x0005 },   /* R1294  - AIF1 Frame Ctrl 8 */
+	{ 0x0000050F, 0x0006 },   /* R1295  - AIF1 Frame Ctrl 9 */
+	{ 0x00000510, 0x0007 },   /* R1296  - AIF1 Frame Ctrl 10 */
+	{ 0x00000511, 0x0000 },   /* R1297  - AIF1 Frame Ctrl 11 */
+	{ 0x00000512, 0x0001 },   /* R1298  - AIF1 Frame Ctrl 12 */
+	{ 0x00000513, 0x0002 },   /* R1299  - AIF1 Frame Ctrl 13 */
+	{ 0x00000514, 0x0003 },   /* R1300  - AIF1 Frame Ctrl 14 */
+	{ 0x00000515, 0x0004 },   /* R1301  - AIF1 Frame Ctrl 15 */
+	{ 0x00000516, 0x0005 },   /* R1302  - AIF1 Frame Ctrl 16 */
+	{ 0x00000517, 0x0006 },   /* R1303  - AIF1 Frame Ctrl 17 */
+	{ 0x00000518, 0x0007 },   /* R1304  - AIF1 Frame Ctrl 18 */
+	{ 0x00000519, 0x0000 },   /* R1305  - AIF1 Tx Enables */
+	{ 0x0000051A, 0x0000 },   /* R1306  - AIF1 Rx Enables */
+	{ 0x00000540, 0x000C },   /* R1344  - AIF2 BCLK Ctrl */
+	{ 0x00000541, 0x0008 },   /* R1345  - AIF2 Tx Pin Ctrl */
+	{ 0x00000542, 0x0000 },   /* R1346  - AIF2 Rx Pin Ctrl */
+	{ 0x00000543, 0x0000 },   /* R1347  - AIF2 Rate Ctrl */
+	{ 0x00000544, 0x0000 },   /* R1348  - AIF2 Format */
+	{ 0x00000545, 0x0040 },   /* R1349  - AIF2 Tx BCLK Rate */
+	{ 0x00000546, 0x0040 },   /* R1350  - AIF2 Rx BCLK Rate */
+	{ 0x00000547, 0x1818 },   /* R1351  - AIF2 Frame Ctrl 1 */
+	{ 0x00000548, 0x1818 },   /* R1352  - AIF2 Frame Ctrl 2 */
+	{ 0x00000549, 0x0000 },   /* R1353  - AIF2 Frame Ctrl 3 */
+	{ 0x0000054A, 0x0001 },   /* R1354  - AIF2 Frame Ctrl 4 */
+	{ 0x00000551, 0x0000 },   /* R1361  - AIF2 Frame Ctrl 11 */
+	{ 0x00000552, 0x0001 },   /* R1362  - AIF2 Frame Ctrl 12 */
+	{ 0x00000559, 0x0000 },   /* R1369  - AIF2 Tx Enables */
+	{ 0x0000055A, 0x0000 },   /* R1370  - AIF2 Rx Enables */
+	{ 0x00000580, 0x000C },   /* R1408  - AIF3 BCLK Ctrl */
+	{ 0x00000581, 0x0008 },   /* R1409  - AIF3 Tx Pin Ctrl */
+	{ 0x00000582, 0x0000 },   /* R1410  - AIF3 Rx Pin Ctrl */
+	{ 0x00000583, 0x0000 },   /* R1411  - AIF3 Rate Ctrl */
+	{ 0x00000584, 0x0000 },   /* R1412  - AIF3 Format */
+	{ 0x00000585, 0x0040 },   /* R1413  - AIF3 Tx BCLK Rate */
+	{ 0x00000586, 0x0040 },   /* R1414  - AIF3 Rx BCLK Rate */
+	{ 0x00000587, 0x1818 },   /* R1415  - AIF3 Frame Ctrl 1 */
+	{ 0x00000588, 0x1818 },   /* R1416  - AIF3 Frame Ctrl 2 */
+	{ 0x00000589, 0x0000 },   /* R1417  - AIF3 Frame Ctrl 3 */
+	{ 0x0000058A, 0x0001 },   /* R1418  - AIF3 Frame Ctrl 4 */
+	{ 0x00000591, 0x0000 },   /* R1425  - AIF3 Frame Ctrl 11 */
+	{ 0x00000592, 0x0001 },   /* R1426  - AIF3 Frame Ctrl 12 */
+	{ 0x00000599, 0x0000 },   /* R1433  - AIF3 Tx Enables */
+	{ 0x0000059A, 0x0000 },   /* R1434  - AIF3 Rx Enables */
+	{ 0x000005E3, 0x0004 },   /* R1507  - SLIMbus Framer Ref Gear */
+	{ 0x000005E5, 0x0000 },   /* R1509  - SLIMbus Rates 1 */
+	{ 0x000005E6, 0x0000 },   /* R1510  - SLIMbus Rates 2 */
+	{ 0x000005E7, 0x0000 },   /* R1511  - SLIMbus Rates 3 */
+	{ 0x000005E8, 0x0000 },   /* R1512  - SLIMbus Rates 4 */
+	{ 0x000005E9, 0x0000 },   /* R1513  - SLIMbus Rates 5 */
+	{ 0x000005EA, 0x0000 },   /* R1514  - SLIMbus Rates 6 */
+	{ 0x000005EB, 0x0000 },   /* R1515  - SLIMbus Rates 7 */
+	{ 0x000005EC, 0x0000 },   /* R1516  - SLIMbus Rates 8 */
+	{ 0x000005F5, 0x0000 },   /* R1525  - SLIMbus RX Channel Enable */
+	{ 0x000005F6, 0x0000 },   /* R1526  - SLIMbus TX Channel Enable */
+	{ 0x00000640, 0x0000 },   /* R1600  - PWM1MIX Input 1 Source */
+	{ 0x00000641, 0x0080 },   /* R1601  - PWM1MIX Input 1 Volume */
+	{ 0x00000642, 0x0000 },   /* R1602  - PWM1MIX Input 2 Source */
+	{ 0x00000643, 0x0080 },   /* R1603  - PWM1MIX Input 2 Volume */
+	{ 0x00000644, 0x0000 },   /* R1604  - PWM1MIX Input 3 Source */
+	{ 0x00000645, 0x0080 },   /* R1605  - PWM1MIX Input 3 Volume */
+	{ 0x00000646, 0x0000 },   /* R1606  - PWM1MIX Input 4 Source */
+	{ 0x00000647, 0x0080 },   /* R1607  - PWM1MIX Input 4 Volume */
+	{ 0x00000648, 0x0000 },   /* R1608  - PWM2MIX Input 1 Source */
+	{ 0x00000649, 0x0080 },   /* R1609  - PWM2MIX Input 1 Volume */
+	{ 0x0000064A, 0x0000 },   /* R1610  - PWM2MIX Input 2 Source */
+	{ 0x0000064B, 0x0080 },   /* R1611  - PWM2MIX Input 2 Volume */
+	{ 0x0000064C, 0x0000 },   /* R1612  - PWM2MIX Input 3 Source */
+	{ 0x0000064D, 0x0080 },   /* R1613  - PWM2MIX Input 3 Volume */
+	{ 0x0000064E, 0x0000 },   /* R1614  - PWM2MIX Input 4 Source */
+	{ 0x0000064F, 0x0080 },   /* R1615  - PWM2MIX Input 4 Volume */
+	{ 0x00000660, 0x0000 },   /* R1632  - MICMIX Input 1 Source */
+	{ 0x00000661, 0x0080 },   /* R1633  - MICMIX Input 1 Volume */
+	{ 0x00000662, 0x0000 },   /* R1634  - MICMIX Input 2 Source */
+	{ 0x00000663, 0x0080 },   /* R1635  - MICMIX Input 2 Volume */
+	{ 0x00000664, 0x0000 },   /* R1636  - MICMIX Input 3 Source */
+	{ 0x00000665, 0x0080 },   /* R1637  - MICMIX Input 3 Volume */
+	{ 0x00000666, 0x0000 },   /* R1638  - MICMIX Input 4 Source */
+	{ 0x00000667, 0x0080 },   /* R1639  - MICMIX Input 4 Volume */
+	{ 0x00000668, 0x0000 },   /* R1640  - NOISEMIX Input 1 Source */
+	{ 0x00000669, 0x0080 },   /* R1641  - NOISEMIX Input 1 Volume */
+	{ 0x0000066A, 0x0000 },   /* R1642  - NOISEMIX Input 2 Source */
+	{ 0x0000066B, 0x0080 },   /* R1643  - NOISEMIX Input 2 Volume */
+	{ 0x0000066C, 0x0000 },   /* R1644  - NOISEMIX Input 3 Source */
+	{ 0x0000066D, 0x0080 },   /* R1645  - NOISEMIX Input 3 Volume */
+	{ 0x0000066E, 0x0000 },   /* R1646  - NOISEMIX Input 4 Source */
+	{ 0x0000066F, 0x0080 },   /* R1647  - NOISEMIX Input 4 Volume */
+	{ 0x00000680, 0x0000 },   /* R1664  - OUT1LMIX Input 1 Source */
+	{ 0x00000681, 0x0080 },   /* R1665  - OUT1LMIX Input 1 Volume */
+	{ 0x00000682, 0x0000 },   /* R1666  - OUT1LMIX Input 2 Source */
+	{ 0x00000683, 0x0080 },   /* R1667  - OUT1LMIX Input 2 Volume */
+	{ 0x00000684, 0x0000 },   /* R1668  - OUT1LMIX Input 3 Source */
+	{ 0x00000685, 0x0080 },   /* R1669  - OUT1LMIX Input 3 Volume */
+	{ 0x00000686, 0x0000 },   /* R1670  - OUT1LMIX Input 4 Source */
+	{ 0x00000687, 0x0080 },   /* R1671  - OUT1LMIX Input 4 Volume */
+	{ 0x00000688, 0x0000 },   /* R1672  - OUT1RMIX Input 1 Source */
+	{ 0x00000689, 0x0080 },   /* R1673  - OUT1RMIX Input 1 Volume */
+	{ 0x0000068A, 0x0000 },   /* R1674  - OUT1RMIX Input 2 Source */
+	{ 0x0000068B, 0x0080 },   /* R1675  - OUT1RMIX Input 2 Volume */
+	{ 0x0000068C, 0x0000 },   /* R1676  - OUT1RMIX Input 3 Source */
+	{ 0x0000068D, 0x0080 },   /* R1677  - OUT1RMIX Input 3 Volume */
+	{ 0x0000068E, 0x0000 },   /* R1678  - OUT1RMIX Input 4 Source */
+	{ 0x0000068F, 0x0080 },   /* R1679  - OUT1RMIX Input 4 Volume */
+	{ 0x00000690, 0x0000 },   /* R1680  - OUT2LMIX Input 1 Source */
+	{ 0x00000691, 0x0080 },   /* R1681  - OUT2LMIX Input 1 Volume */
+	{ 0x00000692, 0x0000 },   /* R1682  - OUT2LMIX Input 2 Source */
+	{ 0x00000693, 0x0080 },   /* R1683  - OUT2LMIX Input 2 Volume */
+	{ 0x00000694, 0x0000 },   /* R1684  - OUT2LMIX Input 3 Source */
+	{ 0x00000695, 0x0080 },   /* R1685  - OUT2LMIX Input 3 Volume */
+	{ 0x00000696, 0x0000 },   /* R1686  - OUT2LMIX Input 4 Source */
+	{ 0x00000697, 0x0080 },   /* R1687  - OUT2LMIX Input 4 Volume */
+	{ 0x00000698, 0x0000 },   /* R1688  - OUT2RMIX Input 1 Source */
+	{ 0x00000699, 0x0080 },   /* R1689  - OUT2RMIX Input 1 Volume */
+	{ 0x0000069A, 0x0000 },   /* R1690  - OUT2RMIX Input 2 Source */
+	{ 0x0000069B, 0x0080 },   /* R1691  - OUT2RMIX Input 2 Volume */
+	{ 0x0000069C, 0x0000 },   /* R1692  - OUT2RMIX Input 3 Source */
+	{ 0x0000069D, 0x0080 },   /* R1693  - OUT2RMIX Input 3 Volume */
+	{ 0x0000069E, 0x0000 },   /* R1694  - OUT2RMIX Input 4 Source */
+	{ 0x0000069F, 0x0080 },   /* R1695  - OUT2RMIX Input 4 Volume */
+	{ 0x000006A0, 0x0000 },   /* R1696  - OUT3LMIX Input 1 Source */
+	{ 0x000006A1, 0x0080 },   /* R1697  - OUT3LMIX Input 1 Volume */
+	{ 0x000006A2, 0x0000 },   /* R1698  - OUT3LMIX Input 2 Source */
+	{ 0x000006A3, 0x0080 },   /* R1699  - OUT3LMIX Input 2 Volume */
+	{ 0x000006A4, 0x0000 },   /* R1700  - OUT3LMIX Input 3 Source */
+	{ 0x000006A5, 0x0080 },   /* R1701  - OUT3LMIX Input 3 Volume */
+	{ 0x000006A6, 0x0000 },   /* R1702  - OUT3LMIX Input 4 Source */
+	{ 0x000006A7, 0x0080 },   /* R1703  - OUT3LMIX Input 4 Volume */
+	{ 0x000006B0, 0x0000 },   /* R1712  - OUT4LMIX Input 1 Source */
+	{ 0x000006B1, 0x0080 },   /* R1713  - OUT4LMIX Input 1 Volume */
+	{ 0x000006B2, 0x0000 },   /* R1714  - OUT4LMIX Input 2 Source */
+	{ 0x000006B3, 0x0080 },   /* R1715  - OUT4LMIX Input 2 Volume */
+	{ 0x000006B4, 0x0000 },   /* R1716  - OUT4LMIX Input 3 Source */
+	{ 0x000006B5, 0x0080 },   /* R1717  - OUT4LMIX Input 3 Volume */
+	{ 0x000006B6, 0x0000 },   /* R1718  - OUT4LMIX Input 4 Source */
+	{ 0x000006B7, 0x0080 },   /* R1719  - OUT4LMIX Input 4 Volume */
+	{ 0x000006B8, 0x0000 },   /* R1720  - OUT4RMIX Input 1 Source */
+	{ 0x000006B9, 0x0080 },   /* R1721  - OUT4RMIX Input 1 Volume */
+	{ 0x000006BA, 0x0000 },   /* R1722  - OUT4RMIX Input 2 Source */
+	{ 0x000006BB, 0x0080 },   /* R1723  - OUT4RMIX Input 2 Volume */
+	{ 0x000006BC, 0x0000 },   /* R1724  - OUT4RMIX Input 3 Source */
+	{ 0x000006BD, 0x0080 },   /* R1725  - OUT4RMIX Input 3 Volume */
+	{ 0x000006BE, 0x0000 },   /* R1726  - OUT4RMIX Input 4 Source */
+	{ 0x000006BF, 0x0080 },   /* R1727  - OUT4RMIX Input 4 Volume */
+	{ 0x000006C0, 0x0000 },   /* R1728  - OUT5LMIX Input 1 Source */
+	{ 0x000006C1, 0x0080 },   /* R1729  - OUT5LMIX Input 1 Volume */
+	{ 0x000006C2, 0x0000 },   /* R1730  - OUT5LMIX Input 2 Source */
+	{ 0x000006C3, 0x0080 },   /* R1731  - OUT5LMIX Input 2 Volume */
+	{ 0x000006C4, 0x0000 },   /* R1732  - OUT5LMIX Input 3 Source */
+	{ 0x000006C5, 0x0080 },   /* R1733  - OUT5LMIX Input 3 Volume */
+	{ 0x000006C6, 0x0000 },   /* R1734  - OUT5LMIX Input 4 Source */
+	{ 0x000006C7, 0x0080 },   /* R1735  - OUT5LMIX Input 4 Volume */
+	{ 0x000006C8, 0x0000 },   /* R1736  - OUT5RMIX Input 1 Source */
+	{ 0x000006C9, 0x0080 },   /* R1737  - OUT5RMIX Input 1 Volume */
+	{ 0x000006CA, 0x0000 },   /* R1738  - OUT5RMIX Input 2 Source */
+	{ 0x000006CB, 0x0080 },   /* R1739  - OUT5RMIX Input 2 Volume */
+	{ 0x000006CC, 0x0000 },   /* R1740  - OUT5RMIX Input 3 Source */
+	{ 0x000006CD, 0x0080 },   /* R1741  - OUT5RMIX Input 3 Volume */
+	{ 0x000006CE, 0x0000 },   /* R1742  - OUT5RMIX Input 4 Source */
+	{ 0x000006CF, 0x0080 },   /* R1743  - OUT5RMIX Input 4 Volume */
+	{ 0x00000700, 0x0000 },   /* R1792  - AIF1TX1MIX Input 1 Source */
+	{ 0x00000701, 0x0080 },   /* R1793  - AIF1TX1MIX Input 1 Volume */
+	{ 0x00000702, 0x0000 },   /* R1794  - AIF1TX1MIX Input 2 Source */
+	{ 0x00000703, 0x0080 },   /* R1795  - AIF1TX1MIX Input 2 Volume */
+	{ 0x00000704, 0x0000 },   /* R1796  - AIF1TX1MIX Input 3 Source */
+	{ 0x00000705, 0x0080 },   /* R1797  - AIF1TX1MIX Input 3 Volume */
+	{ 0x00000706, 0x0000 },   /* R1798  - AIF1TX1MIX Input 4 Source */
+	{ 0x00000707, 0x0080 },   /* R1799  - AIF1TX1MIX Input 4 Volume */
+	{ 0x00000708, 0x0000 },   /* R1800  - AIF1TX2MIX Input 1 Source */
+	{ 0x00000709, 0x0080 },   /* R1801  - AIF1TX2MIX Input 1 Volume */
+	{ 0x0000070A, 0x0000 },   /* R1802  - AIF1TX2MIX Input 2 Source */
+	{ 0x0000070B, 0x0080 },   /* R1803  - AIF1TX2MIX Input 2 Volume */
+	{ 0x0000070C, 0x0000 },   /* R1804  - AIF1TX2MIX Input 3 Source */
+	{ 0x0000070D, 0x0080 },   /* R1805  - AIF1TX2MIX Input 3 Volume */
+	{ 0x0000070E, 0x0000 },   /* R1806  - AIF1TX2MIX Input 4 Source */
+	{ 0x0000070F, 0x0080 },   /* R1807  - AIF1TX2MIX Input 4 Volume */
+	{ 0x00000710, 0x0000 },   /* R1808  - AIF1TX3MIX Input 1 Source */
+	{ 0x00000711, 0x0080 },   /* R1809  - AIF1TX3MIX Input 1 Volume */
+	{ 0x00000712, 0x0000 },   /* R1810  - AIF1TX3MIX Input 2 Source */
+	{ 0x00000713, 0x0080 },   /* R1811  - AIF1TX3MIX Input 2 Volume */
+	{ 0x00000714, 0x0000 },   /* R1812  - AIF1TX3MIX Input 3 Source */
+	{ 0x00000715, 0x0080 },   /* R1813  - AIF1TX3MIX Input 3 Volume */
+	{ 0x00000716, 0x0000 },   /* R1814  - AIF1TX3MIX Input 4 Source */
+	{ 0x00000717, 0x0080 },   /* R1815  - AIF1TX3MIX Input 4 Volume */
+	{ 0x00000718, 0x0000 },   /* R1816  - AIF1TX4MIX Input 1 Source */
+	{ 0x00000719, 0x0080 },   /* R1817  - AIF1TX4MIX Input 1 Volume */
+	{ 0x0000071A, 0x0000 },   /* R1818  - AIF1TX4MIX Input 2 Source */
+	{ 0x0000071B, 0x0080 },   /* R1819  - AIF1TX4MIX Input 2 Volume */
+	{ 0x0000071C, 0x0000 },   /* R1820  - AIF1TX4MIX Input 3 Source */
+	{ 0x0000071D, 0x0080 },   /* R1821  - AIF1TX4MIX Input 3 Volume */
+	{ 0x0000071E, 0x0000 },   /* R1822  - AIF1TX4MIX Input 4 Source */
+	{ 0x0000071F, 0x0080 },   /* R1823  - AIF1TX4MIX Input 4 Volume */
+	{ 0x00000720, 0x0000 },   /* R1824  - AIF1TX5MIX Input 1 Source */
+	{ 0x00000721, 0x0080 },   /* R1825  - AIF1TX5MIX Input 1 Volume */
+	{ 0x00000722, 0x0000 },   /* R1826  - AIF1TX5MIX Input 2 Source */
+	{ 0x00000723, 0x0080 },   /* R1827  - AIF1TX5MIX Input 2 Volume */
+	{ 0x00000724, 0x0000 },   /* R1828  - AIF1TX5MIX Input 3 Source */
+	{ 0x00000725, 0x0080 },   /* R1829  - AIF1TX5MIX Input 3 Volume */
+	{ 0x00000726, 0x0000 },   /* R1830  - AIF1TX5MIX Input 4 Source */
+	{ 0x00000727, 0x0080 },   /* R1831  - AIF1TX5MIX Input 4 Volume */
+	{ 0x00000728, 0x0000 },   /* R1832  - AIF1TX6MIX Input 1 Source */
+	{ 0x00000729, 0x0080 },   /* R1833  - AIF1TX6MIX Input 1 Volume */
+	{ 0x0000072A, 0x0000 },   /* R1834  - AIF1TX6MIX Input 2 Source */
+	{ 0x0000072B, 0x0080 },   /* R1835  - AIF1TX6MIX Input 2 Volume */
+	{ 0x0000072C, 0x0000 },   /* R1836  - AIF1TX6MIX Input 3 Source */
+	{ 0x0000072D, 0x0080 },   /* R1837  - AIF1TX6MIX Input 3 Volume */
+	{ 0x0000072E, 0x0000 },   /* R1838  - AIF1TX6MIX Input 4 Source */
+	{ 0x0000072F, 0x0080 },   /* R1839  - AIF1TX6MIX Input 4 Volume */
+	{ 0x00000730, 0x0000 },   /* R1840  - AIF1TX7MIX Input 1 Source */
+	{ 0x00000731, 0x0080 },   /* R1841  - AIF1TX7MIX Input 1 Volume */
+	{ 0x00000732, 0x0000 },   /* R1842  - AIF1TX7MIX Input 2 Source */
+	{ 0x00000733, 0x0080 },   /* R1843  - AIF1TX7MIX Input 2 Volume */
+	{ 0x00000734, 0x0000 },   /* R1844  - AIF1TX7MIX Input 3 Source */
+	{ 0x00000735, 0x0080 },   /* R1845  - AIF1TX7MIX Input 3 Volume */
+	{ 0x00000736, 0x0000 },   /* R1846  - AIF1TX7MIX Input 4 Source */
+	{ 0x00000737, 0x0080 },   /* R1847  - AIF1TX7MIX Input 4 Volume */
+	{ 0x00000738, 0x0000 },   /* R1848  - AIF1TX8MIX Input 1 Source */
+	{ 0x00000739, 0x0080 },   /* R1849  - AIF1TX8MIX Input 1 Volume */
+	{ 0x0000073A, 0x0000 },   /* R1850  - AIF1TX8MIX Input 2 Source */
+	{ 0x0000073B, 0x0080 },   /* R1851  - AIF1TX8MIX Input 2 Volume */
+	{ 0x0000073C, 0x0000 },   /* R1852  - AIF1TX8MIX Input 3 Source */
+	{ 0x0000073D, 0x0080 },   /* R1853  - AIF1TX8MIX Input 3 Volume */
+	{ 0x0000073E, 0x0000 },   /* R1854  - AIF1TX8MIX Input 4 Source */
+	{ 0x0000073F, 0x0080 },   /* R1855  - AIF1TX8MIX Input 4 Volume */
+	{ 0x00000740, 0x0000 },   /* R1856  - AIF2TX1MIX Input 1 Source */
+	{ 0x00000741, 0x0080 },   /* R1857  - AIF2TX1MIX Input 1 Volume */
+	{ 0x00000742, 0x0000 },   /* R1858  - AIF2TX1MIX Input 2 Source */
+	{ 0x00000743, 0x0080 },   /* R1859  - AIF2TX1MIX Input 2 Volume */
+	{ 0x00000744, 0x0000 },   /* R1860  - AIF2TX1MIX Input 3 Source */
+	{ 0x00000745, 0x0080 },   /* R1861  - AIF2TX1MIX Input 3 Volume */
+	{ 0x00000746, 0x0000 },   /* R1862  - AIF2TX1MIX Input 4 Source */
+	{ 0x00000747, 0x0080 },   /* R1863  - AIF2TX1MIX Input 4 Volume */
+	{ 0x00000748, 0x0000 },   /* R1864  - AIF2TX2MIX Input 1 Source */
+	{ 0x00000749, 0x0080 },   /* R1865  - AIF2TX2MIX Input 1 Volume */
+	{ 0x0000074A, 0x0000 },   /* R1866  - AIF2TX2MIX Input 2 Source */
+	{ 0x0000074B, 0x0080 },   /* R1867  - AIF2TX2MIX Input 2 Volume */
+	{ 0x0000074C, 0x0000 },   /* R1868  - AIF2TX2MIX Input 3 Source */
+	{ 0x0000074D, 0x0080 },   /* R1869  - AIF2TX2MIX Input 3 Volume */
+	{ 0x0000074E, 0x0000 },   /* R1870  - AIF2TX2MIX Input 4 Source */
+	{ 0x0000074F, 0x0080 },   /* R1871  - AIF2TX2MIX Input 4 Volume */
+	{ 0x00000780, 0x0000 },   /* R1920  - AIF3TX1MIX Input 1 Source */
+	{ 0x00000781, 0x0080 },   /* R1921  - AIF3TX1MIX Input 1 Volume */
+	{ 0x00000782, 0x0000 },   /* R1922  - AIF3TX1MIX Input 2 Source */
+	{ 0x00000783, 0x0080 },   /* R1923  - AIF3TX1MIX Input 2 Volume */
+	{ 0x00000784, 0x0000 },   /* R1924  - AIF3TX1MIX Input 3 Source */
+	{ 0x00000785, 0x0080 },   /* R1925  - AIF3TX1MIX Input 3 Volume */
+	{ 0x00000786, 0x0000 },   /* R1926  - AIF3TX1MIX Input 4 Source */
+	{ 0x00000787, 0x0080 },   /* R1927  - AIF3TX1MIX Input 4 Volume */
+	{ 0x00000788, 0x0000 },   /* R1928  - AIF3TX2MIX Input 1 Source */
+	{ 0x00000789, 0x0080 },   /* R1929  - AIF3TX2MIX Input 1 Volume */
+	{ 0x0000078A, 0x0000 },   /* R1930  - AIF3TX2MIX Input 2 Source */
+	{ 0x0000078B, 0x0080 },   /* R1931  - AIF3TX2MIX Input 2 Volume */
+	{ 0x0000078C, 0x0000 },   /* R1932  - AIF3TX2MIX Input 3 Source */
+	{ 0x0000078D, 0x0080 },   /* R1933  - AIF3TX2MIX Input 3 Volume */
+	{ 0x0000078E, 0x0000 },   /* R1934  - AIF3TX2MIX Input 4 Source */
+	{ 0x0000078F, 0x0080 },   /* R1935  - AIF3TX2MIX Input 4 Volume */
+	{ 0x000007C0, 0x0000 },   /* R1984  - SLIMTX1MIX Input 1 Source */
+	{ 0x000007C1, 0x0080 },   /* R1985  - SLIMTX1MIX Input 1 Volume */
+	{ 0x000007C2, 0x0000 },   /* R1986  - SLIMTX1MIX Input 2 Source */
+	{ 0x000007C3, 0x0080 },   /* R1987  - SLIMTX1MIX Input 2 Volume */
+	{ 0x000007C4, 0x0000 },   /* R1988  - SLIMTX1MIX Input 3 Source */
+	{ 0x000007C5, 0x0080 },   /* R1989  - SLIMTX1MIX Input 3 Volume */
+	{ 0x000007C6, 0x0000 },   /* R1990  - SLIMTX1MIX Input 4 Source */
+	{ 0x000007C7, 0x0080 },   /* R1991  - SLIMTX1MIX Input 4 Volume */
+	{ 0x000007C8, 0x0000 },   /* R1992  - SLIMTX2MIX Input 1 Source */
+	{ 0x000007C9, 0x0080 },   /* R1993  - SLIMTX2MIX Input 1 Volume */
+	{ 0x000007CA, 0x0000 },   /* R1994  - SLIMTX2MIX Input 2 Source */
+	{ 0x000007CB, 0x0080 },   /* R1995  - SLIMTX2MIX Input 2 Volume */
+	{ 0x000007CC, 0x0000 },   /* R1996  - SLIMTX2MIX Input 3 Source */
+	{ 0x000007CD, 0x0080 },   /* R1997  - SLIMTX2MIX Input 3 Volume */
+	{ 0x000007CE, 0x0000 },   /* R1998  - SLIMTX2MIX Input 4 Source */
+	{ 0x000007CF, 0x0080 },   /* R1999  - SLIMTX2MIX Input 4 Volume */
+	{ 0x000007D0, 0x0000 },   /* R2000  - SLIMTX3MIX Input 1 Source */
+	{ 0x000007D1, 0x0080 },   /* R2001  - SLIMTX3MIX Input 1 Volume */
+	{ 0x000007D2, 0x0000 },   /* R2002  - SLIMTX3MIX Input 2 Source */
+	{ 0x000007D3, 0x0080 },   /* R2003  - SLIMTX3MIX Input 2 Volume */
+	{ 0x000007D4, 0x0000 },   /* R2004  - SLIMTX3MIX Input 3 Source */
+	{ 0x000007D5, 0x0080 },   /* R2005  - SLIMTX3MIX Input 3 Volume */
+	{ 0x000007D6, 0x0000 },   /* R2006  - SLIMTX3MIX Input 4 Source */
+	{ 0x000007D7, 0x0080 },   /* R2007  - SLIMTX3MIX Input 4 Volume */
+	{ 0x000007D8, 0x0000 },   /* R2008  - SLIMTX4MIX Input 1 Source */
+	{ 0x000007D9, 0x0080 },   /* R2009  - SLIMTX4MIX Input 1 Volume */
+	{ 0x000007DA, 0x0000 },   /* R2010  - SLIMTX4MIX Input 2 Source */
+	{ 0x000007DB, 0x0080 },   /* R2011  - SLIMTX4MIX Input 2 Volume */
+	{ 0x000007DC, 0x0000 },   /* R2012  - SLIMTX4MIX Input 3 Source */
+	{ 0x000007DD, 0x0080 },   /* R2013  - SLIMTX4MIX Input 3 Volume */
+	{ 0x000007DE, 0x0000 },   /* R2014  - SLIMTX4MIX Input 4 Source */
+	{ 0x000007DF, 0x0080 },   /* R2015  - SLIMTX4MIX Input 4 Volume */
+	{ 0x000007E0, 0x0000 },   /* R2016  - SLIMTX5MIX Input 1 Source */
+	{ 0x000007E1, 0x0080 },   /* R2017  - SLIMTX5MIX Input 1 Volume */
+	{ 0x000007E2, 0x0000 },   /* R2018  - SLIMTX5MIX Input 2 Source */
+	{ 0x000007E3, 0x0080 },   /* R2019  - SLIMTX5MIX Input 2 Volume */
+	{ 0x000007E4, 0x0000 },   /* R2020  - SLIMTX5MIX Input 3 Source */
+	{ 0x000007E5, 0x0080 },   /* R2021  - SLIMTX5MIX Input 3 Volume */
+	{ 0x000007E6, 0x0000 },   /* R2022  - SLIMTX5MIX Input 4 Source */
+	{ 0x000007E7, 0x0080 },   /* R2023  - SLIMTX5MIX Input 4 Volume */
+	{ 0x000007E8, 0x0000 },   /* R2024  - SLIMTX6MIX Input 1 Source */
+	{ 0x000007E9, 0x0080 },   /* R2025  - SLIMTX6MIX Input 1 Volume */
+	{ 0x000007EA, 0x0000 },   /* R2026  - SLIMTX6MIX Input 2 Source */
+	{ 0x000007EB, 0x0080 },   /* R2027  - SLIMTX6MIX Input 2 Volume */
+	{ 0x000007EC, 0x0000 },   /* R2028  - SLIMTX6MIX Input 3 Source */
+	{ 0x000007ED, 0x0080 },   /* R2029  - SLIMTX6MIX Input 3 Volume */
+	{ 0x000007EE, 0x0000 },   /* R2030  - SLIMTX6MIX Input 4 Source */
+	{ 0x000007EF, 0x0080 },   /* R2031  - SLIMTX6MIX Input 4 Volume */
+	{ 0x000007F0, 0x0000 },   /* R2032  - SLIMTX7MIX Input 1 Source */
+	{ 0x000007F1, 0x0080 },   /* R2033  - SLIMTX7MIX Input 1 Volume */
+	{ 0x000007F2, 0x0000 },   /* R2034  - SLIMTX7MIX Input 2 Source */
+	{ 0x000007F3, 0x0080 },   /* R2035  - SLIMTX7MIX Input 2 Volume */
+	{ 0x000007F4, 0x0000 },   /* R2036  - SLIMTX7MIX Input 3 Source */
+	{ 0x000007F5, 0x0080 },   /* R2037  - SLIMTX7MIX Input 3 Volume */
+	{ 0x000007F6, 0x0000 },   /* R2038  - SLIMTX7MIX Input 4 Source */
+	{ 0x000007F7, 0x0080 },   /* R2039  - SLIMTX7MIX Input 4 Volume */
+	{ 0x000007F8, 0x0000 },   /* R2040  - SLIMTX8MIX Input 1 Source */
+	{ 0x000007F9, 0x0080 },   /* R2041  - SLIMTX8MIX Input 1 Volume */
+	{ 0x000007FA, 0x0000 },   /* R2042  - SLIMTX8MIX Input 2 Source */
+	{ 0x000007FB, 0x0080 },   /* R2043  - SLIMTX8MIX Input 2 Volume */
+	{ 0x000007FC, 0x0000 },   /* R2044  - SLIMTX8MIX Input 3 Source */
+	{ 0x000007FD, 0x0080 },   /* R2045  - SLIMTX8MIX Input 3 Volume */
+	{ 0x000007FE, 0x0000 },   /* R2046  - SLIMTX8MIX Input 4 Source */
+	{ 0x000007FF, 0x0080 },   /* R2047  - SLIMTX8MIX Input 4 Volume */
+	{ 0x00000880, 0x0000 },   /* R2176  - EQ1MIX Input 1 Source */
+	{ 0x00000881, 0x0080 },   /* R2177  - EQ1MIX Input 1 Volume */
+	{ 0x00000882, 0x0000 },   /* R2178  - EQ1MIX Input 2 Source */
+	{ 0x00000883, 0x0080 },   /* R2179  - EQ1MIX Input 2 Volume */
+	{ 0x00000884, 0x0000 },   /* R2180  - EQ1MIX Input 3 Source */
+	{ 0x00000885, 0x0080 },   /* R2181  - EQ1MIX Input 3 Volume */
+	{ 0x00000886, 0x0000 },   /* R2182  - EQ1MIX Input 4 Source */
+	{ 0x00000887, 0x0080 },   /* R2183  - EQ1MIX Input 4 Volume */
+	{ 0x00000888, 0x0000 },   /* R2184  - EQ2MIX Input 1 Source */
+	{ 0x00000889, 0x0080 },   /* R2185  - EQ2MIX Input 1 Volume */
+	{ 0x0000088A, 0x0000 },   /* R2186  - EQ2MIX Input 2 Source */
+	{ 0x0000088B, 0x0080 },   /* R2187  - EQ2MIX Input 2 Volume */
+	{ 0x0000088C, 0x0000 },   /* R2188  - EQ2MIX Input 3 Source */
+	{ 0x0000088D, 0x0080 },   /* R2189  - EQ2MIX Input 3 Volume */
+	{ 0x0000088E, 0x0000 },   /* R2190  - EQ2MIX Input 4 Source */
+	{ 0x0000088F, 0x0080 },   /* R2191  - EQ2MIX Input 4 Volume */
+	{ 0x00000890, 0x0000 },   /* R2192  - EQ3MIX Input 1 Source */
+	{ 0x00000891, 0x0080 },   /* R2193  - EQ3MIX Input 1 Volume */
+	{ 0x00000892, 0x0000 },   /* R2194  - EQ3MIX Input 2 Source */
+	{ 0x00000893, 0x0080 },   /* R2195  - EQ3MIX Input 2 Volume */
+	{ 0x00000894, 0x0000 },   /* R2196  - EQ3MIX Input 3 Source */
+	{ 0x00000895, 0x0080 },   /* R2197  - EQ3MIX Input 3 Volume */
+	{ 0x00000896, 0x0000 },   /* R2198  - EQ3MIX Input 4 Source */
+	{ 0x00000897, 0x0080 },   /* R2199  - EQ3MIX Input 4 Volume */
+	{ 0x00000898, 0x0000 },   /* R2200  - EQ4MIX Input 1 Source */
+	{ 0x00000899, 0x0080 },   /* R2201  - EQ4MIX Input 1 Volume */
+	{ 0x0000089A, 0x0000 },   /* R2202  - EQ4MIX Input 2 Source */
+	{ 0x0000089B, 0x0080 },   /* R2203  - EQ4MIX Input 2 Volume */
+	{ 0x0000089C, 0x0000 },   /* R2204  - EQ4MIX Input 3 Source */
+	{ 0x0000089D, 0x0080 },   /* R2205  - EQ4MIX Input 3 Volume */
+	{ 0x0000089E, 0x0000 },   /* R2206  - EQ4MIX Input 4 Source */
+	{ 0x0000089F, 0x0080 },   /* R2207  - EQ4MIX Input 4 Volume */
+	{ 0x000008C0, 0x0000 },   /* R2240  - DRC1LMIX Input 1 Source */
+	{ 0x000008C1, 0x0080 },   /* R2241  - DRC1LMIX Input 1 Volume */
+	{ 0x000008C2, 0x0000 },   /* R2242  - DRC1LMIX Input 2 Source */
+	{ 0x000008C3, 0x0080 },   /* R2243  - DRC1LMIX Input 2 Volume */
+	{ 0x000008C4, 0x0000 },   /* R2244  - DRC1LMIX Input 3 Source */
+	{ 0x000008C5, 0x0080 },   /* R2245  - DRC1LMIX Input 3 Volume */
+	{ 0x000008C6, 0x0000 },   /* R2246  - DRC1LMIX Input 4 Source */
+	{ 0x000008C7, 0x0080 },   /* R2247  - DRC1LMIX Input 4 Volume */
+	{ 0x000008C8, 0x0000 },   /* R2248  - DRC1RMIX Input 1 Source */
+	{ 0x000008C9, 0x0080 },   /* R2249  - DRC1RMIX Input 1 Volume */
+	{ 0x000008CA, 0x0000 },   /* R2250  - DRC1RMIX Input 2 Source */
+	{ 0x000008CB, 0x0080 },   /* R2251  - DRC1RMIX Input 2 Volume */
+	{ 0x000008CC, 0x0000 },   /* R2252  - DRC1RMIX Input 3 Source */
+	{ 0x000008CD, 0x0080 },   /* R2253  - DRC1RMIX Input 3 Volume */
+	{ 0x000008CE, 0x0000 },   /* R2254  - DRC1RMIX Input 4 Source */
+	{ 0x000008CF, 0x0080 },   /* R2255  - DRC1RMIX Input 4 Volume */
+	{ 0x00000900, 0x0000 },   /* R2304  - HPLP1MIX Input 1 Source */
+	{ 0x00000901, 0x0080 },   /* R2305  - HPLP1MIX Input 1 Volume */
+	{ 0x00000902, 0x0000 },   /* R2306  - HPLP1MIX Input 2 Source */
+	{ 0x00000903, 0x0080 },   /* R2307  - HPLP1MIX Input 2 Volume */
+	{ 0x00000904, 0x0000 },   /* R2308  - HPLP1MIX Input 3 Source */
+	{ 0x00000905, 0x0080 },   /* R2309  - HPLP1MIX Input 3 Volume */
+	{ 0x00000906, 0x0000 },   /* R2310  - HPLP1MIX Input 4 Source */
+	{ 0x00000907, 0x0080 },   /* R2311  - HPLP1MIX Input 4 Volume */
+	{ 0x00000908, 0x0000 },   /* R2312  - HPLP2MIX Input 1 Source */
+	{ 0x00000909, 0x0080 },   /* R2313  - HPLP2MIX Input 1 Volume */
+	{ 0x0000090A, 0x0000 },   /* R2314  - HPLP2MIX Input 2 Source */
+	{ 0x0000090B, 0x0080 },   /* R2315  - HPLP2MIX Input 2 Volume */
+	{ 0x0000090C, 0x0000 },   /* R2316  - HPLP2MIX Input 3 Source */
+	{ 0x0000090D, 0x0080 },   /* R2317  - HPLP2MIX Input 3 Volume */
+	{ 0x0000090E, 0x0000 },   /* R2318  - HPLP2MIX Input 4 Source */
+	{ 0x0000090F, 0x0080 },   /* R2319  - HPLP2MIX Input 4 Volume */
+	{ 0x00000910, 0x0000 },   /* R2320  - HPLP3MIX Input 1 Source */
+	{ 0x00000911, 0x0080 },   /* R2321  - HPLP3MIX Input 1 Volume */
+	{ 0x00000912, 0x0000 },   /* R2322  - HPLP3MIX Input 2 Source */
+	{ 0x00000913, 0x0080 },   /* R2323  - HPLP3MIX Input 2 Volume */
+	{ 0x00000914, 0x0000 },   /* R2324  - HPLP3MIX Input 3 Source */
+	{ 0x00000915, 0x0080 },   /* R2325  - HPLP3MIX Input 3 Volume */
+	{ 0x00000916, 0x0000 },   /* R2326  - HPLP3MIX Input 4 Source */
+	{ 0x00000917, 0x0080 },   /* R2327  - HPLP3MIX Input 4 Volume */
+	{ 0x00000918, 0x0000 },   /* R2328  - HPLP4MIX Input 1 Source */
+	{ 0x00000919, 0x0080 },   /* R2329  - HPLP4MIX Input 1 Volume */
+	{ 0x0000091A, 0x0000 },   /* R2330  - HPLP4MIX Input 2 Source */
+	{ 0x0000091B, 0x0080 },   /* R2331  - HPLP4MIX Input 2 Volume */
+	{ 0x0000091C, 0x0000 },   /* R2332  - HPLP4MIX Input 3 Source */
+	{ 0x0000091D, 0x0080 },   /* R2333  - HPLP4MIX Input 3 Volume */
+	{ 0x0000091E, 0x0000 },   /* R2334  - HPLP4MIX Input 4 Source */
+	{ 0x0000091F, 0x0080 },   /* R2335  - HPLP4MIX Input 4 Volume */
+	{ 0x00000940, 0x0000 },   /* R2368  - DSP1LMIX Input 1 Source */
+	{ 0x00000941, 0x0080 },   /* R2369  - DSP1LMIX Input 1 Volume */
+	{ 0x00000942, 0x0000 },   /* R2370  - DSP1LMIX Input 2 Source */
+	{ 0x00000943, 0x0080 },   /* R2371  - DSP1LMIX Input 2 Volume */
+	{ 0x00000944, 0x0000 },   /* R2372  - DSP1LMIX Input 3 Source */
+	{ 0x00000945, 0x0080 },   /* R2373  - DSP1LMIX Input 3 Volume */
+	{ 0x00000946, 0x0000 },   /* R2374  - DSP1LMIX Input 4 Source */
+	{ 0x00000947, 0x0080 },   /* R2375  - DSP1LMIX Input 4 Volume */
+	{ 0x00000948, 0x0000 },   /* R2376  - DSP1RMIX Input 1 Source */
+	{ 0x00000949, 0x0080 },   /* R2377  - DSP1RMIX Input 1 Volume */
+	{ 0x0000094A, 0x0000 },   /* R2378  - DSP1RMIX Input 2 Source */
+	{ 0x0000094B, 0x0080 },   /* R2379  - DSP1RMIX Input 2 Volume */
+	{ 0x0000094C, 0x0000 },   /* R2380  - DSP1RMIX Input 3 Source */
+	{ 0x0000094D, 0x0080 },   /* R2381  - DSP1RMIX Input 3 Volume */
+	{ 0x0000094E, 0x0000 },   /* R2382  - DSP1RMIX Input 4 Source */
+	{ 0x0000094F, 0x0080 },   /* R2383  - DSP1RMIX Input 4 Volume */
+	{ 0x00000950, 0x0000 },   /* R2384  - DSP1AUX1MIX Input 1 Source */
+	{ 0x00000958, 0x0000 },   /* R2392  - DSP1AUX2MIX Input 1 Source */
+	{ 0x00000960, 0x0000 },   /* R2400  - DSP1AUX3MIX Input 1 Source */
+	{ 0x00000968, 0x0000 },   /* R2408  - DSP1AUX4MIX Input 1 Source */
+	{ 0x00000970, 0x0000 },   /* R2416  - DSP1AUX5MIX Input 1 Source */
+	{ 0x00000978, 0x0000 },   /* R2424  - DSP1AUX6MIX Input 1 Source */
+	{ 0x00000A80, 0x0000 },   /* R2688  - ASRC1LMIX Input 1 Source */
+	{ 0x00000A88, 0x0000 },   /* R2696  - ASRC1RMIX Input 1 Source */
+	{ 0x00000A90, 0x0000 },   /* R2704  - ASRC2LMIX Input 1 Source */
+	{ 0x00000A98, 0x0000 },   /* R2712  - ASRC2RMIX Input 1 Source */
+	{ 0x00000B00, 0x0000 },   /* R2816  - ISRC1DEC1MIX Input 1 Source */
+	{ 0x00000B08, 0x0000 },   /* R2824  - ISRC1DEC2MIX Input 1 Source */
+	{ 0x00000B20, 0x0000 },   /* R2848  - ISRC1INT1MIX Input 1 Source */
+	{ 0x00000B28, 0x0000 },   /* R2856  - ISRC1INT2MIX Input 1 Source */
+	{ 0x00000B40, 0x0000 },   /* R2880  - ISRC2DEC1MIX Input 1 Source */
+	{ 0x00000B48, 0x0000 },   /* R2888  - ISRC2DEC2MIX Input 1 Source */
+	{ 0x00000B60, 0x0000 },   /* R2912  - ISRC2INT1MIX Input 1 Source */
+	{ 0x00000B68, 0x0000 },   /* R2920  - ISRC2INT2MIX Input 1 Source */
+	{ 0x00000C00, 0xA101 },   /* R3072  - GPIO1 CTRL */
+	{ 0x00000C01, 0xA101 },   /* R3073  - GPIO2 CTRL */
+	{ 0x00000C02, 0xA101 },   /* R3074  - GPIO3 CTRL */
+	{ 0x00000C03, 0xA101 },   /* R3075  - GPIO4 CTRL */
+	{ 0x00000C04, 0xA101 },   /* R3076  - GPIO5 CTRL */
+	{ 0x00000C0F, 0x0400 },   /* R3087  - IRQ CTRL 1 */
+	{ 0x00000C10, 0x1000 },   /* R3088  - GPIO Debounce Config */
+	{ 0x00000C20, 0x8002 },   /* R3104  - Misc Pad Ctrl 1 */
 	{ 0x00000C21, 0x0001 },   /* R3105  - Misc Pad Ctrl 2 */
-	{ 0x00000C22, 0x0000 },   /* R3106  - Misc Pad Ctrl 3 */ 
-	{ 0x00000C23, 0x0000 },   /* R3107  - Misc Pad Ctrl 4 */ 
-	{ 0x00000C24, 0x0000 },   /* R3108  - Misc Pad Ctrl 5 */ 
-	{ 0x00000C25, 0x0000 },   /* R3109  - Misc Pad Ctrl 6 */ 
-	{ 0x00000D08, 0xFFFF },   /* R3336  - Interrupt Status 1 Mask */ 
-	{ 0x00000D09, 0xFFFF },   /* R3337  - Interrupt Status 2 Mask */ 
-	{ 0x00000D0A, 0xFFFF },   /* R3338  - Interrupt Status 3 Mask */ 
-	{ 0x00000D0B, 0xFFFF },   /* R3339  - Interrupt Status 4 Mask */ 
-	{ 0x00000D0C, 0xFEFF },   /* R3340  - Interrupt Status 5 Mask */ 
-	{ 0x00000D0F, 0x0000 },   /* R3343  - Interrupt Control */ 
-	{ 0x00000D18, 0xFFFF },   /* R3352  - IRQ2 Status 1 Mask */ 
-	{ 0x00000D19, 0xFFFF },   /* R3353  - IRQ2 Status 2 Mask */ 
-	{ 0x00000D1A, 0xFFFF },   /* R3354  - IRQ2 Status 3 Mask */ 
-	{ 0x00000D1B, 0xFFFF },   /* R3355  - IRQ2 Status 4 Mask */ 
-	{ 0x00000D1C, 0xFFFF },   /* R3356  - IRQ2 Status 5 Mask */ 
-	{ 0x00000D1F, 0x0000 },   /* R3359  - IRQ2 Control */ 
+	{ 0x00000C22, 0x0000 },   /* R3106  - Misc Pad Ctrl 3 */
+	{ 0x00000C23, 0x0000 },   /* R3107  - Misc Pad Ctrl 4 */
+	{ 0x00000C24, 0x0000 },   /* R3108  - Misc Pad Ctrl 5 */
+	{ 0x00000C25, 0x0000 },   /* R3109  - Misc Pad Ctrl 6 */
+	{ 0x00000D08, 0xFFFF },   /* R3336  - Interrupt Status 1 Mask */
+	{ 0x00000D09, 0xFFFF },   /* R3337  - Interrupt Status 2 Mask */
+	{ 0x00000D0A, 0xFFFF },   /* R3338  - Interrupt Status 3 Mask */
+	{ 0x00000D0B, 0xFFFF },   /* R3339  - Interrupt Status 4 Mask */
+	{ 0x00000D0C, 0xFEFF },   /* R3340  - Interrupt Status 5 Mask */
+	{ 0x00000D0F, 0x0000 },   /* R3343  - Interrupt Control */
+	{ 0x00000D18, 0xFFFF },   /* R3352  - IRQ2 Status 1 Mask */
+	{ 0x00000D19, 0xFFFF },   /* R3353  - IRQ2 Status 2 Mask */
+	{ 0x00000D1A, 0xFFFF },   /* R3354  - IRQ2 Status 3 Mask */
+	{ 0x00000D1B, 0xFFFF },   /* R3355  - IRQ2 Status 4 Mask */
+	{ 0x00000D1C, 0xFFFF },   /* R3356  - IRQ2 Status 5 Mask */
+	{ 0x00000D1F, 0x0000 },   /* R3359  - IRQ2 Control */
 	{ 0x00000D41, 0x0000 },   /* R3393  - ADSP2 IRQ0 */
-	{ 0x00000D53, 0xFFFF },   /* R3411  - AOD IRQ Mask IRQ1 */ 
-	{ 0x00000D54, 0xFFFF },   /* R3412  - AOD IRQ Mask IRQ2 */ 
-	{ 0x00000D56, 0x0000 },   /* R3414  - Jack detect debounce */ 
-	{ 0x00000E00, 0x0000 },   /* R3584  - FX_Ctrl1 */ 
-	{ 0x00000E10, 0x6318 },   /* R3600  - EQ1_1 */ 
-	{ 0x00000E11, 0x6300 },   /* R3601  - EQ1_2 */ 
-	{ 0x00000E12, 0x0FC8 },   /* R3602  - EQ1_3 */ 
-	{ 0x00000E13, 0x03FE },   /* R3603  - EQ1_4 */ 
-	{ 0x00000E14, 0x00E0 },   /* R3604  - EQ1_5 */ 
-	{ 0x00000E15, 0x1EC4 },   /* R3605  - EQ1_6 */ 
-	{ 0x00000E16, 0xF136 },   /* R3606  - EQ1_7 */ 
-	{ 0x00000E17, 0x0409 },   /* R3607  - EQ1_8 */ 
-	{ 0x00000E18, 0x04CC },   /* R3608  - EQ1_9 */ 
-	{ 0x00000E19, 0x1C9B },   /* R3609  - EQ1_10 */ 
-	{ 0x00000E1A, 0xF337 },   /* R3610  - EQ1_11 */ 
-	{ 0x00000E1B, 0x040B },   /* R3611  - EQ1_12 */ 
-	{ 0x00000E1C, 0x0CBB },   /* R3612  - EQ1_13 */ 
-	{ 0x00000E1D, 0x16F8 },   /* R3613  - EQ1_14 */ 
-	{ 0x00000E1E, 0xF7D9 },   /* R3614  - EQ1_15 */ 
-	{ 0x00000E1F, 0x040A },   /* R3615  - EQ1_16 */ 
-	{ 0x00000E20, 0x1F14 },   /* R3616  - EQ1_17 */ 
-	{ 0x00000E21, 0x058C },   /* R3617  - EQ1_18 */ 
-	{ 0x00000E22, 0x0563 },   /* R3618  - EQ1_19 */ 
-	{ 0x00000E23, 0x4000 },   /* R3619  - EQ1_20 */ 
-	{ 0x00000E24, 0x0B75 },   /* R3620  - EQ1_21 */ 
-	{ 0x00000E26, 0x6318 },   /* R3622  - EQ2_1 */ 
-	{ 0x00000E27, 0x6300 },   /* R3623  - EQ2_2 */ 
-	{ 0x00000E28, 0x0FC8 },   /* R3624  - EQ2_3 */ 
-	{ 0x00000E29, 0x03FE },   /* R3625  - EQ2_4 */ 
-	{ 0x00000E2A, 0x00E0 },   /* R3626  - EQ2_5 */ 
-	{ 0x00000E2B, 0x1EC4 },   /* R3627  - EQ2_6 */ 
-	{ 0x00000E2C, 0xF136 },   /* R3628  - EQ2_7 */ 
-	{ 0x00000E2D, 0x0409 },   /* R3629  - EQ2_8 */ 
-	{ 0x00000E2E, 0x04CC },   /* R3630  - EQ2_9 */ 
-	{ 0x00000E2F, 0x1C9B },   /* R3631  - EQ2_10 */ 
-	{ 0x00000E30, 0xF337 },   /* R3632  - EQ2_11 */ 
-	{ 0x00000E31, 0x040B },   /* R3633  - EQ2_12 */ 
-	{ 0x00000E32, 0x0CBB },   /* R3634  - EQ2_13 */ 
-	{ 0x00000E33, 0x16F8 },   /* R3635  - EQ2_14 */ 
-	{ 0x00000E34, 0xF7D9 },   /* R3636  - EQ2_15 */ 
-	{ 0x00000E35, 0x040A },   /* R3637  - EQ2_16 */ 
-	{ 0x00000E36, 0x1F14 },   /* R3638  - EQ2_17 */ 
-	{ 0x00000E37, 0x058C },   /* R3639  - EQ2_18 */ 
-	{ 0x00000E38, 0x0563 },   /* R3640  - EQ2_19 */ 
-	{ 0x00000E39, 0x4000 },   /* R3641  - EQ2_20 */ 
-	{ 0x00000E3A, 0x0B75 },   /* R3642  - EQ2_21 */ 
-	{ 0x00000E3C, 0x6318 },   /* R3644  - EQ3_1 */ 
-	{ 0x00000E3D, 0x6300 },   /* R3645  - EQ3_2 */ 
-	{ 0x00000E3E, 0x0FC8 },   /* R3646  - EQ3_3 */ 
-	{ 0x00000E3F, 0x03FE },   /* R3647  - EQ3_4 */ 
-	{ 0x00000E40, 0x00E0 },   /* R3648  - EQ3_5 */ 
-	{ 0x00000E41, 0x1EC4 },   /* R3649  - EQ3_6 */ 
-	{ 0x00000E42, 0xF136 },   /* R3650  - EQ3_7 */ 
-	{ 0x00000E43, 0x0409 },   /* R3651  - EQ3_8 */ 
-	{ 0x00000E44, 0x04CC },   /* R3652  - EQ3_9 */ 
-	{ 0x00000E45, 0x1C9B },   /* R3653  - EQ3_10 */ 
-	{ 0x00000E46, 0xF337 },   /* R3654  - EQ3_11 */ 
-	{ 0x00000E47, 0x040B },   /* R3655  - EQ3_12 */ 
-	{ 0x00000E48, 0x0CBB },   /* R3656  - EQ3_13 */ 
-	{ 0x00000E49, 0x16F8 },   /* R3657  - EQ3_14 */ 
-	{ 0x00000E4A, 0xF7D9 },   /* R3658  - EQ3_15 */ 
-	{ 0x00000E4B, 0x040A },   /* R3659  - EQ3_16 */ 
-	{ 0x00000E4C, 0x1F14 },   /* R3660  - EQ3_17 */ 
-	{ 0x00000E4D, 0x058C },   /* R3661  - EQ3_18 */ 
-	{ 0x00000E4E, 0x0563 },   /* R3662  - EQ3_19 */ 
-	{ 0x00000E4F, 0x4000 },   /* R3663  - EQ3_20 */ 
-	{ 0x00000E50, 0x0B75 },   /* R3664  - EQ3_21 */ 
-	{ 0x00000E52, 0x6318 },   /* R3666  - EQ4_1 */ 
-	{ 0x00000E53, 0x6300 },   /* R3667  - EQ4_2 */ 
-	{ 0x00000E54, 0x0FC8 },   /* R3668  - EQ4_3 */ 
-	{ 0x00000E55, 0x03FE },   /* R3669  - EQ4_4 */ 
-	{ 0x00000E56, 0x00E0 },   /* R3670  - EQ4_5 */ 
-	{ 0x00000E57, 0x1EC4 },   /* R3671  - EQ4_6 */ 
-	{ 0x00000E58, 0xF136 },   /* R3672  - EQ4_7 */ 
-	{ 0x00000E59, 0x0409 },   /* R3673  - EQ4_8 */ 
-	{ 0x00000E5A, 0x04CC },   /* R3674  - EQ4_9 */ 
-	{ 0x00000E5B, 0x1C9B },   /* R3675  - EQ4_10 */ 
-	{ 0x00000E5C, 0xF337 },   /* R3676  - EQ4_11 */ 
-	{ 0x00000E5D, 0x040B },   /* R3677  - EQ4_12 */ 
-	{ 0x00000E5E, 0x0CBB },   /* R3678  - EQ4_13 */ 
-	{ 0x00000E5F, 0x16F8 },   /* R3679  - EQ4_14 */ 
-	{ 0x00000E60, 0xF7D9 },   /* R3680  - EQ4_15 */ 
-	{ 0x00000E61, 0x040A },   /* R3681  - EQ4_16 */ 
-	{ 0x00000E62, 0x1F14 },   /* R3682  - EQ4_17 */ 
-	{ 0x00000E63, 0x058C },   /* R3683  - EQ4_18 */ 
-	{ 0x00000E64, 0x0563 },   /* R3684  - EQ4_19 */ 
-	{ 0x00000E65, 0x4000 },   /* R3685  - EQ4_20 */ 
-	{ 0x00000E66, 0x0B75 },   /* R3686  - EQ4_21 */ 
-	{ 0x00000E80, 0x0018 },   /* R3712  - DRC1 ctrl1 */ 
-	{ 0x00000E81, 0x0933 },   /* R3713  - DRC1 ctrl2 */ 
-	{ 0x00000E82, 0x0018 },   /* R3714  - DRC1 ctrl3 */ 
-	{ 0x00000E83, 0x0000 },   /* R3715  - DRC1 ctrl4 */ 
-	{ 0x00000E84, 0x0000 },   /* R3716  - DRC1 ctrl5 */ 
-	{ 0x00000EC0, 0x0000 },   /* R3776  - HPLPF1_1 */ 
-	{ 0x00000EC1, 0x0000 },   /* R3777  - HPLPF1_2 */ 
-	{ 0x00000EC4, 0x0000 },   /* R3780  - HPLPF2_1 */ 
-	{ 0x00000EC5, 0x0000 },   /* R3781  - HPLPF2_2 */ 
-	{ 0x00000EC8, 0x0000 },   /* R3784  - HPLPF3_1 */ 
-	{ 0x00000EC9, 0x0000 },   /* R3785  - HPLPF3_2 */ 
-	{ 0x00000ECC, 0x0000 },   /* R3788  - HPLPF4_1 */ 
-	{ 0x00000ECD, 0x0000 },   /* R3789  - HPLPF4_2 */ 
-	{ 0x00000EE0, 0x0000 },   /* R3808  - ASRC_ENABLE */ 
-	{ 0x00000EE2, 0x0000 },   /* R3810  - ASRC_RATE1 */ 
+	{ 0x00000D53, 0xFFFF },   /* R3411  - AOD IRQ Mask IRQ1 */
+	{ 0x00000D54, 0xFFFF },   /* R3412  - AOD IRQ Mask IRQ2 */
+	{ 0x00000D56, 0x0000 },   /* R3414  - Jack detect debounce */
+	{ 0x00000E00, 0x0000 },   /* R3584  - FX_Ctrl1 */
+	{ 0x00000E10, 0x6318 },   /* R3600  - EQ1_1 */
+	{ 0x00000E11, 0x6300 },   /* R3601  - EQ1_2 */
+	{ 0x00000E12, 0x0FC8 },   /* R3602  - EQ1_3 */
+	{ 0x00000E13, 0x03FE },   /* R3603  - EQ1_4 */
+	{ 0x00000E14, 0x00E0 },   /* R3604  - EQ1_5 */
+	{ 0x00000E15, 0x1EC4 },   /* R3605  - EQ1_6 */
+	{ 0x00000E16, 0xF136 },   /* R3606  - EQ1_7 */
+	{ 0x00000E17, 0x0409 },   /* R3607  - EQ1_8 */
+	{ 0x00000E18, 0x04CC },   /* R3608  - EQ1_9 */
+	{ 0x00000E19, 0x1C9B },   /* R3609  - EQ1_10 */
+	{ 0x00000E1A, 0xF337 },   /* R3610  - EQ1_11 */
+	{ 0x00000E1B, 0x040B },   /* R3611  - EQ1_12 */
+	{ 0x00000E1C, 0x0CBB },   /* R3612  - EQ1_13 */
+	{ 0x00000E1D, 0x16F8 },   /* R3613  - EQ1_14 */
+	{ 0x00000E1E, 0xF7D9 },   /* R3614  - EQ1_15 */
+	{ 0x00000E1F, 0x040A },   /* R3615  - EQ1_16 */
+	{ 0x00000E20, 0x1F14 },   /* R3616  - EQ1_17 */
+	{ 0x00000E21, 0x058C },   /* R3617  - EQ1_18 */
+	{ 0x00000E22, 0x0563 },   /* R3618  - EQ1_19 */
+	{ 0x00000E23, 0x4000 },   /* R3619  - EQ1_20 */
+	{ 0x00000E24, 0x0B75 },   /* R3620  - EQ1_21 */
+	{ 0x00000E26, 0x6318 },   /* R3622  - EQ2_1 */
+	{ 0x00000E27, 0x6300 },   /* R3623  - EQ2_2 */
+	{ 0x00000E28, 0x0FC8 },   /* R3624  - EQ2_3 */
+	{ 0x00000E29, 0x03FE },   /* R3625  - EQ2_4 */
+	{ 0x00000E2A, 0x00E0 },   /* R3626  - EQ2_5 */
+	{ 0x00000E2B, 0x1EC4 },   /* R3627  - EQ2_6 */
+	{ 0x00000E2C, 0xF136 },   /* R3628  - EQ2_7 */
+	{ 0x00000E2D, 0x0409 },   /* R3629  - EQ2_8 */
+	{ 0x00000E2E, 0x04CC },   /* R3630  - EQ2_9 */
+	{ 0x00000E2F, 0x1C9B },   /* R3631  - EQ2_10 */
+	{ 0x00000E30, 0xF337 },   /* R3632  - EQ2_11 */
+	{ 0x00000E31, 0x040B },   /* R3633  - EQ2_12 */
+	{ 0x00000E32, 0x0CBB },   /* R3634  - EQ2_13 */
+	{ 0x00000E33, 0x16F8 },   /* R3635  - EQ2_14 */
+	{ 0x00000E34, 0xF7D9 },   /* R3636  - EQ2_15 */
+	{ 0x00000E35, 0x040A },   /* R3637  - EQ2_16 */
+	{ 0x00000E36, 0x1F14 },   /* R3638  - EQ2_17 */
+	{ 0x00000E37, 0x058C },   /* R3639  - EQ2_18 */
+	{ 0x00000E38, 0x0563 },   /* R3640  - EQ2_19 */
+	{ 0x00000E39, 0x4000 },   /* R3641  - EQ2_20 */
+	{ 0x00000E3A, 0x0B75 },   /* R3642  - EQ2_21 */
+	{ 0x00000E3C, 0x6318 },   /* R3644  - EQ3_1 */
+	{ 0x00000E3D, 0x6300 },   /* R3645  - EQ3_2 */
+	{ 0x00000E3E, 0x0FC8 },   /* R3646  - EQ3_3 */
+	{ 0x00000E3F, 0x03FE },   /* R3647  - EQ3_4 */
+	{ 0x00000E40, 0x00E0 },   /* R3648  - EQ3_5 */
+	{ 0x00000E41, 0x1EC4 },   /* R3649  - EQ3_6 */
+	{ 0x00000E42, 0xF136 },   /* R3650  - EQ3_7 */
+	{ 0x00000E43, 0x0409 },   /* R3651  - EQ3_8 */
+	{ 0x00000E44, 0x04CC },   /* R3652  - EQ3_9 */
+	{ 0x00000E45, 0x1C9B },   /* R3653  - EQ3_10 */
+	{ 0x00000E46, 0xF337 },   /* R3654  - EQ3_11 */
+	{ 0x00000E47, 0x040B },   /* R3655  - EQ3_12 */
+	{ 0x00000E48, 0x0CBB },   /* R3656  - EQ3_13 */
+	{ 0x00000E49, 0x16F8 },   /* R3657  - EQ3_14 */
+	{ 0x00000E4A, 0xF7D9 },   /* R3658  - EQ3_15 */
+	{ 0x00000E4B, 0x040A },   /* R3659  - EQ3_16 */
+	{ 0x00000E4C, 0x1F14 },   /* R3660  - EQ3_17 */
+	{ 0x00000E4D, 0x058C },   /* R3661  - EQ3_18 */
+	{ 0x00000E4E, 0x0563 },   /* R3662  - EQ3_19 */
+	{ 0x00000E4F, 0x4000 },   /* R3663  - EQ3_20 */
+	{ 0x00000E50, 0x0B75 },   /* R3664  - EQ3_21 */
+	{ 0x00000E52, 0x6318 },   /* R3666  - EQ4_1 */
+	{ 0x00000E53, 0x6300 },   /* R3667  - EQ4_2 */
+	{ 0x00000E54, 0x0FC8 },   /* R3668  - EQ4_3 */
+	{ 0x00000E55, 0x03FE },   /* R3669  - EQ4_4 */
+	{ 0x00000E56, 0x00E0 },   /* R3670  - EQ4_5 */
+	{ 0x00000E57, 0x1EC4 },   /* R3671  - EQ4_6 */
+	{ 0x00000E58, 0xF136 },   /* R3672  - EQ4_7 */
+	{ 0x00000E59, 0x0409 },   /* R3673  - EQ4_8 */
+	{ 0x00000E5A, 0x04CC },   /* R3674  - EQ4_9 */
+	{ 0x00000E5B, 0x1C9B },   /* R3675  - EQ4_10 */
+	{ 0x00000E5C, 0xF337 },   /* R3676  - EQ4_11 */
+	{ 0x00000E5D, 0x040B },   /* R3677  - EQ4_12 */
+	{ 0x00000E5E, 0x0CBB },   /* R3678  - EQ4_13 */
+	{ 0x00000E5F, 0x16F8 },   /* R3679  - EQ4_14 */
+	{ 0x00000E60, 0xF7D9 },   /* R3680  - EQ4_15 */
+	{ 0x00000E61, 0x040A },   /* R3681  - EQ4_16 */
+	{ 0x00000E62, 0x1F14 },   /* R3682  - EQ4_17 */
+	{ 0x00000E63, 0x058C },   /* R3683  - EQ4_18 */
+	{ 0x00000E64, 0x0563 },   /* R3684  - EQ4_19 */
+	{ 0x00000E65, 0x4000 },   /* R3685  - EQ4_20 */
+	{ 0x00000E66, 0x0B75 },   /* R3686  - EQ4_21 */
+	{ 0x00000E80, 0x0018 },   /* R3712  - DRC1 ctrl1 */
+	{ 0x00000E81, 0x0933 },   /* R3713  - DRC1 ctrl2 */
+	{ 0x00000E82, 0x0018 },   /* R3714  - DRC1 ctrl3 */
+	{ 0x00000E83, 0x0000 },   /* R3715  - DRC1 ctrl4 */
+	{ 0x00000E84, 0x0000 },   /* R3716  - DRC1 ctrl5 */
+	{ 0x00000EC0, 0x0000 },   /* R3776  - HPLPF1_1 */
+	{ 0x00000EC1, 0x0000 },   /* R3777  - HPLPF1_2 */
+	{ 0x00000EC4, 0x0000 },   /* R3780  - HPLPF2_1 */
+	{ 0x00000EC5, 0x0000 },   /* R3781  - HPLPF2_2 */
+	{ 0x00000EC8, 0x0000 },   /* R3784  - HPLPF3_1 */
+	{ 0x00000EC9, 0x0000 },   /* R3785  - HPLPF3_2 */
+	{ 0x00000ECC, 0x0000 },   /* R3788  - HPLPF4_1 */
+	{ 0x00000ECD, 0x0000 },   /* R3789  - HPLPF4_2 */
+	{ 0x00000EE0, 0x0000 },   /* R3808  - ASRC_ENABLE */
+	{ 0x00000EE2, 0x0000 },   /* R3810  - ASRC_RATE1 */
 	{ 0x00000EE3, 0x4000 },   /* R3811  - ASRC_RATE2 */
-	{ 0x00000EF0, 0x0000 },   /* R3824  - ISRC 1 CTRL 1 */ 
-	{ 0x00000EF1, 0x0000 },   /* R3825  - ISRC 1 CTRL 2 */ 
-	{ 0x00000EF2, 0x0000 },   /* R3826  - ISRC 1 CTRL 3 */ 
-	{ 0x00000EF3, 0x0000 },   /* R3827  - ISRC 2 CTRL 1 */ 
-	{ 0x00000EF4, 0x0000 },   /* R3828  - ISRC 2 CTRL 2 */ 
-	{ 0x00000EF5, 0x0000 },   /* R3829  - ISRC 2 CTRL 3 */ 
-	{ 0x00001100, 0x0010 },   /* R4352  - DSP1 Control 1 */ 
+	{ 0x00000EF0, 0x0000 },   /* R3824  - ISRC 1 CTRL 1 */
+	{ 0x00000EF1, 0x0000 },   /* R3825  - ISRC 1 CTRL 2 */
+	{ 0x00000EF2, 0x0000 },   /* R3826  - ISRC 1 CTRL 3 */
+	{ 0x00000EF3, 0x0000 },   /* R3827  - ISRC 2 CTRL 1 */
+	{ 0x00000EF4, 0x0000 },   /* R3828  - ISRC 2 CTRL 2 */
+	{ 0x00000EF5, 0x0000 },   /* R3829  - ISRC 2 CTRL 3 */
+	{ 0x00001100, 0x0010 },   /* R4352  - DSP1 Control 1 */
 };
 
 static bool wm5102_readable_register(struct device *dev, unsigned int reg)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mfd/wm8994-core.c linux-libre-4.10-rc8-gnu/drivers/mfd/wm8994-core.c
--- linux-libre-4.9-gnu/drivers/mfd/wm8994-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mfd/wm8994-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -406,8 +406,7 @@ static int wm8994_device_init(struct wm8
 		goto err;
 	}
 
-	ret = regulator_bulk_enable(wm8994->num_supplies,
-				    wm8994->supplies);
+	ret = regulator_bulk_enable(wm8994->num_supplies, wm8994->supplies);
 	if (ret != 0) {
 		dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
 		goto err_regulator_free;
@@ -612,8 +611,7 @@ static void wm8994_device_exit(struct wm
 {
 	pm_runtime_disable(wm8994->dev);
 	wm8994_irq_exit(wm8994);
-	regulator_bulk_disable(wm8994->num_supplies,
-			       wm8994->supplies);
+	regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
 	regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
 	mfd_remove_devices(wm8994->dev);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/api.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/api.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/api.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/api.c	2017-02-12 16:03:20.000000000 -0500
@@ -9,18 +9,119 @@
 
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/anon_inodes.h>
 #include <linux/file.h>
 #include <misc/cxl.h>
-#include <linux/fs.h>
 #include <asm/pnv-pci.h>
 #include <linux/msi.h>
+#include <linux/module.h>
+#include <linux/mount.h>
 
 #include "cxl.h"
 
+/*
+ * Since we want to track memory mappings to be able to force-unmap
+ * when the AFU is no longer reachable, we need an inode. For devices
+ * opened through the cxl user API, this is not a problem, but a
+ * userland process can also get a cxl fd through the cxl_get_fd()
+ * API, which is used by the cxlflash driver.
+ *
+ * Therefore we implement our own simple pseudo-filesystem and inode
+ * allocator. We don't use the anonymous inode, as we need the
+ * meta-data associated with it (address_space) and it is shared by
+ * other drivers/processes, so it could lead to cxl unmapping VMAs
+ * from random processes.
+ */
+
+#define CXL_PSEUDO_FS_MAGIC	0x1697697f
+
+static int cxl_fs_cnt;
+static struct vfsmount *cxl_vfs_mount;
+
+static const struct dentry_operations cxl_fs_dops = {
+	.d_dname	= simple_dname,
+};
+
+static struct dentry *cxl_fs_mount(struct file_system_type *fs_type, int flags,
+				const char *dev_name, void *data)
+{
+	return mount_pseudo(fs_type, "cxl:", NULL, &cxl_fs_dops,
+			CXL_PSEUDO_FS_MAGIC);
+}
+
+static struct file_system_type cxl_fs_type = {
+	.name		= "cxl",
+	.owner		= THIS_MODULE,
+	.mount		= cxl_fs_mount,
+	.kill_sb	= kill_anon_super,
+};
+
+
+void cxl_release_mapping(struct cxl_context *ctx)
+{
+	if (ctx->kernelapi && ctx->mapping)
+		simple_release_fs(&cxl_vfs_mount, &cxl_fs_cnt);
+}
+
+static struct file *cxl_getfile(const char *name,
+				const struct file_operations *fops,
+				void *priv, int flags)
+{
+	struct qstr this;
+	struct path path;
+	struct file *file;
+	struct inode *inode = NULL;
+	int rc;
+
+	/* strongly inspired by anon_inode_getfile() */
+
+	if (fops->owner && !try_module_get(fops->owner))
+		return ERR_PTR(-ENOENT);
+
+	rc = simple_pin_fs(&cxl_fs_type, &cxl_vfs_mount, &cxl_fs_cnt);
+	if (rc < 0) {
+		pr_err("Cannot mount cxl pseudo filesystem: %d\n", rc);
+		file = ERR_PTR(rc);
+		goto err_module;
+	}
+
+	inode = alloc_anon_inode(cxl_vfs_mount->mnt_sb);
+	if (IS_ERR(inode)) {
+		file = ERR_CAST(inode);
+		goto err_fs;
+	}
+
+	file = ERR_PTR(-ENOMEM);
+	this.name = name;
+	this.len = strlen(name);
+	this.hash = 0;
+	path.dentry = d_alloc_pseudo(cxl_vfs_mount->mnt_sb, &this);
+	if (!path.dentry)
+		goto err_inode;
+
+	path.mnt = mntget(cxl_vfs_mount);
+	d_instantiate(path.dentry, inode);
+
+	file = alloc_file(&path, OPEN_FMODE(flags), fops);
+	if (IS_ERR(file))
+		goto err_dput;
+	file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
+	file->private_data = priv;
+
+	return file;
+
+err_dput:
+	path_put(&path);
+err_inode:
+	iput(inode);
+err_fs:
+	simple_release_fs(&cxl_vfs_mount, &cxl_fs_cnt);
+err_module:
+	module_put(fops->owner);
+	return file;
+}
+
 struct cxl_context *cxl_dev_context_init(struct pci_dev *dev)
 {
-	struct address_space *mapping;
 	struct cxl_afu *afu;
 	struct cxl_context  *ctx;
 	int rc;
@@ -30,38 +131,20 @@ struct cxl_context *cxl_dev_context_init
 		return ERR_CAST(afu);
 
 	ctx = cxl_context_alloc();
-	if (IS_ERR(ctx)) {
-		rc = PTR_ERR(ctx);
-		goto err_dev;
-	}
+	if (!ctx)
+		return ERR_PTR(-ENOMEM);
 
 	ctx->kernelapi = true;
 
-	/*
-	 * Make our own address space since we won't have one from the
-	 * filesystem like the user api has, and even if we do associate a file
-	 * with this context we don't want to use the global anonymous inode's
-	 * address space as that can invalidate unrelated users:
-	 */
-	mapping = kmalloc(sizeof(struct address_space), GFP_KERNEL);
-	if (!mapping) {
-		rc = -ENOMEM;
-		goto err_ctx;
-	}
-	address_space_init_once(mapping);
-
 	/* Make it a slave context.  We can promote it later? */
-	rc = cxl_context_init(ctx, afu, false, mapping);
+	rc = cxl_context_init(ctx, afu, false);
 	if (rc)
-		goto err_mapping;
+		goto err_ctx;
 
 	return ctx;
 
-err_mapping:
-	kfree(mapping);
 err_ctx:
 	kfree(ctx);
-err_dev:
 	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL_GPL(cxl_dev_context_init);
@@ -340,6 +423,11 @@ struct file *cxl_get_fd(struct cxl_conte
 {
 	struct file *file;
 	int rc, flags, fdtmp;
+	char *name = NULL;
+
+	/* only allow one per context */
+	if (ctx->mapping)
+		return ERR_PTR(-EEXIST);
 
 	flags = O_RDWR | O_CLOEXEC;
 
@@ -363,12 +451,13 @@ struct file *cxl_get_fd(struct cxl_conte
 	} else /* use default ops */
 		fops = (struct file_operations *)&afu_fops;
 
-	file = anon_inode_getfile("cxl", fops, ctx, flags);
+	name = kasprintf(GFP_KERNEL, "cxl:%d", ctx->pe);
+	file = cxl_getfile(name, fops, ctx, flags);
+	kfree(name);
 	if (IS_ERR(file))
 		goto err_fd;
 
-	file->f_mapping = ctx->mapping;
-
+	cxl_context_set_mapping(ctx, file->f_mapping);
 	*fd = fdtmp;
 	return file;
 
@@ -541,7 +630,7 @@ int _cxl_cx4_setup_msi_irqs(struct pci_d
 
 		if (remaining > 0) {
 			new_ctx = cxl_dev_context_init(pdev);
-			if (!new_ctx) {
+			if (IS_ERR(new_ctx)) {
 				pr_warn("%s: Failed to allocate enough contexts for MSIs\n", pci_name(pdev));
 				return -ENOSPC;
 			}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/context.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/context.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/context.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/context.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,8 +34,7 @@ struct cxl_context *cxl_context_alloc(vo
 /*
  * Initialises a CXL context.
  */
-int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master,
-		     struct address_space *mapping)
+int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master)
 {
 	int i;
 
@@ -44,7 +43,7 @@ int cxl_context_init(struct cxl_context
 	ctx->master = master;
 	ctx->pid = ctx->glpid = NULL; /* Set in start work ioctl */
 	mutex_init(&ctx->mapping_lock);
-	ctx->mapping = mapping;
+	ctx->mapping = NULL;
 
 	/*
 	 * Allocate the segment table before we put it in the IDR so that we
@@ -114,16 +113,23 @@ int cxl_context_init(struct cxl_context
 	return 0;
 }
 
+void cxl_context_set_mapping(struct cxl_context *ctx,
+			struct address_space *mapping)
+{
+	mutex_lock(&ctx->mapping_lock);
+	ctx->mapping = mapping;
+	mutex_unlock(&ctx->mapping_lock);
+}
+
 static int cxl_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct cxl_context *ctx = vma->vm_file->private_data;
-	unsigned long address = (unsigned long)vmf->virtual_address;
 	u64 area, offset;
 
 	offset = vmf->pgoff << PAGE_SHIFT;
 
 	pr_devel("%s: pe: %i address: 0x%lx offset: 0x%llx\n",
-			__func__, ctx->pe, address, offset);
+			__func__, ctx->pe, vmf->address, offset);
 
 	if (ctx->afu->current_mode == CXL_MODE_DEDICATED) {
 		area = ctx->afu->psn_phys;
@@ -155,7 +161,7 @@ static int cxl_mmap_fault(struct vm_area
 		return VM_FAULT_SIGBUS;
 	}
 
-	vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
+	vm_insert_pfn(vma, vmf->address, (area + offset) >> PAGE_SHIFT);
 
 	mutex_unlock(&ctx->status_mutex);
 
@@ -300,8 +306,6 @@ static void reclaim_ctx(struct rcu_head
 	if (ctx->ff_page)
 		__free_page(ctx->ff_page);
 	ctx->sstp = NULL;
-	if (ctx->kernelapi)
-		kfree(ctx->mapping);
 
 	kfree(ctx->irq_bitmap);
 
@@ -313,6 +317,8 @@ static void reclaim_ctx(struct rcu_head
 
 void cxl_context_free(struct cxl_context *ctx)
 {
+	if (ctx->kernelapi && ctx->mapping)
+		cxl_release_mapping(ctx);
 	mutex_lock(&ctx->afu->contexts_lock);
 	idr_remove(&ctx->afu->contexts_idr, ctx->pe);
 	mutex_unlock(&ctx->afu->contexts_lock);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/cxl.h linux-libre-4.10-rc8-gnu/drivers/misc/cxl/cxl.h
--- linux-libre-4.9-gnu/drivers/misc/cxl/cxl.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/cxl.h	2017-02-12 16:03:20.000000000 -0500
@@ -817,8 +817,9 @@ void cxl_dump_debug_buffer(void *addr, s
 void init_cxl_native(void);
 
 struct cxl_context *cxl_context_alloc(void);
-int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master,
-		     struct address_space *mapping);
+int cxl_context_init(struct cxl_context *ctx, struct cxl_afu *afu, bool master);
+void cxl_context_set_mapping(struct cxl_context *ctx,
+			struct address_space *mapping);
 void cxl_context_free(struct cxl_context *ctx);
 int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma);
 unsigned int cxl_map_irq(struct cxl *adapter, irq_hw_number_t hwirq,
@@ -877,6 +878,7 @@ void cxl_native_err_irq_dump_regs(struct
 void cxl_stop_trace(struct cxl *cxl);
 int cxl_pci_vphb_add(struct cxl_afu *afu);
 void cxl_pci_vphb_remove(struct cxl_afu *afu);
+void cxl_release_mapping(struct cxl_context *ctx);
 
 extern struct pci_driver cxl_pci_driver;
 extern struct platform_driver cxl_of_driver;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/debugfs.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/debugfs.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,12 +43,14 @@ static int debugfs_io_u64_set(void *data
 	out_be64((u64 __iomem *)data, val);
 	return 0;
 }
-DEFINE_SIMPLE_ATTRIBUTE(fops_io_x64, debugfs_io_u64_get, debugfs_io_u64_set, "0x%016llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_io_x64, debugfs_io_u64_get, debugfs_io_u64_set,
+			 "0x%016llx\n");
 
 static struct dentry *debugfs_create_io_x64(const char *name, umode_t mode,
 					    struct dentry *parent, u64 __iomem *value)
 {
-	return debugfs_create_file(name, mode, parent, (void __force *)value, &fops_io_x64);
+	return debugfs_create_file_unsafe(name, mode, parent,
+					  (void __force *)value, &fops_io_x64);
 }
 
 void cxl_debugfs_add_adapter_psl_regs(struct cxl *adapter, struct dentry *dir)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/file.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/file.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/file.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/file.c	2017-02-12 16:03:20.000000000 -0500
@@ -86,9 +86,12 @@ static int __afu_open(struct inode *inod
 		goto err_put_afu;
 	}
 
-	if ((rc = cxl_context_init(ctx, afu, master, inode->i_mapping)))
+	rc = cxl_context_init(ctx, afu, master);
+	if (rc)
 		goto err_put_afu;
 
+	cxl_context_set_mapping(ctx, inode->i_mapping);
+
 	pr_devel("afu_open pe: %i\n", ctx->pe);
 	file->private_data = ctx;
 	cxl_ctx_get();
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/guest.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/guest.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/guest.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/guest.c	2017-02-12 16:03:20.000000000 -0500
@@ -887,7 +887,7 @@ static void afu_handle_errstate(struct w
 	    afu_guest->previous_state == H_STATE_PERM_UNAVAILABLE)
 		return;
 
-	if (afu_guest->handle_err == true)
+	if (afu_guest->handle_err)
 		schedule_delayed_work(&afu_guest->work_err,
 				      msecs_to_jiffies(3000));
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/irq.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/irq.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@ irqreturn_t cxl_irq(int irq, struct cxl_
 		} else {
 			spin_lock(&ctx->lock);
 			ctx->afu_err = irq_info->afu_err;
-			ctx->pending_afu_err = 1;
+			ctx->pending_afu_err = true;
 			spin_unlock(&ctx->lock);
 
 			wake_up_all(&ctx->wq);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/native.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/native.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/native.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/native.c	2017-02-12 16:03:20.000000000 -0500
@@ -10,7 +10,6 @@
 #include <linux/spinlock.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/sched.h>
 #include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
@@ -54,7 +53,7 @@ static int afu_control(struct cxl_afu *a
 				     AFU_Cntl | command);
 		cpu_relax();
 		AFU_Cntl = cxl_p2n_read(afu, CXL_AFU_Cntl_An);
-	};
+	}
 
 	if (AFU_Cntl & CXL_AFU_Cntl_An_RA) {
 		/*
@@ -167,7 +166,7 @@ int cxl_psl_purge(struct cxl_afu *afu)
 			cpu_relax();
 		}
 		PSL_CNTL = cxl_p1n_read(afu, CXL_PSL_SCNTL_An);
-	};
+	}
 	end = local_clock();
 	pr_devel("PSL purged in %lld ns\n", end - start);
 
@@ -931,9 +930,18 @@ static irqreturn_t native_irq_multiplexe
 	struct cxl_afu *afu = data;
 	struct cxl_context *ctx;
 	struct cxl_irq_info irq_info;
-	int ph = cxl_p2n_read(afu, CXL_PSL_PEHandle_An) & 0xffff;
-	int ret;
+	u64 phreg = cxl_p2n_read(afu, CXL_PSL_PEHandle_An);
+	int ph, ret;
 
+	/* check if eeh kicked in while the interrupt was in flight */
+	if (unlikely(phreg == ~0ULL)) {
+		dev_warn(&afu->dev,
+			 "Ignoring slice interrupt(%d) due to fenced card",
+			 irq);
+		return IRQ_HANDLED;
+	}
+	/* Mask the pe-handle from register value */
+	ph = phreg & 0xffff;
 	if ((ret = native_get_irq_info(afu, &irq_info))) {
 		WARN(1, "Unable to get CXL IRQ Info: %i\n", ret);
 		return fail_psl_irq(afu, &irq_info);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/pci.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/pci.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -1921,7 +1921,7 @@ static pci_ers_result_t cxl_pci_slot_res
 				goto err;
 
 			ctx = cxl_dev_context_init(afu_dev);
-			if (!ctx)
+			if (IS_ERR(ctx))
 				goto err;
 
 			afu_dev->dev.archdata.cxl_ctx = ctx;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/cxl/phb.c linux-libre-4.10-rc8-gnu/drivers/misc/cxl/phb.c
--- linux-libre-4.9-gnu/drivers/misc/cxl/phb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/cxl/phb.c	2017-02-12 16:03:20.000000000 -0500
@@ -20,7 +20,7 @@ bool _cxl_pci_associate_default_context(
 	 * in the virtual phb, we'll need a default context to attach them to.
 	 */
 	ctx = cxl_dev_context_init(dev);
-	if (!ctx)
+	if (IS_ERR(ctx))
 		return false;
 	dev->dev.archdata.cxl_ctx = ctx;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/genwqe/card_base.h linux-libre-4.10-rc8-gnu/drivers/misc/genwqe/card_base.h
--- linux-libre-4.9-gnu/drivers/misc/genwqe/card_base.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/genwqe/card_base.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,6 @@
 #include "genwqe_driver.h"
 
 #define GENWQE_MSI_IRQS			4  /* Just one supported, no MSIx */
-#define GENWQE_FLAG_MSI_ENABLED		(1 << 0)
 
 #define GENWQE_MAX_VFS			15 /* maximum 15 VFs are possible */
 #define GENWQE_MAX_FUNCS		16 /* 1 PF and 15 VFs */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/genwqe/card_utils.c linux-libre-4.10-rc8-gnu/drivers/misc/genwqe/card_utils.c
--- linux-libre-4.9-gnu/drivers/misc/genwqe/card_utils.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/genwqe/card_utils.c	2017-02-12 16:03:20.000000000 -0500
@@ -740,13 +740,10 @@ int genwqe_read_softreset(struct genwqe_
 int genwqe_set_interrupt_capability(struct genwqe_dev *cd, int count)
 {
 	int rc;
-	struct pci_dev *pci_dev = cd->pci_dev;
 
-	rc = pci_enable_msi_range(pci_dev, 1, count);
+	rc = pci_alloc_irq_vectors(cd->pci_dev, 1, count, PCI_IRQ_MSI);
 	if (rc < 0)
 		return rc;
-
-	cd->flags |= GENWQE_FLAG_MSI_ENABLED;
 	return 0;
 }
 
@@ -756,12 +753,7 @@ int genwqe_set_interrupt_capability(stru
  */
 void genwqe_reset_interrupt_capability(struct genwqe_dev *cd)
 {
-	struct pci_dev *pci_dev = cd->pci_dev;
-
-	if (cd->flags & GENWQE_FLAG_MSI_ENABLED) {
-		pci_disable_msi(pci_dev);
-		cd->flags &= ~GENWQE_FLAG_MSI_ENABLED;
-	}
+	pci_free_irq_vectors(cd->pci_dev);
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/ibmasm/ibmasmfs.c linux-libre-4.10-rc8-gnu/drivers/misc/ibmasm/ibmasmfs.c
--- linux-libre-4.9-gnu/drivers/misc/ibmasm/ibmasmfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/ibmasm/ibmasmfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -76,7 +76,7 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include "ibmasm.h"
 #include "remote.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/ibmasm/module.c linux-libre-4.10-rc8-gnu/drivers/misc/ibmasm/module.c
--- linux-libre-4.9-gnu/drivers/misc/ibmasm/module.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/ibmasm/module.c	2017-02-12 16:03:20.000000000 -0500
@@ -170,7 +170,7 @@ static void ibmasm_remove_one(struct pci
 	ibmasm_unregister_uart(sp);
 	dbg("Sending OS down message\n");
 	if (ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN))
-		err("failed to get repsonse to 'Send OS State' command\n");
+		err("failed to get response to 'Send OS State' command\n");
 	dbg("Disabling heartbeats\n");
 	ibmasm_heartbeat_exit(sp);
 	dbg("Disabling interrupts\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/lkdtm_bugs.c linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm_bugs.c
--- linux-libre-4.9-gnu/drivers/misc/lkdtm_bugs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm_bugs.c	2017-02-12 16:03:20.000000000 -0500
@@ -5,8 +5,13 @@
  * test source files.
  */
 #include "lkdtm.h"
+#include <linux/list.h>
 #include <linux/sched.h>
 
+struct lkdtm_list {
+	struct list_head node;
+};
+
 /*
  * Make sure our attempts to over run the kernel stack doesn't trigger
  * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -80,7 +85,8 @@ noinline void lkdtm_CORRUPT_STACK(void)
 	/* Use default char array length that triggers stack protection. */
 	char data[8];
 
-	memset((void *)data, 0, 64);
+	memset((void *)data, 'a', 64);
+	pr_info("Corrupted stack with '%16s'...\n", data);
 }
 
 void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void)
@@ -146,3 +152,66 @@ void lkdtm_ATOMIC_OVERFLOW(void)
 	pr_info("attempting bad atomic overflow\n");
 	atomic_inc(&over);
 }
+
+void lkdtm_CORRUPT_LIST_ADD(void)
+{
+	/*
+	 * Initially, an empty list via LIST_HEAD:
+	 *	test_head.next = &test_head
+	 *	test_head.prev = &test_head
+	 */
+	LIST_HEAD(test_head);
+	struct lkdtm_list good, bad;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	pr_info("attempting good list addition\n");
+
+	/*
+	 * Adding to the list performs these actions:
+	 *	test_head.next->prev = &good.node
+	 *	good.node.next = test_head.next
+	 *	good.node.prev = test_head
+	 *	test_head.next = good.node
+	 */
+	list_add(&good.node, &test_head);
+
+	pr_info("attempting corrupted list addition\n");
+	/*
+	 * In simulating this "write what where" primitive, the "what" is
+	 * the address of &bad.node, and the "where" is the address held
+	 * by "redirection".
+	 */
+	test_head.next = redirection;
+	list_add(&bad.node, &test_head);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_add() corruption not detected!\n");
+}
+
+void lkdtm_CORRUPT_LIST_DEL(void)
+{
+	LIST_HEAD(test_head);
+	struct lkdtm_list item;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	list_add(&item.node, &test_head);
+
+	pr_info("attempting good list removal\n");
+	list_del(&item.node);
+
+	pr_info("attempting corrupted list removal\n");
+	list_add(&item.node, &test_head);
+
+	/* As with the list_add() test above, this corrupts "next". */
+	item.node.next = redirection;
+	list_del(&item.node);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_del() corruption not detected!\n");
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/lkdtm_core.c linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm_core.c
--- linux-libre-4.9-gnu/drivers/misc/lkdtm_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -197,6 +197,8 @@ struct crashtype crashtypes[] = {
 	CRASHTYPE(EXCEPTION),
 	CRASHTYPE(LOOP),
 	CRASHTYPE(OVERFLOW),
+	CRASHTYPE(CORRUPT_LIST_ADD),
+	CRASHTYPE(CORRUPT_LIST_DEL),
 	CRASHTYPE(CORRUPT_STACK),
 	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
 	CRASHTYPE(OVERWRITE_ALLOCATION),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/lkdtm.h linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm.h
--- linux-libre-4.9-gnu/drivers/misc/lkdtm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm.h	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,8 @@ void lkdtm_SPINLOCKUP(void);
 void lkdtm_HUNG_TASK(void);
 void lkdtm_ATOMIC_UNDERFLOW(void);
 void lkdtm_ATOMIC_OVERFLOW(void);
+void lkdtm_CORRUPT_LIST_ADD(void);
+void lkdtm_CORRUPT_LIST_DEL(void);
 
 /* lkdtm_heap.c */
 void lkdtm_OVERWRITE_ALLOCATION(void);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/lkdtm_perms.c linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm_perms.c
--- linux-libre-4.9-gnu/drivers/misc/lkdtm_perms.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/lkdtm_perms.c	2017-02-12 16:03:20.000000000 -0500
@@ -60,15 +60,18 @@ static noinline void execute_location(vo
 
 static void execute_user_location(void *dst)
 {
+	int copied;
+
 	/* Intentionally crossing kernel/user memory boundary. */
 	void (*func)(void) = dst;
 
 	pr_info("attempting ok execution at %p\n", do_nothing);
 	do_nothing();
 
-	if (copy_to_user((void __user *)dst, do_nothing, EXEC_SIZE))
+	copied = access_process_vm(current, (unsigned long)dst, do_nothing,
+				   EXEC_SIZE, FOLL_WRITE);
+	if (copied < EXEC_SIZE)
 		return;
-	flush_icache_range((unsigned long)dst, (unsigned long)dst + EXEC_SIZE);
 	pr_info("attempting bad execution at %p\n", func);
 	func();
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/amthif.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/amthif.c
--- linux-libre-4.9-gnu/drivers/misc/mei/amthif.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/amthif.c	2017-02-12 16:03:20.000000000 -0500
@@ -144,7 +144,7 @@ int mei_amthif_run_next_cmd(struct mei_d
 	dev->iamthif_state = MEI_IAMTHIF_WRITING;
 	cl->fp = cb->fp;
 
-	ret = mei_cl_write(cl, cb, false);
+	ret = mei_cl_write(cl, cb);
 	if (ret < 0)
 		return ret;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/bus.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/bus.c
--- linux-libre-4.9-gnu/drivers/misc/mei/bus.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/bus.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,12 +36,12 @@
  * @cl: host client
  * @buf: buffer to send
  * @length: buffer length
- * @blocking: wait for write completion
+ * @mode: sending mode
  *
  * Return: written size bytes or < 0 on error
  */
 ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
-			bool blocking)
+		      unsigned int mode)
 {
 	struct mei_device *bus;
 	struct mei_cl_cb *cb;
@@ -80,9 +80,11 @@ ssize_t __mei_cl_send(struct mei_cl *cl,
 		goto out;
 	}
 
+	cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
+	cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
 	memcpy(cb->buf.data, buf, length);
 
-	rets = mei_cl_write(cl, cb, blocking);
+	rets = mei_cl_write(cl, cb);
 
 out:
 	mutex_unlock(&bus->device_lock);
@@ -96,15 +98,18 @@ out:
  * @cl: host client
  * @buf: buffer to receive
  * @length: buffer length
+ * @mode: io mode
  *
  * Return: read size in bytes of < 0 on error
  */
-ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+		      unsigned int mode)
 {
 	struct mei_device *bus;
 	struct mei_cl_cb *cb;
 	size_t r_length;
 	ssize_t rets;
+	bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
 
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
@@ -125,6 +130,11 @@ ssize_t __mei_cl_recv(struct mei_cl *cl,
 	if (rets && rets != -EBUSY)
 		goto out;
 
+	if (nonblock) {
+		rets = -EAGAIN;
+		goto out;
+	}
+
 	/* wait on event only if there is no other waiter */
 	/* synchronized under device mutex */
 	if (!waitqueue_active(&cl->rx_wait)) {
@@ -185,14 +195,30 @@ ssize_t mei_cldev_send(struct mei_cl_dev
 {
 	struct mei_cl *cl = cldev->cl;
 
-	if (cl == NULL)
-		return -ENODEV;
-
-	return __mei_cl_send(cl, buf, length, 1);
+	return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
 }
 EXPORT_SYMBOL_GPL(mei_cldev_send);
 
 /**
+ * mei_cldev_recv_nonblock - non block client receive (read)
+ *
+ * @cldev: me client device
+ * @buf: buffer to receive
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ *         -EAGAIN if function will block.
+ */
+ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
+				size_t length)
+{
+	struct mei_cl *cl = cldev->cl;
+
+	return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
+
+/**
  * mei_cldev_recv - client receive (read)
  *
  * @cldev: me client device
@@ -205,39 +231,45 @@ ssize_t mei_cldev_recv(struct mei_cl_dev
 {
 	struct mei_cl *cl = cldev->cl;
 
-	if (cl == NULL)
-		return -ENODEV;
-
-	return __mei_cl_recv(cl, buf, length);
+	return __mei_cl_recv(cl, buf, length, 0);
 }
 EXPORT_SYMBOL_GPL(mei_cldev_recv);
 
 /**
- * mei_cl_bus_event_work  - dispatch rx event for a bus device
- *    and schedule new work
+ * mei_cl_bus_rx_work - dispatch rx event for a bus device
  *
  * @work: work
  */
-static void mei_cl_bus_event_work(struct work_struct *work)
+static void mei_cl_bus_rx_work(struct work_struct *work)
 {
 	struct mei_cl_device *cldev;
 	struct mei_device *bus;
 
-	cldev = container_of(work, struct mei_cl_device, event_work);
+	cldev = container_of(work, struct mei_cl_device, rx_work);
 
 	bus = cldev->bus;
 
-	if (cldev->event_cb)
-		cldev->event_cb(cldev, cldev->events, cldev->event_context);
+	if (cldev->rx_cb)
+		cldev->rx_cb(cldev);
 
-	cldev->events = 0;
+	mutex_lock(&bus->device_lock);
+	mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+	mutex_unlock(&bus->device_lock);
+}
 
-	/* Prepare for the next read */
-	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
-		mutex_lock(&bus->device_lock);
-		mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
-		mutex_unlock(&bus->device_lock);
-	}
+/**
+ * mei_cl_bus_notif_work - dispatch FW notif event for a bus device
+ *
+ * @work: work
+ */
+static void mei_cl_bus_notif_work(struct work_struct *work)
+{
+	struct mei_cl_device *cldev;
+
+	cldev = container_of(work, struct mei_cl_device, notif_work);
+
+	if (cldev->notif_cb)
+		cldev->notif_cb(cldev);
 }
 
 /**
@@ -252,18 +284,13 @@ bool mei_cl_bus_notify_event(struct mei_
 {
 	struct mei_cl_device *cldev = cl->cldev;
 
-	if (!cldev || !cldev->event_cb)
-		return false;
-
-	if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)))
+	if (!cldev || !cldev->notif_cb)
 		return false;
 
 	if (!cl->notify_ev)
 		return false;
 
-	set_bit(MEI_CL_EVENT_NOTIF, &cldev->events);
-
-	schedule_work(&cldev->event_work);
+	schedule_work(&cldev->notif_work);
 
 	cl->notify_ev = false;
 
@@ -271,7 +298,7 @@ bool mei_cl_bus_notify_event(struct mei_
 }
 
 /**
- * mei_cl_bus_rx_event  - schedule rx event
+ * mei_cl_bus_rx_event - schedule rx event
  *
  * @cl: host client
  *
@@ -282,66 +309,81 @@ bool mei_cl_bus_rx_event(struct mei_cl *
 {
 	struct mei_cl_device *cldev = cl->cldev;
 
-	if (!cldev || !cldev->event_cb)
-		return false;
-
-	if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX)))
+	if (!cldev || !cldev->rx_cb)
 		return false;
 
-	set_bit(MEI_CL_EVENT_RX, &cldev->events);
-
-	schedule_work(&cldev->event_work);
+	schedule_work(&cldev->rx_work);
 
 	return true;
 }
 
 /**
- * mei_cldev_register_event_cb - register event callback
+ * mei_cldev_register_rx_cb - register Rx event callback
  *
  * @cldev: me client devices
- * @event_cb: callback function
- * @events_mask: requested events bitmask
- * @context: driver context data
+ * @rx_cb: callback function
  *
  * Return: 0 on success
  *         -EALREADY if an callback is already registered
  *         <0 on other errors
  */
-int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
-				unsigned long events_mask,
-				mei_cldev_event_cb_t event_cb, void *context)
+int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
 {
 	struct mei_device *bus = cldev->bus;
 	int ret;
 
-	if (cldev->event_cb)
+	if (!rx_cb)
+		return -EINVAL;
+	if (cldev->rx_cb)
 		return -EALREADY;
 
-	cldev->events = 0;
-	cldev->events_mask = events_mask;
-	cldev->event_cb = event_cb;
-	cldev->event_context = context;
-	INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);
+	cldev->rx_cb = rx_cb;
+	INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
 
-	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
-		mutex_lock(&bus->device_lock);
-		ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
-		mutex_unlock(&bus->device_lock);
-		if (ret && ret != -EBUSY)
-			return ret;
-	}
+	mutex_lock(&bus->device_lock);
+	ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+	mutex_unlock(&bus->device_lock);
+	if (ret && ret != -EBUSY)
+		return ret;
 
-	if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
-		mutex_lock(&bus->device_lock);
-		ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
-		mutex_unlock(&bus->device_lock);
-		if (ret)
-			return ret;
-	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mei_cldev_register_rx_cb);
+
+/**
+ * mei_cldev_register_notif_cb - register FW notification event callback
+ *
+ * @cldev: me client devices
+ * @notif_cb: callback function
+ *
+ * Return: 0 on success
+ *         -EALREADY if an callback is already registered
+ *         <0 on other errors
+ */
+int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
+				mei_cldev_cb_t notif_cb)
+{
+	struct mei_device *bus = cldev->bus;
+	int ret;
+
+	if (!notif_cb)
+		return -EINVAL;
+
+	if (cldev->notif_cb)
+		return -EALREADY;
+
+	cldev->notif_cb = notif_cb;
+	INIT_WORK(&cldev->notif_work, mei_cl_bus_notif_work);
+
+	mutex_lock(&bus->device_lock);
+	ret = mei_cl_notify_request(cldev->cl, NULL, 1);
+	mutex_unlock(&bus->device_lock);
+	if (ret)
+		return ret;
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(mei_cldev_register_event_cb);
+EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
 
 /**
  * mei_cldev_get_drvdata - driver data getter
@@ -403,12 +445,12 @@ EXPORT_SYMBOL_GPL(mei_cldev_ver);
  */
 bool mei_cldev_enabled(struct mei_cl_device *cldev)
 {
-	return cldev->cl && mei_cl_is_connected(cldev->cl);
+	return mei_cl_is_connected(cldev->cl);
 }
 EXPORT_SYMBOL_GPL(mei_cldev_enabled);
 
 /**
- * mei_cldev_enable_device - enable me client device
+ * mei_cldev_enable - enable me client device
  *     create connection with me client
  *
  * @cldev: me client device
@@ -423,14 +465,13 @@ int mei_cldev_enable(struct mei_cl_devic
 
 	cl = cldev->cl;
 
-	if (!cl) {
+	if (cl->state == MEI_FILE_UNINITIALIZED) {
 		mutex_lock(&bus->device_lock);
-		cl = mei_cl_alloc_linked(bus);
+		ret = mei_cl_link(cl);
 		mutex_unlock(&bus->device_lock);
-		if (IS_ERR(cl))
-			return PTR_ERR(cl);
+		if (ret)
+			return ret;
 		/* update pointers */
-		cldev->cl = cl;
 		cl->cldev = cldev;
 	}
 
@@ -471,19 +512,17 @@ int mei_cldev_disable(struct mei_cl_devi
 	struct mei_cl *cl;
 	int err;
 
-	if (!cldev || !cldev->cl)
+	if (!cldev)
 		return -ENODEV;
 
 	cl = cldev->cl;
 
 	bus = cldev->bus;
 
-	cldev->event_cb = NULL;
-
 	mutex_lock(&bus->device_lock);
 
 	if (!mei_cl_is_connected(cl)) {
-		dev_err(bus->dev, "Already disconnected");
+		dev_dbg(bus->dev, "Already disconnected");
 		err = 0;
 		goto out;
 	}
@@ -497,9 +536,6 @@ out:
 	mei_cl_flush_queues(cl, NULL);
 	mei_cl_unlink(cl);
 
-	kfree(cl);
-	cldev->cl = NULL;
-
 	mutex_unlock(&bus->device_lock);
 	return err;
 }
@@ -629,9 +665,13 @@ static int mei_cl_device_remove(struct d
 	if (!cldev || !dev->driver)
 		return 0;
 
-	if (cldev->event_cb) {
-		cldev->event_cb = NULL;
-		cancel_work_sync(&cldev->event_work);
+	if (cldev->rx_cb) {
+		cancel_work_sync(&cldev->rx_work);
+		cldev->rx_cb = NULL;
+	}
+	if (cldev->notif_cb) {
+		cancel_work_sync(&cldev->notif_work);
+		cldev->notif_cb = NULL;
 	}
 
 	cldrv = to_mei_cl_driver(dev->driver);
@@ -754,6 +794,7 @@ static void mei_cl_bus_dev_release(struc
 
 	mei_me_cl_put(cldev->me_cl);
 	mei_dev_bus_put(cldev->bus);
+	kfree(cldev->cl);
 	kfree(cldev);
 }
 
@@ -786,17 +827,25 @@ static struct mei_cl_device *mei_cl_bus_
 						  struct mei_me_client *me_cl)
 {
 	struct mei_cl_device *cldev;
+	struct mei_cl *cl;
 
 	cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
 	if (!cldev)
 		return NULL;
 
+	cl = mei_cl_allocate(bus);
+	if (!cl) {
+		kfree(cldev);
+		return NULL;
+	}
+
 	device_initialize(&cldev->dev);
 	cldev->dev.parent = bus->dev;
 	cldev->dev.bus    = &mei_cl_bus_type;
 	cldev->dev.type   = &mei_cl_device_type;
 	cldev->bus        = mei_dev_bus_get(bus);
 	cldev->me_cl      = mei_me_cl_get(me_cl);
+	cldev->cl         = cl;
 	mei_cl_bus_set_name(cldev);
 	cldev->is_added   = 0;
 	INIT_LIST_HEAD(&cldev->bus_list);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/bus-fixup.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/bus-fixup.c
--- linux-libre-4.9-gnu/drivers/misc/mei/bus-fixup.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/bus-fixup.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,6 +38,9 @@ static const uuid_le mei_nfc_info_guid =
 #define MEI_UUID_WD UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, \
 			    0x89, 0x9D, 0xA9, 0x15, 0x14, 0xCB, 0x32, 0xAB)
 
+#define MEI_UUID_MKHIF_FIX UUID_LE(0x55213584, 0x9a29, 0x4916, \
+			0xba, 0xdf, 0xf, 0xb7, 0xed, 0x68, 0x2a, 0xeb)
+
 #define MEI_UUID_ANY NULL_UUID_LE
 
 /**
@@ -69,6 +72,100 @@ static void blacklist(struct mei_cl_devi
 	cldev->do_match = 0;
 }
 
+#define OSTYPE_LINUX    2
+struct mei_os_ver {
+	__le16 build;
+	__le16 reserved1;
+	u8  os_type;
+	u8  major;
+	u8  minor;
+	u8  reserved2;
+} __packed;
+
+#define MKHI_FEATURE_PTT 0x10
+
+struct mkhi_rule_id {
+	__le16 rule_type;
+	u8 feature_id;
+	u8 reserved;
+} __packed;
+
+struct mkhi_fwcaps {
+	struct mkhi_rule_id id;
+	u8 len;
+	u8 data[0];
+} __packed;
+
+#define MKHI_FWCAPS_GROUP_ID 0x3
+#define MKHI_FWCAPS_SET_OS_VER_APP_RULE_CMD 6
+struct mkhi_msg_hdr {
+	u8  group_id;
+	u8  command;
+	u8  reserved;
+	u8  result;
+} __packed;
+
+struct mkhi_msg {
+	struct mkhi_msg_hdr hdr;
+	u8 data[0];
+} __packed;
+
+static int mei_osver(struct mei_cl_device *cldev)
+{
+	int ret;
+	const size_t size = sizeof(struct mkhi_msg_hdr) +
+			    sizeof(struct mkhi_fwcaps) +
+			    sizeof(struct mei_os_ver);
+	size_t length = 8;
+	char buf[size];
+	struct mkhi_msg *req;
+	struct mkhi_fwcaps *fwcaps;
+	struct mei_os_ver *os_ver;
+	unsigned int mode = MEI_CL_IO_TX_BLOCKING | MEI_CL_IO_TX_INTERNAL;
+
+	memset(buf, 0, size);
+
+	req = (struct mkhi_msg *)buf;
+	req->hdr.group_id = MKHI_FWCAPS_GROUP_ID;
+	req->hdr.command = MKHI_FWCAPS_SET_OS_VER_APP_RULE_CMD;
+
+	fwcaps = (struct mkhi_fwcaps *)req->data;
+
+	fwcaps->id.rule_type = 0x0;
+	fwcaps->id.feature_id = MKHI_FEATURE_PTT;
+	fwcaps->len = sizeof(*os_ver);
+	os_ver = (struct mei_os_ver *)fwcaps->data;
+	os_ver->os_type = OSTYPE_LINUX;
+
+	ret = __mei_cl_send(cldev->cl, buf, size, mode);
+	if (ret < 0)
+		return ret;
+
+	ret = __mei_cl_recv(cldev->cl, buf, length, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void mei_mkhi_fix(struct mei_cl_device *cldev)
+{
+	int ret;
+
+	if (!cldev->bus->hbm_f_os_supported)
+		return;
+
+	ret = mei_cldev_enable(cldev);
+	if (ret)
+		return;
+
+	ret = mei_osver(cldev);
+	if (ret)
+		dev_err(&cldev->dev, "OS version command failed %d\n", ret);
+
+	mei_cldev_disable(cldev);
+}
+
 /**
  * mei_wd - wd client on the bus, change protocol version
  *   as the API has changed.
@@ -162,7 +259,8 @@ static int mei_nfc_if_version(struct mei
 
 	WARN_ON(mutex_is_locked(&bus->device_lock));
 
-	ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1);
+	ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd),
+			    MEI_CL_IO_TX_BLOCKING);
 	if (ret < 0) {
 		dev_err(bus->dev, "Could not send IF version cmd\n");
 		return ret;
@@ -177,7 +275,7 @@ static int mei_nfc_if_version(struct mei
 		return -ENOMEM;
 
 	ret = 0;
-	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
+	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0);
 	if (bytes_recv < if_version_length) {
 		dev_err(bus->dev, "Could not read IF version\n");
 		ret = -EIO;
@@ -309,6 +407,7 @@ static struct mei_fixup {
 	MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist),
 	MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc),
 	MEI_FIXUP(MEI_UUID_WD, mei_wd),
+	MEI_FIXUP(MEI_UUID_MKHIF_FIX, mei_mkhi_fix),
 };
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/client.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/client.c
--- linux-libre-4.9-gnu/drivers/misc/mei/client.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/client.c	2017-02-12 16:03:20.000000000 -0500
@@ -425,7 +425,7 @@ static inline void mei_io_list_free(stru
  *
  * @cl: host client
  * @length: size of the buffer
- * @type: operation type
+ * @fop_type: operation type
  * @fp: associated file pointer (might be NULL)
  *
  * Return: cb on success and NULL on failure
@@ -459,7 +459,7 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct
  *
  * @cl: host client
  * @length: size of the buffer
- * @type: operation type
+ * @fop_type: operation type
  * @fp: associated file pointer (might be NULL)
  *
  * Return: cb on success and NULL on failure
@@ -571,7 +571,7 @@ void mei_cl_init(struct mei_cl *cl, stru
 	INIT_LIST_HEAD(&cl->rd_pending);
 	INIT_LIST_HEAD(&cl->link);
 	cl->writing_state = MEI_IDLE;
-	cl->state = MEI_FILE_INITIALIZING;
+	cl->state = MEI_FILE_UNINITIALIZED;
 	cl->dev = dev;
 }
 
@@ -672,7 +672,12 @@ int mei_cl_unlink(struct mei_cl *cl)
 
 	list_del_init(&cl->link);
 
-	cl->state = MEI_FILE_INITIALIZING;
+	cl->state = MEI_FILE_UNINITIALIZED;
+	cl->writing_state = MEI_IDLE;
+
+	WARN_ON(!list_empty(&cl->rd_completed) ||
+		!list_empty(&cl->rd_pending) ||
+		!list_empty(&cl->link));
 
 	return 0;
 }
@@ -686,7 +691,7 @@ void mei_host_client_init(struct mei_dev
 
 	pm_runtime_mark_last_busy(dev->dev);
 	dev_dbg(dev->dev, "rpm: autosuspend\n");
-	pm_runtime_autosuspend(dev->dev);
+	pm_request_autosuspend(dev->dev);
 }
 
 /**
@@ -756,7 +761,7 @@ void mei_cl_set_disconnected(struct mei_
 	struct mei_device *dev = cl->dev;
 
 	if (cl->state == MEI_FILE_DISCONNECTED ||
-	    cl->state == MEI_FILE_INITIALIZING)
+	    cl->state <= MEI_FILE_INITIALIZING)
 		return;
 
 	cl->state = MEI_FILE_DISCONNECTED;
@@ -1536,7 +1541,7 @@ int mei_cl_irq_write(struct mei_cl *cl,
 
 	rets = first_chunk ? mei_cl_tx_flow_ctrl_creds(cl) : 1;
 	if (rets < 0)
-		return rets;
+		goto err;
 
 	if (rets == 0) {
 		cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
@@ -1570,11 +1575,8 @@ int mei_cl_irq_write(struct mei_cl *cl,
 			cb->buf.size, cb->buf_idx);
 
 	rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
-	if (rets) {
-		cl->status = rets;
-		list_move_tail(&cb->list, &cmpl_list->list);
-		return rets;
-	}
+	if (rets)
+		goto err;
 
 	cl->status = 0;
 	cl->writing_state = MEI_WRITING;
@@ -1582,14 +1584,21 @@ int mei_cl_irq_write(struct mei_cl *cl,
 	cb->completed = mei_hdr.msg_complete == 1;
 
 	if (first_chunk) {
-		if (mei_cl_tx_flow_ctrl_creds_reduce(cl))
-			return -EIO;
+		if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) {
+			rets = -EIO;
+			goto err;
+		}
 	}
 
 	if (mei_hdr.msg_complete)
 		list_move_tail(&cb->list, &dev->write_waiting_list.list);
 
 	return 0;
+
+err:
+	cl->status = rets;
+	list_move_tail(&cb->list, &cmpl_list->list);
+	return rets;
 }
 
 /**
@@ -1598,18 +1607,17 @@ int mei_cl_irq_write(struct mei_cl *cl,
  *
  * @cl: host client
  * @cb: write callback with filled data
- * @blocking: block until completed
  *
  * Return: number of bytes sent on success, <0 on failure.
  */
-int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
+int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
 {
 	struct mei_device *dev;
 	struct mei_msg_data *buf;
 	struct mei_msg_hdr mei_hdr;
 	int size;
 	int rets;
-
+	bool blocking;
 
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
@@ -1621,6 +1629,7 @@ int mei_cl_write(struct mei_cl *cl, stru
 
 	buf = &cb->buf;
 	size = buf->size;
+	blocking = cb->blocking;
 
 	cl_dbg(dev, cl, "size=%d\n", size);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/client.h linux-libre-4.10-rc8-gnu/drivers/misc/mei/client.h
--- linux-libre-4.9-gnu/drivers/misc/mei/client.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/client.h	2017-02-12 16:03:20.000000000 -0500
@@ -219,7 +219,7 @@ int mei_cl_irq_connect(struct mei_cl *cl
 int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp);
 int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr,
 			struct mei_cl_cb *cmpl_list);
-int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
+int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb);
 int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 		     struct mei_cl_cb *cmpl_list);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/debugfs.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/debugfs.c
--- linux-libre-4.9-gnu/drivers/misc/mei/debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -180,6 +180,8 @@ static ssize_t mei_dbgfs_read_devstate(s
 				 dev->hbm_f_ev_supported);
 		pos += scnprintf(buf + pos, bufsz - pos, "\tFA: %01d\n",
 				 dev->hbm_f_fa_supported);
+		pos += scnprintf(buf + pos, bufsz - pos, "\tOS: %01d\n",
+				 dev->hbm_f_os_supported);
 	}
 
 	pos += scnprintf(buf + pos, bufsz - pos, "pg:  %s, %s\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/hbm.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/hbm.c
--- linux-libre-4.9-gnu/drivers/misc/mei/hbm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/hbm.c	2017-02-12 16:03:20.000000000 -0500
@@ -989,6 +989,10 @@ static void mei_hbm_config_features(stru
 	/* Fixed Address Client Support */
 	if (dev->version.major_version >= HBM_MAJOR_VERSION_FA)
 		dev->hbm_f_fa_supported = 1;
+
+	/* OS ver message Support */
+	if (dev->version.major_version >= HBM_MAJOR_VERSION_OS)
+		dev->hbm_f_os_supported = 1;
 }
 
 /**
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/hw.h linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw.h
--- linux-libre-4.9-gnu/drivers/misc/mei/hw.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw.h	2017-02-12 16:03:20.000000000 -0500
@@ -76,6 +76,12 @@
 #define HBM_MINOR_VERSION_FA               0
 #define HBM_MAJOR_VERSION_FA               2
 
+/*
+ * MEI version with OS ver message support
+ */
+#define HBM_MINOR_VERSION_OS               0
+#define HBM_MAJOR_VERSION_OS               2
+
 /* Host bus message command opcode */
 #define MEI_HBM_CMD_OP_MSK                  0x7f
 /* Host bus message command RESPONSE */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/hw-me.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-me.c
--- linux-libre-4.9-gnu/drivers/misc/mei/hw-me.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-me.c	2017-02-12 16:03:20.000000000 -0500
@@ -246,6 +246,36 @@ static inline enum mei_pg_state mei_me_p
 	return hw->pg_state;
 }
 
+static inline u32 me_intr_src(u32 hcsr)
+{
+	return hcsr & H_CSR_IS_MASK;
+}
+
+/**
+ * me_intr_disable - disables mei device interrupts
+ *      using supplied hcsr register value.
+ *
+ * @dev: the device structure
+ * @hcsr: supplied hcsr register value
+ */
+static inline void me_intr_disable(struct mei_device *dev, u32 hcsr)
+{
+	hcsr &= ~H_CSR_IE_MASK;
+	mei_hcsr_set(dev, hcsr);
+}
+
+/**
+ * mei_me_intr_clear - clear and stop interrupts
+ *
+ * @dev: the device structure
+ * @hcsr: supplied hcsr register value
+ */
+static inline void me_intr_clear(struct mei_device *dev, u32 hcsr)
+{
+	if (me_intr_src(hcsr))
+		mei_hcsr_write(dev, hcsr);
+}
+
 /**
  * mei_me_intr_clear - clear and stop interrupts
  *
@@ -255,8 +285,7 @@ static void mei_me_intr_clear(struct mei
 {
 	u32 hcsr = mei_hcsr_read(dev);
 
-	if (hcsr & H_CSR_IS_MASK)
-		mei_hcsr_write(dev, hcsr);
+	me_intr_clear(dev, hcsr);
 }
 /**
  * mei_me_intr_enable - enables mei device interrupts
@@ -280,8 +309,19 @@ static void mei_me_intr_disable(struct m
 {
 	u32 hcsr = mei_hcsr_read(dev);
 
-	hcsr  &= ~H_CSR_IE_MASK;
-	mei_hcsr_set(dev, hcsr);
+	me_intr_disable(dev, hcsr);
+}
+
+/**
+ * mei_me_synchronize_irq - wait for pending IRQ handlers
+ *
+ * @dev: the device structure
+ */
+static void mei_me_synchronize_irq(struct mei_device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+	synchronize_irq(pdev->irq);
 }
 
 /**
@@ -450,7 +490,7 @@ static size_t mei_me_hbuf_max_len(const
 
 
 /**
- * mei_me_write_message - writes a message to mei device.
+ * mei_me_hbuf_write - writes a message to host hw buffer.
  *
  * @dev: the device structure
  * @header: mei HECI header of message
@@ -458,9 +498,9 @@ static size_t mei_me_hbuf_max_len(const
  *
  * Return: -EIO if write has failed
  */
-static int mei_me_write_message(struct mei_device *dev,
-			struct mei_msg_hdr *header,
-			unsigned char *buf)
+static int mei_me_hbuf_write(struct mei_device *dev,
+			     struct mei_msg_hdr *header,
+			     const unsigned char *buf)
 {
 	unsigned long rem;
 	unsigned long length = header->length;
@@ -956,13 +996,14 @@ static void mei_me_pg_legacy_intr(struct
  * mei_me_d0i3_intr - perform d0i3 processing in interrupt thread handler
  *
  * @dev: the device structure
+ * @intr_source: interrupt source
  */
-static void mei_me_d0i3_intr(struct mei_device *dev)
+static void mei_me_d0i3_intr(struct mei_device *dev, u32 intr_source)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 
 	if (dev->pg_event == MEI_PG_EVENT_INTR_WAIT &&
-	    (hw->intr_source & H_D0I3C_IS)) {
+	    (intr_source & H_D0I3C_IS)) {
 		dev->pg_event = MEI_PG_EVENT_INTR_RECEIVED;
 		if (hw->pg_state == MEI_PG_ON) {
 			hw->pg_state = MEI_PG_OFF;
@@ -981,7 +1022,7 @@ static void mei_me_d0i3_intr(struct mei_
 		wake_up(&dev->wait_pg);
 	}
 
-	if (hw->pg_state == MEI_PG_ON && (hw->intr_source & H_IS)) {
+	if (hw->pg_state == MEI_PG_ON && (intr_source & H_IS)) {
 		/*
 		 * HW sent some data and we are in D0i3, so
 		 * we got here because of HW initiated exit from D0i3.
@@ -996,13 +1037,14 @@ static void mei_me_d0i3_intr(struct mei_
  * mei_me_pg_intr - perform pg processing in interrupt thread handler
  *
  * @dev: the device structure
+ * @intr_source: interrupt source
  */
-static void mei_me_pg_intr(struct mei_device *dev)
+static void mei_me_pg_intr(struct mei_device *dev, u32 intr_source)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 
 	if (hw->d0i3_supported)
-		mei_me_d0i3_intr(dev);
+		mei_me_d0i3_intr(dev, intr_source);
 	else
 		mei_me_pg_legacy_intr(dev);
 }
@@ -1121,19 +1163,16 @@ static int mei_me_hw_reset(struct mei_de
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
 {
 	struct mei_device *dev = (struct mei_device *)dev_id;
-	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr;
 
 	hcsr = mei_hcsr_read(dev);
-	if (!(hcsr & H_CSR_IS_MASK))
+	if (!me_intr_src(hcsr))
 		return IRQ_NONE;
 
-	hw->intr_source = hcsr & H_CSR_IS_MASK;
-	dev_dbg(dev->dev, "interrupt source 0x%08X.\n", hw->intr_source);
-
-	/* clear H_IS and H_D0I3C_IS bits in H_CSR to clear the interrupts */
-	mei_hcsr_write(dev, hcsr);
+	dev_dbg(dev->dev, "interrupt source 0x%08X\n", me_intr_src(hcsr));
 
+	/* disable interrupts on device */
+	me_intr_disable(dev, hcsr);
 	return IRQ_WAKE_THREAD;
 }
 
@@ -1152,11 +1191,16 @@ irqreturn_t mei_me_irq_thread_handler(in
 	struct mei_device *dev = (struct mei_device *) dev_id;
 	struct mei_cl_cb complete_list;
 	s32 slots;
+	u32 hcsr;
 	int rets = 0;
 
 	dev_dbg(dev->dev, "function called after ISR to handle the interrupt processing.\n");
 	/* initialize our complete list */
 	mutex_lock(&dev->device_lock);
+
+	hcsr = mei_hcsr_read(dev);
+	me_intr_clear(dev, hcsr);
+
 	mei_io_list_init(&complete_list);
 
 	/* check if ME wants a reset */
@@ -1166,7 +1210,7 @@ irqreturn_t mei_me_irq_thread_handler(in
 		goto end;
 	}
 
-	mei_me_pg_intr(dev);
+	mei_me_pg_intr(dev, me_intr_src(hcsr));
 
 	/*  check if we need to start the dev */
 	if (!mei_host_is_ready(dev)) {
@@ -1216,6 +1260,7 @@ irqreturn_t mei_me_irq_thread_handler(in
 
 end:
 	dev_dbg(dev->dev, "interrupt thread end ret = %d\n", rets);
+	mei_me_intr_enable(dev);
 	mutex_unlock(&dev->device_lock);
 	return IRQ_HANDLED;
 }
@@ -1238,12 +1283,13 @@ static const struct mei_hw_ops mei_me_hw
 	.intr_clear = mei_me_intr_clear,
 	.intr_enable = mei_me_intr_enable,
 	.intr_disable = mei_me_intr_disable,
+	.synchronize_irq = mei_me_synchronize_irq,
 
 	.hbuf_free_slots = mei_me_hbuf_empty_slots,
 	.hbuf_is_ready = mei_me_hbuf_is_empty,
 	.hbuf_max_len = mei_me_hbuf_max_len,
 
-	.write = mei_me_write_message,
+	.write = mei_me_hbuf_write,
 
 	.rdbuf_full_slots = mei_me_count_full_read_slots,
 	.read_hdr = mei_me_mecbrw_read,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/hw-me.h linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-me.h
--- linux-libre-4.9-gnu/drivers/misc/mei/hw-me.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-me.h	2017-02-12 16:03:20.000000000 -0500
@@ -51,14 +51,12 @@ struct mei_cfg {
  *
  * @cfg: per device generation config and ops
  * @mem_addr: io memory address
- * @intr_source: interrupt source
  * @pg_state: power gating state
  * @d0i3_supported: di03 support
  */
 struct mei_me_hw {
 	const struct mei_cfg *cfg;
 	void __iomem *mem_addr;
-	u32 intr_source;
 	enum mei_pg_state pg_state;
 	bool d0i3_supported;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/hw-me-regs.h linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-me-regs.h
--- linux-libre-4.9-gnu/drivers/misc/mei/hw-me-regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-me-regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -122,6 +122,8 @@
 #define MEI_DEV_ID_SPT_H      0xA13A  /* Sunrise Point H */
 #define MEI_DEV_ID_SPT_H_2    0xA13B  /* Sunrise Point H 2 */
 
+#define MEI_DEV_ID_LBG        0xA1BA  /* Lewisburg (SPT) */
+
 #define MEI_DEV_ID_BXT_M      0x1A9A  /* Broxton M */
 #define MEI_DEV_ID_APL_I      0x5A9A  /* Apollo Lake I */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/hw-txe.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-txe.c
--- linux-libre-4.9-gnu/drivers/misc/mei/hw-txe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/hw-txe.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,7 +19,7 @@
 #include <linux/ktime.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
-#include <linux/irqreturn.h>
+#include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 
 #include <linux/mei.h>
@@ -441,6 +441,18 @@ static void mei_txe_intr_enable(struct m
 }
 
 /**
+ * mei_txe_synchronize_irq - wait for pending IRQ handlers
+ *
+ * @dev: the device structure
+ */
+static void mei_txe_synchronize_irq(struct mei_device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev->dev);
+
+	synchronize_irq(pdev->irq);
+}
+
+/**
  * mei_txe_pending_interrupts - check if there are pending interrupts
  *	only Aliveness, Input ready, and output doorbell are of relevance
  *
@@ -691,7 +703,8 @@ static void mei_txe_hw_config(struct mei
  */
 
 static int mei_txe_write(struct mei_device *dev,
-		struct mei_msg_hdr *header, unsigned char *buf)
+			 struct mei_msg_hdr *header,
+			 const unsigned char *buf)
 {
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	unsigned long rem;
@@ -1167,6 +1180,7 @@ static const struct mei_hw_ops mei_txe_h
 	.intr_clear = mei_txe_intr_clear,
 	.intr_enable = mei_txe_intr_enable,
 	.intr_disable = mei_txe_intr_disable,
+	.synchronize_irq = mei_txe_synchronize_irq,
 
 	.hbuf_free_slots = mei_txe_hbuf_empty_slots,
 	.hbuf_is_ready = mei_txe_is_input_ready,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/init.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/init.c
--- linux-libre-4.9-gnu/drivers/misc/mei/init.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/init.c	2017-02-12 16:03:20.000000000 -0500
@@ -122,6 +122,10 @@ int mei_reset(struct mei_device *dev)
 			 mei_dev_state_str(state), fw_sts_str);
 	}
 
+	mei_clear_interrupts(dev);
+
+	mei_synchronize_irq(dev);
+
 	/* we're already in reset, cancel the init timer
 	 * if the reset was called due the hbm protocol error
 	 * we need to call it before hw start
@@ -273,8 +277,6 @@ int mei_restart(struct mei_device *dev)
 
 	mutex_lock(&dev->device_lock);
 
-	mei_clear_interrupts(dev);
-
 	dev->dev_state = MEI_DEV_POWER_UP;
 	dev->reset_count = 0;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/interrupt.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/interrupt.c
--- linux-libre-4.9-gnu/drivers/misc/mei/interrupt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/interrupt.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,7 +118,6 @@ int mei_cl_irq_read_msg(struct mei_cl *c
 
 	if (!mei_cl_is_connected(cl)) {
 		cl_dbg(dev, cl, "not connected\n");
-		list_move_tail(&cb->list, &complete_list->list);
 		cb->status = -ENODEV;
 		goto discard;
 	}
@@ -128,8 +127,6 @@ int mei_cl_irq_read_msg(struct mei_cl *c
 	if (buf_sz < cb->buf_idx) {
 		cl_err(dev, cl, "message is too big len %d idx %zu\n",
 		       mei_hdr->length, cb->buf_idx);
-
-		list_move_tail(&cb->list, &complete_list->list);
 		cb->status = -EMSGSIZE;
 		goto discard;
 	}
@@ -137,8 +134,6 @@ int mei_cl_irq_read_msg(struct mei_cl *c
 	if (cb->buf.size < buf_sz) {
 		cl_dbg(dev, cl, "message overflow. size %zu len %d idx %zu\n",
 			cb->buf.size, mei_hdr->length, cb->buf_idx);
-
-		list_move_tail(&cb->list, &complete_list->list);
 		cb->status = -EMSGSIZE;
 		goto discard;
 	}
@@ -158,6 +153,8 @@ int mei_cl_irq_read_msg(struct mei_cl *c
 	return 0;
 
 discard:
+	if (cb)
+		list_move_tail(&cb->list, &complete_list->list);
 	mei_irq_discard_msg(dev, mei_hdr);
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/main.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/main.c
--- linux-libre-4.9-gnu/drivers/misc/mei/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -322,7 +322,7 @@ static ssize_t mei_write(struct file *fi
 		goto out;
 	}
 
-	rets = mei_cl_write(cl, cb, false);
+	rets = mei_cl_write(cl, cb);
 out:
 	mutex_unlock(&dev->device_lock);
 	return rets;
@@ -653,7 +653,7 @@ static int mei_fasync(int fd, struct fil
 }
 
 /**
- * fw_status_show - mei device attribute show method
+ * fw_status_show - mei device fw_status attribute show method
  *
  * @device: device pointer
  * @attr: attribute pointer
@@ -684,8 +684,49 @@ static ssize_t fw_status_show(struct dev
 }
 static DEVICE_ATTR_RO(fw_status);
 
+/**
+ * hbm_ver_show - display HBM protocol version negotiated with FW
+ *
+ * @device: device pointer
+ * @attr: attribute pointer
+ * @buf:  char out buffer
+ *
+ * Return: number of the bytes printed into buf or error
+ */
+static ssize_t hbm_ver_show(struct device *device,
+			    struct device_attribute *attr, char *buf)
+{
+	struct mei_device *dev = dev_get_drvdata(device);
+	struct hbm_version ver;
+
+	mutex_lock(&dev->device_lock);
+	ver = dev->version;
+	mutex_unlock(&dev->device_lock);
+
+	return sprintf(buf, "%u.%u\n", ver.major_version, ver.minor_version);
+}
+static DEVICE_ATTR_RO(hbm_ver);
+
+/**
+ * hbm_ver_drv_show - display HBM protocol version advertised by driver
+ *
+ * @device: device pointer
+ * @attr: attribute pointer
+ * @buf:  char out buffer
+ *
+ * Return: number of the bytes printed into buf or error
+ */
+static ssize_t hbm_ver_drv_show(struct device *device,
+				struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%u.%u\n", HBM_MAJOR_VERSION, HBM_MINOR_VERSION);
+}
+static DEVICE_ATTR_RO(hbm_ver_drv);
+
 static struct attribute *mei_attrs[] = {
 	&dev_attr_fw_status.attr,
+	&dev_attr_hbm_ver.attr,
+	&dev_attr_hbm_ver_drv.attr,
 	NULL
 };
 ATTRIBUTE_GROUPS(mei);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/mei_dev.h linux-libre-4.10-rc8-gnu/drivers/misc/mei/mei_dev.h
--- linux-libre-4.9-gnu/drivers/misc/mei/mei_dev.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/mei_dev.h	2017-02-12 16:03:20.000000000 -0500
@@ -55,7 +55,8 @@ extern const uuid_le mei_amthif_guid;
 
 /* File state */
 enum file_state {
-	MEI_FILE_INITIALIZING = 0,
+	MEI_FILE_UNINITIALIZED = 0,
+	MEI_FILE_INITIALIZING,
 	MEI_FILE_CONNECTING,
 	MEI_FILE_CONNECTED,
 	MEI_FILE_DISCONNECTING,
@@ -109,6 +110,21 @@ enum mei_cb_file_ops {
 	MEI_FOP_NOTIFY_STOP,
 };
 
+/**
+ * enum mei_cl_io_mode - io mode between driver and fw
+ *
+ * @MEI_CL_IO_TX_BLOCKING: send is blocking
+ * @MEI_CL_IO_TX_INTERNAL: internal communication between driver and FW
+ *
+ * @MEI_CL_IO_RX_NONBLOCK: recv is non-blocking
+ */
+enum mei_cl_io_mode {
+	MEI_CL_IO_TX_BLOCKING = BIT(0),
+	MEI_CL_IO_TX_INTERNAL = BIT(1),
+
+	MEI_CL_IO_RX_NONBLOCK = BIT(2),
+};
+
 /*
  * Intel MEI message data struct
  */
@@ -169,6 +185,7 @@ struct mei_cl;
  * @fp: pointer to file structure
  * @status: io status of the cb
  * @internal: communication between driver and FW flag
+ * @blocking: transmission blocking mode
  * @completed: the transfer or reception has completed
  */
 struct mei_cl_cb {
@@ -180,6 +197,7 @@ struct mei_cl_cb {
 	const struct file *fp;
 	int status;
 	u32 internal:1;
+	u32 blocking:1;
 	u32 completed:1;
 };
 
@@ -253,6 +271,7 @@ struct mei_cl {
  * @intr_clear       : clear pending interrupts
  * @intr_enable      : enable interrupts
  * @intr_disable     : disable interrupts
+ * @synchronize_irq  : synchronize irqs
  *
  * @hbuf_free_slots  : query for write buffer empty slots
  * @hbuf_is_ready    : query if write buffer is empty
@@ -274,7 +293,6 @@ struct mei_hw_ops {
 	int (*hw_start)(struct mei_device *dev);
 	void (*hw_config)(struct mei_device *dev);
 
-
 	int (*fw_status)(struct mei_device *dev, struct mei_fw_status *fw_sts);
 	enum mei_pg_state (*pg_state)(struct mei_device *dev);
 	bool (*pg_in_transition)(struct mei_device *dev);
@@ -283,14 +301,14 @@ struct mei_hw_ops {
 	void (*intr_clear)(struct mei_device *dev);
 	void (*intr_enable)(struct mei_device *dev);
 	void (*intr_disable)(struct mei_device *dev);
+	void (*synchronize_irq)(struct mei_device *dev);
 
 	int (*hbuf_free_slots)(struct mei_device *dev);
 	bool (*hbuf_is_ready)(struct mei_device *dev);
 	size_t (*hbuf_max_len)(const struct mei_device *dev);
-
 	int (*write)(struct mei_device *dev,
 		     struct mei_msg_hdr *hdr,
-		     unsigned char *buf);
+		     const unsigned char *buf);
 
 	int (*rdbuf_full_slots)(struct mei_device *dev);
 
@@ -304,8 +322,9 @@ void mei_cl_bus_rescan(struct mei_device
 void mei_cl_bus_rescan_work(struct work_struct *work);
 void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
 ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
-			bool blocking);
-ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
+		      unsigned int mode);
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+		      unsigned int mode);
 bool mei_cl_bus_rx_event(struct mei_cl *cl);
 bool mei_cl_bus_notify_event(struct mei_cl *cl);
 void mei_cl_bus_remove_devices(struct mei_device *bus);
@@ -387,6 +406,7 @@ const char *mei_pg_state_str(enum mei_pg
  * @hbm_f_ev_supported  : hbm feature event notification
  * @hbm_f_fa_supported  : hbm feature fixed address client
  * @hbm_f_ie_supported  : hbm feature immediate reply to enum request
+ * @hbm_f_os_supported  : hbm feature support OS ver message
  *
  * @me_clients_rwsem: rw lock over me_clients list
  * @me_clients  : list of FW clients
@@ -468,6 +488,7 @@ struct mei_device {
 	unsigned int hbm_f_ev_supported:1;
 	unsigned int hbm_f_fa_supported:1;
 	unsigned int hbm_f_ie_supported:1;
+	unsigned int hbm_f_os_supported:1;
 
 	struct rw_semaphore me_clients_rwsem;
 	struct list_head me_clients;
@@ -627,6 +648,11 @@ static inline void mei_disable_interrupt
 	dev->ops->intr_disable(dev);
 }
 
+static inline void mei_synchronize_irq(struct mei_device *dev)
+{
+	dev->ops->synchronize_irq(dev);
+}
+
 static inline bool mei_host_is_ready(struct mei_device *dev)
 {
 	return dev->ops->host_is_ready(dev);
@@ -652,7 +678,7 @@ static inline size_t mei_hbuf_max_len(co
 }
 
 static inline int mei_write_message(struct mei_device *dev,
-			struct mei_msg_hdr *hdr, void *buf)
+				    struct mei_msg_hdr *hdr, const void *buf)
 {
 	return dev->ops->write(dev, hdr, buf);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/mei/pci-me.c linux-libre-4.10-rc8-gnu/drivers/misc/mei/pci-me.c
--- linux-libre-4.9-gnu/drivers/misc/mei/pci-me.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/mei/pci-me.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,6 +87,7 @@ static const struct pci_device_id mei_me
 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_sps_cfg)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_sps_cfg)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_LBG, mei_me_pch8_cfg)},
 
 	{MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, mei_me_pch8_cfg)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, mei_me_pch8_cfg)},
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/sgi-gru/grumain.c linux-libre-4.10-rc8-gnu/drivers/misc/sgi-gru/grumain.c
--- linux-libre-4.9-gnu/drivers/misc/sgi-gru/grumain.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/sgi-gru/grumain.c	2017-02-12 16:03:20.000000000 -0500
@@ -932,7 +932,7 @@ int gru_fault(struct vm_area_struct *vma
 	unsigned long paddr, vaddr;
 	unsigned long expires;
 
-	vaddr = (unsigned long)vmf->virtual_address;
+	vaddr = vmf->address;
 	gru_dbg(grudev, "vma %p, vaddr 0x%lx (0x%lx)\n",
 		vma, vaddr, GSEG_BASE(vaddr));
 	STAT(nopfn);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/sgi-xp/xpnet.c linux-libre-4.10-rc8-gnu/drivers/misc/sgi-xp/xpnet.c
--- linux-libre-4.9-gnu/drivers/misc/sgi-xp/xpnet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/sgi-xp/xpnet.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,6 +118,8 @@ static DEFINE_SPINLOCK(xpnet_broadcast_l
  * now, the default is 64KB.
  */
 #define XPNET_MAX_MTU (0x800000UL - L1_CACHE_BYTES)
+/* 68 comes from min TCP+IP+MAC header */
+#define XPNET_MIN_MTU 68
 /* 32KB has been determined to be the ideal */
 #define XPNET_DEF_MTU (0x8000UL)
 
@@ -330,22 +332,6 @@ xpnet_dev_stop(struct net_device *dev)
 	return 0;
 }
 
-static int
-xpnet_dev_change_mtu(struct net_device *dev, int new_mtu)
-{
-	/* 68 comes from min TCP+IP+MAC header */
-	if ((new_mtu < 68) || (new_mtu > XPNET_MAX_MTU)) {
-		dev_err(xpnet, "ifconfig %s mtu %d failed; value must be "
-			"between 68 and %ld\n", dev->name, new_mtu,
-			XPNET_MAX_MTU);
-		return -EINVAL;
-	}
-
-	dev->mtu = new_mtu;
-	dev_dbg(xpnet, "ifconfig %s mtu set to %d\n", dev->name, new_mtu);
-	return 0;
-}
-
 /*
  * Notification that the other end has received the message and
  * DMA'd the skb information.  At this point, they are done with
@@ -519,7 +505,6 @@ static const struct net_device_ops xpnet
 	.ndo_open		= xpnet_dev_open,
 	.ndo_stop		= xpnet_dev_stop,
 	.ndo_start_xmit		= xpnet_dev_hard_start_xmit,
-	.ndo_change_mtu		= xpnet_dev_change_mtu,
 	.ndo_tx_timeout		= xpnet_dev_tx_timeout,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
@@ -555,6 +540,8 @@ xpnet_init(void)
 
 	xpnet_device->netdev_ops = &xpnet_netdev_ops;
 	xpnet_device->mtu = XPNET_DEF_MTU;
+	xpnet_device->min_mtu = XPNET_MIN_MTU;
+	xpnet_device->max_mtu = XPNET_MAX_MTU;
 
 	/*
 	 * Multicast assumes the LSB of the first octet is set for multicast
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/misc/sram.c linux-libre-4.10-rc8-gnu/drivers/misc/sram.c
--- linux-libre-4.9-gnu/drivers/misc/sram.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/misc/sram.c	2017-02-12 16:03:20.000000000 -0500
@@ -19,12 +19,17 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/genalloc.h>
 #include <linux/io.h>
 #include <linux/list_sort.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
+#include <linux/mfd/syscon.h>
+#include <soc/at91/atmel-secumod.h>
 
 #define SRAM_GRANULARITY	32
 
@@ -334,12 +339,33 @@ static int sram_reserve_regions(struct s
 	return ret;
 }
 
+static int atmel_securam_wait(void)
+{
+	struct regmap *regmap;
+	u32 val;
+
+	regmap = syscon_regmap_lookup_by_compatible("atmel,sama5d2-secumod");
+	if (IS_ERR(regmap))
+		return -ENODEV;
+
+	return regmap_read_poll_timeout(regmap, AT91_SECUMOD_RAMRDY, val,
+					val & AT91_SECUMOD_RAMRDY_READY,
+					10000, 500000);
+}
+
+static const struct of_device_id sram_dt_ids[] = {
+	{ .compatible = "mmio-sram" },
+	{ .compatible = "atmel,sama5d2-securam", .data = atmel_securam_wait },
+	{}
+};
+
 static int sram_probe(struct platform_device *pdev)
 {
 	struct sram_dev *sram;
 	struct resource *res;
 	size_t size;
 	int ret;
+	int (*init_func)(void);
 
 	sram = devm_kzalloc(&pdev->dev, sizeof(*sram), GFP_KERNEL);
 	if (!sram)
@@ -384,6 +410,13 @@ static int sram_probe(struct platform_de
 
 	platform_set_drvdata(pdev, sram);
 
+	init_func = of_device_get_match_data(&pdev->dev);
+	if (init_func) {
+		ret = init_func();
+		if (ret)
+			return ret;
+	}
+
 	dev_dbg(sram->dev, "SRAM pool: %zu KiB @ 0x%p\n",
 		gen_pool_size(sram->pool) / 1024, sram->virt_base);
 
@@ -405,17 +438,10 @@ static int sram_remove(struct platform_d
 	return 0;
 }
 
-#ifdef CONFIG_OF
-static const struct of_device_id sram_dt_ids[] = {
-	{ .compatible = "mmio-sram" },
-	{}
-};
-#endif
-
 static struct platform_driver sram_driver = {
 	.driver = {
 		.name = "sram",
-		.of_match_table = of_match_ptr(sram_dt_ids),
+		.of_match_table = sram_dt_ids,
 	},
 	.probe = sram_probe,
 	.remove = sram_remove,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/block.c linux-libre-4.10-rc8-gnu/drivers/mmc/card/block.c
--- linux-libre-4.9-gnu/drivers/mmc/card/block.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/block.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2745 +0,0 @@
-/*
- * Block driver for media (i.e., flash cards)
- *
- * Copyright 2002 Hewlett-Packard Company
- * Copyright 2005-2008 Pierre Ossman
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- *
- * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
- * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
- * FITNESS FOR ANY PARTICULAR PURPOSE.
- *
- * Many thanks to Alessandro Rubini and Jonathan Corbet!
- *
- * Author:  Andrew Christian
- *          28 May 2002
- */
-#include <linux/moduleparam.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/kdev_t.h>
-#include <linux/blkdev.h>
-#include <linux/mutex.h>
-#include <linux/scatterlist.h>
-#include <linux/string_helpers.h>
-#include <linux/delay.h>
-#include <linux/capability.h>
-#include <linux/compat.h>
-#include <linux/pm_runtime.h>
-#include <linux/idr.h>
-
-#include <linux/mmc/ioctl.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/mmc.h>
-#include <linux/mmc/sd.h>
-
-#include <asm/uaccess.h>
-
-#include "queue.h"
-#include "block.h"
-
-MODULE_ALIAS("mmc:block");
-#ifdef MODULE_PARAM_PREFIX
-#undef MODULE_PARAM_PREFIX
-#endif
-#define MODULE_PARAM_PREFIX "mmcblk."
-
-#define INAND_CMD38_ARG_EXT_CSD  113
-#define INAND_CMD38_ARG_ERASE    0x00
-#define INAND_CMD38_ARG_TRIM     0x01
-#define INAND_CMD38_ARG_SECERASE 0x80
-#define INAND_CMD38_ARG_SECTRIM1 0x81
-#define INAND_CMD38_ARG_SECTRIM2 0x88
-#define MMC_BLK_TIMEOUT_MS  (10 * 60 * 1000)        /* 10 minute timeout */
-#define MMC_SANITIZE_REQ_TIMEOUT 240000
-#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
-
-#define mmc_req_rel_wr(req)	((req->cmd_flags & REQ_FUA) && \
-				  (rq_data_dir(req) == WRITE))
-#define PACKED_CMD_VER	0x01
-#define PACKED_CMD_WR	0x02
-
-static DEFINE_MUTEX(block_mutex);
-
-/*
- * The defaults come from config options but can be overriden by module
- * or bootarg options.
- */
-static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
-
-/*
- * We've only got one major, so number of mmcblk devices is
- * limited to (1 << 20) / number of minors per device.  It is also
- * limited by the MAX_DEVICES below.
- */
-static int max_devices;
-
-#define MAX_DEVICES 256
-
-static DEFINE_IDA(mmc_blk_ida);
-static DEFINE_SPINLOCK(mmc_blk_lock);
-
-/*
- * There is one mmc_blk_data per slot.
- */
-struct mmc_blk_data {
-	spinlock_t	lock;
-	struct device	*parent;
-	struct gendisk	*disk;
-	struct mmc_queue queue;
-	struct list_head part;
-
-	unsigned int	flags;
-#define MMC_BLK_CMD23	(1 << 0)	/* Can do SET_BLOCK_COUNT for multiblock */
-#define MMC_BLK_REL_WR	(1 << 1)	/* MMC Reliable write support */
-#define MMC_BLK_PACKED_CMD	(1 << 2)	/* MMC packed command support */
-
-	unsigned int	usage;
-	unsigned int	read_only;
-	unsigned int	part_type;
-	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
-	 * with mmc_card with dev_set_drvdata, and keeps
-	 * track of the current selected device partition.
-	 */
-	unsigned int	part_curr;
-	struct device_attribute force_ro;
-	struct device_attribute power_ro_lock;
-	int	area_type;
-};
-
-static DEFINE_MUTEX(open_lock);
-
-enum {
-	MMC_PACKED_NR_IDX = -1,
-	MMC_PACKED_NR_ZERO,
-	MMC_PACKED_NR_SINGLE,
-};
-
-module_param(perdev_minors, int, 0444);
-MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
-
-static inline int mmc_blk_part_switch(struct mmc_card *card,
-				      struct mmc_blk_data *md);
-static int get_card_status(struct mmc_card *card, u32 *status, int retries);
-
-static inline void mmc_blk_clear_packed(struct mmc_queue_req *mqrq)
-{
-	struct mmc_packed *packed = mqrq->packed;
-
-	mqrq->cmd_type = MMC_PACKED_NONE;
-	packed->nr_entries = MMC_PACKED_NR_ZERO;
-	packed->idx_failure = MMC_PACKED_NR_IDX;
-	packed->retries = 0;
-	packed->blocks = 0;
-}
-
-static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
-{
-	struct mmc_blk_data *md;
-
-	mutex_lock(&open_lock);
-	md = disk->private_data;
-	if (md && md->usage == 0)
-		md = NULL;
-	if (md)
-		md->usage++;
-	mutex_unlock(&open_lock);
-
-	return md;
-}
-
-static inline int mmc_get_devidx(struct gendisk *disk)
-{
-	int devidx = disk->first_minor / perdev_minors;
-	return devidx;
-}
-
-static void mmc_blk_put(struct mmc_blk_data *md)
-{
-	mutex_lock(&open_lock);
-	md->usage--;
-	if (md->usage == 0) {
-		int devidx = mmc_get_devidx(md->disk);
-		blk_cleanup_queue(md->queue.queue);
-
-		spin_lock(&mmc_blk_lock);
-		ida_remove(&mmc_blk_ida, devidx);
-		spin_unlock(&mmc_blk_lock);
-
-		put_disk(md->disk);
-		kfree(md);
-	}
-	mutex_unlock(&open_lock);
-}
-
-static ssize_t power_ro_lock_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	int ret;
-	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
-	struct mmc_card *card = md->queue.card;
-	int locked = 0;
-
-	if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
-		locked = 2;
-	else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
-		locked = 1;
-
-	ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
-
-	mmc_blk_put(md);
-
-	return ret;
-}
-
-static ssize_t power_ro_lock_store(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	int ret;
-	struct mmc_blk_data *md, *part_md;
-	struct mmc_card *card;
-	unsigned long set;
-
-	if (kstrtoul(buf, 0, &set))
-		return -EINVAL;
-
-	if (set != 1)
-		return count;
-
-	md = mmc_blk_get(dev_to_disk(dev));
-	card = md->queue.card;
-
-	mmc_get_card(card);
-
-	ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
-				card->ext_csd.boot_ro_lock |
-				EXT_CSD_BOOT_WP_B_PWR_WP_EN,
-				card->ext_csd.part_time);
-	if (ret)
-		pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
-	else
-		card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
-
-	mmc_put_card(card);
-
-	if (!ret) {
-		pr_info("%s: Locking boot partition ro until next power on\n",
-			md->disk->disk_name);
-		set_disk_ro(md->disk, 1);
-
-		list_for_each_entry(part_md, &md->part, part)
-			if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
-				pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
-				set_disk_ro(part_md->disk, 1);
-			}
-	}
-
-	mmc_blk_put(md);
-	return count;
-}
-
-static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
-			     char *buf)
-{
-	int ret;
-	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
-
-	ret = snprintf(buf, PAGE_SIZE, "%d\n",
-		       get_disk_ro(dev_to_disk(dev)) ^
-		       md->read_only);
-	mmc_blk_put(md);
-	return ret;
-}
-
-static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	int ret;
-	char *end;
-	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
-	unsigned long set = simple_strtoul(buf, &end, 0);
-	if (end == buf) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	set_disk_ro(dev_to_disk(dev), set || md->read_only);
-	ret = count;
-out:
-	mmc_blk_put(md);
-	return ret;
-}
-
-static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
-{
-	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
-	int ret = -ENXIO;
-
-	mutex_lock(&block_mutex);
-	if (md) {
-		if (md->usage == 2)
-			check_disk_change(bdev);
-		ret = 0;
-
-		if ((mode & FMODE_WRITE) && md->read_only) {
-			mmc_blk_put(md);
-			ret = -EROFS;
-		}
-	}
-	mutex_unlock(&block_mutex);
-
-	return ret;
-}
-
-static void mmc_blk_release(struct gendisk *disk, fmode_t mode)
-{
-	struct mmc_blk_data *md = disk->private_data;
-
-	mutex_lock(&block_mutex);
-	mmc_blk_put(md);
-	mutex_unlock(&block_mutex);
-}
-
-static int
-mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
-	geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
-	geo->heads = 4;
-	geo->sectors = 16;
-	return 0;
-}
-
-struct mmc_blk_ioc_data {
-	struct mmc_ioc_cmd ic;
-	unsigned char *buf;
-	u64 buf_bytes;
-};
-
-static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
-	struct mmc_ioc_cmd __user *user)
-{
-	struct mmc_blk_ioc_data *idata;
-	int err;
-
-	idata = kmalloc(sizeof(*idata), GFP_KERNEL);
-	if (!idata) {
-		err = -ENOMEM;
-		goto out;
-	}
-
-	if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
-		err = -EFAULT;
-		goto idata_err;
-	}
-
-	idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
-	if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
-		err = -EOVERFLOW;
-		goto idata_err;
-	}
-
-	if (!idata->buf_bytes) {
-		idata->buf = NULL;
-		return idata;
-	}
-
-	idata->buf = kmalloc(idata->buf_bytes, GFP_KERNEL);
-	if (!idata->buf) {
-		err = -ENOMEM;
-		goto idata_err;
-	}
-
-	if (copy_from_user(idata->buf, (void __user *)(unsigned long)
-					idata->ic.data_ptr, idata->buf_bytes)) {
-		err = -EFAULT;
-		goto copy_err;
-	}
-
-	return idata;
-
-copy_err:
-	kfree(idata->buf);
-idata_err:
-	kfree(idata);
-out:
-	return ERR_PTR(err);
-}
-
-static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
-				      struct mmc_blk_ioc_data *idata)
-{
-	struct mmc_ioc_cmd *ic = &idata->ic;
-
-	if (copy_to_user(&(ic_ptr->response), ic->response,
-			 sizeof(ic->response)))
-		return -EFAULT;
-
-	if (!idata->ic.write_flag) {
-		if (copy_to_user((void __user *)(unsigned long)ic->data_ptr,
-				 idata->buf, idata->buf_bytes))
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
-				       u32 retries_max)
-{
-	int err;
-	u32 retry_count = 0;
-
-	if (!status || !retries_max)
-		return -EINVAL;
-
-	do {
-		err = get_card_status(card, status, 5);
-		if (err)
-			break;
-
-		if (!R1_STATUS(*status) &&
-				(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
-			break; /* RPMB programming operation complete */
-
-		/*
-		 * Rechedule to give the MMC device a chance to continue
-		 * processing the previous command without being polled too
-		 * frequently.
-		 */
-		usleep_range(1000, 5000);
-	} while (++retry_count < retries_max);
-
-	if (retry_count == retries_max)
-		err = -EPERM;
-
-	return err;
-}
-
-static int ioctl_do_sanitize(struct mmc_card *card)
-{
-	int err;
-
-	if (!mmc_can_sanitize(card)) {
-			pr_warn("%s: %s - SANITIZE is not supported\n",
-				mmc_hostname(card->host), __func__);
-			err = -EOPNOTSUPP;
-			goto out;
-	}
-
-	pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
-		mmc_hostname(card->host), __func__);
-
-	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-					EXT_CSD_SANITIZE_START, 1,
-					MMC_SANITIZE_REQ_TIMEOUT);
-
-	if (err)
-		pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
-		       mmc_hostname(card->host), __func__, err);
-
-	pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
-					     __func__);
-out:
-	return err;
-}
-
-static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
-			       struct mmc_blk_ioc_data *idata)
-{
-	struct mmc_command cmd = {0};
-	struct mmc_data data = {0};
-	struct mmc_request mrq = {NULL};
-	struct scatterlist sg;
-	int err;
-	int is_rpmb = false;
-	u32 status = 0;
-
-	if (!card || !md || !idata)
-		return -EINVAL;
-
-	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
-		is_rpmb = true;
-
-	cmd.opcode = idata->ic.opcode;
-	cmd.arg = idata->ic.arg;
-	cmd.flags = idata->ic.flags;
-
-	if (idata->buf_bytes) {
-		data.sg = &sg;
-		data.sg_len = 1;
-		data.blksz = idata->ic.blksz;
-		data.blocks = idata->ic.blocks;
-
-		sg_init_one(data.sg, idata->buf, idata->buf_bytes);
-
-		if (idata->ic.write_flag)
-			data.flags = MMC_DATA_WRITE;
-		else
-			data.flags = MMC_DATA_READ;
-
-		/* data.flags must already be set before doing this. */
-		mmc_set_data_timeout(&data, card);
-
-		/* Allow overriding the timeout_ns for empirical tuning. */
-		if (idata->ic.data_timeout_ns)
-			data.timeout_ns = idata->ic.data_timeout_ns;
-
-		if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
-			/*
-			 * Pretend this is a data transfer and rely on the
-			 * host driver to compute timeout.  When all host
-			 * drivers support cmd.cmd_timeout for R1B, this
-			 * can be changed to:
-			 *
-			 *     mrq.data = NULL;
-			 *     cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
-			 */
-			data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
-		}
-
-		mrq.data = &data;
-	}
-
-	mrq.cmd = &cmd;
-
-	err = mmc_blk_part_switch(card, md);
-	if (err)
-		return err;
-
-	if (idata->ic.is_acmd) {
-		err = mmc_app_cmd(card->host, card);
-		if (err)
-			return err;
-	}
-
-	if (is_rpmb) {
-		err = mmc_set_blockcount(card, data.blocks,
-			idata->ic.write_flag & (1 << 31));
-		if (err)
-			return err;
-	}
-
-	if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
-	    (cmd.opcode == MMC_SWITCH)) {
-		err = ioctl_do_sanitize(card);
-
-		if (err)
-			pr_err("%s: ioctl_do_sanitize() failed. err = %d",
-			       __func__, err);
-
-		return err;
-	}
-
-	mmc_wait_for_req(card->host, &mrq);
-
-	if (cmd.error) {
-		dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
-						__func__, cmd.error);
-		return cmd.error;
-	}
-	if (data.error) {
-		dev_err(mmc_dev(card->host), "%s: data error %d\n",
-						__func__, data.error);
-		return data.error;
-	}
-
-	/*
-	 * According to the SD specs, some commands require a delay after
-	 * issuing the command.
-	 */
-	if (idata->ic.postsleep_min_us)
-		usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
-
-	memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
-
-	if (is_rpmb) {
-		/*
-		 * Ensure RPMB command has completed by polling CMD13
-		 * "Send Status".
-		 */
-		err = ioctl_rpmb_card_status_poll(card, &status, 5);
-		if (err)
-			dev_err(mmc_dev(card->host),
-					"%s: Card Status=0x%08X, error %d\n",
-					__func__, status, err);
-	}
-
-	return err;
-}
-
-static int mmc_blk_ioctl_cmd(struct block_device *bdev,
-			     struct mmc_ioc_cmd __user *ic_ptr)
-{
-	struct mmc_blk_ioc_data *idata;
-	struct mmc_blk_data *md;
-	struct mmc_card *card;
-	int err = 0, ioc_err = 0;
-
-	/*
-	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
-	 * whole block device, not on a partition.  This prevents overspray
-	 * between sibling partitions.
-	 */
-	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
-		return -EPERM;
-
-	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
-	if (IS_ERR(idata))
-		return PTR_ERR(idata);
-
-	md = mmc_blk_get(bdev->bd_disk);
-	if (!md) {
-		err = -EINVAL;
-		goto cmd_err;
-	}
-
-	card = md->queue.card;
-	if (IS_ERR(card)) {
-		err = PTR_ERR(card);
-		goto cmd_done;
-	}
-
-	mmc_get_card(card);
-
-	ioc_err = __mmc_blk_ioctl_cmd(card, md, idata);
-
-	/* Always switch back to main area after RPMB access */
-	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
-		mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
-
-	mmc_put_card(card);
-
-	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
-
-cmd_done:
-	mmc_blk_put(md);
-cmd_err:
-	kfree(idata->buf);
-	kfree(idata);
-	return ioc_err ? ioc_err : err;
-}
-
-static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
-				   struct mmc_ioc_multi_cmd __user *user)
-{
-	struct mmc_blk_ioc_data **idata = NULL;
-	struct mmc_ioc_cmd __user *cmds = user->cmds;
-	struct mmc_card *card;
-	struct mmc_blk_data *md;
-	int i, err = 0, ioc_err = 0;
-	__u64 num_of_cmds;
-
-	/*
-	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
-	 * whole block device, not on a partition.  This prevents overspray
-	 * between sibling partitions.
-	 */
-	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
-		return -EPERM;
-
-	if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
-			   sizeof(num_of_cmds)))
-		return -EFAULT;
-
-	if (num_of_cmds > MMC_IOC_MAX_CMDS)
-		return -EINVAL;
-
-	idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL);
-	if (!idata)
-		return -ENOMEM;
-
-	for (i = 0; i < num_of_cmds; i++) {
-		idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]);
-		if (IS_ERR(idata[i])) {
-			err = PTR_ERR(idata[i]);
-			num_of_cmds = i;
-			goto cmd_err;
-		}
-	}
-
-	md = mmc_blk_get(bdev->bd_disk);
-	if (!md) {
-		err = -EINVAL;
-		goto cmd_err;
-	}
-
-	card = md->queue.card;
-	if (IS_ERR(card)) {
-		err = PTR_ERR(card);
-		goto cmd_done;
-	}
-
-	mmc_get_card(card);
-
-	for (i = 0; i < num_of_cmds && !ioc_err; i++)
-		ioc_err = __mmc_blk_ioctl_cmd(card, md, idata[i]);
-
-	/* Always switch back to main area after RPMB access */
-	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
-		mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
-
-	mmc_put_card(card);
-
-	/* copy to user if data and response */
-	for (i = 0; i < num_of_cmds && !err; i++)
-		err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
-
-cmd_done:
-	mmc_blk_put(md);
-cmd_err:
-	for (i = 0; i < num_of_cmds; i++) {
-		kfree(idata[i]->buf);
-		kfree(idata[i]);
-	}
-	kfree(idata);
-	return ioc_err ? ioc_err : err;
-}
-
-static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
-	unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case MMC_IOC_CMD:
-		return mmc_blk_ioctl_cmd(bdev,
-				(struct mmc_ioc_cmd __user *)arg);
-	case MMC_IOC_MULTI_CMD:
-		return mmc_blk_ioctl_multi_cmd(bdev,
-				(struct mmc_ioc_multi_cmd __user *)arg);
-	default:
-		return -EINVAL;
-	}
-}
-
-#ifdef CONFIG_COMPAT
-static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
-	unsigned int cmd, unsigned long arg)
-{
-	return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
-}
-#endif
-
-static const struct block_device_operations mmc_bdops = {
-	.open			= mmc_blk_open,
-	.release		= mmc_blk_release,
-	.getgeo			= mmc_blk_getgeo,
-	.owner			= THIS_MODULE,
-	.ioctl			= mmc_blk_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl		= mmc_blk_compat_ioctl,
-#endif
-};
-
-static inline int mmc_blk_part_switch(struct mmc_card *card,
-				      struct mmc_blk_data *md)
-{
-	int ret;
-	struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
-
-	if (main_md->part_curr == md->part_type)
-		return 0;
-
-	if (mmc_card_mmc(card)) {
-		u8 part_config = card->ext_csd.part_config;
-
-		if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
-			mmc_retune_pause(card->host);
-
-		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, part_config,
-				 card->ext_csd.part_time);
-		if (ret) {
-			if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
-				mmc_retune_unpause(card->host);
-			return ret;
-		}
-
-		card->ext_csd.part_config = part_config;
-
-		if (main_md->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB)
-			mmc_retune_unpause(card->host);
-	}
-
-	main_md->part_curr = md->part_type;
-	return 0;
-}
-
-static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
-{
-	int err;
-	u32 result;
-	__be32 *blocks;
-
-	struct mmc_request mrq = {NULL};
-	struct mmc_command cmd = {0};
-	struct mmc_data data = {0};
-
-	struct scatterlist sg;
-
-	cmd.opcode = MMC_APP_CMD;
-	cmd.arg = card->rca << 16;
-	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
-
-	err = mmc_wait_for_cmd(card->host, &cmd, 0);
-	if (err)
-		return (u32)-1;
-	if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
-		return (u32)-1;
-
-	memset(&cmd, 0, sizeof(struct mmc_command));
-
-	cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
-	cmd.arg = 0;
-	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-
-	data.blksz = 4;
-	data.blocks = 1;
-	data.flags = MMC_DATA_READ;
-	data.sg = &sg;
-	data.sg_len = 1;
-	mmc_set_data_timeout(&data, card);
-
-	mrq.cmd = &cmd;
-	mrq.data = &data;
-
-	blocks = kmalloc(4, GFP_KERNEL);
-	if (!blocks)
-		return (u32)-1;
-
-	sg_init_one(&sg, blocks, 4);
-
-	mmc_wait_for_req(card->host, &mrq);
-
-	result = ntohl(*blocks);
-	kfree(blocks);
-
-	if (cmd.error || data.error)
-		result = (u32)-1;
-
-	return result;
-}
-
-static int get_card_status(struct mmc_card *card, u32 *status, int retries)
-{
-	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, retries);
-	if (err == 0)
-		*status = cmd.resp[0];
-	return err;
-}
-
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
-		bool hw_busy_detect, struct request *req, int *gen_err)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-	int err = 0;
-	u32 status;
-
-	do {
-		err = get_card_status(card, &status, 5);
-		if (err) {
-			pr_err("%s: error %d requesting status\n",
-			       req->rq_disk->disk_name, err);
-			return err;
-		}
-
-		if (status & R1_ERROR) {
-			pr_err("%s: %s: error sending status cmd, status %#x\n",
-				req->rq_disk->disk_name, __func__, status);
-			*gen_err = 1;
-		}
-
-		/* We may rely on the host hw to handle busy detection.*/
-		if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) &&
-			hw_busy_detect)
-			break;
-
-		/*
-		 * Timeout if the device never becomes ready for data and never
-		 * leaves the program state.
-		 */
-		if (time_after(jiffies, timeout)) {
-			pr_err("%s: Card stuck in programming state! %s %s\n",
-				mmc_hostname(card->host),
-				req->rq_disk->disk_name, __func__);
-			return -ETIMEDOUT;
-		}
-
-		/*
-		 * Some cards mishandle the status bits,
-		 * so make sure to check both the busy
-		 * indication and the card state.
-		 */
-	} while (!(status & R1_READY_FOR_DATA) ||
-		 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
-
-	return err;
-}
-
-static int send_stop(struct mmc_card *card, unsigned int timeout_ms,
-		struct request *req, int *gen_err, u32 *stop_status)
-{
-	struct mmc_host *host = card->host;
-	struct mmc_command cmd = {0};
-	int err;
-	bool use_r1b_resp = rq_data_dir(req) == WRITE;
-
-	/*
-	 * Normally we use R1B responses for WRITE, but in cases where the host
-	 * has specified a max_busy_timeout we need to validate it. A failure
-	 * means we need to prevent the host from doing hw busy detection, which
-	 * is done by converting to a R1 response instead.
-	 */
-	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
-		use_r1b_resp = false;
-
-	cmd.opcode = MMC_STOP_TRANSMISSION;
-	if (use_r1b_resp) {
-		cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-		cmd.busy_timeout = timeout_ms;
-	} else {
-		cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
-	}
-
-	err = mmc_wait_for_cmd(host, &cmd, 5);
-	if (err)
-		return err;
-
-	*stop_status = cmd.resp[0];
-
-	/* No need to check card status in case of READ. */
-	if (rq_data_dir(req) == READ)
-		return 0;
-
-	if (!mmc_host_is_spi(host) &&
-		(*stop_status & R1_ERROR)) {
-		pr_err("%s: %s: general error sending stop command, resp %#x\n",
-			req->rq_disk->disk_name, __func__, *stop_status);
-		*gen_err = 1;
-	}
-
-	return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err);
-}
-
-#define ERR_NOMEDIUM	3
-#define ERR_RETRY	2
-#define ERR_ABORT	1
-#define ERR_CONTINUE	0
-
-static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
-	bool status_valid, u32 status)
-{
-	switch (error) {
-	case -EILSEQ:
-		/* response crc error, retry the r/w cmd */
-		pr_err("%s: %s sending %s command, card status %#x\n",
-			req->rq_disk->disk_name, "response CRC error",
-			name, status);
-		return ERR_RETRY;
-
-	case -ETIMEDOUT:
-		pr_err("%s: %s sending %s command, card status %#x\n",
-			req->rq_disk->disk_name, "timed out", name, status);
-
-		/* If the status cmd initially failed, retry the r/w cmd */
-		if (!status_valid) {
-			pr_err("%s: status not valid, retrying timeout\n",
-				req->rq_disk->disk_name);
-			return ERR_RETRY;
-		}
-
-		/*
-		 * If it was a r/w cmd crc error, or illegal command
-		 * (eg, issued in wrong state) then retry - we should
-		 * have corrected the state problem above.
-		 */
-		if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) {
-			pr_err("%s: command error, retrying timeout\n",
-				req->rq_disk->disk_name);
-			return ERR_RETRY;
-		}
-
-		/* Otherwise abort the command */
-		return ERR_ABORT;
-
-	default:
-		/* We don't understand the error code the driver gave us */
-		pr_err("%s: unknown error %d sending read/write command, card status %#x\n",
-		       req->rq_disk->disk_name, error, status);
-		return ERR_ABORT;
-	}
-}
-
-/*
- * Initial r/w and stop cmd error recovery.
- * We don't know whether the card received the r/w cmd or not, so try to
- * restore things back to a sane state.  Essentially, we do this as follows:
- * - Obtain card status.  If the first attempt to obtain card status fails,
- *   the status word will reflect the failed status cmd, not the failed
- *   r/w cmd.  If we fail to obtain card status, it suggests we can no
- *   longer communicate with the card.
- * - Check the card state.  If the card received the cmd but there was a
- *   transient problem with the response, it might still be in a data transfer
- *   mode.  Try to send it a stop command.  If this fails, we can't recover.
- * - If the r/w cmd failed due to a response CRC error, it was probably
- *   transient, so retry the cmd.
- * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry.
- * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or
- *   illegal cmd, retry.
- * 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, int *ecc_err, int *gen_err)
-{
-	bool prev_cmd_status_valid = true;
-	u32 status, stop_status = 0;
-	int err, retry;
-
-	if (mmc_card_removed(card))
-		return ERR_NOMEDIUM;
-
-	/*
-	 * Try to get card status which indicates both the card state
-	 * and why there was no response.  If the first attempt fails,
-	 * we can't be sure the returned status is for the r/w command.
-	 */
-	for (retry = 2; retry >= 0; retry--) {
-		err = get_card_status(card, &status, 0);
-		if (!err)
-			break;
-
-		/* Re-tune if needed */
-		mmc_retune_recheck(card->host);
-
-		prev_cmd_status_valid = false;
-		pr_err("%s: error %d sending status command, %sing\n",
-		       req->rq_disk->disk_name, err, retry ? "retry" : "abort");
-	}
-
-	/* We couldn't get a response from the card.  Give up. */
-	if (err) {
-		/* Check if the card is removed */
-		if (mmc_detect_card_removed(card->host))
-			return ERR_NOMEDIUM;
-		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;
-
-	/* Flag General errors */
-	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
-		if ((status & R1_ERROR) ||
-			(brq->stop.resp[0] & R1_ERROR)) {
-			pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
-			       req->rq_disk->disk_name, __func__,
-			       brq->stop.resp[0], status);
-			*gen_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.)
-	 */
-	if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
-	    R1_CURRENT_STATE(status) == R1_STATE_RCV) {
-		err = send_stop(card,
-			DIV_ROUND_UP(brq->data.timeout_ns, 1000000),
-			req, gen_err, &stop_status);
-		if (err) {
-			pr_err("%s: error %d sending stop command\n",
-			       req->rq_disk->disk_name, err);
-			/*
-			 * If the stop cmd also timed out, the card is probably
-			 * not present, so abort. Other errors are bad news too.
-			 */
-			return ERR_ABORT;
-		}
-
-		if (stop_status & R1_CARD_ECC_FAILED)
-			*ecc_err = 1;
-	}
-
-	/* Check for set block count errors */
-	if (brq->sbc.error)
-		return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error,
-				prev_cmd_status_valid, status);
-
-	/* Check for r/w command errors */
-	if (brq->cmd.error)
-		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_info("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
-	       req->rq_disk->disk_name, brq->stop.error,
-	       brq->cmd.resp[0], status);
-
-	/*
-	 * Subsitute in our own stop status as this will give the error
-	 * state which happened during the execution of the r/w command.
-	 */
-	if (stop_status) {
-		brq->stop.resp[0] = stop_status;
-		brq->stop.error = 0;
-	}
-	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 =
-			dev_get_drvdata(&host->card->dev);
-		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;
-}
-
-int mmc_access_rpmb(struct mmc_queue *mq)
-{
-	struct mmc_blk_data *md = mq->data;
-	/*
-	 * If this is a RPMB partition access, return ture
-	 */
-	if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
-		return true;
-
-	return false;
-}
-
-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, type = MMC_BLK_DISCARD;
-
-	if (!mmc_can_erase(card)) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	from = blk_rq_pos(req);
-	nr = blk_rq_sectors(req);
-
-	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,
-				 arg == MMC_TRIM_ARG ?
-				 INAND_CMD38_ARG_TRIM :
-				 INAND_CMD38_ARG_ERASE,
-				 0);
-		if (err)
-			goto out;
-	}
-	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);
-	blk_end_request(req, err, blk_rq_bytes(req));
-
-	return err ? 0 : 1;
-}
-
-static int mmc_blk_issue_secdiscard_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, type = MMC_BLK_SECDISCARD;
-
-	if (!(mmc_can_secure_erase_trim(card))) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
-
-	from = blk_rq_pos(req);
-	nr = blk_rq_sectors(req);
-
-	if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
-		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,
-				 arg == MMC_SECURE_TRIM1_ARG ?
-				 INAND_CMD38_ARG_SECTRIM1 :
-				 INAND_CMD38_ARG_SECERASE,
-				 0);
-		if (err)
-			goto out_retry;
-	}
-
-	err = mmc_erase(card, from, nr, arg);
-	if (err == -EIO)
-		goto out_retry;
-	if (err)
-		goto out;
-
-	if (arg == MMC_SECURE_TRIM1_ARG) {
-		if (card->quirks & MMC_QUIRK_INAND_CMD38) {
-			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-					 INAND_CMD38_ARG_EXT_CSD,
-					 INAND_CMD38_ARG_SECTRIM2,
-					 0);
-			if (err)
-				goto out_retry;
-		}
-
-		err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
-		if (err == -EIO)
-			goto out_retry;
-		if (err)
-			goto out;
-	}
-
-out_retry:
-	if (err && !mmc_blk_reset(md, card->host, type))
-		goto retry;
-	if (!err)
-		mmc_blk_reset_success(md, type);
-out:
-	blk_end_request(req, err, blk_rq_bytes(req));
-
-	return err ? 0 : 1;
-}
-
-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;
-
-	blk_end_request_all(req, ret);
-
-	return ret ? 0 : 1;
-}
-
-/*
- * Reformat current write as a reliable write, supporting
- * both legacy and the enhanced reliable write MMC cards.
- * In each transfer we'll handle only as much as a single
- * reliable write can handle, thus finish the request in
- * partial completions.
- */
-static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
-				    struct mmc_card *card,
-				    struct request *req)
-{
-	if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
-		/* Legacy mode imposes restrictions on transfers. */
-		if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors))
-			brq->data.blocks = 1;
-
-		if (brq->data.blocks > card->ext_csd.rel_sectors)
-			brq->data.blocks = card->ext_csd.rel_sectors;
-		else if (brq->data.blocks < card->ext_csd.rel_sectors)
-			brq->data.blocks = 1;
-	}
-}
-
-#define CMD_ERRORS							\
-	(R1_OUT_OF_RANGE |	/* Command argument out of range */	\
-	 R1_ADDRESS_ERROR |	/* Misaligned address */		\
-	 R1_BLOCK_LEN_ERROR |	/* Transferred block length incorrect */\
-	 R1_WP_VIOLATION |	/* Tried to write to protected block */	\
-	 R1_CC_ERROR |		/* Card controller error */		\
-	 R1_ERROR)		/* General/unknown error */
-
-static int mmc_blk_err_check(struct mmc_card *card,
-			     struct mmc_async_req *areq)
-{
-	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 need_retune = card->host->need_retune;
-	int ecc_err = 0, gen_err = 0;
-
-	/*
-	 * sbc.error indicates a problem with the set block count
-	 * command.  No data will have been transferred.
-	 *
-	 * cmd.error indicates a problem with the r/w command.  No
-	 * data will have been transferred.
-	 *
-	 * 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 ||
-	    brq->data.error) {
-		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
-		case ERR_RETRY:
-			return MMC_BLK_RETRY;
-		case ERR_ABORT:
-			return MMC_BLK_ABORT;
-		case ERR_NOMEDIUM:
-			return MMC_BLK_NOMEDIUM;
-		case ERR_CONTINUE:
-			break;
-		}
-	}
-
-	/*
-	 * Check for errors relating to the execution of the
-	 * initial command - such as address errors.  No data
-	 * has been transferred.
-	 */
-	if (brq->cmd.resp[0] & CMD_ERRORS) {
-		pr_err("%s: r/w command failed, status = %#x\n",
-		       req->rq_disk->disk_name, brq->cmd.resp[0]);
-		return MMC_BLK_ABORT;
-	}
-
-	/*
-	 * Everything else is either success, or a data error of some
-	 * kind.  If it was a write, we may have transitioned to
-	 * program mode, which we have to wait for it to complete.
-	 */
-	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
-		int err;
-
-		/* Check stop command response */
-		if (brq->stop.resp[0] & R1_ERROR) {
-			pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
-			       req->rq_disk->disk_name, __func__,
-			       brq->stop.resp[0]);
-			gen_err = 1;
-		}
-
-		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req,
-					&gen_err);
-		if (err)
-			return MMC_BLK_CMD_ERR;
-	}
-
-	/* if general error occurs, retry the write operation. */
-	if (gen_err) {
-		pr_warn("%s: retrying write for general error\n",
-				req->rq_disk->disk_name);
-		return MMC_BLK_RETRY;
-	}
-
-	if (brq->data.error) {
-		if (need_retune && !brq->retune_retry_done) {
-			pr_debug("%s: retrying because a re-tune was needed\n",
-				 req->rq_disk->disk_name);
-			brq->retune_retry_done = 1;
-			return MMC_BLK_RETRY;
-		}
-		pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
-		       req->rq_disk->disk_name, brq->data.error,
-		       (unsigned)blk_rq_pos(req),
-		       (unsigned)blk_rq_sectors(req),
-		       brq->cmd.resp[0], brq->stop.resp[0]);
-
-		if (rq_data_dir(req) == READ) {
-			if (ecc_err)
-				return MMC_BLK_ECC_ERR;
-			return MMC_BLK_DATA_ERR;
-		} else {
-			return MMC_BLK_CMD_ERR;
-		}
-	}
-
-	if (!brq->data.bytes_xfered)
-		return MMC_BLK_RETRY;
-
-	if (mmc_packed_cmd(mq_mrq->cmd_type)) {
-		if (unlikely(brq->data.blocks << 9 != brq->data.bytes_xfered))
-			return MMC_BLK_PARTIAL;
-		else
-			return MMC_BLK_SUCCESS;
-	}
-
-	if (blk_rq_bytes(req) != brq->data.bytes_xfered)
-		return MMC_BLK_PARTIAL;
-
-	return MMC_BLK_SUCCESS;
-}
-
-static int mmc_blk_packed_err_check(struct mmc_card *card,
-				    struct mmc_async_req *areq)
-{
-	struct mmc_queue_req *mq_rq = container_of(areq, struct mmc_queue_req,
-			mmc_active);
-	struct request *req = mq_rq->req;
-	struct mmc_packed *packed = mq_rq->packed;
-	int err, check, status;
-	u8 *ext_csd;
-
-	packed->retries--;
-	check = mmc_blk_err_check(card, areq);
-	err = get_card_status(card, &status, 0);
-	if (err) {
-		pr_err("%s: error %d sending status command\n",
-		       req->rq_disk->disk_name, err);
-		return MMC_BLK_ABORT;
-	}
-
-	if (status & R1_EXCEPTION_EVENT) {
-		err = mmc_get_ext_csd(card, &ext_csd);
-		if (err) {
-			pr_err("%s: error %d sending ext_csd\n",
-			       req->rq_disk->disk_name, err);
-			return MMC_BLK_ABORT;
-		}
-
-		if ((ext_csd[EXT_CSD_EXP_EVENTS_STATUS] &
-		     EXT_CSD_PACKED_FAILURE) &&
-		    (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
-		     EXT_CSD_PACKED_GENERIC_ERROR)) {
-			if (ext_csd[EXT_CSD_PACKED_CMD_STATUS] &
-			    EXT_CSD_PACKED_INDEXED_ERROR) {
-				packed->idx_failure =
-				  ext_csd[EXT_CSD_PACKED_FAILURE_INDEX] - 1;
-				check = MMC_BLK_PARTIAL;
-			}
-			pr_err("%s: packed cmd failed, nr %u, sectors %u, "
-			       "failure index: %d\n",
-			       req->rq_disk->disk_name, packed->nr_entries,
-			       packed->blocks, packed->idx_failure);
-		}
-		kfree(ext_csd);
-	}
-
-	return check;
-}
-
-static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
-			       struct mmc_card *card,
-			       int disable_multi,
-			       struct mmc_queue *mq)
-{
-	u32 readcmd, writecmd;
-	struct mmc_blk_request *brq = &mqrq->brq;
-	struct request *req = mqrq->req;
-	struct mmc_blk_data *md = mq->data;
-	bool do_data_tag;
-
-	/*
-	 * Reliable writes are used to implement Forced Unit Access and
-	 * are supported only on MMCs.
-	 */
-	bool do_rel_wr = (req->cmd_flags & REQ_FUA) &&
-		(rq_data_dir(req) == WRITE) &&
-		(md->flags & MMC_BLK_REL_WR);
-
-	memset(brq, 0, sizeof(struct mmc_blk_request));
-	brq->mrq.cmd = &brq->cmd;
-	brq->mrq.data = &brq->data;
-
-	brq->cmd.arg = blk_rq_pos(req);
-	if (!mmc_card_blockaddr(card))
-		brq->cmd.arg <<= 9;
-	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-	brq->data.blksz = 512;
-	brq->stop.opcode = MMC_STOP_TRANSMISSION;
-	brq->stop.arg = 0;
-	brq->data.blocks = blk_rq_sectors(req);
-
-	/*
-	 * The block layer doesn't support all sector count
-	 * restrictions, so we need to be prepared for too big
-	 * requests.
-	 */
-	if (brq->data.blocks > card->host->max_blk_count)
-		brq->data.blocks = card->host->max_blk_count;
-
-	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 have HW issues while operating
-		 * in multiple I/O mode
-		 */
-		if (card->host->ops->multi_io_quirk)
-			brq->data.blocks = card->host->ops->multi_io_quirk(card,
-						(rq_data_dir(req) == READ) ?
-						MMC_DATA_READ : MMC_DATA_WRITE,
-						brq->data.blocks);
-	}
-
-	if (brq->data.blocks > 1 || do_rel_wr) {
-		/* SPI multiblock writes terminate using a special
-		 * token, not a STOP_TRANSMISSION request.
-		 */
-		if (!mmc_host_is_spi(card->host) ||
-		    rq_data_dir(req) == READ)
-			brq->mrq.stop = &brq->stop;
-		readcmd = MMC_READ_MULTIPLE_BLOCK;
-		writecmd = MMC_WRITE_MULTIPLE_BLOCK;
-	} else {
-		brq->mrq.stop = NULL;
-		readcmd = MMC_READ_SINGLE_BLOCK;
-		writecmd = MMC_WRITE_BLOCK;
-	}
-	if (rq_data_dir(req) == READ) {
-		brq->cmd.opcode = readcmd;
-		brq->data.flags = MMC_DATA_READ;
-		if (brq->mrq.stop)
-			brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |
-					MMC_CMD_AC;
-	} else {
-		brq->cmd.opcode = writecmd;
-		brq->data.flags = MMC_DATA_WRITE;
-		if (brq->mrq.stop)
-			brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B |
-					MMC_CMD_AC;
-	}
-
-	if (do_rel_wr)
-		mmc_apply_rel_rw(brq, card, req);
-
-	/*
-	 * Data tag is used only during writing meta data to speed
-	 * up write and any subsequent read of this meta data
-	 */
-	do_data_tag = (card->ext_csd.data_tag_unit_size) &&
-		(req->cmd_flags & REQ_META) &&
-		(rq_data_dir(req) == WRITE) &&
-		((brq->data.blocks * brq->data.blksz) >=
-		 card->ext_csd.data_tag_unit_size);
-
-	/*
-	 * Pre-defined multi-block transfers are preferable to
-	 * open ended-ones (and necessary for reliable writes).
-	 * However, it is not sufficient to just send CMD23,
-	 * and avoid the final CMD12, as on an error condition
-	 * CMD12 (stop) needs to be sent anyway. This, coupled
-	 * with Auto-CMD23 enhancements provided by some
-	 * hosts, means that the complexity of dealing
-	 * with this is best left to the host. If CMD23 is
-	 * supported by card and host, we'll fill sbc in and let
-	 * the host deal with handling it correctly. This means
-	 * that for hosts that don't expose MMC_CAP_CMD23, no
-	 * change of behavior will be observed.
-	 *
-	 * N.B: Some MMC cards experience perf degradation.
-	 * We'll avoid using CMD23-bounded multiblock writes for
-	 * these, while retaining features like reliable writes.
-	 */
-	if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) &&
-	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) ||
-	     do_data_tag)) {
-		brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
-		brq->sbc.arg = brq->data.blocks |
-			(do_rel_wr ? (1 << 31) : 0) |
-			(do_data_tag ? (1 << 29) : 0);
-		brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
-		brq->mrq.sbc = &brq->sbc;
-	}
-
-	mmc_set_data_timeout(&brq->data, card);
-
-	brq->data.sg = mqrq->sg;
-	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
-
-	/*
-	 * Adjust the sg list so it is the same size as the
-	 * request.
-	 */
-	if (brq->data.blocks != blk_rq_sectors(req)) {
-		int i, data_size = brq->data.blocks << 9;
-		struct scatterlist *sg;
-
-		for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
-			data_size -= sg->length;
-			if (data_size <= 0) {
-				sg->length += data_size;
-				i++;
-				break;
-			}
-		}
-		brq->data.sg_len = i;
-	}
-
-	mqrq->mmc_active.mrq = &brq->mrq;
-	mqrq->mmc_active.err_check = mmc_blk_err_check;
-
-	mmc_queue_bounce_pre(mqrq);
-}
-
-static inline u8 mmc_calc_packed_hdr_segs(struct request_queue *q,
-					  struct mmc_card *card)
-{
-	unsigned int hdr_sz = mmc_large_sector(card) ? 4096 : 512;
-	unsigned int max_seg_sz = queue_max_segment_size(q);
-	unsigned int len, nr_segs = 0;
-
-	do {
-		len = min(hdr_sz, max_seg_sz);
-		hdr_sz -= len;
-		nr_segs++;
-	} while (hdr_sz);
-
-	return nr_segs;
-}
-
-static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req)
-{
-	struct request_queue *q = mq->queue;
-	struct mmc_card *card = mq->card;
-	struct request *cur = req, *next = NULL;
-	struct mmc_blk_data *md = mq->data;
-	struct mmc_queue_req *mqrq = mq->mqrq_cur;
-	bool en_rel_wr = card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN;
-	unsigned int req_sectors = 0, phys_segments = 0;
-	unsigned int max_blk_count, max_phys_segs;
-	bool put_back = true;
-	u8 max_packed_rw = 0;
-	u8 reqs = 0;
-
-	/*
-	 * We don't need to check packed for any further
-	 * operation of packed stuff as we set MMC_PACKED_NONE
-	 * and return zero for reqs if geting null packed. Also
-	 * we clean the flag of MMC_BLK_PACKED_CMD to avoid doing
-	 * it again when removing blk req.
-	 */
-	if (!mqrq->packed) {
-		md->flags &= (~MMC_BLK_PACKED_CMD);
-		goto no_packed;
-	}
-
-	if (!(md->flags & MMC_BLK_PACKED_CMD))
-		goto no_packed;
-
-	if ((rq_data_dir(cur) == WRITE) &&
-	    mmc_host_packed_wr(card->host))
-		max_packed_rw = card->ext_csd.max_packed_writes;
-
-	if (max_packed_rw == 0)
-		goto no_packed;
-
-	if (mmc_req_rel_wr(cur) &&
-	    (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
-		goto no_packed;
-
-	if (mmc_large_sector(card) &&
-	    !IS_ALIGNED(blk_rq_sectors(cur), 8))
-		goto no_packed;
-
-	mmc_blk_clear_packed(mqrq);
-
-	max_blk_count = min(card->host->max_blk_count,
-			    card->host->max_req_size >> 9);
-	if (unlikely(max_blk_count > 0xffff))
-		max_blk_count = 0xffff;
-
-	max_phys_segs = queue_max_segments(q);
-	req_sectors += blk_rq_sectors(cur);
-	phys_segments += cur->nr_phys_segments;
-
-	if (rq_data_dir(cur) == WRITE) {
-		req_sectors += mmc_large_sector(card) ? 8 : 1;
-		phys_segments += mmc_calc_packed_hdr_segs(q, card);
-	}
-
-	do {
-		if (reqs >= max_packed_rw - 1) {
-			put_back = false;
-			break;
-		}
-
-		spin_lock_irq(q->queue_lock);
-		next = blk_fetch_request(q);
-		spin_unlock_irq(q->queue_lock);
-		if (!next) {
-			put_back = false;
-			break;
-		}
-
-		if (mmc_large_sector(card) &&
-		    !IS_ALIGNED(blk_rq_sectors(next), 8))
-			break;
-
-		if (req_op(next) == REQ_OP_DISCARD ||
-		    req_op(next) == REQ_OP_SECURE_ERASE ||
-		    req_op(next) == REQ_OP_FLUSH)
-			break;
-
-		if (rq_data_dir(cur) != rq_data_dir(next))
-			break;
-
-		if (mmc_req_rel_wr(next) &&
-		    (md->flags & MMC_BLK_REL_WR) && !en_rel_wr)
-			break;
-
-		req_sectors += blk_rq_sectors(next);
-		if (req_sectors > max_blk_count)
-			break;
-
-		phys_segments +=  next->nr_phys_segments;
-		if (phys_segments > max_phys_segs)
-			break;
-
-		list_add_tail(&next->queuelist, &mqrq->packed->list);
-		cur = next;
-		reqs++;
-	} while (1);
-
-	if (put_back) {
-		spin_lock_irq(q->queue_lock);
-		blk_requeue_request(q, next);
-		spin_unlock_irq(q->queue_lock);
-	}
-
-	if (reqs > 0) {
-		list_add(&req->queuelist, &mqrq->packed->list);
-		mqrq->packed->nr_entries = ++reqs;
-		mqrq->packed->retries = reqs;
-		return reqs;
-	}
-
-no_packed:
-	mqrq->cmd_type = MMC_PACKED_NONE;
-	return 0;
-}
-
-static void mmc_blk_packed_hdr_wrq_prep(struct mmc_queue_req *mqrq,
-					struct mmc_card *card,
-					struct mmc_queue *mq)
-{
-	struct mmc_blk_request *brq = &mqrq->brq;
-	struct request *req = mqrq->req;
-	struct request *prq;
-	struct mmc_blk_data *md = mq->data;
-	struct mmc_packed *packed = mqrq->packed;
-	bool do_rel_wr, do_data_tag;
-	__le32 *packed_cmd_hdr;
-	u8 hdr_blocks;
-	u8 i = 1;
-
-	mqrq->cmd_type = MMC_PACKED_WRITE;
-	packed->blocks = 0;
-	packed->idx_failure = MMC_PACKED_NR_IDX;
-
-	packed_cmd_hdr = packed->cmd_hdr;
-	memset(packed_cmd_hdr, 0, sizeof(packed->cmd_hdr));
-	packed_cmd_hdr[0] = cpu_to_le32((packed->nr_entries << 16) |
-		(PACKED_CMD_WR << 8) | PACKED_CMD_VER);
-	hdr_blocks = mmc_large_sector(card) ? 8 : 1;
-
-	/*
-	 * Argument for each entry of packed group
-	 */
-	list_for_each_entry(prq, &packed->list, queuelist) {
-		do_rel_wr = mmc_req_rel_wr(prq) && (md->flags & MMC_BLK_REL_WR);
-		do_data_tag = (card->ext_csd.data_tag_unit_size) &&
-			(prq->cmd_flags & REQ_META) &&
-			(rq_data_dir(prq) == WRITE) &&
-			blk_rq_bytes(prq) >= card->ext_csd.data_tag_unit_size;
-		/* Argument of CMD23 */
-		packed_cmd_hdr[(i * 2)] = cpu_to_le32(
-			(do_rel_wr ? MMC_CMD23_ARG_REL_WR : 0) |
-			(do_data_tag ? MMC_CMD23_ARG_TAG_REQ : 0) |
-			blk_rq_sectors(prq));
-		/* Argument of CMD18 or CMD25 */
-		packed_cmd_hdr[((i * 2)) + 1] = cpu_to_le32(
-			mmc_card_blockaddr(card) ?
-			blk_rq_pos(prq) : blk_rq_pos(prq) << 9);
-		packed->blocks += blk_rq_sectors(prq);
-		i++;
-	}
-
-	memset(brq, 0, sizeof(struct mmc_blk_request));
-	brq->mrq.cmd = &brq->cmd;
-	brq->mrq.data = &brq->data;
-	brq->mrq.sbc = &brq->sbc;
-	brq->mrq.stop = &brq->stop;
-
-	brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
-	brq->sbc.arg = MMC_CMD23_ARG_PACKED | (packed->blocks + hdr_blocks);
-	brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-	brq->cmd.opcode = MMC_WRITE_MULTIPLE_BLOCK;
-	brq->cmd.arg = blk_rq_pos(req);
-	if (!mmc_card_blockaddr(card))
-		brq->cmd.arg <<= 9;
-	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-
-	brq->data.blksz = 512;
-	brq->data.blocks = packed->blocks + hdr_blocks;
-	brq->data.flags = MMC_DATA_WRITE;
-
-	brq->stop.opcode = MMC_STOP_TRANSMISSION;
-	brq->stop.arg = 0;
-	brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-
-	mmc_set_data_timeout(&brq->data, card);
-
-	brq->data.sg = mqrq->sg;
-	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
-
-	mqrq->mmc_active.mrq = &brq->mrq;
-	mqrq->mmc_active.err_check = mmc_blk_packed_err_check;
-
-	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)
-{
-	struct mmc_queue_req *mq_rq;
-	mq_rq = container_of(brq, struct mmc_queue_req, brq);
-
-	/*
-	 * 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) {
-			ret = blk_end_request(req, 0, blocks << 9);
-		}
-	} else {
-		if (!mmc_packed_cmd(mq_rq->cmd_type))
-			ret = blk_end_request(req, 0, brq->data.bytes_xfered);
-	}
-	return ret;
-}
-
-static int mmc_blk_end_packed_req(struct mmc_queue_req *mq_rq)
-{
-	struct request *prq;
-	struct mmc_packed *packed = mq_rq->packed;
-	int idx = packed->idx_failure, i = 0;
-	int ret = 0;
-
-	while (!list_empty(&packed->list)) {
-		prq = list_entry_rq(packed->list.next);
-		if (idx == i) {
-			/* retry from error index */
-			packed->nr_entries -= idx;
-			mq_rq->req = prq;
-			ret = 1;
-
-			if (packed->nr_entries == MMC_PACKED_NR_SINGLE) {
-				list_del_init(&prq->queuelist);
-				mmc_blk_clear_packed(mq_rq);
-			}
-			return ret;
-		}
-		list_del_init(&prq->queuelist);
-		blk_end_request(prq, 0, blk_rq_bytes(prq));
-		i++;
-	}
-
-	mmc_blk_clear_packed(mq_rq);
-	return ret;
-}
-
-static void mmc_blk_abort_packed_req(struct mmc_queue_req *mq_rq)
-{
-	struct request *prq;
-	struct mmc_packed *packed = mq_rq->packed;
-
-	while (!list_empty(&packed->list)) {
-		prq = list_entry_rq(packed->list.next);
-		list_del_init(&prq->queuelist);
-		blk_end_request(prq, -EIO, blk_rq_bytes(prq));
-	}
-
-	mmc_blk_clear_packed(mq_rq);
-}
-
-static void mmc_blk_revert_packed_req(struct mmc_queue *mq,
-				      struct mmc_queue_req *mq_rq)
-{
-	struct request *prq;
-	struct request_queue *q = mq->queue;
-	struct mmc_packed *packed = mq_rq->packed;
-
-	while (!list_empty(&packed->list)) {
-		prq = list_entry_rq(packed->list.prev);
-		if (prq->queuelist.prev != &packed->list) {
-			list_del_init(&prq->queuelist);
-			spin_lock_irq(q->queue_lock);
-			blk_requeue_request(mq->queue, prq);
-			spin_unlock_irq(q->queue_lock);
-		} else {
-			list_del_init(&prq->queuelist);
-		}
-	}
-
-	mmc_blk_clear_packed(mq_rq);
-}
-
-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, type, retune_retry_done = 0;
-	enum mmc_blk_status status;
-	struct mmc_queue_req *mq_rq;
-	struct request *req = rqc;
-	struct mmc_async_req *areq;
-	const u8 packed_nr = 2;
-	u8 reqs = 0;
-
-	if (!rqc && !mq->mqrq_prev->req)
-		return 0;
-
-	if (rqc)
-		reqs = mmc_blk_prep_packed_list(mq, rqc);
-
-	do {
-		if (rqc) {
-			/*
-			 * When 4KB native sector is enabled, only 8 blocks
-			 * multiple read or write is allowed
-			 */
-			if (mmc_large_sector(card) &&
-				!IS_ALIGNED(blk_rq_sectors(rqc), 8)) {
-				pr_err("%s: Transfer size is not 4KB sector size aligned\n",
-					req->rq_disk->disk_name);
-				mq_rq = mq->mqrq_cur;
-				goto cmd_abort;
-			}
-
-			if (reqs >= packed_nr)
-				mmc_blk_packed_hdr_wrq_prep(mq->mqrq_cur,
-							    card, mq);
-			else
-				mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
-			areq = &mq->mqrq_cur->mmc_active;
-		} else
-			areq = NULL;
-		areq = mmc_start_req(card->host, areq, (int *) &status);
-		if (!areq) {
-			if (status == MMC_BLK_NEW_REQUEST)
-				mq->flags |= MMC_QUEUE_NEW_REQUEST;
-			return 0;
-		}
-
-		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) {
-		case MMC_BLK_SUCCESS:
-		case MMC_BLK_PARTIAL:
-			/*
-			 * A block was successfully transferred.
-			 */
-			mmc_blk_reset_success(md, type);
-
-			if (mmc_packed_cmd(mq_rq->cmd_type)) {
-				ret = mmc_blk_end_packed_req(mq_rq);
-				break;
-			} else {
-				ret = blk_end_request(req, 0,
-						brq->data.bytes_xfered);
-			}
-
-			/*
-			 * 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) {
-				pr_err("%s BUG rq_tot %d d_xfer %d\n",
-				       __func__, blk_rq_bytes(req),
-				       brq->data.bytes_xfered);
-				rqc = NULL;
-				goto cmd_abort;
-			}
-			break;
-		case MMC_BLK_CMD_ERR:
-			ret = mmc_blk_cmd_err(md, card, brq, req, ret);
-			if (mmc_blk_reset(md, card->host, type))
-				goto cmd_abort;
-			if (!ret)
-				goto start_new_req;
-			break;
-		case MMC_BLK_RETRY:
-			retune_retry_done = brq->retune_retry_done;
-			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: {
-			int err;
-
-			err = mmc_blk_reset(md, card->host, type);
-			if (!err)
-				break;
-			if (err == -ENODEV ||
-				mmc_packed_cmd(mq_rq->cmd_type))
-				goto cmd_abort;
-			/* Fall through */
-		}
-		case MMC_BLK_ECC_ERR:
-			if (brq->data.blocks > 1) {
-				/* Redo read one sector at a time */
-				pr_warn("%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
-			 * read a single sector.
-			 */
-			ret = blk_end_request(req, -EIO,
-						brq->data.blksz);
-			if (!ret)
-				goto start_new_req;
-			break;
-		case MMC_BLK_NOMEDIUM:
-			goto cmd_abort;
-		default:
-			pr_err("%s: Unhandled return value (%d)",
-					req->rq_disk->disk_name, status);
-			goto cmd_abort;
-		}
-
-		if (ret) {
-			if (mmc_packed_cmd(mq_rq->cmd_type)) {
-				if (!mq_rq->packed->retries)
-					goto cmd_abort;
-				mmc_blk_packed_hdr_wrq_prep(mq_rq, card, mq);
-				mmc_start_req(card->host,
-					      &mq_rq->mmc_active, NULL);
-			} else {
-
-				/*
-				 * In case of a incomplete request
-				 * prepare it again and resend.
-				 */
-				mmc_blk_rw_rq_prep(mq_rq, card,
-						disable_multi, mq);
-				mmc_start_req(card->host,
-						&mq_rq->mmc_active, NULL);
-			}
-			mq_rq->brq.retune_retry_done = retune_retry_done;
-		}
-	} while (ret);
-
-	return 1;
-
- cmd_abort:
-	if (mmc_packed_cmd(mq_rq->cmd_type)) {
-		mmc_blk_abort_packed_req(mq_rq);
-	} else {
-		if (mmc_card_removed(card))
-			req->cmd_flags |= REQ_QUIET;
-		while (ret)
-			ret = blk_end_request(req, -EIO,
-					blk_rq_cur_bytes(req));
-	}
-
- start_new_req:
-	if (rqc) {
-		if (mmc_card_removed(card)) {
-			rqc->cmd_flags |= REQ_QUIET;
-			blk_end_request_all(rqc, -EIO);
-		} else {
-			/*
-			 * If current request is packed, it needs to put back.
-			 */
-			if (mmc_packed_cmd(mq->mqrq_cur->cmd_type))
-				mmc_blk_revert_packed_req(mq, mq->mqrq_cur);
-
-			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
-			mmc_start_req(card->host,
-				      &mq->mqrq_cur->mmc_active, NULL);
-		}
-	}
-
-	return 0;
-}
-
-int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
-{
-	int ret;
-	struct mmc_blk_data *md = mq->data;
-	struct mmc_card *card = md->queue.card;
-	struct mmc_host *host = card->host;
-	unsigned long flags;
-	bool req_is_special = mmc_req_is_special(req);
-
-	if (req && !mq->mqrq_prev->req)
-		/* claim host only for the first request */
-		mmc_get_card(card);
-
-	ret = mmc_blk_part_switch(card, md);
-	if (ret) {
-		if (req) {
-			blk_end_request_all(req, -EIO);
-		}
-		ret = 0;
-		goto out;
-	}
-
-	mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
-	if (req && req_op(req) == REQ_OP_DISCARD) {
-		/* complete ongoing async transfer before issuing discard */
-		if (card->host->areq)
-			mmc_blk_issue_rw_rq(mq, NULL);
-		ret = mmc_blk_issue_discard_rq(mq, req);
-	} else if (req && req_op(req) == REQ_OP_SECURE_ERASE) {
-		/* complete ongoing async transfer before issuing secure erase*/
-		if (card->host->areq)
-			mmc_blk_issue_rw_rq(mq, NULL);
-		ret = mmc_blk_issue_secdiscard_rq(mq, req);
-	} else if (req && req_op(req) == REQ_OP_FLUSH) {
-		/* complete ongoing async transfer before issuing flush */
-		if (card->host->areq)
-			mmc_blk_issue_rw_rq(mq, NULL);
-		ret = mmc_blk_issue_flush(mq, req);
-	} else {
-		if (!req && host->areq) {
-			spin_lock_irqsave(&host->context_info.lock, flags);
-			host->context_info.is_waiting_last_req = true;
-			spin_unlock_irqrestore(&host->context_info.lock, flags);
-		}
-		ret = mmc_blk_issue_rw_rq(mq, req);
-	}
-
-out:
-	if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || req_is_special)
-		/*
-		 * Release host when there are no more requests
-		 * and after special request(discard, flush) is done.
-		 * In case sepecial request, there is no reentry to
-		 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
-		 */
-		mmc_put_card(card);
-	return ret;
-}
-
-static inline int mmc_blk_readonly(struct mmc_card *card)
-{
-	return mmc_card_readonly(card) ||
-	       !(card->csd.cmdclass & CCC_BLOCK_WRITE);
-}
-
-static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
-					      struct device *parent,
-					      sector_t size,
-					      bool default_ro,
-					      const char *subname,
-					      int area_type)
-{
-	struct mmc_blk_data *md;
-	int devidx, ret;
-
-again:
-	if (!ida_pre_get(&mmc_blk_ida, GFP_KERNEL))
-		return ERR_PTR(-ENOMEM);
-
-	spin_lock(&mmc_blk_lock);
-	ret = ida_get_new(&mmc_blk_ida, &devidx);
-	spin_unlock(&mmc_blk_lock);
-
-	if (ret == -EAGAIN)
-		goto again;
-	else if (ret)
-		return ERR_PTR(ret);
-
-	if (devidx >= max_devices) {
-		ret = -ENOSPC;
-		goto out;
-	}
-
-	md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
-	if (!md) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	md->area_type = area_type;
-
-	/*
-	 * Set the read-only status based on the supported commands
-	 * and the write protect switch.
-	 */
-	md->read_only = mmc_blk_readonly(card);
-
-	md->disk = alloc_disk(perdev_minors);
-	if (md->disk == NULL) {
-		ret = -ENOMEM;
-		goto err_kfree;
-	}
-
-	spin_lock_init(&md->lock);
-	INIT_LIST_HEAD(&md->part);
-	md->usage = 1;
-
-	ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
-	if (ret)
-		goto err_putdisk;
-
-	md->queue.data = md;
-
-	md->disk->major	= MMC_BLOCK_MAJOR;
-	md->disk->first_minor = devidx * perdev_minors;
-	md->disk->fops = &mmc_bdops;
-	md->disk->private_data = md;
-	md->disk->queue = md->queue.queue;
-	md->parent = parent;
-	set_disk_ro(md->disk, md->read_only || default_ro);
-	md->disk->flags = GENHD_FL_EXT_DEVT;
-	if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT))
-		md->disk->flags |= GENHD_FL_NO_PART_SCAN;
-
-	/*
-	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
-	 *
-	 * - be set for removable media with permanent block devices
-	 * - be unset for removable block devices with permanent media
-	 *
-	 * Since MMC block devices clearly fall under the second
-	 * case, we do not set GENHD_FL_REMOVABLE.  Userspace
-	 * should use the block device creation/destruction hotplug
-	 * messages to tell when the card is present.
-	 */
-
-	snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
-		 "mmcblk%u%s", card->host->index, subname ? subname : "");
-
-	if (mmc_card_mmc(card))
-		blk_queue_logical_block_size(md->queue.queue,
-					     card->ext_csd.data_sector_size);
-	else
-		blk_queue_logical_block_size(md->queue.queue, 512);
-
-	set_capacity(md->disk, size);
-
-	if (mmc_host_cmd23(card->host)) {
-		if ((mmc_card_mmc(card) &&
-		     card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
-		    (mmc_card_sd(card) &&
-		     card->scr.cmds & SD_SCR_CMD23_SUPPORT))
-			md->flags |= MMC_BLK_CMD23;
-	}
-
-	if (mmc_card_mmc(card) &&
-	    md->flags & MMC_BLK_CMD23 &&
-	    ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
-	     card->ext_csd.rel_sectors)) {
-		md->flags |= MMC_BLK_REL_WR;
-		blk_queue_write_cache(md->queue.queue, true, true);
-	}
-
-	if (mmc_card_mmc(card) &&
-	    (area_type == MMC_BLK_DATA_AREA_MAIN) &&
-	    (md->flags & MMC_BLK_CMD23) &&
-	    card->ext_csd.packed_event_en) {
-		if (!mmc_packed_init(&md->queue, card))
-			md->flags |= MMC_BLK_PACKED_CMD;
-	}
-
-	return md;
-
- err_putdisk:
-	put_disk(md->disk);
- err_kfree:
-	kfree(md);
- out:
-	spin_lock(&mmc_blk_lock);
-	ida_remove(&mmc_blk_ida, devidx);
-	spin_unlock(&mmc_blk_lock);
-	return ERR_PTR(ret);
-}
-
-static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
-{
-	sector_t size;
-
-	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
-		/*
-		 * The EXT_CSD sector count is in number or 512 byte
-		 * sectors.
-		 */
-		size = card->ext_csd.sectors;
-	} else {
-		/*
-		 * The CSD capacity field is in units of read_blkbits.
-		 * set_capacity takes units of 512 bytes.
-		 */
-		size = (typeof(sector_t))card->csd.capacity
-			<< (card->csd.read_blkbits - 9);
-	}
-
-	return mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
-					MMC_BLK_DATA_AREA_MAIN);
-}
-
-static int mmc_blk_alloc_part(struct mmc_card *card,
-			      struct mmc_blk_data *md,
-			      unsigned int part_type,
-			      sector_t size,
-			      bool default_ro,
-			      const char *subname,
-			      int area_type)
-{
-	char cap_str[10];
-	struct mmc_blk_data *part_md;
-
-	part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
-				    subname, area_type);
-	if (IS_ERR(part_md))
-		return PTR_ERR(part_md);
-	part_md->part_type = part_type;
-	list_add(&part_md->part, &md->part);
-
-	string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2,
-			cap_str, sizeof(cap_str));
-	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 idx, ret = 0;
-
-	if (!mmc_card_mmc(card))
-		return 0;
-
-	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,
-				card->part[idx].area_type);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return ret;
-}
-
-static void mmc_blk_remove_req(struct mmc_blk_data *md)
-{
-	struct mmc_card *card;
-
-	if (md) {
-		/*
-		 * Flush remaining requests and free queues. It
-		 * is freeing the queue that stops new requests
-		 * from being accepted.
-		 */
-		card = md->queue.card;
-		mmc_cleanup_queue(&md->queue);
-		if (md->flags & MMC_BLK_PACKED_CMD)
-			mmc_packed_clean(&md->queue);
-		if (md->disk->flags & GENHD_FL_UP) {
-			device_remove_file(disk_to_dev(md->disk), &md->force_ro);
-			if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
-					card->ext_csd.boot_ro_lockable)
-				device_remove_file(disk_to_dev(md->disk),
-					&md->power_ro_lock);
-
-			del_gendisk(md->disk);
-		}
-		mmc_blk_put(md);
-	}
-}
-
-static void mmc_blk_remove_parts(struct mmc_card *card,
-				 struct mmc_blk_data *md)
-{
-	struct list_head *pos, *q;
-	struct mmc_blk_data *part_md;
-
-	list_for_each_safe(pos, q, &md->part) {
-		part_md = list_entry(pos, struct mmc_blk_data, part);
-		list_del(pos);
-		mmc_blk_remove_req(part_md);
-	}
-}
-
-static int mmc_add_disk(struct mmc_blk_data *md)
-{
-	int ret;
-	struct mmc_card *card = md->queue.card;
-
-	device_add_disk(md->parent, md->disk);
-	md->force_ro.show = force_ro_show;
-	md->force_ro.store = force_ro_store;
-	sysfs_attr_init(&md->force_ro.attr);
-	md->force_ro.attr.name = "force_ro";
-	md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
-	ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
-	if (ret)
-		goto force_ro_fail;
-
-	if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
-	     card->ext_csd.boot_ro_lockable) {
-		umode_t mode;
-
-		if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
-			mode = S_IRUGO;
-		else
-			mode = S_IRUGO | S_IWUSR;
-
-		md->power_ro_lock.show = power_ro_lock_show;
-		md->power_ro_lock.store = power_ro_lock_store;
-		sysfs_attr_init(&md->power_ro_lock.attr);
-		md->power_ro_lock.attr.mode = mode;
-		md->power_ro_lock.attr.name =
-					"ro_lock_until_next_power_on";
-		ret = device_create_file(disk_to_dev(md->disk),
-				&md->power_ro_lock);
-		if (ret)
-			goto power_ro_lock_fail;
-	}
-	return ret;
-
-power_ro_lock_fail:
-	device_remove_file(disk_to_dev(md->disk), &md->force_ro);
-force_ro_fail:
-	del_gendisk(md->disk);
-
-	return ret;
-}
-
-static const struct mmc_fixup blk_fixups[] =
-{
-	MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
-		  MMC_QUIRK_INAND_CMD38),
-	MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk,
-		  MMC_QUIRK_INAND_CMD38),
-	MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk,
-		  MMC_QUIRK_INAND_CMD38),
-	MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk,
-		  MMC_QUIRK_INAND_CMD38),
-	MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk,
-		  MMC_QUIRK_INAND_CMD38),
-
-	/*
-	 * Some MMC cards experience performance degradation with CMD23
-	 * instead of CMD12-bounded multiblock transfers. For now we'll
-	 * black list what's bad...
-	 * - Certain Toshiba cards.
-	 *
-	 * N.B. This doesn't affect SD cards.
-	 */
-	MMC_FIXUP("SDMB-32", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_BLK_NO_CMD23),
-	MMC_FIXUP("SDM032", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_BLK_NO_CMD23),
-	MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_BLK_NO_CMD23),
-	MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_BLK_NO_CMD23),
-	MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_BLK_NO_CMD23),
-
-	/*
-	 * Some MMC cards need longer data read timeout than indicated in CSD.
-	 */
-	MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
-		  MMC_QUIRK_LONG_READ_TIME),
-	MMC_FIXUP("008GE0", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_LONG_READ_TIME),
-
-	/*
-	 * On these Samsung MoviNAND parts, performing secure erase or
-	 * secure trim can result in unrecoverable corruption due to a
-	 * firmware bug.
-	 */
-	MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-	MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-	MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-	MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-	MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-	MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-	MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-	MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
-
-	/*
-	 *  On Some Kingston eMMCs, performing trim can result in
-	 *  unrecoverable data conrruption occasionally due to a firmware bug.
-	 */
-	MMC_FIXUP("V10008", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_TRIM_BROKEN),
-	MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
-		  MMC_QUIRK_TRIM_BROKEN),
-
-	END_FIXUP
-};
-
-static int mmc_blk_probe(struct mmc_card *card)
-{
-	struct mmc_blk_data *md, *part_md;
-	char cap_str[10];
-
-	/*
-	 * Check that the card supports the command class(es) we need.
-	 */
-	if (!(card->csd.cmdclass & CCC_BLOCK_READ))
-		return -ENODEV;
-
-	mmc_fixup_device(card, blk_fixups);
-
-	md = mmc_blk_alloc(card);
-	if (IS_ERR(md))
-		return PTR_ERR(md);
-
-	string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
-			cap_str, sizeof(cap_str));
-	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)" : "");
-
-	if (mmc_blk_alloc_parts(card, md))
-		goto out;
-
-	dev_set_drvdata(&card->dev, md);
-
-	if (mmc_add_disk(md))
-		goto out;
-
-	list_for_each_entry(part_md, &md->part, part) {
-		if (mmc_add_disk(part_md))
-			goto out;
-	}
-
-	pm_runtime_set_autosuspend_delay(&card->dev, 3000);
-	pm_runtime_use_autosuspend(&card->dev);
-
-	/*
-	 * Don't enable runtime PM for SD-combo cards here. Leave that
-	 * decision to be taken during the SDIO init sequence instead.
-	 */
-	if (card->type != MMC_TYPE_SD_COMBO) {
-		pm_runtime_set_active(&card->dev);
-		pm_runtime_enable(&card->dev);
-	}
-
-	return 0;
-
- out:
-	mmc_blk_remove_parts(card, md);
-	mmc_blk_remove_req(md);
-	return 0;
-}
-
-static void mmc_blk_remove(struct mmc_card *card)
-{
-	struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
-
-	mmc_blk_remove_parts(card, md);
-	pm_runtime_get_sync(&card->dev);
-	mmc_claim_host(card->host);
-	mmc_blk_part_switch(card, md);
-	mmc_release_host(card->host);
-	if (card->type != MMC_TYPE_SD_COMBO)
-		pm_runtime_disable(&card->dev);
-	pm_runtime_put_noidle(&card->dev);
-	mmc_blk_remove_req(md);
-	dev_set_drvdata(&card->dev, NULL);
-}
-
-static int _mmc_blk_suspend(struct mmc_card *card)
-{
-	struct mmc_blk_data *part_md;
-	struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
-
-	if (md) {
-		mmc_queue_suspend(&md->queue);
-		list_for_each_entry(part_md, &md->part, part) {
-			mmc_queue_suspend(&part_md->queue);
-		}
-	}
-	return 0;
-}
-
-static void mmc_blk_shutdown(struct mmc_card *card)
-{
-	_mmc_blk_suspend(card);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int mmc_blk_suspend(struct device *dev)
-{
-	struct mmc_card *card = mmc_dev_to_card(dev);
-
-	return _mmc_blk_suspend(card);
-}
-
-static int mmc_blk_resume(struct device *dev)
-{
-	struct mmc_blk_data *part_md;
-	struct mmc_blk_data *md = dev_get_drvdata(dev);
-
-	if (md) {
-		/*
-		 * Resume involves the card going into idle state,
-		 * so current partition is always the main one.
-		 */
-		md->part_curr = md->part_type;
-		mmc_queue_resume(&md->queue);
-		list_for_each_entry(part_md, &md->part, part) {
-			mmc_queue_resume(&part_md->queue);
-		}
-	}
-	return 0;
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume);
-
-static struct mmc_driver mmc_driver = {
-	.drv		= {
-		.name	= "mmcblk",
-		.pm	= &mmc_blk_pm_ops,
-	},
-	.probe		= mmc_blk_probe,
-	.remove		= mmc_blk_remove,
-	.shutdown	= mmc_blk_shutdown,
-};
-
-static int __init mmc_blk_init(void)
-{
-	int res;
-
-	if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
-		pr_info("mmcblk: using %d minors per device\n", perdev_minors);
-
-	max_devices = min(MAX_DEVICES, (1 << MINORBITS) / perdev_minors);
-
-	res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
-	if (res)
-		goto out;
-
-	res = mmc_register_driver(&mmc_driver);
-	if (res)
-		goto out2;
-
-	return 0;
- out2:
-	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
- out:
-	return res;
-}
-
-static void __exit mmc_blk_exit(void)
-{
-	mmc_unregister_driver(&mmc_driver);
-	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
-}
-
-module_init(mmc_blk_init);
-module_exit(mmc_blk_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
-
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/block.h linux-libre-4.10-rc8-gnu/drivers/mmc/card/block.h
--- linux-libre-4.9-gnu/drivers/mmc/card/block.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/block.h	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/Kconfig linux-libre-4.10-rc8-gnu/drivers/mmc/card/Kconfig
--- linux-libre-4.9-gnu/drivers/mmc/card/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-#
-# MMC/SD card drivers
-#
-
-comment "MMC/SD/SDIO Card Drivers"
-
-config MMC_BLOCK
-	tristate "MMC block device driver"
-	depends on BLOCK
-	default y
-	help
-	  Say Y here to enable the MMC block device driver support.
-	  This provides a block device driver, which you can use to
-	  mount the filesystem. Almost everyone wishing MMC support
-	  should say Y or M here.
-
-config MMC_BLOCK_MINORS
-	int "Number of minors per block device"
-	depends on MMC_BLOCK
-	range 4 256
-	default 8
-	help
-	  Number of minors per block device. One is needed for every
-	  partition on the disk (plus one for the whole disk).
-
-	  Number of total MMC minors available is 256, so your number
-	  of supported block devices will be limited to 256 divided
-	  by this number.
-
-	  Default is 8 to be backwards compatible with previous
-	  hardwired device numbering.
-
-	  If unsure, say 8 here.
-
-config MMC_BLOCK_BOUNCE
-	bool "Use bounce buffer for simple hosts"
-	depends on MMC_BLOCK
-	default y
-	help
-	  SD/MMC is a high latency protocol where it is crucial to
-	  send large requests in order to get high performance. Many
-	  controllers, however, are restricted to continuous memory
-	  (i.e. they can't do scatter-gather), something the kernel
-	  rarely can provide.
-
-	  Say Y here to help these restricted hosts by bouncing
-	  requests back and forth from a large buffer. You will get
-	  a big performance gain at the cost of up to 64 KiB of
-	  physical memory.
-
-	  If unsure, say Y here.
-
-config SDIO_UART
-	tristate "SDIO UART/GPS class support"
-	depends on TTY
-	help
-	  SDIO function driver for SDIO cards that implements the UART
-	  class, as well as the GPS class which appears like a UART.
-
-config MMC_TEST
-	tristate "MMC host test driver"
-	help
-	  Development driver that performs a series of reads and writes
-	  to a memory card in order to expose certain well known bugs
-	  in host controllers. The tests are executed by writing to the
-	  "test" file in debugfs under each card. Note that whatever is
-	  on your card will be overwritten by these tests.
-
-	  This driver is only of interest to those developing or
-	  testing a host driver. Most people should say N here.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/Makefile linux-libre-4.10-rc8-gnu/drivers/mmc/card/Makefile
--- linux-libre-4.9-gnu/drivers/mmc/card/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Makefile for MMC/SD card drivers
-#
-
-obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
-mmc_block-objs			:= block.o queue.o
-obj-$(CONFIG_MMC_TEST)		+= mmc_test.o
-
-obj-$(CONFIG_SDIO_UART)		+= sdio_uart.o
-
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/mmc_test.c linux-libre-4.10-rc8-gnu/drivers/mmc/card/mmc_test.c
--- linux-libre-4.9-gnu/drivers/mmc/card/mmc_test.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/mmc_test.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3286 +0,0 @@
-/*
- *  linux/drivers/mmc/card/mmc_test.c
- *
- *  Copyright 2007-2008 Pierre Ossman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/mmc.h>
-#include <linux/slab.h>
-
-#include <linux/scatterlist.h>
-#include <linux/swap.h>		/* For nr_free_buffer_pages() */
-#include <linux/list.h>
-
-#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
-#define RESULT_UNSUP_HOST	2
-#define RESULT_UNSUP_CARD	3
-
-#define BUFFER_ORDER		2
-#define BUFFER_SIZE		(PAGE_SIZE << BUFFER_ORDER)
-
-#define TEST_ALIGN_END		8
-
-/*
- * Limit the test area size to the maximum MMC HC erase group size.  Note that
- * the maximum SD allocation unit size is just 4MiB.
- */
-#define TEST_AREA_MAX_SIZE (128 * 1024 * 1024)
-
-/**
- * struct mmc_test_pages - pages allocated by 'alloc_pages()'.
- * @page: first page in the allocation
- * @order: order of the number of pages allocated
- */
-struct mmc_test_pages {
-	struct page *page;
-	unsigned int order;
-};
-
-/**
- * struct mmc_test_mem - allocated memory.
- * @arr: array of allocations
- * @cnt: number of allocations
- */
-struct mmc_test_mem {
-	struct mmc_test_pages *arr;
-	unsigned int cnt;
-};
-
-/**
- * struct mmc_test_area - information for performance tests.
- * @max_sz: test area size (in bytes)
- * @dev_addr: address on card at which to do performance tests
- * @max_tfr: maximum transfer size allowed by driver (in bytes)
- * @max_segs: maximum segments allowed by driver in scatterlist @sg
- * @max_seg_sz: maximum segment size allowed by driver
- * @blocks: number of (512 byte) blocks currently mapped by @sg
- * @sg_len: length of currently mapped scatterlist @sg
- * @mem: allocated memory
- * @sg: scatterlist
- */
-struct mmc_test_area {
-	unsigned long max_sz;
-	unsigned int dev_addr;
-	unsigned int max_tfr;
-	unsigned int max_segs;
-	unsigned int max_seg_sz;
-	unsigned int blocks;
-	unsigned int sg_len;
-	struct mmc_test_mem *mem;
-	struct scatterlist *sg;
-};
-
-/**
- * struct mmc_test_transfer_result - transfer results for performance tests.
- * @link: double-linked list
- * @count: amount of group of sectors to check
- * @sectors: amount of sectors to check in one group
- * @ts: time values of transfer
- * @rate: calculated transfer rate
- * @iops: I/O operations per second (times 100)
- */
-struct mmc_test_transfer_result {
-	struct list_head link;
-	unsigned int count;
-	unsigned int sectors;
-	struct timespec ts;
-	unsigned int rate;
-	unsigned int iops;
-};
-
-/**
- * struct mmc_test_general_result - results for tests.
- * @link: double-linked list
- * @card: card under test
- * @testcase: number of test case
- * @result: result of test run
- * @tr_lst: transfer measurements if any as mmc_test_transfer_result
- */
-struct mmc_test_general_result {
-	struct list_head link;
-	struct mmc_card *card;
-	int testcase;
-	int result;
-	struct list_head tr_lst;
-};
-
-/**
- * struct mmc_test_dbgfs_file - debugfs related file.
- * @link: double-linked list
- * @card: card under test
- * @file: file created under debugfs
- */
-struct mmc_test_dbgfs_file {
-	struct list_head link;
-	struct mmc_card *card;
-	struct dentry *file;
-};
-
-/**
- * struct mmc_test_card - test information.
- * @card: card under test
- * @scratch: transfer buffer
- * @buffer: transfer buffer
- * @highmem: buffer for highmem tests
- * @area: information for performance tests
- * @gr: pointer to results of current testcase
- */
-struct mmc_test_card {
-	struct mmc_card	*card;
-
-	u8		scratch[BUFFER_SIZE];
-	u8		*buffer;
-#ifdef CONFIG_HIGHMEM
-	struct page	*highmem;
-#endif
-	struct mmc_test_area		area;
-	struct mmc_test_general_result	*gr;
-};
-
-enum mmc_test_prep_media {
-	MMC_TEST_PREP_NONE = 0,
-	MMC_TEST_PREP_WRITE_FULL = 1 << 0,
-	MMC_TEST_PREP_ERASE = 1 << 1,
-};
-
-struct mmc_test_multiple_rw {
-	unsigned int *sg_len;
-	unsigned int *bs;
-	unsigned int len;
-	unsigned int size;
-	bool do_write;
-	bool do_nonblock_req;
-	enum mmc_test_prep_media prepare;
-};
-
-struct mmc_test_async_req {
-	struct mmc_async_req areq;
-	struct mmc_test_card *test;
-};
-
-/*******************************************************************/
-/*  General helper functions                                       */
-/*******************************************************************/
-
-/*
- * Configure correct block size in card
- */
-static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
-{
-	return mmc_set_blocklen(test->card, size);
-}
-
-static bool mmc_test_card_cmd23(struct mmc_card *card)
-{
-	return mmc_card_mmc(card) ||
-	       (mmc_card_sd(card) && card->scr.cmds & SD_SCR_CMD23_SUPPORT);
-}
-
-static void mmc_test_prepare_sbc(struct mmc_test_card *test,
-				 struct mmc_request *mrq, unsigned int blocks)
-{
-	struct mmc_card *card = test->card;
-
-	if (!mrq->sbc || !mmc_host_cmd23(card->host) ||
-	    !mmc_test_card_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) ||
-	    (card->quirks & MMC_QUIRK_BLK_NO_CMD23)) {
-		mrq->sbc = NULL;
-		return;
-	}
-
-	mrq->sbc->opcode = MMC_SET_BLOCK_COUNT;
-	mrq->sbc->arg = blocks;
-	mrq->sbc->flags = MMC_RSP_R1 | MMC_CMD_AC;
-}
-
-/*
- * Fill in the mmc_request structure given a set of transfer parameters.
- */
-static void mmc_test_prepare_mrq(struct mmc_test_card *test,
-	struct mmc_request *mrq, struct scatterlist *sg, unsigned sg_len,
-	unsigned dev_addr, unsigned blocks, unsigned blksz, int write)
-{
-	BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop);
-
-	if (blocks > 1) {
-		mrq->cmd->opcode = write ?
-			MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
-	} else {
-		mrq->cmd->opcode = write ?
-			MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
-	}
-
-	mrq->cmd->arg = dev_addr;
-	if (!mmc_card_blockaddr(test->card))
-		mrq->cmd->arg <<= 9;
-
-	mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
-	if (blocks == 1)
-		mrq->stop = NULL;
-	else {
-		mrq->stop->opcode = MMC_STOP_TRANSMISSION;
-		mrq->stop->arg = 0;
-		mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
-	}
-
-	mrq->data->blksz = blksz;
-	mrq->data->blocks = blocks;
-	mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
-	mrq->data->sg = sg;
-	mrq->data->sg_len = sg_len;
-
-	mmc_test_prepare_sbc(test, mrq, blocks);
-
-	mmc_set_data_timeout(mrq->data, test->card);
-}
-
-static int mmc_test_busy(struct mmc_command *cmd)
-{
-	return !(cmd->resp[0] & R1_READY_FOR_DATA) ||
-		(R1_CURRENT_STATE(cmd->resp[0]) == R1_STATE_PRG);
-}
-
-/*
- * Wait for the card to finish the busy state
- */
-static int mmc_test_wait_busy(struct mmc_test_card *test)
-{
-	int ret, busy;
-	struct mmc_command cmd = {0};
-
-	busy = 0;
-	do {
-		memset(&cmd, 0, sizeof(struct mmc_command));
-
-		cmd.opcode = MMC_SEND_STATUS;
-		cmd.arg = test->card->rca << 16;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
-
-		ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
-		if (ret)
-			break;
-
-		if (!busy && mmc_test_busy(&cmd)) {
-			busy = 1;
-			if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
-				pr_info("%s: Warning: Host did not "
-					"wait for busy state to end.\n",
-					mmc_hostname(test->card->host));
-		}
-	} while (mmc_test_busy(&cmd));
-
-	return ret;
-}
-
-/*
- * Transfer a single sector of kernel addressable data
- */
-static int mmc_test_buffer_transfer(struct mmc_test_card *test,
-	u8 *buffer, unsigned addr, unsigned blksz, int write)
-{
-	struct mmc_request mrq = {0};
-	struct mmc_command cmd = {0};
-	struct mmc_command stop = {0};
-	struct mmc_data data = {0};
-
-	struct scatterlist sg;
-
-	mrq.cmd = &cmd;
-	mrq.data = &data;
-	mrq.stop = &stop;
-
-	sg_init_one(&sg, buffer, blksz);
-
-	mmc_test_prepare_mrq(test, &mrq, &sg, 1, addr, 1, blksz, write);
-
-	mmc_wait_for_req(test->card->host, &mrq);
-
-	if (cmd.error)
-		return cmd.error;
-	if (data.error)
-		return data.error;
-
-	return mmc_test_wait_busy(test);
-}
-
-static void mmc_test_free_mem(struct mmc_test_mem *mem)
-{
-	if (!mem)
-		return;
-	while (mem->cnt--)
-		__free_pages(mem->arr[mem->cnt].page,
-			     mem->arr[mem->cnt].order);
-	kfree(mem->arr);
-	kfree(mem);
-}
-
-/*
- * Allocate a lot of memory, preferably max_sz but at least min_sz.  In case
- * there isn't much memory do not exceed 1/16th total lowmem pages.  Also do
- * not exceed a maximum number of segments and try not to make segments much
- * bigger than maximum segment size.
- */
-static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz,
-					       unsigned long max_sz,
-					       unsigned int max_segs,
-					       unsigned int max_seg_sz)
-{
-	unsigned long max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE);
-	unsigned long min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE);
-	unsigned long max_seg_page_cnt = DIV_ROUND_UP(max_seg_sz, PAGE_SIZE);
-	unsigned long page_cnt = 0;
-	unsigned long limit = nr_free_buffer_pages() >> 4;
-	struct mmc_test_mem *mem;
-
-	if (max_page_cnt > limit)
-		max_page_cnt = limit;
-	if (min_page_cnt > max_page_cnt)
-		min_page_cnt = max_page_cnt;
-
-	if (max_seg_page_cnt > max_page_cnt)
-		max_seg_page_cnt = max_page_cnt;
-
-	if (max_segs > max_page_cnt)
-		max_segs = max_page_cnt;
-
-	mem = kzalloc(sizeof(struct mmc_test_mem), GFP_KERNEL);
-	if (!mem)
-		return NULL;
-
-	mem->arr = kzalloc(sizeof(struct mmc_test_pages) * max_segs,
-			   GFP_KERNEL);
-	if (!mem->arr)
-		goto out_free;
-
-	while (max_page_cnt) {
-		struct page *page;
-		unsigned int order;
-		gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN |
-				__GFP_NORETRY;
-
-		order = get_order(max_seg_page_cnt << PAGE_SHIFT);
-		while (1) {
-			page = alloc_pages(flags, order);
-			if (page || !order)
-				break;
-			order -= 1;
-		}
-		if (!page) {
-			if (page_cnt < min_page_cnt)
-				goto out_free;
-			break;
-		}
-		mem->arr[mem->cnt].page = page;
-		mem->arr[mem->cnt].order = order;
-		mem->cnt += 1;
-		if (max_page_cnt <= (1UL << order))
-			break;
-		max_page_cnt -= 1UL << order;
-		page_cnt += 1UL << order;
-		if (mem->cnt >= max_segs) {
-			if (page_cnt < min_page_cnt)
-				goto out_free;
-			break;
-		}
-	}
-
-	return mem;
-
-out_free:
-	mmc_test_free_mem(mem);
-	return NULL;
-}
-
-/*
- * Map memory into a scatterlist.  Optionally allow the same memory to be
- * mapped more than once.
- */
-static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long size,
-			   struct scatterlist *sglist, int repeat,
-			   unsigned int max_segs, unsigned int max_seg_sz,
-			   unsigned int *sg_len, int min_sg_len)
-{
-	struct scatterlist *sg = NULL;
-	unsigned int i;
-	unsigned long sz = size;
-
-	sg_init_table(sglist, max_segs);
-	if (min_sg_len > max_segs)
-		min_sg_len = max_segs;
-
-	*sg_len = 0;
-	do {
-		for (i = 0; i < mem->cnt; i++) {
-			unsigned long len = PAGE_SIZE << mem->arr[i].order;
-
-			if (min_sg_len && (size / min_sg_len < len))
-				len = ALIGN(size / min_sg_len, 512);
-			if (len > sz)
-				len = sz;
-			if (len > max_seg_sz)
-				len = max_seg_sz;
-			if (sg)
-				sg = sg_next(sg);
-			else
-				sg = sglist;
-			if (!sg)
-				return -EINVAL;
-			sg_set_page(sg, mem->arr[i].page, len, 0);
-			sz -= len;
-			*sg_len += 1;
-			if (!sz)
-				break;
-		}
-	} while (sz && repeat);
-
-	if (sz)
-		return -EINVAL;
-
-	if (sg)
-		sg_mark_end(sg);
-
-	return 0;
-}
-
-/*
- * Map memory into a scatterlist so that no pages are contiguous.  Allow the
- * same memory to be mapped more than once.
- */
-static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem,
-				       unsigned long sz,
-				       struct scatterlist *sglist,
-				       unsigned int max_segs,
-				       unsigned int max_seg_sz,
-				       unsigned int *sg_len)
-{
-	struct scatterlist *sg = NULL;
-	unsigned int i = mem->cnt, cnt;
-	unsigned long len;
-	void *base, *addr, *last_addr = NULL;
-
-	sg_init_table(sglist, max_segs);
-
-	*sg_len = 0;
-	while (sz) {
-		base = page_address(mem->arr[--i].page);
-		cnt = 1 << mem->arr[i].order;
-		while (sz && cnt) {
-			addr = base + PAGE_SIZE * --cnt;
-			if (last_addr && last_addr + PAGE_SIZE == addr)
-				continue;
-			last_addr = addr;
-			len = PAGE_SIZE;
-			if (len > max_seg_sz)
-				len = max_seg_sz;
-			if (len > sz)
-				len = sz;
-			if (sg)
-				sg = sg_next(sg);
-			else
-				sg = sglist;
-			if (!sg)
-				return -EINVAL;
-			sg_set_page(sg, virt_to_page(addr), len, 0);
-			sz -= len;
-			*sg_len += 1;
-		}
-		if (i == 0)
-			i = mem->cnt;
-	}
-
-	if (sg)
-		sg_mark_end(sg);
-
-	return 0;
-}
-
-/*
- * Calculate transfer rate in bytes per second.
- */
-static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts)
-{
-	uint64_t ns;
-
-	ns = ts->tv_sec;
-	ns *= 1000000000;
-	ns += ts->tv_nsec;
-
-	bytes *= 1000000000;
-
-	while (ns > UINT_MAX) {
-		bytes >>= 1;
-		ns >>= 1;
-	}
-
-	if (!ns)
-		return 0;
-
-	do_div(bytes, (uint32_t)ns);
-
-	return bytes;
-}
-
-/*
- * Save transfer results for future usage
- */
-static void mmc_test_save_transfer_result(struct mmc_test_card *test,
-	unsigned int count, unsigned int sectors, struct timespec ts,
-	unsigned int rate, unsigned int iops)
-{
-	struct mmc_test_transfer_result *tr;
-
-	if (!test->gr)
-		return;
-
-	tr = kmalloc(sizeof(struct mmc_test_transfer_result), GFP_KERNEL);
-	if (!tr)
-		return;
-
-	tr->count = count;
-	tr->sectors = sectors;
-	tr->ts = ts;
-	tr->rate = rate;
-	tr->iops = iops;
-
-	list_add_tail(&tr->link, &test->gr->tr_lst);
-}
-
-/*
- * Print the transfer rate.
- */
-static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
-				struct timespec *ts1, struct timespec *ts2)
-{
-	unsigned int rate, iops, sectors = bytes >> 9;
-	struct timespec ts;
-
-	ts = timespec_sub(*ts2, *ts1);
-
-	rate = mmc_test_rate(bytes, &ts);
-	iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */
-
-	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,
-			 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024,
-			 iops / 100, iops % 100);
-
-	mmc_test_save_transfer_result(test, 1, sectors, ts, rate, iops);
-}
-
-/*
- * Print the average transfer rate.
- */
-static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
-				    unsigned int count, struct timespec *ts1,
-				    struct timespec *ts2)
-{
-	unsigned int rate, iops, sectors = bytes >> 9;
-	uint64_t tot = bytes * count;
-	struct timespec ts;
-
-	ts = timespec_sub(*ts2, *ts1);
-
-	rate = mmc_test_rate(tot, &ts);
-	iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
-
-	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,
-			 sectors >> 1, (sectors & 1 ? ".5" : ""),
-			 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
-			 rate / 1000, rate / 1024, iops / 100, iops % 100,
-			 test->area.sg_len);
-
-	mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
-}
-
-/*
- * Return the card size in sectors.
- */
-static unsigned int mmc_test_capacity(struct mmc_card *card)
-{
-	if (!mmc_card_sd(card) && mmc_card_blockaddr(card))
-		return card->ext_csd.sectors;
-	else
-		return card->csd.capacity << (card->csd.read_blkbits - 9);
-}
-
-/*******************************************************************/
-/*  Test preparation and cleanup                                   */
-/*******************************************************************/
-
-/*
- * Fill the first couple of sectors of the card with known data
- * so that bad reads/writes can be detected
- */
-static int __mmc_test_prepare(struct mmc_test_card *test, int write)
-{
-	int ret, i;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	if (write)
-		memset(test->buffer, 0xDF, 512);
-	else {
-		for (i = 0;i < 512;i++)
-			test->buffer[i] = i;
-	}
-
-	for (i = 0;i < BUFFER_SIZE / 512;i++) {
-		ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_prepare_write(struct mmc_test_card *test)
-{
-	return __mmc_test_prepare(test, 1);
-}
-
-static int mmc_test_prepare_read(struct mmc_test_card *test)
-{
-	return __mmc_test_prepare(test, 0);
-}
-
-static int mmc_test_cleanup(struct mmc_test_card *test)
-{
-	int ret, i;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	memset(test->buffer, 0, 512);
-
-	for (i = 0;i < BUFFER_SIZE / 512;i++) {
-		ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-/*******************************************************************/
-/*  Test execution helpers                                         */
-/*******************************************************************/
-
-/*
- * Modifies the mmc_request to perform the "short transfer" tests
- */
-static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test,
-	struct mmc_request *mrq, int write)
-{
-	BUG_ON(!mrq || !mrq->cmd || !mrq->data);
-
-	if (mrq->data->blocks > 1) {
-		mrq->cmd->opcode = write ?
-			MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
-		mrq->stop = NULL;
-	} else {
-		mrq->cmd->opcode = MMC_SEND_STATUS;
-		mrq->cmd->arg = test->card->rca << 16;
-	}
-}
-
-/*
- * Checks that a normal transfer didn't have any errors
- */
-static int mmc_test_check_result(struct mmc_test_card *test,
-				 struct mmc_request *mrq)
-{
-	int ret;
-
-	BUG_ON(!mrq || !mrq->cmd || !mrq->data);
-
-	ret = 0;
-
-	if (mrq->sbc && mrq->sbc->error)
-		ret = mrq->sbc->error;
-	if (!ret && mrq->cmd->error)
-		ret = mrq->cmd->error;
-	if (!ret && mrq->data->error)
-		ret = mrq->data->error;
-	if (!ret && mrq->stop && mrq->stop->error)
-		ret = mrq->stop->error;
-	if (!ret && mrq->data->bytes_xfered !=
-		mrq->data->blocks * mrq->data->blksz)
-		ret = RESULT_FAIL;
-
-	if (ret == -EINVAL)
-		ret = RESULT_UNSUP_HOST;
-
-	return ret;
-}
-
-static int mmc_test_check_result_async(struct mmc_card *card,
-				       struct mmc_async_req *areq)
-{
-	struct mmc_test_async_req *test_async =
-		container_of(areq, struct mmc_test_async_req, areq);
-
-	mmc_test_wait_busy(test_async->test);
-
-	return mmc_test_check_result(test_async->test, areq->mrq);
-}
-
-/*
- * Checks that a "short transfer" behaved as expected
- */
-static int mmc_test_check_broken_result(struct mmc_test_card *test,
-	struct mmc_request *mrq)
-{
-	int ret;
-
-	BUG_ON(!mrq || !mrq->cmd || !mrq->data);
-
-	ret = 0;
-
-	if (!ret && mrq->cmd->error)
-		ret = mrq->cmd->error;
-	if (!ret && mrq->data->error == 0)
-		ret = RESULT_FAIL;
-	if (!ret && mrq->data->error != -ETIMEDOUT)
-		ret = mrq->data->error;
-	if (!ret && mrq->stop && mrq->stop->error)
-		ret = mrq->stop->error;
-	if (mrq->data->blocks > 1) {
-		if (!ret && mrq->data->bytes_xfered > mrq->data->blksz)
-			ret = RESULT_FAIL;
-	} else {
-		if (!ret && mrq->data->bytes_xfered > 0)
-			ret = RESULT_FAIL;
-	}
-
-	if (ret == -EINVAL)
-		ret = RESULT_UNSUP_HOST;
-
-	return ret;
-}
-
-/*
- * Tests nonblock transfer with certain parameters
- */
-static void mmc_test_nonblock_reset(struct mmc_request *mrq,
-				    struct mmc_command *cmd,
-				    struct mmc_command *stop,
-				    struct mmc_data *data)
-{
-	memset(mrq, 0, sizeof(struct mmc_request));
-	memset(cmd, 0, sizeof(struct mmc_command));
-	memset(data, 0, sizeof(struct mmc_data));
-	memset(stop, 0, sizeof(struct mmc_command));
-
-	mrq->cmd = cmd;
-	mrq->data = data;
-	mrq->stop = stop;
-}
-static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
-				      struct scatterlist *sg, unsigned sg_len,
-				      unsigned dev_addr, unsigned blocks,
-				      unsigned blksz, int write, int count)
-{
-	struct mmc_request mrq1;
-	struct mmc_command cmd1;
-	struct mmc_command stop1;
-	struct mmc_data data1;
-
-	struct mmc_request mrq2;
-	struct mmc_command cmd2;
-	struct mmc_command stop2;
-	struct mmc_data data2;
-
-	struct mmc_test_async_req test_areq[2];
-	struct mmc_async_req *done_areq;
-	struct mmc_async_req *cur_areq = &test_areq[0].areq;
-	struct mmc_async_req *other_areq = &test_areq[1].areq;
-	int i;
-	int ret;
-
-	test_areq[0].test = test;
-	test_areq[1].test = test;
-
-	mmc_test_nonblock_reset(&mrq1, &cmd1, &stop1, &data1);
-	mmc_test_nonblock_reset(&mrq2, &cmd2, &stop2, &data2);
-
-	cur_areq->mrq = &mrq1;
-	cur_areq->err_check = mmc_test_check_result_async;
-	other_areq->mrq = &mrq2;
-	other_areq->err_check = mmc_test_check_result_async;
-
-	for (i = 0; i < count; i++) {
-		mmc_test_prepare_mrq(test, cur_areq->mrq, sg, sg_len, dev_addr,
-				     blocks, blksz, write);
-		done_areq = mmc_start_req(test->card->host, cur_areq, &ret);
-
-		if (ret || (!done_areq && i > 0))
-			goto err;
-
-		if (done_areq) {
-			if (done_areq->mrq == &mrq2)
-				mmc_test_nonblock_reset(&mrq2, &cmd2,
-							&stop2, &data2);
-			else
-				mmc_test_nonblock_reset(&mrq1, &cmd1,
-							&stop1, &data1);
-		}
-		swap(cur_areq, other_areq);
-		dev_addr += blocks;
-	}
-
-	done_areq = mmc_start_req(test->card->host, NULL, &ret);
-
-	return ret;
-err:
-	return ret;
-}
-
-/*
- * Tests a basic transfer with certain parameters
- */
-static int mmc_test_simple_transfer(struct mmc_test_card *test,
-	struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
-	unsigned blocks, unsigned blksz, int write)
-{
-	struct mmc_request mrq = {0};
-	struct mmc_command cmd = {0};
-	struct mmc_command stop = {0};
-	struct mmc_data data = {0};
-
-	mrq.cmd = &cmd;
-	mrq.data = &data;
-	mrq.stop = &stop;
-
-	mmc_test_prepare_mrq(test, &mrq, sg, sg_len, dev_addr,
-		blocks, blksz, write);
-
-	mmc_wait_for_req(test->card->host, &mrq);
-
-	mmc_test_wait_busy(test);
-
-	return mmc_test_check_result(test, &mrq);
-}
-
-/*
- * Tests a transfer where the card will fail completely or partly
- */
-static int mmc_test_broken_transfer(struct mmc_test_card *test,
-	unsigned blocks, unsigned blksz, int write)
-{
-	struct mmc_request mrq = {0};
-	struct mmc_command cmd = {0};
-	struct mmc_command stop = {0};
-	struct mmc_data data = {0};
-
-	struct scatterlist sg;
-
-	mrq.cmd = &cmd;
-	mrq.data = &data;
-	mrq.stop = &stop;
-
-	sg_init_one(&sg, test->buffer, blocks * blksz);
-
-	mmc_test_prepare_mrq(test, &mrq, &sg, 1, 0, blocks, blksz, write);
-	mmc_test_prepare_broken_mrq(test, &mrq, write);
-
-	mmc_wait_for_req(test->card->host, &mrq);
-
-	mmc_test_wait_busy(test);
-
-	return mmc_test_check_broken_result(test, &mrq);
-}
-
-/*
- * Does a complete transfer test where data is also validated
- *
- * Note: mmc_test_prepare() must have been done before this call
- */
-static int mmc_test_transfer(struct mmc_test_card *test,
-	struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
-	unsigned blocks, unsigned blksz, int write)
-{
-	int ret, i;
-	unsigned long flags;
-
-	if (write) {
-		for (i = 0;i < blocks * blksz;i++)
-			test->scratch[i] = i;
-	} else {
-		memset(test->scratch, 0, BUFFER_SIZE);
-	}
-	local_irq_save(flags);
-	sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
-	local_irq_restore(flags);
-
-	ret = mmc_test_set_blksize(test, blksz);
-	if (ret)
-		return ret;
-
-	ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr,
-		blocks, blksz, write);
-	if (ret)
-		return ret;
-
-	if (write) {
-		int sectors;
-
-		ret = mmc_test_set_blksize(test, 512);
-		if (ret)
-			return ret;
-
-		sectors = (blocks * blksz + 511) / 512;
-		if ((sectors * 512) == (blocks * blksz))
-			sectors++;
-
-		if ((sectors * 512) > BUFFER_SIZE)
-			return -EINVAL;
-
-		memset(test->buffer, 0, sectors * 512);
-
-		for (i = 0;i < sectors;i++) {
-			ret = mmc_test_buffer_transfer(test,
-				test->buffer + i * 512,
-				dev_addr + i, 512, 0);
-			if (ret)
-				return ret;
-		}
-
-		for (i = 0;i < blocks * blksz;i++) {
-			if (test->buffer[i] != (u8)i)
-				return RESULT_FAIL;
-		}
-
-		for (;i < sectors * 512;i++) {
-			if (test->buffer[i] != 0xDF)
-				return RESULT_FAIL;
-		}
-	} else {
-		local_irq_save(flags);
-		sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
-		local_irq_restore(flags);
-		for (i = 0;i < blocks * blksz;i++) {
-			if (test->scratch[i] != (u8)i)
-				return RESULT_FAIL;
-		}
-	}
-
-	return 0;
-}
-
-/*******************************************************************/
-/*  Tests                                                          */
-/*******************************************************************/
-
-struct mmc_test_case {
-	const char *name;
-
-	int (*prepare)(struct mmc_test_card *);
-	int (*run)(struct mmc_test_card *);
-	int (*cleanup)(struct mmc_test_card *);
-};
-
-static int mmc_test_basic_write(struct mmc_test_card *test)
-{
-	int ret;
-	struct scatterlist sg;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	sg_init_one(&sg, test->buffer, 512);
-
-	return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
-}
-
-static int mmc_test_basic_read(struct mmc_test_card *test)
-{
-	int ret;
-	struct scatterlist sg;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	sg_init_one(&sg, test->buffer, 512);
-
-	return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
-}
-
-static int mmc_test_verify_write(struct mmc_test_card *test)
-{
-	struct scatterlist sg;
-
-	sg_init_one(&sg, test->buffer, 512);
-
-	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
-}
-
-static int mmc_test_verify_read(struct mmc_test_card *test)
-{
-	struct scatterlist sg;
-
-	sg_init_one(&sg, test->buffer, 512);
-
-	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
-}
-
-static int mmc_test_multi_write(struct mmc_test_card *test)
-{
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	sg_init_one(&sg, test->buffer, size);
-
-	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
-}
-
-static int mmc_test_multi_read(struct mmc_test_card *test)
-{
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	sg_init_one(&sg, test->buffer, size);
-
-	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
-}
-
-static int mmc_test_pow2_write(struct mmc_test_card *test)
-{
-	int ret, i;
-	struct scatterlist sg;
-
-	if (!test->card->csd.write_partial)
-		return RESULT_UNSUP_CARD;
-
-	for (i = 1; i < 512;i <<= 1) {
-		sg_init_one(&sg, test->buffer, i);
-		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_pow2_read(struct mmc_test_card *test)
-{
-	int ret, i;
-	struct scatterlist sg;
-
-	if (!test->card->csd.read_partial)
-		return RESULT_UNSUP_CARD;
-
-	for (i = 1; i < 512;i <<= 1) {
-		sg_init_one(&sg, test->buffer, i);
-		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_weird_write(struct mmc_test_card *test)
-{
-	int ret, i;
-	struct scatterlist sg;
-
-	if (!test->card->csd.write_partial)
-		return RESULT_UNSUP_CARD;
-
-	for (i = 3; i < 512;i += 7) {
-		sg_init_one(&sg, test->buffer, i);
-		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_weird_read(struct mmc_test_card *test)
-{
-	int ret, i;
-	struct scatterlist sg;
-
-	if (!test->card->csd.read_partial)
-		return RESULT_UNSUP_CARD;
-
-	for (i = 3; i < 512;i += 7) {
-		sg_init_one(&sg, test->buffer, i);
-		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_align_write(struct mmc_test_card *test)
-{
-	int ret, i;
-	struct scatterlist sg;
-
-	for (i = 1; i < TEST_ALIGN_END; i++) {
-		sg_init_one(&sg, test->buffer + i, 512);
-		ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_align_read(struct mmc_test_card *test)
-{
-	int ret, i;
-	struct scatterlist sg;
-
-	for (i = 1; i < TEST_ALIGN_END; i++) {
-		sg_init_one(&sg, test->buffer + i, 512);
-		ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_align_multi_write(struct mmc_test_card *test)
-{
-	int ret, i;
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	for (i = 1; i < TEST_ALIGN_END; i++) {
-		sg_init_one(&sg, test->buffer + i, size);
-		ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_align_multi_read(struct mmc_test_card *test)
-{
-	int ret, i;
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	for (i = 1; i < TEST_ALIGN_END; i++) {
-		sg_init_one(&sg, test->buffer + i, size);
-		ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int mmc_test_xfersize_write(struct mmc_test_card *test)
-{
-	int ret;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	return mmc_test_broken_transfer(test, 1, 512, 1);
-}
-
-static int mmc_test_xfersize_read(struct mmc_test_card *test)
-{
-	int ret;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	return mmc_test_broken_transfer(test, 1, 512, 0);
-}
-
-static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
-{
-	int ret;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	return mmc_test_broken_transfer(test, 2, 512, 1);
-}
-
-static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
-{
-	int ret;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	return mmc_test_broken_transfer(test, 2, 512, 0);
-}
-
-#ifdef CONFIG_HIGHMEM
-
-static int mmc_test_write_high(struct mmc_test_card *test)
-{
-	struct scatterlist sg;
-
-	sg_init_table(&sg, 1);
-	sg_set_page(&sg, test->highmem, 512, 0);
-
-	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
-}
-
-static int mmc_test_read_high(struct mmc_test_card *test)
-{
-	struct scatterlist sg;
-
-	sg_init_table(&sg, 1);
-	sg_set_page(&sg, test->highmem, 512, 0);
-
-	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
-}
-
-static int mmc_test_multi_write_high(struct mmc_test_card *test)
-{
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	sg_init_table(&sg, 1);
-	sg_set_page(&sg, test->highmem, size, 0);
-
-	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
-}
-
-static int mmc_test_multi_read_high(struct mmc_test_card *test)
-{
-	unsigned int size;
-	struct scatterlist sg;
-
-	if (test->card->host->max_blk_count == 1)
-		return RESULT_UNSUP_HOST;
-
-	size = PAGE_SIZE * 2;
-	size = min(size, test->card->host->max_req_size);
-	size = min(size, test->card->host->max_seg_size);
-	size = min(size, test->card->host->max_blk_count * 512);
-
-	if (size < 1024)
-		return RESULT_UNSUP_HOST;
-
-	sg_init_table(&sg, 1);
-	sg_set_page(&sg, test->highmem, size, 0);
-
-	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
-}
-
-#else
-
-static int mmc_test_no_highmem(struct mmc_test_card *test)
-{
-	pr_info("%s: Highmem not configured - test skipped\n",
-	       mmc_hostname(test->card->host));
-	return 0;
-}
-
-#endif /* CONFIG_HIGHMEM */
-
-/*
- * Map sz bytes so that it can be transferred.
- */
-static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
-			     int max_scatter, int min_sg_len)
-{
-	struct mmc_test_area *t = &test->area;
-	int err;
-
-	t->blocks = sz >> 9;
-
-	if (max_scatter) {
-		err = mmc_test_map_sg_max_scatter(t->mem, sz, t->sg,
-						  t->max_segs, t->max_seg_sz,
-				       &t->sg_len);
-	} else {
-		err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs,
-				      t->max_seg_sz, &t->sg_len, min_sg_len);
-	}
-	if (err)
-		pr_info("%s: Failed to map sg list\n",
-		       mmc_hostname(test->card->host));
-	return err;
-}
-
-/*
- * Transfer bytes mapped by mmc_test_area_map().
- */
-static int mmc_test_area_transfer(struct mmc_test_card *test,
-				  unsigned int dev_addr, int write)
-{
-	struct mmc_test_area *t = &test->area;
-
-	return mmc_test_simple_transfer(test, t->sg, t->sg_len, dev_addr,
-					t->blocks, 512, write);
-}
-
-/*
- * Map and transfer bytes for multiple transfers.
- */
-static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz,
-				unsigned int dev_addr, int write,
-				int max_scatter, int timed, int count,
-				bool nonblock, int min_sg_len)
-{
-	struct timespec ts1, ts2;
-	int ret = 0;
-	int i;
-	struct mmc_test_area *t = &test->area;
-
-	/*
-	 * In the case of a maximally scattered transfer, the maximum transfer
-	 * size is further limited by using PAGE_SIZE segments.
-	 */
-	if (max_scatter) {
-		struct mmc_test_area *t = &test->area;
-		unsigned long max_tfr;
-
-		if (t->max_seg_sz >= PAGE_SIZE)
-			max_tfr = t->max_segs * PAGE_SIZE;
-		else
-			max_tfr = t->max_segs * t->max_seg_sz;
-		if (sz > max_tfr)
-			sz = max_tfr;
-	}
-
-	ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len);
-	if (ret)
-		return ret;
-
-	if (timed)
-		getnstimeofday(&ts1);
-	if (nonblock)
-		ret = mmc_test_nonblock_transfer(test, t->sg, t->sg_len,
-				 dev_addr, t->blocks, 512, write, count);
-	else
-		for (i = 0; i < count && ret == 0; i++) {
-			ret = mmc_test_area_transfer(test, dev_addr, write);
-			dev_addr += sz >> 9;
-		}
-
-	if (ret)
-		return ret;
-
-	if (timed)
-		getnstimeofday(&ts2);
-
-	if (timed)
-		mmc_test_print_avg_rate(test, sz, count, &ts1, &ts2);
-
-	return 0;
-}
-
-static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
-			    unsigned int dev_addr, int write, int max_scatter,
-			    int timed)
-{
-	return mmc_test_area_io_seq(test, sz, dev_addr, write, max_scatter,
-				    timed, 1, false, 0);
-}
-
-/*
- * Write the test area entirely.
- */
-static int mmc_test_area_fill(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-
-	return mmc_test_area_io(test, t->max_tfr, t->dev_addr, 1, 0, 0);
-}
-
-/*
- * Erase the test area entirely.
- */
-static int mmc_test_area_erase(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-
-	if (!mmc_can_erase(test->card))
-		return 0;
-
-	return mmc_erase(test->card, t->dev_addr, t->max_sz >> 9,
-			 MMC_ERASE_ARG);
-}
-
-/*
- * Cleanup struct mmc_test_area.
- */
-static int mmc_test_area_cleanup(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-
-	kfree(t->sg);
-	mmc_test_free_mem(t->mem);
-
-	return 0;
-}
-
-/*
- * Initialize an area for testing large transfers.  The test area is set to the
- * middle of the card because cards may have different charateristics at the
- * front (for FAT file system optimization).  Optionally, the area is erased
- * (if the card supports it) which may improve write performance.  Optionally,
- * the area is filled with data for subsequent read tests.
- */
-static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long min_sz = 64 * 1024, sz;
-	int ret;
-
-	ret = mmc_test_set_blksize(test, 512);
-	if (ret)
-		return ret;
-
-	/* Make the test area size about 4MiB */
-	sz = (unsigned long)test->card->pref_erase << 9;
-	t->max_sz = sz;
-	while (t->max_sz < 4 * 1024 * 1024)
-		t->max_sz += sz;
-	while (t->max_sz > TEST_AREA_MAX_SIZE && t->max_sz > sz)
-		t->max_sz -= sz;
-
-	t->max_segs = test->card->host->max_segs;
-	t->max_seg_sz = test->card->host->max_seg_size;
-	t->max_seg_sz -= t->max_seg_sz % 512;
-
-	t->max_tfr = t->max_sz;
-	if (t->max_tfr >> 9 > test->card->host->max_blk_count)
-		t->max_tfr = test->card->host->max_blk_count << 9;
-	if (t->max_tfr > test->card->host->max_req_size)
-		t->max_tfr = test->card->host->max_req_size;
-	if (t->max_tfr / t->max_seg_sz > t->max_segs)
-		t->max_tfr = t->max_segs * t->max_seg_sz;
-
-	/*
-	 * Try to allocate enough memory for a max. sized transfer.  Less is OK
-	 * because the same memory can be mapped into the scatterlist more than
-	 * once.  Also, take into account the limits imposed on scatterlist
-	 * segments by the host driver.
-	 */
-	t->mem = mmc_test_alloc_mem(min_sz, t->max_tfr, t->max_segs,
-				    t->max_seg_sz);
-	if (!t->mem)
-		return -ENOMEM;
-
-	t->sg = kmalloc(sizeof(struct scatterlist) * t->max_segs, GFP_KERNEL);
-	if (!t->sg) {
-		ret = -ENOMEM;
-		goto out_free;
-	}
-
-	t->dev_addr = mmc_test_capacity(test->card) / 2;
-	t->dev_addr -= t->dev_addr % (t->max_sz >> 9);
-
-	if (erase) {
-		ret = mmc_test_area_erase(test);
-		if (ret)
-			goto out_free;
-	}
-
-	if (fill) {
-		ret = mmc_test_area_fill(test);
-		if (ret)
-			goto out_free;
-	}
-
-	return 0;
-
-out_free:
-	mmc_test_area_cleanup(test);
-	return ret;
-}
-
-/*
- * Prepare for large transfers.  Do not erase the test area.
- */
-static int mmc_test_area_prepare(struct mmc_test_card *test)
-{
-	return mmc_test_area_init(test, 0, 0);
-}
-
-/*
- * Prepare for large transfers.  Do erase the test area.
- */
-static int mmc_test_area_prepare_erase(struct mmc_test_card *test)
-{
-	return mmc_test_area_init(test, 1, 0);
-}
-
-/*
- * Prepare for large transfers.  Erase and fill the test area.
- */
-static int mmc_test_area_prepare_fill(struct mmc_test_card *test)
-{
-	return mmc_test_area_init(test, 1, 1);
-}
-
-/*
- * Test best-case performance.  Best-case performance is expected from
- * a single large transfer.
- *
- * An additional option (max_scatter) allows the measurement of the same
- * transfer but with no contiguous pages in the scatter list.  This tests
- * the efficiency of DMA to handle scattered pages.
- */
-static int mmc_test_best_performance(struct mmc_test_card *test, int write,
-				     int max_scatter)
-{
-	struct mmc_test_area *t = &test->area;
-
-	return mmc_test_area_io(test, t->max_tfr, t->dev_addr, write,
-				max_scatter, 1);
-}
-
-/*
- * Best-case read performance.
- */
-static int mmc_test_best_read_performance(struct mmc_test_card *test)
-{
-	return mmc_test_best_performance(test, 0, 0);
-}
-
-/*
- * Best-case write performance.
- */
-static int mmc_test_best_write_performance(struct mmc_test_card *test)
-{
-	return mmc_test_best_performance(test, 1, 0);
-}
-
-/*
- * Best-case read performance into scattered pages.
- */
-static int mmc_test_best_read_perf_max_scatter(struct mmc_test_card *test)
-{
-	return mmc_test_best_performance(test, 0, 1);
-}
-
-/*
- * Best-case write performance from scattered pages.
- */
-static int mmc_test_best_write_perf_max_scatter(struct mmc_test_card *test)
-{
-	return mmc_test_best_performance(test, 1, 1);
-}
-
-/*
- * Single read performance by transfer size.
- */
-static int mmc_test_profile_read_perf(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long sz;
-	unsigned int dev_addr;
-	int ret;
-
-	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
-		dev_addr = t->dev_addr + (sz >> 9);
-		ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 1);
-		if (ret)
-			return ret;
-	}
-	sz = t->max_tfr;
-	dev_addr = t->dev_addr;
-	return mmc_test_area_io(test, sz, dev_addr, 0, 0, 1);
-}
-
-/*
- * Single write performance by transfer size.
- */
-static int mmc_test_profile_write_perf(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long sz;
-	unsigned int dev_addr;
-	int ret;
-
-	ret = mmc_test_area_erase(test);
-	if (ret)
-		return ret;
-	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
-		dev_addr = t->dev_addr + (sz >> 9);
-		ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 1);
-		if (ret)
-			return ret;
-	}
-	ret = mmc_test_area_erase(test);
-	if (ret)
-		return ret;
-	sz = t->max_tfr;
-	dev_addr = t->dev_addr;
-	return mmc_test_area_io(test, sz, dev_addr, 1, 0, 1);
-}
-
-/*
- * Single trim performance by transfer size.
- */
-static int mmc_test_profile_trim_perf(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long sz;
-	unsigned int dev_addr;
-	struct timespec ts1, ts2;
-	int ret;
-
-	if (!mmc_can_trim(test->card))
-		return RESULT_UNSUP_CARD;
-
-	if (!mmc_can_erase(test->card))
-		return RESULT_UNSUP_HOST;
-
-	for (sz = 512; sz < t->max_sz; sz <<= 1) {
-		dev_addr = t->dev_addr + (sz >> 9);
-		getnstimeofday(&ts1);
-		ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG);
-		if (ret)
-			return ret;
-		getnstimeofday(&ts2);
-		mmc_test_print_rate(test, sz, &ts1, &ts2);
-	}
-	dev_addr = t->dev_addr;
-	getnstimeofday(&ts1);
-	ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG);
-	if (ret)
-		return ret;
-	getnstimeofday(&ts2);
-	mmc_test_print_rate(test, sz, &ts1, &ts2);
-	return 0;
-}
-
-static int mmc_test_seq_read_perf(struct mmc_test_card *test, unsigned long sz)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned int dev_addr, i, cnt;
-	struct timespec ts1, ts2;
-	int ret;
-
-	cnt = t->max_sz / sz;
-	dev_addr = t->dev_addr;
-	getnstimeofday(&ts1);
-	for (i = 0; i < cnt; i++) {
-		ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 0);
-		if (ret)
-			return ret;
-		dev_addr += (sz >> 9);
-	}
-	getnstimeofday(&ts2);
-	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
-	return 0;
-}
-
-/*
- * Consecutive read performance by transfer size.
- */
-static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long sz;
-	int ret;
-
-	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
-		ret = mmc_test_seq_read_perf(test, sz);
-		if (ret)
-			return ret;
-	}
-	sz = t->max_tfr;
-	return mmc_test_seq_read_perf(test, sz);
-}
-
-static int mmc_test_seq_write_perf(struct mmc_test_card *test, unsigned long sz)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned int dev_addr, i, cnt;
-	struct timespec ts1, ts2;
-	int ret;
-
-	ret = mmc_test_area_erase(test);
-	if (ret)
-		return ret;
-	cnt = t->max_sz / sz;
-	dev_addr = t->dev_addr;
-	getnstimeofday(&ts1);
-	for (i = 0; i < cnt; i++) {
-		ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 0);
-		if (ret)
-			return ret;
-		dev_addr += (sz >> 9);
-	}
-	getnstimeofday(&ts2);
-	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
-	return 0;
-}
-
-/*
- * Consecutive write performance by transfer size.
- */
-static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long sz;
-	int ret;
-
-	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
-		ret = mmc_test_seq_write_perf(test, sz);
-		if (ret)
-			return ret;
-	}
-	sz = t->max_tfr;
-	return mmc_test_seq_write_perf(test, sz);
-}
-
-/*
- * Consecutive trim performance by transfer size.
- */
-static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long sz;
-	unsigned int dev_addr, i, cnt;
-	struct timespec ts1, ts2;
-	int ret;
-
-	if (!mmc_can_trim(test->card))
-		return RESULT_UNSUP_CARD;
-
-	if (!mmc_can_erase(test->card))
-		return RESULT_UNSUP_HOST;
-
-	for (sz = 512; sz <= t->max_sz; sz <<= 1) {
-		ret = mmc_test_area_erase(test);
-		if (ret)
-			return ret;
-		ret = mmc_test_area_fill(test);
-		if (ret)
-			return ret;
-		cnt = t->max_sz / sz;
-		dev_addr = t->dev_addr;
-		getnstimeofday(&ts1);
-		for (i = 0; i < cnt; i++) {
-			ret = mmc_erase(test->card, dev_addr, sz >> 9,
-					MMC_TRIM_ARG);
-			if (ret)
-				return ret;
-			dev_addr += (sz >> 9);
-		}
-		getnstimeofday(&ts2);
-		mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
-	}
-	return 0;
-}
-
-static unsigned int rnd_next = 1;
-
-static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
-{
-	uint64_t r;
-
-	rnd_next = rnd_next * 1103515245 + 12345;
-	r = (rnd_next >> 16) & 0x7fff;
-	return (r * rnd_cnt) >> 15;
-}
-
-static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
-			     unsigned long sz)
-{
-	unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
-	unsigned int ssz;
-	struct timespec ts1, ts2, ts;
-	int ret;
-
-	ssz = sz >> 9;
-
-	rnd_addr = mmc_test_capacity(test->card) / 4;
-	range1 = rnd_addr / test->card->pref_erase;
-	range2 = range1 / ssz;
-
-	getnstimeofday(&ts1);
-	for (cnt = 0; cnt < UINT_MAX; cnt++) {
-		getnstimeofday(&ts2);
-		ts = timespec_sub(ts2, ts1);
-		if (ts.tv_sec >= 10)
-			break;
-		ea = mmc_test_rnd_num(range1);
-		if (ea == last_ea)
-			ea -= 1;
-		last_ea = ea;
-		dev_addr = rnd_addr + test->card->pref_erase * ea +
-			   ssz * mmc_test_rnd_num(range2);
-		ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
-		if (ret)
-			return ret;
-	}
-	if (print)
-		mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
-	return 0;
-}
-
-static int mmc_test_random_perf(struct mmc_test_card *test, int write)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned int next;
-	unsigned long sz;
-	int ret;
-
-	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
-		/*
-		 * When writing, try to get more consistent results by running
-		 * the test twice with exactly the same I/O but outputting the
-		 * results only for the 2nd run.
-		 */
-		if (write) {
-			next = rnd_next;
-			ret = mmc_test_rnd_perf(test, write, 0, sz);
-			if (ret)
-				return ret;
-			rnd_next = next;
-		}
-		ret = mmc_test_rnd_perf(test, write, 1, sz);
-		if (ret)
-			return ret;
-	}
-	sz = t->max_tfr;
-	if (write) {
-		next = rnd_next;
-		ret = mmc_test_rnd_perf(test, write, 0, sz);
-		if (ret)
-			return ret;
-		rnd_next = next;
-	}
-	return mmc_test_rnd_perf(test, write, 1, sz);
-}
-
-/*
- * Random read performance by transfer size.
- */
-static int mmc_test_random_read_perf(struct mmc_test_card *test)
-{
-	return mmc_test_random_perf(test, 0);
-}
-
-/*
- * Random write performance by transfer size.
- */
-static int mmc_test_random_write_perf(struct mmc_test_card *test)
-{
-	return mmc_test_random_perf(test, 1);
-}
-
-static int mmc_test_seq_perf(struct mmc_test_card *test, int write,
-			     unsigned int tot_sz, int max_scatter)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned int dev_addr, i, cnt, sz, ssz;
-	struct timespec ts1, ts2;
-	int ret;
-
-	sz = t->max_tfr;
-
-	/*
-	 * In the case of a maximally scattered transfer, the maximum transfer
-	 * size is further limited by using PAGE_SIZE segments.
-	 */
-	if (max_scatter) {
-		unsigned long max_tfr;
-
-		if (t->max_seg_sz >= PAGE_SIZE)
-			max_tfr = t->max_segs * PAGE_SIZE;
-		else
-			max_tfr = t->max_segs * t->max_seg_sz;
-		if (sz > max_tfr)
-			sz = max_tfr;
-	}
-
-	ssz = sz >> 9;
-	dev_addr = mmc_test_capacity(test->card) / 4;
-	if (tot_sz > dev_addr << 9)
-		tot_sz = dev_addr << 9;
-	cnt = tot_sz / sz;
-	dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
-
-	getnstimeofday(&ts1);
-	for (i = 0; i < cnt; i++) {
-		ret = mmc_test_area_io(test, sz, dev_addr, write,
-				       max_scatter, 0);
-		if (ret)
-			return ret;
-		dev_addr += ssz;
-	}
-	getnstimeofday(&ts2);
-
-	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
-
-	return 0;
-}
-
-static int mmc_test_large_seq_perf(struct mmc_test_card *test, int write)
-{
-	int ret, i;
-
-	for (i = 0; i < 10; i++) {
-		ret = mmc_test_seq_perf(test, write, 10 * 1024 * 1024, 1);
-		if (ret)
-			return ret;
-	}
-	for (i = 0; i < 5; i++) {
-		ret = mmc_test_seq_perf(test, write, 100 * 1024 * 1024, 1);
-		if (ret)
-			return ret;
-	}
-	for (i = 0; i < 3; i++) {
-		ret = mmc_test_seq_perf(test, write, 1000 * 1024 * 1024, 1);
-		if (ret)
-			return ret;
-	}
-
-	return ret;
-}
-
-/*
- * Large sequential read performance.
- */
-static int mmc_test_large_seq_read_perf(struct mmc_test_card *test)
-{
-	return mmc_test_large_seq_perf(test, 0);
-}
-
-/*
- * Large sequential write performance.
- */
-static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
-{
-	return mmc_test_large_seq_perf(test, 1);
-}
-
-static int mmc_test_rw_multiple(struct mmc_test_card *test,
-				struct mmc_test_multiple_rw *tdata,
-				unsigned int reqsize, unsigned int size,
-				int min_sg_len)
-{
-	unsigned int dev_addr;
-	struct mmc_test_area *t = &test->area;
-	int ret = 0;
-
-	/* Set up test area */
-	if (size > mmc_test_capacity(test->card) / 2 * 512)
-		size = mmc_test_capacity(test->card) / 2 * 512;
-	if (reqsize > t->max_tfr)
-		reqsize = t->max_tfr;
-	dev_addr = mmc_test_capacity(test->card) / 4;
-	if ((dev_addr & 0xffff0000))
-		dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
-	else
-		dev_addr &= 0xfffff800; /* Round to 1MiB boundary */
-	if (!dev_addr)
-		goto err;
-
-	if (reqsize > size)
-		return 0;
-
-	/* prepare test area */
-	if (mmc_can_erase(test->card) &&
-	    tdata->prepare & MMC_TEST_PREP_ERASE) {
-		ret = mmc_erase(test->card, dev_addr,
-				size / 512, MMC_SECURE_ERASE_ARG);
-		if (ret)
-			ret = mmc_erase(test->card, dev_addr,
-					size / 512, MMC_ERASE_ARG);
-		if (ret)
-			goto err;
-	}
-
-	/* Run test */
-	ret = mmc_test_area_io_seq(test, reqsize, dev_addr,
-				   tdata->do_write, 0, 1, size / reqsize,
-				   tdata->do_nonblock_req, min_sg_len);
-	if (ret)
-		goto err;
-
-	return ret;
- err:
-	pr_info("[%s] error\n", __func__);
-	return ret;
-}
-
-static int mmc_test_rw_multiple_size(struct mmc_test_card *test,
-				     struct mmc_test_multiple_rw *rw)
-{
-	int ret = 0;
-	int i;
-	void *pre_req = test->card->host->ops->pre_req;
-	void *post_req = test->card->host->ops->post_req;
-
-	if (rw->do_nonblock_req &&
-	    ((!pre_req && post_req) || (pre_req && !post_req))) {
-		pr_info("error: only one of pre/post is defined\n");
-		return -EINVAL;
-	}
-
-	for (i = 0 ; i < rw->len && ret == 0; i++) {
-		ret = mmc_test_rw_multiple(test, rw, rw->bs[i], rw->size, 0);
-		if (ret)
-			break;
-	}
-	return ret;
-}
-
-static int mmc_test_rw_multiple_sg_len(struct mmc_test_card *test,
-				       struct mmc_test_multiple_rw *rw)
-{
-	int ret = 0;
-	int i;
-
-	for (i = 0 ; i < rw->len && ret == 0; i++) {
-		ret = mmc_test_rw_multiple(test, rw, 512*1024, rw->size,
-					   rw->sg_len[i]);
-		if (ret)
-			break;
-	}
-	return ret;
-}
-
-/*
- * Multiple blocking write 4k to 4 MB chunks
- */
-static int mmc_test_profile_mult_write_blocking_perf(struct mmc_test_card *test)
-{
-	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
-			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
-	struct mmc_test_multiple_rw test_data = {
-		.bs = bs,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(bs),
-		.do_write = true,
-		.do_nonblock_req = false,
-		.prepare = MMC_TEST_PREP_ERASE,
-	};
-
-	return mmc_test_rw_multiple_size(test, &test_data);
-};
-
-/*
- * Multiple non-blocking write 4k to 4 MB chunks
- */
-static int mmc_test_profile_mult_write_nonblock_perf(struct mmc_test_card *test)
-{
-	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
-			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
-	struct mmc_test_multiple_rw test_data = {
-		.bs = bs,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(bs),
-		.do_write = true,
-		.do_nonblock_req = true,
-		.prepare = MMC_TEST_PREP_ERASE,
-	};
-
-	return mmc_test_rw_multiple_size(test, &test_data);
-}
-
-/*
- * Multiple blocking read 4k to 4 MB chunks
- */
-static int mmc_test_profile_mult_read_blocking_perf(struct mmc_test_card *test)
-{
-	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
-			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
-	struct mmc_test_multiple_rw test_data = {
-		.bs = bs,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(bs),
-		.do_write = false,
-		.do_nonblock_req = false,
-		.prepare = MMC_TEST_PREP_NONE,
-	};
-
-	return mmc_test_rw_multiple_size(test, &test_data);
-}
-
-/*
- * Multiple non-blocking read 4k to 4 MB chunks
- */
-static int mmc_test_profile_mult_read_nonblock_perf(struct mmc_test_card *test)
-{
-	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
-			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
-	struct mmc_test_multiple_rw test_data = {
-		.bs = bs,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(bs),
-		.do_write = false,
-		.do_nonblock_req = true,
-		.prepare = MMC_TEST_PREP_NONE,
-	};
-
-	return mmc_test_rw_multiple_size(test, &test_data);
-}
-
-/*
- * Multiple blocking write 1 to 512 sg elements
- */
-static int mmc_test_profile_sglen_wr_blocking_perf(struct mmc_test_card *test)
-{
-	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
-				 1 << 7, 1 << 8, 1 << 9};
-	struct mmc_test_multiple_rw test_data = {
-		.sg_len = sg_len,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(sg_len),
-		.do_write = true,
-		.do_nonblock_req = false,
-		.prepare = MMC_TEST_PREP_ERASE,
-	};
-
-	return mmc_test_rw_multiple_sg_len(test, &test_data);
-};
-
-/*
- * Multiple non-blocking write 1 to 512 sg elements
- */
-static int mmc_test_profile_sglen_wr_nonblock_perf(struct mmc_test_card *test)
-{
-	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
-				 1 << 7, 1 << 8, 1 << 9};
-	struct mmc_test_multiple_rw test_data = {
-		.sg_len = sg_len,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(sg_len),
-		.do_write = true,
-		.do_nonblock_req = true,
-		.prepare = MMC_TEST_PREP_ERASE,
-	};
-
-	return mmc_test_rw_multiple_sg_len(test, &test_data);
-}
-
-/*
- * Multiple blocking read 1 to 512 sg elements
- */
-static int mmc_test_profile_sglen_r_blocking_perf(struct mmc_test_card *test)
-{
-	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
-				 1 << 7, 1 << 8, 1 << 9};
-	struct mmc_test_multiple_rw test_data = {
-		.sg_len = sg_len,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(sg_len),
-		.do_write = false,
-		.do_nonblock_req = false,
-		.prepare = MMC_TEST_PREP_NONE,
-	};
-
-	return mmc_test_rw_multiple_sg_len(test, &test_data);
-}
-
-/*
- * Multiple non-blocking read 1 to 512 sg elements
- */
-static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
-{
-	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
-				 1 << 7, 1 << 8, 1 << 9};
-	struct mmc_test_multiple_rw test_data = {
-		.sg_len = sg_len,
-		.size = TEST_AREA_MAX_SIZE,
-		.len = ARRAY_SIZE(sg_len),
-		.do_write = false,
-		.do_nonblock_req = true,
-		.prepare = MMC_TEST_PREP_NONE,
-	};
-
-	return mmc_test_rw_multiple_sg_len(test, &test_data);
-}
-
-/*
- * eMMC hardware reset.
- */
-static int mmc_test_reset(struct mmc_test_card *test)
-{
-	struct mmc_card *card = test->card;
-	struct mmc_host *host = card->host;
-	int err;
-
-	err = mmc_hw_reset(host);
-	if (!err)
-		return RESULT_OK;
-	else if (err == -EOPNOTSUPP)
-		return RESULT_UNSUP_HOST;
-
-	return RESULT_FAIL;
-}
-
-struct mmc_test_req {
-	struct mmc_request mrq;
-	struct mmc_command sbc;
-	struct mmc_command cmd;
-	struct mmc_command stop;
-	struct mmc_command status;
-	struct mmc_data data;
-};
-
-static struct mmc_test_req *mmc_test_req_alloc(void)
-{
-	struct mmc_test_req *rq = kzalloc(sizeof(*rq), GFP_KERNEL);
-
-	if (rq) {
-		rq->mrq.cmd = &rq->cmd;
-		rq->mrq.data = &rq->data;
-		rq->mrq.stop = &rq->stop;
-	}
-
-	return rq;
-}
-
-static int mmc_test_send_status(struct mmc_test_card *test,
-				struct mmc_command *cmd)
-{
-	memset(cmd, 0, sizeof(*cmd));
-
-	cmd->opcode = MMC_SEND_STATUS;
-	if (!mmc_host_is_spi(test->card->host))
-		cmd->arg = test->card->rca << 16;
-	cmd->flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
-
-	return mmc_wait_for_cmd(test->card->host, cmd, 0);
-}
-
-static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
-				     unsigned int dev_addr, int use_sbc,
-				     int repeat_cmd, int write, int use_areq)
-{
-	struct mmc_test_req *rq = mmc_test_req_alloc();
-	struct mmc_host *host = test->card->host;
-	struct mmc_test_area *t = &test->area;
-	struct mmc_test_async_req test_areq = { .test = test };
-	struct mmc_request *mrq;
-	unsigned long timeout;
-	bool expired = false;
-	int ret = 0, cmd_ret;
-	u32 status = 0;
-	int count = 0;
-
-	if (!rq)
-		return -ENOMEM;
-
-	mrq = &rq->mrq;
-	if (use_sbc)
-		mrq->sbc = &rq->sbc;
-	mrq->cap_cmd_during_tfr = true;
-
-	test_areq.areq.mrq = mrq;
-	test_areq.areq.err_check = mmc_test_check_result_async;
-
-	mmc_test_prepare_mrq(test, mrq, t->sg, t->sg_len, dev_addr, t->blocks,
-			     512, write);
-
-	if (use_sbc && t->blocks > 1 && !mrq->sbc) {
-		ret =  mmc_host_cmd23(host) ?
-		       RESULT_UNSUP_CARD :
-		       RESULT_UNSUP_HOST;
-		goto out_free;
-	}
-
-	/* Start ongoing data request */
-	if (use_areq) {
-		mmc_start_req(host, &test_areq.areq, &ret);
-		if (ret)
-			goto out_free;
-	} else {
-		mmc_wait_for_req(host, mrq);
-	}
-
-	timeout = jiffies + msecs_to_jiffies(3000);
-	do {
-		count += 1;
-
-		/* Send status command while data transfer in progress */
-		cmd_ret = mmc_test_send_status(test, &rq->status);
-		if (cmd_ret)
-			break;
-
-		status = rq->status.resp[0];
-		if (status & R1_ERROR) {
-			cmd_ret = -EIO;
-			break;
-		}
-
-		if (mmc_is_req_done(host, mrq))
-			break;
-
-		expired = time_after(jiffies, timeout);
-		if (expired) {
-			pr_info("%s: timeout waiting for Tran state status %#x\n",
-				mmc_hostname(host), status);
-			cmd_ret = -ETIMEDOUT;
-			break;
-		}
-	} while (repeat_cmd && R1_CURRENT_STATE(status) != R1_STATE_TRAN);
-
-	/* Wait for data request to complete */
-	if (use_areq)
-		mmc_start_req(host, NULL, &ret);
-	else
-		mmc_wait_for_req_done(test->card->host, mrq);
-
-	/*
-	 * For cap_cmd_during_tfr request, upper layer must send stop if
-	 * required.
-	 */
-	if (mrq->data->stop && (mrq->data->error || !mrq->sbc)) {
-		if (ret)
-			mmc_wait_for_cmd(host, mrq->data->stop, 0);
-		else
-			ret = mmc_wait_for_cmd(host, mrq->data->stop, 0);
-	}
-
-	if (ret)
-		goto out_free;
-
-	if (cmd_ret) {
-		pr_info("%s: Send Status failed: status %#x, error %d\n",
-			mmc_hostname(test->card->host), status, cmd_ret);
-	}
-
-	ret = mmc_test_check_result(test, mrq);
-	if (ret)
-		goto out_free;
-
-	ret = mmc_test_wait_busy(test);
-	if (ret)
-		goto out_free;
-
-	if (repeat_cmd && (t->blocks + 1) << 9 > t->max_tfr)
-		pr_info("%s: %d commands completed during transfer of %u blocks\n",
-			mmc_hostname(test->card->host), count, t->blocks);
-
-	if (cmd_ret)
-		ret = cmd_ret;
-out_free:
-	kfree(rq);
-
-	return ret;
-}
-
-static int __mmc_test_cmds_during_tfr(struct mmc_test_card *test,
-				      unsigned long sz, int use_sbc, int write,
-				      int use_areq)
-{
-	struct mmc_test_area *t = &test->area;
-	int ret;
-
-	if (!(test->card->host->caps & MMC_CAP_CMD_DURING_TFR))
-		return RESULT_UNSUP_HOST;
-
-	ret = mmc_test_area_map(test, sz, 0, 0);
-	if (ret)
-		return ret;
-
-	ret = mmc_test_ongoing_transfer(test, t->dev_addr, use_sbc, 0, write,
-					use_areq);
-	if (ret)
-		return ret;
-
-	return mmc_test_ongoing_transfer(test, t->dev_addr, use_sbc, 1, write,
-					 use_areq);
-}
-
-static int mmc_test_cmds_during_tfr(struct mmc_test_card *test, int use_sbc,
-				    int write, int use_areq)
-{
-	struct mmc_test_area *t = &test->area;
-	unsigned long sz;
-	int ret;
-
-	for (sz = 512; sz <= t->max_tfr; sz += 512) {
-		ret = __mmc_test_cmds_during_tfr(test, sz, use_sbc, write,
-						 use_areq);
-		if (ret)
-			return ret;
-	}
-	return 0;
-}
-
-/*
- * Commands during read - no Set Block Count (CMD23).
- */
-static int mmc_test_cmds_during_read(struct mmc_test_card *test)
-{
-	return mmc_test_cmds_during_tfr(test, 0, 0, 0);
-}
-
-/*
- * Commands during write - no Set Block Count (CMD23).
- */
-static int mmc_test_cmds_during_write(struct mmc_test_card *test)
-{
-	return mmc_test_cmds_during_tfr(test, 0, 1, 0);
-}
-
-/*
- * Commands during read - use Set Block Count (CMD23).
- */
-static int mmc_test_cmds_during_read_cmd23(struct mmc_test_card *test)
-{
-	return mmc_test_cmds_during_tfr(test, 1, 0, 0);
-}
-
-/*
- * Commands during write - use Set Block Count (CMD23).
- */
-static int mmc_test_cmds_during_write_cmd23(struct mmc_test_card *test)
-{
-	return mmc_test_cmds_during_tfr(test, 1, 1, 0);
-}
-
-/*
- * Commands during non-blocking read - use Set Block Count (CMD23).
- */
-static int mmc_test_cmds_during_read_cmd23_nonblock(struct mmc_test_card *test)
-{
-	return mmc_test_cmds_during_tfr(test, 1, 0, 1);
-}
-
-/*
- * Commands during non-blocking write - use Set Block Count (CMD23).
- */
-static int mmc_test_cmds_during_write_cmd23_nonblock(struct mmc_test_card *test)
-{
-	return mmc_test_cmds_during_tfr(test, 1, 1, 1);
-}
-
-static const struct mmc_test_case mmc_test_cases[] = {
-	{
-		.name = "Basic write (no data verification)",
-		.run = mmc_test_basic_write,
-	},
-
-	{
-		.name = "Basic read (no data verification)",
-		.run = mmc_test_basic_read,
-	},
-
-	{
-		.name = "Basic write (with data verification)",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_verify_write,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Basic read (with data verification)",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_verify_read,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Multi-block write",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_multi_write,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Multi-block read",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_multi_read,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Power of two block writes",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_pow2_write,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Power of two block reads",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_pow2_read,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Weird sized block writes",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_weird_write,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Weird sized block reads",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_weird_read,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Badly aligned write",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_align_write,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Badly aligned read",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_align_read,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Badly aligned multi-block write",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_align_multi_write,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Badly aligned multi-block read",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_align_multi_read,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Correct xfer_size at write (start failure)",
-		.run = mmc_test_xfersize_write,
-	},
-
-	{
-		.name = "Correct xfer_size at read (start failure)",
-		.run = mmc_test_xfersize_read,
-	},
-
-	{
-		.name = "Correct xfer_size at write (midway failure)",
-		.run = mmc_test_multi_xfersize_write,
-	},
-
-	{
-		.name = "Correct xfer_size at read (midway failure)",
-		.run = mmc_test_multi_xfersize_read,
-	},
-
-#ifdef CONFIG_HIGHMEM
-
-	{
-		.name = "Highmem write",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_write_high,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Highmem read",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_read_high,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Multi-block highmem write",
-		.prepare = mmc_test_prepare_write,
-		.run = mmc_test_multi_write_high,
-		.cleanup = mmc_test_cleanup,
-	},
-
-	{
-		.name = "Multi-block highmem read",
-		.prepare = mmc_test_prepare_read,
-		.run = mmc_test_multi_read_high,
-		.cleanup = mmc_test_cleanup,
-	},
-
-#else
-
-	{
-		.name = "Highmem write",
-		.run = mmc_test_no_highmem,
-	},
-
-	{
-		.name = "Highmem read",
-		.run = mmc_test_no_highmem,
-	},
-
-	{
-		.name = "Multi-block highmem write",
-		.run = mmc_test_no_highmem,
-	},
-
-	{
-		.name = "Multi-block highmem read",
-		.run = mmc_test_no_highmem,
-	},
-
-#endif /* CONFIG_HIGHMEM */
-
-	{
-		.name = "Best-case read performance",
-		.prepare = mmc_test_area_prepare_fill,
-		.run = mmc_test_best_read_performance,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Best-case write performance",
-		.prepare = mmc_test_area_prepare_erase,
-		.run = mmc_test_best_write_performance,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Best-case read performance into scattered pages",
-		.prepare = mmc_test_area_prepare_fill,
-		.run = mmc_test_best_read_perf_max_scatter,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Best-case write performance from scattered pages",
-		.prepare = mmc_test_area_prepare_erase,
-		.run = mmc_test_best_write_perf_max_scatter,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Single read performance by transfer size",
-		.prepare = mmc_test_area_prepare_fill,
-		.run = mmc_test_profile_read_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Single write performance by transfer size",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_write_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Single trim performance by transfer size",
-		.prepare = mmc_test_area_prepare_fill,
-		.run = mmc_test_profile_trim_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Consecutive read performance by transfer size",
-		.prepare = mmc_test_area_prepare_fill,
-		.run = mmc_test_profile_seq_read_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Consecutive write performance by transfer size",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_seq_write_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Consecutive trim performance by transfer size",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_seq_trim_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Random read performance by transfer size",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_random_read_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Random write performance by transfer size",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_random_write_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Large sequential read into scattered pages",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_large_seq_read_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Large sequential write from scattered pages",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_large_seq_write_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Write performance with blocking req 4k to 4MB",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_mult_write_blocking_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Write performance with non-blocking req 4k to 4MB",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_mult_write_nonblock_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Read performance with blocking req 4k to 4MB",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_mult_read_blocking_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Read performance with non-blocking req 4k to 4MB",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_mult_read_nonblock_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Write performance blocking req 1 to 512 sg elems",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_sglen_wr_blocking_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Write performance non-blocking req 1 to 512 sg elems",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_sglen_wr_nonblock_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Read performance blocking req 1 to 512 sg elems",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_sglen_r_blocking_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Read performance non-blocking req 1 to 512 sg elems",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_profile_sglen_r_nonblock_perf,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Reset test",
-		.run = mmc_test_reset,
-	},
-
-	{
-		.name = "Commands during read - no Set Block Count (CMD23)",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_cmds_during_read,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Commands during write - no Set Block Count (CMD23)",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_cmds_during_write,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Commands during read - use Set Block Count (CMD23)",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_cmds_during_read_cmd23,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Commands during write - use Set Block Count (CMD23)",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_cmds_during_write_cmd23,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Commands during non-blocking read - use Set Block Count (CMD23)",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_cmds_during_read_cmd23_nonblock,
-		.cleanup = mmc_test_area_cleanup,
-	},
-
-	{
-		.name = "Commands during non-blocking write - use Set Block Count (CMD23)",
-		.prepare = mmc_test_area_prepare,
-		.run = mmc_test_cmds_during_write_cmd23_nonblock,
-		.cleanup = mmc_test_area_cleanup,
-	},
-};
-
-static DEFINE_MUTEX(mmc_test_lock);
-
-static LIST_HEAD(mmc_test_result);
-
-static void mmc_test_run(struct mmc_test_card *test, int testcase)
-{
-	int i, ret;
-
-	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);
-
-	for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
-		struct mmc_test_general_result *gr;
-
-		if (testcase && ((i + 1) != testcase))
-			continue;
-
-		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) {
-				pr_info("%s: Result: Prepare "
-					"stage failed! (%d)\n",
-					mmc_hostname(test->card->host),
-					ret);
-				continue;
-			}
-		}
-
-		gr = kzalloc(sizeof(struct mmc_test_general_result),
-			GFP_KERNEL);
-		if (gr) {
-			INIT_LIST_HEAD(&gr->tr_lst);
-
-			/* Assign data what we know already */
-			gr->card = test->card;
-			gr->testcase = i;
-
-			/* Append container to global one */
-			list_add_tail(&gr->link, &mmc_test_result);
-
-			/*
-			 * Save the pointer to created container in our private
-			 * structure.
-			 */
-			test->gr = gr;
-		}
-
-		ret = mmc_test_cases[i].run(test);
-		switch (ret) {
-		case RESULT_OK:
-			pr_info("%s: Result: OK\n",
-				mmc_hostname(test->card->host));
-			break;
-		case RESULT_FAIL:
-			pr_info("%s: Result: FAILED\n",
-				mmc_hostname(test->card->host));
-			break;
-		case RESULT_UNSUP_HOST:
-			pr_info("%s: Result: UNSUPPORTED "
-				"(by host)\n",
-				mmc_hostname(test->card->host));
-			break;
-		case RESULT_UNSUP_CARD:
-			pr_info("%s: Result: UNSUPPORTED "
-				"(by card)\n",
-				mmc_hostname(test->card->host));
-			break;
-		default:
-			pr_info("%s: Result: ERROR (%d)\n",
-				mmc_hostname(test->card->host), ret);
-		}
-
-		/* Save the result */
-		if (gr)
-			gr->result = ret;
-
-		if (mmc_test_cases[i].cleanup) {
-			ret = mmc_test_cases[i].cleanup(test);
-			if (ret) {
-				pr_info("%s: Warning: Cleanup "
-					"stage failed! (%d)\n",
-					mmc_hostname(test->card->host),
-					ret);
-			}
-		}
-	}
-
-	mmc_release_host(test->card->host);
-
-	pr_info("%s: Tests completed.\n",
-		mmc_hostname(test->card->host));
-}
-
-static void mmc_test_free_result(struct mmc_card *card)
-{
-	struct mmc_test_general_result *gr, *grs;
-
-	mutex_lock(&mmc_test_lock);
-
-	list_for_each_entry_safe(gr, grs, &mmc_test_result, link) {
-		struct mmc_test_transfer_result *tr, *trs;
-
-		if (card && gr->card != card)
-			continue;
-
-		list_for_each_entry_safe(tr, trs, &gr->tr_lst, link) {
-			list_del(&tr->link);
-			kfree(tr);
-		}
-
-		list_del(&gr->link);
-		kfree(gr);
-	}
-
-	mutex_unlock(&mmc_test_lock);
-}
-
-static LIST_HEAD(mmc_test_file_test);
-
-static int mtf_test_show(struct seq_file *sf, void *data)
-{
-	struct mmc_card *card = (struct mmc_card *)sf->private;
-	struct mmc_test_general_result *gr;
-
-	mutex_lock(&mmc_test_lock);
-
-	list_for_each_entry(gr, &mmc_test_result, link) {
-		struct mmc_test_transfer_result *tr;
-
-		if (gr->card != card)
-			continue;
-
-		seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
-
-		list_for_each_entry(tr, &gr->tr_lst, link) {
-			seq_printf(sf, "%u %d %lu.%09lu %u %u.%02u\n",
-				tr->count, tr->sectors,
-				(unsigned long)tr->ts.tv_sec,
-				(unsigned long)tr->ts.tv_nsec,
-				tr->rate, tr->iops / 100, tr->iops % 100);
-		}
-	}
-
-	mutex_unlock(&mmc_test_lock);
-
-	return 0;
-}
-
-static int mtf_test_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, mtf_test_show, inode->i_private);
-}
-
-static ssize_t mtf_test_write(struct file *file, const char __user *buf,
-	size_t count, loff_t *pos)
-{
-	struct seq_file *sf = (struct seq_file *)file->private_data;
-	struct mmc_card *card = (struct mmc_card *)sf->private;
-	struct mmc_test_card *test;
-	long testcase;
-	int ret;
-
-	ret = kstrtol_from_user(buf, count, 10, &testcase);
-	if (ret)
-		return ret;
-
-	test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
-	if (!test)
-		return -ENOMEM;
-
-	/*
-	 * Remove all test cases associated with given card. Thus we have only
-	 * actual data of the last run.
-	 */
-	mmc_test_free_result(card);
-
-	test->card = card;
-
-	test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
-#ifdef CONFIG_HIGHMEM
-	test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
-#endif
-
-#ifdef CONFIG_HIGHMEM
-	if (test->buffer && test->highmem) {
-#else
-	if (test->buffer) {
-#endif
-		mutex_lock(&mmc_test_lock);
-		mmc_test_run(test, testcase);
-		mutex_unlock(&mmc_test_lock);
-	}
-
-#ifdef CONFIG_HIGHMEM
-	__free_pages(test->highmem, BUFFER_ORDER);
-#endif
-	kfree(test->buffer);
-	kfree(test);
-
-	return count;
-}
-
-static const struct file_operations mmc_test_fops_test = {
-	.open		= mtf_test_open,
-	.read		= seq_read,
-	.write		= mtf_test_write,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int mtf_testlist_show(struct seq_file *sf, void *data)
-{
-	int i;
-
-	mutex_lock(&mmc_test_lock);
-
-	seq_printf(sf, "0:\tRun all tests\n");
-	for (i = 0; i < ARRAY_SIZE(mmc_test_cases); i++)
-		seq_printf(sf, "%d:\t%s\n", i+1, mmc_test_cases[i].name);
-
-	mutex_unlock(&mmc_test_lock);
-
-	return 0;
-}
-
-static int mtf_testlist_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, mtf_testlist_show, inode->i_private);
-}
-
-static const struct file_operations mmc_test_fops_testlist = {
-	.open		= mtf_testlist_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static void mmc_test_free_dbgfs_file(struct mmc_card *card)
-{
-	struct mmc_test_dbgfs_file *df, *dfs;
-
-	mutex_lock(&mmc_test_lock);
-
-	list_for_each_entry_safe(df, dfs, &mmc_test_file_test, link) {
-		if (card && df->card != card)
-			continue;
-		debugfs_remove(df->file);
-		list_del(&df->link);
-		kfree(df);
-	}
-
-	mutex_unlock(&mmc_test_lock);
-}
-
-static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
-	const char *name, umode_t mode, const struct file_operations *fops)
-{
-	struct dentry *file = NULL;
-	struct mmc_test_dbgfs_file *df;
-
-	if (card->debugfs_root)
-		file = debugfs_create_file(name, mode, card->debugfs_root,
-			card, fops);
-
-	if (IS_ERR_OR_NULL(file)) {
-		dev_err(&card->dev,
-			"Can't create %s. Perhaps debugfs is disabled.\n",
-			name);
-		return -ENODEV;
-	}
-
-	df = kmalloc(sizeof(struct mmc_test_dbgfs_file), GFP_KERNEL);
-	if (!df) {
-		debugfs_remove(file);
-		dev_err(&card->dev,
-			"Can't allocate memory for internal usage.\n");
-		return -ENOMEM;
-	}
-
-	df->card = card;
-	df->file = file;
-
-	list_add(&df->link, &mmc_test_file_test);
-	return 0;
-}
-
-static int mmc_test_register_dbgfs_file(struct mmc_card *card)
-{
-	int ret;
-
-	mutex_lock(&mmc_test_lock);
-
-	ret = __mmc_test_register_dbgfs_file(card, "test", S_IWUSR | S_IRUGO,
-		&mmc_test_fops_test);
-	if (ret)
-		goto err;
-
-	ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO,
-		&mmc_test_fops_testlist);
-	if (ret)
-		goto err;
-
-err:
-	mutex_unlock(&mmc_test_lock);
-
-	return ret;
-}
-
-static int mmc_test_probe(struct mmc_card *card)
-{
-	int ret;
-
-	if (!mmc_card_mmc(card) && !mmc_card_sd(card))
-		return -ENODEV;
-
-	ret = mmc_test_register_dbgfs_file(card);
-	if (ret)
-		return ret;
-
-	dev_info(&card->dev, "Card claimed for testing.\n");
-
-	return 0;
-}
-
-static void mmc_test_remove(struct mmc_card *card)
-{
-	mmc_test_free_result(card);
-	mmc_test_free_dbgfs_file(card);
-}
-
-static void mmc_test_shutdown(struct mmc_card *card)
-{
-}
-
-static struct mmc_driver mmc_driver = {
-	.drv		= {
-		.name	= "mmc_test",
-	},
-	.probe		= mmc_test_probe,
-	.remove		= mmc_test_remove,
-	.shutdown	= mmc_test_shutdown,
-};
-
-static int __init mmc_test_init(void)
-{
-	return mmc_register_driver(&mmc_driver);
-}
-
-static void __exit mmc_test_exit(void)
-{
-	/* Clear stalled data if card is still plugged */
-	mmc_test_free_result(NULL);
-	mmc_test_free_dbgfs_file(NULL);
-
-	mmc_unregister_driver(&mmc_driver);
-}
-
-module_init(mmc_test_init);
-module_exit(mmc_test_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver");
-MODULE_AUTHOR("Pierre Ossman");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/queue.c linux-libre-4.10-rc8-gnu/drivers/mmc/card/queue.c
--- linux-libre-4.9-gnu/drivers/mmc/card/queue.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/queue.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,557 +0,0 @@
-/*
- *  linux/drivers/mmc/card/queue.c
- *
- *  Copyright (C) 2003 Russell King, All Rights Reserved.
- *  Copyright 2006-2007 Pierre Ossman
- *
- * This program is free software; you can redistribute it 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/blkdev.h>
-#include <linux/freezer.h>
-#include <linux/kthread.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include "queue.h"
-#include "block.h"
-
-#define MMC_QUEUE_BOUNCESZ	65536
-
-/*
- * Prepare a MMC request. This just filters out odd stuff.
- */
-static int mmc_prep_request(struct request_queue *q, struct request *req)
-{
-	struct mmc_queue *mq = q->queuedata;
-
-	/*
-	 * We only like normal block requests and discards.
-	 */
-	if (req->cmd_type != REQ_TYPE_FS && req_op(req) != REQ_OP_DISCARD &&
-	    req_op(req) != REQ_OP_SECURE_ERASE) {
-		blk_dump_rq_flags(req, "MMC bad request");
-		return BLKPREP_KILL;
-	}
-
-	if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
-		return BLKPREP_KILL;
-
-	req->cmd_flags |= REQ_DONTPREP;
-
-	return BLKPREP_OK;
-}
-
-static int mmc_queue_thread(void *d)
-{
-	struct mmc_queue *mq = d;
-	struct request_queue *q = mq->queue;
-
-	current->flags |= PF_MEMALLOC;
-
-	down(&mq->thread_sem);
-	do {
-		struct request *req = NULL;
-
-		spin_lock_irq(q->queue_lock);
-		set_current_state(TASK_INTERRUPTIBLE);
-		req = blk_fetch_request(q);
-		mq->mqrq_cur->req = req;
-		spin_unlock_irq(q->queue_lock);
-
-		if (req || mq->mqrq_prev->req) {
-			bool req_is_special = mmc_req_is_special(req);
-
-			set_current_state(TASK_RUNNING);
-			mmc_blk_issue_rq(mq, req);
-			cond_resched();
-			if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
-				mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
-				continue; /* fetch again */
-			}
-
-			/*
-			 * Current request becomes previous request
-			 * and vice versa.
-			 * In case of special requests, current request
-			 * has been finished. Do not assign it to previous
-			 * request.
-			 */
-			if (req_is_special)
-				mq->mqrq_cur->req = NULL;
-
-			mq->mqrq_prev->brq.mrq.data = NULL;
-			mq->mqrq_prev->req = NULL;
-			swap(mq->mqrq_prev, mq->mqrq_cur);
-		} else {
-			if (kthread_should_stop()) {
-				set_current_state(TASK_RUNNING);
-				break;
-			}
-			up(&mq->thread_sem);
-			schedule();
-			down(&mq->thread_sem);
-		}
-	} while (1);
-	up(&mq->thread_sem);
-
-	return 0;
-}
-
-/*
- * Generic MMC request handler.  This is called for any queue on a
- * particular host.  When the host is not busy, we look for a request
- * on any queue on this host, and attempt to issue it.  This may
- * not be the queue we were asked to process.
- */
-static void mmc_request_fn(struct request_queue *q)
-{
-	struct mmc_queue *mq = q->queuedata;
-	struct request *req;
-	unsigned long flags;
-	struct mmc_context_info *cntx;
-
-	if (!mq) {
-		while ((req = blk_fetch_request(q)) != NULL) {
-			req->cmd_flags |= REQ_QUIET;
-			__blk_end_request_all(req, -EIO);
-		}
-		return;
-	}
-
-	cntx = &mq->card->host->context_info;
-	if (!mq->mqrq_cur->req && mq->mqrq_prev->req) {
-		/*
-		 * New MMC request arrived when MMC thread may be
-		 * blocked on the previous request to be complete
-		 * with no current request fetched
-		 */
-		spin_lock_irqsave(&cntx->lock, flags);
-		if (cntx->is_waiting_last_req) {
-			cntx->is_new_req = true;
-			wake_up_interruptible(&cntx->wait);
-		}
-		spin_unlock_irqrestore(&cntx->lock, flags);
-	} else if (!mq->mqrq_cur->req && !mq->mqrq_prev->req)
-		wake_up_process(mq->thread);
-}
-
-static struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
-{
-	struct scatterlist *sg;
-
-	sg = kmalloc(sizeof(struct scatterlist)*sg_len, GFP_KERNEL);
-	if (!sg)
-		*err = -ENOMEM;
-	else {
-		*err = 0;
-		sg_init_table(sg, sg_len);
-	}
-
-	return sg;
-}
-
-static void mmc_queue_setup_discard(struct request_queue *q,
-				    struct mmc_card *card)
-{
-	unsigned max_discard;
-
-	max_discard = mmc_calc_max_discard(card);
-	if (!max_discard)
-		return;
-
-	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
-	blk_queue_max_discard_sectors(q, max_discard);
-	if (card->erased_byte == 0 && !mmc_can_discard(card))
-		q->limits.discard_zeroes_data = 1;
-	q->limits.discard_granularity = card->pref_erase << 9;
-	/* 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))
-		queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q);
-}
-
-/**
- * mmc_init_queue - initialise a queue structure.
- * @mq: mmc queue
- * @card: mmc card to attach this queue
- * @lock: queue lock
- * @subname: partition subname
- *
- * Initialise a MMC card request queue.
- */
-int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
-		   spinlock_t *lock, const char *subname)
-{
-	struct mmc_host *host = card->host;
-	u64 limit = BLK_BOUNCE_HIGH;
-	int ret;
-	struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
-	struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
-
-	if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
-		limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
-
-	mq->card = card;
-	mq->queue = blk_init_queue(mmc_request_fn, lock);
-	if (!mq->queue)
-		return -ENOMEM;
-
-	mq->mqrq_cur = mqrq_cur;
-	mq->mqrq_prev = mqrq_prev;
-	mq->queue->queuedata = mq;
-
-	blk_queue_prep_rq(mq->queue, mmc_prep_request);
-	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
-	queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, mq->queue);
-	if (mmc_can_erase(card))
-		mmc_queue_setup_discard(mq->queue, card);
-
-#ifdef CONFIG_MMC_BLOCK_BOUNCE
-	if (host->max_segs == 1) {
-		unsigned int bouncesz;
-
-		bouncesz = MMC_QUEUE_BOUNCESZ;
-
-		if (bouncesz > host->max_req_size)
-			bouncesz = host->max_req_size;
-		if (bouncesz > host->max_seg_size)
-			bouncesz = host->max_seg_size;
-		if (bouncesz > (host->max_blk_count * 512))
-			bouncesz = host->max_blk_count * 512;
-
-		if (bouncesz > 512) {
-			mqrq_cur->bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
-			if (!mqrq_cur->bounce_buf) {
-				pr_warn("%s: unable to allocate bounce cur buffer\n",
-					mmc_card_name(card));
-			} else {
-				mqrq_prev->bounce_buf =
-						kmalloc(bouncesz, GFP_KERNEL);
-				if (!mqrq_prev->bounce_buf) {
-					pr_warn("%s: unable to allocate bounce prev buffer\n",
-						mmc_card_name(card));
-					kfree(mqrq_cur->bounce_buf);
-					mqrq_cur->bounce_buf = NULL;
-				}
-			}
-		}
-
-		if (mqrq_cur->bounce_buf && mqrq_prev->bounce_buf) {
-			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
-			blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
-			blk_queue_max_segments(mq->queue, bouncesz / 512);
-			blk_queue_max_segment_size(mq->queue, bouncesz);
-
-			mqrq_cur->sg = mmc_alloc_sg(1, &ret);
-			if (ret)
-				goto cleanup_queue;
-
-			mqrq_cur->bounce_sg =
-				mmc_alloc_sg(bouncesz / 512, &ret);
-			if (ret)
-				goto cleanup_queue;
-
-			mqrq_prev->sg = mmc_alloc_sg(1, &ret);
-			if (ret)
-				goto cleanup_queue;
-
-			mqrq_prev->bounce_sg =
-				mmc_alloc_sg(bouncesz / 512, &ret);
-			if (ret)
-				goto cleanup_queue;
-		}
-	}
-#endif
-
-	if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) {
-		blk_queue_bounce_limit(mq->queue, limit);
-		blk_queue_max_hw_sectors(mq->queue,
-			min(host->max_blk_count, host->max_req_size / 512));
-		blk_queue_max_segments(mq->queue, host->max_segs);
-		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
-
-		mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret);
-		if (ret)
-			goto cleanup_queue;
-
-
-		mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret);
-		if (ret)
-			goto cleanup_queue;
-	}
-
-	sema_init(&mq->thread_sem, 1);
-
-	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s",
-		host->index, subname ? subname : "");
-
-	if (IS_ERR(mq->thread)) {
-		ret = PTR_ERR(mq->thread);
-		goto free_bounce_sg;
-	}
-
-	return 0;
- free_bounce_sg:
-	kfree(mqrq_cur->bounce_sg);
-	mqrq_cur->bounce_sg = NULL;
-	kfree(mqrq_prev->bounce_sg);
-	mqrq_prev->bounce_sg = NULL;
-
- cleanup_queue:
-	kfree(mqrq_cur->sg);
-	mqrq_cur->sg = NULL;
-	kfree(mqrq_cur->bounce_buf);
-	mqrq_cur->bounce_buf = NULL;
-
-	kfree(mqrq_prev->sg);
-	mqrq_prev->sg = NULL;
-	kfree(mqrq_prev->bounce_buf);
-	mqrq_prev->bounce_buf = NULL;
-
-	blk_cleanup_queue(mq->queue);
-	return ret;
-}
-
-void mmc_cleanup_queue(struct mmc_queue *mq)
-{
-	struct request_queue *q = mq->queue;
-	unsigned long flags;
-	struct mmc_queue_req *mqrq_cur = mq->mqrq_cur;
-	struct mmc_queue_req *mqrq_prev = mq->mqrq_prev;
-
-	/* Make sure the queue isn't suspended, as that will deadlock */
-	mmc_queue_resume(mq);
-
-	/* Then terminate our worker thread */
-	kthread_stop(mq->thread);
-
-	/* Empty the queue */
-	spin_lock_irqsave(q->queue_lock, flags);
-	q->queuedata = NULL;
-	blk_start_queue(q);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-
-	kfree(mqrq_cur->bounce_sg);
-	mqrq_cur->bounce_sg = NULL;
-
-	kfree(mqrq_cur->sg);
-	mqrq_cur->sg = NULL;
-
-	kfree(mqrq_cur->bounce_buf);
-	mqrq_cur->bounce_buf = NULL;
-
-	kfree(mqrq_prev->bounce_sg);
-	mqrq_prev->bounce_sg = NULL;
-
-	kfree(mqrq_prev->sg);
-	mqrq_prev->sg = NULL;
-
-	kfree(mqrq_prev->bounce_buf);
-	mqrq_prev->bounce_buf = NULL;
-
-	mq->card = NULL;
-}
-EXPORT_SYMBOL(mmc_cleanup_queue);
-
-int mmc_packed_init(struct mmc_queue *mq, struct mmc_card *card)
-{
-	struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
-	struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
-	int ret = 0;
-
-
-	mqrq_cur->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL);
-	if (!mqrq_cur->packed) {
-		pr_warn("%s: unable to allocate packed cmd for mqrq_cur\n",
-			mmc_card_name(card));
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	mqrq_prev->packed = kzalloc(sizeof(struct mmc_packed), GFP_KERNEL);
-	if (!mqrq_prev->packed) {
-		pr_warn("%s: unable to allocate packed cmd for mqrq_prev\n",
-			mmc_card_name(card));
-		kfree(mqrq_cur->packed);
-		mqrq_cur->packed = NULL;
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	INIT_LIST_HEAD(&mqrq_cur->packed->list);
-	INIT_LIST_HEAD(&mqrq_prev->packed->list);
-
-out:
-	return ret;
-}
-
-void mmc_packed_clean(struct mmc_queue *mq)
-{
-	struct mmc_queue_req *mqrq_cur = &mq->mqrq[0];
-	struct mmc_queue_req *mqrq_prev = &mq->mqrq[1];
-
-	kfree(mqrq_cur->packed);
-	mqrq_cur->packed = NULL;
-	kfree(mqrq_prev->packed);
-	mqrq_prev->packed = NULL;
-}
-
-/**
- * mmc_queue_suspend - suspend a MMC request queue
- * @mq: MMC queue to suspend
- *
- * Stop the block request queue, and wait for our thread to
- * complete any outstanding requests.  This ensures that we
- * won't suspend while a request is being processed.
- */
-void mmc_queue_suspend(struct mmc_queue *mq)
-{
-	struct request_queue *q = mq->queue;
-	unsigned long flags;
-
-	if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
-		mq->flags |= MMC_QUEUE_SUSPENDED;
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_stop_queue(q);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-
-		down(&mq->thread_sem);
-	}
-}
-
-/**
- * mmc_queue_resume - resume a previously suspended MMC request queue
- * @mq: MMC queue to resume
- */
-void mmc_queue_resume(struct mmc_queue *mq)
-{
-	struct request_queue *q = mq->queue;
-	unsigned long flags;
-
-	if (mq->flags & MMC_QUEUE_SUSPENDED) {
-		mq->flags &= ~MMC_QUEUE_SUSPENDED;
-
-		up(&mq->thread_sem);
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_start_queue(q);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	}
-}
-
-static unsigned int mmc_queue_packed_map_sg(struct mmc_queue *mq,
-					    struct mmc_packed *packed,
-					    struct scatterlist *sg,
-					    enum mmc_packed_type cmd_type)
-{
-	struct scatterlist *__sg = sg;
-	unsigned int sg_len = 0;
-	struct request *req;
-
-	if (mmc_packed_wr(cmd_type)) {
-		unsigned int hdr_sz = mmc_large_sector(mq->card) ? 4096 : 512;
-		unsigned int max_seg_sz = queue_max_segment_size(mq->queue);
-		unsigned int len, remain, offset = 0;
-		u8 *buf = (u8 *)packed->cmd_hdr;
-
-		remain = hdr_sz;
-		do {
-			len = min(remain, max_seg_sz);
-			sg_set_buf(__sg, buf + offset, len);
-			offset += len;
-			remain -= len;
-			sg_unmark_end(__sg++);
-			sg_len++;
-		} while (remain);
-	}
-
-	list_for_each_entry(req, &packed->list, queuelist) {
-		sg_len += blk_rq_map_sg(mq->queue, req, __sg);
-		__sg = sg + (sg_len - 1);
-		sg_unmark_end(__sg++);
-	}
-	sg_mark_end(sg + (sg_len - 1));
-	return sg_len;
-}
-
-/*
- * Prepare the sg list(s) to be handed of to the host driver
- */
-unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
-{
-	unsigned int sg_len;
-	size_t buflen;
-	struct scatterlist *sg;
-	enum mmc_packed_type cmd_type;
-	int i;
-
-	cmd_type = mqrq->cmd_type;
-
-	if (!mqrq->bounce_buf) {
-		if (mmc_packed_cmd(cmd_type))
-			return mmc_queue_packed_map_sg(mq, mqrq->packed,
-						       mqrq->sg, cmd_type);
-		else
-			return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg);
-	}
-
-	BUG_ON(!mqrq->bounce_sg);
-
-	if (mmc_packed_cmd(cmd_type))
-		sg_len = mmc_queue_packed_map_sg(mq, mqrq->packed,
-						 mqrq->bounce_sg, cmd_type);
-	else
-		sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg);
-
-	mqrq->bounce_sg_len = sg_len;
-
-	buflen = 0;
-	for_each_sg(mqrq->bounce_sg, sg, sg_len, i)
-		buflen += sg->length;
-
-	sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen);
-
-	return 1;
-}
-
-/*
- * If writing, bounce the data to the buffer before the request
- * is sent to the host driver
- */
-void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
-{
-	if (!mqrq->bounce_buf)
-		return;
-
-	if (rq_data_dir(mqrq->req) != WRITE)
-		return;
-
-	sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
-		mqrq->bounce_buf, mqrq->sg[0].length);
-}
-
-/*
- * If reading, bounce the data from the buffer after the request
- * has been handled by the host driver
- */
-void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
-{
-	if (!mqrq->bounce_buf)
-		return;
-
-	if (rq_data_dir(mqrq->req) != READ)
-		return;
-
-	sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
-		mqrq->bounce_buf, mqrq->sg[0].length);
-}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/queue.h linux-libre-4.10-rc8-gnu/drivers/mmc/card/queue.h
--- linux-libre-4.9-gnu/drivers/mmc/card/queue.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/queue.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,83 +0,0 @@
-#ifndef MMC_QUEUE_H
-#define MMC_QUEUE_H
-
-static inline bool mmc_req_is_special(struct request *req)
-{
-	return req &&
-		(req_op(req) == REQ_OP_FLUSH ||
-		 req_op(req) == REQ_OP_DISCARD ||
-		 req_op(req) == REQ_OP_SECURE_ERASE);
-}
-
-struct request;
-struct task_struct;
-
-struct mmc_blk_request {
-	struct mmc_request	mrq;
-	struct mmc_command	sbc;
-	struct mmc_command	cmd;
-	struct mmc_command	stop;
-	struct mmc_data		data;
-	int			retune_retry_done;
-};
-
-enum mmc_packed_type {
-	MMC_PACKED_NONE = 0,
-	MMC_PACKED_WRITE,
-};
-
-#define mmc_packed_cmd(type)	((type) != MMC_PACKED_NONE)
-#define mmc_packed_wr(type)	((type) == MMC_PACKED_WRITE)
-
-struct mmc_packed {
-	struct list_head	list;
-	__le32			cmd_hdr[1024];
-	unsigned int		blocks;
-	u8			nr_entries;
-	u8			retries;
-	s16			idx_failure;
-};
-
-struct mmc_queue_req {
-	struct request		*req;
-	struct mmc_blk_request	brq;
-	struct scatterlist	*sg;
-	char			*bounce_buf;
-	struct scatterlist	*bounce_sg;
-	unsigned int		bounce_sg_len;
-	struct mmc_async_req	mmc_active;
-	enum mmc_packed_type	cmd_type;
-	struct mmc_packed	*packed;
-};
-
-struct mmc_queue {
-	struct mmc_card		*card;
-	struct task_struct	*thread;
-	struct semaphore	thread_sem;
-	unsigned int		flags;
-#define MMC_QUEUE_SUSPENDED	(1 << 0)
-#define MMC_QUEUE_NEW_REQUEST	(1 << 1)
-	void			*data;
-	struct request_queue	*queue;
-	struct mmc_queue_req	mqrq[2];
-	struct mmc_queue_req	*mqrq_cur;
-	struct mmc_queue_req	*mqrq_prev;
-};
-
-extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
-			  const char *);
-extern void mmc_cleanup_queue(struct mmc_queue *);
-extern void mmc_queue_suspend(struct mmc_queue *);
-extern void mmc_queue_resume(struct mmc_queue *);
-
-extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
-				     struct mmc_queue_req *);
-extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
-extern void mmc_queue_bounce_post(struct mmc_queue_req *);
-
-extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *);
-extern void mmc_packed_clean(struct mmc_queue *);
-
-extern int mmc_access_rpmb(struct mmc_queue *);
-
-#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/card/sdio_uart.c linux-libre-4.10-rc8-gnu/drivers/mmc/card/sdio_uart.c
--- linux-libre-4.9-gnu/drivers/mmc/card/sdio_uart.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/card/sdio_uart.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1202 +0,0 @@
-/*
- * linux/drivers/mmc/card/sdio_uart.c - SDIO UART/GPS driver
- *
- * Based on drivers/serial/8250.c and drivers/serial/serial_core.c
- * by Russell King.
- *
- * Author:	Nicolas Pitre
- * Created:	June 15, 2007
- * 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 as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- */
-
-/*
- * Note: Although this driver assumes a 16550A-like UART implementation,
- * it is not possible to leverage the common 8250/16550 driver, nor the
- * core UART infrastructure, as they assumes direct access to the hardware
- * registers, often under a spinlock.  This is not possible in the SDIO
- * context as SDIO access functions must be able to sleep.
- *
- * Because we need to lock the SDIO host to ensure an exclusive access to
- * the card, we simply rely on that lock to also prevent and serialize
- * concurrent access to the same port.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mutex.h>
-#include <linux/seq_file.h>
-#include <linux/serial_reg.h>
-#include <linux/circ_buf.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/kfifo.h>
-#include <linux/slab.h>
-
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-
-
-#define UART_NR		8	/* Number of UARTs this driver can handle */
-
-
-#define FIFO_SIZE	PAGE_SIZE
-#define WAKEUP_CHARS	256
-
-struct uart_icount {
-	__u32	cts;
-	__u32	dsr;
-	__u32	rng;
-	__u32	dcd;
-	__u32	rx;
-	__u32	tx;
-	__u32	frame;
-	__u32	overrun;
-	__u32	parity;
-	__u32	brk;
-};
-
-struct sdio_uart_port {
-	struct tty_port		port;
-	unsigned int		index;
-	struct sdio_func	*func;
-	struct mutex		func_lock;
-	struct task_struct	*in_sdio_uart_irq;
-	unsigned int		regs_offset;
-	struct kfifo		xmit_fifo;
-	spinlock_t		write_lock;
-	struct uart_icount	icount;
-	unsigned int		uartclk;
-	unsigned int		mctrl;
-	unsigned int		rx_mctrl;
-	unsigned int		read_status_mask;
-	unsigned int		ignore_status_mask;
-	unsigned char		x_char;
-	unsigned char           ier;
-	unsigned char           lcr;
-};
-
-static struct sdio_uart_port *sdio_uart_table[UART_NR];
-static DEFINE_SPINLOCK(sdio_uart_table_lock);
-
-static int sdio_uart_add_port(struct sdio_uart_port *port)
-{
-	int index, ret = -EBUSY;
-
-	mutex_init(&port->func_lock);
-	spin_lock_init(&port->write_lock);
-	if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL))
-		return -ENOMEM;
-
-	spin_lock(&sdio_uart_table_lock);
-	for (index = 0; index < UART_NR; index++) {
-		if (!sdio_uart_table[index]) {
-			port->index = index;
-			sdio_uart_table[index] = port;
-			ret = 0;
-			break;
-		}
-	}
-	spin_unlock(&sdio_uart_table_lock);
-
-	return ret;
-}
-
-static struct sdio_uart_port *sdio_uart_port_get(unsigned index)
-{
-	struct sdio_uart_port *port;
-
-	if (index >= UART_NR)
-		return NULL;
-
-	spin_lock(&sdio_uart_table_lock);
-	port = sdio_uart_table[index];
-	if (port)
-		tty_port_get(&port->port);
-	spin_unlock(&sdio_uart_table_lock);
-
-	return port;
-}
-
-static void sdio_uart_port_put(struct sdio_uart_port *port)
-{
-	tty_port_put(&port->port);
-}
-
-static void sdio_uart_port_remove(struct sdio_uart_port *port)
-{
-	struct sdio_func *func;
-
-	BUG_ON(sdio_uart_table[port->index] != port);
-
-	spin_lock(&sdio_uart_table_lock);
-	sdio_uart_table[port->index] = NULL;
-	spin_unlock(&sdio_uart_table_lock);
-
-	/*
-	 * We're killing a port that potentially still is in use by
-	 * the tty layer. Be careful to prevent any further access
-	 * to the SDIO function and arrange for the tty layer to
-	 * give up on that port ASAP.
-	 * Beware: the lock ordering is critical.
-	 */
-	mutex_lock(&port->port.mutex);
-	mutex_lock(&port->func_lock);
-	func = port->func;
-	sdio_claim_host(func);
-	port->func = NULL;
-	mutex_unlock(&port->func_lock);
-	/* tty_hangup is async so is this safe as is ?? */
-	tty_port_tty_hangup(&port->port, false);
-	mutex_unlock(&port->port.mutex);
-	sdio_release_irq(func);
-	sdio_disable_func(func);
-	sdio_release_host(func);
-
-	sdio_uart_port_put(port);
-}
-
-static int sdio_uart_claim_func(struct sdio_uart_port *port)
-{
-	mutex_lock(&port->func_lock);
-	if (unlikely(!port->func)) {
-		mutex_unlock(&port->func_lock);
-		return -ENODEV;
-	}
-	if (likely(port->in_sdio_uart_irq != current))
-		sdio_claim_host(port->func);
-	mutex_unlock(&port->func_lock);
-	return 0;
-}
-
-static inline void sdio_uart_release_func(struct sdio_uart_port *port)
-{
-	if (likely(port->in_sdio_uart_irq != current))
-		sdio_release_host(port->func);
-}
-
-static inline unsigned int sdio_in(struct sdio_uart_port *port, int offset)
-{
-	unsigned char c;
-	c = sdio_readb(port->func, port->regs_offset + offset, NULL);
-	return c;
-}
-
-static inline void sdio_out(struct sdio_uart_port *port, int offset, int value)
-{
-	sdio_writeb(port->func, value, port->regs_offset + offset, NULL);
-}
-
-static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port)
-{
-	unsigned char status;
-	unsigned int ret;
-
-	/* FIXME: What stops this losing the delta bits and breaking
-	   sdio_uart_check_modem_status ? */
-	status = sdio_in(port, UART_MSR);
-
-	ret = 0;
-	if (status & UART_MSR_DCD)
-		ret |= TIOCM_CAR;
-	if (status & UART_MSR_RI)
-		ret |= TIOCM_RNG;
-	if (status & UART_MSR_DSR)
-		ret |= TIOCM_DSR;
-	if (status & UART_MSR_CTS)
-		ret |= TIOCM_CTS;
-	return ret;
-}
-
-static void sdio_uart_write_mctrl(struct sdio_uart_port *port,
-				  unsigned int mctrl)
-{
-	unsigned char mcr = 0;
-
-	if (mctrl & TIOCM_RTS)
-		mcr |= UART_MCR_RTS;
-	if (mctrl & TIOCM_DTR)
-		mcr |= UART_MCR_DTR;
-	if (mctrl & TIOCM_OUT1)
-		mcr |= UART_MCR_OUT1;
-	if (mctrl & TIOCM_OUT2)
-		mcr |= UART_MCR_OUT2;
-	if (mctrl & TIOCM_LOOP)
-		mcr |= UART_MCR_LOOP;
-
-	sdio_out(port, UART_MCR, mcr);
-}
-
-static inline void sdio_uart_update_mctrl(struct sdio_uart_port *port,
-					  unsigned int set, unsigned int clear)
-{
-	unsigned int old;
-
-	old = port->mctrl;
-	port->mctrl = (old & ~clear) | set;
-	if (old != port->mctrl)
-		sdio_uart_write_mctrl(port, port->mctrl);
-}
-
-#define sdio_uart_set_mctrl(port, x)	sdio_uart_update_mctrl(port, x, 0)
-#define sdio_uart_clear_mctrl(port, x)	sdio_uart_update_mctrl(port, 0, x)
-
-static void sdio_uart_change_speed(struct sdio_uart_port *port,
-				   struct ktermios *termios,
-				   struct ktermios *old)
-{
-	unsigned char cval, fcr = 0;
-	unsigned int baud, quot;
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		cval = UART_LCR_WLEN5;
-		break;
-	case CS6:
-		cval = UART_LCR_WLEN6;
-		break;
-	case CS7:
-		cval = UART_LCR_WLEN7;
-		break;
-	default:
-	case CS8:
-		cval = UART_LCR_WLEN8;
-		break;
-	}
-
-	if (termios->c_cflag & CSTOPB)
-		cval |= UART_LCR_STOP;
-	if (termios->c_cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(termios->c_cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-
-	for (;;) {
-		baud = tty_termios_baud_rate(termios);
-		if (baud == 0)
-			baud = 9600;  /* Special case: B0 rate. */
-		if (baud <= port->uartclk)
-			break;
-		/*
-		 * Oops, the quotient was zero.  Try again with the old
-		 * baud rate if possible, otherwise default to 9600.
-		 */
-		termios->c_cflag &= ~CBAUD;
-		if (old) {
-			termios->c_cflag |= old->c_cflag & CBAUD;
-			old = NULL;
-		} else
-			termios->c_cflag |= B9600;
-	}
-	quot = (2 * port->uartclk + baud) / (2 * baud);
-
-	if (baud < 2400)
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
-	else
-		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
-
-	port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (termios->c_iflag & INPCK)
-		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		port->read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	port->ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (termios->c_iflag & IGNBRK) {
-		port->ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too (for real raw support).
-		 */
-		if (termios->c_iflag & IGNPAR)
-			port->ignore_status_mask |= UART_LSR_OE;
-	}
-
-	/*
-	 * ignore all characters if CREAD is not set
-	 */
-	if ((termios->c_cflag & CREAD) == 0)
-		port->ignore_status_mask |= UART_LSR_DR;
-
-	/*
-	 * CTS flow control flag and modem status interrupts
-	 */
-	port->ier &= ~UART_IER_MSI;
-	if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))
-		port->ier |= UART_IER_MSI;
-
-	port->lcr = cval;
-
-	sdio_out(port, UART_IER, port->ier);
-	sdio_out(port, UART_LCR, cval | UART_LCR_DLAB);
-	sdio_out(port, UART_DLL, quot & 0xff);
-	sdio_out(port, UART_DLM, quot >> 8);
-	sdio_out(port, UART_LCR, cval);
-	sdio_out(port, UART_FCR, fcr);
-
-	sdio_uart_write_mctrl(port, port->mctrl);
-}
-
-static void sdio_uart_start_tx(struct sdio_uart_port *port)
-{
-	if (!(port->ier & UART_IER_THRI)) {
-		port->ier |= UART_IER_THRI;
-		sdio_out(port, UART_IER, port->ier);
-	}
-}
-
-static void sdio_uart_stop_tx(struct sdio_uart_port *port)
-{
-	if (port->ier & UART_IER_THRI) {
-		port->ier &= ~UART_IER_THRI;
-		sdio_out(port, UART_IER, port->ier);
-	}
-}
-
-static void sdio_uart_stop_rx(struct sdio_uart_port *port)
-{
-	port->ier &= ~UART_IER_RLSI;
-	port->read_status_mask &= ~UART_LSR_DR;
-	sdio_out(port, UART_IER, port->ier);
-}
-
-static void sdio_uart_receive_chars(struct sdio_uart_port *port,
-				    unsigned int *status)
-{
-	unsigned int ch, flag;
-	int max_count = 256;
-
-	do {
-		ch = sdio_in(port, UART_RX);
-		flag = TTY_NORMAL;
-		port->icount.rx++;
-
-		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
-					UART_LSR_FE | UART_LSR_OE))) {
-			/*
-			 * For statistics only
-			 */
-			if (*status & UART_LSR_BI) {
-				*status &= ~(UART_LSR_FE | UART_LSR_PE);
-				port->icount.brk++;
-			} else if (*status & UART_LSR_PE)
-				port->icount.parity++;
-			else if (*status & UART_LSR_FE)
-				port->icount.frame++;
-			if (*status & UART_LSR_OE)
-				port->icount.overrun++;
-
-			/*
-			 * Mask off conditions which should be ignored.
-			 */
-			*status &= port->read_status_mask;
-			if (*status & UART_LSR_BI)
-				flag = TTY_BREAK;
-			else if (*status & UART_LSR_PE)
-				flag = TTY_PARITY;
-			else if (*status & UART_LSR_FE)
-				flag = TTY_FRAME;
-		}
-
-		if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
-			tty_insert_flip_char(&port->port, ch, flag);
-
-		/*
-		 * Overrun is special.  Since it's reported immediately,
-		 * it doesn't affect the current character.
-		 */
-		if (*status & ~port->ignore_status_mask & UART_LSR_OE)
-			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
-
-		*status = sdio_in(port, UART_LSR);
-	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
-
-	tty_flip_buffer_push(&port->port);
-}
-
-static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
-{
-	struct kfifo *xmit = &port->xmit_fifo;
-	int count;
-	struct tty_struct *tty;
-	u8 iobuf[16];
-	int len;
-
-	if (port->x_char) {
-		sdio_out(port, UART_TX, port->x_char);
-		port->icount.tx++;
-		port->x_char = 0;
-		return;
-	}
-
-	tty = tty_port_tty_get(&port->port);
-
-	if (tty == NULL || !kfifo_len(xmit) ||
-				tty->stopped || tty->hw_stopped) {
-		sdio_uart_stop_tx(port);
-		tty_kref_put(tty);
-		return;
-	}
-
-	len = kfifo_out_locked(xmit, iobuf, 16, &port->write_lock);
-	for (count = 0; count < len; count++) {
-		sdio_out(port, UART_TX, iobuf[count]);
-		port->icount.tx++;
-	}
-
-	len = kfifo_len(xmit);
-	if (len < WAKEUP_CHARS) {
-		tty_wakeup(tty);
-		if (len == 0)
-			sdio_uart_stop_tx(port);
-	}
-	tty_kref_put(tty);
-}
-
-static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
-{
-	int status;
-	struct tty_struct *tty;
-
-	status = sdio_in(port, UART_MSR);
-
-	if ((status & UART_MSR_ANY_DELTA) == 0)
-		return;
-
-	if (status & UART_MSR_TERI)
-		port->icount.rng++;
-	if (status & UART_MSR_DDSR)
-		port->icount.dsr++;
-	if (status & UART_MSR_DDCD) {
-		port->icount.dcd++;
-		/* DCD raise - wake for open */
-		if (status & UART_MSR_DCD)
-			wake_up_interruptible(&port->port.open_wait);
-		else {
-			/* DCD drop - hang up if tty attached */
-			tty_port_tty_hangup(&port->port, false);
-		}
-	}
-	if (status & UART_MSR_DCTS) {
-		port->icount.cts++;
-		tty = tty_port_tty_get(&port->port);
-		if (tty && C_CRTSCTS(tty)) {
-			int cts = (status & UART_MSR_CTS);
-			if (tty->hw_stopped) {
-				if (cts) {
-					tty->hw_stopped = 0;
-					sdio_uart_start_tx(port);
-					tty_wakeup(tty);
-				}
-			} else {
-				if (!cts) {
-					tty->hw_stopped = 1;
-					sdio_uart_stop_tx(port);
-				}
-			}
-		}
-		tty_kref_put(tty);
-	}
-}
-
-/*
- * This handles the interrupt from one port.
- */
-static void sdio_uart_irq(struct sdio_func *func)
-{
-	struct sdio_uart_port *port = sdio_get_drvdata(func);
-	unsigned int iir, lsr;
-
-	/*
-	 * In a few places sdio_uart_irq() is called directly instead of
-	 * waiting for the actual interrupt to be raised and the SDIO IRQ
-	 * thread scheduled in order to reduce latency.  However, some
-	 * interaction with the tty core may end up calling us back
-	 * (serial echo, flow control, etc.) through those same places
-	 * causing undesirable effects.  Let's stop the recursion here.
-	 */
-	if (unlikely(port->in_sdio_uart_irq == current))
-		return;
-
-	iir = sdio_in(port, UART_IIR);
-	if (iir & UART_IIR_NO_INT)
-		return;
-
-	port->in_sdio_uart_irq = current;
-	lsr = sdio_in(port, UART_LSR);
-	if (lsr & UART_LSR_DR)
-		sdio_uart_receive_chars(port, &lsr);
-	sdio_uart_check_modem_status(port);
-	if (lsr & UART_LSR_THRE)
-		sdio_uart_transmit_chars(port);
-	port->in_sdio_uart_irq = NULL;
-}
-
-static int uart_carrier_raised(struct tty_port *tport)
-{
-	struct sdio_uart_port *port =
-			container_of(tport, struct sdio_uart_port, port);
-	unsigned int ret = sdio_uart_claim_func(port);
-	if (ret)	/* Missing hardware shouldn't block for carrier */
-		return 1;
-	ret = sdio_uart_get_mctrl(port);
-	sdio_uart_release_func(port);
-	if (ret & TIOCM_CAR)
-		return 1;
-	return 0;
-}
-
-/**
- *	uart_dtr_rts		-	 port helper to set uart signals
- *	@tport: tty port to be updated
- *	@onoff: set to turn on DTR/RTS
- *
- *	Called by the tty port helpers when the modem signals need to be
- *	adjusted during an open, close and hangup.
- */
-
-static void uart_dtr_rts(struct tty_port *tport, int onoff)
-{
-	struct sdio_uart_port *port =
-			container_of(tport, struct sdio_uart_port, port);
-	int ret = sdio_uart_claim_func(port);
-	if (ret)
-		return;
-	if (onoff == 0)
-		sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-	else
-		sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-	sdio_uart_release_func(port);
-}
-
-/**
- *	sdio_uart_activate	-	start up hardware
- *	@tport: tty port to activate
- *	@tty: tty bound to this port
- *
- *	Activate a tty port. The port locking guarantees us this will be
- *	run exactly once per set of opens, and if successful will see the
- *	shutdown method run exactly once to match. Start up and shutdown are
- *	protected from each other by the internal locking and will not run
- *	at the same time even during a hangup event.
- *
- *	If we successfully start up the port we take an extra kref as we
- *	will keep it around until shutdown when the kref is dropped.
- */
-
-static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
-{
-	struct sdio_uart_port *port =
-			container_of(tport, struct sdio_uart_port, port);
-	int ret;
-
-	/*
-	 * Set the TTY IO error marker - we will only clear this
-	 * once we have successfully opened the port.
-	 */
-	set_bit(TTY_IO_ERROR, &tty->flags);
-
-	kfifo_reset(&port->xmit_fifo);
-
-	ret = sdio_uart_claim_func(port);
-	if (ret)
-		return ret;
-	ret = sdio_enable_func(port->func);
-	if (ret)
-		goto err1;
-	ret = sdio_claim_irq(port->func, sdio_uart_irq);
-	if (ret)
-		goto err2;
-
-	/*
-	 * Clear the FIFO buffers and disable them.
-	 * (they will be reenabled in sdio_change_speed())
-	 */
-	sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
-	sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
-		       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-	sdio_out(port, UART_FCR, 0);
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) sdio_in(port, UART_LSR);
-	(void) sdio_in(port, UART_RX);
-	(void) sdio_in(port, UART_IIR);
-	(void) sdio_in(port, UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	sdio_out(port, UART_LCR, UART_LCR_WLEN8);
-
-	port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;
-	port->mctrl = TIOCM_OUT2;
-
-	sdio_uart_change_speed(port, &tty->termios, NULL);
-
-	if (C_BAUD(tty))
-		sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
-
-	if (C_CRTSCTS(tty))
-		if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
-			tty->hw_stopped = 1;
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-
-	/* Kick the IRQ handler once while we're still holding the host lock */
-	sdio_uart_irq(port->func);
-
-	sdio_uart_release_func(port);
-	return 0;
-
-err2:
-	sdio_disable_func(port->func);
-err1:
-	sdio_uart_release_func(port);
-	return ret;
-}
-
-/**
- *	sdio_uart_shutdown	-	stop hardware
- *	@tport: tty port to shut down
- *
- *	Deactivate a tty port. The port locking guarantees us this will be
- *	run only if a successful matching activate already ran. The two are
- *	protected from each other by the internal locking and will not run
- *	at the same time even during a hangup event.
- */
-
-static void sdio_uart_shutdown(struct tty_port *tport)
-{
-	struct sdio_uart_port *port =
-			container_of(tport, struct sdio_uart_port, port);
-	int ret;
-
-	ret = sdio_uart_claim_func(port);
-	if (ret)
-		return;
-
-	sdio_uart_stop_rx(port);
-
-	/* Disable interrupts from this port */
-	sdio_release_irq(port->func);
-	port->ier = 0;
-	sdio_out(port, UART_IER, 0);
-
-	sdio_uart_clear_mctrl(port, TIOCM_OUT2);
-
-	/* Disable break condition and FIFOs. */
-	port->lcr &= ~UART_LCR_SBC;
-	sdio_out(port, UART_LCR, port->lcr);
-	sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
-				 UART_FCR_CLEAR_RCVR |
-				 UART_FCR_CLEAR_XMIT);
-	sdio_out(port, UART_FCR, 0);
-
-	sdio_disable_func(port->func);
-
-	sdio_uart_release_func(port);
-}
-
-static void sdio_uart_port_destroy(struct tty_port *tport)
-{
-	struct sdio_uart_port *port =
-		container_of(tport, struct sdio_uart_port, port);
-	kfifo_free(&port->xmit_fifo);
-	kfree(port);
-}
-
-/**
- *	sdio_uart_install	-	install method
- *	@driver: the driver in use (sdio_uart in our case)
- *	@tty: the tty being bound
- *
- *	Look up and bind the tty and the driver together. Initialize
- *	any needed private data (in our case the termios)
- */
-
-static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)
-{
-	int idx = tty->index;
-	struct sdio_uart_port *port = sdio_uart_port_get(idx);
-	int ret = tty_standard_install(driver, tty);
-
-	if (ret == 0)
-		/* This is the ref sdio_uart_port get provided */
-		tty->driver_data = port;
-	else
-		sdio_uart_port_put(port);
-	return ret;
-}
-
-/**
- *	sdio_uart_cleanup	-	called on the last tty kref drop
- *	@tty: the tty being destroyed
- *
- *	Called asynchronously when the last reference to the tty is dropped.
- *	We cannot destroy the tty->driver_data port kref until this point
- */
-
-static void sdio_uart_cleanup(struct tty_struct *tty)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	tty->driver_data = NULL;	/* Bug trap */
-	sdio_uart_port_put(port);
-}
-
-/*
- *	Open/close/hangup is now entirely boilerplate
- */
-
-static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	return tty_port_open(&port->port, tty, filp);
-}
-
-static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	tty_port_close(&port->port, tty, filp);
-}
-
-static void sdio_uart_hangup(struct tty_struct *tty)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	tty_port_hangup(&port->port);
-}
-
-static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf,
-			   int count)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	int ret;
-
-	if (!port->func)
-		return -ENODEV;
-
-	ret = kfifo_in_locked(&port->xmit_fifo, buf, count, &port->write_lock);
-	if (!(port->ier & UART_IER_THRI)) {
-		int err = sdio_uart_claim_func(port);
-		if (!err) {
-			sdio_uart_start_tx(port);
-			sdio_uart_irq(port->func);
-			sdio_uart_release_func(port);
-		} else
-			ret = err;
-	}
-
-	return ret;
-}
-
-static int sdio_uart_write_room(struct tty_struct *tty)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	return FIFO_SIZE - kfifo_len(&port->xmit_fifo);
-}
-
-static int sdio_uart_chars_in_buffer(struct tty_struct *tty)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	return kfifo_len(&port->xmit_fifo);
-}
-
-static void sdio_uart_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-
-	port->x_char = ch;
-	if (ch && !(port->ier & UART_IER_THRI)) {
-		if (sdio_uart_claim_func(port) != 0)
-			return;
-		sdio_uart_start_tx(port);
-		sdio_uart_irq(port->func);
-		sdio_uart_release_func(port);
-	}
-}
-
-static void sdio_uart_throttle(struct tty_struct *tty)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-
-	if (!I_IXOFF(tty) && !C_CRTSCTS(tty))
-		return;
-
-	if (sdio_uart_claim_func(port) != 0)
-		return;
-
-	if (I_IXOFF(tty)) {
-		port->x_char = STOP_CHAR(tty);
-		sdio_uart_start_tx(port);
-	}
-
-	if (C_CRTSCTS(tty))
-		sdio_uart_clear_mctrl(port, TIOCM_RTS);
-
-	sdio_uart_irq(port->func);
-	sdio_uart_release_func(port);
-}
-
-static void sdio_uart_unthrottle(struct tty_struct *tty)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-
-	if (!I_IXOFF(tty) && !C_CRTSCTS(tty))
-		return;
-
-	if (sdio_uart_claim_func(port) != 0)
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (port->x_char) {
-			port->x_char = 0;
-		} else {
-			port->x_char = START_CHAR(tty);
-			sdio_uart_start_tx(port);
-		}
-	}
-
-	if (C_CRTSCTS(tty))
-		sdio_uart_set_mctrl(port, TIOCM_RTS);
-
-	sdio_uart_irq(port->func);
-	sdio_uart_release_func(port);
-}
-
-static void sdio_uart_set_termios(struct tty_struct *tty,
-						struct ktermios *old_termios)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	unsigned int cflag = tty->termios.c_cflag;
-
-	if (sdio_uart_claim_func(port) != 0)
-		return;
-
-	sdio_uart_change_speed(port, &tty->termios, old_termios);
-
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
-		sdio_uart_clear_mctrl(port, TIOCM_RTS | TIOCM_DTR);
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-		unsigned int mask = TIOCM_DTR;
-		if (!(cflag & CRTSCTS) || !tty_throttled(tty))
-			mask |= TIOCM_RTS;
-		sdio_uart_set_mctrl(port, mask);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		sdio_uart_start_tx(port);
-	}
-
-	/* Handle turning on CRTSCTS */
-	if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
-		if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) {
-			tty->hw_stopped = 1;
-			sdio_uart_stop_tx(port);
-		}
-	}
-
-	sdio_uart_release_func(port);
-}
-
-static int sdio_uart_break_ctl(struct tty_struct *tty, int break_state)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	int result;
-
-	result = sdio_uart_claim_func(port);
-	if (result != 0)
-		return result;
-
-	if (break_state == -1)
-		port->lcr |= UART_LCR_SBC;
-	else
-		port->lcr &= ~UART_LCR_SBC;
-	sdio_out(port, UART_LCR, port->lcr);
-
-	sdio_uart_release_func(port);
-	return 0;
-}
-
-static int sdio_uart_tiocmget(struct tty_struct *tty)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	int result;
-
-	result = sdio_uart_claim_func(port);
-	if (!result) {
-		result = port->mctrl | sdio_uart_get_mctrl(port);
-		sdio_uart_release_func(port);
-	}
-
-	return result;
-}
-
-static int sdio_uart_tiocmset(struct tty_struct *tty,
-			      unsigned int set, unsigned int clear)
-{
-	struct sdio_uart_port *port = tty->driver_data;
-	int result;
-
-	result = sdio_uart_claim_func(port);
-	if (!result) {
-		sdio_uart_update_mctrl(port, set, clear);
-		sdio_uart_release_func(port);
-	}
-
-	return result;
-}
-
-static int sdio_uart_proc_show(struct seq_file *m, void *v)
-{
-	int i;
-
-	seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n",
-		       "", "", "");
-	for (i = 0; i < UART_NR; i++) {
-		struct sdio_uart_port *port = sdio_uart_port_get(i);
-		if (port) {
-			seq_printf(m, "%d: uart:SDIO", i);
-			if (capable(CAP_SYS_ADMIN)) {
-				seq_printf(m, " tx:%d rx:%d",
-					      port->icount.tx, port->icount.rx);
-				if (port->icount.frame)
-					seq_printf(m, " fe:%d",
-						      port->icount.frame);
-				if (port->icount.parity)
-					seq_printf(m, " pe:%d",
-						      port->icount.parity);
-				if (port->icount.brk)
-					seq_printf(m, " brk:%d",
-						      port->icount.brk);
-				if (port->icount.overrun)
-					seq_printf(m, " oe:%d",
-						      port->icount.overrun);
-				if (port->icount.cts)
-					seq_printf(m, " cts:%d",
-						      port->icount.cts);
-				if (port->icount.dsr)
-					seq_printf(m, " dsr:%d",
-						      port->icount.dsr);
-				if (port->icount.rng)
-					seq_printf(m, " rng:%d",
-						      port->icount.rng);
-				if (port->icount.dcd)
-					seq_printf(m, " dcd:%d",
-						      port->icount.dcd);
-			}
-			sdio_uart_port_put(port);
-			seq_putc(m, '\n');
-		}
-	}
-	return 0;
-}
-
-static int sdio_uart_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, sdio_uart_proc_show, NULL);
-}
-
-static const struct file_operations sdio_uart_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= sdio_uart_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static const struct tty_port_operations sdio_uart_port_ops = {
-	.dtr_rts = uart_dtr_rts,
-	.carrier_raised = uart_carrier_raised,
-	.shutdown = sdio_uart_shutdown,
-	.activate = sdio_uart_activate,
-	.destruct = sdio_uart_port_destroy,
-};
-
-static const struct tty_operations sdio_uart_ops = {
-	.open			= sdio_uart_open,
-	.close			= sdio_uart_close,
-	.write			= sdio_uart_write,
-	.write_room		= sdio_uart_write_room,
-	.chars_in_buffer	= sdio_uart_chars_in_buffer,
-	.send_xchar		= sdio_uart_send_xchar,
-	.throttle		= sdio_uart_throttle,
-	.unthrottle		= sdio_uart_unthrottle,
-	.set_termios		= sdio_uart_set_termios,
-	.hangup			= sdio_uart_hangup,
-	.break_ctl		= sdio_uart_break_ctl,
-	.tiocmget		= sdio_uart_tiocmget,
-	.tiocmset		= sdio_uart_tiocmset,
-	.install		= sdio_uart_install,
-	.cleanup		= sdio_uart_cleanup,
-	.proc_fops		= &sdio_uart_proc_fops,
-};
-
-static struct tty_driver *sdio_uart_tty_driver;
-
-static int sdio_uart_probe(struct sdio_func *func,
-			   const struct sdio_device_id *id)
-{
-	struct sdio_uart_port *port;
-	int ret;
-
-	port = kzalloc(sizeof(struct sdio_uart_port), GFP_KERNEL);
-	if (!port)
-		return -ENOMEM;
-
-	if (func->class == SDIO_CLASS_UART) {
-		pr_warn("%s: need info on UART class basic setup\n",
-			sdio_func_id(func));
-		kfree(port);
-		return -ENOSYS;
-	} else if (func->class == SDIO_CLASS_GPS) {
-		/*
-		 * We need tuple 0x91.  It contains SUBTPL_SIOREG
-		 * and SUBTPL_RCVCAPS.
-		 */
-		struct sdio_func_tuple *tpl;
-		for (tpl = func->tuples; tpl; tpl = tpl->next) {
-			if (tpl->code != 0x91)
-				continue;
-			if (tpl->size < 10)
-				continue;
-			if (tpl->data[1] == 0)  /* SUBTPL_SIOREG */
-				break;
-		}
-		if (!tpl) {
-			pr_warn("%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
-				sdio_func_id(func));
-			kfree(port);
-			return -EINVAL;
-		}
-		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);
-		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;
-		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 {
-		kfree(port);
-		return -EINVAL;
-	}
-
-	port->func = func;
-	sdio_set_drvdata(func, port);
-	tty_port_init(&port->port);
-	port->port.ops = &sdio_uart_port_ops;
-
-	ret = sdio_uart_add_port(port);
-	if (ret) {
-		kfree(port);
-	} else {
-		struct device *dev;
-		dev = tty_port_register_device(&port->port,
-				sdio_uart_tty_driver, port->index, &func->dev);
-		if (IS_ERR(dev)) {
-			sdio_uart_port_remove(port);
-			ret = PTR_ERR(dev);
-		}
-	}
-
-	return ret;
-}
-
-static void sdio_uart_remove(struct sdio_func *func)
-{
-	struct sdio_uart_port *port = sdio_get_drvdata(func);
-
-	tty_unregister_device(sdio_uart_tty_driver, port->index);
-	sdio_uart_port_remove(port);
-}
-
-static const struct sdio_device_id sdio_uart_ids[] = {
-	{ SDIO_DEVICE_CLASS(SDIO_CLASS_UART)		},
-	{ SDIO_DEVICE_CLASS(SDIO_CLASS_GPS)		},
-	{ /* end: all zeroes */				},
-};
-
-MODULE_DEVICE_TABLE(sdio, sdio_uart_ids);
-
-static struct sdio_driver sdio_uart_driver = {
-	.probe		= sdio_uart_probe,
-	.remove		= sdio_uart_remove,
-	.name		= "sdio_uart",
-	.id_table	= sdio_uart_ids,
-};
-
-static int __init sdio_uart_init(void)
-{
-	int ret;
-	struct tty_driver *tty_drv;
-
-	sdio_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);
-	if (!tty_drv)
-		return -ENOMEM;
-
-	tty_drv->driver_name = "sdio_uart";
-	tty_drv->name =   "ttySDIO";
-	tty_drv->major = 0;  /* dynamically allocated */
-	tty_drv->minor_start = 0;
-	tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
-	tty_drv->subtype = SERIAL_TYPE_NORMAL;
-	tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_drv->init_termios = tty_std_termios;
-	tty_drv->init_termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
-	tty_drv->init_termios.c_ispeed = 4800;
-	tty_drv->init_termios.c_ospeed = 4800;
-	tty_set_operations(tty_drv, &sdio_uart_ops);
-
-	ret = tty_register_driver(tty_drv);
-	if (ret)
-		goto err1;
-
-	ret = sdio_register_driver(&sdio_uart_driver);
-	if (ret)
-		goto err2;
-
-	return 0;
-
-err2:
-	tty_unregister_driver(tty_drv);
-err1:
-	put_tty_driver(tty_drv);
-	return ret;
-}
-
-static void __exit sdio_uart_exit(void)
-{
-	sdio_unregister_driver(&sdio_uart_driver);
-	tty_unregister_driver(sdio_uart_tty_driver);
-	put_tty_driver(sdio_uart_tty_driver);
-}
-
-module_init(sdio_uart_init);
-module_exit(sdio_uart_exit);
-
-MODULE_AUTHOR("Nicolas Pitre");
-MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/block.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/block.c
--- linux-libre-4.9-gnu/drivers/mmc/core/block.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/block.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2336 @@
+/*
+ * Block driver for media (i.e., flash cards)
+ *
+ * Copyright 2002 Hewlett-Packard Company
+ * Copyright 2005-2008 Pierre Ossman
+ *
+ * Use consistent with the GNU GPL is permitted,
+ * provided that this copyright notice is
+ * preserved in its entirety in all copies and derived works.
+ *
+ * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
+ * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * Many thanks to Alessandro Rubini and Jonathan Corbet!
+ *
+ * Author:  Andrew Christian
+ *          28 May 2002
+ */
+#include <linux/moduleparam.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/hdreg.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <linux/string_helpers.h>
+#include <linux/delay.h>
+#include <linux/capability.h>
+#include <linux/compat.h>
+#include <linux/pm_runtime.h>
+#include <linux/idr.h>
+
+#include <linux/mmc/ioctl.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include <linux/uaccess.h>
+
+#include "queue.h"
+#include "block.h"
+
+MODULE_ALIAS("mmc:block");
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "mmcblk."
+
+#define INAND_CMD38_ARG_EXT_CSD  113
+#define INAND_CMD38_ARG_ERASE    0x00
+#define INAND_CMD38_ARG_TRIM     0x01
+#define INAND_CMD38_ARG_SECERASE 0x80
+#define INAND_CMD38_ARG_SECTRIM1 0x81
+#define INAND_CMD38_ARG_SECTRIM2 0x88
+#define MMC_BLK_TIMEOUT_MS  (10 * 60 * 1000)        /* 10 minute timeout */
+#define MMC_SANITIZE_REQ_TIMEOUT 240000
+#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
+
+#define mmc_req_rel_wr(req)	((req->cmd_flags & REQ_FUA) && \
+				  (rq_data_dir(req) == WRITE))
+static DEFINE_MUTEX(block_mutex);
+
+/*
+ * The defaults come from config options but can be overriden by module
+ * or bootarg options.
+ */
+static int perdev_minors = CONFIG_MMC_BLOCK_MINORS;
+
+/*
+ * We've only got one major, so number of mmcblk devices is
+ * limited to (1 << 20) / number of minors per device.  It is also
+ * limited by the MAX_DEVICES below.
+ */
+static int max_devices;
+
+#define MAX_DEVICES 256
+
+static DEFINE_IDA(mmc_blk_ida);
+static DEFINE_SPINLOCK(mmc_blk_lock);
+
+/*
+ * There is one mmc_blk_data per slot.
+ */
+struct mmc_blk_data {
+	spinlock_t	lock;
+	struct device	*parent;
+	struct gendisk	*disk;
+	struct mmc_queue queue;
+	struct list_head part;
+
+	unsigned int	flags;
+#define MMC_BLK_CMD23	(1 << 0)	/* Can do SET_BLOCK_COUNT for multiblock */
+#define MMC_BLK_REL_WR	(1 << 1)	/* MMC Reliable write support */
+
+	unsigned int	usage;
+	unsigned int	read_only;
+	unsigned int	part_type;
+	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
+	 * with mmc_card with dev_set_drvdata, and keeps
+	 * track of the current selected device partition.
+	 */
+	unsigned int	part_curr;
+	struct device_attribute force_ro;
+	struct device_attribute power_ro_lock;
+	int	area_type;
+};
+
+static DEFINE_MUTEX(open_lock);
+
+module_param(perdev_minors, int, 0444);
+MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
+
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+				      struct mmc_blk_data *md);
+static int get_card_status(struct mmc_card *card, u32 *status, int retries);
+
+static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
+{
+	struct mmc_blk_data *md;
+
+	mutex_lock(&open_lock);
+	md = disk->private_data;
+	if (md && md->usage == 0)
+		md = NULL;
+	if (md)
+		md->usage++;
+	mutex_unlock(&open_lock);
+
+	return md;
+}
+
+static inline int mmc_get_devidx(struct gendisk *disk)
+{
+	int devidx = disk->first_minor / perdev_minors;
+	return devidx;
+}
+
+static void mmc_blk_put(struct mmc_blk_data *md)
+{
+	mutex_lock(&open_lock);
+	md->usage--;
+	if (md->usage == 0) {
+		int devidx = mmc_get_devidx(md->disk);
+		blk_cleanup_queue(md->queue.queue);
+
+		spin_lock(&mmc_blk_lock);
+		ida_remove(&mmc_blk_ida, devidx);
+		spin_unlock(&mmc_blk_lock);
+
+		put_disk(md->disk);
+		kfree(md);
+	}
+	mutex_unlock(&open_lock);
+}
+
+static ssize_t power_ro_lock_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int ret;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	struct mmc_card *card = md->queue.card;
+	int locked = 0;
+
+	if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PERM_WP_EN)
+		locked = 2;
+	else if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_EN)
+		locked = 1;
+
+	ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
+
+	mmc_blk_put(md);
+
+	return ret;
+}
+
+static ssize_t power_ro_lock_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+	struct mmc_blk_data *md, *part_md;
+	struct mmc_card *card;
+	unsigned long set;
+
+	if (kstrtoul(buf, 0, &set))
+		return -EINVAL;
+
+	if (set != 1)
+		return count;
+
+	md = mmc_blk_get(dev_to_disk(dev));
+	card = md->queue.card;
+
+	mmc_get_card(card);
+
+	ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
+				card->ext_csd.boot_ro_lock |
+				EXT_CSD_BOOT_WP_B_PWR_WP_EN,
+				card->ext_csd.part_time);
+	if (ret)
+		pr_err("%s: Locking boot partition ro until next power on failed: %d\n", md->disk->disk_name, ret);
+	else
+		card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;
+
+	mmc_put_card(card);
+
+	if (!ret) {
+		pr_info("%s: Locking boot partition ro until next power on\n",
+			md->disk->disk_name);
+		set_disk_ro(md->disk, 1);
+
+		list_for_each_entry(part_md, &md->part, part)
+			if (part_md->area_type == MMC_BLK_DATA_AREA_BOOT) {
+				pr_info("%s: Locking boot partition ro until next power on\n", part_md->disk->disk_name);
+				set_disk_ro(part_md->disk, 1);
+			}
+	}
+
+	mmc_blk_put(md);
+	return count;
+}
+
+static ssize_t force_ro_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	int ret;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+
+	ret = snprintf(buf, PAGE_SIZE, "%d\n",
+		       get_disk_ro(dev_to_disk(dev)) ^
+		       md->read_only);
+	mmc_blk_put(md);
+	return ret;
+}
+
+static ssize_t force_ro_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	int ret;
+	char *end;
+	struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
+	unsigned long set = simple_strtoul(buf, &end, 0);
+	if (end == buf) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	set_disk_ro(dev_to_disk(dev), set || md->read_only);
+	ret = count;
+out:
+	mmc_blk_put(md);
+	return ret;
+}
+
+static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
+{
+	struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
+	int ret = -ENXIO;
+
+	mutex_lock(&block_mutex);
+	if (md) {
+		if (md->usage == 2)
+			check_disk_change(bdev);
+		ret = 0;
+
+		if ((mode & FMODE_WRITE) && md->read_only) {
+			mmc_blk_put(md);
+			ret = -EROFS;
+		}
+	}
+	mutex_unlock(&block_mutex);
+
+	return ret;
+}
+
+static void mmc_blk_release(struct gendisk *disk, fmode_t mode)
+{
+	struct mmc_blk_data *md = disk->private_data;
+
+	mutex_lock(&block_mutex);
+	mmc_blk_put(md);
+	mutex_unlock(&block_mutex);
+}
+
+static int
+mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+	geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16);
+	geo->heads = 4;
+	geo->sectors = 16;
+	return 0;
+}
+
+struct mmc_blk_ioc_data {
+	struct mmc_ioc_cmd ic;
+	unsigned char *buf;
+	u64 buf_bytes;
+};
+
+static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
+	struct mmc_ioc_cmd __user *user)
+{
+	struct mmc_blk_ioc_data *idata;
+	int err;
+
+	idata = kmalloc(sizeof(*idata), GFP_KERNEL);
+	if (!idata) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	if (copy_from_user(&idata->ic, user, sizeof(idata->ic))) {
+		err = -EFAULT;
+		goto idata_err;
+	}
+
+	idata->buf_bytes = (u64) idata->ic.blksz * idata->ic.blocks;
+	if (idata->buf_bytes > MMC_IOC_MAX_BYTES) {
+		err = -EOVERFLOW;
+		goto idata_err;
+	}
+
+	if (!idata->buf_bytes) {
+		idata->buf = NULL;
+		return idata;
+	}
+
+	idata->buf = kmalloc(idata->buf_bytes, GFP_KERNEL);
+	if (!idata->buf) {
+		err = -ENOMEM;
+		goto idata_err;
+	}
+
+	if (copy_from_user(idata->buf, (void __user *)(unsigned long)
+					idata->ic.data_ptr, idata->buf_bytes)) {
+		err = -EFAULT;
+		goto copy_err;
+	}
+
+	return idata;
+
+copy_err:
+	kfree(idata->buf);
+idata_err:
+	kfree(idata);
+out:
+	return ERR_PTR(err);
+}
+
+static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
+				      struct mmc_blk_ioc_data *idata)
+{
+	struct mmc_ioc_cmd *ic = &idata->ic;
+
+	if (copy_to_user(&(ic_ptr->response), ic->response,
+			 sizeof(ic->response)))
+		return -EFAULT;
+
+	if (!idata->ic.write_flag) {
+		if (copy_to_user((void __user *)(unsigned long)ic->data_ptr,
+				 idata->buf, idata->buf_bytes))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
+				       u32 retries_max)
+{
+	int err;
+	u32 retry_count = 0;
+
+	if (!status || !retries_max)
+		return -EINVAL;
+
+	do {
+		err = get_card_status(card, status, 5);
+		if (err)
+			break;
+
+		if (!R1_STATUS(*status) &&
+				(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
+			break; /* RPMB programming operation complete */
+
+		/*
+		 * Rechedule to give the MMC device a chance to continue
+		 * processing the previous command without being polled too
+		 * frequently.
+		 */
+		usleep_range(1000, 5000);
+	} while (++retry_count < retries_max);
+
+	if (retry_count == retries_max)
+		err = -EPERM;
+
+	return err;
+}
+
+static int ioctl_do_sanitize(struct mmc_card *card)
+{
+	int err;
+
+	if (!mmc_can_sanitize(card)) {
+			pr_warn("%s: %s - SANITIZE is not supported\n",
+				mmc_hostname(card->host), __func__);
+			err = -EOPNOTSUPP;
+			goto out;
+	}
+
+	pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
+		mmc_hostname(card->host), __func__);
+
+	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					EXT_CSD_SANITIZE_START, 1,
+					MMC_SANITIZE_REQ_TIMEOUT);
+
+	if (err)
+		pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
+		       mmc_hostname(card->host), __func__, err);
+
+	pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
+					     __func__);
+out:
+	return err;
+}
+
+static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
+			       struct mmc_blk_ioc_data *idata)
+{
+	struct mmc_command cmd = {0};
+	struct mmc_data data = {0};
+	struct mmc_request mrq = {NULL};
+	struct scatterlist sg;
+	int err;
+	int is_rpmb = false;
+	u32 status = 0;
+
+	if (!card || !md || !idata)
+		return -EINVAL;
+
+	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+		is_rpmb = true;
+
+	cmd.opcode = idata->ic.opcode;
+	cmd.arg = idata->ic.arg;
+	cmd.flags = idata->ic.flags;
+
+	if (idata->buf_bytes) {
+		data.sg = &sg;
+		data.sg_len = 1;
+		data.blksz = idata->ic.blksz;
+		data.blocks = idata->ic.blocks;
+
+		sg_init_one(data.sg, idata->buf, idata->buf_bytes);
+
+		if (idata->ic.write_flag)
+			data.flags = MMC_DATA_WRITE;
+		else
+			data.flags = MMC_DATA_READ;
+
+		/* data.flags must already be set before doing this. */
+		mmc_set_data_timeout(&data, card);
+
+		/* Allow overriding the timeout_ns for empirical tuning. */
+		if (idata->ic.data_timeout_ns)
+			data.timeout_ns = idata->ic.data_timeout_ns;
+
+		if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+			/*
+			 * Pretend this is a data transfer and rely on the
+			 * host driver to compute timeout.  When all host
+			 * drivers support cmd.cmd_timeout for R1B, this
+			 * can be changed to:
+			 *
+			 *     mrq.data = NULL;
+			 *     cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
+			 */
+			data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
+		}
+
+		mrq.data = &data;
+	}
+
+	mrq.cmd = &cmd;
+
+	err = mmc_blk_part_switch(card, md);
+	if (err)
+		return err;
+
+	if (idata->ic.is_acmd) {
+		err = mmc_app_cmd(card->host, card);
+		if (err)
+			return err;
+	}
+
+	if (is_rpmb) {
+		err = mmc_set_blockcount(card, data.blocks,
+			idata->ic.write_flag & (1 << 31));
+		if (err)
+			return err;
+	}
+
+	if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
+	    (cmd.opcode == MMC_SWITCH)) {
+		err = ioctl_do_sanitize(card);
+
+		if (err)
+			pr_err("%s: ioctl_do_sanitize() failed. err = %d",
+			       __func__, err);
+
+		return err;
+	}
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	if (cmd.error) {
+		dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
+						__func__, cmd.error);
+		return cmd.error;
+	}
+	if (data.error) {
+		dev_err(mmc_dev(card->host), "%s: data error %d\n",
+						__func__, data.error);
+		return data.error;
+	}
+
+	/*
+	 * According to the SD specs, some commands require a delay after
+	 * issuing the command.
+	 */
+	if (idata->ic.postsleep_min_us)
+		usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
+
+	memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
+
+	if (is_rpmb) {
+		/*
+		 * Ensure RPMB command has completed by polling CMD13
+		 * "Send Status".
+		 */
+		err = ioctl_rpmb_card_status_poll(card, &status, 5);
+		if (err)
+			dev_err(mmc_dev(card->host),
+					"%s: Card Status=0x%08X, error %d\n",
+					__func__, status, err);
+	}
+
+	return err;
+}
+
+static int mmc_blk_ioctl_cmd(struct block_device *bdev,
+			     struct mmc_ioc_cmd __user *ic_ptr)
+{
+	struct mmc_blk_ioc_data *idata;
+	struct mmc_blk_data *md;
+	struct mmc_card *card;
+	int err = 0, ioc_err = 0;
+
+	/*
+	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
+	 * whole block device, not on a partition.  This prevents overspray
+	 * between sibling partitions.
+	 */
+	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
+		return -EPERM;
+
+	idata = mmc_blk_ioctl_copy_from_user(ic_ptr);
+	if (IS_ERR(idata))
+		return PTR_ERR(idata);
+
+	md = mmc_blk_get(bdev->bd_disk);
+	if (!md) {
+		err = -EINVAL;
+		goto cmd_err;
+	}
+
+	card = md->queue.card;
+	if (IS_ERR(card)) {
+		err = PTR_ERR(card);
+		goto cmd_done;
+	}
+
+	mmc_get_card(card);
+
+	ioc_err = __mmc_blk_ioctl_cmd(card, md, idata);
+
+	/* Always switch back to main area after RPMB access */
+	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+		mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
+
+	mmc_put_card(card);
+
+	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
+
+cmd_done:
+	mmc_blk_put(md);
+cmd_err:
+	kfree(idata->buf);
+	kfree(idata);
+	return ioc_err ? ioc_err : err;
+}
+
+static int mmc_blk_ioctl_multi_cmd(struct block_device *bdev,
+				   struct mmc_ioc_multi_cmd __user *user)
+{
+	struct mmc_blk_ioc_data **idata = NULL;
+	struct mmc_ioc_cmd __user *cmds = user->cmds;
+	struct mmc_card *card;
+	struct mmc_blk_data *md;
+	int i, err = 0, ioc_err = 0;
+	__u64 num_of_cmds;
+
+	/*
+	 * The caller must have CAP_SYS_RAWIO, and must be calling this on the
+	 * whole block device, not on a partition.  This prevents overspray
+	 * between sibling partitions.
+	 */
+	if ((!capable(CAP_SYS_RAWIO)) || (bdev != bdev->bd_contains))
+		return -EPERM;
+
+	if (copy_from_user(&num_of_cmds, &user->num_of_cmds,
+			   sizeof(num_of_cmds)))
+		return -EFAULT;
+
+	if (num_of_cmds > MMC_IOC_MAX_CMDS)
+		return -EINVAL;
+
+	idata = kcalloc(num_of_cmds, sizeof(*idata), GFP_KERNEL);
+	if (!idata)
+		return -ENOMEM;
+
+	for (i = 0; i < num_of_cmds; i++) {
+		idata[i] = mmc_blk_ioctl_copy_from_user(&cmds[i]);
+		if (IS_ERR(idata[i])) {
+			err = PTR_ERR(idata[i]);
+			num_of_cmds = i;
+			goto cmd_err;
+		}
+	}
+
+	md = mmc_blk_get(bdev->bd_disk);
+	if (!md) {
+		err = -EINVAL;
+		goto cmd_err;
+	}
+
+	card = md->queue.card;
+	if (IS_ERR(card)) {
+		err = PTR_ERR(card);
+		goto cmd_done;
+	}
+
+	mmc_get_card(card);
+
+	for (i = 0; i < num_of_cmds && !ioc_err; i++)
+		ioc_err = __mmc_blk_ioctl_cmd(card, md, idata[i]);
+
+	/* Always switch back to main area after RPMB access */
+	if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+		mmc_blk_part_switch(card, dev_get_drvdata(&card->dev));
+
+	mmc_put_card(card);
+
+	/* copy to user if data and response */
+	for (i = 0; i < num_of_cmds && !err; i++)
+		err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
+
+cmd_done:
+	mmc_blk_put(md);
+cmd_err:
+	for (i = 0; i < num_of_cmds; i++) {
+		kfree(idata[i]->buf);
+		kfree(idata[i]);
+	}
+	kfree(idata);
+	return ioc_err ? ioc_err : err;
+}
+
+static int mmc_blk_ioctl(struct block_device *bdev, fmode_t mode,
+	unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case MMC_IOC_CMD:
+		return mmc_blk_ioctl_cmd(bdev,
+				(struct mmc_ioc_cmd __user *)arg);
+	case MMC_IOC_MULTI_CMD:
+		return mmc_blk_ioctl_multi_cmd(bdev,
+				(struct mmc_ioc_multi_cmd __user *)arg);
+	default:
+		return -EINVAL;
+	}
+}
+
+#ifdef CONFIG_COMPAT
+static int mmc_blk_compat_ioctl(struct block_device *bdev, fmode_t mode,
+	unsigned int cmd, unsigned long arg)
+{
+	return mmc_blk_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg));
+}
+#endif
+
+static const struct block_device_operations mmc_bdops = {
+	.open			= mmc_blk_open,
+	.release		= mmc_blk_release,
+	.getgeo			= mmc_blk_getgeo,
+	.owner			= THIS_MODULE,
+	.ioctl			= mmc_blk_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl		= mmc_blk_compat_ioctl,
+#endif
+};
+
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+				      struct mmc_blk_data *md)
+{
+	int ret;
+	struct mmc_blk_data *main_md = dev_get_drvdata(&card->dev);
+
+	if (main_md->part_curr == md->part_type)
+		return 0;
+
+	if (mmc_card_mmc(card)) {
+		u8 part_config = card->ext_csd.part_config;
+
+		if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+			mmc_retune_pause(card->host);
+
+		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, part_config,
+				 card->ext_csd.part_time);
+		if (ret) {
+			if (md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+				mmc_retune_unpause(card->host);
+			return ret;
+		}
+
+		card->ext_csd.part_config = part_config;
+
+		if (main_md->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB)
+			mmc_retune_unpause(card->host);
+	}
+
+	main_md->part_curr = md->part_type;
+	return 0;
+}
+
+static u32 mmc_sd_num_wr_blocks(struct mmc_card *card)
+{
+	int err;
+	u32 result;
+	__be32 *blocks;
+
+	struct mmc_request mrq = {NULL};
+	struct mmc_command cmd = {0};
+	struct mmc_data data = {0};
+
+	struct scatterlist sg;
+
+	cmd.opcode = MMC_APP_CMD;
+	cmd.arg = card->rca << 16;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &cmd, 0);
+	if (err)
+		return (u32)-1;
+	if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD))
+		return (u32)-1;
+
+	memset(&cmd, 0, sizeof(struct mmc_command));
+
+	cmd.opcode = SD_APP_SEND_NUM_WR_BLKS;
+	cmd.arg = 0;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	data.blksz = 4;
+	data.blocks = 1;
+	data.flags = MMC_DATA_READ;
+	data.sg = &sg;
+	data.sg_len = 1;
+	mmc_set_data_timeout(&data, card);
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+
+	blocks = kmalloc(4, GFP_KERNEL);
+	if (!blocks)
+		return (u32)-1;
+
+	sg_init_one(&sg, blocks, 4);
+
+	mmc_wait_for_req(card->host, &mrq);
+
+	result = ntohl(*blocks);
+	kfree(blocks);
+
+	if (cmd.error || data.error)
+		result = (u32)-1;
+
+	return result;
+}
+
+static int get_card_status(struct mmc_card *card, u32 *status, int retries)
+{
+	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, retries);
+	if (err == 0)
+		*status = cmd.resp[0];
+	return err;
+}
+
+static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+		bool hw_busy_detect, struct request *req, bool *gen_err)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	int err = 0;
+	u32 status;
+
+	do {
+		err = get_card_status(card, &status, 5);
+		if (err) {
+			pr_err("%s: error %d requesting status\n",
+			       req->rq_disk->disk_name, err);
+			return err;
+		}
+
+		if (status & R1_ERROR) {
+			pr_err("%s: %s: error sending status cmd, status %#x\n",
+				req->rq_disk->disk_name, __func__, status);
+			*gen_err = true;
+		}
+
+		/* We may rely on the host hw to handle busy detection.*/
+		if ((card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) &&
+			hw_busy_detect)
+			break;
+
+		/*
+		 * Timeout if the device never becomes ready for data and never
+		 * leaves the program state.
+		 */
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s: Card stuck in programming state! %s %s\n",
+				mmc_hostname(card->host),
+				req->rq_disk->disk_name, __func__);
+			return -ETIMEDOUT;
+		}
+
+		/*
+		 * Some cards mishandle the status bits,
+		 * so make sure to check both the busy
+		 * indication and the card state.
+		 */
+	} while (!(status & R1_READY_FOR_DATA) ||
+		 (R1_CURRENT_STATE(status) == R1_STATE_PRG));
+
+	return err;
+}
+
+static int send_stop(struct mmc_card *card, unsigned int timeout_ms,
+		struct request *req, bool *gen_err, u32 *stop_status)
+{
+	struct mmc_host *host = card->host;
+	struct mmc_command cmd = {0};
+	int err;
+	bool use_r1b_resp = rq_data_dir(req) == WRITE;
+
+	/*
+	 * Normally we use R1B responses for WRITE, but in cases where the host
+	 * has specified a max_busy_timeout we need to validate it. A failure
+	 * means we need to prevent the host from doing hw busy detection, which
+	 * is done by converting to a R1 response instead.
+	 */
+	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
+		use_r1b_resp = false;
+
+	cmd.opcode = MMC_STOP_TRANSMISSION;
+	if (use_r1b_resp) {
+		cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+		cmd.busy_timeout = timeout_ms;
+	} else {
+		cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+	}
+
+	err = mmc_wait_for_cmd(host, &cmd, 5);
+	if (err)
+		return err;
+
+	*stop_status = cmd.resp[0];
+
+	/* No need to check card status in case of READ. */
+	if (rq_data_dir(req) == READ)
+		return 0;
+
+	if (!mmc_host_is_spi(host) &&
+		(*stop_status & R1_ERROR)) {
+		pr_err("%s: %s: general error sending stop command, resp %#x\n",
+			req->rq_disk->disk_name, __func__, *stop_status);
+		*gen_err = true;
+	}
+
+	return card_busy_detect(card, timeout_ms, use_r1b_resp, req, gen_err);
+}
+
+#define ERR_NOMEDIUM	3
+#define ERR_RETRY	2
+#define ERR_ABORT	1
+#define ERR_CONTINUE	0
+
+static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
+	bool status_valid, u32 status)
+{
+	switch (error) {
+	case -EILSEQ:
+		/* response crc error, retry the r/w cmd */
+		pr_err("%s: %s sending %s command, card status %#x\n",
+			req->rq_disk->disk_name, "response CRC error",
+			name, status);
+		return ERR_RETRY;
+
+	case -ETIMEDOUT:
+		pr_err("%s: %s sending %s command, card status %#x\n",
+			req->rq_disk->disk_name, "timed out", name, status);
+
+		/* If the status cmd initially failed, retry the r/w cmd */
+		if (!status_valid) {
+			pr_err("%s: status not valid, retrying timeout\n",
+				req->rq_disk->disk_name);
+			return ERR_RETRY;
+		}
+
+		/*
+		 * If it was a r/w cmd crc error, or illegal command
+		 * (eg, issued in wrong state) then retry - we should
+		 * have corrected the state problem above.
+		 */
+		if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) {
+			pr_err("%s: command error, retrying timeout\n",
+				req->rq_disk->disk_name);
+			return ERR_RETRY;
+		}
+
+		/* Otherwise abort the command */
+		return ERR_ABORT;
+
+	default:
+		/* We don't understand the error code the driver gave us */
+		pr_err("%s: unknown error %d sending read/write command, card status %#x\n",
+		       req->rq_disk->disk_name, error, status);
+		return ERR_ABORT;
+	}
+}
+
+/*
+ * Initial r/w and stop cmd error recovery.
+ * We don't know whether the card received the r/w cmd or not, so try to
+ * restore things back to a sane state.  Essentially, we do this as follows:
+ * - Obtain card status.  If the first attempt to obtain card status fails,
+ *   the status word will reflect the failed status cmd, not the failed
+ *   r/w cmd.  If we fail to obtain card status, it suggests we can no
+ *   longer communicate with the card.
+ * - Check the card state.  If the card received the cmd but there was a
+ *   transient problem with the response, it might still be in a data transfer
+ *   mode.  Try to send it a stop command.  If this fails, we can't recover.
+ * - If the r/w cmd failed due to a response CRC error, it was probably
+ *   transient, so retry the cmd.
+ * - If the r/w cmd timed out, but we didn't get the r/w cmd status, retry.
+ * - If the r/w cmd timed out, and the r/w cmd failed due to CRC error or
+ *   illegal cmd, retry.
+ * 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, bool *ecc_err, bool *gen_err)
+{
+	bool prev_cmd_status_valid = true;
+	u32 status, stop_status = 0;
+	int err, retry;
+
+	if (mmc_card_removed(card))
+		return ERR_NOMEDIUM;
+
+	/*
+	 * Try to get card status which indicates both the card state
+	 * and why there was no response.  If the first attempt fails,
+	 * we can't be sure the returned status is for the r/w command.
+	 */
+	for (retry = 2; retry >= 0; retry--) {
+		err = get_card_status(card, &status, 0);
+		if (!err)
+			break;
+
+		/* Re-tune if needed */
+		mmc_retune_recheck(card->host);
+
+		prev_cmd_status_valid = false;
+		pr_err("%s: error %d sending status command, %sing\n",
+		       req->rq_disk->disk_name, err, retry ? "retry" : "abort");
+	}
+
+	/* We couldn't get a response from the card.  Give up. */
+	if (err) {
+		/* Check if the card is removed */
+		if (mmc_detect_card_removed(card->host))
+			return ERR_NOMEDIUM;
+		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 = true;
+
+	/* Flag General errors */
+	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ)
+		if ((status & R1_ERROR) ||
+			(brq->stop.resp[0] & R1_ERROR)) {
+			pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n",
+			       req->rq_disk->disk_name, __func__,
+			       brq->stop.resp[0], status);
+			*gen_err = true;
+		}
+
+	/*
+	 * Check the current card state.  If it is in some data transfer
+	 * mode, tell it to stop (and hopefully transition back to TRAN.)
+	 */
+	if (R1_CURRENT_STATE(status) == R1_STATE_DATA ||
+	    R1_CURRENT_STATE(status) == R1_STATE_RCV) {
+		err = send_stop(card,
+			DIV_ROUND_UP(brq->data.timeout_ns, 1000000),
+			req, gen_err, &stop_status);
+		if (err) {
+			pr_err("%s: error %d sending stop command\n",
+			       req->rq_disk->disk_name, err);
+			/*
+			 * If the stop cmd also timed out, the card is probably
+			 * not present, so abort. Other errors are bad news too.
+			 */
+			return ERR_ABORT;
+		}
+
+		if (stop_status & R1_CARD_ECC_FAILED)
+			*ecc_err = true;
+	}
+
+	/* Check for set block count errors */
+	if (brq->sbc.error)
+		return mmc_blk_cmd_error(req, "SET_BLOCK_COUNT", brq->sbc.error,
+				prev_cmd_status_valid, status);
+
+	/* Check for r/w command errors */
+	if (brq->cmd.error)
+		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_info("%s: error %d sending stop command, original cmd response %#x, card status %#x\n",
+	       req->rq_disk->disk_name, brq->stop.error,
+	       brq->cmd.resp[0], status);
+
+	/*
+	 * Subsitute in our own stop status as this will give the error
+	 * state which happened during the execution of the r/w command.
+	 */
+	if (stop_status) {
+		brq->stop.resp[0] = stop_status;
+		brq->stop.error = 0;
+	}
+	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 =
+			dev_get_drvdata(&host->card->dev);
+		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;
+}
+
+int mmc_access_rpmb(struct mmc_queue *mq)
+{
+	struct mmc_blk_data *md = mq->blkdata;
+	/*
+	 * If this is a RPMB partition access, return ture
+	 */
+	if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+		return true;
+
+	return false;
+}
+
+static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
+{
+	struct mmc_blk_data *md = mq->blkdata;
+	struct mmc_card *card = md->queue.card;
+	unsigned int from, nr, arg;
+	int err = 0, type = MMC_BLK_DISCARD;
+
+	if (!mmc_can_erase(card)) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	from = blk_rq_pos(req);
+	nr = blk_rq_sectors(req);
+
+	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,
+				 arg == MMC_TRIM_ARG ?
+				 INAND_CMD38_ARG_TRIM :
+				 INAND_CMD38_ARG_ERASE,
+				 0);
+		if (err)
+			goto out;
+	}
+	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);
+	blk_end_request(req, err, blk_rq_bytes(req));
+
+	return err ? 0 : 1;
+}
+
+static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
+				       struct request *req)
+{
+	struct mmc_blk_data *md = mq->blkdata;
+	struct mmc_card *card = md->queue.card;
+	unsigned int from, nr, arg;
+	int err = 0, type = MMC_BLK_SECDISCARD;
+
+	if (!(mmc_can_secure_erase_trim(card))) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	from = blk_rq_pos(req);
+	nr = blk_rq_sectors(req);
+
+	if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
+		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,
+				 arg == MMC_SECURE_TRIM1_ARG ?
+				 INAND_CMD38_ARG_SECTRIM1 :
+				 INAND_CMD38_ARG_SECERASE,
+				 0);
+		if (err)
+			goto out_retry;
+	}
+
+	err = mmc_erase(card, from, nr, arg);
+	if (err == -EIO)
+		goto out_retry;
+	if (err)
+		goto out;
+
+	if (arg == MMC_SECURE_TRIM1_ARG) {
+		if (card->quirks & MMC_QUIRK_INAND_CMD38) {
+			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+					 INAND_CMD38_ARG_EXT_CSD,
+					 INAND_CMD38_ARG_SECTRIM2,
+					 0);
+			if (err)
+				goto out_retry;
+		}
+
+		err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
+		if (err == -EIO)
+			goto out_retry;
+		if (err)
+			goto out;
+	}
+
+out_retry:
+	if (err && !mmc_blk_reset(md, card->host, type))
+		goto retry;
+	if (!err)
+		mmc_blk_reset_success(md, type);
+out:
+	blk_end_request(req, err, blk_rq_bytes(req));
+
+	return err ? 0 : 1;
+}
+
+static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
+{
+	struct mmc_blk_data *md = mq->blkdata;
+	struct mmc_card *card = md->queue.card;
+	int ret = 0;
+
+	ret = mmc_flush_cache(card);
+	if (ret)
+		ret = -EIO;
+
+	blk_end_request_all(req, ret);
+
+	return ret ? 0 : 1;
+}
+
+/*
+ * Reformat current write as a reliable write, supporting
+ * both legacy and the enhanced reliable write MMC cards.
+ * In each transfer we'll handle only as much as a single
+ * reliable write can handle, thus finish the request in
+ * partial completions.
+ */
+static inline void mmc_apply_rel_rw(struct mmc_blk_request *brq,
+				    struct mmc_card *card,
+				    struct request *req)
+{
+	if (!(card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN)) {
+		/* Legacy mode imposes restrictions on transfers. */
+		if (!IS_ALIGNED(brq->cmd.arg, card->ext_csd.rel_sectors))
+			brq->data.blocks = 1;
+
+		if (brq->data.blocks > card->ext_csd.rel_sectors)
+			brq->data.blocks = card->ext_csd.rel_sectors;
+		else if (brq->data.blocks < card->ext_csd.rel_sectors)
+			brq->data.blocks = 1;
+	}
+}
+
+#define CMD_ERRORS							\
+	(R1_OUT_OF_RANGE |	/* Command argument out of range */	\
+	 R1_ADDRESS_ERROR |	/* Misaligned address */		\
+	 R1_BLOCK_LEN_ERROR |	/* Transferred block length incorrect */\
+	 R1_WP_VIOLATION |	/* Tried to write to protected block */	\
+	 R1_CC_ERROR |		/* Card controller error */		\
+	 R1_ERROR)		/* General/unknown error */
+
+static enum mmc_blk_status mmc_blk_err_check(struct mmc_card *card,
+					     struct mmc_async_req *areq)
+{
+	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 need_retune = card->host->need_retune;
+	bool ecc_err = false;
+	bool gen_err = false;
+
+	/*
+	 * sbc.error indicates a problem with the set block count
+	 * command.  No data will have been transferred.
+	 *
+	 * cmd.error indicates a problem with the r/w command.  No
+	 * data will have been transferred.
+	 *
+	 * 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 ||
+	    brq->data.error) {
+		switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) {
+		case ERR_RETRY:
+			return MMC_BLK_RETRY;
+		case ERR_ABORT:
+			return MMC_BLK_ABORT;
+		case ERR_NOMEDIUM:
+			return MMC_BLK_NOMEDIUM;
+		case ERR_CONTINUE:
+			break;
+		}
+	}
+
+	/*
+	 * Check for errors relating to the execution of the
+	 * initial command - such as address errors.  No data
+	 * has been transferred.
+	 */
+	if (brq->cmd.resp[0] & CMD_ERRORS) {
+		pr_err("%s: r/w command failed, status = %#x\n",
+		       req->rq_disk->disk_name, brq->cmd.resp[0]);
+		return MMC_BLK_ABORT;
+	}
+
+	/*
+	 * Everything else is either success, or a data error of some
+	 * kind.  If it was a write, we may have transitioned to
+	 * program mode, which we have to wait for it to complete.
+	 */
+	if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
+		int err;
+
+		/* Check stop command response */
+		if (brq->stop.resp[0] & R1_ERROR) {
+			pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n",
+			       req->rq_disk->disk_name, __func__,
+			       brq->stop.resp[0]);
+			gen_err = true;
+		}
+
+		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, false, req,
+					&gen_err);
+		if (err)
+			return MMC_BLK_CMD_ERR;
+	}
+
+	/* if general error occurs, retry the write operation. */
+	if (gen_err) {
+		pr_warn("%s: retrying write for general error\n",
+				req->rq_disk->disk_name);
+		return MMC_BLK_RETRY;
+	}
+
+	if (brq->data.error) {
+		if (need_retune && !brq->retune_retry_done) {
+			pr_debug("%s: retrying because a re-tune was needed\n",
+				 req->rq_disk->disk_name);
+			brq->retune_retry_done = 1;
+			return MMC_BLK_RETRY;
+		}
+		pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
+		       req->rq_disk->disk_name, brq->data.error,
+		       (unsigned)blk_rq_pos(req),
+		       (unsigned)blk_rq_sectors(req),
+		       brq->cmd.resp[0], brq->stop.resp[0]);
+
+		if (rq_data_dir(req) == READ) {
+			if (ecc_err)
+				return MMC_BLK_ECC_ERR;
+			return MMC_BLK_DATA_ERR;
+		} else {
+			return MMC_BLK_CMD_ERR;
+		}
+	}
+
+	if (!brq->data.bytes_xfered)
+		return MMC_BLK_RETRY;
+
+	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,
+			       struct mmc_card *card,
+			       int disable_multi,
+			       struct mmc_queue *mq)
+{
+	u32 readcmd, writecmd;
+	struct mmc_blk_request *brq = &mqrq->brq;
+	struct request *req = mqrq->req;
+	struct mmc_blk_data *md = mq->blkdata;
+	bool do_data_tag;
+
+	/*
+	 * Reliable writes are used to implement Forced Unit Access and
+	 * are supported only on MMCs.
+	 */
+	bool do_rel_wr = (req->cmd_flags & REQ_FUA) &&
+		(rq_data_dir(req) == WRITE) &&
+		(md->flags & MMC_BLK_REL_WR);
+
+	memset(brq, 0, sizeof(struct mmc_blk_request));
+	brq->mrq.cmd = &brq->cmd;
+	brq->mrq.data = &brq->data;
+
+	brq->cmd.arg = blk_rq_pos(req);
+	if (!mmc_card_blockaddr(card))
+		brq->cmd.arg <<= 9;
+	brq->cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+	brq->data.blksz = 512;
+	brq->stop.opcode = MMC_STOP_TRANSMISSION;
+	brq->stop.arg = 0;
+	brq->data.blocks = blk_rq_sectors(req);
+
+	/*
+	 * The block layer doesn't support all sector count
+	 * restrictions, so we need to be prepared for too big
+	 * requests.
+	 */
+	if (brq->data.blocks > card->host->max_blk_count)
+		brq->data.blocks = card->host->max_blk_count;
+
+	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 have HW issues while operating
+		 * in multiple I/O mode
+		 */
+		if (card->host->ops->multi_io_quirk)
+			brq->data.blocks = card->host->ops->multi_io_quirk(card,
+						(rq_data_dir(req) == READ) ?
+						MMC_DATA_READ : MMC_DATA_WRITE,
+						brq->data.blocks);
+	}
+
+	if (brq->data.blocks > 1 || do_rel_wr) {
+		/* SPI multiblock writes terminate using a special
+		 * token, not a STOP_TRANSMISSION request.
+		 */
+		if (!mmc_host_is_spi(card->host) ||
+		    rq_data_dir(req) == READ)
+			brq->mrq.stop = &brq->stop;
+		readcmd = MMC_READ_MULTIPLE_BLOCK;
+		writecmd = MMC_WRITE_MULTIPLE_BLOCK;
+	} else {
+		brq->mrq.stop = NULL;
+		readcmd = MMC_READ_SINGLE_BLOCK;
+		writecmd = MMC_WRITE_BLOCK;
+	}
+	if (rq_data_dir(req) == READ) {
+		brq->cmd.opcode = readcmd;
+		brq->data.flags = MMC_DATA_READ;
+		if (brq->mrq.stop)
+			brq->stop.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 |
+					MMC_CMD_AC;
+	} else {
+		brq->cmd.opcode = writecmd;
+		brq->data.flags = MMC_DATA_WRITE;
+		if (brq->mrq.stop)
+			brq->stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B |
+					MMC_CMD_AC;
+	}
+
+	if (do_rel_wr)
+		mmc_apply_rel_rw(brq, card, req);
+
+	/*
+	 * Data tag is used only during writing meta data to speed
+	 * up write and any subsequent read of this meta data
+	 */
+	do_data_tag = (card->ext_csd.data_tag_unit_size) &&
+		(req->cmd_flags & REQ_META) &&
+		(rq_data_dir(req) == WRITE) &&
+		((brq->data.blocks * brq->data.blksz) >=
+		 card->ext_csd.data_tag_unit_size);
+
+	/*
+	 * Pre-defined multi-block transfers are preferable to
+	 * open ended-ones (and necessary for reliable writes).
+	 * However, it is not sufficient to just send CMD23,
+	 * and avoid the final CMD12, as on an error condition
+	 * CMD12 (stop) needs to be sent anyway. This, coupled
+	 * with Auto-CMD23 enhancements provided by some
+	 * hosts, means that the complexity of dealing
+	 * with this is best left to the host. If CMD23 is
+	 * supported by card and host, we'll fill sbc in and let
+	 * the host deal with handling it correctly. This means
+	 * that for hosts that don't expose MMC_CAP_CMD23, no
+	 * change of behavior will be observed.
+	 *
+	 * N.B: Some MMC cards experience perf degradation.
+	 * We'll avoid using CMD23-bounded multiblock writes for
+	 * these, while retaining features like reliable writes.
+	 */
+	if ((md->flags & MMC_BLK_CMD23) && mmc_op_multi(brq->cmd.opcode) &&
+	    (do_rel_wr || !(card->quirks & MMC_QUIRK_BLK_NO_CMD23) ||
+	     do_data_tag)) {
+		brq->sbc.opcode = MMC_SET_BLOCK_COUNT;
+		brq->sbc.arg = brq->data.blocks |
+			(do_rel_wr ? (1 << 31) : 0) |
+			(do_data_tag ? (1 << 29) : 0);
+		brq->sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
+		brq->mrq.sbc = &brq->sbc;
+	}
+
+	mmc_set_data_timeout(&brq->data, card);
+
+	brq->data.sg = mqrq->sg;
+	brq->data.sg_len = mmc_queue_map_sg(mq, mqrq);
+
+	/*
+	 * Adjust the sg list so it is the same size as the
+	 * request.
+	 */
+	if (brq->data.blocks != blk_rq_sectors(req)) {
+		int i, data_size = brq->data.blocks << 9;
+		struct scatterlist *sg;
+
+		for_each_sg(brq->data.sg, sg, brq->data.sg_len, i) {
+			data_size -= sg->length;
+			if (data_size <= 0) {
+				sg->length += data_size;
+				i++;
+				break;
+			}
+		}
+		brq->data.sg_len = i;
+	}
+
+	mqrq->mmc_active.mrq = &brq->mrq;
+	mqrq->mmc_active.err_check = mmc_blk_err_check;
+
+	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)
+{
+	struct mmc_queue_req *mq_rq;
+	mq_rq = container_of(brq, struct mmc_queue_req, brq);
+
+	/*
+	 * 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) {
+			ret = blk_end_request(req, 0, blocks << 9);
+		}
+	} else {
+		ret = blk_end_request(req, 0, brq->data.bytes_xfered);
+	}
+	return ret;
+}
+
+static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
+{
+	struct mmc_blk_data *md = mq->blkdata;
+	struct mmc_card *card = md->queue.card;
+	struct mmc_blk_request *brq;
+	int ret = 1, disable_multi = 0, retry = 0, type, retune_retry_done = 0;
+	enum mmc_blk_status status;
+	struct mmc_queue_req *mq_rq;
+	struct request *req;
+	struct mmc_async_req *areq;
+
+	if (!rqc && !mq->mqrq_prev->req)
+		return 0;
+
+	do {
+		if (rqc) {
+			/*
+			 * When 4KB native sector is enabled, only 8 blocks
+			 * multiple read or write is allowed
+			 */
+			if (mmc_large_sector(card) &&
+				!IS_ALIGNED(blk_rq_sectors(rqc), 8)) {
+				pr_err("%s: Transfer size is not 4KB sector size aligned\n",
+					rqc->rq_disk->disk_name);
+				mq_rq = mq->mqrq_cur;
+				req = rqc;
+				rqc = NULL;
+				goto cmd_abort;
+			}
+
+			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+			areq = &mq->mqrq_cur->mmc_active;
+		} else
+			areq = NULL;
+		areq = mmc_start_req(card->host, areq, &status);
+		if (!areq) {
+			if (status == MMC_BLK_NEW_REQUEST)
+				mq->flags |= MMC_QUEUE_NEW_REQUEST;
+			return 0;
+		}
+
+		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) {
+		case MMC_BLK_SUCCESS:
+		case MMC_BLK_PARTIAL:
+			/*
+			 * A block was successfully transferred.
+			 */
+			mmc_blk_reset_success(md, type);
+
+			ret = blk_end_request(req, 0,
+					brq->data.bytes_xfered);
+
+			/*
+			 * 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) {
+				pr_err("%s BUG rq_tot %d d_xfer %d\n",
+				       __func__, blk_rq_bytes(req),
+				       brq->data.bytes_xfered);
+				rqc = NULL;
+				goto cmd_abort;
+			}
+			break;
+		case MMC_BLK_CMD_ERR:
+			ret = mmc_blk_cmd_err(md, card, brq, req, ret);
+			if (mmc_blk_reset(md, card->host, type))
+				goto cmd_abort;
+			if (!ret)
+				goto start_new_req;
+			break;
+		case MMC_BLK_RETRY:
+			retune_retry_done = brq->retune_retry_done;
+			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: {
+			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_warn("%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
+			 * read a single sector.
+			 */
+			ret = blk_end_request(req, -EIO,
+						brq->data.blksz);
+			if (!ret)
+				goto start_new_req;
+			break;
+		case MMC_BLK_NOMEDIUM:
+			goto cmd_abort;
+		default:
+			pr_err("%s: Unhandled return value (%d)",
+					req->rq_disk->disk_name, status);
+			goto cmd_abort;
+		}
+
+		if (ret) {
+			/*
+			 * In case of a incomplete request
+			 * prepare it again and resend.
+			 */
+			mmc_blk_rw_rq_prep(mq_rq, card,
+					disable_multi, mq);
+			mmc_start_req(card->host,
+					&mq_rq->mmc_active, NULL);
+			mq_rq->brq.retune_retry_done = retune_retry_done;
+		}
+	} while (ret);
+
+	return 1;
+
+ cmd_abort:
+	if (mmc_card_removed(card))
+		req->rq_flags |= RQF_QUIET;
+	while (ret)
+		ret = blk_end_request(req, -EIO,
+				blk_rq_cur_bytes(req));
+
+ start_new_req:
+	if (rqc) {
+		if (mmc_card_removed(card)) {
+			rqc->rq_flags |= RQF_QUIET;
+			blk_end_request_all(rqc, -EIO);
+		} else {
+			mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
+			mmc_start_req(card->host,
+				      &mq->mqrq_cur->mmc_active, NULL);
+		}
+	}
+
+	return 0;
+}
+
+int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
+{
+	int ret;
+	struct mmc_blk_data *md = mq->blkdata;
+	struct mmc_card *card = md->queue.card;
+	bool req_is_special = mmc_req_is_special(req);
+
+	if (req && !mq->mqrq_prev->req)
+		/* claim host only for the first request */
+		mmc_get_card(card);
+
+	ret = mmc_blk_part_switch(card, md);
+	if (ret) {
+		if (req) {
+			blk_end_request_all(req, -EIO);
+		}
+		ret = 0;
+		goto out;
+	}
+
+	mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
+	if (req && req_op(req) == REQ_OP_DISCARD) {
+		/* complete ongoing async transfer before issuing discard */
+		if (card->host->areq)
+			mmc_blk_issue_rw_rq(mq, NULL);
+		ret = mmc_blk_issue_discard_rq(mq, req);
+	} else if (req && req_op(req) == REQ_OP_SECURE_ERASE) {
+		/* complete ongoing async transfer before issuing secure erase*/
+		if (card->host->areq)
+			mmc_blk_issue_rw_rq(mq, NULL);
+		ret = mmc_blk_issue_secdiscard_rq(mq, req);
+	} else if (req && req_op(req) == REQ_OP_FLUSH) {
+		/* complete ongoing async transfer before issuing flush */
+		if (card->host->areq)
+			mmc_blk_issue_rw_rq(mq, NULL);
+		ret = mmc_blk_issue_flush(mq, req);
+	} else {
+		ret = mmc_blk_issue_rw_rq(mq, req);
+	}
+
+out:
+	if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || req_is_special)
+		/*
+		 * Release host when there are no more requests
+		 * and after special request(discard, flush) is done.
+		 * In case sepecial request, there is no reentry to
+		 * the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
+		 */
+		mmc_put_card(card);
+	return ret;
+}
+
+static inline int mmc_blk_readonly(struct mmc_card *card)
+{
+	return mmc_card_readonly(card) ||
+	       !(card->csd.cmdclass & CCC_BLOCK_WRITE);
+}
+
+static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
+					      struct device *parent,
+					      sector_t size,
+					      bool default_ro,
+					      const char *subname,
+					      int area_type)
+{
+	struct mmc_blk_data *md;
+	int devidx, ret;
+
+again:
+	if (!ida_pre_get(&mmc_blk_ida, GFP_KERNEL))
+		return ERR_PTR(-ENOMEM);
+
+	spin_lock(&mmc_blk_lock);
+	ret = ida_get_new(&mmc_blk_ida, &devidx);
+	spin_unlock(&mmc_blk_lock);
+
+	if (ret == -EAGAIN)
+		goto again;
+	else if (ret)
+		return ERR_PTR(ret);
+
+	if (devidx >= max_devices) {
+		ret = -ENOSPC;
+		goto out;
+	}
+
+	md = kzalloc(sizeof(struct mmc_blk_data), GFP_KERNEL);
+	if (!md) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	md->area_type = area_type;
+
+	/*
+	 * Set the read-only status based on the supported commands
+	 * and the write protect switch.
+	 */
+	md->read_only = mmc_blk_readonly(card);
+
+	md->disk = alloc_disk(perdev_minors);
+	if (md->disk == NULL) {
+		ret = -ENOMEM;
+		goto err_kfree;
+	}
+
+	spin_lock_init(&md->lock);
+	INIT_LIST_HEAD(&md->part);
+	md->usage = 1;
+
+	ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
+	if (ret)
+		goto err_putdisk;
+
+	md->queue.blkdata = md;
+
+	md->disk->major	= MMC_BLOCK_MAJOR;
+	md->disk->first_minor = devidx * perdev_minors;
+	md->disk->fops = &mmc_bdops;
+	md->disk->private_data = md;
+	md->disk->queue = md->queue.queue;
+	md->parent = parent;
+	set_disk_ro(md->disk, md->read_only || default_ro);
+	md->disk->flags = GENHD_FL_EXT_DEVT;
+	if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT))
+		md->disk->flags |= GENHD_FL_NO_PART_SCAN;
+
+	/*
+	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
+	 *
+	 * - be set for removable media with permanent block devices
+	 * - be unset for removable block devices with permanent media
+	 *
+	 * Since MMC block devices clearly fall under the second
+	 * case, we do not set GENHD_FL_REMOVABLE.  Userspace
+	 * should use the block device creation/destruction hotplug
+	 * messages to tell when the card is present.
+	 */
+
+	snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
+		 "mmcblk%u%s", card->host->index, subname ? subname : "");
+
+	if (mmc_card_mmc(card))
+		blk_queue_logical_block_size(md->queue.queue,
+					     card->ext_csd.data_sector_size);
+	else
+		blk_queue_logical_block_size(md->queue.queue, 512);
+
+	set_capacity(md->disk, size);
+
+	if (mmc_host_cmd23(card->host)) {
+		if ((mmc_card_mmc(card) &&
+		     card->csd.mmca_vsn >= CSD_SPEC_VER_3) ||
+		    (mmc_card_sd(card) &&
+		     card->scr.cmds & SD_SCR_CMD23_SUPPORT))
+			md->flags |= MMC_BLK_CMD23;
+	}
+
+	if (mmc_card_mmc(card) &&
+	    md->flags & MMC_BLK_CMD23 &&
+	    ((card->ext_csd.rel_param & EXT_CSD_WR_REL_PARAM_EN) ||
+	     card->ext_csd.rel_sectors)) {
+		md->flags |= MMC_BLK_REL_WR;
+		blk_queue_write_cache(md->queue.queue, true, true);
+	}
+
+	return md;
+
+ err_putdisk:
+	put_disk(md->disk);
+ err_kfree:
+	kfree(md);
+ out:
+	spin_lock(&mmc_blk_lock);
+	ida_remove(&mmc_blk_ida, devidx);
+	spin_unlock(&mmc_blk_lock);
+	return ERR_PTR(ret);
+}
+
+static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
+{
+	sector_t size;
+
+	if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
+		/*
+		 * The EXT_CSD sector count is in number or 512 byte
+		 * sectors.
+		 */
+		size = card->ext_csd.sectors;
+	} else {
+		/*
+		 * The CSD capacity field is in units of read_blkbits.
+		 * set_capacity takes units of 512 bytes.
+		 */
+		size = (typeof(sector_t))card->csd.capacity
+			<< (card->csd.read_blkbits - 9);
+	}
+
+	return mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
+					MMC_BLK_DATA_AREA_MAIN);
+}
+
+static int mmc_blk_alloc_part(struct mmc_card *card,
+			      struct mmc_blk_data *md,
+			      unsigned int part_type,
+			      sector_t size,
+			      bool default_ro,
+			      const char *subname,
+			      int area_type)
+{
+	char cap_str[10];
+	struct mmc_blk_data *part_md;
+
+	part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro,
+				    subname, area_type);
+	if (IS_ERR(part_md))
+		return PTR_ERR(part_md);
+	part_md->part_type = part_type;
+	list_add(&part_md->part, &md->part);
+
+	string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2,
+			cap_str, sizeof(cap_str));
+	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 idx, ret = 0;
+
+	if (!mmc_card_mmc(card))
+		return 0;
+
+	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,
+				card->part[idx].area_type);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return ret;
+}
+
+static void mmc_blk_remove_req(struct mmc_blk_data *md)
+{
+	struct mmc_card *card;
+
+	if (md) {
+		/*
+		 * Flush remaining requests and free queues. It
+		 * is freeing the queue that stops new requests
+		 * from being accepted.
+		 */
+		card = md->queue.card;
+		mmc_cleanup_queue(&md->queue);
+		if (md->disk->flags & GENHD_FL_UP) {
+			device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+			if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+					card->ext_csd.boot_ro_lockable)
+				device_remove_file(disk_to_dev(md->disk),
+					&md->power_ro_lock);
+
+			del_gendisk(md->disk);
+		}
+		mmc_blk_put(md);
+	}
+}
+
+static void mmc_blk_remove_parts(struct mmc_card *card,
+				 struct mmc_blk_data *md)
+{
+	struct list_head *pos, *q;
+	struct mmc_blk_data *part_md;
+
+	list_for_each_safe(pos, q, &md->part) {
+		part_md = list_entry(pos, struct mmc_blk_data, part);
+		list_del(pos);
+		mmc_blk_remove_req(part_md);
+	}
+}
+
+static int mmc_add_disk(struct mmc_blk_data *md)
+{
+	int ret;
+	struct mmc_card *card = md->queue.card;
+
+	device_add_disk(md->parent, md->disk);
+	md->force_ro.show = force_ro_show;
+	md->force_ro.store = force_ro_store;
+	sysfs_attr_init(&md->force_ro.attr);
+	md->force_ro.attr.name = "force_ro";
+	md->force_ro.attr.mode = S_IRUGO | S_IWUSR;
+	ret = device_create_file(disk_to_dev(md->disk), &md->force_ro);
+	if (ret)
+		goto force_ro_fail;
+
+	if ((md->area_type & MMC_BLK_DATA_AREA_BOOT) &&
+	     card->ext_csd.boot_ro_lockable) {
+		umode_t mode;
+
+		if (card->ext_csd.boot_ro_lock & EXT_CSD_BOOT_WP_B_PWR_WP_DIS)
+			mode = S_IRUGO;
+		else
+			mode = S_IRUGO | S_IWUSR;
+
+		md->power_ro_lock.show = power_ro_lock_show;
+		md->power_ro_lock.store = power_ro_lock_store;
+		sysfs_attr_init(&md->power_ro_lock.attr);
+		md->power_ro_lock.attr.mode = mode;
+		md->power_ro_lock.attr.name =
+					"ro_lock_until_next_power_on";
+		ret = device_create_file(disk_to_dev(md->disk),
+				&md->power_ro_lock);
+		if (ret)
+			goto power_ro_lock_fail;
+	}
+	return ret;
+
+power_ro_lock_fail:
+	device_remove_file(disk_to_dev(md->disk), &md->force_ro);
+force_ro_fail:
+	del_gendisk(md->disk);
+
+	return ret;
+}
+
+static const struct mmc_fixup blk_fixups[] =
+{
+	MMC_FIXUP("SEM02G", CID_MANFID_SANDISK, 0x100, add_quirk,
+		  MMC_QUIRK_INAND_CMD38),
+	MMC_FIXUP("SEM04G", CID_MANFID_SANDISK, 0x100, add_quirk,
+		  MMC_QUIRK_INAND_CMD38),
+	MMC_FIXUP("SEM08G", CID_MANFID_SANDISK, 0x100, add_quirk,
+		  MMC_QUIRK_INAND_CMD38),
+	MMC_FIXUP("SEM16G", CID_MANFID_SANDISK, 0x100, add_quirk,
+		  MMC_QUIRK_INAND_CMD38),
+	MMC_FIXUP("SEM32G", CID_MANFID_SANDISK, 0x100, add_quirk,
+		  MMC_QUIRK_INAND_CMD38),
+
+	/*
+	 * Some MMC cards experience performance degradation with CMD23
+	 * instead of CMD12-bounded multiblock transfers. For now we'll
+	 * black list what's bad...
+	 * - Certain Toshiba cards.
+	 *
+	 * N.B. This doesn't affect SD cards.
+	 */
+	MMC_FIXUP("SDMB-32", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_BLK_NO_CMD23),
+	MMC_FIXUP("SDM032", CID_MANFID_SANDISK, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_BLK_NO_CMD23),
+	MMC_FIXUP("MMC08G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_BLK_NO_CMD23),
+	MMC_FIXUP("MMC16G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_BLK_NO_CMD23),
+	MMC_FIXUP("MMC32G", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_BLK_NO_CMD23),
+
+	/*
+	 * Some MMC cards need longer data read timeout than indicated in CSD.
+	 */
+	MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
+		  MMC_QUIRK_LONG_READ_TIME),
+	MMC_FIXUP("008GE0", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_LONG_READ_TIME),
+
+	/*
+	 * On these Samsung MoviNAND parts, performing secure erase or
+	 * secure trim can result in unrecoverable corruption due to a
+	 * firmware bug.
+	 */
+	MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+
+	/*
+	 *  On Some Kingston eMMCs, performing trim can result in
+	 *  unrecoverable data conrruption occasionally due to a firmware bug.
+	 */
+	MMC_FIXUP("V10008", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_TRIM_BROKEN),
+	MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_TRIM_BROKEN),
+
+	END_FIXUP
+};
+
+static int mmc_blk_probe(struct mmc_card *card)
+{
+	struct mmc_blk_data *md, *part_md;
+	char cap_str[10];
+
+	/*
+	 * Check that the card supports the command class(es) we need.
+	 */
+	if (!(card->csd.cmdclass & CCC_BLOCK_READ))
+		return -ENODEV;
+
+	mmc_fixup_device(card, blk_fixups);
+
+	md = mmc_blk_alloc(card);
+	if (IS_ERR(md))
+		return PTR_ERR(md);
+
+	string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
+			cap_str, sizeof(cap_str));
+	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)" : "");
+
+	if (mmc_blk_alloc_parts(card, md))
+		goto out;
+
+	dev_set_drvdata(&card->dev, md);
+
+	if (mmc_add_disk(md))
+		goto out;
+
+	list_for_each_entry(part_md, &md->part, part) {
+		if (mmc_add_disk(part_md))
+			goto out;
+	}
+
+	pm_runtime_set_autosuspend_delay(&card->dev, 3000);
+	pm_runtime_use_autosuspend(&card->dev);
+
+	/*
+	 * Don't enable runtime PM for SD-combo cards here. Leave that
+	 * decision to be taken during the SDIO init sequence instead.
+	 */
+	if (card->type != MMC_TYPE_SD_COMBO) {
+		pm_runtime_set_active(&card->dev);
+		pm_runtime_enable(&card->dev);
+	}
+
+	return 0;
+
+ out:
+	mmc_blk_remove_parts(card, md);
+	mmc_blk_remove_req(md);
+	return 0;
+}
+
+static void mmc_blk_remove(struct mmc_card *card)
+{
+	struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
+
+	mmc_blk_remove_parts(card, md);
+	pm_runtime_get_sync(&card->dev);
+	mmc_claim_host(card->host);
+	mmc_blk_part_switch(card, md);
+	mmc_release_host(card->host);
+	if (card->type != MMC_TYPE_SD_COMBO)
+		pm_runtime_disable(&card->dev);
+	pm_runtime_put_noidle(&card->dev);
+	mmc_blk_remove_req(md);
+	dev_set_drvdata(&card->dev, NULL);
+}
+
+static int _mmc_blk_suspend(struct mmc_card *card)
+{
+	struct mmc_blk_data *part_md;
+	struct mmc_blk_data *md = dev_get_drvdata(&card->dev);
+
+	if (md) {
+		mmc_queue_suspend(&md->queue);
+		list_for_each_entry(part_md, &md->part, part) {
+			mmc_queue_suspend(&part_md->queue);
+		}
+	}
+	return 0;
+}
+
+static void mmc_blk_shutdown(struct mmc_card *card)
+{
+	_mmc_blk_suspend(card);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mmc_blk_suspend(struct device *dev)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+
+	return _mmc_blk_suspend(card);
+}
+
+static int mmc_blk_resume(struct device *dev)
+{
+	struct mmc_blk_data *part_md;
+	struct mmc_blk_data *md = dev_get_drvdata(dev);
+
+	if (md) {
+		/*
+		 * Resume involves the card going into idle state,
+		 * so current partition is always the main one.
+		 */
+		md->part_curr = md->part_type;
+		mmc_queue_resume(&md->queue);
+		list_for_each_entry(part_md, &md->part, part) {
+			mmc_queue_resume(&part_md->queue);
+		}
+	}
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mmc_blk_pm_ops, mmc_blk_suspend, mmc_blk_resume);
+
+static struct mmc_driver mmc_driver = {
+	.drv		= {
+		.name	= "mmcblk",
+		.pm	= &mmc_blk_pm_ops,
+	},
+	.probe		= mmc_blk_probe,
+	.remove		= mmc_blk_remove,
+	.shutdown	= mmc_blk_shutdown,
+};
+
+static int __init mmc_blk_init(void)
+{
+	int res;
+
+	if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
+		pr_info("mmcblk: using %d minors per device\n", perdev_minors);
+
+	max_devices = min(MAX_DEVICES, (1 << MINORBITS) / perdev_minors);
+
+	res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
+	if (res)
+		goto out;
+
+	res = mmc_register_driver(&mmc_driver);
+	if (res)
+		goto out2;
+
+	return 0;
+ out2:
+	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
+ out:
+	return res;
+}
+
+static void __exit mmc_blk_exit(void)
+{
+	mmc_unregister_driver(&mmc_driver);
+	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
+}
+
+module_init(mmc_blk_init);
+module_exit(mmc_blk_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/block.h linux-libre-4.10-rc8-gnu/drivers/mmc/core/block.h
--- linux-libre-4.9-gnu/drivers/mmc/core/block.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/block.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1 @@
+int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/core.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/core.c
--- linux-libre-4.9-gnu/drivers/mmc/core/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -306,16 +306,16 @@ static int mmc_start_request(struct mmc_
 		mrq->sbc->mrq = mrq;
 	}
 	if (mrq->data) {
-		BUG_ON(mrq->data->blksz > host->max_blk_size);
-		BUG_ON(mrq->data->blocks > host->max_blk_count);
-		BUG_ON(mrq->data->blocks * mrq->data->blksz >
-			host->max_req_size);
-
+		if (mrq->data->blksz > host->max_blk_size ||
+		    mrq->data->blocks > host->max_blk_count ||
+		    mrq->data->blocks * mrq->data->blksz > host->max_req_size)
+			return -EINVAL;
 #ifdef CONFIG_MMC_DEBUG
 		sz = 0;
 		for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)
 			sz += sg->length;
-		BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
+		if (sz != mrq->data->blocks * mrq->data->blksz)
+			return -EINVAL;
 #endif
 
 		mrq->cmd->data = mrq->data;
@@ -349,8 +349,6 @@ void mmc_start_bkops(struct mmc_card *ca
 	int timeout;
 	bool use_busy_signal;
 
-	BUG_ON(!card);
-
 	if (!card->ext_csd.man_bkops_en || mmc_card_doing_bkops(card))
 		return;
 
@@ -380,7 +378,7 @@ void mmc_start_bkops(struct mmc_card *ca
 	mmc_retune_hold(card->host);
 
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-			EXT_CSD_BKOPS_START, 1, timeout,
+			EXT_CSD_BKOPS_START, 1, timeout, 0,
 			use_busy_signal, true, false);
 	if (err) {
 		pr_warn("%s: Error %d starting bkops\n",
@@ -497,32 +495,27 @@ static int __mmc_start_req(struct mmc_ho
  *
  * Returns enum mmc_blk_status after checking errors.
  */
-static int mmc_wait_for_data_req_done(struct mmc_host *host,
-				      struct mmc_request *mrq,
-				      struct mmc_async_req *next_req)
+static enum mmc_blk_status mmc_wait_for_data_req_done(struct mmc_host *host,
+						      struct mmc_request *mrq)
 {
 	struct mmc_command *cmd;
 	struct mmc_context_info *context_info = &host->context_info;
-	int err;
-	unsigned long flags;
+	enum mmc_blk_status status;
 
 	while (1) {
 		wait_event_interruptible(context_info->wait,
 				(context_info->is_done_rcv ||
 				 context_info->is_new_req));
-		spin_lock_irqsave(&context_info->lock, flags);
-		context_info->is_waiting_last_req = false;
-		spin_unlock_irqrestore(&context_info->lock, flags);
+
 		if (context_info->is_done_rcv) {
 			context_info->is_done_rcv = false;
-			context_info->is_new_req = false;
 			cmd = mrq->cmd;
 
 			if (!cmd->error || !cmd->retries ||
 			    mmc_card_removed(host->card)) {
-				err = host->areq->err_check(host->card,
-							    host->areq);
-				break; /* return err */
+				status = host->areq->err_check(host->card,
+							       host->areq);
+				break; /* return status */
 			} else {
 				mmc_retune_recheck(host);
 				pr_info("%s: req failed (CMD%u): %d, retrying...\n",
@@ -533,14 +526,12 @@ static int mmc_wait_for_data_req_done(st
 				__mmc_start_request(host, mrq);
 				continue; /* wait for done/new event again */
 			}
-		} else if (context_info->is_new_req) {
-			context_info->is_new_req = false;
-			if (!next_req)
-				return MMC_BLK_NEW_REQUEST;
 		}
+
+		return MMC_BLK_NEW_REQUEST;
 	}
 	mmc_retune_release(host);
-	return err;
+	return status;
 }
 
 void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq)
@@ -611,18 +602,15 @@ EXPORT_SYMBOL(mmc_is_req_done);
  *	mmc_pre_req - Prepare for a new request
  *	@host: MMC host to prepare command
  *	@mrq: MMC request to prepare for
- *	@is_first_req: true if there is no previous started request
- *                     that may run in parellel to this call, otherwise false
  *
  *	mmc_pre_req() is called in prior to mmc_start_req() to let
  *	host prepare for the new request. Preparation of a request may be
  *	performed while another request is running on the host.
  */
-static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
-		 bool is_first_req)
+static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq)
 {
 	if (host->ops->pre_req)
-		host->ops->pre_req(host, mrq, is_first_req);
+		host->ops->pre_req(host, mrq);
 }
 
 /**
@@ -658,21 +646,22 @@ static void mmc_post_req(struct mmc_host
  *	is returned without waiting. NULL is not an error condition.
  */
 struct mmc_async_req *mmc_start_req(struct mmc_host *host,
-				    struct mmc_async_req *areq, int *error)
+				    struct mmc_async_req *areq,
+				    enum mmc_blk_status *ret_stat)
 {
-	int err = 0;
+	enum mmc_blk_status status = MMC_BLK_SUCCESS;
 	int start_err = 0;
 	struct mmc_async_req *data = host->areq;
 
 	/* Prepare a new request */
 	if (areq)
-		mmc_pre_req(host, areq->mrq, !host->areq);
+		mmc_pre_req(host, areq->mrq);
 
 	if (host->areq) {
-		err = mmc_wait_for_data_req_done(host, host->areq->mrq,	areq);
-		if (err == MMC_BLK_NEW_REQUEST) {
-			if (error)
-				*error = err;
+		status = mmc_wait_for_data_req_done(host, host->areq->mrq);
+		if (status == MMC_BLK_NEW_REQUEST) {
+			if (ret_stat)
+				*ret_stat = status;
 			/*
 			 * The previous request was not completed,
 			 * nothing to return
@@ -695,27 +684,27 @@ struct mmc_async_req *mmc_start_req(stru
 
 			/* prepare the request again */
 			if (areq)
-				mmc_pre_req(host, areq->mrq, !host->areq);
+				mmc_pre_req(host, areq->mrq);
 		}
 	}
 
-	if (!err && areq)
+	if (status == MMC_BLK_SUCCESS && areq)
 		start_err = __mmc_start_data_req(host, areq->mrq);
 
 	if (host->areq)
 		mmc_post_req(host, host->areq->mrq, 0);
 
 	 /* Cancel a prepared request if it was not started. */
-	if ((err || start_err) && areq)
+	if ((status != MMC_BLK_SUCCESS || start_err) && areq)
 		mmc_post_req(host, areq->mrq, -EINVAL);
 
-	if (err)
+	if (status != MMC_BLK_SUCCESS)
 		host->areq = NULL;
 	else
 		host->areq = areq;
 
-	if (error)
-		*error = err;
+	if (ret_stat)
+		*ret_stat = status;
 	return data;
 }
 EXPORT_SYMBOL(mmc_start_req);
@@ -754,8 +743,6 @@ int mmc_interrupt_hpi(struct mmc_card *c
 	u32 status;
 	unsigned long prg_wait;
 
-	BUG_ON(!card);
-
 	if (!card->ext_csd.hpi_en) {
 		pr_info("%s: HPI enable bit unset\n", mmc_hostname(card->host));
 		return 1;
@@ -850,7 +837,6 @@ int mmc_stop_bkops(struct mmc_card *card
 {
 	int err = 0;
 
-	BUG_ON(!card);
 	err = mmc_interrupt_hpi(card);
 
 	/*
@@ -1666,8 +1652,6 @@ int mmc_set_signal_voltage(struct mmc_ho
 	int err = 0;
 	u32 clock;
 
-	BUG_ON(!host);
-
 	/*
 	 * Send CMD11 only if the request is to switch the card to
 	 * 1.8V signalling.
@@ -1884,9 +1868,7 @@ void mmc_power_cycle(struct mmc_host *ho
  */
 static void __mmc_release_bus(struct mmc_host *host)
 {
-	BUG_ON(!host);
-	BUG_ON(host->bus_refs);
-	BUG_ON(!host->bus_dead);
+	WARN_ON(!host->bus_dead);
 
 	host->bus_ops = NULL;
 }
@@ -1926,15 +1908,12 @@ void mmc_attach_bus(struct mmc_host *hos
 {
 	unsigned long flags;
 
-	BUG_ON(!host);
-	BUG_ON(!ops);
-
 	WARN_ON(!host->claimed);
 
 	spin_lock_irqsave(&host->lock, flags);
 
-	BUG_ON(host->bus_ops);
-	BUG_ON(host->bus_refs);
+	WARN_ON(host->bus_ops);
+	WARN_ON(host->bus_refs);
 
 	host->bus_ops = ops;
 	host->bus_refs = 1;
@@ -1950,8 +1929,6 @@ void mmc_detach_bus(struct mmc_host *hos
 {
 	unsigned long flags;
 
-	BUG_ON(!host);
-
 	WARN_ON(!host->claimed);
 	WARN_ON(!host->bus_ops);
 
@@ -2824,12 +2801,11 @@ void mmc_start_host(struct mmc_host *hos
 	host->rescan_disable = 0;
 	host->ios.power_mode = MMC_POWER_UNDEFINED;
 
-	mmc_claim_host(host);
-	if (host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)
-		mmc_power_off(host);
-	else
+	if (!(host->caps2 & MMC_CAP2_NO_PRESCAN_POWERUP)) {
+		mmc_claim_host(host);
 		mmc_power_up(host, host->ocr_avail);
-	mmc_release_host(host);
+		mmc_release_host(host);
+	}
 
 	mmc_gpiod_request_cd_irq(host);
 	_mmc_detect_change(host, 0, false);
@@ -2865,8 +2841,6 @@ void mmc_stop_host(struct mmc_host *host
 	}
 	mmc_bus_put(host);
 
-	BUG_ON(host->card);
-
 	mmc_claim_host(host);
 	mmc_power_off(host);
 	mmc_release_host(host);
@@ -3019,7 +2993,6 @@ void mmc_unregister_pm_notifier(struct m
  */
 void mmc_init_context_info(struct mmc_host *host)
 {
-	spin_lock_init(&host->context_info.lock);
 	host->context_info.is_new_req = false;
 	host->context_info.is_done_rcv = false;
 	host->context_info.is_waiting_last_req = false;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/debugfs.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/debugfs.c
--- linux-libre-4.9-gnu/drivers/mmc/core/debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -321,7 +321,11 @@ static int mmc_ext_csd_open(struct inode
 	for (i = 0; i < 512; i++)
 		n += sprintf(buf + n, "%02x", ext_csd[i]);
 	n += sprintf(buf + n, "\n");
-	BUG_ON(n != EXT_CSD_STR_LEN);
+
+	if (n != EXT_CSD_STR_LEN) {
+		err = -EINVAL;
+		goto out_free;
+	}
 
 	filp->private_data = buf;
 	kfree(ext_csd);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/Kconfig linux-libre-4.10-rc8-gnu/drivers/mmc/core/Kconfig
--- linux-libre-4.9-gnu/drivers/mmc/core/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -22,3 +22,69 @@ config PWRSEQ_SIMPLE
 
 	  This driver can also be built as a module. If so, the module
 	  will be called pwrseq_simple.
+
+config MMC_BLOCK
+	tristate "MMC block device driver"
+	depends on BLOCK
+	default y
+	help
+	  Say Y here to enable the MMC block device driver support.
+	  This provides a block device driver, which you can use to
+	  mount the filesystem. Almost everyone wishing MMC support
+	  should say Y or M here.
+
+config MMC_BLOCK_MINORS
+	int "Number of minors per block device"
+	depends on MMC_BLOCK
+	range 4 256
+	default 8
+	help
+	  Number of minors per block device. One is needed for every
+	  partition on the disk (plus one for the whole disk).
+
+	  Number of total MMC minors available is 256, so your number
+	  of supported block devices will be limited to 256 divided
+	  by this number.
+
+	  Default is 8 to be backwards compatible with previous
+	  hardwired device numbering.
+
+	  If unsure, say 8 here.
+
+config MMC_BLOCK_BOUNCE
+	bool "Use bounce buffer for simple hosts"
+	depends on MMC_BLOCK
+	default y
+	help
+	  SD/MMC is a high latency protocol where it is crucial to
+	  send large requests in order to get high performance. Many
+	  controllers, however, are restricted to continuous memory
+	  (i.e. they can't do scatter-gather), something the kernel
+	  rarely can provide.
+
+	  Say Y here to help these restricted hosts by bouncing
+	  requests back and forth from a large buffer. You will get
+	  a big performance gain at the cost of up to 64 KiB of
+	  physical memory.
+
+	  If unsure, say Y here.
+
+config SDIO_UART
+	tristate "SDIO UART/GPS class support"
+	depends on TTY
+	help
+	  SDIO function driver for SDIO cards that implements the UART
+	  class, as well as the GPS class which appears like a UART.
+
+config MMC_TEST
+	tristate "MMC host test driver"
+	help
+	  Development driver that performs a series of reads and writes
+	  to a memory card in order to expose certain well known bugs
+	  in host controllers. The tests are executed by writing to the
+	  "test" file in debugfs under each card. Note that whatever is
+	  on your card will be overwritten by these tests.
+
+	  This driver is only of interest to those developing or
+	  testing a host driver. Most people should say N here.
+
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/Makefile linux-libre-4.10-rc8-gnu/drivers/mmc/core/Makefile
--- linux-libre-4.9-gnu/drivers/mmc/core/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -12,3 +12,7 @@ mmc_core-$(CONFIG_OF)		+= pwrseq.o
 obj-$(CONFIG_PWRSEQ_SIMPLE)	+= pwrseq_simple.o
 obj-$(CONFIG_PWRSEQ_EMMC)	+= pwrseq_emmc.o
 mmc_core-$(CONFIG_DEBUG_FS)	+= debugfs.o
+obj-$(CONFIG_MMC_BLOCK)		+= mmc_block.o
+mmc_block-objs			:= block.o queue.o
+obj-$(CONFIG_MMC_TEST)		+= mmc_test.o
+obj-$(CONFIG_SDIO_UART)		+= sdio_uart.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/mmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc.c
--- linux-libre-4.9-gnu/drivers/mmc/core/mmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -618,6 +618,24 @@ static int mmc_decode_ext_csd(struct mmc
 			(ext_csd[EXT_CSD_SUPPORTED_MODE] & 0x1) &&
 			!(ext_csd[EXT_CSD_FW_CONFIG] & 0x1);
 	}
+
+	/* eMMC v5.1 or later */
+	if (card->ext_csd.rev >= 8) {
+		card->ext_csd.cmdq_support = ext_csd[EXT_CSD_CMDQ_SUPPORT] &
+					     EXT_CSD_CMDQ_SUPPORTED;
+		card->ext_csd.cmdq_depth = (ext_csd[EXT_CSD_CMDQ_DEPTH] &
+					    EXT_CSD_CMDQ_DEPTH_MASK) + 1;
+		/* Exclude inefficiently small queue depths */
+		if (card->ext_csd.cmdq_depth <= 2) {
+			card->ext_csd.cmdq_support = false;
+			card->ext_csd.cmdq_depth = 0;
+		}
+		if (card->ext_csd.cmdq_support) {
+			pr_debug("%s: Command Queue supported depth %u\n",
+				 mmc_hostname(card->host),
+				 card->ext_csd.cmdq_depth);
+		}
+	}
 out:
 	return err;
 }
@@ -1003,19 +1021,6 @@ static int mmc_select_bus_width(struct m
 	return err;
 }
 
-/* Caller must hold re-tuning */
-static int mmc_switch_status(struct mmc_card *card)
-{
-	u32 status;
-	int err;
-
-	err = mmc_send_status(card, &status);
-	if (err)
-		return err;
-
-	return mmc_switch_status_error(card->host, status);
-}
-
 /*
  * Switch to the high-speed mode
  */
@@ -1025,13 +1030,8 @@ static int mmc_select_hs(struct mmc_card
 
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
-			   card->ext_csd.generic_cmd6_time,
-			   true, false, true);
-	if (!err) {
-		mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
-		err = mmc_switch_status(card);
-	}
-
+			   card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS,
+			   true, true, true);
 	if (err)
 		pr_warn("%s: switch to high-speed failed, err:%d\n",
 			mmc_hostname(card->host), err);
@@ -1058,10 +1058,12 @@ static int mmc_select_hs_ddr(struct mmc_
 	ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
 		EXT_CSD_DDR_BUS_WIDTH_8 : EXT_CSD_DDR_BUS_WIDTH_4;
 
-	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-			EXT_CSD_BUS_WIDTH,
-			ext_csd_bits,
-			card->ext_csd.generic_cmd6_time);
+	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			   EXT_CSD_BUS_WIDTH,
+			   ext_csd_bits,
+			   card->ext_csd.generic_cmd6_time,
+			   MMC_TIMING_MMC_DDR52,
+			   true, true, true);
 	if (err) {
 		pr_err("%s: switch to bus width %d ddr failed\n",
 			mmc_hostname(host), 1 << bus_width);
@@ -1104,9 +1106,6 @@ static int mmc_select_hs_ddr(struct mmc_
 	if (err)
 		err = __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330);
 
-	if (!err)
-		mmc_set_timing(host, MMC_TIMING_MMC_DDR52);
-
 	return err;
 }
 
@@ -1128,7 +1127,7 @@ static int mmc_select_hs400(struct mmc_c
 	val = EXT_CSD_TIMING_HS;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
-			   card->ext_csd.generic_cmd6_time,
+			   card->ext_csd.generic_cmd6_time, 0,
 			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
@@ -1163,7 +1162,7 @@ static int mmc_select_hs400(struct mmc_c
 	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
-			   card->ext_csd.generic_cmd6_time,
+			   card->ext_csd.generic_cmd6_time, 0,
 			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to hs400 failed, err:%d\n",
@@ -1206,7 +1205,7 @@ int mmc_hs400_to_hs200(struct mmc_card *
 	/* Switch HS400 to HS DDR */
 	val = EXT_CSD_TIMING_HS;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
-			   val, card->ext_csd.generic_cmd6_time,
+			   val, card->ext_csd.generic_cmd6_time, 0,
 			   true, false, true);
 	if (err)
 		goto out_err;
@@ -1220,7 +1219,7 @@ int mmc_hs400_to_hs200(struct mmc_card *
 	/* Switch HS DDR to HS */
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
 			   EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time,
-			   true, false, true);
+			   0, true, false, true);
 	if (err)
 		goto out_err;
 
@@ -1234,14 +1233,19 @@ int mmc_hs400_to_hs200(struct mmc_card *
 	val = EXT_CSD_TIMING_HS200 |
 	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
-			   val, card->ext_csd.generic_cmd6_time,
+			   val, card->ext_csd.generic_cmd6_time, 0,
 			   true, false, true);
 	if (err)
 		goto out_err;
 
 	mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 
-	err = mmc_switch_status(card);
+	/*
+	 * For HS200, CRC errors are not a reliable way to know the switch
+	 * failed. If there really is a problem, we would expect tuning will
+	 * fail and the result ends up the same.
+	 */
+	err = __mmc_switch_status(card, false);
 	if (err)
 		goto out_err;
 
@@ -1281,16 +1285,23 @@ static int mmc_select_hs400es(struct mmc
 		goto out_err;
 
 	/* Switch card to HS mode */
-	err = mmc_select_hs(card);
-	if (err)
+	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+			   EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS,
+			   card->ext_csd.generic_cmd6_time, 0,
+			   true, false, true);
+	if (err) {
+		pr_err("%s: switch to hs for hs400es failed, err:%d\n",
+			mmc_hostname(host), err);
 		goto out_err;
+	}
 
-	mmc_set_clock(host, card->ext_csd.hs_max_dtr);
-
+	mmc_set_timing(host, MMC_TIMING_MMC_HS);
 	err = mmc_switch_status(card);
 	if (err)
 		goto out_err;
 
+	mmc_set_clock(host, card->ext_csd.hs_max_dtr);
+
 	/* Switch card to DDR with strobe bit */
 	val = EXT_CSD_DDR_BUS_WIDTH_8 | EXT_CSD_BUS_WIDTH_STROBE;
 	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1308,7 +1319,7 @@ static int mmc_select_hs400es(struct mmc
 	      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			   EXT_CSD_HS_TIMING, val,
-			   card->ext_csd.generic_cmd6_time,
+			   card->ext_csd.generic_cmd6_time, 0,
 			   true, false, true);
 	if (err) {
 		pr_err("%s: switch to hs400es failed, err:%d\n",
@@ -1390,14 +1401,20 @@ static int mmc_select_hs200(struct mmc_c
 		      card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
 		err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 				   EXT_CSD_HS_TIMING, val,
-				   card->ext_csd.generic_cmd6_time,
+				   card->ext_csd.generic_cmd6_time, 0,
 				   true, false, true);
 		if (err)
 			goto err;
 		old_timing = host->ios.timing;
 		mmc_set_timing(host, MMC_TIMING_MMC_HS200);
 
-		err = mmc_switch_status(card);
+		/*
+		 * For HS200, CRC errors are not a reliable way to know the
+		 * switch failed. If there really is a problem, we would expect
+		 * tuning will fail and the result ends up the same.
+		 */
+		err = __mmc_switch_status(card, false);
+
 		/*
 		 * mmc_select_timing() assumes timing has not changed if
 		 * it is a switch error.
@@ -1480,7 +1497,6 @@ static int mmc_init_card(struct mmc_host
 	u32 cid[4];
 	u32 rocr;
 
-	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
 	/* Set correct bus mode for MMC before attempting init */
@@ -1854,7 +1870,7 @@ static int mmc_poweroff_notify(struct mm
 
 	err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 			EXT_CSD_POWER_OFF_NOTIFICATION,
-			notify_type, timeout, true, false, false);
+			notify_type, timeout, 0, true, false, false);
 	if (err)
 		pr_err("%s: Power Off Notification timed out, %u\n",
 		       mmc_hostname(card->host), timeout);
@@ -1870,9 +1886,6 @@ static int mmc_poweroff_notify(struct mm
  */
 static void mmc_remove(struct mmc_host *host)
 {
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_remove_card(host->card);
 	host->card = NULL;
 }
@@ -1892,9 +1905,6 @@ static void mmc_detect(struct mmc_host *
 {
 	int err;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_get_card(host->card);
 
 	/*
@@ -1920,9 +1930,6 @@ static int _mmc_suspend(struct mmc_host
 	unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT :
 					EXT_CSD_POWER_OFF_LONG;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_claim_host(host);
 
 	if (mmc_card_suspended(host->card))
@@ -1979,9 +1986,6 @@ static int _mmc_resume(struct mmc_host *
 {
 	int err = 0;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_claim_host(host);
 
 	if (!mmc_card_suspended(host->card))
@@ -2114,7 +2118,6 @@ int mmc_attach_mmc(struct mmc_host *host
 	int err;
 	u32 ocr, rocr;
 
-	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
 	/* Set correct bus mode for MMC before attempting attach */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/mmc_ops.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc_ops.c
--- linux-libre-4.9-gnu/drivers/mmc/core/mmc_ops.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc_ops.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,21 +54,15 @@ static const u8 tuning_blk_pattern_8bit[
 	0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
 };
 
-static inline int __mmc_send_status(struct mmc_card *card, u32 *status,
-				    bool ignore_crc)
+int mmc_send_status(struct mmc_card *card, u32 *status)
 {
 	int err;
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-
 	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;
-	if (ignore_crc)
-		cmd.flags &= ~MMC_RSP_CRC;
 
 	err = mmc_wait_for_cmd(card->host, &cmd, MMC_CMD_RETRIES);
 	if (err)
@@ -83,17 +77,10 @@ static inline int __mmc_send_status(stru
 	return 0;
 }
 
-int mmc_send_status(struct mmc_card *card, u32 *status)
-{
-	return __mmc_send_status(card, status, false);
-}
-
 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!host);
-
 	cmd.opcode = MMC_SELECT_CARD;
 
 	if (card) {
@@ -109,7 +96,6 @@ static int _mmc_select_card(struct mmc_h
 
 int mmc_select_card(struct mmc_card *card)
 {
-	BUG_ON(!card);
 
 	return _mmc_select_card(card->host, card);
 }
@@ -181,8 +167,6 @@ int mmc_send_op_cond(struct mmc_host *ho
 	struct mmc_command cmd = {0};
 	int i, err = 0;
 
-	BUG_ON(!host);
-
 	cmd.opcode = MMC_SEND_OP_COND;
 	cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
 	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
@@ -221,9 +205,6 @@ int mmc_all_send_cid(struct mmc_host *ho
 	int err;
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!host);
-	BUG_ON(!cid);
-
 	cmd.opcode = MMC_ALL_SEND_CID;
 	cmd.arg = 0;
 	cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
@@ -241,9 +222,6 @@ int mmc_set_relative_addr(struct mmc_car
 {
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-
 	cmd.opcode = MMC_SET_RELATIVE_ADDR;
 	cmd.arg = card->rca << 16;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
@@ -257,9 +235,6 @@ mmc_send_cxd_native(struct mmc_host *hos
 	int err;
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!host);
-	BUG_ON(!cxd);
-
 	cmd.opcode = opcode;
 	cmd.arg = arg;
 	cmd.flags = MMC_RSP_R2 | MMC_CMD_AC;
@@ -440,7 +415,7 @@ int mmc_spi_set_crc(struct mmc_host *hos
 	return err;
 }
 
-int mmc_switch_status_error(struct mmc_host *host, u32 status)
+static int mmc_switch_status_error(struct mmc_host *host, u32 status)
 {
 	if (mmc_host_is_spi(host)) {
 		if (status & R1_SPI_ILLEGAL_COMMAND)
@@ -455,6 +430,85 @@ int mmc_switch_status_error(struct mmc_h
 	return 0;
 }
 
+/* Caller must hold re-tuning */
+int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal)
+{
+	u32 status;
+	int err;
+
+	err = mmc_send_status(card, &status);
+	if (!crc_err_fatal && err == -EILSEQ)
+		return 0;
+	if (err)
+		return err;
+
+	return mmc_switch_status_error(card->host, status);
+}
+
+int mmc_switch_status(struct mmc_card *card)
+{
+	return __mmc_switch_status(card, true);
+}
+
+static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
+			bool send_status, bool retry_crc_err)
+{
+	struct mmc_host *host = card->host;
+	int err;
+	unsigned long timeout;
+	u32 status = 0;
+	bool expired = false;
+	bool busy = false;
+
+	/* We have an unspecified cmd timeout, use the fallback value. */
+	if (!timeout_ms)
+		timeout_ms = MMC_OPS_TIMEOUT_MS;
+
+	/*
+	 * In cases when not allowed to poll by using CMD13 or because we aren't
+	 * capable of polling by using ->card_busy(), then rely on waiting the
+	 * stated timeout to be sufficient.
+	 */
+	if (!send_status && !host->ops->card_busy) {
+		mmc_delay(timeout_ms);
+		return 0;
+	}
+
+	timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
+	do {
+		/*
+		 * Due to the possibility of being preempted while polling,
+		 * check the expiration time first.
+		 */
+		expired = time_after(jiffies, timeout);
+
+		if (host->ops->card_busy) {
+			busy = host->ops->card_busy(host);
+		} else {
+			err = mmc_send_status(card, &status);
+			if (retry_crc_err && err == -EILSEQ) {
+				busy = true;
+			} else if (err) {
+				return err;
+			} else {
+				err = mmc_switch_status_error(host, status);
+				if (err)
+					return err;
+				busy = R1_CURRENT_STATE(status) == R1_STATE_PRG;
+			}
+		}
+
+		/* Timeout if the device still remains busy. */
+		if (expired && busy) {
+			pr_err("%s: Card stuck being busy! %s\n",
+				mmc_hostname(host), __func__);
+			return -ETIMEDOUT;
+		}
+	} while (busy);
+
+	return 0;
+}
+
 /**
  *	__mmc_switch - modify EXT_CSD register
  *	@card: the MMC card associated with the data transfer
@@ -463,24 +517,22 @@ int mmc_switch_status_error(struct mmc_h
  *	@value: value to program into EXT_CSD register
  *	@timeout_ms: timeout (ms) for operation performed by register write,
  *                   timeout of zero implies maximum possible timeout
+ *	@timing: new timing to change to
  *	@use_busy_signal: use the busy signal as response type
  *	@send_status: send status cmd to poll for busy
- *	@ignore_crc: ignore CRC errors when sending status cmd to poll for busy
+ *	@retry_crc_err: retry when CRC errors when polling with CMD13 for busy
  *
  *	Modifies the EXT_CSD register for selected card.
  */
 int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
-		unsigned int timeout_ms, bool use_busy_signal, bool send_status,
-		bool ignore_crc)
+		unsigned int timeout_ms, unsigned char timing,
+		bool use_busy_signal, bool send_status,	bool retry_crc_err)
 {
 	struct mmc_host *host = card->host;
 	int err;
 	struct mmc_command cmd = {0};
-	unsigned long timeout;
-	u32 status = 0;
 	bool use_r1b_resp = use_busy_signal;
-	bool expired = false;
-	bool busy = false;
+	unsigned char old_timing = host->ios.timing;
 
 	mmc_retune_hold(host);
 
@@ -522,62 +574,26 @@ int __mmc_switch(struct mmc_card *card,
 	if (!use_busy_signal)
 		goto out;
 
-	/*
-	 * CRC errors shall only be ignored in cases were CMD13 is used to poll
-	 * to detect busy completion.
-	 */
-	if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
-		ignore_crc = false;
-
-	/* We have an unspecified cmd timeout, use the fallback value. */
-	if (!timeout_ms)
-		timeout_ms = MMC_OPS_TIMEOUT_MS;
-
-	/* Must check status to be sure of no errors. */
-	timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
-	do {
-		/*
-		 * Due to the possibility of being preempted after
-		 * sending the status command, check the expiration
-		 * time first.
-		 */
-		expired = time_after(jiffies, timeout);
-		if (send_status) {
-			err = __mmc_send_status(card, &status, ignore_crc);
-			if (err)
-				goto out;
-		}
-		if ((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp)
-			break;
-		if (host->ops->card_busy) {
-			if (!host->ops->card_busy(host))
-				break;
-			busy = true;
-		}
-		if (mmc_host_is_spi(host))
-			break;
+	/*If SPI or used HW busy detection above, then we don't need to poll. */
+	if (((host->caps & MMC_CAP_WAIT_WHILE_BUSY) && use_r1b_resp) ||
+		mmc_host_is_spi(host))
+		goto out_tim;
 
-		/*
-		 * We are not allowed to issue a status command and the host
-		 * does'nt support MMC_CAP_WAIT_WHILE_BUSY, then we can only
-		 * rely on waiting for the stated timeout to be sufficient.
-		 */
-		if (!send_status && !host->ops->card_busy) {
-			mmc_delay(timeout_ms);
-			goto out;
-		}
+	/* Let's try to poll to find out when the command is completed. */
+	err = mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err);
+	if (err)
+		goto out;
 
-		/* Timeout if the device never leaves the program state. */
-		if (expired &&
-		    (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy)) {
-			pr_err("%s: Card stuck in programming state! %s\n",
-				mmc_hostname(host), __func__);
-			err = -ETIMEDOUT;
-			goto out;
-		}
-	} while (R1_CURRENT_STATE(status) == R1_STATE_PRG || busy);
+out_tim:
+	/* Switch to new timing before check switch status. */
+	if (timing)
+		mmc_set_timing(host, timing);
 
-	err = mmc_switch_status_error(host, status);
+	if (send_status) {
+		err = mmc_switch_status(card);
+		if (err && timing)
+			mmc_set_timing(host, old_timing);
+	}
 out:
 	mmc_retune_release(host);
 
@@ -587,8 +603,8 @@ out:
 int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		unsigned int timeout_ms)
 {
-	return __mmc_switch(card, set, index, value, timeout_ms, true, true,
-				false);
+	return __mmc_switch(card, set, index, value, timeout_ms, 0,
+			true, true, false);
 }
 EXPORT_SYMBOL_GPL(mmc_switch);
 
@@ -661,6 +677,31 @@ out:
 }
 EXPORT_SYMBOL_GPL(mmc_send_tuning);
 
+int mmc_abort_tuning(struct mmc_host *host, u32 opcode)
+{
+	struct mmc_command cmd = {0};
+
+	/*
+	 * eMMC specification specifies that CMD12 can be used to stop a tuning
+	 * command, but SD specification does not, so do nothing unless it is
+	 * eMMC.
+	 */
+	if (opcode != MMC_SEND_TUNING_BLOCK_HS200)
+		return 0;
+
+	cmd.opcode = MMC_STOP_TRANSMISSION;
+	cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+
+	/*
+	 * For drivers that override R1 to R1b, set an arbitrary timeout based
+	 * on the tuning timeout i.e. 150ms.
+	 */
+	cmd.busy_timeout = 150;
+
+	return mmc_wait_for_cmd(host, &cmd, 0);
+}
+EXPORT_SYMBOL_GPL(mmc_abort_tuning);
+
 static int
 mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
 		  u8 len)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/mmc_ops.h linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc_ops.h
--- linux-libre-4.9-gnu/drivers/mmc/core/mmc_ops.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc_ops.h	2017-02-12 16:03:20.000000000 -0500
@@ -27,10 +27,11 @@ int mmc_spi_set_crc(struct mmc_host *hos
 int mmc_bus_test(struct mmc_card *card, u8 bus_width);
 int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
 int mmc_can_ext_csd(struct mmc_card *card);
-int mmc_switch_status_error(struct mmc_host *host, u32 status);
+int mmc_switch_status(struct mmc_card *card);
+int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
 int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
-		unsigned int timeout_ms, bool use_busy_signal, bool send_status,
-		bool ignore_crc);
+		unsigned int timeout_ms, unsigned char timing,
+		bool use_busy_signal, bool send_status,	bool retry_crc_err);
 
 #endif
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/mmc_test.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc_test.c
--- linux-libre-4.9-gnu/drivers/mmc/core/mmc_test.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/mmc_test.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3312 @@
+/*
+ *  Copyright 2007-2008 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/slab.h>
+
+#include <linux/scatterlist.h>
+#include <linux/swap.h>		/* For nr_free_buffer_pages() */
+#include <linux/list.h>
+
+#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
+#define RESULT_UNSUP_HOST	2
+#define RESULT_UNSUP_CARD	3
+
+#define BUFFER_ORDER		2
+#define BUFFER_SIZE		(PAGE_SIZE << BUFFER_ORDER)
+
+#define TEST_ALIGN_END		8
+
+/*
+ * Limit the test area size to the maximum MMC HC erase group size.  Note that
+ * the maximum SD allocation unit size is just 4MiB.
+ */
+#define TEST_AREA_MAX_SIZE (128 * 1024 * 1024)
+
+/**
+ * struct mmc_test_pages - pages allocated by 'alloc_pages()'.
+ * @page: first page in the allocation
+ * @order: order of the number of pages allocated
+ */
+struct mmc_test_pages {
+	struct page *page;
+	unsigned int order;
+};
+
+/**
+ * struct mmc_test_mem - allocated memory.
+ * @arr: array of allocations
+ * @cnt: number of allocations
+ */
+struct mmc_test_mem {
+	struct mmc_test_pages *arr;
+	unsigned int cnt;
+};
+
+/**
+ * struct mmc_test_area - information for performance tests.
+ * @max_sz: test area size (in bytes)
+ * @dev_addr: address on card at which to do performance tests
+ * @max_tfr: maximum transfer size allowed by driver (in bytes)
+ * @max_segs: maximum segments allowed by driver in scatterlist @sg
+ * @max_seg_sz: maximum segment size allowed by driver
+ * @blocks: number of (512 byte) blocks currently mapped by @sg
+ * @sg_len: length of currently mapped scatterlist @sg
+ * @mem: allocated memory
+ * @sg: scatterlist
+ */
+struct mmc_test_area {
+	unsigned long max_sz;
+	unsigned int dev_addr;
+	unsigned int max_tfr;
+	unsigned int max_segs;
+	unsigned int max_seg_sz;
+	unsigned int blocks;
+	unsigned int sg_len;
+	struct mmc_test_mem *mem;
+	struct scatterlist *sg;
+};
+
+/**
+ * struct mmc_test_transfer_result - transfer results for performance tests.
+ * @link: double-linked list
+ * @count: amount of group of sectors to check
+ * @sectors: amount of sectors to check in one group
+ * @ts: time values of transfer
+ * @rate: calculated transfer rate
+ * @iops: I/O operations per second (times 100)
+ */
+struct mmc_test_transfer_result {
+	struct list_head link;
+	unsigned int count;
+	unsigned int sectors;
+	struct timespec ts;
+	unsigned int rate;
+	unsigned int iops;
+};
+
+/**
+ * struct mmc_test_general_result - results for tests.
+ * @link: double-linked list
+ * @card: card under test
+ * @testcase: number of test case
+ * @result: result of test run
+ * @tr_lst: transfer measurements if any as mmc_test_transfer_result
+ */
+struct mmc_test_general_result {
+	struct list_head link;
+	struct mmc_card *card;
+	int testcase;
+	int result;
+	struct list_head tr_lst;
+};
+
+/**
+ * struct mmc_test_dbgfs_file - debugfs related file.
+ * @link: double-linked list
+ * @card: card under test
+ * @file: file created under debugfs
+ */
+struct mmc_test_dbgfs_file {
+	struct list_head link;
+	struct mmc_card *card;
+	struct dentry *file;
+};
+
+/**
+ * struct mmc_test_card - test information.
+ * @card: card under test
+ * @scratch: transfer buffer
+ * @buffer: transfer buffer
+ * @highmem: buffer for highmem tests
+ * @area: information for performance tests
+ * @gr: pointer to results of current testcase
+ */
+struct mmc_test_card {
+	struct mmc_card	*card;
+
+	u8		scratch[BUFFER_SIZE];
+	u8		*buffer;
+#ifdef CONFIG_HIGHMEM
+	struct page	*highmem;
+#endif
+	struct mmc_test_area		area;
+	struct mmc_test_general_result	*gr;
+};
+
+enum mmc_test_prep_media {
+	MMC_TEST_PREP_NONE = 0,
+	MMC_TEST_PREP_WRITE_FULL = 1 << 0,
+	MMC_TEST_PREP_ERASE = 1 << 1,
+};
+
+struct mmc_test_multiple_rw {
+	unsigned int *sg_len;
+	unsigned int *bs;
+	unsigned int len;
+	unsigned int size;
+	bool do_write;
+	bool do_nonblock_req;
+	enum mmc_test_prep_media prepare;
+};
+
+struct mmc_test_async_req {
+	struct mmc_async_req areq;
+	struct mmc_test_card *test;
+};
+
+/*******************************************************************/
+/*  General helper functions                                       */
+/*******************************************************************/
+
+/*
+ * Configure correct block size in card
+ */
+static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size)
+{
+	return mmc_set_blocklen(test->card, size);
+}
+
+static bool mmc_test_card_cmd23(struct mmc_card *card)
+{
+	return mmc_card_mmc(card) ||
+	       (mmc_card_sd(card) && card->scr.cmds & SD_SCR_CMD23_SUPPORT);
+}
+
+static void mmc_test_prepare_sbc(struct mmc_test_card *test,
+				 struct mmc_request *mrq, unsigned int blocks)
+{
+	struct mmc_card *card = test->card;
+
+	if (!mrq->sbc || !mmc_host_cmd23(card->host) ||
+	    !mmc_test_card_cmd23(card) || !mmc_op_multi(mrq->cmd->opcode) ||
+	    (card->quirks & MMC_QUIRK_BLK_NO_CMD23)) {
+		mrq->sbc = NULL;
+		return;
+	}
+
+	mrq->sbc->opcode = MMC_SET_BLOCK_COUNT;
+	mrq->sbc->arg = blocks;
+	mrq->sbc->flags = MMC_RSP_R1 | MMC_CMD_AC;
+}
+
+/*
+ * Fill in the mmc_request structure given a set of transfer parameters.
+ */
+static void mmc_test_prepare_mrq(struct mmc_test_card *test,
+	struct mmc_request *mrq, struct scatterlist *sg, unsigned sg_len,
+	unsigned dev_addr, unsigned blocks, unsigned blksz, int write)
+{
+	if (WARN_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop))
+		return;
+
+	if (blocks > 1) {
+		mrq->cmd->opcode = write ?
+			MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
+	} else {
+		mrq->cmd->opcode = write ?
+			MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
+	}
+
+	mrq->cmd->arg = dev_addr;
+	if (!mmc_card_blockaddr(test->card))
+		mrq->cmd->arg <<= 9;
+
+	mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+	if (blocks == 1)
+		mrq->stop = NULL;
+	else {
+		mrq->stop->opcode = MMC_STOP_TRANSMISSION;
+		mrq->stop->arg = 0;
+		mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
+	}
+
+	mrq->data->blksz = blksz;
+	mrq->data->blocks = blocks;
+	mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
+	mrq->data->sg = sg;
+	mrq->data->sg_len = sg_len;
+
+	mmc_test_prepare_sbc(test, mrq, blocks);
+
+	mmc_set_data_timeout(mrq->data, test->card);
+}
+
+static int mmc_test_busy(struct mmc_command *cmd)
+{
+	return !(cmd->resp[0] & R1_READY_FOR_DATA) ||
+		(R1_CURRENT_STATE(cmd->resp[0]) == R1_STATE_PRG);
+}
+
+/*
+ * Wait for the card to finish the busy state
+ */
+static int mmc_test_wait_busy(struct mmc_test_card *test)
+{
+	int ret, busy;
+	struct mmc_command cmd = {0};
+
+	busy = 0;
+	do {
+		memset(&cmd, 0, sizeof(struct mmc_command));
+
+		cmd.opcode = MMC_SEND_STATUS;
+		cmd.arg = test->card->rca << 16;
+		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+
+		ret = mmc_wait_for_cmd(test->card->host, &cmd, 0);
+		if (ret)
+			break;
+
+		if (!busy && mmc_test_busy(&cmd)) {
+			busy = 1;
+			if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+				pr_info("%s: Warning: Host did not "
+					"wait for busy state to end.\n",
+					mmc_hostname(test->card->host));
+		}
+	} while (mmc_test_busy(&cmd));
+
+	return ret;
+}
+
+/*
+ * Transfer a single sector of kernel addressable data
+ */
+static int mmc_test_buffer_transfer(struct mmc_test_card *test,
+	u8 *buffer, unsigned addr, unsigned blksz, int write)
+{
+	struct mmc_request mrq = {0};
+	struct mmc_command cmd = {0};
+	struct mmc_command stop = {0};
+	struct mmc_data data = {0};
+
+	struct scatterlist sg;
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	mrq.stop = &stop;
+
+	sg_init_one(&sg, buffer, blksz);
+
+	mmc_test_prepare_mrq(test, &mrq, &sg, 1, addr, 1, blksz, write);
+
+	mmc_wait_for_req(test->card->host, &mrq);
+
+	if (cmd.error)
+		return cmd.error;
+	if (data.error)
+		return data.error;
+
+	return mmc_test_wait_busy(test);
+}
+
+static void mmc_test_free_mem(struct mmc_test_mem *mem)
+{
+	if (!mem)
+		return;
+	while (mem->cnt--)
+		__free_pages(mem->arr[mem->cnt].page,
+			     mem->arr[mem->cnt].order);
+	kfree(mem->arr);
+	kfree(mem);
+}
+
+/*
+ * Allocate a lot of memory, preferably max_sz but at least min_sz.  In case
+ * there isn't much memory do not exceed 1/16th total lowmem pages.  Also do
+ * not exceed a maximum number of segments and try not to make segments much
+ * bigger than maximum segment size.
+ */
+static struct mmc_test_mem *mmc_test_alloc_mem(unsigned long min_sz,
+					       unsigned long max_sz,
+					       unsigned int max_segs,
+					       unsigned int max_seg_sz)
+{
+	unsigned long max_page_cnt = DIV_ROUND_UP(max_sz, PAGE_SIZE);
+	unsigned long min_page_cnt = DIV_ROUND_UP(min_sz, PAGE_SIZE);
+	unsigned long max_seg_page_cnt = DIV_ROUND_UP(max_seg_sz, PAGE_SIZE);
+	unsigned long page_cnt = 0;
+	unsigned long limit = nr_free_buffer_pages() >> 4;
+	struct mmc_test_mem *mem;
+
+	if (max_page_cnt > limit)
+		max_page_cnt = limit;
+	if (min_page_cnt > max_page_cnt)
+		min_page_cnt = max_page_cnt;
+
+	if (max_seg_page_cnt > max_page_cnt)
+		max_seg_page_cnt = max_page_cnt;
+
+	if (max_segs > max_page_cnt)
+		max_segs = max_page_cnt;
+
+	mem = kzalloc(sizeof(struct mmc_test_mem), GFP_KERNEL);
+	if (!mem)
+		return NULL;
+
+	mem->arr = kzalloc(sizeof(struct mmc_test_pages) * max_segs,
+			   GFP_KERNEL);
+	if (!mem->arr)
+		goto out_free;
+
+	while (max_page_cnt) {
+		struct page *page;
+		unsigned int order;
+		gfp_t flags = GFP_KERNEL | GFP_DMA | __GFP_NOWARN |
+				__GFP_NORETRY;
+
+		order = get_order(max_seg_page_cnt << PAGE_SHIFT);
+		while (1) {
+			page = alloc_pages(flags, order);
+			if (page || !order)
+				break;
+			order -= 1;
+		}
+		if (!page) {
+			if (page_cnt < min_page_cnt)
+				goto out_free;
+			break;
+		}
+		mem->arr[mem->cnt].page = page;
+		mem->arr[mem->cnt].order = order;
+		mem->cnt += 1;
+		if (max_page_cnt <= (1UL << order))
+			break;
+		max_page_cnt -= 1UL << order;
+		page_cnt += 1UL << order;
+		if (mem->cnt >= max_segs) {
+			if (page_cnt < min_page_cnt)
+				goto out_free;
+			break;
+		}
+	}
+
+	return mem;
+
+out_free:
+	mmc_test_free_mem(mem);
+	return NULL;
+}
+
+/*
+ * Map memory into a scatterlist.  Optionally allow the same memory to be
+ * mapped more than once.
+ */
+static int mmc_test_map_sg(struct mmc_test_mem *mem, unsigned long size,
+			   struct scatterlist *sglist, int repeat,
+			   unsigned int max_segs, unsigned int max_seg_sz,
+			   unsigned int *sg_len, int min_sg_len)
+{
+	struct scatterlist *sg = NULL;
+	unsigned int i;
+	unsigned long sz = size;
+
+	sg_init_table(sglist, max_segs);
+	if (min_sg_len > max_segs)
+		min_sg_len = max_segs;
+
+	*sg_len = 0;
+	do {
+		for (i = 0; i < mem->cnt; i++) {
+			unsigned long len = PAGE_SIZE << mem->arr[i].order;
+
+			if (min_sg_len && (size / min_sg_len < len))
+				len = ALIGN(size / min_sg_len, 512);
+			if (len > sz)
+				len = sz;
+			if (len > max_seg_sz)
+				len = max_seg_sz;
+			if (sg)
+				sg = sg_next(sg);
+			else
+				sg = sglist;
+			if (!sg)
+				return -EINVAL;
+			sg_set_page(sg, mem->arr[i].page, len, 0);
+			sz -= len;
+			*sg_len += 1;
+			if (!sz)
+				break;
+		}
+	} while (sz && repeat);
+
+	if (sz)
+		return -EINVAL;
+
+	if (sg)
+		sg_mark_end(sg);
+
+	return 0;
+}
+
+/*
+ * Map memory into a scatterlist so that no pages are contiguous.  Allow the
+ * same memory to be mapped more than once.
+ */
+static int mmc_test_map_sg_max_scatter(struct mmc_test_mem *mem,
+				       unsigned long sz,
+				       struct scatterlist *sglist,
+				       unsigned int max_segs,
+				       unsigned int max_seg_sz,
+				       unsigned int *sg_len)
+{
+	struct scatterlist *sg = NULL;
+	unsigned int i = mem->cnt, cnt;
+	unsigned long len;
+	void *base, *addr, *last_addr = NULL;
+
+	sg_init_table(sglist, max_segs);
+
+	*sg_len = 0;
+	while (sz) {
+		base = page_address(mem->arr[--i].page);
+		cnt = 1 << mem->arr[i].order;
+		while (sz && cnt) {
+			addr = base + PAGE_SIZE * --cnt;
+			if (last_addr && last_addr + PAGE_SIZE == addr)
+				continue;
+			last_addr = addr;
+			len = PAGE_SIZE;
+			if (len > max_seg_sz)
+				len = max_seg_sz;
+			if (len > sz)
+				len = sz;
+			if (sg)
+				sg = sg_next(sg);
+			else
+				sg = sglist;
+			if (!sg)
+				return -EINVAL;
+			sg_set_page(sg, virt_to_page(addr), len, 0);
+			sz -= len;
+			*sg_len += 1;
+		}
+		if (i == 0)
+			i = mem->cnt;
+	}
+
+	if (sg)
+		sg_mark_end(sg);
+
+	return 0;
+}
+
+/*
+ * Calculate transfer rate in bytes per second.
+ */
+static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts)
+{
+	uint64_t ns;
+
+	ns = ts->tv_sec;
+	ns *= 1000000000;
+	ns += ts->tv_nsec;
+
+	bytes *= 1000000000;
+
+	while (ns > UINT_MAX) {
+		bytes >>= 1;
+		ns >>= 1;
+	}
+
+	if (!ns)
+		return 0;
+
+	do_div(bytes, (uint32_t)ns);
+
+	return bytes;
+}
+
+/*
+ * Save transfer results for future usage
+ */
+static void mmc_test_save_transfer_result(struct mmc_test_card *test,
+	unsigned int count, unsigned int sectors, struct timespec ts,
+	unsigned int rate, unsigned int iops)
+{
+	struct mmc_test_transfer_result *tr;
+
+	if (!test->gr)
+		return;
+
+	tr = kmalloc(sizeof(struct mmc_test_transfer_result), GFP_KERNEL);
+	if (!tr)
+		return;
+
+	tr->count = count;
+	tr->sectors = sectors;
+	tr->ts = ts;
+	tr->rate = rate;
+	tr->iops = iops;
+
+	list_add_tail(&tr->link, &test->gr->tr_lst);
+}
+
+/*
+ * Print the transfer rate.
+ */
+static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
+				struct timespec *ts1, struct timespec *ts2)
+{
+	unsigned int rate, iops, sectors = bytes >> 9;
+	struct timespec ts;
+
+	ts = timespec_sub(*ts2, *ts1);
+
+	rate = mmc_test_rate(bytes, &ts);
+	iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */
+
+	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,
+			 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024,
+			 iops / 100, iops % 100);
+
+	mmc_test_save_transfer_result(test, 1, sectors, ts, rate, iops);
+}
+
+/*
+ * Print the average transfer rate.
+ */
+static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
+				    unsigned int count, struct timespec *ts1,
+				    struct timespec *ts2)
+{
+	unsigned int rate, iops, sectors = bytes >> 9;
+	uint64_t tot = bytes * count;
+	struct timespec ts;
+
+	ts = timespec_sub(*ts2, *ts1);
+
+	rate = mmc_test_rate(tot, &ts);
+	iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
+
+	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,
+			 sectors >> 1, (sectors & 1 ? ".5" : ""),
+			 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
+			 rate / 1000, rate / 1024, iops / 100, iops % 100,
+			 test->area.sg_len);
+
+	mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
+}
+
+/*
+ * Return the card size in sectors.
+ */
+static unsigned int mmc_test_capacity(struct mmc_card *card)
+{
+	if (!mmc_card_sd(card) && mmc_card_blockaddr(card))
+		return card->ext_csd.sectors;
+	else
+		return card->csd.capacity << (card->csd.read_blkbits - 9);
+}
+
+/*******************************************************************/
+/*  Test preparation and cleanup                                   */
+/*******************************************************************/
+
+/*
+ * Fill the first couple of sectors of the card with known data
+ * so that bad reads/writes can be detected
+ */
+static int __mmc_test_prepare(struct mmc_test_card *test, int write)
+{
+	int ret, i;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	if (write)
+		memset(test->buffer, 0xDF, 512);
+	else {
+		for (i = 0;i < 512;i++)
+			test->buffer[i] = i;
+	}
+
+	for (i = 0;i < BUFFER_SIZE / 512;i++) {
+		ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_prepare_write(struct mmc_test_card *test)
+{
+	return __mmc_test_prepare(test, 1);
+}
+
+static int mmc_test_prepare_read(struct mmc_test_card *test)
+{
+	return __mmc_test_prepare(test, 0);
+}
+
+static int mmc_test_cleanup(struct mmc_test_card *test)
+{
+	int ret, i;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	memset(test->buffer, 0, 512);
+
+	for (i = 0;i < BUFFER_SIZE / 512;i++) {
+		ret = mmc_test_buffer_transfer(test, test->buffer, i, 512, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/*******************************************************************/
+/*  Test execution helpers                                         */
+/*******************************************************************/
+
+/*
+ * Modifies the mmc_request to perform the "short transfer" tests
+ */
+static void mmc_test_prepare_broken_mrq(struct mmc_test_card *test,
+	struct mmc_request *mrq, int write)
+{
+	if (WARN_ON(!mrq || !mrq->cmd || !mrq->data))
+		return;
+
+	if (mrq->data->blocks > 1) {
+		mrq->cmd->opcode = write ?
+			MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
+		mrq->stop = NULL;
+	} else {
+		mrq->cmd->opcode = MMC_SEND_STATUS;
+		mrq->cmd->arg = test->card->rca << 16;
+	}
+}
+
+/*
+ * Checks that a normal transfer didn't have any errors
+ */
+static int mmc_test_check_result(struct mmc_test_card *test,
+				 struct mmc_request *mrq)
+{
+	int ret;
+
+	if (WARN_ON(!mrq || !mrq->cmd || !mrq->data))
+		return -EINVAL;
+
+	ret = 0;
+
+	if (mrq->sbc && mrq->sbc->error)
+		ret = mrq->sbc->error;
+	if (!ret && mrq->cmd->error)
+		ret = mrq->cmd->error;
+	if (!ret && mrq->data->error)
+		ret = mrq->data->error;
+	if (!ret && mrq->stop && mrq->stop->error)
+		ret = mrq->stop->error;
+	if (!ret && mrq->data->bytes_xfered !=
+		mrq->data->blocks * mrq->data->blksz)
+		ret = RESULT_FAIL;
+
+	if (ret == -EINVAL)
+		ret = RESULT_UNSUP_HOST;
+
+	return ret;
+}
+
+static enum mmc_blk_status mmc_test_check_result_async(struct mmc_card *card,
+				       struct mmc_async_req *areq)
+{
+	struct mmc_test_async_req *test_async =
+		container_of(areq, struct mmc_test_async_req, areq);
+	int ret;
+
+	mmc_test_wait_busy(test_async->test);
+
+	/*
+	 * FIXME: this would earlier just casts a regular error code,
+	 * either of the kernel type -ERRORCODE or the local test framework
+	 * RESULT_* errorcode, into an enum mmc_blk_status and return as
+	 * result check. Instead, convert it to some reasonable type by just
+	 * returning either MMC_BLK_SUCCESS or MMC_BLK_CMD_ERR.
+	 * If possible, a reasonable error code should be returned.
+	 */
+	ret = mmc_test_check_result(test_async->test, areq->mrq);
+	if (ret)
+		return MMC_BLK_CMD_ERR;
+
+	return MMC_BLK_SUCCESS;
+}
+
+/*
+ * Checks that a "short transfer" behaved as expected
+ */
+static int mmc_test_check_broken_result(struct mmc_test_card *test,
+	struct mmc_request *mrq)
+{
+	int ret;
+
+	if (WARN_ON(!mrq || !mrq->cmd || !mrq->data))
+		return -EINVAL;
+
+	ret = 0;
+
+	if (!ret && mrq->cmd->error)
+		ret = mrq->cmd->error;
+	if (!ret && mrq->data->error == 0)
+		ret = RESULT_FAIL;
+	if (!ret && mrq->data->error != -ETIMEDOUT)
+		ret = mrq->data->error;
+	if (!ret && mrq->stop && mrq->stop->error)
+		ret = mrq->stop->error;
+	if (mrq->data->blocks > 1) {
+		if (!ret && mrq->data->bytes_xfered > mrq->data->blksz)
+			ret = RESULT_FAIL;
+	} else {
+		if (!ret && mrq->data->bytes_xfered > 0)
+			ret = RESULT_FAIL;
+	}
+
+	if (ret == -EINVAL)
+		ret = RESULT_UNSUP_HOST;
+
+	return ret;
+}
+
+/*
+ * Tests nonblock transfer with certain parameters
+ */
+static void mmc_test_nonblock_reset(struct mmc_request *mrq,
+				    struct mmc_command *cmd,
+				    struct mmc_command *stop,
+				    struct mmc_data *data)
+{
+	memset(mrq, 0, sizeof(struct mmc_request));
+	memset(cmd, 0, sizeof(struct mmc_command));
+	memset(data, 0, sizeof(struct mmc_data));
+	memset(stop, 0, sizeof(struct mmc_command));
+
+	mrq->cmd = cmd;
+	mrq->data = data;
+	mrq->stop = stop;
+}
+static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
+				      struct scatterlist *sg, unsigned sg_len,
+				      unsigned dev_addr, unsigned blocks,
+				      unsigned blksz, int write, int count)
+{
+	struct mmc_request mrq1;
+	struct mmc_command cmd1;
+	struct mmc_command stop1;
+	struct mmc_data data1;
+
+	struct mmc_request mrq2;
+	struct mmc_command cmd2;
+	struct mmc_command stop2;
+	struct mmc_data data2;
+
+	struct mmc_test_async_req test_areq[2];
+	struct mmc_async_req *done_areq;
+	struct mmc_async_req *cur_areq = &test_areq[0].areq;
+	struct mmc_async_req *other_areq = &test_areq[1].areq;
+	enum mmc_blk_status status;
+	int i;
+	int ret = RESULT_OK;
+
+	test_areq[0].test = test;
+	test_areq[1].test = test;
+
+	mmc_test_nonblock_reset(&mrq1, &cmd1, &stop1, &data1);
+	mmc_test_nonblock_reset(&mrq2, &cmd2, &stop2, &data2);
+
+	cur_areq->mrq = &mrq1;
+	cur_areq->err_check = mmc_test_check_result_async;
+	other_areq->mrq = &mrq2;
+	other_areq->err_check = mmc_test_check_result_async;
+
+	for (i = 0; i < count; i++) {
+		mmc_test_prepare_mrq(test, cur_areq->mrq, sg, sg_len, dev_addr,
+				     blocks, blksz, write);
+		done_areq = mmc_start_req(test->card->host, cur_areq, &status);
+
+		if (status != MMC_BLK_SUCCESS || (!done_areq && i > 0)) {
+			ret = RESULT_FAIL;
+			goto err;
+		}
+
+		if (done_areq) {
+			if (done_areq->mrq == &mrq2)
+				mmc_test_nonblock_reset(&mrq2, &cmd2,
+							&stop2, &data2);
+			else
+				mmc_test_nonblock_reset(&mrq1, &cmd1,
+							&stop1, &data1);
+		}
+		swap(cur_areq, other_areq);
+		dev_addr += blocks;
+	}
+
+	done_areq = mmc_start_req(test->card->host, NULL, &status);
+	if (status != MMC_BLK_SUCCESS)
+		ret = RESULT_FAIL;
+
+	return ret;
+err:
+	return ret;
+}
+
+/*
+ * Tests a basic transfer with certain parameters
+ */
+static int mmc_test_simple_transfer(struct mmc_test_card *test,
+	struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
+	unsigned blocks, unsigned blksz, int write)
+{
+	struct mmc_request mrq = {0};
+	struct mmc_command cmd = {0};
+	struct mmc_command stop = {0};
+	struct mmc_data data = {0};
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	mrq.stop = &stop;
+
+	mmc_test_prepare_mrq(test, &mrq, sg, sg_len, dev_addr,
+		blocks, blksz, write);
+
+	mmc_wait_for_req(test->card->host, &mrq);
+
+	mmc_test_wait_busy(test);
+
+	return mmc_test_check_result(test, &mrq);
+}
+
+/*
+ * Tests a transfer where the card will fail completely or partly
+ */
+static int mmc_test_broken_transfer(struct mmc_test_card *test,
+	unsigned blocks, unsigned blksz, int write)
+{
+	struct mmc_request mrq = {0};
+	struct mmc_command cmd = {0};
+	struct mmc_command stop = {0};
+	struct mmc_data data = {0};
+
+	struct scatterlist sg;
+
+	mrq.cmd = &cmd;
+	mrq.data = &data;
+	mrq.stop = &stop;
+
+	sg_init_one(&sg, test->buffer, blocks * blksz);
+
+	mmc_test_prepare_mrq(test, &mrq, &sg, 1, 0, blocks, blksz, write);
+	mmc_test_prepare_broken_mrq(test, &mrq, write);
+
+	mmc_wait_for_req(test->card->host, &mrq);
+
+	mmc_test_wait_busy(test);
+
+	return mmc_test_check_broken_result(test, &mrq);
+}
+
+/*
+ * Does a complete transfer test where data is also validated
+ *
+ * Note: mmc_test_prepare() must have been done before this call
+ */
+static int mmc_test_transfer(struct mmc_test_card *test,
+	struct scatterlist *sg, unsigned sg_len, unsigned dev_addr,
+	unsigned blocks, unsigned blksz, int write)
+{
+	int ret, i;
+	unsigned long flags;
+
+	if (write) {
+		for (i = 0;i < blocks * blksz;i++)
+			test->scratch[i] = i;
+	} else {
+		memset(test->scratch, 0, BUFFER_SIZE);
+	}
+	local_irq_save(flags);
+	sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+	local_irq_restore(flags);
+
+	ret = mmc_test_set_blksize(test, blksz);
+	if (ret)
+		return ret;
+
+	ret = mmc_test_simple_transfer(test, sg, sg_len, dev_addr,
+		blocks, blksz, write);
+	if (ret)
+		return ret;
+
+	if (write) {
+		int sectors;
+
+		ret = mmc_test_set_blksize(test, 512);
+		if (ret)
+			return ret;
+
+		sectors = (blocks * blksz + 511) / 512;
+		if ((sectors * 512) == (blocks * blksz))
+			sectors++;
+
+		if ((sectors * 512) > BUFFER_SIZE)
+			return -EINVAL;
+
+		memset(test->buffer, 0, sectors * 512);
+
+		for (i = 0;i < sectors;i++) {
+			ret = mmc_test_buffer_transfer(test,
+				test->buffer + i * 512,
+				dev_addr + i, 512, 0);
+			if (ret)
+				return ret;
+		}
+
+		for (i = 0;i < blocks * blksz;i++) {
+			if (test->buffer[i] != (u8)i)
+				return RESULT_FAIL;
+		}
+
+		for (;i < sectors * 512;i++) {
+			if (test->buffer[i] != 0xDF)
+				return RESULT_FAIL;
+		}
+	} else {
+		local_irq_save(flags);
+		sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE);
+		local_irq_restore(flags);
+		for (i = 0;i < blocks * blksz;i++) {
+			if (test->scratch[i] != (u8)i)
+				return RESULT_FAIL;
+		}
+	}
+
+	return 0;
+}
+
+/*******************************************************************/
+/*  Tests                                                          */
+/*******************************************************************/
+
+struct mmc_test_case {
+	const char *name;
+
+	int (*prepare)(struct mmc_test_card *);
+	int (*run)(struct mmc_test_card *);
+	int (*cleanup)(struct mmc_test_card *);
+};
+
+static int mmc_test_basic_write(struct mmc_test_card *test)
+{
+	int ret;
+	struct scatterlist sg;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	sg_init_one(&sg, test->buffer, 512);
+
+	return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
+}
+
+static int mmc_test_basic_read(struct mmc_test_card *test)
+{
+	int ret;
+	struct scatterlist sg;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	sg_init_one(&sg, test->buffer, 512);
+
+	return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
+}
+
+static int mmc_test_verify_write(struct mmc_test_card *test)
+{
+	struct scatterlist sg;
+
+	sg_init_one(&sg, test->buffer, 512);
+
+	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
+}
+
+static int mmc_test_verify_read(struct mmc_test_card *test)
+{
+	struct scatterlist sg;
+
+	sg_init_one(&sg, test->buffer, 512);
+
+	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
+}
+
+static int mmc_test_multi_write(struct mmc_test_card *test)
+{
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	sg_init_one(&sg, test->buffer, size);
+
+	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+}
+
+static int mmc_test_multi_read(struct mmc_test_card *test)
+{
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	sg_init_one(&sg, test->buffer, size);
+
+	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+}
+
+static int mmc_test_pow2_write(struct mmc_test_card *test)
+{
+	int ret, i;
+	struct scatterlist sg;
+
+	if (!test->card->csd.write_partial)
+		return RESULT_UNSUP_CARD;
+
+	for (i = 1; i < 512;i <<= 1) {
+		sg_init_one(&sg, test->buffer, i);
+		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_pow2_read(struct mmc_test_card *test)
+{
+	int ret, i;
+	struct scatterlist sg;
+
+	if (!test->card->csd.read_partial)
+		return RESULT_UNSUP_CARD;
+
+	for (i = 1; i < 512;i <<= 1) {
+		sg_init_one(&sg, test->buffer, i);
+		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_weird_write(struct mmc_test_card *test)
+{
+	int ret, i;
+	struct scatterlist sg;
+
+	if (!test->card->csd.write_partial)
+		return RESULT_UNSUP_CARD;
+
+	for (i = 3; i < 512;i += 7) {
+		sg_init_one(&sg, test->buffer, i);
+		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_weird_read(struct mmc_test_card *test)
+{
+	int ret, i;
+	struct scatterlist sg;
+
+	if (!test->card->csd.read_partial)
+		return RESULT_UNSUP_CARD;
+
+	for (i = 3; i < 512;i += 7) {
+		sg_init_one(&sg, test->buffer, i);
+		ret = mmc_test_transfer(test, &sg, 1, 0, 1, i, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_align_write(struct mmc_test_card *test)
+{
+	int ret, i;
+	struct scatterlist sg;
+
+	for (i = 1; i < TEST_ALIGN_END; i++) {
+		sg_init_one(&sg, test->buffer + i, 512);
+		ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_align_read(struct mmc_test_card *test)
+{
+	int ret, i;
+	struct scatterlist sg;
+
+	for (i = 1; i < TEST_ALIGN_END; i++) {
+		sg_init_one(&sg, test->buffer + i, 512);
+		ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_align_multi_write(struct mmc_test_card *test)
+{
+	int ret, i;
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	for (i = 1; i < TEST_ALIGN_END; i++) {
+		sg_init_one(&sg, test->buffer + i, size);
+		ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_align_multi_read(struct mmc_test_card *test)
+{
+	int ret, i;
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	for (i = 1; i < TEST_ALIGN_END; i++) {
+		sg_init_one(&sg, test->buffer + i, size);
+		ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mmc_test_xfersize_write(struct mmc_test_card *test)
+{
+	int ret;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	return mmc_test_broken_transfer(test, 1, 512, 1);
+}
+
+static int mmc_test_xfersize_read(struct mmc_test_card *test)
+{
+	int ret;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	return mmc_test_broken_transfer(test, 1, 512, 0);
+}
+
+static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
+{
+	int ret;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	return mmc_test_broken_transfer(test, 2, 512, 1);
+}
+
+static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
+{
+	int ret;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	return mmc_test_broken_transfer(test, 2, 512, 0);
+}
+
+#ifdef CONFIG_HIGHMEM
+
+static int mmc_test_write_high(struct mmc_test_card *test)
+{
+	struct scatterlist sg;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, 512, 0);
+
+	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
+}
+
+static int mmc_test_read_high(struct mmc_test_card *test)
+{
+	struct scatterlist sg;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, 512, 0);
+
+	return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
+}
+
+static int mmc_test_multi_write_high(struct mmc_test_card *test)
+{
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, size, 0);
+
+	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
+}
+
+static int mmc_test_multi_read_high(struct mmc_test_card *test)
+{
+	unsigned int size;
+	struct scatterlist sg;
+
+	if (test->card->host->max_blk_count == 1)
+		return RESULT_UNSUP_HOST;
+
+	size = PAGE_SIZE * 2;
+	size = min(size, test->card->host->max_req_size);
+	size = min(size, test->card->host->max_seg_size);
+	size = min(size, test->card->host->max_blk_count * 512);
+
+	if (size < 1024)
+		return RESULT_UNSUP_HOST;
+
+	sg_init_table(&sg, 1);
+	sg_set_page(&sg, test->highmem, size, 0);
+
+	return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
+}
+
+#else
+
+static int mmc_test_no_highmem(struct mmc_test_card *test)
+{
+	pr_info("%s: Highmem not configured - test skipped\n",
+	       mmc_hostname(test->card->host));
+	return 0;
+}
+
+#endif /* CONFIG_HIGHMEM */
+
+/*
+ * Map sz bytes so that it can be transferred.
+ */
+static int mmc_test_area_map(struct mmc_test_card *test, unsigned long sz,
+			     int max_scatter, int min_sg_len)
+{
+	struct mmc_test_area *t = &test->area;
+	int err;
+
+	t->blocks = sz >> 9;
+
+	if (max_scatter) {
+		err = mmc_test_map_sg_max_scatter(t->mem, sz, t->sg,
+						  t->max_segs, t->max_seg_sz,
+				       &t->sg_len);
+	} else {
+		err = mmc_test_map_sg(t->mem, sz, t->sg, 1, t->max_segs,
+				      t->max_seg_sz, &t->sg_len, min_sg_len);
+	}
+	if (err)
+		pr_info("%s: Failed to map sg list\n",
+		       mmc_hostname(test->card->host));
+	return err;
+}
+
+/*
+ * Transfer bytes mapped by mmc_test_area_map().
+ */
+static int mmc_test_area_transfer(struct mmc_test_card *test,
+				  unsigned int dev_addr, int write)
+{
+	struct mmc_test_area *t = &test->area;
+
+	return mmc_test_simple_transfer(test, t->sg, t->sg_len, dev_addr,
+					t->blocks, 512, write);
+}
+
+/*
+ * Map and transfer bytes for multiple transfers.
+ */
+static int mmc_test_area_io_seq(struct mmc_test_card *test, unsigned long sz,
+				unsigned int dev_addr, int write,
+				int max_scatter, int timed, int count,
+				bool nonblock, int min_sg_len)
+{
+	struct timespec ts1, ts2;
+	int ret = 0;
+	int i;
+	struct mmc_test_area *t = &test->area;
+
+	/*
+	 * In the case of a maximally scattered transfer, the maximum transfer
+	 * size is further limited by using PAGE_SIZE segments.
+	 */
+	if (max_scatter) {
+		struct mmc_test_area *t = &test->area;
+		unsigned long max_tfr;
+
+		if (t->max_seg_sz >= PAGE_SIZE)
+			max_tfr = t->max_segs * PAGE_SIZE;
+		else
+			max_tfr = t->max_segs * t->max_seg_sz;
+		if (sz > max_tfr)
+			sz = max_tfr;
+	}
+
+	ret = mmc_test_area_map(test, sz, max_scatter, min_sg_len);
+	if (ret)
+		return ret;
+
+	if (timed)
+		getnstimeofday(&ts1);
+	if (nonblock)
+		ret = mmc_test_nonblock_transfer(test, t->sg, t->sg_len,
+				 dev_addr, t->blocks, 512, write, count);
+	else
+		for (i = 0; i < count && ret == 0; i++) {
+			ret = mmc_test_area_transfer(test, dev_addr, write);
+			dev_addr += sz >> 9;
+		}
+
+	if (ret)
+		return ret;
+
+	if (timed)
+		getnstimeofday(&ts2);
+
+	if (timed)
+		mmc_test_print_avg_rate(test, sz, count, &ts1, &ts2);
+
+	return 0;
+}
+
+static int mmc_test_area_io(struct mmc_test_card *test, unsigned long sz,
+			    unsigned int dev_addr, int write, int max_scatter,
+			    int timed)
+{
+	return mmc_test_area_io_seq(test, sz, dev_addr, write, max_scatter,
+				    timed, 1, false, 0);
+}
+
+/*
+ * Write the test area entirely.
+ */
+static int mmc_test_area_fill(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+
+	return mmc_test_area_io(test, t->max_tfr, t->dev_addr, 1, 0, 0);
+}
+
+/*
+ * Erase the test area entirely.
+ */
+static int mmc_test_area_erase(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+
+	if (!mmc_can_erase(test->card))
+		return 0;
+
+	return mmc_erase(test->card, t->dev_addr, t->max_sz >> 9,
+			 MMC_ERASE_ARG);
+}
+
+/*
+ * Cleanup struct mmc_test_area.
+ */
+static int mmc_test_area_cleanup(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+
+	kfree(t->sg);
+	mmc_test_free_mem(t->mem);
+
+	return 0;
+}
+
+/*
+ * Initialize an area for testing large transfers.  The test area is set to the
+ * middle of the card because cards may have different charateristics at the
+ * front (for FAT file system optimization).  Optionally, the area is erased
+ * (if the card supports it) which may improve write performance.  Optionally,
+ * the area is filled with data for subsequent read tests.
+ */
+static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long min_sz = 64 * 1024, sz;
+	int ret;
+
+	ret = mmc_test_set_blksize(test, 512);
+	if (ret)
+		return ret;
+
+	/* Make the test area size about 4MiB */
+	sz = (unsigned long)test->card->pref_erase << 9;
+	t->max_sz = sz;
+	while (t->max_sz < 4 * 1024 * 1024)
+		t->max_sz += sz;
+	while (t->max_sz > TEST_AREA_MAX_SIZE && t->max_sz > sz)
+		t->max_sz -= sz;
+
+	t->max_segs = test->card->host->max_segs;
+	t->max_seg_sz = test->card->host->max_seg_size;
+	t->max_seg_sz -= t->max_seg_sz % 512;
+
+	t->max_tfr = t->max_sz;
+	if (t->max_tfr >> 9 > test->card->host->max_blk_count)
+		t->max_tfr = test->card->host->max_blk_count << 9;
+	if (t->max_tfr > test->card->host->max_req_size)
+		t->max_tfr = test->card->host->max_req_size;
+	if (t->max_tfr / t->max_seg_sz > t->max_segs)
+		t->max_tfr = t->max_segs * t->max_seg_sz;
+
+	/*
+	 * Try to allocate enough memory for a max. sized transfer.  Less is OK
+	 * because the same memory can be mapped into the scatterlist more than
+	 * once.  Also, take into account the limits imposed on scatterlist
+	 * segments by the host driver.
+	 */
+	t->mem = mmc_test_alloc_mem(min_sz, t->max_tfr, t->max_segs,
+				    t->max_seg_sz);
+	if (!t->mem)
+		return -ENOMEM;
+
+	t->sg = kmalloc(sizeof(struct scatterlist) * t->max_segs, GFP_KERNEL);
+	if (!t->sg) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	t->dev_addr = mmc_test_capacity(test->card) / 2;
+	t->dev_addr -= t->dev_addr % (t->max_sz >> 9);
+
+	if (erase) {
+		ret = mmc_test_area_erase(test);
+		if (ret)
+			goto out_free;
+	}
+
+	if (fill) {
+		ret = mmc_test_area_fill(test);
+		if (ret)
+			goto out_free;
+	}
+
+	return 0;
+
+out_free:
+	mmc_test_area_cleanup(test);
+	return ret;
+}
+
+/*
+ * Prepare for large transfers.  Do not erase the test area.
+ */
+static int mmc_test_area_prepare(struct mmc_test_card *test)
+{
+	return mmc_test_area_init(test, 0, 0);
+}
+
+/*
+ * Prepare for large transfers.  Do erase the test area.
+ */
+static int mmc_test_area_prepare_erase(struct mmc_test_card *test)
+{
+	return mmc_test_area_init(test, 1, 0);
+}
+
+/*
+ * Prepare for large transfers.  Erase and fill the test area.
+ */
+static int mmc_test_area_prepare_fill(struct mmc_test_card *test)
+{
+	return mmc_test_area_init(test, 1, 1);
+}
+
+/*
+ * Test best-case performance.  Best-case performance is expected from
+ * a single large transfer.
+ *
+ * An additional option (max_scatter) allows the measurement of the same
+ * transfer but with no contiguous pages in the scatter list.  This tests
+ * the efficiency of DMA to handle scattered pages.
+ */
+static int mmc_test_best_performance(struct mmc_test_card *test, int write,
+				     int max_scatter)
+{
+	struct mmc_test_area *t = &test->area;
+
+	return mmc_test_area_io(test, t->max_tfr, t->dev_addr, write,
+				max_scatter, 1);
+}
+
+/*
+ * Best-case read performance.
+ */
+static int mmc_test_best_read_performance(struct mmc_test_card *test)
+{
+	return mmc_test_best_performance(test, 0, 0);
+}
+
+/*
+ * Best-case write performance.
+ */
+static int mmc_test_best_write_performance(struct mmc_test_card *test)
+{
+	return mmc_test_best_performance(test, 1, 0);
+}
+
+/*
+ * Best-case read performance into scattered pages.
+ */
+static int mmc_test_best_read_perf_max_scatter(struct mmc_test_card *test)
+{
+	return mmc_test_best_performance(test, 0, 1);
+}
+
+/*
+ * Best-case write performance from scattered pages.
+ */
+static int mmc_test_best_write_perf_max_scatter(struct mmc_test_card *test)
+{
+	return mmc_test_best_performance(test, 1, 1);
+}
+
+/*
+ * Single read performance by transfer size.
+ */
+static int mmc_test_profile_read_perf(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long sz;
+	unsigned int dev_addr;
+	int ret;
+
+	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
+		dev_addr = t->dev_addr + (sz >> 9);
+		ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 1);
+		if (ret)
+			return ret;
+	}
+	sz = t->max_tfr;
+	dev_addr = t->dev_addr;
+	return mmc_test_area_io(test, sz, dev_addr, 0, 0, 1);
+}
+
+/*
+ * Single write performance by transfer size.
+ */
+static int mmc_test_profile_write_perf(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long sz;
+	unsigned int dev_addr;
+	int ret;
+
+	ret = mmc_test_area_erase(test);
+	if (ret)
+		return ret;
+	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
+		dev_addr = t->dev_addr + (sz >> 9);
+		ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 1);
+		if (ret)
+			return ret;
+	}
+	ret = mmc_test_area_erase(test);
+	if (ret)
+		return ret;
+	sz = t->max_tfr;
+	dev_addr = t->dev_addr;
+	return mmc_test_area_io(test, sz, dev_addr, 1, 0, 1);
+}
+
+/*
+ * Single trim performance by transfer size.
+ */
+static int mmc_test_profile_trim_perf(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long sz;
+	unsigned int dev_addr;
+	struct timespec ts1, ts2;
+	int ret;
+
+	if (!mmc_can_trim(test->card))
+		return RESULT_UNSUP_CARD;
+
+	if (!mmc_can_erase(test->card))
+		return RESULT_UNSUP_HOST;
+
+	for (sz = 512; sz < t->max_sz; sz <<= 1) {
+		dev_addr = t->dev_addr + (sz >> 9);
+		getnstimeofday(&ts1);
+		ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG);
+		if (ret)
+			return ret;
+		getnstimeofday(&ts2);
+		mmc_test_print_rate(test, sz, &ts1, &ts2);
+	}
+	dev_addr = t->dev_addr;
+	getnstimeofday(&ts1);
+	ret = mmc_erase(test->card, dev_addr, sz >> 9, MMC_TRIM_ARG);
+	if (ret)
+		return ret;
+	getnstimeofday(&ts2);
+	mmc_test_print_rate(test, sz, &ts1, &ts2);
+	return 0;
+}
+
+static int mmc_test_seq_read_perf(struct mmc_test_card *test, unsigned long sz)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned int dev_addr, i, cnt;
+	struct timespec ts1, ts2;
+	int ret;
+
+	cnt = t->max_sz / sz;
+	dev_addr = t->dev_addr;
+	getnstimeofday(&ts1);
+	for (i = 0; i < cnt; i++) {
+		ret = mmc_test_area_io(test, sz, dev_addr, 0, 0, 0);
+		if (ret)
+			return ret;
+		dev_addr += (sz >> 9);
+	}
+	getnstimeofday(&ts2);
+	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+	return 0;
+}
+
+/*
+ * Consecutive read performance by transfer size.
+ */
+static int mmc_test_profile_seq_read_perf(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long sz;
+	int ret;
+
+	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
+		ret = mmc_test_seq_read_perf(test, sz);
+		if (ret)
+			return ret;
+	}
+	sz = t->max_tfr;
+	return mmc_test_seq_read_perf(test, sz);
+}
+
+static int mmc_test_seq_write_perf(struct mmc_test_card *test, unsigned long sz)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned int dev_addr, i, cnt;
+	struct timespec ts1, ts2;
+	int ret;
+
+	ret = mmc_test_area_erase(test);
+	if (ret)
+		return ret;
+	cnt = t->max_sz / sz;
+	dev_addr = t->dev_addr;
+	getnstimeofday(&ts1);
+	for (i = 0; i < cnt; i++) {
+		ret = mmc_test_area_io(test, sz, dev_addr, 1, 0, 0);
+		if (ret)
+			return ret;
+		dev_addr += (sz >> 9);
+	}
+	getnstimeofday(&ts2);
+	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+	return 0;
+}
+
+/*
+ * Consecutive write performance by transfer size.
+ */
+static int mmc_test_profile_seq_write_perf(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long sz;
+	int ret;
+
+	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
+		ret = mmc_test_seq_write_perf(test, sz);
+		if (ret)
+			return ret;
+	}
+	sz = t->max_tfr;
+	return mmc_test_seq_write_perf(test, sz);
+}
+
+/*
+ * Consecutive trim performance by transfer size.
+ */
+static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long sz;
+	unsigned int dev_addr, i, cnt;
+	struct timespec ts1, ts2;
+	int ret;
+
+	if (!mmc_can_trim(test->card))
+		return RESULT_UNSUP_CARD;
+
+	if (!mmc_can_erase(test->card))
+		return RESULT_UNSUP_HOST;
+
+	for (sz = 512; sz <= t->max_sz; sz <<= 1) {
+		ret = mmc_test_area_erase(test);
+		if (ret)
+			return ret;
+		ret = mmc_test_area_fill(test);
+		if (ret)
+			return ret;
+		cnt = t->max_sz / sz;
+		dev_addr = t->dev_addr;
+		getnstimeofday(&ts1);
+		for (i = 0; i < cnt; i++) {
+			ret = mmc_erase(test->card, dev_addr, sz >> 9,
+					MMC_TRIM_ARG);
+			if (ret)
+				return ret;
+			dev_addr += (sz >> 9);
+		}
+		getnstimeofday(&ts2);
+		mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+	}
+	return 0;
+}
+
+static unsigned int rnd_next = 1;
+
+static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
+{
+	uint64_t r;
+
+	rnd_next = rnd_next * 1103515245 + 12345;
+	r = (rnd_next >> 16) & 0x7fff;
+	return (r * rnd_cnt) >> 15;
+}
+
+static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
+			     unsigned long sz)
+{
+	unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
+	unsigned int ssz;
+	struct timespec ts1, ts2, ts;
+	int ret;
+
+	ssz = sz >> 9;
+
+	rnd_addr = mmc_test_capacity(test->card) / 4;
+	range1 = rnd_addr / test->card->pref_erase;
+	range2 = range1 / ssz;
+
+	getnstimeofday(&ts1);
+	for (cnt = 0; cnt < UINT_MAX; cnt++) {
+		getnstimeofday(&ts2);
+		ts = timespec_sub(ts2, ts1);
+		if (ts.tv_sec >= 10)
+			break;
+		ea = mmc_test_rnd_num(range1);
+		if (ea == last_ea)
+			ea -= 1;
+		last_ea = ea;
+		dev_addr = rnd_addr + test->card->pref_erase * ea +
+			   ssz * mmc_test_rnd_num(range2);
+		ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
+		if (ret)
+			return ret;
+	}
+	if (print)
+		mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+	return 0;
+}
+
+static int mmc_test_random_perf(struct mmc_test_card *test, int write)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned int next;
+	unsigned long sz;
+	int ret;
+
+	for (sz = 512; sz < t->max_tfr; sz <<= 1) {
+		/*
+		 * When writing, try to get more consistent results by running
+		 * the test twice with exactly the same I/O but outputting the
+		 * results only for the 2nd run.
+		 */
+		if (write) {
+			next = rnd_next;
+			ret = mmc_test_rnd_perf(test, write, 0, sz);
+			if (ret)
+				return ret;
+			rnd_next = next;
+		}
+		ret = mmc_test_rnd_perf(test, write, 1, sz);
+		if (ret)
+			return ret;
+	}
+	sz = t->max_tfr;
+	if (write) {
+		next = rnd_next;
+		ret = mmc_test_rnd_perf(test, write, 0, sz);
+		if (ret)
+			return ret;
+		rnd_next = next;
+	}
+	return mmc_test_rnd_perf(test, write, 1, sz);
+}
+
+/*
+ * Random read performance by transfer size.
+ */
+static int mmc_test_random_read_perf(struct mmc_test_card *test)
+{
+	return mmc_test_random_perf(test, 0);
+}
+
+/*
+ * Random write performance by transfer size.
+ */
+static int mmc_test_random_write_perf(struct mmc_test_card *test)
+{
+	return mmc_test_random_perf(test, 1);
+}
+
+static int mmc_test_seq_perf(struct mmc_test_card *test, int write,
+			     unsigned int tot_sz, int max_scatter)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned int dev_addr, i, cnt, sz, ssz;
+	struct timespec ts1, ts2;
+	int ret;
+
+	sz = t->max_tfr;
+
+	/*
+	 * In the case of a maximally scattered transfer, the maximum transfer
+	 * size is further limited by using PAGE_SIZE segments.
+	 */
+	if (max_scatter) {
+		unsigned long max_tfr;
+
+		if (t->max_seg_sz >= PAGE_SIZE)
+			max_tfr = t->max_segs * PAGE_SIZE;
+		else
+			max_tfr = t->max_segs * t->max_seg_sz;
+		if (sz > max_tfr)
+			sz = max_tfr;
+	}
+
+	ssz = sz >> 9;
+	dev_addr = mmc_test_capacity(test->card) / 4;
+	if (tot_sz > dev_addr << 9)
+		tot_sz = dev_addr << 9;
+	cnt = tot_sz / sz;
+	dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
+
+	getnstimeofday(&ts1);
+	for (i = 0; i < cnt; i++) {
+		ret = mmc_test_area_io(test, sz, dev_addr, write,
+				       max_scatter, 0);
+		if (ret)
+			return ret;
+		dev_addr += ssz;
+	}
+	getnstimeofday(&ts2);
+
+	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+
+	return 0;
+}
+
+static int mmc_test_large_seq_perf(struct mmc_test_card *test, int write)
+{
+	int ret, i;
+
+	for (i = 0; i < 10; i++) {
+		ret = mmc_test_seq_perf(test, write, 10 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < 5; i++) {
+		ret = mmc_test_seq_perf(test, write, 100 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < 3; i++) {
+		ret = mmc_test_seq_perf(test, write, 1000 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+/*
+ * Large sequential read performance.
+ */
+static int mmc_test_large_seq_read_perf(struct mmc_test_card *test)
+{
+	return mmc_test_large_seq_perf(test, 0);
+}
+
+/*
+ * Large sequential write performance.
+ */
+static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
+{
+	return mmc_test_large_seq_perf(test, 1);
+}
+
+static int mmc_test_rw_multiple(struct mmc_test_card *test,
+				struct mmc_test_multiple_rw *tdata,
+				unsigned int reqsize, unsigned int size,
+				int min_sg_len)
+{
+	unsigned int dev_addr;
+	struct mmc_test_area *t = &test->area;
+	int ret = 0;
+
+	/* Set up test area */
+	if (size > mmc_test_capacity(test->card) / 2 * 512)
+		size = mmc_test_capacity(test->card) / 2 * 512;
+	if (reqsize > t->max_tfr)
+		reqsize = t->max_tfr;
+	dev_addr = mmc_test_capacity(test->card) / 4;
+	if ((dev_addr & 0xffff0000))
+		dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
+	else
+		dev_addr &= 0xfffff800; /* Round to 1MiB boundary */
+	if (!dev_addr)
+		goto err;
+
+	if (reqsize > size)
+		return 0;
+
+	/* prepare test area */
+	if (mmc_can_erase(test->card) &&
+	    tdata->prepare & MMC_TEST_PREP_ERASE) {
+		ret = mmc_erase(test->card, dev_addr,
+				size / 512, MMC_SECURE_ERASE_ARG);
+		if (ret)
+			ret = mmc_erase(test->card, dev_addr,
+					size / 512, MMC_ERASE_ARG);
+		if (ret)
+			goto err;
+	}
+
+	/* Run test */
+	ret = mmc_test_area_io_seq(test, reqsize, dev_addr,
+				   tdata->do_write, 0, 1, size / reqsize,
+				   tdata->do_nonblock_req, min_sg_len);
+	if (ret)
+		goto err;
+
+	return ret;
+ err:
+	pr_info("[%s] error\n", __func__);
+	return ret;
+}
+
+static int mmc_test_rw_multiple_size(struct mmc_test_card *test,
+				     struct mmc_test_multiple_rw *rw)
+{
+	int ret = 0;
+	int i;
+	void *pre_req = test->card->host->ops->pre_req;
+	void *post_req = test->card->host->ops->post_req;
+
+	if (rw->do_nonblock_req &&
+	    ((!pre_req && post_req) || (pre_req && !post_req))) {
+		pr_info("error: only one of pre/post is defined\n");
+		return -EINVAL;
+	}
+
+	for (i = 0 ; i < rw->len && ret == 0; i++) {
+		ret = mmc_test_rw_multiple(test, rw, rw->bs[i], rw->size, 0);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+static int mmc_test_rw_multiple_sg_len(struct mmc_test_card *test,
+				       struct mmc_test_multiple_rw *rw)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0 ; i < rw->len && ret == 0; i++) {
+		ret = mmc_test_rw_multiple(test, rw, 512*1024, rw->size,
+					   rw->sg_len[i]);
+		if (ret)
+			break;
+	}
+	return ret;
+}
+
+/*
+ * Multiple blocking write 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_write_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = true,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+};
+
+/*
+ * Multiple non-blocking write 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_write_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = true,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple blocking read 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_read_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = false,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple non-blocking read 4k to 4 MB chunks
+ */
+static int mmc_test_profile_mult_read_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int bs[] = {1 << 12, 1 << 13, 1 << 14, 1 << 15, 1 << 16,
+			     1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 22};
+	struct mmc_test_multiple_rw test_data = {
+		.bs = bs,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(bs),
+		.do_write = false,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_size(test, &test_data);
+}
+
+/*
+ * Multiple blocking write 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_wr_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = true,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+};
+
+/*
+ * Multiple non-blocking write 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_wr_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = true,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_ERASE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
+/*
+ * Multiple blocking read 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_r_blocking_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = false,
+		.do_nonblock_req = false,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
+/*
+ * Multiple non-blocking read 1 to 512 sg elements
+ */
+static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
+{
+	unsigned int sg_len[] = {1, 1 << 3, 1 << 4, 1 << 5, 1 << 6,
+				 1 << 7, 1 << 8, 1 << 9};
+	struct mmc_test_multiple_rw test_data = {
+		.sg_len = sg_len,
+		.size = TEST_AREA_MAX_SIZE,
+		.len = ARRAY_SIZE(sg_len),
+		.do_write = false,
+		.do_nonblock_req = true,
+		.prepare = MMC_TEST_PREP_NONE,
+	};
+
+	return mmc_test_rw_multiple_sg_len(test, &test_data);
+}
+
+/*
+ * eMMC hardware reset.
+ */
+static int mmc_test_reset(struct mmc_test_card *test)
+{
+	struct mmc_card *card = test->card;
+	struct mmc_host *host = card->host;
+	int err;
+
+	err = mmc_hw_reset(host);
+	if (!err)
+		return RESULT_OK;
+	else if (err == -EOPNOTSUPP)
+		return RESULT_UNSUP_HOST;
+
+	return RESULT_FAIL;
+}
+
+struct mmc_test_req {
+	struct mmc_request mrq;
+	struct mmc_command sbc;
+	struct mmc_command cmd;
+	struct mmc_command stop;
+	struct mmc_command status;
+	struct mmc_data data;
+};
+
+static struct mmc_test_req *mmc_test_req_alloc(void)
+{
+	struct mmc_test_req *rq = kzalloc(sizeof(*rq), GFP_KERNEL);
+
+	if (rq) {
+		rq->mrq.cmd = &rq->cmd;
+		rq->mrq.data = &rq->data;
+		rq->mrq.stop = &rq->stop;
+	}
+
+	return rq;
+}
+
+static int mmc_test_send_status(struct mmc_test_card *test,
+				struct mmc_command *cmd)
+{
+	memset(cmd, 0, sizeof(*cmd));
+
+	cmd->opcode = MMC_SEND_STATUS;
+	if (!mmc_host_is_spi(test->card->host))
+		cmd->arg = test->card->rca << 16;
+	cmd->flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC;
+
+	return mmc_wait_for_cmd(test->card->host, cmd, 0);
+}
+
+static int mmc_test_ongoing_transfer(struct mmc_test_card *test,
+				     unsigned int dev_addr, int use_sbc,
+				     int repeat_cmd, int write, int use_areq)
+{
+	struct mmc_test_req *rq = mmc_test_req_alloc();
+	struct mmc_host *host = test->card->host;
+	struct mmc_test_area *t = &test->area;
+	struct mmc_test_async_req test_areq = { .test = test };
+	struct mmc_request *mrq;
+	unsigned long timeout;
+	bool expired = false;
+	enum mmc_blk_status blkstat = MMC_BLK_SUCCESS;
+	int ret = 0, cmd_ret;
+	u32 status = 0;
+	int count = 0;
+
+	if (!rq)
+		return -ENOMEM;
+
+	mrq = &rq->mrq;
+	if (use_sbc)
+		mrq->sbc = &rq->sbc;
+	mrq->cap_cmd_during_tfr = true;
+
+	test_areq.areq.mrq = mrq;
+	test_areq.areq.err_check = mmc_test_check_result_async;
+
+	mmc_test_prepare_mrq(test, mrq, t->sg, t->sg_len, dev_addr, t->blocks,
+			     512, write);
+
+	if (use_sbc && t->blocks > 1 && !mrq->sbc) {
+		ret =  mmc_host_cmd23(host) ?
+		       RESULT_UNSUP_CARD :
+		       RESULT_UNSUP_HOST;
+		goto out_free;
+	}
+
+	/* Start ongoing data request */
+	if (use_areq) {
+		mmc_start_req(host, &test_areq.areq, &blkstat);
+		if (blkstat != MMC_BLK_SUCCESS) {
+			ret = RESULT_FAIL;
+			goto out_free;
+		}
+	} else {
+		mmc_wait_for_req(host, mrq);
+	}
+
+	timeout = jiffies + msecs_to_jiffies(3000);
+	do {
+		count += 1;
+
+		/* Send status command while data transfer in progress */
+		cmd_ret = mmc_test_send_status(test, &rq->status);
+		if (cmd_ret)
+			break;
+
+		status = rq->status.resp[0];
+		if (status & R1_ERROR) {
+			cmd_ret = -EIO;
+			break;
+		}
+
+		if (mmc_is_req_done(host, mrq))
+			break;
+
+		expired = time_after(jiffies, timeout);
+		if (expired) {
+			pr_info("%s: timeout waiting for Tran state status %#x\n",
+				mmc_hostname(host), status);
+			cmd_ret = -ETIMEDOUT;
+			break;
+		}
+	} while (repeat_cmd && R1_CURRENT_STATE(status) != R1_STATE_TRAN);
+
+	/* Wait for data request to complete */
+	if (use_areq) {
+		mmc_start_req(host, NULL, &blkstat);
+		if (blkstat != MMC_BLK_SUCCESS)
+			ret = RESULT_FAIL;
+	} else {
+		mmc_wait_for_req_done(test->card->host, mrq);
+	}
+
+	/*
+	 * For cap_cmd_during_tfr request, upper layer must send stop if
+	 * required.
+	 */
+	if (mrq->data->stop && (mrq->data->error || !mrq->sbc)) {
+		if (ret)
+			mmc_wait_for_cmd(host, mrq->data->stop, 0);
+		else
+			ret = mmc_wait_for_cmd(host, mrq->data->stop, 0);
+	}
+
+	if (ret)
+		goto out_free;
+
+	if (cmd_ret) {
+		pr_info("%s: Send Status failed: status %#x, error %d\n",
+			mmc_hostname(test->card->host), status, cmd_ret);
+	}
+
+	ret = mmc_test_check_result(test, mrq);
+	if (ret)
+		goto out_free;
+
+	ret = mmc_test_wait_busy(test);
+	if (ret)
+		goto out_free;
+
+	if (repeat_cmd && (t->blocks + 1) << 9 > t->max_tfr)
+		pr_info("%s: %d commands completed during transfer of %u blocks\n",
+			mmc_hostname(test->card->host), count, t->blocks);
+
+	if (cmd_ret)
+		ret = cmd_ret;
+out_free:
+	kfree(rq);
+
+	return ret;
+}
+
+static int __mmc_test_cmds_during_tfr(struct mmc_test_card *test,
+				      unsigned long sz, int use_sbc, int write,
+				      int use_areq)
+{
+	struct mmc_test_area *t = &test->area;
+	int ret;
+
+	if (!(test->card->host->caps & MMC_CAP_CMD_DURING_TFR))
+		return RESULT_UNSUP_HOST;
+
+	ret = mmc_test_area_map(test, sz, 0, 0);
+	if (ret)
+		return ret;
+
+	ret = mmc_test_ongoing_transfer(test, t->dev_addr, use_sbc, 0, write,
+					use_areq);
+	if (ret)
+		return ret;
+
+	return mmc_test_ongoing_transfer(test, t->dev_addr, use_sbc, 1, write,
+					 use_areq);
+}
+
+static int mmc_test_cmds_during_tfr(struct mmc_test_card *test, int use_sbc,
+				    int write, int use_areq)
+{
+	struct mmc_test_area *t = &test->area;
+	unsigned long sz;
+	int ret;
+
+	for (sz = 512; sz <= t->max_tfr; sz += 512) {
+		ret = __mmc_test_cmds_during_tfr(test, sz, use_sbc, write,
+						 use_areq);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+/*
+ * Commands during read - no Set Block Count (CMD23).
+ */
+static int mmc_test_cmds_during_read(struct mmc_test_card *test)
+{
+	return mmc_test_cmds_during_tfr(test, 0, 0, 0);
+}
+
+/*
+ * Commands during write - no Set Block Count (CMD23).
+ */
+static int mmc_test_cmds_during_write(struct mmc_test_card *test)
+{
+	return mmc_test_cmds_during_tfr(test, 0, 1, 0);
+}
+
+/*
+ * Commands during read - use Set Block Count (CMD23).
+ */
+static int mmc_test_cmds_during_read_cmd23(struct mmc_test_card *test)
+{
+	return mmc_test_cmds_during_tfr(test, 1, 0, 0);
+}
+
+/*
+ * Commands during write - use Set Block Count (CMD23).
+ */
+static int mmc_test_cmds_during_write_cmd23(struct mmc_test_card *test)
+{
+	return mmc_test_cmds_during_tfr(test, 1, 1, 0);
+}
+
+/*
+ * Commands during non-blocking read - use Set Block Count (CMD23).
+ */
+static int mmc_test_cmds_during_read_cmd23_nonblock(struct mmc_test_card *test)
+{
+	return mmc_test_cmds_during_tfr(test, 1, 0, 1);
+}
+
+/*
+ * Commands during non-blocking write - use Set Block Count (CMD23).
+ */
+static int mmc_test_cmds_during_write_cmd23_nonblock(struct mmc_test_card *test)
+{
+	return mmc_test_cmds_during_tfr(test, 1, 1, 1);
+}
+
+static const struct mmc_test_case mmc_test_cases[] = {
+	{
+		.name = "Basic write (no data verification)",
+		.run = mmc_test_basic_write,
+	},
+
+	{
+		.name = "Basic read (no data verification)",
+		.run = mmc_test_basic_read,
+	},
+
+	{
+		.name = "Basic write (with data verification)",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_verify_write,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Basic read (with data verification)",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_verify_read,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Multi-block write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_multi_write,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Multi-block read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_multi_read,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Power of two block writes",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_pow2_write,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Power of two block reads",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_pow2_read,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Weird sized block writes",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_weird_write,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Weird sized block reads",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_weird_read,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Badly aligned write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_align_write,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Badly aligned read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_align_read,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Badly aligned multi-block write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_align_multi_write,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Badly aligned multi-block read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_align_multi_read,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Correct xfer_size at write (start failure)",
+		.run = mmc_test_xfersize_write,
+	},
+
+	{
+		.name = "Correct xfer_size at read (start failure)",
+		.run = mmc_test_xfersize_read,
+	},
+
+	{
+		.name = "Correct xfer_size at write (midway failure)",
+		.run = mmc_test_multi_xfersize_write,
+	},
+
+	{
+		.name = "Correct xfer_size at read (midway failure)",
+		.run = mmc_test_multi_xfersize_read,
+	},
+
+#ifdef CONFIG_HIGHMEM
+
+	{
+		.name = "Highmem write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_write_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Highmem read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_read_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Multi-block highmem write",
+		.prepare = mmc_test_prepare_write,
+		.run = mmc_test_multi_write_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+	{
+		.name = "Multi-block highmem read",
+		.prepare = mmc_test_prepare_read,
+		.run = mmc_test_multi_read_high,
+		.cleanup = mmc_test_cleanup,
+	},
+
+#else
+
+	{
+		.name = "Highmem write",
+		.run = mmc_test_no_highmem,
+	},
+
+	{
+		.name = "Highmem read",
+		.run = mmc_test_no_highmem,
+	},
+
+	{
+		.name = "Multi-block highmem write",
+		.run = mmc_test_no_highmem,
+	},
+
+	{
+		.name = "Multi-block highmem read",
+		.run = mmc_test_no_highmem,
+	},
+
+#endif /* CONFIG_HIGHMEM */
+
+	{
+		.name = "Best-case read performance",
+		.prepare = mmc_test_area_prepare_fill,
+		.run = mmc_test_best_read_performance,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Best-case write performance",
+		.prepare = mmc_test_area_prepare_erase,
+		.run = mmc_test_best_write_performance,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Best-case read performance into scattered pages",
+		.prepare = mmc_test_area_prepare_fill,
+		.run = mmc_test_best_read_perf_max_scatter,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Best-case write performance from scattered pages",
+		.prepare = mmc_test_area_prepare_erase,
+		.run = mmc_test_best_write_perf_max_scatter,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Single read performance by transfer size",
+		.prepare = mmc_test_area_prepare_fill,
+		.run = mmc_test_profile_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Single write performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Single trim performance by transfer size",
+		.prepare = mmc_test_area_prepare_fill,
+		.run = mmc_test_profile_trim_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Consecutive read performance by transfer size",
+		.prepare = mmc_test_area_prepare_fill,
+		.run = mmc_test_profile_seq_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Consecutive write performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_seq_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Consecutive trim performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_seq_trim_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Random read performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_random_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Random write performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_random_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Large sequential read into scattered pages",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_large_seq_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Large sequential write from scattered pages",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_large_seq_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Write performance with blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_write_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Write performance with non-blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_write_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance with blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_read_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance with non-blocking req 4k to 4MB",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_mult_read_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Write performance blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_wr_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Write performance non-blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_wr_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_r_blocking_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Read performance non-blocking req 1 to 512 sg elems",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_profile_sglen_r_nonblock_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Reset test",
+		.run = mmc_test_reset,
+	},
+
+	{
+		.name = "Commands during read - no Set Block Count (CMD23)",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_cmds_during_read,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Commands during write - no Set Block Count (CMD23)",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_cmds_during_write,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Commands during read - use Set Block Count (CMD23)",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_cmds_during_read_cmd23,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Commands during write - use Set Block Count (CMD23)",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_cmds_during_write_cmd23,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Commands during non-blocking read - use Set Block Count (CMD23)",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_cmds_during_read_cmd23_nonblock,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Commands during non-blocking write - use Set Block Count (CMD23)",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_cmds_during_write_cmd23_nonblock,
+		.cleanup = mmc_test_area_cleanup,
+	},
+};
+
+static DEFINE_MUTEX(mmc_test_lock);
+
+static LIST_HEAD(mmc_test_result);
+
+static void mmc_test_run(struct mmc_test_card *test, int testcase)
+{
+	int i, ret;
+
+	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);
+
+	for (i = 0;i < ARRAY_SIZE(mmc_test_cases);i++) {
+		struct mmc_test_general_result *gr;
+
+		if (testcase && ((i + 1) != testcase))
+			continue;
+
+		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) {
+				pr_info("%s: Result: Prepare "
+					"stage failed! (%d)\n",
+					mmc_hostname(test->card->host),
+					ret);
+				continue;
+			}
+		}
+
+		gr = kzalloc(sizeof(struct mmc_test_general_result),
+			GFP_KERNEL);
+		if (gr) {
+			INIT_LIST_HEAD(&gr->tr_lst);
+
+			/* Assign data what we know already */
+			gr->card = test->card;
+			gr->testcase = i;
+
+			/* Append container to global one */
+			list_add_tail(&gr->link, &mmc_test_result);
+
+			/*
+			 * Save the pointer to created container in our private
+			 * structure.
+			 */
+			test->gr = gr;
+		}
+
+		ret = mmc_test_cases[i].run(test);
+		switch (ret) {
+		case RESULT_OK:
+			pr_info("%s: Result: OK\n",
+				mmc_hostname(test->card->host));
+			break;
+		case RESULT_FAIL:
+			pr_info("%s: Result: FAILED\n",
+				mmc_hostname(test->card->host));
+			break;
+		case RESULT_UNSUP_HOST:
+			pr_info("%s: Result: UNSUPPORTED "
+				"(by host)\n",
+				mmc_hostname(test->card->host));
+			break;
+		case RESULT_UNSUP_CARD:
+			pr_info("%s: Result: UNSUPPORTED "
+				"(by card)\n",
+				mmc_hostname(test->card->host));
+			break;
+		default:
+			pr_info("%s: Result: ERROR (%d)\n",
+				mmc_hostname(test->card->host), ret);
+		}
+
+		/* Save the result */
+		if (gr)
+			gr->result = ret;
+
+		if (mmc_test_cases[i].cleanup) {
+			ret = mmc_test_cases[i].cleanup(test);
+			if (ret) {
+				pr_info("%s: Warning: Cleanup "
+					"stage failed! (%d)\n",
+					mmc_hostname(test->card->host),
+					ret);
+			}
+		}
+	}
+
+	mmc_release_host(test->card->host);
+
+	pr_info("%s: Tests completed.\n",
+		mmc_hostname(test->card->host));
+}
+
+static void mmc_test_free_result(struct mmc_card *card)
+{
+	struct mmc_test_general_result *gr, *grs;
+
+	mutex_lock(&mmc_test_lock);
+
+	list_for_each_entry_safe(gr, grs, &mmc_test_result, link) {
+		struct mmc_test_transfer_result *tr, *trs;
+
+		if (card && gr->card != card)
+			continue;
+
+		list_for_each_entry_safe(tr, trs, &gr->tr_lst, link) {
+			list_del(&tr->link);
+			kfree(tr);
+		}
+
+		list_del(&gr->link);
+		kfree(gr);
+	}
+
+	mutex_unlock(&mmc_test_lock);
+}
+
+static LIST_HEAD(mmc_test_file_test);
+
+static int mtf_test_show(struct seq_file *sf, void *data)
+{
+	struct mmc_card *card = (struct mmc_card *)sf->private;
+	struct mmc_test_general_result *gr;
+
+	mutex_lock(&mmc_test_lock);
+
+	list_for_each_entry(gr, &mmc_test_result, link) {
+		struct mmc_test_transfer_result *tr;
+
+		if (gr->card != card)
+			continue;
+
+		seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
+
+		list_for_each_entry(tr, &gr->tr_lst, link) {
+			seq_printf(sf, "%u %d %lu.%09lu %u %u.%02u\n",
+				tr->count, tr->sectors,
+				(unsigned long)tr->ts.tv_sec,
+				(unsigned long)tr->ts.tv_nsec,
+				tr->rate, tr->iops / 100, tr->iops % 100);
+		}
+	}
+
+	mutex_unlock(&mmc_test_lock);
+
+	return 0;
+}
+
+static int mtf_test_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mtf_test_show, inode->i_private);
+}
+
+static ssize_t mtf_test_write(struct file *file, const char __user *buf,
+	size_t count, loff_t *pos)
+{
+	struct seq_file *sf = (struct seq_file *)file->private_data;
+	struct mmc_card *card = (struct mmc_card *)sf->private;
+	struct mmc_test_card *test;
+	long testcase;
+	int ret;
+
+	ret = kstrtol_from_user(buf, count, 10, &testcase);
+	if (ret)
+		return ret;
+
+	test = kzalloc(sizeof(struct mmc_test_card), GFP_KERNEL);
+	if (!test)
+		return -ENOMEM;
+
+	/*
+	 * Remove all test cases associated with given card. Thus we have only
+	 * actual data of the last run.
+	 */
+	mmc_test_free_result(card);
+
+	test->card = card;
+
+	test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
+#ifdef CONFIG_HIGHMEM
+	test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
+#endif
+
+#ifdef CONFIG_HIGHMEM
+	if (test->buffer && test->highmem) {
+#else
+	if (test->buffer) {
+#endif
+		mutex_lock(&mmc_test_lock);
+		mmc_test_run(test, testcase);
+		mutex_unlock(&mmc_test_lock);
+	}
+
+#ifdef CONFIG_HIGHMEM
+	__free_pages(test->highmem, BUFFER_ORDER);
+#endif
+	kfree(test->buffer);
+	kfree(test);
+
+	return count;
+}
+
+static const struct file_operations mmc_test_fops_test = {
+	.open		= mtf_test_open,
+	.read		= seq_read,
+	.write		= mtf_test_write,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int mtf_testlist_show(struct seq_file *sf, void *data)
+{
+	int i;
+
+	mutex_lock(&mmc_test_lock);
+
+	seq_printf(sf, "0:\tRun all tests\n");
+	for (i = 0; i < ARRAY_SIZE(mmc_test_cases); i++)
+		seq_printf(sf, "%d:\t%s\n", i+1, mmc_test_cases[i].name);
+
+	mutex_unlock(&mmc_test_lock);
+
+	return 0;
+}
+
+static int mtf_testlist_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mtf_testlist_show, inode->i_private);
+}
+
+static const struct file_operations mmc_test_fops_testlist = {
+	.open		= mtf_testlist_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static void mmc_test_free_dbgfs_file(struct mmc_card *card)
+{
+	struct mmc_test_dbgfs_file *df, *dfs;
+
+	mutex_lock(&mmc_test_lock);
+
+	list_for_each_entry_safe(df, dfs, &mmc_test_file_test, link) {
+		if (card && df->card != card)
+			continue;
+		debugfs_remove(df->file);
+		list_del(&df->link);
+		kfree(df);
+	}
+
+	mutex_unlock(&mmc_test_lock);
+}
+
+static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
+	const char *name, umode_t mode, const struct file_operations *fops)
+{
+	struct dentry *file = NULL;
+	struct mmc_test_dbgfs_file *df;
+
+	if (card->debugfs_root)
+		file = debugfs_create_file(name, mode, card->debugfs_root,
+			card, fops);
+
+	if (IS_ERR_OR_NULL(file)) {
+		dev_err(&card->dev,
+			"Can't create %s. Perhaps debugfs is disabled.\n",
+			name);
+		return -ENODEV;
+	}
+
+	df = kmalloc(sizeof(struct mmc_test_dbgfs_file), GFP_KERNEL);
+	if (!df) {
+		debugfs_remove(file);
+		dev_err(&card->dev,
+			"Can't allocate memory for internal usage.\n");
+		return -ENOMEM;
+	}
+
+	df->card = card;
+	df->file = file;
+
+	list_add(&df->link, &mmc_test_file_test);
+	return 0;
+}
+
+static int mmc_test_register_dbgfs_file(struct mmc_card *card)
+{
+	int ret;
+
+	mutex_lock(&mmc_test_lock);
+
+	ret = __mmc_test_register_dbgfs_file(card, "test", S_IWUSR | S_IRUGO,
+		&mmc_test_fops_test);
+	if (ret)
+		goto err;
+
+	ret = __mmc_test_register_dbgfs_file(card, "testlist", S_IRUGO,
+		&mmc_test_fops_testlist);
+	if (ret)
+		goto err;
+
+err:
+	mutex_unlock(&mmc_test_lock);
+
+	return ret;
+}
+
+static int mmc_test_probe(struct mmc_card *card)
+{
+	int ret;
+
+	if (!mmc_card_mmc(card) && !mmc_card_sd(card))
+		return -ENODEV;
+
+	ret = mmc_test_register_dbgfs_file(card);
+	if (ret)
+		return ret;
+
+	dev_info(&card->dev, "Card claimed for testing.\n");
+
+	return 0;
+}
+
+static void mmc_test_remove(struct mmc_card *card)
+{
+	mmc_test_free_result(card);
+	mmc_test_free_dbgfs_file(card);
+}
+
+static void mmc_test_shutdown(struct mmc_card *card)
+{
+}
+
+static struct mmc_driver mmc_driver = {
+	.drv		= {
+		.name	= "mmc_test",
+	},
+	.probe		= mmc_test_probe,
+	.remove		= mmc_test_remove,
+	.shutdown	= mmc_test_shutdown,
+};
+
+static int __init mmc_test_init(void)
+{
+	return mmc_register_driver(&mmc_driver);
+}
+
+static void __exit mmc_test_exit(void)
+{
+	/* Clear stalled data if card is still plugged */
+	mmc_test_free_result(NULL);
+	mmc_test_free_dbgfs_file(NULL);
+
+	mmc_unregister_driver(&mmc_driver);
+}
+
+module_init(mmc_test_init);
+module_exit(mmc_test_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Multimedia Card (MMC) host test driver");
+MODULE_AUTHOR("Pierre Ossman");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/queue.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/queue.c
--- linux-libre-4.9-gnu/drivers/mmc/core/queue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/queue.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,489 @@
+/*
+ *  Copyright (C) 2003 Russell King, All Rights Reserved.
+ *  Copyright 2006-2007 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it 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/blkdev.h>
+#include <linux/freezer.h>
+#include <linux/kthread.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include "queue.h"
+#include "block.h"
+
+#define MMC_QUEUE_BOUNCESZ	65536
+
+/*
+ * Prepare a MMC request. This just filters out odd stuff.
+ */
+static int mmc_prep_request(struct request_queue *q, struct request *req)
+{
+	struct mmc_queue *mq = q->queuedata;
+
+	/*
+	 * We only like normal block requests and discards.
+	 */
+	if (req->cmd_type != REQ_TYPE_FS && req_op(req) != REQ_OP_DISCARD &&
+	    req_op(req) != REQ_OP_SECURE_ERASE) {
+		blk_dump_rq_flags(req, "MMC bad request");
+		return BLKPREP_KILL;
+	}
+
+	if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
+		return BLKPREP_KILL;
+
+	req->rq_flags |= RQF_DONTPREP;
+
+	return BLKPREP_OK;
+}
+
+static int mmc_queue_thread(void *d)
+{
+	struct mmc_queue *mq = d;
+	struct request_queue *q = mq->queue;
+	struct mmc_context_info *cntx = &mq->card->host->context_info;
+
+	current->flags |= PF_MEMALLOC;
+
+	down(&mq->thread_sem);
+	do {
+		struct request *req = NULL;
+
+		spin_lock_irq(q->queue_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+		req = blk_fetch_request(q);
+		mq->asleep = false;
+		cntx->is_waiting_last_req = false;
+		cntx->is_new_req = false;
+		if (!req) {
+			/*
+			 * Dispatch queue is empty so set flags for
+			 * mmc_request_fn() to wake us up.
+			 */
+			if (mq->mqrq_prev->req)
+				cntx->is_waiting_last_req = true;
+			else
+				mq->asleep = true;
+		}
+		mq->mqrq_cur->req = req;
+		spin_unlock_irq(q->queue_lock);
+
+		if (req || mq->mqrq_prev->req) {
+			bool req_is_special = mmc_req_is_special(req);
+
+			set_current_state(TASK_RUNNING);
+			mmc_blk_issue_rq(mq, req);
+			cond_resched();
+			if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
+				mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
+				continue; /* fetch again */
+			}
+
+			/*
+			 * Current request becomes previous request
+			 * and vice versa.
+			 * In case of special requests, current request
+			 * has been finished. Do not assign it to previous
+			 * request.
+			 */
+			if (req_is_special)
+				mq->mqrq_cur->req = NULL;
+
+			mq->mqrq_prev->brq.mrq.data = NULL;
+			mq->mqrq_prev->req = NULL;
+			swap(mq->mqrq_prev, mq->mqrq_cur);
+		} else {
+			if (kthread_should_stop()) {
+				set_current_state(TASK_RUNNING);
+				break;
+			}
+			up(&mq->thread_sem);
+			schedule();
+			down(&mq->thread_sem);
+		}
+	} while (1);
+	up(&mq->thread_sem);
+
+	return 0;
+}
+
+/*
+ * Generic MMC request handler.  This is called for any queue on a
+ * particular host.  When the host is not busy, we look for a request
+ * on any queue on this host, and attempt to issue it.  This may
+ * not be the queue we were asked to process.
+ */
+static void mmc_request_fn(struct request_queue *q)
+{
+	struct mmc_queue *mq = q->queuedata;
+	struct request *req;
+	struct mmc_context_info *cntx;
+
+	if (!mq) {
+		while ((req = blk_fetch_request(q)) != NULL) {
+			req->rq_flags |= RQF_QUIET;
+			__blk_end_request_all(req, -EIO);
+		}
+		return;
+	}
+
+	cntx = &mq->card->host->context_info;
+
+	if (cntx->is_waiting_last_req) {
+		cntx->is_new_req = true;
+		wake_up_interruptible(&cntx->wait);
+	}
+
+	if (mq->asleep)
+		wake_up_process(mq->thread);
+}
+
+static struct scatterlist *mmc_alloc_sg(int sg_len, int *err)
+{
+	struct scatterlist *sg;
+
+	sg = kmalloc(sizeof(struct scatterlist)*sg_len, GFP_KERNEL);
+	if (!sg)
+		*err = -ENOMEM;
+	else {
+		*err = 0;
+		sg_init_table(sg, sg_len);
+	}
+
+	return sg;
+}
+
+static void mmc_queue_setup_discard(struct request_queue *q,
+				    struct mmc_card *card)
+{
+	unsigned max_discard;
+
+	max_discard = mmc_calc_max_discard(card);
+	if (!max_discard)
+		return;
+
+	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+	blk_queue_max_discard_sectors(q, max_discard);
+	if (card->erased_byte == 0 && !mmc_can_discard(card))
+		q->limits.discard_zeroes_data = 1;
+	q->limits.discard_granularity = card->pref_erase << 9;
+	/* 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))
+		queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q);
+}
+
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+static bool mmc_queue_alloc_bounce_bufs(struct mmc_queue *mq,
+					unsigned int bouncesz)
+{
+	int i;
+
+	for (i = 0; i < mq->qdepth; i++) {
+		mq->mqrq[i].bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+		if (!mq->mqrq[i].bounce_buf)
+			goto out_err;
+	}
+
+	return true;
+
+out_err:
+	while (--i >= 0) {
+		kfree(mq->mqrq[i].bounce_buf);
+		mq->mqrq[i].bounce_buf = NULL;
+	}
+	pr_warn("%s: unable to allocate bounce buffers\n",
+		mmc_card_name(mq->card));
+	return false;
+}
+
+static int mmc_queue_alloc_bounce_sgs(struct mmc_queue *mq,
+				      unsigned int bouncesz)
+{
+	int i, ret;
+
+	for (i = 0; i < mq->qdepth; i++) {
+		mq->mqrq[i].sg = mmc_alloc_sg(1, &ret);
+		if (ret)
+			return ret;
+
+		mq->mqrq[i].bounce_sg = mmc_alloc_sg(bouncesz / 512, &ret);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+#endif
+
+static int mmc_queue_alloc_sgs(struct mmc_queue *mq, int max_segs)
+{
+	int i, ret;
+
+	for (i = 0; i < mq->qdepth; i++) {
+		mq->mqrq[i].sg = mmc_alloc_sg(max_segs, &ret);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void mmc_queue_req_free_bufs(struct mmc_queue_req *mqrq)
+{
+	kfree(mqrq->bounce_sg);
+	mqrq->bounce_sg = NULL;
+
+	kfree(mqrq->sg);
+	mqrq->sg = NULL;
+
+	kfree(mqrq->bounce_buf);
+	mqrq->bounce_buf = NULL;
+}
+
+static void mmc_queue_reqs_free_bufs(struct mmc_queue *mq)
+{
+	int i;
+
+	for (i = 0; i < mq->qdepth; i++)
+		mmc_queue_req_free_bufs(&mq->mqrq[i]);
+}
+
+/**
+ * mmc_init_queue - initialise a queue structure.
+ * @mq: mmc queue
+ * @card: mmc card to attach this queue
+ * @lock: queue lock
+ * @subname: partition subname
+ *
+ * Initialise a MMC card request queue.
+ */
+int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
+		   spinlock_t *lock, const char *subname)
+{
+	struct mmc_host *host = card->host;
+	u64 limit = BLK_BOUNCE_HIGH;
+	bool bounce = false;
+	int ret = -ENOMEM;
+
+	if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
+		limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
+
+	mq->card = card;
+	mq->queue = blk_init_queue(mmc_request_fn, lock);
+	if (!mq->queue)
+		return -ENOMEM;
+
+	mq->qdepth = 2;
+	mq->mqrq = kcalloc(mq->qdepth, sizeof(struct mmc_queue_req),
+			   GFP_KERNEL);
+	if (!mq->mqrq)
+		goto blk_cleanup;
+	mq->mqrq_cur = &mq->mqrq[0];
+	mq->mqrq_prev = &mq->mqrq[1];
+	mq->queue->queuedata = mq;
+
+	blk_queue_prep_rq(mq->queue, mmc_prep_request);
+	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue);
+	queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, mq->queue);
+	if (mmc_can_erase(card))
+		mmc_queue_setup_discard(mq->queue, card);
+
+#ifdef CONFIG_MMC_BLOCK_BOUNCE
+	if (host->max_segs == 1) {
+		unsigned int bouncesz;
+
+		bouncesz = MMC_QUEUE_BOUNCESZ;
+
+		if (bouncesz > host->max_req_size)
+			bouncesz = host->max_req_size;
+		if (bouncesz > host->max_seg_size)
+			bouncesz = host->max_seg_size;
+		if (bouncesz > (host->max_blk_count * 512))
+			bouncesz = host->max_blk_count * 512;
+
+		if (bouncesz > 512 &&
+		    mmc_queue_alloc_bounce_bufs(mq, bouncesz)) {
+			blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY);
+			blk_queue_max_hw_sectors(mq->queue, bouncesz / 512);
+			blk_queue_max_segments(mq->queue, bouncesz / 512);
+			blk_queue_max_segment_size(mq->queue, bouncesz);
+
+			ret = mmc_queue_alloc_bounce_sgs(mq, bouncesz);
+			if (ret)
+				goto cleanup_queue;
+			bounce = true;
+		}
+	}
+#endif
+
+	if (!bounce) {
+		blk_queue_bounce_limit(mq->queue, limit);
+		blk_queue_max_hw_sectors(mq->queue,
+			min(host->max_blk_count, host->max_req_size / 512));
+		blk_queue_max_segments(mq->queue, host->max_segs);
+		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+
+		ret = mmc_queue_alloc_sgs(mq, host->max_segs);
+		if (ret)
+			goto cleanup_queue;
+	}
+
+	sema_init(&mq->thread_sem, 1);
+
+	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s",
+		host->index, subname ? subname : "");
+
+	if (IS_ERR(mq->thread)) {
+		ret = PTR_ERR(mq->thread);
+		goto cleanup_queue;
+	}
+
+	return 0;
+
+ cleanup_queue:
+	mmc_queue_reqs_free_bufs(mq);
+	kfree(mq->mqrq);
+	mq->mqrq = NULL;
+blk_cleanup:
+	blk_cleanup_queue(mq->queue);
+	return ret;
+}
+
+void mmc_cleanup_queue(struct mmc_queue *mq)
+{
+	struct request_queue *q = mq->queue;
+	unsigned long flags;
+
+	/* Make sure the queue isn't suspended, as that will deadlock */
+	mmc_queue_resume(mq);
+
+	/* Then terminate our worker thread */
+	kthread_stop(mq->thread);
+
+	/* Empty the queue */
+	spin_lock_irqsave(q->queue_lock, flags);
+	q->queuedata = NULL;
+	blk_start_queue(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	mmc_queue_reqs_free_bufs(mq);
+	kfree(mq->mqrq);
+	mq->mqrq = NULL;
+
+	mq->card = NULL;
+}
+EXPORT_SYMBOL(mmc_cleanup_queue);
+
+/**
+ * mmc_queue_suspend - suspend a MMC request queue
+ * @mq: MMC queue to suspend
+ *
+ * Stop the block request queue, and wait for our thread to
+ * complete any outstanding requests.  This ensures that we
+ * won't suspend while a request is being processed.
+ */
+void mmc_queue_suspend(struct mmc_queue *mq)
+{
+	struct request_queue *q = mq->queue;
+	unsigned long flags;
+
+	if (!(mq->flags & MMC_QUEUE_SUSPENDED)) {
+		mq->flags |= MMC_QUEUE_SUSPENDED;
+
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_stop_queue(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+
+		down(&mq->thread_sem);
+	}
+}
+
+/**
+ * mmc_queue_resume - resume a previously suspended MMC request queue
+ * @mq: MMC queue to resume
+ */
+void mmc_queue_resume(struct mmc_queue *mq)
+{
+	struct request_queue *q = mq->queue;
+	unsigned long flags;
+
+	if (mq->flags & MMC_QUEUE_SUSPENDED) {
+		mq->flags &= ~MMC_QUEUE_SUSPENDED;
+
+		up(&mq->thread_sem);
+
+		spin_lock_irqsave(q->queue_lock, flags);
+		blk_start_queue(q);
+		spin_unlock_irqrestore(q->queue_lock, flags);
+	}
+}
+
+/*
+ * Prepare the sg list(s) to be handed of to the host driver
+ */
+unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
+{
+	unsigned int sg_len;
+	size_t buflen;
+	struct scatterlist *sg;
+	int i;
+
+	if (!mqrq->bounce_buf)
+		return blk_rq_map_sg(mq->queue, mqrq->req, mqrq->sg);
+
+	sg_len = blk_rq_map_sg(mq->queue, mqrq->req, mqrq->bounce_sg);
+
+	mqrq->bounce_sg_len = sg_len;
+
+	buflen = 0;
+	for_each_sg(mqrq->bounce_sg, sg, sg_len, i)
+		buflen += sg->length;
+
+	sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen);
+
+	return 1;
+}
+
+/*
+ * If writing, bounce the data to the buffer before the request
+ * is sent to the host driver
+ */
+void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
+{
+	if (!mqrq->bounce_buf)
+		return;
+
+	if (rq_data_dir(mqrq->req) != WRITE)
+		return;
+
+	sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
+		mqrq->bounce_buf, mqrq->sg[0].length);
+}
+
+/*
+ * If reading, bounce the data from the buffer after the request
+ * has been handled by the host driver
+ */
+void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
+{
+	if (!mqrq->bounce_buf)
+		return;
+
+	if (rq_data_dir(mqrq->req) != READ)
+		return;
+
+	sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
+		mqrq->bounce_buf, mqrq->sg[0].length);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/queue.h linux-libre-4.10-rc8-gnu/drivers/mmc/core/queue.h
--- linux-libre-4.9-gnu/drivers/mmc/core/queue.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/queue.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,64 @@
+#ifndef MMC_QUEUE_H
+#define MMC_QUEUE_H
+
+static inline bool mmc_req_is_special(struct request *req)
+{
+	return req &&
+		(req_op(req) == REQ_OP_FLUSH ||
+		 req_op(req) == REQ_OP_DISCARD ||
+		 req_op(req) == REQ_OP_SECURE_ERASE);
+}
+
+struct request;
+struct task_struct;
+struct mmc_blk_data;
+
+struct mmc_blk_request {
+	struct mmc_request	mrq;
+	struct mmc_command	sbc;
+	struct mmc_command	cmd;
+	struct mmc_command	stop;
+	struct mmc_data		data;
+	int			retune_retry_done;
+};
+
+struct mmc_queue_req {
+	struct request		*req;
+	struct mmc_blk_request	brq;
+	struct scatterlist	*sg;
+	char			*bounce_buf;
+	struct scatterlist	*bounce_sg;
+	unsigned int		bounce_sg_len;
+	struct mmc_async_req	mmc_active;
+};
+
+struct mmc_queue {
+	struct mmc_card		*card;
+	struct task_struct	*thread;
+	struct semaphore	thread_sem;
+	unsigned int		flags;
+#define MMC_QUEUE_SUSPENDED	(1 << 0)
+#define MMC_QUEUE_NEW_REQUEST	(1 << 1)
+	bool			asleep;
+	struct mmc_blk_data	*blkdata;
+	struct request_queue	*queue;
+	struct mmc_queue_req	*mqrq;
+	struct mmc_queue_req	*mqrq_cur;
+	struct mmc_queue_req	*mqrq_prev;
+	int			qdepth;
+};
+
+extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
+			  const char *);
+extern void mmc_cleanup_queue(struct mmc_queue *);
+extern void mmc_queue_suspend(struct mmc_queue *);
+extern void mmc_queue_resume(struct mmc_queue *);
+
+extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
+				     struct mmc_queue_req *);
+extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
+extern void mmc_queue_bounce_post(struct mmc_queue_req *);
+
+extern int mmc_access_rpmb(struct mmc_queue *);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/sd.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/sd.c
--- linux-libre-4.9-gnu/drivers/mmc/core/sd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/sd.c	2017-02-12 16:03:20.000000000 -0500
@@ -223,6 +223,7 @@ static int mmc_decode_scr(struct mmc_car
 static int mmc_read_ssr(struct mmc_card *card)
 {
 	unsigned int au, es, et, eo;
+	u32 *raw_ssr;
 	int i;
 
 	if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
@@ -231,14 +232,21 @@ static int mmc_read_ssr(struct mmc_card
 		return 0;
 	}
 
-	if (mmc_app_sd_status(card, card->raw_ssr)) {
+	raw_ssr = kmalloc(sizeof(card->raw_ssr), GFP_KERNEL);
+	if (!raw_ssr)
+		return -ENOMEM;
+
+	if (mmc_app_sd_status(card, raw_ssr)) {
 		pr_warn("%s: problem reading SD Status register\n",
 			mmc_hostname(card->host));
+		kfree(raw_ssr);
 		return 0;
 	}
 
 	for (i = 0; i < 16; i++)
-		card->raw_ssr[i] = be32_to_cpu(card->raw_ssr[i]);
+		card->raw_ssr[i] = be32_to_cpu(raw_ssr[i]);
+
+	kfree(raw_ssr);
 
 	/*
 	 * UNSTUFF_BITS only works with four u32s so we have to offset the
@@ -927,7 +935,6 @@ static int mmc_sd_init_card(struct mmc_h
 	u32 cid[4];
 	u32 rocr = 0;
 
-	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
 	err = mmc_sd_get_cid(host, ocr, cid, &rocr);
@@ -1043,9 +1050,6 @@ free_card:
  */
 static void mmc_sd_remove(struct mmc_host *host)
 {
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_remove_card(host->card);
 	host->card = NULL;
 }
@@ -1065,9 +1069,6 @@ static void mmc_sd_detect(struct mmc_hos
 {
 	int err;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_get_card(host->card);
 
 	/*
@@ -1091,9 +1092,6 @@ static int _mmc_sd_suspend(struct mmc_ho
 {
 	int err = 0;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_claim_host(host);
 
 	if (mmc_card_suspended(host->card))
@@ -1136,9 +1134,6 @@ static int _mmc_sd_resume(struct mmc_hos
 {
 	int err = 0;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_claim_host(host);
 
 	if (!mmc_card_suspended(host->card))
@@ -1221,7 +1216,6 @@ int mmc_attach_sd(struct mmc_host *host)
 	int err;
 	u32 ocr, rocr;
 
-	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
 	err = mmc_send_app_op_cond(host, 0, &ocr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/sdio.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio.c
--- linux-libre-4.9-gnu/drivers/mmc/core/sdio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio.c	2017-02-12 16:03:20.000000000 -0500
@@ -63,7 +63,8 @@ static int sdio_init_func(struct mmc_car
 	int ret;
 	struct sdio_func *func;
 
-	BUG_ON(fn > SDIO_MAX_FUNCS);
+	if (WARN_ON(fn > SDIO_MAX_FUNCS))
+		return -EINVAL;
 
 	func = sdio_alloc_func(card);
 	if (IS_ERR(func))
@@ -555,7 +556,6 @@ static int mmc_sdio_init_card(struct mmc
 	u32 rocr = 0;
 	u32 ocr_card = ocr;
 
-	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
 	/* to query card if 1.8V signalling is supported */
@@ -791,9 +791,6 @@ static void mmc_sdio_remove(struct mmc_h
 {
 	int i;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	for (i = 0;i < host->card->sdio_funcs;i++) {
 		if (host->card->sdio_func[i]) {
 			sdio_remove_func(host->card->sdio_func[i]);
@@ -820,9 +817,6 @@ static void mmc_sdio_detect(struct mmc_h
 {
 	int err;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	/* Make sure card is powered before detecting it */
 	if (host->caps & MMC_CAP_POWER_OFF_CARD) {
 		err = pm_runtime_get_sync(&host->card->dev);
@@ -916,9 +910,6 @@ static int mmc_sdio_resume(struct mmc_ho
 {
 	int err = 0;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	/* Basic card reinitialization. */
 	mmc_claim_host(host);
 
@@ -970,9 +961,6 @@ static int mmc_sdio_power_restore(struct
 {
 	int ret;
 
-	BUG_ON(!host);
-	BUG_ON(!host->card);
-
 	mmc_claim_host(host);
 
 	/*
@@ -1063,7 +1051,6 @@ int mmc_attach_sdio(struct mmc_host *hos
 	u32 ocr, rocr;
 	struct mmc_card *card;
 
-	BUG_ON(!host);
 	WARN_ON(!host->claimed);
 
 	err = mmc_send_io_op_cond(host, 0, &ocr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/sdio_cis.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio_cis.c
--- linux-libre-4.9-gnu/drivers/mmc/core/sdio_cis.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio_cis.c	2017-02-12 16:03:20.000000000 -0500
@@ -262,7 +262,8 @@ static int sdio_read_cis(struct mmc_card
 	else
 		prev = &card->tuples;
 
-	BUG_ON(*prev);
+	if (*prev)
+		return -EINVAL;
 
 	do {
 		unsigned char tpl_code, tpl_link;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/sdio_irq.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio_irq.c
--- linux-libre-4.9-gnu/drivers/mmc/core/sdio_irq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio_irq.c	2017-02-12 16:03:20.000000000 -0500
@@ -214,7 +214,9 @@ static int sdio_card_irq_put(struct mmc_
 	struct mmc_host *host = card->host;
 
 	WARN_ON(!host->claimed);
-	BUG_ON(host->sdio_irqs < 1);
+
+	if (host->sdio_irqs < 1)
+		return -EINVAL;
 
 	if (!--host->sdio_irqs) {
 		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
@@ -261,8 +263,8 @@ int sdio_claim_irq(struct sdio_func *fun
 	int ret;
 	unsigned char reg;
 
-	BUG_ON(!func);
-	BUG_ON(!func->card);
+	if (!func)
+		return -EINVAL;
 
 	pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func));
 
@@ -304,8 +306,8 @@ int sdio_release_irq(struct sdio_func *f
 	int ret;
 	unsigned char reg;
 
-	BUG_ON(!func);
-	BUG_ON(!func->card);
+	if (!func)
+		return -EINVAL;
 
 	pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func));
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/sdio_uart.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio_uart.c
--- linux-libre-4.9-gnu/drivers/mmc/core/sdio_uart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/sdio_uart.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,1200 @@
+/*
+ * SDIO UART/GPS driver
+ *
+ * Based on drivers/serial/8250.c and drivers/serial/serial_core.c
+ * by Russell King.
+ *
+ * Author:	Nicolas Pitre
+ * Created:	June 15, 2007
+ * 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+/*
+ * Note: Although this driver assumes a 16550A-like UART implementation,
+ * it is not possible to leverage the common 8250/16550 driver, nor the
+ * core UART infrastructure, as they assumes direct access to the hardware
+ * registers, often under a spinlock.  This is not possible in the SDIO
+ * context as SDIO access functions must be able to sleep.
+ *
+ * Because we need to lock the SDIO host to ensure an exclusive access to
+ * the card, we simply rely on that lock to also prevent and serialize
+ * concurrent access to the same port.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/seq_file.h>
+#include <linux/serial_reg.h>
+#include <linux/circ_buf.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/kfifo.h>
+#include <linux/slab.h>
+
+#include <linux/mmc/core.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+
+
+#define UART_NR		8	/* Number of UARTs this driver can handle */
+
+
+#define FIFO_SIZE	PAGE_SIZE
+#define WAKEUP_CHARS	256
+
+struct uart_icount {
+	__u32	cts;
+	__u32	dsr;
+	__u32	rng;
+	__u32	dcd;
+	__u32	rx;
+	__u32	tx;
+	__u32	frame;
+	__u32	overrun;
+	__u32	parity;
+	__u32	brk;
+};
+
+struct sdio_uart_port {
+	struct tty_port		port;
+	unsigned int		index;
+	struct sdio_func	*func;
+	struct mutex		func_lock;
+	struct task_struct	*in_sdio_uart_irq;
+	unsigned int		regs_offset;
+	struct kfifo		xmit_fifo;
+	spinlock_t		write_lock;
+	struct uart_icount	icount;
+	unsigned int		uartclk;
+	unsigned int		mctrl;
+	unsigned int		rx_mctrl;
+	unsigned int		read_status_mask;
+	unsigned int		ignore_status_mask;
+	unsigned char		x_char;
+	unsigned char           ier;
+	unsigned char           lcr;
+};
+
+static struct sdio_uart_port *sdio_uart_table[UART_NR];
+static DEFINE_SPINLOCK(sdio_uart_table_lock);
+
+static int sdio_uart_add_port(struct sdio_uart_port *port)
+{
+	int index, ret = -EBUSY;
+
+	mutex_init(&port->func_lock);
+	spin_lock_init(&port->write_lock);
+	if (kfifo_alloc(&port->xmit_fifo, FIFO_SIZE, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&sdio_uart_table_lock);
+	for (index = 0; index < UART_NR; index++) {
+		if (!sdio_uart_table[index]) {
+			port->index = index;
+			sdio_uart_table[index] = port;
+			ret = 0;
+			break;
+		}
+	}
+	spin_unlock(&sdio_uart_table_lock);
+
+	return ret;
+}
+
+static struct sdio_uart_port *sdio_uart_port_get(unsigned index)
+{
+	struct sdio_uart_port *port;
+
+	if (index >= UART_NR)
+		return NULL;
+
+	spin_lock(&sdio_uart_table_lock);
+	port = sdio_uart_table[index];
+	if (port)
+		tty_port_get(&port->port);
+	spin_unlock(&sdio_uart_table_lock);
+
+	return port;
+}
+
+static void sdio_uart_port_put(struct sdio_uart_port *port)
+{
+	tty_port_put(&port->port);
+}
+
+static void sdio_uart_port_remove(struct sdio_uart_port *port)
+{
+	struct sdio_func *func;
+
+	spin_lock(&sdio_uart_table_lock);
+	sdio_uart_table[port->index] = NULL;
+	spin_unlock(&sdio_uart_table_lock);
+
+	/*
+	 * We're killing a port that potentially still is in use by
+	 * the tty layer. Be careful to prevent any further access
+	 * to the SDIO function and arrange for the tty layer to
+	 * give up on that port ASAP.
+	 * Beware: the lock ordering is critical.
+	 */
+	mutex_lock(&port->port.mutex);
+	mutex_lock(&port->func_lock);
+	func = port->func;
+	sdio_claim_host(func);
+	port->func = NULL;
+	mutex_unlock(&port->func_lock);
+	/* tty_hangup is async so is this safe as is ?? */
+	tty_port_tty_hangup(&port->port, false);
+	mutex_unlock(&port->port.mutex);
+	sdio_release_irq(func);
+	sdio_disable_func(func);
+	sdio_release_host(func);
+
+	sdio_uart_port_put(port);
+}
+
+static int sdio_uart_claim_func(struct sdio_uart_port *port)
+{
+	mutex_lock(&port->func_lock);
+	if (unlikely(!port->func)) {
+		mutex_unlock(&port->func_lock);
+		return -ENODEV;
+	}
+	if (likely(port->in_sdio_uart_irq != current))
+		sdio_claim_host(port->func);
+	mutex_unlock(&port->func_lock);
+	return 0;
+}
+
+static inline void sdio_uart_release_func(struct sdio_uart_port *port)
+{
+	if (likely(port->in_sdio_uart_irq != current))
+		sdio_release_host(port->func);
+}
+
+static inline unsigned int sdio_in(struct sdio_uart_port *port, int offset)
+{
+	unsigned char c;
+	c = sdio_readb(port->func, port->regs_offset + offset, NULL);
+	return c;
+}
+
+static inline void sdio_out(struct sdio_uart_port *port, int offset, int value)
+{
+	sdio_writeb(port->func, value, port->regs_offset + offset, NULL);
+}
+
+static unsigned int sdio_uart_get_mctrl(struct sdio_uart_port *port)
+{
+	unsigned char status;
+	unsigned int ret;
+
+	/* FIXME: What stops this losing the delta bits and breaking
+	   sdio_uart_check_modem_status ? */
+	status = sdio_in(port, UART_MSR);
+
+	ret = 0;
+	if (status & UART_MSR_DCD)
+		ret |= TIOCM_CAR;
+	if (status & UART_MSR_RI)
+		ret |= TIOCM_RNG;
+	if (status & UART_MSR_DSR)
+		ret |= TIOCM_DSR;
+	if (status & UART_MSR_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+static void sdio_uart_write_mctrl(struct sdio_uart_port *port,
+				  unsigned int mctrl)
+{
+	unsigned char mcr = 0;
+
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_OUT1)
+		mcr |= UART_MCR_OUT1;
+	if (mctrl & TIOCM_OUT2)
+		mcr |= UART_MCR_OUT2;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+	sdio_out(port, UART_MCR, mcr);
+}
+
+static inline void sdio_uart_update_mctrl(struct sdio_uart_port *port,
+					  unsigned int set, unsigned int clear)
+{
+	unsigned int old;
+
+	old = port->mctrl;
+	port->mctrl = (old & ~clear) | set;
+	if (old != port->mctrl)
+		sdio_uart_write_mctrl(port, port->mctrl);
+}
+
+#define sdio_uart_set_mctrl(port, x)	sdio_uart_update_mctrl(port, x, 0)
+#define sdio_uart_clear_mctrl(port, x)	sdio_uart_update_mctrl(port, 0, x)
+
+static void sdio_uart_change_speed(struct sdio_uart_port *port,
+				   struct ktermios *termios,
+				   struct ktermios *old)
+{
+	unsigned char cval, fcr = 0;
+	unsigned int baud, quot;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		cval = UART_LCR_WLEN5;
+		break;
+	case CS6:
+		cval = UART_LCR_WLEN6;
+		break;
+	case CS7:
+		cval = UART_LCR_WLEN7;
+		break;
+	default:
+	case CS8:
+		cval = UART_LCR_WLEN8;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		cval |= UART_LCR_STOP;
+	if (termios->c_cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(termios->c_cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+
+	for (;;) {
+		baud = tty_termios_baud_rate(termios);
+		if (baud == 0)
+			baud = 9600;  /* Special case: B0 rate. */
+		if (baud <= port->uartclk)
+			break;
+		/*
+		 * Oops, the quotient was zero.  Try again with the old
+		 * baud rate if possible, otherwise default to 9600.
+		 */
+		termios->c_cflag &= ~CBAUD;
+		if (old) {
+			termios->c_cflag |= old->c_cflag & CBAUD;
+			old = NULL;
+		} else
+			termios->c_cflag |= B9600;
+	}
+	quot = (2 * port->uartclk + baud) / (2 * baud);
+
+	if (baud < 2400)
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+	else
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
+
+	port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= UART_LSR_BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= UART_LSR_OE;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		port->ignore_status_mask |= UART_LSR_DR;
+
+	/*
+	 * CTS flow control flag and modem status interrupts
+	 */
+	port->ier &= ~UART_IER_MSI;
+	if ((termios->c_cflag & CRTSCTS) || !(termios->c_cflag & CLOCAL))
+		port->ier |= UART_IER_MSI;
+
+	port->lcr = cval;
+
+	sdio_out(port, UART_IER, port->ier);
+	sdio_out(port, UART_LCR, cval | UART_LCR_DLAB);
+	sdio_out(port, UART_DLL, quot & 0xff);
+	sdio_out(port, UART_DLM, quot >> 8);
+	sdio_out(port, UART_LCR, cval);
+	sdio_out(port, UART_FCR, fcr);
+
+	sdio_uart_write_mctrl(port, port->mctrl);
+}
+
+static void sdio_uart_start_tx(struct sdio_uart_port *port)
+{
+	if (!(port->ier & UART_IER_THRI)) {
+		port->ier |= UART_IER_THRI;
+		sdio_out(port, UART_IER, port->ier);
+	}
+}
+
+static void sdio_uart_stop_tx(struct sdio_uart_port *port)
+{
+	if (port->ier & UART_IER_THRI) {
+		port->ier &= ~UART_IER_THRI;
+		sdio_out(port, UART_IER, port->ier);
+	}
+}
+
+static void sdio_uart_stop_rx(struct sdio_uart_port *port)
+{
+	port->ier &= ~UART_IER_RLSI;
+	port->read_status_mask &= ~UART_LSR_DR;
+	sdio_out(port, UART_IER, port->ier);
+}
+
+static void sdio_uart_receive_chars(struct sdio_uart_port *port,
+				    unsigned int *status)
+{
+	unsigned int ch, flag;
+	int max_count = 256;
+
+	do {
+		ch = sdio_in(port, UART_RX);
+		flag = TTY_NORMAL;
+		port->icount.rx++;
+
+		if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
+					UART_LSR_FE | UART_LSR_OE))) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & UART_LSR_BI) {
+				*status &= ~(UART_LSR_FE | UART_LSR_PE);
+				port->icount.brk++;
+			} else if (*status & UART_LSR_PE)
+				port->icount.parity++;
+			else if (*status & UART_LSR_FE)
+				port->icount.frame++;
+			if (*status & UART_LSR_OE)
+				port->icount.overrun++;
+
+			/*
+			 * Mask off conditions which should be ignored.
+			 */
+			*status &= port->read_status_mask;
+			if (*status & UART_LSR_BI)
+				flag = TTY_BREAK;
+			else if (*status & UART_LSR_PE)
+				flag = TTY_PARITY;
+			else if (*status & UART_LSR_FE)
+				flag = TTY_FRAME;
+		}
+
+		if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
+			tty_insert_flip_char(&port->port, ch, flag);
+
+		/*
+		 * Overrun is special.  Since it's reported immediately,
+		 * it doesn't affect the current character.
+		 */
+		if (*status & ~port->ignore_status_mask & UART_LSR_OE)
+			tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
+
+		*status = sdio_in(port, UART_LSR);
+	} while ((*status & UART_LSR_DR) && (max_count-- > 0));
+
+	tty_flip_buffer_push(&port->port);
+}
+
+static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
+{
+	struct kfifo *xmit = &port->xmit_fifo;
+	int count;
+	struct tty_struct *tty;
+	u8 iobuf[16];
+	int len;
+
+	if (port->x_char) {
+		sdio_out(port, UART_TX, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	tty = tty_port_tty_get(&port->port);
+
+	if (tty == NULL || !kfifo_len(xmit) ||
+				tty->stopped || tty->hw_stopped) {
+		sdio_uart_stop_tx(port);
+		tty_kref_put(tty);
+		return;
+	}
+
+	len = kfifo_out_locked(xmit, iobuf, 16, &port->write_lock);
+	for (count = 0; count < len; count++) {
+		sdio_out(port, UART_TX, iobuf[count]);
+		port->icount.tx++;
+	}
+
+	len = kfifo_len(xmit);
+	if (len < WAKEUP_CHARS) {
+		tty_wakeup(tty);
+		if (len == 0)
+			sdio_uart_stop_tx(port);
+	}
+	tty_kref_put(tty);
+}
+
+static void sdio_uart_check_modem_status(struct sdio_uart_port *port)
+{
+	int status;
+	struct tty_struct *tty;
+
+	status = sdio_in(port, UART_MSR);
+
+	if ((status & UART_MSR_ANY_DELTA) == 0)
+		return;
+
+	if (status & UART_MSR_TERI)
+		port->icount.rng++;
+	if (status & UART_MSR_DDSR)
+		port->icount.dsr++;
+	if (status & UART_MSR_DDCD) {
+		port->icount.dcd++;
+		/* DCD raise - wake for open */
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&port->port.open_wait);
+		else {
+			/* DCD drop - hang up if tty attached */
+			tty_port_tty_hangup(&port->port, false);
+		}
+	}
+	if (status & UART_MSR_DCTS) {
+		port->icount.cts++;
+		tty = tty_port_tty_get(&port->port);
+		if (tty && C_CRTSCTS(tty)) {
+			int cts = (status & UART_MSR_CTS);
+			if (tty->hw_stopped) {
+				if (cts) {
+					tty->hw_stopped = 0;
+					sdio_uart_start_tx(port);
+					tty_wakeup(tty);
+				}
+			} else {
+				if (!cts) {
+					tty->hw_stopped = 1;
+					sdio_uart_stop_tx(port);
+				}
+			}
+		}
+		tty_kref_put(tty);
+	}
+}
+
+/*
+ * This handles the interrupt from one port.
+ */
+static void sdio_uart_irq(struct sdio_func *func)
+{
+	struct sdio_uart_port *port = sdio_get_drvdata(func);
+	unsigned int iir, lsr;
+
+	/*
+	 * In a few places sdio_uart_irq() is called directly instead of
+	 * waiting for the actual interrupt to be raised and the SDIO IRQ
+	 * thread scheduled in order to reduce latency.  However, some
+	 * interaction with the tty core may end up calling us back
+	 * (serial echo, flow control, etc.) through those same places
+	 * causing undesirable effects.  Let's stop the recursion here.
+	 */
+	if (unlikely(port->in_sdio_uart_irq == current))
+		return;
+
+	iir = sdio_in(port, UART_IIR);
+	if (iir & UART_IIR_NO_INT)
+		return;
+
+	port->in_sdio_uart_irq = current;
+	lsr = sdio_in(port, UART_LSR);
+	if (lsr & UART_LSR_DR)
+		sdio_uart_receive_chars(port, &lsr);
+	sdio_uart_check_modem_status(port);
+	if (lsr & UART_LSR_THRE)
+		sdio_uart_transmit_chars(port);
+	port->in_sdio_uart_irq = NULL;
+}
+
+static int uart_carrier_raised(struct tty_port *tport)
+{
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
+	unsigned int ret = sdio_uart_claim_func(port);
+	if (ret)	/* Missing hardware shouldn't block for carrier */
+		return 1;
+	ret = sdio_uart_get_mctrl(port);
+	sdio_uart_release_func(port);
+	if (ret & TIOCM_CAR)
+		return 1;
+	return 0;
+}
+
+/**
+ *	uart_dtr_rts		-	 port helper to set uart signals
+ *	@tport: tty port to be updated
+ *	@onoff: set to turn on DTR/RTS
+ *
+ *	Called by the tty port helpers when the modem signals need to be
+ *	adjusted during an open, close and hangup.
+ */
+
+static void uart_dtr_rts(struct tty_port *tport, int onoff)
+{
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
+	int ret = sdio_uart_claim_func(port);
+	if (ret)
+		return;
+	if (onoff == 0)
+		sdio_uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+	else
+		sdio_uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+	sdio_uart_release_func(port);
+}
+
+/**
+ *	sdio_uart_activate	-	start up hardware
+ *	@tport: tty port to activate
+ *	@tty: tty bound to this port
+ *
+ *	Activate a tty port. The port locking guarantees us this will be
+ *	run exactly once per set of opens, and if successful will see the
+ *	shutdown method run exactly once to match. Start up and shutdown are
+ *	protected from each other by the internal locking and will not run
+ *	at the same time even during a hangup event.
+ *
+ *	If we successfully start up the port we take an extra kref as we
+ *	will keep it around until shutdown when the kref is dropped.
+ */
+
+static int sdio_uart_activate(struct tty_port *tport, struct tty_struct *tty)
+{
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
+	int ret;
+
+	/*
+	 * Set the TTY IO error marker - we will only clear this
+	 * once we have successfully opened the port.
+	 */
+	set_bit(TTY_IO_ERROR, &tty->flags);
+
+	kfifo_reset(&port->xmit_fifo);
+
+	ret = sdio_uart_claim_func(port);
+	if (ret)
+		return ret;
+	ret = sdio_enable_func(port->func);
+	if (ret)
+		goto err1;
+	ret = sdio_claim_irq(port->func, sdio_uart_irq);
+	if (ret)
+		goto err2;
+
+	/*
+	 * Clear the FIFO buffers and disable them.
+	 * (they will be reenabled in sdio_change_speed())
+	 */
+	sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
+	sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
+		       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+	sdio_out(port, UART_FCR, 0);
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) sdio_in(port, UART_LSR);
+	(void) sdio_in(port, UART_RX);
+	(void) sdio_in(port, UART_IIR);
+	(void) sdio_in(port, UART_MSR);
+
+	/*
+	 * Now, initialize the UART
+	 */
+	sdio_out(port, UART_LCR, UART_LCR_WLEN8);
+
+	port->ier = UART_IER_RLSI|UART_IER_RDI|UART_IER_RTOIE|UART_IER_UUE;
+	port->mctrl = TIOCM_OUT2;
+
+	sdio_uart_change_speed(port, &tty->termios, NULL);
+
+	if (C_BAUD(tty))
+		sdio_uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR);
+
+	if (C_CRTSCTS(tty))
+		if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS))
+			tty->hw_stopped = 1;
+
+	clear_bit(TTY_IO_ERROR, &tty->flags);
+
+	/* Kick the IRQ handler once while we're still holding the host lock */
+	sdio_uart_irq(port->func);
+
+	sdio_uart_release_func(port);
+	return 0;
+
+err2:
+	sdio_disable_func(port->func);
+err1:
+	sdio_uart_release_func(port);
+	return ret;
+}
+
+/**
+ *	sdio_uart_shutdown	-	stop hardware
+ *	@tport: tty port to shut down
+ *
+ *	Deactivate a tty port. The port locking guarantees us this will be
+ *	run only if a successful matching activate already ran. The two are
+ *	protected from each other by the internal locking and will not run
+ *	at the same time even during a hangup event.
+ */
+
+static void sdio_uart_shutdown(struct tty_port *tport)
+{
+	struct sdio_uart_port *port =
+			container_of(tport, struct sdio_uart_port, port);
+	int ret;
+
+	ret = sdio_uart_claim_func(port);
+	if (ret)
+		return;
+
+	sdio_uart_stop_rx(port);
+
+	/* Disable interrupts from this port */
+	sdio_release_irq(port->func);
+	port->ier = 0;
+	sdio_out(port, UART_IER, 0);
+
+	sdio_uart_clear_mctrl(port, TIOCM_OUT2);
+
+	/* Disable break condition and FIFOs. */
+	port->lcr &= ~UART_LCR_SBC;
+	sdio_out(port, UART_LCR, port->lcr);
+	sdio_out(port, UART_FCR, UART_FCR_ENABLE_FIFO |
+				 UART_FCR_CLEAR_RCVR |
+				 UART_FCR_CLEAR_XMIT);
+	sdio_out(port, UART_FCR, 0);
+
+	sdio_disable_func(port->func);
+
+	sdio_uart_release_func(port);
+}
+
+static void sdio_uart_port_destroy(struct tty_port *tport)
+{
+	struct sdio_uart_port *port =
+		container_of(tport, struct sdio_uart_port, port);
+	kfifo_free(&port->xmit_fifo);
+	kfree(port);
+}
+
+/**
+ *	sdio_uart_install	-	install method
+ *	@driver: the driver in use (sdio_uart in our case)
+ *	@tty: the tty being bound
+ *
+ *	Look up and bind the tty and the driver together. Initialize
+ *	any needed private data (in our case the termios)
+ */
+
+static int sdio_uart_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	int idx = tty->index;
+	struct sdio_uart_port *port = sdio_uart_port_get(idx);
+	int ret = tty_standard_install(driver, tty);
+
+	if (ret == 0)
+		/* This is the ref sdio_uart_port get provided */
+		tty->driver_data = port;
+	else
+		sdio_uart_port_put(port);
+	return ret;
+}
+
+/**
+ *	sdio_uart_cleanup	-	called on the last tty kref drop
+ *	@tty: the tty being destroyed
+ *
+ *	Called asynchronously when the last reference to the tty is dropped.
+ *	We cannot destroy the tty->driver_data port kref until this point
+ */
+
+static void sdio_uart_cleanup(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	tty->driver_data = NULL;	/* Bug trap */
+	sdio_uart_port_put(port);
+}
+
+/*
+ *	Open/close/hangup is now entirely boilerplate
+ */
+
+static int sdio_uart_open(struct tty_struct *tty, struct file *filp)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	return tty_port_open(&port->port, tty, filp);
+}
+
+static void sdio_uart_close(struct tty_struct *tty, struct file * filp)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	tty_port_close(&port->port, tty, filp);
+}
+
+static void sdio_uart_hangup(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	tty_port_hangup(&port->port);
+}
+
+static int sdio_uart_write(struct tty_struct *tty, const unsigned char *buf,
+			   int count)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	int ret;
+
+	if (!port->func)
+		return -ENODEV;
+
+	ret = kfifo_in_locked(&port->xmit_fifo, buf, count, &port->write_lock);
+	if (!(port->ier & UART_IER_THRI)) {
+		int err = sdio_uart_claim_func(port);
+		if (!err) {
+			sdio_uart_start_tx(port);
+			sdio_uart_irq(port->func);
+			sdio_uart_release_func(port);
+		} else
+			ret = err;
+	}
+
+	return ret;
+}
+
+static int sdio_uart_write_room(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	return FIFO_SIZE - kfifo_len(&port->xmit_fifo);
+}
+
+static int sdio_uart_chars_in_buffer(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	return kfifo_len(&port->xmit_fifo);
+}
+
+static void sdio_uart_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+
+	port->x_char = ch;
+	if (ch && !(port->ier & UART_IER_THRI)) {
+		if (sdio_uart_claim_func(port) != 0)
+			return;
+		sdio_uart_start_tx(port);
+		sdio_uart_irq(port->func);
+		sdio_uart_release_func(port);
+	}
+}
+
+static void sdio_uart_throttle(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+
+	if (!I_IXOFF(tty) && !C_CRTSCTS(tty))
+		return;
+
+	if (sdio_uart_claim_func(port) != 0)
+		return;
+
+	if (I_IXOFF(tty)) {
+		port->x_char = STOP_CHAR(tty);
+		sdio_uart_start_tx(port);
+	}
+
+	if (C_CRTSCTS(tty))
+		sdio_uart_clear_mctrl(port, TIOCM_RTS);
+
+	sdio_uart_irq(port->func);
+	sdio_uart_release_func(port);
+}
+
+static void sdio_uart_unthrottle(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+
+	if (!I_IXOFF(tty) && !C_CRTSCTS(tty))
+		return;
+
+	if (sdio_uart_claim_func(port) != 0)
+		return;
+
+	if (I_IXOFF(tty)) {
+		if (port->x_char) {
+			port->x_char = 0;
+		} else {
+			port->x_char = START_CHAR(tty);
+			sdio_uart_start_tx(port);
+		}
+	}
+
+	if (C_CRTSCTS(tty))
+		sdio_uart_set_mctrl(port, TIOCM_RTS);
+
+	sdio_uart_irq(port->func);
+	sdio_uart_release_func(port);
+}
+
+static void sdio_uart_set_termios(struct tty_struct *tty,
+						struct ktermios *old_termios)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	unsigned int cflag = tty->termios.c_cflag;
+
+	if (sdio_uart_claim_func(port) != 0)
+		return;
+
+	sdio_uart_change_speed(port, &tty->termios, old_termios);
+
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD))
+		sdio_uart_clear_mctrl(port, TIOCM_RTS | TIOCM_DTR);
+
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
+		unsigned int mask = TIOCM_DTR;
+		if (!(cflag & CRTSCTS) || !tty_throttled(tty))
+			mask |= TIOCM_RTS;
+		sdio_uart_set_mctrl(port, mask);
+	}
+
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		sdio_uart_start_tx(port);
+	}
+
+	/* Handle turning on CRTSCTS */
+	if (!(old_termios->c_cflag & CRTSCTS) && (cflag & CRTSCTS)) {
+		if (!(sdio_uart_get_mctrl(port) & TIOCM_CTS)) {
+			tty->hw_stopped = 1;
+			sdio_uart_stop_tx(port);
+		}
+	}
+
+	sdio_uart_release_func(port);
+}
+
+static int sdio_uart_break_ctl(struct tty_struct *tty, int break_state)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	int result;
+
+	result = sdio_uart_claim_func(port);
+	if (result != 0)
+		return result;
+
+	if (break_state == -1)
+		port->lcr |= UART_LCR_SBC;
+	else
+		port->lcr &= ~UART_LCR_SBC;
+	sdio_out(port, UART_LCR, port->lcr);
+
+	sdio_uart_release_func(port);
+	return 0;
+}
+
+static int sdio_uart_tiocmget(struct tty_struct *tty)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	int result;
+
+	result = sdio_uart_claim_func(port);
+	if (!result) {
+		result = port->mctrl | sdio_uart_get_mctrl(port);
+		sdio_uart_release_func(port);
+	}
+
+	return result;
+}
+
+static int sdio_uart_tiocmset(struct tty_struct *tty,
+			      unsigned int set, unsigned int clear)
+{
+	struct sdio_uart_port *port = tty->driver_data;
+	int result;
+
+	result = sdio_uart_claim_func(port);
+	if (!result) {
+		sdio_uart_update_mctrl(port, set, clear);
+		sdio_uart_release_func(port);
+	}
+
+	return result;
+}
+
+static int sdio_uart_proc_show(struct seq_file *m, void *v)
+{
+	int i;
+
+	seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n",
+		       "", "", "");
+	for (i = 0; i < UART_NR; i++) {
+		struct sdio_uart_port *port = sdio_uart_port_get(i);
+		if (port) {
+			seq_printf(m, "%d: uart:SDIO", i);
+			if (capable(CAP_SYS_ADMIN)) {
+				seq_printf(m, " tx:%d rx:%d",
+					      port->icount.tx, port->icount.rx);
+				if (port->icount.frame)
+					seq_printf(m, " fe:%d",
+						      port->icount.frame);
+				if (port->icount.parity)
+					seq_printf(m, " pe:%d",
+						      port->icount.parity);
+				if (port->icount.brk)
+					seq_printf(m, " brk:%d",
+						      port->icount.brk);
+				if (port->icount.overrun)
+					seq_printf(m, " oe:%d",
+						      port->icount.overrun);
+				if (port->icount.cts)
+					seq_printf(m, " cts:%d",
+						      port->icount.cts);
+				if (port->icount.dsr)
+					seq_printf(m, " dsr:%d",
+						      port->icount.dsr);
+				if (port->icount.rng)
+					seq_printf(m, " rng:%d",
+						      port->icount.rng);
+				if (port->icount.dcd)
+					seq_printf(m, " dcd:%d",
+						      port->icount.dcd);
+			}
+			sdio_uart_port_put(port);
+			seq_putc(m, '\n');
+		}
+	}
+	return 0;
+}
+
+static int sdio_uart_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, sdio_uart_proc_show, NULL);
+}
+
+static const struct file_operations sdio_uart_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= sdio_uart_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static const struct tty_port_operations sdio_uart_port_ops = {
+	.dtr_rts = uart_dtr_rts,
+	.carrier_raised = uart_carrier_raised,
+	.shutdown = sdio_uart_shutdown,
+	.activate = sdio_uart_activate,
+	.destruct = sdio_uart_port_destroy,
+};
+
+static const struct tty_operations sdio_uart_ops = {
+	.open			= sdio_uart_open,
+	.close			= sdio_uart_close,
+	.write			= sdio_uart_write,
+	.write_room		= sdio_uart_write_room,
+	.chars_in_buffer	= sdio_uart_chars_in_buffer,
+	.send_xchar		= sdio_uart_send_xchar,
+	.throttle		= sdio_uart_throttle,
+	.unthrottle		= sdio_uart_unthrottle,
+	.set_termios		= sdio_uart_set_termios,
+	.hangup			= sdio_uart_hangup,
+	.break_ctl		= sdio_uart_break_ctl,
+	.tiocmget		= sdio_uart_tiocmget,
+	.tiocmset		= sdio_uart_tiocmset,
+	.install		= sdio_uart_install,
+	.cleanup		= sdio_uart_cleanup,
+	.proc_fops		= &sdio_uart_proc_fops,
+};
+
+static struct tty_driver *sdio_uart_tty_driver;
+
+static int sdio_uart_probe(struct sdio_func *func,
+			   const struct sdio_device_id *id)
+{
+	struct sdio_uart_port *port;
+	int ret;
+
+	port = kzalloc(sizeof(struct sdio_uart_port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	if (func->class == SDIO_CLASS_UART) {
+		pr_warn("%s: need info on UART class basic setup\n",
+			sdio_func_id(func));
+		kfree(port);
+		return -ENOSYS;
+	} else if (func->class == SDIO_CLASS_GPS) {
+		/*
+		 * We need tuple 0x91.  It contains SUBTPL_SIOREG
+		 * and SUBTPL_RCVCAPS.
+		 */
+		struct sdio_func_tuple *tpl;
+		for (tpl = func->tuples; tpl; tpl = tpl->next) {
+			if (tpl->code != 0x91)
+				continue;
+			if (tpl->size < 10)
+				continue;
+			if (tpl->data[1] == 0)  /* SUBTPL_SIOREG */
+				break;
+		}
+		if (!tpl) {
+			pr_warn("%s: can't find tuple 0x91 subtuple 0 (SUBTPL_SIOREG) for GPS class\n",
+				sdio_func_id(func));
+			kfree(port);
+			return -EINVAL;
+		}
+		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);
+		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;
+		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 {
+		kfree(port);
+		return -EINVAL;
+	}
+
+	port->func = func;
+	sdio_set_drvdata(func, port);
+	tty_port_init(&port->port);
+	port->port.ops = &sdio_uart_port_ops;
+
+	ret = sdio_uart_add_port(port);
+	if (ret) {
+		kfree(port);
+	} else {
+		struct device *dev;
+		dev = tty_port_register_device(&port->port,
+				sdio_uart_tty_driver, port->index, &func->dev);
+		if (IS_ERR(dev)) {
+			sdio_uart_port_remove(port);
+			ret = PTR_ERR(dev);
+		}
+	}
+
+	return ret;
+}
+
+static void sdio_uart_remove(struct sdio_func *func)
+{
+	struct sdio_uart_port *port = sdio_get_drvdata(func);
+
+	tty_unregister_device(sdio_uart_tty_driver, port->index);
+	sdio_uart_port_remove(port);
+}
+
+static const struct sdio_device_id sdio_uart_ids[] = {
+	{ SDIO_DEVICE_CLASS(SDIO_CLASS_UART)		},
+	{ SDIO_DEVICE_CLASS(SDIO_CLASS_GPS)		},
+	{ /* end: all zeroes */				},
+};
+
+MODULE_DEVICE_TABLE(sdio, sdio_uart_ids);
+
+static struct sdio_driver sdio_uart_driver = {
+	.probe		= sdio_uart_probe,
+	.remove		= sdio_uart_remove,
+	.name		= "sdio_uart",
+	.id_table	= sdio_uart_ids,
+};
+
+static int __init sdio_uart_init(void)
+{
+	int ret;
+	struct tty_driver *tty_drv;
+
+	sdio_uart_tty_driver = tty_drv = alloc_tty_driver(UART_NR);
+	if (!tty_drv)
+		return -ENOMEM;
+
+	tty_drv->driver_name = "sdio_uart";
+	tty_drv->name =   "ttySDIO";
+	tty_drv->major = 0;  /* dynamically allocated */
+	tty_drv->minor_start = 0;
+	tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
+	tty_drv->subtype = SERIAL_TYPE_NORMAL;
+	tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_drv->init_termios = tty_std_termios;
+	tty_drv->init_termios.c_cflag = B4800 | CS8 | CREAD | HUPCL | CLOCAL;
+	tty_drv->init_termios.c_ispeed = 4800;
+	tty_drv->init_termios.c_ospeed = 4800;
+	tty_set_operations(tty_drv, &sdio_uart_ops);
+
+	ret = tty_register_driver(tty_drv);
+	if (ret)
+		goto err1;
+
+	ret = sdio_register_driver(&sdio_uart_driver);
+	if (ret)
+		goto err2;
+
+	return 0;
+
+err2:
+	tty_unregister_driver(tty_drv);
+err1:
+	put_tty_driver(tty_drv);
+	return ret;
+}
+
+static void __exit sdio_uart_exit(void)
+{
+	sdio_unregister_driver(&sdio_uart_driver);
+	tty_unregister_driver(sdio_uart_tty_driver);
+	put_tty_driver(sdio_uart_tty_driver);
+}
+
+module_init(sdio_uart_init);
+module_exit(sdio_uart_exit);
+
+MODULE_AUTHOR("Nicolas Pitre");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/sd_ops.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/sd_ops.c
--- linux-libre-4.9-gnu/drivers/mmc/core/sd_ops.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/sd_ops.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,8 +27,8 @@ int mmc_app_cmd(struct mmc_host *host, s
 	int err;
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!host);
-	BUG_ON(card && (card->host != host));
+	if (WARN_ON(card && card->host != host))
+		return -EINVAL;
 
 	cmd.opcode = MMC_APP_CMD;
 
@@ -72,8 +72,8 @@ int mmc_wait_for_app_cmd(struct mmc_host
 
 	int i, err;
 
-	BUG_ON(!cmd);
-	BUG_ON(retries < 0);
+	if (retries < 0)
+		retries = MMC_CMD_RETRIES;
 
 	err = -EIO;
 
@@ -122,9 +122,6 @@ int mmc_app_set_bus_width(struct mmc_car
 {
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-
 	cmd.opcode = SD_APP_SET_BUS_WIDTH;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 
@@ -147,8 +144,6 @@ int mmc_send_app_op_cond(struct mmc_host
 	struct mmc_command cmd = {0};
 	int i, err = 0;
 
-	BUG_ON(!host);
-
 	cmd.opcode = SD_APP_OP_COND;
 	if (mmc_host_is_spi(host))
 		cmd.arg = ocr & (1 << 30); /* SPI only defines one bit */
@@ -224,9 +219,6 @@ int mmc_send_relative_addr(struct mmc_ho
 	int err;
 	struct mmc_command cmd = {0};
 
-	BUG_ON(!host);
-	BUG_ON(!rca);
-
 	cmd.opcode = SD_SEND_RELATIVE_ADDR;
 	cmd.arg = 0;
 	cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
@@ -249,10 +241,6 @@ int mmc_app_send_scr(struct mmc_card *ca
 	struct scatterlist sg;
 	void *data_buf;
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-	BUG_ON(!scr);
-
 	/* NOTE: caller guarantees scr is heap-allocated */
 
 	err = mmc_app_cmd(card->host, card);
@@ -307,9 +295,6 @@ int mmc_sd_switch(struct mmc_card *card,
 	struct mmc_data data = {0};
 	struct scatterlist sg;
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-
 	/* NOTE: caller guarantees resp is heap-allocated */
 
 	mode = !!mode;
@@ -352,10 +337,6 @@ int mmc_app_sd_status(struct mmc_card *c
 	struct mmc_data data = {0};
 	struct scatterlist sg;
 
-	BUG_ON(!card);
-	BUG_ON(!card->host);
-	BUG_ON(!ssr);
-
 	/* NOTE: caller guarantees ssr is heap-allocated */
 
 	err = mmc_app_cmd(card->host, card);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/core/slot-gpio.c linux-libre-4.10-rc8-gnu/drivers/mmc/core/slot-gpio.c
--- linux-libre-4.9-gnu/drivers/mmc/core/slot-gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/core/slot-gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -258,6 +258,14 @@ int mmc_gpiod_request_cd(struct mmc_host
 }
 EXPORT_SYMBOL(mmc_gpiod_request_cd);
 
+bool mmc_can_gpio_cd(struct mmc_host *host)
+{
+	struct mmc_gpio *ctx = host->slot.handler_priv;
+
+	return ctx->cd_gpio ? true : false;
+}
+EXPORT_SYMBOL(mmc_can_gpio_cd);
+
 /**
  * mmc_gpiod_request_ro - request a gpio descriptor for write protection
  * @host: mmc host
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/android-goldfish.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/android-goldfish.c
--- linux-libre-4.9-gnu/drivers/mmc/host/android-goldfish.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/android-goldfish.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,7 @@
 
 #include <asm/types.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define DRIVER_NAME "goldfish_mmc"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/davinci_mmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/davinci_mmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/davinci_mmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/davinci_mmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,6 +35,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/mmc/slot-gpio.h>
 
 #include <linux/platform_data/mmc-davinci.h>
 
@@ -1029,9 +1030,10 @@ static int mmc_davinci_get_cd(struct mmc
 	struct platform_device *pdev = to_platform_device(mmc->parent);
 	struct davinci_mmc_config *config = pdev->dev.platform_data;
 
-	if (!config || !config->get_cd)
-		return -ENOSYS;
-	return config->get_cd(pdev->id);
+	if (config && config->get_cd)
+		return config->get_cd(pdev->id);
+
+	return mmc_gpio_get_cd(mmc);
 }
 
 static int mmc_davinci_get_ro(struct mmc_host *mmc)
@@ -1039,9 +1041,10 @@ static int mmc_davinci_get_ro(struct mmc
 	struct platform_device *pdev = to_platform_device(mmc->parent);
 	struct davinci_mmc_config *config = pdev->dev.platform_data;
 
-	if (!config || !config->get_ro)
-		return -ENOSYS;
-	return config->get_ro(pdev->id);
+	if (config && config->get_ro)
+		return config->get_ro(pdev->id);
+
+	return mmc_gpio_get_ro(mmc);
 }
 
 static void mmc_davinci_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -1159,49 +1162,53 @@ static const struct of_device_id davinci
 };
 MODULE_DEVICE_TABLE(of, davinci_mmc_dt_ids);
 
-static struct davinci_mmc_config
-	*mmc_parse_pdata(struct platform_device *pdev)
+static int mmc_davinci_parse_pdata(struct mmc_host *mmc)
 {
-	struct device_node *np;
+	struct platform_device *pdev = to_platform_device(mmc->parent);
 	struct davinci_mmc_config *pdata = pdev->dev.platform_data;
-	const struct of_device_id *match =
-		of_match_device(davinci_mmc_dt_ids, &pdev->dev);
-	u32 data;
+	struct mmc_davinci_host *host;
+	int ret;
 
-	np = pdev->dev.of_node;
-	if (!np)
-		return pdata;
+	if (!pdata)
+		return -EINVAL;
 
-	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-	if (!pdata) {
-		dev_err(&pdev->dev, "Failed to allocate memory for struct davinci_mmc_config\n");
-		goto nodata;
-	}
+	host = mmc_priv(mmc);
+	if (!host)
+		return -EINVAL;
 
-	if (match)
-		pdev->id_entry = match->data;
+	if (pdata && pdata->nr_sg)
+		host->nr_sg = pdata->nr_sg - 1;
 
-	if (of_property_read_u32(np, "max-frequency", &pdata->max_freq))
-		dev_info(&pdev->dev, "'max-frequency' property not specified, defaulting to 25MHz\n");
+	if (pdata && (pdata->wires == 4 || pdata->wires == 0))
+		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
-	of_property_read_u32(np, "bus-width", &data);
-	switch (data) {
-	case 1:
-	case 4:
-	case 8:
-		pdata->wires = data;
-		break;
-	default:
-		pdata->wires = 1;
-		dev_info(&pdev->dev, "Unsupported buswidth, defaulting to 1 bit\n");
-	}
-nodata:
-	return pdata;
+	if (pdata && (pdata->wires == 8))
+		mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
+
+	mmc->f_min = 312500;
+	mmc->f_max = 25000000;
+	if (pdata && pdata->max_freq)
+		mmc->f_max = pdata->max_freq;
+	if (pdata && pdata->caps)
+		mmc->caps |= pdata->caps;
+
+	/* Register a cd gpio, if there is not one, enable polling */
+	ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL);
+	if (ret == -EPROBE_DEFER)
+		return ret;
+	else if (ret)
+		mmc->caps |= MMC_CAP_NEEDS_POLL;
+
+	ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL);
+	if (ret == -EPROBE_DEFER)
+		return ret;
+
+	return 0;
 }
 
 static int __init davinci_mmcsd_probe(struct platform_device *pdev)
 {
-	struct davinci_mmc_config *pdata = NULL;
+	const struct of_device_id *match;
 	struct mmc_davinci_host *host = NULL;
 	struct mmc_host *mmc = NULL;
 	struct resource *r, *mem = NULL;
@@ -1209,12 +1216,6 @@ static int __init davinci_mmcsd_probe(st
 	size_t mem_size;
 	const struct platform_device_id *id_entry;
 
-	pdata = mmc_parse_pdata(pdev);
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "Couldn't get platform data\n");
-		return -ENOENT;
-	}
-
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r)
 		return -ENODEV;
@@ -1253,14 +1254,28 @@ static int __init davinci_mmcsd_probe(st
 
 	host->mmc_input_clk = clk_get_rate(host->clk);
 
-	init_mmcsd_host(host);
-
-	if (pdata->nr_sg)
-		host->nr_sg = pdata->nr_sg - 1;
+	match = of_match_device(davinci_mmc_dt_ids, &pdev->dev);
+	if (match) {
+		pdev->id_entry = match->data;
+		ret = mmc_of_parse(mmc);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"could not parse of data: %d\n", ret);
+			goto parse_fail;
+		}
+	} else {
+		ret = mmc_davinci_parse_pdata(mmc);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"could not parse platform data: %d\n", ret);
+			goto parse_fail;
+	}	}
 
 	if (host->nr_sg > MAX_NR_SG || !host->nr_sg)
 		host->nr_sg = MAX_NR_SG;
 
+	init_mmcsd_host(host);
+
 	host->use_dma = use_dma;
 	host->mmc_irq = irq;
 	host->sdio_irq = platform_get_irq(pdev, 1);
@@ -1273,27 +1288,13 @@ static int __init davinci_mmcsd_probe(st
 			host->use_dma = 0;
 	}
 
-	/* REVISIT:  someday, support IRQ-driven card detection.  */
-	mmc->caps |= MMC_CAP_NEEDS_POLL;
 	mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
 
-	if (pdata && (pdata->wires == 4 || pdata->wires == 0))
-		mmc->caps |= MMC_CAP_4_BIT_DATA;
-
-	if (pdata && (pdata->wires == 8))
-		mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
-
 	id_entry = platform_get_device_id(pdev);
 	if (id_entry)
 		host->version = id_entry->driver_data;
 
 	mmc->ops = &mmc_davinci_ops;
-	mmc->f_min = 312500;
-	mmc->f_max = 25000000;
-	if (pdata && pdata->max_freq)
-		mmc->f_max = pdata->max_freq;
-	if (pdata && pdata->caps)
-		mmc->caps |= pdata->caps;
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
 	/* With no iommu coalescing pages, each phys_seg is a hw_seg.
@@ -1354,6 +1355,7 @@ mmc_add_host_fail:
 	mmc_davinci_cpufreq_deregister(host);
 cpu_freq_fail:
 	davinci_release_dma_channels(host);
+parse_fail:
 dma_probe_defer:
 	clk_disable_unprepare(host->clk);
 clk_prepare_enable_fail:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 #define DW_MCI_DMA_THRESHOLD	16
 
 #define DW_MCI_FREQ_MAX	200000000	/* unit: HZ */
-#define DW_MCI_FREQ_MIN	400000		/* unit: HZ */
+#define DW_MCI_FREQ_MIN	100000		/* unit: HZ */
 
 #define IDMAC_INT_CLR		(SDMMC_IDMAC_INT_AI | SDMMC_IDMAC_INT_NI | \
 				 SDMMC_IDMAC_INT_CES | SDMMC_IDMAC_INT_DU | \
@@ -165,12 +165,14 @@ static const struct file_operations dw_m
 
 static int dw_mci_regs_show(struct seq_file *s, void *v)
 {
-	seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS);
-	seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS);
-	seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD);
-	seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL);
-	seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK);
-	seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA);
+	struct dw_mci *host = s->private;
+
+	seq_printf(s, "STATUS:\t0x%08x\n", mci_readl(host, STATUS));
+	seq_printf(s, "RINTSTS:\t0x%08x\n", mci_readl(host, RINTSTS));
+	seq_printf(s, "CMD:\t0x%08x\n", mci_readl(host, CMD));
+	seq_printf(s, "CTRL:\t0x%08x\n", mci_readl(host, CTRL));
+	seq_printf(s, "INTMASK:\t0x%08x\n", mci_readl(host, INTMASK));
+	seq_printf(s, "CLKENA:\t0x%08x\n", mci_readl(host, CLKENA));
 
 	return 0;
 }
@@ -234,7 +236,6 @@ static void mci_send_cmd(struct dw_mci_s
 
 static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 {
-	struct mmc_data	*data;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci *host = slot->host;
 	u32 cmdr;
@@ -289,10 +290,9 @@ static u32 dw_mci_prepare_command(struct
 	if (cmd->flags & MMC_RSP_CRC)
 		cmdr |= SDMMC_CMD_RESP_CRC;
 
-	data = cmd->data;
-	if (data) {
+	if (cmd->data) {
 		cmdr |= SDMMC_CMD_DAT_EXP;
-		if (data->flags & MMC_DATA_WRITE)
+		if (cmd->data->flags & MMC_DATA_WRITE)
 			cmdr |= SDMMC_CMD_DAT_WR;
 	}
 
@@ -335,6 +335,9 @@ static u32 dw_mci_prep_stop_abort(struct
 	cmdr = stop->opcode | SDMMC_CMD_STOP |
 		SDMMC_CMD_RESP_CRC | SDMMC_CMD_RESP_EXP;
 
+	if (!test_bit(DW_MMC_CARD_NO_USE_HOLD, &host->cur_slot->flags))
+		cmdr |= SDMMC_CMD_USE_HOLD_REG;
+
 	return cmdr;
 }
 
@@ -380,7 +383,7 @@ static void dw_mci_start_command(struct
 
 static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
 {
-	struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
+	struct mmc_command *stop = &host->stop_abort;
 
 	dw_mci_start_command(host, stop, host->stop_cmdr);
 }
@@ -409,12 +412,13 @@ static void dw_mci_dma_cleanup(struct dw
 {
 	struct mmc_data *data = host->data;
 
-	if (data)
-		if (!data->host_cookie)
-			dma_unmap_sg(host->dev,
-				     data->sg,
-				     data->sg_len,
-				     dw_mci_get_dma_dir(data));
+	if (data && data->host_cookie == COOKIE_MAPPED) {
+		dma_unmap_sg(host->dev,
+			     data->sg,
+			     data->sg_len,
+			     dw_mci_get_dma_dir(data));
+		data->host_cookie = COOKIE_UNMAPPED;
+	}
 }
 
 static void dw_mci_idmac_reset(struct dw_mci *host)
@@ -612,7 +616,7 @@ static inline int dw_mci_prepare_desc64(
 	return 0;
 err_own_bit:
 	/* restore the descriptor chain as it's polluted */
-	dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n");
+	dev_dbg(host->dev, "descriptor is still owned by IDMAC.\n");
 	memset(host->sg_cpu, 0, DESC_RING_BUF_SZ);
 	dw_mci_idmac_init(host);
 	return -EINVAL;
@@ -688,7 +692,7 @@ static inline int dw_mci_prepare_desc32(
 	return 0;
 err_own_bit:
 	/* restore the descriptor chain as it's polluted */
-	dev_dbg(host->dev, "desciptor is still owned by IDMAC.\n");
+	dev_dbg(host->dev, "descriptor is still owned by IDMAC.\n");
 	memset(host->sg_cpu, 0, DESC_RING_BUF_SZ);
 	dw_mci_idmac_init(host);
 	return -EINVAL;
@@ -845,13 +849,13 @@ static const struct dw_mci_dma_ops dw_mc
 
 static int dw_mci_pre_dma_transfer(struct dw_mci *host,
 				   struct mmc_data *data,
-				   bool next)
+				   int cookie)
 {
 	struct scatterlist *sg;
 	unsigned int i, sg_len;
 
-	if (!next && data->host_cookie)
-		return data->host_cookie;
+	if (data->host_cookie == COOKIE_PRE_MAPPED)
+		return data->sg_len;
 
 	/*
 	 * We don't do DMA on "complex" transfers, i.e. with
@@ -876,15 +880,13 @@ static int dw_mci_pre_dma_transfer(struc
 	if (sg_len == 0)
 		return -EINVAL;
 
-	if (next)
-		data->host_cookie = sg_len;
+	data->host_cookie = cookie;
 
 	return sg_len;
 }
 
 static void dw_mci_pre_req(struct mmc_host *mmc,
-			   struct mmc_request *mrq,
-			   bool is_first_req)
+			   struct mmc_request *mrq)
 {
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct mmc_data *data = mrq->data;
@@ -892,13 +894,12 @@ static void dw_mci_pre_req(struct mmc_ho
 	if (!slot->host->use_dma || !data)
 		return;
 
-	if (data->host_cookie) {
-		data->host_cookie = 0;
-		return;
-	}
+	/* This data might be unmapped at this time */
+	data->host_cookie = COOKIE_UNMAPPED;
 
-	if (dw_mci_pre_dma_transfer(slot->host, mrq->data, 1) < 0)
-		data->host_cookie = 0;
+	if (dw_mci_pre_dma_transfer(slot->host, mrq->data,
+				COOKIE_PRE_MAPPED) < 0)
+		data->host_cookie = COOKIE_UNMAPPED;
 }
 
 static void dw_mci_post_req(struct mmc_host *mmc,
@@ -911,12 +912,12 @@ static void dw_mci_post_req(struct mmc_h
 	if (!slot->host->use_dma || !data)
 		return;
 
-	if (data->host_cookie)
+	if (data->host_cookie != COOKIE_UNMAPPED)
 		dma_unmap_sg(slot->host->dev,
 			     data->sg,
 			     data->sg_len,
 			     dw_mci_get_dma_dir(data));
-	data->host_cookie = 0;
+	data->host_cookie = COOKIE_UNMAPPED;
 }
 
 static void dw_mci_adjust_fifoth(struct dw_mci *host, struct mmc_data *data)
@@ -1022,7 +1023,7 @@ static int dw_mci_submit_data_dma(struct
 	if (!host->use_dma)
 		return -ENODEV;
 
-	sg_len = dw_mci_pre_dma_transfer(host, data, 0);
+	sg_len = dw_mci_pre_dma_transfer(host, data, COOKIE_MAPPED);
 	if (sg_len < 0) {
 		host->dma_ops->stop(host);
 		return sg_len;
@@ -1175,13 +1176,24 @@ static void dw_mci_setup_bus(struct dw_m
 
 		div = (host->bus_hz != clock) ? DIV_ROUND_UP(div, 2) : 0;
 
-		if (clock != slot->__clk_old || force_clkinit)
+		if ((clock != slot->__clk_old &&
+			!test_bit(DW_MMC_CARD_NEEDS_POLL, &slot->flags)) ||
+			force_clkinit) {
 			dev_info(&slot->mmc->class_dev,
 				 "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ div = %d)\n",
 				 slot->id, host->bus_hz, clock,
 				 div ? ((host->bus_hz / div) >> 1) :
 				 host->bus_hz, div);
 
+			/*
+			 * If card is polling, display the message only
+			 * one time at boot time.
+			 */
+			if (slot->mmc->caps & MMC_CAP_NEEDS_POLL &&
+					slot->mmc->f_min == clock)
+				set_bit(DW_MMC_CARD_NEEDS_POLL, &slot->flags);
+		}
+
 		/* disable clock */
 		mci_writel(host, CLKENA, 0);
 		mci_writel(host, CLKSRC, 0);
@@ -1273,10 +1285,7 @@ static void __dw_mci_start_request(struc
 		spin_unlock_irqrestore(&host->irq_lock, irqflags);
 	}
 
-	if (mrq->stop)
-		host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
-	else
-		host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
+	host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
 }
 
 static void dw_mci_start_request(struct dw_mci *host,
@@ -1527,22 +1536,34 @@ static int dw_mci_get_cd(struct mmc_host
 	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
-	if ((mmc->caps & MMC_CAP_NEEDS_POLL) || !mmc_card_is_removable(mmc))
+	if (((mmc->caps & MMC_CAP_NEEDS_POLL)
+				|| !mmc_card_is_removable(mmc))) {
 		present = 1;
-	else if (gpio_cd >= 0)
+
+		if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) {
+			if (mmc->caps & MMC_CAP_NEEDS_POLL) {
+				dev_info(&mmc->class_dev,
+					"card is polling.\n");
+			} else {
+				dev_info(&mmc->class_dev,
+					"card is non-removable.\n");
+			}
+			set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+		}
+
+		return present;
+	} else if (gpio_cd >= 0)
 		present = gpio_cd;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
 	spin_lock_bh(&host->lock);
-	if (present) {
-		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+	if (present && !test_and_set_bit(DW_MMC_CARD_PRESENT, &slot->flags))
 		dev_dbg(&mmc->class_dev, "card is present\n");
-	} else {
-		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
+	else if (!present &&
+			!test_and_clear_bit(DW_MMC_CARD_PRESENT, &slot->flags))
 		dev_dbg(&mmc->class_dev, "card is not present\n");
-	}
 	spin_unlock_bh(&host->lock);
 
 	return present;
@@ -1889,8 +1910,7 @@ static void dw_mci_tasklet_func(unsigned
 			if (test_and_clear_bit(EVENT_DATA_ERROR,
 					       &host->pending_events)) {
 				dw_mci_stop_dma(host);
-				if (data->stop ||
-				    !(host->data_status & (SDMMC_INT_DRTO |
+				if (!(host->data_status & (SDMMC_INT_DRTO |
 							   SDMMC_INT_EBE)))
 					send_stop_abort(host, data);
 				state = STATE_DATA_ERROR;
@@ -1926,8 +1946,7 @@ static void dw_mci_tasklet_func(unsigned
 			if (test_and_clear_bit(EVENT_DATA_ERROR,
 					       &host->pending_events)) {
 				dw_mci_stop_dma(host);
-				if (data->stop ||
-				    !(host->data_status & (SDMMC_INT_DRTO |
+				if (!(host->data_status & (SDMMC_INT_DRTO |
 							   SDMMC_INT_EBE)))
 					send_stop_abort(host, data);
 				state = STATE_DATA_ERROR;
@@ -2003,7 +2022,7 @@ static void dw_mci_tasklet_func(unsigned
 			host->cmd = NULL;
 			host->data = NULL;
 
-			if (mrq->stop)
+			if (!mrq->sbc && mrq->stop)
 				dw_mci_command_complete(host, mrq->stop);
 			else
 				host->cmd_status = 0;
@@ -2615,6 +2634,8 @@ static int dw_mci_init_slot(struct dw_mc
 		mmc->f_min = DW_MCI_FREQ_MIN;
 		mmc->f_max = DW_MCI_FREQ_MAX;
 	} else {
+		dev_info(host->dev,
+			"'clock-freq-min-max' property was deprecated.\n");
 		mmc->f_min = freq[0];
 		mmc->f_max = freq[1];
 	}
@@ -3267,26 +3288,46 @@ EXPORT_SYMBOL(dw_mci_remove);
 
 
 
-#ifdef CONFIG_PM_SLEEP
-/*
- * TODO: we should probably disable the clock to the card in the suspend path.
- */
-int dw_mci_suspend(struct dw_mci *host)
+#ifdef CONFIG_PM
+int dw_mci_runtime_suspend(struct device *dev)
 {
+	struct dw_mci *host = dev_get_drvdata(dev);
+
 	if (host->use_dma && host->dma_ops->exit)
 		host->dma_ops->exit(host);
 
+	clk_disable_unprepare(host->ciu_clk);
+
+	if (host->cur_slot &&
+	    (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+	     !mmc_card_is_removable(host->cur_slot->mmc)))
+		clk_disable_unprepare(host->biu_clk);
+
 	return 0;
 }
-EXPORT_SYMBOL(dw_mci_suspend);
+EXPORT_SYMBOL(dw_mci_runtime_suspend);
 
-int dw_mci_resume(struct dw_mci *host)
+int dw_mci_runtime_resume(struct device *dev)
 {
-	int i, ret;
+	int i, ret = 0;
+	struct dw_mci *host = dev_get_drvdata(dev);
+
+	if (host->cur_slot &&
+	    (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+	     !mmc_card_is_removable(host->cur_slot->mmc))) {
+		ret = clk_prepare_enable(host->biu_clk);
+		if (ret)
+			return ret;
+	}
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret)
+		goto err;
 
 	if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
+		clk_disable_unprepare(host->ciu_clk);
 		ret = -ENODEV;
-		return ret;
+		goto err;
 	}
 
 	if (host->use_dma && host->dma_ops->init)
@@ -3296,8 +3337,8 @@ int dw_mci_resume(struct dw_mci *host)
 	 * Restore the initial value at FIFOTH register
 	 * And Invalidate the prev_blksz with zero
 	 */
-	mci_writel(host, FIFOTH, host->fifoth_val);
-	host->prev_blksz = 0;
+	 mci_writel(host, FIFOTH, host->fifoth_val);
+	 host->prev_blksz = 0;
 
 	/* Put in max timeout */
 	mci_writel(host, TMOUT, 0xFFFFFFFF);
@@ -3313,19 +3354,28 @@ int dw_mci_resume(struct dw_mci *host)
 
 		if (!slot)
 			continue;
-		if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+		if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER)
 			dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
-			dw_mci_setup_bus(slot, true);
-		}
+
+		/* Force setup bus to guarantee available clock output */
+		dw_mci_setup_bus(slot, true);
 	}
 
 	/* Now that slots are all setup, we can enable card detect */
 	dw_mci_enable_cd(host);
 
 	return 0;
+
+err:
+	if (host->cur_slot &&
+	    (mmc_can_gpio_cd(host->cur_slot->mmc) ||
+	     !mmc_card_is_removable(host->cur_slot->mmc)))
+		clk_disable_unprepare(host->biu_clk);
+
+	return ret;
 }
-EXPORT_SYMBOL(dw_mci_resume);
-#endif /* CONFIG_PM_SLEEP */
+EXPORT_SYMBOL(dw_mci_runtime_resume);
+#endif /* CONFIG_PM */
 
 static int __init dw_mci_init(void)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-exynos.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-exynos.c
--- linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-exynos.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-exynos.c	2017-02-12 16:03:20.000000000 -0500
@@ -17,6 +17,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include "dw_mmc.h"
@@ -161,20 +162,13 @@ static void dw_mci_exynos_set_clksel_tim
 		set_bit(DW_MMC_CARD_NO_USE_HOLD, &host->cur_slot->flags);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int dw_mci_exynos_suspend(struct device *dev)
-{
-	struct dw_mci *host = dev_get_drvdata(dev);
-
-	return dw_mci_suspend(host);
-}
-
-static int dw_mci_exynos_resume(struct device *dev)
+#ifdef CONFIG_PM
+static int dw_mci_exynos_runtime_resume(struct device *dev)
 {
 	struct dw_mci *host = dev_get_drvdata(dev);
 
 	dw_mci_exynos_config_smu(host);
-	return dw_mci_resume(host);
+	return dw_mci_runtime_resume(dev);
 }
 
 /**
@@ -211,10 +205,8 @@ static int dw_mci_exynos_resume_noirq(st
 	return 0;
 }
 #else
-#define dw_mci_exynos_suspend		NULL
-#define dw_mci_exynos_resume		NULL
 #define dw_mci_exynos_resume_noirq	NULL
-#endif /* CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */
 
 static void dw_mci_exynos_config_hs400(struct dw_mci *host, u32 timing)
 {
@@ -524,14 +516,42 @@ static int dw_mci_exynos_probe(struct pl
 {
 	const struct dw_mci_drv_data *drv_data;
 	const struct of_device_id *match;
+	int ret;
 
 	match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
 	drv_data = match->data;
-	return dw_mci_pltfm_register(pdev, drv_data);
+
+	pm_runtime_get_noresume(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	ret = dw_mci_pltfm_register(pdev, drv_data);
+	if (ret) {
+		pm_runtime_disable(&pdev->dev);
+		pm_runtime_set_suspended(&pdev->dev);
+		pm_runtime_put_noidle(&pdev->dev);
+
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dw_mci_exynos_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	return dw_mci_pltfm_remove(pdev);
 }
 
 static const struct dev_pm_ops dw_mci_exynos_pmops = {
-	SET_SYSTEM_SLEEP_PM_OPS(dw_mci_exynos_suspend, dw_mci_exynos_resume)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+			   dw_mci_exynos_runtime_resume,
+			   NULL)
 	.resume_noirq = dw_mci_exynos_resume_noirq,
 	.thaw_noirq = dw_mci_exynos_resume_noirq,
 	.restore_noirq = dw_mci_exynos_resume_noirq,
@@ -539,7 +559,7 @@ static const struct dev_pm_ops dw_mci_ex
 
 static struct platform_driver dw_mci_exynos_pltfm_driver = {
 	.probe		= dw_mci_exynos_probe,
-	.remove		= dw_mci_pltfm_remove,
+	.remove		= dw_mci_exynos_remove,
 	.driver		= {
 		.name		= "dwmmc_exynos",
 		.of_match_table	= dw_mci_exynos_match,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc.h linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc.h
--- linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc.h	2017-02-12 16:03:20.000000000 -0500
@@ -234,9 +234,9 @@
 
 extern int dw_mci_probe(struct dw_mci *host);
 extern void dw_mci_remove(struct dw_mci *host);
-#ifdef CONFIG_PM_SLEEP
-extern int dw_mci_suspend(struct dw_mci *host);
-extern int dw_mci_resume(struct dw_mci *host);
+#ifdef CONFIG_PM
+extern int dw_mci_runtime_suspend(struct device *device);
+extern int dw_mci_runtime_resume(struct device *device);
 #endif
 
 /**
@@ -272,6 +272,7 @@ struct dw_mci_slot {
 #define DW_MMC_CARD_NEED_INIT	1
 #define DW_MMC_CARD_NO_LOW_PWR	2
 #define DW_MMC_CARD_NO_USE_HOLD 3
+#define DW_MMC_CARD_NEEDS_POLL	4
 	int			id;
 	int			sdio_id;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-k3.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-k3.c
--- linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-k3.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-k3.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
@@ -162,35 +163,13 @@ static int dw_mci_k3_probe(struct platfo
 	return dw_mci_pltfm_register(pdev, drv_data);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int dw_mci_k3_suspend(struct device *dev)
-{
-	struct dw_mci *host = dev_get_drvdata(dev);
-	int ret;
-
-	ret = dw_mci_suspend(host);
-	if (!ret)
-		clk_disable_unprepare(host->ciu_clk);
-
-	return ret;
-}
-
-static int dw_mci_k3_resume(struct device *dev)
-{
-	struct dw_mci *host = dev_get_drvdata(dev);
-	int ret;
-
-	ret = clk_prepare_enable(host->ciu_clk);
-	if (ret) {
-		dev_err(host->dev, "failed to enable ciu clock\n");
-		return ret;
-	}
-
-	return dw_mci_resume(host);
-}
-#endif /* CONFIG_PM_SLEEP */
-
-static SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+static const struct dev_pm_ops dw_mci_k3_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+			   dw_mci_runtime_resume,
+			   NULL)
+};
 
 static struct platform_driver dw_mci_k3_pltfm_driver = {
 	.probe		= dw_mci_k3_probe,
@@ -198,7 +177,7 @@ static struct platform_driver dw_mci_k3_
 	.driver		= {
 		.name		= "dwmmc_k3",
 		.of_match_table	= dw_mci_k3_match,
-		.pm		= &dw_mci_k3_pmops,
+		.pm		= &dw_mci_k3_dev_pm_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-pci.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-pci.c
--- linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/pci.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
@@ -79,25 +80,13 @@ static void dw_mci_pci_remove(struct pci
 	dw_mci_remove(host);
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int dw_mci_pci_suspend(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct dw_mci *host = pci_get_drvdata(pdev);
-
-	return dw_mci_suspend(host);
-}
-
-static int dw_mci_pci_resume(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	struct dw_mci *host = pci_get_drvdata(pdev);
-
-	return dw_mci_resume(host);
-}
-#endif /* CONFIG_PM_SLEEP */
-
-static SIMPLE_DEV_PM_OPS(dw_mci_pci_pmops, dw_mci_pci_suspend, dw_mci_pci_resume);
+static const struct dev_pm_ops dw_mci_pci_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+			   dw_mci_runtime_resume,
+			   NULL)
+};
 
 static const struct pci_device_id dw_mci_pci_id[] = {
 	{ PCI_DEVICE(SYNOPSYS_DW_MCI_VENDOR_ID, SYNOPSYS_DW_MCI_DEVICE_ID) },
@@ -111,7 +100,7 @@ static struct pci_driver dw_mci_pci_driv
 	.probe		= dw_mci_pci_probe,
 	.remove		= dw_mci_pci_remove,
 	.driver		=	{
-		.pm =   &dw_mci_pci_pmops
+		.pm =   &dw_mci_pci_dev_pm_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-pltfm.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-pltfm.c
--- linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-pltfm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-pltfm.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
@@ -58,26 +59,13 @@ int dw_mci_pltfm_register(struct platfor
 }
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
 
-#ifdef CONFIG_PM_SLEEP
-/*
- * TODO: we should probably disable the clock to the card in the suspend path.
- */
-static int dw_mci_pltfm_suspend(struct device *dev)
-{
-	struct dw_mci *host = dev_get_drvdata(dev);
-
-	return dw_mci_suspend(host);
-}
-
-static int dw_mci_pltfm_resume(struct device *dev)
-{
-	struct dw_mci *host = dev_get_drvdata(dev);
-
-	return dw_mci_resume(host);
-}
-#endif /* CONFIG_PM_SLEEP */
-
-SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume);
+const struct dev_pm_ops dw_mci_pltfm_pmops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+			   dw_mci_runtime_resume,
+			   NULL)
+};
 EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
 
 static const struct of_device_id dw_mci_pltfm_match[] = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-rockchip.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-rockchip.c
--- linux-libre-4.9-gnu/drivers/mmc/host/dw_mmc-rockchip.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/dw_mmc-rockchip.c	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,8 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/dw_mmc.h>
 #include <linux/of_address.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include "dw_mmc.h"
@@ -325,6 +327,7 @@ static int dw_mci_rockchip_probe(struct
 {
 	const struct dw_mci_drv_data *drv_data;
 	const struct of_device_id *match;
+	int ret;
 
 	if (!pdev->dev.of_node)
 		return -ENODEV;
@@ -332,16 +335,49 @@ static int dw_mci_rockchip_probe(struct
 	match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node);
 	drv_data = match->data;
 
-	return dw_mci_pltfm_register(pdev, drv_data);
+	pm_runtime_get_noresume(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+	pm_runtime_use_autosuspend(&pdev->dev);
+
+	ret = dw_mci_pltfm_register(pdev, drv_data);
+	if (ret) {
+		pm_runtime_disable(&pdev->dev);
+		pm_runtime_set_suspended(&pdev->dev);
+		pm_runtime_put_noidle(&pdev->dev);
+		return ret;
+	}
+
+	pm_runtime_put_autosuspend(&pdev->dev);
+
+	return 0;
 }
 
+static int dw_mci_rockchip_remove(struct platform_device *pdev)
+{
+	pm_runtime_get_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	return dw_mci_pltfm_remove(pdev);
+}
+
+static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend,
+			   dw_mci_runtime_resume,
+			   NULL)
+};
+
 static struct platform_driver dw_mci_rockchip_pltfm_driver = {
 	.probe		= dw_mci_rockchip_probe,
-	.remove		= dw_mci_pltfm_remove,
+	.remove		= dw_mci_rockchip_remove,
 	.driver		= {
 		.name		= "dwmmc_rockchip",
 		.of_match_table	= dw_mci_rockchip_match,
-		.pm		= &dw_mci_pltfm_pmops,
+		.pm		= &dw_mci_rockchip_dev_pm_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/jz4740_mmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/jz4740_mmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/jz4740_mmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/jz4740_mmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -320,8 +320,7 @@ dma_unmap:
 }
 
 static void jz4740_mmc_pre_request(struct mmc_host *mmc,
-				   struct mmc_request *mrq,
-				   bool is_first_req)
+				   struct mmc_request *mrq)
 {
 	struct jz4740_mmc_host *host = mmc_priv(mmc);
 	struct mmc_data *data = mrq->data;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/Kconfig linux-libre-4.10-rc8-gnu/drivers/mmc/host/Kconfig
--- linux-libre-4.9-gnu/drivers/mmc/host/Kconfig	2016-12-11 17:58:47.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/Kconfig	2017-02-12 17:51:03.000000000 -0500
@@ -135,7 +135,6 @@ config MMC_SDHCI_OF_AT91
 	tristate "SDHCI OF support for the Atmel SDMMC controller"
 	depends on MMC_SDHCI_PLTFM
 	depends on OF
-	select MMC_SDHCI_IO_ACCESSORS
 	help
 	  This selects the Atmel SDMMC driver
 
@@ -144,6 +143,7 @@ config MMC_SDHCI_OF_ESDHC
 	depends on MMC_SDHCI_PLTFM
 	depends on PPC || ARCH_MXC || ARCH_LAYERSCAPE
 	select MMC_SDHCI_IO_ACCESSORS
+	select FSL_GUTS
 	help
 	  This selects the Freescale eSDHC controller support.
 
@@ -165,6 +165,17 @@ config MMC_SDHCI_OF_HLWD
 
 	  If unsure, say N.
 
+config MMC_SDHCI_CADENCE
+	tristate "SDHCI support for the Cadence SD/SDIO/eMMC controller"
+	depends on MMC_SDHCI_PLTFM
+	depends on OF
+	help
+	  This selects the Cadence SD/SDIO/eMMC driver.
+
+	  If you have a controller with this interface, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_CNS3XXX
 	tristate "SDHCI support on the Cavium Networks CNS3xxx SoC"
 	depends on ARCH_CNS3XXX
@@ -322,6 +333,16 @@ config MMC_SDHCI_IPROC
 
 	  If unsure, say N.
 
+config MMC_MESON_GX
+	tristate "Amlogic S905/GX* SD/MMC Host Controller support"
+	depends on ARCH_MESON && MMC
+	help
+	  This selects support for the Amlogic SD/MMC Host Controller
+	  found on the S905/GX* family of SoCs.  This controller is
+	  MMC 5.1 compliant and supports SD, eMMC and SDIO interfaces.
+
+	  If you have a controller with this interface, say Y here.
+
 config MMC_MOXART
 	tristate "MOXART SD/MMC Host Controller support"
 	depends on ARCH_MOXART && MMC
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/Makefile linux-libre-4.10-rc8-gnu/drivers/mmc/host/Makefile
--- linux-libre-4.9-gnu/drivers/mmc/host/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -53,6 +53,7 @@ obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
 obj-$(CONFIG_MMC_VUB300)	+= vub300.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
 obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
+obj-$(CONFIG_MMC_MESON_GX)	+= meson-gx-mmc.o
 obj-$(CONFIG_MMC_MOXART)	+= moxart-mmc.o
 obj-$(CONFIG_MMC_SUNXI)		+= sunxi-mmc.o
 obj-$(CONFIG_MMC_USDHI6ROL0)	+= usdhi6rol0.o
@@ -62,6 +63,7 @@ obj-$(CONFIG_MMC_REALTEK_PCI)	+= rtsx_pc
 obj-$(CONFIG_MMC_REALTEK_USB)	+= rtsx_usb_sdmmc.o
 
 obj-$(CONFIG_MMC_SDHCI_PLTFM)		+= sdhci-pltfm.o
+obj-$(CONFIG_MMC_SDHCI_CADENCE)		+= sdhci-cadence.o
 obj-$(CONFIG_MMC_SDHCI_CNS3XXX)		+= sdhci-cns3xxx.o
 obj-$(CONFIG_MMC_SDHCI_ESDHC_IMX)	+= sdhci-esdhc-imx.o
 obj-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/meson-gx-mmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/meson-gx-mmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/meson-gx-mmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/meson-gx-mmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,853 @@
+/*
+ * Amlogic SD/eMMC driver for the GX/S905 family SoCs
+ *
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Kevin Hilman <khilman@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regulator/consumer.h>
+
+#define DRIVER_NAME "meson-gx-mmc"
+
+#define SD_EMMC_CLOCK 0x0
+#define   CLK_DIV_SHIFT 0
+#define   CLK_DIV_WIDTH 6
+#define   CLK_DIV_MASK 0x3f
+#define   CLK_DIV_MAX 63
+#define   CLK_SRC_SHIFT 6
+#define   CLK_SRC_WIDTH 2
+#define   CLK_SRC_MASK 0x3
+#define   CLK_SRC_XTAL 0   /* external crystal */
+#define   CLK_SRC_XTAL_RATE 24000000
+#define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
+#define   CLK_SRC_PLL_RATE 1000000000
+#define   CLK_PHASE_SHIFT 8
+#define   CLK_PHASE_MASK 0x3
+#define   CLK_PHASE_0 0
+#define   CLK_PHASE_90 1
+#define   CLK_PHASE_180 2
+#define   CLK_PHASE_270 3
+#define   CLK_ALWAYS_ON BIT(24)
+
+#define SD_EMMC_DElAY 0x4
+#define SD_EMMC_ADJUST 0x8
+#define SD_EMMC_CALOUT 0x10
+#define SD_EMMC_START 0x40
+#define   START_DESC_INIT BIT(0)
+#define   START_DESC_BUSY BIT(1)
+#define   START_DESC_ADDR_SHIFT 2
+#define   START_DESC_ADDR_MASK (~0x3)
+
+#define SD_EMMC_CFG 0x44
+#define   CFG_BUS_WIDTH_SHIFT 0
+#define   CFG_BUS_WIDTH_MASK 0x3
+#define   CFG_BUS_WIDTH_1 0x0
+#define   CFG_BUS_WIDTH_4 0x1
+#define   CFG_BUS_WIDTH_8 0x2
+#define   CFG_DDR BIT(2)
+#define   CFG_BLK_LEN_SHIFT 4
+#define   CFG_BLK_LEN_MASK 0xf
+#define   CFG_RESP_TIMEOUT_SHIFT 8
+#define   CFG_RESP_TIMEOUT_MASK 0xf
+#define   CFG_RC_CC_SHIFT 12
+#define   CFG_RC_CC_MASK 0xf
+#define   CFG_STOP_CLOCK BIT(22)
+#define   CFG_CLK_ALWAYS_ON BIT(18)
+#define   CFG_AUTO_CLK BIT(23)
+
+#define SD_EMMC_STATUS 0x48
+#define   STATUS_BUSY BIT(31)
+
+#define SD_EMMC_IRQ_EN 0x4c
+#define   IRQ_EN_MASK 0x3fff
+#define   IRQ_RXD_ERR_SHIFT 0
+#define   IRQ_RXD_ERR_MASK 0xff
+#define   IRQ_TXD_ERR BIT(8)
+#define   IRQ_DESC_ERR BIT(9)
+#define   IRQ_RESP_ERR BIT(10)
+#define   IRQ_RESP_TIMEOUT BIT(11)
+#define   IRQ_DESC_TIMEOUT BIT(12)
+#define   IRQ_END_OF_CHAIN BIT(13)
+#define   IRQ_RESP_STATUS BIT(14)
+#define   IRQ_SDIO BIT(15)
+
+#define SD_EMMC_CMD_CFG 0x50
+#define SD_EMMC_CMD_ARG 0x54
+#define SD_EMMC_CMD_DAT 0x58
+#define SD_EMMC_CMD_RSP 0x5c
+#define SD_EMMC_CMD_RSP1 0x60
+#define SD_EMMC_CMD_RSP2 0x64
+#define SD_EMMC_CMD_RSP3 0x68
+
+#define SD_EMMC_RXD 0x94
+#define SD_EMMC_TXD 0x94
+#define SD_EMMC_LAST_REG SD_EMMC_TXD
+
+#define SD_EMMC_CFG_BLK_SIZE 512 /* internal buffer max: 512 bytes */
+#define SD_EMMC_CFG_RESP_TIMEOUT 256 /* in clock cycles */
+#define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
+#define MUX_CLK_NUM_PARENTS 2
+
+struct meson_host {
+	struct	device		*dev;
+	struct	mmc_host	*mmc;
+	struct	mmc_request	*mrq;
+	struct	mmc_command	*cmd;
+
+	spinlock_t lock;
+	void __iomem *regs;
+	int irq;
+	u32 ocr_mask;
+	struct clk *core_clk;
+	struct clk_mux mux;
+	struct clk *mux_clk;
+	struct clk *mux_parent[MUX_CLK_NUM_PARENTS];
+	unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
+
+	struct clk_divider cfg_div;
+	struct clk *cfg_div_clk;
+
+	unsigned int bounce_buf_size;
+	void *bounce_buf;
+	dma_addr_t bounce_dma_addr;
+
+	bool vqmmc_enabled;
+};
+
+struct sd_emmc_desc {
+	u32 cmd_cfg;
+	u32 cmd_arg;
+	u32 cmd_data;
+	u32 cmd_resp;
+};
+#define CMD_CFG_LENGTH_SHIFT 0
+#define CMD_CFG_LENGTH_MASK 0x1ff
+#define CMD_CFG_BLOCK_MODE BIT(9)
+#define CMD_CFG_R1B BIT(10)
+#define CMD_CFG_END_OF_CHAIN BIT(11)
+#define CMD_CFG_TIMEOUT_SHIFT 12
+#define CMD_CFG_TIMEOUT_MASK 0xf
+#define CMD_CFG_NO_RESP BIT(16)
+#define CMD_CFG_NO_CMD BIT(17)
+#define CMD_CFG_DATA_IO BIT(18)
+#define CMD_CFG_DATA_WR BIT(19)
+#define CMD_CFG_RESP_NOCRC BIT(20)
+#define CMD_CFG_RESP_128 BIT(21)
+#define CMD_CFG_RESP_NUM BIT(22)
+#define CMD_CFG_DATA_NUM BIT(23)
+#define CMD_CFG_CMD_INDEX_SHIFT 24
+#define CMD_CFG_CMD_INDEX_MASK 0x3f
+#define CMD_CFG_ERROR BIT(30)
+#define CMD_CFG_OWNER BIT(31)
+
+#define CMD_DATA_MASK (~0x3)
+#define CMD_DATA_BIG_ENDIAN BIT(1)
+#define CMD_DATA_SRAM BIT(0)
+#define CMD_RESP_MASK (~0x1)
+#define CMD_RESP_SRAM BIT(0)
+
+static int meson_mmc_clk_set(struct meson_host *host, unsigned long clk_rate)
+{
+	struct mmc_host *mmc = host->mmc;
+	int ret = 0;
+	u32 cfg;
+
+	if (clk_rate) {
+		if (WARN_ON(clk_rate > mmc->f_max))
+			clk_rate = mmc->f_max;
+		else if (WARN_ON(clk_rate < mmc->f_min))
+			clk_rate = mmc->f_min;
+	}
+
+	if (clk_rate == mmc->actual_clock)
+		return 0;
+
+	/* stop clock */
+	cfg = readl(host->regs + SD_EMMC_CFG);
+	if (!(cfg & CFG_STOP_CLOCK)) {
+		cfg |= CFG_STOP_CLOCK;
+		writel(cfg, host->regs + SD_EMMC_CFG);
+	}
+
+	dev_dbg(host->dev, "change clock rate %u -> %lu\n",
+		mmc->actual_clock, clk_rate);
+
+	if (clk_rate == 0) {
+		mmc->actual_clock = 0;
+		return 0;
+	}
+
+	ret = clk_set_rate(host->cfg_div_clk, clk_rate);
+	if (ret)
+		dev_warn(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n",
+			 clk_rate, ret);
+	else if (clk_rate && clk_rate != clk_get_rate(host->cfg_div_clk))
+		dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
+			 clk_rate, clk_get_rate(host->cfg_div_clk), ret);
+	else
+		mmc->actual_clock = clk_rate;
+
+	/* (re)start clock, if non-zero */
+	if (!ret && clk_rate) {
+		cfg = readl(host->regs + SD_EMMC_CFG);
+		cfg &= ~CFG_STOP_CLOCK;
+		writel(cfg, host->regs + SD_EMMC_CFG);
+	}
+
+	return ret;
+}
+
+/*
+ * The SD/eMMC IP block has an internal mux and divider used for
+ * generating the MMC clock.  Use the clock framework to create and
+ * manage these clocks.
+ */
+static int meson_mmc_clk_init(struct meson_host *host)
+{
+	struct clk_init_data init;
+	char clk_name[32];
+	int i, ret = 0;
+	const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
+	unsigned int mux_parent_count = 0;
+	const char *clk_div_parents[1];
+	unsigned int f_min = UINT_MAX;
+	u32 clk_reg, cfg;
+
+	/* get the mux parents */
+	for (i = 0; i < MUX_CLK_NUM_PARENTS; i++) {
+		char name[16];
+
+		snprintf(name, sizeof(name), "clkin%d", i);
+		host->mux_parent[i] = devm_clk_get(host->dev, name);
+		if (IS_ERR(host->mux_parent[i])) {
+			ret = PTR_ERR(host->mux_parent[i]);
+			if (PTR_ERR(host->mux_parent[i]) != -EPROBE_DEFER)
+				dev_err(host->dev, "Missing clock %s\n", name);
+			host->mux_parent[i] = NULL;
+			return ret;
+		}
+
+		host->mux_parent_rate[i] = clk_get_rate(host->mux_parent[i]);
+		mux_parent_names[i] = __clk_get_name(host->mux_parent[i]);
+		mux_parent_count++;
+		if (host->mux_parent_rate[i] < f_min)
+			f_min = host->mux_parent_rate[i];
+	}
+
+	/* cacluate f_min based on input clocks, and max divider value */
+	if (f_min != UINT_MAX)
+		f_min = DIV_ROUND_UP(CLK_SRC_XTAL_RATE, CLK_DIV_MAX);
+	else
+		f_min = 4000000;  /* default min: 400 MHz */
+	host->mmc->f_min = f_min;
+
+	/* create the mux */
+	snprintf(clk_name, sizeof(clk_name), "%s#mux", dev_name(host->dev));
+	init.name = clk_name;
+	init.ops = &clk_mux_ops;
+	init.flags = 0;
+	init.parent_names = mux_parent_names;
+	init.num_parents = mux_parent_count;
+
+	host->mux.reg = host->regs + SD_EMMC_CLOCK;
+	host->mux.shift = CLK_SRC_SHIFT;
+	host->mux.mask = CLK_SRC_MASK;
+	host->mux.flags = 0;
+	host->mux.table = NULL;
+	host->mux.hw.init = &init;
+
+	host->mux_clk = devm_clk_register(host->dev, &host->mux.hw);
+	if (WARN_ON(IS_ERR(host->mux_clk)))
+		return PTR_ERR(host->mux_clk);
+
+	/* create the divider */
+	snprintf(clk_name, sizeof(clk_name), "%s#div", dev_name(host->dev));
+	init.name = devm_kstrdup(host->dev, clk_name, GFP_KERNEL);
+	init.ops = &clk_divider_ops;
+	init.flags = CLK_SET_RATE_PARENT;
+	clk_div_parents[0] = __clk_get_name(host->mux_clk);
+	init.parent_names = clk_div_parents;
+	init.num_parents = ARRAY_SIZE(clk_div_parents);
+
+	host->cfg_div.reg = host->regs + SD_EMMC_CLOCK;
+	host->cfg_div.shift = CLK_DIV_SHIFT;
+	host->cfg_div.width = CLK_DIV_WIDTH;
+	host->cfg_div.hw.init = &init;
+	host->cfg_div.flags = CLK_DIVIDER_ONE_BASED |
+		CLK_DIVIDER_ROUND_CLOSEST | CLK_DIVIDER_ALLOW_ZERO;
+
+	host->cfg_div_clk = devm_clk_register(host->dev, &host->cfg_div.hw);
+	if (WARN_ON(PTR_ERR_OR_ZERO(host->cfg_div_clk)))
+		return PTR_ERR(host->cfg_div_clk);
+
+	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
+	clk_reg = 0;
+	clk_reg |= CLK_PHASE_180 << CLK_PHASE_SHIFT;
+	clk_reg |= CLK_SRC_XTAL << CLK_SRC_SHIFT;
+	clk_reg |= CLK_DIV_MAX << CLK_DIV_SHIFT;
+	clk_reg &= ~CLK_ALWAYS_ON;
+	writel(clk_reg, host->regs + SD_EMMC_CLOCK);
+
+	/* Ensure clock starts in "auto" mode, not "always on" */
+	cfg = readl(host->regs + SD_EMMC_CFG);
+	cfg &= ~CFG_CLK_ALWAYS_ON;
+	cfg |= CFG_AUTO_CLK;
+	writel(cfg, host->regs + SD_EMMC_CFG);
+
+	ret = clk_prepare_enable(host->cfg_div_clk);
+	if (!ret)
+		ret = meson_mmc_clk_set(host, f_min);
+
+	if (!ret)
+		clk_disable_unprepare(host->cfg_div_clk);
+
+	return ret;
+}
+
+static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	u32 bus_width;
+	u32 val, orig;
+
+	/*
+	 * GPIO regulator, only controls switching between 1v8 and
+	 * 3v3, doesn't support MMC_POWER_OFF, MMC_POWER_ON.
+	 */
+	switch (ios->power_mode) {
+	case MMC_POWER_OFF:
+		if (!IS_ERR(mmc->supply.vmmc))
+			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+
+		if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
+			regulator_disable(mmc->supply.vqmmc);
+			host->vqmmc_enabled = false;
+		}
+
+		break;
+
+	case MMC_POWER_UP:
+		if (!IS_ERR(mmc->supply.vmmc))
+			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
+		break;
+
+	case MMC_POWER_ON:
+		if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
+			int ret = regulator_enable(mmc->supply.vqmmc);
+
+			if (ret < 0)
+				dev_err(mmc_dev(mmc),
+					"failed to enable vqmmc regulator\n");
+			else
+				host->vqmmc_enabled = true;
+		}
+
+		break;
+	}
+
+
+	meson_mmc_clk_set(host, ios->clock);
+
+	/* Bus width */
+	val = readl(host->regs + SD_EMMC_CFG);
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		bus_width = CFG_BUS_WIDTH_1;
+		break;
+	case MMC_BUS_WIDTH_4:
+		bus_width = CFG_BUS_WIDTH_4;
+		break;
+	case MMC_BUS_WIDTH_8:
+		bus_width = CFG_BUS_WIDTH_8;
+		break;
+	default:
+		dev_err(host->dev, "Invalid ios->bus_width: %u.  Setting to 4.\n",
+			ios->bus_width);
+		bus_width = CFG_BUS_WIDTH_4;
+		return;
+	}
+
+	val = readl(host->regs + SD_EMMC_CFG);
+	orig = val;
+
+	val &= ~(CFG_BUS_WIDTH_MASK << CFG_BUS_WIDTH_SHIFT);
+	val |= bus_width << CFG_BUS_WIDTH_SHIFT;
+
+	val &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+	val |= ilog2(SD_EMMC_CFG_BLK_SIZE) << CFG_BLK_LEN_SHIFT;
+
+	val &= ~(CFG_RESP_TIMEOUT_MASK << CFG_RESP_TIMEOUT_SHIFT);
+	val |= ilog2(SD_EMMC_CFG_RESP_TIMEOUT) << CFG_RESP_TIMEOUT_SHIFT;
+
+	val &= ~(CFG_RC_CC_MASK << CFG_RC_CC_SHIFT);
+	val |= ilog2(SD_EMMC_CFG_CMD_GAP) << CFG_RC_CC_SHIFT;
+
+	writel(val, host->regs + SD_EMMC_CFG);
+
+	if (val != orig)
+		dev_dbg(host->dev, "%s: SD_EMMC_CFG: 0x%08x -> 0x%08x\n",
+			__func__, orig, val);
+}
+
+static int meson_mmc_request_done(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_host *host = mmc_priv(mmc);
+
+	WARN_ON(host->mrq != mrq);
+
+	host->mrq = NULL;
+	host->cmd = NULL;
+	mmc_request_done(host->mmc, mrq);
+
+	return 0;
+}
+
+static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	struct sd_emmc_desc *desc, desc_tmp;
+	u32 cfg;
+	u8 blk_len, cmd_cfg_timeout;
+	unsigned int xfer_bytes = 0;
+
+	/* Setup descriptors */
+	dma_rmb();
+	desc = &desc_tmp;
+	memset(desc, 0, sizeof(struct sd_emmc_desc));
+
+	desc->cmd_cfg |= (cmd->opcode & CMD_CFG_CMD_INDEX_MASK)	<<
+		CMD_CFG_CMD_INDEX_SHIFT;
+	desc->cmd_cfg |= CMD_CFG_OWNER;  /* owned by CPU */
+	desc->cmd_arg = cmd->arg;
+
+	/* Response */
+	if (cmd->flags & MMC_RSP_PRESENT) {
+		desc->cmd_cfg &= ~CMD_CFG_NO_RESP;
+		if (cmd->flags & MMC_RSP_136)
+			desc->cmd_cfg |= CMD_CFG_RESP_128;
+		desc->cmd_cfg |= CMD_CFG_RESP_NUM;
+		desc->cmd_resp = 0;
+
+		if (!(cmd->flags & MMC_RSP_CRC))
+			desc->cmd_cfg |= CMD_CFG_RESP_NOCRC;
+
+		if (cmd->flags & MMC_RSP_BUSY)
+			desc->cmd_cfg |= CMD_CFG_R1B;
+	} else {
+		desc->cmd_cfg |= CMD_CFG_NO_RESP;
+	}
+
+	/* data? */
+	if (cmd->data) {
+		desc->cmd_cfg |= CMD_CFG_DATA_IO;
+		if (cmd->data->blocks > 1) {
+			desc->cmd_cfg |= CMD_CFG_BLOCK_MODE;
+			desc->cmd_cfg |=
+				(cmd->data->blocks & CMD_CFG_LENGTH_MASK) <<
+				CMD_CFG_LENGTH_SHIFT;
+
+			/* check if block-size matches, if not update */
+			cfg = readl(host->regs + SD_EMMC_CFG);
+			blk_len = cfg & (CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+			blk_len >>= CFG_BLK_LEN_SHIFT;
+			if (blk_len != ilog2(cmd->data->blksz)) {
+				dev_warn(host->dev, "%s: update blk_len %d -> %d\n",
+					__func__, blk_len,
+					 ilog2(cmd->data->blksz));
+				blk_len = ilog2(cmd->data->blksz);
+				cfg &= ~(CFG_BLK_LEN_MASK << CFG_BLK_LEN_SHIFT);
+				cfg |= blk_len << CFG_BLK_LEN_SHIFT;
+				writel(cfg, host->regs + SD_EMMC_CFG);
+			}
+		} else {
+			desc->cmd_cfg &= ~CMD_CFG_BLOCK_MODE;
+			desc->cmd_cfg |=
+				(cmd->data->blksz & CMD_CFG_LENGTH_MASK) <<
+				CMD_CFG_LENGTH_SHIFT;
+		}
+
+		cmd->data->bytes_xfered = 0;
+		xfer_bytes = cmd->data->blksz * cmd->data->blocks;
+		if (cmd->data->flags & MMC_DATA_WRITE) {
+			desc->cmd_cfg |= CMD_CFG_DATA_WR;
+			WARN_ON(xfer_bytes > host->bounce_buf_size);
+			sg_copy_to_buffer(cmd->data->sg, cmd->data->sg_len,
+					  host->bounce_buf, xfer_bytes);
+			cmd->data->bytes_xfered = xfer_bytes;
+			dma_wmb();
+		} else {
+			desc->cmd_cfg &= ~CMD_CFG_DATA_WR;
+		}
+
+		if (xfer_bytes > 0) {
+			desc->cmd_cfg &= ~CMD_CFG_DATA_NUM;
+			desc->cmd_data = host->bounce_dma_addr & CMD_DATA_MASK;
+		} else {
+			/* write data to data_addr */
+			desc->cmd_cfg |= CMD_CFG_DATA_NUM;
+			desc->cmd_data = 0;
+		}
+
+		cmd_cfg_timeout = 12;
+	} else {
+		desc->cmd_cfg &= ~CMD_CFG_DATA_IO;
+		cmd_cfg_timeout = 10;
+	}
+	desc->cmd_cfg |= (cmd_cfg_timeout & CMD_CFG_TIMEOUT_MASK) <<
+		CMD_CFG_TIMEOUT_SHIFT;
+
+	host->cmd = cmd;
+
+	/* Last descriptor */
+	desc->cmd_cfg |= CMD_CFG_END_OF_CHAIN;
+	writel(desc->cmd_cfg, host->regs + SD_EMMC_CMD_CFG);
+	writel(desc->cmd_data, host->regs + SD_EMMC_CMD_DAT);
+	writel(desc->cmd_resp, host->regs + SD_EMMC_CMD_RSP);
+	wmb(); /* ensure descriptor is written before kicked */
+	writel(desc->cmd_arg, host->regs + SD_EMMC_CMD_ARG);
+}
+
+static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_host *host = mmc_priv(mmc);
+
+	WARN_ON(host->mrq != NULL);
+
+	/* Stop execution */
+	writel(0, host->regs + SD_EMMC_START);
+
+	/* clear, ack, enable all interrupts */
+	writel(0, host->regs + SD_EMMC_IRQ_EN);
+	writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
+	writel(IRQ_EN_MASK, host->regs + SD_EMMC_IRQ_EN);
+
+	host->mrq = mrq;
+
+	if (mrq->sbc)
+		meson_mmc_start_cmd(mmc, mrq->sbc);
+	else
+		meson_mmc_start_cmd(mmc, mrq->cmd);
+}
+
+static int meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
+{
+	struct meson_host *host = mmc_priv(mmc);
+
+	if (cmd->flags & MMC_RSP_136) {
+		cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP3);
+		cmd->resp[1] = readl(host->regs + SD_EMMC_CMD_RSP2);
+		cmd->resp[2] = readl(host->regs + SD_EMMC_CMD_RSP1);
+		cmd->resp[3] = readl(host->regs + SD_EMMC_CMD_RSP);
+	} else if (cmd->flags & MMC_RSP_PRESENT) {
+		cmd->resp[0] = readl(host->regs + SD_EMMC_CMD_RSP);
+	}
+
+	return 0;
+}
+
+static irqreturn_t meson_mmc_irq(int irq, void *dev_id)
+{
+	struct meson_host *host = dev_id;
+	struct mmc_request *mrq;
+	struct mmc_command *cmd;
+	u32 irq_en, status, raw_status;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	if (WARN_ON(!host))
+		return IRQ_NONE;
+
+	cmd = host->cmd;
+
+	mrq = host->mrq;
+
+	if (WARN_ON(!mrq))
+		return IRQ_NONE;
+
+	if (WARN_ON(!cmd))
+		return IRQ_NONE;
+
+	spin_lock(&host->lock);
+	irq_en = readl(host->regs + SD_EMMC_IRQ_EN);
+	raw_status = readl(host->regs + SD_EMMC_STATUS);
+	status = raw_status & irq_en;
+
+	if (!status) {
+		dev_warn(host->dev, "Spurious IRQ! status=0x%08x, irq_en=0x%08x\n",
+			 raw_status, irq_en);
+		ret = IRQ_NONE;
+		goto out;
+	}
+
+	cmd->error = 0;
+	if (status & IRQ_RXD_ERR_MASK) {
+		dev_dbg(host->dev, "Unhandled IRQ: RXD error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_TXD_ERR) {
+		dev_dbg(host->dev, "Unhandled IRQ: TXD error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_DESC_ERR)
+		dev_dbg(host->dev, "Unhandled IRQ: Descriptor error\n");
+	if (status & IRQ_RESP_ERR) {
+		dev_dbg(host->dev, "Unhandled IRQ: Response error\n");
+		cmd->error = -EILSEQ;
+	}
+	if (status & IRQ_RESP_TIMEOUT) {
+		dev_dbg(host->dev, "Unhandled IRQ: Response timeout\n");
+		cmd->error = -ETIMEDOUT;
+	}
+	if (status & IRQ_DESC_TIMEOUT) {
+		dev_dbg(host->dev, "Unhandled IRQ: Descriptor timeout\n");
+		cmd->error = -ETIMEDOUT;
+	}
+	if (status & IRQ_SDIO)
+		dev_dbg(host->dev, "Unhandled IRQ: SDIO.\n");
+
+	if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS))
+		ret = IRQ_WAKE_THREAD;
+	else  {
+		dev_warn(host->dev, "Unknown IRQ! status=0x%04x: MMC CMD%u arg=0x%08x flags=0x%08x stop=%d\n",
+			 status, cmd->opcode, cmd->arg,
+			 cmd->flags, mrq->stop ? 1 : 0);
+		if (cmd->data) {
+			struct mmc_data *data = cmd->data;
+
+			dev_warn(host->dev, "\tblksz %u blocks %u flags 0x%08x (%s%s)",
+				 data->blksz, data->blocks, data->flags,
+				 data->flags & MMC_DATA_WRITE ? "write" : "",
+				 data->flags & MMC_DATA_READ ? "read" : "");
+		}
+	}
+
+out:
+	/* ack all (enabled) interrupts */
+	writel(status, host->regs + SD_EMMC_STATUS);
+
+	if (ret == IRQ_HANDLED) {
+		meson_mmc_read_resp(host->mmc, cmd);
+		meson_mmc_request_done(host->mmc, cmd->mrq);
+	}
+
+	spin_unlock(&host->lock);
+	return ret;
+}
+
+static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
+{
+	struct meson_host *host = dev_id;
+	struct mmc_request *mrq = host->mrq;
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data;
+	unsigned int xfer_bytes;
+	int ret = IRQ_HANDLED;
+
+	if (WARN_ON(!mrq))
+		return IRQ_NONE;
+
+	if (WARN_ON(!cmd))
+		return IRQ_NONE;
+
+	data = cmd->data;
+	if (data) {
+		xfer_bytes = data->blksz * data->blocks;
+		if (data->flags & MMC_DATA_READ) {
+			WARN_ON(xfer_bytes > host->bounce_buf_size);
+			sg_copy_from_buffer(data->sg, data->sg_len,
+					    host->bounce_buf, xfer_bytes);
+			data->bytes_xfered = xfer_bytes;
+		}
+	}
+
+	meson_mmc_read_resp(host->mmc, cmd);
+	if (!data || !data->stop || mrq->sbc)
+		meson_mmc_request_done(host->mmc, mrq);
+	else
+		meson_mmc_start_cmd(host->mmc, data->stop);
+
+	return ret;
+}
+
+/*
+ * NOTE: we only need this until the GPIO/pinctrl driver can handle
+ * interrupts.  For now, the MMC core will use this for polling.
+ */
+static int meson_mmc_get_cd(struct mmc_host *mmc)
+{
+	int status = mmc_gpio_get_cd(mmc);
+
+	if (status == -ENOSYS)
+		return 1; /* assume present */
+
+	return status;
+}
+
+static const struct mmc_host_ops meson_mmc_ops = {
+	.request	= meson_mmc_request,
+	.set_ios	= meson_mmc_set_ios,
+	.get_cd         = meson_mmc_get_cd,
+};
+
+static int meson_mmc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct meson_host *host;
+	struct mmc_host *mmc;
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, host);
+
+	spin_lock_init(&host->lock);
+
+	/* Get regulators and the supported OCR mask */
+	host->vqmmc_enabled = false;
+	ret = mmc_regulator_get_supply(mmc);
+	if (ret == -EPROBE_DEFER)
+		goto free_host;
+
+	ret = mmc_of_parse(mmc);
+	if (ret) {
+		dev_warn(&pdev->dev, "error parsing DT: %d\n", ret);
+		goto free_host;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->regs)) {
+		ret = PTR_ERR(host->regs);
+		goto free_host;
+	}
+
+	host->irq = platform_get_irq(pdev, 0);
+	if (host->irq == 0) {
+		dev_err(&pdev->dev, "failed to get interrupt resource.\n");
+		ret = -EINVAL;
+		goto free_host;
+	}
+
+	host->core_clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(host->core_clk)) {
+		ret = PTR_ERR(host->core_clk);
+		goto free_host;
+	}
+
+	ret = clk_prepare_enable(host->core_clk);
+	if (ret)
+		goto free_host;
+
+	ret = meson_mmc_clk_init(host);
+	if (ret)
+		goto free_host;
+
+	/* Stop execution */
+	writel(0, host->regs + SD_EMMC_START);
+
+	/* clear, ack, enable all interrupts */
+	writel(0, host->regs + SD_EMMC_IRQ_EN);
+	writel(IRQ_EN_MASK, host->regs + SD_EMMC_STATUS);
+
+	ret = devm_request_threaded_irq(&pdev->dev, host->irq,
+					meson_mmc_irq, meson_mmc_irq_thread,
+					IRQF_SHARED, DRIVER_NAME, host);
+	if (ret)
+		goto free_host;
+
+	/* data bounce buffer */
+	host->bounce_buf_size = SZ_512K;
+	host->bounce_buf =
+		dma_alloc_coherent(host->dev, host->bounce_buf_size,
+				   &host->bounce_dma_addr, GFP_KERNEL);
+	if (host->bounce_buf == NULL) {
+		dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
+		ret = -ENOMEM;
+		goto free_host;
+	}
+
+	mmc->ops = &meson_mmc_ops;
+	mmc_add_host(mmc);
+
+	return 0;
+
+free_host:
+	clk_disable_unprepare(host->cfg_div_clk);
+	clk_disable_unprepare(host->core_clk);
+	mmc_free_host(mmc);
+	return ret;
+}
+
+static int meson_mmc_remove(struct platform_device *pdev)
+{
+	struct meson_host *host = dev_get_drvdata(&pdev->dev);
+
+	if (WARN_ON(!host))
+		return 0;
+
+	if (host->bounce_buf)
+		dma_free_coherent(host->dev, host->bounce_buf_size,
+				  host->bounce_buf, host->bounce_dma_addr);
+
+	clk_disable_unprepare(host->cfg_div_clk);
+	clk_disable_unprepare(host->core_clk);
+
+	mmc_free_host(host->mmc);
+	return 0;
+}
+
+static const struct of_device_id meson_mmc_of_match[] = {
+	{ .compatible = "amlogic,meson-gx-mmc", },
+	{ .compatible = "amlogic,meson-gxbb-mmc", },
+	{ .compatible = "amlogic,meson-gxl-mmc", },
+	{ .compatible = "amlogic,meson-gxm-mmc", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
+
+static struct platform_driver meson_mmc_driver = {
+	.probe		= meson_mmc_probe,
+	.remove		= meson_mmc_remove,
+	.driver		= {
+		.name = DRIVER_NAME,
+		.of_match_table = of_match_ptr(meson_mmc_of_match),
+	},
+};
+
+module_platform_driver(meson_mmc_driver);
+
+MODULE_DESCRIPTION("Amlogic S905*/GX* SD/eMMC driver");
+MODULE_AUTHOR("Kevin Hilman <khilman@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/mmci.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/mmci.c
--- linux-libre-4.9-gnu/drivers/mmc/host/mmci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/mmci.c	2017-02-12 16:03:20.000000000 -0500
@@ -71,7 +71,12 @@ static unsigned int fmax = 515633;
  * @f_max: maximum clk frequency supported by the controller.
  * @signal_direction: input/out direction of bus signals can be indicated
  * @pwrreg_clkgate: MMCIPOWER register must be used to gate the clock
- * @busy_detect: true if busy detection on dat0 is supported
+ * @busy_detect: true if the variant supports busy detection on DAT0.
+ * @busy_dpsm_flag: bitmask enabling busy detection in the DPSM
+ * @busy_detect_flag: bitmask identifying the bit in the MMCISTATUS register
+ *		      indicating that the card is busy
+ * @busy_detect_mask: bitmask identifying the bit in the MMCIMASK0 to mask for
+ *		      getting busy end detection interrupts
  * @pwrreg_nopower: bits in MMCIPOWER don't controls ext. power supply
  * @explicit_mclk_control: enable explicit mclk control in driver.
  * @qcom_fifo: enables qcom specific fifo pio read logic.
@@ -98,6 +103,9 @@ struct variant_data {
 	bool			signal_direction;
 	bool			pwrreg_clkgate;
 	bool			busy_detect;
+	u32			busy_dpsm_flag;
+	u32			busy_detect_flag;
+	u32			busy_detect_mask;
 	bool			pwrreg_nopower;
 	bool			explicit_mclk_control;
 	bool			qcom_fifo;
@@ -137,7 +145,7 @@ static struct variant_data variant_u300
 	.clkreg_enable		= MCI_ST_U300_HWFCEN,
 	.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
 	.datalength_bits	= 16,
-	.datactrl_mask_sdio	= MCI_ST_DPSM_SDIOEN,
+	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,
 	.st_sdio			= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
 	.f_max			= 100000000,
@@ -152,7 +160,7 @@ static struct variant_data variant_nomad
 	.clkreg			= MCI_CLK_ENABLE,
 	.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
 	.datalength_bits	= 24,
-	.datactrl_mask_sdio	= MCI_ST_DPSM_SDIOEN,
+	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,
 	.st_sdio		= true,
 	.st_clkdiv		= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
@@ -170,7 +178,7 @@ static struct variant_data variant_ux500
 	.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
 	.clkreg_neg_edge_enable	= MCI_ST_UX500_NEG_EDGE,
 	.datalength_bits	= 24,
-	.datactrl_mask_sdio	= MCI_ST_DPSM_SDIOEN,
+	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,
 	.st_sdio		= true,
 	.st_clkdiv		= true,
 	.pwrreg_powerup		= MCI_PWR_ON,
@@ -178,6 +186,9 @@ static struct variant_data variant_ux500
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.busy_detect		= true,
+	.busy_dpsm_flag		= MCI_DPSM_ST_BUSYMODE,
+	.busy_detect_flag	= MCI_ST_CARDBUSY,
+	.busy_detect_mask	= MCI_ST_BUSYENDMASK,
 	.pwrreg_nopower		= true,
 };
 
@@ -188,9 +199,9 @@ static struct variant_data variant_ux500
 	.clkreg_enable		= MCI_ST_UX500_HWFCEN,
 	.clkreg_8bit_bus_enable = MCI_ST_8BIT_BUS,
 	.clkreg_neg_edge_enable	= MCI_ST_UX500_NEG_EDGE,
-	.datactrl_mask_ddrmode	= MCI_ST_DPSM_DDRMODE,
+	.datactrl_mask_ddrmode	= MCI_DPSM_ST_DDRMODE,
 	.datalength_bits	= 24,
-	.datactrl_mask_sdio	= MCI_ST_DPSM_SDIOEN,
+	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,
 	.st_sdio		= true,
 	.st_clkdiv		= true,
 	.blksz_datactrl16	= true,
@@ -199,6 +210,9 @@ static struct variant_data variant_ux500
 	.signal_direction	= true,
 	.pwrreg_clkgate		= true,
 	.busy_detect		= true,
+	.busy_dpsm_flag		= MCI_DPSM_ST_BUSYMODE,
+	.busy_detect_flag	= MCI_ST_CARDBUSY,
+	.busy_detect_mask	= MCI_ST_BUSYENDMASK,
 	.pwrreg_nopower		= true,
 };
 
@@ -210,7 +224,7 @@ static struct variant_data variant_qcom
 				  MCI_QCOM_CLK_SELECT_IN_FBCLK,
 	.clkreg_8bit_bus_enable = MCI_QCOM_CLK_WIDEBUS_8,
 	.datactrl_mask_ddrmode	= MCI_QCOM_CLK_SELECT_IN_DDR_MODE,
-	.data_cmd_enable	= MCI_QCOM_CSPM_DATCMD,
+	.data_cmd_enable	= MCI_CPSM_QCOM_DATCMD,
 	.blksz_datactrl4	= true,
 	.datalength_bits	= 24,
 	.pwrreg_powerup		= MCI_PWR_UP,
@@ -220,6 +234,7 @@ static struct variant_data variant_qcom
 	.qcom_dml		= true,
 };
 
+/* Busy detection for the ST Micro variant */
 static int mmci_card_busy(struct mmc_host *mmc)
 {
 	struct mmci_host *host = mmc_priv(mmc);
@@ -227,7 +242,7 @@ static int mmci_card_busy(struct mmc_hos
 	int busy = 0;
 
 	spin_lock_irqsave(&host->lock, flags);
-	if (readl(host->base + MMCISTATUS) & MCI_ST_CARDBUSY)
+	if (readl(host->base + MMCISTATUS) & host->variant->busy_detect_flag)
 		busy = 1;
 	spin_unlock_irqrestore(&host->lock, flags);
 
@@ -294,8 +309,8 @@ static void mmci_write_pwrreg(struct mmc
  */
 static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl)
 {
-	/* Keep ST Micro busy mode if enabled */
-	datactrl |= host->datactrl_reg & MCI_ST_DPSM_BUSYMODE;
+	/* Keep busy mode in DPSM if enabled */
+	datactrl |= host->datactrl_reg & host->variant->busy_dpsm_flag;
 
 	if (host->datactrl_reg != datactrl) {
 		host->datactrl_reg = datactrl;
@@ -684,8 +699,7 @@ static void mmci_get_next_data(struct mm
 	next->dma_chan = NULL;
 }
 
-static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq,
-			     bool is_first_req)
+static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct mmci_host *host = mmc_priv(mmc);
 	struct mmc_data *data = mrq->data;
@@ -973,37 +987,75 @@ mmci_cmd_irq(struct mmci_host *host, str
 	     unsigned int status)
 {
 	void __iomem *base = host->base;
-	bool sbc, busy_resp;
+	bool sbc;
 
 	if (!cmd)
 		return;
 
 	sbc = (cmd == host->mrq->sbc);
-	busy_resp = host->variant->busy_detect && (cmd->flags & MMC_RSP_BUSY);
 
-	if (!((status|host->busy_status) & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|
-		MCI_CMDSENT|MCI_CMDRESPEND)))
+	/*
+	 * We need to be one of these interrupts to be considered worth
+	 * handling. Note that we tag on any latent IRQs postponed
+	 * due to waiting for busy status.
+	 */
+	if (!((status|host->busy_status) &
+	      (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND)))
 		return;
 
-	/* Check if we need to wait for busy completion. */
-	if (host->busy_status && (status & MCI_ST_CARDBUSY))
-		return;
+	/*
+	 * ST Micro variant: handle busy detection.
+	 */
+	if (host->variant->busy_detect) {
+		bool busy_resp = !!(cmd->flags & MMC_RSP_BUSY);
 
-	/* Enable busy completion if needed and supported. */
-	if (!host->busy_status && busy_resp &&
-		!(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
-		(readl(base + MMCISTATUS) & MCI_ST_CARDBUSY)) {
-		writel(readl(base + MMCIMASK0) | MCI_ST_BUSYEND,
-			base + MMCIMASK0);
-		host->busy_status = status & (MCI_CMDSENT|MCI_CMDRESPEND);
-		return;
-	}
+		/* We are busy with a command, return */
+		if (host->busy_status &&
+		    (status & host->variant->busy_detect_flag))
+			return;
 
-	/* At busy completion, mask the IRQ and complete the request. */
-	if (host->busy_status) {
-		writel(readl(base + MMCIMASK0) & ~MCI_ST_BUSYEND,
-			base + MMCIMASK0);
-		host->busy_status = 0;
+		/*
+		 * We were not busy, but we now got a busy response on
+		 * something that was not an error, and we double-check
+		 * that the special busy status bit is still set before
+		 * proceeding.
+		 */
+		if (!host->busy_status && busy_resp &&
+		    !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
+		    (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) {
+
+			/* Clear the busy start IRQ */
+			writel(host->variant->busy_detect_mask,
+			       host->base + MMCICLEAR);
+
+			/* Unmask the busy end IRQ */
+			writel(readl(base + MMCIMASK0) |
+			       host->variant->busy_detect_mask,
+			       base + MMCIMASK0);
+			/*
+			 * Now cache the last response status code (until
+			 * the busy bit goes low), and return.
+			 */
+			host->busy_status =
+				status & (MCI_CMDSENT|MCI_CMDRESPEND);
+			return;
+		}
+
+		/*
+		 * At this point we are not busy with a command, we have
+		 * not received a new busy request, clear and mask the busy
+		 * end IRQ and fall through to process the IRQ.
+		 */
+		if (host->busy_status) {
+
+			writel(host->variant->busy_detect_mask,
+			       host->base + MMCICLEAR);
+
+			writel(readl(base + MMCIMASK0) &
+			       ~host->variant->busy_detect_mask,
+			       base + MMCIMASK0);
+			host->busy_status = 0;
+		}
 	}
 
 	host->cmd = NULL;
@@ -1240,12 +1292,21 @@ static irqreturn_t mmci_irq(int irq, voi
 		}
 
 		/*
-		 * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's
-		 * enabled) since the HW seems to be triggering the IRQ on both
-		 * edges while monitoring DAT0 for busy completion.
+		 * We intentionally clear the MCI_ST_CARDBUSY IRQ (if it's
+		 * enabled) in mmci_cmd_irq() function where ST Micro busy
+		 * detection variant is handled. Considering the HW seems to be
+		 * triggering the IRQ on both edges while monitoring DAT0 for
+		 * busy completion and that same status bit is used to monitor
+		 * start and end of busy detection, special care must be taken
+		 * to make sure that both start and end interrupts are always
+		 * cleared one after the other.
 		 */
 		status &= readl(host->base + MMCIMASK0);
-		writel(status, host->base + MMCICLEAR);
+		if (host->variant->busy_detect)
+			writel(status & ~host->variant->busy_detect_mask,
+			       host->base + MMCICLEAR);
+		else
+			writel(status, host->base + MMCICLEAR);
 
 		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
 
@@ -1257,9 +1318,11 @@ static irqreturn_t mmci_irq(int irq, voi
 			mmci_data_irq(host, host->data, status);
 		}
 
-		/* Don't poll for busy completion in irq context. */
-		if (host->busy_status)
-			status &= ~MCI_ST_CARDBUSY;
+		/*
+		 * Don't poll for busy completion in irq context.
+		 */
+		if (host->variant->busy_detect && host->busy_status)
+			status &= ~host->variant->busy_detect_flag;
 
 		ret = 1;
 	} while (status);
@@ -1612,9 +1675,18 @@ static int mmci_probe(struct amba_device
 	/* We support these capabilities. */
 	mmc->caps |= MMC_CAP_CMD23;
 
+	/*
+	 * Enable busy detection.
+	 */
 	if (variant->busy_detect) {
 		mmci_ops.card_busy = mmci_card_busy;
-		mmci_write_datactrlreg(host, MCI_ST_DPSM_BUSYMODE);
+		/*
+		 * Not all variants have a flag to enable busy detection
+		 * in the DPSM, but if they do, set it here.
+		 */
+		if (variant->busy_dpsm_flag)
+			mmci_write_datactrlreg(host,
+					       host->variant->busy_dpsm_flag);
 		mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
 		mmc->max_busy_timeout = 0;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/mmci.h linux-libre-4.10-rc8-gnu/drivers/mmc/host/mmci.h
--- linux-libre-4.9-gnu/drivers/mmc/host/mmci.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/mmci.h	2017-02-12 16:03:20.000000000 -0500
@@ -51,25 +51,27 @@
 #define MCI_QCOM_CLK_SELECT_IN_DDR_MODE	(BIT(14) | BIT(15))
 
 #define MMCIARGUMENT		0x008
-#define MMCICOMMAND		0x00c
-#define MCI_CPSM_RESPONSE	(1 << 6)
-#define MCI_CPSM_LONGRSP	(1 << 7)
-#define MCI_CPSM_INTERRUPT	(1 << 8)
-#define MCI_CPSM_PENDING	(1 << 9)
-#define MCI_CPSM_ENABLE		(1 << 10)
-/* Argument flag extenstions in the ST Micro versions */
-#define MCI_ST_SDIO_SUSP	(1 << 11)
-#define MCI_ST_ENCMD_COMPL	(1 << 12)
-#define MCI_ST_NIEN		(1 << 13)
-#define MCI_ST_CE_ATACMD	(1 << 14)
 
-/* Modified on Qualcomm Integrations */
-#define MCI_QCOM_CSPM_DATCMD		BIT(12)
-#define MCI_QCOM_CSPM_MCIABORT		BIT(13)
-#define MCI_QCOM_CSPM_CCSENABLE		BIT(14)
-#define MCI_QCOM_CSPM_CCSDISABLE	BIT(15)
-#define MCI_QCOM_CSPM_AUTO_CMD19	BIT(16)
-#define MCI_QCOM_CSPM_AUTO_CMD21	BIT(21)
+/* The command register controls the Command Path State Machine (CPSM) */
+#define MMCICOMMAND		0x00c
+#define MCI_CPSM_RESPONSE	BIT(6)
+#define MCI_CPSM_LONGRSP	BIT(7)
+#define MCI_CPSM_INTERRUPT	BIT(8)
+#define MCI_CPSM_PENDING	BIT(9)
+#define MCI_CPSM_ENABLE		BIT(10)
+/* Command register flag extenstions in the ST Micro versions */
+#define MCI_CPSM_ST_SDIO_SUSP		BIT(11)
+#define MCI_CPSM_ST_ENCMD_COMPL		BIT(12)
+#define MCI_CPSM_ST_NIEN		BIT(13)
+#define MCI_CPSM_ST_CE_ATACMD		BIT(14)
+/* Command register flag extensions in the Qualcomm versions */
+#define MCI_CPSM_QCOM_PROGENA		BIT(11)
+#define MCI_CPSM_QCOM_DATCMD		BIT(12)
+#define MCI_CPSM_QCOM_MCIABORT		BIT(13)
+#define MCI_CPSM_QCOM_CCSENABLE		BIT(14)
+#define MCI_CPSM_QCOM_CCSDISABLE	BIT(15)
+#define MCI_CPSM_QCOM_AUTO_CMD19	BIT(16)
+#define MCI_CPSM_QCOM_AUTO_CMD21	BIT(21)
 
 #define MMCIRESPCMD		0x010
 #define MMCIRESPONSE0		0x014
@@ -78,22 +80,27 @@
 #define MMCIRESPONSE3		0x020
 #define MMCIDATATIMER		0x024
 #define MMCIDATALENGTH		0x028
+
+/* The data control register controls the Data Path State Machine (DPSM) */
 #define MMCIDATACTRL		0x02c
-#define MCI_DPSM_ENABLE		(1 << 0)
-#define MCI_DPSM_DIRECTION	(1 << 1)
-#define MCI_DPSM_MODE		(1 << 2)
-#define MCI_DPSM_DMAENABLE	(1 << 3)
-#define MCI_DPSM_BLOCKSIZE	(1 << 4)
+#define MCI_DPSM_ENABLE		BIT(0)
+#define MCI_DPSM_DIRECTION	BIT(1)
+#define MCI_DPSM_MODE		BIT(2)
+#define MCI_DPSM_DMAENABLE	BIT(3)
+#define MCI_DPSM_BLOCKSIZE	BIT(4)
 /* Control register extensions in the ST Micro U300 and Ux500 versions */
-#define MCI_ST_DPSM_RWSTART	(1 << 8)
-#define MCI_ST_DPSM_RWSTOP	(1 << 9)
-#define MCI_ST_DPSM_RWMOD	(1 << 10)
-#define MCI_ST_DPSM_SDIOEN	(1 << 11)
+#define MCI_DPSM_ST_RWSTART	BIT(8)
+#define MCI_DPSM_ST_RWSTOP	BIT(9)
+#define MCI_DPSM_ST_RWMOD	BIT(10)
+#define MCI_DPSM_ST_SDIOEN	BIT(11)
 /* Control register extensions in the ST Micro Ux500 versions */
-#define MCI_ST_DPSM_DMAREQCTL	(1 << 12)
-#define MCI_ST_DPSM_DBOOTMODEEN	(1 << 13)
-#define MCI_ST_DPSM_BUSYMODE	(1 << 14)
-#define MCI_ST_DPSM_DDRMODE	(1 << 15)
+#define MCI_DPSM_ST_DMAREQCTL	BIT(12)
+#define MCI_DPSM_ST_DBOOTMODEEN	BIT(13)
+#define MCI_DPSM_ST_BUSYMODE	BIT(14)
+#define MCI_DPSM_ST_DDRMODE	BIT(15)
+/* Control register extensions in the Qualcomm versions */
+#define MCI_DPSM_QCOM_DATA_PEND	BIT(17)
+#define MCI_DPSM_QCOM_RX_DATA_PEND BIT(20)
 
 #define MMCIDATACNT		0x030
 #define MMCISTATUS		0x034
@@ -167,7 +174,7 @@
 /* Extended status bits for the ST Micro variants */
 #define MCI_ST_SDIOITMASK	(1 << 22)
 #define MCI_ST_CEATAENDMASK	(1 << 23)
-#define MCI_ST_BUSYEND		(1 << 24)
+#define MCI_ST_BUSYENDMASK	(1 << 24)
 
 #define MMCIMASK1		0x040
 #define MMCIFIFOCNT		0x048
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/mtk-sd.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/mtk-sd.c
--- linux-libre-4.9-gnu/drivers/mmc/host/mtk-sd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/mtk-sd.c	2017-02-12 16:03:20.000000000 -0500
@@ -927,8 +927,7 @@ static void msdc_ops_request(struct mmc_
 		msdc_start_command(host, mrq, mrq->cmd);
 }
 
-static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
-		bool is_first_req)
+static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct msdc_host *host = mmc_priv(mmc);
 	struct mmc_data *data = mrq->data;
@@ -1713,6 +1712,7 @@ static const struct of_device_id msdc_of
 	{   .compatible = "mediatek,mt8135-mmc", },
 	{}
 };
+MODULE_DEVICE_TABLE(of, msdc_of_ids);
 
 static struct platform_driver mt_msdc_driver = {
 	.probe = msdc_drv_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/mxs-mmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/mxs-mmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/mxs-mmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/mxs-mmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -309,6 +309,9 @@ static void mxs_mmc_ac(struct mxs_mmc_ho
 	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
 	cmd1 = cmd->arg;
 
+	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
 	if (host->sdio_irq_en) {
 		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
 		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
@@ -417,8 +420,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_
 		       ssp->base + HW_SSP_BLOCK_SIZE);
 	}
 
-	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
-	    (cmd->opcode == SD_IO_RW_EXTENDED))
+	if (cmd->opcode == SD_IO_RW_EXTENDED)
 		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
 
 	cmd1 = cmd->arg;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/omap_hsmmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/omap_hsmmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/omap_hsmmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1565,8 +1565,7 @@ static void omap_hsmmc_post_req(struct m
 	}
 }
 
-static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
-			       bool is_first_req)
+static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct omap_hsmmc_host *host = mmc_priv(mmc);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/rtsx_pci_sdmmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -190,8 +190,7 @@ static int sd_pre_dma_transfer(struct re
 	return using_cookie;
 }
 
-static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
-		bool is_first_req)
+static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
 	struct mmc_data *data = mrq->data;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/rtsx_usb_sdmmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/rtsx_usb_sdmmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/rtsx_usb_sdmmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/rtsx_usb_sdmmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -1374,6 +1374,8 @@ static int rtsx_usb_sdmmc_drv_probe(stru
 
 	mutex_init(&host->host_mutex);
 	rtsx_usb_init_host(host);
+	pm_runtime_use_autosuspend(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
 	pm_runtime_enable(&pdev->dev);
 
 #ifdef RTSX_USB_USE_LEDS_CLASS
@@ -1428,6 +1430,7 @@ static int rtsx_usb_sdmmc_drv_remove(str
 
 	mmc_free_host(mmc);
 	pm_runtime_disable(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	platform_set_drvdata(pdev, NULL);
 
 	dev_dbg(&(pdev->dev),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/s3cmci.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/s3cmci.c
--- linux-libre-4.9-gnu/drivers/mmc/host/s3cmci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/s3cmci.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,7 +28,6 @@
 #include <mach/dma.h>
 #include <mach/gpio-samsung.h>
 
-#include <linux/platform_data/dma-s3c24xx.h>
 #include <linux/platform_data/mmc-s3cmci.h>
 
 #include "s3cmci.h"
@@ -1682,19 +1681,13 @@ static int s3cmci_probe(struct platform_
 		gpio_direction_input(host->pdata->gpio_wprotect);
 	}
 
-	/* depending on the dma state, get a dma channel to use. */
+	/* Depending on the dma state, get a DMA channel to use. */
 
 	if (s3cmci_host_usedma(host)) {
-		dma_cap_mask_t mask;
-
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
-
-		host->dma = dma_request_slave_channel_compat(mask,
-			s3c24xx_dma_filter, (void *)DMACH_SDI, &pdev->dev, "rx-tx");
-		if (!host->dma) {
+		host->dma = dma_request_chan(&pdev->dev, "rx-tx");
+		ret = PTR_ERR_OR_ZERO(host->dma);
+		if (ret) {
 			dev_err(&pdev->dev, "cannot get DMA channel.\n");
-			ret = -EBUSY;
 			goto probe_free_gpio_wp;
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-acpi.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-acpi.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-acpi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-acpi.c	2017-02-12 16:03:20.000000000 -0500
@@ -328,6 +328,7 @@ static const struct sdhci_acpi_uid_slot
 	{ "80865ACC", NULL, &sdhci_acpi_slot_int_emmc },
 	{ "80865AD0", NULL, &sdhci_acpi_slot_int_sdio },
 	{ "80860F14" , "1" , &sdhci_acpi_slot_int_emmc },
+	{ "80860F14" , "2" , &sdhci_acpi_slot_int_sdio },
 	{ "80860F14" , "3" , &sdhci_acpi_slot_int_sd   },
 	{ "80860F16" , NULL, &sdhci_acpi_slot_int_sd   },
 	{ "INT33BB"  , "2" , &sdhci_acpi_slot_int_sdio },
@@ -394,7 +395,8 @@ static int sdhci_acpi_probe(struct platf
 	/* Power on the SDHCI controller and its children */
 	acpi_device_fix_up_power(device);
 	list_for_each_entry(child, &device->children, node)
-		acpi_device_fix_up_power(child);
+		if (child->status.present && child->status.enabled)
+			acpi_device_fix_up_power(child);
 
 	if (acpi_bus_get_status(device) || !device->status.present)
 		return -ENODEV;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@
 #include <linux/scatterlist.h>
 #include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
 
 #include <linux/leds.h>
 
@@ -1343,20 +1344,10 @@ clock_set:
 }
 EXPORT_SYMBOL_GPL(sdhci_calc_clk);
 
-void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
 {
-	u16 clk;
 	unsigned long timeout;
 
-	host->mmc->actual_clock = 0;
-
-	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
-
-	if (clock == 0)
-		return;
-
-	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
-
 	clk |= SDHCI_CLOCK_INT_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 
@@ -1377,6 +1368,22 @@ void sdhci_set_clock(struct sdhci_host *
 	clk |= SDHCI_CLOCK_CARD_EN;
 	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
 }
+EXPORT_SYMBOL_GPL(sdhci_enable_clk);
+
+void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	u16 clk;
+
+	host->mmc->actual_clock = 0;
+
+	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+	if (clock == 0)
+		return;
+
+	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+	sdhci_enable_clk(host, clk);
+}
 EXPORT_SYMBOL_GPL(sdhci_set_clock);
 
 static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
@@ -1569,6 +1576,9 @@ static void sdhci_set_ios(struct mmc_hos
 	unsigned long flags;
 	u8 ctrl;
 
+	if (ios->power_mode == MMC_POWER_UNDEFINED)
+		return;
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	if (host->flags & SDHCI_DEVICE_DEAD) {
@@ -1623,7 +1633,14 @@ static void sdhci_set_ios(struct mmc_hos
 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
 
 	if ((ios->timing == MMC_TIMING_SD_HS ||
-	     ios->timing == MMC_TIMING_MMC_HS)
+	     ios->timing == MMC_TIMING_MMC_HS ||
+	     ios->timing == MMC_TIMING_MMC_HS400 ||
+	     ios->timing == MMC_TIMING_MMC_HS200 ||
+	     ios->timing == MMC_TIMING_MMC_DDR52 ||
+	     ios->timing == MMC_TIMING_UHS_SDR50 ||
+	     ios->timing == MMC_TIMING_UHS_SDR104 ||
+	     ios->timing == MMC_TIMING_UHS_DDR50 ||
+	     ios->timing == MMC_TIMING_UHS_SDR25)
 	    && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
 		ctrl |= SDHCI_CTRL_HISPD;
 	else
@@ -1632,16 +1649,6 @@ static void sdhci_set_ios(struct mmc_hos
 	if (host->version >= SDHCI_SPEC_300) {
 		u16 clk, ctrl_2;
 
-		/* In case of UHS-I modes, set High Speed Enable */
-		if ((ios->timing == MMC_TIMING_MMC_HS400) ||
-		    (ios->timing == MMC_TIMING_MMC_HS200) ||
-		    (ios->timing == MMC_TIMING_MMC_DDR52) ||
-		    (ios->timing == MMC_TIMING_UHS_SDR50) ||
-		    (ios->timing == MMC_TIMING_UHS_SDR104) ||
-		    (ios->timing == MMC_TIMING_UHS_DDR50) ||
-		    (ios->timing == MMC_TIMING_UHS_SDR25))
-			ctrl |= SDHCI_CTRL_HISPD;
-
 		if (!host->preset_enabled) {
 			sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
 			/*
@@ -1948,11 +1955,157 @@ static int sdhci_prepare_hs400_tuning(st
 	return 0;
 }
 
-static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+static void sdhci_start_tuning(struct sdhci_host *host)
 {
-	struct sdhci_host *host = mmc_priv(mmc);
 	u16 ctrl;
-	int tuning_loop_counter = MAX_TUNING_LOOP;
+
+	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	ctrl |= SDHCI_CTRL_EXEC_TUNING;
+	if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
+		ctrl |= SDHCI_CTRL_TUNED_CLK;
+	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+
+	/*
+	 * As per the Host Controller spec v3.00, tuning command
+	 * generates Buffer Read Ready interrupt, so enable that.
+	 *
+	 * Note: The spec clearly says that when tuning sequence
+	 * is being performed, the controller does not generate
+	 * interrupts other than Buffer Read Ready interrupt. But
+	 * to make sure we don't hit a controller bug, we _only_
+	 * enable Buffer Read Ready interrupt here.
+	 */
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
+	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_end_tuning(struct sdhci_host *host)
+{
+	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+}
+
+static void sdhci_reset_tuning(struct sdhci_host *host)
+{
+	u16 ctrl;
+
+	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+	ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+	ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
+	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
+}
+
+static void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode,
+			       unsigned long flags)
+{
+	sdhci_reset_tuning(host);
+
+	sdhci_do_reset(host, SDHCI_RESET_CMD);
+	sdhci_do_reset(host, SDHCI_RESET_DATA);
+
+	sdhci_end_tuning(host);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+	mmc_abort_tuning(host->mmc, opcode);
+	spin_lock_irqsave(&host->lock, flags);
+}
+
+/*
+ * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI
+ * tuning command does not have a data payload (or rather the hardware does it
+ * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command
+ * interrupt setup is different to other commands and there is no timeout
+ * interrupt so special handling is needed.
+ */
+static void sdhci_send_tuning(struct sdhci_host *host, u32 opcode,
+			      unsigned long flags)
+{
+	struct mmc_host *mmc = host->mmc;
+	struct mmc_command cmd = {0};
+	struct mmc_request mrq = {NULL};
+
+	cmd.opcode = opcode;
+	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+	cmd.mrq = &mrq;
+
+	mrq.cmd = &cmd;
+	/*
+	 * In response to CMD19, the card sends 64 bytes of tuning
+	 * block to the Host Controller. So we set the block size
+	 * to 64 here.
+	 */
+	if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200 &&
+	    mmc->ios.bus_width == MMC_BUS_WIDTH_8)
+		sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), SDHCI_BLOCK_SIZE);
+	else
+		sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE);
+
+	/*
+	 * The tuning block is sent by the card to the host controller.
+	 * So we set the TRNS_READ bit in the Transfer Mode register.
+	 * This also takes care of setting DMA Enable and Multi Block
+	 * Select in the same register to 0.
+	 */
+	sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
+
+	sdhci_send_command(host, &cmd);
+
+	host->cmd = NULL;
+
+	sdhci_del_timer(host, &mrq);
+
+	host->tuning_done = 0;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	/* Wait for Buffer Read Ready interrupt */
+	wait_event_timeout(host->buf_ready_int, (host->tuning_done == 1),
+			   msecs_to_jiffies(50));
+
+	spin_lock_irqsave(&host->lock, flags);
+}
+
+static void __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode,
+				   unsigned long flags)
+{
+	int i;
+
+	/*
+	 * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
+	 * of loops reaches 40 times.
+	 */
+	for (i = 0; i < MAX_TUNING_LOOP; i++) {
+		u16 ctrl;
+
+		sdhci_send_tuning(host, opcode, flags);
+
+		if (!host->tuning_done) {
+			pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
+				mmc_hostname(host->mmc));
+			sdhci_abort_tuning(host, opcode, flags);
+			return;
+		}
+
+		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+		if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
+			if (ctrl & SDHCI_CTRL_TUNED_CLK)
+				return; /* Success! */
+			break;
+		}
+
+		/* eMMC spec does not require a delay between tuning cycles */
+		if (opcode == MMC_SEND_TUNING_BLOCK)
+			mdelay(1);
+	}
+
+	pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
+		mmc_hostname(host->mmc));
+	sdhci_reset_tuning(host);
+}
+
+int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
 	int err = 0;
 	unsigned long flags;
 	unsigned int tuning_count = 0;
@@ -2003,144 +2156,22 @@ static int sdhci_execute_tuning(struct m
 
 	if (host->ops->platform_execute_tuning) {
 		spin_unlock_irqrestore(&host->lock, flags);
-		err = host->ops->platform_execute_tuning(host, opcode);
-		return err;
+		return host->ops->platform_execute_tuning(host, opcode);
 	}
 
-	ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-	ctrl |= SDHCI_CTRL_EXEC_TUNING;
-	if (host->quirks2 & SDHCI_QUIRK2_TUNING_WORK_AROUND)
-		ctrl |= SDHCI_CTRL_TUNED_CLK;
-	sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
-	/*
-	 * As per the Host Controller spec v3.00, tuning command
-	 * generates Buffer Read Ready interrupt, so enable that.
-	 *
-	 * Note: The spec clearly says that when tuning sequence
-	 * is being performed, the controller does not generate
-	 * interrupts other than Buffer Read Ready interrupt. But
-	 * to make sure we don't hit a controller bug, we _only_
-	 * enable Buffer Read Ready interrupt here.
-	 */
-	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
-	sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
-
-	/*
-	 * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
-	 * of loops reaches 40 times.
-	 */
-	do {
-		struct mmc_command cmd = {0};
-		struct mmc_request mrq = {NULL};
-
-		cmd.opcode = opcode;
-		cmd.arg = 0;
-		cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-		cmd.retries = 0;
-		cmd.data = NULL;
-		cmd.mrq = &mrq;
-		cmd.error = 0;
-
-		if (tuning_loop_counter-- == 0)
-			break;
-
-		mrq.cmd = &cmd;
-
-		/*
-		 * In response to CMD19, the card sends 64 bytes of tuning
-		 * block to the Host Controller. So we set the block size
-		 * to 64 here.
-		 */
-		if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) {
-			if (mmc->ios.bus_width == MMC_BUS_WIDTH_8)
-				sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128),
-					     SDHCI_BLOCK_SIZE);
-			else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4)
-				sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
-					     SDHCI_BLOCK_SIZE);
-		} else {
-			sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64),
-				     SDHCI_BLOCK_SIZE);
-		}
-
-		/*
-		 * The tuning block is sent by the card to the host controller.
-		 * So we set the TRNS_READ bit in the Transfer Mode register.
-		 * This also takes care of setting DMA Enable and Multi Block
-		 * Select in the same register to 0.
-		 */
-		sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
-
-		sdhci_send_command(host, &cmd);
-
-		host->cmd = NULL;
-		sdhci_del_timer(host, &mrq);
-
-		spin_unlock_irqrestore(&host->lock, flags);
-		/* Wait for Buffer Read Ready interrupt */
-		wait_event_timeout(host->buf_ready_int,
-					(host->tuning_done == 1),
-					msecs_to_jiffies(50));
-		spin_lock_irqsave(&host->lock, flags);
-
-		if (!host->tuning_done) {
-			pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n");
-
-			sdhci_do_reset(host, SDHCI_RESET_CMD);
-			sdhci_do_reset(host, SDHCI_RESET_DATA);
-
-			ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-			ctrl &= ~SDHCI_CTRL_TUNED_CLK;
-			ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
-			sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-
-			err = -EIO;
-			goto out;
-		}
-
-		host->tuning_done = 0;
-
-		ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
-
-		/* eMMC spec does not require a delay between tuning cycles */
-		if (opcode == MMC_SEND_TUNING_BLOCK)
-			mdelay(1);
-	} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
-
-	/*
-	 * The Host Driver has exhausted the maximum number of loops allowed,
-	 * so use fixed sampling frequency.
-	 */
-	if (tuning_loop_counter < 0) {
-		ctrl &= ~SDHCI_CTRL_TUNED_CLK;
-		sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
-	}
-	if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
-		pr_info(DRIVER_NAME ": Tuning procedure failed, falling back to fixed sampling clock\n");
-		err = -EIO;
-	}
+	host->mmc->retune_period = tuning_count;
 
-out:
-	if (tuning_count) {
-		/*
-		 * In case tuning fails, host controllers which support
-		 * re-tuning can try tuning again at a later time, when the
-		 * re-tuning timer expires.  So for these controllers, we
-		 * return 0. Since there might be other controllers who do not
-		 * have this capability, we return error for them.
-		 */
-		err = 0;
-	}
+	sdhci_start_tuning(host);
 
-	host->mmc->retune_period = err ? 0 : tuning_count;
+	__sdhci_execute_tuning(host, opcode, flags);
 
-	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+	sdhci_end_tuning(host);
 out_unlock:
 	spin_unlock_irqrestore(&host->lock, flags);
+
 	return err;
 }
+EXPORT_SYMBOL_GPL(sdhci_execute_tuning);
 
 static int sdhci_select_drive_strength(struct mmc_card *card,
 				       unsigned int max_dtr, int host_drv,
@@ -2198,8 +2229,7 @@ static void sdhci_post_req(struct mmc_ho
 	data->host_cookie = COOKIE_UNMAPPED;
 }
 
-static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
-			       bool is_first_req)
+static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
 
@@ -2703,7 +2733,8 @@ static irqreturn_t sdhci_irq(int irq, vo
 		if (intmask & SDHCI_INT_RETUNE)
 			mmc_retune_needed(host->mmc);
 
-		if (intmask & SDHCI_INT_CARD_INT) {
+		if ((intmask & SDHCI_INT_CARD_INT) &&
+		    (host->ier & SDHCI_INT_CARD_INT)) {
 			sdhci_enable_sdio_irq_nolock(host, false);
 			host->thread_isr |= SDHCI_INT_CARD_INT;
 			result = IRQ_WAKE_THREAD;
@@ -2911,22 +2942,24 @@ int sdhci_runtime_resume_host(struct sdh
 
 	sdhci_init(host, 0);
 
-	/* Force clock and power re-program */
-	host->pwr = 0;
-	host->clock = 0;
-	mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
-	mmc->ops->set_ios(mmc, &mmc->ios);
+	if (mmc->ios.power_mode != MMC_POWER_UNDEFINED) {
+		/* Force clock and power re-program */
+		host->pwr = 0;
+		host->clock = 0;
+		mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
+		mmc->ops->set_ios(mmc, &mmc->ios);
 
-	if ((host_flags & SDHCI_PV_ENABLED) &&
-		!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
-		spin_lock_irqsave(&host->lock, flags);
-		sdhci_enable_preset_value(host, true);
-		spin_unlock_irqrestore(&host->lock, flags);
-	}
+		if ((host_flags & SDHCI_PV_ENABLED) &&
+		    !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
+			spin_lock_irqsave(&host->lock, flags);
+			sdhci_enable_preset_value(host, true);
+			spin_unlock_irqrestore(&host->lock, flags);
+		}
 
-	if ((mmc->caps2 & MMC_CAP2_HS400_ES) &&
-	    mmc->ops->hs400_enhanced_strobe)
-		mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios);
+		if ((mmc->caps2 & MMC_CAP2_HS400_ES) &&
+		    mmc->ops->hs400_enhanced_strobe)
+			mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios);
+	}
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -3010,6 +3043,8 @@ static int sdhci_set_dma_mask(struct sdh
 void __sdhci_read_caps(struct sdhci_host *host, u16 *ver, u32 *caps, u32 *caps1)
 {
 	u16 v;
+	u64 dt_caps_mask = 0;
+	u64 dt_caps = 0;
 
 	if (host->read_caps)
 		return;
@@ -3024,18 +3059,35 @@ void __sdhci_read_caps(struct sdhci_host
 
 	sdhci_do_reset(host, SDHCI_RESET_ALL);
 
+	of_property_read_u64(mmc_dev(host->mmc)->of_node,
+			     "sdhci-caps-mask", &dt_caps_mask);
+	of_property_read_u64(mmc_dev(host->mmc)->of_node,
+			     "sdhci-caps", &dt_caps);
+
 	v = ver ? *ver : sdhci_readw(host, SDHCI_HOST_VERSION);
 	host->version = (v & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
 
 	if (host->quirks & SDHCI_QUIRK_MISSING_CAPS)
 		return;
 
-	host->caps = caps ? *caps : sdhci_readl(host, SDHCI_CAPABILITIES);
+	if (caps) {
+		host->caps = *caps;
+	} else {
+		host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+		host->caps &= ~lower_32_bits(dt_caps_mask);
+		host->caps |= lower_32_bits(dt_caps);
+	}
 
 	if (host->version < SDHCI_SPEC_300)
 		return;
 
-	host->caps1 = caps1 ? *caps1 : sdhci_readl(host, SDHCI_CAPABILITIES_1);
+	if (caps1) {
+		host->caps1 = *caps1;
+	} else {
+		host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
+		host->caps1 &= ~upper_32_bits(dt_caps_mask);
+		host->caps1 |= upper_32_bits(dt_caps);
+	}
 }
 EXPORT_SYMBOL_GPL(__sdhci_read_caps);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-cadence.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-cadence.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-cadence.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-cadence.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2016 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mmc/host.h>
+
+#include "sdhci-pltfm.h"
+
+/* HRS - Host Register Set (specific to Cadence) */
+#define SDHCI_CDNS_HRS04		0x10		/* PHY access port */
+#define   SDHCI_CDNS_HRS04_ACK			BIT(26)
+#define   SDHCI_CDNS_HRS04_RD			BIT(25)
+#define   SDHCI_CDNS_HRS04_WR			BIT(24)
+#define   SDHCI_CDNS_HRS04_RDATA_SHIFT		12
+#define   SDHCI_CDNS_HRS04_WDATA_SHIFT		8
+#define   SDHCI_CDNS_HRS04_ADDR_SHIFT		0
+
+#define SDHCI_CDNS_HRS06		0x18		/* eMMC control */
+#define   SDHCI_CDNS_HRS06_TUNE_UP		BIT(15)
+#define   SDHCI_CDNS_HRS06_TUNE_SHIFT		8
+#define   SDHCI_CDNS_HRS06_TUNE_MASK		0x3f
+#define   SDHCI_CDNS_HRS06_MODE_MASK		0x7
+#define   SDHCI_CDNS_HRS06_MODE_SD		0x0
+#define   SDHCI_CDNS_HRS06_MODE_MMC_SDR		0x2
+#define   SDHCI_CDNS_HRS06_MODE_MMC_DDR		0x3
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS200	0x4
+#define   SDHCI_CDNS_HRS06_MODE_MMC_HS400	0x5
+
+/* SRS - Slot Register Set (SDHCI-compatible) */
+#define SDHCI_CDNS_SRS_BASE		0x200
+
+/* PHY */
+#define SDHCI_CDNS_PHY_DLY_SD_HS	0x00
+#define SDHCI_CDNS_PHY_DLY_SD_DEFAULT	0x01
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR12	0x02
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR25	0x03
+#define SDHCI_CDNS_PHY_DLY_UHS_SDR50	0x04
+#define SDHCI_CDNS_PHY_DLY_UHS_DDR50	0x05
+#define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY	0x06
+#define SDHCI_CDNS_PHY_DLY_EMMC_SDR	0x07
+#define SDHCI_CDNS_PHY_DLY_EMMC_DDR	0x08
+
+/*
+ * The tuned val register is 6 bit-wide, but not the whole of the range is
+ * available.  The range 0-42 seems to be available (then 43 wraps around to 0)
+ * but I am not quite sure if it is official.  Use only 0 to 39 for safety.
+ */
+#define SDHCI_CDNS_MAX_TUNING_LOOP	40
+
+struct sdhci_cdns_priv {
+	void __iomem *hrs_addr;
+};
+
+static void sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
+				     u8 addr, u8 data)
+{
+	void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
+	u32 tmp;
+
+	tmp = (data << SDHCI_CDNS_HRS04_WDATA_SHIFT) |
+	      (addr << SDHCI_CDNS_HRS04_ADDR_SHIFT);
+	writel(tmp, reg);
+
+	tmp |= SDHCI_CDNS_HRS04_WR;
+	writel(tmp, reg);
+
+	tmp &= ~SDHCI_CDNS_HRS04_WR;
+	writel(tmp, reg);
+}
+
+static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
+{
+	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
+	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
+	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
+	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
+	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
+}
+
+static inline void *sdhci_cdns_priv(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	return sdhci_pltfm_priv(pltfm_host);
+}
+
+static unsigned int sdhci_cdns_get_timeout_clock(struct sdhci_host *host)
+{
+	/*
+	 * Cadence's spec says the Timeout Clock Frequency is the same as the
+	 * Base Clock Frequency.  Divide it by 1000 to return a value in kHz.
+	 */
+	return host->max_clk / 1000;
+}
+
+static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
+					 unsigned int timing)
+{
+	struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+	u32 mode, tmp;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+		mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
+		break;
+	case MMC_TIMING_MMC_DDR52:
+		mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
+		break;
+	case MMC_TIMING_MMC_HS200:
+		mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
+		break;
+	case MMC_TIMING_MMC_HS400:
+		mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
+		break;
+	default:
+		mode = SDHCI_CDNS_HRS06_MODE_SD;
+		break;
+	}
+
+	/* The speed mode for eMMC is selected by HRS06 register */
+	tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
+	tmp &= ~SDHCI_CDNS_HRS06_MODE_MASK;
+	tmp |= mode;
+	writel(tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
+
+	/* For SD, fall back to the default handler */
+	if (mode == SDHCI_CDNS_HRS06_MODE_SD)
+		sdhci_set_uhs_signaling(host, timing);
+}
+
+static const struct sdhci_ops sdhci_cdns_ops = {
+	.set_clock = sdhci_set_clock,
+	.get_timeout_clock = sdhci_cdns_get_timeout_clock,
+	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = {
+	.ops = &sdhci_cdns_ops,
+};
+
+static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val)
+{
+	struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+	void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS06;
+	u32 tmp;
+
+	if (WARN_ON(val > SDHCI_CDNS_HRS06_TUNE_MASK))
+		return -EINVAL;
+
+	tmp = readl(reg);
+	tmp &= ~(SDHCI_CDNS_HRS06_TUNE_MASK << SDHCI_CDNS_HRS06_TUNE_SHIFT);
+	tmp |= val << SDHCI_CDNS_HRS06_TUNE_SHIFT;
+	tmp |= SDHCI_CDNS_HRS06_TUNE_UP;
+	writel(tmp, reg);
+
+	return readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS06_TUNE_UP),
+				  0, 1);
+}
+
+static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int cur_streak = 0;
+	int max_streak = 0;
+	int end_of_streak = 0;
+	int i;
+
+	/*
+	 * This handler only implements the eMMC tuning that is specific to
+	 * this controller.  Fall back to the standard method for SD timing.
+	 */
+	if (host->timing != MMC_TIMING_MMC_HS200)
+		return sdhci_execute_tuning(mmc, opcode);
+
+	if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200))
+		return -EINVAL;
+
+	for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) {
+		if (sdhci_cdns_set_tune_val(host, i) ||
+		    mmc_send_tuning(host->mmc, opcode, NULL)) { /* bad */
+			cur_streak = 0;
+		} else { /* good */
+			cur_streak++;
+			if (cur_streak > max_streak) {
+				max_streak = cur_streak;
+				end_of_streak = i;
+			}
+		}
+	}
+
+	if (!max_streak) {
+		dev_err(mmc_dev(host->mmc), "no tuning point found\n");
+		return -EIO;
+	}
+
+	return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
+}
+
+static int sdhci_cdns_probe(struct platform_device *pdev)
+{
+	struct sdhci_host *host;
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_cdns_priv *priv;
+	struct clk *clk;
+	int ret;
+
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	ret = clk_prepare_enable(clk);
+	if (ret)
+		return ret;
+
+	host = sdhci_pltfm_init(pdev, &sdhci_cdns_pltfm_data, sizeof(*priv));
+	if (IS_ERR(host)) {
+		ret = PTR_ERR(host);
+		goto disable_clk;
+	}
+
+	pltfm_host = sdhci_priv(host);
+	pltfm_host->clk = clk;
+
+	priv = sdhci_cdns_priv(host);
+	priv->hrs_addr = host->ioaddr;
+	host->ioaddr += SDHCI_CDNS_SRS_BASE;
+	host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
+
+	ret = mmc_of_parse(host->mmc);
+	if (ret)
+		goto free;
+
+	sdhci_cdns_phy_init(priv);
+
+	ret = sdhci_add_host(host);
+	if (ret)
+		goto free;
+
+	return 0;
+free:
+	sdhci_pltfm_free(pdev);
+disable_clk:
+	clk_disable_unprepare(clk);
+
+	return ret;
+}
+
+static const struct of_device_id sdhci_cdns_match[] = {
+	{ .compatible = "socionext,uniphier-sd4hc" },
+	{ .compatible = "cdns,sd4hc" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sdhci_cdns_match);
+
+static struct platform_driver sdhci_cdns_driver = {
+	.driver = {
+		.name = "sdhci-cdns",
+		.pm = &sdhci_pltfm_pmops,
+		.of_match_table = sdhci_cdns_match,
+	},
+	.probe = sdhci_cdns_probe,
+	.remove = sdhci_pltfm_unregister,
+};
+module_platform_driver(sdhci_cdns_driver);
+
+MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
+MODULE_DESCRIPTION("Cadence SD/SDIO/eMMC Host Controller Driver");
+MODULE_LICENSE("GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci.h linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci.h
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci.h	2017-02-12 16:03:20.000000000 -0500
@@ -656,7 +656,7 @@ extern void sdhci_free_host(struct sdhci
 
 static inline void *sdhci_priv(struct sdhci_host *host)
 {
-	return (void *)host->private;
+	return host->private;
 }
 
 extern void sdhci_card_detect(struct sdhci_host *host);
@@ -682,6 +682,7 @@ static inline bool sdhci_sdio_irq_enable
 u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
 		   unsigned int *actual_clock);
 void sdhci_set_clock(struct sdhci_host *host, unsigned int clock);
+void sdhci_enable_clk(struct sdhci_host *host, u16 clk);
 void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
 		     unsigned short vdd);
 void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
@@ -689,6 +690,7 @@ void sdhci_set_power_noreg(struct sdhci_
 void sdhci_set_bus_width(struct sdhci_host *host, int width);
 void sdhci_reset(struct sdhci_host *host, u8 mask);
 void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
+int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
 
 #ifdef CONFIG_PM
 extern int sdhci_suspend_host(struct sdhci_host *host);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-iproc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-iproc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-iproc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-iproc.c	2017-02-12 16:03:20.000000000 -0500
@@ -143,6 +143,14 @@ static void sdhci_iproc_writeb(struct sd
 }
 
 static const struct sdhci_ops sdhci_iproc_ops = {
+	.set_clock = sdhci_set_clock,
+	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
+	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
+	.set_uhs_signaling = sdhci_set_uhs_signaling,
+};
+
+static const struct sdhci_ops sdhci_iproc_32only_ops = {
 	.read_l = sdhci_iproc_readl,
 	.read_w = sdhci_iproc_readw,
 	.read_b = sdhci_iproc_readb,
@@ -156,6 +164,28 @@ static const struct sdhci_ops sdhci_ipro
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
+static const struct sdhci_pltfm_data sdhci_iproc_cygnus_pltfm_data = {
+	.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
+	.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
+	.ops = &sdhci_iproc_32only_ops,
+};
+
+static const struct sdhci_iproc_data iproc_cygnus_data = {
+	.pdata = &sdhci_iproc_cygnus_pltfm_data,
+	.caps = ((0x1 << SDHCI_MAX_BLOCK_SHIFT)
+			& SDHCI_MAX_BLOCK_MASK) |
+		SDHCI_CAN_VDD_330 |
+		SDHCI_CAN_VDD_180 |
+		SDHCI_CAN_DO_SUSPEND |
+		SDHCI_CAN_DO_HISPD |
+		SDHCI_CAN_DO_ADMA2 |
+		SDHCI_CAN_DO_SDMA,
+	.caps1 = SDHCI_DRIVER_TYPE_C |
+		 SDHCI_DRIVER_TYPE_D |
+		 SDHCI_SUPPORT_DDR50,
+	.mmc_caps = MMC_CAP_1_8V_DDR,
+};
+
 static const struct sdhci_pltfm_data sdhci_iproc_pltfm_data = {
 	.quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK,
 	.quirks2 = SDHCI_QUIRK2_ACMD23_BROKEN,
@@ -182,7 +212,7 @@ static const struct sdhci_pltfm_data sdh
 	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
 		  SDHCI_QUIRK_MISSING_CAPS,
-	.ops = &sdhci_iproc_ops,
+	.ops = &sdhci_iproc_32only_ops,
 };
 
 static const struct sdhci_iproc_data bcm2835_data = {
@@ -194,7 +224,8 @@ static const struct sdhci_iproc_data bcm
 
 static const struct of_device_id sdhci_iproc_of_match[] = {
 	{ .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
-	{ .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_data },
+	{ .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
+	{ .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-msm.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-msm.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-msm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-msm.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,7 +18,9 @@
 #include <linux/of_device.h>
 #include <linux/delay.h>
 #include <linux/mmc/mmc.h>
+#include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/iopoll.h>
 
 #include "sdhci-pltfm.h"
 
@@ -31,6 +33,7 @@
 #define HC_MODE_EN		0x1
 #define CORE_POWER		0x0
 #define CORE_SW_RST		BIT(7)
+#define FF_CLK_SW_RST_DIS	BIT(13)
 
 #define CORE_PWRCTL_STATUS	0xdc
 #define CORE_PWRCTL_MASK	0xe0
@@ -49,6 +52,7 @@
 #define INT_MASK		0xf
 #define MAX_PHASES		16
 #define CORE_DLL_LOCK		BIT(7)
+#define CORE_DDR_DLL_LOCK	BIT(11)
 #define CORE_DLL_EN		BIT(16)
 #define CORE_CDR_EN		BIT(17)
 #define CORE_CK_OUT_EN		BIT(18)
@@ -56,18 +60,67 @@
 #define CORE_DLL_PDN		BIT(29)
 #define CORE_DLL_RST		BIT(30)
 #define CORE_DLL_CONFIG		0x100
+#define CORE_CMD_DAT_TRACK_SEL	BIT(0)
 #define CORE_DLL_STATUS		0x108
 
+#define CORE_DLL_CONFIG_2	0x1b4
+#define CORE_DDR_CAL_EN		BIT(0)
+#define CORE_FLL_CYCLE_CNT	BIT(18)
+#define CORE_DLL_CLOCK_DISABLE	BIT(21)
+
 #define CORE_VENDOR_SPEC	0x10c
 #define CORE_CLK_PWRSAVE	BIT(1)
+#define CORE_HC_MCLK_SEL_DFLT	(2 << 8)
+#define CORE_HC_MCLK_SEL_HS400	(3 << 8)
+#define CORE_HC_MCLK_SEL_MASK	(3 << 8)
+#define CORE_HC_SELECT_IN_EN	BIT(18)
+#define CORE_HC_SELECT_IN_HS400	(6 << 19)
+#define CORE_HC_SELECT_IN_MASK	(7 << 19)
+
+#define CORE_CSR_CDC_CTLR_CFG0		0x130
+#define CORE_SW_TRIG_FULL_CALIB		BIT(16)
+#define CORE_HW_AUTOCAL_ENA		BIT(17)
+
+#define CORE_CSR_CDC_CTLR_CFG1		0x134
+#define CORE_CSR_CDC_CAL_TIMER_CFG0	0x138
+#define CORE_TIMER_ENA			BIT(16)
+
+#define CORE_CSR_CDC_CAL_TIMER_CFG1	0x13C
+#define CORE_CSR_CDC_REFCOUNT_CFG	0x140
+#define CORE_CSR_CDC_COARSE_CAL_CFG	0x144
+#define CORE_CDC_OFFSET_CFG		0x14C
+#define CORE_CSR_CDC_DELAY_CFG		0x150
+#define CORE_CDC_SLAVE_DDA_CFG		0x160
+#define CORE_CSR_CDC_STATUS0		0x164
+#define CORE_CALIBRATION_DONE		BIT(0)
+
+#define CORE_CDC_ERROR_CODE_MASK	0x7000000
+
+#define CORE_CSR_CDC_GEN_CFG		0x178
+#define CORE_CDC_SWITCH_BYPASS_OFF	BIT(0)
+#define CORE_CDC_SWITCH_RC_EN		BIT(1)
+
+#define CORE_DDR_200_CFG		0x184
+#define CORE_CDC_T4_DLY_SEL		BIT(0)
+#define CORE_START_CDC_TRAFFIC		BIT(6)
+#define CORE_VENDOR_SPEC3	0x1b0
+#define CORE_PWRSAVE_DLL	BIT(3)
+
+#define CORE_DDR_CONFIG		0x1b8
+#define DDR_CONFIG_POR_VAL	0x80040853
 
 #define CORE_VENDOR_SPEC_CAPABILITIES0	0x11c
 
+#define INVALID_TUNING_PHASE	-1
+#define SDHCI_MSM_MIN_CLOCK	400000
+#define CORE_FREQ_100MHZ	(100 * 1000 * 1000)
+
 #define CDR_SELEXT_SHIFT	20
 #define CDR_SELEXT_MASK		(0xf << CDR_SELEXT_SHIFT)
 #define CMUX_SHIFT_PHASE_SHIFT	24
 #define CMUX_SHIFT_PHASE_MASK	(7 << CMUX_SHIFT_PHASE_SHIFT)
 
+#define MSM_MMC_AUTOSUSPEND_DELAY_MS	50
 struct sdhci_msm_host {
 	struct platform_device *pdev;
 	void __iomem *core_mem;	/* MSM SDCC mapped address */
@@ -75,7 +128,14 @@ struct sdhci_msm_host {
 	struct clk *clk;	/* main SD/MMC bus clock */
 	struct clk *pclk;	/* SDHC peripheral bus clock */
 	struct clk *bus_clk;	/* SDHC bus voter clock */
+	struct clk *xo_clk;	/* TCXO clk needed for FLL feature of cm_dll*/
+	unsigned long clk_rate;
 	struct mmc_host *mmc;
+	bool use_14lpp_dll_reset;
+	bool tuning_done;
+	bool calibration_done;
+	u8 saved_tuning_phase;
+	bool use_cdclp533;
 };
 
 /* Platform specific tuning */
@@ -115,6 +175,9 @@ static int msm_config_cm_dll_phase(struc
 	u32 config;
 	struct mmc_host *mmc = host->mmc;
 
+	if (phase > 0xf)
+		return -EINVAL;
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
@@ -136,9 +199,9 @@ static int msm_config_cm_dll_phase(struc
 	config |= grey_coded_phase_table[phase] << CDR_SELEXT_SHIFT;
 	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 
-	/* Set CK_OUT_EN bit of DLL_CONFIG register to 1. */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
-			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_CK_OUT_EN;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 
 	/* Wait until CK_OUT_EN bit of DLL_CONFIG register becomes '1' */
 	rc = msm_dll_poll_ck_out_en(host, 1);
@@ -163,8 +226,8 @@ out:
  * Find out the greatest range of consecuitive selected
  * DLL clock output phases that can be used as sampling
  * setting for SD3.0 UHS-I card read operation (in SDR104
- * timing mode) or for eMMC4.5 card read operation (in HS200
- * timing mode).
+ * timing mode) or for eMMC4.5 card read operation (in
+ * HS400/HS200 timing mode).
  * Select the 3/4 of the range and configure the DLL with the
  * selected DLL clock output phase.
  */
@@ -303,8 +366,11 @@ static inline void msm_cm_dll_set_freq(s
 static int msm_init_cm_dll(struct sdhci_host *host)
 {
 	struct mmc_host *mmc = host->mmc;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 	int wait_cnt = 50;
 	unsigned long flags;
+	u32 config;
 
 	spin_lock_irqsave(&host->lock, flags);
 
@@ -313,33 +379,73 @@ static int msm_init_cm_dll(struct sdhci_
 	 * tuning is in progress. Keeping PWRSAVE ON may
 	 * turn off the clock.
 	 */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC)
-			& ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC);
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+	config &= ~CORE_CLK_PWRSAVE;
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
 
-	/* Write 1 to DLL_RST bit of DLL_CONFIG register */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
-			| CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+	if (msm_host->use_14lpp_dll_reset) {
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+		config &= ~CORE_CK_OUT_EN;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 
-	/* Write 1 to DLL_PDN bit of DLL_CONFIG register */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
-			| CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config |= CORE_DLL_CLOCK_DISABLE;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+	}
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_DLL_RST;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_DLL_PDN;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 	msm_cm_dll_set_freq(host);
 
-	/* Write 0 to DLL_RST bit of DLL_CONFIG register */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
-			& ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG);
+	if (msm_host->use_14lpp_dll_reset &&
+	    !IS_ERR_OR_NULL(msm_host->xo_clk)) {
+		u32 mclk_freq = 0;
 
-	/* Write 0 to DLL_PDN bit of DLL_CONFIG register */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
-			& ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG);
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config &= CORE_FLL_CYCLE_CNT;
+		if (config)
+			mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8),
+					clk_get_rate(msm_host->xo_clk));
+		else
+			mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4),
+					clk_get_rate(msm_host->xo_clk));
 
-	/* Set DLL_EN bit to 1. */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
-			| CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG);
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config &= ~(0xFF << 10);
+		config |= mclk_freq << 10;
 
-	/* Set CK_OUT_EN bit to 1. */
-	writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG)
-			| CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG);
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+		/* wait for 5us before enabling DLL clock */
+		udelay(5);
+	}
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config &= ~CORE_DLL_RST;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config &= ~CORE_DLL_PDN;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+	if (msm_host->use_14lpp_dll_reset) {
+		msm_cm_dll_set_freq(host);
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+		config &= ~CORE_DLL_CLOCK_DISABLE;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+	}
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_DLL_EN;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_CK_OUT_EN;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
 
 	/* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */
 	while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) &
@@ -358,6 +464,200 @@ static int msm_init_cm_dll(struct sdhci_
 	return 0;
 }
 
+static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	u32 config, calib_done;
+	int ret;
+
+	pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+	/*
+	 * Retuning in HS400 (DDR mode) will fail, just reset the
+	 * tuning block and restore the saved tuning phase.
+	 */
+	ret = msm_init_cm_dll(host);
+	if (ret)
+		goto out;
+
+	/* Set the selected phase in delay line hw block */
+	ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
+	if (ret)
+		goto out;
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_CMD_DAT_TRACK_SEL;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+	config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+	config &= ~CORE_CDC_T4_DLY_SEL;
+	writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+
+	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+	config &= ~CORE_CDC_SWITCH_BYPASS_OFF;
+	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+	config |= CORE_CDC_SWITCH_RC_EN;
+	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_GEN_CFG);
+
+	config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+	config &= ~CORE_START_CDC_TRAFFIC;
+	writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+
+	/*
+	 * Perform CDC Register Initialization Sequence
+	 *
+	 * CORE_CSR_CDC_CTLR_CFG0	0x11800EC
+	 * CORE_CSR_CDC_CTLR_CFG1	0x3011111
+	 * CORE_CSR_CDC_CAL_TIMER_CFG0	0x1201000
+	 * CORE_CSR_CDC_CAL_TIMER_CFG1	0x4
+	 * CORE_CSR_CDC_REFCOUNT_CFG	0xCB732020
+	 * CORE_CSR_CDC_COARSE_CAL_CFG	0xB19
+	 * CORE_CSR_CDC_DELAY_CFG	0x3AC
+	 * CORE_CDC_OFFSET_CFG		0x0
+	 * CORE_CDC_SLAVE_DDA_CFG	0x16334
+	 */
+
+	writel_relaxed(0x11800EC, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+	writel_relaxed(0x3011111, host->ioaddr + CORE_CSR_CDC_CTLR_CFG1);
+	writel_relaxed(0x1201000, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+	writel_relaxed(0x4, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG1);
+	writel_relaxed(0xCB732020, host->ioaddr + CORE_CSR_CDC_REFCOUNT_CFG);
+	writel_relaxed(0xB19, host->ioaddr + CORE_CSR_CDC_COARSE_CAL_CFG);
+	writel_relaxed(0x3AC, host->ioaddr + CORE_CSR_CDC_DELAY_CFG);
+	writel_relaxed(0x0, host->ioaddr + CORE_CDC_OFFSET_CFG);
+	writel_relaxed(0x16334, host->ioaddr + CORE_CDC_SLAVE_DDA_CFG);
+
+	/* CDC HW Calibration */
+
+	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+	config |= CORE_SW_TRIG_FULL_CALIB;
+	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+	config &= ~CORE_SW_TRIG_FULL_CALIB;
+	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+	config |= CORE_HW_AUTOCAL_ENA;
+	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CTLR_CFG0);
+
+	config = readl_relaxed(host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+	config |= CORE_TIMER_ENA;
+	writel_relaxed(config, host->ioaddr + CORE_CSR_CDC_CAL_TIMER_CFG0);
+
+	ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_CSR_CDC_STATUS0,
+					 calib_done,
+					 (calib_done & CORE_CALIBRATION_DONE),
+					 1, 50);
+
+	if (ret == -ETIMEDOUT) {
+		pr_err("%s: %s: CDC calibration was not completed\n",
+		       mmc_hostname(host->mmc), __func__);
+		goto out;
+	}
+
+	ret = readl_relaxed(host->ioaddr + CORE_CSR_CDC_STATUS0)
+			& CORE_CDC_ERROR_CODE_MASK;
+	if (ret) {
+		pr_err("%s: %s: CDC error code %d\n",
+		       mmc_hostname(host->mmc), __func__, ret);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	config = readl_relaxed(host->ioaddr + CORE_DDR_200_CFG);
+	config |= CORE_START_CDC_TRAFFIC;
+	writel_relaxed(config, host->ioaddr + CORE_DDR_200_CFG);
+out:
+	pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+		 __func__, ret);
+	return ret;
+}
+
+static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
+{
+	u32 dll_status, config;
+	int ret;
+
+	pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+	/*
+	 * Currently the CORE_DDR_CONFIG register defaults to desired
+	 * configuration on reset. Currently reprogramming the power on
+	 * reset (POR) value in case it might have been modified by
+	 * bootloaders. In the future, if this changes, then the desired
+	 * values will need to be programmed appropriately.
+	 */
+	writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + CORE_DDR_CONFIG);
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2);
+	config |= CORE_DDR_CAL_EN;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2);
+
+	ret = readl_relaxed_poll_timeout(host->ioaddr + CORE_DLL_STATUS,
+					 dll_status,
+					 (dll_status & CORE_DDR_DLL_LOCK),
+					 10, 1000);
+
+	if (ret == -ETIMEDOUT) {
+		pr_err("%s: %s: CM_DLL_SDC4 calibration was not completed\n",
+		       mmc_hostname(host->mmc), __func__);
+		goto out;
+	}
+
+	config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC3);
+	config |= CORE_PWRSAVE_DLL;
+	writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC3);
+
+	/*
+	 * Drain writebuffer to ensure above DLL calibration
+	 * and PWRSAVE DLL is enabled.
+	 */
+	wmb();
+out:
+	pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+		 __func__, ret);
+	return ret;
+}
+
+static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	int ret;
+	u32 config;
+
+	pr_debug("%s: %s: Enter\n", mmc_hostname(host->mmc), __func__);
+
+	/*
+	 * Retuning in HS400 (DDR mode) will fail, just reset the
+	 * tuning block and restore the saved tuning phase.
+	 */
+	ret = msm_init_cm_dll(host);
+	if (ret)
+		goto out;
+
+	/* Set the selected phase in delay line hw block */
+	ret = msm_config_cm_dll_phase(host, msm_host->saved_tuning_phase);
+	if (ret)
+		goto out;
+
+	config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+	config |= CORE_CMD_DAT_TRACK_SEL;
+	writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+	if (msm_host->use_cdclp533)
+		ret = sdhci_msm_cdclp533_calibration(host);
+	else
+		ret = sdhci_msm_cm_dll_sdc4_calibration(host);
+out:
+	pr_debug("%s: %s: Exit, ret %d\n", mmc_hostname(host->mmc),
+		 __func__, ret);
+	return ret;
+}
+
 static int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
 {
 	int tuning_seq_cnt = 3;
@@ -365,14 +665,17 @@ static int sdhci_msm_execute_tuning(stru
 	int rc;
 	struct mmc_host *mmc = host->mmc;
 	struct mmc_ios ios = host->mmc->ios;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 
 	/*
 	 * Tuning is required for SDR104, HS200 and HS400 cards and
 	 * if clock frequency is greater than 100MHz in these modes.
 	 */
-	if (host->clock <= 100 * 1000 * 1000 ||
-	    !((ios.timing == MMC_TIMING_MMC_HS200) ||
-	      (ios.timing == MMC_TIMING_UHS_SDR104)))
+	if (host->clock <= CORE_FREQ_100MHZ ||
+	    !(ios.timing == MMC_TIMING_MMC_HS400 ||
+	    ios.timing == MMC_TIMING_MMC_HS200 ||
+	    ios.timing == MMC_TIMING_UHS_SDR104))
 		return 0;
 
 retry:
@@ -388,6 +691,7 @@ retry:
 		if (rc)
 			return rc;
 
+		msm_host->saved_tuning_phase = phase;
 		rc = mmc_send_tuning(mmc, opcode, NULL);
 		if (!rc) {
 			/* Tuning is successful at this tuning point */
@@ -423,6 +727,8 @@ retry:
 		rc = -EIO;
 	}
 
+	if (!rc)
+		msm_host->tuning_done = true;
 	return rc;
 }
 
@@ -430,7 +736,10 @@ static void sdhci_msm_set_uhs_signaling(
 					unsigned int uhs)
 {
 	struct mmc_host *mmc = host->mmc;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 	u16 ctrl_2;
+	u32 config;
 
 	ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 	/* Select Bus Speed Mode for host */
@@ -445,6 +754,7 @@ static void sdhci_msm_set_uhs_signaling(
 	case MMC_TIMING_UHS_SDR50:
 		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
 		break;
+	case MMC_TIMING_MMC_HS400:
 	case MMC_TIMING_MMC_HS200:
 	case MMC_TIMING_UHS_SDR104:
 		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
@@ -461,15 +771,42 @@ static void sdhci_msm_set_uhs_signaling(
 	 * provide feedback clock, the mode selection can be any value less
 	 * than 3'b011 in bits [2:0] of HOST CONTROL2 register.
 	 */
-	if (host->clock <= 100000000 &&
-	    (uhs == MMC_TIMING_MMC_HS400 ||
-	     uhs == MMC_TIMING_MMC_HS200 ||
-	     uhs == MMC_TIMING_UHS_SDR104))
-		ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+	if (host->clock <= CORE_FREQ_100MHZ) {
+		if (uhs == MMC_TIMING_MMC_HS400 ||
+		    uhs == MMC_TIMING_MMC_HS200 ||
+		    uhs == MMC_TIMING_UHS_SDR104)
+			ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+		/*
+		 * DLL is not required for clock <= 100MHz
+		 * Thus, make sure DLL it is disabled when not required
+		 */
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+		config |= CORE_DLL_RST;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+		config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG);
+		config |= CORE_DLL_PDN;
+		writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG);
+
+		/*
+		 * The DLL needs to be restored and CDCLP533 recalibrated
+		 * when the clock frequency is set back to 400MHz.
+		 */
+		msm_host->calibration_done = false;
+	}
 
 	dev_dbg(mmc_dev(mmc), "%s: clock=%u uhs=%u ctrl_2=0x%x\n",
 		mmc_hostname(host->mmc), host->clock, uhs, ctrl_2);
 	sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+
+	spin_unlock_irq(&host->lock);
+	/* CDCLP533 HW calibration is only required for HS400 mode*/
+	if (host->clock > CORE_FREQ_100MHZ &&
+	    msm_host->tuning_done && !msm_host->calibration_done &&
+	    mmc->ios.timing == MMC_TIMING_MMC_HS400)
+		if (!sdhci_msm_hs400_dll_calibration(host))
+			msm_host->calibration_done = true;
+	spin_lock_irq(&host->lock);
 }
 
 static void sdhci_msm_voltage_switch(struct sdhci_host *host)
@@ -505,6 +842,183 @@ static irqreturn_t sdhci_msm_pwr_irq(int
 	return IRQ_HANDLED;
 }
 
+static unsigned int sdhci_msm_get_max_clock(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+	return clk_round_rate(msm_host->clk, ULONG_MAX);
+}
+
+static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
+{
+	return SDHCI_MSM_MIN_CLOCK;
+}
+
+/**
+ * __sdhci_msm_set_clock - sdhci_msm clock control.
+ *
+ * Description:
+ * MSM controller does not use internal divider and
+ * instead directly control the GCC clock as per
+ * HW recommendation.
+ **/
+void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	u16 clk;
+	/*
+	 * Keep actual_clock as zero -
+	 * - since there is no divider used so no need of having actual_clock.
+	 * - MSM controller uses SDCLK for data timeout calculation. If
+	 *   actual_clock is zero, host->clock is taken for calculation.
+	 */
+	host->mmc->actual_clock = 0;
+
+	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+	if (clock == 0)
+		return;
+
+	/*
+	 * MSM controller do not use clock divider.
+	 * Thus read SDHCI_CLOCK_CONTROL and only enable
+	 * clock with no divider value programmed.
+	 */
+	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	sdhci_enable_clk(host, clk);
+}
+
+/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
+static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	struct mmc_ios curr_ios = host->mmc->ios;
+	u32 config, dll_lock;
+	int rc;
+
+	if (!clock) {
+		msm_host->clk_rate = clock;
+		goto out;
+	}
+
+	spin_unlock_irq(&host->lock);
+	/*
+	 * The SDHC requires internal clock frequency to be double the
+	 * actual clock that will be set for DDR mode. The controller
+	 * uses the faster clock(100/400MHz) for some of its parts and
+	 * send the actual required clock (50/200MHz) to the card.
+	 */
+	if (curr_ios.timing == MMC_TIMING_UHS_DDR50 ||
+	    curr_ios.timing == MMC_TIMING_MMC_DDR52 ||
+	    curr_ios.timing == MMC_TIMING_MMC_HS400)
+		clock *= 2;
+	/*
+	 * In general all timing modes are controlled via UHS mode select in
+	 * Host Control2 register. eMMC specific HS200/HS400 doesn't have
+	 * their respective modes defined here, hence we use these values.
+	 *
+	 * HS200 - SDR104 (Since they both are equivalent in functionality)
+	 * HS400 - This involves multiple configurations
+	 *		Initially SDR104 - when tuning is required as HS200
+	 *		Then when switching to DDR @ 400MHz (HS400) we use
+	 *		the vendor specific HC_SELECT_IN to control the mode.
+	 *
+	 * In addition to controlling the modes we also need to select the
+	 * correct input clock for DLL depending on the mode.
+	 *
+	 * HS400 - divided clock (free running MCLK/2)
+	 * All other modes - default (free running MCLK)
+	 */
+	if (curr_ios.timing == MMC_TIMING_MMC_HS400) {
+		/* Select the divided clock (free running MCLK/2) */
+		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+		config &= ~CORE_HC_MCLK_SEL_MASK;
+		config |= CORE_HC_MCLK_SEL_HS400;
+
+		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+		/*
+		 * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC
+		 * register
+		 */
+		if (msm_host->tuning_done && !msm_host->calibration_done) {
+			/*
+			 * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN
+			 * field in VENDOR_SPEC_FUNC
+			 */
+			config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+			config |= CORE_HC_SELECT_IN_HS400;
+			config |= CORE_HC_SELECT_IN_EN;
+			writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+		}
+		if (!msm_host->clk_rate && !msm_host->use_cdclp533) {
+			/*
+			 * Poll on DLL_LOCK or DDR_DLL_LOCK bits in
+			 * CORE_DLL_STATUS to be set.  This should get set
+			 * within 15 us at 200 MHz.
+			 */
+			rc = readl_relaxed_poll_timeout(host->ioaddr +
+							CORE_DLL_STATUS,
+							dll_lock,
+							(dll_lock &
+							(CORE_DLL_LOCK |
+							CORE_DDR_DLL_LOCK)), 10,
+							1000);
+			if (rc == -ETIMEDOUT)
+				pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n",
+				       mmc_hostname(host->mmc), dll_lock);
+		}
+	} else {
+		if (!msm_host->use_cdclp533) {
+			config = readl_relaxed(host->ioaddr +
+					CORE_VENDOR_SPEC3);
+			config &= ~CORE_PWRSAVE_DLL;
+			writel_relaxed(config, host->ioaddr +
+					CORE_VENDOR_SPEC3);
+		}
+
+		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+		config &= ~CORE_HC_MCLK_SEL_MASK;
+		config |= CORE_HC_MCLK_SEL_DFLT;
+		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+
+		/*
+		 * Disable HC_SELECT_IN to be able to use the UHS mode select
+		 * configuration from Host Control2 register for all other
+		 * modes.
+		 * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field
+		 * in VENDOR_SPEC_FUNC
+		 */
+		config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC);
+		config &= ~CORE_HC_SELECT_IN_EN;
+		config &= ~CORE_HC_SELECT_IN_MASK;
+		writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC);
+	}
+
+	/*
+	 * Make sure above writes impacting free running MCLK are completed
+	 * before changing the clk_rate at GCC.
+	 */
+	wmb();
+
+	rc = clk_set_rate(msm_host->clk, clock);
+	if (rc) {
+		pr_err("%s: Failed to set clock at rate %u at timing %d\n",
+		       mmc_hostname(host->mmc), clock,
+		       curr_ios.timing);
+		goto out_lock;
+	}
+	msm_host->clk_rate = clock;
+	pr_debug("%s: Setting clock at rate %lu at timing %d\n",
+		 mmc_hostname(host->mmc), clk_get_rate(msm_host->clk),
+		 curr_ios.timing);
+
+out_lock:
+	spin_lock_irq(&host->lock);
+out:
+	__sdhci_msm_set_clock(host, clock);
+}
+
 static const struct of_device_id sdhci_msm_dt_match[] = {
 	{ .compatible = "qcom,sdhci-msm-v4" },
 	{},
@@ -515,7 +1029,9 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat
 static const struct sdhci_ops sdhci_msm_ops = {
 	.platform_execute_tuning = sdhci_msm_execute_tuning,
 	.reset = sdhci_reset,
-	.set_clock = sdhci_set_clock,
+	.set_clock = sdhci_msm_set_clock,
+	.get_min_clock = sdhci_msm_get_min_clock,
+	.get_max_clock = sdhci_msm_get_max_clock,
 	.set_bus_width = sdhci_set_bus_width,
 	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
 	.voltage_switch = sdhci_msm_voltage_switch,
@@ -524,7 +1040,9 @@ static const struct sdhci_ops sdhci_msm_
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {
 	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
 		  SDHCI_QUIRK_NO_CARD_NO_RESET |
-		  SDHCI_QUIRK_SINGLE_POWER_WRITE,
+		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
+		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 	.ops = &sdhci_msm_ops,
 };
 
@@ -536,7 +1054,7 @@ static int sdhci_msm_probe(struct platfo
 	struct resource *core_memres;
 	int ret;
 	u16 host_version, core_minor;
-	u32 core_version, caps;
+	u32 core_version, config;
 	u8 core_major;
 
 	host = sdhci_pltfm_init(pdev, &sdhci_msm_pdata, sizeof(*msm_host));
@@ -554,6 +1072,8 @@ static int sdhci_msm_probe(struct platfo
 
 	sdhci_get_of_property(pdev);
 
+	msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
+
 	/* Setup SDCC bus voter clock. */
 	msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
 	if (!IS_ERR(msm_host->bus_clk)) {
@@ -586,6 +1106,16 @@ static int sdhci_msm_probe(struct platfo
 		goto pclk_disable;
 	}
 
+	/*
+	 * xo clock is needed for FLL feature of cm_dll.
+	 * In case if xo clock is not mentioned in DT, warn and proceed.
+	 */
+	msm_host->xo_clk = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(msm_host->xo_clk)) {
+		ret = PTR_ERR(msm_host->xo_clk);
+		dev_warn(&pdev->dev, "TCXO clk not present (%d)\n", ret);
+	}
+
 	/* Vote for maximum clock rate for maximum performance */
 	ret = clk_set_rate(msm_host->clk, INT_MAX);
 	if (ret)
@@ -604,9 +1134,9 @@ static int sdhci_msm_probe(struct platfo
 		goto clk_disable;
 	}
 
-	/* Reset the core and Enable SDHC mode */
-	writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
-		       CORE_SW_RST, msm_host->core_mem + CORE_POWER);
+	config = readl_relaxed(msm_host->core_mem + CORE_POWER);
+	config |= CORE_SW_RST;
+	writel_relaxed(config, msm_host->core_mem + CORE_POWER);
 
 	/* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */
 	usleep_range(1000, 5000);
@@ -619,6 +1149,10 @@ static int sdhci_msm_probe(struct platfo
 	/* Set HC_MODE_EN bit in HC_MODE register */
 	writel_relaxed(HC_MODE_EN, (msm_host->core_mem + CORE_HC_MODE));
 
+	config = readl_relaxed(msm_host->core_mem + CORE_HC_MODE);
+	config |= FF_CLK_SW_RST_DIS;
+	writel_relaxed(config, msm_host->core_mem + CORE_HC_MODE);
+
 	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
 	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
 		host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
@@ -631,14 +1165,24 @@ static int sdhci_msm_probe(struct platfo
 	dev_dbg(&pdev->dev, "MCI Version: 0x%08x, major: 0x%04x, minor: 0x%02x\n",
 		core_version, core_major, core_minor);
 
+	if (core_major == 1 && core_minor >= 0x42)
+		msm_host->use_14lpp_dll_reset = true;
+
+	/*
+	 * SDCC 5 controller with major version 1, minor version 0x34 and later
+	 * with HS 400 mode support will use CM DLL instead of CDC LP 533 DLL.
+	 */
+	if (core_major == 1 && core_minor < 0x34)
+		msm_host->use_cdclp533 = true;
+
 	/*
 	 * Support for some capabilities is not advertised by newer
 	 * controller versions and must be explicitly enabled.
 	 */
 	if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
-		caps = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
-		caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
-		writel_relaxed(caps, host->ioaddr +
+		config = readl_relaxed(host->ioaddr + SDHCI_CAPABILITIES);
+		config |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
+		writel_relaxed(config, host->ioaddr +
 			       CORE_VENDOR_SPEC_CAPABILITIES0);
 	}
 
@@ -659,12 +1203,26 @@ static int sdhci_msm_probe(struct platfo
 		goto clk_disable;
 	}
 
+	pm_runtime_get_noresume(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_set_autosuspend_delay(&pdev->dev,
+					 MSM_MMC_AUTOSUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(&pdev->dev);
+
 	ret = sdhci_add_host(host);
 	if (ret)
-		goto clk_disable;
+		goto pm_runtime_disable;
+
+	pm_runtime_mark_last_busy(&pdev->dev);
+	pm_runtime_put_autosuspend(&pdev->dev);
 
 	return 0;
 
+pm_runtime_disable:
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
 clk_disable:
 	clk_disable_unprepare(msm_host->clk);
 pclk_disable:
@@ -686,6 +1244,11 @@ static int sdhci_msm_remove(struct platf
 		    0xffffffff);
 
 	sdhci_remove_host(host, dead);
+
+	pm_runtime_get_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
 	clk_disable_unprepare(msm_host->clk);
 	clk_disable_unprepare(msm_host->pclk);
 	if (!IS_ERR(msm_host->bus_clk))
@@ -694,12 +1257,57 @@ static int sdhci_msm_remove(struct platf
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int sdhci_msm_runtime_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+
+	clk_disable_unprepare(msm_host->clk);
+	clk_disable_unprepare(msm_host->pclk);
+
+	return 0;
+}
+
+static int sdhci_msm_runtime_resume(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
+	int ret;
+
+	ret = clk_prepare_enable(msm_host->clk);
+	if (ret) {
+		dev_err(dev, "clk_enable failed for core_clk: %d\n", ret);
+		return ret;
+	}
+	ret = clk_prepare_enable(msm_host->pclk);
+	if (ret) {
+		dev_err(dev, "clk_enable failed for iface_clk: %d\n", ret);
+		clk_disable_unprepare(msm_host->clk);
+		return ret;
+	}
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops sdhci_msm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(sdhci_msm_runtime_suspend,
+			   sdhci_msm_runtime_resume,
+			   NULL)
+};
+
 static struct platform_driver sdhci_msm_driver = {
 	.probe = sdhci_msm_probe,
 	.remove = sdhci_msm_remove,
 	.driver = {
 		   .name = "sdhci_msm",
 		   .of_match_table = sdhci_msm_dt_match,
+		   .pm = &sdhci_msm_pm_ops,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-of-at91.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-of-at91.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-of-at91.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-of-at91.c	2017-02-12 16:03:20.000000000 -0500
@@ -100,6 +100,7 @@ static const struct of_device_id sdhci_a
 	{ .compatible = "atmel,sama5d2-sdhci", .data = &soc_data_sama5d2 },
 	{}
 };
+MODULE_DEVICE_TABLE(of, sdhci_at91_dt_match);
 
 #ifdef CONFIG_PM
 static int sdhci_at91_runtime_suspend(struct device *dev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-of-esdhc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-of-esdhc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-of-esdhc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-of-esdhc.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/sys_soc.h>
 #include <linux/mmc/host.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -28,6 +29,7 @@
 struct sdhci_esdhc {
 	u8 vendor_ver;
 	u8 spec_ver;
+	bool quirk_incorrect_hostver;
 };
 
 /**
@@ -87,6 +89,8 @@ static u32 esdhc_readl_fixup(struct sdhc
 static u16 esdhc_readw_fixup(struct sdhci_host *host,
 				     int spec_reg, u32 value)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 	u16 ret;
 	int shift = (spec_reg & 0x2) * 8;
 
@@ -94,6 +98,12 @@ static u16 esdhc_readw_fixup(struct sdhc
 		ret = value & 0xffff;
 	else
 		ret = (value >> shift) & 0xffff;
+	/* Workaround for T4240-R1.0-R2.0 eSDHC which has incorrect
+	 * vendor version and spec version information.
+	 */
+	if ((spec_reg == SDHCI_HOST_VERSION) &&
+	    (esdhc->quirk_incorrect_hostver))
+		ret = (VENDOR_V_23 << SDHCI_VENDOR_VER_SHIFT) | SDHCI_SPEC_200;
 	return ret;
 }
 
@@ -572,6 +582,12 @@ static const struct sdhci_pltfm_data sdh
 	.ops = &sdhci_esdhc_le_ops,
 };
 
+static struct soc_device_attribute soc_incorrect_hostver[] = {
+	{ .family = "QorIQ T4240", .revision = "1.0", },
+	{ .family = "QorIQ T4240", .revision = "2.0", },
+	{ },
+};
+
 static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host;
@@ -585,6 +601,10 @@ static void esdhc_init(struct platform_d
 	esdhc->vendor_ver = (host_ver & SDHCI_VENDOR_VER_MASK) >>
 			     SDHCI_VENDOR_VER_SHIFT;
 	esdhc->spec_ver = host_ver & SDHCI_SPEC_VER_MASK;
+	if (soc_device_match(soc_incorrect_hostver))
+		esdhc->quirk_incorrect_hostver = true;
+	else
+		esdhc->quirk_incorrect_hostver = false;
 }
 
 static int sdhci_esdhc_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-pci-core.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-pci-core.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-pci-core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-pci-core.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/mmc/slot-gpio.h>
 #include <linux/mmc/sdhci-pci-data.h>
+#include <linux/acpi.h>
 
 #include "sdhci.h"
 #include "sdhci-pci.h"
@@ -375,6 +376,44 @@ static int byt_emmc_probe_slot(struct sd
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+static int ni_set_max_freq(struct sdhci_pci_slot *slot)
+{
+	acpi_status status;
+	unsigned long long max_freq;
+
+	status = acpi_evaluate_integer(ACPI_HANDLE(&slot->chip->pdev->dev),
+				       "MXFQ", NULL, &max_freq);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&slot->chip->pdev->dev,
+			"MXFQ not found in acpi table\n");
+		return -EINVAL;
+	}
+
+	slot->host->mmc->f_max = max_freq * 1000000;
+
+	return 0;
+}
+#else
+static inline int ni_set_max_freq(struct sdhci_pci_slot *slot)
+{
+	return 0;
+}
+#endif
+
+static int ni_byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
+{
+	int err;
+
+	err = ni_set_max_freq(slot);
+	if (err)
+		return err;
+
+	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
+				 MMC_CAP_WAIT_WHILE_BUSY;
+	return 0;
+}
+
 static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
 {
 	slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
@@ -390,7 +429,8 @@ static int byt_sd_probe_slot(struct sdhc
 	slot->cd_override_level = true;
 	if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXT_SD ||
 	    slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BXTM_SD ||
-	    slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD) {
+	    slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_APL_SD ||
+	    slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_SD) {
 		slot->host->mmc_host_ops.get_cd = bxt_get_cd;
 		slot->host->mmc->caps |= MMC_CAP_AGGRESSIVE_PM;
 	}
@@ -447,6 +487,15 @@ static const struct sdhci_pci_fixes sdhc
 	.ops		= &sdhci_intel_byt_ops,
 };
 
+static const struct sdhci_pci_fixes sdhci_ni_byt_sdio = {
+	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
+	.quirks2	= SDHCI_QUIRK2_HOST_OFF_CARD_ON |
+			  SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+	.allow_runtime_pm = true,
+	.probe_slot	= ni_byt_sdio_probe_slot,
+	.ops		= &sdhci_intel_byt_ops,
+};
+
 static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
 	.quirks2	= SDHCI_QUIRK2_HOST_OFF_CARD_ON |
@@ -1079,6 +1128,14 @@ static const struct pci_device_id pci_id
 	{
 		.vendor		= PCI_VENDOR_ID_INTEL,
 		.device		= PCI_DEVICE_ID_INTEL_BYT_SDIO,
+		.subvendor	= PCI_VENDOR_ID_NI,
+		.subdevice	= 0x7884,
+		.driver_data	= (kernel_ulong_t)&sdhci_ni_byt_sdio,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_BYT_SDIO,
 		.subvendor	= PCI_ANY_ID,
 		.subdevice	= PCI_ANY_ID,
 		.driver_data	= (kernel_ulong_t)&sdhci_intel_byt_sdio,
@@ -1277,6 +1334,30 @@ static const struct pci_device_id pci_id
 	},
 
 	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_GLK_EMMC,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_byt_emmc,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_GLK_SDIO,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_byt_sdio,
+	},
+
+	{
+		.vendor		= PCI_VENDOR_ID_INTEL,
+		.device		= PCI_DEVICE_ID_INTEL_GLK_SD,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (kernel_ulong_t)&sdhci_intel_byt_sd,
+	},
+
+	{
 		.vendor		= PCI_VENDOR_ID_O2,
 		.device		= PCI_DEVICE_ID_O2_8120,
 		.subvendor	= PCI_ANY_ID,
@@ -1735,11 +1816,16 @@ static struct sdhci_pci_slot *sdhci_pci_
 	host->mmc->slotno = slotno;
 	host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;
 
-	if (slot->cd_idx >= 0 &&
-	    mmc_gpiod_request_cd(host->mmc, slot->cd_con_id, slot->cd_idx,
-				 slot->cd_override_level, 0, NULL)) {
-		dev_warn(&pdev->dev, "failed to setup card detect gpio\n");
-		slot->cd_idx = -1;
+	if (slot->cd_idx >= 0) {
+		ret = mmc_gpiod_request_cd(host->mmc, slot->cd_con_id, slot->cd_idx,
+					   slot->cd_override_level, 0, NULL);
+		if (ret == -EPROBE_DEFER)
+			goto remove;
+
+		if (ret) {
+			dev_warn(&pdev->dev, "failed to setup card detect gpio\n");
+			slot->cd_idx = -1;
+		}
 	}
 
 	ret = sdhci_add_host(host);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-pci.h linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-pci.h
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-pci.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-pci.h	2017-02-12 16:03:20.000000000 -0500
@@ -34,6 +34,9 @@
 #define PCI_DEVICE_ID_INTEL_APL_SD	0x5aca
 #define PCI_DEVICE_ID_INTEL_APL_EMMC	0x5acc
 #define PCI_DEVICE_ID_INTEL_APL_SDIO	0x5ad0
+#define PCI_DEVICE_ID_INTEL_GLK_SD	0x31ca
+#define PCI_DEVICE_ID_INTEL_GLK_EMMC	0x31cc
+#define PCI_DEVICE_ID_INTEL_GLK_SDIO	0x31d0
 
 /*
  * PCI registers
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-pltfm.h linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-pltfm.h
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-pltfm.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-pltfm.h	2017-02-12 16:03:20.000000000 -0500
@@ -106,7 +106,7 @@ extern unsigned int sdhci_pltfm_clk_get_
 
 static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
 {
-	return (void *)host->private;
+	return host->private;
 }
 
 extern const struct dev_pm_ops sdhci_pltfm_pmops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sdhci-s3c.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-s3c.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sdhci-s3c.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sdhci-s3c.c	2017-02-12 16:03:20.000000000 -0500
@@ -121,7 +121,9 @@ static unsigned int sdhci_s3c_consider_c
 	 * speed possible with selected clock source and skip the division.
 	 */
 	if (ourhost->no_divider) {
+		spin_unlock_irq(&ourhost->host->lock);
 		rate = clk_round_rate(clksrc, wanted);
+		spin_lock_irq(&ourhost->host->lock);
 		return wanted - rate;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sh_mobile_sdhi.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sh_mobile_sdhi.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sh_mobile_sdhi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sh_mobile_sdhi.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,31 +47,69 @@
 
 #define host_to_priv(host) container_of((host)->pdata, struct sh_mobile_sdhi, mmc_data)
 
+struct sh_mobile_sdhi_scc {
+	unsigned long clk_rate;	/* clock rate for SDR104 */
+	u32 tap;		/* sampling clock position for SDR104 */
+};
+
 struct sh_mobile_sdhi_of_data {
 	unsigned long tmio_flags;
+	u32	      tmio_ocr_mask;
 	unsigned long capabilities;
 	unsigned long capabilities2;
 	enum dma_slave_buswidth dma_buswidth;
 	dma_addr_t dma_rx_offset;
 	unsigned bus_shift;
+	int scc_offset;
+	struct sh_mobile_sdhi_scc *taps;
+	int taps_num;
 };
 
 static const struct sh_mobile_sdhi_of_data of_default_cfg = {
 	.tmio_flags = TMIO_MMC_HAS_IDLE_WAIT,
 };
 
+static const struct sh_mobile_sdhi_of_data of_rz_compatible = {
+	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_32BIT_DATA_PORT,
+	.tmio_ocr_mask	= MMC_VDD_32_33,
+	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
+};
+
 static const struct sh_mobile_sdhi_of_data of_rcar_gen1_compatible = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE |
 			  TMIO_MMC_CLK_ACTUAL,
 	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
 };
 
+/* Definitions for sampling clocks */
+static struct sh_mobile_sdhi_scc rcar_gen2_scc_taps[] = {
+	{
+		.clk_rate = 156000000,
+		.tap = 0x00000703,
+	},
+	{
+		.clk_rate = 0,
+		.tap = 0x00000300,
+	},
+};
+
 static const struct sh_mobile_sdhi_of_data of_rcar_gen2_compatible = {
 	.tmio_flags	= TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_WRPROTECT_DISABLE |
 			  TMIO_MMC_CLK_ACTUAL | TMIO_MMC_MIN_RCAR2,
 	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
 	.dma_buswidth	= DMA_SLAVE_BUSWIDTH_4_BYTES,
 	.dma_rx_offset	= 0x2000,
+	.scc_offset	= 0x0300,
+	.taps		= rcar_gen2_scc_taps,
+	.taps_num	= ARRAY_SIZE(rcar_gen2_scc_taps),
+};
+
+/* Definitions for sampling clocks */
+static struct sh_mobile_sdhi_scc rcar_gen3_scc_taps[] = {
+	{
+		.clk_rate = 0,
+		.tap = 0x00000300,
+	},
 };
 
 static const struct sh_mobile_sdhi_of_data of_rcar_gen3_compatible = {
@@ -79,6 +117,9 @@ static const struct sh_mobile_sdhi_of_da
 			  TMIO_MMC_CLK_ACTUAL | TMIO_MMC_MIN_RCAR2,
 	.capabilities	= MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ,
 	.bus_shift	= 2,
+	.scc_offset	= 0x1000,
+	.taps		= rcar_gen3_scc_taps,
+	.taps_num	= ARRAY_SIZE(rcar_gen3_scc_taps),
 };
 
 static const struct of_device_id sh_mobile_sdhi_of_match[] = {
@@ -86,6 +127,7 @@ static const struct of_device_id sh_mobi
 	{ .compatible = "renesas,sdhi-sh73a0", .data = &of_default_cfg, },
 	{ .compatible = "renesas,sdhi-r8a73a4", .data = &of_default_cfg, },
 	{ .compatible = "renesas,sdhi-r8a7740", .data = &of_default_cfg, },
+	{ .compatible = "renesas,sdhi-r7s72100", .data = &of_rz_compatible, },
 	{ .compatible = "renesas,sdhi-r8a7778", .data = &of_rcar_gen1_compatible, },
 	{ .compatible = "renesas,sdhi-r8a7779", .data = &of_rcar_gen1_compatible, },
 	{ .compatible = "renesas,sdhi-r8a7790", .data = &of_rcar_gen2_compatible, },
@@ -105,6 +147,7 @@ struct sh_mobile_sdhi {
 	struct tmio_mmc_dma dma_priv;
 	struct pinctrl *pinctrl;
 	struct pinctrl_state *pins_default, *pins_uhs;
+	void __iomem *scc_ctl;
 };
 
 static void sh_mobile_sdhi_sdbuf_width(struct tmio_mmc_host *host, int width)
@@ -255,6 +298,201 @@ static int sh_mobile_sdhi_start_signal_v
 	return pinctrl_select_state(priv->pinctrl, pin_state);
 }
 
+/* SCC registers */
+#define SH_MOBILE_SDHI_SCC_DTCNTL	0x000
+#define SH_MOBILE_SDHI_SCC_TAPSET	0x002
+#define SH_MOBILE_SDHI_SCC_DT2FF	0x004
+#define SH_MOBILE_SDHI_SCC_CKSEL	0x006
+#define SH_MOBILE_SDHI_SCC_RVSCNTL	0x008
+#define SH_MOBILE_SDHI_SCC_RVSREQ	0x00A
+
+/* Definitions for values the SH_MOBILE_SDHI_SCC_DTCNTL register */
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN		BIT(0)
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT	16
+#define SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK	0xff
+
+/* Definitions for values the SH_MOBILE_SDHI_SCC_CKSEL register */
+#define SH_MOBILE_SDHI_SCC_CKSEL_DTSEL		BIT(0)
+/* Definitions for values the SH_MOBILE_SDHI_SCC_RVSCNTL register */
+#define SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN	BIT(0)
+/* Definitions for values the SH_MOBILE_SDHI_SCC_RVSREQ register */
+#define SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR	BIT(2)
+
+static inline u32 sd_scc_read32(struct tmio_mmc_host *host,
+				struct sh_mobile_sdhi *priv, int addr)
+{
+	return readl(priv->scc_ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_scc_write32(struct tmio_mmc_host *host,
+				  struct sh_mobile_sdhi *priv,
+				  int addr, u32 val)
+{
+	writel(val, priv->scc_ctl + (addr << host->bus_shift));
+}
+
+static unsigned int sh_mobile_sdhi_init_tuning(struct tmio_mmc_host *host)
+{
+	struct sh_mobile_sdhi *priv;
+
+	if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+		return 0;
+
+	priv = host_to_priv(host);
+
+	/* set sampling clock selection range */
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
+		       0x8 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT);
+
+	/* Initialize SCC */
+	sd_ctrl_write32_as_16_and_16(host, CTL_STATUS, 0x0);
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
+		       SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
+		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL));
+
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+			sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL,
+		       SH_MOBILE_SDHI_SCC_CKSEL_DTSEL |
+		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL));
+
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+			sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+		       ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DT2FF, host->scc_tappos);
+
+	/* Read TAPNUM */
+	return (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL) >>
+		SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) &
+		SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_MASK;
+}
+
+static void sh_mobile_sdhi_prepare_tuning(struct tmio_mmc_host *host,
+					 unsigned long tap)
+{
+	struct sh_mobile_sdhi *priv = host_to_priv(host);
+
+	/* Set sampling clock position */
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, tap);
+}
+
+#define SH_MOBILE_SDHI_MAX_TAP 3
+
+static int sh_mobile_sdhi_select_tuning(struct tmio_mmc_host *host)
+{
+	struct sh_mobile_sdhi *priv = host_to_priv(host);
+	unsigned long tap_cnt;  /* counter of tuning success */
+	unsigned long tap_set;  /* tap position */
+	unsigned long tap_start;/* start position of tuning success */
+	unsigned long tap_end;  /* end position of tuning success */
+	unsigned long ntap;     /* temporary counter of tuning success */
+	unsigned long i;
+
+	/* Clear SCC_RVSREQ */
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
+
+	/*
+	 * Find the longest consecutive run of successful probes.  If that
+	 * is more than SH_MOBILE_SDHI_MAX_TAP probes long then use the
+	 * center index as the tap.
+	 */
+	tap_cnt = 0;
+	ntap = 0;
+	tap_start = 0;
+	tap_end = 0;
+	for (i = 0; i < host->tap_num * 2; i++) {
+		if (test_bit(i, host->taps))
+			ntap++;
+		else {
+			if (ntap > tap_cnt) {
+				tap_start = i - ntap;
+				tap_end = i - 1;
+				tap_cnt = ntap;
+			}
+			ntap = 0;
+		}
+	}
+
+	if (ntap > tap_cnt) {
+		tap_start = i - ntap;
+		tap_end = i - 1;
+		tap_cnt = ntap;
+	}
+
+	if (tap_cnt >= SH_MOBILE_SDHI_MAX_TAP)
+		tap_set = (tap_start + tap_end) / 2 % host->tap_num;
+	else
+		return -EIO;
+
+	/* Set SCC */
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_TAPSET, tap_set);
+
+	/* Enable auto re-tuning */
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+		       SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN |
+		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+	return 0;
+}
+
+
+static bool sh_mobile_sdhi_check_scc_error(struct tmio_mmc_host *host)
+{
+	struct sh_mobile_sdhi *priv;
+
+	if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+		return 0;
+
+	priv = host_to_priv(host);
+
+	/* Check SCC error */
+	if (sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL) &
+	    SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &&
+	    sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ) &
+	    SH_MOBILE_SDHI_SCC_RVSREQ_RVSERR) {
+		/* Clear SCC error */
+		sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSREQ, 0);
+		return true;
+	}
+
+	return false;
+}
+
+static void sh_mobile_sdhi_hw_reset(struct tmio_mmc_host *host)
+{
+	struct sh_mobile_sdhi *priv;
+
+	if (!(host->mmc->caps & MMC_CAP_UHS_SDR104))
+		return;
+
+	priv = host_to_priv(host);
+
+	/* Reset SCC */
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~CLK_CTL_SCLKEN &
+			sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL,
+		       ~SH_MOBILE_SDHI_SCC_CKSEL_DTSEL &
+		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_CKSEL));
+
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, CLK_CTL_SCLKEN |
+			sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+		       ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+
+	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL,
+		       ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN &
+		       sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL));
+}
+
 static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
 {
 	int timeout = 1000;
@@ -325,7 +563,7 @@ static int sh_mobile_sdhi_probe(struct p
 	struct tmio_mmc_data *mmd = pdev->dev.platform_data;
 	struct tmio_mmc_host *host;
 	struct resource *res;
-	int irq, ret, i = 0;
+	int irq, ret, i;
 	struct tmio_mmc_dma *dma_priv;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -364,6 +602,7 @@ static int sh_mobile_sdhi_probe(struct p
 		const struct sh_mobile_sdhi_of_data *of_data = of_id->data;
 
 		mmc_data->flags |= of_data->tmio_flags;
+		mmc_data->ocr_mask = of_data->tmio_ocr_mask;
 		mmc_data->capabilities |= of_data->capabilities;
 		mmc_data->capabilities2 |= of_data->capabilities2;
 		mmc_data->dma_rx_offset = of_data->dma_rx_offset;
@@ -384,6 +623,11 @@ static int sh_mobile_sdhi_probe(struct p
 		host->card_busy	= sh_mobile_sdhi_card_busy;
 		host->start_signal_voltage_switch =
 			sh_mobile_sdhi_start_signal_voltage_switch;
+		host->init_tuning	= sh_mobile_sdhi_init_tuning;
+		host->prepare_tuning	= sh_mobile_sdhi_prepare_tuning;
+		host->select_tuning	= sh_mobile_sdhi_select_tuning;
+		host->check_scc_error	= sh_mobile_sdhi_check_scc_error;
+		host->hw_reset		= sh_mobile_sdhi_hw_reset;
 	}
 
 	/* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */
@@ -424,6 +668,34 @@ static int sh_mobile_sdhi_probe(struct p
 	if (ret < 0)
 		goto efree;
 
+	if (host->mmc->caps & MMC_CAP_UHS_SDR104) {
+		host->mmc->caps |= MMC_CAP_HW_RESET;
+
+		if (of_id && of_id->data) {
+			const struct sh_mobile_sdhi_of_data *of_data;
+			const struct sh_mobile_sdhi_scc *taps;
+			bool hit = false;
+
+			of_data = of_id->data;
+			taps = of_data->taps;
+
+			for (i = 0; i < of_data->taps_num; i++) {
+				if (taps[i].clk_rate == 0 ||
+				    taps[i].clk_rate == host->mmc->f_max) {
+					host->scc_tappos = taps->tap;
+					hit = true;
+					break;
+				}
+			}
+
+			if (!hit)
+				dev_warn(&host->pdev->dev, "Unknown clock rate for SDR104\n");
+
+			priv->scc_ctl = host->ctl + of_data->scc_offset;
+		}
+	}
+
+	i = 0;
 	while (1) {
 		irq = platform_get_irq(pdev, i);
 		if (irq < 0)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/sunxi-mmc.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/sunxi-mmc.c
--- linux-libre-4.9-gnu/drivers/mmc/host/sunxi-mmc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/sunxi-mmc.c	2017-02-12 16:03:20.000000000 -0500
@@ -822,10 +822,13 @@ static void sunxi_mmc_set_ios(struct mmc
 		break;
 
 	case MMC_POWER_UP:
-		host->ferror = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
-						     ios->vdd);
-		if (host->ferror)
-			return;
+		if (!IS_ERR(mmc->supply.vmmc)) {
+			host->ferror = mmc_regulator_set_ocr(mmc,
+							     mmc->supply.vmmc,
+							     ios->vdd);
+			if (host->ferror)
+				return;
+		}
 
 		if (!IS_ERR(mmc->supply.vqmmc)) {
 			host->ferror = regulator_enable(mmc->supply.vqmmc);
@@ -847,7 +850,9 @@ static void sunxi_mmc_set_ios(struct mmc
 	case MMC_POWER_OFF:
 		dev_dbg(mmc_dev(mmc), "power off!\n");
 		sunxi_mmc_reset_host(host);
-		mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+		if (!IS_ERR(mmc->supply.vmmc))
+			mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+
 		if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled)
 			regulator_disable(mmc->supply.vqmmc);
 		host->vqmmc_enabled = false;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/tmio_mmc.h linux-libre-4.10-rc8-gnu/drivers/mmc/host/tmio_mmc.h
--- linux-libre-4.9-gnu/drivers/mmc/host/tmio_mmc.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/tmio_mmc.h	2017-02-12 16:03:20.000000000 -0500
@@ -153,9 +153,12 @@ struct tmio_mmc_host {
 	struct mutex		ios_lock;	/* protect set_ios() context */
 	bool			native_hotplug;
 	bool			sdio_irq_enabled;
+	u32			scc_tappos;
 
-	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+	/* Mandatory callback */
 	int (*clk_enable)(struct tmio_mmc_host *host);
+
+	/* Optional callbacks */
 	unsigned int (*clk_update)(struct tmio_mmc_host *host,
 				   unsigned int new_clock);
 	void (*clk_disable)(struct tmio_mmc_host *host);
@@ -164,6 +167,21 @@ struct tmio_mmc_host {
 	int (*card_busy)(struct mmc_host *mmc);
 	int (*start_signal_voltage_switch)(struct mmc_host *mmc,
 					   struct mmc_ios *ios);
+	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+	void (*hw_reset)(struct tmio_mmc_host *host);
+	void (*prepare_tuning)(struct tmio_mmc_host *host, unsigned long tap);
+	bool (*check_scc_error)(struct tmio_mmc_host *host);
+
+	/*
+	 * Mandatory callback for tuning to occur which is optional for SDR50
+	 * and mandatory for SDR104.
+	 */
+	unsigned int (*init_tuning)(struct tmio_mmc_host *host);
+	int (*select_tuning)(struct tmio_mmc_host *host);
+
+	/* Tuning values: 1 for success, 0 for failure */
+	DECLARE_BITMAP(taps, BITS_PER_BYTE * sizeof(long));
+	unsigned int tap_num;
 };
 
 struct tmio_mmc_host *tmio_mmc_host_alloc(struct platform_device *pdev);
@@ -245,6 +263,12 @@ static inline u32 sd_ctrl_read16_and_16_
 	       readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
 }
 
+static inline void sd_ctrl_read32_rep(struct tmio_mmc_host *host, int addr,
+		u32 *buf, int count)
+{
+	readsl(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
 static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
 {
 	/* If there is a hook and it returns non-zero then there
@@ -267,4 +291,10 @@ static inline void sd_ctrl_write32_as_16
 	writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
 }
 
+static inline void sd_ctrl_write32_rep(struct tmio_mmc_host *host, int addr,
+		const u32 *buf, int count)
+{
+	writesl(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/tmio_mmc_pio.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/tmio_mmc_pio.c
--- linux-libre-4.9-gnu/drivers/mmc/host/tmio_mmc_pio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/tmio_mmc_pio.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,7 +22,6 @@
  * TODO:
  *   Investigate using a workqueue for PIO transfers
  *   Eliminate FIXMEs
- *   SDIO support
  *   Better Power management
  *   Handle MMC errors better
  *   double buffer support
@@ -36,6 +35,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/mfd/tmio.h>
+#include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/slot-gpio.h>
@@ -298,6 +298,9 @@ static void tmio_mmc_finish_request(stru
 	if (mrq->cmd->error || (mrq->data && mrq->data->error))
 		tmio_mmc_abort_dma(host);
 
+	if (host->check_scc_error)
+		host->check_scc_error(host);
+
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -393,6 +396,36 @@ static void tmio_mmc_transfer_data(struc
 	/*
 	 * Transfer the data
 	 */
+	if (host->pdata->flags & TMIO_MMC_32BIT_DATA_PORT) {
+		u8 data[4] = { };
+
+		if (is_read)
+			sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf,
+					   count >> 2);
+		else
+			sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT, (u32 *)buf,
+					    count >> 2);
+
+		/* if count was multiple of 4 */
+		if (!(count & 0x3))
+			return;
+
+		buf8 = (u8 *)(buf + (count >> 2));
+		count %= 4;
+
+		if (is_read) {
+			sd_ctrl_read32_rep(host, CTL_SD_DATA_PORT,
+					   (u32 *)data, 1);
+			memcpy(buf8, data, count);
+		} else {
+			memcpy(data, buf8, count);
+			sd_ctrl_write32_rep(host, CTL_SD_DATA_PORT,
+					    (u32 *)data, 1);
+		}
+
+		return;
+	}
+
 	if (is_read)
 		sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
 	else
@@ -522,7 +555,7 @@ void tmio_mmc_do_data_irq(struct tmio_mm
 	schedule_work(&host->done);
 }
 
-static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
+static void tmio_mmc_data_irq(struct tmio_mmc_host *host, unsigned int stat)
 {
 	struct mmc_data *data;
 	spin_lock(&host->lock);
@@ -531,6 +564,9 @@ static void tmio_mmc_data_irq(struct tmi
 	if (!data)
 		goto out;
 
+	if (stat & TMIO_STAT_CRCFAIL || stat & TMIO_STAT_STOPBIT_ERR ||
+	    stat & TMIO_STAT_TXUNDERRUN)
+		data->error = -EILSEQ;
 	if (host->chan_tx && (data->flags & MMC_DATA_WRITE) && !host->force_pio) {
 		u32 status = sd_ctrl_read16_and_16_as_32(host, CTL_STATUS);
 		bool done = false;
@@ -579,8 +615,6 @@ static void tmio_mmc_cmd_irq(struct tmio
 		goto out;
 	}
 
-	host->cmd = NULL;
-
 	/* This controller is sicker than the PXA one. Not only do we need to
 	 * drop the top 8 bits of the first response word, we also need to
 	 * modify the order of the response for short response command types.
@@ -600,14 +634,16 @@ static void tmio_mmc_cmd_irq(struct tmio
 
 	if (stat & TMIO_STAT_CMDTIMEOUT)
 		cmd->error = -ETIMEDOUT;
-	else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
+	else if ((stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC) ||
+		 stat & TMIO_STAT_STOPBIT_ERR ||
+		 stat & TMIO_STAT_CMD_IDX_ERR)
 		cmd->error = -EILSEQ;
 
 	/* If there is data to handle we enable data IRQs here, and
 	 * we will ultimatley finish the request in the data_end handler.
 	 * If theres no data or we encountered an error, finish now.
 	 */
-	if (host->data && !cmd->error) {
+	if (host->data && (!cmd->error || cmd->error == -EILSEQ)) {
 		if (host->data->flags & MMC_DATA_READ) {
 			if (host->force_pio || !host->chan_rx)
 				tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_READOP);
@@ -668,7 +704,7 @@ static bool __tmio_mmc_sdcard_irq(struct
 	/* Data transfer completion */
 	if (ireg & TMIO_STAT_DATAEND) {
 		tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
-		tmio_mmc_data_irq(host);
+		tmio_mmc_data_irq(host, status);
 		return true;
 	}
 
@@ -687,7 +723,7 @@ static void tmio_mmc_sdio_irq(int irq, v
 		return;
 
 	status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
-	ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdcard_irq_mask;
+	ireg = status & TMIO_SDIO_MASK_ALL & ~host->sdio_irq_mask;
 
 	sdio_status = status & ~TMIO_SDIO_MASK_ALL;
 	if (pdata->flags & TMIO_MMC_SDIO_STATUS_QUIRK)
@@ -756,6 +792,63 @@ static int tmio_mmc_start_data(struct tm
 	return 0;
 }
 
+static void tmio_mmc_hw_reset(struct mmc_host *mmc)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+
+	if (host->hw_reset)
+		host->hw_reset(host);
+}
+
+static int tmio_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+	int i, ret = 0;
+
+	if (!host->tap_num) {
+		if (!host->init_tuning || !host->select_tuning)
+			/* Tuning is not supported */
+			goto out;
+
+		host->tap_num = host->init_tuning(host);
+		if (!host->tap_num)
+			/* Tuning is not supported */
+			goto out;
+	}
+
+	if (host->tap_num * 2 >= sizeof(host->taps) * BITS_PER_BYTE) {
+		dev_warn_once(&host->pdev->dev,
+		      "Too many taps, skipping tuning. Please consider updating size of taps field of tmio_mmc_host\n");
+		goto out;
+	}
+
+	bitmap_zero(host->taps, host->tap_num * 2);
+
+	/* Issue CMD19 twice for each tap */
+	for (i = 0; i < 2 * host->tap_num; i++) {
+		if (host->prepare_tuning)
+			host->prepare_tuning(host, i % host->tap_num);
+
+		ret = mmc_send_tuning(mmc, opcode, NULL);
+		if (ret && ret != -EILSEQ)
+			goto out;
+		if (ret == 0)
+			set_bit(i, host->taps);
+
+		mdelay(1);
+	}
+
+	ret = host->select_tuning(host);
+
+out:
+	if (ret < 0) {
+		dev_warn(&host->pdev->dev, "Tuning procedure failed\n");
+		tmio_mmc_hw_reset(mmc);
+	}
+
+	return ret;
+}
+
 /* Process requests from the MMC layer */
 static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
@@ -972,6 +1065,8 @@ static struct mmc_host_ops tmio_mmc_ops
 	.get_cd		= mmc_gpio_get_cd,
 	.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
 	.multi_io_quirk	= tmio_multi_io_quirk,
+	.hw_reset	= tmio_mmc_hw_reset,
+	.execute_tuning = tmio_mmc_execute_tuning,
 };
 
 static int tmio_mmc_init_ocr(struct tmio_mmc_host *host)
@@ -1218,6 +1313,11 @@ int tmio_mmc_host_runtime_suspend(struct
 }
 EXPORT_SYMBOL(tmio_mmc_host_runtime_suspend);
 
+static bool tmio_mmc_can_retune(struct tmio_mmc_host *host)
+{
+	return host->tap_num && mmc_can_retune(host->mmc);
+}
+
 int tmio_mmc_host_runtime_resume(struct device *dev)
 {
 	struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -1231,6 +1331,9 @@ int tmio_mmc_host_runtime_resume(struct
 
 	tmio_mmc_enable_dma(host, true);
 
+	if (tmio_mmc_can_retune(host) && host->select_tuning(host))
+		dev_warn(&host->pdev->dev, "Tuning selection failed\n");
+
 	return 0;
 }
 EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/host/wbsd.c linux-libre-4.10-rc8-gnu/drivers/mmc/host/wbsd.c
--- linux-libre-4.9-gnu/drivers/mmc/host/wbsd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/host/wbsd.c	2017-02-12 16:03:20.000000000 -0500
@@ -1395,23 +1395,25 @@ static void wbsd_request_dma(struct wbsd
 	 */
 	host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
 		WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(mmc_dev(host->mmc), host->dma_addr))
+		goto kfree;
 
 	/*
 	 * ISA DMA must be aligned on a 64k basis.
 	 */
 	if ((host->dma_addr & 0xffff) != 0)
-		goto kfree;
+		goto unmap;
 	/*
 	 * ISA cannot access memory above 16 MB.
 	 */
 	else if (host->dma_addr >= 0x1000000)
-		goto kfree;
+		goto unmap;
 
 	host->dma = dma;
 
 	return;
 
-kfree:
+unmap:
 	/*
 	 * If we've gotten here then there is some kind of alignment bug
 	 */
@@ -1421,6 +1423,7 @@ kfree:
 		WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
 	host->dma_addr = 0;
 
+kfree:
 	kfree(host->dma_buffer);
 	host->dma_buffer = NULL;
 
@@ -1434,7 +1437,7 @@ err:
 
 static void wbsd_release_dma(struct wbsd_host *host)
 {
-	if (host->dma_addr) {
+	if (!dma_mapping_error(mmc_dev(host->mmc), host->dma_addr)) {
 		dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
 			WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/Kconfig linux-libre-4.10-rc8-gnu/drivers/mmc/Kconfig
--- linux-libre-4.9-gnu/drivers/mmc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -23,8 +23,6 @@ if MMC
 
 source "drivers/mmc/core/Kconfig"
 
-source "drivers/mmc/card/Kconfig"
-
 source "drivers/mmc/host/Kconfig"
 
 endif # MMC
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mmc/Makefile linux-libre-4.10-rc8-gnu/drivers/mmc/Makefile
--- linux-libre-4.9-gnu/drivers/mmc/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mmc/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -5,5 +5,4 @@
 subdir-ccflags-$(CONFIG_MMC_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_MMC)		+= core/
-obj-$(CONFIG_MMC)		+= card/
 obj-$(subst m,y,$(CONFIG_MMC))	+= host/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/bcm47xxpart.c linux-libre-4.10-rc8-gnu/drivers/mtd/bcm47xxpart.c
--- linux-libre-4.9-gnu/drivers/mtd/bcm47xxpart.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/bcm47xxpart.c	2017-02-12 16:03:20.000000000 -0500
@@ -229,12 +229,10 @@ static int bcm47xxpart_parse(struct mtd_
 
 			last_trx_part = curr_part - 1;
 
-			/*
-			 * We have whole TRX scanned, skip to the next part. Use
-			 * roundown (not roundup), as the loop will increase
-			 * offset in next step.
-			 */
-			offset = rounddown(offset + trx->length, blocksize);
+			/* Jump to the end of TRX */
+			offset = roundup(offset + trx->length, blocksize);
+			/* Next loop iteration will increase the offset */
+			offset -= blocksize;
 			continue;
 		}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/devices/bcm47xxsflash.c linux-libre-4.10-rc8-gnu/drivers/mtd/devices/bcm47xxsflash.c
--- linux-libre-4.9-gnu/drivers/mtd/devices/bcm47xxsflash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/devices/bcm47xxsflash.c	2017-02-12 16:03:20.000000000 -0500
@@ -296,16 +296,30 @@ static int bcm47xxsflash_bcma_probe(stru
 		dev_err(dev, "can't request region for resource %pR\n", res);
 		return -EBUSY;
 	}
-	b47s->window = ioremap_cache(res->start, resource_size(res));
-	if (!b47s->window) {
-		dev_err(dev, "ioremap failed for resource %pR\n", res);
-		return -ENOMEM;
-	}
 
 	b47s->bcma_cc = container_of(sflash, struct bcma_drv_cc, sflash);
 	b47s->cc_read = bcm47xxsflash_bcma_cc_read;
 	b47s->cc_write = bcm47xxsflash_bcma_cc_write;
 
+	/*
+	 * On old MIPS devices cache was magically invalidated when needed,
+	 * allowing us to use cached access and gain some performance. Trying
+	 * the same on ARM based BCM53573 results in flash corruptions, we need
+	 * to use uncached access for it.
+	 *
+	 * It may be arch specific, but right now there is only 1 ARM SoC using
+	 * this driver, so let's follow Broadcom's reference code and check
+	 * ChipCommon revision.
+	 */
+	if (b47s->bcma_cc->core->id.rev == 54)
+		b47s->window = ioremap_nocache(res->start, resource_size(res));
+	else
+		b47s->window = ioremap_cache(res->start, resource_size(res));
+	if (!b47s->window) {
+		dev_err(dev, "ioremap failed for resource %pR\n", res);
+		return -ENOMEM;
+	}
+
 	switch (b47s->bcma_cc->capabilities & BCMA_CC_CAP_FLASHT) {
 	case BCMA_CC_FLASHT_STSER:
 		b47s->type = BCM47XXSFLASH_TYPE_ST;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/devices/pmc551.c linux-libre-4.10-rc8-gnu/drivers/mtd/devices/pmc551.c
--- linux-libre-4.9-gnu/drivers/mtd/devices/pmc551.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/devices/pmc551.c	2017-02-12 16:03:20.000000000 -0500
@@ -82,7 +82,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/devices/slram.c linux-libre-4.10-rc8-gnu/drivers/mtd/devices/slram.c
--- linux-libre-4.9-gnu/drivers/mtd/devices/slram.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/devices/slram.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 
 
 #include <linux/module.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/ftl.c linux-libre-4.10-rc8-gnu/drivers/mtd/ftl.c
--- linux-libre-4.9-gnu/drivers/mtd/ftl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/ftl.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,7 +70,7 @@
 #include <linux/hdreg.h>
 #include <linux/vmalloc.h>
 #include <linux/blkpg.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/mtd/ftl.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/inftlcore.c linux-libre-4.10-rc8-gnu/drivers/mtd/inftlcore.c
--- linux-libre-4.9-gnu/drivers/mtd/inftlcore.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/inftlcore.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,7 +34,7 @@
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/inftl.h>
 #include <linux/mtd/nand.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/inftlmount.c linux-libre-4.10-rc8-gnu/drivers/mtd/inftlmount.c
--- linux-libre-4.9-gnu/drivers/mtd/inftlmount.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/inftlmount.c	2017-02-12 16:03:20.000000000 -0500
@@ -27,7 +27,7 @@
 #include <linux/module.h>
 #include <asm/errno.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/maps/sc520cdp.c linux-libre-4.10-rc8-gnu/drivers/mtd/maps/sc520cdp.c
--- linux-libre-4.9-gnu/drivers/mtd/maps/sc520cdp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/maps/sc520cdp.c	2017-02-12 16:03:20.000000000 -0500
@@ -227,7 +227,7 @@ static void sc520cdp_setup_par(void)
 
 static int __init init_sc520cdp(void)
 {
-	int i, devices_found = 0;
+	int i, j, devices_found = 0;
 
 #ifdef REPROGRAM_PAR
 	/* reprogram PAR registers so flash appears at the desired addresses */
@@ -243,6 +243,12 @@ static int __init init_sc520cdp(void)
 
 		if (!sc520cdp_map[i].virt) {
 			printk("Failed to ioremap_nocache\n");
+			for (j = 0; j < i; j++) {
+				if (mymtd[j]) {
+					map_destroy(mymtd[j]);
+					iounmap(sc520cdp_map[j].virt);
+				}
+			}
 			return -EIO;
 		}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/maps/sun_uflash.c linux-libre-4.10-rc8-gnu/drivers/mtd/maps/sun_uflash.c
--- linux-libre-4.9-gnu/drivers/mtd/maps/sun_uflash.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/maps/sun_uflash.c	2017-02-12 16:03:20.000000000 -0500
@@ -16,7 +16,7 @@
 #include <linux/of_device.h>
 #include <linux/slab.h>
 #include <asm/prom.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/mtd/mtd.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/mtd_blkdevs.c linux-libre-4.10-rc8-gnu/drivers/mtd/mtd_blkdevs.c
--- linux-libre-4.9-gnu/drivers/mtd/mtd_blkdevs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/mtd_blkdevs.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/hdreg.h>
 #include <linux/mutex.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "mtdcore.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/mtdchar.c linux-libre-4.10-rc8-gnu/drivers/mtd/mtdchar.c
--- linux-libre-4.9-gnu/drivers/mtd/mtdchar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/mtdchar.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/map.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "mtdcore.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/mtdcore.c linux-libre-4.10-rc8-gnu/drivers/mtd/mtdcore.c
--- linux-libre-4.9-gnu/drivers/mtd/mtdcore.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/mtdcore.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,8 +46,7 @@
 
 #include "mtdcore.h"
 
-static struct backing_dev_info mtd_bdi = {
-};
+static struct backing_dev_info *mtd_bdi;
 
 #ifdef CONFIG_PM_SLEEP
 
@@ -500,7 +499,7 @@ int add_mtd_device(struct mtd_info *mtd)
 	if (WARN_ONCE(mtd->backing_dev_info, "MTD already registered\n"))
 		return -EEXIST;
 
-	mtd->backing_dev_info = &mtd_bdi;
+	mtd->backing_dev_info = mtd_bdi;
 
 	BUG_ON(mtd->writesize == 0);
 	mutex_lock(&mtd_table_mutex);
@@ -1274,8 +1273,8 @@ static int mtd_ooblayout_get_bytes(struc
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
-	int section = 0, ret;
+	struct mtd_oob_region oobregion;
+	int section, ret;
 
 	ret = mtd_ooblayout_find_region(mtd, start, &section,
 					&oobregion, iter);
@@ -1283,7 +1282,7 @@ static int mtd_ooblayout_get_bytes(struc
 	while (!ret) {
 		int cnt;
 
-		cnt = oobregion.length > nbytes ? nbytes : oobregion.length;
+		cnt = min_t(int, nbytes, oobregion.length);
 		memcpy(buf, oobbuf + oobregion.offset, cnt);
 		buf += cnt;
 		nbytes -= cnt;
@@ -1317,8 +1316,8 @@ static int mtd_ooblayout_set_bytes(struc
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
-	int section = 0, ret;
+	struct mtd_oob_region oobregion;
+	int section, ret;
 
 	ret = mtd_ooblayout_find_region(mtd, start, &section,
 					&oobregion, iter);
@@ -1326,7 +1325,7 @@ static int mtd_ooblayout_set_bytes(struc
 	while (!ret) {
 		int cnt;
 
-		cnt = oobregion.length > nbytes ? nbytes : oobregion.length;
+		cnt = min_t(int, nbytes, oobregion.length);
 		memcpy(oobbuf + oobregion.offset, buf, cnt);
 		buf += cnt;
 		nbytes -= cnt;
@@ -1354,7 +1353,7 @@ static int mtd_ooblayout_count_bytes(str
 					    int section,
 					    struct mtd_oob_region *oobregion))
 {
-	struct mtd_oob_region oobregion = { };
+	struct mtd_oob_region oobregion;
 	int section = 0, ret, nbytes = 0;
 
 	while (1) {
@@ -1771,18 +1770,20 @@ static const struct file_operations mtd_
 /*====================================================================*/
 /* Init code */
 
-static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name)
+static struct backing_dev_info * __init mtd_bdi_init(char *name)
 {
+	struct backing_dev_info *bdi;
 	int ret;
 
-	ret = bdi_init(bdi);
-	if (!ret)
-		ret = bdi_register(bdi, NULL, "%s", name);
+	bdi = kzalloc(sizeof(*bdi), GFP_KERNEL);
+	if (!bdi)
+		return ERR_PTR(-ENOMEM);
 
+	ret = bdi_setup_and_register(bdi, name);
 	if (ret)
-		bdi_destroy(bdi);
+		kfree(bdi);
 
-	return ret;
+	return ret ? ERR_PTR(ret) : bdi;
 }
 
 static struct proc_dir_entry *proc_mtd;
@@ -1795,9 +1796,11 @@ static int __init init_mtd(void)
 	if (ret)
 		goto err_reg;
 
-	ret = mtd_bdi_init(&mtd_bdi, "mtd");
-	if (ret)
+	mtd_bdi = mtd_bdi_init("mtd");
+	if (IS_ERR(mtd_bdi)) {
+		ret = PTR_ERR(mtd_bdi);
 		goto err_bdi;
+	}
 
 	proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops);
 
@@ -1810,6 +1813,8 @@ static int __init init_mtd(void)
 out_procfs:
 	if (proc_mtd)
 		remove_proc_entry("mtd", NULL);
+	bdi_destroy(mtd_bdi);
+	kfree(mtd_bdi);
 err_bdi:
 	class_unregister(&mtd_class);
 err_reg:
@@ -1823,7 +1828,8 @@ static void __exit cleanup_mtd(void)
 	if (proc_mtd)
 		remove_proc_entry("mtd", NULL);
 	class_unregister(&mtd_class);
-	bdi_destroy(&mtd_bdi);
+	bdi_destroy(mtd_bdi);
+	kfree(mtd_bdi);
 	idr_destroy(&mtd_idr);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/mtdswap.c linux-libre-4.10-rc8-gnu/drivers/mtd/mtdswap.c
--- linux-libre-4.9-gnu/drivers/mtd/mtdswap.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/mtdswap.c	2017-02-12 16:03:20.000000000 -0500
@@ -587,7 +587,7 @@ retry:
 	ret = wait_event_interruptible(wq, erase.state == MTD_ERASE_DONE ||
 					   erase.state == MTD_ERASE_FAILED);
 	if (ret) {
-		dev_err(d->dev, "Interrupted erase block %#llx erassure on %s",
+		dev_err(d->dev, "Interrupted erase block %#llx erasure on %s\n",
 			erase.addr, mtd->name);
 		return -EINTR;
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/ams-delta.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/ams-delta.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/ams-delta.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/ams-delta.c	2017-02-12 16:03:20.000000000 -0500
@@ -234,10 +234,9 @@ static int ams_delta_init(struct platfor
 		goto out_gpio;
 
 	/* Scan to find existence of the device */
-	if (nand_scan(ams_delta_mtd, 1)) {
-		err = -ENXIO;
+	err = nand_scan(ams_delta_mtd, 1);
+	if (err)
 		goto out_mtd;
-	}
 
 	/* Register the partitions */
 	mtd_device_register(ams_delta_mtd, partition_info,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/atmel_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/atmel_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/atmel_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/atmel_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -2267,10 +2267,9 @@ static int atmel_nand_probe(struct platf
 		dev_info(host->dev, "No DMA support for NAND access.\n");
 
 	/* first scan to find the device and get the page size */
-	if (nand_scan_ident(mtd, 1, NULL)) {
-		res = -ENXIO;
+	res = nand_scan_ident(mtd, 1, NULL);
+	if (res)
 		goto err_scan_ident;
-	}
 
 	if (host->board.on_flash_bbt || on_flash_bbt)
 		nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
@@ -2304,10 +2303,9 @@ static int atmel_nand_probe(struct platf
 	}
 
 	/* second phase scan */
-	if (nand_scan_tail(mtd)) {
-		res = -ENXIO;
+	res = nand_scan_tail(mtd);
+	if (res)
 		goto err_scan_tail;
-	}
 
 	mtd->name = "atmel_nand";
 	res = mtd_device_register(mtd, host->board.parts,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/brcmnand/brcmnand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/brcmnand/brcmnand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/brcmnand/brcmnand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/brcmnand/brcmnand.c	2017-02-12 16:03:20.000000000 -0500
@@ -2209,8 +2209,9 @@ static int brcmnand_init_cs(struct brcmn
 	nand_writereg(ctrl, cfg_offs,
 		      nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH);
 
-	if (nand_scan_ident(mtd, 1, NULL))
-		return -ENXIO;
+	ret = nand_scan_ident(mtd, 1, NULL);
+	if (ret)
+		return ret;
 
 	chip->options |= NAND_NO_SUBPAGE_WRITE;
 	/*
@@ -2234,8 +2235,9 @@ static int brcmnand_init_cs(struct brcmn
 	if (ret)
 		return ret;
 
-	if (nand_scan_tail(mtd))
-		return -ENXIO;
+	ret = nand_scan_tail(mtd);
+	if (ret)
+		return ret;
 
 	return mtd_device_register(mtd, NULL, 0);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/cafe_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/cafe_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/cafe_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/cafe_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -725,10 +725,9 @@ static int cafe_nand_probe(struct pci_de
 	usedma = 0;
 
 	/* Scan to find existence of the device */
-	if (nand_scan_ident(mtd, 2, NULL)) {
-		err = -ENXIO;
+	err = nand_scan_ident(mtd, 2, NULL);
+	if (err)
 		goto out_irq;
-	}
 
 	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev,
 				2112 + sizeof(struct nand_buffers) +
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/cmx270_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/cmx270_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/cmx270_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/cmx270_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -195,9 +195,9 @@ static int __init cmx270_init(void)
 	this->write_buf = cmx270_write_buf;
 
 	/* Scan to find existence of the device */
-	if (nand_scan (cmx270_nand_mtd, 1)) {
+	ret = nand_scan(cmx270_nand_mtd, 1);
+	if (ret) {
 		pr_notice("No NAND device\n");
-		ret = -ENXIO;
 		goto err_scan;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/cs553x_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/cs553x_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/cs553x_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/cs553x_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -242,10 +242,9 @@ static int __init cs553x_init_one(int cs
 	}
 
 	/* Scan to find existence of the device */
-	if (nand_scan(new_mtd, 1)) {
-		err = -ENXIO;
+	err = nand_scan(new_mtd, 1);
+	if (err)
 		goto out_free;
-	}
 
 	cs553x_mtd[cs] = new_mtd;
 	goto out;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/denali.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/denali.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/wait.h>
 #include <linux/mutex.h>
-#include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
 
@@ -182,9 +181,6 @@ static uint16_t denali_nand_reset(struct
 {
 	int i;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		__FILE__, __LINE__, __func__);
-
 	for (i = 0; i < denali->max_banks; i++)
 		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
 		denali->flash_reg + INTR_STATUS(i));
@@ -234,9 +230,6 @@ static void nand_onfi_timing_set(struct
 	uint16_t acc_clks;
 	uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		__FILE__, __LINE__, __func__);
-
 	en_lo = CEIL_DIV(Trp[mode], CLK_X);
 	en_hi = CEIL_DIV(Treh[mode], CLK_X);
 #if ONFI_BLOOM_TIME
@@ -403,7 +396,7 @@ static void get_hynix_nand_para(struct d
 		break;
 	default:
 		dev_warn(denali->dev,
-			 "Spectra: Unknown Hynix NAND (Device ID: 0x%x).\n"
+			 "Unknown Hynix NAND (Device ID: 0x%x).\n"
 			 "Will use default parameter values instead.\n",
 			 device_id);
 	}
@@ -474,33 +467,6 @@ static void detect_max_banks(struct dena
 		denali->max_banks = 1 << (features & FEATURES__N_BANKS);
 }
 
-static void detect_partition_feature(struct denali_nand_info *denali)
-{
-	/*
-	 * For MRST platform, denali->fwblks represent the
-	 * number of blocks firmware is taken,
-	 * FW is in protect partition and MTD driver has no
-	 * permission to access it. So let driver know how many
-	 * blocks it can't touch.
-	 */
-	if (ioread32(denali->flash_reg + FEATURES) & FEATURES__PARTITION) {
-		if ((ioread32(denali->flash_reg + PERM_SRC_ID(1)) &
-			PERM_SRC_ID__SRCID) == SPECTRA_PARTITION_ID) {
-			denali->fwblks =
-			    ((ioread32(denali->flash_reg + MIN_MAX_BANK(1)) &
-			      MIN_MAX_BANK__MIN_VALUE) *
-			     denali->blksperchip)
-			    +
-			    (ioread32(denali->flash_reg + MIN_BLK_ADDR(1)) &
-			    MIN_BLK_ADDR__VALUE);
-		} else {
-			denali->fwblks = SPECTRA_START_BLOCK;
-		}
-	} else {
-		denali->fwblks = SPECTRA_START_BLOCK;
-	}
-}
-
 static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 {
 	uint16_t status = PASS;
@@ -508,9 +474,6 @@ static uint16_t denali_nand_timing_set(s
 	uint8_t maf_id, device_id;
 	int i;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-			__FILE__, __LINE__, __func__);
-
 	/*
 	 * Use read id method to get device ID and other params.
 	 * For some NAND chips, controller can't report the correct
@@ -552,8 +515,6 @@ static uint16_t denali_nand_timing_set(s
 
 	find_valid_banks(denali);
 
-	detect_partition_feature(denali);
-
 	/*
 	 * If the user specified to override the default timings
 	 * with a specific ONFI mode, we apply those changes here.
@@ -567,9 +528,6 @@ static uint16_t denali_nand_timing_set(s
 static void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 {
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		__FILE__, __LINE__, __func__);
-
 	if (INT_ENABLE)
 		iowrite32(1, denali->flash_reg + GLOBAL_INT_ENABLE);
 	else
@@ -605,7 +563,6 @@ static void denali_irq_init(struct denal
 static void denali_irq_cleanup(int irqnum, struct denali_nand_info *denali)
 {
 	denali_set_intr_modes(denali, false);
-	free_irq(irqnum, denali);
 }
 
 static void denali_irq_enable(struct denali_nand_info *denali,
@@ -1437,9 +1394,6 @@ static struct nand_bbt_descr bbt_mirror_
 /* initialize driver data structures */
 static void denali_drv_init(struct denali_nand_info *denali)
 {
-	denali->idx = 0;
-
-	/* setup interrupt handler */
 	/*
 	 * the completion object will be used to notify
 	 * the callee that the interrupt is done
@@ -1485,14 +1439,12 @@ int denali_init(struct denali_nand_info
 	denali_hw_init(denali);
 	denali_drv_init(denali);
 
-	/*
-	 * denali_isr register is done after all the hardware
-	 * initilization is finished
-	 */
-	if (request_irq(denali->irq, denali_isr, IRQF_SHARED,
-			DENALI_NAND_NAME, denali)) {
-		pr_err("Spectra: Unable to allocate IRQ\n");
-		return -ENODEV;
+	/* Request IRQ after all the hardware initialization is finished */
+	ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
+			       IRQF_SHARED, DENALI_NAND_NAME, denali);
+	if (ret) {
+		dev_err(denali->dev, "Unable to request IRQ\n");
+		return ret;
 	}
 
 	/* now that our ISR is registered, we can enable interrupts */
@@ -1510,10 +1462,9 @@ int denali_init(struct denali_nand_info
 	 * this is the first stage in a two step process to register
 	 * with the nand subsystem
 	 */
-	if (nand_scan_ident(mtd, denali->max_banks, NULL)) {
-		ret = -ENXIO;
+	ret = nand_scan_ident(mtd, denali->max_banks, NULL);
+	if (ret)
 		goto failed_req_irq;
-	}
 
 	/* allocate the right size buffer now */
 	devm_kfree(denali->dev, denali->buf.buf);
@@ -1528,7 +1479,7 @@ int denali_init(struct denali_nand_info
 	/* Is 32-bit DMA supported? */
 	ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
 	if (ret) {
-		pr_err("Spectra: no usable DMA configuration\n");
+		dev_err(denali->dev, "No usable DMA configuration\n");
 		goto failed_req_irq;
 	}
 
@@ -1536,7 +1487,7 @@ int denali_init(struct denali_nand_info
 			     mtd->writesize + mtd->oobsize,
 			     DMA_BIDIRECTIONAL);
 	if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
-		dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
+		dev_err(denali->dev, "Failed to map DMA buffer\n");
 		ret = -EIO;
 		goto failed_req_irq;
 	}
@@ -1547,16 +1498,16 @@ int denali_init(struct denali_nand_info
 	 * the real pagesize and anything necessery
 	 */
 	denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED);
-	denali->nand.chipsize <<= (denali->devnum - 1);
-	denali->nand.page_shift += (denali->devnum - 1);
+	denali->nand.chipsize <<= denali->devnum - 1;
+	denali->nand.page_shift += denali->devnum - 1;
 	denali->nand.pagemask = (denali->nand.chipsize >>
 						denali->nand.page_shift) - 1;
-	denali->nand.bbt_erase_shift += (denali->devnum - 1);
+	denali->nand.bbt_erase_shift += denali->devnum - 1;
 	denali->nand.phys_erase_shift = denali->nand.bbt_erase_shift;
-	denali->nand.chip_shift += (denali->devnum - 1);
-	mtd->writesize <<= (denali->devnum - 1);
-	mtd->oobsize <<= (denali->devnum - 1);
-	mtd->erasesize <<= (denali->devnum - 1);
+	denali->nand.chip_shift += denali->devnum - 1;
+	mtd->writesize <<= denali->devnum - 1;
+	mtd->oobsize <<= denali->devnum - 1;
+	mtd->erasesize <<= denali->devnum - 1;
 	mtd->size = denali->nand.numchips * denali->nand.chipsize;
 	denali->bbtskipbytes *= denali->devnum;
 
@@ -1606,14 +1557,6 @@ int denali_init(struct denali_nand_info
 	denali->nand.ecc.bytes *= denali->devnum;
 	denali->nand.ecc.strength *= denali->devnum;
 
-	/*
-	 * Let driver know the total blocks number and how many blocks
-	 * contained by each nand chip. blksperchip will help driver to
-	 * know how many blocks is taken by FW.
-	 */
-	denali->totalblks = mtd->size >> denali->nand.phys_erase_shift;
-	denali->blksperchip = denali->totalblks / denali->nand.numchips;
-
 	/* override the default read operations */
 	denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum;
 	denali->nand.ecc.read_page = denali_read_page;
@@ -1624,15 +1567,13 @@ int denali_init(struct denali_nand_info
 	denali->nand.ecc.write_oob = denali_write_oob;
 	denali->nand.erase = denali_erase;
 
-	if (nand_scan_tail(mtd)) {
-		ret = -ENXIO;
+	ret = nand_scan_tail(mtd);
+	if (ret)
 		goto failed_req_irq;
-	}
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
-		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
-				ret);
+		dev_err(denali->dev, "Failed to register MTD: %d\n", ret);
 		goto failed_req_irq;
 	}
 	return 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/denali_dt.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali_dt.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/denali_dt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali_dt.c	2017-02-12 16:03:20.000000000 -0500
@@ -21,7 +21,6 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/slab.h>
 
 #include "denali.h"
 
@@ -110,7 +109,7 @@ static int denali_dt_remove(struct platf
 	struct denali_dt *dt = platform_get_drvdata(ofdev);
 
 	denali_remove(&dt->denali);
-	clk_disable(dt->clk);
+	clk_disable_unprepare(dt->clk);
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/denali.h linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali.h
--- linux-libre-4.9-gnu/drivers/mtd/nand/denali.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali.h	2017-02-12 16:03:20.000000000 -0500
@@ -383,14 +383,6 @@
 #define CLK_X  5
 #define CLK_MULTI 4
 
-/* spectraswconfig.h */
-#define CMD_DMA 0
-
-#define SPECTRA_PARTITION_ID    0
-/**** Block Table and Reserved Block Parameters *****/
-#define SPECTRA_START_BLOCK     3
-#define NUM_FREE_BLOCKS_GATE    30
-
 /* KBV - Updated to LNW scratch register address */
 #define SCRATCH_REG_ADDR    CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR
 #define SCRATCH_REG_SIZE    64
@@ -467,13 +459,9 @@ struct denali_nand_info {
 	spinlock_t irq_lock;
 	uint32_t irq_status;
 	int irq_debug_array[32];
-	int idx;
 	int irq;
 
 	uint32_t devnum;	/* represent how many nands connected */
-	uint32_t fwblks; /* represent how many blocks FW used */
-	uint32_t totalblks;
-	uint32_t blksperchip;
 	uint32_t bbtskipbytes;
 	uint32_t max_banks;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/denali_pci.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali_pci.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/denali_pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/denali_pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/slab.h>
 
 #include "denali.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/fsmc_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/fsmc_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/fsmc_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/fsmc_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -926,8 +926,8 @@ static int __init fsmc_nand_probe(struct
 	/*
 	 * Scan to find existence of the device
 	 */
-	if (nand_scan_ident(mtd, 1, NULL)) {
-		ret = -ENXIO;
+	ret = nand_scan_ident(mtd, 1, NULL);
+	if (ret) {
 		dev_err(&pdev->dev, "No NAND Device found!\n");
 		goto err_scan_ident;
 	}
@@ -992,10 +992,9 @@ static int __init fsmc_nand_probe(struct
 	}
 
 	/* Second stage of scan to fill MTD data-structures */
-	if (nand_scan_tail(mtd)) {
-		ret = -ENXIO;
+	ret = nand_scan_tail(mtd);
+	if (ret)
 		goto err_probe;
-	}
 
 	/*
 	 * The partition information can is accessed by (in the same precedence)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/gpio.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/gpio.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/gpio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/gpio.c	2017-02-12 16:03:20.000000000 -0500
@@ -286,10 +286,9 @@ static int gpio_nand_probe(struct platfo
 	if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
 		gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
 
-	if (nand_scan(mtd, 1)) {
-		ret = -ENXIO;
+	ret = nand_scan(mtd, 1);
+	if (ret)
 		goto err_wp;
-	}
 
 	if (gpiomtd->plat.adjust_parts)
 		gpiomtd->plat.adjust_parts(&gpiomtd->plat, mtd->size);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/hisi504_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/hisi504_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/hisi504_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/hisi504_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -774,10 +774,8 @@ static int hisi_nfc_probe(struct platfor
 	}
 
 	ret = nand_scan_ident(mtd, max_chips, NULL);
-	if (ret) {
-		ret = -ENODEV;
+	if (ret)
 		goto err_res;
-	}
 
 	host->buffer = dmam_alloc_coherent(dev, mtd->writesize + mtd->oobsize,
 		&host->dma_buffer, GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/Kconfig linux-libre-4.10-rc8-gnu/drivers/mtd/nand/Kconfig
--- linux-libre-4.9-gnu/drivers/mtd/nand/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -179,15 +179,6 @@ config MTD_NAND_S3C2410_DEBUG
 	help
 	  Enable debugging of the S3C NAND driver
 
-config MTD_NAND_S3C2410_HWECC
-	bool "Samsung S3C NAND Hardware ECC"
-	depends on MTD_NAND_S3C2410
-	help
-	  Enable the use of the controller's internal ECC generator when
-	  using NAND. Early versions of the chips have had problems with
-	  incorrect ECC generation, and if using these, the default of
-	  software ECC is preferable.
-
 config MTD_NAND_NDFC
 	tristate "NDFC NanD Flash Controller"
 	depends on 4xx
@@ -205,6 +196,13 @@ config MTD_NAND_S3C2410_CLKSTOP
 	  when the is NAND chip selected or released, but will save
 	  approximately 5mA of power when there is nothing happening.
 
+config MTD_NAND_TANGO
+	tristate "NAND Flash support for Tango chips"
+	depends on ARCH_TANGO || COMPILE_TEST
+	depends on HAS_DMA
+	help
+	  Enables the NAND Flash controller on Tango chips.
+
 config MTD_NAND_DISKONCHIP
 	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation)"
 	depends on HAS_IOMEM
@@ -426,6 +424,12 @@ config MTD_NAND_ORION
 	  No board specific support is done by this driver, each board
 	  must advertise a platform_device for the driver to attach.
 
+config MTD_NAND_OXNAS
+	tristate "NAND Flash support for Oxford Semiconductor SoC"
+	depends on HAS_IOMEM
+	help
+	  This enables the NAND flash controller on Oxford Semiconductor SoCs.
+
 config MTD_NAND_FSL_ELBC
 	tristate "NAND support for Freescale eLBC controllers"
 	depends on FSL_SOC
@@ -537,7 +541,7 @@ config MTD_NAND_FSMC
 	  Flexible Static Memory Controller (FSMC)
 
 config MTD_NAND_XWAY
-	tristate "Support for NAND on Lantiq XWAY SoC"
+	bool "Support for NAND on Lantiq XWAY SoC"
 	depends on LANTIQ && SOC_TYPE_XWAY
 	help
 	  Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/lpc32xx_mlc.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/lpc32xx_mlc.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/lpc32xx_mlc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/lpc32xx_mlc.c	2017-02-12 16:03:20.000000000 -0500
@@ -747,10 +747,9 @@ static int lpc32xx_nand_probe(struct pla
 	 * Scan to find existance of the device and
 	 * Get the type of NAND device SMALL block or LARGE block
 	 */
-	if (nand_scan_ident(mtd, 1, NULL)) {
-		res = -ENXIO;
+	res = nand_scan_ident(mtd, 1, NULL);
+	if (res)
 		goto err_exit3;
-	}
 
 	host->dma_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
 	if (!host->dma_buf) {
@@ -776,7 +775,7 @@ static int lpc32xx_nand_probe(struct pla
 	init_completion(&host->comp_controller);
 
 	host->irq = platform_get_irq(pdev, 0);
-	if ((host->irq < 0) || (host->irq >= NR_IRQS)) {
+	if (host->irq < 0) {
 		dev_err(&pdev->dev, "failed to get platform irq\n");
 		res = -EINVAL;
 		goto err_exit3;
@@ -793,10 +792,9 @@ static int lpc32xx_nand_probe(struct pla
 	 * Fills out all the uninitialized function pointers with the defaults
 	 * And scans for a bad block table if appropriate.
 	 */
-	if (nand_scan_tail(mtd)) {
-		res = -ENXIO;
+	res = nand_scan_tail(mtd);
+	if (res)
 		goto err_exit4;
-	}
 
 	mtd->name = DRV_NAME;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/lpc32xx_slc.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/lpc32xx_slc.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/lpc32xx_slc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/lpc32xx_slc.c	2017-02-12 16:03:20.000000000 -0500
@@ -894,10 +894,9 @@ static int lpc32xx_nand_probe(struct pla
 	}
 
 	/* Find NAND device */
-	if (nand_scan_ident(mtd, 1, NULL)) {
-		res = -ENXIO;
+	res = nand_scan_ident(mtd, 1, NULL);
+	if (res)
 		goto err_exit3;
-	}
 
 	/* OOB and ECC CPU and DMA work areas */
 	host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
@@ -929,10 +928,9 @@ static int lpc32xx_nand_probe(struct pla
 	/*
 	 * Fills out all the uninitialized function pointers with the defaults
 	 */
-	if (nand_scan_tail(mtd)) {
-		res = -ENXIO;
+	res = nand_scan_tail(mtd);
+	if (res)
 		goto err_exit3;
-	}
 
 	mtd->name = "nxp_lpc3220_slc";
 	res = mtd_device_register(mtd, host->ncfg->parts,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/Makefile linux-libre-4.10-rc8-gnu/drivers/mtd/nand/Makefile
--- linux-libre-4.9-gnu/drivers/mtd/nand/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -16,6 +16,7 @@ obj-$(CONFIG_MTD_NAND_DENALI_DT)	+= dena
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
 obj-$(CONFIG_MTD_NAND_S3C2410)		+= s3c2410.o
+obj-$(CONFIG_MTD_NAND_TANGO)		+= tango_nand.o
 obj-$(CONFIG_MTD_NAND_DAVINCI)		+= davinci_nand.o
 obj-$(CONFIG_MTD_NAND_DISKONCHIP)	+= diskonchip.o
 obj-$(CONFIG_MTD_NAND_DOCG4)		+= docg4.o
@@ -35,6 +36,7 @@ obj-$(CONFIG_MTD_NAND_TMIO)		+= tmio_nan
 obj-$(CONFIG_MTD_NAND_PLATFORM)		+= plat_nand.o
 obj-$(CONFIG_MTD_NAND_PASEMI)		+= pasemi_nand.o
 obj-$(CONFIG_MTD_NAND_ORION)		+= orion_nand.o
+obj-$(CONFIG_MTD_NAND_OXNAS)		+= oxnas_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_ELBC)		+= fsl_elbc_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_IFC)		+= fsl_ifc_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_UPM)		+= fsl_upm.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/mpc5121_nfc.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/mpc5121_nfc.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/mpc5121_nfc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/mpc5121_nfc.c	2017-02-12 16:03:20.000000000 -0500
@@ -777,9 +777,9 @@ static int mpc5121_nfc_probe(struct plat
 	}
 
 	/* Detect NAND chips */
-	if (nand_scan(mtd, be32_to_cpup(chips_no))) {
+	retval = nand_scan(mtd, be32_to_cpup(chips_no));
+	if (retval) {
 		dev_err(dev, "NAND Flash not found !\n");
-		retval = -ENXIO;
 		goto error;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/mtk_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/mtk_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/mtk_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/mtk_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -1297,7 +1297,7 @@ static int mtk_nfc_nand_chip_init(struct
 
 	ret = nand_scan_ident(mtd, nsels, NULL);
 	if (ret)
-		return -ENODEV;
+		return ret;
 
 	/* store bbt magic in page, cause OOB is not protected */
 	if (nand->bbt_options & NAND_BBT_USE_FLASH)
@@ -1323,7 +1323,7 @@ static int mtk_nfc_nand_chip_init(struct
 
 	ret = nand_scan_tail(mtd);
 	if (ret)
-		return -ENODEV;
+		return ret;
 
 	ret = mtd_device_parse_register(mtd, NULL, NULL, NULL, 0);
 	if (ret) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/mxc_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/mxc_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/mxc_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/mxc_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -1747,10 +1747,9 @@ static int mxcnd_probe(struct platform_d
 	}
 
 	/* first scan to find the device and get the page size */
-	if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
-		err = -ENXIO;
+	err = nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL);
+	if (err)
 		goto escan;
-	}
 
 	switch (this->ecc.mode) {
 	case NAND_ECC_HW:
@@ -1808,10 +1807,9 @@ static int mxcnd_probe(struct platform_d
 	}
 
 	/* second phase scan */
-	if (nand_scan_tail(mtd)) {
-		err = -ENXIO;
+	err = nand_scan_tail(mtd);
+	if (err)
 		goto escan;
-	}
 
 	/* Register the partitions */
 	mtd_device_parse_register(mtd, part_probes,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/nand_base.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nand_base.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/nand_base.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nand_base.c	2017-02-12 16:03:20.000000000 -0500
@@ -709,6 +709,25 @@ static void nand_command(struct mtd_info
 	nand_wait_ready(mtd);
 }
 
+static void nand_ccs_delay(struct nand_chip *chip)
+{
+	/*
+	 * The controller already takes care of waiting for tCCS when the RNDIN
+	 * or RNDOUT command is sent, return directly.
+	 */
+	if (!(chip->options & NAND_WAIT_TCCS))
+		return;
+
+	/*
+	 * Wait tCCS_min if it is correctly defined, otherwise wait 500ns
+	 * (which should be safe for all NANDs).
+	 */
+	if (chip->data_interface && chip->data_interface->timings.sdr.tCCS_min)
+		ndelay(chip->data_interface->timings.sdr.tCCS_min / 1000);
+	else
+		ndelay(500);
+}
+
 /**
  * nand_command_lp - [DEFAULT] Send command to NAND large page device
  * @mtd: MTD device structure
@@ -773,10 +792,13 @@ static void nand_command_lp(struct mtd_i
 	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE2:
 	case NAND_CMD_SEQIN:
-	case NAND_CMD_RNDIN:
 	case NAND_CMD_STATUS:
 		return;
 
+	case NAND_CMD_RNDIN:
+		nand_ccs_delay(chip);
+		return;
+
 	case NAND_CMD_RESET:
 		if (chip->dev_ready)
 			break;
@@ -795,6 +817,8 @@ static void nand_command_lp(struct mtd_i
 			       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
 		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
 			       NAND_NCE | NAND_CTRL_CHANGE);
+
+		nand_ccs_delay(chip);
 		return;
 
 	case NAND_CMD_READ0:
@@ -1946,7 +1970,8 @@ static int nand_do_read_ops(struct mtd_i
 						 __func__, buf);
 
 read_retry:
-			chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+			if (nand_standard_page_accessors(&chip->ecc))
+				chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
 
 			/*
 			 * Now read the page into the buffer.  Absent an error,
@@ -2634,7 +2659,8 @@ static int nand_write_page(struct mtd_in
 	else
 		subpage = 0;
 
-	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+	if (nand_standard_page_accessors(&chip->ecc))
+		chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
 
 	if (unlikely(raw))
 		status = chip->ecc.write_page_raw(mtd, chip, buf,
@@ -2657,7 +2683,8 @@ static int nand_write_page(struct mtd_in
 
 	if (!cached || !NAND_HAS_CACHEPROG(chip)) {
 
-		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+		if (nand_standard_page_accessors(&chip->ecc))
+			chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 		status = chip->waitfunc(mtd, chip);
 		/*
 		 * See if operation failed and additional status checks are
@@ -3985,10 +4012,9 @@ static bool find_full_id_nand(struct mtd
 /*
  * 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,
-						  int *maf_id, int *dev_id,
-						  struct nand_flash_dev *type)
+static int nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip,
+			       int *maf_id, int *dev_id,
+			       struct nand_flash_dev *type)
 {
 	int busw;
 	int i, maf_idx;
@@ -4026,7 +4052,7 @@ static struct nand_flash_dev *nand_get_f
 	if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
 		pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
 			*maf_id, *dev_id, id_data[0], id_data[1]);
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 	}
 
 	if (!type)
@@ -4053,7 +4079,7 @@ static struct nand_flash_dev *nand_get_f
 	}
 
 	if (!type->name)
-		return ERR_PTR(-ENODEV);
+		return -ENODEV;
 
 	if (!mtd->name)
 		mtd->name = type->name;
@@ -4098,7 +4124,7 @@ ident_done:
 		pr_warn("bus width %d instead %d bit\n",
 			   (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
 			   busw ? 16 : 8);
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
 	nand_decode_bbm_options(mtd, chip, id_data);
@@ -4140,7 +4166,7 @@ ident_done:
 	pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
 		(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
 		mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
-	return type;
+	return 0;
 }
 
 static const char * const nand_ecc_modes[] = {
@@ -4306,7 +4332,6 @@ int nand_scan_ident(struct mtd_info *mtd
 {
 	int i, nand_maf_id, nand_dev_id;
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_flash_dev *type;
 	int ret;
 
 	ret = nand_dt_init(chip);
@@ -4329,14 +4354,12 @@ int nand_scan_ident(struct mtd_info *mtd
 	nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
 
 	/* Read the flash type */
-	type = nand_get_flash_type(mtd, chip, &nand_maf_id,
-				   &nand_dev_id, table);
-
-	if (IS_ERR(type)) {
+	ret = nand_get_flash_type(mtd, chip, &nand_maf_id, &nand_dev_id, table);
+	if (ret) {
 		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
 			pr_warn("No NAND device found\n");
 		chip->select_chip(mtd, -1);
-		return PTR_ERR(type);
+		return ret;
 	}
 
 	/* Initialize the ->data_interface field. */
@@ -4515,6 +4538,26 @@ static bool nand_ecc_strength_good(struc
 	return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds;
 }
 
+static bool invalid_ecc_page_accessors(struct nand_chip *chip)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+	if (nand_standard_page_accessors(ecc))
+		return false;
+
+	/*
+	 * NAND_ECC_CUSTOM_PAGE_ACCESS flag is set, make sure the NAND
+	 * controller driver implements all the page accessors because
+	 * default helpers are not suitable when the core does not
+	 * send the READ0/PAGEPROG commands.
+	 */
+	return (!ecc->read_page || !ecc->write_page ||
+		!ecc->read_page_raw || !ecc->write_page_raw ||
+		(NAND_HAS_SUBPAGE_READ(chip) && !ecc->read_subpage) ||
+		(NAND_HAS_SUBPAGE_WRITE(chip) && !ecc->write_subpage &&
+		 ecc->hwctl && ecc->calculate));
+}
+
 /**
  * nand_scan_tail - [NAND Interface] Scan for the NAND device
  * @mtd: MTD device structure
@@ -4535,6 +4578,11 @@ int nand_scan_tail(struct mtd_info *mtd)
 		   !(chip->bbt_options & NAND_BBT_USE_FLASH)))
 		return -EINVAL;
 
+	if (invalid_ecc_page_accessors(chip)) {
+		pr_err("Invalid ECC page accessors setup\n");
+		return -EINVAL;
+	}
+
 	if (!(chip->options & NAND_OWN_BUFFERS)) {
 		nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
 				+ mtd->oobsize * 3, GFP_KERNEL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/nand_ids.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nand_ids.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/nand_ids.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nand_ids.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,9 @@ struct nand_flash_dev nand_flash_ids[] =
 	{"TC58NVG2S0F 4G 3.3V 8-bit",
 		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
 		  SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },
+	{"TC58NVG2S0H 4G 3.3V 8-bit",
+		{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x16, 0x08, 0x00} },
+		  SZ_4K, SZ_512, SZ_256K, 0, 8, 256, NAND_ECC_INFO(8, SZ_512) },
 	{"TC58NVG3S0F 8G 3.3V 8-bit",
 		{ .id = {0x98, 0xd3, 0x90, 0x26, 0x76, 0x15, 0x02, 0x08} },
 		  SZ_4K, SZ_1K, SZ_256K, 0, 8, 232, NAND_ECC_INFO(4, SZ_512) },
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/nandsim.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nandsim.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/nandsim.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nandsim.c	2017-02-12 16:03:20.000000000 -0500
@@ -525,24 +525,20 @@ static int nandsim_debugfs_create(struct
 {
 	struct nandsim_debug_info *dbg = &dev->dbg;
 	struct dentry *dent;
-	int err;
 
 	if (!IS_ENABLED(CONFIG_DEBUG_FS))
 		return 0;
 
 	dent = debugfs_create_dir("nandsim", NULL);
-	if (IS_ERR_OR_NULL(dent)) {
-		int err = dent ? -ENODEV : PTR_ERR(dent);
-
-		NS_ERR("cannot create \"nandsim\" debugfs directory, err %d\n",
-			err);
-		return err;
+	if (!dent) {
+		NS_ERR("cannot create \"nandsim\" debugfs directory\n");
+		return -ENODEV;
 	}
 	dbg->dfs_root = dent;
 
 	dent = debugfs_create_file("wear_report", S_IRUSR,
 				   dbg->dfs_root, dev, &dfs_fops);
-	if (IS_ERR_OR_NULL(dent))
+	if (!dent)
 		goto out_remove;
 	dbg->dfs_wear_report = dent;
 
@@ -550,8 +546,7 @@ static int nandsim_debugfs_create(struct
 
 out_remove:
 	debugfs_remove_recursive(dbg->dfs_root);
-	err = dent ? PTR_ERR(dent) : -ENODEV;
-	return err;
+	return -ENODEV;
 }
 
 /**
@@ -2313,8 +2308,6 @@ static int __init ns_init_module(void)
 	retval = nand_scan_ident(nsmtd, 1, NULL);
 	if (retval) {
 		NS_ERR("cannot scan NAND Simulator device\n");
-		if (retval > 0)
-			retval = -ENXIO;
 		goto error;
 	}
 
@@ -2350,8 +2343,6 @@ static int __init ns_init_module(void)
 	retval = nand_scan_tail(nsmtd);
 	if (retval) {
 		NS_ERR("can't register NAND Simulator\n");
-		if (retval > 0)
-			retval = -ENXIO;
 		goto error;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/nand_timings.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nand_timings.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/nand_timings.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/nand_timings.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,6 +18,8 @@ static const struct nand_data_interface
 	{
 		.type = NAND_SDR_IFACE,
 		.timings.sdr = {
+			.tCCS_min = 500000,
+			.tR_max = 200000000,
 			.tADL_min = 400000,
 			.tALH_min = 20000,
 			.tALS_min = 50000,
@@ -58,6 +60,8 @@ static const struct nand_data_interface
 	{
 		.type = NAND_SDR_IFACE,
 		.timings.sdr = {
+			.tCCS_min = 500000,
+			.tR_max = 200000000,
 			.tADL_min = 400000,
 			.tALH_min = 10000,
 			.tALS_min = 25000,
@@ -98,6 +102,8 @@ static const struct nand_data_interface
 	{
 		.type = NAND_SDR_IFACE,
 		.timings.sdr = {
+			.tCCS_min = 500000,
+			.tR_max = 200000000,
 			.tADL_min = 400000,
 			.tALH_min = 10000,
 			.tALS_min = 15000,
@@ -138,6 +144,8 @@ static const struct nand_data_interface
 	{
 		.type = NAND_SDR_IFACE,
 		.timings.sdr = {
+			.tCCS_min = 500000,
+			.tR_max = 200000000,
 			.tADL_min = 400000,
 			.tALH_min = 5000,
 			.tALS_min = 10000,
@@ -178,6 +186,8 @@ static const struct nand_data_interface
 	{
 		.type = NAND_SDR_IFACE,
 		.timings.sdr = {
+			.tCCS_min = 500000,
+			.tR_max = 200000000,
 			.tADL_min = 400000,
 			.tALH_min = 5000,
 			.tALS_min = 10000,
@@ -218,6 +228,8 @@ static const struct nand_data_interface
 	{
 		.type = NAND_SDR_IFACE,
 		.timings.sdr = {
+			.tCCS_min = 500000,
+			.tR_max = 200000000,
 			.tADL_min = 400000,
 			.tALH_min = 5000,
 			.tALS_min = 10000,
@@ -290,10 +302,22 @@ int onfi_init_data_interface(struct nand
 	*iface = onfi_sdr_timings[timing_mode];
 
 	/*
-	 * TODO: initialize timings that cannot be deduced from timing mode:
+	 * Initialize timings that cannot be deduced from timing mode:
 	 * tR, tPROG, tCCS, ...
 	 * These information are part of the ONFI parameter page.
 	 */
+	if (chip->onfi_version) {
+		struct nand_onfi_params *params = &chip->onfi_params;
+		struct nand_sdr_timings *timings = &iface->timings.sdr;
+
+		/* microseconds -> picoseconds */
+		timings->tPROG_max = 1000000UL * le16_to_cpu(params->t_prog);
+		timings->tBERS_max = 1000000UL * le16_to_cpu(params->t_bers);
+		timings->tR_max = 1000000UL * le16_to_cpu(params->t_r);
+
+		/* nanoseconds -> picoseconds */
+		timings->tCCS_min = 1000UL * le16_to_cpu(params->t_ccs);
+	}
 
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/omap2.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/omap2.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/omap2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/omap2.c	2017-02-12 16:03:20.000000000 -0500
@@ -1895,10 +1895,10 @@ static int omap_nand_probe(struct platfo
 
 	/* scan NAND device connected to chip controller */
 	nand_chip->options |= info->devsize & NAND_BUSWIDTH_16;
-	if (nand_scan_ident(mtd, 1, NULL)) {
+	err = nand_scan_ident(mtd, 1, NULL);
+	if (err) {
 		dev_err(&info->pdev->dev,
 			"scan failed, may be bus-width mismatch\n");
-		err = -ENXIO;
 		goto return_error;
 	}
 
@@ -2154,10 +2154,9 @@ static int omap_nand_probe(struct platfo
 
 scan_tail:
 	/* second phase scan */
-	if (nand_scan_tail(mtd)) {
-		err = -ENXIO;
+	err = nand_scan_tail(mtd);
+	if (err)
 		goto return_error;
-	}
 
 	if (dev->of_node)
 		mtd_device_register(mtd, NULL, 0);
@@ -2197,6 +2196,7 @@ static const struct of_device_id omap_na
 	{ .compatible = "ti,omap2-nand", },
 	{},
 };
+MODULE_DEVICE_TABLE(of, omap_nand_ids);
 
 static struct platform_driver omap_nand_driver = {
 	.probe		= omap_nand_probe,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/orion_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/orion_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/orion_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/orion_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -155,10 +155,9 @@ static int __init orion_nand_probe(struc
 		clk_put(clk);
 	}
 
-	if (nand_scan(mtd, 1)) {
-		ret = -ENXIO;
+	ret = nand_scan(mtd, 1);
+	if (ret)
 		goto no_dev;
-	}
 
 	mtd->name = "orion_nand";
 	ret = mtd_device_register(mtd, board->parts, board->nr_parts);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/oxnas_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/oxnas_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/oxnas_nand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/oxnas_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,195 @@
+/*
+ * Oxford Semiconductor OXNAS NAND driver
+
+ * Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
+ * Heavily based on plat_nand.c :
+ * Author: Vitaly Wool <vitalywool@gmail.com>
+ * Copyright (C) 2013 Ma Haijun <mahaijuns@gmail.com>
+ * Copyright (C) 2012 John Crispin <blogic@openwrt.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.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of.h>
+
+/* Nand commands */
+#define OXNAS_NAND_CMD_ALE		BIT(18)
+#define OXNAS_NAND_CMD_CLE		BIT(19)
+
+#define OXNAS_NAND_MAX_CHIPS	1
+
+struct oxnas_nand_ctrl {
+	struct nand_hw_control base;
+	void __iomem *io_base;
+	struct clk *clk;
+	struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS];
+};
+
+static uint8_t oxnas_nand_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
+
+	return readb(oxnas->io_base);
+}
+
+static void oxnas_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
+
+	ioread8_rep(oxnas->io_base, buf, len);
+}
+
+static void oxnas_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
+
+	iowrite8_rep(oxnas->io_base, buf, len);
+}
+
+/* Single CS command control */
+static void oxnas_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+				unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct oxnas_nand_ctrl *oxnas = nand_get_controller_data(chip);
+
+	if (ctrl & NAND_CLE)
+		writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_CLE);
+	else if (ctrl & NAND_ALE)
+		writeb(cmd, oxnas->io_base + OXNAS_NAND_CMD_ALE);
+}
+
+/*
+ * Probe for the NAND device.
+ */
+static int oxnas_nand_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct device_node *nand_np;
+	struct oxnas_nand_ctrl *oxnas;
+	struct nand_chip *chip;
+	struct mtd_info *mtd;
+	struct resource *res;
+	int nchips = 0;
+	int count = 0;
+	int err = 0;
+
+	/* Allocate memory for the device structure (and zero it) */
+	oxnas = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
+			     GFP_KERNEL);
+	if (!oxnas)
+		return -ENOMEM;
+
+	nand_hw_control_init(&oxnas->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	oxnas->io_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(oxnas->io_base))
+		return PTR_ERR(oxnas->io_base);
+
+	oxnas->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(oxnas->clk))
+		oxnas->clk = NULL;
+
+	/* Only a single chip node is supported */
+	count = of_get_child_count(np);
+	if (count > 1)
+		return -EINVAL;
+
+	clk_prepare_enable(oxnas->clk);
+	device_reset_optional(&pdev->dev);
+
+	for_each_child_of_node(np, nand_np) {
+		chip = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
+				    GFP_KERNEL);
+		if (!chip)
+			return -ENOMEM;
+
+		chip->controller = &oxnas->base;
+
+		nand_set_flash_node(chip, nand_np);
+		nand_set_controller_data(chip, oxnas);
+
+		mtd = nand_to_mtd(chip);
+		mtd->dev.parent = &pdev->dev;
+		mtd->priv = chip;
+
+		chip->cmd_ctrl = oxnas_nand_cmd_ctrl;
+		chip->read_buf = oxnas_nand_read_buf;
+		chip->read_byte = oxnas_nand_read_byte;
+		chip->write_buf = oxnas_nand_write_buf;
+		chip->chip_delay = 30;
+
+		/* Scan to find existence of the device */
+		err = nand_scan(mtd, 1);
+		if (err)
+			return err;
+
+		err = mtd_device_register(mtd, NULL, 0);
+		if (err) {
+			nand_release(mtd);
+			return err;
+		}
+
+		oxnas->chips[nchips] = chip;
+		++nchips;
+	}
+
+	/* Exit if no chips found */
+	if (!nchips)
+		return -ENODEV;
+
+	platform_set_drvdata(pdev, oxnas);
+
+	return 0;
+}
+
+static int oxnas_nand_remove(struct platform_device *pdev)
+{
+	struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev);
+
+	if (oxnas->chips[0])
+		nand_release(nand_to_mtd(oxnas->chips[0]));
+
+	clk_disable_unprepare(oxnas->clk);
+
+	return 0;
+}
+
+static const struct of_device_id oxnas_nand_match[] = {
+	{ .compatible = "oxsemi,ox820-nand" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, oxnas_nand_match);
+
+static struct platform_driver oxnas_nand_driver = {
+	.probe	= oxnas_nand_probe,
+	.remove	= oxnas_nand_remove,
+	.driver	= {
+		.name		= "oxnas_nand",
+		.of_match_table = oxnas_nand_match,
+	},
+};
+
+module_platform_driver(oxnas_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_DESCRIPTION("Oxnas NAND driver");
+MODULE_ALIAS("platform:oxnas_nand");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/pasemi_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/pasemi_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/pasemi_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/pasemi_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -156,10 +156,9 @@ static int pasemi_nand_probe(struct plat
 	chip->bbt_options = NAND_BBT_USE_FLASH;
 
 	/* Scan to find existence of the device */
-	if (nand_scan(pasemi_nand_mtd, 1)) {
-		err = -ENXIO;
+	err = nand_scan(pasemi_nand_mtd, 1);
+	if (err)
 		goto out_lpc;
-	}
 
 	if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) {
 		dev_err(dev, "Unable to register MTD device\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/plat_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/plat_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/plat_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/plat_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -86,10 +86,9 @@ static int plat_nand_probe(struct platfo
 	}
 
 	/* Scan to find existence of the device */
-	if (nand_scan(mtd, pdata->chip.nr_chips)) {
-		err = -ENXIO;
+	err = nand_scan(mtd, pdata->chip.nr_chips);
+	if (err)
 		goto out;
-	}
 
 	part_types = pdata->chip.part_probe_types;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/pxa3xx_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/pxa3xx_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/pxa3xx_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/pxa3xx_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -1680,8 +1680,9 @@ static int pxa3xx_nand_scan(struct mtd_i
 	chip->ecc.strength = pdata->ecc_strength;
 	chip->ecc.size = pdata->ecc_step_size;
 
-	if (nand_scan_ident(mtd, 1, NULL))
-		return -ENODEV;
+	ret = nand_scan_ident(mtd, 1, NULL);
+	if (ret)
+		return ret;
 
 	if (!pdata->keep_config) {
 		ret = pxa3xx_nand_init(host);
@@ -1774,8 +1775,11 @@ static int alloc_nand_resource(struct pl
 	int ret, irq, cs;
 
 	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata->num_cs <= 0)
+	if (pdata->num_cs <= 0) {
+		dev_err(&pdev->dev, "invalid number of chip selects\n");
 		return -ENODEV;
+	}
+
 	info = devm_kzalloc(&pdev->dev,
 			    sizeof(*info) + sizeof(*host) * pdata->num_cs,
 			    GFP_KERNEL);
@@ -1813,8 +1817,9 @@ static int alloc_nand_resource(struct pl
 	nand_hw_control_init(chip->controller);
 	info->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
-		dev_err(&pdev->dev, "failed to get nand clock\n");
-		return PTR_ERR(info->clk);
+		ret = PTR_ERR(info->clk);
+		dev_err(&pdev->dev, "failed to get nand clock: %d\n", ret);
+		return ret;
 	}
 	ret = clk_prepare_enable(info->clk);
 	if (ret < 0)
@@ -1842,6 +1847,7 @@ static int alloc_nand_resource(struct pl
 	info->mmio_base = devm_ioremap_resource(&pdev->dev, r);
 	if (IS_ERR(info->mmio_base)) {
 		ret = PTR_ERR(info->mmio_base);
+		dev_err(&pdev->dev, "failed to map register space: %d\n", ret);
 		goto fail_disable_clk;
 	}
 	info->mmio_phys = r->start;
@@ -1861,7 +1867,7 @@ static int alloc_nand_resource(struct pl
 				   pxa3xx_nand_irq_thread, IRQF_ONESHOT,
 				   pdev->name, info);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to request IRQ\n");
+		dev_err(&pdev->dev, "failed to request IRQ: %d\n", ret);
 		goto fail_free_buf;
 	}
 
@@ -1960,10 +1966,8 @@ static int pxa3xx_nand_probe(struct plat
 	}
 
 	ret = alloc_nand_resource(pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "alloc nand resource failed\n");
+	if (ret)
 		return ret;
-	}
 
 	info = platform_get_drvdata(pdev);
 	probe_success = 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/s3c2410.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/s3c2410.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/s3c2410.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/s3c2410.c	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,8 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/cpufreq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -185,6 +187,22 @@ struct s3c2410_nand_info {
 #endif
 };
 
+struct s3c24XX_nand_devtype_data {
+	enum s3c_cpu_type type;
+};
+
+static const struct s3c24XX_nand_devtype_data s3c2410_nand_devtype_data = {
+	.type = TYPE_S3C2410,
+};
+
+static const struct s3c24XX_nand_devtype_data s3c2412_nand_devtype_data = {
+	.type = TYPE_S3C2412,
+};
+
+static const struct s3c24XX_nand_devtype_data s3c2440_nand_devtype_data = {
+	.type = TYPE_S3C2440,
+};
+
 /* conversion functions */
 
 static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
@@ -497,7 +515,6 @@ static int s3c2412_nand_devready(struct
 
 /* ECC handling functions */
 
-#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				     u_char *read_ecc, u_char *calc_ecc)
 {
@@ -649,7 +666,6 @@ static int s3c2440_nand_calculate_ecc(st
 
 	return 0;
 }
-#endif
 
 /* over-ride the standard functions for a little more speed. We can
  * use read/write block to move the data buffers to/from the controller
@@ -796,6 +812,30 @@ static int s3c2410_nand_add_partition(st
 	return -ENODEV;
 }
 
+static int s3c2410_nand_setup_data_interface(struct mtd_info *mtd,
+					const struct nand_data_interface *conf,
+					bool check_only)
+{
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+	struct s3c2410_platform_nand *pdata = info->platform;
+	const struct nand_sdr_timings *timings;
+	int tacls;
+
+	timings = nand_get_sdr_timings(conf);
+	if (IS_ERR(timings))
+		return -ENOTSUPP;
+
+	tacls = timings->tCLS_min - timings->tWP_min;
+	if (tacls < 0)
+		tacls = 0;
+
+	pdata->tacls  = DIV_ROUND_UP(tacls, 1000);
+	pdata->twrph0 = DIV_ROUND_UP(timings->tWP_min, 1000);
+	pdata->twrph1 = DIV_ROUND_UP(timings->tCLH_min, 1000);
+
+	return s3c2410_nand_setrate(info);
+}
+
 /**
  * s3c2410_nand_init_chip - initialise a single instance of an chip
  * @info: The base NAND controller the chip is on.
@@ -810,9 +850,12 @@ static void s3c2410_nand_init_chip(struc
 				   struct s3c2410_nand_mtd *nmtd,
 				   struct s3c2410_nand_set *set)
 {
+	struct device_node *np = info->device->of_node;
 	struct nand_chip *chip = &nmtd->chip;
 	void __iomem *regs = info->regs;
 
+	nand_set_flash_node(chip, set->of_node);
+
 	chip->write_buf    = s3c2410_nand_write_buf;
 	chip->read_buf     = s3c2410_nand_read_buf;
 	chip->select_chip  = s3c2410_nand_select_chip;
@@ -821,6 +864,13 @@ static void s3c2410_nand_init_chip(struc
 	chip->options	   = set->options;
 	chip->controller   = &info->controller;
 
+	/*
+	 * let's keep behavior unchanged for legacy boards booting via pdata and
+	 * auto-detect timings only when booting with a device tree.
+	 */
+	if (np)
+		chip->setup_data_interface = s3c2410_nand_setup_data_interface;
+
 	switch (info->cpu_type) {
 	case TYPE_S3C2410:
 		chip->IO_ADDR_W = regs + S3C2410_NFDATA;
@@ -858,58 +908,14 @@ static void s3c2410_nand_init_chip(struc
 	nmtd->info	   = info;
 	nmtd->set	   = set;
 
-#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
-	chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-	chip->ecc.correct   = s3c2410_nand_correct_data;
-	chip->ecc.mode	    = NAND_ECC_HW;
-	chip->ecc.strength  = 1;
-
-	switch (info->cpu_type) {
-	case TYPE_S3C2410:
-		chip->ecc.hwctl	    = s3c2410_nand_enable_hwecc;
-		chip->ecc.calculate = s3c2410_nand_calculate_ecc;
-		break;
-
-	case TYPE_S3C2412:
-		chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
-		chip->ecc.calculate = s3c2412_nand_calculate_ecc;
-		break;
-
-	case TYPE_S3C2440:
-		chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
-		chip->ecc.calculate = s3c2440_nand_calculate_ecc;
-		break;
-	}
-#else
-	chip->ecc.mode	    = NAND_ECC_SOFT;
-	chip->ecc.algo	= NAND_ECC_HAMMING;
-#endif
-
-	if (set->disable_ecc)
-		chip->ecc.mode	= NAND_ECC_NONE;
-
-	switch (chip->ecc.mode) {
-	case NAND_ECC_NONE:
-		dev_info(info->device, "NAND ECC disabled\n");
-		break;
-	case NAND_ECC_SOFT:
-		dev_info(info->device, "NAND soft ECC\n");
-		break;
-	case NAND_ECC_HW:
-		dev_info(info->device, "NAND hardware ECC\n");
-		break;
-	default:
-		dev_info(info->device, "NAND ECC UNKNOWN\n");
-		break;
-	}
+	chip->ecc.mode = info->platform->ecc_mode;
 
-	/* 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) {
+	/*
+	 * If you use u-boot BBT creation code, specifying this flag will
+	 * let the kernel fish out the BBT from the NAND.
+	 */
+	if (set->flash_bbt)
 		chip->bbt_options |= NAND_BBT_USE_FLASH;
-		chip->options |= NAND_SKIP_BBTSCAN;
-	}
 }
 
 /**
@@ -923,28 +929,146 @@ static void s3c2410_nand_init_chip(struc
  *
  * The internal state is currently limited to the ECC state information.
 */
-static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
-				     struct s3c2410_nand_mtd *nmtd)
+static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
+				    struct s3c2410_nand_mtd *nmtd)
 {
 	struct nand_chip *chip = &nmtd->chip;
 
-	dev_dbg(info->device, "chip %p => page shift %d\n",
-		chip, chip->page_shift);
+	switch (chip->ecc.mode) {
 
-	if (chip->ecc.mode != NAND_ECC_HW)
-		return;
+	case NAND_ECC_NONE:
+		dev_info(info->device, "ECC disabled\n");
+		break;
+
+	case NAND_ECC_SOFT:
+		/*
+		 * This driver expects Hamming based ECC when ecc_mode is set
+		 * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
+		 * avoid adding an extra ecc_algo field to
+		 * s3c2410_platform_nand.
+		 */
+		chip->ecc.algo = NAND_ECC_HAMMING;
+		dev_info(info->device, "soft ECC\n");
+		break;
+
+	case NAND_ECC_HW:
+		chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+		chip->ecc.correct   = s3c2410_nand_correct_data;
+		chip->ecc.strength  = 1;
+
+		switch (info->cpu_type) {
+		case TYPE_S3C2410:
+			chip->ecc.hwctl	    = s3c2410_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+			break;
+
+		case TYPE_S3C2412:
+			chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2412_nand_calculate_ecc;
+			break;
+
+		case TYPE_S3C2440:
+			chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2440_nand_calculate_ecc;
+			break;
+		}
+
+		dev_dbg(info->device, "chip %p => page shift %d\n",
+			chip, chip->page_shift);
 
 		/* change the behaviour depending on whether we are using
 		 * the large or small page nand device */
+		if (chip->page_shift > 10) {
+			chip->ecc.size	    = 256;
+			chip->ecc.bytes	    = 3;
+		} else {
+			chip->ecc.size	    = 512;
+			chip->ecc.bytes	    = 3;
+			mtd_set_ooblayout(nand_to_mtd(chip),
+					  &s3c2410_ooblayout_ops);
+		}
 
-	if (chip->page_shift > 10) {
-		chip->ecc.size	    = 256;
-		chip->ecc.bytes	    = 3;
-	} else {
-		chip->ecc.size	    = 512;
-		chip->ecc.bytes	    = 3;
-		mtd_set_ooblayout(nand_to_mtd(chip), &s3c2410_ooblayout_ops);
+		dev_info(info->device, "hardware ECC\n");
+		break;
+
+	default:
+		dev_err(info->device, "invalid ECC mode!\n");
+		return -EINVAL;
 	}
+
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->options |= NAND_SKIP_BBTSCAN;
+
+	return 0;
+}
+
+static const struct of_device_id s3c24xx_nand_dt_ids[] = {
+	{
+		.compatible = "samsung,s3c2410-nand",
+		.data = &s3c2410_nand_devtype_data,
+	}, {
+		/* also compatible with s3c6400 */
+		.compatible = "samsung,s3c2412-nand",
+		.data = &s3c2412_nand_devtype_data,
+	}, {
+		.compatible = "samsung,s3c2440-nand",
+		.data = &s3c2440_nand_devtype_data,
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, s3c24xx_nand_dt_ids);
+
+static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
+{
+	const struct s3c24XX_nand_devtype_data *devtype_data;
+	struct s3c2410_platform_nand *pdata;
+	struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node, *child;
+	struct s3c2410_nand_set *sets;
+
+	devtype_data = of_device_get_match_data(&pdev->dev);
+	if (!devtype_data)
+		return -ENODEV;
+
+	info->cpu_type = devtype_data->type;
+
+	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdev->dev.platform_data = pdata;
+
+	pdata->nr_sets = of_get_child_count(np);
+	if (!pdata->nr_sets)
+		return 0;
+
+	sets = devm_kzalloc(&pdev->dev, sizeof(*sets) * pdata->nr_sets,
+			    GFP_KERNEL);
+	if (!sets)
+		return -ENOMEM;
+
+	pdata->sets = sets;
+
+	for_each_available_child_of_node(np, child) {
+		sets->name = (char *)child->name;
+		sets->of_node = child;
+		sets->nr_chips = 1;
+
+		of_node_get(child);
+
+		sets++;
+	}
+
+	return 0;
+}
+
+static int s3c24xx_nand_probe_pdata(struct platform_device *pdev)
+{
+	struct s3c2410_nand_info *info = platform_get_drvdata(pdev);
+
+	info->cpu_type = platform_get_device_id(pdev)->driver_data;
+
+	return 0;
 }
 
 /* s3c24xx_nand_probe
@@ -956,8 +1080,7 @@ static void s3c2410_nand_update_chip(str
 */
 static int s3c24xx_nand_probe(struct platform_device *pdev)
 {
-	struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
-	enum s3c_cpu_type cpu_type;
+	struct s3c2410_platform_nand *plat;
 	struct s3c2410_nand_info *info;
 	struct s3c2410_nand_mtd *nmtd;
 	struct s3c2410_nand_set *sets;
@@ -967,8 +1090,6 @@ static int s3c24xx_nand_probe(struct pla
 	int nr_sets;
 	int setno;
 
-	cpu_type = platform_get_device_id(pdev)->driver_data;
-
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 	if (info == NULL) {
 		err = -ENOMEM;
@@ -990,6 +1111,16 @@ static int s3c24xx_nand_probe(struct pla
 
 	s3c2410_nand_clk_set_state(info, CLOCK_ENABLE);
 
+	if (pdev->dev.of_node)
+		err = s3c24xx_nand_probe_dt(pdev);
+	else
+		err = s3c24xx_nand_probe_pdata(pdev);
+
+	if (err)
+		goto exit_error;
+
+	plat = to_nand_plat(pdev);
+
 	/* allocate and map the resource */
 
 	/* currently we assume we have the one resource */
@@ -998,7 +1129,6 @@ static int s3c24xx_nand_probe(struct pla
 
 	info->device	= &pdev->dev;
 	info->platform	= plat;
-	info->cpu_type	= cpu_type;
 
 	info->regs = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(info->regs)) {
@@ -1008,12 +1138,6 @@ static int s3c24xx_nand_probe(struct pla
 
 	dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);
 
-	/* initialise the hardware */
-
-	err = s3c2410_nand_inithw(info);
-	if (err != 0)
-		goto exit_error;
-
 	sets = (plat != NULL) ? plat->sets : NULL;
 	nr_sets = (plat != NULL) ? plat->nr_sets : 1;
 
@@ -1046,7 +1170,9 @@ static int s3c24xx_nand_probe(struct pla
 						 NULL);
 
 		if (nmtd->scan_res == 0) {
-			s3c2410_nand_update_chip(info, nmtd);
+			err = s3c2410_nand_update_chip(info, nmtd);
+			if (err < 0)
+				goto exit_error;
 			nand_scan_tail(mtd);
 			s3c2410_nand_add_partition(info, nmtd, sets);
 		}
@@ -1055,6 +1181,11 @@ static int s3c24xx_nand_probe(struct pla
 			sets++;
 	}
 
+	/* initialise the hardware */
+	err = s3c2410_nand_inithw(info);
+	if (err != 0)
+		goto exit_error;
+
 	err = s3c2410_nand_cpufreq_register(info);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to init cpufreq support\n");
@@ -1155,6 +1286,7 @@ static struct platform_driver s3c24xx_na
 	.id_table	= s3c24xx_driver_ids,
 	.driver		= {
 		.name	= "s3c24xx-nand",
+		.of_match_table = s3c24xx_nand_dt_ids,
 	},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/socrates_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/socrates_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/socrates_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/socrates_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -187,17 +187,9 @@ static int socrates_nand_probe(struct pl
 
 	dev_set_drvdata(&ofdev->dev, host);
 
-	/* first scan to find the device and get the page size */
-	if (nand_scan_ident(mtd, 1, NULL)) {
-		res = -ENXIO;
-		goto out;
-	}
-
-	/* second phase scan */
-	if (nand_scan_tail(mtd)) {
-		res = -ENXIO;
+	res = nand_scan(mtd, 1);
+	if (res)
 		goto out;
-	}
 
 	res = mtd_device_register(mtd, NULL, 0);
 	if (!res)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/sunxi_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/sunxi_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/sunxi_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/sunxi_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -145,6 +145,7 @@
 #define NFC_ECC_PIPELINE	BIT(3)
 #define NFC_ECC_EXCEPTION	BIT(4)
 #define NFC_ECC_BLOCK_SIZE_MSK	BIT(5)
+#define NFC_ECC_BLOCK_512	BIT(5)
 #define NFC_RANDOM_EN		BIT(9)
 #define NFC_RANDOM_DIRECTION	BIT(10)
 #define NFC_ECC_MODE_MSK	GENMASK(15, 12)
@@ -817,6 +818,9 @@ static void sunxi_nfc_hw_ecc_enable(stru
 	ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION |
 		   NFC_ECC_PIPELINE;
 
+	if (nand->ecc.size == 512)
+		ecc_ctl |= NFC_ECC_BLOCK_512;
+
 	writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/tango_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/tango_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/tango_nand.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/tango_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,678 @@
+/*
+ * Copyright (C) 2016 Sigma Designs
+ *
+ * This program is free software; you can redistribute it 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/of.h>
+#include <linux/clk.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+/* Offsets relative to chip->base */
+#define PBUS_CMD	0
+#define PBUS_ADDR	4
+#define PBUS_DATA	8
+
+/* Offsets relative to reg_base */
+#define NFC_STATUS	0x00
+#define NFC_FLASH_CMD	0x04
+#define NFC_DEVICE_CFG	0x08
+#define NFC_TIMING1	0x0c
+#define NFC_TIMING2	0x10
+#define NFC_XFER_CFG	0x14
+#define NFC_PKT_0_CFG	0x18
+#define NFC_PKT_N_CFG	0x1c
+#define NFC_BB_CFG	0x20
+#define NFC_ADDR_PAGE	0x24
+#define NFC_ADDR_OFFSET	0x28
+#define NFC_XFER_STATUS	0x2c
+
+/* NFC_STATUS values */
+#define CMD_READY	BIT(31)
+
+/* NFC_FLASH_CMD values */
+#define NFC_READ	1
+#define NFC_WRITE	2
+
+/* NFC_XFER_STATUS values */
+#define PAGE_IS_EMPTY	BIT(16)
+
+/* Offsets relative to mem_base */
+#define METADATA	0x000
+#define ERROR_REPORT	0x1c0
+
+/*
+ * Error reports are split in two bytes:
+ * byte 0 for the first packet in the page (PKT_0)
+ * byte 1 for other packets in the page (PKT_N, for N > 0)
+ * ERR_COUNT_PKT_N is the max error count over all but the first packet.
+ */
+#define DECODE_OK_PKT_0(v)	((v) & BIT(7))
+#define DECODE_OK_PKT_N(v)	((v) & BIT(15))
+#define ERR_COUNT_PKT_0(v)	(((v) >> 0) & 0x3f)
+#define ERR_COUNT_PKT_N(v)	(((v) >> 8) & 0x3f)
+
+/* Offsets relative to pbus_base */
+#define PBUS_CS_CTRL	0x83c
+#define PBUS_PAD_MODE	0x8f0
+
+/* PBUS_CS_CTRL values */
+#define PBUS_IORDY	BIT(31)
+
+/*
+ * PBUS_PAD_MODE values
+ * In raw mode, the driver communicates directly with the NAND chips.
+ * In NFC mode, the NAND Flash controller manages the communication.
+ * We use NFC mode for read and write; raw mode for everything else.
+ */
+#define MODE_RAW	0
+#define MODE_NFC	BIT(31)
+
+#define METADATA_SIZE	4
+#define BBM_SIZE	6
+#define FIELD_ORDER	15
+
+#define MAX_CS		4
+
+struct tango_nfc {
+	struct nand_hw_control hw;
+	void __iomem *reg_base;
+	void __iomem *mem_base;
+	void __iomem *pbus_base;
+	struct tango_chip *chips[MAX_CS];
+	struct dma_chan *chan;
+	int freq_kHz;
+};
+
+#define to_tango_nfc(ptr) container_of(ptr, struct tango_nfc, hw)
+
+struct tango_chip {
+	struct nand_chip nand_chip;
+	void __iomem *base;
+	u32 timing1;
+	u32 timing2;
+	u32 xfer_cfg;
+	u32 pkt_0_cfg;
+	u32 pkt_n_cfg;
+	u32 bb_cfg;
+};
+
+#define to_tango_chip(ptr) container_of(ptr, struct tango_chip, nand_chip)
+
+#define XFER_CFG(cs, page_count, steps, metadata_size)	\
+	((cs) << 24 | (page_count) << 16 | (steps) << 8 | (metadata_size))
+
+#define PKT_CFG(size, strength) ((size) << 16 | (strength))
+
+#define BB_CFG(bb_offset, bb_size) ((bb_offset) << 16 | (bb_size))
+
+#define TIMING(t0, t1, t2, t3) ((t0) << 24 | (t1) << 16 | (t2) << 8 | (t3))
+
+static void tango_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
+{
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+
+	if (ctrl & NAND_CLE)
+		writeb_relaxed(dat, tchip->base + PBUS_CMD);
+
+	if (ctrl & NAND_ALE)
+		writeb_relaxed(dat, tchip->base + PBUS_ADDR);
+}
+
+static int tango_dev_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
+
+	return readl_relaxed(nfc->pbus_base + PBUS_CS_CTRL) & PBUS_IORDY;
+}
+
+static u8 tango_read_byte(struct mtd_info *mtd)
+{
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+
+	return readb_relaxed(tchip->base + PBUS_DATA);
+}
+
+static void tango_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+
+	ioread8_rep(tchip->base + PBUS_DATA, buf, len);
+}
+
+static void tango_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct tango_chip *tchip = to_tango_chip(mtd_to_nand(mtd));
+
+	iowrite8_rep(tchip->base + PBUS_DATA, buf, len);
+}
+
+static void tango_select_chip(struct mtd_info *mtd, int idx)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
+	struct tango_chip *tchip = to_tango_chip(chip);
+
+	if (idx < 0)
+		return; /* No "chip unselect" function */
+
+	writel_relaxed(tchip->timing1, nfc->reg_base + NFC_TIMING1);
+	writel_relaxed(tchip->timing2, nfc->reg_base + NFC_TIMING2);
+	writel_relaxed(tchip->xfer_cfg, nfc->reg_base + NFC_XFER_CFG);
+	writel_relaxed(tchip->pkt_0_cfg, nfc->reg_base + NFC_PKT_0_CFG);
+	writel_relaxed(tchip->pkt_n_cfg, nfc->reg_base + NFC_PKT_N_CFG);
+	writel_relaxed(tchip->bb_cfg, nfc->reg_base + NFC_BB_CFG);
+}
+
+/*
+ * The controller does not check for bitflips in erased pages,
+ * therefore software must check instead.
+ */
+static int check_erased_page(struct nand_chip *chip, u8 *buf)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u8 *meta = chip->oob_poi + BBM_SIZE;
+	u8 *ecc = chip->oob_poi + BBM_SIZE + METADATA_SIZE;
+	const int ecc_size = chip->ecc.bytes;
+	const int pkt_size = chip->ecc.size;
+	int i, res, meta_len, bitflips = 0;
+
+	for (i = 0; i < chip->ecc.steps; ++i) {
+		meta_len = i ? 0 : METADATA_SIZE;
+		res = nand_check_erased_ecc_chunk(buf, pkt_size, ecc, ecc_size,
+						  meta, meta_len,
+						  chip->ecc.strength);
+		if (res < 0)
+			mtd->ecc_stats.failed++;
+
+		bitflips = max(res, bitflips);
+		buf += pkt_size;
+		ecc += ecc_size;
+	}
+
+	return bitflips;
+}
+
+static int decode_error_report(struct tango_nfc *nfc)
+{
+	u32 status, res;
+
+	status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS);
+	if (status & PAGE_IS_EMPTY)
+		return 0;
+
+	res = readl_relaxed(nfc->mem_base + ERROR_REPORT);
+
+	if (DECODE_OK_PKT_0(res) && DECODE_OK_PKT_N(res))
+		return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
+
+	return -EBADMSG;
+}
+
+static void tango_dma_callback(void *arg)
+{
+	complete(arg);
+}
+
+static int do_dma(struct tango_nfc *nfc, int dir, int cmd, const void *buf,
+		  int len, int page)
+{
+	void __iomem *addr = nfc->reg_base + NFC_STATUS;
+	struct dma_chan *chan = nfc->chan;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist sg;
+	struct completion tx_done;
+	int err = -EIO;
+	u32 res, val;
+
+	sg_init_one(&sg, buf, len);
+	if (dma_map_sg(chan->device->dev, &sg, 1, dir) != 1)
+		return -EIO;
+
+	desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, DMA_PREP_INTERRUPT);
+	if (!desc)
+		goto dma_unmap;
+
+	desc->callback = tango_dma_callback;
+	desc->callback_param = &tx_done;
+	init_completion(&tx_done);
+
+	writel_relaxed(MODE_NFC, nfc->pbus_base + PBUS_PAD_MODE);
+
+	writel_relaxed(page, nfc->reg_base + NFC_ADDR_PAGE);
+	writel_relaxed(0, nfc->reg_base + NFC_ADDR_OFFSET);
+	writel_relaxed(cmd, nfc->reg_base + NFC_FLASH_CMD);
+
+	dmaengine_submit(desc);
+	dma_async_issue_pending(chan);
+
+	res = wait_for_completion_timeout(&tx_done, HZ);
+	if (res > 0)
+		err = readl_poll_timeout(addr, val, val & CMD_READY, 0, 1000);
+
+	writel_relaxed(MODE_RAW, nfc->pbus_base + PBUS_PAD_MODE);
+
+dma_unmap:
+	dma_unmap_sg(chan->device->dev, &sg, 1, dir);
+
+	return err;
+}
+
+static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
+			   u8 *buf, int oob_required, int page)
+{
+	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
+	int err, res, len = mtd->writesize;
+
+	if (oob_required)
+		chip->ecc.read_oob(mtd, chip, page);
+
+	err = do_dma(nfc, DMA_FROM_DEVICE, NFC_READ, buf, len, page);
+	if (err)
+		return err;
+
+	res = decode_error_report(nfc);
+	if (res < 0) {
+		chip->ecc.read_oob_raw(mtd, chip, page);
+		res = check_erased_page(chip, buf);
+	}
+
+	return res;
+}
+
+static int tango_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+			    const u8 *buf, int oob_required, int page)
+{
+	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
+	int err, len = mtd->writesize;
+
+	/* Calling tango_write_oob() would send PAGEPROG twice */
+	if (oob_required)
+		return -ENOTSUPP;
+
+	writel_relaxed(0xffffffff, nfc->mem_base + METADATA);
+	err = do_dma(nfc, DMA_TO_DEVICE, NFC_WRITE, buf, len, page);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static void aux_read(struct nand_chip *chip, u8 **buf, int len, int *pos)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	*pos += len;
+
+	if (!*buf) {
+		/* skip over "len" bytes */
+		chip->cmdfunc(mtd, NAND_CMD_RNDOUT, *pos, -1);
+	} else {
+		tango_read_buf(mtd, *buf, len);
+		*buf += len;
+	}
+}
+
+static void aux_write(struct nand_chip *chip, const u8 **buf, int len, int *pos)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	*pos += len;
+
+	if (!*buf) {
+		/* skip over "len" bytes */
+		chip->cmdfunc(mtd, NAND_CMD_SEQIN, *pos, -1);
+	} else {
+		tango_write_buf(mtd, *buf, len);
+		*buf += len;
+	}
+}
+
+/*
+ * Physical page layout (not drawn to scale)
+ *
+ * NB: Bad Block Marker area splits PKT_N in two (N1, N2).
+ *
+ * +---+-----------------+-------+-----+-----------+-----+----+-------+
+ * | M |      PKT_0      | ECC_0 | ... |     N1    | BBM | N2 | ECC_N |
+ * +---+-----------------+-------+-----+-----------+-----+----+-------+
+ *
+ * Logical page layout:
+ *
+ *       +-----+---+-------+-----+-------+
+ * oob = | BBM | M | ECC_0 | ... | ECC_N |
+ *       +-----+---+-------+-----+-------+
+ *
+ *       +-----------------+-----+-----------------+
+ * buf = |      PKT_0      | ... |      PKT_N      |
+ *       +-----------------+-----+-----------------+
+ */
+static void raw_read(struct nand_chip *chip, u8 *buf, u8 *oob)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u8 *oob_orig = oob;
+	const int page_size = mtd->writesize;
+	const int ecc_size = chip->ecc.bytes;
+	const int pkt_size = chip->ecc.size;
+	int pos = 0; /* position within physical page */
+	int rem = page_size; /* bytes remaining until BBM area */
+
+	if (oob)
+		oob += BBM_SIZE;
+
+	aux_read(chip, &oob, METADATA_SIZE, &pos);
+
+	while (rem > pkt_size) {
+		aux_read(chip, &buf, pkt_size, &pos);
+		aux_read(chip, &oob, ecc_size, &pos);
+		rem = page_size - pos;
+	}
+
+	aux_read(chip, &buf, rem, &pos);
+	aux_read(chip, &oob_orig, BBM_SIZE, &pos);
+	aux_read(chip, &buf, pkt_size - rem, &pos);
+	aux_read(chip, &oob, ecc_size, &pos);
+}
+
+static void raw_write(struct nand_chip *chip, const u8 *buf, const u8 *oob)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	const u8 *oob_orig = oob;
+	const int page_size = mtd->writesize;
+	const int ecc_size = chip->ecc.bytes;
+	const int pkt_size = chip->ecc.size;
+	int pos = 0; /* position within physical page */
+	int rem = page_size; /* bytes remaining until BBM area */
+
+	if (oob)
+		oob += BBM_SIZE;
+
+	aux_write(chip, &oob, METADATA_SIZE, &pos);
+
+	while (rem > pkt_size) {
+		aux_write(chip, &buf, pkt_size, &pos);
+		aux_write(chip, &oob, ecc_size, &pos);
+		rem = page_size - pos;
+	}
+
+	aux_write(chip, &buf, rem, &pos);
+	aux_write(chip, &oob_orig, BBM_SIZE, &pos);
+	aux_write(chip, &buf, pkt_size - rem, &pos);
+	aux_write(chip, &oob, ecc_size, &pos);
+}
+
+static int tango_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+			       u8 *buf, int oob_required, int page)
+{
+	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+	raw_read(chip, buf, chip->oob_poi);
+	return 0;
+}
+
+static int tango_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+				const u8 *buf, int oob_required, int page)
+{
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
+	raw_write(chip, buf, chip->oob_poi);
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+	return 0;
+}
+
+static int tango_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
+			  int page)
+{
+	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+	raw_read(chip, NULL, chip->oob_poi);
+	return 0;
+}
+
+static int tango_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+			   int page)
+{
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0, page);
+	raw_write(chip, NULL, chip->oob_poi);
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+	chip->waitfunc(mtd, chip);
+	return 0;
+}
+
+static int oob_ecc(struct mtd_info *mtd, int idx, struct mtd_oob_region *res)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+	if (idx >= ecc->steps)
+		return -ERANGE;
+
+	res->offset = BBM_SIZE + METADATA_SIZE + ecc->bytes * idx;
+	res->length = ecc->bytes;
+
+	return 0;
+}
+
+static int oob_free(struct mtd_info *mtd, int idx, struct mtd_oob_region *res)
+{
+	return -ERANGE; /* no free space in spare area */
+}
+
+static const struct mtd_ooblayout_ops tango_nand_ooblayout_ops = {
+	.ecc	= oob_ecc,
+	.free	= oob_free,
+};
+
+static u32 to_ticks(int kHz, int ps)
+{
+	return DIV_ROUND_UP_ULL((u64)kHz * ps, NSEC_PER_SEC);
+}
+
+static int tango_set_timings(struct mtd_info *mtd,
+			     const struct nand_data_interface *conf,
+			     bool check_only)
+{
+	const struct nand_sdr_timings *sdr = nand_get_sdr_timings(conf);
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct tango_nfc *nfc = to_tango_nfc(chip->controller);
+	struct tango_chip *tchip = to_tango_chip(chip);
+	u32 Trdy, Textw, Twc, Twpw, Tacc, Thold, Trpw, Textr;
+	int kHz = nfc->freq_kHz;
+
+	if (IS_ERR(sdr))
+		return PTR_ERR(sdr);
+
+	if (check_only)
+		return 0;
+
+	Trdy = to_ticks(kHz, sdr->tCEA_max - sdr->tREA_max);
+	Textw = to_ticks(kHz, sdr->tWB_max);
+	Twc = to_ticks(kHz, sdr->tWC_min);
+	Twpw = to_ticks(kHz, sdr->tWC_min - sdr->tWP_min);
+
+	Tacc = to_ticks(kHz, sdr->tREA_max);
+	Thold = to_ticks(kHz, sdr->tREH_min);
+	Trpw = to_ticks(kHz, sdr->tRC_min - sdr->tREH_min);
+	Textr = to_ticks(kHz, sdr->tRHZ_max);
+
+	tchip->timing1 = TIMING(Trdy, Textw, Twc, Twpw);
+	tchip->timing2 = TIMING(Tacc, Thold, Trpw, Textr);
+
+	return 0;
+}
+
+static int chip_init(struct device *dev, struct device_node *np)
+{
+	u32 cs;
+	int err, res;
+	struct mtd_info *mtd;
+	struct nand_chip *chip;
+	struct tango_chip *tchip;
+	struct nand_ecc_ctrl *ecc;
+	struct tango_nfc *nfc = dev_get_drvdata(dev);
+
+	tchip = devm_kzalloc(dev, sizeof(*tchip), GFP_KERNEL);
+	if (!tchip)
+		return -ENOMEM;
+
+	res = of_property_count_u32_elems(np, "reg");
+	if (res < 0)
+		return res;
+
+	if (res != 1)
+		return -ENOTSUPP; /* Multi-CS chips are not supported */
+
+	err = of_property_read_u32_index(np, "reg", 0, &cs);
+	if (err)
+		return err;
+
+	if (cs >= MAX_CS)
+		return -EINVAL;
+
+	chip = &tchip->nand_chip;
+	ecc = &chip->ecc;
+	mtd = nand_to_mtd(chip);
+
+	chip->read_byte = tango_read_byte;
+	chip->write_buf = tango_write_buf;
+	chip->read_buf = tango_read_buf;
+	chip->select_chip = tango_select_chip;
+	chip->cmd_ctrl = tango_cmd_ctrl;
+	chip->dev_ready = tango_dev_ready;
+	chip->setup_data_interface = tango_set_timings;
+	chip->options = NAND_USE_BOUNCE_BUFFER |
+			NAND_NO_SUBPAGE_WRITE |
+			NAND_WAIT_TCCS;
+	chip->controller = &nfc->hw;
+	tchip->base = nfc->pbus_base + (cs * 256);
+
+	nand_set_flash_node(chip, np);
+	mtd_set_ooblayout(mtd, &tango_nand_ooblayout_ops);
+	mtd->dev.parent = dev;
+
+	err = nand_scan_ident(mtd, 1, NULL);
+	if (err)
+		return err;
+
+	ecc->mode = NAND_ECC_HW;
+	ecc->algo = NAND_ECC_BCH;
+	ecc->bytes = DIV_ROUND_UP(ecc->strength * FIELD_ORDER, BITS_PER_BYTE);
+
+	ecc->read_page_raw = tango_read_page_raw;
+	ecc->write_page_raw = tango_write_page_raw;
+	ecc->read_page = tango_read_page;
+	ecc->write_page = tango_write_page;
+	ecc->read_oob = tango_read_oob;
+	ecc->write_oob = tango_write_oob;
+	ecc->options = NAND_ECC_CUSTOM_PAGE_ACCESS;
+
+	err = nand_scan_tail(mtd);
+	if (err)
+		return err;
+
+	tchip->xfer_cfg = XFER_CFG(cs, 1, ecc->steps, METADATA_SIZE);
+	tchip->pkt_0_cfg = PKT_CFG(ecc->size + METADATA_SIZE, ecc->strength);
+	tchip->pkt_n_cfg = PKT_CFG(ecc->size, ecc->strength);
+	tchip->bb_cfg = BB_CFG(mtd->writesize, BBM_SIZE);
+
+	err = mtd_device_register(mtd, NULL, 0);
+	if (err)
+		return err;
+
+	nfc->chips[cs] = tchip;
+
+	return 0;
+}
+
+static int tango_nand_remove(struct platform_device *pdev)
+{
+	int cs;
+	struct tango_nfc *nfc = platform_get_drvdata(pdev);
+
+	dma_release_channel(nfc->chan);
+
+	for (cs = 0; cs < MAX_CS; ++cs) {
+		if (nfc->chips[cs])
+			nand_release(nand_to_mtd(&nfc->chips[cs]->nand_chip));
+	}
+
+	return 0;
+}
+
+static int tango_nand_probe(struct platform_device *pdev)
+{
+	int err;
+	struct clk *clk;
+	struct resource *res;
+	struct tango_nfc *nfc;
+	struct device_node *np;
+
+	nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL);
+	if (!nfc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	nfc->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(nfc->reg_base))
+		return PTR_ERR(nfc->reg_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	nfc->mem_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(nfc->mem_base))
+		return PTR_ERR(nfc->mem_base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	nfc->pbus_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(nfc->pbus_base))
+		return PTR_ERR(nfc->pbus_base);
+
+	writel_relaxed(MODE_RAW, nfc->pbus_base + PBUS_PAD_MODE);
+
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	nfc->chan = dma_request_chan(&pdev->dev, "rxtx");
+	if (IS_ERR(nfc->chan))
+		return PTR_ERR(nfc->chan);
+
+	platform_set_drvdata(pdev, nfc);
+	nand_hw_control_init(&nfc->hw);
+	nfc->freq_kHz = clk_get_rate(clk) / 1000;
+
+	for_each_child_of_node(pdev->dev.of_node, np) {
+		err = chip_init(&pdev->dev, np);
+		if (err) {
+			tango_nand_remove(pdev);
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static const struct of_device_id tango_nand_ids[] = {
+	{ .compatible = "sigma,smp8758-nand" },
+	{ /* sentinel */ }
+};
+
+static struct platform_driver tango_nand_driver = {
+	.probe	= tango_nand_probe,
+	.remove	= tango_nand_remove,
+	.driver	= {
+		.name		= "tango-nand",
+		.of_match_table	= tango_nand_ids,
+	},
+};
+
+module_platform_driver(tango_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sigma Designs");
+MODULE_DESCRIPTION("Tango4 NAND Flash controller driver");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/tmio_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/tmio_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/tmio_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/tmio_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -435,10 +435,10 @@ static int tmio_probe(struct platform_de
 	nand_chip->waitfunc = tmio_nand_wait;
 
 	/* Scan to find existence of the device */
-	if (nand_scan(mtd, 1)) {
-		retval = -ENODEV;
+	retval = nand_scan(mtd, 1);
+	if (retval)
 		goto err_irq;
-	}
+
 	/* Register the partitions */
 	retval = mtd_device_parse_register(mtd, NULL, NULL,
 					   data ? data->partition : NULL,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/vf610_nfc.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/vf610_nfc.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/vf610_nfc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/vf610_nfc.c	2017-02-12 16:03:20.000000000 -0500
@@ -717,10 +717,9 @@ static int vf610_nfc_probe(struct platfo
 	vf610_nfc_preinit_controller(nfc);
 
 	/* first scan to find the device and get the page size */
-	if (nand_scan_ident(mtd, 1, NULL)) {
-		err = -ENXIO;
+	err = nand_scan_ident(mtd, 1, NULL);
+	if (err)
 		goto error;
-	}
 
 	vf610_nfc_init_controller(nfc);
 
@@ -775,10 +774,9 @@ static int vf610_nfc_probe(struct platfo
 	}
 
 	/* second phase scan */
-	if (nand_scan_tail(mtd)) {
-		err = -ENXIO;
+	err = nand_scan_tail(mtd);
+	if (err)
 		goto error;
-	}
 
 	platform_set_drvdata(pdev, mtd);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nand/xway_nand.c linux-libre-4.10-rc8-gnu/drivers/mtd/nand/xway_nand.c
--- linux-libre-4.9-gnu/drivers/mtd/nand/xway_nand.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nand/xway_nand.c	2017-02-12 16:03:20.000000000 -0500
@@ -232,7 +232,6 @@ static const struct of_device_id xway_na
 	{ .compatible = "lantiq,nand-xway" },
 	{},
 };
-MODULE_DEVICE_TABLE(of, xway_nand_match);
 
 static struct platform_driver xway_nand_driver = {
 	.probe	= xway_nand_probe,
@@ -243,6 +242,4 @@ static struct platform_driver xway_nand_
 	},
 };
 
-module_platform_driver(xway_nand_driver);
-
-MODULE_LICENSE("GPL");
+builtin_platform_driver(xway_nand_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/nftlcore.c linux-libre-4.10-rc8-gnu/drivers/mtd/nftlcore.c
--- linux-libre-4.9-gnu/drivers/mtd/nftlcore.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/nftlcore.c	2017-02-12 16:03:20.000000000 -0500
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <asm/errno.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/init.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/spi-nor/cadence-quadspi.c linux-libre-4.10-rc8-gnu/drivers/mtd/spi-nor/cadence-quadspi.c
--- linux-libre-4.9-gnu/drivers/mtd/spi-nor/cadence-quadspi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/spi-nor/cadence-quadspi.c	2017-02-12 16:03:20.000000000 -0500
@@ -1077,12 +1077,14 @@ static int cqspi_setup_flash(struct cqsp
 
 	/* Get flash device data */
 	for_each_available_child_of_node(dev->of_node, np) {
-		if (of_property_read_u32(np, "reg", &cs)) {
+		ret = of_property_read_u32(np, "reg", &cs);
+		if (ret) {
 			dev_err(dev, "Couldn't determine chip select.\n");
 			goto err;
 		}
 
-		if (cs > CQSPI_MAX_CHIPSELECT) {
+		if (cs >= CQSPI_MAX_CHIPSELECT) {
+			ret = -EINVAL;
 			dev_err(dev, "Chip select %d out of range.\n", cs);
 			goto err;
 		}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/spi-nor/fsl-quadspi.c linux-libre-4.10-rc8-gnu/drivers/mtd/spi-nor/fsl-quadspi.c
--- linux-libre-4.9-gnu/drivers/mtd/spi-nor/fsl-quadspi.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/spi-nor/fsl-quadspi.c	2017-02-12 16:03:20.000000000 -0500
@@ -224,7 +224,7 @@ struct fsl_qspi_devtype_data {
 	int driver_data;
 };
 
-static struct fsl_qspi_devtype_data vybrid_data = {
+static const struct fsl_qspi_devtype_data vybrid_data = {
 	.devtype = FSL_QUADSPI_VYBRID,
 	.rxfifo = 128,
 	.txfifo = 64,
@@ -232,7 +232,7 @@ static struct fsl_qspi_devtype_data vybr
 	.driver_data = QUADSPI_QUIRK_SWAP_ENDIAN,
 };
 
-static struct fsl_qspi_devtype_data imx6sx_data = {
+static const struct fsl_qspi_devtype_data imx6sx_data = {
 	.devtype = FSL_QUADSPI_IMX6SX,
 	.rxfifo = 128,
 	.txfifo = 512,
@@ -241,7 +241,7 @@ static struct fsl_qspi_devtype_data imx6
 		       | QUADSPI_QUIRK_TKT245618,
 };
 
-static struct fsl_qspi_devtype_data imx7d_data = {
+static const struct fsl_qspi_devtype_data imx7d_data = {
 	.devtype = FSL_QUADSPI_IMX7D,
 	.rxfifo = 512,
 	.txfifo = 512,
@@ -250,7 +250,7 @@ static struct fsl_qspi_devtype_data imx7
 		       | QUADSPI_QUIRK_4X_INT_CLK,
 };
 
-static struct fsl_qspi_devtype_data imx6ul_data = {
+static const struct fsl_qspi_devtype_data imx6ul_data = {
 	.devtype = FSL_QUADSPI_IMX6UL,
 	.rxfifo = 128,
 	.txfifo = 512,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/mtd/spi-nor/spi-nor.c linux-libre-4.10-rc8-gnu/drivers/mtd/spi-nor/spi-nor.c
--- linux-libre-4.9-gnu/drivers/mtd/spi-nor/spi-nor.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/mtd/spi-nor/spi-nor.c	2017-02-12 16:03:20.000000000 -0500
@@ -799,6 +799,7 @@ static const struct flash_info spi_nor_i
 	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
 
 	{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024,   8, SECT_4K) },
+	{ "at25df321",  INFO(0x1f4700, 0, 64 * 1024,  64, SECT_4K) },
 	{ "at25df321a", INFO(0x1f4701, 0, 64 * 1024,  64, SECT_4K) },
 	{ "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
 
@@ -825,6 +826,7 @@ static const struct flash_info spi_nor_i
 	/* Everspin */
 	{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
 	{ "mr25h10",  CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "mr25h40",  CAT25_INFO(512 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
 
 	/* Fujitsu */
 	{ "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
@@ -872,11 +874,13 @@ static const struct flash_info spi_nor_i
 	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
 	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
 	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
+	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K) },
 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
 	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
 
 	/* Micron */
+	{ "n25q016a",	 INFO(0x20bb15, 0, 64 * 1024,   32, SECT_4K | SPI_NOR_QUAD_READ) },
 	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
 	{ "n25q032a",	 INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
 	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | SPI_NOR_QUAD_READ) },
@@ -905,7 +909,7 @@ static const struct flash_info spi_nor_i
 	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
 	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
 	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
-	{ "s25fl128s",	INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "s25fl128s",	INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
@@ -921,6 +925,7 @@ static const struct flash_info spi_nor_i
 	{ "s25fl132k",  INFO(0x014016,      0,  64 * 1024,  64, SECT_4K) },
 	{ "s25fl164k",  INFO(0x014017,      0,  64 * 1024, 128, SECT_4K) },
 	{ "s25fl204k",  INFO(0x014013,      0,  64 * 1024,   8, SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "s25fl208k",  INFO(0x014014,      0,  64 * 1024,  16, SECT_4K | SPI_NOR_DUAL_READ) },
 
 	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
 	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, SECT_4K | SST_WRITE) },
@@ -1255,6 +1260,13 @@ static int spansion_quad_enable(struct s
 		return -EINVAL;
 	}
 
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret) {
+		dev_err(nor->dev,
+			"timeout while writing configuration register\n");
+		return ret;
+	}
+
 	/* read back and check it */
 	ret = read_cr(nor);
 	if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/appletalk/ipddp.c linux-libre-4.10-rc8-gnu/drivers/net/appletalk/ipddp.c
--- linux-libre-4.9-gnu/drivers/net/appletalk/ipddp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/appletalk/ipddp.c	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 #include <linux/if_arp.h>
 #include <linux/slab.h>
 #include <net/route.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "ipddp.h"		/* Our stuff */
 
@@ -59,7 +59,6 @@ static int ipddp_ioctl(struct net_device
 static const struct net_device_ops ipddp_netdev_ops = {
 	.ndo_start_xmit		= ipddp_xmit,
 	.ndo_do_ioctl   	= ipddp_ioctl,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
@@ -191,7 +190,7 @@ static netdev_tx_t ipddp_xmit(struct sk_
  */
 static int ipddp_create(struct ipddp_route *new_rt)
 {
-        struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL);
+        struct ipddp_route *rt = kzalloc(sizeof(*rt), GFP_KERNEL);
 
         if (rt == NULL)
                 return -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/bonding/bond_alb.c linux-libre-4.10-rc8-gnu/drivers/net/bonding/bond_alb.c
--- linux-libre-4.9-gnu/drivers/net/bonding/bond_alb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/bonding/bond_alb.c	2017-02-12 16:03:20.000000000 -0500
@@ -950,13 +950,61 @@ static void alb_send_lp_vid(struct slave
 	dev_queue_xmit(skb);
 }
 
+struct alb_walk_data {
+	struct bonding *bond;
+	struct slave *slave;
+	u8 *mac_addr;
+	bool strict_match;
+};
+
+static int alb_upper_dev_walk(struct net_device *upper, void *_data)
+{
+	struct alb_walk_data *data = _data;
+	bool strict_match = data->strict_match;
+	struct bonding *bond = data->bond;
+	struct slave *slave = data->slave;
+	u8 *mac_addr = data->mac_addr;
+	struct bond_vlan_tag *tags;
+
+	if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
+		if (strict_match &&
+		    ether_addr_equal_64bits(mac_addr,
+					    upper->dev_addr)) {
+			alb_send_lp_vid(slave, mac_addr,
+					vlan_dev_vlan_proto(upper),
+					vlan_dev_vlan_id(upper));
+		} else if (!strict_match) {
+			alb_send_lp_vid(slave, upper->dev_addr,
+					vlan_dev_vlan_proto(upper),
+					vlan_dev_vlan_id(upper));
+		}
+	}
+
+	/* If this is a macvlan device, then only send updates
+	 * when strict_match is turned off.
+	 */
+	if (netif_is_macvlan(upper) && !strict_match) {
+		tags = bond_verify_device_path(bond->dev, upper, 0);
+		if (IS_ERR_OR_NULL(tags))
+			BUG();
+		alb_send_lp_vid(slave, upper->dev_addr,
+				tags[0].vlan_proto, tags[0].vlan_id);
+		kfree(tags);
+	}
+
+	return 0;
+}
+
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
 				      bool strict_match)
 {
 	struct bonding *bond = bond_get_bond_by_slave(slave);
-	struct net_device *upper;
-	struct list_head *iter;
-	struct bond_vlan_tag *tags;
+	struct alb_walk_data data = {
+		.strict_match = strict_match,
+		.mac_addr = mac_addr,
+		.slave = slave,
+		.bond = bond,
+	};
 
 	/* send untagged */
 	alb_send_lp_vid(slave, mac_addr, 0, 0);
@@ -965,33 +1013,7 @@ static void alb_send_learning_packets(st
 	 * for that device.
 	 */
 	rcu_read_lock();
-	netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
-		if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
-			if (strict_match &&
-			    ether_addr_equal_64bits(mac_addr,
-						    upper->dev_addr)) {
-				alb_send_lp_vid(slave, mac_addr,
-						vlan_dev_vlan_proto(upper),
-						vlan_dev_vlan_id(upper));
-			} else if (!strict_match) {
-				alb_send_lp_vid(slave, upper->dev_addr,
-						vlan_dev_vlan_proto(upper),
-						vlan_dev_vlan_id(upper));
-			}
-		}
-
-		/* If this is a macvlan device, then only send updates
-		 * when strict_match is turned off.
-		 */
-		if (netif_is_macvlan(upper) && !strict_match) {
-			tags = bond_verify_device_path(bond->dev, upper, 0);
-			if (IS_ERR_OR_NULL(tags))
-				BUG();
-			alb_send_lp_vid(slave, upper->dev_addr,
-					tags[0].vlan_proto, tags[0].vlan_id);
-			kfree(tags);
-		}
-	}
+	netdev_walk_all_upper_dev_rcu(bond->dev, alb_upper_dev_walk, &data);
 	rcu_read_unlock();
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/bonding/bond_main.c linux-libre-4.10-rc8-gnu/drivers/net/bonding/bond_main.c
--- linux-libre-4.9-gnu/drivers/net/bonding/bond_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/bonding/bond_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -199,7 +199,7 @@ MODULE_PARM_DESC(lp_interval, "The numbe
 atomic_t netpoll_block_tx = ATOMIC_INIT(0);
 #endif
 
-int bond_net_id __read_mostly;
+unsigned int bond_net_id __read_mostly;
 
 static __be32 arp_target[BOND_MAX_ARP_TARGETS];
 static int arp_ip_count;
@@ -2270,22 +2270,23 @@ re_arm:
 	}
 }
 
+static int bond_upper_dev_walk(struct net_device *upper, void *data)
+{
+	__be32 ip = *((__be32 *)data);
+
+	return ip == bond_confirm_addr(upper, 0, ip);
+}
+
 static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
 {
-	struct net_device *upper;
-	struct list_head *iter;
 	bool ret = false;
 
 	if (ip == bond_confirm_addr(bond->dev, 0, ip))
 		return true;
 
 	rcu_read_lock();
-	netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
-		if (ip == bond_confirm_addr(upper, 0, ip)) {
-			ret = true;
-			break;
-		}
-	}
+	if (netdev_walk_all_upper_dev_rcu(bond->dev, bond_upper_dev_walk, &ip))
+		ret = true;
 	rcu_read_unlock();
 
 	return ret;
@@ -4079,16 +4080,16 @@ static netdev_tx_t bond_start_xmit(struc
 	return ret;
 }
 
-static int bond_ethtool_get_settings(struct net_device *bond_dev,
-				     struct ethtool_cmd *ecmd)
+static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev,
+					   struct ethtool_link_ksettings *cmd)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
 	unsigned long speed = 0;
 	struct list_head *iter;
 	struct slave *slave;
 
-	ecmd->duplex = DUPLEX_UNKNOWN;
-	ecmd->port = PORT_OTHER;
+	cmd->base.duplex = DUPLEX_UNKNOWN;
+	cmd->base.port = PORT_OTHER;
 
 	/* Since bond_slave_can_tx returns false for all inactive or down slaves, we
 	 * do not need to check mode.  Though link speed might not represent
@@ -4099,12 +4100,12 @@ static int bond_ethtool_get_settings(str
 		if (bond_slave_can_tx(slave)) {
 			if (slave->speed != SPEED_UNKNOWN)
 				speed += slave->speed;
-			if (ecmd->duplex == DUPLEX_UNKNOWN &&
+			if (cmd->base.duplex == DUPLEX_UNKNOWN &&
 			    slave->duplex != DUPLEX_UNKNOWN)
-				ecmd->duplex = slave->duplex;
+				cmd->base.duplex = slave->duplex;
 		}
 	}
-	ethtool_cmd_speed_set(ecmd, speed ? : SPEED_UNKNOWN);
+	cmd->base.speed = speed ? : SPEED_UNKNOWN;
 
 	return 0;
 }
@@ -4120,8 +4121,8 @@ static void bond_ethtool_get_drvinfo(str
 
 static const struct ethtool_ops bond_ethtool_ops = {
 	.get_drvinfo		= bond_ethtool_get_drvinfo,
-	.get_settings		= bond_ethtool_get_settings,
 	.get_link		= ethtool_op_get_link,
+	.get_link_ksettings	= bond_ethtool_get_link_ksettings,
 };
 
 static const struct net_device_ops bond_netdev_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/can/c_can/c_can_pci.c linux-libre-4.10-rc8-gnu/drivers/net/can/c_can/c_can_pci.c
--- linux-libre-4.9-gnu/drivers/net/can/c_can/c_can_pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/can/c_can/c_can_pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -161,6 +161,7 @@ static int c_can_pci_probe(struct pci_de
 
 	dev->irq = pdev->irq;
 	priv->base = addr;
+	priv->device = &pdev->dev;
 
 	if (!c_can_pci_data->freq) {
 		dev_err(&pdev->dev, "no clock frequency defined\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/can/grcan.c linux-libre-4.10-rc8-gnu/drivers/net/can/grcan.c
--- linux-libre-4.9-gnu/drivers/net/can/grcan.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/can/grcan.c	2017-02-12 16:03:20.000000000 -0500
@@ -15,7 +15,7 @@
  * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the
  * sysfs interface.
  *
- * See "Documentation/kernel-parameters.txt" for information on the module
+ * See "Documentation/admin-guide/kernel-parameters.rst" for information on the module
  * parameters.
  *
  * This program is free software; you can redistribute it and/or modify it
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/can/Makefile linux-libre-4.10-rc8-gnu/drivers/net/can/Makefile
--- linux-libre-4.9-gnu/drivers/net/can/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/can/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -31,5 +31,4 @@ obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
 obj-$(CONFIG_CAN_XILINXCAN)	+= xilinx_can.o
 obj-$(CONFIG_PCH_CAN)		+= pch_can.o
 
-subdir-ccflags-y += -D__CHECK_ENDIAN__
 subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/can/softing/softing_fw.c linux-libre-4.10-rc8-gnu/drivers/net/can/softing/softing_fw.c
--- linux-libre-4.9-gnu/drivers/net/can/softing/softing_fw.c	2016-12-11 17:57:34.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/can/softing/softing_fw.c	2017-02-12 17:49:21.000000000 -0500
@@ -390,7 +390,7 @@ static void softing_initialize_timestamp
 	ovf = 0x100000000ULL * 16;
 	do_div(ovf, card->pdat->freq ?: 16);
 
-	card->ts_overflow = ktime_add_us(ktime_set(0, 0), ovf);
+	card->ts_overflow = ktime_add_us(0, ovf);
 }
 
 ktime_t softing_raw2ktime(struct softing *card, u32 raw)
@@ -647,7 +647,7 @@ int softing_startstop(struct net_device
 		open_candev(netdev);
 		if (dev != netdev) {
 			/* notify other busses on the restart */
-			softing_netdev_rx(netdev, &msg, ktime_set(0, 0));
+			softing_netdev_rx(netdev, &msg, 0);
 			++priv->can.can_stats.restarts;
 		}
 		netif_wake_queue(netdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/can/softing/softing_main.c linux-libre-4.10-rc8-gnu/drivers/net/can/softing/softing_main.c
--- linux-libre-4.9-gnu/drivers/net/can/softing/softing_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/can/softing/softing_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -192,7 +192,7 @@ static int softing_handle_1(struct softi
 				/* a dead bus has no overflows */
 				continue;
 			++netdev->stats.rx_over_errors;
-			softing_netdev_rx(netdev, &msg, ktime_set(0, 0));
+			softing_netdev_rx(netdev, &msg, 0);
 		}
 		/* prepare for other use */
 		memset(&msg, 0, sizeof(msg));
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/can/ti_hecc.c linux-libre-4.10-rc8-gnu/drivers/net/can/ti_hecc.c
--- linux-libre-4.9-gnu/drivers/net/can/ti_hecc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/can/ti_hecc.c	2017-02-12 16:03:20.000000000 -0500
@@ -948,7 +948,12 @@ static int ti_hecc_probe(struct platform
 	netif_napi_add(ndev, &priv->napi, ti_hecc_rx_poll,
 		HECC_DEF_NAPI_WEIGHT);
 
-	clk_enable(priv->clk);
+	err = clk_prepare_enable(priv->clk);
+	if (err) {
+		dev_err(&pdev->dev, "clk_prepare_enable() failed\n");
+		goto probe_exit_clk;
+	}
+
 	err = register_candev(ndev);
 	if (err) {
 		dev_err(&pdev->dev, "register_candev() failed\n");
@@ -981,7 +986,7 @@ static int ti_hecc_remove(struct platfor
 	struct ti_hecc_priv *priv = netdev_priv(ndev);
 
 	unregister_candev(ndev);
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 	clk_put(priv->clk);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	iounmap(priv->base);
@@ -1006,7 +1011,7 @@ static int ti_hecc_suspend(struct platfo
 	hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
 	priv->can.state = CAN_STATE_SLEEPING;
 
-	clk_disable(priv->clk);
+	clk_disable_unprepare(priv->clk);
 
 	return 0;
 }
@@ -1015,8 +1020,11 @@ static int ti_hecc_resume(struct platfor
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct ti_hecc_priv *priv = netdev_priv(dev);
+	int err;
 
-	clk_enable(priv->clk);
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
 
 	hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_PDR);
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/can/usb/kvaser_usb.c linux-libre-4.10-rc8-gnu/drivers/net/can/usb/kvaser_usb.c
--- linux-libre-4.9-gnu/drivers/net/can/usb/kvaser_usb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/can/usb/kvaser_usb.c	2017-02-12 16:03:20.000000000 -0500
@@ -459,7 +459,7 @@ struct kvaser_usb {
 	struct usb_endpoint_descriptor *bulk_in, *bulk_out;
 	struct usb_anchor rx_submitted;
 
-	/* @max_tx_urbs: Firmware-reported maximum number of oustanding,
+	/* @max_tx_urbs: Firmware-reported maximum number of outstanding,
 	 * not yet ACKed, transmissions on this device. This value is
 	 * also used as a sentinel for marking free tx contexts.
 	 */
@@ -2027,7 +2027,7 @@ static int kvaser_usb_probe(struct usb_i
 		((dev->fw_version >> 16) & 0xff),
 		(dev->fw_version & 0xffff));
 
-	dev_dbg(&intf->dev, "Max oustanding tx = %d URBs\n", dev->max_tx_urbs);
+	dev_dbg(&intf->dev, "Max outstanding tx = %d URBs\n", dev->max_tx_urbs);
 
 	err = kvaser_usb_get_card_info(dev);
 	if (err) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/cris/eth_v10.c linux-libre-4.10-rc8-gnu/drivers/net/cris/eth_v10.c
--- linux-libre-4.9-gnu/drivers/net/cris/eth_v10.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/cris/eth_v10.c	2017-02-12 16:03:20.000000000 -0500
@@ -7,9 +7,6 @@
  *
  */
 
-
-#include <linux/module.h>
-
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/types.h>
@@ -264,7 +261,6 @@ static const struct net_device_ops e100_
 	.ndo_do_ioctl		= e100_ioctl,
 	.ndo_set_mac_address	= e100_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_config		= e100_set_config,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= e100_netpoll,
@@ -412,6 +408,7 @@ etrax_ethernet_init(void)
 	led_next_time = jiffies;
 	return 0;
 }
+device_initcall(etrax_ethernet_init)
 
 /* set MAC address of the interface. called from the core after a
  * SIOCSIFADDR ioctl, and from the bootup above.
@@ -1715,11 +1712,6 @@ e100_netpoll(struct net_device* netdev)
 }
 #endif
 
-static int
-etrax_init_module(void)
-{
-	return etrax_ethernet_init();
-}
 
 static int __init
 e100_boot_setup(char* str)
@@ -1742,5 +1734,3 @@ e100_boot_setup(char* str)
 }
 
 __setup("etrax100_eth=", e100_boot_setup);
-
-module_init(etrax_init_module);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/bcm_sf2.c linux-libre-4.10-rc8-gnu/drivers/net/dsa/bcm_sf2.c
--- linux-libre-4.9-gnu/drivers/net/dsa/bcm_sf2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/bcm_sf2.c	2017-02-12 16:03:20.000000000 -0500
@@ -393,7 +393,7 @@ static int bcm_sf2_sw_mdio_read(struct m
 	if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
 		return bcm_sf2_sw_indir_rw(priv, 1, addr, regnum, 0);
 	else
-		return mdiobus_read(priv->master_mii_bus, addr, regnum);
+		return mdiobus_read_nested(priv->master_mii_bus, addr, regnum);
 }
 
 static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
@@ -407,7 +407,7 @@ static int bcm_sf2_sw_mdio_write(struct
 	if (addr == BRCM_PSEUDO_PHY_ADDR && priv->indir_phy_mask & BIT(addr))
 		bcm_sf2_sw_indir_rw(priv, 0, addr, regnum, val);
 	else
-		mdiobus_write(priv->master_mii_bus, addr, regnum, val);
+		mdiobus_write_nested(priv->master_mii_bus, addr, regnum, val);
 
 	return 0;
 }
@@ -982,6 +982,7 @@ static int bcm_sf2_sw_probe(struct platf
 	const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
 	struct device_node *dn = pdev->dev.of_node;
 	struct b53_platform_data *pdata;
+	struct dsa_switch_ops *ops;
 	struct bcm_sf2_priv *priv;
 	struct b53_device *dev;
 	struct dsa_switch *ds;
@@ -995,6 +996,10 @@ static int bcm_sf2_sw_probe(struct platf
 	if (!priv)
 		return -ENOMEM;
 
+	ops = devm_kzalloc(&pdev->dev, sizeof(*ops), GFP_KERNEL);
+	if (!ops)
+		return -ENOMEM;
+
 	dev = b53_switch_alloc(&pdev->dev, &bcm_sf2_io_ops, priv);
 	if (!dev)
 		return -ENOMEM;
@@ -1014,6 +1019,8 @@ static int bcm_sf2_sw_probe(struct platf
 	ds = dev->ds;
 
 	/* Override the parts that are non-standard wrt. normal b53 devices */
+	memcpy(ops, ds->ops, sizeof(*ops));
+	ds->ops = ops;
 	ds->ops->get_tag_protocol = bcm_sf2_sw_get_tag_protocol;
 	ds->ops->setup = bcm_sf2_sw_setup;
 	ds->ops->get_phy_flags = bcm_sf2_sw_get_phy_flags;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/chip.c linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/chip.c
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/chip.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/chip.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,11 +18,15 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/if_bridge.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/jiffies.h>
 #include <linux/list.h>
 #include <linux/mdio.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_mdio.h>
 #include <linux/netdevice.h>
 #include <linux/gpio/consumer.h>
@@ -33,6 +37,7 @@
 #include "mv88e6xxx.h"
 #include "global1.h"
 #include "global2.h"
+#include "port.h"
 
 static void assert_reg_lock(struct mv88e6xxx_chip *chip)
 {
@@ -217,22 +222,6 @@ int mv88e6xxx_write(struct mv88e6xxx_chi
 	return 0;
 }
 
-static int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
-			       u16 *val)
-{
-	int addr = chip->info->port_base_addr + port;
-
-	return mv88e6xxx_read(chip, addr, reg, val);
-}
-
-static int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
-				u16 val)
-{
-	int addr = chip->info->port_base_addr + port;
-
-	return mv88e6xxx_write(chip, addr, reg, val);
-}
-
 static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy,
 			      int reg, u16 *val)
 {
@@ -323,6 +312,180 @@ static int mv88e6xxx_serdes_write(struct
 					reg, val);
 }
 
+static void mv88e6xxx_g1_irq_mask(struct irq_data *d)
+{
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int n = d->hwirq;
+
+	chip->g1_irq.masked |= (1 << n);
+}
+
+static void mv88e6xxx_g1_irq_unmask(struct irq_data *d)
+{
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int n = d->hwirq;
+
+	chip->g1_irq.masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_g1_irq_thread_fn(int irq, void *dev_id)
+{
+	struct mv88e6xxx_chip *chip = dev_id;
+	unsigned int nhandled = 0;
+	unsigned int sub_irq;
+	unsigned int n;
+	u16 reg;
+	int err;
+
+	mutex_lock(&chip->reg_lock);
+	err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
+	mutex_unlock(&chip->reg_lock);
+
+	if (err)
+		goto out;
+
+	for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+		if (reg & (1 << n)) {
+			sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
+			handle_nested_irq(sub_irq);
+			++nhandled;
+		}
+	}
+out:
+	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
+
+static void mv88e6xxx_g1_irq_bus_lock(struct irq_data *d)
+{
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&chip->reg_lock);
+}
+
+static void mv88e6xxx_g1_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+	u16 mask = GENMASK(chip->g1_irq.nirqs, 0);
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &reg);
+	if (err)
+		goto out;
+
+	reg &= ~mask;
+	reg |= (~chip->g1_irq.masked & mask);
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
+	if (err)
+		goto out;
+
+out:
+	mutex_unlock(&chip->reg_lock);
+}
+
+static struct irq_chip mv88e6xxx_g1_irq_chip = {
+	.name			= "mv88e6xxx-g1",
+	.irq_mask		= mv88e6xxx_g1_irq_mask,
+	.irq_unmask		= mv88e6xxx_g1_irq_unmask,
+	.irq_bus_lock		= mv88e6xxx_g1_irq_bus_lock,
+	.irq_bus_sync_unlock	= mv88e6xxx_g1_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_g1_irq_domain_map(struct irq_domain *d,
+				       unsigned int irq,
+				       irq_hw_number_t hwirq)
+{
+	struct mv88e6xxx_chip *chip = d->host_data;
+
+	irq_set_chip_data(irq, d->host_data);
+	irq_set_chip_and_handler(irq, &chip->g1_irq.chip, handle_level_irq);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_g1_irq_domain_ops = {
+	.map	= mv88e6xxx_g1_irq_domain_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+static void mv88e6xxx_g1_irq_free(struct mv88e6xxx_chip *chip)
+{
+	int irq, virq;
+	u16 mask;
+
+	mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &mask);
+	mask |= GENMASK(chip->g1_irq.nirqs, 0);
+	mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
+
+	free_irq(chip->irq, chip);
+
+	for (irq = 0; irq < chip->g1_irq.nirqs; irq++) {
+		virq = irq_find_mapping(chip->g1_irq.domain, irq);
+		irq_dispose_mapping(virq);
+	}
+
+	irq_domain_remove(chip->g1_irq.domain);
+}
+
+static int mv88e6xxx_g1_irq_setup(struct mv88e6xxx_chip *chip)
+{
+	int err, irq, virq;
+	u16 reg, mask;
+
+	chip->g1_irq.nirqs = chip->info->g1_irqs;
+	chip->g1_irq.domain = irq_domain_add_simple(
+		NULL, chip->g1_irq.nirqs, 0,
+		&mv88e6xxx_g1_irq_domain_ops, chip);
+	if (!chip->g1_irq.domain)
+		return -ENOMEM;
+
+	for (irq = 0; irq < chip->g1_irq.nirqs; irq++)
+		irq_create_mapping(chip->g1_irq.domain, irq);
+
+	chip->g1_irq.chip = mv88e6xxx_g1_irq_chip;
+	chip->g1_irq.masked = ~0;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &mask);
+	if (err)
+		goto out_mapping;
+
+	mask &= ~GENMASK(chip->g1_irq.nirqs, 0);
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
+	if (err)
+		goto out_disable;
+
+	/* Reading the interrupt status clears (most of) them */
+	err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &reg);
+	if (err)
+		goto out_disable;
+
+	err = request_threaded_irq(chip->irq, NULL,
+				   mv88e6xxx_g1_irq_thread_fn,
+				   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+				   dev_name(chip->dev), chip);
+	if (err)
+		goto out_disable;
+
+	return 0;
+
+out_disable:
+	mask |= GENMASK(chip->g1_irq.nirqs, 0);
+	mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, mask);
+
+out_mapping:
+	for (irq = 0; irq < 16; irq++) {
+		virq = irq_find_mapping(chip->g1_irq.domain, irq);
+		irq_dispose_mapping(virq);
+	}
+
+	irq_domain_remove(chip->g1_irq.domain);
+
+	return err;
+}
+
 int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask)
 {
 	int i;
@@ -364,56 +527,18 @@ int mv88e6xxx_update(struct mv88e6xxx_ch
 
 static int mv88e6xxx_ppu_disable(struct mv88e6xxx_chip *chip)
 {
-	u16 val;
-	int i, err;
-
-	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
-	if (err)
-		return err;
-
-	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL,
-				 val & ~GLOBAL_CONTROL_PPU_ENABLE);
-	if (err)
-		return err;
-
-	for (i = 0; i < 16; i++) {
-		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
-		if (err)
-			return err;
-
-		usleep_range(1000, 2000);
-		if ((val & GLOBAL_STATUS_PPU_MASK) != GLOBAL_STATUS_PPU_POLLING)
-			return 0;
-	}
+	if (!chip->info->ops->ppu_disable)
+		return 0;
 
-	return -ETIMEDOUT;
+	return chip->info->ops->ppu_disable(chip);
 }
 
 static int mv88e6xxx_ppu_enable(struct mv88e6xxx_chip *chip)
 {
-	u16 val;
-	int i, err;
-
-	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
-	if (err)
-		return err;
-
-	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL,
-				 val | GLOBAL_CONTROL_PPU_ENABLE);
-	if (err)
-		return err;
-
-	for (i = 0; i < 16; i++) {
-		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
-		if (err)
-			return err;
-
-		usleep_range(1000, 2000);
-		if ((val & GLOBAL_STATUS_PPU_MASK) == GLOBAL_STATUS_PPU_POLLING)
-			return 0;
-	}
+	if (!chip->info->ops->ppu_enable)
+		return 0;
 
-	return -ETIMEDOUT;
+	return chip->info->ops->ppu_enable(chip);
 }
 
 static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
@@ -477,9 +602,8 @@ static void mv88e6xxx_ppu_state_init(str
 {
 	mutex_init(&chip->ppu_mutex);
 	INIT_WORK(&chip->ppu_work, mv88e6xxx_ppu_reenable_work);
-	init_timer(&chip->ppu_timer);
-	chip->ppu_timer.data = (unsigned long)chip;
-	chip->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
+	setup_timer(&chip->ppu_timer, mv88e6xxx_ppu_reenable_timer,
+		    (unsigned long)chip);
 }
 
 static void mv88e6xxx_ppu_state_destroy(struct mv88e6xxx_chip *chip)
@@ -515,11 +639,6 @@ static int mv88e6xxx_phy_ppu_write(struc
 	return err;
 }
 
-static bool mv88e6xxx_6065_family(struct mv88e6xxx_chip *chip)
-{
-	return chip->info->family == MV88E6XXX_FAMILY_6065;
-}
-
 static bool mv88e6xxx_6095_family(struct mv88e6xxx_chip *chip)
 {
 	return chip->info->family == MV88E6XXX_FAMILY_6095;
@@ -555,231 +674,152 @@ static bool mv88e6xxx_6352_family(struct
 	return chip->info->family == MV88E6XXX_FAMILY_6352;
 }
 
-/* We expect the switch to perform auto negotiation if there is a real
- * phy. However, in the case of a fixed link phy, we force the port
- * settings from the fixed link settings.
- */
-static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
-				  struct phy_device *phydev)
+static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
+				    int link, int speed, int duplex,
+				    phy_interface_t mode)
 {
-	struct mv88e6xxx_chip *chip = ds->priv;
-	u16 reg;
 	int err;
 
-	if (!phy_is_pseudo_fixed_link(phydev))
-		return;
-
-	mutex_lock(&chip->reg_lock);
+	if (!chip->info->ops->port_set_link)
+		return 0;
 
-	err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+	/* Port's MAC control must not be changed unless the link is down */
+	err = chip->info->ops->port_set_link(chip, port, 0);
 	if (err)
-		goto out;
-
-	reg &= ~(PORT_PCS_CTRL_LINK_UP |
-		 PORT_PCS_CTRL_FORCE_LINK |
-		 PORT_PCS_CTRL_DUPLEX_FULL |
-		 PORT_PCS_CTRL_FORCE_DUPLEX |
-		 PORT_PCS_CTRL_UNFORCED);
-
-	reg |= PORT_PCS_CTRL_FORCE_LINK;
-	if (phydev->link)
-		reg |= PORT_PCS_CTRL_LINK_UP;
-
-	if (mv88e6xxx_6065_family(chip) && phydev->speed > SPEED_100)
-		goto out;
+		return err;
 
-	switch (phydev->speed) {
-	case SPEED_1000:
-		reg |= PORT_PCS_CTRL_1000;
-		break;
-	case SPEED_100:
-		reg |= PORT_PCS_CTRL_100;
-		break;
-	case SPEED_10:
-		reg |= PORT_PCS_CTRL_10;
-		break;
-	default:
-		pr_info("Unknown speed");
-		goto out;
+	if (chip->info->ops->port_set_speed) {
+		err = chip->info->ops->port_set_speed(chip, port, speed);
+		if (err && err != -EOPNOTSUPP)
+			goto restore_link;
 	}
 
-	reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
-	if (phydev->duplex == DUPLEX_FULL)
-		reg |= PORT_PCS_CTRL_DUPLEX_FULL;
-
-	if ((mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip)) &&
-	    (port >= mv88e6xxx_num_ports(chip) - 2)) {
-		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
-			reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
-		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
-			reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
-		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
-			reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
-				PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
+	if (chip->info->ops->port_set_duplex) {
+		err = chip->info->ops->port_set_duplex(chip, port, duplex);
+		if (err && err != -EOPNOTSUPP)
+			goto restore_link;
 	}
-	mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
-
-out:
-	mutex_unlock(&chip->reg_lock);
-}
-
-static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip)
-{
-	u16 val;
-	int i, err;
 
-	for (i = 0; i < 10; i++) {
-		err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_OP, &val);
-		if ((val & GLOBAL_STATS_OP_BUSY) == 0)
-			return 0;
+	if (chip->info->ops->port_set_rgmii_delay) {
+		err = chip->info->ops->port_set_rgmii_delay(chip, port, mode);
+		if (err && err != -EOPNOTSUPP)
+			goto restore_link;
 	}
 
-	return -ETIMEDOUT;
-}
-
-static int _mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
-{
-	int err;
-
-	if (mv88e6xxx_6320_family(chip) || mv88e6xxx_6352_family(chip))
-		port = (port + 1) << 5;
-
-	/* Snapshot the hardware statistics counters for this port. */
-	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
-				 GLOBAL_STATS_OP_CAPTURE_PORT |
-				 GLOBAL_STATS_OP_HIST_RX_TX | port);
-	if (err)
-		return err;
+	err = 0;
+restore_link:
+	if (chip->info->ops->port_set_link(chip, port, link))
+		netdev_err(chip->ds->ports[port].netdev,
+			   "failed to restore MAC's link\n");
 
-	/* Wait for the snapshotting to complete. */
-	return _mv88e6xxx_stats_wait(chip);
+	return err;
 }
 
-static void _mv88e6xxx_stats_read(struct mv88e6xxx_chip *chip,
-				  int stat, u32 *val)
+/* We expect the switch to perform auto negotiation if there is a real
+ * phy. However, in the case of a fixed link phy, we force the port
+ * settings from the fixed link settings.
+ */
+static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
+				  struct phy_device *phydev)
 {
-	u32 value;
-	u16 reg;
+	struct mv88e6xxx_chip *chip = ds->priv;
 	int err;
 
-	*val = 0;
-
-	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
-				 GLOBAL_STATS_OP_READ_CAPTURED |
-				 GLOBAL_STATS_OP_HIST_RX_TX | stat);
-	if (err)
-		return;
-
-	err = _mv88e6xxx_stats_wait(chip);
-	if (err)
+	if (!phy_is_pseudo_fixed_link(phydev))
 		return;
 
-	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
-	if (err)
-		return;
+	mutex_lock(&chip->reg_lock);
+	err = mv88e6xxx_port_setup_mac(chip, port, phydev->link, phydev->speed,
+				       phydev->duplex, phydev->interface);
+	mutex_unlock(&chip->reg_lock);
 
-	value = reg << 16;
+	if (err && err != -EOPNOTSUPP)
+		netdev_err(ds->ports[port].netdev, "failed to configure MAC\n");
+}
 
-	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
-	if (err)
-		return;
+static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+	if (!chip->info->ops->stats_snapshot)
+		return -EOPNOTSUPP;
 
-	*val = value | reg;
+	return chip->info->ops->stats_snapshot(chip, port);
 }
 
 static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
-	{ "in_good_octets",	8, 0x00, BANK0, },
-	{ "in_bad_octets",	4, 0x02, BANK0, },
-	{ "in_unicast",		4, 0x04, BANK0, },
-	{ "in_broadcasts",	4, 0x06, BANK0, },
-	{ "in_multicasts",	4, 0x07, BANK0, },
-	{ "in_pause",		4, 0x16, BANK0, },
-	{ "in_undersize",	4, 0x18, BANK0, },
-	{ "in_fragments",	4, 0x19, BANK0, },
-	{ "in_oversize",	4, 0x1a, BANK0, },
-	{ "in_jabber",		4, 0x1b, BANK0, },
-	{ "in_rx_error",	4, 0x1c, BANK0, },
-	{ "in_fcs_error",	4, 0x1d, BANK0, },
-	{ "out_octets",		8, 0x0e, BANK0, },
-	{ "out_unicast",	4, 0x10, BANK0, },
-	{ "out_broadcasts",	4, 0x13, BANK0, },
-	{ "out_multicasts",	4, 0x12, BANK0, },
-	{ "out_pause",		4, 0x15, BANK0, },
-	{ "excessive",		4, 0x11, BANK0, },
-	{ "collisions",		4, 0x1e, BANK0, },
-	{ "deferred",		4, 0x05, BANK0, },
-	{ "single",		4, 0x14, BANK0, },
-	{ "multiple",		4, 0x17, BANK0, },
-	{ "out_fcs_error",	4, 0x03, BANK0, },
-	{ "late",		4, 0x1f, BANK0, },
-	{ "hist_64bytes",	4, 0x08, BANK0, },
-	{ "hist_65_127bytes",	4, 0x09, BANK0, },
-	{ "hist_128_255bytes",	4, 0x0a, BANK0, },
-	{ "hist_256_511bytes",	4, 0x0b, BANK0, },
-	{ "hist_512_1023bytes", 4, 0x0c, BANK0, },
-	{ "hist_1024_max_bytes", 4, 0x0d, BANK0, },
-	{ "sw_in_discards",	4, 0x10, PORT, },
-	{ "sw_in_filtered",	2, 0x12, PORT, },
-	{ "sw_out_filtered",	2, 0x13, PORT, },
-	{ "in_discards",	4, 0x00 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_filtered",	4, 0x01 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_accepted",	4, 0x02 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_bad_accepted",	4, 0x03 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_good_avb_class_a", 4, 0x04 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_good_avb_class_b", 4, 0x05 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_bad_avb_class_a", 4, 0x06 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_bad_avb_class_b", 4, 0x07 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "tcam_counter_0",	4, 0x08 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "tcam_counter_1",	4, 0x09 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "tcam_counter_2",	4, 0x0a | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "tcam_counter_3",	4, 0x0b | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_da_unknown",	4, 0x0e | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "in_management",	4, 0x0f | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_0",	4, 0x10 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_1",	4, 0x11 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_2",	4, 0x12 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_3",	4, 0x13 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_4",	4, 0x14 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_5",	4, 0x15 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_6",	4, 0x16 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_queue_7",	4, 0x17 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_cut_through",	4, 0x18 | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_octets_a",	4, 0x1a | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_octets_b",	4, 0x1b | GLOBAL_STATS_OP_BANK_1, BANK1, },
-	{ "out_management",	4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, },
+	{ "in_good_octets",		8, 0x00, STATS_TYPE_BANK0, },
+	{ "in_bad_octets",		4, 0x02, STATS_TYPE_BANK0, },
+	{ "in_unicast",			4, 0x04, STATS_TYPE_BANK0, },
+	{ "in_broadcasts",		4, 0x06, STATS_TYPE_BANK0, },
+	{ "in_multicasts",		4, 0x07, STATS_TYPE_BANK0, },
+	{ "in_pause",			4, 0x16, STATS_TYPE_BANK0, },
+	{ "in_undersize",		4, 0x18, STATS_TYPE_BANK0, },
+	{ "in_fragments",		4, 0x19, STATS_TYPE_BANK0, },
+	{ "in_oversize",		4, 0x1a, STATS_TYPE_BANK0, },
+	{ "in_jabber",			4, 0x1b, STATS_TYPE_BANK0, },
+	{ "in_rx_error",		4, 0x1c, STATS_TYPE_BANK0, },
+	{ "in_fcs_error",		4, 0x1d, STATS_TYPE_BANK0, },
+	{ "out_octets",			8, 0x0e, STATS_TYPE_BANK0, },
+	{ "out_unicast",		4, 0x10, STATS_TYPE_BANK0, },
+	{ "out_broadcasts",		4, 0x13, STATS_TYPE_BANK0, },
+	{ "out_multicasts",		4, 0x12, STATS_TYPE_BANK0, },
+	{ "out_pause",			4, 0x15, STATS_TYPE_BANK0, },
+	{ "excessive",			4, 0x11, STATS_TYPE_BANK0, },
+	{ "collisions",			4, 0x1e, STATS_TYPE_BANK0, },
+	{ "deferred",			4, 0x05, STATS_TYPE_BANK0, },
+	{ "single",			4, 0x14, STATS_TYPE_BANK0, },
+	{ "multiple",			4, 0x17, STATS_TYPE_BANK0, },
+	{ "out_fcs_error",		4, 0x03, STATS_TYPE_BANK0, },
+	{ "late",			4, 0x1f, STATS_TYPE_BANK0, },
+	{ "hist_64bytes",		4, 0x08, STATS_TYPE_BANK0, },
+	{ "hist_65_127bytes",		4, 0x09, STATS_TYPE_BANK0, },
+	{ "hist_128_255bytes",		4, 0x0a, STATS_TYPE_BANK0, },
+	{ "hist_256_511bytes",		4, 0x0b, STATS_TYPE_BANK0, },
+	{ "hist_512_1023bytes",		4, 0x0c, STATS_TYPE_BANK0, },
+	{ "hist_1024_max_bytes",	4, 0x0d, STATS_TYPE_BANK0, },
+	{ "sw_in_discards",		4, 0x10, STATS_TYPE_PORT, },
+	{ "sw_in_filtered",		2, 0x12, STATS_TYPE_PORT, },
+	{ "sw_out_filtered",		2, 0x13, STATS_TYPE_PORT, },
+	{ "in_discards",		4, 0x00, STATS_TYPE_BANK1, },
+	{ "in_filtered",		4, 0x01, STATS_TYPE_BANK1, },
+	{ "in_accepted",		4, 0x02, STATS_TYPE_BANK1, },
+	{ "in_bad_accepted",		4, 0x03, STATS_TYPE_BANK1, },
+	{ "in_good_avb_class_a",	4, 0x04, STATS_TYPE_BANK1, },
+	{ "in_good_avb_class_b",	4, 0x05, STATS_TYPE_BANK1, },
+	{ "in_bad_avb_class_a",		4, 0x06, STATS_TYPE_BANK1, },
+	{ "in_bad_avb_class_b",		4, 0x07, STATS_TYPE_BANK1, },
+	{ "tcam_counter_0",		4, 0x08, STATS_TYPE_BANK1, },
+	{ "tcam_counter_1",		4, 0x09, STATS_TYPE_BANK1, },
+	{ "tcam_counter_2",		4, 0x0a, STATS_TYPE_BANK1, },
+	{ "tcam_counter_3",		4, 0x0b, STATS_TYPE_BANK1, },
+	{ "in_da_unknown",		4, 0x0e, STATS_TYPE_BANK1, },
+	{ "in_management",		4, 0x0f, STATS_TYPE_BANK1, },
+	{ "out_queue_0",		4, 0x10, STATS_TYPE_BANK1, },
+	{ "out_queue_1",		4, 0x11, STATS_TYPE_BANK1, },
+	{ "out_queue_2",		4, 0x12, STATS_TYPE_BANK1, },
+	{ "out_queue_3",		4, 0x13, STATS_TYPE_BANK1, },
+	{ "out_queue_4",		4, 0x14, STATS_TYPE_BANK1, },
+	{ "out_queue_5",		4, 0x15, STATS_TYPE_BANK1, },
+	{ "out_queue_6",		4, 0x16, STATS_TYPE_BANK1, },
+	{ "out_queue_7",		4, 0x17, STATS_TYPE_BANK1, },
+	{ "out_cut_through",		4, 0x18, STATS_TYPE_BANK1, },
+	{ "out_octets_a",		4, 0x1a, STATS_TYPE_BANK1, },
+	{ "out_octets_b",		4, 0x1b, STATS_TYPE_BANK1, },
+	{ "out_management",		4, 0x1f, STATS_TYPE_BANK1, },
 };
 
-static bool mv88e6xxx_has_stat(struct mv88e6xxx_chip *chip,
-			       struct mv88e6xxx_hw_stat *stat)
-{
-	switch (stat->type) {
-	case BANK0:
-		return true;
-	case BANK1:
-		return mv88e6xxx_6320_family(chip);
-	case PORT:
-		return mv88e6xxx_6095_family(chip) ||
-			mv88e6xxx_6185_family(chip) ||
-			mv88e6xxx_6097_family(chip) ||
-			mv88e6xxx_6165_family(chip) ||
-			mv88e6xxx_6351_family(chip) ||
-			mv88e6xxx_6352_family(chip);
-	}
-	return false;
-}
-
 static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
 					    struct mv88e6xxx_hw_stat *s,
-					    int port)
+					    int port, u16 bank1_select,
+					    u16 histogram)
 {
 	u32 low;
 	u32 high = 0;
+	u16 reg = 0;
 	int err;
-	u16 reg;
 	u64 value;
 
 	switch (s->type) {
-	case PORT:
+	case STATS_TYPE_PORT:
 		err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
 		if (err)
 			return UINT64_MAX;
@@ -792,26 +832,28 @@ static uint64_t _mv88e6xxx_get_ethtool_s
 			high = reg;
 		}
 		break;
-	case BANK0:
-	case BANK1:
-		_mv88e6xxx_stats_read(chip, s->reg, &low);
+	case STATS_TYPE_BANK1:
+		reg = bank1_select;
+		/* fall through */
+	case STATS_TYPE_BANK0:
+		reg |= s->reg | histogram;
+		mv88e6xxx_g1_stats_read(chip, reg, &low);
 		if (s->sizeof_stat == 8)
-			_mv88e6xxx_stats_read(chip, s->reg + 1, &high);
+			mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
 	}
 	value = (((u64)high) << 16) | low;
 	return value;
 }
 
-static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
-				  uint8_t *data)
+static void mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
+					uint8_t *data, int types)
 {
-	struct mv88e6xxx_chip *chip = ds->priv;
 	struct mv88e6xxx_hw_stat *stat;
 	int i, j;
 
 	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
 		stat = &mv88e6xxx_hw_stats[i];
-		if (mv88e6xxx_has_stat(chip, stat)) {
+		if (stat->type & types) {
 			memcpy(data + j * ETH_GSTRING_LEN, stat->string,
 			       ETH_GSTRING_LEN);
 			j++;
@@ -819,46 +861,142 @@ static void mv88e6xxx_get_strings(struct
 	}
 }
 
-static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
+static void mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
+					uint8_t *data)
+{
+	mv88e6xxx_stats_get_strings(chip, data,
+				    STATS_TYPE_BANK0 | STATS_TYPE_PORT);
+}
+
+static void mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
+					uint8_t *data)
+{
+	mv88e6xxx_stats_get_strings(chip, data,
+				    STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
+}
+
+static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
+				  uint8_t *data)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
+
+	if (chip->info->ops->stats_get_strings)
+		chip->info->ops->stats_get_strings(chip, data);
+}
+
+static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
+					  int types)
+{
 	struct mv88e6xxx_hw_stat *stat;
 	int i, j;
 
 	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
 		stat = &mv88e6xxx_hw_stats[i];
-		if (mv88e6xxx_has_stat(chip, stat))
+		if (stat->type & types)
 			j++;
 	}
 	return j;
 }
 
+static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
+{
+	return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
+					      STATS_TYPE_PORT);
+}
+
+static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
+{
+	return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
+					      STATS_TYPE_BANK1);
+}
+
+static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
+{
+	struct mv88e6xxx_chip *chip = ds->priv;
+
+	if (chip->info->ops->stats_get_sset_count)
+		return chip->info->ops->stats_get_sset_count(chip);
+
+	return 0;
+}
+
+static void mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+				      uint64_t *data, int types,
+				      u16 bank1_select, u16 histogram)
+{
+	struct mv88e6xxx_hw_stat *stat;
+	int i, j;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
+		stat = &mv88e6xxx_hw_stats[i];
+		if (stat->type & types) {
+			data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
+							      bank1_select,
+							      histogram);
+			j++;
+		}
+	}
+}
+
+static void mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+				      uint64_t *data)
+{
+	return mv88e6xxx_stats_get_stats(chip, port, data,
+					 STATS_TYPE_BANK0 | STATS_TYPE_PORT,
+					 0, GLOBAL_STATS_OP_HIST_RX_TX);
+}
+
+static void mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+				      uint64_t *data)
+{
+	return mv88e6xxx_stats_get_stats(chip, port, data,
+					 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
+					 GLOBAL_STATS_OP_BANK_1_BIT_9,
+					 GLOBAL_STATS_OP_HIST_RX_TX);
+}
+
+static void mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+				      uint64_t *data)
+{
+	return mv88e6xxx_stats_get_stats(chip, port, data,
+					 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
+					 GLOBAL_STATS_OP_BANK_1_BIT_10, 0);
+}
+
+static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
+				uint64_t *data)
+{
+	if (chip->info->ops->stats_get_stats)
+		chip->info->ops->stats_get_stats(chip, port, data);
+}
+
 static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
 					uint64_t *data)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
-	struct mv88e6xxx_hw_stat *stat;
 	int ret;
-	int i, j;
 
 	mutex_lock(&chip->reg_lock);
 
-	ret = _mv88e6xxx_stats_snapshot(chip, port);
+	ret = mv88e6xxx_stats_snapshot(chip, port);
 	if (ret < 0) {
 		mutex_unlock(&chip->reg_lock);
 		return;
 	}
-	for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
-		stat = &mv88e6xxx_hw_stats[i];
-		if (mv88e6xxx_has_stat(chip, stat)) {
-			data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port);
-			j++;
-		}
-	}
+
+	mv88e6xxx_get_stats(chip, port, data);
 
 	mutex_unlock(&chip->reg_lock);
 }
 
+static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip)
+{
+	if (chip->info->ops->stats_set_histogram)
+		return chip->info->ops->stats_set_histogram(chip);
+
+	return 0;
+}
+
 static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
 {
 	return 32 * sizeof(u16);
@@ -1069,54 +1207,16 @@ static int _mv88e6xxx_atu_remove(struct
 	return _mv88e6xxx_atu_move(chip, fid, port, 0x0f, static_too);
 }
 
-static const char * const mv88e6xxx_port_state_names[] = {
-	[PORT_CONTROL_STATE_DISABLED] = "Disabled",
-	[PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
-	[PORT_CONTROL_STATE_LEARNING] = "Learning",
-	[PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
-};
-
-static int _mv88e6xxx_port_state(struct mv88e6xxx_chip *chip, int port,
-				 u8 state)
-{
-	struct dsa_switch *ds = chip->ds;
-	u16 reg;
-	int err;
-	u8 oldstate;
-
-	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
-	if (err)
-		return err;
-
-	oldstate = reg & PORT_CONTROL_STATE_MASK;
-
-	reg &= ~PORT_CONTROL_STATE_MASK;
-	reg |= state;
-
-	err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
-	if (err)
-		return err;
-
-	netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n",
-		   mv88e6xxx_port_state_names[state],
-		   mv88e6xxx_port_state_names[oldstate]);
-
-	return 0;
-}
-
 static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port)
 {
 	struct net_device *bridge = chip->ports[port].bridge_dev;
-	const u16 mask = (1 << mv88e6xxx_num_ports(chip)) - 1;
 	struct dsa_switch *ds = chip->ds;
 	u16 output_ports = 0;
-	u16 reg;
-	int err;
 	int i;
 
 	/* allow CPU port or DSA link(s) to send frames to every port */
 	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
-		output_ports = mask;
+		output_ports = ~0;
 	} else {
 		for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
 			/* allow sending frames to every group member */
@@ -1132,14 +1232,7 @@ static int _mv88e6xxx_port_based_vlan_ma
 	/* prevent frames from going back out of the port they came in on */
 	output_ports &= ~BIT(port);
 
-	err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
-	if (err)
-		return err;
-
-	reg &= ~mask;
-	reg |= output_ports & mask;
-
-	return mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+	return mv88e6xxx_port_set_vlan_map(chip, port, output_ports);
 }
 
 static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port,
@@ -1167,13 +1260,11 @@ static void mv88e6xxx_port_stp_state_set
 	}
 
 	mutex_lock(&chip->reg_lock);
-	err = _mv88e6xxx_port_state(chip, port, stp_state);
+	err = mv88e6xxx_port_set_state(chip, port, stp_state);
 	mutex_unlock(&chip->reg_lock);
 
 	if (err)
-		netdev_err(ds->ports[port].netdev,
-			   "failed to update state to %s\n",
-			   mv88e6xxx_port_state_names[stp_state]);
+		netdev_err(ds->ports[port].netdev, "failed to update state\n");
 }
 
 static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port)
@@ -1189,49 +1280,6 @@ static void mv88e6xxx_port_fast_age(stru
 		netdev_err(ds->ports[port].netdev, "failed to flush ATU\n");
 }
 
-static int _mv88e6xxx_port_pvid(struct mv88e6xxx_chip *chip, int port,
-				u16 *new, u16 *old)
-{
-	struct dsa_switch *ds = chip->ds;
-	u16 pvid, reg;
-	int err;
-
-	err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
-	if (err)
-		return err;
-
-	pvid = reg & PORT_DEFAULT_VLAN_MASK;
-
-	if (new) {
-		reg &= ~PORT_DEFAULT_VLAN_MASK;
-		reg |= *new & PORT_DEFAULT_VLAN_MASK;
-
-		err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
-		if (err)
-			return err;
-
-		netdev_dbg(ds->ports[port].netdev,
-			   "DefaultVID %d (was %d)\n", *new, pvid);
-	}
-
-	if (old)
-		*old = pvid;
-
-	return 0;
-}
-
-static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_chip *chip,
-				    int port, u16 *pvid)
-{
-	return _mv88e6xxx_port_pvid(chip, port, NULL, pvid);
-}
-
-static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_chip *chip,
-				    int port, u16 pvid)
-{
-	return _mv88e6xxx_port_pvid(chip, port, &pvid, NULL);
-}
-
 static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_chip *chip)
 {
 	return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY);
@@ -1411,7 +1459,7 @@ static int mv88e6xxx_port_vlan_dump(stru
 
 	mutex_lock(&chip->reg_lock);
 
-	err = _mv88e6xxx_port_pvid_get(chip, port, &pvid);
+	err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
 	if (err)
 		goto unlock;
 
@@ -1575,75 +1623,6 @@ loadpurge:
 	return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE);
 }
 
-static int _mv88e6xxx_port_fid(struct mv88e6xxx_chip *chip, int port,
-			       u16 *new, u16 *old)
-{
-	struct dsa_switch *ds = chip->ds;
-	u16 upper_mask;
-	u16 fid;
-	u16 reg;
-	int err;
-
-	if (mv88e6xxx_num_databases(chip) == 4096)
-		upper_mask = 0xff;
-	else if (mv88e6xxx_num_databases(chip) == 256)
-		upper_mask = 0xf;
-	else
-		return -EOPNOTSUPP;
-
-	/* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */
-	err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
-	if (err)
-		return err;
-
-	fid = (reg & PORT_BASE_VLAN_FID_3_0_MASK) >> 12;
-
-	if (new) {
-		reg &= ~PORT_BASE_VLAN_FID_3_0_MASK;
-		reg |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK;
-
-		err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
-		if (err)
-			return err;
-	}
-
-	/* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */
-	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
-	if (err)
-		return err;
-
-	fid |= (reg & upper_mask) << 4;
-
-	if (new) {
-		reg &= ~upper_mask;
-		reg |= (*new >> 4) & upper_mask;
-
-		err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
-		if (err)
-			return err;
-
-		netdev_dbg(ds->ports[port].netdev,
-			   "FID %d (was %d)\n", *new, fid);
-	}
-
-	if (old)
-		*old = fid;
-
-	return 0;
-}
-
-static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_chip *chip,
-				   int port, u16 *fid)
-{
-	return _mv88e6xxx_port_fid(chip, port, NULL, fid);
-}
-
-static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_chip *chip,
-				   int port, u16 fid)
-{
-	return _mv88e6xxx_port_fid(chip, port, &fid, NULL);
-}
-
 static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid)
 {
 	DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID);
@@ -1654,7 +1633,7 @@ static int _mv88e6xxx_fid_new(struct mv8
 
 	/* Set every FID bit used by the (un)bridged ports */
 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
-		err = _mv88e6xxx_port_fid_get(chip, i, fid);
+		err = mv88e6xxx_port_get_fid(chip, i, fid);
 		if (err)
 			return err;
 
@@ -1796,6 +1775,9 @@ static int mv88e6xxx_port_check_hw_vlan(
 			if (dsa_is_dsa_port(ds, i) || dsa_is_cpu_port(ds, i))
 				continue;
 
+			if (!ds->ports[port].netdev)
+				continue;
+
 			if (vlan.data[i] ==
 			    GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER)
 				continue;
@@ -1804,6 +1786,9 @@ static int mv88e6xxx_port_check_hw_vlan(
 			    chip->ports[port].bridge_dev)
 				break; /* same bridge, check next VLAN */
 
+			if (!chip->ports[i].bridge_dev)
+				continue;
+
 			netdev_warn(ds->ports[port].netdev,
 				    "hardware VLAN %d already used by %s\n",
 				    vlan.vid,
@@ -1819,48 +1804,19 @@ unlock:
 	return err;
 }
 
-static const char * const mv88e6xxx_port_8021q_mode_names[] = {
-	[PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
-	[PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
-	[PORT_CONTROL_2_8021Q_CHECK] = "Check",
-	[PORT_CONTROL_2_8021Q_SECURE] = "Secure",
-};
-
 static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port,
 					 bool vlan_filtering)
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
-	u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
+	u16 mode = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE :
 		PORT_CONTROL_2_8021Q_DISABLED;
-	u16 reg;
 	int err;
 
 	if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU))
 		return -EOPNOTSUPP;
 
 	mutex_lock(&chip->reg_lock);
-
-	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
-	if (err)
-		goto unlock;
-
-	old = reg & PORT_CONTROL_2_8021Q_MASK;
-
-	if (new != old) {
-		reg &= ~PORT_CONTROL_2_8021Q_MASK;
-		reg |= new & PORT_CONTROL_2_8021Q_MASK;
-
-		err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
-		if (err)
-			goto unlock;
-
-		netdev_dbg(ds->ports[port].netdev, "802.1Q Mode %s (was %s)\n",
-			   mv88e6xxx_port_8021q_mode_names[new],
-			   mv88e6xxx_port_8021q_mode_names[old]);
-	}
-
-	err = 0;
-unlock:
+	err = mv88e6xxx_port_set_8021q_mode(chip, port, mode);
 	mutex_unlock(&chip->reg_lock);
 
 	return err;
@@ -1928,7 +1884,7 @@ static void mv88e6xxx_port_vlan_add(stru
 				   "failed to add VLAN %d%c\n",
 				   vid, untagged ? 'u' : 't');
 
-	if (pvid && _mv88e6xxx_port_pvid_set(chip, port, vlan->vid_end))
+	if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end))
 		netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n",
 			   vlan->vid_end);
 
@@ -1983,7 +1939,7 @@ static int mv88e6xxx_port_vlan_del(struc
 
 	mutex_lock(&chip->reg_lock);
 
-	err = _mv88e6xxx_port_pvid_get(chip, port, &pvid);
+	err = mv88e6xxx_port_get_pvid(chip, port, &pvid);
 	if (err)
 		goto unlock;
 
@@ -1993,7 +1949,7 @@ static int mv88e6xxx_port_vlan_del(struc
 			goto unlock;
 
 		if (vid == pvid) {
-			err = _mv88e6xxx_port_pvid_set(chip, port, 0);
+			err = mv88e6xxx_port_set_pvid(chip, port, 0);
 			if (err)
 				goto unlock;
 		}
@@ -2104,7 +2060,7 @@ static int mv88e6xxx_port_db_load_purge(
 
 	/* Null VLAN ID corresponds to the port private database */
 	if (vid == 0)
-		err = _mv88e6xxx_port_fid_get(chip, port, &vlan.fid);
+		err = mv88e6xxx_port_get_fid(chip, port, &vlan.fid);
 	else
 		err = _mv88e6xxx_vtu_get(chip, vid, &vlan, false);
 	if (err)
@@ -2280,7 +2236,7 @@ static int mv88e6xxx_port_db_dump(struct
 	int err;
 
 	/* Dump port's default Filtering Information Database (VLAN ID 0) */
-	err = _mv88e6xxx_port_fid_get(chip, port, &fid);
+	err = mv88e6xxx_port_get_fid(chip, port, &fid);
 	if (err)
 		return err;
 
@@ -2368,67 +2324,58 @@ static void mv88e6xxx_port_bridge_leave(
 	mutex_unlock(&chip->reg_lock);
 }
 
-static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
+static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
 {
-	bool ppu_active = mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU_ACTIVE);
-	u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
-	struct gpio_desc *gpiod = chip->reset;
-	unsigned long timeout;
-	u16 reg;
-	int err;
-	int i;
-
-	/* Set all ports to the disabled state. */
-	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
-		err = mv88e6xxx_port_read(chip, i, PORT_CONTROL, &reg);
-		if (err)
-			return err;
+	if (chip->info->ops->reset)
+		return chip->info->ops->reset(chip);
 
-		err = mv88e6xxx_port_write(chip, i, PORT_CONTROL,
-					   reg & 0xfffc);
-		if (err)
-			return err;
-	}
+	return 0;
+}
 
-	/* Wait for transmit queues to drain. */
-	usleep_range(2000, 4000);
+static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
+{
+	struct gpio_desc *gpiod = chip->reset;
 
-	/* If there is a gpio connected to the reset pin, toggle it */
+	/* If there is a GPIO connected to the reset pin, toggle it */
 	if (gpiod) {
 		gpiod_set_value_cansleep(gpiod, 1);
 		usleep_range(10000, 20000);
 		gpiod_set_value_cansleep(gpiod, 0);
 		usleep_range(10000, 20000);
 	}
+}
 
-	/* Reset the switch. Keep the PPU active if requested. The PPU
-	 * needs to be active to support indirect phy register access
-	 * through global registers 0x18 and 0x19.
-	 */
-	if (ppu_active)
-		err = mv88e6xxx_g1_write(chip, 0x04, 0xc000);
-	else
-		err = mv88e6xxx_g1_write(chip, 0x04, 0xc400);
-	if (err)
-		return err;
+static int mv88e6xxx_disable_ports(struct mv88e6xxx_chip *chip)
+{
+	int i, err;
 
-	/* Wait up to one second for reset to complete. */
-	timeout = jiffies + 1 * HZ;
-	while (time_before(jiffies, timeout)) {
-		err = mv88e6xxx_g1_read(chip, 0x00, &reg);
+	/* Set all ports to the Disabled state */
+	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
+		err = mv88e6xxx_port_set_state(chip, i,
+					       PORT_CONTROL_STATE_DISABLED);
 		if (err)
 			return err;
-
-		if ((reg & is_reset) == is_reset)
-			break;
-		usleep_range(1000, 2000);
 	}
-	if (time_after(jiffies, timeout))
-		err = -ETIMEDOUT;
-	else
-		err = 0;
 
-	return err;
+	/* Wait for transmit queues to drain,
+	 * i.e. 2ms for a maximum frame to be transmitted at 10 Mbps.
+	 */
+	usleep_range(2000, 4000);
+
+	return 0;
+}
+
+static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip)
+{
+	int err;
+
+	err = mv88e6xxx_disable_ports(chip);
+	if (err)
+		return err;
+
+	mv88e6xxx_hardware_reset(chip);
+
+	return mv88e6xxx_software_reset(chip);
 }
 
 static int mv88e6xxx_serdes_power_on(struct mv88e6xxx_chip *chip)
@@ -2449,42 +2396,93 @@ static int mv88e6xxx_serdes_power_on(str
 	return err;
 }
 
-static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
+static int mv88e6xxx_setup_port_dsa(struct mv88e6xxx_chip *chip, int port,
+				    int upstream_port)
 {
-	struct dsa_switch *ds = chip->ds;
 	int err;
-	u16 reg;
 
-	if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
-	    mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
-	    mv88e6xxx_6185_family(chip) || mv88e6xxx_6095_family(chip) ||
-	    mv88e6xxx_6065_family(chip) || mv88e6xxx_6320_family(chip)) {
-		/* MAC Forcing register: don't force link, speed,
-		 * duplex or flow control state to any particular
-		 * values on physical ports, but force the CPU port
-		 * and all DSA ports to their maximum bandwidth and
-		 * full duplex.
-		 */
-		err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
-		if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
-			reg &= ~PORT_PCS_CTRL_UNFORCED;
-			reg |= PORT_PCS_CTRL_FORCE_LINK |
-				PORT_PCS_CTRL_LINK_UP |
-				PORT_PCS_CTRL_DUPLEX_FULL |
-				PORT_PCS_CTRL_FORCE_DUPLEX;
-			if (mv88e6xxx_6065_family(chip))
-				reg |= PORT_PCS_CTRL_100;
-			else
-				reg |= PORT_PCS_CTRL_1000;
-		} else {
-			reg |= PORT_PCS_CTRL_UNFORCED;
-		}
+	err = chip->info->ops->port_set_frame_mode(
+		chip, port, MV88E6XXX_FRAME_MODE_DSA);
+	if (err)
+		return err;
 
-		err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+	return chip->info->ops->port_set_egress_unknowns(
+		chip, port, port == upstream_port);
+}
+
+static int mv88e6xxx_setup_port_cpu(struct mv88e6xxx_chip *chip, int port)
+{
+	int err;
+
+	switch (chip->info->tag_protocol) {
+	case DSA_TAG_PROTO_EDSA:
+		err = chip->info->ops->port_set_frame_mode(
+			chip, port, MV88E6XXX_FRAME_MODE_ETHERTYPE);
+		if (err)
+			return err;
+
+		err = mv88e6xxx_port_set_egress_mode(
+			chip, port, PORT_CONTROL_EGRESS_ADD_TAG);
+		if (err)
+			return err;
+
+		if (chip->info->ops->port_set_ether_type)
+			err = chip->info->ops->port_set_ether_type(
+				chip, port, ETH_P_EDSA);
+		break;
+
+	case DSA_TAG_PROTO_DSA:
+		err = chip->info->ops->port_set_frame_mode(
+			chip, port, MV88E6XXX_FRAME_MODE_DSA);
 		if (err)
 			return err;
+
+		err = mv88e6xxx_port_set_egress_mode(
+			chip, port, PORT_CONTROL_EGRESS_UNMODIFIED);
+		break;
+	default:
+		err = -EINVAL;
 	}
 
+	if (err)
+		return err;
+
+	return chip->info->ops->port_set_egress_unknowns(chip, port, true);
+}
+
+static int mv88e6xxx_setup_port_normal(struct mv88e6xxx_chip *chip, int port)
+{
+	int err;
+
+	err = chip->info->ops->port_set_frame_mode(
+		chip, port, MV88E6XXX_FRAME_MODE_NORMAL);
+	if (err)
+		return err;
+
+	return chip->info->ops->port_set_egress_unknowns(chip, port, false);
+}
+
+static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)
+{
+	struct dsa_switch *ds = chip->ds;
+	int err;
+	u16 reg;
+
+	/* MAC Forcing register: don't force link, speed, duplex or flow control
+	 * state to any particular values on physical ports, but force the CPU
+	 * port and all DSA ports to their maximum bandwidth and full duplex.
+	 */
+	if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
+		err = mv88e6xxx_port_setup_mac(chip, port, LINK_FORCED_UP,
+					       SPEED_MAX, DUPLEX_FULL,
+					       PHY_INTERFACE_MODE_NA);
+	else
+		err = mv88e6xxx_port_setup_mac(chip, port, LINK_UNFORCED,
+					       SPEED_UNFORCED, DUPLEX_UNFORCED,
+					       PHY_INTERFACE_MODE_NA);
+	if (err)
+		return err;
+
 	/* Port Control: disable Drop-on-Unlock, disable Drop-on-Lock,
 	 * disable Header mode, enable IGMP/MLD snooping, disable VLAN
 	 * tunneling, determine priority by looking at 802.1p and IP
@@ -2499,44 +2497,23 @@ static int mv88e6xxx_setup_port(struct m
 	 * If this is the upstream port for this switch, enable
 	 * forwarding of unknown unicasts and multicasts.
 	 */
-	reg = 0;
-	if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
-	    mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
-	    mv88e6xxx_6095_family(chip) || mv88e6xxx_6065_family(chip) ||
-	    mv88e6xxx_6185_family(chip) || mv88e6xxx_6320_family(chip))
-		reg = PORT_CONTROL_IGMP_MLD_SNOOP |
+	reg = PORT_CONTROL_IGMP_MLD_SNOOP |
 		PORT_CONTROL_USE_TAG | PORT_CONTROL_USE_IP |
 		PORT_CONTROL_STATE_FORWARDING;
-	if (dsa_is_cpu_port(ds, port)) {
-		if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA))
-			reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA |
-				PORT_CONTROL_FORWARD_UNKNOWN_MC;
-		else
-			reg |= PORT_CONTROL_DSA_TAG;
-		reg |= PORT_CONTROL_EGRESS_ADD_TAG |
-			PORT_CONTROL_FORWARD_UNKNOWN;
-	}
-	if (dsa_is_dsa_port(ds, port)) {
-		if (mv88e6xxx_6095_family(chip) ||
-		    mv88e6xxx_6185_family(chip))
-			reg |= PORT_CONTROL_DSA_TAG;
-		if (mv88e6xxx_6352_family(chip) ||
-		    mv88e6xxx_6351_family(chip) ||
-		    mv88e6xxx_6165_family(chip) ||
-		    mv88e6xxx_6097_family(chip) ||
-		    mv88e6xxx_6320_family(chip)) {
-			reg |= PORT_CONTROL_FRAME_MODE_DSA;
-		}
+	err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+	if (err)
+		return err;
 
-		if (port == dsa_upstream_port(ds))
-			reg |= PORT_CONTROL_FORWARD_UNKNOWN |
-				PORT_CONTROL_FORWARD_UNKNOWN_MC;
-	}
-	if (reg) {
-		err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
-		if (err)
-			return err;
+	if (dsa_is_cpu_port(ds, port)) {
+		err = mv88e6xxx_setup_port_cpu(chip, port);
+	} else if (dsa_is_dsa_port(ds, port)) {
+		err = mv88e6xxx_setup_port_dsa(chip, port,
+					       dsa_upstream_port(ds));
+	} else {
+		err = mv88e6xxx_setup_port_normal(chip, port);
 	}
+	if (err)
+		return err;
 
 	/* If this port is connected to a SerDes, make sure the SerDes is not
 	 * powered down.
@@ -2568,10 +2545,6 @@ static int mv88e6xxx_setup_port(struct m
 	    mv88e6xxx_6185_family(chip))
 		reg = PORT_CONTROL_2_MAP_DA;
 
-	if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
-	    mv88e6xxx_6165_family(chip) || mv88e6xxx_6320_family(chip))
-		reg |= PORT_CONTROL_2_JUMBO_10240;
-
 	if (mv88e6xxx_6095_family(chip) || mv88e6xxx_6185_family(chip)) {
 		/* Set the upstream port this port should use */
 		reg |= dsa_upstream_port(ds);
@@ -2590,6 +2563,12 @@ static int mv88e6xxx_setup_port(struct m
 			return err;
 	}
 
+	if (chip->info->ops->port_jumbo_config) {
+		err = chip->info->ops->port_jumbo_config(chip, port);
+		if (err)
+			return err;
+	}
+
 	/* Port Association Vector: when learning source addresses
 	 * of packets, add the address to the address database using
 	 * a port bitmap that has only the bit for this port set and
@@ -2609,17 +2588,15 @@ static int mv88e6xxx_setup_port(struct m
 	if (err)
 		return err;
 
-	if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
-	    mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
-	    mv88e6xxx_6320_family(chip)) {
-		/* Do not limit the period of time that this port can
-		 * be paused for by the remote end or the period of
-		 * time that this port can pause the remote end.
-		 */
-		err = mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL, 0x0000);
+	if (chip->info->ops->port_pause_config) {
+		err = chip->info->ops->port_pause_config(chip, port);
 		if (err)
 			return err;
+	}
 
+	if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
+	    mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
+	    mv88e6xxx_6320_family(chip)) {
 		/* Port ATU control: disable limiting the number of
 		 * address database entries that this port is allowed
 		 * to use.
@@ -2633,45 +2610,16 @@ static int mv88e6xxx_setup_port(struct m
 					   0x0000);
 		if (err)
 			return err;
+	}
 
-		/* Port Ethertype: use the Ethertype DSA Ethertype
-		 * value.
-		 */
-		if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA)) {
-			err = mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE,
-						   ETH_P_EDSA);
-			if (err)
-				return err;
-		}
-
-		/* Tag Remap: use an identity 802.1p prio -> switch
-		 * prio mapping.
-		 */
-		err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123,
-					   0x3210);
-		if (err)
-			return err;
-
-		/* Tag Remap 2: use an identity 802.1p prio -> switch
-		 * prio mapping.
-		 */
-		err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567,
-					   0x7654);
+	if (chip->info->ops->port_tag_remap) {
+		err = chip->info->ops->port_tag_remap(chip, port);
 		if (err)
 			return err;
 	}
 
-	/* Rate Control: disable ingress rate limiting. */
-	if (mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip) ||
-	    mv88e6xxx_6165_family(chip) || mv88e6xxx_6097_family(chip) ||
-	    mv88e6xxx_6320_family(chip)) {
-		err = mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL,
-					   0x0001);
-		if (err)
-			return err;
-	} else if (mv88e6xxx_6185_family(chip) || mv88e6xxx_6095_family(chip)) {
-		err = mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL,
-					   0x0000);
+	if (chip->info->ops->port_egress_rate_limiting) {
+		err = chip->info->ops->port_egress_rate_limiting(chip, port);
 		if (err)
 			return err;
 	}
@@ -2687,7 +2635,7 @@ static int mv88e6xxx_setup_port(struct m
 	 * database, and allow bidirectional communication between the
 	 * CPU and DSA port(s), and the other ports.
 	 */
-	err = _mv88e6xxx_port_fid_set(chip, port, 0);
+	err = mv88e6xxx_port_set_fid(chip, port, 0);
 	if (err)
 		return err;
 
@@ -2701,7 +2649,7 @@ static int mv88e6xxx_setup_port(struct m
 	return mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, 0x0000);
 }
 
-int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
+static int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
 {
 	int err;
 
@@ -2764,30 +2712,26 @@ static int mv88e6xxx_g1_setup(struct mv8
 {
 	struct dsa_switch *ds = chip->ds;
 	u32 upstream_port = dsa_upstream_port(ds);
-	u16 reg;
 	int err;
 
 	/* Enable the PHY Polling Unit if present, don't discard any packets,
 	 * and mask all interrupt sources.
 	 */
-	reg = 0;
-	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU) ||
-	    mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU_ACTIVE))
-		reg |= GLOBAL_CONTROL_PPU_ENABLE;
-
-	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, reg);
+	err = mv88e6xxx_ppu_enable(chip);
 	if (err)
 		return err;
 
-	/* Configure the upstream port, and configure it as the port to which
-	 * ingress and egress and ARP monitor frames are to be sent.
-	 */
-	reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
-		upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT |
-		upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
-	err = mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
-	if (err)
-		return err;
+	if (chip->info->ops->g1_set_cpu_port) {
+		err = chip->info->ops->g1_set_cpu_port(chip, upstream_port);
+		if (err)
+			return err;
+	}
+
+	if (chip->info->ops->g1_set_egress_port) {
+		err = chip->info->ops->g1_set_egress_port(chip, upstream_port);
+		if (err)
+			return err;
+	}
 
 	/* Disable remote management, and set the switch's DSA device number. */
 	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2,
@@ -2850,6 +2794,11 @@ static int mv88e6xxx_g1_setup(struct mv8
 	if (err)
 		return err;
 
+	/* Initialize the statistics unit */
+	err = mv88e6xxx_stats_set_histogram(chip);
+	if (err)
+		return err;
+
 	/* Clear the statistics counters for all ports */
 	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
 				 GLOBAL_STATS_OP_FLUSH_ALL);
@@ -2857,7 +2806,7 @@ static int mv88e6xxx_g1_setup(struct mv8
 		return err;
 
 	/* Wait for the flush to complete. */
-	err = _mv88e6xxx_stats_wait(chip);
+	err = mv88e6xxx_g1_stats_wait(chip);
 	if (err)
 		return err;
 
@@ -2875,10 +2824,6 @@ static int mv88e6xxx_setup(struct dsa_sw
 
 	mutex_lock(&chip->reg_lock);
 
-	err = mv88e6xxx_switch_reset(chip);
-	if (err)
-		goto unlock;
-
 	/* Setup Switch Port Registers */
 	for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
 		err = mv88e6xxx_setup_port(chip, i);
@@ -2898,6 +2843,17 @@ static int mv88e6xxx_setup(struct dsa_sw
 			goto unlock;
 	}
 
+	/* Some generations have the configuration of sending reserved
+	 * management frames to the CPU in global2, others in
+	 * global1. Hence it does not fit the two setup functions
+	 * above.
+	 */
+	if (chip->info->ops->mgmt_rsvd2cpu) {
+		err = chip->info->ops->mgmt_rsvd2cpu(chip);
+		if (err)
+			goto unlock;
+	}
+
 unlock:
 	mutex_unlock(&chip->reg_lock);
 
@@ -3203,119 +3159,653 @@ static int mv88e6xxx_set_eeprom(struct d
 }
 
 static const struct mv88e6xxx_ops mv88e6085_ops = {
+	/* MV88E6XXX_FAMILY_6097 */
 	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
 	.phy_read = mv88e6xxx_phy_ppu_read,
 	.phy_write = mv88e6xxx_phy_ppu_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.ppu_enable = mv88e6185_g1_ppu_enable,
+	.ppu_disable = mv88e6185_g1_ppu_disable,
+	.reset = mv88e6185_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6095_ops = {
+	/* MV88E6XXX_FAMILY_6095 */
 	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
 	.phy_read = mv88e6xxx_phy_ppu_read,
 	.phy_write = mv88e6xxx_phy_ppu_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.ppu_enable = mv88e6185_g1_ppu_enable,
+	.ppu_disable = mv88e6185_g1_ppu_disable,
+	.reset = mv88e6185_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6097_ops = {
+	/* MV88E6XXX_FAMILY_6097 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6123_ops = {
+	/* MV88E6XXX_FAMILY_6165 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_read,
 	.phy_write = mv88e6xxx_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6131_ops = {
+	/* MV88E6XXX_FAMILY_6185 */
 	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
 	.phy_read = mv88e6xxx_phy_ppu_read,
 	.phy_write = mv88e6xxx_phy_ppu_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.ppu_enable = mv88e6185_g1_ppu_enable,
+	.ppu_disable = mv88e6185_g1_ppu_disable,
+	.reset = mv88e6185_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6161_ops = {
+	/* MV88E6XXX_FAMILY_6165 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_read,
 	.phy_write = mv88e6xxx_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6165_ops = {
+	/* MV88E6XXX_FAMILY_6165 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_read,
 	.phy_write = mv88e6xxx_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6171_ops = {
+	/* MV88E6XXX_FAMILY_6351 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6172_ops = {
+	/* MV88E6XXX_FAMILY_6352 */
 	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6352_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6175_ops = {
+	/* MV88E6XXX_FAMILY_6351 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6176_ops = {
+	/* MV88E6XXX_FAMILY_6352 */
 	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6352_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6185_ops = {
+	/* MV88E6XXX_FAMILY_6185 */
 	.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
 	.phy_read = mv88e6xxx_phy_ppu_read,
 	.phy_write = mv88e6xxx_phy_ppu_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_set_frame_mode = mv88e6085_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6085_port_set_egress_unknowns,
+	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
+	.stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.ppu_enable = mv88e6185_g1_ppu_enable,
+	.ppu_disable = mv88e6185_g1_ppu_disable,
+	.reset = mv88e6185_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6190_ops = {
+	/* MV88E6XXX_FAMILY_6390 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+	.port_set_speed = mv88e6390_port_set_speed,
+	.port_tag_remap = mv88e6390_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_pause_config = mv88e6390_port_pause_config,
+	.stats_snapshot = mv88e6390_g1_stats_snapshot,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6390_stats_get_stats,
+	.g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6390_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6190x_ops = {
+	/* MV88E6XXX_FAMILY_6390 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+	.port_set_speed = mv88e6390x_port_set_speed,
+	.port_tag_remap = mv88e6390_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_pause_config = mv88e6390_port_pause_config,
+	.stats_snapshot = mv88e6390_g1_stats_snapshot,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6390_stats_get_stats,
+	.g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6390_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6191_ops = {
+	/* MV88E6XXX_FAMILY_6390 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+	.port_set_speed = mv88e6390_port_set_speed,
+	.port_tag_remap = mv88e6390_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_pause_config = mv88e6390_port_pause_config,
+	.stats_snapshot = mv88e6390_g1_stats_snapshot,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6390_stats_get_stats,
+	.g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6390_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6240_ops = {
+	/* MV88E6XXX_FAMILY_6352 */
 	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6352_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6290_ops = {
+	/* MV88E6XXX_FAMILY_6390 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+	.port_set_speed = mv88e6390_port_set_speed,
+	.port_tag_remap = mv88e6390_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_pause_config = mv88e6390_port_pause_config,
+	.stats_snapshot = mv88e6390_g1_stats_snapshot,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6390_stats_get_stats,
+	.g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6390_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6320_ops = {
+	/* MV88E6XXX_FAMILY_6320 */
 	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6320_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6321_ops = {
+	/* MV88E6XXX_FAMILY_6321 */
 	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6320_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6350_ops = {
+	/* MV88E6XXX_FAMILY_6351 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6351_ops = {
+	/* MV88E6XXX_FAMILY_6351 */
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6185_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
 static const struct mv88e6xxx_ops mv88e6352_ops = {
+	/* MV88E6XXX_FAMILY_6352 */
 	.get_eeprom = mv88e6xxx_g2_get_eeprom16,
 	.set_eeprom = mv88e6xxx_g2_set_eeprom16,
 	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
 	.phy_read = mv88e6xxx_g2_smi_phy_read,
 	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
+	.port_set_speed = mv88e6352_port_set_speed,
+	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6097_port_pause_config,
+	.stats_snapshot = mv88e6320_g1_stats_snapshot,
+	.stats_get_sset_count = mv88e6095_stats_get_sset_count,
+	.stats_get_strings = mv88e6095_stats_get_strings,
+	.stats_get_stats = mv88e6095_stats_get_stats,
+	.g1_set_cpu_port = mv88e6095_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6095_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6095_g2_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6390_ops = {
+	/* MV88E6XXX_FAMILY_6390 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+	.port_set_speed = mv88e6390_port_set_speed,
+	.port_tag_remap = mv88e6390_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6390_port_pause_config,
+	.stats_snapshot = mv88e6390_g1_stats_snapshot,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6390_stats_get_stats,
+	.g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6390_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
 };
 
+static const struct mv88e6xxx_ops mv88e6390x_ops = {
+	/* MV88E6XXX_FAMILY_6390 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+	.port_set_speed = mv88e6390x_port_set_speed,
+	.port_tag_remap = mv88e6390_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_jumbo_config = mv88e6165_port_jumbo_config,
+	.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
+	.port_pause_config = mv88e6390_port_pause_config,
+	.stats_snapshot = mv88e6390_g1_stats_snapshot,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6390_stats_get_stats,
+	.g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6390_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
+};
+
+static const struct mv88e6xxx_ops mv88e6391_ops = {
+	/* MV88E6XXX_FAMILY_6390 */
+	.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+	.phy_read = mv88e6xxx_g2_smi_phy_read,
+	.phy_write = mv88e6xxx_g2_smi_phy_write,
+	.port_set_link = mv88e6xxx_port_set_link,
+	.port_set_duplex = mv88e6xxx_port_set_duplex,
+	.port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+	.port_set_speed = mv88e6390_port_set_speed,
+	.port_tag_remap = mv88e6390_port_tag_remap,
+	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
+	.port_set_egress_unknowns = mv88e6351_port_set_egress_unknowns,
+	.port_set_ether_type = mv88e6351_port_set_ether_type,
+	.port_pause_config = mv88e6390_port_pause_config,
+	.stats_snapshot = mv88e6390_g1_stats_snapshot,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
+	.stats_get_strings = mv88e6320_stats_get_strings,
+	.stats_get_stats = mv88e6390_stats_get_stats,
+	.g1_set_cpu_port = mv88e6390_g1_set_cpu_port,
+	.g1_set_egress_port = mv88e6390_g1_set_egress_port,
+	.mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+	.reset = mv88e6352_g1_reset,
+};
+
+static int mv88e6xxx_verify_madatory_ops(struct mv88e6xxx_chip *chip,
+					 const struct mv88e6xxx_ops *ops)
+{
+	if (!ops->port_set_frame_mode) {
+		dev_err(chip->dev, "Missing port_set_frame_mode");
+		return -EINVAL;
+	}
+
+	if (!ops->port_set_egress_unknowns) {
+		dev_err(chip->dev, "Missing port_set_egress_mode");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static const struct mv88e6xxx_info mv88e6xxx_table[] = {
 	[MV88E6085] = {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6085,
@@ -3326,6 +3816,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 8,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6097,
 		.ops = &mv88e6085_ops,
 	},
@@ -3339,10 +3831,27 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 8,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6095,
 		.ops = &mv88e6095_ops,
 	},
 
+	[MV88E6097] = {
+		.prod_num = PORT_SWITCH_ID_PROD_NUM_6097,
+		.family = MV88E6XXX_FAMILY_6097,
+		.name = "Marvell 88E6097/88E6097F",
+		.num_databases = 4096,
+		.num_ports = 11,
+		.port_base_addr = 0x10,
+		.global1_addr = 0x1b,
+		.age_time_coeff = 15000,
+		.g1_irqs = 8,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
+		.flags = MV88E6XXX_FLAGS_FAMILY_6097,
+		.ops = &mv88e6097_ops,
+	},
+
 	[MV88E6123] = {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6123,
 		.family = MV88E6XXX_FAMILY_6165,
@@ -3352,6 +3861,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6165,
 		.ops = &mv88e6123_ops,
 	},
@@ -3365,6 +3876,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6185,
 		.ops = &mv88e6131_ops,
 	},
@@ -3378,6 +3891,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6165,
 		.ops = &mv88e6161_ops,
 	},
@@ -3391,6 +3906,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6165,
 		.ops = &mv88e6165_ops,
 	},
@@ -3404,6 +3921,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 		.ops = &mv88e6171_ops,
 	},
@@ -3417,6 +3936,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 		.ops = &mv88e6172_ops,
 	},
@@ -3430,6 +3951,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 		.ops = &mv88e6175_ops,
 	},
@@ -3443,6 +3966,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 		.ops = &mv88e6176_ops,
 	},
@@ -3456,10 +3981,57 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 8,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6185,
 		.ops = &mv88e6185_ops,
 	},
 
+	[MV88E6190] = {
+		.prod_num = PORT_SWITCH_ID_PROD_NUM_6190,
+		.family = MV88E6XXX_FAMILY_6390,
+		.name = "Marvell 88E6190",
+		.num_databases = 4096,
+		.num_ports = 11,	/* 10 + Z80 */
+		.port_base_addr = 0x0,
+		.global1_addr = 0x1b,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
+		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
+		.ops = &mv88e6190_ops,
+	},
+
+	[MV88E6190X] = {
+		.prod_num = PORT_SWITCH_ID_PROD_NUM_6190X,
+		.family = MV88E6XXX_FAMILY_6390,
+		.name = "Marvell 88E6190X",
+		.num_databases = 4096,
+		.num_ports = 11,	/* 10 + Z80 */
+		.port_base_addr = 0x0,
+		.global1_addr = 0x1b,
+		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
+		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
+		.ops = &mv88e6190x_ops,
+	},
+
+	[MV88E6191] = {
+		.prod_num = PORT_SWITCH_ID_PROD_NUM_6191,
+		.family = MV88E6XXX_FAMILY_6390,
+		.name = "Marvell 88E6191",
+		.num_databases = 4096,
+		.num_ports = 11,	/* 10 + Z80 */
+		.port_base_addr = 0x0,
+		.global1_addr = 0x1b,
+		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
+		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
+		.ops = &mv88e6391_ops,
+	},
+
 	[MV88E6240] = {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
 		.family = MV88E6XXX_FAMILY_6352,
@@ -3469,10 +4041,27 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 		.ops = &mv88e6240_ops,
 	},
 
+	[MV88E6290] = {
+		.prod_num = PORT_SWITCH_ID_PROD_NUM_6290,
+		.family = MV88E6XXX_FAMILY_6390,
+		.name = "Marvell 88E6290",
+		.num_databases = 4096,
+		.num_ports = 11,	/* 10 + Z80 */
+		.port_base_addr = 0x0,
+		.global1_addr = 0x1b,
+		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
+		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
+		.ops = &mv88e6290_ops,
+	},
+
 	[MV88E6320] = {
 		.prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
 		.family = MV88E6XXX_FAMILY_6320,
@@ -3482,6 +4071,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 8,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6320,
 		.ops = &mv88e6320_ops,
 	},
@@ -3495,6 +4086,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 8,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6320,
 		.ops = &mv88e6321_ops,
 	},
@@ -3508,6 +4101,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 		.ops = &mv88e6350_ops,
 	},
@@ -3521,6 +4116,8 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6351,
 		.ops = &mv88e6351_ops,
 	},
@@ -3534,9 +4131,39 @@ static const struct mv88e6xxx_info mv88e
 		.port_base_addr = 0x10,
 		.global1_addr = 0x1b,
 		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_EDSA,
 		.flags = MV88E6XXX_FLAGS_FAMILY_6352,
 		.ops = &mv88e6352_ops,
 	},
+	[MV88E6390] = {
+		.prod_num = PORT_SWITCH_ID_PROD_NUM_6390,
+		.family = MV88E6XXX_FAMILY_6390,
+		.name = "Marvell 88E6390",
+		.num_databases = 4096,
+		.num_ports = 11,	/* 10 + Z80 */
+		.port_base_addr = 0x0,
+		.global1_addr = 0x1b,
+		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
+		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
+		.ops = &mv88e6390_ops,
+	},
+	[MV88E6390X] = {
+		.prod_num = PORT_SWITCH_ID_PROD_NUM_6390X,
+		.family = MV88E6XXX_FAMILY_6390,
+		.name = "Marvell 88E6390X",
+		.num_databases = 4096,
+		.num_ports = 11,	/* 10 + Z80 */
+		.port_base_addr = 0x0,
+		.global1_addr = 0x1b,
+		.age_time_coeff = 15000,
+		.g1_irqs = 9,
+		.tag_protocol = DSA_TAG_PROTO_DSA,
+		.flags = MV88E6XXX_FLAGS_FAMILY_6390,
+		.ops = &mv88e6390x_ops,
+	},
 };
 
 static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
@@ -3600,13 +4227,13 @@ static struct mv88e6xxx_chip *mv88e6xxx_
 
 static void mv88e6xxx_phy_init(struct mv88e6xxx_chip *chip)
 {
-	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU))
+	if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
 		mv88e6xxx_ppu_state_init(chip);
 }
 
 static void mv88e6xxx_phy_destroy(struct mv88e6xxx_chip *chip)
 {
-	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_PPU))
+	if (chip->info->ops->ppu_enable && chip->info->ops->ppu_disable)
 		mv88e6xxx_ppu_state_destroy(chip);
 }
 
@@ -3634,10 +4261,7 @@ static enum dsa_tag_protocol mv88e6xxx_g
 {
 	struct mv88e6xxx_chip *chip = ds->priv;
 
-	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_EDSA))
-		return DSA_TAG_PROTO_EDSA;
-
-	return DSA_TAG_PROTO_DSA;
+	return chip->info->tag_protocol;
 }
 
 static const char *mv88e6xxx_drv_probe(struct device *dsa_dev,
@@ -3667,6 +4291,12 @@ static const char *mv88e6xxx_drv_probe(s
 	if (err)
 		goto free;
 
+	mutex_lock(&chip->reg_lock);
+	err = mv88e6xxx_switch_reset(chip);
+	mutex_unlock(&chip->reg_lock);
+	if (err)
+		goto free;
+
 	mv88e6xxx_phy_init(chip);
 
 	err = mv88e6xxx_mdio_register(chip, NULL);
@@ -3819,35 +4449,82 @@ static int mv88e6xxx_probe(struct mdio_d
 
 	chip->info = compat_info;
 
+	err = mv88e6xxx_verify_madatory_ops(chip, chip->info->ops);
+	if (err)
+		return err;
+
 	err = mv88e6xxx_smi_init(chip, mdiodev->bus, mdiodev->addr);
 	if (err)
 		return err;
 
+	chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(chip->reset))
+		return PTR_ERR(chip->reset);
+
 	err = mv88e6xxx_detect(chip);
 	if (err)
 		return err;
 
 	mv88e6xxx_phy_init(chip);
 
-	chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
-	if (IS_ERR(chip->reset))
-		return PTR_ERR(chip->reset);
-
 	if (chip->info->ops->get_eeprom &&
 	    !of_property_read_u32(np, "eeprom-length", &eeprom_len))
 		chip->eeprom_len = eeprom_len;
 
+	mutex_lock(&chip->reg_lock);
+	err = mv88e6xxx_switch_reset(chip);
+	mutex_unlock(&chip->reg_lock);
+	if (err)
+		goto out;
+
+	chip->irq = of_irq_get(np, 0);
+	if (chip->irq == -EPROBE_DEFER) {
+		err = chip->irq;
+		goto out;
+	}
+
+	if (chip->irq > 0) {
+		/* Has to be performed before the MDIO bus is created,
+		 * because the PHYs will link there interrupts to these
+		 * interrupt controllers
+		 */
+		mutex_lock(&chip->reg_lock);
+		err = mv88e6xxx_g1_irq_setup(chip);
+		mutex_unlock(&chip->reg_lock);
+
+		if (err)
+			goto out;
+
+		if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT)) {
+			err = mv88e6xxx_g2_irq_setup(chip);
+			if (err)
+				goto out_g1_irq;
+		}
+	}
+
 	err = mv88e6xxx_mdio_register(chip, np);
 	if (err)
-		return err;
+		goto out_g2_irq;
 
 	err = mv88e6xxx_register_switch(chip, np);
-	if (err) {
-		mv88e6xxx_mdio_unregister(chip);
-		return err;
-	}
+	if (err)
+		goto out_mdio;
 
 	return 0;
+
+out_mdio:
+	mv88e6xxx_mdio_unregister(chip);
+out_g2_irq:
+	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT) && chip->irq > 0)
+		mv88e6xxx_g2_irq_free(chip);
+out_g1_irq:
+	if (chip->irq > 0) {
+		mutex_lock(&chip->reg_lock);
+		mv88e6xxx_g1_irq_free(chip);
+		mutex_unlock(&chip->reg_lock);
+	}
+out:
+	return err;
 }
 
 static void mv88e6xxx_remove(struct mdio_device *mdiodev)
@@ -3858,6 +4535,12 @@ static void mv88e6xxx_remove(struct mdio
 	mv88e6xxx_phy_destroy(chip);
 	mv88e6xxx_unregister_switch(chip);
 	mv88e6xxx_mdio_unregister(chip);
+
+	if (chip->irq > 0) {
+		if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_INT))
+			mv88e6xxx_g2_irq_free(chip);
+		mv88e6xxx_g1_irq_free(chip);
+	}
 }
 
 static const struct of_device_id mv88e6xxx_of_match[] = {
@@ -3865,6 +4548,10 @@ static const struct of_device_id mv88e6x
 		.compatible = "marvell,mv88e6085",
 		.data = &mv88e6xxx_table[MV88E6085],
 	},
+	{
+		.compatible = "marvell,mv88e6190",
+		.data = &mv88e6xxx_table[MV88E6190],
+	},
 	{ /* sentinel */ },
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global1.c linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global1.c
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global1.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,3 +32,370 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_c
 {
 	return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
 }
+
+/* Offset 0x00: Switch Global Status Register */
+
+static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
+{
+	u16 state;
+	int i, err;
+
+	for (i = 0; i < 16; i++) {
+		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
+		if (err)
+			return err;
+
+		/* Check the value of the PPUState bits 15:14 */
+		state &= GLOBAL_STATUS_PPU_STATE_MASK;
+		if (state != GLOBAL_STATUS_PPU_STATE_POLLING)
+			return 0;
+
+		usleep_range(1000, 2000);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
+{
+	u16 state;
+	int i, err;
+
+	for (i = 0; i < 16; ++i) {
+		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
+		if (err)
+			return err;
+
+		/* Check the value of the PPUState bits 15:14 */
+		state &= GLOBAL_STATUS_PPU_STATE_MASK;
+		if (state == GLOBAL_STATUS_PPU_STATE_POLLING)
+			return 0;
+
+		usleep_range(1000, 2000);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
+{
+	u16 state;
+	int i, err;
+
+	for (i = 0; i < 16; ++i) {
+		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &state);
+		if (err)
+			return err;
+
+		/* Check the value of the PPUState (or InitState) bit 15 */
+		if (state & GLOBAL_STATUS_PPU_STATE)
+			return 0;
+
+		usleep_range(1000, 2000);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
+{
+	const unsigned long timeout = jiffies + 1 * HZ;
+	u16 val;
+	int err;
+
+	/* Wait up to 1 second for the switch to be ready. The InitReady bit 11
+	 * is set to a one when all units inside the device (ATU, VTU, etc.)
+	 * have finished their initialization and are ready to accept frames.
+	 */
+	while (time_before(jiffies, timeout)) {
+		err = mv88e6xxx_g1_read(chip, GLOBAL_STATUS, &val);
+		if (err)
+			return err;
+
+		if (val & GLOBAL_STATUS_INIT_READY)
+			break;
+
+		usleep_range(1000, 2000);
+	}
+
+	if (time_after(jiffies, timeout))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/* Offset 0x04: Switch Global Control Register */
+
+int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
+{
+	u16 val;
+	int err;
+
+	/* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart
+	 * the PPU, including re-doing PHY detection and initialization
+	 */
+	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+	if (err)
+		return err;
+
+	val |= GLOBAL_CONTROL_SW_RESET;
+	val |= GLOBAL_CONTROL_PPU_ENABLE;
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+	if (err)
+		return err;
+
+	err = mv88e6xxx_g1_wait_init_ready(chip);
+	if (err)
+		return err;
+
+	return mv88e6185_g1_wait_ppu_polling(chip);
+}
+
+int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
+{
+	u16 val;
+	int err;
+
+	/* Set the SWReset bit 15 */
+	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+	if (err)
+		return err;
+
+	val |= GLOBAL_CONTROL_SW_RESET;
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+	if (err)
+		return err;
+
+	err = mv88e6xxx_g1_wait_init_ready(chip);
+	if (err)
+		return err;
+
+	return mv88e6352_g1_wait_ppu_polling(chip);
+}
+
+int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
+{
+	u16 val;
+	int err;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+	if (err)
+		return err;
+
+	val |= GLOBAL_CONTROL_PPU_ENABLE;
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+	if (err)
+		return err;
+
+	return mv88e6185_g1_wait_ppu_polling(chip);
+}
+
+int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
+{
+	u16 val;
+	int err;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL, &val);
+	if (err)
+		return err;
+
+	val &= ~GLOBAL_CONTROL_PPU_ENABLE;
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL, val);
+	if (err)
+		return err;
+
+	return mv88e6185_g1_wait_ppu_disabled(chip);
+}
+
+/* Offset 0x1a: Monitor Control */
+/* Offset 0x1a: Monitor & MGMT Control on some devices */
+
+int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~(GLOBAL_MONITOR_CONTROL_INGRESS_MASK |
+		 GLOBAL_MONITOR_CONTROL_EGRESS_MASK);
+
+	reg |= port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT |
+		port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT;
+
+	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
+}
+
+/* Older generations also call this the ARP destination. It has been
+ * generalized in more modern devices such that more than ARP can
+ * egress it
+ */
+int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_MONITOR_CONTROL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~GLOBAL_MONITOR_CONTROL_ARP_MASK;
+	reg |= port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT;
+
+	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
+}
+
+static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
+				      u16 pointer, u8 data)
+{
+	u16 reg;
+
+	reg = GLOBAL_MONITOR_CONTROL_UPDATE | pointer | data;
+
+	return mv88e6xxx_g1_write(chip, GLOBAL_MONITOR_CONTROL, reg);
+}
+
+int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
+{
+	int err;
+
+	err = mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_INGRESS,
+					 port);
+	if (err)
+		return err;
+
+	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_EGRESS,
+					  port);
+}
+
+int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
+{
+	return mv88e6390_g1_monitor_write(chip, GLOBAL_MONITOR_CONTROL_CPU_DEST,
+					  port);
+}
+
+int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+	int err;
+
+	/* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
+	err = mv88e6390_g1_monitor_write(
+		chip, GLOBAL_MONITOR_CONTROL_0180C280000000XLO, 0xff);
+	if (err)
+		return err;
+
+	/* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
+	err = mv88e6390_g1_monitor_write(
+		chip, GLOBAL_MONITOR_CONTROL_0180C280000000XHI, 0xff);
+	if (err)
+		return err;
+
+	/* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
+	err = mv88e6390_g1_monitor_write(
+		chip, GLOBAL_MONITOR_CONTROL_0180C280000002XLO, 0xff);
+	if (err)
+		return err;
+
+	/* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
+	return mv88e6390_g1_monitor_write(
+		chip, GLOBAL_MONITOR_CONTROL_0180C280000002XHI, 0xff);
+}
+
+/* Offset 0x1c: Global Control 2 */
+
+int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
+{
+	u16 val;
+	int err;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
+	if (err)
+		return err;
+
+	val |= GLOBAL_CONTROL_2_HIST_RX_TX;
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
+
+	return err;
+}
+
+/* Offset 0x1d: Statistics Operation 2 */
+
+int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
+{
+	return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
+}
+
+int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+	int err;
+
+	/* Snapshot the hardware statistics counters for this port. */
+	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+				 GLOBAL_STATS_OP_CAPTURE_PORT |
+				 GLOBAL_STATS_OP_HIST_RX_TX | port);
+	if (err)
+		return err;
+
+	/* Wait for the snapshotting to complete. */
+	return mv88e6xxx_g1_stats_wait(chip);
+}
+
+int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+	port = (port + 1) << 5;
+
+	return mv88e6xxx_g1_stats_snapshot(chip, port);
+}
+
+int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+	int err;
+
+	port = (port + 1) << 5;
+
+	/* Snapshot the hardware statistics counters for this port. */
+	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+				 GLOBAL_STATS_OP_CAPTURE_PORT | port);
+	if (err)
+		return err;
+
+	/* Wait for the snapshotting to complete. */
+	return mv88e6xxx_g1_stats_wait(chip);
+}
+
+void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
+{
+	u32 value;
+	u16 reg;
+	int err;
+
+	*val = 0;
+
+	err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+				 GLOBAL_STATS_OP_READ_CAPTURED | stat);
+	if (err)
+		return;
+
+	err = mv88e6xxx_g1_stats_wait(chip);
+	if (err)
+		return;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
+	if (err)
+		return;
+
+	value = reg << 16;
+
+	err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
+	if (err)
+		return;
+
+	*val = value | reg;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global1.h linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global1.h
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global1.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global1.h	2017-02-12 16:03:20.000000000 -0500
@@ -20,4 +20,22 @@ int mv88e6xxx_g1_read(struct mv88e6xxx_c
 int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
 int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
 
+int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
+int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
+
+int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
+int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
+
+int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val);
+int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
+
 #endif /* _MV88E6XXX_GLOBAL1_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global2.c linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global2.c
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global2.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,5 +1,6 @@
 /*
- * Marvell 88E6xxx Switch Global 2 Registers support (device address 0x1C)
+ * Marvell 88E6xxx Switch Global 2 Registers support (device address
+ * 0x1C)
  *
  * Copyright (c) 2008 Marvell Semiconductor
  *
@@ -11,6 +12,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/irqdomain.h>
 #include "mv88e6xxx.h"
 #include "global2.h"
 
@@ -36,6 +38,31 @@ static int mv88e6xxx_g2_wait(struct mv88
 	return mv88e6xxx_wait(chip, ADDR_GLOBAL2, reg, mask);
 }
 
+/* Offset 0x02: Management Enable 2x */
+/* Offset 0x03: Management Enable 0x */
+
+int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+	int err;
+
+	/* Consider the frames with reserved multicast destination
+	 * addresses matching 01:80:c2:00:00:2x as MGMT.
+	 */
+	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
+		err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
+		if (err)
+			return err;
+	}
+
+	/* Consider the frames with reserved multicast destination
+	 * addresses matching 01:80:c2:00:00:0x as MGMT.
+	 */
+	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X))
+		return mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
+
+	return 0;
+}
+
 /* Offset 0x06: Device Mapping Table register */
 
 static int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip,
@@ -417,29 +444,154 @@ int mv88e6xxx_g2_smi_phy_write(struct mv
 	return mv88e6xxx_g2_smi_phy_cmd(chip, cmd);
 }
 
-int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
+static void mv88e6xxx_g2_irq_mask(struct irq_data *d)
 {
-	u16 reg;
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int n = d->hwirq;
+
+	chip->g2_irq.masked |= (1 << n);
+}
+
+static void mv88e6xxx_g2_irq_unmask(struct irq_data *d)
+{
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int n = d->hwirq;
+
+	chip->g2_irq.masked &= ~(1 << n);
+}
+
+static irqreturn_t mv88e6xxx_g2_irq_thread_fn(int irq, void *dev_id)
+{
+	struct mv88e6xxx_chip *chip = dev_id;
+	unsigned int nhandled = 0;
+	unsigned int sub_irq;
+	unsigned int n;
 	int err;
+	u16 reg;
 
-	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_2X)) {
-		/* Consider the frames with reserved multicast destination
-		 * addresses matching 01:80:c2:00:00:2x as MGMT.
-		 */
-		err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_2X, 0xffff);
-		if (err)
-			return err;
+	mutex_lock(&chip->reg_lock);
+	err = mv88e6xxx_g2_read(chip, GLOBAL2_INT_SOURCE, &reg);
+	mutex_unlock(&chip->reg_lock);
+	if (err)
+		goto out;
+
+	for (n = 0; n < 16; ++n) {
+		if (reg & (1 << n)) {
+			sub_irq = irq_find_mapping(chip->g2_irq.domain, n);
+			handle_nested_irq(sub_irq);
+			++nhandled;
+		}
 	}
+out:
+	return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
+}
 
-	if (mv88e6xxx_has(chip, MV88E6XXX_FLAG_G2_MGMT_EN_0X)) {
-		/* Consider the frames with reserved multicast destination
-		 * addresses matching 01:80:c2:00:00:0x as MGMT.
-		 */
-		err = mv88e6xxx_g2_write(chip, GLOBAL2_MGMT_EN_0X, 0xffff);
-		if (err)
-			return err;
+static void mv88e6xxx_g2_irq_bus_lock(struct irq_data *d)
+{
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+	mutex_lock(&chip->reg_lock);
+}
+
+static void mv88e6xxx_g2_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct mv88e6xxx_chip *chip = irq_data_get_irq_chip_data(d);
+
+	mv88e6xxx_g2_write(chip, GLOBAL2_INT_MASK, ~chip->g2_irq.masked);
+
+	mutex_unlock(&chip->reg_lock);
+}
+
+static struct irq_chip mv88e6xxx_g2_irq_chip = {
+	.name			= "mv88e6xxx-g2",
+	.irq_mask		= mv88e6xxx_g2_irq_mask,
+	.irq_unmask		= mv88e6xxx_g2_irq_unmask,
+	.irq_bus_lock		= mv88e6xxx_g2_irq_bus_lock,
+	.irq_bus_sync_unlock	= mv88e6xxx_g2_irq_bus_sync_unlock,
+};
+
+static int mv88e6xxx_g2_irq_domain_map(struct irq_domain *d,
+				       unsigned int irq,
+				       irq_hw_number_t hwirq)
+{
+	struct mv88e6xxx_chip *chip = d->host_data;
+
+	irq_set_chip_data(irq, d->host_data);
+	irq_set_chip_and_handler(irq, &chip->g2_irq.chip, handle_level_irq);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops mv88e6xxx_g2_irq_domain_ops = {
+	.map	= mv88e6xxx_g2_irq_domain_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
+void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
+{
+	int irq, virq;
+
+	free_irq(chip->device_irq, chip);
+	irq_dispose_mapping(chip->device_irq);
+
+	for (irq = 0; irq < 16; irq++) {
+		virq = irq_find_mapping(chip->g2_irq.domain, irq);
+		irq_dispose_mapping(virq);
 	}
 
+	irq_domain_remove(chip->g2_irq.domain);
+}
+
+int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+{
+	int err, irq, virq;
+
+	if (!chip->dev->of_node)
+		return -EINVAL;
+
+	chip->g2_irq.domain = irq_domain_add_simple(
+		chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
+	if (!chip->g2_irq.domain)
+		return -ENOMEM;
+
+	for (irq = 0; irq < 16; irq++)
+		irq_create_mapping(chip->g2_irq.domain, irq);
+
+	chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
+	chip->g2_irq.masked = ~0;
+
+	chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
+					    GLOBAL_STATUS_IRQ_DEVICE);
+	if (chip->device_irq < 0) {
+		err = chip->device_irq;
+		goto out;
+	}
+
+	err = request_threaded_irq(chip->device_irq, NULL,
+				   mv88e6xxx_g2_irq_thread_fn,
+				   IRQF_ONESHOT, "mv88e6xxx-g1", chip);
+	if (err)
+		goto out;
+
+	return 0;
+
+out:
+	for (irq = 0; irq < 16; irq++) {
+		virq = irq_find_mapping(chip->g2_irq.domain, irq);
+		irq_dispose_mapping(virq);
+	}
+
+	irq_domain_remove(chip->g2_irq.domain);
+
+	return err;
+}
+
+int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip)
+{
+	u16 reg;
+	int err;
+
 	/* Ignore removed tag data on doubly tagged packets, disable
 	 * flow control messages, force flow control priority to the
 	 * highest, and send all special multicast frames to the CPU
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global2.h linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global2.h
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/global2.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/global2.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,6 +33,9 @@ int mv88e6xxx_g2_get_eeprom16(struct mv8
 int mv88e6xxx_g2_set_eeprom16(struct mv88e6xxx_chip *chip,
 			      struct ethtool_eeprom *eeprom, u8 *data);
 int mv88e6xxx_g2_setup(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip);
+int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip);
 
 #else /* !CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
 
@@ -82,6 +85,20 @@ static inline int mv88e6xxx_g2_setup(str
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void mv88e6xxx_g2_irq_free(struct mv88e6xxx_chip *chip)
+{
+}
+
+static inline int mv88e6095_g2_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
+{
+	return -EOPNOTSUPP;
+}
 
 #endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/Kconfig
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,7 @@
 config NET_DSA_MV88E6XXX
 	tristate "Marvell 88E6xxx Ethernet switch fabric support"
 	depends on NET_DSA
+	select IRQ_DOMAIN
 	select NET_DSA_TAG_EDSA
 	select NET_DSA_TAG_DSA
 	help
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/Makefile linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/Makefile
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,3 +2,4 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e
 mv88e6xxx-objs := chip.o
 mv88e6xxx-objs += global1.o
 mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o
+mv88e6xxx-objs += port.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h	2017-02-12 16:03:20.000000000 -0500
@@ -13,6 +13,7 @@
 #define __MV88E6XXX_H
 
 #include <linux/if_vlan.h>
+#include <linux/irq.h>
 #include <linux/gpio/consumer.h>
 
 #ifndef UINT64_MAX
@@ -60,20 +61,29 @@
 #define PORT_PCS_CTRL		0x01
 #define PORT_PCS_CTRL_RGMII_DELAY_RXCLK	BIT(15)
 #define PORT_PCS_CTRL_RGMII_DELAY_TXCLK	BIT(14)
+#define PORT_PCS_CTRL_FORCE_SPEED	BIT(13) /* 6390 */
+#define PORT_PCS_CTRL_ALTSPEED		BIT(12) /* 6390 */
+#define PORT_PCS_CTRL_200BASE		BIT(12) /* 6352 */
 #define PORT_PCS_CTRL_FC		BIT(7)
 #define PORT_PCS_CTRL_FORCE_FC		BIT(6)
 #define PORT_PCS_CTRL_LINK_UP		BIT(5)
 #define PORT_PCS_CTRL_FORCE_LINK	BIT(4)
 #define PORT_PCS_CTRL_DUPLEX_FULL	BIT(3)
 #define PORT_PCS_CTRL_FORCE_DUPLEX	BIT(2)
-#define PORT_PCS_CTRL_10		0x00
-#define PORT_PCS_CTRL_100		0x01
-#define PORT_PCS_CTRL_1000		0x02
-#define PORT_PCS_CTRL_UNFORCED		0x03
+#define PORT_PCS_CTRL_SPEED_MASK	(0x03)
+#define PORT_PCS_CTRL_SPEED_10		(0x00)
+#define PORT_PCS_CTRL_SPEED_100		(0x01)
+#define PORT_PCS_CTRL_SPEED_200		(0x02) /* 6065 and non Gb chips */
+#define PORT_PCS_CTRL_SPEED_1000	(0x02)
+#define PORT_PCS_CTRL_SPEED_10000	(0x03) /* 6390X */
+#define PORT_PCS_CTRL_SPEED_UNFORCED	(0x03)
 #define PORT_PAUSE_CTRL		0x02
+#define PORT_FLOW_CTRL_LIMIT_IN		((0x00 << 8) | BIT(15))
+#define PORT_FLOW_CTRL_LIMIT_OUT	((0x01 << 8) | BIT(15))
 #define PORT_SWITCH_ID		0x03
 #define PORT_SWITCH_ID_PROD_NUM_6085	0x04a
 #define PORT_SWITCH_ID_PROD_NUM_6095	0x095
+#define PORT_SWITCH_ID_PROD_NUM_6097	0x099
 #define PORT_SWITCH_ID_PROD_NUM_6131	0x106
 #define PORT_SWITCH_ID_PROD_NUM_6320	0x115
 #define PORT_SWITCH_ID_PROD_NUM_6123	0x121
@@ -84,11 +94,17 @@
 #define PORT_SWITCH_ID_PROD_NUM_6175	0x175
 #define PORT_SWITCH_ID_PROD_NUM_6176	0x176
 #define PORT_SWITCH_ID_PROD_NUM_6185	0x1a7
+#define PORT_SWITCH_ID_PROD_NUM_6190	0x190
+#define PORT_SWITCH_ID_PROD_NUM_6190X	0x0a0
+#define PORT_SWITCH_ID_PROD_NUM_6191	0x191
 #define PORT_SWITCH_ID_PROD_NUM_6240	0x240
+#define PORT_SWITCH_ID_PROD_NUM_6290	0x290
 #define PORT_SWITCH_ID_PROD_NUM_6321	0x310
 #define PORT_SWITCH_ID_PROD_NUM_6352	0x352
 #define PORT_SWITCH_ID_PROD_NUM_6350	0x371
 #define PORT_SWITCH_ID_PROD_NUM_6351	0x375
+#define PORT_SWITCH_ID_PROD_NUM_6390	0x390
+#define PORT_SWITCH_ID_PROD_NUM_6390X	0x0a1
 #define PORT_CONTROL		0x04
 #define PORT_CONTROL_USE_CORE_TAG	BIT(15)
 #define PORT_CONTROL_DROP_ON_LOCK	BIT(14)
@@ -96,6 +112,7 @@
 #define PORT_CONTROL_EGRESS_UNTAGGED	(0x1 << 12)
 #define PORT_CONTROL_EGRESS_TAGGED	(0x2 << 12)
 #define PORT_CONTROL_EGRESS_ADD_TAG	(0x3 << 12)
+#define PORT_CONTROL_EGRESS_MASK	(0x3 << 12)
 #define PORT_CONTROL_HEADER		BIT(11)
 #define PORT_CONTROL_IGMP_MLD_SNOOP	BIT(10)
 #define PORT_CONTROL_DOUBLE_TAG		BIT(9)
@@ -103,6 +120,7 @@
 #define PORT_CONTROL_FRAME_MODE_DSA		(0x1 << 8)
 #define PORT_CONTROL_FRAME_MODE_PROVIDER	(0x2 << 8)
 #define PORT_CONTROL_FRAME_ETHER_TYPE_DSA	(0x3 << 8)
+#define PORT_CONTROL_FRAME_MASK			(0x3 << 8)
 #define PORT_CONTROL_DSA_TAG		BIT(8)
 #define PORT_CONTROL_VLAN_TUNNEL	BIT(7)
 #define PORT_CONTROL_TAG_IF_BOTH	BIT(6)
@@ -110,6 +128,10 @@
 #define PORT_CONTROL_USE_TAG		BIT(4)
 #define PORT_CONTROL_FORWARD_UNKNOWN_MC	BIT(3)
 #define PORT_CONTROL_FORWARD_UNKNOWN	BIT(2)
+#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_DA		(0x0 << 2)
+#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_MULTICAST_DA	(0x1 << 2)
+#define PORT_CONTROL_NOT_EGRESS_UNKNOWN_UNITCAST_DA	(0x2 << 2)
+#define PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA		(0x3 << 2)
 #define PORT_CONTROL_STATE_MASK		0x03
 #define PORT_CONTROL_STATE_DISABLED	0x00
 #define PORT_CONTROL_STATE_BLOCKING	0x01
@@ -158,15 +180,34 @@
 #define PORT_OUT_FILTERED	0x13
 #define PORT_TAG_REGMAP_0123	0x18
 #define PORT_TAG_REGMAP_4567	0x19
+#define PORT_IEEE_PRIO_MAP_TABLE	0x18    /* 6390 */
+#define PORT_IEEE_PRIO_MAP_TABLE_UPDATE		BIT(15)
+#define PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP		(0x0 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP	(0x1 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP	(0x2 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP		(0x3 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP	(0x5 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP	(0x6 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP	(0x7 << 12)
+#define PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT		9
 
 #define GLOBAL_STATUS		0x00
 #define GLOBAL_STATUS_PPU_STATE BIT(15) /* 6351 and 6171 */
-/* Two bits for 6165, 6185 etc */
-#define GLOBAL_STATUS_PPU_MASK		(0x3 << 14)
-#define GLOBAL_STATUS_PPU_DISABLED_RST	(0x0 << 14)
-#define GLOBAL_STATUS_PPU_INITIALIZING	(0x1 << 14)
-#define GLOBAL_STATUS_PPU_DISABLED	(0x2 << 14)
-#define GLOBAL_STATUS_PPU_POLLING	(0x3 << 14)
+#define GLOBAL_STATUS_PPU_STATE_MASK		(0x3 << 14) /* 6165 6185 */
+#define GLOBAL_STATUS_PPU_STATE_DISABLED_RST	(0x0 << 14)
+#define GLOBAL_STATUS_PPU_STATE_INITIALIZING	(0x1 << 14)
+#define GLOBAL_STATUS_PPU_STATE_DISABLED	(0x2 << 14)
+#define GLOBAL_STATUS_PPU_STATE_POLLING		(0x3 << 14)
+#define GLOBAL_STATUS_INIT_READY	BIT(11)
+#define GLOBAL_STATUS_IRQ_AVB		8
+#define GLOBAL_STATUS_IRQ_DEVICE	7
+#define GLOBAL_STATUS_IRQ_STATS		6
+#define GLOBAL_STATUS_IRQ_VTU_PROBLEM	5
+#define GLOBAL_STATUS_IRQ_VTU_DONE	4
+#define GLOBAL_STATUS_IRQ_ATU_PROBLEM	3
+#define GLOBAL_STATUS_IRQ_ATU_DONE	2
+#define GLOBAL_STATUS_IRQ_TCAM_DONE	1
+#define GLOBAL_STATUS_IRQ_EEPROM_DONE	0
 #define GLOBAL_MAC_01		0x01
 #define GLOBAL_MAC_23		0x02
 #define GLOBAL_MAC_45		0x03
@@ -254,14 +295,27 @@
 #define GLOBAL_CORE_TAG_TYPE	0x19
 #define GLOBAL_MONITOR_CONTROL	0x1a
 #define GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT	12
+#define GLOBAL_MONITOR_CONTROL_INGRESS_MASK	(0xf << 12)
 #define GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT	8
+#define GLOBAL_MONITOR_CONTROL_EGRESS_MASK	(0xf << 8)
 #define GLOBAL_MONITOR_CONTROL_ARP_SHIFT	4
+#define GLOBAL_MONITOR_CONTROL_ARP_MASK	        (0xf << 4)
 #define GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT	0
 #define GLOBAL_MONITOR_CONTROL_ARP_DISABLED	(0xf0)
+#define GLOBAL_MONITOR_CONTROL_UPDATE			BIT(15)
+#define GLOBAL_MONITOR_CONTROL_0180C280000000XLO	(0x00 << 8)
+#define GLOBAL_MONITOR_CONTROL_0180C280000000XHI	(0x01 << 8)
+#define GLOBAL_MONITOR_CONTROL_0180C280000002XLO	(0x02 << 8)
+#define GLOBAL_MONITOR_CONTROL_0180C280000002XHI	(0x03 << 8)
+#define GLOBAL_MONITOR_CONTROL_INGRESS			(0x20 << 8)
+#define GLOBAL_MONITOR_CONTROL_EGRESS			(0x21 << 8)
+#define GLOBAL_MONITOR_CONTROL_CPU_DEST			(0x30 << 8)
 #define GLOBAL_CONTROL_2	0x1c
 #define GLOBAL_CONTROL_2_NO_CASCADE		0xe000
 #define GLOBAL_CONTROL_2_MULTIPLE_CASCADE	0xf000
-
+#define GLOBAL_CONTROL_2_HIST_RX	       (0x1 << 6)
+#define GLOBAL_CONTROL_2_HIST_TX	       (0x2 << 6)
+#define GLOBAL_CONTROL_2_HIST_RX_TX	       (0x3 << 6)
 #define GLOBAL_STATS_OP		0x1d
 #define GLOBAL_STATS_OP_BUSY	BIT(15)
 #define GLOBAL_STATS_OP_NOP		(0 << 12)
@@ -272,7 +326,8 @@
 #define GLOBAL_STATS_OP_HIST_RX		((1 << 10) | GLOBAL_STATS_OP_BUSY)
 #define GLOBAL_STATS_OP_HIST_TX		((2 << 10) | GLOBAL_STATS_OP_BUSY)
 #define GLOBAL_STATS_OP_HIST_RX_TX	((3 << 10) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_BANK_1	BIT(9)
+#define GLOBAL_STATS_OP_BANK_1_BIT_9	BIT(9)
+#define GLOBAL_STATS_OP_BANK_1_BIT_10	BIT(10)
 #define GLOBAL_STATS_COUNTER_32	0x1e
 #define GLOBAL_STATS_COUNTER_01	0x1f
 
@@ -349,10 +404,18 @@
 
 #define MV88E6XXX_N_FID		4096
 
+enum mv88e6xxx_frame_mode {
+	MV88E6XXX_FRAME_MODE_NORMAL,
+	MV88E6XXX_FRAME_MODE_DSA,
+	MV88E6XXX_FRAME_MODE_PROVIDER,
+	MV88E6XXX_FRAME_MODE_ETHERTYPE,
+};
+
 /* List of supported models */
 enum mv88e6xxx_model {
 	MV88E6085,
 	MV88E6095,
+	MV88E6097,
 	MV88E6123,
 	MV88E6131,
 	MV88E6161,
@@ -362,12 +425,18 @@ enum mv88e6xxx_model {
 	MV88E6175,
 	MV88E6176,
 	MV88E6185,
+	MV88E6190,
+	MV88E6190X,
+	MV88E6191,
 	MV88E6240,
+	MV88E6290,
 	MV88E6320,
 	MV88E6321,
 	MV88E6350,
 	MV88E6351,
 	MV88E6352,
+	MV88E6390,
+	MV88E6390X,
 };
 
 enum mv88e6xxx_family {
@@ -380,15 +449,10 @@ enum mv88e6xxx_family {
 	MV88E6XXX_FAMILY_6320,	/* 6320 6321 */
 	MV88E6XXX_FAMILY_6351,	/* 6171 6175 6350 6351 */
 	MV88E6XXX_FAMILY_6352,	/* 6172 6176 6240 6352 */
+	MV88E6XXX_FAMILY_6390,  /* 6190 6190X 6191 6290 6390 6390X */
 };
 
 enum mv88e6xxx_cap {
-	/* Two different tag protocols can be used by the driver. All
-	 * switches support DSA, but only later generations support
-	 * EDSA.
-	 */
-	MV88E6XXX_CAP_EDSA,
-
 	/* Energy Efficient Ethernet.
 	 */
 	MV88E6XXX_CAP_EEE,
@@ -417,6 +481,7 @@ enum mv88e6xxx_cap {
 	 * The device contains a second set of global 16-bit registers.
 	 */
 	MV88E6XXX_CAP_GLOBAL2,
+	MV88E6XXX_CAP_G2_INT,		/* (0x00) Interrupt Status */
 	MV88E6XXX_CAP_G2_MGMT_EN_2X,	/* (0x02) MGMT Enable Register 2x */
 	MV88E6XXX_CAP_G2_MGMT_EN_0X,	/* (0x03) MGMT Enable Register 0x */
 	MV88E6XXX_CAP_G2_IRL_CMD,	/* (0x09) Ingress Rate Command */
@@ -425,12 +490,6 @@ enum mv88e6xxx_cap {
 	MV88E6XXX_CAP_G2_PVT_DATA,	/* (0x0c) Cross Chip Port VLAN Data */
 	MV88E6XXX_CAP_G2_POT,		/* (0x0f) Priority Override Table */
 
-	/* PHY Polling Unit.
-	 * See GLOBAL_CONTROL_PPU_ENABLE and GLOBAL_STATUS_PPU_POLLING.
-	 */
-	MV88E6XXX_CAP_PPU,
-	MV88E6XXX_CAP_PPU_ACTIVE,
-
 	/* Per VLAN Spanning Tree Unit (STU).
 	 * The Port State database, if present, is accessed through VTU
 	 * operations and dedicated SID registers. See GLOBAL_VTU_SID.
@@ -450,7 +509,6 @@ enum mv88e6xxx_cap {
 };
 
 /* Bitmask of capabilities */
-#define MV88E6XXX_FLAG_EDSA		BIT_ULL(MV88E6XXX_CAP_EDSA)
 #define MV88E6XXX_FLAG_EEE		BIT_ULL(MV88E6XXX_CAP_EEE)
 
 #define MV88E6XXX_FLAG_SMI_CMD		BIT_ULL(MV88E6XXX_CAP_SMI_CMD)
@@ -464,6 +522,7 @@ enum mv88e6xxx_cap {
 #define MV88E6XXX_FLAG_G1_VTU_FID	BIT_ULL(MV88E6XXX_CAP_G1_VTU_FID)
 
 #define MV88E6XXX_FLAG_GLOBAL2		BIT_ULL(MV88E6XXX_CAP_GLOBAL2)
+#define MV88E6XXX_FLAG_G2_INT		BIT_ULL(MV88E6XXX_CAP_G2_INT)
 #define MV88E6XXX_FLAG_G2_MGMT_EN_2X	BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_2X)
 #define MV88E6XXX_FLAG_G2_MGMT_EN_0X	BIT_ULL(MV88E6XXX_CAP_G2_MGMT_EN_0X)
 #define MV88E6XXX_FLAG_G2_IRL_CMD	BIT_ULL(MV88E6XXX_CAP_G2_IRL_CMD)
@@ -472,8 +531,6 @@ enum mv88e6xxx_cap {
 #define MV88E6XXX_FLAG_G2_PVT_DATA	BIT_ULL(MV88E6XXX_CAP_G2_PVT_DATA)
 #define MV88E6XXX_FLAG_G2_POT		BIT_ULL(MV88E6XXX_CAP_G2_POT)
 
-#define MV88E6XXX_FLAG_PPU		BIT_ULL(MV88E6XXX_CAP_PPU)
-#define MV88E6XXX_FLAG_PPU_ACTIVE	BIT_ULL(MV88E6XXX_CAP_PPU_ACTIVE)
 #define MV88E6XXX_FLAG_STU		BIT_ULL(MV88E6XXX_CAP_STU)
 #define MV88E6XXX_FLAG_TEMP		BIT_ULL(MV88E6XXX_CAP_TEMP)
 #define MV88E6XXX_FLAG_TEMP_LIMIT	BIT_ULL(MV88E6XXX_CAP_TEMP_LIMIT)
@@ -502,7 +559,6 @@ enum mv88e6xxx_cap {
 #define MV88E6XXX_FLAGS_FAMILY_6095	\
 	(MV88E6XXX_FLAG_GLOBAL2 |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_0X |	\
-	 MV88E6XXX_FLAG_PPU |		\
 	 MV88E6XXX_FLAG_VTU |		\
 	 MV88E6XXX_FLAGS_MULTI_CHIP)
 
@@ -513,7 +569,6 @@ enum mv88e6xxx_cap {
 	 MV88E6XXX_FLAG_G2_MGMT_EN_2X |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_0X |	\
 	 MV88E6XXX_FLAG_G2_POT |	\
-	 MV88E6XXX_FLAG_PPU |		\
 	 MV88E6XXX_FLAG_STU |		\
 	 MV88E6XXX_FLAG_VTU |		\
 	 MV88E6XXX_FLAGS_IRL |		\
@@ -524,6 +579,7 @@ enum mv88e6xxx_cap {
 	(MV88E6XXX_FLAG_G1_ATU_FID |	\
 	 MV88E6XXX_FLAG_G1_VTU_FID |	\
 	 MV88E6XXX_FLAG_GLOBAL2 |	\
+	 MV88E6XXX_FLAG_G2_INT |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_2X |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_0X |	\
 	 MV88E6XXX_FLAG_G2_POT |	\
@@ -536,19 +592,17 @@ enum mv88e6xxx_cap {
 
 #define MV88E6XXX_FLAGS_FAMILY_6185	\
 	(MV88E6XXX_FLAG_GLOBAL2 |	\
+	 MV88E6XXX_FLAG_G2_INT |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_0X |	\
 	 MV88E6XXX_FLAGS_MULTI_CHIP |	\
-	 MV88E6XXX_FLAG_PPU |		\
 	 MV88E6XXX_FLAG_VTU)
 
 #define MV88E6XXX_FLAGS_FAMILY_6320	\
-	(MV88E6XXX_FLAG_EDSA |		\
-	 MV88E6XXX_FLAG_EEE |		\
+	(MV88E6XXX_FLAG_EEE |		\
 	 MV88E6XXX_FLAG_GLOBAL2 |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_2X |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_0X |	\
 	 MV88E6XXX_FLAG_G2_POT |	\
-	 MV88E6XXX_FLAG_PPU_ACTIVE |	\
 	 MV88E6XXX_FLAG_TEMP |		\
 	 MV88E6XXX_FLAG_TEMP_LIMIT |	\
 	 MV88E6XXX_FLAG_VTU |		\
@@ -557,14 +611,13 @@ enum mv88e6xxx_cap {
 	 MV88E6XXX_FLAGS_PVT)
 
 #define MV88E6XXX_FLAGS_FAMILY_6351	\
-	(MV88E6XXX_FLAG_EDSA |		\
-	 MV88E6XXX_FLAG_G1_ATU_FID |	\
+	(MV88E6XXX_FLAG_G1_ATU_FID |	\
 	 MV88E6XXX_FLAG_G1_VTU_FID |	\
 	 MV88E6XXX_FLAG_GLOBAL2 |	\
+	 MV88E6XXX_FLAG_G2_INT |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_2X |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_0X |	\
 	 MV88E6XXX_FLAG_G2_POT |	\
-	 MV88E6XXX_FLAG_PPU_ACTIVE |	\
 	 MV88E6XXX_FLAG_STU |		\
 	 MV88E6XXX_FLAG_TEMP |		\
 	 MV88E6XXX_FLAG_VTU |		\
@@ -573,15 +626,14 @@ enum mv88e6xxx_cap {
 	 MV88E6XXX_FLAGS_PVT)
 
 #define MV88E6XXX_FLAGS_FAMILY_6352	\
-	(MV88E6XXX_FLAG_EDSA |		\
-	 MV88E6XXX_FLAG_EEE |		\
+	(MV88E6XXX_FLAG_EEE |		\
 	 MV88E6XXX_FLAG_G1_ATU_FID |	\
 	 MV88E6XXX_FLAG_G1_VTU_FID |	\
 	 MV88E6XXX_FLAG_GLOBAL2 |	\
+	 MV88E6XXX_FLAG_G2_INT |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_2X |	\
 	 MV88E6XXX_FLAG_G2_MGMT_EN_0X |	\
 	 MV88E6XXX_FLAG_G2_POT |	\
-	 MV88E6XXX_FLAG_PPU_ACTIVE |	\
 	 MV88E6XXX_FLAG_STU |		\
 	 MV88E6XXX_FLAG_TEMP |		\
 	 MV88E6XXX_FLAG_TEMP_LIMIT |	\
@@ -593,6 +645,17 @@ enum mv88e6xxx_cap {
 
 struct mv88e6xxx_ops;
 
+#define MV88E6XXX_FLAGS_FAMILY_6390	\
+	(MV88E6XXX_FLAG_EEE |		\
+	 MV88E6XXX_FLAG_GLOBAL2 |	\
+	 MV88E6XXX_FLAG_STU |		\
+	 MV88E6XXX_FLAG_TEMP |		\
+	 MV88E6XXX_FLAG_TEMP_LIMIT |	\
+	 MV88E6XXX_FLAG_VTU |		\
+	 MV88E6XXX_FLAGS_IRL |		\
+	 MV88E6XXX_FLAGS_MULTI_CHIP |	\
+	 MV88E6XXX_FLAGS_PVT)
+
 struct mv88e6xxx_info {
 	enum mv88e6xxx_family family;
 	u16 prod_num;
@@ -602,6 +665,8 @@ struct mv88e6xxx_info {
 	unsigned int port_base_addr;
 	unsigned int global1_addr;
 	unsigned int age_time_coeff;
+	unsigned int g1_irqs;
+	enum dsa_tag_protocol tag_protocol;
 	unsigned long long flags;
 	const struct mv88e6xxx_ops *ops;
 };
@@ -628,6 +693,13 @@ struct mv88e6xxx_priv_port {
 	struct net_device *bridge_dev;
 };
 
+struct mv88e6xxx_irq {
+	u16 masked;
+	struct irq_chip chip;
+	struct irq_domain *domain;
+	unsigned int nirqs;
+};
+
 struct mv88e6xxx_chip {
 	const struct mv88e6xxx_info *info;
 
@@ -677,6 +749,14 @@ struct mv88e6xxx_chip {
 
 	/* And the MDIO bus itself */
 	struct mii_bus *mdio_bus;
+
+	/* There can be two interrupt controllers, which are chained
+	 * off a GPIO as interrupt source
+	 */
+	struct mv88e6xxx_irq g1_irq;
+	struct mv88e6xxx_irq g2_irq;
+	int irq;
+	int device_irq;
 };
 
 struct mv88e6xxx_bus_ops {
@@ -696,19 +776,93 @@ struct mv88e6xxx_ops {
 			u16 *val);
 	int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg,
 			 u16 val);
-};
 
-enum stat_type {
-	BANK0,
-	BANK1,
-	PORT,
+	/* PHY Polling Unit (PPU) operations */
+	int (*ppu_enable)(struct mv88e6xxx_chip *chip);
+	int (*ppu_disable)(struct mv88e6xxx_chip *chip);
+
+	/* Switch Software Reset */
+	int (*reset)(struct mv88e6xxx_chip *chip);
+
+	/* RGMII Receive/Transmit Timing Control
+	 * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise.
+	 */
+	int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port,
+				    phy_interface_t mode);
+
+#define LINK_FORCED_DOWN	0
+#define LINK_FORCED_UP		1
+#define LINK_UNFORCED		-2
+
+	/* Port's MAC link state
+	 * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down,
+	 * or LINK_UNFORCED for normal link detection.
+	 */
+	int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link);
+
+#define DUPLEX_UNFORCED		-2
+
+	/* Port's MAC duplex mode
+	 *
+	 * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex,
+	 * or DUPLEX_UNFORCED for normal duplex detection.
+	 */
+	int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
+
+#define SPEED_MAX		INT_MAX
+#define SPEED_UNFORCED		-2
+
+	/* Port's MAC speed (in Mbps)
+	 *
+	 * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid.
+	 * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
+	 */
+	int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
+
+	int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port);
+
+	int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port,
+				   enum mv88e6xxx_frame_mode mode);
+	int (*port_set_egress_unknowns)(struct mv88e6xxx_chip *chip, int port,
+					bool on);
+	int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
+				   u16 etype);
+	int (*port_jumbo_config)(struct mv88e6xxx_chip *chip, int port);
+
+	int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
+	int (*port_pause_config)(struct mv88e6xxx_chip *chip, int port);
+
+	/* Snapshot the statistics for a port. The statistics can then
+	 * be read back a leisure but still with a consistent view.
+	 */
+	int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port);
+
+	/* Set the histogram mode for statistics, when the control registers
+	 * are separated out of the STATS_OP register.
+	 */
+	int (*stats_set_histogram)(struct mv88e6xxx_chip *chip);
+
+	/* Return the number of strings describing statistics */
+	int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
+	void (*stats_get_strings)(struct mv88e6xxx_chip *chip,  uint8_t *data);
+	void (*stats_get_stats)(struct mv88e6xxx_chip *chip,  int port,
+				uint64_t *data);
+	int (*g1_set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
+	int (*g1_set_egress_port)(struct mv88e6xxx_chip *chip, int port);
+
+	/* Can be either in g1 or g2, so don't use a prefix */
+	int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
 };
 
+#define STATS_TYPE_PORT		BIT(0)
+#define STATS_TYPE_BANK0	BIT(1)
+#define STATS_TYPE_BANK1	BIT(2)
+
 struct mv88e6xxx_hw_stat {
 	char string[ETH_GSTRING_LEN];
 	int sizeof_stat;
 	int reg;
-	enum stat_type type;
+	int type;
 };
 
 static inline bool mv88e6xxx_has(struct mv88e6xxx_chip *chip,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/port.c linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/port.c
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/port.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/port.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,729 @@
+/*
+ * Marvell 88E6xxx Switch Port Registers support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.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 "mv88e6xxx.h"
+#include "port.h"
+
+int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
+			u16 *val)
+{
+	int addr = chip->info->port_base_addr + port;
+
+	return mv88e6xxx_read(chip, addr, reg, val);
+}
+
+int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
+			 u16 val)
+{
+	int addr = chip->info->port_base_addr + port;
+
+	return mv88e6xxx_write(chip, addr, reg, val);
+}
+
+/* Offset 0x01: MAC (or PCS or Physical) Control Register
+ *
+ * Link, Duplex and Flow Control have one force bit, one value bit.
+ *
+ * For port's MAC speed, ForceSpd (or SpdValue) bits 1:0 program the value.
+ * Alternative values require the 200BASE (or AltSpeed) bit 12 set.
+ * Newer chips need a ForcedSpd bit 13 set to consider the value.
+ */
+
+static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+					  phy_interface_t mode)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
+		 PORT_PCS_CTRL_RGMII_DELAY_TXCLK);
+
+	switch (mode) {
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+		reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK;
+		break;
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
+		break;
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK |
+			PORT_PCS_CTRL_RGMII_DELAY_TXCLK;
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+		break;
+	default:
+		return 0;
+	}
+
+	err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+	if (err)
+		return err;
+
+	netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n",
+		   reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no",
+		   reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no");
+
+	return 0;
+}
+
+int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+				   phy_interface_t mode)
+{
+	if (port < 5)
+		return -EOPNOTSUPP;
+
+	return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
+}
+
+int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+				   phy_interface_t mode)
+{
+	if (port != 0)
+		return -EOPNOTSUPP;
+
+	return mv88e6xxx_port_set_rgmii_delay(chip, port, mode);
+}
+
+int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~(PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP);
+
+	switch (link) {
+	case LINK_FORCED_DOWN:
+		reg |= PORT_PCS_CTRL_FORCE_LINK;
+		break;
+	case LINK_FORCED_UP:
+		reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP;
+		break;
+	case LINK_UNFORCED:
+		/* normal link detection */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+	if (err)
+		return err;
+
+	netdev_dbg(chip->ds->ports[port].netdev, "%s link %s\n",
+		   reg & PORT_PCS_CTRL_FORCE_LINK ? "Force" : "Unforce",
+		   reg & PORT_PCS_CTRL_LINK_UP ? "up" : "down");
+
+	return 0;
+}
+
+int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~(PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL);
+
+	switch (dup) {
+	case DUPLEX_HALF:
+		reg |= PORT_PCS_CTRL_FORCE_DUPLEX;
+		break;
+	case DUPLEX_FULL:
+		reg |= PORT_PCS_CTRL_FORCE_DUPLEX | PORT_PCS_CTRL_DUPLEX_FULL;
+		break;
+	case DUPLEX_UNFORCED:
+		/* normal duplex detection */
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+	if (err)
+		return err;
+
+	netdev_dbg(chip->ds->ports[port].netdev, "%s %s duplex\n",
+		   reg & PORT_PCS_CTRL_FORCE_DUPLEX ? "Force" : "Unforce",
+		   reg & PORT_PCS_CTRL_DUPLEX_FULL ? "full" : "half");
+
+	return 0;
+}
+
+static int mv88e6xxx_port_set_speed(struct mv88e6xxx_chip *chip, int port,
+				    int speed, bool alt_bit, bool force_bit)
+{
+	u16 reg, ctrl;
+	int err;
+
+	switch (speed) {
+	case 10:
+		ctrl = PORT_PCS_CTRL_SPEED_10;
+		break;
+	case 100:
+		ctrl = PORT_PCS_CTRL_SPEED_100;
+		break;
+	case 200:
+		if (alt_bit)
+			ctrl = PORT_PCS_CTRL_SPEED_100 | PORT_PCS_CTRL_ALTSPEED;
+		else
+			ctrl = PORT_PCS_CTRL_SPEED_200;
+		break;
+	case 1000:
+		ctrl = PORT_PCS_CTRL_SPEED_1000;
+		break;
+	case 2500:
+		ctrl = PORT_PCS_CTRL_SPEED_1000 | PORT_PCS_CTRL_ALTSPEED;
+		break;
+	case 10000:
+		/* all bits set, fall through... */
+	case SPEED_UNFORCED:
+		ctrl = PORT_PCS_CTRL_SPEED_UNFORCED;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~PORT_PCS_CTRL_SPEED_MASK;
+	if (alt_bit)
+		reg &= ~PORT_PCS_CTRL_ALTSPEED;
+	if (force_bit) {
+		reg &= ~PORT_PCS_CTRL_FORCE_SPEED;
+		if (speed != SPEED_UNFORCED)
+			ctrl |= PORT_PCS_CTRL_FORCE_SPEED;
+	}
+	reg |= ctrl;
+
+	err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg);
+	if (err)
+		return err;
+
+	if (speed)
+		netdev_dbg(chip->ds->ports[port].netdev,
+			   "Speed set to %d Mbps\n", speed);
+	else
+		netdev_dbg(chip->ds->ports[port].netdev, "Speed unforced\n");
+
+	return 0;
+}
+
+/* Support 10, 100, 200 Mbps (e.g. 88E6065 family) */
+int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+	if (speed == SPEED_MAX)
+		speed = 200;
+
+	if (speed > 200)
+		return -EOPNOTSUPP;
+
+	/* Setting 200 Mbps on port 0 to 3 selects 100 Mbps */
+	return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
+}
+
+/* Support 10, 100, 1000 Mbps (e.g. 88E6185 family) */
+int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+	if (speed == SPEED_MAX)
+		speed = 1000;
+
+	if (speed == 200 || speed > 1000)
+		return -EOPNOTSUPP;
+
+	return mv88e6xxx_port_set_speed(chip, port, speed, false, false);
+}
+
+/* Support 10, 100, 200, 1000 Mbps (e.g. 88E6352 family) */
+int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+	if (speed == SPEED_MAX)
+		speed = 1000;
+
+	if (speed > 1000)
+		return -EOPNOTSUPP;
+
+	if (speed == 200 && port < 5)
+		return -EOPNOTSUPP;
+
+	return mv88e6xxx_port_set_speed(chip, port, speed, true, false);
+}
+
+/* Support 10, 100, 200, 1000, 2500 Mbps (e.g. 88E6390) */
+int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+	if (speed == SPEED_MAX)
+		speed = port < 9 ? 1000 : 2500;
+
+	if (speed > 2500)
+		return -EOPNOTSUPP;
+
+	if (speed == 200 && port != 0)
+		return -EOPNOTSUPP;
+
+	if (speed == 2500 && port < 9)
+		return -EOPNOTSUPP;
+
+	return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
+}
+
+/* Support 10, 100, 200, 1000, 2500, 10000 Mbps (e.g. 88E6190X) */
+int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed)
+{
+	if (speed == SPEED_MAX)
+		speed = port < 9 ? 1000 : 10000;
+
+	if (speed == 200 && port != 0)
+		return -EOPNOTSUPP;
+
+	if (speed >= 2500 && port < 9)
+		return -EOPNOTSUPP;
+
+	return mv88e6xxx_port_set_speed(chip, port, speed, true, true);
+}
+
+/* Offset 0x02: Pause Control
+ *
+ * Do not limit the period of time that this port can be paused for by
+ * the remote end or the period of time that this port can pause the
+ * remote end.
+ */
+int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port)
+{
+	return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL, 0x0000);
+}
+
+int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port)
+{
+	int err;
+
+	err = mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
+				   PORT_FLOW_CTRL_LIMIT_IN | 0);
+	if (err)
+		return err;
+
+	return mv88e6xxx_port_write(chip, port, PORT_PAUSE_CTRL,
+				    PORT_FLOW_CTRL_LIMIT_OUT | 0);
+}
+
+/* Offset 0x04: Port Control Register */
+
+static const char * const mv88e6xxx_port_state_names[] = {
+	[PORT_CONTROL_STATE_DISABLED] = "Disabled",
+	[PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening",
+	[PORT_CONTROL_STATE_LEARNING] = "Learning",
+	[PORT_CONTROL_STATE_FORWARDING] = "Forwarding",
+};
+
+int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~PORT_CONTROL_STATE_MASK;
+	reg |= state;
+
+	err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+	if (err)
+		return err;
+
+	netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n",
+		   mv88e6xxx_port_state_names[state]);
+
+	return 0;
+}
+
+int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
+				   u16 mode)
+{
+	int err;
+	u16 reg;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~PORT_CONTROL_EGRESS_MASK;
+	reg |= mode;
+
+	return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+				  enum mv88e6xxx_frame_mode mode)
+{
+	int err;
+	u16 reg;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~PORT_CONTROL_FRAME_MODE_DSA;
+
+	switch (mode) {
+	case MV88E6XXX_FRAME_MODE_NORMAL:
+		reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
+		break;
+	case MV88E6XXX_FRAME_MODE_DSA:
+		reg |= PORT_CONTROL_FRAME_MODE_DSA;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+				  enum mv88e6xxx_frame_mode mode)
+{
+	int err;
+	u16 reg;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~PORT_CONTROL_FRAME_MASK;
+
+	switch (mode) {
+	case MV88E6XXX_FRAME_MODE_NORMAL:
+		reg |= PORT_CONTROL_FRAME_MODE_NORMAL;
+		break;
+	case MV88E6XXX_FRAME_MODE_DSA:
+		reg |= PORT_CONTROL_FRAME_MODE_DSA;
+		break;
+	case MV88E6XXX_FRAME_MODE_PROVIDER:
+		reg |= PORT_CONTROL_FRAME_MODE_PROVIDER;
+		break;
+	case MV88E6XXX_FRAME_MODE_ETHERTYPE:
+		reg |= PORT_CONTROL_FRAME_ETHER_TYPE_DSA;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+				       bool on)
+{
+	int err;
+	u16 reg;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+	if (err)
+		return err;
+
+	if (on)
+		reg |= PORT_CONTROL_FORWARD_UNKNOWN;
+	else
+		reg &= ~PORT_CONTROL_FORWARD_UNKNOWN;
+
+	return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+				       bool on)
+{
+	int err;
+	u16 reg;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, &reg);
+	if (err)
+		return err;
+
+	if (on)
+		reg |= PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
+	else
+		reg &= ~PORT_CONTROL_EGRESS_ALL_UNKNOWN_DA;
+
+	return mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg);
+}
+
+/* Offset 0x05: Port Control 1 */
+
+/* Offset 0x06: Port Based VLAN Map */
+
+int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map)
+{
+	const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+	if (err)
+		return err;
+
+	reg &= ~mask;
+	reg |= map & mask;
+
+	err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+	if (err)
+		return err;
+
+	netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n",
+		   map);
+
+	return 0;
+}
+
+int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid)
+{
+	const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
+	u16 reg;
+	int err;
+
+	/* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
+	err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+	if (err)
+		return err;
+
+	*fid = (reg & 0xf000) >> 12;
+
+	/* Port's default FID upper bits are located in reg 0x05, offset 0 */
+	if (upper_mask) {
+		err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
+		if (err)
+			return err;
+
+		*fid |= (reg & upper_mask) << 4;
+	}
+
+	return 0;
+}
+
+int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid)
+{
+	const u16 upper_mask = (mv88e6xxx_num_databases(chip) - 1) >> 4;
+	u16 reg;
+	int err;
+
+	if (fid >= mv88e6xxx_num_databases(chip))
+		return -EINVAL;
+
+	/* Port's default FID lower 4 bits are located in reg 0x06, offset 12 */
+	err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, &reg);
+	if (err)
+		return err;
+
+	reg &= 0x0fff;
+	reg |= (fid & 0x000f) << 12;
+
+	err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg);
+	if (err)
+		return err;
+
+	/* Port's default FID upper bits are located in reg 0x05, offset 0 */
+	if (upper_mask) {
+		err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, &reg);
+		if (err)
+			return err;
+
+		reg &= ~upper_mask;
+		reg |= (fid >> 4) & upper_mask;
+
+		err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg);
+		if (err)
+			return err;
+	}
+
+	netdev_dbg(chip->ds->ports[port].netdev, "FID set to %u\n", fid);
+
+	return 0;
+}
+
+/* Offset 0x07: Default Port VLAN ID & Priority */
+
+int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
+	if (err)
+		return err;
+
+	*pvid = reg & PORT_DEFAULT_VLAN_MASK;
+
+	return 0;
+}
+
+int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, &reg);
+	if (err)
+		return err;
+
+	reg &= ~PORT_DEFAULT_VLAN_MASK;
+	reg |= pvid & PORT_DEFAULT_VLAN_MASK;
+
+	err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg);
+	if (err)
+		return err;
+
+	netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n",
+		   pvid);
+
+	return 0;
+}
+
+/* Offset 0x08: Port Control 2 Register */
+
+static const char * const mv88e6xxx_port_8021q_mode_names[] = {
+	[PORT_CONTROL_2_8021Q_DISABLED] = "Disabled",
+	[PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback",
+	[PORT_CONTROL_2_8021Q_CHECK] = "Check",
+	[PORT_CONTROL_2_8021Q_SECURE] = "Secure",
+};
+
+int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
+				  u16 mode)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+	if (err)
+		return err;
+
+	reg &= ~PORT_CONTROL_2_8021Q_MASK;
+	reg |= mode & PORT_CONTROL_2_8021Q_MASK;
+
+	err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+	if (err)
+		return err;
+
+	netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n",
+		   mv88e6xxx_port_8021q_mode_names[mode]);
+
+	return 0;
+}
+
+int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, &reg);
+	if (err)
+		return err;
+
+	reg |= PORT_CONTROL_2_JUMBO_10240;
+
+	return mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg);
+}
+
+/* Offset 0x09: Port Rate Control */
+
+int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
+{
+	return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0000);
+}
+
+int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port)
+{
+	return mv88e6xxx_port_write(chip, port, PORT_RATE_CONTROL, 0x0001);
+}
+
+/* Offset 0x0f: Port Ether type */
+
+int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
+				  u16 etype)
+{
+	return mv88e6xxx_port_write(chip, port, PORT_ETH_TYPE, etype);
+}
+
+/* Offset 0x18: Port IEEE Priority Remapping Registers [0-3]
+ * Offset 0x19: Port IEEE Priority Remapping Registers [4-7]
+ */
+
+int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
+{
+	int err;
+
+	/* Use a direct priority mapping for all IEEE tagged frames */
+	err = mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_0123, 0x3210);
+	if (err)
+		return err;
+
+	return mv88e6xxx_port_write(chip, port, PORT_TAG_REGMAP_4567, 0x7654);
+}
+
+static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
+					int port, u16 table,
+					u8 pointer, u16 data)
+{
+	u16 reg;
+
+	reg = PORT_IEEE_PRIO_MAP_TABLE_UPDATE |
+		table |
+		(pointer << PORT_IEEE_PRIO_MAP_TABLE_POINTER_SHIFT) |
+		data;
+
+	return mv88e6xxx_port_write(chip, port, PORT_IEEE_PRIO_MAP_TABLE, reg);
+}
+
+int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
+{
+	int err, i;
+
+	for (i = 0; i <= 7; i++) {
+		err = mv88e6xxx_port_ieeepmt_write(
+			chip, port, PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP,
+			i, (i | i << 4));
+		if (err)
+			return err;
+
+		err = mv88e6xxx_port_ieeepmt_write(
+			chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP,
+			i, i);
+		if (err)
+			return err;
+
+		err = mv88e6xxx_port_ieeepmt_write(
+			chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP,
+			i, i);
+		if (err)
+			return err;
+
+		err = mv88e6xxx_port_ieeepmt_write(
+			chip, port, PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP,
+			i, i);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/port.h linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/port.h
--- linux-libre-4.9-gnu/drivers/net/dsa/mv88e6xxx/port.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dsa/mv88e6xxx/port.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,71 @@
+/*
+ * Marvell 88E6xxx Switch Port Registers support
+ *
+ * Copyright (c) 2008 Marvell Semiconductor
+ *
+ * Copyright (c) 2016 Vivien Didelot <vivien.didelot@savoirfairelinux.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 _MV88E6XXX_PORT_H
+#define _MV88E6XXX_PORT_H
+
+#include "mv88e6xxx.h"
+
+int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
+			u16 *val);
+int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
+			 u16 val);
+
+int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+				   phy_interface_t mode);
+int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
+				   phy_interface_t mode);
+
+int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);
+
+int mv88e6xxx_port_set_duplex(struct mv88e6xxx_chip *chip, int port, int dup);
+
+int mv88e6065_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6185_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6352_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6390_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+int mv88e6390x_port_set_speed(struct mv88e6xxx_chip *chip, int port, int speed);
+
+int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state);
+
+int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map);
+
+int mv88e6xxx_port_get_fid(struct mv88e6xxx_chip *chip, int port, u16 *fid);
+int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid);
+
+int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid);
+int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid);
+
+int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
+				  u16 mode);
+int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
+int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
+				   u16 mode);
+int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+				  enum mv88e6xxx_frame_mode mode);
+int mv88e6351_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
+				  enum mv88e6xxx_frame_mode mode);
+int mv88e6085_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+				       bool on);
+int mv88e6351_port_set_egress_unknowns(struct mv88e6xxx_chip *chip, int port,
+				       bool on);
+int mv88e6351_port_set_ether_type(struct mv88e6xxx_chip *chip, int port,
+				  u16 etype);
+int mv88e6165_port_jumbo_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
+int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int port);
+int mv88e6097_port_pause_config(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_port_pause_config(struct mv88e6xxx_chip *chip, int port);
+
+#endif /* _MV88E6XXX_PORT_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/dummy.c linux-libre-4.10-rc8-gnu/drivers/net/dummy.c
--- linux-libre-4.9-gnu/drivers/net/dummy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/dummy.c	2017-02-12 16:03:20.000000000 -0500
@@ -154,6 +154,9 @@ static void dummy_setup(struct net_devic
 	dev->hw_features |= dev->features;
 	dev->hw_enc_features |= dev->features;
 	eth_hw_addr_random(dev);
+
+	dev->min_mtu = 0;
+	dev->max_mtu = ETH_MAX_MTU;
 }
 
 static int dummy_validate(struct nlattr *tb[], struct nlattr *data[])
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/eql.c linux-libre-4.10-rc8-gnu/drivers/net/eql.c
--- linux-libre-4.9-gnu/drivers/net/eql.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/eql.c	2017-02-12 16:03:20.000000000 -0500
@@ -127,7 +127,7 @@
 #include <linux/if_eql.h>
 #include <linux/pkt_sched.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 static int eql_open(struct net_device *dev);
 static int eql_close(struct net_device *dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c509.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c509.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c509.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c509.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,7 +88,7 @@
 #include <linux/eisa.h>
 #include <linux/bitops.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -508,7 +508,6 @@ static const struct net_device_ops netde
 	.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
@@ -1041,67 +1040,68 @@ el3_link_ok(struct net_device *dev)
 }
 
 static int
-el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_link_ksettings *cmd)
 {
 	u16 tmp;
 	int ioaddr = dev->base_addr;
+	u32 supported;
 
 	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;
+		cmd->base.port = PORT_TP;
 		break;
 	case 1:
-		ecmd->port = PORT_AUI;
-		ecmd->transceiver = XCVR_EXTERNAL;
+		cmd->base.port = PORT_AUI;
 		break;
 	case 3:
-		ecmd->port = PORT_BNC;
+		cmd->base.port = PORT_BNC;
 	default:
 		break;
 	}
 
-	ecmd->duplex = DUPLEX_HALF;
-	ecmd->supported = 0;
+	cmd->base.duplex = DUPLEX_HALF;
+	supported = 0;
 	tmp = inw(ioaddr + WN0_CONF_CTRL);
 	if (tmp & (1<<13))
-		ecmd->supported |= SUPPORTED_AUI;
+		supported |= SUPPORTED_AUI;
 	if (tmp & (1<<12))
-		ecmd->supported |= SUPPORTED_BNC;
+		supported |= SUPPORTED_BNC;
 	if (tmp & (1<<9)) {
-		ecmd->supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
+		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;
+			cmd->base.duplex = DUPLEX_FULL;
 	}
 
-	ethtool_cmd_speed_set(ecmd, SPEED_10);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	cmd->base.speed = SPEED_10;
 	EL3WINDOW(1);
 	return 0;
 }
 
 static int
-el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+el3_netdev_set_ecmd(struct net_device *dev,
+		    const struct ethtool_link_ksettings *cmd)
 {
 	u16 tmp;
 	int ioaddr = dev->base_addr;
 
-	if (ecmd->speed != SPEED_10)
-		return -EINVAL;
-	if ((ecmd->duplex != DUPLEX_HALF) && (ecmd->duplex != DUPLEX_FULL))
+	if (cmd->base.speed != SPEED_10)
 		return -EINVAL;
-	if ((ecmd->transceiver != XCVR_INTERNAL) && (ecmd->transceiver != XCVR_EXTERNAL))
+	if ((cmd->base.duplex != DUPLEX_HALF) &&
+	    (cmd->base.duplex != DUPLEX_FULL))
 		return -EINVAL;
 
 	/* change XCVR type */
 	EL3WINDOW(0);
 	tmp = inw(ioaddr + WN0_ADDR_CONF);
-	switch (ecmd->port) {
+	switch (cmd->base.port) {
 	case PORT_TP:
 		tmp &= ~(3<<14);
 		dev->if_port = 0;
@@ -1131,7 +1131,7 @@ el3_netdev_set_ecmd(struct net_device *d
 
 	EL3WINDOW(4);
 	tmp = inw(ioaddr + WN4_NETDIAG);
-	if (ecmd->duplex == DUPLEX_FULL)
+	if (cmd->base.duplex == DUPLEX_FULL)
 		tmp |= FD_ENABLE;
 	else
 		tmp &= ~FD_ENABLE;
@@ -1147,24 +1147,26 @@ static void el3_get_drvinfo(struct net_d
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
-static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int el3_get_link_ksettings(struct net_device *dev,
+				  struct ethtool_link_ksettings *cmd)
 {
 	struct el3_private *lp = netdev_priv(dev);
 	int ret;
 
 	spin_lock_irq(&lp->lock);
-	ret = el3_netdev_get_ecmd(dev, ecmd);
+	ret = el3_netdev_get_ecmd(dev, cmd);
 	spin_unlock_irq(&lp->lock);
 	return ret;
 }
 
-static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int el3_set_link_ksettings(struct net_device *dev,
+				  const struct ethtool_link_ksettings *cmd)
 {
 	struct el3_private *lp = netdev_priv(dev);
 	int ret;
 
 	spin_lock_irq(&lp->lock);
-	ret = el3_netdev_set_ecmd(dev, ecmd);
+	ret = el3_netdev_set_ecmd(dev, cmd);
 	spin_unlock_irq(&lp->lock);
 	return ret;
 }
@@ -1192,11 +1194,11 @@ static void el3_set_msglevel(struct net_
 
 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,
+	.get_link_ksettings = el3_get_link_ksettings,
+	.set_link_ksettings = el3_set_link_ksettings,
 };
 
 static void
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c515.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c515.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c515.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c515.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,7 @@ static int max_interrupt_work = 20;
 #include <linux/ethtool.h>
 #include <linux/bitops.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 
@@ -570,7 +570,6 @@ static const struct net_device_ops netde
 	.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,
 };
@@ -628,6 +627,8 @@ static int corkscrew_setup(struct net_de
 
 	spin_lock_init(&vp->lock);
 
+	setup_timer(&vp->timer, corkscrew_timer, (unsigned long) dev);
+
 	/* Read the station address from the EEPROM. */
 	EL3WINDOW(0);
 	for (i = 0; i < 0x18; i++) {
@@ -708,6 +709,7 @@ static int corkscrew_open(struct net_dev
 {
 	int ioaddr = dev->base_addr;
 	struct corkscrew_private *vp = netdev_priv(dev);
+	bool armtimer = false;
 	__u32 config;
 	int i;
 
@@ -732,12 +734,7 @@ static int corkscrew_open(struct net_dev
 		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);
+		armtimer = true;
 	} else
 		dev->if_port = vp->default_media;
 
@@ -777,6 +774,9 @@ static int corkscrew_open(struct net_dev
 		return -EAGAIN;
 	}
 
+	if (armtimer)
+		mod_timer(&vp->timer, jiffies + media_tbl[dev->if_port].wait);
+
 	if (corkscrew_debug > 1) {
 		EL3WINDOW(4);
 		pr_debug("%s: corkscrew_open() irq %d media status %4.4x.\n",
@@ -1427,7 +1427,7 @@ static int corkscrew_close(struct net_de
 			dev->name, rx_nocopy, rx_copy, queued_packet);
 	}
 
-	del_timer(&vp->timer);
+	del_timer_sync(&vp->timer);
 
 	/* Turn off statistics ASAP.  We update lp->stats below. */
 	outw(StatsDisable, ioaddr + EL3_CMD);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c574_cs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c574_cs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c574_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c574_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -92,7 +92,7 @@ earlier 3Com products.
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 /*====================================================================*/
@@ -254,7 +254,6 @@ static const struct net_device_ops el3_n
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c589_cs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c589_cs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c589_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c589_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -188,7 +188,6 @@ static const struct net_device_ops el3_n
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c59x.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c59x.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/3com/3c59x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/3c59x.c	2017-02-12 16:03:20.000000000 -0500
@@ -92,7 +92,7 @@ static int vortex_debug = 1;
 #include <linux/gfp.h>
 #include <asm/irq.h>			/* For nr_irqs only. */
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 /* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
    This is only in the support-all-kernels source code. */
@@ -1062,7 +1062,6 @@ static const struct net_device_ops boomr
 	.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
@@ -1080,7 +1079,6 @@ static const struct net_device_ops vorte
 	.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
@@ -2909,18 +2907,20 @@ static int vortex_nway_reset(struct net_
 	return mii_nway_restart(&vp->mii);
 }
 
-static int vortex_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int vortex_get_link_ksettings(struct net_device *dev,
+				     struct ethtool_link_ksettings *cmd)
 {
 	struct vortex_private *vp = netdev_priv(dev);
 
-	return mii_ethtool_gset(&vp->mii, cmd);
+	return mii_ethtool_get_link_ksettings(&vp->mii, cmd);
 }
 
-static int vortex_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int vortex_set_link_ksettings(struct net_device *dev,
+				     const struct ethtool_link_ksettings *cmd)
 {
 	struct vortex_private *vp = netdev_priv(dev);
 
-	return mii_ethtool_sset(&vp->mii, cmd);
+	return mii_ethtool_set_link_ksettings(&vp->mii, cmd);
 }
 
 static u32 vortex_get_msglevel(struct net_device *dev)
@@ -3033,13 +3033,13 @@ static const struct ethtool_ops vortex_e
 	.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,
 	.get_ts_info		= ethtool_op_get_ts_info,
+	.get_link_ksettings     = vortex_get_link_ksettings,
+	.set_link_ksettings     = vortex_set_link_ksettings,
 };
 
 #ifdef CONFIG_PCI
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/3com/typhoon.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/typhoon.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/3com/typhoon.c	2016-12-11 17:50:49.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/3com/typhoon.c	2017-02-12 17:40:13.000000000 -0500
@@ -119,7 +119,7 @@ static const int multicast_filter_limit
 #include <linux/bitops.h>
 #include <asm/processor.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/in6.h>
 #include <linux/dma-mapping.h>
 #include <linux/firmware.h>
@@ -996,28 +996,30 @@ typhoon_get_drvinfo(struct net_device *d
 }
 
 static int
-typhoon_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+typhoon_get_link_ksettings(struct net_device *dev,
+			   struct ethtool_link_ksettings *cmd)
 {
 	struct typhoon *tp = netdev_priv(dev);
+	u32 supported, advertising = 0;
 
-	cmd->supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+	supported = SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
 				SUPPORTED_Autoneg;
 
 	switch (tp->xcvr_select) {
 	case TYPHOON_XCVR_10HALF:
-		cmd->advertising = ADVERTISED_10baseT_Half;
+		advertising = ADVERTISED_10baseT_Half;
 		break;
 	case TYPHOON_XCVR_10FULL:
-		cmd->advertising = ADVERTISED_10baseT_Full;
+		advertising = ADVERTISED_10baseT_Full;
 		break;
 	case TYPHOON_XCVR_100HALF:
-		cmd->advertising = ADVERTISED_100baseT_Half;
+		advertising = ADVERTISED_100baseT_Half;
 		break;
 	case TYPHOON_XCVR_100FULL:
-		cmd->advertising = ADVERTISED_100baseT_Full;
+		advertising = ADVERTISED_100baseT_Full;
 		break;
 	case TYPHOON_XCVR_AUTONEG:
-		cmd->advertising = ADVERTISED_10baseT_Half |
+		advertising = ADVERTISED_10baseT_Half |
 					    ADVERTISED_10baseT_Full |
 					    ADVERTISED_100baseT_Half |
 					    ADVERTISED_100baseT_Full |
@@ -1026,54 +1028,57 @@ typhoon_get_settings(struct net_device *
 	}
 
 	if(tp->capabilities & TYPHOON_FIBER) {
-		cmd->supported |= SUPPORTED_FIBRE;
-		cmd->advertising |= ADVERTISED_FIBRE;
-		cmd->port = PORT_FIBRE;
+		supported |= SUPPORTED_FIBRE;
+		advertising |= ADVERTISED_FIBRE;
+		cmd->base.port = PORT_FIBRE;
 	} else {
-		cmd->supported |= SUPPORTED_10baseT_Half |
+		supported |= SUPPORTED_10baseT_Half |
 		    			SUPPORTED_10baseT_Full |
 					SUPPORTED_TP;
-		cmd->advertising |= ADVERTISED_TP;
-		cmd->port = PORT_TP;
+		advertising |= ADVERTISED_TP;
+		cmd->base.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;
+	cmd->base.speed = tp->speed;
+	cmd->base.duplex = tp->duplex;
+	cmd->base.phy_address = 0;
 	if(tp->xcvr_select == TYPHOON_XCVR_AUTONEG)
-		cmd->autoneg = AUTONEG_ENABLE;
+		cmd->base.autoneg = AUTONEG_ENABLE;
 	else
-		cmd->autoneg = AUTONEG_DISABLE;
-	cmd->maxtxpkt = 1;
-	cmd->maxrxpkt = 1;
+		cmd->base.autoneg = AUTONEG_DISABLE;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return 0;
 }
 
 static int
-typhoon_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+typhoon_set_link_ksettings(struct net_device *dev,
+			   const struct ethtool_link_ksettings *cmd)
 {
 	struct typhoon *tp = netdev_priv(dev);
-	u32 speed = ethtool_cmd_speed(cmd);
+	u32 speed = cmd->base.speed;
 	struct cmd_desc xp_cmd;
 	__le16 xcvr;
 	int err;
 
 	err = -EINVAL;
-	if (cmd->autoneg == AUTONEG_ENABLE) {
+	if (cmd->base.autoneg == AUTONEG_ENABLE) {
 		xcvr = TYPHOON_XCVR_AUTONEG;
 	} else {
-		if (cmd->duplex == DUPLEX_HALF) {
+		if (cmd->base.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) {
+		} else if (cmd->base.duplex == DUPLEX_FULL) {
 			if (speed == SPEED_10)
 				xcvr = TYPHOON_XCVR_10FULL;
 			else if (speed == SPEED_100)
@@ -1091,12 +1096,12 @@ typhoon_set_settings(struct net_device *
 		goto out;
 
 	tp->xcvr_select = xcvr;
-	if(cmd->autoneg == AUTONEG_ENABLE) {
+	if (cmd->base.autoneg == AUTONEG_ENABLE) {
 		tp->speed = 0xff;	/* invalid */
 		tp->duplex = 0xff;	/* invalid */
 	} else {
 		tp->speed = speed;
-		tp->duplex = cmd->duplex;
+		tp->duplex = cmd->base.duplex;
 	}
 
 out:
@@ -1145,13 +1150,13 @@ typhoon_get_ringparam(struct net_device
 }
 
 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,
+	.get_link_ksettings	= typhoon_get_link_ksettings,
+	.set_link_ksettings	= typhoon_set_link_ksettings,
 };
 
 static int
@@ -2255,7 +2260,6 @@ static const struct net_device_ops typho
 	.ndo_get_stats		= typhoon_get_stats,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_change_mtu		= eth_change_mtu,
 };
 
 static int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/8390.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/8390.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/8390.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/8390.c	2017-02-12 16:03:20.000000000 -0500
@@ -64,7 +64,6 @@ const struct net_device_ops ei_netdev_op
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/8390p.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/8390p.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/8390p.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/8390p.c	2017-02-12 16:03:20.000000000 -0500
@@ -69,7 +69,6 @@ const struct net_device_ops eip_netdev_o
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/ax88796.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/ax88796.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/ax88796.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/ax88796.c	2017-02-12 16:03:20.000000000 -0500
@@ -536,7 +536,6 @@ static const struct net_device_ops ax_ne
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/axnet_cs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/axnet_cs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/axnet_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/axnet_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -46,7 +46,7 @@
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define AXNET_CMD	0x00
 #define AXNET_DATAPORT	0x10	/* NatSemi-defined port window offset. */
@@ -134,7 +134,6 @@ static const struct net_device_ops axnet
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/etherh.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/etherh.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/etherh.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/etherh.c	2017-02-12 16:03:20.000000000 -0500
@@ -654,7 +654,6 @@ static const struct net_device_ops ether
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/hydra.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/hydra.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/hydra.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/hydra.c	2017-02-12 16:03:20.000000000 -0500
@@ -105,7 +105,6 @@ static const struct net_device_ops hydra
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/mac8390.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/mac8390.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/mac8390.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/mac8390.c	2017-02-12 16:03:20.000000000 -0500
@@ -483,7 +483,6 @@ static const struct net_device_ops mac83
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/mcf8390.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/mcf8390.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/mcf8390.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/mcf8390.c	2017-02-12 16:03:20.000000000 -0500
@@ -308,7 +308,6 @@ static const struct net_device_ops mcf83
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/ne2k-pci.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/ne2k-pci.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/ne2k-pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/ne2k-pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@ static int options[MAX_UNITS];
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "8390.h"
 
@@ -209,7 +209,6 @@ static const struct net_device_ops ne2k_
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/pcnet_cs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/pcnet_cs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/pcnet_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/pcnet_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,7 @@
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define PCNET_CMD	0x00
 #define PCNET_DATAPORT	0x10	/* NatSemi-defined port window offset. */
@@ -227,7 +227,6 @@ static const struct net_device_ops pcnet
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/smc-ultra.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/smc-ultra.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/smc-ultra.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/smc-ultra.c	2017-02-12 16:03:20.000000000 -0500
@@ -195,7 +195,6 @@ static const struct net_device_ops ultra
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/wd.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/wd.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/wd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/wd.c	2017-02-12 16:03:20.000000000 -0500
@@ -156,7 +156,6 @@ static const struct net_device_ops wd_ne
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/8390/zorro8390.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/zorro8390.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/8390/zorro8390.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/8390/zorro8390.c	2017-02-12 16:03:20.000000000 -0500
@@ -284,7 +284,6 @@ static const struct net_device_ops zorro
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/adaptec/starfire.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/adaptec/starfire.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/adaptec/starfire.c	2016-12-11 17:48:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/adaptec/starfire.c	2017-02-12 17:37:12.000000000 -0500
@@ -45,7 +45,7 @@
 #include <linux/mm.h>
 #include <linux/firmware.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 /*
@@ -633,7 +633,6 @@ static const struct net_device_ops netde
 	.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
@@ -1152,6 +1151,12 @@ static void init_ring(struct net_device
 		if (skb == NULL)
 			break;
 		np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+		if (pci_dma_mapping_error(np->pci_dev,
+					  np->rx_info[i].mapping)) {
+			dev_kfree_skb(skb);
+			np->rx_info[i].skb = NULL;
+			break;
+		}
 		/* Grrr, we cannot offset to correctly align the IP header. */
 		np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
 	}
@@ -1182,8 +1187,9 @@ static netdev_tx_t start_tx(struct sk_bu
 {
 	struct netdev_private *np = netdev_priv(dev);
 	unsigned int entry;
+	unsigned int prev_tx;
 	u32 status;
-	int i;
+	int i, j;
 
 	/*
 	 * be cautious here, wrapping the queue has weird semantics
@@ -1201,6 +1207,7 @@ static netdev_tx_t start_tx(struct sk_bu
 	}
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
+	prev_tx = np->cur_tx;
 	entry = np->cur_tx % TX_RING_SIZE;
 	for (i = 0; i < skb_num_frags(skb); i++) {
 		int wrap_ring = 0;
@@ -1234,6 +1241,11 @@ static netdev_tx_t start_tx(struct sk_bu
 					       skb_frag_size(this_frag),
 					       PCI_DMA_TODEVICE);
 		}
+		if (pci_dma_mapping_error(np->pci_dev,
+					  np->tx_info[entry].mapping)) {
+			dev->stats.tx_dropped++;
+			goto err_out;
+		}
 
 		np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
 		np->tx_ring[entry].status = cpu_to_le32(status);
@@ -1268,8 +1280,30 @@ static netdev_tx_t start_tx(struct sk_bu
 		netif_stop_queue(dev);
 
 	return NETDEV_TX_OK;
-}
 
+err_out:
+	entry = prev_tx % TX_RING_SIZE;
+	np->tx_info[entry].skb = NULL;
+	if (i > 0) {
+		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;
+		entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
+		for (j = 1; j < i; j++) {
+			pci_unmap_single(np->pci_dev,
+					 np->tx_info[entry].mapping,
+					 skb_frag_size(
+						&skb_shinfo(skb)->frags[j-1]),
+					 PCI_DMA_TODEVICE);
+			entry++;
+		}
+	}
+	dev_kfree_skb_any(skb);
+	np->cur_tx = prev_tx;
+	return NETDEV_TX_OK;
+}
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
@@ -1569,6 +1603,12 @@ static void refill_rx_ring(struct net_de
 				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);
+			if (pci_dma_mapping_error(np->pci_dev,
+						np->rx_info[entry].mapping)) {
+				dev_kfree_skb(skb);
+				np->rx_info[entry].skb = NULL;
+				break;
+			}
 			np->rx_ring[entry].rxaddr =
 				cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
 		}
@@ -1816,21 +1856,23 @@ static void get_drvinfo(struct net_devic
 	strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
-static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int get_link_ksettings(struct net_device *dev,
+			      struct ethtool_link_ksettings *cmd)
 {
 	struct netdev_private *np = netdev_priv(dev);
 	spin_lock_irq(&np->lock);
-	mii_ethtool_gset(&np->mii_if, ecmd);
+	mii_ethtool_get_link_ksettings(&np->mii_if, cmd);
 	spin_unlock_irq(&np->lock);
 	return 0;
 }
 
-static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int set_link_ksettings(struct net_device *dev,
+			      const struct ethtool_link_ksettings *cmd)
 {
 	struct netdev_private *np = netdev_priv(dev);
 	int res;
 	spin_lock_irq(&np->lock);
-	res = mii_ethtool_sset(&np->mii_if, ecmd);
+	res = mii_ethtool_set_link_ksettings(&np->mii_if, cmd);
 	spin_unlock_irq(&np->lock);
 	check_duplex(dev);
 	return res;
@@ -1861,12 +1903,12 @@ static void set_msglevel(struct net_devi
 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,
+	.get_link_ksettings = get_link_ksettings,
+	.set_link_ksettings = set_link_ksettings,
 };
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/adi/bfin_mac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/adi/bfin_mac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/adi/bfin_mac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/adi/bfin_mac.c	2017-02-12 16:03:20.000000000 -0500
@@ -1571,7 +1571,6 @@ static const struct net_device_ops bfin_
 	.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_controller,
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/adi/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/adi/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/adi/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/adi/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,7 @@ config BFIN_RX_DESC_NUM
 config BFIN_MAC_USE_HWSTAMP
 	bool "Use IEEE 1588 hwstamp"
 	depends on BFIN_MAC && BF518
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	default y
 	---help---
 	  To support the IEEE 1588 Precision Time Protocol (PTP), select y here
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/aeroflex/greth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/aeroflex/greth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/aeroflex/greth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/aeroflex/greth.c	2017-02-12 16:03:20.000000000 -0500
@@ -1290,15 +1290,6 @@ static int greth_mdio_probe(struct net_d
 	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;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/agere/et131x.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/agere/et131x.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/agere/et131x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/agere/et131x.c	2017-02-12 16:03:20.000000000 -0500
@@ -176,6 +176,8 @@ MODULE_DESCRIPTION("10/100/1000 Base-T E
 #define NUM_FBRS		2
 
 #define MAX_PACKETS_HANDLED	256
+#define ET131X_MIN_MTU		64
+#define ET131X_MAX_MTU		9216
 
 #define ALCATEL_MULTICAST_PKT	0x01000000
 #define ALCATEL_BROADCAST_PKT	0x02000000
@@ -3869,9 +3871,6 @@ static int et131x_change_mtu(struct net_
 	int result = 0;
 	struct et131x_adapter *adapter = netdev_priv(netdev);
 
-	if (new_mtu < 64 || new_mtu > 9216)
-		return -EINVAL;
-
 	et131x_disable_txrx(netdev);
 
 	netdev->mtu = new_mtu;
@@ -3958,6 +3957,8 @@ static int et131x_pci_setup(struct pci_d
 
 	netdev->watchdog_timeo = ET131X_TX_TIMEOUT;
 	netdev->netdev_ops     = &et131x_netdev_ops;
+	netdev->min_mtu        = ET131X_MIN_MTU;
+	netdev->max_mtu        = ET131X_MAX_MTU;
 
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 	netdev->ethtool_ops = &et131x_ethtool_ops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,28 @@
+config NET_VENDOR_ALACRITECH
+	bool "Alacritech devices"
+	default y
+	---help---
+	  If you have a network (Ethernet) card belonging to this class, 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
+	  questions about Alacritech devices. If you say Y, you will be asked
+	  for your specific device in the following questions.
+
+if NET_VENDOR_ALACRITECH
+
+config SLICOSS
+	tristate "Alacritech Slicoss support"
+	depends on PCI
+	select CRC32
+	---help---
+	  This driver supports Gigabit Ethernet adapters based on the
+	  Session Layer Interface (SLIC) technology by Alacritech.
+
+	  Supported are Mojave (1 port) and Oasis (1, 2 and 4 port) cards,
+	  both copper and fiber.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called slicoss. This is recommended.
+
+endif # NET_VENDOR_ALACRITECH
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,4 @@
+#
+# Makefile for the Alacritech Slicoss driver
+#
+obj-$(CONFIG_SLICOSS) += slicoss.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/slic.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/slic.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/slic.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/slic.h	2017-02-12 17:39:31.000000000 -0500
@@ -0,0 +1,575 @@
+
+#ifndef _SLIC_H
+#define _SLIC_H
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock_types.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/list.h>
+#include <linux/u64_stats_sync.h>
+
+#define SLIC_VGBSTAT_XPERR		0x40000000
+#define SLIC_VGBSTAT_XERRSHFT		25
+#define SLIC_VGBSTAT_XCSERR		0x23
+#define SLIC_VGBSTAT_XUFLOW		0x22
+#define SLIC_VGBSTAT_XHLEN		0x20
+#define SLIC_VGBSTAT_NETERR		0x01000000
+#define SLIC_VGBSTAT_NERRSHFT		16
+#define SLIC_VGBSTAT_NERRMSK		0x1ff
+#define SLIC_VGBSTAT_NCSERR		0x103
+#define SLIC_VGBSTAT_NUFLOW		0x102
+#define SLIC_VGBSTAT_NHLEN		0x100
+#define SLIC_VGBSTAT_LNKERR		0x00000080
+#define SLIC_VGBSTAT_LERRMSK		0xff
+#define SLIC_VGBSTAT_LDEARLY		0x86
+#define SLIC_VGBSTAT_LBOFLO		0x85
+#define SLIC_VGBSTAT_LCODERR		0x84
+#define SLIC_VGBSTAT_LDBLNBL		0x83
+#define SLIC_VGBSTAT_LCRCERR		0x82
+#define SLIC_VGBSTAT_LOFLO		0x81
+#define SLIC_VGBSTAT_LUFLO		0x80
+
+#define SLIC_IRHDDR_FLEN_MSK		0x0000ffff
+#define SLIC_IRHDDR_SVALID		0x80000000
+#define SLIC_IRHDDR_ERR			0x10000000
+
+#define SLIC_VRHSTAT_802OE		0x80000000
+#define SLIC_VRHSTAT_TPOFLO		0x10000000
+#define SLIC_VRHSTATB_802UE		0x80000000
+#define SLIC_VRHSTATB_RCVE		0x40000000
+#define SLIC_VRHSTATB_BUFF		0x20000000
+#define SLIC_VRHSTATB_CARRE		0x08000000
+#define SLIC_VRHSTATB_LONGE		0x02000000
+#define SLIC_VRHSTATB_PREA		0x01000000
+#define SLIC_VRHSTATB_CRC		0x00800000
+#define SLIC_VRHSTATB_DRBL		0x00400000
+#define SLIC_VRHSTATB_CODE		0x00200000
+#define SLIC_VRHSTATB_TPCSUM		0x00100000
+#define SLIC_VRHSTATB_TPHLEN		0x00080000
+#define SLIC_VRHSTATB_IPCSUM		0x00040000
+#define SLIC_VRHSTATB_IPLERR		0x00020000
+#define SLIC_VRHSTATB_IPHERR		0x00010000
+
+#define SLIC_CMD_XMT_REQ		0x01
+#define SLIC_CMD_TYPE_DUMB		3
+
+#define SLIC_RESET_MAGIC		0xDEAD
+#define SLIC_ICR_INT_OFF		0
+#define SLIC_ICR_INT_ON			1
+#define SLIC_ICR_INT_MASK		2
+
+#define SLIC_ISR_ERR			0x80000000
+#define SLIC_ISR_RCV			0x40000000
+#define SLIC_ISR_CMD			0x20000000
+#define SLIC_ISR_IO			0x60000000
+#define SLIC_ISR_UPC			0x10000000
+#define SLIC_ISR_LEVENT			0x08000000
+#define SLIC_ISR_RMISS			0x02000000
+#define SLIC_ISR_UPCERR			0x01000000
+#define SLIC_ISR_XDROP			0x00800000
+#define SLIC_ISR_UPCBSY			0x00020000
+
+#define SLIC_ISR_PING_MASK		0x00700000
+#define SLIC_ISR_UPCERR_MASK		(SLIC_ISR_UPCERR | SLIC_ISR_UPCBSY)
+#define SLIC_ISR_UPC_MASK		(SLIC_ISR_UPC | SLIC_ISR_UPCERR_MASK)
+#define SLIC_WCS_START			0x80000000
+#define SLIC_WCS_COMPARE		0x40000000
+#define SLIC_RCVWCS_BEGIN		0x40000000
+#define SLIC_RCVWCS_FINISH		0x80000000
+
+#define SLIC_MIICR_REG_16		0x00100000
+#define SLIC_MRV_REG16_XOVERON		0x0068
+
+#define SLIC_GIG_LINKUP			0x0001
+#define SLIC_GIG_FULLDUPLEX		0x0002
+#define SLIC_GIG_SPEED_MASK		0x000C
+#define SLIC_GIG_SPEED_1000		0x0008
+#define SLIC_GIG_SPEED_100		0x0004
+#define SLIC_GIG_SPEED_10		0x0000
+
+#define SLIC_GMCR_RESET			0x80000000
+#define SLIC_GMCR_GBIT			0x20000000
+#define SLIC_GMCR_FULLD			0x10000000
+#define SLIC_GMCR_GAPBB_SHIFT		14
+#define SLIC_GMCR_GAPR1_SHIFT		7
+#define SLIC_GMCR_GAPR2_SHIFT		0
+#define SLIC_GMCR_GAPBB_1000		0x60
+#define SLIC_GMCR_GAPR1_1000		0x2C
+#define SLIC_GMCR_GAPR2_1000		0x40
+#define SLIC_GMCR_GAPBB_100		0x70
+#define SLIC_GMCR_GAPR1_100		0x2C
+#define SLIC_GMCR_GAPR2_100		0x40
+
+#define SLIC_XCR_RESET			0x80000000
+#define SLIC_XCR_XMTEN			0x40000000
+#define SLIC_XCR_PAUSEEN		0x20000000
+#define SLIC_XCR_LOADRNG		0x10000000
+
+#define SLIC_GXCR_RESET			0x80000000
+#define SLIC_GXCR_XMTEN			0x40000000
+#define SLIC_GXCR_PAUSEEN		0x20000000
+
+#define SLIC_GRCR_RESET			0x80000000
+#define SLIC_GRCR_RCVEN			0x40000000
+#define SLIC_GRCR_RCVALL		0x20000000
+#define SLIC_GRCR_RCVBAD		0x10000000
+#define SLIC_GRCR_CTLEN			0x08000000
+#define SLIC_GRCR_ADDRAEN		0x02000000
+#define SLIC_GRCR_HASHSIZE_SHIFT	17
+#define SLIC_GRCR_HASHSIZE		14
+
+/* Reset Register */
+#define SLIC_REG_RESET			0x0000
+/* Interrupt Control Register */
+#define SLIC_REG_ICR			0x0008
+/* Interrupt status pointer */
+#define SLIC_REG_ISP			0x0010
+/* Interrupt status */
+#define SLIC_REG_ISR			0x0018
+/* Header buffer address reg
+ * 31-8 - phy addr of set of contiguous hdr buffers
+ *  7-0 - number of buffers passed
+ * Buffers are 256 bytes long on 256-byte boundaries.
+ */
+#define SLIC_REG_HBAR			0x0020
+/* Data buffer handle & address reg
+ * 4 sets of registers; Buffers are 2K bytes long 2 per 4K page.
+ */
+#define SLIC_REG_DBAR			0x0028
+/* Xmt Cmd buf addr regs.
+ * 1 per XMT interface
+ * 31-5 - phy addr of host command buffer
+ *  4-0 - length of cmd in multiples of 32 bytes
+ * Buffers are 32 bytes up to 512 bytes long
+ */
+#define SLIC_REG_CBAR			0x0030
+/* Write control store */
+#define	SLIC_REG_WCS			0x0034
+/*Response buffer address reg.
+ * 31-8 - phy addr of set of contiguous response buffers
+ * 7-0 - number of buffers passed
+ * Buffers are 32 bytes long on 32-byte boundaries.
+ */
+#define	SLIC_REG_RBAR			0x0038
+/* Read statistics (UPR) */
+#define	SLIC_REG_RSTAT			0x0040
+/* Read link status */
+#define	SLIC_REG_LSTAT			0x0048
+/* Write Mac Config */
+#define	SLIC_REG_WMCFG			0x0050
+/* Write phy register */
+#define SLIC_REG_WPHY			0x0058
+/* Rcv Cmd buf addr reg */
+#define	SLIC_REG_RCBAR			0x0060
+/* Read SLIC Config*/
+#define SLIC_REG_RCONFIG		0x0068
+/* Interrupt aggregation time */
+#define SLIC_REG_INTAGG			0x0070
+/* Write XMIT config reg */
+#define	SLIC_REG_WXCFG			0x0078
+/* Write RCV config reg */
+#define	SLIC_REG_WRCFG			0x0080
+/* Write rcv addr a low */
+#define	SLIC_REG_WRADDRAL		0x0088
+/* Write rcv addr a high */
+#define	SLIC_REG_WRADDRAH		0x0090
+/* Write rcv addr b low */
+#define	SLIC_REG_WRADDRBL		0x0098
+/* Write rcv addr b high */
+#define	SLIC_REG_WRADDRBH		0x00a0
+/* Low bits of mcast mask */
+#define	SLIC_REG_MCASTLOW		0x00a8
+/* High bits of mcast mask */
+#define	SLIC_REG_MCASTHIGH		0x00b0
+/* Ping the card */
+#define SLIC_REG_PING			0x00b8
+/* Dump command */
+#define SLIC_REG_DUMP_CMD		0x00c0
+/* Dump data pointer */
+#define SLIC_REG_DUMP_DATA		0x00c8
+/* Read card's pci_status register */
+#define	SLIC_REG_PCISTATUS		0x00d0
+/* Write hostid field */
+#define SLIC_REG_WRHOSTID		0x00d8
+/* Put card in a low power state */
+#define SLIC_REG_LOW_POWER		0x00e0
+/* Force slic into quiescent state  before soft reset */
+#define SLIC_REG_QUIESCE		0x00e8
+/* Reset interface queues */
+#define SLIC_REG_RESET_IFACE		0x00f0
+/* Register is only written when it has changed.
+ * Bits 63-32 for host i/f addrs.
+ */
+#define SLIC_REG_ADDR_UPPER		0x00f8
+/* 64 bit Header buffer address reg */
+#define SLIC_REG_HBAR64			0x0100
+/* 64 bit Data buffer handle & address reg */
+#define SLIC_REG_DBAR64			0x0108
+/* 64 bit Xmt Cmd buf addr regs. */
+#define SLIC_REG_CBAR64			0x0110
+/* 64 bit Response buffer address reg.*/
+#define SLIC_REG_RBAR64			0x0118
+/* 64 bit Rcv Cmd buf addr reg*/
+#define	SLIC_REG_RCBAR64		0x0120
+/* Read statistics (64 bit UPR) */
+#define	SLIC_REG_RSTAT64		0x0128
+/* Download Gigabit RCV sequencer ucode */
+#define SLIC_REG_RCV_WCS		0x0130
+/* Write VlanId field */
+#define SLIC_REG_WRVLANID		0x0138
+/* Read Transformer info */
+#define SLIC_REG_READ_XF_INFO		0x0140
+/* Write Transformer info */
+#define SLIC_REG_WRITE_XF_INFO		0x0148
+/* Write card ticks per second */
+#define SLIC_REG_TICKS_PER_SEC		0x0170
+#define SLIC_REG_HOSTID			0x1554
+
+#define PCI_VENDOR_ID_ALACRITECH		0x139A
+#define PCI_DEVICE_ID_ALACRITECH_MOJAVE		0x0005
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1	0x0005
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1_2	0x0006
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1F	0x0007
+#define PCI_SUBDEVICE_ID_ALACRITECH_CICADA	0x0008
+#define PCI_SUBDEVICE_ID_ALACRITECH_SES1001T	0x2006
+#define PCI_SUBDEVICE_ID_ALACRITECH_SES1001F	0x2007
+#define PCI_DEVICE_ID_ALACRITECH_OASIS		0x0007
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XT	0x000B
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF	0x000C
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XT	0x000D
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF	0x000E
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF	0x000F
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2104ET	0x0010
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF	0x0011
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2102ET	0x0012
+
+/* Note: power of two required for number descriptors  */
+#define SLIC_NUM_RX_LES			256
+#define SLIC_RX_BUFF_SIZE		2048
+#define SLIC_RX_BUFF_ALIGN		256
+#define SLIC_RX_BUFF_HDR_SIZE		34
+#define SLIC_MAX_REQ_RX_DESCS		1
+
+#define SLIC_NUM_TX_DESCS		256
+#define SLIC_TX_DESC_ALIGN		32
+#define SLIC_MIN_TX_WAKEUP_DESCS	10
+#define SLIC_MAX_REQ_TX_DESCS		1
+#define SLIC_MAX_TX_COMPLETIONS		100
+
+#define SLIC_NUM_STAT_DESCS		128
+#define SLIC_STATS_DESC_ALIGN		256
+
+#define SLIC_NUM_STAT_DESC_ARRAYS	4
+#define SLIC_INVALID_STAT_DESC_IDX	0xffffffff
+
+#define SLIC_NAPI_WEIGHT		64
+
+#define SLIC_UPR_LSTAT			0
+#define SLIC_UPR_CONFIG			1
+
+#define SLIC_EEPROM_SIZE		128
+#define SLIC_EEPROM_MAGIC		0xa5a5
+
+#define SLIC_FIRMWARE_MOJAVE		"/*(DEBLOBBED)*/"
+#define SLIC_FIRMWARE_OASIS		"/*(DEBLOBBED)*/"
+#define SLIC_RCV_FIRMWARE_MOJAVE	"/*(DEBLOBBED)*/"
+#define SLIC_RCV_FIRMWARE_OASIS		"/*(DEBLOBBED)*/"
+#define SLIC_FIRMWARE_MIN_SIZE		64
+#define SLIC_FIRMWARE_MAX_SECTIONS	3
+
+#define SLIC_MODEL_MOJAVE		0
+#define SLIC_MODEL_OASIS		1
+
+#define SLIC_INC_STATS_COUNTER(st, counter)	\
+do {						\
+	u64_stats_update_begin(&(st)->syncp);	\
+	(st)->counter++;			\
+	u64_stats_update_end(&(st)->syncp);	\
+} while (0)
+
+#define SLIC_GET_STATS_COUNTER(newst, st, counter)			\
+{									\
+	unsigned int start;						\
+	do {							\
+		start = u64_stats_fetch_begin_irq(&(st)->syncp);	\
+		newst = (st)->counter;					\
+	} while (u64_stats_fetch_retry_irq(&(st)->syncp, start));	\
+}
+
+struct slic_upr {
+	dma_addr_t paddr;
+	unsigned int type;
+	struct list_head list;
+};
+
+struct slic_upr_list {
+	bool pending;
+	struct list_head list;
+	/* upr list lock */
+	spinlock_t lock;
+};
+
+/* SLIC EEPROM structure for Mojave */
+struct slic_mojave_eeprom {
+	__le16 id;		/* 00 EEPROM/FLASH Magic code 'A5A5'*/
+	__le16 eeprom_code_size;/* 01 Size of EEPROM Codes (bytes * 4)*/
+	__le16 flash_size;	/* 02 Flash size */
+	__le16 eeprom_size;	/* 03 EEPROM Size */
+	__le16 vendor_id;	/* 04 Vendor ID */
+	__le16 dev_id;		/* 05 Device ID */
+	u8 rev_id;		/* 06 Revision ID */
+	u8 class_code[3];	/* 07 Class Code */
+	u8 irqpin_dbg;		/* 08 Debug Interrupt pin */
+	u8 irqpin;		/*    Network Interrupt Pin */
+	u8 min_grant;		/* 09 Minimum grant */
+	u8 max_lat;		/*    Maximum Latency */
+	__le16 pci_stat;	/* 10 PCI Status */
+	__le16 sub_vendor_id;	/* 11 Subsystem Vendor Id */
+	__le16 sub_id;		/* 12 Subsystem ID */
+	__le16 dev_id_dbg;	/* 13 Debug Device Id */
+	__le16 ramrom;		/* 14 Dram/Rom function */
+	__le16 dram_size2pci;	/* 15 DRAM size to PCI (bytes * 64K) */
+	__le16 rom_size2pci;	/* 16 ROM extension size to PCI (bytes * 4k) */
+	u8 pad[2];		/* 17 Padding */
+	u8 freetime;		/* 18 FreeTime setting */
+	u8 ifctrl;		/* 10-bit interface control (Mojave only) */
+	__le16 dram_size;	/* 19 DRAM size (bytes * 64k) */
+	u8 mac[ETH_ALEN];	/* 20 MAC addresses */
+	u8 mac2[ETH_ALEN];
+	u8 pad2[6];
+	u16 dev_id2;		/* Device ID for 2nd PCI function */
+	u8 irqpin2;		/* Interrupt pin for 2nd PCI function */
+	u8 class_code2[3];	/* Class Code for 2nd PCI function */
+	u16 cfg_byte6;		/* Config Byte 6 */
+	u16 pme_cap;		/* Power Mgment capabilities */
+	u16 nwclk_ctrl;		/* NetworkClockControls */
+	u8 fru_format;		/* Alacritech FRU format type */
+	u8 fru_assembly[6];	/* Alacritech FRU information */
+	u8 fru_rev[2];
+	u8 fru_serial[14];
+	u8 fru_pad[3];
+	u8 oem_fru[28];		/* optional OEM FRU format type */
+	u8 pad3[4];		/* Pad to 128 bytes - includes 2 cksum bytes
+				 * (if OEM FRU info exists) and two unusable
+				 * bytes at the end
+				 */
+};
+
+/* SLIC EEPROM structure for Oasis */
+struct slic_oasis_eeprom {
+	__le16 id;		/* 00 EEPROM/FLASH Magic code 'A5A5' */
+	__le16 eeprom_code_size;/* 01 Size of EEPROM Codes (bytes * 4)*/
+	__le16 spidev0_cfg;	/* 02 Flash Config for SPI device 0 */
+	__le16 spidev1_cfg;	/* 03 Flash Config for SPI device 1 */
+	__le16 vendor_id;	/* 04 Vendor ID */
+	__le16 dev_id;		/* 05 Device ID (function 0) */
+	u8 rev_id;		/* 06 Revision ID */
+	u8 class_code0[3];	/* 07 Class Code for PCI function 0 */
+	u8 irqpin1;		/* 08 Interrupt pin for PCI function 1*/
+	u8 class_code1[3];	/* 09 Class Code for PCI function 1 */
+	u8 irqpin2;		/* 10 Interrupt pin for PCI function 2*/
+	u8 irqpin0;		/*    Interrupt pin for PCI function 0*/
+	u8 min_grant;		/* 11 Minimum grant */
+	u8 max_lat;		/*    Maximum Latency */
+	__le16 sub_vendor_id;	/* 12 Subsystem Vendor Id */
+	__le16 sub_id;		/* 13 Subsystem ID */
+	__le16 flash_size;	/* 14 Flash size (bytes / 4K) */
+	__le16 dram_size2pci;	/* 15 DRAM size to PCI (bytes / 64K) */
+	__le16 rom_size2pci;	/* 16 Flash (ROM extension) size to PCI
+				 *   (bytes / 4K)
+				 */
+	__le16 dev_id1;		/* 17 Device Id (function 1) */
+	__le16 dev_id2;		/* 18 Device Id (function 2) */
+	__le16 dev_stat_cfg;	/* 19 Device Status Config Bytes 6-7 */
+	__le16 pme_cap;		/* 20 Power Mgment capabilities */
+	u8 msi_cap;		/* 21 MSI capabilities */
+	u8 clock_div;		/*    Clock divider */
+	__le16 pci_stat_lo;	/* 22 PCI Status bits 15:0 */
+	__le16 pci_stat_hi;	/* 23 PCI Status bits 31:16 */
+	__le16 dram_cfg_lo;	/* 24 DRAM Configuration bits 15:0 */
+	__le16 dram_cfg_hi;	/* 25 DRAM Configuration bits 31:16 */
+	__le16 dram_size;	/* 26 DRAM size (bytes / 64K) */
+	__le16 gpio_tbi_ctrl;	/* 27 GPIO/TBI controls for functions 1/0 */
+	__le16 eeprom_size;	/* 28 EEPROM Size */
+	u8 mac[ETH_ALEN];	/* 29 MAC addresses (2 ports) */
+	u8 mac2[ETH_ALEN];
+	u8 fru_format;		/* 35 Alacritech FRU format type */
+	u8 fru_assembly[6];	/* Alacritech FRU information */
+	u8 fru_rev[2];
+	u8 fru_serial[14];
+	u8 fru_pad[3];
+	u8 oem_fru[28];		/* optional OEM FRU information */
+	u8 pad[4];		/* Pad to 128 bytes - includes 2 checksum bytes
+				 * (if OEM FRU info exists) and two unusable
+				 * bytes at the end
+				 */
+};
+
+struct slic_stats {
+	u64 rx_packets;
+	u64 rx_bytes;
+	u64 rx_mcasts;
+	u64 rx_errors;
+	u64 tx_packets;
+	u64 tx_bytes;
+	/* HW STATS */
+	u64 rx_buff_miss;
+	u64 tx_dropped;
+	u64 irq_errs;
+	/* transport layer */
+	u64 rx_tpcsum;
+	u64 rx_tpoflow;
+	u64 rx_tphlen;
+	/* ip layer */
+	u64 rx_ipcsum;
+	u64 rx_iplen;
+	u64 rx_iphlen;
+	/* link layer */
+	u64 rx_early;
+	u64 rx_buffoflow;
+	u64 rx_lcode;
+	u64 rx_drbl;
+	u64 rx_crc;
+	u64 rx_oflow802;
+	u64 rx_uflow802;
+	/* oasis only */
+	u64 tx_carrier;
+	struct u64_stats_sync syncp;
+};
+
+struct slic_shmem_data {
+	__le32 isr;
+	__le32 link;
+};
+
+struct slic_shmem {
+	dma_addr_t isr_paddr;
+	dma_addr_t link_paddr;
+	struct slic_shmem_data *shmem_data;
+};
+
+struct slic_rx_info_oasis {
+	__le32 frame_status;
+	__le32 frame_status_b;
+	__le32 time_stamp;
+	__le32 checksum;
+};
+
+struct slic_rx_info_mojave {
+	__le32 frame_status;
+	__le16 byte_cnt;
+	__le16 tp_chksum;
+	__le16 ctx_hash;
+	__le16 mac_hash;
+	__le16 buff_lnk;
+};
+
+struct slic_stat_desc {
+	__le32 hnd;
+	__u8 pad[8];
+	__le32 status;
+	__u8 pad2[16];
+};
+
+struct slic_stat_queue {
+	struct slic_stat_desc *descs[SLIC_NUM_STAT_DESC_ARRAYS];
+	dma_addr_t paddr[SLIC_NUM_STAT_DESC_ARRAYS];
+	unsigned int addr_offset[SLIC_NUM_STAT_DESC_ARRAYS];
+	unsigned int active_array;
+	unsigned int len;
+	unsigned int done_idx;
+	size_t mem_size;
+};
+
+struct slic_tx_desc {
+	__le32 hnd;
+	__le32 rsvd;
+	u8 cmd;
+	u8 flags;
+	__le16 rsvd2;
+	__le32 totlen;
+	__le32 paddrl;
+	__le32 paddrh;
+	__le32 len;
+	__le32 type;
+};
+
+struct slic_tx_buffer {
+	struct sk_buff *skb;
+	DEFINE_DMA_UNMAP_ADDR(map_addr);
+	DEFINE_DMA_UNMAP_LEN(map_len);
+	struct slic_tx_desc *desc;
+	dma_addr_t desc_paddr;
+};
+
+struct slic_tx_queue {
+	struct dma_pool *dma_pool;
+	struct slic_tx_buffer *txbuffs;
+	unsigned int len;
+	unsigned int put_idx;
+	unsigned int done_idx;
+};
+
+struct slic_rx_desc {
+	u8 pad[16];
+	__le32 buffer;
+	__le32 length;
+	__le32 status;
+};
+
+struct slic_rx_buffer {
+	struct sk_buff *skb;
+	DEFINE_DMA_UNMAP_ADDR(map_addr);
+	DEFINE_DMA_UNMAP_LEN(map_len);
+	unsigned int addr_offset;
+};
+
+struct slic_rx_queue {
+	struct slic_rx_buffer *rxbuffs;
+	unsigned int len;
+	unsigned int done_idx;
+	unsigned int put_idx;
+};
+
+struct slic_device {
+	struct pci_dev *pdev;
+	struct net_device *netdev;
+	void __iomem *regs;
+	/* upper address setting lock */
+	spinlock_t upper_lock;
+	struct slic_shmem shmem;
+	struct napi_struct napi;
+	struct slic_rx_queue rxq;
+	struct slic_tx_queue txq;
+	struct slic_stat_queue stq;
+	struct slic_stats stats;
+	struct slic_upr_list upr_list;
+	/* link configuration lock */
+	spinlock_t link_lock;
+	bool promisc;
+	int speed;
+	unsigned int duplex;
+	bool is_fiber;
+	unsigned char model;
+};
+
+static inline u32 slic_read(struct slic_device *sdev, unsigned int reg)
+{
+	return ioread32(sdev->regs + reg);
+}
+
+static inline void slic_write(struct slic_device *sdev, unsigned int reg,
+			      u32 val)
+{
+	iowrite32(val, sdev->regs + reg);
+}
+
+static inline void slic_flush_write(struct slic_device *sdev)
+{
+	(void)ioread32(sdev->regs + SLIC_REG_HOSTID);
+}
+
+#endif /* _SLIC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/slicoss.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/slicoss.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/alacritech/slicoss.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alacritech/slicoss.c	2017-02-12 17:39:34.000000000 -0500
@@ -0,0 +1,1868 @@
+/*
+ * Driver for Gigabit Ethernet adapters based on the Session Layer
+ * Interface (SLIC) technology by Alacritech. The driver does not
+ * support the hardware acceleration features provided by these cards.
+ *
+ * Copyright (C) 2016 Lino Sanfilippo <LinoSanfilippo@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/list.h>
+#include <linux/u64_stats_sync.h>
+
+#include "slic.h"
+
+#define DRV_NAME			"slicoss"
+#define DRV_VERSION			"1.0"
+
+static const struct pci_device_id slic_id_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH,
+		     PCI_DEVICE_ID_ALACRITECH_MOJAVE) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH,
+		     PCI_DEVICE_ID_ALACRITECH_OASIS) },
+	{ 0 }
+};
+
+static const char slic_stats_strings[][ETH_GSTRING_LEN] = {
+	"rx_packets",
+	"rx_bytes",
+	"rx_multicasts",
+	"rx_errors",
+	"rx_buff_miss",
+	"rx_tp_csum",
+	"rx_tp_oflow",
+	"rx_tp_hlen",
+	"rx_ip_csum",
+	"rx_ip_len",
+	"rx_ip_hdr_len",
+	"rx_early",
+	"rx_buff_oflow",
+	"rx_lcode",
+	"rx_drbl",
+	"rx_crc",
+	"rx_oflow_802",
+	"rx_uflow_802",
+	"tx_packets",
+	"tx_bytes",
+	"tx_carrier",
+	"tx_dropped",
+	"irq_errs",
+};
+
+static inline int slic_next_queue_idx(unsigned int idx, unsigned int qlen)
+{
+	return (idx + 1) & (qlen - 1);
+}
+
+static inline int slic_get_free_queue_descs(unsigned int put_idx,
+					    unsigned int done_idx,
+					    unsigned int qlen)
+{
+	if (put_idx >= done_idx)
+		return (qlen - (put_idx - done_idx) - 1);
+	return (done_idx - put_idx - 1);
+}
+
+static unsigned int slic_next_compl_idx(struct slic_device *sdev)
+{
+	struct slic_stat_queue *stq = &sdev->stq;
+	unsigned int active = stq->active_array;
+	struct slic_stat_desc *descs;
+	struct slic_stat_desc *stat;
+	unsigned int idx;
+
+	descs = stq->descs[active];
+	stat = &descs[stq->done_idx];
+
+	if (!stat->status)
+		return SLIC_INVALID_STAT_DESC_IDX;
+
+	idx = (le32_to_cpu(stat->hnd) & 0xffff) - 1;
+	/* reset desc */
+	stat->hnd = 0;
+	stat->status = 0;
+
+	stq->done_idx = slic_next_queue_idx(stq->done_idx, stq->len);
+	/* check for wraparound */
+	if (!stq->done_idx) {
+		dma_addr_t paddr = stq->paddr[active];
+
+		slic_write(sdev, SLIC_REG_RBAR, lower_32_bits(paddr) |
+						stq->len);
+		/* make sure new status descriptors are immediately available */
+		slic_flush_write(sdev);
+		active++;
+		active &= (SLIC_NUM_STAT_DESC_ARRAYS - 1);
+		stq->active_array = active;
+	}
+	return idx;
+}
+
+static unsigned int slic_get_free_tx_descs(struct slic_tx_queue *txq)
+{
+	/* ensure tail idx is updated */
+	smp_mb();
+	return slic_get_free_queue_descs(txq->put_idx, txq->done_idx, txq->len);
+}
+
+static unsigned int slic_get_free_rx_descs(struct slic_rx_queue *rxq)
+{
+	return slic_get_free_queue_descs(rxq->put_idx, rxq->done_idx, rxq->len);
+}
+
+static void slic_clear_upr_list(struct slic_upr_list *upr_list)
+{
+	struct slic_upr *upr;
+	struct slic_upr *tmp;
+
+	spin_lock_bh(&upr_list->lock);
+	list_for_each_entry_safe(upr, tmp, &upr_list->list, list) {
+		list_del(&upr->list);
+		kfree(upr);
+	}
+	upr_list->pending = false;
+	spin_unlock_bh(&upr_list->lock);
+}
+
+static void slic_start_upr(struct slic_device *sdev, struct slic_upr *upr)
+{
+	u32 reg;
+
+	reg = (upr->type == SLIC_UPR_CONFIG) ? SLIC_REG_RCONFIG :
+					       SLIC_REG_LSTAT;
+	slic_write(sdev, reg, lower_32_bits(upr->paddr));
+	slic_flush_write(sdev);
+}
+
+static void slic_queue_upr(struct slic_device *sdev, struct slic_upr *upr)
+{
+	struct slic_upr_list *upr_list = &sdev->upr_list;
+	bool pending;
+
+	spin_lock_bh(&upr_list->lock);
+	pending = upr_list->pending;
+	INIT_LIST_HEAD(&upr->list);
+	list_add_tail(&upr->list, &upr_list->list);
+	upr_list->pending = true;
+	spin_unlock_bh(&upr_list->lock);
+
+	if (!pending)
+		slic_start_upr(sdev, upr);
+}
+
+static struct slic_upr *slic_dequeue_upr(struct slic_device *sdev)
+{
+	struct slic_upr_list *upr_list = &sdev->upr_list;
+	struct slic_upr *next_upr = NULL;
+	struct slic_upr *upr = NULL;
+
+	spin_lock_bh(&upr_list->lock);
+	if (!list_empty(&upr_list->list)) {
+		upr = list_first_entry(&upr_list->list, struct slic_upr, list);
+		list_del(&upr->list);
+
+		if (list_empty(&upr_list->list))
+			upr_list->pending = false;
+		else
+			next_upr = list_first_entry(&upr_list->list,
+						    struct slic_upr, list);
+	}
+	spin_unlock_bh(&upr_list->lock);
+	/* trigger processing of the next upr in list */
+	if (next_upr)
+		slic_start_upr(sdev, next_upr);
+
+	return upr;
+}
+
+static int slic_new_upr(struct slic_device *sdev, unsigned int type,
+			dma_addr_t paddr)
+{
+	struct slic_upr *upr;
+
+	upr = kmalloc(sizeof(*upr), GFP_ATOMIC);
+	if (!upr)
+		return -ENOMEM;
+	upr->type = type;
+	upr->paddr = paddr;
+
+	slic_queue_upr(sdev, upr);
+
+	return 0;
+}
+
+static void slic_set_mcast_bit(u64 *mcmask, unsigned char const *addr)
+{
+	u64 mask = *mcmask;
+	u8 crc;
+	/* Get the CRC polynomial for the mac address: we use bits 1-8 (lsb),
+	 * bitwise reversed, msb (= lsb bit 0 before bitrev) is automatically
+	 * discarded.
+	 */
+	crc = ether_crc(ETH_ALEN, addr) >> 23;
+	 /* we only have space on the SLIC for 64 entries */
+	crc &= 0x3F;
+	mask |= (u64)1 << crc;
+	*mcmask = mask;
+}
+
+/* must be called with link_lock held */
+static void slic_configure_rcv(struct slic_device *sdev)
+{
+	u32 val;
+
+	val = SLIC_GRCR_RESET | SLIC_GRCR_ADDRAEN | SLIC_GRCR_RCVEN |
+	      SLIC_GRCR_HASHSIZE << SLIC_GRCR_HASHSIZE_SHIFT | SLIC_GRCR_RCVBAD;
+
+	if (sdev->duplex == DUPLEX_FULL)
+		val |= SLIC_GRCR_CTLEN;
+
+	if (sdev->promisc)
+		val |= SLIC_GRCR_RCVALL;
+
+	slic_write(sdev, SLIC_REG_WRCFG, val);
+}
+
+/* must be called with link_lock held */
+static void slic_configure_xmt(struct slic_device *sdev)
+{
+	u32 val;
+
+	val = SLIC_GXCR_RESET | SLIC_GXCR_XMTEN;
+
+	if (sdev->duplex == DUPLEX_FULL)
+		val |= SLIC_GXCR_PAUSEEN;
+
+	slic_write(sdev, SLIC_REG_WXCFG, val);
+}
+
+/* must be called with link_lock held */
+static void slic_configure_mac(struct slic_device *sdev)
+{
+	u32 val;
+
+	if (sdev->speed == SPEED_1000) {
+		val = SLIC_GMCR_GAPBB_1000 << SLIC_GMCR_GAPBB_SHIFT |
+		      SLIC_GMCR_GAPR1_1000 << SLIC_GMCR_GAPR1_SHIFT |
+		      SLIC_GMCR_GAPR2_1000 << SLIC_GMCR_GAPR2_SHIFT |
+		      SLIC_GMCR_GBIT; /* enable GMII */
+	} else {
+		val = SLIC_GMCR_GAPBB_100 << SLIC_GMCR_GAPBB_SHIFT |
+		      SLIC_GMCR_GAPR1_100 << SLIC_GMCR_GAPR1_SHIFT |
+		      SLIC_GMCR_GAPR2_100 << SLIC_GMCR_GAPR2_SHIFT;
+	}
+
+	if (sdev->duplex == DUPLEX_FULL)
+		val |= SLIC_GMCR_FULLD;
+
+	slic_write(sdev, SLIC_REG_WMCFG, val);
+}
+
+static void slic_configure_link_locked(struct slic_device *sdev, int speed,
+				       unsigned int duplex)
+{
+	struct net_device *dev = sdev->netdev;
+
+	if (sdev->speed == speed && sdev->duplex == duplex)
+		return;
+
+	sdev->speed = speed;
+	sdev->duplex = duplex;
+
+	if (sdev->speed == SPEED_UNKNOWN) {
+		if (netif_carrier_ok(dev))
+			netif_carrier_off(dev);
+	} else {
+		/* (re)configure link settings */
+		slic_configure_mac(sdev);
+		slic_configure_xmt(sdev);
+		slic_configure_rcv(sdev);
+		slic_flush_write(sdev);
+
+		if (!netif_carrier_ok(dev))
+			netif_carrier_on(dev);
+	}
+}
+
+static void slic_configure_link(struct slic_device *sdev, int speed,
+				unsigned int duplex)
+{
+	spin_lock_bh(&sdev->link_lock);
+	slic_configure_link_locked(sdev, speed, duplex);
+	spin_unlock_bh(&sdev->link_lock);
+}
+
+static void slic_set_rx_mode(struct net_device *dev)
+{
+	struct slic_device *sdev = netdev_priv(dev);
+	struct netdev_hw_addr *hwaddr;
+	bool set_promisc;
+	u64 mcmask;
+
+	if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+		/* Turn on all multicast addresses. We have to do this for
+		 * promiscuous mode as well as ALLMCAST mode (it saves the
+		 * microcode from having to keep state about the MAC
+		 * configuration).
+		 */
+		mcmask = ~(u64)0;
+	} else  {
+		mcmask = 0;
+
+		netdev_for_each_mc_addr(hwaddr, dev) {
+			slic_set_mcast_bit(&mcmask, hwaddr->addr);
+		}
+	}
+
+	slic_write(sdev, SLIC_REG_MCASTLOW, lower_32_bits(mcmask));
+	slic_write(sdev, SLIC_REG_MCASTHIGH, upper_32_bits(mcmask));
+
+	set_promisc = !!(dev->flags & IFF_PROMISC);
+
+	spin_lock_bh(&sdev->link_lock);
+	if (sdev->promisc != set_promisc) {
+		sdev->promisc = set_promisc;
+		slic_configure_rcv(sdev);
+		/* make sure writes to receiver cant leak out of the lock */
+		mmiowb();
+	}
+	spin_unlock_bh(&sdev->link_lock);
+}
+
+static void slic_xmit_complete(struct slic_device *sdev)
+{
+	struct slic_tx_queue *txq = &sdev->txq;
+	struct net_device *dev = sdev->netdev;
+	unsigned int idx = txq->done_idx;
+	struct slic_tx_buffer *buff;
+	unsigned int frames = 0;
+	unsigned int bytes = 0;
+
+	/* Limit processing to SLIC_MAX_TX_COMPLETIONS frames to avoid that new
+	 * completions during processing keeps the loop running endlessly.
+	 */
+	do {
+		idx = slic_next_compl_idx(sdev);
+		if (idx == SLIC_INVALID_STAT_DESC_IDX)
+			break;
+
+		txq->done_idx = idx;
+		buff = &txq->txbuffs[idx];
+
+		if (unlikely(!buff->skb)) {
+			netdev_warn(dev,
+				    "no skb found for desc idx %i\n", idx);
+			continue;
+		}
+		dma_unmap_single(&sdev->pdev->dev,
+				 dma_unmap_addr(buff, map_addr),
+				 dma_unmap_len(buff, map_len), DMA_TO_DEVICE);
+
+		bytes += buff->skb->len;
+		frames++;
+
+		dev_kfree_skb_any(buff->skb);
+		buff->skb = NULL;
+	} while (frames < SLIC_MAX_TX_COMPLETIONS);
+	/* make sure xmit sees the new value for done_idx */
+	smp_wmb();
+
+	u64_stats_update_begin(&sdev->stats.syncp);
+	sdev->stats.tx_bytes += bytes;
+	sdev->stats.tx_packets += frames;
+	u64_stats_update_end(&sdev->stats.syncp);
+
+	netif_tx_lock(dev);
+	if (netif_queue_stopped(dev) &&
+	    (slic_get_free_tx_descs(txq) >= SLIC_MIN_TX_WAKEUP_DESCS))
+		netif_wake_queue(dev);
+	netif_tx_unlock(dev);
+}
+
+static void slic_refill_rx_queue(struct slic_device *sdev, gfp_t gfp)
+{
+	const unsigned int ALIGN_MASK = SLIC_RX_BUFF_ALIGN - 1;
+	unsigned int maplen = SLIC_RX_BUFF_SIZE;
+	struct slic_rx_queue *rxq = &sdev->rxq;
+	struct net_device *dev = sdev->netdev;
+	struct slic_rx_buffer *buff;
+	struct slic_rx_desc *desc;
+	unsigned int misalign;
+	unsigned int offset;
+	struct sk_buff *skb;
+	dma_addr_t paddr;
+
+	while (slic_get_free_rx_descs(rxq) > SLIC_MAX_REQ_RX_DESCS) {
+		skb = alloc_skb(maplen + ALIGN_MASK, gfp);
+		if (!skb)
+			break;
+
+		paddr = dma_map_single(&sdev->pdev->dev, skb->data, maplen,
+				       DMA_FROM_DEVICE);
+		if (dma_mapping_error(&sdev->pdev->dev, paddr)) {
+			netdev_err(dev, "mapping rx packet failed\n");
+			/* drop skb */
+			dev_kfree_skb_any(skb);
+			break;
+		}
+		/* ensure head buffer descriptors are 256 byte aligned */
+		offset = 0;
+		misalign = paddr & ALIGN_MASK;
+		if (misalign) {
+			offset = SLIC_RX_BUFF_ALIGN - misalign;
+			skb_reserve(skb, offset);
+		}
+		/* the HW expects dma chunks for descriptor + frame data */
+		desc = (struct slic_rx_desc *)skb->data;
+		/* temporarily sync descriptor for CPU to clear status */
+		dma_sync_single_for_cpu(&sdev->pdev->dev, paddr,
+					offset + sizeof(*desc),
+					DMA_FROM_DEVICE);
+		desc->status = 0;
+		/* return it to HW again */
+		dma_sync_single_for_device(&sdev->pdev->dev, paddr,
+					   offset + sizeof(*desc),
+					   DMA_FROM_DEVICE);
+
+		buff = &rxq->rxbuffs[rxq->put_idx];
+		buff->skb = skb;
+		dma_unmap_addr_set(buff, map_addr, paddr);
+		dma_unmap_len_set(buff, map_len, maplen);
+		buff->addr_offset = offset;
+		/* complete write to descriptor before it is handed to HW */
+		wmb();
+		/* head buffer descriptors are placed immediately before skb */
+		slic_write(sdev, SLIC_REG_HBAR, lower_32_bits(paddr) + offset);
+		rxq->put_idx = slic_next_queue_idx(rxq->put_idx, rxq->len);
+	}
+}
+
+static void slic_handle_frame_error(struct slic_device *sdev,
+				    struct sk_buff *skb)
+{
+	struct slic_stats *stats = &sdev->stats;
+
+	if (sdev->model == SLIC_MODEL_OASIS) {
+		struct slic_rx_info_oasis *info;
+		u32 status_b;
+		u32 status;
+
+		info = (struct slic_rx_info_oasis *)skb->data;
+		status = le32_to_cpu(info->frame_status);
+		status_b = le32_to_cpu(info->frame_status_b);
+		/* transport layer */
+		if (status_b & SLIC_VRHSTATB_TPCSUM)
+			SLIC_INC_STATS_COUNTER(stats, rx_tpcsum);
+		if (status & SLIC_VRHSTAT_TPOFLO)
+			SLIC_INC_STATS_COUNTER(stats, rx_tpoflow);
+		if (status_b & SLIC_VRHSTATB_TPHLEN)
+			SLIC_INC_STATS_COUNTER(stats, rx_tphlen);
+		/* ip layer */
+		if (status_b & SLIC_VRHSTATB_IPCSUM)
+			SLIC_INC_STATS_COUNTER(stats, rx_ipcsum);
+		if (status_b & SLIC_VRHSTATB_IPLERR)
+			SLIC_INC_STATS_COUNTER(stats, rx_iplen);
+		if (status_b & SLIC_VRHSTATB_IPHERR)
+			SLIC_INC_STATS_COUNTER(stats, rx_iphlen);
+		/* link layer */
+		if (status_b & SLIC_VRHSTATB_RCVE)
+			SLIC_INC_STATS_COUNTER(stats, rx_early);
+		if (status_b & SLIC_VRHSTATB_BUFF)
+			SLIC_INC_STATS_COUNTER(stats, rx_buffoflow);
+		if (status_b & SLIC_VRHSTATB_CODE)
+			SLIC_INC_STATS_COUNTER(stats, rx_lcode);
+		if (status_b & SLIC_VRHSTATB_DRBL)
+			SLIC_INC_STATS_COUNTER(stats, rx_drbl);
+		if (status_b & SLIC_VRHSTATB_CRC)
+			SLIC_INC_STATS_COUNTER(stats, rx_crc);
+		if (status & SLIC_VRHSTAT_802OE)
+			SLIC_INC_STATS_COUNTER(stats, rx_oflow802);
+		if (status_b & SLIC_VRHSTATB_802UE)
+			SLIC_INC_STATS_COUNTER(stats, rx_uflow802);
+		if (status_b & SLIC_VRHSTATB_CARRE)
+			SLIC_INC_STATS_COUNTER(stats, tx_carrier);
+	} else { /* mojave */
+		struct slic_rx_info_mojave *info;
+		u32 status;
+
+		info = (struct slic_rx_info_mojave *)skb->data;
+		status = le32_to_cpu(info->frame_status);
+		/* transport layer */
+		if (status & SLIC_VGBSTAT_XPERR) {
+			u32 xerr = status >> SLIC_VGBSTAT_XERRSHFT;
+
+			if (xerr == SLIC_VGBSTAT_XCSERR)
+				SLIC_INC_STATS_COUNTER(stats, rx_tpcsum);
+			if (xerr == SLIC_VGBSTAT_XUFLOW)
+				SLIC_INC_STATS_COUNTER(stats, rx_tpoflow);
+			if (xerr == SLIC_VGBSTAT_XHLEN)
+				SLIC_INC_STATS_COUNTER(stats, rx_tphlen);
+		}
+		/* ip layer */
+		if (status & SLIC_VGBSTAT_NETERR) {
+			u32 nerr = status >> SLIC_VGBSTAT_NERRSHFT &
+				   SLIC_VGBSTAT_NERRMSK;
+
+			if (nerr == SLIC_VGBSTAT_NCSERR)
+				SLIC_INC_STATS_COUNTER(stats, rx_ipcsum);
+			if (nerr == SLIC_VGBSTAT_NUFLOW)
+				SLIC_INC_STATS_COUNTER(stats, rx_iplen);
+			if (nerr == SLIC_VGBSTAT_NHLEN)
+				SLIC_INC_STATS_COUNTER(stats, rx_iphlen);
+		}
+		/* link layer */
+		if (status & SLIC_VGBSTAT_LNKERR) {
+			u32 lerr = status & SLIC_VGBSTAT_LERRMSK;
+
+			if (lerr == SLIC_VGBSTAT_LDEARLY)
+				SLIC_INC_STATS_COUNTER(stats, rx_early);
+			if (lerr == SLIC_VGBSTAT_LBOFLO)
+				SLIC_INC_STATS_COUNTER(stats, rx_buffoflow);
+			if (lerr == SLIC_VGBSTAT_LCODERR)
+				SLIC_INC_STATS_COUNTER(stats, rx_lcode);
+			if (lerr == SLIC_VGBSTAT_LDBLNBL)
+				SLIC_INC_STATS_COUNTER(stats, rx_drbl);
+			if (lerr == SLIC_VGBSTAT_LCRCERR)
+				SLIC_INC_STATS_COUNTER(stats, rx_crc);
+			if (lerr == SLIC_VGBSTAT_LOFLO)
+				SLIC_INC_STATS_COUNTER(stats, rx_oflow802);
+			if (lerr == SLIC_VGBSTAT_LUFLO)
+				SLIC_INC_STATS_COUNTER(stats, rx_uflow802);
+		}
+	}
+	SLIC_INC_STATS_COUNTER(stats, rx_errors);
+}
+
+static void slic_handle_receive(struct slic_device *sdev, unsigned int todo,
+				unsigned int *done)
+{
+	struct slic_rx_queue *rxq = &sdev->rxq;
+	struct net_device *dev = sdev->netdev;
+	struct slic_rx_buffer *buff;
+	struct slic_rx_desc *desc;
+	unsigned int frames = 0;
+	unsigned int bytes = 0;
+	struct sk_buff *skb;
+	u32 status;
+	u32 len;
+
+	while (todo && (rxq->done_idx != rxq->put_idx)) {
+		buff = &rxq->rxbuffs[rxq->done_idx];
+
+		skb = buff->skb;
+		if (!skb)
+			break;
+
+		desc = (struct slic_rx_desc *)skb->data;
+
+		dma_sync_single_for_cpu(&sdev->pdev->dev,
+					dma_unmap_addr(buff, map_addr),
+					buff->addr_offset + sizeof(*desc),
+					DMA_FROM_DEVICE);
+
+		status = le32_to_cpu(desc->status);
+		if (!(status & SLIC_IRHDDR_SVALID)) {
+			dma_sync_single_for_device(&sdev->pdev->dev,
+						   dma_unmap_addr(buff,
+								  map_addr),
+						   buff->addr_offset +
+						   sizeof(*desc),
+						   DMA_FROM_DEVICE);
+			break;
+		}
+
+		buff->skb = NULL;
+
+		dma_unmap_single(&sdev->pdev->dev,
+				 dma_unmap_addr(buff, map_addr),
+				 dma_unmap_len(buff, map_len),
+				 DMA_FROM_DEVICE);
+
+		/* skip rx descriptor that is placed before the frame data */
+		skb_reserve(skb, SLIC_RX_BUFF_HDR_SIZE);
+
+		if (unlikely(status & SLIC_IRHDDR_ERR)) {
+			slic_handle_frame_error(sdev, skb);
+			dev_kfree_skb_any(skb);
+		} else {
+			struct ethhdr *eh = (struct ethhdr *)skb->data;
+
+			if (is_multicast_ether_addr(eh->h_dest))
+				SLIC_INC_STATS_COUNTER(&sdev->stats, rx_mcasts);
+
+			len = le32_to_cpu(desc->length) & SLIC_IRHDDR_FLEN_MSK;
+			skb_put(skb, len);
+			skb->protocol = eth_type_trans(skb, dev);
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+			napi_gro_receive(&sdev->napi, skb);
+
+			bytes += len;
+			frames++;
+		}
+		rxq->done_idx = slic_next_queue_idx(rxq->done_idx, rxq->len);
+		todo--;
+	}
+
+	u64_stats_update_begin(&sdev->stats.syncp);
+	sdev->stats.rx_bytes += bytes;
+	sdev->stats.rx_packets += frames;
+	u64_stats_update_end(&sdev->stats.syncp);
+
+	slic_refill_rx_queue(sdev, GFP_ATOMIC);
+}
+
+static void slic_handle_link_irq(struct slic_device *sdev)
+{
+	struct slic_shmem *sm = &sdev->shmem;
+	struct slic_shmem_data *sm_data = sm->shmem_data;
+	unsigned int duplex;
+	int speed;
+	u32 link;
+
+	link = le32_to_cpu(sm_data->link);
+
+	if (link & SLIC_GIG_LINKUP) {
+		if (link & SLIC_GIG_SPEED_1000)
+			speed = SPEED_1000;
+		else if (link & SLIC_GIG_SPEED_100)
+			speed = SPEED_100;
+		else
+			speed = SPEED_10;
+
+		duplex = (link & SLIC_GIG_FULLDUPLEX) ? DUPLEX_FULL :
+							DUPLEX_HALF;
+	} else {
+		duplex = DUPLEX_UNKNOWN;
+		speed = SPEED_UNKNOWN;
+	}
+	slic_configure_link(sdev, speed, duplex);
+}
+
+static void slic_handle_upr_irq(struct slic_device *sdev, u32 irqs)
+{
+	struct slic_upr *upr;
+
+	/* remove upr that caused this irq (always the first entry in list) */
+	upr = slic_dequeue_upr(sdev);
+	if (!upr) {
+		netdev_warn(sdev->netdev, "no upr found on list\n");
+		return;
+	}
+
+	if (upr->type == SLIC_UPR_LSTAT) {
+		if (unlikely(irqs & SLIC_ISR_UPCERR_MASK)) {
+			/* try again */
+			slic_queue_upr(sdev, upr);
+			return;
+		}
+		slic_handle_link_irq(sdev);
+	}
+	kfree(upr);
+}
+
+static int slic_handle_link_change(struct slic_device *sdev)
+{
+	return slic_new_upr(sdev, SLIC_UPR_LSTAT, sdev->shmem.link_paddr);
+}
+
+static void slic_handle_err_irq(struct slic_device *sdev, u32 isr)
+{
+	struct slic_stats *stats = &sdev->stats;
+
+	if (isr & SLIC_ISR_RMISS)
+		SLIC_INC_STATS_COUNTER(stats, rx_buff_miss);
+	if (isr & SLIC_ISR_XDROP)
+		SLIC_INC_STATS_COUNTER(stats, tx_dropped);
+	if (!(isr & (SLIC_ISR_RMISS | SLIC_ISR_XDROP)))
+		SLIC_INC_STATS_COUNTER(stats, irq_errs);
+}
+
+static void slic_handle_irq(struct slic_device *sdev, u32 isr,
+			    unsigned int todo, unsigned int *done)
+{
+	if (isr & SLIC_ISR_ERR)
+		slic_handle_err_irq(sdev, isr);
+
+	if (isr & SLIC_ISR_LEVENT)
+		slic_handle_link_change(sdev);
+
+	if (isr & SLIC_ISR_UPC_MASK)
+		slic_handle_upr_irq(sdev, isr);
+
+	if (isr & SLIC_ISR_RCV)
+		slic_handle_receive(sdev, todo, done);
+
+	if (isr & SLIC_ISR_CMD)
+		slic_xmit_complete(sdev);
+}
+
+static int slic_poll(struct napi_struct *napi, int todo)
+{
+	struct slic_device *sdev = container_of(napi, struct slic_device, napi);
+	struct slic_shmem *sm = &sdev->shmem;
+	struct slic_shmem_data *sm_data = sm->shmem_data;
+	u32 isr = le32_to_cpu(sm_data->isr);
+	int done = 0;
+
+	slic_handle_irq(sdev, isr, todo, &done);
+
+	if (done < todo) {
+		napi_complete_done(napi, done);
+		/* reenable irqs */
+		sm_data->isr = 0;
+		/* make sure sm_data->isr is cleard before irqs are reenabled */
+		wmb();
+		slic_write(sdev, SLIC_REG_ISR, 0);
+		slic_flush_write(sdev);
+	}
+
+	return done;
+}
+
+static irqreturn_t slic_irq(int irq, void *dev_id)
+{
+	struct slic_device *sdev = dev_id;
+	struct slic_shmem *sm = &sdev->shmem;
+	struct slic_shmem_data *sm_data = sm->shmem_data;
+
+	slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_MASK);
+	slic_flush_write(sdev);
+	/* make sure sm_data->isr is read after ICR_INT_MASK is set */
+	wmb();
+
+	if (!sm_data->isr) {
+		dma_rmb();
+		/* spurious interrupt */
+		slic_write(sdev, SLIC_REG_ISR, 0);
+		slic_flush_write(sdev);
+		return IRQ_NONE;
+	}
+
+	napi_schedule_irqoff(&sdev->napi);
+
+	return IRQ_HANDLED;
+}
+
+static void slic_card_reset(struct slic_device *sdev)
+{
+	u16 cmd;
+
+	slic_write(sdev, SLIC_REG_RESET, SLIC_RESET_MAGIC);
+	/* flush write by means of config space */
+	pci_read_config_word(sdev->pdev, PCI_COMMAND, &cmd);
+	mdelay(1);
+}
+
+static int slic_init_stat_queue(struct slic_device *sdev)
+{
+	const unsigned int DESC_ALIGN_MASK = SLIC_STATS_DESC_ALIGN - 1;
+	struct slic_stat_queue *stq = &sdev->stq;
+	struct slic_stat_desc *descs;
+	unsigned int misalign;
+	unsigned int offset;
+	dma_addr_t paddr;
+	size_t size;
+	int err;
+	int i;
+
+	stq->len = SLIC_NUM_STAT_DESCS;
+	stq->active_array = 0;
+	stq->done_idx = 0;
+
+	size = stq->len * sizeof(*descs) + DESC_ALIGN_MASK;
+
+	for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
+		descs = dma_zalloc_coherent(&sdev->pdev->dev, size, &paddr,
+					    GFP_KERNEL);
+		if (!descs) {
+			netdev_err(sdev->netdev,
+				   "failed to allocate status descriptors\n");
+			err = -ENOMEM;
+			goto free_descs;
+		}
+		/* ensure correct alignment */
+		offset = 0;
+		misalign = paddr & DESC_ALIGN_MASK;
+		if (misalign) {
+			offset = SLIC_STATS_DESC_ALIGN - misalign;
+			descs += offset;
+			paddr += offset;
+		}
+
+		slic_write(sdev, SLIC_REG_RBAR, lower_32_bits(paddr) |
+						stq->len);
+		stq->descs[i] = descs;
+		stq->paddr[i] = paddr;
+		stq->addr_offset[i] = offset;
+	}
+
+	stq->mem_size = size;
+
+	return 0;
+
+free_descs:
+	while (i--) {
+		dma_free_coherent(&sdev->pdev->dev, stq->mem_size,
+				  stq->descs[i] - stq->addr_offset[i],
+				  stq->paddr[i] - stq->addr_offset[i]);
+	}
+
+	return err;
+}
+
+static void slic_free_stat_queue(struct slic_device *sdev)
+{
+	struct slic_stat_queue *stq = &sdev->stq;
+	int i;
+
+	for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
+		dma_free_coherent(&sdev->pdev->dev, stq->mem_size,
+				  stq->descs[i] - stq->addr_offset[i],
+				  stq->paddr[i] - stq->addr_offset[i]);
+	}
+}
+
+static int slic_init_tx_queue(struct slic_device *sdev)
+{
+	struct slic_tx_queue *txq = &sdev->txq;
+	struct slic_tx_buffer *buff;
+	struct slic_tx_desc *desc;
+	unsigned int i;
+	int err;
+
+	txq->len = SLIC_NUM_TX_DESCS;
+	txq->put_idx = 0;
+	txq->done_idx = 0;
+
+	txq->txbuffs = kcalloc(txq->len, sizeof(*buff), GFP_KERNEL);
+	if (!txq->txbuffs)
+		return -ENOMEM;
+
+	txq->dma_pool = dma_pool_create("slic_pool", &sdev->pdev->dev,
+					sizeof(*desc), SLIC_TX_DESC_ALIGN,
+					4096);
+	if (!txq->dma_pool) {
+		err = -ENOMEM;
+		netdev_err(sdev->netdev, "failed to create dma pool\n");
+		goto free_buffs;
+	}
+
+	for (i = 0; i < txq->len; i++) {
+		buff = &txq->txbuffs[i];
+		desc = dma_pool_zalloc(txq->dma_pool, GFP_KERNEL,
+				       &buff->desc_paddr);
+		if (!desc) {
+			netdev_err(sdev->netdev,
+				   "failed to alloc pool chunk (%i)\n", i);
+			err = -ENOMEM;
+			goto free_descs;
+		}
+
+		desc->hnd = cpu_to_le32((u32)(i + 1));
+		desc->cmd = SLIC_CMD_XMT_REQ;
+		desc->flags = 0;
+		desc->type = cpu_to_le32(SLIC_CMD_TYPE_DUMB);
+		buff->desc = desc;
+	}
+
+	return 0;
+
+free_descs:
+	while (i--) {
+		buff = &txq->txbuffs[i];
+		dma_pool_free(txq->dma_pool, buff->desc, buff->desc_paddr);
+	}
+	dma_pool_destroy(txq->dma_pool);
+
+free_buffs:
+	kfree(txq->txbuffs);
+
+	return err;
+}
+
+static void slic_free_tx_queue(struct slic_device *sdev)
+{
+	struct slic_tx_queue *txq = &sdev->txq;
+	struct slic_tx_buffer *buff;
+	unsigned int i;
+
+	for (i = 0; i < txq->len; i++) {
+		buff = &txq->txbuffs[i];
+		dma_pool_free(txq->dma_pool, buff->desc, buff->desc_paddr);
+		if (!buff->skb)
+			continue;
+
+		dma_unmap_single(&sdev->pdev->dev,
+				 dma_unmap_addr(buff, map_addr),
+				 dma_unmap_len(buff, map_len), DMA_TO_DEVICE);
+		consume_skb(buff->skb);
+	}
+	dma_pool_destroy(txq->dma_pool);
+
+	kfree(txq->txbuffs);
+}
+
+static int slic_init_rx_queue(struct slic_device *sdev)
+{
+	struct slic_rx_queue *rxq = &sdev->rxq;
+	struct slic_rx_buffer *buff;
+
+	rxq->len = SLIC_NUM_RX_LES;
+	rxq->done_idx = 0;
+	rxq->put_idx = 0;
+
+	buff = kcalloc(rxq->len, sizeof(*buff), GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	rxq->rxbuffs = buff;
+	slic_refill_rx_queue(sdev, GFP_KERNEL);
+
+	return 0;
+}
+
+static void slic_free_rx_queue(struct slic_device *sdev)
+{
+	struct slic_rx_queue *rxq = &sdev->rxq;
+	struct slic_rx_buffer *buff;
+	unsigned int i;
+
+	/* free rx buffers */
+	for (i = 0; i < rxq->len; i++) {
+		buff = &rxq->rxbuffs[i];
+
+		if (!buff->skb)
+			continue;
+
+		dma_unmap_single(&sdev->pdev->dev,
+				 dma_unmap_addr(buff, map_addr),
+				 dma_unmap_len(buff, map_len),
+				 DMA_FROM_DEVICE);
+		consume_skb(buff->skb);
+	}
+	kfree(rxq->rxbuffs);
+}
+
+static void slic_set_link_autoneg(struct slic_device *sdev)
+{
+	unsigned int subid = sdev->pdev->subsystem_device;
+	u32 val;
+
+	if (sdev->is_fiber) {
+		/* We've got a fiber gigabit interface, and register 4 is
+		 * different in fiber mode than in copper mode.
+		 */
+		/* advertise FD only @1000 Mb */
+		val = MII_ADVERTISE << 16 | ADVERTISE_1000XFULL |
+		      ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+		/* enable PAUSE frames */
+		slic_write(sdev, SLIC_REG_WPHY, val);
+		/* reset phy, enable auto-neg  */
+		val = MII_BMCR << 16 | BMCR_RESET | BMCR_ANENABLE |
+		      BMCR_ANRESTART;
+		slic_write(sdev, SLIC_REG_WPHY, val);
+	} else {	/* copper gigabit */
+		/* We've got a copper gigabit interface, and register 4 is
+		 * different in copper mode than in fiber mode.
+		 */
+		/* advertise 10/100 Mb modes   */
+		val = MII_ADVERTISE << 16 | ADVERTISE_100FULL |
+		      ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF;
+		/* enable PAUSE frames  */
+		val |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+		/* required by the Cicada PHY  */
+		val |= ADVERTISE_CSMA;
+		slic_write(sdev, SLIC_REG_WPHY, val);
+
+		/* advertise FD only @1000 Mb  */
+		val = MII_CTRL1000 << 16 | ADVERTISE_1000FULL;
+		slic_write(sdev, SLIC_REG_WPHY, val);
+
+		if (subid != PCI_SUBDEVICE_ID_ALACRITECH_CICADA) {
+			 /* if a Marvell PHY enable auto crossover */
+			val = SLIC_MIICR_REG_16 | SLIC_MRV_REG16_XOVERON;
+			slic_write(sdev, SLIC_REG_WPHY, val);
+
+			/* reset phy, enable auto-neg  */
+			val = MII_BMCR << 16 | BMCR_RESET | BMCR_ANENABLE |
+			      BMCR_ANRESTART;
+			slic_write(sdev, SLIC_REG_WPHY, val);
+		} else {
+			/* enable and restart auto-neg (don't reset)  */
+			val = MII_BMCR << 16 | BMCR_ANENABLE | BMCR_ANRESTART;
+			slic_write(sdev, SLIC_REG_WPHY, val);
+		}
+	}
+}
+
+static void slic_set_mac_address(struct slic_device *sdev)
+{
+	u8 *addr = sdev->netdev->dev_addr;
+	u32 val;
+
+	val = addr[5] | addr[4] << 8 | addr[3] << 16 | addr[2] << 24;
+
+	slic_write(sdev, SLIC_REG_WRADDRAL, val);
+	slic_write(sdev, SLIC_REG_WRADDRBL, val);
+
+	val = addr[0] << 8 | addr[1];
+
+	slic_write(sdev, SLIC_REG_WRADDRAH, val);
+	slic_write(sdev, SLIC_REG_WRADDRBH, val);
+	slic_flush_write(sdev);
+}
+
+static u32 slic_read_dword_from_firmware(const struct firmware *fw, int *offset)
+{
+	int idx = *offset;
+	__le32 val;
+
+	memcpy(&val, fw->data + *offset, sizeof(val));
+	idx += 4;
+	*offset = idx;
+
+	return le32_to_cpu(val);
+}
+
+/*(DEBLOBBED)*/
+
+static int slic_load_rcvseq_firmware(struct slic_device *sdev)
+{
+	const struct firmware *fw;
+	const char *file;
+	u32 codelen;
+	int idx = 0;
+	u32 instr;
+	u32 addr;
+	int err;
+
+	file = (sdev->model == SLIC_MODEL_OASIS) ?  SLIC_RCV_FIRMWARE_OASIS :
+						    SLIC_RCV_FIRMWARE_MOJAVE;
+	err = reject_firmware(&fw, file, &sdev->pdev->dev);
+	if (err) {
+		dev_err(&sdev->pdev->dev,
+			"failed to load receive sequencer firmware %s\n", file);
+		return err;
+	}
+	/* Do an initial sanity check concerning firmware size now. A further
+	 * check follows below.
+	 */
+	if (fw->size < SLIC_FIRMWARE_MIN_SIZE) {
+		dev_err(&sdev->pdev->dev,
+			"invalid firmware size %zu (min %u expected)\n",
+			fw->size, SLIC_FIRMWARE_MIN_SIZE);
+		err = -EINVAL;
+		goto release;
+	}
+
+	codelen = slic_read_dword_from_firmware(fw, &idx);
+
+	/* do another sanity check against firmware size */
+	if ((codelen + 4) > fw->size) {
+		dev_err(&sdev->pdev->dev,
+			"invalid rcv-sequencer firmware size %zu\n", fw->size);
+		err = -EINVAL;
+		goto release;
+	}
+
+	/* download sequencer code to card */
+	slic_write(sdev, SLIC_REG_RCV_WCS, SLIC_RCVWCS_BEGIN);
+	for (addr = 0; addr < codelen; addr++) {
+		__le32 val;
+		/* write out instruction address */
+		slic_write(sdev, SLIC_REG_RCV_WCS, addr);
+
+		instr = slic_read_dword_from_firmware(fw, &idx);
+		/* write out the instruction data low addr */
+		slic_write(sdev, SLIC_REG_RCV_WCS, instr);
+
+		val = (__le32)fw->data[idx];
+		instr = le32_to_cpu(val);
+		idx++;
+		/* write out the instruction data high addr */
+		slic_write(sdev, SLIC_REG_RCV_WCS, instr);
+	}
+	/* finish download */
+	slic_write(sdev, SLIC_REG_RCV_WCS, SLIC_RCVWCS_FINISH);
+	slic_flush_write(sdev);
+release:
+	release_firmware(fw);
+
+	return err;
+}
+
+/*(DEBLOBBED)*/
+
+static int slic_load_firmware(struct slic_device *sdev)
+{
+	u32 sectstart[SLIC_FIRMWARE_MAX_SECTIONS];
+	u32 sectsize[SLIC_FIRMWARE_MAX_SECTIONS];
+	const struct firmware *fw;
+	unsigned int datalen;
+	const char *file;
+	int code_start;
+	unsigned int i;
+	u32 numsects;
+	int idx = 0;
+	u32 sect;
+	u32 instr;
+	u32 addr;
+	u32 base;
+	int err;
+
+	file = (sdev->model == SLIC_MODEL_OASIS) ?  SLIC_FIRMWARE_OASIS :
+						    SLIC_FIRMWARE_MOJAVE;
+	err = reject_firmware(&fw, file, &sdev->pdev->dev);
+	if (err) {
+		dev_err(&sdev->pdev->dev, "failed to load firmware %s\n", file);
+		return err;
+	}
+	/* Do an initial sanity check concerning firmware size now. A further
+	 * check follows below.
+	 */
+	if (fw->size < SLIC_FIRMWARE_MIN_SIZE) {
+		dev_err(&sdev->pdev->dev,
+			"invalid firmware size %zu (min is %u)\n", fw->size,
+			SLIC_FIRMWARE_MIN_SIZE);
+		err = -EINVAL;
+		goto release;
+	}
+
+	numsects = slic_read_dword_from_firmware(fw, &idx);
+	if (numsects == 0 || numsects > SLIC_FIRMWARE_MAX_SECTIONS) {
+		dev_err(&sdev->pdev->dev,
+			"invalid number of sections in firmware: %u", numsects);
+		err = -EINVAL;
+		goto release;
+	}
+
+	datalen = numsects * 8 + 4;
+	for (i = 0; i < numsects; i++) {
+		sectsize[i] = slic_read_dword_from_firmware(fw, &idx);
+		datalen += sectsize[i];
+	}
+
+	/* do another sanity check against firmware size */
+	if (datalen > fw->size) {
+		dev_err(&sdev->pdev->dev,
+			"invalid firmware size %zu (expected >= %u)\n",
+			fw->size, datalen);
+		err = -EINVAL;
+		goto release;
+	}
+	/* get sections */
+	for (i = 0; i < numsects; i++)
+		sectstart[i] = slic_read_dword_from_firmware(fw, &idx);
+
+	code_start = idx;
+	instr = slic_read_dword_from_firmware(fw, &idx);
+
+	for (sect = 0; sect < numsects; sect++) {
+		unsigned int ssize = sectsize[sect] >> 3;
+
+		base = sectstart[sect];
+
+		for (addr = 0; addr < ssize; addr++) {
+			/* write out instruction address */
+			slic_write(sdev, SLIC_REG_WCS, base + addr);
+			/* write out instruction to low addr */
+			slic_write(sdev, SLIC_REG_WCS, instr);
+			instr = slic_read_dword_from_firmware(fw, &idx);
+			/* write out instruction to high addr */
+			slic_write(sdev, SLIC_REG_WCS, instr);
+			instr = slic_read_dword_from_firmware(fw, &idx);
+		}
+	}
+
+	idx = code_start;
+
+	for (sect = 0; sect < numsects; sect++) {
+		unsigned int ssize = sectsize[sect] >> 3;
+
+		instr = slic_read_dword_from_firmware(fw, &idx);
+		base = sectstart[sect];
+		if (base < 0x8000)
+			continue;
+
+		for (addr = 0; addr < ssize; addr++) {
+			/* write out instruction address */
+			slic_write(sdev, SLIC_REG_WCS,
+				   SLIC_WCS_COMPARE | (base + addr));
+			/* write out instruction to low addr */
+			slic_write(sdev, SLIC_REG_WCS, instr);
+			instr = slic_read_dword_from_firmware(fw, &idx);
+			/* write out instruction to high addr */
+			slic_write(sdev, SLIC_REG_WCS, instr);
+			instr = slic_read_dword_from_firmware(fw, &idx);
+		}
+	}
+	slic_flush_write(sdev);
+	mdelay(10);
+	/* everything OK, kick off the card */
+	slic_write(sdev, SLIC_REG_WCS, SLIC_WCS_START);
+	slic_flush_write(sdev);
+	/* wait long enough for ucode to init card and reach the mainloop */
+	mdelay(20);
+release:
+	release_firmware(fw);
+
+	return err;
+}
+
+static int slic_init_shmem(struct slic_device *sdev)
+{
+	struct slic_shmem *sm = &sdev->shmem;
+	struct slic_shmem_data *sm_data;
+	dma_addr_t paddr;
+
+	sm_data = dma_zalloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
+				      &paddr, GFP_KERNEL);
+	if (!sm_data) {
+		dev_err(&sdev->pdev->dev, "failed to allocate shared memory\n");
+		return -ENOMEM;
+	}
+
+	sm->shmem_data = sm_data;
+	sm->isr_paddr = paddr;
+	sm->link_paddr = paddr + offsetof(struct slic_shmem_data, link);
+
+	return 0;
+}
+
+static void slic_free_shmem(struct slic_device *sdev)
+{
+	struct slic_shmem *sm = &sdev->shmem;
+	struct slic_shmem_data *sm_data = sm->shmem_data;
+
+	dma_free_coherent(&sdev->pdev->dev, sizeof(*sm_data), sm_data,
+			  sm->isr_paddr);
+}
+
+static int slic_init_iface(struct slic_device *sdev)
+{
+	struct slic_shmem *sm = &sdev->shmem;
+	int err;
+
+	sdev->upr_list.pending = false;
+
+	err = slic_init_shmem(sdev);
+	if (err) {
+		netdev_err(sdev->netdev, "failed to init shared memory\n");
+		return err;
+	}
+
+	err = slic_load_firmware(sdev);
+	if (err) {
+		netdev_err(sdev->netdev, "failed to load firmware\n");
+		goto free_sm;
+	}
+
+	err = slic_load_rcvseq_firmware(sdev);
+	if (err) {
+		netdev_err(sdev->netdev,
+			   "failed to load firmware for receive sequencer\n");
+		goto free_sm;
+	}
+
+	slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+	slic_flush_write(sdev);
+	mdelay(1);
+
+	err = slic_init_rx_queue(sdev);
+	if (err) {
+		netdev_err(sdev->netdev, "failed to init rx queue: %u\n", err);
+		goto free_sm;
+	}
+
+	err = slic_init_tx_queue(sdev);
+	if (err) {
+		netdev_err(sdev->netdev, "failed to init tx queue: %u\n", err);
+		goto free_rxq;
+	}
+
+	err = slic_init_stat_queue(sdev);
+	if (err) {
+		netdev_err(sdev->netdev, "failed to init status queue: %u\n",
+			   err);
+		goto free_txq;
+	}
+
+	slic_write(sdev, SLIC_REG_ISP, lower_32_bits(sm->isr_paddr));
+	napi_enable(&sdev->napi);
+	/* disable irq mitigation */
+	slic_write(sdev, SLIC_REG_INTAGG, 0);
+	slic_write(sdev, SLIC_REG_ISR, 0);
+	slic_flush_write(sdev);
+
+	slic_set_mac_address(sdev);
+
+	spin_lock_bh(&sdev->link_lock);
+	sdev->duplex = DUPLEX_UNKNOWN;
+	sdev->speed = SPEED_UNKNOWN;
+	spin_unlock_bh(&sdev->link_lock);
+
+	slic_set_link_autoneg(sdev);
+
+	err = request_irq(sdev->pdev->irq, slic_irq, IRQF_SHARED, DRV_NAME,
+			  sdev);
+	if (err) {
+		netdev_err(sdev->netdev, "failed to request irq: %u\n", err);
+		goto disable_napi;
+	}
+
+	slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_ON);
+	slic_flush_write(sdev);
+	/* request initial link status */
+	err = slic_handle_link_change(sdev);
+	if (err)
+		netdev_warn(sdev->netdev,
+			    "failed to set initial link state: %u\n", err);
+	return 0;
+
+disable_napi:
+	napi_disable(&sdev->napi);
+	slic_free_stat_queue(sdev);
+free_txq:
+	slic_free_tx_queue(sdev);
+free_rxq:
+	slic_free_rx_queue(sdev);
+free_sm:
+	slic_free_shmem(sdev);
+	slic_card_reset(sdev);
+
+	return err;
+}
+
+static int slic_open(struct net_device *dev)
+{
+	struct slic_device *sdev = netdev_priv(dev);
+	int err;
+
+	netif_carrier_off(dev);
+
+	err = slic_init_iface(sdev);
+	if (err) {
+		netdev_err(dev, "failed to initialize interface: %i\n", err);
+		return err;
+	}
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int slic_close(struct net_device *dev)
+{
+	struct slic_device *sdev = netdev_priv(dev);
+	u32 val;
+
+	netif_stop_queue(dev);
+
+	/* stop irq handling */
+	napi_disable(&sdev->napi);
+	slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+	slic_write(sdev, SLIC_REG_ISR, 0);
+	slic_flush_write(sdev);
+
+	free_irq(sdev->pdev->irq, sdev);
+	/* turn off RCV and XMT and power down PHY */
+	val = SLIC_GXCR_RESET | SLIC_GXCR_PAUSEEN;
+	slic_write(sdev, SLIC_REG_WXCFG, val);
+
+	val = SLIC_GRCR_RESET | SLIC_GRCR_CTLEN | SLIC_GRCR_ADDRAEN |
+	      SLIC_GRCR_HASHSIZE << SLIC_GRCR_HASHSIZE_SHIFT;
+	slic_write(sdev, SLIC_REG_WRCFG, val);
+
+	val = MII_BMCR << 16 | BMCR_PDOWN;
+	slic_write(sdev, SLIC_REG_WPHY, val);
+	slic_flush_write(sdev);
+
+	slic_clear_upr_list(&sdev->upr_list);
+	slic_write(sdev, SLIC_REG_QUIESCE, 0);
+
+	slic_free_stat_queue(sdev);
+	slic_free_tx_queue(sdev);
+	slic_free_rx_queue(sdev);
+	slic_free_shmem(sdev);
+
+	slic_card_reset(sdev);
+	netif_carrier_off(dev);
+
+	return 0;
+}
+
+static netdev_tx_t slic_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct slic_device *sdev = netdev_priv(dev);
+	struct slic_tx_queue *txq = &sdev->txq;
+	struct slic_tx_buffer *buff;
+	struct slic_tx_desc *desc;
+	dma_addr_t paddr;
+	u32 cbar_val;
+	u32 maplen;
+
+	if (unlikely(slic_get_free_tx_descs(txq) < SLIC_MAX_REQ_TX_DESCS)) {
+		netdev_err(dev, "BUG! not enough tx LEs left: %u\n",
+			   slic_get_free_tx_descs(txq));
+		return NETDEV_TX_BUSY;
+	}
+
+	maplen = skb_headlen(skb);
+	paddr = dma_map_single(&sdev->pdev->dev, skb->data, maplen,
+			       DMA_TO_DEVICE);
+	if (dma_mapping_error(&sdev->pdev->dev, paddr)) {
+		netdev_err(dev, "failed to map tx buffer\n");
+		goto drop_skb;
+	}
+
+	buff = &txq->txbuffs[txq->put_idx];
+	buff->skb = skb;
+	dma_unmap_addr_set(buff, map_addr, paddr);
+	dma_unmap_len_set(buff, map_len, maplen);
+
+	desc = buff->desc;
+	desc->totlen = cpu_to_le32(maplen);
+	desc->paddrl = cpu_to_le32(lower_32_bits(paddr));
+	desc->paddrh = cpu_to_le32(upper_32_bits(paddr));
+	desc->len = cpu_to_le32(maplen);
+
+	txq->put_idx = slic_next_queue_idx(txq->put_idx, txq->len);
+
+	cbar_val = lower_32_bits(buff->desc_paddr) | 1;
+	/* complete writes to RAM and DMA before hardware is informed */
+	wmb();
+
+	slic_write(sdev, SLIC_REG_CBAR, cbar_val);
+
+	if (slic_get_free_tx_descs(txq) < SLIC_MAX_REQ_TX_DESCS)
+		netif_stop_queue(dev);
+	/* make sure writes to io-memory cant leak out of tx queue lock */
+	mmiowb();
+
+	return NETDEV_TX_OK;
+drop_skb:
+	dev_kfree_skb_any(skb);
+
+	return NETDEV_TX_OK;
+}
+
+static struct rtnl_link_stats64 *slic_get_stats(struct net_device *dev,
+						struct rtnl_link_stats64 *lst)
+{
+	struct slic_device *sdev = netdev_priv(dev);
+	struct slic_stats *stats = &sdev->stats;
+
+	SLIC_GET_STATS_COUNTER(lst->rx_packets, stats, rx_packets);
+	SLIC_GET_STATS_COUNTER(lst->tx_packets, stats, tx_packets);
+	SLIC_GET_STATS_COUNTER(lst->rx_bytes, stats, rx_bytes);
+	SLIC_GET_STATS_COUNTER(lst->tx_bytes, stats, tx_bytes);
+	SLIC_GET_STATS_COUNTER(lst->rx_errors, stats, rx_errors);
+	SLIC_GET_STATS_COUNTER(lst->rx_dropped, stats, rx_buff_miss);
+	SLIC_GET_STATS_COUNTER(lst->tx_dropped, stats, tx_dropped);
+	SLIC_GET_STATS_COUNTER(lst->multicast, stats, rx_mcasts);
+	SLIC_GET_STATS_COUNTER(lst->rx_over_errors, stats, rx_buffoflow);
+	SLIC_GET_STATS_COUNTER(lst->rx_crc_errors, stats, rx_crc);
+	SLIC_GET_STATS_COUNTER(lst->rx_fifo_errors, stats, rx_oflow802);
+	SLIC_GET_STATS_COUNTER(lst->tx_carrier_errors, stats, tx_carrier);
+
+	return lst;
+}
+
+static int slic_get_sset_count(struct net_device *dev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(slic_stats_strings);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void slic_get_ethtool_stats(struct net_device *dev,
+				   struct ethtool_stats *eth_stats, u64 *data)
+{
+	struct slic_device *sdev = netdev_priv(dev);
+	struct slic_stats *stats = &sdev->stats;
+
+	SLIC_GET_STATS_COUNTER(data[0], stats, rx_packets);
+	SLIC_GET_STATS_COUNTER(data[1], stats, rx_bytes);
+	SLIC_GET_STATS_COUNTER(data[2], stats, rx_mcasts);
+	SLIC_GET_STATS_COUNTER(data[3], stats, rx_errors);
+	SLIC_GET_STATS_COUNTER(data[4], stats, rx_buff_miss);
+	SLIC_GET_STATS_COUNTER(data[5], stats, rx_tpcsum);
+	SLIC_GET_STATS_COUNTER(data[6], stats, rx_tpoflow);
+	SLIC_GET_STATS_COUNTER(data[7], stats, rx_tphlen);
+	SLIC_GET_STATS_COUNTER(data[8], stats, rx_ipcsum);
+	SLIC_GET_STATS_COUNTER(data[9], stats, rx_iplen);
+	SLIC_GET_STATS_COUNTER(data[10], stats, rx_iphlen);
+	SLIC_GET_STATS_COUNTER(data[11], stats, rx_early);
+	SLIC_GET_STATS_COUNTER(data[12], stats, rx_buffoflow);
+	SLIC_GET_STATS_COUNTER(data[13], stats, rx_lcode);
+	SLIC_GET_STATS_COUNTER(data[14], stats, rx_drbl);
+	SLIC_GET_STATS_COUNTER(data[15], stats, rx_crc);
+	SLIC_GET_STATS_COUNTER(data[16], stats, rx_oflow802);
+	SLIC_GET_STATS_COUNTER(data[17], stats, rx_uflow802);
+	SLIC_GET_STATS_COUNTER(data[18], stats, tx_packets);
+	SLIC_GET_STATS_COUNTER(data[19], stats, tx_bytes);
+	SLIC_GET_STATS_COUNTER(data[20], stats, tx_carrier);
+	SLIC_GET_STATS_COUNTER(data[21], stats, tx_dropped);
+	SLIC_GET_STATS_COUNTER(data[22], stats, irq_errs);
+}
+
+static void slic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+	if (stringset == ETH_SS_STATS) {
+		memcpy(data, slic_stats_strings, sizeof(slic_stats_strings));
+		data += sizeof(slic_stats_strings);
+	}
+}
+
+static void slic_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	struct slic_device *sdev = netdev_priv(dev);
+
+	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+	strlcpy(info->bus_info, pci_name(sdev->pdev), sizeof(info->bus_info));
+}
+
+static const struct ethtool_ops slic_ethtool_ops = {
+	.get_drvinfo		= slic_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+	.get_strings		= slic_get_strings,
+	.get_ethtool_stats	= slic_get_ethtool_stats,
+	.get_sset_count		= slic_get_sset_count,
+};
+
+static const struct net_device_ops slic_netdev_ops = {
+	.ndo_open		= slic_open,
+	.ndo_stop		= slic_close,
+	.ndo_start_xmit		= slic_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_get_stats64	= slic_get_stats,
+	.ndo_set_rx_mode	= slic_set_rx_mode,
+	.ndo_validate_addr	= eth_validate_addr,
+};
+
+static u16 slic_eeprom_csum(unsigned char *eeprom, unsigned int len)
+{
+	unsigned char *ptr = eeprom;
+	u32 csum = 0;
+	__le16 data;
+
+	while (len > 1) {
+		memcpy(&data, ptr, sizeof(data));
+		csum += le16_to_cpu(data);
+		ptr += 2;
+		len -= 2;
+	}
+	if (len > 0)
+		csum += *(u8 *)ptr;
+	while (csum >> 16)
+		csum = (csum & 0xFFFF) + ((csum >> 16) & 0xFFFF);
+	return ~csum;
+}
+
+/* check eeprom size, magic and checksum */
+static bool slic_eeprom_valid(unsigned char *eeprom, unsigned int size)
+{
+	const unsigned int MAX_SIZE = 128;
+	const unsigned int MIN_SIZE = 98;
+	__le16 magic;
+	__le16 csum;
+
+	if (size < MIN_SIZE || size > MAX_SIZE)
+		return false;
+	memcpy(&magic, eeprom, sizeof(magic));
+	if (le16_to_cpu(magic) != SLIC_EEPROM_MAGIC)
+		return false;
+	/* cut checksum bytes */
+	size -= 2;
+	memcpy(&csum, eeprom + size, sizeof(csum));
+
+	return (le16_to_cpu(csum) == slic_eeprom_csum(eeprom, size));
+}
+
+static int slic_read_eeprom(struct slic_device *sdev)
+{
+	unsigned int devfn = PCI_FUNC(sdev->pdev->devfn);
+	struct slic_shmem *sm = &sdev->shmem;
+	struct slic_shmem_data *sm_data = sm->shmem_data;
+	const unsigned int MAX_LOOPS = 5000;
+	unsigned int codesize;
+	unsigned char *eeprom;
+	struct slic_upr *upr;
+	unsigned int i = 0;
+	dma_addr_t paddr;
+	int err = 0;
+	u8 *mac[2];
+
+	eeprom = dma_zalloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
+				     &paddr, GFP_KERNEL);
+	if (!eeprom)
+		return -ENOMEM;
+
+	slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+	/* setup ISP temporarily */
+	slic_write(sdev, SLIC_REG_ISP, lower_32_bits(sm->isr_paddr));
+
+	err = slic_new_upr(sdev, SLIC_UPR_CONFIG, paddr);
+	if (!err) {
+		for (i = 0; i < MAX_LOOPS; i++) {
+			if (le32_to_cpu(sm_data->isr) & SLIC_ISR_UPC)
+				break;
+			mdelay(1);
+		}
+		if (i == MAX_LOOPS) {
+			dev_err(&sdev->pdev->dev,
+				"timed out while waiting for eeprom data\n");
+			err = -ETIMEDOUT;
+		}
+		upr = slic_dequeue_upr(sdev);
+		kfree(upr);
+	}
+
+	slic_write(sdev, SLIC_REG_ISP, 0);
+	slic_write(sdev, SLIC_REG_ISR, 0);
+	slic_flush_write(sdev);
+
+	if (err)
+		goto free_eeprom;
+
+	if (sdev->model == SLIC_MODEL_OASIS) {
+		struct slic_oasis_eeprom *oee;
+
+		oee = (struct slic_oasis_eeprom *)eeprom;
+		mac[0] = oee->mac;
+		mac[1] = oee->mac2;
+		codesize = le16_to_cpu(oee->eeprom_code_size);
+	} else {
+		struct slic_mojave_eeprom *mee;
+
+		mee = (struct slic_mojave_eeprom *)eeprom;
+		mac[0] = mee->mac;
+		mac[1] = mee->mac2;
+		codesize = le16_to_cpu(mee->eeprom_code_size);
+	}
+
+	if (!slic_eeprom_valid(eeprom, codesize)) {
+		dev_err(&sdev->pdev->dev, "invalid checksum in eeprom\n");
+		err = -EINVAL;
+		goto free_eeprom;
+	}
+	/* set mac address */
+	ether_addr_copy(sdev->netdev->dev_addr, mac[devfn]);
+free_eeprom:
+	dma_free_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE, eeprom, paddr);
+
+	return err;
+}
+
+static int slic_init(struct slic_device *sdev)
+{
+	int err;
+
+	spin_lock_init(&sdev->upper_lock);
+	spin_lock_init(&sdev->link_lock);
+	INIT_LIST_HEAD(&sdev->upr_list.list);
+	spin_lock_init(&sdev->upr_list.lock);
+	u64_stats_init(&sdev->stats.syncp);
+
+	slic_card_reset(sdev);
+
+	err = slic_load_firmware(sdev);
+	if (err) {
+		dev_err(&sdev->pdev->dev, "failed to load firmware\n");
+		return err;
+	}
+
+	/* we need the shared memory to read EEPROM so set it up temporarily */
+	err = slic_init_shmem(sdev);
+	if (err) {
+		dev_err(&sdev->pdev->dev, "failed to init shared memory\n");
+		return err;
+	}
+
+	err = slic_read_eeprom(sdev);
+	if (err) {
+		dev_err(&sdev->pdev->dev, "failed to read eeprom\n");
+		goto free_sm;
+	}
+
+	slic_card_reset(sdev);
+	slic_free_shmem(sdev);
+
+	return 0;
+free_sm:
+	slic_free_shmem(sdev);
+
+	return err;
+}
+
+static bool slic_is_fiber(unsigned short subdev)
+{
+	switch (subdev) {
+	/* Mojave */
+	case PCI_SUBDEVICE_ID_ALACRITECH_1000X1F: /* fallthrough */
+	case PCI_SUBDEVICE_ID_ALACRITECH_SES1001F: /* fallthrough */
+	/* Oasis */
+	case PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF: /* fallthrough */
+	case PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF: /* fallthrough */
+	case PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF: /* fallthrough */
+	case PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF: /* fallthrough */
+		return true;
+	}
+	return false;
+}
+
+static void slic_configure_pci(struct pci_dev *pdev)
+{
+	u16 old;
+	u16 cmd;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &old);
+
+	cmd = old | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+	if (old != cmd)
+		pci_write_config_word(pdev, PCI_COMMAND, cmd);
+}
+
+static int slic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct slic_device *sdev;
+	struct net_device *dev;
+	int err;
+
+	err = pci_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable PCI device\n");
+		return err;
+	}
+
+	pci_set_master(pdev);
+	pci_try_set_mwi(pdev);
+
+	slic_configure_pci(pdev);
+
+	err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (err) {
+		dev_err(&pdev->dev, "failed to setup DMA\n");
+		goto disable;
+	}
+
+	dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err) {
+		dev_err(&pdev->dev, "failed to obtain PCI regions\n");
+		goto disable;
+	}
+
+	dev = alloc_etherdev(sizeof(*sdev));
+	if (!dev) {
+		dev_err(&pdev->dev, "failed to alloc ethernet device\n");
+		err = -ENOMEM;
+		goto free_regions;
+	}
+
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	pci_set_drvdata(pdev, dev);
+	dev->irq = pdev->irq;
+	dev->netdev_ops = &slic_netdev_ops;
+	dev->hw_features = NETIF_F_RXCSUM;
+	dev->features |= dev->hw_features;
+
+	dev->ethtool_ops = &slic_ethtool_ops;
+
+	sdev = netdev_priv(dev);
+	sdev->model = (pdev->device == PCI_DEVICE_ID_ALACRITECH_OASIS) ?
+		      SLIC_MODEL_OASIS : SLIC_MODEL_MOJAVE;
+	sdev->is_fiber = slic_is_fiber(pdev->subsystem_device);
+	sdev->pdev = pdev;
+	sdev->netdev = dev;
+	sdev->regs = ioremap_nocache(pci_resource_start(pdev, 0),
+				     pci_resource_len(pdev, 0));
+	if (!sdev->regs) {
+		dev_err(&pdev->dev, "failed to map registers\n");
+		err = -ENOMEM;
+		goto free_netdev;
+	}
+
+	err = slic_init(sdev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize driver\n");
+		goto unmap;
+	}
+
+	netif_napi_add(dev, &sdev->napi, slic_poll, SLIC_NAPI_WEIGHT);
+	netif_carrier_off(dev);
+
+	err = register_netdev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register net device: %i\n", err);
+		goto unmap;
+	}
+
+	return 0;
+
+unmap:
+	iounmap(sdev->regs);
+free_netdev:
+	free_netdev(dev);
+free_regions:
+	pci_release_regions(pdev);
+disable:
+	pci_disable_device(pdev);
+
+	return err;
+}
+
+static void slic_remove(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct slic_device *sdev = netdev_priv(dev);
+
+	unregister_netdev(dev);
+	iounmap(sdev->regs);
+	free_netdev(dev);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+}
+
+static struct pci_driver slic_driver = {
+	.name = DRV_NAME,
+	.id_table = slic_id_tbl,
+	.probe = slic_probe,
+	.remove = slic_remove,
+};
+
+module_pci_driver(slic_driver);
+
+MODULE_DESCRIPTION("Alacritech non-accelerated SLIC driver");
+MODULE_AUTHOR("Lino Sanfilippo <LinoSanfilippo@gmx.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/allwinner/sun4i-emac.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,11 @@
 
 #define EMAC_MAX_FRAME_LEN	0x0600
 
+#define EMAC_DEFAULT_MSG_ENABLE 0x0000
+static int debug = -1;     /* defaults above */;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "debug message flags");
+
 /* Transmit timeout, default 5 seconds. */
 static int watchdog = 5000;
 module_param(watchdog, int, 0400);
@@ -225,11 +230,27 @@ static void emac_get_drvinfo(struct net_
 	strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info));
 }
 
+static u32 emac_get_msglevel(struct net_device *dev)
+{
+	struct emac_board_info *db = netdev_priv(dev);
+
+	return db->msg_enable;
+}
+
+static void emac_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct emac_board_info *db = netdev_priv(dev);
+
+	db->msg_enable = value;
+}
+
 static const struct ethtool_ops emac_ethtool_ops = {
 	.get_drvinfo	= emac_get_drvinfo,
 	.get_link	= ethtool_op_get_link,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
+	.get_msglevel	= emac_get_msglevel,
+	.set_msglevel	= emac_set_msglevel,
 };
 
 static unsigned int emac_setup(struct net_device *ndev)
@@ -571,8 +592,7 @@ static void emac_rx(struct net_device *d
 		/* A packet ready now  & Get status/length */
 		good_packet = true;
 
-		emac_inblk_32bit(db->membase + EMAC_RX_IO_DATA_REG,
-				&rxhdr, sizeof(rxhdr));
+		rxhdr = readl(db->membase + EMAC_RX_IO_DATA_REG);
 
 		if (netif_msg_rx_status(db))
 			dev_dbg(db->dev, "rxhdr: %x\n", *((int *)(&rxhdr)));
@@ -773,7 +793,6 @@ static const struct net_device_ops emac_
 	.ndo_tx_timeout		= emac_timeout,
 	.ndo_set_rx_mode	= emac_set_rx_mode,
 	.ndo_do_ioctl		= emac_ioctl,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= emac_set_mac_address,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -805,6 +824,7 @@ static int emac_probe(struct platform_de
 	db->dev = &pdev->dev;
 	db->ndev = ndev;
 	db->pdev = pdev;
+	db->msg_enable = netif_msg_init(debug, EMAC_DEFAULT_MSG_ENABLE);
 
 	spin_lock_init(&db->lock);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/alteon/acenic.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alteon/acenic.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/alteon/acenic.c	2016-12-11 17:48:46.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/alteon/acenic.c	2017-02-12 17:36:53.000000000 -0500
@@ -80,7 +80,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 
 #define DRV_NAME "acenic"
@@ -429,14 +429,16 @@ static const char version[] =
   "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 int ace_get_link_ksettings(struct net_device *,
+				  struct ethtool_link_ksettings *);
+static int ace_set_link_ksettings(struct net_device *,
+				  const struct ethtool_link_ksettings *);
 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,
+	.get_link_ksettings = ace_get_link_ksettings,
+	.set_link_ksettings = ace_set_link_ksettings,
 };
 
 static void ace_watchdog(struct net_device *dev);
@@ -474,6 +476,8 @@ static int acenic_probe_one(struct pci_d
 	dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
 
 	dev->watchdog_timeo = 5*HZ;
+	dev->min_mtu = 0;
+	dev->max_mtu = ACE_JUMBO_MTU;
 
 	dev->netdev_ops = &ace_netdev_ops;
 	dev->ethtool_ops = &ace_ethtool_ops;
@@ -2548,9 +2552,6 @@ static int ace_change_mtu(struct net_dev
 	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;
 
@@ -2580,43 +2581,44 @@ static int ace_change_mtu(struct net_dev
 	return 0;
 }
 
-static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int ace_get_link_ksettings(struct net_device *dev,
+				  struct ethtool_link_ksettings *cmd)
 {
 	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs __iomem *regs = ap->regs;
 	u32 link;
+	u32 supported;
 
-	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);
+	memset(cmd, 0, sizeof(struct ethtool_link_ksettings));
 
-	ecmd->port = PORT_FIBRE;
-	ecmd->transceiver = XCVR_INTERNAL;
+	supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+		     SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+		     SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
+		     SUPPORTED_Autoneg | SUPPORTED_FIBRE);
+
+	cmd->base.port = PORT_FIBRE;
 
 	link = readl(&regs->GigLnkState);
-	if (link & LNK_1000MB)
-		ethtool_cmd_speed_set(ecmd, SPEED_1000);
-	else {
+	if (link & LNK_1000MB) {
+		cmd->base.speed = SPEED_1000;
+	} else {
 		link = readl(&regs->FastLnkState);
 		if (link & LNK_100MB)
-			ethtool_cmd_speed_set(ecmd, SPEED_100);
+			cmd->base.speed = SPEED_100;
 		else if (link & LNK_10MB)
-			ethtool_cmd_speed_set(ecmd, SPEED_10);
+			cmd->base.speed = SPEED_10;
 		else
-			ethtool_cmd_speed_set(ecmd, 0);
+			cmd->base.speed = 0;
 	}
 	if (link & LNK_FULL_DUPLEX)
-		ecmd->duplex = DUPLEX_FULL;
+		cmd->base.duplex = DUPLEX_FULL;
 	else
-		ecmd->duplex = DUPLEX_HALF;
+		cmd->base.duplex = DUPLEX_HALF;
 
 	if (link & LNK_NEGOTIATE)
-		ecmd->autoneg = AUTONEG_ENABLE;
+		cmd->base.autoneg = AUTONEG_ENABLE;
 	else
-		ecmd->autoneg = AUTONEG_DISABLE;
+		cmd->base.autoneg = AUTONEG_DISABLE;
 
 #if 0
 	/*
@@ -2627,13 +2629,15 @@ static int ace_get_settings(struct net_d
 	ecmd->txcoal = readl(&regs->TuneTxCoalTicks);
 	ecmd->rxcoal = readl(&regs->TuneRxCoalTicks);
 #endif
-	ecmd->maxtxpkt = readl(&regs->TuneMaxTxDesc);
-	ecmd->maxrxpkt = readl(&regs->TuneMaxRxDesc);
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
 
 	return 0;
 }
 
-static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int ace_set_link_ksettings(struct net_device *dev,
+				  const struct ethtool_link_ksettings *cmd)
 {
 	struct ace_private *ap = netdev_priv(dev);
 	struct ace_regs __iomem *regs = ap->regs;
@@ -2656,11 +2660,11 @@ static int ace_set_settings(struct net_d
 		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)
+	if (cmd->base.autoneg == AUTONEG_ENABLE)
 		link |= LNK_NEGOTIATE;
-	if (ethtool_cmd_speed(ecmd) != speed) {
+	if (cmd->base.speed != speed) {
 		link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
-		switch (ethtool_cmd_speed(ecmd)) {
+		switch (cmd->base.speed) {
 		case SPEED_1000:
 			link |= LNK_1000MB;
 			break;
@@ -2673,7 +2677,7 @@ static int ace_set_settings(struct net_d
 		}
 	}
 
-	if (ecmd->duplex == DUPLEX_FULL)
+	if (cmd->base.duplex == DUPLEX_FULL)
 		link |= LNK_FULL_DUPLEX;
 
 	if (link != ap->link) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/altera/altera_tse.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/altera/altera_tse.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/altera/altera_tse.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/altera/altera_tse.h	2017-02-12 16:03:20.000000000 -0500
@@ -120,6 +120,17 @@
 #define MAC_CMDCFG_DISABLE_READ_TIMEOUT_GET(v)	GET_BIT_VALUE(v, 27)
 #define MAC_CMDCFG_CNT_RESET_GET(v)		GET_BIT_VALUE(v, 31)
 
+/* SGMII PCS register addresses
+ */
+#define SGMII_PCS_SCRATCH	0x10
+#define SGMII_PCS_REV		0x11
+#define SGMII_PCS_LINK_TIMER_0	0x12
+#define SGMII_PCS_LINK_TIMER_1	0x13
+#define SGMII_PCS_IF_MODE	0x14
+#define SGMII_PCS_DIS_READ_TO	0x15
+#define SGMII_PCS_READ_TO	0x16
+#define SGMII_PCS_SW_RESET_TIMEOUT 100 /* usecs */
+
 /* MDIO registers within MAC register Space
  */
 struct altera_tse_mdio {
@@ -443,7 +454,6 @@ struct altera_tse_private {
 	/* RX/TX MAC FIFO configs */
 	u32 tx_fifo_depth;
 	u32 rx_fifo_depth;
-	u32 max_mtu;
 
 	/* Hash filter settings */
 	u32 hash_filter;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/altera/altera_tse_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/altera/altera_tse_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/altera/altera_tse_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/altera/altera_tse_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/of_device.h>
 #include <linux/of_mdio.h>
@@ -96,6 +97,27 @@ static inline u32 tse_tx_avail(struct al
 	return priv->tx_cons + priv->tx_ring_size - priv->tx_prod - 1;
 }
 
+/* PCS Register read/write functions
+ */
+static u16 sgmii_pcs_read(struct altera_tse_private *priv, int regnum)
+{
+	return csrrd32(priv->mac_dev,
+		       tse_csroffs(mdio_phy0) + regnum * 4) & 0xffff;
+}
+
+static void sgmii_pcs_write(struct altera_tse_private *priv, int regnum,
+				u16 value)
+{
+	csrwr32(value, priv->mac_dev, tse_csroffs(mdio_phy0) + regnum * 4);
+}
+
+/* Check PCS scratch memory */
+static int sgmii_pcs_scratch_test(struct altera_tse_private *priv, u16 value)
+{
+	sgmii_pcs_write(priv, SGMII_PCS_SCRATCH, value);
+	return (sgmii_pcs_read(priv, SGMII_PCS_SCRATCH) == value);
+}
+
 /* MDIO specific functions
  */
 static int altera_tse_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
@@ -984,20 +1006,11 @@ static void tse_set_mac(struct altera_ts
  */
 static int tse_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct altera_tse_private *priv = netdev_priv(dev);
-	unsigned int max_mtu = priv->max_mtu;
-	unsigned int min_mtu = ETH_ZLEN + ETH_FCS_LEN;
-
 	if (netif_running(dev)) {
 		netdev_err(dev, "must be stopped to change its MTU\n");
 		return -EBUSY;
 	}
 
-	if ((new_mtu < min_mtu) || (new_mtu > max_mtu)) {
-		netdev_err(dev, "invalid MTU, max MTU is: %u\n", max_mtu);
-		return -EINVAL;
-	}
-
 	dev->mtu = new_mtu;
 	netdev_update_features(dev);
 
@@ -1082,6 +1095,66 @@ static void tse_set_rx_mode(struct net_d
 	spin_unlock(&priv->mac_cfg_lock);
 }
 
+/* Initialise (if necessary) the SGMII PCS component
+ */
+static int init_sgmii_pcs(struct net_device *dev)
+{
+	struct altera_tse_private *priv = netdev_priv(dev);
+	int n;
+	unsigned int tmp_reg = 0;
+
+	if (priv->phy_iface != PHY_INTERFACE_MODE_SGMII)
+		return 0; /* Nothing to do, not in SGMII mode */
+
+	/* The TSE SGMII PCS block looks a little like a PHY, it is
+	 * mapped into the zeroth MDIO space of the MAC and it has
+	 * ID registers like a PHY would.  Sadly this is often
+	 * configured to zeroes, so don't be surprised if it does
+	 * show 0x00000000.
+	 */
+
+	if (sgmii_pcs_scratch_test(priv, 0x0000) &&
+		sgmii_pcs_scratch_test(priv, 0xffff) &&
+		sgmii_pcs_scratch_test(priv, 0xa5a5) &&
+		sgmii_pcs_scratch_test(priv, 0x5a5a)) {
+		netdev_info(dev, "PCS PHY ID: 0x%04x%04x\n",
+				sgmii_pcs_read(priv, MII_PHYSID1),
+				sgmii_pcs_read(priv, MII_PHYSID2));
+	} else {
+		netdev_err(dev, "SGMII PCS Scratch memory test failed.\n");
+		return -ENOMEM;
+	}
+
+	/* Starting on page 5-29 of the MegaCore Function User Guide
+	 * Set SGMII Link timer to 1.6ms
+	 */
+	sgmii_pcs_write(priv, SGMII_PCS_LINK_TIMER_0, 0x0D40);
+	sgmii_pcs_write(priv, SGMII_PCS_LINK_TIMER_1, 0x03);
+
+	/* Enable SGMII Interface and Enable SGMII Auto Negotiation */
+	sgmii_pcs_write(priv, SGMII_PCS_IF_MODE, 0x3);
+
+	/* Enable Autonegotiation */
+	tmp_reg = sgmii_pcs_read(priv, MII_BMCR);
+	tmp_reg |= (BMCR_SPEED1000 | BMCR_FULLDPLX | BMCR_ANENABLE);
+	sgmii_pcs_write(priv, MII_BMCR, tmp_reg);
+
+	/* Reset PCS block */
+	tmp_reg |= BMCR_RESET;
+	sgmii_pcs_write(priv, MII_BMCR, tmp_reg);
+	for (n = 0; n < SGMII_PCS_SW_RESET_TIMEOUT; n++) {
+		if (!(sgmii_pcs_read(priv, MII_BMCR) & BMCR_RESET)) {
+			netdev_info(dev, "SGMII PCS block initialised OK\n");
+			return 0;
+		}
+		udelay(1);
+	}
+
+	/* We failed to reset the block, return a timeout */
+	netdev_err(dev, "SGMII PCS block reset failed.\n");
+	return -ETIMEDOUT;
+}
+
 /* Open and initialize the interface
  */
 static int tse_open(struct net_device *dev)
@@ -1106,6 +1179,15 @@ static int tse_open(struct net_device *d
 		netdev_warn(dev, "TSE revision %x\n", priv->revision);
 
 	spin_lock(&priv->mac_cfg_lock);
+	/* no-op if MAC not operating in SGMII mode*/
+	ret = init_sgmii_pcs(dev);
+	if (ret) {
+		netdev_err(dev,
+			   "Cannot init the SGMII PCS (error: %d)\n", ret);
+		spin_unlock(&priv->mac_cfg_lock);
+		goto phy_error;
+	}
+
 	ret = reset_mac(priv);
 	/* Note that reset_mac will fail if the clocks are gated by the PHY
 	 * due to the PHY being put into isolation or power down mode.
@@ -1328,11 +1410,13 @@ static int altera_tse_probe(struct platf
 		if (upper_32_bits(priv->rxdescmem_busaddr)) {
 			dev_dbg(priv->device,
 				"SGDMA bus addresses greater than 32-bits\n");
+			ret = -EINVAL;
 			goto err_free_netdev;
 		}
 		if (upper_32_bits(priv->txdescmem_busaddr)) {
 			dev_dbg(priv->device,
 				"SGDMA bus addresses greater than 32-bits\n");
+			ret = -EINVAL;
 			goto err_free_netdev;
 		}
 	} else if (priv->dmaops &&
@@ -1436,15 +1520,16 @@ static int altera_tse_probe(struct platf
 		of_property_read_bool(pdev->dev.of_node,
 				      "altr,has-supplementary-unicast");
 
+	priv->dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN;
 	/* Max MTU is 1500, ETH_DATA_LEN */
-	priv->max_mtu = ETH_DATA_LEN;
+	priv->dev->max_mtu = ETH_DATA_LEN;
 
 	/* Get the max mtu from the device tree. Note that the
 	 * "max-frame-size" parameter is actually max mtu. Definition
 	 * in the ePAPR v1.1 spec and usage differ, so go with usage.
 	 */
 	of_property_read_u32(pdev->dev.of_node, "max-frame-size",
-			     &priv->max_mtu);
+			     &priv->dev->max_mtu);
 
 	/* The DMA buffer size already accounts for an alignment bias
 	 * to avoid unaligned access exceptions for the NIOS processor,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/altera/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/altera/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/altera/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/altera/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -5,4 +5,3 @@
 obj-$(CONFIG_ALTERA_TSE) += altera_tse.o
 altera_tse-objs := altera_tse_main.o altera_tse_ethtool.o \
 altera_msgdma.o altera_sgdma.o altera_utils.o
-ccflags-y += -D__CHECK_ENDIAN__
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amazon/ena/ena_netdev.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amazon/ena/ena_netdev.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amazon/ena/ena_netdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amazon/ena/ena_netdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -103,13 +103,6 @@ static int ena_change_mtu(struct net_dev
 	struct ena_adapter *adapter = netdev_priv(dev);
 	int ret;
 
-	if ((new_mtu > adapter->max_mtu) || (new_mtu < ENA_MIN_MTU)) {
-		netif_err(adapter, drv, dev,
-			  "Invalid MTU setting. new_mtu: %d\n", new_mtu);
-
-		return -EINVAL;
-	}
-
 	ret = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu);
 	if (!ret) {
 		netif_dbg(adapter, drv, dev, "set MTU to %d\n", new_mtu);
@@ -2755,6 +2748,8 @@ static void ena_set_conf_feat_params(str
 	ena_set_dev_offloads(feat, netdev);
 
 	adapter->max_mtu = feat->dev_attr.max_mtu;
+	netdev->max_mtu = adapter->max_mtu;
+	netdev->min_mtu = ENA_MIN_MTU;
 }
 
 static int ena_rss_init_default(struct ena_adapter *adapter)
@@ -3018,12 +3013,9 @@ static int ena_probe(struct pci_dev *pde
 
 	adapter->last_keep_alive_jiffies = jiffies;
 
-	init_timer(&adapter->timer_service);
-	adapter->timer_service.expires = round_jiffies(jiffies + HZ);
-	adapter->timer_service.function = ena_timer_service;
-	adapter->timer_service.data = (unsigned long)adapter;
-
-	add_timer(&adapter->timer_service);
+	setup_timer(&adapter->timer_service, ena_timer_service,
+		    (unsigned long)adapter);
+	mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
 
 	dev_info(&pdev->dev, "%s found at mem %lx, mac addr %pM Queues %d\n",
 		 DEVICE_NAME, (long)pci_resource_start(pdev, 0),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/a2065.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/a2065.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/a2065.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/a2065.c	2017-02-12 16:03:20.000000000 -0500
@@ -665,7 +665,6 @@ static const struct net_device_ops lance
 	.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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/am79c961a.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/am79c961a.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/am79c961a.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/am79c961a.c	2017-02-12 16:03:20.000000000 -0500
@@ -663,7 +663,6 @@ static const struct net_device_ops am79c
 	.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,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/amd8111e.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/amd8111e.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/amd8111e.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/amd8111e.c	2017-02-12 16:03:20.000000000 -0500
@@ -87,7 +87,7 @@ Revision History:
 
 #include <asm/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #if IS_ENABLED(CONFIG_VLAN_8021Q)
 #define AMD8111E_VLAN_TAG_USED 1
@@ -1421,21 +1421,23 @@ static void amd8111e_get_regs(struct net
 	amd8111e_read_regs(lp, buf);
 }
 
-static int amd8111e_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int amd8111e_get_link_ksettings(struct net_device *dev,
+				       struct ethtool_link_ksettings *cmd)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	spin_lock_irq(&lp->lock);
-	mii_ethtool_gset(&lp->mii_if, ecmd);
+	mii_ethtool_get_link_ksettings(&lp->mii_if, cmd);
 	spin_unlock_irq(&lp->lock);
 	return 0;
 }
 
-static int amd8111e_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+static int amd8111e_set_link_ksettings(struct net_device *dev,
+				       const struct ethtool_link_ksettings *cmd)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	int res;
 	spin_lock_irq(&lp->lock);
-	res = mii_ethtool_sset(&lp->mii_if, ecmd);
+	res = mii_ethtool_set_link_ksettings(&lp->mii_if, cmd);
 	spin_unlock_irq(&lp->lock);
 	return res;
 }
@@ -1482,12 +1484,12 @@ 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,
+	.get_link_ksettings = amd8111e_get_link_ksettings,
+	.set_link_ksettings = amd8111e_set_link_ksettings,
 };
 
 /* This function handles all the  ethtool ioctls. It gives driver info,
@@ -1556,9 +1558,6 @@ static int amd8111e_change_mtu(struct ne
 	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
@@ -1874,6 +1873,8 @@ static int amd8111e_probe_one(struct pci
 	dev->ethtool_ops = &ops;
 	dev->irq =pdev->irq;
 	dev->watchdog_timeo = AMD8111E_TX_TIMEOUT;
+	dev->min_mtu = AMD8111E_MIN_MTU;
+	dev->max_mtu = AMD8111E_MAX_MTU;
 	netif_napi_add(dev, &lp->napi, amd8111e_rx_poll, 32);
 
 #if AMD8111E_VLAN_TAG_USED
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/ariadne.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/ariadne.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/ariadne.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/ariadne.c	2017-02-12 16:03:20.000000000 -0500
@@ -706,7 +706,6 @@ static const struct net_device_ops ariad
 	.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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/atarilance.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/atarilance.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/atarilance.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/atarilance.c	2017-02-12 16:03:20.000000000 -0500
@@ -460,7 +460,6 @@ static const struct net_device_ops lance
 	.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,
@@ -1013,13 +1012,9 @@ static int lance_rx( struct net_device *
 					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",
+						   "data %8ph 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);
+						   &data[6], data, &data[15], pkt_len);
 				}
 
 				skb_reserve( skb, 2 );	/* 16 byte align */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/au1000_eth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/au1000_eth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/au1000_eth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/au1000_eth.c	2017-02-12 16:03:20.000000000 -0500
@@ -1103,7 +1103,6 @@ static const struct net_device_ops au100
 	.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 au1000_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/declance.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/declance.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/declance.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/declance.c	2017-02-12 16:03:20.000000000 -0500
@@ -1013,7 +1013,6 @@ static const struct net_device_ops lance
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/hplance.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/hplance.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/hplance.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/hplance.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,6 @@ static const struct net_device_ops hplan
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -173,11 +173,13 @@ config SUNLANCE
 
 config AMD_XGBE
 	tristate "AMD 10GbE Ethernet driver"
-	depends on ((OF_NET && OF_ADDRESS) || ACPI) && HAS_IOMEM && HAS_DMA
-	depends on ARM64 || COMPILE_TEST
+	depends on ((OF_NET && OF_ADDRESS) || ACPI || PCI) && HAS_IOMEM && HAS_DMA
+	depends on X86 || ARM64 || COMPILE_TEST
 	select BITREVERSE
 	select CRC32
-	select PTP_1588_CLOCK
+	select PHYLIB
+	select AMD_XGBE_HAVE_ECC if X86
+	imply PTP_1588_CLOCK
 	---help---
 	  This driver supports the AMD 10GbE Ethernet device found on an
 	  AMD SoC.
@@ -195,4 +197,8 @@ config AMD_XGBE_DCB
 
 	  If unsure, say N.
 
+config AMD_XGBE_HAVE_ECC
+	bool
+	default n
+
 endif # NET_VENDOR_AMD
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/lance.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/lance.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/lance.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/lance.c	2017-02-12 16:03:20.000000000 -0500
@@ -461,7 +461,6 @@ static const struct net_device_ops lance
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/mvme147.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/mvme147.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/mvme147.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/mvme147.c	2017-02-12 16:03:20.000000000 -0500
@@ -62,7 +62,6 @@ static const struct net_device_ops lance
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/ni65.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/ni65.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/ni65.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/ni65.c	2017-02-12 16:03:20.000000000 -0500
@@ -407,7 +407,6 @@ static const struct net_device_ops ni65_
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/nmclan_cs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/nmclan_cs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/nmclan_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/nmclan_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -151,7 +151,7 @@ Include Files
 #include <pcmcia/cistpl.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 /* ----------------------------------------------------------------------------
@@ -427,7 +427,6 @@ static const struct net_device_ops mace_
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/pcnet32.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/pcnet32.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/pcnet32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/pcnet32.c	2017-02-12 16:03:20.000000000 -0500
@@ -677,7 +677,8 @@ static void pcnet32_poll_controller(stru
 }
 #endif
 
-static int pcnet32_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int pcnet32_get_link_ksettings(struct net_device *dev,
+				      struct ethtool_link_ksettings *cmd)
 {
 	struct pcnet32_private *lp = netdev_priv(dev);
 	unsigned long flags;
@@ -685,14 +686,15 @@ static int pcnet32_get_settings(struct n
 
 	if (lp->mii) {
 		spin_lock_irqsave(&lp->lock, flags);
-		mii_ethtool_gset(&lp->mii_if, cmd);
+		mii_ethtool_get_link_ksettings(&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)
+static int pcnet32_set_link_ksettings(struct net_device *dev,
+				      const struct ethtool_link_ksettings *cmd)
 {
 	struct pcnet32_private *lp = netdev_priv(dev);
 	unsigned long flags;
@@ -700,7 +702,7 @@ static int pcnet32_set_settings(struct n
 
 	if (lp->mii) {
 		spin_lock_irqsave(&lp->lock, flags);
-		r = mii_ethtool_sset(&lp->mii_if, cmd);
+		r = mii_ethtool_set_link_ksettings(&lp->mii_if, cmd);
 		spin_unlock_irqrestore(&lp->lock, flags);
 	}
 	return r;
@@ -1440,8 +1442,6 @@ static void pcnet32_get_regs(struct net_
 }
 
 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,
@@ -1455,6 +1455,8 @@ static const struct ethtool_ops pcnet32_
 	.get_regs_len		= pcnet32_get_regs_len,
 	.get_regs		= pcnet32_get_regs,
 	.get_sset_count		= pcnet32_get_sset_count,
+	.get_link_ksettings	= pcnet32_get_link_ksettings,
+	.set_link_ksettings	= pcnet32_set_link_ksettings,
 };
 
 /* only probes for non-PCI devices, the rest are handled by
@@ -1527,7 +1529,6 @@ static const struct net_device_ops pcnet
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/sun3lance.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/sun3lance.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/sun3lance.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/sun3lance.c	2017-02-12 16:03:20.000000000 -0500
@@ -299,7 +299,6 @@ static const struct net_device_ops lance
 	.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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/sunlance.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/sunlance.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/sunlance.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/sunlance.c	2017-02-12 16:03:20.000000000 -0500
@@ -1294,7 +1294,6 @@ static const struct net_device_ops sparc
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -2,7 +2,10 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o
 
 amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \
 		 xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \
-		 xgbe-ptp.o
+		 xgbe-ptp.o \
+		 xgbe-i2c.o xgbe-phy-v1.o xgbe-phy-v2.o \
+		 xgbe-platform.o
 
+amd-xgbe-$(CONFIG_PCI) += xgbe-pci.o
 amd-xgbe-$(CONFIG_AMD_XGBE_DCB) += xgbe-dcb.o
 amd-xgbe-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-common.h	2017-02-12 16:03:20.000000000 -0500
@@ -159,6 +159,8 @@
 #define DMA_ISR_MACIS_WIDTH		1
 #define DMA_ISR_MTLIS_INDEX		16
 #define DMA_ISR_MTLIS_WIDTH		1
+#define DMA_MR_INTM_INDEX		12
+#define DMA_MR_INTM_WIDTH		2
 #define DMA_MR_SWR_INDEX		0
 #define DMA_MR_SWR_WIDTH		1
 #define DMA_SBMR_EAME_INDEX		11
@@ -309,6 +311,11 @@
 #define MAC_HWF0R			0x011c
 #define MAC_HWF1R			0x0120
 #define MAC_HWF2R			0x0124
+#define MAC_MDIOSCAR			0x0200
+#define MAC_MDIOSCCDR			0x0204
+#define MAC_MDIOISR			0x0214
+#define MAC_MDIOIER			0x0218
+#define MAC_MDIOCL22R			0x0220
 #define MAC_GPIOCR			0x0278
 #define MAC_GPIOSR			0x027c
 #define MAC_MACA0HR			0x0300
@@ -409,10 +416,34 @@
 #define MAC_ISR_MMCTXIS_WIDTH		1
 #define MAC_ISR_PMTIS_INDEX		4
 #define MAC_ISR_PMTIS_WIDTH		1
+#define MAC_ISR_SMI_INDEX		1
+#define MAC_ISR_SMI_WIDTH		1
 #define MAC_ISR_TSIS_INDEX		12
 #define MAC_ISR_TSIS_WIDTH		1
 #define MAC_MACA1HR_AE_INDEX		31
 #define MAC_MACA1HR_AE_WIDTH		1
+#define MAC_MDIOIER_SNGLCOMPIE_INDEX	12
+#define MAC_MDIOIER_SNGLCOMPIE_WIDTH	1
+#define MAC_MDIOISR_SNGLCOMPINT_INDEX	12
+#define MAC_MDIOISR_SNGLCOMPINT_WIDTH	1
+#define MAC_MDIOSCAR_DA_INDEX		21
+#define MAC_MDIOSCAR_DA_WIDTH		5
+#define MAC_MDIOSCAR_PA_INDEX		16
+#define MAC_MDIOSCAR_PA_WIDTH		5
+#define MAC_MDIOSCAR_RA_INDEX		0
+#define MAC_MDIOSCAR_RA_WIDTH		16
+#define MAC_MDIOSCAR_REG_INDEX		0
+#define MAC_MDIOSCAR_REG_WIDTH		21
+#define MAC_MDIOSCCDR_BUSY_INDEX	22
+#define MAC_MDIOSCCDR_BUSY_WIDTH	1
+#define MAC_MDIOSCCDR_CMD_INDEX		16
+#define MAC_MDIOSCCDR_CMD_WIDTH		2
+#define MAC_MDIOSCCDR_CR_INDEX		19
+#define MAC_MDIOSCCDR_CR_WIDTH		3
+#define MAC_MDIOSCCDR_DATA_INDEX	0
+#define MAC_MDIOSCCDR_DATA_WIDTH	16
+#define MAC_MDIOSCCDR_SADDR_INDEX	18
+#define MAC_MDIOSCCDR_SADDR_WIDTH	1
 #define MAC_PFR_HMC_INDEX		2
 #define MAC_PFR_HMC_WIDTH		1
 #define MAC_PFR_HPF_INDEX		10
@@ -790,6 +821,10 @@
 #define MTL_Q_RQOMR_RSF_WIDTH		1
 #define MTL_Q_RQOMR_RTC_INDEX		0
 #define MTL_Q_RQOMR_RTC_WIDTH		2
+#define MTL_Q_TQDR_TRCSTS_INDEX		1
+#define MTL_Q_TQDR_TRCSTS_WIDTH		2
+#define MTL_Q_TQDR_TXQSTS_INDEX		4
+#define MTL_Q_TQDR_TXQSTS_WIDTH		1
 #define MTL_Q_TQOMR_FTQ_INDEX		0
 #define MTL_Q_TQOMR_FTQ_WIDTH		1
 #define MTL_Q_TQOMR_Q2TCMAP_INDEX	8
@@ -852,14 +887,18 @@
 #define MTL_TSA_SP			0x00
 #define MTL_TSA_ETS			0x02
 
-/* PCS MMD select register offset
- *  The MMD select register is used for accessing PCS registers
- *  when the underlying APB3 interface is using indirect addressing.
- *  Indirect addressing requires accessing registers in two phases,
- *  an address phase and a data phase.  The address phases requires
- *  writing an address selection value to the MMD select regiesters.
- */
-#define PCS_MMD_SELECT			0xff
+/* PCS register offsets */
+#define PCS_V1_WINDOW_SELECT		0x03fc
+#define PCS_V2_WINDOW_DEF		0x9060
+#define PCS_V2_WINDOW_SELECT		0x9064
+#define PCS_V2_RV_WINDOW_DEF		0x1060
+#define PCS_V2_RV_WINDOW_SELECT		0x1064
+
+/* PCS register entry bit positions and sizes */
+#define PCS_V2_WINDOW_DEF_OFFSET_INDEX	6
+#define PCS_V2_WINDOW_DEF_OFFSET_WIDTH	14
+#define PCS_V2_WINDOW_DEF_SIZE_INDEX	2
+#define PCS_V2_WINDOW_DEF_SIZE_WIDTH	4
 
 /* SerDes integration register offsets */
 #define SIR0_KR_RT_1			0x002c
@@ -903,6 +942,198 @@
 #define RXTX_REG129_RXDFE_CONFIG_INDEX	14
 #define RXTX_REG129_RXDFE_CONFIG_WIDTH	2
 
+/* MAC Control register offsets */
+#define XP_PROP_0			0x0000
+#define XP_PROP_1			0x0004
+#define XP_PROP_2			0x0008
+#define XP_PROP_3			0x000c
+#define XP_PROP_4			0x0010
+#define XP_PROP_5			0x0014
+#define XP_MAC_ADDR_LO			0x0020
+#define XP_MAC_ADDR_HI			0x0024
+#define XP_ECC_ISR			0x0030
+#define XP_ECC_IER			0x0034
+#define XP_ECC_CNT0			0x003c
+#define XP_ECC_CNT1			0x0040
+#define XP_DRIVER_INT_REQ		0x0060
+#define XP_DRIVER_INT_RO		0x0064
+#define XP_DRIVER_SCRATCH_0		0x0068
+#define XP_DRIVER_SCRATCH_1		0x006c
+#define XP_INT_EN			0x0078
+#define XP_I2C_MUTEX			0x0080
+#define XP_MDIO_MUTEX			0x0084
+
+/* MAC Control register entry bit positions and sizes */
+#define XP_DRIVER_INT_REQ_REQUEST_INDEX		0
+#define XP_DRIVER_INT_REQ_REQUEST_WIDTH		1
+#define XP_DRIVER_INT_RO_STATUS_INDEX		0
+#define XP_DRIVER_INT_RO_STATUS_WIDTH		1
+#define XP_DRIVER_SCRATCH_0_COMMAND_INDEX	0
+#define XP_DRIVER_SCRATCH_0_COMMAND_WIDTH	8
+#define XP_DRIVER_SCRATCH_0_SUB_COMMAND_INDEX	8
+#define XP_DRIVER_SCRATCH_0_SUB_COMMAND_WIDTH	8
+#define XP_ECC_CNT0_RX_DED_INDEX		24
+#define XP_ECC_CNT0_RX_DED_WIDTH		8
+#define XP_ECC_CNT0_RX_SEC_INDEX		16
+#define XP_ECC_CNT0_RX_SEC_WIDTH		8
+#define XP_ECC_CNT0_TX_DED_INDEX		8
+#define XP_ECC_CNT0_TX_DED_WIDTH		8
+#define XP_ECC_CNT0_TX_SEC_INDEX		0
+#define XP_ECC_CNT0_TX_SEC_WIDTH		8
+#define XP_ECC_CNT1_DESC_DED_INDEX		8
+#define XP_ECC_CNT1_DESC_DED_WIDTH		8
+#define XP_ECC_CNT1_DESC_SEC_INDEX		0
+#define XP_ECC_CNT1_DESC_SEC_WIDTH		8
+#define XP_ECC_IER_DESC_DED_INDEX		0
+#define XP_ECC_IER_DESC_DED_WIDTH		1
+#define XP_ECC_IER_DESC_SEC_INDEX		1
+#define XP_ECC_IER_DESC_SEC_WIDTH		1
+#define XP_ECC_IER_RX_DED_INDEX			2
+#define XP_ECC_IER_RX_DED_WIDTH			1
+#define XP_ECC_IER_RX_SEC_INDEX			3
+#define XP_ECC_IER_RX_SEC_WIDTH			1
+#define XP_ECC_IER_TX_DED_INDEX			4
+#define XP_ECC_IER_TX_DED_WIDTH			1
+#define XP_ECC_IER_TX_SEC_INDEX			5
+#define XP_ECC_IER_TX_SEC_WIDTH			1
+#define XP_ECC_ISR_DESC_DED_INDEX		0
+#define XP_ECC_ISR_DESC_DED_WIDTH		1
+#define XP_ECC_ISR_DESC_SEC_INDEX		1
+#define XP_ECC_ISR_DESC_SEC_WIDTH		1
+#define XP_ECC_ISR_RX_DED_INDEX			2
+#define XP_ECC_ISR_RX_DED_WIDTH			1
+#define XP_ECC_ISR_RX_SEC_INDEX			3
+#define XP_ECC_ISR_RX_SEC_WIDTH			1
+#define XP_ECC_ISR_TX_DED_INDEX			4
+#define XP_ECC_ISR_TX_DED_WIDTH			1
+#define XP_ECC_ISR_TX_SEC_INDEX			5
+#define XP_ECC_ISR_TX_SEC_WIDTH			1
+#define XP_I2C_MUTEX_BUSY_INDEX			31
+#define XP_I2C_MUTEX_BUSY_WIDTH			1
+#define XP_I2C_MUTEX_ID_INDEX			29
+#define XP_I2C_MUTEX_ID_WIDTH			2
+#define XP_I2C_MUTEX_ACTIVE_INDEX		0
+#define XP_I2C_MUTEX_ACTIVE_WIDTH		1
+#define XP_MAC_ADDR_HI_VALID_INDEX		31
+#define XP_MAC_ADDR_HI_VALID_WIDTH		1
+#define XP_PROP_0_CONN_TYPE_INDEX		28
+#define XP_PROP_0_CONN_TYPE_WIDTH		3
+#define XP_PROP_0_MDIO_ADDR_INDEX		16
+#define XP_PROP_0_MDIO_ADDR_WIDTH		5
+#define XP_PROP_0_PORT_ID_INDEX			0
+#define XP_PROP_0_PORT_ID_WIDTH			8
+#define XP_PROP_0_PORT_MODE_INDEX		8
+#define XP_PROP_0_PORT_MODE_WIDTH		4
+#define XP_PROP_0_PORT_SPEEDS_INDEX		23
+#define XP_PROP_0_PORT_SPEEDS_WIDTH		4
+#define XP_PROP_1_MAX_RX_DMA_INDEX		24
+#define XP_PROP_1_MAX_RX_DMA_WIDTH		5
+#define XP_PROP_1_MAX_RX_QUEUES_INDEX		8
+#define XP_PROP_1_MAX_RX_QUEUES_WIDTH		5
+#define XP_PROP_1_MAX_TX_DMA_INDEX		16
+#define XP_PROP_1_MAX_TX_DMA_WIDTH		5
+#define XP_PROP_1_MAX_TX_QUEUES_INDEX		0
+#define XP_PROP_1_MAX_TX_QUEUES_WIDTH		5
+#define XP_PROP_2_RX_FIFO_SIZE_INDEX		16
+#define XP_PROP_2_RX_FIFO_SIZE_WIDTH		16
+#define XP_PROP_2_TX_FIFO_SIZE_INDEX		0
+#define XP_PROP_2_TX_FIFO_SIZE_WIDTH		16
+#define XP_PROP_3_GPIO_MASK_INDEX		28
+#define XP_PROP_3_GPIO_MASK_WIDTH		4
+#define XP_PROP_3_GPIO_MOD_ABS_INDEX		20
+#define XP_PROP_3_GPIO_MOD_ABS_WIDTH		4
+#define XP_PROP_3_GPIO_RATE_SELECT_INDEX	16
+#define XP_PROP_3_GPIO_RATE_SELECT_WIDTH	4
+#define XP_PROP_3_GPIO_RX_LOS_INDEX		24
+#define XP_PROP_3_GPIO_RX_LOS_WIDTH		4
+#define XP_PROP_3_GPIO_TX_FAULT_INDEX		12
+#define XP_PROP_3_GPIO_TX_FAULT_WIDTH		4
+#define XP_PROP_3_GPIO_ADDR_INDEX		8
+#define XP_PROP_3_GPIO_ADDR_WIDTH		3
+#define XP_PROP_3_MDIO_RESET_INDEX		0
+#define XP_PROP_3_MDIO_RESET_WIDTH		2
+#define XP_PROP_3_MDIO_RESET_I2C_ADDR_INDEX	8
+#define XP_PROP_3_MDIO_RESET_I2C_ADDR_WIDTH	3
+#define XP_PROP_3_MDIO_RESET_I2C_GPIO_INDEX	12
+#define XP_PROP_3_MDIO_RESET_I2C_GPIO_WIDTH	4
+#define XP_PROP_3_MDIO_RESET_INT_GPIO_INDEX	4
+#define XP_PROP_3_MDIO_RESET_INT_GPIO_WIDTH	2
+#define XP_PROP_4_MUX_ADDR_HI_INDEX		8
+#define XP_PROP_4_MUX_ADDR_HI_WIDTH		5
+#define XP_PROP_4_MUX_ADDR_LO_INDEX		0
+#define XP_PROP_4_MUX_ADDR_LO_WIDTH		3
+#define XP_PROP_4_MUX_CHAN_INDEX		4
+#define XP_PROP_4_MUX_CHAN_WIDTH		3
+#define XP_PROP_4_REDRV_ADDR_INDEX		16
+#define XP_PROP_4_REDRV_ADDR_WIDTH		7
+#define XP_PROP_4_REDRV_IF_INDEX		23
+#define XP_PROP_4_REDRV_IF_WIDTH		1
+#define XP_PROP_4_REDRV_LANE_INDEX		24
+#define XP_PROP_4_REDRV_LANE_WIDTH		3
+#define XP_PROP_4_REDRV_MODEL_INDEX		28
+#define XP_PROP_4_REDRV_MODEL_WIDTH		3
+#define XP_PROP_4_REDRV_PRESENT_INDEX		31
+#define XP_PROP_4_REDRV_PRESENT_WIDTH		1
+
+/* I2C Control register offsets */
+#define IC_CON					0x0000
+#define IC_TAR					0x0004
+#define IC_DATA_CMD				0x0010
+#define IC_INTR_STAT				0x002c
+#define IC_INTR_MASK				0x0030
+#define IC_RAW_INTR_STAT			0x0034
+#define IC_CLR_INTR				0x0040
+#define IC_CLR_TX_ABRT				0x0054
+#define IC_CLR_STOP_DET				0x0060
+#define IC_ENABLE				0x006c
+#define IC_TXFLR				0x0074
+#define IC_RXFLR				0x0078
+#define IC_TX_ABRT_SOURCE			0x0080
+#define IC_ENABLE_STATUS			0x009c
+#define IC_COMP_PARAM_1				0x00f4
+
+/* I2C Control register entry bit positions and sizes */
+#define IC_COMP_PARAM_1_MAX_SPEED_MODE_INDEX	2
+#define IC_COMP_PARAM_1_MAX_SPEED_MODE_WIDTH	2
+#define IC_COMP_PARAM_1_RX_BUFFER_DEPTH_INDEX	8
+#define IC_COMP_PARAM_1_RX_BUFFER_DEPTH_WIDTH	8
+#define IC_COMP_PARAM_1_TX_BUFFER_DEPTH_INDEX	16
+#define IC_COMP_PARAM_1_TX_BUFFER_DEPTH_WIDTH	8
+#define IC_CON_MASTER_MODE_INDEX		0
+#define IC_CON_MASTER_MODE_WIDTH		1
+#define IC_CON_RESTART_EN_INDEX			5
+#define IC_CON_RESTART_EN_WIDTH			1
+#define IC_CON_RX_FIFO_FULL_HOLD_INDEX		9
+#define IC_CON_RX_FIFO_FULL_HOLD_WIDTH		1
+#define IC_CON_SLAVE_DISABLE_INDEX		6
+#define IC_CON_SLAVE_DISABLE_WIDTH		1
+#define IC_CON_SPEED_INDEX			1
+#define IC_CON_SPEED_WIDTH			2
+#define IC_DATA_CMD_CMD_INDEX			8
+#define IC_DATA_CMD_CMD_WIDTH			1
+#define IC_DATA_CMD_STOP_INDEX			9
+#define IC_DATA_CMD_STOP_WIDTH			1
+#define IC_ENABLE_ABORT_INDEX			1
+#define IC_ENABLE_ABORT_WIDTH			1
+#define IC_ENABLE_EN_INDEX			0
+#define IC_ENABLE_EN_WIDTH			1
+#define IC_ENABLE_STATUS_EN_INDEX		0
+#define IC_ENABLE_STATUS_EN_WIDTH		1
+#define IC_INTR_MASK_TX_EMPTY_INDEX		4
+#define IC_INTR_MASK_TX_EMPTY_WIDTH		1
+#define IC_RAW_INTR_STAT_RX_FULL_INDEX		2
+#define IC_RAW_INTR_STAT_RX_FULL_WIDTH		1
+#define IC_RAW_INTR_STAT_STOP_DET_INDEX		9
+#define IC_RAW_INTR_STAT_STOP_DET_WIDTH		1
+#define IC_RAW_INTR_STAT_TX_ABRT_INDEX		6
+#define IC_RAW_INTR_STAT_TX_ABRT_WIDTH		1
+#define IC_RAW_INTR_STAT_TX_EMPTY_INDEX		4
+#define IC_RAW_INTR_STAT_TX_EMPTY_WIDTH		1
+
+/* I2C Control register value */
+#define IC_TX_ABRT_7B_ADDR_NOACK		0x0001
+#define IC_TX_ABRT_ARB_LOST			0x1000
+
 /* Descriptor/Packet entry bit positions and sizes */
 #define RX_PACKET_ERRORS_CRC_INDEX		2
 #define RX_PACKET_ERRORS_CRC_WIDTH		1
@@ -1027,6 +1258,10 @@
 #define MDIO_PMA_10GBR_FECCTRL		0x00ab
 #endif
 
+#ifndef MDIO_PCS_DIG_CTRL
+#define MDIO_PCS_DIG_CTRL		0x8000
+#endif
+
 #ifndef MDIO_AN_XNP
 #define MDIO_AN_XNP			0x0016
 #endif
@@ -1047,11 +1282,48 @@
 #define MDIO_AN_INT			0x8002
 #endif
 
+#ifndef MDIO_VEND2_AN_ADVERTISE
+#define MDIO_VEND2_AN_ADVERTISE		0x0004
+#endif
+
+#ifndef MDIO_VEND2_AN_LP_ABILITY
+#define MDIO_VEND2_AN_LP_ABILITY	0x0005
+#endif
+
+#ifndef MDIO_VEND2_AN_CTRL
+#define MDIO_VEND2_AN_CTRL		0x8001
+#endif
+
+#ifndef MDIO_VEND2_AN_STAT
+#define MDIO_VEND2_AN_STAT		0x8002
+#endif
+
 #ifndef MDIO_CTRL1_SPEED1G
 #define MDIO_CTRL1_SPEED1G		(MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
 #endif
 
+#ifndef MDIO_VEND2_CTRL1_AN_ENABLE
+#define MDIO_VEND2_CTRL1_AN_ENABLE	BIT(12)
+#endif
+
+#ifndef MDIO_VEND2_CTRL1_AN_RESTART
+#define MDIO_VEND2_CTRL1_AN_RESTART	BIT(9)
+#endif
+
+#ifndef MDIO_VEND2_CTRL1_SS6
+#define MDIO_VEND2_CTRL1_SS6		BIT(6)
+#endif
+
+#ifndef MDIO_VEND2_CTRL1_SS13
+#define MDIO_VEND2_CTRL1_SS13		BIT(13)
+#endif
+
 /* MDIO mask values */
+#define XGBE_AN_CL73_INT_CMPLT		BIT(0)
+#define XGBE_AN_CL73_INC_LINK		BIT(1)
+#define XGBE_AN_CL73_PG_RCV		BIT(2)
+#define XGBE_AN_CL73_INT_MASK		0x07
+
 #define XGBE_XNP_MCF_NULL_MESSAGE	0x001
 #define XGBE_XNP_ACK_PROCESSED		BIT(12)
 #define XGBE_XNP_MP_FORMATTED		BIT(13)
@@ -1060,6 +1332,19 @@
 #define XGBE_KR_TRAINING_START		BIT(0)
 #define XGBE_KR_TRAINING_ENABLE		BIT(1)
 
+#define XGBE_PCS_CL37_BP		BIT(12)
+
+#define XGBE_AN_CL37_INT_CMPLT		BIT(0)
+#define XGBE_AN_CL37_INT_MASK		0x01
+
+#define XGBE_AN_CL37_HD_MASK		0x40
+#define XGBE_AN_CL37_FD_MASK		0x20
+
+#define XGBE_AN_CL37_PCS_MODE_MASK	0x06
+#define XGBE_AN_CL37_PCS_MODE_BASEX	0x00
+#define XGBE_AN_CL37_PCS_MODE_SGMII	0x04
+#define XGBE_AN_CL37_TX_CONFIG_MASK	0x08
+
 /* Bit setting and getting macros
  *  The get macro will extract the current bit field value from within
  *  the variable
@@ -1195,12 +1480,28 @@ do {									\
 /* Macros for building, reading or writing register values or bits
  * within the register values of XPCS registers.
  */
-#define XPCS_IOWRITE(_pdata, _off, _val)				\
+#define XPCS_GET_BITS(_var, _prefix, _field)				\
+	GET_BITS((_var),                                                \
+		 _prefix##_##_field##_INDEX,                            \
+		 _prefix##_##_field##_WIDTH)
+
+#define XPCS_SET_BITS(_var, _prefix, _field, _val)                      \
+	SET_BITS((_var),                                                \
+		 _prefix##_##_field##_INDEX,                            \
+		 _prefix##_##_field##_WIDTH, (_val))
+
+#define XPCS32_IOWRITE(_pdata, _off, _val)				\
 	iowrite32(_val, (_pdata)->xpcs_regs + (_off))
 
-#define XPCS_IOREAD(_pdata, _off)					\
+#define XPCS32_IOREAD(_pdata, _off)					\
 	ioread32((_pdata)->xpcs_regs + (_off))
 
+#define XPCS16_IOWRITE(_pdata, _off, _val)				\
+	iowrite16(_val, (_pdata)->xpcs_regs + (_off))
+
+#define XPCS16_IOREAD(_pdata, _off)					\
+	ioread16((_pdata)->xpcs_regs + (_off))
+
 /* Macros for building, reading or writing register values or bits
  * within the register values of SerDes integration registers.
  */
@@ -1278,6 +1579,72 @@ do {									\
 } while (0)
 
 /* Macros for building, reading or writing register values or bits
+ * within the register values of MAC Control registers.
+ */
+#define XP_GET_BITS(_var, _prefix, _field)				\
+	GET_BITS((_var),						\
+		 _prefix##_##_field##_INDEX,				\
+		 _prefix##_##_field##_WIDTH)
+
+#define XP_SET_BITS(_var, _prefix, _field, _val)			\
+	SET_BITS((_var),						\
+		 _prefix##_##_field##_INDEX,				\
+		 _prefix##_##_field##_WIDTH, (_val))
+
+#define XP_IOREAD(_pdata, _reg)						\
+	ioread32((_pdata)->xprop_regs + (_reg))
+
+#define XP_IOREAD_BITS(_pdata, _reg, _field)				\
+	GET_BITS(XP_IOREAD((_pdata), (_reg)),				\
+		 _reg##_##_field##_INDEX,				\
+		 _reg##_##_field##_WIDTH)
+
+#define XP_IOWRITE(_pdata, _reg, _val)					\
+	iowrite32((_val), (_pdata)->xprop_regs + (_reg))
+
+#define XP_IOWRITE_BITS(_pdata, _reg, _field, _val)			\
+do {									\
+	u32 reg_val = XP_IOREAD((_pdata), (_reg));			\
+	SET_BITS(reg_val,						\
+		 _reg##_##_field##_INDEX,				\
+		 _reg##_##_field##_WIDTH, (_val));			\
+	XP_IOWRITE((_pdata), (_reg), reg_val);				\
+} while (0)
+
+/* Macros for building, reading or writing register values or bits
+ * within the register values of I2C Control registers.
+ */
+#define XI2C_GET_BITS(_var, _prefix, _field)				\
+	GET_BITS((_var),						\
+		 _prefix##_##_field##_INDEX,				\
+		 _prefix##_##_field##_WIDTH)
+
+#define XI2C_SET_BITS(_var, _prefix, _field, _val)			\
+	SET_BITS((_var),						\
+		 _prefix##_##_field##_INDEX,				\
+		 _prefix##_##_field##_WIDTH, (_val))
+
+#define XI2C_IOREAD(_pdata, _reg)					\
+	ioread32((_pdata)->xi2c_regs + (_reg))
+
+#define XI2C_IOREAD_BITS(_pdata, _reg, _field)				\
+	GET_BITS(XI2C_IOREAD((_pdata), (_reg)),				\
+		 _reg##_##_field##_INDEX,				\
+		 _reg##_##_field##_WIDTH)
+
+#define XI2C_IOWRITE(_pdata, _reg, _val)				\
+	iowrite32((_val), (_pdata)->xi2c_regs + (_reg))
+
+#define XI2C_IOWRITE_BITS(_pdata, _reg, _field, _val)			\
+do {									\
+	u32 reg_val = XI2C_IOREAD((_pdata), (_reg));			\
+	SET_BITS(reg_val,						\
+		 _reg##_##_field##_INDEX,				\
+		 _reg##_##_field##_WIDTH, (_val));			\
+	XI2C_IOWRITE((_pdata), (_reg), reg_val);			\
+} while (0)
+
+/* Macros for building, reading or writing register values or bits
  * using MDIO.  Different from above because of the use of standardized
  * Linux include values.  No shifting is performed with the bit
  * operations, everything works on mask values.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -153,7 +153,7 @@ static ssize_t xgbe_common_write(const c
 	int ret;
 
 	if (*ppos != 0)
-		return 0;
+		return -EINVAL;
 
 	if (count >= sizeof(workarea))
 		return -ENOSPC;
@@ -316,6 +316,126 @@ static const struct file_operations xpcs
 	.write = xpcs_reg_value_write,
 };
 
+static ssize_t xprop_reg_addr_read(struct file *filp, char __user *buffer,
+				   size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+
+	return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xprop_reg);
+}
+
+static ssize_t xprop_reg_addr_write(struct file *filp,
+				    const char __user *buffer,
+				    size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+
+	return xgbe_common_write(buffer, count, ppos,
+				 &pdata->debugfs_xprop_reg);
+}
+
+static ssize_t xprop_reg_value_read(struct file *filp, char __user *buffer,
+				    size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+	unsigned int value;
+
+	value = XP_IOREAD(pdata, pdata->debugfs_xprop_reg);
+
+	return xgbe_common_read(buffer, count, ppos, value);
+}
+
+static ssize_t xprop_reg_value_write(struct file *filp,
+				     const char __user *buffer,
+				     size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+	unsigned int value;
+	ssize_t len;
+
+	len = xgbe_common_write(buffer, count, ppos, &value);
+	if (len < 0)
+		return len;
+
+	XP_IOWRITE(pdata, pdata->debugfs_xprop_reg, value);
+
+	return len;
+}
+
+static const struct file_operations xprop_reg_addr_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read =  xprop_reg_addr_read,
+	.write = xprop_reg_addr_write,
+};
+
+static const struct file_operations xprop_reg_value_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read =  xprop_reg_value_read,
+	.write = xprop_reg_value_write,
+};
+
+static ssize_t xi2c_reg_addr_read(struct file *filp, char __user *buffer,
+				  size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+
+	return xgbe_common_read(buffer, count, ppos, pdata->debugfs_xi2c_reg);
+}
+
+static ssize_t xi2c_reg_addr_write(struct file *filp,
+				   const char __user *buffer,
+				   size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+
+	return xgbe_common_write(buffer, count, ppos,
+				 &pdata->debugfs_xi2c_reg);
+}
+
+static ssize_t xi2c_reg_value_read(struct file *filp, char __user *buffer,
+				   size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+	unsigned int value;
+
+	value = XI2C_IOREAD(pdata, pdata->debugfs_xi2c_reg);
+
+	return xgbe_common_read(buffer, count, ppos, value);
+}
+
+static ssize_t xi2c_reg_value_write(struct file *filp,
+				    const char __user *buffer,
+				    size_t count, loff_t *ppos)
+{
+	struct xgbe_prv_data *pdata = filp->private_data;
+	unsigned int value;
+	ssize_t len;
+
+	len = xgbe_common_write(buffer, count, ppos, &value);
+	if (len < 0)
+		return len;
+
+	XI2C_IOWRITE(pdata, pdata->debugfs_xi2c_reg, value);
+
+	return len;
+}
+
+static const struct file_operations xi2c_reg_addr_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read =  xi2c_reg_addr_read,
+	.write = xi2c_reg_addr_write,
+};
+
+static const struct file_operations xi2c_reg_value_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read =  xi2c_reg_value_read,
+	.write = xi2c_reg_value_write,
+};
+
 void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
 {
 	struct dentry *pfile;
@@ -367,6 +487,38 @@ void xgbe_debugfs_init(struct xgbe_prv_d
 	if (!pfile)
 		netdev_err(pdata->netdev, "debugfs_create_file failed\n");
 
+	if (pdata->xprop_regs) {
+		pfile = debugfs_create_file("xprop_register", 0600,
+					    pdata->xgbe_debugfs, pdata,
+					    &xprop_reg_addr_fops);
+		if (!pfile)
+			netdev_err(pdata->netdev,
+				   "debugfs_create_file failed\n");
+
+		pfile = debugfs_create_file("xprop_register_value", 0600,
+					    pdata->xgbe_debugfs, pdata,
+					    &xprop_reg_value_fops);
+		if (!pfile)
+			netdev_err(pdata->netdev,
+				   "debugfs_create_file failed\n");
+	}
+
+	if (pdata->xi2c_regs) {
+		pfile = debugfs_create_file("xi2c_register", 0600,
+					    pdata->xgbe_debugfs, pdata,
+					    &xi2c_reg_addr_fops);
+		if (!pfile)
+			netdev_err(pdata->netdev,
+				   "debugfs_create_file failed\n");
+
+		pfile = debugfs_create_file("xi2c_register_value", 0600,
+					    pdata->xgbe_debugfs, pdata,
+					    &xi2c_reg_value_fops);
+		if (!pfile)
+			netdev_err(pdata->netdev,
+				   "debugfs_create_file failed\n");
+	}
+
 	kfree(buf);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-dev.c	2017-02-12 16:03:20.000000000 -0500
@@ -123,6 +123,11 @@
 #include "xgbe.h"
 #include "xgbe-common.h"
 
+static inline unsigned int xgbe_get_max_frame(struct xgbe_prv_data *pdata)
+{
+	return pdata->netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+}
+
 static unsigned int xgbe_usec_to_riwt(struct xgbe_prv_data *pdata,
 				      unsigned int usec)
 {
@@ -491,6 +496,27 @@ static void xgbe_config_rss(struct xgbe_
 			   "error configuring RSS, RSS disabled\n");
 }
 
+static bool xgbe_is_pfc_queue(struct xgbe_prv_data *pdata,
+			      unsigned int queue)
+{
+	unsigned int prio, tc;
+
+	for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
+		/* Does this queue handle the priority? */
+		if (pdata->prio2q_map[prio] != queue)
+			continue;
+
+		/* Get the Traffic Class for this priority */
+		tc = pdata->ets->prio_tc[prio];
+
+		/* Check if PFC is enabled for this traffic class */
+		if (pdata->pfc->pfc_en & (1 << tc))
+			return true;
+	}
+
+	return false;
+}
+
 static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
 {
 	unsigned int max_q_count, q_count;
@@ -528,27 +554,14 @@ static int xgbe_enable_tx_flow_control(s
 	for (i = 0; i < pdata->rx_q_count; i++) {
 		unsigned int ehfc = 0;
 
-		if (pfc && ets) {
-			unsigned int prio;
-
-			for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
-				unsigned int tc;
-
-				/* Does this queue handle the priority? */
-				if (pdata->prio2q_map[prio] != i)
-					continue;
-
-				/* Get the Traffic Class for this priority */
-				tc = ets->prio_tc[prio];
-
-				/* Check if flow control should be enabled */
-				if (pfc->pfc_en & (1 << tc)) {
+		if (pdata->rx_rfd[i]) {
+			/* Flow control thresholds are established */
+			if (pfc && ets) {
+				if (xgbe_is_pfc_queue(pdata, i))
 					ehfc = 1;
-					break;
-				}
+			} else {
+				ehfc = 1;
 			}
-		} else {
-			ehfc = 1;
 		}
 
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, ehfc);
@@ -633,6 +646,11 @@ static void xgbe_enable_dma_interrupts(s
 	unsigned int dma_ch_isr, dma_ch_ier;
 	unsigned int i;
 
+	/* Set the interrupt mode if supported */
+	if (pdata->channel_irq_mode)
+		XGMAC_IOWRITE_BITS(pdata, DMA_MR, INTM,
+				   pdata->channel_irq_mode);
+
 	channel = pdata->channel;
 	for (i = 0; i < pdata->channel_count; i++, channel++) {
 		/* Clear all the interrupts which are set */
@@ -654,19 +672,21 @@ static void xgbe_enable_dma_interrupts(s
 		if (channel->tx_ring) {
 			/* Enable the following Tx interrupts
 			 *   TIE  - Transmit Interrupt Enable (unless using
-			 *          per channel interrupts)
+			 *          per channel interrupts in edge triggered
+			 *          mode)
 			 */
-			if (!pdata->per_channel_irq)
+			if (!pdata->per_channel_irq || pdata->channel_irq_mode)
 				XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, TIE, 1);
 		}
 		if (channel->rx_ring) {
 			/* Enable following Rx interrupts
 			 *   RBUE - Receive Buffer Unavailable Enable
 			 *   RIE  - Receive Interrupt Enable (unless using
-			 *          per channel interrupts)
+			 *          per channel interrupts in edge triggered
+			 *          mode)
 			 */
 			XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RBUE, 1);
-			if (!pdata->per_channel_irq)
+			if (!pdata->per_channel_irq || pdata->channel_irq_mode)
 				XGMAC_SET_BITS(dma_ch_ier, DMA_CH_IER, RIE, 1);
 		}
 
@@ -702,34 +722,90 @@ static void xgbe_enable_mac_interrupts(s
 	/* Enable all counter interrupts */
 	XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xffffffff);
 	XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff);
+
+	/* Enable MDIO single command completion interrupt */
+	XGMAC_IOWRITE_BITS(pdata, MAC_MDIOIER, SNGLCOMPIE, 1);
 }
 
-static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
+static void xgbe_enable_ecc_interrupts(struct xgbe_prv_data *pdata)
 {
-	if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x3)
-		return 0;
+	unsigned int ecc_isr, ecc_ier = 0;
 
-	XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x3);
+	if (!pdata->vdata->ecc_support)
+		return;
 
-	return 0;
+	/* Clear all the interrupts which are set */
+	ecc_isr = XP_IOREAD(pdata, XP_ECC_ISR);
+	XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr);
+
+	/* Enable ECC interrupts */
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_DED, 1);
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_SEC, 1);
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_DED, 1);
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_SEC, 1);
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_DED, 1);
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_SEC, 1);
+
+	XP_IOWRITE(pdata, XP_ECC_IER, ecc_ier);
 }
 
-static int xgbe_set_gmii_2500_speed(struct xgbe_prv_data *pdata)
+static void xgbe_disable_ecc_ded(struct xgbe_prv_data *pdata)
 {
-	if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0x2)
-		return 0;
+	unsigned int ecc_ier;
 
-	XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0x2);
+	ecc_ier = XP_IOREAD(pdata, XP_ECC_IER);
 
-	return 0;
+	/* Disable ECC DED interrupts */
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_DED, 0);
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_DED, 0);
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_DED, 0);
+
+	XP_IOWRITE(pdata, XP_ECC_IER, ecc_ier);
 }
 
-static int xgbe_set_xgmii_speed(struct xgbe_prv_data *pdata)
+static void xgbe_disable_ecc_sec(struct xgbe_prv_data *pdata,
+				 enum xgbe_ecc_sec sec)
 {
-	if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) == 0)
-		return 0;
+	unsigned int ecc_ier;
 
-	XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, 0);
+	ecc_ier = XP_IOREAD(pdata, XP_ECC_IER);
+
+	/* Disable ECC SEC interrupt */
+	switch (sec) {
+	case XGBE_ECC_SEC_TX:
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, TX_SEC, 0);
+		break;
+	case XGBE_ECC_SEC_RX:
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, RX_SEC, 0);
+		break;
+	case XGBE_ECC_SEC_DESC:
+	XP_SET_BITS(ecc_ier, XP_ECC_IER, DESC_SEC, 0);
+		break;
+	}
+
+	XP_IOWRITE(pdata, XP_ECC_IER, ecc_ier);
+}
+
+static int xgbe_set_speed(struct xgbe_prv_data *pdata, int speed)
+{
+	unsigned int ss;
+
+	switch (speed) {
+	case SPEED_1000:
+		ss = 0x03;
+		break;
+	case SPEED_2500:
+		ss = 0x02;
+		break;
+	case SPEED_10000:
+		ss = 0x00;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (XGMAC_IOREAD_BITS(pdata, MAC_TCR, SS) != ss)
+		XGMAC_IOWRITE_BITS(pdata, MAC_TCR, SS, ss);
 
 	return 0;
 }
@@ -1019,8 +1095,101 @@ static int xgbe_config_rx_mode(struct xg
 	return 0;
 }
 
-static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
-			      int mmd_reg)
+static int xgbe_clr_gpio(struct xgbe_prv_data *pdata, unsigned int gpio)
+{
+	unsigned int reg;
+
+	if (gpio > 15)
+		return -EINVAL;
+
+	reg = XGMAC_IOREAD(pdata, MAC_GPIOSR);
+
+	reg &= ~(1 << (gpio + 16));
+	XGMAC_IOWRITE(pdata, MAC_GPIOSR, reg);
+
+	return 0;
+}
+
+static int xgbe_set_gpio(struct xgbe_prv_data *pdata, unsigned int gpio)
+{
+	unsigned int reg;
+
+	if (gpio > 15)
+		return -EINVAL;
+
+	reg = XGMAC_IOREAD(pdata, MAC_GPIOSR);
+
+	reg |= (1 << (gpio + 16));
+	XGMAC_IOWRITE(pdata, MAC_GPIOSR, reg);
+
+	return 0;
+}
+
+static int xgbe_read_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
+				 int mmd_reg)
+{
+	unsigned long flags;
+	unsigned int mmd_address, index, offset;
+	int mmd_data;
+
+	if (mmd_reg & MII_ADDR_C45)
+		mmd_address = mmd_reg & ~MII_ADDR_C45;
+	else
+		mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
+
+	/* The PCS registers are accessed using mmio. The underlying
+	 * management interface uses indirect addressing to access the MMD
+	 * register sets. This requires accessing of the PCS register in two
+	 * phases, an address phase and a data phase.
+	 *
+	 * The mmio interface is based on 16-bit offsets and values. All
+	 * register offsets must therefore be adjusted by left shifting the
+	 * offset 1 bit and reading 16 bits of data.
+	 */
+	mmd_address <<= 1;
+	index = mmd_address & ~pdata->xpcs_window_mask;
+	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
+
+	spin_lock_irqsave(&pdata->xpcs_lock, flags);
+	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
+	mmd_data = XPCS16_IOREAD(pdata, offset);
+	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
+
+	return mmd_data;
+}
+
+static void xgbe_write_mmd_regs_v2(struct xgbe_prv_data *pdata, int prtad,
+				   int mmd_reg, int mmd_data)
+{
+	unsigned long flags;
+	unsigned int mmd_address, index, offset;
+
+	if (mmd_reg & MII_ADDR_C45)
+		mmd_address = mmd_reg & ~MII_ADDR_C45;
+	else
+		mmd_address = (pdata->mdio_mmd << 16) | (mmd_reg & 0xffff);
+
+	/* The PCS registers are accessed using mmio. The underlying
+	 * management interface uses indirect addressing to access the MMD
+	 * register sets. This requires accessing of the PCS register in two
+	 * phases, an address phase and a data phase.
+	 *
+	 * The mmio interface is based on 16-bit offsets and values. All
+	 * register offsets must therefore be adjusted by left shifting the
+	 * offset 1 bit and writing 16 bits of data.
+	 */
+	mmd_address <<= 1;
+	index = mmd_address & ~pdata->xpcs_window_mask;
+	offset = pdata->xpcs_window + (mmd_address & pdata->xpcs_window_mask);
+
+	spin_lock_irqsave(&pdata->xpcs_lock, flags);
+	XPCS32_IOWRITE(pdata, pdata->xpcs_window_sel_reg, index);
+	XPCS16_IOWRITE(pdata, offset, mmd_data);
+	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
+}
+
+static int xgbe_read_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
+				 int mmd_reg)
 {
 	unsigned long flags;
 	unsigned int mmd_address;
@@ -1041,15 +1210,15 @@ static int xgbe_read_mmd_regs(struct xgb
 	 * offset 2 bits and reading 32 bits of data.
 	 */
 	spin_lock_irqsave(&pdata->xpcs_lock, flags);
-	XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
-	mmd_data = XPCS_IOREAD(pdata, (mmd_address & 0xff) << 2);
+	XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
+	mmd_data = XPCS32_IOREAD(pdata, (mmd_address & 0xff) << 2);
 	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
 
 	return mmd_data;
 }
 
-static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
-				int mmd_reg, int mmd_data)
+static void xgbe_write_mmd_regs_v1(struct xgbe_prv_data *pdata, int prtad,
+				   int mmd_reg, int mmd_data)
 {
 	unsigned int mmd_address;
 	unsigned long flags;
@@ -1066,14 +1235,113 @@ static void xgbe_write_mmd_regs(struct x
 	 *
 	 * The mmio interface is based on 32-bit offsets and values. All
 	 * register offsets must therefore be adjusted by left shifting the
-	 * offset 2 bits and reading 32 bits of data.
+	 * offset 2 bits and writing 32 bits of data.
 	 */
 	spin_lock_irqsave(&pdata->xpcs_lock, flags);
-	XPCS_IOWRITE(pdata, PCS_MMD_SELECT << 2, mmd_address >> 8);
-	XPCS_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
+	XPCS32_IOWRITE(pdata, PCS_V1_WINDOW_SELECT, mmd_address >> 8);
+	XPCS32_IOWRITE(pdata, (mmd_address & 0xff) << 2, mmd_data);
 	spin_unlock_irqrestore(&pdata->xpcs_lock, flags);
 }
 
+static int xgbe_read_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+			      int mmd_reg)
+{
+	switch (pdata->vdata->xpcs_access) {
+	case XGBE_XPCS_ACCESS_V1:
+		return xgbe_read_mmd_regs_v1(pdata, prtad, mmd_reg);
+
+	case XGBE_XPCS_ACCESS_V2:
+	default:
+		return xgbe_read_mmd_regs_v2(pdata, prtad, mmd_reg);
+	}
+}
+
+static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
+				int mmd_reg, int mmd_data)
+{
+	switch (pdata->vdata->xpcs_access) {
+	case XGBE_XPCS_ACCESS_V1:
+		return xgbe_write_mmd_regs_v1(pdata, prtad, mmd_reg, mmd_data);
+
+	case XGBE_XPCS_ACCESS_V2:
+	default:
+		return xgbe_write_mmd_regs_v2(pdata, prtad, mmd_reg, mmd_data);
+	}
+}
+
+static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
+				   int reg, u16 val)
+{
+	unsigned int mdio_sca, mdio_sccd;
+
+	reinit_completion(&pdata->mdio_complete);
+
+	mdio_sca = 0;
+	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
+	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+	XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
+
+	mdio_sccd = 0;
+	XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, DATA, val);
+	XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 1);
+	XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
+	XGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
+
+	if (!wait_for_completion_timeout(&pdata->mdio_complete, HZ)) {
+		netdev_err(pdata->netdev, "mdio write operation timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
+				  int reg)
+{
+	unsigned int mdio_sca, mdio_sccd;
+
+	reinit_completion(&pdata->mdio_complete);
+
+	mdio_sca = 0;
+	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
+	XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+	XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
+
+	mdio_sccd = 0;
+	XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, CMD, 3);
+	XGMAC_SET_BITS(mdio_sccd, MAC_MDIOSCCDR, BUSY, 1);
+	XGMAC_IOWRITE(pdata, MAC_MDIOSCCDR, mdio_sccd);
+
+	if (!wait_for_completion_timeout(&pdata->mdio_complete, HZ)) {
+		netdev_err(pdata->netdev, "mdio read operation timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	return XGMAC_IOREAD_BITS(pdata, MAC_MDIOSCCDR, DATA);
+}
+
+static int xgbe_set_ext_mii_mode(struct xgbe_prv_data *pdata, unsigned int port,
+				 enum xgbe_mdio_mode mode)
+{
+	unsigned int reg_val = 0;
+
+	switch (mode) {
+	case XGBE_MDIO_MODE_CL22:
+		if (port > XGMAC_MAX_C22_PORT)
+			return -EINVAL;
+		reg_val |= (1 << port);
+		break;
+	case XGBE_MDIO_MODE_CL45:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	XGMAC_IOWRITE(pdata, MAC_MDIOCL22R, reg_val);
+
+	return 0;
+}
+
 static int xgbe_tx_complete(struct xgbe_ring_desc *rdesc)
 {
 	return !XGMAC_GET_BITS_LE(rdesc->desc3, TX_NORMAL_DESC3, OWN);
@@ -1264,14 +1532,21 @@ static u64 xgbe_get_tstamp_time(struct x
 
 static u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata)
 {
-	unsigned int tx_snr;
+	unsigned int tx_snr, tx_ssr;
 	u64 nsec;
 
-	tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
+	if (pdata->vdata->tx_tstamp_workaround) {
+		tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
+		tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
+	} else {
+		tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR);
+		tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR);
+	}
+
 	if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS))
 		return 0;
 
-	nsec = XGMAC_IOREAD(pdata, MAC_TXSSR);
+	nsec = tx_ssr;
 	nsec *= NSEC_PER_SEC;
 	nsec += tx_snr;
 
@@ -1327,106 +1602,6 @@ static int xgbe_config_tstamp(struct xgb
 	return 0;
 }
 
-static void xgbe_config_tc(struct xgbe_prv_data *pdata)
-{
-	unsigned int offset, queue, prio;
-	u8 i;
-
-	netdev_reset_tc(pdata->netdev);
-	if (!pdata->num_tcs)
-		return;
-
-	netdev_set_num_tc(pdata->netdev, pdata->num_tcs);
-
-	for (i = 0, queue = 0, offset = 0; i < pdata->num_tcs; i++) {
-		while ((queue < pdata->tx_q_count) &&
-		       (pdata->q2tc_map[queue] == i))
-			queue++;
-
-		netif_dbg(pdata, drv, pdata->netdev, "TC%u using TXq%u-%u\n",
-			  i, offset, queue - 1);
-		netdev_set_tc_queue(pdata->netdev, i, queue - offset, offset);
-		offset = queue;
-	}
-
-	if (!pdata->ets)
-		return;
-
-	for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
-		netdev_set_prio_tc_map(pdata->netdev, prio,
-				       pdata->ets->prio_tc[prio]);
-}
-
-static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
-{
-	struct ieee_ets *ets = pdata->ets;
-	unsigned int total_weight, min_weight, weight;
-	unsigned int mask, reg, reg_val;
-	unsigned int i, prio;
-
-	if (!ets)
-		return;
-
-	/* Set Tx to deficit weighted round robin scheduling algorithm (when
-	 * traffic class is using ETS algorithm)
-	 */
-	XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR);
-
-	/* Set Traffic Class algorithms */
-	total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt;
-	min_weight = total_weight / 100;
-	if (!min_weight)
-		min_weight = 1;
-
-	for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
-		/* Map the priorities to the traffic class */
-		mask = 0;
-		for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
-			if (ets->prio_tc[prio] == i)
-				mask |= (1 << prio);
-		}
-		mask &= 0xff;
-
-		netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n",
-			  i, mask);
-		reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG));
-		reg_val = XGMAC_IOREAD(pdata, reg);
-
-		reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3));
-		reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3));
-
-		XGMAC_IOWRITE(pdata, reg, reg_val);
-
-		/* Set the traffic class algorithm */
-		switch (ets->tc_tsa[i]) {
-		case IEEE_8021QAZ_TSA_STRICT:
-			netif_dbg(pdata, drv, pdata->netdev,
-				  "TC%u using SP\n", i);
-			XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
-					       MTL_TSA_SP);
-			break;
-		case IEEE_8021QAZ_TSA_ETS:
-			weight = total_weight * ets->tc_tx_bw[i] / 100;
-			weight = clamp(weight, min_weight, total_weight);
-
-			netif_dbg(pdata, drv, pdata->netdev,
-				  "TC%u using DWRR (weight %u)\n", i, weight);
-			XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
-					       MTL_TSA_ETS);
-			XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW,
-					       weight);
-			break;
-		}
-	}
-
-	xgbe_config_tc(pdata);
-}
-
-static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
-{
-	xgbe_config_flow_control(pdata);
-}
-
 static void xgbe_tx_start_xmit(struct xgbe_channel *channel,
 			       struct xgbe_ring *ring)
 {
@@ -1901,7 +2076,7 @@ static int xgbe_disable_int(struct xgbe_
 	return 0;
 }
 
-static int xgbe_exit(struct xgbe_prv_data *pdata)
+static int __xgbe_exit(struct xgbe_prv_data *pdata)
 {
 	unsigned int count = 2000;
 
@@ -1923,6 +2098,20 @@ static int xgbe_exit(struct xgbe_prv_dat
 	return 0;
 }
 
+static int xgbe_exit(struct xgbe_prv_data *pdata)
+{
+	int ret;
+
+	/* To guard against possible incorrectly generated interrupts,
+	 * issue the software reset twice.
+	 */
+	ret = __xgbe_exit(pdata);
+	if (ret)
+		return ret;
+
+	return __xgbe_exit(pdata);
+}
+
 static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata)
 {
 	unsigned int i, count;
@@ -2000,61 +2189,331 @@ static void xgbe_config_mtl_mode(struct
 	XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP);
 }
 
-static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size,
-						  unsigned int queue_count)
+static void xgbe_queue_flow_control_threshold(struct xgbe_prv_data *pdata,
+					      unsigned int queue,
+					      unsigned int q_fifo_size)
+{
+	unsigned int frame_fifo_size;
+	unsigned int rfa, rfd;
+
+	frame_fifo_size = XGMAC_FLOW_CONTROL_ALIGN(xgbe_get_max_frame(pdata));
+
+	if (pdata->pfcq[queue] && (q_fifo_size > pdata->pfc_rfa)) {
+		/* PFC is active for this queue */
+		rfa = pdata->pfc_rfa;
+		rfd = rfa + frame_fifo_size;
+		if (rfd > XGMAC_FLOW_CONTROL_MAX)
+			rfd = XGMAC_FLOW_CONTROL_MAX;
+		if (rfa >= XGMAC_FLOW_CONTROL_MAX)
+			rfa = XGMAC_FLOW_CONTROL_MAX - XGMAC_FLOW_CONTROL_UNIT;
+	} else {
+		/* This path deals with just maximum frame sizes which are
+		 * limited to a jumbo frame of 9,000 (plus headers, etc.)
+		 * so we can never exceed the maximum allowable RFA/RFD
+		 * values.
+		 */
+		if (q_fifo_size <= 2048) {
+			/* rx_rfd to zero to signal no flow control */
+			pdata->rx_rfa[queue] = 0;
+			pdata->rx_rfd[queue] = 0;
+			return;
+		}
+
+		if (q_fifo_size <= 4096) {
+			/* Between 2048 and 4096 */
+			pdata->rx_rfa[queue] = 0;	/* Full - 1024 bytes */
+			pdata->rx_rfd[queue] = 1;	/* Full - 1536 bytes */
+			return;
+		}
+
+		if (q_fifo_size <= frame_fifo_size) {
+			/* Between 4096 and max-frame */
+			pdata->rx_rfa[queue] = 2;	/* Full - 2048 bytes */
+			pdata->rx_rfd[queue] = 5;	/* Full - 3584 bytes */
+			return;
+		}
+
+		if (q_fifo_size <= (frame_fifo_size * 3)) {
+			/* Between max-frame and 3 max-frames,
+			 * trigger if we get just over a frame of data and
+			 * resume when we have just under half a frame left.
+			 */
+			rfa = q_fifo_size - frame_fifo_size;
+			rfd = rfa + (frame_fifo_size / 2);
+		} else {
+			/* Above 3 max-frames - trigger when just over
+			 * 2 frames of space available
+			 */
+			rfa = frame_fifo_size * 2;
+			rfa += XGMAC_FLOW_CONTROL_UNIT;
+			rfd = rfa + frame_fifo_size;
+		}
+	}
+
+	pdata->rx_rfa[queue] = XGMAC_FLOW_CONTROL_VALUE(rfa);
+	pdata->rx_rfd[queue] = XGMAC_FLOW_CONTROL_VALUE(rfd);
+}
+
+static void xgbe_calculate_flow_control_threshold(struct xgbe_prv_data *pdata,
+						  unsigned int *fifo)
 {
 	unsigned int q_fifo_size;
-	unsigned int p_fifo;
+	unsigned int i;
 
-	/* Calculate the configured fifo size */
-	q_fifo_size = 1 << (fifo_size + 7);
+	for (i = 0; i < pdata->rx_q_count; i++) {
+		q_fifo_size = (fifo[i] + 1) * XGMAC_FIFO_UNIT;
+
+		xgbe_queue_flow_control_threshold(pdata, i, q_fifo_size);
+	}
+}
+
+static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
+{
+	unsigned int i;
+
+	for (i = 0; i < pdata->rx_q_count; i++) {
+		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA,
+				       pdata->rx_rfa[i]);
+		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD,
+				       pdata->rx_rfd[i]);
+	}
+}
 
+static unsigned int xgbe_get_tx_fifo_size(struct xgbe_prv_data *pdata)
+{
 	/* The configured value may not be the actual amount of fifo RAM */
-	q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size);
+	return min_t(unsigned int, pdata->tx_max_fifo_size,
+		     pdata->hw_feat.tx_fifo_size);
+}
 
-	q_fifo_size = q_fifo_size / queue_count;
+static unsigned int xgbe_get_rx_fifo_size(struct xgbe_prv_data *pdata)
+{
+	/* The configured value may not be the actual amount of fifo RAM */
+	return min_t(unsigned int, pdata->rx_max_fifo_size,
+		     pdata->hw_feat.rx_fifo_size);
+}
 
-	/* Each increment in the queue fifo size represents 256 bytes of
-	 * fifo, with 0 representing 256 bytes. Distribute the fifo equally
-	 * between the queues.
+static void xgbe_calculate_equal_fifo(unsigned int fifo_size,
+				      unsigned int queue_count,
+				      unsigned int *fifo)
+{
+	unsigned int q_fifo_size;
+	unsigned int p_fifo;
+	unsigned int i;
+
+	q_fifo_size = fifo_size / queue_count;
+
+	/* Calculate the fifo setting by dividing the queue's fifo size
+	 * by the fifo allocation increment (with 0 representing the
+	 * base allocation increment so decrement the result by 1).
 	 */
-	p_fifo = q_fifo_size / 256;
+	p_fifo = q_fifo_size / XGMAC_FIFO_UNIT;
 	if (p_fifo)
 		p_fifo--;
 
-	return p_fifo;
+	/* Distribute the fifo equally amongst the queues */
+	for (i = 0; i < queue_count; i++)
+		fifo[i] = p_fifo;
+}
+
+static unsigned int xgbe_set_nonprio_fifos(unsigned int fifo_size,
+					   unsigned int queue_count,
+					   unsigned int *fifo)
+{
+	unsigned int i;
+
+	BUILD_BUG_ON_NOT_POWER_OF_2(XGMAC_FIFO_MIN_ALLOC);
+
+	if (queue_count <= IEEE_8021QAZ_MAX_TCS)
+		return fifo_size;
+
+	/* Rx queues 9 and up are for specialized packets,
+	 * such as PTP or DCB control packets, etc. and
+	 * don't require a large fifo
+	 */
+	for (i = IEEE_8021QAZ_MAX_TCS; i < queue_count; i++) {
+		fifo[i] = (XGMAC_FIFO_MIN_ALLOC / XGMAC_FIFO_UNIT) - 1;
+		fifo_size -= XGMAC_FIFO_MIN_ALLOC;
+	}
+
+	return fifo_size;
+}
+
+static unsigned int xgbe_get_pfc_delay(struct xgbe_prv_data *pdata)
+{
+	unsigned int delay;
+
+	/* If a delay has been provided, use that */
+	if (pdata->pfc->delay)
+		return pdata->pfc->delay / 8;
+
+	/* Allow for two maximum size frames */
+	delay = xgbe_get_max_frame(pdata);
+	delay += XGMAC_ETH_PREAMBLE;
+	delay *= 2;
+
+	/* Allow for PFC frame */
+	delay += XGMAC_PFC_DATA_LEN;
+	delay += ETH_HLEN + ETH_FCS_LEN;
+	delay += XGMAC_ETH_PREAMBLE;
+
+	/* Allow for miscellaneous delays (LPI exit, cable, etc.) */
+	delay += XGMAC_PFC_DELAYS;
+
+	return delay;
+}
+
+static unsigned int xgbe_get_pfc_queues(struct xgbe_prv_data *pdata)
+{
+	unsigned int count, prio_queues;
+	unsigned int i;
+
+	if (!pdata->pfc->pfc_en)
+		return 0;
+
+	count = 0;
+	prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
+	for (i = 0; i < prio_queues; i++) {
+		if (!xgbe_is_pfc_queue(pdata, i))
+			continue;
+
+		pdata->pfcq[i] = 1;
+		count++;
+	}
+
+	return count;
+}
+
+static void xgbe_calculate_dcb_fifo(struct xgbe_prv_data *pdata,
+				    unsigned int fifo_size,
+				    unsigned int *fifo)
+{
+	unsigned int q_fifo_size, rem_fifo, addn_fifo;
+	unsigned int prio_queues;
+	unsigned int pfc_count;
+	unsigned int i;
+
+	q_fifo_size = XGMAC_FIFO_ALIGN(xgbe_get_max_frame(pdata));
+	prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
+	pfc_count = xgbe_get_pfc_queues(pdata);
+
+	if (!pfc_count || ((q_fifo_size * prio_queues) > fifo_size)) {
+		/* No traffic classes with PFC enabled or can't do lossless */
+		xgbe_calculate_equal_fifo(fifo_size, prio_queues, fifo);
+		return;
+	}
+
+	/* Calculate how much fifo we have to play with */
+	rem_fifo = fifo_size - (q_fifo_size * prio_queues);
+
+	/* Calculate how much more than base fifo PFC needs, which also
+	 * becomes the threshold activation point (RFA)
+	 */
+	pdata->pfc_rfa = xgbe_get_pfc_delay(pdata);
+	pdata->pfc_rfa = XGMAC_FLOW_CONTROL_ALIGN(pdata->pfc_rfa);
+
+	if (pdata->pfc_rfa > q_fifo_size) {
+		addn_fifo = pdata->pfc_rfa - q_fifo_size;
+		addn_fifo = XGMAC_FIFO_ALIGN(addn_fifo);
+	} else {
+		addn_fifo = 0;
+	}
+
+	/* Calculate DCB fifo settings:
+	 *   - distribute remaining fifo between the VLAN priority
+	 *     queues based on traffic class PFC enablement and overall
+	 *     priority (0 is lowest priority, so start at highest)
+	 */
+	i = prio_queues;
+	while (i > 0) {
+		i--;
+
+		fifo[i] = (q_fifo_size / XGMAC_FIFO_UNIT) - 1;
+
+		if (!pdata->pfcq[i] || !addn_fifo)
+			continue;
+
+		if (addn_fifo > rem_fifo) {
+			netdev_warn(pdata->netdev,
+				    "RXq%u cannot set needed fifo size\n", i);
+			if (!rem_fifo)
+				continue;
+
+			addn_fifo = rem_fifo;
+		}
+
+		fifo[i] += (addn_fifo / XGMAC_FIFO_UNIT);
+		rem_fifo -= addn_fifo;
+	}
+
+	if (rem_fifo) {
+		unsigned int inc_fifo = rem_fifo / prio_queues;
+
+		/* Distribute remaining fifo across queues */
+		for (i = 0; i < prio_queues; i++)
+			fifo[i] += (inc_fifo / XGMAC_FIFO_UNIT);
+	}
 }
 
 static void xgbe_config_tx_fifo_size(struct xgbe_prv_data *pdata)
 {
 	unsigned int fifo_size;
+	unsigned int fifo[XGBE_MAX_QUEUES];
 	unsigned int i;
 
-	fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.tx_fifo_size,
-						  pdata->tx_q_count);
+	fifo_size = xgbe_get_tx_fifo_size(pdata);
+
+	xgbe_calculate_equal_fifo(fifo_size, pdata->tx_q_count, fifo);
 
 	for (i = 0; i < pdata->tx_q_count; i++)
-		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo_size);
+		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, TQS, fifo[i]);
 
 	netif_info(pdata, drv, pdata->netdev,
 		   "%d Tx hardware queues, %d byte fifo per queue\n",
-		   pdata->tx_q_count, ((fifo_size + 1) * 256));
+		   pdata->tx_q_count, ((fifo[0] + 1) * XGMAC_FIFO_UNIT));
 }
 
 static void xgbe_config_rx_fifo_size(struct xgbe_prv_data *pdata)
 {
 	unsigned int fifo_size;
+	unsigned int fifo[XGBE_MAX_QUEUES];
+	unsigned int prio_queues;
 	unsigned int i;
 
-	fifo_size = xgbe_calculate_per_queue_fifo(pdata->hw_feat.rx_fifo_size,
-						  pdata->rx_q_count);
+	/* Clear any DCB related fifo/queue information */
+	memset(pdata->pfcq, 0, sizeof(pdata->pfcq));
+	pdata->pfc_rfa = 0;
+
+	fifo_size = xgbe_get_rx_fifo_size(pdata);
+	prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
+
+	/* Assign a minimum fifo to the non-VLAN priority queues */
+	fifo_size = xgbe_set_nonprio_fifos(fifo_size, pdata->rx_q_count, fifo);
+
+	if (pdata->pfc && pdata->ets)
+		xgbe_calculate_dcb_fifo(pdata, fifo_size, fifo);
+	else
+		xgbe_calculate_equal_fifo(fifo_size, prio_queues, fifo);
 
 	for (i = 0; i < pdata->rx_q_count; i++)
-		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo_size);
+		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, RQS, fifo[i]);
 
-	netif_info(pdata, drv, pdata->netdev,
-		   "%d Rx hardware queues, %d byte fifo per queue\n",
-		   pdata->rx_q_count, ((fifo_size + 1) * 256));
+	xgbe_calculate_flow_control_threshold(pdata, fifo);
+	xgbe_config_flow_control_threshold(pdata);
+
+	if (pdata->pfc && pdata->ets && pdata->pfc->pfc_en) {
+		netif_info(pdata, drv, pdata->netdev,
+			   "%u Rx hardware queues\n", pdata->rx_q_count);
+		for (i = 0; i < pdata->rx_q_count; i++)
+			netif_info(pdata, drv, pdata->netdev,
+				   "RxQ%u, %u byte fifo queue\n", i,
+				   ((fifo[i] + 1) * XGMAC_FIFO_UNIT));
+	} else {
+		netif_info(pdata, drv, pdata->netdev,
+			   "%u Rx hardware queues, %u byte fifo per queue\n",
+			   pdata->rx_q_count,
+			   ((fifo[0] + 1) * XGMAC_FIFO_UNIT));
+	}
 }
 
 static void xgbe_config_queue_mapping(struct xgbe_prv_data *pdata)
@@ -2090,8 +2549,7 @@ static void xgbe_config_queue_mapping(st
 	}
 
 	/* Map the 8 VLAN priority values to available MTL Rx queues */
-	prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
-			    pdata->rx_q_count);
+	prio_queues = XGMAC_PRIO_QUEUES(pdata->rx_q_count);
 	ppq = IEEE_8021QAZ_MAX_TCS / prio_queues;
 	ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues;
 
@@ -2139,16 +2597,120 @@ static void xgbe_config_queue_mapping(st
 	}
 }
 
-static void xgbe_config_flow_control_threshold(struct xgbe_prv_data *pdata)
+static void xgbe_config_tc(struct xgbe_prv_data *pdata)
 {
-	unsigned int i;
+	unsigned int offset, queue, prio;
+	u8 i;
 
-	for (i = 0; i < pdata->rx_q_count; i++) {
-		/* Activate flow control when less than 4k left in fifo */
-		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFA, 2);
+	netdev_reset_tc(pdata->netdev);
+	if (!pdata->num_tcs)
+		return;
 
-		/* De-activate flow control when more than 6k left in fifo */
-		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQFCR, RFD, 4);
+	netdev_set_num_tc(pdata->netdev, pdata->num_tcs);
+
+	for (i = 0, queue = 0, offset = 0; i < pdata->num_tcs; i++) {
+		while ((queue < pdata->tx_q_count) &&
+		       (pdata->q2tc_map[queue] == i))
+			queue++;
+
+		netif_dbg(pdata, drv, pdata->netdev, "TC%u using TXq%u-%u\n",
+			  i, offset, queue - 1);
+		netdev_set_tc_queue(pdata->netdev, i, queue - offset, offset);
+		offset = queue;
+	}
+
+	if (!pdata->ets)
+		return;
+
+	for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
+		netdev_set_prio_tc_map(pdata->netdev, prio,
+				       pdata->ets->prio_tc[prio]);
+}
+
+static void xgbe_config_dcb_tc(struct xgbe_prv_data *pdata)
+{
+	struct ieee_ets *ets = pdata->ets;
+	unsigned int total_weight, min_weight, weight;
+	unsigned int mask, reg, reg_val;
+	unsigned int i, prio;
+
+	if (!ets)
+		return;
+
+	/* Set Tx to deficit weighted round robin scheduling algorithm (when
+	 * traffic class is using ETS algorithm)
+	 */
+	XGMAC_IOWRITE_BITS(pdata, MTL_OMR, ETSALG, MTL_ETSALG_DWRR);
+
+	/* Set Traffic Class algorithms */
+	total_weight = pdata->netdev->mtu * pdata->hw_feat.tc_cnt;
+	min_weight = total_weight / 100;
+	if (!min_weight)
+		min_weight = 1;
+
+	for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
+		/* Map the priorities to the traffic class */
+		mask = 0;
+		for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) {
+			if (ets->prio_tc[prio] == i)
+				mask |= (1 << prio);
+		}
+		mask &= 0xff;
+
+		netif_dbg(pdata, drv, pdata->netdev, "TC%u PRIO mask=%#x\n",
+			  i, mask);
+		reg = MTL_TCPM0R + (MTL_TCPM_INC * (i / MTL_TCPM_TC_PER_REG));
+		reg_val = XGMAC_IOREAD(pdata, reg);
+
+		reg_val &= ~(0xff << ((i % MTL_TCPM_TC_PER_REG) << 3));
+		reg_val |= (mask << ((i % MTL_TCPM_TC_PER_REG) << 3));
+
+		XGMAC_IOWRITE(pdata, reg, reg_val);
+
+		/* Set the traffic class algorithm */
+		switch (ets->tc_tsa[i]) {
+		case IEEE_8021QAZ_TSA_STRICT:
+			netif_dbg(pdata, drv, pdata->netdev,
+				  "TC%u using SP\n", i);
+			XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+					       MTL_TSA_SP);
+			break;
+		case IEEE_8021QAZ_TSA_ETS:
+			weight = total_weight * ets->tc_tx_bw[i] / 100;
+			weight = clamp(weight, min_weight, total_weight);
+
+			netif_dbg(pdata, drv, pdata->netdev,
+				  "TC%u using DWRR (weight %u)\n", i, weight);
+			XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_ETSCR, TSA,
+					       MTL_TSA_ETS);
+			XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_TC_QWR, QW,
+					       weight);
+			break;
+		}
+	}
+
+	xgbe_config_tc(pdata);
+}
+
+static void xgbe_config_dcb_pfc(struct xgbe_prv_data *pdata)
+{
+	if (!test_bit(XGBE_DOWN, &pdata->dev_state)) {
+		/* Just stop the Tx queues while Rx fifo is changed */
+		netif_tx_stop_all_queues(pdata->netdev);
+
+		/* Suspend Rx so that fifo's can be adjusted */
+		pdata->hw_if.disable_rx(pdata);
+	}
+
+	xgbe_config_rx_fifo_size(pdata);
+	xgbe_config_flow_control(pdata);
+
+	if (!test_bit(XGBE_DOWN, &pdata->dev_state)) {
+		/* Resume Rx */
+		pdata->hw_if.enable_rx(pdata);
+
+		/* Resume Tx queues */
+		netif_tx_start_all_queues(pdata->netdev);
 	}
 }
 
@@ -2175,19 +2737,7 @@ static void xgbe_config_jumbo_enable(str
 
 static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata)
 {
-	switch (pdata->phy_speed) {
-	case SPEED_10000:
-		xgbe_set_xgmii_speed(pdata);
-		break;
-
-	case SPEED_2500:
-		xgbe_set_gmii_2500_speed(pdata);
-		break;
-
-	case SPEED_1000:
-		xgbe_set_gmii_speed(pdata);
-		break;
-	}
+	xgbe_set_speed(pdata, pdata->phy_speed);
 }
 
 static void xgbe_config_checksum_offload(struct xgbe_prv_data *pdata)
@@ -2223,17 +2773,33 @@ static u64 xgbe_mmc_read(struct xgbe_prv
 	bool read_hi;
 	u64 val;
 
-	switch (reg_lo) {
-	/* These registers are always 64 bit */
-	case MMC_TXOCTETCOUNT_GB_LO:
-	case MMC_TXOCTETCOUNT_G_LO:
-	case MMC_RXOCTETCOUNT_GB_LO:
-	case MMC_RXOCTETCOUNT_G_LO:
-		read_hi = true;
-		break;
+	if (pdata->vdata->mmc_64bit) {
+		switch (reg_lo) {
+		/* These registers are always 32 bit */
+		case MMC_RXRUNTERROR:
+		case MMC_RXJABBERERROR:
+		case MMC_RXUNDERSIZE_G:
+		case MMC_RXOVERSIZE_G:
+		case MMC_RXWATCHDOGERROR:
+			read_hi = false;
+			break;
 
-	default:
-		read_hi = false;
+		default:
+			read_hi = true;
+		}
+	} else {
+		switch (reg_lo) {
+		/* These registers are always 64 bit */
+		case MMC_TXOCTETCOUNT_GB_LO:
+		case MMC_TXOCTETCOUNT_G_LO:
+		case MMC_RXOCTETCOUNT_GB_LO:
+		case MMC_RXOCTETCOUNT_G_LO:
+			read_hi = true;
+			break;
+
+		default:
+			read_hi = false;
+		}
 	}
 
 	val = XGMAC_IOREAD(pdata, reg_lo);
@@ -2563,20 +3129,48 @@ static void xgbe_config_mmc(struct xgbe_
 	XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1);
 }
 
+static void xgbe_txq_prepare_tx_stop(struct xgbe_prv_data *pdata,
+				     unsigned int queue)
+{
+	unsigned int tx_status;
+	unsigned long tx_timeout;
+
+	/* The Tx engine cannot be stopped if it is actively processing
+	 * packets. Wait for the Tx queue to empty the Tx fifo.  Don't
+	 * wait forever though...
+	 */
+	tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ);
+	while (time_before(jiffies, tx_timeout)) {
+		tx_status = XGMAC_MTL_IOREAD(pdata, queue, MTL_Q_TQDR);
+		if ((XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TRCSTS) != 1) &&
+		    (XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TXQSTS) == 0))
+			break;
+
+		usleep_range(500, 1000);
+	}
+
+	if (!time_before(jiffies, tx_timeout))
+		netdev_info(pdata->netdev,
+			    "timed out waiting for Tx queue %u to empty\n",
+			    queue);
+}
+
 static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata,
-				 struct xgbe_channel *channel)
+				 unsigned int queue)
 {
 	unsigned int tx_dsr, tx_pos, tx_qidx;
 	unsigned int tx_status;
 	unsigned long tx_timeout;
 
+	if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) > 0x20)
+		return xgbe_txq_prepare_tx_stop(pdata, queue);
+
 	/* Calculate the status register to read and the position within */
-	if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) {
+	if (queue < DMA_DSRX_FIRST_QUEUE) {
 		tx_dsr = DMA_DSR0;
-		tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) +
-			 DMA_DSR0_TPS_START;
+		tx_pos = (queue * DMA_DSR_Q_WIDTH) + DMA_DSR0_TPS_START;
 	} else {
-		tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE;
+		tx_qidx = queue - DMA_DSRX_FIRST_QUEUE;
 
 		tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
 		tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) +
@@ -2601,7 +3195,7 @@ static void xgbe_prepare_tx_stop(struct
 	if (!time_before(jiffies, tx_timeout))
 		netdev_info(pdata->netdev,
 			    "timed out waiting for Tx DMA channel %u to stop\n",
-			    channel->queue_index);
+			    queue);
 }
 
 static void xgbe_enable_tx(struct xgbe_prv_data *pdata)
@@ -2633,13 +3227,8 @@ static void xgbe_disable_tx(struct xgbe_
 	unsigned int i;
 
 	/* Prepare for Tx DMA channel stop */
-	channel = pdata->channel;
-	for (i = 0; i < pdata->channel_count; i++, channel++) {
-		if (!channel->tx_ring)
-			break;
-
-		xgbe_prepare_tx_stop(pdata, channel);
-	}
+	for (i = 0; i < pdata->tx_q_count; i++)
+		xgbe_prepare_tx_stop(pdata, i);
 
 	/* Disable MAC Tx */
 	XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
@@ -2763,13 +3352,8 @@ static void xgbe_powerdown_tx(struct xgb
 	unsigned int i;
 
 	/* Prepare for Tx DMA channel stop */
-	channel = pdata->channel;
-	for (i = 0; i < pdata->channel_count; i++, channel++) {
-		if (!channel->tx_ring)
-			break;
-
-		xgbe_prepare_tx_stop(pdata, channel);
-	}
+	for (i = 0; i < pdata->tx_q_count; i++)
+		xgbe_prepare_tx_stop(pdata, i);
 
 	/* Disable MAC Tx */
 	XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
@@ -2823,8 +3407,10 @@ static int xgbe_init(struct xgbe_prv_dat
 
 	/* Flush Tx queues */
 	ret = xgbe_flush_tx_queues(pdata);
-	if (ret)
+	if (ret) {
+		netdev_err(pdata->netdev, "error flushing TX queues\n");
 		return ret;
+	}
 
 	/*
 	 * Initialize DMA related features
@@ -2856,12 +3442,10 @@ static int xgbe_init(struct xgbe_prv_dat
 	xgbe_config_rx_threshold(pdata, pdata->rx_threshold);
 	xgbe_config_tx_fifo_size(pdata);
 	xgbe_config_rx_fifo_size(pdata);
-	xgbe_config_flow_control_threshold(pdata);
 	/*TODO: Error Packet and undersized good Packet forwarding enable
 		(FEP and FUP)
 	 */
 	xgbe_config_dcb_tc(pdata);
-	xgbe_config_dcb_pfc(pdata);
 	xgbe_enable_mtl_interrupts(pdata);
 
 	/*
@@ -2877,6 +3461,11 @@ static int xgbe_init(struct xgbe_prv_dat
 	xgbe_config_mmc(pdata);
 	xgbe_enable_mac_interrupts(pdata);
 
+	/*
+	 * Initialize ECC related features
+	 */
+	xgbe_enable_ecc_interrupts(pdata);
+
 	DBGPR("<--xgbe_init\n");
 
 	return 0;
@@ -2903,9 +3492,14 @@ void xgbe_init_function_ptrs_dev(struct
 	hw_if->read_mmd_regs = xgbe_read_mmd_regs;
 	hw_if->write_mmd_regs = xgbe_write_mmd_regs;
 
-	hw_if->set_gmii_speed = xgbe_set_gmii_speed;
-	hw_if->set_gmii_2500_speed = xgbe_set_gmii_2500_speed;
-	hw_if->set_xgmii_speed = xgbe_set_xgmii_speed;
+	hw_if->set_speed = xgbe_set_speed;
+
+	hw_if->set_ext_mii_mode = xgbe_set_ext_mii_mode;
+	hw_if->read_ext_mii_regs = xgbe_read_ext_mii_regs;
+	hw_if->write_ext_mii_regs = xgbe_write_ext_mii_regs;
+
+	hw_if->set_gpio = xgbe_set_gpio;
+	hw_if->clr_gpio = xgbe_clr_gpio;
 
 	hw_if->enable_tx = xgbe_enable_tx;
 	hw_if->disable_tx = xgbe_disable_tx;
@@ -2984,5 +3578,9 @@ void xgbe_init_function_ptrs_dev(struct
 	hw_if->set_rss_hash_key = xgbe_set_rss_hash_key;
 	hw_if->set_rss_lookup_table = xgbe_set_rss_lookup_table;
 
+	/* For ECC */
+	hw_if->disable_ecc_ded = xgbe_disable_ecc_ded;
+	hw_if->disable_ecc_sec = xgbe_disable_ecc_sec;
+
 	DBGPR("<--xgbe_init_function_ptrs\n");
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-drv.c	2017-02-12 16:03:20.000000000 -0500
@@ -114,7 +114,7 @@
  *     THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <linux/platform_device.h>
+#include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/tcp.h>
 #include <linux/if_vlan.h>
@@ -127,8 +127,35 @@
 #include "xgbe.h"
 #include "xgbe-common.h"
 
+static unsigned int ecc_sec_info_threshold = 10;
+static unsigned int ecc_sec_warn_threshold = 10000;
+static unsigned int ecc_sec_period = 600;
+static unsigned int ecc_ded_threshold = 2;
+static unsigned int ecc_ded_period = 600;
+
+#ifdef CONFIG_AMD_XGBE_HAVE_ECC
+/* Only expose the ECC parameters if supported */
+module_param(ecc_sec_info_threshold, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_sec_info_threshold,
+		 " ECC corrected error informational threshold setting");
+
+module_param(ecc_sec_warn_threshold, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_sec_warn_threshold,
+		 " ECC corrected error warning threshold setting");
+
+module_param(ecc_sec_period, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_sec_period, " ECC corrected error period (in seconds)");
+
+module_param(ecc_ded_threshold, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_ded_threshold, " ECC detected error threshold setting");
+
+module_param(ecc_ded_period, uint, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(ecc_ded_period, " ECC detected error period (in seconds)");
+#endif
+
 static int xgbe_one_poll(struct napi_struct *, int);
 static int xgbe_all_poll(struct napi_struct *, int);
+static void xgbe_stop(struct xgbe_prv_data *);
 
 static int xgbe_alloc_channels(struct xgbe_prv_data *pdata)
 {
@@ -160,18 +187,8 @@ static int xgbe_alloc_channels(struct xg
 		channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE +
 				    (DMA_CH_INC * i);
 
-		if (pdata->per_channel_irq) {
-			/* Get the DMA interrupt (offset 1) */
-			ret = platform_get_irq(pdata->pdev, i + 1);
-			if (ret < 0) {
-				netdev_err(pdata->netdev,
-					   "platform_get_irq %u failed\n",
-					   i + 1);
-				goto err_irq;
-			}
-
-			channel->dma_irq = ret;
-		}
+		if (pdata->per_channel_irq)
+			channel->dma_irq = pdata->channel_irq[i];
 
 		if (i < pdata->tx_ring_count) {
 			spin_lock_init(&tx_ring->lock);
@@ -194,9 +211,6 @@ static int xgbe_alloc_channels(struct xg
 
 	return 0;
 
-err_irq:
-	kfree(rx_ring);
-
 err_rx_ring:
 	kfree(tx_ring);
 
@@ -257,11 +271,6 @@ static int xgbe_calc_rx_buf_size(struct
 {
 	unsigned int rx_buf_size;
 
-	if (mtu > XGMAC_JUMBO_PACKET_MTU) {
-		netdev_alert(netdev, "MTU exceeds maximum supported value\n");
-		return -EINVAL;
-	}
-
 	rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 	rx_buf_size = clamp_val(rx_buf_size, XGBE_RX_MIN_BUF_SIZE, PAGE_SIZE);
 
@@ -271,48 +280,161 @@ static int xgbe_calc_rx_buf_size(struct
 	return rx_buf_size;
 }
 
-static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata)
+static void xgbe_enable_rx_tx_int(struct xgbe_prv_data *pdata,
+				  struct xgbe_channel *channel)
 {
 	struct xgbe_hw_if *hw_if = &pdata->hw_if;
-	struct xgbe_channel *channel;
 	enum xgbe_int int_id;
+
+	if (channel->tx_ring && channel->rx_ring)
+		int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
+	else if (channel->tx_ring)
+		int_id = XGMAC_INT_DMA_CH_SR_TI;
+	else if (channel->rx_ring)
+		int_id = XGMAC_INT_DMA_CH_SR_RI;
+	else
+		return;
+
+	hw_if->enable_int(channel, int_id);
+}
+
+static void xgbe_enable_rx_tx_ints(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_channel *channel;
 	unsigned int i;
 
 	channel = pdata->channel;
-	for (i = 0; i < pdata->channel_count; i++, channel++) {
-		if (channel->tx_ring && channel->rx_ring)
-			int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
-		else if (channel->tx_ring)
-			int_id = XGMAC_INT_DMA_CH_SR_TI;
-		else if (channel->rx_ring)
-			int_id = XGMAC_INT_DMA_CH_SR_RI;
-		else
-			continue;
+	for (i = 0; i < pdata->channel_count; i++, channel++)
+		xgbe_enable_rx_tx_int(pdata, channel);
+}
 
-		hw_if->enable_int(channel, int_id);
-	}
+static void xgbe_disable_rx_tx_int(struct xgbe_prv_data *pdata,
+				   struct xgbe_channel *channel)
+{
+	struct xgbe_hw_if *hw_if = &pdata->hw_if;
+	enum xgbe_int int_id;
+
+	if (channel->tx_ring && channel->rx_ring)
+		int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
+	else if (channel->tx_ring)
+		int_id = XGMAC_INT_DMA_CH_SR_TI;
+	else if (channel->rx_ring)
+		int_id = XGMAC_INT_DMA_CH_SR_RI;
+	else
+		return;
+
+	hw_if->disable_int(channel, int_id);
 }
 
 static void xgbe_disable_rx_tx_ints(struct xgbe_prv_data *pdata)
 {
-	struct xgbe_hw_if *hw_if = &pdata->hw_if;
 	struct xgbe_channel *channel;
-	enum xgbe_int int_id;
 	unsigned int i;
 
 	channel = pdata->channel;
-	for (i = 0; i < pdata->channel_count; i++, channel++) {
-		if (channel->tx_ring && channel->rx_ring)
-			int_id = XGMAC_INT_DMA_CH_SR_TI_RI;
-		else if (channel->tx_ring)
-			int_id = XGMAC_INT_DMA_CH_SR_TI;
-		else if (channel->rx_ring)
-			int_id = XGMAC_INT_DMA_CH_SR_RI;
-		else
-			continue;
+	for (i = 0; i < pdata->channel_count; i++, channel++)
+		xgbe_disable_rx_tx_int(pdata, channel);
+}
 
-		hw_if->disable_int(channel, int_id);
+static bool xgbe_ecc_sec(struct xgbe_prv_data *pdata, unsigned long *period,
+			 unsigned int *count, const char *area)
+{
+	if (time_before(jiffies, *period)) {
+		(*count)++;
+	} else {
+		*period = jiffies + (ecc_sec_period * HZ);
+		*count = 1;
+	}
+
+	if (*count > ecc_sec_info_threshold)
+		dev_warn_once(pdata->dev,
+			      "%s ECC corrected errors exceed informational threshold\n",
+			      area);
+
+	if (*count > ecc_sec_warn_threshold) {
+		dev_warn_once(pdata->dev,
+			      "%s ECC corrected errors exceed warning threshold\n",
+			      area);
+		return true;
+	}
+
+	return false;
+}
+
+static bool xgbe_ecc_ded(struct xgbe_prv_data *pdata, unsigned long *period,
+			 unsigned int *count, const char *area)
+{
+	if (time_before(jiffies, *period)) {
+		(*count)++;
+	} else {
+		*period = jiffies + (ecc_ded_period * HZ);
+		*count = 1;
+	}
+
+	if (*count > ecc_ded_threshold) {
+		netdev_alert(pdata->netdev,
+			     "%s ECC detected errors exceed threshold\n",
+			     area);
+		return true;
 	}
+
+	return false;
+}
+
+static irqreturn_t xgbe_ecc_isr(int irq, void *data)
+{
+	struct xgbe_prv_data *pdata = data;
+	unsigned int ecc_isr;
+	bool stop = false;
+
+	/* Mask status with only the interrupts we care about */
+	ecc_isr = XP_IOREAD(pdata, XP_ECC_ISR);
+	ecc_isr &= XP_IOREAD(pdata, XP_ECC_IER);
+	netif_dbg(pdata, intr, pdata->netdev, "ECC_ISR=%#010x\n", ecc_isr);
+
+	if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, TX_DED)) {
+		stop |= xgbe_ecc_ded(pdata, &pdata->tx_ded_period,
+				     &pdata->tx_ded_count, "TX fifo");
+	}
+
+	if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, RX_DED)) {
+		stop |= xgbe_ecc_ded(pdata, &pdata->rx_ded_period,
+				     &pdata->rx_ded_count, "RX fifo");
+	}
+
+	if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, DESC_DED)) {
+		stop |= xgbe_ecc_ded(pdata, &pdata->desc_ded_period,
+				     &pdata->desc_ded_count,
+				     "descriptor cache");
+	}
+
+	if (stop) {
+		pdata->hw_if.disable_ecc_ded(pdata);
+		schedule_work(&pdata->stopdev_work);
+		goto out;
+	}
+
+	if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, TX_SEC)) {
+		if (xgbe_ecc_sec(pdata, &pdata->tx_sec_period,
+				 &pdata->tx_sec_count, "TX fifo"))
+			pdata->hw_if.disable_ecc_sec(pdata, XGBE_ECC_SEC_TX);
+	}
+
+	if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, RX_SEC))
+		if (xgbe_ecc_sec(pdata, &pdata->rx_sec_period,
+				 &pdata->rx_sec_count, "RX fifo"))
+			pdata->hw_if.disable_ecc_sec(pdata, XGBE_ECC_SEC_RX);
+
+	if (XP_GET_BITS(ecc_isr, XP_ECC_ISR, DESC_SEC))
+		if (xgbe_ecc_sec(pdata, &pdata->desc_sec_period,
+				 &pdata->desc_sec_count, "descriptor cache"))
+			pdata->hw_if.disable_ecc_sec(pdata, XGBE_ECC_SEC_DESC);
+
+out:
+	/* Clear all ECC interrupts */
+	XP_IOWRITE(pdata, XP_ECC_ISR, ecc_isr);
+
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t xgbe_isr(int irq, void *data)
@@ -321,7 +443,7 @@ static irqreturn_t xgbe_isr(int irq, voi
 	struct xgbe_hw_if *hw_if = &pdata->hw_if;
 	struct xgbe_channel *channel;
 	unsigned int dma_isr, dma_ch_isr;
-	unsigned int mac_isr, mac_tssr;
+	unsigned int mac_isr, mac_tssr, mac_mdioisr;
 	unsigned int i;
 
 	/* The DMA interrupt status register also reports MAC and MTL
@@ -358,6 +480,13 @@ static irqreturn_t xgbe_isr(int irq, voi
 				/* Turn on polling */
 				__napi_schedule_irqoff(&pdata->napi);
 			}
+		} else {
+			/* Don't clear Rx/Tx status if doing per channel DMA
+			 * interrupts, these will be cleared by the ISR for
+			 * per channel DMA interrupts.
+			 */
+			XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, TI, 0);
+			XGMAC_SET_BITS(dma_ch_isr, DMA_CH_SR, RI, 0);
 		}
 
 		if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RBU))
@@ -367,13 +496,16 @@ static irqreturn_t xgbe_isr(int irq, voi
 		if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, FBE))
 			schedule_work(&pdata->restart_work);
 
-		/* Clear all interrupt signals */
+		/* Clear interrupt signals */
 		XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_ch_isr);
 	}
 
 	if (XGMAC_GET_BITS(dma_isr, DMA_ISR, MACIS)) {
 		mac_isr = XGMAC_IOREAD(pdata, MAC_ISR);
 
+		netif_dbg(pdata, intr, pdata->netdev, "MAC_ISR=%#010x\n",
+			  mac_isr);
+
 		if (XGMAC_GET_BITS(mac_isr, MAC_ISR, MMCTXIS))
 			hw_if->tx_mmc_int(pdata);
 
@@ -383,6 +515,9 @@ static irqreturn_t xgbe_isr(int irq, voi
 		if (XGMAC_GET_BITS(mac_isr, MAC_ISR, TSIS)) {
 			mac_tssr = XGMAC_IOREAD(pdata, MAC_TSSR);
 
+			netif_dbg(pdata, intr, pdata->netdev,
+				  "MAC_TSSR=%#010x\n", mac_tssr);
+
 			if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) {
 				/* Read Tx Timestamp to clear interrupt */
 				pdata->tx_tstamp =
@@ -391,27 +526,61 @@ static irqreturn_t xgbe_isr(int irq, voi
 					   &pdata->tx_tstamp_work);
 			}
 		}
+
+		if (XGMAC_GET_BITS(mac_isr, MAC_ISR, SMI)) {
+			mac_mdioisr = XGMAC_IOREAD(pdata, MAC_MDIOISR);
+
+			netif_dbg(pdata, intr, pdata->netdev,
+				  "MAC_MDIOISR=%#010x\n", mac_mdioisr);
+
+			if (XGMAC_GET_BITS(mac_mdioisr, MAC_MDIOISR,
+					   SNGLCOMPINT))
+				complete(&pdata->mdio_complete);
+		}
 	}
 
 isr_done:
+	/* If there is not a separate AN irq, handle it here */
+	if (pdata->dev_irq == pdata->an_irq)
+		pdata->phy_if.an_isr(irq, pdata);
+
+	/* If there is not a separate ECC irq, handle it here */
+	if (pdata->vdata->ecc_support && (pdata->dev_irq == pdata->ecc_irq))
+		xgbe_ecc_isr(irq, pdata);
+
+	/* If there is not a separate I2C irq, handle it here */
+	if (pdata->vdata->i2c_support && (pdata->dev_irq == pdata->i2c_irq))
+		pdata->i2c_if.i2c_isr(irq, pdata);
+
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t xgbe_dma_isr(int irq, void *data)
 {
 	struct xgbe_channel *channel = data;
+	struct xgbe_prv_data *pdata = channel->pdata;
+	unsigned int dma_status;
 
 	/* Per channel DMA interrupts are enabled, so we use the per
 	 * channel napi structure and not the private data napi structure
 	 */
 	if (napi_schedule_prep(&channel->napi)) {
 		/* Disable Tx and Rx interrupts */
-		disable_irq_nosync(channel->dma_irq);
+		if (pdata->channel_irq_mode)
+			xgbe_disable_rx_tx_int(pdata, channel);
+		else
+			disable_irq_nosync(channel->dma_irq);
 
 		/* Turn on polling */
 		__napi_schedule_irqoff(&channel->napi);
 	}
 
+	/* Clear Tx/Rx signals */
+	dma_status = 0;
+	XGMAC_SET_BITS(dma_status, DMA_CH_SR, TI, 1);
+	XGMAC_SET_BITS(dma_status, DMA_CH_SR, RI, 1);
+	XGMAC_DMA_IOWRITE(channel, DMA_CH_SR, dma_status);
+
 	return IRQ_HANDLED;
 }
 
@@ -428,7 +597,10 @@ static void xgbe_tx_timer(unsigned long
 	if (napi_schedule_prep(napi)) {
 		/* Disable Tx and Rx interrupts */
 		if (pdata->per_channel_irq)
-			disable_irq_nosync(channel->dma_irq);
+			if (pdata->channel_irq_mode)
+				xgbe_disable_rx_tx_int(pdata, channel);
+			else
+				disable_irq_nosync(channel->dma_irq);
 		else
 			xgbe_disable_rx_tx_ints(pdata);
 
@@ -595,6 +767,10 @@ void xgbe_get_all_hw_features(struct xgb
 	hw_feat->tx_ch_cnt++;
 	hw_feat->tc_cnt++;
 
+	/* Translate the fifo sizes into actual numbers */
+	hw_feat->rx_fifo_size = 1 << (hw_feat->rx_fifo_size + 7);
+	hw_feat->tx_fifo_size = 1 << (hw_feat->tx_fifo_size + 7);
+
 	DBGPR("<--xgbe_get_all_hw_features\n");
 }
 
@@ -657,6 +833,16 @@ static int xgbe_request_irqs(struct xgbe
 		return ret;
 	}
 
+	if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq)) {
+		ret = devm_request_irq(pdata->dev, pdata->ecc_irq, xgbe_ecc_isr,
+				       0, pdata->ecc_name, pdata);
+		if (ret) {
+			netdev_alert(netdev, "error requesting ecc irq %d\n",
+				     pdata->ecc_irq);
+			goto err_dev_irq;
+		}
+	}
+
 	if (!pdata->per_channel_irq)
 		return 0;
 
@@ -673,17 +859,21 @@ static int xgbe_request_irqs(struct xgbe
 		if (ret) {
 			netdev_alert(netdev, "error requesting irq %d\n",
 				     channel->dma_irq);
-			goto err_irq;
+			goto err_dma_irq;
 		}
 	}
 
 	return 0;
 
-err_irq:
+err_dma_irq:
 	/* Using an unsigned int, 'i' will go to UINT_MAX and exit */
 	for (i--, channel--; i < pdata->channel_count; i--, channel--)
 		devm_free_irq(pdata->dev, channel->dma_irq, channel);
 
+	if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq))
+		devm_free_irq(pdata->dev, pdata->ecc_irq, pdata);
+
+err_dev_irq:
 	devm_free_irq(pdata->dev, pdata->dev_irq, pdata);
 
 	return ret;
@@ -696,6 +886,9 @@ static void xgbe_free_irqs(struct xgbe_p
 
 	devm_free_irq(pdata->dev, pdata->dev_irq, pdata);
 
+	if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq))
+		devm_free_irq(pdata->dev, pdata->ecc_irq, pdata);
+
 	if (!pdata->per_channel_irq)
 		return;
 
@@ -783,7 +976,7 @@ static void xgbe_free_rx_data(struct xgb
 	DBGPR("<--xgbe_free_rx_data\n");
 }
 
-static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
 {
 	pdata->phy_link = -1;
 	pdata->phy_speed = SPEED_UNKNOWN;
@@ -877,11 +1070,9 @@ static int xgbe_start(struct xgbe_prv_da
 
 	DBGPR("-->xgbe_start\n");
 
-	hw_if->init(pdata);
-
-	ret = phy_if->phy_start(pdata);
+	ret = hw_if->init(pdata);
 	if (ret)
-		goto err_phy;
+		return ret;
 
 	xgbe_napi_enable(pdata, 1);
 
@@ -889,6 +1080,10 @@ static int xgbe_start(struct xgbe_prv_da
 	if (ret)
 		goto err_napi;
 
+	ret = phy_if->phy_start(pdata);
+	if (ret)
+		goto err_irqs;
+
 	hw_if->enable_tx(pdata);
 	hw_if->enable_rx(pdata);
 
@@ -897,16 +1092,18 @@ static int xgbe_start(struct xgbe_prv_da
 	xgbe_start_timers(pdata);
 	queue_work(pdata->dev_workqueue, &pdata->service_work);
 
+	clear_bit(XGBE_STOPPED, &pdata->dev_state);
+
 	DBGPR("<--xgbe_start\n");
 
 	return 0;
 
+err_irqs:
+	xgbe_free_irqs(pdata);
+
 err_napi:
 	xgbe_napi_disable(pdata, 1);
 
-	phy_if->phy_stop(pdata);
-
-err_phy:
 	hw_if->exit(pdata);
 
 	return ret;
@@ -923,6 +1120,9 @@ static void xgbe_stop(struct xgbe_prv_da
 
 	DBGPR("-->xgbe_stop\n");
 
+	if (test_bit(XGBE_STOPPED, &pdata->dev_state))
+		return;
+
 	netif_tx_stop_all_queues(netdev);
 
 	xgbe_stop_timers(pdata);
@@ -948,9 +1148,29 @@ static void xgbe_stop(struct xgbe_prv_da
 		netdev_tx_reset_queue(txq);
 	}
 
+	set_bit(XGBE_STOPPED, &pdata->dev_state);
+
 	DBGPR("<--xgbe_stop\n");
 }
 
+static void xgbe_stopdev(struct work_struct *work)
+{
+	struct xgbe_prv_data *pdata = container_of(work,
+						   struct xgbe_prv_data,
+						   stopdev_work);
+
+	rtnl_lock();
+
+	xgbe_stop(pdata);
+
+	xgbe_free_tx_data(pdata);
+	xgbe_free_rx_data(pdata);
+
+	rtnl_unlock();
+
+	netdev_alert(pdata->netdev, "device stopped\n");
+}
+
 static void xgbe_restart_dev(struct xgbe_prv_data *pdata)
 {
 	DBGPR("-->xgbe_restart_dev\n");
@@ -1297,8 +1517,8 @@ static int xgbe_open(struct net_device *
 
 	DBGPR("-->xgbe_open\n");
 
-	/* Initialize the phy */
-	ret = xgbe_phy_init(pdata);
+	/* Reset the phy settings */
+	ret = xgbe_phy_reset(pdata);
 	if (ret)
 		return ret;
 
@@ -1333,6 +1553,7 @@ static int xgbe_open(struct net_device *
 
 	INIT_WORK(&pdata->service_work, xgbe_service);
 	INIT_WORK(&pdata->restart_work, xgbe_restart);
+	INIT_WORK(&pdata->stopdev_work, xgbe_stopdev);
 	INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
 	xgbe_init_timers(pdata);
 
@@ -2041,6 +2262,7 @@ static int xgbe_one_poll(struct napi_str
 {
 	struct xgbe_channel *channel = container_of(napi, struct xgbe_channel,
 						    napi);
+	struct xgbe_prv_data *pdata = channel->pdata;
 	int processed = 0;
 
 	DBGPR("-->xgbe_one_poll: budget=%d\n", budget);
@@ -2057,7 +2279,10 @@ static int xgbe_one_poll(struct napi_str
 		napi_complete_done(napi, processed);
 
 		/* Enable Tx and Rx interrupts */
-		enable_irq(channel->dma_irq);
+		if (pdata->channel_irq_mode)
+			xgbe_enable_rx_tx_int(pdata, channel);
+		else
+			enable_irq(channel->dma_irq);
 	}
 
 	DBGPR("<--xgbe_one_poll: received = %d\n", processed);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -272,97 +272,86 @@ static int xgbe_set_pauseparam(struct ne
 	return ret;
 }
 
-static int xgbe_get_settings(struct net_device *netdev,
-			     struct ethtool_cmd *cmd)
+static int xgbe_get_link_ksettings(struct net_device *netdev,
+				   struct ethtool_link_ksettings *cmd)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
 
-	cmd->phy_address = pdata->phy.address;
+	cmd->base.phy_address = pdata->phy.address;
 
-	cmd->supported = pdata->phy.supported;
-	cmd->advertising = pdata->phy.advertising;
-	cmd->lp_advertising = pdata->phy.lp_advertising;
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						pdata->phy.supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						pdata->phy.advertising);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising,
+						pdata->phy.lp_advertising);
 
-	cmd->autoneg = pdata->phy.autoneg;
-	ethtool_cmd_speed_set(cmd, pdata->phy.speed);
-	cmd->duplex = pdata->phy.duplex;
+	cmd->base.autoneg = pdata->phy.autoneg;
+	cmd->base.speed = pdata->phy.speed;
+	cmd->base.duplex = pdata->phy.duplex;
 
-	cmd->port = PORT_NONE;
-	cmd->transceiver = XCVR_INTERNAL;
+	cmd->base.port = PORT_NONE;
 
 	return 0;
 }
 
-static int xgbe_set_settings(struct net_device *netdev,
-			     struct ethtool_cmd *cmd)
+static int xgbe_set_link_ksettings(struct net_device *netdev,
+				   const struct ethtool_link_ksettings *cmd)
 {
 	struct xgbe_prv_data *pdata = netdev_priv(netdev);
+	u32 advertising;
 	u32 speed;
 	int ret;
 
-	speed = ethtool_cmd_speed(cmd);
+	speed = cmd->base.speed;
 
-	if (cmd->phy_address != pdata->phy.address) {
+	if (cmd->base.phy_address != pdata->phy.address) {
 		netdev_err(netdev, "invalid phy address %hhu\n",
-			   cmd->phy_address);
+			   cmd->base.phy_address);
 		return -EINVAL;
 	}
 
-	if ((cmd->autoneg != AUTONEG_ENABLE) &&
-	    (cmd->autoneg != AUTONEG_DISABLE)) {
+	if ((cmd->base.autoneg != AUTONEG_ENABLE) &&
+	    (cmd->base.autoneg != AUTONEG_DISABLE)) {
 		netdev_err(netdev, "unsupported autoneg %hhu\n",
-			   cmd->autoneg);
+			   cmd->base.autoneg);
 		return -EINVAL;
 	}
 
-	if (cmd->autoneg == AUTONEG_DISABLE) {
-		switch (speed) {
-		case SPEED_10000:
-			break;
-		case SPEED_2500:
-			if (pdata->speed_set != XGBE_SPEEDSET_2500_10000) {
-				netdev_err(netdev, "unsupported speed %u\n",
-					   speed);
-				return -EINVAL;
-			}
-			break;
-		case SPEED_1000:
-			if (pdata->speed_set != XGBE_SPEEDSET_1000_10000) {
-				netdev_err(netdev, "unsupported speed %u\n",
-					   speed);
-				return -EINVAL;
-			}
-			break;
-		default:
+	if (cmd->base.autoneg == AUTONEG_DISABLE) {
+		if (!pdata->phy_if.phy_valid_speed(pdata, speed)) {
 			netdev_err(netdev, "unsupported speed %u\n", speed);
 			return -EINVAL;
 		}
 
-		if (cmd->duplex != DUPLEX_FULL) {
+		if (cmd->base.duplex != DUPLEX_FULL) {
 			netdev_err(netdev, "unsupported duplex %hhu\n",
-				   cmd->duplex);
+				   cmd->base.duplex);
 			return -EINVAL;
 		}
 	}
 
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						cmd->link_modes.advertising);
+
 	netif_dbg(pdata, link, netdev,
 		  "requested advertisement %#x, phy supported %#x\n",
-		  cmd->advertising, pdata->phy.supported);
+		  advertising, pdata->phy.supported);
 
-	cmd->advertising &= pdata->phy.supported;
-	if ((cmd->autoneg == AUTONEG_ENABLE) && !cmd->advertising) {
+	advertising &= pdata->phy.supported;
+	if ((cmd->base.autoneg == AUTONEG_ENABLE) && !advertising) {
 		netdev_err(netdev,
 			   "unsupported requested advertisement\n");
 		return -EINVAL;
 	}
 
 	ret = 0;
-	pdata->phy.autoneg = cmd->autoneg;
+	pdata->phy.autoneg = cmd->base.autoneg;
 	pdata->phy.speed = speed;
-	pdata->phy.duplex = cmd->duplex;
-	pdata->phy.advertising = cmd->advertising;
+	pdata->phy.duplex = cmd->base.duplex;
+	pdata->phy.advertising = advertising;
 
-	if (cmd->autoneg == AUTONEG_ENABLE)
+	if (cmd->base.autoneg == AUTONEG_ENABLE)
 		pdata->phy.advertising |= ADVERTISED_Autoneg;
 	else
 		pdata->phy.advertising &= ~ADVERTISED_Autoneg;
@@ -602,8 +591,6 @@ static int xgbe_get_ts_info(struct net_d
 }
 
 static const struct ethtool_ops xgbe_ethtool_ops = {
-	.get_settings = xgbe_get_settings,
-	.set_settings = xgbe_set_settings,
 	.get_drvinfo = xgbe_get_drvinfo,
 	.get_msglevel = xgbe_get_msglevel,
 	.set_msglevel = xgbe_set_msglevel,
@@ -621,6 +608,8 @@ static const struct ethtool_ops xgbe_eth
 	.get_rxfh = xgbe_get_rxfh,
 	.set_rxfh = xgbe_set_rxfh,
 	.get_ts_info = xgbe_get_ts_info,
+	.get_link_ksettings = xgbe_get_link_ksettings,
+	.set_link_ksettings = xgbe_set_link_ksettings,
 };
 
 const struct ethtool_ops *xgbe_get_ethtool_ops(void)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe.h	2017-02-12 16:03:20.000000000 -0500
@@ -127,9 +127,10 @@
 #include <linux/timecounter.h>
 #include <linux/net_tstamp.h>
 #include <net/dcbnl.h>
+#include <linux/completion.h>
 
 #define XGBE_DRV_NAME		"amd-xgbe"
-#define XGBE_DRV_VERSION	"1.0.2"
+#define XGBE_DRV_VERSION	"1.0.3"
 #define XGBE_DRV_DESC		"AMD 10 Gigabit Ethernet Driver"
 
 /* Descriptor related defines */
@@ -158,7 +159,8 @@
 
 #define XGBE_MAX_DMA_CHANNELS	16
 #define XGBE_MAX_QUEUES		16
-#define XGBE_DMA_STOP_TIMEOUT	5
+#define XGBE_PRIORITY_QUEUES	8
+#define XGBE_DMA_STOP_TIMEOUT	1
 
 /* DMA cache settings - Outer sharable, write-back, write-allocate */
 #define XGBE_DMA_OS_AXDOMAIN	0x2
@@ -170,6 +172,10 @@
 #define XGBE_DMA_SYS_ARCACHE	0x0
 #define XGBE_DMA_SYS_AWCACHE	0x0
 
+/* DMA channel interrupt modes */
+#define XGBE_IRQ_MODE_EDGE	0
+#define XGBE_IRQ_MODE_LEVEL	1
+
 #define XGBE_DMA_INTERRUPT_MASK	0x31c7
 
 #define XGMAC_MIN_PACKET	60
@@ -177,18 +183,19 @@
 #define XGMAC_MAX_STD_PACKET	1518
 #define XGMAC_JUMBO_PACKET_MTU	9000
 #define XGMAC_MAX_JUMBO_PACKET	9018
+#define XGMAC_ETH_PREAMBLE	(12 + 8)	/* Inter-frame gap + preamble */
+
+#define XGMAC_PFC_DATA_LEN	46
+#define XGMAC_PFC_DELAYS	14000
+
+#define XGMAC_PRIO_QUEUES(_cnt)					\
+	min_t(unsigned int, IEEE_8021QAZ_MAX_TCS, (_cnt))
 
 /* Common property names */
 #define XGBE_MAC_ADDR_PROPERTY	"mac-address"
 #define XGBE_PHY_MODE_PROPERTY	"phy-mode"
 #define XGBE_DMA_IRQS_PROPERTY	"amd,per-channel-interrupt"
 #define XGBE_SPEEDSET_PROPERTY	"amd,speed-set"
-#define XGBE_BLWC_PROPERTY	"amd,serdes-blwc"
-#define XGBE_CDR_RATE_PROPERTY	"amd,serdes-cdr-rate"
-#define XGBE_PQ_SKEW_PROPERTY	"amd,serdes-pq-skew"
-#define XGBE_TX_AMP_PROPERTY	"amd,serdes-tx-amp"
-#define XGBE_DFE_CFG_PROPERTY	"amd,serdes-dfe-tap-config"
-#define XGBE_DFE_ENA_PROPERTY	"amd,serdes-dfe-tap-enable"
 
 /* Device-tree clock names */
 #define XGBE_DMA_CLOCK		"dma_clk"
@@ -198,6 +205,20 @@
 #define XGBE_ACPI_DMA_FREQ	"amd,dma-freq"
 #define XGBE_ACPI_PTP_FREQ	"amd,ptp-freq"
 
+/* PCI BAR mapping */
+#define XGBE_XGMAC_BAR		0
+#define XGBE_XPCS_BAR		1
+#define XGBE_MAC_PROP_OFFSET	0x1d000
+#define XGBE_I2C_CTRL_OFFSET	0x1e000
+
+/* PCI MSIx support */
+#define XGBE_MSIX_BASE_COUNT	4
+#define XGBE_MSIX_MIN_COUNT	(XGBE_MSIX_BASE_COUNT + 1)
+
+/* PCI clock frequencies */
+#define XGBE_V2_DMA_CLOCK_FREQ	500000000	/* 500 MHz */
+#define XGBE_V2_PTP_CLOCK_FREQ	125000000	/* 125 MHz */
+
 /* Timestamp support - values based on 50MHz PTP clock
  *   50MHz => 20 nsec
  */
@@ -208,7 +229,12 @@
 #define XGMAC_DRIVER_CONTEXT	1
 #define XGMAC_IOCTL_CONTEXT	2
 
-#define XGBE_FIFO_MAX		81920
+#define XGMAC_FIFO_MIN_ALLOC	2048
+#define XGMAC_FIFO_UNIT		256
+#define XGMAC_FIFO_ALIGN(_x)				\
+	(((_x) + XGMAC_FIFO_UNIT - 1) & ~(XGMAC_FIFO_UNIT - 1))
+#define XGMAC_FIFO_FC_OFF	2048
+#define XGMAC_FIFO_FC_MIN	4096
 
 #define XGBE_TC_MIN_QUANTUM	10
 
@@ -233,6 +259,14 @@
 /* Flow control queue count */
 #define XGMAC_MAX_FLOW_CONTROL_QUEUES	8
 
+/* Flow control threshold units */
+#define XGMAC_FLOW_CONTROL_UNIT		512
+#define XGMAC_FLOW_CONTROL_ALIGN(_x)				\
+	(((_x) + XGMAC_FLOW_CONTROL_UNIT - 1) & ~(XGMAC_FLOW_CONTROL_UNIT - 1))
+#define XGMAC_FLOW_CONTROL_VALUE(_x)				\
+	(((_x) < 1024) ? 0 : ((_x) / XGMAC_FLOW_CONTROL_UNIT) - 2)
+#define XGMAC_FLOW_CONTROL_MAX		33280
+
 /* Maximum MAC address hash table size (256 bits = 8 bytes) */
 #define XGBE_MAC_HASH_TABLE_SIZE	8
 
@@ -244,46 +278,19 @@
 
 /* Auto-negotiation */
 #define XGBE_AN_MS_TIMEOUT		500
-#define XGBE_LINK_TIMEOUT		10
-
-#define XGBE_AN_INT_CMPLT		0x01
-#define XGBE_AN_INC_LINK		0x02
-#define XGBE_AN_PG_RCV			0x04
-#define XGBE_AN_INT_MASK		0x07
-
-/* Rate-change complete wait/retry count */
-#define XGBE_RATECHANGE_COUNT		500
+#define XGBE_LINK_TIMEOUT		5
 
-/* Default SerDes settings */
-#define XGBE_SPEED_10000_BLWC		0
-#define XGBE_SPEED_10000_CDR		0x7
-#define XGBE_SPEED_10000_PLL		0x1
-#define XGBE_SPEED_10000_PQ		0x12
-#define XGBE_SPEED_10000_RATE		0x0
-#define XGBE_SPEED_10000_TXAMP		0xa
-#define XGBE_SPEED_10000_WORD		0x7
-#define XGBE_SPEED_10000_DFE_TAP_CONFIG	0x1
-#define XGBE_SPEED_10000_DFE_TAP_ENABLE	0x7f
+#define XGBE_SGMII_AN_LINK_STATUS	BIT(1)
+#define XGBE_SGMII_AN_LINK_SPEED	(BIT(2) | BIT(3))
+#define XGBE_SGMII_AN_LINK_SPEED_100	0x04
+#define XGBE_SGMII_AN_LINK_SPEED_1000	0x08
+#define XGBE_SGMII_AN_LINK_DUPLEX	BIT(4)
 
-#define XGBE_SPEED_2500_BLWC		1
-#define XGBE_SPEED_2500_CDR		0x2
-#define XGBE_SPEED_2500_PLL		0x0
-#define XGBE_SPEED_2500_PQ		0xa
-#define XGBE_SPEED_2500_RATE		0x1
-#define XGBE_SPEED_2500_TXAMP		0xf
-#define XGBE_SPEED_2500_WORD		0x1
-#define XGBE_SPEED_2500_DFE_TAP_CONFIG	0x3
-#define XGBE_SPEED_2500_DFE_TAP_ENABLE	0x0
+/* ECC correctable error notification window (seconds) */
+#define XGBE_ECC_LIMIT			60
 
-#define XGBE_SPEED_1000_BLWC		1
-#define XGBE_SPEED_1000_CDR		0x2
-#define XGBE_SPEED_1000_PLL		0x0
-#define XGBE_SPEED_1000_PQ		0xa
-#define XGBE_SPEED_1000_RATE		0x3
-#define XGBE_SPEED_1000_TXAMP		0xf
-#define XGBE_SPEED_1000_WORD		0x1
-#define XGBE_SPEED_1000_DFE_TAP_CONFIG	0x3
-#define XGBE_SPEED_1000_DFE_TAP_ENABLE	0x0
+/* MDIO port types */
+#define XGMAC_MAX_C22_PORT		3
 
 struct xgbe_prv_data;
 
@@ -461,6 +468,7 @@ enum xgbe_state {
 	XGBE_DOWN,
 	XGBE_LINK_INIT,
 	XGBE_LINK_ERR,
+	XGBE_STOPPED,
 };
 
 enum xgbe_int {
@@ -480,6 +488,12 @@ enum xgbe_int_state {
 	XGMAC_INT_STATE_RESTORE,
 };
 
+enum xgbe_ecc_sec {
+	XGBE_ECC_SEC_TX,
+	XGBE_ECC_SEC_RX,
+	XGBE_ECC_SEC_DESC,
+};
+
 enum xgbe_speed {
 	XGBE_SPEED_1000 = 0,
 	XGBE_SPEED_2500,
@@ -487,6 +501,19 @@ enum xgbe_speed {
 	XGBE_SPEEDS,
 };
 
+enum xgbe_xpcs_access {
+	XGBE_XPCS_ACCESS_V1 = 0,
+	XGBE_XPCS_ACCESS_V2,
+};
+
+enum xgbe_an_mode {
+	XGBE_AN_MODE_CL73 = 0,
+	XGBE_AN_MODE_CL73_REDRV,
+	XGBE_AN_MODE_CL37,
+	XGBE_AN_MODE_CL37_SGMII,
+	XGBE_AN_MODE_NONE,
+};
+
 enum xgbe_an {
 	XGBE_AN_READY = 0,
 	XGBE_AN_PAGE_RECEIVED,
@@ -504,8 +531,14 @@ enum xgbe_rx {
 };
 
 enum xgbe_mode {
-	XGBE_MODE_KR = 0,
-	XGBE_MODE_KX,
+	XGBE_MODE_KX_1000 = 0,
+	XGBE_MODE_KX_2500,
+	XGBE_MODE_KR,
+	XGBE_MODE_X,
+	XGBE_MODE_SGMII_100,
+	XGBE_MODE_SGMII_1000,
+	XGBE_MODE_SFI,
+	XGBE_MODE_UNKNOWN,
 };
 
 enum xgbe_speedset {
@@ -513,6 +546,12 @@ enum xgbe_speedset {
 	XGBE_SPEEDSET_2500_10000,
 };
 
+enum xgbe_mdio_mode {
+	XGBE_MDIO_MODE_NONE = 0,
+	XGBE_MDIO_MODE_CL22,
+	XGBE_MDIO_MODE_CL45,
+};
+
 struct xgbe_phy {
 	u32 supported;
 	u32 advertising;
@@ -531,6 +570,43 @@ struct xgbe_phy {
 	int rx_pause;
 };
 
+enum xgbe_i2c_cmd {
+	XGBE_I2C_CMD_READ = 0,
+	XGBE_I2C_CMD_WRITE,
+};
+
+struct xgbe_i2c_op {
+	enum xgbe_i2c_cmd cmd;
+
+	unsigned int target;
+
+	void *buf;
+	unsigned int len;
+};
+
+struct xgbe_i2c_op_state {
+	struct xgbe_i2c_op *op;
+
+	unsigned int tx_len;
+	unsigned char *tx_buf;
+
+	unsigned int rx_len;
+	unsigned char *rx_buf;
+
+	unsigned int tx_abort_source;
+
+	int ret;
+};
+
+struct xgbe_i2c {
+	unsigned int started;
+	unsigned int max_speed_mode;
+	unsigned int rx_fifo_size;
+	unsigned int tx_fifo_size;
+
+	struct xgbe_i2c_op_state op_state;
+};
+
 struct xgbe_mmc_stats {
 	/* Tx Stats */
 	u64 txoctetcount_gb;
@@ -601,9 +677,15 @@ struct xgbe_hw_if {
 
 	int (*read_mmd_regs)(struct xgbe_prv_data *, int, int);
 	void (*write_mmd_regs)(struct xgbe_prv_data *, int, int, int);
-	int (*set_gmii_speed)(struct xgbe_prv_data *);
-	int (*set_gmii_2500_speed)(struct xgbe_prv_data *);
-	int (*set_xgmii_speed)(struct xgbe_prv_data *);
+	int (*set_speed)(struct xgbe_prv_data *, int);
+
+	int (*set_ext_mii_mode)(struct xgbe_prv_data *, unsigned int,
+				enum xgbe_mdio_mode);
+	int (*read_ext_mii_regs)(struct xgbe_prv_data *, int, int);
+	int (*write_ext_mii_regs)(struct xgbe_prv_data *, int, int, u16);
+
+	int (*set_gpio)(struct xgbe_prv_data *, unsigned int);
+	int (*clr_gpio)(struct xgbe_prv_data *, unsigned int);
 
 	void (*enable_tx)(struct xgbe_prv_data *);
 	void (*disable_tx)(struct xgbe_prv_data *);
@@ -682,11 +764,65 @@ struct xgbe_hw_if {
 	int (*disable_rss)(struct xgbe_prv_data *);
 	int (*set_rss_hash_key)(struct xgbe_prv_data *, const u8 *);
 	int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *);
+
+	/* For ECC */
+	void (*disable_ecc_ded)(struct xgbe_prv_data *);
+	void (*disable_ecc_sec)(struct xgbe_prv_data *, enum xgbe_ecc_sec);
+};
+
+/* This structure represents implementation specific routines for an
+ * implementation of a PHY. All routines are required unless noted below.
+ *   Optional routines:
+ *     kr_training_pre, kr_training_post
+ */
+struct xgbe_phy_impl_if {
+	/* Perform Setup/teardown actions */
+	int (*init)(struct xgbe_prv_data *);
+	void (*exit)(struct xgbe_prv_data *);
+
+	/* Perform start/stop specific actions */
+	int (*reset)(struct xgbe_prv_data *);
+	int (*start)(struct xgbe_prv_data *);
+	void (*stop)(struct xgbe_prv_data *);
+
+	/* Return the link status */
+	int (*link_status)(struct xgbe_prv_data *, int *);
+
+	/* Indicate if a particular speed is valid */
+	bool (*valid_speed)(struct xgbe_prv_data *, int);
+
+	/* Check if the specified mode can/should be used */
+	bool (*use_mode)(struct xgbe_prv_data *, enum xgbe_mode);
+	/* Switch the PHY into various modes */
+	void (*set_mode)(struct xgbe_prv_data *, enum xgbe_mode);
+	/* Retrieve mode needed for a specific speed */
+	enum xgbe_mode (*get_mode)(struct xgbe_prv_data *, int);
+	/* Retrieve new/next mode when trying to auto-negotiate */
+	enum xgbe_mode (*switch_mode)(struct xgbe_prv_data *);
+	/* Retrieve current mode */
+	enum xgbe_mode (*cur_mode)(struct xgbe_prv_data *);
+
+	/* Retrieve current auto-negotiation mode */
+	enum xgbe_an_mode (*an_mode)(struct xgbe_prv_data *);
+
+	/* Configure auto-negotiation settings */
+	int (*an_config)(struct xgbe_prv_data *);
+
+	/* Set/override auto-negotiation advertisement settings */
+	unsigned int (*an_advertising)(struct xgbe_prv_data *);
+
+	/* Process results of auto-negotiation */
+	enum xgbe_mode (*an_outcome)(struct xgbe_prv_data *);
+
+	/* Pre/Post KR training enablement support */
+	void (*kr_training_pre)(struct xgbe_prv_data *);
+	void (*kr_training_post)(struct xgbe_prv_data *);
 };
 
 struct xgbe_phy_if {
-	/* For initial PHY setup */
-	void (*phy_init)(struct xgbe_prv_data *);
+	/* For PHY setup/teardown */
+	int (*phy_init)(struct xgbe_prv_data *);
+	void (*phy_exit)(struct xgbe_prv_data *);
 
 	/* For PHY support when setting device up/down */
 	int (*phy_reset)(struct xgbe_prv_data *);
@@ -696,6 +832,30 @@ struct xgbe_phy_if {
 	/* For PHY support while device is up */
 	void (*phy_status)(struct xgbe_prv_data *);
 	int (*phy_config_aneg)(struct xgbe_prv_data *);
+
+	/* For PHY settings validation */
+	bool (*phy_valid_speed)(struct xgbe_prv_data *, int);
+
+	/* For single interrupt support */
+	irqreturn_t (*an_isr)(int, struct xgbe_prv_data *);
+
+	/* PHY implementation specific services */
+	struct xgbe_phy_impl_if phy_impl;
+};
+
+struct xgbe_i2c_if {
+	/* For initial I2C setup */
+	int (*i2c_init)(struct xgbe_prv_data *);
+
+	/* For I2C support when setting device up/down */
+	int (*i2c_start)(struct xgbe_prv_data *);
+	void (*i2c_stop)(struct xgbe_prv_data *);
+
+	/* For performing I2C operations */
+	int (*i2c_xfer)(struct xgbe_prv_data *, struct xgbe_i2c_op *);
+
+	/* For single interrupt support */
+	irqreturn_t (*i2c_isr)(int, struct xgbe_prv_data *);
 };
 
 struct xgbe_desc_if {
@@ -755,11 +915,28 @@ struct xgbe_hw_features {
 	unsigned int aux_snap_num;	/* Number of Aux snapshot inputs */
 };
 
+struct xgbe_version_data {
+	void (*init_function_ptrs_phy_impl)(struct xgbe_phy_if *);
+	enum xgbe_xpcs_access xpcs_access;
+	unsigned int mmc_64bit;
+	unsigned int tx_max_fifo_size;
+	unsigned int rx_max_fifo_size;
+	unsigned int tx_tstamp_workaround;
+	unsigned int ecc_support;
+	unsigned int i2c_support;
+};
+
 struct xgbe_prv_data {
 	struct net_device *netdev;
-	struct platform_device *pdev;
+	struct pci_dev *pcidev;
+	struct platform_device *platdev;
 	struct acpi_device *adev;
 	struct device *dev;
+	struct platform_device *phy_platdev;
+	struct device *phy_dev;
+
+	/* Version related data */
+	struct xgbe_version_data *vdata;
 
 	/* ACPI or DT flag */
 	unsigned int use_acpi;
@@ -770,12 +947,19 @@ struct xgbe_prv_data {
 	void __iomem *rxtx_regs;	/* SerDes Rx/Tx CSRs */
 	void __iomem *sir0_regs;	/* SerDes integration registers (1/2) */
 	void __iomem *sir1_regs;	/* SerDes integration registers (2/2) */
+	void __iomem *xprop_regs;	/* XGBE property registers */
+	void __iomem *xi2c_regs;	/* XGBE I2C CSRs */
 
 	/* Overall device lock */
 	spinlock_t lock;
 
 	/* XPCS indirect addressing lock */
 	spinlock_t xpcs_lock;
+	unsigned int xpcs_window_def_reg;
+	unsigned int xpcs_window_sel_reg;
+	unsigned int xpcs_window;
+	unsigned int xpcs_window_size;
+	unsigned int xpcs_window_mask;
 
 	/* RSS addressing mutex */
 	struct mutex rss_mutex;
@@ -783,12 +967,39 @@ struct xgbe_prv_data {
 	/* Flags representing xgbe_state */
 	unsigned long dev_state;
 
+	/* ECC support */
+	unsigned long tx_sec_period;
+	unsigned long tx_ded_period;
+	unsigned long rx_sec_period;
+	unsigned long rx_ded_period;
+	unsigned long desc_sec_period;
+	unsigned long desc_ded_period;
+
+	unsigned int tx_sec_count;
+	unsigned int tx_ded_count;
+	unsigned int rx_sec_count;
+	unsigned int rx_ded_count;
+	unsigned int desc_ded_count;
+	unsigned int desc_sec_count;
+
+	struct msix_entry *msix_entries;
 	int dev_irq;
+	int ecc_irq;
+	int i2c_irq;
+	int channel_irq[XGBE_MAX_DMA_CHANNELS];
+
 	unsigned int per_channel_irq;
+	unsigned int irq_shared;
+	unsigned int irq_count;
+	unsigned int channel_irq_count;
+	unsigned int channel_irq_mode;
+
+	char ecc_name[IFNAMSIZ + 32];
 
 	struct xgbe_hw_if hw_if;
 	struct xgbe_phy_if phy_if;
 	struct xgbe_desc_if desc_if;
+	struct xgbe_i2c_if i2c_if;
 
 	/* AXI DMA settings */
 	unsigned int coherent;
@@ -803,12 +1014,16 @@ struct xgbe_prv_data {
 
 	/* Rings for Tx/Rx on a DMA channel */
 	struct xgbe_channel *channel;
+	unsigned int tx_max_channel_count;
+	unsigned int rx_max_channel_count;
 	unsigned int channel_count;
 	unsigned int tx_ring_count;
 	unsigned int tx_desc_count;
 	unsigned int rx_ring_count;
 	unsigned int rx_desc_count;
 
+	unsigned int tx_max_q_count;
+	unsigned int rx_max_q_count;
 	unsigned int tx_q_count;
 	unsigned int rx_q_count;
 
@@ -820,11 +1035,13 @@ struct xgbe_prv_data {
 	unsigned int tx_threshold;
 	unsigned int tx_pbl;
 	unsigned int tx_osp_mode;
+	unsigned int tx_max_fifo_size;
 
 	/* Rx settings */
 	unsigned int rx_sf_mode;
 	unsigned int rx_threshold;
 	unsigned int rx_pbl;
+	unsigned int rx_max_fifo_size;
 
 	/* Tx coalescing settings */
 	unsigned int tx_usecs;
@@ -842,6 +1059,8 @@ struct xgbe_prv_data {
 	unsigned int pause_autoneg;
 	unsigned int tx_pause;
 	unsigned int rx_pause;
+	unsigned int rx_rfa[XGBE_MAX_QUEUES];
+	unsigned int rx_rfd[XGBE_MAX_QUEUES];
 
 	/* Receive Side Scaling settings */
 	u8 rss_key[XGBE_RSS_HASH_KEY_SIZE];
@@ -881,13 +1100,16 @@ struct xgbe_prv_data {
 	struct ieee_pfc *pfc;
 	unsigned int q2tc_map[XGBE_MAX_QUEUES];
 	unsigned int prio2q_map[IEEE_8021QAZ_MAX_TCS];
+	unsigned int pfcq[XGBE_MAX_QUEUES];
+	unsigned int pfc_rfa;
 	u8 num_tcs;
 
 	/* Hardware features of the device */
 	struct xgbe_hw_features hw_feat;
 
-	/* Device restart work structure */
+	/* Device work structures */
 	struct work_struct restart_work;
+	struct work_struct stopdev_work;
 
 	/* Keeps track of power mode */
 	unsigned int power_down;
@@ -901,9 +1123,14 @@ struct xgbe_prv_data {
 	int phy_speed;
 
 	/* MDIO/PHY related settings */
+	unsigned int phy_started;
+	void *phy_data;
 	struct xgbe_phy phy;
 	int mdio_mmd;
 	unsigned long link_check;
+	struct completion mdio_complete;
+
+	unsigned int kr_redrv;
 
 	char an_name[IFNAMSIZ + 32];
 	struct workqueue_struct *an_workqueue;
@@ -911,23 +1138,9 @@ struct xgbe_prv_data {
 	int an_irq;
 	struct work_struct an_irq_work;
 
-	unsigned int speed_set;
-
-	/* SerDes UEFI configurable settings.
-	 *   Switching between modes/speeds requires new values for some
-	 *   SerDes settings.  The values can be supplied as device
-	 *   properties in array format.  The first array entry is for
-	 *   1GbE, second for 2.5GbE and third for 10GbE
-	 */
-	u32 serdes_blwc[XGBE_SPEEDS];
-	u32 serdes_cdr_rate[XGBE_SPEEDS];
-	u32 serdes_pq_skew[XGBE_SPEEDS];
-	u32 serdes_tx_amp[XGBE_SPEEDS];
-	u32 serdes_dfe_tap_cfg[XGBE_SPEEDS];
-	u32 serdes_dfe_tap_ena[XGBE_SPEEDS];
-
 	/* Auto-negotiation state machine support */
 	unsigned int an_int;
+	unsigned int an_status;
 	struct mutex an_mutex;
 	enum xgbe_an an_result;
 	enum xgbe_an an_state;
@@ -938,6 +1151,13 @@ struct xgbe_prv_data {
 	unsigned int parallel_detect;
 	unsigned int fec_ability;
 	unsigned long an_start;
+	enum xgbe_an_mode an_mode;
+
+	/* I2C support */
+	struct xgbe_i2c i2c;
+	struct mutex i2c_mutex;
+	struct completion i2c_complete;
+	char i2c_name[IFNAMSIZ + 32];
 
 	unsigned int lpm_ctrl;		/* CTRL1 for resume */
 
@@ -948,14 +1168,36 @@ struct xgbe_prv_data {
 
 	unsigned int debugfs_xpcs_mmd;
 	unsigned int debugfs_xpcs_reg;
+
+	unsigned int debugfs_xprop_reg;
+
+	unsigned int debugfs_xi2c_reg;
 #endif
 };
 
 /* Function prototypes*/
+struct xgbe_prv_data *xgbe_alloc_pdata(struct device *);
+void xgbe_free_pdata(struct xgbe_prv_data *);
+void xgbe_set_counts(struct xgbe_prv_data *);
+int xgbe_config_netdev(struct xgbe_prv_data *);
+void xgbe_deconfig_netdev(struct xgbe_prv_data *);
+
+int xgbe_platform_init(void);
+void xgbe_platform_exit(void);
+#ifdef CONFIG_PCI
+int xgbe_pci_init(void);
+void xgbe_pci_exit(void);
+#else
+static inline int xgbe_pci_init(void) { return 0; }
+static inline void xgbe_pci_exit(void) { }
+#endif
 
 void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *);
 void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *);
+void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *);
+void xgbe_init_function_ptrs_phy_v2(struct xgbe_phy_if *);
 void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *);
+void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *);
 const struct net_device_ops *xgbe_get_netdev_ops(void);
 const struct ethtool_ops *xgbe_get_ethtool_ops(void);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,492 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Advanced Micro Devices, Inc. nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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 file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ *     THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#define XGBE_ABORT_COUNT	500
+#define XGBE_DISABLE_COUNT	1000
+
+#define XGBE_STD_SPEED		1
+
+#define XGBE_INTR_RX_FULL	BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX)
+#define XGBE_INTR_TX_EMPTY	BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX)
+#define XGBE_INTR_TX_ABRT	BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX)
+#define XGBE_INTR_STOP_DET	BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX)
+#define XGBE_DEFAULT_INT_MASK	(XGBE_INTR_RX_FULL  |	\
+				 XGBE_INTR_TX_EMPTY |	\
+				 XGBE_INTR_TX_ABRT  |	\
+				 XGBE_INTR_STOP_DET)
+
+#define XGBE_I2C_READ		BIT(8)
+#define XGBE_I2C_STOP		BIT(9)
+
+static int xgbe_i2c_abort(struct xgbe_prv_data *pdata)
+{
+	unsigned int wait = XGBE_ABORT_COUNT;
+
+	/* Must be enabled to recognize the abort request */
+	XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1);
+
+	/* Issue the abort */
+	XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1);
+
+	while (wait--) {
+		if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT))
+			return 0;
+
+		usleep_range(500, 600);
+	}
+
+	return -EBUSY;
+}
+
+static int xgbe_i2c_set_enable(struct xgbe_prv_data *pdata, bool enable)
+{
+	unsigned int wait = XGBE_DISABLE_COUNT;
+	unsigned int mode = enable ? 1 : 0;
+
+	while (wait--) {
+		XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode);
+		if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode)
+			return 0;
+
+		usleep_range(100, 110);
+	}
+
+	return -EBUSY;
+}
+
+static int xgbe_i2c_disable(struct xgbe_prv_data *pdata)
+{
+	unsigned int ret;
+
+	ret = xgbe_i2c_set_enable(pdata, false);
+	if (ret) {
+		/* Disable failed, try an abort */
+		ret = xgbe_i2c_abort(pdata);
+		if (ret)
+			return ret;
+
+		/* Abort succeeded, try to disable again */
+		ret = xgbe_i2c_set_enable(pdata, false);
+	}
+
+	return ret;
+}
+
+static int xgbe_i2c_enable(struct xgbe_prv_data *pdata)
+{
+	return xgbe_i2c_set_enable(pdata, true);
+}
+
+static void xgbe_i2c_clear_all_interrupts(struct xgbe_prv_data *pdata)
+{
+	XI2C_IOREAD(pdata, IC_CLR_INTR);
+}
+
+static void xgbe_i2c_disable_interrupts(struct xgbe_prv_data *pdata)
+{
+	XI2C_IOWRITE(pdata, IC_INTR_MASK, 0);
+}
+
+static void xgbe_i2c_enable_interrupts(struct xgbe_prv_data *pdata)
+{
+	XI2C_IOWRITE(pdata, IC_INTR_MASK, XGBE_DEFAULT_INT_MASK);
+}
+
+static void xgbe_i2c_write(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+	unsigned int tx_slots;
+	unsigned int cmd;
+
+	/* Configured to never receive Rx overflows, so fill up Tx fifo */
+	tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR);
+	while (tx_slots && state->tx_len) {
+		if (state->op->cmd == XGBE_I2C_CMD_READ)
+			cmd = XGBE_I2C_READ;
+		else
+			cmd = *state->tx_buf++;
+
+		if (state->tx_len == 1)
+			XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1);
+
+		XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd);
+
+		tx_slots--;
+		state->tx_len--;
+	}
+
+	/* No more Tx operations, so ignore TX_EMPTY and return */
+	if (!state->tx_len)
+		XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0);
+}
+
+static void xgbe_i2c_read(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+	unsigned int rx_slots;
+
+	/* Anything to be read? */
+	if (state->op->cmd != XGBE_I2C_CMD_READ)
+		return;
+
+	rx_slots = XI2C_IOREAD(pdata, IC_RXFLR);
+	while (rx_slots && state->rx_len) {
+		*state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD);
+		state->rx_len--;
+		rx_slots--;
+	}
+}
+
+static void xgbe_i2c_clear_isr_interrupts(struct xgbe_prv_data *pdata,
+					  unsigned int isr)
+{
+	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+
+	if (isr & XGBE_INTR_TX_ABRT) {
+		state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE);
+		XI2C_IOREAD(pdata, IC_CLR_TX_ABRT);
+	}
+
+	if (isr & XGBE_INTR_STOP_DET)
+		XI2C_IOREAD(pdata, IC_CLR_STOP_DET);
+}
+
+static irqreturn_t xgbe_i2c_isr(int irq, void *data)
+{
+	struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+	unsigned int isr;
+
+	isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT);
+	netif_dbg(pdata, intr, pdata->netdev,
+		  "I2C interrupt received: status=%#010x\n", isr);
+
+	xgbe_i2c_clear_isr_interrupts(pdata, isr);
+
+	if (isr & XGBE_INTR_TX_ABRT) {
+		netif_dbg(pdata, link, pdata->netdev,
+			  "I2C TX_ABRT received (%#010x) for target %#04x\n",
+			  state->tx_abort_source, state->op->target);
+
+		xgbe_i2c_disable_interrupts(pdata);
+
+		state->ret = -EIO;
+		goto out;
+	}
+
+	/* Check for data in the Rx fifo */
+	xgbe_i2c_read(pdata);
+
+	/* Fill up the Tx fifo next */
+	xgbe_i2c_write(pdata);
+
+out:
+	/* Complete on an error or STOP condition */
+	if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET))
+		complete(&pdata->i2c_complete);
+
+	return IRQ_HANDLED;
+}
+
+static void xgbe_i2c_set_mode(struct xgbe_prv_data *pdata)
+{
+	unsigned int reg;
+
+	reg = XI2C_IOREAD(pdata, IC_CON);
+	XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1);
+	XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1);
+	XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1);
+	XI2C_SET_BITS(reg, IC_CON, SPEED, XGBE_STD_SPEED);
+	XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1);
+	XI2C_IOWRITE(pdata, IC_CON, reg);
+}
+
+static void xgbe_i2c_get_features(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_i2c *i2c = &pdata->i2c;
+	unsigned int reg;
+
+	reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1);
+	i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
+					    MAX_SPEED_MODE);
+	i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
+					  RX_BUFFER_DEPTH);
+	i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
+					  TX_BUFFER_DEPTH);
+
+	if (netif_msg_probe(pdata))
+		dev_dbg(pdata->dev, "I2C features: %s=%u, %s=%u, %s=%u\n",
+			"MAX_SPEED_MODE", i2c->max_speed_mode,
+			"RX_BUFFER_DEPTH", i2c->rx_fifo_size,
+			"TX_BUFFER_DEPTH", i2c->tx_fifo_size);
+}
+
+static void xgbe_i2c_set_target(struct xgbe_prv_data *pdata, unsigned int addr)
+{
+	XI2C_IOWRITE(pdata, IC_TAR, addr);
+}
+
+static irqreturn_t xgbe_i2c_combined_isr(int irq, struct xgbe_prv_data *pdata)
+{
+	if (!XI2C_IOREAD(pdata, IC_RAW_INTR_STAT))
+		return IRQ_HANDLED;
+
+	return xgbe_i2c_isr(irq, pdata);
+}
+
+static int xgbe_i2c_xfer(struct xgbe_prv_data *pdata, struct xgbe_i2c_op *op)
+{
+	struct xgbe_i2c_op_state *state = &pdata->i2c.op_state;
+	int ret;
+
+	mutex_lock(&pdata->i2c_mutex);
+
+	reinit_completion(&pdata->i2c_complete);
+
+	ret = xgbe_i2c_disable(pdata);
+	if (ret) {
+		netdev_err(pdata->netdev, "failed to disable i2c master\n");
+		goto unlock;
+	}
+
+	xgbe_i2c_set_target(pdata, op->target);
+
+	memset(state, 0, sizeof(*state));
+	state->op = op;
+	state->tx_len = op->len;
+	state->tx_buf = op->buf;
+	state->rx_len = op->len;
+	state->rx_buf = op->buf;
+
+	xgbe_i2c_clear_all_interrupts(pdata);
+	ret = xgbe_i2c_enable(pdata);
+	if (ret) {
+		netdev_err(pdata->netdev, "failed to enable i2c master\n");
+		goto unlock;
+	}
+
+	/* Enabling the interrupts will cause the TX FIFO empty interrupt to
+	 * fire and begin to process the command via the ISR.
+	 */
+	xgbe_i2c_enable_interrupts(pdata);
+
+	if (!wait_for_completion_timeout(&pdata->i2c_complete, HZ)) {
+		netdev_err(pdata->netdev, "i2c operation timed out\n");
+		ret = -ETIMEDOUT;
+		goto disable;
+	}
+
+	ret = state->ret;
+	if (ret) {
+		if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK)
+			ret = -ENOTCONN;
+		else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST)
+			ret = -EAGAIN;
+	}
+
+disable:
+	xgbe_i2c_disable_interrupts(pdata);
+	xgbe_i2c_disable(pdata);
+
+unlock:
+	mutex_unlock(&pdata->i2c_mutex);
+
+	return ret;
+}
+
+static void xgbe_i2c_stop(struct xgbe_prv_data *pdata)
+{
+	if (!pdata->i2c.started)
+		return;
+
+	netif_dbg(pdata, link, pdata->netdev, "stopping I2C\n");
+
+	pdata->i2c.started = 0;
+
+	xgbe_i2c_disable_interrupts(pdata);
+	xgbe_i2c_disable(pdata);
+	xgbe_i2c_clear_all_interrupts(pdata);
+
+	if (pdata->dev_irq != pdata->i2c_irq)
+		devm_free_irq(pdata->dev, pdata->i2c_irq, pdata);
+}
+
+static int xgbe_i2c_start(struct xgbe_prv_data *pdata)
+{
+	int ret;
+
+	if (pdata->i2c.started)
+		return 0;
+
+	netif_dbg(pdata, link, pdata->netdev, "starting I2C\n");
+
+	/* If we have a separate I2C irq, enable it */
+	if (pdata->dev_irq != pdata->i2c_irq) {
+		ret = devm_request_irq(pdata->dev, pdata->i2c_irq,
+				       xgbe_i2c_isr, 0, pdata->i2c_name,
+				       pdata);
+		if (ret) {
+			netdev_err(pdata->netdev, "i2c irq request failed\n");
+			return ret;
+		}
+	}
+
+	pdata->i2c.started = 1;
+
+	return 0;
+}
+
+static int xgbe_i2c_init(struct xgbe_prv_data *pdata)
+{
+	int ret;
+
+	xgbe_i2c_disable_interrupts(pdata);
+
+	ret = xgbe_i2c_disable(pdata);
+	if (ret) {
+		dev_err(pdata->dev, "failed to disable i2c master\n");
+		return ret;
+	}
+
+	xgbe_i2c_get_features(pdata);
+
+	xgbe_i2c_set_mode(pdata);
+
+	xgbe_i2c_clear_all_interrupts(pdata);
+
+	return 0;
+}
+
+void xgbe_init_function_ptrs_i2c(struct xgbe_i2c_if *i2c_if)
+{
+	i2c_if->i2c_init		= xgbe_i2c_init;
+
+	i2c_if->i2c_start		= xgbe_i2c_start;
+	i2c_if->i2c_stop		= xgbe_i2c_stop;
+
+	i2c_if->i2c_xfer		= xgbe_i2c_xfer;
+
+	i2c_if->i2c_isr			= xgbe_i2c_combined_isr;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-main.c	2017-02-12 16:03:20.000000000 -0500
@@ -116,19 +116,10 @@
 
 #include <linux/module.h>
 #include <linux/device.h>
-#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_net.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/property.h>
-#include <linux/acpi.h>
-#include <linux/mdio.h>
 
 #include "xgbe.h"
 #include "xgbe-common.h"
@@ -145,42 +136,6 @@ MODULE_PARM_DESC(debug, " Network interf
 static const u32 default_msg_level = (NETIF_MSG_LINK | NETIF_MSG_IFDOWN |
 				      NETIF_MSG_IFUP);
 
-static const u32 xgbe_serdes_blwc[] = {
-	XGBE_SPEED_1000_BLWC,
-	XGBE_SPEED_2500_BLWC,
-	XGBE_SPEED_10000_BLWC,
-};
-
-static const u32 xgbe_serdes_cdr_rate[] = {
-	XGBE_SPEED_1000_CDR,
-	XGBE_SPEED_2500_CDR,
-	XGBE_SPEED_10000_CDR,
-};
-
-static const u32 xgbe_serdes_pq_skew[] = {
-	XGBE_SPEED_1000_PQ,
-	XGBE_SPEED_2500_PQ,
-	XGBE_SPEED_10000_PQ,
-};
-
-static const u32 xgbe_serdes_tx_amp[] = {
-	XGBE_SPEED_1000_TXAMP,
-	XGBE_SPEED_2500_TXAMP,
-	XGBE_SPEED_10000_TXAMP,
-};
-
-static const u32 xgbe_serdes_dfe_tap_cfg[] = {
-	XGBE_SPEED_1000_DFE_TAP_CONFIG,
-	XGBE_SPEED_2500_DFE_TAP_CONFIG,
-	XGBE_SPEED_10000_DFE_TAP_CONFIG,
-};
-
-static const u32 xgbe_serdes_dfe_tap_ena[] = {
-	XGBE_SPEED_1000_DFE_TAP_ENABLE,
-	XGBE_SPEED_2500_DFE_TAP_ENABLE,
-	XGBE_SPEED_10000_DFE_TAP_ENABLE,
-};
-
 static void xgbe_default_config(struct xgbe_prv_data *pdata)
 {
 	DBGPR("-->xgbe_default_config\n");
@@ -206,455 +161,124 @@ static void xgbe_init_all_fptrs(struct x
 {
 	xgbe_init_function_ptrs_dev(&pdata->hw_if);
 	xgbe_init_function_ptrs_phy(&pdata->phy_if);
+	xgbe_init_function_ptrs_i2c(&pdata->i2c_if);
 	xgbe_init_function_ptrs_desc(&pdata->desc_if);
-}
-
-#ifdef CONFIG_ACPI
-static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
-{
-	struct device *dev = pdata->dev;
-	u32 property;
-	int ret;
-
-	/* Obtain the system clock setting */
-	ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property);
-	if (ret) {
-		dev_err(dev, "unable to obtain %s property\n",
-			XGBE_ACPI_DMA_FREQ);
-		return ret;
-	}
-	pdata->sysclk_rate = property;
-
-	/* Obtain the PTP clock setting */
-	ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property);
-	if (ret) {
-		dev_err(dev, "unable to obtain %s property\n",
-			XGBE_ACPI_PTP_FREQ);
-		return ret;
-	}
-	pdata->ptpclk_rate = property;
-
-	return 0;
-}
-#else   /* CONFIG_ACPI */
-static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
-{
-	return -EINVAL;
-}
-#endif  /* CONFIG_ACPI */
 
-#ifdef CONFIG_OF
-static int xgbe_of_support(struct xgbe_prv_data *pdata)
-{
-	struct device *dev = pdata->dev;
-
-	/* Obtain the system clock setting */
-	pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
-	if (IS_ERR(pdata->sysclk)) {
-		dev_err(dev, "dma devm_clk_get failed\n");
-		return PTR_ERR(pdata->sysclk);
-	}
-	pdata->sysclk_rate = clk_get_rate(pdata->sysclk);
-
-	/* Obtain the PTP clock setting */
-	pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
-	if (IS_ERR(pdata->ptpclk)) {
-		dev_err(dev, "ptp devm_clk_get failed\n");
-		return PTR_ERR(pdata->ptpclk);
-	}
-	pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk);
-
-	return 0;
-}
-
-static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
-{
-	struct device *dev = pdata->dev;
-	struct device_node *phy_node;
-	struct platform_device *phy_pdev;
-
-	phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0);
-	if (phy_node) {
-		/* Old style device tree:
-		 *   The XGBE and PHY resources are separate
-		 */
-		phy_pdev = of_find_device_by_node(phy_node);
-		of_node_put(phy_node);
-	} else {
-		/* New style device tree:
-		 *   The XGBE and PHY resources are grouped together with
-		 *   the PHY resources listed last
-		 */
-		get_device(dev);
-		phy_pdev = pdata->pdev;
-	}
-
-	return phy_pdev;
-}
-#else   /* CONFIG_OF */
-static int xgbe_of_support(struct xgbe_prv_data *pdata)
-{
-	return -EINVAL;
-}
-
-static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
-{
-	return NULL;
-}
-#endif  /* CONFIG_OF */
-
-static unsigned int xgbe_resource_count(struct platform_device *pdev,
-					unsigned int type)
-{
-	unsigned int count;
-	int i;
-
-	for (i = 0, count = 0; i < pdev->num_resources; i++) {
-		struct resource *res = &pdev->resource[i];
-
-		if (type == resource_type(res))
-			count++;
-	}
-
-	return count;
-}
-
-static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata)
-{
-	struct platform_device *phy_pdev;
-
-	if (pdata->use_acpi) {
-		get_device(pdata->dev);
-		phy_pdev = pdata->pdev;
-	} else {
-		phy_pdev = xgbe_of_get_phy_pdev(pdata);
-	}
-
-	return phy_pdev;
+	pdata->vdata->init_function_ptrs_phy_impl(&pdata->phy_if);
 }
 
-static int xgbe_probe(struct platform_device *pdev)
+struct xgbe_prv_data *xgbe_alloc_pdata(struct device *dev)
 {
 	struct xgbe_prv_data *pdata;
 	struct net_device *netdev;
-	struct device *dev = &pdev->dev, *phy_dev;
-	struct platform_device *phy_pdev;
-	struct resource *res;
-	const char *phy_mode;
-	unsigned int i, phy_memnum, phy_irqnum;
-	enum dev_dma_attr attr;
-	int ret;
-
-	DBGPR("--> xgbe_probe\n");
 
 	netdev = alloc_etherdev_mq(sizeof(struct xgbe_prv_data),
 				   XGBE_MAX_DMA_CHANNELS);
 	if (!netdev) {
-		dev_err(dev, "alloc_etherdev failed\n");
-		ret = -ENOMEM;
-		goto err_alloc;
+		dev_err(dev, "alloc_etherdev_mq failed\n");
+		return ERR_PTR(-ENOMEM);
 	}
 	SET_NETDEV_DEV(netdev, dev);
 	pdata = netdev_priv(netdev);
 	pdata->netdev = netdev;
-	pdata->pdev = pdev;
-	pdata->adev = ACPI_COMPANION(dev);
 	pdata->dev = dev;
-	platform_set_drvdata(pdev, netdev);
 
 	spin_lock_init(&pdata->lock);
 	spin_lock_init(&pdata->xpcs_lock);
 	mutex_init(&pdata->rss_mutex);
 	spin_lock_init(&pdata->tstamp_lock);
+	mutex_init(&pdata->i2c_mutex);
+	init_completion(&pdata->i2c_complete);
+	init_completion(&pdata->mdio_complete);
 
 	pdata->msg_enable = netif_msg_init(debug, default_msg_level);
 
 	set_bit(XGBE_DOWN, &pdata->dev_state);
+	set_bit(XGBE_STOPPED, &pdata->dev_state);
 
-	/* Check if we should use ACPI or DT */
-	pdata->use_acpi = dev->of_node ? 0 : 1;
-
-	phy_pdev = xgbe_get_phy_pdev(pdata);
-	if (!phy_pdev) {
-		dev_err(dev, "unable to obtain phy device\n");
-		ret = -EINVAL;
-		goto err_phydev;
-	}
-	phy_dev = &phy_pdev->dev;
-
-	if (pdev == phy_pdev) {
-		/* New style device tree or ACPI:
-		 *   The XGBE and PHY resources are grouped together with
-		 *   the PHY resources listed last
-		 */
-		phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3;
-		phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1;
-	} else {
-		/* Old style device tree:
-		 *   The XGBE and PHY resources are separate
-		 */
-		phy_memnum = 0;
-		phy_irqnum = 0;
-	}
-
-	/* Set and validate the number of descriptors for a ring */
-	BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT);
-	pdata->tx_desc_count = XGBE_TX_DESC_CNT;
-	if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) {
-		dev_err(dev, "tx descriptor count (%d) is not valid\n",
-			pdata->tx_desc_count);
-		ret = -EINVAL;
-		goto err_io;
-	}
-	BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT);
-	pdata->rx_desc_count = XGBE_RX_DESC_CNT;
-	if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) {
-		dev_err(dev, "rx descriptor count (%d) is not valid\n",
-			pdata->rx_desc_count);
-		ret = -EINVAL;
-		goto err_io;
-	}
-
-	/* Obtain the mmio areas for the device */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	pdata->xgmac_regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(pdata->xgmac_regs)) {
-		dev_err(dev, "xgmac ioremap failed\n");
-		ret = PTR_ERR(pdata->xgmac_regs);
-		goto err_io;
-	}
-	if (netif_msg_probe(pdata))
-		dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	pdata->xpcs_regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(pdata->xpcs_regs)) {
-		dev_err(dev, "xpcs ioremap failed\n");
-		ret = PTR_ERR(pdata->xpcs_regs);
-		goto err_io;
-	}
-	if (netif_msg_probe(pdata))
-		dev_dbg(dev, "xpcs_regs  = %p\n", pdata->xpcs_regs);
-
-	res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
-	pdata->rxtx_regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(pdata->rxtx_regs)) {
-		dev_err(dev, "rxtx ioremap failed\n");
-		ret = PTR_ERR(pdata->rxtx_regs);
-		goto err_io;
-	}
-	if (netif_msg_probe(pdata))
-		dev_dbg(dev, "rxtx_regs  = %p\n", pdata->rxtx_regs);
-
-	res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
-	pdata->sir0_regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(pdata->sir0_regs)) {
-		dev_err(dev, "sir0 ioremap failed\n");
-		ret = PTR_ERR(pdata->sir0_regs);
-		goto err_io;
-	}
-	if (netif_msg_probe(pdata))
-		dev_dbg(dev, "sir0_regs  = %p\n", pdata->sir0_regs);
-
-	res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
-	pdata->sir1_regs = devm_ioremap_resource(dev, res);
-	if (IS_ERR(pdata->sir1_regs)) {
-		dev_err(dev, "sir1 ioremap failed\n");
-		ret = PTR_ERR(pdata->sir1_regs);
-		goto err_io;
-	}
-	if (netif_msg_probe(pdata))
-		dev_dbg(dev, "sir1_regs  = %p\n", pdata->sir1_regs);
-
-	/* Retrieve the MAC address */
-	ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY,
-					    pdata->mac_addr,
-					    sizeof(pdata->mac_addr));
-	if (ret || !is_valid_ether_addr(pdata->mac_addr)) {
-		dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY);
-		if (!ret)
-			ret = -EINVAL;
-		goto err_io;
-	}
-
-	/* Retrieve the PHY mode - it must be "xgmii" */
-	ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY,
-					  &phy_mode);
-	if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) {
-		dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY);
-		if (!ret)
-			ret = -EINVAL;
-		goto err_io;
-	}
-	pdata->phy_mode = PHY_INTERFACE_MODE_XGMII;
-
-	/* Check for per channel interrupt support */
-	if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY))
-		pdata->per_channel_irq = 1;
+	return pdata;
+}
 
-	/* Retrieve the PHY speedset */
-	ret = device_property_read_u32(phy_dev, XGBE_SPEEDSET_PROPERTY,
-				       &pdata->speed_set);
-	if (ret) {
-		dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
-		goto err_io;
-	}
+void xgbe_free_pdata(struct xgbe_prv_data *pdata)
+{
+	struct net_device *netdev = pdata->netdev;
 
-	switch (pdata->speed_set) {
-	case XGBE_SPEEDSET_1000_10000:
-	case XGBE_SPEEDSET_2500_10000:
-		break;
-	default:
-		dev_err(dev, "invalid %s property\n", XGBE_SPEEDSET_PROPERTY);
-		ret = -EINVAL;
-		goto err_io;
-	}
+	free_netdev(netdev);
+}
 
-	/* Retrieve the PHY configuration properties */
-	if (device_property_present(phy_dev, XGBE_BLWC_PROPERTY)) {
-		ret = device_property_read_u32_array(phy_dev,
-						     XGBE_BLWC_PROPERTY,
-						     pdata->serdes_blwc,
-						     XGBE_SPEEDS);
-		if (ret) {
-			dev_err(dev, "invalid %s property\n",
-				XGBE_BLWC_PROPERTY);
-			goto err_io;
-		}
-	} else {
-		memcpy(pdata->serdes_blwc, xgbe_serdes_blwc,
-		       sizeof(pdata->serdes_blwc));
-	}
+void xgbe_set_counts(struct xgbe_prv_data *pdata)
+{
+	/* Set all the function pointers */
+	xgbe_init_all_fptrs(pdata);
 
-	if (device_property_present(phy_dev, XGBE_CDR_RATE_PROPERTY)) {
-		ret = device_property_read_u32_array(phy_dev,
-						     XGBE_CDR_RATE_PROPERTY,
-						     pdata->serdes_cdr_rate,
-						     XGBE_SPEEDS);
-		if (ret) {
-			dev_err(dev, "invalid %s property\n",
-				XGBE_CDR_RATE_PROPERTY);
-			goto err_io;
-		}
-	} else {
-		memcpy(pdata->serdes_cdr_rate, xgbe_serdes_cdr_rate,
-		       sizeof(pdata->serdes_cdr_rate));
-	}
+	/* Populate the hardware features */
+	xgbe_get_all_hw_features(pdata);
 
-	if (device_property_present(phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
-		ret = device_property_read_u32_array(phy_dev,
-						     XGBE_PQ_SKEW_PROPERTY,
-						     pdata->serdes_pq_skew,
-						     XGBE_SPEEDS);
-		if (ret) {
-			dev_err(dev, "invalid %s property\n",
-				XGBE_PQ_SKEW_PROPERTY);
-			goto err_io;
-		}
-	} else {
-		memcpy(pdata->serdes_pq_skew, xgbe_serdes_pq_skew,
-		       sizeof(pdata->serdes_pq_skew));
-	}
+	/* Set default max values if not provided */
+	if (!pdata->tx_max_channel_count)
+		pdata->tx_max_channel_count = pdata->hw_feat.tx_ch_cnt;
+	if (!pdata->rx_max_channel_count)
+		pdata->rx_max_channel_count = pdata->hw_feat.rx_ch_cnt;
 
-	if (device_property_present(phy_dev, XGBE_TX_AMP_PROPERTY)) {
-		ret = device_property_read_u32_array(phy_dev,
-						     XGBE_TX_AMP_PROPERTY,
-						     pdata->serdes_tx_amp,
-						     XGBE_SPEEDS);
-		if (ret) {
-			dev_err(dev, "invalid %s property\n",
-				XGBE_TX_AMP_PROPERTY);
-			goto err_io;
-		}
-	} else {
-		memcpy(pdata->serdes_tx_amp, xgbe_serdes_tx_amp,
-		       sizeof(pdata->serdes_tx_amp));
-	}
+	if (!pdata->tx_max_q_count)
+		pdata->tx_max_q_count = pdata->hw_feat.tx_q_cnt;
+	if (!pdata->rx_max_q_count)
+		pdata->rx_max_q_count = pdata->hw_feat.rx_q_cnt;
 
-	if (device_property_present(phy_dev, XGBE_DFE_CFG_PROPERTY)) {
-		ret = device_property_read_u32_array(phy_dev,
-						     XGBE_DFE_CFG_PROPERTY,
-						     pdata->serdes_dfe_tap_cfg,
-						     XGBE_SPEEDS);
-		if (ret) {
-			dev_err(dev, "invalid %s property\n",
-				XGBE_DFE_CFG_PROPERTY);
-			goto err_io;
-		}
-	} else {
-		memcpy(pdata->serdes_dfe_tap_cfg, xgbe_serdes_dfe_tap_cfg,
-		       sizeof(pdata->serdes_dfe_tap_cfg));
-	}
+	/* Calculate the number of Tx and Rx rings to be created
+	 *  -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
+	 *   the number of Tx queues to the number of Tx channels
+	 *   enabled
+	 *  -Rx (DMA) Channels do not map 1-to-1 so use the actual
+	 *   number of Rx queues or maximum allowed
+	 */
+	pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
+				     pdata->hw_feat.tx_ch_cnt);
+	pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
+				     pdata->tx_max_channel_count);
+	pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
+				     pdata->tx_max_q_count);
 
-	if (device_property_present(phy_dev, XGBE_DFE_ENA_PROPERTY)) {
-		ret = device_property_read_u32_array(phy_dev,
-						     XGBE_DFE_ENA_PROPERTY,
-						     pdata->serdes_dfe_tap_ena,
-						     XGBE_SPEEDS);
-		if (ret) {
-			dev_err(dev, "invalid %s property\n",
-				XGBE_DFE_ENA_PROPERTY);
-			goto err_io;
-		}
-	} else {
-		memcpy(pdata->serdes_dfe_tap_ena, xgbe_serdes_dfe_tap_ena,
-		       sizeof(pdata->serdes_dfe_tap_ena));
-	}
+	pdata->tx_q_count = pdata->tx_ring_count;
 
-	/* Obtain device settings unique to ACPI/OF */
-	if (pdata->use_acpi)
-		ret = xgbe_acpi_support(pdata);
-	else
-		ret = xgbe_of_support(pdata);
-	if (ret)
-		goto err_io;
+	pdata->rx_ring_count = min_t(unsigned int, num_online_cpus(),
+				     pdata->hw_feat.rx_ch_cnt);
+	pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count,
+				     pdata->rx_max_channel_count);
 
-	/* Set the DMA coherency values */
-	attr = device_get_dma_attr(dev);
-	if (attr == DEV_DMA_NOT_SUPPORTED) {
-		dev_err(dev, "DMA is not supported");
-		goto err_io;
-	}
-	pdata->coherent = (attr == DEV_DMA_COHERENT);
-	if (pdata->coherent) {
-		pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
-		pdata->arcache = XGBE_DMA_OS_ARCACHE;
-		pdata->awcache = XGBE_DMA_OS_AWCACHE;
-	} else {
-		pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
-		pdata->arcache = XGBE_DMA_SYS_ARCACHE;
-		pdata->awcache = XGBE_DMA_SYS_AWCACHE;
-	}
+	pdata->rx_q_count = min_t(unsigned int, pdata->hw_feat.rx_q_cnt,
+				  pdata->rx_max_q_count);
 
-	/* Get the device interrupt */
-	ret = platform_get_irq(pdev, 0);
-	if (ret < 0) {
-		dev_err(dev, "platform_get_irq 0 failed\n");
-		goto err_io;
+	if (netif_msg_probe(pdata)) {
+		dev_dbg(pdata->dev, "TX/RX DMA channel count = %u/%u\n",
+			pdata->tx_ring_count, pdata->rx_ring_count);
+		dev_dbg(pdata->dev, "TX/RX hardware queue count = %u/%u\n",
+			pdata->tx_q_count, pdata->rx_q_count);
 	}
-	pdata->dev_irq = ret;
+}
 
-	/* Get the auto-negotiation interrupt */
-	ret = platform_get_irq(phy_pdev, phy_irqnum++);
-	if (ret < 0) {
-		dev_err(dev, "platform_get_irq phy 0 failed\n");
-		goto err_io;
-	}
-	pdata->an_irq = ret;
+int xgbe_config_netdev(struct xgbe_prv_data *pdata)
+{
+	struct net_device *netdev = pdata->netdev;
+	struct device *dev = pdata->dev;
+	unsigned int i;
+	int ret;
 
 	netdev->irq = pdata->dev_irq;
 	netdev->base_addr = (unsigned long)pdata->xgmac_regs;
 	memcpy(netdev->dev_addr, pdata->mac_addr, netdev->addr_len);
 
-	/* Set all the function pointers */
-	xgbe_init_all_fptrs(pdata);
+	/* Initialize ECC timestamps */
+	pdata->tx_sec_period = jiffies;
+	pdata->tx_ded_period = jiffies;
+	pdata->rx_sec_period = jiffies;
+	pdata->rx_ded_period = jiffies;
+	pdata->desc_sec_period = jiffies;
+	pdata->desc_ded_period = jiffies;
 
 	/* Issue software reset to device */
 	pdata->hw_if.exit(pdata);
 
-	/* Populate the hardware features */
-	xgbe_get_all_hw_features(pdata);
-
 	/* Set default configuration data */
 	xgbe_default_config(pdata);
 
@@ -663,33 +287,46 @@ static int xgbe_probe(struct platform_de
 					DMA_BIT_MASK(pdata->hw_feat.dma_width));
 	if (ret) {
 		dev_err(dev, "dma_set_mask_and_coherent failed\n");
-		goto err_io;
+		return ret;
 	}
 
-	/* Calculate the number of Tx and Rx rings to be created
-	 *  -Tx (DMA) Channels map 1-to-1 to Tx Queues so set
-	 *   the number of Tx queues to the number of Tx channels
-	 *   enabled
-	 *  -Rx (DMA) Channels do not map 1-to-1 so use the actual
-	 *   number of Rx queues
-	 */
-	pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
-				     pdata->hw_feat.tx_ch_cnt);
-	pdata->tx_q_count = pdata->tx_ring_count;
+	/* Set default max values if not provided */
+	if (!pdata->tx_max_fifo_size)
+		pdata->tx_max_fifo_size = pdata->hw_feat.tx_fifo_size;
+	if (!pdata->rx_max_fifo_size)
+		pdata->rx_max_fifo_size = pdata->hw_feat.rx_fifo_size;
+
+	/* Set and validate the number of descriptors for a ring */
+	BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_TX_DESC_CNT);
+	pdata->tx_desc_count = XGBE_TX_DESC_CNT;
+
+	BUILD_BUG_ON_NOT_POWER_OF_2(XGBE_RX_DESC_CNT);
+	pdata->rx_desc_count = XGBE_RX_DESC_CNT;
+
+	/* Adjust the number of queues based on interrupts assigned */
+	if (pdata->channel_irq_count) {
+		pdata->tx_ring_count = min_t(unsigned int, pdata->tx_ring_count,
+					     pdata->channel_irq_count);
+		pdata->rx_ring_count = min_t(unsigned int, pdata->rx_ring_count,
+					     pdata->channel_irq_count);
+
+		if (netif_msg_probe(pdata))
+			dev_dbg(pdata->dev,
+				"adjusted TX/RX DMA channel count = %u/%u\n",
+				pdata->tx_ring_count, pdata->rx_ring_count);
+	}
+
+	/* Set the number of queues */
 	ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
 	if (ret) {
 		dev_err(dev, "error setting real tx queue count\n");
-		goto err_io;
+		return ret;
 	}
 
-	pdata->rx_ring_count = min_t(unsigned int,
-				     netif_get_num_default_rss_queues(),
-				     pdata->hw_feat.rx_ch_cnt);
-	pdata->rx_q_count = pdata->hw_feat.rx_q_cnt;
 	ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count);
 	if (ret) {
 		dev_err(dev, "error setting real rx queue count\n");
-		goto err_io;
+		return ret;
 	}
 
 	/* Initialize RSS hash key and lookup table */
@@ -704,7 +341,9 @@ static int xgbe_probe(struct platform_de
 	XGMAC_SET_BITS(pdata->rss_options, MAC_RSSCR, UDP4TE, 1);
 
 	/* Call MDIO/PHY initialization routine */
-	pdata->phy_if.phy_init(pdata);
+	ret = pdata->phy_if.phy_init(pdata);
+	if (ret)
+		return ret;
 
 	/* Set device operations */
 	netdev->netdev_ops = xgbe_get_netdev_ops();
@@ -738,6 +377,8 @@ static int xgbe_probe(struct platform_de
 	pdata->netdev_features = netdev->features;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
+	netdev->min_mtu = 0;
+	netdev->max_mtu = XGMAC_JUMBO_PACKET_MTU;
 
 	/* Use default watchdog timeout */
 	netdev->watchdog_timeo = 0;
@@ -749,13 +390,21 @@ static int xgbe_probe(struct platform_de
 	ret = register_netdev(netdev);
 	if (ret) {
 		dev_err(dev, "net device registration failed\n");
-		goto err_io;
+		return ret;
 	}
 
 	/* Create the PHY/ANEG name based on netdev name */
 	snprintf(pdata->an_name, sizeof(pdata->an_name) - 1, "%s-pcs",
 		 netdev_name(netdev));
 
+	/* Create the ECC name based on netdev name */
+	snprintf(pdata->ecc_name, sizeof(pdata->ecc_name) - 1, "%s-ecc",
+		 netdev_name(netdev));
+
+	/* Create the I2C name based on netdev name */
+	snprintf(pdata->i2c_name, sizeof(pdata->i2c_name) - 1, "%s-i2c",
+		 netdev_name(netdev));
+
 	/* Create workqueues */
 	pdata->dev_workqueue =
 		create_singlethread_workqueue(netdev_name(netdev));
@@ -773,15 +422,15 @@ static int xgbe_probe(struct platform_de
 		goto err_wq;
 	}
 
-	xgbe_ptp_register(pdata);
+	if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
+		xgbe_ptp_register(pdata);
 
 	xgbe_debugfs_init(pdata);
 
-	platform_device_put(phy_pdev);
-
-	netdev_notice(netdev, "net device enabled\n");
-
-	DBGPR("<-- xgbe_probe\n");
+	netif_dbg(pdata, drv, pdata->netdev, "%u Tx software queues\n",
+		  pdata->tx_ring_count);
+	netif_dbg(pdata, drv, pdata->netdev, "%u Rx software queues\n",
+		  pdata->rx_ring_count);
 
 	return 0;
 
@@ -791,28 +440,19 @@ err_wq:
 err_netdev:
 	unregister_netdev(netdev);
 
-err_io:
-	platform_device_put(phy_pdev);
-
-err_phydev:
-	free_netdev(netdev);
-
-err_alloc:
-	dev_notice(dev, "net device not enabled\n");
-
 	return ret;
 }
 
-static int xgbe_remove(struct platform_device *pdev)
+void xgbe_deconfig_netdev(struct xgbe_prv_data *pdata)
 {
-	struct net_device *netdev = platform_get_drvdata(pdev);
-	struct xgbe_prv_data *pdata = netdev_priv(netdev);
-
-	DBGPR("-->xgbe_remove\n");
+	struct net_device *netdev = pdata->netdev;
 
 	xgbe_debugfs_exit(pdata);
 
-	xgbe_ptp_unregister(pdata);
+	if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
+		xgbe_ptp_unregister(pdata);
+
+	pdata->phy_if.phy_exit(pdata);
 
 	flush_workqueue(pdata->an_workqueue);
 	destroy_workqueue(pdata->an_workqueue);
@@ -821,94 +461,29 @@ static int xgbe_remove(struct platform_d
 	destroy_workqueue(pdata->dev_workqueue);
 
 	unregister_netdev(netdev);
-
-	free_netdev(netdev);
-
-	DBGPR("<--xgbe_remove\n");
-
-	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int xgbe_suspend(struct device *dev)
+static int __init xgbe_mod_init(void)
 {
-	struct net_device *netdev = dev_get_drvdata(dev);
-	struct xgbe_prv_data *pdata = netdev_priv(netdev);
-	int ret = 0;
-
-	DBGPR("-->xgbe_suspend\n");
-
-	if (netif_running(netdev))
-		ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
+	int ret;
 
-	pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-	pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+	ret = xgbe_platform_init();
+	if (ret)
+		return ret;
 
-	DBGPR("<--xgbe_suspend\n");
+	ret = xgbe_pci_init();
+	if (ret)
+		return ret;
 
-	return ret;
+	return 0;
 }
 
-static int xgbe_resume(struct device *dev)
+static void __exit xgbe_mod_exit(void)
 {
-	struct net_device *netdev = dev_get_drvdata(dev);
-	struct xgbe_prv_data *pdata = netdev_priv(netdev);
-	int ret = 0;
-
-	DBGPR("-->xgbe_resume\n");
-
-	pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
-
-	if (netif_running(netdev)) {
-		ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
-
-		/* Schedule a restart in case the link or phy state changed
-		 * while we were powered down.
-		 */
-		schedule_work(&pdata->restart_work);
-	}
-
-	DBGPR("<--xgbe_resume\n");
+	xgbe_pci_exit();
 
-	return ret;
+	xgbe_platform_exit();
 }
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_ACPI
-static const struct acpi_device_id xgbe_acpi_match[] = {
-	{ "AMDI8001", 0 },
-	{},
-};
-
-MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match);
-#endif
-
-#ifdef CONFIG_OF
-static const struct of_device_id xgbe_of_match[] = {
-	{ .compatible = "amd,xgbe-seattle-v1a", },
-	{},
-};
-
-MODULE_DEVICE_TABLE(of, xgbe_of_match);
-#endif
-
-static SIMPLE_DEV_PM_OPS(xgbe_pm_ops, xgbe_suspend, xgbe_resume);
-
-static struct platform_driver xgbe_driver = {
-	.driver = {
-		.name = "amd-xgbe",
-#ifdef CONFIG_ACPI
-		.acpi_match_table = xgbe_acpi_match,
-#endif
-#ifdef CONFIG_OF
-		.of_match_table = xgbe_of_match,
-#endif
-		.pm = &xgbe_pm_ops,
-	},
-	.probe = xgbe_probe,
-	.remove = xgbe_remove,
-};
 
-module_platform_driver(xgbe_driver);
+module_init(xgbe_mod_init);
+module_exit(xgbe_mod_exit);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c	2017-02-12 16:03:20.000000000 -0500
@@ -125,303 +125,284 @@
 #include "xgbe.h"
 #include "xgbe-common.h"
 
-static void xgbe_an_enable_kr_training(struct xgbe_prv_data *pdata)
+static void xgbe_an37_clear_interrupts(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg;
-
-	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+	int reg;
 
-	reg |= XGBE_KR_TRAINING_ENABLE;
-	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
+	reg &= ~XGBE_AN_CL37_INT_MASK;
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
 }
 
-static void xgbe_an_disable_kr_training(struct xgbe_prv_data *pdata)
+static void xgbe_an37_disable_interrupts(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg;
+	int reg;
 
-	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+	reg &= ~XGBE_AN_CL37_INT_MASK;
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
 
-	reg &= ~XGBE_KR_TRAINING_ENABLE;
-	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
+	reg &= ~XGBE_PCS_CL37_BP;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
 }
 
-static void xgbe_pcs_power_cycle(struct xgbe_prv_data *pdata)
+static void xgbe_an37_enable_interrupts(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg;
-
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-
-	reg |= MDIO_CTRL1_LPOWER;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+	int reg;
 
-	usleep_range(75, 100);
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
+	reg |= XGBE_PCS_CL37_BP;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
 
-	reg &= ~MDIO_CTRL1_LPOWER;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+	reg |= XGBE_AN_CL37_INT_MASK;
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
 }
 
-static void xgbe_serdes_start_ratechange(struct xgbe_prv_data *pdata)
+static void xgbe_an73_clear_interrupts(struct xgbe_prv_data *pdata)
 {
-	/* Assert Rx and Tx ratechange */
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
+	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
 }
 
-static void xgbe_serdes_complete_ratechange(struct xgbe_prv_data *pdata)
+static void xgbe_an73_disable_interrupts(struct xgbe_prv_data *pdata)
 {
-	unsigned int wait;
-	u16 status;
-
-	/* Release Rx and Tx ratechange */
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
+	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+}
 
-	/* Wait for Rx and Tx ready */
-	wait = XGBE_RATECHANGE_COUNT;
-	while (wait--) {
-		usleep_range(50, 75);
+static void xgbe_an73_enable_interrupts(struct xgbe_prv_data *pdata)
+{
+	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_CL73_INT_MASK);
+}
 
-		status = XSIR0_IOREAD(pdata, SIR0_STATUS);
-		if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
-		    XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
-			goto rx_reset;
+static void xgbe_an_enable_interrupts(struct xgbe_prv_data *pdata)
+{
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL73:
+	case XGBE_AN_MODE_CL73_REDRV:
+		xgbe_an73_enable_interrupts(pdata);
+		break;
+	case XGBE_AN_MODE_CL37:
+	case XGBE_AN_MODE_CL37_SGMII:
+		xgbe_an37_enable_interrupts(pdata);
+		break;
+	default:
+		break;
 	}
+}
 
-	netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
-		  status);
-
-rx_reset:
-	/* Perform Rx reset for the DFE changes */
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
+static void xgbe_an_clear_interrupts_all(struct xgbe_prv_data *pdata)
+{
+	xgbe_an73_clear_interrupts(pdata);
+	xgbe_an37_clear_interrupts(pdata);
 }
 
-static void xgbe_xgmii_mode(struct xgbe_prv_data *pdata)
+static void xgbe_an73_enable_kr_training(struct xgbe_prv_data *pdata)
 {
 	unsigned int reg;
 
-	/* Enable KR training */
-	xgbe_an_enable_kr_training(pdata);
-
-	/* Set MAC to 10G speed */
-	pdata->hw_if.set_xgmii_speed(pdata);
-
-	/* Set PCS to KR/10G speed */
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-	reg &= ~MDIO_PCS_CTRL2_TYPE;
-	reg |= MDIO_PCS_CTRL2_10GBR;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
 
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-	reg &= ~MDIO_CTRL1_SPEEDSEL;
-	reg |= MDIO_CTRL1_SPEED10G;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+	reg |= XGBE_KR_TRAINING_ENABLE;
+	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+}
 
-	xgbe_pcs_power_cycle(pdata);
+static void xgbe_an73_disable_kr_training(struct xgbe_prv_data *pdata)
+{
+	unsigned int reg;
 
-	/* Set SerDes to 10G speed */
-	xgbe_serdes_start_ratechange(pdata);
+	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
 
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
+	reg &= ~XGBE_KR_TRAINING_ENABLE;
+	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+}
 
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-			   pdata->serdes_cdr_rate[XGBE_SPEED_10000]);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-			   pdata->serdes_tx_amp[XGBE_SPEED_10000]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-			   pdata->serdes_blwc[XGBE_SPEED_10000]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-			   pdata->serdes_pq_skew[XGBE_SPEED_10000]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-			   pdata->serdes_dfe_tap_cfg[XGBE_SPEED_10000]);
-	XRXTX_IOWRITE(pdata, RXTX_REG22,
-		      pdata->serdes_dfe_tap_ena[XGBE_SPEED_10000]);
+static void xgbe_kr_mode(struct xgbe_prv_data *pdata)
+{
+	/* Enable KR training */
+	xgbe_an73_enable_kr_training(pdata);
 
-	xgbe_serdes_complete_ratechange(pdata);
+	/* Set MAC to 10G speed */
+	pdata->hw_if.set_speed(pdata, SPEED_10000);
 
-	netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KR);
 }
 
-static void xgbe_gmii_2500_mode(struct xgbe_prv_data *pdata)
+static void xgbe_kx_2500_mode(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg;
-
 	/* Disable KR training */
-	xgbe_an_disable_kr_training(pdata);
+	xgbe_an73_disable_kr_training(pdata);
 
 	/* Set MAC to 2.5G speed */
-	pdata->hw_if.set_gmii_2500_speed(pdata);
+	pdata->hw_if.set_speed(pdata, SPEED_2500);
 
-	/* Set PCS to KX/1G speed */
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-	reg &= ~MDIO_PCS_CTRL2_TYPE;
-	reg |= MDIO_PCS_CTRL2_10GBX;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_2500);
+}
 
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-	reg &= ~MDIO_CTRL1_SPEEDSEL;
-	reg |= MDIO_CTRL1_SPEED1G;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+static void xgbe_kx_1000_mode(struct xgbe_prv_data *pdata)
+{
+	/* Disable KR training */
+	xgbe_an73_disable_kr_training(pdata);
 
-	xgbe_pcs_power_cycle(pdata);
+	/* Set MAC to 1G speed */
+	pdata->hw_if.set_speed(pdata, SPEED_1000);
 
-	/* Set SerDes to 2.5G speed */
-	xgbe_serdes_start_ratechange(pdata);
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_KX_1000);
+}
 
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
+static void xgbe_sfi_mode(struct xgbe_prv_data *pdata)
+{
+	/* If a KR re-driver is present, change to KR mode instead */
+	if (pdata->kr_redrv)
+		return xgbe_kr_mode(pdata);
 
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-			   pdata->serdes_cdr_rate[XGBE_SPEED_2500]);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-			   pdata->serdes_tx_amp[XGBE_SPEED_2500]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-			   pdata->serdes_blwc[XGBE_SPEED_2500]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-			   pdata->serdes_pq_skew[XGBE_SPEED_2500]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-			   pdata->serdes_dfe_tap_cfg[XGBE_SPEED_2500]);
-	XRXTX_IOWRITE(pdata, RXTX_REG22,
-		      pdata->serdes_dfe_tap_ena[XGBE_SPEED_2500]);
+	/* Disable KR training */
+	xgbe_an73_disable_kr_training(pdata);
 
-	xgbe_serdes_complete_ratechange(pdata);
+	/* Set MAC to 10G speed */
+	pdata->hw_if.set_speed(pdata, SPEED_10000);
 
-	netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SFI);
 }
 
-static void xgbe_gmii_mode(struct xgbe_prv_data *pdata)
+static void xgbe_x_mode(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg;
-
 	/* Disable KR training */
-	xgbe_an_disable_kr_training(pdata);
+	xgbe_an73_disable_kr_training(pdata);
 
 	/* Set MAC to 1G speed */
-	pdata->hw_if.set_gmii_speed(pdata);
-
-	/* Set PCS to KX/1G speed */
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-	reg &= ~MDIO_PCS_CTRL2_TYPE;
-	reg |= MDIO_PCS_CTRL2_10GBX;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+	pdata->hw_if.set_speed(pdata, SPEED_1000);
 
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-	reg &= ~MDIO_CTRL1_SPEEDSEL;
-	reg |= MDIO_CTRL1_SPEED1G;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_X);
+}
 
-	xgbe_pcs_power_cycle(pdata);
+static void xgbe_sgmii_1000_mode(struct xgbe_prv_data *pdata)
+{
+	/* Disable KR training */
+	xgbe_an73_disable_kr_training(pdata);
 
-	/* Set SerDes to 1G speed */
-	xgbe_serdes_start_ratechange(pdata);
+	/* Set MAC to 1G speed */
+	pdata->hw_if.set_speed(pdata, SPEED_1000);
 
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_1000);
+}
 
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
-			   pdata->serdes_cdr_rate[XGBE_SPEED_1000]);
-	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
-			   pdata->serdes_tx_amp[XGBE_SPEED_1000]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
-			   pdata->serdes_blwc[XGBE_SPEED_1000]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
-			   pdata->serdes_pq_skew[XGBE_SPEED_1000]);
-	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
-			   pdata->serdes_dfe_tap_cfg[XGBE_SPEED_1000]);
-	XRXTX_IOWRITE(pdata, RXTX_REG22,
-		      pdata->serdes_dfe_tap_ena[XGBE_SPEED_1000]);
+static void xgbe_sgmii_100_mode(struct xgbe_prv_data *pdata)
+{
+	/* Disable KR training */
+	xgbe_an73_disable_kr_training(pdata);
 
-	xgbe_serdes_complete_ratechange(pdata);
+	/* Set MAC to 1G speed */
+	pdata->hw_if.set_speed(pdata, SPEED_1000);
 
-	netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
+	/* Call PHY implementation support to complete rate change */
+	pdata->phy_if.phy_impl.set_mode(pdata, XGBE_MODE_SGMII_100);
 }
 
-static void xgbe_cur_mode(struct xgbe_prv_data *pdata,
-			  enum xgbe_mode *mode)
+static enum xgbe_mode xgbe_cur_mode(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg;
-
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
-	if ((reg & MDIO_PCS_CTRL2_TYPE) == MDIO_PCS_CTRL2_10GBR)
-		*mode = XGBE_MODE_KR;
-	else
-		*mode = XGBE_MODE_KX;
+	return pdata->phy_if.phy_impl.cur_mode(pdata);
 }
 
 static bool xgbe_in_kr_mode(struct xgbe_prv_data *pdata)
 {
-	enum xgbe_mode mode;
-
-	xgbe_cur_mode(pdata, &mode);
+	return (xgbe_cur_mode(pdata) == XGBE_MODE_KR);
+}
 
-	return (mode == XGBE_MODE_KR);
+static void xgbe_change_mode(struct xgbe_prv_data *pdata,
+			     enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_KX_1000:
+		xgbe_kx_1000_mode(pdata);
+		break;
+	case XGBE_MODE_KX_2500:
+		xgbe_kx_2500_mode(pdata);
+		break;
+	case XGBE_MODE_KR:
+		xgbe_kr_mode(pdata);
+		break;
+	case XGBE_MODE_SGMII_100:
+		xgbe_sgmii_100_mode(pdata);
+		break;
+	case XGBE_MODE_SGMII_1000:
+		xgbe_sgmii_1000_mode(pdata);
+		break;
+	case XGBE_MODE_X:
+		xgbe_x_mode(pdata);
+		break;
+	case XGBE_MODE_SFI:
+		xgbe_sfi_mode(pdata);
+		break;
+	case XGBE_MODE_UNKNOWN:
+		break;
+	default:
+		netif_dbg(pdata, link, pdata->netdev,
+			  "invalid operation mode requested (%u)\n", mode);
+	}
 }
 
 static void xgbe_switch_mode(struct xgbe_prv_data *pdata)
 {
-	/* If we are in KR switch to KX, and vice-versa */
-	if (xgbe_in_kr_mode(pdata)) {
-		if (pdata->speed_set == XGBE_SPEEDSET_1000_10000)
-			xgbe_gmii_mode(pdata);
-		else
-			xgbe_gmii_2500_mode(pdata);
-	} else {
-		xgbe_xgmii_mode(pdata);
-	}
+	xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata));
 }
 
 static void xgbe_set_mode(struct xgbe_prv_data *pdata,
 			  enum xgbe_mode mode)
 {
-	enum xgbe_mode cur_mode;
+	if (mode == xgbe_cur_mode(pdata))
+		return;
 
-	xgbe_cur_mode(pdata, &cur_mode);
-	if (mode != cur_mode)
-		xgbe_switch_mode(pdata);
+	xgbe_change_mode(pdata, mode);
 }
 
-static bool xgbe_use_xgmii_mode(struct xgbe_prv_data *pdata)
+static bool xgbe_use_mode(struct xgbe_prv_data *pdata,
+			  enum xgbe_mode mode)
 {
-	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
-		if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
-			return true;
-	} else {
-		if (pdata->phy.speed == SPEED_10000)
-			return true;
-	}
+	return pdata->phy_if.phy_impl.use_mode(pdata, mode);
+}
 
-	return false;
+static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable,
+			  bool restart)
+{
+	unsigned int reg;
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_CTRL1);
+	reg &= ~MDIO_VEND2_CTRL1_AN_ENABLE;
+
+	if (enable)
+		reg |= MDIO_VEND2_CTRL1_AN_ENABLE;
+
+	if (restart)
+		reg |= MDIO_VEND2_CTRL1_AN_RESTART;
+
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
 }
 
-static bool xgbe_use_gmii_2500_mode(struct xgbe_prv_data *pdata)
+static void xgbe_an37_restart(struct xgbe_prv_data *pdata)
 {
-	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
-		if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
-			return true;
-	} else {
-		if (pdata->phy.speed == SPEED_2500)
-			return true;
-	}
+	xgbe_an37_enable_interrupts(pdata);
+	xgbe_an37_set(pdata, true, true);
 
-	return false;
+	netif_dbg(pdata, link, pdata->netdev, "CL37 AN enabled/restarted\n");
 }
 
-static bool xgbe_use_gmii_mode(struct xgbe_prv_data *pdata)
+static void xgbe_an37_disable(struct xgbe_prv_data *pdata)
 {
-	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
-		if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
-			return true;
-	} else {
-		if (pdata->phy.speed == SPEED_1000)
-			return true;
-	}
+	xgbe_an37_set(pdata, false, false);
+	xgbe_an37_disable_interrupts(pdata);
 
-	return false;
+	netif_dbg(pdata, link, pdata->netdev, "CL37 AN disabled\n");
 }
 
-static void xgbe_set_an(struct xgbe_prv_data *pdata, bool enable, bool restart)
+static void xgbe_an73_set(struct xgbe_prv_data *pdata, bool enable,
+			  bool restart)
 {
 	unsigned int reg;
 
@@ -437,22 +418,62 @@ static void xgbe_set_an(struct xgbe_prv_
 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg);
 }
 
-static void xgbe_restart_an(struct xgbe_prv_data *pdata)
+static void xgbe_an73_restart(struct xgbe_prv_data *pdata)
 {
-	xgbe_set_an(pdata, true, true);
+	xgbe_an73_enable_interrupts(pdata);
+	xgbe_an73_set(pdata, true, true);
 
-	netif_dbg(pdata, link, pdata->netdev, "AN enabled/restarted\n");
+	netif_dbg(pdata, link, pdata->netdev, "CL73 AN enabled/restarted\n");
 }
 
-static void xgbe_disable_an(struct xgbe_prv_data *pdata)
+static void xgbe_an73_disable(struct xgbe_prv_data *pdata)
 {
-	xgbe_set_an(pdata, false, false);
+	xgbe_an73_set(pdata, false, false);
+	xgbe_an73_disable_interrupts(pdata);
 
-	netif_dbg(pdata, link, pdata->netdev, "AN disabled\n");
+	netif_dbg(pdata, link, pdata->netdev, "CL73 AN disabled\n");
 }
 
-static enum xgbe_an xgbe_an_tx_training(struct xgbe_prv_data *pdata,
-					enum xgbe_rx *state)
+static void xgbe_an_restart(struct xgbe_prv_data *pdata)
+{
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL73:
+	case XGBE_AN_MODE_CL73_REDRV:
+		xgbe_an73_restart(pdata);
+		break;
+	case XGBE_AN_MODE_CL37:
+	case XGBE_AN_MODE_CL37_SGMII:
+		xgbe_an37_restart(pdata);
+		break;
+	default:
+		break;
+	}
+}
+
+static void xgbe_an_disable(struct xgbe_prv_data *pdata)
+{
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL73:
+	case XGBE_AN_MODE_CL73_REDRV:
+		xgbe_an73_disable(pdata);
+		break;
+	case XGBE_AN_MODE_CL37:
+	case XGBE_AN_MODE_CL37_SGMII:
+		xgbe_an37_disable(pdata);
+		break;
+	default:
+		break;
+	}
+}
+
+static void xgbe_an_disable_all(struct xgbe_prv_data *pdata)
+{
+	xgbe_an73_disable(pdata);
+	xgbe_an37_disable(pdata);
+}
+
+static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
+					  enum xgbe_rx *state)
 {
 	unsigned int ad_reg, lp_reg, reg;
 
@@ -476,13 +497,15 @@ static enum xgbe_an xgbe_an_tx_training(
 	/* Start KR training */
 	reg = XMDIO_READ(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL);
 	if (reg & XGBE_KR_TRAINING_ENABLE) {
-		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
+		if (pdata->phy_if.phy_impl.kr_training_pre)
+			pdata->phy_if.phy_impl.kr_training_pre(pdata);
 
 		reg |= XGBE_KR_TRAINING_START;
 		XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL,
 			    reg);
 
-		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
+		if (pdata->phy_if.phy_impl.kr_training_post)
+			pdata->phy_if.phy_impl.kr_training_post(pdata);
 
 		netif_dbg(pdata, link, pdata->netdev,
 			  "KR training initiated\n");
@@ -491,8 +514,8 @@ static enum xgbe_an xgbe_an_tx_training(
 	return XGBE_AN_PAGE_RECEIVED;
 }
 
-static enum xgbe_an xgbe_an_tx_xnp(struct xgbe_prv_data *pdata,
-				   enum xgbe_rx *state)
+static enum xgbe_an xgbe_an73_tx_xnp(struct xgbe_prv_data *pdata,
+				     enum xgbe_rx *state)
 {
 	u16 msg;
 
@@ -508,8 +531,8 @@ static enum xgbe_an xgbe_an_tx_xnp(struc
 	return XGBE_AN_PAGE_RECEIVED;
 }
 
-static enum xgbe_an xgbe_an_rx_bpa(struct xgbe_prv_data *pdata,
-				   enum xgbe_rx *state)
+static enum xgbe_an xgbe_an73_rx_bpa(struct xgbe_prv_data *pdata,
+				     enum xgbe_rx *state)
 {
 	unsigned int link_support;
 	unsigned int reg, ad_reg, lp_reg;
@@ -528,12 +551,12 @@ static enum xgbe_an xgbe_an_rx_bpa(struc
 
 	return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
 		(lp_reg & XGBE_XNP_NP_EXCHANGE))
-	       ? xgbe_an_tx_xnp(pdata, state)
-	       : xgbe_an_tx_training(pdata, state);
+	       ? xgbe_an73_tx_xnp(pdata, state)
+	       : xgbe_an73_tx_training(pdata, state);
 }
 
-static enum xgbe_an xgbe_an_rx_xnp(struct xgbe_prv_data *pdata,
-				   enum xgbe_rx *state)
+static enum xgbe_an xgbe_an73_rx_xnp(struct xgbe_prv_data *pdata,
+				     enum xgbe_rx *state)
 {
 	unsigned int ad_reg, lp_reg;
 
@@ -543,11 +566,11 @@ static enum xgbe_an xgbe_an_rx_xnp(struc
 
 	return ((ad_reg & XGBE_XNP_NP_EXCHANGE) ||
 		(lp_reg & XGBE_XNP_NP_EXCHANGE))
-	       ? xgbe_an_tx_xnp(pdata, state)
-	       : xgbe_an_tx_training(pdata, state);
+	       ? xgbe_an73_tx_xnp(pdata, state)
+	       : xgbe_an73_tx_training(pdata, state);
 }
 
-static enum xgbe_an xgbe_an_page_received(struct xgbe_prv_data *pdata)
+static enum xgbe_an xgbe_an73_page_received(struct xgbe_prv_data *pdata)
 {
 	enum xgbe_rx *state;
 	unsigned long an_timeout;
@@ -566,20 +589,20 @@ static enum xgbe_an xgbe_an_page_receive
 			pdata->an_start = jiffies;
 
 			netif_dbg(pdata, link, pdata->netdev,
-				  "AN timed out, resetting state\n");
+				  "CL73 AN timed out, resetting state\n");
 		}
 	}
 
 	state = xgbe_in_kr_mode(pdata) ? &pdata->kr_state
-					   : &pdata->kx_state;
+				       : &pdata->kx_state;
 
 	switch (*state) {
 	case XGBE_RX_BPA:
-		ret = xgbe_an_rx_bpa(pdata, state);
+		ret = xgbe_an73_rx_bpa(pdata, state);
 		break;
 
 	case XGBE_RX_XNP:
-		ret = xgbe_an_rx_xnp(pdata, state);
+		ret = xgbe_an73_rx_xnp(pdata, state);
 		break;
 
 	default:
@@ -589,7 +612,7 @@ static enum xgbe_an xgbe_an_page_receive
 	return ret;
 }
 
-static enum xgbe_an xgbe_an_incompat_link(struct xgbe_prv_data *pdata)
+static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
 {
 	/* Be sure we aren't looping trying to negotiate */
 	if (xgbe_in_kr_mode(pdata)) {
@@ -611,23 +634,43 @@ static enum xgbe_an xgbe_an_incompat_lin
 			return XGBE_AN_NO_LINK;
 	}
 
-	xgbe_disable_an(pdata);
+	xgbe_an73_disable(pdata);
 
 	xgbe_switch_mode(pdata);
 
-	xgbe_restart_an(pdata);
+	xgbe_an73_restart(pdata);
 
 	return XGBE_AN_INCOMPAT_LINK;
 }
 
-static irqreturn_t xgbe_an_isr(int irq, void *data)
+static void xgbe_an37_isr(struct xgbe_prv_data *pdata)
 {
-	struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+	unsigned int reg;
 
-	netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
+	/* Disable AN interrupts */
+	xgbe_an37_disable_interrupts(pdata);
 
+	/* Save the interrupt(s) that fired */
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
+	pdata->an_int = reg & XGBE_AN_CL37_INT_MASK;
+	pdata->an_status = reg & ~XGBE_AN_CL37_INT_MASK;
+
+	if (pdata->an_int) {
+		/* Clear the interrupt(s) that fired and process them */
+		reg &= ~XGBE_AN_CL37_INT_MASK;
+		XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
+
+		queue_work(pdata->an_workqueue, &pdata->an_irq_work);
+	} else {
+		/* Enable AN interrupts */
+		xgbe_an37_enable_interrupts(pdata);
+	}
+}
+
+static void xgbe_an73_isr(struct xgbe_prv_data *pdata)
+{
 	/* Disable AN interrupts */
-	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+	xgbe_an73_disable_interrupts(pdata);
 
 	/* Save the interrupt(s) that fired */
 	pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
@@ -639,13 +682,37 @@ static irqreturn_t xgbe_an_isr(int irq,
 		queue_work(pdata->an_workqueue, &pdata->an_irq_work);
 	} else {
 		/* Enable AN interrupts */
-		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK,
-			    XGBE_AN_INT_MASK);
+		xgbe_an73_enable_interrupts(pdata);
+	}
+}
+
+static irqreturn_t xgbe_an_isr(int irq, void *data)
+{
+	struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
+
+	netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
+
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL73:
+	case XGBE_AN_MODE_CL73_REDRV:
+		xgbe_an73_isr(pdata);
+		break;
+	case XGBE_AN_MODE_CL37:
+	case XGBE_AN_MODE_CL37_SGMII:
+		xgbe_an37_isr(pdata);
+		break;
+	default:
+		break;
 	}
 
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t xgbe_an_combined_isr(int irq, struct xgbe_prv_data *pdata)
+{
+	return xgbe_an_isr(irq, pdata);
+}
+
 static void xgbe_an_irq_work(struct work_struct *work)
 {
 	struct xgbe_prv_data *pdata = container_of(work,
@@ -679,36 +746,87 @@ static const char *xgbe_state_as_string(
 	}
 }
 
-static void xgbe_an_state_machine(struct work_struct *work)
+static void xgbe_an37_state_machine(struct xgbe_prv_data *pdata)
 {
-	struct xgbe_prv_data *pdata = container_of(work,
-						   struct xgbe_prv_data,
-						   an_work);
 	enum xgbe_an cur_state = pdata->an_state;
 
-	mutex_lock(&pdata->an_mutex);
+	if (!pdata->an_int)
+		return;
+
+	if (pdata->an_int & XGBE_AN_CL37_INT_CMPLT) {
+		pdata->an_state = XGBE_AN_COMPLETE;
+		pdata->an_int &= ~XGBE_AN_CL37_INT_CMPLT;
+
+		/* If SGMII is enabled, check the link status */
+		if ((pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) &&
+		    !(pdata->an_status & XGBE_SGMII_AN_LINK_STATUS))
+			pdata->an_state = XGBE_AN_NO_LINK;
+	}
+
+	netif_dbg(pdata, link, pdata->netdev, "CL37 AN %s\n",
+		  xgbe_state_as_string(pdata->an_state));
+
+	cur_state = pdata->an_state;
+
+	switch (pdata->an_state) {
+	case XGBE_AN_READY:
+		break;
+
+	case XGBE_AN_COMPLETE:
+		netif_dbg(pdata, link, pdata->netdev,
+			  "Auto negotiation successful\n");
+		break;
+
+	case XGBE_AN_NO_LINK:
+		break;
+
+	default:
+		pdata->an_state = XGBE_AN_ERROR;
+	}
+
+	if (pdata->an_state == XGBE_AN_ERROR) {
+		netdev_err(pdata->netdev,
+			   "error during auto-negotiation, state=%u\n",
+			   cur_state);
+
+		pdata->an_int = 0;
+		xgbe_an37_clear_interrupts(pdata);
+	}
+
+	if (pdata->an_state >= XGBE_AN_COMPLETE) {
+		pdata->an_result = pdata->an_state;
+		pdata->an_state = XGBE_AN_READY;
+
+		netif_dbg(pdata, link, pdata->netdev, "CL37 AN result: %s\n",
+			  xgbe_state_as_string(pdata->an_result));
+	}
+
+	xgbe_an37_enable_interrupts(pdata);
+}
+
+static void xgbe_an73_state_machine(struct xgbe_prv_data *pdata)
+{
+	enum xgbe_an cur_state = pdata->an_state;
 
 	if (!pdata->an_int)
-		goto out;
+		return;
 
 next_int:
-	if (pdata->an_int & XGBE_AN_PG_RCV) {
+	if (pdata->an_int & XGBE_AN_CL73_PG_RCV) {
 		pdata->an_state = XGBE_AN_PAGE_RECEIVED;
-		pdata->an_int &= ~XGBE_AN_PG_RCV;
-	} else if (pdata->an_int & XGBE_AN_INC_LINK) {
+		pdata->an_int &= ~XGBE_AN_CL73_PG_RCV;
+	} else if (pdata->an_int & XGBE_AN_CL73_INC_LINK) {
 		pdata->an_state = XGBE_AN_INCOMPAT_LINK;
-		pdata->an_int &= ~XGBE_AN_INC_LINK;
-	} else if (pdata->an_int & XGBE_AN_INT_CMPLT) {
+		pdata->an_int &= ~XGBE_AN_CL73_INC_LINK;
+	} else if (pdata->an_int & XGBE_AN_CL73_INT_CMPLT) {
 		pdata->an_state = XGBE_AN_COMPLETE;
-		pdata->an_int &= ~XGBE_AN_INT_CMPLT;
+		pdata->an_int &= ~XGBE_AN_CL73_INT_CMPLT;
 	} else {
 		pdata->an_state = XGBE_AN_ERROR;
 	}
 
-	pdata->an_result = pdata->an_state;
-
 again:
-	netif_dbg(pdata, link, pdata->netdev, "AN %s\n",
+	netif_dbg(pdata, link, pdata->netdev, "CL73 AN %s\n",
 		  xgbe_state_as_string(pdata->an_state));
 
 	cur_state = pdata->an_state;
@@ -719,14 +837,14 @@ again:
 		break;
 
 	case XGBE_AN_PAGE_RECEIVED:
-		pdata->an_state = xgbe_an_page_received(pdata);
+		pdata->an_state = xgbe_an73_page_received(pdata);
 		pdata->an_supported++;
 		break;
 
 	case XGBE_AN_INCOMPAT_LINK:
 		pdata->an_supported = 0;
 		pdata->parallel_detect = 0;
-		pdata->an_state = xgbe_an_incompat_link(pdata);
+		pdata->an_state = xgbe_an73_incompat_link(pdata);
 		break;
 
 	case XGBE_AN_COMPLETE:
@@ -745,14 +863,14 @@ again:
 
 	if (pdata->an_state == XGBE_AN_NO_LINK) {
 		pdata->an_int = 0;
-		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+		xgbe_an73_clear_interrupts(pdata);
 	} else if (pdata->an_state == XGBE_AN_ERROR) {
 		netdev_err(pdata->netdev,
 			   "error during auto-negotiation, state=%u\n",
 			   cur_state);
 
 		pdata->an_int = 0;
-		XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+		xgbe_an73_clear_interrupts(pdata);
 	}
 
 	if (pdata->an_state >= XGBE_AN_COMPLETE) {
@@ -762,7 +880,7 @@ again:
 		pdata->kx_state = XGBE_RX_BPA;
 		pdata->an_start = 0;
 
-		netif_dbg(pdata, link, pdata->netdev, "AN result: %s\n",
+		netif_dbg(pdata, link, pdata->netdev, "CL73 AN result: %s\n",
 			  xgbe_state_as_string(pdata->an_result));
 	}
 
@@ -772,20 +890,88 @@ again:
 	if (pdata->an_int)
 		goto next_int;
 
-out:
-	/* Enable AN interrupts on the way out */
-	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, XGBE_AN_INT_MASK);
+	xgbe_an73_enable_interrupts(pdata);
+}
+
+static void xgbe_an_state_machine(struct work_struct *work)
+{
+	struct xgbe_prv_data *pdata = container_of(work,
+						   struct xgbe_prv_data,
+						   an_work);
+
+	mutex_lock(&pdata->an_mutex);
+
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL73:
+	case XGBE_AN_MODE_CL73_REDRV:
+		xgbe_an73_state_machine(pdata);
+		break;
+	case XGBE_AN_MODE_CL37:
+	case XGBE_AN_MODE_CL37_SGMII:
+		xgbe_an37_state_machine(pdata);
+		break;
+	default:
+		break;
+	}
 
 	mutex_unlock(&pdata->an_mutex);
 }
 
-static void xgbe_an_init(struct xgbe_prv_data *pdata)
+static void xgbe_an37_init(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg;
+	unsigned int advertising, reg;
+
+	advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
+
+	/* Set up Advertisement register */
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
+	if (advertising & ADVERTISED_Pause)
+		reg |= 0x100;
+	else
+		reg &= ~0x100;
+
+	if (advertising & ADVERTISED_Asym_Pause)
+		reg |= 0x80;
+	else
+		reg &= ~0x80;
+
+	/* Full duplex, but not half */
+	reg |= XGBE_AN_CL37_FD_MASK;
+	reg &= ~XGBE_AN_CL37_HD_MASK;
+
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg);
+
+	/* Set up the Control register */
+	reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+	reg &= ~XGBE_AN_CL37_TX_CONFIG_MASK;
+	reg &= ~XGBE_AN_CL37_PCS_MODE_MASK;
+
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL37:
+		reg |= XGBE_AN_CL37_PCS_MODE_BASEX;
+		break;
+	case XGBE_AN_MODE_CL37_SGMII:
+		reg |= XGBE_AN_CL37_PCS_MODE_SGMII;
+		break;
+	default:
+		break;
+	}
+
+	XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
+
+	netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n",
+		  (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII");
+}
+
+static void xgbe_an73_init(struct xgbe_prv_data *pdata)
+{
+	unsigned int advertising, reg;
+
+	advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
 
 	/* Set up Advertisement register 3 first */
 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
-	if (pdata->phy.advertising & ADVERTISED_10000baseR_FEC)
+	if (advertising & ADVERTISED_10000baseR_FEC)
 		reg |= 0xc000;
 	else
 		reg &= ~0xc000;
@@ -794,13 +980,13 @@ static void xgbe_an_init(struct xgbe_prv
 
 	/* Set up Advertisement register 2 next */
 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
-	if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
+	if (advertising & ADVERTISED_10000baseKR_Full)
 		reg |= 0x80;
 	else
 		reg &= ~0x80;
 
-	if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
-	    (pdata->phy.advertising & ADVERTISED_2500baseX_Full))
+	if ((advertising & ADVERTISED_1000baseKX_Full) ||
+	    (advertising & ADVERTISED_2500baseX_Full))
 		reg |= 0x20;
 	else
 		reg &= ~0x20;
@@ -809,12 +995,12 @@ static void xgbe_an_init(struct xgbe_prv
 
 	/* Set up Advertisement register 1 last */
 	reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
-	if (pdata->phy.advertising & ADVERTISED_Pause)
+	if (advertising & ADVERTISED_Pause)
 		reg |= 0x400;
 	else
 		reg &= ~0x400;
 
-	if (pdata->phy.advertising & ADVERTISED_Asym_Pause)
+	if (advertising & ADVERTISED_Asym_Pause)
 		reg |= 0x800;
 	else
 		reg &= ~0x800;
@@ -824,7 +1010,25 @@ static void xgbe_an_init(struct xgbe_prv
 
 	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg);
 
-	netif_dbg(pdata, link, pdata->netdev, "AN initialized\n");
+	netif_dbg(pdata, link, pdata->netdev, "CL73 AN initialized\n");
+}
+
+static void xgbe_an_init(struct xgbe_prv_data *pdata)
+{
+	/* Set up advertisement registers based on current settings */
+	pdata->an_mode = pdata->phy_if.phy_impl.an_mode(pdata);
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL73:
+	case XGBE_AN_MODE_CL73_REDRV:
+		xgbe_an73_init(pdata);
+		break;
+	case XGBE_AN_MODE_CL37:
+	case XGBE_AN_MODE_CL37_SGMII:
+		xgbe_an37_init(pdata);
+		break;
+	default:
+		break;
+	}
 }
 
 static const char *xgbe_phy_fc_string(struct xgbe_prv_data *pdata)
@@ -842,6 +1046,8 @@ static const char *xgbe_phy_fc_string(st
 static const char *xgbe_phy_speed_string(int speed)
 {
 	switch (speed) {
+	case SPEED_100:
+		return "100Mbps";
 	case SPEED_1000:
 		return "1Gbps";
 	case SPEED_2500:
@@ -907,24 +1113,32 @@ static void xgbe_phy_adjust_link(struct
 		xgbe_phy_print_status(pdata);
 }
 
+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
+{
+	return pdata->phy_if.phy_impl.valid_speed(pdata, speed);
+}
+
 static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata)
 {
+	enum xgbe_mode mode;
+
 	netif_dbg(pdata, link, pdata->netdev, "fixed PHY configuration\n");
 
 	/* Disable auto-negotiation */
-	xgbe_disable_an(pdata);
-
-	/* Validate/Set specified speed */
-	switch (pdata->phy.speed) {
-	case SPEED_10000:
-		xgbe_set_mode(pdata, XGBE_MODE_KR);
-		break;
+	xgbe_an_disable(pdata);
 
-	case SPEED_2500:
-	case SPEED_1000:
-		xgbe_set_mode(pdata, XGBE_MODE_KX);
+	/* Set specified mode for specified speed */
+	mode = pdata->phy_if.phy_impl.get_mode(pdata, pdata->phy.speed);
+	switch (mode) {
+	case XGBE_MODE_KX_1000:
+	case XGBE_MODE_KX_2500:
+	case XGBE_MODE_KR:
+	case XGBE_MODE_SGMII_100:
+	case XGBE_MODE_SGMII_1000:
+	case XGBE_MODE_X:
+	case XGBE_MODE_SFI:
 		break;
-
+	case XGBE_MODE_UNKNOWN:
 	default:
 		return -EINVAL;
 	}
@@ -933,38 +1147,60 @@ static int xgbe_phy_config_fixed(struct
 	if (pdata->phy.duplex != DUPLEX_FULL)
 		return -EINVAL;
 
+	xgbe_set_mode(pdata, mode);
+
 	return 0;
 }
 
 static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata)
 {
+	int ret;
+
 	set_bit(XGBE_LINK_INIT, &pdata->dev_state);
 	pdata->link_check = jiffies;
 
-	if (pdata->phy.autoneg != AUTONEG_ENABLE)
-		return xgbe_phy_config_fixed(pdata);
+	ret = pdata->phy_if.phy_impl.an_config(pdata);
+	if (ret)
+		return ret;
 
-	netif_dbg(pdata, link, pdata->netdev, "AN PHY configuration\n");
+	if (pdata->phy.autoneg != AUTONEG_ENABLE) {
+		ret = xgbe_phy_config_fixed(pdata);
+		if (ret || !pdata->kr_redrv)
+			return ret;
+
+		netif_dbg(pdata, link, pdata->netdev, "AN redriver support\n");
+	} else {
+		netif_dbg(pdata, link, pdata->netdev, "AN PHY configuration\n");
+	}
 
 	/* Disable auto-negotiation interrupt */
 	disable_irq(pdata->an_irq);
 
 	/* Start auto-negotiation in a supported mode */
-	if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full) {
+	if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
 		xgbe_set_mode(pdata, XGBE_MODE_KR);
-	} else if ((pdata->phy.advertising & ADVERTISED_1000baseKX_Full) ||
-		   (pdata->phy.advertising & ADVERTISED_2500baseX_Full)) {
-		xgbe_set_mode(pdata, XGBE_MODE_KX);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
+		xgbe_set_mode(pdata, XGBE_MODE_KX_2500);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
+		xgbe_set_mode(pdata, XGBE_MODE_KX_1000);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
+		xgbe_set_mode(pdata, XGBE_MODE_SFI);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
+		xgbe_set_mode(pdata, XGBE_MODE_X);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
+		xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
+		xgbe_set_mode(pdata, XGBE_MODE_SGMII_100);
 	} else {
 		enable_irq(pdata->an_irq);
 		return -EINVAL;
 	}
 
 	/* Disable and stop any in progress auto-negotiation */
-	xgbe_disable_an(pdata);
+	xgbe_an_disable_all(pdata);
 
 	/* Clear any auto-negotitation interrupts */
-	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+	xgbe_an_clear_interrupts_all(pdata);
 
 	pdata->an_result = XGBE_AN_READY;
 	pdata->an_state = XGBE_AN_READY;
@@ -974,11 +1210,8 @@ static int __xgbe_phy_config_aneg(struct
 	/* Re-enable auto-negotiation interrupt */
 	enable_irq(pdata->an_irq);
 
-	/* Set up advertisement registers based on current settings */
 	xgbe_an_init(pdata);
-
-	/* Enable and start auto-negotiation */
-	xgbe_restart_an(pdata);
+	xgbe_an_restart(pdata);
 
 	return 0;
 }
@@ -1016,108 +1249,52 @@ static void xgbe_check_link_timeout(stru
 	}
 }
 
-static void xgbe_phy_status_force(struct xgbe_prv_data *pdata)
+static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
 {
-	if (xgbe_in_kr_mode(pdata)) {
-		pdata->phy.speed = SPEED_10000;
-	} else {
-		switch (pdata->speed_set) {
-		case XGBE_SPEEDSET_1000_10000:
-			pdata->phy.speed = SPEED_1000;
-			break;
-
-		case XGBE_SPEEDSET_2500_10000:
-			pdata->phy.speed = SPEED_2500;
-			break;
-		}
-	}
-	pdata->phy.duplex = DUPLEX_FULL;
+	return pdata->phy_if.phy_impl.an_outcome(pdata);
 }
 
-static void xgbe_phy_status_aneg(struct xgbe_prv_data *pdata)
+static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 {
-	unsigned int ad_reg, lp_reg;
+	enum xgbe_mode mode;
 
 	pdata->phy.lp_advertising = 0;
 
 	if ((pdata->phy.autoneg != AUTONEG_ENABLE) || pdata->parallel_detect)
-		return xgbe_phy_status_force(pdata);
-
-	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
-	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
-
-	/* Compare Advertisement and Link Partner register 1 */
-	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
-	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
-	if (lp_reg & 0x400)
-		pdata->phy.lp_advertising |= ADVERTISED_Pause;
-	if (lp_reg & 0x800)
-		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
-
-	if (pdata->phy.pause_autoneg) {
-		/* Set flow control based on auto-negotiation result */
-		pdata->phy.tx_pause = 0;
-		pdata->phy.rx_pause = 0;
-
-		if (ad_reg & lp_reg & 0x400) {
-			pdata->phy.tx_pause = 1;
-			pdata->phy.rx_pause = 1;
-		} else if (ad_reg & lp_reg & 0x800) {
-			if (ad_reg & 0x400)
-				pdata->phy.rx_pause = 1;
-			else if (lp_reg & 0x400)
-				pdata->phy.tx_pause = 1;
-		}
-	}
-
-	/* Compare Advertisement and Link Partner register 2 */
-	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
-	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
-	if (lp_reg & 0x80)
-		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
-	if (lp_reg & 0x20) {
-		switch (pdata->speed_set) {
-		case XGBE_SPEEDSET_1000_10000:
-			pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
-			break;
-		case XGBE_SPEEDSET_2500_10000:
-			pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
-			break;
-		}
-	}
+		mode = xgbe_cur_mode(pdata);
+	else
+		mode = xgbe_phy_status_aneg(pdata);
 
-	ad_reg &= lp_reg;
-	if (ad_reg & 0x80) {
+	switch (mode) {
+	case XGBE_MODE_SGMII_100:
+		pdata->phy.speed = SPEED_100;
+		break;
+	case XGBE_MODE_X:
+	case XGBE_MODE_KX_1000:
+	case XGBE_MODE_SGMII_1000:
+		pdata->phy.speed = SPEED_1000;
+		break;
+	case XGBE_MODE_KX_2500:
+		pdata->phy.speed = SPEED_2500;
+		break;
+	case XGBE_MODE_KR:
+	case XGBE_MODE_SFI:
 		pdata->phy.speed = SPEED_10000;
-		xgbe_set_mode(pdata, XGBE_MODE_KR);
-	} else if (ad_reg & 0x20) {
-		switch (pdata->speed_set) {
-		case XGBE_SPEEDSET_1000_10000:
-			pdata->phy.speed = SPEED_1000;
-			break;
-
-		case XGBE_SPEEDSET_2500_10000:
-			pdata->phy.speed = SPEED_2500;
-			break;
-		}
-
-		xgbe_set_mode(pdata, XGBE_MODE_KX);
-	} else {
+		break;
+	case XGBE_MODE_UNKNOWN:
+	default:
 		pdata->phy.speed = SPEED_UNKNOWN;
 	}
 
-	/* Compare Advertisement and Link Partner register 3 */
-	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
-	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
-	if (lp_reg & 0xc000)
-		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
-
 	pdata->phy.duplex = DUPLEX_FULL;
+
+	xgbe_set_mode(pdata, mode);
 }
 
 static void xgbe_phy_status(struct xgbe_prv_data *pdata)
 {
-	unsigned int reg, link_aneg;
+	unsigned int link_aneg;
+	int an_restart;
 
 	if (test_bit(XGBE_LINK_ERR, &pdata->dev_state)) {
 		netif_carrier_off(pdata->netdev);
@@ -1128,12 +1305,12 @@ static void xgbe_phy_status(struct xgbe_
 
 	link_aneg = (pdata->phy.autoneg == AUTONEG_ENABLE);
 
-	/* Get the link status. Link status is latched low, so read
-	 * once to clear and then read again to get current state
-	 */
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
-	pdata->phy.link = (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
+	pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata,
+							     &an_restart);
+	if (an_restart) {
+		xgbe_phy_config_aneg(pdata);
+		return;
+	}
 
 	if (pdata->phy.link) {
 		if (link_aneg && !xgbe_phy_aneg_done(pdata)) {
@@ -1141,7 +1318,7 @@ static void xgbe_phy_status(struct xgbe_
 			return;
 		}
 
-		xgbe_phy_status_aneg(pdata);
+		xgbe_phy_status_result(pdata);
 
 		if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
 			clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
@@ -1155,7 +1332,7 @@ static void xgbe_phy_status(struct xgbe_
 				return;
 		}
 
-		xgbe_phy_status_aneg(pdata);
+		xgbe_phy_status_result(pdata);
 
 		netif_carrier_off(pdata->netdev);
 	}
@@ -1168,13 +1345,19 @@ static void xgbe_phy_stop(struct xgbe_pr
 {
 	netif_dbg(pdata, link, pdata->netdev, "stopping PHY\n");
 
+	if (!pdata->phy_started)
+		return;
+
+	/* Indicate the PHY is down */
+	pdata->phy_started = 0;
+
 	/* Disable auto-negotiation */
-	xgbe_disable_an(pdata);
+	xgbe_an_disable_all(pdata);
 
-	/* Disable auto-negotiation interrupts */
-	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0);
+	if (pdata->dev_irq != pdata->an_irq)
+		devm_free_irq(pdata->dev, pdata->an_irq, pdata);
 
-	devm_free_irq(pdata->dev, pdata->an_irq, pdata);
+	pdata->phy_if.phy_impl.stop(pdata);
 
 	pdata->phy.link = 0;
 	netif_carrier_off(pdata->netdev);
@@ -1189,64 +1372,74 @@ static int xgbe_phy_start(struct xgbe_pr
 
 	netif_dbg(pdata, link, pdata->netdev, "starting PHY\n");
 
-	ret = devm_request_irq(pdata->dev, pdata->an_irq,
-			       xgbe_an_isr, 0, pdata->an_name,
-			       pdata);
-	if (ret) {
-		netdev_err(netdev, "phy irq request failed\n");
+	ret = pdata->phy_if.phy_impl.start(pdata);
+	if (ret)
 		return ret;
+
+	/* If we have a separate AN irq, enable it */
+	if (pdata->dev_irq != pdata->an_irq) {
+		ret = devm_request_irq(pdata->dev, pdata->an_irq,
+				       xgbe_an_isr, 0, pdata->an_name,
+				       pdata);
+		if (ret) {
+			netdev_err(netdev, "phy irq request failed\n");
+			goto err_stop;
+		}
 	}
 
 	/* Set initial mode - call the mode setting routines
 	 * directly to insure we are properly configured
 	 */
-	if (xgbe_use_xgmii_mode(pdata)) {
-		xgbe_xgmii_mode(pdata);
-	} else if (xgbe_use_gmii_mode(pdata)) {
-		xgbe_gmii_mode(pdata);
-	} else if (xgbe_use_gmii_2500_mode(pdata)) {
-		xgbe_gmii_2500_mode(pdata);
+	if (xgbe_use_mode(pdata, XGBE_MODE_KR)) {
+		xgbe_kr_mode(pdata);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) {
+		xgbe_kx_2500_mode(pdata);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) {
+		xgbe_kx_1000_mode(pdata);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) {
+		xgbe_sfi_mode(pdata);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_X)) {
+		xgbe_x_mode(pdata);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) {
+		xgbe_sgmii_1000_mode(pdata);
+	} else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) {
+		xgbe_sgmii_100_mode(pdata);
 	} else {
 		ret = -EINVAL;
 		goto err_irq;
 	}
 
-	/* Set up advertisement registers based on current settings */
-	xgbe_an_init(pdata);
+	/* Indicate the PHY is up and running */
+	pdata->phy_started = 1;
 
-	/* Enable auto-negotiation interrupts */
-	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INTMASK, 0x07);
+	xgbe_an_init(pdata);
+	xgbe_an_enable_interrupts(pdata);
 
 	return xgbe_phy_config_aneg(pdata);
 
 err_irq:
-	devm_free_irq(pdata->dev, pdata->an_irq, pdata);
+	if (pdata->dev_irq != pdata->an_irq)
+		devm_free_irq(pdata->dev, pdata->an_irq, pdata);
+
+err_stop:
+	pdata->phy_if.phy_impl.stop(pdata);
 
 	return ret;
 }
 
 static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
 {
-	unsigned int count, reg;
-
-	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-	reg |= MDIO_CTRL1_RESET;
-	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
-
-	count = 50;
-	do {
-		msleep(20);
-		reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
-	} while ((reg & MDIO_CTRL1_RESET) && --count);
+	int ret;
 
-	if (reg & MDIO_CTRL1_RESET)
-		return -ETIMEDOUT;
+	ret = pdata->phy_if.phy_impl.reset(pdata);
+	if (ret)
+		return ret;
 
 	/* Disable auto-negotiation for now */
-	xgbe_disable_an(pdata);
+	xgbe_an_disable_all(pdata);
 
 	/* Clear auto-negotiation interrupts */
-	XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
+	xgbe_an_clear_interrupts_all(pdata);
 
 	return 0;
 }
@@ -1257,74 +1450,96 @@ static void xgbe_dump_phy_registers(stru
 
 	dev_dbg(dev, "\n************* PHY Reg dump **********************\n");
 
-	dev_dbg(dev, "PCS Control Reg (%#04x) = %#04x\n", MDIO_CTRL1,
+	dev_dbg(dev, "PCS Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
 		XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1));
-	dev_dbg(dev, "PCS Status Reg (%#04x) = %#04x\n", MDIO_STAT1,
+	dev_dbg(dev, "PCS Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
 		XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1));
-	dev_dbg(dev, "Phy Id (PHYS ID 1 %#04x)= %#04x\n", MDIO_DEVID1,
+	dev_dbg(dev, "Phy Id (PHYS ID 1 %#06x)= %#06x\n", MDIO_DEVID1,
 		XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID1));
-	dev_dbg(dev, "Phy Id (PHYS ID 2 %#04x)= %#04x\n", MDIO_DEVID2,
+	dev_dbg(dev, "Phy Id (PHYS ID 2 %#06x)= %#06x\n", MDIO_DEVID2,
 		XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVID2));
-	dev_dbg(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS1,
+	dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS1,
 		XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS1));
-	dev_dbg(dev, "Devices in Package (%#04x)= %#04x\n", MDIO_DEVS2,
+	dev_dbg(dev, "Devices in Package (%#06x)= %#06x\n", MDIO_DEVS2,
 		XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_DEVS2));
 
-	dev_dbg(dev, "Auto-Neg Control Reg (%#04x) = %#04x\n", MDIO_CTRL1,
+	dev_dbg(dev, "Auto-Neg Control Reg (%#06x) = %#06x\n", MDIO_CTRL1,
 		XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1));
-	dev_dbg(dev, "Auto-Neg Status Reg (%#04x) = %#04x\n", MDIO_STAT1,
+	dev_dbg(dev, "Auto-Neg Status Reg (%#06x) = %#06x\n", MDIO_STAT1,
 		XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_STAT1));
-	dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#04x) = %#04x\n",
+	dev_dbg(dev, "Auto-Neg Ad Reg 1 (%#06x) = %#06x\n",
 		MDIO_AN_ADVERTISE,
 		XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE));
-	dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#04x) = %#04x\n",
+	dev_dbg(dev, "Auto-Neg Ad Reg 2 (%#06x) = %#06x\n",
 		MDIO_AN_ADVERTISE + 1,
 		XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1));
-	dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#04x) = %#04x\n",
+	dev_dbg(dev, "Auto-Neg Ad Reg 3 (%#06x) = %#06x\n",
 		MDIO_AN_ADVERTISE + 2,
 		XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2));
-	dev_dbg(dev, "Auto-Neg Completion Reg (%#04x) = %#04x\n",
+	dev_dbg(dev, "Auto-Neg Completion Reg (%#06x) = %#06x\n",
 		MDIO_AN_COMP_STAT,
 		XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_COMP_STAT));
 
 	dev_dbg(dev, "\n*************************************************\n");
 }
 
-static void xgbe_phy_init(struct xgbe_prv_data *pdata)
+static int xgbe_phy_best_advertised_speed(struct xgbe_prv_data *pdata)
 {
+	if (pdata->phy.advertising & ADVERTISED_10000baseKR_Full)
+		return SPEED_10000;
+	else if (pdata->phy.advertising & ADVERTISED_10000baseT_Full)
+		return SPEED_10000;
+	else if (pdata->phy.advertising & ADVERTISED_2500baseX_Full)
+		return SPEED_2500;
+	else if (pdata->phy.advertising & ADVERTISED_1000baseKX_Full)
+		return SPEED_1000;
+	else if (pdata->phy.advertising & ADVERTISED_1000baseT_Full)
+		return SPEED_1000;
+	else if (pdata->phy.advertising & ADVERTISED_100baseT_Full)
+		return SPEED_100;
+
+	return SPEED_UNKNOWN;
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+	xgbe_phy_stop(pdata);
+
+	pdata->phy_if.phy_impl.exit(pdata);
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+	int ret;
+
 	mutex_init(&pdata->an_mutex);
 	INIT_WORK(&pdata->an_irq_work, xgbe_an_irq_work);
 	INIT_WORK(&pdata->an_work, xgbe_an_state_machine);
 	pdata->mdio_mmd = MDIO_MMD_PCS;
 
-	/* Initialize supported features */
-	pdata->phy.supported = SUPPORTED_Autoneg;
-	pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
-	pdata->phy.supported |= SUPPORTED_Backplane;
-	pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
-	switch (pdata->speed_set) {
-	case XGBE_SPEEDSET_1000_10000:
-		pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
-		break;
-	case XGBE_SPEEDSET_2500_10000:
-		pdata->phy.supported |= SUPPORTED_2500baseX_Full;
-		break;
-	}
-
+	/* Check for FEC support */
 	pdata->fec_ability = XMDIO_READ(pdata, MDIO_MMD_PMAPMD,
 					MDIO_PMA_10GBR_FECABLE);
 	pdata->fec_ability &= (MDIO_PMA_10GBR_FECABLE_ABLE |
 			       MDIO_PMA_10GBR_FECABLE_ERRABLE);
-	if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
-		pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
 
+	/* Setup the phy (including supported features) */
+	ret = pdata->phy_if.phy_impl.init(pdata);
+	if (ret)
+		return ret;
 	pdata->phy.advertising = pdata->phy.supported;
 
 	pdata->phy.address = 0;
 
-	pdata->phy.autoneg = AUTONEG_ENABLE;
-	pdata->phy.speed = SPEED_UNKNOWN;
-	pdata->phy.duplex = DUPLEX_UNKNOWN;
+	if (pdata->phy.advertising & ADVERTISED_Autoneg) {
+		pdata->phy.autoneg = AUTONEG_ENABLE;
+		pdata->phy.speed = SPEED_UNKNOWN;
+		pdata->phy.duplex = DUPLEX_UNKNOWN;
+	} else {
+		pdata->phy.autoneg = AUTONEG_DISABLE;
+		pdata->phy.speed = xgbe_phy_best_advertised_speed(pdata);
+		pdata->phy.duplex = DUPLEX_FULL;
+	}
 
 	pdata->phy.link = 0;
 
@@ -1346,11 +1561,14 @@ static void xgbe_phy_init(struct xgbe_pr
 
 	if (netif_msg_drv(pdata))
 		xgbe_dump_phy_registers(pdata);
+
+	return 0;
 }
 
 void xgbe_init_function_ptrs_phy(struct xgbe_phy_if *phy_if)
 {
 	phy_if->phy_init        = xgbe_phy_init;
+	phy_if->phy_exit        = xgbe_phy_exit;
 
 	phy_if->phy_reset       = xgbe_phy_reset;
 	phy_if->phy_start       = xgbe_phy_start;
@@ -1358,4 +1576,8 @@ void xgbe_init_function_ptrs_phy(struct
 
 	phy_if->phy_status      = xgbe_phy_status;
 	phy_if->phy_config_aneg = xgbe_phy_config_aneg;
+
+	phy_if->phy_valid_speed = xgbe_phy_valid_speed;
+
+	phy_if->an_isr          = xgbe_an_combined_isr;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-pci.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,542 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Advanced Micro Devices, Inc. nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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 file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ *     THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/log2.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+static int xgbe_config_msi(struct xgbe_prv_data *pdata)
+{
+	unsigned int msi_count;
+	unsigned int i, j;
+	int ret;
+
+	msi_count = XGBE_MSIX_BASE_COUNT;
+	msi_count += max(pdata->rx_ring_count,
+			 pdata->tx_ring_count);
+	msi_count = roundup_pow_of_two(msi_count);
+
+	ret = pci_enable_msi_exact(pdata->pcidev, msi_count);
+	if (ret < 0) {
+		dev_info(pdata->dev, "MSI request for %u interrupts failed\n",
+			 msi_count);
+
+		ret = pci_enable_msi(pdata->pcidev);
+		if (ret < 0) {
+			dev_info(pdata->dev, "MSI enablement failed\n");
+			return ret;
+		}
+
+		msi_count = 1;
+	}
+
+	pdata->irq_count = msi_count;
+
+	pdata->dev_irq = pdata->pcidev->irq;
+
+	if (msi_count > 1) {
+		pdata->ecc_irq = pdata->pcidev->irq + 1;
+		pdata->i2c_irq = pdata->pcidev->irq + 2;
+		pdata->an_irq = pdata->pcidev->irq + 3;
+
+		for (i = XGBE_MSIX_BASE_COUNT, j = 0;
+		     (i < msi_count) && (j < XGBE_MAX_DMA_CHANNELS);
+		     i++, j++)
+			pdata->channel_irq[j] = pdata->pcidev->irq + i;
+		pdata->channel_irq_count = j;
+
+		pdata->per_channel_irq = 1;
+		pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL;
+	} else {
+		pdata->ecc_irq = pdata->pcidev->irq;
+		pdata->i2c_irq = pdata->pcidev->irq;
+		pdata->an_irq = pdata->pcidev->irq;
+	}
+
+	if (netif_msg_probe(pdata))
+		dev_dbg(pdata->dev, "MSI interrupts enabled\n");
+
+	return 0;
+}
+
+static int xgbe_config_msix(struct xgbe_prv_data *pdata)
+{
+	unsigned int msix_count;
+	unsigned int i, j;
+	int ret;
+
+	msix_count = XGBE_MSIX_BASE_COUNT;
+	msix_count += max(pdata->rx_ring_count,
+			  pdata->tx_ring_count);
+
+	pdata->msix_entries = devm_kcalloc(pdata->dev, msix_count,
+					   sizeof(struct msix_entry),
+					   GFP_KERNEL);
+	if (!pdata->msix_entries)
+		return -ENOMEM;
+
+	for (i = 0; i < msix_count; i++)
+		pdata->msix_entries[i].entry = i;
+
+	ret = pci_enable_msix_range(pdata->pcidev, pdata->msix_entries,
+				    XGBE_MSIX_MIN_COUNT, msix_count);
+	if (ret < 0) {
+		dev_info(pdata->dev, "MSI-X enablement failed\n");
+		devm_kfree(pdata->dev, pdata->msix_entries);
+		pdata->msix_entries = NULL;
+		return ret;
+	}
+
+	pdata->irq_count = ret;
+
+	pdata->dev_irq = pdata->msix_entries[0].vector;
+	pdata->ecc_irq = pdata->msix_entries[1].vector;
+	pdata->i2c_irq = pdata->msix_entries[2].vector;
+	pdata->an_irq = pdata->msix_entries[3].vector;
+
+	for (i = XGBE_MSIX_BASE_COUNT, j = 0; i < ret; i++, j++)
+		pdata->channel_irq[j] = pdata->msix_entries[i].vector;
+	pdata->channel_irq_count = j;
+
+	pdata->per_channel_irq = 1;
+	pdata->channel_irq_mode = XGBE_IRQ_MODE_LEVEL;
+
+	if (netif_msg_probe(pdata))
+		dev_dbg(pdata->dev, "MSI-X interrupts enabled\n");
+
+	return 0;
+}
+
+static int xgbe_config_irqs(struct xgbe_prv_data *pdata)
+{
+	int ret;
+
+	ret = xgbe_config_msix(pdata);
+	if (!ret)
+		goto out;
+
+	ret = xgbe_config_msi(pdata);
+	if (!ret)
+		goto out;
+
+	pdata->irq_count = 1;
+	pdata->irq_shared = 1;
+
+	pdata->dev_irq = pdata->pcidev->irq;
+	pdata->ecc_irq = pdata->pcidev->irq;
+	pdata->i2c_irq = pdata->pcidev->irq;
+	pdata->an_irq = pdata->pcidev->irq;
+
+out:
+	if (netif_msg_probe(pdata)) {
+		unsigned int i;
+
+		dev_dbg(pdata->dev, " dev irq=%d\n", pdata->dev_irq);
+		dev_dbg(pdata->dev, " ecc irq=%d\n", pdata->ecc_irq);
+		dev_dbg(pdata->dev, " i2c irq=%d\n", pdata->i2c_irq);
+		dev_dbg(pdata->dev, "  an irq=%d\n", pdata->an_irq);
+		for (i = 0; i < pdata->channel_irq_count; i++)
+			dev_dbg(pdata->dev, " dma%u irq=%d\n",
+				i, pdata->channel_irq[i]);
+	}
+
+	return 0;
+}
+
+static int xgbe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct xgbe_prv_data *pdata;
+	struct device *dev = &pdev->dev;
+	void __iomem * const *iomap_table;
+	struct pci_dev *rdev;
+	unsigned int ma_lo, ma_hi;
+	unsigned int reg;
+	int bar_mask;
+	int ret;
+
+	pdata = xgbe_alloc_pdata(dev);
+	if (IS_ERR(pdata)) {
+		ret = PTR_ERR(pdata);
+		goto err_alloc;
+	}
+
+	pdata->pcidev = pdev;
+	pci_set_drvdata(pdev, pdata);
+
+	/* Get the version data */
+	pdata->vdata = (struct xgbe_version_data *)id->driver_data;
+
+	ret = pcim_enable_device(pdev);
+	if (ret) {
+		dev_err(dev, "pcim_enable_device failed\n");
+		goto err_pci_enable;
+	}
+
+	/* Obtain the mmio areas for the device */
+	bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
+	ret = pcim_iomap_regions(pdev, bar_mask, XGBE_DRV_NAME);
+	if (ret) {
+		dev_err(dev, "pcim_iomap_regions failed\n");
+		goto err_pci_enable;
+	}
+
+	iomap_table = pcim_iomap_table(pdev);
+	if (!iomap_table) {
+		dev_err(dev, "pcim_iomap_table failed\n");
+		ret = -ENOMEM;
+		goto err_pci_enable;
+	}
+
+	pdata->xgmac_regs = iomap_table[XGBE_XGMAC_BAR];
+	if (!pdata->xgmac_regs) {
+		dev_err(dev, "xgmac ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_pci_enable;
+	}
+	pdata->xprop_regs = pdata->xgmac_regs + XGBE_MAC_PROP_OFFSET;
+	pdata->xi2c_regs = pdata->xgmac_regs + XGBE_I2C_CTRL_OFFSET;
+	if (netif_msg_probe(pdata)) {
+		dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs);
+		dev_dbg(dev, "xprop_regs = %p\n", pdata->xprop_regs);
+		dev_dbg(dev, "xi2c_regs  = %p\n", pdata->xi2c_regs);
+	}
+
+	pdata->xpcs_regs = iomap_table[XGBE_XPCS_BAR];
+	if (!pdata->xpcs_regs) {
+		dev_err(dev, "xpcs ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_pci_enable;
+	}
+	if (netif_msg_probe(pdata))
+		dev_dbg(dev, "xpcs_regs  = %p\n", pdata->xpcs_regs);
+
+	/* Set the PCS indirect addressing definition registers */
+	rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
+	if (rdev &&
+	    (rdev->vendor == PCI_VENDOR_ID_AMD) && (rdev->device == 0x15d0)) {
+		pdata->xpcs_window_def_reg = PCS_V2_RV_WINDOW_DEF;
+		pdata->xpcs_window_sel_reg = PCS_V2_RV_WINDOW_SELECT;
+	} else {
+		pdata->xpcs_window_def_reg = PCS_V2_WINDOW_DEF;
+		pdata->xpcs_window_sel_reg = PCS_V2_WINDOW_SELECT;
+	}
+	pci_dev_put(rdev);
+
+	/* Configure the PCS indirect addressing support */
+	reg = XPCS32_IOREAD(pdata, pdata->xpcs_window_def_reg);
+	pdata->xpcs_window = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, OFFSET);
+	pdata->xpcs_window <<= 6;
+	pdata->xpcs_window_size = XPCS_GET_BITS(reg, PCS_V2_WINDOW_DEF, SIZE);
+	pdata->xpcs_window_size = 1 << (pdata->xpcs_window_size + 7);
+	pdata->xpcs_window_mask = pdata->xpcs_window_size - 1;
+	if (netif_msg_probe(pdata)) {
+		dev_dbg(dev, "xpcs window      = %#010x\n",
+			pdata->xpcs_window);
+		dev_dbg(dev, "xpcs window size = %#010x\n",
+			pdata->xpcs_window_size);
+		dev_dbg(dev, "xpcs window mask = %#010x\n",
+			pdata->xpcs_window_mask);
+	}
+
+	pci_set_master(pdev);
+
+	/* Enable all interrupts in the hardware */
+	XP_IOWRITE(pdata, XP_INT_EN, 0x1fffff);
+
+	/* Retrieve the MAC address */
+	ma_lo = XP_IOREAD(pdata, XP_MAC_ADDR_LO);
+	ma_hi = XP_IOREAD(pdata, XP_MAC_ADDR_HI);
+	pdata->mac_addr[0] = ma_lo & 0xff;
+	pdata->mac_addr[1] = (ma_lo >> 8) & 0xff;
+	pdata->mac_addr[2] = (ma_lo >> 16) & 0xff;
+	pdata->mac_addr[3] = (ma_lo >> 24) & 0xff;
+	pdata->mac_addr[4] = ma_hi & 0xff;
+	pdata->mac_addr[5] = (ma_hi >> 8) & 0xff;
+	if (!XP_GET_BITS(ma_hi, XP_MAC_ADDR_HI, VALID) ||
+	    !is_valid_ether_addr(pdata->mac_addr)) {
+		dev_err(dev, "invalid mac address\n");
+		ret = -EINVAL;
+		goto err_pci_enable;
+	}
+
+	/* Clock settings */
+	pdata->sysclk_rate = XGBE_V2_DMA_CLOCK_FREQ;
+	pdata->ptpclk_rate = XGBE_V2_PTP_CLOCK_FREQ;
+
+	/* Set the DMA coherency values */
+	pdata->coherent = 1;
+	pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
+	pdata->arcache = XGBE_DMA_OS_ARCACHE;
+	pdata->awcache = XGBE_DMA_OS_AWCACHE;
+
+	/* Set the maximum channels and queues */
+	reg = XP_IOREAD(pdata, XP_PROP_1);
+	pdata->tx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_DMA);
+	pdata->rx_max_channel_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_DMA);
+	pdata->tx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_TX_QUEUES);
+	pdata->rx_max_q_count = XP_GET_BITS(reg, XP_PROP_1, MAX_RX_QUEUES);
+	if (netif_msg_probe(pdata)) {
+		dev_dbg(dev, "max tx/rx channel count = %u/%u\n",
+			pdata->tx_max_channel_count,
+			pdata->tx_max_channel_count);
+		dev_dbg(dev, "max tx/rx hw queue count = %u/%u\n",
+			pdata->tx_max_q_count, pdata->rx_max_q_count);
+	}
+
+	/* Set the hardware channel and queue counts */
+	xgbe_set_counts(pdata);
+
+	/* Set the maximum fifo amounts */
+	reg = XP_IOREAD(pdata, XP_PROP_2);
+	pdata->tx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, TX_FIFO_SIZE);
+	pdata->tx_max_fifo_size *= 16384;
+	pdata->tx_max_fifo_size = min(pdata->tx_max_fifo_size,
+				      pdata->vdata->tx_max_fifo_size);
+	pdata->rx_max_fifo_size = XP_GET_BITS(reg, XP_PROP_2, RX_FIFO_SIZE);
+	pdata->rx_max_fifo_size *= 16384;
+	pdata->rx_max_fifo_size = min(pdata->rx_max_fifo_size,
+				      pdata->vdata->rx_max_fifo_size);
+	if (netif_msg_probe(pdata))
+		dev_dbg(dev, "max tx/rx max fifo size = %u/%u\n",
+			pdata->tx_max_fifo_size, pdata->rx_max_fifo_size);
+
+	/* Configure interrupt support */
+	ret = xgbe_config_irqs(pdata);
+	if (ret)
+		goto err_pci_enable;
+
+	/* Configure the netdev resource */
+	ret = xgbe_config_netdev(pdata);
+	if (ret)
+		goto err_pci_enable;
+
+	netdev_notice(pdata->netdev, "net device enabled\n");
+
+	return 0;
+
+err_pci_enable:
+	xgbe_free_pdata(pdata);
+
+err_alloc:
+	dev_notice(dev, "net device not enabled\n");
+
+	return ret;
+}
+
+static void xgbe_pci_remove(struct pci_dev *pdev)
+{
+	struct xgbe_prv_data *pdata = pci_get_drvdata(pdev);
+
+	xgbe_deconfig_netdev(pdata);
+
+	xgbe_free_pdata(pdata);
+}
+
+#ifdef CONFIG_PM
+static int xgbe_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct xgbe_prv_data *pdata = pci_get_drvdata(pdev);
+	struct net_device *netdev = pdata->netdev;
+	int ret = 0;
+
+	if (netif_running(netdev))
+		ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
+
+	pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+	pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+	return ret;
+}
+
+static int xgbe_pci_resume(struct pci_dev *pdev)
+{
+	struct xgbe_prv_data *pdata = pci_get_drvdata(pdev);
+	struct net_device *netdev = pdata->netdev;
+	int ret = 0;
+
+	pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+	if (netif_running(netdev)) {
+		ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
+
+		/* Schedule a restart in case the link or phy state changed
+		 * while we were powered down.
+		 */
+		schedule_work(&pdata->restart_work);
+	}
+
+	return ret;
+}
+#endif /* CONFIG_PM */
+
+static const struct xgbe_version_data xgbe_v2a = {
+	.init_function_ptrs_phy_impl	= xgbe_init_function_ptrs_phy_v2,
+	.xpcs_access			= XGBE_XPCS_ACCESS_V2,
+	.mmc_64bit			= 1,
+	.tx_max_fifo_size		= 229376,
+	.rx_max_fifo_size		= 229376,
+	.tx_tstamp_workaround		= 1,
+	.ecc_support			= 1,
+	.i2c_support			= 1,
+};
+
+static const struct xgbe_version_data xgbe_v2b = {
+	.init_function_ptrs_phy_impl	= xgbe_init_function_ptrs_phy_v2,
+	.xpcs_access			= XGBE_XPCS_ACCESS_V2,
+	.mmc_64bit			= 1,
+	.tx_max_fifo_size		= 65536,
+	.rx_max_fifo_size		= 65536,
+	.tx_tstamp_workaround		= 1,
+	.ecc_support			= 1,
+	.i2c_support			= 1,
+};
+
+static const struct pci_device_id xgbe_pci_table[] = {
+	{ PCI_VDEVICE(AMD, 0x1458),
+	  .driver_data = (kernel_ulong_t)&xgbe_v2a },
+	{ PCI_VDEVICE(AMD, 0x1459),
+	  .driver_data = (kernel_ulong_t)&xgbe_v2b },
+	/* Last entry must be zero */
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, xgbe_pci_table);
+
+static struct pci_driver xgbe_driver = {
+	.name = XGBE_DRV_NAME,
+	.id_table = xgbe_pci_table,
+	.probe = xgbe_pci_probe,
+	.remove = xgbe_pci_remove,
+#ifdef CONFIG_PM
+	.suspend = xgbe_pci_suspend,
+	.resume = xgbe_pci_resume,
+#endif
+};
+
+int xgbe_pci_init(void)
+{
+	return pci_register_driver(&xgbe_driver);
+}
+
+void xgbe_pci_exit(void)
+{
+	pci_unregister_driver(&xgbe_driver);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,845 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Advanced Micro Devices, Inc. nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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 file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ *     THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/device.h>
+#include <linux/property.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#define XGBE_BLWC_PROPERTY		"amd,serdes-blwc"
+#define XGBE_CDR_RATE_PROPERTY		"amd,serdes-cdr-rate"
+#define XGBE_PQ_SKEW_PROPERTY		"amd,serdes-pq-skew"
+#define XGBE_TX_AMP_PROPERTY		"amd,serdes-tx-amp"
+#define XGBE_DFE_CFG_PROPERTY		"amd,serdes-dfe-tap-config"
+#define XGBE_DFE_ENA_PROPERTY		"amd,serdes-dfe-tap-enable"
+
+/* Default SerDes settings */
+#define XGBE_SPEED_1000_BLWC		1
+#define XGBE_SPEED_1000_CDR		0x2
+#define XGBE_SPEED_1000_PLL		0x0
+#define XGBE_SPEED_1000_PQ		0xa
+#define XGBE_SPEED_1000_RATE		0x3
+#define XGBE_SPEED_1000_TXAMP		0xf
+#define XGBE_SPEED_1000_WORD		0x1
+#define XGBE_SPEED_1000_DFE_TAP_CONFIG	0x3
+#define XGBE_SPEED_1000_DFE_TAP_ENABLE	0x0
+
+#define XGBE_SPEED_2500_BLWC		1
+#define XGBE_SPEED_2500_CDR		0x2
+#define XGBE_SPEED_2500_PLL		0x0
+#define XGBE_SPEED_2500_PQ		0xa
+#define XGBE_SPEED_2500_RATE		0x1
+#define XGBE_SPEED_2500_TXAMP		0xf
+#define XGBE_SPEED_2500_WORD		0x1
+#define XGBE_SPEED_2500_DFE_TAP_CONFIG	0x3
+#define XGBE_SPEED_2500_DFE_TAP_ENABLE	0x0
+
+#define XGBE_SPEED_10000_BLWC		0
+#define XGBE_SPEED_10000_CDR		0x7
+#define XGBE_SPEED_10000_PLL		0x1
+#define XGBE_SPEED_10000_PQ		0x12
+#define XGBE_SPEED_10000_RATE		0x0
+#define XGBE_SPEED_10000_TXAMP		0xa
+#define XGBE_SPEED_10000_WORD		0x7
+#define XGBE_SPEED_10000_DFE_TAP_CONFIG	0x1
+#define XGBE_SPEED_10000_DFE_TAP_ENABLE	0x7f
+
+/* Rate-change complete wait/retry count */
+#define XGBE_RATECHANGE_COUNT		500
+
+static const u32 xgbe_phy_blwc[] = {
+	XGBE_SPEED_1000_BLWC,
+	XGBE_SPEED_2500_BLWC,
+	XGBE_SPEED_10000_BLWC,
+};
+
+static const u32 xgbe_phy_cdr_rate[] = {
+	XGBE_SPEED_1000_CDR,
+	XGBE_SPEED_2500_CDR,
+	XGBE_SPEED_10000_CDR,
+};
+
+static const u32 xgbe_phy_pq_skew[] = {
+	XGBE_SPEED_1000_PQ,
+	XGBE_SPEED_2500_PQ,
+	XGBE_SPEED_10000_PQ,
+};
+
+static const u32 xgbe_phy_tx_amp[] = {
+	XGBE_SPEED_1000_TXAMP,
+	XGBE_SPEED_2500_TXAMP,
+	XGBE_SPEED_10000_TXAMP,
+};
+
+static const u32 xgbe_phy_dfe_tap_cfg[] = {
+	XGBE_SPEED_1000_DFE_TAP_CONFIG,
+	XGBE_SPEED_2500_DFE_TAP_CONFIG,
+	XGBE_SPEED_10000_DFE_TAP_CONFIG,
+};
+
+static const u32 xgbe_phy_dfe_tap_ena[] = {
+	XGBE_SPEED_1000_DFE_TAP_ENABLE,
+	XGBE_SPEED_2500_DFE_TAP_ENABLE,
+	XGBE_SPEED_10000_DFE_TAP_ENABLE,
+};
+
+struct xgbe_phy_data {
+	/* 1000/10000 vs 2500/10000 indicator */
+	unsigned int speed_set;
+
+	/* SerDes UEFI configurable settings.
+	 *   Switching between modes/speeds requires new values for some
+	 *   SerDes settings.  The values can be supplied as device
+	 *   properties in array format.  The first array entry is for
+	 *   1GbE, second for 2.5GbE and third for 10GbE
+	 */
+	u32 blwc[XGBE_SPEEDS];
+	u32 cdr_rate[XGBE_SPEEDS];
+	u32 pq_skew[XGBE_SPEEDS];
+	u32 tx_amp[XGBE_SPEEDS];
+	u32 dfe_tap_cfg[XGBE_SPEEDS];
+	u32 dfe_tap_ena[XGBE_SPEEDS];
+};
+
+static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
+{
+		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
+}
+
+static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
+{
+		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
+}
+
+static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	enum xgbe_mode mode;
+	unsigned int ad_reg, lp_reg;
+
+	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
+
+	/* Compare Advertisement and Link Partner register 1 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
+	if (lp_reg & 0x400)
+		pdata->phy.lp_advertising |= ADVERTISED_Pause;
+	if (lp_reg & 0x800)
+		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+
+	if (pdata->phy.pause_autoneg) {
+		/* Set flow control based on auto-negotiation result */
+		pdata->phy.tx_pause = 0;
+		pdata->phy.rx_pause = 0;
+
+		if (ad_reg & lp_reg & 0x400) {
+			pdata->phy.tx_pause = 1;
+			pdata->phy.rx_pause = 1;
+		} else if (ad_reg & lp_reg & 0x800) {
+			if (ad_reg & 0x400)
+				pdata->phy.rx_pause = 1;
+			else if (lp_reg & 0x400)
+				pdata->phy.tx_pause = 1;
+		}
+	}
+
+	/* Compare Advertisement and Link Partner register 2 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
+	if (lp_reg & 0x80)
+		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
+	if (lp_reg & 0x20) {
+		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+			pdata->phy.lp_advertising |= ADVERTISED_2500baseX_Full;
+		else
+			pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
+	}
+
+	ad_reg &= lp_reg;
+	if (ad_reg & 0x80) {
+		mode = XGBE_MODE_KR;
+	} else if (ad_reg & 0x20) {
+		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+			mode = XGBE_MODE_KX_2500;
+		else
+			mode = XGBE_MODE_KX_1000;
+	} else {
+		mode = XGBE_MODE_UNKNOWN;
+	}
+
+	/* Compare Advertisement and Link Partner register 3 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
+	if (lp_reg & 0xc000)
+		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
+
+	return mode;
+}
+
+static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata)
+{
+	return pdata->phy.advertising;
+}
+
+static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
+{
+	/* Nothing uniquely required for an configuration */
+	return 0;
+}
+
+static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
+{
+	return XGBE_AN_MODE_CL73;
+}
+
+static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
+{
+	unsigned int reg;
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+
+	reg |= MDIO_CTRL1_LPOWER;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+	usleep_range(75, 100);
+
+	reg &= ~MDIO_CTRL1_LPOWER;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+}
+
+static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
+{
+	/* Assert Rx and Tx ratechange */
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
+}
+
+static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
+{
+	unsigned int wait;
+	u16 status;
+
+	/* Release Rx and Tx ratechange */
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
+
+	/* Wait for Rx and Tx ready */
+	wait = XGBE_RATECHANGE_COUNT;
+	while (wait--) {
+		usleep_range(50, 75);
+
+		status = XSIR0_IOREAD(pdata, SIR0_STATUS);
+		if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
+		    XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
+			goto rx_reset;
+	}
+
+	netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
+		  status);
+
+rx_reset:
+	/* Perform Rx reset for the DFE changes */
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
+}
+
+static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int reg;
+
+	/* Set PCS to KR/10G speed */
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+	reg &= ~MDIO_PCS_CTRL2_TYPE;
+	reg |= MDIO_PCS_CTRL2_10GBR;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+	reg &= ~MDIO_CTRL1_SPEEDSEL;
+	reg |= MDIO_CTRL1_SPEED10G;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+	xgbe_phy_pcs_power_cycle(pdata);
+
+	/* Set SerDes to 10G speed */
+	xgbe_phy_start_ratechange(pdata);
+
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
+
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+			   phy_data->cdr_rate[XGBE_SPEED_10000]);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+			   phy_data->tx_amp[XGBE_SPEED_10000]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+			   phy_data->blwc[XGBE_SPEED_10000]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+			   phy_data->pq_skew[XGBE_SPEED_10000]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+			   phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
+	XRXTX_IOWRITE(pdata, RXTX_REG22,
+		      phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
+}
+
+static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int reg;
+
+	/* Set PCS to KX/1G speed */
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+	reg &= ~MDIO_PCS_CTRL2_TYPE;
+	reg |= MDIO_PCS_CTRL2_10GBX;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+	reg &= ~MDIO_CTRL1_SPEEDSEL;
+	reg |= MDIO_CTRL1_SPEED1G;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+	xgbe_phy_pcs_power_cycle(pdata);
+
+	/* Set SerDes to 2.5G speed */
+	xgbe_phy_start_ratechange(pdata);
+
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
+
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+			   phy_data->cdr_rate[XGBE_SPEED_2500]);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+			   phy_data->tx_amp[XGBE_SPEED_2500]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+			   phy_data->blwc[XGBE_SPEED_2500]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+			   phy_data->pq_skew[XGBE_SPEED_2500]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+			   phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
+	XRXTX_IOWRITE(pdata, RXTX_REG22,
+		      phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
+}
+
+static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int reg;
+
+	/* Set PCS to KX/1G speed */
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+	reg &= ~MDIO_PCS_CTRL2_TYPE;
+	reg |= MDIO_PCS_CTRL2_10GBX;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+	reg &= ~MDIO_CTRL1_SPEEDSEL;
+	reg |= MDIO_CTRL1_SPEED1G;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+	xgbe_phy_pcs_power_cycle(pdata);
+
+	/* Set SerDes to 1G speed */
+	xgbe_phy_start_ratechange(pdata);
+
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
+
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
+			   phy_data->cdr_rate[XGBE_SPEED_1000]);
+	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
+			   phy_data->tx_amp[XGBE_SPEED_1000]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
+			   phy_data->blwc[XGBE_SPEED_1000]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
+			   phy_data->pq_skew[XGBE_SPEED_1000]);
+	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
+			   phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
+	XRXTX_IOWRITE(pdata, RXTX_REG22,
+		      phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
+}
+
+static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	enum xgbe_mode mode;
+	unsigned int reg;
+
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
+	reg &= MDIO_PCS_CTRL2_TYPE;
+
+	if (reg == MDIO_PCS_CTRL2_10GBR) {
+		mode = XGBE_MODE_KR;
+	} else {
+		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+			mode = XGBE_MODE_KX_2500;
+		else
+			mode = XGBE_MODE_KX_1000;
+	}
+
+	return mode;
+}
+
+static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	enum xgbe_mode mode;
+
+	/* If we are in KR switch to KX, and vice-versa */
+	if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
+		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+			mode = XGBE_MODE_KX_2500;
+		else
+			mode = XGBE_MODE_KX_1000;
+	} else {
+		mode = XGBE_MODE_KR;
+	}
+
+	return mode;
+}
+
+static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
+					int speed)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (speed) {
+	case SPEED_1000:
+		return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
+			? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN;
+	case SPEED_2500:
+		return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
+			? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN;
+	case SPEED_10000:
+		return XGBE_MODE_KR;
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_KX_1000:
+		xgbe_phy_kx_1000_mode(pdata);
+		break;
+	case XGBE_MODE_KX_2500:
+		xgbe_phy_kx_2500_mode(pdata);
+		break;
+	case XGBE_MODE_KR:
+		xgbe_phy_kr_mode(pdata);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
+				enum xgbe_mode mode, u32 advert)
+{
+	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
+		if (pdata->phy.advertising & advert)
+			return true;
+	} else {
+		enum xgbe_mode cur_mode;
+
+		cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
+		if (cur_mode == mode)
+			return true;
+	}
+
+	return false;
+}
+
+static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_KX_1000:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_1000baseKX_Full);
+	case XGBE_MODE_KX_2500:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_2500baseX_Full);
+	case XGBE_MODE_KR:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_10000baseKR_Full);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (speed) {
+	case SPEED_1000:
+		if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
+			return false;
+		return true;
+	case SPEED_2500:
+		if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
+			return false;
+		return true;
+	case SPEED_10000:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
+{
+	unsigned int reg;
+
+	*an_restart = 0;
+
+	/* Link status is latched low, so read once to clear
+	 * and then read again to get current state
+	 */
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+
+	return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
+}
+
+static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
+{
+	/* Nothing uniquely required for stop */
+}
+
+static int xgbe_phy_start(struct xgbe_prv_data *pdata)
+{
+	/* Nothing uniquely required for start */
+	return 0;
+}
+
+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
+{
+	unsigned int reg, count;
+
+	/* Perform a software reset of the PCS */
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+	reg |= MDIO_CTRL1_RESET;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
+
+	count = 50;
+	do {
+		msleep(20);
+		reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+	} while ((reg & MDIO_CTRL1_RESET) && --count);
+
+	if (reg & MDIO_CTRL1_RESET)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+	/* Nothing uniquely required for exit */
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data;
+	int ret;
+
+	phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
+	if (!phy_data)
+		return -ENOMEM;
+
+	/* Retrieve the PHY speedset */
+	ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY,
+				       &phy_data->speed_set);
+	if (ret) {
+		dev_err(pdata->dev, "invalid %s property\n",
+			XGBE_SPEEDSET_PROPERTY);
+		return ret;
+	}
+
+	switch (phy_data->speed_set) {
+	case XGBE_SPEEDSET_1000_10000:
+	case XGBE_SPEEDSET_2500_10000:
+		break;
+	default:
+		dev_err(pdata->dev, "invalid %s property\n",
+			XGBE_SPEEDSET_PROPERTY);
+		return -EINVAL;
+	}
+
+	/* Retrieve the PHY configuration properties */
+	if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {
+		ret = device_property_read_u32_array(pdata->phy_dev,
+						     XGBE_BLWC_PROPERTY,
+						     phy_data->blwc,
+						     XGBE_SPEEDS);
+		if (ret) {
+			dev_err(pdata->dev, "invalid %s property\n",
+				XGBE_BLWC_PROPERTY);
+			return ret;
+		}
+	} else {
+		memcpy(phy_data->blwc, xgbe_phy_blwc,
+		       sizeof(phy_data->blwc));
+	}
+
+	if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) {
+		ret = device_property_read_u32_array(pdata->phy_dev,
+						     XGBE_CDR_RATE_PROPERTY,
+						     phy_data->cdr_rate,
+						     XGBE_SPEEDS);
+		if (ret) {
+			dev_err(pdata->dev, "invalid %s property\n",
+				XGBE_CDR_RATE_PROPERTY);
+			return ret;
+		}
+	} else {
+		memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate,
+		       sizeof(phy_data->cdr_rate));
+	}
+
+	if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
+		ret = device_property_read_u32_array(pdata->phy_dev,
+						     XGBE_PQ_SKEW_PROPERTY,
+						     phy_data->pq_skew,
+						     XGBE_SPEEDS);
+		if (ret) {
+			dev_err(pdata->dev, "invalid %s property\n",
+				XGBE_PQ_SKEW_PROPERTY);
+			return ret;
+		}
+	} else {
+		memcpy(phy_data->pq_skew, xgbe_phy_pq_skew,
+		       sizeof(phy_data->pq_skew));
+	}
+
+	if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) {
+		ret = device_property_read_u32_array(pdata->phy_dev,
+						     XGBE_TX_AMP_PROPERTY,
+						     phy_data->tx_amp,
+						     XGBE_SPEEDS);
+		if (ret) {
+			dev_err(pdata->dev, "invalid %s property\n",
+				XGBE_TX_AMP_PROPERTY);
+			return ret;
+		}
+	} else {
+		memcpy(phy_data->tx_amp, xgbe_phy_tx_amp,
+		       sizeof(phy_data->tx_amp));
+	}
+
+	if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) {
+		ret = device_property_read_u32_array(pdata->phy_dev,
+						     XGBE_DFE_CFG_PROPERTY,
+						     phy_data->dfe_tap_cfg,
+						     XGBE_SPEEDS);
+		if (ret) {
+			dev_err(pdata->dev, "invalid %s property\n",
+				XGBE_DFE_CFG_PROPERTY);
+			return ret;
+		}
+	} else {
+		memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg,
+		       sizeof(phy_data->dfe_tap_cfg));
+	}
+
+	if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) {
+		ret = device_property_read_u32_array(pdata->phy_dev,
+						     XGBE_DFE_ENA_PROPERTY,
+						     phy_data->dfe_tap_ena,
+						     XGBE_SPEEDS);
+		if (ret) {
+			dev_err(pdata->dev, "invalid %s property\n",
+				XGBE_DFE_ENA_PROPERTY);
+			return ret;
+		}
+	} else {
+		memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena,
+		       sizeof(phy_data->dfe_tap_ena));
+	}
+
+	/* Initialize supported features */
+	pdata->phy.supported = SUPPORTED_Autoneg;
+	pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+	pdata->phy.supported |= SUPPORTED_Backplane;
+	pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
+	switch (phy_data->speed_set) {
+	case XGBE_SPEEDSET_1000_10000:
+		pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
+		break;
+	case XGBE_SPEEDSET_2500_10000:
+		pdata->phy.supported |= SUPPORTED_2500baseX_Full;
+		break;
+	}
+
+	if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+		pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
+
+	pdata->phy_data = phy_data;
+
+	return 0;
+}
+
+void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
+{
+	struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
+
+	phy_impl->init			= xgbe_phy_init;
+	phy_impl->exit			= xgbe_phy_exit;
+
+	phy_impl->reset			= xgbe_phy_reset;
+	phy_impl->start			= xgbe_phy_start;
+	phy_impl->stop			= xgbe_phy_stop;
+
+	phy_impl->link_status		= xgbe_phy_link_status;
+
+	phy_impl->valid_speed		= xgbe_phy_valid_speed;
+
+	phy_impl->use_mode		= xgbe_phy_use_mode;
+	phy_impl->set_mode		= xgbe_phy_set_mode;
+	phy_impl->get_mode		= xgbe_phy_get_mode;
+	phy_impl->switch_mode		= xgbe_phy_switch_mode;
+	phy_impl->cur_mode		= xgbe_phy_cur_mode;
+
+	phy_impl->an_mode		= xgbe_phy_an_mode;
+
+	phy_impl->an_config		= xgbe_phy_an_config;
+
+	phy_impl->an_advertising	= xgbe_phy_an_advertising;
+
+	phy_impl->an_outcome		= xgbe_phy_an_outcome;
+
+	phy_impl->kr_training_pre	= xgbe_phy_kr_training_pre;
+	phy_impl->kr_training_post	= xgbe_phy_kr_training_post;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3084 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Advanced Micro Devices, Inc. nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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 file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ *     THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kmod.h>
+#include <linux/mdio.h>
+#include <linux/phy.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#define XGBE_PHY_PORT_SPEED_100		BIT(0)
+#define XGBE_PHY_PORT_SPEED_1000	BIT(1)
+#define XGBE_PHY_PORT_SPEED_2500	BIT(2)
+#define XGBE_PHY_PORT_SPEED_10000	BIT(3)
+
+#define XGBE_MUTEX_RELEASE		0x80000000
+
+#define XGBE_SFP_DIRECT			7
+
+/* I2C target addresses */
+#define XGBE_SFP_SERIAL_ID_ADDRESS	0x50
+#define XGBE_SFP_DIAG_INFO_ADDRESS	0x51
+#define XGBE_SFP_PHY_ADDRESS		0x56
+#define XGBE_GPIO_ADDRESS_PCA9555	0x20
+
+/* SFP sideband signal indicators */
+#define XGBE_GPIO_NO_TX_FAULT		BIT(0)
+#define XGBE_GPIO_NO_RATE_SELECT	BIT(1)
+#define XGBE_GPIO_NO_MOD_ABSENT		BIT(2)
+#define XGBE_GPIO_NO_RX_LOS		BIT(3)
+
+/* Rate-change complete wait/retry count */
+#define XGBE_RATECHANGE_COUNT		500
+
+enum xgbe_port_mode {
+	XGBE_PORT_MODE_RSVD = 0,
+	XGBE_PORT_MODE_BACKPLANE,
+	XGBE_PORT_MODE_BACKPLANE_2500,
+	XGBE_PORT_MODE_1000BASE_T,
+	XGBE_PORT_MODE_1000BASE_X,
+	XGBE_PORT_MODE_NBASE_T,
+	XGBE_PORT_MODE_10GBASE_T,
+	XGBE_PORT_MODE_10GBASE_R,
+	XGBE_PORT_MODE_SFP,
+	XGBE_PORT_MODE_MAX,
+};
+
+enum xgbe_conn_type {
+	XGBE_CONN_TYPE_NONE = 0,
+	XGBE_CONN_TYPE_SFP,
+	XGBE_CONN_TYPE_MDIO,
+	XGBE_CONN_TYPE_RSVD1,
+	XGBE_CONN_TYPE_BACKPLANE,
+	XGBE_CONN_TYPE_MAX,
+};
+
+/* SFP/SFP+ related definitions */
+enum xgbe_sfp_comm {
+	XGBE_SFP_COMM_DIRECT = 0,
+	XGBE_SFP_COMM_PCA9545,
+};
+
+enum xgbe_sfp_cable {
+	XGBE_SFP_CABLE_UNKNOWN = 0,
+	XGBE_SFP_CABLE_ACTIVE,
+	XGBE_SFP_CABLE_PASSIVE,
+};
+
+enum xgbe_sfp_base {
+	XGBE_SFP_BASE_UNKNOWN = 0,
+	XGBE_SFP_BASE_1000_T,
+	XGBE_SFP_BASE_1000_SX,
+	XGBE_SFP_BASE_1000_LX,
+	XGBE_SFP_BASE_1000_CX,
+	XGBE_SFP_BASE_10000_SR,
+	XGBE_SFP_BASE_10000_LR,
+	XGBE_SFP_BASE_10000_LRM,
+	XGBE_SFP_BASE_10000_ER,
+	XGBE_SFP_BASE_10000_CR,
+};
+
+enum xgbe_sfp_speed {
+	XGBE_SFP_SPEED_UNKNOWN = 0,
+	XGBE_SFP_SPEED_100_1000,
+	XGBE_SFP_SPEED_1000,
+	XGBE_SFP_SPEED_10000,
+};
+
+/* SFP Serial ID Base ID values relative to an offset of 0 */
+#define XGBE_SFP_BASE_ID			0
+#define XGBE_SFP_ID_SFP				0x03
+
+#define XGBE_SFP_BASE_EXT_ID			1
+#define XGBE_SFP_EXT_ID_SFP			0x04
+
+#define XGBE_SFP_BASE_10GBE_CC			3
+#define XGBE_SFP_BASE_10GBE_CC_SR		BIT(4)
+#define XGBE_SFP_BASE_10GBE_CC_LR		BIT(5)
+#define XGBE_SFP_BASE_10GBE_CC_LRM		BIT(6)
+#define XGBE_SFP_BASE_10GBE_CC_ER		BIT(7)
+
+#define XGBE_SFP_BASE_1GBE_CC			6
+#define XGBE_SFP_BASE_1GBE_CC_SX		BIT(0)
+#define XGBE_SFP_BASE_1GBE_CC_LX		BIT(1)
+#define XGBE_SFP_BASE_1GBE_CC_CX		BIT(2)
+#define XGBE_SFP_BASE_1GBE_CC_T			BIT(3)
+
+#define XGBE_SFP_BASE_CABLE			8
+#define XGBE_SFP_BASE_CABLE_PASSIVE		BIT(2)
+#define XGBE_SFP_BASE_CABLE_ACTIVE		BIT(3)
+
+#define XGBE_SFP_BASE_BR			12
+#define XGBE_SFP_BASE_BR_1GBE_MIN		0x0a
+#define XGBE_SFP_BASE_BR_1GBE_MAX		0x0d
+#define XGBE_SFP_BASE_BR_10GBE_MIN		0x64
+#define XGBE_SFP_BASE_BR_10GBE_MAX		0x68
+
+#define XGBE_SFP_BASE_CU_CABLE_LEN		18
+
+#define XGBE_SFP_BASE_VENDOR_NAME		20
+#define XGBE_SFP_BASE_VENDOR_NAME_LEN		16
+#define XGBE_SFP_BASE_VENDOR_PN			40
+#define XGBE_SFP_BASE_VENDOR_PN_LEN		16
+#define XGBE_SFP_BASE_VENDOR_REV		56
+#define XGBE_SFP_BASE_VENDOR_REV_LEN		4
+
+#define XGBE_SFP_BASE_CC			63
+
+/* SFP Serial ID Extended ID values relative to an offset of 64 */
+#define XGBE_SFP_BASE_VENDOR_SN			4
+#define XGBE_SFP_BASE_VENDOR_SN_LEN		16
+
+#define XGBE_SFP_EXTD_DIAG			28
+#define XGBE_SFP_EXTD_DIAG_ADDR_CHANGE		BIT(2)
+
+#define XGBE_SFP_EXTD_SFF_8472			30
+
+#define XGBE_SFP_EXTD_CC			31
+
+struct xgbe_sfp_eeprom {
+	u8 base[64];
+	u8 extd[32];
+	u8 vendor[32];
+};
+
+#define XGBE_BEL_FUSE_VENDOR	"BEL-FUSE        "
+#define XGBE_BEL_FUSE_PARTNO	"1GBT-SFP06      "
+
+struct xgbe_sfp_ascii {
+	union {
+		char vendor[XGBE_SFP_BASE_VENDOR_NAME_LEN + 1];
+		char partno[XGBE_SFP_BASE_VENDOR_PN_LEN + 1];
+		char rev[XGBE_SFP_BASE_VENDOR_REV_LEN + 1];
+		char serno[XGBE_SFP_BASE_VENDOR_SN_LEN + 1];
+	} u;
+};
+
+/* MDIO PHY reset types */
+enum xgbe_mdio_reset {
+	XGBE_MDIO_RESET_NONE = 0,
+	XGBE_MDIO_RESET_I2C_GPIO,
+	XGBE_MDIO_RESET_INT_GPIO,
+	XGBE_MDIO_RESET_MAX,
+};
+
+/* Re-driver related definitions */
+enum xgbe_phy_redrv_if {
+	XGBE_PHY_REDRV_IF_MDIO = 0,
+	XGBE_PHY_REDRV_IF_I2C,
+	XGBE_PHY_REDRV_IF_MAX,
+};
+
+enum xgbe_phy_redrv_model {
+	XGBE_PHY_REDRV_MODEL_4223 = 0,
+	XGBE_PHY_REDRV_MODEL_4227,
+	XGBE_PHY_REDRV_MODEL_MAX,
+};
+
+enum xgbe_phy_redrv_mode {
+	XGBE_PHY_REDRV_MODE_CX = 5,
+	XGBE_PHY_REDRV_MODE_SR = 9,
+};
+
+#define XGBE_PHY_REDRV_MODE_REG	0x12b0
+
+/* PHY related configuration information */
+struct xgbe_phy_data {
+	enum xgbe_port_mode port_mode;
+
+	unsigned int port_id;
+
+	unsigned int port_speeds;
+
+	enum xgbe_conn_type conn_type;
+
+	enum xgbe_mode cur_mode;
+	enum xgbe_mode start_mode;
+
+	unsigned int rrc_count;
+
+	unsigned int mdio_addr;
+
+	unsigned int comm_owned;
+
+	/* SFP Support */
+	enum xgbe_sfp_comm sfp_comm;
+	unsigned int sfp_mux_address;
+	unsigned int sfp_mux_channel;
+
+	unsigned int sfp_gpio_address;
+	unsigned int sfp_gpio_mask;
+	unsigned int sfp_gpio_rx_los;
+	unsigned int sfp_gpio_tx_fault;
+	unsigned int sfp_gpio_mod_absent;
+	unsigned int sfp_gpio_rate_select;
+
+	unsigned int sfp_rx_los;
+	unsigned int sfp_tx_fault;
+	unsigned int sfp_mod_absent;
+	unsigned int sfp_diags;
+	unsigned int sfp_changed;
+	unsigned int sfp_phy_avail;
+	unsigned int sfp_cable_len;
+	enum xgbe_sfp_base sfp_base;
+	enum xgbe_sfp_cable sfp_cable;
+	enum xgbe_sfp_speed sfp_speed;
+	struct xgbe_sfp_eeprom sfp_eeprom;
+
+	/* External PHY support */
+	enum xgbe_mdio_mode phydev_mode;
+	struct mii_bus *mii;
+	struct phy_device *phydev;
+	enum xgbe_mdio_reset mdio_reset;
+	unsigned int mdio_reset_addr;
+	unsigned int mdio_reset_gpio;
+
+	/* Re-driver support */
+	unsigned int redrv;
+	unsigned int redrv_if;
+	unsigned int redrv_addr;
+	unsigned int redrv_lane;
+	unsigned int redrv_model;
+};
+
+/* I2C, MDIO and GPIO lines are muxed, so only one device at a time */
+static DEFINE_MUTEX(xgbe_phy_comm_lock);
+
+static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata);
+
+static int xgbe_phy_i2c_xfer(struct xgbe_prv_data *pdata,
+			     struct xgbe_i2c_op *i2c_op)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	/* Be sure we own the bus */
+	if (WARN_ON(!phy_data->comm_owned))
+		return -EIO;
+
+	return pdata->i2c_if.i2c_xfer(pdata, i2c_op);
+}
+
+static int xgbe_phy_redrv_write(struct xgbe_prv_data *pdata, unsigned int reg,
+				unsigned int val)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	struct xgbe_i2c_op i2c_op;
+	__be16 *redrv_val;
+	u8 redrv_data[5], csum;
+	unsigned int i, retry;
+	int ret;
+
+	/* High byte of register contains read/write indicator */
+	redrv_data[0] = ((reg >> 8) & 0xff) << 1;
+	redrv_data[1] = reg & 0xff;
+	redrv_val = (__be16 *)&redrv_data[2];
+	*redrv_val = cpu_to_be16(val);
+
+	/* Calculate 1 byte checksum */
+	csum = 0;
+	for (i = 0; i < 4; i++) {
+		csum += redrv_data[i];
+		if (redrv_data[i] > csum)
+			csum++;
+	}
+	redrv_data[4] = ~csum;
+
+	retry = 1;
+again1:
+	i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+	i2c_op.target = phy_data->redrv_addr;
+	i2c_op.len = sizeof(redrv_data);
+	i2c_op.buf = redrv_data;
+	ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+	if (ret) {
+		if ((ret == -EAGAIN) && retry--)
+			goto again1;
+
+		return ret;
+	}
+
+	retry = 1;
+again2:
+	i2c_op.cmd = XGBE_I2C_CMD_READ;
+	i2c_op.target = phy_data->redrv_addr;
+	i2c_op.len = 1;
+	i2c_op.buf = redrv_data;
+	ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+	if (ret) {
+		if ((ret == -EAGAIN) && retry--)
+			goto again2;
+
+		return ret;
+	}
+
+	if (redrv_data[0] != 0xff) {
+		netif_dbg(pdata, drv, pdata->netdev,
+			  "Redriver write checksum error\n");
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+static int xgbe_phy_i2c_write(struct xgbe_prv_data *pdata, unsigned int target,
+			      void *val, unsigned int val_len)
+{
+	struct xgbe_i2c_op i2c_op;
+	int retry, ret;
+
+	retry = 1;
+again:
+	/* Write the specfied register */
+	i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+	i2c_op.target = target;
+	i2c_op.len = val_len;
+	i2c_op.buf = val;
+	ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+	if ((ret == -EAGAIN) && retry--)
+		goto again;
+
+	return ret;
+}
+
+static int xgbe_phy_i2c_read(struct xgbe_prv_data *pdata, unsigned int target,
+			     void *reg, unsigned int reg_len,
+			     void *val, unsigned int val_len)
+{
+	struct xgbe_i2c_op i2c_op;
+	int retry, ret;
+
+	retry = 1;
+again1:
+	/* Set the specified register to read */
+	i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+	i2c_op.target = target;
+	i2c_op.len = reg_len;
+	i2c_op.buf = reg;
+	ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+	if (ret) {
+		if ((ret == -EAGAIN) && retry--)
+			goto again1;
+
+		return ret;
+	}
+
+	retry = 1;
+again2:
+	/* Read the specfied register */
+	i2c_op.cmd = XGBE_I2C_CMD_READ;
+	i2c_op.target = target;
+	i2c_op.len = val_len;
+	i2c_op.buf = val;
+	ret = xgbe_phy_i2c_xfer(pdata, &i2c_op);
+	if ((ret == -EAGAIN) && retry--)
+		goto again2;
+
+	return ret;
+}
+
+static int xgbe_phy_sfp_put_mux(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	struct xgbe_i2c_op i2c_op;
+	u8 mux_channel;
+
+	if (phy_data->sfp_comm == XGBE_SFP_COMM_DIRECT)
+		return 0;
+
+	/* Select no mux channels */
+	mux_channel = 0;
+	i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+	i2c_op.target = phy_data->sfp_mux_address;
+	i2c_op.len = sizeof(mux_channel);
+	i2c_op.buf = &mux_channel;
+
+	return xgbe_phy_i2c_xfer(pdata, &i2c_op);
+}
+
+static int xgbe_phy_sfp_get_mux(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	struct xgbe_i2c_op i2c_op;
+	u8 mux_channel;
+
+	if (phy_data->sfp_comm == XGBE_SFP_COMM_DIRECT)
+		return 0;
+
+	/* Select desired mux channel */
+	mux_channel = 1 << phy_data->sfp_mux_channel;
+	i2c_op.cmd = XGBE_I2C_CMD_WRITE;
+	i2c_op.target = phy_data->sfp_mux_address;
+	i2c_op.len = sizeof(mux_channel);
+	i2c_op.buf = &mux_channel;
+
+	return xgbe_phy_i2c_xfer(pdata, &i2c_op);
+}
+
+static void xgbe_phy_put_comm_ownership(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	phy_data->comm_owned = 0;
+
+	mutex_unlock(&xgbe_phy_comm_lock);
+}
+
+static int xgbe_phy_get_comm_ownership(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned long timeout;
+	unsigned int mutex_id;
+
+	if (phy_data->comm_owned)
+		return 0;
+
+	/* The I2C and MDIO/GPIO bus is multiplexed between multiple devices,
+	 * the driver needs to take the software mutex and then the hardware
+	 * mutexes before being able to use the busses.
+	 */
+	mutex_lock(&xgbe_phy_comm_lock);
+
+	/* Clear the mutexes */
+	XP_IOWRITE(pdata, XP_I2C_MUTEX, XGBE_MUTEX_RELEASE);
+	XP_IOWRITE(pdata, XP_MDIO_MUTEX, XGBE_MUTEX_RELEASE);
+
+	/* Mutex formats are the same for I2C and MDIO/GPIO */
+	mutex_id = 0;
+	XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ID, phy_data->port_id);
+	XP_SET_BITS(mutex_id, XP_I2C_MUTEX, ACTIVE, 1);
+
+	timeout = jiffies + (5 * HZ);
+	while (time_before(jiffies, timeout)) {
+		/* Must be all zeroes in order to obtain the mutex */
+		if (XP_IOREAD(pdata, XP_I2C_MUTEX) ||
+		    XP_IOREAD(pdata, XP_MDIO_MUTEX)) {
+			usleep_range(100, 200);
+			continue;
+		}
+
+		/* Obtain the mutex */
+		XP_IOWRITE(pdata, XP_I2C_MUTEX, mutex_id);
+		XP_IOWRITE(pdata, XP_MDIO_MUTEX, mutex_id);
+
+		phy_data->comm_owned = 1;
+		return 0;
+	}
+
+	mutex_unlock(&xgbe_phy_comm_lock);
+
+	netdev_err(pdata->netdev, "unable to obtain hardware mutexes\n");
+
+	return -ETIMEDOUT;
+}
+
+static int xgbe_phy_mdio_mii_write(struct xgbe_prv_data *pdata, int addr,
+				   int reg, u16 val)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	if (reg & MII_ADDR_C45) {
+		if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
+			return -ENOTSUPP;
+	} else {
+		if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
+			return -ENOTSUPP;
+	}
+
+	return pdata->hw_if.write_ext_mii_regs(pdata, addr, reg, val);
+}
+
+static int xgbe_phy_i2c_mii_write(struct xgbe_prv_data *pdata, int reg, u16 val)
+{
+	__be16 *mii_val;
+	u8 mii_data[3];
+	int ret;
+
+	ret = xgbe_phy_sfp_get_mux(pdata);
+	if (ret)
+		return ret;
+
+	mii_data[0] = reg & 0xff;
+	mii_val = (__be16 *)&mii_data[1];
+	*mii_val = cpu_to_be16(val);
+
+	ret = xgbe_phy_i2c_write(pdata, XGBE_SFP_PHY_ADDRESS,
+				 mii_data, sizeof(mii_data));
+
+	xgbe_phy_sfp_put_mux(pdata);
+
+	return ret;
+}
+
+static int xgbe_phy_mii_write(struct mii_bus *mii, int addr, int reg, u16 val)
+{
+	struct xgbe_prv_data *pdata = mii->priv;
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int ret;
+
+	ret = xgbe_phy_get_comm_ownership(pdata);
+	if (ret)
+		return ret;
+
+	if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
+		ret = xgbe_phy_i2c_mii_write(pdata, reg, val);
+	else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
+		ret = xgbe_phy_mdio_mii_write(pdata, addr, reg, val);
+	else
+		ret = -ENOTSUPP;
+
+	xgbe_phy_put_comm_ownership(pdata);
+
+	return ret;
+}
+
+static int xgbe_phy_mdio_mii_read(struct xgbe_prv_data *pdata, int addr,
+				  int reg)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	if (reg & MII_ADDR_C45) {
+		if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL45)
+			return -ENOTSUPP;
+	} else {
+		if (phy_data->phydev_mode != XGBE_MDIO_MODE_CL22)
+			return -ENOTSUPP;
+	}
+
+	return pdata->hw_if.read_ext_mii_regs(pdata, addr, reg);
+}
+
+static int xgbe_phy_i2c_mii_read(struct xgbe_prv_data *pdata, int reg)
+{
+	__be16 mii_val;
+	u8 mii_reg;
+	int ret;
+
+	ret = xgbe_phy_sfp_get_mux(pdata);
+	if (ret)
+		return ret;
+
+	mii_reg = reg;
+	ret = xgbe_phy_i2c_read(pdata, XGBE_SFP_PHY_ADDRESS,
+				&mii_reg, sizeof(mii_reg),
+				&mii_val, sizeof(mii_val));
+	if (!ret)
+		ret = be16_to_cpu(mii_val);
+
+	xgbe_phy_sfp_put_mux(pdata);
+
+	return ret;
+}
+
+static int xgbe_phy_mii_read(struct mii_bus *mii, int addr, int reg)
+{
+	struct xgbe_prv_data *pdata = mii->priv;
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int ret;
+
+	ret = xgbe_phy_get_comm_ownership(pdata);
+	if (ret)
+		return ret;
+
+	if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
+		ret = xgbe_phy_i2c_mii_read(pdata, reg);
+	else if (phy_data->conn_type & XGBE_CONN_TYPE_MDIO)
+		ret = xgbe_phy_mdio_mii_read(pdata, addr, reg);
+	else
+		ret = -ENOTSUPP;
+
+	xgbe_phy_put_comm_ownership(pdata);
+
+	return ret;
+}
+
+static void xgbe_phy_sfp_phy_settings(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	if (phy_data->sfp_mod_absent) {
+		pdata->phy.speed = SPEED_UNKNOWN;
+		pdata->phy.duplex = DUPLEX_UNKNOWN;
+		pdata->phy.autoneg = AUTONEG_ENABLE;
+		pdata->phy.advertising = pdata->phy.supported;
+	}
+
+	pdata->phy.advertising &= ~ADVERTISED_Autoneg;
+	pdata->phy.advertising &= ~ADVERTISED_TP;
+	pdata->phy.advertising &= ~ADVERTISED_FIBRE;
+	pdata->phy.advertising &= ~ADVERTISED_100baseT_Full;
+	pdata->phy.advertising &= ~ADVERTISED_1000baseT_Full;
+	pdata->phy.advertising &= ~ADVERTISED_10000baseT_Full;
+	pdata->phy.advertising &= ~ADVERTISED_10000baseR_FEC;
+
+	switch (phy_data->sfp_base) {
+	case XGBE_SFP_BASE_1000_T:
+	case XGBE_SFP_BASE_1000_SX:
+	case XGBE_SFP_BASE_1000_LX:
+	case XGBE_SFP_BASE_1000_CX:
+		pdata->phy.speed = SPEED_UNKNOWN;
+		pdata->phy.duplex = DUPLEX_UNKNOWN;
+		pdata->phy.autoneg = AUTONEG_ENABLE;
+		pdata->phy.advertising |= ADVERTISED_Autoneg;
+		break;
+	case XGBE_SFP_BASE_10000_SR:
+	case XGBE_SFP_BASE_10000_LR:
+	case XGBE_SFP_BASE_10000_LRM:
+	case XGBE_SFP_BASE_10000_ER:
+	case XGBE_SFP_BASE_10000_CR:
+	default:
+		pdata->phy.speed = SPEED_10000;
+		pdata->phy.duplex = DUPLEX_FULL;
+		pdata->phy.autoneg = AUTONEG_DISABLE;
+		break;
+	}
+
+	switch (phy_data->sfp_base) {
+	case XGBE_SFP_BASE_1000_T:
+	case XGBE_SFP_BASE_1000_CX:
+	case XGBE_SFP_BASE_10000_CR:
+		pdata->phy.advertising |= ADVERTISED_TP;
+		break;
+	default:
+		pdata->phy.advertising |= ADVERTISED_FIBRE;
+	}
+
+	switch (phy_data->sfp_speed) {
+	case XGBE_SFP_SPEED_100_1000:
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
+			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+		break;
+	case XGBE_SFP_SPEED_1000:
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+		break;
+	case XGBE_SFP_SPEED_10000:
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
+			pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
+		break;
+	default:
+		/* Choose the fastest supported speed */
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
+			pdata->phy.advertising |= ADVERTISED_10000baseT_Full;
+		else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+			pdata->phy.advertising |= ADVERTISED_1000baseT_Full;
+		else if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
+			pdata->phy.advertising |= ADVERTISED_100baseT_Full;
+	}
+}
+
+static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom,
+				  enum xgbe_sfp_speed sfp_speed)
+{
+	u8 *sfp_base, min, max;
+
+	sfp_base = sfp_eeprom->base;
+
+	switch (sfp_speed) {
+	case XGBE_SFP_SPEED_1000:
+		min = XGBE_SFP_BASE_BR_1GBE_MIN;
+		max = XGBE_SFP_BASE_BR_1GBE_MAX;
+		break;
+	case XGBE_SFP_SPEED_10000:
+		min = XGBE_SFP_BASE_BR_10GBE_MIN;
+		max = XGBE_SFP_BASE_BR_10GBE_MAX;
+		break;
+	default:
+		return false;
+	}
+
+	return ((sfp_base[XGBE_SFP_BASE_BR] >= min) &&
+		(sfp_base[XGBE_SFP_BASE_BR] <= max));
+}
+
+static void xgbe_phy_free_phy_device(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	if (phy_data->phydev) {
+		phy_detach(phy_data->phydev);
+		phy_device_remove(phy_data->phydev);
+		phy_device_free(phy_data->phydev);
+		phy_data->phydev = NULL;
+	}
+}
+
+static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int phy_id = phy_data->phydev->phy_id;
+
+	if ((phy_id & 0xfffffff0) != 0x01ff0cc0)
+		return false;
+
+	/* Enable Base-T AN */
+	phy_write(phy_data->phydev, 0x16, 0x0001);
+	phy_write(phy_data->phydev, 0x00, 0x9140);
+	phy_write(phy_data->phydev, 0x16, 0x0000);
+
+	/* Enable SGMII at 100Base-T/1000Base-T Full Duplex */
+	phy_write(phy_data->phydev, 0x1b, 0x9084);
+	phy_write(phy_data->phydev, 0x09, 0x0e00);
+	phy_write(phy_data->phydev, 0x00, 0x8140);
+	phy_write(phy_data->phydev, 0x04, 0x0d01);
+	phy_write(phy_data->phydev, 0x00, 0x9140);
+
+	phy_data->phydev->supported = PHY_GBIT_FEATURES;
+	phy_data->phydev->supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+	phy_data->phydev->advertising = phy_data->phydev->supported;
+
+	netif_dbg(pdata, drv, pdata->netdev,
+		  "Finisar PHY quirk in place\n");
+
+	return true;
+}
+
+static void xgbe_phy_external_phy_quirks(struct xgbe_prv_data *pdata)
+{
+	if (xgbe_phy_finisar_phy_quirks(pdata))
+		return;
+}
+
+static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	struct phy_device *phydev;
+	int ret;
+
+	/* If we already have a PHY, just return */
+	if (phy_data->phydev)
+		return 0;
+
+	/* Check for the use of an external PHY */
+	if (phy_data->phydev_mode == XGBE_MDIO_MODE_NONE)
+		return 0;
+
+	/* For SFP, only use an external PHY if available */
+	if ((phy_data->port_mode == XGBE_PORT_MODE_SFP) &&
+	    !phy_data->sfp_phy_avail)
+		return 0;
+
+	/* Create and connect to the PHY device */
+	phydev = get_phy_device(phy_data->mii, phy_data->mdio_addr,
+				(phy_data->phydev_mode == XGBE_MDIO_MODE_CL45));
+	if (IS_ERR(phydev)) {
+		netdev_err(pdata->netdev, "get_phy_device failed\n");
+		return -ENODEV;
+	}
+	netif_dbg(pdata, drv, pdata->netdev, "external PHY id is %#010x\n",
+		  phydev->phy_id);
+
+	/*TODO: If c45, add request_module based on one of the MMD ids? */
+
+	ret = phy_device_register(phydev);
+	if (ret) {
+		netdev_err(pdata->netdev, "phy_device_register failed\n");
+		phy_device_free(phydev);
+		return ret;
+	}
+
+	ret = phy_attach_direct(pdata->netdev, phydev, phydev->dev_flags,
+				PHY_INTERFACE_MODE_SGMII);
+	if (ret) {
+		netdev_err(pdata->netdev, "phy_attach_direct failed\n");
+		phy_device_remove(phydev);
+		phy_device_free(phydev);
+		return ret;
+	}
+	phy_data->phydev = phydev;
+
+	xgbe_phy_external_phy_quirks(pdata);
+	phydev->advertising &= pdata->phy.advertising;
+
+	phy_start_aneg(phy_data->phydev);
+
+	return 0;
+}
+
+static void xgbe_phy_sfp_external_phy(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int ret;
+
+	if (!phy_data->sfp_changed)
+		return;
+
+	phy_data->sfp_phy_avail = 0;
+
+	if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
+		return;
+
+	/* Check access to the PHY by reading CTRL1 */
+	ret = xgbe_phy_i2c_mii_read(pdata, MII_BMCR);
+	if (ret < 0)
+		return;
+
+	/* Successfully accessed the PHY */
+	phy_data->sfp_phy_avail = 1;
+}
+
+static bool xgbe_phy_belfuse_parse_quirks(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
+
+	if (memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
+		   XGBE_BEL_FUSE_VENDOR, XGBE_SFP_BASE_VENDOR_NAME_LEN))
+		return false;
+
+	if (!memcmp(&sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
+		    XGBE_BEL_FUSE_PARTNO, XGBE_SFP_BASE_VENDOR_PN_LEN)) {
+		phy_data->sfp_base = XGBE_SFP_BASE_1000_SX;
+		phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
+		phy_data->sfp_speed = XGBE_SFP_SPEED_1000;
+		if (phy_data->sfp_changed)
+			netif_dbg(pdata, drv, pdata->netdev,
+				  "Bel-Fuse SFP quirk in place\n");
+		return true;
+	}
+
+	return false;
+}
+
+static bool xgbe_phy_sfp_parse_quirks(struct xgbe_prv_data *pdata)
+{
+	if (xgbe_phy_belfuse_parse_quirks(pdata))
+		return true;
+
+	return false;
+}
+
+static void xgbe_phy_sfp_parse_eeprom(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
+	u8 *sfp_base;
+
+	sfp_base = sfp_eeprom->base;
+
+	if (sfp_base[XGBE_SFP_BASE_ID] != XGBE_SFP_ID_SFP)
+		return;
+
+	if (sfp_base[XGBE_SFP_BASE_EXT_ID] != XGBE_SFP_EXT_ID_SFP)
+		return;
+
+	if (xgbe_phy_sfp_parse_quirks(pdata))
+		return;
+
+	/* Assume ACTIVE cable unless told it is PASSIVE */
+	if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) {
+		phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE;
+		phy_data->sfp_cable_len = sfp_base[XGBE_SFP_BASE_CU_CABLE_LEN];
+	} else {
+		phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
+	}
+
+	/* Determine the type of SFP */
+	if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR)
+		phy_data->sfp_base = XGBE_SFP_BASE_10000_SR;
+	else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LR)
+		phy_data->sfp_base = XGBE_SFP_BASE_10000_LR;
+	else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LRM)
+		phy_data->sfp_base = XGBE_SFP_BASE_10000_LRM;
+	else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_ER)
+		phy_data->sfp_base = XGBE_SFP_BASE_10000_ER;
+	else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_SX)
+		phy_data->sfp_base = XGBE_SFP_BASE_1000_SX;
+	else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_LX)
+		phy_data->sfp_base = XGBE_SFP_BASE_1000_LX;
+	else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_CX)
+		phy_data->sfp_base = XGBE_SFP_BASE_1000_CX;
+	else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_T)
+		phy_data->sfp_base = XGBE_SFP_BASE_1000_T;
+	else if ((phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE) &&
+		 xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000))
+		phy_data->sfp_base = XGBE_SFP_BASE_10000_CR;
+
+	switch (phy_data->sfp_base) {
+	case XGBE_SFP_BASE_1000_T:
+		phy_data->sfp_speed = XGBE_SFP_SPEED_100_1000;
+		break;
+	case XGBE_SFP_BASE_1000_SX:
+	case XGBE_SFP_BASE_1000_LX:
+	case XGBE_SFP_BASE_1000_CX:
+		phy_data->sfp_speed = XGBE_SFP_SPEED_1000;
+		break;
+	case XGBE_SFP_BASE_10000_SR:
+	case XGBE_SFP_BASE_10000_LR:
+	case XGBE_SFP_BASE_10000_LRM:
+	case XGBE_SFP_BASE_10000_ER:
+	case XGBE_SFP_BASE_10000_CR:
+		phy_data->sfp_speed = XGBE_SFP_SPEED_10000;
+		break;
+	default:
+		break;
+	}
+}
+
+static void xgbe_phy_sfp_eeprom_info(struct xgbe_prv_data *pdata,
+				     struct xgbe_sfp_eeprom *sfp_eeprom)
+{
+	struct xgbe_sfp_ascii sfp_ascii;
+	char *sfp_data = (char *)&sfp_ascii;
+
+	netif_dbg(pdata, drv, pdata->netdev, "SFP detected:\n");
+	memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_NAME],
+	       XGBE_SFP_BASE_VENDOR_NAME_LEN);
+	sfp_data[XGBE_SFP_BASE_VENDOR_NAME_LEN] = '\0';
+	netif_dbg(pdata, drv, pdata->netdev, "  vendor:         %s\n",
+		  sfp_data);
+
+	memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_PN],
+	       XGBE_SFP_BASE_VENDOR_PN_LEN);
+	sfp_data[XGBE_SFP_BASE_VENDOR_PN_LEN] = '\0';
+	netif_dbg(pdata, drv, pdata->netdev, "  part number:    %s\n",
+		  sfp_data);
+
+	memcpy(sfp_data, &sfp_eeprom->base[XGBE_SFP_BASE_VENDOR_REV],
+	       XGBE_SFP_BASE_VENDOR_REV_LEN);
+	sfp_data[XGBE_SFP_BASE_VENDOR_REV_LEN] = '\0';
+	netif_dbg(pdata, drv, pdata->netdev, "  revision level: %s\n",
+		  sfp_data);
+
+	memcpy(sfp_data, &sfp_eeprom->extd[XGBE_SFP_BASE_VENDOR_SN],
+	       XGBE_SFP_BASE_VENDOR_SN_LEN);
+	sfp_data[XGBE_SFP_BASE_VENDOR_SN_LEN] = '\0';
+	netif_dbg(pdata, drv, pdata->netdev, "  serial number:  %s\n",
+		  sfp_data);
+}
+
+static bool xgbe_phy_sfp_verify_eeprom(u8 cc_in, u8 *buf, unsigned int len)
+{
+	u8 cc;
+
+	for (cc = 0; len; buf++, len--)
+		cc += *buf;
+
+	return (cc == cc_in) ? true : false;
+}
+
+static int xgbe_phy_sfp_read_eeprom(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	struct xgbe_sfp_eeprom sfp_eeprom;
+	u8 eeprom_addr;
+	int ret;
+
+	ret = xgbe_phy_sfp_get_mux(pdata);
+	if (ret) {
+		netdev_err(pdata->netdev, "I2C error setting SFP MUX\n");
+		return ret;
+	}
+
+	/* Read the SFP serial ID eeprom */
+	eeprom_addr = 0;
+	ret = xgbe_phy_i2c_read(pdata, XGBE_SFP_SERIAL_ID_ADDRESS,
+				&eeprom_addr, sizeof(eeprom_addr),
+				&sfp_eeprom, sizeof(sfp_eeprom));
+	if (ret) {
+		netdev_err(pdata->netdev, "I2C error reading SFP EEPROM\n");
+		goto put;
+	}
+
+	/* Validate the contents read */
+	if (!xgbe_phy_sfp_verify_eeprom(sfp_eeprom.base[XGBE_SFP_BASE_CC],
+					sfp_eeprom.base,
+					sizeof(sfp_eeprom.base) - 1)) {
+		ret = -EINVAL;
+		goto put;
+	}
+
+	if (!xgbe_phy_sfp_verify_eeprom(sfp_eeprom.extd[XGBE_SFP_EXTD_CC],
+					sfp_eeprom.extd,
+					sizeof(sfp_eeprom.extd) - 1)) {
+		ret = -EINVAL;
+		goto put;
+	}
+
+	/* Check for an added or changed SFP */
+	if (memcmp(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom))) {
+		phy_data->sfp_changed = 1;
+
+		if (netif_msg_drv(pdata))
+			xgbe_phy_sfp_eeprom_info(pdata, &sfp_eeprom);
+
+		memcpy(&phy_data->sfp_eeprom, &sfp_eeprom, sizeof(sfp_eeprom));
+
+		if (sfp_eeprom.extd[XGBE_SFP_EXTD_SFF_8472]) {
+			u8 diag_type = sfp_eeprom.extd[XGBE_SFP_EXTD_DIAG];
+
+			if (!(diag_type & XGBE_SFP_EXTD_DIAG_ADDR_CHANGE))
+				phy_data->sfp_diags = 1;
+		}
+
+		xgbe_phy_free_phy_device(pdata);
+	} else {
+		phy_data->sfp_changed = 0;
+	}
+
+put:
+	xgbe_phy_sfp_put_mux(pdata);
+
+	return ret;
+}
+
+static void xgbe_phy_sfp_signals(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int gpio_input;
+	u8 gpio_reg, gpio_ports[2];
+	int ret;
+
+	/* Read the input port registers */
+	gpio_reg = 0;
+	ret = xgbe_phy_i2c_read(pdata, phy_data->sfp_gpio_address,
+				&gpio_reg, sizeof(gpio_reg),
+				gpio_ports, sizeof(gpio_ports));
+	if (ret) {
+		netdev_err(pdata->netdev, "I2C error reading SFP GPIOs\n");
+		return;
+	}
+
+	gpio_input = (gpio_ports[1] << 8) | gpio_ports[0];
+
+	if (phy_data->sfp_gpio_mask & XGBE_GPIO_NO_MOD_ABSENT) {
+		/* No GPIO, just assume the module is present for now */
+		phy_data->sfp_mod_absent = 0;
+	} else {
+		if (!(gpio_input & (1 << phy_data->sfp_gpio_mod_absent)))
+			phy_data->sfp_mod_absent = 0;
+	}
+
+	if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_RX_LOS) &&
+	    (gpio_input & (1 << phy_data->sfp_gpio_rx_los)))
+		phy_data->sfp_rx_los = 1;
+
+	if (!(phy_data->sfp_gpio_mask & XGBE_GPIO_NO_TX_FAULT) &&
+	    (gpio_input & (1 << phy_data->sfp_gpio_tx_fault)))
+		phy_data->sfp_tx_fault = 1;
+}
+
+static void xgbe_phy_sfp_mod_absent(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	xgbe_phy_free_phy_device(pdata);
+
+	phy_data->sfp_mod_absent = 1;
+	phy_data->sfp_phy_avail = 0;
+	memset(&phy_data->sfp_eeprom, 0, sizeof(phy_data->sfp_eeprom));
+}
+
+static void xgbe_phy_sfp_reset(struct xgbe_phy_data *phy_data)
+{
+	phy_data->sfp_rx_los = 0;
+	phy_data->sfp_tx_fault = 0;
+	phy_data->sfp_mod_absent = 1;
+	phy_data->sfp_diags = 0;
+	phy_data->sfp_base = XGBE_SFP_BASE_UNKNOWN;
+	phy_data->sfp_cable = XGBE_SFP_CABLE_UNKNOWN;
+	phy_data->sfp_speed = XGBE_SFP_SPEED_UNKNOWN;
+}
+
+static void xgbe_phy_sfp_detect(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int ret;
+
+	/* Reset the SFP signals and info */
+	xgbe_phy_sfp_reset(phy_data);
+
+	ret = xgbe_phy_get_comm_ownership(pdata);
+	if (ret)
+		return;
+
+	/* Read the SFP signals and check for module presence */
+	xgbe_phy_sfp_signals(pdata);
+	if (phy_data->sfp_mod_absent) {
+		xgbe_phy_sfp_mod_absent(pdata);
+		goto put;
+	}
+
+	ret = xgbe_phy_sfp_read_eeprom(pdata);
+	if (ret) {
+		/* Treat any error as if there isn't an SFP plugged in */
+		xgbe_phy_sfp_reset(phy_data);
+		xgbe_phy_sfp_mod_absent(pdata);
+		goto put;
+	}
+
+	xgbe_phy_sfp_parse_eeprom(pdata);
+
+	xgbe_phy_sfp_external_phy(pdata);
+
+put:
+	xgbe_phy_sfp_phy_settings(pdata);
+
+	xgbe_phy_put_comm_ownership(pdata);
+}
+
+static void xgbe_phy_phydev_flowctrl(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	u16 lcl_adv = 0, rmt_adv = 0;
+	u8 fc;
+
+	pdata->phy.tx_pause = 0;
+	pdata->phy.rx_pause = 0;
+
+	if (!phy_data->phydev)
+		return;
+
+	if (phy_data->phydev->advertising & ADVERTISED_Pause)
+		lcl_adv |= ADVERTISE_PAUSE_CAP;
+	if (phy_data->phydev->advertising & ADVERTISED_Asym_Pause)
+		lcl_adv |= ADVERTISE_PAUSE_ASYM;
+
+	if (phy_data->phydev->pause) {
+		pdata->phy.lp_advertising |= ADVERTISED_Pause;
+		rmt_adv |= LPA_PAUSE_CAP;
+	}
+	if (phy_data->phydev->asym_pause) {
+		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+		rmt_adv |= LPA_PAUSE_ASYM;
+	}
+
+	fc = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
+	if (fc & FLOW_CTRL_TX)
+		pdata->phy.tx_pause = 1;
+	if (fc & FLOW_CTRL_RX)
+		pdata->phy.rx_pause = 1;
+}
+
+static enum xgbe_mode xgbe_phy_an37_sgmii_outcome(struct xgbe_prv_data *pdata)
+{
+	enum xgbe_mode mode;
+
+	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+	pdata->phy.lp_advertising |= ADVERTISED_TP;
+
+	/* Use external PHY to determine flow control */
+	if (pdata->phy.pause_autoneg)
+		xgbe_phy_phydev_flowctrl(pdata);
+
+	switch (pdata->an_status & XGBE_SGMII_AN_LINK_SPEED) {
+	case XGBE_SGMII_AN_LINK_SPEED_100:
+		if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
+			pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
+			mode = XGBE_MODE_SGMII_100;
+		} else {
+			/* Half-duplex not supported */
+			pdata->phy.lp_advertising |= ADVERTISED_100baseT_Half;
+			mode = XGBE_MODE_UNKNOWN;
+		}
+		break;
+	case XGBE_SGMII_AN_LINK_SPEED_1000:
+		if (pdata->an_status & XGBE_SGMII_AN_LINK_DUPLEX) {
+			pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+			mode = XGBE_MODE_SGMII_1000;
+		} else {
+			/* Half-duplex not supported */
+			pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half;
+			mode = XGBE_MODE_UNKNOWN;
+		}
+		break;
+	default:
+		mode = XGBE_MODE_UNKNOWN;
+	}
+
+	return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an37_outcome(struct xgbe_prv_data *pdata)
+{
+	enum xgbe_mode mode;
+	unsigned int ad_reg, lp_reg;
+
+	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+	pdata->phy.lp_advertising |= ADVERTISED_FIBRE;
+
+	/* Compare Advertisement and Link Partner register */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_LP_ABILITY);
+	if (lp_reg & 0x100)
+		pdata->phy.lp_advertising |= ADVERTISED_Pause;
+	if (lp_reg & 0x80)
+		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+
+	if (pdata->phy.pause_autoneg) {
+		/* Set flow control based on auto-negotiation result */
+		pdata->phy.tx_pause = 0;
+		pdata->phy.rx_pause = 0;
+
+		if (ad_reg & lp_reg & 0x100) {
+			pdata->phy.tx_pause = 1;
+			pdata->phy.rx_pause = 1;
+		} else if (ad_reg & lp_reg & 0x80) {
+			if (ad_reg & 0x100)
+				pdata->phy.rx_pause = 1;
+			else if (lp_reg & 0x100)
+				pdata->phy.tx_pause = 1;
+		}
+	}
+
+	if (lp_reg & 0x40)
+		pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Half;
+	if (lp_reg & 0x20)
+		pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+
+	/* Half duplex is not supported */
+	ad_reg &= lp_reg;
+	mode = (ad_reg & 0x20) ? XGBE_MODE_X : XGBE_MODE_UNKNOWN;
+
+	return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	enum xgbe_mode mode;
+	unsigned int ad_reg, lp_reg;
+
+	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
+
+	/* Use external PHY to determine flow control */
+	if (pdata->phy.pause_autoneg)
+		xgbe_phy_phydev_flowctrl(pdata);
+
+	/* Compare Advertisement and Link Partner register 2 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
+	if (lp_reg & 0x80)
+		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
+	if (lp_reg & 0x20)
+		pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
+
+	ad_reg &= lp_reg;
+	if (ad_reg & 0x80) {
+		switch (phy_data->port_mode) {
+		case XGBE_PORT_MODE_BACKPLANE:
+			mode = XGBE_MODE_KR;
+			break;
+		default:
+			mode = XGBE_MODE_SFI;
+			break;
+		}
+	} else if (ad_reg & 0x20) {
+		switch (phy_data->port_mode) {
+		case XGBE_PORT_MODE_BACKPLANE:
+			mode = XGBE_MODE_KX_1000;
+			break;
+		case XGBE_PORT_MODE_1000BASE_X:
+			mode = XGBE_MODE_X;
+			break;
+		case XGBE_PORT_MODE_SFP:
+			switch (phy_data->sfp_base) {
+			case XGBE_SFP_BASE_1000_T:
+				if (phy_data->phydev &&
+				    (phy_data->phydev->speed == SPEED_100))
+					mode = XGBE_MODE_SGMII_100;
+				else
+					mode = XGBE_MODE_SGMII_1000;
+				break;
+			case XGBE_SFP_BASE_1000_SX:
+			case XGBE_SFP_BASE_1000_LX:
+			case XGBE_SFP_BASE_1000_CX:
+			default:
+				mode = XGBE_MODE_X;
+				break;
+			}
+			break;
+		default:
+			if (phy_data->phydev &&
+			    (phy_data->phydev->speed == SPEED_100))
+				mode = XGBE_MODE_SGMII_100;
+			else
+				mode = XGBE_MODE_SGMII_1000;
+			break;
+		}
+	} else {
+		mode = XGBE_MODE_UNKNOWN;
+	}
+
+	/* Compare Advertisement and Link Partner register 3 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
+	if (lp_reg & 0xc000)
+		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
+
+	return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
+{
+	enum xgbe_mode mode;
+	unsigned int ad_reg, lp_reg;
+
+	pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+	pdata->phy.lp_advertising |= ADVERTISED_Backplane;
+
+	/* Compare Advertisement and Link Partner register 1 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
+	if (lp_reg & 0x400)
+		pdata->phy.lp_advertising |= ADVERTISED_Pause;
+	if (lp_reg & 0x800)
+		pdata->phy.lp_advertising |= ADVERTISED_Asym_Pause;
+
+	if (pdata->phy.pause_autoneg) {
+		/* Set flow control based on auto-negotiation result */
+		pdata->phy.tx_pause = 0;
+		pdata->phy.rx_pause = 0;
+
+		if (ad_reg & lp_reg & 0x400) {
+			pdata->phy.tx_pause = 1;
+			pdata->phy.rx_pause = 1;
+		} else if (ad_reg & lp_reg & 0x800) {
+			if (ad_reg & 0x400)
+				pdata->phy.rx_pause = 1;
+			else if (lp_reg & 0x400)
+				pdata->phy.tx_pause = 1;
+		}
+	}
+
+	/* Compare Advertisement and Link Partner register 2 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
+	if (lp_reg & 0x80)
+		pdata->phy.lp_advertising |= ADVERTISED_10000baseKR_Full;
+	if (lp_reg & 0x20)
+		pdata->phy.lp_advertising |= ADVERTISED_1000baseKX_Full;
+
+	ad_reg &= lp_reg;
+	if (ad_reg & 0x80)
+		mode = XGBE_MODE_KR;
+	else if (ad_reg & 0x20)
+		mode = XGBE_MODE_KX_1000;
+	else
+		mode = XGBE_MODE_UNKNOWN;
+
+	/* Compare Advertisement and Link Partner register 3 */
+	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
+	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
+	if (lp_reg & 0xc000)
+		pdata->phy.lp_advertising |= ADVERTISED_10000baseR_FEC;
+
+	return mode;
+}
+
+static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
+{
+	switch (pdata->an_mode) {
+	case XGBE_AN_MODE_CL73:
+		return xgbe_phy_an73_outcome(pdata);
+	case XGBE_AN_MODE_CL73_REDRV:
+		return xgbe_phy_an73_redrv_outcome(pdata);
+	case XGBE_AN_MODE_CL37:
+		return xgbe_phy_an37_outcome(pdata);
+	case XGBE_AN_MODE_CL37_SGMII:
+		return xgbe_phy_an37_sgmii_outcome(pdata);
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static unsigned int xgbe_phy_an_advertising(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int advertising;
+
+	/* Without a re-driver, just return current advertising */
+	if (!phy_data->redrv)
+		return pdata->phy.advertising;
+
+	/* With the KR re-driver we need to advertise a single speed */
+	advertising = pdata->phy.advertising;
+	advertising &= ~ADVERTISED_1000baseKX_Full;
+	advertising &= ~ADVERTISED_10000baseKR_Full;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+		advertising |= ADVERTISED_10000baseKR_Full;
+		break;
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		advertising |= ADVERTISED_1000baseKX_Full;
+		break;
+	case XGBE_PORT_MODE_1000BASE_T:
+	case XGBE_PORT_MODE_1000BASE_X:
+	case XGBE_PORT_MODE_NBASE_T:
+		advertising |= ADVERTISED_1000baseKX_Full;
+		break;
+	case XGBE_PORT_MODE_10GBASE_T:
+		if (phy_data->phydev &&
+		    (phy_data->phydev->speed == SPEED_10000))
+			advertising |= ADVERTISED_10000baseKR_Full;
+		else
+			advertising |= ADVERTISED_1000baseKX_Full;
+		break;
+	case XGBE_PORT_MODE_10GBASE_R:
+		advertising |= ADVERTISED_10000baseKR_Full;
+		break;
+	case XGBE_PORT_MODE_SFP:
+		switch (phy_data->sfp_base) {
+		case XGBE_SFP_BASE_1000_T:
+		case XGBE_SFP_BASE_1000_SX:
+		case XGBE_SFP_BASE_1000_LX:
+		case XGBE_SFP_BASE_1000_CX:
+			advertising |= ADVERTISED_1000baseKX_Full;
+			break;
+		default:
+			advertising |= ADVERTISED_10000baseKR_Full;
+			break;
+		}
+		break;
+	default:
+		advertising |= ADVERTISED_10000baseKR_Full;
+		break;
+	}
+
+	return advertising;
+}
+
+static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int ret;
+
+	ret = xgbe_phy_find_phy_device(pdata);
+	if (ret)
+		return ret;
+
+	if (!phy_data->phydev)
+		return 0;
+
+	phy_data->phydev->autoneg = pdata->phy.autoneg;
+	phy_data->phydev->advertising = phy_data->phydev->supported &
+					pdata->phy.advertising;
+
+	if (pdata->phy.autoneg != AUTONEG_ENABLE) {
+		phy_data->phydev->speed = pdata->phy.speed;
+		phy_data->phydev->duplex = pdata->phy.duplex;
+	}
+
+	ret = phy_start_aneg(phy_data->phydev);
+
+	return ret;
+}
+
+static enum xgbe_an_mode xgbe_phy_an_sfp_mode(struct xgbe_phy_data *phy_data)
+{
+	switch (phy_data->sfp_base) {
+	case XGBE_SFP_BASE_1000_T:
+		return XGBE_AN_MODE_CL37_SGMII;
+	case XGBE_SFP_BASE_1000_SX:
+	case XGBE_SFP_BASE_1000_LX:
+	case XGBE_SFP_BASE_1000_CX:
+		return XGBE_AN_MODE_CL37;
+	default:
+		return XGBE_AN_MODE_NONE;
+	}
+}
+
+static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	/* A KR re-driver will always require CL73 AN */
+	if (phy_data->redrv)
+		return XGBE_AN_MODE_CL73_REDRV;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+		return XGBE_AN_MODE_CL73;
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		return XGBE_AN_MODE_NONE;
+	case XGBE_PORT_MODE_1000BASE_T:
+		return XGBE_AN_MODE_CL37_SGMII;
+	case XGBE_PORT_MODE_1000BASE_X:
+		return XGBE_AN_MODE_CL37;
+	case XGBE_PORT_MODE_NBASE_T:
+		return XGBE_AN_MODE_CL37_SGMII;
+	case XGBE_PORT_MODE_10GBASE_T:
+		return XGBE_AN_MODE_CL73;
+	case XGBE_PORT_MODE_10GBASE_R:
+		return XGBE_AN_MODE_NONE;
+	case XGBE_PORT_MODE_SFP:
+		return xgbe_phy_an_sfp_mode(phy_data);
+	default:
+		return XGBE_AN_MODE_NONE;
+	}
+}
+
+static int xgbe_phy_set_redrv_mode_mdio(struct xgbe_prv_data *pdata,
+					enum xgbe_phy_redrv_mode mode)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	u16 redrv_reg, redrv_val;
+
+	redrv_reg = XGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
+	redrv_val = (u16)mode;
+
+	return pdata->hw_if.write_ext_mii_regs(pdata, phy_data->redrv_addr,
+					       redrv_reg, redrv_val);
+}
+
+static int xgbe_phy_set_redrv_mode_i2c(struct xgbe_prv_data *pdata,
+				       enum xgbe_phy_redrv_mode mode)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int redrv_reg;
+	int ret;
+
+	/* Calculate the register to write */
+	redrv_reg = XGBE_PHY_REDRV_MODE_REG + (phy_data->redrv_lane * 0x1000);
+
+	ret = xgbe_phy_redrv_write(pdata, redrv_reg, mode);
+
+	return ret;
+}
+
+static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	enum xgbe_phy_redrv_mode mode;
+	int ret;
+
+	if (!phy_data->redrv)
+		return;
+
+	mode = XGBE_PHY_REDRV_MODE_CX;
+	if ((phy_data->port_mode == XGBE_PORT_MODE_SFP) &&
+	    (phy_data->sfp_base != XGBE_SFP_BASE_1000_CX) &&
+	    (phy_data->sfp_base != XGBE_SFP_BASE_10000_CR))
+		mode = XGBE_PHY_REDRV_MODE_SR;
+
+	ret = xgbe_phy_get_comm_ownership(pdata);
+	if (ret)
+		return;
+
+	if (phy_data->redrv_if)
+		xgbe_phy_set_redrv_mode_i2c(pdata, mode);
+	else
+		xgbe_phy_set_redrv_mode_mdio(pdata, mode);
+
+	xgbe_phy_put_comm_ownership(pdata);
+}
+
+static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
+{
+	if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
+		return;
+
+	/* Log if a previous command did not complete */
+	netif_dbg(pdata, link, pdata->netdev,
+		  "firmware mailbox not ready for command\n");
+}
+
+static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
+{
+	unsigned int wait;
+
+	/* Wait for command to complete */
+	wait = XGBE_RATECHANGE_COUNT;
+	while (wait--) {
+		if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
+			return;
+
+		usleep_range(1000, 2000);
+	}
+
+	netif_dbg(pdata, link, pdata->netdev,
+		  "firmware mailbox command did not complete\n");
+}
+
+static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
+{
+	unsigned int s0;
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* Receiver Reset Cycle */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 5);
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	netif_dbg(pdata, link, pdata->netdev, "receiver reset complete\n");
+}
+
+static void xgbe_phy_power_off(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, 0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_UNKNOWN;
+
+	netif_dbg(pdata, link, pdata->netdev, "phy powered off\n");
+}
+
+static void xgbe_phy_sfi_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int s0;
+
+	xgbe_phy_set_redrv_mode(pdata);
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* 10G/SFI */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 3);
+	if (phy_data->sfp_cable != XGBE_SFP_CABLE_PASSIVE) {
+		XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+	} else {
+		if (phy_data->sfp_cable_len <= 1)
+			XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1);
+		else if (phy_data->sfp_cable_len <= 3)
+			XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2);
+		else
+			XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
+	}
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_SFI;
+
+	netif_dbg(pdata, link, pdata->netdev, "10GbE SFI mode set\n");
+}
+
+static void xgbe_phy_x_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int s0;
+
+	xgbe_phy_set_redrv_mode(pdata);
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* 1G/X */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_X;
+
+	netif_dbg(pdata, link, pdata->netdev, "1GbE X mode set\n");
+}
+
+static void xgbe_phy_sgmii_1000_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int s0;
+
+	xgbe_phy_set_redrv_mode(pdata);
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* 1G/SGMII */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 2);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_SGMII_1000;
+
+	netif_dbg(pdata, link, pdata->netdev, "1GbE SGMII mode set\n");
+}
+
+static void xgbe_phy_sgmii_100_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int s0;
+
+	xgbe_phy_set_redrv_mode(pdata);
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* 1G/SGMII */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 1);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_SGMII_100;
+
+	netif_dbg(pdata, link, pdata->netdev, "100MbE SGMII mode set\n");
+}
+
+static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int s0;
+
+	xgbe_phy_set_redrv_mode(pdata);
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* 10G/KR */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 4);
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_KR;
+
+	netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
+}
+
+static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int s0;
+
+	xgbe_phy_set_redrv_mode(pdata);
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* 2.5G/KX */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 2);
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 0);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_KX_2500;
+
+	netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
+}
+
+static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int s0;
+
+	xgbe_phy_set_redrv_mode(pdata);
+
+	xgbe_phy_start_ratechange(pdata);
+
+	/* 1G/KX */
+	s0 = 0;
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, 1);
+	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, SUB_COMMAND, 3);
+
+	/* Call FW to make the change */
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_0, s0);
+	XP_IOWRITE(pdata, XP_DRIVER_SCRATCH_1, 0);
+	XP_IOWRITE_BITS(pdata, XP_DRIVER_INT_REQ, REQUEST, 1);
+
+	xgbe_phy_complete_ratechange(pdata);
+
+	phy_data->cur_mode = XGBE_MODE_KX_1000;
+
+	netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
+}
+
+static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	return phy_data->cur_mode;
+}
+
+static enum xgbe_mode xgbe_phy_switch_baset_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	/* No switching if not 10GBase-T */
+	if (phy_data->port_mode != XGBE_PORT_MODE_10GBASE_T)
+		return xgbe_phy_cur_mode(pdata);
+
+	switch (xgbe_phy_cur_mode(pdata)) {
+	case XGBE_MODE_SGMII_100:
+	case XGBE_MODE_SGMII_1000:
+		return XGBE_MODE_KR;
+	case XGBE_MODE_KR:
+	default:
+		return XGBE_MODE_SGMII_1000;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_switch_bp_2500_mode(struct xgbe_prv_data *pdata)
+{
+	return XGBE_MODE_KX_2500;
+}
+
+static enum xgbe_mode xgbe_phy_switch_bp_mode(struct xgbe_prv_data *pdata)
+{
+	/* If we are in KR switch to KX, and vice-versa */
+	switch (xgbe_phy_cur_mode(pdata)) {
+	case XGBE_MODE_KX_1000:
+		return XGBE_MODE_KR;
+	case XGBE_MODE_KR:
+	default:
+		return XGBE_MODE_KX_1000;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+		return xgbe_phy_switch_bp_mode(pdata);
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		return xgbe_phy_switch_bp_2500_mode(pdata);
+	case XGBE_PORT_MODE_1000BASE_T:
+	case XGBE_PORT_MODE_NBASE_T:
+	case XGBE_PORT_MODE_10GBASE_T:
+		return xgbe_phy_switch_baset_mode(pdata);
+	case XGBE_PORT_MODE_1000BASE_X:
+	case XGBE_PORT_MODE_10GBASE_R:
+	case XGBE_PORT_MODE_SFP:
+		/* No switching, so just return current mode */
+		return xgbe_phy_cur_mode(pdata);
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_get_basex_mode(struct xgbe_phy_data *phy_data,
+					      int speed)
+{
+	switch (speed) {
+	case SPEED_1000:
+		return XGBE_MODE_X;
+	case SPEED_10000:
+		return XGBE_MODE_KR;
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_get_baset_mode(struct xgbe_phy_data *phy_data,
+					      int speed)
+{
+	switch (speed) {
+	case SPEED_100:
+		return XGBE_MODE_SGMII_100;
+	case SPEED_1000:
+		return XGBE_MODE_SGMII_1000;
+	case SPEED_10000:
+		return XGBE_MODE_KR;
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_get_sfp_mode(struct xgbe_phy_data *phy_data,
+					    int speed)
+{
+	switch (speed) {
+	case SPEED_100:
+		return XGBE_MODE_SGMII_100;
+	case SPEED_1000:
+		if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T)
+			return XGBE_MODE_SGMII_1000;
+		else
+			return XGBE_MODE_X;
+	case SPEED_10000:
+	case SPEED_UNKNOWN:
+		return XGBE_MODE_SFI;
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_get_bp_2500_mode(int speed)
+{
+	switch (speed) {
+	case SPEED_2500:
+		return XGBE_MODE_KX_2500;
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_get_bp_mode(int speed)
+{
+	switch (speed) {
+	case SPEED_1000:
+		return XGBE_MODE_KX_1000;
+	case SPEED_10000:
+		return XGBE_MODE_KR;
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
+					int speed)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+		return xgbe_phy_get_bp_mode(speed);
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		return xgbe_phy_get_bp_2500_mode(speed);
+	case XGBE_PORT_MODE_1000BASE_T:
+	case XGBE_PORT_MODE_NBASE_T:
+	case XGBE_PORT_MODE_10GBASE_T:
+		return xgbe_phy_get_baset_mode(phy_data, speed);
+	case XGBE_PORT_MODE_1000BASE_X:
+	case XGBE_PORT_MODE_10GBASE_R:
+		return xgbe_phy_get_basex_mode(phy_data, speed);
+	case XGBE_PORT_MODE_SFP:
+		return xgbe_phy_get_sfp_mode(phy_data, speed);
+	default:
+		return XGBE_MODE_UNKNOWN;
+	}
+}
+
+static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_KX_1000:
+		xgbe_phy_kx_1000_mode(pdata);
+		break;
+	case XGBE_MODE_KX_2500:
+		xgbe_phy_kx_2500_mode(pdata);
+		break;
+	case XGBE_MODE_KR:
+		xgbe_phy_kr_mode(pdata);
+		break;
+	case XGBE_MODE_SGMII_100:
+		xgbe_phy_sgmii_100_mode(pdata);
+		break;
+	case XGBE_MODE_SGMII_1000:
+		xgbe_phy_sgmii_1000_mode(pdata);
+		break;
+	case XGBE_MODE_X:
+		xgbe_phy_x_mode(pdata);
+		break;
+	case XGBE_MODE_SFI:
+		xgbe_phy_sfi_mode(pdata);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
+				enum xgbe_mode mode, u32 advert)
+{
+	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
+		if (pdata->phy.advertising & advert)
+			return true;
+	} else {
+		enum xgbe_mode cur_mode;
+
+		cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
+		if (cur_mode == mode)
+			return true;
+	}
+
+	return false;
+}
+
+static bool xgbe_phy_use_basex_mode(struct xgbe_prv_data *pdata,
+				    enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_X:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_1000baseT_Full);
+	case XGBE_MODE_KR:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_10000baseT_Full);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_use_baset_mode(struct xgbe_prv_data *pdata,
+				    enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_SGMII_100:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_100baseT_Full);
+	case XGBE_MODE_SGMII_1000:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_1000baseT_Full);
+	case XGBE_MODE_KR:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_10000baseT_Full);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_use_sfp_mode(struct xgbe_prv_data *pdata,
+				  enum xgbe_mode mode)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (mode) {
+	case XGBE_MODE_X:
+		if (phy_data->sfp_base == XGBE_SFP_BASE_1000_T)
+			return false;
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_1000baseT_Full);
+	case XGBE_MODE_SGMII_100:
+		if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
+			return false;
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_100baseT_Full);
+	case XGBE_MODE_SGMII_1000:
+		if (phy_data->sfp_base != XGBE_SFP_BASE_1000_T)
+			return false;
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_1000baseT_Full);
+	case XGBE_MODE_SFI:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_10000baseT_Full);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_use_bp_2500_mode(struct xgbe_prv_data *pdata,
+				      enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_KX_2500:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_2500baseX_Full);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_use_bp_mode(struct xgbe_prv_data *pdata,
+				 enum xgbe_mode mode)
+{
+	switch (mode) {
+	case XGBE_MODE_KX_1000:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_1000baseKX_Full);
+	case XGBE_MODE_KR:
+		return xgbe_phy_check_mode(pdata, mode,
+					   ADVERTISED_10000baseKR_Full);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+		return xgbe_phy_use_bp_mode(pdata, mode);
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		return xgbe_phy_use_bp_2500_mode(pdata, mode);
+	case XGBE_PORT_MODE_1000BASE_T:
+	case XGBE_PORT_MODE_NBASE_T:
+	case XGBE_PORT_MODE_10GBASE_T:
+		return xgbe_phy_use_baset_mode(pdata, mode);
+	case XGBE_PORT_MODE_1000BASE_X:
+	case XGBE_PORT_MODE_10GBASE_R:
+		return xgbe_phy_use_basex_mode(pdata, mode);
+	case XGBE_PORT_MODE_SFP:
+		return xgbe_phy_use_sfp_mode(pdata, mode);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_valid_speed_basex_mode(struct xgbe_phy_data *phy_data,
+					    int speed)
+{
+	switch (speed) {
+	case SPEED_1000:
+		return (phy_data->port_mode == XGBE_PORT_MODE_1000BASE_X);
+	case SPEED_10000:
+		return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_R);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_phy_data *phy_data,
+					    int speed)
+{
+	switch (speed) {
+	case SPEED_100:
+	case SPEED_1000:
+		return true;
+	case SPEED_10000:
+		return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_phy_data *phy_data,
+					  int speed)
+{
+	switch (speed) {
+	case SPEED_100:
+		return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000);
+	case SPEED_1000:
+		return ((phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000) ||
+			(phy_data->sfp_speed == XGBE_SFP_SPEED_1000));
+	case SPEED_10000:
+		return (phy_data->sfp_speed == XGBE_SFP_SPEED_10000);
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_valid_speed_bp_2500_mode(int speed)
+{
+	switch (speed) {
+	case SPEED_2500:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_valid_speed_bp_mode(int speed)
+{
+	switch (speed) {
+	case SPEED_1000:
+	case SPEED_10000:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+		return xgbe_phy_valid_speed_bp_mode(speed);
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		return xgbe_phy_valid_speed_bp_2500_mode(speed);
+	case XGBE_PORT_MODE_1000BASE_T:
+	case XGBE_PORT_MODE_NBASE_T:
+	case XGBE_PORT_MODE_10GBASE_T:
+		return xgbe_phy_valid_speed_baset_mode(phy_data, speed);
+	case XGBE_PORT_MODE_1000BASE_X:
+	case XGBE_PORT_MODE_10GBASE_R:
+		return xgbe_phy_valid_speed_basex_mode(phy_data, speed);
+	case XGBE_PORT_MODE_SFP:
+		return xgbe_phy_valid_speed_sfp_mode(phy_data, speed);
+	default:
+		return false;
+	}
+}
+
+static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int reg;
+	int ret;
+
+	*an_restart = 0;
+
+	if (phy_data->port_mode == XGBE_PORT_MODE_SFP) {
+		/* Check SFP signals */
+		xgbe_phy_sfp_detect(pdata);
+
+		if (phy_data->sfp_changed) {
+			*an_restart = 1;
+			return 0;
+		}
+
+		if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los)
+			return 0;
+	}
+
+	if (phy_data->phydev) {
+		/* Check external PHY */
+		ret = phy_read_status(phy_data->phydev);
+		if (ret < 0)
+			return 0;
+
+		if ((pdata->phy.autoneg == AUTONEG_ENABLE) &&
+		    !phy_aneg_done(phy_data->phydev))
+			return 0;
+
+		if (!phy_data->phydev->link)
+			return 0;
+	}
+
+	/* Link status is latched low, so read once to clear
+	 * and then read again to get current state
+	 */
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
+	if (reg & MDIO_STAT1_LSTATUS)
+		return 1;
+
+	/* No link, attempt a receiver reset cycle */
+	if (phy_data->rrc_count++) {
+		phy_data->rrc_count = 0;
+		xgbe_phy_rrc(pdata);
+	}
+
+	return 0;
+}
+
+static void xgbe_phy_sfp_gpio_setup(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int reg;
+
+	reg = XP_IOREAD(pdata, XP_PROP_3);
+
+	phy_data->sfp_gpio_address = XGBE_GPIO_ADDRESS_PCA9555 +
+				     XP_GET_BITS(reg, XP_PROP_3, GPIO_ADDR);
+
+	phy_data->sfp_gpio_mask = XP_GET_BITS(reg, XP_PROP_3, GPIO_MASK);
+
+	phy_data->sfp_gpio_rx_los = XP_GET_BITS(reg, XP_PROP_3,
+						GPIO_RX_LOS);
+	phy_data->sfp_gpio_tx_fault = XP_GET_BITS(reg, XP_PROP_3,
+						  GPIO_TX_FAULT);
+	phy_data->sfp_gpio_mod_absent = XP_GET_BITS(reg, XP_PROP_3,
+						    GPIO_MOD_ABS);
+	phy_data->sfp_gpio_rate_select = XP_GET_BITS(reg, XP_PROP_3,
+						     GPIO_RATE_SELECT);
+
+	if (netif_msg_probe(pdata)) {
+		dev_dbg(pdata->dev, "SFP: gpio_address=%#x\n",
+			phy_data->sfp_gpio_address);
+		dev_dbg(pdata->dev, "SFP: gpio_mask=%#x\n",
+			phy_data->sfp_gpio_mask);
+		dev_dbg(pdata->dev, "SFP: gpio_rx_los=%u\n",
+			phy_data->sfp_gpio_rx_los);
+		dev_dbg(pdata->dev, "SFP: gpio_tx_fault=%u\n",
+			phy_data->sfp_gpio_tx_fault);
+		dev_dbg(pdata->dev, "SFP: gpio_mod_absent=%u\n",
+			phy_data->sfp_gpio_mod_absent);
+		dev_dbg(pdata->dev, "SFP: gpio_rate_select=%u\n",
+			phy_data->sfp_gpio_rate_select);
+	}
+}
+
+static void xgbe_phy_sfp_comm_setup(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int reg, mux_addr_hi, mux_addr_lo;
+
+	reg = XP_IOREAD(pdata, XP_PROP_4);
+
+	mux_addr_hi = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_HI);
+	mux_addr_lo = XP_GET_BITS(reg, XP_PROP_4, MUX_ADDR_LO);
+	if (mux_addr_lo == XGBE_SFP_DIRECT)
+		return;
+
+	phy_data->sfp_comm = XGBE_SFP_COMM_PCA9545;
+	phy_data->sfp_mux_address = (mux_addr_hi << 2) + mux_addr_lo;
+	phy_data->sfp_mux_channel = XP_GET_BITS(reg, XP_PROP_4, MUX_CHAN);
+
+	if (netif_msg_probe(pdata)) {
+		dev_dbg(pdata->dev, "SFP: mux_address=%#x\n",
+			phy_data->sfp_mux_address);
+		dev_dbg(pdata->dev, "SFP: mux_channel=%u\n",
+			phy_data->sfp_mux_channel);
+	}
+}
+
+static void xgbe_phy_sfp_setup(struct xgbe_prv_data *pdata)
+{
+	xgbe_phy_sfp_comm_setup(pdata);
+	xgbe_phy_sfp_gpio_setup(pdata);
+}
+
+static int xgbe_phy_int_mdio_reset(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int ret;
+
+	ret = pdata->hw_if.set_gpio(pdata, phy_data->mdio_reset_gpio);
+	if (ret)
+		return ret;
+
+	ret = pdata->hw_if.clr_gpio(pdata, phy_data->mdio_reset_gpio);
+
+	return ret;
+}
+
+static int xgbe_phy_i2c_mdio_reset(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	u8 gpio_reg, gpio_ports[2], gpio_data[3];
+	int ret;
+
+	/* Read the output port registers */
+	gpio_reg = 2;
+	ret = xgbe_phy_i2c_read(pdata, phy_data->mdio_reset_addr,
+				&gpio_reg, sizeof(gpio_reg),
+				gpio_ports, sizeof(gpio_ports));
+	if (ret)
+		return ret;
+
+	/* Prepare to write the GPIO data */
+	gpio_data[0] = 2;
+	gpio_data[1] = gpio_ports[0];
+	gpio_data[2] = gpio_ports[1];
+
+	/* Set the GPIO pin */
+	if (phy_data->mdio_reset_gpio < 8)
+		gpio_data[1] |= (1 << (phy_data->mdio_reset_gpio % 8));
+	else
+		gpio_data[2] |= (1 << (phy_data->mdio_reset_gpio % 8));
+
+	/* Write the output port registers */
+	ret = xgbe_phy_i2c_write(pdata, phy_data->mdio_reset_addr,
+				 gpio_data, sizeof(gpio_data));
+	if (ret)
+		return ret;
+
+	/* Clear the GPIO pin */
+	if (phy_data->mdio_reset_gpio < 8)
+		gpio_data[1] &= ~(1 << (phy_data->mdio_reset_gpio % 8));
+	else
+		gpio_data[2] &= ~(1 << (phy_data->mdio_reset_gpio % 8));
+
+	/* Write the output port registers */
+	ret = xgbe_phy_i2c_write(pdata, phy_data->mdio_reset_addr,
+				 gpio_data, sizeof(gpio_data));
+
+	return ret;
+}
+
+static int xgbe_phy_mdio_reset(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int ret;
+
+	if (phy_data->conn_type != XGBE_CONN_TYPE_MDIO)
+		return 0;
+
+	ret = xgbe_phy_get_comm_ownership(pdata);
+	if (ret)
+		return ret;
+
+	if (phy_data->mdio_reset == XGBE_MDIO_RESET_I2C_GPIO)
+		ret = xgbe_phy_i2c_mdio_reset(pdata);
+	else if (phy_data->mdio_reset == XGBE_MDIO_RESET_INT_GPIO)
+		ret = xgbe_phy_int_mdio_reset(pdata);
+
+	xgbe_phy_put_comm_ownership(pdata);
+
+	return ret;
+}
+
+static bool xgbe_phy_redrv_error(struct xgbe_phy_data *phy_data)
+{
+	if (!phy_data->redrv)
+		return false;
+
+	if (phy_data->redrv_if >= XGBE_PHY_REDRV_IF_MAX)
+		return true;
+
+	switch (phy_data->redrv_model) {
+	case XGBE_PHY_REDRV_MODEL_4223:
+		if (phy_data->redrv_lane > 3)
+			return true;
+		break;
+	case XGBE_PHY_REDRV_MODEL_4227:
+		if (phy_data->redrv_lane > 1)
+			return true;
+		break;
+	default:
+		return true;
+	}
+
+	return false;
+}
+
+static int xgbe_phy_mdio_reset_setup(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	unsigned int reg;
+
+	if (phy_data->conn_type != XGBE_CONN_TYPE_MDIO)
+		return 0;
+
+	reg = XP_IOREAD(pdata, XP_PROP_3);
+	phy_data->mdio_reset = XP_GET_BITS(reg, XP_PROP_3, MDIO_RESET);
+	switch (phy_data->mdio_reset) {
+	case XGBE_MDIO_RESET_NONE:
+	case XGBE_MDIO_RESET_I2C_GPIO:
+	case XGBE_MDIO_RESET_INT_GPIO:
+		break;
+	default:
+		dev_err(pdata->dev, "unsupported MDIO reset (%#x)\n",
+			phy_data->mdio_reset);
+		return -EINVAL;
+	}
+
+	if (phy_data->mdio_reset == XGBE_MDIO_RESET_I2C_GPIO) {
+		phy_data->mdio_reset_addr = XGBE_GPIO_ADDRESS_PCA9555 +
+					    XP_GET_BITS(reg, XP_PROP_3,
+							MDIO_RESET_I2C_ADDR);
+		phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3,
+							MDIO_RESET_I2C_GPIO);
+	} else if (phy_data->mdio_reset == XGBE_MDIO_RESET_INT_GPIO) {
+		phy_data->mdio_reset_gpio = XP_GET_BITS(reg, XP_PROP_3,
+							MDIO_RESET_INT_GPIO);
+	}
+
+	return 0;
+}
+
+static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+		if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
+			return false;
+		break;
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500)
+			return false;
+		break;
+	case XGBE_PORT_MODE_1000BASE_T:
+		if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000))
+			return false;
+		break;
+	case XGBE_PORT_MODE_1000BASE_X:
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+			return false;
+		break;
+	case XGBE_PORT_MODE_NBASE_T:
+		if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500))
+			return false;
+		break;
+	case XGBE_PORT_MODE_10GBASE_T:
+		if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
+			return false;
+		break;
+	case XGBE_PORT_MODE_10GBASE_R:
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
+			return false;
+		break;
+	case XGBE_PORT_MODE_SFP:
+		if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) ||
+		    (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000))
+			return false;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+static bool xgbe_phy_conn_type_mismatch(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_BACKPLANE:
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		if (phy_data->conn_type == XGBE_CONN_TYPE_BACKPLANE)
+			return false;
+		break;
+	case XGBE_PORT_MODE_1000BASE_T:
+	case XGBE_PORT_MODE_1000BASE_X:
+	case XGBE_PORT_MODE_NBASE_T:
+	case XGBE_PORT_MODE_10GBASE_T:
+	case XGBE_PORT_MODE_10GBASE_R:
+		if (phy_data->conn_type == XGBE_CONN_TYPE_MDIO)
+			return false;
+		break;
+	case XGBE_PORT_MODE_SFP:
+		if (phy_data->conn_type == XGBE_CONN_TYPE_SFP)
+			return false;
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+static bool xgbe_phy_port_enabled(struct xgbe_prv_data *pdata)
+{
+	unsigned int reg;
+
+	reg = XP_IOREAD(pdata, XP_PROP_0);
+	if (!XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS))
+		return false;
+	if (!XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE))
+		return false;
+
+	return true;
+}
+
+static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	/* If we have an external PHY, free it */
+	xgbe_phy_free_phy_device(pdata);
+
+	/* Reset SFP data */
+	xgbe_phy_sfp_reset(phy_data);
+	xgbe_phy_sfp_mod_absent(pdata);
+
+	/* Power off the PHY */
+	xgbe_phy_power_off(pdata);
+
+	/* Stop the I2C controller */
+	pdata->i2c_if.i2c_stop(pdata);
+}
+
+static int xgbe_phy_start(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int ret;
+
+	/* Start the I2C controller */
+	ret = pdata->i2c_if.i2c_start(pdata);
+	if (ret)
+		return ret;
+
+	/* Start in highest supported mode */
+	xgbe_phy_set_mode(pdata, phy_data->start_mode);
+
+	/* After starting the I2C controller, we can check for an SFP */
+	switch (phy_data->port_mode) {
+	case XGBE_PORT_MODE_SFP:
+		xgbe_phy_sfp_detect(pdata);
+		break;
+	default:
+		break;
+	}
+
+	/* If we have an external PHY, start it */
+	ret = xgbe_phy_find_phy_device(pdata);
+	if (ret)
+		goto err_i2c;
+
+	return 0;
+
+err_i2c:
+	pdata->i2c_if.i2c_stop(pdata);
+
+	return ret;
+}
+
+static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	enum xgbe_mode cur_mode;
+	int ret;
+
+	/* Reset by power cycling the PHY */
+	cur_mode = phy_data->cur_mode;
+	xgbe_phy_power_off(pdata);
+	xgbe_phy_set_mode(pdata, cur_mode);
+
+	if (!phy_data->phydev)
+		return 0;
+
+	/* Reset the external PHY */
+	ret = xgbe_phy_mdio_reset(pdata);
+	if (ret)
+		return ret;
+
+	return phy_init_hw(phy_data->phydev);
+}
+
+static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	/* Unregister for driving external PHYs */
+	mdiobus_unregister(phy_data->mii);
+}
+
+static int xgbe_phy_init(struct xgbe_prv_data *pdata)
+{
+	struct xgbe_phy_data *phy_data;
+	struct mii_bus *mii;
+	unsigned int reg;
+	int ret;
+
+	/* Check if enabled */
+	if (!xgbe_phy_port_enabled(pdata)) {
+		dev_info(pdata->dev, "device is not enabled\n");
+		return -ENODEV;
+	}
+
+	/* Initialize the I2C controller */
+	ret = pdata->i2c_if.i2c_init(pdata);
+	if (ret)
+		return ret;
+
+	phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
+	if (!phy_data)
+		return -ENOMEM;
+	pdata->phy_data = phy_data;
+
+	reg = XP_IOREAD(pdata, XP_PROP_0);
+	phy_data->port_mode = XP_GET_BITS(reg, XP_PROP_0, PORT_MODE);
+	phy_data->port_id = XP_GET_BITS(reg, XP_PROP_0, PORT_ID);
+	phy_data->port_speeds = XP_GET_BITS(reg, XP_PROP_0, PORT_SPEEDS);
+	phy_data->conn_type = XP_GET_BITS(reg, XP_PROP_0, CONN_TYPE);
+	phy_data->mdio_addr = XP_GET_BITS(reg, XP_PROP_0, MDIO_ADDR);
+	if (netif_msg_probe(pdata)) {
+		dev_dbg(pdata->dev, "port mode=%u\n", phy_data->port_mode);
+		dev_dbg(pdata->dev, "port id=%u\n", phy_data->port_id);
+		dev_dbg(pdata->dev, "port speeds=%#x\n", phy_data->port_speeds);
+		dev_dbg(pdata->dev, "conn type=%u\n", phy_data->conn_type);
+		dev_dbg(pdata->dev, "mdio addr=%u\n", phy_data->mdio_addr);
+	}
+
+	reg = XP_IOREAD(pdata, XP_PROP_4);
+	phy_data->redrv = XP_GET_BITS(reg, XP_PROP_4, REDRV_PRESENT);
+	phy_data->redrv_if = XP_GET_BITS(reg, XP_PROP_4, REDRV_IF);
+	phy_data->redrv_addr = XP_GET_BITS(reg, XP_PROP_4, REDRV_ADDR);
+	phy_data->redrv_lane = XP_GET_BITS(reg, XP_PROP_4, REDRV_LANE);
+	phy_data->redrv_model = XP_GET_BITS(reg, XP_PROP_4, REDRV_MODEL);
+	if (phy_data->redrv && netif_msg_probe(pdata)) {
+		dev_dbg(pdata->dev, "redrv present\n");
+		dev_dbg(pdata->dev, "redrv i/f=%u\n", phy_data->redrv_if);
+		dev_dbg(pdata->dev, "redrv addr=%#x\n", phy_data->redrv_addr);
+		dev_dbg(pdata->dev, "redrv lane=%u\n", phy_data->redrv_lane);
+		dev_dbg(pdata->dev, "redrv model=%u\n", phy_data->redrv_model);
+	}
+
+	/* Validate the connection requested */
+	if (xgbe_phy_conn_type_mismatch(pdata)) {
+		dev_err(pdata->dev, "phy mode/connection mismatch (%#x/%#x)\n",
+			phy_data->port_mode, phy_data->conn_type);
+		return -EINVAL;
+	}
+
+	/* Validate the mode requested */
+	if (xgbe_phy_port_mode_mismatch(pdata)) {
+		dev_err(pdata->dev, "phy mode/speed mismatch (%#x/%#x)\n",
+			phy_data->port_mode, phy_data->port_speeds);
+		return -EINVAL;
+	}
+
+	/* Check for and validate MDIO reset support */
+	ret = xgbe_phy_mdio_reset_setup(pdata);
+	if (ret)
+		return ret;
+
+	/* Validate the re-driver information */
+	if (xgbe_phy_redrv_error(phy_data)) {
+		dev_err(pdata->dev, "phy re-driver settings error\n");
+		return -EINVAL;
+	}
+	pdata->kr_redrv = phy_data->redrv;
+
+	/* Indicate current mode is unknown */
+	phy_data->cur_mode = XGBE_MODE_UNKNOWN;
+
+	/* Initialize supported features */
+	pdata->phy.supported = 0;
+
+	switch (phy_data->port_mode) {
+	/* Backplane support */
+	case XGBE_PORT_MODE_BACKPLANE:
+		pdata->phy.supported |= SUPPORTED_Autoneg;
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_Backplane;
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+			pdata->phy.supported |= SUPPORTED_1000baseKX_Full;
+			phy_data->start_mode = XGBE_MODE_KX_1000;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
+			pdata->phy.supported |= SUPPORTED_10000baseKR_Full;
+			if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+				pdata->phy.supported |=
+					SUPPORTED_10000baseR_FEC;
+			phy_data->start_mode = XGBE_MODE_KR;
+		}
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+		break;
+	case XGBE_PORT_MODE_BACKPLANE_2500:
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_Backplane;
+		pdata->phy.supported |= SUPPORTED_2500baseX_Full;
+		phy_data->start_mode = XGBE_MODE_KX_2500;
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+		break;
+
+	/* MDIO 1GBase-T support */
+	case XGBE_PORT_MODE_1000BASE_T:
+		pdata->phy.supported |= SUPPORTED_Autoneg;
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_TP;
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+			pdata->phy.supported |= SUPPORTED_100baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_100;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_1000;
+		}
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
+		break;
+
+	/* MDIO Base-X support */
+	case XGBE_PORT_MODE_1000BASE_X:
+		pdata->phy.supported |= SUPPORTED_Autoneg;
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_FIBRE;
+		pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+		phy_data->start_mode = XGBE_MODE_X;
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
+		break;
+
+	/* MDIO NBase-T support */
+	case XGBE_PORT_MODE_NBASE_T:
+		pdata->phy.supported |= SUPPORTED_Autoneg;
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_TP;
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+			pdata->phy.supported |= SUPPORTED_100baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_100;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_1000;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500) {
+			pdata->phy.supported |= SUPPORTED_2500baseX_Full;
+			phy_data->start_mode = XGBE_MODE_KX_2500;
+		}
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_CL45;
+		break;
+
+	/* 10GBase-T support */
+	case XGBE_PORT_MODE_10GBASE_T:
+		pdata->phy.supported |= SUPPORTED_Autoneg;
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_TP;
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+			pdata->phy.supported |= SUPPORTED_100baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_100;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_1000;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
+			pdata->phy.supported |= SUPPORTED_10000baseT_Full;
+			phy_data->start_mode = XGBE_MODE_KR;
+		}
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+		break;
+
+	/* 10GBase-R support */
+	case XGBE_PORT_MODE_10GBASE_R:
+		pdata->phy.supported |= SUPPORTED_Autoneg;
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_TP;
+		pdata->phy.supported |= SUPPORTED_10000baseT_Full;
+		if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+			pdata->phy.supported |= SUPPORTED_10000baseR_FEC;
+		phy_data->start_mode = XGBE_MODE_SFI;
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+		break;
+
+	/* SFP support */
+	case XGBE_PORT_MODE_SFP:
+		pdata->phy.supported |= SUPPORTED_Autoneg;
+		pdata->phy.supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
+		pdata->phy.supported |= SUPPORTED_TP;
+		pdata->phy.supported |= SUPPORTED_FIBRE;
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100) {
+			pdata->phy.supported |= SUPPORTED_100baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_100;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000) {
+			pdata->phy.supported |= SUPPORTED_1000baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SGMII_1000;
+		}
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) {
+			pdata->phy.supported |= SUPPORTED_10000baseT_Full;
+			phy_data->start_mode = XGBE_MODE_SFI;
+			if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
+				pdata->phy.supported |=
+					SUPPORTED_10000baseR_FEC;
+		}
+
+		phy_data->phydev_mode = XGBE_MDIO_MODE_CL22;
+
+		xgbe_phy_sfp_setup(pdata);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (netif_msg_probe(pdata))
+		dev_dbg(pdata->dev, "phy supported=%#x\n",
+			pdata->phy.supported);
+
+	if ((phy_data->conn_type & XGBE_CONN_TYPE_MDIO) &&
+	    (phy_data->phydev_mode != XGBE_MDIO_MODE_NONE)) {
+		ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->mdio_addr,
+						    phy_data->phydev_mode);
+		if (ret) {
+			dev_err(pdata->dev,
+				"mdio port/clause not compatible (%d/%u)\n",
+				phy_data->mdio_addr, phy_data->phydev_mode);
+			return -EINVAL;
+		}
+	}
+
+	if (phy_data->redrv && !phy_data->redrv_if) {
+		ret = pdata->hw_if.set_ext_mii_mode(pdata, phy_data->redrv_addr,
+						    XGBE_MDIO_MODE_CL22);
+		if (ret) {
+			dev_err(pdata->dev,
+				"redriver mdio port not compatible (%u)\n",
+				phy_data->redrv_addr);
+			return -EINVAL;
+		}
+	}
+
+	/* Register for driving external PHYs */
+	mii = devm_mdiobus_alloc(pdata->dev);
+	if (!mii) {
+		dev_err(pdata->dev, "mdiobus_alloc failed\n");
+		return -ENOMEM;
+	}
+
+	mii->priv = pdata;
+	mii->name = "amd-xgbe-mii";
+	mii->read = xgbe_phy_mii_read;
+	mii->write = xgbe_phy_mii_write;
+	mii->parent = pdata->dev;
+	mii->phy_mask = ~0;
+	snprintf(mii->id, sizeof(mii->id), "%s", dev_name(pdata->dev));
+	ret = mdiobus_register(mii);
+	if (ret) {
+		dev_err(pdata->dev, "mdiobus_register failed\n");
+		return ret;
+	}
+	phy_data->mii = mii;
+
+	return 0;
+}
+
+void xgbe_init_function_ptrs_phy_v2(struct xgbe_phy_if *phy_if)
+{
+	struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
+
+	phy_impl->init			= xgbe_phy_init;
+	phy_impl->exit			= xgbe_phy_exit;
+
+	phy_impl->reset			= xgbe_phy_reset;
+	phy_impl->start			= xgbe_phy_start;
+	phy_impl->stop			= xgbe_phy_stop;
+
+	phy_impl->link_status		= xgbe_phy_link_status;
+
+	phy_impl->valid_speed		= xgbe_phy_valid_speed;
+
+	phy_impl->use_mode		= xgbe_phy_use_mode;
+	phy_impl->set_mode		= xgbe_phy_set_mode;
+	phy_impl->get_mode		= xgbe_phy_get_mode;
+	phy_impl->switch_mode		= xgbe_phy_switch_mode;
+	phy_impl->cur_mode		= xgbe_phy_cur_mode;
+
+	phy_impl->an_mode		= xgbe_phy_an_mode;
+
+	phy_impl->an_config		= xgbe_phy_an_config;
+
+	phy_impl->an_advertising	= xgbe_phy_an_advertising;
+
+	phy_impl->an_outcome		= xgbe_phy_an_outcome;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-platform.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-platform.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-platform.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,642 @@
+/*
+ * AMD 10Gb Ethernet driver
+ *
+ * This file is available to you under your choice of the following two
+ * licenses:
+ *
+ * License 1: GPLv2
+ *
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ *
+ * This file is free software; you may copy, redistribute and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     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.
+ *
+ *
+ * License 2: Modified BSD
+ *
+ * Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Advanced Micro Devices, Inc. nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> 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 file incorporates work covered by the following copyright and
+ * permission notice:
+ *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
+ *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
+ *     Inc. unless otherwise expressly agreed to in writing between Synopsys
+ *     and you.
+ *
+ *     The Software IS NOT an item of Licensed Software or Licensed Product
+ *     under any End User Software License Agreement or Agreement for Licensed
+ *     Product with Synopsys or any supplement thereto.  Permission is hereby
+ *     granted, free of charge, to any person obtaining a copy of this software
+ *     annotated with this license and 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.
+ *
+ *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
+ *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
+ *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ *     THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/property.h>
+#include <linux/acpi.h>
+#include <linux/mdio.h>
+
+#include "xgbe.h"
+#include "xgbe-common.h"
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgbe_acpi_match[];
+
+static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
+{
+	const struct acpi_device_id *id;
+
+	id = acpi_match_device(xgbe_acpi_match, pdata->dev);
+
+	return id ? (struct xgbe_version_data *)id->driver_data : NULL;
+}
+
+static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
+{
+	struct device *dev = pdata->dev;
+	u32 property;
+	int ret;
+
+	/* Obtain the system clock setting */
+	ret = device_property_read_u32(dev, XGBE_ACPI_DMA_FREQ, &property);
+	if (ret) {
+		dev_err(dev, "unable to obtain %s property\n",
+			XGBE_ACPI_DMA_FREQ);
+		return ret;
+	}
+	pdata->sysclk_rate = property;
+
+	/* Obtain the PTP clock setting */
+	ret = device_property_read_u32(dev, XGBE_ACPI_PTP_FREQ, &property);
+	if (ret) {
+		dev_err(dev, "unable to obtain %s property\n",
+			XGBE_ACPI_PTP_FREQ);
+		return ret;
+	}
+	pdata->ptpclk_rate = property;
+
+	return 0;
+}
+#else   /* CONFIG_ACPI */
+static struct xgbe_version_data *xgbe_acpi_vdata(struct xgbe_prv_data *pdata)
+{
+	return NULL;
+}
+
+static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
+{
+	return -EINVAL;
+}
+#endif  /* CONFIG_ACPI */
+
+#ifdef CONFIG_OF
+static const struct of_device_id xgbe_of_match[];
+
+static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
+{
+	const struct of_device_id *id;
+
+	id = of_match_device(xgbe_of_match, pdata->dev);
+
+	return id ? (struct xgbe_version_data *)id->data : NULL;
+}
+
+static int xgbe_of_support(struct xgbe_prv_data *pdata)
+{
+	struct device *dev = pdata->dev;
+
+	/* Obtain the system clock setting */
+	pdata->sysclk = devm_clk_get(dev, XGBE_DMA_CLOCK);
+	if (IS_ERR(pdata->sysclk)) {
+		dev_err(dev, "dma devm_clk_get failed\n");
+		return PTR_ERR(pdata->sysclk);
+	}
+	pdata->sysclk_rate = clk_get_rate(pdata->sysclk);
+
+	/* Obtain the PTP clock setting */
+	pdata->ptpclk = devm_clk_get(dev, XGBE_PTP_CLOCK);
+	if (IS_ERR(pdata->ptpclk)) {
+		dev_err(dev, "ptp devm_clk_get failed\n");
+		return PTR_ERR(pdata->ptpclk);
+	}
+	pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk);
+
+	return 0;
+}
+
+static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
+{
+	struct device *dev = pdata->dev;
+	struct device_node *phy_node;
+	struct platform_device *phy_pdev;
+
+	phy_node = of_parse_phandle(dev->of_node, "phy-handle", 0);
+	if (phy_node) {
+		/* Old style device tree:
+		 *   The XGBE and PHY resources are separate
+		 */
+		phy_pdev = of_find_device_by_node(phy_node);
+		of_node_put(phy_node);
+	} else {
+		/* New style device tree:
+		 *   The XGBE and PHY resources are grouped together with
+		 *   the PHY resources listed last
+		 */
+		get_device(dev);
+		phy_pdev = pdata->platdev;
+	}
+
+	return phy_pdev;
+}
+#else   /* CONFIG_OF */
+static struct xgbe_version_data *xgbe_of_vdata(struct xgbe_prv_data *pdata)
+{
+	return NULL;
+}
+
+static int xgbe_of_support(struct xgbe_prv_data *pdata)
+{
+	return -EINVAL;
+}
+
+static struct platform_device *xgbe_of_get_phy_pdev(struct xgbe_prv_data *pdata)
+{
+	return NULL;
+}
+#endif  /* CONFIG_OF */
+
+static unsigned int xgbe_resource_count(struct platform_device *pdev,
+					unsigned int type)
+{
+	unsigned int count;
+	int i;
+
+	for (i = 0, count = 0; i < pdev->num_resources; i++) {
+		struct resource *res = &pdev->resource[i];
+
+		if (type == resource_type(res))
+			count++;
+	}
+
+	return count;
+}
+
+static struct platform_device *xgbe_get_phy_pdev(struct xgbe_prv_data *pdata)
+{
+	struct platform_device *phy_pdev;
+
+	if (pdata->use_acpi) {
+		get_device(pdata->dev);
+		phy_pdev = pdata->platdev;
+	} else {
+		phy_pdev = xgbe_of_get_phy_pdev(pdata);
+	}
+
+	return phy_pdev;
+}
+
+static struct xgbe_version_data *xgbe_get_vdata(struct xgbe_prv_data *pdata)
+{
+	return pdata->use_acpi ? xgbe_acpi_vdata(pdata)
+			       : xgbe_of_vdata(pdata);
+}
+
+static int xgbe_platform_probe(struct platform_device *pdev)
+{
+	struct xgbe_prv_data *pdata;
+	struct device *dev = &pdev->dev;
+	struct platform_device *phy_pdev;
+	struct resource *res;
+	const char *phy_mode;
+	unsigned int phy_memnum, phy_irqnum;
+	unsigned int dma_irqnum, dma_irqend;
+	enum dev_dma_attr attr;
+	int ret;
+
+	pdata = xgbe_alloc_pdata(dev);
+	if (IS_ERR(pdata)) {
+		ret = PTR_ERR(pdata);
+		goto err_alloc;
+	}
+
+	pdata->platdev = pdev;
+	pdata->adev = ACPI_COMPANION(dev);
+	platform_set_drvdata(pdev, pdata);
+
+	/* Check if we should use ACPI or DT */
+	pdata->use_acpi = dev->of_node ? 0 : 1;
+
+	/* Get the version data */
+	pdata->vdata = xgbe_get_vdata(pdata);
+
+	phy_pdev = xgbe_get_phy_pdev(pdata);
+	if (!phy_pdev) {
+		dev_err(dev, "unable to obtain phy device\n");
+		ret = -EINVAL;
+		goto err_phydev;
+	}
+	pdata->phy_platdev = phy_pdev;
+	pdata->phy_dev = &phy_pdev->dev;
+
+	if (pdev == phy_pdev) {
+		/* New style device tree or ACPI:
+		 *   The XGBE and PHY resources are grouped together with
+		 *   the PHY resources listed last
+		 */
+		phy_memnum = xgbe_resource_count(pdev, IORESOURCE_MEM) - 3;
+		phy_irqnum = xgbe_resource_count(pdev, IORESOURCE_IRQ) - 1;
+		dma_irqnum = 1;
+		dma_irqend = phy_irqnum;
+	} else {
+		/* Old style device tree:
+		 *   The XGBE and PHY resources are separate
+		 */
+		phy_memnum = 0;
+		phy_irqnum = 0;
+		dma_irqnum = 1;
+		dma_irqend = xgbe_resource_count(pdev, IORESOURCE_IRQ);
+	}
+
+	/* Obtain the mmio areas for the device */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pdata->xgmac_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->xgmac_regs)) {
+		dev_err(dev, "xgmac ioremap failed\n");
+		ret = PTR_ERR(pdata->xgmac_regs);
+		goto err_io;
+	}
+	if (netif_msg_probe(pdata))
+		dev_dbg(dev, "xgmac_regs = %p\n", pdata->xgmac_regs);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	pdata->xpcs_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->xpcs_regs)) {
+		dev_err(dev, "xpcs ioremap failed\n");
+		ret = PTR_ERR(pdata->xpcs_regs);
+		goto err_io;
+	}
+	if (netif_msg_probe(pdata))
+		dev_dbg(dev, "xpcs_regs  = %p\n", pdata->xpcs_regs);
+
+	res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
+	pdata->rxtx_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->rxtx_regs)) {
+		dev_err(dev, "rxtx ioremap failed\n");
+		ret = PTR_ERR(pdata->rxtx_regs);
+		goto err_io;
+	}
+	if (netif_msg_probe(pdata))
+		dev_dbg(dev, "rxtx_regs  = %p\n", pdata->rxtx_regs);
+
+	res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
+	pdata->sir0_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->sir0_regs)) {
+		dev_err(dev, "sir0 ioremap failed\n");
+		ret = PTR_ERR(pdata->sir0_regs);
+		goto err_io;
+	}
+	if (netif_msg_probe(pdata))
+		dev_dbg(dev, "sir0_regs  = %p\n", pdata->sir0_regs);
+
+	res = platform_get_resource(phy_pdev, IORESOURCE_MEM, phy_memnum++);
+	pdata->sir1_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(pdata->sir1_regs)) {
+		dev_err(dev, "sir1 ioremap failed\n");
+		ret = PTR_ERR(pdata->sir1_regs);
+		goto err_io;
+	}
+	if (netif_msg_probe(pdata))
+		dev_dbg(dev, "sir1_regs  = %p\n", pdata->sir1_regs);
+
+	/* Retrieve the MAC address */
+	ret = device_property_read_u8_array(dev, XGBE_MAC_ADDR_PROPERTY,
+					    pdata->mac_addr,
+					    sizeof(pdata->mac_addr));
+	if (ret || !is_valid_ether_addr(pdata->mac_addr)) {
+		dev_err(dev, "invalid %s property\n", XGBE_MAC_ADDR_PROPERTY);
+		if (!ret)
+			ret = -EINVAL;
+		goto err_io;
+	}
+
+	/* Retrieve the PHY mode - it must be "xgmii" */
+	ret = device_property_read_string(dev, XGBE_PHY_MODE_PROPERTY,
+					  &phy_mode);
+	if (ret || strcmp(phy_mode, phy_modes(PHY_INTERFACE_MODE_XGMII))) {
+		dev_err(dev, "invalid %s property\n", XGBE_PHY_MODE_PROPERTY);
+		if (!ret)
+			ret = -EINVAL;
+		goto err_io;
+	}
+	pdata->phy_mode = PHY_INTERFACE_MODE_XGMII;
+
+	/* Check for per channel interrupt support */
+	if (device_property_present(dev, XGBE_DMA_IRQS_PROPERTY)) {
+		pdata->per_channel_irq = 1;
+		pdata->channel_irq_mode = XGBE_IRQ_MODE_EDGE;
+	}
+
+	/* Obtain device settings unique to ACPI/OF */
+	if (pdata->use_acpi)
+		ret = xgbe_acpi_support(pdata);
+	else
+		ret = xgbe_of_support(pdata);
+	if (ret)
+		goto err_io;
+
+	/* Set the DMA coherency values */
+	attr = device_get_dma_attr(dev);
+	if (attr == DEV_DMA_NOT_SUPPORTED) {
+		dev_err(dev, "DMA is not supported");
+		ret = -ENODEV;
+		goto err_io;
+	}
+	pdata->coherent = (attr == DEV_DMA_COHERENT);
+	if (pdata->coherent) {
+		pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
+		pdata->arcache = XGBE_DMA_OS_ARCACHE;
+		pdata->awcache = XGBE_DMA_OS_AWCACHE;
+	} else {
+		pdata->axdomain = XGBE_DMA_SYS_AXDOMAIN;
+		pdata->arcache = XGBE_DMA_SYS_ARCACHE;
+		pdata->awcache = XGBE_DMA_SYS_AWCACHE;
+	}
+
+	/* Set the maximum fifo amounts */
+	pdata->tx_max_fifo_size = pdata->vdata->tx_max_fifo_size;
+	pdata->rx_max_fifo_size = pdata->vdata->rx_max_fifo_size;
+
+	/* Set the hardware channel and queue counts */
+	xgbe_set_counts(pdata);
+
+	/* Always have XGMAC and XPCS (auto-negotiation) interrupts */
+	pdata->irq_count = 2;
+
+	/* Get the device interrupt */
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
+		dev_err(dev, "platform_get_irq 0 failed\n");
+		goto err_io;
+	}
+	pdata->dev_irq = ret;
+
+	/* Get the per channel DMA interrupts */
+	if (pdata->per_channel_irq) {
+		unsigned int i, max = ARRAY_SIZE(pdata->channel_irq);
+
+		for (i = 0; (i < max) && (dma_irqnum < dma_irqend); i++) {
+			ret = platform_get_irq(pdata->platdev, dma_irqnum++);
+			if (ret < 0) {
+				netdev_err(pdata->netdev,
+					   "platform_get_irq %u failed\n",
+					   dma_irqnum - 1);
+				goto err_io;
+			}
+
+			pdata->channel_irq[i] = ret;
+		}
+
+		pdata->channel_irq_count = max;
+
+		pdata->irq_count += max;
+	}
+
+	/* Get the auto-negotiation interrupt */
+	ret = platform_get_irq(phy_pdev, phy_irqnum++);
+	if (ret < 0) {
+		dev_err(dev, "platform_get_irq phy 0 failed\n");
+		goto err_io;
+	}
+	pdata->an_irq = ret;
+
+	/* Configure the netdev resource */
+	ret = xgbe_config_netdev(pdata);
+	if (ret)
+		goto err_io;
+
+	netdev_notice(pdata->netdev, "net device enabled\n");
+
+	return 0;
+
+err_io:
+	platform_device_put(phy_pdev);
+
+err_phydev:
+	xgbe_free_pdata(pdata);
+
+err_alloc:
+	dev_notice(dev, "net device not enabled\n");
+
+	return ret;
+}
+
+static int xgbe_platform_remove(struct platform_device *pdev)
+{
+	struct xgbe_prv_data *pdata = platform_get_drvdata(pdev);
+
+	xgbe_deconfig_netdev(pdata);
+
+	platform_device_put(pdata->phy_platdev);
+
+	xgbe_free_pdata(pdata);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int xgbe_platform_suspend(struct device *dev)
+{
+	struct xgbe_prv_data *pdata = dev_get_drvdata(dev);
+	struct net_device *netdev = pdata->netdev;
+	int ret = 0;
+
+	DBGPR("-->xgbe_suspend\n");
+
+	if (netif_running(netdev))
+		ret = xgbe_powerdown(netdev, XGMAC_DRIVER_CONTEXT);
+
+	pdata->lpm_ctrl = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
+	pdata->lpm_ctrl |= MDIO_CTRL1_LPOWER;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+	DBGPR("<--xgbe_suspend\n");
+
+	return ret;
+}
+
+static int xgbe_platform_resume(struct device *dev)
+{
+	struct xgbe_prv_data *pdata = dev_get_drvdata(dev);
+	struct net_device *netdev = pdata->netdev;
+	int ret = 0;
+
+	DBGPR("-->xgbe_resume\n");
+
+	pdata->lpm_ctrl &= ~MDIO_CTRL1_LPOWER;
+	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, pdata->lpm_ctrl);
+
+	if (netif_running(netdev)) {
+		ret = xgbe_powerup(netdev, XGMAC_DRIVER_CONTEXT);
+
+		/* Schedule a restart in case the link or phy state changed
+		 * while we were powered down.
+		 */
+		schedule_work(&pdata->restart_work);
+	}
+
+	DBGPR("<--xgbe_resume\n");
+
+	return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct xgbe_version_data xgbe_v1 = {
+	.init_function_ptrs_phy_impl	= xgbe_init_function_ptrs_phy_v1,
+	.xpcs_access			= XGBE_XPCS_ACCESS_V1,
+	.tx_max_fifo_size		= 81920,
+	.rx_max_fifo_size		= 81920,
+	.tx_tstamp_workaround		= 1,
+};
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id xgbe_acpi_match[] = {
+	{ .id = "AMDI8001",
+	  .driver_data = (kernel_ulong_t)&xgbe_v1 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(acpi, xgbe_acpi_match);
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id xgbe_of_match[] = {
+	{ .compatible = "amd,xgbe-seattle-v1a",
+	  .data = &xgbe_v1 },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, xgbe_of_match);
+#endif
+
+static SIMPLE_DEV_PM_OPS(xgbe_platform_pm_ops,
+			 xgbe_platform_suspend, xgbe_platform_resume);
+
+static struct platform_driver xgbe_driver = {
+	.driver = {
+		.name = XGBE_DRV_NAME,
+#ifdef CONFIG_ACPI
+		.acpi_match_table = xgbe_acpi_match,
+#endif
+#ifdef CONFIG_OF
+		.of_match_table = xgbe_of_match,
+#endif
+		.pm = &xgbe_platform_pm_ops,
+	},
+	.probe = xgbe_platform_probe,
+	.remove = xgbe_platform_remove,
+};
+
+int xgbe_platform_init(void)
+{
+	return platform_driver_register(&xgbe_driver);
+}
+
+void xgbe_platform_exit(void)
+{
+	platform_driver_unregister(&xgbe_driver);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c	2017-02-12 16:03:20.000000000 -0500
@@ -122,7 +122,7 @@
 #include "xgbe.h"
 #include "xgbe-common.h"
 
-static cycle_t xgbe_cc_read(const struct cyclecounter *cc)
+static u64 xgbe_cc_read(const struct cyclecounter *cc)
 {
 	struct xgbe_prv_data *pdata = container_of(cc,
 						   struct xgbe_prv_data,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,6 +52,7 @@ static void xgene_cle_dbptr_to_hw(struct
 {
 	buf[0] = SET_VAL(CLE_DROP, dbptr->drop);
 	buf[4] = SET_VAL(CLE_FPSEL, dbptr->fpsel) |
+		 SET_VAL(CLE_NFPSEL, dbptr->nxtfpsel) |
 		 SET_VAL(CLE_DSTQIDL, dbptr->dstqid);
 
 	buf[5] = SET_VAL(CLE_DSTQIDH, (u32)dbptr->dstqid >> CLE_DSTQIDL_LEN) |
@@ -78,10 +79,10 @@ static void xgene_cle_kn_to_hw(struct xg
 	}
 }
 
-static void xgene_cle_dn_to_hw(struct xgene_cle_ptree_ewdn *dn,
+static void xgene_cle_dn_to_hw(const struct xgene_cle_ptree_ewdn *dn,
 			       u32 *buf, u32 jb)
 {
-	struct xgene_cle_ptree_branch *br;
+	const struct xgene_cle_ptree_branch *br;
 	u32 i, j = 0;
 	u32 npp;
 
@@ -204,17 +205,385 @@ static int xgene_cle_setup_dbptr(struct
 	return 0;
 }
 
+static const struct xgene_cle_ptree_ewdn xgene_init_ptree_dn[] = {
+	{
+		/* PKT_TYPE_NODE */
+		.node_type = EWDN,
+		.last_node = 0,
+		.hdr_len_store = 1,
+		.hdr_extn = NO_BYTE,
+		.byte_store = NO_BYTE,
+		.search_byte_store = NO_BYTE,
+		.result_pointer = DB_RES_DROP,
+		.num_branches = 2,
+		.branch = {
+			{
+				/* IPV4 */
+				.valid = 1,
+				.next_packet_pointer = 22,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = PKT_PROT_NODE,
+				.next_branch = 0,
+				.data = 0x8,
+				.mask = 0x0
+			},
+			{
+				.valid = 0,
+				.next_packet_pointer = 262,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = LAST_NODE,
+				.next_branch = 0,
+				.data = 0x0,
+				.mask = 0xffff
+			}
+		},
+	},
+	{
+		/* PKT_PROT_NODE */
+		.node_type = EWDN,
+		.last_node = 0,
+		.hdr_len_store = 1,
+		.hdr_extn = NO_BYTE,
+		.byte_store = NO_BYTE,
+		.search_byte_store = NO_BYTE,
+		.result_pointer = DB_RES_DROP,
+		.num_branches = 3,
+		.branch = {
+			{
+				/* TCP */
+				.valid = 1,
+				.next_packet_pointer = 26,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_TCP_NODE,
+				.next_branch = 0,
+				.data = 0x0600,
+				.mask = 0x00ff
+			},
+			{
+				/* UDP */
+				.valid = 1,
+				.next_packet_pointer = 26,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_UDP_NODE,
+				.next_branch = 0,
+				.data = 0x1100,
+				.mask = 0x00ff
+			},
+			{
+				.valid = 0,
+				.next_packet_pointer = 26,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_OTHERS_NODE,
+				.next_branch = 0,
+				.data = 0x0,
+				.mask = 0xffff
+			}
+		}
+	},
+	{
+		/* RSS_IPV4_TCP_NODE */
+		.node_type = EWDN,
+		.last_node = 0,
+		.hdr_len_store = 1,
+		.hdr_extn = NO_BYTE,
+		.byte_store = NO_BYTE,
+		.search_byte_store = BOTH_BYTES,
+		.result_pointer = DB_RES_DROP,
+		.num_branches = 6,
+		.branch = {
+			{
+				/* SRC IPV4 B01 */
+				.valid = 0,
+				.next_packet_pointer = 28,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_TCP_NODE,
+				.next_branch = 1,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* SRC IPV4 B23 */
+				.valid = 0,
+				.next_packet_pointer = 30,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_TCP_NODE,
+				.next_branch = 2,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* DST IPV4 B01 */
+				.valid = 0,
+				.next_packet_pointer = 32,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_TCP_NODE,
+				.next_branch = 3,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* DST IPV4 B23 */
+				.valid = 0,
+				.next_packet_pointer = 34,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_TCP_NODE,
+				.next_branch = 4,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* TCP SRC Port */
+				.valid = 0,
+				.next_packet_pointer = 36,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_TCP_NODE,
+				.next_branch = 5,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* TCP DST Port */
+				.valid = 0,
+				.next_packet_pointer = 256,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = LAST_NODE,
+				.next_branch = 0,
+				.data = 0x0,
+				.mask = 0xffff
+			}
+		}
+	},
+	{
+		/* RSS_IPV4_UDP_NODE */
+		.node_type = EWDN,
+		.last_node = 0,
+		.hdr_len_store = 1,
+		.hdr_extn = NO_BYTE,
+		.byte_store = NO_BYTE,
+		.search_byte_store = BOTH_BYTES,
+		.result_pointer = DB_RES_DROP,
+		.num_branches = 6,
+		.branch = {
+			{
+				/* SRC IPV4 B01 */
+				.valid = 0,
+				.next_packet_pointer = 28,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_UDP_NODE,
+				.next_branch = 1,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* SRC IPV4 B23 */
+				.valid = 0,
+				.next_packet_pointer = 30,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_UDP_NODE,
+				.next_branch = 2,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* DST IPV4 B01 */
+				.valid = 0,
+				.next_packet_pointer = 32,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_UDP_NODE,
+				.next_branch = 3,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* DST IPV4 B23 */
+				.valid = 0,
+				.next_packet_pointer = 34,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_UDP_NODE,
+				.next_branch = 4,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* TCP SRC Port */
+				.valid = 0,
+				.next_packet_pointer = 36,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_UDP_NODE,
+				.next_branch = 5,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* TCP DST Port */
+				.valid = 0,
+				.next_packet_pointer = 258,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = LAST_NODE,
+				.next_branch = 0,
+				.data = 0x0,
+				.mask = 0xffff
+			}
+		}
+	},
+	{
+		/* RSS_IPV4_OTHERS_NODE */
+		.node_type = EWDN,
+		.last_node = 0,
+		.hdr_len_store = 1,
+		.hdr_extn = NO_BYTE,
+		.byte_store = NO_BYTE,
+		.search_byte_store = BOTH_BYTES,
+		.result_pointer = DB_RES_DROP,
+		.num_branches = 6,
+		.branch = {
+			{
+				/* SRC IPV4 B01 */
+				.valid = 0,
+				.next_packet_pointer = 28,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_OTHERS_NODE,
+				.next_branch = 1,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* SRC IPV4 B23 */
+				.valid = 0,
+				.next_packet_pointer = 30,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_OTHERS_NODE,
+				.next_branch = 2,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* DST IPV4 B01 */
+				.valid = 0,
+				.next_packet_pointer = 32,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_OTHERS_NODE,
+				.next_branch = 3,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* DST IPV4 B23 */
+				.valid = 0,
+				.next_packet_pointer = 34,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_OTHERS_NODE,
+				.next_branch = 4,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* TCP SRC Port */
+				.valid = 0,
+				.next_packet_pointer = 36,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = RSS_IPV4_OTHERS_NODE,
+				.next_branch = 5,
+				.data = 0x0,
+				.mask = 0xffff
+			},
+			{
+				/* TCP DST Port */
+				.valid = 0,
+				.next_packet_pointer = 260,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = LAST_NODE,
+				.next_branch = 0,
+				.data = 0x0,
+				.mask = 0xffff
+			}
+		}
+	},
+
+	{
+		/* LAST NODE */
+		.node_type = EWDN,
+		.last_node = 1,
+		.hdr_len_store = 1,
+		.hdr_extn = NO_BYTE,
+		.byte_store = NO_BYTE,
+		.search_byte_store = NO_BYTE,
+		.result_pointer = DB_RES_DROP,
+		.num_branches = 1,
+		.branch = {
+			{
+				.valid = 0,
+				.next_packet_pointer = 0,
+				.jump_bw = JMP_FW,
+				.jump_rel = JMP_ABS,
+				.operation = EQT,
+				.next_node = MAX_NODES,
+				.next_branch = 0,
+				.data = 0,
+				.mask = 0xffff
+			}
+		}
+	}
+};
+
 static int xgene_cle_setup_node(struct xgene_enet_pdata *pdata,
 				struct xgene_enet_cle *cle)
 {
 	struct xgene_cle_ptree *ptree = &cle->ptree;
-	struct xgene_cle_ptree_ewdn *dn = ptree->dn;
+	const struct xgene_cle_ptree_ewdn *dn = xgene_init_ptree_dn;
+	int num_dn = ARRAY_SIZE(xgene_init_ptree_dn);
 	struct xgene_cle_ptree_kn *kn = ptree->kn;
 	u32 buf[CLE_DRAM_REGS];
 	int i, j, ret;
 
 	memset(buf, 0, sizeof(buf));
-	for (i = 0; i < ptree->num_dn; i++) {
+	for (i = 0; i < num_dn; i++) {
 		xgene_cle_dn_to_hw(&dn[i], buf, cle->jump_bytes);
 		ret = xgene_cle_dram_wr(cle, buf, 17, i + ptree->start_node,
 					PTREE_RAM, CLE_CMD_WR);
@@ -224,8 +593,8 @@ static int xgene_cle_setup_node(struct x
 
 	/* continue node index for key node */
 	memset(buf, 0, sizeof(buf));
-	for (j = i; j < (ptree->num_kn + ptree->num_dn); j++) {
-		xgene_cle_kn_to_hw(&kn[j - ptree->num_dn], buf);
+	for (j = i; j < (ptree->num_kn + num_dn); j++) {
+		xgene_cle_kn_to_hw(&kn[j - num_dn], buf);
 		ret = xgene_cle_dram_wr(cle, buf, 17, j + ptree->start_node,
 					PTREE_RAM, CLE_CMD_WR);
 		if (ret)
@@ -346,11 +715,15 @@ static int xgene_cle_set_rss_idt(struct
 	for (i = 0; i < XGENE_CLE_IDT_ENTRIES; i++) {
 		idx = i % pdata->rxq_cnt;
 		pool_id = pdata->rx_ring[idx]->buf_pool->id;
-		fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+		fpsel = xgene_enet_get_fpsel(pool_id);
 		dstqid = xgene_enet_dst_ring_num(pdata->rx_ring[idx]);
 		nfpsel = 0;
-		idt_reg = 0;
+		if (pdata->rx_ring[idx]->page_pool) {
+			pool_id = pdata->rx_ring[idx]->page_pool->id;
+			nfpsel = xgene_enet_get_fpsel(pool_id);
+		}
 
+		idt_reg = 0;
 		xgene_cle_idt_to_hw(pdata, dstqid, fpsel, nfpsel, &idt_reg);
 		ret = xgene_cle_dram_wr(&pdata->cle, &idt_reg, 1, i,
 					RSS_IDT, CLE_CMD_WR);
@@ -400,320 +773,41 @@ static int xgene_cle_setup_rss(struct xg
 static int xgene_enet_cle_init(struct xgene_enet_pdata *pdata)
 {
 	struct xgene_enet_cle *enet_cle = &pdata->cle;
+	u32 def_qid, def_fpsel, def_nxtfpsel, pool_id;
 	struct xgene_cle_dbptr dbptr[DB_MAX_PTRS];
-	struct xgene_cle_ptree_branch *br;
-	u32 def_qid, def_fpsel, pool_id;
 	struct xgene_cle_ptree *ptree;
 	struct xgene_cle_ptree_kn kn;
 	int ret;
-	struct xgene_cle_ptree_ewdn ptree_dn[] = {
-		{
-			/* PKT_TYPE_NODE */
-			.node_type = EWDN,
-			.last_node = 0,
-			.hdr_len_store = 1,
-			.hdr_extn = NO_BYTE,
-			.byte_store = NO_BYTE,
-			.search_byte_store = NO_BYTE,
-			.result_pointer = DB_RES_DROP,
-			.num_branches = 2,
-			.branch = {
-				{
-					/* IPV4 */
-					.valid = 1,
-					.next_packet_pointer = 22,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = PKT_PROT_NODE,
-					.next_branch = 0,
-					.data = 0x8,
-					.mask = 0x0
-				},
-				{
-					.valid = 0,
-					.next_packet_pointer = 262,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = LAST_NODE,
-					.next_branch = 0,
-					.data = 0x0,
-					.mask = 0xffff
-				}
-			},
-		},
-		{
-			/* PKT_PROT_NODE */
-			.node_type = EWDN,
-			.last_node = 0,
-			.hdr_len_store = 1,
-			.hdr_extn = NO_BYTE,
-			.byte_store = NO_BYTE,
-			.search_byte_store = NO_BYTE,
-			.result_pointer = DB_RES_DROP,
-			.num_branches = 3,
-			.branch = {
-				{
-					/* TCP */
-					.valid = 1,
-					.next_packet_pointer = 26,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_TCP_NODE,
-					.next_branch = 0,
-					.data = 0x0600,
-					.mask = 0x00ff
-				},
-				{
-					/* UDP */
-					.valid = 1,
-					.next_packet_pointer = 26,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_UDP_NODE,
-					.next_branch = 0,
-					.data = 0x1100,
-					.mask = 0x00ff
-				},
-				{
-					.valid = 0,
-					.next_packet_pointer = 260,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = LAST_NODE,
-					.next_branch = 0,
-					.data = 0x0,
-					.mask = 0xffff
-				}
-			}
-		},
-		{
-			/* RSS_IPV4_TCP_NODE */
-			.node_type = EWDN,
-			.last_node = 0,
-			.hdr_len_store = 1,
-			.hdr_extn = NO_BYTE,
-			.byte_store = NO_BYTE,
-			.search_byte_store = BOTH_BYTES,
-			.result_pointer = DB_RES_DROP,
-			.num_branches = 6,
-			.branch = {
-				{
-					/* SRC IPV4 B01 */
-					.valid = 0,
-					.next_packet_pointer = 28,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_TCP_NODE,
-					.next_branch = 1,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* SRC IPV4 B23 */
-					.valid = 0,
-					.next_packet_pointer = 30,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_TCP_NODE,
-					.next_branch = 2,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* DST IPV4 B01 */
-					.valid = 0,
-					.next_packet_pointer = 32,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_TCP_NODE,
-					.next_branch = 3,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* DST IPV4 B23 */
-					.valid = 0,
-					.next_packet_pointer = 34,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_TCP_NODE,
-					.next_branch = 4,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* TCP SRC Port */
-					.valid = 0,
-					.next_packet_pointer = 36,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_TCP_NODE,
-					.next_branch = 5,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* TCP DST Port */
-					.valid = 0,
-					.next_packet_pointer = 256,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = LAST_NODE,
-					.next_branch = 0,
-					.data = 0x0,
-					.mask = 0xffff
-				}
-			}
-		},
-		{
-			/* RSS_IPV4_UDP_NODE */
-			.node_type = EWDN,
-			.last_node = 0,
-			.hdr_len_store = 1,
-			.hdr_extn = NO_BYTE,
-			.byte_store = NO_BYTE,
-			.search_byte_store = BOTH_BYTES,
-			.result_pointer = DB_RES_DROP,
-			.num_branches = 6,
-			.branch = {
-				{
-					/* SRC IPV4 B01 */
-					.valid = 0,
-					.next_packet_pointer = 28,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_UDP_NODE,
-					.next_branch = 1,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* SRC IPV4 B23 */
-					.valid = 0,
-					.next_packet_pointer = 30,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_UDP_NODE,
-					.next_branch = 2,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* DST IPV4 B01 */
-					.valid = 0,
-					.next_packet_pointer = 32,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_UDP_NODE,
-					.next_branch = 3,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* DST IPV4 B23 */
-					.valid = 0,
-					.next_packet_pointer = 34,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_UDP_NODE,
-					.next_branch = 4,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* TCP SRC Port */
-					.valid = 0,
-					.next_packet_pointer = 36,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = RSS_IPV4_UDP_NODE,
-					.next_branch = 5,
-					.data = 0x0,
-					.mask = 0xffff
-				},
-				{
-					/* TCP DST Port */
-					.valid = 0,
-					.next_packet_pointer = 258,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = LAST_NODE,
-					.next_branch = 0,
-					.data = 0x0,
-					.mask = 0xffff
-				}
-			}
-		},
-		{
-			/* LAST NODE */
-			.node_type = EWDN,
-			.last_node = 1,
-			.hdr_len_store = 1,
-			.hdr_extn = NO_BYTE,
-			.byte_store = NO_BYTE,
-			.search_byte_store = NO_BYTE,
-			.result_pointer = DB_RES_DROP,
-			.num_branches = 1,
-			.branch = {
-				{
-					.valid = 0,
-					.next_packet_pointer = 0,
-					.jump_bw = JMP_FW,
-					.jump_rel = JMP_ABS,
-					.operation = EQT,
-					.next_node = MAX_NODES,
-					.next_branch = 0,
-					.data = 0,
-					.mask = 0xffff
-				}
-			}
-		}
-	};
+
+	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+		return -EINVAL;
 
 	ptree = &enet_cle->ptree;
 	ptree->start_pkt = 12; /* Ethertype */
-	if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
-		ret = xgene_cle_setup_rss(pdata);
-		if (ret) {
-			netdev_err(pdata->ndev, "RSS initialization failed\n");
-			return ret;
-		}
-	} else {
-		br = &ptree_dn[PKT_PROT_NODE].branch[0];
-		br->valid = 0;
-		br->next_packet_pointer = 260;
-		br->next_node = LAST_NODE;
-		br->data = 0x0000;
-		br->mask = 0xffff;
+
+	ret = xgene_cle_setup_rss(pdata);
+	if (ret) {
+		netdev_err(pdata->ndev, "RSS initialization failed\n");
+		return ret;
 	}
 
 	def_qid = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
 	pool_id = pdata->rx_ring[0]->buf_pool->id;
-	def_fpsel = xgene_enet_ring_bufnum(pool_id) - 0x20;
+	def_fpsel = xgene_enet_get_fpsel(pool_id);
+	def_nxtfpsel = 0;
+	if (pdata->rx_ring[0]->page_pool) {
+		pool_id = pdata->rx_ring[0]->page_pool->id;
+		def_nxtfpsel = xgene_enet_get_fpsel(pool_id);
+	}
 
 	memset(dbptr, 0, sizeof(struct xgene_cle_dbptr) * DB_MAX_PTRS);
 	dbptr[DB_RES_ACCEPT].fpsel =  def_fpsel;
+	dbptr[DB_RES_ACCEPT].nxtfpsel = def_nxtfpsel;
 	dbptr[DB_RES_ACCEPT].dstqid = def_qid;
 	dbptr[DB_RES_ACCEPT].cle_priority = 1;
 
 	dbptr[DB_RES_DEF].fpsel = def_fpsel;
+	dbptr[DB_RES_DEF].nxtfpsel = def_nxtfpsel;
 	dbptr[DB_RES_DEF].dstqid = def_qid;
 	dbptr[DB_RES_DEF].cle_priority = 7;
 	xgene_cle_setup_def_dbptr(pdata, enet_cle, &dbptr[DB_RES_DEF],
@@ -727,10 +821,8 @@ static int xgene_enet_cle_init(struct xg
 	kn.key[0].priority = 0;
 	kn.key[0].result_pointer = DB_RES_ACCEPT;
 
-	ptree->dn = ptree_dn;
 	ptree->kn = &kn;
 	ptree->dbptr = dbptr;
-	ptree->num_dn = MAX_NODES;
 	ptree->num_kn = 1;
 	ptree->num_dbptr = DB_MAX_PTRS;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_cle.h	2017-02-12 16:03:20.000000000 -0500
@@ -91,6 +91,8 @@
 #define CLE_DSTQIDH_LEN		5
 #define CLE_FPSEL_POS		21
 #define CLE_FPSEL_LEN		4
+#define CLE_NFPSEL_POS		17
+#define CLE_NFPSEL_LEN		4
 #define CLE_PRIORITY_POS	5
 #define CLE_PRIORITY_LEN	3
 
@@ -104,6 +106,7 @@ enum xgene_cle_ptree_nodes {
 	PKT_PROT_NODE,
 	RSS_IPV4_TCP_NODE,
 	RSS_IPV4_UDP_NODE,
+	RSS_IPV4_OTHERS_NODE,
 	LAST_NODE,
 	MAX_NODES
 };
@@ -275,10 +278,8 @@ struct xgene_cle_dbptr {
 };
 
 struct xgene_cle_ptree {
-	struct xgene_cle_ptree_ewdn *dn;
 	struct xgene_cle_ptree_kn *kn;
 	struct xgene_cle_dbptr *dbptr;
-	u32 num_dn;
 	u32 num_kn;
 	u32 num_dbptr;
 	u32 start_node;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -163,6 +163,74 @@ static void xgene_get_ethtool_stats(stru
 		*data++ = *(u64 *)(pdata + gstrings_stats[i].offset);
 }
 
+static void xgene_get_pauseparam(struct net_device *ndev,
+				 struct ethtool_pauseparam *pp)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+
+	pp->autoneg = pdata->pause_autoneg;
+	pp->tx_pause = pdata->tx_pause;
+	pp->rx_pause = pdata->rx_pause;
+}
+
+static int xgene_set_pauseparam(struct net_device *ndev,
+				struct ethtool_pauseparam *pp)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct phy_device *phydev = ndev->phydev;
+	u32 oldadv, newadv;
+
+	if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII ||
+	    pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
+		if (!phydev)
+			return -EINVAL;
+
+		if (!(phydev->supported & SUPPORTED_Pause) ||
+		    (!(phydev->supported & SUPPORTED_Asym_Pause) &&
+		     pp->rx_pause != pp->tx_pause))
+			return -EINVAL;
+
+		pdata->pause_autoneg = pp->autoneg;
+		pdata->tx_pause = pp->tx_pause;
+		pdata->rx_pause = pp->rx_pause;
+
+		oldadv = phydev->advertising;
+		newadv = oldadv & ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
+
+		if (pp->rx_pause)
+			newadv |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+
+		if (pp->tx_pause)
+			newadv ^= ADVERTISED_Asym_Pause;
+
+		if (oldadv ^ newadv) {
+			phydev->advertising = newadv;
+
+			if (phydev->autoneg)
+				return phy_start_aneg(phydev);
+
+			if (!pp->autoneg) {
+				pdata->mac_ops->flowctl_tx(pdata,
+							   pdata->tx_pause);
+				pdata->mac_ops->flowctl_rx(pdata,
+							   pdata->rx_pause);
+			}
+		}
+
+	} else {
+		if (pp->autoneg)
+			return -EINVAL;
+
+		pdata->tx_pause = pp->tx_pause;
+		pdata->rx_pause = pp->rx_pause;
+
+		pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
+		pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
+	}
+
+	return 0;
+}
+
 static const struct ethtool_ops xgene_ethtool_ops = {
 	.get_drvinfo = xgene_get_drvinfo,
 	.get_link = ethtool_op_get_link,
@@ -171,6 +239,8 @@ static const struct ethtool_ops xgene_et
 	.get_ethtool_stats = xgene_get_ethtool_stats,
 	.get_link_ksettings = xgene_get_link_ksettings,
 	.set_link_ksettings = xgene_set_link_ksettings,
+	.get_pauseparam = xgene_get_pauseparam,
+	.set_pauseparam = xgene_set_pauseparam
 };
 
 void xgene_enet_set_ethtool_ops(struct net_device *ndev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c	2017-02-12 16:03:20.000000000 -0500
@@ -504,6 +504,56 @@ static void xgene_gmac_set_speed(struct
 	xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2);
 }
 
+static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+	xgene_enet_wr_mcx_mac(pdata, MAX_FRAME_LEN_ADDR, size);
+}
+
+static void xgene_gmac_enable_tx_pause(struct xgene_enet_pdata *pdata,
+				       bool enable)
+{
+	u32 data;
+
+	xgene_enet_rd_mcx_csr(pdata, CSR_ECM_CFG_0_ADDR, &data);
+
+	if (enable)
+		data |= MULTI_DPF_AUTOCTRL | PAUSE_XON_EN;
+	else
+		data &= ~(MULTI_DPF_AUTOCTRL | PAUSE_XON_EN);
+
+	xgene_enet_wr_mcx_csr(pdata, CSR_ECM_CFG_0_ADDR, data);
+}
+
+static void xgene_gmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
+{
+	u32 data;
+
+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+
+	if (enable)
+		data |= TX_FLOW_EN;
+	else
+		data &= ~TX_FLOW_EN;
+
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
+
+	pdata->mac_ops->enable_tx_pause(pdata, enable);
+}
+
+static void xgene_gmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
+{
+	u32 data;
+
+	xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data);
+
+	if (enable)
+		data |= RX_FLOW_EN;
+	else
+		data &= ~RX_FLOW_EN;
+
+	xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data);
+}
+
 static void xgene_gmac_init(struct xgene_enet_pdata *pdata)
 {
 	u32 value;
@@ -527,6 +577,17 @@ static void xgene_gmac_init(struct xgene
 	/* Rtype should be copied from FP */
 	xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0);
 
+	/* Configure HW pause frame generation */
+	xgene_enet_rd_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, &value);
+	value = (DEF_QUANTA << 16) | (value & 0xFFFF);
+	xgene_enet_wr_mcx_csr(pdata, CSR_MULTI_DPF0_ADDR, value);
+
+	xgene_enet_wr_csr(pdata, RXBUF_PAUSE_THRESH, DEF_PAUSE_THRES);
+	xgene_enet_wr_csr(pdata, RXBUF_PAUSE_OFF_THRESH, DEF_PAUSE_OFF_THRES);
+
+	xgene_gmac_flowctl_tx(pdata, pdata->tx_pause);
+	xgene_gmac_flowctl_rx(pdata, pdata->rx_pause);
+
 	/* Rx-Tx traffic resume */
 	xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0);
 
@@ -550,12 +611,14 @@ static void xgene_enet_config_ring_if_as
 }
 
 static void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata,
-				  u32 dst_ring_num, u16 bufpool_id)
+				  u32 dst_ring_num, u16 bufpool_id,
+				  u16 nxtbufpool_id)
 {
 	u32 cb;
-	u32 fpsel;
+	u32 fpsel, nxtfpsel;
 
-	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+	fpsel = xgene_enet_get_fpsel(bufpool_id);
+	nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
 
 	xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb);
 	cb |= CFG_CLE_BYPASS_EN0;
@@ -565,6 +628,7 @@ static void xgene_enet_cle_bypass(struct
 	xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb);
 	CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
 	CFG_CLE_FPSEL0_SET(&cb, fpsel);
+	CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
 	xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb);
 }
 
@@ -652,16 +716,14 @@ static int xgene_enet_reset(struct xgene
 static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
 			     struct xgene_enet_desc_ring *ring)
 {
-	u32 addr, val, data;
-
-	val = xgene_enet_ring_bufnum(ring->id);
+	u32 addr, data;
 
 	if (xgene_enet_is_bufpool(ring->id)) {
 		addr = ENET_CFGSSQMIFPRESET_ADDR;
-		data = BIT(val - 0x20);
+		data = BIT(xgene_enet_get_fpsel(ring->id));
 	} else {
 		addr = ENET_CFGSSQMIWQRESET_ADDR;
-		data = BIT(val);
+		data = BIT(xgene_enet_ring_bufnum(ring->id));
 	}
 
 	xgene_enet_wr_ring_if(pdata, addr, data);
@@ -671,24 +733,24 @@ static void xgene_gport_shutdown(struct
 {
 	struct device *dev = &pdata->pdev->dev;
 	struct xgene_enet_desc_ring *ring;
-	u32 pb, val;
+	u32 pb;
 	int i;
 
 	pb = 0;
 	for (i = 0; i < pdata->rxq_cnt; i++) {
 		ring = pdata->rx_ring[i]->buf_pool;
+		pb |= BIT(xgene_enet_get_fpsel(ring->id));
+		ring = pdata->rx_ring[i]->page_pool;
+		if (ring)
+			pb |= BIT(xgene_enet_get_fpsel(ring->id));
 
-		val = xgene_enet_ring_bufnum(ring->id);
-		pb |= BIT(val - 0x20);
 	}
 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
 
 	pb = 0;
 	for (i = 0; i < pdata->txq_cnt; i++) {
 		ring = pdata->tx_ring[i];
-
-		val = xgene_enet_ring_bufnum(ring->id);
-		pb |= BIT(val);
+		pb |= BIT(xgene_enet_ring_bufnum(ring->id));
 	}
 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
 
@@ -698,6 +760,48 @@ static void xgene_gport_shutdown(struct
 	}
 }
 
+static u32 xgene_enet_flowctrl_cfg(struct net_device *ndev)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct phy_device *phydev = ndev->phydev;
+	u16 lcladv, rmtadv = 0;
+	u32 rx_pause, tx_pause;
+	u8 flowctl = 0;
+
+	if (!phydev->duplex || !pdata->pause_autoneg)
+		return 0;
+
+	if (pdata->tx_pause)
+		flowctl |= FLOW_CTRL_TX;
+
+	if (pdata->rx_pause)
+		flowctl |= FLOW_CTRL_RX;
+
+	lcladv = mii_advertise_flowctrl(flowctl);
+
+	if (phydev->pause)
+		rmtadv = LPA_PAUSE_CAP;
+
+	if (phydev->asym_pause)
+		rmtadv |= LPA_PAUSE_ASYM;
+
+	flowctl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+	tx_pause = !!(flowctl & FLOW_CTRL_TX);
+	rx_pause = !!(flowctl & FLOW_CTRL_RX);
+
+	if (tx_pause != pdata->tx_pause) {
+		pdata->tx_pause = tx_pause;
+		pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
+	}
+
+	if (rx_pause != pdata->rx_pause) {
+		pdata->rx_pause = rx_pause;
+		pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
+	}
+
+	return 0;
+}
+
 static void xgene_enet_adjust_link(struct net_device *ndev)
 {
 	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
@@ -712,6 +816,8 @@ static void xgene_enet_adjust_link(struc
 			mac_ops->tx_enable(pdata);
 			phy_print_status(phydev);
 		}
+
+		xgene_enet_flowctrl_cfg(ndev);
 	} else {
 		mac_ops->rx_disable(pdata);
 		mac_ops->tx_disable(pdata);
@@ -785,6 +891,8 @@ int xgene_enet_phy_connect(struct net_de
 	phy_dev->supported &= ~SUPPORTED_10baseT_Half &
 			      ~SUPPORTED_100baseT_Half &
 			      ~SUPPORTED_1000baseT_Half;
+	phy_dev->supported |= SUPPORTED_Pause |
+			      SUPPORTED_Asym_Pause;
 	phy_dev->advertising = phy_dev->supported;
 
 	return 0;
@@ -902,6 +1010,10 @@ const struct xgene_mac_ops xgene_gmac_op
 	.tx_disable = xgene_gmac_tx_disable,
 	.set_speed = xgene_gmac_set_speed,
 	.set_mac_addr = xgene_gmac_set_mac_addr,
+	.set_framesize = xgene_enet_set_frame_size,
+	.enable_tx_pause = xgene_gmac_enable_tx_pause,
+	.flowctl_tx     = xgene_gmac_flowctl_tx,
+	.flowctl_rx     = xgene_gmac_flowctl_rx,
 };
 
 const struct xgene_port_ops xgene_gport_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h	2017-02-12 16:03:20.000000000 -0500
@@ -165,10 +165,23 @@ enum xgene_enet_rm {
 #define CFG_CLE_IP_PROTOCOL0_SET(dst, val)	xgene_set_bits(dst, val, 16, 2)
 #define CFG_CLE_DSTQID0_SET(dst, val)		xgene_set_bits(dst, val, 0, 12)
 #define CFG_CLE_FPSEL0_SET(dst, val)		xgene_set_bits(dst, val, 16, 4)
+#define CFG_CLE_NXTFPSEL0_SET(dst, val)		xgene_set_bits(dst, val, 20, 4)
 #define CFG_MACMODE_SET(dst, val)		xgene_set_bits(dst, val, 18, 2)
 #define CFG_WAITASYNCRD_SET(dst, val)		xgene_set_bits(dst, val, 0, 16)
-#define CFG_CLE_DSTQID0(val)		(val & GENMASK(11, 0))
-#define CFG_CLE_FPSEL0(val)		((val << 16) & GENMASK(19, 16))
+#define CFG_CLE_DSTQID0(val)		((val) & GENMASK(11, 0))
+#define CFG_CLE_FPSEL0(val)		(((val) << 16) & GENMASK(19, 16))
+#define CSR_ECM_CFG_0_ADDR		0x0220
+#define CSR_ECM_CFG_1_ADDR		0x0224
+#define CSR_MULTI_DPF0_ADDR		0x0230
+#define RXBUF_PAUSE_THRESH		0x0534
+#define RXBUF_PAUSE_OFF_THRESH		0x0540
+#define DEF_PAUSE_THRES			0x7d
+#define DEF_PAUSE_OFF_THRES		0x6d
+#define DEF_QUANTA			0x8000
+#define NORM_PAUSE_OPCODE		0x0001
+#define PAUSE_XON_EN			BIT(30)
+#define MULTI_DPF_AUTOCTRL		BIT(28)
+#define CFG_CLE_NXTFPSEL0(val)		(((val) << 20) & GENMASK(23, 20))
 #define ICM_CONFIG0_REG_0_ADDR		0x0400
 #define ICM_CONFIG2_REG_0_ADDR		0x0410
 #define RX_DV_GATE_REG_0_ADDR		0x05fc
@@ -196,6 +209,8 @@ enum xgene_enet_rm {
 #define SOFT_RESET1			BIT(31)
 #define TX_EN				BIT(0)
 #define RX_EN				BIT(2)
+#define TX_FLOW_EN			BIT(4)
+#define RX_FLOW_EN			BIT(5)
 #define ENET_LHD_MODE			BIT(25)
 #define ENET_GHD_MODE			BIT(26)
 #define FULL_DUPLEX2			BIT(0)
@@ -346,6 +361,14 @@ static inline bool xgene_enet_is_bufpool
 	return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false;
 }
 
+static inline u8 xgene_enet_get_fpsel(u16 id)
+{
+	if (xgene_enet_is_bufpool(id))
+		return xgene_enet_ring_bufnum(id) - RING_BUFNUM_BUFPOOL;
+
+	return 0;
+}
+
 static inline u16 xgene_enet_get_numslots(u16 id, u32 size)
 {
 	bool is_bufpool = xgene_enet_is_bufpool(id);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,9 @@ static void xgene_enet_init_bufpool(stru
 	struct xgene_enet_raw_desc16 *raw_desc;
 	int i;
 
+	if (!buf_pool)
+		return;
+
 	for (i = 0; i < buf_pool->slots; i++) {
 		raw_desc = &buf_pool->raw_desc16[i];
 
@@ -47,6 +50,86 @@ static void xgene_enet_init_bufpool(stru
 	}
 }
 
+static u16 xgene_enet_get_data_len(u64 bufdatalen)
+{
+	u16 hw_len, mask;
+
+	hw_len = GET_VAL(BUFDATALEN, bufdatalen);
+
+	if (unlikely(hw_len == 0x7800)) {
+		return 0;
+	} else if (!(hw_len & BIT(14))) {
+		mask = GENMASK(13, 0);
+		return (hw_len & mask) ? (hw_len & mask) : SIZE_16K;
+	} else if (!(hw_len & GENMASK(13, 12))) {
+		mask = GENMASK(11, 0);
+		return (hw_len & mask) ? (hw_len & mask) : SIZE_4K;
+	} else {
+		mask = GENMASK(11, 0);
+		return (hw_len & mask) ? (hw_len & mask) : SIZE_2K;
+	}
+}
+
+static u16 xgene_enet_set_data_len(u32 size)
+{
+	u16 hw_len;
+
+	hw_len =  (size == SIZE_4K) ? BIT(14) : 0;
+
+	return hw_len;
+}
+
+static int xgene_enet_refill_pagepool(struct xgene_enet_desc_ring *buf_pool,
+				      u32 nbuf)
+{
+	struct xgene_enet_raw_desc16 *raw_desc;
+	struct xgene_enet_pdata *pdata;
+	struct net_device *ndev;
+	dma_addr_t dma_addr;
+	struct device *dev;
+	struct page *page;
+	u32 slots, tail;
+	u16 hw_len;
+	int i;
+
+	if (unlikely(!buf_pool))
+		return 0;
+
+	ndev = buf_pool->ndev;
+	pdata = netdev_priv(ndev);
+	dev = ndev_to_dev(ndev);
+	slots = buf_pool->slots - 1;
+	tail = buf_pool->tail;
+
+	for (i = 0; i < nbuf; i++) {
+		raw_desc = &buf_pool->raw_desc16[tail];
+
+		page = dev_alloc_page();
+		if (unlikely(!page))
+			return -ENOMEM;
+
+		dma_addr = dma_map_page(dev, page, 0,
+					PAGE_SIZE, DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(dev, dma_addr))) {
+			put_page(page);
+			return -ENOMEM;
+		}
+
+		hw_len = xgene_enet_set_data_len(PAGE_SIZE);
+		raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) |
+					   SET_VAL(BUFDATALEN, hw_len) |
+					   SET_BIT(COHERENT));
+
+		buf_pool->frag_page[tail] = page;
+		tail = (tail + 1) & slots;
+	}
+
+	pdata->ring_ops->wr_cmd(buf_pool, nbuf);
+	buf_pool->tail = tail;
+
+	return 0;
+}
+
 static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool,
 				     u32 nbuf)
 {
@@ -64,8 +147,9 @@ static int xgene_enet_refill_bufpool(str
 	ndev = buf_pool->ndev;
 	dev = ndev_to_dev(buf_pool->ndev);
 	pdata = netdev_priv(ndev);
+
 	bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0));
-	len = XGENE_ENET_MAX_MTU;
+	len = XGENE_ENET_STD_MTU;
 
 	for (i = 0; i < nbuf; i++) {
 		raw_desc = &buf_pool->raw_desc16[tail];
@@ -122,6 +206,25 @@ static void xgene_enet_delete_bufpool(st
 	}
 }
 
+static void xgene_enet_delete_pagepool(struct xgene_enet_desc_ring *buf_pool)
+{
+	struct device *dev = ndev_to_dev(buf_pool->ndev);
+	dma_addr_t dma_addr;
+	struct page *page;
+	int i;
+
+	/* Free up the buffers held by hardware */
+	for (i = 0; i < buf_pool->slots; i++) {
+		page = buf_pool->frag_page[i];
+		if (page) {
+			dma_addr = buf_pool->frag_dma_addr[i];
+			dma_unmap_page(dev, dma_addr, PAGE_SIZE,
+				       DMA_FROM_DEVICE);
+			put_page(page);
+		}
+	}
+}
+
 static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
 {
 	struct xgene_enet_desc_ring *rx_ring = data;
@@ -216,11 +319,11 @@ static int xgene_enet_setup_mss(struct n
 		}
 	}
 
-	spin_unlock(&pdata->mss_lock);
-
 	/* No slots with ref_count = 0 available, return busy */
 	if (!mss_index_found)
-		return -EBUSY;
+		mss_index = -EBUSY;
+
+	spin_unlock(&pdata->mss_lock);
 
 	return mss_index;
 }
@@ -515,23 +618,67 @@ static void xgene_enet_skip_csum(struct
 	}
 }
 
+static void xgene_enet_free_pagepool(struct xgene_enet_desc_ring *buf_pool,
+				     struct xgene_enet_raw_desc *raw_desc,
+				     struct xgene_enet_raw_desc *exp_desc)
+{
+	__le64 *desc = (void *)exp_desc;
+	dma_addr_t dma_addr;
+	struct device *dev;
+	struct page *page;
+	u16 slots, head;
+	u32 frag_size;
+	int i;
+
+	if (!buf_pool || !raw_desc || !exp_desc ||
+	    (!GET_VAL(NV, le64_to_cpu(raw_desc->m0))))
+		return;
+
+	dev = ndev_to_dev(buf_pool->ndev);
+	slots = buf_pool->slots - 1;
+	head = buf_pool->head;
+
+	for (i = 0; i < 4; i++) {
+		frag_size = xgene_enet_get_data_len(le64_to_cpu(desc[i ^ 1]));
+		if (!frag_size)
+			break;
+
+		dma_addr = GET_VAL(DATAADDR, le64_to_cpu(desc[i ^ 1]));
+		dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
+
+		page = buf_pool->frag_page[head];
+		put_page(page);
+
+		buf_pool->frag_page[head] = NULL;
+		head = (head + 1) & slots;
+	}
+	buf_pool->head = head;
+}
+
 static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring,
-			       struct xgene_enet_raw_desc *raw_desc)
+			       struct xgene_enet_raw_desc *raw_desc,
+			       struct xgene_enet_raw_desc *exp_desc)
 {
+	struct xgene_enet_desc_ring *buf_pool, *page_pool;
+	u32 datalen, frag_size, skb_index;
 	struct net_device *ndev;
-	struct device *dev;
-	struct xgene_enet_desc_ring *buf_pool;
-	u32 datalen, skb_index;
+	dma_addr_t dma_addr;
 	struct sk_buff *skb;
+	struct device *dev;
+	struct page *page;
+	u16 slots, head;
+	int i, ret = 0;
+	__le64 *desc;
 	u8 status;
-	int ret = 0;
+	bool nv;
 
 	ndev = rx_ring->ndev;
 	dev = ndev_to_dev(rx_ring->ndev);
 	buf_pool = rx_ring->buf_pool;
+	page_pool = rx_ring->page_pool;
 
 	dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)),
-			 XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE);
+			 XGENE_ENET_STD_MTU, DMA_FROM_DEVICE);
 	skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
 	skb = buf_pool->rx_skb[skb_index];
 	buf_pool->rx_skb[skb_index] = NULL;
@@ -541,6 +688,7 @@ static int xgene_enet_rx_frame(struct xg
 		  GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
 	if (unlikely(status > 2)) {
 		dev_kfree_skb_any(skb);
+		xgene_enet_free_pagepool(page_pool, raw_desc, exp_desc);
 		xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev),
 				       status);
 		ret = -EIO;
@@ -548,11 +696,44 @@ static int xgene_enet_rx_frame(struct xg
 	}
 
 	/* strip off CRC as HW isn't doing this */
-	datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1));
-	datalen = (datalen & DATALEN_MASK) - 4;
-	prefetch(skb->data - NET_IP_ALIGN);
+	datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1));
+
+	nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
+	if (!nv)
+		datalen -= 4;
+
 	skb_put(skb, datalen);
+	prefetch(skb->data - NET_IP_ALIGN);
+
+	if (!nv)
+		goto skip_jumbo;
+
+	slots = page_pool->slots - 1;
+	head = page_pool->head;
+	desc = (void *)exp_desc;
+
+	for (i = 0; i < 4; i++) {
+		frag_size = xgene_enet_get_data_len(le64_to_cpu(desc[i ^ 1]));
+		if (!frag_size)
+			break;
+
+		dma_addr = GET_VAL(DATAADDR, le64_to_cpu(desc[i ^ 1]));
+		dma_unmap_page(dev, dma_addr, PAGE_SIZE, DMA_FROM_DEVICE);
+
+		page = page_pool->frag_page[head];
+		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, 0,
+				frag_size, PAGE_SIZE);
 
+		datalen += frag_size;
+
+		page_pool->frag_page[head] = NULL;
+		head = (head + 1) & slots;
+	}
+
+	page_pool->head = head;
+	rx_ring->npagepool -= skb_shinfo(skb)->nr_frags;
+
+skip_jumbo:
 	skb_checksum_none_assert(skb);
 	skb->protocol = eth_type_trans(skb, ndev);
 	if (likely((ndev->features & NETIF_F_IP_CSUM) &&
@@ -563,7 +744,15 @@ static int xgene_enet_rx_frame(struct xg
 	rx_ring->rx_packets++;
 	rx_ring->rx_bytes += datalen;
 	napi_gro_receive(&rx_ring->napi, skb);
+
 out:
+	if (rx_ring->npagepool <= 0) {
+		ret = xgene_enet_refill_pagepool(page_pool, NUM_NXTBUFPOOL);
+		rx_ring->npagepool = NUM_NXTBUFPOOL;
+		if (ret)
+			return ret;
+	}
+
 	if (--rx_ring->nbufpool == 0) {
 		ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL);
 		rx_ring->nbufpool = NUM_BUFPOOL;
@@ -611,7 +800,7 @@ static int xgene_enet_process_ring(struc
 			desc_count++;
 		}
 		if (is_rx_desc(raw_desc)) {
-			ret = xgene_enet_rx_frame(ring, raw_desc);
+			ret = xgene_enet_rx_frame(ring, raw_desc, exp_desc);
 		} else {
 			ret = xgene_enet_tx_completion(ring, raw_desc);
 			is_completion = true;
@@ -854,7 +1043,7 @@ static void xgene_enet_delete_ring(struc
 
 static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata)
 {
-	struct xgene_enet_desc_ring *buf_pool;
+	struct xgene_enet_desc_ring *buf_pool, *page_pool;
 	struct xgene_enet_desc_ring *ring;
 	int i;
 
@@ -867,18 +1056,28 @@ static void xgene_enet_delete_desc_rings
 				xgene_enet_delete_ring(ring->cp_ring);
 			pdata->tx_ring[i] = NULL;
 		}
+
 	}
 
 	for (i = 0; i < pdata->rxq_cnt; i++) {
 		ring = pdata->rx_ring[i];
 		if (ring) {
+			page_pool = ring->page_pool;
+			if (page_pool) {
+				xgene_enet_delete_pagepool(page_pool);
+				xgene_enet_delete_ring(page_pool);
+				pdata->port_ops->clear(pdata, page_pool);
+			}
+
 			buf_pool = ring->buf_pool;
 			xgene_enet_delete_bufpool(buf_pool);
 			xgene_enet_delete_ring(buf_pool);
 			pdata->port_ops->clear(pdata, buf_pool);
+
 			xgene_enet_delete_ring(ring);
 			pdata->rx_ring[i] = NULL;
 		}
+
 	}
 }
 
@@ -931,8 +1130,10 @@ static void xgene_enet_free_desc_ring(st
 
 static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata)
 {
+	struct xgene_enet_desc_ring *page_pool;
 	struct device *dev = &pdata->pdev->dev;
 	struct xgene_enet_desc_ring *ring;
+	void *p;
 	int i;
 
 	for (i = 0; i < pdata->txq_cnt; i++) {
@@ -940,10 +1141,13 @@ static void xgene_enet_free_desc_rings(s
 		if (ring) {
 			if (ring->cp_ring && ring->cp_ring->cp_skb)
 				devm_kfree(dev, ring->cp_ring->cp_skb);
+
 			if (ring->cp_ring && pdata->cq_cnt)
 				xgene_enet_free_desc_ring(ring->cp_ring);
+
 			xgene_enet_free_desc_ring(ring);
 		}
+
 	}
 
 	for (i = 0; i < pdata->rxq_cnt; i++) {
@@ -952,8 +1156,21 @@ static void xgene_enet_free_desc_rings(s
 			if (ring->buf_pool) {
 				if (ring->buf_pool->rx_skb)
 					devm_kfree(dev, ring->buf_pool->rx_skb);
+
 				xgene_enet_free_desc_ring(ring->buf_pool);
 			}
+
+			page_pool = ring->page_pool;
+			if (page_pool) {
+				p = page_pool->frag_page;
+				if (p)
+					devm_kfree(dev, p);
+
+				p = page_pool->frag_dma_addr;
+				if (p)
+					devm_kfree(dev, p);
+			}
+
 			xgene_enet_free_desc_ring(ring);
 		}
 	}
@@ -1071,19 +1288,20 @@ static u8 xgene_start_cpu_bufnum(struct
 
 static int xgene_enet_create_desc_rings(struct net_device *ndev)
 {
-	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
-	struct device *dev = ndev_to_dev(ndev);
 	struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring;
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	struct xgene_enet_desc_ring *page_pool = NULL;
 	struct xgene_enet_desc_ring *buf_pool = NULL;
-	enum xgene_ring_owner owner;
-	dma_addr_t dma_exp_bufs;
-	u8 cpu_bufnum;
+	struct device *dev = ndev_to_dev(ndev);
 	u8 eth_bufnum = pdata->eth_bufnum;
 	u8 bp_bufnum = pdata->bp_bufnum;
 	u16 ring_num = pdata->ring_num;
+	enum xgene_ring_owner owner;
+	dma_addr_t dma_exp_bufs;
+	u16 ring_id, slots;
 	__le64 *exp_bufs;
-	u16 ring_id;
 	int i, ret, size;
+	u8 cpu_bufnum;
 
 	cpu_bufnum = xgene_start_cpu_bufnum(pdata);
 
@@ -1103,7 +1321,7 @@ static int xgene_enet_create_desc_rings(
 		owner = xgene_derive_ring_owner(pdata);
 		ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
 		buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
-						       RING_CFGSIZE_2KB,
+						       RING_CFGSIZE_16KB,
 						       ring_id);
 		if (!buf_pool) {
 			ret = -ENOMEM;
@@ -1111,7 +1329,7 @@ static int xgene_enet_create_desc_rings(
 		}
 
 		rx_ring->nbufpool = NUM_BUFPOOL;
-		rx_ring->buf_pool = buf_pool;
+		rx_ring->npagepool = NUM_NXTBUFPOOL;
 		rx_ring->irq = pdata->irqs[i];
 		buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots,
 						sizeof(struct sk_buff *),
@@ -1124,6 +1342,42 @@ static int xgene_enet_create_desc_rings(
 		buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool);
 		rx_ring->buf_pool = buf_pool;
 		pdata->rx_ring[i] = rx_ring;
+
+		if ((pdata->enet_id == XGENE_ENET1 &&  pdata->rxq_cnt > 4) ||
+		    (pdata->enet_id == XGENE_ENET2 &&  pdata->rxq_cnt > 16)) {
+			break;
+		}
+
+		/* allocate next buffer pool for jumbo packets */
+		owner = xgene_derive_ring_owner(pdata);
+		ring_id = xgene_enet_get_ring_id(owner, bp_bufnum++);
+		page_pool = xgene_enet_create_desc_ring(ndev, ring_num++,
+							RING_CFGSIZE_16KB,
+							ring_id);
+		if (!page_pool) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		slots = page_pool->slots;
+		page_pool->frag_page = devm_kcalloc(dev, slots,
+						    sizeof(struct page *),
+						    GFP_KERNEL);
+		if (!page_pool->frag_page) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		page_pool->frag_dma_addr = devm_kcalloc(dev, slots,
+							sizeof(dma_addr_t),
+							GFP_KERNEL);
+		if (!page_pool->frag_dma_addr) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		page_pool->dst_ring_num = xgene_enet_dst_ring_num(page_pool);
+		rx_ring->page_pool = page_pool;
 	}
 
 	for (i = 0; i < pdata->txq_cnt; i++) {
@@ -1247,13 +1501,31 @@ static int xgene_enet_set_mac_address(st
 	return ret;
 }
 
+static int xgene_change_mtu(struct net_device *ndev, int new_mtu)
+{
+	struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+	int frame_size;
+
+	if (!netif_running(ndev))
+		return 0;
+
+	frame_size = (new_mtu > ETH_DATA_LEN) ? (new_mtu + 18) : 0x600;
+
+	xgene_enet_close(ndev);
+	ndev->mtu = new_mtu;
+	pdata->mac_ops->set_framesize(pdata, frame_size);
+	xgene_enet_open(ndev);
+
+	return 0;
+}
+
 static const struct net_device_ops xgene_ndev_ops = {
 	.ndo_open = xgene_enet_open,
 	.ndo_stop = xgene_enet_close,
 	.ndo_start_xmit = xgene_enet_start_xmit,
 	.ndo_tx_timeout = xgene_enet_timeout,
 	.ndo_get_stats64 = xgene_enet_get_stats64,
-	.ndo_change_mtu = eth_change_mtu,
+	.ndo_change_mtu = xgene_change_mtu,
 	.ndo_set_mac_address = xgene_enet_set_mac_address,
 };
 
@@ -1382,9 +1654,13 @@ static void xgene_enet_gpiod_get(struct
 {
 	struct device *dev = &pdata->pdev->dev;
 
-	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
+	pdata->sfp_gpio_en = false;
+	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII ||
+	    (!device_property_present(dev, "sfp-gpios") &&
+	     !device_property_present(dev, "rxlos-gpios")))
 		return;
 
+	pdata->sfp_gpio_en = true;
 	pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
 	if (IS_ERR(pdata->sfp_rdy))
 		pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
@@ -1515,10 +1791,12 @@ static int xgene_enet_get_resources(stru
 static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata)
 {
 	struct xgene_enet_cle *enet_cle = &pdata->cle;
+	struct xgene_enet_desc_ring *page_pool;
 	struct net_device *ndev = pdata->ndev;
 	struct xgene_enet_desc_ring *buf_pool;
-	u16 dst_ring_num;
+	u16 dst_ring_num, ring_id;
 	int i, ret;
+	u32 count;
 
 	ret = pdata->port_ops->reset(pdata);
 	if (ret)
@@ -1534,9 +1812,18 @@ static int xgene_enet_init_hw(struct xge
 	for (i = 0; i < pdata->rxq_cnt; i++) {
 		buf_pool = pdata->rx_ring[i]->buf_pool;
 		xgene_enet_init_bufpool(buf_pool);
-		ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt);
+		page_pool = pdata->rx_ring[i]->page_pool;
+		xgene_enet_init_bufpool(page_pool);
+
+		count = pdata->rx_buff_cnt;
+		ret = xgene_enet_refill_bufpool(buf_pool, count);
+		if (ret)
+			goto err;
+
+		ret = xgene_enet_refill_pagepool(page_pool, count);
 		if (ret)
 			goto err;
+
 	}
 
 	dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
@@ -1555,10 +1842,17 @@ static int xgene_enet_init_hw(struct xge
 			netdev_err(ndev, "Preclass Tree init error\n");
 			goto err;
 		}
+
 	} else {
-		pdata->port_ops->cle_bypass(pdata, dst_ring_num, buf_pool->id);
+		dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring[0]);
+		buf_pool = pdata->rx_ring[0]->buf_pool;
+		page_pool = pdata->rx_ring[0]->page_pool;
+		ring_id = (page_pool) ? page_pool->id : 0;
+		pdata->port_ops->cle_bypass(pdata, dst_ring_num,
+					    buf_pool->id, ring_id);
 	}
 
+	ndev->max_mtu = XGENE_ENET_MAX_MTU;
 	pdata->phy_speed = SPEED_UNKNOWN;
 	pdata->mac_ops->init(pdata);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_main.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,11 +41,14 @@
 #include "../../../phy/mdio-xgene.h"
 
 #define XGENE_DRV_VERSION	"v1.0"
-#define XGENE_ENET_MAX_MTU	1536
-#define SKB_BUFFER_SIZE		(XGENE_ENET_MAX_MTU - NET_IP_ALIGN)
+#define XGENE_ENET_STD_MTU	1536
+#define XGENE_ENET_MAX_MTU	9600
+#define SKB_BUFFER_SIZE		(XGENE_ENET_STD_MTU - NET_IP_ALIGN)
+
 #define BUFLEN_16K	(16 * 1024)
-#define NUM_PKT_BUF	64
+#define NUM_PKT_BUF	1024
 #define NUM_BUFPOOL	32
+#define NUM_NXTBUFPOOL	8
 #define MAX_EXP_BUFFS	256
 #define NUM_MSS_REG	4
 #define XGENE_MIN_ENET_FRAME_SIZE	60
@@ -88,6 +91,12 @@ enum xgene_enet_id {
 	XGENE_ENET2
 };
 
+enum xgene_enet_buf_len {
+	SIZE_2K = 2048,
+	SIZE_4K = 4096,
+	SIZE_16K = 16384
+};
+
 /* software context of a descriptor ring */
 struct xgene_enet_desc_ring {
 	struct net_device *ndev;
@@ -107,14 +116,18 @@ struct xgene_enet_desc_ring {
 	dma_addr_t irq_mbox_dma;
 	void *irq_mbox_addr;
 	u16 dst_ring_num;
-	u8 nbufpool;
+	u16 nbufpool;
+	int npagepool;
 	u8 index;
+	u32 flags;
 	struct sk_buff *(*rx_skb);
 	struct sk_buff *(*cp_skb);
 	dma_addr_t *frag_dma_addr;
+	struct page *(*frag_page);
 	enum xgene_enet_ring_cfgsize cfgsize;
 	struct xgene_enet_desc_ring *cp_ring;
 	struct xgene_enet_desc_ring *buf_pool;
+	struct xgene_enet_desc_ring *page_pool;
 	struct napi_struct napi;
 	union {
 		void *desc_addr;
@@ -143,8 +156,12 @@ struct xgene_mac_ops {
 	void (*rx_disable)(struct xgene_enet_pdata *pdata);
 	void (*set_speed)(struct xgene_enet_pdata *pdata);
 	void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
+	void (*set_framesize)(struct xgene_enet_pdata *pdata, int framesize);
 	void (*set_mss)(struct xgene_enet_pdata *pdata, u16 mss, u8 index);
 	void (*link_state)(struct work_struct *work);
+	void (*enable_tx_pause)(struct xgene_enet_pdata *pdata, bool enable);
+	void (*flowctl_rx)(struct xgene_enet_pdata *pdata, bool enable);
+	void (*flowctl_tx)(struct xgene_enet_pdata *pdata, bool enable);
 };
 
 struct xgene_port_ops {
@@ -152,7 +169,7 @@ struct xgene_port_ops {
 	void (*clear)(struct xgene_enet_pdata *pdata,
 		      struct xgene_enet_desc_ring *ring);
 	void (*cle_bypass)(struct xgene_enet_pdata *pdata,
-			   u32 dst_ring_num, u16 bufpool_id);
+			   u32 dst_ring_num, u16 bufpool_id, u16 nxtbufpool_id);
 	void (*shutdown)(struct xgene_enet_pdata *pdata);
 };
 
@@ -219,6 +236,10 @@ struct xgene_enet_pdata {
 	u8 rx_delay;
 	bool mdio_driver;
 	struct gpio_desc *sfp_rdy;
+	bool sfp_gpio_en;
+	u32 pause_autoneg;
+	bool tx_pause;
+	bool rx_pause;
 };
 
 struct xgene_indirect_ctl {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c	2017-02-12 16:03:20.000000000 -0500
@@ -119,6 +119,7 @@ static void xgene_enet_set_ring_id(struc
 
 	ring_id_buf = (ring->num << 9) & GENMASK(18, 9);
 	ring_id_buf |= PREFETCH_BUF_EN;
+
 	if (is_bufpool)
 		ring_id_buf |= IS_BUFFER_POOL;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -343,6 +343,11 @@ static void xgene_sgmac_set_speed(struct
 	xgene_enet_wr_mcx_csr(p, icm2_addr, icm2);
 }
 
+static void xgene_sgmac_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+	xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size);
+}
+
 static void xgene_sgmii_enable_autoneg(struct xgene_enet_pdata *p)
 {
 	u32 data, loop = 10;
@@ -360,11 +365,39 @@ static void xgene_sgmii_enable_autoneg(s
 		netdev_err(p->ndev, "Auto-negotiation failed\n");
 }
 
+static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set)
+{
+	u32 data;
+
+	data = xgene_enet_rd_mac(p, MAC_CONFIG_1_ADDR);
+
+	if (set)
+		data |= bits;
+	else
+		data &= ~bits;
+
+	xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, data);
+}
+
+static void xgene_sgmac_flowctl_tx(struct xgene_enet_pdata *p, bool enable)
+{
+	xgene_sgmac_rxtx(p, TX_FLOW_EN, enable);
+
+	p->mac_ops->enable_tx_pause(p, enable);
+}
+
+static void xgene_sgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
+{
+	xgene_sgmac_rxtx(pdata, RX_FLOW_EN, enable);
+}
+
 static void xgene_sgmac_init(struct xgene_enet_pdata *p)
 {
+	u32 pause_thres_reg, pause_off_thres_reg;
 	u32 enet_spare_cfg_reg, rsif_config_reg;
 	u32 cfg_bypass_reg, rx_dv_gate_reg;
-	u32 data, offset;
+	u32 data, data1, data2, offset;
+	u32 multi_dpf_reg;
 
 	if (!(p->enet_id == XGENE_ENET2 && p->mdio_driver))
 		xgene_sgmac_reset(p);
@@ -400,24 +433,50 @@ static void xgene_sgmac_init(struct xgen
 	data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
 	xgene_enet_wr_csr(p, rsif_config_reg, data);
 
-	/* Bypass traffic gating */
-	xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84);
-	xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX);
-	xgene_enet_wr_mcx_csr(p, rx_dv_gate_reg, RESUME_RX0);
-}
+	/* Configure HW pause frame generation */
+	multi_dpf_reg = (p->enet_id == XGENE_ENET1) ? CSR_MULTI_DPF0_ADDR :
+			 XG_MCX_MULTI_DPF0_ADDR;
+	data = xgene_enet_rd_mcx_csr(p, multi_dpf_reg);
+	data = (DEF_QUANTA << 16) | (data & 0xffff);
+	xgene_enet_wr_mcx_csr(p, multi_dpf_reg, data);
 
-static void xgene_sgmac_rxtx(struct xgene_enet_pdata *p, u32 bits, bool set)
-{
-	u32 data;
+	if (p->enet_id != XGENE_ENET1) {
+		data = xgene_enet_rd_mcx_csr(p, XG_MCX_MULTI_DPF1_ADDR);
+		data =  (NORM_PAUSE_OPCODE << 16) | (data & 0xFFFF);
+		xgene_enet_wr_mcx_csr(p, XG_MCX_MULTI_DPF1_ADDR, data);
+	}
 
-	data = xgene_enet_rd_mac(p, MAC_CONFIG_1_ADDR);
+	pause_thres_reg = (p->enet_id == XGENE_ENET1) ? RXBUF_PAUSE_THRESH :
+			   XG_RXBUF_PAUSE_THRESH;
+	pause_off_thres_reg = (p->enet_id == XGENE_ENET1) ?
+			       RXBUF_PAUSE_OFF_THRESH : 0;
 
-	if (set)
-		data |= bits;
-	else
-		data &= ~bits;
+	if (p->enet_id == XGENE_ENET1) {
+		data1 = xgene_enet_rd_csr(p, pause_thres_reg);
+		data2 = xgene_enet_rd_csr(p, pause_off_thres_reg);
 
-	xgene_enet_wr_mac(p, MAC_CONFIG_1_ADDR, data);
+		if (!(p->port_id % 2)) {
+			data1 = (data1 & 0xffff0000) | DEF_PAUSE_THRES;
+			data2 = (data2 & 0xffff0000) | DEF_PAUSE_OFF_THRES;
+		} else {
+			data1 = (data1 & 0xffff) | (DEF_PAUSE_THRES << 16);
+			data2 = (data2 & 0xffff) | (DEF_PAUSE_OFF_THRES << 16);
+		}
+
+		xgene_enet_wr_csr(p, pause_thres_reg, data1);
+		xgene_enet_wr_csr(p, pause_off_thres_reg, data2);
+	} else {
+		data = (DEF_PAUSE_OFF_THRES << 16) | DEF_PAUSE_THRES;
+		xgene_enet_wr_csr(p, pause_thres_reg, data);
+	}
+
+	xgene_sgmac_flowctl_tx(p, p->tx_pause);
+	xgene_sgmac_flowctl_rx(p, p->rx_pause);
+
+	/* Bypass traffic gating */
+	xgene_enet_wr_csr(p, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x84);
+	xgene_enet_wr_csr(p, cfg_bypass_reg, RESUME_TX);
+	xgene_enet_wr_mcx_csr(p, rx_dv_gate_reg, RESUME_RX0);
 }
 
 static void xgene_sgmac_rx_enable(struct xgene_enet_pdata *p)
@@ -484,11 +543,12 @@ static int xgene_enet_reset(struct xgene
 }
 
 static void xgene_enet_cle_bypass(struct xgene_enet_pdata *p,
-				  u32 dst_ring_num, u16 bufpool_id)
+				  u32 dst_ring_num, u16 bufpool_id,
+				  u16 nxtbufpool_id)
 {
-	u32 data, fpsel;
 	u32 cle_bypass_reg0, cle_bypass_reg1;
 	u32 offset = p->port_id * MAC_OFFSET;
+	u32 data, fpsel, nxtfpsel;
 
 	if (p->enet_id == XGENE_ENET1) {
 		cle_bypass_reg0 = CLE_BYPASS_REG0_0_ADDR;
@@ -501,24 +561,24 @@ static void xgene_enet_cle_bypass(struct
 	data = CFG_CLE_BYPASS_EN0;
 	xgene_enet_wr_csr(p, cle_bypass_reg0 + offset, data);
 
-	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
-	data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel);
+	fpsel = xgene_enet_get_fpsel(bufpool_id);
+	nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
+	data = CFG_CLE_DSTQID0(dst_ring_num) | CFG_CLE_FPSEL0(fpsel) |
+	       CFG_CLE_NXTFPSEL0(nxtfpsel);
 	xgene_enet_wr_csr(p, cle_bypass_reg1 + offset, data);
 }
 
 static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
 			     struct xgene_enet_desc_ring *ring)
 {
-	u32 addr, val, data;
-
-	val = xgene_enet_ring_bufnum(ring->id);
+	u32 addr, data;
 
 	if (xgene_enet_is_bufpool(ring->id)) {
 		addr = ENET_CFGSSQMIFPRESET_ADDR;
-		data = BIT(val - 0x20);
+		data = BIT(xgene_enet_get_fpsel(ring->id));
 	} else {
 		addr = ENET_CFGSSQMIWQRESET_ADDR;
-		data = BIT(val);
+		data = BIT(xgene_enet_ring_bufnum(ring->id));
 	}
 
 	xgene_enet_wr_ring_if(pdata, addr, data);
@@ -528,24 +588,23 @@ static void xgene_enet_shutdown(struct x
 {
 	struct device *dev = &p->pdev->dev;
 	struct xgene_enet_desc_ring *ring;
-	u32 pb, val;
+	u32 pb;
 	int i;
 
 	pb = 0;
 	for (i = 0; i < p->rxq_cnt; i++) {
 		ring = p->rx_ring[i]->buf_pool;
-
-		val = xgene_enet_ring_bufnum(ring->id);
-		pb |= BIT(val - 0x20);
+		pb |= BIT(xgene_enet_get_fpsel(ring->id));
+		ring = p->rx_ring[i]->page_pool;
+		if (ring)
+			pb |= BIT(xgene_enet_get_fpsel(ring->id));
 	}
 	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIFPRESET_ADDR, pb);
 
 	pb = 0;
 	for (i = 0; i < p->txq_cnt; i++) {
 		ring = p->tx_ring[i];
-
-		val = xgene_enet_ring_bufnum(ring->id);
-		pb |= BIT(val);
+		pb |= BIT(xgene_enet_ring_bufnum(ring->id));
 	}
 	xgene_enet_wr_ring_if(p, ENET_CFGSSQMIWQRESET_ADDR, pb);
 
@@ -586,6 +645,25 @@ static void xgene_enet_link_state(struct
 	schedule_delayed_work(&p->link_work, poll_interval);
 }
 
+static void xgene_sgmac_enable_tx_pause(struct xgene_enet_pdata *p, bool enable)
+{
+	u32 data, ecm_cfg_addr;
+
+	if (p->enet_id == XGENE_ENET1) {
+		ecm_cfg_addr = (!(p->port_id % 2)) ? CSR_ECM_CFG_0_ADDR :
+				CSR_ECM_CFG_1_ADDR;
+	} else {
+		ecm_cfg_addr = XG_MCX_ECM_CFG_0_ADDR;
+	}
+
+	data = xgene_enet_rd_mcx_csr(p, ecm_cfg_addr);
+	if (enable)
+		data |= MULTI_DPF_AUTOCTRL | PAUSE_XON_EN;
+	else
+		data &= ~(MULTI_DPF_AUTOCTRL | PAUSE_XON_EN);
+	xgene_enet_wr_mcx_csr(p, ecm_cfg_addr, data);
+}
+
 const struct xgene_mac_ops xgene_sgmac_ops = {
 	.init		= xgene_sgmac_init,
 	.reset		= xgene_sgmac_reset,
@@ -595,7 +673,11 @@ const struct xgene_mac_ops xgene_sgmac_o
 	.tx_disable	= xgene_sgmac_tx_disable,
 	.set_speed	= xgene_sgmac_set_speed,
 	.set_mac_addr	= xgene_sgmac_set_mac_addr,
-	.link_state	= xgene_enet_link_state
+	.set_framesize  = xgene_sgmac_set_frame_size,
+	.link_state	= xgene_enet_link_state,
+	.enable_tx_pause = xgene_sgmac_enable_tx_pause,
+	.flowctl_tx     = xgene_sgmac_flowctl_tx,
+	.flowctl_rx     = xgene_sgmac_flowctl_rx
 };
 
 const struct xgene_port_ops xgene_sgport_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -101,6 +101,14 @@ static void xgene_enet_wr_pcs(struct xge
 			   wr_addr);
 }
 
+static void xgene_enet_wr_axg_csr(struct xgene_enet_pdata *pdata,
+				  u32 offset, u32 val)
+{
+	void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+	iowrite32(val, addr);
+}
+
 static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata,
 			      u32 offset, u32 *val)
 {
@@ -174,6 +182,14 @@ static bool xgene_enet_rd_pcs(struct xge
 	return success;
 }
 
+static void xgene_enet_rd_axg_csr(struct xgene_enet_pdata *pdata,
+				  u32 offset, u32 *val)
+{
+	void __iomem *addr = pdata->mcx_mac_csr_addr + offset;
+
+	*val = ioread32(addr);
+}
+
 static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
 {
 	struct net_device *ndev = pdata->ndev;
@@ -250,6 +266,12 @@ static void xgene_xgmac_set_mss(struct x
 	xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR + offset, data);
 }
 
+static void xgene_xgmac_set_frame_size(struct xgene_enet_pdata *pdata, int size)
+{
+	xgene_enet_wr_mac(pdata, HSTMAXFRAME_LENGTH_ADDR,
+			  ((((size + 2) >> 2) << 16) | size));
+}
+
 static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
 {
 	u32 data;
@@ -259,6 +281,51 @@ static u32 xgene_enet_link_status(struct
 	return data;
 }
 
+static void xgene_xgmac_enable_tx_pause(struct xgene_enet_pdata *pdata,
+					bool enable)
+{
+	u32 data;
+
+	xgene_enet_rd_axg_csr(pdata, XGENET_CSR_ECM_CFG_0_ADDR, &data);
+
+	if (enable)
+		data |= MULTI_DPF_AUTOCTRL | PAUSE_XON_EN;
+	else
+		data &= ~(MULTI_DPF_AUTOCTRL | PAUSE_XON_EN);
+
+	xgene_enet_wr_axg_csr(pdata, XGENET_CSR_ECM_CFG_0_ADDR, data);
+}
+
+static void xgene_xgmac_flowctl_tx(struct xgene_enet_pdata *pdata, bool enable)
+{
+	u32 data;
+
+	xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+
+	if (enable)
+		data |= HSTTCTLEN;
+	else
+		data &= ~HSTTCTLEN;
+
+	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
+
+	pdata->mac_ops->enable_tx_pause(pdata, enable);
+}
+
+static void xgene_xgmac_flowctl_rx(struct xgene_enet_pdata *pdata, bool enable)
+{
+	u32 data;
+
+	xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data);
+
+	if (enable)
+		data |= HSTRCTLEN;
+	else
+		data &= ~HSTRCTLEN;
+
+	xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
+}
+
 static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
 {
 	u32 data;
@@ -282,6 +349,23 @@ static void xgene_xgmac_init(struct xgen
 	xgene_enet_wr_csr(pdata, XG_ENET_SPARE_CFG_REG_1_ADDR, 0x82);
 	xgene_enet_wr_csr(pdata, XGENET_RX_DV_GATE_REG_0_ADDR, 0);
 	xgene_enet_wr_csr(pdata, XG_CFG_BYPASS_ADDR, RESUME_TX);
+
+	/* Configure HW pause frame generation */
+	xgene_enet_rd_axg_csr(pdata, XGENET_CSR_MULTI_DPF0_ADDR, &data);
+	data = (DEF_QUANTA << 16) | (data & 0xFFFF);
+	xgene_enet_wr_axg_csr(pdata, XGENET_CSR_MULTI_DPF0_ADDR, data);
+
+	if (pdata->enet_id != XGENE_ENET1) {
+		xgene_enet_rd_axg_csr(pdata, XGENET_CSR_MULTI_DPF1_ADDR, &data);
+		data = (NORM_PAUSE_OPCODE << 16) | (data & 0xFFFF);
+		xgene_enet_wr_axg_csr(pdata, XGENET_CSR_MULTI_DPF1_ADDR, data);
+	}
+
+	data = (XG_DEF_PAUSE_OFF_THRES << 16) | XG_DEF_PAUSE_THRES;
+	xgene_enet_wr_csr(pdata, XG_RXBUF_PAUSE_THRESH, data);
+
+	xgene_xgmac_flowctl_tx(pdata, pdata->tx_pause);
+	xgene_xgmac_flowctl_rx(pdata, pdata->rx_pause);
 }
 
 static void xgene_xgmac_rx_enable(struct xgene_enet_pdata *pdata)
@@ -350,44 +434,47 @@ static int xgene_enet_reset(struct xgene
 }
 
 static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata,
-				    u32 dst_ring_num, u16 bufpool_id)
+				    u32 dst_ring_num, u16 bufpool_id,
+				    u16 nxtbufpool_id)
 {
-	u32 cb, fpsel;
+	u32 cb, fpsel, nxtfpsel;
 
 	xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG0_ADDR, &cb);
 	cb |= CFG_CLE_BYPASS_EN0;
 	CFG_CLE_IP_PROTOCOL0_SET(&cb, 3);
 	xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG0_ADDR, cb);
 
-	fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20;
+	fpsel = xgene_enet_get_fpsel(bufpool_id);
+	nxtfpsel = xgene_enet_get_fpsel(nxtbufpool_id);
 	xgene_enet_rd_csr(pdata, XCLE_BYPASS_REG1_ADDR, &cb);
 	CFG_CLE_DSTQID0_SET(&cb, dst_ring_num);
 	CFG_CLE_FPSEL0_SET(&cb, fpsel);
+	CFG_CLE_NXTFPSEL0_SET(&cb, nxtfpsel);
 	xgene_enet_wr_csr(pdata, XCLE_BYPASS_REG1_ADDR, cb);
+	pr_info("+ cle_bypass: fpsel: %d nxtfpsel: %d\n", fpsel, nxtfpsel);
 }
 
 static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata)
 {
 	struct device *dev = &pdata->pdev->dev;
 	struct xgene_enet_desc_ring *ring;
-	u32 pb, val;
+	u32 pb;
 	int i;
 
 	pb = 0;
 	for (i = 0; i < pdata->rxq_cnt; i++) {
 		ring = pdata->rx_ring[i]->buf_pool;
-
-		val = xgene_enet_ring_bufnum(ring->id);
-		pb |= BIT(val - 0x20);
+		pb |= BIT(xgene_enet_get_fpsel(ring->id));
+		ring = pdata->rx_ring[i]->page_pool;
+		if (ring)
+			pb |= BIT(xgene_enet_get_fpsel(ring->id));
 	}
 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPRESET_ADDR, pb);
 
 	pb = 0;
 	for (i = 0; i < pdata->txq_cnt; i++) {
 		ring = pdata->tx_ring[i];
-
-		val = xgene_enet_ring_bufnum(ring->id);
-		pb |= BIT(val);
+		pb |= BIT(xgene_enet_ring_bufnum(ring->id));
 	}
 	xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb);
 
@@ -400,31 +487,44 @@ static void xgene_enet_shutdown(struct x
 static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
 			     struct xgene_enet_desc_ring *ring)
 {
-	u32 addr, val, data;
-
-	val = xgene_enet_ring_bufnum(ring->id);
+	u32 addr, data;
 
 	if (xgene_enet_is_bufpool(ring->id)) {
 		addr = ENET_CFGSSQMIFPRESET_ADDR;
-		data = BIT(val - 0x20);
+		data = BIT(xgene_enet_get_fpsel(ring->id));
 	} else {
 		addr = ENET_CFGSSQMIWQRESET_ADDR;
-		data = BIT(val);
+		data = BIT(xgene_enet_ring_bufnum(ring->id));
 	}
 
 	xgene_enet_wr_ring_if(pdata, addr, data);
 }
 
+static int xgene_enet_gpio_lookup(struct xgene_enet_pdata *pdata)
+{
+	struct device *dev = &pdata->pdev->dev;
+
+	pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
+	if (IS_ERR(pdata->sfp_rdy))
+		pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
+
+	if (IS_ERR(pdata->sfp_rdy))
+		return -ENODEV;
+
+	return 0;
+}
+
 static void xgene_enet_link_state(struct work_struct *work)
 {
 	struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
 					 struct xgene_enet_pdata, link_work);
-	struct gpio_desc *sfp_rdy = pdata->sfp_rdy;
 	struct net_device *ndev = pdata->ndev;
 	u32 link_status, poll_interval;
 
 	link_status = xgene_enet_link_status(pdata);
-	if (link_status && !IS_ERR(sfp_rdy) && !gpiod_get_value(sfp_rdy))
+	if (pdata->sfp_gpio_en && link_status &&
+	    (!IS_ERR(pdata->sfp_rdy) || !xgene_enet_gpio_lookup(pdata)) &&
+	    !gpiod_get_value(pdata->sfp_rdy))
 		link_status = 0;
 
 	if (link_status) {
@@ -458,8 +558,12 @@ const struct xgene_mac_ops xgene_xgmac_o
 	.rx_disable = xgene_xgmac_rx_disable,
 	.tx_disable = xgene_xgmac_tx_disable,
 	.set_mac_addr = xgene_xgmac_set_mac_addr,
+	.set_framesize = xgene_xgmac_set_frame_size,
 	.set_mss = xgene_xgmac_set_mss,
-	.link_state = xgene_enet_link_state
+	.link_state = xgene_enet_link_state,
+	.enable_tx_pause = xgene_xgmac_enable_tx_pause,
+	.flowctl_rx = xgene_xgmac_flowctl_rx,
+	.flowctl_tx = xgene_xgmac_flowctl_tx
 };
 
 const struct xgene_port_ops xgene_xgport_ops = {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.h	2017-02-12 16:03:20.000000000 -0500
@@ -59,6 +59,11 @@
 #define HSTMAXFRAME_LENGTH_ADDR		0x0020
 
 #define XG_MCX_RX_DV_GATE_REG_0_ADDR	0x0004
+#define XG_MCX_ECM_CFG_0_ADDR		0x0074
+#define XG_MCX_MULTI_DPF0_ADDR		0x007c
+#define XG_MCX_MULTI_DPF1_ADDR		0x0080
+#define XG_DEF_PAUSE_THRES		0x390
+#define XG_DEF_PAUSE_OFF_THRES		0x2c0
 #define XG_RSIF_CONFIG_REG_ADDR		0x00a0
 #define XCLE_BYPASS_REG0_ADDR           0x0160
 #define XCLE_BYPASS_REG1_ADDR           0x0164
@@ -70,6 +75,10 @@
 #define XG_ENET_SPARE_CFG_REG_ADDR	0x040c
 #define XG_ENET_SPARE_CFG_REG_1_ADDR	0x0410
 #define XGENET_RX_DV_GATE_REG_0_ADDR	0x0804
+#define XGENET_CSR_ECM_CFG_0_ADDR	0x0880
+#define XGENET_CSR_MULTI_DPF0_ADDR	0x0888
+#define XGENET_CSR_MULTI_DPF1_ADDR	0x088c
+#define XG_RXBUF_PAUSE_THRESH		0x0020
 #define XG_MCX_ICM_CONFIG0_REG_0_ADDR	0x00e0
 #define XG_MCX_ICM_CONFIG2_REG_0_ADDR	0x00e8
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apple/bmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apple/bmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apple/bmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apple/bmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -1237,7 +1237,6 @@ static const struct net_device_ops bmac_
 	.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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apple/mace.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apple/mace.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apple/mace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apple/mace.c	2017-02-12 16:03:20.000000000 -0500
@@ -102,7 +102,6 @@ static const struct net_device_ops mace_
 	.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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/apple/macmace.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apple/macmace.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/apple/macmace.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/apple/macmace.c	2017-02-12 16:03:20.000000000 -0500
@@ -186,7 +186,6 @@ static const struct net_device_ops mace_
 	.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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/arc/emac_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/arc/emac_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/arc/emac_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/arc/emac_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -636,7 +636,7 @@ static int arc_emac_tx(struct sk_buff *s
 	if (unlikely(dma_mapping_error(&ndev->dev, addr))) {
 		stats->tx_dropped++;
 		stats->tx_errors++;
-		dev_kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
 	dma_unmap_addr_set(&priv->tx_buff[*txbd_curr], addr, addr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/arc/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/arc/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/arc/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/arc/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -17,13 +17,14 @@ if NET_VENDOR_ARC
 
 config ARC_EMAC_CORE
 	tristate
+	depends on ARC || ARCH_ROCKCHIP || COMPILE_TEST
 	select MII
 	select PHYLIB
 
 config ARC_EMAC
 	tristate "ARC EMAC support"
 	select ARC_EMAC_CORE
-	depends on OF_IRQ && OF_NET && HAS_DMA
+	depends on OF_IRQ && OF_NET && HAS_DMA && (ARC || COMPILE_TEST)
 	---help---
 	  On some legacy ARC (Synopsys) FPGA boards such as ARCAngel4/ML50x
 	  non-standard on-chip ethernet device ARC EMAC 10/100 is used.
@@ -32,7 +33,7 @@ config ARC_EMAC
 config EMAC_ROCKCHIP
 	tristate "Rockchip EMAC support"
 	select ARC_EMAC_CORE
-	depends on OF_IRQ && OF_NET && REGULATOR && HAS_DMA
+	depends on OF_IRQ && OF_NET && REGULATOR && HAS_DMA && (ARCH_ROCKCHIP || COMPILE_TEST)
 	---help---
 	  Support for Rockchip RK3036/RK3066/RK3188 EMAC ethernet controllers.
 	  This selects Rockchip SoC glue layer support for the
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/alx.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/alx.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/alx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/alx.h	2017-02-12 16:03:20.000000000 -0500
@@ -50,6 +50,10 @@ struct alx_buffer {
 };
 
 struct alx_rx_queue {
+	struct net_device *netdev;
+	struct device *dev;
+	struct alx_napi *np;
+
 	struct alx_rrd *rrd;
 	dma_addr_t rrd_dma;
 
@@ -58,16 +62,26 @@ struct alx_rx_queue {
 
 	struct alx_buffer *bufs;
 
+	u16 count;
 	u16 write_idx, read_idx;
 	u16 rrd_read_idx;
+	u16 queue_idx;
 };
 #define ALX_RX_ALLOC_THRESH	32
 
 struct alx_tx_queue {
+	struct net_device *netdev;
+	struct device *dev;
+
 	struct alx_txd *tpd;
 	dma_addr_t tpd_dma;
+
 	struct alx_buffer *bufs;
+
+	u16 count;
 	u16 write_idx, read_idx;
+	u16 queue_idx;
+	u16 p_reg, c_reg;
 };
 
 #define ALX_DEFAULT_TX_WORK 128
@@ -76,6 +90,18 @@ enum alx_device_quirks {
 	ALX_DEV_QUIRK_MSI_INTX_DISABLE_BUG = BIT(0),
 };
 
+struct alx_napi {
+	struct napi_struct	napi;
+	struct alx_priv		*alx;
+	struct alx_rx_queue	*rxq;
+	struct alx_tx_queue	*txq;
+	int			vec_idx;
+	u32			vec_mask;
+	char			irq_lbl[IFNAMSIZ + 8];
+};
+
+#define ALX_MAX_NAPIS 8
+
 #define ALX_FLAG_USING_MSIX	BIT(0)
 #define ALX_FLAG_USING_MSI	BIT(1)
 
@@ -87,7 +113,6 @@ struct alx_priv {
 	/* msi-x vectors */
 	int num_vec;
 	struct msix_entry *msix_entries;
-	char irq_lbl[IFNAMSIZ + 8];
 
 	/* all descriptor memory */
 	struct {
@@ -96,6 +121,11 @@ struct alx_priv {
 		unsigned int size;
 	} descmem;
 
+	struct alx_napi *qnapi[ALX_MAX_NAPIS];
+	int num_txq;
+	int num_rxq;
+	int num_napi;
+
 	/* protect int_mask updates */
 	spinlock_t irq_lock;
 	u32 int_mask;
@@ -104,10 +134,6 @@ struct alx_priv {
 	unsigned int rx_ringsz;
 	unsigned int rxbuf_size;
 
-	struct napi_struct napi;
-	struct alx_tx_queue txq;
-	struct alx_rx_queue rxq;
-
 	struct work_struct link_check_wk;
 	struct work_struct reset_wk;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -125,64 +125,75 @@ static u32 alx_get_supported_speeds(stru
 	return supported;
 }
 
-static int alx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int alx_get_link_ksettings(struct net_device *netdev,
+				  struct ethtool_link_ksettings *cmd)
 {
 	struct alx_priv *alx = netdev_priv(netdev);
 	struct alx_hw *hw = &alx->hw;
+	u32 supported, advertising;
 
-	ecmd->supported = SUPPORTED_Autoneg |
+	supported = SUPPORTED_Autoneg |
 			  SUPPORTED_TP |
 			  SUPPORTED_Pause |
 			  SUPPORTED_Asym_Pause;
 	if (alx_hw_giga(hw))
-		ecmd->supported |= SUPPORTED_1000baseT_Full;
-	ecmd->supported |= alx_get_supported_speeds(hw);
+		supported |= SUPPORTED_1000baseT_Full;
+	supported |= alx_get_supported_speeds(hw);
 
-	ecmd->advertising = ADVERTISED_TP;
+	advertising = ADVERTISED_TP;
 	if (hw->adv_cfg & ADVERTISED_Autoneg)
-		ecmd->advertising |= hw->adv_cfg;
+		advertising |= hw->adv_cfg;
 
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
+	cmd->base.port = PORT_TP;
+	cmd->base.phy_address = 0;
 
 	if (hw->adv_cfg & ADVERTISED_Autoneg)
-		ecmd->autoneg = AUTONEG_ENABLE;
+		cmd->base.autoneg = AUTONEG_ENABLE;
 	else
-		ecmd->autoneg = AUTONEG_DISABLE;
-	ecmd->transceiver = XCVR_INTERNAL;
+		cmd->base.autoneg = AUTONEG_DISABLE;
 
 	if (hw->flowctrl & ALX_FC_ANEG && hw->adv_cfg & ADVERTISED_Autoneg) {
 		if (hw->flowctrl & ALX_FC_RX) {
-			ecmd->advertising |= ADVERTISED_Pause;
+			advertising |= ADVERTISED_Pause;
 
 			if (!(hw->flowctrl & ALX_FC_TX))
-				ecmd->advertising |= ADVERTISED_Asym_Pause;
+				advertising |= ADVERTISED_Asym_Pause;
 		} else if (hw->flowctrl & ALX_FC_TX) {
-			ecmd->advertising |= ADVERTISED_Asym_Pause;
+			advertising |= ADVERTISED_Asym_Pause;
 		}
 	}
 
-	ethtool_cmd_speed_set(ecmd, hw->link_speed);
-	ecmd->duplex = hw->duplex;
+	cmd->base.speed = hw->link_speed;
+	cmd->base.duplex = hw->duplex;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return 0;
 }
 
-static int alx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int alx_set_link_ksettings(struct net_device *netdev,
+				  const struct ethtool_link_ksettings *cmd)
 {
 	struct alx_priv *alx = netdev_priv(netdev);
 	struct alx_hw *hw = &alx->hw;
 	u32 adv_cfg;
+	u32 advertising;
 
 	ASSERT_RTNL();
 
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-		if (ecmd->advertising & ~alx_get_supported_speeds(hw))
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						cmd->link_modes.advertising);
+
+	if (cmd->base.autoneg == AUTONEG_ENABLE) {
+		if (advertising & ~alx_get_supported_speeds(hw))
 			return -EINVAL;
-		adv_cfg = ecmd->advertising | ADVERTISED_Autoneg;
+		adv_cfg = advertising | ADVERTISED_Autoneg;
 	} else {
-		adv_cfg = alx_speed_to_ethadv(ethtool_cmd_speed(ecmd),
-					      ecmd->duplex);
+		adv_cfg = alx_speed_to_ethadv(cmd->base.speed,
+					      cmd->base.duplex);
 
 		if (!adv_cfg || adv_cfg == ADVERTISED_1000baseT_Full)
 			return -EINVAL;
@@ -300,8 +311,6 @@ static int alx_get_sset_count(struct net
 }
 
 const struct ethtool_ops alx_ethtool_ops = {
-	.get_settings	= alx_get_settings,
-	.set_settings	= alx_set_settings,
 	.get_pauseparam	= alx_get_pauseparam,
 	.set_pauseparam	= alx_set_pauseparam,
 	.get_msglevel	= alx_get_msglevel,
@@ -310,4 +319,6 @@ const struct ethtool_ops alx_ethtool_ops
 	.get_strings	= alx_get_strings,
 	.get_sset_count	= alx_get_sset_count,
 	.get_ethtool_stats	= alx_get_ethtool_stats,
+	.get_link_ksettings	= alx_get_link_ksettings,
+	.set_link_ksettings	= alx_set_link_ksettings,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/hw.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/hw.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/hw.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/hw.h	2017-02-12 16:03:20.000000000 -0500
@@ -351,7 +351,6 @@ struct alx_rrd {
 #define ALX_MAX_JUMBO_PKT_SIZE	(9*1024)
 #define ALX_MAX_TSO_PKT_SIZE	(7*1024)
 #define ALX_MAX_FRAME_SIZE	ALX_MAX_JUMBO_PKT_SIZE
-#define ALX_MIN_FRAME_SIZE	(ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN)
 
 #define ALX_MAX_RX_QUEUES	8
 #define ALX_MAX_TX_QUEUES	4
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,16 +51,12 @@
 
 const char alx_drv_name[] = "alx";
 
-static bool msix = false;
-module_param(msix, bool, 0);
-MODULE_PARM_DESC(msix, "Enable msi-x interrupt support");
-
-static void alx_free_txbuf(struct alx_priv *alx, int entry)
+static void alx_free_txbuf(struct alx_tx_queue *txq, int entry)
 {
-	struct alx_buffer *txb = &alx->txq.bufs[entry];
+	struct alx_buffer *txb = &txq->bufs[entry];
 
 	if (dma_unmap_len(txb, size)) {
-		dma_unmap_single(&alx->hw.pdev->dev,
+		dma_unmap_single(txq->dev,
 				 dma_unmap_addr(txb, dma),
 				 dma_unmap_len(txb, size),
 				 DMA_TO_DEVICE);
@@ -75,7 +71,7 @@ static void alx_free_txbuf(struct alx_pr
 
 static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
 {
-	struct alx_rx_queue *rxq = &alx->rxq;
+	struct alx_rx_queue *rxq = alx->qnapi[0]->rxq;
 	struct sk_buff *skb;
 	struct alx_buffer *cur_buf;
 	dma_addr_t dma;
@@ -143,24 +139,42 @@ static int alx_refill_rx_ring(struct alx
 	return count;
 }
 
-static inline int alx_tpd_avail(struct alx_priv *alx)
+static struct alx_tx_queue *alx_tx_queue_mapping(struct alx_priv *alx,
+						 struct sk_buff *skb)
 {
-	struct alx_tx_queue *txq = &alx->txq;
+	unsigned int r_idx = skb->queue_mapping;
+
+	if (r_idx >= alx->num_txq)
+		r_idx = r_idx % alx->num_txq;
+
+	return alx->qnapi[r_idx]->txq;
+}
+
+static struct netdev_queue *alx_get_tx_queue(const struct alx_tx_queue *txq)
+{
+	return netdev_get_tx_queue(txq->netdev, txq->queue_idx);
+}
 
+static inline int alx_tpd_avail(struct alx_tx_queue *txq)
+{
 	if (txq->write_idx >= txq->read_idx)
-		return alx->tx_ringsz + txq->read_idx - txq->write_idx - 1;
+		return txq->count + txq->read_idx - txq->write_idx - 1;
 	return txq->read_idx - txq->write_idx - 1;
 }
 
-static bool alx_clean_tx_irq(struct alx_priv *alx)
+static bool alx_clean_tx_irq(struct alx_tx_queue *txq)
 {
-	struct alx_tx_queue *txq = &alx->txq;
+	struct alx_priv *alx;
+	struct netdev_queue *tx_queue;
 	u16 hw_read_idx, sw_read_idx;
 	unsigned int total_bytes = 0, total_packets = 0;
 	int budget = ALX_DEFAULT_TX_WORK;
 
+	alx = netdev_priv(txq->netdev);
+	tx_queue = alx_get_tx_queue(txq);
+
 	sw_read_idx = txq->read_idx;
-	hw_read_idx = alx_read_mem16(&alx->hw, ALX_TPD_PRI0_CIDX);
+	hw_read_idx = alx_read_mem16(&alx->hw, txq->c_reg);
 
 	if (sw_read_idx != hw_read_idx) {
 		while (sw_read_idx != hw_read_idx && budget > 0) {
@@ -173,19 +187,19 @@ static bool alx_clean_tx_irq(struct alx_
 				budget--;
 			}
 
-			alx_free_txbuf(alx, sw_read_idx);
+			alx_free_txbuf(txq, sw_read_idx);
 
-			if (++sw_read_idx == alx->tx_ringsz)
+			if (++sw_read_idx == txq->count)
 				sw_read_idx = 0;
 		}
 		txq->read_idx = sw_read_idx;
 
-		netdev_completed_queue(alx->dev, total_packets, total_bytes);
+		netdev_tx_completed_queue(tx_queue, total_packets, total_bytes);
 	}
 
-	if (netif_queue_stopped(alx->dev) && netif_carrier_ok(alx->dev) &&
-	    alx_tpd_avail(alx) > alx->tx_ringsz/4)
-		netif_wake_queue(alx->dev);
+	if (netif_tx_queue_stopped(tx_queue) && netif_carrier_ok(alx->dev) &&
+	    alx_tpd_avail(txq) > txq->count / 4)
+		netif_tx_wake_queue(tx_queue);
 
 	return sw_read_idx == hw_read_idx;
 }
@@ -200,15 +214,17 @@ static void alx_schedule_reset(struct al
 	schedule_work(&alx->reset_wk);
 }
 
-static int alx_clean_rx_irq(struct alx_priv *alx, int budget)
+static int alx_clean_rx_irq(struct alx_rx_queue *rxq, int budget)
 {
-	struct alx_rx_queue *rxq = &alx->rxq;
+	struct alx_priv *alx;
 	struct alx_rrd *rrd;
 	struct alx_buffer *rxb;
 	struct sk_buff *skb;
 	u16 length, rfd_cleaned = 0;
 	int work = 0;
 
+	alx = netdev_priv(rxq->netdev);
+
 	while (work < budget) {
 		rrd = &rxq->rrd[rxq->rrd_read_idx];
 		if (!(rrd->word3 & cpu_to_le32(1 << RRD_UPDATED_SHIFT)))
@@ -224,7 +240,7 @@ static int alx_clean_rx_irq(struct alx_p
 		}
 
 		rxb = &rxq->bufs[rxq->read_idx];
-		dma_unmap_single(&alx->hw.pdev->dev,
+		dma_unmap_single(rxq->dev,
 				 dma_unmap_addr(rxb, dma),
 				 dma_unmap_len(rxb, size),
 				 DMA_FROM_DEVICE);
@@ -242,7 +258,7 @@ static int alx_clean_rx_irq(struct alx_p
 		length = ALX_GET_FIELD(le32_to_cpu(rrd->word3),
 				       RRD_PKTLEN) - ETH_FCS_LEN;
 		skb_put(skb, length);
-		skb->protocol = eth_type_trans(skb, alx->dev);
+		skb->protocol = eth_type_trans(skb, rxq->netdev);
 
 		skb_checksum_none_assert(skb);
 		if (alx->dev->features & NETIF_F_RXCSUM &&
@@ -259,13 +275,13 @@ static int alx_clean_rx_irq(struct alx_p
 			}
 		}
 
-		napi_gro_receive(&alx->napi, skb);
+		napi_gro_receive(&rxq->np->napi, skb);
 		work++;
 
 next_pkt:
-		if (++rxq->read_idx == alx->rx_ringsz)
+		if (++rxq->read_idx == rxq->count)
 			rxq->read_idx = 0;
-		if (++rxq->rrd_read_idx == alx->rx_ringsz)
+		if (++rxq->rrd_read_idx == rxq->count)
 			rxq->rrd_read_idx = 0;
 
 		if (++rfd_cleaned > ALX_RX_ALLOC_THRESH)
@@ -280,23 +296,26 @@ next_pkt:
 
 static int alx_poll(struct napi_struct *napi, int budget)
 {
-	struct alx_priv *alx = container_of(napi, struct alx_priv, napi);
+	struct alx_napi *np = container_of(napi, struct alx_napi, napi);
+	struct alx_priv *alx = np->alx;
 	struct alx_hw *hw = &alx->hw;
 	unsigned long flags;
-	bool tx_complete;
-	int work;
+	bool tx_complete = true;
+	int work = 0;
 
-	tx_complete = alx_clean_tx_irq(alx);
-	work = alx_clean_rx_irq(alx, budget);
+	if (np->txq)
+		tx_complete = alx_clean_tx_irq(np->txq);
+	if (np->rxq)
+		work = alx_clean_rx_irq(np->rxq, budget);
 
 	if (!tx_complete || work == budget)
 		return budget;
 
-	napi_complete(&alx->napi);
+	napi_complete(&np->napi);
 
 	/* enable interrupt */
 	if (alx->flags & ALX_FLAG_USING_MSIX) {
-		alx_mask_msix(hw, 1, false);
+		alx_mask_msix(hw, np->vec_idx, false);
 	} else {
 		spin_lock_irqsave(&alx->irq_lock, flags);
 		alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
@@ -350,7 +369,7 @@ static irqreturn_t alx_intr_handle(struc
 		goto out;
 
 	if (intr & (ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0)) {
-		napi_schedule(&alx->napi);
+		napi_schedule(&alx->qnapi[0]->napi);
 		/* mask rx/tx interrupt, enable them when napi complete */
 		alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
 		alx_write_mem32(hw, ALX_IMR, alx->int_mask);
@@ -365,15 +384,15 @@ static irqreturn_t alx_intr_handle(struc
 
 static irqreturn_t alx_intr_msix_ring(int irq, void *data)
 {
-	struct alx_priv *alx = data;
-	struct alx_hw *hw = &alx->hw;
+	struct alx_napi *np = data;
+	struct alx_hw *hw = &np->alx->hw;
 
 	/* mask interrupt to ACK chip */
-	alx_mask_msix(hw, 1, true);
+	alx_mask_msix(hw, np->vec_idx, true);
 	/* clear interrupt status */
-	alx_write_mem32(hw, ALX_ISR, (ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0));
+	alx_write_mem32(hw, ALX_ISR, np->vec_mask);
 
-	napi_schedule(&alx->napi);
+	napi_schedule(&np->napi);
 
 	return IRQ_HANDLED;
 }
@@ -424,63 +443,79 @@ static irqreturn_t alx_intr_legacy(int i
 	return alx_intr_handle(alx, intr);
 }
 
+static const u16 txring_header_reg[] = {ALX_TPD_PRI0_ADDR_LO,
+					ALX_TPD_PRI1_ADDR_LO,
+					ALX_TPD_PRI2_ADDR_LO,
+					ALX_TPD_PRI3_ADDR_LO};
+
 static void alx_init_ring_ptrs(struct alx_priv *alx)
 {
 	struct alx_hw *hw = &alx->hw;
 	u32 addr_hi = ((u64)alx->descmem.dma) >> 32;
+	struct alx_napi *np;
+	int i;
+
+	for (i = 0; i < alx->num_napi; i++) {
+		np = alx->qnapi[i];
+		if (np->txq) {
+			np->txq->read_idx = 0;
+			np->txq->write_idx = 0;
+			alx_write_mem32(hw,
+					txring_header_reg[np->txq->queue_idx],
+					np->txq->tpd_dma);
+		}
+
+		if (np->rxq) {
+			np->rxq->read_idx = 0;
+			np->rxq->write_idx = 0;
+			np->rxq->rrd_read_idx = 0;
+			alx_write_mem32(hw, ALX_RRD_ADDR_LO, np->rxq->rrd_dma);
+			alx_write_mem32(hw, ALX_RFD_ADDR_LO, np->rxq->rfd_dma);
+		}
+	}
+
+	alx_write_mem32(hw, ALX_TX_BASE_ADDR_HI, addr_hi);
+	alx_write_mem32(hw, ALX_TPD_RING_SZ, alx->tx_ringsz);
 
-	alx->rxq.read_idx = 0;
-	alx->rxq.write_idx = 0;
-	alx->rxq.rrd_read_idx = 0;
 	alx_write_mem32(hw, ALX_RX_BASE_ADDR_HI, addr_hi);
-	alx_write_mem32(hw, ALX_RRD_ADDR_LO, alx->rxq.rrd_dma);
 	alx_write_mem32(hw, ALX_RRD_RING_SZ, alx->rx_ringsz);
-	alx_write_mem32(hw, ALX_RFD_ADDR_LO, alx->rxq.rfd_dma);
 	alx_write_mem32(hw, ALX_RFD_RING_SZ, alx->rx_ringsz);
 	alx_write_mem32(hw, ALX_RFD_BUF_SZ, alx->rxbuf_size);
 
-	alx->txq.read_idx = 0;
-	alx->txq.write_idx = 0;
-	alx_write_mem32(hw, ALX_TX_BASE_ADDR_HI, addr_hi);
-	alx_write_mem32(hw, ALX_TPD_PRI0_ADDR_LO, alx->txq.tpd_dma);
-	alx_write_mem32(hw, ALX_TPD_RING_SZ, alx->tx_ringsz);
-
 	/* load these pointers into the chip */
 	alx_write_mem32(hw, ALX_SRAM9, ALX_SRAM_LOAD_PTR);
 }
 
-static void alx_free_txring_buf(struct alx_priv *alx)
+static void alx_free_txring_buf(struct alx_tx_queue *txq)
 {
-	struct alx_tx_queue *txq = &alx->txq;
 	int i;
 
 	if (!txq->bufs)
 		return;
 
-	for (i = 0; i < alx->tx_ringsz; i++)
-		alx_free_txbuf(alx, i);
+	for (i = 0; i < txq->count; i++)
+		alx_free_txbuf(txq, i);
 
-	memset(txq->bufs, 0, alx->tx_ringsz * sizeof(struct alx_buffer));
-	memset(txq->tpd, 0, alx->tx_ringsz * sizeof(struct alx_txd));
+	memset(txq->bufs, 0, txq->count * sizeof(struct alx_buffer));
+	memset(txq->tpd, 0, txq->count * sizeof(struct alx_txd));
 	txq->write_idx = 0;
 	txq->read_idx = 0;
 
-	netdev_reset_queue(alx->dev);
+	netdev_tx_reset_queue(alx_get_tx_queue(txq));
 }
 
-static void alx_free_rxring_buf(struct alx_priv *alx)
+static void alx_free_rxring_buf(struct alx_rx_queue *rxq)
 {
-	struct alx_rx_queue *rxq = &alx->rxq;
 	struct alx_buffer *cur_buf;
 	u16 i;
 
-	if (rxq == NULL)
+	if (!rxq->bufs)
 		return;
 
-	for (i = 0; i < alx->rx_ringsz; i++) {
+	for (i = 0; i < rxq->count; i++) {
 		cur_buf = rxq->bufs + i;
 		if (cur_buf->skb) {
-			dma_unmap_single(&alx->hw.pdev->dev,
+			dma_unmap_single(rxq->dev,
 					 dma_unmap_addr(cur_buf, dma),
 					 dma_unmap_len(cur_buf, size),
 					 DMA_FROM_DEVICE);
@@ -498,8 +533,14 @@ static void alx_free_rxring_buf(struct a
 
 static void alx_free_buffers(struct alx_priv *alx)
 {
-	alx_free_txring_buf(alx);
-	alx_free_rxring_buf(alx);
+	int i;
+
+	for (i = 0; i < alx->num_txq; i++)
+		if (alx->qnapi[i] && alx->qnapi[i]->txq)
+			alx_free_txring_buf(alx->qnapi[i]->txq);
+
+	if (alx->qnapi[0] && alx->qnapi[0]->rxq)
+		alx_free_rxring_buf(alx->qnapi[0]->rxq);
 }
 
 static int alx_reinit_rings(struct alx_priv *alx)
@@ -573,19 +614,41 @@ static int alx_set_mac_address(struct ne
 	return 0;
 }
 
-static int alx_alloc_descriptors(struct alx_priv *alx)
+static int alx_alloc_tx_ring(struct alx_priv *alx, struct alx_tx_queue *txq,
+			     int offset)
 {
-	alx->txq.bufs = kcalloc(alx->tx_ringsz,
-				sizeof(struct alx_buffer),
-				GFP_KERNEL);
-	if (!alx->txq.bufs)
+	txq->bufs = kcalloc(txq->count, sizeof(struct alx_buffer), GFP_KERNEL);
+	if (!txq->bufs)
 		return -ENOMEM;
 
-	alx->rxq.bufs = kcalloc(alx->rx_ringsz,
-				sizeof(struct alx_buffer),
-				GFP_KERNEL);
-	if (!alx->rxq.bufs)
-		goto out_free;
+	txq->tpd = alx->descmem.virt + offset;
+	txq->tpd_dma = alx->descmem.dma + offset;
+	offset += sizeof(struct alx_txd) * txq->count;
+
+	return offset;
+}
+
+static int alx_alloc_rx_ring(struct alx_priv *alx, struct alx_rx_queue *rxq,
+			     int offset)
+{
+	rxq->bufs = kcalloc(rxq->count, sizeof(struct alx_buffer), GFP_KERNEL);
+	if (!rxq->bufs)
+		return -ENOMEM;
+
+	rxq->rrd = alx->descmem.virt + offset;
+	rxq->rrd_dma = alx->descmem.dma + offset;
+	offset += sizeof(struct alx_rrd) * rxq->count;
+
+	rxq->rfd = alx->descmem.virt + offset;
+	rxq->rfd_dma = alx->descmem.dma + offset;
+	offset += sizeof(struct alx_rfd) * rxq->count;
+
+	return offset;
+}
+
+static int alx_alloc_rings(struct alx_priv *alx)
+{
+	int i, offset = 0;
 
 	/* physical tx/rx ring descriptors
 	 *
@@ -593,7 +656,8 @@ static int alx_alloc_descriptors(struct
 	 * 4G boundary (hardware has a single register for high 32 bits
 	 * of addresses only)
 	 */
-	alx->descmem.size = sizeof(struct alx_txd) * alx->tx_ringsz +
+	alx->descmem.size = sizeof(struct alx_txd) * alx->tx_ringsz *
+			    alx->num_txq +
 			    sizeof(struct alx_rrd) * alx->rx_ringsz +
 			    sizeof(struct alx_rfd) * alx->rx_ringsz;
 	alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev,
@@ -601,87 +665,176 @@ static int alx_alloc_descriptors(struct
 						&alx->descmem.dma,
 						GFP_KERNEL);
 	if (!alx->descmem.virt)
-		goto out_free;
-
-	alx->txq.tpd = alx->descmem.virt;
-	alx->txq.tpd_dma = alx->descmem.dma;
+		return -ENOMEM;
 
-	/* alignment requirement for next block */
+	/* alignment requirements */
 	BUILD_BUG_ON(sizeof(struct alx_txd) % 8);
-
-	alx->rxq.rrd =
-		(void *)((u8 *)alx->descmem.virt +
-			 sizeof(struct alx_txd) * alx->tx_ringsz);
-	alx->rxq.rrd_dma = alx->descmem.dma +
-			   sizeof(struct alx_txd) * alx->tx_ringsz;
-
-	/* alignment requirement for next block */
 	BUILD_BUG_ON(sizeof(struct alx_rrd) % 8);
 
-	alx->rxq.rfd =
-		(void *)((u8 *)alx->descmem.virt +
-			 sizeof(struct alx_txd) * alx->tx_ringsz +
-			 sizeof(struct alx_rrd) * alx->rx_ringsz);
-	alx->rxq.rfd_dma = alx->descmem.dma +
-			   sizeof(struct alx_txd) * alx->tx_ringsz +
-			   sizeof(struct alx_rrd) * alx->rx_ringsz;
+	for (i = 0; i < alx->num_txq; i++) {
+		offset = alx_alloc_tx_ring(alx, alx->qnapi[i]->txq, offset);
+		if (offset < 0) {
+			netdev_err(alx->dev, "Allocation of tx buffer failed!\n");
+			return -ENOMEM;
+		}
+	}
+
+	offset = alx_alloc_rx_ring(alx, alx->qnapi[0]->rxq, offset);
+	if (offset < 0) {
+		netdev_err(alx->dev, "Allocation of rx buffer failed!\n");
+		return -ENOMEM;
+	}
 
 	return 0;
-out_free:
-	kfree(alx->txq.bufs);
-	kfree(alx->rxq.bufs);
-	return -ENOMEM;
 }
 
-static int alx_alloc_rings(struct alx_priv *alx)
+static void alx_free_rings(struct alx_priv *alx)
 {
-	int err;
+	int i;
 
-	err = alx_alloc_descriptors(alx);
-	if (err)
-		return err;
+	alx_free_buffers(alx);
 
-	alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
-	alx->int_mask |= ALX_ISR_TX_Q0 | ALX_ISR_RX_Q0;
+	for (i = 0; i < alx->num_txq; i++)
+		if (alx->qnapi[i] && alx->qnapi[i]->txq)
+			kfree(alx->qnapi[i]->txq->bufs);
 
-	netif_napi_add(alx->dev, &alx->napi, alx_poll, 64);
+	if (alx->qnapi[0] && alx->qnapi[0]->rxq)
+		kfree(alx->qnapi[0]->rxq->bufs);
 
-	alx_reinit_rings(alx);
-	return 0;
+	if (alx->descmem.virt)
+		dma_free_coherent(&alx->hw.pdev->dev,
+				  alx->descmem.size,
+				  alx->descmem.virt,
+				  alx->descmem.dma);
 }
 
-static void alx_free_rings(struct alx_priv *alx)
+static void alx_free_napis(struct alx_priv *alx)
 {
-	netif_napi_del(&alx->napi);
-	alx_free_buffers(alx);
+	struct alx_napi *np;
+	int i;
 
-	kfree(alx->txq.bufs);
-	kfree(alx->rxq.bufs);
+	for (i = 0; i < alx->num_napi; i++) {
+		np = alx->qnapi[i];
+		if (!np)
+			continue;
 
-	dma_free_coherent(&alx->hw.pdev->dev,
-			  alx->descmem.size,
-			  alx->descmem.virt,
-			  alx->descmem.dma);
+		netif_napi_del(&np->napi);
+		kfree(np->txq);
+		kfree(np->rxq);
+		kfree(np);
+		alx->qnapi[i] = NULL;
+	}
+}
+
+static const u16 tx_pidx_reg[] = {ALX_TPD_PRI0_PIDX, ALX_TPD_PRI1_PIDX,
+				  ALX_TPD_PRI2_PIDX, ALX_TPD_PRI3_PIDX};
+static const u16 tx_cidx_reg[] = {ALX_TPD_PRI0_CIDX, ALX_TPD_PRI1_CIDX,
+				  ALX_TPD_PRI2_CIDX, ALX_TPD_PRI3_CIDX};
+static const u32 tx_vect_mask[] = {ALX_ISR_TX_Q0, ALX_ISR_TX_Q1,
+				   ALX_ISR_TX_Q2, ALX_ISR_TX_Q3};
+static const u32 rx_vect_mask[] = {ALX_ISR_RX_Q0, ALX_ISR_RX_Q1,
+				   ALX_ISR_RX_Q2, ALX_ISR_RX_Q3,
+				   ALX_ISR_RX_Q4, ALX_ISR_RX_Q5,
+				   ALX_ISR_RX_Q6, ALX_ISR_RX_Q7};
+
+static int alx_alloc_napis(struct alx_priv *alx)
+{
+	struct alx_napi *np;
+	struct alx_rx_queue *rxq;
+	struct alx_tx_queue *txq;
+	int i;
+
+	alx->int_mask &= ~ALX_ISR_ALL_QUEUES;
+
+	/* allocate alx_napi structures */
+	for (i = 0; i < alx->num_napi; i++) {
+		np = kzalloc(sizeof(struct alx_napi), GFP_KERNEL);
+		if (!np)
+			goto err_out;
+
+		np->alx = alx;
+		netif_napi_add(alx->dev, &np->napi, alx_poll, 64);
+		alx->qnapi[i] = np;
+	}
+
+	/* allocate tx queues */
+	for (i = 0; i < alx->num_txq; i++) {
+		np = alx->qnapi[i];
+		txq = kzalloc(sizeof(*txq), GFP_KERNEL);
+		if (!txq)
+			goto err_out;
+
+		np->txq = txq;
+		txq->p_reg = tx_pidx_reg[i];
+		txq->c_reg = tx_cidx_reg[i];
+		txq->queue_idx = i;
+		txq->count = alx->tx_ringsz;
+		txq->netdev = alx->dev;
+		txq->dev = &alx->hw.pdev->dev;
+		np->vec_mask |= tx_vect_mask[i];
+		alx->int_mask |= tx_vect_mask[i];
+	}
+
+	/* allocate rx queues */
+	np = alx->qnapi[0];
+	rxq = kzalloc(sizeof(*rxq), GFP_KERNEL);
+	if (!rxq)
+		goto err_out;
+
+	np->rxq = rxq;
+	rxq->np = alx->qnapi[0];
+	rxq->queue_idx = 0;
+	rxq->count = alx->rx_ringsz;
+	rxq->netdev = alx->dev;
+	rxq->dev = &alx->hw.pdev->dev;
+	np->vec_mask |= rx_vect_mask[0];
+	alx->int_mask |= rx_vect_mask[0];
+
+	return 0;
+
+err_out:
+	netdev_err(alx->dev, "error allocating internal structures\n");
+	alx_free_napis(alx);
+	return -ENOMEM;
 }
 
+static const int txq_vec_mapping_shift[] = {
+	0, ALX_MSI_MAP_TBL1_TXQ0_SHIFT,
+	0, ALX_MSI_MAP_TBL1_TXQ1_SHIFT,
+	1, ALX_MSI_MAP_TBL2_TXQ2_SHIFT,
+	1, ALX_MSI_MAP_TBL2_TXQ3_SHIFT,
+};
+
 static void alx_config_vector_mapping(struct alx_priv *alx)
 {
 	struct alx_hw *hw = &alx->hw;
-	u32 tbl = 0;
+	u32 tbl[2] = {0, 0};
+	int i, vector, idx, shift;
 
 	if (alx->flags & ALX_FLAG_USING_MSIX) {
-		tbl |= 1 << ALX_MSI_MAP_TBL1_TXQ0_SHIFT;
-		tbl |= 1 << ALX_MSI_MAP_TBL1_RXQ0_SHIFT;
+		/* tx mappings */
+		for (i = 0, vector = 1; i < alx->num_txq; i++, vector++) {
+			idx = txq_vec_mapping_shift[i * 2];
+			shift = txq_vec_mapping_shift[i * 2 + 1];
+			tbl[idx] |= vector << shift;
+		}
+
+		/* rx mapping */
+		tbl[0] |= 1 << ALX_MSI_MAP_TBL1_RXQ0_SHIFT;
 	}
 
-	alx_write_mem32(hw, ALX_MSI_MAP_TBL1, tbl);
-	alx_write_mem32(hw, ALX_MSI_MAP_TBL2, 0);
+	alx_write_mem32(hw, ALX_MSI_MAP_TBL1, tbl[0]);
+	alx_write_mem32(hw, ALX_MSI_MAP_TBL2, tbl[1]);
 	alx_write_mem32(hw, ALX_MSI_ID_MAP, 0);
 }
 
 static bool alx_enable_msix(struct alx_priv *alx)
 {
-	int i, err, num_vec = 2;
+	int i, err, num_vec, num_txq, num_rxq;
+
+	num_txq = min_t(int, num_online_cpus(), ALX_MAX_TX_QUEUES);
+	num_rxq = 1;
+	num_vec = max_t(int, num_txq, num_rxq) + 1;
 
 	alx->msix_entries = kcalloc(num_vec, sizeof(struct msix_entry),
 				    GFP_KERNEL);
@@ -701,6 +854,10 @@ static bool alx_enable_msix(struct alx_p
 	}
 
 	alx->num_vec = num_vec;
+	alx->num_napi = num_vec - 1;
+	alx->num_txq = num_txq;
+	alx->num_rxq = num_rxq;
+
 	return true;
 }
 
@@ -714,14 +871,29 @@ static int alx_request_msix(struct alx_p
 	if (err)
 		goto out_err;
 
-	vector++;
-	sprintf(alx->irq_lbl, "%s-TxRx-0", netdev->name);
+	for (i = 0; i < alx->num_napi; i++) {
+		struct alx_napi *np = alx->qnapi[i];
 
-	err = request_irq(alx->msix_entries[vector].vector,
-			  alx_intr_msix_ring, 0, alx->irq_lbl, alx);
+		vector++;
+
+		if (np->txq && np->rxq)
+			sprintf(np->irq_lbl, "%s-TxRx-%u", netdev->name,
+				np->txq->queue_idx);
+		else if (np->txq)
+			sprintf(np->irq_lbl, "%s-tx-%u", netdev->name,
+				np->txq->queue_idx);
+		else if (np->rxq)
+			sprintf(np->irq_lbl, "%s-rx-%u", netdev->name,
+				np->rxq->queue_idx);
+		else
+			sprintf(np->irq_lbl, "%s-unused", netdev->name);
+
+		np->vec_idx = vector;
+		err = request_irq(alx->msix_entries[vector].vector,
+				  alx_intr_msix_ring, 0, np->irq_lbl, np);
 		if (err)
 			goto out_free;
-
+	}
 	return 0;
 
 out_free:
@@ -729,7 +901,8 @@ out_free:
 
 	vector--;
 	for (i = 0; i < vector; i++)
-		free_irq(alx->msix_entries[free_vector++].vector, alx);
+		free_irq(alx->msix_entries[free_vector++].vector,
+			 alx->qnapi[i]);
 
 out_err:
 	return err;
@@ -744,6 +917,9 @@ static void alx_init_intr(struct alx_pri
 
 	if (!(alx->flags & ALX_FLAG_USING_MSIX)) {
 		alx->num_vec = 1;
+		alx->num_napi = 1;
+		alx->num_txq = 1;
+		alx->num_rxq = 1;
 
 		if (!pci_enable_msi(alx->hw.pdev))
 			alx->flags |= ALX_FLAG_USING_MSI;
@@ -799,6 +975,26 @@ static void alx_irq_disable(struct alx_p
 	}
 }
 
+static int alx_realloc_resources(struct alx_priv *alx)
+{
+	int err;
+
+	alx_free_rings(alx);
+	alx_free_napis(alx);
+	alx_disable_advanced_intr(alx);
+	alx_init_intr(alx, false);
+
+	err = alx_alloc_napis(alx);
+	if (err)
+		return err;
+
+	err = alx_alloc_rings(alx);
+	if (err)
+		return err;
+
+	return 0;
+}
+
 static int alx_request_irq(struct alx_priv *alx)
 {
 	struct pci_dev *pdev = alx->hw.pdev;
@@ -815,8 +1011,9 @@ static int alx_request_irq(struct alx_pr
 			goto out;
 
 		/* msix request failed, realloc resources */
-		alx_disable_advanced_intr(alx);
-		alx_init_intr(alx, false);
+		err = alx_realloc_resources(alx);
+		if (err)
+			goto out;
 	}
 
 	if (alx->flags & ALX_FLAG_USING_MSI) {
@@ -845,12 +1042,13 @@ out:
 static void alx_free_irq(struct alx_priv *alx)
 {
 	struct pci_dev *pdev = alx->hw.pdev;
-	int i;
+	int i, vector = 0;
 
 	if (alx->flags & ALX_FLAG_USING_MSIX) {
-		/* we have only 2 vectors without multi queue support */
-		for (i = 0; i < 2; i++)
-			free_irq(alx->msix_entries[i].vector, alx);
+		free_irq(alx->msix_entries[vector++].vector, alx);
+		for (i = 0; i < alx->num_napi; i++)
+			free_irq(alx->msix_entries[vector++].vector,
+				 alx->qnapi[i]);
 	} else {
 		free_irq(pdev->irq, alx);
 	}
@@ -892,6 +1090,9 @@ static int alx_init_sw(struct alx_priv *
 	hw->smb_timer = 400;
 	hw->mtu = alx->dev->mtu;
 	alx->rxbuf_size = ALX_MAX_FRAME_LEN(hw->mtu);
+	/* MTU range: 34 - 9256 */
+	alx->dev->min_mtu = 34;
+	alx->dev->max_mtu = ALX_MAX_FRAME_LEN(ALX_MAX_FRAME_SIZE);
 	alx->tx_ringsz = 256;
 	alx->rx_ringsz = 512;
 	hw->imt = 200;
@@ -932,11 +1133,14 @@ static netdev_features_t alx_fix_feature
 
 static void alx_netif_stop(struct alx_priv *alx)
 {
+	int i;
+
 	netif_trans_update(alx->dev);
 	if (netif_carrier_ok(alx->dev)) {
 		netif_carrier_off(alx->dev);
 		netif_tx_disable(alx->dev);
-		napi_disable(&alx->napi);
+		for (i = 0; i < alx->num_napi; i++)
+			napi_disable(&alx->qnapi[i]->napi);
 	}
 }
 
@@ -994,13 +1198,6 @@ static int alx_change_mtu(struct net_dev
 	struct alx_priv *alx = netdev_priv(netdev);
 	int max_frame = ALX_MAX_FRAME_LEN(mtu);
 
-	if ((max_frame < ALX_MIN_FRAME_SIZE) ||
-	    (max_frame > ALX_MAX_FRAME_SIZE))
-		return -EINVAL;
-
-	if (netdev->mtu == mtu)
-		return 0;
-
 	netdev->mtu = mtu;
 	alx->hw.mtu = mtu;
 	alx->rxbuf_size = max(max_frame, ALX_DEF_RXBUF_SIZE);
@@ -1012,8 +1209,11 @@ static int alx_change_mtu(struct net_dev
 
 static void alx_netif_start(struct alx_priv *alx)
 {
+	int i;
+
 	netif_tx_wake_all_queues(alx->dev);
-	napi_enable(&alx->napi);
+	for (i = 0; i < alx->num_napi; i++)
+		napi_enable(&alx->qnapi[i]->napi);
 	netif_carrier_on(alx->dev);
 }
 
@@ -1021,21 +1221,34 @@ static int __alx_open(struct alx_priv *a
 {
 	int err;
 
-	alx_init_intr(alx, msix);
+	alx_init_intr(alx, true);
 
 	if (!resume)
 		netif_carrier_off(alx->dev);
 
-	err = alx_alloc_rings(alx);
+	err = alx_alloc_napis(alx);
 	if (err)
 		goto out_disable_adv_intr;
 
+	err = alx_alloc_rings(alx);
+	if (err)
+		goto out_free_rings;
+
 	alx_configure(alx);
 
 	err = alx_request_irq(alx);
 	if (err)
 		goto out_free_rings;
 
+	/* must be called after alx_request_irq because the chip stops working
+	 * if we copy the dma addresses in alx_init_ring_ptrs twice when
+	 * requesting msi-x interrupts failed
+	 */
+	alx_reinit_rings(alx);
+
+	netif_set_real_num_tx_queues(alx->dev, alx->num_txq);
+	netif_set_real_num_rx_queues(alx->dev, alx->num_rxq);
+
 	/* clear old interrupts */
 	alx_write_mem32(&alx->hw, ALX_ISR, ~(u32)ALX_ISR_DIS);
 
@@ -1049,6 +1262,7 @@ static int __alx_open(struct alx_priv *a
 
 out_free_rings:
 	alx_free_rings(alx);
+	alx_free_napis(alx);
 out_disable_adv_intr:
 	alx_disable_advanced_intr(alx);
 	return err;
@@ -1059,6 +1273,7 @@ static void __alx_stop(struct alx_priv *
 	alx_halt(alx);
 	alx_free_irq(alx);
 	alx_free_rings(alx);
+	alx_free_napis(alx);
 }
 
 static const char *alx_speed_desc(struct alx_hw *hw)
@@ -1241,9 +1456,8 @@ static int alx_tso(struct sk_buff *skb,
 	return 1;
 }
 
-static int alx_map_tx_skb(struct alx_priv *alx, struct sk_buff *skb)
+static int alx_map_tx_skb(struct alx_tx_queue *txq, struct sk_buff *skb)
 {
-	struct alx_tx_queue *txq = &alx->txq;
 	struct alx_txd *tpd, *first_tpd;
 	dma_addr_t dma;
 	int maplen, f, first_idx = txq->write_idx;
@@ -1252,7 +1466,7 @@ static int alx_map_tx_skb(struct alx_pri
 	tpd = first_tpd;
 
 	if (tpd->word1 & (1 << TPD_LSO_V2_SHIFT)) {
-		if (++txq->write_idx == alx->tx_ringsz)
+		if (++txq->write_idx == txq->count)
 			txq->write_idx = 0;
 
 		tpd = &txq->tpd[txq->write_idx];
@@ -1262,9 +1476,9 @@ static int alx_map_tx_skb(struct alx_pri
 	}
 
 	maplen = skb_headlen(skb);
-	dma = dma_map_single(&alx->hw.pdev->dev, skb->data, maplen,
+	dma = dma_map_single(txq->dev, skb->data, maplen,
 			     DMA_TO_DEVICE);
-	if (dma_mapping_error(&alx->hw.pdev->dev, dma))
+	if (dma_mapping_error(txq->dev, dma))
 		goto err_dma;
 
 	dma_unmap_len_set(&txq->bufs[txq->write_idx], size, maplen);
@@ -1278,16 +1492,16 @@ static int alx_map_tx_skb(struct alx_pri
 
 		frag = &skb_shinfo(skb)->frags[f];
 
-		if (++txq->write_idx == alx->tx_ringsz)
+		if (++txq->write_idx == txq->count)
 			txq->write_idx = 0;
 		tpd = &txq->tpd[txq->write_idx];
 
 		tpd->word1 = first_tpd->word1;
 
 		maplen = skb_frag_size(frag);
-		dma = skb_frag_dma_map(&alx->hw.pdev->dev, frag, 0,
+		dma = skb_frag_dma_map(txq->dev, frag, 0,
 				       maplen, DMA_TO_DEVICE);
-		if (dma_mapping_error(&alx->hw.pdev->dev, dma))
+		if (dma_mapping_error(txq->dev, dma))
 			goto err_dma;
 		dma_unmap_len_set(&txq->bufs[txq->write_idx], size, maplen);
 		dma_unmap_addr_set(&txq->bufs[txq->write_idx], dma, dma);
@@ -1300,7 +1514,7 @@ static int alx_map_tx_skb(struct alx_pri
 	tpd->word1 |= cpu_to_le32(1 << TPD_EOP_SHIFT);
 	txq->bufs[txq->write_idx].skb = skb;
 
-	if (++txq->write_idx == alx->tx_ringsz)
+	if (++txq->write_idx == txq->count)
 		txq->write_idx = 0;
 
 	return 0;
@@ -1308,23 +1522,24 @@ static int alx_map_tx_skb(struct alx_pri
 err_dma:
 	f = first_idx;
 	while (f != txq->write_idx) {
-		alx_free_txbuf(alx, f);
-		if (++f == alx->tx_ringsz)
+		alx_free_txbuf(txq, f);
+		if (++f == txq->count)
 			f = 0;
 	}
 	return -ENOMEM;
 }
 
-static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
-				  struct net_device *netdev)
+static netdev_tx_t alx_start_xmit_ring(struct sk_buff *skb,
+				       struct alx_tx_queue *txq)
 {
-	struct alx_priv *alx = netdev_priv(netdev);
-	struct alx_tx_queue *txq = &alx->txq;
+	struct alx_priv *alx;
 	struct alx_txd *first;
 	int tso;
 
-	if (alx_tpd_avail(alx) < alx_tpd_req(skb)) {
-		netif_stop_queue(alx->dev);
+	alx = netdev_priv(txq->netdev);
+
+	if (alx_tpd_avail(txq) < alx_tpd_req(skb)) {
+		netif_tx_stop_queue(alx_get_tx_queue(txq));
 		goto drop;
 	}
 
@@ -1337,17 +1552,17 @@ static netdev_tx_t alx_start_xmit(struct
 	else if (!tso && alx_tx_csum(skb, first))
 		goto drop;
 
-	if (alx_map_tx_skb(alx, skb) < 0)
+	if (alx_map_tx_skb(txq, skb) < 0)
 		goto drop;
 
-	netdev_sent_queue(alx->dev, skb->len);
+	netdev_tx_sent_queue(alx_get_tx_queue(txq), skb->len);
 
 	/* flush updates before updating hardware */
 	wmb();
-	alx_write_mem16(&alx->hw, ALX_TPD_PRI0_PIDX, txq->write_idx);
+	alx_write_mem16(&alx->hw, txq->p_reg, txq->write_idx);
 
-	if (alx_tpd_avail(alx) < alx->tx_ringsz/8)
-		netif_stop_queue(alx->dev);
+	if (alx_tpd_avail(txq) < txq->count / 8)
+		netif_tx_stop_queue(alx_get_tx_queue(txq));
 
 	return NETDEV_TX_OK;
 
@@ -1356,6 +1571,13 @@ drop:
 	return NETDEV_TX_OK;
 }
 
+static netdev_tx_t alx_start_xmit(struct sk_buff *skb,
+				  struct net_device *netdev)
+{
+	struct alx_priv *alx = netdev_priv(netdev);
+	return alx_start_xmit_ring(skb, alx_tx_queue_mapping(alx, skb));
+}
+
 static void alx_tx_timeout(struct net_device *dev)
 {
 	struct alx_priv *alx = netdev_priv(dev);
@@ -1413,10 +1635,12 @@ static int alx_ioctl(struct net_device *
 static void alx_poll_controller(struct net_device *netdev)
 {
 	struct alx_priv *alx = netdev_priv(netdev);
+	int i;
 
 	if (alx->flags & ALX_FLAG_USING_MSIX) {
 		alx_intr_msix_misc(0, alx);
-		alx_intr_msix_ring(0, alx);
+		for (i = 0; i < alx->num_txq; i++)
+			alx_intr_msix_ring(0, alx->qnapi[i]);
 	} else if (alx->flags & ALX_FLAG_USING_MSI)
 		alx_intr_msi(0, alx);
 	else
@@ -1533,7 +1757,8 @@ static int alx_probe(struct pci_dev *pde
 		goto out_pci_release;
 	}
 
-	netdev = alloc_etherdev(sizeof(*alx));
+	netdev = alloc_etherdev_mqs(sizeof(*alx),
+				    ALX_MAX_TX_QUEUES, 1);
 	if (!netdev) {
 		err = -ENOMEM;
 		goto out_pci_release;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/alx/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/alx/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,2 @@
 obj-$(CONFIG_ALX) += alx.o
 alx-objs := main.o ethtool.o hw.o
-ccflags-y += -D__CHECK_ENDIAN__
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,46 +26,52 @@
 
 #include "atl1c.h"
 
-static int atl1c_get_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
+static int atl1c_get_link_ksettings(struct net_device *netdev,
+				    struct ethtool_link_ksettings *cmd)
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 	struct atl1c_hw *hw = &adapter->hw;
+	u32 supported, advertising;
 
-	ecmd->supported = (SUPPORTED_10baseT_Half  |
+	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;
+		supported |= SUPPORTED_1000baseT_Full;
 
-	ecmd->advertising = ADVERTISED_TP;
+	advertising = ADVERTISED_TP;
 
-	ecmd->advertising |= hw->autoneg_advertised;
+	advertising |= hw->autoneg_advertised;
 
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
+	cmd->base.port = PORT_TP;
+	cmd->base.phy_address = 0;
 
 	if (adapter->link_speed != SPEED_0) {
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+		cmd->base.speed = adapter->link_speed;
 		if (adapter->link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
+			cmd->base.duplex = DUPLEX_FULL;
 		else
-			ecmd->duplex = DUPLEX_HALF;
+			cmd->base.duplex = DUPLEX_HALF;
 	} else {
-		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
-		ecmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 
-	ecmd->autoneg = AUTONEG_ENABLE;
+	cmd->base.autoneg = AUTONEG_ENABLE;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
+
 	return 0;
 }
 
-static int atl1c_set_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
+static int atl1c_set_link_ksettings(struct net_device *netdev,
+				    const struct ethtool_link_ksettings *cmd)
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 	struct atl1c_hw *hw = &adapter->hw;
@@ -74,12 +80,12 @@ static int atl1c_set_settings(struct net
 	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
 		msleep(1);
 
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
+	if (cmd->base.autoneg == AUTONEG_ENABLE) {
 		autoneg_advertised = ADVERTISED_Autoneg;
 	} else {
-		u32 speed = ethtool_cmd_speed(ecmd);
+		u32 speed = cmd->base.speed;
 		if (speed == SPEED_1000) {
-			if (ecmd->duplex != DUPLEX_FULL) {
+			if (cmd->base.duplex != DUPLEX_FULL) {
 				if (netif_msg_link(adapter))
 					dev_warn(&adapter->pdev->dev,
 						"1000M half is invalid\n");
@@ -88,12 +94,12 @@ static int atl1c_set_settings(struct net
 			}
 			autoneg_advertised = ADVERTISED_1000baseT_Full;
 		} else if (speed == SPEED_100) {
-			if (ecmd->duplex == DUPLEX_FULL)
+			if (cmd->base.duplex == DUPLEX_FULL)
 				autoneg_advertised = ADVERTISED_100baseT_Full;
 			else
 				autoneg_advertised = ADVERTISED_100baseT_Half;
 		} else {
-			if (ecmd->duplex == DUPLEX_FULL)
+			if (cmd->base.duplex == DUPLEX_FULL)
 				autoneg_advertised = ADVERTISED_10baseT_Full;
 			else
 				autoneg_advertised = ADVERTISED_10baseT_Half;
@@ -284,8 +290,6 @@ static int atl1c_nway_reset(struct net_d
 }
 
 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,
@@ -297,6 +301,8 @@ static const struct ethtool_ops atl1c_et
 	.get_link               = ethtool_op_get_link,
 	.get_eeprom_len         = atl1c_get_eeprom_len,
 	.get_eeprom             = atl1c_get_eeprom,
+	.get_link_ksettings     = atl1c_get_link_ksettings,
+	.set_link_ksettings     = atl1c_set_link_ksettings,
 };
 
 void atl1c_set_ethtool_ops(struct net_device *netdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1c/atl1c_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -519,6 +519,26 @@ static int atl1c_set_features(struct net
 	return 0;
 }
 
+static void atl1c_set_max_mtu(struct net_device *netdev)
+{
+	struct atl1c_adapter *adapter = netdev_priv(netdev);
+	struct atl1c_hw *hw = &adapter->hw;
+
+	switch (hw->nic_type) {
+	/* These (GbE) devices support jumbo packets, max_mtu 6122 */
+	case athr_l1c:
+	case athr_l1d:
+	case athr_l1d_2:
+		netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+				  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+		break;
+	/* The 10/100 devices don't support jumbo packets, max_mtu 1500 */
+	default:
+		netdev->max_mtu = ETH_DATA_LEN;
+		break;
+	}
+}
+
 /**
  * atl1c_change_mtu - Change the Maximum Transfer Unit
  * @netdev: network interface device structure
@@ -529,22 +549,9 @@ static int atl1c_set_features(struct net
 static int atl1c_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
-	struct atl1c_hw *hw = &adapter->hw;
-	int old_mtu   = netdev->mtu;
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 
-	/* Fast Ethernet controller doesn't support jumbo packet */
-	if (((hw->nic_type == athr_l2c ||
-	      hw->nic_type == athr_l2c_b ||
-	      hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) ||
-	      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)) {
+	if (netif_running(netdev)) {
 		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
 			msleep(1);
 		netdev->mtu = new_mtu;
@@ -2511,6 +2518,7 @@ static int atl1c_init_netdev(struct net_
 
 	netdev->netdev_ops = &atl1c_netdev_ops;
 	netdev->watchdog_timeo = AT_TX_WATCHDOG;
+	netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
 	atl1c_set_ethtool_ops(netdev);
 
 	/* TODO: add when ready */
@@ -2613,6 +2621,9 @@ static int atl1c_probe(struct pci_dev *p
 		dev_err(&pdev->dev, "net device private data init failed\n");
 		goto err_sw_init;
 	}
+	/* set max MTU */
+	atl1c_set_max_mtu(netdev);
+
 	atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE);
 
 	/* Init GPHY as early as possible due to power saving issue  */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -26,73 +26,83 @@
 
 #include "atl1e.h"
 
-static int atl1e_get_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
+static int atl1e_get_link_ksettings(struct net_device *netdev,
+				    struct ethtool_link_ksettings *cmd)
 {
 	struct atl1e_adapter *adapter = netdev_priv(netdev);
 	struct atl1e_hw *hw = &adapter->hw;
+	u32 supported, advertising;
 
-	ecmd->supported = (SUPPORTED_10baseT_Half  |
+	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;
+		supported |= SUPPORTED_1000baseT_Full;
 
-	ecmd->advertising = ADVERTISED_TP;
+	advertising = ADVERTISED_TP;
 
-	ecmd->advertising |= ADVERTISED_Autoneg;
-	ecmd->advertising |= hw->autoneg_advertised;
+	advertising |= ADVERTISED_Autoneg;
+	advertising |= hw->autoneg_advertised;
 
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
+	cmd->base.port = PORT_TP;
+	cmd->base.phy_address = 0;
 
 	if (adapter->link_speed != SPEED_0) {
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+		cmd->base.speed = adapter->link_speed;
 		if (adapter->link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
+			cmd->base.duplex = DUPLEX_FULL;
 		else
-			ecmd->duplex = DUPLEX_HALF;
+			cmd->base.duplex = DUPLEX_HALF;
 	} else {
-		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
-		ecmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 
-	ecmd->autoneg = AUTONEG_ENABLE;
+	cmd->base.autoneg = AUTONEG_ENABLE;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
+
 	return 0;
 }
 
-static int atl1e_set_settings(struct net_device *netdev,
-			      struct ethtool_cmd *ecmd)
+static int atl1e_set_link_ksettings(struct net_device *netdev,
+				    const struct ethtool_link_ksettings *cmd)
 {
 	struct atl1e_adapter *adapter = netdev_priv(netdev);
 	struct atl1e_hw *hw = &adapter->hw;
+	u32 advertising;
+
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						cmd->link_modes.advertising);
 
 	while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
 		msleep(1);
 
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
+	if (cmd->base.autoneg == AUTONEG_ENABLE) {
 		u16 adv4, adv9;
 
-		if ((ecmd->advertising&ADVERTISE_1000_FULL)) {
+		if (advertising & ADVERTISE_1000_FULL) {
 			if (hw->nic_type == athr_l1e) {
 				hw->autoneg_advertised =
-					ecmd->advertising & AT_ADV_MASK;
+					advertising & AT_ADV_MASK;
 			} else {
 				clear_bit(__AT_RESETTING, &adapter->flags);
 				return -EINVAL;
 			}
-		} else if (ecmd->advertising&ADVERTISE_1000_HALF) {
+		} else if (advertising & ADVERTISE_1000_HALF) {
 			clear_bit(__AT_RESETTING, &adapter->flags);
 			return -EINVAL;
 		} else {
 			hw->autoneg_advertised =
-				ecmd->advertising & AT_ADV_MASK;
+				advertising & AT_ADV_MASK;
 		}
-		ecmd->advertising = hw->autoneg_advertised |
+		advertising = hw->autoneg_advertised |
 				    ADVERTISED_TP | ADVERTISED_Autoneg;
 
 		adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL;
@@ -367,8 +377,6 @@ static int atl1e_nway_reset(struct net_d
 }
 
 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,
@@ -380,6 +388,8 @@ static const struct ethtool_ops atl1e_et
 	.get_eeprom_len         = atl1e_get_eeprom_len,
 	.get_eeprom             = atl1e_get_eeprom,
 	.set_eeprom             = atl1e_set_eeprom,
+	.get_link_ksettings     = atl1e_get_link_ksettings,
+	.set_link_ksettings     = atl1e_set_link_ksettings,
 };
 
 void atl1e_set_ethtool_ops(struct net_device *netdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atl1e/atl1e_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -439,16 +439,10 @@ static int atl1e_set_features(struct net
 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)) {
+	if (netif_running(netdev)) {
 		while (test_and_set_bit(__AT_RESETTING, &adapter->flags))
 			msleep(1);
 		netdev->mtu = new_mtu;
@@ -2272,6 +2266,10 @@ static int atl1e_init_netdev(struct net_
 	netdev->netdev_ops = &atl1e_netdev_ops;
 
 	netdev->watchdog_timeo = AT_TX_WATCHDOG;
+	/* MTU range: 42 - 8170 */
+	netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
+	netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+			  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
 	atl1e_set_ethtool_ops(netdev);
 
 	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO |
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atlx/atl1.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atlx/atl1.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atlx/atl1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atlx/atl1.c	2017-02-12 16:03:20.000000000 -0500
@@ -2701,23 +2701,15 @@ static void atl1_reset_dev_task(struct w
 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)) {
+	if (netif_running(netdev)) {
 		atl1_down(adapter);
 		atl1_up(adapter);
 	}
@@ -3031,6 +3023,11 @@ static int atl1_probe(struct pci_dev *pd
 	/* is this valid? see atl1_setup_mac_ctrl() */
 	netdev->features |= NETIF_F_RXCSUM;
 
+	/* MTU range: 42 - 10218 */
+	netdev->min_mtu = ETH_ZLEN - (ETH_HLEN + VLAN_HLEN);
+	netdev->max_mtu = MAX_JUMBO_FRAME_SIZE -
+			  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
 	/*
 	 * patch for some L1 of old version,
 	 * the final version of L1 may not need these
@@ -3217,66 +3214,72 @@ static int atl1_get_sset_count(struct ne
 	}
 }
 
-static int atl1_get_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
+static int atl1_get_link_ksettings(struct net_device *netdev,
+				   struct ethtool_link_ksettings *cmd)
 {
 	struct atl1_adapter *adapter = netdev_priv(netdev);
 	struct atl1_hw *hw = &adapter->hw;
+	u32 supported, advertising;
 
-	ecmd->supported = (SUPPORTED_10baseT_Half |
+	supported = (SUPPORTED_10baseT_Half |
 			   SUPPORTED_10baseT_Full |
 			   SUPPORTED_100baseT_Half |
 			   SUPPORTED_100baseT_Full |
 			   SUPPORTED_1000baseT_Full |
 			   SUPPORTED_Autoneg | SUPPORTED_TP);
-	ecmd->advertising = ADVERTISED_TP;
+	advertising = ADVERTISED_TP;
 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
 	    hw->media_type == MEDIA_TYPE_1000M_FULL) {
-		ecmd->advertising |= ADVERTISED_Autoneg;
+		advertising |= ADVERTISED_Autoneg;
 		if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR) {
-			ecmd->advertising |= ADVERTISED_Autoneg;
-			ecmd->advertising |=
+			advertising |= ADVERTISED_Autoneg;
+			advertising |=
 			    (ADVERTISED_10baseT_Half |
 			     ADVERTISED_10baseT_Full |
 			     ADVERTISED_100baseT_Half |
 			     ADVERTISED_100baseT_Full |
 			     ADVERTISED_1000baseT_Full);
 		} else
-			ecmd->advertising |= (ADVERTISED_1000baseT_Full);
+			advertising |= (ADVERTISED_1000baseT_Full);
 	}
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
+	cmd->base.port = PORT_TP;
+	cmd->base.phy_address = 0;
 
 	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);
+		cmd->base.speed = link_speed;
 		if (link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
+			cmd->base.duplex = DUPLEX_FULL;
 		else
-			ecmd->duplex = DUPLEX_HALF;
+			cmd->base.duplex = DUPLEX_HALF;
 	} else {
-		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
-		ecmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||
 	    hw->media_type == MEDIA_TYPE_1000M_FULL)
-		ecmd->autoneg = AUTONEG_ENABLE;
+		cmd->base.autoneg = AUTONEG_ENABLE;
 	else
-		ecmd->autoneg = AUTONEG_DISABLE;
+		cmd->base.autoneg = AUTONEG_DISABLE;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return 0;
 }
 
-static int atl1_set_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
+static int atl1_set_link_ksettings(struct net_device *netdev,
+				   const struct ethtool_link_ksettings *cmd)
 {
 	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;
+	u32 advertising;
 
 	if (netif_running(adapter->netdev)) {
 		if (netif_msg_link(adapter))
@@ -3285,12 +3288,12 @@ static int atl1_set_settings(struct net_
 		atl1_down(adapter);
 	}
 
-	if (ecmd->autoneg == AUTONEG_ENABLE)
+	if (cmd->base.autoneg == AUTONEG_ENABLE)
 		hw->media_type = MEDIA_TYPE_AUTO_SENSOR;
 	else {
-		u32 speed = ethtool_cmd_speed(ecmd);
+		u32 speed = cmd->base.speed;
 		if (speed == SPEED_1000) {
-			if (ecmd->duplex != DUPLEX_FULL) {
+			if (cmd->base.duplex != DUPLEX_FULL) {
 				if (netif_msg_link(adapter))
 					dev_warn(&adapter->pdev->dev,
 						"1000M half is invalid\n");
@@ -3299,12 +3302,12 @@ static int atl1_set_settings(struct net_
 			}
 			hw->media_type = MEDIA_TYPE_1000M_FULL;
 		} else if (speed == SPEED_100) {
-			if (ecmd->duplex == DUPLEX_FULL)
+			if (cmd->base.duplex == DUPLEX_FULL)
 				hw->media_type = MEDIA_TYPE_100M_FULL;
 			else
 				hw->media_type = MEDIA_TYPE_100M_HALF;
 		} else {
-			if (ecmd->duplex == DUPLEX_FULL)
+			if (cmd->base.duplex == DUPLEX_FULL)
 				hw->media_type = MEDIA_TYPE_10M_FULL;
 			else
 				hw->media_type = MEDIA_TYPE_10M_HALF;
@@ -3312,7 +3315,7 @@ static int atl1_set_settings(struct net_
 	}
 	switch (hw->media_type) {
 	case MEDIA_TYPE_AUTO_SENSOR:
-		ecmd->advertising =
+		advertising =
 		    ADVERTISED_10baseT_Half |
 		    ADVERTISED_10baseT_Full |
 		    ADVERTISED_100baseT_Half |
@@ -3321,12 +3324,12 @@ static int atl1_set_settings(struct net_
 		    ADVERTISED_Autoneg | ADVERTISED_TP;
 		break;
 	case MEDIA_TYPE_1000M_FULL:
-		ecmd->advertising =
+		advertising =
 		    ADVERTISED_1000baseT_Full |
 		    ADVERTISED_Autoneg | ADVERTISED_TP;
 		break;
 	default:
-		ecmd->advertising = 0;
+		advertising = 0;
 		break;
 	}
 	if (atl1_phy_setup_autoneg_adv(hw)) {
@@ -3666,8 +3669,6 @@ static int atl1_nway_reset(struct net_de
 }
 
 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,
@@ -3684,6 +3685,8 @@ static const struct ethtool_ops atl1_eth
 	.nway_reset		= atl1_nway_reset,
 	.get_ethtool_stats	= atl1_get_ethtool_stats,
 	.get_sset_count		= atl1_get_sset_count,
+	.get_link_ksettings	= atl1_get_link_ksettings,
+	.set_link_ksettings	= atl1_set_link_ksettings,
 };
 
 module_pci_driver(atl1_driver);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atlx/atl2.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atlx/atl2.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atlx/atl2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atlx/atl2.c	2017-02-12 16:03:20.000000000 -0500
@@ -253,7 +253,7 @@ static int atl2_configure(struct atl2_ad
 
 	/* set MTU */
 	ATL2_WRITE_REG(hw, REG_MTU, adapter->netdev->mtu +
-		ENET_HEADER_SIZE + VLAN_SIZE + ETHERNET_FCS_SIZE);
+		ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
 
 	/* 1590 */
 	ATL2_WRITE_REG(hw, REG_TX_CUT_THRESH, 0x177);
@@ -925,15 +925,11 @@ static int atl2_change_mtu(struct net_de
 	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);
-	}
+	netdev->mtu = new_mtu;
+	hw->max_frame_size = new_mtu;
+	ATL2_WRITE_REG(hw, REG_MTU, new_mtu + ETH_HLEN +
+		       VLAN_HLEN + ETH_FCS_LEN);
 
 	return 0;
 }
@@ -1398,6 +1394,8 @@ static int atl2_probe(struct pci_dev *pd
 	netdev->netdev_ops = &atl2_netdev_ops;
 	netdev->ethtool_ops = &atl2_ethtool_ops;
 	netdev->watchdog_timeo = 5 * HZ;
+	netdev->min_mtu = 40;
+	netdev->max_mtu = ETH_DATA_LEN + VLAN_HLEN;
 	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
 
 	netdev->mem_start = mmio_start;
@@ -1739,81 +1737,87 @@ static void atl2_write_pci_cfg(struct at
 	pci_write_config_word(adapter->pdev, reg, *value);
 }
 
-static int atl2_get_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
+static int atl2_get_link_ksettings(struct net_device *netdev,
+				   struct ethtool_link_ksettings *cmd)
 {
 	struct atl2_adapter *adapter = netdev_priv(netdev);
 	struct atl2_hw *hw = &adapter->hw;
+	u32 supported, advertising;
 
-	ecmd->supported = (SUPPORTED_10baseT_Half |
+	supported = (SUPPORTED_10baseT_Half |
 		SUPPORTED_10baseT_Full |
 		SUPPORTED_100baseT_Half |
 		SUPPORTED_100baseT_Full |
 		SUPPORTED_Autoneg |
 		SUPPORTED_TP);
-	ecmd->advertising = ADVERTISED_TP;
+	advertising = ADVERTISED_TP;
 
-	ecmd->advertising |= ADVERTISED_Autoneg;
-	ecmd->advertising |= hw->autoneg_advertised;
+	advertising |= ADVERTISED_Autoneg;
+	advertising |= hw->autoneg_advertised;
 
-	ecmd->port = PORT_TP;
-	ecmd->phy_address = 0;
-	ecmd->transceiver = XCVR_INTERNAL;
+	cmd->base.port = PORT_TP;
+	cmd->base.phy_address = 0;
 
 	if (adapter->link_speed != SPEED_0) {
-		ethtool_cmd_speed_set(ecmd, adapter->link_speed);
+		cmd->base.speed = adapter->link_speed;
 		if (adapter->link_duplex == FULL_DUPLEX)
-			ecmd->duplex = DUPLEX_FULL;
+			cmd->base.duplex = DUPLEX_FULL;
 		else
-			ecmd->duplex = DUPLEX_HALF;
+			cmd->base.duplex = DUPLEX_HALF;
 	} else {
-		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
-		ecmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 
-	ecmd->autoneg = AUTONEG_ENABLE;
+	cmd->base.autoneg = AUTONEG_ENABLE;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
+
 	return 0;
 }
 
-static int atl2_set_settings(struct net_device *netdev,
-	struct ethtool_cmd *ecmd)
+static int atl2_set_link_ksettings(struct net_device *netdev,
+				   const struct ethtool_link_ksettings *cmd)
 {
 	struct atl2_adapter *adapter = netdev_priv(netdev);
 	struct atl2_hw *hw = &adapter->hw;
+	u32 advertising;
+
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						cmd->link_modes.advertising);
 
 	while (test_and_set_bit(__ATL2_RESETTING, &adapter->flags))
 		msleep(1);
 
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
+	if (cmd->base.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) {
+		if ((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) {
+		} else if ((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) {
+		} else if ((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) {
+		} else if ((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) {
+		}  else if ((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 |
+		advertising = hw->autoneg_advertised |
 			ADVERTISED_TP | ADVERTISED_Autoneg;
 	} else {
 		clear_bit(__ATL2_RESETTING, &adapter->flags);
@@ -2082,8 +2086,6 @@ static int atl2_nway_reset(struct net_de
 }
 
 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,
@@ -2096,6 +2098,8 @@ static const struct ethtool_ops atl2_eth
 	.get_eeprom_len		= atl2_get_eeprom_len,
 	.get_eeprom		= atl2_get_eeprom,
 	.set_eeprom		= atl2_set_eeprom,
+	.get_link_ksettings	= atl2_get_link_ksettings,
+	.set_link_ksettings	= atl2_set_link_ksettings,
 };
 
 #define LBYTESWAP(a)  ((((a) & 0x00ff00ff) << 8) | \
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atlx/atl2.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atlx/atl2.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/atheros/atlx/atl2.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/atheros/atlx/atl2.h	2017-02-12 16:03:20.000000000 -0500
@@ -228,12 +228,9 @@ static void atl2_force_ps(struct atl2_hw
 #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;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/aurora/nb8800.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/aurora/nb8800.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/aurora/nb8800.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/aurora/nb8800.c	2017-02-12 16:03:20.000000000 -0500
@@ -975,8 +975,10 @@ static int nb8800_open(struct net_device
 	phydev = of_phy_connect(dev, priv->phy_node,
 				nb8800_link_reconfigure, 0,
 				priv->phy_mode);
-	if (!phydev)
+	if (!phydev) {
+		err = -ENODEV;
 		goto err_free_irq;
+	}
 
 	nb8800_pause_adv(dev);
 
@@ -1032,20 +1034,9 @@ static const struct net_device_ops nb880
 	.ndo_set_mac_address	= nb8800_set_mac_address,
 	.ndo_set_rx_mode	= nb8800_set_rx_mode,
 	.ndo_do_ioctl		= nb8800_ioctl,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-static int nb8800_nway_reset(struct net_device *dev)
-{
-	struct phy_device *phydev = dev->phydev;
-
-	if (!phydev)
-		return -ENODEV;
-
-	return genphy_restart_aneg(phydev);
-}
-
 static void nb8800_get_pauseparam(struct net_device *dev,
 				  struct ethtool_pauseparam *pp)
 {
@@ -1164,7 +1155,7 @@ static void nb8800_get_ethtool_stats(str
 }
 
 static const struct ethtool_ops nb8800_ethtool_ops = {
-	.nway_reset		= nb8800_nway_reset,
+	.nway_reset		= phy_ethtool_nway_reset,
 	.get_link		= ethtool_op_get_link,
 	.get_pauseparam		= nb8800_get_pauseparam,
 	.set_pauseparam		= nb8800_set_pauseparam,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/b44.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/b44.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/b44.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/b44.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 #include <linux/slab.h>
 #include <linux/phy.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -59,8 +59,8 @@
 #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_MIN_MTU			ETH_ZLEN
+#define B44_MAX_MTU			ETH_DATA_LEN
 
 #define B44_RX_RING_SIZE		512
 #define B44_DEF_RX_RING_PENDING		200
@@ -1064,9 +1064,6 @@ static int b44_change_mtu(struct net_dev
 {
 	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.
@@ -2377,6 +2374,8 @@ static int b44_init_one(struct ssb_devic
 	dev->netdev_ops = &b44_netdev_ops;
 	netif_napi_add(dev, &bp->napi, b44_poll, 64);
 	dev->watchdog_timeo = B44_TX_TIMEOUT;
+	dev->min_mtu = B44_MIN_MTU;
+	dev->max_mtu = B44_MAX_MTU;
 	dev->irq = sdev->irq;
 	dev->ethtool_ops = &b44_ethtool_ops;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bcm63xx_enet.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bcm63xx_enet.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bcm63xx_enet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bcm63xx_enet.c	2017-02-12 16:03:20.000000000 -0500
@@ -913,6 +913,8 @@ static int bcm_enet_open(struct net_devi
 		priv->old_link = 0;
 		priv->old_duplex = -1;
 		priv->old_pause = -1;
+	} else {
+		phydev = NULL;
 	}
 
 	/* mask all interrupts and request them */
@@ -1083,7 +1085,7 @@ static int bcm_enet_open(struct net_devi
 	enet_dmac_writel(priv, priv->dma_chan_int_mask,
 			 ENETDMAC_IRMASK, priv->tx_chan);
 
-	if (priv->has_phy)
+	if (phydev)
 		phy_start(phydev);
 	else
 		bcm_enet_adjust_link(dev);
@@ -1126,7 +1128,7 @@ out_freeirq:
 	free_irq(dev->irq, dev);
 
 out_phy_disconnect:
-	if (priv->has_phy)
+	if (phydev)
 		phy_disconnect(phydev);
 
 	return ret;
@@ -1434,11 +1436,8 @@ static int bcm_enet_nway_reset(struct ne
 	struct bcm_enet_priv *priv;
 
 	priv = netdev_priv(dev);
-	if (priv->has_phy) {
-		if (!dev->phydev)
-			return -ENODEV;
-		return genphy_restart_aneg(dev->phydev);
-	}
+	if (priv->has_phy)
+		return phy_ethtool_nway_reset(dev);
 
 	return -EOPNOTSUPP;
 }
@@ -1623,20 +1622,19 @@ static int bcm_enet_ioctl(struct net_dev
 }
 
 /*
- * calculate actual hardware mtu
+ * adjust mtu, can't be called while device is running
  */
-static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu)
+static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu)
 {
-	int actual_mtu;
+	struct bcm_enet_priv *priv = netdev_priv(dev);
+	int actual_mtu = new_mtu;
 
-	actual_mtu = mtu;
+	if (netif_running(dev))
+		return -EBUSY;
 
 	/* 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
@@ -1651,22 +1649,7 @@ static int compute_hw_mtu(struct bcm_ene
 	 */
 	priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
 				  priv->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;
 }
@@ -1756,7 +1739,7 @@ static int bcm_enet_probe(struct platfor
 	priv->enet_is_sw = false;
 	priv->dma_maxburst = BCMENET_DMA_MAXBURST;
 
-	ret = compute_hw_mtu(priv, dev->mtu);
+	ret = bcm_enet_change_mtu(dev, dev->mtu);
 	if (ret)
 		goto out;
 
@@ -1889,6 +1872,9 @@ static int bcm_enet_probe(struct platfor
 	netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);
 
 	dev->ethtool_ops = &bcm_enet_ethtool_ops;
+	/* MTU range: 46 - 2028 */
+	dev->min_mtu = ETH_ZLEN - ETH_HLEN;
+	dev->max_mtu = BCMENET_MAX_MTU - VLAN_ETH_HLEN;
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
 	ret = register_netdev(dev);
@@ -2743,7 +2729,7 @@ static int bcm_enetsw_probe(struct platf
 		priv->dma_chan_width = pd->dma_chan_width;
 	}
 
-	ret = compute_hw_mtu(priv, dev->mtu);
+	ret = bcm_enet_change_mtu(dev, dev->mtu);
 	if (ret)
 		goto out;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bcmsysport.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bcmsysport.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bcmsysport.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bcmsysport.c	2017-02-12 16:03:20.000000000 -0500
@@ -710,11 +710,8 @@ static unsigned int __bcm_sysport_tx_rec
 	unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
 	unsigned int pkts_compl = 0, bytes_compl = 0;
 	struct bcm_sysport_cb *cb;
-	struct netdev_queue *txq;
 	u32 hw_ind;
 
-	txq = netdev_get_tx_queue(ndev, ring->index);
-
 	/* Compute how many descriptors have been processed since last call */
 	hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index));
 	c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK;
@@ -745,9 +742,6 @@ static unsigned int __bcm_sysport_tx_rec
 
 	ring->c_index = c_index;
 
-	if (netif_tx_queue_stopped(txq) && pkts_compl)
-		netif_tx_wake_queue(txq);
-
 	netif_dbg(priv, tx_done, ndev,
 		  "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
 		  ring->index, ring->c_index, pkts_compl, bytes_compl);
@@ -759,16 +753,33 @@ static unsigned int __bcm_sysport_tx_rec
 static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
 					   struct bcm_sysport_tx_ring *ring)
 {
+	struct netdev_queue *txq;
 	unsigned int released;
 	unsigned long flags;
 
+	txq = netdev_get_tx_queue(priv->netdev, ring->index);
+
 	spin_lock_irqsave(&ring->lock, flags);
 	released = __bcm_sysport_tx_reclaim(priv, ring);
+	if (released)
+		netif_tx_wake_queue(txq);
+
 	spin_unlock_irqrestore(&ring->lock, flags);
 
 	return released;
 }
 
+/* Locked version of the per-ring TX reclaim, but does not wake the queue */
+static void bcm_sysport_tx_clean(struct bcm_sysport_priv *priv,
+				 struct bcm_sysport_tx_ring *ring)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ring->lock, flags);
+	__bcm_sysport_tx_reclaim(priv, ring);
+	spin_unlock_irqrestore(&ring->lock, flags);
+}
+
 static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
 {
 	struct bcm_sysport_tx_ring *ring =
@@ -1012,15 +1023,6 @@ static netdev_tx_t bcm_sysport_xmit(stru
 		goto out;
 	}
 
-	/* Insert TSB and checksum infos */
-	if (priv->tsb_en) {
-		skb = bcm_sysport_insert_tsb(skb, dev);
-		if (!skb) {
-			ret = NETDEV_TX_OK;
-			goto out;
-		}
-	}
-
 	/* The Ethernet switch we are interfaced with needs packets to be at
 	 * least 64 bytes (including FCS) otherwise they will be discarded when
 	 * they enter the switch port logic. When Broadcom tags are enabled, we
@@ -1028,13 +1030,21 @@ static netdev_tx_t bcm_sysport_xmit(stru
 	 * (including FCS and tag) because the length verification is done after
 	 * the Broadcom tag is stripped off the ingress packet.
 	 */
-	if (skb_padto(skb, ETH_ZLEN + ENET_BRCM_TAG_LEN)) {
+	if (skb_put_padto(skb, ETH_ZLEN + ENET_BRCM_TAG_LEN)) {
 		ret = NETDEV_TX_OK;
 		goto out;
 	}
 
-	skb_len = skb->len < ETH_ZLEN + ENET_BRCM_TAG_LEN ?
-			ETH_ZLEN + ENET_BRCM_TAG_LEN : skb->len;
+	/* Insert TSB and checksum infos */
+	if (priv->tsb_en) {
+		skb = bcm_sysport_insert_tsb(skb, dev);
+		if (!skb) {
+			ret = NETDEV_TX_OK;
+			goto out;
+		}
+	}
+
+	skb_len = skb->len;
 
 	mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE);
 	if (dma_mapping_error(kdev, mapping)) {
@@ -1253,7 +1263,7 @@ static void bcm_sysport_fini_tx_ring(str
 	napi_disable(&ring->napi);
 	netif_napi_del(&ring->napi);
 
-	bcm_sysport_tx_reclaim(priv, ring);
+	bcm_sysport_tx_clean(priv, ring);
 
 	kfree(ring->cbs);
 	ring->cbs = NULL;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac-bcma.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac-bcma.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac-bcma.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac-bcma.c	2017-02-12 16:03:20.000000000 -0500
@@ -80,6 +80,24 @@ static void bcma_bgmac_cmn_maskset32(str
 	bcma_maskset32(bgmac->bcma.cmn, offset, mask, set);
 }
 
+static int bcma_phy_connect(struct bgmac *bgmac)
+{
+	struct phy_device *phy_dev;
+	char bus_id[MII_BUS_ID_SIZE + 3];
+
+	/* Connect to the PHY */
+	snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
+		 bgmac->phyaddr);
+	phy_dev = phy_connect(bgmac->net_dev, bus_id, bgmac_adjust_link,
+			      PHY_INTERFACE_MODE_MII);
+	if (IS_ERR(phy_dev)) {
+		dev_err(bgmac->dev, "PHY connection failed\n");
+		return PTR_ERR(phy_dev);
+	}
+
+	return 0;
+}
+
 static const struct bcma_device_id bgmac_bcma_tbl[] = {
 	BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT,
 		  BCMA_ANY_REV, BCMA_ANY_CLASS),
@@ -275,6 +293,10 @@ static int bgmac_probe(struct bcma_devic
 	bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
 	bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
 	bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
+	if (bgmac->mii_bus)
+		bgmac->phy_connect = bcma_phy_connect;
+	else
+		bgmac->phy_connect = bgmac_phy_connect_direct;
 
 	err = bgmac_enet_probe(bgmac);
 	if (err)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -1085,6 +1085,9 @@ static void bgmac_enable(struct bgmac *b
 /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
 static void bgmac_chip_init(struct bgmac *bgmac)
 {
+	/* Clear any erroneously pending interrupts */
+	bgmac_write(bgmac, BGMAC_INT_STATUS, ~0);
+
 	/* 1 interrupt per received frame */
 	bgmac_write(bgmac, BGMAC_INT_RECV_LAZY, 1 << BGMAC_IRL_FC_SHIFT);
 
@@ -1391,7 +1394,7 @@ static const struct ethtool_ops bgmac_et
  * MII
  **************************************************/
 
-static void bgmac_adjust_link(struct net_device *net_dev)
+void bgmac_adjust_link(struct net_device *net_dev)
 {
 	struct bgmac *bgmac = netdev_priv(net_dev);
 	struct phy_device *phy_dev = net_dev->phydev;
@@ -1414,8 +1417,9 @@ static void bgmac_adjust_link(struct net
 		phy_print_status(phy_dev);
 	}
 }
+EXPORT_SYMBOL_GPL(bgmac_adjust_link);
 
-static int bgmac_phy_connect_direct(struct bgmac *bgmac)
+int bgmac_phy_connect_direct(struct bgmac *bgmac)
 {
 	struct fixed_phy_status fphy_status = {
 		.link = 1,
@@ -1440,24 +1444,7 @@ static int bgmac_phy_connect_direct(stru
 
 	return err;
 }
-
-static int bgmac_phy_connect(struct bgmac *bgmac)
-{
-	struct phy_device *phy_dev;
-	char bus_id[MII_BUS_ID_SIZE + 3];
-
-	/* Connect to the PHY */
-	snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, bgmac->mii_bus->id,
-		 bgmac->phyaddr);
-	phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
-			      PHY_INTERFACE_MODE_MII);
-	if (IS_ERR(phy_dev)) {
-		dev_err(bgmac->dev, "PHY connection failed\n");
-		return PTR_ERR(phy_dev);
-	}
-
-	return 0;
-}
+EXPORT_SYMBOL_GPL(bgmac_phy_connect_direct);
 
 int bgmac_enet_probe(struct bgmac *info)
 {
@@ -1510,10 +1497,7 @@ int bgmac_enet_probe(struct bgmac *info)
 
 	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);
 
-	if (!bgmac->mii_bus)
-		err = bgmac_phy_connect_direct(bgmac);
-	else
-		err = bgmac_phy_connect(bgmac);
+	err = bgmac_phy_connect(bgmac);
 	if (err) {
 		dev_err(bgmac->dev, "Cannot connect to phy\n");
 		goto err_dma_free;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac.h	2017-02-12 16:03:20.000000000 -0500
@@ -463,6 +463,7 @@ struct bgmac {
 		struct {
 			void *base;
 			void *idm_base;
+			void *nicpm_base;
 		} plat;
 		struct {
 			struct bcma_device *core;
@@ -513,10 +514,13 @@ struct bgmac {
 	u32 (*get_bus_clock)(struct bgmac *bgmac);
 	void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask,
 			      u32 set);
+	int (*phy_connect)(struct bgmac *bgmac);
 };
 
 int bgmac_enet_probe(struct bgmac *info);
 void bgmac_enet_remove(struct bgmac *bgmac);
+void bgmac_adjust_link(struct net_device *net_dev);
+int bgmac_phy_connect_direct(struct bgmac *bgmac);
 
 struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
 void bcma_mdio_mii_unregister(struct mii_bus *mii_bus);
@@ -583,4 +587,9 @@ static inline void bgmac_set(struct bgma
 {
 	bgmac_maskset(bgmac, offset, ~0, set);
 }
+
+static inline int bgmac_phy_connect(struct bgmac *bgmac)
+{
+	return bgmac->phy_connect(bgmac);
+}
 #endif /* _BGMAC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac-platform.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac-platform.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bgmac-platform.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bgmac-platform.c	2017-02-12 16:03:20.000000000 -0500
@@ -14,11 +14,21 @@
 #define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt
 
 #include <linux/bcma/bcma.h>
+#include <linux/brcmphy.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
+#include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include "bgmac.h"
 
+#define NICPM_IOMUX_CTRL		0x00000008
+
+#define NICPM_IOMUX_CTRL_INIT_VAL	0x3196e000
+#define NICPM_IOMUX_CTRL_SPD_SHIFT	10
+#define NICPM_IOMUX_CTRL_SPD_10M	0
+#define NICPM_IOMUX_CTRL_SPD_100M	1
+#define NICPM_IOMUX_CTRL_SPD_1000M	2
+
 static u32 platform_bgmac_read(struct bgmac *bgmac, u16 offset)
 {
 	return readl(bgmac->plat.base + offset);
@@ -86,6 +96,54 @@ static void platform_bgmac_cmn_maskset32
 	WARN_ON(1);
 }
 
+static void bgmac_nicpm_speed_set(struct net_device *net_dev)
+{
+	struct bgmac *bgmac = netdev_priv(net_dev);
+	u32 val;
+
+	if (!bgmac->plat.nicpm_base)
+		return;
+
+	val = NICPM_IOMUX_CTRL_INIT_VAL;
+	switch (bgmac->net_dev->phydev->speed) {
+	default:
+		netdev_err(net_dev, "Unsupported speed. Defaulting to 1000Mb\n");
+	case SPEED_1000:
+		val |= NICPM_IOMUX_CTRL_SPD_1000M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+		break;
+	case SPEED_100:
+		val |= NICPM_IOMUX_CTRL_SPD_100M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+		break;
+	case SPEED_10:
+		val |= NICPM_IOMUX_CTRL_SPD_10M << NICPM_IOMUX_CTRL_SPD_SHIFT;
+		break;
+	}
+
+	writel(val, bgmac->plat.nicpm_base + NICPM_IOMUX_CTRL);
+
+	bgmac_adjust_link(bgmac->net_dev);
+}
+
+static int platform_phy_connect(struct bgmac *bgmac)
+{
+	struct phy_device *phy_dev;
+
+	if (bgmac->plat.nicpm_base)
+		phy_dev = of_phy_get_and_connect(bgmac->net_dev,
+						 bgmac->dev->of_node,
+						 bgmac_nicpm_speed_set);
+	else
+		phy_dev = of_phy_get_and_connect(bgmac->net_dev,
+						 bgmac->dev->of_node,
+						 bgmac_adjust_link);
+	if (!phy_dev) {
+		dev_err(bgmac->dev, "PHY connection failed\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
 static int bgmac_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -102,7 +160,6 @@ static int bgmac_probe(struct platform_d
 	/* Set the features of the 4707 family */
 	bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 	bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
-	bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
 	bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
 	bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
 	bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
@@ -142,6 +199,14 @@ static int bgmac_probe(struct platform_d
 	if (IS_ERR(bgmac->plat.idm_base))
 		return PTR_ERR(bgmac->plat.idm_base);
 
+	regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nicpm_base");
+	if (regs) {
+		bgmac->plat.nicpm_base = devm_ioremap_resource(&pdev->dev,
+							       regs);
+		if (IS_ERR(bgmac->plat.nicpm_base))
+			return PTR_ERR(bgmac->plat.nicpm_base);
+	}
+
 	bgmac->read = platform_bgmac_read;
 	bgmac->write = platform_bgmac_write;
 	bgmac->idm_read = platform_bgmac_idm_read;
@@ -151,6 +216,12 @@ static int bgmac_probe(struct platform_d
 	bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
 	bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
 	bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
+	if (of_parse_phandle(np, "phy-handle", 0)) {
+		bgmac->phy_connect = platform_phy_connect;
+	} else {
+		bgmac->phy_connect = bgmac_phy_connect_direct;
+		bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
+	}
 
 	return bgmac_enet_probe(bgmac);
 }
@@ -167,6 +238,7 @@ static int bgmac_remove(struct platform_
 static const struct of_device_id bgmac_of_enet_match[] = {
 	{.compatible = "brcm,amac",},
 	{.compatible = "brcm,nsp-amac",},
+	{.compatible = "brcm,ns2-amac",},
 	{},
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2.c	2016-12-11 17:49:07.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2.c	2017-02-12 17:37:30.000000000 -0500
@@ -250,13 +250,10 @@ static inline u32 bnx2_tx_avail(struct b
 {
 	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;
+	diff = READ_ONCE(txr->tx_prod) - READ_ONCE(txr->tx_cons);
 	if (unlikely(diff >= BNX2_TX_DESC_CNT)) {
 		diff &= 0xffff;
 		if (diff == BNX2_TX_DESC_CNT)
@@ -2300,7 +2297,7 @@ bnx2_init_5706s_phy(struct bnx2 *bp, int
 	if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
 		BNX2_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
 
-	if (bp->dev->mtu > 1500) {
+	if (bp->dev->mtu > ETH_DATA_LEN) {
 		u32 val;
 
 		/* Set extended packet length bit */
@@ -2354,7 +2351,7 @@ bnx2_init_copper_phy(struct bnx2 *bp, in
 		bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
 	}
 
-	if (bp->dev->mtu > 1500) {
+	if (bp->dev->mtu > ETH_DATA_LEN) {
 		/* Set extended packet length bit */
 		bnx2_write_phy(bp, 0x18, 0x7);
 		bnx2_read_phy(bp, 0x18, &val);
@@ -2835,10 +2832,8 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bn
 {
 	u16 cons;
 
-	/* Tell compiler that status block fields can change. */
-	barrier();
-	cons = *bnapi->hw_tx_cons_ptr;
-	barrier();
+	cons = READ_ONCE(*bnapi->hw_tx_cons_ptr);
+
 	if (unlikely((cons & BNX2_MAX_TX_DESC_CNT) == BNX2_MAX_TX_DESC_CNT))
 		cons++;
 	return cons;
@@ -3137,10 +3132,8 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bn
 {
 	u16 cons;
 
-	/* Tell compiler that status block fields can change. */
-	barrier();
-	cons = *bnapi->hw_rx_cons_ptr;
-	barrier();
+	cons = READ_ONCE(*bnapi->hw_rx_cons_ptr);
+
 	if (unlikely((cons & BNX2_MAX_RX_DESC_CNT) == BNX2_MAX_RX_DESC_CNT))
 		cons++;
 	return cons;
@@ -5003,12 +4996,12 @@ bnx2_init_chip(struct bnx2 *bp)
 	/* 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))
+	if (val > (MAX_ETHERNET_PACKET_SIZE + ETH_HLEN + 4))
 		val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
 	BNX2_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
 
-	if (mtu < 1500)
-		mtu = 1500;
+	if (mtu < ETH_DATA_LEN)
+		mtu = ETH_DATA_LEN;
 
 	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));
@@ -6900,12 +6893,14 @@ bnx2_get_stats64(struct net_device *dev,
 /* All ethtool functions called with rtnl_lock */
 
 static int
-bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+bnx2_get_link_ksettings(struct net_device *dev,
+			struct ethtool_link_ksettings *cmd)
 {
 	struct bnx2 *bp = netdev_priv(dev);
 	int support_serdes = 0, support_copper = 0;
+	u32 supported, advertising;
 
-	cmd->supported = SUPPORTED_Autoneg;
+	supported = SUPPORTED_Autoneg;
 	if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP) {
 		support_serdes = 1;
 		support_copper = 1;
@@ -6915,56 +6910,59 @@ bnx2_get_settings(struct net_device *dev
 		support_copper = 1;
 
 	if (support_serdes) {
-		cmd->supported |= SUPPORTED_1000baseT_Full |
+		supported |= SUPPORTED_1000baseT_Full |
 			SUPPORTED_FIBRE;
 		if (bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE)
-			cmd->supported |= SUPPORTED_2500baseX_Full;
-
+			supported |= SUPPORTED_2500baseX_Full;
 	}
 	if (support_copper) {
-		cmd->supported |= SUPPORTED_10baseT_Half |
+		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;
+	cmd->base.port = bp->phy_port;
+	advertising = bp->advertising;
 
 	if (bp->autoneg & AUTONEG_SPEED) {
-		cmd->autoneg = AUTONEG_ENABLE;
+		cmd->base.autoneg = AUTONEG_ENABLE;
 	} else {
-		cmd->autoneg = AUTONEG_DISABLE;
+		cmd->base.autoneg = AUTONEG_DISABLE;
 	}
 
 	if (netif_carrier_ok(dev)) {
-		ethtool_cmd_speed_set(cmd, bp->line_speed);
-		cmd->duplex = bp->duplex;
+		cmd->base.speed = bp->line_speed;
+		cmd->base.duplex = bp->duplex;
 		if (!(bp->phy_flags & BNX2_PHY_FLAG_SERDES)) {
 			if (bp->phy_flags & BNX2_PHY_FLAG_MDIX)
-				cmd->eth_tp_mdix = ETH_TP_MDI_X;
+				cmd->base.eth_tp_mdix = ETH_TP_MDI_X;
 			else
-				cmd->eth_tp_mdix = ETH_TP_MDI;
+				cmd->base.eth_tp_mdix = ETH_TP_MDI;
 		}
 	}
 	else {
-		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
-		cmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 	spin_unlock_bh(&bp->phy_lock);
 
-	cmd->transceiver = XCVR_INTERNAL;
-	cmd->phy_address = bp->phy_addr;
+	cmd->base.phy_address = bp->phy_addr;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return 0;
 }
 
 static int
-bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+bnx2_set_link_ksettings(struct net_device *dev,
+			const struct ethtool_link_ksettings *cmd)
 {
 	struct bnx2 *bp = netdev_priv(dev);
 	u8 autoneg = bp->autoneg;
@@ -6975,24 +6973,26 @@ bnx2_set_settings(struct net_device *dev
 
 	spin_lock_bh(&bp->phy_lock);
 
-	if (cmd->port != PORT_TP && cmd->port != PORT_FIBRE)
+	if (cmd->base.port != PORT_TP && cmd->base.port != PORT_FIBRE)
 		goto err_out_unlock;
 
-	if (cmd->port != bp->phy_port &&
+	if (cmd->base.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)
+	if (!netif_running(dev) && cmd->base.port != bp->phy_port)
 		goto err_out_unlock;
 
-	if (cmd->autoneg == AUTONEG_ENABLE) {
+	if (cmd->base.autoneg == AUTONEG_ENABLE) {
 		autoneg |= AUTONEG_SPEED;
 
-		advertising = cmd->advertising;
-		if (cmd->port == PORT_TP) {
+		ethtool_convert_link_mode_to_legacy_u32(
+			&advertising, cmd->link_modes.advertising);
+
+		if (cmd->base.port == PORT_TP) {
 			advertising &= ETHTOOL_ALL_COPPER_SPEED;
 			if (!advertising)
 				advertising = ETHTOOL_ALL_COPPER_SPEED;
@@ -7004,11 +7004,12 @@ bnx2_set_settings(struct net_device *dev
 		advertising |= ADVERTISED_Autoneg;
 	}
 	else {
-		u32 speed = ethtool_cmd_speed(cmd);
-		if (cmd->port == PORT_FIBRE) {
+		u32 speed = cmd->base.speed;
+
+		if (cmd->base.port == PORT_FIBRE) {
 			if ((speed != SPEED_1000 &&
 			     speed != SPEED_2500) ||
-			    (cmd->duplex != DUPLEX_FULL))
+			    (cmd->base.duplex != DUPLEX_FULL))
 				goto err_out_unlock;
 
 			if (speed == SPEED_2500 &&
@@ -7019,7 +7020,7 @@ bnx2_set_settings(struct net_device *dev
 
 		autoneg &= ~AUTONEG_SPEED;
 		req_line_speed = speed;
-		req_duplex = cmd->duplex;
+		req_duplex = cmd->base.duplex;
 		advertising = 0;
 	}
 
@@ -7033,7 +7034,7 @@ bnx2_set_settings(struct net_device *dev
 	 * brought up.
 	 */
 	if (netif_running(dev))
-		err = bnx2_setup_phy(bp, cmd->port);
+		err = bnx2_setup_phy(bp, cmd->base.port);
 
 err_out_unlock:
 	spin_unlock_bh(&bp->phy_lock);
@@ -7818,8 +7819,6 @@ static int bnx2_set_channels(struct net_
 }
 
 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,
@@ -7843,6 +7842,8 @@ static const struct ethtool_ops bnx2_eth
 	.get_sset_count		= bnx2_get_sset_count,
 	.get_channels		= bnx2_get_channels,
 	.set_channels		= bnx2_set_channels,
+	.get_link_ksettings	= bnx2_get_link_ksettings,
+	.set_link_ksettings	= bnx2_set_link_ksettings,
 };
 
 /* Called with rtnl_lock */
@@ -7919,10 +7920,6 @@ bnx2_change_mtu(struct net_device *dev,
 {
 	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,
 				     false);
@@ -8615,6 +8612,8 @@ bnx2_init_one(struct pci_dev *pdev, cons
 	dev->hw_features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
 	dev->features |= dev->hw_features;
 	dev->priv_flags |= IFF_UNICAST_FLT;
+	dev->min_mtu = MIN_ETHERNET_PACKET_SIZE;
+	dev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE;
 
 	if (!(bp->flags & BNX2_FLAG_CAN_KEEP_VLAN))
 		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2.h	2017-02-12 16:03:20.000000000 -0500
@@ -6530,9 +6530,9 @@ struct l2_fhdr {
 #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 MIN_ETHERNET_PACKET_SIZE	(ETH_ZLEN - ETH_HLEN)
+#define MAX_ETHERNET_PACKET_SIZE	ETH_DATA_LEN
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE	9000
 
 #define BNX2_RX_COPY_THRESH		128
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c	2016-12-11 17:49:18.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c	2017-02-12 17:37:43.000000000 -0500
@@ -724,7 +724,7 @@ static void bnx2x_gro_ipv6_csum(struct b
 static void bnx2x_gro_csum(struct bnx2x *bp, struct sk_buff *skb,
 			    void (*gro_func)(struct bnx2x*, struct sk_buff*))
 {
-	skb_set_network_header(skb, 0);
+	skb_reset_network_header(skb);
 	gro_func(bp, skb);
 	tcp_gro_complete(skb);
 }
@@ -2023,7 +2023,7 @@ static void bnx2x_set_rx_buf_size(struct
 			mtu = bp->dev->mtu;
 		fp->rx_buf_size = BNX2X_FW_RX_ALIGN_START +
 				  IP_HEADER_ALIGNMENT_PADDING +
-				  ETH_OVREHEAD +
+				  ETH_OVERHEAD +
 				  mtu +
 				  BNX2X_FW_RX_ALIGN_END;
 		/* Note : rx_buf_size doesn't take into account NET_SKB_PAD */
@@ -3247,13 +3247,14 @@ static int bnx2x_poll(struct napi_struct
 			rmb();
 
 			if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
-				napi_complete(napi);
-				/* Re-enable interrupts */
-				DP(NETIF_MSG_RX_STATUS,
-				   "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);
+				if (napi_complete_done(napi, rx_work_done)) {
+					/* Re-enable interrupts */
+					DP(NETIF_MSG_RX_STATUS,
+					   "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);
+				}
 			} else {
 				rx_work_done = budget;
 			}
@@ -4854,12 +4855,6 @@ int bnx2x_change_mtu(struct net_device *
 		return -EAGAIN;
 	}
 
-	if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
-	    ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) {
-		BNX2X_ERR("Can't support requested MTU size\n");
-		return -EINVAL;
-	}
-
 	/* This does not race with packet allocation
 	 * because the actual alloc size is
 	 * only updated as part of load
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h	2017-02-12 16:03:20.000000000 -0500
@@ -1396,9 +1396,9 @@ struct bnx2x {
 	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_OVERHEAD		(ETH_HLEN + 8 + 8)
+#define ETH_MIN_PACKET_SIZE		(ETH_ZLEN - ETH_HLEN)
+#define ETH_MAX_PACKET_SIZE		ETH_DATA_LEN
 #define ETH_MAX_JUMBO_PACKET_SIZE	9600
 /* TCP with Timestamp Option (32) + IPv6 (40) */
 #define ETH_MAX_TPA_HEADER_SIZE		72
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,12 +34,6 @@ typedef int (*read_sfp_module_eeprom_fun
 					     u8 dev_addr, u16 addr, u8 byte_cnt,
 					     u8 *o_buf, u8);
 /********************************************************/
-#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 WC_LANE_MAX			4
 #define I2C_SWITCH_WIDTH		2
@@ -1917,7 +1911,7 @@ static int bnx2x_emac_enable(struct link
 	/* 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)));
+		 (ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD)));
 
 	/* Strip CRC */
 	REG_WR(bp, NIG_REG_NIG_INGRESS_EMAC0_NO_CRC + port*4, 0x1);
@@ -2314,19 +2308,19 @@ static int bnx2x_bmac1_enable(struct lin
 	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[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
 	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[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
 	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[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
 
@@ -2384,18 +2378,18 @@ static int bnx2x_bmac2_enable(struct lin
 	udelay(30);
 
 	/* Set RX MTU */
-	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
+	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
 	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[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD;
 	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[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVERHEAD - 2;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2);
 	udelay(30);
@@ -2516,7 +2510,7 @@ static int bnx2x_pbf_update(struct link_
 
 	} else {
 		u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
-			      ETH_OVREHEAD)/16;
+			      ETH_OVERHEAD)/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);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c	2016-12-11 17:49:18.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c	2017-02-12 17:37:43.000000000 -0500
@@ -12074,8 +12074,7 @@ static int bnx2x_get_hwinfo(struct bnx2x
 					   mtu_size, mtu);
 
 					/* if valid: update device mtu */
-					if (((mtu_size + ETH_HLEN) >=
-					     ETH_MIN_PACKET_SIZE) &&
+					if ((mtu_size >= ETH_MIN_PACKET_SIZE) &&
 					    (mtu_size <=
 					     ETH_MAX_JUMBO_PACKET_SIZE))
 						bp->dev->mtu = mtu_size;
@@ -13309,6 +13308,10 @@ static int bnx2x_init_dev(struct bnx2x *
 	dev->dcbnl_ops = &bnx2x_dcbnl_ops;
 #endif
 
+	/* MTU range, 46 - 9600 */
+	dev->min_mtu = ETH_MIN_PACKET_SIZE;
+	dev->max_mtu = ETH_MAX_JUMBO_PACKET_SIZE;
+
 	/* get_port_hwinfo() will set prtad and mmds properly */
 	bp->mdio.prtad = MDIO_PRTAD_NONE;
 	bp->mdio.mmds = 0;
@@ -15156,7 +15159,7 @@ void bnx2x_set_rx_ts(struct bnx2x *bp, s
 }
 
 /* Read the PHC */
-static cycle_t bnx2x_cyclecounter_read(const struct cyclecounter *cc)
+static u64 bnx2x_cyclecounter_read(const struct cyclecounter *cc)
 {
 	struct bnx2x *bp = container_of(cc, struct bnx2x, cyclecounter);
 	int port = BP_PORT(bp);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c	2017-02-12 16:03:20.000000000 -0500
@@ -585,7 +585,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, str
 		mcast.mcast_list_len = mc_num;
 		rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_SET);
 		if (rc)
-			BNX2X_ERR("Faled to set multicasts\n");
+			BNX2X_ERR("Failed to set multicasts\n");
 	} else {
 		/* clear existing mcasts */
 		rc = bnx2x_config_mcast(bp, &mcast, BNX2X_MCAST_CMD_DEL);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.c	2017-02-12 16:03:20.000000000 -0500
@@ -52,8 +52,10 @@
 
 #include "bnxt_hsi.h"
 #include "bnxt.h"
+#include "bnxt_ulp.h"
 #include "bnxt_sriov.h"
 #include "bnxt_ethtool.h"
+#include "bnxt_dcb.h"
 
 #define BNXT_TX_TIMEOUT		(5 * HZ)
 
@@ -186,11 +188,11 @@ static const u16 bnxt_vf_req_snif[] = {
 };
 
 static const u16 bnxt_async_events_arr[] = {
-	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
-	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
-	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
-	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
-	HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
+	ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE,
+	ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD,
+	ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED,
+	ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE,
+	ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE,
 };
 
 static bool bnxt_vf_pciid(enum board_idx idx)
@@ -1097,7 +1099,7 @@ static struct sk_buff *bnxt_gro_func_573
 {
 #ifdef CONFIG_INET
 	struct tcphdr *th;
-	int len, nw_off, tcp_opt_len;
+	int len, nw_off, tcp_opt_len = 0;
 
 	if (tcp_ts)
 		tcp_opt_len = 12;
@@ -1476,8 +1478,8 @@ next_rx_no_prod:
 }
 
 #define BNXT_GET_EVENT_PORT(data)	\
-	((data) &				\
-	 HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
+	((data) &			\
+	 ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK)
 
 static int bnxt_async_event_process(struct bnxt *bp,
 				    struct hwrm_async_event_cmpl *cmpl)
@@ -1486,7 +1488,7 @@ static int bnxt_async_event_process(stru
 
 	/* TODO CHIMP_FW: Define event id's for link change, error etc */
 	switch (event_id) {
-	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: {
+	case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE: {
 		u32 data1 = le32_to_cpu(cmpl->event_data1);
 		struct bnxt_link_info *link_info = &bp->link_info;
 
@@ -1499,15 +1501,16 @@ static int bnxt_async_event_process(stru
 			netdev_warn(bp->dev, "Link speed %d no longer supported\n",
 				    speed);
 		}
+		set_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT, &bp->sp_event);
 		/* fall thru */
 	}
-	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
+	case ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
 		set_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event);
 		break;
-	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD:
+	case ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD:
 		set_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event);
 		break;
-	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: {
+	case ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED: {
 		u32 data1 = le32_to_cpu(cmpl->event_data1);
 		u16 port_id = BNXT_GET_EVENT_PORT(data1);
 
@@ -1520,18 +1523,17 @@ static int bnxt_async_event_process(stru
 		set_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event);
 		break;
 	}
-	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
+	case ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
 		if (BNXT_PF(bp))
 			goto async_event_process_exit;
 		set_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event);
 		break;
 	default:
-		netdev_err(bp->dev, "unhandled ASYNC event (id 0x%x)\n",
-			   event_id);
 		goto async_event_process_exit;
 	}
 	schedule_work(&bp->sp_task);
 async_event_process_exit:
+	bnxt_ulp_async_events(bp, cmpl);
 	return 0;
 }
 
@@ -3115,27 +3117,46 @@ int hwrm_send_message_silent(struct bnxt
 	return rc;
 }
 
-static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
+int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
+				     int bmap_size)
 {
 	struct hwrm_func_drv_rgtr_input req = {0};
-	int i;
 	DECLARE_BITMAP(async_events_bmap, 256);
 	u32 *events = (u32 *)async_events_bmap;
+	int i;
 
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR, -1, -1);
 
 	req.enables =
-		cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
-			    FUNC_DRV_RGTR_REQ_ENABLES_VER |
-			    FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
+		cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
 
 	memset(async_events_bmap, 0, sizeof(async_events_bmap));
 	for (i = 0; i < ARRAY_SIZE(bnxt_async_events_arr); i++)
 		__set_bit(bnxt_async_events_arr[i], async_events_bmap);
 
+	if (bmap && bmap_size) {
+		for (i = 0; i < bmap_size; i++) {
+			if (test_bit(i, bmap))
+				__set_bit(i, async_events_bmap);
+		}
+	}
+
 	for (i = 0; i < 8; i++)
 		req.async_event_fwd[i] |= cpu_to_le32(events[i]);
 
+	return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
+static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
+{
+	struct hwrm_func_drv_rgtr_input req = {0};
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_DRV_RGTR, -1, -1);
+
+	req.enables =
+		cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE |
+			    FUNC_DRV_RGTR_REQ_ENABLES_VER);
+
 	req.os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
 	req.ver_maj = DRV_VER_MAJ;
 	req.ver_min = DRV_VER_MIN;
@@ -3144,6 +3165,7 @@ static int bnxt_hwrm_func_drv_rgtr(struc
 	if (BNXT_PF(bp)) {
 		DECLARE_BITMAP(vf_req_snif_bmap, 256);
 		u32 *data = (u32 *)vf_req_snif_bmap;
+		int i;
 
 		memset(vf_req_snif_bmap, 0, sizeof(vf_req_snif_bmap));
 		for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++)
@@ -3433,13 +3455,7 @@ static int bnxt_hwrm_vnic_set_rss(struct
 
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VNIC_RSS_CFG, -1, -1);
 	if (set_rss) {
-		vnic->hash_type = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 |
-				  VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
-				  VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
-				  VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
-
-		req.hash_type = cpu_to_le32(vnic->hash_type);
-
+		req.hash_type = cpu_to_le32(bp->rss_hash_cfg);
 		if (vnic->flags & BNXT_VNIC_RSS_FLAG) {
 			if (BNXT_CHIP_TYPE_NITRO_A0(bp))
 				max_rings = bp->rx_nr_rings - 1;
@@ -3531,7 +3547,7 @@ static int bnxt_hwrm_vnic_ctx_alloc(stru
 	return rc;
 }
 
-static int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
+int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id)
 {
 	unsigned int ring = 0, grp_idx;
 	struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
@@ -3579,6 +3595,9 @@ static int bnxt_hwrm_vnic_cfg(struct bnx
 #endif
 	if ((bp->flags & BNXT_FLAG_STRIP_VLAN) || def_vlan)
 		req.flags |= cpu_to_le32(VNIC_CFG_REQ_FLAGS_VLAN_STRIP_MODE);
+	if (!vnic_id && bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP))
+		req.flags |=
+			cpu_to_le32(VNIC_CFG_REQ_FLAGS_ROCE_DUAL_VNIC_MODE);
 
 	return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 }
@@ -4156,7 +4175,7 @@ func_qcfg_exit:
 	return rc;
 }
 
-int bnxt_hwrm_func_qcaps(struct bnxt *bp)
+static int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 {
 	int rc = 0;
 	struct hwrm_func_qcaps_input req = {0};
@@ -4170,6 +4189,11 @@ int bnxt_hwrm_func_qcaps(struct bnxt *bp
 	if (rc)
 		goto hwrm_func_qcaps_exit;
 
+	if (resp->flags & cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_ROCE_V1_SUPPORTED))
+		bp->flags |= BNXT_FLAG_ROCEV1_CAP;
+	if (resp->flags & cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED))
+		bp->flags |= BNXT_FLAG_ROCEV2_CAP;
+
 	bp->tx_push_thresh = 0;
 	if (resp->flags &
 	    cpu_to_le32(FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED))
@@ -4266,12 +4290,16 @@ static int bnxt_hwrm_queue_qportcfg(stru
 		goto qportcfg_exit;
 	}
 	bp->max_tc = resp->max_configurable_queues;
+	bp->max_lltc = resp->max_configurable_lossless_queues;
 	if (bp->max_tc > BNXT_MAX_QUEUE)
 		bp->max_tc = BNXT_MAX_QUEUE;
 
 	if (resp->queue_cfg_info & QUEUE_QPORTCFG_RESP_QUEUE_CFG_INFO_ASYM_CFG)
 		bp->max_tc = 1;
 
+	if (bp->max_lltc > bp->max_tc)
+		bp->max_lltc = bp->max_tc;
+
 	qptr = &resp->queue_id0;
 	for (i = 0; i < bp->max_tc; i++) {
 		bp->q_info[i].queue_id = *qptr++;
@@ -4743,16 +4771,134 @@ static int bnxt_trim_rings(struct bnxt *
 	return 0;
 }
 
-static int bnxt_setup_msix(struct bnxt *bp)
+static void bnxt_setup_msix(struct bnxt *bp)
 {
-	struct msix_entry *msix_ent;
+	const int len = sizeof(bp->irq_tbl[0].name);
 	struct net_device *dev = bp->dev;
-	int i, total_vecs, rc = 0, min = 1;
+	int tcs, i;
+
+	tcs = netdev_get_num_tc(dev);
+	if (tcs > 1) {
+		bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs;
+		if (bp->tx_nr_rings_per_tc == 0) {
+			netdev_reset_tc(dev);
+			bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
+		} else {
+			int i, off, count;
+
+			bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
+			for (i = 0; i < tcs; i++) {
+				count = bp->tx_nr_rings_per_tc;
+				off = i * count;
+				netdev_set_tc_queue(dev, i, count, off);
+			}
+		}
+	}
+
+	for (i = 0; i < bp->cp_nr_rings; i++) {
+		char *attr;
+
+		if (bp->flags & BNXT_FLAG_SHARED_RINGS)
+			attr = "TxRx";
+		else if (i < bp->rx_nr_rings)
+			attr = "rx";
+		else
+			attr = "tx";
+
+		snprintf(bp->irq_tbl[i].name, len, "%s-%s-%d", dev->name, attr,
+			 i);
+		bp->irq_tbl[i].handler = bnxt_msix;
+	}
+}
+
+static void bnxt_setup_inta(struct bnxt *bp)
+{
 	const int len = sizeof(bp->irq_tbl[0].name);
 
-	bp->flags &= ~BNXT_FLAG_USING_MSIX;
-	total_vecs = bp->cp_nr_rings;
+	if (netdev_get_num_tc(bp->dev))
+		netdev_reset_tc(bp->dev);
 
+	snprintf(bp->irq_tbl[0].name, len, "%s-%s-%d", bp->dev->name, "TxRx",
+		 0);
+	bp->irq_tbl[0].handler = bnxt_inta;
+}
+
+static int bnxt_setup_int_mode(struct bnxt *bp)
+{
+	int rc;
+
+	if (bp->flags & BNXT_FLAG_USING_MSIX)
+		bnxt_setup_msix(bp);
+	else
+		bnxt_setup_inta(bp);
+
+	rc = bnxt_set_real_num_queues(bp);
+	return rc;
+}
+
+unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+	if (BNXT_VF(bp))
+		return bp->vf.max_stat_ctxs;
+#endif
+	return bp->pf.max_stat_ctxs;
+}
+
+void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+	if (BNXT_VF(bp))
+		bp->vf.max_stat_ctxs = max;
+	else
+#endif
+		bp->pf.max_stat_ctxs = max;
+}
+
+unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+	if (BNXT_VF(bp))
+		return bp->vf.max_cp_rings;
+#endif
+	return bp->pf.max_cp_rings;
+}
+
+void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+	if (BNXT_VF(bp))
+		bp->vf.max_cp_rings = max;
+	else
+#endif
+		bp->pf.max_cp_rings = max;
+}
+
+static unsigned int bnxt_get_max_func_irqs(struct bnxt *bp)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+	if (BNXT_VF(bp))
+		return bp->vf.max_irqs;
+#endif
+	return bp->pf.max_irqs;
+}
+
+void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max_irqs)
+{
+#if defined(CONFIG_BNXT_SRIOV)
+	if (BNXT_VF(bp))
+		bp->vf.max_irqs = max_irqs;
+	else
+#endif
+		bp->pf.max_irqs = max_irqs;
+}
+
+static int bnxt_init_msix(struct bnxt *bp)
+{
+	int i, total_vecs, rc = 0, min = 1;
+	struct msix_entry *msix_ent;
+
+	total_vecs = bnxt_get_max_func_irqs(bp);
 	msix_ent = kcalloc(total_vecs, sizeof(struct msix_entry), GFP_KERNEL);
 	if (!msix_ent)
 		return -ENOMEM;
@@ -4773,8 +4919,10 @@ static int bnxt_setup_msix(struct bnxt *
 
 	bp->irq_tbl = kcalloc(total_vecs, sizeof(struct bnxt_irq), GFP_KERNEL);
 	if (bp->irq_tbl) {
-		int tcs;
+		for (i = 0; i < total_vecs; i++)
+			bp->irq_tbl[i].vector = msix_ent[i].vector;
 
+		bp->total_irqs = total_vecs;
 		/* Trim rings based upon num of vectors allocated */
 		rc = bnxt_trim_rings(bp, &bp->rx_nr_rings, &bp->tx_nr_rings,
 				     total_vecs, min == 1);
@@ -4782,43 +4930,10 @@ static int bnxt_setup_msix(struct bnxt *
 			goto msix_setup_exit;
 
 		bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
-		tcs = netdev_get_num_tc(dev);
-		if (tcs > 1) {
-			bp->tx_nr_rings_per_tc = bp->tx_nr_rings / tcs;
-			if (bp->tx_nr_rings_per_tc == 0) {
-				netdev_reset_tc(dev);
-				bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
-			} else {
-				int i, off, count;
-
-				bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tcs;
-				for (i = 0; i < tcs; i++) {
-					count = bp->tx_nr_rings_per_tc;
-					off = i * count;
-					netdev_set_tc_queue(dev, i, count, off);
-				}
-			}
-		}
-		bp->cp_nr_rings = total_vecs;
-
-		for (i = 0; i < bp->cp_nr_rings; i++) {
-			char *attr;
-
-			bp->irq_tbl[i].vector = msix_ent[i].vector;
-			if (bp->flags & BNXT_FLAG_SHARED_RINGS)
-				attr = "TxRx";
-			else if (i < bp->rx_nr_rings)
-				attr = "rx";
-			else
-				attr = "tx";
+		bp->cp_nr_rings = (min == 1) ?
+				  max_t(int, bp->tx_nr_rings, bp->rx_nr_rings) :
+				  bp->tx_nr_rings + bp->rx_nr_rings;
 
-			snprintf(bp->irq_tbl[i].name, len,
-				 "%s-%s-%d", dev->name, attr, i);
-			bp->irq_tbl[i].handler = bnxt_msix;
-		}
-		rc = bnxt_set_real_num_queues(bp);
-		if (rc)
-			goto msix_setup_exit;
 	} else {
 		rc = -ENOMEM;
 		goto msix_setup_exit;
@@ -4828,52 +4943,54 @@ static int bnxt_setup_msix(struct bnxt *
 	return 0;
 
 msix_setup_exit:
-	netdev_err(bp->dev, "bnxt_setup_msix err: %x\n", rc);
+	netdev_err(bp->dev, "bnxt_init_msix err: %x\n", rc);
+	kfree(bp->irq_tbl);
+	bp->irq_tbl = NULL;
 	pci_disable_msix(bp->pdev);
 	kfree(msix_ent);
 	return rc;
 }
 
-static int bnxt_setup_inta(struct bnxt *bp)
+static int bnxt_init_inta(struct bnxt *bp)
 {
-	int rc;
-	const int len = sizeof(bp->irq_tbl[0].name);
-
-	if (netdev_get_num_tc(bp->dev))
-		netdev_reset_tc(bp->dev);
-
 	bp->irq_tbl = kcalloc(1, sizeof(struct bnxt_irq), GFP_KERNEL);
-	if (!bp->irq_tbl) {
-		rc = -ENOMEM;
-		return rc;
-	}
+	if (!bp->irq_tbl)
+		return -ENOMEM;
+
+	bp->total_irqs = 1;
 	bp->rx_nr_rings = 1;
 	bp->tx_nr_rings = 1;
 	bp->cp_nr_rings = 1;
 	bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
 	bp->flags |= BNXT_FLAG_SHARED_RINGS;
 	bp->irq_tbl[0].vector = bp->pdev->irq;
-	snprintf(bp->irq_tbl[0].name, len,
-		 "%s-%s-%d", bp->dev->name, "TxRx", 0);
-	bp->irq_tbl[0].handler = bnxt_inta;
-	rc = bnxt_set_real_num_queues(bp);
-	return rc;
+	return 0;
 }
 
-static int bnxt_setup_int_mode(struct bnxt *bp)
+static int bnxt_init_int_mode(struct bnxt *bp)
 {
 	int rc = 0;
 
 	if (bp->flags & BNXT_FLAG_MSIX_CAP)
-		rc = bnxt_setup_msix(bp);
+		rc = bnxt_init_msix(bp);
 
 	if (!(bp->flags & BNXT_FLAG_USING_MSIX) && BNXT_PF(bp)) {
 		/* fallback to INTA */
-		rc = bnxt_setup_inta(bp);
+		rc = bnxt_init_inta(bp);
 	}
 	return rc;
 }
 
+static void bnxt_clear_int_mode(struct bnxt *bp)
+{
+	if (bp->flags & BNXT_FLAG_USING_MSIX)
+		pci_disable_msix(bp->pdev);
+
+	kfree(bp->irq_tbl);
+	bp->irq_tbl = NULL;
+	bp->flags &= ~BNXT_FLAG_USING_MSIX;
+}
+
 static void bnxt_free_irq(struct bnxt *bp)
 {
 	struct bnxt_irq *irq;
@@ -4892,10 +5009,6 @@ static void bnxt_free_irq(struct bnxt *b
 			free_irq(irq->vector, bp->bnapi[i]);
 		irq->requested = 0;
 	}
-	if (bp->flags & BNXT_FLAG_USING_MSIX)
-		pci_disable_msix(bp->pdev);
-	kfree(bp->irq_tbl);
-	bp->irq_tbl = NULL;
 }
 
 static int bnxt_request_irq(struct bnxt *bp)
@@ -4967,7 +5080,6 @@ static void bnxt_init_napi(struct bnxt *
 			bnapi = bp->bnapi[cp_nr_rings];
 			netif_napi_add(bp->dev, &bnapi->napi,
 				       bnxt_poll_nitroa0, 64);
-			napi_hash_add(&bnapi->napi);
 		}
 	} else {
 		bnapi = bp->bnapi[0];
@@ -4999,7 +5111,7 @@ static void bnxt_enable_napi(struct bnxt
 	}
 }
 
-static void bnxt_tx_disable(struct bnxt *bp)
+void bnxt_tx_disable(struct bnxt *bp)
 {
 	int i;
 	struct bnxt_tx_ring_info *txr;
@@ -5017,7 +5129,7 @@ static void bnxt_tx_disable(struct bnxt
 	netif_carrier_off(bp->dev);
 }
 
-static void bnxt_tx_enable(struct bnxt *bp)
+void bnxt_tx_enable(struct bnxt *bp)
 {
 	int i;
 	struct bnxt_tx_ring_info *txr;
@@ -5109,6 +5221,7 @@ static int bnxt_update_link(struct bnxt
 	struct hwrm_port_phy_qcfg_input req = {0};
 	struct hwrm_port_phy_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
 	u8 link_up = link_info->link_up;
+	u16 diff;
 
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_QCFG, -1, -1);
 
@@ -5196,6 +5309,18 @@ static int bnxt_update_link(struct bnxt
 		link_info->link_up = 0;
 	}
 	mutex_unlock(&bp->hwrm_cmd_lock);
+
+	diff = link_info->support_auto_speeds ^ link_info->advertising;
+	if ((link_info->support_auto_speeds | diff) !=
+	    link_info->support_auto_speeds) {
+		/* An advertised speed is no longer supported, so we need to
+		 * update the advertisement settings.  Caller holds RTNL
+		 * so we can modify link settings.
+		 */
+		link_info->advertising = link_info->support_auto_speeds;
+		if (link_info->autoneg & BNXT_AUTONEG_SPEED)
+			bnxt_hwrm_set_link_setting(bp, true, false);
+	}
 	return 0;
 }
 
@@ -5360,7 +5485,7 @@ static int bnxt_hwrm_shutdown_link(struc
 		return 0;
 
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1);
-	req.flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN);
+	req.flags = cpu_to_le32(PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DWN);
 	return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 }
 
@@ -5423,6 +5548,12 @@ static int bnxt_update_phy_setting(struc
 			update_link = true;
 	}
 
+	/* The last close may have shutdown the link, so need to call
+	 * PHY_CFG to bring it back up.
+	 */
+	if (!netif_carrier_ok(bp->dev))
+		update_link = true;
+
 	if (!bnxt_eee_config_ok(bp))
 		update_eee = true;
 
@@ -5543,22 +5674,7 @@ int bnxt_open_nic(struct bnxt *bp, bool
 static int bnxt_open(struct net_device *dev)
 {
 	struct bnxt *bp = netdev_priv(dev);
-	int rc = 0;
 
-	if (!test_bit(BNXT_STATE_FN_RST_DONE, &bp->state)) {
-		rc = bnxt_hwrm_func_reset(bp);
-		if (rc) {
-			netdev_err(bp->dev, "hwrm chip reset failure rc: %x\n",
-				   rc);
-			rc = -EBUSY;
-			return rc;
-		}
-		/* Do func_reset during the 1st PF open only to prevent killing
-		 * the VFs when the PF is brought down and up.
-		 */
-		if (BNXT_PF(bp))
-			set_bit(BNXT_STATE_FN_RST_DONE, &bp->state);
-	}
 	return __bnxt_open_nic(bp, true, true);
 }
 
@@ -6079,29 +6195,37 @@ bnxt_restart_timer:
 	mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
 
-/* Only called from bnxt_sp_task() */
-static void bnxt_reset(struct bnxt *bp, bool silent)
+static void bnxt_rtnl_lock_sp(struct bnxt *bp)
 {
-	/* bnxt_reset_task() calls bnxt_close_nic() which waits
-	 * for BNXT_STATE_IN_SP_TASK to clear.
-	 * If there is a parallel dev_close(), bnxt_close() may be holding
+	/* We are called from bnxt_sp_task which has BNXT_STATE_IN_SP_TASK
+	 * set.  If the device is being closed, bnxt_close() may be holding
 	 * rtnl() and waiting for BNXT_STATE_IN_SP_TASK to clear.  So we
 	 * must clear BNXT_STATE_IN_SP_TASK before holding rtnl().
 	 */
 	clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 	rtnl_lock();
-	if (test_bit(BNXT_STATE_OPEN, &bp->state))
-		bnxt_reset_task(bp, silent);
+}
+
+static void bnxt_rtnl_unlock_sp(struct bnxt *bp)
+{
 	set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 	rtnl_unlock();
 }
 
+/* Only called from bnxt_sp_task() */
+static void bnxt_reset(struct bnxt *bp, bool silent)
+{
+	bnxt_rtnl_lock_sp(bp);
+	if (test_bit(BNXT_STATE_OPEN, &bp->state))
+		bnxt_reset_task(bp, silent);
+	bnxt_rtnl_unlock_sp(bp);
+}
+
 static void bnxt_cfg_ntp_filters(struct bnxt *);
 
 static void bnxt_sp_task(struct work_struct *work)
 {
 	struct bnxt *bp = container_of(work, struct bnxt, sp_task);
-	int rc;
 
 	set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 	smp_mb__after_atomic();
@@ -6115,12 +6239,6 @@ static void bnxt_sp_task(struct work_str
 
 	if (test_and_clear_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event))
 		bnxt_cfg_ntp_filters(bp);
-	if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
-		rc = bnxt_update_link(bp, true);
-		if (rc)
-			netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
-				   rc);
-	}
 	if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
 		bnxt_hwrm_exec_fwd_req(bp);
 	if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
@@ -6141,18 +6259,39 @@ static void bnxt_sp_task(struct work_str
 		bnxt_hwrm_tunnel_dst_port_free(
 			bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE);
 	}
+	if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
+		bnxt_hwrm_port_qstats(bp);
+
+	/* These functions below will clear BNXT_STATE_IN_SP_TASK.  They
+	 * must be the last functions to be called before exiting.
+	 */
+	if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
+		int rc = 0;
+
+		if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
+				       &bp->sp_event))
+			bnxt_hwrm_phy_qcaps(bp);
+
+		bnxt_rtnl_lock_sp(bp);
+		if (test_bit(BNXT_STATE_OPEN, &bp->state))
+			rc = bnxt_update_link(bp, true);
+		bnxt_rtnl_unlock_sp(bp);
+		if (rc)
+			netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
+				   rc);
+	}
+	if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) {
+		bnxt_rtnl_lock_sp(bp);
+		if (test_bit(BNXT_STATE_OPEN, &bp->state))
+			bnxt_get_port_module_status(bp);
+		bnxt_rtnl_unlock_sp(bp);
+	}
 	if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
 		bnxt_reset(bp, false);
 
 	if (test_and_clear_bit(BNXT_RESET_TASK_SILENT_SP_EVENT, &bp->sp_event))
 		bnxt_reset(bp, true);
 
-	if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event))
-		bnxt_get_port_module_status(bp);
-
-	if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
-		bnxt_hwrm_port_qstats(bp);
-
 	smp_mb__before_atomic();
 	clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 }
@@ -6303,9 +6442,6 @@ static int bnxt_change_mtu(struct net_de
 {
 	struct bnxt *bp = netdev_priv(dev);
 
-	if (new_mtu < 60 || new_mtu > 9500)
-		return -EINVAL;
-
 	if (netif_running(dev))
 		bnxt_close_nic(bp, false, false);
 
@@ -6318,17 +6454,10 @@ static int bnxt_change_mtu(struct net_de
 	return 0;
 }
 
-static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
-			 struct tc_to_netdev *ntc)
+int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
 {
 	struct bnxt *bp = netdev_priv(dev);
 	bool sh = false;
-	u8 tc;
-
-	if (ntc->type != TC_SETUP_MQPRIO)
-		return -EINVAL;
-
-	tc = ntc->tc;
 
 	if (tc > bp->max_tc) {
 		netdev_err(dev, "too many traffic classes requested: %d Max supported is %d\n",
@@ -6371,6 +6500,15 @@ static int bnxt_setup_tc(struct net_devi
 	return 0;
 }
 
+static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
+			 struct tc_to_netdev *ntc)
+{
+	if (ntc->type != TC_SETUP_MQPRIO)
+		return -EINVAL;
+
+	return bnxt_setup_mq_tc(dev, ntc->tc);
+}
+
 #ifdef CONFIG_RFS_ACCEL
 static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1,
 			    struct bnxt_ntuple_filter *f2)
@@ -6659,11 +6797,15 @@ static void bnxt_remove_one(struct pci_d
 	cancel_work_sync(&bp->sp_task);
 	bp->sp_event = 0;
 
+	bnxt_clear_int_mode(bp);
 	bnxt_hwrm_func_drv_unrgtr(bp);
 	bnxt_free_hwrm_resources(bp);
+	bnxt_dcb_free(bp);
 	pci_iounmap(pdev, bp->bar2);
 	pci_iounmap(pdev, bp->bar1);
 	pci_iounmap(pdev, bp->bar0);
+	kfree(bp->edev);
+	bp->edev = NULL;
 	free_netdev(dev);
 
 	pci_release_regions(pdev);
@@ -6772,6 +6914,39 @@ int bnxt_get_max_rings(struct bnxt *bp,
 	return bnxt_trim_rings(bp, max_rx, max_tx, cp, shared);
 }
 
+static int bnxt_get_dflt_rings(struct bnxt *bp, int *max_rx, int *max_tx,
+			       bool shared)
+{
+	int rc;
+
+	rc = bnxt_get_max_rings(bp, max_rx, max_tx, shared);
+	if (rc)
+		return rc;
+
+	if (bp->flags & BNXT_FLAG_ROCE_CAP) {
+		int max_cp, max_stat, max_irq;
+
+		/* Reserve minimum resources for RoCE */
+		max_cp = bnxt_get_max_func_cp_rings(bp);
+		max_stat = bnxt_get_max_func_stat_ctxs(bp);
+		max_irq = bnxt_get_max_func_irqs(bp);
+		if (max_cp <= BNXT_MIN_ROCE_CP_RINGS ||
+		    max_irq <= BNXT_MIN_ROCE_CP_RINGS ||
+		    max_stat <= BNXT_MIN_ROCE_STAT_CTXS)
+			return 0;
+
+		max_cp -= BNXT_MIN_ROCE_CP_RINGS;
+		max_irq -= BNXT_MIN_ROCE_CP_RINGS;
+		max_stat -= BNXT_MIN_ROCE_STAT_CTXS;
+		max_cp = min_t(int, max_cp, max_irq);
+		max_cp = min_t(int, max_cp, max_stat);
+		rc = bnxt_trim_rings(bp, max_rx, max_tx, max_cp, shared);
+		if (rc)
+			rc = 0;
+	}
+	return rc;
+}
+
 static int bnxt_set_dflt_rings(struct bnxt *bp)
 {
 	int dflt_rings, max_rx_rings, max_tx_rings, rc;
@@ -6780,7 +6955,7 @@ static int bnxt_set_dflt_rings(struct bn
 	if (sh)
 		bp->flags |= BNXT_FLAG_SHARED_RINGS;
 	dflt_rings = netif_get_num_default_rss_queues();
-	rc = bnxt_get_max_rings(bp, &max_rx_rings, &max_tx_rings, sh);
+	rc = bnxt_get_dflt_rings(bp, &max_rx_rings, &max_tx_rings, sh);
 	if (rc)
 		return rc;
 	bp->rx_nr_rings = min_t(int, dflt_rings, max_rx_rings);
@@ -6796,6 +6971,13 @@ static int bnxt_set_dflt_rings(struct bn
 	return rc;
 }
 
+void bnxt_restore_pf_fw_resources(struct bnxt *bp)
+{
+	ASSERT_RTNL();
+	bnxt_hwrm_func_qcaps(bp);
+	bnxt_subtract_ulp_resources(bp, BNXT_ROCE_ULP);
+}
+
 static void bnxt_parse_log_pcie_link(struct bnxt *bp)
 {
 	enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN;
@@ -6884,6 +7066,12 @@ static int bnxt_init_one(struct pci_dev
 	dev->features |= dev->hw_features | NETIF_F_HIGHDMA;
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
+	/* MTU range: 60 - 9500 */
+	dev->min_mtu = ETH_ZLEN;
+	dev->max_mtu = 9500;
+
+	bnxt_dcb_init(bp);
+
 #ifdef CONFIG_BNXT_SRIOV
 	init_waitqueue_head(&bp->sriov_cfg_wait);
 #endif
@@ -6895,6 +7083,12 @@ static int bnxt_init_one(struct pci_dev
 	if (rc)
 		goto init_err;
 
+	rc = bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0);
+	if (rc)
+		goto init_err;
+
+	bp->ulp_probe = bnxt_ulp_probe;
+
 	/* Get the MAX capabilities for this function */
 	rc = bnxt_hwrm_func_qcaps(bp);
 	if (rc) {
@@ -6916,14 +7110,22 @@ static int bnxt_init_one(struct pci_dev
 
 	bnxt_set_tpa_flags(bp);
 	bnxt_set_ring_params(bp);
-	if (BNXT_PF(bp))
-		bp->pf.max_irqs = max_irqs;
-#if defined(CONFIG_BNXT_SRIOV)
-	else
-		bp->vf.max_irqs = max_irqs;
-#endif
+	bnxt_set_max_func_irqs(bp, max_irqs);
 	bnxt_set_dflt_rings(bp);
 
+	/* Default RSS hash cfg. */
+	bp->rss_hash_cfg = VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4 |
+			   VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4 |
+			   VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6 |
+			   VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+	if (!BNXT_CHIP_NUM_57X0X(bp->chip_num) &&
+	    !BNXT_CHIP_TYPE_NITRO_A0(bp) &&
+	    bp->hwrm_spec_code >= 0x10501) {
+		bp->flags |= BNXT_FLAG_UDP_RSS_CAP;
+		bp->rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4 |
+				    VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
+	}
+
 	if (BNXT_PF(bp) && !BNXT_CHIP_TYPE_NITRO_A0(bp)) {
 		dev->hw_features |= NETIF_F_NTUPLE;
 		if (bnxt_rfs_capable(bp)) {
@@ -6939,10 +7141,18 @@ static int bnxt_init_one(struct pci_dev
 	if (rc)
 		goto init_err;
 
-	rc = register_netdev(dev);
+	rc = bnxt_hwrm_func_reset(bp);
+	if (rc)
+		goto init_err;
+
+	rc = bnxt_init_int_mode(bp);
 	if (rc)
 		goto init_err;
 
+	rc = register_netdev(dev);
+	if (rc)
+		goto init_err_clr_int;
+
 	netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
 		    board_info[ent->driver_data].name,
 		    (long)pci_resource_start(pdev, 0), dev->dev_addr);
@@ -6951,6 +7161,9 @@ static int bnxt_init_one(struct pci_dev
 
 	return 0;
 
+init_err_clr_int:
+	bnxt_clear_int_mode(bp);
+
 init_err:
 	pci_iounmap(pdev, bp->bar0);
 	pci_release_regions(pdev);
@@ -6980,6 +7193,8 @@ static pci_ers_result_t bnxt_io_error_de
 	rtnl_lock();
 	netif_device_detach(netdev);
 
+	bnxt_ulp_stop(bp);
+
 	if (state == pci_channel_io_perm_failure) {
 		rtnl_unlock();
 		return PCI_ERS_RESULT_DISCONNECT;
@@ -6988,8 +7203,6 @@ static pci_ers_result_t bnxt_io_error_de
 	if (netif_running(netdev))
 		bnxt_close(netdev);
 
-	/* So that func_reset will be done during slot_reset */
-	clear_bit(BNXT_STATE_FN_RST_DONE, &bp->state);
 	pci_disable_device(pdev);
 	rtnl_unlock();
 
@@ -7023,11 +7236,14 @@ static pci_ers_result_t bnxt_io_slot_res
 	} else {
 		pci_set_master(pdev);
 
-		if (netif_running(netdev))
+		err = bnxt_hwrm_func_reset(bp);
+		if (!err && netif_running(netdev))
 			err = bnxt_open(netdev);
 
-		if (!err)
+		if (!err) {
 			result = PCI_ERS_RESULT_RECOVERED;
+			bnxt_ulp_start(bp);
+		}
 	}
 
 	if (result != PCI_ERS_RESULT_RECOVERED && netif_running(netdev))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,502 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-2016 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.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/rtnetlink.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_dcb.h"
+
+#ifdef CONFIG_BNXT_DCB
+static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
+{
+	struct hwrm_queue_pri2cos_cfg_input req = {0};
+	int rc = 0, i;
+	u8 *pri2cos;
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_CFG, -1, -1);
+	req.flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
+				QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN);
+
+	pri2cos = &req.pri0_cos_queue_id;
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+		req.enables |= cpu_to_le32(
+			QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
+
+		pri2cos[i] = bp->q_info[ets->prio_tc[i]].queue_id;
+	}
+	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	return rc;
+}
+
+static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
+{
+	struct hwrm_queue_pri2cos_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+	struct hwrm_queue_pri2cos_qcfg_input req = {0};
+	int rc = 0;
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_QCFG, -1, -1);
+	req.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
+	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	if (!rc) {
+		u8 *pri2cos = &resp->pri0_cos_queue_id;
+		int i, j;
+
+		for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+			u8 queue_id = pri2cos[i];
+
+			for (j = 0; j < bp->max_tc; j++) {
+				if (bp->q_info[j].queue_id == queue_id) {
+					ets->prio_tc[i] = j;
+					break;
+				}
+			}
+		}
+	}
+	return rc;
+}
+
+static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
+				      u8 max_tc)
+{
+	struct hwrm_queue_cos2bw_cfg_input req = {0};
+	struct bnxt_cos2bw_cfg cos2bw;
+	int rc = 0, i;
+	void *data;
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_CFG, -1, -1);
+	data = &req.unused_0;
+	for (i = 0; i < max_tc; i++, data += sizeof(cos2bw) - 4) {
+		req.enables |= cpu_to_le32(
+			QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID << i);
+
+		memset(&cos2bw, 0, sizeof(cos2bw));
+		cos2bw.queue_id = bp->q_info[i].queue_id;
+		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) {
+			cos2bw.tsa =
+				QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP;
+			cos2bw.pri_lvl = i;
+		} else {
+			cos2bw.tsa =
+				QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS;
+			cos2bw.bw_weight = ets->tc_tx_bw[i];
+		}
+		memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
+		if (i == 0) {
+			req.queue_id0 = cos2bw.queue_id;
+			req.unused_0 = 0;
+		}
+	}
+	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	return rc;
+}
+
+static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
+{
+	struct hwrm_queue_cos2bw_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+	struct hwrm_queue_cos2bw_qcfg_input req = {0};
+	struct bnxt_cos2bw_cfg cos2bw;
+	void *data;
+	int rc, i;
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_QCFG, -1, -1);
+	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	if (rc)
+		return rc;
+
+	data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id);
+	for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw) - 4) {
+		int j;
+
+		memcpy(&cos2bw.queue_id, data, sizeof(cos2bw) - 4);
+		if (i == 0)
+			cos2bw.queue_id = resp->queue_id0;
+
+		for (j = 0; j < bp->max_tc; j++) {
+			if (bp->q_info[j].queue_id != cos2bw.queue_id)
+				continue;
+			if (cos2bw.tsa ==
+			    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) {
+				ets->tc_tsa[j] = IEEE_8021QAZ_TSA_STRICT;
+			} else {
+				ets->tc_tsa[j] = IEEE_8021QAZ_TSA_ETS;
+				ets->tc_tx_bw[j] = cos2bw.bw_weight;
+			}
+		}
+	}
+	return 0;
+}
+
+static int bnxt_hwrm_queue_cfg(struct bnxt *bp, unsigned int lltc_mask)
+{
+	struct hwrm_queue_cfg_input req = {0};
+	int i;
+
+	if (netif_running(bp->dev))
+		bnxt_tx_disable(bp);
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_CFG, -1, -1);
+	req.flags = cpu_to_le32(QUEUE_CFG_REQ_FLAGS_PATH_BIDIR);
+	req.enables = cpu_to_le32(QUEUE_CFG_REQ_ENABLES_SERVICE_PROFILE);
+
+	/* Configure lossless queues to lossy first */
+	req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
+	for (i = 0; i < bp->max_tc; i++) {
+		if (BNXT_LLQ(bp->q_info[i].queue_profile)) {
+			req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
+			hwrm_send_message(bp, &req, sizeof(req),
+					  HWRM_CMD_TIMEOUT);
+			bp->q_info[i].queue_profile =
+				QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
+		}
+	}
+
+	/* Now configure desired queues to lossless */
+	req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
+	for (i = 0; i < bp->max_tc; i++) {
+		if (lltc_mask & (1 << i)) {
+			req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
+			hwrm_send_message(bp, &req, sizeof(req),
+					  HWRM_CMD_TIMEOUT);
+			bp->q_info[i].queue_profile =
+				QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
+		}
+	}
+	if (netif_running(bp->dev))
+		bnxt_tx_enable(bp);
+
+	return 0;
+}
+
+static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
+{
+	struct hwrm_queue_pfcenable_cfg_input req = {0};
+	struct ieee_ets *my_ets = bp->ieee_ets;
+	unsigned int tc_mask = 0, pri_mask = 0;
+	u8 i, pri, lltc_count = 0;
+	bool need_q_recfg = false;
+	int rc;
+
+	if (!my_ets)
+		return -EINVAL;
+
+	for (i = 0; i < bp->max_tc; i++) {
+		for (pri = 0; pri < IEEE_8021QAZ_MAX_TCS; pri++) {
+			if ((pfc->pfc_en & (1 << pri)) &&
+			    (my_ets->prio_tc[pri] == i)) {
+				pri_mask |= 1 << pri;
+				tc_mask |= 1 << i;
+			}
+		}
+		if (tc_mask & (1 << i))
+			lltc_count++;
+	}
+	if (lltc_count > bp->max_lltc)
+		return -EINVAL;
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1);
+	req.flags = cpu_to_le32(pri_mask);
+	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < bp->max_tc; i++) {
+		if (tc_mask & (1 << i)) {
+			if (!BNXT_LLQ(bp->q_info[i].queue_profile))
+				need_q_recfg = true;
+		}
+	}
+
+	if (need_q_recfg)
+		rc = bnxt_hwrm_queue_cfg(bp, tc_mask);
+
+	return rc;
+}
+
+static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc)
+{
+	struct hwrm_queue_pfcenable_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+	struct hwrm_queue_pfcenable_qcfg_input req = {0};
+	u8 pri_mask;
+	int rc;
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_QCFG, -1, -1);
+	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	if (rc)
+		return rc;
+
+	pri_mask = le32_to_cpu(resp->flags);
+	pfc->pfc_en = pri_mask;
+	return 0;
+}
+
+static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
+{
+	int total_ets_bw = 0;
+	u8 max_tc = 0;
+	int i;
+
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+		if (ets->prio_tc[i] > bp->max_tc) {
+			netdev_err(bp->dev, "priority to TC mapping exceeds TC count %d\n",
+				   ets->prio_tc[i]);
+			return -EINVAL;
+		}
+		if (ets->prio_tc[i] > max_tc)
+			max_tc = ets->prio_tc[i];
+
+		if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc)
+			return -EINVAL;
+
+		switch (ets->tc_tsa[i]) {
+		case IEEE_8021QAZ_TSA_STRICT:
+			break;
+		case IEEE_8021QAZ_TSA_ETS:
+			total_ets_bw += ets->tc_tx_bw[i];
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+	if (total_ets_bw > 100)
+		return -EINVAL;
+
+	*tc = max_tc + 1;
+	return 0;
+}
+
+static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	struct ieee_ets *my_ets = bp->ieee_ets;
+
+	ets->ets_cap = bp->max_tc;
+
+	if (!my_ets) {
+		int rc;
+
+		if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
+			return 0;
+
+		my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
+		if (!my_ets)
+			return 0;
+		rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets);
+		if (rc)
+			return 0;
+		rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets);
+		if (rc)
+			return 0;
+	}
+
+	ets->cbs = my_ets->cbs;
+	memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
+	memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
+	memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
+	memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
+	return 0;
+}
+
+static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	struct ieee_ets *my_ets = bp->ieee_ets;
+	u8 max_tc = 0;
+	int rc, i;
+
+	if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
+	    !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
+		return -EINVAL;
+
+	rc = bnxt_ets_validate(bp, ets, &max_tc);
+	if (!rc) {
+		if (!my_ets) {
+			my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
+			if (!my_ets)
+				return -ENOMEM;
+			/* initialize PRI2TC mappings to invalid value */
+			for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+				my_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS;
+			bp->ieee_ets = my_ets;
+		}
+		rc = bnxt_setup_mq_tc(dev, max_tc);
+		if (rc)
+			return rc;
+		rc = bnxt_hwrm_queue_cos2bw_cfg(bp, ets, max_tc);
+		if (rc)
+			return rc;
+		rc = bnxt_hwrm_queue_pri2cos_cfg(bp, ets);
+		if (rc)
+			return rc;
+		memcpy(my_ets, ets, sizeof(*my_ets));
+	}
+	return rc;
+}
+
+static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	__le64 *stats = (__le64 *)bp->hw_rx_port_stats;
+	struct ieee_pfc *my_pfc = bp->ieee_pfc;
+	long rx_off, tx_off;
+	int i, rc;
+
+	pfc->pfc_cap = bp->max_lltc;
+
+	if (!my_pfc) {
+		if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
+			return 0;
+
+		my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
+		if (!my_pfc)
+			return 0;
+		bp->ieee_pfc = my_pfc;
+		rc = bnxt_hwrm_queue_pfc_qcfg(bp, my_pfc);
+		if (rc)
+			return 0;
+	}
+
+	pfc->pfc_en = my_pfc->pfc_en;
+	pfc->mbc = my_pfc->mbc;
+	pfc->delay = my_pfc->delay;
+
+	if (!stats)
+		return 0;
+
+	rx_off = BNXT_RX_STATS_OFFSET(rx_pfc_ena_frames_pri0);
+	tx_off = BNXT_TX_STATS_OFFSET(tx_pfc_ena_frames_pri0);
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++, rx_off++, tx_off++) {
+		pfc->requests[i] = le64_to_cpu(*(stats + tx_off));
+		pfc->indications[i] = le64_to_cpu(*(stats + rx_off));
+	}
+
+	return 0;
+}
+
+static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	struct ieee_pfc *my_pfc = bp->ieee_pfc;
+	int rc;
+
+	if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
+	    !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
+		return -EINVAL;
+
+	if (!my_pfc) {
+		my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
+		if (!my_pfc)
+			return -ENOMEM;
+		bp->ieee_pfc = my_pfc;
+	}
+	rc = bnxt_hwrm_queue_pfc_cfg(bp, pfc);
+	if (!rc)
+		memcpy(my_pfc, pfc, sizeof(*my_pfc));
+
+	return rc;
+}
+
+static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	int rc = -EINVAL;
+
+	if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
+	    !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
+		return -EINVAL;
+
+	rc = dcb_ieee_setapp(dev, app);
+	return rc;
+}
+
+static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	int rc;
+
+	if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+
+	rc = dcb_ieee_delapp(dev, app);
+	return rc;
+}
+
+static u8 bnxt_dcbnl_getdcbx(struct net_device *dev)
+{
+	struct bnxt *bp = netdev_priv(dev);
+
+	return bp->dcbx_cap;
+}
+
+static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
+{
+	struct bnxt *bp = netdev_priv(dev);
+
+	/* only support IEEE */
+	if ((mode & DCB_CAP_DCBX_VER_CEE) || !(mode & DCB_CAP_DCBX_VER_IEEE))
+		return 1;
+
+	if ((mode & DCB_CAP_DCBX_HOST) && BNXT_VF(bp))
+		return 1;
+
+	if (mode == bp->dcbx_cap)
+		return 0;
+
+	bp->dcbx_cap = mode;
+	return 0;
+}
+
+static const struct dcbnl_rtnl_ops dcbnl_ops = {
+	.ieee_getets	= bnxt_dcbnl_ieee_getets,
+	.ieee_setets	= bnxt_dcbnl_ieee_setets,
+	.ieee_getpfc	= bnxt_dcbnl_ieee_getpfc,
+	.ieee_setpfc	= bnxt_dcbnl_ieee_setpfc,
+	.ieee_setapp	= bnxt_dcbnl_ieee_setapp,
+	.ieee_delapp	= bnxt_dcbnl_ieee_delapp,
+	.getdcbx	= bnxt_dcbnl_getdcbx,
+	.setdcbx	= bnxt_dcbnl_setdcbx,
+};
+
+void bnxt_dcb_init(struct bnxt *bp)
+{
+	if (bp->hwrm_spec_code < 0x10501)
+		return;
+
+	bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
+	if (BNXT_PF(bp))
+		bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
+	else
+		bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED;
+	bp->dev->dcbnl_ops = &dcbnl_ops;
+}
+
+void bnxt_dcb_free(struct bnxt *bp)
+{
+	kfree(bp->ieee_pfc);
+	kfree(bp->ieee_ets);
+	bp->ieee_pfc = NULL;
+	bp->ieee_ets = NULL;
+}
+
+#else
+
+void bnxt_dcb_init(struct bnxt *bp)
+{
+}
+
+void bnxt_dcb_free(struct bnxt *bp)
+{
+}
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,41 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2014-2016 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 BNXT_DCB_H
+#define BNXT_DCB_H
+
+#include <net/dcbnl.h>
+
+struct bnxt_dcb {
+	u8			max_tc;
+	struct ieee_pfc		*ieee_pfc;
+	struct ieee_ets		*ieee_ets;
+	u8			dcbx_cap;
+	u8			default_pri;
+};
+
+struct bnxt_cos2bw_cfg {
+	u8			pad[3];
+	u8			queue_id;
+	__le32			min_bw;
+	__le32			max_bw;
+	u8			tsa;
+	u8			pri_lvl;
+	u8			bw_weight;
+	u8			unused;
+};
+
+#define BNXT_LLQ(q_profile)	\
+	((q_profile) == QUEUE_QPORTCFG_RESP_QUEUE_ID0_SERVICE_PROFILE_LOSSLESS)
+
+#define HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL	0x0300
+
+void bnxt_dcb_init(struct bnxt *bp);
+void bnxt_dcb_free(struct bnxt *bp);
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -107,16 +107,9 @@ static int bnxt_set_coalesce(struct net_
 
 #define BNXT_NUM_STATS	21
 
-#define BNXT_RX_STATS_OFFSET(counter)	\
-	(offsetof(struct rx_port_stats, counter) / 8)
-
 #define BNXT_RX_STATS_ENTRY(counter)	\
 	{ BNXT_RX_STATS_OFFSET(counter), __stringify(counter) }
 
-#define BNXT_TX_STATS_OFFSET(counter)			\
-	((offsetof(struct tx_port_stats, counter) +	\
-	  sizeof(struct rx_port_stats) + 512) / 8)
-
 #define BNXT_TX_STATS_ENTRY(counter)	\
 	{ BNXT_TX_STATS_OFFSET(counter), __stringify(counter) }
 
@@ -150,6 +143,14 @@ static const struct {
 	BNXT_RX_STATS_ENTRY(rx_tagged_frames),
 	BNXT_RX_STATS_ENTRY(rx_double_tagged_frames),
 	BNXT_RX_STATS_ENTRY(rx_good_frames),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri0),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri1),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri2),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri3),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri4),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri5),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri6),
+	BNXT_RX_STATS_ENTRY(rx_pfc_ena_frames_pri7),
 	BNXT_RX_STATS_ENTRY(rx_undrsz_frames),
 	BNXT_RX_STATS_ENTRY(rx_eee_lpi_events),
 	BNXT_RX_STATS_ENTRY(rx_eee_lpi_duration),
@@ -179,6 +180,14 @@ static const struct {
 	BNXT_TX_STATS_ENTRY(tx_fcs_err_frames),
 	BNXT_TX_STATS_ENTRY(tx_err),
 	BNXT_TX_STATS_ENTRY(tx_fifo_underruns),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri0),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri1),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri2),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri3),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri4),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri5),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri6),
+	BNXT_TX_STATS_ENTRY(tx_pfc_ena_frames_pri7),
 	BNXT_TX_STATS_ENTRY(tx_eee_lpi_events),
 	BNXT_TX_STATS_ENTRY(tx_eee_lpi_duration),
 	BNXT_TX_STATS_ENTRY(tx_total_collisions),
@@ -542,6 +551,146 @@ fltr_err:
 
 	return rc;
 }
+#endif
+
+static u64 get_ethtool_ipv4_rss(struct bnxt *bp)
+{
+	if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4)
+		return RXH_IP_SRC | RXH_IP_DST;
+	return 0;
+}
+
+static u64 get_ethtool_ipv6_rss(struct bnxt *bp)
+{
+	if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6)
+		return RXH_IP_SRC | RXH_IP_DST;
+	return 0;
+}
+
+static int bnxt_grxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
+{
+	cmd->data = 0;
+	switch (cmd->flow_type) {
+	case TCP_V4_FLOW:
+		if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4)
+			cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+				     RXH_L4_B_0_1 | RXH_L4_B_2_3;
+		cmd->data |= get_ethtool_ipv4_rss(bp);
+		break;
+	case UDP_V4_FLOW:
+		if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4)
+			cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+				     RXH_L4_B_0_1 | RXH_L4_B_2_3;
+		/* fall through */
+	case SCTP_V4_FLOW:
+	case AH_ESP_V4_FLOW:
+	case AH_V4_FLOW:
+	case ESP_V4_FLOW:
+	case IPV4_FLOW:
+		cmd->data |= get_ethtool_ipv4_rss(bp);
+		break;
+
+	case TCP_V6_FLOW:
+		if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6)
+			cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+				     RXH_L4_B_0_1 | RXH_L4_B_2_3;
+		cmd->data |= get_ethtool_ipv6_rss(bp);
+		break;
+	case UDP_V6_FLOW:
+		if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6)
+			cmd->data |= RXH_IP_SRC | RXH_IP_DST |
+				     RXH_L4_B_0_1 | RXH_L4_B_2_3;
+		/* fall through */
+	case SCTP_V6_FLOW:
+	case AH_ESP_V6_FLOW:
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+	case IPV6_FLOW:
+		cmd->data |= get_ethtool_ipv6_rss(bp);
+		break;
+	}
+	return 0;
+}
+
+#define RXH_4TUPLE (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3)
+#define RXH_2TUPLE (RXH_IP_SRC | RXH_IP_DST)
+
+static int bnxt_srxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd)
+{
+	u32 rss_hash_cfg = bp->rss_hash_cfg;
+	int tuple, rc = 0;
+
+	if (cmd->data == RXH_4TUPLE)
+		tuple = 4;
+	else if (cmd->data == RXH_2TUPLE)
+		tuple = 2;
+	else if (!cmd->data)
+		tuple = 0;
+	else
+		return -EINVAL;
+
+	if (cmd->flow_type == TCP_V4_FLOW) {
+		rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4;
+		if (tuple == 4)
+			rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV4;
+	} else if (cmd->flow_type == UDP_V4_FLOW) {
+		if (tuple == 4 && !(bp->flags & BNXT_FLAG_UDP_RSS_CAP))
+			return -EINVAL;
+		rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4;
+		if (tuple == 4)
+			rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4;
+	} else if (cmd->flow_type == TCP_V6_FLOW) {
+		rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+		if (tuple == 4)
+			rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_TCP_IPV6;
+	} else if (cmd->flow_type == UDP_V6_FLOW) {
+		if (tuple == 4 && !(bp->flags & BNXT_FLAG_UDP_RSS_CAP))
+			return -EINVAL;
+		rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
+		if (tuple == 4)
+			rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
+	} else if (tuple == 4) {
+		return -EINVAL;
+	}
+
+	switch (cmd->flow_type) {
+	case TCP_V4_FLOW:
+	case UDP_V4_FLOW:
+	case SCTP_V4_FLOW:
+	case AH_ESP_V4_FLOW:
+	case AH_V4_FLOW:
+	case ESP_V4_FLOW:
+	case IPV4_FLOW:
+		if (tuple == 2)
+			rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4;
+		else if (!tuple)
+			rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_IPV4;
+		break;
+
+	case TCP_V6_FLOW:
+	case UDP_V6_FLOW:
+	case SCTP_V6_FLOW:
+	case AH_ESP_V6_FLOW:
+	case AH_V6_FLOW:
+	case ESP_V6_FLOW:
+	case IPV6_FLOW:
+		if (tuple == 2)
+			rss_hash_cfg |= VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6;
+		else if (!tuple)
+			rss_hash_cfg &= ~VNIC_RSS_CFG_REQ_HASH_TYPE_IPV6;
+		break;
+	}
+
+	if (bp->rss_hash_cfg == rss_hash_cfg)
+		return 0;
+
+	bp->rss_hash_cfg = rss_hash_cfg;
+	if (netif_running(bp->dev)) {
+		bnxt_close_nic(bp, false, false);
+		rc = bnxt_open_nic(bp, false, false);
+	}
+	return rc;
+}
 
 static int bnxt_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 			  u32 *rule_locs)
@@ -550,6 +699,7 @@ static int bnxt_get_rxnfc(struct net_dev
 	int rc = 0;
 
 	switch (cmd->cmd) {
+#ifdef CONFIG_RFS_ACCEL
 	case ETHTOOL_GRXRINGS:
 		cmd->data = bp->rx_nr_rings;
 		break;
@@ -566,6 +716,11 @@ static int bnxt_get_rxnfc(struct net_dev
 	case ETHTOOL_GRXCLSRULE:
 		rc = bnxt_grxclsrule(bp, cmd);
 		break;
+#endif
+
+	case ETHTOOL_GRXFH:
+		rc = bnxt_grxfh(bp, cmd);
+		break;
 
 	default:
 		rc = -EOPNOTSUPP;
@@ -574,7 +729,23 @@ static int bnxt_get_rxnfc(struct net_dev
 
 	return rc;
 }
-#endif
+
+static int bnxt_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	int rc;
+
+	switch (cmd->cmd) {
+	case ETHTOOL_SRXFH:
+		rc = bnxt_srxfh(bp, cmd);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+	return rc;
+}
 
 static u32 bnxt_get_rxfh_indir_size(struct net_device *dev)
 {
@@ -1885,9 +2056,8 @@ const struct ethtool_ops bnxt_ethtool_op
 	.get_ringparam		= bnxt_get_ringparam,
 	.get_channels		= bnxt_get_channels,
 	.set_channels		= bnxt_set_channels,
-#ifdef CONFIG_RFS_ACCEL
 	.get_rxnfc		= bnxt_get_rxnfc,
-#endif
+	.set_rxnfc		= bnxt_set_rxnfc,
 	.get_rxfh_indir_size    = bnxt_get_rxfh_indir_size,
 	.get_rxfh_key_size      = bnxt_get_rxfh_key_size,
 	.get_rxfh               = bnxt_get_rxfh,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt.h	2017-02-12 16:03:20.000000000 -0500
@@ -11,10 +11,10 @@
 #define BNXT_H
 
 #define DRV_MODULE_NAME		"bnxt_en"
-#define DRV_MODULE_VERSION	"1.5.0"
+#define DRV_MODULE_VERSION	"1.6.0"
 
 #define DRV_VER_MAJ	1
-#define DRV_VER_MIN	5
+#define DRV_VER_MIN	6
 #define DRV_VER_UPD	0
 
 struct tx_bd {
@@ -387,6 +387,9 @@ struct rx_tpa_end_cmp_ext {
 #define DB_KEY_TX_PUSH						(0x4 << 28)
 #define DB_LONG_TX_PUSH						(0x2 << 24)
 
+#define BNXT_MIN_ROCE_CP_RINGS	2
+#define BNXT_MIN_ROCE_STAT_CTXS	1
+
 #define INVALID_HW_RING_ID	((u16)-1)
 
 /* The hardware supports certain page sizes.  Use the supported page sizes
@@ -700,7 +703,6 @@ struct bnxt_vnic_info {
 	u8		*uc_list;
 
 	u16		*fw_grp_ids;
-	u16		hash_type;
 	dma_addr_t	rss_table_dma_addr;
 	__le16		*rss_table;
 	dma_addr_t	rss_hash_key_dma_addr;
@@ -952,7 +954,12 @@ struct bnxt {
 	#define BNXT_FLAG_RFS		0x100
 	#define BNXT_FLAG_SHARED_RINGS	0x200
 	#define BNXT_FLAG_PORT_STATS	0x400
+	#define BNXT_FLAG_UDP_RSS_CAP	0x800
 	#define BNXT_FLAG_EEE_CAP	0x1000
+	#define BNXT_FLAG_ROCEV1_CAP	0x8000
+	#define BNXT_FLAG_ROCEV2_CAP	0x10000
+	#define BNXT_FLAG_ROCE_CAP	(BNXT_FLAG_ROCEV1_CAP |	\
+					 BNXT_FLAG_ROCEV2_CAP)
 	#define BNXT_FLAG_CHIP_NITRO_A0	0x1000000
 
 	#define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA |		\
@@ -965,6 +972,9 @@ struct bnxt {
 #define BNXT_SINGLE_PF(bp)	(BNXT_PF(bp) && !BNXT_NPAR(bp))
 #define BNXT_CHIP_TYPE_NITRO_A0(bp) ((bp)->flags & BNXT_FLAG_CHIP_NITRO_A0)
 
+	struct bnxt_en_dev	*edev;
+	struct bnxt_en_dev *	(*ulp_probe)(struct net_device *);
+
 	struct bnxt_napi	**bnapi;
 
 	struct bnxt_rx_ring_info	*rx_ring;
@@ -1007,8 +1017,10 @@ struct bnxt {
 	struct bnxt_ring_grp_info	*grp_info;
 	struct bnxt_vnic_info	*vnic_info;
 	int			nr_vnics;
+	u32			rss_hash_cfg;
 
 	u8			max_tc;
+	u8			max_lltc;	/* lossless TCs */
 	struct bnxt_queue_info	q_info[BNXT_MAX_QUEUE];
 
 	unsigned int		current_interval;
@@ -1019,11 +1031,18 @@ struct bnxt {
 	unsigned long		state;
 #define BNXT_STATE_OPEN		0
 #define BNXT_STATE_IN_SP_TASK	1
-#define BNXT_STATE_FN_RST_DONE	2
 
 	struct bnxt_irq	*irq_tbl;
+	int			total_irqs;
 	u8			mac_addr[ETH_ALEN];
 
+#ifdef CONFIG_BNXT_DCB
+	struct ieee_pfc		*ieee_pfc;
+	struct ieee_ets		*ieee_ets;
+	u8			dcbx_cap;
+	u8			default_pri;
+#endif /* CONFIG_BNXT_DCB */
+
 	u32			msg_enable;
 
 	u32			hwrm_spec_code;
@@ -1089,6 +1108,7 @@ struct bnxt {
 #define BNXT_RESET_TASK_SILENT_SP_EVENT	11
 #define BNXT_GENEVE_ADD_PORT_SP_EVENT	12
 #define BNXT_GENEVE_DEL_PORT_SP_EVENT	13
+#define BNXT_LINK_SPEED_CHNG_SP_EVENT	14
 
 	struct bnxt_pf_info	pf;
 #ifdef CONFIG_BNXT_SRIOV
@@ -1114,6 +1134,13 @@ struct bnxt {
 	u32			lpi_tmr_hi;
 };
 
+#define BNXT_RX_STATS_OFFSET(counter)			\
+	(offsetof(struct rx_port_stats, counter) / 8)
+
+#define BNXT_TX_STATS_OFFSET(counter)			\
+	((offsetof(struct tx_port_stats, counter) +	\
+	  sizeof(struct rx_port_stats) + 512) / 8)
+
 #ifdef CONFIG_NET_RX_BUSY_POLL
 static inline void bnxt_enable_poll(struct bnxt_napi *bnapi)
 {
@@ -1216,12 +1243,23 @@ void bnxt_hwrm_cmd_hdr_init(struct bnxt
 int _hwrm_send_message(struct bnxt *, void *, u32, int);
 int hwrm_send_message(struct bnxt *, void *, u32, int);
 int hwrm_send_message_silent(struct bnxt *, void *, u32, int);
+int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap,
+				     int bmap_size);
+int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id);
 int bnxt_hwrm_set_coal(struct bnxt *);
-int bnxt_hwrm_func_qcaps(struct bnxt *);
+unsigned int bnxt_get_max_func_stat_ctxs(struct bnxt *bp);
+void bnxt_set_max_func_stat_ctxs(struct bnxt *bp, unsigned int max);
+unsigned int bnxt_get_max_func_cp_rings(struct bnxt *bp);
+void bnxt_set_max_func_cp_rings(struct bnxt *bp, unsigned int max);
+void bnxt_set_max_func_irqs(struct bnxt *bp, unsigned int max);
+void bnxt_tx_disable(struct bnxt *bp);
+void bnxt_tx_enable(struct bnxt *bp);
 int bnxt_hwrm_set_pause(struct bnxt *);
 int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool);
 int bnxt_hwrm_fw_set_time(struct bnxt *);
 int bnxt_open_nic(struct bnxt *, bool, bool);
 int bnxt_close_nic(struct bnxt *, bool, bool);
+int bnxt_setup_mq_tc(struct net_device *dev, u8 tc);
 int bnxt_get_max_rings(struct bnxt *, int *, int *, bool);
+void bnxt_restore_pf_fw_resources(struct bnxt *bp);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,7 @@
 /* Broadcom NetXtreme-C/E network driver.
  *
  * Copyright (c) 2014-2016 Broadcom Corporation
+ * Copyright (c) 2016 Broadcom 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
@@ -10,29 +11,22 @@
 #ifndef BNXT_HSI_H
 #define BNXT_HSI_H
 
-/* per-context HW statistics -- chip view */
-struct ctx_hw_stats  {
-	__le64 rx_ucast_pkts;
-	__le64 rx_mcast_pkts;
-	__le64 rx_bcast_pkts;
-	__le64 rx_discard_pkts;
-	__le64 rx_drop_pkts;
-	__le64 rx_ucast_bytes;
-	__le64 rx_mcast_bytes;
-	__le64 rx_bcast_bytes;
-	__le64 tx_ucast_pkts;
-	__le64 tx_mcast_pkts;
-	__le64 tx_bcast_pkts;
-	__le64 tx_discard_pkts;
-	__le64 tx_drop_pkts;
-	__le64 tx_ucast_bytes;
-	__le64 tx_mcast_bytes;
-	__le64 tx_bcast_bytes;
-	__le64 tpa_pkts;
-	__le64 tpa_bytes;
-	__le64 tpa_events;
-	__le64 tpa_aborts;
-};
+/* HSI and HWRM Specification 1.6.0 */
+#define HWRM_VERSION_MAJOR	1
+#define HWRM_VERSION_MINOR	6
+#define HWRM_VERSION_UPDATE	0
+
+#define HWRM_VERSION_STR	"1.6.0"
+/*
+ * Following is the signature for HWRM message field that indicates not
+ * applicable (All F's). Need to cast it the size of the field if needed.
+ */
+#define HWRM_NA_SIGNATURE	((__le32)(-1))
+#define HWRM_MAX_REQ_LEN    (128)  /* hwrm_func_buf_rgtr */
+#define HWRM_MAX_RESP_LEN    (176)  /* hwrm_func_qstats */
+#define HW_HASH_INDEX_SIZE      0x80    /* 7 bit indirection table index. */
+#define HW_HASH_KEY_SIZE	40
+#define HWRM_RESP_VALID_KEY      1 /* valid key for HWRM response */
 
 /* Statistics Ejection Buffer Completion Record (16 bytes) */
 struct eject_cmpl {
@@ -50,77 +44,77 @@ struct eject_cmpl {
 /* HWRM Completion Record (16 bytes) */
 struct hwrm_cmpl {
 	__le16 type;
-	#define HWRM_CMPL_TYPE_MASK				    0x3fUL
-	#define HWRM_CMPL_TYPE_SFT				    0
-	#define HWRM_CMPL_TYPE_HWRM_DONE			   0x20UL
+	#define CMPL_TYPE_MASK					    0x3fUL
+	#define CMPL_TYPE_SFT					    0
+	#define CMPL_TYPE_HWRM_DONE				   0x20UL
 	__le16 sequence_id;
 	__le32 unused_1;
 	__le32 v;
-	#define HWRM_CMPL_V					    0x1UL
+	#define CMPL_V						    0x1UL
 	__le32 unused_3;
 };
 
 /* HWRM Forwarded Request (16 bytes) */
 struct hwrm_fwd_req_cmpl {
 	__le16 req_len_type;
-	#define HWRM_FWD_REQ_CMPL_TYPE_MASK			    0x3fUL
-	#define HWRM_FWD_REQ_CMPL_TYPE_SFT			    0
-	#define HWRM_FWD_REQ_CMPL_TYPE_HWRM_FWD_REQ		   0x22UL
-	#define HWRM_FWD_REQ_CMPL_REQ_LEN_MASK			    0xffc0UL
-	#define HWRM_FWD_REQ_CMPL_REQ_LEN_SFT			    6
+	#define FWD_REQ_CMPL_TYPE_MASK				    0x3fUL
+	#define FWD_REQ_CMPL_TYPE_SFT				    0
+	#define FWD_REQ_CMPL_TYPE_HWRM_FWD_REQ			   0x22UL
+	#define FWD_REQ_CMPL_REQ_LEN_MASK			    0xffc0UL
+	#define FWD_REQ_CMPL_REQ_LEN_SFT			    6
 	__le16 source_id;
 	__le32 unused_0;
 	__le32 req_buf_addr_v[2];
-	#define HWRM_FWD_REQ_CMPL_V				    0x1UL
-	#define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_MASK		    0xfffffffeUL
-	#define HWRM_FWD_REQ_CMPL_REQ_BUF_ADDR_SFT		    1
+	#define FWD_REQ_CMPL_V					    0x1UL
+	#define FWD_REQ_CMPL_REQ_BUF_ADDR_MASK			    0xfffffffeUL
+	#define FWD_REQ_CMPL_REQ_BUF_ADDR_SFT			    1
 };
 
 /* HWRM Forwarded Response (16 bytes) */
 struct hwrm_fwd_resp_cmpl {
 	__le16 type;
-	#define HWRM_FWD_RESP_CMPL_TYPE_MASK			    0x3fUL
-	#define HWRM_FWD_RESP_CMPL_TYPE_SFT			    0
-	#define HWRM_FWD_RESP_CMPL_TYPE_HWRM_FWD_RESP		   0x24UL
+	#define FWD_RESP_CMPL_TYPE_MASK			    0x3fUL
+	#define FWD_RESP_CMPL_TYPE_SFT				    0
+	#define FWD_RESP_CMPL_TYPE_HWRM_FWD_RESP		   0x24UL
 	__le16 source_id;
 	__le16 resp_len;
 	__le16 unused_1;
 	__le32 resp_buf_addr_v[2];
-	#define HWRM_FWD_RESP_CMPL_V				    0x1UL
-	#define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_MASK		    0xfffffffeUL
-	#define HWRM_FWD_RESP_CMPL_RESP_BUF_ADDR_SFT		    1
+	#define FWD_RESP_CMPL_V				    0x1UL
+	#define FWD_RESP_CMPL_RESP_BUF_ADDR_MASK		    0xfffffffeUL
+	#define FWD_RESP_CMPL_RESP_BUF_ADDR_SFT		    1
 };
 
 /* HWRM Asynchronous Event Completion Record (16 bytes) */
 struct hwrm_async_event_cmpl {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_TYPE_MASK		    0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_TYPE_SFT			    0
-	#define HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT       0x2eUL
+	#define ASYNC_EVENT_CMPL_TYPE_MASK			    0x3fUL
+	#define ASYNC_EVENT_CMPL_TYPE_SFT			    0
+	#define ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT		   0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE 0x0UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE  0x2UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE  0x3UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED 0x4UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE 0x7UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD   0x10UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD     0x11UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT 0x12UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD     0x20UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD       0x21UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR		   0x30UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE 0x31UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE      0x33UL
-	#define HWRM_ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR	   0xffUL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE      0x0UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_LINK_MTU_CHANGE	   0x1UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE       0x2UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_DCB_CONFIG_CHANGE       0x3UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED   0x4UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE   0x6UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE     0x7UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_UNLOAD	   0x10UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_DRVR_LOAD	   0x11UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_FUNC_FLR_PROC_CMPLT     0x12UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD	   0x20UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_LOAD		   0x21UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_VF_FLR		   0x30UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_VF_MAC_ADDR_CHANGE      0x31UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE	   0x33UL
+	#define ASYNC_EVENT_CMPL_EVENT_ID_HWRM_ERROR		   0xffUL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_V			    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_OPAQUE_MASK		    0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_OPAQUE_SFT		    1
+	#define ASYNC_EVENT_CMPL_V				    0x1UL
+	#define ASYNC_EVENT_CMPL_OPAQUE_MASK			    0xfeUL
+	#define ASYNC_EVENT_CMPL_OPAQUE_SFT			    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
@@ -129,670 +123,391 @@ struct hwrm_async_event_cmpl {
 /* HWRM Asynchronous Event Completion Record for link status change (16 bytes) */
 struct hwrm_async_event_cmpl_link_status_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_MASK 0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_SFT  0
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_MASK      0x3fUL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_SFT       0
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE 0x0UL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_ID_LINK_STATUS_CHANGE 0x0UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_V	    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_MASK    0xfeUL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_OPAQUE_SFT     1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE 0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_DOWN (0x0UL << 0)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP (0x1UL << 0)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_LAST    HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_MASK 0xeUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_SFT 1
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_SFT 4
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE 0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_DOWN (0x0UL << 0)
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP (0x1UL << 0)
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_LAST    ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_LINK_CHANGE_UP
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_MASK 0xeUL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_SFT 1
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0UL
+	#define ASYNC_EVENT_CMPL_LINK_STATUS_CHANGE_EVENT_DATA1_PORT_ID_SFT 4
 };
 
 /* HWRM Asynchronous Event Completion Record for link MTU change (16 bytes) */
 struct hwrm_async_event_cmpl_link_mtu_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_MASK    0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_SFT     0
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_MASK	    0x3fUL
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_SFT	    0
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE 0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_ID_LINK_MTU_CHANGE 0x1UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_V	    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_MASK  0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_SFT   1
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_MASK       0xfeUL
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_OPAQUE_SFT	    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_SFT 0
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_LINK_MTU_CHANGE_EVENT_DATA1_NEW_MTU_SFT 0
 };
 
 /* HWRM Asynchronous Event Completion Record for link speed change (16 bytes) */
 struct hwrm_async_event_cmpl_link_speed_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_MASK  0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_SFT   0
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_MASK       0x3fUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_SFT	    0
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE 0x2UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_ID_LINK_SPEED_CHANGE 0x2UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_V	    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_MASK     0xfeUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_OPAQUE_SFT      1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_FORCE 0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_MASK 0xfffeUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_SFT 1
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100MB (0x1UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_1GB (0xaUL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2GB (0x14UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2_5GB (0x19UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10GB (0x64UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_20GB (0xc8UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (0xfaUL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (0x190UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (0x1f4UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB (0x3e8UL << 1)
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_LAST    HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0000UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_SFT 16
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_FORCE 0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_MASK 0xfffeUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_SFT 1
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100MB (0x1UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_1GB (0xaUL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2GB (0x14UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_2_5GB (0x19UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_10GB (0x64UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_20GB (0xc8UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_25GB (0xfaUL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_40GB (0x190UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_50GB (0x1f4UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB (0x3e8UL << 1)
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_LAST    ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_NEW_LINK_SPEED_100MBPS_100GB
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffff0000UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CHANGE_EVENT_DATA1_PORT_ID_SFT 16
 };
 
 /* HWRM Asynchronous Event Completion Record for DCB Config change (16 bytes) */
 struct hwrm_async_event_cmpl_dcb_config_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_MASK  0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_SFT   0
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_MASK       0x3fUL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_SFT	    0
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE 0x3UL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_ID_DCB_CONFIG_CHANGE 0x3UL
 	__le32 event_data2;
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA2_ETS 0x1UL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA2_PFC 0x2UL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA2_APP 0x4UL
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_V	    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_MASK     0xfeUL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_OPAQUE_SFT      1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_MASK 0xff0000UL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_SFT 16
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_NONE (0xffUL << 16)
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_LAST    ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_ROCE_PRIORITY_NONE
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_MASK 0xff000000UL
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_SFT 24
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_NONE (0xffUL << 24)
+	#define ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_LAST    ASYNC_EVENT_CMPL_DCB_CONFIG_CHANGE_EVENT_DATA1_RECOMMEND_L2_PRIORITY_NONE
 };
 
 /* HWRM Asynchronous Event Completion Record for port connection not allowed (16 bytes) */
 struct hwrm_async_event_cmpl_port_conn_not_allowed {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_MASK 0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_MASK   0x3fUL
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_SFT    0
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED 0x4UL
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_ID_PORT_CONN_NOT_ALLOWED 0x4UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_V      0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_V	    0x1UL
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_OPAQUE_SFT  1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK 0xff0000UL
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT 16
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_NONE (0x0UL << 16)
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_DISABLETX (0x1UL << 16)
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_WARNINGMSG (0x2UL << 16)
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN (0x3UL << 16)
-	#define HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_LAST    HWRM_ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_MASK 0xff0000UL
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_SFT 16
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_NONE (0x0UL << 16)
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_DISABLETX (0x1UL << 16)
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_WARNINGMSG (0x2UL << 16)
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN (0x3UL << 16)
+	#define ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_LAST    ASYNC_EVENT_CMPL_PORT_CONN_NOT_ALLOWED_EVENT_DATA1_ENFORCEMENT_POLICY_PWRDOWN
 };
 
 /* HWRM Asynchronous Event Completion Record for link speed config not allowed (16 bytes) */
 struct hwrm_async_event_cmpl_link_speed_cfg_not_allowed {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_MASK 0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_MASK 0x3fUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_SFT 0
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_ID_LINK_SPEED_CFG_NOT_ALLOWED 0x5UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_V 0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_V      0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_MASK 0xfeUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_OPAQUE_SFT 1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_NOT_ALLOWED_EVENT_DATA1_PORT_ID_SFT 0
 };
 
 /* HWRM Asynchronous Event Completion Record for link speed configuration change (16 bytes) */
 struct hwrm_async_event_cmpl_link_speed_cfg_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_MASK 0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_MASK   0x3fUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_SFT    0
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_ID_LINK_SPEED_CFG_CHANGE 0x6UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_V      0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_V	    0x1UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_MASK 0xfeUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_OPAQUE_SFT  1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_SUPPORTED_LINK_SPEEDS_CHANGE 0x10000UL
-	#define HWRM_ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_ILLEGAL_LINK_SPEED_CFG 0x20000UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_PORT_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_SUPPORTED_LINK_SPEEDS_CHANGE 0x10000UL
+	#define ASYNC_EVENT_CMPL_LINK_SPEED_CFG_CHANGE_EVENT_DATA1_ILLEGAL_LINK_SPEED_CFG 0x20000UL
 };
 
 /* HWRM Asynchronous Event Completion Record for Function Driver Unload (16 bytes) */
 struct hwrm_async_event_cmpl_func_drvr_unload {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_MASK   0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_SFT    0
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_MASK	    0x3fUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_SFT	    0
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_ID_FUNC_DRVR_UNLOAD 0x10UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_V	    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_SFT  1
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_MASK      0xfeUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_OPAQUE_SFT       1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
 };
 
 /* HWRM Asynchronous Event Completion Record for Function Driver load (16 bytes) */
 struct hwrm_async_event_cmpl_func_drvr_load {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_MASK     0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_SFT      0
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_MASK	    0x3fUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_SFT	    0
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD 0x11UL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_ID_FUNC_DRVR_LOAD 0x11UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_V		    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_MASK   0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_SFT    1
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_MASK	    0xfeUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_OPAQUE_SFT	    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_FUNC_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+};
+
+/* HWRM Asynchronous Event Completion Record to indicate completion of FLR related processing (16 bytes) */
+struct hwrm_async_event_cmpl_func_flr_proc_cmplt {
+	__le16 type;
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_MASK     0x3fUL
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_SFT      0
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	__le16 event_id;
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_ID_FUNC_FLR_PROC_CMPLT 0x12UL
+	__le32 event_data2;
+	u8 opaque_v;
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_MASK   0xfeUL
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_OPAQUE_SFT    1
+	u8 timestamp_lo;
+	__le16 timestamp_hi;
+	__le32 event_data1;
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_FUNC_FLR_PROC_CMPLT_EVENT_DATA1_FUNC_ID_SFT 0
 };
 
 /* HWRM Asynchronous Event Completion Record for PF Driver Unload (16 bytes) */
 struct hwrm_async_event_cmpl_pf_drvr_unload {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_MASK     0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_SFT      0
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_MASK	    0x3fUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_SFT	    0
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD 0x20UL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_ID_PF_DRVR_UNLOAD 0x20UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_V		    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_MASK   0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_SFT    1
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_MASK	    0xfeUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_OPAQUE_SFT	    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_MASK 0x70000UL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_SFT 16
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_FUNC_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_MASK 0x70000UL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_UNLOAD_EVENT_DATA1_PORT_SFT 16
 };
 
 /* HWRM Asynchronous Event Completion Record for PF Driver load (16 bytes) */
 struct hwrm_async_event_cmpl_pf_drvr_load {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_MASK       0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_SFT	    0
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_MASK	    0x3fUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_SFT		    0
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD 0x21UL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_ID_PF_DRVR_LOAD 0x21UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_V		    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_MASK     0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_SFT      1
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_MASK	    0xfeUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_OPAQUE_SFT	    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_MASK 0x70000UL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_SFT 16
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_FUNC_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_MASK 0x70000UL
+	#define ASYNC_EVENT_CMPL_PF_DRVR_LOAD_EVENT_DATA1_PORT_SFT 16
 };
 
 /* HWRM Asynchronous Event Completion Record for VF FLR (16 bytes) */
 struct hwrm_async_event_cmpl_vf_flr {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_MASK		    0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_SFT		    0
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_VF_FLR_TYPE_MASK		    0x3fUL
+	#define ASYNC_EVENT_CMPL_VF_FLR_TYPE_SFT		    0
+	#define ASYNC_EVENT_CMPL_VF_FLR_TYPE_HWRM_ASYNC_EVENT     0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR      0x30UL
+	#define ASYNC_EVENT_CMPL_VF_FLR_EVENT_ID_VF_FLR	   0x30UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_V			    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_MASK	    0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_SFT	    1
+	#define ASYNC_EVENT_CMPL_VF_FLR_V			    0x1UL
+	#define ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_MASK		    0xfeUL
+	#define ASYNC_EVENT_CMPL_VF_FLR_OPAQUE_SFT		    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_MASK     0xffffUL
+	#define ASYNC_EVENT_CMPL_VF_FLR_EVENT_DATA1_VF_ID_SFT      0
 };
 
 /* HWRM Asynchronous Event Completion Record for VF MAC Addr change (16 bytes) */
 struct hwrm_async_event_cmpl_vf_mac_addr_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_MASK 0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_SFT  0
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_MASK      0x3fUL
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_SFT       0
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE 0x31UL
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_ID_VF_MAC_ADDR_CHANGE 0x31UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_V	    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_MASK    0xfeUL
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_OPAQUE_SFT     1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_MASK 0xffffUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_MASK 0xffffUL
+	#define ASYNC_EVENT_CMPL_VF_MAC_ADDR_CHANGE_EVENT_DATA1_VF_ID_SFT 0
 };
 
 /* HWRM Asynchronous Event Completion Record for PF-VF communication status change (16 bytes) */
 struct hwrm_async_event_cmpl_pf_vf_comm_status_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_MASK 0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_MASK 0x3fUL
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_SFT 0
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_ID_PF_VF_COMM_STATUS_CHANGE 0x32UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_V   0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_MASK 0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_SFT 1
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_V	    0x1UL
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_MASK 0xfeUL
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_OPAQUE_SFT 1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_DATA1_COMM_ESTABLISHED 0x1UL
+	#define ASYNC_EVENT_CMPL_PF_VF_COMM_STATUS_CHANGE_EVENT_DATA1_COMM_ESTABLISHED 0x1UL
 };
 
 /* HWRM Asynchronous Event Completion Record for VF configuration change (16 bytes) */
 struct hwrm_async_event_cmpl_vf_cfg_change {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_MASK      0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_SFT       0
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_MASK	    0x3fUL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_SFT	    0
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_ID_VF_CFG_CHANGE 0x33UL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_ID_VF_CFG_CHANGE 0x33UL
 	__le32 event_data2;
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_V		    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_MASK    0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_SFT     1
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_V		    0x1UL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_MASK	    0xfeUL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_OPAQUE_SFT	    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MTU_CHANGE 0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MRU_CHANGE 0x2UL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_MAC_ADDR_CHANGE 0x4UL
-	#define HWRM_ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_VLAN_CHANGE 0x8UL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MTU_CHANGE 0x1UL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_MRU_CHANGE 0x2UL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_MAC_ADDR_CHANGE 0x4UL
+	#define ASYNC_EVENT_CMPL_VF_CFG_CHANGE_EVENT_DATA1_DFLT_VLAN_CHANGE 0x8UL
 };
 
 /* HWRM Asynchronous Event Completion Record for HWRM Error (16 bytes) */
 struct hwrm_async_event_cmpl_hwrm_error {
 	__le16 type;
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_MASK	    0x3fUL
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_SFT	    0
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_HWRM_ASYNC_EVENT 0x2eUL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_MASK		    0x3fUL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_SFT		    0
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_TYPE_HWRM_ASYNC_EVENT 0x2eUL
 	__le16 event_id;
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR 0xffUL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_ID_HWRM_ERROR   0xffUL
 	__le32 event_data2;
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_MASK 0xffUL
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_SFT 0
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING 0x0UL
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL 0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL 0x2UL
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_LAST    HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_MASK 0xffUL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_SFT 0
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_WARNING 0x0UL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_NONFATAL 0x1UL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL 0x2UL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_LAST    ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA2_SEVERITY_FATAL
 	u8 opaque_v;
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_V		    0x1UL
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK       0xfeUL
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_SFT	    1
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_V			    0x1UL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_MASK	    0xfeUL
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_OPAQUE_SFT		    1
 	u8 timestamp_lo;
 	__le16 timestamp_hi;
 	__le32 event_data1;
-	#define HWRM_ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP 0x1UL
-};
-
-/* HW Resource Manager Specification 1.5.1 */
-#define HWRM_VERSION_MAJOR	1
-#define HWRM_VERSION_MINOR	5
-#define HWRM_VERSION_UPDATE	1
-
-#define HWRM_VERSION_STR	"1.5.1"
-/*
- * Following is the signature for HWRM message field that indicates not
- * applicable (All F's). Need to cast it the size of the field if needed.
- */
-#define HWRM_NA_SIGNATURE	((__le32)(-1))
-#define HWRM_MAX_REQ_LEN    (128)  /* hwrm_func_buf_rgtr */
-#define HWRM_MAX_RESP_LEN    (176)  /* hwrm_func_qstats */
-#define HW_HASH_INDEX_SIZE      0x80    /* 7 bit indirection table index. */
-#define HW_HASH_KEY_SIZE	40
-#define HWRM_RESP_VALID_KEY      1 /* valid key for HWRM response */
-/* Input (16 bytes) */
-struct input {
-	__le16 req_type;
-	__le16 cmpl_ring;
-	__le16 seq_id;
-	__le16 target_id;
-	__le64 resp_addr;
-};
-
-/* Output (8 bytes) */
-struct output {
-	__le16 error_code;
-	__le16 req_type;
-	__le16 seq_id;
-	__le16 resp_len;
-};
-
-/* Command numbering (8 bytes) */
-struct cmd_nums {
-	__le16 req_type;
-	#define HWRM_VER_GET					   (0x0UL)
-	#define HWRM_FUNC_BUF_UNRGTR				   (0xeUL)
-	#define HWRM_FUNC_VF_CFG				   (0xfUL)
-	#define RESERVED1					   (0x10UL)
-	#define HWRM_FUNC_RESET				   (0x11UL)
-	#define HWRM_FUNC_GETFID				   (0x12UL)
-	#define HWRM_FUNC_VF_ALLOC				   (0x13UL)
-	#define HWRM_FUNC_VF_FREE				   (0x14UL)
-	#define HWRM_FUNC_QCAPS				   (0x15UL)
-	#define HWRM_FUNC_QCFG					   (0x16UL)
-	#define HWRM_FUNC_CFG					   (0x17UL)
-	#define HWRM_FUNC_QSTATS				   (0x18UL)
-	#define HWRM_FUNC_CLR_STATS				   (0x19UL)
-	#define HWRM_FUNC_DRV_UNRGTR				   (0x1aUL)
-	#define HWRM_FUNC_VF_RESC_FREE				   (0x1bUL)
-	#define HWRM_FUNC_VF_VNIC_IDS_QUERY			   (0x1cUL)
-	#define HWRM_FUNC_DRV_RGTR				   (0x1dUL)
-	#define HWRM_FUNC_DRV_QVER				   (0x1eUL)
-	#define HWRM_FUNC_BUF_RGTR				   (0x1fUL)
-	#define HWRM_PORT_PHY_CFG				   (0x20UL)
-	#define HWRM_PORT_MAC_CFG				   (0x21UL)
-	#define HWRM_PORT_TS_QUERY				   (0x22UL)
-	#define HWRM_PORT_QSTATS				   (0x23UL)
-	#define HWRM_PORT_LPBK_QSTATS				   (0x24UL)
-	#define HWRM_PORT_CLR_STATS				   (0x25UL)
-	#define HWRM_PORT_LPBK_CLR_STATS			   (0x26UL)
-	#define HWRM_PORT_PHY_QCFG				   (0x27UL)
-	#define HWRM_PORT_MAC_QCFG				   (0x28UL)
-	#define HWRM_PORT_BLINK_LED				   (0x29UL)
-	#define HWRM_PORT_PHY_QCAPS				   (0x2aUL)
-	#define HWRM_PORT_PHY_I2C_WRITE			   (0x2bUL)
-	#define HWRM_PORT_PHY_I2C_READ				   (0x2cUL)
-	#define HWRM_QUEUE_QPORTCFG				   (0x30UL)
-	#define HWRM_QUEUE_QCFG				   (0x31UL)
-	#define HWRM_QUEUE_CFG					   (0x32UL)
-	#define RESERVED2					   (0x33UL)
-	#define RESERVED3					   (0x34UL)
-	#define HWRM_QUEUE_PFCENABLE_QCFG			   (0x35UL)
-	#define HWRM_QUEUE_PFCENABLE_CFG			   (0x36UL)
-	#define HWRM_QUEUE_PRI2COS_QCFG			   (0x37UL)
-	#define HWRM_QUEUE_PRI2COS_CFG				   (0x38UL)
-	#define HWRM_QUEUE_COS2BW_QCFG				   (0x39UL)
-	#define HWRM_QUEUE_COS2BW_CFG				   (0x3aUL)
-	#define HWRM_VNIC_ALLOC				   (0x40UL)
-	#define HWRM_VNIC_FREE					   (0x41UL)
-	#define HWRM_VNIC_CFG					   (0x42UL)
-	#define HWRM_VNIC_QCFG					   (0x43UL)
-	#define HWRM_VNIC_TPA_CFG				   (0x44UL)
-	#define HWRM_VNIC_TPA_QCFG				   (0x45UL)
-	#define HWRM_VNIC_RSS_CFG				   (0x46UL)
-	#define HWRM_VNIC_RSS_QCFG				   (0x47UL)
-	#define HWRM_VNIC_PLCMODES_CFG				   (0x48UL)
-	#define HWRM_VNIC_PLCMODES_QCFG			   (0x49UL)
-	#define HWRM_VNIC_QCAPS				   (0x4aUL)
-	#define HWRM_RING_ALLOC				   (0x50UL)
-	#define HWRM_RING_FREE					   (0x51UL)
-	#define HWRM_RING_CMPL_RING_QAGGINT_PARAMS		   (0x52UL)
-	#define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS		   (0x53UL)
-	#define HWRM_RING_RESET				   (0x5eUL)
-	#define HWRM_RING_GRP_ALLOC				   (0x60UL)
-	#define HWRM_RING_GRP_FREE				   (0x61UL)
-	#define RESERVED5					   (0x64UL)
-	#define RESERVED6					   (0x65UL)
-	#define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC			   (0x70UL)
-	#define HWRM_VNIC_RSS_COS_LB_CTX_FREE			   (0x71UL)
-	#define HWRM_CFA_L2_FILTER_ALLOC			   (0x90UL)
-	#define HWRM_CFA_L2_FILTER_FREE			   (0x91UL)
-	#define HWRM_CFA_L2_FILTER_CFG				   (0x92UL)
-	#define HWRM_CFA_L2_SET_RX_MASK			   (0x93UL)
-	#define RESERVED4					   (0x94UL)
-	#define HWRM_CFA_TUNNEL_FILTER_ALLOC			   (0x95UL)
-	#define HWRM_CFA_TUNNEL_FILTER_FREE			   (0x96UL)
-	#define HWRM_CFA_ENCAP_RECORD_ALLOC			   (0x97UL)
-	#define HWRM_CFA_ENCAP_RECORD_FREE			   (0x98UL)
-	#define HWRM_CFA_NTUPLE_FILTER_ALLOC			   (0x99UL)
-	#define HWRM_CFA_NTUPLE_FILTER_FREE			   (0x9aUL)
-	#define HWRM_CFA_NTUPLE_FILTER_CFG			   (0x9bUL)
-	#define HWRM_CFA_EM_FLOW_ALLOC				   (0x9cUL)
-	#define HWRM_CFA_EM_FLOW_FREE				   (0x9dUL)
-	#define HWRM_CFA_EM_FLOW_CFG				   (0x9eUL)
-	#define HWRM_TUNNEL_DST_PORT_QUERY			   (0xa0UL)
-	#define HWRM_TUNNEL_DST_PORT_ALLOC			   (0xa1UL)
-	#define HWRM_TUNNEL_DST_PORT_FREE			   (0xa2UL)
-	#define HWRM_STAT_CTX_ALLOC				   (0xb0UL)
-	#define HWRM_STAT_CTX_FREE				   (0xb1UL)
-	#define HWRM_STAT_CTX_QUERY				   (0xb2UL)
-	#define HWRM_STAT_CTX_CLR_STATS			   (0xb3UL)
-	#define HWRM_FW_RESET					   (0xc0UL)
-	#define HWRM_FW_QSTATUS				   (0xc1UL)
-	#define HWRM_FW_SET_TIME				   (0xc8UL)
-	#define HWRM_FW_GET_TIME				   (0xc9UL)
-	#define HWRM_EXEC_FWD_RESP				   (0xd0UL)
-	#define HWRM_REJECT_FWD_RESP				   (0xd1UL)
-	#define HWRM_FWD_RESP					   (0xd2UL)
-	#define HWRM_FWD_ASYNC_EVENT_CMPL			   (0xd3UL)
-	#define HWRM_TEMP_MONITOR_QUERY			   (0xe0UL)
-	#define HWRM_WOL_FILTER_ALLOC				   (0xf0UL)
-	#define HWRM_WOL_FILTER_FREE				   (0xf1UL)
-	#define HWRM_WOL_FILTER_QCFG				   (0xf2UL)
-	#define HWRM_WOL_REASON_QCFG				   (0xf3UL)
-	#define HWRM_DBG_READ_DIRECT				   (0xff10UL)
-	#define HWRM_DBG_READ_INDIRECT				   (0xff11UL)
-	#define HWRM_DBG_WRITE_DIRECT				   (0xff12UL)
-	#define HWRM_DBG_WRITE_INDIRECT			   (0xff13UL)
-	#define HWRM_DBG_DUMP					   (0xff14UL)
-	#define HWRM_NVM_INSTALL_UPDATE			   (0xfff3UL)
-	#define HWRM_NVM_MODIFY				   (0xfff4UL)
-	#define HWRM_NVM_VERIFY_UPDATE				   (0xfff5UL)
-	#define HWRM_NVM_GET_DEV_INFO				   (0xfff6UL)
-	#define HWRM_NVM_ERASE_DIR_ENTRY			   (0xfff7UL)
-	#define HWRM_NVM_MOD_DIR_ENTRY				   (0xfff8UL)
-	#define HWRM_NVM_FIND_DIR_ENTRY			   (0xfff9UL)
-	#define HWRM_NVM_GET_DIR_ENTRIES			   (0xfffaUL)
-	#define HWRM_NVM_GET_DIR_INFO				   (0xfffbUL)
-	#define HWRM_NVM_RAW_DUMP				   (0xfffcUL)
-	#define HWRM_NVM_READ					   (0xfffdUL)
-	#define HWRM_NVM_WRITE					   (0xfffeUL)
-	#define HWRM_NVM_RAW_WRITE_BLK				   (0xffffUL)
-	__le16 unused_0[3];
-};
-
-/* Return Codes (8 bytes) */
-struct ret_codes {
-	__le16 error_code;
-	#define HWRM_ERR_CODE_SUCCESS				   (0x0UL)
-	#define HWRM_ERR_CODE_FAIL				   (0x1UL)
-	#define HWRM_ERR_CODE_INVALID_PARAMS			   (0x2UL)
-	#define HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED		   (0x3UL)
-	#define HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR		   (0x4UL)
-	#define HWRM_ERR_CODE_INVALID_FLAGS			   (0x5UL)
-	#define HWRM_ERR_CODE_INVALID_ENABLES			   (0x6UL)
-	#define HWRM_ERR_CODE_HWRM_ERROR			   (0xfUL)
-	#define HWRM_ERR_CODE_UNKNOWN_ERR			   (0xfffeUL)
-	#define HWRM_ERR_CODE_CMD_NOT_SUPPORTED		   (0xffffUL)
-	__le16 unused_0[3];
-};
-
-/* Output (16 bytes) */
-struct hwrm_err_output {
-	__le16 error_code;
-	__le16 req_type;
-	__le16 seq_id;
-	__le16 resp_len;
-	__le32 opaque_0;
-	__le16 opaque_1;
-	u8 cmd_err;
-	u8 valid;
-};
-
-/* Port Tx Statistics Formats (408 bytes) */
-struct tx_port_stats {
-	__le64 tx_64b_frames;
-	__le64 tx_65b_127b_frames;
-	__le64 tx_128b_255b_frames;
-	__le64 tx_256b_511b_frames;
-	__le64 tx_512b_1023b_frames;
-	__le64 tx_1024b_1518_frames;
-	__le64 tx_good_vlan_frames;
-	__le64 tx_1519b_2047_frames;
-	__le64 tx_2048b_4095b_frames;
-	__le64 tx_4096b_9216b_frames;
-	__le64 tx_9217b_16383b_frames;
-	__le64 tx_good_frames;
-	__le64 tx_total_frames;
-	__le64 tx_ucast_frames;
-	__le64 tx_mcast_frames;
-	__le64 tx_bcast_frames;
-	__le64 tx_pause_frames;
-	__le64 tx_pfc_frames;
-	__le64 tx_jabber_frames;
-	__le64 tx_fcs_err_frames;
-	__le64 tx_control_frames;
-	__le64 tx_oversz_frames;
-	__le64 tx_single_dfrl_frames;
-	__le64 tx_multi_dfrl_frames;
-	__le64 tx_single_coll_frames;
-	__le64 tx_multi_coll_frames;
-	__le64 tx_late_coll_frames;
-	__le64 tx_excessive_coll_frames;
-	__le64 tx_frag_frames;
-	__le64 tx_err;
-	__le64 tx_tagged_frames;
-	__le64 tx_dbl_tagged_frames;
-	__le64 tx_runt_frames;
-	__le64 tx_fifo_underruns;
-	__le64 tx_pfc_ena_frames_pri0;
-	__le64 tx_pfc_ena_frames_pri1;
-	__le64 tx_pfc_ena_frames_pri2;
-	__le64 tx_pfc_ena_frames_pri3;
-	__le64 tx_pfc_ena_frames_pri4;
-	__le64 tx_pfc_ena_frames_pri5;
-	__le64 tx_pfc_ena_frames_pri6;
-	__le64 tx_pfc_ena_frames_pri7;
-	__le64 tx_eee_lpi_events;
-	__le64 tx_eee_lpi_duration;
-	__le64 tx_llfc_logical_msgs;
-	__le64 tx_hcfc_msgs;
-	__le64 tx_total_collisions;
-	__le64 tx_bytes;
-	__le64 tx_xthol_frames;
-	__le64 tx_stat_discard;
-	__le64 tx_stat_error;
-};
-
-/* Port Rx Statistics Formats (528 bytes) */
-struct rx_port_stats {
-	__le64 rx_64b_frames;
-	__le64 rx_65b_127b_frames;
-	__le64 rx_128b_255b_frames;
-	__le64 rx_256b_511b_frames;
-	__le64 rx_512b_1023b_frames;
-	__le64 rx_1024b_1518_frames;
-	__le64 rx_good_vlan_frames;
-	__le64 rx_1519b_2047b_frames;
-	__le64 rx_2048b_4095b_frames;
-	__le64 rx_4096b_9216b_frames;
-	__le64 rx_9217b_16383b_frames;
-	__le64 rx_total_frames;
-	__le64 rx_ucast_frames;
-	__le64 rx_mcast_frames;
-	__le64 rx_bcast_frames;
-	__le64 rx_fcs_err_frames;
-	__le64 rx_ctrl_frames;
-	__le64 rx_pause_frames;
-	__le64 rx_pfc_frames;
-	__le64 rx_unsupported_opcode_frames;
-	__le64 rx_unsupported_da_pausepfc_frames;
-	__le64 rx_wrong_sa_frames;
-	__le64 rx_align_err_frames;
-	__le64 rx_oor_len_frames;
-	__le64 rx_code_err_frames;
-	__le64 rx_false_carrier_frames;
-	__le64 rx_ovrsz_frames;
-	__le64 rx_jbr_frames;
-	__le64 rx_mtu_err_frames;
-	__le64 rx_match_crc_frames;
-	__le64 rx_promiscuous_frames;
-	__le64 rx_tagged_frames;
-	__le64 rx_double_tagged_frames;
-	__le64 rx_trunc_frames;
-	__le64 rx_good_frames;
-	__le64 rx_pfc_xon2xoff_frames_pri0;
-	__le64 rx_pfc_xon2xoff_frames_pri1;
-	__le64 rx_pfc_xon2xoff_frames_pri2;
-	__le64 rx_pfc_xon2xoff_frames_pri3;
-	__le64 rx_pfc_xon2xoff_frames_pri4;
-	__le64 rx_pfc_xon2xoff_frames_pri5;
-	__le64 rx_pfc_xon2xoff_frames_pri6;
-	__le64 rx_pfc_xon2xoff_frames_pri7;
-	__le64 rx_pfc_ena_frames_pri0;
-	__le64 rx_pfc_ena_frames_pri1;
-	__le64 rx_pfc_ena_frames_pri2;
-	__le64 rx_pfc_ena_frames_pri3;
-	__le64 rx_pfc_ena_frames_pri4;
-	__le64 rx_pfc_ena_frames_pri5;
-	__le64 rx_pfc_ena_frames_pri6;
-	__le64 rx_pfc_ena_frames_pri7;
-	__le64 rx_sch_crc_err_frames;
-	__le64 rx_undrsz_frames;
-	__le64 rx_frag_frames;
-	__le64 rx_eee_lpi_events;
-	__le64 rx_eee_lpi_duration;
-	__le64 rx_llfc_physical_msgs;
-	__le64 rx_llfc_logical_msgs;
-	__le64 rx_llfc_msgs_with_crc_err;
-	__le64 rx_hcfc_msgs;
-	__le64 rx_hcfc_msgs_with_crc_err;
-	__le64 rx_bytes;
-	__le64 rx_runt_bytes;
-	__le64 rx_runt_frames;
-	__le64 rx_stat_discard;
-	__le64 rx_stat_err;
+	#define ASYNC_EVENT_CMPL_HWRM_ERROR_EVENT_DATA1_TIMESTAMP  0x1UL
 };
 
 /* hwrm_ver_get */
@@ -1041,6 +756,7 @@ struct hwrm_func_qcaps_output {
 	#define FUNC_QCAPS_RESP_FLAGS_TX_BW_CFG_SUPPORTED	    0x100UL
 	#define FUNC_QCAPS_RESP_FLAGS_VF_TX_RING_RL_SUPPORTED      0x200UL
 	#define FUNC_QCAPS_RESP_FLAGS_VF_BW_CFG_SUPPORTED	    0x400UL
+	#define FUNC_QCAPS_RESP_FLAGS_STD_TX_RING_MODE_SUPPORTED   0x800UL
 	u8 mac_address[6];
 	__le16 max_rsscos_ctx;
 	__le16 max_cmpl_rings;
@@ -1090,6 +806,7 @@ struct hwrm_func_qcfg_output {
 	#define FUNC_QCFG_RESP_FLAGS_OOB_WOL_MAGICPKT_ENABLED      0x1UL
 	#define FUNC_QCFG_RESP_FLAGS_OOB_WOL_BMP_ENABLED	    0x2UL
 	#define FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED	    0x4UL
+	#define FUNC_QCFG_RESP_FLAGS_STD_TX_RING_MODE_ENABLED      0x8UL
 	u8 mac_address[6];
 	__le16 pci_id;
 	__le16 alloc_rsscos_ctx;
@@ -1166,6 +883,7 @@ struct hwrm_func_cfg_input {
 	#define FUNC_CFG_REQ_FLAGS_DISABLE_STP			    0x40UL
 	#define FUNC_CFG_REQ_FLAGS_DISABLE_LLDP		    0x80UL
 	#define FUNC_CFG_REQ_FLAGS_DISABLE_PTPV2		    0x100UL
+	#define FUNC_CFG_REQ_FLAGS_STD_TX_RING_MODE		    0x200UL
 	__le32 enables;
 	#define FUNC_CFG_REQ_ENABLES_MTU			    0x1UL
 	#define FUNC_CFG_REQ_ENABLES_MRU			    0x2UL
@@ -1399,6 +1117,7 @@ struct hwrm_func_drv_rgtr_input {
 	#define FUNC_DRV_RGTR_REQ_OS_TYPE_ESXI			   0x68UL
 	#define FUNC_DRV_RGTR_REQ_OS_TYPE_WIN864		   0x73UL
 	#define FUNC_DRV_RGTR_REQ_OS_TYPE_WIN2012R2		   0x74UL
+	#define FUNC_DRV_RGTR_REQ_OS_TYPE_UEFI			   0x8000UL
 	u8 ver_maj;
 	u8 ver_min;
 	u8 ver_upd;
@@ -1531,6 +1250,7 @@ struct hwrm_func_drv_qver_output {
 	#define FUNC_DRV_QVER_RESP_OS_TYPE_ESXI		   0x68UL
 	#define FUNC_DRV_QVER_RESP_OS_TYPE_WIN864		   0x73UL
 	#define FUNC_DRV_QVER_RESP_OS_TYPE_WIN2012R2		   0x74UL
+	#define FUNC_DRV_QVER_RESP_OS_TYPE_UEFI		   0x8000UL
 	u8 ver_maj;
 	u8 ver_min;
 	u8 ver_upd;
@@ -1549,7 +1269,7 @@ struct hwrm_port_phy_cfg_input {
 	__le64 resp_addr;
 	__le32 flags;
 	#define PORT_PHY_CFG_REQ_FLAGS_RESET_PHY		    0x1UL
-	#define PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DOWN		    0x2UL
+	#define PORT_PHY_CFG_REQ_FLAGS_DEPRECATED		    0x2UL
 	#define PORT_PHY_CFG_REQ_FLAGS_FORCE			    0x4UL
 	#define PORT_PHY_CFG_REQ_FLAGS_RESTART_AUTONEG		    0x8UL
 	#define PORT_PHY_CFG_REQ_FLAGS_EEE_ENABLE		    0x10UL
@@ -1562,6 +1282,7 @@ struct hwrm_port_phy_cfg_input {
 	#define PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE	    0x800UL
 	#define PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE91_ENABLE	    0x1000UL
 	#define PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE91_DISABLE	    0x2000UL
+	#define PORT_PHY_CFG_REQ_FLAGS_FORCE_LINK_DWN		    0x4000UL
 	__le32 enables;
 	#define PORT_PHY_CFG_REQ_ENABLES_AUTO_MODE		    0x1UL
 	#define PORT_PHY_CFG_REQ_ENABLES_AUTO_DUPLEX		    0x2UL
@@ -2091,31 +1812,6 @@ struct hwrm_port_lpbk_clr_stats_output {
 	u8 valid;
 };
 
-/* hwrm_port_blink_led */
-/* Input (24 bytes) */
-struct hwrm_port_blink_led_input {
-	__le16 req_type;
-	__le16 cmpl_ring;
-	__le16 seq_id;
-	__le16 target_id;
-	__le64 resp_addr;
-	__le32 num_blinks;
-	__le32 unused_0;
-};
-
-/* Output (16 bytes) */
-struct hwrm_port_blink_led_output {
-	__le16 error_code;
-	__le16 req_type;
-	__le16 seq_id;
-	__le16 resp_len;
-	__le32 unused_0;
-	u8 unused_1;
-	u8 unused_2;
-	u8 unused_3;
-	u8 valid;
-};
-
 /* hwrm_port_phy_qcaps */
 /* Input (24 bytes) */
 struct hwrm_port_phy_qcaps_input {
@@ -2337,6 +2033,39 @@ struct hwrm_queue_cfg_output {
 	u8 valid;
 };
 
+/* hwrm_queue_pfcenable_qcfg */
+/* Input (24 bytes) */
+struct hwrm_queue_pfcenable_qcfg_input {
+	__le16 req_type;
+	__le16 cmpl_ring;
+	__le16 seq_id;
+	__le16 target_id;
+	__le64 resp_addr;
+	__le16 port_id;
+	__le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_queue_pfcenable_qcfg_output {
+	__le16 error_code;
+	__le16 req_type;
+	__le16 seq_id;
+	__le16 resp_len;
+	__le32 flags;
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI0_PFC_ENABLED   0x1UL
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI1_PFC_ENABLED   0x2UL
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI2_PFC_ENABLED   0x4UL
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI3_PFC_ENABLED   0x8UL
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI4_PFC_ENABLED   0x10UL
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI5_PFC_ENABLED   0x20UL
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI6_PFC_ENABLED   0x40UL
+	#define QUEUE_PFCENABLE_QCFG_RESP_FLAGS_PRI7_PFC_ENABLED   0x80UL
+	u8 unused_0;
+	u8 unused_1;
+	u8 unused_2;
+	u8 valid;
+};
+
 /* hwrm_queue_pfcenable_cfg */
 /* Input (24 bytes) */
 struct hwrm_queue_pfcenable_cfg_input {
@@ -2371,6 +2100,48 @@ struct hwrm_queue_pfcenable_cfg_output {
 	u8 valid;
 };
 
+/* hwrm_queue_pri2cos_qcfg */
+/* Input (24 bytes) */
+struct hwrm_queue_pri2cos_qcfg_input {
+	__le16 req_type;
+	__le16 cmpl_ring;
+	__le16 seq_id;
+	__le16 target_id;
+	__le64 resp_addr;
+	__le32 flags;
+	#define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH		    0x1UL
+	#define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_TX		   (0x0UL << 0)
+	#define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_RX		   (0x1UL << 0)
+	#define QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_LAST    QUEUE_PRI2COS_QCFG_REQ_FLAGS_PATH_RX
+	#define QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN		    0x2UL
+	u8 port_id;
+	u8 unused_0[3];
+};
+
+/* Output (24 bytes) */
+struct hwrm_queue_pri2cos_qcfg_output {
+	__le16 error_code;
+	__le16 req_type;
+	__le16 seq_id;
+	__le16 resp_len;
+	u8 pri0_cos_queue_id;
+	u8 pri1_cos_queue_id;
+	u8 pri2_cos_queue_id;
+	u8 pri3_cos_queue_id;
+	u8 pri4_cos_queue_id;
+	u8 pri5_cos_queue_id;
+	u8 pri6_cos_queue_id;
+	u8 pri7_cos_queue_id;
+	u8 queue_cfg_info;
+	#define QUEUE_PRI2COS_QCFG_RESP_QUEUE_CFG_INFO_ASYM_CFG    0x1UL
+	u8 unused_0;
+	__le16 unused_1;
+	u8 unused_2;
+	u8 unused_3;
+	u8 unused_4;
+	u8 valid;
+};
+
 /* hwrm_queue_pri2cos_cfg */
 /* Input (40 bytes) */
 struct hwrm_queue_pri2cos_cfg_input {
@@ -2421,6 +2192,257 @@ struct hwrm_queue_pri2cos_cfg_output {
 	u8 valid;
 };
 
+/* hwrm_queue_cos2bw_qcfg */
+/* Input (24 bytes) */
+struct hwrm_queue_cos2bw_qcfg_input {
+	__le16 req_type;
+	__le16 cmpl_ring;
+	__le16 seq_id;
+	__le16 target_id;
+	__le64 resp_addr;
+	__le16 port_id;
+	__le16 unused_0[3];
+};
+
+/* Output (112 bytes) */
+struct hwrm_queue_cos2bw_qcfg_output {
+	__le16 error_code;
+	__le16 req_type;
+	__le16 seq_id;
+	__le16 resp_len;
+	u8 queue_id0;
+	u8 unused_0;
+	__le16 unused_1;
+	__le32 queue_id0_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id0_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id0_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id0_pri_lvl;
+	u8 queue_id0_bw_weight;
+	u8 queue_id1;
+	__le32 queue_id1_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id1_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id1_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID1_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id1_pri_lvl;
+	u8 queue_id1_bw_weight;
+	u8 queue_id2;
+	__le32 queue_id2_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id2_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id2_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID2_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id2_pri_lvl;
+	u8 queue_id2_bw_weight;
+	u8 queue_id3;
+	__le32 queue_id3_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id3_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id3_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID3_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id3_pri_lvl;
+	u8 queue_id3_bw_weight;
+	u8 queue_id4;
+	__le32 queue_id4_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id4_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id4_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID4_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id4_pri_lvl;
+	u8 queue_id4_bw_weight;
+	u8 queue_id5;
+	__le32 queue_id5_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id5_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id5_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID5_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id5_pri_lvl;
+	u8 queue_id5_bw_weight;
+	u8 queue_id6;
+	__le32 queue_id6_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id6_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id6_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID6_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id6_pri_lvl;
+	u8 queue_id6_bw_weight;
+	u8 queue_id7;
+	__le32 queue_id7_min_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MIN_BW_BW_VALUE_UNIT_INVALID
+	__le32 queue_id7_max_bw;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_MASK 0xfffffffUL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_SFT 0
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_RSVD       0x10000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MASK 0xe0000000UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_SFT 29
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_MBPS (0x0UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_PERCENT1_100 (0x1UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID (0x7UL << 29)
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_LAST    QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_MAX_BW_BW_VALUE_UNIT_INVALID
+	u8 queue_id7_tsa_assign;
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_SP    0x0UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_ETS   0x1UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_RESERVED_FIRST 0x2UL
+	#define QUEUE_COS2BW_QCFG_RESP_QUEUE_ID7_TSA_ASSIGN_RESERVED_LAST 0xffUL
+	u8 queue_id7_pri_lvl;
+	u8 queue_id7_bw_weight;
+	u8 unused_2;
+	u8 unused_3;
+	u8 unused_4;
+	u8 unused_5;
+	u8 valid;
+};
+
 /* hwrm_queue_cos2bw_cfg */
 /* Input (128 bytes) */
 struct hwrm_queue_cos2bw_cfg_input {
@@ -3802,7 +3824,9 @@ struct hwrm_stat_ctx_alloc_input {
 	__le64 resp_addr;
 	__le64 stats_dma_addr;
 	__le32 update_period_ms;
-	__le32 unused_0;
+	u8 stat_ctx_flags;
+	#define STAT_CTX_ALLOC_REQ_STAT_CTX_FLAGS_ROCE		    0x1UL
+	u8 unused_0[3];
 };
 
 /* Output (16 bytes) */
@@ -4023,6 +4047,75 @@ struct hwrm_fw_set_time_output {
 	u8 valid;
 };
 
+/* hwrm_fw_set_structured_data */
+/* Input (32 bytes) */
+struct hwrm_fw_set_structured_data_input {
+	__le16 req_type;
+	__le16 cmpl_ring;
+	__le16 seq_id;
+	__le16 target_id;
+	__le64 resp_addr;
+	__le64 src_data_addr;
+	__le16 data_len;
+	u8 hdr_cnt;
+	u8 unused_0;
+	__le16 port_id;
+	__le16 unused_1;
+};
+
+/* Output (16 bytes) */
+struct hwrm_fw_set_structured_data_output {
+	__le16 error_code;
+	__le16 req_type;
+	__le16 seq_id;
+	__le16 resp_len;
+	__le32 unused_0;
+	u8 unused_1;
+	u8 unused_2;
+	u8 unused_3;
+	u8 valid;
+};
+
+/* hwrm_fw_get_structured_data */
+/* Input (40 bytes) */
+struct hwrm_fw_get_structured_data_input {
+	__le16 req_type;
+	__le16 cmpl_ring;
+	__le16 seq_id;
+	__le16 target_id;
+	__le64 resp_addr;
+	__le64 dest_data_addr;
+	__le16 data_len;
+	__le16 structure_id;
+	__le16 subtype;
+	#define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_ALL		   0xffffUL
+	#define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NEAR_BRIDGE_ADMIN 0x100UL
+	#define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NEAR_BRIDGE_PEER 0x101UL
+	#define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NEAR_BRIDGE_OPERATIONAL 0x102UL
+	#define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NON_TPMR_ADMIN 0x200UL
+	#define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NON_TPMR_PEER  0x201UL
+	#define FW_GET_STRUCTURED_DATA_REQ_SUBTYPE_NON_TPMR_OPERATIONAL 0x202UL
+	u8 count;
+	u8 unused_0;
+	__le16 port_id;
+	__le16 unused_1[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_fw_get_structured_data_output {
+	__le16 error_code;
+	__le16 req_type;
+	__le16 seq_id;
+	__le16 resp_len;
+	u8 hdr_cnt;
+	u8 unused_0;
+	__le16 unused_1;
+	u8 unused_2;
+	u8 unused_3;
+	u8 unused_4;
+	u8 valid;
+};
+
 /* hwrm_exec_fwd_resp */
 /* Input (128 bytes) */
 struct hwrm_exec_fwd_resp_input {
@@ -4515,4 +4608,363 @@ struct hwrm_nvm_install_update_output {
 	u8 valid;
 };
 
+/* Hardware Resource Manager Specification */
+/* Input (16 bytes) */
+struct input {
+	__le16 req_type;
+	__le16 cmpl_ring;
+	__le16 seq_id;
+	__le16 target_id;
+	__le64 resp_addr;
+};
+
+/* Output (8 bytes) */
+struct output {
+	__le16 error_code;
+	__le16 req_type;
+	__le16 seq_id;
+	__le16 resp_len;
+};
+
+/* Command numbering (8 bytes) */
+struct cmd_nums {
+	__le16 req_type;
+	#define HWRM_VER_GET					   (0x0UL)
+	#define HWRM_FUNC_BUF_UNRGTR				   (0xeUL)
+	#define HWRM_FUNC_VF_CFG				   (0xfUL)
+	#define RESERVED1					   (0x10UL)
+	#define HWRM_FUNC_RESET				   (0x11UL)
+	#define HWRM_FUNC_GETFID				   (0x12UL)
+	#define HWRM_FUNC_VF_ALLOC				   (0x13UL)
+	#define HWRM_FUNC_VF_FREE				   (0x14UL)
+	#define HWRM_FUNC_QCAPS				   (0x15UL)
+	#define HWRM_FUNC_QCFG					   (0x16UL)
+	#define HWRM_FUNC_CFG					   (0x17UL)
+	#define HWRM_FUNC_QSTATS				   (0x18UL)
+	#define HWRM_FUNC_CLR_STATS				   (0x19UL)
+	#define HWRM_FUNC_DRV_UNRGTR				   (0x1aUL)
+	#define HWRM_FUNC_VF_RESC_FREE				   (0x1bUL)
+	#define HWRM_FUNC_VF_VNIC_IDS_QUERY			   (0x1cUL)
+	#define HWRM_FUNC_DRV_RGTR				   (0x1dUL)
+	#define HWRM_FUNC_DRV_QVER				   (0x1eUL)
+	#define HWRM_FUNC_BUF_RGTR				   (0x1fUL)
+	#define HWRM_PORT_PHY_CFG				   (0x20UL)
+	#define HWRM_PORT_MAC_CFG				   (0x21UL)
+	#define HWRM_PORT_TS_QUERY				   (0x22UL)
+	#define HWRM_PORT_QSTATS				   (0x23UL)
+	#define HWRM_PORT_LPBK_QSTATS				   (0x24UL)
+	#define HWRM_PORT_CLR_STATS				   (0x25UL)
+	#define HWRM_PORT_LPBK_CLR_STATS			   (0x26UL)
+	#define HWRM_PORT_PHY_QCFG				   (0x27UL)
+	#define HWRM_PORT_MAC_QCFG				   (0x28UL)
+	#define RESERVED7					   (0x29UL)
+	#define HWRM_PORT_PHY_QCAPS				   (0x2aUL)
+	#define HWRM_PORT_PHY_I2C_WRITE			   (0x2bUL)
+	#define HWRM_PORT_PHY_I2C_READ				   (0x2cUL)
+	#define HWRM_PORT_LED_CFG				   (0x2dUL)
+	#define HWRM_PORT_LED_QCFG				   (0x2eUL)
+	#define HWRM_PORT_LED_QCAPS				   (0x2fUL)
+	#define HWRM_QUEUE_QPORTCFG				   (0x30UL)
+	#define HWRM_QUEUE_QCFG				   (0x31UL)
+	#define HWRM_QUEUE_CFG					   (0x32UL)
+	#define RESERVED2					   (0x33UL)
+	#define RESERVED3					   (0x34UL)
+	#define HWRM_QUEUE_PFCENABLE_QCFG			   (0x35UL)
+	#define HWRM_QUEUE_PFCENABLE_CFG			   (0x36UL)
+	#define HWRM_QUEUE_PRI2COS_QCFG			   (0x37UL)
+	#define HWRM_QUEUE_PRI2COS_CFG				   (0x38UL)
+	#define HWRM_QUEUE_COS2BW_QCFG				   (0x39UL)
+	#define HWRM_QUEUE_COS2BW_CFG				   (0x3aUL)
+	#define HWRM_VNIC_ALLOC				   (0x40UL)
+	#define HWRM_VNIC_FREE					   (0x41UL)
+	#define HWRM_VNIC_CFG					   (0x42UL)
+	#define HWRM_VNIC_QCFG					   (0x43UL)
+	#define HWRM_VNIC_TPA_CFG				   (0x44UL)
+	#define HWRM_VNIC_TPA_QCFG				   (0x45UL)
+	#define HWRM_VNIC_RSS_CFG				   (0x46UL)
+	#define HWRM_VNIC_RSS_QCFG				   (0x47UL)
+	#define HWRM_VNIC_PLCMODES_CFG				   (0x48UL)
+	#define HWRM_VNIC_PLCMODES_QCFG			   (0x49UL)
+	#define HWRM_VNIC_QCAPS				   (0x4aUL)
+	#define HWRM_RING_ALLOC				   (0x50UL)
+	#define HWRM_RING_FREE					   (0x51UL)
+	#define HWRM_RING_CMPL_RING_QAGGINT_PARAMS		   (0x52UL)
+	#define HWRM_RING_CMPL_RING_CFG_AGGINT_PARAMS		   (0x53UL)
+	#define HWRM_RING_RESET				   (0x5eUL)
+	#define HWRM_RING_GRP_ALLOC				   (0x60UL)
+	#define HWRM_RING_GRP_FREE				   (0x61UL)
+	#define RESERVED5					   (0x64UL)
+	#define RESERVED6					   (0x65UL)
+	#define HWRM_VNIC_RSS_COS_LB_CTX_ALLOC			   (0x70UL)
+	#define HWRM_VNIC_RSS_COS_LB_CTX_FREE			   (0x71UL)
+	#define HWRM_CFA_L2_FILTER_ALLOC			   (0x90UL)
+	#define HWRM_CFA_L2_FILTER_FREE			   (0x91UL)
+	#define HWRM_CFA_L2_FILTER_CFG				   (0x92UL)
+	#define HWRM_CFA_L2_SET_RX_MASK			   (0x93UL)
+	#define RESERVED4					   (0x94UL)
+	#define HWRM_CFA_TUNNEL_FILTER_ALLOC			   (0x95UL)
+	#define HWRM_CFA_TUNNEL_FILTER_FREE			   (0x96UL)
+	#define HWRM_CFA_ENCAP_RECORD_ALLOC			   (0x97UL)
+	#define HWRM_CFA_ENCAP_RECORD_FREE			   (0x98UL)
+	#define HWRM_CFA_NTUPLE_FILTER_ALLOC			   (0x99UL)
+	#define HWRM_CFA_NTUPLE_FILTER_FREE			   (0x9aUL)
+	#define HWRM_CFA_NTUPLE_FILTER_CFG			   (0x9bUL)
+	#define HWRM_CFA_EM_FLOW_ALLOC				   (0x9cUL)
+	#define HWRM_CFA_EM_FLOW_FREE				   (0x9dUL)
+	#define HWRM_CFA_EM_FLOW_CFG				   (0x9eUL)
+	#define HWRM_TUNNEL_DST_PORT_QUERY			   (0xa0UL)
+	#define HWRM_TUNNEL_DST_PORT_ALLOC			   (0xa1UL)
+	#define HWRM_TUNNEL_DST_PORT_FREE			   (0xa2UL)
+	#define HWRM_STAT_CTX_ALLOC				   (0xb0UL)
+	#define HWRM_STAT_CTX_FREE				   (0xb1UL)
+	#define HWRM_STAT_CTX_QUERY				   (0xb2UL)
+	#define HWRM_STAT_CTX_CLR_STATS			   (0xb3UL)
+	#define HWRM_FW_RESET					   (0xc0UL)
+	#define HWRM_FW_QSTATUS				   (0xc1UL)
+	#define HWRM_FW_SET_TIME				   (0xc8UL)
+	#define HWRM_FW_GET_TIME				   (0xc9UL)
+	#define HWRM_FW_SET_STRUCTURED_DATA			   (0xcaUL)
+	#define HWRM_FW_GET_STRUCTURED_DATA			   (0xcbUL)
+	#define HWRM_FW_IPC_MAILBOX				   (0xccUL)
+	#define HWRM_EXEC_FWD_RESP				   (0xd0UL)
+	#define HWRM_REJECT_FWD_RESP				   (0xd1UL)
+	#define HWRM_FWD_RESP					   (0xd2UL)
+	#define HWRM_FWD_ASYNC_EVENT_CMPL			   (0xd3UL)
+	#define HWRM_TEMP_MONITOR_QUERY			   (0xe0UL)
+	#define HWRM_WOL_FILTER_ALLOC				   (0xf0UL)
+	#define HWRM_WOL_FILTER_FREE				   (0xf1UL)
+	#define HWRM_WOL_FILTER_QCFG				   (0xf2UL)
+	#define HWRM_WOL_REASON_QCFG				   (0xf3UL)
+	#define HWRM_DBG_READ_DIRECT				   (0xff10UL)
+	#define HWRM_DBG_READ_INDIRECT				   (0xff11UL)
+	#define HWRM_DBG_WRITE_DIRECT				   (0xff12UL)
+	#define HWRM_DBG_WRITE_INDIRECT			   (0xff13UL)
+	#define HWRM_DBG_DUMP					   (0xff14UL)
+	#define HWRM_NVM_GET_VARIABLE				   (0xfff1UL)
+	#define HWRM_NVM_SET_VARIABLE				   (0xfff2UL)
+	#define HWRM_NVM_INSTALL_UPDATE			   (0xfff3UL)
+	#define HWRM_NVM_MODIFY				   (0xfff4UL)
+	#define HWRM_NVM_VERIFY_UPDATE				   (0xfff5UL)
+	#define HWRM_NVM_GET_DEV_INFO				   (0xfff6UL)
+	#define HWRM_NVM_ERASE_DIR_ENTRY			   (0xfff7UL)
+	#define HWRM_NVM_MOD_DIR_ENTRY				   (0xfff8UL)
+	#define HWRM_NVM_FIND_DIR_ENTRY			   (0xfff9UL)
+	#define HWRM_NVM_GET_DIR_ENTRIES			   (0xfffaUL)
+	#define HWRM_NVM_GET_DIR_INFO				   (0xfffbUL)
+	#define HWRM_NVM_RAW_DUMP				   (0xfffcUL)
+	#define HWRM_NVM_READ					   (0xfffdUL)
+	#define HWRM_NVM_WRITE					   (0xfffeUL)
+	#define HWRM_NVM_RAW_WRITE_BLK				   (0xffffUL)
+	__le16 unused_0[3];
+};
+
+/* Return Codes (8 bytes) */
+struct ret_codes {
+	__le16 error_code;
+	#define HWRM_ERR_CODE_SUCCESS				   (0x0UL)
+	#define HWRM_ERR_CODE_FAIL				   (0x1UL)
+	#define HWRM_ERR_CODE_INVALID_PARAMS			   (0x2UL)
+	#define HWRM_ERR_CODE_RESOURCE_ACCESS_DENIED		   (0x3UL)
+	#define HWRM_ERR_CODE_RESOURCE_ALLOC_ERROR		   (0x4UL)
+	#define HWRM_ERR_CODE_INVALID_FLAGS			   (0x5UL)
+	#define HWRM_ERR_CODE_INVALID_ENABLES			   (0x6UL)
+	#define HWRM_ERR_CODE_HWRM_ERROR			   (0xfUL)
+	#define HWRM_ERR_CODE_UNKNOWN_ERR			   (0xfffeUL)
+	#define HWRM_ERR_CODE_CMD_NOT_SUPPORTED		   (0xffffUL)
+	__le16 unused_0[3];
+};
+
+/* Output (16 bytes) */
+struct hwrm_err_output {
+	__le16 error_code;
+	__le16 req_type;
+	__le16 seq_id;
+	__le16 resp_len;
+	__le32 opaque_0;
+	__le16 opaque_1;
+	u8 cmd_err;
+	u8 valid;
+};
+
+/* Port Tx Statistics Formats (408 bytes) */
+struct tx_port_stats {
+	__le64 tx_64b_frames;
+	__le64 tx_65b_127b_frames;
+	__le64 tx_128b_255b_frames;
+	__le64 tx_256b_511b_frames;
+	__le64 tx_512b_1023b_frames;
+	__le64 tx_1024b_1518_frames;
+	__le64 tx_good_vlan_frames;
+	__le64 tx_1519b_2047_frames;
+	__le64 tx_2048b_4095b_frames;
+	__le64 tx_4096b_9216b_frames;
+	__le64 tx_9217b_16383b_frames;
+	__le64 tx_good_frames;
+	__le64 tx_total_frames;
+	__le64 tx_ucast_frames;
+	__le64 tx_mcast_frames;
+	__le64 tx_bcast_frames;
+	__le64 tx_pause_frames;
+	__le64 tx_pfc_frames;
+	__le64 tx_jabber_frames;
+	__le64 tx_fcs_err_frames;
+	__le64 tx_control_frames;
+	__le64 tx_oversz_frames;
+	__le64 tx_single_dfrl_frames;
+	__le64 tx_multi_dfrl_frames;
+	__le64 tx_single_coll_frames;
+	__le64 tx_multi_coll_frames;
+	__le64 tx_late_coll_frames;
+	__le64 tx_excessive_coll_frames;
+	__le64 tx_frag_frames;
+	__le64 tx_err;
+	__le64 tx_tagged_frames;
+	__le64 tx_dbl_tagged_frames;
+	__le64 tx_runt_frames;
+	__le64 tx_fifo_underruns;
+	__le64 tx_pfc_ena_frames_pri0;
+	__le64 tx_pfc_ena_frames_pri1;
+	__le64 tx_pfc_ena_frames_pri2;
+	__le64 tx_pfc_ena_frames_pri3;
+	__le64 tx_pfc_ena_frames_pri4;
+	__le64 tx_pfc_ena_frames_pri5;
+	__le64 tx_pfc_ena_frames_pri6;
+	__le64 tx_pfc_ena_frames_pri7;
+	__le64 tx_eee_lpi_events;
+	__le64 tx_eee_lpi_duration;
+	__le64 tx_llfc_logical_msgs;
+	__le64 tx_hcfc_msgs;
+	__le64 tx_total_collisions;
+	__le64 tx_bytes;
+	__le64 tx_xthol_frames;
+	__le64 tx_stat_discard;
+	__le64 tx_stat_error;
+};
+
+/* Port Rx Statistics Formats (528 bytes) */
+struct rx_port_stats {
+	__le64 rx_64b_frames;
+	__le64 rx_65b_127b_frames;
+	__le64 rx_128b_255b_frames;
+	__le64 rx_256b_511b_frames;
+	__le64 rx_512b_1023b_frames;
+	__le64 rx_1024b_1518_frames;
+	__le64 rx_good_vlan_frames;
+	__le64 rx_1519b_2047b_frames;
+	__le64 rx_2048b_4095b_frames;
+	__le64 rx_4096b_9216b_frames;
+	__le64 rx_9217b_16383b_frames;
+	__le64 rx_total_frames;
+	__le64 rx_ucast_frames;
+	__le64 rx_mcast_frames;
+	__le64 rx_bcast_frames;
+	__le64 rx_fcs_err_frames;
+	__le64 rx_ctrl_frames;
+	__le64 rx_pause_frames;
+	__le64 rx_pfc_frames;
+	__le64 rx_unsupported_opcode_frames;
+	__le64 rx_unsupported_da_pausepfc_frames;
+	__le64 rx_wrong_sa_frames;
+	__le64 rx_align_err_frames;
+	__le64 rx_oor_len_frames;
+	__le64 rx_code_err_frames;
+	__le64 rx_false_carrier_frames;
+	__le64 rx_ovrsz_frames;
+	__le64 rx_jbr_frames;
+	__le64 rx_mtu_err_frames;
+	__le64 rx_match_crc_frames;
+	__le64 rx_promiscuous_frames;
+	__le64 rx_tagged_frames;
+	__le64 rx_double_tagged_frames;
+	__le64 rx_trunc_frames;
+	__le64 rx_good_frames;
+	__le64 rx_pfc_xon2xoff_frames_pri0;
+	__le64 rx_pfc_xon2xoff_frames_pri1;
+	__le64 rx_pfc_xon2xoff_frames_pri2;
+	__le64 rx_pfc_xon2xoff_frames_pri3;
+	__le64 rx_pfc_xon2xoff_frames_pri4;
+	__le64 rx_pfc_xon2xoff_frames_pri5;
+	__le64 rx_pfc_xon2xoff_frames_pri6;
+	__le64 rx_pfc_xon2xoff_frames_pri7;
+	__le64 rx_pfc_ena_frames_pri0;
+	__le64 rx_pfc_ena_frames_pri1;
+	__le64 rx_pfc_ena_frames_pri2;
+	__le64 rx_pfc_ena_frames_pri3;
+	__le64 rx_pfc_ena_frames_pri4;
+	__le64 rx_pfc_ena_frames_pri5;
+	__le64 rx_pfc_ena_frames_pri6;
+	__le64 rx_pfc_ena_frames_pri7;
+	__le64 rx_sch_crc_err_frames;
+	__le64 rx_undrsz_frames;
+	__le64 rx_frag_frames;
+	__le64 rx_eee_lpi_events;
+	__le64 rx_eee_lpi_duration;
+	__le64 rx_llfc_physical_msgs;
+	__le64 rx_llfc_logical_msgs;
+	__le64 rx_llfc_msgs_with_crc_err;
+	__le64 rx_hcfc_msgs;
+	__le64 rx_hcfc_msgs_with_crc_err;
+	__le64 rx_bytes;
+	__le64 rx_runt_bytes;
+	__le64 rx_runt_frames;
+	__le64 rx_stat_discard;
+	__le64 rx_stat_err;
+};
+
+/* Periodic Statistics Context DMA to host (160 bytes) */
+struct ctx_hw_stats {
+	__le64 rx_ucast_pkts;
+	__le64 rx_mcast_pkts;
+	__le64 rx_bcast_pkts;
+	__le64 rx_discard_pkts;
+	__le64 rx_drop_pkts;
+	__le64 rx_ucast_bytes;
+	__le64 rx_mcast_bytes;
+	__le64 rx_bcast_bytes;
+	__le64 tx_ucast_pkts;
+	__le64 tx_mcast_pkts;
+	__le64 tx_bcast_pkts;
+	__le64 tx_discard_pkts;
+	__le64 tx_drop_pkts;
+	__le64 tx_ucast_bytes;
+	__le64 tx_mcast_bytes;
+	__le64 tx_bcast_bytes;
+	__le64 tpa_pkts;
+	__le64 tpa_bytes;
+	__le64 tpa_events;
+	__le64 tpa_aborts;
+};
+
+/* Structure data header (16 bytes) */
+struct hwrm_struct_hdr {
+	__le16 struct_id;
+	#define STRUCT_HDR_STRUCT_ID_LLDP_CFG			   0x41bUL
+	#define STRUCT_HDR_STRUCT_ID_DCBX_ETS_CFG		   0x41dUL
+	#define STRUCT_HDR_STRUCT_ID_DCBX_PFC_CFG		   0x41fUL
+	#define STRUCT_HDR_STRUCT_ID_DCBX_APP_CFG		   0x421UL
+	#define STRUCT_HDR_STRUCT_ID_DCBX_STATE_CFG		   0x422UL
+	#define STRUCT_HDR_STRUCT_ID_LLDP_GENERIC_CFG		   0x424UL
+	#define STRUCT_HDR_STRUCT_ID_LLDP_DEVICE_CFG		   0x426UL
+	__le16 len;
+	u8 version;
+	u8 count;
+	__le16 subtype;
+	__le16 next_offset;
+	#define STRUCT_HDR_NEXT_OFFSET_LAST			   0x0UL
+	__le16 unused_0[3];
+};
+
+/* DCBX Application configuration structure (8 bytes) */
+struct hwrm_struct_data_dcbx_app_cfg {
+	__le16 protocol_id;
+	u8 protocol_selector;
+	#define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_ETHER_TYPE 0x1UL
+	#define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_TCP_PORT 0x2UL
+	#define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_UDP_PORT 0x3UL
+	#define STRUCT_DATA_DCBX_APP_CFG_PROTOCOL_SELECTOR_TCP_UDP_PORT 0x4UL
+	u8 priority;
+	u8 valid;
+	u8 unused_0[3];
+};
+
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c	2017-02-12 16:03:20.000000000 -0500
@@ -34,8 +34,7 @@ static int bnxt_hwrm_fwd_async_event_cmp
 		/* broadcast this async event to all VFs */
 		req.encap_async_event_target_id = cpu_to_le16(0xffff);
 	async_cmpl = (struct hwrm_async_event_cmpl *)req.encap_async_event_cmpl;
-	async_cmpl->type =
-		cpu_to_le16(HWRM_ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT);
+	async_cmpl->type = cpu_to_le16(ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT);
 	async_cmpl->event_id = cpu_to_le16(event_id);
 
 	mutex_lock(&bp->hwrm_cmd_lock);
@@ -288,7 +287,7 @@ int bnxt_set_vf_link_state(struct net_de
 	}
 	if (vf->flags & (BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED))
 		rc = bnxt_hwrm_fwd_async_event_cmpl(bp, vf,
-			HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
+			ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE);
 	return rc;
 }
 
@@ -421,15 +420,7 @@ static int bnxt_hwrm_func_cfg(struct bnx
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
 
 	/* Remaining rings are distributed equally amongs VF's for now */
-	/* TODO: the following workaroud is needed to restrict total number
-	 * of vf_cp_rings not exceed number of HW ring groups. This WA should
-	 * be removed once new HWRM provides HW ring groups capability in
-	 * hwrm_func_qcap.
-	 */
-	vf_cp_rings = min_t(u16, pf->max_cp_rings, pf->max_stat_ctxs);
-	vf_cp_rings = (vf_cp_rings - bp->cp_nr_rings) / num_vfs;
-	/* TODO: restore this logic below once the WA above is removed */
-	/* vf_cp_rings = (pf->max_cp_rings - bp->cp_nr_rings) / num_vfs; */
+	vf_cp_rings = (pf->max_cp_rings - bp->cp_nr_rings) / num_vfs;
 	vf_stat_ctx = (pf->max_stat_ctxs - bp->num_stat_ctxs) / num_vfs;
 	if (bp->flags & BNXT_FLAG_AGG_RINGS)
 		vf_rx_rings = (pf->max_rx_rings - bp->rx_nr_rings * 2) /
@@ -578,8 +569,7 @@ void bnxt_sriov_disable(struct bnxt *bp)
 
 	if (pci_vfs_assigned(bp->pdev)) {
 		bnxt_hwrm_fwd_async_event_cmpl(
-			bp, NULL,
-			HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
+			bp, NULL, ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD);
 		netdev_warn(bp->dev, "Unable to free %d VFs because some are assigned to VMs.\n",
 			    num_vfs);
 	} else {
@@ -592,7 +582,9 @@ void bnxt_sriov_disable(struct bnxt *bp)
 
 	bp->pf.active_vfs = 0;
 	/* Reclaim all resources for the PF. */
-	bnxt_hwrm_func_qcaps(bp);
+	rtnl_lock();
+	bnxt_restore_pf_fw_resources(bp);
+	rtnl_unlock();
 }
 
 int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,346 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom 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.
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <asm/byteorder.h>
+#include <linux/bitmap.h>
+
+#include "bnxt_hsi.h"
+#include "bnxt.h"
+#include "bnxt_ulp.h"
+
+static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,
+			     struct bnxt_ulp_ops *ulp_ops, void *handle)
+{
+	struct net_device *dev = edev->net;
+	struct bnxt *bp = netdev_priv(dev);
+	struct bnxt_ulp *ulp;
+
+	ASSERT_RTNL();
+	if (ulp_id >= BNXT_MAX_ULP)
+		return -EINVAL;
+
+	ulp = &edev->ulp_tbl[ulp_id];
+	if (rcu_access_pointer(ulp->ulp_ops)) {
+		netdev_err(bp->dev, "ulp id %d already registered\n", ulp_id);
+		return -EBUSY;
+	}
+	if (ulp_id == BNXT_ROCE_ULP) {
+		unsigned int max_stat_ctxs;
+
+		max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);
+		if (max_stat_ctxs <= BNXT_MIN_ROCE_STAT_CTXS ||
+		    bp->num_stat_ctxs == max_stat_ctxs)
+			return -ENOMEM;
+		bnxt_set_max_func_stat_ctxs(bp, max_stat_ctxs -
+					    BNXT_MIN_ROCE_STAT_CTXS);
+	}
+
+	atomic_set(&ulp->ref_count, 0);
+	ulp->handle = handle;
+	rcu_assign_pointer(ulp->ulp_ops, ulp_ops);
+
+	if (ulp_id == BNXT_ROCE_ULP) {
+		if (test_bit(BNXT_STATE_OPEN, &bp->state))
+			bnxt_hwrm_vnic_cfg(bp, 0);
+	}
+
+	return 0;
+}
+
+static int bnxt_unregister_dev(struct bnxt_en_dev *edev, int ulp_id)
+{
+	struct net_device *dev = edev->net;
+	struct bnxt *bp = netdev_priv(dev);
+	struct bnxt_ulp *ulp;
+	int i = 0;
+
+	ASSERT_RTNL();
+	if (ulp_id >= BNXT_MAX_ULP)
+		return -EINVAL;
+
+	ulp = &edev->ulp_tbl[ulp_id];
+	if (!rcu_access_pointer(ulp->ulp_ops)) {
+		netdev_err(bp->dev, "ulp id %d not registered\n", ulp_id);
+		return -EINVAL;
+	}
+	if (ulp_id == BNXT_ROCE_ULP) {
+		unsigned int max_stat_ctxs;
+
+		max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);
+		bnxt_set_max_func_stat_ctxs(bp, max_stat_ctxs + 1);
+	}
+	if (ulp->max_async_event_id)
+		bnxt_hwrm_func_rgtr_async_events(bp, NULL, 0);
+
+	RCU_INIT_POINTER(ulp->ulp_ops, NULL);
+	synchronize_rcu();
+	ulp->max_async_event_id = 0;
+	ulp->async_events_bmap = NULL;
+	while (atomic_read(&ulp->ref_count) != 0 && i < 10) {
+		msleep(100);
+		i++;
+	}
+	return 0;
+}
+
+static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
+			      struct bnxt_msix_entry *ent, int num_msix)
+{
+	struct net_device *dev = edev->net;
+	struct bnxt *bp = netdev_priv(dev);
+	int max_idx, max_cp_rings;
+	int avail_msix, i, idx;
+
+	ASSERT_RTNL();
+	if (ulp_id != BNXT_ROCE_ULP)
+		return -EINVAL;
+
+	if (!(bp->flags & BNXT_FLAG_USING_MSIX))
+		return -ENODEV;
+
+	max_cp_rings = bnxt_get_max_func_cp_rings(bp);
+	max_idx = min_t(int, bp->total_irqs, max_cp_rings);
+	avail_msix = max_idx - bp->cp_nr_rings;
+	if (!avail_msix)
+		return -ENOMEM;
+	if (avail_msix > num_msix)
+		avail_msix = num_msix;
+
+	idx = max_idx - avail_msix;
+	for (i = 0; i < avail_msix; i++) {
+		ent[i].vector = bp->irq_tbl[idx + i].vector;
+		ent[i].ring_idx = idx + i;
+		ent[i].db_offset = (idx + i) * 0x80;
+	}
+	bnxt_set_max_func_irqs(bp, max_idx - avail_msix);
+	bnxt_set_max_func_cp_rings(bp, max_cp_rings - avail_msix);
+	edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
+	return avail_msix;
+}
+
+static int bnxt_free_msix_vecs(struct bnxt_en_dev *edev, int ulp_id)
+{
+	struct net_device *dev = edev->net;
+	struct bnxt *bp = netdev_priv(dev);
+	int max_cp_rings, msix_requested;
+
+	ASSERT_RTNL();
+	if (ulp_id != BNXT_ROCE_ULP)
+		return -EINVAL;
+
+	max_cp_rings = bnxt_get_max_func_cp_rings(bp);
+	msix_requested = edev->ulp_tbl[ulp_id].msix_requested;
+	bnxt_set_max_func_cp_rings(bp, max_cp_rings + msix_requested);
+	edev->ulp_tbl[ulp_id].msix_requested = 0;
+	bnxt_set_max_func_irqs(bp, bp->total_irqs);
+	return 0;
+}
+
+void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id)
+{
+	ASSERT_RTNL();
+	if (bnxt_ulp_registered(bp->edev, ulp_id)) {
+		struct bnxt_en_dev *edev = bp->edev;
+		unsigned int msix_req, max;
+
+		msix_req = edev->ulp_tbl[ulp_id].msix_requested;
+		max = bnxt_get_max_func_cp_rings(bp);
+		bnxt_set_max_func_cp_rings(bp, max - msix_req);
+		max = bnxt_get_max_func_stat_ctxs(bp);
+		bnxt_set_max_func_stat_ctxs(bp, max - 1);
+	}
+}
+
+static int bnxt_send_msg(struct bnxt_en_dev *edev, int ulp_id,
+			 struct bnxt_fw_msg *fw_msg)
+{
+	struct net_device *dev = edev->net;
+	struct bnxt *bp = netdev_priv(dev);
+	struct input *req;
+	int rc;
+
+	mutex_lock(&bp->hwrm_cmd_lock);
+	req = fw_msg->msg;
+	req->resp_addr = cpu_to_le64(bp->hwrm_cmd_resp_dma_addr);
+	rc = _hwrm_send_message(bp, fw_msg->msg, fw_msg->msg_len,
+				fw_msg->timeout);
+	if (!rc) {
+		struct output *resp = bp->hwrm_cmd_resp_addr;
+		u32 len = le16_to_cpu(resp->resp_len);
+
+		if (fw_msg->resp_max_len < len)
+			len = fw_msg->resp_max_len;
+
+		memcpy(fw_msg->resp, resp, len);
+	}
+	mutex_unlock(&bp->hwrm_cmd_lock);
+	return rc;
+}
+
+static void bnxt_ulp_get(struct bnxt_ulp *ulp)
+{
+	atomic_inc(&ulp->ref_count);
+}
+
+static void bnxt_ulp_put(struct bnxt_ulp *ulp)
+{
+	atomic_dec(&ulp->ref_count);
+}
+
+void bnxt_ulp_stop(struct bnxt *bp)
+{
+	struct bnxt_en_dev *edev = bp->edev;
+	struct bnxt_ulp_ops *ops;
+	int i;
+
+	if (!edev)
+		return;
+
+	for (i = 0; i < BNXT_MAX_ULP; i++) {
+		struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+		ops = rtnl_dereference(ulp->ulp_ops);
+		if (!ops || !ops->ulp_stop)
+			continue;
+		ops->ulp_stop(ulp->handle);
+	}
+}
+
+void bnxt_ulp_start(struct bnxt *bp)
+{
+	struct bnxt_en_dev *edev = bp->edev;
+	struct bnxt_ulp_ops *ops;
+	int i;
+
+	if (!edev)
+		return;
+
+	for (i = 0; i < BNXT_MAX_ULP; i++) {
+		struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+		ops = rtnl_dereference(ulp->ulp_ops);
+		if (!ops || !ops->ulp_start)
+			continue;
+		ops->ulp_start(ulp->handle);
+	}
+}
+
+void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs)
+{
+	struct bnxt_en_dev *edev = bp->edev;
+	struct bnxt_ulp_ops *ops;
+	int i;
+
+	if (!edev)
+		return;
+
+	for (i = 0; i < BNXT_MAX_ULP; i++) {
+		struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+		rcu_read_lock();
+		ops = rcu_dereference(ulp->ulp_ops);
+		if (!ops || !ops->ulp_sriov_config) {
+			rcu_read_unlock();
+			continue;
+		}
+		bnxt_ulp_get(ulp);
+		rcu_read_unlock();
+		ops->ulp_sriov_config(ulp->handle, num_vfs);
+		bnxt_ulp_put(ulp);
+	}
+}
+
+void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl)
+{
+	u16 event_id = le16_to_cpu(cmpl->event_id);
+	struct bnxt_en_dev *edev = bp->edev;
+	struct bnxt_ulp_ops *ops;
+	int i;
+
+	if (!edev)
+		return;
+
+	rcu_read_lock();
+	for (i = 0; i < BNXT_MAX_ULP; i++) {
+		struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
+
+		ops = rcu_dereference(ulp->ulp_ops);
+		if (!ops || !ops->ulp_async_notifier)
+			continue;
+		if (!ulp->async_events_bmap ||
+		    event_id > ulp->max_async_event_id)
+			continue;
+
+		/* Read max_async_event_id first before testing the bitmap. */
+		smp_rmb();
+		if (test_bit(event_id, ulp->async_events_bmap))
+			ops->ulp_async_notifier(ulp->handle, cmpl);
+	}
+	rcu_read_unlock();
+}
+
+static int bnxt_register_async_events(struct bnxt_en_dev *edev, int ulp_id,
+				      unsigned long *events_bmap, u16 max_id)
+{
+	struct net_device *dev = edev->net;
+	struct bnxt *bp = netdev_priv(dev);
+	struct bnxt_ulp *ulp;
+
+	if (ulp_id >= BNXT_MAX_ULP)
+		return -EINVAL;
+
+	ulp = &edev->ulp_tbl[ulp_id];
+	ulp->async_events_bmap = events_bmap;
+	/* Make sure bnxt_ulp_async_events() sees this order */
+	smp_wmb();
+	ulp->max_async_event_id = max_id;
+	bnxt_hwrm_func_rgtr_async_events(bp, events_bmap, max_id + 1);
+	return 0;
+}
+
+static const struct bnxt_en_ops bnxt_en_ops_tbl = {
+	.bnxt_register_device	= bnxt_register_dev,
+	.bnxt_unregister_device	= bnxt_unregister_dev,
+	.bnxt_request_msix	= bnxt_req_msix_vecs,
+	.bnxt_free_msix		= bnxt_free_msix_vecs,
+	.bnxt_send_fw_msg	= bnxt_send_msg,
+	.bnxt_register_fw_async_events	= bnxt_register_async_events,
+};
+
+struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev)
+{
+	struct bnxt *bp = netdev_priv(dev);
+	struct bnxt_en_dev *edev;
+
+	edev = bp->edev;
+	if (!edev) {
+		edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+		if (!edev)
+			return ERR_PTR(-ENOMEM);
+		edev->en_ops = &bnxt_en_ops_tbl;
+		if (bp->flags & BNXT_FLAG_ROCEV1_CAP)
+			edev->flags |= BNXT_EN_FLAG_ROCEV1_CAP;
+		if (bp->flags & BNXT_FLAG_ROCEV2_CAP)
+			edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP;
+		edev->net = dev;
+		edev->pdev = bp->pdev;
+		bp->edev = edev;
+	}
+	return bp->edev;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,93 @@
+/* Broadcom NetXtreme-C/E network driver.
+ *
+ * Copyright (c) 2016 Broadcom 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.
+ */
+
+#ifndef BNXT_ULP_H
+#define BNXT_ULP_H
+
+#define BNXT_ROCE_ULP	0
+#define BNXT_OTHER_ULP	1
+#define BNXT_MAX_ULP	2
+
+#define BNXT_MIN_ROCE_CP_RINGS	2
+#define BNXT_MIN_ROCE_STAT_CTXS	1
+
+struct hwrm_async_event_cmpl;
+struct bnxt;
+
+struct bnxt_ulp_ops {
+	/* async_notifier() cannot sleep (in BH context) */
+	void (*ulp_async_notifier)(void *, struct hwrm_async_event_cmpl *);
+	void (*ulp_stop)(void *);
+	void (*ulp_start)(void *);
+	void (*ulp_sriov_config)(void *, int);
+};
+
+struct bnxt_msix_entry {
+	u32	vector;
+	u32	ring_idx;
+	u32	db_offset;
+};
+
+struct bnxt_fw_msg {
+	void	*msg;
+	int	msg_len;
+	void	*resp;
+	int	resp_max_len;
+	int	timeout;
+};
+
+struct bnxt_ulp {
+	void		*handle;
+	struct bnxt_ulp_ops __rcu *ulp_ops;
+	unsigned long	*async_events_bmap;
+	u16		max_async_event_id;
+	u16		msix_requested;
+	atomic_t	ref_count;
+};
+
+struct bnxt_en_dev {
+	struct net_device *net;
+	struct pci_dev *pdev;
+	u32 flags;
+	#define BNXT_EN_FLAG_ROCEV1_CAP		0x1
+	#define BNXT_EN_FLAG_ROCEV2_CAP		0x2
+	#define BNXT_EN_FLAG_ROCE_CAP		(BNXT_EN_FLAG_ROCEV1_CAP | \
+						 BNXT_EN_FLAG_ROCEV2_CAP)
+	const struct bnxt_en_ops	*en_ops;
+	struct bnxt_ulp			ulp_tbl[BNXT_MAX_ULP];
+};
+
+struct bnxt_en_ops {
+	int (*bnxt_register_device)(struct bnxt_en_dev *, int,
+				    struct bnxt_ulp_ops *, void *);
+	int (*bnxt_unregister_device)(struct bnxt_en_dev *, int);
+	int (*bnxt_request_msix)(struct bnxt_en_dev *, int,
+				 struct bnxt_msix_entry *, int);
+	int (*bnxt_free_msix)(struct bnxt_en_dev *, int);
+	int (*bnxt_send_fw_msg)(struct bnxt_en_dev *, int,
+				struct bnxt_fw_msg *);
+	int (*bnxt_register_fw_async_events)(struct bnxt_en_dev *, int,
+					     unsigned long *, u16);
+};
+
+static inline bool bnxt_ulp_registered(struct bnxt_en_dev *edev, int ulp_id)
+{
+	if (edev && rcu_access_pointer(edev->ulp_tbl[ulp_id].ulp_ops))
+		return true;
+	return false;
+}
+
+void bnxt_subtract_ulp_resources(struct bnxt *bp, int ulp_id);
+void bnxt_ulp_stop(struct bnxt *bp);
+void bnxt_ulp_start(struct bnxt *bp);
+void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs);
+void bnxt_ulp_async_events(struct bnxt *bp, struct hwrm_async_event_cmpl *cmpl);
+struct bnxt_en_dev *bnxt_ulp_probe(struct net_device *dev);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/bnxt/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/bnxt/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,3 +1,3 @@
 obj-$(CONFIG_BNXT) += bnxt_en.o
 
-bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o
+bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/genet/bcmgenet.c	2017-02-12 16:03:20.000000000 -0500
@@ -971,13 +971,6 @@ static int bcmgenet_set_eee(struct net_d
 	return phy_ethtool_set_eee(priv->phydev, e);
 }
 
-static int bcmgenet_nway_reset(struct net_device *dev)
-{
-	struct bcmgenet_priv *priv = netdev_priv(dev);
-
-	return genphy_restart_aneg(priv->phydev);
-}
-
 /* standard ethtool support functions. */
 static const struct ethtool_ops bcmgenet_ethtool_ops = {
 	.get_strings		= bcmgenet_get_strings,
@@ -991,7 +984,7 @@ static const struct ethtool_ops bcmgenet
 	.set_wol		= bcmgenet_set_wol,
 	.get_eee		= bcmgenet_get_eee,
 	.set_eee		= bcmgenet_set_eee,
-	.nway_reset		= bcmgenet_nway_reset,
+	.nway_reset		= phy_ethtool_nway_reset,
 	.get_coalesce		= bcmgenet_get_coalesce,
 	.set_coalesce		= bcmgenet_set_coalesce,
 	.get_link_ksettings	= bcmgenet_get_link_ksettings,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -110,7 +110,7 @@ config TIGON3
 	depends on PCI
 	select PHYLIB
 	select HWMON
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	---help---
 	  This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
 
@@ -120,7 +120,7 @@ config TIGON3
 config BNX2X
 	tristate "Broadcom NetXtremeII 10Gb support"
 	depends on PCI
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	select FW_LOADER
 	select ZLIB_INFLATE
 	select LIBCRC32C
@@ -203,4 +203,14 @@ config BNXT_SRIOV
 	  Virtualization support in the NetXtreme-C/E products. This
 	  allows for virtual function acceleration in virtual environments.
 
+config BNXT_DCB
+	bool "Data Center Bridging (DCB) Support"
+	default n
+	depends on BNXT && DCB
+	---help---
+	  Say Y here if you want to use Data Center Bridging (DCB) in the
+	  driver.
+
+	  If unsure, say N.
+
 endif # NET_VENDOR_BROADCOM
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/sb1250-mac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/sb1250-mac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/sb1250-mac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/sb1250-mac.c	2017-02-12 16:03:20.000000000 -0500
@@ -2147,15 +2147,6 @@ static void sbmac_setmulti(struct sbmac_
 	}
 }
 
-static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
-{
-	if (new_mtu >  ENET_PACKET_SIZE)
-		return -EINVAL;
-	_dev->mtu = new_mtu;
-	pr_info("changing the mtu to %d\n", new_mtu);
-	return 0;
-}
-
 static const struct net_device_ops sbmac_netdev_ops = {
 	.ndo_open		= sbmac_open,
 	.ndo_stop		= sbmac_close,
@@ -2163,7 +2154,6 @@ static const struct net_device_ops sbmac
 	.ndo_set_rx_mode	= sbmac_set_rx_mode,
 	.ndo_tx_timeout		= sbmac_tx_timeout,
 	.ndo_do_ioctl		= sbmac_mii_ioctl,
-	.ndo_change_mtu		= sb1250_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2229,6 +2219,8 @@ static int sbmac_init(struct platform_de
 
 	dev->netdev_ops = &sbmac_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->min_mtu = 0;
+	dev->max_mtu = ENET_PACKET_SIZE;
 
 	netif_napi_add(dev, &sc->napi, sbmac_poll, 16);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/tg3.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/tg3.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/broadcom/tg3.c	2016-12-11 17:50:46.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/broadcom/tg3.c	2017-02-12 17:40:08.000000000 -0500
@@ -117,7 +117,7 @@ static inline void _tg3_flag_clear(enum
 #define TG3_TX_TIMEOUT			(5 * HZ)
 
 /* hardware minimum and maximum for a single frame's data payload */
-#define TG3_MIN_MTU			60
+#define TG3_MIN_MTU			ETH_ZLEN
 #define TG3_MAX_MTU(tp)	\
 	(tg3_flag(tp, JUMBO_CAPABLE) ? 9000 : 1500)
 
@@ -8711,11 +8711,14 @@ static void tg3_free_consistent(struct t
 	tg3_mem_rx_release(tp);
 	tg3_mem_tx_release(tp);
 
+	/* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
+	tg3_full_lock(tp, 0);
 	if (tp->hw_stats) {
 		dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
 				  tp->hw_stats, tp->stats_mapping);
 		tp->hw_stats = NULL;
 	}
+	tg3_full_unlock(tp);
 }
 
 /*
@@ -14190,9 +14193,6 @@ static int tg3_change_mtu(struct net_dev
 	int err;
 	bool reset_phy = false;
 
-	if (new_mtu < TG3_MIN_MTU || new_mtu > TG3_MAX_MTU(tp))
-		return -EINVAL;
-
 	if (!netif_running(dev)) {
 		/* We'll just catch it later when the
 		 * device is up'd.
@@ -17790,6 +17790,10 @@ static int tg3_init_one(struct pci_dev *
 	dev->hw_features |= features;
 	dev->priv_flags |= IFF_UNICAST_FLT;
 
+	/* MTU range: 60 - 9000 or 1500, depending on hardware */
+	dev->min_mtu = TG3_MIN_MTU;
+	dev->max_mtu = TG3_MAX_MTU(tp);
+
 	if (tg3_chip_rev_id(tp) == CHIPREV_ID_5705_A1 &&
 	    !tg3_flag(tp, TSO_CAPABLE) &&
 	    !(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/brocade/bna/bnad.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/brocade/bna/bnad.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/brocade/bna/bnad.c	2016-12-11 17:48:58.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/brocade/bna/bnad.c	2017-02-12 17:37:17.000000000 -0500
@@ -3296,9 +3296,6 @@ bnad_change_mtu(struct net_device *netde
 	struct bnad *bnad = netdev_priv(netdev);
 	u32 rx_count = 0, frame, new_frame;
 
-	if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU)
-		return -EINVAL;
-
 	mutex_lock(&bnad->conf_mutex);
 
 	mtu = netdev->mtu;
@@ -3465,6 +3462,10 @@ bnad_netdev_init(struct bnad *bnad, bool
 	netdev->mem_start = bnad->mmio_start;
 	netdev->mem_end = bnad->mmio_start + bnad->mmio_len - 1;
 
+	/* MTU range: 46 - 9000 */
+	netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+	netdev->max_mtu = BNAD_JUMBO_MTU;
+
 	netdev->netdev_ops = &bnad_netdev_ops;
 	bnad_set_ethtool_ops(netdev);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c	2016-12-11 17:49:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/brocade/bna/bnad_ethtool.c	2017-02-12 17:37:21.000000000 -0500
@@ -240,40 +240,46 @@ static const char *bnad_net_stats_string
 #define BNAD_ETHTOOL_STATS_NUM	ARRAY_SIZE(bnad_net_stats_strings)
 
 static int
-bnad_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+bnad_get_link_ksettings(struct net_device *netdev,
+			struct ethtool_link_ksettings *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;
+	u32 supported, advertising;
+
+	supported = SUPPORTED_10000baseT_Full;
+	advertising = ADVERTISED_10000baseT_Full;
+	cmd->base.autoneg = AUTONEG_DISABLE;
+	supported |= SUPPORTED_FIBRE;
+	advertising |= ADVERTISED_FIBRE;
+	cmd->base.port = PORT_FIBRE;
+	cmd->base.phy_address = 0;
 
 	if (netif_carrier_ok(netdev)) {
-		ethtool_cmd_speed_set(cmd, SPEED_10000);
-		cmd->duplex = DUPLEX_FULL;
+		cmd->base.speed = SPEED_10000;
+		cmd->base.duplex = DUPLEX_FULL;
 	} else {
-		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
-		cmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->maxtxpkt = 0;
-	cmd->maxrxpkt = 0;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return 0;
 }
 
 static int
-bnad_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+bnad_set_link_ksettings(struct net_device *netdev,
+			const struct ethtool_link_ksettings *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;
-	}
+	if (cmd->base.autoneg == AUTONEG_ENABLE)
+		return -EOPNOTSUPP;
+
+	if ((cmd->base.speed == SPEED_10000) &&
+	    (cmd->base.duplex == DUPLEX_FULL))
+		return 0;
 
 	return -EOPNOTSUPP;
 }
@@ -1118,8 +1124,6 @@ out:
 }
 
 static const struct ethtool_ops bnad_ethtool_ops = {
-	.get_settings = bnad_get_settings,
-	.set_settings = bnad_set_settings,
 	.get_drvinfo = bnad_get_drvinfo,
 	.get_wol = bnad_get_wol,
 	.get_link = ethtool_op_get_link,
@@ -1137,6 +1141,8 @@ static const struct ethtool_ops bnad_eth
 	.set_eeprom = bnad_set_eeprom,
 	.flash_device = bnad_flash_device,
 	.get_ts_info = ethtool_op_get_ts_info,
+	.get_link_ksettings = bnad_get_link_ksettings,
+	.set_link_ksettings = bnad_set_link_ksettings,
 };
 
 void
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/brocade/bna/bna_enet.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/brocade/bna/bna_enet.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/brocade/bna/bna_enet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/brocade/bna/bna_enet.c	2017-02-12 16:03:20.000000000 -0500
@@ -1676,10 +1676,10 @@ bna_cb_ioceth_reset(void *arg)
 }
 
 static struct bfa_ioc_cbfn bna_ioceth_cbfn = {
-	bna_cb_ioceth_enable,
-	bna_cb_ioceth_disable,
-	bna_cb_ioceth_hbfail,
-	bna_cb_ioceth_reset
+	.enable_cbfn = bna_cb_ioceth_enable,
+	.disable_cbfn = bna_cb_ioceth_disable,
+	.hbfail_cbfn = bna_cb_ioceth_hbfail,
+	.reset_cbfn = bna_cb_ioceth_reset
 };
 
 static void bna_attr_init(struct bna_ioceth *ioceth)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cadence/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/cadence/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -31,4 +31,13 @@ config MACB
 	  To compile this driver as a module, choose M here: the module
 	  will be called macb.
 
+config MACB_PCI
+	tristate "Cadence PCI MACB/GEM support"
+	depends on MACB && PCI && COMMON_CLK
+	---help---
+	  This is PCI wrapper for MACB driver.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called macb_pci.
+
 endif # NET_CADENCE
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cadence/macb.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/macb.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cadence/macb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/macb.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,19 +32,28 @@
 #include <linux/of_gpio.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
-
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
 #include "macb.h"
 
 #define MACB_RX_BUFFER_SIZE	128
 #define RX_BUFFER_MULTIPLE	64  /* bytes */
-#define RX_RING_SIZE		512 /* must be power of 2 */
-#define RX_RING_BYTES		(sizeof(struct macb_dma_desc) * RX_RING_SIZE)
 
-#define TX_RING_SIZE		128 /* must be power of 2 */
-#define TX_RING_BYTES		(sizeof(struct macb_dma_desc) * TX_RING_SIZE)
+#define DEFAULT_RX_RING_SIZE	512 /* must be power of 2 */
+#define MIN_RX_RING_SIZE	64
+#define MAX_RX_RING_SIZE	8192
+#define RX_RING_BYTES(bp)	(macb_dma_desc_get_size(bp)	\
+				 * (bp)->rx_ring_size)
+
+#define DEFAULT_TX_RING_SIZE	512 /* must be power of 2 */
+#define MIN_TX_RING_SIZE	64
+#define MAX_TX_RING_SIZE	4096
+#define TX_RING_BYTES(bp)	(macb_dma_desc_get_size(bp)	\
+				 * (bp)->tx_ring_size)
 
 /* level of occupied TX descriptors under which we wake up TX process */
-#define MACB_TX_WAKEUP_THRESH	(3 * TX_RING_SIZE / 4)
+#define MACB_TX_WAKEUP_THRESH(bp)	(3 * (bp)->tx_ring_size / 4)
 
 #define MACB_RX_INT_FLAGS	(MACB_BIT(RCOMP) | MACB_BIT(RXUBR)	\
 				 | MACB_BIT(ISR_ROVR))
@@ -53,10 +62,13 @@
 					| MACB_BIT(TXERR))
 #define MACB_TX_INT_FLAGS	(MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
 
-#define MACB_MAX_TX_LEN		((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1))
-#define GEM_MAX_TX_LEN		((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1))
+/* Max length of transmit frame must be a multiple of 8 bytes */
+#define MACB_TX_LEN_ALIGN	8
+#define MACB_MAX_TX_LEN		((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
+#define GEM_MAX_TX_LEN		((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
 
-#define GEM_MTU_MIN_SIZE	68
+#define GEM_MTU_MIN_SIZE	ETH_MIN_MTU
+#define MACB_NETIF_LSO		(NETIF_F_TSO | NETIF_F_UFO)
 
 #define MACB_WOL_HAS_MAGIC_PACKET	(0x1 << 0)
 #define MACB_WOL_ENABLED		(0x1 << 1)
@@ -66,46 +78,83 @@
  */
 #define MACB_HALT_TIMEOUT	1230
 
+/* DMA buffer descriptor might be different size
+ * depends on hardware configuration.
+ */
+static unsigned int macb_dma_desc_get_size(struct macb *bp)
+{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+		return sizeof(struct macb_dma_desc) + sizeof(struct macb_dma_desc_64);
+#endif
+	return sizeof(struct macb_dma_desc);
+}
+
+static unsigned int macb_adj_dma_desc_idx(struct macb *bp, unsigned int idx)
+{
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	/* Dma buffer descriptor is 4 words length (instead of 2 words)
+	 * for 64b GEM.
+	 */
+	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+		idx <<= 1;
+#endif
+	return idx;
+}
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+static struct macb_dma_desc_64 *macb_64b_desc(struct macb *bp, struct macb_dma_desc *desc)
+{
+	return (struct macb_dma_desc_64 *)((void *)desc + sizeof(struct macb_dma_desc));
+}
+#endif
+
 /* Ring buffer accessors */
-static unsigned int macb_tx_ring_wrap(unsigned int index)
+static unsigned int macb_tx_ring_wrap(struct macb *bp, unsigned int index)
 {
-	return index & (TX_RING_SIZE - 1);
+	return index & (bp->tx_ring_size - 1);
 }
 
 static struct macb_dma_desc *macb_tx_desc(struct macb_queue *queue,
 					  unsigned int index)
 {
-	return &queue->tx_ring[macb_tx_ring_wrap(index)];
+	index = macb_tx_ring_wrap(queue->bp, index);
+	index = macb_adj_dma_desc_idx(queue->bp, index);
+	return &queue->tx_ring[index];
 }
 
 static struct macb_tx_skb *macb_tx_skb(struct macb_queue *queue,
 				       unsigned int index)
 {
-	return &queue->tx_skb[macb_tx_ring_wrap(index)];
+	return &queue->tx_skb[macb_tx_ring_wrap(queue->bp, index)];
 }
 
 static dma_addr_t macb_tx_dma(struct macb_queue *queue, unsigned int index)
 {
 	dma_addr_t offset;
 
-	offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
+	offset = macb_tx_ring_wrap(queue->bp, index) *
+			macb_dma_desc_get_size(queue->bp);
 
 	return queue->tx_ring_dma + offset;
 }
 
-static unsigned int macb_rx_ring_wrap(unsigned int index)
+static unsigned int macb_rx_ring_wrap(struct macb *bp, unsigned int index)
 {
-	return index & (RX_RING_SIZE - 1);
+	return index & (bp->rx_ring_size - 1);
 }
 
 static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
 {
-	return &bp->rx_ring[macb_rx_ring_wrap(index)];
+	index = macb_rx_ring_wrap(bp, index);
+	index = macb_adj_dma_desc_idx(bp, index);
+	return &bp->rx_ring[index];
 }
 
 static void *macb_rx_buffer(struct macb *bp, unsigned int index)
 {
-	return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
+	return bp->rx_buffers + bp->rx_buffer_size *
+	       macb_rx_ring_wrap(bp, index);
 }
 
 /* I/O accessors */
@@ -390,6 +439,8 @@ static int macb_mii_probe(struct net_dev
 			phy_irq = gpio_to_irq(pdata->phy_irq_pin);
 			phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq;
 		}
+	} else {
+		phydev->irq = PHY_POLL;
 	}
 
 	/* attach the mac to the phy */
@@ -468,6 +519,9 @@ static int macb_mii_init(struct macb *bp
 				goto err_out_unregister_bus;
 		}
 	} else {
+		for (i = 0; i < PHY_MAX_ADDR; i++)
+			bp->mii_bus->irq[i] = PHY_POLL;
+
 		if (pdata)
 			bp->mii_bus->phy_mask = pdata->phy_mask;
 
@@ -541,12 +595,32 @@ static void macb_tx_unmap(struct macb *b
 	}
 }
 
-static inline void macb_set_addr(struct macb_dma_desc *desc, dma_addr_t addr)
+static void macb_set_addr(struct macb *bp, struct macb_dma_desc *desc, dma_addr_t addr)
 {
-	desc->addr = (u32)addr;
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	desc->addrh = (u32)(addr >> 32);
+	struct macb_dma_desc_64 *desc_64;
+
+	if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+		desc_64 = macb_64b_desc(bp, desc);
+		desc_64->addrh = upper_32_bits(addr);
+	}
 #endif
+	desc->addr = lower_32_bits(addr);
+}
+
+static dma_addr_t macb_get_addr(struct macb *bp, struct macb_dma_desc *desc)
+{
+	dma_addr_t addr = 0;
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	struct macb_dma_desc_64 *desc_64;
+
+	if (bp->hw_dma_cap == HW_DMA_CAP_64B) {
+		desc_64 = macb_64b_desc(bp, desc);
+		addr = ((u64)(desc_64->addrh) << 32);
+	}
+#endif
+	addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
+	return addr;
 }
 
 static void macb_tx_error_task(struct work_struct *work)
@@ -608,7 +682,8 @@ static void macb_tx_error_task(struct wo
 			 */
 			if (!(ctrl & MACB_BIT(TX_BUF_EXHAUSTED))) {
 				netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
-					    macb_tx_ring_wrap(tail), skb->data);
+					    macb_tx_ring_wrap(bp, tail),
+					    skb->data);
 				bp->stats.tx_packets++;
 				bp->stats.tx_bytes += skb->len;
 			}
@@ -629,16 +704,17 @@ static void macb_tx_error_task(struct wo
 
 	/* Set end of TX queue */
 	desc = macb_tx_desc(queue, 0);
-	macb_set_addr(desc, 0);
+	macb_set_addr(bp, desc, 0);
 	desc->ctrl = MACB_BIT(TX_USED);
 
 	/* Make descriptor updates visible to hardware */
 	wmb();
 
 	/* Reinitialize the TX desc queue */
-	queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
+	queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
+	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+		queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
 #endif
 	/* Make TX ring reflect state of hardware */
 	queue->tx_head = 0;
@@ -700,7 +776,8 @@ static void macb_tx_interrupt(struct mac
 			/* First, update TX stats if needed */
 			if (skb) {
 				netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
-					    macb_tx_ring_wrap(tail), skb->data);
+					    macb_tx_ring_wrap(bp, tail),
+					    skb->data);
 				bp->stats.tx_packets++;
 				bp->stats.tx_bytes += skb->len;
 			}
@@ -720,7 +797,7 @@ static void macb_tx_interrupt(struct mac
 	queue->tx_tail = tail;
 	if (__netif_subqueue_stopped(bp->dev, queue_index) &&
 	    CIRC_CNT(queue->tx_head, queue->tx_tail,
-		     TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
+		     bp->tx_ring_size) <= MACB_TX_WAKEUP_THRESH(bp))
 		netif_wake_subqueue(bp->dev, queue_index);
 }
 
@@ -729,15 +806,17 @@ static void gem_rx_refill(struct macb *b
 	unsigned int		entry;
 	struct sk_buff		*skb;
 	dma_addr_t		paddr;
+	struct macb_dma_desc *desc;
 
 	while (CIRC_SPACE(bp->rx_prepared_head, bp->rx_tail,
-			  RX_RING_SIZE) > 0) {
-		entry = macb_rx_ring_wrap(bp->rx_prepared_head);
+			  bp->rx_ring_size) > 0) {
+		entry = macb_rx_ring_wrap(bp, bp->rx_prepared_head);
 
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
 
 		bp->rx_prepared_head++;
+		desc = macb_rx_desc(bp, entry);
 
 		if (!bp->rx_skbuff[entry]) {
 			/* allocate sk_buff for this free entry in ring */
@@ -759,16 +838,16 @@ static void gem_rx_refill(struct macb *b
 
 			bp->rx_skbuff[entry] = skb;
 
-			if (entry == RX_RING_SIZE - 1)
+			if (entry == bp->rx_ring_size - 1)
 				paddr |= MACB_BIT(RX_WRAP);
-			macb_set_addr(&(bp->rx_ring[entry]), paddr);
-			bp->rx_ring[entry].ctrl = 0;
+			macb_set_addr(bp, desc, paddr);
+			desc->ctrl = 0;
 
 			/* properly align Ethernet header */
 			skb_reserve(skb, NET_IP_ALIGN);
 		} else {
-			bp->rx_ring[entry].addr &= ~MACB_BIT(RX_USED);
-			bp->rx_ring[entry].ctrl = 0;
+			desc->addr &= ~MACB_BIT(RX_USED);
+			desc->ctrl = 0;
 		}
 	}
 
@@ -813,17 +892,14 @@ static int gem_rx(struct macb *bp, int b
 		dma_addr_t addr;
 		bool rxused;
 
-		entry = macb_rx_ring_wrap(bp->rx_tail);
-		desc = &bp->rx_ring[entry];
+		entry = macb_rx_ring_wrap(bp, bp->rx_tail);
+		desc = macb_rx_desc(bp, entry);
 
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
 
 		rxused = (desc->addr & MACB_BIT(RX_USED)) ? true : false;
-		addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-		addr |= ((u64)(desc->addrh) << 32);
-#endif
+		addr = macb_get_addr(bp, desc);
 		ctrl = desc->ctrl;
 
 		if (!rxused)
@@ -895,8 +971,8 @@ static int macb_rx_frame(struct macb *bp
 	len = desc->ctrl & bp->rx_frm_len_mask;
 
 	netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-		    macb_rx_ring_wrap(first_frag),
-		    macb_rx_ring_wrap(last_frag), len);
+		macb_rx_ring_wrap(bp, first_frag),
+		macb_rx_ring_wrap(bp, last_frag), len);
 
 	/* The ethernet header starts NET_IP_ALIGN bytes into the
 	 * first buffer. Since the header is 14 bytes, this makes the
@@ -966,15 +1042,17 @@ static int macb_rx_frame(struct macb *bp
 static inline void macb_init_rx_ring(struct macb *bp)
 {
 	dma_addr_t addr;
+	struct macb_dma_desc *desc = NULL;
 	int i;
 
 	addr = bp->rx_buffers_dma;
-	for (i = 0; i < RX_RING_SIZE; i++) {
-		bp->rx_ring[i].addr = addr;
-		bp->rx_ring[i].ctrl = 0;
+	for (i = 0; i < bp->rx_ring_size; i++) {
+		desc = macb_rx_desc(bp, i);
+		macb_set_addr(bp, desc, addr);
+		desc->ctrl = 0;
 		addr += bp->rx_buffer_size;
 	}
-	bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+	desc->addr |= MACB_BIT(RX_WRAP);
 	bp->rx_tail = 0;
 }
 
@@ -987,15 +1065,14 @@ static int macb_rx(struct macb *bp, int
 
 	for (tail = bp->rx_tail; budget > 0; tail++) {
 		struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
-		u32 addr, ctrl;
+		u32 ctrl;
 
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
 
-		addr = desc->addr;
 		ctrl = desc->ctrl;
 
-		if (!(addr & MACB_BIT(RX_USED)))
+		if (!(desc->addr & MACB_BIT(RX_USED)))
 			break;
 
 		if (ctrl & MACB_BIT(RX_SOF)) {
@@ -1214,7 +1291,8 @@ static void macb_poll_controller(struct
 
 static unsigned int macb_tx_map(struct macb *bp,
 				struct macb_queue *queue,
-				struct sk_buff *skb)
+				struct sk_buff *skb,
+				unsigned int hdrlen)
 {
 	dma_addr_t mapping;
 	unsigned int len, entry, i, tx_head = queue->tx_head;
@@ -1222,15 +1300,28 @@ static unsigned int macb_tx_map(struct m
 	struct macb_dma_desc *desc;
 	unsigned int offset, size, count = 0;
 	unsigned int f, nr_frags = skb_shinfo(skb)->nr_frags;
-	unsigned int eof = 1;
-	u32 ctrl;
+	unsigned int eof = 1, mss_mfs = 0;
+	u32 ctrl, lso_ctrl = 0, seq_ctrl = 0;
+
+	/* LSO */
+	if (skb_shinfo(skb)->gso_size != 0) {
+		if (ip_hdr(skb)->protocol == IPPROTO_UDP)
+			/* UDP - UFO */
+			lso_ctrl = MACB_LSO_UFO_ENABLE;
+		else
+			/* TCP - TSO */
+			lso_ctrl = MACB_LSO_TSO_ENABLE;
+	}
 
 	/* First, map non-paged data */
 	len = skb_headlen(skb);
+
+	/* first buffer length */
+	size = hdrlen;
+
 	offset = 0;
 	while (len) {
-		size = min(len, bp->max_tx_length);
-		entry = macb_tx_ring_wrap(tx_head);
+		entry = macb_tx_ring_wrap(bp, tx_head);
 		tx_skb = &queue->tx_skb[entry];
 
 		mapping = dma_map_single(&bp->pdev->dev,
@@ -1249,6 +1340,8 @@ static unsigned int macb_tx_map(struct m
 		offset += size;
 		count++;
 		tx_head++;
+
+		size = min(len, bp->max_tx_length);
 	}
 
 	/* Then, map paged data from fragments */
@@ -1259,7 +1352,7 @@ static unsigned int macb_tx_map(struct m
 		offset = 0;
 		while (len) {
 			size = min(len, bp->max_tx_length);
-			entry = macb_tx_ring_wrap(tx_head);
+			entry = macb_tx_ring_wrap(bp, tx_head);
 			tx_skb = &queue->tx_skb[entry];
 
 			mapping = skb_frag_dma_map(&bp->pdev->dev, frag,
@@ -1297,27 +1390,52 @@ static unsigned int macb_tx_map(struct m
 	 * to set the end of TX queue
 	 */
 	i = tx_head;
-	entry = macb_tx_ring_wrap(i);
+	entry = macb_tx_ring_wrap(bp, i);
 	ctrl = MACB_BIT(TX_USED);
-	desc = &queue->tx_ring[entry];
+	desc = macb_tx_desc(queue, entry);
 	desc->ctrl = ctrl;
 
+	if (lso_ctrl) {
+		if (lso_ctrl == MACB_LSO_UFO_ENABLE)
+			/* include header and FCS in value given to h/w */
+			mss_mfs = skb_shinfo(skb)->gso_size +
+					skb_transport_offset(skb) +
+					ETH_FCS_LEN;
+		else /* TSO */ {
+			mss_mfs = skb_shinfo(skb)->gso_size;
+			/* TCP Sequence Number Source Select
+			 * can be set only for TSO
+			 */
+			seq_ctrl = 0;
+		}
+	}
+
 	do {
 		i--;
-		entry = macb_tx_ring_wrap(i);
+		entry = macb_tx_ring_wrap(bp, i);
 		tx_skb = &queue->tx_skb[entry];
-		desc = &queue->tx_ring[entry];
+		desc = macb_tx_desc(queue, entry);
 
 		ctrl = (u32)tx_skb->size;
 		if (eof) {
 			ctrl |= MACB_BIT(TX_LAST);
 			eof = 0;
 		}
-		if (unlikely(entry == (TX_RING_SIZE - 1)))
+		if (unlikely(entry == (bp->tx_ring_size - 1)))
 			ctrl |= MACB_BIT(TX_WRAP);
 
+		/* First descriptor is header descriptor */
+		if (i == queue->tx_head) {
+			ctrl |= MACB_BF(TX_LSO, lso_ctrl);
+			ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
+		} else
+			/* Only set MSS/MFS on payload descriptors
+			 * (second or later descriptor)
+			 */
+			ctrl |= MACB_BF(MSS_MFS, mss_mfs);
+
 		/* Set TX buffer descriptor */
-		macb_set_addr(desc, tx_skb->mapping);
+		macb_set_addr(bp, desc, tx_skb->mapping);
 		/* desc->addr must be visible to hardware before clearing
 		 * 'TX_USED' bit in desc->ctrl.
 		 */
@@ -1341,6 +1459,43 @@ dma_error:
 	return 0;
 }
 
+static netdev_features_t macb_features_check(struct sk_buff *skb,
+					     struct net_device *dev,
+					     netdev_features_t features)
+{
+	unsigned int nr_frags, f;
+	unsigned int hdrlen;
+
+	/* Validate LSO compatibility */
+
+	/* there is only one buffer */
+	if (!skb_is_nonlinear(skb))
+		return features;
+
+	/* length of header */
+	hdrlen = skb_transport_offset(skb);
+	if (ip_hdr(skb)->protocol == IPPROTO_TCP)
+		hdrlen += tcp_hdrlen(skb);
+
+	/* For LSO:
+	 * When software supplies two or more payload buffers all payload buffers
+	 * apart from the last must be a multiple of 8 bytes in size.
+	 */
+	if (!IS_ALIGNED(skb_headlen(skb) - hdrlen, MACB_TX_LEN_ALIGN))
+		return features & ~MACB_NETIF_LSO;
+
+	nr_frags = skb_shinfo(skb)->nr_frags;
+	/* No need to check last fragment */
+	nr_frags--;
+	for (f = 0; f < nr_frags; f++) {
+		const skb_frag_t *frag = &skb_shinfo(skb)->frags[f];
+
+		if (!IS_ALIGNED(skb_frag_size(frag), MACB_TX_LEN_ALIGN))
+			return features & ~MACB_NETIF_LSO;
+	}
+	return features;
+}
+
 static inline int macb_clear_csum(struct sk_buff *skb)
 {
 	/* no change for packets without checksum offloading */
@@ -1365,7 +1520,28 @@ static int macb_start_xmit(struct sk_buf
 	struct macb *bp = netdev_priv(dev);
 	struct macb_queue *queue = &bp->queues[queue_index];
 	unsigned long flags;
-	unsigned int count, nr_frags, frag_size, f;
+	unsigned int desc_cnt, nr_frags, frag_size, f;
+	unsigned int hdrlen;
+	bool is_lso, is_udp = 0;
+
+	is_lso = (skb_shinfo(skb)->gso_size != 0);
+
+	if (is_lso) {
+		is_udp = !!(ip_hdr(skb)->protocol == IPPROTO_UDP);
+
+		/* length of headers */
+		if (is_udp)
+			/* only queue eth + ip headers separately for UDP */
+			hdrlen = skb_transport_offset(skb);
+		else
+			hdrlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
+		if (skb_headlen(skb) < hdrlen) {
+			netdev_err(bp->dev, "Error - LSO headers fragmented!!!\n");
+			/* if this is required, would need to copy to single buffer */
+			return NETDEV_TX_BUSY;
+		}
+	} else
+		hdrlen = min(skb_headlen(skb), bp->max_tx_length);
 
 #if defined(DEBUG) && defined(VERBOSE_DEBUG)
 	netdev_vdbg(bp->dev,
@@ -1380,17 +1556,22 @@ static int macb_start_xmit(struct sk_buf
 	 * socket buffer: skb fragments of jumbo frames may need to be
 	 * split into many buffer descriptors.
 	 */
-	count = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length);
+	if (is_lso && (skb_headlen(skb) > hdrlen))
+		/* extra header descriptor if also payload in first buffer */
+		desc_cnt = DIV_ROUND_UP((skb_headlen(skb) - hdrlen), bp->max_tx_length) + 1;
+	else
+		desc_cnt = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length);
 	nr_frags = skb_shinfo(skb)->nr_frags;
 	for (f = 0; f < nr_frags; f++) {
 		frag_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
-		count += DIV_ROUND_UP(frag_size, bp->max_tx_length);
+		desc_cnt += DIV_ROUND_UP(frag_size, bp->max_tx_length);
 	}
 
 	spin_lock_irqsave(&bp->lock, flags);
 
 	/* This is a hard error, log it. */
-	if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < count) {
+	if (CIRC_SPACE(queue->tx_head, queue->tx_tail,
+		       bp->tx_ring_size) < desc_cnt) {
 		netif_stop_subqueue(dev, queue_index);
 		spin_unlock_irqrestore(&bp->lock, flags);
 		netdev_dbg(bp->dev, "tx_head = %u, tx_tail = %u\n",
@@ -1404,7 +1585,7 @@ static int macb_start_xmit(struct sk_buf
 	}
 
 	/* Map socket buffer for DMA transfer */
-	if (!macb_tx_map(bp, queue, skb)) {
+	if (!macb_tx_map(bp, queue, skb, hdrlen)) {
 		dev_kfree_skb_any(skb);
 		goto unlock;
 	}
@@ -1416,7 +1597,7 @@ static int macb_start_xmit(struct sk_buf
 
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
-	if (CIRC_SPACE(queue->tx_head, queue->tx_tail, TX_RING_SIZE) < 1)
+	if (CIRC_SPACE(queue->tx_head, queue->tx_tail, bp->tx_ring_size) < 1)
 		netif_stop_subqueue(dev, queue_index);
 
 unlock:
@@ -1455,17 +1636,15 @@ static void gem_free_rx_buffers(struct m
 	if (!bp->rx_skbuff)
 		return;
 
-	for (i = 0; i < RX_RING_SIZE; i++) {
+	for (i = 0; i < bp->rx_ring_size; i++) {
 		skb = bp->rx_skbuff[i];
 
 		if (!skb)
 			continue;
 
-		desc = &bp->rx_ring[i];
-		addr = MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
-#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-		addr |= ((u64)(desc->addrh) << 32);
-#endif
+		desc = macb_rx_desc(bp, i);
+		addr = macb_get_addr(bp, desc);
+
 		dma_unmap_single(&bp->pdev->dev, addr, bp->rx_buffer_size,
 				 DMA_FROM_DEVICE);
 		dev_kfree_skb_any(skb);
@@ -1480,7 +1659,7 @@ static void macb_free_rx_buffers(struct
 {
 	if (bp->rx_buffers) {
 		dma_free_coherent(&bp->pdev->dev,
-				  RX_RING_SIZE * bp->rx_buffer_size,
+				  bp->rx_ring_size * bp->rx_buffer_size,
 				  bp->rx_buffers, bp->rx_buffers_dma);
 		bp->rx_buffers = NULL;
 	}
@@ -1493,7 +1672,7 @@ static void macb_free_consistent(struct
 
 	bp->macbgem_ops.mog_free_rx_buffers(bp);
 	if (bp->rx_ring) {
-		dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES,
+		dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES(bp),
 				  bp->rx_ring, bp->rx_ring_dma);
 		bp->rx_ring = NULL;
 	}
@@ -1502,7 +1681,7 @@ static void macb_free_consistent(struct
 		kfree(queue->tx_skb);
 		queue->tx_skb = NULL;
 		if (queue->tx_ring) {
-			dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES,
+			dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES(bp),
 					  queue->tx_ring, queue->tx_ring_dma);
 			queue->tx_ring = NULL;
 		}
@@ -1513,14 +1692,14 @@ static int gem_alloc_rx_buffers(struct m
 {
 	int size;
 
-	size = RX_RING_SIZE * sizeof(struct sk_buff *);
+	size = bp->rx_ring_size * sizeof(struct sk_buff *);
 	bp->rx_skbuff = kzalloc(size, GFP_KERNEL);
 	if (!bp->rx_skbuff)
 		return -ENOMEM;
-
-	netdev_dbg(bp->dev,
-		   "Allocated %d RX struct sk_buff entries at %p\n",
-		   RX_RING_SIZE, bp->rx_skbuff);
+	else
+		netdev_dbg(bp->dev,
+			   "Allocated %d RX struct sk_buff entries at %p\n",
+			   bp->rx_ring_size, bp->rx_skbuff);
 	return 0;
 }
 
@@ -1528,7 +1707,7 @@ static int macb_alloc_rx_buffers(struct
 {
 	int size;
 
-	size = RX_RING_SIZE * bp->rx_buffer_size;
+	size = bp->rx_ring_size * bp->rx_buffer_size;
 	bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size,
 					    &bp->rx_buffers_dma, GFP_KERNEL);
 	if (!bp->rx_buffers)
@@ -1547,7 +1726,7 @@ static int macb_alloc_consistent(struct
 	int size;
 
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		size = TX_RING_BYTES;
+		size = TX_RING_BYTES(bp);
 		queue->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
 						    &queue->tx_ring_dma,
 						    GFP_KERNEL);
@@ -1558,13 +1737,13 @@ static int macb_alloc_consistent(struct
 			   q, size, (unsigned long)queue->tx_ring_dma,
 			   queue->tx_ring);
 
-		size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
+		size = bp->tx_ring_size * sizeof(struct macb_tx_skb);
 		queue->tx_skb = kmalloc(size, GFP_KERNEL);
 		if (!queue->tx_skb)
 			goto out_err;
 	}
 
-	size = RX_RING_BYTES;
+	size = RX_RING_BYTES(bp);
 	bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size,
 					 &bp->rx_ring_dma, GFP_KERNEL);
 	if (!bp->rx_ring)
@@ -1586,15 +1765,17 @@ out_err:
 static void gem_init_rings(struct macb *bp)
 {
 	struct macb_queue *queue;
+	struct macb_dma_desc *desc = NULL;
 	unsigned int q;
 	int i;
 
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		for (i = 0; i < TX_RING_SIZE; i++) {
-			macb_set_addr(&(queue->tx_ring[i]), 0);
-			queue->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+		for (i = 0; i < bp->tx_ring_size; i++) {
+			desc = macb_tx_desc(queue, i);
+			macb_set_addr(bp, desc, 0);
+			desc->ctrl = MACB_BIT(TX_USED);
 		}
-		queue->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+		desc->ctrl |= MACB_BIT(TX_WRAP);
 		queue->tx_head = 0;
 		queue->tx_tail = 0;
 	}
@@ -1608,16 +1789,18 @@ static void gem_init_rings(struct macb *
 static void macb_init_rings(struct macb *bp)
 {
 	int i;
+	struct macb_dma_desc *desc = NULL;
 
 	macb_init_rx_ring(bp);
 
-	for (i = 0; i < TX_RING_SIZE; i++) {
-		bp->queues[0].tx_ring[i].addr = 0;
-		bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED);
+	for (i = 0; i < bp->tx_ring_size; i++) {
+		desc = macb_tx_desc(&bp->queues[0], i);
+		macb_set_addr(bp, desc, 0);
+		desc->ctrl = MACB_BIT(TX_USED);
 	}
 	bp->queues[0].tx_head = 0;
 	bp->queues[0].tx_tail = 0;
-	bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+	desc->ctrl |= MACB_BIT(TX_WRAP);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -1738,7 +1921,8 @@ static void macb_configure_dma(struct ma
 			dmacfg &= ~GEM_BIT(TXCOEN);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-		dmacfg |= GEM_BIT(ADDR64);
+		if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+			dmacfg |= GEM_BIT(ADDR64);
 #endif
 		netdev_dbg(bp->dev, "Cadence configure DMA with 0x%08x\n",
 			   dmacfg);
@@ -1785,14 +1969,16 @@ static void macb_init_hw(struct macb *bp
 	macb_configure_dma(bp);
 
 	/* Initialize TX and RX buffers */
-	macb_writel(bp, RBQP, (u32)(bp->rx_ring_dma));
+	macb_writel(bp, RBQP, lower_32_bits(bp->rx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	macb_writel(bp, RBQPH, (u32)(bp->rx_ring_dma >> 32));
+	if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+		macb_writel(bp, RBQPH, upper_32_bits(bp->rx_ring_dma));
 #endif
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-		queue_writel(queue, TBQP, (u32)(queue->tx_ring_dma));
+		queue_writel(queue, TBQP, lower_32_bits(queue->tx_ring_dma));
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-		queue_writel(queue, TBQPH, (u32)(queue->tx_ring_dma >> 32));
+		if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+			queue_writel(queue, TBQPH, upper_32_bits(queue->tx_ring_dma));
 #endif
 
 		/* Enable interrupts */
@@ -1986,19 +2172,9 @@ static int macb_close(struct net_device
 
 static int macb_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct macb *bp = netdev_priv(dev);
-	u32 max_mtu;
-
 	if (netif_running(dev))
 		return -EBUSY;
 
-	max_mtu = ETH_DATA_LEN;
-	if (bp->caps & MACB_CAPS_JUMBO)
-		max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
-
-	if ((new_mtu > max_mtu) || (new_mtu < GEM_MTU_MIN_SIZE))
-		return -EINVAL;
-
 	dev->mtu = new_mtu;
 
 	return 0;
@@ -2158,8 +2334,8 @@ static void macb_get_regs(struct net_dev
 	regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
 			| MACB_GREGS_VERSION;
 
-	tail = macb_tx_ring_wrap(bp->queues[0].tx_tail);
-	head = macb_tx_ring_wrap(bp->queues[0].tx_head);
+	tail = macb_tx_ring_wrap(bp, bp->queues[0].tx_tail);
+	head = macb_tx_ring_wrap(bp, bp->queues[0].tx_head);
 
 	regs_buff[0]  = macb_readl(bp, NCR);
 	regs_buff[1]  = macb_or_gem_readl(bp, NCFGR);
@@ -2214,6 +2390,56 @@ static int macb_set_wol(struct net_devic
 	return 0;
 }
 
+static void macb_get_ringparam(struct net_device *netdev,
+			       struct ethtool_ringparam *ring)
+{
+	struct macb *bp = netdev_priv(netdev);
+
+	ring->rx_max_pending = MAX_RX_RING_SIZE;
+	ring->tx_max_pending = MAX_TX_RING_SIZE;
+
+	ring->rx_pending = bp->rx_ring_size;
+	ring->tx_pending = bp->tx_ring_size;
+}
+
+static int macb_set_ringparam(struct net_device *netdev,
+			      struct ethtool_ringparam *ring)
+{
+	struct macb *bp = netdev_priv(netdev);
+	u32 new_rx_size, new_tx_size;
+	unsigned int reset = 0;
+
+	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+		return -EINVAL;
+
+	new_rx_size = clamp_t(u32, ring->rx_pending,
+			      MIN_RX_RING_SIZE, MAX_RX_RING_SIZE);
+	new_rx_size = roundup_pow_of_two(new_rx_size);
+
+	new_tx_size = clamp_t(u32, ring->tx_pending,
+			      MIN_TX_RING_SIZE, MAX_TX_RING_SIZE);
+	new_tx_size = roundup_pow_of_two(new_tx_size);
+
+	if ((new_tx_size == bp->tx_ring_size) &&
+	    (new_rx_size == bp->rx_ring_size)) {
+		/* nothing to do */
+		return 0;
+	}
+
+	if (netif_running(bp->dev)) {
+		reset = 1;
+		macb_close(bp->dev);
+	}
+
+	bp->rx_ring_size = new_rx_size;
+	bp->tx_ring_size = new_tx_size;
+
+	if (reset)
+		macb_open(bp->dev);
+
+	return 0;
+}
+
 static const struct ethtool_ops macb_ethtool_ops = {
 	.get_regs_len		= macb_get_regs_len,
 	.get_regs		= macb_get_regs,
@@ -2223,6 +2449,8 @@ static const struct ethtool_ops macb_eth
 	.set_wol		= macb_set_wol,
 	.get_link_ksettings     = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings     = phy_ethtool_set_link_ksettings,
+	.get_ringparam		= macb_get_ringparam,
+	.set_ringparam		= macb_set_ringparam,
 };
 
 static const struct ethtool_ops gem_ethtool_ops = {
@@ -2235,6 +2463,8 @@ static const struct ethtool_ops gem_etht
 	.get_sset_count		= gem_get_sset_count,
 	.get_link_ksettings     = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings     = phy_ethtool_set_link_ksettings,
+	.get_ringparam		= macb_get_ringparam,
+	.set_ringparam		= macb_set_ringparam,
 };
 
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -2298,6 +2528,7 @@ static const struct net_device_ops macb_
 	.ndo_poll_controller	= macb_poll_controller,
 #endif
 	.ndo_set_features	= macb_set_features,
+	.ndo_features_check	= macb_features_check,
 };
 
 /* Configure peripheral capabilities according to device tree
@@ -2358,16 +2589,24 @@ static int macb_clk_init(struct platform
 			 struct clk **hclk, struct clk **tx_clk,
 			 struct clk **rx_clk)
 {
+	struct macb_platform_data *pdata;
 	int err;
 
-	*pclk = devm_clk_get(&pdev->dev, "pclk");
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata) {
+		*pclk = pdata->pclk;
+		*hclk = pdata->hclk;
+	} else {
+		*pclk = devm_clk_get(&pdev->dev, "pclk");
+		*hclk = devm_clk_get(&pdev->dev, "hclk");
+	}
+
 	if (IS_ERR(*pclk)) {
 		err = PTR_ERR(*pclk);
 		dev_err(&pdev->dev, "failed to get macb_clk (%u)\n", err);
 		return err;
 	}
 
-	*hclk = devm_clk_get(&pdev->dev, "hclk");
 	if (IS_ERR(*hclk)) {
 		err = PTR_ERR(*hclk);
 		dev_err(&pdev->dev, "failed to get hclk (%u)\n", err);
@@ -2429,6 +2668,9 @@ static int macb_init(struct platform_dev
 	int err;
 	u32 val;
 
+	bp->tx_ring_size = DEFAULT_TX_RING_SIZE;
+	bp->rx_ring_size = DEFAULT_RX_RING_SIZE;
+
 	/* set the queue register mapping once for all: queue0 has a special
 	 * register mapping but we don't want to test the queue index then
 	 * compute the corresponding register offset at run time.
@@ -2446,7 +2688,8 @@ static int macb_init(struct platform_dev
 			queue->IMR  = GEM_IMR(hw_q - 1);
 			queue->TBQP = GEM_TBQP(hw_q - 1);
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-			queue->TBQPH = GEM_TBQPH(hw_q -1);
+			if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+				queue->TBQPH = GEM_TBQPH(hw_q - 1);
 #endif
 		} else {
 			/* queue0 uses legacy registers */
@@ -2456,7 +2699,8 @@ static int macb_init(struct platform_dev
 			queue->IMR  = MACB_IMR;
 			queue->TBQP = MACB_TBQP;
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-			queue->TBQPH = MACB_TBQPH;
+			if (bp->hw_dma_cap == HW_DMA_CAP_64B)
+				queue->TBQPH = MACB_TBQPH;
 #endif
 		}
 
@@ -2501,6 +2745,11 @@ static int macb_init(struct platform_dev
 
 	/* Set features */
 	dev->hw_features = NETIF_F_SG;
+
+	/* Check LSO capability */
+	if (GEM_BFEXT(PBUF_LSO, gem_readl(bp, DCFG6)))
+		dev->hw_features |= MACB_NETIF_LSO;
+
 	/* Checksum offload is only available on gem with packet buffer */
 	if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
 		dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
@@ -2544,13 +2793,14 @@ static int macb_init(struct platform_dev
 static int at91ether_start(struct net_device *dev)
 {
 	struct macb *lp = netdev_priv(dev);
+	struct macb_dma_desc *desc;
 	dma_addr_t addr;
 	u32 ctl;
 	int i;
 
 	lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
 					 (AT91ETHER_MAX_RX_DESCR *
-					  sizeof(struct macb_dma_desc)),
+					  macb_dma_desc_get_size(lp)),
 					 &lp->rx_ring_dma, GFP_KERNEL);
 	if (!lp->rx_ring)
 		return -ENOMEM;
@@ -2562,7 +2812,7 @@ static int at91ether_start(struct net_de
 	if (!lp->rx_buffers) {
 		dma_free_coherent(&lp->pdev->dev,
 				  AT91ETHER_MAX_RX_DESCR *
-				  sizeof(struct macb_dma_desc),
+				  macb_dma_desc_get_size(lp),
 				  lp->rx_ring, lp->rx_ring_dma);
 		lp->rx_ring = NULL;
 		return -ENOMEM;
@@ -2570,13 +2820,14 @@ static int at91ether_start(struct net_de
 
 	addr = lp->rx_buffers_dma;
 	for (i = 0; i < AT91ETHER_MAX_RX_DESCR; i++) {
-		lp->rx_ring[i].addr = addr;
-		lp->rx_ring[i].ctrl = 0;
+		desc = macb_rx_desc(lp, i);
+		macb_set_addr(lp, desc, addr);
+		desc->ctrl = 0;
 		addr += AT91ETHER_MAX_RBUFF_SZ;
 	}
 
 	/* Set the Wrap bit on the last descriptor */
-	lp->rx_ring[AT91ETHER_MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
+	desc->addr |= MACB_BIT(RX_WRAP);
 
 	/* Reset buffer index */
 	lp->rx_tail = 0;
@@ -2648,7 +2899,7 @@ static int at91ether_close(struct net_de
 
 	dma_free_coherent(&lp->pdev->dev,
 			  AT91ETHER_MAX_RX_DESCR *
-			  sizeof(struct macb_dma_desc),
+			  macb_dma_desc_get_size(lp),
 			  lp->rx_ring, lp->rx_ring_dma);
 	lp->rx_ring = NULL;
 
@@ -2699,13 +2950,15 @@ static int at91ether_start_xmit(struct s
 static void at91ether_rx(struct net_device *dev)
 {
 	struct macb *lp = netdev_priv(dev);
+	struct macb_dma_desc *desc;
 	unsigned char *p_recv;
 	struct sk_buff *skb;
 	unsigned int pktlen;
 
-	while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+	desc = macb_rx_desc(lp, lp->rx_tail);
+	while (desc->addr & MACB_BIT(RX_USED)) {
 		p_recv = lp->rx_buffers + lp->rx_tail * AT91ETHER_MAX_RBUFF_SZ;
-		pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
+		pktlen = MACB_BF(RX_FRMLEN, desc->ctrl);
 		skb = netdev_alloc_skb(dev, pktlen + 2);
 		if (skb) {
 			skb_reserve(skb, 2);
@@ -2719,17 +2972,19 @@ static void at91ether_rx(struct net_devi
 			lp->stats.rx_dropped++;
 		}
 
-		if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
+		if (desc->ctrl & MACB_BIT(RX_MHASH_MATCH))
 			lp->stats.multicast++;
 
 		/* reset ownership bit */
-		lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
+		desc->addr &= ~MACB_BIT(RX_USED);
 
 		/* wrap after last buffer */
 		if (lp->rx_tail == AT91ETHER_MAX_RX_DESCR - 1)
 			lp->rx_tail = 0;
 		else
 			lp->rx_tail++;
+
+		desc = macb_rx_desc(lp, lp->rx_tail);
 	}
 }
 
@@ -2800,7 +3055,6 @@ static const struct net_device_ops at91e
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_do_ioctl		= macb_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
@@ -2935,15 +3189,23 @@ static const struct of_device_id macb_dt
 MODULE_DEVICE_TABLE(of, macb_dt_ids);
 #endif /* CONFIG_OF */
 
+static const struct macb_config default_gem_config = {
+	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO,
+	.dma_burst_length = 16,
+	.clk_init = macb_clk_init,
+	.init = macb_init,
+	.jumbo_max_len = 10240,
+};
+
 static int macb_probe(struct platform_device *pdev)
 {
+	const struct macb_config *macb_config = &default_gem_config;
 	int (*clk_init)(struct platform_device *, struct clk **,
 			struct clk **, struct clk **,  struct clk **)
-					      = macb_clk_init;
-	int (*init)(struct platform_device *) = macb_init;
+					      = macb_config->clk_init;
+	int (*init)(struct platform_device *) = macb_config->init;
 	struct device_node *np = pdev->dev.of_node;
 	struct device_node *phy_node;
-	const struct macb_config *macb_config = NULL;
 	struct clk *pclk, *hclk = NULL, *tx_clk = NULL, *rx_clk = NULL;
 	unsigned int queue_mask, num_queues;
 	struct macb_platform_data *pdata;
@@ -3018,8 +3280,11 @@ static int macb_probe(struct platform_de
 	device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	if (GEM_BFEXT(DBWDEF, gem_readl(bp, DCFG1)) > GEM_DBW32)
+	if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
 		dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+		bp->hw_dma_cap = HW_DMA_CAP_64B;
+	} else
+		bp->hw_dma_cap = HW_DMA_CAP_32B;
 #endif
 
 	spin_lock_init(&bp->lock);
@@ -3035,6 +3300,13 @@ static int macb_probe(struct platform_de
 		goto err_out_free_netdev;
 	}
 
+	/* MTU range: 68 - 1500 or 10240 */
+	dev->min_mtu = GEM_MTU_MIN_SIZE;
+	if (bp->caps & MACB_CAPS_JUMBO)
+		dev->max_mtu = gem_readl(bp, JML) - ETH_HLEN - ETH_FCS_LEN;
+	else
+		dev->max_mtu = ETH_DATA_LEN;
+
 	mac = of_get_mac_address(np);
 	if (mac)
 		ether_addr_copy(bp->dev->dev_addr, mac);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cadence/macb.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/macb.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cadence/macb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/macb.h	2017-02-12 16:03:20.000000000 -0500
@@ -382,6 +382,12 @@
 #define GEM_TX_PKT_BUFF_OFFSET			21
 #define GEM_TX_PKT_BUFF_SIZE			1
 
+/* Bitfields in DCFG6. */
+#define GEM_PBUF_LSO_OFFSET			27
+#define GEM_PBUF_LSO_SIZE			1
+#define GEM_DAW64_OFFSET			23
+#define GEM_DAW64_SIZE				1
+
 /* Constants for CLK */
 #define MACB_CLK_DIV8				0
 #define MACB_CLK_DIV16				1
@@ -414,6 +420,10 @@
 #define MACB_CAPS_SG_DISABLED			0x40000000
 #define MACB_CAPS_MACB_IS_GEM			0x80000000
 
+/* LSO settings */
+#define MACB_LSO_UFO_ENABLE			0x01
+#define MACB_LSO_TSO_ENABLE			0x02
+
 /* Bit manipulation macros */
 #define MACB_BIT(name)					\
 	(1 << MACB_##name##_OFFSET)
@@ -479,12 +489,20 @@
 struct macb_dma_desc {
 	u32	addr;
 	u32	ctrl;
+};
+
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
-	u32     addrh;
-	u32     resvd;
-#endif
+enum macb_hw_dma_cap {
+	HW_DMA_CAP_32B,
+	HW_DMA_CAP_64B,
 };
 
+struct macb_dma_desc_64 {
+	u32 addrh;
+	u32 resvd;
+};
+#endif
+
 /* DMA descriptor bitfields */
 #define MACB_RX_USED_OFFSET			0
 #define MACB_RX_USED_SIZE			1
@@ -545,6 +563,12 @@ struct macb_dma_desc {
 #define MACB_TX_LAST_SIZE			1
 #define MACB_TX_NOCRC_OFFSET			16
 #define MACB_TX_NOCRC_SIZE			1
+#define MACB_MSS_MFS_OFFSET			16
+#define MACB_MSS_MFS_SIZE			14
+#define MACB_TX_LSO_OFFSET			17
+#define MACB_TX_LSO_SIZE			2
+#define MACB_TX_TCP_SEQ_SRC_OFFSET		19
+#define MACB_TX_TCP_SEQ_SRC_SIZE		1
 #define MACB_TX_BUF_EXHAUSTED_OFFSET		27
 #define MACB_TX_BUF_EXHAUSTED_SIZE		1
 #define MACB_TX_UNDERRUN_OFFSET			28
@@ -811,6 +835,9 @@ struct macb {
 	void			*rx_buffers;
 	size_t			rx_buffer_size;
 
+	unsigned int		rx_ring_size;
+	unsigned int		tx_ring_size;
+
 	unsigned int		num_queues;
 	unsigned int		queue_mask;
 	struct macb_queue	queues[MACB_MAX_QUEUES];
@@ -857,6 +884,10 @@ struct macb {
 	unsigned int		jumbo_max_len;
 
 	u32			wol;
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	enum macb_hw_dma_cap hw_dma_cap;
+#endif
 };
 
 static inline bool macb_is_gem(struct macb *bp)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cadence/macb_pci.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/macb_pci.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cadence/macb_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/macb_pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,146 @@
+/**
+ * Cadence GEM PCI wrapper.
+ *
+ * Copyright (C) 2016 Cadence Design Systems - http://www.cadence.com
+ *
+ * Authors: Rafal Ozieblo <rafalo@cadence.com>
+ *	    Bartosz Folta <bfolta@cadence.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_data/macb.h>
+#include <linux/platform_device.h>
+#include "macb.h"
+
+#define PCI_DRIVER_NAME "macb_pci"
+#define PLAT_DRIVER_NAME "macb"
+
+#define CDNS_VENDOR_ID 0x17cd
+#define CDNS_DEVICE_ID 0xe007
+
+#define GEM_PCLK_RATE 50000000
+#define GEM_HCLK_RATE 50000000
+
+static int macb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int err;
+	struct platform_device *plat_dev;
+	struct platform_device_info plat_info;
+	struct macb_platform_data plat_data;
+	struct resource res[2];
+
+	/* enable pci device */
+	err = pcim_enable_device(pdev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Enabling PCI device has failed: %d", err);
+		return err;
+	}
+
+	pci_set_master(pdev);
+
+	/* set up resources */
+	memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
+	res[0].start = pci_resource_start(pdev, 0);
+	res[0].end = pci_resource_end(pdev, 0);
+	res[0].name = PCI_DRIVER_NAME;
+	res[0].flags = IORESOURCE_MEM;
+	res[1].start = pci_irq_vector(pdev, 0);
+	res[1].name = PCI_DRIVER_NAME;
+	res[1].flags = IORESOURCE_IRQ;
+
+	dev_info(&pdev->dev, "EMAC physical base addr: %pa\n",
+		 &res[0].start);
+
+	/* set up macb platform data */
+	memset(&plat_data, 0, sizeof(plat_data));
+
+	/* initialize clocks */
+	plat_data.pclk = clk_register_fixed_rate(&pdev->dev, "pclk", NULL, 0,
+						 GEM_PCLK_RATE);
+	if (IS_ERR(plat_data.pclk)) {
+		err = PTR_ERR(plat_data.pclk);
+		goto err_pclk_register;
+	}
+
+	plat_data.hclk = clk_register_fixed_rate(&pdev->dev, "hclk", NULL, 0,
+						 GEM_HCLK_RATE);
+	if (IS_ERR(plat_data.hclk)) {
+		err = PTR_ERR(plat_data.hclk);
+		goto err_hclk_register;
+	}
+
+	/* set up platform device info */
+	memset(&plat_info, 0, sizeof(plat_info));
+	plat_info.parent = &pdev->dev;
+	plat_info.fwnode = pdev->dev.fwnode;
+	plat_info.name = PLAT_DRIVER_NAME;
+	plat_info.id = pdev->devfn;
+	plat_info.res = res;
+	plat_info.num_res = ARRAY_SIZE(res);
+	plat_info.data = &plat_data;
+	plat_info.size_data = sizeof(plat_data);
+	plat_info.dma_mask = pdev->dma_mask;
+
+	/* register platform device */
+	plat_dev = platform_device_register_full(&plat_info);
+	if (IS_ERR(plat_dev)) {
+		err = PTR_ERR(plat_dev);
+		goto err_plat_dev_register;
+	}
+
+	pci_set_drvdata(pdev, plat_dev);
+
+	return 0;
+
+err_plat_dev_register:
+	clk_unregister(plat_data.hclk);
+
+err_hclk_register:
+	clk_unregister(plat_data.pclk);
+
+err_pclk_register:
+	return err;
+}
+
+static void macb_remove(struct pci_dev *pdev)
+{
+	struct platform_device *plat_dev = pci_get_drvdata(pdev);
+	struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);
+
+	platform_device_unregister(plat_dev);
+	clk_unregister(plat_data->pclk);
+	clk_unregister(plat_data->hclk);
+}
+
+static struct pci_device_id dev_id_table[] = {
+	{ PCI_DEVICE(CDNS_VENDOR_ID, CDNS_DEVICE_ID), },
+	{ 0, }
+};
+
+static struct pci_driver macb_pci_driver = {
+	.name     = PCI_DRIVER_NAME,
+	.id_table = dev_id_table,
+	.probe    = macb_probe,
+	.remove	  = macb_remove,
+};
+
+module_pci_driver(macb_pci_driver);
+MODULE_DEVICE_TABLE(pci, dev_id_table);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cadence NIC PCI wrapper");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cadence/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/cadence/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cadence/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_MACB) += macb.o
+obj-$(CONFIG_MACB_PCI) += macb_pci.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/calxeda/xgmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/calxeda/xgmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/calxeda/xgmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/calxeda/xgmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -394,7 +394,7 @@ struct xgmac_priv {
 };
 
 /* XGMAC Configuration Settings */
-#define MAX_MTU			9000
+#define XGMAC_MAX_MTU		9000
 #define PAUSE_TIME		0x400
 
 #define DMA_RX_RING_SZ		256
@@ -1360,20 +1360,6 @@ out:
  */
 static int xgmac_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct xgmac_priv *priv = netdev_priv(dev);
-	int old_mtu;
-
-	if ((new_mtu < 46) || (new_mtu > MAX_MTU)) {
-		netdev_err(priv->dev, "invalid MTU, max MTU is: %d\n", MAX_MTU);
-		return -EINVAL;
-	}
-
-	old_mtu = dev->mtu;
-
-	/* return early if the buffer sizes will not change */
-	if (old_mtu == new_mtu)
-		return 0;
-
 	/* Stop everything, get ready to change the MTU */
 	if (!netif_running(dev))
 		return 0;
@@ -1544,15 +1530,14 @@ static const struct net_device_ops xgmac
 	.ndo_set_features = xgmac_set_features,
 };
 
-static int xgmac_ethtool_getsettings(struct net_device *dev,
-					  struct ethtool_cmd *cmd)
+static int xgmac_ethtool_get_link_ksettings(struct net_device *dev,
+					    struct ethtool_link_ksettings *cmd)
 {
-	cmd->autoneg = 0;
-	cmd->duplex = DUPLEX_FULL;
-	ethtool_cmd_speed_set(cmd, 10000);
-	cmd->supported = 0;
-	cmd->advertising = 0;
-	cmd->transceiver = XCVR_INTERNAL;
+	cmd->base.autoneg = 0;
+	cmd->base.duplex = DUPLEX_FULL;
+	cmd->base.speed = 10000;
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 0);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 0);
 	return 0;
 }
 
@@ -1695,7 +1680,6 @@ static int xgmac_set_wol(struct net_devi
 }
 
 static const struct ethtool_ops xgmac_ethtool_ops = {
-	.get_settings = xgmac_ethtool_getsettings,
 	.get_link = ethtool_op_get_link,
 	.get_pauseparam = xgmac_get_pauseparam,
 	.set_pauseparam = xgmac_set_pauseparam,
@@ -1704,6 +1688,7 @@ static const struct ethtool_ops xgmac_et
 	.get_wol = xgmac_get_wol,
 	.set_wol = xgmac_set_wol,
 	.get_sset_count = xgmac_get_sset_count,
+	.get_link_ksettings = xgmac_ethtool_get_link_ksettings,
 };
 
 /**
@@ -1804,6 +1789,10 @@ static int xgmac_probe(struct platform_d
 	ndev->features |= ndev->hw_features;
 	ndev->priv_flags |= IFF_UNICAST_FLT;
 
+	/* MTU range: 46 - 9000 */
+	ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
+	ndev->max_mtu = XGMAC_MAX_MTU;
+
 	/* Get the MAC address */
 	xgmac_get_mac_addr(priv->base, ndev->dev_addr, 0);
 	if (!is_valid_ether_addr(ndev->dev_addr))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -53,7 +53,7 @@ config	THUNDER_NIC_RGX
 config LIQUIDIO
 	tristate "Cavium LiquidIO support"
 	depends on 64BIT
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	select FW_LOADER
 	select LIBCRC32C
 	---help---
@@ -74,4 +74,16 @@ config OCTEON_MGMT_ETHERNET
 	  port on Cavium Networks' Octeon CN57XX, CN56XX, CN55XX,
 	  CN54XX, CN52XX, and CN6XXX chips.
 
+config LIQUIDIO_VF
+	tristate "Cavium LiquidIO VF support"
+	depends on 64BIT && PCI_MSI
+	imply PTP_1588_CLOCK
+	---help---
+	  This driver supports Cavium LiquidIO Intelligent Server Adapter
+	  based on CN23XX chips.
+
+	  To compile this driver as a module, choose M here: The module
+	  will be called liquidio_vf. MSI-X interrupt support is required
+	  for this driver to work correctly
+
 endif # NET_VENDOR_CAVIUM
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,28 +1,23 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/pci.h>
-#include <linux/netdevice.h>
 #include <linux/vmalloc.h>
+#include <linux/etherdevice.h>
 #include "liquidio_common.h"
 #include "octeon_droq.h"
 #include "octeon_iq.h"
@@ -30,6 +25,7 @@
 #include "octeon_device.h"
 #include "cn23xx_pf_device.h"
 #include "octeon_main.h"
+#include "octeon_mailbox.h"
 
 #define RESET_NOTDONE 0
 #define RESET_DONE 1
@@ -40,11 +36,6 @@
  */
 #define CN23XX_INPUT_JABBER 64600
 
-#define LIOLUT_RING_DISTRIBUTION 9
-const int liolut_num_vfs_to_rings_per_vf[LIOLUT_RING_DISTRIBUTION] = {
-	0, 8, 4, 2, 2, 2, 1, 1, 1
-};
-
 void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct)
 {
 	int i = 0;
@@ -309,9 +300,10 @@ u32 cn23xx_pf_get_oq_ticks(struct octeon
 
 static void cn23xx_setup_global_mac_regs(struct octeon_device *oct)
 {
-	u64 reg_val;
 	u16 mac_no = oct->pcie_port;
 	u16 pf_num = oct->pf_num;
+	u64 reg_val;
+	u64 temp;
 
 	/* programming SRN and TRS for each MAC(0..3)  */
 
@@ -333,6 +325,14 @@ static void cn23xx_setup_global_mac_regs
 	/* setting TRS <23:16> */
 	reg_val = reg_val |
 		  (oct->sriov_info.trs << CN23XX_PKT_MAC_CTL_RINFO_TRS_BIT_POS);
+	/* setting RPVF <39:32> */
+	temp = oct->sriov_info.rings_per_vf & 0xff;
+	reg_val |= (temp << CN23XX_PKT_MAC_CTL_RINFO_RPVF_BIT_POS);
+
+	/* setting NVFS <55:48> */
+	temp = oct->sriov_info.max_vfs & 0xff;
+	reg_val |= (temp << CN23XX_PKT_MAC_CTL_RINFO_NVFS_BIT_POS);
+
 	/* write these settings to MAC register */
 	octeon_write_csr64(oct, CN23XX_SLI_PKT_MAC_RINFO64(mac_no, pf_num),
 			   reg_val);
@@ -399,11 +399,12 @@ static int cn23xx_reset_io_queues(struct
 
 static int cn23xx_pf_setup_global_input_regs(struct octeon_device *oct)
 {
+	struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
+	struct octeon_instr_queue *iq;
+	u64 intr_threshold, reg_val;
 	u32 q_no, ern, srn;
 	u64 pf_num;
-	u64 intr_threshold, reg_val;
-	struct octeon_instr_queue *iq;
-	struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
+	u64 vf_num;
 
 	pf_num = oct->pf_num;
 
@@ -414,12 +415,22 @@ static int cn23xx_pf_setup_global_input_
 		return -1;
 
 	/** Set the MAC_NUM and PVF_NUM in IQ_PKT_CONTROL reg
-	* for all queues.Only PF can set these bits.
-	* bits 29:30 indicate the MAC num.
-	* bits 32:47 indicate the PVF num.
-	*/
+	 * for all queues.Only PF can set these bits.
+	 * bits 29:30 indicate the MAC num.
+	 * bits 32:47 indicate the PVF num.
+	 */
 	for (q_no = 0; q_no < ern; q_no++) {
 		reg_val = oct->pcie_port << CN23XX_PKT_INPUT_CTL_MAC_NUM_POS;
+
+		/* for VF assigned queues. */
+		if (q_no < oct->sriov_info.pf_srn) {
+			vf_num = q_no / oct->sriov_info.rings_per_vf;
+			vf_num += 1; /* VF1, VF2,........ */
+		} else {
+			vf_num = 0;
+		}
+
+		reg_val |= vf_num << CN23XX_PKT_INPUT_CTL_VF_NUM_POS;
 		reg_val |= pf_num << CN23XX_PKT_INPUT_CTL_PF_NUM_POS;
 
 		octeon_write_csr64(oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
@@ -530,8 +541,8 @@ static void cn23xx_pf_setup_global_outpu
 	writeq(0x40, (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_OQ_WMARK);
 
 	/** Disabling setting OQs in reset when ring has no dorebells
-	  * enabling this will cause of head of line blocking
-	  */
+	 * enabling this will cause of head of line blocking
+	 */
 	/* Do it only for pass1.1. and pass1.2 */
 	if ((oct->rev_id == OCTEON_CN23XX_REV_1_0) ||
 	    (oct->rev_id == OCTEON_CN23XX_REV_1_1))
@@ -662,6 +673,118 @@ static void cn23xx_setup_oq_regs(struct
 	}
 }
 
+static void cn23xx_pf_mbox_thread(struct work_struct *work)
+{
+	struct cavium_wk *wk = (struct cavium_wk *)work;
+	struct octeon_mbox *mbox = (struct octeon_mbox *)wk->ctxptr;
+	struct octeon_device *oct = mbox->oct_dev;
+	u64 mbox_int_val, val64;
+	u32 q_no, i;
+
+	if (oct->rev_id < OCTEON_CN23XX_REV_1_1) {
+		/*read and clear by writing 1*/
+		mbox_int_val = readq(mbox->mbox_int_reg);
+		writeq(mbox_int_val, mbox->mbox_int_reg);
+
+		for (i = 0; i < oct->sriov_info.num_vfs_alloced; i++) {
+			q_no = i * oct->sriov_info.rings_per_vf;
+
+			val64 = readq(oct->mbox[q_no]->mbox_write_reg);
+
+			if (val64 && (val64 != OCTEON_PFVFACK)) {
+				if (octeon_mbox_read(oct->mbox[q_no]))
+					octeon_mbox_process_message(
+					    oct->mbox[q_no]);
+			}
+		}
+
+		schedule_delayed_work(&wk->work, msecs_to_jiffies(10));
+	} else {
+		octeon_mbox_process_message(mbox);
+	}
+}
+
+static int cn23xx_setup_pf_mbox(struct octeon_device *oct)
+{
+	struct octeon_mbox *mbox = NULL;
+	u16 mac_no = oct->pcie_port;
+	u16 pf_num = oct->pf_num;
+	u32 q_no, i;
+
+	if (!oct->sriov_info.max_vfs)
+		return 0;
+
+	for (i = 0; i < oct->sriov_info.max_vfs; i++) {
+		q_no = i * oct->sriov_info.rings_per_vf;
+
+		mbox = vmalloc(sizeof(*mbox));
+		if (!mbox)
+			goto free_mbox;
+
+		memset(mbox, 0, sizeof(struct octeon_mbox));
+
+		spin_lock_init(&mbox->lock);
+
+		mbox->oct_dev = oct;
+
+		mbox->q_no = q_no;
+
+		mbox->state = OCTEON_MBOX_STATE_IDLE;
+
+		/* PF mbox interrupt reg */
+		mbox->mbox_int_reg = (u8 *)oct->mmio[0].hw_addr +
+				     CN23XX_SLI_MAC_PF_MBOX_INT(mac_no, pf_num);
+
+		/* PF writes into SIG0 reg */
+		mbox->mbox_write_reg = (u8 *)oct->mmio[0].hw_addr +
+				       CN23XX_SLI_PKT_PF_VF_MBOX_SIG(q_no, 0);
+
+		/* PF reads from SIG1 reg */
+		mbox->mbox_read_reg = (u8 *)oct->mmio[0].hw_addr +
+				      CN23XX_SLI_PKT_PF_VF_MBOX_SIG(q_no, 1);
+
+		/*Mail Box Thread creation*/
+		INIT_DELAYED_WORK(&mbox->mbox_poll_wk.work,
+				  cn23xx_pf_mbox_thread);
+		mbox->mbox_poll_wk.ctxptr = (void *)mbox;
+
+		oct->mbox[q_no] = mbox;
+
+		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+	}
+
+	if (oct->rev_id < OCTEON_CN23XX_REV_1_1)
+		schedule_delayed_work(&oct->mbox[0]->mbox_poll_wk.work,
+				      msecs_to_jiffies(0));
+
+	return 0;
+
+free_mbox:
+	while (i) {
+		i--;
+		vfree(oct->mbox[i]);
+	}
+
+	return 1;
+}
+
+static int cn23xx_free_pf_mbox(struct octeon_device *oct)
+{
+	u32 q_no, i;
+
+	if (!oct->sriov_info.max_vfs)
+		return 0;
+
+	for (i = 0; i < oct->sriov_info.max_vfs; i++) {
+		q_no = i * oct->sriov_info.rings_per_vf;
+		cancel_delayed_work_sync(
+		    &oct->mbox[q_no]->mbox_poll_wk.work);
+		vfree(oct->mbox[q_no]);
+	}
+
+	return 0;
+}
+
 static int cn23xx_enable_io_queues(struct octeon_device *oct)
 {
 	u64 reg_val;
@@ -856,6 +979,29 @@ static u64 cn23xx_pf_msix_interrupt_hand
 	return ret;
 }
 
+static void cn23xx_handle_pf_mbox_intr(struct octeon_device *oct)
+{
+	struct delayed_work *work;
+	u64 mbox_int_val;
+	u32 i, q_no;
+
+	mbox_int_val = readq(oct->mbox[0]->mbox_int_reg);
+
+	for (i = 0; i < oct->sriov_info.num_vfs_alloced; i++) {
+		q_no = i * oct->sriov_info.rings_per_vf;
+
+		if (mbox_int_val & BIT_ULL(q_no)) {
+			writeq(BIT_ULL(q_no),
+			       oct->mbox[0]->mbox_int_reg);
+			if (octeon_mbox_read(oct->mbox[q_no])) {
+				work = &oct->mbox[q_no]->mbox_poll_wk.work;
+				schedule_delayed_work(work,
+						      msecs_to_jiffies(0));
+			}
+		}
+	}
+}
+
 static irqreturn_t cn23xx_interrupt_handler(void *dev)
 {
 	struct octeon_device *oct = (struct octeon_device *)dev;
@@ -871,6 +1017,10 @@ static irqreturn_t cn23xx_interrupt_hand
 		dev_err(&oct->pci_dev->dev, "OCTEON[%d]: Error Intr: 0x%016llx\n",
 			oct->octeon_id, CVM_CAST64(intr64));
 
+	/* When VFs write into MBOX_SIG2 reg,these intr is set in PF */
+	if (intr64 & CN23XX_INTR_VF_MBOX)
+		cn23xx_handle_pf_mbox_intr(oct);
+
 	if (oct->msix_on != LIO_FLAG_MSIX_ENABLED) {
 		if (intr64 & CN23XX_INTR_PKT_DATA)
 			oct->int_status |= OCT_DEV_INTR_PKT_DATA;
@@ -961,6 +1111,13 @@ static void cn23xx_enable_pf_interrupt(s
 		intr_val = readq(cn23xx->intr_enb_reg64);
 		intr_val |= CN23XX_INTR_PKT_DATA;
 		writeq(intr_val, cn23xx->intr_enb_reg64);
+	} else if ((intr_flag & OCTEON_MBOX_INTR) &&
+		   (oct->sriov_info.max_vfs > 0)) {
+		if (oct->rev_id >= OCTEON_CN23XX_REV_1_1) {
+			intr_val = readq(cn23xx->intr_enb_reg64);
+			intr_val |= CN23XX_INTR_VF_MBOX;
+			writeq(intr_val, cn23xx->intr_enb_reg64);
+		}
 	}
 }
 
@@ -976,6 +1133,13 @@ static void cn23xx_disable_pf_interrupt(
 		intr_val = readq(cn23xx->intr_enb_reg64);
 		intr_val &= ~CN23XX_INTR_PKT_DATA;
 		writeq(intr_val, cn23xx->intr_enb_reg64);
+	} else if ((intr_flag & OCTEON_MBOX_INTR) &&
+		   (oct->sriov_info.max_vfs > 0)) {
+		if (oct->rev_id >= OCTEON_CN23XX_REV_1_1) {
+			intr_val = readq(cn23xx->intr_enb_reg64);
+			intr_val &= ~CN23XX_INTR_VF_MBOX;
+			writeq(intr_val, cn23xx->intr_enb_reg64);
+		}
 	}
 }
 
@@ -1048,50 +1212,59 @@ static void cn23xx_setup_reg_address(str
 
 static int cn23xx_sriov_config(struct octeon_device *oct)
 {
-	u32 total_rings;
 	struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip;
-	/* num_vfs is already filled for us */
+	u32 max_rings, total_rings, max_vfs, rings_per_vf;
 	u32 pf_srn, num_pf_rings;
+	u32 max_possible_vfs;
 
 	cn23xx->conf =
-	    (struct octeon_config *)oct_get_config_info(oct, LIO_23XX);
+		(struct octeon_config *)oct_get_config_info(oct, LIO_23XX);
 	switch (oct->rev_id) {
 	case OCTEON_CN23XX_REV_1_0:
-		total_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_0;
+		max_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_0;
+		max_possible_vfs = CN23XX_MAX_VFS_PER_PF_PASS_1_0;
 		break;
 	case OCTEON_CN23XX_REV_1_1:
-		total_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_1;
+		max_rings = CN23XX_MAX_RINGS_PER_PF_PASS_1_1;
+		max_possible_vfs = CN23XX_MAX_VFS_PER_PF_PASS_1_1;
 		break;
 	default:
-		total_rings = CN23XX_MAX_RINGS_PER_PF;
+		max_rings = CN23XX_MAX_RINGS_PER_PF;
+		max_possible_vfs = CN23XX_MAX_VFS_PER_PF;
 		break;
 	}
-	if (!oct->sriov_info.num_pf_rings) {
-		if (total_rings > num_present_cpus())
-			num_pf_rings = num_present_cpus();
-		else
-			num_pf_rings = total_rings;
-	} else {
-		num_pf_rings = oct->sriov_info.num_pf_rings;
 
-		if (num_pf_rings > total_rings) {
-			dev_warn(&oct->pci_dev->dev,
-				 "num_queues_per_pf requested %u is more than available rings. Reducing to %u\n",
-				 num_pf_rings, total_rings);
-			num_pf_rings = total_rings;
-		}
-	}
+	if (max_rings <= num_present_cpus())
+		num_pf_rings = 1;
+	else
+		num_pf_rings = num_present_cpus();
+
+#ifdef CONFIG_PCI_IOV
+	max_vfs = min_t(u32,
+			(max_rings - num_pf_rings), max_possible_vfs);
+	rings_per_vf = 1;
+#else
+	max_vfs = 0;
+	rings_per_vf = 0;
+#endif
+
+	total_rings = num_pf_rings + max_vfs;
 
-	total_rings = num_pf_rings;
 	/* the first ring of the pf */
 	pf_srn = total_rings - num_pf_rings;
 
 	oct->sriov_info.trs = total_rings;
+	oct->sriov_info.max_vfs = max_vfs;
+	oct->sriov_info.rings_per_vf = rings_per_vf;
 	oct->sriov_info.pf_srn = pf_srn;
 	oct->sriov_info.num_pf_rings = num_pf_rings;
-	dev_dbg(&oct->pci_dev->dev, "trs:%d pf_srn:%d num_pf_rings:%d\n",
-		oct->sriov_info.trs, oct->sriov_info.pf_srn,
-		oct->sriov_info.num_pf_rings);
+	dev_notice(&oct->pci_dev->dev, "trs:%d max_vfs:%d rings_per_vf:%d pf_srn:%d num_pf_rings:%d\n",
+		   oct->sriov_info.trs, oct->sriov_info.max_vfs,
+		   oct->sriov_info.rings_per_vf, oct->sriov_info.pf_srn,
+		   oct->sriov_info.num_pf_rings);
+
+	oct->sriov_info.sriov_enabled = 0;
+
 	return 0;
 }
 
@@ -1119,6 +1292,9 @@ int setup_cn23xx_octeon_pf_device(struct
 
 	oct->fn_list.setup_iq_regs = cn23xx_setup_iq_regs;
 	oct->fn_list.setup_oq_regs = cn23xx_setup_oq_regs;
+	oct->fn_list.setup_mbox = cn23xx_setup_pf_mbox;
+	oct->fn_list.free_mbox = cn23xx_free_pf_mbox;
+
 	oct->fn_list.process_interrupt_regs = cn23xx_interrupt_handler;
 	oct->fn_list.msix_interrupt_handler = cn23xx_pf_msix_interrupt_handler;
 
@@ -1209,8 +1385,7 @@ void cn23xx_dump_iq_regs(struct octeon_d
 		dev_dbg(&oct->pci_dev->dev, "SLI_PKT[%d]_INPUT_CTL [0x%x]: 0x%016llx\n",
 			q_no, CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
 			CVM_CAST64(octeon_read_csr64
-				(oct,
-					CN23XX_SLI_IQ_PKT_CONTROL64(q_no))));
+				(oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no))));
 	}
 
 	pci_read_config_dword(oct->pci_dev, CN23XX_CONFIG_PCIE_DEVCTL, &regval);
@@ -1235,3 +1410,24 @@ int cn23xx_fw_loaded(struct octeon_devic
 	val = octeon_read_csr64(oct, CN23XX_SLI_SCRATCH1);
 	return (val >> 1) & 1ULL;
 }
+
+void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
+					u8 *mac)
+{
+	if (oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vfidx)) {
+		struct octeon_mbox_cmd mbox_cmd;
+
+		mbox_cmd.msg.u64 = 0;
+		mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST;
+		mbox_cmd.msg.s.resp_needed = 0;
+		mbox_cmd.msg.s.cmd = OCTEON_PF_CHANGED_VF_MACADDR;
+		mbox_cmd.msg.s.len = 1;
+		mbox_cmd.recv_len = 0;
+		mbox_cmd.recv_status = 0;
+		mbox_cmd.fn = NULL;
+		mbox_cmd.fn_arg = 0;
+		ether_addr_copy(mbox_cmd.msg.s.params, mac);
+		mbox_cmd.q_no = vfidx * oct->sriov_info.rings_per_vf;
+		octeon_mbox_write(oct, &mbox_cmd);
+	}
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,34 +1,31 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file  cn23xx_device.h
  * \brief Host Driver: Routines that perform CN23XX specific operations.
-*/
+ */
 
 #ifndef __CN23XX_PF_DEVICE_H__
 #define __CN23XX_PF_DEVICE_H__
 
 #include "cn23xx_pf_regs.h"
 
+#define LIO_CMD_WAIT_TM 100
+
 /* Register address and configuration for a CN23XX devices.
  * If device specific changes need to be made then add a struct to include
  * device specific fields as shown in the commented section
@@ -56,4 +53,7 @@ u32 cn23xx_pf_get_oq_ticks(struct octeon
 void cn23xx_dump_pf_initialized_regs(struct octeon_device *oct);
 
 int cn23xx_fw_loaded(struct octeon_device *oct);
+
+void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx,
+					u8 *mac);
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,29 +1,24 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file cn23xx_regs.h
  * \brief Host Driver: Register Address and Register Mask values for
  * Octeon CN23XX devices.
-*/
+ */
 
 #ifndef __CN23XX_PF_REGS_H__
 #define __CN23XX_PF_REGS_H__
@@ -63,7 +58,7 @@
 
 #define     CN23XX_CONFIG_SRIOV_BAR_START	   0x19C
 #define     CN23XX_CONFIG_SRIOV_BARX(i)		\
-		(CN23XX_CONFIG_SRIOV_BAR_START + (i * 4))
+		(CN23XX_CONFIG_SRIOV_BAR_START + ((i) * 4))
 #define     CN23XX_CONFIG_SRIOV_BAR_PF		   0x08
 #define     CN23XX_CONFIG_SRIOV_BAR_64BIT	   0x04
 #define     CN23XX_CONFIG_SRIOV_BAR_IO		   0x01
@@ -513,7 +508,7 @@
 /* 4 Registers (64 - bit) */
 #define    CN23XX_SLI_S2M_PORT_CTL_START         0x23D80
 #define    CN23XX_SLI_S2M_PORTX_CTL(port)	\
-		(CN23XX_SLI_S2M_PORT_CTL_START + (port * 0x10))
+		(CN23XX_SLI_S2M_PORT_CTL_START + ((port) * 0x10))
 
 #define    CN23XX_SLI_MAC_NUMBER                 0x20050
 
@@ -554,26 +549,26 @@
  * Provides DMA Engine Queue Enable
  */
 #define    CN23XX_DPI_DMA_ENG0_ENB        0x0001df0000000080ULL
-#define    CN23XX_DPI_DMA_ENG_ENB(eng) (CN23XX_DPI_DMA_ENG0_ENB + (eng * 8))
+#define    CN23XX_DPI_DMA_ENG_ENB(eng) (CN23XX_DPI_DMA_ENG0_ENB + ((eng) * 8))
 
 /* 8 register (64-bit) - DPI_DMA(0..7)_REQQ_CTL
  * Provides control bits for transaction on 8 Queues
  */
 #define    CN23XX_DPI_DMA_REQQ0_CTL       0x0001df0000000180ULL
 #define    CN23XX_DPI_DMA_REQQ_CTL(q_no)	\
-		(CN23XX_DPI_DMA_REQQ0_CTL + (q_no * 8))
+		(CN23XX_DPI_DMA_REQQ0_CTL + ((q_no) * 8))
 
 /* 6 register (64-bit) - DPI_ENG(0..5)_BUF
  * Provides DMA Engine FIFO (Queue) Size
  */
 #define    CN23XX_DPI_DMA_ENG0_BUF        0x0001df0000000880ULL
 #define    CN23XX_DPI_DMA_ENG_BUF(eng)   \
-		(CN23XX_DPI_DMA_ENG0_BUF + (eng * 8))
+		(CN23XX_DPI_DMA_ENG0_BUF + ((eng) * 8))
 
 /* 4 Registers (64-bit) */
 #define    CN23XX_DPI_SLI_PRT_CFG_START   0x0001df0000000900ULL
 #define    CN23XX_DPI_SLI_PRTX_CFG(port)        \
-		(CN23XX_DPI_SLI_PRT_CFG_START + (port * 0x8))
+		(CN23XX_DPI_SLI_PRT_CFG_START + ((port) * 0x8))
 
 /* Masks for DPI_DMA_CONTROL Register */
 #define    CN23XX_DPI_DMA_COMMIT_MODE     BIT_ULL(58)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,722 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+#include "cn23xx_vf_device.h"
+#include "octeon_main.h"
+#include "octeon_mailbox.h"
+
+u32 cn23xx_vf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us)
+{
+	/* This gives the SLI clock per microsec */
+	u32 oqticks_per_us = (u32)oct->pfvf_hsword.coproc_tics_per_us;
+
+	/* This gives the clock cycles per millisecond */
+	oqticks_per_us *= 1000;
+
+	/* This gives the oq ticks (1024 core clock cycles) per millisecond */
+	oqticks_per_us /= 1024;
+
+	/* time_intr is in microseconds. The next 2 steps gives the oq ticks
+	 * corressponding to time_intr.
+	 */
+	oqticks_per_us *= time_intr_in_us;
+	oqticks_per_us /= 1000;
+
+	return oqticks_per_us;
+}
+
+static int cn23xx_vf_reset_io_queues(struct octeon_device *oct, u32 num_queues)
+{
+	u32 loop = BUSY_READING_REG_VF_LOOP_COUNT;
+	int ret_val = 0;
+	u32 q_no;
+	u64 d64;
+
+	for (q_no = 0; q_no < num_queues; q_no++) {
+		/* set RST bit to 1. This bit applies to both IQ and OQ */
+		d64 = octeon_read_csr64(oct,
+					CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+		d64 |= CN23XX_PKT_INPUT_CTL_RST;
+		octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+				   d64);
+	}
+
+	/* wait until the RST bit is clear or the RST and QUIET bits are set */
+	for (q_no = 0; q_no < num_queues; q_no++) {
+		u64 reg_val = octeon_read_csr64(oct,
+					CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+		while ((READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_RST) &&
+		       !(READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_QUIET) &&
+		       loop) {
+			WRITE_ONCE(reg_val, octeon_read_csr64(
+			    oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no)));
+			loop--;
+		}
+		if (!loop) {
+			dev_err(&oct->pci_dev->dev,
+				"clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
+				q_no);
+			return -1;
+		}
+		WRITE_ONCE(reg_val, READ_ONCE(reg_val) &
+			   ~CN23XX_PKT_INPUT_CTL_RST);
+		octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+				   READ_ONCE(reg_val));
+
+		WRITE_ONCE(reg_val, octeon_read_csr64(
+		    oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no)));
+		if (READ_ONCE(reg_val) & CN23XX_PKT_INPUT_CTL_RST) {
+			dev_err(&oct->pci_dev->dev,
+				"clearing the reset failed for qno: %u\n",
+				q_no);
+			ret_val = -1;
+		}
+	}
+
+	return ret_val;
+}
+
+static int cn23xx_vf_setup_global_input_regs(struct octeon_device *oct)
+{
+	struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+	struct octeon_instr_queue *iq;
+	u64 q_no, intr_threshold;
+	u64 d64;
+
+	if (cn23xx_vf_reset_io_queues(oct, oct->sriov_info.rings_per_vf))
+		return -1;
+
+	for (q_no = 0; q_no < (oct->sriov_info.rings_per_vf); q_no++) {
+		void __iomem *inst_cnt_reg;
+
+		octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_DOORBELL(q_no),
+				   0xFFFFFFFF);
+		iq = oct->instr_queue[q_no];
+
+		if (iq)
+			inst_cnt_reg = iq->inst_cnt_reg;
+		else
+			inst_cnt_reg = (u8 *)oct->mmio[0].hw_addr +
+				       CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no);
+
+		d64 = octeon_read_csr64(oct,
+					CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no));
+
+		d64 &= 0xEFFFFFFFFFFFFFFFL;
+
+		octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no),
+				   d64);
+
+		/* Select ES, RO, NS, RDSIZE,DPTR Fomat#0 for
+		 * the Input Queues
+		 */
+		octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+				   CN23XX_PKT_INPUT_CTL_MASK);
+
+		/* set the wmark level to trigger PI_INT */
+		intr_threshold = CFG_GET_IQ_INTR_PKT(cn23xx->conf) &
+				 CN23XX_PKT_IN_DONE_WMARK_MASK;
+
+		writeq((readq(inst_cnt_reg) &
+			~(CN23XX_PKT_IN_DONE_WMARK_MASK <<
+			  CN23XX_PKT_IN_DONE_WMARK_BIT_POS)) |
+		       (intr_threshold << CN23XX_PKT_IN_DONE_WMARK_BIT_POS),
+		       inst_cnt_reg);
+	}
+	return 0;
+}
+
+static void cn23xx_vf_setup_global_output_regs(struct octeon_device *oct)
+{
+	u32 reg_val;
+	u32 q_no;
+
+	for (q_no = 0; q_no < (oct->sriov_info.rings_per_vf); q_no++) {
+		octeon_write_csr(oct, CN23XX_VF_SLI_OQ_PKTS_CREDIT(q_no),
+				 0xFFFFFFFF);
+
+		reg_val =
+		    octeon_read_csr(oct, CN23XX_VF_SLI_OQ_PKTS_SENT(q_no));
+
+		reg_val &= 0xEFFFFFFFFFFFFFFFL;
+
+		reg_val =
+		    octeon_read_csr(oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no));
+
+		/* set IPTR & DPTR */
+		reg_val |=
+		    (CN23XX_PKT_OUTPUT_CTL_IPTR | CN23XX_PKT_OUTPUT_CTL_DPTR);
+
+		/* reset BMODE */
+		reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_BMODE);
+
+		/* No Relaxed Ordering, No Snoop, 64-bit Byte swap
+		 * for Output Queue ScatterList reset ROR_P, NSR_P
+		 */
+		reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ROR_P);
+		reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_NSR_P);
+
+#ifdef __LITTLE_ENDIAN_BITFIELD
+		reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ES_P);
+#else
+		reg_val |= (CN23XX_PKT_OUTPUT_CTL_ES_P);
+#endif
+		/* No Relaxed Ordering, No Snoop, 64-bit Byte swap
+		 * for Output Queue Data reset ROR, NSR
+		 */
+		reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_ROR);
+		reg_val &= ~(CN23XX_PKT_OUTPUT_CTL_NSR);
+		/* set the ES bit */
+		reg_val |= (CN23XX_PKT_OUTPUT_CTL_ES);
+
+		/* write all the selected settings */
+		octeon_write_csr(oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no),
+				 reg_val);
+	}
+}
+
+static int cn23xx_setup_vf_device_regs(struct octeon_device *oct)
+{
+	if (cn23xx_vf_setup_global_input_regs(oct))
+		return -1;
+
+	cn23xx_vf_setup_global_output_regs(oct);
+
+	return 0;
+}
+
+static void cn23xx_setup_vf_iq_regs(struct octeon_device *oct, u32 iq_no)
+{
+	struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
+	u64 pkt_in_done;
+
+	/* Write the start of the input queue's ring and its size */
+	octeon_write_csr64(oct, CN23XX_VF_SLI_IQ_BASE_ADDR64(iq_no),
+			   iq->base_addr_dma);
+	octeon_write_csr(oct, CN23XX_VF_SLI_IQ_SIZE(iq_no), iq->max_count);
+
+	/* Remember the doorbell & instruction count register addr
+	 * for this queue
+	 */
+	iq->doorbell_reg =
+	    (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_IQ_DOORBELL(iq_no);
+	iq->inst_cnt_reg =
+	    (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_IQ_INSTR_COUNT64(iq_no);
+	dev_dbg(&oct->pci_dev->dev, "InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p\n",
+		iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
+
+	/* Store the current instruction counter (used in flush_iq
+	 * calculation)
+	 */
+	pkt_in_done = readq(iq->inst_cnt_reg);
+
+	if (oct->msix_on) {
+		/* Set CINT_ENB to enable IQ interrupt */
+		writeq((pkt_in_done | CN23XX_INTR_CINT_ENB),
+		       iq->inst_cnt_reg);
+	}
+	iq->reset_instr_cnt = 0;
+}
+
+static void cn23xx_setup_vf_oq_regs(struct octeon_device *oct, u32 oq_no)
+{
+	struct octeon_droq *droq = oct->droq[oq_no];
+
+	octeon_write_csr64(oct, CN23XX_VF_SLI_OQ_BASE_ADDR64(oq_no),
+			   droq->desc_ring_dma);
+	octeon_write_csr(oct, CN23XX_VF_SLI_OQ_SIZE(oq_no), droq->max_count);
+
+	octeon_write_csr(oct, CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(oq_no),
+			 (droq->buffer_size | (OCT_RH_SIZE << 16)));
+
+	/* Get the mapped address of the pkt_sent and pkts_credit regs */
+	droq->pkts_sent_reg =
+	    (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_OQ_PKTS_SENT(oq_no);
+	droq->pkts_credit_reg =
+	    (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_OQ_PKTS_CREDIT(oq_no);
+}
+
+static void cn23xx_vf_mbox_thread(struct work_struct *work)
+{
+	struct cavium_wk *wk = (struct cavium_wk *)work;
+	struct octeon_mbox *mbox = (struct octeon_mbox *)wk->ctxptr;
+
+	octeon_mbox_process_message(mbox);
+}
+
+static int cn23xx_free_vf_mbox(struct octeon_device *oct)
+{
+	cancel_delayed_work_sync(&oct->mbox[0]->mbox_poll_wk.work);
+	vfree(oct->mbox[0]);
+	return 0;
+}
+
+static int cn23xx_setup_vf_mbox(struct octeon_device *oct)
+{
+	struct octeon_mbox *mbox = NULL;
+
+	mbox = vmalloc(sizeof(*mbox));
+	if (!mbox)
+		return 1;
+
+	memset(mbox, 0, sizeof(struct octeon_mbox));
+
+	spin_lock_init(&mbox->lock);
+
+	mbox->oct_dev = oct;
+
+	mbox->q_no = 0;
+
+	mbox->state = OCTEON_MBOX_STATE_IDLE;
+
+	/* VF mbox interrupt reg */
+	mbox->mbox_int_reg =
+	    (u8 *)oct->mmio[0].hw_addr + CN23XX_VF_SLI_PKT_MBOX_INT(0);
+	/* VF reads from SIG0 reg */
+	mbox->mbox_read_reg =
+	    (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_PKT_PF_VF_MBOX_SIG(0, 0);
+	/* VF writes into SIG1 reg */
+	mbox->mbox_write_reg =
+	    (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_PKT_PF_VF_MBOX_SIG(0, 1);
+
+	INIT_DELAYED_WORK(&mbox->mbox_poll_wk.work,
+			  cn23xx_vf_mbox_thread);
+
+	mbox->mbox_poll_wk.ctxptr = mbox;
+
+	oct->mbox[0] = mbox;
+
+	writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+
+	return 0;
+}
+
+static int cn23xx_enable_vf_io_queues(struct octeon_device *oct)
+{
+	u32 q_no;
+
+	for (q_no = 0; q_no < oct->num_iqs; q_no++) {
+		u64 reg_val;
+
+		/* set the corresponding IQ IS_64B bit */
+		if (oct->io_qmask.iq64B & BIT_ULL(q_no)) {
+			reg_val = octeon_read_csr64(
+			    oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+			reg_val |= CN23XX_PKT_INPUT_CTL_IS_64B;
+			octeon_write_csr64(
+			    oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
+		}
+
+		/* set the corresponding IQ ENB bit */
+		if (oct->io_qmask.iq & BIT_ULL(q_no)) {
+			reg_val = octeon_read_csr64(
+			    oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+			reg_val |= CN23XX_PKT_INPUT_CTL_RING_ENB;
+			octeon_write_csr64(
+			    oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no), reg_val);
+		}
+	}
+	for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+		u32 reg_val;
+
+		/* set the corresponding OQ ENB bit */
+		if (oct->io_qmask.oq & BIT_ULL(q_no)) {
+			reg_val = octeon_read_csr(
+			    oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no));
+			reg_val |= CN23XX_PKT_OUTPUT_CTL_RING_ENB;
+			octeon_write_csr(
+			    oct, CN23XX_VF_SLI_OQ_PKT_CONTROL(q_no), reg_val);
+		}
+	}
+
+	return 0;
+}
+
+static void cn23xx_disable_vf_io_queues(struct octeon_device *oct)
+{
+	u32 num_queues = oct->num_iqs;
+
+	/* per HRM, rings can only be disabled via reset operation,
+	 * NOT via SLI_PKT()_INPUT/OUTPUT_CONTROL[ENB]
+	 */
+	if (num_queues < oct->num_oqs)
+		num_queues = oct->num_oqs;
+
+	cn23xx_vf_reset_io_queues(oct, num_queues);
+}
+
+void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct)
+{
+	struct octeon_mbox_cmd mbox_cmd;
+
+	mbox_cmd.msg.u64 = 0;
+	mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST;
+	mbox_cmd.msg.s.resp_needed = 0;
+	mbox_cmd.msg.s.cmd = OCTEON_VF_FLR_REQUEST;
+	mbox_cmd.msg.s.len = 1;
+	mbox_cmd.q_no = 0;
+	mbox_cmd.recv_len = 0;
+	mbox_cmd.recv_status = 0;
+	mbox_cmd.fn = NULL;
+	mbox_cmd.fn_arg = 0;
+
+	octeon_mbox_write(oct, &mbox_cmd);
+}
+
+static void octeon_pfvf_hs_callback(struct octeon_device *oct,
+				    struct octeon_mbox_cmd *cmd,
+				    void *arg)
+{
+	u32 major = 0;
+
+	memcpy((uint8_t *)&oct->pfvf_hsword, cmd->msg.s.params,
+	       CN23XX_MAILBOX_MSGPARAM_SIZE);
+	if (cmd->recv_len > 1)  {
+		major = ((struct lio_version *)(cmd->data))->major;
+		major = major << 16;
+	}
+
+	atomic_set((atomic_t *)arg, major | 1);
+}
+
+int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct)
+{
+	struct octeon_mbox_cmd mbox_cmd;
+	u32 q_no, count = 0;
+	atomic_t status;
+	u32 pfmajor;
+	u32 vfmajor;
+	u32 ret;
+
+	/* Sending VF_ACTIVE indication to the PF driver */
+	dev_dbg(&oct->pci_dev->dev, "requesting info from pf\n");
+
+	mbox_cmd.msg.u64 = 0;
+	mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST;
+	mbox_cmd.msg.s.resp_needed = 1;
+	mbox_cmd.msg.s.cmd = OCTEON_VF_ACTIVE;
+	mbox_cmd.msg.s.len = 2;
+	mbox_cmd.data[0] = 0;
+	((struct lio_version *)&mbox_cmd.data[0])->major =
+						LIQUIDIO_BASE_MAJOR_VERSION;
+	((struct lio_version *)&mbox_cmd.data[0])->minor =
+						LIQUIDIO_BASE_MINOR_VERSION;
+	((struct lio_version *)&mbox_cmd.data[0])->micro =
+						LIQUIDIO_BASE_MICRO_VERSION;
+	mbox_cmd.q_no = 0;
+	mbox_cmd.recv_len = 0;
+	mbox_cmd.recv_status = 0;
+	mbox_cmd.fn = (octeon_mbox_callback_t)octeon_pfvf_hs_callback;
+	mbox_cmd.fn_arg = &status;
+
+	/* Interrupts are not enabled at this point.
+	 * Enable them with default oq ticks
+	 */
+	oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
+
+	octeon_mbox_write(oct, &mbox_cmd);
+
+	atomic_set(&status, 0);
+
+	do {
+		schedule_timeout_uninterruptible(1);
+	} while ((!atomic_read(&status)) && (count++ < 100000));
+
+	/* Disable the interrupt so that the interrupsts will be reenabled
+	 * with the oq ticks received from the PF
+	 */
+	oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
+
+	ret = atomic_read(&status);
+	if (!ret) {
+		dev_err(&oct->pci_dev->dev, "octeon_pfvf_handshake timeout\n");
+		return 1;
+	}
+
+	for (q_no = 0 ; q_no < oct->num_iqs ; q_no++)
+		oct->instr_queue[q_no]->txpciq.s.pkind = oct->pfvf_hsword.pkind;
+
+	vfmajor = LIQUIDIO_BASE_MAJOR_VERSION;
+	pfmajor = ret >> 16;
+	if (pfmajor != vfmajor) {
+		dev_err(&oct->pci_dev->dev,
+			"VF Liquidio driver (major version %d) is not compatible with Liquidio PF driver (major version %d)\n",
+			vfmajor, pfmajor);
+		return 1;
+	}
+
+	dev_dbg(&oct->pci_dev->dev,
+		"VF Liquidio driver (major version %d), Liquidio PF driver (major version %d)\n",
+		vfmajor, pfmajor);
+
+	dev_dbg(&oct->pci_dev->dev, "got data from pf pkind is %d\n",
+		oct->pfvf_hsword.pkind);
+
+	return 0;
+}
+
+static void cn23xx_handle_vf_mbox_intr(struct octeon_ioq_vector *ioq_vector)
+{
+	struct octeon_device *oct = ioq_vector->oct_dev;
+	u64 mbox_int_val;
+
+	if (!ioq_vector->droq_index) {
+		/* read and clear by writing 1 */
+		mbox_int_val = readq(oct->mbox[0]->mbox_int_reg);
+		writeq(mbox_int_val, oct->mbox[0]->mbox_int_reg);
+		if (octeon_mbox_read(oct->mbox[0]))
+			schedule_delayed_work(&oct->mbox[0]->mbox_poll_wk.work,
+					      msecs_to_jiffies(0));
+	}
+}
+
+static u64 cn23xx_vf_msix_interrupt_handler(void *dev)
+{
+	struct octeon_ioq_vector *ioq_vector = (struct octeon_ioq_vector *)dev;
+	struct octeon_device *oct = ioq_vector->oct_dev;
+	struct octeon_droq *droq = oct->droq[ioq_vector->droq_index];
+	u64 pkts_sent;
+	u64 ret = 0;
+
+	dev_dbg(&oct->pci_dev->dev, "In %s octeon_dev @ %p\n", __func__, oct);
+	pkts_sent = readq(droq->pkts_sent_reg);
+
+	/* If our device has interrupted, then proceed. Also check
+	 * for all f's if interrupt was triggered on an error
+	 * and the PCI read fails.
+	 */
+	if (!pkts_sent || (pkts_sent == 0xFFFFFFFFFFFFFFFFULL))
+		return ret;
+
+	/* Write count reg in sli_pkt_cnts to clear these int. */
+	if ((pkts_sent & CN23XX_INTR_PO_INT) ||
+	    (pkts_sent & CN23XX_INTR_PI_INT)) {
+		if (pkts_sent & CN23XX_INTR_PO_INT)
+			ret |= MSIX_PO_INT;
+	}
+
+	if (pkts_sent & CN23XX_INTR_PI_INT)
+		/* We will clear the count when we update the read_index. */
+		ret |= MSIX_PI_INT;
+
+	if (pkts_sent & CN23XX_INTR_MBOX_INT) {
+		cn23xx_handle_vf_mbox_intr(ioq_vector);
+		ret |= MSIX_MBOX_INT;
+	}
+
+	return ret;
+}
+
+static u32 cn23xx_update_read_index(struct octeon_instr_queue *iq)
+{
+	u32 pkt_in_done = readl(iq->inst_cnt_reg);
+	u32 last_done;
+	u32 new_idx;
+
+	last_done = pkt_in_done - iq->pkt_in_done;
+	iq->pkt_in_done = pkt_in_done;
+
+	/* Modulo of the new index with the IQ size will give us
+	 * the new index.  The iq->reset_instr_cnt is always zero for
+	 * cn23xx, so no extra adjustments are needed.
+	 */
+	new_idx = (iq->octeon_read_index +
+		   (u32)(last_done & CN23XX_PKT_IN_DONE_CNT_MASK)) %
+		  iq->max_count;
+
+	return new_idx;
+}
+
+static void cn23xx_enable_vf_interrupt(struct octeon_device *oct, u8 intr_flag)
+{
+	struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+	u32 q_no, time_threshold;
+
+	if (intr_flag & OCTEON_OUTPUT_INTR) {
+		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+			/* Set up interrupt packet and time thresholds
+			 * for all the OQs
+			 */
+			time_threshold = cn23xx_vf_get_oq_ticks(
+				oct, (u32)CFG_GET_OQ_INTR_TIME(cn23xx->conf));
+
+			octeon_write_csr64(
+			    oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+			    (CFG_GET_OQ_INTR_PKT(cn23xx->conf) |
+			     ((u64)time_threshold << 32)));
+		}
+	}
+
+	if (intr_flag & OCTEON_INPUT_INTR) {
+		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+			/* Set CINT_ENB to enable IQ interrupt */
+			octeon_write_csr64(
+			    oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no),
+			    ((octeon_read_csr64(
+				  oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no)) &
+			      ~CN23XX_PKT_IN_DONE_CNT_MASK) |
+			     CN23XX_INTR_CINT_ENB));
+		}
+	}
+
+	/* Set queue-0 MBOX_ENB to enable VF mailbox interrupt */
+	if (intr_flag & OCTEON_MBOX_INTR) {
+		octeon_write_csr64(
+		    oct, CN23XX_VF_SLI_PKT_MBOX_INT(0),
+		    (octeon_read_csr64(oct, CN23XX_VF_SLI_PKT_MBOX_INT(0)) |
+		     CN23XX_INTR_MBOX_ENB));
+	}
+}
+
+static void cn23xx_disable_vf_interrupt(struct octeon_device *oct, u8 intr_flag)
+{
+	u32 q_no;
+
+	if (intr_flag & OCTEON_OUTPUT_INTR) {
+		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+			/* Write all 1's in INT_LEVEL reg to disable PO_INT */
+			octeon_write_csr64(
+			    oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+			    0x3fffffffffffff);
+		}
+	}
+	if (intr_flag & OCTEON_INPUT_INTR) {
+		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+			octeon_write_csr64(
+			    oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no),
+			    (octeon_read_csr64(
+				 oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no)) &
+			     ~(CN23XX_INTR_CINT_ENB |
+			       CN23XX_PKT_IN_DONE_CNT_MASK)));
+		}
+	}
+
+	if (intr_flag & OCTEON_MBOX_INTR) {
+		octeon_write_csr64(
+		    oct, CN23XX_VF_SLI_PKT_MBOX_INT(0),
+		    (octeon_read_csr64(oct, CN23XX_VF_SLI_PKT_MBOX_INT(0)) &
+		     ~CN23XX_INTR_MBOX_ENB));
+	}
+}
+
+int cn23xx_setup_octeon_vf_device(struct octeon_device *oct)
+{
+	struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip;
+	u32 rings_per_vf, ring_flag;
+	u64 reg_val;
+
+	if (octeon_map_pci_barx(oct, 0, 0))
+		return 1;
+
+	/* INPUT_CONTROL[RPVF] gives the VF IOq count */
+	reg_val = octeon_read_csr64(oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(0));
+
+	oct->pf_num = (reg_val >> CN23XX_PKT_INPUT_CTL_PF_NUM_POS) &
+		      CN23XX_PKT_INPUT_CTL_PF_NUM_MASK;
+	oct->vf_num = (reg_val >> CN23XX_PKT_INPUT_CTL_VF_NUM_POS) &
+		      CN23XX_PKT_INPUT_CTL_VF_NUM_MASK;
+
+	reg_val = reg_val >> CN23XX_PKT_INPUT_CTL_RPVF_POS;
+
+	rings_per_vf = reg_val & CN23XX_PKT_INPUT_CTL_RPVF_MASK;
+
+	ring_flag = 0;
+
+	cn23xx->conf  = oct_get_config_info(oct, LIO_23XX);
+	if (!cn23xx->conf) {
+		dev_err(&oct->pci_dev->dev, "%s No Config found for CN23XX\n",
+			__func__);
+		octeon_unmap_pci_barx(oct, 0);
+		return 1;
+	}
+
+	if (oct->sriov_info.rings_per_vf > rings_per_vf) {
+		dev_warn(&oct->pci_dev->dev,
+			 "num_queues:%d greater than PF configured rings_per_vf:%d. Reducing to %d.\n",
+			 oct->sriov_info.rings_per_vf, rings_per_vf,
+			 rings_per_vf);
+		oct->sriov_info.rings_per_vf = rings_per_vf;
+	} else {
+		if (rings_per_vf > num_present_cpus()) {
+			dev_warn(&oct->pci_dev->dev,
+				 "PF configured rings_per_vf:%d greater than num_cpu:%d. Using rings_per_vf:%d equal to num cpus\n",
+				 rings_per_vf,
+				 num_present_cpus(),
+				 num_present_cpus());
+			oct->sriov_info.rings_per_vf =
+				num_present_cpus();
+		} else {
+			oct->sriov_info.rings_per_vf = rings_per_vf;
+		}
+	}
+
+	oct->fn_list.setup_iq_regs = cn23xx_setup_vf_iq_regs;
+	oct->fn_list.setup_oq_regs = cn23xx_setup_vf_oq_regs;
+	oct->fn_list.setup_mbox = cn23xx_setup_vf_mbox;
+	oct->fn_list.free_mbox = cn23xx_free_vf_mbox;
+
+	oct->fn_list.msix_interrupt_handler = cn23xx_vf_msix_interrupt_handler;
+
+	oct->fn_list.setup_device_regs = cn23xx_setup_vf_device_regs;
+	oct->fn_list.update_iq_read_idx = cn23xx_update_read_index;
+
+	oct->fn_list.enable_interrupt = cn23xx_enable_vf_interrupt;
+	oct->fn_list.disable_interrupt = cn23xx_disable_vf_interrupt;
+
+	oct->fn_list.enable_io_queues = cn23xx_enable_vf_io_queues;
+	oct->fn_list.disable_io_queues = cn23xx_disable_vf_io_queues;
+
+	return 0;
+}
+
+void cn23xx_dump_vf_iq_regs(struct octeon_device *oct)
+{
+	u32 regval, q_no;
+
+	dev_dbg(&oct->pci_dev->dev, "SLI_IQ_DOORBELL_0 [0x%x]: 0x%016llx\n",
+		CN23XX_VF_SLI_IQ_DOORBELL(0),
+		CVM_CAST64(octeon_read_csr64(
+					oct, CN23XX_VF_SLI_IQ_DOORBELL(0))));
+
+	dev_dbg(&oct->pci_dev->dev, "SLI_IQ_BASEADDR_0 [0x%x]: 0x%016llx\n",
+		CN23XX_VF_SLI_IQ_BASE_ADDR64(0),
+		CVM_CAST64(octeon_read_csr64(
+			oct, CN23XX_VF_SLI_IQ_BASE_ADDR64(0))));
+
+	dev_dbg(&oct->pci_dev->dev, "SLI_IQ_FIFO_RSIZE_0 [0x%x]: 0x%016llx\n",
+		CN23XX_VF_SLI_IQ_SIZE(0),
+		CVM_CAST64(octeon_read_csr64(oct, CN23XX_VF_SLI_IQ_SIZE(0))));
+
+	for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) {
+		dev_dbg(&oct->pci_dev->dev, "SLI_PKT[%d]_INPUT_CTL [0x%x]: 0x%016llx\n",
+			q_no, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no),
+			CVM_CAST64(octeon_read_csr64(
+				oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no))));
+	}
+
+	pci_read_config_dword(oct->pci_dev, CN23XX_CONFIG_PCIE_DEVCTL, &regval);
+	dev_dbg(&oct->pci_dev->dev, "Config DevCtl [0x%x]: 0x%08x\n",
+		CN23XX_CONFIG_PCIE_DEVCTL, regval);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,50 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
+/*! \file  cn23xx_device.h
+ * \brief Host Driver: Routines that perform CN23XX specific operations.
+ */
+
+#ifndef __CN23XX_VF_DEVICE_H__
+#define __CN23XX_VF_DEVICE_H__
+
+#include "cn23xx_vf_regs.h"
+
+/* Register address and configuration for a CN23XX devices.
+ * If device specific changes need to be made then add a struct to include
+ * device specific fields as shown in the commented section
+ */
+struct octeon_cn23xx_vf {
+	struct octeon_config *conf;
+};
+
+#define BUSY_READING_REG_VF_LOOP_COUNT		10000
+
+#define CN23XX_MAILBOX_MSGPARAM_SIZE		6
+
+#define MAX_VF_IP_OP_PENDING_PKT_COUNT		100
+
+void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct);
+
+int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct);
+
+int cn23xx_setup_octeon_vf_device(struct octeon_device *oct);
+
+u32 cn23xx_vf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us);
+
+void cn23xx_dump_vf_initialized_regs(struct octeon_device *oct);
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,274 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
+/*! \file cn23xx_vf_regs.h
+ * \brief Host Driver: Register Address and Register Mask values for
+ * Octeon CN23XX vf functions.
+ */
+
+#ifndef __CN23XX_VF_REGS_H__
+#define __CN23XX_VF_REGS_H__
+
+#define     CN23XX_CONFIG_XPANSION_BAR             0x38
+
+#define     CN23XX_CONFIG_PCIE_CAP                 0x70
+#define     CN23XX_CONFIG_PCIE_DEVCAP              0x74
+#define     CN23XX_CONFIG_PCIE_DEVCTL              0x78
+#define     CN23XX_CONFIG_PCIE_LINKCAP             0x7C
+#define     CN23XX_CONFIG_PCIE_LINKCTL             0x80
+#define     CN23XX_CONFIG_PCIE_SLOTCAP             0x84
+#define     CN23XX_CONFIG_PCIE_SLOTCTL             0x88
+
+#define     CN23XX_CONFIG_PCIE_FLTMSK              0x720
+
+/* The input jabber is used to determine the TSO max size.
+ * Due to H/W limitation, this need to be reduced to 60000
+ * in order to to H/W TSO and avoid the WQE malfarmation
+ * PKO_BUG_24989_WQE_LEN
+ */
+#define    CN23XX_DEFAULT_INPUT_JABBER             0xEA60 /*60000*/
+
+/* ##############  BAR0 Registers ################ */
+
+/* Each Input Queue register is at a 16-byte Offset in BAR0 */
+#define    CN23XX_VF_IQ_OFFSET                     0x20000
+
+/*###################### REQUEST QUEUE #########################*/
+
+/* 64 registers for Input Queue Instr Count - SLI_PKT_IN_DONE0_CNTS */
+#define    CN23XX_VF_SLI_IQ_INSTR_COUNT_START64     0x10040
+
+/* 64 registers for Input Queues Start Addr - SLI_PKT0_INSTR_BADDR */
+#define    CN23XX_VF_SLI_IQ_BASE_ADDR_START64       0x10010
+
+/* 64 registers for Input Doorbell - SLI_PKT0_INSTR_BAOFF_DBELL */
+#define    CN23XX_VF_SLI_IQ_DOORBELL_START          0x10020
+
+/* 64 registers for Input Queue size - SLI_PKT0_INSTR_FIFO_RSIZE */
+#define    CN23XX_VF_SLI_IQ_SIZE_START              0x10030
+
+/* 64 registers (64-bit) - ES, RO, NS, Arbitration for Input Queue Data &
+ * gather list fetches. SLI_PKT(0..63)_INPUT_CONTROL.
+ */
+#define    CN23XX_VF_SLI_IQ_PKT_CONTROL_START64     0x10000
+
+/*------- Request Queue Macros ---------*/
+#define CN23XX_VF_SLI_IQ_PKT_CONTROL64(iq)		\
+	(CN23XX_VF_SLI_IQ_PKT_CONTROL_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_BASE_ADDR64(iq)		\
+	(CN23XX_VF_SLI_IQ_BASE_ADDR_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_SIZE(iq)			\
+	(CN23XX_VF_SLI_IQ_SIZE_START + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_DOORBELL(iq)			\
+	(CN23XX_VF_SLI_IQ_DOORBELL_START + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+#define CN23XX_VF_SLI_IQ_INSTR_COUNT64(iq)		\
+	(CN23XX_VF_SLI_IQ_INSTR_COUNT_START64 + ((iq) * CN23XX_VF_IQ_OFFSET))
+
+/*------------------ Masks ----------------*/
+#define    CN23XX_PKT_INPUT_CTL_VF_NUM                  BIT_ULL(32)
+#define    CN23XX_PKT_INPUT_CTL_MAC_NUM                 BIT(29)
+/* Number of instructions to be read in one MAC read request.
+ * setting to Max value(4)
+ */
+#define    CN23XX_PKT_INPUT_CTL_RDSIZE                  (3 << 25)
+#define    CN23XX_PKT_INPUT_CTL_IS_64B                  BIT(24)
+#define    CN23XX_PKT_INPUT_CTL_RST                     BIT(23)
+#define    CN23XX_PKT_INPUT_CTL_QUIET                   BIT(28)
+#define    CN23XX_PKT_INPUT_CTL_RING_ENB                BIT(22)
+#define    CN23XX_PKT_INPUT_CTL_DATA_NS                 BIT(8)
+#define    CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP        BIT(6)
+#define    CN23XX_PKT_INPUT_CTL_DATA_RO                 BIT(5)
+#define    CN23XX_PKT_INPUT_CTL_USE_CSR                 BIT(4)
+#define    CN23XX_PKT_INPUT_CTL_GATHER_NS               BIT(3)
+#define    CN23XX_PKT_INPUT_CTL_GATHER_ES_64B_SWAP      (2)
+#define    CN23XX_PKT_INPUT_CTL_GATHER_RO               (1)
+
+/** Rings per Virtual Function [RO] **/
+#define    CN23XX_PKT_INPUT_CTL_RPVF_MASK               (0x3F)
+#define    CN23XX_PKT_INPUT_CTL_RPVF_POS                (48)
+/* These bits[47:44][RO] give the Physical function number info within the MAC*/
+#define    CN23XX_PKT_INPUT_CTL_PF_NUM_MASK             (0x7)
+#define    CN23XX_PKT_INPUT_CTL_PF_NUM_POS              (45)
+/** These bits[43:32][RO] give the virtual function number info within the PF*/
+#define    CN23XX_PKT_INPUT_CTL_VF_NUM_MASK             (0x1FFF)
+#define    CN23XX_PKT_INPUT_CTL_VF_NUM_POS              (32)
+#define    CN23XX_PKT_INPUT_CTL_MAC_NUM_MASK            (0x3)
+#define    CN23XX_PKT_INPUT_CTL_MAC_NUM_POS             (29)
+#define    CN23XX_PKT_IN_DONE_WMARK_MASK                (0xFFFFULL)
+#define    CN23XX_PKT_IN_DONE_WMARK_BIT_POS             (32)
+#define    CN23XX_PKT_IN_DONE_CNT_MASK                  (0x00000000FFFFFFFFULL)
+
+#ifdef __LITTLE_ENDIAN_BITFIELD
+#define CN23XX_PKT_INPUT_CTL_MASK			\
+	(CN23XX_PKT_INPUT_CTL_RDSIZE			\
+	 | CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP	\
+	 | CN23XX_PKT_INPUT_CTL_USE_CSR)
+#else
+#define CN23XX_PKT_INPUT_CTL_MASK			\
+	(CN23XX_PKT_INPUT_CTL_RDSIZE			\
+	 | CN23XX_PKT_INPUT_CTL_DATA_ES_64B_SWAP	\
+	 | CN23XX_PKT_INPUT_CTL_USE_CSR			\
+	 | CN23XX_PKT_INPUT_CTL_GATHER_ES_64B_SWAP)
+#endif
+
+/** Masks for SLI_PKT_IN_DONE(0..63)_CNTS Register */
+#define    CN23XX_IN_DONE_CNTS_PI_INT               BIT_ULL(62)
+#define    CN23XX_IN_DONE_CNTS_CINT_ENB             BIT_ULL(48)
+
+/*############################ OUTPUT QUEUE #########################*/
+
+/* 64 registers for Output queue control - SLI_PKT(0..63)_OUTPUT_CONTROL */
+#define    CN23XX_VF_SLI_OQ_PKT_CONTROL_START       0x10050
+
+/* 64 registers for Output queue buffer and info size - SLI_PKT0_OUT_SIZE */
+#define    CN23XX_VF_SLI_OQ0_BUFF_INFO_SIZE         0x10060
+
+/* 64 registers for Output Queue Start Addr - SLI_PKT0_SLIST_BADDR */
+#define    CN23XX_VF_SLI_OQ_BASE_ADDR_START64       0x10070
+
+/* 64 registers for Output Queue Packet Credits - SLI_PKT0_SLIST_BAOFF_DBELL */
+#define    CN23XX_VF_SLI_OQ_PKT_CREDITS_START       0x10080
+
+/* 64 registers for Output Queue size - SLI_PKT0_SLIST_FIFO_RSIZE */
+#define    CN23XX_VF_SLI_OQ_SIZE_START              0x10090
+
+/* 64 registers for Output Queue Packet Count - SLI_PKT0_CNTS */
+#define    CN23XX_VF_SLI_OQ_PKT_SENT_START          0x100B0
+
+/* 64 registers for Output Queue INT Levels - SLI_PKT0_INT_LEVELS */
+#define    CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64  0x100A0
+
+/* Each Output Queue register is at a 16-byte Offset in BAR0 */
+#define    CN23XX_VF_OQ_OFFSET                      0x20000
+
+/*------- Output Queue Macros ---------*/
+
+#define CN23XX_VF_SLI_OQ_PKT_CONTROL(oq)		\
+	(CN23XX_VF_SLI_OQ_PKT_CONTROL_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_BASE_ADDR64(oq)		\
+	(CN23XX_VF_SLI_OQ_BASE_ADDR_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_SIZE(oq)			\
+	(CN23XX_VF_SLI_OQ_SIZE_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(oq)		\
+	(CN23XX_VF_SLI_OQ0_BUFF_INFO_SIZE + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKTS_SENT(oq)		\
+	(CN23XX_VF_SLI_OQ_PKT_SENT_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKTS_CREDIT(oq)		\
+	(CN23XX_VF_SLI_OQ_PKT_CREDITS_START + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(oq)		\
+	(CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+/* Macro's for accessing CNT and TIME separately from INT_LEVELS */
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_CNT(oq)	\
+	(CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 + ((oq) * CN23XX_VF_OQ_OFFSET))
+
+#define CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_TIME(oq)	\
+	(CN23XX_VF_SLI_OQ_PKT_INT_LEVELS_START64 +	\
+	 ((oq) * CN23XX_VF_OQ_OFFSET) + 4)
+
+/*------------------ Masks ----------------*/
+#define    CN23XX_PKT_OUTPUT_CTL_TENB                  BIT(13)
+#define    CN23XX_PKT_OUTPUT_CTL_CENB                  BIT(12)
+#define    CN23XX_PKT_OUTPUT_CTL_IPTR                  BIT(11)
+#define    CN23XX_PKT_OUTPUT_CTL_ES                    BIT(9)
+#define    CN23XX_PKT_OUTPUT_CTL_NSR                   BIT(8)
+#define    CN23XX_PKT_OUTPUT_CTL_ROR                   BIT(7)
+#define    CN23XX_PKT_OUTPUT_CTL_DPTR                  BIT(6)
+#define    CN23XX_PKT_OUTPUT_CTL_BMODE                 BIT(5)
+#define    CN23XX_PKT_OUTPUT_CTL_ES_P                  BIT(3)
+#define    CN23XX_PKT_OUTPUT_CTL_NSR_P                 BIT(2)
+#define    CN23XX_PKT_OUTPUT_CTL_ROR_P                 BIT(1)
+#define    CN23XX_PKT_OUTPUT_CTL_RING_ENB              BIT(0)
+
+/*######################### Mailbox Reg Macros ########################*/
+#define    CN23XX_VF_SLI_PKT_MBOX_INT_START            0x10210
+#define    CN23XX_SLI_PKT_PF_VF_MBOX_SIG_START         0x10200
+
+#define    CN23XX_SLI_MBOX_OFFSET                      0x20000
+#define    CN23XX_SLI_MBOX_SIG_IDX_OFFSET              0x8
+
+#define CN23XX_VF_SLI_PKT_MBOX_INT(q)	\
+	(CN23XX_VF_SLI_PKT_MBOX_INT_START + ((q) * CN23XX_SLI_MBOX_OFFSET))
+
+#define CN23XX_SLI_PKT_PF_VF_MBOX_SIG(q, idx)		\
+	(CN23XX_SLI_PKT_PF_VF_MBOX_SIG_START +		\
+	 ((q) * CN23XX_SLI_MBOX_OFFSET +		\
+	  (idx) * CN23XX_SLI_MBOX_SIG_IDX_OFFSET))
+
+/*######################## INTERRUPTS #########################*/
+
+#define    CN23XX_VF_SLI_INT_SUM_START		  0x100D0
+
+#define CN23XX_VF_SLI_INT_SUM(q)			\
+	(CN23XX_VF_SLI_INT_SUM_START + ((q) * CN23XX_VF_IQ_OFFSET))
+
+/*------------------ Interrupt Masks ----------------*/
+
+#define    CN23XX_INTR_PO_INT                   BIT_ULL(63)
+#define    CN23XX_INTR_PI_INT                   BIT_ULL(62)
+#define    CN23XX_INTR_MBOX_INT                 BIT_ULL(61)
+#define    CN23XX_INTR_RESEND                   BIT_ULL(60)
+
+#define    CN23XX_INTR_CINT_ENB                 BIT_ULL(48)
+#define    CN23XX_INTR_MBOX_ENB                 BIT(0)
+
+/*############################ MIO #########################*/
+#define    CN23XX_MIO_PTP_CLOCK_CFG       0x0001070000000f00ULL
+#define    CN23XX_MIO_PTP_CLOCK_LO        0x0001070000000f08ULL
+#define    CN23XX_MIO_PTP_CLOCK_HI        0x0001070000000f10ULL
+#define    CN23XX_MIO_PTP_CLOCK_COMP      0x0001070000000f18ULL
+#define    CN23XX_MIO_PTP_TIMESTAMP       0x0001070000000f20ULL
+#define    CN23XX_MIO_PTP_EVT_CNT         0x0001070000000f28ULL
+#define    CN23XX_MIO_PTP_CKOUT_THRESH_LO 0x0001070000000f30ULL
+#define    CN23XX_MIO_PTP_CKOUT_THRESH_HI 0x0001070000000f38ULL
+#define    CN23XX_MIO_PTP_CKOUT_HI_INCR   0x0001070000000f40ULL
+#define    CN23XX_MIO_PTP_CKOUT_LO_INCR   0x0001070000000f48ULL
+#define    CN23XX_MIO_PTP_PPS_THRESH_LO   0x0001070000000f50ULL
+#define    CN23XX_MIO_PTP_PPS_THRESH_HI   0x0001070000000f58ULL
+#define    CN23XX_MIO_PTP_PPS_HI_INCR     0x0001070000000f60ULL
+#define    CN23XX_MIO_PTP_PPS_LO_INCR     0x0001070000000f68ULL
+
+/*############################ RST #########################*/
+#define    CN23XX_RST_BOOT                0x0001180006001600ULL
+
+/*######################## MSIX TABLE #########################*/
+
+#define    CN23XX_MSIX_TABLE_ADDR_START    0x0
+#define    CN23XX_MSIX_TABLE_DATA_START    0x8
+
+#define    CN23XX_MSIX_TABLE_SIZE          0x10
+#define    CN23XX_MSIX_TABLE_ENTRIES       0x41
+
+#define    CN23XX_MSIX_ENTRY_VECTOR_CTL    BIT_ULL(32)
+
+#define CN23XX_MSIX_TABLE_ADDR(idx)		\
+	(CN23XX_MSIX_TABLE_ADDR_START + ((idx) * CN23XX_MSIX_TABLE_SIZE))
+
+#define CN23XX_MSIX_TABLE_DATA(idx)		\
+	(CN23XX_MSIX_TABLE_DATA_START + ((idx) * CN23XX_MSIX_TABLE_SIZE))
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,24 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include "liquidio_common.h"
@@ -275,7 +271,6 @@ void lio_cn6xxx_setup_iq_regs(struct oct
 {
 	struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
 
-	/* Disable Packet-by-Packet mode; No Parse Mode or Skip length */
 	octeon_write_csr64(oct, CN6XXX_SLI_IQ_PKT_INSTR_HDR64(iq_no), 0);
 
 	/* Write the start of the input queue's ring and its size  */
@@ -378,7 +373,7 @@ void lio_cn6xxx_disable_io_queues(struct
 
 	/* Reset the doorbell register for each Input queue. */
 	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
-		if (!(oct->io_qmask.iq & (1ULL << i)))
+		if (!(oct->io_qmask.iq & BIT_ULL(i)))
 			continue;
 		octeon_write_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i), 0xFFFFFFFF);
 		d32 = octeon_read_csr(oct, CN6XXX_SLI_IQ_DOORBELL(i));
@@ -400,9 +395,8 @@ void lio_cn6xxx_disable_io_queues(struct
 	;
 
 	/* Reset the doorbell register for each Output queue. */
-	/* for (i = 0; i < oct->num_oqs; i++) { */
 	for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
-		if (!(oct->io_qmask.oq & (1ULL << i)))
+		if (!(oct->io_qmask.oq & BIT_ULL(i)))
 			continue;
 		octeon_write_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i), 0xFFFFFFFF);
 		d32 = octeon_read_csr(oct, CN6XXX_SLI_OQ_PKTS_CREDIT(i));
@@ -537,15 +531,14 @@ static int lio_cn6xxx_process_droq_intr_
 
 	oct->droq_intr = 0;
 
-	/* for (oq_no = 0; oq_no < oct->num_oqs; oq_no++) { */
 	for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES(oct); oq_no++) {
-		if (!(droq_mask & (1ULL << oq_no)))
+		if (!(droq_mask & BIT_ULL(oq_no)))
 			continue;
 
 		droq = oct->droq[oq_no];
 		pkt_count = octeon_droq_check_hw_for_pkts(droq);
 		if (pkt_count) {
-			oct->droq_intr |= (1ULL << oq_no);
+			oct->droq_intr |= BIT_ULL(oq_no);
 			if (droq->ops.poll_mode) {
 				u32 value;
 				u32 reg;
@@ -721,8 +714,6 @@ int lio_setup_cn66xx_octeon_device(struc
 int lio_validate_cn6xxx_config_info(struct octeon_device *oct,
 				    struct octeon_config *conf6xxx)
 {
-	/* int total_instrs = 0; */
-
 	if (CFG_GET_IQ_MAX_Q(conf6xxx) > CN6XXX_MAX_INPUT_QUEUES) {
 		dev_err(&oct->pci_dev->dev, "%s: Num IQ (%d) exceeds Max (%d)\n",
 			__func__, CFG_GET_IQ_MAX_Q(conf6xxx),
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file  cn66xx_device.h
  *  \brief Host Driver: Routines that perform CN66XX specific operations.
  */
@@ -96,8 +91,8 @@ void lio_cn6xxx_setup_reg_address(struct
 				  struct octeon_reg_list *reg_list);
 u32 lio_cn6xxx_coprocessor_clock(struct octeon_device *oct);
 u32 lio_cn6xxx_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us);
-int lio_setup_cn66xx_octeon_device(struct octeon_device *);
+int lio_setup_cn66xx_octeon_device(struct octeon_device *oct);
 int lio_validate_cn6xxx_config_info(struct octeon_device *oct,
-				    struct octeon_config *);
+				    struct octeon_config *conf6xxx);
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file cn66xx_regs.h
  *  \brief Host Driver: Register Address and Register Mask values for
  *  Octeon CN66XX devices.
@@ -443,10 +438,10 @@
 #define    CN6XXX_SLI_S2M_PORT0_CTL              0x3D80
 #define    CN6XXX_SLI_S2M_PORT1_CTL              0x3D90
 #define    CN6XXX_SLI_S2M_PORTX_CTL(port)        \
-	(CN6XXX_SLI_S2M_PORT0_CTL + (port * 0x10))
+	(CN6XXX_SLI_S2M_PORT0_CTL + ((port) * 0x10))
 
 #define    CN6XXX_SLI_INT_ENB64(port)            \
-	(CN6XXX_SLI_INT_ENB64_PORT0 + (port * 0x10))
+	(CN6XXX_SLI_INT_ENB64_PORT0 + ((port) * 0x10))
 
 #define    CN6XXX_SLI_MAC_NUMBER                 0x3E00
 
@@ -458,7 +453,7 @@
 #define    CN6XXX_PCI_BAR1_OFFSET                  0x8
 
 #define    CN6XXX_BAR1_REG(idx, port) \
-		(CN6XXX_BAR1_INDEX_START + (port * CN6XXX_PEM_OFFSET) + \
+		(CN6XXX_BAR1_INDEX_START + ((port) * CN6XXX_PEM_OFFSET) + \
 		(CN6XXX_PCI_BAR1_OFFSET * (idx)))
 
 /*############################ DPI #########################*/
@@ -476,17 +471,17 @@
 #define    CN6XXX_DPI_DMA_ENG0_ENB        0x0001df0000000080ULL
 
 #define    CN6XXX_DPI_DMA_ENG_ENB(q_no)   \
-	(CN6XXX_DPI_DMA_ENG0_ENB + (q_no * 8))
+	(CN6XXX_DPI_DMA_ENG0_ENB + ((q_no) * 8))
 
 #define    CN6XXX_DPI_DMA_ENG0_BUF        0x0001df0000000880ULL
 
 #define    CN6XXX_DPI_DMA_ENG_BUF(q_no)   \
-	(CN6XXX_DPI_DMA_ENG0_BUF + (q_no * 8))
+	(CN6XXX_DPI_DMA_ENG0_BUF + ((q_no) * 8))
 
 #define    CN6XXX_DPI_SLI_PRT0_CFG        0x0001df0000000900ULL
 #define    CN6XXX_DPI_SLI_PRT1_CFG        0x0001df0000000908ULL
 #define    CN6XXX_DPI_SLI_PRTX_CFG(port)        \
-	(CN6XXX_DPI_SLI_PRT0_CFG + (port * 0x10))
+	(CN6XXX_DPI_SLI_PRT0_CFG + ((port) * 0x10))
 
 #define    CN6XXX_DPI_DMA_COMMIT_MODE     BIT_ULL(58)
 #define    CN6XXX_DPI_DMA_PKT_HP          BIT_ULL(57)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,24 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include "liquidio_common.h"
@@ -76,7 +72,7 @@ static void lio_cn68xx_setup_pkt_ctl_reg
 	pktctl = octeon_read_csr64(oct, CN6XXX_SLI_PKT_CTL);
 
 	/* 68XX specific */
-	max_oqs = CFG_GET_OQ_MAX_Q(CHIP_FIELD(oct, cn6xxx, conf));
+	max_oqs = CFG_GET_OQ_MAX_Q(CHIP_CONF(oct, cn6xxx));
 	tx_pipe  = octeon_read_csr64(oct, CN68XX_SLI_TX_PIPE);
 	tx_pipe &= 0xffffffffff00ffffULL; /* clear out NUMP field */
 	tx_pipe |= max_oqs << 16; /* put max_oqs in NUMP field */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_device.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file  cn68xx_device.h
  *  \brief Host Driver: Routines that perform CN68XX specific operations.
  */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/cn68xx_regs.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file cn68xx_regs.h
  *  \brief Host Driver: Register Address and Register Mask values for
  *  Octeon CN68XX devices. The register map for CN66XX is the same
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_core.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_core.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,24 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/pci.h>
 #include <linux/if_vlan.h>
 #include "liquidio_common.h"
@@ -89,13 +85,6 @@ void octeon_update_tx_completion_counter
 	}
 
 	(*pkts_compl)++;
-/*TODO, Use some other pound define to suggest
- * the fact that iqs are not tied to netdevs
- * and can take traffic from different netdevs
- * hence bql reporting is done per packet
- * than in bulk. Usage of NO_NAPI in txq completion is
- * a little confusing
- */
 	*bytes_compl += skb->len;
 }
 
@@ -264,3 +253,34 @@ void liquidio_link_ctrl_cmd_completion(v
 			nctrl->ncmd.s.cmd);
 	}
 }
+
+void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac)
+{
+	bool macaddr_changed = false;
+	struct net_device *netdev;
+	struct lio *lio;
+
+	rtnl_lock();
+
+	netdev = oct->props[0].netdev;
+	lio = GET_LIO(netdev);
+
+	lio->linfo.macaddr_is_admin_asgnd = true;
+
+	if (!ether_addr_equal(netdev->dev_addr, mac)) {
+		macaddr_changed = true;
+		ether_addr_copy(netdev->dev_addr, mac);
+		ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, mac);
+		call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev);
+	}
+
+	rtnl_unlock();
+
+	if (macaddr_changed)
+		dev_info(&oct->pci_dev->dev,
+			 "PF changed VF's MAC address to %pM\n", mac);
+
+	/* no need to notify the firmware of the macaddr change because
+	 * the PF did that already
+	 */
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,24 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/netdevice.h>
 #include <linux/net_tstamp.h>
 #include <linux/pci.h>
@@ -33,6 +29,7 @@
 #include "cn66xx_regs.h"
 #include "cn66xx_device.h"
 #include "cn23xx_pf_device.h"
+#include "cn23xx_vf_device.h"
 
 static int octnet_get_link_stats(struct net_device *netdev);
 
@@ -74,9 +71,9 @@ enum {
 	INTERFACE_MODE_MIXED,
 };
 
-#define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0]))
 #define OCT_ETHTOOL_REGDUMP_LEN  4096
 #define OCT_ETHTOOL_REGDUMP_LEN_23XX  (4096 * 11)
+#define OCT_ETHTOOL_REGDUMP_LEN_23XX_VF  (4096 * 2)
 #define OCT_ETHTOOL_REGSVER  1
 
 /* statistics of PF */
@@ -87,9 +84,9 @@ static const char oct_stats_strings[][ET
 	"tx_bytes",
 	"rx_errors",	/*jabber_err+l2_err+frame_err */
 	"tx_errors",	/*fw_err_pko+fw_err_link+fw_err_drop */
-	"rx_dropped",   /*st->fromwire.total_rcvd - st->fromwire.fw_total_rcvd
-			*+st->fromwire.dmac_drop + st->fromwire.fw_err_drop
-			*/
+	"rx_dropped",   /*st->fromwire.total_rcvd - st->fromwire.fw_total_rcvd +
+			 *st->fromwire.dmac_drop + st->fromwire.fw_err_drop
+			 */
 	"tx_dropped",
 
 	"tx_total_sent",
@@ -152,6 +149,19 @@ static const char oct_stats_strings[][ET
 	"link_state_changes",
 };
 
+/* statistics of VF */
+static const char oct_vf_stats_strings[][ETH_GSTRING_LEN] = {
+	"rx_packets",
+	"tx_packets",
+	"rx_bytes",
+	"tx_bytes",
+	"rx_errors", /* jabber_err + l2_err+frame_err */
+	"tx_errors", /* fw_err_pko + fw_err_link+fw_err_drop */
+	"rx_dropped", /* total_rcvd - fw_total_rcvd + dmac_drop + fw_err_drop */
+	"tx_dropped",
+	"link_state_changes",
+};
+
 /* statistics of host tx queue */
 static const char oct_iq_stats_strings[][ETH_GSTRING_LEN] = {
 	"packets",		/*oct->instr_queue[iq_no]->stats.tx_done*/
@@ -197,25 +207,28 @@ static const char oct_priv_flags_strings
 #define OCTNIC_NCMD_AUTONEG_ON  0x1
 #define OCTNIC_NCMD_PHY_ON      0x2
 
-static int lio_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+static int lio_get_link_ksettings(struct net_device *netdev,
+				  struct ethtool_link_ksettings *ecmd)
 {
 	struct lio *lio = GET_LIO(netdev);
 	struct octeon_device *oct = lio->oct_dev;
 	struct oct_link_info *linfo;
+	u32 supported, advertising;
 
 	linfo = &lio->linfo;
 
 	if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI ||
 	    linfo->link.s.if_mode == INTERFACE_MODE_RXAUI ||
 	    linfo->link.s.if_mode == INTERFACE_MODE_XFI) {
-		ecmd->port = PORT_FIBRE;
-		ecmd->supported =
-			(SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE |
-			 SUPPORTED_Pause);
-		ecmd->advertising =
-			(ADVERTISED_10000baseT_Full | ADVERTISED_Pause);
-		ecmd->transceiver = XCVR_EXTERNAL;
-		ecmd->autoneg = AUTONEG_DISABLE;
+		ecmd->base.port = PORT_FIBRE;
+		supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE |
+			     SUPPORTED_Pause);
+		advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Pause);
+		ethtool_convert_legacy_u32_to_link_mode(
+			ecmd->link_modes.supported, supported);
+		ethtool_convert_legacy_u32_to_link_mode(
+			ecmd->link_modes.advertising, advertising);
+		ecmd->base.autoneg = AUTONEG_DISABLE;
 
 	} else {
 		dev_err(&oct->pci_dev->dev, "Unknown link interface reported %d\n",
@@ -223,11 +236,11 @@ static int lio_get_settings(struct net_d
 	}
 
 	if (linfo->link.s.link_up) {
-		ethtool_cmd_speed_set(ecmd, linfo->link.s.speed);
-		ecmd->duplex = linfo->link.s.duplex;
+		ecmd->base.speed = linfo->link.s.speed;
+		ecmd->base.duplex = linfo->link.s.duplex;
 	} else {
-		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
-		ecmd->duplex = DUPLEX_UNKNOWN;
+		ecmd->base.speed = SPEED_UNKNOWN;
+		ecmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 
 	return 0;
@@ -251,6 +264,23 @@ lio_get_drvinfo(struct net_device *netde
 }
 
 static void
+lio_get_vf_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+{
+	struct octeon_device *oct;
+	struct lio *lio;
+
+	lio = GET_LIO(netdev);
+	oct = lio->oct_dev;
+
+	memset(drvinfo, 0, sizeof(struct ethtool_drvinfo));
+	strcpy(drvinfo->driver, "liquidio_vf");
+	strcpy(drvinfo->version, LIQUIDIO_VERSION);
+	strncpy(drvinfo->fw_version, oct->fw_info.liquidio_firmware_version,
+		ETHTOOL_FWVERS_LEN);
+	strncpy(drvinfo->bus_info, pci_name(oct->pci_dev), 32);
+}
+
+static void
 lio_ethtool_get_channels(struct net_device *dev,
 			 struct ethtool_channels *channel)
 {
@@ -259,14 +289,14 @@ lio_ethtool_get_channels(struct net_devi
 	u32 max_rx = 0, max_tx = 0, tx_count = 0, rx_count = 0;
 
 	if (OCTEON_CN6XXX(oct)) {
-		struct octeon_config *conf6x = CHIP_FIELD(oct, cn6xxx, conf);
+		struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
 
 		max_rx = CFG_GET_OQ_MAX_Q(conf6x);
 		max_tx = CFG_GET_IQ_MAX_Q(conf6x);
 		rx_count = CFG_GET_NUM_RXQS_NIC_IF(conf6x, lio->ifidx);
 		tx_count = CFG_GET_NUM_TXQS_NIC_IF(conf6x, lio->ifidx);
 	} else if (OCTEON_CN23XX_PF(oct)) {
-		struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
+		struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_pf);
 
 		max_rx = CFG_GET_OQ_MAX_Q(conf23);
 		max_tx = CFG_GET_IQ_MAX_Q(conf23);
@@ -589,14 +619,14 @@ lio_ethtool_get_ringparam(struct net_dev
 	    rx_pending = 0;
 
 	if (OCTEON_CN6XXX(oct)) {
-		struct octeon_config *conf6x = CHIP_FIELD(oct, cn6xxx, conf);
+		struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
 
 		tx_max_pending = CN6XXX_MAX_IQ_DESCRIPTORS;
 		rx_max_pending = CN6XXX_MAX_OQ_DESCRIPTORS;
 		rx_pending = CFG_GET_NUM_RX_DESCS_NIC_IF(conf6x, lio->ifidx);
 		tx_pending = CFG_GET_NUM_TX_DESCS_NIC_IF(conf6x, lio->ifidx);
 	} else if (OCTEON_CN23XX_PF(oct)) {
-		struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
+		struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_pf);
 
 		tx_max_pending = CN23XX_MAX_IQ_DESCRIPTORS;
 		rx_max_pending = CN23XX_MAX_OQ_DESCRIPTORS;
@@ -757,9 +787,6 @@ lio_get_ethtool_stats(struct net_device
 	/*sum of oct->instr_queue[iq_no]->stats.tx_dropped */
 	data[i++] = CVM_CAST64(netstats->tx_dropped);
 
-	/*data[i++] = CVM_CAST64(stats->multicast); */
-	/*data[i++] = CVM_CAST64(stats->collisions); */
-
 	/* firmware tx stats */
 	/*per_core_stats[cvmx_get_core_num()].link_stats[mdata->from_ifidx].
 	 *fromhost.fw_total_sent
@@ -910,9 +937,8 @@ lio_get_ethtool_stats(struct net_device
 	/*lio->link_changes*/
 	data[i++] = CVM_CAST64(lio->link_changes);
 
-	/* TX  -- lio_update_stats(lio); */
 	for (j = 0; j < MAX_OCTEON_INSTR_QUEUES(oct_dev); j++) {
-		if (!(oct_dev->io_qmask.iq & (1ULL << j)))
+		if (!(oct_dev->io_qmask.iq & BIT_ULL(j)))
 			continue;
 		/*packets to network port*/
 		/*# of packets tx to network */
@@ -954,9 +980,8 @@ lio_get_ethtool_stats(struct net_device
 	}
 
 	/* RX */
-	/* for (j = 0; j < oct_dev->num_oqs; j++) { */
 	for (j = 0; j < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); j++) {
-		if (!(oct_dev->io_qmask.oq & (1ULL << j)))
+		if (!(oct_dev->io_qmask.oq & BIT_ULL(j)))
 			continue;
 
 		/*packets send to TCP/IP network stack */
@@ -992,6 +1017,109 @@ lio_get_ethtool_stats(struct net_device
 	}
 }
 
+static void lio_vf_get_ethtool_stats(struct net_device *netdev,
+				     struct ethtool_stats *stats
+				     __attribute__((unused)),
+				     u64 *data)
+{
+	struct net_device_stats *netstats = &netdev->stats;
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct_dev = lio->oct_dev;
+	int i = 0, j, vj;
+
+	netdev->netdev_ops->ndo_get_stats(netdev);
+	/* sum of oct->droq[oq_no]->stats->rx_pkts_received */
+	data[i++] = CVM_CAST64(netstats->rx_packets);
+	/* sum of oct->instr_queue[iq_no]->stats.tx_done */
+	data[i++] = CVM_CAST64(netstats->tx_packets);
+	/* sum of oct->droq[oq_no]->stats->rx_bytes_received */
+	data[i++] = CVM_CAST64(netstats->rx_bytes);
+	/* sum of oct->instr_queue[iq_no]->stats.tx_tot_bytes */
+	data[i++] = CVM_CAST64(netstats->tx_bytes);
+	data[i++] = CVM_CAST64(netstats->rx_errors);
+	data[i++] = CVM_CAST64(netstats->tx_errors);
+	 /* sum of oct->droq[oq_no]->stats->rx_dropped +
+	  * oct->droq[oq_no]->stats->dropped_nodispatch +
+	  * oct->droq[oq_no]->stats->dropped_toomany +
+	  * oct->droq[oq_no]->stats->dropped_nomem
+	  */
+	data[i++] = CVM_CAST64(netstats->rx_dropped);
+	/* sum of oct->instr_queue[iq_no]->stats.tx_dropped */
+	data[i++] = CVM_CAST64(netstats->tx_dropped);
+	/* lio->link_changes */
+	data[i++] = CVM_CAST64(lio->link_changes);
+
+	for (vj = 0; vj < lio->linfo.num_txpciq; vj++) {
+		j = lio->linfo.txpciq[vj].s.q_no;
+
+		/* packets to network port */
+		/* # of packets tx to network */
+		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_done);
+		 /* # of bytes tx to network */
+		data[i++] = CVM_CAST64(
+				oct_dev->instr_queue[j]->stats.tx_tot_bytes);
+		/* # of packets dropped */
+		data[i++] = CVM_CAST64(
+				oct_dev->instr_queue[j]->stats.tx_dropped);
+		/* # of tx fails due to queue full */
+		data[i++] = CVM_CAST64(
+				oct_dev->instr_queue[j]->stats.tx_iq_busy);
+		/* XXX gather entries sent */
+		data[i++] = CVM_CAST64(
+				oct_dev->instr_queue[j]->stats.sgentry_sent);
+
+		/* instruction to firmware: data and control */
+		/* # of instructions to the queue */
+		data[i++] = CVM_CAST64(
+				oct_dev->instr_queue[j]->stats.instr_posted);
+		/* # of instructions processed */
+		data[i++] =
+		    CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_processed);
+		/* # of instructions could not be processed */
+		data[i++] =
+		    CVM_CAST64(oct_dev->instr_queue[j]->stats.instr_dropped);
+		/* bytes sent through the queue */
+		data[i++] = CVM_CAST64(
+				oct_dev->instr_queue[j]->stats.bytes_sent);
+		/* tso request */
+		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_gso);
+		/* vxlan request */
+		data[i++] = CVM_CAST64(oct_dev->instr_queue[j]->stats.tx_vxlan);
+		/* txq restart */
+		data[i++] = CVM_CAST64(
+				oct_dev->instr_queue[j]->stats.tx_restart);
+	}
+
+	/* RX */
+	for (vj = 0; vj < lio->linfo.num_rxpciq; vj++) {
+		j = lio->linfo.rxpciq[vj].s.q_no;
+
+		/* packets send to TCP/IP network stack */
+		/* # of packets to network stack */
+		data[i++] = CVM_CAST64(
+				oct_dev->droq[j]->stats.rx_pkts_received);
+		/* # of bytes to network stack */
+		data[i++] = CVM_CAST64(
+				oct_dev->droq[j]->stats.rx_bytes_received);
+		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem +
+				       oct_dev->droq[j]->stats.dropped_toomany +
+				       oct_dev->droq[j]->stats.rx_dropped);
+		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_nomem);
+		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.dropped_toomany);
+		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.rx_dropped);
+
+		/* control and data path */
+		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.pkts_received);
+		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.bytes_received);
+		data[i++] =
+			CVM_CAST64(oct_dev->droq[j]->stats.dropped_nodispatch);
+
+		data[i++] = CVM_CAST64(oct_dev->droq[j]->stats.rx_vxlan);
+		data[i++] =
+		    CVM_CAST64(oct_dev->droq[j]->stats.rx_alloc_failure);
+	}
+}
+
 static void lio_get_priv_flags_strings(struct lio *lio, u8 *data)
 {
 	struct octeon_device *oct_dev = lio->oct_dev;
@@ -999,6 +1127,7 @@ static void lio_get_priv_flags_strings(s
 
 	switch (oct_dev->chip_id) {
 	case OCTEON_CN23XX_PF_VID:
+	case OCTEON_CN23XX_VF_VID:
 		for (i = 0; i < ARRAY_SIZE(oct_priv_flags_strings); i++) {
 			sprintf(data, "%s", oct_priv_flags_strings[i]);
 			data += ETH_GSTRING_LEN;
@@ -1030,7 +1159,7 @@ static void lio_get_strings(struct net_d
 
 		num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
 		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct_dev); i++) {
-			if (!(oct_dev->io_qmask.iq & (1ULL << i)))
+			if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
 				continue;
 			for (j = 0; j < num_iq_stats; j++) {
 				sprintf(data, "tx-%d-%s", i,
@@ -1040,9 +1169,56 @@ static void lio_get_strings(struct net_d
 		}
 
 		num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
-		/* for (i = 0; i < oct_dev->num_oqs; i++) { */
 		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); i++) {
-			if (!(oct_dev->io_qmask.oq & (1ULL << i)))
+			if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
+				continue;
+			for (j = 0; j < num_oq_stats; j++) {
+				sprintf(data, "rx-%d-%s", i,
+					oct_droq_stats_strings[j]);
+				data += ETH_GSTRING_LEN;
+			}
+		}
+		break;
+
+	case ETH_SS_PRIV_FLAGS:
+		lio_get_priv_flags_strings(lio, data);
+		break;
+	default:
+		netif_info(lio, drv, lio->netdev, "Unknown Stringset !!\n");
+		break;
+	}
+}
+
+static void lio_vf_get_strings(struct net_device *netdev, u32 stringset,
+			       u8 *data)
+{
+	int num_iq_stats, num_oq_stats, i, j;
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct_dev = lio->oct_dev;
+	int num_stats;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		num_stats = ARRAY_SIZE(oct_vf_stats_strings);
+		for (j = 0; j < num_stats; j++) {
+			sprintf(data, "%s", oct_vf_stats_strings[j]);
+			data += ETH_GSTRING_LEN;
+		}
+
+		num_iq_stats = ARRAY_SIZE(oct_iq_stats_strings);
+		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct_dev); i++) {
+			if (!(oct_dev->io_qmask.iq & BIT_ULL(i)))
+				continue;
+			for (j = 0; j < num_iq_stats; j++) {
+				sprintf(data, "tx-%d-%s", i,
+					oct_iq_stats_strings[j]);
+				data += ETH_GSTRING_LEN;
+			}
+		}
+
+		num_oq_stats = ARRAY_SIZE(oct_droq_stats_strings);
+		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct_dev); i++) {
+			if (!(oct_dev->io_qmask.oq & BIT_ULL(i)))
 				continue;
 			for (j = 0; j < num_oq_stats; j++) {
 				sprintf(data, "rx-%d-%s", i,
@@ -1067,6 +1243,7 @@ static int lio_get_priv_flags_ss_count(s
 
 	switch (oct_dev->chip_id) {
 	case OCTEON_CN23XX_PF_VID:
+	case OCTEON_CN23XX_VF_VID:
 		return ARRAY_SIZE(oct_priv_flags_strings);
 	case OCTEON_CN68XX:
 	case OCTEON_CN66XX:
@@ -1094,6 +1271,23 @@ static int lio_get_sset_count(struct net
 	}
 }
 
+static int lio_vf_get_sset_count(struct net_device *netdev, int sset)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct_dev = lio->oct_dev;
+
+	switch (sset) {
+	case ETH_SS_STATS:
+		return (ARRAY_SIZE(oct_vf_stats_strings) +
+			ARRAY_SIZE(oct_iq_stats_strings) * oct_dev->num_iqs +
+			ARRAY_SIZE(oct_droq_stats_strings) * oct_dev->num_oqs);
+	case ETH_SS_PRIV_FLAGS:
+		return lio_get_priv_flags_ss_count(lio);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static int lio_get_intr_coalesce(struct net_device *netdev,
 				 struct ethtool_coalesce *intr_coal)
 {
@@ -1106,6 +1300,7 @@ static int lio_get_intr_coalesce(struct
 
 	switch (oct->chip_id) {
 	case OCTEON_CN23XX_PF_VID:
+	case OCTEON_CN23XX_VF_VID:
 		if (!intrmod_cfg->rx_enable) {
 			intr_coal->rx_coalesce_usecs = intrmod_cfg->rx_usecs;
 			intr_coal->rx_max_coalesced_frames =
@@ -1152,7 +1347,7 @@ static int lio_get_intr_coalesce(struct
 		intr_coal->rx_max_coalesced_frames_low =
 		    intrmod_cfg->rx_mincnt_trigger;
 	}
-	if (OCTEON_CN23XX_PF(oct) &&
+	if ((OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) &&
 	    (intrmod_cfg->tx_enable)) {
 		intr_coal->use_adaptive_tx_coalesce = intrmod_cfg->tx_enable;
 		intr_coal->tx_max_coalesced_frames_high =
@@ -1510,6 +1705,26 @@ oct_cfg_rx_intrcnt(struct lio *lio, stru
 		oct->intrmod.rx_frames = rx_max_coalesced_frames;
 		break;
 	}
+	case OCTEON_CN23XX_VF_VID: {
+		int q_no;
+
+		if (!intr_coal->rx_max_coalesced_frames)
+			rx_max_coalesced_frames = oct->intrmod.rx_frames;
+		else
+			rx_max_coalesced_frames =
+			    intr_coal->rx_max_coalesced_frames;
+		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+			octeon_write_csr64(
+			    oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+			    (octeon_read_csr64(
+				 oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no)) &
+			     (0x3fffff00000000UL)) |
+				rx_max_coalesced_frames);
+			/* consider writing to resend bit here */
+		}
+		oct->intrmod.rx_frames = rx_max_coalesced_frames;
+		break;
+	}
 	default:
 		return -EINVAL;
 	}
@@ -1563,6 +1778,27 @@ static int oct_cfg_rx_intrtime(struct li
 		oct->intrmod.rx_usecs = rx_coalesce_usecs;
 		break;
 	}
+	case OCTEON_CN23XX_VF_VID: {
+		u64 time_threshold;
+		int q_no;
+
+		if (!intr_coal->rx_coalesce_usecs)
+			rx_coalesce_usecs = oct->intrmod.rx_usecs;
+		else
+			rx_coalesce_usecs = intr_coal->rx_coalesce_usecs;
+
+		time_threshold =
+		    cn23xx_vf_get_oq_ticks(oct, (u32)rx_coalesce_usecs);
+		for (q_no = 0; q_no < oct->num_oqs; q_no++) {
+			octeon_write_csr64(
+				oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no),
+				(oct->intrmod.rx_frames |
+				 (time_threshold << 32)));
+			/* consider setting resend bit */
+		}
+		oct->intrmod.rx_usecs = rx_coalesce_usecs;
+		break;
+	}
 	default:
 		return -EINVAL;
 	}
@@ -1584,6 +1820,7 @@ oct_cfg_tx_intrcnt(struct lio *lio, stru
 	case OCTEON_CN68XX:
 	case OCTEON_CN66XX:
 		break;
+	case OCTEON_CN23XX_VF_VID:
 	case OCTEON_CN23XX_PF_VID: {
 		int q_no;
 
@@ -1642,6 +1879,7 @@ static int lio_set_intr_coalesce(struct
 		}
 		break;
 	case OCTEON_CN23XX_PF_VID:
+	case OCTEON_CN23XX_VF_VID:
 		break;
 	default:
 		return -EINVAL;
@@ -1704,86 +1942,6 @@ static int lio_get_ts_info(struct net_de
 	return 0;
 }
 
-static int lio_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
-{
-	struct lio *lio = GET_LIO(netdev);
-	struct octeon_device *oct = lio->oct_dev;
-	struct oct_link_info *linfo;
-	struct octnic_ctrl_pkt nctrl;
-	int ret = 0;
-
-	/* get the link info */
-	linfo = &lio->linfo;
-
-	if (ecmd->autoneg != AUTONEG_ENABLE && ecmd->autoneg != AUTONEG_DISABLE)
-		return -EINVAL;
-
-	if (ecmd->autoneg == AUTONEG_DISABLE && ((ecmd->speed != SPEED_100 &&
-						  ecmd->speed != SPEED_10) ||
-						 (ecmd->duplex != DUPLEX_HALF &&
-						  ecmd->duplex != DUPLEX_FULL)))
-		return -EINVAL;
-
-	/* Ethtool Support is not provided for XAUI, RXAUI, and XFI Interfaces
-	 * as they operate at fixed Speed and Duplex settings
-	 */
-	if (linfo->link.s.if_mode == INTERFACE_MODE_XAUI ||
-	    linfo->link.s.if_mode == INTERFACE_MODE_RXAUI ||
-	    linfo->link.s.if_mode == INTERFACE_MODE_XFI) {
-		dev_info(&oct->pci_dev->dev,
-			 "Autonegotiation, duplex and speed settings cannot be modified.\n");
-		return -EINVAL;
-	}
-
-	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
-
-	nctrl.ncmd.u64 = 0;
-	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_SETTINGS;
-	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
-	nctrl.wait_time = 1000;
-	nctrl.netpndev = (u64)netdev;
-	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
-
-	/* Passing the parameters sent by ethtool like Speed, Autoneg & Duplex
-	 * to SE core application using ncmd.s.more & ncmd.s.param
-	 */
-	if (ecmd->autoneg == AUTONEG_ENABLE) {
-		/* Autoneg ON */
-		nctrl.ncmd.s.more = OCTNIC_NCMD_PHY_ON |
-				     OCTNIC_NCMD_AUTONEG_ON;
-		nctrl.ncmd.s.param1 = ecmd->advertising;
-	} else {
-		/* Autoneg OFF */
-		nctrl.ncmd.s.more = OCTNIC_NCMD_PHY_ON;
-
-		nctrl.ncmd.s.param2 = ecmd->duplex;
-
-		nctrl.ncmd.s.param1 = ecmd->speed;
-	}
-
-	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
-	if (ret < 0) {
-		dev_err(&oct->pci_dev->dev, "Failed to set settings\n");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int lio_nway_reset(struct net_device *netdev)
-{
-	if (netif_running(netdev)) {
-		struct ethtool_cmd ecmd;
-
-		memset(&ecmd, 0, sizeof(struct ethtool_cmd));
-		ecmd.autoneg = 0;
-		ecmd.speed = 0;
-		ecmd.duplex = 0;
-		lio_set_settings(netdev, &ecmd);
-	}
-	return 0;
-}
-
 /* Return register dump len. */
 static int lio_get_regs_len(struct net_device *dev)
 {
@@ -1793,6 +1951,8 @@ static int lio_get_regs_len(struct net_d
 	switch (oct->chip_id) {
 	case OCTEON_CN23XX_PF_VID:
 		return OCT_ETHTOOL_REGDUMP_LEN_23XX;
+	case OCTEON_CN23XX_VF_VID:
+		return OCT_ETHTOOL_REGDUMP_LEN_23XX_VF;
 	default:
 		return OCT_ETHTOOL_REGDUMP_LEN;
 	}
@@ -2018,6 +2178,123 @@ static int cn23xx_read_csr_reg(char *s,
 	return len;
 }
 
+static int cn23xx_vf_read_csr_reg(char *s, struct octeon_device *oct)
+{
+	int len = 0;
+	u32 reg;
+	int i;
+
+	/* PCI  Window Registers */
+
+	len += sprintf(s + len, "\n\t Octeon CSR Registers\n\n");
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_OQ_BUFF_INFO_SIZE(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_OUT_SIZE): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_IQ_INSTR_COUNT64(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_OQ_PKTS_CREDIT(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_SLIST_BAOFF_DBELL): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_OQ_SIZE(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_SLIST_FIFO_RSIZE): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_OQ_PKT_CONTROL(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d__OUTPUT_CONTROL): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_OQ_BASE_ADDR64(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_SLIST_BADDR): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_INT_LEVELS): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_OQ_PKTS_SENT(i);
+		len += sprintf(s + len, "\n[%08x] (SLI_PKT%d_CNTS): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = 0x100c0 + i * CN23XX_VF_OQ_OFFSET;
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_ERROR_INFO): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = 0x100d0 + i * CN23XX_VF_IQ_OFFSET;
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_VF_INT_SUM): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_IQ_PKT_CONTROL64(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_INPUT_CONTROL): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_IQ_BASE_ADDR64(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_INSTR_BADDR): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_IQ_DOORBELL(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_INSTR_BAOFF_DBELL): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_IQ_SIZE(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT%d_INSTR_FIFO_RSIZE): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	for (i = 0; i < (oct->sriov_info.rings_per_vf); i++) {
+		reg = CN23XX_VF_SLI_IQ_INSTR_COUNT64(i);
+		len += sprintf(s + len,
+			       "\n[%08x] (SLI_PKT_IN_DONE%d_CNTS): %016llx\n",
+			       reg, i, (u64)octeon_read_csr64(oct, reg));
+	}
+
+	return len;
+}
+
 static int cn6xxx_read_csr_reg(char *s, struct octeon_device *oct)
 {
 	u32 reg;
@@ -2164,6 +2441,10 @@ static void lio_get_regs(struct net_devi
 		memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN_23XX);
 		len += cn23xx_read_csr_reg(regbuf + len, oct);
 		break;
+	case OCTEON_CN23XX_VF_VID:
+		memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN_23XX_VF);
+		len += cn23xx_vf_read_csr_reg(regbuf + len, oct);
+		break;
 	case OCTEON_CN68XX:
 	case OCTEON_CN66XX:
 		memset(regbuf, 0, OCT_ETHTOOL_REGDUMP_LEN);
@@ -2194,7 +2475,7 @@ static int lio_set_priv_flags(struct net
 }
 
 static const struct ethtool_ops lio_ethtool_ops = {
-	.get_settings		= lio_get_settings,
+	.get_link_ksettings	= lio_get_link_ksettings,
 	.get_link		= ethtool_op_get_link,
 	.get_drvinfo		= lio_get_drvinfo,
 	.get_ringparam		= lio_ethtool_get_ringparam,
@@ -2211,8 +2492,26 @@ static const struct ethtool_ops lio_etht
 	.get_msglevel		= lio_get_msglevel,
 	.set_msglevel		= lio_set_msglevel,
 	.get_sset_count		= lio_get_sset_count,
-	.nway_reset		= lio_nway_reset,
-	.set_settings		= lio_set_settings,
+	.get_coalesce		= lio_get_intr_coalesce,
+	.set_coalesce		= lio_set_intr_coalesce,
+	.get_priv_flags		= lio_get_priv_flags,
+	.set_priv_flags		= lio_set_priv_flags,
+	.get_ts_info		= lio_get_ts_info,
+};
+
+static const struct ethtool_ops lio_vf_ethtool_ops = {
+	.get_link_ksettings	= lio_get_link_ksettings,
+	.get_link		= ethtool_op_get_link,
+	.get_drvinfo		= lio_get_vf_drvinfo,
+	.get_ringparam		= lio_ethtool_get_ringparam,
+	.get_channels		= lio_ethtool_get_channels,
+	.get_strings		= lio_vf_get_strings,
+	.get_ethtool_stats	= lio_vf_get_ethtool_stats,
+	.get_regs_len		= lio_get_regs_len,
+	.get_regs		= lio_get_regs,
+	.get_msglevel		= lio_get_msglevel,
+	.set_msglevel		= lio_set_msglevel,
+	.get_sset_count		= lio_vf_get_sset_count,
 	.get_coalesce		= lio_get_intr_coalesce,
 	.set_coalesce		= lio_set_intr_coalesce,
 	.get_priv_flags		= lio_get_priv_flags,
@@ -2222,5 +2521,11 @@ static const struct ethtool_ops lio_etht
 
 void liquidio_set_ethtool_ops(struct net_device *netdev)
 {
-	netdev->ethtool_ops = &lio_ethtool_ops;
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+
+	if (OCTEON_CN23XX_VF(oct))
+		netdev->ethtool_ops = &lio_vf_ethtool_ops;
+	else
+		netdev->ethtool_ops = &lio_ethtool_ops;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_main.c	2016-12-11 17:49:49.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_main.c	2017-02-12 17:38:40.000000000 -0500
@@ -1,28 +1,22 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-#include <linux/version.h>
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/pci.h>
 #include <linux/firmware.h>
-#include <linux/ptp_clock_kernel.h>
 #include <net/vxlan.h>
 #include <linux/kthread.h>
 #include "liquidio_common.h"
@@ -52,9 +46,6 @@ MODULE_PARM_DESC(ddr_timeout,
 
 #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
 
-#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count)  \
-	(octeon_dev_ptr->instr_queue[iq_no]->stats.field += count)
-
 static int debug = -1;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
@@ -63,10 +54,6 @@ static char fw_type[LIO_MAX_FW_TYPE_LEN]
 module_param_string(fw_type, fw_type, sizeof(fw_type), 0000);
 MODULE_PARM_DESC(fw_type, "Type of firmware to be loaded. Default \"nic\"");
 
-static int conf_type;
-module_param(conf_type, int, 0);
-MODULE_PARM_DESC(conf_type, "select octeon configuration 0 default 1 ovs");
-
 static int ptp_enable = 1;
 
 /* Bit mask values for lio->ifstate */
@@ -178,6 +165,10 @@ struct octeon_device_priv {
 	unsigned long napi_mask;
 };
 
+#ifdef CONFIG_PCI_IOV
+static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs);
+#endif
+
 static int octeon_device_init(struct octeon_device *);
 static int liquidio_stop(struct net_device *netdev);
 static void liquidio_remove(struct pci_dev *pdev);
@@ -195,9 +186,8 @@ static void octeon_droq_bh(unsigned long
 	struct octeon_device_priv *oct_priv =
 		(struct octeon_device_priv *)oct->priv;
 
-	/* for (q_no = 0; q_no < oct->num_oqs; q_no++) { */
 	for (q_no = 0; q_no < MAX_OCTEON_OUTPUT_QUEUES(oct); q_no++) {
-		if (!(oct->io_qmask.oq & (1ULL << q_no)))
+		if (!(oct->io_qmask.oq & BIT_ULL(q_no)))
 			continue;
 		reschedule |= octeon_droq_process_packets(oct, oct->droq[q_no],
 							  MAX_PACKET_BUDGET);
@@ -232,7 +222,7 @@ static int lio_wait_for_oq_pkts(struct o
 		pending_pkts = 0;
 
 		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
-			if (!(oct->io_qmask.oq & (1ULL << i)))
+			if (!(oct->io_qmask.oq & BIT_ULL(i)))
 				continue;
 			pkt_cnt += octeon_droq_check_hw_for_pkts(oct->droq[i]);
 		}
@@ -314,7 +304,7 @@ static inline void pcierror_quiesce_devi
 	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
 		struct octeon_instr_queue *iq;
 
-		if (!(oct->io_qmask.iq & (1ULL << i)))
+		if (!(oct->io_qmask.iq & BIT_ULL(i)))
 			continue;
 		iq = oct->instr_queue[i];
 
@@ -380,7 +370,6 @@ static void stop_pci_io(struct octeon_de
 	dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
 		lio_get_state_string(&oct->status));
 
-	/* cn63xx_cleanup_aer_uncorrect_error_status(oct->pci_dev); */
 	/* making it a common function for all OCTEON models */
 	cleanup_aer_uncorrect_error_status(oct->pci_dev);
 }
@@ -516,6 +505,9 @@ static struct pci_driver liquidio_pci_dr
 	.suspend	= liquidio_suspend,
 	.resume		= liquidio_resume,
 #endif
+#ifdef CONFIG_PCI_IOV
+	.sriov_configure = liquidio_enable_sriov,
+#endif
 };
 
 /**
@@ -761,6 +753,7 @@ static void delete_glists(struct lio *li
 	}
 
 	kfree((void *)lio->glist);
+	kfree((void *)lio->glist_lock);
 }
 
 /**
@@ -931,7 +924,6 @@ static inline void update_link_status(st
 
 		if (lio->linfo.link.s.link_up) {
 			netif_carrier_on(netdev);
-			/* start_txq(netdev); */
 			txqs_wake(netdev);
 		} else {
 			netif_carrier_off(netdev);
@@ -1009,7 +1001,7 @@ static void liquidio_schedule_droq_pkt_h
 	if (oct->int_status & OCT_DEV_INTR_PKT_DATA) {
 		for (oq_no = 0; oq_no < MAX_OCTEON_OUTPUT_QUEUES(oct);
 		     oq_no++) {
-			if (!(oct->droq_intr & (1ULL << oq_no)))
+			if (!(oct->droq_intr & BIT_ULL(oq_no)))
 				continue;
 
 			droq = oct->droq[oq_no];
@@ -1320,6 +1312,7 @@ liquidio_probe(struct pci_dev *pdev,
 		complete(&first_stage);
 
 	if (octeon_device_init(oct_dev)) {
+		complete(&hs->init);
 		liquidio_remove(pdev);
 		return -ENOMEM;
 	}
@@ -1344,7 +1337,15 @@ liquidio_probe(struct pci_dev *pdev,
 			oct_dev->watchdog_task = kthread_create(
 			    liquidio_watchdog, oct_dev,
 			    "liowd/%02hhx:%02hhx.%hhx", bus, device, function);
-			wake_up_process(oct_dev->watchdog_task);
+			if (!IS_ERR(oct_dev->watchdog_task)) {
+				wake_up_process(oct_dev->watchdog_task);
+			} else {
+				oct_dev->watchdog_task = NULL;
+				dev_err(&oct_dev->pci_dev->dev,
+					"failed to create kernel_thread\n");
+				liquidio_remove(pdev);
+				return -1;
+			}
 		}
 	}
 
@@ -1408,6 +1409,8 @@ static void octeon_destroy_resources(str
 		if (lio_wait_for_oq_pkts(oct))
 			dev_err(&oct->pci_dev->dev, "OQ had pending packets\n");
 
+	/* fallthrough */
+	case OCT_DEV_INTR_SET_DONE:
 		/* Disable interrupts  */
 		oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
 
@@ -1434,12 +1437,20 @@ static void octeon_destroy_resources(str
 				pci_disable_msi(oct->pci_dev);
 		}
 
+	/* fallthrough */
+	case OCT_DEV_MSIX_ALLOC_VECTOR_DONE:
 		if (OCTEON_CN23XX_PF(oct))
 			octeon_free_ioq_vector(oct);
+
+	/* fallthrough */
+	case OCT_DEV_MBOX_SETUP_DONE:
+		if (OCTEON_CN23XX_PF(oct))
+			oct->fn_list.free_mbox(oct);
+
 	/* fallthrough */
 	case OCT_DEV_IN_RESET:
 	case OCT_DEV_DROQ_INIT_DONE:
-		/*atomic_set(&oct->status, OCT_DEV_DROQ_INIT_DONE);*/
+		/* Wait for any pending operations */
 		mdelay(100);
 		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
 			if (!(oct->io_qmask.oq & BIT_ULL(i)))
@@ -1470,6 +1481,10 @@ static void octeon_destroy_resources(str
 				continue;
 			octeon_delete_instr_queue(oct, i);
 		}
+#ifdef CONFIG_PCI_IOV
+		if (oct->sriov_info.sriov_enabled)
+			pci_disable_sriov(oct->pci_dev);
+#endif
 		/* fallthrough */
 	case OCT_DEV_SC_BUFF_POOL_INIT_DONE:
 		octeon_free_sc_buffer_pool(oct);
@@ -1489,10 +1504,13 @@ static void octeon_destroy_resources(str
 		octeon_unmap_pci_barx(oct, 1);
 
 		/* fallthrough */
-	case OCT_DEV_BEGIN_STATE:
+	case OCT_DEV_PCI_ENABLE_DONE:
+		pci_clear_master(oct->pci_dev);
 		/* Disable the device, releasing the PCI INT */
 		pci_disable_device(oct->pci_dev);
 
+		/* fallthrough */
+	case OCT_DEV_BEGIN_STATE:
 		/* Nothing to be done here either */
 		break;
 	}                       /* end switch (oct->status) */
@@ -1762,6 +1780,7 @@ static int octeon_pci_os_setup(struct oc
 
 	if (dma_set_mask_and_coherent(&oct->pci_dev->dev, DMA_BIT_MASK(64))) {
 		dev_err(&oct->pci_dev->dev, "Unexpected DMA device capability\n");
+		pci_disable_device(oct->pci_dev);
 		return 1;
 	}
 
@@ -2424,7 +2443,6 @@ static int liquidio_napi_poll(struct nap
 		 * Return back if tx_done is false.
 		 */
 		update_txq_status(oct, iq_no);
-		/*tx_done = (iq->flush_index == iq->octeon_read_index);*/
 	} else {
 		dev_err(&oct->pci_dev->dev, "%s:  iq (%d) num invalid\n",
 			__func__, iq_no);
@@ -2866,17 +2884,6 @@ static int liquidio_change_mtu(struct ne
 	struct octnic_ctrl_pkt nctrl;
 	int ret = 0;
 
-	/* Limit the MTU to make sure the ethernet packets are between 68 bytes
-	 * and 16000 bytes
-	 */
-	if ((new_mtu < LIO_MIN_MTU_SIZE) ||
-	    (new_mtu > LIO_MAX_MTU_SIZE)) {
-		dev_err(&oct->pci_dev->dev, "Invalid MTU: %d\n", new_mtu);
-		dev_err(&oct->pci_dev->dev, "Valid range %d and %d\n",
-			LIO_MIN_MTU_SIZE, LIO_MAX_MTU_SIZE);
-		return -EINVAL;
-	}
-
 	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
 
 	nctrl.ncmd.u64 = 0;
@@ -3565,7 +3572,152 @@ static void liquidio_del_vxlan_port(stru
 				    OCTNET_CMD_VXLAN_PORT_DEL);
 }
 
-static struct net_device_ops lionetdevops = {
+static int __liquidio_set_vf_mac(struct net_device *netdev, int vfidx,
+				 u8 *mac, bool is_admin_assigned)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+
+	if (!is_valid_ether_addr(mac))
+		return -EINVAL;
+
+	if (vfidx < 0 || vfidx >= oct->sriov_info.max_vfs)
+		return -EINVAL;
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+	nctrl.ncmd.u64 = 0;
+	nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
+	/* vfidx is 0 based, but vf_num (param1) is 1 based */
+	nctrl.ncmd.s.param1 = vfidx + 1;
+	nctrl.ncmd.s.param2 = (is_admin_assigned ? 1 : 0);
+	nctrl.ncmd.s.more = 1;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.cb_fn = 0;
+	nctrl.wait_time = LIO_CMD_WAIT_TM;
+
+	nctrl.udd[0] = 0;
+	/* The MAC Address is presented in network byte order. */
+	ether_addr_copy((u8 *)&nctrl.udd[0] + 2, mac);
+
+	oct->sriov_info.vf_macaddr[vfidx] = nctrl.udd[0];
+
+	octnet_send_nic_ctrl_pkt(oct, &nctrl);
+
+	return 0;
+}
+
+static int liquidio_set_vf_mac(struct net_device *netdev, int vfidx, u8 *mac)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	int retval;
+
+	retval = __liquidio_set_vf_mac(netdev, vfidx, mac, true);
+	if (!retval)
+		cn23xx_tell_vf_its_macaddr_changed(oct, vfidx, mac);
+
+	return retval;
+}
+
+static int liquidio_set_vf_vlan(struct net_device *netdev, int vfidx,
+				u16 vlan, u8 qos, __be16 vlan_proto)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	u16 vlantci;
+
+	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
+		return -EINVAL;
+
+	if (vlan_proto != htons(ETH_P_8021Q))
+		return -EPROTONOSUPPORT;
+
+	if (vlan >= VLAN_N_VID || qos > 7)
+		return -EINVAL;
+
+	if (vlan)
+		vlantci = vlan | (u16)qos << VLAN_PRIO_SHIFT;
+	else
+		vlantci = 0;
+
+	if (oct->sriov_info.vf_vlantci[vfidx] == vlantci)
+		return 0;
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+	if (vlan)
+		nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
+	else
+		nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
+
+	nctrl.ncmd.s.param1 = vlantci;
+	nctrl.ncmd.s.param2 =
+	    vfidx + 1; /* vfidx is 0 based, but vf_num (param2) is 1 based */
+	nctrl.ncmd.s.more = 0;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.cb_fn = 0;
+	nctrl.wait_time = LIO_CMD_WAIT_TM;
+
+	octnet_send_nic_ctrl_pkt(oct, &nctrl);
+
+	oct->sriov_info.vf_vlantci[vfidx] = vlantci;
+
+	return 0;
+}
+
+static int liquidio_get_vf_config(struct net_device *netdev, int vfidx,
+				  struct ifla_vf_info *ivi)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	u8 *macaddr;
+
+	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
+		return -EINVAL;
+
+	ivi->vf = vfidx;
+	macaddr = 2 + (u8 *)&oct->sriov_info.vf_macaddr[vfidx];
+	ether_addr_copy(&ivi->mac[0], macaddr);
+	ivi->vlan = oct->sriov_info.vf_vlantci[vfidx] & VLAN_VID_MASK;
+	ivi->qos = oct->sriov_info.vf_vlantci[vfidx] >> VLAN_PRIO_SHIFT;
+	ivi->linkstate = oct->sriov_info.vf_linkstate[vfidx];
+	return 0;
+}
+
+static int liquidio_set_vf_link_state(struct net_device *netdev, int vfidx,
+				      int linkstate)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+
+	if (vfidx < 0 || vfidx >= oct->sriov_info.num_vfs_alloced)
+		return -EINVAL;
+
+	if (oct->sriov_info.vf_linkstate[vfidx] == linkstate)
+		return 0;
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_VF_LINKSTATE;
+	nctrl.ncmd.s.param1 =
+	    vfidx + 1; /* vfidx is 0 based, but vf_num (param1) is 1 based */
+	nctrl.ncmd.s.param2 = linkstate;
+	nctrl.ncmd.s.more = 0;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.cb_fn = 0;
+	nctrl.wait_time = LIO_CMD_WAIT_TM;
+
+	octnet_send_nic_ctrl_pkt(oct, &nctrl);
+
+	oct->sriov_info.vf_linkstate[vfidx] = linkstate;
+
+	return 0;
+}
+
+static const struct net_device_ops lionetdevops = {
 	.ndo_open		= liquidio_open,
 	.ndo_stop		= liquidio_stop,
 	.ndo_start_xmit		= liquidio_xmit,
@@ -3582,6 +3734,11 @@ static struct net_device_ops lionetdevop
 	.ndo_set_features	= liquidio_set_features,
 	.ndo_udp_tunnel_add	= liquidio_add_vxlan_port,
 	.ndo_udp_tunnel_del	= liquidio_del_vxlan_port,
+	.ndo_set_vf_mac		= liquidio_set_vf_mac,
+	.ndo_set_vf_vlan	= liquidio_set_vf_vlan,
+	.ndo_get_vf_config	= liquidio_get_vf_config,
+	.ndo_set_vf_link_state  = liquidio_set_vf_link_state,
+	.ndo_select_queue	= select_q
 };
 
 /** \brief Entry point for the liquidio module
@@ -3593,7 +3750,7 @@ static int __init liquidio_init(void)
 
 	init_completion(&first_stage);
 
-	octeon_init_device_list(conf_type);
+	octeon_init_device_list(OCTEON_CONFIG_TYPE_DEFAULT);
 
 	if (liquidio_init_pci())
 		return -EINVAL;
@@ -3814,9 +3971,6 @@ static int setup_nic_devices(struct octe
 
 		SET_NETDEV_DEV(netdev, &octeon_dev->pci_dev->dev);
 
-		if (num_iqueues > 1)
-			lionetdevops.ndo_select_queue = select_q;
-
 		/* Associate the routines that will handle different
 		 * netdev tasks.
 		 */
@@ -3889,6 +4043,10 @@ static int setup_nic_devices(struct octe
 		netdev->hw_features = netdev->hw_features &
 			~NETIF_F_HW_VLAN_CTAG_RX;
 
+		/* MTU range: 68 - 16000 */
+		netdev->min_mtu = LIO_MIN_MTU_SIZE;
+		netdev->max_mtu = LIO_MAX_MTU_SIZE;
+
 		/* Point to the  properties for octeon device to which this
 		 * interface belongs.
 		 */
@@ -3900,6 +4058,19 @@ static int setup_nic_devices(struct octe
 			"if%d gmx: %d hw_addr: 0x%llx\n", i,
 			lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr));
 
+		for (j = 0; j < octeon_dev->sriov_info.max_vfs; j++) {
+			u8 vfmac[ETH_ALEN];
+
+			random_ether_addr(&vfmac[0]);
+			if (__liquidio_set_vf_mac(netdev, j,
+						  &vfmac[0], false)) {
+				dev_err(&octeon_dev->pci_dev->dev,
+					"Error setting VF%d MAC address\n",
+					j);
+				goto setup_nic_dev_fail;
+			}
+		}
+
 		/* 64-bit swap required on LE machines */
 		octeon_swap_8B_data(&lio->linfo.hw_addr, 1);
 		for (j = 0; j < 6; j++)
@@ -3995,6 +4166,101 @@ setup_nic_wait_intr:
 	return -ENODEV;
 }
 
+#ifdef CONFIG_PCI_IOV
+static int octeon_enable_sriov(struct octeon_device *oct)
+{
+	unsigned int num_vfs_alloced = oct->sriov_info.num_vfs_alloced;
+	struct pci_dev *vfdev;
+	int err;
+	u32 u;
+
+	if (OCTEON_CN23XX_PF(oct) && num_vfs_alloced) {
+		err = pci_enable_sriov(oct->pci_dev,
+				       oct->sriov_info.num_vfs_alloced);
+		if (err) {
+			dev_err(&oct->pci_dev->dev,
+				"OCTEON: Failed to enable PCI sriov: %d\n",
+				err);
+			oct->sriov_info.num_vfs_alloced = 0;
+			return err;
+		}
+		oct->sriov_info.sriov_enabled = 1;
+
+		/* init lookup table that maps DPI ring number to VF pci_dev
+		 * struct pointer
+		 */
+		u = 0;
+		vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+				       OCTEON_CN23XX_VF_VID, NULL);
+		while (vfdev) {
+			if (vfdev->is_virtfn &&
+			    (vfdev->physfn == oct->pci_dev)) {
+				oct->sriov_info.dpiring_to_vfpcidev_lut[u] =
+					vfdev;
+				u += oct->sriov_info.rings_per_vf;
+			}
+			vfdev = pci_get_device(PCI_VENDOR_ID_CAVIUM,
+					       OCTEON_CN23XX_VF_VID, vfdev);
+		}
+	}
+
+	return num_vfs_alloced;
+}
+
+static int lio_pci_sriov_disable(struct octeon_device *oct)
+{
+	int u;
+
+	if (pci_vfs_assigned(oct->pci_dev)) {
+		dev_err(&oct->pci_dev->dev, "VFs are still assigned to VMs.\n");
+		return -EPERM;
+	}
+
+	pci_disable_sriov(oct->pci_dev);
+
+	u = 0;
+	while (u < MAX_POSSIBLE_VFS) {
+		oct->sriov_info.dpiring_to_vfpcidev_lut[u] = NULL;
+		u += oct->sriov_info.rings_per_vf;
+	}
+
+	oct->sriov_info.num_vfs_alloced = 0;
+	dev_info(&oct->pci_dev->dev, "oct->pf_num:%d disabled VFs\n",
+		 oct->pf_num);
+
+	return 0;
+}
+
+static int liquidio_enable_sriov(struct pci_dev *dev, int num_vfs)
+{
+	struct octeon_device *oct = pci_get_drvdata(dev);
+	int ret = 0;
+
+	if ((num_vfs == oct->sriov_info.num_vfs_alloced) &&
+	    (oct->sriov_info.sriov_enabled)) {
+		dev_info(&oct->pci_dev->dev, "oct->pf_num:%d already enabled num_vfs:%d\n",
+			 oct->pf_num, num_vfs);
+		return 0;
+	}
+
+	if (!num_vfs) {
+		ret = lio_pci_sriov_disable(oct);
+	} else if (num_vfs > oct->sriov_info.max_vfs) {
+		dev_err(&oct->pci_dev->dev,
+			"OCTEON: Max allowed VFs:%d user requested:%d",
+			oct->sriov_info.max_vfs, num_vfs);
+		ret = -EPERM;
+	} else {
+		oct->sriov_info.num_vfs_alloced = num_vfs;
+		ret = octeon_enable_sriov(oct);
+		dev_info(&oct->pci_dev->dev, "oct->pf_num:%d num_vfs:%d\n",
+			 oct->pf_num, num_vfs);
+	}
+
+	return ret;
+}
+#endif
+
 /**
  * \brief initialize the NIC
  * @param oct octeon device
@@ -4100,6 +4366,52 @@ static void nic_starter(struct work_stru
 	complete(&handshake[oct->octeon_id].started);
 }
 
+static int
+octeon_recv_vf_drv_notice(struct octeon_recv_info *recv_info, void *buf)
+{
+	struct octeon_device *oct = (struct octeon_device *)buf;
+	struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
+	int i, notice, vf_idx;
+	u64 *data, vf_num;
+
+	notice = recv_pkt->rh.r.ossp;
+	data = (u64 *)get_rbd(recv_pkt->buffer_ptr[0]);
+
+	/* the first 64-bit word of data is the vf_num */
+	vf_num = data[0];
+	octeon_swap_8B_data(&vf_num, 1);
+	vf_idx = (int)vf_num - 1;
+
+	if (notice == VF_DRV_LOADED) {
+		if (!(oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vf_idx))) {
+			oct->sriov_info.vf_drv_loaded_mask |= BIT_ULL(vf_idx);
+			dev_info(&oct->pci_dev->dev,
+				 "driver for VF%d was loaded\n", vf_idx);
+			try_module_get(THIS_MODULE);
+		}
+	} else if (notice == VF_DRV_REMOVED) {
+		if (oct->sriov_info.vf_drv_loaded_mask & BIT_ULL(vf_idx)) {
+			oct->sriov_info.vf_drv_loaded_mask &= ~BIT_ULL(vf_idx);
+			dev_info(&oct->pci_dev->dev,
+				 "driver for VF%d was removed\n", vf_idx);
+			module_put(THIS_MODULE);
+		}
+	} else if (notice == VF_DRV_MACADDR_CHANGED) {
+		u8 *b = (u8 *)&data[1];
+
+		oct->sriov_info.vf_macaddr[vf_idx] = data[1];
+		dev_info(&oct->pci_dev->dev,
+			 "VF driver changed VF%d's MAC address to %pM\n",
+			 vf_idx, b + 2);
+	}
+
+	for (i = 0; i < recv_pkt->buffer_count; i++)
+		recv_buffer_free(recv_pkt->buffer_ptr[i]);
+	octeon_free_recv_info(recv_info);
+
+	return 0;
+}
+
 /**
  * \brief Device initialization for each Octeon device that is probed
  * @param octeon_dev  octeon device
@@ -4119,6 +4431,8 @@ static int octeon_device_init(struct oct
 	if (octeon_pci_os_setup(octeon_dev))
 		return 1;
 
+	atomic_set(&octeon_dev->status, OCT_DEV_PCI_ENABLE_DONE);
+
 	/* Identify the Octeon type and map the BAR address space. */
 	if (octeon_chip_specific_setup(octeon_dev)) {
 		dev_err(&octeon_dev->pci_dev->dev, "Chip specific setup failed\n");
@@ -4158,6 +4472,9 @@ static int octeon_device_init(struct oct
 				    octeon_core_drv_init,
 				    octeon_dev);
 
+	octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC,
+				    OPCODE_NIC_VF_DRV_NOTICE,
+				    octeon_recv_vf_drv_notice, octeon_dev);
 	INIT_DELAYED_WORK(&octeon_dev->nic_poll_work.work, nic_starter);
 	octeon_dev->nic_poll_work.ctxptr = (void *)octeon_dev;
 	schedule_delayed_work(&octeon_dev->nic_poll_work.work,
@@ -4165,7 +4482,10 @@ static int octeon_device_init(struct oct
 
 	atomic_set(&octeon_dev->status, OCT_DEV_DISPATCH_INIT_DONE);
 
-	octeon_set_io_queues_off(octeon_dev);
+	if (octeon_set_io_queues_off(octeon_dev)) {
+		dev_err(&octeon_dev->pci_dev->dev, "setting io queues off failed\n");
+		return 1;
+	}
 
 	if (OCTEON_CN23XX_PF(octeon_dev)) {
 		ret = octeon_dev->fn_list.setup_device_regs(octeon_dev);
@@ -4187,9 +4507,6 @@ static int octeon_device_init(struct oct
 	if (octeon_setup_instr_queues(octeon_dev)) {
 		dev_err(&octeon_dev->pci_dev->dev,
 			"instruction queue initialization failed\n");
-		/* On error, release any previously allocated queues */
-		for (j = 0; j < octeon_dev->num_iqs; j++)
-			octeon_delete_instr_queue(octeon_dev, j);
 		return 1;
 	}
 	atomic_set(&octeon_dev->status, OCT_DEV_INSTR_QUEUE_INIT_DONE);
@@ -4205,19 +4522,23 @@ static int octeon_device_init(struct oct
 
 	if (octeon_setup_output_queues(octeon_dev)) {
 		dev_err(&octeon_dev->pci_dev->dev, "Output queue initialization failed\n");
-		/* Release any previously allocated queues */
-		for (j = 0; j < octeon_dev->num_oqs; j++)
-			octeon_delete_droq(octeon_dev, j);
 		return 1;
 	}
 
 	atomic_set(&octeon_dev->status, OCT_DEV_DROQ_INIT_DONE);
 
 	if (OCTEON_CN23XX_PF(octeon_dev)) {
+		if (octeon_dev->fn_list.setup_mbox(octeon_dev)) {
+			dev_err(&octeon_dev->pci_dev->dev, "OCTEON: Mailbox setup failed\n");
+			return 1;
+		}
+		atomic_set(&octeon_dev->status, OCT_DEV_MBOX_SETUP_DONE);
+
 		if (octeon_allocate_ioq_vector(octeon_dev)) {
 			dev_err(&octeon_dev->pci_dev->dev, "OCTEON: ioq vector allocation failed\n");
 			return 1;
 		}
+		atomic_set(&octeon_dev->status, OCT_DEV_MSIX_ALLOC_VECTOR_DONE);
 
 	} else {
 		/* The input and output queue registers were setup earlier (the
@@ -4245,6 +4566,8 @@ static int octeon_device_init(struct oct
 	/* Enable Octeon device interrupts */
 	octeon_dev->fn_list.enable_interrupt(octeon_dev, OCTEON_ALL_INTR);
 
+	atomic_set(&octeon_dev->status, OCT_DEV_INTR_SET_DONE);
+
 	/* Enable the input and output queues for this Octeon device */
 	ret = octeon_dev->fn_list.enable_io_queues(octeon_dev);
 	if (ret) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,3251 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <net/vxlan.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+#include "octeon_nic.h"
+#include "octeon_main.h"
+#include "octeon_network.h"
+#include "cn23xx_vf_device.h"
+
+MODULE_AUTHOR("Cavium Networks, <support@cavium.com>");
+MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Virtual Function Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(LIQUIDIO_VERSION);
+
+static int debug = -1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "NETIF_MSG debug bits");
+
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+
+/* Bit mask values for lio->ifstate */
+#define   LIO_IFSTATE_DROQ_OPS             0x01
+#define   LIO_IFSTATE_REGISTERED           0x02
+#define   LIO_IFSTATE_RUNNING              0x04
+#define   LIO_IFSTATE_RX_TIMESTAMP_ENABLED 0x08
+
+struct liquidio_if_cfg_context {
+	int octeon_id;
+
+	wait_queue_head_t wc;
+
+	int cond;
+};
+
+struct liquidio_if_cfg_resp {
+	u64 rh;
+	struct liquidio_if_cfg_info cfg_info;
+	u64 status;
+};
+
+struct liquidio_rx_ctl_context {
+	int octeon_id;
+
+	wait_queue_head_t wc;
+
+	int cond;
+};
+
+struct oct_timestamp_resp {
+	u64 rh;
+	u64 timestamp;
+	u64 status;
+};
+
+union tx_info {
+	u64 u64;
+	struct {
+#ifdef __BIG_ENDIAN_BITFIELD
+		u16 gso_size;
+		u16 gso_segs;
+		u32 reserved;
+#else
+		u32 reserved;
+		u16 gso_segs;
+		u16 gso_size;
+#endif
+	} s;
+};
+
+#define OCTNIC_MAX_SG  (MAX_SKB_FRAGS)
+
+#define OCTNIC_GSO_MAX_HEADER_SIZE 128
+#define OCTNIC_GSO_MAX_SIZE \
+		(CN23XX_DEFAULT_INPUT_JABBER - OCTNIC_GSO_MAX_HEADER_SIZE)
+
+struct octnic_gather {
+	/* List manipulation. Next and prev pointers. */
+	struct list_head list;
+
+	/* Size of the gather component at sg in bytes. */
+	int sg_size;
+
+	/* Number of bytes that sg was adjusted to make it 8B-aligned. */
+	int adjust;
+
+	/* Gather component that can accommodate max sized fragment list
+	 * received from the IP layer.
+	 */
+	struct octeon_sg_entry *sg;
+};
+
+struct octeon_device_priv {
+	/* Tasklet structures for this device. */
+	struct tasklet_struct droq_tasklet;
+	unsigned long napi_mask;
+};
+
+static int
+liquidio_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void liquidio_vf_remove(struct pci_dev *pdev);
+static int octeon_device_init(struct octeon_device *oct);
+static int liquidio_stop(struct net_device *netdev);
+
+static int lio_wait_for_oq_pkts(struct octeon_device *oct)
+{
+	struct octeon_device_priv *oct_priv =
+	    (struct octeon_device_priv *)oct->priv;
+	int retry = MAX_VF_IP_OP_PENDING_PKT_COUNT;
+	int pkt_cnt = 0, pending_pkts;
+	int i;
+
+	do {
+		pending_pkts = 0;
+
+		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
+			if (!(oct->io_qmask.oq & BIT_ULL(i)))
+				continue;
+			pkt_cnt += octeon_droq_check_hw_for_pkts(oct->droq[i]);
+		}
+		if (pkt_cnt > 0) {
+			pending_pkts += pkt_cnt;
+			tasklet_schedule(&oct_priv->droq_tasklet);
+		}
+		pkt_cnt = 0;
+		schedule_timeout_uninterruptible(1);
+
+	} while (retry-- && pending_pkts);
+
+	return pkt_cnt;
+}
+
+/**
+ * \brief wait for all pending requests to complete
+ * @param oct Pointer to Octeon device
+ *
+ * Called during shutdown sequence
+ */
+static int wait_for_pending_requests(struct octeon_device *oct)
+{
+	int i, pcount = 0;
+
+	for (i = 0; i < MAX_VF_IP_OP_PENDING_PKT_COUNT; i++) {
+		pcount = atomic_read(
+		    &oct->response_list[OCTEON_ORDERED_SC_LIST]
+			 .pending_req_count);
+		if (pcount)
+			schedule_timeout_uninterruptible(HZ / 10);
+		else
+			break;
+	}
+
+	if (pcount)
+		return 1;
+
+	return 0;
+}
+
+/**
+ * \brief Cause device to go quiet so it can be safely removed/reset/etc
+ * @param oct Pointer to Octeon device
+ */
+static void pcierror_quiesce_device(struct octeon_device *oct)
+{
+	int i;
+
+	/* Disable the input and output queues now. No more packets will
+	 * arrive from Octeon, but we should wait for all packet processing
+	 * to finish.
+	 */
+
+	/* To allow for in-flight requests */
+	schedule_timeout_uninterruptible(100);
+
+	if (wait_for_pending_requests(oct))
+		dev_err(&oct->pci_dev->dev, "There were pending requests\n");
+
+	/* Force all requests waiting to be fetched by OCTEON to complete. */
+	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
+		struct octeon_instr_queue *iq;
+
+		if (!(oct->io_qmask.iq & BIT_ULL(i)))
+			continue;
+		iq = oct->instr_queue[i];
+
+		if (atomic_read(&iq->instr_pending)) {
+			spin_lock_bh(&iq->lock);
+			iq->fill_cnt = 0;
+			iq->octeon_read_index = iq->host_write_index;
+			iq->stats.instr_processed +=
+			    atomic_read(&iq->instr_pending);
+			lio_process_iq_request_list(oct, iq, 0);
+			spin_unlock_bh(&iq->lock);
+		}
+	}
+
+	/* Force all pending ordered list requests to time out. */
+	lio_process_ordered_list(oct, 1);
+
+	/* We do not need to wait for output queue packets to be processed. */
+}
+
+/**
+ * \brief Cleanup PCI AER uncorrectable error status
+ * @param dev Pointer to PCI device
+ */
+static void cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+{
+	u32 status, mask;
+	int pos = 0x100;
+
+	pr_info("%s :\n", __func__);
+
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
+	if (dev->error_state == pci_channel_io_normal)
+		status &= ~mask; /* Clear corresponding nonfatal bits */
+	else
+		status &= mask; /* Clear corresponding fatal bits */
+	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+}
+
+/**
+ * \brief Stop all PCI IO to a given device
+ * @param dev Pointer to Octeon device
+ */
+static void stop_pci_io(struct octeon_device *oct)
+{
+	struct msix_entry *msix_entries;
+	int i;
+
+	/* No more instructions will be forwarded. */
+	atomic_set(&oct->status, OCT_DEV_IN_RESET);
+
+	for (i = 0; i < oct->ifcount; i++)
+		netif_device_detach(oct->props[i].netdev);
+
+	/* Disable interrupts  */
+	oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
+
+	pcierror_quiesce_device(oct);
+	if (oct->msix_on) {
+		msix_entries = (struct msix_entry *)oct->msix_entries;
+		for (i = 0; i < oct->num_msix_irqs; i++) {
+			/* clear the affinity_cpumask */
+			irq_set_affinity_hint(msix_entries[i].vector,
+					      NULL);
+			free_irq(msix_entries[i].vector,
+				 &oct->ioq_vector[i]);
+		}
+		pci_disable_msix(oct->pci_dev);
+		kfree(oct->msix_entries);
+		oct->msix_entries = NULL;
+		octeon_free_ioq_vector(oct);
+	}
+	dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
+		lio_get_state_string(&oct->status));
+
+	/* making it a common function for all OCTEON models */
+	cleanup_aer_uncorrect_error_status(oct->pci_dev);
+
+	pci_disable_device(oct->pci_dev);
+}
+
+/**
+ * \brief called when PCI error is detected
+ * @param pdev Pointer to PCI device
+ * @param 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 liquidio_pcie_error_detected(struct pci_dev *pdev,
+						     pci_channel_state_t state)
+{
+	struct octeon_device *oct = pci_get_drvdata(pdev);
+
+	/* Non-correctable Non-fatal errors */
+	if (state == pci_channel_io_normal) {
+		dev_err(&oct->pci_dev->dev, "Non-correctable non-fatal error reported:\n");
+		cleanup_aer_uncorrect_error_status(oct->pci_dev);
+		return PCI_ERS_RESULT_CAN_RECOVER;
+	}
+
+	/* Non-correctable Fatal errors */
+	dev_err(&oct->pci_dev->dev, "Non-correctable FATAL reported by PCI AER driver\n");
+	stop_pci_io(oct);
+
+	return PCI_ERS_RESULT_DISCONNECT;
+}
+
+/* For PCI-E Advanced Error Recovery (AER) Interface */
+static const struct pci_error_handlers liquidio_vf_err_handler = {
+	.error_detected = liquidio_pcie_error_detected,
+};
+
+static const struct pci_device_id liquidio_vf_pci_tbl[] = {
+	{
+		PCI_VENDOR_ID_CAVIUM, OCTEON_CN23XX_VF_VID,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0
+	},
+	{
+		0, 0, 0, 0, 0, 0, 0
+	}
+};
+MODULE_DEVICE_TABLE(pci, liquidio_vf_pci_tbl);
+
+static struct pci_driver liquidio_vf_pci_driver = {
+	.name		= "LiquidIO_VF",
+	.id_table	= liquidio_vf_pci_tbl,
+	.probe		= liquidio_vf_probe,
+	.remove		= liquidio_vf_remove,
+	.err_handler	= &liquidio_vf_err_handler,    /* For AER */
+};
+
+/**
+ * \brief check interface state
+ * @param lio per-network private data
+ * @param state_flag flag state to check
+ */
+static int ifstate_check(struct lio *lio, int state_flag)
+{
+	return atomic_read(&lio->ifstate) & state_flag;
+}
+
+/**
+ * \brief set interface state
+ * @param lio per-network private data
+ * @param state_flag flag state to set
+ */
+static void ifstate_set(struct lio *lio, int state_flag)
+{
+	atomic_set(&lio->ifstate, (atomic_read(&lio->ifstate) | state_flag));
+}
+
+/**
+ * \brief clear interface state
+ * @param lio per-network private data
+ * @param state_flag flag state to clear
+ */
+static void ifstate_reset(struct lio *lio, int state_flag)
+{
+	atomic_set(&lio->ifstate, (atomic_read(&lio->ifstate) & ~(state_flag)));
+}
+
+/**
+ * \brief Stop Tx queues
+ * @param netdev network device
+ */
+static void txqs_stop(struct net_device *netdev)
+{
+	if (netif_is_multiqueue(netdev)) {
+		int i;
+
+		for (i = 0; i < netdev->num_tx_queues; i++)
+			netif_stop_subqueue(netdev, i);
+	} else {
+		netif_stop_queue(netdev);
+	}
+}
+
+/**
+ * \brief Start Tx queues
+ * @param netdev network device
+ */
+static void txqs_start(struct net_device *netdev)
+{
+	if (netif_is_multiqueue(netdev)) {
+		int i;
+
+		for (i = 0; i < netdev->num_tx_queues; i++)
+			netif_start_subqueue(netdev, i);
+	} else {
+		netif_start_queue(netdev);
+	}
+}
+
+/**
+ * \brief Wake Tx queues
+ * @param netdev network device
+ */
+static void txqs_wake(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+
+	if (netif_is_multiqueue(netdev)) {
+		int i;
+
+		for (i = 0; i < netdev->num_tx_queues; i++) {
+			int qno = lio->linfo.txpciq[i % (lio->linfo.num_txpciq)]
+				      .s.q_no;
+			if (__netif_subqueue_stopped(netdev, i)) {
+				INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, qno,
+							  tx_restart, 1);
+				netif_wake_subqueue(netdev, i);
+			}
+		}
+	} else {
+		INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, lio->txq,
+					  tx_restart, 1);
+		netif_wake_queue(netdev);
+	}
+}
+
+/**
+ * \brief Start Tx queue
+ * @param netdev network device
+ */
+static void start_txq(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+
+	if (lio->linfo.link.s.link_up) {
+		txqs_start(netdev);
+		return;
+	}
+}
+
+/**
+ * \brief Wake a queue
+ * @param netdev network device
+ * @param q which queue to wake
+ */
+static void wake_q(struct net_device *netdev, int q)
+{
+	if (netif_is_multiqueue(netdev))
+		netif_wake_subqueue(netdev, q);
+	else
+		netif_wake_queue(netdev);
+}
+
+/**
+ * \brief Stop a queue
+ * @param netdev network device
+ * @param q which queue to stop
+ */
+static void stop_q(struct net_device *netdev, int q)
+{
+	if (netif_is_multiqueue(netdev))
+		netif_stop_subqueue(netdev, q);
+	else
+		netif_stop_queue(netdev);
+}
+
+/**
+ * Remove the node at the head of the list. The list would be empty at
+ * the end of this call if there are no more nodes in the list.
+ */
+static struct list_head *list_delete_head(struct list_head *root)
+{
+	struct list_head *node;
+
+	if ((root->prev == root) && (root->next == root))
+		node = NULL;
+	else
+		node = root->next;
+
+	if (node)
+		list_del(node);
+
+	return node;
+}
+
+/**
+ * \brief Delete gather lists
+ * @param lio per-network private data
+ */
+static void delete_glists(struct lio *lio)
+{
+	struct octnic_gather *g;
+	int i;
+
+	if (!lio->glist)
+		return;
+
+	for (i = 0; i < lio->linfo.num_txpciq; i++) {
+		do {
+			g = (struct octnic_gather *)
+			    list_delete_head(&lio->glist[i]);
+			if (g) {
+				if (g->sg)
+					kfree((void *)((unsigned long)g->sg -
+							g->adjust));
+				kfree(g);
+			}
+		} while (g);
+	}
+
+	kfree(lio->glist);
+	kfree(lio->glist_lock);
+}
+
+/**
+ * \brief Setup gather lists
+ * @param lio per-network private data
+ */
+static int setup_glists(struct lio *lio, int num_iqs)
+{
+	struct octnic_gather *g;
+	int i, j;
+
+	lio->glist_lock =
+	    kzalloc(sizeof(*lio->glist_lock) * num_iqs, GFP_KERNEL);
+	if (!lio->glist_lock)
+		return 1;
+
+	lio->glist =
+	    kzalloc(sizeof(*lio->glist) * num_iqs, GFP_KERNEL);
+	if (!lio->glist) {
+		kfree(lio->glist_lock);
+		return 1;
+	}
+
+	for (i = 0; i < num_iqs; i++) {
+		spin_lock_init(&lio->glist_lock[i]);
+
+		INIT_LIST_HEAD(&lio->glist[i]);
+
+		for (j = 0; j < lio->tx_qsize; j++) {
+			g = kzalloc(sizeof(*g), GFP_KERNEL);
+			if (!g)
+				break;
+
+			g->sg_size = ((ROUNDUP4(OCTNIC_MAX_SG) >> 2) *
+				      OCT_SG_ENTRY_SIZE);
+
+			g->sg = kmalloc(g->sg_size + 8, GFP_KERNEL);
+			if (!g->sg) {
+				kfree(g);
+				break;
+			}
+
+			/* The gather component should be aligned on 64-bit
+			 * boundary
+			 */
+			if (((unsigned long)g->sg) & 7) {
+				g->adjust = 8 - (((unsigned long)g->sg) & 7);
+				g->sg = (struct octeon_sg_entry *)
+					((unsigned long)g->sg + g->adjust);
+			}
+			list_add_tail(&g->list, &lio->glist[i]);
+		}
+
+		if (j != lio->tx_qsize) {
+			delete_glists(lio);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * \brief Print link information
+ * @param netdev network device
+ */
+static void print_link_info(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+
+	if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED) {
+		struct oct_link_info *linfo = &lio->linfo;
+
+		if (linfo->link.s.link_up) {
+			netif_info(lio, link, lio->netdev, "%d Mbps %s Duplex UP\n",
+				   linfo->link.s.speed,
+				   (linfo->link.s.duplex) ? "Full" : "Half");
+		} else {
+			netif_info(lio, link, lio->netdev, "Link Down\n");
+		}
+	}
+}
+
+/**
+ * \brief Routine to notify MTU change
+ * @param work work_struct data structure
+ */
+static void octnet_link_status_change(struct work_struct *work)
+{
+	struct cavium_wk *wk = (struct cavium_wk *)work;
+	struct lio *lio = (struct lio *)wk->ctxptr;
+
+	rtnl_lock();
+	call_netdevice_notifiers(NETDEV_CHANGEMTU, lio->netdev);
+	rtnl_unlock();
+}
+
+/**
+ * \brief Sets up the mtu status change work
+ * @param netdev network device
+ */
+static int setup_link_status_change_wq(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+
+	lio->link_status_wq.wq = alloc_workqueue("link-status",
+						 WQ_MEM_RECLAIM, 0);
+	if (!lio->link_status_wq.wq) {
+		dev_err(&oct->pci_dev->dev, "unable to create cavium link status wq\n");
+		return -1;
+	}
+	INIT_DELAYED_WORK(&lio->link_status_wq.wk.work,
+			  octnet_link_status_change);
+	lio->link_status_wq.wk.ctxptr = lio;
+
+	return 0;
+}
+
+static void cleanup_link_status_change_wq(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+
+	if (lio->link_status_wq.wq) {
+		cancel_delayed_work_sync(&lio->link_status_wq.wk.work);
+		destroy_workqueue(lio->link_status_wq.wq);
+	}
+}
+
+/**
+ * \brief Update link status
+ * @param netdev network device
+ * @param ls link status structure
+ *
+ * Called on receipt of a link status response from the core application to
+ * update each interface's link status.
+ */
+static void update_link_status(struct net_device *netdev,
+			       union oct_link_status *ls)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+
+	if ((lio->intf_open) && (lio->linfo.link.u64 != ls->u64)) {
+		lio->linfo.link.u64 = ls->u64;
+
+		print_link_info(netdev);
+		lio->link_changes++;
+
+		if (lio->linfo.link.s.link_up) {
+			netif_carrier_on(netdev);
+			txqs_wake(netdev);
+		} else {
+			netif_carrier_off(netdev);
+			txqs_stop(netdev);
+		}
+
+		if (lio->linfo.link.s.mtu < netdev->mtu) {
+			dev_warn(&oct->pci_dev->dev,
+				 "PF has changed the MTU for gmx port. Reducing the mtu from %d to %d\n",
+				 netdev->mtu, lio->linfo.link.s.mtu);
+			lio->mtu = lio->linfo.link.s.mtu;
+			netdev->mtu = lio->linfo.link.s.mtu;
+			queue_delayed_work(lio->link_status_wq.wq,
+					   &lio->link_status_wq.wk.work, 0);
+		}
+	}
+}
+
+static void update_txq_status(struct octeon_device *oct, int iq_num)
+{
+	struct octeon_instr_queue *iq = oct->instr_queue[iq_num];
+	struct net_device *netdev;
+	struct lio *lio;
+
+	netdev = oct->props[iq->ifidx].netdev;
+	lio = GET_LIO(netdev);
+	if (netif_is_multiqueue(netdev)) {
+		if (__netif_subqueue_stopped(netdev, iq->q_index) &&
+		    lio->linfo.link.s.link_up &&
+		    (!octnet_iq_is_full(oct, iq_num))) {
+			netif_wake_subqueue(netdev, iq->q_index);
+			INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq_num,
+						  tx_restart, 1);
+		} else {
+			if (!octnet_iq_is_full(oct, lio->txq)) {
+				INCR_INSTRQUEUE_PKT_COUNT(
+				    lio->oct_dev, lio->txq, tx_restart, 1);
+				wake_q(netdev, lio->txq);
+			}
+		}
+	}
+}
+
+static
+int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret)
+{
+	struct octeon_device *oct = droq->oct_dev;
+	struct octeon_device_priv *oct_priv =
+	    (struct octeon_device_priv *)oct->priv;
+
+	if (droq->ops.poll_mode) {
+		droq->ops.napi_fn(droq);
+	} else {
+		if (ret & MSIX_PO_INT) {
+			dev_err(&oct->pci_dev->dev,
+				"should not come here should not get rx when poll mode = 0 for vf\n");
+			tasklet_schedule(&oct_priv->droq_tasklet);
+			return 1;
+		}
+		/* this will be flushed periodically by check iq db */
+		if (ret & MSIX_PI_INT)
+			return 0;
+	}
+	return 0;
+}
+
+static irqreturn_t
+liquidio_msix_intr_handler(int irq __attribute__((unused)), void *dev)
+{
+	struct octeon_ioq_vector *ioq_vector = (struct octeon_ioq_vector *)dev;
+	struct octeon_device *oct = ioq_vector->oct_dev;
+	struct octeon_droq *droq = oct->droq[ioq_vector->droq_index];
+	u64 ret;
+
+	ret = oct->fn_list.msix_interrupt_handler(ioq_vector);
+
+	if ((ret & MSIX_PO_INT) || (ret & MSIX_PI_INT))
+		liquidio_schedule_msix_droq_pkt_handler(droq, ret);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * \brief Setup interrupt for octeon device
+ * @param oct octeon device
+ *
+ *  Enable interrupt in Octeon device as given in the PCI interrupt mask.
+ */
+static int octeon_setup_interrupt(struct octeon_device *oct)
+{
+	struct msix_entry *msix_entries;
+	int num_alloc_ioq_vectors;
+	int num_ioq_vectors;
+	int irqret;
+	int i;
+
+	if (oct->msix_on) {
+		oct->num_msix_irqs = oct->sriov_info.rings_per_vf;
+
+		oct->msix_entries = kcalloc(
+		    oct->num_msix_irqs, sizeof(struct msix_entry), GFP_KERNEL);
+		if (!oct->msix_entries)
+			return 1;
+
+		msix_entries = (struct msix_entry *)oct->msix_entries;
+
+		for (i = 0; i < oct->num_msix_irqs; i++)
+			msix_entries[i].entry = i;
+		num_alloc_ioq_vectors = pci_enable_msix_range(
+						oct->pci_dev, msix_entries,
+						oct->num_msix_irqs,
+						oct->num_msix_irqs);
+		if (num_alloc_ioq_vectors < 0) {
+			dev_err(&oct->pci_dev->dev, "unable to Allocate MSI-X interrupts\n");
+			kfree(oct->msix_entries);
+			oct->msix_entries = NULL;
+			return 1;
+		}
+		dev_dbg(&oct->pci_dev->dev, "OCTEON: Enough MSI-X interrupts are allocated...\n");
+
+		num_ioq_vectors = oct->num_msix_irqs;
+
+		for (i = 0; i < num_ioq_vectors; i++) {
+			irqret = request_irq(msix_entries[i].vector,
+					     liquidio_msix_intr_handler, 0,
+					     "octeon", &oct->ioq_vector[i]);
+			if (irqret) {
+				dev_err(&oct->pci_dev->dev,
+					"OCTEON: Request_irq failed for MSIX interrupt Error: %d\n",
+					irqret);
+
+				while (i) {
+					i--;
+					irq_set_affinity_hint(
+					    msix_entries[i].vector, NULL);
+					free_irq(msix_entries[i].vector,
+						 &oct->ioq_vector[i]);
+				}
+				pci_disable_msix(oct->pci_dev);
+				kfree(oct->msix_entries);
+				oct->msix_entries = NULL;
+				return 1;
+			}
+			oct->ioq_vector[i].vector = msix_entries[i].vector;
+			/* assign the cpu mask for this msix interrupt vector */
+			irq_set_affinity_hint(
+			    msix_entries[i].vector,
+			    (&oct->ioq_vector[i].affinity_mask));
+		}
+		dev_dbg(&oct->pci_dev->dev,
+			"OCTEON[%d]: MSI-X enabled\n", oct->octeon_id);
+	}
+	return 0;
+}
+
+/**
+ * \brief PCI probe handler
+ * @param pdev PCI device structure
+ * @param ent unused
+ */
+static int
+liquidio_vf_probe(struct pci_dev *pdev,
+		  const struct pci_device_id *ent __attribute__((unused)))
+{
+	struct octeon_device *oct_dev = NULL;
+
+	oct_dev = octeon_allocate_device(pdev->device,
+					 sizeof(struct octeon_device_priv));
+
+	if (!oct_dev) {
+		dev_err(&pdev->dev, "Unable to allocate device\n");
+		return -ENOMEM;
+	}
+	oct_dev->msix_on = LIO_FLAG_MSIX_ENABLED;
+
+	dev_info(&pdev->dev, "Initializing device %x:%x.\n",
+		 (u32)pdev->vendor, (u32)pdev->device);
+
+	/* Assign octeon_device for this device to the private data area. */
+	pci_set_drvdata(pdev, oct_dev);
+
+	/* set linux specific device pointer */
+	oct_dev->pci_dev = pdev;
+
+	if (octeon_device_init(oct_dev)) {
+		liquidio_vf_remove(pdev);
+		return -ENOMEM;
+	}
+
+	dev_dbg(&oct_dev->pci_dev->dev, "Device is ready\n");
+
+	return 0;
+}
+
+/**
+ * \brief PCI FLR for each Octeon device.
+ * @param oct octeon device
+ */
+static void octeon_pci_flr(struct octeon_device *oct)
+{
+	u16 status;
+
+	pci_save_state(oct->pci_dev);
+
+	pci_cfg_access_lock(oct->pci_dev);
+
+	/* Quiesce the device completely */
+	pci_write_config_word(oct->pci_dev, PCI_COMMAND,
+			      PCI_COMMAND_INTX_DISABLE);
+
+	/* Wait for Transaction Pending bit clean */
+	msleep(100);
+	pcie_capability_read_word(oct->pci_dev, PCI_EXP_DEVSTA, &status);
+	if (status & PCI_EXP_DEVSTA_TRPND) {
+		dev_info(&oct->pci_dev->dev, "Function reset incomplete after 100ms, sleeping for 5 seconds\n");
+		ssleep(5);
+		pcie_capability_read_word(oct->pci_dev, PCI_EXP_DEVSTA,
+					  &status);
+		if (status & PCI_EXP_DEVSTA_TRPND)
+			dev_info(&oct->pci_dev->dev, "Function reset still incomplete after 5s, reset anyway\n");
+	}
+	pcie_capability_set_word(oct->pci_dev, PCI_EXP_DEVCTL,
+				 PCI_EXP_DEVCTL_BCR_FLR);
+	mdelay(100);
+
+	pci_cfg_access_unlock(oct->pci_dev);
+
+	pci_restore_state(oct->pci_dev);
+}
+
+/**
+ *\brief Destroy resources associated with octeon device
+ * @param pdev PCI device structure
+ * @param ent unused
+ */
+static void octeon_destroy_resources(struct octeon_device *oct)
+{
+	struct msix_entry *msix_entries;
+	int i;
+
+	switch (atomic_read(&oct->status)) {
+	case OCT_DEV_RUNNING:
+	case OCT_DEV_CORE_OK:
+		/* No more instructions will be forwarded. */
+		atomic_set(&oct->status, OCT_DEV_IN_RESET);
+
+		oct->app_mode = CVM_DRV_INVALID_APP;
+		dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n",
+			lio_get_state_string(&oct->status));
+
+		schedule_timeout_uninterruptible(HZ / 10);
+
+		/* fallthrough */
+	case OCT_DEV_HOST_OK:
+		/* fallthrough */
+	case OCT_DEV_IO_QUEUES_DONE:
+		if (wait_for_pending_requests(oct))
+			dev_err(&oct->pci_dev->dev, "There were pending requests\n");
+
+		if (lio_wait_for_instr_fetch(oct))
+			dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n");
+
+		/* Disable the input and output queues now. No more packets will
+		 * arrive from Octeon, but we should wait for all packet
+		 * processing to finish.
+		 */
+		oct->fn_list.disable_io_queues(oct);
+
+		if (lio_wait_for_oq_pkts(oct))
+			dev_err(&oct->pci_dev->dev, "OQ had pending packets\n");
+
+	case OCT_DEV_INTR_SET_DONE:
+		/* Disable interrupts  */
+		oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR);
+
+		if (oct->msix_on) {
+			msix_entries = (struct msix_entry *)oct->msix_entries;
+			for (i = 0; i < oct->num_msix_irqs; i++) {
+				irq_set_affinity_hint(msix_entries[i].vector,
+						      NULL);
+				free_irq(msix_entries[i].vector,
+					 &oct->ioq_vector[i]);
+			}
+			pci_disable_msix(oct->pci_dev);
+			kfree(oct->msix_entries);
+			oct->msix_entries = NULL;
+		}
+		/* Soft reset the octeon device before exiting */
+		if (oct->pci_dev->reset_fn)
+			octeon_pci_flr(oct);
+		else
+			cn23xx_vf_ask_pf_to_do_flr(oct);
+
+		/* fallthrough */
+	case OCT_DEV_MSIX_ALLOC_VECTOR_DONE:
+		octeon_free_ioq_vector(oct);
+
+		/* fallthrough */
+	case OCT_DEV_MBOX_SETUP_DONE:
+		oct->fn_list.free_mbox(oct);
+
+		/* fallthrough */
+	case OCT_DEV_IN_RESET:
+	case OCT_DEV_DROQ_INIT_DONE:
+		mdelay(100);
+		for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
+			if (!(oct->io_qmask.oq & BIT_ULL(i)))
+				continue;
+			octeon_delete_droq(oct, i);
+		}
+
+		/* fallthrough */
+	case OCT_DEV_RESP_LIST_INIT_DONE:
+		octeon_delete_response_list(oct);
+
+		/* fallthrough */
+	case OCT_DEV_INSTR_QUEUE_INIT_DONE:
+		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
+			if (!(oct->io_qmask.iq & BIT_ULL(i)))
+				continue;
+			octeon_delete_instr_queue(oct, i);
+		}
+
+		/* fallthrough */
+	case OCT_DEV_SC_BUFF_POOL_INIT_DONE:
+		octeon_free_sc_buffer_pool(oct);
+
+		/* fallthrough */
+	case OCT_DEV_DISPATCH_INIT_DONE:
+		octeon_delete_dispatch_list(oct);
+		cancel_delayed_work_sync(&oct->nic_poll_work.work);
+
+		/* fallthrough */
+	case OCT_DEV_PCI_MAP_DONE:
+		octeon_unmap_pci_barx(oct, 0);
+		octeon_unmap_pci_barx(oct, 1);
+
+		/* fallthrough */
+	case OCT_DEV_PCI_ENABLE_DONE:
+		pci_clear_master(oct->pci_dev);
+		/* Disable the device, releasing the PCI INT */
+		pci_disable_device(oct->pci_dev);
+
+		/* fallthrough */
+	case OCT_DEV_BEGIN_STATE:
+		/* Nothing to be done here either */
+		break;
+	}
+}
+
+/**
+ * \brief Callback for rx ctrl
+ * @param status status of request
+ * @param buf pointer to resp structure
+ */
+static void rx_ctl_callback(struct octeon_device *oct,
+			    u32 status, void *buf)
+{
+	struct octeon_soft_command *sc = (struct octeon_soft_command *)buf;
+	struct liquidio_rx_ctl_context *ctx;
+
+	ctx  = (struct liquidio_rx_ctl_context *)sc->ctxptr;
+
+	oct = lio_get_device(ctx->octeon_id);
+	if (status)
+		dev_err(&oct->pci_dev->dev, "rx ctl instruction failed. Status: %llx\n",
+			CVM_CAST64(status));
+	WRITE_ONCE(ctx->cond, 1);
+
+	/* This barrier is required to be sure that the response has been
+	 * written fully before waking up the handler
+	 */
+	wmb();
+
+	wake_up_interruptible(&ctx->wc);
+}
+
+/**
+ * \brief Send Rx control command
+ * @param lio per-network private data
+ * @param start_stop whether to start or stop
+ */
+static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
+{
+	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
+	int ctx_size = sizeof(struct liquidio_rx_ctl_context);
+	struct liquidio_rx_ctl_context *ctx;
+	struct octeon_soft_command *sc;
+	union octnet_cmd *ncmd;
+	int retval;
+
+	if (oct->props[lio->ifidx].rx_on == start_stop)
+		return;
+
+	sc = (struct octeon_soft_command *)
+		octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
+					  16, ctx_size);
+
+	ncmd = (union octnet_cmd *)sc->virtdptr;
+	ctx  = (struct liquidio_rx_ctl_context *)sc->ctxptr;
+
+	WRITE_ONCE(ctx->cond, 0);
+	ctx->octeon_id = lio_get_device_id(oct);
+	init_waitqueue_head(&ctx->wc);
+
+	ncmd->u64 = 0;
+	ncmd->s.cmd = OCTNET_CMD_RX_CTL;
+	ncmd->s.param1 = start_stop;
+
+	octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
+
+	sc->iq_no = lio->linfo.txpciq[0].s.q_no;
+
+	octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
+				    OPCODE_NIC_CMD, 0, 0, 0);
+
+	sc->callback = rx_ctl_callback;
+	sc->callback_arg = sc;
+	sc->wait_time = 5000;
+
+	retval = octeon_send_soft_command(oct, sc);
+	if (retval == IQ_SEND_FAILED) {
+		netif_info(lio, rx_err, lio->netdev, "Failed to send RX Control message\n");
+	} else {
+		/* Sleep on a wait queue till the cond flag indicates that the
+		 * response arrived or timed-out.
+		 */
+		if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR)
+			return;
+		oct->props[lio->ifidx].rx_on = start_stop;
+	}
+
+	octeon_free_soft_command(oct, sc);
+}
+
+/**
+ * \brief Destroy NIC device interface
+ * @param oct octeon device
+ * @param ifidx which interface to destroy
+ *
+ * Cleanup associated with each interface for an Octeon device  when NIC
+ * module is being unloaded or if initialization fails during load.
+ */
+static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx)
+{
+	struct net_device *netdev = oct->props[ifidx].netdev;
+	struct napi_struct *napi, *n;
+	struct lio *lio;
+
+	if (!netdev) {
+		dev_err(&oct->pci_dev->dev, "%s No netdevice ptr for index %d\n",
+			__func__, ifidx);
+		return;
+	}
+
+	lio = GET_LIO(netdev);
+
+	dev_dbg(&oct->pci_dev->dev, "NIC device cleanup\n");
+
+	if (atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING)
+		liquidio_stop(netdev);
+
+	if (oct->props[lio->ifidx].napi_enabled == 1) {
+		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+			napi_disable(napi);
+
+		oct->props[lio->ifidx].napi_enabled = 0;
+
+		oct->droq[0]->ops.poll_mode = 0;
+	}
+
+	if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED)
+		unregister_netdev(netdev);
+
+	cleanup_link_status_change_wq(netdev);
+
+	delete_glists(lio);
+
+	free_netdev(netdev);
+
+	oct->props[ifidx].gmxport = -1;
+
+	oct->props[ifidx].netdev = NULL;
+}
+
+/**
+ * \brief Stop complete NIC functionality
+ * @param oct octeon device
+ */
+static int liquidio_stop_nic_module(struct octeon_device *oct)
+{
+	struct lio *lio;
+	int i, j;
+
+	dev_dbg(&oct->pci_dev->dev, "Stopping network interfaces\n");
+	if (!oct->ifcount) {
+		dev_err(&oct->pci_dev->dev, "Init for Octeon was not completed\n");
+		return 1;
+	}
+
+	spin_lock_bh(&oct->cmd_resp_wqlock);
+	oct->cmd_resp_state = OCT_DRV_OFFLINE;
+	spin_unlock_bh(&oct->cmd_resp_wqlock);
+
+	for (i = 0; i < oct->ifcount; i++) {
+		lio = GET_LIO(oct->props[i].netdev);
+		for (j = 0; j < lio->linfo.num_rxpciq; j++)
+			octeon_unregister_droq_ops(oct,
+						   lio->linfo.rxpciq[j].s.q_no);
+	}
+
+	for (i = 0; i < oct->ifcount; i++)
+		liquidio_destroy_nic_device(oct, i);
+
+	dev_dbg(&oct->pci_dev->dev, "Network interfaces stopped\n");
+	return 0;
+}
+
+/**
+ * \brief Cleans up resources at unload time
+ * @param pdev PCI device structure
+ */
+static void liquidio_vf_remove(struct pci_dev *pdev)
+{
+	struct octeon_device *oct_dev = pci_get_drvdata(pdev);
+
+	dev_dbg(&oct_dev->pci_dev->dev, "Stopping device\n");
+
+	if (oct_dev->app_mode == CVM_DRV_NIC_APP)
+		liquidio_stop_nic_module(oct_dev);
+
+	/* Reset the octeon device and cleanup all memory allocated for
+	 * the octeon device by driver.
+	 */
+	octeon_destroy_resources(oct_dev);
+
+	dev_info(&oct_dev->pci_dev->dev, "Device removed\n");
+
+	/* This octeon device has been removed. Update the global
+	 * data structure to reflect this. Free the device structure.
+	 */
+	octeon_free_device_mem(oct_dev);
+}
+
+/**
+ * \brief PCI initialization for each Octeon device.
+ * @param oct octeon device
+ */
+static int octeon_pci_os_setup(struct octeon_device *oct)
+{
+#ifdef CONFIG_PCI_IOV
+	/* setup PCI stuff first */
+	if (!oct->pci_dev->physfn)
+		octeon_pci_flr(oct);
+#endif
+
+	if (pci_enable_device(oct->pci_dev)) {
+		dev_err(&oct->pci_dev->dev, "pci_enable_device failed\n");
+		return 1;
+	}
+
+	if (dma_set_mask_and_coherent(&oct->pci_dev->dev, DMA_BIT_MASK(64))) {
+		dev_err(&oct->pci_dev->dev, "Unexpected DMA device capability\n");
+		pci_disable_device(oct->pci_dev);
+		return 1;
+	}
+
+	/* Enable PCI DMA Master. */
+	pci_set_master(oct->pci_dev);
+
+	return 0;
+}
+
+static int skb_iq(struct lio *lio, struct sk_buff *skb)
+{
+	int q = 0;
+
+	if (netif_is_multiqueue(lio->netdev))
+		q = skb->queue_mapping % lio->linfo.num_txpciq;
+
+	return q;
+}
+
+/**
+ * \brief Check Tx queue state for a given network buffer
+ * @param lio per-network private data
+ * @param skb network buffer
+ */
+static int check_txq_state(struct lio *lio, struct sk_buff *skb)
+{
+	int q = 0, iq = 0;
+
+	if (netif_is_multiqueue(lio->netdev)) {
+		q = skb->queue_mapping;
+		iq = lio->linfo.txpciq[(q % (lio->linfo.num_txpciq))].s.q_no;
+	} else {
+		iq = lio->txq;
+		q = iq;
+	}
+
+	if (octnet_iq_is_full(lio->oct_dev, iq))
+		return 0;
+
+	if (__netif_subqueue_stopped(lio->netdev, q)) {
+		INCR_INSTRQUEUE_PKT_COUNT(lio->oct_dev, iq, tx_restart, 1);
+		wake_q(lio->netdev, q);
+	}
+
+	return 1;
+}
+
+/**
+ * \brief Unmap and free network buffer
+ * @param buf buffer
+ */
+static void free_netbuf(void *buf)
+{
+	struct octnet_buf_free_info *finfo;
+	struct sk_buff *skb;
+	struct lio *lio;
+
+	finfo = (struct octnet_buf_free_info *)buf;
+	skb = finfo->skb;
+	lio = finfo->lio;
+
+	dma_unmap_single(&lio->oct_dev->pci_dev->dev, finfo->dptr, skb->len,
+			 DMA_TO_DEVICE);
+
+	check_txq_state(lio, skb);
+
+	tx_buffer_free(skb);
+}
+
+/**
+ * \brief Unmap and free gather buffer
+ * @param buf buffer
+ */
+static void free_netsgbuf(void *buf)
+{
+	struct octnet_buf_free_info *finfo;
+	struct octnic_gather *g;
+	struct sk_buff *skb;
+	int i, frags, iq;
+	struct lio *lio;
+
+	finfo = (struct octnet_buf_free_info *)buf;
+	skb = finfo->skb;
+	lio = finfo->lio;
+	g = finfo->g;
+	frags = skb_shinfo(skb)->nr_frags;
+
+	dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+			 g->sg[0].ptr[0], (skb->len - skb->data_len),
+			 DMA_TO_DEVICE);
+
+	i = 1;
+	while (frags--) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
+
+		pci_unmap_page((lio->oct_dev)->pci_dev,
+			       g->sg[(i >> 2)].ptr[(i & 3)],
+			       frag->size, DMA_TO_DEVICE);
+		i++;
+	}
+
+	dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+			 finfo->dptr, g->sg_size,
+			 DMA_TO_DEVICE);
+
+	iq = skb_iq(lio, skb);
+
+	spin_lock(&lio->glist_lock[iq]);
+	list_add_tail(&g->list, &lio->glist[iq]);
+	spin_unlock(&lio->glist_lock[iq]);
+
+	check_txq_state(lio, skb); /* mq support: sub-queue state check */
+
+	tx_buffer_free(skb);
+}
+
+/**
+ * \brief Unmap and free gather buffer with response
+ * @param buf buffer
+ */
+static void free_netsgbuf_with_resp(void *buf)
+{
+	struct octnet_buf_free_info *finfo;
+	struct octeon_soft_command *sc;
+	struct octnic_gather *g;
+	struct sk_buff *skb;
+	int i, frags, iq;
+	struct lio *lio;
+
+	sc = (struct octeon_soft_command *)buf;
+	skb = (struct sk_buff *)sc->callback_arg;
+	finfo = (struct octnet_buf_free_info *)&skb->cb;
+
+	lio = finfo->lio;
+	g = finfo->g;
+	frags = skb_shinfo(skb)->nr_frags;
+
+	dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+			 g->sg[0].ptr[0], (skb->len - skb->data_len),
+			 DMA_TO_DEVICE);
+
+	i = 1;
+	while (frags--) {
+		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1];
+
+		pci_unmap_page((lio->oct_dev)->pci_dev,
+			       g->sg[(i >> 2)].ptr[(i & 3)],
+			       frag->size, DMA_TO_DEVICE);
+		i++;
+	}
+
+	dma_unmap_single(&lio->oct_dev->pci_dev->dev,
+			 finfo->dptr, g->sg_size,
+			 DMA_TO_DEVICE);
+
+	iq = skb_iq(lio, skb);
+
+	spin_lock(&lio->glist_lock[iq]);
+	list_add_tail(&g->list, &lio->glist[iq]);
+	spin_unlock(&lio->glist_lock[iq]);
+
+	/* Don't free the skb yet */
+
+	check_txq_state(lio, skb);
+}
+
+/**
+ * \brief Setup output queue
+ * @param oct octeon device
+ * @param q_no which queue
+ * @param num_descs how many descriptors
+ * @param desc_size size of each descriptor
+ * @param app_ctx application context
+ */
+static int octeon_setup_droq(struct octeon_device *oct, int q_no, int num_descs,
+			     int desc_size, void *app_ctx)
+{
+	int ret_val;
+
+	dev_dbg(&oct->pci_dev->dev, "Creating Droq: %d\n", q_no);
+	/* droq creation and local register settings. */
+	ret_val = octeon_create_droq(oct, q_no, num_descs, desc_size, app_ctx);
+	if (ret_val < 0)
+		return ret_val;
+
+	if (ret_val == 1) {
+		dev_dbg(&oct->pci_dev->dev, "Using default droq %d\n", q_no);
+		return 0;
+	}
+
+	/* Enable the droq queues */
+	octeon_set_droq_pkt_op(oct, q_no, 1);
+
+	/* Send Credit for Octeon Output queues. Credits are always
+	 * sent after the output queue is enabled.
+	 */
+	writel(oct->droq[q_no]->max_count, oct->droq[q_no]->pkts_credit_reg);
+
+	return ret_val;
+}
+
+/**
+ * \brief Callback for getting interface configuration
+ * @param status status of request
+ * @param buf pointer to resp structure
+ */
+static void if_cfg_callback(struct octeon_device *oct,
+			    u32 status __attribute__((unused)), void *buf)
+{
+	struct octeon_soft_command *sc = (struct octeon_soft_command *)buf;
+	struct liquidio_if_cfg_context *ctx;
+	struct liquidio_if_cfg_resp *resp;
+
+	resp = (struct liquidio_if_cfg_resp *)sc->virtrptr;
+	ctx = (struct liquidio_if_cfg_context *)sc->ctxptr;
+
+	oct = lio_get_device(ctx->octeon_id);
+	if (resp->status)
+		dev_err(&oct->pci_dev->dev, "nic if cfg instruction failed. Status: %llx\n",
+			CVM_CAST64(resp->status));
+	WRITE_ONCE(ctx->cond, 1);
+
+	snprintf(oct->fw_info.liquidio_firmware_version, 32, "%s",
+		 resp->cfg_info.liquidio_firmware_version);
+
+	/* This barrier is required to be sure that the response has been
+	 * written fully before waking up the handler
+	 */
+	wmb();
+
+	wake_up_interruptible(&ctx->wc);
+}
+
+/**
+ * \brief Select queue based on hash
+ * @param dev Net device
+ * @param skb sk_buff structure
+ * @returns selected queue number
+ */
+static u16 select_q(struct net_device *dev, struct sk_buff *skb,
+		    void *accel_priv __attribute__((unused)),
+		    select_queue_fallback_t fallback __attribute__((unused)))
+{
+	struct lio *lio;
+	u32 qindex;
+
+	lio = GET_LIO(dev);
+
+	qindex = skb_tx_hash(dev, skb);
+
+	return (u16)(qindex % (lio->linfo.num_txpciq));
+}
+
+/** Routine to push packets arriving on Octeon interface upto network layer.
+ * @param oct_id   - octeon device id.
+ * @param skbuff   - skbuff struct to be passed to network layer.
+ * @param len      - size of total data received.
+ * @param rh       - Control header associated with the packet
+ * @param param    - additional control data with the packet
+ * @param arg      - farg registered in droq_ops
+ */
+static void
+liquidio_push_packet(u32 octeon_id __attribute__((unused)),
+		     void *skbuff,
+		     u32 len,
+		     union octeon_rh *rh,
+		     void *param,
+		     void *arg)
+{
+	struct napi_struct *napi = param;
+	struct octeon_droq *droq =
+		container_of(param, struct octeon_droq, napi);
+	struct net_device *netdev = (struct net_device *)arg;
+	struct sk_buff *skb = (struct sk_buff *)skbuff;
+	u16 vtag = 0;
+
+	if (netdev) {
+		struct lio *lio = GET_LIO(netdev);
+		int packet_was_received;
+
+		/* Do not proceed if the interface is not in RUNNING state. */
+		if (!ifstate_check(lio, LIO_IFSTATE_RUNNING)) {
+			recv_buffer_free(skb);
+			droq->stats.rx_dropped++;
+			return;
+		}
+
+		skb->dev = netdev;
+
+		skb_record_rx_queue(skb, droq->q_no);
+		if (likely(len > MIN_SKB_SIZE)) {
+			struct octeon_skb_page_info *pg_info;
+			unsigned char *va;
+
+			pg_info = ((struct octeon_skb_page_info *)(skb->cb));
+			if (pg_info->page) {
+				/* For Paged allocation use the frags */
+				va = page_address(pg_info->page) +
+					pg_info->page_offset;
+				memcpy(skb->data, va, MIN_SKB_SIZE);
+				skb_put(skb, MIN_SKB_SIZE);
+				skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+						pg_info->page,
+						pg_info->page_offset +
+						MIN_SKB_SIZE,
+						len - MIN_SKB_SIZE,
+						LIO_RXBUFFER_SZ);
+			}
+		} else {
+			struct octeon_skb_page_info *pg_info =
+				((struct octeon_skb_page_info *)(skb->cb));
+			skb_copy_to_linear_data(skb,
+						page_address(pg_info->page) +
+						pg_info->page_offset, len);
+			skb_put(skb, len);
+			put_page(pg_info->page);
+		}
+
+		skb_pull(skb, rh->r_dh.len * 8);
+		skb->protocol = eth_type_trans(skb, skb->dev);
+
+		if ((netdev->features & NETIF_F_RXCSUM) &&
+		    (((rh->r_dh.encap_on) &&
+		      (rh->r_dh.csum_verified & CNNIC_TUN_CSUM_VERIFIED)) ||
+		     (!(rh->r_dh.encap_on) &&
+		      (rh->r_dh.csum_verified & CNNIC_CSUM_VERIFIED))))
+			/* checksum has already been verified */
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+		else
+			skb->ip_summed = CHECKSUM_NONE;
+
+		/* Setting Encapsulation field on basis of status received
+		 * from the firmware
+		 */
+		if (rh->r_dh.encap_on) {
+			skb->encapsulation = 1;
+			skb->csum_level = 1;
+			droq->stats.rx_vxlan++;
+		}
+
+		/* inbound VLAN tag */
+		if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
+		    rh->r_dh.vlan) {
+			u16 priority = rh->r_dh.priority;
+			u16 vid = rh->r_dh.vlan;
+
+			vtag = (priority << VLAN_PRIO_SHIFT) | vid;
+			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vtag);
+		}
+
+		packet_was_received = (napi_gro_receive(napi, skb) != GRO_DROP);
+
+		if (packet_was_received) {
+			droq->stats.rx_bytes_received += len;
+			droq->stats.rx_pkts_received++;
+			netdev->last_rx = jiffies;
+		} else {
+			droq->stats.rx_dropped++;
+			netif_info(lio, rx_err, lio->netdev,
+				   "droq:%d  error rx_dropped:%llu\n",
+				   droq->q_no, droq->stats.rx_dropped);
+		}
+
+	} else {
+		recv_buffer_free(skb);
+	}
+}
+
+/**
+ * \brief callback when receive interrupt occurs and we are in NAPI mode
+ * @param arg pointer to octeon output queue
+ */
+static void liquidio_vf_napi_drv_callback(void *arg)
+{
+	struct octeon_droq *droq = arg;
+
+	napi_schedule_irqoff(&droq->napi);
+}
+
+/**
+ * \brief Entry point for NAPI polling
+ * @param napi NAPI structure
+ * @param budget maximum number of items to process
+ */
+static int liquidio_napi_poll(struct napi_struct *napi, int budget)
+{
+	struct octeon_instr_queue *iq;
+	struct octeon_device *oct;
+	struct octeon_droq *droq;
+	int tx_done = 0, iq_no;
+	int work_done;
+
+	droq = container_of(napi, struct octeon_droq, napi);
+	oct = droq->oct_dev;
+	iq_no = droq->q_no;
+
+	/* Handle Droq descriptors */
+	work_done = octeon_process_droq_poll_cmd(oct, droq->q_no,
+						 POLL_EVENT_PROCESS_PKTS,
+						 budget);
+
+	/* Flush the instruction queue */
+	iq = oct->instr_queue[iq_no];
+	if (iq) {
+		/* Process iq buffers with in the budget limits */
+		tx_done = octeon_flush_iq(oct, iq, 1, budget);
+		/* Update iq read-index rather than waiting for next interrupt.
+		 * Return back if tx_done is false.
+		 */
+		update_txq_status(oct, iq_no);
+	} else {
+		dev_err(&oct->pci_dev->dev, "%s: iq (%d) num invalid\n",
+			__func__, iq_no);
+	}
+
+	if ((work_done < budget) && (tx_done)) {
+		napi_complete(napi);
+		octeon_process_droq_poll_cmd(droq->oct_dev, droq->q_no,
+					     POLL_EVENT_ENABLE_INTR, 0);
+		return 0;
+	}
+
+	return (!tx_done) ? (budget) : (work_done);
+}
+
+/**
+ * \brief Setup input and output queues
+ * @param octeon_dev octeon device
+ * @param ifidx Interface index
+ *
+ * Note: Queues are with respect to the octeon device. Thus
+ * an input queue is for egress packets, and output queues
+ * are for ingress packets.
+ */
+static int setup_io_queues(struct octeon_device *octeon_dev, int ifidx)
+{
+	struct octeon_droq_ops droq_ops;
+	struct net_device *netdev;
+	static int cpu_id_modulus;
+	struct octeon_droq *droq;
+	struct napi_struct *napi;
+	static int cpu_id;
+	int num_tx_descs;
+	struct lio *lio;
+	int retval = 0;
+	int q, q_no;
+
+	netdev = octeon_dev->props[ifidx].netdev;
+
+	lio = GET_LIO(netdev);
+
+	memset(&droq_ops, 0, sizeof(struct octeon_droq_ops));
+
+	droq_ops.fptr = liquidio_push_packet;
+	droq_ops.farg = netdev;
+
+	droq_ops.poll_mode = 1;
+	droq_ops.napi_fn = liquidio_vf_napi_drv_callback;
+	cpu_id = 0;
+	cpu_id_modulus = num_present_cpus();
+
+	/* set up DROQs. */
+	for (q = 0; q < lio->linfo.num_rxpciq; q++) {
+		q_no = lio->linfo.rxpciq[q].s.q_no;
+
+		retval = octeon_setup_droq(
+		    octeon_dev, q_no,
+		    CFG_GET_NUM_RX_DESCS_NIC_IF(octeon_get_conf(octeon_dev),
+						lio->ifidx),
+		    CFG_GET_NUM_RX_BUF_SIZE_NIC_IF(octeon_get_conf(octeon_dev),
+						   lio->ifidx),
+		    NULL);
+		if (retval) {
+			dev_err(&octeon_dev->pci_dev->dev,
+				"%s : Runtime DROQ(RxQ) creation failed.\n",
+				__func__);
+			return 1;
+		}
+
+		droq = octeon_dev->droq[q_no];
+		napi = &droq->napi;
+		netif_napi_add(netdev, napi, liquidio_napi_poll, 64);
+
+		/* designate a CPU for this droq */
+		droq->cpu_id = cpu_id;
+		cpu_id++;
+		if (cpu_id >= cpu_id_modulus)
+			cpu_id = 0;
+
+		octeon_register_droq_ops(octeon_dev, q_no, &droq_ops);
+	}
+
+	/* 23XX VF can send/recv control messages (via the first VF-owned
+	 * droq) from the firmware even if the ethX interface is down,
+	 * so that's why poll_mode must be off for the first droq.
+	 */
+	octeon_dev->droq[0]->ops.poll_mode = 0;
+
+	/* set up IQs. */
+	for (q = 0; q < lio->linfo.num_txpciq; q++) {
+		num_tx_descs = CFG_GET_NUM_TX_DESCS_NIC_IF(
+		    octeon_get_conf(octeon_dev), lio->ifidx);
+		retval = octeon_setup_iq(octeon_dev, ifidx, q,
+					 lio->linfo.txpciq[q], num_tx_descs,
+					 netdev_get_tx_queue(netdev, q));
+		if (retval) {
+			dev_err(&octeon_dev->pci_dev->dev,
+				" %s : Runtime IQ(TxQ) creation failed.\n",
+				__func__);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * \brief Net device open for LiquidIO
+ * @param netdev network device
+ */
+static int liquidio_open(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct napi_struct *napi, *n;
+
+	if (!oct->props[lio->ifidx].napi_enabled) {
+		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+			napi_enable(napi);
+
+		oct->props[lio->ifidx].napi_enabled = 1;
+
+		oct->droq[0]->ops.poll_mode = 1;
+	}
+
+	ifstate_set(lio, LIO_IFSTATE_RUNNING);
+
+	/* Ready for link status updates */
+	lio->intf_open = 1;
+
+	netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n");
+	start_txq(netdev);
+
+	/* tell Octeon to start forwarding packets to host */
+	send_rx_ctrl_cmd(lio, 1);
+
+	dev_info(&oct->pci_dev->dev, "%s interface is opened\n", netdev->name);
+
+	return 0;
+}
+
+/**
+ * \brief Net device stop for LiquidIO
+ * @param netdev network device
+ */
+static int liquidio_stop(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+
+	netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n");
+	/* Inform that netif carrier is down */
+	lio->intf_open = 0;
+	lio->linfo.link.s.link_up = 0;
+
+	netif_carrier_off(netdev);
+	lio->link_changes++;
+
+	/* tell Octeon to stop forwarding packets to host */
+	send_rx_ctrl_cmd(lio, 0);
+
+	ifstate_reset(lio, LIO_IFSTATE_RUNNING);
+
+	txqs_stop(netdev);
+
+	dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
+
+	return 0;
+}
+
+/**
+ * \brief Converts a mask based on net device flags
+ * @param netdev network device
+ *
+ * This routine generates a octnet_ifflags mask from the net device flags
+ * received from the OS.
+ */
+static enum octnet_ifflags get_new_flags(struct net_device *netdev)
+{
+	enum octnet_ifflags f = OCTNET_IFFLAG_UNICAST;
+
+	if (netdev->flags & IFF_PROMISC)
+		f |= OCTNET_IFFLAG_PROMISC;
+
+	if (netdev->flags & IFF_ALLMULTI)
+		f |= OCTNET_IFFLAG_ALLMULTI;
+
+	if (netdev->flags & IFF_MULTICAST) {
+		f |= OCTNET_IFFLAG_MULTICAST;
+
+		/* Accept all multicast addresses if there are more than we
+		 * can handle
+		 */
+		if (netdev_mc_count(netdev) > MAX_OCTEON_MULTICAST_ADDR)
+			f |= OCTNET_IFFLAG_ALLMULTI;
+	}
+
+	if (netdev->flags & IFF_BROADCAST)
+		f |= OCTNET_IFFLAG_BROADCAST;
+
+	return f;
+}
+
+static void liquidio_set_uc_list(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	struct netdev_hw_addr *ha;
+	u64 *mac;
+
+	if (lio->netdev_uc_count == netdev_uc_count(netdev))
+		return;
+
+	if (netdev_uc_count(netdev) > MAX_NCTRL_UDD) {
+		dev_err(&oct->pci_dev->dev, "too many MAC addresses in netdev uc list\n");
+		return;
+	}
+
+	lio->netdev_uc_count = netdev_uc_count(netdev);
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_UC_LIST;
+	nctrl.ncmd.s.more = lio->netdev_uc_count;
+	nctrl.ncmd.s.param1 = oct->vf_num;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.netpndev = (u64)netdev;
+	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+	/* copy all the addresses into the udd */
+	mac = &nctrl.udd[0];
+	netdev_for_each_uc_addr(ha, netdev) {
+		ether_addr_copy(((u8 *)mac) + 2, ha->addr);
+		mac++;
+	}
+
+	octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+}
+
+/**
+ * \brief Net device set_multicast_list
+ * @param netdev network device
+ */
+static void liquidio_set_mcast_list(struct net_device *netdev)
+{
+	int mc_count = min(netdev_mc_count(netdev), MAX_OCTEON_MULTICAST_ADDR);
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	struct netdev_hw_addr *ha;
+	u64 *mc;
+	int ret;
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+	/* Create a ctrl pkt command to be sent to core app. */
+	nctrl.ncmd.u64 = 0;
+	nctrl.ncmd.s.cmd = OCTNET_CMD_SET_MULTI_LIST;
+	nctrl.ncmd.s.param1 = get_new_flags(netdev);
+	nctrl.ncmd.s.param2 = mc_count;
+	nctrl.ncmd.s.more = mc_count;
+	nctrl.netpndev = (u64)netdev;
+	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+	/* copy all the addresses into the udd */
+	mc = &nctrl.udd[0];
+	netdev_for_each_mc_addr(ha, netdev) {
+		*mc = 0;
+		ether_addr_copy(((u8 *)mc) + 2, ha->addr);
+		/* no need to swap bytes */
+		if (++mc > &nctrl.udd[mc_count])
+			break;
+	}
+
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+
+	/* Apparently, any activity in this call from the kernel has to
+	 * be atomic. So we won't wait for response.
+	 */
+	nctrl.wait_time = 0;
+
+	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+	if (ret < 0) {
+		dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n",
+			ret);
+	}
+
+	liquidio_set_uc_list(netdev);
+}
+
+/**
+ * \brief Net device set_mac_address
+ * @param netdev network device
+ */
+static int liquidio_set_mac(struct net_device *netdev, void *p)
+{
+	struct sockaddr *addr = (struct sockaddr *)p;
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	int ret = 0;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
+		return 0;
+
+	if (lio->linfo.macaddr_is_admin_asgnd)
+		return -EPERM;
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+	nctrl.ncmd.u64 = 0;
+	nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
+	nctrl.ncmd.s.param1 = 0;
+	nctrl.ncmd.s.more = 1;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.netpndev = (u64)netdev;
+	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+	nctrl.wait_time = 100;
+
+	nctrl.udd[0] = 0;
+	/* The MAC Address is presented in network byte order. */
+	ether_addr_copy((u8 *)&nctrl.udd[0] + 2, addr->sa_data);
+
+	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+	if (ret < 0) {
+		dev_err(&oct->pci_dev->dev, "MAC Address change failed\n");
+		return -ENOMEM;
+	}
+	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
+	ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data);
+
+	return 0;
+}
+
+/**
+ * \brief Net device get_stats
+ * @param netdev network device
+ */
+static struct net_device_stats *liquidio_get_stats(struct net_device *netdev)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct net_device_stats *stats = &netdev->stats;
+	u64 pkts = 0, drop = 0, bytes = 0;
+	struct oct_droq_stats *oq_stats;
+	struct oct_iq_stats *iq_stats;
+	struct octeon_device *oct;
+	int i, iq_no, oq_no;
+
+	oct = lio->oct_dev;
+
+	for (i = 0; i < lio->linfo.num_txpciq; i++) {
+		iq_no = lio->linfo.txpciq[i].s.q_no;
+		iq_stats = &oct->instr_queue[iq_no]->stats;
+		pkts += iq_stats->tx_done;
+		drop += iq_stats->tx_dropped;
+		bytes += iq_stats->tx_tot_bytes;
+	}
+
+	stats->tx_packets = pkts;
+	stats->tx_bytes = bytes;
+	stats->tx_dropped = drop;
+
+	pkts = 0;
+	drop = 0;
+	bytes = 0;
+
+	for (i = 0; i < lio->linfo.num_rxpciq; i++) {
+		oq_no = lio->linfo.rxpciq[i].s.q_no;
+		oq_stats = &oct->droq[oq_no]->stats;
+		pkts += oq_stats->rx_pkts_received;
+		drop += (oq_stats->rx_dropped +
+			 oq_stats->dropped_nodispatch +
+			 oq_stats->dropped_toomany +
+			 oq_stats->dropped_nomem);
+		bytes += oq_stats->rx_bytes_received;
+	}
+
+	stats->rx_bytes = bytes;
+	stats->rx_packets = pkts;
+	stats->rx_dropped = drop;
+
+	return stats;
+}
+
+/**
+ * \brief Net device change_mtu
+ * @param netdev network device
+ */
+static int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+
+	lio->mtu = new_mtu;
+
+	netif_info(lio, probe, lio->netdev, "MTU Changed from %d to %d\n",
+		   netdev->mtu, new_mtu);
+	dev_info(&oct->pci_dev->dev, "%s MTU Changed from %d to %d\n",
+		 netdev->name, netdev->mtu, new_mtu);
+
+	netdev->mtu = new_mtu;
+
+	return 0;
+}
+
+/**
+ * \brief Handler for SIOCSHWTSTAMP ioctl
+ * @param netdev network device
+ * @param ifr interface request
+ * @param cmd command
+ */
+static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct hwtstamp_config conf;
+
+	if (copy_from_user(&conf, ifr->ifr_data, sizeof(conf)))
+		return -EFAULT;
+
+	if (conf.flags)
+		return -EINVAL;
+
+	switch (conf.tx_type) {
+	case HWTSTAMP_TX_ON:
+	case HWTSTAMP_TX_OFF:
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (conf.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+		conf.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (conf.rx_filter == HWTSTAMP_FILTER_ALL)
+		ifstate_set(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED);
+
+	else
+		ifstate_reset(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED);
+
+	return copy_to_user(ifr->ifr_data, &conf, sizeof(conf)) ? -EFAULT : 0;
+}
+
+/**
+ * \brief ioctl handler
+ * @param netdev network device
+ * @param ifr interface request
+ * @param cmd command
+ */
+static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCSHWTSTAMP:
+		return hwtstamp_ioctl(netdev, ifr);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void handle_timestamp(struct octeon_device *oct, u32 status, void *buf)
+{
+	struct sk_buff *skb = (struct sk_buff *)buf;
+	struct octnet_buf_free_info *finfo;
+	struct oct_timestamp_resp *resp;
+	struct octeon_soft_command *sc;
+	struct lio *lio;
+
+	finfo = (struct octnet_buf_free_info *)skb->cb;
+	lio = finfo->lio;
+	sc = finfo->sc;
+	oct = lio->oct_dev;
+	resp = (struct oct_timestamp_resp *)sc->virtrptr;
+
+	if (status != OCTEON_REQUEST_DONE) {
+		dev_err(&oct->pci_dev->dev, "Tx timestamp instruction failed. Status: %llx\n",
+			CVM_CAST64(status));
+		resp->timestamp = 0;
+	}
+
+	octeon_swap_8B_data(&resp->timestamp, 1);
+
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+		struct skb_shared_hwtstamps ts;
+		u64 ns = resp->timestamp;
+
+		netif_info(lio, tx_done, lio->netdev,
+			   "Got resulting SKBTX_HW_TSTAMP skb=%p ns=%016llu\n",
+			   skb, (unsigned long long)ns);
+		ts.hwtstamp = ns_to_ktime(ns + lio->ptp_adjust);
+		skb_tstamp_tx(skb, &ts);
+	}
+
+	octeon_free_soft_command(oct, sc);
+	tx_buffer_free(skb);
+}
+
+/* \brief Send a data packet that will be timestamped
+ * @param oct octeon device
+ * @param ndata pointer to network data
+ * @param finfo pointer to private network data
+ */
+static int send_nic_timestamp_pkt(struct octeon_device *oct,
+				  struct octnic_data_pkt *ndata,
+				  struct octnet_buf_free_info *finfo)
+{
+	struct octeon_soft_command *sc;
+	int ring_doorbell;
+	struct lio *lio;
+	int retval;
+	u32 len;
+
+	lio = finfo->lio;
+
+	sc = octeon_alloc_soft_command_resp(oct, &ndata->cmd,
+					    sizeof(struct oct_timestamp_resp));
+	finfo->sc = sc;
+
+	if (!sc) {
+		dev_err(&oct->pci_dev->dev, "No memory for timestamped data packet\n");
+		return IQ_SEND_FAILED;
+	}
+
+	if (ndata->reqtype == REQTYPE_NORESP_NET)
+		ndata->reqtype = REQTYPE_RESP_NET;
+	else if (ndata->reqtype == REQTYPE_NORESP_NET_SG)
+		ndata->reqtype = REQTYPE_RESP_NET_SG;
+
+	sc->callback = handle_timestamp;
+	sc->callback_arg = finfo->skb;
+	sc->iq_no = ndata->q_no;
+
+	len = (u32)((struct octeon_instr_ih3 *)(&sc->cmd.cmd3.ih3))->dlengsz;
+
+	ring_doorbell = 1;
+
+	retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd,
+				     sc, len, ndata->reqtype);
+
+	if (retval == IQ_SEND_FAILED) {
+		dev_err(&oct->pci_dev->dev, "timestamp data packet failed status: %x\n",
+			retval);
+		octeon_free_soft_command(oct, sc);
+	} else {
+		netif_info(lio, tx_queued, lio->netdev, "Queued timestamp packet\n");
+	}
+
+	return retval;
+}
+
+/** \brief Transmit networks packets to the Octeon interface
+ * @param skbuff   skbuff struct to be passed to network layer.
+ * @param netdev   pointer to network device
+ * @returns whether the packet was transmitted to the device okay or not
+ *             (NETDEV_TX_OK or NETDEV_TX_BUSY)
+ */
+static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct octnet_buf_free_info *finfo;
+	union octnic_cmd_setup cmdsetup;
+	struct octnic_data_pkt ndata;
+	struct octeon_instr_irh *irh;
+	struct oct_iq_stats *stats;
+	struct octeon_device *oct;
+	int q_idx = 0, iq_no = 0;
+	union tx_info *tx_info;
+	struct lio *lio;
+	int status = 0;
+	u64 dptr = 0;
+	u32 tag = 0;
+	int j;
+
+	lio = GET_LIO(netdev);
+	oct = lio->oct_dev;
+
+	if (netif_is_multiqueue(netdev)) {
+		q_idx = skb->queue_mapping;
+		q_idx = (q_idx % (lio->linfo.num_txpciq));
+		tag = q_idx;
+		iq_no = lio->linfo.txpciq[q_idx].s.q_no;
+	} else {
+		iq_no = lio->txq;
+	}
+
+	stats = &oct->instr_queue[iq_no]->stats;
+
+	/* Check for all conditions in which the current packet cannot be
+	 * transmitted.
+	 */
+	if (!(atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING) ||
+	    (!lio->linfo.link.s.link_up) || (skb->len <= 0)) {
+		netif_info(lio, tx_err, lio->netdev, "Transmit failed link_status : %d\n",
+			   lio->linfo.link.s.link_up);
+		goto lio_xmit_failed;
+	}
+
+	/* Use space in skb->cb to store info used to unmap and
+	 * free the buffers.
+	 */
+	finfo = (struct octnet_buf_free_info *)skb->cb;
+	finfo->lio = lio;
+	finfo->skb = skb;
+	finfo->sc = NULL;
+
+	/* Prepare the attributes for the data to be passed to OSI. */
+	memset(&ndata, 0, sizeof(struct octnic_data_pkt));
+
+	ndata.buf = finfo;
+
+	ndata.q_no = iq_no;
+
+	if (netif_is_multiqueue(netdev)) {
+		if (octnet_iq_is_full(oct, ndata.q_no)) {
+			/* defer sending if queue is full */
+			netif_info(lio, tx_err, lio->netdev, "Transmit failed iq:%d full\n",
+				   ndata.q_no);
+			stats->tx_iq_busy++;
+			return NETDEV_TX_BUSY;
+		}
+	} else {
+		if (octnet_iq_is_full(oct, lio->txq)) {
+			/* defer sending if queue is full */
+			stats->tx_iq_busy++;
+			netif_info(lio, tx_err, lio->netdev, "Transmit failed iq:%d full\n",
+				   ndata.q_no);
+			return NETDEV_TX_BUSY;
+		}
+	}
+
+	ndata.datasize = skb->len;
+
+	cmdsetup.u64 = 0;
+	cmdsetup.s.iq_no = iq_no;
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+		if (skb->encapsulation) {
+			cmdsetup.s.tnl_csum = 1;
+			stats->tx_vxlan++;
+		} else {
+			cmdsetup.s.transport_csum = 1;
+		}
+	}
+	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+		cmdsetup.s.timestamp = 1;
+	}
+
+	if (!skb_shinfo(skb)->nr_frags) {
+		cmdsetup.s.u.datasize = skb->len;
+		octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
+		/* Offload checksum calculation for TCP/UDP packets */
+		dptr = dma_map_single(&oct->pci_dev->dev,
+				      skb->data,
+				      skb->len,
+				      DMA_TO_DEVICE);
+		if (dma_mapping_error(&oct->pci_dev->dev, dptr)) {
+			dev_err(&oct->pci_dev->dev, "%s DMA mapping error 1\n",
+				__func__);
+			return NETDEV_TX_BUSY;
+		}
+
+		ndata.cmd.cmd3.dptr = dptr;
+		finfo->dptr = dptr;
+		ndata.reqtype = REQTYPE_NORESP_NET;
+
+	} else {
+		struct skb_frag_struct *frag;
+		struct octnic_gather *g;
+		int i, frags;
+
+		spin_lock(&lio->glist_lock[q_idx]);
+		g = (struct octnic_gather *)list_delete_head(
+		    &lio->glist[q_idx]);
+		spin_unlock(&lio->glist_lock[q_idx]);
+
+		if (!g) {
+			netif_info(lio, tx_err, lio->netdev,
+				   "Transmit scatter gather: glist null!\n");
+			goto lio_xmit_failed;
+		}
+
+		cmdsetup.s.gather = 1;
+		cmdsetup.s.u.gatherptrs = (skb_shinfo(skb)->nr_frags + 1);
+		octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag);
+
+		memset(g->sg, 0, g->sg_size);
+
+		g->sg[0].ptr[0] = dma_map_single(&oct->pci_dev->dev,
+						 skb->data,
+						 (skb->len - skb->data_len),
+						 DMA_TO_DEVICE);
+		if (dma_mapping_error(&oct->pci_dev->dev, g->sg[0].ptr[0])) {
+			dev_err(&oct->pci_dev->dev, "%s DMA mapping error 2\n",
+				__func__);
+			return NETDEV_TX_BUSY;
+		}
+		add_sg_size(&g->sg[0], (skb->len - skb->data_len), 0);
+
+		frags = skb_shinfo(skb)->nr_frags;
+		i = 1;
+		while (frags--) {
+			frag = &skb_shinfo(skb)->frags[i - 1];
+
+			g->sg[(i >> 2)].ptr[(i & 3)] =
+				dma_map_page(&oct->pci_dev->dev,
+					     frag->page.p,
+					     frag->page_offset,
+					     frag->size,
+					     DMA_TO_DEVICE);
+			if (dma_mapping_error(&oct->pci_dev->dev,
+					      g->sg[i >> 2].ptr[i & 3])) {
+				dma_unmap_single(&oct->pci_dev->dev,
+						 g->sg[0].ptr[0],
+						 skb->len - skb->data_len,
+						 DMA_TO_DEVICE);
+				for (j = 1; j < i; j++) {
+					frag = &skb_shinfo(skb)->frags[j - 1];
+					dma_unmap_page(&oct->pci_dev->dev,
+						       g->sg[j >> 2].ptr[j & 3],
+						       frag->size,
+						       DMA_TO_DEVICE);
+				}
+				dev_err(&oct->pci_dev->dev, "%s DMA mapping error 3\n",
+					__func__);
+				return NETDEV_TX_BUSY;
+			}
+
+			add_sg_size(&g->sg[(i >> 2)], frag->size, (i & 3));
+			i++;
+		}
+
+		dptr = dma_map_single(&oct->pci_dev->dev,
+				      g->sg, g->sg_size,
+				      DMA_TO_DEVICE);
+		if (dma_mapping_error(&oct->pci_dev->dev, dptr)) {
+			dev_err(&oct->pci_dev->dev, "%s DMA mapping error 4\n",
+				__func__);
+			dma_unmap_single(&oct->pci_dev->dev, g->sg[0].ptr[0],
+					 skb->len - skb->data_len,
+					 DMA_TO_DEVICE);
+			for (j = 1; j <= frags; j++) {
+				frag = &skb_shinfo(skb)->frags[j - 1];
+				dma_unmap_page(&oct->pci_dev->dev,
+					       g->sg[j >> 2].ptr[j & 3],
+					       frag->size, DMA_TO_DEVICE);
+			}
+			return NETDEV_TX_BUSY;
+		}
+
+		ndata.cmd.cmd3.dptr = dptr;
+		finfo->dptr = dptr;
+		finfo->g = g;
+
+		ndata.reqtype = REQTYPE_NORESP_NET_SG;
+	}
+
+	irh = (struct octeon_instr_irh *)&ndata.cmd.cmd3.irh;
+	tx_info = (union tx_info *)&ndata.cmd.cmd3.ossp[0];
+
+	if (skb_shinfo(skb)->gso_size) {
+		tx_info->s.gso_size = skb_shinfo(skb)->gso_size;
+		tx_info->s.gso_segs = skb_shinfo(skb)->gso_segs;
+	}
+
+	/* HW insert VLAN tag */
+	if (skb_vlan_tag_present(skb)) {
+		irh->priority = skb_vlan_tag_get(skb) >> VLAN_PRIO_SHIFT;
+		irh->vlan = skb_vlan_tag_get(skb) & VLAN_VID_MASK;
+	}
+
+	if (unlikely(cmdsetup.s.timestamp))
+		status = send_nic_timestamp_pkt(oct, &ndata, finfo);
+	else
+		status = octnet_send_nic_data_pkt(oct, &ndata);
+	if (status == IQ_SEND_FAILED)
+		goto lio_xmit_failed;
+
+	netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n");
+
+	if (status == IQ_SEND_STOP) {
+		dev_err(&oct->pci_dev->dev, "Rcvd IQ_SEND_STOP signal; stopping IQ-%d\n",
+			iq_no);
+		stop_q(lio->netdev, q_idx);
+	}
+
+	netif_trans_update(netdev);
+
+	if (skb_shinfo(skb)->gso_size)
+		stats->tx_done += skb_shinfo(skb)->gso_segs;
+	else
+		stats->tx_done++;
+	stats->tx_tot_bytes += skb->len;
+
+	return NETDEV_TX_OK;
+
+lio_xmit_failed:
+	stats->tx_dropped++;
+	netif_info(lio, tx_err, lio->netdev, "IQ%d Transmit dropped:%llu\n",
+		   iq_no, stats->tx_dropped);
+	if (dptr)
+		dma_unmap_single(&oct->pci_dev->dev, dptr,
+				 ndata.datasize, DMA_TO_DEVICE);
+	tx_buffer_free(skb);
+	return NETDEV_TX_OK;
+}
+
+/** \brief Network device Tx timeout
+ * @param netdev    pointer to network device
+ */
+static void liquidio_tx_timeout(struct net_device *netdev)
+{
+	struct lio *lio;
+
+	lio = GET_LIO(netdev);
+
+	netif_info(lio, tx_err, lio->netdev,
+		   "Transmit timeout tx_dropped:%ld, waking up queues now!!\n",
+		   netdev->stats.tx_dropped);
+	netif_trans_update(netdev);
+	txqs_wake(netdev);
+}
+
+static int
+liquidio_vlan_rx_add_vid(struct net_device *netdev,
+			 __be16 proto __attribute__((unused)), u16 vid)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	int ret = 0;
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+	nctrl.ncmd.u64 = 0;
+	nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER;
+	nctrl.ncmd.s.param1 = vid;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.wait_time = 100;
+	nctrl.netpndev = (u64)netdev;
+	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+	if (ret < 0) {
+		dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
+			ret);
+	}
+
+	return ret;
+}
+
+static int
+liquidio_vlan_rx_kill_vid(struct net_device *netdev,
+			  __be16 proto __attribute__((unused)), u16 vid)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	int ret = 0;
+
+	memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
+
+	nctrl.ncmd.u64 = 0;
+	nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER;
+	nctrl.ncmd.s.param1 = vid;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.wait_time = 100;
+	nctrl.netpndev = (u64)netdev;
+	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+	if (ret < 0) {
+		dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n",
+			ret);
+	}
+	return ret;
+}
+
+/** Sending command to enable/disable RX checksum offload
+ * @param netdev                pointer to network device
+ * @param command               OCTNET_CMD_TNL_RX_CSUM_CTL
+ * @param rx_cmd_bit            OCTNET_CMD_RXCSUM_ENABLE/
+ *                              OCTNET_CMD_RXCSUM_DISABLE
+ * @returns                     SUCCESS or FAILURE
+ */
+static int liquidio_set_rxcsum_command(struct net_device *netdev, int command,
+				       u8 rx_cmd)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	int ret = 0;
+
+	nctrl.ncmd.u64 = 0;
+	nctrl.ncmd.s.cmd = command;
+	nctrl.ncmd.s.param1 = rx_cmd;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.wait_time = 100;
+	nctrl.netpndev = (u64)netdev;
+	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+	if (ret < 0) {
+		dev_err(&oct->pci_dev->dev, "DEVFLAGS RXCSUM change failed in core (ret:0x%x)\n",
+			ret);
+	}
+	return ret;
+}
+
+/** Sending command to add/delete VxLAN UDP port to firmware
+ * @param netdev                pointer to network device
+ * @param command               OCTNET_CMD_VXLAN_PORT_CONFIG
+ * @param vxlan_port            VxLAN port to be added or deleted
+ * @param vxlan_cmd_bit         OCTNET_CMD_VXLAN_PORT_ADD,
+ *                              OCTNET_CMD_VXLAN_PORT_DEL
+ * @returns                     SUCCESS or FAILURE
+ */
+static int liquidio_vxlan_port_command(struct net_device *netdev, int command,
+				       u16 vxlan_port, u8 vxlan_cmd_bit)
+{
+	struct lio *lio = GET_LIO(netdev);
+	struct octeon_device *oct = lio->oct_dev;
+	struct octnic_ctrl_pkt nctrl;
+	int ret = 0;
+
+	nctrl.ncmd.u64 = 0;
+	nctrl.ncmd.s.cmd = command;
+	nctrl.ncmd.s.more = vxlan_cmd_bit;
+	nctrl.ncmd.s.param1 = vxlan_port;
+	nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
+	nctrl.wait_time = 100;
+	nctrl.netpndev = (u64)netdev;
+	nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
+
+	ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
+	if (ret < 0) {
+		dev_err(&oct->pci_dev->dev,
+			"DEVFLAGS VxLAN port add/delete failed in core (ret : 0x%x)\n",
+			ret);
+	}
+	return ret;
+}
+
+/** \brief Net device fix features
+ * @param netdev  pointer to network device
+ * @param request features requested
+ * @returns updated features list
+ */
+static netdev_features_t liquidio_fix_features(struct net_device *netdev,
+					       netdev_features_t request)
+{
+	struct lio *lio = netdev_priv(netdev);
+
+	if ((request & NETIF_F_RXCSUM) &&
+	    !(lio->dev_capability & NETIF_F_RXCSUM))
+		request &= ~NETIF_F_RXCSUM;
+
+	if ((request & NETIF_F_HW_CSUM) &&
+	    !(lio->dev_capability & NETIF_F_HW_CSUM))
+		request &= ~NETIF_F_HW_CSUM;
+
+	if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO))
+		request &= ~NETIF_F_TSO;
+
+	if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6))
+		request &= ~NETIF_F_TSO6;
+
+	if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO))
+		request &= ~NETIF_F_LRO;
+
+	/* Disable LRO if RXCSUM is off */
+	if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) &&
+	    (lio->dev_capability & NETIF_F_LRO))
+		request &= ~NETIF_F_LRO;
+
+	return request;
+}
+
+/** \brief Net device set features
+ * @param netdev  pointer to network device
+ * @param features features to enable/disable
+ */
+static int liquidio_set_features(struct net_device *netdev,
+				 netdev_features_t features)
+{
+	struct lio *lio = netdev_priv(netdev);
+
+	if (!((netdev->features ^ features) & NETIF_F_LRO))
+		return 0;
+
+	if ((features & NETIF_F_LRO) && (lio->dev_capability & NETIF_F_LRO))
+		liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
+				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
+	else if (!(features & NETIF_F_LRO) &&
+		 (lio->dev_capability & NETIF_F_LRO))
+		liquidio_set_feature(netdev, OCTNET_CMD_LRO_DISABLE,
+				     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
+	if (!(netdev->features & NETIF_F_RXCSUM) &&
+	    (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
+	    (features & NETIF_F_RXCSUM))
+		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
+					    OCTNET_CMD_RXCSUM_ENABLE);
+	else if ((netdev->features & NETIF_F_RXCSUM) &&
+		 (lio->enc_dev_capability & NETIF_F_RXCSUM) &&
+		 !(features & NETIF_F_RXCSUM))
+		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
+					    OCTNET_CMD_RXCSUM_DISABLE);
+
+	return 0;
+}
+
+static void liquidio_add_vxlan_port(struct net_device *netdev,
+				    struct udp_tunnel_info *ti)
+{
+	if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
+		return;
+
+	liquidio_vxlan_port_command(netdev,
+				    OCTNET_CMD_VXLAN_PORT_CONFIG,
+				    htons(ti->port),
+				    OCTNET_CMD_VXLAN_PORT_ADD);
+}
+
+static void liquidio_del_vxlan_port(struct net_device *netdev,
+				    struct udp_tunnel_info *ti)
+{
+	if (ti->type != UDP_TUNNEL_TYPE_VXLAN)
+		return;
+
+	liquidio_vxlan_port_command(netdev,
+				    OCTNET_CMD_VXLAN_PORT_CONFIG,
+				    htons(ti->port),
+				    OCTNET_CMD_VXLAN_PORT_DEL);
+}
+
+static const struct net_device_ops lionetdevops = {
+	.ndo_open		= liquidio_open,
+	.ndo_stop		= liquidio_stop,
+	.ndo_start_xmit		= liquidio_xmit,
+	.ndo_get_stats		= liquidio_get_stats,
+	.ndo_set_mac_address	= liquidio_set_mac,
+	.ndo_set_rx_mode	= liquidio_set_mcast_list,
+	.ndo_tx_timeout		= liquidio_tx_timeout,
+	.ndo_vlan_rx_add_vid    = liquidio_vlan_rx_add_vid,
+	.ndo_vlan_rx_kill_vid   = liquidio_vlan_rx_kill_vid,
+	.ndo_change_mtu		= liquidio_change_mtu,
+	.ndo_do_ioctl		= liquidio_ioctl,
+	.ndo_fix_features	= liquidio_fix_features,
+	.ndo_set_features	= liquidio_set_features,
+	.ndo_udp_tunnel_add     = liquidio_add_vxlan_port,
+	.ndo_udp_tunnel_del     = liquidio_del_vxlan_port,
+	.ndo_select_queue	= select_q,
+};
+
+static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf)
+{
+	struct octeon_device *oct = (struct octeon_device *)buf;
+	struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
+	union oct_link_status *ls;
+	int gmxport = 0;
+	int i;
+
+	if (recv_pkt->buffer_size[0] != sizeof(*ls)) {
+		dev_err(&oct->pci_dev->dev, "Malformed NIC_INFO, len=%d, ifidx=%d\n",
+			recv_pkt->buffer_size[0],
+			recv_pkt->rh.r_nic_info.gmxport);
+		goto nic_info_err;
+	}
+
+	gmxport = recv_pkt->rh.r_nic_info.gmxport;
+	ls = (union oct_link_status *)get_rbd(recv_pkt->buffer_ptr[0]);
+
+	octeon_swap_8B_data((u64 *)ls, (sizeof(union oct_link_status)) >> 3);
+
+	for (i = 0; i < oct->ifcount; i++) {
+		if (oct->props[i].gmxport == gmxport) {
+			update_link_status(oct->props[i].netdev, ls);
+			break;
+		}
+	}
+
+nic_info_err:
+	for (i = 0; i < recv_pkt->buffer_count; i++)
+		recv_buffer_free(recv_pkt->buffer_ptr[i]);
+	octeon_free_recv_info(recv_info);
+	return 0;
+}
+
+/**
+ * \brief Setup network interfaces
+ * @param octeon_dev  octeon device
+ *
+ * Called during init time for each device. It assumes the NIC
+ * is already up and running.  The link information for each
+ * interface is passed in link_info.
+ */
+static int setup_nic_devices(struct octeon_device *octeon_dev)
+{
+	int retval, num_iqueues, num_oqueues;
+	struct liquidio_if_cfg_context *ctx;
+	u32 resp_size, ctx_size, data_size;
+	struct liquidio_if_cfg_resp *resp;
+	struct octeon_soft_command *sc;
+	union oct_nic_if_cfg if_cfg;
+	struct octdev_props *props;
+	struct net_device *netdev;
+	struct lio_version *vdata;
+	struct lio *lio = NULL;
+	u8 mac[ETH_ALEN], i, j;
+	u32 ifidx_or_pfnum;
+
+	ifidx_or_pfnum = octeon_dev->pf_num;
+
+	/* This is to handle link status changes */
+	octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC, OPCODE_NIC_INFO,
+				    lio_nic_info, octeon_dev);
+
+	/* REQTYPE_RESP_NET and REQTYPE_SOFT_COMMAND do not have free functions.
+	 * They are handled directly.
+	 */
+	octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET,
+					free_netbuf);
+
+	octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET_SG,
+					free_netsgbuf);
+
+	octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_RESP_NET_SG,
+					free_netsgbuf_with_resp);
+
+	for (i = 0; i < octeon_dev->ifcount; i++) {
+		resp_size = sizeof(struct liquidio_if_cfg_resp);
+		ctx_size = sizeof(struct liquidio_if_cfg_context);
+		data_size = sizeof(struct lio_version);
+		sc = (struct octeon_soft_command *)
+			octeon_alloc_soft_command(octeon_dev, data_size,
+						  resp_size, ctx_size);
+		resp = (struct liquidio_if_cfg_resp *)sc->virtrptr;
+		ctx  = (struct liquidio_if_cfg_context *)sc->ctxptr;
+		vdata = (struct lio_version *)sc->virtdptr;
+
+		*((u64 *)vdata) = 0;
+		vdata->major = cpu_to_be16(LIQUIDIO_BASE_MAJOR_VERSION);
+		vdata->minor = cpu_to_be16(LIQUIDIO_BASE_MINOR_VERSION);
+		vdata->micro = cpu_to_be16(LIQUIDIO_BASE_MICRO_VERSION);
+
+		WRITE_ONCE(ctx->cond, 0);
+		ctx->octeon_id = lio_get_device_id(octeon_dev);
+		init_waitqueue_head(&ctx->wc);
+
+		if_cfg.u64 = 0;
+
+		if_cfg.s.num_iqueues = octeon_dev->sriov_info.rings_per_vf;
+		if_cfg.s.num_oqueues = octeon_dev->sriov_info.rings_per_vf;
+		if_cfg.s.base_queue = 0;
+
+		sc->iq_no = 0;
+
+		octeon_prepare_soft_command(octeon_dev, sc, OPCODE_NIC,
+					    OPCODE_NIC_IF_CFG, 0, if_cfg.u64,
+					    0);
+
+		sc->callback = if_cfg_callback;
+		sc->callback_arg = sc;
+		sc->wait_time = 5000;
+
+		retval = octeon_send_soft_command(octeon_dev, sc);
+		if (retval == IQ_SEND_FAILED) {
+			dev_err(&octeon_dev->pci_dev->dev,
+				"iq/oq config failed status: %x\n", retval);
+			/* Soft instr is freed by driver in case of failure. */
+			goto setup_nic_dev_fail;
+		}
+
+		/* Sleep on a wait queue till the cond flag indicates that the
+		 * response arrived or timed-out.
+		 */
+		if (sleep_cond(&ctx->wc, &ctx->cond) == -EINTR) {
+			dev_err(&octeon_dev->pci_dev->dev, "Wait interrupted\n");
+			goto setup_nic_wait_intr;
+		}
+
+		retval = resp->status;
+		if (retval) {
+			dev_err(&octeon_dev->pci_dev->dev, "iq/oq config failed\n");
+			goto setup_nic_dev_fail;
+		}
+
+		octeon_swap_8B_data((u64 *)(&resp->cfg_info),
+				    (sizeof(struct liquidio_if_cfg_info)) >> 3);
+
+		num_iqueues = hweight64(resp->cfg_info.iqmask);
+		num_oqueues = hweight64(resp->cfg_info.oqmask);
+
+		if (!(num_iqueues) || !(num_oqueues)) {
+			dev_err(&octeon_dev->pci_dev->dev,
+				"Got bad iqueues (%016llx) or oqueues (%016llx) from firmware.\n",
+				resp->cfg_info.iqmask, resp->cfg_info.oqmask);
+			goto setup_nic_dev_fail;
+		}
+		dev_dbg(&octeon_dev->pci_dev->dev,
+			"interface %d, iqmask %016llx, oqmask %016llx, numiqueues %d, numoqueues %d\n",
+			i, resp->cfg_info.iqmask, resp->cfg_info.oqmask,
+			num_iqueues, num_oqueues);
+
+		netdev = alloc_etherdev_mq(LIO_SIZE, num_iqueues);
+
+		if (!netdev) {
+			dev_err(&octeon_dev->pci_dev->dev, "Device allocation failed\n");
+			goto setup_nic_dev_fail;
+		}
+
+		SET_NETDEV_DEV(netdev, &octeon_dev->pci_dev->dev);
+
+		/* Associate the routines that will handle different
+		 * netdev tasks.
+		 */
+		netdev->netdev_ops = &lionetdevops;
+
+		lio = GET_LIO(netdev);
+
+		memset(lio, 0, sizeof(struct lio));
+
+		lio->ifidx = ifidx_or_pfnum;
+
+		props = &octeon_dev->props[i];
+		props->gmxport = resp->cfg_info.linfo.gmxport;
+		props->netdev = netdev;
+
+		lio->linfo.num_rxpciq = num_oqueues;
+		lio->linfo.num_txpciq = num_iqueues;
+
+		for (j = 0; j < num_oqueues; j++) {
+			lio->linfo.rxpciq[j].u64 =
+			    resp->cfg_info.linfo.rxpciq[j].u64;
+		}
+		for (j = 0; j < num_iqueues; j++) {
+			lio->linfo.txpciq[j].u64 =
+			    resp->cfg_info.linfo.txpciq[j].u64;
+		}
+
+		lio->linfo.hw_addr = resp->cfg_info.linfo.hw_addr;
+		lio->linfo.gmxport = resp->cfg_info.linfo.gmxport;
+		lio->linfo.link.u64 = resp->cfg_info.linfo.link.u64;
+		lio->linfo.macaddr_is_admin_asgnd =
+			resp->cfg_info.linfo.macaddr_is_admin_asgnd;
+
+		lio->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
+
+		lio->dev_capability = NETIF_F_HIGHDMA
+				      | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM
+				      | NETIF_F_SG | NETIF_F_RXCSUM
+				      | NETIF_F_TSO | NETIF_F_TSO6
+				      | NETIF_F_GRO
+				      | NETIF_F_LRO;
+		netif_set_gso_max_size(netdev, OCTNIC_GSO_MAX_SIZE);
+
+		/* Copy of transmit encapsulation capabilities:
+		 * TSO, TSO6, Checksums for this device
+		 */
+		lio->enc_dev_capability = NETIF_F_IP_CSUM
+					  | NETIF_F_IPV6_CSUM
+					  | NETIF_F_GSO_UDP_TUNNEL
+					  | NETIF_F_HW_CSUM | NETIF_F_SG
+					  | NETIF_F_RXCSUM
+					  | NETIF_F_TSO | NETIF_F_TSO6
+					  | NETIF_F_LRO;
+
+		netdev->hw_enc_features =
+		    (lio->enc_dev_capability & ~NETIF_F_LRO);
+		netdev->vlan_features = lio->dev_capability;
+		/* Add any unchangeable hw features */
+		lio->dev_capability |= NETIF_F_HW_VLAN_CTAG_FILTER |
+				       NETIF_F_HW_VLAN_CTAG_RX |
+				       NETIF_F_HW_VLAN_CTAG_TX;
+
+		netdev->features = (lio->dev_capability & ~NETIF_F_LRO);
+
+		netdev->hw_features = lio->dev_capability;
+
+		/* MTU range: 68 - 16000 */
+		netdev->min_mtu = LIO_MIN_MTU_SIZE;
+		netdev->max_mtu = LIO_MAX_MTU_SIZE;
+
+		/* Point to the  properties for octeon device to which this
+		 * interface belongs.
+		 */
+		lio->oct_dev = octeon_dev;
+		lio->octprops = props;
+		lio->netdev = netdev;
+
+		dev_dbg(&octeon_dev->pci_dev->dev,
+			"if%d gmx: %d hw_addr: 0x%llx\n", i,
+			lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr));
+
+		/* 64-bit swap required on LE machines */
+		octeon_swap_8B_data(&lio->linfo.hw_addr, 1);
+		for (j = 0; j < ETH_ALEN; j++)
+			mac[j] = *((u8 *)(((u8 *)&lio->linfo.hw_addr) + 2 + j));
+
+		/* Copy MAC Address to OS network device structure */
+		ether_addr_copy(netdev->dev_addr, mac);
+
+		if (setup_io_queues(octeon_dev, i)) {
+			dev_err(&octeon_dev->pci_dev->dev, "I/O queues creation failed\n");
+			goto setup_nic_dev_fail;
+		}
+
+		ifstate_set(lio, LIO_IFSTATE_DROQ_OPS);
+
+		/* For VFs, enable Octeon device interrupts here,
+		 * as this is contingent upon IO queue setup
+		 */
+		octeon_dev->fn_list.enable_interrupt(octeon_dev,
+						     OCTEON_ALL_INTR);
+
+		/* By default all interfaces on a single Octeon uses the same
+		 * tx and rx queues
+		 */
+		lio->txq = lio->linfo.txpciq[0].s.q_no;
+		lio->rxq = lio->linfo.rxpciq[0].s.q_no;
+
+		lio->tx_qsize = octeon_get_tx_qsize(octeon_dev, lio->txq);
+		lio->rx_qsize = octeon_get_rx_qsize(octeon_dev, lio->rxq);
+
+		if (setup_glists(lio, num_iqueues)) {
+			dev_err(&octeon_dev->pci_dev->dev,
+				"Gather list allocation failed\n");
+			goto setup_nic_dev_fail;
+		}
+
+		/* Register ethtool support */
+		liquidio_set_ethtool_ops(netdev);
+		if (lio->oct_dev->chip_id == OCTEON_CN23XX_VF_VID)
+			octeon_dev->priv_flags = OCT_PRIV_FLAG_DEFAULT;
+		else
+			octeon_dev->priv_flags = 0x0;
+
+		if (netdev->features & NETIF_F_LRO)
+			liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE,
+					     OCTNIC_LROIPV4 | OCTNIC_LROIPV6);
+
+		if ((debug != -1) && (debug & NETIF_MSG_HW))
+			liquidio_set_feature(netdev, OCTNET_CMD_VERBOSE_ENABLE,
+					     0);
+
+		if (setup_link_status_change_wq(netdev))
+			goto setup_nic_dev_fail;
+
+		/* Register the network device with the OS */
+		if (register_netdev(netdev)) {
+			dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n");
+			goto setup_nic_dev_fail;
+		}
+
+		dev_dbg(&octeon_dev->pci_dev->dev,
+			"Setup NIC ifidx:%d mac:%02x%02x%02x%02x%02x%02x\n",
+			i, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+		netif_carrier_off(netdev);
+		lio->link_changes++;
+
+		ifstate_set(lio, LIO_IFSTATE_REGISTERED);
+
+		/* Sending command to firmware to enable Rx checksum offload
+		 * by default at the time of setup of Liquidio driver for
+		 * this device
+		 */
+		liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL,
+					    OCTNET_CMD_RXCSUM_ENABLE);
+		liquidio_set_feature(netdev, OCTNET_CMD_TNL_TX_CSUM_CTL,
+				     OCTNET_CMD_TXCSUM_ENABLE);
+
+		dev_dbg(&octeon_dev->pci_dev->dev,
+			"NIC ifidx:%d Setup successful\n", i);
+
+		octeon_free_soft_command(octeon_dev, sc);
+	}
+
+	return 0;
+
+setup_nic_dev_fail:
+
+	octeon_free_soft_command(octeon_dev, sc);
+
+setup_nic_wait_intr:
+
+	while (i--) {
+		dev_err(&octeon_dev->pci_dev->dev,
+			"NIC ifidx:%d Setup failed\n", i);
+		liquidio_destroy_nic_device(octeon_dev, i);
+	}
+	return -ENODEV;
+}
+
+/**
+ * \brief initialize the NIC
+ * @param oct octeon device
+ *
+ * This initialization routine is called once the Octeon device application is
+ * up and running
+ */
+static int liquidio_init_nic_module(struct octeon_device *oct)
+{
+	struct oct_intrmod_cfg *intrmod_cfg;
+	int num_nic_ports = 1;
+	int i, retval = 0;
+
+	dev_dbg(&oct->pci_dev->dev, "Initializing network interfaces\n");
+
+	/* only default iq and oq were initialized
+	 * initialize the rest as well run port_config command for each port
+	 */
+	oct->ifcount = num_nic_ports;
+	memset(oct->props, 0,
+	       sizeof(struct octdev_props) * num_nic_ports);
+
+	for (i = 0; i < MAX_OCTEON_LINKS; i++)
+		oct->props[i].gmxport = -1;
+
+	retval = setup_nic_devices(oct);
+	if (retval) {
+		dev_err(&oct->pci_dev->dev, "Setup NIC devices failed\n");
+		goto octnet_init_failure;
+	}
+
+	/* Initialize interrupt moderation params */
+	intrmod_cfg = &((struct octeon_device *)oct)->intrmod;
+	intrmod_cfg->rx_enable = 1;
+	intrmod_cfg->check_intrvl = LIO_INTRMOD_CHECK_INTERVAL;
+	intrmod_cfg->maxpkt_ratethr = LIO_INTRMOD_MAXPKT_RATETHR;
+	intrmod_cfg->minpkt_ratethr = LIO_INTRMOD_MINPKT_RATETHR;
+	intrmod_cfg->rx_maxcnt_trigger = LIO_INTRMOD_RXMAXCNT_TRIGGER;
+	intrmod_cfg->rx_maxtmr_trigger = LIO_INTRMOD_RXMAXTMR_TRIGGER;
+	intrmod_cfg->rx_mintmr_trigger = LIO_INTRMOD_RXMINTMR_TRIGGER;
+	intrmod_cfg->rx_mincnt_trigger = LIO_INTRMOD_RXMINCNT_TRIGGER;
+	intrmod_cfg->tx_enable = 1;
+	intrmod_cfg->tx_maxcnt_trigger = LIO_INTRMOD_TXMAXCNT_TRIGGER;
+	intrmod_cfg->tx_mincnt_trigger = LIO_INTRMOD_TXMINCNT_TRIGGER;
+	intrmod_cfg->rx_frames = CFG_GET_OQ_INTR_PKT(octeon_get_conf(oct));
+	intrmod_cfg->rx_usecs = CFG_GET_OQ_INTR_TIME(octeon_get_conf(oct));
+	intrmod_cfg->tx_frames = CFG_GET_IQ_INTR_PKT(octeon_get_conf(oct));
+	dev_dbg(&oct->pci_dev->dev, "Network interfaces ready\n");
+
+	return retval;
+
+octnet_init_failure:
+
+	oct->ifcount = 0;
+
+	return retval;
+}
+
+/**
+ * \brief Device initialization for each Octeon device that is probed
+ * @param octeon_dev  octeon device
+ */
+static int octeon_device_init(struct octeon_device *oct)
+{
+	u32 rev_id;
+	int j;
+
+	atomic_set(&oct->status, OCT_DEV_BEGIN_STATE);
+
+	/* Enable access to the octeon device and make its DMA capability
+	 * known to the OS.
+	 */
+	if (octeon_pci_os_setup(oct))
+		return 1;
+	atomic_set(&oct->status, OCT_DEV_PCI_ENABLE_DONE);
+
+	oct->chip_id = OCTEON_CN23XX_VF_VID;
+	pci_read_config_dword(oct->pci_dev, 8, &rev_id);
+	oct->rev_id = rev_id & 0xff;
+
+	if (cn23xx_setup_octeon_vf_device(oct))
+		return 1;
+
+	atomic_set(&oct->status, OCT_DEV_PCI_MAP_DONE);
+
+	oct->app_mode = CVM_DRV_NIC_APP;
+
+	/* Initialize the dispatch mechanism used to push packets arriving on
+	 * Octeon Output queues.
+	 */
+	if (octeon_init_dispatch_list(oct))
+		return 1;
+
+	atomic_set(&oct->status, OCT_DEV_DISPATCH_INIT_DONE);
+
+	if (octeon_set_io_queues_off(oct)) {
+		dev_err(&oct->pci_dev->dev, "setting io queues off failed\n");
+		return 1;
+	}
+
+	if (oct->fn_list.setup_device_regs(oct)) {
+		dev_err(&oct->pci_dev->dev, "device registers configuration failed\n");
+		return 1;
+	}
+
+	/* Initialize soft command buffer pool */
+	if (octeon_setup_sc_buffer_pool(oct)) {
+		dev_err(&oct->pci_dev->dev, "sc buffer pool allocation failed\n");
+		return 1;
+	}
+	atomic_set(&oct->status, OCT_DEV_SC_BUFF_POOL_INIT_DONE);
+
+	/* Setup the data structures that manage this Octeon's Input queues. */
+	if (octeon_setup_instr_queues(oct)) {
+		dev_err(&oct->pci_dev->dev, "instruction queue initialization failed\n");
+		return 1;
+	}
+	atomic_set(&oct->status, OCT_DEV_INSTR_QUEUE_INIT_DONE);
+
+	/* Initialize lists to manage the requests of different types that
+	 * arrive from user & kernel applications for this octeon device.
+	 */
+	if (octeon_setup_response_list(oct)) {
+		dev_err(&oct->pci_dev->dev, "Response list allocation failed\n");
+		return 1;
+	}
+	atomic_set(&oct->status, OCT_DEV_RESP_LIST_INIT_DONE);
+
+	if (octeon_setup_output_queues(oct)) {
+		dev_err(&oct->pci_dev->dev, "Output queue initialization failed\n");
+		return 1;
+	}
+	atomic_set(&oct->status, OCT_DEV_DROQ_INIT_DONE);
+
+	if (oct->fn_list.setup_mbox(oct)) {
+		dev_err(&oct->pci_dev->dev, "Mailbox setup failed\n");
+		return 1;
+	}
+	atomic_set(&oct->status, OCT_DEV_MBOX_SETUP_DONE);
+
+	if (octeon_allocate_ioq_vector(oct)) {
+		dev_err(&oct->pci_dev->dev, "ioq vector allocation failed\n");
+		return 1;
+	}
+	atomic_set(&oct->status, OCT_DEV_MSIX_ALLOC_VECTOR_DONE);
+
+	dev_info(&oct->pci_dev->dev, "OCTEON_CN23XX VF Version: %s, %d ioqs\n",
+		 LIQUIDIO_VERSION, oct->sriov_info.rings_per_vf);
+
+	/* Setup the interrupt handler and record the INT SUM register address*/
+	if (octeon_setup_interrupt(oct))
+		return 1;
+
+	if (cn23xx_octeon_pfvf_handshake(oct))
+		return 1;
+
+	/* Enable Octeon device interrupts */
+	oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR);
+
+	atomic_set(&oct->status, OCT_DEV_INTR_SET_DONE);
+
+	/* Enable the input and output queues for this Octeon device */
+	if (oct->fn_list.enable_io_queues(oct)) {
+		dev_err(&oct->pci_dev->dev, "enabling io queues failed\n");
+		return 1;
+	}
+
+	atomic_set(&oct->status, OCT_DEV_IO_QUEUES_DONE);
+
+	atomic_set(&oct->status, OCT_DEV_HOST_OK);
+
+	/* Send Credit for Octeon Output queues. Credits are always sent after
+	 * the output queue is enabled.
+	 */
+	for (j = 0; j < oct->num_oqs; j++)
+		writel(oct->droq[j]->max_count, oct->droq[j]->pkts_credit_reg);
+
+	/* Packets can start arriving on the output queues from this point. */
+
+	atomic_set(&oct->status, OCT_DEV_CORE_OK);
+
+	atomic_set(&oct->status, OCT_DEV_RUNNING);
+
+	if (liquidio_init_nic_module(oct))
+		return 1;
+
+	return 0;
+}
+
+static int __init liquidio_vf_init(void)
+{
+	octeon_init_device_list(0);
+	return pci_register_driver(&liquidio_vf_pci_driver);
+}
+
+static void __exit liquidio_vf_exit(void)
+{
+	pci_unregister_driver(&liquidio_vf_pci_driver);
+
+	pr_info("LiquidIO_VF network module is now unloaded\n");
+}
+
+module_init(liquidio_vf_init);
+module_exit(liquidio_vf_exit);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_common.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_common.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*!  \file  liquidio_common.h
  *   \brief Common: Structures and macros used in PCI-NIC package by core and
  *   host driver.
@@ -68,12 +63,10 @@ enum octeon_tag_type {
  */
 #define OPCODE_CORE 0           /* used for generic core operations */
 #define OPCODE_NIC  1           /* used for NIC operations */
-#define OPCODE_LAST OPCODE_NIC
-
 /* Subcodes are used by host driver/apps to identify the sub-operation
  * for the core. They only need to by unique for a given subsystem.
  */
-#define OPCODE_SUBCODE(op, sub)       (((op & 0x0f) << 8) | ((sub) & 0x7f))
+#define OPCODE_SUBCODE(op, sub)       ((((op) & 0x0f) << 8) | ((sub) & 0x7f))
 
 /** OPCODE_CORE subcodes. For future use. */
 
@@ -89,13 +82,13 @@ enum octeon_tag_type {
 #define OPCODE_NIC_TIMESTAMP           0x07
 #define OPCODE_NIC_INTRMOD_CFG         0x08
 #define OPCODE_NIC_IF_CFG              0x09
+#define OPCODE_NIC_VF_DRV_NOTICE       0x0A
+#define VF_DRV_LOADED                  1
+#define VF_DRV_REMOVED                -1
+#define VF_DRV_MACADDR_CHANGED         2
 
 #define CORE_DRV_TEST_SCATTER_OP    0xFFF5
 
-#define OPCODE_SLOW_PATH(rh)  \
-	(OPCODE_SUBCODE(rh->r.opcode, rh->r.subcode) != \
-		OPCODE_SUBCODE(OPCODE_NIC, OPCODE_NIC_NW_DATA))
-
 /* Application codes advertised by the core driver initialization packet. */
 #define CVM_DRV_APP_START           0x0
 #define CVM_DRV_NO_APP              0
@@ -105,31 +98,15 @@ enum octeon_tag_type {
 #define CVM_DRV_INVALID_APP         (CVM_DRV_APP_START + 0x2)
 #define CVM_DRV_APP_END             (CVM_DRV_INVALID_APP - 1)
 
-/* Macro to increment index.
- * Index is incremented by count; if the sum exceeds
- * max, index is wrapped-around to the start.
- */
-#define INCR_INDEX(index, count, max)                \
-do {                                                 \
-	if (((index) + (count)) >= (max))            \
-		index = ((index) + (count)) - (max); \
-	else                                         \
-		index += (count);                    \
-} while (0)
-
-#define INCR_INDEX_BY1(index, max)	\
-do {                                    \
-	if ((++(index)) == (max))       \
-		index = 0;	        \
-} while (0)
+static inline u32 incr_index(u32 index, u32 count, u32 max)
+{
+	if ((index + count) >= max)
+		index = index + count - max;
+	else
+		index += count;
 
-#define DECR_INDEX(index, count, max)                  \
-do {						       \
-	if ((count) > (index))                         \
-		index = ((max) - ((count - index)));   \
-	else                                           \
-		index -= count;			       \
-} while (0)
+	return index;
+}
 
 #define OCT_BOARD_NAME 32
 #define OCT_SERIAL_LEN 64
@@ -235,6 +212,8 @@ static inline void add_sg_size(struct oc
 
 #define   OCTNET_CMD_ID_ACTIVE         0x1a
 
+#define   OCTNET_CMD_SET_UC_LIST       0x1b
+#define   OCTNET_CMD_SET_VF_LINKSTATE  0x1c
 #define   OCTNET_CMD_VXLAN_PORT_ADD    0x0
 #define   OCTNET_CMD_VXLAN_PORT_DEL    0x1
 #define   OCTNET_CMD_RXCSUM_ENABLE     0x0
@@ -731,13 +710,15 @@ struct oct_link_info {
 
 #ifdef __BIG_ENDIAN_BITFIELD
 	u64 gmxport:16;
-	u64 rsvd:32;
+	u64 macaddr_is_admin_asgnd:1;
+	u64 rsvd:31;
 	u64 num_txpciq:8;
 	u64 num_rxpciq:8;
 #else
 	u64 num_rxpciq:8;
 	u64 num_txpciq:8;
-	u64 rsvd:32;
+	u64 rsvd:31;
+	u64 macaddr_is_admin_asgnd:1;
 	u64 gmxport:16;
 #endif
 
@@ -827,6 +808,16 @@ struct oct_link_stats {
 
 };
 
+static inline int opcode_slow_path(union octeon_rh *rh)
+{
+	u16 subcode1, subcode2;
+
+	subcode1 = OPCODE_SUBCODE((rh)->r.opcode, (rh)->r.subcode);
+	subcode2 = OPCODE_SUBCODE(OPCODE_NIC, OPCODE_NIC_NW_DATA);
+
+	return (subcode2 != subcode1);
+}
+
 #define LIO68XX_LED_CTRL_ADDR     0x3501
 #define LIO68XX_LED_CTRL_CFGON    0x1f
 #define LIO68XX_LED_CTRL_CFGOFF   0x100
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_image.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_image.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_image.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/liquidio_image.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,24 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #ifndef _LIQUIDIO_IMAGE_H_
 #define _LIQUIDIO_IMAGE_H_
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -11,8 +11,32 @@ liquidio-$(CONFIG_LIQUIDIO) += lio_ethto
 			cn66xx_device.o    \
 			cn68xx_device.o    \
 			cn23xx_pf_device.o \
+			cn23xx_vf_device.o \
+			octeon_mailbox.o   \
 			octeon_mem_ops.o   \
 			octeon_droq.o      \
 			octeon_nic.o
 
 liquidio-objs := lio_main.o octeon_console.o $(liquidio-y)
+
+obj-$(CONFIG_LIQUIDIO_VF) += liquidio_vf.o
+
+ifeq ($(CONFIG_LIQUIDIO)$(CONFIG_LIQUIDIO_VF), yy)
+	liquidio_vf-objs := lio_vf_main.o
+else
+liquidio_vf-$(CONFIG_LIQUIDIO_VF) += lio_ethtool.o \
+			lio_core.o         \
+			request_manager.o  \
+			response_manager.o \
+			octeon_device.o    \
+			cn66xx_device.o    \
+			cn68xx_device.o    \
+			cn23xx_pf_device.o \
+			cn23xx_vf_device.o \
+			octeon_mailbox.o   \
+			octeon_mem_ops.o   \
+			octeon_droq.o      \
+			octeon_nic.o
+
+liquidio_vf-objs := lio_vf_main.o $(liquidio_vf-y)
+endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_config.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_config.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_config.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_config.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file  octeon_config.h
  *  \brief Host Driver: Configuration data structures for the host driver.
  */
@@ -65,9 +60,15 @@
 #define   DEFAULT_NUM_NIC_PORTS_68XX_210NV  2
 
 /* CN23xx  IQ configuration macros */
+#define   CN23XX_MAX_VFS_PER_PF_PASS_1_0 8
+#define   CN23XX_MAX_VFS_PER_PF_PASS_1_1 31
+#define   CN23XX_MAX_VFS_PER_PF          63
+#define   CN23XX_MAX_RINGS_PER_VF        8
+
 #define   CN23XX_MAX_RINGS_PER_PF_PASS_1_0 12
 #define   CN23XX_MAX_RINGS_PER_PF_PASS_1_1 32
 #define   CN23XX_MAX_RINGS_PER_PF          64
+#define   CN23XX_MAX_RINGS_PER_VF          8
 
 #define   CN23XX_MAX_INPUT_QUEUES	CN23XX_MAX_RINGS_PER_PF
 #define   CN23XX_MAX_IQ_DESCRIPTORS	2048
@@ -466,4 +467,7 @@ struct octeon_config {
 
 #define MAX_POSSIBLE_OCTEON_INSTR_QUEUES	CN23XX_MAX_INPUT_QUEUES
 #define MAX_POSSIBLE_OCTEON_OUTPUT_QUEUES	CN23XX_MAX_OUTPUT_QUEUES
+
+#define MAX_POSSIBLE_VFS			64
+
 #endif /* __OCTEON_CONFIG_H__  */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_console.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_console.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_console.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_console.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /**
  * @file octeon_console.c
  */
@@ -76,9 +71,9 @@ MODULE_PARM_DESC(console_bitmask,
 #define OCTEON_CONSOLE_POLL_INTERVAL_MS  100    /* 10 times per second */
 
 /* First three members of cvmx_bootmem_desc are left in original
-** positions for backwards compatibility.
-** Assumes big endian target
-*/
+ * positions for backwards compatibility.
+ * Assumes big endian target
+ */
 struct cvmx_bootmem_desc {
 	/** spinlock to control access to list */
 	u32 lock;
@@ -143,46 +138,6 @@ struct octeon_pci_console_desc {
 };
 
 /**
- * This macro returns the size of a member of a structure.
- * Logically it is the same as "sizeof(s::field)" in C++, but
- * C lacks the "::" operator.
- */
-#define SIZEOF_FIELD(s, field) sizeof(((s *)NULL)->field)
-
-/**
- * This macro returns a member of the cvmx_bootmem_desc
- * structure. These members can't be directly addressed as
- * they might be in memory not directly reachable. In the case
- * where bootmem is compiled with LINUX_HOST, the structure
- * itself might be located on a remote Octeon. The argument
- * "field" is the member name of the cvmx_bootmem_desc to read.
- * Regardless of the type of the field, the return type is always
- * a u64.
- */
-#define CVMX_BOOTMEM_DESC_GET_FIELD(oct, field)                              \
-	__cvmx_bootmem_desc_get(oct, oct->bootmem_desc_addr,                 \
-				offsetof(struct cvmx_bootmem_desc, field),   \
-				SIZEOF_FIELD(struct cvmx_bootmem_desc, field))
-
-#define __cvmx_bootmem_lock(flags)	(flags = flags)
-#define __cvmx_bootmem_unlock(flags)	(flags = flags)
-
-/**
- * This macro returns a member of the
- * cvmx_bootmem_named_block_desc structure. These members can't
- * be directly addressed as they might be in memory not directly
- * reachable. In the case where bootmem is compiled with
- * LINUX_HOST, the structure itself might be located on a remote
- * Octeon. The argument "field" is the member name of the
- * cvmx_bootmem_named_block_desc to read. Regardless of the type
- * of the field, the return type is always a u64. The "addr"
- * parameter is the physical address of the structure.
- */
-#define CVMX_BOOTMEM_NAMED_GET_FIELD(oct, addr, field)                   \
-	__cvmx_bootmem_desc_get(oct, addr,                               \
-		offsetof(struct cvmx_bootmem_named_block_desc, field),   \
-		SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field))
-/**
  * \brief determines if a given console has debug enabled.
  * @param console console to check
  * @returns  1 = enabled. 0 otherwise
@@ -263,10 +218,15 @@ static int __cvmx_bootmem_check_version(
 		oct->bootmem_desc_addr =
 			octeon_read_device_mem64(oct,
 						 BOOTLOADER_PCI_READ_DESC_ADDR);
-	major_version =
-		(u32)CVMX_BOOTMEM_DESC_GET_FIELD(oct, major_version);
-	minor_version =
-		(u32)CVMX_BOOTMEM_DESC_GET_FIELD(oct, minor_version);
+	major_version = (u32)__cvmx_bootmem_desc_get(
+			oct, oct->bootmem_desc_addr,
+			offsetof(struct cvmx_bootmem_desc, major_version),
+			FIELD_SIZEOF(struct cvmx_bootmem_desc, major_version));
+	minor_version = (u32)__cvmx_bootmem_desc_get(
+			oct, oct->bootmem_desc_addr,
+			offsetof(struct cvmx_bootmem_desc, minor_version),
+			FIELD_SIZEOF(struct cvmx_bootmem_desc, minor_version));
+
 	dev_dbg(&oct->pci_dev->dev, "%s: major_version=%d\n", __func__,
 		major_version);
 	if ((major_version > 3) ||
@@ -289,10 +249,20 @@ static const struct cvmx_bootmem_named_b
 	u64 named_addr = cvmx_bootmem_phy_named_block_find(oct, name, flags);
 
 	if (named_addr) {
-		desc->base_addr = CVMX_BOOTMEM_NAMED_GET_FIELD(oct, named_addr,
-							       base_addr);
-		desc->size =
-			CVMX_BOOTMEM_NAMED_GET_FIELD(oct, named_addr, size);
+		desc->base_addr = __cvmx_bootmem_desc_get(
+				oct, named_addr,
+				offsetof(struct cvmx_bootmem_named_block_desc,
+					 base_addr),
+				FIELD_SIZEOF(
+					struct cvmx_bootmem_named_block_desc,
+					base_addr));
+		desc->size = __cvmx_bootmem_desc_get(oct, named_addr,
+				offsetof(struct cvmx_bootmem_named_block_desc,
+					 size),
+				FIELD_SIZEOF(
+					struct cvmx_bootmem_named_block_desc,
+					size));
+
 		strncpy(desc->name, name, sizeof(desc->name));
 		desc->name[sizeof(desc->name) - 1] = 0;
 		return &oct->bootmem_named_block_desc;
@@ -307,22 +277,41 @@ static u64 cvmx_bootmem_phy_named_block_
 {
 	u64 result = 0;
 
-	__cvmx_bootmem_lock(flags);
 	if (!__cvmx_bootmem_check_version(oct, 3)) {
 		u32 i;
-		u64 named_block_array_addr =
-			CVMX_BOOTMEM_DESC_GET_FIELD(oct,
-						    named_block_array_addr);
-		u32 num_blocks = (u32)
-			CVMX_BOOTMEM_DESC_GET_FIELD(oct, nb_num_blocks);
-		u32 name_length = (u32)
-			CVMX_BOOTMEM_DESC_GET_FIELD(oct, named_block_name_len);
+
+		u64 named_block_array_addr = __cvmx_bootmem_desc_get(
+					oct, oct->bootmem_desc_addr,
+					offsetof(struct cvmx_bootmem_desc,
+						 named_block_array_addr),
+					FIELD_SIZEOF(struct cvmx_bootmem_desc,
+						     named_block_array_addr));
+		u32 num_blocks = (u32)__cvmx_bootmem_desc_get(
+					oct, oct->bootmem_desc_addr,
+					offsetof(struct cvmx_bootmem_desc,
+						 nb_num_blocks),
+					FIELD_SIZEOF(struct cvmx_bootmem_desc,
+						     nb_num_blocks));
+
+		u32 name_length = (u32)__cvmx_bootmem_desc_get(
+					oct, oct->bootmem_desc_addr,
+					offsetof(struct cvmx_bootmem_desc,
+						 named_block_name_len),
+					FIELD_SIZEOF(struct cvmx_bootmem_desc,
+						     named_block_name_len));
+
 		u64 named_addr = named_block_array_addr;
 
 		for (i = 0; i < num_blocks; i++) {
-			u64 named_size =
-				CVMX_BOOTMEM_NAMED_GET_FIELD(oct, named_addr,
-							     size);
+			u64 named_size = __cvmx_bootmem_desc_get(
+					oct, named_addr,
+					 offsetof(
+					struct cvmx_bootmem_named_block_desc,
+					size),
+					 FIELD_SIZEOF(
+					struct cvmx_bootmem_named_block_desc,
+					size));
+
 			if (name && named_size) {
 				char *name_tmp =
 					kmalloc(name_length + 1, GFP_KERNEL);
@@ -347,7 +336,6 @@ static u64 cvmx_bootmem_phy_named_block_
 				sizeof(struct cvmx_bootmem_named_block_desc);
 		}
 	}
-	__cvmx_bootmem_unlock(flags);
 	return result;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,24 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
@@ -32,6 +28,7 @@
 #include "cn66xx_regs.h"
 #include "cn66xx_device.h"
 #include "cn23xx_pf_device.h"
+#include "cn23xx_vf_device.h"
 
 /** Default configuration
  *  for CN66XX OCTEON Models.
@@ -520,11 +517,6 @@ static struct octeon_config default_cn23
 	}
 };
 
-enum {
-	OCTEON_CONFIG_TYPE_DEFAULT = 0,
-	NUM_OCTEON_CONFS,
-};
-
 static struct octeon_config_ptr {
 	u32 conf_type;
 } oct_conf_info[MAX_OCTEON_DEVICES] = {
@@ -580,15 +572,17 @@ static void *__retrieve_octeon_config_in
 	switch (oct_conf_info[oct_id].conf_type) {
 	case OCTEON_CONFIG_TYPE_DEFAULT:
 		if (oct->chip_id == OCTEON_CN66XX) {
-			ret = (void *)&default_cn66xx_conf;
+			ret = &default_cn66xx_conf;
 		} else if ((oct->chip_id == OCTEON_CN68XX) &&
 			   (card_type == LIO_210NV)) {
-			ret =  (void *)&default_cn68xx_210nv_conf;
+			ret = &default_cn68xx_210nv_conf;
 		} else if ((oct->chip_id == OCTEON_CN68XX) &&
 			   (card_type == LIO_410NV)) {
-			ret =  (void *)&default_cn68xx_conf;
+			ret = &default_cn68xx_conf;
 		} else if (oct->chip_id == OCTEON_CN23XX_PF_VID) {
-			ret =  (void *)&default_cn23xx_conf;
+			ret = &default_cn23xx_conf;
+		} else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
+			ret = &default_cn23xx_conf;
 		}
 		break;
 	default:
@@ -604,6 +598,7 @@ static int __verify_octeon_config_info(s
 	case OCTEON_CN68XX:
 		return lio_validate_cn6xxx_config_info(oct, conf);
 	case OCTEON_CN23XX_PF_VID:
+	case OCTEON_CN23XX_VF_VID:
 		return 0;
 	default:
 		break;
@@ -649,12 +644,12 @@ void octeon_free_device_mem(struct octeo
 	int i;
 
 	for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) {
-		if (oct->io_qmask.oq & (1ULL << i))
+		if (oct->io_qmask.oq & BIT_ULL(i))
 			vfree(oct->droq[i]);
 	}
 
 	for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
-		if (oct->io_qmask.iq & (1ULL << i))
+		if (oct->io_qmask.iq & BIT_ULL(i))
 			vfree(oct->instr_queue[i]);
 	}
 
@@ -681,6 +676,9 @@ static struct octeon_device *octeon_allo
 	case OCTEON_CN23XX_PF_VID:
 		configsize = sizeof(struct octeon_cn23xx_pf);
 		break;
+	case OCTEON_CN23XX_VF_VID:
+		configsize = sizeof(struct octeon_cn23xx_vf);
+		break;
 	default:
 		pr_err("%s: Unknown PCI Device: 0x%x\n",
 		       __func__,
@@ -756,6 +754,9 @@ octeon_allocate_ioq_vector(struct octeon
 
 	if (OCTEON_CN23XX_PF(oct))
 		num_ioqs = oct->sriov_info.num_pf_rings;
+	else if (OCTEON_CN23XX_VF(oct))
+		num_ioqs = oct->sriov_info.rings_per_vf;
+
 	size = sizeof(struct octeon_ioq_vector) * num_ioqs;
 
 	oct->ioq_vector = vmalloc(size);
@@ -767,6 +768,7 @@ octeon_allocate_ioq_vector(struct octeon
 		ioq_vector->oct_dev	= oct;
 		ioq_vector->iq_index	= i;
 		ioq_vector->droq_index	= i;
+		ioq_vector->mbox	= oct->mbox[i];
 
 		cpu_num = i % num_online_cpus();
 		cpumask_set_cpu(cpu_num, &ioq_vector->affinity_mask);
@@ -795,10 +797,11 @@ int octeon_setup_instr_queues(struct oct
 
 	if (OCTEON_CN6XXX(oct))
 		num_descs =
-			CFG_GET_NUM_DEF_TX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
+			CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn6xxx));
 	else if (OCTEON_CN23XX_PF(oct))
-		num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_FIELD(oct, cn23xx_pf,
-								conf));
+		num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_pf));
+	else if (OCTEON_CN23XX_VF(oct))
+		num_descs = CFG_GET_NUM_DEF_TX_DESCS(CHIP_CONF(oct, cn23xx_vf));
 
 	oct->num_iqs = 0;
 
@@ -821,6 +824,7 @@ int octeon_setup_instr_queues(struct oct
 	if (octeon_init_instr_queue(oct, txpciq, num_descs)) {
 		/* prevent memory leak */
 		vfree(oct->instr_queue[0]);
+		oct->instr_queue[0] = NULL;
 		return 1;
 	}
 
@@ -837,14 +841,15 @@ int octeon_setup_output_queues(struct oc
 
 	if (OCTEON_CN6XXX(oct)) {
 		num_descs =
-			CFG_GET_NUM_DEF_RX_DESCS(CHIP_FIELD(oct, cn6xxx, conf));
+			CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn6xxx));
 		desc_size =
-			CFG_GET_DEF_RX_BUF_SIZE(CHIP_FIELD(oct, cn6xxx, conf));
+			CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn6xxx));
 	} else if (OCTEON_CN23XX_PF(oct)) {
-		num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_FIELD(oct, cn23xx_pf,
-								conf));
-		desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_FIELD(oct, cn23xx_pf,
-							       conf));
+		num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_pf));
+		desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_pf));
+	} else if (OCTEON_CN23XX_VF(oct)) {
+		num_descs = CFG_GET_NUM_DEF_RX_DESCS(CHIP_CONF(oct, cn23xx_vf));
+		desc_size = CFG_GET_DEF_RX_BUF_SIZE(CHIP_CONF(oct, cn23xx_vf));
 	}
 	oct->num_oqs = 0;
 	oct->droq[0] = vmalloc_node(sizeof(*oct->droq[0]), numa_node);
@@ -853,19 +858,63 @@ int octeon_setup_output_queues(struct oc
 	if (!oct->droq[0])
 		return 1;
 
-	if (octeon_init_droq(oct, oq_no, num_descs, desc_size, NULL))
+	if (octeon_init_droq(oct, oq_no, num_descs, desc_size, NULL)) {
+		vfree(oct->droq[oq_no]);
+		oct->droq[oq_no] = NULL;
 		return 1;
+	}
 	oct->num_oqs++;
 
 	return 0;
 }
 
-void octeon_set_io_queues_off(struct octeon_device *oct)
+int octeon_set_io_queues_off(struct octeon_device *oct)
 {
+	int loop = BUSY_READING_REG_VF_LOOP_COUNT;
+
 	if (OCTEON_CN6XXX(oct)) {
 		octeon_write_csr(oct, CN6XXX_SLI_PKT_INSTR_ENB, 0);
 		octeon_write_csr(oct, CN6XXX_SLI_PKT_OUT_ENB, 0);
+	} else if (oct->chip_id == OCTEON_CN23XX_VF_VID) {
+		u32 q_no;
+
+		/* IOQs will already be in reset.
+		 * If RST bit is set, wait for quiet bit to be set.
+		 * Once quiet bit is set, clear the RST bit.
+		 */
+		for (q_no = 0; q_no < oct->sriov_info.rings_per_vf; q_no++) {
+			u64 reg_val = octeon_read_csr64(
+				oct, CN23XX_VF_SLI_IQ_PKT_CONTROL64(q_no));
+
+			while ((reg_val & CN23XX_PKT_INPUT_CTL_RST) &&
+			       !(reg_val &  CN23XX_PKT_INPUT_CTL_QUIET) &&
+			       loop) {
+				reg_val = octeon_read_csr64(
+					oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
+				loop--;
+			}
+			if (!loop) {
+				dev_err(&oct->pci_dev->dev,
+					"clearing the reset reg failed or setting the quiet reg failed for qno: %u\n",
+					q_no);
+				return -1;
+			}
+
+			reg_val = reg_val & ~CN23XX_PKT_INPUT_CTL_RST;
+			octeon_write_csr64(oct,
+					   CN23XX_SLI_IQ_PKT_CONTROL64(q_no),
+					   reg_val);
+
+			reg_val = octeon_read_csr64(
+					oct, CN23XX_SLI_IQ_PKT_CONTROL64(q_no));
+			if (reg_val & CN23XX_PKT_INPUT_CTL_RST) {
+				dev_err(&oct->pci_dev->dev,
+					"unable to reset qno %u\n", q_no);
+				return -1;
+			}
+		}
 	}
+	return 0;
 }
 
 void octeon_set_droq_pkt_op(struct octeon_device *oct,
@@ -1070,10 +1119,10 @@ int octeon_core_drv_init(struct octeon_r
 
 	if (OCTEON_CN6XXX(oct))
 		num_nic_ports =
-			CFG_GET_NUM_NIC_PORTS(CHIP_FIELD(oct, cn6xxx, conf));
+			CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn6xxx));
 	else if (OCTEON_CN23XX_PF(oct))
 		num_nic_ports =
-			CFG_GET_NUM_NIC_PORTS(CHIP_FIELD(oct, cn23xx_pf, conf));
+			CFG_GET_NUM_NIC_PORTS(CHIP_CONF(oct, cn23xx_pf));
 
 	if (atomic_read(&oct->status) >= OCT_DEV_RUNNING) {
 		dev_err(&oct->pci_dev->dev, "Received CORE OK when device state is 0x%x\n",
@@ -1143,7 +1192,7 @@ int octeon_get_tx_qsize(struct octeon_de
 
 {
 	if (oct && (q_no < MAX_OCTEON_INSTR_QUEUES(oct)) &&
-	    (oct->io_qmask.iq & (1ULL << q_no)))
+	    (oct->io_qmask.iq & BIT_ULL(q_no)))
 		return oct->instr_queue[q_no]->max_count;
 
 	return -1;
@@ -1152,7 +1201,7 @@ int octeon_get_tx_qsize(struct octeon_de
 int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no)
 {
 	if (oct && (q_no < MAX_OCTEON_OUTPUT_QUEUES(oct)) &&
-	    (oct->io_qmask.oq & (1ULL << q_no)))
+	    (oct->io_qmask.oq & BIT_ULL(q_no)))
 		return oct->droq[q_no]->max_count;
 	return -1;
 }
@@ -1168,10 +1217,13 @@ struct octeon_config *octeon_get_conf(st
 
 	if (OCTEON_CN6XXX(oct)) {
 		default_oct_conf =
-			(struct octeon_config *)(CHIP_FIELD(oct, cn6xxx, conf));
+			(struct octeon_config *)(CHIP_CONF(oct, cn6xxx));
 	} else if (OCTEON_CN23XX_PF(oct)) {
 		default_oct_conf = (struct octeon_config *)
-			(CHIP_FIELD(oct, cn23xx_pf, conf));
+			(CHIP_CONF(oct, cn23xx_pf));
+	} else if (OCTEON_CN23XX_VF(oct)) {
+		default_oct_conf = (struct octeon_config *)
+			(CHIP_CONF(oct, cn23xx_vf));
 	}
 	return default_oct_conf;
 }
@@ -1322,7 +1374,7 @@ void lio_enable_irq(struct octeon_droq *
 	/*write resend. Writing RESEND in SLI_PKTX_CNTS should be enough
 	 *to trigger tx interrupts as well, if they are pending.
 	 */
-	if (oct && OCTEON_CN23XX_PF(oct)) {
+	if (oct && (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct))) {
 		if (droq)
 			writeq(CN23XX_INTR_RESEND, droq->pkts_sent_reg);
 		/*we race with firmrware here. read and write the IN_DONE_CNTS*/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_device.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,25 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
-
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file octeon_device.h
  *  \brief Host Driver: This file defines the octeon device structure.
  */
@@ -38,6 +33,7 @@
 #define  OCTEON_CN68XX                0x0091
 #define  OCTEON_CN66XX                0x0092
 #define  OCTEON_CN23XX_PF_VID         0x9702
+#define  OCTEON_CN23XX_VF_VID         0x9712
 
 /**RevisionId for the chips */
 #define  OCTEON_CN23XX_REV_1_0        0x00
@@ -52,7 +48,14 @@ enum octeon_pci_swap_mode {
 	OCTEON_PCI_32BIT_LW_SWAP = 3
 };
 
+enum {
+	OCTEON_CONFIG_TYPE_DEFAULT = 0,
+	NUM_OCTEON_CONFS,
+};
+
+#define  OCTEON_INPUT_INTR    (1)
 #define  OCTEON_OUTPUT_INTR   (2)
+#define  OCTEON_MBOX_INTR     (4)
 #define  OCTEON_ALL_INTR      0xff
 
 /*---------------   PCI BAR1 index registers -------------*/
@@ -70,26 +73,30 @@ enum octeon_pci_swap_mode {
  *  as it is initialized.
  */
 #define    OCT_DEV_BEGIN_STATE            0x0
-#define    OCT_DEV_PCI_MAP_DONE           0x1
-#define    OCT_DEV_DISPATCH_INIT_DONE     0x2
-#define    OCT_DEV_INSTR_QUEUE_INIT_DONE  0x3
-#define    OCT_DEV_SC_BUFF_POOL_INIT_DONE 0x4
-#define    OCT_DEV_RESP_LIST_INIT_DONE    0x5
-#define    OCT_DEV_DROQ_INIT_DONE         0x6
-#define    OCT_DEV_IO_QUEUES_DONE         0x7
-#define    OCT_DEV_CONSOLE_INIT_DONE      0x8
-#define    OCT_DEV_HOST_OK                0x9
-#define    OCT_DEV_CORE_OK                0xa
-#define    OCT_DEV_RUNNING                0xb
-#define    OCT_DEV_IN_RESET               0xc
-#define    OCT_DEV_STATE_INVALID          0xd
+#define    OCT_DEV_PCI_ENABLE_DONE        0x1
+#define    OCT_DEV_PCI_MAP_DONE           0x2
+#define    OCT_DEV_DISPATCH_INIT_DONE     0x3
+#define    OCT_DEV_INSTR_QUEUE_INIT_DONE  0x4
+#define    OCT_DEV_SC_BUFF_POOL_INIT_DONE 0x5
+#define    OCT_DEV_RESP_LIST_INIT_DONE    0x6
+#define    OCT_DEV_DROQ_INIT_DONE         0x7
+#define    OCT_DEV_MBOX_SETUP_DONE        0x8
+#define    OCT_DEV_MSIX_ALLOC_VECTOR_DONE 0x9
+#define    OCT_DEV_INTR_SET_DONE          0xa
+#define    OCT_DEV_IO_QUEUES_DONE         0xb
+#define    OCT_DEV_CONSOLE_INIT_DONE      0xc
+#define    OCT_DEV_HOST_OK                0xd
+#define    OCT_DEV_CORE_OK                0xe
+#define    OCT_DEV_RUNNING                0xf
+#define    OCT_DEV_IN_RESET               0x10
+#define    OCT_DEV_STATE_INVALID          0x11
 
 #define    OCT_DEV_STATES                 OCT_DEV_STATE_INVALID
 
 /** Octeon Device interrupts
-  *  These interrupt bits are set in int_status filed of
-  *  octeon_device structure
-  */
+ * These interrupt bits are set in int_status filed of
+ * octeon_device structure
+ */
 #define	   OCT_DEV_INTR_DMA0_FORCE	  0x01
 #define	   OCT_DEV_INTR_DMA1_FORCE	  0x02
 #define	   OCT_DEV_INTR_PKT_DATA	  0x04
@@ -208,6 +215,10 @@ struct octeon_fn_list {
 
 	irqreturn_t (*process_interrupt_regs)(void *);
 	u64 (*msix_interrupt_handler)(void *);
+
+	int (*setup_mbox)(struct octeon_device *);
+	int (*free_mbox)(struct octeon_device *);
+
 	int (*soft_reset)(struct octeon_device *);
 	int (*setup_device_regs)(struct octeon_device *);
 	void (*bar1_idx_setup)(struct octeon_device *, u64, u32, int);
@@ -284,6 +295,7 @@ struct octdev_props {
 #define LIO_FLAG_MSIX_ENABLED	0x1
 #define MSIX_PO_INT		0x1
 #define MSIX_PI_INT		0x2
+#define MSIX_MBOX_INT		0x4
 
 struct octeon_pf_vf_hs_word {
 #ifdef __LITTLE_ENDIAN_BITFIELD
@@ -322,14 +334,39 @@ struct octeon_pf_vf_hs_word {
 };
 
 struct octeon_sriov_info {
+	/* Number of rings assigned to VF */
+	u32	rings_per_vf;
+
+	/** Max Number of VF devices that can be enabled. This variable can
+	 *  specified during load time or it will be derived after allocating
+	 *  PF queues. When max_vfs is derived then each VF will get one queue
+	 **/
+	u32	max_vfs;
+
+	/** Number of VF devices enabled using sysfs. */
+	u32	num_vfs_alloced;
+
 	/* Actual rings left for PF device */
 	u32	num_pf_rings;
 
-	/* SRN of PF usable IO queues   */
+	/* SRN of PF usable IO queues */
 	u32	pf_srn;
+
 	/* total pf rings */
 	u32	trs;
 
+	u32	sriov_enabled;
+
+	/*lookup table that maps DPI ring number to VF pci_dev struct pointer*/
+	struct pci_dev *dpiring_to_vfpcidev_lut[MAX_POSSIBLE_VFS];
+
+	u64	vf_macaddr[MAX_POSSIBLE_VFS];
+
+	u16	vf_vlantci[MAX_POSSIBLE_VFS];
+
+	int	vf_linkstate[MAX_POSSIBLE_VFS];
+
+	u64	vf_drv_loaded_mask;
 };
 
 struct octeon_ioq_vector {
@@ -337,6 +374,7 @@ struct octeon_ioq_vector {
 	int		        iq_index;
 	int		        droq_index;
 	int			vector;
+	struct octeon_mbox     *mbox;
 	struct cpumask		affinity_mask;
 	u32			ioq_num;
 };
@@ -365,8 +403,13 @@ struct octeon_device {
 
 	/** Octeon Chip type. */
 	u16 chip_id;
+
 	u16 rev_id;
+
 	u16 pf_num;
+
+	u16 vf_num;
+
 	/** This device's id - set by the driver. */
 	u32 octeon_id;
 
@@ -474,6 +517,9 @@ struct octeon_device {
 
 	int msix_on;
 
+	/** Mail Box details of each octeon queue. */
+	struct octeon_mbox  *mbox[MAX_POSSIBLE_VFS];
+
 	/** IOq information of it's corresponding MSI-X interrupt. */
 	struct octeon_ioq_vector    *ioq_vector;
 
@@ -490,11 +536,14 @@ struct octeon_device {
 
 #define  OCT_DRV_ONLINE 1
 #define  OCT_DRV_OFFLINE 2
-#define  OCTEON_CN6XXX(oct)           ((oct->chip_id == OCTEON_CN66XX) || \
-				       (oct->chip_id == OCTEON_CN68XX))
-#define  OCTEON_CN23XX_PF(oct)        (oct->chip_id == OCTEON_CN23XX_PF_VID)
-#define CHIP_FIELD(oct, TYPE, field)             \
-	(((struct octeon_ ## TYPE  *)(oct->chip))->field)
+#define  OCTEON_CN6XXX(oct)	({					\
+				 typeof(oct) _oct = (oct);		\
+				 ((_oct->chip_id == OCTEON_CN66XX) ||	\
+				  (_oct->chip_id == OCTEON_CN68XX));	})
+#define  OCTEON_CN23XX_PF(oct)        ((oct)->chip_id == OCTEON_CN23XX_PF_VID)
+#define  OCTEON_CN23XX_VF(oct)        ((oct)->chip_id == OCTEON_CN23XX_VF_VID)
+#define CHIP_CONF(oct, TYPE)             \
+	(((struct octeon_ ## TYPE  *)((oct)->chip))->conf)
 
 struct oct_intrmod_cmd {
 	struct octeon_device *oct_dev;
@@ -508,7 +557,7 @@ struct oct_intrmod_cmd {
 void octeon_init_device_list(int conf_type);
 
 /** Free memory for Input and Output queue structures for a octeon device */
-void octeon_free_device_mem(struct octeon_device *);
+void octeon_free_device_mem(struct octeon_device *oct);
 
 /* Look up a free entry in the octeon_device table and allocate resources
  * for the octeon_device structure for an octeon device. Called at init
@@ -606,16 +655,16 @@ void lio_pci_writeq(struct octeon_device
 
 /* Routines for reading and writing CSRs */
 #define   octeon_write_csr(oct_dev, reg_off, value) \
-		writel(value, oct_dev->mmio[0].hw_addr + reg_off)
+		writel(value, (oct_dev)->mmio[0].hw_addr + (reg_off))
 
 #define   octeon_write_csr64(oct_dev, reg_off, val64) \
-		writeq(val64, oct_dev->mmio[0].hw_addr + reg_off)
+		writeq(val64, (oct_dev)->mmio[0].hw_addr + (reg_off))
 
 #define   octeon_read_csr(oct_dev, reg_off)         \
-		readl(oct_dev->mmio[0].hw_addr + reg_off)
+		readl((oct_dev)->mmio[0].hw_addr + (reg_off))
 
 #define   octeon_read_csr64(oct_dev, reg_off)         \
-		readq(oct_dev->mmio[0].hw_addr + reg_off)
+		readq((oct_dev)->mmio[0].hw_addr + (reg_off))
 
 /**
  * Checks if memory access is okay
@@ -724,7 +773,7 @@ int octeon_get_rx_qsize(struct octeon_de
 /** Turns off the input and output queues for the device
  *  @param oct which octeon to disable
  */
-void octeon_set_io_queues_off(struct octeon_device *oct);
+int octeon_set_io_queues_off(struct octeon_device *oct);
 
 /** Turns on or off the given output queue for the device
  *  @param oct which octeon to change
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.c	2017-02-12 16:03:20.000000000 -0500
@@ -1,24 +1,20 @@
 /**********************************************************************
-* Author: Cavium, Inc.
-*
-* Contact: support@cavium.com
-*          Please include "LiquidIO" in the subject.
-*
-* Copyright (c) 2003-2015 Cavium, Inc.
-*
-* This file is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License, Version 2, as
-* published by the Free Software Foundation.
-*
-* This file is distributed in the hope that it will be useful, but
-* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
-* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
-* NONINFRINGEMENT.  See the GNU General Public License for more
-* details.
-*
-* This file may also be available under a different license from Cavium.
-* Contact Cavium, Inc. for more information
-**********************************************************************/
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/vmalloc.h>
@@ -32,9 +28,7 @@
 #include "cn66xx_regs.h"
 #include "cn66xx_device.h"
 #include "cn23xx_pf_device.h"
-
-#define     CVM_MIN(d1, d2)           (((d1) < (d2)) ? (d1) : (d2))
-#define     CVM_MAX(d1, d2)           (((d1) > (d2)) ? (d1) : (d2))
+#include "cn23xx_vf_device.h"
 
 struct niclist {
 	struct list_head list;
@@ -258,13 +252,18 @@ int octeon_init_droq(struct octeon_devic
 	c_num_descs = num_descs;
 	c_buf_size = desc_size;
 	if (OCTEON_CN6XXX(oct)) {
-		struct octeon_config *conf6x = CHIP_FIELD(oct, cn6xxx, conf);
+		struct octeon_config *conf6x = CHIP_CONF(oct, cn6xxx);
 
 		c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf6x);
 		c_refill_threshold =
 			(u32)CFG_GET_OQ_REFILL_THRESHOLD(conf6x);
 	} else if (OCTEON_CN23XX_PF(oct)) {
-		struct octeon_config *conf23 = CHIP_FIELD(oct, cn23xx_pf, conf);
+		struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_pf);
+
+		c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf23);
+		c_refill_threshold = (u32)CFG_GET_OQ_REFILL_THRESHOLD(conf23);
+	} else if (OCTEON_CN23XX_VF(oct)) {
+		struct octeon_config *conf23 = CHIP_CONF(oct, cn23xx_vf);
 
 		c_pkts_per_intr = (u32)CFG_GET_OQ_PKTS_PER_INTR(conf23);
 		c_refill_threshold = (u32)CFG_GET_OQ_REFILL_THRESHOLD(conf23);
@@ -337,7 +336,7 @@ int octeon_init_droq(struct octeon_devic
 	/* For 56xx Pass1, this function won't be called, so no checks. */
 	oct->fn_list.setup_oq_regs(oct, q_no);
 
-	oct->io_qmask.oq |= (1ULL << q_no);
+	oct->io_qmask.oq |= BIT_ULL(q_no);
 
 	return 0;
 
@@ -409,7 +408,7 @@ static inline struct octeon_recv_info *o
 		recv_pkt->buffer_ptr[i] = droq->recv_buf_list[idx].buffer;
 		droq->recv_buf_list[idx].buffer = NULL;
 
-		INCR_INDEX_BY1(idx, droq->max_count);
+		idx = incr_index(idx, 1, droq->max_count);
 		bytes_left -= droq->buffer_size;
 		i++;
 		buf_cnt--;
@@ -440,14 +439,15 @@ octeon_droq_refill_pullup_descs(struct o
 			droq->recv_buf_list[refill_index].buffer = NULL;
 			desc_ring[refill_index].buffer_ptr = 0;
 			do {
-				INCR_INDEX_BY1(droq->refill_idx,
-					       droq->max_count);
+				droq->refill_idx = incr_index(droq->refill_idx,
+							      1,
+							      droq->max_count);
 				desc_refilled++;
 				droq->refill_count--;
 			} while (droq->recv_buf_list[droq->refill_idx].
 				 buffer);
 		}
-		INCR_INDEX_BY1(refill_index, droq->max_count);
+		refill_index = incr_index(refill_index, 1, droq->max_count);
 	}                       /* while */
 	return desc_refilled;
 }
@@ -514,7 +514,8 @@ octeon_droq_refill(struct octeon_device
 		/* Reset any previous values in the length field. */
 		droq->info_list[droq->refill_idx].length = 0;
 
-		INCR_INDEX_BY1(droq->refill_idx, droq->max_count);
+		droq->refill_idx = incr_index(droq->refill_idx, 1,
+					      droq->max_count);
 		desc_refilled++;
 		droq->refill_count--;
 	}
@@ -599,7 +600,8 @@ static inline void octeon_droq_drop_pack
 			buf_cnt = 1;
 		}
 
-		INCR_INDEX(droq->read_idx, buf_cnt, droq->max_count);
+		droq->read_idx = incr_index(droq->read_idx, buf_cnt,
+					    droq->max_count);
 		droq->refill_count += buf_cnt;
 	}
 }
@@ -639,11 +641,12 @@ octeon_droq_fast_process_packets(struct
 		rh = &info->rh;
 
 		total_len += (u32)info->length;
-		if (OPCODE_SLOW_PATH(rh)) {
+		if (opcode_slow_path(rh)) {
 			u32 buf_cnt;
 
 			buf_cnt = octeon_droq_dispatch_pkt(oct, droq, rh, info);
-			INCR_INDEX(droq->read_idx, buf_cnt, droq->max_count);
+			droq->read_idx = incr_index(droq->read_idx,
+						    buf_cnt, droq->max_count);
 			droq->refill_count += buf_cnt;
 		} else {
 			if (info->length <= droq->buffer_size) {
@@ -657,7 +660,8 @@ octeon_droq_fast_process_packets(struct
 				droq->recv_buf_list[droq->read_idx].buffer =
 					NULL;
 
-				INCR_INDEX_BY1(droq->read_idx, droq->max_count);
+				droq->read_idx = incr_index(droq->read_idx, 1,
+							    droq->max_count);
 				droq->refill_count++;
 			} else {
 				nicbuf = octeon_fast_packet_alloc((u32)
@@ -689,8 +693,9 @@ octeon_droq_fast_process_packets(struct
 					}
 
 					pkt_len += cpy_len;
-					INCR_INDEX_BY1(droq->read_idx,
-						       droq->max_count);
+					droq->read_idx =
+						incr_index(droq->read_idx, 1,
+							   droq->max_count);
 					droq->refill_count++;
 				}
 			}
@@ -804,9 +809,8 @@ octeon_droq_process_poll_pkts(struct oct
 	while (total_pkts_processed < budget) {
 		octeon_droq_check_hw_for_pkts(droq);
 
-		pkts_available =
-			CVM_MIN((budget - total_pkts_processed),
-				(u32)(atomic_read(&droq->pkts_pending)));
+		pkts_available = min((budget - total_pkts_processed),
+				     (u32)(atomic_read(&droq->pkts_pending)));
 
 		if (pkts_available == 0)
 			break;
@@ -891,6 +895,10 @@ octeon_process_droq_poll_cmd(struct octe
 			lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]);
 		}
 		break;
+
+		case OCTEON_CN23XX_VF_VID:
+			lio_enable_irq(oct->droq[q_no], oct->instr_queue[q_no]);
+		break;
 		}
 		return 0;
 	}
@@ -988,7 +996,8 @@ int octeon_create_droq(struct octeon_dev
 	if (!droq)
 		droq = vmalloc(sizeof(*droq));
 	if (!droq)
-		goto create_droq_fail;
+		return -1;
+
 	memset(droq, 0, sizeof(struct octeon_droq));
 
 	/*Disable the pkt o/p for this Q  */
@@ -996,7 +1005,11 @@ int octeon_create_droq(struct octeon_dev
 	oct->droq[q_no] = droq;
 
 	/* Initialize the Droq */
-	octeon_init_droq(oct, q_no, num_descs, desc_size, app_ctx);
+	if (octeon_init_droq(oct, q_no, num_descs, desc_size, app_ctx)) {
+		vfree(oct->droq[q_no]);
+		oct->droq[q_no] = NULL;
+		return -1;
+	}
 
 	oct->num_oqs++;
 
@@ -1009,8 +1022,4 @@ int octeon_create_droq(struct octeon_dev
 	 * the same time.
 	 */
 	return 0;
-
-create_droq_fail:
-	octeon_delete_droq(oct, q_no);
-	return -ENOMEM;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_droq.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -13,13 +13,8 @@
  * This file is distributed in the hope that it will be useful, but
  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
- **********************************************************************/
-
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*!  \file  octeon_droq.h
  *   \brief Implementation of Octeon Output queues. "Output" is with
  *   respect to the Octeon device on the NIC. From this driver's point of
@@ -81,7 +76,7 @@ struct octeon_skb_page_info {
  *  the Octeon device. Since the descriptor ring keeps physical (bus)
  *  addresses, this field is required for the driver to keep track of
  *  the virtual address pointers.
-*/
+ */
 struct octeon_recv_buffer {
 	/** Packet buffer, including metadata. */
 	void *buffer;
@@ -121,7 +116,6 @@ struct oct_droq_stats {
 	/** Num of Packets dropped due to receive path failures. */
 	u64 rx_dropped;
 
-	/** Num of vxlan packets received; */
 	u64 rx_vxlan;
 
 	/** Num of failures of recv_buffer_alloc() */
@@ -359,7 +353,7 @@ struct octeon_droq {
  * @param  q_no       - droq no. ranges from 0 - 3.
  * @param app_ctx     - pointer to application context
  * @return Success: 0    Failure: 1
-*/
+ */
 int octeon_init_droq(struct octeon_device *oct_dev,
 		     u32 q_no,
 		     u32 num_descs,
@@ -372,7 +366,7 @@ int octeon_init_droq(struct octeon_devic
  *  @param oct_dev - pointer to the octeon device structure
  *  @param q_no    - droq no. ranges from 0 - 3.
  *  @return:    Success: 0    Failure: 1
-*/
+ */
 int octeon_delete_droq(struct octeon_device *oct_dev, u32 q_no);
 
 /** Register a change in droq operations. The ops field has a pointer to a
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_iq.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_iq.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_iq.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_iq.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -13,13 +13,8 @@
  * This file is distributed in the hope that it will be useful, but
  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
- **********************************************************************/
-
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*!  \file  octeon_iq.h
  *   \brief Host Driver: Implementation of Octeon input queues. "Input" is
  *   with respect to the Octeon device on the NIC. From this driver's
@@ -69,7 +64,6 @@ struct oct_iq_stats {
 	u64 tx_vxlan; /* tunnel */
 	u64 tx_dmamap_fail;
 	u64 tx_restart;
-	/*u64 tx_timeout_count;*/
 };
 
 #define OCT_IQ_STATS_SIZE   (sizeof(struct oct_iq_stats))
@@ -78,7 +72,7 @@ struct oct_iq_stats {
  *  The input queue is used to post raw (instruction) mode data or packet
  *  data to Octeon device from the host. Each input queue (upto 4) for
  *  a Octeon device has one such structure to represent it.
-*/
+ */
 struct octeon_instr_queue {
 	struct octeon_device *oct_dev;
 
@@ -118,8 +112,8 @@ struct octeon_instr_queue {
 	u32 octeon_read_index;
 
 	/** This index aids in finding the window in the queue where Octeon
-	  * has read the commands.
-	  */
+	 *  has read the commands.
+	 */
 	u32 flush_index;
 
 	/** This field keeps track of the instructions pending in this queue. */
@@ -150,8 +144,8 @@ struct octeon_instr_queue {
 	u64 last_db_time;
 
 	/** The doorbell timeout. If the doorbell was not rung for this time and
-	  * fill_cnt is non-zero, ring the doorbell again.
-	  */
+	 * fill_cnt is non-zero, ring the doorbell again.
+	 */
 	u32 db_timeout;
 
 	/** Statistics for this input queue. */
@@ -309,6 +303,9 @@ struct octeon_sc_buffer_pool {
 	atomic_t alloc_buf_count;
 };
 
+#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count)  \
+		(((octeon_dev_ptr)->instr_queue[iq_no]->stats.field) += count)
+
 int octeon_setup_sc_buffer_pool(struct octeon_device *oct);
 int octeon_free_sc_buffer_pool(struct octeon_device *oct);
 struct octeon_soft_command *
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,318 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include "liquidio_common.h"
+#include "octeon_droq.h"
+#include "octeon_iq.h"
+#include "response_manager.h"
+#include "octeon_device.h"
+#include "octeon_main.h"
+#include "octeon_mailbox.h"
+
+/**
+ * octeon_mbox_read:
+ * @oct: Pointer mailbox
+ *
+ * Reads the 8-bytes of data from the mbox register
+ * Writes back the acknowldgement inidcating completion of read
+ */
+int octeon_mbox_read(struct octeon_mbox *mbox)
+{
+	union octeon_mbox_message msg;
+	int ret = 0;
+
+	spin_lock(&mbox->lock);
+
+	msg.u64 = readq(mbox->mbox_read_reg);
+
+	if ((msg.u64 == OCTEON_PFVFACK) || (msg.u64 == OCTEON_PFVFSIG)) {
+		spin_unlock(&mbox->lock);
+		return 0;
+	}
+
+	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
+		mbox->mbox_req.data[mbox->mbox_req.recv_len - 1] = msg.u64;
+		mbox->mbox_req.recv_len++;
+	} else {
+		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
+			mbox->mbox_resp.data[mbox->mbox_resp.recv_len - 1] =
+				msg.u64;
+			mbox->mbox_resp.recv_len++;
+		} else {
+			if ((mbox->state & OCTEON_MBOX_STATE_IDLE) &&
+			    (msg.s.type == OCTEON_MBOX_REQUEST)) {
+				mbox->state &= ~OCTEON_MBOX_STATE_IDLE;
+				mbox->state |=
+				    OCTEON_MBOX_STATE_REQUEST_RECEIVING;
+				mbox->mbox_req.msg.u64 = msg.u64;
+				mbox->mbox_req.q_no = mbox->q_no;
+				mbox->mbox_req.recv_len = 1;
+			} else {
+				if ((mbox->state &
+				     OCTEON_MBOX_STATE_RESPONSE_PENDING) &&
+				    (msg.s.type == OCTEON_MBOX_RESPONSE)) {
+					mbox->state &=
+					    ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
+					mbox->state |=
+					    OCTEON_MBOX_STATE_RESPONSE_RECEIVING
+					    ;
+					mbox->mbox_resp.msg.u64 = msg.u64;
+					mbox->mbox_resp.q_no = mbox->q_no;
+					mbox->mbox_resp.recv_len = 1;
+				} else {
+					writeq(OCTEON_PFVFERR,
+					       mbox->mbox_read_reg);
+					mbox->state |= OCTEON_MBOX_STATE_ERROR;
+					spin_unlock(&mbox->lock);
+					return 1;
+				}
+			}
+		}
+	}
+
+	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVING) {
+		if (mbox->mbox_req.recv_len < msg.s.len) {
+			ret = 0;
+		} else {
+			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVING;
+			mbox->state |= OCTEON_MBOX_STATE_REQUEST_RECEIVED;
+			ret = 1;
+		}
+	} else {
+		if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVING) {
+			if (mbox->mbox_resp.recv_len < msg.s.len) {
+				ret = 0;
+			} else {
+				mbox->state &=
+				    ~OCTEON_MBOX_STATE_RESPONSE_RECEIVING;
+				mbox->state |=
+				    OCTEON_MBOX_STATE_RESPONSE_RECEIVED;
+				ret = 1;
+			}
+		} else {
+			WARN_ON(1);
+		}
+	}
+
+	writeq(OCTEON_PFVFACK, mbox->mbox_read_reg);
+
+	spin_unlock(&mbox->lock);
+
+	return ret;
+}
+
+/**
+ * octeon_mbox_write:
+ * @oct: Pointer Octeon Device
+ * @mbox_cmd: Cmd to send to mailbox.
+ *
+ * Populates the queue specific mbox structure
+ * with cmd information.
+ * Write the cmd to mbox register
+ */
+int octeon_mbox_write(struct octeon_device *oct,
+		      struct octeon_mbox_cmd *mbox_cmd)
+{
+	struct octeon_mbox *mbox = oct->mbox[mbox_cmd->q_no];
+	u32 count, i, ret = OCTEON_MBOX_STATUS_SUCCESS;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mbox->lock, flags);
+
+	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) &&
+	    !(mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED)) {
+		spin_unlock_irqrestore(&mbox->lock, flags);
+		return OCTEON_MBOX_STATUS_FAILED;
+	}
+
+	if ((mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) &&
+	    !(mbox->state & OCTEON_MBOX_STATE_IDLE)) {
+		spin_unlock_irqrestore(&mbox->lock, flags);
+		return OCTEON_MBOX_STATUS_BUSY;
+	}
+
+	if (mbox_cmd->msg.s.type == OCTEON_MBOX_REQUEST) {
+		memcpy(&mbox->mbox_resp, mbox_cmd,
+		       sizeof(struct octeon_mbox_cmd));
+		mbox->state = OCTEON_MBOX_STATE_RESPONSE_PENDING;
+	}
+
+	spin_unlock_irqrestore(&mbox->lock, flags);
+
+	count = 0;
+
+	while (readq(mbox->mbox_write_reg) != OCTEON_PFVFSIG) {
+		schedule_timeout_uninterruptible(LIO_MBOX_WRITE_WAIT_TIME);
+		if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
+			ret = OCTEON_MBOX_STATUS_FAILED;
+			break;
+		}
+	}
+
+	if (ret == OCTEON_MBOX_STATUS_SUCCESS) {
+		writeq(mbox_cmd->msg.u64, mbox->mbox_write_reg);
+		for (i = 0; i < (u32)(mbox_cmd->msg.s.len - 1); i++) {
+			count = 0;
+			while (readq(mbox->mbox_write_reg) !=
+			       OCTEON_PFVFACK) {
+				schedule_timeout_uninterruptible(10);
+				if (count++ == LIO_MBOX_WRITE_WAIT_CNT) {
+					ret = OCTEON_MBOX_STATUS_FAILED;
+					break;
+				}
+			}
+			writeq(mbox_cmd->data[i], mbox->mbox_write_reg);
+		}
+	}
+
+	spin_lock_irqsave(&mbox->lock, flags);
+	if (mbox_cmd->msg.s.type == OCTEON_MBOX_RESPONSE) {
+		mbox->state = OCTEON_MBOX_STATE_IDLE;
+		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+	} else {
+		if ((!mbox_cmd->msg.s.resp_needed) ||
+		    (ret == OCTEON_MBOX_STATUS_FAILED)) {
+			mbox->state &= ~OCTEON_MBOX_STATE_RESPONSE_PENDING;
+			if (!(mbox->state &
+			      (OCTEON_MBOX_STATE_REQUEST_RECEIVING |
+			       OCTEON_MBOX_STATE_REQUEST_RECEIVED)))
+				mbox->state = OCTEON_MBOX_STATE_IDLE;
+		}
+	}
+	spin_unlock_irqrestore(&mbox->lock, flags);
+
+	return ret;
+}
+
+/**
+ * octeon_mbox_process_cmd:
+ * @mbox: Pointer mailbox
+ * @mbox_cmd: Pointer to command received
+ *
+ * Process the cmd received in mbox
+ */
+static int octeon_mbox_process_cmd(struct octeon_mbox *mbox,
+				   struct octeon_mbox_cmd *mbox_cmd)
+{
+	struct octeon_device *oct = mbox->oct_dev;
+
+	switch (mbox_cmd->msg.s.cmd) {
+	case OCTEON_VF_ACTIVE:
+		dev_dbg(&oct->pci_dev->dev, "got vfactive sending data back\n");
+		mbox_cmd->msg.s.type = OCTEON_MBOX_RESPONSE;
+		mbox_cmd->msg.s.resp_needed = 1;
+		mbox_cmd->msg.s.len = 2;
+		mbox_cmd->data[0] = 0; /* VF version is in mbox_cmd->data[0] */
+		((struct lio_version *)&mbox_cmd->data[0])->major =
+			LIQUIDIO_BASE_MAJOR_VERSION;
+		((struct lio_version *)&mbox_cmd->data[0])->minor =
+			LIQUIDIO_BASE_MINOR_VERSION;
+		((struct lio_version *)&mbox_cmd->data[0])->micro =
+			LIQUIDIO_BASE_MICRO_VERSION;
+		memcpy(mbox_cmd->msg.s.params, (uint8_t *)&oct->pfvf_hsword, 6);
+		/* Sending core cofig info to the corresponding active VF.*/
+		octeon_mbox_write(oct, mbox_cmd);
+		break;
+
+	case OCTEON_VF_FLR_REQUEST:
+		dev_info(&oct->pci_dev->dev,
+			 "got a request for FLR from VF that owns DPI ring %u\n",
+			 mbox->q_no);
+		pcie_capability_set_word(
+			oct->sriov_info.dpiring_to_vfpcidev_lut[mbox->q_no],
+			PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
+		break;
+
+	case OCTEON_PF_CHANGED_VF_MACADDR:
+		if (OCTEON_CN23XX_VF(oct))
+			octeon_pf_changed_vf_macaddr(oct,
+						     mbox_cmd->msg.s.params);
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+
+/**
+ *octeon_mbox_process_message:
+ *
+ * Process the received mbox message.
+ */
+int octeon_mbox_process_message(struct octeon_mbox *mbox)
+{
+	struct octeon_mbox_cmd mbox_cmd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mbox->lock, flags);
+
+	if (mbox->state & OCTEON_MBOX_STATE_ERROR) {
+		if (mbox->state & (OCTEON_MBOX_STATE_RESPONSE_PENDING |
+				   OCTEON_MBOX_STATE_RESPONSE_RECEIVING)) {
+			memcpy(&mbox_cmd, &mbox->mbox_resp,
+			       sizeof(struct octeon_mbox_cmd));
+			mbox->state = OCTEON_MBOX_STATE_IDLE;
+			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+			spin_unlock_irqrestore(&mbox->lock, flags);
+			mbox_cmd.recv_status = 1;
+			if (mbox_cmd.fn)
+				mbox_cmd.fn(mbox->oct_dev, &mbox_cmd,
+					    mbox_cmd.fn_arg);
+			return 0;
+		}
+
+		mbox->state = OCTEON_MBOX_STATE_IDLE;
+		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+		spin_unlock_irqrestore(&mbox->lock, flags);
+		return 0;
+	}
+
+	if (mbox->state & OCTEON_MBOX_STATE_RESPONSE_RECEIVED) {
+		memcpy(&mbox_cmd, &mbox->mbox_resp,
+		       sizeof(struct octeon_mbox_cmd));
+		mbox->state = OCTEON_MBOX_STATE_IDLE;
+		writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+		spin_unlock_irqrestore(&mbox->lock, flags);
+		mbox_cmd.recv_status = 0;
+		if (mbox_cmd.fn)
+			mbox_cmd.fn(mbox->oct_dev, &mbox_cmd, mbox_cmd.fn_arg);
+		return 0;
+	}
+
+	if (mbox->state & OCTEON_MBOX_STATE_REQUEST_RECEIVED) {
+		memcpy(&mbox_cmd, &mbox->mbox_req,
+		       sizeof(struct octeon_mbox_cmd));
+		if (!mbox_cmd.msg.s.resp_needed) {
+			mbox->state &= ~OCTEON_MBOX_STATE_REQUEST_RECEIVED;
+			if (!(mbox->state &
+			      OCTEON_MBOX_STATE_RESPONSE_PENDING))
+				mbox->state = OCTEON_MBOX_STATE_IDLE;
+			writeq(OCTEON_PFVFSIG, mbox->mbox_read_reg);
+		}
+
+		spin_unlock_irqrestore(&mbox->lock, flags);
+		octeon_mbox_process_cmd(mbox, &mbox_cmd);
+		return 0;
+	}
+
+	WARN_ON(1);
+
+	return 0;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mailbox.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,115 @@
+/**********************************************************************
+ * Author: Cavium, Inc.
+ *
+ * Contact: support@cavium.com
+ *          Please include "LiquidIO" in the subject.
+ *
+ * Copyright (c) 2003-2016 Cavium, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
+#ifndef __MAILBOX_H__
+#define __MAILBOX_H__
+
+/* Macros for Mail Box Communication */
+
+#define OCTEON_MBOX_DATA_MAX	32
+
+#define OCTEON_VF_ACTIVE		0x1
+#define OCTEON_VF_FLR_REQUEST		0x2
+#define OCTEON_PF_CHANGED_VF_MACADDR	0x4
+
+/*Macro for Read acknowldgement*/
+#define OCTEON_PFVFACK			0xffffffffffffffff
+#define OCTEON_PFVFSIG			0x1122334455667788
+#define OCTEON_PFVFERR			0xDEADDEADDEADDEAD
+
+#define LIO_MBOX_WRITE_WAIT_CNT          1000
+#define LIO_MBOX_WRITE_WAIT_TIME           10
+
+enum octeon_mbox_cmd_status {
+	OCTEON_MBOX_STATUS_SUCCESS = 0,
+	OCTEON_MBOX_STATUS_FAILED = 1,
+	OCTEON_MBOX_STATUS_BUSY = 2
+};
+
+enum octeon_mbox_message_type {
+	OCTEON_MBOX_REQUEST = 0,
+	OCTEON_MBOX_RESPONSE = 1
+};
+
+union octeon_mbox_message {
+	u64 u64;
+	struct {
+		u16 type : 1;
+		u16 resp_needed : 1;
+		u16 cmd : 6;
+		u16 len : 8;
+		u8 params[6];
+	} s;
+};
+
+typedef void (*octeon_mbox_callback_t)(void *, void *, void *);
+
+struct octeon_mbox_cmd {
+	union octeon_mbox_message msg;
+	u64 data[OCTEON_MBOX_DATA_MAX];
+	u32 q_no;
+	u32 recv_len;
+	u32 recv_status;
+	octeon_mbox_callback_t fn;
+	void *fn_arg;
+};
+
+enum octeon_mbox_state {
+	OCTEON_MBOX_STATE_IDLE = 1,
+	OCTEON_MBOX_STATE_REQUEST_RECEIVING = 2,
+	OCTEON_MBOX_STATE_REQUEST_RECEIVED = 4,
+	OCTEON_MBOX_STATE_RESPONSE_PENDING = 8,
+	OCTEON_MBOX_STATE_RESPONSE_RECEIVING = 16,
+	OCTEON_MBOX_STATE_RESPONSE_RECEIVED = 16,
+	OCTEON_MBOX_STATE_ERROR = 32
+};
+
+struct octeon_mbox {
+	/** A spinlock to protect access to this q_mbox. */
+	spinlock_t lock;
+
+	struct octeon_device *oct_dev;
+
+	u32 q_no;
+
+	enum octeon_mbox_state state;
+
+	struct cavium_wk mbox_poll_wk;
+
+	/** SLI_MAC_PF_MBOX_INT for PF, SLI_PKT_MBOX_INT for VF. */
+	void *mbox_int_reg;
+
+	/** SLI_PKT_PF_VF_MBOX_SIG(0) for PF, SLI_PKT_PF_VF_MBOX_SIG(1) for VF.
+	 */
+	void *mbox_write_reg;
+
+	/** SLI_PKT_PF_VF_MBOX_SIG(1) for PF, SLI_PKT_PF_VF_MBOX_SIG(0) for VF.
+	 */
+	void *mbox_read_reg;
+
+	struct octeon_mbox_cmd mbox_req;
+
+	struct octeon_mbox_cmd mbox_resp;
+
+};
+
+int octeon_mbox_read(struct octeon_mbox *mbox);
+int octeon_mbox_write(struct octeon_device *oct,
+		      struct octeon_mbox_cmd *mbox_cmd);
+int octeon_mbox_process_message(struct octeon_mbox *mbox);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_main.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_main.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_main.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_main.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -13,13 +13,8 @@
  * This file is distributed in the hope that it will be useful, but
  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
- **********************************************************************/
-
+ * NONINFRINGEMENT.  See the GNU General Public License for more details.
+ ***********************************************************************/
 /*! \file octeon_main.h
  *  \brief Host Driver: This file is included by all host driver source files
  *  to include common definitions.
@@ -66,7 +61,7 @@ void octeon_update_tx_completion_counter
 					  unsigned int *bytes_compl);
 void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl,
 					unsigned int bytes_compl);
-
+void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac);
 /** Swap 8B blocks */
 static inline void octeon_swap_8B_data(u64 *data, u32 blocks)
 {
@@ -78,10 +73,10 @@ static inline void octeon_swap_8B_data(u
 }
 
 /**
-  * \brief unmaps a PCI BAR
-  * @param oct Pointer to Octeon device
-  * @param baridx bar index
-  */
+ * \brief unmaps a PCI BAR
+ * @param oct Pointer to Octeon device
+ * @param baridx bar index
+ */
 static inline void octeon_unmap_pci_barx(struct octeon_device *oct, int baridx)
 {
 	dev_dbg(&oct->pci_dev->dev, "Freeing PCI mapped regions for Bar%d\n",
@@ -116,7 +111,7 @@ static inline int octeon_map_pci_barx(st
 
 	mapped_len = oct->mmio[baridx].len;
 	if (!mapped_len)
-		return 1;
+		goto err_release_region;
 
 	if (max_map_len && (mapped_len > max_map_len))
 		mapped_len = max_map_len;
@@ -132,11 +127,15 @@ static inline int octeon_map_pci_barx(st
 	if (!oct->mmio[baridx].hw_addr) {
 		dev_err(&oct->pci_dev->dev, "error ioremap for bar %d\n",
 			baridx);
-		return 1;
+		goto err_release_region;
 	}
 	oct->mmio[baridx].done = 1;
 
 	return 0;
+
+err_release_region:
+	pci_release_region(oct->pci_dev, baridx * 2);
+	return 1;
 }
 
 static inline void *
@@ -203,24 +202,6 @@ out:
 	return errno;
 }
 
-static inline void
-sleep_atomic_cond(wait_queue_head_t *waitq, atomic_t *pcond)
-{
-	wait_queue_t we;
-
-	init_waitqueue_entry(&we, current);
-	add_wait_queue(waitq, &we);
-	while (!atomic_read(pcond)) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (signal_pending(current))
-			goto out;
-		schedule();
-	}
-out:
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(waitq, &we);
-}
-
 /* Gives up the CPU for a timeout period.
  * Check that the condition is not true before we go to sleep for a
  * timeout period.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 #include <linux/netdevice.h>
 #include "liquidio_common.h"
@@ -39,7 +36,7 @@ octeon_toggle_bar1_swapmode(struct octeo
 	oct->fn_list.bar1_idx_write(oct, idx, mask);
 }
 #else
-#define octeon_toggle_bar1_swapmode(oct, idx) (oct = oct)
+#define octeon_toggle_bar1_swapmode(oct, idx)
 #endif
 
 static void
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 
 /*!  \file octeon_mem_ops.h
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_network.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_network.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_network.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_network.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 
 /*!  \file  octeon_network.h
@@ -29,7 +26,7 @@
 #include <linux/ptp_clock_kernel.h>
 
 #define LIO_MAX_MTU_SIZE (OCTNET_MAX_FRM_SIZE - OCTNET_FRM_HEADER_SIZE)
-#define LIO_MIN_MTU_SIZE 68
+#define LIO_MIN_MTU_SIZE ETH_MIN_MTU
 
 struct oct_nic_stats_resp {
 	u64     rh;
@@ -126,12 +123,13 @@ struct lio {
 	/* work queue for  link status */
 	struct cavium_wq	link_status_wq;
 
+	int netdev_uc_count;
 };
 
 #define LIO_SIZE         (sizeof(struct lio))
 #define GET_LIO(netdev)  ((struct lio *)netdev_priv(netdev))
 
-#define CIU3_WDOG(c)                 (0x1010000020000ULL + (c << 3))
+#define CIU3_WDOG(c)                 (0x1010000020000ULL + ((c) << 3))
 #define CIU3_WDOG_MASK               12ULL
 #define LIO_MONITOR_WDOG_EXPIRE      1
 #define LIO_MONITOR_CORE_STUCK_MSGD  2
@@ -342,9 +340,9 @@ static inline void tx_buffer_free(void *
 }
 
 #define lio_dma_alloc(oct, size, dma_addr) \
-	dma_alloc_coherent(&oct->pci_dev->dev, size, dma_addr, GFP_KERNEL)
+	dma_alloc_coherent(&(oct)->pci_dev->dev, size, dma_addr, GFP_KERNEL)
 #define lio_dma_free(oct, size, virt_addr, dma_addr) \
-	dma_free_coherent(&oct->pci_dev->dev, size, virt_addr, dma_addr)
+	dma_free_coherent(&(oct)->pci_dev->dev, size, virt_addr, dma_addr)
 
 static inline
 void *get_rbd(struct sk_buff *skb)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 #include <linux/pci.h>
 #include <linux/netdevice.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/octeon_nic.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 
 /*!  \file octeon_nic.h
@@ -67,7 +64,7 @@ struct octnic_ctrl_pkt {
 	octnic_ctrl_pkt_cb_fn_t cb_fn;
 };
 
-#define MAX_UDD_SIZE(nctrl) (sizeof(nctrl->udd))
+#define MAX_UDD_SIZE(nctrl) (sizeof((nctrl)->udd))
 
 /** Structure of data information passed by the NIC module to the OSI
  * layer when forwarding data to Octeon device software.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/request_manager.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/request_manager.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/request_manager.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/request_manager.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -31,9 +28,7 @@
 #include "octeon_network.h"
 #include "cn66xx_device.h"
 #include "cn23xx_pf_device.h"
-
-#define INCR_INSTRQUEUE_PKT_COUNT(octeon_dev_ptr, iq_no, field, count)  \
-	(octeon_dev_ptr->instr_queue[iq_no]->stats.field += count)
+#include "cn23xx_vf_device.h"
 
 struct iq_post_status {
 	int status;
@@ -71,9 +66,12 @@ int octeon_init_instr_queue(struct octeo
 	int numa_node = cpu_to_node(iq_no % num_online_cpus());
 
 	if (OCTEON_CN6XXX(oct))
-		conf = &(CFG_GET_IQ_CFG(CHIP_FIELD(oct, cn6xxx, conf)));
+		conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn6xxx)));
 	else if (OCTEON_CN23XX_PF(oct))
-		conf = &(CFG_GET_IQ_CFG(CHIP_FIELD(oct, cn23xx_pf, conf)));
+		conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn23xx_pf)));
+	else if (OCTEON_CN23XX_VF(oct))
+		conf = &(CFG_GET_IQ_CFG(CHIP_CONF(oct, cn23xx_vf)));
+
 	if (!conf) {
 		dev_err(&oct->pci_dev->dev, "Unsupported Chip %x\n",
 			oct->chip_id);
@@ -145,7 +143,7 @@ int octeon_init_instr_queue(struct octeo
 
 	spin_lock_init(&iq->iq_flush_running_lock);
 
-	oct->io_qmask.iq |= (1ULL << iq_no);
+	oct->io_qmask.iq |= BIT_ULL(iq_no);
 
 	/* Set the 32B/64B mode for each input queue */
 	oct->io_qmask.iq64B |= ((conf->instr_type == 64) << iq_no);
@@ -157,6 +155,8 @@ int octeon_init_instr_queue(struct octeo
 						     WQ_MEM_RECLAIM,
 						     0);
 	if (!oct->check_db_wq[iq_no].wq) {
+		vfree(iq->request_list);
+		iq->request_list = NULL;
 		lio_dma_free(oct, q_size, iq->base_addr, iq->base_addr_dma);
 		dev_err(&oct->pci_dev->dev, "check db wq create failed for iq %d\n",
 			iq_no);
@@ -183,10 +183,13 @@ int octeon_delete_instr_queue(struct oct
 
 	if (OCTEON_CN6XXX(oct))
 		desc_size =
-		    CFG_GET_IQ_INSTR_TYPE(CHIP_FIELD(oct, cn6xxx, conf));
+		    CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn6xxx));
 	else if (OCTEON_CN23XX_PF(oct))
 		desc_size =
-		    CFG_GET_IQ_INSTR_TYPE(CHIP_FIELD(oct, cn23xx_pf, conf));
+		    CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn23xx_pf));
+	else if (OCTEON_CN23XX_VF(oct))
+		desc_size =
+		    CFG_GET_IQ_INSTR_TYPE(CHIP_CONF(oct, cn23xx_vf));
 
 	vfree(iq->request_list);
 
@@ -239,7 +242,9 @@ int octeon_setup_iq(struct octeon_device
 	}
 
 	oct->num_iqs++;
-	oct->fn_list.enable_io_queues(oct);
+	if (oct->fn_list.enable_io_queues(oct))
+		return 1;
+
 	return 0;
 }
 
@@ -250,9 +255,8 @@ int lio_wait_for_instr_fetch(struct octe
 	do {
 		instr_cnt = 0;
 
-		/*for (i = 0; i < oct->num_iqs; i++) {*/
 		for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) {
-			if (!(oct->io_qmask.iq & (1ULL << i)))
+			if (!(oct->io_qmask.iq & BIT_ULL(i)))
 				continue;
 			pending =
 			    atomic_read(&oct->
@@ -319,7 +323,8 @@ __post_command2(struct octeon_instr_queu
 
 	/* "index" is returned, host_write_index is modified. */
 	st.index = iq->host_write_index;
-	INCR_INDEX_BY1(iq->host_write_index, iq->max_count);
+	iq->host_write_index = incr_index(iq->host_write_index, 1,
+					  iq->max_count);
 	iq->fill_cnt++;
 
 	/* Flush the command into memory. We need to be sure the data is in
@@ -389,7 +394,7 @@ lio_process_iq_request_list(struct octeo
 		case REQTYPE_SOFT_COMMAND:
 			sc = buf;
 
-			if (OCTEON_CN23XX_PF(oct))
+			if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct))
 				irh = (struct octeon_instr_irh *)
 					&sc->cmd.cmd3.irh;
 			else
@@ -434,7 +439,7 @@ lio_process_iq_request_list(struct octeo
 
  skip_this:
 		inst_count++;
-		INCR_INDEX_BY1(old, iq->max_count);
+		old = incr_index(old, 1, iq->max_count);
 
 		if ((napi_budget) && (inst_count >= napi_budget))
 			break;
@@ -577,8 +582,6 @@ octeon_send_command(struct octeon_device
 	/* This is only done here to expedite packets being flushed
 	 * for cases where there are no IQ completion interrupts.
 	 */
-	/*if (iq->do_auto_flush)*/
-	/*	octeon_flush_iq(oct, iq, 2, 0);*/
 
 	return st.status;
 }
@@ -604,7 +607,7 @@ octeon_prepare_soft_command(struct octeo
 
 	oct_cfg = octeon_get_conf(oct);
 
-	if (OCTEON_CN23XX_PF(oct)) {
+	if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) {
 		ih3 = (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
 
 		ih3->pkind = oct->instr_queue[sc->iq_no]->txpciq.s.pkind;
@@ -697,7 +700,7 @@ int octeon_send_soft_command(struct octe
 	struct octeon_instr_irh *irh;
 	u32 len;
 
-	if (OCTEON_CN23XX_PF(oct)) {
+	if (OCTEON_CN23XX_PF(oct) || OCTEON_CN23XX_VF(oct)) {
 		ih3 =  (struct octeon_instr_ih3 *)&sc->cmd.cmd3.ih3;
 		if (ih3->dlengsz) {
 			WARN_ON(!sc->dmadptr);
@@ -749,8 +752,10 @@ int octeon_setup_sc_buffer_pool(struct o
 			lio_dma_alloc(oct,
 				      SOFT_COMMAND_BUFFER_SIZE,
 					  (dma_addr_t *)&dma_addr);
-		if (!sc)
+		if (!sc) {
+			octeon_free_sc_buffer_pool(oct);
 			return 1;
+		}
 
 		sc->dma_addr = dma_addr;
 		sc->size = SOFT_COMMAND_BUFFER_SIZE;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.c	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -81,17 +78,14 @@ int lio_process_ordered_list(struct octe
 		spin_lock_bh(&ordered_sc_list->lock);
 
 		if (ordered_sc_list->head.next == &ordered_sc_list->head) {
-			/* ordered_sc_list is empty; there is
-			 * nothing to process
-			 */
-			spin_unlock_bh
-			    (&ordered_sc_list->lock);
+			spin_unlock_bh(&ordered_sc_list->lock);
 			return 1;
 		}
 
 		sc = (struct octeon_soft_command *)ordered_sc_list->
 		    head.next;
-		if (OCTEON_CN23XX_PF(octeon_dev)) {
+		if (OCTEON_CN23XX_PF(octeon_dev) ||
+		    OCTEON_CN23XX_VF(octeon_dev)) {
 			rdp = (struct octeon_instr_rdp *)&sc->cmd.cmd3.rdp;
 			rptr = sc->cmd.cmd3.rptr;
 		} else {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/liquidio/response_manager.h	2017-02-12 16:03:20.000000000 -0500
@@ -4,7 +4,7 @@
  * Contact: support@cavium.com
  *          Please include "LiquidIO" in the subject.
  *
- * Copyright (c) 2003-2015 Cavium, Inc.
+ * Copyright (c) 2003-2016 Cavium, Inc.
  *
  * 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
@@ -15,9 +15,6 @@
  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  * NONINFRINGEMENT.  See the GNU General Public License for more
  * details.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium, Inc. for more information
  **********************************************************************/
 
 /*! \file response_manager.h
@@ -85,7 +82,6 @@ enum {
 /**  A value of 0x00000000 indicates no error i.e. success */
 #define DRIVER_ERROR_NONE                 0x00000000
 
-/**  (Major number: 0x0000; Minor Number: 0x0001) */
 #define DRIVER_ERROR_REQ_PENDING          0x00000001
 #define DRIVER_ERROR_REQ_TIMEOUT          0x00000003
 #define DRIVER_ERROR_REQ_EINTR            0x00000004
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c	2017-02-12 16:03:20.000000000 -0500
@@ -645,16 +645,6 @@ static int octeon_mgmt_change_mtu(struct
 	struct octeon_mgmt *p = netdev_priv(netdev);
 	int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
 
-	/* Limit the MTU to make sure the ethernet packets are between
-	 * 64 bytes and 16383 bytes.
-	 */
-	if (size_without_fcs < 64 || size_without_fcs > 16383) {
-		dev_warn(p->dev, "MTU must be between %d and %d.\n",
-			 64 - OCTEON_MGMT_RX_HEADROOM,
-			 16383 - OCTEON_MGMT_RX_HEADROOM);
-		return -EINVAL;
-	}
-
 	netdev->mtu = new_mtu;
 
 	cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs);
@@ -1479,6 +1469,12 @@ static int octeon_mgmt_probe(struct plat
 	p->agl = (u64)devm_ioremap(&pdev->dev, p->agl_phys, p->agl_size);
 	p->agl_prt_ctl = (u64)devm_ioremap(&pdev->dev, p->agl_prt_ctl_phys,
 					   p->agl_prt_ctl_size);
+	if (!p->mix || !p->agl || !p->agl_prt_ctl) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		result = -ENOMEM;
+		goto err;
+	}
+
 	spin_lock_init(&p->lock);
 
 	skb_queue_head_init(&p->tx_list);
@@ -1491,6 +1487,9 @@ static int octeon_mgmt_probe(struct plat
 	netdev->netdev_ops = &octeon_mgmt_ops;
 	netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
 
+	netdev->min_mtu = 64 - OCTEON_MGMT_RX_HEADROOM;
+	netdev->max_mtu = 16383 - OCTEON_MGMT_RX_HEADROOM;
+
 	mac = of_get_mac_address(pdev->dev.of_node);
 
 	if (mac)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nic.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nic.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nic.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nic.h	2017-02-12 16:03:20.000000000 -0500
@@ -149,6 +149,12 @@ struct nicvf_rss_info {
 	u64 key[RSS_HASH_KEY_SIZE];
 } ____cacheline_aligned_in_smp;
 
+struct nicvf_pfc {
+	u8    autoneg;
+	u8    fc_rx;
+	u8    fc_tx;
+};
+
 enum rx_stats_reg_offset {
 	RX_OCTS = 0x0,
 	RX_UCAST = 0x1,
@@ -292,11 +298,13 @@ struct nicvf {
 	u8			node;
 	u8			cpi_alg;
 	bool			link_up;
+	u8			mac_type;
 	u8			duplex;
 	u32			speed;
 	bool			tns_mode;
 	bool			loopback_supported;
 	struct nicvf_rss_info	rss_info;
+	struct nicvf_pfc	pfc;
 	struct tasklet_struct	qs_err_task;
 	struct work_struct	reset_task;
 
@@ -357,6 +365,7 @@ struct nicvf {
 #define	NIC_MBOX_MSG_SNICVF_PTR		0x15	/* Send sqet nicvf ptr to PVF */
 #define	NIC_MBOX_MSG_LOOPBACK		0x16	/* Set interface in loopback */
 #define	NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17	/* Reset statistics counters */
+#define	NIC_MBOX_MSG_PFC		0x18	/* Pause frame control */
 #define	NIC_MBOX_MSG_CFG_DONE		0xF0	/* VF configuration done */
 #define	NIC_MBOX_MSG_SHUTDOWN		0xF1	/* VF is being shutdown */
 
@@ -446,6 +455,7 @@ struct bgx_stats_msg {
 /* Physical interface link status */
 struct bgx_link_status {
 	u8    msg;
+	u8    mac_type;
 	u8    link_up;
 	u8    duplex;
 	u32   speed;
@@ -498,6 +508,14 @@ struct reset_stat_cfg {
 	u16   sq_stat_mask;
 };
 
+struct pfc {
+	u8    msg;
+	u8    get; /* Get or set PFC settings */
+	u8    autoneg;
+	u8    fc_rx;
+	u8    fc_tx;
+};
+
 /* 128 bit shared memory between PF and each VF */
 union nic_mbx {
 	struct { u8 msg; }	msg;
@@ -516,6 +534,7 @@ union nic_mbx {
 	struct nicvf_ptr	nicvf;
 	struct set_loopback	lbk;
 	struct reset_stat_cfg	reset_stat;
+	struct pfc		pfc;
 };
 
 #define NIC_NODE_ID_MASK	0x03
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nic_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nic_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nic_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nic_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -809,6 +809,15 @@ static int nic_config_loopback(struct ni
 
 	bgx_lmac_internal_loopback(nic->node, bgx_idx, lmac_idx, lbk->enable);
 
+	/* Enable moving average calculation.
+	 * Keep the LVL/AVG delay to HW enforced minimum so that, not too many
+	 * packets sneek in between average calculations.
+	 */
+	nic_reg_write(nic, NIC_PF_CQ_AVG_CFG,
+		      (BIT_ULL(20) | 0x2ull << 14 | 0x1));
+	nic_reg_write(nic, NIC_PF_RRM_AVG_CFG,
+		      (BIT_ULL(20) | 0x3ull << 14 | 0x1));
+
 	return 0;
 }
 
@@ -889,6 +898,30 @@ static void nic_enable_vf(struct nicpf *
 	bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, enable);
 }
 
+static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg)
+{
+	int bgx, lmac;
+	struct pfc pfc;
+	union nic_mbx mbx = {};
+
+	if (vf >= nic->num_vf_en)
+		return;
+	bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+	lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+	if (cfg->get) {
+		bgx_lmac_get_pfc(nic->node, bgx, lmac, &pfc);
+		mbx.pfc.msg = NIC_MBOX_MSG_PFC;
+		mbx.pfc.autoneg = pfc.autoneg;
+		mbx.pfc.fc_rx = pfc.fc_rx;
+		mbx.pfc.fc_tx = pfc.fc_tx;
+		nic_send_msg_to_vf(nic, vf, &mbx);
+	} else {
+		bgx_lmac_set_pfc(nic->node, bgx, lmac, cfg);
+		nic_mbx_send_ack(nic, vf);
+	}
+}
+
 /* Interrupt handler to handle mailbox messages from VFs */
 static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
 {
@@ -1028,6 +1061,9 @@ static void nic_handle_mbx_intr(struct n
 	case NIC_MBOX_MSG_RESET_STAT_COUNTER:
 		ret = nic_reset_stat_counters(nic, vf, &mbx.reset_stat);
 		break;
+	case NIC_MBOX_MSG_PFC:
+		nic_pause_frame(nic, vf, &mbx.pfc);
+		goto unlock;
 	default:
 		dev_err(&nic->pdev->dev,
 			"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
@@ -1258,6 +1294,7 @@ static void nic_poll_for_link(struct wor
 			mbx.link_status.link_up = link.link_up;
 			mbx.link_status.duplex = link.duplex;
 			mbx.link_status.speed = link.speed;
+			mbx.link_status.mac_type = link.mac_type;
 			nic_send_msg_to_vf(nic, vf, &mbx);
 		}
 	}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -116,29 +116,65 @@ static const unsigned int nicvf_n_hw_sta
 static const unsigned int nicvf_n_drv_stats = ARRAY_SIZE(nicvf_drv_stats);
 static const unsigned int nicvf_n_queue_stats = ARRAY_SIZE(nicvf_queue_stats);
 
-static int nicvf_get_settings(struct net_device *netdev,
-			      struct ethtool_cmd *cmd)
+static int nicvf_get_link_ksettings(struct net_device *netdev,
+				    struct ethtool_link_ksettings *cmd)
 {
 	struct nicvf *nic = netdev_priv(netdev);
+	u32 supported, advertising;
 
-	cmd->supported = 0;
-	cmd->transceiver = XCVR_EXTERNAL;
+	supported = 0;
+	advertising = 0;
 
 	if (!nic->link_up) {
-		cmd->duplex = DUPLEX_UNKNOWN;
-		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
+		cmd->base.duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
 		return 0;
 	}
 
-	if (nic->speed <= 1000) {
-		cmd->port = PORT_MII;
-		cmd->autoneg = AUTONEG_ENABLE;
-	} else {
-		cmd->port = PORT_FIBRE;
-		cmd->autoneg = AUTONEG_DISABLE;
+	switch (nic->speed) {
+	case SPEED_1000:
+		cmd->base.port = PORT_MII | PORT_TP;
+		cmd->base.autoneg = AUTONEG_ENABLE;
+		supported |= SUPPORTED_MII | SUPPORTED_TP;
+		supported |= SUPPORTED_1000baseT_Full |
+				  SUPPORTED_1000baseT_Half |
+				  SUPPORTED_100baseT_Full  |
+				  SUPPORTED_100baseT_Half  |
+				  SUPPORTED_10baseT_Full   |
+				  SUPPORTED_10baseT_Half;
+		supported |= SUPPORTED_Autoneg;
+		advertising |= ADVERTISED_1000baseT_Full |
+				    ADVERTISED_1000baseT_Half |
+				    ADVERTISED_100baseT_Full  |
+				    ADVERTISED_100baseT_Half  |
+				    ADVERTISED_10baseT_Full   |
+				    ADVERTISED_10baseT_Half;
+		break;
+	case SPEED_10000:
+		if (nic->mac_type == BGX_MODE_RXAUI) {
+			cmd->base.port = PORT_TP;
+			supported |= SUPPORTED_TP;
+		} else {
+			cmd->base.port = PORT_FIBRE;
+			supported |= SUPPORTED_FIBRE;
+		}
+		cmd->base.autoneg = AUTONEG_DISABLE;
+		supported |= SUPPORTED_10000baseT_Full;
+		break;
+	case SPEED_40000:
+		cmd->base.port = PORT_FIBRE;
+		cmd->base.autoneg = AUTONEG_DISABLE;
+		supported |= SUPPORTED_FIBRE;
+		supported |= SUPPORTED_40000baseCR4_Full;
+		break;
 	}
-	cmd->duplex = nic->duplex;
-	ethtool_cmd_speed_set(cmd, nic->speed);
+	cmd->base.duplex = nic->duplex;
+	cmd->base.speed = nic->speed;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return 0;
 }
@@ -690,8 +726,56 @@ static int nicvf_set_channels(struct net
 	return err;
 }
 
+static void nicvf_get_pauseparam(struct net_device *dev,
+				 struct ethtool_pauseparam *pause)
+{
+	struct nicvf *nic = netdev_priv(dev);
+	union nic_mbx mbx = {};
+
+	/* Supported only for 10G/40G interfaces */
+	if ((nic->mac_type == BGX_MODE_SGMII) ||
+	    (nic->mac_type == BGX_MODE_QSGMII) ||
+	    (nic->mac_type == BGX_MODE_RGMII))
+		return;
+
+	mbx.pfc.msg = NIC_MBOX_MSG_PFC;
+	mbx.pfc.get = 1;
+	if (!nicvf_send_msg_to_pf(nic, &mbx)) {
+		pause->autoneg = nic->pfc.autoneg;
+		pause->rx_pause = nic->pfc.fc_rx;
+		pause->tx_pause = nic->pfc.fc_tx;
+	}
+}
+
+static int nicvf_set_pauseparam(struct net_device *dev,
+				struct ethtool_pauseparam *pause)
+{
+	struct nicvf *nic = netdev_priv(dev);
+	union nic_mbx mbx = {};
+
+	/* Supported only for 10G/40G interfaces */
+	if ((nic->mac_type == BGX_MODE_SGMII) ||
+	    (nic->mac_type == BGX_MODE_QSGMII) ||
+	    (nic->mac_type == BGX_MODE_RGMII))
+		return -EOPNOTSUPP;
+
+	if (pause->autoneg)
+		return -EOPNOTSUPP;
+
+	mbx.pfc.msg = NIC_MBOX_MSG_PFC;
+	mbx.pfc.get = 0;
+	mbx.pfc.fc_rx = pause->rx_pause;
+	mbx.pfc.fc_tx = pause->tx_pause;
+	if (nicvf_send_msg_to_pf(nic, &mbx))
+		return -EAGAIN;
+
+	nic->pfc.fc_rx = pause->rx_pause;
+	nic->pfc.fc_tx = pause->tx_pause;
+
+	return 0;
+}
+
 static const struct ethtool_ops nicvf_ethtool_ops = {
-	.get_settings		= nicvf_get_settings,
 	.get_link		= nicvf_get_link,
 	.get_drvinfo		= nicvf_get_drvinfo,
 	.get_msglevel		= nicvf_get_msglevel,
@@ -711,7 +795,10 @@ static const struct ethtool_ops nicvf_et
 	.set_rxfh		= nicvf_set_rxfh,
 	.get_channels		= nicvf_get_channels,
 	.set_channels		= nicvf_set_channels,
+	.get_pauseparam         = nicvf_get_pauseparam,
+	.set_pauseparam         = nicvf_set_pauseparam,
 	.get_ts_info		= ethtool_op_get_ts_info,
+	.get_link_ksettings	= nicvf_get_link_ksettings,
 };
 
 void nicvf_set_ethtool_ops(struct net_device *netdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -221,6 +221,7 @@ static void  nicvf_handle_mbx_intr(struc
 		nic->link_up = mbx.link_status.link_up;
 		nic->duplex = mbx.link_status.duplex;
 		nic->speed = mbx.link_status.speed;
+		nic->mac_type = mbx.link_status.mac_type;
 		if (nic->link_up) {
 			netdev_info(nic->netdev, "%s: Link is Up %d Mbps %s\n",
 				    nic->netdev->name, nic->speed,
@@ -255,6 +256,12 @@ static void  nicvf_handle_mbx_intr(struc
 		nic->pnicvf = (struct nicvf *)mbx.nicvf.nicvf;
 		nic->pf_acked = true;
 		break;
+	case NIC_MBOX_MSG_PFC:
+		nic->pfc.autoneg = mbx.pfc.autoneg;
+		nic->pfc.fc_rx = mbx.pfc.fc_rx;
+		nic->pfc.fc_tx = mbx.pfc.fc_tx;
+		nic->pf_acked = true;
+		break;
 	default:
 		netdev_err(nic->netdev,
 			   "Invalid message from PF, msg 0x%x\n", mbx.msg.msg);
@@ -637,6 +644,7 @@ static int nicvf_cq_intr_handler(struct
 	struct cmp_queue *cq = &qs->cq[cq_idx];
 	struct cqe_rx_t *cq_desc;
 	struct netdev_queue *txq;
+	struct snd_queue *sq;
 	unsigned int tx_pkts = 0, tx_bytes = 0;
 
 	spin_lock_bh(&cq->lock);
@@ -702,16 +710,20 @@ loop:
 
 done:
 	/* Wakeup TXQ if its stopped earlier due to SQ full */
-	if (tx_done) {
+	sq = &nic->qs->sq[cq_idx];
+	if (tx_done ||
+	    (atomic_read(&sq->free_cnt) >= MIN_SQ_DESC_PER_PKT_XMIT)) {
 		netdev = nic->pnicvf->netdev;
 		txq = netdev_get_tx_queue(netdev,
 					  nicvf_netdev_qidx(nic, cq_idx));
 		if (tx_pkts)
 			netdev_tx_completed_queue(txq, tx_pkts, tx_bytes);
 
-		nic = nic->pnicvf;
+		/* To read updated queue and carrier status */
+		smp_mb();
 		if (netif_tx_queue_stopped(txq) && netif_carrier_ok(netdev)) {
-			netif_tx_start_queue(txq);
+			netif_tx_wake_queue(txq);
+			nic = nic->pnicvf;
 			this_cpu_inc(nic->drv_stats->txq_wake);
 			if (netif_msg_tx_err(nic))
 				netdev_warn(netdev,
@@ -1047,6 +1059,9 @@ static netdev_tx_t nicvf_xmit(struct sk_
 	struct nicvf *nic = netdev_priv(netdev);
 	int qid = skb_get_queue_mapping(skb);
 	struct netdev_queue *txq = netdev_get_tx_queue(netdev, qid);
+	struct nicvf *snic;
+	struct snd_queue *sq;
+	int tmp;
 
 	/* Check for minimum packet length */
 	if (skb->len <= ETH_HLEN) {
@@ -1054,13 +1069,39 @@ static netdev_tx_t nicvf_xmit(struct sk_
 		return NETDEV_TX_OK;
 	}
 
-	if (!netif_tx_queue_stopped(txq) && !nicvf_sq_append_skb(nic, skb)) {
+	snic = nic;
+	/* Get secondary Qset's SQ structure */
+	if (qid >= MAX_SND_QUEUES_PER_QS) {
+		tmp = qid / MAX_SND_QUEUES_PER_QS;
+		snic = (struct nicvf *)nic->snicvf[tmp - 1];
+		if (!snic) {
+			netdev_warn(nic->netdev,
+				    "Secondary Qset#%d's ptr not initialized\n",
+				    tmp - 1);
+			dev_kfree_skb(skb);
+			return NETDEV_TX_OK;
+		}
+		qid = qid % MAX_SND_QUEUES_PER_QS;
+	}
+
+	sq = &snic->qs->sq[qid];
+	if (!netif_tx_queue_stopped(txq) &&
+	    !nicvf_sq_append_skb(snic, sq, skb, qid)) {
 		netif_tx_stop_queue(txq);
-		this_cpu_inc(nic->drv_stats->txq_stop);
-		if (netif_msg_tx_err(nic))
-			netdev_warn(netdev,
-				    "%s: Transmit ring full, stopping SQ%d\n",
-				    netdev->name, qid);
+
+		/* Barrier, so that stop_queue visible to other cpus */
+		smp_mb();
+
+		/* Check again, incase another cpu freed descriptors */
+		if (atomic_read(&sq->free_cnt) > MIN_SQ_DESC_PER_PKT_XMIT) {
+			netif_tx_wake_queue(txq);
+		} else {
+			this_cpu_inc(nic->drv_stats->txq_stop);
+			if (netif_msg_tx_err(nic))
+				netdev_warn(netdev,
+					    "%s: Transmit ring full, stopping SQ%d\n",
+					    netdev->name, qid);
+		}
 		return NETDEV_TX_BUSY;
 	}
 
@@ -1291,20 +1332,17 @@ napi_del:
 static int nicvf_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct nicvf *nic = netdev_priv(netdev);
-
-	if (new_mtu > NIC_HW_MAX_FRS)
-		return -EINVAL;
-
-	if (new_mtu < NIC_HW_MIN_FRS)
-		return -EINVAL;
+	int orig_mtu = netdev->mtu;
 
 	netdev->mtu = new_mtu;
 
 	if (!netif_running(netdev))
 		return 0;
 
-	if (nicvf_update_hw_max_frs(nic, new_mtu))
+	if (nicvf_update_hw_max_frs(nic, new_mtu)) {
+		netdev->mtu = orig_mtu;
 		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -1631,6 +1669,10 @@ static int nicvf_probe(struct pci_dev *p
 	netdev->netdev_ops = &nicvf_netdev_ops;
 	netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
 
+	/* MTU range: 64 - 9200 */
+	netdev->min_mtu = NIC_HW_MIN_FRS;
+	netdev->max_mtu = NIC_HW_MAX_FRS;
+
 	INIT_WORK(&nic->reset_task, nicvf_reset_task);
 
 	err = register_netdev(netdev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.c	2017-02-12 16:03:20.000000000 -0500
@@ -544,14 +544,18 @@ static void nicvf_rcv_queue_config(struc
 	nicvf_send_msg_to_pf(nic, &mbx);
 
 	mbx.rq.msg = NIC_MBOX_MSG_RQ_BP_CFG;
-	mbx.rq.cfg = (1ULL << 63) | (1ULL << 62) | (qs->vnic_id << 0);
+	mbx.rq.cfg = BIT_ULL(63) | BIT_ULL(62) |
+		     (RQ_PASS_RBDR_LVL << 16) | (RQ_PASS_CQ_LVL << 8) |
+		     (qs->vnic_id << 0);
 	nicvf_send_msg_to_pf(nic, &mbx);
 
 	/* RQ drop config
 	 * Enable CQ drop to reserve sufficient CQEs for all tx packets
 	 */
 	mbx.rq.msg = NIC_MBOX_MSG_RQ_DROP_CFG;
-	mbx.rq.cfg = (1ULL << 62) | (RQ_CQ_DROP << 8);
+	mbx.rq.cfg = BIT_ULL(63) | BIT_ULL(62) |
+		     (RQ_PASS_RBDR_LVL << 40) | (RQ_DROP_RBDR_LVL << 32) |
+		     (RQ_PASS_CQ_LVL << 16) | (RQ_DROP_CQ_LVL << 8);
 	nicvf_send_msg_to_pf(nic, &mbx);
 
 	if (!nic->sqs_mode && (qidx == 0)) {
@@ -650,6 +654,7 @@ static void nicvf_snd_queue_config(struc
 	sq_cfg.ldwb = 0;
 	sq_cfg.qsize = SND_QSIZE;
 	sq_cfg.tstmp_bgx_intf = 0;
+	sq_cfg.cq_limit = 0;
 	nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, *(u64 *)&sq_cfg);
 
 	/* Set threshold value for interrupt generation */
@@ -1185,30 +1190,12 @@ static int nicvf_sq_append_tso(struct ni
 }
 
 /* Append an skb to a SQ for packet transfer. */
-int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb)
+int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
+			struct sk_buff *skb, u8 sq_num)
 {
 	int i, size;
 	int subdesc_cnt, tso_sqe = 0;
-	int sq_num, qentry;
-	struct queue_set *qs;
-	struct snd_queue *sq;
-
-	sq_num = skb_get_queue_mapping(skb);
-	if (sq_num >= MAX_SND_QUEUES_PER_QS) {
-		/* Get secondary Qset's SQ structure */
-		i = sq_num / MAX_SND_QUEUES_PER_QS;
-		if (!nic->snicvf[i - 1]) {
-			netdev_warn(nic->netdev,
-				    "Secondary Qset#%d's ptr not initialized\n",
-				    i - 1);
-			return 1;
-		}
-		nic = (struct nicvf *)nic->snicvf[i - 1];
-		sq_num = sq_num % MAX_SND_QUEUES_PER_QS;
-	}
-
-	qs = nic->qs;
-	sq = &qs->sq[sq_num];
+	int qentry;
 
 	subdesc_cnt = nicvf_sq_subdesc_required(nic, skb);
 	if (subdesc_cnt > atomic_read(&sq->free_cnt))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/nicvf_queues.h	2017-02-12 16:03:20.000000000 -0500
@@ -85,12 +85,26 @@
 
 #define MAX_CQES_FOR_TX		((SND_QUEUE_LEN / MIN_SQ_DESC_PER_PKT_XMIT) * \
 				 MAX_CQE_PER_PKT_XMIT)
-/* Calculate number of CQEs to reserve for all SQEs.
- * Its 1/256th level of CQ size.
- * '+ 1' to account for pipelining
+
+/* RED and Backpressure levels of CQ for pkt reception
+ * For CQ, level is a measure of emptiness i.e 0x0 means full
+ * eg: For CQ of size 4K, and for pass/drop levels of 160/144
+ * HW accepts pkt if unused CQE >= 2560
+ * RED accepts pkt if unused CQE < 2304 & >= 2560
+ * DROPs pkts if unused CQE < 2304
  */
-#define RQ_CQ_DROP		((256 / (CMP_QUEUE_LEN / \
-				 (CMP_QUEUE_LEN - MAX_CQES_FOR_TX))) + 1)
+#define RQ_PASS_CQ_LVL		160ULL
+#define RQ_DROP_CQ_LVL		144ULL
+
+/* RED and Backpressure levels of RBDR for pkt reception
+ * For RBDR, level is a measure of fullness i.e 0x0 means empty
+ * eg: For RBDR of size 8K, and for pass/drop levels of 4/0
+ * HW accepts pkt if unused RBs >= 256
+ * RED accepts pkt if unused RBs < 256 & >= 0
+ * DROPs pkts if unused RBs < 0
+ */
+#define RQ_PASS_RBDR_LVL	8ULL
+#define RQ_DROP_RBDR_LVL	0ULL
 
 /* Descriptor size in bytes */
 #define SND_QUEUE_DESC_SIZE	16
@@ -292,7 +306,8 @@ void nicvf_sq_disable(struct nicvf *nic,
 void nicvf_put_sq_desc(struct snd_queue *sq, int desc_cnt);
 void nicvf_sq_free_used_descs(struct net_device *netdev,
 			      struct snd_queue *sq, int qidx);
-int nicvf_sq_append_skb(struct nicvf *nic, struct sk_buff *skb);
+int nicvf_sq_append_skb(struct nicvf *nic, struct snd_queue *sq,
+			struct sk_buff *skb, u8 sq_num);
 
 struct sk_buff *nicvf_get_rcv_skb(struct nicvf *nic, struct cqe_rx_t *cqe_rx);
 void nicvf_rbdr_task(unsigned long data);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/q_struct.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/q_struct.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/q_struct.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/q_struct.h	2017-02-12 16:03:20.000000000 -0500
@@ -624,7 +624,9 @@ struct cq_cfg {
 
 struct sq_cfg {
 #if defined(__BIG_ENDIAN_BITFIELD)
-	u64 reserved_20_63:44;
+	u64 reserved_32_63:32;
+	u64 cq_limit:8;
+	u64 reserved_20_23:4;
 	u64 ena:1;
 	u64 reserved_18_18:1;
 	u64 reset:1;
@@ -642,7 +644,9 @@ struct sq_cfg {
 	u64 reset:1;
 	u64 reserved_18_18:1;
 	u64 ena:1;
-	u64 reserved_20_63:44;
+	u64 reserved_20_23:4;
+	u64 cq_limit:8;
+	u64 reserved_32_63:32;
 #endif
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@ struct lmac {
 	u8                      lmac_type;
 	u8                      lane_to_sds;
 	bool                    use_training;
+	bool                    autoneg;
 	bool			link_up;
 	int			lmacid; /* ID within BGX */
 	int			lmacid_bd; /* ID on board */
@@ -47,8 +48,9 @@ struct lmac {
 struct bgx {
 	u8			bgx_id;
 	struct	lmac		lmac[MAX_LMAC_PER_BGX];
-	int			lmac_count;
+	u8			lmac_count;
 	u8			max_lmac;
+	u8                      acpi_lmac_idx;
 	void __iomem		*reg_base;
 	struct pci_dev		*pdev;
 	bool                    is_dlm;
@@ -161,6 +163,7 @@ void bgx_get_lmac_link_state(int node, i
 		return;
 
 	lmac = &bgx->lmac[lmacid];
+	link->mac_type = lmac->lmac_type;
 	link->link_up = lmac->link_up;
 	link->duplex = lmac->last_duplex;
 	link->speed = lmac->last_speed;
@@ -211,6 +214,47 @@ void bgx_lmac_rx_tx_enable(int node, int
 }
 EXPORT_SYMBOL(bgx_lmac_rx_tx_enable);
 
+void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause)
+{
+	struct pfc *pfc = (struct pfc *)pause;
+	struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
+	struct lmac *lmac;
+	u64 cfg;
+
+	if (!bgx)
+		return;
+	lmac = &bgx->lmac[lmacid];
+	if (lmac->is_sgmii)
+		return;
+
+	cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_CBFC_CTL);
+	pfc->fc_rx = cfg & RX_EN;
+	pfc->fc_tx = cfg & TX_EN;
+	pfc->autoneg = 0;
+}
+EXPORT_SYMBOL(bgx_lmac_get_pfc);
+
+void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause)
+{
+	struct pfc *pfc = (struct pfc *)pause;
+	struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
+	struct lmac *lmac;
+	u64 cfg;
+
+	if (!bgx)
+		return;
+	lmac = &bgx->lmac[lmacid];
+	if (lmac->is_sgmii)
+		return;
+
+	cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_CBFC_CTL);
+	cfg &= ~(RX_EN | TX_EN);
+	cfg |= (pfc->fc_rx ? RX_EN : 0x00);
+	cfg |= (pfc->fc_tx ? TX_EN : 0x00);
+	bgx_reg_write(bgx, lmacid, BGX_SMUX_CBFC_CTL, cfg);
+}
+EXPORT_SYMBOL(bgx_lmac_set_pfc);
+
 static void bgx_sgmii_change_link_state(struct lmac *lmac)
 {
 	struct bgx *bgx = lmac->bgx;
@@ -418,7 +462,17 @@ static int bgx_lmac_sgmii_init(struct bg
 	/* power down, reset autoneg, autoneg enable */
 	cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MRX_CTL);
 	cfg &= ~PCS_MRX_CTL_PWR_DN;
-	cfg |= (PCS_MRX_CTL_RST_AN | PCS_MRX_CTL_AN_EN);
+	cfg |= PCS_MRX_CTL_RST_AN;
+	if (lmac->phydev) {
+		cfg |= PCS_MRX_CTL_AN_EN;
+	} else {
+		/* In scenarios where PHY driver is not present or it's a
+		 * non-standard PHY, FW sets AN_EN to inform Linux driver
+		 * to do auto-neg and link polling or not.
+		 */
+		if (cfg & PCS_MRX_CTL_AN_EN)
+			lmac->autoneg = true;
+	}
 	bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg);
 
 	if (lmac->lmac_type == BGX_MODE_QSGMII) {
@@ -429,7 +483,7 @@ static int bgx_lmac_sgmii_init(struct bg
 		return 0;
 	}
 
-	if (lmac->lmac_type == BGX_MODE_SGMII) {
+	if ((lmac->lmac_type == BGX_MODE_SGMII) && lmac->phydev) {
 		if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
 				 PCS_MRX_STATUS_AN_CPT, false)) {
 			dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
@@ -524,6 +578,18 @@ static int bgx_lmac_xaui_init(struct bgx
 	cfg |= SMU_TX_CTL_DIC_EN;
 	bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_CTL, cfg);
 
+	/* Enable receive and transmission of pause frames */
+	bgx_reg_write(bgx, lmacid, BGX_SMUX_CBFC_CTL, ((0xffffULL << 32) |
+		      BCK_EN | DRP_EN | TX_EN | RX_EN));
+	/* Configure pause time and interval */
+	bgx_reg_write(bgx, lmacid,
+		      BGX_SMUX_TX_PAUSE_PKT_TIME, DEFAULT_PAUSE_TIME);
+	cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_TX_PAUSE_PKT_INTERVAL);
+	cfg &= ~0xFFFFull;
+	bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_PAUSE_PKT_INTERVAL,
+		      cfg | (DEFAULT_PAUSE_TIME - 0x1000));
+	bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_PAUSE_ZERO, 0x01);
+
 	/* take lmac_count into account */
 	bgx_reg_modify(bgx, lmacid, BGX_SMUX_TX_THRESH, (0x100 - 1));
 	/* max packet size */
@@ -623,12 +689,71 @@ static int bgx_xaui_check_link(struct lm
 	return -1;
 }
 
+static void bgx_poll_for_sgmii_link(struct lmac *lmac)
+{
+	u64 pcs_link, an_result;
+	u8 speed;
+
+	pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
+				BGX_GMP_PCS_MRX_STATUS);
+
+	/*Link state bit is sticky, read it again*/
+	if (!(pcs_link & PCS_MRX_STATUS_LINK))
+		pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
+					BGX_GMP_PCS_MRX_STATUS);
+
+	if (bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_GMP_PCS_MRX_STATUS,
+			 PCS_MRX_STATUS_AN_CPT, false)) {
+		lmac->link_up = false;
+		lmac->last_speed = SPEED_UNKNOWN;
+		lmac->last_duplex = DUPLEX_UNKNOWN;
+		goto next_poll;
+	}
+
+	lmac->link_up = ((pcs_link & PCS_MRX_STATUS_LINK) != 0) ? true : false;
+	an_result = bgx_reg_read(lmac->bgx, lmac->lmacid,
+				 BGX_GMP_PCS_ANX_AN_RESULTS);
+
+	speed = (an_result >> 3) & 0x3;
+	lmac->last_duplex = (an_result >> 1) & 0x1;
+	switch (speed) {
+	case 0:
+		lmac->last_speed = 10;
+		break;
+	case 1:
+		lmac->last_speed = 100;
+		break;
+	case 2:
+		lmac->last_speed = 1000;
+		break;
+	default:
+		lmac->link_up = false;
+		lmac->last_speed = SPEED_UNKNOWN;
+		lmac->last_duplex = DUPLEX_UNKNOWN;
+		break;
+	}
+
+next_poll:
+
+	if (lmac->last_link != lmac->link_up) {
+		if (lmac->link_up)
+			bgx_sgmii_change_link_state(lmac);
+		lmac->last_link = lmac->link_up;
+	}
+
+	queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 3);
+}
+
 static void bgx_poll_for_link(struct work_struct *work)
 {
 	struct lmac *lmac;
 	u64 spu_link, smu_link;
 
 	lmac = container_of(work, struct lmac, dwork.work);
+	if (lmac->is_sgmii) {
+		bgx_poll_for_sgmii_link(lmac);
+		return;
+	}
 
 	/* Receive link is latching low. Force it high and verify it */
 	bgx_reg_modify(lmac->bgx, lmac->lmacid,
@@ -720,9 +845,21 @@ static int bgx_lmac_enable(struct bgx *b
 	    (lmac->lmac_type != BGX_MODE_XLAUI) &&
 	    (lmac->lmac_type != BGX_MODE_40G_KR) &&
 	    (lmac->lmac_type != BGX_MODE_10G_KR)) {
-		if (!lmac->phydev)
-			return -ENODEV;
-
+		if (!lmac->phydev) {
+			if (lmac->autoneg) {
+				bgx_reg_write(bgx, lmacid,
+					      BGX_GMP_PCS_LINKX_TIMER,
+					      PCS_LINKX_TIMER_COUNT);
+				goto poll;
+			} else {
+				/* Default to below link speed and duplex */
+				lmac->link_up = true;
+				lmac->last_speed = 1000;
+				lmac->last_duplex = 1;
+				bgx_sgmii_change_link_state(lmac);
+				return 0;
+			}
+		}
 		lmac->phydev->dev_flags = 0;
 
 		if (phy_connect_direct(&lmac->netdev, lmac->phydev,
@@ -731,15 +868,17 @@ static int bgx_lmac_enable(struct bgx *b
 			return -ENODEV;
 
 		phy_start_aneg(lmac->phydev);
-	} else {
-		lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
-						   WQ_MEM_RECLAIM, 1);
-		if (!lmac->check_link)
-			return -ENOMEM;
-		INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
-		queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
+		return 0;
 	}
 
+poll:
+	lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
+					   WQ_MEM_RECLAIM, 1);
+	if (!lmac->check_link)
+		return -ENOMEM;
+	INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
+	queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
+
 	return 0;
 }
 
@@ -970,11 +1109,25 @@ static void bgx_set_lmac_config(struct b
 		lmac_set_training(bgx, lmac, lmac->lmacid);
 		lmac_set_lane2sds(bgx, lmac);
 
-		/* Set LMAC type of other lmac on same DLM i.e LMAC 1/3 */
 		olmac = &bgx->lmac[idx + 1];
-		olmac->lmac_type = lmac->lmac_type;
+		/*  Check if other LMAC on the same DLM is already configured by
+		 *  firmware, if so use the same config or else set as same, as
+		 *  that of LMAC 0/2.
+		 *  This check is needed as on 80xx only one lane of each of the
+		 *  DLM of BGX0 is used, so have to rely on firmware for
+		 *  distingushing 80xx from 81xx.
+		 */
+		cmr_cfg = bgx_reg_read(bgx, idx + 1, BGX_CMRX_CFG);
+		lmac_type = (u8)((cmr_cfg >> 8) & 0x07);
+		lane_to_sds = (u8)(cmr_cfg & 0xFF);
+		if ((lmac_type == 0) && (lane_to_sds == 0xE4)) {
+			olmac->lmac_type = lmac->lmac_type;
+			lmac_set_lane2sds(bgx, olmac);
+		} else {
+			olmac->lmac_type = lmac_type;
+			olmac->lane_to_sds = lane_to_sds;
+		}
 		lmac_set_training(bgx, olmac, olmac->lmacid);
-		lmac_set_lane2sds(bgx, olmac);
 	}
 }
 
@@ -1075,13 +1228,13 @@ static acpi_status bgx_acpi_register_phy
 	if (acpi_bus_get_device(handle, &adev))
 		goto out;
 
-	acpi_get_mac_address(dev, adev, bgx->lmac[bgx->lmac_count].mac);
+	acpi_get_mac_address(dev, adev, bgx->lmac[bgx->acpi_lmac_idx].mac);
 
-	SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, dev);
+	SET_NETDEV_DEV(&bgx->lmac[bgx->acpi_lmac_idx].netdev, dev);
 
-	bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count;
+	bgx->lmac[bgx->acpi_lmac_idx].lmacid = bgx->acpi_lmac_idx;
+	bgx->acpi_lmac_idx++; /* move to next LMAC */
 out:
-	bgx->lmac_count++;
 	return AE_OK;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/thunder_bgx.h	2017-02-12 16:03:20.000000000 -0500
@@ -27,6 +27,7 @@
 #define    MAX_BGX_CHANS_PER_LMAC		16
 #define    MAX_DMAC_PER_LMAC			8
 #define    MAX_FRAME_SIZE			9216
+#define    DEFAULT_PAUSE_TIME			0xFFFF
 
 #define	   BGX_ID_MASK				0x3
 
@@ -126,7 +127,10 @@
 #define  SMU_RX_CTL_STATUS			(3ull << 0)
 #define BGX_SMUX_TX_APPEND		0x20100
 #define  SMU_TX_APPEND_FCS_D			BIT_ULL(2)
+#define BGX_SMUX_TX_PAUSE_PKT_TIME	0x20110
 #define BGX_SMUX_TX_MIN_PKT		0x20118
+#define BGX_SMUX_TX_PAUSE_PKT_INTERVAL	0x20120
+#define BGX_SMUX_TX_PAUSE_ZERO		0x20138
 #define BGX_SMUX_TX_INT			0x20140
 #define BGX_SMUX_TX_CTL			0x20178
 #define  SMU_TX_CTL_DIC_EN			BIT_ULL(0)
@@ -136,6 +140,11 @@
 #define BGX_SMUX_CTL			0x20200
 #define  SMU_CTL_RX_IDLE			BIT_ULL(0)
 #define  SMU_CTL_TX_IDLE			BIT_ULL(1)
+#define	BGX_SMUX_CBFC_CTL		0x20218
+#define	RX_EN					BIT_ULL(0)
+#define	TX_EN					BIT_ULL(1)
+#define	BCK_EN					BIT_ULL(2)
+#define	DRP_EN					BIT_ULL(3)
 
 #define BGX_GMP_PCS_MRX_CTL		0x30000
 #define	 PCS_MRX_CTL_RST_AN			BIT_ULL(9)
@@ -144,10 +153,15 @@
 #define	 PCS_MRX_CTL_LOOPBACK1			BIT_ULL(14)
 #define	 PCS_MRX_CTL_RESET			BIT_ULL(15)
 #define BGX_GMP_PCS_MRX_STATUS		0x30008
+#define	 PCS_MRX_STATUS_LINK			BIT_ULL(2)
 #define	 PCS_MRX_STATUS_AN_CPT			BIT_ULL(5)
+#define BGX_GMP_PCS_ANX_ADV		0x30010
 #define BGX_GMP_PCS_ANX_AN_RESULTS	0x30020
+#define BGX_GMP_PCS_LINKX_TIMER		0x30040
+#define PCS_LINKX_TIMER_COUNT			0x1E84
 #define BGX_GMP_PCS_SGM_AN_ADV		0x30068
 #define BGX_GMP_PCS_MISCX_CTL		0x30078
+#define  PCS_MISC_CTL_MODE			BIT_ULL(8)
 #define  PCS_MISC_CTL_DISP_EN			BIT_ULL(13)
 #define  PCS_MISC_CTL_GMX_ENO			BIT_ULL(11)
 #define  PCS_MISC_CTL_SAMP_PT_MASK	0x7Full
@@ -207,6 +221,9 @@ void bgx_set_lmac_mac(int node, int bgx_
 void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status);
 void bgx_lmac_internal_loopback(int node, int bgx_idx,
 				int lmac_idx, bool enable);
+void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause);
+void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause);
+
 void xcv_init_hw(void);
 void xcv_setup_link(bool link_up, int link_speed);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/thunder_xcv.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/thunder_xcv.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cavium/thunder/thunder_xcv.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cavium/thunder/thunder_xcv.c	2017-02-12 16:03:20.000000000 -0500
@@ -116,8 +116,7 @@ void xcv_setup_link(bool link_up, int li
 	int speed = 2;
 
 	if (!xcv) {
-		dev_err(&xcv->pdev->dev,
-			"XCV init not done, probe may have failed\n");
+		pr_err("XCV init not done, probe may have failed\n");
 		return;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/common.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/common.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/common.h	2017-02-12 16:03:20.000000000 -0500
@@ -85,6 +85,11 @@ struct t1_rx_mode {
 #define SPEED_INVALID 0xffff
 #define DUPLEX_INVALID 0xff
 
+/* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */
+#define PM3393_MAX_FRAME_SIZE 9600
+
+#define VSC7326_MAX_MTU 9600
+
 enum {
 	CHBT_BOARD_N110,
 	CHBT_BOARD_N210,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/cxgb2.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/cxgb2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/cxgb2.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 #include <linux/mii.h>
 #include <linux/sockios.h>
 #include <linux/dma-mapping.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "cpl5_cmd.h"
 #include "regs.h"
@@ -568,28 +568,33 @@ static void get_regs(struct net_device *
 	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)
+static int get_link_ksettings(struct net_device *dev,
+			      struct ethtool_link_ksettings *cmd)
 {
 	struct adapter *adapter = dev->ml_priv;
 	struct port_info *p = &adapter->port[dev->if_port];
+	u32 supported, advertising;
 
-	cmd->supported = p->link_config.supported;
-	cmd->advertising = p->link_config.advertising;
+	supported = p->link_config.supported;
+	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;
+		cmd->base.speed = p->link_config.speed;
+		cmd->base.duplex = p->link_config.duplex;
 	} else {
-		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
-		cmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 
-	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;
+	cmd->base.port = (supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
+	cmd->base.phy_address = p->phy->mdio.prtad;
+	cmd->base.autoneg = p->link_config.autoneg;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
+
 	return 0;
 }
 
@@ -628,36 +633,41 @@ static int speed_duplex_to_caps(int spee
 		      ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
 		      ADVERTISED_10000baseT_Full)
 
-static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int set_link_ksettings(struct net_device *dev,
+			      const struct ethtool_link_ksettings *cmd)
 {
 	struct adapter *adapter = dev->ml_priv;
 	struct port_info *p = &adapter->port[dev->if_port];
 	struct link_config *lc = &p->link_config;
+	u32 advertising;
+
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						cmd->link_modes.advertising);
 
 	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 (cmd->base.autoneg == AUTONEG_DISABLE) {
+		u32 speed = cmd->base.speed;
+		int cap = speed_duplex_to_caps(speed, cmd->base.duplex);
 
 		if (!(lc->supported & cap) || (speed == SPEED_1000))
 			return -EINVAL;
 		lc->requested_speed = speed;
-		lc->requested_duplex = cmd->duplex;
+		lc->requested_duplex = cmd->base.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)
+		advertising &= ADVERTISED_MASK;
+		if (advertising & (advertising - 1))
+			advertising = lc->supported;
+		advertising &= lc->supported;
+		if (!advertising)
 			return -EINVAL;
 		lc->requested_speed = SPEED_INVALID;
 		lc->requested_duplex = DUPLEX_INVALID;
-		lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
+		lc->advertising = advertising | ADVERTISED_Autoneg;
 	}
-	lc->autoneg = cmd->autoneg;
+	lc->autoneg = cmd->base.autoneg;
 	if (netif_running(dev))
 		t1_link_start(p->phy, p->mac, lc);
 	return 0;
@@ -788,8 +798,6 @@ static int get_eeprom(struct net_device
 }
 
 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,
@@ -807,6 +815,8 @@ static const struct ethtool_ops t1_ethto
 	.get_ethtool_stats = get_stats,
 	.get_regs_len      = get_regs_len,
 	.get_regs          = get_regs,
+	.get_link_ksettings = get_link_ksettings,
+	.set_link_ksettings = set_link_ksettings,
 };
 
 static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
@@ -825,8 +835,6 @@ static int t1_change_mtu(struct net_devi
 
 	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;
@@ -1101,6 +1109,22 @@ static int init_one(struct pci_dev *pdev
 		netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
 
 		netdev->ethtool_ops = &t1_ethtool_ops;
+
+		switch (bi->board) {
+		case CHBT_BOARD_CHT110:
+		case CHBT_BOARD_N110:
+		case CHBT_BOARD_N210:
+		case CHBT_BOARD_CHT210:
+			netdev->max_mtu = PM3393_MAX_FRAME_SIZE -
+					  (ETH_HLEN + ETH_FCS_LEN);
+			break;
+		case CHBT_BOARD_CHN204:
+			netdev->max_mtu = VSC7326_MAX_MTU;
+			break;
+		default:
+			netdev->max_mtu = ETH_DATA_LEN;
+			break;
+		}
 	}
 
 	if (t1_init_sw_modules(adapter, bi) < 0) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/pm3393.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/pm3393.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/pm3393.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/pm3393.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,9 +47,6 @@
 
 #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 | \
@@ -331,10 +328,7 @@ static int pm3393_set_mtu(struct cmac *c
 {
 	int enabled = cmac->instance->enabled;
 
-	/* MAX_FRAME_SIZE includes header + FCS, mtu doesn't */
-	mtu += 14 + 4;
-	if (mtu > MAX_FRAME_SIZE)
-		return -EINVAL;
+	mtu += ETH_HLEN + ETH_FCS_LEN;
 
 	/* Disable Rx/Tx MAC before configuring it. */
 	if (enabled)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/vsc7326.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/vsc7326.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb/vsc7326.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb/vsc7326.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,8 +11,6 @@
 /* 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
@@ -452,9 +450,6 @@ static int mac_set_mtu(struct cmac *mac,
 {
 	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;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c	2016-12-11 17:49:35.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c	2017-02-12 17:38:08.000000000 -0500
@@ -50,7 +50,7 @@
 #include <linux/stringify.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "common.h"
 #include "cxgb3_ioctl.h"
@@ -1794,27 +1794,31 @@ static int set_phys_id(struct net_device
 	return 0;
 }
 
-static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int get_link_ksettings(struct net_device *dev,
+			      struct ethtool_link_ksettings *cmd)
 {
 	struct port_info *p = netdev_priv(dev);
+	u32 supported;
 
-	cmd->supported = p->link_config.supported;
-	cmd->advertising = p->link_config.advertising;
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						p->link_config.supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.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;
+		cmd->base.speed = p->link_config.speed;
+		cmd->base.duplex = p->link_config.duplex;
 	} else {
-		ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
-		cmd->duplex = DUPLEX_UNKNOWN;
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
 	}
 
-	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;
+	ethtool_convert_link_mode_to_legacy_u32(&supported,
+						cmd->link_modes.supported);
+
+	cmd->base.port = (supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE;
+	cmd->base.phy_address = p->phy.mdio.prtad;
+	cmd->base.autoneg = p->link_config.autoneg;
 	return 0;
 }
 
@@ -1853,44 +1857,49 @@ static int speed_duplex_to_caps(int spee
 		      ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full | \
 		      ADVERTISED_10000baseT_Full)
 
-static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int set_link_ksettings(struct net_device *dev,
+			      const struct ethtool_link_ksettings *cmd)
 {
 	struct port_info *p = netdev_priv(dev);
 	struct link_config *lc = &p->link_config;
+	u32 advertising;
+
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						cmd->link_modes.advertising);
 
 	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 (cmd->base.autoneg == AUTONEG_DISABLE) {
+			u32 speed = cmd->base.speed;
+			int cap = speed_duplex_to_caps(speed, cmd->base.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 (cmd->base.autoneg == AUTONEG_DISABLE) {
+		u32 speed = cmd->base.speed;
+		int cap = speed_duplex_to_caps(speed, cmd->base.duplex);
 
 		if (!(lc->supported & cap) || (speed == SPEED_1000))
 			return -EINVAL;
 		lc->requested_speed = speed;
-		lc->requested_duplex = cmd->duplex;
+		lc->requested_duplex = cmd->base.duplex;
 		lc->advertising = 0;
 	} else {
-		cmd->advertising &= ADVERTISED_MASK;
-		cmd->advertising &= lc->supported;
-		if (!cmd->advertising)
+		advertising &= ADVERTISED_MASK;
+		advertising &= lc->supported;
+		if (!advertising)
 			return -EINVAL;
 		lc->requested_speed = SPEED_INVALID;
 		lc->requested_duplex = DUPLEX_INVALID;
-		lc->advertising = cmd->advertising | ADVERTISED_Autoneg;
+		lc->advertising = advertising | ADVERTISED_Autoneg;
 	}
-	lc->autoneg = cmd->autoneg;
+	lc->autoneg = cmd->base.autoneg;
 	if (netif_running(dev))
 		t3_link_start(&p->phy, &p->mac, lc);
 	return 0;
@@ -2090,8 +2099,6 @@ static void get_wol(struct net_device *d
 }
 
 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,
@@ -2113,6 +2120,8 @@ static const struct ethtool_ops cxgb_eth
 	.get_regs_len = get_regs_len,
 	.get_regs = get_regs,
 	.get_wol = get_wol,
+	.get_link_ksettings = get_link_ksettings,
+	.set_link_ksettings = set_link_ksettings,
 };
 
 static int in_range(int val, int lo, int hi)
@@ -2524,8 +2533,6 @@ static int cxgb_change_mtu(struct net_de
 	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;
@@ -3288,6 +3295,8 @@ static int init_one(struct pci_dev *pdev
 
 		netdev->netdev_ops = &cxgb_netdev_ops;
 		netdev->ethtool_ops = &cxgb_ethtool_ops;
+		netdev->min_mtu = 81;
+		netdev->max_mtu = ETH_MAX_MTU;
 	}
 
 	pci_set_drvdata(pdev, adapter);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -2512,18 +2512,6 @@ do { \
 		RL("FLLow:", fl.low);
 		RL("FLStarving:", fl.starving);
 
-	} else if (ofld_idx < ofld_entries) {
-		const struct sge_ofld_txq *tx =
-			&adap->sge.ofldtxq[ofld_idx * 4];
-		int n = min(4, adap->sge.ofldqsets - 4 * ofld_idx);
-
-		S("QType:", "OFLD-Txq");
-		T("TxQ ID:", q.cntxt_id);
-		T("TxQ size:", q.size);
-		T("TxQ inuse:", q.in_use);
-		T("TxQ CIDX:", q.cidx);
-		T("TxQ PIDX:", q.pidx);
-
 	} else if (ctrl_idx < ctrl_entries) {
 		const struct sge_ctrl_txq *tx = &adap->sge.ctrlq[ctrl_idx * 4];
 		int n = min(4, adap->params.nports - 4 * ctrl_idx);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h	2017-02-12 16:03:20.000000000 -0500
@@ -635,6 +635,7 @@ struct tx_sw_desc;
 
 struct sge_txq {
 	unsigned int  in_use;       /* # of in-use Tx descriptors */
+	unsigned int  q_type;	    /* Q type Eth/Ctrl/Ofld */
 	unsigned int  size;         /* # of descriptors */
 	unsigned int  cidx;         /* SW consumer index */
 	unsigned int  pidx;         /* producer index */
@@ -665,7 +666,7 @@ struct sge_eth_txq {                /* s
 	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_uld_txq {               /* state for an SGE offload Tx queue */
 	struct sge_txq q;
 	struct adapter *adap;
 	struct sk_buff_head sendq;  /* list of backpressured packets */
@@ -693,14 +694,20 @@ struct sge_uld_rxq_info {
 	u8 uld;			/* uld type */
 };
 
+struct sge_uld_txq_info {
+	struct sge_uld_txq *uldtxq; /* Txq's for ULD */
+	atomic_t users;		/* num users */
+	u16 ntxq;		/* # of egress uld queues */
+};
+
 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_rspq fw_evtq ____cacheline_aligned_in_smp;
 	struct sge_uld_rxq_info **uld_rxq_info;
+	struct sge_uld_txq_info **uld_txq_info;
 
 	struct sge_rspq intrq ____cacheline_aligned_in_smp;
 	spinlock_t intrq_lock;
@@ -1298,8 +1305,9 @@ int t4_sge_alloc_ctrl_txq(struct adapter
 			  unsigned int cmplqid);
 int t4_sge_mod_ctrl_txq(struct adapter *adap, unsigned int eqid,
 			unsigned int cmplqid);
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
-			  struct net_device *dev, unsigned int iqid);
+int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
+			 struct net_device *dev, unsigned int iqid,
+			 unsigned int uld_type);
 irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
 int t4_sge_init(struct adapter *adap);
 void t4_sge_start(struct adapter *adap);
@@ -1661,4 +1669,7 @@ int t4_uld_mem_alloc(struct adapter *ada
 void t4_uld_clean_up(struct adapter *adap);
 void t4_register_netevent_notifier(void);
 void free_rspq_fl(struct adapter *adap, struct sge_rspq *rq, struct sge_fl *fl);
+void free_tx_desc(struct adapter *adap, struct sge_txq *q,
+		  unsigned int n, bool unmap);
+void free_txq(struct adapter *adap, struct sge_txq *q);
 #endif /* __CXGB4_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c	2016-12-11 17:49:40.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c	2017-02-12 17:38:19.000000000 -0500
@@ -63,7 +63,7 @@
 #include <net/addrconf.h>
 #include <net/bonding.h>
 #include <net/addrconf.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/crash_dump.h>
 
 #include "cxgb4.h"
@@ -132,24 +132,6 @@ MODULE_DEVICE_TABLE(pci, cxgb4_pci_tbl);
 /*(DEBLOBBED)*/
 
 /*
- * Normally we're willing to become the firmware's Master PF but will be happy
- * if another PF has already become the Master and initialized the adapter.
- * Setting "force_init" will cause this driver to forcibly establish itself as
- * the Master PF and initialize the adapter.
- */
-static uint force_init;
-
-module_param(force_init, uint, 0644);
-MODULE_PARM_DESC(force_init, "Forcibly become Master PF and initialize adapter,"
-		 "deprecated parameter");
-
-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, "
-		 "deprecated parameter");
-
-/*
  * 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:
@@ -177,16 +159,6 @@ MODULE_PARM_DESC(msi, "whether to use IN
  */
 static int rx_dma_offset = 2;
 
-#ifdef CONFIG_PCI_IOV
-/* Configure the number of PCI-E Virtual Function which are to be instantiated
- * on SR-IOV Capable Physical Functions.
- */
-static unsigned int num_vf[NUM_OF_PF_WITH_SRIOV];
-
-module_param_array(num_vf, uint, NULL, 0644);
-MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3, deprecated parameter - please use the pci sysfs interface.");
-#endif
-
 /* TX Queue select used to determine what algorithm to use for selecting TX
  * queue. Select between the kernel provided function (select_queue=0) or user
  * cxgb_select_queue function (select_queue=1)
@@ -528,15 +500,15 @@ static int fwevtq_handler(struct sge_rsp
 
 		txq = q->adap->sge.egr_map[qid - q->adap->sge.egr_start];
 		txq->restarts++;
-		if ((u8 *)txq < (u8 *)q->adap->sge.ofldtxq) {
+		if (txq->q_type == CXGB4_TXQ_ETH) {
 			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;
+			struct sge_uld_txq *oq;
 
-			oq = container_of(txq, struct sge_ofld_txq, q);
+			oq = container_of(txq, struct sge_uld_txq, q);
 			tasklet_schedule(&oq->qresume_tsk);
 		}
 	} else if (opcode == CPL_FW6_MSG || opcode == CPL_FW4_MSG) {
@@ -883,15 +855,6 @@ static int setup_sge_queues(struct adapt
 		}
 	}
 
-	j = s->ofldqsets / adap->params.nports; /* iscsi queues per channel */
-	for_each_ofldtxq(s, i) {
-		err = t4_sge_alloc_ofld_txq(adap, &s->ofldtxq[i],
-					    adap->port[i / j],
-					    s->fw_evtq.cntxt_id);
-		if (err)
-			goto freeout;
-	}
-
 	for_each_port(adap, i) {
 		/* Note that cmplqid below is 0 if we don't
 		 * have RDMA queues, and that's the right value.
@@ -1920,8 +1883,18 @@ static void disable_dbs(struct adapter *
 
 	for_each_ethrxq(&adap->sge, i)
 		disable_txq_db(&adap->sge.ethtxq[i].q);
-	for_each_ofldtxq(&adap->sge, i)
-		disable_txq_db(&adap->sge.ofldtxq[i].q);
+	if (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info =
+			adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+
+		if (txq_info) {
+			for_each_ofldtxq(&adap->sge, i) {
+				struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+				disable_txq_db(&txq->q);
+			}
+		}
+	}
 	for_each_port(adap, i)
 		disable_txq_db(&adap->sge.ctrlq[i].q);
 }
@@ -1932,8 +1905,18 @@ static void enable_dbs(struct adapter *a
 
 	for_each_ethrxq(&adap->sge, i)
 		enable_txq_db(adap, &adap->sge.ethtxq[i].q);
-	for_each_ofldtxq(&adap->sge, i)
-		enable_txq_db(adap, &adap->sge.ofldtxq[i].q);
+	if (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info =
+			adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+
+		if (txq_info) {
+			for_each_ofldtxq(&adap->sge, i) {
+				struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+				enable_txq_db(adap, &txq->q);
+			}
+		}
+	}
 	for_each_port(adap, i)
 		enable_txq_db(adap, &adap->sge.ctrlq[i].q);
 }
@@ -2004,8 +1987,17 @@ static void recover_all_queues(struct ad
 
 	for_each_ethrxq(&adap->sge, i)
 		sync_txq_pidx(adap, &adap->sge.ethtxq[i].q);
-	for_each_ofldtxq(&adap->sge, i)
-		sync_txq_pidx(adap, &adap->sge.ofldtxq[i].q);
+	if (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info =
+			adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+		if (txq_info) {
+			for_each_ofldtxq(&adap->sge, i) {
+				struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+				sync_txq_pidx(adap, &txq->q);
+			}
+		}
+	}
 	for_each_port(adap, i)
 		sync_txq_pidx(adap, &adap->sge.ctrlq[i].q);
 }
@@ -2500,8 +2492,6 @@ static int cxgb_change_mtu(struct net_de
 	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->pf, pi->viid, new_mtu, -1,
 			    -1, -1, -1, true);
 	if (!ret)
@@ -3991,7 +3981,7 @@ static inline bool is_x_10g_port(const s
 static void cfg_queues(struct adapter *adap)
 {
 	struct sge *s = &adap->sge;
-	int i, n10g = 0, qidx = 0;
+	int i = 0, n10g = 0, qidx = 0;
 #ifndef CONFIG_CHELSIO_T4_DCB
 	int q10g = 0;
 #endif
@@ -4006,8 +3996,7 @@ static void cfg_queues(struct adapter *a
 		adap->params.crypto = 0;
 	}
 
-	for_each_port(adap, i)
-		n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
+	n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);
 #ifdef CONFIG_CHELSIO_T4_DCB
 	/* For Data Center Bridging support we need to be able to support up
 	 * to 8 Traffic Priorities; each of which will be assigned to its
@@ -4075,9 +4064,6 @@ static void cfg_queues(struct adapter *a
 	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;
-
 	init_rspq(adap, &s->fw_evtq, 0, 1, 1024, 64);
 	init_rspq(adap, &s->intrq, 0, 1, 512, 64);
 }
@@ -4713,7 +4699,7 @@ static int init_one(struct pci_dev *pdev
 	adapter->name = pci_name(pdev);
 	adapter->mbox = func;
 	adapter->pf = func;
-	adapter->msg_enable = dflt_msg_enable;
+	adapter->msg_enable = DFLT_MSG_ENABLE;
 	memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
 
 	spin_lock_init(&adapter->stats_lock);
@@ -4801,6 +4787,10 @@ static int init_one(struct pci_dev *pdev
 
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 
+		/* MTU range: 81 - 9600 */
+		netdev->min_mtu = 81;
+		netdev->max_mtu = MAX_MTU;
+
 		netdev->netdev_ops = &cxgb4_netdev_ops;
 #ifdef CONFIG_CHELSIO_T4_DCB
 		netdev->dcbnl_ops = &cxgb4_dcb_ops;
@@ -4969,17 +4959,6 @@ static int init_one(struct pci_dev *pdev
 
 sriov:
 #ifdef CONFIG_PCI_IOV
-	if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0) {
-		dev_warn(&pdev->dev,
-			 "Enabling SR-IOV VFs using the num_vf module "
-			 "parameter is deprecated - please use the pci sysfs "
-			 "interface instead.\n");
-		if (pci_enable_sriov(pdev, num_vf[func]) == 0)
-			dev_info(&pdev->dev,
-				 "instantiated %u virtual functions\n",
-				 num_vf[func]);
-	}
-
 	adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
 	if (!adapter) {
 		err = -ENOMEM;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,7 +113,7 @@ static int fill_action_fields(struct ada
 		}
 
 		/* Re-direct to specified port in hardware. */
-		if (is_tcf_mirred_redirect(a)) {
+		if (is_tcf_mirred_egress_redirect(a)) {
 			struct net_device *n_dev;
 			unsigned int i, index;
 			bool found = false;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c	2017-02-12 16:03:20.000000000 -0500
@@ -447,6 +447,106 @@ static void quiesce_rx_uld(struct adapte
 		quiesce_rx(adap, &rxq_info->uldrxq[idx].rspq);
 }
 
+static void
+free_sge_txq_uld(struct adapter *adap, struct sge_uld_txq_info *txq_info)
+{
+	int nq = txq_info->ntxq;
+	int i;
+
+	for (i = 0; i < nq; i++) {
+		struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+		if (txq && txq->q.desc) {
+			tasklet_kill(&txq->qresume_tsk);
+			t4_ofld_eq_free(adap, adap->mbox, adap->pf, 0,
+					txq->q.cntxt_id);
+			free_tx_desc(adap, &txq->q, txq->q.in_use, false);
+			kfree(txq->q.sdesc);
+			__skb_queue_purge(&txq->sendq);
+			free_txq(adap, &txq->q);
+		}
+	}
+}
+
+static int
+alloc_sge_txq_uld(struct adapter *adap, struct sge_uld_txq_info *txq_info,
+		  unsigned int uld_type)
+{
+	struct sge *s = &adap->sge;
+	int nq = txq_info->ntxq;
+	int i, j, err;
+
+	j = nq / adap->params.nports;
+	for (i = 0; i < nq; i++) {
+		struct sge_uld_txq *txq = &txq_info->uldtxq[i];
+
+		txq->q.size = 1024;
+		err = t4_sge_alloc_uld_txq(adap, txq, adap->port[i / j],
+					   s->fw_evtq.cntxt_id, uld_type);
+		if (err)
+			goto freeout;
+	}
+	return 0;
+freeout:
+	free_sge_txq_uld(adap, txq_info);
+	return err;
+}
+
+static void
+release_sge_txq_uld(struct adapter *adap, unsigned int uld_type)
+{
+	struct sge_uld_txq_info *txq_info = NULL;
+	int tx_uld_type = TX_ULD(uld_type);
+
+	txq_info = adap->sge.uld_txq_info[tx_uld_type];
+
+	if (txq_info && atomic_dec_and_test(&txq_info->users)) {
+		free_sge_txq_uld(adap, txq_info);
+		kfree(txq_info->uldtxq);
+		kfree(txq_info);
+		adap->sge.uld_txq_info[tx_uld_type] = NULL;
+	}
+}
+
+static int
+setup_sge_txq_uld(struct adapter *adap, unsigned int uld_type,
+		  const struct cxgb4_uld_info *uld_info)
+{
+	struct sge_uld_txq_info *txq_info = NULL;
+	int tx_uld_type, i;
+
+	tx_uld_type = TX_ULD(uld_type);
+	txq_info = adap->sge.uld_txq_info[tx_uld_type];
+
+	if ((tx_uld_type == CXGB4_TX_OFLD) && txq_info &&
+	    (atomic_inc_return(&txq_info->users) > 1))
+		return 0;
+
+	txq_info = kzalloc(sizeof(*txq_info), GFP_KERNEL);
+	if (!txq_info)
+		return -ENOMEM;
+
+	i = min_t(int, uld_info->ntxq, num_online_cpus());
+	txq_info->ntxq = roundup(i, adap->params.nports);
+
+	txq_info->uldtxq = kcalloc(txq_info->ntxq, sizeof(struct sge_uld_txq),
+				   GFP_KERNEL);
+	if (!txq_info->uldtxq) {
+		kfree(txq_info);
+		return -ENOMEM;
+	}
+
+	if (alloc_sge_txq_uld(adap, txq_info, tx_uld_type)) {
+		kfree(txq_info->uldtxq);
+		kfree(txq_info);
+		return -ENOMEM;
+	}
+
+	atomic_inc(&txq_info->users);
+	adap->sge.uld_txq_info[tx_uld_type] = txq_info;
+	return 0;
+}
+
 static void uld_queue_init(struct adapter *adap, unsigned int uld_type,
 			   struct cxgb4_lld_info *lli)
 {
@@ -472,7 +572,15 @@ int t4_uld_mem_alloc(struct adapter *ada
 	if (!s->uld_rxq_info)
 		goto err_uld;
 
+	s->uld_txq_info = kzalloc(CXGB4_TX_MAX *
+				  sizeof(struct sge_uld_txq_info *),
+				  GFP_KERNEL);
+	if (!s->uld_txq_info)
+		goto err_uld_rx;
 	return 0;
+
+err_uld_rx:
+	kfree(s->uld_rxq_info);
 err_uld:
 	kfree(adap->uld);
 	return -ENOMEM;
@@ -482,6 +590,7 @@ void t4_uld_mem_free(struct adapter *ada
 {
 	struct sge *s = &adap->sge;
 
+	kfree(s->uld_txq_info);
 	kfree(s->uld_rxq_info);
 	kfree(adap->uld);
 }
@@ -616,6 +725,9 @@ int cxgb4_register_uld(enum cxgb4_uld ty
 			ret = -EBUSY;
 			goto free_irq;
 		}
+		ret = setup_sge_txq_uld(adap, type, p);
+		if (ret)
+			goto free_irq;
 		adap->uld[type] = *p;
 		uld_attach(adap, type);
 		adap_idx++;
@@ -644,6 +756,7 @@ out:
 			break;
 		adap->uld[type].handle = NULL;
 		adap->uld[type].add = NULL;
+		release_sge_txq_uld(adap, type);
 		if (adap->flags & FULL_INIT_DONE)
 			quiesce_rx_uld(adap, type);
 		if (adap->flags & USING_MSIX)
@@ -679,6 +792,7 @@ int cxgb4_unregister_uld(enum cxgb4_uld
 			continue;
 		adap->uld[type].handle = NULL;
 		adap->uld[type].add = NULL;
+		release_sge_txq_uld(adap, type);
 		if (adap->flags & FULL_INIT_DONE)
 			quiesce_rx_uld(adap, type);
 		if (adap->flags & USING_MSIX)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h	2017-02-12 16:03:20.000000000 -0500
@@ -77,6 +77,8 @@ enum {
 
 /* Special asynchronous notification message */
 #define CXGB4_MSG_AN ((void *)1)
+#define TX_ULD(uld)(((uld) != CXGB4_ULD_CRYPTO) ? CXGB4_TX_OFLD :\
+		      CXGB4_TX_CRYPTO)
 
 struct serv_entry {
 	void *data;
@@ -223,6 +225,19 @@ enum cxgb4_uld {
 	CXGB4_ULD_MAX
 };
 
+enum cxgb4_tx_uld {
+	CXGB4_TX_OFLD,
+	CXGB4_TX_CRYPTO,
+	CXGB4_TX_MAX
+};
+
+enum cxgb4_txq_type {
+	CXGB4_TXQ_ETH,
+	CXGB4_TXQ_ULD,
+	CXGB4_TXQ_CTRL,
+	CXGB4_TXQ_MAX
+};
+
 enum cxgb4_state {
 	CXGB4_STATE_UP,
 	CXGB4_STATE_START_RECOVERY,
@@ -316,6 +331,7 @@ struct cxgb4_uld_info {
 	void *handle;
 	unsigned int nrxq;
 	unsigned int rxq_size;
+	unsigned int ntxq;
 	bool ciq;
 	bool lro;
 	void *(*add)(const struct cxgb4_lld_info *p);
@@ -333,6 +349,7 @@ struct cxgb4_uld_info {
 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);
+int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb);
 unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
 unsigned int cxgb4_port_chan(const struct net_device *dev);
 unsigned int cxgb4_port_viid(const struct net_device *dev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/sge.c	2017-02-12 16:03:20.000000000 -0500
@@ -377,8 +377,8 @@ unmap:			dma_unmap_page(dev, be64_to_cpu
  *	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)
+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;
@@ -1543,7 +1543,7 @@ static inline unsigned int calc_tx_flits
  *	inability to map packets.  A periodic timer attempts to restart
  *	queues so marked.
  */
-static void txq_stop_maperr(struct sge_ofld_txq *q)
+static void txq_stop_maperr(struct sge_uld_txq *q)
 {
 	q->mapping_err++;
 	q->q.stops++;
@@ -1559,7 +1559,7 @@ static void txq_stop_maperr(struct sge_o
  *	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)
+static void ofldtxq_stop(struct sge_uld_txq *q, struct sk_buff *skb)
 {
 	struct fw_wr_hdr *wr = (struct fw_wr_hdr *)skb->data;
 
@@ -1586,7 +1586,7 @@ static void ofldtxq_stop(struct sge_ofld
  *	boolean "service_ofldq_running" to make sure that only one instance
  *	is ever running at a time ...
  */
-static void service_ofldq(struct sge_ofld_txq *q)
+static void service_ofldq(struct sge_uld_txq *q)
 {
 	u64 *pos, *before, *end;
 	int credits;
@@ -1706,7 +1706,7 @@ static void service_ofldq(struct sge_ofl
  *
  *	Send an offload packet through an SGE offload queue.
  */
-static int ofld_xmit(struct sge_ofld_txq *q, struct sk_buff *skb)
+static int ofld_xmit(struct sge_uld_txq *q, struct sk_buff *skb)
 {
 	skb->priority = calc_tx_flits_ofld(skb);       /* save for restart */
 	spin_lock(&q->sendq.lock);
@@ -1735,7 +1735,7 @@ static int ofld_xmit(struct sge_ofld_txq
  */
 static void restart_ofldq(unsigned long data)
 {
-	struct sge_ofld_txq *q = (struct sge_ofld_txq *)data;
+	struct sge_uld_txq *q = (struct sge_uld_txq *)data;
 
 	spin_lock(&q->sendq.lock);
 	q->full = 0;            /* the queue actually is completely empty now */
@@ -1767,17 +1767,23 @@ static inline unsigned int is_ctrl_pkt(c
 	return skb->queue_mapping & 1;
 }
 
-static inline int ofld_send(struct adapter *adap, struct sk_buff *skb)
+static inline int uld_send(struct adapter *adap, struct sk_buff *skb,
+			   unsigned int tx_uld_type)
 {
+	struct sge_uld_txq_info *txq_info;
+	struct sge_uld_txq *txq;
 	unsigned int idx = skb_txq(skb);
 
+	txq_info = adap->sge.uld_txq_info[tx_uld_type];
+	txq = &txq_info->uldtxq[idx];
+
 	if (unlikely(is_ctrl_pkt(skb))) {
 		/* Single ctrl queue is a requirement for LE workaround path */
 		if (adap->tids.nsftids)
 			idx = 0;
 		return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
 	}
-	return ofld_xmit(&adap->sge.ofldtxq[idx], skb);
+	return ofld_xmit(txq, skb);
 }
 
 /**
@@ -1794,7 +1800,7 @@ int t4_ofld_send(struct adapter *adap, s
 	int ret;
 
 	local_bh_disable();
-	ret = ofld_send(adap, skb);
+	ret = uld_send(adap, skb, CXGB4_TX_OFLD);
 	local_bh_enable();
 	return ret;
 }
@@ -1813,6 +1819,39 @@ int cxgb4_ofld_send(struct net_device *d
 }
 EXPORT_SYMBOL(cxgb4_ofld_send);
 
+/**
+ *	t4_crypto_send - send crypto packet
+ *	@adap: the adapter
+ *	@skb: the packet
+ *
+ *	Sends crypto 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.
+ */
+static int t4_crypto_send(struct adapter *adap, struct sk_buff *skb)
+{
+	int ret;
+
+	local_bh_disable();
+	ret = uld_send(adap, skb, CXGB4_TX_CRYPTO);
+	local_bh_enable();
+	return ret;
+}
+
+/**
+ *	cxgb4_crypto_send - send crypto packet
+ *	@dev: the net device
+ *	@skb: the packet
+ *
+ *	Sends crypto packet.  This is an exported version of @t4_crypto_send,
+ *	intended for ULDs.
+ */
+int cxgb4_crypto_send(struct net_device *dev, struct sk_buff *skb)
+{
+	return t4_crypto_send(netdev2adap(dev), skb);
+}
+EXPORT_SYMBOL(cxgb4_crypto_send);
+
 static inline void copy_frags(struct sk_buff *skb,
 			      const struct pkt_gl *gl, unsigned int offset)
 {
@@ -2479,7 +2518,7 @@ static void sge_tx_timer_cb(unsigned lon
 	for (i = 0; i < BITS_TO_LONGS(s->egr_sz); 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];
+			struct sge_uld_txq *txq = s->egr_map[id];
 
 			clear_bit(id, s->txq_maperr);
 			tasklet_schedule(&txq->qresume_tsk);
@@ -2799,6 +2838,7 @@ int t4_sge_alloc_eth_txq(struct adapter
 		return ret;
 	}
 
+	txq->q.q_type = CXGB4_TXQ_ETH;
 	init_txq(adap, &txq->q, FW_EQ_ETH_CMD_EQID_G(ntohl(c.eqid_pkd)));
 	txq->txq = netdevq;
 	txq->tso = txq->tx_cso = txq->vlan_ins = 0;
@@ -2852,6 +2892,7 @@ int t4_sge_alloc_ctrl_txq(struct adapter
 		return ret;
 	}
 
+	txq->q.q_type = CXGB4_TXQ_CTRL;
 	init_txq(adap, &txq->q, FW_EQ_CTRL_CMD_EQID_G(ntohl(c.cmpliqid_eqid)));
 	txq->adap = adap;
 	skb_queue_head_init(&txq->sendq);
@@ -2872,13 +2913,15 @@ int t4_sge_mod_ctrl_txq(struct adapter *
 	return t4_set_params(adap, adap->mbox, adap->pf, 0, 1, &param, &val);
 }
 
-int t4_sge_alloc_ofld_txq(struct adapter *adap, struct sge_ofld_txq *txq,
-			  struct net_device *dev, unsigned int iqid)
+int t4_sge_alloc_uld_txq(struct adapter *adap, struct sge_uld_txq *txq,
+			 struct net_device *dev, unsigned int iqid,
+			 unsigned int uld_type)
 {
 	int ret, nentries;
 	struct fw_eq_ofld_cmd c;
 	struct sge *s = &adap->sge;
 	struct port_info *pi = netdev_priv(dev);
+	int cmd = FW_EQ_OFLD_CMD;
 
 	/* Add status entries */
 	nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
@@ -2891,7 +2934,9 @@ int t4_sge_alloc_ofld_txq(struct adapter
 		return -ENOMEM;
 
 	memset(&c, 0, sizeof(c));
-	c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST_F |
+	if (unlikely(uld_type == CXGB4_TX_CRYPTO))
+		cmd = FW_EQ_CTRL_CMD;
+	c.op_to_vfn = htonl(FW_CMD_OP_V(cmd) | FW_CMD_REQUEST_F |
 			    FW_CMD_WRITE_F | FW_CMD_EXEC_F |
 			    FW_EQ_OFLD_CMD_PFN_V(adap->pf) |
 			    FW_EQ_OFLD_CMD_VFN_V(0));
@@ -2919,6 +2964,7 @@ int t4_sge_alloc_ofld_txq(struct adapter
 		return ret;
 	}
 
+	txq->q.q_type = CXGB4_TXQ_ULD;
 	init_txq(adap, &txq->q, FW_EQ_OFLD_CMD_EQID_G(ntohl(c.eqid_pkd)));
 	txq->adap = adap;
 	skb_queue_head_init(&txq->sendq);
@@ -2928,7 +2974,7 @@ int t4_sge_alloc_ofld_txq(struct adapter
 	return 0;
 }
 
-static void free_txq(struct adapter *adap, struct sge_txq *q)
+void free_txq(struct adapter *adap, struct sge_txq *q)
 {
 	struct sge *s = &adap->sge;
 
@@ -3025,21 +3071,6 @@ void t4_free_sge_resources(struct adapte
 		}
 	}
 
-	/* 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->mbox, adap->pf, 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];
@@ -3092,12 +3123,34 @@ void t4_sge_stop(struct adapter *adap)
 	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 (is_offload(adap)) {
+		struct sge_uld_txq_info *txq_info;
 
-		if (q->q.desc)
-			tasklet_kill(&q->qresume_tsk);
+		txq_info = adap->sge.uld_txq_info[CXGB4_TX_OFLD];
+		if (txq_info) {
+			struct sge_uld_txq *txq = txq_info->uldtxq;
+
+			for_each_ofldtxq(&adap->sge, i) {
+				if (txq->q.desc)
+					tasklet_kill(&txq->qresume_tsk);
+			}
+		}
 	}
+
+	if (is_pci_uld(adap)) {
+		struct sge_uld_txq_info *txq_info;
+
+		txq_info = adap->sge.uld_txq_info[CXGB4_TX_CRYPTO];
+		if (txq_info) {
+			struct sge_uld_txq *txq = txq_info->uldtxq;
+
+			for_each_ofldtxq(&adap->sge, i) {
+				if (txq->q.desc)
+					tasklet_kill(&txq->qresume_tsk);
+			}
+		}
+	}
+
 	for (i = 0; i < ARRAY_SIZE(s->ctrlq); i++) {
 		struct sge_ctrl_txq *cq = &s->ctrlq[i];
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h	2017-02-12 16:03:20.000000000 -0500
@@ -76,6 +76,7 @@ enum {
 	CPL_PASS_ESTABLISH    = 0x41,
 	CPL_RX_DATA_DDP       = 0x42,
 	CPL_PASS_ACCEPT_REQ   = 0x44,
+	CPL_RX_ISCSI_CMP      = 0x45,
 	CPL_TRACE_PKT_T5      = 0x48,
 	CPL_RX_ISCSI_DDP      = 0x49,
 
@@ -934,6 +935,18 @@ struct cpl_iscsi_data {
 	__u8 status;
 };
 
+struct cpl_rx_iscsi_cmp {
+	union opcode_tid ot;
+	__be16 pdu_len_ddp;
+	__be16 len;
+	__be32 seq;
+	__be16 urg;
+	__u8 rsvd;
+	__u8 status;
+	__be32 ulp_crc;
+	__be32 ddpvld;
+};
+
 struct cpl_tx_data_iso {
 	__be32 op_to_scsi;
 	__u8   reserved1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -70,13 +70,6 @@
 			 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, "
-		 "deprecated parameter");
-
 /*
  * 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
@@ -1108,10 +1101,6 @@ static int cxgb4vf_change_mtu(struct net
 	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)
@@ -2895,7 +2884,7 @@ static int cxgb4vf_pci_probe(struct pci_
 	 * Initialize adapter level features.
 	 */
 	adapter->name = pci_name(pdev);
-	adapter->msg_enable = dflt_msg_enable;
+	adapter->msg_enable = DFLT_MSG_ENABLE;
 	err = adap_init0(adapter);
 	if (err)
 		goto err_unmap_bar;
@@ -2966,6 +2955,8 @@ static int cxgb4vf_pci_probe(struct pci_
 			netdev->features |= NETIF_F_HIGHDMA;
 
 		netdev->priv_flags |= IFF_UNICAST_FLT;
+		netdev->min_mtu = 81;
+		netdev->max_mtu = ETH_MAX_MTU;
 
 		netdev->netdev_ops = &cxgb4vf_netdev_ops;
 		netdev->ethtool_ops = &cxgb4vf_ethtool_ops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c	2017-02-12 16:03:20.000000000 -0500
@@ -133,17 +133,15 @@ cxgb_find_route6(struct cxgb4_lld_info *
 		if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
 			fl6.flowi6_oif = sin6_scope_id;
 		dst = ip6_route_output(&init_net, NULL, &fl6);
-		if (!dst)
-			goto out;
-		if (!cxgb_our_interface(lldi, get_real_dev,
-					ip6_dst_idev(dst)->dev) &&
-		    !(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK)) {
+		if (dst->error ||
+		    (!cxgb_our_interface(lldi, get_real_dev,
+					 ip6_dst_idev(dst)->dev) &&
+		     !(ip6_dst_idev(dst)->dev->flags & IFF_LOOPBACK))) {
 			dst_release(dst);
-			dst = NULL;
+			return NULL;
 		}
 	}
 
-out:
 	return dst;
 }
 EXPORT_SYMBOL(cxgb_find_route6);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cirrus/cs89x0.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cirrus/cs89x0.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cirrus/cs89x0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cirrus/cs89x0.c	2017-02-12 16:03:20.000000000 -0500
@@ -1266,7 +1266,6 @@ static const struct net_device_ops net_o
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= net_poll_controller,
 #endif
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cirrus/ep93xx_eth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cirrus/ep93xx_eth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cirrus/ep93xx_eth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cirrus/ep93xx_eth.c	2017-02-12 16:03:20.000000000 -0500
@@ -715,16 +715,18 @@ static void ep93xx_get_drvinfo(struct ne
 	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
 }
 
-static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int ep93xx_get_link_ksettings(struct net_device *dev,
+				     struct ethtool_link_ksettings *cmd)
 {
 	struct ep93xx_priv *ep = netdev_priv(dev);
-	return mii_ethtool_gset(&ep->mii, cmd);
+	return mii_ethtool_get_link_ksettings(&ep->mii, cmd);
 }
 
-static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int ep93xx_set_link_ksettings(struct net_device *dev,
+				     const struct ethtool_link_ksettings *cmd)
 {
 	struct ep93xx_priv *ep = netdev_priv(dev);
-	return mii_ethtool_sset(&ep->mii, cmd);
+	return mii_ethtool_set_link_ksettings(&ep->mii, cmd);
 }
 
 static int ep93xx_nway_reset(struct net_device *dev)
@@ -741,10 +743,10 @@ static u32 ep93xx_get_link(struct net_de
 
 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,
+	.get_link_ksettings	= ep93xx_get_link_ksettings,
+	.set_link_ksettings	= ep93xx_set_link_ksettings,
 };
 
 static const struct net_device_ops ep93xx_netdev_ops = {
@@ -753,7 +755,6 @@ static const struct net_device_ops ep93x
 	.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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cirrus/mac89x0.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cirrus/mac89x0.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cirrus/mac89x0.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cirrus/mac89x0.c	2017-02-12 16:03:20.000000000 -0500
@@ -172,7 +172,6 @@ static const struct net_device_ops mac89
 	.ndo_set_rx_mode	= set_multicast_list,
 	.ndo_set_mac_address	= set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
 };
 
 /* Probe for the CS8900 card in slot E.  We won't bother looking
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cisco/enic/enic.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cisco/enic/enic.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cisco/enic/enic.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cisco/enic/enic.h	2017-02-12 16:03:20.000000000 -0500
@@ -33,7 +33,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"2.3.0.20"
+#define DRV_VERSION		"2.3.0.31"
 #define DRV_COPYRIGHT		"Copyright 2008-2013 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cisco/enic/enic_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cisco/enic/enic_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/cisco/enic/enic_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cisco/enic/enic_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -1166,12 +1166,18 @@ static void enic_rq_indicate_buf(struct
 		skb->protocol = eth_type_trans(skb, netdev);
 		skb_record_rx_queue(skb, q_number);
 		if (netdev->features & NETIF_F_RXHASH) {
-			skb_set_hash(skb, rss_hash,
-				     (rss_type &
-				      (NIC_CFG_RSS_HASH_TYPE_TCP_IPV6_EX |
-				       NIC_CFG_RSS_HASH_TYPE_TCP_IPV6 |
-				       NIC_CFG_RSS_HASH_TYPE_TCP_IPV4)) ?
-				     PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3);
+			switch (rss_type) {
+			case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4:
+			case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6:
+			case CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX:
+				skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L4);
+				break;
+			case CQ_ENET_RQ_DESC_RSS_TYPE_IPv4:
+			case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6:
+			case CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX:
+				skb_set_hash(skb, rss_hash, PKT_HASH_TYPE_L3);
+				break;
+			}
 		}
 
 		/* Hardware does not provide whole packet checksum. It only
@@ -1843,9 +1849,6 @@ static int enic_change_mtu(struct net_de
 	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) || enic_is_sriov_vf(enic))
 		return -EOPNOTSUPP;
 
@@ -2751,6 +2754,10 @@ static int enic_probe(struct pci_dev *pd
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
+	/* MTU range: 68 - 9000 */
+	netdev->min_mtu = ENIC_MIN_MTU;
+	netdev->max_mtu = ENIC_MAX_MTU;
+
 	err = register_netdev(netdev);
 	if (err) {
 		dev_err(dev, "Cannot register net device, aborting\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/cisco/enic/enic_res.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cisco/enic/enic_res.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/cisco/enic/enic_res.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/cisco/enic/enic_res.h	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #define ENIC_MIN_RQ_DESCS		64
 #define ENIC_MAX_RQ_DESCS		4096
 
-#define ENIC_MIN_MTU			68
+#define ENIC_MIN_MTU			ETH_MIN_MTU
 #define ENIC_MAX_MTU			9000
 
 #define ENIC_MULTICAST_PERFECT_FILTERS	32
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/davicom/dm9000.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/davicom/dm9000.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/davicom/dm9000.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/davicom/dm9000.c	2017-02-12 16:03:20.000000000 -0500
@@ -570,19 +570,21 @@ static void dm9000_set_msglevel(struct n
 	dm->msg_enable = value;
 }
 
-static int dm9000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int dm9000_get_link_ksettings(struct net_device *dev,
+				     struct ethtool_link_ksettings *cmd)
 {
 	struct board_info *dm = to_dm9000_board(dev);
 
-	mii_ethtool_gset(&dm->mii, cmd);
+	mii_ethtool_get_link_ksettings(&dm->mii, cmd);
 	return 0;
 }
 
-static int dm9000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int dm9000_set_link_ksettings(struct net_device *dev,
+				     const struct ethtool_link_ksettings *cmd)
 {
 	struct board_info *dm = to_dm9000_board(dev);
 
-	return mii_ethtool_sset(&dm->mii, cmd);
+	return mii_ethtool_set_link_ksettings(&dm->mii, cmd);
 }
 
 static int dm9000_nway_reset(struct net_device *dev)
@@ -741,8 +743,6 @@ static int dm9000_set_wol(struct net_dev
 
 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,
@@ -752,6 +752,8 @@ static const struct ethtool_ops dm9000_e
 	.get_eeprom_len		= dm9000_get_eeprom_len,
 	.get_eeprom		= dm9000_get_eeprom,
 	.set_eeprom		= dm9000_set_eeprom,
+	.get_link_ksettings	= dm9000_get_link_ksettings,
+	.set_link_ksettings	= dm9000_set_link_ksettings,
 };
 
 static void dm9000_show_carrier(struct board_info *db,
@@ -1382,7 +1384,6 @@ static const struct net_device_ops dm900
 	.ndo_tx_timeout		= dm9000_timeout,
 	.ndo_set_rx_mode	= 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,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/de2104x.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/de2104x.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/de2104x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/de2104x.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
 /* These identify the driver base version and may not be removed. */
@@ -1956,7 +1956,6 @@ static const struct net_device_ops de_ne
 	.ndo_start_xmit		= de_start_xmit,
 	.ndo_get_stats		= de_get_stats,
 	.ndo_tx_timeout 	= de_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/de4x5.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/de4x5.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/de4x5.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/de4x5.c	2017-02-12 16:03:20.000000000 -0500
@@ -472,7 +472,7 @@
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #ifdef CONFIG_PPC_PMAC
 #include <asm/machdep.h>
 #endif /* CONFIG_PPC_PMAC */
@@ -1085,7 +1085,6 @@ static const struct net_device_ops de4x5
     .ndo_get_stats	= de4x5_get_stats,
     .ndo_set_rx_mode	= set_multicast_list,
     .ndo_do_ioctl	= de4x5_ioctl,
-    .ndo_change_mtu	= eth_change_mtu,
     .ndo_set_mac_address= eth_mac_addr,
     .ndo_validate_addr	= eth_validate_addr,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/dmfe.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/dmfe.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/dmfe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/dmfe.c	2017-02-12 16:03:20.000000000 -0500
@@ -90,7 +90,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 
 #ifdef CONFIG_TULIP_DM910X
@@ -352,7 +352,6 @@ static const struct net_device_ops netde
 	.ndo_stop		= dmfe_stop,
 	.ndo_start_xmit		= dmfe_start_xmit,
 	.ndo_set_rx_mode	= dmfe_set_filter_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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/tulip_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/mii.h>
 #include <linux/crc32.h>
 #include <asm/unaligned.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_SPARC
 #include <asm/prom.h>
@@ -1282,7 +1282,6 @@ static const struct net_device_ops tulip
 	.ndo_get_stats		= tulip_get_stats,
 	.ndo_do_ioctl 		= private_ioctl,
 	.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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/uli526x.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/uli526x.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/uli526x.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/uli526x.c	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define uw32(reg, val)	iowrite32(val, ioaddr + (reg))
 #define ur32(reg)	ioread32(ioaddr + (reg))
@@ -269,7 +269,6 @@ static const struct net_device_ops netde
 	.ndo_stop		= uli526x_stop,
 	.ndo_start_xmit		= uli526x_start_xmit,
 	.ndo_set_rx_mode	= uli526x_set_filter_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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/winbond-840.c	2017-02-12 16:03:20.000000000 -0500
@@ -129,7 +129,7 @@ static int full_duplex[MAX_UNITS] = {-1,
 #include <linux/rtnetlink.h>
 #include <linux/crc32.h>
 #include <linux/bitops.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -353,7 +353,6 @@ static const struct net_device_ops netde
 	.ndo_set_rx_mode	= set_rx_mode,
 	.ndo_do_ioctl		= netdev_ioctl,
 	.ndo_tx_timeout		= tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dec/tulip/xircom_cb.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 #ifdef CONFIG_NET_POLL_CONTROLLER
 #include <asm/irq.h>
@@ -174,7 +174,6 @@ static const struct net_device_ops netde
 	.ndo_open		= xircom_open,
 	.ndo_stop		= xircom_close,
 	.ndo_start_xmit		= xircom_start_xmit,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dlink/dl2k.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dlink/dl2k.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dlink/dl2k.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dlink/dl2k.c	2017-02-12 16:03:20.000000000 -0500
@@ -76,7 +76,6 @@ static void rio_free_tx (struct net_devi
 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);
@@ -106,7 +105,6 @@ static const struct net_device_ops netde
 	.ndo_set_rx_mode	= set_multicast,
 	.ndo_do_ioctl		= rio_ioctl,
 	.ndo_tx_timeout		= rio_tx_timeout,
-	.ndo_change_mtu		= change_mtu,
 };
 
 static int
@@ -230,6 +228,10 @@ rio_probe1 (struct pci_dev *pdev, const
 #if 0
 	dev->features = NETIF_F_IP_CSUM;
 #endif
+	/* MTU range: 68 - 1536 or 8000 */
+	dev->min_mtu = ETH_MIN_MTU;
+	dev->max_mtu = np->jumbo ? MAX_JUMBO : PACKET_SIZE;
+
 	pci_set_drvdata (pdev, dev);
 
 	ring_space = pci_alloc_consistent (pdev, TX_TOTAL_SIZE, &ring_dma);
@@ -1198,22 +1200,6 @@ clear_stats (struct net_device *dev)
 	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)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dlink/dl2k.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dlink/dl2k.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/dlink/dl2k.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dlink/dl2k.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@
 #include <linux/bitops.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include <linux/time.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dlink/sundance.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dlink/sundance.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dlink/sundance.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dlink/sundance.c	2017-02-12 16:03:20.000000000 -0500
@@ -91,7 +91,7 @@ static char *media[MAX_UNITS];
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/io.h>
 #include <linux/delay.h>
@@ -580,6 +580,10 @@ static int sundance_probe1(struct pci_de
 	dev->ethtool_ops = &ethtool_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
+	/* MTU range: 68 - 8191 */
+	dev->min_mtu = ETH_MIN_MTU;
+	dev->max_mtu = 8191;
+
 	pci_set_drvdata(pdev, dev);
 
 	i = register_netdev(dev);
@@ -713,8 +717,6 @@ err_out_netdev:
 
 static int change_mtu(struct net_device *dev, int new_mtu)
 {
-	if ((new_mtu < 68) || (new_mtu > 8191)) /* Set by RxDMAFrameLen */
-		return -EINVAL;
 	if (netif_running(dev))
 		return -EBUSY;
 	dev->mtu = new_mtu;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/dnet.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dnet.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/dnet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/dnet.c	2017-02-12 16:03:20.000000000 -0500
@@ -767,7 +767,6 @@ static const struct net_device_ops dnet_
 	.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 dnet_probe(struct platform_device *pdev)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/ec_bhf.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ec_bhf.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/ec_bhf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ec_bhf.c	2017-02-12 16:03:20.000000000 -0500
@@ -253,7 +253,7 @@ static enum hrtimer_restart ec_bhf_timer
 	if (!netif_running(priv->net_dev))
 		return HRTIMER_NORESTART;
 
-	hrtimer_forward_now(timer, ktime_set(0, polling_frequency));
+	hrtimer_forward_now(timer, polling_frequency);
 	return HRTIMER_RESTART;
 }
 
@@ -427,8 +427,7 @@ static int ec_bhf_open(struct net_device
 
 	hrtimer_init(&priv->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	priv->hrtimer.function = ec_bhf_timer_fun;
-	hrtimer_start(&priv->hrtimer, ktime_set(0, polling_frequency),
-		      HRTIMER_MODE_REL);
+	hrtimer_start(&priv->hrtimer, polling_frequency, HRTIMER_MODE_REL);
 
 	return 0;
 
@@ -482,7 +481,6 @@ static const struct net_device_ops ec_bh
 	.ndo_open		= ec_bhf_open,
 	.ndo_stop		= ec_bhf_stop,
 	.ndo_get_stats64	= ec_bhf_get_stats,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= eth_mac_addr
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/emulex/benet/be_cmds.c	2017-02-12 16:03:20.000000000 -0500
@@ -1118,7 +1118,7 @@ int be_cmd_pmac_add(struct be_adapter *a
 err:
 	mutex_unlock(&adapter->mcc_lock);
 
-	 if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
+	 if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
 		status = -EPERM;
 
 	return status;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/emulex/benet/be.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/emulex/benet/be.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/emulex/benet/be.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/emulex/benet/be.h	2017-02-12 16:03:20.000000000 -0500
@@ -65,7 +65,7 @@
 /* Number of bytes of an RX frame that are copied to skb->data */
 #define BE_HDR_LEN		((u16) 64)
 /* allocate extra space to allow tunneling decapsulation without head reallocation */
-#define BE_RX_SKB_ALLOC_SIZE (BE_HDR_LEN + 64)
+#define BE_RX_SKB_ALLOC_SIZE	256
 
 #define BE_MAX_JUMBO_FRAME_SIZE	9018
 #define BE_MIN_MTU		256
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/emulex/benet/be_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/emulex/benet/be_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/emulex/benet/be_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/emulex/benet/be_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -275,8 +275,7 @@ static int be_dev_mac_add(struct be_adap
 
 	/* Check if mac has already been added as part of uc-list */
 	for (i = 0; i < adapter->uc_macs; i++) {
-		if (ether_addr_equal((u8 *)&adapter->uc_list[i * ETH_ALEN],
-				     mac)) {
+		if (ether_addr_equal(adapter->uc_list[i].mac, mac)) {
 			/* mac already added, skip addition */
 			adapter->pmac_id[0] = adapter->pmac_id[i + 1];
 			return 0;
@@ -319,6 +318,13 @@ static int be_mac_addr_set(struct net_de
 	if (ether_addr_equal(addr->sa_data, adapter->dev_mac))
 		return 0;
 
+	/* BE3 VFs without FILTMGMT privilege are not allowed to set its MAC
+	 * address
+	 */
+	if (BEx_chip(adapter) && be_virtfn(adapter) &&
+	    !check_privilege(adapter, BE_PRIV_FILTMGMT))
+		return -EPERM;
+
 	/* if device is not running, copy MAC to netdev->dev_addr */
 	if (!netif_running(netdev))
 		goto done;
@@ -356,8 +362,10 @@ static int be_mac_addr_set(struct net_de
 		status = -EPERM;
 		goto err;
 	}
-done:
+
+	/* Remember currently programmed MAC */
 	ether_addr_copy(adapter->dev_mac, addr->sa_data);
+done:
 	ether_addr_copy(netdev->dev_addr, addr->sa_data);
 	dev_info(dev, "MAC address changed to %pM\n", addr->sa_data);
 	return 0;
@@ -1406,23 +1414,6 @@ drop:
 	return NETDEV_TX_OK;
 }
 
-static int be_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct be_adapter *adapter = netdev_priv(netdev);
-	struct device *dev = &adapter->pdev->dev;
-
-	if (new_mtu < BE_MIN_MTU || new_mtu > BE_MAX_MTU) {
-		dev_info(dev, "MTU must be between %d and %d bytes\n",
-			 BE_MIN_MTU, BE_MAX_MTU);
-		return -EINVAL;
-	}
-
-	dev_info(dev, "MTU changed from %d to %d bytes\n",
-		 netdev->mtu, new_mtu);
-	netdev->mtu = new_mtu;
-	return 0;
-}
-
 static inline bool be_in_all_promisc(struct be_adapter *adapter)
 {
 	return (adapter->if_flags & BE_IF_FLAGS_ALL_PROMISCUOUS) ==
@@ -1672,14 +1663,12 @@ static void be_clear_mc_list(struct be_a
 
 static int be_uc_mac_add(struct be_adapter *adapter, int uc_idx)
 {
-	if (ether_addr_equal((u8 *)&adapter->uc_list[uc_idx * ETH_ALEN],
-			     adapter->dev_mac)) {
+	if (ether_addr_equal(adapter->uc_list[uc_idx].mac, adapter->dev_mac)) {
 		adapter->pmac_id[uc_idx + 1] = adapter->pmac_id[0];
 		return 0;
 	}
 
-	return be_cmd_pmac_add(adapter,
-			       (u8 *)&adapter->uc_list[uc_idx * ETH_ALEN],
+	return be_cmd_pmac_add(adapter, adapter->uc_list[uc_idx].mac,
 			       adapter->if_handle,
 			       &adapter->pmac_id[uc_idx + 1], 0);
 }
@@ -1715,9 +1704,8 @@ static void be_set_uc_list(struct be_ada
 	}
 
 	if (adapter->update_uc_list) {
-		i = 1; /* First slot is claimed by the Primary MAC */
-
 		/* cache the uc-list in adapter array */
+		i = 0;
 		netdev_for_each_uc_addr(ha, netdev) {
 			ether_addr_copy(adapter->uc_list[i].mac, ha->addr);
 			i++;
@@ -3630,7 +3618,13 @@ static void be_rx_qs_destroy(struct be_a
 
 static void be_disable_if_filters(struct be_adapter *adapter)
 {
-	be_dev_mac_del(adapter, adapter->pmac_id[0]);
+	/* Don't delete MAC on BE3 VFs without FILTMGMT privilege  */
+	if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
+	    check_privilege(adapter, BE_PRIV_FILTMGMT)) {
+		be_dev_mac_del(adapter, adapter->pmac_id[0]);
+		eth_zero_addr(adapter->dev_mac);
+	}
+
 	be_clear_uc_list(adapter);
 	be_clear_mc_list(adapter);
 
@@ -3783,11 +3777,27 @@ static int be_enable_if_filters(struct b
 	if (status)
 		return status;
 
-	/* For BE3 VFs, the PF programs the initial MAC address */
-	if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
+	/* Normally this condition usually true as the ->dev_mac is zeroed.
+	 * But on BE3 VFs the initial MAC is pre-programmed by PF and
+	 * subsequent be_dev_mac_add() can fail (after fresh boot)
+	 */
+	if (!ether_addr_equal(adapter->dev_mac, adapter->netdev->dev_addr)) {
+		int old_pmac_id = -1;
+
+		/* Remember old programmed MAC if any - can happen on BE3 VF */
+		if (!is_zero_ether_addr(adapter->dev_mac))
+			old_pmac_id = adapter->pmac_id[0];
+
 		status = be_dev_mac_add(adapter, adapter->netdev->dev_addr);
 		if (status)
 			return status;
+
+		/* Delete the old programmed MAC as we successfully programmed
+		 * a new MAC
+		 */
+		if (old_pmac_id >= 0 && old_pmac_id != adapter->pmac_id[0])
+			be_dev_mac_del(adapter, old_pmac_id);
+
 		ether_addr_copy(adapter->dev_mac, adapter->netdev->dev_addr);
 	}
 
@@ -4561,6 +4571,10 @@ static int be_mac_setup(struct be_adapte
 
 		memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
 		memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
+
+		/* Initial MAC for BE3 VFs is already programmed by PF */
+		if (BEx_chip(adapter) && be_virtfn(adapter))
+			memcpy(adapter->dev_mac, mac, ETH_ALEN);
 	}
 
 	return 0;
@@ -5172,7 +5186,9 @@ static netdev_features_t be_features_che
 	    skb->inner_protocol_type != ENCAP_TYPE_ETHER ||
 	    skb->inner_protocol != htons(ETH_P_TEB) ||
 	    skb_inner_mac_header(skb) - skb_transport_header(skb) !=
-	    sizeof(struct udphdr) + sizeof(struct vxlanhdr))
+		sizeof(struct udphdr) + sizeof(struct vxlanhdr) ||
+	    !adapter->vxlan_port ||
+	    udp_hdr(skb)->dest != adapter->vxlan_port)
 		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
 
 	return features;
@@ -5215,7 +5231,6 @@ static const struct net_device_ops be_ne
 	.ndo_start_xmit		= be_xmit,
 	.ndo_set_rx_mode	= be_set_rx_mode,
 	.ndo_set_mac_address	= be_mac_addr_set,
-	.ndo_change_mtu		= be_change_mtu,
 	.ndo_get_stats64	= be_get_stats64,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_vlan_rx_add_vid	= be_vlan_add_vid,
@@ -5265,6 +5280,10 @@ static void be_netdev_init(struct net_de
 	netdev->netdev_ops = &be_netdev_ops;
 
 	netdev->ethtool_ops = &be_ethtool_ops;
+
+	/* MTU range: 256 - 9000 */
+	netdev->min_mtu = BE_MIN_MTU;
+	netdev->max_mtu = BE_MAX_MTU;
 }
 
 static void be_cleanup(struct be_adapter *adapter)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/ethoc.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ethoc.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/ethoc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ethoc.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,6 +23,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_net.h>
 #include <linux/module.h>
 #include <net/ethoc.h>
 
@@ -221,6 +222,9 @@ struct ethoc {
 	struct mii_bus *mdio;
 	struct clk *clk;
 	s8 phy_id;
+
+	int old_link;
+	int old_duplex;
 };
 
 /**
@@ -572,7 +576,7 @@ static irqreturn_t ethoc_interrupt(int i
 
 	/* We always handle the dropped packet interrupt */
 	if (pending & INT_MASK_BUSY) {
-		dev_err(&dev->dev, "packet dropped\n");
+		dev_dbg(&dev->dev, "packet dropped\n");
 		dev->stats.rx_dropped++;
 	}
 
@@ -667,6 +671,32 @@ static int ethoc_mdio_write(struct mii_b
 
 static void ethoc_mdio_poll(struct net_device *dev)
 {
+	struct ethoc *priv = netdev_priv(dev);
+	struct phy_device *phydev = dev->phydev;
+	bool changed = false;
+	u32 mode;
+
+	if (priv->old_link != phydev->link) {
+		changed = true;
+		priv->old_link = phydev->link;
+	}
+
+	if (priv->old_duplex != phydev->duplex) {
+		changed = true;
+		priv->old_duplex = phydev->duplex;
+	}
+
+	if (!changed)
+		return;
+
+	mode = ethoc_read(priv, MODER);
+	if (phydev->duplex == DUPLEX_FULL)
+		mode |= MODER_FULLD;
+	else
+		mode &= ~MODER_FULLD;
+	ethoc_write(priv, MODER, mode);
+
+	phy_print_status(phydev);
 }
 
 static int ethoc_mdio_probe(struct net_device *dev)
@@ -685,6 +715,9 @@ static int ethoc_mdio_probe(struct net_d
 		return -ENXIO;
 	}
 
+	priv->old_duplex = -1;
+	priv->old_link = -1;
+
 	err = phy_connect_direct(dev, phy, ethoc_mdio_poll,
 				 PHY_INTERFACE_MODE_GMII);
 	if (err) {
@@ -721,6 +754,9 @@ static int ethoc_open(struct net_device
 		netif_start_queue(dev);
 	}
 
+	priv->old_link = -1;
+	priv->old_duplex = -1;
+
 	phy_start(dev->phydev);
 	napi_enable(&priv->napi);
 
@@ -966,6 +1002,7 @@ static int ethoc_set_ringparam(struct ne
 const struct ethtool_ops ethoc_ethtool_ops = {
 	.get_regs_len = ethoc_get_regs_len,
 	.get_regs = ethoc_get_regs,
+	.nway_reset = phy_ethtool_nway_reset,
 	.get_link = ethtool_op_get_link,
 	.get_ringparam = ethoc_get_ringparam,
 	.set_ringparam = ethoc_set_ringparam,
@@ -1122,11 +1159,9 @@ static int ethoc_probe(struct platform_d
 		memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN);
 		priv->phy_id = pdata->phy_id;
 	} else {
-		const uint8_t *mac;
+		const void *mac;
 
-		mac = of_get_property(pdev->dev.of_node,
-				      "local-mac-address",
-				      NULL);
+		mac = of_get_mac_address(pdev->dev.of_node);
 		if (mac)
 			memcpy(netdev->dev_addr, mac, IFHWADDRLEN);
 		priv->phy_id = -1;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/fealnx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/fealnx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/fealnx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/fealnx.c	2017-02-12 16:03:20.000000000 -0500
@@ -88,7 +88,7 @@ static int full_duplex[MAX_UNITS] = { -1
 
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/byteorder.h>
 
 /* These identify the driver base version and may not be removed. */
@@ -472,7 +472,6 @@ static const struct net_device_ops netde
 	.ndo_set_rx_mode	= set_rx_mode,
 	.ndo_do_ioctl		= mii_ioctl,
 	.ndo_tx_timeout		= fealnx_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,2760 @@
+/* Copyright 2008 - 2016 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/io.h>
+#include <linux/if_arp.h>
+#include <linux/if_vlan.h>
+#include <linux/icmp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/highmem.h>
+#include <linux/percpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/sort.h>
+#include <soc/fsl/bman.h>
+#include <soc/fsl/qman.h>
+
+#include "fman.h"
+#include "fman_port.h"
+#include "mac.h"
+#include "dpaa_eth.h"
+
+/* CREATE_TRACE_POINTS only needs to be defined once. Other dpaa files
+ * using trace events only need to #include <trace/events/sched.h>
+ */
+#define CREATE_TRACE_POINTS
+#include "dpaa_eth_trace.h"
+
+static int debug = -1;
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level (0=none,...,16=all)");
+
+static u16 tx_timeout = 1000;
+module_param(tx_timeout, ushort, 0444);
+MODULE_PARM_DESC(tx_timeout, "The Tx timeout in ms");
+
+#define FM_FD_STAT_RX_ERRORS						\
+	(FM_FD_ERR_DMA | FM_FD_ERR_PHYSICAL	| \
+	 FM_FD_ERR_SIZE | FM_FD_ERR_CLS_DISCARD | \
+	 FM_FD_ERR_EXTRACTION | FM_FD_ERR_NO_SCHEME	| \
+	 FM_FD_ERR_PRS_TIMEOUT | FM_FD_ERR_PRS_ILL_INSTRUCT | \
+	 FM_FD_ERR_PRS_HDR_ERR)
+
+#define FM_FD_STAT_TX_ERRORS \
+	(FM_FD_ERR_UNSUPPORTED_FORMAT | \
+	 FM_FD_ERR_LENGTH | FM_FD_ERR_DMA)
+
+#define DPAA_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | \
+			  NETIF_MSG_LINK | NETIF_MSG_IFUP | \
+			  NETIF_MSG_IFDOWN)
+
+#define DPAA_INGRESS_CS_THRESHOLD 0x10000000
+/* Ingress congestion threshold on FMan ports
+ * The size in bytes of the ingress tail-drop threshold on FMan ports.
+ * Traffic piling up above this value will be rejected by QMan and discarded
+ * by FMan.
+ */
+
+/* Size in bytes of the FQ taildrop threshold */
+#define DPAA_FQ_TD 0x200000
+
+#define DPAA_CS_THRESHOLD_1G 0x06000000
+/* Egress congestion threshold on 1G ports, range 0x1000 .. 0x10000000
+ * The size in bytes of the egress Congestion State notification threshold on
+ * 1G ports. The 1G dTSECs can quite easily be flooded by cores doing Tx in a
+ * tight loop (e.g. by sending UDP datagrams at "while(1) speed"),
+ * and the larger the frame size, the more acute the problem.
+ * So we have to find a balance between these factors:
+ * - avoiding the device staying congested for a prolonged time (risking
+ *   the netdev watchdog to fire - see also the tx_timeout module param);
+ * - affecting performance of protocols such as TCP, which otherwise
+ *   behave well under the congestion notification mechanism;
+ * - preventing the Tx cores from tightly-looping (as if the congestion
+ *   threshold was too low to be effective);
+ * - running out of memory if the CS threshold is set too high.
+ */
+
+#define DPAA_CS_THRESHOLD_10G 0x10000000
+/* The size in bytes of the egress Congestion State notification threshold on
+ * 10G ports, range 0x1000 .. 0x10000000
+ */
+
+/* Largest value that the FQD's OAL field can hold */
+#define FSL_QMAN_MAX_OAL	127
+
+/* Default alignment for start of data in an Rx FD */
+#define DPAA_FD_DATA_ALIGNMENT  16
+
+/* Values for the L3R field of the FM Parse Results
+ */
+/* L3 Type field: First IP Present IPv4 */
+#define FM_L3_PARSE_RESULT_IPV4	0x8000
+/* L3 Type field: First IP Present IPv6 */
+#define FM_L3_PARSE_RESULT_IPV6	0x4000
+/* Values for the L4R field of the FM Parse Results */
+/* L4 Type field: UDP */
+#define FM_L4_PARSE_RESULT_UDP	0x40
+/* L4 Type field: TCP */
+#define FM_L4_PARSE_RESULT_TCP	0x20
+
+#define DPAA_SGT_MAX_ENTRIES 16 /* maximum number of entries in SG Table */
+#define DPAA_BUFF_RELEASE_MAX 8 /* maximum number of buffers released at once */
+
+#define FSL_DPAA_BPID_INV		0xff
+#define FSL_DPAA_ETH_MAX_BUF_COUNT	128
+#define FSL_DPAA_ETH_REFILL_THRESHOLD	80
+
+#define DPAA_TX_PRIV_DATA_SIZE	16
+#define DPAA_PARSE_RESULTS_SIZE sizeof(struct fman_prs_result)
+#define DPAA_TIME_STAMP_SIZE 8
+#define DPAA_HASH_RESULTS_SIZE 8
+#define DPAA_RX_PRIV_DATA_SIZE	(u16)(DPAA_TX_PRIV_DATA_SIZE + \
+					dpaa_rx_extra_headroom)
+
+#define DPAA_ETH_RX_QUEUES	128
+
+#define DPAA_ENQUEUE_RETRIES	100000
+
+enum port_type {RX, TX};
+
+struct fm_port_fqs {
+	struct dpaa_fq *tx_defq;
+	struct dpaa_fq *tx_errq;
+	struct dpaa_fq *rx_defq;
+	struct dpaa_fq *rx_errq;
+};
+
+/* All the dpa bps in use at any moment */
+static struct dpaa_bp *dpaa_bp_array[BM_MAX_NUM_OF_POOLS];
+
+/* The raw buffer size must be cacheline aligned */
+#define DPAA_BP_RAW_SIZE 4096
+/* When using more than one buffer pool, the raw sizes are as follows:
+ * 1 bp: 4KB
+ * 2 bp: 2KB, 4KB
+ * 3 bp: 1KB, 2KB, 4KB
+ * 4 bp: 1KB, 2KB, 4KB, 8KB
+ */
+static inline size_t bpool_buffer_raw_size(u8 index, u8 cnt)
+{
+	size_t res = DPAA_BP_RAW_SIZE / 4;
+	u8 i;
+
+	for (i = (cnt < 3) ? cnt : 3; i < 3 + index; i++)
+		res *= 2;
+	return res;
+}
+
+/* FMan-DMA requires 16-byte alignment for Rx buffers, but SKB_DATA_ALIGN is
+ * even stronger (SMP_CACHE_BYTES-aligned), so we just get away with that,
+ * via SKB_WITH_OVERHEAD(). We can't rely on netdev_alloc_frag() giving us
+ * half-page-aligned buffers, so we reserve some more space for start-of-buffer
+ * alignment.
+ */
+#define dpaa_bp_size(raw_size) SKB_WITH_OVERHEAD((raw_size) - SMP_CACHE_BYTES)
+
+static int dpaa_max_frm;
+
+static int dpaa_rx_extra_headroom;
+
+#define dpaa_get_max_mtu()	\
+	(dpaa_max_frm - (VLAN_ETH_HLEN + ETH_FCS_LEN))
+
+static int dpaa_netdev_init(struct net_device *net_dev,
+			    const struct net_device_ops *dpaa_ops,
+			    u16 tx_timeout)
+{
+	struct dpaa_priv *priv = netdev_priv(net_dev);
+	struct device *dev = net_dev->dev.parent;
+	struct dpaa_percpu_priv *percpu_priv;
+	const u8 *mac_addr;
+	int i, err;
+
+	/* Although we access another CPU's private data here
+	 * we do it at initialization so it is safe
+	 */
+	for_each_possible_cpu(i) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+		percpu_priv->net_dev = net_dev;
+	}
+
+	net_dev->netdev_ops = dpaa_ops;
+	mac_addr = priv->mac_dev->addr;
+
+	net_dev->mem_start = priv->mac_dev->res->start;
+	net_dev->mem_end = priv->mac_dev->res->end;
+
+	net_dev->min_mtu = ETH_MIN_MTU;
+	net_dev->max_mtu = dpaa_get_max_mtu();
+
+	net_dev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+				 NETIF_F_LLTX);
+
+	net_dev->hw_features |= NETIF_F_SG | NETIF_F_HIGHDMA;
+	/* The kernels enables GSO automatically, if we declare NETIF_F_SG.
+	 * For conformity, we'll still declare GSO explicitly.
+	 */
+	net_dev->features |= NETIF_F_GSO;
+
+	net_dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+	/* we do not want shared skbs on TX */
+	net_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+
+	net_dev->features |= net_dev->hw_features;
+	net_dev->vlan_features = net_dev->features;
+
+	memcpy(net_dev->perm_addr, mac_addr, net_dev->addr_len);
+	memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len);
+
+	net_dev->ethtool_ops = &dpaa_ethtool_ops;
+
+	net_dev->needed_headroom = priv->tx_headroom;
+	net_dev->watchdog_timeo = msecs_to_jiffies(tx_timeout);
+
+	/* start without the RUNNING flag, phylib controls it later */
+	netif_carrier_off(net_dev);
+
+	err = register_netdev(net_dev);
+	if (err < 0) {
+		dev_err(dev, "register_netdev() = %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int dpaa_stop(struct net_device *net_dev)
+{
+	struct mac_device *mac_dev;
+	struct dpaa_priv *priv;
+	int i, err, error;
+
+	priv = netdev_priv(net_dev);
+	mac_dev = priv->mac_dev;
+
+	netif_tx_stop_all_queues(net_dev);
+	/* Allow the Fman (Tx) port to process in-flight frames before we
+	 * try switching it off.
+	 */
+	usleep_range(5000, 10000);
+
+	err = mac_dev->stop(mac_dev);
+	if (err < 0)
+		netif_err(priv, ifdown, net_dev, "mac_dev->stop() = %d\n",
+			  err);
+
+	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
+		error = fman_port_disable(mac_dev->port[i]);
+		if (error)
+			err = error;
+	}
+
+	if (net_dev->phydev)
+		phy_disconnect(net_dev->phydev);
+	net_dev->phydev = NULL;
+
+	return err;
+}
+
+static void dpaa_tx_timeout(struct net_device *net_dev)
+{
+	struct dpaa_percpu_priv *percpu_priv;
+	const struct dpaa_priv	*priv;
+
+	priv = netdev_priv(net_dev);
+	percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+	netif_crit(priv, timer, net_dev, "Transmit timeout latency: %u ms\n",
+		   jiffies_to_msecs(jiffies - dev_trans_start(net_dev)));
+
+	percpu_priv->stats.tx_errors++;
+}
+
+/* Calculates the statistics for the given device by adding the statistics
+ * collected by each CPU.
+ */
+static struct rtnl_link_stats64 *dpaa_get_stats64(struct net_device *net_dev,
+						  struct rtnl_link_stats64 *s)
+{
+	int numstats = sizeof(struct rtnl_link_stats64) / sizeof(u64);
+	struct dpaa_priv *priv = netdev_priv(net_dev);
+	struct dpaa_percpu_priv *percpu_priv;
+	u64 *netstats = (u64 *)s;
+	u64 *cpustats;
+	int i, j;
+
+	for_each_possible_cpu(i) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+		cpustats = (u64 *)&percpu_priv->stats;
+
+		/* add stats from all CPUs */
+		for (j = 0; j < numstats; j++)
+			netstats[j] += cpustats[j];
+	}
+
+	return s;
+}
+
+static struct mac_device *dpaa_mac_dev_get(struct platform_device *pdev)
+{
+	struct platform_device *of_dev;
+	struct dpaa_eth_data *eth_data;
+	struct device *dpaa_dev, *dev;
+	struct device_node *mac_node;
+	struct mac_device *mac_dev;
+
+	dpaa_dev = &pdev->dev;
+	eth_data = dpaa_dev->platform_data;
+	if (!eth_data)
+		return ERR_PTR(-ENODEV);
+
+	mac_node = eth_data->mac_node;
+
+	of_dev = of_find_device_by_node(mac_node);
+	if (!of_dev) {
+		dev_err(dpaa_dev, "of_find_device_by_node(%s) failed\n",
+			mac_node->full_name);
+		of_node_put(mac_node);
+		return ERR_PTR(-EINVAL);
+	}
+	of_node_put(mac_node);
+
+	dev = &of_dev->dev;
+
+	mac_dev = dev_get_drvdata(dev);
+	if (!mac_dev) {
+		dev_err(dpaa_dev, "dev_get_drvdata(%s) failed\n",
+			dev_name(dev));
+		return ERR_PTR(-EINVAL);
+	}
+
+	return mac_dev;
+}
+
+static int dpaa_set_mac_address(struct net_device *net_dev, void *addr)
+{
+	const struct dpaa_priv *priv;
+	struct mac_device *mac_dev;
+	struct sockaddr old_addr;
+	int err;
+
+	priv = netdev_priv(net_dev);
+
+	memcpy(old_addr.sa_data, net_dev->dev_addr,  ETH_ALEN);
+
+	err = eth_mac_addr(net_dev, addr);
+	if (err < 0) {
+		netif_err(priv, drv, net_dev, "eth_mac_addr() = %d\n", err);
+		return err;
+	}
+
+	mac_dev = priv->mac_dev;
+
+	err = mac_dev->change_addr(mac_dev->fman_mac,
+				   (enet_addr_t *)net_dev->dev_addr);
+	if (err < 0) {
+		netif_err(priv, drv, net_dev, "mac_dev->change_addr() = %d\n",
+			  err);
+		/* reverting to previous address */
+		eth_mac_addr(net_dev, &old_addr);
+
+		return err;
+	}
+
+	return 0;
+}
+
+static void dpaa_set_rx_mode(struct net_device *net_dev)
+{
+	const struct dpaa_priv	*priv;
+	int err;
+
+	priv = netdev_priv(net_dev);
+
+	if (!!(net_dev->flags & IFF_PROMISC) != priv->mac_dev->promisc) {
+		priv->mac_dev->promisc = !priv->mac_dev->promisc;
+		err = priv->mac_dev->set_promisc(priv->mac_dev->fman_mac,
+						 priv->mac_dev->promisc);
+		if (err < 0)
+			netif_err(priv, drv, net_dev,
+				  "mac_dev->set_promisc() = %d\n",
+				  err);
+	}
+
+	err = priv->mac_dev->set_multi(net_dev, priv->mac_dev);
+	if (err < 0)
+		netif_err(priv, drv, net_dev, "mac_dev->set_multi() = %d\n",
+			  err);
+}
+
+static struct dpaa_bp *dpaa_bpid2pool(int bpid)
+{
+	if (WARN_ON(bpid < 0 || bpid >= BM_MAX_NUM_OF_POOLS))
+		return NULL;
+
+	return dpaa_bp_array[bpid];
+}
+
+/* checks if this bpool is already allocated */
+static bool dpaa_bpid2pool_use(int bpid)
+{
+	if (dpaa_bpid2pool(bpid)) {
+		atomic_inc(&dpaa_bp_array[bpid]->refs);
+		return true;
+	}
+
+	return false;
+}
+
+/* called only once per bpid by dpaa_bp_alloc_pool() */
+static void dpaa_bpid2pool_map(int bpid, struct dpaa_bp *dpaa_bp)
+{
+	dpaa_bp_array[bpid] = dpaa_bp;
+	atomic_set(&dpaa_bp->refs, 1);
+}
+
+static int dpaa_bp_alloc_pool(struct dpaa_bp *dpaa_bp)
+{
+	int err;
+
+	if (dpaa_bp->size == 0 || dpaa_bp->config_count == 0) {
+		pr_err("%s: Buffer pool is not properly initialized! Missing size or initial number of buffers\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	/* If the pool is already specified, we only create one per bpid */
+	if (dpaa_bp->bpid != FSL_DPAA_BPID_INV &&
+	    dpaa_bpid2pool_use(dpaa_bp->bpid))
+		return 0;
+
+	if (dpaa_bp->bpid == FSL_DPAA_BPID_INV) {
+		dpaa_bp->pool = bman_new_pool();
+		if (!dpaa_bp->pool) {
+			pr_err("%s: bman_new_pool() failed\n",
+			       __func__);
+			return -ENODEV;
+		}
+
+		dpaa_bp->bpid = (u8)bman_get_bpid(dpaa_bp->pool);
+	}
+
+	if (dpaa_bp->seed_cb) {
+		err = dpaa_bp->seed_cb(dpaa_bp);
+		if (err)
+			goto pool_seed_failed;
+	}
+
+	dpaa_bpid2pool_map(dpaa_bp->bpid, dpaa_bp);
+
+	return 0;
+
+pool_seed_failed:
+	pr_err("%s: pool seeding failed\n", __func__);
+	bman_free_pool(dpaa_bp->pool);
+
+	return err;
+}
+
+/* remove and free all the buffers from the given buffer pool */
+static void dpaa_bp_drain(struct dpaa_bp *bp)
+{
+	u8 num = 8;
+	int ret;
+
+	do {
+		struct bm_buffer bmb[8];
+		int i;
+
+		ret = bman_acquire(bp->pool, bmb, num);
+		if (ret < 0) {
+			if (num == 8) {
+				/* we have less than 8 buffers left;
+				 * drain them one by one
+				 */
+				num = 1;
+				ret = 1;
+				continue;
+			} else {
+				/* Pool is fully drained */
+				break;
+			}
+		}
+
+		if (bp->free_buf_cb)
+			for (i = 0; i < num; i++)
+				bp->free_buf_cb(bp, &bmb[i]);
+	} while (ret > 0);
+}
+
+static void dpaa_bp_free(struct dpaa_bp *dpaa_bp)
+{
+	struct dpaa_bp *bp = dpaa_bpid2pool(dpaa_bp->bpid);
+
+	/* the mapping between bpid and dpaa_bp is done very late in the
+	 * allocation procedure; if something failed before the mapping, the bp
+	 * was not configured, therefore we don't need the below instructions
+	 */
+	if (!bp)
+		return;
+
+	if (!atomic_dec_and_test(&bp->refs))
+		return;
+
+	if (bp->free_buf_cb)
+		dpaa_bp_drain(bp);
+
+	dpaa_bp_array[bp->bpid] = NULL;
+	bman_free_pool(bp->pool);
+}
+
+static void dpaa_bps_free(struct dpaa_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < DPAA_BPS_NUM; i++)
+		dpaa_bp_free(priv->dpaa_bps[i]);
+}
+
+/* Use multiple WQs for FQ assignment:
+ *	- Tx Confirmation queues go to WQ1.
+ *	- Rx Error and Tx Error queues go to WQ2 (giving them a better chance
+ *	  to be scheduled, in case there are many more FQs in WQ3).
+ *	- Rx Default and Tx queues go to WQ3 (no differentiation between
+ *	  Rx and Tx traffic).
+ * This ensures that Tx-confirmed buffers are timely released. In particular,
+ * it avoids congestion on the Tx Confirm FQs, which can pile up PFDRs if they
+ * are greatly outnumbered by other FQs in the system, while
+ * dequeue scheduling is round-robin.
+ */
+static inline void dpaa_assign_wq(struct dpaa_fq *fq)
+{
+	switch (fq->fq_type) {
+	case FQ_TYPE_TX_CONFIRM:
+	case FQ_TYPE_TX_CONF_MQ:
+		fq->wq = 1;
+		break;
+	case FQ_TYPE_RX_ERROR:
+	case FQ_TYPE_TX_ERROR:
+		fq->wq = 2;
+		break;
+	case FQ_TYPE_RX_DEFAULT:
+	case FQ_TYPE_TX:
+		fq->wq = 3;
+		break;
+	default:
+		WARN(1, "Invalid FQ type %d for FQID %d!\n",
+		     fq->fq_type, fq->fqid);
+	}
+}
+
+static struct dpaa_fq *dpaa_fq_alloc(struct device *dev,
+				     u32 start, u32 count,
+				     struct list_head *list,
+				     enum dpaa_fq_type fq_type)
+{
+	struct dpaa_fq *dpaa_fq;
+	int i;
+
+	dpaa_fq = devm_kzalloc(dev, sizeof(*dpaa_fq) * count,
+			       GFP_KERNEL);
+	if (!dpaa_fq)
+		return NULL;
+
+	for (i = 0; i < count; i++) {
+		dpaa_fq[i].fq_type = fq_type;
+		dpaa_fq[i].fqid = start ? start + i : 0;
+		list_add_tail(&dpaa_fq[i].list, list);
+	}
+
+	for (i = 0; i < count; i++)
+		dpaa_assign_wq(dpaa_fq + i);
+
+	return dpaa_fq;
+}
+
+static int dpaa_alloc_all_fqs(struct device *dev, struct list_head *list,
+			      struct fm_port_fqs *port_fqs)
+{
+	struct dpaa_fq *dpaa_fq;
+
+	dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_RX_ERROR);
+	if (!dpaa_fq)
+		goto fq_alloc_failed;
+
+	port_fqs->rx_errq = &dpaa_fq[0];
+
+	dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_RX_DEFAULT);
+	if (!dpaa_fq)
+		goto fq_alloc_failed;
+
+	port_fqs->rx_defq = &dpaa_fq[0];
+
+	if (!dpaa_fq_alloc(dev, 0, DPAA_ETH_TXQ_NUM, list, FQ_TYPE_TX_CONF_MQ))
+		goto fq_alloc_failed;
+
+	dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_TX_ERROR);
+	if (!dpaa_fq)
+		goto fq_alloc_failed;
+
+	port_fqs->tx_errq = &dpaa_fq[0];
+
+	dpaa_fq = dpaa_fq_alloc(dev, 0, 1, list, FQ_TYPE_TX_CONFIRM);
+	if (!dpaa_fq)
+		goto fq_alloc_failed;
+
+	port_fqs->tx_defq = &dpaa_fq[0];
+
+	if (!dpaa_fq_alloc(dev, 0, DPAA_ETH_TXQ_NUM, list, FQ_TYPE_TX))
+		goto fq_alloc_failed;
+
+	return 0;
+
+fq_alloc_failed:
+	dev_err(dev, "dpaa_fq_alloc() failed\n");
+	return -ENOMEM;
+}
+
+static u32 rx_pool_channel;
+static DEFINE_SPINLOCK(rx_pool_channel_init);
+
+static int dpaa_get_channel(void)
+{
+	spin_lock(&rx_pool_channel_init);
+	if (!rx_pool_channel) {
+		u32 pool;
+		int ret;
+
+		ret = qman_alloc_pool(&pool);
+
+		if (!ret)
+			rx_pool_channel = pool;
+	}
+	spin_unlock(&rx_pool_channel_init);
+	if (!rx_pool_channel)
+		return -ENOMEM;
+	return rx_pool_channel;
+}
+
+static void dpaa_release_channel(void)
+{
+	qman_release_pool(rx_pool_channel);
+}
+
+static void dpaa_eth_add_channel(u16 channel)
+{
+	u32 pool = QM_SDQCR_CHANNELS_POOL_CONV(channel);
+	const cpumask_t *cpus = qman_affine_cpus();
+	struct qman_portal *portal;
+	int cpu;
+
+	for_each_cpu(cpu, cpus) {
+		portal = qman_get_affine_portal(cpu);
+		qman_p_static_dequeue_add(portal, pool);
+	}
+}
+
+/* Congestion group state change notification callback.
+ * Stops the device's egress queues while they are congested and
+ * wakes them upon exiting congested state.
+ * Also updates some CGR-related stats.
+ */
+static void dpaa_eth_cgscn(struct qman_portal *qm, struct qman_cgr *cgr,
+			   int congested)
+{
+	struct dpaa_priv *priv = (struct dpaa_priv *)container_of(cgr,
+		struct dpaa_priv, cgr_data.cgr);
+
+	if (congested) {
+		priv->cgr_data.congestion_start_jiffies = jiffies;
+		netif_tx_stop_all_queues(priv->net_dev);
+		priv->cgr_data.cgr_congested_count++;
+	} else {
+		priv->cgr_data.congested_jiffies +=
+			(jiffies - priv->cgr_data.congestion_start_jiffies);
+		netif_tx_wake_all_queues(priv->net_dev);
+	}
+}
+
+static int dpaa_eth_cgr_init(struct dpaa_priv *priv)
+{
+	struct qm_mcc_initcgr initcgr;
+	u32 cs_th;
+	int err;
+
+	err = qman_alloc_cgrid(&priv->cgr_data.cgr.cgrid);
+	if (err < 0) {
+		if (netif_msg_drv(priv))
+			pr_err("%s: Error %d allocating CGR ID\n",
+			       __func__, err);
+		goto out_error;
+	}
+	priv->cgr_data.cgr.cb = dpaa_eth_cgscn;
+
+	/* Enable Congestion State Change Notifications and CS taildrop */
+	memset(&initcgr, 0, sizeof(initcgr));
+	initcgr.we_mask = cpu_to_be16(QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES);
+	initcgr.cgr.cscn_en = QM_CGR_EN;
+
+	/* Set different thresholds based on the MAC speed.
+	 * This may turn suboptimal if the MAC is reconfigured at a speed
+	 * lower than its max, e.g. if a dTSEC later negotiates a 100Mbps link.
+	 * In such cases, we ought to reconfigure the threshold, too.
+	 */
+	if (priv->mac_dev->if_support & SUPPORTED_10000baseT_Full)
+		cs_th = DPAA_CS_THRESHOLD_10G;
+	else
+		cs_th = DPAA_CS_THRESHOLD_1G;
+	qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1);
+
+	initcgr.we_mask |= cpu_to_be16(QM_CGR_WE_CSTD_EN);
+	initcgr.cgr.cstd_en = QM_CGR_EN;
+
+	err = qman_create_cgr(&priv->cgr_data.cgr, QMAN_CGR_FLAG_USE_INIT,
+			      &initcgr);
+	if (err < 0) {
+		if (netif_msg_drv(priv))
+			pr_err("%s: Error %d creating CGR with ID %d\n",
+			       __func__, err, priv->cgr_data.cgr.cgrid);
+		qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+		goto out_error;
+	}
+	if (netif_msg_drv(priv))
+		pr_debug("Created CGR %d for netdev with hwaddr %pM on QMan channel %d\n",
+			 priv->cgr_data.cgr.cgrid, priv->mac_dev->addr,
+			 priv->cgr_data.cgr.chan);
+
+out_error:
+	return err;
+}
+
+static inline void dpaa_setup_ingress(const struct dpaa_priv *priv,
+				      struct dpaa_fq *fq,
+				      const struct qman_fq *template)
+{
+	fq->fq_base = *template;
+	fq->net_dev = priv->net_dev;
+
+	fq->flags = QMAN_FQ_FLAG_NO_ENQUEUE;
+	fq->channel = priv->channel;
+}
+
+static inline void dpaa_setup_egress(const struct dpaa_priv *priv,
+				     struct dpaa_fq *fq,
+				     struct fman_port *port,
+				     const struct qman_fq *template)
+{
+	fq->fq_base = *template;
+	fq->net_dev = priv->net_dev;
+
+	if (port) {
+		fq->flags = QMAN_FQ_FLAG_TO_DCPORTAL;
+		fq->channel = (u16)fman_port_get_qman_channel_id(port);
+	} else {
+		fq->flags = QMAN_FQ_FLAG_NO_MODIFY;
+	}
+}
+
+static void dpaa_fq_setup(struct dpaa_priv *priv,
+			  const struct dpaa_fq_cbs *fq_cbs,
+			  struct fman_port *tx_port)
+{
+	int egress_cnt = 0, conf_cnt = 0, num_portals = 0, cpu;
+	const cpumask_t *affine_cpus = qman_affine_cpus();
+	u16 portals[NR_CPUS];
+	struct dpaa_fq *fq;
+
+	for_each_cpu(cpu, affine_cpus)
+		portals[num_portals++] = qman_affine_channel(cpu);
+	if (num_portals == 0)
+		dev_err(priv->net_dev->dev.parent,
+			"No Qman software (affine) channels found");
+
+	/* Initialize each FQ in the list */
+	list_for_each_entry(fq, &priv->dpaa_fq_list, list) {
+		switch (fq->fq_type) {
+		case FQ_TYPE_RX_DEFAULT:
+			dpaa_setup_ingress(priv, fq, &fq_cbs->rx_defq);
+			break;
+		case FQ_TYPE_RX_ERROR:
+			dpaa_setup_ingress(priv, fq, &fq_cbs->rx_errq);
+			break;
+		case FQ_TYPE_TX:
+			dpaa_setup_egress(priv, fq, tx_port,
+					  &fq_cbs->egress_ern);
+			/* If we have more Tx queues than the number of cores,
+			 * just ignore the extra ones.
+			 */
+			if (egress_cnt < DPAA_ETH_TXQ_NUM)
+				priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+			break;
+		case FQ_TYPE_TX_CONF_MQ:
+			priv->conf_fqs[conf_cnt++] = &fq->fq_base;
+			/* fall through */
+		case FQ_TYPE_TX_CONFIRM:
+			dpaa_setup_ingress(priv, fq, &fq_cbs->tx_defq);
+			break;
+		case FQ_TYPE_TX_ERROR:
+			dpaa_setup_ingress(priv, fq, &fq_cbs->tx_errq);
+			break;
+		default:
+			dev_warn(priv->net_dev->dev.parent,
+				 "Unknown FQ type detected!\n");
+			break;
+		}
+	}
+
+	 /* Make sure all CPUs receive a corresponding Tx queue. */
+	while (egress_cnt < DPAA_ETH_TXQ_NUM) {
+		list_for_each_entry(fq, &priv->dpaa_fq_list, list) {
+			if (fq->fq_type != FQ_TYPE_TX)
+				continue;
+			priv->egress_fqs[egress_cnt++] = &fq->fq_base;
+			if (egress_cnt == DPAA_ETH_TXQ_NUM)
+				break;
+		}
+	}
+}
+
+static inline int dpaa_tx_fq_to_id(const struct dpaa_priv *priv,
+				   struct qman_fq *tx_fq)
+{
+	int i;
+
+	for (i = 0; i < DPAA_ETH_TXQ_NUM; i++)
+		if (priv->egress_fqs[i] == tx_fq)
+			return i;
+
+	return -EINVAL;
+}
+
+static int dpaa_fq_init(struct dpaa_fq *dpaa_fq, bool td_enable)
+{
+	const struct dpaa_priv	*priv;
+	struct qman_fq *confq = NULL;
+	struct qm_mcc_initfq initfq;
+	struct device *dev;
+	struct qman_fq *fq;
+	int queue_id;
+	int err;
+
+	priv = netdev_priv(dpaa_fq->net_dev);
+	dev = dpaa_fq->net_dev->dev.parent;
+
+	if (dpaa_fq->fqid == 0)
+		dpaa_fq->flags |= QMAN_FQ_FLAG_DYNAMIC_FQID;
+
+	dpaa_fq->init = !(dpaa_fq->flags & QMAN_FQ_FLAG_NO_MODIFY);
+
+	err = qman_create_fq(dpaa_fq->fqid, dpaa_fq->flags, &dpaa_fq->fq_base);
+	if (err) {
+		dev_err(dev, "qman_create_fq() failed\n");
+		return err;
+	}
+	fq = &dpaa_fq->fq_base;
+
+	if (dpaa_fq->init) {
+		memset(&initfq, 0, sizeof(initfq));
+
+		initfq.we_mask = cpu_to_be16(QM_INITFQ_WE_FQCTRL);
+		/* Note: we may get to keep an empty FQ in cache */
+		initfq.fqd.fq_ctrl = cpu_to_be16(QM_FQCTRL_PREFERINCACHE);
+
+		/* Try to reduce the number of portal interrupts for
+		 * Tx Confirmation FQs.
+		 */
+		if (dpaa_fq->fq_type == FQ_TYPE_TX_CONFIRM)
+			initfq.fqd.fq_ctrl |= cpu_to_be16(QM_FQCTRL_HOLDACTIVE);
+
+		/* FQ placement */
+		initfq.we_mask |= cpu_to_be16(QM_INITFQ_WE_DESTWQ);
+
+		qm_fqd_set_destwq(&initfq.fqd, dpaa_fq->channel, dpaa_fq->wq);
+
+		/* Put all egress queues in a congestion group of their own.
+		 * Sensu stricto, the Tx confirmation queues are Rx FQs,
+		 * rather than Tx - but they nonetheless account for the
+		 * memory footprint on behalf of egress traffic. We therefore
+		 * place them in the netdev's CGR, along with the Tx FQs.
+		 */
+		if (dpaa_fq->fq_type == FQ_TYPE_TX ||
+		    dpaa_fq->fq_type == FQ_TYPE_TX_CONFIRM ||
+		    dpaa_fq->fq_type == FQ_TYPE_TX_CONF_MQ) {
+			initfq.we_mask |= cpu_to_be16(QM_INITFQ_WE_CGID);
+			initfq.fqd.fq_ctrl |= cpu_to_be16(QM_FQCTRL_CGE);
+			initfq.fqd.cgid = (u8)priv->cgr_data.cgr.cgrid;
+			/* Set a fixed overhead accounting, in an attempt to
+			 * reduce the impact of fixed-size skb shells and the
+			 * driver's needed headroom on system memory. This is
+			 * especially the case when the egress traffic is
+			 * composed of small datagrams.
+			 * Unfortunately, QMan's OAL value is capped to an
+			 * insufficient value, but even that is better than
+			 * no overhead accounting at all.
+			 */
+			initfq.we_mask |= cpu_to_be16(QM_INITFQ_WE_OAC);
+			qm_fqd_set_oac(&initfq.fqd, QM_OAC_CG);
+			qm_fqd_set_oal(&initfq.fqd,
+				       min(sizeof(struct sk_buff) +
+				       priv->tx_headroom,
+				       (size_t)FSL_QMAN_MAX_OAL));
+		}
+
+		if (td_enable) {
+			initfq.we_mask |= cpu_to_be16(QM_INITFQ_WE_TDTHRESH);
+			qm_fqd_set_taildrop(&initfq.fqd, DPAA_FQ_TD, 1);
+			initfq.fqd.fq_ctrl = cpu_to_be16(QM_FQCTRL_TDE);
+		}
+
+		if (dpaa_fq->fq_type == FQ_TYPE_TX) {
+			queue_id = dpaa_tx_fq_to_id(priv, &dpaa_fq->fq_base);
+			if (queue_id >= 0)
+				confq = priv->conf_fqs[queue_id];
+			if (confq) {
+				initfq.we_mask |=
+					cpu_to_be16(QM_INITFQ_WE_CONTEXTA);
+			/* ContextA: OVOM=1(use contextA2 bits instead of ICAD)
+			 *	     A2V=1 (contextA A2 field is valid)
+			 *	     A0V=1 (contextA A0 field is valid)
+			 *	     B0V=1 (contextB field is valid)
+			 * ContextA A2: EBD=1 (deallocate buffers inside FMan)
+			 * ContextB B0(ASPID): 0 (absolute Virtual Storage ID)
+			 */
+				qm_fqd_context_a_set64(&initfq.fqd,
+						       0x1e00000080000000ULL);
+			}
+		}
+
+		/* Put all the ingress queues in our "ingress CGR". */
+		if (priv->use_ingress_cgr &&
+		    (dpaa_fq->fq_type == FQ_TYPE_RX_DEFAULT ||
+		     dpaa_fq->fq_type == FQ_TYPE_RX_ERROR)) {
+			initfq.we_mask |= cpu_to_be16(QM_INITFQ_WE_CGID);
+			initfq.fqd.fq_ctrl |= cpu_to_be16(QM_FQCTRL_CGE);
+			initfq.fqd.cgid = (u8)priv->ingress_cgr.cgrid;
+			/* Set a fixed overhead accounting, just like for the
+			 * egress CGR.
+			 */
+			initfq.we_mask |= cpu_to_be16(QM_INITFQ_WE_OAC);
+			qm_fqd_set_oac(&initfq.fqd, QM_OAC_CG);
+			qm_fqd_set_oal(&initfq.fqd,
+				       min(sizeof(struct sk_buff) +
+				       priv->tx_headroom,
+				       (size_t)FSL_QMAN_MAX_OAL));
+		}
+
+		/* Initialization common to all ingress queues */
+		if (dpaa_fq->flags & QMAN_FQ_FLAG_NO_ENQUEUE) {
+			initfq.we_mask |= cpu_to_be16(QM_INITFQ_WE_CONTEXTA);
+			initfq.fqd.fq_ctrl |= cpu_to_be16(QM_FQCTRL_HOLDACTIVE);
+			initfq.fqd.context_a.stashing.exclusive =
+				QM_STASHING_EXCL_DATA | QM_STASHING_EXCL_CTX |
+				QM_STASHING_EXCL_ANNOTATION;
+			qm_fqd_set_stashing(&initfq.fqd, 1, 2,
+					    DIV_ROUND_UP(sizeof(struct qman_fq),
+							 64));
+		}
+
+		err = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &initfq);
+		if (err < 0) {
+			dev_err(dev, "qman_init_fq(%u) = %d\n",
+				qman_fq_fqid(fq), err);
+			qman_destroy_fq(fq);
+			return err;
+		}
+	}
+
+	dpaa_fq->fqid = qman_fq_fqid(fq);
+
+	return 0;
+}
+
+static int dpaa_fq_free_entry(struct device *dev, struct qman_fq *fq)
+{
+	const struct dpaa_priv  *priv;
+	struct dpaa_fq *dpaa_fq;
+	int err, error;
+
+	err = 0;
+
+	dpaa_fq = container_of(fq, struct dpaa_fq, fq_base);
+	priv = netdev_priv(dpaa_fq->net_dev);
+
+	if (dpaa_fq->init) {
+		err = qman_retire_fq(fq, NULL);
+		if (err < 0 && netif_msg_drv(priv))
+			dev_err(dev, "qman_retire_fq(%u) = %d\n",
+				qman_fq_fqid(fq), err);
+
+		error = qman_oos_fq(fq);
+		if (error < 0 && netif_msg_drv(priv)) {
+			dev_err(dev, "qman_oos_fq(%u) = %d\n",
+				qman_fq_fqid(fq), error);
+			if (err >= 0)
+				err = error;
+		}
+	}
+
+	qman_destroy_fq(fq);
+	list_del(&dpaa_fq->list);
+
+	return err;
+}
+
+static int dpaa_fq_free(struct device *dev, struct list_head *list)
+{
+	struct dpaa_fq *dpaa_fq, *tmp;
+	int err, error;
+
+	err = 0;
+	list_for_each_entry_safe(dpaa_fq, tmp, list, list) {
+		error = dpaa_fq_free_entry(dev, (struct qman_fq *)dpaa_fq);
+		if (error < 0 && err >= 0)
+			err = error;
+	}
+
+	return err;
+}
+
+static void dpaa_eth_init_tx_port(struct fman_port *port, struct dpaa_fq *errq,
+				  struct dpaa_fq *defq,
+				  struct dpaa_buffer_layout *buf_layout)
+{
+	struct fman_buffer_prefix_content buf_prefix_content;
+	struct fman_port_params params;
+	int err;
+
+	memset(&params, 0, sizeof(params));
+	memset(&buf_prefix_content, 0, sizeof(buf_prefix_content));
+
+	buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
+	buf_prefix_content.pass_prs_result = true;
+	buf_prefix_content.pass_hash_result = true;
+	buf_prefix_content.pass_time_stamp = false;
+	buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
+
+	params.specific_params.non_rx_params.err_fqid = errq->fqid;
+	params.specific_params.non_rx_params.dflt_fqid = defq->fqid;
+
+	err = fman_port_config(port, &params);
+	if (err)
+		pr_err("%s: fman_port_config failed\n", __func__);
+
+	err = fman_port_cfg_buf_prefix_content(port, &buf_prefix_content);
+	if (err)
+		pr_err("%s: fman_port_cfg_buf_prefix_content failed\n",
+		       __func__);
+
+	err = fman_port_init(port);
+	if (err)
+		pr_err("%s: fm_port_init failed\n", __func__);
+}
+
+static void dpaa_eth_init_rx_port(struct fman_port *port, struct dpaa_bp **bps,
+				  size_t count, struct dpaa_fq *errq,
+				  struct dpaa_fq *defq,
+				  struct dpaa_buffer_layout *buf_layout)
+{
+	struct fman_buffer_prefix_content buf_prefix_content;
+	struct fman_port_rx_params *rx_p;
+	struct fman_port_params params;
+	int i, err;
+
+	memset(&params, 0, sizeof(params));
+	memset(&buf_prefix_content, 0, sizeof(buf_prefix_content));
+
+	buf_prefix_content.priv_data_size = buf_layout->priv_data_size;
+	buf_prefix_content.pass_prs_result = true;
+	buf_prefix_content.pass_hash_result = true;
+	buf_prefix_content.pass_time_stamp = false;
+	buf_prefix_content.data_align = DPAA_FD_DATA_ALIGNMENT;
+
+	rx_p = &params.specific_params.rx_params;
+	rx_p->err_fqid = errq->fqid;
+	rx_p->dflt_fqid = defq->fqid;
+
+	count = min(ARRAY_SIZE(rx_p->ext_buf_pools.ext_buf_pool), count);
+	rx_p->ext_buf_pools.num_of_pools_used = (u8)count;
+	for (i = 0; i < count; i++) {
+		rx_p->ext_buf_pools.ext_buf_pool[i].id =  bps[i]->bpid;
+		rx_p->ext_buf_pools.ext_buf_pool[i].size = (u16)bps[i]->size;
+	}
+
+	err = fman_port_config(port, &params);
+	if (err)
+		pr_err("%s: fman_port_config failed\n", __func__);
+
+	err = fman_port_cfg_buf_prefix_content(port, &buf_prefix_content);
+	if (err)
+		pr_err("%s: fman_port_cfg_buf_prefix_content failed\n",
+		       __func__);
+
+	err = fman_port_init(port);
+	if (err)
+		pr_err("%s: fm_port_init failed\n", __func__);
+}
+
+static void dpaa_eth_init_ports(struct mac_device *mac_dev,
+				struct dpaa_bp **bps, size_t count,
+				struct fm_port_fqs *port_fqs,
+				struct dpaa_buffer_layout *buf_layout,
+				struct device *dev)
+{
+	struct fman_port *rxport = mac_dev->port[RX];
+	struct fman_port *txport = mac_dev->port[TX];
+
+	dpaa_eth_init_tx_port(txport, port_fqs->tx_errq,
+			      port_fqs->tx_defq, &buf_layout[TX]);
+	dpaa_eth_init_rx_port(rxport, bps, count, port_fqs->rx_errq,
+			      port_fqs->rx_defq, &buf_layout[RX]);
+}
+
+static int dpaa_bman_release(const struct dpaa_bp *dpaa_bp,
+			     struct bm_buffer *bmb, int cnt)
+{
+	int err;
+
+	err = bman_release(dpaa_bp->pool, bmb, cnt);
+	/* Should never occur, address anyway to avoid leaking the buffers */
+	if (unlikely(WARN_ON(err)) && dpaa_bp->free_buf_cb)
+		while (cnt-- > 0)
+			dpaa_bp->free_buf_cb(dpaa_bp, &bmb[cnt]);
+
+	return cnt;
+}
+
+static void dpaa_release_sgt_members(struct qm_sg_entry *sgt)
+{
+	struct bm_buffer bmb[DPAA_BUFF_RELEASE_MAX];
+	struct dpaa_bp *dpaa_bp;
+	int i = 0, j;
+
+	memset(bmb, 0, sizeof(bmb));
+
+	do {
+		dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+		if (!dpaa_bp)
+			return;
+
+		j = 0;
+		do {
+			WARN_ON(qm_sg_entry_is_ext(&sgt[i]));
+
+			bm_buffer_set64(&bmb[j], qm_sg_entry_get64(&sgt[i]));
+
+			j++; i++;
+		} while (j < ARRAY_SIZE(bmb) &&
+				!qm_sg_entry_is_final(&sgt[i - 1]) &&
+				sgt[i - 1].bpid == sgt[i].bpid);
+
+		dpaa_bman_release(dpaa_bp, bmb, j);
+	} while (!qm_sg_entry_is_final(&sgt[i - 1]));
+}
+
+static void dpaa_fd_release(const struct net_device *net_dev,
+			    const struct qm_fd *fd)
+{
+	struct qm_sg_entry *sgt;
+	struct dpaa_bp *dpaa_bp;
+	struct bm_buffer bmb;
+	dma_addr_t addr;
+	void *vaddr;
+
+	bmb.data = 0;
+	bm_buffer_set64(&bmb, qm_fd_addr(fd));
+
+	dpaa_bp = dpaa_bpid2pool(fd->bpid);
+	if (!dpaa_bp)
+		return;
+
+	if (qm_fd_get_format(fd) == qm_fd_sg) {
+		vaddr = phys_to_virt(qm_fd_addr(fd));
+		sgt = vaddr + qm_fd_get_offset(fd);
+
+		dma_unmap_single(dpaa_bp->dev, qm_fd_addr(fd), dpaa_bp->size,
+				 DMA_FROM_DEVICE);
+
+		dpaa_release_sgt_members(sgt);
+
+		addr = dma_map_single(dpaa_bp->dev, vaddr, dpaa_bp->size,
+				      DMA_FROM_DEVICE);
+		if (dma_mapping_error(dpaa_bp->dev, addr)) {
+			dev_err(dpaa_bp->dev, "DMA mapping failed");
+			return;
+		}
+		bm_buffer_set64(&bmb, addr);
+	}
+
+	dpaa_bman_release(dpaa_bp, &bmb, 1);
+}
+
+static void count_ern(struct dpaa_percpu_priv *percpu_priv,
+		      const union qm_mr_entry *msg)
+{
+	switch (msg->ern.rc & QM_MR_RC_MASK) {
+	case QM_MR_RC_CGR_TAILDROP:
+		percpu_priv->ern_cnt.cg_tdrop++;
+		break;
+	case QM_MR_RC_WRED:
+		percpu_priv->ern_cnt.wred++;
+		break;
+	case QM_MR_RC_ERROR:
+		percpu_priv->ern_cnt.err_cond++;
+		break;
+	case QM_MR_RC_ORPWINDOW_EARLY:
+		percpu_priv->ern_cnt.early_window++;
+		break;
+	case QM_MR_RC_ORPWINDOW_LATE:
+		percpu_priv->ern_cnt.late_window++;
+		break;
+	case QM_MR_RC_FQ_TAILDROP:
+		percpu_priv->ern_cnt.fq_tdrop++;
+		break;
+	case QM_MR_RC_ORPWINDOW_RETIRED:
+		percpu_priv->ern_cnt.fq_retired++;
+		break;
+	case QM_MR_RC_ORP_ZERO:
+		percpu_priv->ern_cnt.orp_zero++;
+		break;
+	}
+}
+
+/* Turn on HW checksum computation for this outgoing frame.
+ * If the current protocol is not something we support in this regard
+ * (or if the stack has already computed the SW checksum), we do nothing.
+ *
+ * Returns 0 if all goes well (or HW csum doesn't apply), and a negative value
+ * otherwise.
+ *
+ * Note that this function may modify the fd->cmd field and the skb data buffer
+ * (the Parse Results area).
+ */
+static int dpaa_enable_tx_csum(struct dpaa_priv *priv,
+			       struct sk_buff *skb,
+			       struct qm_fd *fd,
+			       char *parse_results)
+{
+	struct fman_prs_result *parse_result;
+	u16 ethertype = ntohs(skb->protocol);
+	struct ipv6hdr *ipv6h = NULL;
+	struct iphdr *iph;
+	int retval = 0;
+	u8 l4_proto;
+
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return 0;
+
+	/* Note: L3 csum seems to be already computed in sw, but we can't choose
+	 * L4 alone from the FM configuration anyway.
+	 */
+
+	/* Fill in some fields of the Parse Results array, so the FMan
+	 * can find them as if they came from the FMan Parser.
+	 */
+	parse_result = (struct fman_prs_result *)parse_results;
+
+	/* If we're dealing with VLAN, get the real Ethernet type */
+	if (ethertype == ETH_P_8021Q) {
+		/* We can't always assume the MAC header is set correctly
+		 * by the stack, so reset to beginning of skb->data
+		 */
+		skb_reset_mac_header(skb);
+		ethertype = ntohs(vlan_eth_hdr(skb)->h_vlan_encapsulated_proto);
+	}
+
+	/* Fill in the relevant L3 parse result fields
+	 * and read the L4 protocol type
+	 */
+	switch (ethertype) {
+	case ETH_P_IP:
+		parse_result->l3r = cpu_to_be16(FM_L3_PARSE_RESULT_IPV4);
+		iph = ip_hdr(skb);
+		WARN_ON(!iph);
+		l4_proto = iph->protocol;
+		break;
+	case ETH_P_IPV6:
+		parse_result->l3r = cpu_to_be16(FM_L3_PARSE_RESULT_IPV6);
+		ipv6h = ipv6_hdr(skb);
+		WARN_ON(!ipv6h);
+		l4_proto = ipv6h->nexthdr;
+		break;
+	default:
+		/* We shouldn't even be here */
+		if (net_ratelimit())
+			netif_alert(priv, tx_err, priv->net_dev,
+				    "Can't compute HW csum for L3 proto 0x%x\n",
+				    ntohs(skb->protocol));
+		retval = -EIO;
+		goto return_error;
+	}
+
+	/* Fill in the relevant L4 parse result fields */
+	switch (l4_proto) {
+	case IPPROTO_UDP:
+		parse_result->l4r = FM_L4_PARSE_RESULT_UDP;
+		break;
+	case IPPROTO_TCP:
+		parse_result->l4r = FM_L4_PARSE_RESULT_TCP;
+		break;
+	default:
+		if (net_ratelimit())
+			netif_alert(priv, tx_err, priv->net_dev,
+				    "Can't compute HW csum for L4 proto 0x%x\n",
+				    l4_proto);
+		retval = -EIO;
+		goto return_error;
+	}
+
+	/* At index 0 is IPOffset_1 as defined in the Parse Results */
+	parse_result->ip_off[0] = (u8)skb_network_offset(skb);
+	parse_result->l4_off = (u8)skb_transport_offset(skb);
+
+	/* Enable L3 (and L4, if TCP or UDP) HW checksum. */
+	fd->cmd |= cpu_to_be32(FM_FD_CMD_RPD | FM_FD_CMD_DTC);
+
+	/* On P1023 and similar platforms fd->cmd interpretation could
+	 * be disabled by setting CONTEXT_A bit ICMD; currently this bit
+	 * is not set so we do not need to check; in the future, if/when
+	 * using context_a we need to check this bit
+	 */
+
+return_error:
+	return retval;
+}
+
+static int dpaa_bp_add_8_bufs(const struct dpaa_bp *dpaa_bp)
+{
+	struct device *dev = dpaa_bp->dev;
+	struct bm_buffer bmb[8];
+	dma_addr_t addr;
+	void *new_buf;
+	u8 i;
+
+	for (i = 0; i < 8; i++) {
+		new_buf = netdev_alloc_frag(dpaa_bp->raw_size);
+		if (unlikely(!new_buf)) {
+			dev_err(dev, "netdev_alloc_frag() failed, size %zu\n",
+				dpaa_bp->raw_size);
+			goto release_previous_buffs;
+		}
+		new_buf = PTR_ALIGN(new_buf, SMP_CACHE_BYTES);
+
+		addr = dma_map_single(dev, new_buf,
+				      dpaa_bp->size, DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(dev, addr))) {
+			dev_err(dpaa_bp->dev, "DMA map failed");
+			goto release_previous_buffs;
+		}
+
+		bmb[i].data = 0;
+		bm_buffer_set64(&bmb[i], addr);
+	}
+
+release_bufs:
+	return dpaa_bman_release(dpaa_bp, bmb, i);
+
+release_previous_buffs:
+	WARN_ONCE(1, "dpaa_eth: failed to add buffers on Rx\n");
+
+	bm_buffer_set64(&bmb[i], 0);
+	/* Avoid releasing a completely null buffer; bman_release() requires
+	 * at least one buffer.
+	 */
+	if (likely(i))
+		goto release_bufs;
+
+	return 0;
+}
+
+static int dpaa_bp_seed(struct dpaa_bp *dpaa_bp)
+{
+	int i;
+
+	/* Give each CPU an allotment of "config_count" buffers */
+	for_each_possible_cpu(i) {
+		int *count_ptr = per_cpu_ptr(dpaa_bp->percpu_count, i);
+		int j;
+
+		/* Although we access another CPU's counters here
+		 * we do it at boot time so it is safe
+		 */
+		for (j = 0; j < dpaa_bp->config_count; j += 8)
+			*count_ptr += dpaa_bp_add_8_bufs(dpaa_bp);
+	}
+	return 0;
+}
+
+/* Add buffers/(pages) for Rx processing whenever bpool count falls below
+ * REFILL_THRESHOLD.
+ */
+static int dpaa_eth_refill_bpool(struct dpaa_bp *dpaa_bp, int *countptr)
+{
+	int count = *countptr;
+	int new_bufs;
+
+	if (unlikely(count < FSL_DPAA_ETH_REFILL_THRESHOLD)) {
+		do {
+			new_bufs = dpaa_bp_add_8_bufs(dpaa_bp);
+			if (unlikely(!new_bufs)) {
+				/* Avoid looping forever if we've temporarily
+				 * run out of memory. We'll try again at the
+				 * next NAPI cycle.
+				 */
+				break;
+			}
+			count += new_bufs;
+		} while (count < FSL_DPAA_ETH_MAX_BUF_COUNT);
+
+		*countptr = count;
+		if (unlikely(count < FSL_DPAA_ETH_MAX_BUF_COUNT))
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
+{
+	struct dpaa_bp *dpaa_bp;
+	int *countptr;
+	int res, i;
+
+	for (i = 0; i < DPAA_BPS_NUM; i++) {
+		dpaa_bp = priv->dpaa_bps[i];
+		if (!dpaa_bp)
+			return -EINVAL;
+		countptr = this_cpu_ptr(dpaa_bp->percpu_count);
+		res  = dpaa_eth_refill_bpool(dpaa_bp, countptr);
+		if (res)
+			return res;
+	}
+	return 0;
+}
+
+/* Cleanup function for outgoing frame descriptors that were built on Tx path,
+ * either contiguous frames or scatter/gather ones.
+ * Skb freeing is not handled here.
+ *
+ * This function may be called on error paths in the Tx function, so guard
+ * against cases when not all fd relevant fields were filled in.
+ *
+ * Return the skb backpointer, since for S/G frames the buffer containing it
+ * gets freed here.
+ */
+static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv,
+					  const struct qm_fd *fd)
+{
+	const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
+	struct device *dev = priv->net_dev->dev.parent;
+	dma_addr_t addr = qm_fd_addr(fd);
+	const struct qm_sg_entry *sgt;
+	struct sk_buff **skbh, *skb;
+	int nr_frags, i;
+
+	skbh = (struct sk_buff **)phys_to_virt(addr);
+	skb = *skbh;
+
+	if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
+		nr_frags = skb_shinfo(skb)->nr_frags;
+		dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
+				 sizeof(struct qm_sg_entry) * (1 + nr_frags),
+				 dma_dir);
+
+		/* The sgt buffer has been allocated with netdev_alloc_frag(),
+		 * it's from lowmem.
+		 */
+		sgt = phys_to_virt(addr + qm_fd_get_offset(fd));
+
+		/* sgt[0] is from lowmem, was dma_map_single()-ed */
+		dma_unmap_single(dev, qm_sg_addr(&sgt[0]),
+				 qm_sg_entry_get_len(&sgt[0]), dma_dir);
+
+		/* remaining pages were mapped with skb_frag_dma_map() */
+		for (i = 1; i < nr_frags; i++) {
+			WARN_ON(qm_sg_entry_is_ext(&sgt[i]));
+
+			dma_unmap_page(dev, qm_sg_addr(&sgt[i]),
+				       qm_sg_entry_get_len(&sgt[i]), dma_dir);
+		}
+
+		/* Free the page frag that we allocated on Tx */
+		skb_free_frag(phys_to_virt(addr));
+	} else {
+		dma_unmap_single(dev, addr,
+				 skb_tail_pointer(skb) - (u8 *)skbh, dma_dir);
+	}
+
+	return skb;
+}
+
+/* Build a linear skb around the received buffer.
+ * We are guaranteed there is enough room at the end of the data buffer to
+ * accommodate the shared info area of the skb.
+ */
+static struct sk_buff *contig_fd_to_skb(const struct dpaa_priv *priv,
+					const struct qm_fd *fd)
+{
+	ssize_t fd_off = qm_fd_get_offset(fd);
+	dma_addr_t addr = qm_fd_addr(fd);
+	struct dpaa_bp *dpaa_bp;
+	struct sk_buff *skb;
+	void *vaddr;
+
+	vaddr = phys_to_virt(addr);
+	WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
+
+	dpaa_bp = dpaa_bpid2pool(fd->bpid);
+	if (!dpaa_bp)
+		goto free_buffer;
+
+	skb = build_skb(vaddr, dpaa_bp->size +
+			SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
+	if (unlikely(!skb)) {
+		WARN_ONCE(1, "Build skb failure on Rx\n");
+		goto free_buffer;
+	}
+	WARN_ON(fd_off != priv->rx_headroom);
+	skb_reserve(skb, fd_off);
+	skb_put(skb, qm_fd_get_length(fd));
+
+	skb->ip_summed = CHECKSUM_NONE;
+
+	return skb;
+
+free_buffer:
+	skb_free_frag(vaddr);
+	return NULL;
+}
+
+/* Build an skb with the data of the first S/G entry in the linear portion and
+ * the rest of the frame as skb fragments.
+ *
+ * The page fragment holding the S/G Table is recycled here.
+ */
+static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
+				    const struct qm_fd *fd)
+{
+	ssize_t fd_off = qm_fd_get_offset(fd);
+	dma_addr_t addr = qm_fd_addr(fd);
+	const struct qm_sg_entry *sgt;
+	struct page *page, *head_page;
+	struct dpaa_bp *dpaa_bp;
+	void *vaddr, *sg_vaddr;
+	int frag_off, frag_len;
+	struct sk_buff *skb;
+	dma_addr_t sg_addr;
+	int page_offset;
+	unsigned int sz;
+	int *count_ptr;
+	int i;
+
+	vaddr = phys_to_virt(addr);
+	WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
+
+	/* Iterate through the SGT entries and add data buffers to the skb */
+	sgt = vaddr + fd_off;
+	for (i = 0; i < DPAA_SGT_MAX_ENTRIES; i++) {
+		/* Extension bit is not supported */
+		WARN_ON(qm_sg_entry_is_ext(&sgt[i]));
+
+		sg_addr = qm_sg_addr(&sgt[i]);
+		sg_vaddr = phys_to_virt(sg_addr);
+		WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
+				    SMP_CACHE_BYTES));
+
+		/* We may use multiple Rx pools */
+		dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+		if (!dpaa_bp)
+			goto free_buffers;
+
+		count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+		dma_unmap_single(dpaa_bp->dev, sg_addr, dpaa_bp->size,
+				 DMA_FROM_DEVICE);
+		if (i == 0) {
+			sz = dpaa_bp->size +
+				SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+			skb = build_skb(sg_vaddr, sz);
+			if (WARN_ON(unlikely(!skb)))
+				goto free_buffers;
+
+			skb->ip_summed = CHECKSUM_NONE;
+
+			/* Make sure forwarded skbs will have enough space
+			 * on Tx, if extra headers are added.
+			 */
+			WARN_ON(fd_off != priv->rx_headroom);
+			skb_reserve(skb, fd_off);
+			skb_put(skb, qm_sg_entry_get_len(&sgt[i]));
+		} else {
+			/* Not the first S/G entry; all data from buffer will
+			 * be added in an skb fragment; fragment index is offset
+			 * by one since first S/G entry was incorporated in the
+			 * linear part of the skb.
+			 *
+			 * Caution: 'page' may be a tail page.
+			 */
+			page = virt_to_page(sg_vaddr);
+			head_page = virt_to_head_page(sg_vaddr);
+
+			/* Compute offset in (possibly tail) page */
+			page_offset = ((unsigned long)sg_vaddr &
+					(PAGE_SIZE - 1)) +
+				(page_address(page) - page_address(head_page));
+			/* page_offset only refers to the beginning of sgt[i];
+			 * but the buffer itself may have an internal offset.
+			 */
+			frag_off = qm_sg_entry_get_off(&sgt[i]) + page_offset;
+			frag_len = qm_sg_entry_get_len(&sgt[i]);
+			/* skb_add_rx_frag() does no checking on the page; if
+			 * we pass it a tail page, we'll end up with
+			 * bad page accounting and eventually with segafults.
+			 */
+			skb_add_rx_frag(skb, i - 1, head_page, frag_off,
+					frag_len, dpaa_bp->size);
+		}
+		/* Update the pool count for the current {cpu x bpool} */
+		(*count_ptr)--;
+
+		if (qm_sg_entry_is_final(&sgt[i]))
+			break;
+	}
+	WARN_ONCE(i == DPAA_SGT_MAX_ENTRIES, "No final bit on SGT\n");
+
+	/* free the SG table buffer */
+	skb_free_frag(vaddr);
+
+	return skb;
+
+free_buffers:
+	/* compensate sw bpool counter changes */
+	for (i--; i > 0; i--) {
+		dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+		if (dpaa_bp) {
+			count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+			(*count_ptr)++;
+		}
+	}
+	/* free all the SG entries */
+	for (i = 0; i < DPAA_SGT_MAX_ENTRIES ; i++) {
+		sg_addr = qm_sg_addr(&sgt[i]);
+		sg_vaddr = phys_to_virt(sg_addr);
+		skb_free_frag(sg_vaddr);
+		dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
+		if (dpaa_bp) {
+			count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+			(*count_ptr)--;
+		}
+
+		if (qm_sg_entry_is_final(&sgt[i]))
+			break;
+	}
+	/* free the SGT fragment */
+	skb_free_frag(vaddr);
+
+	return NULL;
+}
+
+static int skb_to_contig_fd(struct dpaa_priv *priv,
+			    struct sk_buff *skb, struct qm_fd *fd,
+			    int *offset)
+{
+	struct net_device *net_dev = priv->net_dev;
+	struct device *dev = net_dev->dev.parent;
+	enum dma_data_direction dma_dir;
+	unsigned char *buffer_start;
+	struct sk_buff **skbh;
+	dma_addr_t addr;
+	int err;
+
+	/* We are guaranteed to have at least tx_headroom bytes
+	 * available, so just use that for offset.
+	 */
+	fd->bpid = FSL_DPAA_BPID_INV;
+	buffer_start = skb->data - priv->tx_headroom;
+	dma_dir = DMA_TO_DEVICE;
+
+	skbh = (struct sk_buff **)buffer_start;
+	*skbh = skb;
+
+	/* Enable L3/L4 hardware checksum computation.
+	 *
+	 * We must do this before dma_map_single(DMA_TO_DEVICE), because we may
+	 * need to write into the skb.
+	 */
+	err = dpaa_enable_tx_csum(priv, skb, fd,
+				  ((char *)skbh) + DPAA_TX_PRIV_DATA_SIZE);
+	if (unlikely(err < 0)) {
+		if (net_ratelimit())
+			netif_err(priv, tx_err, net_dev, "HW csum error: %d\n",
+				  err);
+		return err;
+	}
+
+	/* Fill in the rest of the FD fields */
+	qm_fd_set_contig(fd, priv->tx_headroom, skb->len);
+	fd->cmd |= cpu_to_be32(FM_FD_CMD_FCO);
+
+	/* Map the entire buffer size that may be seen by FMan, but no more */
+	addr = dma_map_single(dev, skbh,
+			      skb_tail_pointer(skb) - buffer_start, dma_dir);
+	if (unlikely(dma_mapping_error(dev, addr))) {
+		if (net_ratelimit())
+			netif_err(priv, tx_err, net_dev, "dma_map_single() failed\n");
+		return -EINVAL;
+	}
+	qm_fd_addr_set64(fd, addr);
+
+	return 0;
+}
+
+static int skb_to_sg_fd(struct dpaa_priv *priv,
+			struct sk_buff *skb, struct qm_fd *fd)
+{
+	const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
+	const int nr_frags = skb_shinfo(skb)->nr_frags;
+	struct net_device *net_dev = priv->net_dev;
+	struct device *dev = net_dev->dev.parent;
+	struct qm_sg_entry *sgt;
+	struct sk_buff **skbh;
+	int i, j, err, sz;
+	void *buffer_start;
+	skb_frag_t *frag;
+	dma_addr_t addr;
+	size_t frag_len;
+	void *sgt_buf;
+
+	/* get a page frag to store the SGTable */
+	sz = SKB_DATA_ALIGN(priv->tx_headroom +
+		sizeof(struct qm_sg_entry) * (1 + nr_frags));
+	sgt_buf = netdev_alloc_frag(sz);
+	if (unlikely(!sgt_buf)) {
+		netdev_err(net_dev, "netdev_alloc_frag() failed for size %d\n",
+			   sz);
+		return -ENOMEM;
+	}
+
+	/* Enable L3/L4 hardware checksum computation.
+	 *
+	 * We must do this before dma_map_single(DMA_TO_DEVICE), because we may
+	 * need to write into the skb.
+	 */
+	err = dpaa_enable_tx_csum(priv, skb, fd,
+				  sgt_buf + DPAA_TX_PRIV_DATA_SIZE);
+	if (unlikely(err < 0)) {
+		if (net_ratelimit())
+			netif_err(priv, tx_err, net_dev, "HW csum error: %d\n",
+				  err);
+		goto csum_failed;
+	}
+
+	sgt = (struct qm_sg_entry *)(sgt_buf + priv->tx_headroom);
+	qm_sg_entry_set_len(&sgt[0], skb_headlen(skb));
+	sgt[0].bpid = FSL_DPAA_BPID_INV;
+	sgt[0].offset = 0;
+	addr = dma_map_single(dev, skb->data,
+			      skb_headlen(skb), dma_dir);
+	if (unlikely(dma_mapping_error(dev, addr))) {
+		dev_err(dev, "DMA mapping failed");
+		err = -EINVAL;
+		goto sg0_map_failed;
+	}
+	qm_sg_entry_set64(&sgt[0], addr);
+
+	/* populate the rest of SGT entries */
+	frag = &skb_shinfo(skb)->frags[0];
+	frag_len = frag->size;
+	for (i = 1; i <= nr_frags; i++, frag++) {
+		WARN_ON(!skb_frag_page(frag));
+		addr = skb_frag_dma_map(dev, frag, 0,
+					frag_len, dma_dir);
+		if (unlikely(dma_mapping_error(dev, addr))) {
+			dev_err(dev, "DMA mapping failed");
+			err = -EINVAL;
+			goto sg_map_failed;
+		}
+
+		qm_sg_entry_set_len(&sgt[i], frag_len);
+		sgt[i].bpid = FSL_DPAA_BPID_INV;
+		sgt[i].offset = 0;
+
+		/* keep the offset in the address */
+		qm_sg_entry_set64(&sgt[i], addr);
+		frag_len = frag->size;
+	}
+	qm_sg_entry_set_f(&sgt[i - 1], frag_len);
+
+	qm_fd_set_sg(fd, priv->tx_headroom, skb->len);
+
+	/* DMA map the SGT page */
+	buffer_start = (void *)sgt - priv->tx_headroom;
+	skbh = (struct sk_buff **)buffer_start;
+	*skbh = skb;
+
+	addr = dma_map_single(dev, buffer_start, priv->tx_headroom +
+			      sizeof(struct qm_sg_entry) * (1 + nr_frags),
+			      dma_dir);
+	if (unlikely(dma_mapping_error(dev, addr))) {
+		dev_err(dev, "DMA mapping failed");
+		err = -EINVAL;
+		goto sgt_map_failed;
+	}
+
+	fd->bpid = FSL_DPAA_BPID_INV;
+	fd->cmd |= cpu_to_be32(FM_FD_CMD_FCO);
+	qm_fd_addr_set64(fd, addr);
+
+	return 0;
+
+sgt_map_failed:
+sg_map_failed:
+	for (j = 0; j < i; j++)
+		dma_unmap_page(dev, qm_sg_addr(&sgt[j]),
+			       qm_sg_entry_get_len(&sgt[j]), dma_dir);
+sg0_map_failed:
+csum_failed:
+	skb_free_frag(sgt_buf);
+
+	return err;
+}
+
+static inline int dpaa_xmit(struct dpaa_priv *priv,
+			    struct rtnl_link_stats64 *percpu_stats,
+			    int queue,
+			    struct qm_fd *fd)
+{
+	struct qman_fq *egress_fq;
+	int err, i;
+
+	egress_fq = priv->egress_fqs[queue];
+	if (fd->bpid == FSL_DPAA_BPID_INV)
+		fd->cmd |= cpu_to_be32(qman_fq_fqid(priv->conf_fqs[queue]));
+
+	/* Trace this Tx fd */
+	trace_dpaa_tx_fd(priv->net_dev, egress_fq, fd);
+
+	for (i = 0; i < DPAA_ENQUEUE_RETRIES; i++) {
+		err = qman_enqueue(egress_fq, fd);
+		if (err != -EBUSY)
+			break;
+	}
+
+	if (unlikely(err < 0)) {
+		percpu_stats->tx_errors++;
+		percpu_stats->tx_fifo_errors++;
+		return err;
+	}
+
+	percpu_stats->tx_packets++;
+	percpu_stats->tx_bytes += qm_fd_get_length(fd);
+
+	return 0;
+}
+
+static int dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
+{
+	const int queue_mapping = skb_get_queue_mapping(skb);
+	bool nonlinear = skb_is_nonlinear(skb);
+	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa_percpu_priv *percpu_priv;
+	struct dpaa_priv *priv;
+	struct qm_fd fd;
+	int offset = 0;
+	int err = 0;
+
+	priv = netdev_priv(net_dev);
+	percpu_priv = this_cpu_ptr(priv->percpu_priv);
+	percpu_stats = &percpu_priv->stats;
+
+	qm_fd_clear_fd(&fd);
+
+	if (!nonlinear) {
+		/* We're going to store the skb backpointer at the beginning
+		 * of the data buffer, so we need a privately owned skb
+		 *
+		 * We've made sure skb is not shared in dev->priv_flags,
+		 * we need to verify the skb head is not cloned
+		 */
+		if (skb_cow_head(skb, priv->tx_headroom))
+			goto enomem;
+
+		WARN_ON(skb_is_nonlinear(skb));
+	}
+
+	/* MAX_SKB_FRAGS is equal or larger than our dpaa_SGT_MAX_ENTRIES;
+	 * make sure we don't feed FMan with more fragments than it supports.
+	 */
+	if (nonlinear &&
+	    likely(skb_shinfo(skb)->nr_frags < DPAA_SGT_MAX_ENTRIES)) {
+		/* Just create a S/G fd based on the skb */
+		err = skb_to_sg_fd(priv, skb, &fd);
+		percpu_priv->tx_frag_skbuffs++;
+	} else {
+		/* If the egress skb contains more fragments than we support
+		 * we have no choice but to linearize it ourselves.
+		 */
+		if (unlikely(nonlinear) && __skb_linearize(skb))
+			goto enomem;
+
+		/* Finally, create a contig FD from this skb */
+		err = skb_to_contig_fd(priv, skb, &fd, &offset);
+	}
+	if (unlikely(err < 0))
+		goto skb_to_fd_failed;
+
+	if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
+		return NETDEV_TX_OK;
+
+	dpaa_cleanup_tx_fd(priv, &fd);
+skb_to_fd_failed:
+enomem:
+	percpu_stats->tx_errors++;
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static void dpaa_rx_error(struct net_device *net_dev,
+			  const struct dpaa_priv *priv,
+			  struct dpaa_percpu_priv *percpu_priv,
+			  const struct qm_fd *fd,
+			  u32 fqid)
+{
+	if (net_ratelimit())
+		netif_err(priv, hw, net_dev, "Err FD status = 0x%08x\n",
+			  be32_to_cpu(fd->status) & FM_FD_STAT_RX_ERRORS);
+
+	percpu_priv->stats.rx_errors++;
+
+	if (be32_to_cpu(fd->status) & FM_FD_ERR_DMA)
+		percpu_priv->rx_errors.dme++;
+	if (be32_to_cpu(fd->status) & FM_FD_ERR_PHYSICAL)
+		percpu_priv->rx_errors.fpe++;
+	if (be32_to_cpu(fd->status) & FM_FD_ERR_SIZE)
+		percpu_priv->rx_errors.fse++;
+	if (be32_to_cpu(fd->status) & FM_FD_ERR_PRS_HDR_ERR)
+		percpu_priv->rx_errors.phe++;
+
+	dpaa_fd_release(net_dev, fd);
+}
+
+static void dpaa_tx_error(struct net_device *net_dev,
+			  const struct dpaa_priv *priv,
+			  struct dpaa_percpu_priv *percpu_priv,
+			  const struct qm_fd *fd,
+			  u32 fqid)
+{
+	struct sk_buff *skb;
+
+	if (net_ratelimit())
+		netif_warn(priv, hw, net_dev, "FD status = 0x%08x\n",
+			   be32_to_cpu(fd->status) & FM_FD_STAT_TX_ERRORS);
+
+	percpu_priv->stats.tx_errors++;
+
+	skb = dpaa_cleanup_tx_fd(priv, fd);
+	dev_kfree_skb(skb);
+}
+
+static int dpaa_eth_poll(struct napi_struct *napi, int budget)
+{
+	struct dpaa_napi_portal *np =
+			container_of(napi, struct dpaa_napi_portal, napi);
+
+	int cleaned = qman_p_poll_dqrr(np->p, budget);
+
+	if (cleaned < budget) {
+		napi_complete(napi);
+		qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
+
+	} else if (np->down) {
+		qman_p_irqsource_add(np->p, QM_PIRQ_DQRI);
+	}
+
+	return cleaned;
+}
+
+static void dpaa_tx_conf(struct net_device *net_dev,
+			 const struct dpaa_priv *priv,
+			 struct dpaa_percpu_priv *percpu_priv,
+			 const struct qm_fd *fd,
+			 u32 fqid)
+{
+	struct sk_buff	*skb;
+
+	if (unlikely(be32_to_cpu(fd->status) & FM_FD_STAT_TX_ERRORS)) {
+		if (net_ratelimit())
+			netif_warn(priv, hw, net_dev, "FD status = 0x%08x\n",
+				   be32_to_cpu(fd->status) &
+				   FM_FD_STAT_TX_ERRORS);
+
+		percpu_priv->stats.tx_errors++;
+	}
+
+	percpu_priv->tx_confirm++;
+
+	skb = dpaa_cleanup_tx_fd(priv, fd);
+
+	consume_skb(skb);
+}
+
+static inline int dpaa_eth_napi_schedule(struct dpaa_percpu_priv *percpu_priv,
+					 struct qman_portal *portal)
+{
+	if (unlikely(in_irq() || !in_serving_softirq())) {
+		/* Disable QMan IRQ and invoke NAPI */
+		qman_p_irqsource_remove(portal, QM_PIRQ_DQRI);
+
+		percpu_priv->np.p = portal;
+		napi_schedule(&percpu_priv->np.napi);
+		percpu_priv->in_interrupt++;
+		return 1;
+	}
+	return 0;
+}
+
+static enum qman_cb_dqrr_result rx_error_dqrr(struct qman_portal *portal,
+					      struct qman_fq *fq,
+					      const struct qm_dqrr_entry *dq)
+{
+	struct dpaa_fq *dpaa_fq = container_of(fq, struct dpaa_fq, fq_base);
+	struct dpaa_percpu_priv *percpu_priv;
+	struct net_device *net_dev;
+	struct dpaa_bp *dpaa_bp;
+	struct dpaa_priv *priv;
+
+	net_dev = dpaa_fq->net_dev;
+	priv = netdev_priv(net_dev);
+	dpaa_bp = dpaa_bpid2pool(dq->fd.bpid);
+	if (!dpaa_bp)
+		return qman_cb_dqrr_consume;
+
+	percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+	if (dpaa_eth_napi_schedule(percpu_priv, portal))
+		return qman_cb_dqrr_stop;
+
+	if (dpaa_eth_refill_bpools(priv))
+		/* Unable to refill the buffer pool due to insufficient
+		 * system memory. Just release the frame back into the pool,
+		 * otherwise we'll soon end up with an empty buffer pool.
+		 */
+		dpaa_fd_release(net_dev, &dq->fd);
+	else
+		dpaa_rx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+	return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result rx_default_dqrr(struct qman_portal *portal,
+						struct qman_fq *fq,
+						const struct qm_dqrr_entry *dq)
+{
+	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa_percpu_priv *percpu_priv;
+	const struct qm_fd *fd = &dq->fd;
+	dma_addr_t addr = qm_fd_addr(fd);
+	enum qm_fd_format fd_format;
+	struct net_device *net_dev;
+	u32 fd_status = fd->status;
+	struct dpaa_bp *dpaa_bp;
+	struct dpaa_priv *priv;
+	unsigned int skb_len;
+	struct sk_buff *skb;
+	int *count_ptr;
+
+	fd_status = be32_to_cpu(fd->status);
+	fd_format = qm_fd_get_format(fd);
+	net_dev = ((struct dpaa_fq *)fq)->net_dev;
+	priv = netdev_priv(net_dev);
+	dpaa_bp = dpaa_bpid2pool(dq->fd.bpid);
+	if (!dpaa_bp)
+		return qman_cb_dqrr_consume;
+
+	/* Trace the Rx fd */
+	trace_dpaa_rx_fd(net_dev, fq, &dq->fd);
+
+	percpu_priv = this_cpu_ptr(priv->percpu_priv);
+	percpu_stats = &percpu_priv->stats;
+
+	if (unlikely(dpaa_eth_napi_schedule(percpu_priv, portal)))
+		return qman_cb_dqrr_stop;
+
+	/* Make sure we didn't run out of buffers */
+	if (unlikely(dpaa_eth_refill_bpools(priv))) {
+		/* Unable to refill the buffer pool due to insufficient
+		 * system memory. Just release the frame back into the pool,
+		 * otherwise we'll soon end up with an empty buffer pool.
+		 */
+		dpaa_fd_release(net_dev, &dq->fd);
+		return qman_cb_dqrr_consume;
+	}
+
+	if (unlikely(fd_status & FM_FD_STAT_RX_ERRORS) != 0) {
+		if (net_ratelimit())
+			netif_warn(priv, hw, net_dev, "FD status = 0x%08x\n",
+				   fd_status & FM_FD_STAT_RX_ERRORS);
+
+		percpu_stats->rx_errors++;
+		dpaa_fd_release(net_dev, fd);
+		return qman_cb_dqrr_consume;
+	}
+
+	dpaa_bp = dpaa_bpid2pool(fd->bpid);
+	if (!dpaa_bp)
+		return qman_cb_dqrr_consume;
+
+	dma_unmap_single(dpaa_bp->dev, addr, dpaa_bp->size, DMA_FROM_DEVICE);
+
+	/* prefetch the first 64 bytes of the frame or the SGT start */
+	prefetch(phys_to_virt(addr) + qm_fd_get_offset(fd));
+
+	fd_format = qm_fd_get_format(fd);
+	/* The only FD types that we may receive are contig and S/G */
+	WARN_ON((fd_format != qm_fd_contig) && (fd_format != qm_fd_sg));
+
+	/* Account for either the contig buffer or the SGT buffer (depending on
+	 * which case we were in) having been removed from the pool.
+	 */
+	count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+	(*count_ptr)--;
+
+	if (likely(fd_format == qm_fd_contig))
+		skb = contig_fd_to_skb(priv, fd);
+	else
+		skb = sg_fd_to_skb(priv, fd);
+	if (!skb)
+		return qman_cb_dqrr_consume;
+
+	skb->protocol = eth_type_trans(skb, net_dev);
+
+	skb_len = skb->len;
+
+	if (unlikely(netif_receive_skb(skb) == NET_RX_DROP))
+		return qman_cb_dqrr_consume;
+
+	percpu_stats->rx_packets++;
+	percpu_stats->rx_bytes += skb_len;
+
+	return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result conf_error_dqrr(struct qman_portal *portal,
+						struct qman_fq *fq,
+						const struct qm_dqrr_entry *dq)
+{
+	struct dpaa_percpu_priv *percpu_priv;
+	struct net_device *net_dev;
+	struct dpaa_priv *priv;
+
+	net_dev = ((struct dpaa_fq *)fq)->net_dev;
+	priv = netdev_priv(net_dev);
+
+	percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+	if (dpaa_eth_napi_schedule(percpu_priv, portal))
+		return qman_cb_dqrr_stop;
+
+	dpaa_tx_error(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+	return qman_cb_dqrr_consume;
+}
+
+static enum qman_cb_dqrr_result conf_dflt_dqrr(struct qman_portal *portal,
+					       struct qman_fq *fq,
+					       const struct qm_dqrr_entry *dq)
+{
+	struct dpaa_percpu_priv *percpu_priv;
+	struct net_device *net_dev;
+	struct dpaa_priv *priv;
+
+	net_dev = ((struct dpaa_fq *)fq)->net_dev;
+	priv = netdev_priv(net_dev);
+
+	/* Trace the fd */
+	trace_dpaa_tx_conf_fd(net_dev, fq, &dq->fd);
+
+	percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+	if (dpaa_eth_napi_schedule(percpu_priv, portal))
+		return qman_cb_dqrr_stop;
+
+	dpaa_tx_conf(net_dev, priv, percpu_priv, &dq->fd, fq->fqid);
+
+	return qman_cb_dqrr_consume;
+}
+
+static void egress_ern(struct qman_portal *portal,
+		       struct qman_fq *fq,
+		       const union qm_mr_entry *msg)
+{
+	const struct qm_fd *fd = &msg->ern.fd;
+	struct dpaa_percpu_priv *percpu_priv;
+	const struct dpaa_priv *priv;
+	struct net_device *net_dev;
+	struct sk_buff *skb;
+
+	net_dev = ((struct dpaa_fq *)fq)->net_dev;
+	priv = netdev_priv(net_dev);
+	percpu_priv = this_cpu_ptr(priv->percpu_priv);
+
+	percpu_priv->stats.tx_dropped++;
+	percpu_priv->stats.tx_fifo_errors++;
+	count_ern(percpu_priv, msg);
+
+	skb = dpaa_cleanup_tx_fd(priv, fd);
+	dev_kfree_skb_any(skb);
+}
+
+static const struct dpaa_fq_cbs dpaa_fq_cbs = {
+	.rx_defq = { .cb = { .dqrr = rx_default_dqrr } },
+	.tx_defq = { .cb = { .dqrr = conf_dflt_dqrr } },
+	.rx_errq = { .cb = { .dqrr = rx_error_dqrr } },
+	.tx_errq = { .cb = { .dqrr = conf_error_dqrr } },
+	.egress_ern = { .cb = { .ern = egress_ern } }
+};
+
+static void dpaa_eth_napi_enable(struct dpaa_priv *priv)
+{
+	struct dpaa_percpu_priv *percpu_priv;
+	int i;
+
+	for_each_possible_cpu(i) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+		percpu_priv->np.down = 0;
+		napi_enable(&percpu_priv->np.napi);
+	}
+}
+
+static void dpaa_eth_napi_disable(struct dpaa_priv *priv)
+{
+	struct dpaa_percpu_priv *percpu_priv;
+	int i;
+
+	for_each_possible_cpu(i) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+
+		percpu_priv->np.down = 1;
+		napi_disable(&percpu_priv->np.napi);
+	}
+}
+
+static int dpaa_open(struct net_device *net_dev)
+{
+	struct mac_device *mac_dev;
+	struct dpaa_priv *priv;
+	int err, i;
+
+	priv = netdev_priv(net_dev);
+	mac_dev = priv->mac_dev;
+	dpaa_eth_napi_enable(priv);
+
+	net_dev->phydev = mac_dev->init_phy(net_dev, priv->mac_dev);
+	if (!net_dev->phydev) {
+		netif_err(priv, ifup, net_dev, "init_phy() failed\n");
+		err = -ENODEV;
+		goto phy_init_failed;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
+		err = fman_port_enable(mac_dev->port[i]);
+		if (err)
+			goto mac_start_failed;
+	}
+
+	err = priv->mac_dev->start(mac_dev);
+	if (err < 0) {
+		netif_err(priv, ifup, net_dev, "mac_dev->start() = %d\n", err);
+		goto mac_start_failed;
+	}
+
+	netif_tx_start_all_queues(net_dev);
+
+	return 0;
+
+mac_start_failed:
+	for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++)
+		fman_port_disable(mac_dev->port[i]);
+
+phy_init_failed:
+	dpaa_eth_napi_disable(priv);
+
+	return err;
+}
+
+static int dpaa_eth_stop(struct net_device *net_dev)
+{
+	struct dpaa_priv *priv;
+	int err;
+
+	err = dpaa_stop(net_dev);
+
+	priv = netdev_priv(net_dev);
+	dpaa_eth_napi_disable(priv);
+
+	return err;
+}
+
+static const struct net_device_ops dpaa_ops = {
+	.ndo_open = dpaa_open,
+	.ndo_start_xmit = dpaa_start_xmit,
+	.ndo_stop = dpaa_eth_stop,
+	.ndo_tx_timeout = dpaa_tx_timeout,
+	.ndo_get_stats64 = dpaa_get_stats64,
+	.ndo_set_mac_address = dpaa_set_mac_address,
+	.ndo_validate_addr = eth_validate_addr,
+	.ndo_set_rx_mode = dpaa_set_rx_mode,
+};
+
+static int dpaa_napi_add(struct net_device *net_dev)
+{
+	struct dpaa_priv *priv = netdev_priv(net_dev);
+	struct dpaa_percpu_priv *percpu_priv;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+		netif_napi_add(net_dev, &percpu_priv->np.napi,
+			       dpaa_eth_poll, NAPI_POLL_WEIGHT);
+	}
+
+	return 0;
+}
+
+static void dpaa_napi_del(struct net_device *net_dev)
+{
+	struct dpaa_priv *priv = netdev_priv(net_dev);
+	struct dpaa_percpu_priv *percpu_priv;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, cpu);
+
+		netif_napi_del(&percpu_priv->np.napi);
+	}
+}
+
+static inline void dpaa_bp_free_pf(const struct dpaa_bp *bp,
+				   struct bm_buffer *bmb)
+{
+	dma_addr_t addr = bm_buf_addr(bmb);
+
+	dma_unmap_single(bp->dev, addr, bp->size, DMA_FROM_DEVICE);
+
+	skb_free_frag(phys_to_virt(addr));
+}
+
+/* Alloc the dpaa_bp struct and configure default values */
+static struct dpaa_bp *dpaa_bp_alloc(struct device *dev)
+{
+	struct dpaa_bp *dpaa_bp;
+
+	dpaa_bp = devm_kzalloc(dev, sizeof(*dpaa_bp), GFP_KERNEL);
+	if (!dpaa_bp)
+		return ERR_PTR(-ENOMEM);
+
+	dpaa_bp->bpid = FSL_DPAA_BPID_INV;
+	dpaa_bp->percpu_count = devm_alloc_percpu(dev, *dpaa_bp->percpu_count);
+	dpaa_bp->config_count = FSL_DPAA_ETH_MAX_BUF_COUNT;
+
+	dpaa_bp->seed_cb = dpaa_bp_seed;
+	dpaa_bp->free_buf_cb = dpaa_bp_free_pf;
+
+	return dpaa_bp;
+}
+
+/* Place all ingress FQs (Rx Default, Rx Error) in a dedicated CGR.
+ * We won't be sending congestion notifications to FMan; for now, we just use
+ * this CGR to generate enqueue rejections to FMan in order to drop the frames
+ * before they reach our ingress queues and eat up memory.
+ */
+static int dpaa_ingress_cgr_init(struct dpaa_priv *priv)
+{
+	struct qm_mcc_initcgr initcgr;
+	u32 cs_th;
+	int err;
+
+	err = qman_alloc_cgrid(&priv->ingress_cgr.cgrid);
+	if (err < 0) {
+		if (netif_msg_drv(priv))
+			pr_err("Error %d allocating CGR ID\n", err);
+		goto out_error;
+	}
+
+	/* Enable CS TD, but disable Congestion State Change Notifications. */
+	memset(&initcgr, 0, sizeof(initcgr));
+	initcgr.we_mask = cpu_to_be16(QM_CGR_WE_CS_THRES);
+	initcgr.cgr.cscn_en = QM_CGR_EN;
+	cs_th = DPAA_INGRESS_CS_THRESHOLD;
+	qm_cgr_cs_thres_set64(&initcgr.cgr.cs_thres, cs_th, 1);
+
+	initcgr.we_mask |= cpu_to_be16(QM_CGR_WE_CSTD_EN);
+	initcgr.cgr.cstd_en = QM_CGR_EN;
+
+	/* This CGR will be associated with the SWP affined to the current CPU.
+	 * However, we'll place all our ingress FQs in it.
+	 */
+	err = qman_create_cgr(&priv->ingress_cgr, QMAN_CGR_FLAG_USE_INIT,
+			      &initcgr);
+	if (err < 0) {
+		if (netif_msg_drv(priv))
+			pr_err("Error %d creating ingress CGR with ID %d\n",
+			       err, priv->ingress_cgr.cgrid);
+		qman_release_cgrid(priv->ingress_cgr.cgrid);
+		goto out_error;
+	}
+	if (netif_msg_drv(priv))
+		pr_debug("Created ingress CGR %d for netdev with hwaddr %pM\n",
+			 priv->ingress_cgr.cgrid, priv->mac_dev->addr);
+
+	priv->use_ingress_cgr = true;
+
+out_error:
+	return err;
+}
+
+static const struct of_device_id dpaa_match[];
+
+static inline u16 dpaa_get_headroom(struct dpaa_buffer_layout *bl)
+{
+	u16 headroom;
+
+	/* The frame headroom must accommodate:
+	 * - the driver private data area
+	 * - parse results, hash results, timestamp if selected
+	 * If either hash results or time stamp are selected, both will
+	 * be copied to/from the frame headroom, as TS is located between PR and
+	 * HR in the IC and IC copy size has a granularity of 16bytes
+	 * (see description of FMBM_RICP and FMBM_TICP registers in DPAARM)
+	 *
+	 * Also make sure the headroom is a multiple of data_align bytes
+	 */
+	headroom = (u16)(bl->priv_data_size + DPAA_PARSE_RESULTS_SIZE +
+		DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE);
+
+	return DPAA_FD_DATA_ALIGNMENT ? ALIGN(headroom,
+					      DPAA_FD_DATA_ALIGNMENT) :
+					headroom;
+}
+
+static int dpaa_eth_probe(struct platform_device *pdev)
+{
+	struct dpaa_bp *dpaa_bps[DPAA_BPS_NUM] = {NULL};
+	struct dpaa_percpu_priv *percpu_priv;
+	struct net_device *net_dev = NULL;
+	struct dpaa_fq *dpaa_fq, *tmp;
+	struct dpaa_priv *priv = NULL;
+	struct fm_port_fqs port_fqs;
+	struct mac_device *mac_dev;
+	int err = 0, i, channel;
+	struct device *dev;
+
+	dev = &pdev->dev;
+
+	/* Allocate this early, so we can store relevant information in
+	 * the private area
+	 */
+	net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA_ETH_TXQ_NUM);
+	if (!net_dev) {
+		dev_err(dev, "alloc_etherdev_mq() failed\n");
+		goto alloc_etherdev_mq_failed;
+	}
+
+	/* Do this here, so we can be verbose early */
+	SET_NETDEV_DEV(net_dev, dev);
+	dev_set_drvdata(dev, net_dev);
+
+	priv = netdev_priv(net_dev);
+	priv->net_dev = net_dev;
+
+	priv->msg_enable = netif_msg_init(debug, DPAA_MSG_DEFAULT);
+
+	mac_dev = dpaa_mac_dev_get(pdev);
+	if (IS_ERR(mac_dev)) {
+		dev_err(dev, "dpaa_mac_dev_get() failed\n");
+		err = PTR_ERR(mac_dev);
+		goto mac_probe_failed;
+	}
+
+	/* If fsl_fm_max_frm is set to a higher value than the all-common 1500,
+	 * we choose conservatively and let the user explicitly set a higher
+	 * MTU via ifconfig. Otherwise, the user may end up with different MTUs
+	 * in the same LAN.
+	 * If on the other hand fsl_fm_max_frm has been chosen below 1500,
+	 * start with the maximum allowed.
+	 */
+	net_dev->mtu = min(dpaa_get_max_mtu(), ETH_DATA_LEN);
+
+	netdev_dbg(net_dev, "Setting initial MTU on net device: %d\n",
+		   net_dev->mtu);
+
+	priv->buf_layout[RX].priv_data_size = DPAA_RX_PRIV_DATA_SIZE; /* Rx */
+	priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx */
+
+	/* device used for DMA mapping */
+	arch_setup_dma_ops(dev, 0, 0, NULL, false);
+	err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
+	if (err) {
+		dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
+		goto dev_mask_failed;
+	}
+
+	/* bp init */
+	for (i = 0; i < DPAA_BPS_NUM; i++) {
+		int err;
+
+		dpaa_bps[i] = dpaa_bp_alloc(dev);
+		if (IS_ERR(dpaa_bps[i]))
+			return PTR_ERR(dpaa_bps[i]);
+		/* the raw size of the buffers used for reception */
+		dpaa_bps[i]->raw_size = bpool_buffer_raw_size(i, DPAA_BPS_NUM);
+		/* avoid runtime computations by keeping the usable size here */
+		dpaa_bps[i]->size = dpaa_bp_size(dpaa_bps[i]->raw_size);
+		dpaa_bps[i]->dev = dev;
+
+		err = dpaa_bp_alloc_pool(dpaa_bps[i]);
+		if (err < 0) {
+			dpaa_bps_free(priv);
+			priv->dpaa_bps[i] = NULL;
+			goto bp_create_failed;
+		}
+		priv->dpaa_bps[i] = dpaa_bps[i];
+	}
+
+	INIT_LIST_HEAD(&priv->dpaa_fq_list);
+
+	memset(&port_fqs, 0, sizeof(port_fqs));
+
+	err = dpaa_alloc_all_fqs(dev, &priv->dpaa_fq_list, &port_fqs);
+	if (err < 0) {
+		dev_err(dev, "dpaa_alloc_all_fqs() failed\n");
+		goto fq_probe_failed;
+	}
+
+	priv->mac_dev = mac_dev;
+
+	channel = dpaa_get_channel();
+	if (channel < 0) {
+		dev_err(dev, "dpaa_get_channel() failed\n");
+		err = channel;
+		goto get_channel_failed;
+	}
+
+	priv->channel = (u16)channel;
+
+	/* Start a thread that will walk the CPUs with affine portals
+	 * and add this pool channel to each's dequeue mask.
+	 */
+	dpaa_eth_add_channel(priv->channel);
+
+	dpaa_fq_setup(priv, &dpaa_fq_cbs, priv->mac_dev->port[TX]);
+
+	/* Create a congestion group for this netdev, with
+	 * dynamically-allocated CGR ID.
+	 * Must be executed after probing the MAC, but before
+	 * assigning the egress FQs to the CGRs.
+	 */
+	err = dpaa_eth_cgr_init(priv);
+	if (err < 0) {
+		dev_err(dev, "Error initializing CGR\n");
+		goto tx_cgr_init_failed;
+	}
+
+	err = dpaa_ingress_cgr_init(priv);
+	if (err < 0) {
+		dev_err(dev, "Error initializing ingress CGR\n");
+		goto rx_cgr_init_failed;
+	}
+
+	/* Add the FQs to the interface, and make them active */
+	list_for_each_entry_safe(dpaa_fq, tmp, &priv->dpaa_fq_list, list) {
+		err = dpaa_fq_init(dpaa_fq, false);
+		if (err < 0)
+			goto fq_alloc_failed;
+	}
+
+	priv->tx_headroom = dpaa_get_headroom(&priv->buf_layout[TX]);
+	priv->rx_headroom = dpaa_get_headroom(&priv->buf_layout[RX]);
+
+	/* All real interfaces need their ports initialized */
+	dpaa_eth_init_ports(mac_dev, dpaa_bps, DPAA_BPS_NUM, &port_fqs,
+			    &priv->buf_layout[0], dev);
+
+	priv->percpu_priv = devm_alloc_percpu(dev, *priv->percpu_priv);
+	if (!priv->percpu_priv) {
+		dev_err(dev, "devm_alloc_percpu() failed\n");
+		err = -ENOMEM;
+		goto alloc_percpu_failed;
+	}
+	for_each_possible_cpu(i) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+		memset(percpu_priv, 0, sizeof(*percpu_priv));
+	}
+
+	/* Initialize NAPI */
+	err = dpaa_napi_add(net_dev);
+	if (err < 0)
+		goto napi_add_failed;
+
+	err = dpaa_netdev_init(net_dev, &dpaa_ops, tx_timeout);
+	if (err < 0)
+		goto netdev_init_failed;
+
+	dpaa_eth_sysfs_init(&net_dev->dev);
+
+	netif_info(priv, probe, net_dev, "Probed interface %s\n",
+		   net_dev->name);
+
+	return 0;
+
+netdev_init_failed:
+napi_add_failed:
+	dpaa_napi_del(net_dev);
+alloc_percpu_failed:
+	dpaa_fq_free(dev, &priv->dpaa_fq_list);
+fq_alloc_failed:
+	qman_delete_cgr_safe(&priv->ingress_cgr);
+	qman_release_cgrid(priv->ingress_cgr.cgrid);
+rx_cgr_init_failed:
+	qman_delete_cgr_safe(&priv->cgr_data.cgr);
+	qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+tx_cgr_init_failed:
+get_channel_failed:
+	dpaa_bps_free(priv);
+bp_create_failed:
+fq_probe_failed:
+dev_mask_failed:
+mac_probe_failed:
+	dev_set_drvdata(dev, NULL);
+	free_netdev(net_dev);
+alloc_etherdev_mq_failed:
+	for (i = 0; i < DPAA_BPS_NUM && dpaa_bps[i]; i++) {
+		if (atomic_read(&dpaa_bps[i]->refs) == 0)
+			devm_kfree(dev, dpaa_bps[i]);
+	}
+	return err;
+}
+
+static int dpaa_remove(struct platform_device *pdev)
+{
+	struct net_device *net_dev;
+	struct dpaa_priv *priv;
+	struct device *dev;
+	int err;
+
+	dev = &pdev->dev;
+	net_dev = dev_get_drvdata(dev);
+
+	priv = netdev_priv(net_dev);
+
+	dpaa_eth_sysfs_remove(dev);
+
+	dev_set_drvdata(dev, NULL);
+	unregister_netdev(net_dev);
+
+	err = dpaa_fq_free(dev, &priv->dpaa_fq_list);
+
+	qman_delete_cgr_safe(&priv->ingress_cgr);
+	qman_release_cgrid(priv->ingress_cgr.cgrid);
+	qman_delete_cgr_safe(&priv->cgr_data.cgr);
+	qman_release_cgrid(priv->cgr_data.cgr.cgrid);
+
+	dpaa_napi_del(net_dev);
+
+	dpaa_bps_free(priv);
+
+	free_netdev(net_dev);
+
+	return err;
+}
+
+static struct platform_device_id dpaa_devtype[] = {
+	{
+		.name = "dpaa-ethernet",
+		.driver_data = 0,
+	}, {
+	}
+};
+MODULE_DEVICE_TABLE(platform, dpaa_devtype);
+
+static struct platform_driver dpaa_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+	},
+	.id_table = dpaa_devtype,
+	.probe = dpaa_eth_probe,
+	.remove = dpaa_remove
+};
+
+static int __init dpaa_load(void)
+{
+	int err;
+
+	pr_debug("FSL DPAA Ethernet driver\n");
+
+	/* initialize dpaa_eth mirror values */
+	dpaa_rx_extra_headroom = fman_get_rx_extra_headroom();
+	dpaa_max_frm = fman_get_max_frm();
+
+	err = platform_driver_register(&dpaa_driver);
+	if (err < 0)
+		pr_err("Error, platform_driver_register() = %d\n", err);
+
+	return err;
+}
+module_init(dpaa_load);
+
+static void __exit dpaa_unload(void)
+{
+	platform_driver_unregister(&dpaa_driver);
+
+	/* Only one channel is used and needs to be released after all
+	 * interfaces are removed
+	 */
+	dpaa_release_channel();
+}
+module_exit(dpaa_unload);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("FSL DPAA Ethernet driver");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,185 @@
+/* Copyright 2008 - 2016 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.
+ */
+
+#ifndef __DPAA_H
+#define __DPAA_H
+
+#include <linux/netdevice.h>
+#include <soc/fsl/qman.h>
+#include <soc/fsl/bman.h>
+
+#include "fman.h"
+#include "mac.h"
+#include "dpaa_eth_trace.h"
+
+#define DPAA_ETH_TXQ_NUM	NR_CPUS
+
+#define DPAA_BPS_NUM 3 /* number of bpools per interface */
+
+/* More detailed FQ types - used for fine-grained WQ assignments */
+enum dpaa_fq_type {
+	FQ_TYPE_RX_DEFAULT = 1, /* Rx Default FQs */
+	FQ_TYPE_RX_ERROR,	/* Rx Error FQs */
+	FQ_TYPE_TX,		/* "Real" Tx FQs */
+	FQ_TYPE_TX_CONFIRM,	/* Tx default Conf FQ (actually an Rx FQ) */
+	FQ_TYPE_TX_CONF_MQ,	/* Tx conf FQs (one for each Tx FQ) */
+	FQ_TYPE_TX_ERROR,	/* Tx Error FQs (these are actually Rx FQs) */
+};
+
+struct dpaa_fq {
+	struct qman_fq fq_base;
+	struct list_head list;
+	struct net_device *net_dev;
+	bool init;
+	u32 fqid;
+	u32 flags;
+	u16 channel;
+	u8 wq;
+	enum dpaa_fq_type fq_type;
+};
+
+struct dpaa_fq_cbs {
+	struct qman_fq rx_defq;
+	struct qman_fq tx_defq;
+	struct qman_fq rx_errq;
+	struct qman_fq tx_errq;
+	struct qman_fq egress_ern;
+};
+
+struct dpaa_bp {
+	/* device used in the DMA mapping operations */
+	struct device *dev;
+	/* current number of buffers in the buffer pool alloted to each CPU */
+	int __percpu *percpu_count;
+	/* all buffers allocated for this pool have this raw size */
+	size_t raw_size;
+	/* all buffers in this pool have this same usable size */
+	size_t size;
+	/* the buffer pools are initialized with config_count buffers for each
+	 * CPU; at runtime the number of buffers per CPU is constantly brought
+	 * back to this level
+	 */
+	u16 config_count;
+	u8 bpid;
+	struct bman_pool *pool;
+	/* bpool can be seeded before use by this cb */
+	int (*seed_cb)(struct dpaa_bp *);
+	/* bpool can be emptied before freeing by this cb */
+	void (*free_buf_cb)(const struct dpaa_bp *, struct bm_buffer *);
+	atomic_t refs;
+};
+
+struct dpaa_rx_errors {
+	u64 dme;		/* DMA Error */
+	u64 fpe;		/* Frame Physical Error */
+	u64 fse;		/* Frame Size Error */
+	u64 phe;		/* Header Error */
+};
+
+/* Counters for QMan ERN frames - one counter per rejection code */
+struct dpaa_ern_cnt {
+	u64 cg_tdrop;		/* Congestion group taildrop */
+	u64 wred;		/* WRED congestion */
+	u64 err_cond;		/* Error condition */
+	u64 early_window;	/* Order restoration, frame too early */
+	u64 late_window;	/* Order restoration, frame too late */
+	u64 fq_tdrop;		/* FQ taildrop */
+	u64 fq_retired;		/* FQ is retired */
+	u64 orp_zero;		/* ORP disabled */
+};
+
+struct dpaa_napi_portal {
+	struct napi_struct napi;
+	struct qman_portal *p;
+	bool down;
+};
+
+struct dpaa_percpu_priv {
+	struct net_device *net_dev;
+	struct dpaa_napi_portal np;
+	u64 in_interrupt;
+	u64 tx_confirm;
+	/* fragmented (non-linear) skbuffs received from the stack */
+	u64 tx_frag_skbuffs;
+	struct rtnl_link_stats64 stats;
+	struct dpaa_rx_errors rx_errors;
+	struct dpaa_ern_cnt ern_cnt;
+};
+
+struct dpaa_buffer_layout {
+	u16 priv_data_size;
+};
+
+struct dpaa_priv {
+	struct dpaa_percpu_priv __percpu *percpu_priv;
+	struct dpaa_bp *dpaa_bps[DPAA_BPS_NUM];
+	/* Store here the needed Tx headroom for convenience and speed
+	 * (even though it can be computed based on the fields of buf_layout)
+	 */
+	u16 tx_headroom;
+	struct net_device *net_dev;
+	struct mac_device *mac_dev;
+	struct qman_fq *egress_fqs[DPAA_ETH_TXQ_NUM];
+	struct qman_fq *conf_fqs[DPAA_ETH_TXQ_NUM];
+
+	u16 channel;
+	struct list_head dpaa_fq_list;
+
+	u32 msg_enable;	/* net_device message level */
+
+	struct {
+		/* All egress queues to a given net device belong to one
+		 * (and the same) congestion group.
+		 */
+		struct qman_cgr cgr;
+		/* If congested, when it began. Used for performance stats. */
+		u32 congestion_start_jiffies;
+		/* Number of jiffies the Tx port was congested. */
+		u32 congested_jiffies;
+		/* Counter for the number of times the CGR
+		 * entered congestion state
+		 */
+		u32 cgr_congested_count;
+	} cgr_data;
+	/* Use a per-port CGR for ingress traffic. */
+	bool use_ingress_cgr;
+	struct qman_cgr ingress_cgr;
+
+	struct dpaa_buffer_layout buf_layout[2];
+	u16 rx_headroom;
+};
+
+/* from dpaa_ethtool.c */
+extern const struct ethtool_ops dpaa_ethtool_ops;
+
+/* from dpaa_eth_sysfs.c */
+void dpaa_eth_sysfs_remove(struct device *dev);
+void dpaa_eth_sysfs_init(struct device *dev);
+#endif	/* __DPAA_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_sysfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,165 @@
+/* Copyright 2008-2016 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 <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of_net.h>
+#include "dpaa_eth.h"
+#include "mac.h"
+
+static ssize_t dpaa_eth_show_addr(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
+	struct mac_device *mac_dev = priv->mac_dev;
+
+	if (mac_dev)
+		return sprintf(buf, "%llx",
+				(unsigned long long)mac_dev->res->start);
+	else
+		return sprintf(buf, "none");
+}
+
+static ssize_t dpaa_eth_show_fqids(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
+	struct dpaa_fq *prev = NULL;
+	char *prevstr = NULL;
+	struct dpaa_fq *tmp;
+	struct dpaa_fq *fq;
+	u32 first_fqid = 0;
+	u32 last_fqid = 0;
+	ssize_t bytes = 0;
+	char *str;
+	int i = 0;
+
+	list_for_each_entry_safe(fq, tmp, &priv->dpaa_fq_list, list) {
+		switch (fq->fq_type) {
+		case FQ_TYPE_RX_DEFAULT:
+			str = "Rx default";
+			break;
+		case FQ_TYPE_RX_ERROR:
+			str = "Rx error";
+			break;
+		case FQ_TYPE_TX_CONFIRM:
+			str = "Tx default confirmation";
+			break;
+		case FQ_TYPE_TX_CONF_MQ:
+			str = "Tx confirmation (mq)";
+			break;
+		case FQ_TYPE_TX_ERROR:
+			str = "Tx error";
+			break;
+		case FQ_TYPE_TX:
+			str = "Tx";
+			break;
+		default:
+			str = "Unknown";
+		}
+
+		if (prev && (abs(fq->fqid - prev->fqid) != 1 ||
+			     str != prevstr)) {
+			if (last_fqid == first_fqid)
+				bytes += sprintf(buf + bytes,
+					"%s: %d\n", prevstr, prev->fqid);
+			else
+				bytes += sprintf(buf + bytes,
+					"%s: %d - %d\n", prevstr,
+					first_fqid, last_fqid);
+		}
+
+		if (prev && abs(fq->fqid - prev->fqid) == 1 &&
+		    str == prevstr) {
+			last_fqid = fq->fqid;
+		} else {
+			first_fqid = fq->fqid;
+			last_fqid = fq->fqid;
+		}
+
+		prev = fq;
+		prevstr = str;
+		i++;
+	}
+
+	if (prev) {
+		if (last_fqid == first_fqid)
+			bytes += sprintf(buf + bytes, "%s: %d\n", prevstr,
+					prev->fqid);
+		else
+			bytes += sprintf(buf + bytes, "%s: %d - %d\n", prevstr,
+					first_fqid, last_fqid);
+	}
+
+	return bytes;
+}
+
+static ssize_t dpaa_eth_show_bpids(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct dpaa_priv *priv = netdev_priv(to_net_dev(dev));
+	ssize_t bytes = 0;
+	int i = 0;
+
+	for (i = 0; i < DPAA_BPS_NUM; i++)
+		bytes += snprintf(buf + bytes, PAGE_SIZE - bytes, "%u\n",
+				  priv->dpaa_bps[i]->bpid);
+
+	return bytes;
+}
+
+static struct device_attribute dpaa_eth_attrs[] = {
+	__ATTR(device_addr, 0444, dpaa_eth_show_addr, NULL),
+	__ATTR(fqids, 0444, dpaa_eth_show_fqids, NULL),
+	__ATTR(bpids, 0444, dpaa_eth_show_bpids, NULL),
+};
+
+void dpaa_eth_sysfs_init(struct device *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
+		if (device_create_file(dev, &dpaa_eth_attrs[i])) {
+			dev_err(dev, "Error creating sysfs file\n");
+			while (i > 0)
+				device_remove_file(dev, &dpaa_eth_attrs[--i]);
+			return;
+		}
+}
+
+void dpaa_eth_sysfs_remove(struct device *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa_eth_attrs); i++)
+		device_remove_file(dev, &dpaa_eth_attrs[i]);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,417 @@
+/* Copyright 2008-2016 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/string.h>
+
+#include "dpaa_eth.h"
+#include "mac.h"
+
+static const char dpaa_stats_percpu[][ETH_GSTRING_LEN] = {
+	"interrupts",
+	"rx packets",
+	"tx packets",
+	"tx confirm",
+	"tx S/G",
+	"tx error",
+	"rx error",
+};
+
+static char dpaa_stats_global[][ETH_GSTRING_LEN] = {
+	/* dpa rx errors */
+	"rx dma error",
+	"rx frame physical error",
+	"rx frame size error",
+	"rx header error",
+
+	/* demultiplexing errors */
+	"qman cg_tdrop",
+	"qman wred",
+	"qman error cond",
+	"qman early window",
+	"qman late window",
+	"qman fq tdrop",
+	"qman fq retired",
+	"qman orp disabled",
+
+	/* congestion related stats */
+	"congestion time (ms)",
+	"entered congestion",
+	"congested (0/1)"
+};
+
+#define DPAA_STATS_PERCPU_LEN ARRAY_SIZE(dpaa_stats_percpu)
+#define DPAA_STATS_GLOBAL_LEN ARRAY_SIZE(dpaa_stats_global)
+
+static int dpaa_get_settings(struct net_device *net_dev,
+			     struct ethtool_cmd *et_cmd)
+{
+	int err;
+
+	if (!net_dev->phydev) {
+		netdev_dbg(net_dev, "phy device not initialized\n");
+		return 0;
+	}
+
+	err = phy_ethtool_gset(net_dev->phydev, et_cmd);
+
+	return err;
+}
+
+static int dpaa_set_settings(struct net_device *net_dev,
+			     struct ethtool_cmd *et_cmd)
+{
+	int err;
+
+	if (!net_dev->phydev) {
+		netdev_err(net_dev, "phy device not initialized\n");
+		return -ENODEV;
+	}
+
+	err = phy_ethtool_sset(net_dev->phydev, et_cmd);
+	if (err < 0)
+		netdev_err(net_dev, "phy_ethtool_sset() = %d\n", err);
+
+	return err;
+}
+
+static void dpaa_get_drvinfo(struct net_device *net_dev,
+			     struct ethtool_drvinfo *drvinfo)
+{
+	int len;
+
+	strlcpy(drvinfo->driver, KBUILD_MODNAME,
+		sizeof(drvinfo->driver));
+	len = snprintf(drvinfo->version, sizeof(drvinfo->version),
+		       "%X", 0);
+	len = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+		       "%X", 0);
+
+	if (len >= sizeof(drvinfo->fw_version)) {
+		/* Truncated output */
+		netdev_notice(net_dev, "snprintf() = %d\n", len);
+	}
+	strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
+		sizeof(drvinfo->bus_info));
+}
+
+static u32 dpaa_get_msglevel(struct net_device *net_dev)
+{
+	return ((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable;
+}
+
+static void dpaa_set_msglevel(struct net_device *net_dev,
+			      u32 msg_enable)
+{
+	((struct dpaa_priv *)netdev_priv(net_dev))->msg_enable = msg_enable;
+}
+
+static int dpaa_nway_reset(struct net_device *net_dev)
+{
+	int err;
+
+	if (!net_dev->phydev) {
+		netdev_err(net_dev, "phy device not initialized\n");
+		return -ENODEV;
+	}
+
+	err = 0;
+	if (net_dev->phydev->autoneg) {
+		err = phy_start_aneg(net_dev->phydev);
+		if (err < 0)
+			netdev_err(net_dev, "phy_start_aneg() = %d\n",
+				   err);
+	}
+
+	return err;
+}
+
+static void dpaa_get_pauseparam(struct net_device *net_dev,
+				struct ethtool_pauseparam *epause)
+{
+	struct mac_device *mac_dev;
+	struct dpaa_priv *priv;
+
+	priv = netdev_priv(net_dev);
+	mac_dev = priv->mac_dev;
+
+	if (!net_dev->phydev) {
+		netdev_err(net_dev, "phy device not initialized\n");
+		return;
+	}
+
+	epause->autoneg = mac_dev->autoneg_pause;
+	epause->rx_pause = mac_dev->rx_pause_active;
+	epause->tx_pause = mac_dev->tx_pause_active;
+}
+
+static int dpaa_set_pauseparam(struct net_device *net_dev,
+			       struct ethtool_pauseparam *epause)
+{
+	struct mac_device *mac_dev;
+	struct phy_device *phydev;
+	bool rx_pause, tx_pause;
+	struct dpaa_priv *priv;
+	u32 newadv, oldadv;
+	int err;
+
+	priv = netdev_priv(net_dev);
+	mac_dev = priv->mac_dev;
+
+	phydev = net_dev->phydev;
+	if (!phydev) {
+		netdev_err(net_dev, "phy device not initialized\n");
+		return -ENODEV;
+	}
+
+	if (!(phydev->supported & SUPPORTED_Pause) ||
+	    (!(phydev->supported & SUPPORTED_Asym_Pause) &&
+	    (epause->rx_pause != epause->tx_pause)))
+		return -EINVAL;
+
+	/* The MAC should know how to handle PAUSE frame autonegotiation before
+	 * adjust_link is triggered by a forced renegotiation of sym/asym PAUSE
+	 * settings.
+	 */
+	mac_dev->autoneg_pause = !!epause->autoneg;
+	mac_dev->rx_pause_req = !!epause->rx_pause;
+	mac_dev->tx_pause_req = !!epause->tx_pause;
+
+	/* Determine the sym/asym advertised PAUSE capabilities from the desired
+	 * rx/tx pause settings.
+	 */
+	newadv = 0;
+	if (epause->rx_pause)
+		newadv = ADVERTISED_Pause | ADVERTISED_Asym_Pause;
+	if (epause->tx_pause)
+		newadv |= ADVERTISED_Asym_Pause;
+
+	oldadv = phydev->advertising &
+			(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
+
+	/* If there are differences between the old and the new advertised
+	 * values, restart PHY autonegotiation and advertise the new values.
+	 */
+	if (oldadv != newadv) {
+		phydev->advertising &= ~(ADVERTISED_Pause
+				| ADVERTISED_Asym_Pause);
+		phydev->advertising |= newadv;
+		if (phydev->autoneg) {
+			err = phy_start_aneg(phydev);
+			if (err < 0)
+				netdev_err(net_dev, "phy_start_aneg() = %d\n",
+					   err);
+		}
+	}
+
+	fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
+	err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
+	if (err < 0)
+		netdev_err(net_dev, "set_mac_active_pause() = %d\n", err);
+
+	return err;
+}
+
+static int dpaa_get_sset_count(struct net_device *net_dev, int type)
+{
+	unsigned int total_stats, num_stats;
+
+	num_stats   = num_online_cpus() + 1;
+	total_stats = num_stats * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM) +
+			DPAA_STATS_GLOBAL_LEN;
+
+	switch (type) {
+	case ETH_SS_STATS:
+		return total_stats;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void copy_stats(struct dpaa_percpu_priv *percpu_priv, int num_cpus,
+		       int crr_cpu, u64 *bp_count, u64 *data)
+{
+	int num_values = num_cpus + 1;
+	int crr = 0, j;
+
+	/* update current CPU's stats and also add them to the total values */
+	data[crr * num_values + crr_cpu] = percpu_priv->in_interrupt;
+	data[crr++ * num_values + num_cpus] += percpu_priv->in_interrupt;
+
+	data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_packets;
+	data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_packets;
+
+	data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_packets;
+	data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_packets;
+
+	data[crr * num_values + crr_cpu] = percpu_priv->tx_confirm;
+	data[crr++ * num_values + num_cpus] += percpu_priv->tx_confirm;
+
+	data[crr * num_values + crr_cpu] = percpu_priv->tx_frag_skbuffs;
+	data[crr++ * num_values + num_cpus] += percpu_priv->tx_frag_skbuffs;
+
+	data[crr * num_values + crr_cpu] = percpu_priv->stats.tx_errors;
+	data[crr++ * num_values + num_cpus] += percpu_priv->stats.tx_errors;
+
+	data[crr * num_values + crr_cpu] = percpu_priv->stats.rx_errors;
+	data[crr++ * num_values + num_cpus] += percpu_priv->stats.rx_errors;
+
+	for (j = 0; j < DPAA_BPS_NUM; j++) {
+		data[crr * num_values + crr_cpu] = bp_count[j];
+		data[crr++ * num_values + num_cpus] += bp_count[j];
+	}
+}
+
+static void dpaa_get_ethtool_stats(struct net_device *net_dev,
+				   struct ethtool_stats *stats, u64 *data)
+{
+	u64 bp_count[DPAA_BPS_NUM], cg_time, cg_num;
+	struct dpaa_percpu_priv *percpu_priv;
+	struct dpaa_rx_errors rx_errors;
+	unsigned int num_cpus, offset;
+	struct dpaa_ern_cnt ern_cnt;
+	struct dpaa_bp *dpaa_bp;
+	struct dpaa_priv *priv;
+	int total_stats, i, j;
+	bool cg_status;
+
+	total_stats = dpaa_get_sset_count(net_dev, ETH_SS_STATS);
+	priv     = netdev_priv(net_dev);
+	num_cpus = num_online_cpus();
+
+	memset(&bp_count, 0, sizeof(bp_count));
+	memset(&rx_errors, 0, sizeof(struct dpaa_rx_errors));
+	memset(&ern_cnt, 0, sizeof(struct dpaa_ern_cnt));
+	memset(data, 0, total_stats * sizeof(u64));
+
+	for_each_online_cpu(i) {
+		percpu_priv = per_cpu_ptr(priv->percpu_priv, i);
+		for (j = 0; j < DPAA_BPS_NUM; j++) {
+			dpaa_bp = priv->dpaa_bps[j];
+			if (!dpaa_bp->percpu_count)
+				continue;
+			bp_count[j] = *(per_cpu_ptr(dpaa_bp->percpu_count, i));
+		}
+		rx_errors.dme += percpu_priv->rx_errors.dme;
+		rx_errors.fpe += percpu_priv->rx_errors.fpe;
+		rx_errors.fse += percpu_priv->rx_errors.fse;
+		rx_errors.phe += percpu_priv->rx_errors.phe;
+
+		ern_cnt.cg_tdrop     += percpu_priv->ern_cnt.cg_tdrop;
+		ern_cnt.wred         += percpu_priv->ern_cnt.wred;
+		ern_cnt.err_cond     += percpu_priv->ern_cnt.err_cond;
+		ern_cnt.early_window += percpu_priv->ern_cnt.early_window;
+		ern_cnt.late_window  += percpu_priv->ern_cnt.late_window;
+		ern_cnt.fq_tdrop     += percpu_priv->ern_cnt.fq_tdrop;
+		ern_cnt.fq_retired   += percpu_priv->ern_cnt.fq_retired;
+		ern_cnt.orp_zero     += percpu_priv->ern_cnt.orp_zero;
+
+		copy_stats(percpu_priv, num_cpus, i, bp_count, data);
+	}
+
+	offset = (num_cpus + 1) * (DPAA_STATS_PERCPU_LEN + DPAA_BPS_NUM);
+	memcpy(data + offset, &rx_errors, sizeof(struct dpaa_rx_errors));
+
+	offset += sizeof(struct dpaa_rx_errors) / sizeof(u64);
+	memcpy(data + offset, &ern_cnt, sizeof(struct dpaa_ern_cnt));
+
+	/* gather congestion related counters */
+	cg_num    = 0;
+	cg_status = 0;
+	cg_time   = jiffies_to_msecs(priv->cgr_data.congested_jiffies);
+	if (qman_query_cgr_congested(&priv->cgr_data.cgr, &cg_status) == 0) {
+		cg_num    = priv->cgr_data.cgr_congested_count;
+
+		/* reset congestion stats (like QMan API does */
+		priv->cgr_data.congested_jiffies   = 0;
+		priv->cgr_data.cgr_congested_count = 0;
+	}
+
+	offset += sizeof(struct dpaa_ern_cnt) / sizeof(u64);
+	data[offset++] = cg_time;
+	data[offset++] = cg_num;
+	data[offset++] = cg_status;
+}
+
+static void dpaa_get_strings(struct net_device *net_dev, u32 stringset,
+			     u8 *data)
+{
+	unsigned int i, j, num_cpus, size;
+	char string_cpu[ETH_GSTRING_LEN];
+	u8 *strings;
+
+	memset(string_cpu, 0, sizeof(string_cpu));
+	strings   = data;
+	num_cpus  = num_online_cpus();
+	size      = DPAA_STATS_GLOBAL_LEN * ETH_GSTRING_LEN;
+
+	for (i = 0; i < DPAA_STATS_PERCPU_LEN; i++) {
+		for (j = 0; j < num_cpus; j++) {
+			snprintf(string_cpu, ETH_GSTRING_LEN, "%s [CPU %d]",
+				 dpaa_stats_percpu[i], j);
+			memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+			strings += ETH_GSTRING_LEN;
+		}
+		snprintf(string_cpu, ETH_GSTRING_LEN, "%s [TOTAL]",
+			 dpaa_stats_percpu[i]);
+		memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+		strings += ETH_GSTRING_LEN;
+	}
+	for (i = 0; i < DPAA_BPS_NUM; i++) {
+		for (j = 0; j < num_cpus; j++) {
+			snprintf(string_cpu, ETH_GSTRING_LEN,
+				 "bpool %c [CPU %d]", 'a' + i, j);
+			memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+			strings += ETH_GSTRING_LEN;
+		}
+		snprintf(string_cpu, ETH_GSTRING_LEN, "bpool %c [TOTAL]",
+			 'a' + i);
+		memcpy(strings, string_cpu, ETH_GSTRING_LEN);
+		strings += ETH_GSTRING_LEN;
+	}
+	memcpy(strings, dpaa_stats_global, size);
+}
+
+const struct ethtool_ops dpaa_ethtool_ops = {
+	.get_settings = dpaa_get_settings,
+	.set_settings = dpaa_set_settings,
+	.get_drvinfo = dpaa_get_drvinfo,
+	.get_msglevel = dpaa_get_msglevel,
+	.set_msglevel = dpaa_set_msglevel,
+	.nway_reset = dpaa_nway_reset,
+	.get_pauseparam = dpaa_get_pauseparam,
+	.set_pauseparam = dpaa_set_pauseparam,
+	.get_link = ethtool_op_get_link,
+	.get_sset_count = dpaa_get_sset_count,
+	.get_ethtool_stats = dpaa_get_ethtool_stats,
+	.get_strings = dpaa_get_strings,
+};
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/dpaa_eth_trace.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,141 @@
+/* Copyright 2013-2015 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM	dpaa_eth
+
+#if !defined(_DPAA_ETH_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _DPAA_ETH_TRACE_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include "dpaa_eth.h"
+#include <linux/tracepoint.h>
+
+#define fd_format_name(format)	{ qm_fd_##format, #format }
+#define fd_format_list	\
+	fd_format_name(contig),	\
+	fd_format_name(sg)
+
+/* This is used to declare a class of events.
+ * individual events of this type will be defined below.
+ */
+
+/* Store details about a frame descriptor and the FQ on which it was
+ * transmitted/received.
+ */
+DECLARE_EVENT_CLASS(dpaa_eth_fd,
+	/* Trace function prototype */
+	TP_PROTO(struct net_device *netdev,
+		 struct qman_fq *fq,
+		 const struct qm_fd *fd),
+
+	/* Repeat argument list here */
+	TP_ARGS(netdev, fq, fd),
+
+	/* A structure containing the relevant information we want to record.
+	 * Declare name and type for each normal element, name, type and size
+	 * for arrays. Use __string for variable length strings.
+	 */
+	TP_STRUCT__entry(
+		__field(u32,	fqid)
+		__field(u64,	fd_addr)
+		__field(u8,	fd_format)
+		__field(u16,	fd_offset)
+		__field(u32,	fd_length)
+		__field(u32,	fd_status)
+		__string(name,	netdev->name)
+	),
+
+	/* The function that assigns values to the above declared fields */
+	TP_fast_assign(
+		__entry->fqid = fq->fqid;
+		__entry->fd_addr = qm_fd_addr_get64(fd);
+		__entry->fd_format = qm_fd_get_format(fd);
+		__entry->fd_offset = qm_fd_get_offset(fd);
+		__entry->fd_length = qm_fd_get_length(fd);
+		__entry->fd_status = fd->status;
+		__assign_str(name, netdev->name);
+	),
+
+	/* This is what gets printed when the trace event is triggered */
+	TP_printk("[%s] fqid=%d, fd: addr=0x%llx, format=%s, off=%u, len=%u, status=0x%08x",
+		  __get_str(name), __entry->fqid, __entry->fd_addr,
+		  __print_symbolic(__entry->fd_format, fd_format_list),
+		  __entry->fd_offset, __entry->fd_length, __entry->fd_status)
+);
+
+/* Now declare events of the above type. Format is:
+ * DEFINE_EVENT(class, name, proto, args), with proto and args same as for class
+ */
+
+/* Tx (egress) fd */
+DEFINE_EVENT(dpaa_eth_fd, dpaa_tx_fd,
+
+	TP_PROTO(struct net_device *netdev,
+		 struct qman_fq *fq,
+		 const struct qm_fd *fd),
+
+	TP_ARGS(netdev, fq, fd)
+);
+
+/* Rx fd */
+DEFINE_EVENT(dpaa_eth_fd, dpaa_rx_fd,
+
+	TP_PROTO(struct net_device *netdev,
+		 struct qman_fq *fq,
+		 const struct qm_fd *fd),
+
+	TP_ARGS(netdev, fq, fd)
+);
+
+/* Tx confirmation fd */
+DEFINE_EVENT(dpaa_eth_fd, dpaa_tx_conf_fd,
+
+	TP_PROTO(struct net_device *netdev,
+		 struct qman_fq *fq,
+		 const struct qm_fd *fd),
+
+	TP_ARGS(netdev, fq, fd)
+);
+
+/* If only one event of a certain type needs to be declared, use TRACE_EVENT().
+ * The syntax is the same as for DECLARE_EVENT_CLASS().
+ */
+
+#endif /* _DPAA_ETH_TRACE_H */
+
+/* This must be outside ifdef _DPAA_ETH_TRACE_H */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE	dpaa_eth_trace
+#include <trace/define_trace.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,10 @@
+menuconfig FSL_DPAA_ETH
+	tristate "DPAA Ethernet"
+	depends on FSL_DPAA && FSL_FMAN
+	select PHYLIB
+	select FSL_FMAN_MAC
+	---help---
+	  Data Path Acceleration Architecture Ethernet driver,
+	  supporting the Freescale QorIQ chips.
+	  Depends on Freescale Buffer Manager and Queue Manager
+	  driver and Frame Manager Driver.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/dpaa/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/dpaa/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,12 @@
+#
+# Makefile for the Freescale DPAA Ethernet controllers
+#
+
+# Include FMan headers
+FMAN        = $(srctree)/drivers/net/ethernet/freescale/fman
+ccflags-y += -I$(FMAN)
+
+obj-$(CONFIG_FSL_DPAA_ETH) += fsl_dpa.o
+
+fsl_dpa-objs += dpaa_eth.o dpaa_ethtool.o dpaa_eth_sysfs.o
+CFLAGS_dpaa_eth.o := -I$(src)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fec_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fec_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fec_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fec_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -1841,11 +1841,11 @@ static int fec_enet_clk_enable(struct ne
 		ret = clk_prepare_enable(fep->clk_ahb);
 		if (ret)
 			return ret;
-		if (fep->clk_enet_out) {
-			ret = clk_prepare_enable(fep->clk_enet_out);
-			if (ret)
-				goto failed_clk_enet_out;
-		}
+
+		ret = clk_prepare_enable(fep->clk_enet_out);
+		if (ret)
+			goto failed_clk_enet_out;
+
 		if (fep->clk_ptp) {
 			mutex_lock(&fep->ptp_clk_mutex);
 			ret = clk_prepare_enable(fep->clk_ptp);
@@ -1857,23 +1857,20 @@ static int fec_enet_clk_enable(struct ne
 			}
 			mutex_unlock(&fep->ptp_clk_mutex);
 		}
-		if (fep->clk_ref) {
-			ret = clk_prepare_enable(fep->clk_ref);
-			if (ret)
-				goto failed_clk_ref;
-		}
+
+		ret = clk_prepare_enable(fep->clk_ref);
+		if (ret)
+			goto failed_clk_ref;
 	} else {
 		clk_disable_unprepare(fep->clk_ahb);
-		if (fep->clk_enet_out)
-			clk_disable_unprepare(fep->clk_enet_out);
+		clk_disable_unprepare(fep->clk_enet_out);
 		if (fep->clk_ptp) {
 			mutex_lock(&fep->ptp_clk_mutex);
 			clk_disable_unprepare(fep->clk_ptp);
 			fep->ptp_clk_on = false;
 			mutex_unlock(&fep->ptp_clk_mutex);
 		}
-		if (fep->clk_ref)
-			clk_disable_unprepare(fep->clk_ref);
+		clk_disable_unprepare(fep->clk_ref);
 	}
 
 	return 0;
@@ -2365,16 +2362,6 @@ static inline void fec_enet_update_ethto
 }
 #endif /* !defined(CONFIG_M5272) */
 
-static int fec_enet_nway_reset(struct net_device *dev)
-{
-	struct phy_device *phydev = dev->phydev;
-
-	if (!phydev)
-		return -ENODEV;
-
-	return genphy_restart_aneg(phydev);
-}
-
 /* ITR clock source is enet system clock (clk_ahb).
  * TCTT unit is cycle_ns * 64 cycle
  * So, the ICTT value = X us / (cycle_ns * 64)
@@ -2574,7 +2561,7 @@ static const struct ethtool_ops fec_enet
 	.get_drvinfo		= fec_enet_get_drvinfo,
 	.get_regs_len		= fec_enet_get_regs_len,
 	.get_regs		= fec_enet_get_regs,
-	.nway_reset		= fec_enet_nway_reset,
+	.nway_reset		= phy_ethtool_nway_reset,
 	.get_link		= ethtool_op_get_link,
 	.get_coalesce		= fec_enet_get_coalesce,
 	.set_coalesce		= fec_enet_set_coalesce,
@@ -3075,7 +3062,6 @@ static const struct net_device_ops fec_n
 	.ndo_stop		= fec_enet_close,
 	.ndo_start_xmit		= fec_enet_start_xmit,
 	.ndo_set_rx_mode	= set_multicast_list,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= fec_timeout,
 	.ndo_set_mac_address	= fec_set_mac_address,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fec_mpc52xx.c	2017-02-12 16:03:20.000000000 -0500
@@ -802,7 +802,6 @@ static const struct net_device_ops mpc52
 	.ndo_set_mac_address = mpc52xx_fec_set_mac_address,
 	.ndo_validate_addr = eth_validate_addr,
 	.ndo_do_ioctl = mpc52xx_fec_ioctl,
-	.ndo_change_mtu = eth_change_mtu,
 	.ndo_tx_timeout = mpc52xx_fec_tx_timeout,
 	.ndo_get_stats = mpc52xx_fec_get_stats,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fec_ptp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fec_ptp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fec_ptp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fec_ptp.c	2017-02-12 16:03:20.000000000 -0500
@@ -230,7 +230,7 @@ static int fec_ptp_enable_pps(struct fec
  * cyclecounter structure used to construct a ns counter from the
  * arbitrary fixed point registers
  */
-static cycle_t fec_ptp_read(const struct cyclecounter *cc)
+static u64 fec_ptp_read(const struct cyclecounter *cc)
 {
 	struct fec_enet_private *fep =
 		container_of(cc, struct fec_enet_private, cc);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fman/fman.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fman/fman.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fman/fman.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fman/fman.c	2017-02-12 16:03:20.000000000 -0500
@@ -1890,6 +1890,7 @@ static int fman_reset(struct fman *fman)
 
 		goto _return;
 	} else {
+#ifdef CONFIG_PPC
 		struct device_node *guts_node;
 		struct ccsr_guts __iomem *guts_regs;
 		u32 devdisr2, reg;
@@ -1921,6 +1922,7 @@ static int fman_reset(struct fman *fman)
 
 		/* Enable all MACs */
 		iowrite32be(reg, &guts_regs->devdisr2);
+#endif
 
 		/* Perform FMan reset */
 		iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc);
@@ -1932,25 +1934,31 @@ static int fman_reset(struct fman *fman)
 		} while (((ioread32be(&fman->fpm_regs->fm_rstc)) &
 			 FPM_RSTC_FM_RESET) && --count);
 		if (count == 0) {
+#ifdef CONFIG_PPC
 			iounmap(guts_regs);
 			of_node_put(guts_node);
+#endif
 			err = -EBUSY;
 			goto _return;
 		}
+#ifdef CONFIG_PPC
 
 		/* Restore devdisr2 value */
 		iowrite32be(devdisr2, &guts_regs->devdisr2);
 
 		iounmap(guts_regs);
 		of_node_put(guts_node);
+#endif
 
 		goto _return;
 
+#ifdef CONFIG_PPC
 guts_regs:
 		of_node_put(guts_node);
 guts_node:
 		dev_dbg(fman->dev, "%s: Didn't perform FManV3 reset due to Errata A007273!\n",
 			__func__);
+#endif
 	}
 _return:
 	return err;
@@ -2868,6 +2876,13 @@ static struct fman *read_dts_node(struct
 
 	fman->dev = &of_dev->dev;
 
+	err = of_platform_populate(fm_node, NULL, NULL, &of_dev->dev);
+	if (err) {
+		dev_err(&of_dev->dev, "%s: of_platform_populate() failed\n",
+			__func__);
+		goto fman_free;
+	}
+
 	return fman;
 
 fman_node_put:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fman/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fman/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fman/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fman/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -1,6 +1,6 @@
 config FSL_FMAN
 	tristate "FMan support"
-	depends on FSL_SOC || COMPILE_TEST
+	depends on FSL_SOC || ARCH_LAYERSCAPE || COMPILE_TEST
 	select GENERIC_ALLOCATOR
 	select PHYLIB
 	default n
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fman/mac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fman/mac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fman/mac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fman/mac.c	2017-02-12 16:03:20.000000000 -0500
@@ -594,6 +594,7 @@ static const u16 phy2speed[] = {
 	[PHY_INTERFACE_MODE_RGMII_RXID]	= SPEED_1000,
 	[PHY_INTERFACE_MODE_RGMII_TXID]	= SPEED_1000,
 	[PHY_INTERFACE_MODE_RTBI]		= SPEED_1000,
+	[PHY_INTERFACE_MODE_QSGMII]		= SPEED_1000,
 	[PHY_INTERFACE_MODE_XGMII]		= SPEED_10000
 };
 
@@ -879,13 +880,17 @@ static int mac_probe(struct platform_dev
 
 		priv->fixed_link = kzalloc(sizeof(*priv->fixed_link),
 					   GFP_KERNEL);
-		if (!priv->fixed_link)
+		if (!priv->fixed_link) {
+			err = -ENOMEM;
 			goto _return_dev_set_drvdata;
+		}
 
 		priv->phy_node = of_node_get(mac_node);
 		phy = of_phy_find_device(priv->phy_node);
-		if (!phy)
+		if (!phy) {
+			err = -EINVAL;
 			goto _return_dev_set_drvdata;
+		}
 
 		priv->fixed_link->link = phy->link;
 		priv->fixed_link->speed = phy->speed;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet.h	2017-02-12 16:03:20.000000000 -0500
@@ -137,7 +137,6 @@ struct fs_enet_private {
 	cbd_t __iomem *cur_rx;
 	cbd_t __iomem *cur_tx;
 	int tx_free;
-	struct net_device_stats stats;
 	struct timer_list phy_timer_list;
 	const struct phy_info *phy;
 	u32 msg_enable;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c	2017-02-12 16:03:20.000000000 -0500
@@ -44,7 +44,7 @@
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "fs_enet.h"
 
@@ -118,22 +118,22 @@ static int fs_enet_napi(struct napi_stru
 			  BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
 
 			if (sc & BD_ENET_TX_HB)	/* No heartbeat */
-				fep->stats.tx_heartbeat_errors++;
+				dev->stats.tx_heartbeat_errors++;
 			if (sc & BD_ENET_TX_LC)	/* Late collision */
-				fep->stats.tx_window_errors++;
+				dev->stats.tx_window_errors++;
 			if (sc & BD_ENET_TX_RL)	/* Retrans limit */
-				fep->stats.tx_aborted_errors++;
+				dev->stats.tx_aborted_errors++;
 			if (sc & BD_ENET_TX_UN)	/* Underrun */
-				fep->stats.tx_fifo_errors++;
+				dev->stats.tx_fifo_errors++;
 			if (sc & BD_ENET_TX_CSL)	/* Carrier lost */
-				fep->stats.tx_carrier_errors++;
+				dev->stats.tx_carrier_errors++;
 
 			if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
-				fep->stats.tx_errors++;
+				dev->stats.tx_errors++;
 				do_restart = 1;
 			}
 		} else
-			fep->stats.tx_packets++;
+			dev->stats.tx_packets++;
 
 		if (sc & BD_ENET_TX_READY) {
 			dev_warn(fep->dev,
@@ -145,7 +145,7 @@ static int fs_enet_napi(struct napi_stru
 		 * but we eventually sent the packet OK.
 		 */
 		if (sc & BD_ENET_TX_DEF)
-			fep->stats.collisions++;
+			dev->stats.collisions++;
 
 		/* unmap */
 		if (fep->mapped_as_page[dirtyidx])
@@ -212,19 +212,19 @@ static int fs_enet_napi(struct napi_stru
 		 */
 		if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
 			  BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-			fep->stats.rx_errors++;
+			dev->stats.rx_errors++;
 			/* Frame too long or too short. */
 			if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-				fep->stats.rx_length_errors++;
+				dev->stats.rx_length_errors++;
 			/* Frame alignment */
 			if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
-				fep->stats.rx_frame_errors++;
+				dev->stats.rx_frame_errors++;
 			/* CRC Error */
 			if (sc & BD_ENET_RX_CR)
-				fep->stats.rx_crc_errors++;
+				dev->stats.rx_crc_errors++;
 			/* FIFO overrun */
 			if (sc & BD_ENET_RX_OV)
-				fep->stats.rx_crc_errors++;
+				dev->stats.rx_crc_errors++;
 
 			skbn = fep->rx_skbuff[curidx];
 		} else {
@@ -233,9 +233,9 @@ static int fs_enet_napi(struct napi_stru
 			/*
 			 * Process the incoming frame.
 			 */
-			fep->stats.rx_packets++;
+			dev->stats.rx_packets++;
 			pkt_len = CBDR_DATLEN(bdp) - 4;	/* remove CRC */
-			fep->stats.rx_bytes += pkt_len + 4;
+			dev->stats.rx_bytes += pkt_len + 4;
 
 			if (pkt_len <= fpi->rx_copybreak) {
 				/* +2 to make IP header L1 cache aligned */
@@ -277,7 +277,7 @@ static int fs_enet_napi(struct napi_stru
 				received++;
 				netif_receive_skb(skb);
 			} else {
-				fep->stats.rx_dropped++;
+				dev->stats.rx_dropped++;
 				skbn = skb;
 			}
 		}
@@ -543,7 +543,7 @@ static int fs_enet_start_xmit(struct sk_
 	curidx = bdp - fep->tx_bd_base;
 
 	len = skb->len;
-	fep->stats.tx_bytes += len;
+	dev->stats.tx_bytes += len;
 	if (nr_frags)
 		len -= skb->data_len;
 	fep->tx_free -= nr_frags + 1;
@@ -619,7 +619,7 @@ static void fs_timeout(struct net_device
 	unsigned long flags;
 	int wake = 0;
 
-	fep->stats.tx_errors++;
+	dev->stats.tx_errors++;
 
 	spin_lock_irqsave(&fep->lock, flags);
 
@@ -774,12 +774,6 @@ static int fs_enet_close(struct net_devi
 	return 0;
 }
 
-static struct net_device_stats *fs_enet_get_stats(struct net_device *dev)
-{
-	struct fs_enet_private *fep = netdev_priv(dev);
-	return &fep->stats;
-}
-
 /*************************************************************************/
 
 static void fs_get_drvinfo(struct net_device *dev,
@@ -813,11 +807,6 @@ static void fs_get_regs(struct net_devic
 		regs->version = 0;
 }
 
-static int fs_nway_reset(struct net_device *dev)
-{
-	return 0;
-}
-
 static u32 fs_get_msglevel(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
@@ -871,7 +860,7 @@ static int fs_set_tunable(struct net_dev
 static const struct ethtool_ops fs_ethtool_ops = {
 	.get_drvinfo = fs_get_drvinfo,
 	.get_regs_len = fs_get_regs_len,
-	.nway_reset = fs_nway_reset,
+	.nway_reset = phy_ethtool_nway_reset,
 	.get_link = ethtool_op_get_link,
 	.get_msglevel = fs_get_msglevel,
 	.set_msglevel = fs_set_msglevel,
@@ -905,14 +894,12 @@ extern void fs_mii_disconnect(struct net
 static const struct net_device_ops fs_enet_netdev_ops = {
 	.ndo_open		= fs_enet_open,
 	.ndo_stop		= fs_enet_close,
-	.ndo_get_stats		= fs_enet_get_stats,
 	.ndo_start_xmit		= fs_enet_start_xmit,
 	.ndo_tx_timeout		= fs_timeout,
 	.ndo_set_rx_mode	= fs_set_multicast_list,
 	.ndo_do_ioctl		= fs_ioctl,
 	.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	= fs_enet_netpoll,
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fcc.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,7 +42,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include "fs_enet.h"
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mac-fec.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 #include <linux/gfp.h>
 
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mac-scc.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 #include <linux/of_platform.h>
 
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mii-fec.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/fs_enet/mii-fec.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/fs_enet/mii-fec.c	2017-02-12 16:03:20.000000000 -0500
@@ -35,7 +35,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/mpc5xxx.h>
 
 #include "fs_enet.h"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar.c	2017-02-12 16:03:20.000000000 -0500
@@ -93,7 +93,7 @@
 #include <asm/mpc85xx.h>
 #endif
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/crc32.h>
@@ -1339,7 +1339,10 @@ static int gfar_probe(struct platform_de
 
 	/* Fill in the dev structure */
 	dev->watchdog_timeo = TX_TIMEOUT;
+	/* MTU range: 50 - 9586 */
 	dev->mtu = 1500;
+	dev->min_mtu = 50;
+	dev->max_mtu = GFAR_JUMBO_FRAME_SIZE - ETH_HLEN;
 	dev->netdev_ops = &gfar_netdev_ops;
 	dev->ethtool_ops = &gfar_ethtool_ops;
 
@@ -2007,8 +2010,8 @@ static void free_skb_rx_queue(struct gfa
 		if (!rxb->page)
 			continue;
 
-		dma_unmap_single(rx_queue->dev, rxb->dma,
-				 PAGE_SIZE, DMA_FROM_DEVICE);
+		dma_unmap_page(rx_queue->dev, rxb->dma,
+			       PAGE_SIZE, DMA_FROM_DEVICE);
 		__free_page(rxb->page);
 
 		rxb->page = NULL;
@@ -2600,12 +2603,6 @@ static int gfar_set_mac_address(struct n
 static int gfar_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct gfar_private *priv = netdev_priv(dev);
-	int frame_size = new_mtu + ETH_HLEN;
-
-	if ((frame_size < 64) || (frame_size > GFAR_JUMBO_FRAME_SIZE)) {
-		netif_err(priv, drv, dev, "Invalid MTU setting\n");
-		return -EINVAL;
-	}
 
 	while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
 		cpu_relax();
@@ -2951,7 +2948,7 @@ static bool gfar_add_rx_frag(struct gfar
 	}
 
 	/* try reuse page */
-	if (unlikely(page_count(page) != 1))
+	if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page)))
 		return false;
 
 	/* change offset to the other half */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/crc32.h>
 #include <asm/types.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar.h	2017-02-12 16:03:20.000000000 -0500
@@ -40,7 +40,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/crc32.h>
 #include <linux/workqueue.h>
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar_ptp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar_ptp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/gianfar_ptp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/gianfar_ptp.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,7 @@ struct gianfar_ptp_registers {
 /* Bit definitions for the TMR_CTRL register */
 #define ALM1P                 (1<<31) /* Alarm1 output polarity */
 #define ALM2P                 (1<<30) /* Alarm2 output polarity */
-#define FS                    (1<<28) /* FIPER start indication */
+#define FIPERST               (1<<28) /* FIPER start indication */
 #define PP1L                  (1<<27) /* Fiper1 pulse loopback mode enabled. */
 #define PP2L                  (1<<26) /* Fiper2 pulse loopback mode enabled. */
 #define TCLK_PERIOD_SHIFT     (16) /* 1588 timer reference clock period. */
@@ -280,21 +280,26 @@ static irqreturn_t isr(int irq, void *pr
  * PTP clock operations
  */
 
-static int ptp_gianfar_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int ptp_gianfar_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
-	u64 adj;
-	u32 diff, tmr_add;
+	u64 adj, diff;
+	u32 tmr_add;
 	int neg_adj = 0;
 	struct etsects *etsects = container_of(ptp, struct etsects, caps);
 
-	if (ppb < 0) {
+	if (scaled_ppm < 0) {
 		neg_adj = 1;
-		ppb = -ppb;
+		scaled_ppm = -scaled_ppm;
 	}
 	tmr_add = etsects->tmr_add;
 	adj = tmr_add;
-	adj *= ppb;
-	diff = div_u64(adj, 1000000000ULL);
+
+	/* calculate diff as adj*(scaled_ppm/65536)/1000000
+	 * and round() to the nearest integer
+	 */
+	adj *= scaled_ppm;
+	diff = div_u64(adj, 8000000);
+	diff = (diff >> 13) + ((diff >> 12) & 1);
 
 	tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
 
@@ -415,7 +420,7 @@ static struct ptp_clock_info ptp_gianfar
 	.n_per_out	= 0,
 	.n_pins		= 0,
 	.pps		= 1,
-	.adjfreq	= ptp_gianfar_adjfreq,
+	.adjfine	= ptp_gianfar_adjfine,
 	.adjtime	= ptp_gianfar_adjtime,
 	.gettime64	= ptp_gianfar_gettime,
 	.settime64	= ptp_gianfar_settime,
@@ -502,7 +507,7 @@ static int gianfar_ptp_probe(struct plat
 	gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1);
 	gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2);
 	set_alarm(etsects);
-	gfar_write(&etsects->regs->tmr_ctrl,   tmr_ctrl|FS|RTPE|TE|FRD);
+	gfar_write(&etsects->regs->tmr_ctrl,   tmr_ctrl|FIPERST|RTPE|TE|FRD);
 
 	spin_unlock_irqrestore(&etsects->lock, flags);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -8,7 +8,7 @@ config NET_VENDOR_FREESCALE
 	depends on FSL_SOC || QUICC_ENGINE || CPM1 || CPM2 || PPC_MPC512x || \
 		   M523x || M527x || M5272 || M528x || M520x || M532x || \
 		   ARCH_MXC || ARCH_MXS || (PPC_MPC52xx && PPC_BESTCOMM) || \
-		   ARCH_LAYERSCAPE
+		   ARCH_LAYERSCAPE || COMPILE_TEST
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y.
 
@@ -25,7 +25,7 @@ config FEC
 		   ARCH_MXC || SOC_IMX28)
 	default ARCH_MXC || SOC_IMX28 if ARM
 	select PHYLIB
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	---help---
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
 	  controller on some Motorola ColdFire and Freescale i.MX processors.
@@ -65,6 +65,7 @@ config FSL_PQ_MDIO
 config FSL_XGMAC_MDIO
 	tristate "Freescale XGMAC MDIO"
 	select PHYLIB
+	depends on OF
 	select OF_MDIO
 	---help---
 	  This driver supports the MDIO bus on the Fman 10G Ethernet MACs, and
@@ -85,6 +86,7 @@ config UGETH_TX_ON_DEMAND
 
 config GIANFAR
 	tristate "Gianfar Ethernet"
+	depends on HAS_DMA
 	select FSL_PQ_MDIO
 	select PHYLIB
 	select CRC32
@@ -93,4 +95,6 @@ config GIANFAR
 	  and MPC86xx family of chips, the eTSEC on LS1021A and the FEC
 	  on the 8540.
 
+source "drivers/net/ethernet/freescale/dpaa/Kconfig"
+
 endif # NET_VENDOR_FREESCALE
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -4,8 +4,6 @@
 
 obj-$(CONFIG_FEC) += fec.o
 fec-objs :=fec_main.o fec_ptp.o
-CFLAGS_fec_main.o := -D__CHECK_ENDIAN__
-CFLAGS_fec_ptp.o := -D__CHECK_ENDIAN__
 
 obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
@@ -22,3 +20,4 @@ obj-$(CONFIG_UCC_GETH) += ucc_geth_drive
 ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
 
 obj-$(CONFIG_FSL_FMAN) += fman/
+obj-$(CONFIG_FSL_DPAA_ETH) += dpaa/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/ucc_geth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/ucc_geth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/ucc_geth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/ucc_geth.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,7 +37,7 @@
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <soc/fsl/qe/immap_qe.h>
@@ -3681,7 +3681,6 @@ static const struct net_device_ops ucc_g
 	.ndo_start_xmit		= ucc_geth_start_xmit,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= ucc_geth_set_mac_addr,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_rx_mode	= ucc_geth_set_multi,
 	.ndo_tx_timeout		= ucc_geth_timeout,
 	.ndo_do_ioctl		= ucc_geth_ioctl,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/freescale/ucc_geth_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/freescale/ucc_geth_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/freescale/ucc_geth_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -32,7 +32,7 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/types.h>
 
 #include "ucc_geth.h"
@@ -332,13 +332,6 @@ static void uec_get_ethtool_stats(struct
 	}
 }
 
-static int uec_nway_reset(struct net_device *netdev)
-{
-	struct ucc_geth_private *ugeth = netdev_priv(netdev);
-
-	return phy_start_aneg(ugeth->phydev);
-}
-
 /* Report driver information */
 static void
 uec_get_drvinfo(struct net_device *netdev,
@@ -394,7 +387,7 @@ static const struct ethtool_ops uec_etht
 	.get_regs               = uec_get_regs,
 	.get_msglevel           = uec_get_msglevel,
 	.set_msglevel           = uec_set_msglevel,
-	.nway_reset             = uec_nway_reset,
+	.nway_reset             = phy_ethtool_nway_reset,
 	.get_link               = ethtool_op_get_link,
 	.get_ringparam          = uec_get_ringparam,
 	.set_ringparam          = uec_set_ringparam,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/fujitsu/fmvj18x_cs.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,7 +54,7 @@
 #include <pcmcia/ciscode.h>
 #include <pcmcia/ds.h>
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/io.h>
 
 /*====================================================================*/
@@ -225,7 +225,6 @@ static const struct net_device_ops fjn_n
 	.ndo_tx_timeout 	= fjn_tx_timeout,
 	.ndo_set_config 	= fjn_config,
 	.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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hip04_eth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hip04_eth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hip04_eth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hip04_eth.c	2017-02-12 16:03:20.000000000 -0500
@@ -769,7 +769,6 @@ static const struct net_device_ops hip04
 	.ndo_set_mac_address	= hip04_set_mac_address,
 	.ndo_tx_timeout         = hip04_timeout,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= eth_change_mtu,
 };
 
 static int hip04_alloc_ring(struct net_device *ndev, struct device *d)
@@ -829,6 +828,7 @@ static int hip04_mac_probe(struct platfo
 	priv = netdev_priv(ndev);
 	priv->ndev = ndev;
 	platform_set_drvdata(pdev, ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->base = devm_ioremap_resource(d, res);
@@ -898,14 +898,12 @@ static int hip04_mac_probe(struct platfo
 
 	INIT_WORK(&priv->tx_timeout_task, hip04_tx_timeout_task);
 
-	ether_setup(ndev);
 	ndev->netdev_ops = &hip04_netdev_ops;
 	ndev->ethtool_ops = &hip04_ethtool_ops;
 	ndev->watchdog_timeo = TX_TIMEOUT;
 	ndev->priv_flags |= IFF_UNICAST_FLT;
 	ndev->irq = irq;
 	netif_napi_add(ndev, &priv->napi, hip04_rx_poll, NAPI_POLL_WEIGHT);
-	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	hip04_reset_ppe(priv);
 	if (priv->phy_mode == PHY_INTERFACE_MODE_MII)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hisi_femac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hisi_femac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hisi_femac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hisi_femac.c	2017-02-12 16:03:20.000000000 -0500
@@ -712,7 +712,6 @@ static const struct net_device_ops hisi_
 	.ndo_do_ioctl		= hisi_femac_net_ioctl,
 	.ndo_set_mac_address	= hisi_femac_set_mac_address,
 	.ndo_set_rx_mode	= hisi_femac_net_set_rx_mode,
-	.ndo_change_mtu		= eth_change_mtu,
 };
 
 static void hisi_femac_core_reset(struct hisi_femac_priv *priv)
@@ -806,6 +805,7 @@ static int hisi_femac_drv_probe(struct p
 		return -ENOMEM;
 
 	platform_set_drvdata(pdev, ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	priv = netdev_priv(ndev);
 	priv->dev = dev;
@@ -883,7 +883,6 @@ static int hisi_femac_drv_probe(struct p
 	ndev->netdev_ops = &hisi_femac_netdev_ops;
 	ndev->ethtool_ops = &hisi_femac_ethtools_ops;
 	netif_napi_add(ndev, &priv->napi, hisi_femac_poll, FEMAC_POLL_WEIGHT);
-	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	hisi_femac_port_init(priv);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -11,8 +11,10 @@
 #include <linux/interrupt.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
+#include <linux/of_device.h>
 #include <linux/of_net.h>
 #include <linux/of_mdio.h>
+#include <linux/reset.h>
 #include <linux/clk.h>
 #include <linux/circ_buf.h>
 
@@ -183,12 +185,28 @@
 #define DESC_DATA_LEN_OFF		16
 #define DESC_BUFF_LEN_OFF		0
 #define DESC_DATA_MASK			0x7ff
+#define DESC_SG				BIT(30)
+#define DESC_FRAGS_NUM_OFF		11
 
 /* DMA descriptor ring helpers */
 #define dma_ring_incr(n, s)		(((n) + 1) & ((s) - 1))
 #define dma_cnt(n)			((n) >> 5)
 #define dma_byte(n)			((n) << 5)
 
+#define HW_CAP_TSO			BIT(0)
+#define GEMAC_V1			0
+#define GEMAC_V2			(GEMAC_V1 | HW_CAP_TSO)
+#define HAS_CAP_TSO(hw_cap)		((hw_cap) & HW_CAP_TSO)
+
+#define PHY_RESET_DELAYS_PROPERTY	"hisilicon,phy-reset-delays-us"
+
+enum phy_reset_delays {
+	PRE_DELAY,
+	PULSE,
+	POST_DELAY,
+	DELAYS_NUM,
+};
+
 struct hix5hd2_desc {
 	__le32 buff_addr;
 	__le32 cmd;
@@ -201,6 +219,27 @@ struct hix5hd2_desc_sw {
 	unsigned int	size;
 };
 
+struct hix5hd2_sg_desc_ring {
+	struct sg_desc *desc;
+	dma_addr_t phys_addr;
+};
+
+struct frags_info {
+	__le32 addr;
+	__le32 size;
+};
+
+/* hardware supported max skb frags num */
+#define SG_MAX_SKB_FRAGS	17
+struct sg_desc {
+	__le32 total_len;
+	__le32 resvd0;
+	__le32 linear_addr;
+	__le32 linear_len;
+	/* reserve one more frags for memory alignment */
+	struct frags_info frags[SG_MAX_SKB_FRAGS + 1];
+};
+
 #define QUEUE_NUMS	4
 struct hix5hd2_priv {
 	struct hix5hd2_desc_sw pool[QUEUE_NUMS];
@@ -208,6 +247,7 @@ struct hix5hd2_priv {
 #define rx_bq		pool[1]
 #define tx_bq		pool[2]
 #define tx_rq		pool[3]
+	struct hix5hd2_sg_desc_ring tx_ring;
 
 	void __iomem *base;
 	void __iomem *ctrl_base;
@@ -221,15 +261,30 @@ struct hix5hd2_priv {
 	struct device_node *phy_node;
 	phy_interface_t	phy_mode;
 
+	unsigned long hw_cap;
 	unsigned int speed;
 	unsigned int duplex;
 
-	struct clk *clk;
+	struct clk *mac_core_clk;
+	struct clk *mac_ifc_clk;
+	struct reset_control *mac_core_rst;
+	struct reset_control *mac_ifc_rst;
+	struct reset_control *phy_rst;
+	u32 phy_reset_delays[DELAYS_NUM];
 	struct mii_bus *bus;
 	struct napi_struct napi;
 	struct work_struct tx_timeout_task;
 };
 
+static inline void hix5hd2_mac_interface_reset(struct hix5hd2_priv *priv)
+{
+	if (!priv->mac_ifc_rst)
+		return;
+
+	reset_control_assert(priv->mac_ifc_rst);
+	reset_control_deassert(priv->mac_ifc_rst);
+}
+
 static void hix5hd2_config_port(struct net_device *dev, u32 speed, u32 duplex)
 {
 	struct hix5hd2_priv *priv = netdev_priv(dev);
@@ -262,6 +317,7 @@ static void hix5hd2_config_port(struct n
 	if (duplex)
 		val |= GMAC_FULL_DUPLEX;
 	writel_relaxed(val, priv->ctrl_base);
+	hix5hd2_mac_interface_reset(priv);
 
 	writel_relaxed(BIT_MODE_CHANGE_EN, priv->base + MODE_CHANGE_EN);
 	if (speed == SPEED_1000)
@@ -511,6 +567,27 @@ next:
 	return num;
 }
 
+static void hix5hd2_clean_sg_desc(struct hix5hd2_priv *priv,
+				  struct sk_buff *skb, u32 pos)
+{
+	struct sg_desc *desc;
+	dma_addr_t addr;
+	u32 len;
+	int i;
+
+	desc = priv->tx_ring.desc + pos;
+
+	addr = le32_to_cpu(desc->linear_addr);
+	len = le32_to_cpu(desc->linear_len);
+	dma_unmap_single(priv->dev, addr, len, DMA_TO_DEVICE);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		addr = le32_to_cpu(desc->frags[i].addr);
+		len = le32_to_cpu(desc->frags[i].size);
+		dma_unmap_page(priv->dev, addr, len, DMA_TO_DEVICE);
+	}
+}
+
 static void hix5hd2_xmit_reclaim(struct net_device *dev)
 {
 	struct sk_buff *skb;
@@ -538,8 +615,15 @@ static void hix5hd2_xmit_reclaim(struct
 		pkts_compl++;
 		bytes_compl += skb->len;
 		desc = priv->tx_rq.desc + pos;
-		addr = le32_to_cpu(desc->buff_addr);
-		dma_unmap_single(priv->dev, addr, skb->len, DMA_TO_DEVICE);
+
+		if (skb_shinfo(skb)->nr_frags) {
+			hix5hd2_clean_sg_desc(priv, skb, pos);
+		} else {
+			addr = le32_to_cpu(desc->buff_addr);
+			dma_unmap_single(priv->dev, addr, skb->len,
+					 DMA_TO_DEVICE);
+		}
+
 		priv->tx_skb[pos] = NULL;
 		dev_consume_skb_any(skb);
 		pos = dma_ring_incr(pos, TX_DESC_NUM);
@@ -600,12 +684,66 @@ static irqreturn_t hix5hd2_interrupt(int
 	return IRQ_HANDLED;
 }
 
+static u32 hix5hd2_get_desc_cmd(struct sk_buff *skb, unsigned long hw_cap)
+{
+	u32 cmd = 0;
+
+	if (HAS_CAP_TSO(hw_cap)) {
+		if (skb_shinfo(skb)->nr_frags)
+			cmd |= DESC_SG;
+		cmd |= skb_shinfo(skb)->nr_frags << DESC_FRAGS_NUM_OFF;
+	} else {
+		cmd |= DESC_FL_FULL |
+			((skb->len & DESC_DATA_MASK) << DESC_BUFF_LEN_OFF);
+	}
+
+	cmd |= (skb->len & DESC_DATA_MASK) << DESC_DATA_LEN_OFF;
+	cmd |= DESC_VLD_BUSY;
+
+	return cmd;
+}
+
+static int hix5hd2_fill_sg_desc(struct hix5hd2_priv *priv,
+				struct sk_buff *skb, u32 pos)
+{
+	struct sg_desc *desc;
+	dma_addr_t addr;
+	int ret;
+	int i;
+
+	desc = priv->tx_ring.desc + pos;
+
+	desc->total_len = cpu_to_le32(skb->len);
+	addr = dma_map_single(priv->dev, skb->data, skb_headlen(skb),
+			      DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, addr)))
+		return -EINVAL;
+	desc->linear_addr = cpu_to_le32(addr);
+	desc->linear_len = 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];
+		int len = frag->size;
+
+		addr = skb_frag_dma_map(priv->dev, frag, 0, len, DMA_TO_DEVICE);
+		ret = dma_mapping_error(priv->dev, addr);
+		if (unlikely(ret))
+			return -EINVAL;
+		desc->frags[i].addr = cpu_to_le32(addr);
+		desc->frags[i].size = cpu_to_le32(len);
+	}
+
+	return 0;
+}
+
 static int hix5hd2_net_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct hix5hd2_priv *priv = netdev_priv(dev);
 	struct hix5hd2_desc *desc;
 	dma_addr_t addr;
 	u32 pos;
+	u32 cmd;
+	int ret;
 
 	/* software write pointer */
 	pos = dma_cnt(readl_relaxed(priv->base + TX_BQ_WR_ADDR));
@@ -616,18 +754,31 @@ static int hix5hd2_net_xmit(struct sk_bu
 		return NETDEV_TX_BUSY;
 	}
 
-	addr = dma_map_single(priv->dev, skb->data, skb->len, DMA_TO_DEVICE);
-	if (dma_mapping_error(priv->dev, addr)) {
-		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
-	}
-
 	desc = priv->tx_bq.desc + pos;
+
+	cmd = hix5hd2_get_desc_cmd(skb, priv->hw_cap);
+	desc->cmd = cpu_to_le32(cmd);
+
+	if (skb_shinfo(skb)->nr_frags) {
+		ret = hix5hd2_fill_sg_desc(priv, skb, pos);
+		if (unlikely(ret)) {
+			dev_kfree_skb_any(skb);
+			dev->stats.tx_dropped++;
+			return NETDEV_TX_OK;
+		}
+		addr = priv->tx_ring.phys_addr + pos * sizeof(struct sg_desc);
+	} else {
+		addr = dma_map_single(priv->dev, skb->data, skb->len,
+				      DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(priv->dev, addr))) {
+			dev_kfree_skb_any(skb);
+			dev->stats.tx_dropped++;
+			return NETDEV_TX_OK;
+		}
+	}
 	desc->buff_addr = cpu_to_le32(addr);
+
 	priv->tx_skb[pos] = skb;
-	desc->cmd = cpu_to_le32(DESC_VLD_BUSY | DESC_FL_FULL |
-				(skb->len & DESC_DATA_MASK) << DESC_DATA_LEN_OFF |
-				(skb->len & DESC_DATA_MASK) << DESC_BUFF_LEN_OFF);
 
 	/* ensure desc updated */
 	wmb();
@@ -681,16 +832,26 @@ static int hix5hd2_net_open(struct net_d
 	struct phy_device *phy;
 	int ret;
 
-	ret = clk_prepare_enable(priv->clk);
+	ret = clk_prepare_enable(priv->mac_core_clk);
 	if (ret < 0) {
-		netdev_err(dev, "failed to enable clk %d\n", ret);
+		netdev_err(dev, "failed to enable mac core clk %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(priv->mac_ifc_clk);
+	if (ret < 0) {
+		clk_disable_unprepare(priv->mac_core_clk);
+		netdev_err(dev, "failed to enable mac ifc clk %d\n", ret);
 		return ret;
 	}
 
 	phy = of_phy_connect(dev, priv->phy_node,
 			     &hix5hd2_adjust_link, 0, priv->phy_mode);
-	if (!phy)
+	if (!phy) {
+		clk_disable_unprepare(priv->mac_ifc_clk);
+		clk_disable_unprepare(priv->mac_core_clk);
 		return -ENODEV;
+	}
 
 	phy_start(phy);
 	hix5hd2_hw_init(priv);
@@ -721,7 +882,8 @@ static int hix5hd2_net_close(struct net_
 		phy_disconnect(dev->phydev);
 	}
 
-	clk_disable_unprepare(priv->clk);
+	clk_disable_unprepare(priv->mac_ifc_clk);
+	clk_disable_unprepare(priv->mac_core_clk);
 
 	return 0;
 }
@@ -862,10 +1024,82 @@ error_free_pool:
 	return -ENOMEM;
 }
 
+static int hix5hd2_init_sg_desc_queue(struct hix5hd2_priv *priv)
+{
+	struct sg_desc *desc;
+	dma_addr_t phys_addr;
+
+	desc = (struct sg_desc *)dma_alloc_coherent(priv->dev,
+				TX_DESC_NUM * sizeof(struct sg_desc),
+				&phys_addr, GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	priv->tx_ring.desc = desc;
+	priv->tx_ring.phys_addr = phys_addr;
+
+	return 0;
+}
+
+static void hix5hd2_destroy_sg_desc_queue(struct hix5hd2_priv *priv)
+{
+	if (priv->tx_ring.desc) {
+		dma_free_coherent(priv->dev,
+				  TX_DESC_NUM * sizeof(struct sg_desc),
+				  priv->tx_ring.desc, priv->tx_ring.phys_addr);
+		priv->tx_ring.desc = NULL;
+	}
+}
+
+static inline void hix5hd2_mac_core_reset(struct hix5hd2_priv *priv)
+{
+	if (!priv->mac_core_rst)
+		return;
+
+	reset_control_assert(priv->mac_core_rst);
+	reset_control_deassert(priv->mac_core_rst);
+}
+
+static void hix5hd2_sleep_us(u32 time_us)
+{
+	u32 time_ms;
+
+	if (!time_us)
+		return;
+
+	time_ms = DIV_ROUND_UP(time_us, 1000);
+	if (time_ms < 20)
+		usleep_range(time_us, time_us + 500);
+	else
+		msleep(time_ms);
+}
+
+static void hix5hd2_phy_reset(struct hix5hd2_priv *priv)
+{
+	/* To make sure PHY hardware reset success,
+	 * we must keep PHY in deassert state first and
+	 * then complete the hardware reset operation
+	 */
+	reset_control_deassert(priv->phy_rst);
+	hix5hd2_sleep_us(priv->phy_reset_delays[PRE_DELAY]);
+
+	reset_control_assert(priv->phy_rst);
+	/* delay some time to ensure reset ok,
+	 * this depends on PHY hardware feature
+	 */
+	hix5hd2_sleep_us(priv->phy_reset_delays[PULSE]);
+	reset_control_deassert(priv->phy_rst);
+	/* delay some time to ensure later MDIO access */
+	hix5hd2_sleep_us(priv->phy_reset_delays[POST_DELAY]);
+}
+
+static const struct of_device_id hix5hd2_of_match[];
+
 static int hix5hd2_dev_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
+	const struct of_device_id *of_id = NULL;
 	struct net_device *ndev;
 	struct hix5hd2_priv *priv;
 	struct resource *res;
@@ -883,6 +1117,13 @@ static int hix5hd2_dev_probe(struct plat
 	priv->dev = dev;
 	priv->netdev = ndev;
 
+	of_id = of_match_device(hix5hd2_of_match, dev);
+	if (!of_id) {
+		ret = -EINVAL;
+		goto out_free_netdev;
+	}
+	priv->hw_cap = (unsigned long)of_id->data;
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(priv->base)) {
@@ -897,23 +1138,55 @@ static int hix5hd2_dev_probe(struct plat
 		goto out_free_netdev;
 	}
 
-	priv->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(priv->clk)) {
-		netdev_err(ndev, "failed to get clk\n");
+	priv->mac_core_clk = devm_clk_get(&pdev->dev, "mac_core");
+	if (IS_ERR(priv->mac_core_clk)) {
+		netdev_err(ndev, "failed to get mac core clk\n");
 		ret = -ENODEV;
 		goto out_free_netdev;
 	}
 
-	ret = clk_prepare_enable(priv->clk);
+	ret = clk_prepare_enable(priv->mac_core_clk);
 	if (ret < 0) {
-		netdev_err(ndev, "failed to enable clk %d\n", ret);
+		netdev_err(ndev, "failed to enable mac core clk %d\n", ret);
 		goto out_free_netdev;
 	}
 
+	priv->mac_ifc_clk = devm_clk_get(&pdev->dev, "mac_ifc");
+	if (IS_ERR(priv->mac_ifc_clk))
+		priv->mac_ifc_clk = NULL;
+
+	ret = clk_prepare_enable(priv->mac_ifc_clk);
+	if (ret < 0) {
+		netdev_err(ndev, "failed to enable mac ifc clk %d\n", ret);
+		goto out_disable_mac_core_clk;
+	}
+
+	priv->mac_core_rst = devm_reset_control_get(dev, "mac_core");
+	if (IS_ERR(priv->mac_core_rst))
+		priv->mac_core_rst = NULL;
+	hix5hd2_mac_core_reset(priv);
+
+	priv->mac_ifc_rst = devm_reset_control_get(dev, "mac_ifc");
+	if (IS_ERR(priv->mac_ifc_rst))
+		priv->mac_ifc_rst = NULL;
+
+	priv->phy_rst = devm_reset_control_get(dev, "phy");
+	if (IS_ERR(priv->phy_rst)) {
+		priv->phy_rst = NULL;
+	} else {
+		ret = of_property_read_u32_array(node,
+						 PHY_RESET_DELAYS_PROPERTY,
+						 priv->phy_reset_delays,
+						 DELAYS_NUM);
+		if (ret)
+			goto out_disable_clk;
+		hix5hd2_phy_reset(priv);
+	}
+
 	bus = mdiobus_alloc();
 	if (bus == NULL) {
 		ret = -ENOMEM;
-		goto out_free_netdev;
+		goto out_disable_clk;
 	}
 
 	bus->priv = priv;
@@ -972,22 +1245,38 @@ static int hix5hd2_dev_probe(struct plat
 	ndev->ethtool_ops = &hix5hd2_ethtools_ops;
 	SET_NETDEV_DEV(ndev, dev);
 
+	if (HAS_CAP_TSO(priv->hw_cap))
+		ndev->hw_features |= NETIF_F_SG;
+
+	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
+	ndev->vlan_features |= ndev->features;
+
 	ret = hix5hd2_init_hw_desc_queue(priv);
 	if (ret)
 		goto out_phy_node;
 
 	netif_napi_add(ndev, &priv->napi, hix5hd2_poll, NAPI_POLL_WEIGHT);
+
+	if (HAS_CAP_TSO(priv->hw_cap)) {
+		ret = hix5hd2_init_sg_desc_queue(priv);
+		if (ret)
+			goto out_destroy_queue;
+	}
+
 	ret = register_netdev(priv->netdev);
 	if (ret) {
 		netdev_err(ndev, "register_netdev failed!");
 		goto out_destroy_queue;
 	}
 
-	clk_disable_unprepare(priv->clk);
+	clk_disable_unprepare(priv->mac_ifc_clk);
+	clk_disable_unprepare(priv->mac_core_clk);
 
 	return ret;
 
 out_destroy_queue:
+	if (HAS_CAP_TSO(priv->hw_cap))
+		hix5hd2_destroy_sg_desc_queue(priv);
 	netif_napi_del(&priv->napi);
 	hix5hd2_destroy_hw_desc_queue(priv);
 out_phy_node:
@@ -996,6 +1285,10 @@ err_mdiobus:
 	mdiobus_unregister(bus);
 err_free_mdio:
 	mdiobus_free(bus);
+out_disable_clk:
+	clk_disable_unprepare(priv->mac_ifc_clk);
+out_disable_mac_core_clk:
+	clk_disable_unprepare(priv->mac_core_clk);
 out_free_netdev:
 	free_netdev(ndev);
 
@@ -1012,6 +1305,8 @@ static int hix5hd2_dev_remove(struct pla
 	mdiobus_unregister(priv->bus);
 	mdiobus_free(priv->bus);
 
+	if (HAS_CAP_TSO(priv->hw_cap))
+		hix5hd2_destroy_sg_desc_queue(priv);
 	hix5hd2_destroy_hw_desc_queue(priv);
 	of_node_put(priv->phy_node);
 	cancel_work_sync(&priv->tx_timeout_task);
@@ -1021,7 +1316,11 @@ static int hix5hd2_dev_remove(struct pla
 }
 
 static const struct of_device_id hix5hd2_of_match[] = {
-	{.compatible = "hisilicon,hix5hd2-gmac",},
+	{ .compatible = "hisilicon,hisi-gmac-v1", .data = (void *)GEMAC_V1 },
+	{ .compatible = "hisilicon,hisi-gmac-v2", .data = (void *)GEMAC_V2 },
+	{ .compatible = "hisilicon,hix5hd2-gmac", .data = (void *)GEMAC_V1 },
+	{ .compatible = "hisilicon,hi3798cv200-gmac", .data = (void *)GEMAC_V2 },
+	{ .compatible = "hisilicon,hi3516a-gmac", .data = (void *)GEMAC_V2 },
 	{},
 };
 
@@ -1029,7 +1328,7 @@ MODULE_DEVICE_TABLE(of, hix5hd2_of_match
 
 static struct platform_driver hix5hd2_dev_driver = {
 	.driver = {
-		.name = "hix5hd2-gmac",
+		.name = "hisi-gmac",
 		.of_match_table = hix5hd2_of_match,
 	},
 	.probe = hix5hd2_dev_probe,
@@ -1038,6 +1337,6 @@ static struct platform_driver hix5hd2_de
 
 module_platform_driver(hix5hd2_dev_driver);
 
-MODULE_DESCRIPTION("HISILICON HIX5HD2 Ethernet driver");
+MODULE_DESCRIPTION("HISILICON Gigabit Ethernet MAC driver");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:hix5hd2-gmac");
+MODULE_ALIAS("platform:hisi-gmac");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hnae.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hnae.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hnae.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hnae.h	2017-02-12 16:03:20.000000000 -0500
@@ -99,6 +99,8 @@ enum hnae_led_state {
 #define HNS_RX_FLAG_L3ID_IPV6 0x1
 #define HNS_RX_FLAG_L4ID_UDP 0x0
 #define HNS_RX_FLAG_L4ID_TCP 0x1
+#define HNS_RX_FLAG_L4ID_SCTP 0x3
+
 
 #define HNS_TXD_ASID_S 0
 #define HNS_TXD_ASID_M (0xff << HNS_TXD_ASID_S)
@@ -426,8 +428,14 @@ enum hnae_media_type {
  *   get mac address
  * set_mac_addr()
  *   set mac address
+ * clr_mc_addr()
+ *   clear mcast tcam table
  * set_mc_addr()
  *   set multicast mode
+ * add_uc_addr()
+ *   add ucast address
+ * rm_uc_addr()
+ *   remove ucast address
  * set_mtu()
  *   set mtu
  * update_stats()
@@ -488,6 +496,11 @@ struct hnae_ae_ops {
 	void (*set_promisc_mode)(struct hnae_handle *handle, u32 en);
 	int (*get_mac_addr)(struct hnae_handle *handle, void **p);
 	int (*set_mac_addr)(struct hnae_handle *handle, void *p);
+	int (*add_uc_addr)(struct hnae_handle *handle,
+			   const unsigned char *addr);
+	int (*rm_uc_addr)(struct hnae_handle *handle,
+			  const unsigned char *addr);
+	int (*clr_mc_addr)(struct hnae_handle *handle);
 	int (*set_mc_addr)(struct hnae_handle *handle, void *addr);
 	int (*set_mtu)(struct hnae_handle *handle, int new_mtu);
 	void (*set_tso_stats)(struct hnae_handle *handle, int enable);
@@ -590,7 +603,7 @@ static inline int hnae_alloc_buffer_atta
 	if (ret)
 		return ret;
 
-	ring->desc[i].addr = (__le64)ring->desc_cb[i].dma;
+	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma);
 
 	return 0;
 }
@@ -621,14 +634,14 @@ static inline void hnae_replace_buffer(s
 
 	bops->unmap_buffer(ring, &ring->desc_cb[i]);
 	ring->desc_cb[i] = *res_cb;
-	ring->desc[i].addr = (__le64)ring->desc_cb[i].dma;
+	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma);
 	ring->desc[i].rx.ipoff_bnum_pid_flag = 0;
 }
 
 static inline void hnae_reuse_buffer(struct hnae_ring *ring, int i)
 {
 	ring->desc_cb[i].reuse_flag = 0;
-	ring->desc[i].addr = (__le64)(ring->desc_cb[i].dma
+	ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma
 		+ ring->desc_cb[i].page_offset);
 	ring->desc[i].rx.ipoff_bnum_pid_flag = 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c	2017-02-12 16:03:20.000000000 -0500
@@ -18,9 +18,6 @@
 #include "hns_dsaf_rcb.h"
 
 #define AE_NAME_PORT_ID_IDX 6
-#define ETH_STATIC_REG	 1
-#define ETH_DUMP_REG	 5
-#define ETH_GSTRING_LEN	32
 
 static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle)
 {
@@ -202,6 +199,28 @@ static int hns_ae_set_mac_address(struct
 	return 0;
 }
 
+static int hns_ae_add_uc_address(struct hnae_handle *handle,
+				 const unsigned char *addr)
+{
+	struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+	if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+		return -ENOSPC;
+
+	return hns_mac_add_uc_addr(mac_cb, handle->vf_id, addr);
+}
+
+static int hns_ae_rm_uc_address(struct hnae_handle *handle,
+				const unsigned char *addr)
+{
+	struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+	if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+		return -ENOSPC;
+
+	return hns_mac_rm_uc_addr(mac_cb, handle->vf_id, addr);
+}
+
 static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr)
 {
 	int ret;
@@ -235,6 +254,16 @@ static int hns_ae_set_multicast_one(stru
 	return ret;
 }
 
+static int hns_ae_clr_multicast(struct hnae_handle *handle)
+{
+	struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
+
+	if (mac_cb->mac_type != HNAE_PORT_SERVICE)
+		return 0;
+
+	return hns_mac_clr_multicast(mac_cb, handle->vf_id);
+}
+
 static int hns_ae_set_mtu(struct hnae_handle *handle, int new_mtu)
 {
 	struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle);
@@ -823,7 +852,10 @@ static struct hnae_ae_ops hns_dsaf_ops =
 	.get_coalesce_range = hns_ae_get_coalesce_range,
 	.set_promisc_mode = hns_ae_set_promisc_mode,
 	.set_mac_addr = hns_ae_set_mac_address,
+	.add_uc_addr = hns_ae_add_uc_address,
+	.rm_uc_addr = hns_ae_rm_uc_address,
 	.set_mc_addr = hns_ae_set_multicast_one,
+	.clr_mc_addr = hns_ae_clr_multicast,
 	.set_mtu = hns_ae_set_mtu,
 	.update_stats = hns_ae_update_stats,
 	.set_tso_stats = hns_ae_set_tso_stats,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,8 +37,8 @@ static const struct mac_stats_string g_g
 	{"gmac_rx_very_long_err", MAC_STATS_FIELD_OFF(rx_long_err)},
 	{"gmac_rx_runt_err", MAC_STATS_FIELD_OFF(rx_minto64)},
 	{"gmac_rx_short_err", MAC_STATS_FIELD_OFF(rx_under_min)},
-	{"gmac_rx_filt_pkt", MAC_STATS_FIELD_OFF(rx_filter_bytes)},
-	{"gmac_rx_octets_total_filt", MAC_STATS_FIELD_OFF(rx_filter_pkts)},
+	{"gmac_rx_filt_pkt", MAC_STATS_FIELD_OFF(rx_filter_pkts)},
+	{"gmac_rx_octets_total_filt", MAC_STATS_FIELD_OFF(rx_filter_bytes)},
 	{"gmac_rx_overrun_cnt", MAC_STATS_FIELD_OFF(rx_fifo_overrun_err)},
 	{"gmac_rx_length_err", MAC_STATS_FIELD_OFF(rx_len_err)},
 	{"gmac_rx_fail_comma", MAC_STATS_FIELD_OFF(rx_comma_err)},
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c	2017-02-12 16:03:20.000000000 -0500
@@ -263,6 +263,46 @@ int hns_mac_change_vf_addr(struct hns_ma
 	return 0;
 }
 
+int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+			const unsigned char *addr)
+{
+	struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+	struct dsaf_drv_mac_single_dest_entry mac_entry;
+	int ret;
+
+	if (HNS_DSAF_IS_DEBUG(dsaf_dev))
+		return -ENOSPC;
+
+	memset(&mac_entry, 0, sizeof(mac_entry));
+	memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+	mac_entry.in_port_num = mac_cb->mac_id;
+	ret = hns_mac_get_inner_port_num(mac_cb, vf_id, &mac_entry.port_num);
+	if (ret)
+		return ret;
+
+	return hns_dsaf_set_mac_uc_entry(dsaf_dev, &mac_entry);
+}
+
+int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+		       const unsigned char *addr)
+{
+	struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+	struct dsaf_drv_mac_single_dest_entry mac_entry;
+	int ret;
+
+	if (HNS_DSAF_IS_DEBUG(dsaf_dev))
+		return -ENOSPC;
+
+	memset(&mac_entry, 0, sizeof(mac_entry));
+	memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr));
+	mac_entry.in_port_num = mac_cb->mac_id;
+	ret = hns_mac_get_inner_port_num(mac_cb, vf_id, &mac_entry.port_num);
+	if (ret)
+		return ret;
+
+	return hns_dsaf_rm_mac_addr(dsaf_dev, &mac_entry);
+}
+
 int hns_mac_set_multi(struct hns_mac_cb *mac_cb,
 		      u32 port_num, char *addr, bool enable)
 {
@@ -330,13 +370,24 @@ int hns_mac_del_mac(struct hns_mac_cb *m
 	return 0;
 }
 
+int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn)
+{
+	struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
+	u8 port_num;
+	int ret = hns_mac_get_inner_port_num(mac_cb, vfn, &port_num);
+
+	if (ret)
+		return ret;
+
+	return hns_dsaf_clr_mac_mc_port(dsaf_dev, mac_cb->mac_id, port_num);
+}
+
 static void hns_mac_param_get(struct mac_params *param,
 			      struct hns_mac_cb *mac_cb)
 {
 	param->vaddr = (void *)mac_cb->vaddr;
 	param->mac_mode = hns_get_enet_interface(mac_cb);
-	memcpy(param->addr, mac_cb->addr_entry_idx[0].addr,
-	       MAC_NUM_OCTETS_PER_ADDR);
+	ether_addr_copy(param->addr, mac_cb->addr_entry_idx[0].addr);
 	param->mac_id = mac_cb->mac_id;
 	param->dev = mac_cb->dev;
 }
@@ -353,8 +404,7 @@ static int hns_mac_port_config_bc_en(str
 {
 	int ret;
 	struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
-	u8 addr[MAC_NUM_OCTETS_PER_ADDR]
-		= {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	struct dsaf_drv_mac_single_dest_entry mac_entry;
 
 	/* directy return ok in debug network mode */
@@ -389,8 +439,7 @@ int hns_mac_vm_config_bc_en(struct hns_m
 	int ret;
 	struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev;
 	u8 port_num;
-	u8 addr[MAC_NUM_OCTETS_PER_ADDR]
-		= {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	struct mac_entry_idx *uc_mac_entry;
 	struct dsaf_drv_mac_single_dest_entry mac_entry;
 
@@ -453,8 +502,7 @@ int hns_mac_set_mtu(struct hns_mac_cb *m
 	if (mac_cb->mac_type == HNAE_PORT_DEBUG)
 		max_frm = MAC_MAX_MTU_DBG;
 
-	if ((new_mtu < MAC_MIN_MTU) || (new_frm > max_frm) ||
-	    (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size))
+	if (new_frm > HNS_RCB_RING_MAX_BD_PER_PKT * buf_size)
 		return -EINVAL;
 
 	if (!drv->config_max_frame_length)
@@ -869,6 +917,13 @@ static int  hns_mac_get_info(struct hns_
 		}
 	}
 
+	if (fwnode_property_read_u8_array(mac_cb->fw_port, "mc-mac-mask",
+					  mac_cb->mc_mask, ETH_ALEN)) {
+		dev_warn(mac_cb->dev,
+			 "no mc-mac-mask property, set to default value.\n");
+		eth_broadcast_addr(mac_cb->mc_mask);
+	}
+
 	return 0;
 }
 
@@ -1082,6 +1137,8 @@ void hns_mac_set_promisc(struct hns_mac_
 {
 	struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb);
 
+	hns_dsaf_set_promisc_tcam(mac_cb->dsaf_dev, mac_cb->mac_id, !!en);
+
 	if (mac_ctrl_drv->set_promiscuous)
 		mac_ctrl_drv->set_promiscuous(mac_ctrl_drv, en);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h	2017-02-12 16:03:20.000000000 -0500
@@ -31,7 +31,7 @@ struct dsaf_device;
 #define MAC_MIN_MTU		68
 #define MAC_MAX_MTU_DBG		MAC_DEFAULT_MTU
 
-#define MAC_DEFAULT_PAUSE_TIME 0xff
+#define MAC_DEFAULT_PAUSE_TIME 0xffff
 
 #define MAC_GMAC_IDX 0
 #define MAC_XGMAC_IDX 1
@@ -56,9 +56,6 @@ struct dsaf_device;
 /*check mac addr multicast*/
 #define MAC_IS_MULTICAST(p)	((*((u8 *)((p) + 0)) & 0x01) ? (1) : (0))
 
-/**< Number of octets (8-bit bytes) in an ethernet address */
-#define MAC_NUM_OCTETS_PER_ADDR 6
-
 struct mac_priv {
 	void *mac;
 };
@@ -189,7 +186,7 @@ struct mac_statistics {
 
 /*mac para struct ,mac get param from nic or dsaf when initialize*/
 struct mac_params {
-	char addr[MAC_NUM_OCTETS_PER_ADDR];
+	char addr[ETH_ALEN];
 	void *vaddr; /*virtual address*/
 	struct device *dev;
 	u8 mac_id;
@@ -214,7 +211,7 @@ struct mac_info {
 };
 
 struct mac_entry_idx {
-	u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+	u8 addr[ETH_ALEN];
 	u16 vlan_id:12;
 	u16 valid:1;
 	u16 qos:3;
@@ -317,6 +314,7 @@ struct hns_mac_cb {
 	u8 __iomem *serdes_vaddr;
 	struct regmap *serdes_ctrl;
 	struct regmap *cpld_ctrl;
+	char mc_mask[ETH_ALEN];
 	u32 cpld_ctrl_reg;
 	u32 port_rst_off;
 	u32 port_mode_off;
@@ -409,7 +407,7 @@ struct mac_driver {
 };
 
 struct mac_stats_string {
-	char desc[64];
+	char desc[ETH_GSTRING_LEN];
 	unsigned long offset;
 };
 
@@ -463,5 +461,10 @@ int hns_cpld_led_set_id(struct hns_mac_c
 void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en);
 int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb,
 			       u8 vmid, u8 *port_num);
+int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+			const unsigned char *addr);
+int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id,
+		       const unsigned char *addr);
+int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn);
 
 #endif /* _HNS_DSAF_MAC_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -591,6 +591,16 @@ static void hns_dsaf_voq_bp_all_thrd_cfg
 	}
 }
 
+static void hns_dsaf_tbl_tcam_match_cfg(
+	struct dsaf_device *dsaf_dev,
+	struct dsaf_tbl_tcam_data *ptbl_tcam_data)
+{
+	dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MATCH_CFG_L_REG,
+		       ptbl_tcam_data->tbl_tcam_data_low);
+	dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MATCH_CFG_H_REG,
+		       ptbl_tcam_data->tbl_tcam_data_high);
+}
+
 /**
  * hns_dsaf_tbl_tcam_data_cfg - tbl
  * @dsaf_id: dsa fabric id
@@ -755,7 +765,7 @@ static void hns_dsaf_tbl_tcam_data_ucast
 
 void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en)
 {
-	if (!HNS_DSAF_IS_DEBUG(dsaf_dev))
+	if (AE_IS_VER1(dsaf_dev->dsaf_ver) && !HNS_DSAF_IS_DEBUG(dsaf_dev))
 		dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG,
 				 DSAF_CFG_MIX_MODE_S, !!en);
 }
@@ -894,15 +904,16 @@ static void hns_dsaf_tcam_uc_cfg(
 }
 
 /**
- * hns_dsaf_tcam_mc_cfg - INT
- * @dsaf_id: dsa fabric id
- * @address,
- * @ptbl_tcam_data,
- * @ptbl_tcam_mcast,
+ * hns_dsaf_tcam_mc_cfg - cfg the tcam for mc
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @address: tcam index
+ * @ptbl_tcam_data: tcam data struct pointer
+ * @ptbl_tcam_mcast: tcam mask struct pointer, it must be null for HNSv1
  */
 static void hns_dsaf_tcam_mc_cfg(
 	struct dsaf_device *dsaf_dev, u32 address,
 	struct dsaf_tbl_tcam_data *ptbl_tcam_data,
+	struct dsaf_tbl_tcam_data *ptbl_tcam_mask,
 	struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast)
 {
 	spin_lock_bh(&dsaf_dev->tcam_lock);
@@ -913,7 +924,11 @@ static void hns_dsaf_tcam_mc_cfg(
 	hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, ptbl_tcam_data);
 	/*Write Tcam Mcast*/
 	hns_dsaf_tbl_tcam_mcast_cfg(dsaf_dev, ptbl_tcam_mcast);
-	/*Write Plus*/
+	/* Write Match Data */
+	if (ptbl_tcam_mask)
+		hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, ptbl_tcam_mask);
+
+	/* Write Puls */
 	hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev);
 
 	spin_unlock_bh(&dsaf_dev->tcam_lock);
@@ -944,6 +959,16 @@ static void hns_dsaf_tcam_mc_invld(struc
 	spin_unlock_bh(&dsaf_dev->tcam_lock);
 }
 
+void hns_dsaf_tcam_addr_get(struct dsaf_drv_tbl_tcam_key *mac_key, u8 *addr)
+{
+	addr[0] = mac_key->high.bits.mac_0;
+	addr[1] = mac_key->high.bits.mac_1;
+	addr[2] = mac_key->high.bits.mac_2;
+	addr[3] = mac_key->high.bits.mac_3;
+	addr[4] = mac_key->low.bits.mac_4;
+	addr[5] = mac_key->low.bits.mac_5;
+}
+
 /**
  * hns_dsaf_tcam_uc_get - INT
  * @dsaf_id: dsa fabric id
@@ -1369,6 +1394,12 @@ static int hns_dsaf_init(struct dsaf_dev
 	if (HNS_DSAF_IS_DEBUG(dsaf_dev))
 		return 0;
 
+	if (AE_IS_VER1(dsaf_dev->dsaf_ver))
+		dsaf_dev->tcam_max_num = DSAF_TCAM_SUM;
+	else
+		dsaf_dev->tcam_max_num =
+			DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM;
+
 	spin_lock_init(&dsaf_dev->tcam_lock);
 	ret = hns_dsaf_init_hw(dsaf_dev);
 	if (ret)
@@ -1424,7 +1455,7 @@ static u16 hns_dsaf_find_soft_mac_entry(
 	u32 i;
 
 	soft_mac_entry = priv->soft_mac_tbl;
-	for (i = 0; i < DSAF_TCAM_SUM; i++) {
+	for (i = 0; i < dsaf_dev->tcam_max_num; i++) {
 		/* invall tab entry */
 		if ((soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX) &&
 		    (soft_mac_entry->tcam_key.high.val == mac_key->high.val) &&
@@ -1449,7 +1480,7 @@ static u16 hns_dsaf_find_empty_mac_entry
 	u32 i;
 
 	soft_mac_entry = priv->soft_mac_tbl;
-	for (i = 0; i < DSAF_TCAM_SUM; i++) {
+	for (i = 0; i < dsaf_dev->tcam_max_num; i++) {
 		/* inv all entry */
 		if (soft_mac_entry->index == DSAF_INVALID_ENTRY_IDX)
 			/* return find result --soft index */
@@ -1488,8 +1519,12 @@ static void hns_dsaf_set_mac_key(
 	mac_key->high.bits.mac_3 = addr[3];
 	mac_key->low.bits.mac_4 = addr[4];
 	mac_key->low.bits.mac_5 = addr[5];
-	mac_key->low.bits.vlan = vlan_id;
-	mac_key->low.bits.port = port;
+	dsaf_set_field(mac_key->low.bits.port_vlan, DSAF_TBL_TCAM_KEY_VLAN_M,
+		       DSAF_TBL_TCAM_KEY_VLAN_S, vlan_id);
+	dsaf_set_field(mac_key->low.bits.port_vlan, DSAF_TBL_TCAM_KEY_PORT_M,
+		       DSAF_TBL_TCAM_KEY_PORT_S, port);
+
+	mac_key->low.bits.port_vlan = le16_to_cpu(mac_key->low.bits.port_vlan);
 }
 
 /**
@@ -1507,6 +1542,7 @@ int hns_dsaf_set_mac_uc_entry(
 	struct dsaf_drv_priv *priv =
 	    (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
 	struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+	struct dsaf_tbl_tcam_data tcam_data;
 
 	/* mac addr check */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
@@ -1548,9 +1584,10 @@ int hns_dsaf_set_mac_uc_entry(
 	/* default config dvc to 0 */
 	mac_data.tbl_ucast_dvc = 0;
 	mac_data.tbl_ucast_out_port = mac_entry->port_num;
-	hns_dsaf_tcam_uc_cfg(
-		dsaf_dev, entry_index,
-		(struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+	tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+	tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+	hns_dsaf_tcam_uc_cfg(dsaf_dev, entry_index, &tcam_data, &mac_data);
 
 	/* config software entry */
 	soft_mac_entry += entry_index;
@@ -1561,6 +1598,55 @@ int hns_dsaf_set_mac_uc_entry(
 	return 0;
 }
 
+int hns_dsaf_rm_mac_addr(
+	struct dsaf_device *dsaf_dev,
+	struct dsaf_drv_mac_single_dest_entry *mac_entry)
+{
+	u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+	struct dsaf_tbl_tcam_ucast_cfg mac_data;
+	struct dsaf_drv_tbl_tcam_key mac_key;
+
+	/* mac addr check */
+	if (!is_valid_ether_addr(mac_entry->addr)) {
+		dev_err(dsaf_dev->dev, "rm_uc_addr %s Mac %pM err!\n",
+			dsaf_dev->ae_dev.name, mac_entry->addr);
+		return -EINVAL;
+	}
+
+	/* config key */
+	hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id,
+			     mac_entry->in_port_num, mac_entry->addr);
+
+	entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+	if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+		/* can not find the tcam entry, return 0 */
+		dev_info(dsaf_dev->dev,
+			 "rm_uc_addr no tcam, %s Mac key(%#x:%#x)\n",
+			 dsaf_dev->ae_dev.name,
+			 mac_key.high.val, mac_key.low.val);
+		return 0;
+	}
+
+	dev_dbg(dsaf_dev->dev,
+		"rm_uc_addr, %s Mac key(%#x:%#x) entry_index%d\n",
+		dsaf_dev->ae_dev.name, mac_key.high.val,
+		mac_key.low.val, entry_index);
+
+	hns_dsaf_tcam_uc_get(
+			dsaf_dev, entry_index,
+			(struct dsaf_tbl_tcam_data *)&mac_key,
+			&mac_data);
+
+	/* unicast entry not used locally should not clear */
+	if (mac_entry->port_num != mac_data.tbl_ucast_out_port)
+		return -EFAULT;
+
+	return hns_dsaf_del_mac_entry(dsaf_dev,
+				      mac_entry->in_vlan_id,
+				      mac_entry->in_port_num,
+				      mac_entry->addr);
+}
+
 /**
  * hns_dsaf_set_mac_mc_entry - set mac mc-entry
  * @dsaf_dev: dsa fabric device struct pointer
@@ -1577,6 +1663,7 @@ int hns_dsaf_set_mac_mc_entry(
 	    (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
 	struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
 	struct dsaf_drv_tbl_tcam_key tmp_mac_key;
+	struct dsaf_tbl_tcam_data tcam_data;
 
 	/* mac addr check */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
@@ -1609,9 +1696,12 @@ int hns_dsaf_set_mac_mc_entry(
 		       0, sizeof(mac_data.tbl_mcast_port_msk));
 	} else {
 		/* config hardware entry */
-		hns_dsaf_tcam_mc_get(
-			dsaf_dev, entry_index,
-			(struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data);
+		hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data,
+				     &mac_data);
+
+		tmp_mac_key.high.val =
+			le32_to_cpu(tcam_data.tbl_tcam_data_high);
+		tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
 	}
 	mac_data.tbl_mcast_old_en = 0;
 	mac_data.tbl_mcast_item_vld = 1;
@@ -1623,9 +1713,11 @@ int hns_dsaf_set_mac_mc_entry(
 		dsaf_dev->ae_dev.name, mac_key.high.val,
 		mac_key.low.val, entry_index);
 
-	hns_dsaf_tcam_mc_cfg(
-		dsaf_dev, entry_index,
-		(struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+	tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+	tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+	hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data, NULL,
+			     &mac_data);
 
 	/* config software entry */
 	soft_mac_entry += entry_index;
@@ -1636,6 +1728,16 @@ int hns_dsaf_set_mac_mc_entry(
 	return 0;
 }
 
+static void hns_dsaf_mc_mask_bit_clear(char *dst, const char *src)
+{
+	u16 *a = (u16 *)dst;
+	const u16 *b = (const u16 *)src;
+
+	a[0] &= b[0];
+	a[1] &= b[1];
+	a[2] &= b[2];
+}
+
 /**
  * hns_dsaf_add_mac_mc_port - add mac mc-port
  * @dsaf_dev: dsa fabric device struct pointer
@@ -1646,11 +1748,15 @@ int hns_dsaf_add_mac_mc_port(struct dsaf
 {
 	u16 entry_index = DSAF_INVALID_ENTRY_IDX;
 	struct dsaf_drv_tbl_tcam_key mac_key;
+	struct dsaf_drv_tbl_tcam_key mask_key;
+	struct dsaf_tbl_tcam_data *pmask_key = NULL;
 	struct dsaf_tbl_tcam_mcast_cfg mac_data;
-	struct dsaf_drv_priv *priv =
-	    (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
 	struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
 	struct dsaf_drv_tbl_tcam_key tmp_mac_key;
+	struct dsaf_tbl_tcam_data tcam_data;
+	u8 mc_addr[ETH_ALEN];
+	u8 *mc_mask;
 	int mskid;
 
 	/*chechk mac addr */
@@ -1660,14 +1766,32 @@ int hns_dsaf_add_mac_mc_port(struct dsaf
 		return -EINVAL;
 	}
 
+	ether_addr_copy(mc_addr, mac_entry->addr);
+	mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask;
+	if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) {
+		/* prepare for key data setting */
+		hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask);
+
+		/* config key mask */
+		hns_dsaf_set_mac_key(dsaf_dev, &mask_key,
+				     0x0,
+				     0xff,
+				     mc_mask);
+
+		mask_key.high.val = le32_to_cpu(mask_key.high.val);
+		mask_key.low.val = le32_to_cpu(mask_key.low.val);
+
+		pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key);
+	}
+
 	/*config key */
 	hns_dsaf_set_mac_key(
 		dsaf_dev, &mac_key, mac_entry->in_vlan_id,
-		mac_entry->in_port_num, mac_entry->addr);
+		mac_entry->in_port_num, mc_addr);
 
 	memset(&mac_data, 0, sizeof(struct dsaf_tbl_tcam_mcast_cfg));
 
-	/*check exist? */
+	/* check if the tcam is exist */
 	entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
 	if (entry_index == DSAF_INVALID_ENTRY_IDX) {
 		/*if hasnot , find a empty*/
@@ -1681,11 +1805,15 @@ int hns_dsaf_add_mac_mc_port(struct dsaf
 			return -EINVAL;
 		}
 	} else {
-		/*if exist, add in */
-		hns_dsaf_tcam_mc_get(
-			dsaf_dev, entry_index,
-			(struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data);
+		/* if exist, add in */
+		hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data,
+				     &mac_data);
+
+		tmp_mac_key.high.val =
+			le32_to_cpu(tcam_data.tbl_tcam_data_high);
+		tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
 	}
+
 	/* config hardware entry */
 	if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) {
 		mskid = mac_entry->port_num;
@@ -1708,9 +1836,12 @@ int hns_dsaf_add_mac_mc_port(struct dsaf
 		dsaf_dev->ae_dev.name, mac_key.high.val,
 		mac_key.low.val, entry_index);
 
-	hns_dsaf_tcam_mc_cfg(
-		dsaf_dev, entry_index,
-		(struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+	tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+	tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+	/* config mc entry with mask */
+	hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data,
+			     pmask_key, &mac_data);
 
 	/*config software entry */
 	soft_mac_entry += entry_index;
@@ -1782,15 +1913,18 @@ int hns_dsaf_del_mac_mc_port(struct dsaf
 {
 	u16 entry_index = DSAF_INVALID_ENTRY_IDX;
 	struct dsaf_drv_tbl_tcam_key mac_key;
-	struct dsaf_drv_priv *priv =
-	    (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev);
+	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
 	struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
 	u16 vlan_id;
 	u8 in_port_num;
 	struct dsaf_tbl_tcam_mcast_cfg mac_data;
-	struct dsaf_drv_tbl_tcam_key tmp_mac_key;
+	struct dsaf_tbl_tcam_data tcam_data;
 	int mskid;
 	const u8 empty_msk[sizeof(mac_data.tbl_mcast_port_msk)] = {0};
+	struct dsaf_drv_tbl_tcam_key mask_key, tmp_mac_key;
+	struct dsaf_tbl_tcam_data *pmask_key = NULL;
+	u8 mc_addr[ETH_ALEN];
+	u8 *mc_mask;
 
 	if (!(void *)mac_entry) {
 		dev_err(dsaf_dev->dev,
@@ -1798,10 +1932,6 @@ int hns_dsaf_del_mac_mc_port(struct dsaf
 		return -EINVAL;
 	}
 
-	/*get key info*/
-	vlan_id = mac_entry->in_vlan_id;
-	in_port_num = mac_entry->in_port_num;
-
 	/*check mac addr */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
 		dev_err(dsaf_dev->dev, "del_port failed, addr %pM!\n",
@@ -1809,11 +1939,31 @@ int hns_dsaf_del_mac_mc_port(struct dsaf
 		return -EINVAL;
 	}
 
-	/*config key */
-	hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num,
-			     mac_entry->addr);
+	/* always mask vlan_id field */
+	ether_addr_copy(mc_addr, mac_entry->addr);
+	mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask;
 
-	/*check is exist? */
+	if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) {
+		/* prepare for key data setting */
+		hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask);
+
+		/* config key mask */
+		hns_dsaf_set_mac_key(dsaf_dev, &mask_key, 0x00, 0xff, mc_addr);
+
+		mask_key.high.val = le32_to_cpu(mask_key.high.val);
+		mask_key.low.val = le32_to_cpu(mask_key.low.val);
+
+		pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key);
+	}
+
+	/* get key info */
+	vlan_id = mac_entry->in_vlan_id;
+	in_port_num = mac_entry->in_port_num;
+
+	/* config key */
+	hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num, mc_addr);
+
+	/* check if the tcam entry is exist */
 	entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
 	if (entry_index == DSAF_INVALID_ENTRY_IDX) {
 		/*find none */
@@ -1829,10 +1979,11 @@ int hns_dsaf_del_mac_mc_port(struct dsaf
 		dsaf_dev->ae_dev.name, mac_key.high.val,
 		mac_key.low.val, entry_index);
 
-	/*read entry*/
-	hns_dsaf_tcam_mc_get(
-		dsaf_dev, entry_index,
-		(struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data);
+	/* read entry */
+	hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+	tmp_mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+	tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
 
 	/*del the port*/
 	if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) {
@@ -1857,15 +2008,87 @@ int hns_dsaf_del_mac_mc_port(struct dsaf
 		/* del soft entry */
 		soft_mac_entry += entry_index;
 		soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX;
-	} else { /* not zer, just del port, updata*/
-		hns_dsaf_tcam_mc_cfg(
-			dsaf_dev, entry_index,
-			(struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data);
+	} else { /* not zero, just del port, update */
+		tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val);
+		tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val);
+
+		hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index,
+				     &tcam_data,
+				     pmask_key, &mac_data);
 	}
 
 	return 0;
 }
 
+int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev, u8 mac_id,
+			     u8 port_num)
+{
+	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+	struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+	struct dsaf_tbl_tcam_mcast_cfg mac_data;
+	int ret = 0, i;
+
+	if (HNS_DSAF_IS_DEBUG(dsaf_dev))
+		return 0;
+
+	for (i = 0; i < DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM; i++) {
+		u8 addr[ETH_ALEN];
+		u8 port;
+
+		soft_mac_entry = priv->soft_mac_tbl + i;
+
+		hns_dsaf_tcam_addr_get(&soft_mac_entry->tcam_key, addr);
+		port = dsaf_get_field(
+				soft_mac_entry->tcam_key.low.bits.port_vlan,
+				DSAF_TBL_TCAM_KEY_PORT_M,
+				DSAF_TBL_TCAM_KEY_PORT_S);
+		/* check valid tcam mc entry */
+		if (soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX &&
+		    port == mac_id &&
+		    is_multicast_ether_addr(addr) &&
+		    !is_broadcast_ether_addr(addr)) {
+			const u32 empty_msk[DSAF_PORT_MSK_NUM] = {0};
+			struct dsaf_drv_mac_single_dest_entry mac_entry;
+
+			/* disable receiving of this multicast address for
+			 * the VF.
+			 */
+			ether_addr_copy(mac_entry.addr, addr);
+			mac_entry.in_vlan_id = dsaf_get_field(
+				soft_mac_entry->tcam_key.low.bits.port_vlan,
+				DSAF_TBL_TCAM_KEY_VLAN_M,
+				DSAF_TBL_TCAM_KEY_VLAN_S);
+			mac_entry.in_port_num = mac_id;
+			mac_entry.port_num = port_num;
+			if (hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry)) {
+				ret = -EINVAL;
+				continue;
+			}
+
+			/* disable receiving of this multicast address for
+			 * the mac port if all VF are disable
+			 */
+			hns_dsaf_tcam_mc_get(dsaf_dev, i,
+					     (struct dsaf_tbl_tcam_data *)
+					     (&soft_mac_entry->tcam_key),
+					     &mac_data);
+			dsaf_set_bit(mac_data.tbl_mcast_port_msk[mac_id / 32],
+				     mac_id % 32, 0);
+			if (!memcmp(mac_data.tbl_mcast_port_msk, empty_msk,
+				    sizeof(u32) * DSAF_PORT_MSK_NUM)) {
+				mac_entry.port_num = mac_id;
+				if (hns_dsaf_del_mac_mc_port(dsaf_dev,
+							     &mac_entry)) {
+					ret = -EINVAL;
+					continue;
+				}
+			}
+		}
+	}
+
+	return ret;
+}
+
 /**
  * hns_dsaf_get_mac_uc_entry - get mac uc entry
  * @dsaf_dev: dsa fabric device struct pointer
@@ -1878,6 +2101,7 @@ int hns_dsaf_get_mac_uc_entry(struct dsa
 	struct dsaf_drv_tbl_tcam_key mac_key;
 
 	struct dsaf_tbl_tcam_ucast_cfg mac_data;
+	struct dsaf_tbl_tcam_data tcam_data;
 
 	/* check macaddr */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
@@ -1906,9 +2130,12 @@ int hns_dsaf_get_mac_uc_entry(struct dsa
 		dsaf_dev->ae_dev.name, mac_key.high.val,
 		mac_key.low.val, entry_index);
 
-	/*read entry*/
-	hns_dsaf_tcam_uc_get(dsaf_dev, entry_index,
-			     (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data);
+	/* read entry */
+	hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+	mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+	mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
+
 	mac_entry->port_num = mac_data.tbl_ucast_out_port;
 
 	return 0;
@@ -1926,6 +2153,7 @@ int hns_dsaf_get_mac_mc_entry(struct dsa
 	struct dsaf_drv_tbl_tcam_key mac_key;
 
 	struct dsaf_tbl_tcam_mcast_cfg mac_data;
+	struct dsaf_tbl_tcam_data tcam_data;
 
 	/*check mac addr */
 	if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
@@ -1955,8 +2183,10 @@ int hns_dsaf_get_mac_mc_entry(struct dsa
 		mac_key.low.val, entry_index);
 
 	/*read entry */
-	hns_dsaf_tcam_mc_get(dsaf_dev, entry_index,
-			     (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data);
+	hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+	mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+	mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
 
 	mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F;
 	return 0;
@@ -1976,9 +2206,10 @@ int hns_dsaf_get_mac_entry_by_index(
 
 	struct dsaf_tbl_tcam_mcast_cfg mac_data;
 	struct dsaf_tbl_tcam_ucast_cfg mac_uc_data;
-	char mac_addr[MAC_NUM_OCTETS_PER_ADDR] = {0};
+	struct dsaf_tbl_tcam_data tcam_data;
+	char mac_addr[ETH_ALEN] = {0};
 
-	if (entry_index >= DSAF_TCAM_SUM) {
+	if (entry_index >= dsaf_dev->tcam_max_num) {
 		/* find none, del error */
 		dev_err(dsaf_dev->dev, "get_uc_entry failed, %s\n",
 			dsaf_dev->ae_dev.name);
@@ -1986,8 +2217,10 @@ int hns_dsaf_get_mac_entry_by_index(
 	}
 
 	/* mc entry, do read opt */
-	hns_dsaf_tcam_mc_get(dsaf_dev, entry_index,
-			     (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data);
+	hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data);
+
+	mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+	mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
 
 	mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F;
 
@@ -2004,9 +2237,12 @@ int hns_dsaf_get_mac_entry_by_index(
 		/**mc donot do*/
 	} else {
 		/*is not mc, just uc... */
-		hns_dsaf_tcam_uc_get(dsaf_dev, entry_index,
-				     (struct dsaf_tbl_tcam_data *)&mac_key,
+		hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, &tcam_data,
 				     &mac_uc_data);
+
+		mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high);
+		mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low);
+
 		mac_entry->port_mask[0] = (1 << mac_uc_data.tbl_ucast_out_port);
 	}
 
@@ -2670,6 +2906,59 @@ int hns_dsaf_get_regs_count(void)
 	return DSAF_DUMP_REGS_NUM;
 }
 
+/* Reserve the last TCAM entry for promisc support */
+#define dsaf_promisc_tcam_entry(port) \
+	(DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM + (port))
+void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
+			       u32 port, bool enable)
+{
+	struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+	struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl;
+	u16 entry_index;
+	struct dsaf_drv_tbl_tcam_key tbl_tcam_data, tbl_tcam_mask;
+	struct dsaf_tbl_tcam_mcast_cfg mac_data = {0};
+
+	if ((AE_IS_VER1(dsaf_dev->dsaf_ver)) || HNS_DSAF_IS_DEBUG(dsaf_dev))
+		return;
+
+	/* find the tcam entry index for promisc */
+	entry_index = dsaf_promisc_tcam_entry(port);
+
+	/* config key mask */
+	if (enable) {
+		memset(&tbl_tcam_data, 0, sizeof(tbl_tcam_data));
+		memset(&tbl_tcam_mask, 0, sizeof(tbl_tcam_mask));
+		dsaf_set_field(tbl_tcam_data.low.bits.port_vlan,
+			       DSAF_TBL_TCAM_KEY_PORT_M,
+			       DSAF_TBL_TCAM_KEY_PORT_S, port);
+		dsaf_set_field(tbl_tcam_mask.low.bits.port_vlan,
+			       DSAF_TBL_TCAM_KEY_PORT_M,
+			       DSAF_TBL_TCAM_KEY_PORT_S, 0xf);
+
+		/* SUB_QID */
+		dsaf_set_bit(mac_data.tbl_mcast_port_msk[0],
+			     DSAF_SERVICE_NW_NUM, true);
+		mac_data.tbl_mcast_item_vld = true;	/* item_vld bit */
+	} else {
+		mac_data.tbl_mcast_item_vld = false;	/* item_vld bit */
+	}
+
+	dev_dbg(dsaf_dev->dev,
+		"set_promisc_entry, %s Mac key(%#x:%#x) entry_index%d\n",
+		dsaf_dev->ae_dev.name, tbl_tcam_data.high.val,
+		tbl_tcam_data.low.val, entry_index);
+
+	/* config promisc entry with mask */
+	hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index,
+			     (struct dsaf_tbl_tcam_data *)&tbl_tcam_data,
+			     (struct dsaf_tbl_tcam_data *)&tbl_tcam_mask,
+			     &mac_data);
+
+	/* config software entry */
+	soft_mac_entry += entry_index;
+	soft_mac_entry->index = enable ? entry_index : DSAF_INVALID_ENTRY_IDX;
+}
+
 /**
  * dsaf_probe - probo dsaf dev
  * @pdev: dasf platform device
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h	2017-02-12 16:03:20.000000000 -0500
@@ -35,8 +35,6 @@ struct hns_mac_cb;
 
 #define DSAF_CFG_READ_CNT   30
 
-#define MAC_NUM_OCTETS_PER_ADDR 6
-
 #define DSAF_DUMP_REGS_NUM 504
 #define DSAF_STATIC_NUM 28
 #define DSAF_V2_STATIC_NUM	44
@@ -165,7 +163,7 @@ enum dsaf_mode {
 /*mac entry, mc or uc entry*/
 struct dsaf_drv_mac_single_dest_entry {
 	/* mac addr, match the entry*/
-	u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+	u8 addr[ETH_ALEN];
 	u16 in_vlan_id; /* value of VlanId */
 
 	/* the vld input port num, dsaf-mode fix 0, */
@@ -179,7 +177,7 @@ struct dsaf_drv_mac_single_dest_entry {
 /*only mc entry*/
 struct dsaf_drv_mac_multi_dest_entry {
 	/* mac addr, match the entry*/
-	u8 addr[MAC_NUM_OCTETS_PER_ADDR];
+	u8 addr[ETH_ALEN];
 	u16 in_vlan_id;
 	/* this mac addr output port,*/
 	/*	bit0-bit5 means Port0-Port5(1bit is vld)**/
@@ -308,8 +306,6 @@ struct dsaf_misc_op {
 	/* reset series function, it will be reset if the dereset is 0 */
 	void (*dsaf_reset)(struct dsaf_device *dsaf_dev, bool dereset);
 	void (*xge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
-	void (*xge_core_srst)(struct dsaf_device *dsaf_dev, u32 port,
-			      bool dereset);
 	void (*ge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
 	void (*ppe_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
 	void (*ppe_comm_srst)(struct dsaf_device *dsaf_dev, bool dereset);
@@ -343,6 +339,7 @@ struct dsaf_device {
 	enum hal_dsaf_mode dsaf_en;
 	enum hal_dsaf_tc_mode dsaf_tc_mode;
 	u32 dsaf_ver;
+	u16 tcam_max_num;	/* max TCAM entry for user except promisc */
 
 	struct ppe_common_cb *ppe_common[DSAF_COMM_DEV_NUM];
 	struct rcb_common_cb *rcb_common[DSAF_COMM_DEV_NUM];
@@ -360,6 +357,11 @@ static inline void *hns_dsaf_dev_priv(co
 	return (void *)((u8 *)dsaf_dev + sizeof(*dsaf_dev));
 }
 
+#define DSAF_TBL_TCAM_KEY_PORT_S 0
+#define DSAF_TBL_TCAM_KEY_PORT_M (((1ULL << 4) - 1) << 0)
+#define DSAF_TBL_TCAM_KEY_VLAN_S 4
+#define DSAF_TBL_TCAM_KEY_VLAN_M (((1ULL << 12) - 1) << 4)
+
 struct dsaf_drv_tbl_tcam_key {
 	union {
 		struct {
@@ -373,11 +375,9 @@ struct dsaf_drv_tbl_tcam_key {
 	} high;
 	union {
 		struct {
-			u32 port:4; /* port id, */
-			/* dsaf-mode fixed 0, non-dsaf-mode port id*/
-			u32 vlan:12; /* vlan id */
-			u32 mac_5:8;
-			u32 mac_4:8;
+			u16 port_vlan;
+			u8 mac_5;
+			u8 mac_4;
 		} bits;
 
 		u32 val;
@@ -461,10 +461,19 @@ void hns_dsaf_get_strings(int stringset,
 void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data);
 int hns_dsaf_get_regs_count(void);
 void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en);
+void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
+			       u32 port, bool enable);
 
 void hns_dsaf_get_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id,
 				  u32 *en);
 int hns_dsaf_set_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id,
 				 u32 en);
+int hns_dsaf_rm_mac_addr(
+	struct dsaf_device *dsaf_dev,
+	struct dsaf_drv_mac_single_dest_entry *mac_entry);
+
+int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev,
+			     u8 mac_id, u8 port_num);
+
 
 #endif /* __HNS_DSAF_MAIN_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c	2017-02-12 16:03:20.000000000 -0500
@@ -23,7 +23,6 @@ enum _dsm_op_index {
 enum _dsm_rst_type {
 	HNS_DSAF_RESET_FUNC     = 0x1,
 	HNS_PPE_RESET_FUNC      = 0x2,
-	HNS_XGE_CORE_RESET_FUNC = 0x3,
 	HNS_XGE_RESET_FUNC      = 0x4,
 	HNS_GE_RESET_FUNC       = 0x5,
 	HNS_DSAF_CHN_RESET_FUNC = 0x6,
@@ -213,26 +212,6 @@ static void hns_dsaf_xge_srst_by_port_ac
 				   HNS_XGE_RESET_FUNC, port, dereset);
 }
 
-static void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev,
-					   u32 port, bool dereset)
-{
-	u32 reg_val = 0;
-	u32 reg_addr;
-
-	if (port >= DSAF_XGE_NUM)
-		return;
-
-	reg_val |= XGMAC_TRX_CORE_SRST_M
-		<< dsaf_dev->mac_cb[port]->port_rst_off;
-
-	if (!dereset)
-		reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG;
-	else
-		reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG;
-
-	dsaf_write_sub(dsaf_dev, reg_addr, reg_val);
-}
-
 /**
  * hns_dsaf_srst_chns - reset dsaf channels
  * @dsaf_dev: dsaf device struct pointer
@@ -293,14 +272,6 @@ void hns_dsaf_roce_srst_acpi(struct dsaf
 				   HNS_ROCE_RESET_FUNC, 0, dereset);
 }
 
-static void
-hns_dsaf_xge_core_srst_by_port_acpi(struct dsaf_device *dsaf_dev,
-				    u32 port, bool dereset)
-{
-	hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC,
-				   HNS_XGE_CORE_RESET_FUNC, port, dereset);
-}
-
 static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port,
 				     bool dereset)
 {
@@ -597,7 +568,6 @@ struct dsaf_misc_op *hns_misc_op_get(str
 
 		misc_op->dsaf_reset = hns_dsaf_rst;
 		misc_op->xge_srst = hns_dsaf_xge_srst_by_port;
-		misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port;
 		misc_op->ge_srst = hns_dsaf_ge_srst_by_port;
 		misc_op->ppe_srst = hns_ppe_srst_by_port;
 		misc_op->ppe_comm_srst = hns_ppe_com_srst;
@@ -615,7 +585,6 @@ struct dsaf_misc_op *hns_misc_op_get(str
 
 		misc_op->dsaf_reset = hns_dsaf_rst_acpi;
 		misc_op->xge_srst = hns_dsaf_xge_srst_by_port_acpi;
-		misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port_acpi;
 		misc_op->ge_srst = hns_dsaf_ge_srst_by_port_acpi;
 		misc_op->ppe_srst = hns_ppe_srst_by_port_acpi;
 		misc_op->ppe_comm_srst = hns_ppe_com_srst;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -41,6 +41,9 @@
 #define DSAF_SW_PORT_NUM	8
 #define DSAF_TOTAL_QUEUE_NUM	129
 
+/* reserved a tcam entry for each port to support promisc by fuzzy match */
+#define DSAFV2_MAC_FUZZY_TCAM_NUM    DSAF_MAX_PORT_NUM
+
 #define DSAF_TCAM_SUM		512
 #define DSAF_LINE_SUM		(2048 * 14)
 
@@ -297,6 +300,8 @@
 #define DSAF_TBL_LKUP_NUM_I_0_REG		0x50C0
 #define DSAF_TBL_LKUP_NUM_O_0_REG		0x50E0
 #define DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG	0x510C
+#define DSAF_TBL_TCAM_MATCH_CFG_H_REG		0x5130
+#define DSAF_TBL_TCAM_MATCH_CFG_L_REG		0x5134
 
 #define DSAF_INODE_FIFO_WL_0_REG		0x6000
 #define DSAF_ONODE_FIFO_WL_0_REG		0x6020
@@ -309,7 +314,6 @@
 #define PPE_COM_INTEN_REG			0x110
 #define PPE_COM_RINT_REG			0x114
 #define PPE_COM_INTSTS_REG			0x118
-#define PPE_COM_COMMON_CNT_CLR_CE_REG		0x1120
 #define PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG	0x300
 #define PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG	0x600
 #define PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG	0x900
@@ -698,8 +702,6 @@
 #define XGMAC_RX_SYMBOLERRPKTS			0x0210
 #define XGMAC_RX_FCSERRPKTS			0x0218
 
-#define XGMAC_TRX_CORE_SRST_M			0x2080
-
 #define DSAF_SRAM_INIT_OVER_M 0xff
 #define DSAFV2_SRAM_INIT_OVER_M 0x3ff
 #define DSAF_SRAM_INIT_OVER_S 0
@@ -978,6 +980,11 @@
 #define XGMAC_ENABLE_TX_B		0
 #define XGMAC_ENABLE_RX_B		1
 
+#define XGMAC_UNIDIR_EN_B		0
+#define XGMAC_RF_TX_EN_B		1
+#define XGMAC_LF_RF_INSERT_S		2
+#define XGMAC_LF_RF_INSERT_M		(0x3 << XGMAC_LF_RF_INSERT_S)
+
 #define XGMAC_CTL_TX_FCS_B		0
 #define XGMAC_CTL_TX_PAD_B		1
 #define XGMAC_CTL_TX_PREAMBLE_TRANS_B	3
@@ -1007,9 +1014,7 @@
 
 static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value)
 {
-	u8 __iomem *reg_addr = ACCESS_ONCE(base);
-
-	writel(value, reg_addr + reg);
+	writel(value, base + reg);
 }
 
 #define dsaf_write_dev(a, reg, value) \
@@ -1017,9 +1022,7 @@ static inline void dsaf_write_reg(void _
 
 static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg)
 {
-	u8 __iomem *reg_addr = ACCESS_ONCE(base);
-
-	return readl(reg_addr + reg);
+	return readl(base + reg);
 }
 
 static inline void dsaf_write_syscon(struct regmap *base, u32 reg, u32 value)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c	2017-02-12 16:03:20.000000000 -0500
@@ -108,6 +108,31 @@ static void hns_xgmac_rx_enable(struct m
 }
 
 /**
+ * hns_xgmac_tx_lf_rf_insert - insert lf rf control about xgmac
+ * @mac_drv: mac driver
+ * @mode: inserf rf or lf
+ */
+static void hns_xgmac_lf_rf_insert(struct mac_driver *mac_drv, u32 mode)
+{
+	dsaf_set_dev_field(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG,
+			   XGMAC_LF_RF_INSERT_M, XGMAC_LF_RF_INSERT_S, mode);
+}
+
+/**
+ * hns_xgmac__lf_rf_control_init - initial the lf rf control register
+ * @mac_drv: mac driver
+ */
+static void hns_xgmac_lf_rf_control_init(struct mac_driver *mac_drv)
+{
+	u32 val = 0;
+
+	dsaf_set_bit(val, XGMAC_UNIDIR_EN_B, 0);
+	dsaf_set_bit(val, XGMAC_RF_TX_EN_B, 1);
+	dsaf_set_field(val, XGMAC_LF_RF_INSERT_M, XGMAC_LF_RF_INSERT_S, 0);
+	dsaf_write_reg(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG, val);
+}
+
+/**
  *hns_xgmac_enable - enable xgmac port
  *@drv: mac driver
  *@mode: mode of mac port
@@ -115,12 +140,8 @@ static void hns_xgmac_rx_enable(struct m
 static void hns_xgmac_enable(void *mac_drv, enum mac_commom_mode mode)
 {
 	struct mac_driver *drv = (struct mac_driver *)mac_drv;
-	struct dsaf_device *dsaf_dev
-		= (struct dsaf_device *)dev_get_drvdata(drv->dev);
-	u32 port = drv->mac_id;
 
-	dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 1);
-	mdelay(10);
+	hns_xgmac_lf_rf_insert(drv, HNS_XGMAC_NO_LF_RF_INSERT);
 
 	/*enable XGE rX/tX */
 	if (mode == MAC_COMM_MODE_TX) {
@@ -143,9 +164,6 @@ static void hns_xgmac_enable(void *mac_d
 static void hns_xgmac_disable(void *mac_drv, enum mac_commom_mode mode)
 {
 	struct mac_driver *drv = (struct mac_driver *)mac_drv;
-	struct dsaf_device *dsaf_dev
-		= (struct dsaf_device *)dev_get_drvdata(drv->dev);
-	u32 port = drv->mac_id;
 
 	if (mode == MAC_COMM_MODE_TX) {
 		hns_xgmac_tx_enable(drv, 0);
@@ -155,9 +173,7 @@ static void hns_xgmac_disable(void *mac_
 		hns_xgmac_tx_enable(drv, 0);
 		hns_xgmac_rx_enable(drv, 0);
 	}
-
-	mdelay(10);
-	dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 0);
+	hns_xgmac_lf_rf_insert(drv, HNS_XGMAC_LF_INSERT);
 }
 
 /**
@@ -203,6 +219,7 @@ static void hns_xgmac_init(void *mac_drv
 	dsaf_dev->misc_op->xge_srst(dsaf_dev, port, 1);
 
 	mdelay(100);
+	hns_xgmac_lf_rf_control_init(drv);
 	hns_xgmac_exc_irq_en(drv, 0);
 
 	hns_xgmac_pma_fec_enable(drv, 0x0, 0x0);
@@ -788,7 +805,7 @@ static int hns_xgmac_get_sset_count(int
  */
 static int hns_xgmac_get_regs_count(void)
 {
-	return ETH_XGMAC_DUMP_NUM;
+	return HNS_XGMAC_DUMP_NUM;
 }
 
 void *hns_xgmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h	2017-02-12 16:03:20.000000000 -0500
@@ -10,6 +10,7 @@
 #ifndef _HNS_XGMAC_H
 #define _HNS_XGMAC_H
 
-#define ETH_XGMAC_DUMP_NUM		(214)
-
+#define HNS_XGMAC_DUMP_NUM		214
+#define HNS_XGMAC_NO_LF_RF_INSERT	0x0
+#define HNS_XGMAC_LF_INSERT		0x2
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_enet.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_enet.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_enet.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_enet.c	2017-02-12 16:03:20.000000000 -0500
@@ -22,6 +22,7 @@
 
 #include "hnae.h"
 #include "hns_enet.h"
+#include "hns_dsaf_mac.h"
 
 #define NIC_MAX_Q_PER_VF 16
 #define HNS_NIC_TX_TIMEOUT (5 * HZ)
@@ -304,8 +305,8 @@ int hns_nic_net_xmit_hw(struct net_devic
 			struct hns_nic_ring_data *ring_data)
 {
 	struct hns_nic_priv *priv = netdev_priv(ndev);
-	struct device *dev = priv->dev;
 	struct hnae_ring *ring = ring_data->ring;
+	struct device *dev = ring_to_dev(ring);
 	struct netdev_queue *dev_queue;
 	struct skb_frag_struct *frag;
 	int buf_num;
@@ -565,6 +566,71 @@ static void get_rx_desc_bnum(u32 bnum_fl
 				   HNS_RXD_BUFNUM_M, HNS_RXD_BUFNUM_S);
 }
 
+static void hns_nic_rx_checksum(struct hns_nic_ring_data *ring_data,
+				struct sk_buff *skb, u32 flag)
+{
+	struct net_device *netdev = ring_data->napi.dev;
+	u32 l3id;
+	u32 l4id;
+
+	/* check if RX checksum offload is enabled */
+	if (unlikely(!(netdev->features & NETIF_F_RXCSUM)))
+		return;
+
+	/* In hardware, we only support checksum for the following protocols:
+	 * 1) IPv4,
+	 * 2) TCP(over IPv4 or IPv6),
+	 * 3) UDP(over IPv4 or IPv6),
+	 * 4) SCTP(over IPv4 or IPv6)
+	 * but we support many L3(IPv4, IPv6, MPLS, PPPoE etc) and L4(TCP,
+	 * UDP, GRE, SCTP, IGMP, ICMP etc.) protocols.
+	 *
+	 * Hardware limitation:
+	 * Our present hardware RX Descriptor lacks L3/L4 checksum "Status &
+	 * Error" bit (which usually can be used to indicate whether checksum
+	 * was calculated by the hardware and if there was any error encountered
+	 * during checksum calculation).
+	 *
+	 * Software workaround:
+	 * We do get info within the RX descriptor about the kind of L3/L4
+	 * protocol coming in the packet and the error status. These errors
+	 * might not just be checksum errors but could be related to version,
+	 * length of IPv4, UDP, TCP etc.
+	 * Because there is no-way of knowing if it is a L3/L4 error due to bad
+	 * checksum or any other L3/L4 error, we will not (cannot) convey
+	 * checksum status for such cases to upper stack and will not maintain
+	 * the RX L3/L4 checksum counters as well.
+	 */
+
+	l3id = hnae_get_field(flag, HNS_RXD_L3ID_M, HNS_RXD_L3ID_S);
+	l4id = hnae_get_field(flag, HNS_RXD_L4ID_M, HNS_RXD_L4ID_S);
+
+	/*  check L3 protocol for which checksum is supported */
+	if ((l3id != HNS_RX_FLAG_L3ID_IPV4) && (l3id != HNS_RX_FLAG_L3ID_IPV6))
+		return;
+
+	/* check for any(not just checksum)flagged L3 protocol errors */
+	if (unlikely(hnae_get_bit(flag, HNS_RXD_L3E_B)))
+		return;
+
+	/* we do not support checksum of fragmented packets */
+	if (unlikely(hnae_get_bit(flag, HNS_RXD_FRAG_B)))
+		return;
+
+	/*  check L4 protocol for which checksum is supported */
+	if ((l4id != HNS_RX_FLAG_L4ID_TCP) &&
+	    (l4id != HNS_RX_FLAG_L4ID_UDP) &&
+	    (l4id != HNS_RX_FLAG_L4ID_SCTP))
+		return;
+
+	/* check for any(not just checksum)flagged L4 protocol errors */
+	if (unlikely(hnae_get_bit(flag, HNS_RXD_L4E_B)))
+		return;
+
+	/* now, this has to be a packet with valid RX checksum */
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
 static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data,
 			       struct sk_buff **out_skb, int *out_bnum)
 {
@@ -683,13 +749,10 @@ out_bnum_err:
 	ring->stats.rx_pkts++;
 	ring->stats.rx_bytes += skb->len;
 
-	if (unlikely(hnae_get_bit(bnum_flag, HNS_RXD_L3E_B) ||
-		     hnae_get_bit(bnum_flag, HNS_RXD_L4E_B))) {
-		ring->stats.l3l4_csum_err++;
-		return 0;
-	}
-
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	/* indicate to upper stack if our hardware has already calculated
+	 * the RX checksum
+	 */
+	hns_nic_rx_checksum(ring_data, skb, bnum_flag);
 
 	return 0;
 }
@@ -1426,10 +1489,6 @@ static int hns_nic_change_mtu(struct net
 	struct hnae_handle *h = priv->ae_handle;
 	int ret;
 
-	/* MTU < 68 is an error and causes problems on some kernels */
-	if (new_mtu < 68)
-		return -EINVAL;
-
 	if (!h->dev->ops->set_mtu)
 		return -ENOTSUPP;
 
@@ -1496,6 +1555,29 @@ static netdev_features_t hns_nic_fix_fea
 	return features;
 }
 
+static int hns_nic_uc_sync(struct net_device *netdev, const unsigned char *addr)
+{
+	struct hns_nic_priv *priv = netdev_priv(netdev);
+	struct hnae_handle *h = priv->ae_handle;
+
+	if (h->dev->ops->add_uc_addr)
+		return h->dev->ops->add_uc_addr(h, addr);
+
+	return 0;
+}
+
+static int hns_nic_uc_unsync(struct net_device *netdev,
+			     const unsigned char *addr)
+{
+	struct hns_nic_priv *priv = netdev_priv(netdev);
+	struct hnae_handle *h = priv->ae_handle;
+
+	if (h->dev->ops->rm_uc_addr)
+		return h->dev->ops->rm_uc_addr(h, addr);
+
+	return 0;
+}
+
 /**
  * nic_set_multicast_list - set mutl mac address
  * @netdev: net device
@@ -1514,6 +1596,10 @@ void hns_set_multicast_list(struct net_d
 		return;
 	}
 
+	if (h->dev->ops->clr_mc_addr)
+		if (h->dev->ops->clr_mc_addr(h))
+			netdev_err(ndev, "clear multicast address fail\n");
+
 	if (h->dev->ops->set_mc_addr) {
 		netdev_for_each_mc_addr(ha, ndev)
 			if (h->dev->ops->set_mc_addr(h, ha->addr))
@@ -1534,6 +1620,9 @@ void hns_nic_set_rx_mode(struct net_devi
 	}
 
 	hns_set_multicast_list(ndev);
+
+	if (__dev_uc_sync(ndev, hns_nic_uc_sync, hns_nic_uc_unsync))
+		netdev_err(ndev, "sync uc address fail\n");
 }
 
 struct rtnl_link_stats64 *hns_nic_get_stats64(struct net_device *ndev,
@@ -1992,14 +2081,20 @@ static int hns_nic_dev_probe(struct plat
 		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
 	ndev->vlan_features |= NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO;
 
+	/* MTU range: 68 - 9578 (v1) or 9706 (v2) */
+	ndev->min_mtu = MAC_MIN_MTU;
 	switch (priv->enet_ver) {
 	case AE_VERSION_2:
 		ndev->features |= NETIF_F_TSO | NETIF_F_TSO6;
 		ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 			NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
 			NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6;
+		ndev->max_mtu = MAC_MAX_MTU_V2 -
+				(ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
 		break;
 	default:
+		ndev->max_mtu = MAC_MAX_MTU -
+				(ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
 		break;
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -1178,7 +1178,8 @@ static int hns_nic_nway_reset(struct net
 	struct phy_device *phy = netdev->phydev;
 
 	if (netif_running(netdev)) {
-		if (phy)
+		/* if autoneg is disabled, don't restart auto-negotiation */
+		if (phy && phy->autoneg == AUTONEG_ENABLE)
 			ret = genphy_restart_aneg(phy);
 	}
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/hp/hp100.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hp/hp100.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/hp/hp100.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/hp/hp100.c	2017-02-12 16:03:20.000000000 -0500
@@ -427,7 +427,6 @@ static const struct net_device_ops hp100
 	.ndo_start_xmit		= hp100_start_xmit_bm,
 	.ndo_get_stats 		= hp100_get_stats,
 	.ndo_set_rx_mode	= hp100_set_multicast_list,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
@@ -438,7 +437,6 @@ static const struct net_device_ops hp100
 	.ndo_start_xmit		= hp100_start_xmit,
 	.ndo_get_stats 		= hp100_get_stats,
 	.ndo_set_rx_mode	= hp100_set_multicast_list,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/82596.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/82596.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/82596.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/82596.c	2017-02-12 16:03:20.000000000 -0500
@@ -1118,7 +1118,6 @@ static const struct net_device_ops i596_
 	.ndo_start_xmit		= i596_start_xmit,
 	.ndo_set_rx_mode	= 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,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/ether1.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/ether1.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/ether1.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/ether1.c	2017-02-12 16:03:20.000000000 -0500
@@ -981,7 +981,6 @@ static const struct net_device_ops ether
 	.ndo_set_rx_mode	= 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,
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/lib82596.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/lib82596.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/lib82596.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/lib82596.c	2017-02-12 16:03:20.000000000 -0500
@@ -1037,7 +1037,6 @@ static const struct net_device_ops i596_
 	.ndo_start_xmit		= i596_start_xmit,
 	.ndo_set_rx_mode	= set_multicast_list,
 	.ndo_tx_timeout		= i596_tx_timeout,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/sun3_82586.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/sun3_82586.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/i825xx/sun3_82586.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/i825xx/sun3_82586.c	2017-02-12 16:03:20.000000000 -0500
@@ -337,7 +337,6 @@ static const struct net_device_ops sun3_
 	.ndo_get_stats		= sun3_82586_get_stats,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= eth_mac_addr,
-	.ndo_change_mtu		= eth_change_mtu,
 };
 
 static int __init sun3_82586_probe1(struct net_device *dev,int ioaddr)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/ehea/ehea_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -1981,14 +1981,6 @@ 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 xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
 {
 	swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
@@ -2970,7 +2962,6 @@ static const struct net_device_ops ehea_
 	.ndo_set_mac_address	= ehea_set_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_rx_mode	= 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,
@@ -3043,13 +3034,16 @@ static struct ehea_port *ehea_setup_sing
 			NETIF_F_IP_CSUM;
 	dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
 
+	/* MTU range: 68 - 9022 */
+	dev->min_mtu = ETH_MIN_MTU;
+	dev->max_mtu = EHEA_MAX_PACKET_SIZE;
+
 	INIT_WORK(&port->reset_task, ehea_reset_port);
 	INIT_DELAYED_WORK(&port->stats_work, ehea_update_stats);
 
 	init_waitqueue_head(&port->swqe_avail_wq);
 	init_waitqueue_head(&port->restart_wq);
 
-	memset(&port->stats, 0, sizeof(struct net_device_stats));
 	ret = register_netdev(dev);
 	if (ret) {
 		pr_err("register_netdev failed. ret=%d\n", ret);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/ibm/emac/core.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/emac/core.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/ibm/emac/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/emac/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -47,7 +47,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/dma.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/dcr.h>
 #include <asm/dcr-regs.h>
 
@@ -1099,9 +1099,6 @@ static int emac_change_mtu(struct net_de
 	struct emac_instance *dev = netdev_priv(ndev);
 	int ret = 0;
 
-	if (new_mtu < EMAC_MIN_MTU || new_mtu > dev->max_mtu)
-		return -EINVAL;
-
 	DBG(dev, "change_mtu(%d)" NL, new_mtu);
 
 	if (netif_running(ndev)) {
@@ -2564,7 +2561,7 @@ static int emac_init_config(struct emac_
 	if (emac_read_uint_prop(np, "cell-index", &dev->cell_index, 1))
 		return -ENXIO;
 	if (emac_read_uint_prop(np, "max-frame-size", &dev->max_mtu, 0))
-		dev->max_mtu = 1500;
+		dev->max_mtu = ETH_DATA_LEN;
 	if (emac_read_uint_prop(np, "rx-fifo-size", &dev->rx_fifo_size, 0))
 		dev->rx_fifo_size = 2048;
 	if (emac_read_uint_prop(np, "tx-fifo-size", &dev->tx_fifo_size, 0))
@@ -2718,7 +2715,6 @@ static const struct net_device_ops emac_
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= emac_set_mac_address,
 	.ndo_start_xmit		= emac_start_xmit,
-	.ndo_change_mtu		= eth_change_mtu,
 };
 
 static const struct net_device_ops emac_gige_netdev_ops = {
@@ -2891,6 +2887,10 @@ static int emac_probe(struct platform_de
 		ndev->netdev_ops = &emac_netdev_ops;
 	ndev->ethtool_ops = &emac_ethtool_ops;
 
+	/* MTU range: 46 - 1500 or whatever is in OF */
+	ndev->min_mtu = EMAC_MIN_MTU;
+	ndev->max_mtu = dev->max_mtu;
+
 	netif_carrier_off(ndev);
 
 	err = register_netdev(ndev);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/ibm/ibmveth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/ibmveth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/ibm/ibmveth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/ibmveth.c	2017-02-12 16:03:20.000000000 -0500
@@ -1181,7 +1181,9 @@ map_failed:
 
 static void ibmveth_rx_mss_helper(struct sk_buff *skb, u16 mss, int lrg_pkt)
 {
+	struct tcphdr *tcph;
 	int offset = 0;
+	int hdr_len;
 
 	/* only TCP packets will be aggregated */
 	if (skb->protocol == htons(ETH_P_IP)) {
@@ -1208,14 +1210,20 @@ static void ibmveth_rx_mss_helper(struct
 	/* if mss is not set through Large Packet bit/mss in rx buffer,
 	 * expect that the mss will be written to the tcp header checksum.
 	 */
+	tcph = (struct tcphdr *)(skb->data + offset);
 	if (lrg_pkt) {
 		skb_shinfo(skb)->gso_size = mss;
 	} else if (offset) {
-		struct tcphdr *tcph = (struct tcphdr *)(skb->data + offset);
-
 		skb_shinfo(skb)->gso_size = ntohs(tcph->check);
 		tcph->check = 0;
 	}
+
+	if (skb_shinfo(skb)->gso_size) {
+		hdr_len = offset + tcph->doff * 4;
+		skb_shinfo(skb)->gso_segs =
+				DIV_ROUND_UP(skb->len - hdr_len,
+					     skb_shinfo(skb)->gso_size);
+	}
 }
 
 static int ibmveth_poll(struct napi_struct *napi, int budget)
@@ -1410,9 +1418,6 @@ static int ibmveth_change_mtu(struct net
 	int i, rc;
 	int need_restart = 0;
 
-	if (new_mtu < IBMVETH_MIN_MTU)
-		return -EINVAL;
-
 	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++)
 		if (new_mtu_oh <= adapter->rx_buff_pool[i].buff_size)
 			break;
@@ -1596,8 +1601,11 @@ static int ibmveth_probe(struct vio_dev
 	netdev->netdev_ops = &ibmveth_netdev_ops;
 	netdev->ethtool_ops = &netdev_ethtool_ops;
 	SET_NETDEV_DEV(netdev, &dev->dev);
-	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
-		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+	netdev->hw_features = NETIF_F_SG;
+	if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) {
+		netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+				       NETIF_F_RXCSUM;
+	}
 
 	netdev->features |= netdev->hw_features;
 
@@ -1612,6 +1620,9 @@ static int ibmveth_probe(struct vio_dev
 		netdev->hw_features |= NETIF_F_TSO;
 	}
 
+	netdev->min_mtu = IBMVETH_MIN_MTU;
+	netdev->max_mtu = ETH_MAX_MTU;
+
 	memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN);
 
 	if (firmware_has_feature(FW_FEATURE_CMO))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/ibm/ibmvnic.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/ibmvnic.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/ibm/ibmvnic.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/ibm/ibmvnic.c	2017-02-12 16:03:20.000000000 -0500
@@ -901,17 +901,6 @@ static int ibmvnic_set_mac(struct net_de
 	return 0;
 }
 
-static int ibmvnic_change_mtu(struct net_device *netdev, int new_mtu)
-{
-	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
-
-	if (new_mtu > adapter->req_mtu || new_mtu < adapter->min_mtu)
-		return -EINVAL;
-
-	netdev->mtu = new_mtu;
-	return 0;
-}
-
 static void ibmvnic_tx_timeout(struct net_device *dev)
 {
 	struct ibmvnic_adapter *adapter = netdev_priv(dev);
@@ -1028,7 +1017,6 @@ static const struct net_device_ops ibmvn
 	.ndo_set_rx_mode	= ibmvnic_set_multi,
 	.ndo_set_mac_address	= ibmvnic_set_mac,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_change_mtu		= ibmvnic_change_mtu,
 	.ndo_tx_timeout		= ibmvnic_tx_timeout,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ibmvnic_netpoll_controller,
@@ -2638,10 +2626,12 @@ static void handle_query_cap_rsp(union i
 		break;
 	case MIN_MTU:
 		adapter->min_mtu = be64_to_cpu(crq->query_capability.number);
+		netdev->min_mtu = adapter->min_mtu;
 		netdev_dbg(netdev, "min_mtu = %lld\n", adapter->min_mtu);
 		break;
 	case MAX_MTU:
 		adapter->max_mtu = be64_to_cpu(crq->query_capability.number);
+		netdev->max_mtu = adapter->max_mtu;
 		netdev_dbg(netdev, "max_mtu = %lld\n", adapter->max_mtu);
 		break;
 	case MAX_MULTICAST_FILTERS:
@@ -3667,6 +3657,8 @@ static void handle_crq_init_rsp(struct w
 
 	netdev->real_num_tx_queues = adapter->req_tx_queues;
 	netdev->mtu = adapter->req_mtu;
+	netdev->min_mtu = adapter->min_mtu;
+	netdev->max_mtu = adapter->max_mtu;
 
 	if (adapter->failover) {
 		adapter->failover = false;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e1000/e1000_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -1085,6 +1085,10 @@ static int e1000_probe(struct pci_dev *p
 	    hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE)
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 
+	/* MTU range: 46 - 16110 */
+	netdev->min_mtu = ETH_ZLEN - ETH_HLEN;
+	netdev->max_mtu = MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
 	adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw);
 
 	/* initialize eeprom parameters */
@@ -3549,13 +3553,7 @@ static int e1000_change_mtu(struct net_d
 {
 	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;
-	}
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
 	/* Adapter-specific max frame size limits. */
 	switch (hw->mac_type) {
@@ -5257,8 +5255,8 @@ static void e1000_netpoll(struct net_dev
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
-	disable_irq(adapter->pdev->irq);
-	e1000_intr(adapter->pdev->irq, netdev);
+	if (disable_hardirq(adapter->pdev->irq))
+		e1000_intr(adapter->pdev->irq, netdev);
 	enable_irq(adapter->pdev->irq);
 }
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/e1000e/netdev.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e1000e/netdev.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/e1000e/netdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e1000e/netdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -4305,24 +4305,24 @@ void e1000e_reinit_locked(struct e1000_a
 /**
  * e1000e_sanitize_systim - sanitize raw cycle counter reads
  * @hw: pointer to the HW structure
- * @systim: cycle_t value read, sanitized and returned
+ * @systim: time value read, sanitized and returned
  *
  * Errata for 82574/82583 possible bad bits read from SYSTIMH/L:
  * check to see that the time is incrementing at a reasonable
  * rate and is a multiple of incvalue.
  **/
-static cycle_t e1000e_sanitize_systim(struct e1000_hw *hw, cycle_t systim)
+static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim)
 {
 	u64 time_delta, rem, temp;
-	cycle_t systim_next;
+	u64 systim_next;
 	u32 incvalue;
 	int i;
 
 	incvalue = er32(TIMINCA) & E1000_TIMINCA_INCVALUE_MASK;
 	for (i = 0; i < E1000_MAX_82574_SYSTIM_REREADS; i++) {
 		/* latch SYSTIMH on read of SYSTIML */
-		systim_next = (cycle_t)er32(SYSTIML);
-		systim_next |= (cycle_t)er32(SYSTIMH) << 32;
+		systim_next = (u64)er32(SYSTIML);
+		systim_next |= (u64)er32(SYSTIMH) << 32;
 
 		time_delta = systim_next - systim;
 		temp = time_delta;
@@ -4342,13 +4342,13 @@ static cycle_t e1000e_sanitize_systim(st
  * e1000e_cyclecounter_read - read raw cycle counter (used by time counter)
  * @cc: cyclecounter structure
  **/
-static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc)
+static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc)
 {
 	struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
 						     cc);
 	struct e1000_hw *hw = &adapter->hw;
 	u32 systimel, systimeh;
-	cycle_t systim;
+	u64 systim;
 	/* SYSTIMH latching upon SYSTIML read does not work well.
 	 * This means that if SYSTIML overflows after we read it but before
 	 * we read SYSTIMH, the value of SYSTIMH has been incremented and we
@@ -4368,8 +4368,8 @@ static cycle_t e1000e_cyclecounter_read(
 			systimel = systimel_2;
 		}
 	}
-	systim = (cycle_t)systimel;
-	systim |= (cycle_t)systimeh << 32;
+	systim = (u64)systimel;
+	systim |= (u64)systimeh << 32;
 
 	if (adapter->flags2 & FLAG2_CHECK_SYSTIM_OVERFLOW)
 		systim = e1000e_sanitize_systim(hw, systim);
@@ -5974,19 +5974,12 @@ static int e1000_change_mtu(struct net_d
 	int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
 
 	/* Jumbo frame support */
-	if ((max_frame > (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) &&
+	if ((new_mtu > ETH_DATA_LEN) &&
 	    !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) {
 		e_err("Jumbo Frames not supported.\n");
 		return -EINVAL;
 	}
 
-	/* Supported frame sizes */
-	if ((new_mtu < (VLAN_ETH_ZLEN + ETH_FCS_LEN)) ||
-	    (max_frame > adapter->max_hw_frame_size)) {
-		e_err("Unsupported MTU setting\n");
-		return -EINVAL;
-	}
-
 	/* Jumbo frame workaround on 82579 and newer requires CRC be stripped */
 	if ((adapter->hw.mac.type >= e1000_pch2lan) &&
 	    !(adapter->flags2 & FLAG2_CRC_STRIPPING) &&
@@ -6762,13 +6755,13 @@ static void e1000_netpoll(struct net_dev
 		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);
+		if (disable_hardirq(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);
+		if (disable_hardirq(adapter->pdev->irq))
+			e1000_intr(adapter->pdev->irq, netdev);
 		enable_irq(adapter->pdev->irq);
 		break;
 	}
@@ -7187,6 +7180,11 @@ static int e1000_probe(struct pci_dev *p
 		netdev->vlan_features |= NETIF_F_HIGHDMA;
 	}
 
+	/* MTU range: 68 - max_hw_frame_size */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = adapter->max_hw_frame_size -
+			  (VLAN_ETH_HLEN + ETH_FCS_LEN);
+
 	if (e1000e_enable_mng_pass_thru(&adapter->hw))
 		adapter->flags |= FLAG_MNG_PT_ENABLED;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/e1000e/ptp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e1000e/ptp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/e1000e/ptp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e1000e/ptp.c	2017-02-12 16:03:20.000000000 -0500
@@ -127,8 +127,8 @@ static int e1000e_phc_get_syncdevicetime
 	unsigned long flags;
 	int i;
 	u32 tsync_ctrl;
-	cycle_t dev_cycles;
-	cycle_t sys_cycles;
+	u64 dev_cycles;
+	u64 sys_cycles;
 
 	tsync_ctrl = er32(TSYNCTXCTL);
 	tsync_ctrl |= E1000_TSYNCTXCTL_START_SYNC |
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/e100.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e100.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/e100.c	2016-12-11 17:49:45.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/e100.c	2017-02-12 17:38:28.000000000 -0500
@@ -2285,14 +2285,6 @@ static int e100_set_mac_address(struct n
 	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 */
@@ -2833,7 +2825,6 @@ static const struct net_device_ops e100_
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_rx_mode	= 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
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -706,16 +706,6 @@ static netdev_tx_t fm10k_xmit_frame(stru
 	return err;
 }
 
-static int fm10k_change_mtu(struct net_device *dev, int new_mtu)
-{
-	if (new_mtu < 68 || new_mtu > FM10K_MAX_JUMBO_FRAME_SIZE)
-		return -EINVAL;
-
-	dev->mtu = new_mtu;
-
-	return 0;
-}
-
 /**
  * fm10k_tx_timeout - Respond to a Tx Hang
  * @netdev: network interface device structure
@@ -1405,7 +1395,6 @@ static const struct net_device_ops fm10k
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_start_xmit		= fm10k_xmit_frame,
 	.ndo_set_mac_address	= fm10k_set_mac,
-	.ndo_change_mtu		= fm10k_change_mtu,
 	.ndo_tx_timeout		= fm10k_tx_timeout,
 	.ndo_vlan_rx_add_vid	= fm10k_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= fm10k_vlan_rx_kill_vid,
@@ -1490,5 +1479,9 @@ struct net_device *fm10k_alloc_netdev(co
 
 	dev->hw_features |= hw_features;
 
+	/* MTU range: 68 - 15342 */
+	dev->min_mtu = ETH_MIN_MTU;
+	dev->max_mtu = FM10K_MAX_JUMBO_FRAME_SIZE;
+
 	return dev;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq.c	2017-02-12 16:03:20.000000000 -0500
@@ -964,11 +964,11 @@ i40e_status i40e_clean_arq_element(struc
 	desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
 	desc_idx = ntc;
 
+	hw->aq.arq_last_status =
+		(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
 	flags = le16_to_cpu(desc->flags);
 	if (flags & I40E_AQ_FLAG_ERR) {
 		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
-		hw->aq.arq_last_status =
-			(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
 		i40e_debug(hw,
 			   I40E_DEBUG_AQ_MESSAGE,
 			   "AQRX: Event received with error 0x%X.\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h	2017-02-12 16:03:20.000000000 -0500
@@ -1642,6 +1642,10 @@ enum i40e_aq_phy_type {
 	I40E_PHY_TYPE_1000BASE_LX		= 0x1C,
 	I40E_PHY_TYPE_1000BASE_T_OPTICAL	= 0x1D,
 	I40E_PHY_TYPE_20GBASE_KR2		= 0x1E,
+	I40E_PHY_TYPE_25GBASE_KR		= 0x1F,
+	I40E_PHY_TYPE_25GBASE_CR		= 0x20,
+	I40E_PHY_TYPE_25GBASE_SR		= 0x21,
+	I40E_PHY_TYPE_25GBASE_LR		= 0x22,
 	I40E_PHY_TYPE_MAX
 };
 
@@ -1650,6 +1654,7 @@ enum i40e_aq_phy_type {
 #define I40E_LINK_SPEED_10GB_SHIFT	0x3
 #define I40E_LINK_SPEED_40GB_SHIFT	0x4
 #define I40E_LINK_SPEED_20GB_SHIFT	0x5
+#define I40E_LINK_SPEED_25GB_SHIFT	0x6
 
 enum i40e_aq_link_speed {
 	I40E_LINK_SPEED_UNKNOWN	= 0,
@@ -1657,7 +1662,8 @@ enum i40e_aq_link_speed {
 	I40E_LINK_SPEED_1GB	= BIT(I40E_LINK_SPEED_1000MB_SHIFT),
 	I40E_LINK_SPEED_10GB	= BIT(I40E_LINK_SPEED_10GB_SHIFT),
 	I40E_LINK_SPEED_40GB	= BIT(I40E_LINK_SPEED_40GB_SHIFT),
-	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT)
+	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT),
+	I40E_LINK_SPEED_25GB	= BIT(I40E_LINK_SPEED_25GB_SHIFT),
 };
 
 struct i40e_aqc_module_desc {
@@ -1680,6 +1686,8 @@ struct i40e_aq_get_phy_abilities_resp {
 #define I40E_AQ_PHY_LINK_ENABLED	0x08
 #define I40E_AQ_PHY_AN_ENABLED		0x10
 #define I40E_AQ_PHY_FLAG_MODULE_QUAL	0x20
+#define I40E_AQ_PHY_FEC_ABILITY_KR	0x40
+#define I40E_AQ_PHY_FEC_ABILITY_RS	0x80
 	__le16	eee_capability;
 #define I40E_AQ_EEE_100BASE_TX		0x0002
 #define I40E_AQ_EEE_1000BASE_T		0x0004
@@ -1690,7 +1698,22 @@ struct i40e_aq_get_phy_abilities_resp {
 	__le32	eeer_val;
 	u8	d3_lpan;
 #define I40E_AQ_SET_PHY_D3_LPAN_ENA	0x01
-	u8	reserved[3];
+	u8	phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08
+	u8	fec_cfg_curr_mod_ext_info;
+#define I40E_AQ_ENABLE_FEC_KR		0x01
+#define I40E_AQ_ENABLE_FEC_RS		0x02
+#define I40E_AQ_REQUEST_FEC_KR		0x04
+#define I40E_AQ_REQUEST_FEC_RS		0x08
+#define I40E_AQ_ENABLE_FEC_AUTO		0x10
+#define I40E_AQ_FEC
+#define I40E_AQ_MODULE_TYPE_EXT_MASK	0xE0
+#define I40E_AQ_MODULE_TYPE_EXT_SHIFT	5
+
+	u8	ext_comp_code;
 	u8	phy_id[4];
 	u8	module_type[3];
 	u8	qualified_module_count;
@@ -1712,7 +1735,20 @@ struct i40e_aq_set_phy_config { /* same
 	__le16	eee_capability;
 	__le32	eeer;
 	u8	low_power_ctrl;
-	u8	reserved[3];
+	u8	phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08
+	u8	fec_config;
+#define I40E_AQ_SET_FEC_ABILITY_KR	BIT(0)
+#define I40E_AQ_SET_FEC_ABILITY_RS	BIT(1)
+#define I40E_AQ_SET_FEC_REQUEST_KR	BIT(2)
+#define I40E_AQ_SET_FEC_REQUEST_RS	BIT(3)
+#define I40E_AQ_SET_FEC_AUTO		BIT(4)
+#define I40E_AQ_PHY_FEC_CONFIG_SHIFT	0x0
+#define I40E_AQ_PHY_FEC_CONFIG_MASK	(0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
+	u8	reserved;
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1792,9 +1828,18 @@ struct i40e_aqc_get_link_status {
 #define I40E_AQ_LINK_TX_DRAINED		0x01
 #define I40E_AQ_LINK_TX_FLUSHED		0x03
 #define I40E_AQ_LINK_FORCED_40G		0x10
+/* 25G Error Codes */
+#define I40E_AQ_25G_NO_ERR		0X00
+#define I40E_AQ_25G_NOT_PRESENT		0X01
+#define I40E_AQ_25G_NVM_CRC_ERR		0X02
+#define I40E_AQ_25G_SBUS_UCODE_ERR	0X03
+#define I40E_AQ_25G_SERDES_UCODE_ERR	0X04
+#define I40E_AQ_25G_NIMB_UCODE_ERR	0X05
 	u8	loopback; /* use defines from i40e_aqc_set_lb_mode */
 	__le16	max_frame_size;
 	u8	config;
+#define I40E_AQ_CONFIG_FEC_KR_ENA	0x01
+#define I40E_AQ_CONFIG_FEC_RS_ENA	0x02
 #define I40E_AQ_CONFIG_CRC_ENA		0x04
 #define I40E_AQ_CONFIG_PACING_MASK	0x78
 	u8	external_power_ability;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_client.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_client.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_client.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_client.c	2017-02-12 16:03:20.000000000 -0500
@@ -287,6 +287,7 @@ void i40e_notify_client_of_netdev_close(
 			}
 			cdev->client->ops->close(&cdev->lan_info, cdev->client,
 						 reset);
+			clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
 			i40e_client_release_qvlist(&cdev->lan_info);
 		}
 	}
@@ -406,37 +407,6 @@ int i40e_vf_client_capable(struct i40e_p
 }
 
 /**
- * i40e_vsi_lookup - finds a matching VSI from the PF list starting at start_vsi
- * @pf: board private structure
- * @type: vsi type
- * @start_vsi: a VSI pointer from where to start the search
- *
- * Returns non NULL on success or NULL for failure
- **/
-struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf,
-				 enum i40e_vsi_type type,
-				 struct i40e_vsi *start_vsi)
-{
-	struct i40e_vsi *vsi;
-	int i = 0;
-
-	if (start_vsi) {
-		for (i = 0; i < pf->num_alloc_vsi; i++) {
-			vsi = pf->vsi[i];
-			if (vsi == start_vsi)
-				break;
-		}
-	}
-	for (; i < pf->num_alloc_vsi; i++) {
-		vsi = pf->vsi[i];
-		if (vsi && vsi->type == type)
-			return vsi;
-	}
-
-	return NULL;
-}
-
-/**
  * i40e_client_add_instance - add a client instance struct to the instance list
  * @pf: pointer to the board struct
  * @client: pointer to a client struct in the client list.
@@ -565,7 +535,7 @@ void i40e_client_subtask(struct i40e_pf
 			if (test_bit(__I40E_DOWN, &pf->vsi[pf->lan_vsi]->state))
 				continue;
 		} else {
-			dev_warn(&pf->pdev->dev, "This client %s is being instanciated at probe\n",
+			dev_warn(&pf->pdev->dev, "This client %s is being instantiated at probe\n",
 				 client->name);
 		}
 
@@ -575,29 +545,25 @@ void i40e_client_subtask(struct i40e_pf
 			continue;
 
 		if (!existing) {
-			/* Also up the ref_cnt for no. of instances of this
-			 * client.
-			 */
-			atomic_inc(&client->ref_cnt);
 			dev_info(&pf->pdev->dev, "Added instance of Client %s to PF%d bus=0x%02x func=0x%02x\n",
 				 client->name, pf->hw.pf_id,
 				 pf->hw.bus.device, pf->hw.bus.func);
 		}
 
 		mutex_lock(&i40e_client_instance_mutex);
-		/* Send an Open request to the client */
-		atomic_inc(&cdev->ref_cnt);
-		if (client->ops && client->ops->open)
-			ret = client->ops->open(&cdev->lan_info, client);
-		atomic_dec(&cdev->ref_cnt);
-		if (!ret) {
-			set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
-		} else {
-			/* remove client instance */
-			mutex_unlock(&i40e_client_instance_mutex);
-			i40e_client_del_instance(pf, client);
-			atomic_dec(&client->ref_cnt);
-			continue;
+		if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED,
+			      &cdev->state)) {
+			/* Send an Open request to the client */
+			if (client->ops && client->ops->open)
+				ret = client->ops->open(&cdev->lan_info,
+							client);
+			if (!ret) {
+				set_bit(__I40E_CLIENT_INSTANCE_OPENED,
+					&cdev->state);
+			} else {
+				/* remove client instance */
+				i40e_client_del_instance(pf, client);
+			}
 		}
 		mutex_unlock(&i40e_client_instance_mutex);
 	}
@@ -694,10 +660,6 @@ static int i40e_client_release(struct i4
 			continue;
 		pf = (struct i40e_pf *)cdev->lan_info.pf;
 		if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
-			if (atomic_read(&cdev->ref_cnt) > 0) {
-				ret = I40E_ERR_NOT_READY;
-				goto out;
-			}
 			if (client->ops && client->ops->close)
 				client->ops->close(&cdev->lan_info, client,
 						   false);
@@ -710,11 +672,9 @@ static int i40e_client_release(struct i4
 		}
 		/* delete the client instance from the list */
 		list_move(&cdev->list, &cdevs_tmp);
-		atomic_dec(&client->ref_cnt);
 		dev_info(&pf->pdev->dev, "Deleted client instance of Client %s\n",
 			 client->name);
 	}
-out:
 	mutex_unlock(&i40e_client_instance_mutex);
 
 	/* free the client device and release its vsi */
@@ -1040,17 +1000,10 @@ int i40e_unregister_client(struct i40e_c
 		ret = -ENODEV;
 		goto out;
 	}
-	if (atomic_read(&client->ref_cnt) == 0) {
-		clear_bit(__I40E_CLIENT_REGISTERED, &client->state);
-		list_del(&client->list);
-		pr_info("i40e: Unregistered client %s with return code %d\n",
-			client->name, ret);
-	} else {
-		ret = I40E_ERR_NOT_READY;
-		pr_err("i40e: Client %s failed unregister - client has open instances\n",
-		       client->name);
-	}
-
+	clear_bit(__I40E_CLIENT_REGISTERED, &client->state);
+	list_del(&client->list);
+	pr_info("i40e: Unregistered client %s with return code %d\n",
+		client->name, ret);
 out:
 	mutex_unlock(&i40e_client_mutex);
 	return ret;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_client.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_client.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_client.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_client.h	2017-02-12 16:03:20.000000000 -0500
@@ -203,8 +203,6 @@ struct i40e_client_instance {
 	struct i40e_info lan_info;
 	struct i40e_client *client;
 	unsigned long  state;
-	/* A count of all the in-progress calls to the client */
-	atomic_t ref_cnt;
 };
 
 struct i40e_client {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_common.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,6 +53,8 @@ static i40e_status i40e_set_mac_type(str
 		case I40E_DEV_ID_10G_BASE_T4:
 		case I40E_DEV_ID_20G_KR2:
 		case I40E_DEV_ID_20G_KR2_A:
+		case I40E_DEV_ID_25G_B:
+		case I40E_DEV_ID_25G_SFP28:
 			hw->mac.type = I40E_MAC_XL710;
 			break;
 		case I40E_DEV_ID_KX_X722:
@@ -1183,6 +1185,8 @@ static enum i40e_media_type i40e_get_med
 	case I40E_PHY_TYPE_1000BASE_LX:
 	case I40E_PHY_TYPE_40GBASE_SR4:
 	case I40E_PHY_TYPE_40GBASE_LR4:
+	case I40E_PHY_TYPE_25GBASE_LR:
+	case I40E_PHY_TYPE_25GBASE_SR:
 		media = I40E_MEDIA_TYPE_FIBER;
 		break;
 	case I40E_PHY_TYPE_100BASE_TX:
@@ -1197,6 +1201,7 @@ static enum i40e_media_type i40e_get_med
 	case I40E_PHY_TYPE_10GBASE_SFPP_CU:
 	case I40E_PHY_TYPE_40GBASE_AOC:
 	case I40E_PHY_TYPE_10GBASE_AOC:
+	case I40E_PHY_TYPE_25GBASE_CR:
 		media = I40E_MEDIA_TYPE_DA;
 		break;
 	case I40E_PHY_TYPE_1000BASE_KX:
@@ -1204,6 +1209,7 @@ static enum i40e_media_type i40e_get_med
 	case I40E_PHY_TYPE_10GBASE_KR:
 	case I40E_PHY_TYPE_40GBASE_KR4:
 	case I40E_PHY_TYPE_20GBASE_KR2:
+	case I40E_PHY_TYPE_25GBASE_KR:
 		media = I40E_MEDIA_TYPE_BACKPLANE;
 		break;
 	case I40E_PHY_TYPE_SGMII:
@@ -1608,8 +1614,10 @@ i40e_status i40e_aq_get_phy_capabilities
 	if (hw->aq.asq_last_status == I40E_AQ_RC_EIO)
 		status = I40E_ERR_UNKNOWN_PHY;
 
-	if (report_init)
+	if (report_init) {
 		hw->phy.phy_types = le32_to_cpu(abilities->phy_type);
+		hw->phy.phy_types |= ((u64)abilities->phy_type_ext << 32);
+	}
 
 	return status;
 }
@@ -1701,10 +1709,13 @@ enum i40e_status_code i40e_set_fc(struct
 			config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
 		/* Copy over all the old settings */
 		config.phy_type = abilities.phy_type;
+		config.phy_type_ext = abilities.phy_type_ext;
 		config.link_speed = abilities.link_speed;
 		config.eee_capability = abilities.eee_capability;
 		config.eeer = abilities.eeer_val;
 		config.low_power_ctrl = abilities.d3_lpan;
+		config.fec_config = abilities.fec_cfg_curr_mod_ext_info &
+				    I40E_AQ_PHY_FEC_CONFIG_MASK;
 		status = i40e_aq_set_phy_config(hw, &config, NULL);
 
 		if (status)
@@ -1849,12 +1860,13 @@ i40e_status i40e_aq_get_link_info(struct
 	else
 		hw_link_info->crc_enable = false;
 
-	if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE))
+	if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_IS_ENABLED))
 		hw_link_info->lse_enable = true;
 	else
 		hw_link_info->lse_enable = false;
 
-	if ((hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&
+	if ((hw->mac.type == I40E_MAC_XL710) &&
+	    (hw->aq.fw_maj_ver < 4 || (hw->aq.fw_maj_ver == 4 &&
 	     hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
 		hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
 
@@ -2169,6 +2181,40 @@ enum i40e_status_code i40e_aq_set_vsi_uc
 }
 
 /**
+ * i40e_aq_set_vsi_bc_promisc_on_vlan
+ * @hw: pointer to the hw struct
+ * @seid: vsi number
+ * @enable: set broadcast promiscuous enable/disable for a given VLAN
+ * @vid: The VLAN tag filter - capture any broadcast packet with this VLAN tag
+ * @cmd_details: pointer to command details structure or NULL
+ **/
+i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
+				u16 seid, bool enable, u16 vid,
+				struct i40e_asq_cmd_details *cmd_details)
+{
+	struct i40e_aq_desc desc;
+	struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
+		(struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
+	i40e_status status;
+	u16 flags = 0;
+
+	i40e_fill_default_direct_cmd_desc(&desc,
+					i40e_aqc_opc_set_vsi_promiscuous_modes);
+
+	if (enable)
+		flags |= I40E_AQC_SET_VSI_PROMISC_BROADCAST;
+
+	cmd->promiscuous_flags = cpu_to_le16(flags);
+	cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_BROADCAST);
+	cmd->seid = cpu_to_le16(seid);
+	cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
+
+	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
+
+	return status;
+}
+
+/**
  * i40e_aq_set_vsi_broadcast
  * @hw: pointer to the hw struct
  * @seid: vsi number
@@ -2494,7 +2540,10 @@ i40e_status i40e_update_link_info(struct
 	if (status)
 		return status;
 
-	if (hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) {
+	/* extra checking needed to ensure link info to user is timely */
+	if ((hw->phy.link_info.link_info & I40E_AQ_MEDIA_AVAILABLE) &&
+	    ((hw->phy.link_info.link_info & I40E_AQ_LINK_UP) ||
+	     !(hw->phy.link_info_old.link_info & I40E_AQ_LINK_UP))) {
 		status = i40e_aq_get_phy_capabilities(hw, false, false,
 						      &abilities, NULL);
 		if (status)
@@ -3144,6 +3193,14 @@ static void i40e_parse_discover_capabili
 			break;
 		case I40E_AQ_CAP_ID_MNG_MODE:
 			p->management_mode = number;
+			if (major_rev > 1) {
+				p->mng_protocols_over_mctp = logical_id;
+				i40e_debug(hw, I40E_DEBUG_INIT,
+					   "HW Capability: Protocols over MCTP = %d\n",
+					   p->mng_protocols_over_mctp);
+			} else {
+				p->mng_protocols_over_mctp = 0;
+			}
 			break;
 		case I40E_AQ_CAP_ID_NPAR_ACTIVE:
 			p->npar_enable = number;
@@ -3310,8 +3367,10 @@ static void i40e_parse_discover_capabili
 	/* partition id is 1-based, and functions are evenly spread
 	 * across the ports as partitions
 	 */
-	hw->partition_id = (hw->pf_id / hw->num_ports) + 1;
-	hw->num_partitions = num_functions / hw->num_ports;
+	if (hw->num_ports != 0) {
+		hw->partition_id = (hw->pf_id / hw->num_ports) + 1;
+		hw->num_partitions = num_functions / hw->num_ports;
+	}
 
 	/* additional HW specific goodies that might
 	 * someday be HW version specific
@@ -4391,7 +4450,92 @@ i40e_status i40e_aq_configure_partition_
 }
 
 /**
- * i40e_read_phy_register
+ * i40e_read_phy_register_clause22
+ * @hw: pointer to the HW structure
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
+					    u16 reg, u8 phy_addr, u16 *value)
+{
+	i40e_status status = I40E_ERR_TIMEOUT;
+	u8 port_num = (u8)hw->func_caps.mdio_port_num;
+	u32 command = 0;
+	u16 retry = 1000;
+
+	command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
+		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
+		  (I40E_MDIO_CLAUSE22_OPCODE_READ_MASK) |
+		  (I40E_MDIO_CLAUSE22_STCODE_MASK) |
+		  (I40E_GLGEN_MSCA_MDICMD_MASK);
+	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
+	do {
+		command = rd32(hw, I40E_GLGEN_MSCA(port_num));
+		if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
+			status = 0;
+			break;
+		}
+		udelay(10);
+		retry--;
+	} while (retry);
+
+	if (status) {
+		i40e_debug(hw, I40E_DEBUG_PHY,
+			   "PHY: Can't write command to external PHY.\n");
+	} else {
+		command = rd32(hw, I40E_GLGEN_MSRWD(port_num));
+		*value = (command & I40E_GLGEN_MSRWD_MDIRDDATA_MASK) >>
+			 I40E_GLGEN_MSRWD_MDIRDDATA_SHIFT;
+	}
+
+	return status;
+}
+
+/**
+ * i40e_write_phy_register_clause22
+ * @hw: pointer to the HW structure
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes specified PHY register value
+ **/
+i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
+					     u16 reg, u8 phy_addr, u16 value)
+{
+	i40e_status status = I40E_ERR_TIMEOUT;
+	u8 port_num = (u8)hw->func_caps.mdio_port_num;
+	u32 command  = 0;
+	u16 retry = 1000;
+
+	command = value << I40E_GLGEN_MSRWD_MDIWRDATA_SHIFT;
+	wr32(hw, I40E_GLGEN_MSRWD(port_num), command);
+
+	command = (reg << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
+		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
+		  (I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK) |
+		  (I40E_MDIO_CLAUSE22_STCODE_MASK) |
+		  (I40E_GLGEN_MSCA_MDICMD_MASK);
+
+	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
+	do {
+		command = rd32(hw, I40E_GLGEN_MSCA(port_num));
+		if (!(command & I40E_GLGEN_MSCA_MDICMD_MASK)) {
+			status = 0;
+			break;
+		}
+		udelay(10);
+		retry--;
+	} while (retry);
+
+	return status;
+}
+
+/**
+ * i40e_read_phy_register_clause45
  * @hw: pointer to the HW structure
  * @page: registers page number
  * @reg: register address in the page
@@ -4400,9 +4544,8 @@ i40e_status i40e_aq_configure_partition_
  *
  * Reads specified PHY register value
  **/
-i40e_status i40e_read_phy_register(struct i40e_hw *hw,
-				   u8 page, u16 reg, u8 phy_addr,
-				   u16 *value)
+i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 *value)
 {
 	i40e_status status = I40E_ERR_TIMEOUT;
 	u32 command = 0;
@@ -4412,8 +4555,8 @@ i40e_status i40e_read_phy_register(struc
 	command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
 		  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_ADDRESS) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -4435,8 +4578,8 @@ i40e_status i40e_read_phy_register(struc
 
 	command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_READ) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_READ_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	status = I40E_ERR_TIMEOUT;
@@ -4466,7 +4609,7 @@ phy_read_end:
 }
 
 /**
- * i40e_write_phy_register
+ * i40e_write_phy_register_clause45
  * @hw: pointer to the HW structure
  * @page: registers page number
  * @reg: register address in the page
@@ -4475,9 +4618,8 @@ phy_read_end:
  *
  * Writes value to specified PHY register
  **/
-i40e_status i40e_write_phy_register(struct i40e_hw *hw,
-				    u8 page, u16 reg, u8 phy_addr,
-				    u16 value)
+i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 value)
 {
 	i40e_status status = I40E_ERR_TIMEOUT;
 	u32 command = 0;
@@ -4487,8 +4629,8 @@ i40e_status i40e_write_phy_register(stru
 	command = (reg << I40E_GLGEN_MSCA_MDIADD_SHIFT) |
 		  (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_ADDRESS) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	wr32(hw, I40E_GLGEN_MSCA(port_num), command);
@@ -4512,8 +4654,8 @@ i40e_status i40e_write_phy_register(stru
 
 	command = (page << I40E_GLGEN_MSCA_DEVADD_SHIFT) |
 		  (phy_addr << I40E_GLGEN_MSCA_PHYADD_SHIFT) |
-		  (I40E_MDIO_OPCODE_WRITE) |
-		  (I40E_MDIO_STCODE) |
+		  (I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK) |
+		  (I40E_MDIO_CLAUSE45_STCODE_MASK) |
 		  (I40E_GLGEN_MSCA_MDICMD_MASK) |
 		  (I40E_GLGEN_MSCA_MDIINPROGEN_MASK);
 	status = I40E_ERR_TIMEOUT;
@@ -4534,6 +4676,78 @@ phy_write_end:
 }
 
 /**
+ * i40e_write_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes value to specified PHY register
+ **/
+i40e_status i40e_write_phy_register(struct i40e_hw *hw,
+				    u8 page, u16 reg, u8 phy_addr, u16 value)
+{
+	i40e_status status;
+
+	switch (hw->device_id) {
+	case I40E_DEV_ID_1G_BASE_T_X722:
+		status = i40e_write_phy_register_clause22(hw, reg, phy_addr,
+							  value);
+		break;
+	case I40E_DEV_ID_10G_BASE_T:
+	case I40E_DEV_ID_10G_BASE_T4:
+	case I40E_DEV_ID_10G_BASE_T_X722:
+	case I40E_DEV_ID_25G_B:
+	case I40E_DEV_ID_25G_SFP28:
+		status = i40e_write_phy_register_clause45(hw, page, reg,
+							  phy_addr, value);
+		break;
+	default:
+		status = I40E_ERR_UNKNOWN_PHY;
+		break;
+	}
+
+	return status;
+}
+
+/**
+ * i40e_read_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+i40e_status i40e_read_phy_register(struct i40e_hw *hw,
+				   u8 page, u16 reg, u8 phy_addr, u16 *value)
+{
+	i40e_status status;
+
+	switch (hw->device_id) {
+	case I40E_DEV_ID_1G_BASE_T_X722:
+		status = i40e_read_phy_register_clause22(hw, reg, phy_addr,
+							 value);
+		break;
+	case I40E_DEV_ID_10G_BASE_T:
+	case I40E_DEV_ID_10G_BASE_T4:
+	case I40E_DEV_ID_10G_BASE_T_X722:
+	case I40E_DEV_ID_25G_B:
+	case I40E_DEV_ID_25G_SFP28:
+		status = i40e_read_phy_register_clause45(hw, page, reg,
+							 phy_addr, value);
+		break;
+	default:
+		status = I40E_ERR_UNKNOWN_PHY;
+		break;
+	}
+
+	return status;
+}
+
+/**
  * i40e_get_phy_address
  * @hw: pointer to the HW structure
  * @dev_num: PHY port num that address we want
@@ -4575,14 +4789,16 @@ i40e_status i40e_blink_phy_link_led(stru
 
 	for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
 	     led_addr++) {
-		status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-						led_addr, phy_addr, &led_reg);
+		status = i40e_read_phy_register_clause45(hw,
+							 I40E_PHY_COM_REG_PAGE,
+							 led_addr, phy_addr,
+							 &led_reg);
 		if (status)
 			goto phy_blinking_end;
 		led_ctl = led_reg;
 		if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
 			led_reg = 0;
-			status = i40e_write_phy_register(hw,
+			status = i40e_write_phy_register_clause45(hw,
 							 I40E_PHY_COM_REG_PAGE,
 							 led_addr, phy_addr,
 							 led_reg);
@@ -4594,20 +4810,18 @@ i40e_status i40e_blink_phy_link_led(stru
 
 	if (time > 0 && interval > 0) {
 		for (i = 0; i < time * 1000; i += interval) {
-			status = i40e_read_phy_register(hw,
-							I40E_PHY_COM_REG_PAGE,
-							led_addr, phy_addr,
-							&led_reg);
+			status = i40e_read_phy_register_clause45(hw,
+						I40E_PHY_COM_REG_PAGE,
+						led_addr, phy_addr, &led_reg);
 			if (status)
 				goto restore_config;
 			if (led_reg & I40E_PHY_LED_MANUAL_ON)
 				led_reg = 0;
 			else
 				led_reg = I40E_PHY_LED_MANUAL_ON;
-			status = i40e_write_phy_register(hw,
-							 I40E_PHY_COM_REG_PAGE,
-							 led_addr, phy_addr,
-							 led_reg);
+			status = i40e_write_phy_register_clause45(hw,
+						I40E_PHY_COM_REG_PAGE,
+						led_addr, phy_addr, led_reg);
 			if (status)
 				goto restore_config;
 			msleep(interval);
@@ -4615,8 +4829,9 @@ i40e_status i40e_blink_phy_link_led(stru
 	}
 
 restore_config:
-	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-					 phy_addr, led_ctl);
+	status = i40e_write_phy_register_clause45(hw,
+						  I40E_PHY_COM_REG_PAGE,
+						  led_addr, phy_addr, led_ctl);
 
 phy_blinking_end:
 	return status;
@@ -4647,8 +4862,10 @@ i40e_status i40e_led_get_phy(struct i40e
 
 	for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
 	     temp_addr++) {
-		status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-						temp_addr, phy_addr, &reg_val);
+		status = i40e_read_phy_register_clause45(hw,
+							 I40E_PHY_COM_REG_PAGE,
+							 temp_addr, phy_addr,
+							 &reg_val);
 		if (status)
 			return status;
 		*val = reg_val;
@@ -4681,41 +4898,42 @@ i40e_status i40e_led_set_phy(struct i40e
 	i = rd32(hw, I40E_PFGEN_PORTNUM);
 	port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
 	phy_addr = i40e_get_phy_address(hw, port_num);
-
-	status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-					phy_addr, &led_reg);
+	status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						 led_addr, phy_addr, &led_reg);
 	if (status)
 		return status;
 	led_ctl = led_reg;
 	if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
 		led_reg = 0;
-		status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-						 led_addr, phy_addr, led_reg);
+		status = i40e_write_phy_register_clause45(hw,
+							  I40E_PHY_COM_REG_PAGE,
+							  led_addr, phy_addr,
+							  led_reg);
 		if (status)
 			return status;
 	}
-	status = i40e_read_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-					led_addr, phy_addr, &led_reg);
+	status = i40e_read_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						 led_addr, phy_addr, &led_reg);
 	if (status)
 		goto restore_config;
 	if (on)
 		led_reg = I40E_PHY_LED_MANUAL_ON;
 	else
 		led_reg = 0;
-	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE,
-					 led_addr, phy_addr, led_reg);
+	status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						  led_addr, phy_addr, led_reg);
 	if (status)
 		goto restore_config;
 	if (mode & I40E_PHY_LED_MODE_ORIG) {
 		led_ctl = (mode & I40E_PHY_LED_MODE_MASK);
-		status = i40e_write_phy_register(hw,
+		status = i40e_write_phy_register_clause45(hw,
 						 I40E_PHY_COM_REG_PAGE,
 						 led_addr, phy_addr, led_ctl);
 	}
 	return status;
 restore_config:
-	status = i40e_write_phy_register(hw, I40E_PHY_COM_REG_PAGE, led_addr,
-					 phy_addr, led_ctl);
+	status = i40e_write_phy_register_clause45(hw, I40E_PHY_COM_REG_PAGE,
+						  led_addr, phy_addr, led_ctl);
 	return status;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_debugfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -134,7 +134,7 @@ static void i40e_dbg_dump_vsi_seid(struc
 	struct rtnl_link_stats64 *nstat;
 	struct i40e_mac_filter *f;
 	struct i40e_vsi *vsi;
-	int i;
+	int i, bkt;
 
 	vsi = i40e_dbg_find_vsi(pf, seid);
 	if (!vsi) {
@@ -166,13 +166,13 @@ static void i40e_dbg_dump_vsi_seid(struc
 			 pf->hw.mac.addr,
 			 pf->hw.mac.san_addr,
 			 pf->hw.mac.port_addr);
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
+	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
 		dev_info(&pf->pdev->dev,
-			 "    mac_filter_list: %pM vid=%d, is_netdev=%d is_vf=%d counter=%d, state %s\n",
-			 f->macaddr, f->vlan, f->is_netdev, f->is_vf,
-			 f->counter, i40e_filter_state_string[f->state]);
+			 "    mac_filter_hash: %pM vid=%d, state %s\n",
+			 f->macaddr, f->vlan,
+			 i40e_filter_state_string[f->state]);
 	}
-	dev_info(&pf->pdev->dev, "    active_filters %d, promisc_threshold %d, overflow promisc %s\n",
+	dev_info(&pf->pdev->dev, "    active_filters %u, promisc_threshold %u, overflow promisc %s\n",
 		 vsi->active_filters, vsi->promisc_threshold,
 		 (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) ?
 		  "ON" : "OFF"));
@@ -867,86 +867,6 @@ static ssize_t i40e_dbg_command_write(st
 
 		dev_info(&pf->pdev->dev, "deleting relay %d\n", veb_seid);
 		i40e_veb_release(pf->veb[i]);
-
-	} else if (strncmp(cmd_buf, "add macaddr", 11) == 0) {
-		struct i40e_mac_filter *f;
-		int vlan = 0;
-		u8 ma[6];
-		int ret;
-
-		cnt = sscanf(&cmd_buf[11],
-			     "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i",
-			     &vsi_seid,
-			     &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5],
-			     &vlan);
-		if (cnt == 7) {
-			vlan = 0;
-		} else if (cnt != 8) {
-			dev_info(&pf->pdev->dev,
-				 "add macaddr: bad command string, cnt=%d\n",
-				 cnt);
-			goto command_write_done;
-		}
-
-		vsi = i40e_dbg_find_vsi(pf, vsi_seid);
-		if (!vsi) {
-			dev_info(&pf->pdev->dev,
-				 "add macaddr: VSI %d not found\n", vsi_seid);
-			goto command_write_done;
-		}
-
-		spin_lock_bh(&vsi->mac_filter_list_lock);
-		f = i40e_add_filter(vsi, ma, vlan, false, false);
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
-		ret = i40e_sync_vsi_filters(vsi);
-		if (f && !ret)
-			dev_info(&pf->pdev->dev,
-				 "add macaddr: %pM vlan=%d added to VSI %d\n",
-				 ma, vlan, vsi_seid);
-		else
-			dev_info(&pf->pdev->dev,
-				 "add macaddr: %pM vlan=%d to VSI %d failed, f=%p ret=%d\n",
-				 ma, vlan, vsi_seid, f, ret);
-
-	} else if (strncmp(cmd_buf, "del macaddr", 11) == 0) {
-		int vlan = 0;
-		u8 ma[6];
-		int ret;
-
-		cnt = sscanf(&cmd_buf[11],
-			     "%i %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %i",
-			     &vsi_seid,
-			     &ma[0], &ma[1], &ma[2], &ma[3], &ma[4], &ma[5],
-			     &vlan);
-		if (cnt == 7) {
-			vlan = 0;
-		} else if (cnt != 8) {
-			dev_info(&pf->pdev->dev,
-				 "del macaddr: bad command string, cnt=%d\n",
-				 cnt);
-			goto command_write_done;
-		}
-
-		vsi = i40e_dbg_find_vsi(pf, vsi_seid);
-		if (!vsi) {
-			dev_info(&pf->pdev->dev,
-				 "del macaddr: VSI %d not found\n", vsi_seid);
-			goto command_write_done;
-		}
-
-		spin_lock_bh(&vsi->mac_filter_list_lock);
-		i40e_del_filter(vsi, ma, vlan, false, false);
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
-		ret = i40e_sync_vsi_filters(vsi);
-		if (!ret)
-			dev_info(&pf->pdev->dev,
-				 "del macaddr: %pM vlan=%d removed from VSI %d\n",
-				 ma, vlan, vsi_seid);
-		else
-			dev_info(&pf->pdev->dev,
-				 "del macaddr: %pM vlan=%d from VSI %d failed, ret=%d\n",
-				 ma, vlan, vsi_seid, ret);
-
 	} else if (strncmp(cmd_buf, "add pvid", 8) == 0) {
 		i40e_status ret;
 		u16 vid;
@@ -1210,24 +1130,6 @@ static ssize_t i40e_dbg_command_write(st
 			dev_info(&pf->pdev->dev,
 				 "dump debug fwdata <cluster_id> <table_id> <index>\n");
 		}
-
-	} else if (strncmp(cmd_buf, "msg_enable", 10) == 0) {
-		u32 level;
-		cnt = sscanf(&cmd_buf[10], "%i", &level);
-		if (cnt) {
-			if (I40E_DEBUG_USER & level) {
-				pf->hw.debug_mask = level;
-				dev_info(&pf->pdev->dev,
-					 "set hw.debug_mask = 0x%08x\n",
-					 pf->hw.debug_mask);
-			}
-			pf->msg_enable = level;
-			dev_info(&pf->pdev->dev, "set msg_enable = 0x%08x\n",
-				 pf->msg_enable);
-		} else {
-			dev_info(&pf->pdev->dev, "msg_enable = 0x%08x\n",
-				 pf->msg_enable);
-		}
 	} else if (strncmp(cmd_buf, "pfr", 3) == 0) {
 		dev_info(&pf->pdev->dev, "debugfs: forcing PFR\n");
 		i40e_do_reset_safe(pf, BIT(__I40E_PF_RESET_REQUESTED));
@@ -1633,8 +1535,6 @@ static ssize_t i40e_dbg_command_write(st
 		dev_info(&pf->pdev->dev, "  del vsi [vsi_seid]\n");
 		dev_info(&pf->pdev->dev, "  add relay <uplink_seid> <vsi_seid>\n");
 		dev_info(&pf->pdev->dev, "  del relay <relay_seid>\n");
-		dev_info(&pf->pdev->dev, "  add macaddr <vsi_seid> <aa:bb:cc:dd:ee:ff> [vlan]\n");
-		dev_info(&pf->pdev->dev, "  del macaddr <vsi_seid> <aa:bb:cc:dd:ee:ff> [vlan]\n");
 		dev_info(&pf->pdev->dev, "  add pvid <vsi_seid> <vid>\n");
 		dev_info(&pf->pdev->dev, "  del pvid <vsi_seid>\n");
 		dev_info(&pf->pdev->dev, "  dump switch\n");
@@ -1644,7 +1544,6 @@ static ssize_t i40e_dbg_command_write(st
 		dev_info(&pf->pdev->dev, "  dump desc aq\n");
 		dev_info(&pf->pdev->dev, "  dump reset stats\n");
 		dev_info(&pf->pdev->dev, "  dump debug fwdata <cluster_id> <table_id> <index>\n");
-		dev_info(&pf->pdev->dev, "  msg_enable [level]\n");
 		dev_info(&pf->pdev->dev, "  read <reg>\n");
 		dev_info(&pf->pdev->dev, "  write <reg> <value>\n");
 		dev_info(&pf->pdev->dev, "  clear_stats vsi [seid]\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_devids.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_devids.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_devids.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_devids.h	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,8 @@
 #define I40E_DEV_ID_20G_KR2		0x1587
 #define I40E_DEV_ID_20G_KR2_A		0x1588
 #define I40E_DEV_ID_10G_BASE_T4		0x1589
+#define I40E_DEV_ID_25G_B		0x158A
+#define I40E_DEV_ID_25G_SFP28		0x158B
 #define I40E_DEV_ID_KX_X722		0x37CE
 #define I40E_DEV_ID_QSFP_X722		0x37CF
 #define I40E_DEV_ID_SFP_X722		0x37D0
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -104,7 +104,7 @@ static const struct i40e_stats i40e_gstr
  * The PF_STATs are appended to the netdev stats only when ethtool -S
  * is queried on the base PF netdev, not on the VMDq or FCoE netdev.
  */
-static struct i40e_stats i40e_gstrings_stats[] = {
+static const struct i40e_stats i40e_gstrings_stats[] = {
 	I40E_PF_STAT("rx_bytes", stats.eth.rx_bytes),
 	I40E_PF_STAT("tx_bytes", stats.eth.tx_bytes),
 	I40E_PF_STAT("rx_unicast", stats.eth.rx_unicast),
@@ -216,7 +216,6 @@ enum i40e_ethtool_test_id {
 	I40E_ETH_TEST_REG = 0,
 	I40E_ETH_TEST_EEPROM,
 	I40E_ETH_TEST_INTR,
-	I40E_ETH_TEST_LOOPBACK,
 	I40E_ETH_TEST_LINK,
 };
 
@@ -224,32 +223,27 @@ static const char i40e_gstrings_test[][E
 	"Register test  (offline)",
 	"Eeprom test    (offline)",
 	"Interrupt test (offline)",
-	"Loopback test  (offline)",
 	"Link test   (on/offline)"
 };
 
 #define I40E_TEST_LEN (sizeof(i40e_gstrings_test) / ETH_GSTRING_LEN)
 
-static const char i40e_priv_flags_strings_gl[][ETH_GSTRING_LEN] = {
+static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
 	"MFP",
 	"LinkPolling",
 	"flow-director-atr",
 	"veb-stats",
 	"hw-atr-eviction",
-	"vf-true-promisc-support",
 };
 
-#define I40E_PRIV_FLAGS_GL_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings_gl)
+#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
 
-static const char i40e_priv_flags_strings[][ETH_GSTRING_LEN] = {
-	"NPAR",
-	"LinkPolling",
-	"flow-director-atr",
-	"veb-stats",
-	"hw-atr-eviction",
+/* Private flags with a global effect, restricted to PF 0 */
+static const char i40e_gl_priv_flags_strings[][ETH_GSTRING_LEN] = {
+	"vf-true-promisc-support",
 };
 
-#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_priv_flags_strings)
+#define I40E_GL_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gl_priv_flags_strings)
 
 /**
  * i40e_partition_setting_complaint - generic complaint for MFP restriction
@@ -271,8 +265,9 @@ static void i40e_partition_setting_compl
 static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
 				     u32 *advertising)
 {
-	enum i40e_aq_capabilities_phy_type phy_types = pf->hw.phy.phy_types;
 	struct i40e_link_status *hw_link_info = &pf->hw.phy.link_info;
+	u64 phy_types = pf->hw.phy.phy_types;
+
 	*supported = 0x0;
 	*advertising = 0x0;
 
@@ -351,11 +346,13 @@ static void i40e_phy_type_to_ethtool(str
 			*advertising |= ADVERTISED_20000baseKR2_Full;
 	}
 	if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) {
-		*supported |= SUPPORTED_10000baseKR_Full |
-			      SUPPORTED_Autoneg;
+		if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+			*supported |= SUPPORTED_10000baseKR_Full |
+				      SUPPORTED_Autoneg;
 		*advertising |= ADVERTISED_Autoneg;
 		if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB)
-			*advertising |= ADVERTISED_10000baseKR_Full;
+			if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+				*advertising |= ADVERTISED_10000baseKR_Full;
 	}
 	if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) {
 		*supported |= SUPPORTED_10000baseKX4_Full |
@@ -365,11 +362,20 @@ static void i40e_phy_type_to_ethtool(str
 			*advertising |= ADVERTISED_10000baseKX4_Full;
 	}
 	if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) {
-		*supported |= SUPPORTED_1000baseKX_Full |
-			      SUPPORTED_Autoneg;
+		if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+			*supported |= SUPPORTED_1000baseKX_Full |
+				      SUPPORTED_Autoneg;
 		*advertising |= ADVERTISED_Autoneg;
 		if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB)
-			*advertising |= ADVERTISED_1000baseKX_Full;
+			if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
+				*advertising |= ADVERTISED_1000baseKX_Full;
+	}
+	if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR ||
+	    phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR ||
+	    phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR ||
+	    phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR) {
+		*supported |= SUPPORTED_Autoneg;
+		*advertising |= ADVERTISED_Autoneg;
 	}
 }
 
@@ -493,6 +499,14 @@ static void i40e_get_settings_link_up(st
 				     ADVERTISED_1000baseKX_Full |
 				     ADVERTISED_Autoneg;
 		break;
+	case I40E_PHY_TYPE_25GBASE_KR:
+	case I40E_PHY_TYPE_25GBASE_CR:
+	case I40E_PHY_TYPE_25GBASE_SR:
+	case I40E_PHY_TYPE_25GBASE_LR:
+		ecmd->supported = SUPPORTED_Autoneg;
+		ecmd->advertising = ADVERTISED_Autoneg;
+		/* TODO: add speeds when ethtool is ready to support*/
+		break;
 	default:
 		/* if we got here and link is up something bad is afoot */
 		netdev_info(netdev, "WARNING: Link is up but PHY type 0x%x is not recognized.\n",
@@ -514,6 +528,14 @@ static void i40e_get_settings_link_up(st
 	case I40E_LINK_SPEED_40GB:
 		ethtool_cmd_speed_set(ecmd, SPEED_40000);
 		break;
+	case I40E_LINK_SPEED_25GB:
+#ifdef SPEED_25000
+		ethtool_cmd_speed_set(ecmd, SPEED_25000);
+#else
+		netdev_info(netdev,
+			    "Speed is 25G, display not supported by this version of ethtool.\n");
+#endif
+		break;
 	case I40E_LINK_SPEED_20GB:
 		ethtool_cmd_speed_set(ecmd, SPEED_20000);
 		break;
@@ -978,6 +1000,10 @@ static u32 i40e_get_msglevel(struct net_
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_pf *pf = np->vsi->back;
+	u32 debug_mask = pf->hw.debug_mask;
+
+	if (debug_mask)
+		netdev_info(netdev, "i40e debug_mask: 0x%08X\n", debug_mask);
 
 	return pf->msg_enable;
 }
@@ -989,7 +1015,8 @@ static void i40e_set_msglevel(struct net
 
 	if (I40E_DEBUG_USER & data)
 		pf->hw.debug_mask = data;
-	pf->msg_enable = data;
+	else
+		pf->msg_enable = data;
 }
 
 static int i40e_get_regs_len(struct net_device *netdev)
@@ -1191,10 +1218,9 @@ static void i40e_get_drvinfo(struct net_
 		sizeof(drvinfo->fw_version));
 	strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
 		sizeof(drvinfo->bus_info));
+	drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;
 	if (pf->hw.pf_id == 0)
-		drvinfo->n_priv_flags = I40E_PRIV_FLAGS_GL_STR_LEN;
-	else
-		drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;
+		drvinfo->n_priv_flags += I40E_GL_PRIV_FLAGS_STR_LEN;
 }
 
 static void i40e_get_ringparam(struct net_device *netdev,
@@ -1219,6 +1245,7 @@ static int i40e_set_ringparam(struct net
 {
 	struct i40e_ring *tx_rings = NULL, *rx_rings = NULL;
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_hw *hw = &np->vsi->back->hw;
 	struct i40e_vsi *vsi = np->vsi;
 	struct i40e_pf *pf = vsi->back;
 	u32 new_rx_count, new_tx_count;
@@ -1311,10 +1338,6 @@ static int i40e_set_ringparam(struct net
 		}
 
 		for (i = 0; i < vsi->num_queue_pairs; i++) {
-			/* this is to allow wr32 to have something to write to
-			 * during early allocation of Rx buffers
-			 */
-			u32 __iomem faketail = 0;
 			struct i40e_ring *ring;
 			u16 unused;
 
@@ -1326,7 +1349,10 @@ static int i40e_set_ringparam(struct net
 			 */
 			rx_rings[i].desc = NULL;
 			rx_rings[i].rx_bi = NULL;
-			rx_rings[i].tail = (u8 __iomem *)&faketail;
+			/* this is to allow wr32 to have something to write to
+			 * during early allocation of Rx buffers
+			 */
+			rx_rings[i].tail = hw->hw_addr + I40E_PRTGEN_STATUS;
 			err = i40e_setup_rx_descriptors(&rx_rings[i]);
 			if (err)
 				goto rx_unwind;
@@ -1422,10 +1448,8 @@ static int i40e_get_sset_count(struct ne
 			return I40E_VSI_STATS_LEN(netdev);
 		}
 	case ETH_SS_PRIV_FLAGS:
-		if (pf->hw.pf_id == 0)
-			return I40E_PRIV_FLAGS_GL_STR_LEN;
-		else
-			return I40E_PRIV_FLAGS_STR_LEN;
+		return I40E_PRIV_FLAGS_STR_LEN +
+			(pf->hw.pf_id == 0 ? I40E_GL_PRIV_FLAGS_STR_LEN : 0);
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -1536,10 +1560,8 @@ static void i40e_get_strings(struct net_
 
 	switch (stringset) {
 	case ETH_SS_TEST:
-		for (i = 0; i < I40E_TEST_LEN; i++) {
-			memcpy(data, i40e_gstrings_test[i], ETH_GSTRING_LEN);
-			data += ETH_GSTRING_LEN;
-		}
+		memcpy(data, i40e_gstrings_test,
+		       I40E_TEST_LEN * ETH_GSTRING_LEN);
 		break;
 	case ETH_SS_STATS:
 		for (i = 0; i < I40E_NETDEV_STATS_LEN; i++) {
@@ -1623,19 +1645,12 @@ static void i40e_get_strings(struct net_
 		/* BUG_ON(p - data != I40E_STATS_LEN * ETH_GSTRING_LEN); */
 		break;
 	case ETH_SS_PRIV_FLAGS:
-		if (pf->hw.pf_id == 0) {
-			for (i = 0; i < I40E_PRIV_FLAGS_GL_STR_LEN; i++) {
-				memcpy(data, i40e_priv_flags_strings_gl[i],
-				       ETH_GSTRING_LEN);
-				data += ETH_GSTRING_LEN;
-			}
-		} else {
-			for (i = 0; i < I40E_PRIV_FLAGS_STR_LEN; i++) {
-				memcpy(data, i40e_priv_flags_strings[i],
-				       ETH_GSTRING_LEN);
-				data += ETH_GSTRING_LEN;
-			}
-		}
+		memcpy(data, i40e_priv_flags_strings,
+		       I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
+		data += I40E_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN;
+		if (pf->hw.pf_id == 0)
+			memcpy(data, i40e_gl_priv_flags_strings,
+			       I40E_GL_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
 		break;
 	default:
 		break;
@@ -1666,8 +1681,19 @@ static int i40e_get_ts_info(struct net_d
 	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
 
 	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
-			   BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
-			   BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
+			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ);
+
+	if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE)
+		info->rx_filters |= BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
+				    BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
+				    BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
+				    BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+				    BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) |
+				    BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
+				    BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) |
+				    BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);
 
 	return 0;
 }
@@ -1739,17 +1765,6 @@ static int i40e_intr_test(struct net_dev
 	return *data;
 }
 
-static int i40e_loopback_test(struct net_device *netdev, u64 *data)
-{
-	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_pf *pf = np->vsi->back;
-
-	netif_info(pf, hw, netdev, "loopback test not implemented\n");
-	*data = 0;
-
-	return *data;
-}
-
 static inline bool i40e_active_vfs(struct i40e_pf *pf)
 {
 	struct i40e_vf *vfs = pf->vf;
@@ -1763,17 +1778,7 @@ static inline bool i40e_active_vfs(struc
 
 static inline bool i40e_active_vmdqs(struct i40e_pf *pf)
 {
-	struct i40e_vsi **vsi = pf->vsi;
-	int i;
-
-	for (i = 0; i < pf->num_alloc_vsi; i++) {
-		if (!vsi[i])
-			continue;
-		if (vsi[i]->type == I40E_VSI_VMDQ2)
-			return true;
-	}
-
-	return false;
+	return !!i40e_find_vsi_by_type(pf, I40E_VSI_VMDQ2);
 }
 
 static void i40e_diag_test(struct net_device *netdev,
@@ -1795,7 +1800,6 @@ static void i40e_diag_test(struct net_de
 			data[I40E_ETH_TEST_REG]		= 1;
 			data[I40E_ETH_TEST_EEPROM]	= 1;
 			data[I40E_ETH_TEST_INTR]	= 1;
-			data[I40E_ETH_TEST_LOOPBACK]	= 1;
 			data[I40E_ETH_TEST_LINK]	= 1;
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 			clear_bit(__I40E_TESTING, &pf->state);
@@ -1823,9 +1827,6 @@ static void i40e_diag_test(struct net_de
 		if (i40e_intr_test(netdev, &data[I40E_ETH_TEST_INTR]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
 
-		if (i40e_loopback_test(netdev, &data[I40E_ETH_TEST_LOOPBACK]))
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-
 		/* run reg test last, a reset is required after it */
 		if (i40e_reg_test(netdev, &data[I40E_ETH_TEST_REG]))
 			eth_test->flags |= ETH_TEST_FL_FAILED;
@@ -1846,7 +1847,6 @@ static void i40e_diag_test(struct net_de
 		data[I40E_ETH_TEST_REG] = 0;
 		data[I40E_ETH_TEST_EEPROM] = 0;
 		data[I40E_ETH_TEST_INTR] = 0;
-		data[I40E_ETH_TEST_LOOPBACK] = 0;
 	}
 
 skip_ol_tests:
@@ -1925,7 +1925,7 @@ static int i40e_set_phys_id(struct net_d
 
 	switch (state) {
 	case ETHTOOL_ID_ACTIVE:
-		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) {
+		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {
 			pf->led_status = i40e_led_get(hw);
 		} else {
 			i40e_aq_set_phy_debug(hw, I40E_PHY_DEBUG_ALL, NULL);
@@ -1935,20 +1935,20 @@ static int i40e_set_phys_id(struct net_d
 		}
 		return blink_freq;
 	case ETHTOOL_ID_ON:
-		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY))
+		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
 			i40e_led_set(hw, 0xf, false);
 		else
 			ret = i40e_led_set_phy(hw, true, pf->led_status, 0);
 		break;
 	case ETHTOOL_ID_OFF:
-		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY))
+		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS))
 			i40e_led_set(hw, 0x0, false);
 		else
 			ret = i40e_led_set_phy(hw, false, pf->led_status, 0);
 		break;
 	case ETHTOOL_ID_INACTIVE:
-		if (!(pf->flags & I40E_FLAG_HAVE_10GBASET_PHY)) {
-			i40e_led_set(hw, false, pf->led_status);
+		if (!(pf->flags & I40E_FLAG_PHY_CONTROLS_LEDS)) {
+			i40e_led_set(hw, pf->led_status, false);
 		} else {
 			ret = i40e_led_set_phy(hw, false, pf->led_status,
 					       (pf->phy_led_val |
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_fcoe.c	2017-02-12 16:03:20.000000000 -0500
@@ -1522,12 +1522,12 @@ void i40e_fcoe_config_netdev(struct net_
 	 * same PCI function.
 	 */
 	netdev->dev_port = 1;
-	spin_lock_bh(&vsi->mac_filter_list_lock);
-	i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false);
-	i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false);
-	i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false);
-	i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false);
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	i40e_add_filter(vsi, hw->mac.san_addr, 0);
+	i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0);
+	i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0);
+	i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	/* use san mac */
 	ether_addr_copy(netdev->dev_addr, hw->mac.san_addr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e.h	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,7 @@
 #include <linux/iommu.h>
 #include <linux/slab.h>
 #include <linux/list.h>
+#include <linux/hashtable.h>
 #include <linux/string.h>
 #include <linux/in.h>
 #include <linux/ip.h>
@@ -355,9 +356,11 @@ struct i40e_pf {
 #define I40E_FLAG_NO_DCB_SUPPORT		BIT_ULL(45)
 #define I40E_FLAG_USE_SET_LLDP_MIB		BIT_ULL(46)
 #define I40E_FLAG_STOP_FW_LLDP			BIT_ULL(47)
-#define I40E_FLAG_HAVE_10GBASET_PHY		BIT_ULL(48)
+#define I40E_FLAG_PHY_CONTROLS_LEDS		BIT_ULL(48)
 #define I40E_FLAG_PF_MAC			BIT_ULL(50)
 #define I40E_FLAG_TRUE_PROMISC_SUPPORT		BIT_ULL(51)
+#define I40E_FLAG_HAVE_CRT_RETIMER		BIT_ULL(52)
+#define I40E_FLAG_PTP_L4_CAPABLE		BIT_ULL(53)
 
 	/* tracks features that get auto disabled by errors */
 	u64 auto_disable_flags;
@@ -428,11 +431,13 @@ struct i40e_pf {
 	struct ptp_clock_info ptp_caps;
 	struct sk_buff *ptp_tx_skb;
 	struct hwtstamp_config tstamp_config;
-	unsigned long last_rx_ptp_check;
-	spinlock_t tmreg_lock; /* Used to protect the device time registers. */
+	struct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */
 	u64 ptp_base_adj;
 	u32 tx_hwtstamp_timeouts;
 	u32 rx_hwtstamp_cleared;
+	u32 latch_event_flags;
+	spinlock_t ptp_rx_lock; /* Used to protect Rx timestamp registers. */
+	unsigned long latch_events[4];
 	bool ptp_tx;
 	bool ptp_rx;
 	u16 rss_table_size; /* HW RSS table size */
@@ -445,6 +450,20 @@ struct i40e_pf {
 	u16 phy_led_val;
 };
 
+/**
+ * i40e_mac_to_hkey - Convert a 6-byte MAC Address to a u64 hash key
+ * @macaddr: the MAC Address as the base key
+ *
+ * Simply copies the address and returns it as a u64 for hashing
+ **/
+static inline u64 i40e_addr_to_hkey(const u8 *macaddr)
+{
+	u64 key = 0;
+
+	ether_addr_copy((u8 *)&key, macaddr);
+	return key;
+}
+
 enum i40e_filter_state {
 	I40E_FILTER_INVALID = 0,	/* Invalid state */
 	I40E_FILTER_NEW,		/* New, not sent to FW yet */
@@ -454,13 +473,10 @@ enum i40e_filter_state {
 /* There is no 'removed' state; the filter struct is freed */
 };
 struct i40e_mac_filter {
-	struct list_head list;
+	struct hlist_node hlist;
 	u8 macaddr[ETH_ALEN];
 #define I40E_VLAN_ANY -1
 	s16 vlan;
-	u8 counter;		/* number of instances of this filter */
-	bool is_vf;		/* filter belongs to a VF */
-	bool is_netdev;		/* filter belongs to a netdev */
 	enum i40e_filter_state state;
 };
 
@@ -501,9 +517,11 @@ struct i40e_vsi {
 #define I40E_VSI_FLAG_VEB_OWNER		BIT(1)
 	unsigned long flags;
 
-	/* Per VSI lock to protect elements/list (MAC filter) */
-	spinlock_t mac_filter_list_lock;
-	struct list_head mac_filter_list;
+	/* Per VSI lock to protect elements/hash (MAC filter) */
+	spinlock_t mac_filter_hash_lock;
+	/* Fixed size hash table with 2^8 buckets for MAC filters */
+	DECLARE_HASHTABLE(mac_filter_hash, 8);
+	bool has_vlan_filter;
 
 	/* VSI stats */
 	struct rtnl_link_stats64 net_stats;
@@ -579,6 +597,7 @@ struct i40e_vsi {
 	u16 veb_idx;		/* index of VEB parent */
 	struct kobject *kobj;	/* sysfs object */
 	bool current_isup;	/* Sync 'link up' logging */
+	enum i40e_aq_link_speed current_speed;	/* Sync link speed logging */
 
 	void *priv;	/* client driver data reference. */
 
@@ -608,6 +627,8 @@ struct i40e_q_vector {
 	unsigned long hung_detected; /* Set/Reset for hung_detection logic */
 
 	cpumask_t affinity_mask;
+	struct irq_affinity_notify affinity_notify;
+
 	struct rcu_head rcu;	/* to avoid race with update stats on free */
 	char name[I40E_INT_NAME_STR_LEN];
 	bool arm_wb_state;
@@ -705,6 +726,25 @@ int i40e_get_rss(struct i40e_vsi *vsi, u
 void i40e_fill_rss_lut(struct i40e_pf *pf, u8 *lut,
 		       u16 rss_table_size, u16 rss_size);
 struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id);
+/**
+ * i40e_find_vsi_by_type - Find and return Flow Director VSI
+ * @pf: PF to search for VSI
+ * @type: Value indicating type of VSI we are looking for
+ **/
+static inline struct i40e_vsi *
+i40e_find_vsi_by_type(struct i40e_pf *pf, u16 type)
+{
+	int i;
+
+	for (i = 0; i < pf->num_alloc_vsi; i++) {
+		struct i40e_vsi *vsi = pf->vsi[i];
+
+		if (vsi && vsi->type == type)
+			return vsi;
+	}
+
+	return NULL;
+}
 void i40e_update_stats(struct i40e_vsi *vsi);
 void i40e_update_eth_stats(struct i40e_vsi *vsi);
 struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi);
@@ -721,16 +761,12 @@ u32 i40e_get_global_fd_count(struct i40e
 bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
 void i40e_set_ethtool_ops(struct net_device *netdev);
 struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
-					u8 *macaddr, s16 vlan,
-					bool is_vf, bool is_netdev);
-void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan,
-		     bool is_vf, bool is_netdev);
+					const u8 *macaddr, s16 vlan);
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);
 int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
 struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
 				u16 uplink, u32 param1);
 int i40e_vsi_release(struct i40e_vsi *vsi);
-struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type,
-				 struct i40e_vsi *start_vsi);
 #ifdef I40E_FCOE
 void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
 			      struct i40e_vsi_context *ctxt,
@@ -740,7 +776,8 @@ void i40e_service_event_schedule(struct
 void i40e_notify_client_of_vf_msg(struct i40e_vsi *vsi, u32 vf_id,
 				  u8 *msg, u16 len);
 
-int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable);
+int i40e_vsi_start_rings(struct i40e_vsi *vsi);
+void i40e_vsi_stop_rings(struct i40e_vsi *vsi);
 int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);
 struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
 				u16 downlink_seid, u8 enabled_tc);
@@ -815,15 +852,15 @@ int i40e_open(struct net_device *netdev)
 int i40e_close(struct net_device *netdev);
 int i40e_vsi_open(struct i40e_vsi *vsi);
 void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
+int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid);
 int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
-int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
-struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
-					     bool is_vf, bool is_netdev);
-int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
-			  bool is_vf, bool is_netdev);
+void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid);
+void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
+struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
+					     const u8 *macaddr);
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr);
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
-struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
-				      bool is_vf, bool is_netdev);
+struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
 #ifdef I40E_FCOE
 int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
 		    struct tc_to_netdev *tc);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -41,7 +41,7 @@ static const char i40e_driver_string[] =
 
 #define DRV_VERSION_MAJOR 1
 #define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 16
+#define DRV_VERSION_BUILD 25
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
 	     __stringify(DRV_VERSION_MINOR) "." \
 	     __stringify(DRV_VERSION_BUILD)    DRV_KERN
@@ -86,6 +86,8 @@ static const struct pci_device_id i40e_p
 	{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_I_X722), 0},
 	{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},
 	{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0},
+	{PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_B), 0},
+	{PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_SFP28), 0},
 	/* required last entry */
 	{0, }
 };
@@ -93,8 +95,8 @@ MODULE_DEVICE_TABLE(pci, i40e_pci_tbl);
 
 #define I40E_MAX_VF_COUNT 128
 static int debug = -1;
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX)");
 
 MODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>");
 MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver");
@@ -286,8 +288,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(s
 void i40e_service_event_schedule(struct i40e_pf *pf)
 {
 	if (!test_bit(__I40E_DOWN, &pf->state) &&
-	    !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) &&
-	    !test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
+	    !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
 		queue_work(i40e_wq, &pf->service_task);
 }
 
@@ -1145,25 +1146,22 @@ void i40e_update_stats(struct i40e_vsi *
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address
  * @vlan: the vlan
- * @is_vf: make sure its a VF filter, else doesn't matter
- * @is_netdev: make sure its a netdev filter, else doesn't matter
  *
  * Returns ptr to the filter object or NULL
  **/
 static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
-						u8 *macaddr, s16 vlan,
-						bool is_vf, bool is_netdev)
+						const u8 *macaddr, s16 vlan)
 {
 	struct i40e_mac_filter *f;
+	u64 key;
 
 	if (!vsi || !macaddr)
 		return NULL;
 
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
+	key = i40e_addr_to_hkey(macaddr);
+	hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
 		if ((ether_addr_equal(macaddr, f->macaddr)) &&
-		    (vlan == f->vlan)    &&
-		    (!is_vf || f->is_vf) &&
-		    (!is_netdev || f->is_netdev))
+		    (vlan == f->vlan))
 			return f;
 	}
 	return NULL;
@@ -1173,24 +1171,21 @@ static struct i40e_mac_filter *i40e_find
  * i40e_find_mac - Find a mac addr in the macvlan filters list
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address we are searching for
- * @is_vf: make sure its a VF filter, else doesn't matter
- * @is_netdev: make sure its a netdev filter, else doesn't matter
  *
  * Returns the first filter with the provided MAC address or NULL if
  * MAC address was not found
  **/
-struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
-				      bool is_vf, bool is_netdev)
+struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr)
 {
 	struct i40e_mac_filter *f;
+	u64 key;
 
 	if (!vsi || !macaddr)
 		return NULL;
 
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
-		if ((ether_addr_equal(macaddr, f->macaddr)) &&
-		    (!is_vf || f->is_vf) &&
-		    (!is_netdev || f->is_netdev))
+	key = i40e_addr_to_hkey(macaddr);
+	hash_for_each_possible(vsi->mac_filter_hash, f, hlist, key) {
+		if ((ether_addr_equal(macaddr, f->macaddr)))
 			return f;
 	}
 	return NULL;
@@ -1204,86 +1199,132 @@ struct i40e_mac_filter *i40e_find_mac(st
  **/
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)
 {
-	struct i40e_mac_filter *f;
+	/* If we have a PVID, always operate in VLAN mode */
+	if (vsi->info.pvid)
+		return true;
 
-	/* Only -1 for all the filters denotes not in vlan mode
-	 * so we have to go through all the list in order to make sure
+	/* We need to operate in VLAN mode whenever we have any filters with
+	 * a VLAN other than I40E_VLAN_ALL. We could check the table each
+	 * time, incurring search cost repeatedly. However, we can notice two
+	 * things:
+	 *
+	 * 1) the only place where we can gain a VLAN filter is in
+	 *    i40e_add_filter.
+	 *
+	 * 2) the only place where filters are actually removed is in
+	 *    i40e_sync_filters_subtask.
+	 *
+	 * Thus, we can simply use a boolean value, has_vlan_filters which we
+	 * will set to true when we add a VLAN filter in i40e_add_filter. Then
+	 * we have to perform the full search after deleting filters in
+	 * i40e_sync_filters_subtask, but we already have to search
+	 * filters here and can perform the check at the same time. This
+	 * results in avoiding embedding a loop for VLAN mode inside another
+	 * loop over all the filters, and should maintain correctness as noted
+	 * above.
 	 */
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
-		if (f->vlan >= 0 || vsi->info.pvid)
-			return true;
-	}
-
-	return false;
+	return vsi->has_vlan_filter;
 }
 
 /**
- * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans
- * @vsi: the VSI to be searched
- * @macaddr: the mac address to be filtered
- * @is_vf: true if it is a VF
- * @is_netdev: true if it is a netdev
+ * i40e_correct_mac_vlan_filters - Correct non-VLAN filters if necessary
+ * @vsi: the VSI to configure
+ * @tmp_add_list: list of filters ready to be added
+ * @tmp_del_list: list of filters ready to be deleted
+ * @vlan_filters: the number of active VLAN filters
  *
- * Goes through all the macvlan filters and adds a
- * macvlan filter for each unique vlan that already exists
+ * Update VLAN=0 and VLAN=-1 (I40E_VLAN_ANY) filters properly so that they
+ * behave as expected. If we have any active VLAN filters remaining or about
+ * to be added then we need to update non-VLAN filters to be marked as VLAN=0
+ * so that they only match against untagged traffic. If we no longer have any
+ * active VLAN filters, we need to make all non-VLAN filters marked as VLAN=-1
+ * so that they match against both tagged and untagged traffic. In this way,
+ * we ensure that we correctly receive the desired traffic. This ensures that
+ * when we have an active VLAN we will receive only untagged traffic and
+ * traffic matching active VLANs. If we have no active VLANs then we will
+ * operate in non-VLAN mode and receive all traffic, tagged or untagged.
  *
- * Returns first filter found on success, else NULL
- **/
-struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
-					     bool is_vf, bool is_netdev)
+ * Finally, in a similar fashion, this function also corrects filters when
+ * there is an active PVID assigned to this VSI.
+ *
+ * In case of memory allocation failure return -ENOMEM. Otherwise, return 0.
+ *
+ * This function is only expected to be called from within
+ * i40e_sync_vsi_filters.
+ *
+ * NOTE: This function expects to be called while under the
+ * mac_filter_hash_lock
+ */
+static int i40e_correct_mac_vlan_filters(struct i40e_vsi *vsi,
+					 struct hlist_head *tmp_add_list,
+					 struct hlist_head *tmp_del_list,
+					 int vlan_filters)
 {
-	struct i40e_mac_filter *f;
+	struct i40e_mac_filter *f, *add_head;
+	struct hlist_node *h;
+	int bkt, new_vlan;
 
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
-		if (vsi->info.pvid)
-			f->vlan = le16_to_cpu(vsi->info.pvid);
-		if (!i40e_find_filter(vsi, macaddr, f->vlan,
-				      is_vf, is_netdev)) {
-			if (!i40e_add_filter(vsi, macaddr, f->vlan,
-					     is_vf, is_netdev))
-				return NULL;
-		}
+	/* To determine if a particular filter needs to be replaced we
+	 * have the three following conditions:
+	 *
+	 * a) if we have a PVID assigned, then all filters which are
+	 *    not marked as VLAN=PVID must be replaced with filters that
+	 *    are.
+	 * b) otherwise, if we have any active VLANS, all filters
+	 *    which are marked as VLAN=-1 must be replaced with
+	 *    filters marked as VLAN=0
+	 * c) finally, if we do not have any active VLANS, all filters
+	 *    which are marked as VLAN=0 must be replaced with filters
+	 *    marked as VLAN=-1
+	 */
+
+	/* Update the filters about to be added in place */
+	hlist_for_each_entry(f, tmp_add_list, hlist) {
+		if (vsi->info.pvid && f->vlan != vsi->info.pvid)
+			f->vlan = vsi->info.pvid;
+		else if (vlan_filters && f->vlan == I40E_VLAN_ANY)
+			f->vlan = 0;
+		else if (!vlan_filters && f->vlan == 0)
+			f->vlan = I40E_VLAN_ANY;
 	}
 
-	return list_first_entry_or_null(&vsi->mac_filter_list,
-					struct i40e_mac_filter, list);
-}
+	/* Update the remaining active filters */
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+		/* Combine the checks for whether a filter needs to be changed
+		 * and then determine the new VLAN inside the if block, in
+		 * order to avoid duplicating code for adding the new filter
+		 * then deleting the old filter.
+		 */
+		if ((vsi->info.pvid && f->vlan != vsi->info.pvid) ||
+		    (vlan_filters && f->vlan == I40E_VLAN_ANY) ||
+		    (!vlan_filters && f->vlan == 0)) {
+			/* Determine the new vlan we will be adding */
+			if (vsi->info.pvid)
+				new_vlan = vsi->info.pvid;
+			else if (vlan_filters)
+				new_vlan = 0;
+			else
+				new_vlan = I40E_VLAN_ANY;
 
-/**
- * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS
- * @vsi: the VSI to be searched
- * @macaddr: the mac address to be removed
- * @is_vf: true if it is a VF
- * @is_netdev: true if it is a netdev
- *
- * Removes a given MAC address from a VSI, regardless of VLAN
- *
- * Returns 0 for success, or error
- **/
-int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr,
-			  bool is_vf, bool is_netdev)
-{
-	struct i40e_mac_filter *f = NULL;
-	int changed = 0;
+			/* Create the new filter */
+			add_head = i40e_add_filter(vsi, f->macaddr, new_vlan);
+			if (!add_head)
+				return -ENOMEM;
 
-	WARN(!spin_is_locked(&vsi->mac_filter_list_lock),
-	     "Missing mac_filter_list_lock\n");
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
-		if ((ether_addr_equal(macaddr, f->macaddr)) &&
-		    (is_vf == f->is_vf) &&
-		    (is_netdev == f->is_netdev)) {
-			f->counter--;
-			changed = 1;
-			if (f->counter == 0)
-				f->state = I40E_FILTER_REMOVE;
+			/* Put the replacement filter into the add list */
+			hash_del(&add_head->hlist);
+			hlist_add_head(&add_head->hlist, tmp_add_list);
+
+			/* Put the original filter into the delete list */
+			f->state = I40E_FILTER_REMOVE;
+			hash_del(&f->hlist);
+			hlist_add_head(&f->hlist, tmp_del_list);
 		}
 	}
-	if (changed) {
-		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
-		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
-		return 0;
-	}
-	return -ENOENT;
+
+	vsi->has_vlan_filter = !!vlan_filters;
+
+	return 0;
 }
 
 /**
@@ -1324,36 +1365,32 @@ static void i40e_rm_default_mac_filter(s
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address
  * @vlan: the vlan
- * @is_vf: make sure its a VF filter, else doesn't matter
- * @is_netdev: make sure its a netdev filter, else doesn't matter
  *
  * Returns ptr to the filter object or NULL when no memory available.
  *
- * NOTE: This function is expected to be called with mac_filter_list_lock
+ * NOTE: This function is expected to be called with mac_filter_hash_lock
  * being held.
  **/
 struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
-					u8 *macaddr, s16 vlan,
-					bool is_vf, bool is_netdev)
+					const u8 *macaddr, s16 vlan)
 {
 	struct i40e_mac_filter *f;
-	int changed = false;
+	u64 key;
 
 	if (!vsi || !macaddr)
 		return NULL;
 
-	/* Do not allow broadcast filter to be added since broadcast filter
-	 * is added as part of add VSI for any newly created VSI except
-	 * FDIR VSI
-	 */
-	if (is_broadcast_ether_addr(macaddr))
-		return NULL;
-
-	f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev);
+	f = i40e_find_filter(vsi, macaddr, vlan);
 	if (!f) {
 		f = kzalloc(sizeof(*f), GFP_ATOMIC);
 		if (!f)
-			goto add_filter_out;
+			return NULL;
+
+		/* Update the boolean indicating if we need to function in
+		 * VLAN mode.
+		 */
+		if (vlan >= 0)
+			vsi->has_vlan_filter = true;
 
 		ether_addr_copy(f->macaddr, macaddr);
 		f->vlan = vlan;
@@ -1365,100 +1402,148 @@ struct i40e_mac_filter *i40e_add_filter(
 			f->state = I40E_FILTER_FAILED;
 		else
 			f->state = I40E_FILTER_NEW;
-		changed = true;
-		INIT_LIST_HEAD(&f->list);
-		list_add_tail(&f->list, &vsi->mac_filter_list);
-	}
+		INIT_HLIST_NODE(&f->hlist);
 
-	/* increment counter and add a new flag if needed */
-	if (is_vf) {
-		if (!f->is_vf) {
-			f->is_vf = true;
-			f->counter++;
-		}
-	} else if (is_netdev) {
-		if (!f->is_netdev) {
-			f->is_netdev = true;
-			f->counter++;
-		}
-	} else {
-		f->counter++;
-	}
+		key = i40e_addr_to_hkey(macaddr);
+		hash_add(vsi->mac_filter_hash, &f->hlist, key);
 
-	if (changed) {
 		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
 		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
 	}
 
-add_filter_out:
+	/* If we're asked to add a filter that has been marked for removal, it
+	 * is safe to simply restore it to active state. __i40e_del_filter
+	 * will have simply deleted any filters which were previously marked
+	 * NEW or FAILED, so if it is currently marked REMOVE it must have
+	 * previously been ACTIVE. Since we haven't yet run the sync filters
+	 * task, just restore this filter to the ACTIVE state so that the
+	 * sync task leaves it in place
+	 */
+	if (f->state == I40E_FILTER_REMOVE)
+		f->state = I40E_FILTER_ACTIVE;
+
 	return f;
 }
 
 /**
- * i40e_del_filter - Remove a mac/vlan filter from the VSI
+ * __i40e_del_filter - Remove a specific filter from the VSI
+ * @vsi: VSI to remove from
+ * @f: the filter to remove from the list
+ *
+ * This function should be called instead of i40e_del_filter only if you know
+ * the exact filter you will remove already, such as via i40e_find_filter or
+ * i40e_find_mac.
+ *
+ * NOTE: This function is expected to be called with mac_filter_hash_lock
+ * being held.
+ * ANOTHER NOTE: This function MUST be called from within the context of
+ * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
+ * instead of list_for_each_entry().
+ **/
+static void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
+{
+	if (!f)
+		return;
+
+	if ((f->state == I40E_FILTER_FAILED) ||
+	    (f->state == I40E_FILTER_NEW)) {
+		/* this one never got added by the FW. Just remove it,
+		 * no need to sync anything.
+		 */
+		hash_del(&f->hlist);
+		kfree(f);
+	} else {
+		f->state = I40E_FILTER_REMOVE;
+		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+		vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
+	}
+}
+
+/**
+ * i40e_del_filter - Remove a MAC/VLAN filter from the VSI
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address
- * @vlan: the vlan
- * @is_vf: make sure it's a VF filter, else doesn't matter
- * @is_netdev: make sure it's a netdev filter, else doesn't matter
+ * @vlan: the VLAN
  *
- * NOTE: This function is expected to be called with mac_filter_list_lock
+ * NOTE: This function is expected to be called with mac_filter_hash_lock
  * being held.
  * ANOTHER NOTE: This function MUST be called from within the context of
  * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
  * instead of list_for_each_entry().
  **/
-void i40e_del_filter(struct i40e_vsi *vsi,
-		     u8 *macaddr, s16 vlan,
-		     bool is_vf, bool is_netdev)
+void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
 {
 	struct i40e_mac_filter *f;
 
 	if (!vsi || !macaddr)
 		return;
 
-	f = i40e_find_filter(vsi, macaddr, vlan, is_vf, is_netdev);
-	if (!f || f->counter == 0)
-		return;
+	f = i40e_find_filter(vsi, macaddr, vlan);
+	__i40e_del_filter(vsi, f);
+}
 
-	if (is_vf) {
-		if (f->is_vf) {
-			f->is_vf = false;
-			f->counter--;
-		}
-	} else if (is_netdev) {
-		if (f->is_netdev) {
-			f->is_netdev = false;
-			f->counter--;
-		}
-	} else {
-		/* make sure we don't remove a filter in use by VF or netdev */
-		int min_f = 0;
+/**
+ * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans
+ * @vsi: the VSI to be searched
+ * @macaddr: the mac address to be filtered
+ *
+ * Goes through all the macvlan filters and adds a macvlan filter for each
+ * unique vlan that already exists. If a PVID has been assigned, instead only
+ * add the macaddr to that VLAN.
+ *
+ * Returns last filter added on success, else NULL
+ **/
+struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
+					     const u8 *macaddr)
+{
+	struct i40e_mac_filter *f, *add = NULL;
+	struct hlist_node *h;
+	int bkt;
 
-		min_f += (f->is_vf ? 1 : 0);
-		min_f += (f->is_netdev ? 1 : 0);
+	if (vsi->info.pvid)
+		return i40e_add_filter(vsi, macaddr,
+				       le16_to_cpu(vsi->info.pvid));
 
-		if (f->counter > min_f)
-			f->counter--;
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+		if (f->state == I40E_FILTER_REMOVE)
+			continue;
+		add = i40e_add_filter(vsi, macaddr, f->vlan);
+		if (!add)
+			return NULL;
 	}
 
-	/* counter == 0 tells sync_filters_subtask to
-	 * remove the filter from the firmware's list
-	 */
-	if (f->counter == 0) {
-		if ((f->state == I40E_FILTER_FAILED) ||
-		    (f->state == I40E_FILTER_NEW)) {
-			/* this one never got added by the FW. Just remove it,
-			 * no need to sync anything.
-			 */
-			list_del(&f->list);
-			kfree(f);
-		} else {
-			f->state = I40E_FILTER_REMOVE;
-			vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
-			vsi->back->flags |= I40E_FLAG_FILTER_SYNC;
+	return add;
+}
+
+/**
+ * i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS
+ * @vsi: the VSI to be searched
+ * @macaddr: the mac address to be removed
+ *
+ * Removes a given MAC address from a VSI, regardless of VLAN
+ *
+ * Returns 0 for success, or error
+ **/
+int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr)
+{
+	struct i40e_mac_filter *f;
+	struct hlist_node *h;
+	bool found = false;
+	int bkt;
+
+	WARN(!spin_is_locked(&vsi->mac_filter_hash_lock),
+	     "Missing mac_filter_hash_lock\n");
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+		if (ether_addr_equal(macaddr, f->macaddr)) {
+			__i40e_del_filter(vsi, f);
+			found = true;
 		}
 	}
+
+	if (found)
+		return 0;
+	else
+		return -ENOENT;
 }
 
 /**
@@ -1499,10 +1584,10 @@ static int i40e_set_mac(struct net_devic
 	else
 		netdev_info(netdev, "set new mac address %pM\n", addr->sa_data);
 
-	spin_lock_bh(&vsi->mac_filter_list_lock);
-	i40e_del_mac_all_vlan(vsi, netdev->dev_addr, false, true);
-	i40e_put_mac_in_vlan(vsi, addr->sa_data, false, true);
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	i40e_del_mac_all_vlan(vsi, netdev->dev_addr);
+	i40e_put_mac_in_vlan(vsi, addr->sa_data);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 	ether_addr_copy(netdev->dev_addr, addr->sa_data);
 	if (vsi->type == I40E_VSI_MAIN) {
 		i40e_status ret;
@@ -1666,6 +1751,52 @@ static void i40e_vsi_setup_queue_map(str
 }
 
 /**
+ * i40e_addr_sync - Callback for dev_(mc|uc)_sync to add address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be added. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40e_addr_sync(struct net_device *netdev, const u8 *addr)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_mac_filter *f;
+
+	if (i40e_is_vsi_in_vlan(vsi))
+		f = i40e_put_mac_in_vlan(vsi, addr);
+	else
+		f = i40e_add_filter(vsi, addr, I40E_VLAN_ANY);
+
+	if (f)
+		return 0;
+	else
+		return -ENOMEM;
+}
+
+/**
+ * i40e_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
+ * @netdev: the netdevice
+ * @addr: address to add
+ *
+ * Called by __dev_(mc|uc)_sync when an address needs to be removed. We call
+ * __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
+ */
+static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_vsi *vsi = np->vsi;
+
+	if (i40e_is_vsi_in_vlan(vsi))
+		i40e_del_mac_all_vlan(vsi, addr);
+	else
+		i40e_del_filter(vsi, addr, I40E_VLAN_ANY);
+
+	return 0;
+}
+
+/**
  * i40e_set_rx_mode - NDO callback to set the netdev filters
  * @netdev: network interface device structure
  **/
@@ -1676,62 +1807,14 @@ static void i40e_set_rx_mode(struct net_
 #endif
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	struct i40e_mac_filter *f, *ftmp;
 	struct i40e_vsi *vsi = np->vsi;
-	struct netdev_hw_addr *uca;
-	struct netdev_hw_addr *mca;
-	struct netdev_hw_addr *ha;
-
-	spin_lock_bh(&vsi->mac_filter_list_lock);
-
-	/* add addr if not already in the filter list */
-	netdev_for_each_uc_addr(uca, netdev) {
-		if (!i40e_find_mac(vsi, uca->addr, false, true)) {
-			if (i40e_is_vsi_in_vlan(vsi))
-				i40e_put_mac_in_vlan(vsi, uca->addr,
-						     false, true);
-			else
-				i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY,
-						false, true);
-		}
-	}
-
-	netdev_for_each_mc_addr(mca, netdev) {
-		if (!i40e_find_mac(vsi, mca->addr, false, true)) {
-			if (i40e_is_vsi_in_vlan(vsi))
-				i40e_put_mac_in_vlan(vsi, mca->addr,
-						     false, true);
-			else
-				i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY,
-						false, true);
-		}
-	}
-
-	/* remove filter if not in netdev list */
-	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
-
-		if (!f->is_netdev)
-			continue;
-
-		netdev_for_each_mc_addr(mca, netdev)
-			if (ether_addr_equal(mca->addr, f->macaddr))
-				goto bottom_of_search_loop;
-
-		netdev_for_each_uc_addr(uca, netdev)
-			if (ether_addr_equal(uca->addr, f->macaddr))
-				goto bottom_of_search_loop;
 
-		for_each_dev_addr(netdev, ha)
-			if (ether_addr_equal(ha->addr, f->macaddr))
-				goto bottom_of_search_loop;
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
 
-		/* f->macaddr wasn't found in uc, mc, or ha list so delete it */
-		i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY, false, true);
+	__dev_uc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
+	__dev_mc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
 
-bottom_of_search_loop:
-		continue;
-	}
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	/* check for other flag changes */
 	if (vsi->current_netdev_flags != vsi->netdev->flags) {
@@ -1746,21 +1829,26 @@ bottom_of_search_loop:
 }
 
 /**
- * i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries
- * @vsi: pointer to vsi struct
+ * i40e_undo_filter_entries - Undo the changes made to MAC filter entries
+ * @vsi: Pointer to VSI struct
  * @from: Pointer to list which contains MAC filter entries - changes to
  *        those entries needs to be undone.
  *
- * MAC filter entries from list were slated to be removed from device.
+ * MAC filter entries from list were slated to be sent to firmware, either for
+ * addition or deletion.
  **/
-static void i40e_undo_del_filter_entries(struct i40e_vsi *vsi,
-					 struct list_head *from)
+static void i40e_undo_filter_entries(struct i40e_vsi *vsi,
+				     struct hlist_head *from)
 {
-	struct i40e_mac_filter *f, *ftmp;
+	struct i40e_mac_filter *f;
+	struct hlist_node *h;
+
+	hlist_for_each_entry_safe(f, h, from, hlist) {
+		u64 key = i40e_addr_to_hkey(f->macaddr);
 
-	list_for_each_entry_safe(f, ftmp, from, list) {
 		/* Move the element back into MAC filter list*/
-		list_move_tail(&f->list, &vsi->mac_filter_list);
+		hlist_del(&f->hlist);
+		hash_add(vsi->mac_filter_hash, &f->hlist, key);
 	}
 }
 
@@ -1770,7 +1858,6 @@ static void i40e_undo_del_filter_entries
  * @count: Number of filters added
  * @add_list: return data from fw
  * @head: pointer to first filter in current batch
- * @aq_err: status from fw
  *
  * MAC filter entries from list were slated to be added to device. Returns
  * number of successful filters. Note that 0 does NOT mean success!
@@ -1778,45 +1865,146 @@ static void i40e_undo_del_filter_entries
 static int
 i40e_update_filter_state(int count,
 			 struct i40e_aqc_add_macvlan_element_data *add_list,
-			 struct i40e_mac_filter *add_head, int aq_err)
+			 struct i40e_mac_filter *add_head)
 {
 	int retval = 0;
 	int i;
 
-
-	if (!aq_err) {
-		retval = count;
-		/* Everything's good, mark all filters active. */
-		for (i = 0; i < count ; i++) {
-			add_head->state = I40E_FILTER_ACTIVE;
-			add_head = list_next_entry(add_head, list);
-		}
-	} else if (aq_err == I40E_AQ_RC_ENOSPC) {
-		/* Device ran out of filter space. Check the return value
-		 * for each filter to see which ones are active.
+	for (i = 0; i < count; i++) {
+		/* Always check status of each filter. We don't need to check
+		 * the firmware return status because we pre-set the filter
+		 * status to I40E_AQC_MM_ERR_NO_RES when sending the filter
+		 * request to the adminq. Thus, if it no longer matches then
+		 * we know the filter is active.
 		 */
-		for (i = 0; i < count ; i++) {
-			if (add_list[i].match_method ==
-			    I40E_AQC_MM_ERR_NO_RES) {
-				add_head->state = I40E_FILTER_FAILED;
-			} else {
-				add_head->state = I40E_FILTER_ACTIVE;
-				retval++;
-			}
-			add_head = list_next_entry(add_head, list);
-		}
-	} else {
-		/* Some other horrible thing happened, fail all filters */
-		retval = 0;
-		for (i = 0; i < count ; i++) {
+		if (add_list[i].match_method == I40E_AQC_MM_ERR_NO_RES) {
 			add_head->state = I40E_FILTER_FAILED;
-			add_head = list_next_entry(add_head, list);
+		} else {
+			add_head->state = I40E_FILTER_ACTIVE;
+			retval++;
 		}
+
+		add_head = hlist_entry(add_head->hlist.next,
+				       typeof(struct i40e_mac_filter),
+				       hlist);
 	}
+
 	return retval;
 }
 
 /**
+ * i40e_aqc_del_filters - Request firmware to delete a set of filters
+ * @vsi: ptr to the VSI
+ * @vsi_name: name to display in messages
+ * @list: the list of filters to send to firmware
+ * @num_del: the number of filters to delete
+ * @retval: Set to -EIO on failure to delete
+ *
+ * Send a request to firmware via AdminQ to delete a set of filters. Uses
+ * *retval instead of a return value so that success does not force ret_val to
+ * be set to 0. This ensures that a sequence of calls to this function
+ * preserve the previous value of *retval on successful delete.
+ */
+static
+void i40e_aqc_del_filters(struct i40e_vsi *vsi, const char *vsi_name,
+			  struct i40e_aqc_remove_macvlan_element_data *list,
+			  int num_del, int *retval)
+{
+	struct i40e_hw *hw = &vsi->back->hw;
+	i40e_status aq_ret;
+	int aq_err;
+
+	aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, list, num_del, NULL);
+	aq_err = hw->aq.asq_last_status;
+
+	/* Explicitly ignore and do not report when firmware returns ENOENT */
+	if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
+		*retval = -EIO;
+		dev_info(&vsi->back->pdev->dev,
+			 "ignoring delete macvlan error on %s, err %s, aq_err %s\n",
+			 vsi_name, i40e_stat_str(hw, aq_ret),
+			 i40e_aq_str(hw, aq_err));
+	}
+}
+
+/**
+ * i40e_aqc_add_filters - Request firmware to add a set of filters
+ * @vsi: ptr to the VSI
+ * @vsi_name: name to display in messages
+ * @list: the list of filters to send to firmware
+ * @add_head: Position in the add hlist
+ * @num_add: the number of filters to add
+ * @promisc_change: set to true on exit if promiscuous mode was forced on
+ *
+ * Send a request to firmware via AdminQ to add a chunk of filters. Will set
+ * promisc_changed to true if the firmware has run out of space for more
+ * filters.
+ */
+static
+void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
+			  struct i40e_aqc_add_macvlan_element_data *list,
+			  struct i40e_mac_filter *add_head,
+			  int num_add, bool *promisc_changed)
+{
+	struct i40e_hw *hw = &vsi->back->hw;
+	int aq_err, fcnt;
+
+	i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL);
+	aq_err = hw->aq.asq_last_status;
+	fcnt = i40e_update_filter_state(num_add, list, add_head);
+
+	if (fcnt != num_add) {
+		*promisc_changed = true;
+		set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+		dev_warn(&vsi->back->pdev->dev,
+			 "Error %s adding RX filters on %s, promiscuous mode forced on\n",
+			 i40e_aq_str(hw, aq_err),
+			 vsi_name);
+	}
+}
+
+/**
+ * i40e_aqc_broadcast_filter - Set promiscuous broadcast flags
+ * @vsi: pointer to the VSI
+ * @f: filter data
+ *
+ * This function sets or clears the promiscuous broadcast flags for VLAN
+ * filters in order to properly receive broadcast frames. Assumes that only
+ * broadcast filters are passed.
+ **/
+static
+void i40e_aqc_broadcast_filter(struct i40e_vsi *vsi, const char *vsi_name,
+			       struct i40e_mac_filter *f)
+{
+	bool enable = f->state == I40E_FILTER_NEW;
+	struct i40e_hw *hw = &vsi->back->hw;
+	i40e_status aq_ret;
+
+	if (f->vlan == I40E_VLAN_ANY) {
+		aq_ret = i40e_aq_set_vsi_broadcast(hw,
+						   vsi->seid,
+						   enable,
+						   NULL);
+	} else {
+		aq_ret = i40e_aq_set_vsi_bc_promisc_on_vlan(hw,
+							    vsi->seid,
+							    enable,
+							    f->vlan,
+							    NULL);
+	}
+
+	if (aq_ret) {
+		dev_warn(&vsi->back->pdev->dev,
+			 "Error %s setting broadcast promiscuous mode on %s\n",
+			 i40e_aq_str(hw, hw->aq.asq_last_status),
+			 vsi_name);
+		f->state = I40E_FILTER_FAILED;
+	} else if (enable) {
+		f->state = I40E_FILTER_ACTIVE;
+	}
+}
+
+/**
  * i40e_sync_vsi_filters - Update the VSI filter list to the HW
  * @vsi: ptr to the VSI
  *
@@ -1826,22 +2014,24 @@ i40e_update_filter_state(int count,
  **/
 int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
 {
-	struct i40e_mac_filter *f, *ftmp, *add_head = NULL;
-	struct list_head tmp_add_list, tmp_del_list;
+	struct hlist_head tmp_add_list, tmp_del_list;
+	struct i40e_mac_filter *f, *add_head = NULL;
 	struct i40e_hw *hw = &vsi->back->hw;
+	unsigned int failed_filters = 0;
+	unsigned int vlan_filters = 0;
 	bool promisc_changed = false;
 	char vsi_name[16] = "PF";
 	int filter_list_len = 0;
-	u32 changed_flags = 0;
 	i40e_status aq_ret = 0;
-	int retval = 0;
+	u32 changed_flags = 0;
+	struct hlist_node *h;
 	struct i40e_pf *pf;
 	int num_add = 0;
 	int num_del = 0;
-	int aq_err = 0;
+	int retval = 0;
 	u16 cmd_flags;
 	int list_size;
-	int fcnt;
+	int bkt;
 
 	/* empty array typed pointers, kcalloc later */
 	struct i40e_aqc_add_macvlan_element_data *add_list;
@@ -1856,8 +2046,8 @@ int i40e_sync_vsi_filters(struct i40e_vs
 		vsi->current_netdev_flags = vsi->netdev->flags;
 	}
 
-	INIT_LIST_HEAD(&tmp_add_list);
-	INIT_LIST_HEAD(&tmp_del_list);
+	INIT_HLIST_HEAD(&tmp_add_list);
+	INIT_HLIST_HEAD(&tmp_del_list);
 
 	if (vsi->type == I40E_VSI_SRIOV)
 		snprintf(vsi_name, sizeof(vsi_name) - 1, "VF %d", vsi->vf_id);
@@ -1867,43 +2057,64 @@ int i40e_sync_vsi_filters(struct i40e_vs
 	if (vsi->flags & I40E_VSI_FLAG_FILTER_CHANGED) {
 		vsi->flags &= ~I40E_VSI_FLAG_FILTER_CHANGED;
 
-		spin_lock_bh(&vsi->mac_filter_list_lock);
+		spin_lock_bh(&vsi->mac_filter_hash_lock);
 		/* Create a list of filters to delete. */
-		list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
+		hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
 			if (f->state == I40E_FILTER_REMOVE) {
-				WARN_ON(f->counter != 0);
 				/* Move the element into temporary del_list */
-				list_move_tail(&f->list, &tmp_del_list);
-				vsi->active_filters--;
+				hash_del(&f->hlist);
+				hlist_add_head(&f->hlist, &tmp_del_list);
+
+				/* Avoid counting removed filters */
+				continue;
 			}
 			if (f->state == I40E_FILTER_NEW) {
-				WARN_ON(f->counter == 0);
-				/* Move the element into temporary add_list */
-				list_move_tail(&f->list, &tmp_add_list);
+				hash_del(&f->hlist);
+				hlist_add_head(&f->hlist, &tmp_add_list);
 			}
+
+			/* Count the number of active (current and new) VLAN
+			 * filters we have now. Does not count filters which
+			 * are marked for deletion.
+			 */
+			if (f->vlan > 0)
+				vlan_filters++;
 		}
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
+
+		retval = i40e_correct_mac_vlan_filters(vsi,
+						       &tmp_add_list,
+						       &tmp_del_list,
+						       vlan_filters);
+		if (retval)
+			goto err_no_memory_locked;
+
+		spin_unlock_bh(&vsi->mac_filter_hash_lock);
 	}
 
 	/* Now process 'del_list' outside the lock */
-	if (!list_empty(&tmp_del_list)) {
+	if (!hlist_empty(&tmp_del_list)) {
 		filter_list_len = hw->aq.asq_buf_size /
 			    sizeof(struct i40e_aqc_remove_macvlan_element_data);
 		list_size = filter_list_len *
 			    sizeof(struct i40e_aqc_remove_macvlan_element_data);
 		del_list = kzalloc(list_size, GFP_ATOMIC);
-		if (!del_list) {
-			/* Undo VSI's MAC filter entry element updates */
-			spin_lock_bh(&vsi->mac_filter_list_lock);
-			i40e_undo_del_filter_entries(vsi, &tmp_del_list);
-			spin_unlock_bh(&vsi->mac_filter_list_lock);
-			retval = -ENOMEM;
-			goto out;
-		}
+		if (!del_list)
+			goto err_no_memory;
 
-		list_for_each_entry_safe(f, ftmp, &tmp_del_list, list) {
+		hlist_for_each_entry_safe(f, h, &tmp_del_list, hlist) {
 			cmd_flags = 0;
 
+			/* handle broadcast filters by updating the broadcast
+			 * promiscuous flag instead of deleting a MAC filter.
+			 */
+			if (is_broadcast_ether_addr(f->macaddr)) {
+				i40e_aqc_broadcast_filter(vsi, vsi_name, f);
+
+				hlist_del(&f->hlist);
+				kfree(f);
+				continue;
+			}
+
 			/* add to delete list */
 			ether_addr_copy(del_list[num_del].mac_addr, f->macaddr);
 			if (f->vlan == I40E_VLAN_ANY) {
@@ -1920,73 +2131,57 @@ int i40e_sync_vsi_filters(struct i40e_vs
 
 			/* flush a full buffer */
 			if (num_del == filter_list_len) {
-				aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid,
-								del_list,
-								num_del, NULL);
-				aq_err = hw->aq.asq_last_status;
-				num_del = 0;
+				i40e_aqc_del_filters(vsi, vsi_name, del_list,
+						     num_del, &retval);
 				memset(del_list, 0, list_size);
-
-				/* Explicitly ignore and do not report when
-				 * firmware returns ENOENT.
-				 */
-				if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
-					retval = -EIO;
-					dev_info(&pf->pdev->dev,
-						 "ignoring delete macvlan error on %s, err %s, aq_err %s\n",
-						 vsi_name,
-						 i40e_stat_str(hw, aq_ret),
-						 i40e_aq_str(hw, aq_err));
-				}
+				num_del = 0;
 			}
 			/* Release memory for MAC filter entries which were
 			 * synced up with HW.
 			 */
-			list_del(&f->list);
+			hlist_del(&f->hlist);
 			kfree(f);
 		}
 
 		if (num_del) {
-			aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, del_list,
-							num_del, NULL);
-			aq_err = hw->aq.asq_last_status;
-			num_del = 0;
-
-			/* Explicitly ignore and do not report when firmware
-			 * returns ENOENT.
-			 */
-			if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
-				retval = -EIO;
-				dev_info(&pf->pdev->dev,
-					 "ignoring delete macvlan error on %s, err %s aq_err %s\n",
-					 vsi_name,
-					 i40e_stat_str(hw, aq_ret),
-					 i40e_aq_str(hw, aq_err));
-			}
+			i40e_aqc_del_filters(vsi, vsi_name, del_list,
+					     num_del, &retval);
 		}
 
 		kfree(del_list);
 		del_list = NULL;
 	}
 
-	if (!list_empty(&tmp_add_list)) {
+	if (!hlist_empty(&tmp_add_list)) {
 		/* Do all the adds now. */
 		filter_list_len = hw->aq.asq_buf_size /
 			       sizeof(struct i40e_aqc_add_macvlan_element_data);
 		list_size = filter_list_len *
 			       sizeof(struct i40e_aqc_add_macvlan_element_data);
 		add_list = kzalloc(list_size, GFP_ATOMIC);
-		if (!add_list) {
-			retval = -ENOMEM;
-			goto out;
-		}
+		if (!add_list)
+			goto err_no_memory;
+
 		num_add = 0;
-		list_for_each_entry(f, &tmp_add_list, list) {
+		hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {
 			if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
 				     &vsi->state)) {
 				f->state = I40E_FILTER_FAILED;
 				continue;
 			}
+
+			/* handle broadcast filters by updating the broadcast
+			 * promiscuous flag instead of adding a MAC filter.
+			 */
+			if (is_broadcast_ether_addr(f->macaddr)) {
+				u64 key = i40e_addr_to_hkey(f->macaddr);
+				i40e_aqc_broadcast_filter(vsi, vsi_name, f);
+
+				hlist_del(&f->hlist);
+				hash_add(vsi->mac_filter_hash, &f->hlist, key);
+				continue;
+			}
+
 			/* add to add array */
 			if (num_add == 0)
 				add_head = f;
@@ -2000,88 +2195,70 @@ int i40e_sync_vsi_filters(struct i40e_vs
 					cpu_to_le16((u16)(f->vlan));
 			}
 			add_list[num_add].queue_number = 0;
+			/* set invalid match method for later detection */
+			add_list[num_add].match_method = I40E_AQC_MM_ERR_NO_RES;
 			cmd_flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
 			add_list[num_add].flags = cpu_to_le16(cmd_flags);
 			num_add++;
 
 			/* flush a full buffer */
 			if (num_add == filter_list_len) {
-				aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
-							     add_list, num_add,
-							     NULL);
-				aq_err = hw->aq.asq_last_status;
-				fcnt = i40e_update_filter_state(num_add,
-								add_list,
-								add_head,
-								aq_ret);
-				vsi->active_filters += fcnt;
-
-				if (fcnt != num_add) {
-					promisc_changed = true;
-					set_bit(__I40E_FILTER_OVERFLOW_PROMISC,
-						&vsi->state);
-					vsi->promisc_threshold =
-						(vsi->active_filters * 3) / 4;
-					dev_warn(&pf->pdev->dev,
-						 "Error %s adding RX filters on %s, promiscuous mode forced on\n",
-						 i40e_aq_str(hw, aq_err),
-						 vsi_name);
-				}
+				i40e_aqc_add_filters(vsi, vsi_name, add_list,
+						     add_head, num_add,
+						     &promisc_changed);
 				memset(add_list, 0, list_size);
 				num_add = 0;
 			}
 		}
 		if (num_add) {
-			aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
-						     add_list, num_add, NULL);
-			aq_err = hw->aq.asq_last_status;
-			fcnt = i40e_update_filter_state(num_add, add_list,
-							add_head, aq_ret);
-			vsi->active_filters += fcnt;
-			if (fcnt != num_add) {
-				promisc_changed = true;
-				set_bit(__I40E_FILTER_OVERFLOW_PROMISC,
-					&vsi->state);
-				vsi->promisc_threshold =
-						(vsi->active_filters * 3) / 4;
-				dev_warn(&pf->pdev->dev,
-					 "Error %s adding RX filters on %s, promiscuous mode forced on\n",
-					 i40e_aq_str(hw, aq_err), vsi_name);
-			}
+			i40e_aqc_add_filters(vsi, vsi_name, add_list, add_head,
+					     num_add, &promisc_changed);
 		}
 		/* Now move all of the filters from the temp add list back to
 		 * the VSI's list.
 		 */
-		spin_lock_bh(&vsi->mac_filter_list_lock);
-		list_for_each_entry_safe(f, ftmp, &tmp_add_list, list) {
-			list_move_tail(&f->list, &vsi->mac_filter_list);
+		spin_lock_bh(&vsi->mac_filter_hash_lock);
+		hlist_for_each_entry_safe(f, h, &tmp_add_list, hlist) {
+			u64 key = i40e_addr_to_hkey(f->macaddr);
+
+			hlist_del(&f->hlist);
+			hash_add(vsi->mac_filter_hash, &f->hlist, key);
 		}
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
+		spin_unlock_bh(&vsi->mac_filter_hash_lock);
 		kfree(add_list);
 		add_list = NULL;
 	}
 
-	/* Check to see if we can drop out of overflow promiscuous mode. */
+	/* Determine the number of active and failed filters. */
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	vsi->active_filters = 0;
+	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
+		if (f->state == I40E_FILTER_ACTIVE)
+			vsi->active_filters++;
+		else if (f->state == I40E_FILTER_FAILED)
+			failed_filters++;
+	}
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+	/* If promiscuous mode has changed, we need to calculate a new
+	 * threshold for when we are safe to exit
+	 */
+	if (promisc_changed)
+		vsi->promisc_threshold = (vsi->active_filters * 3) / 4;
+
+	/* Check if we are able to exit overflow promiscuous mode. We can
+	 * safely exit if we didn't just enter, we no longer have any failed
+	 * filters, and we have reduced filters below the threshold value.
+	 */
 	if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) &&
+	    !promisc_changed && !failed_filters &&
 	    (vsi->active_filters < vsi->promisc_threshold)) {
-		int failed_count = 0;
-		/* See if we have any failed filters. We can't drop out of
-		 * promiscuous until these have all been deleted.
-		 */
-		spin_lock_bh(&vsi->mac_filter_list_lock);
-		list_for_each_entry(f, &vsi->mac_filter_list, list) {
-			if (f->state == I40E_FILTER_FAILED)
-				failed_count++;
-		}
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
-		if (!failed_count) {
-			dev_info(&pf->pdev->dev,
-				 "filter logjam cleared on %s, leaving overflow promiscuous mode\n",
-				 vsi_name);
-			clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
-			promisc_changed = true;
-			vsi->promisc_threshold = 0;
-		}
+		dev_info(&pf->pdev->dev,
+			 "filter logjam cleared on %s, leaving overflow promiscuous mode\n",
+			 vsi_name);
+		clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+		promisc_changed = true;
+		vsi->promisc_threshold = 0;
 	}
 
 	/* if the VF is not trusted do not do promisc */
@@ -2201,6 +2378,18 @@ out:
 
 	clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
 	return retval;
+
+err_no_memory:
+	/* Restore elements on the temporary add and delete lists */
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+err_no_memory_locked:
+	i40e_undo_filter_entries(vsi, &tmp_del_list);
+	i40e_undo_filter_entries(vsi, &tmp_add_list);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+	vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
+	clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+	return -ENOMEM;
 }
 
 /**
@@ -2239,13 +2428,8 @@ static void i40e_sync_filters_subtask(st
 static int i40e_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 	struct i40e_vsi *vsi = np->vsi;
 
-	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
-		return -EINVAL;
-
 	netdev_info(netdev, "changing MTU from %d to %d\n",
 		    netdev->mtu, new_mtu);
 	netdev->mtu = new_mtu;
@@ -2354,88 +2538,54 @@ static void i40e_vlan_rx_register(struct
 }
 
 /**
- * i40e_vsi_add_vlan - Add vsi membership for given vlan
+ * i40e_add_vlan_all_mac - Add a MAC/VLAN filter for each existing MAC address
  * @vsi: the vsi being configured
  * @vid: vlan id to be added (0 = untagged only , -1 = any)
+ *
+ * This is a helper function for adding a new MAC/VLAN filter with the
+ * specified VLAN for each existing MAC address already in the hash table.
+ * This function does *not* perform any accounting to update filters based on
+ * VLAN mode.
+ *
+ * NOTE: this function expects to be called while under the
+ * mac_filter_hash_lock
  **/
-int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
+int i40e_add_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
 {
-	struct i40e_mac_filter *f, *ftmp, *add_f;
-	bool is_netdev, is_vf;
-
-	is_vf = (vsi->type == I40E_VSI_SRIOV);
-	is_netdev = !!(vsi->netdev);
-
-	/* Locked once because all functions invoked below iterates list*/
-	spin_lock_bh(&vsi->mac_filter_list_lock);
-
-	if (is_netdev) {
-		add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, vid,
-					is_vf, is_netdev);
-		if (!add_f) {
-			dev_info(&vsi->back->pdev->dev,
-				 "Could not add vlan filter %d for %pM\n",
-				 vid, vsi->netdev->dev_addr);
-			spin_unlock_bh(&vsi->mac_filter_list_lock);
-			return -ENOMEM;
-		}
-	}
+	struct i40e_mac_filter *f, *add_f;
+	struct hlist_node *h;
+	int bkt;
 
-	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
-		add_f = i40e_add_filter(vsi, f->macaddr, vid, is_vf, is_netdev);
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+		if (f->state == I40E_FILTER_REMOVE)
+			continue;
+		add_f = i40e_add_filter(vsi, f->macaddr, vid);
 		if (!add_f) {
 			dev_info(&vsi->back->pdev->dev,
 				 "Could not add vlan filter %d for %pM\n",
 				 vid, f->macaddr);
-			spin_unlock_bh(&vsi->mac_filter_list_lock);
 			return -ENOMEM;
 		}
 	}
 
-	/* Now if we add a vlan tag, make sure to check if it is the first
-	 * tag (i.e. a "tag" -1 does exist) and if so replace the -1 "tag"
-	 * with 0, so we now accept untagged and specified tagged traffic
-	 * (and not all tags along with untagged)
-	 */
-	if (vid > 0) {
-		if (is_netdev && i40e_find_filter(vsi, vsi->netdev->dev_addr,
-						  I40E_VLAN_ANY,
-						  is_vf, is_netdev)) {
-			i40e_del_filter(vsi, vsi->netdev->dev_addr,
-					I40E_VLAN_ANY, is_vf, is_netdev);
-			add_f = i40e_add_filter(vsi, vsi->netdev->dev_addr, 0,
-						is_vf, is_netdev);
-			if (!add_f) {
-				dev_info(&vsi->back->pdev->dev,
-					 "Could not add filter 0 for %pM\n",
-					 vsi->netdev->dev_addr);
-				spin_unlock_bh(&vsi->mac_filter_list_lock);
-				return -ENOMEM;
-			}
-		}
-	}
+	return 0;
+}
 
-	/* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */
-	if (vid > 0 && !vsi->info.pvid) {
-		list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
-			if (!i40e_find_filter(vsi, f->macaddr, I40E_VLAN_ANY,
-					      is_vf, is_netdev))
-				continue;
-			i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY,
-					is_vf, is_netdev);
-			add_f = i40e_add_filter(vsi, f->macaddr,
-						0, is_vf, is_netdev);
-			if (!add_f) {
-				dev_info(&vsi->back->pdev->dev,
-					 "Could not add filter 0 for %pM\n",
-					f->macaddr);
-				spin_unlock_bh(&vsi->mac_filter_list_lock);
-				return -ENOMEM;
-			}
-		}
-	}
+/**
+ * i40e_vsi_add_vlan - Add VSI membership for given VLAN
+ * @vsi: the VSI being configured
+ * @vid: VLAN id to be added (0 = untagged only , -1 = any)
+ **/
+int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)
+{
+	int err;
 
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	/* Locked once because all functions invoked below iterates list*/
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	err = i40e_add_vlan_all_mac(vsi, vid);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+	if (err)
+		return err;
 
 	/* schedule our worker thread which will take care of
 	 * applying the new filter changes
@@ -2445,82 +2595,45 @@ int i40e_vsi_add_vlan(struct i40e_vsi *v
 }
 
 /**
- * i40e_vsi_kill_vlan - Remove vsi membership for given vlan
+ * i40e_rm_vlan_all_mac - Remove MAC/VLAN pair for all MAC with the given VLAN
  * @vsi: the vsi being configured
  * @vid: vlan id to be removed (0 = untagged only , -1 = any)
  *
- * Return: 0 on success or negative otherwise
- **/
-int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
+ * This function should be used to remove all VLAN filters which match the
+ * given VID. It does not schedule the service event and does not take the
+ * mac_filter_hash_lock so it may be combined with other operations under
+ * a single invocation of the mac_filter_hash_lock.
+ *
+ * NOTE: this function expects to be called while under the
+ * mac_filter_hash_lock
+ */
+void i40e_rm_vlan_all_mac(struct i40e_vsi *vsi, s16 vid)
 {
-	struct net_device *netdev = vsi->netdev;
-	struct i40e_mac_filter *f, *ftmp, *add_f;
-	bool is_vf, is_netdev;
-	int filter_count = 0;
-
-	is_vf = (vsi->type == I40E_VSI_SRIOV);
-	is_netdev = !!(netdev);
-
-	/* Locked once because all functions invoked below iterates list */
-	spin_lock_bh(&vsi->mac_filter_list_lock);
-
-	if (is_netdev)
-		i40e_del_filter(vsi, netdev->dev_addr, vid, is_vf, is_netdev);
-
-	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
-		i40e_del_filter(vsi, f->macaddr, vid, is_vf, is_netdev);
-
-	/* go through all the filters for this VSI and if there is only
-	 * vid == 0 it means there are no other filters, so vid 0 must
-	 * be replaced with -1. This signifies that we should from now
-	 * on accept any traffic (with any tag present, or untagged)
-	 */
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
-		if (is_netdev) {
-			if (f->vlan &&
-			    ether_addr_equal(netdev->dev_addr, f->macaddr))
-				filter_count++;
-		}
-
-		if (f->vlan)
-			filter_count++;
-	}
-
-	if (!filter_count && is_netdev) {
-		i40e_del_filter(vsi, netdev->dev_addr, 0, is_vf, is_netdev);
-		f = i40e_add_filter(vsi, netdev->dev_addr, I40E_VLAN_ANY,
-				    is_vf, is_netdev);
-		if (!f) {
-			dev_info(&vsi->back->pdev->dev,
-				 "Could not add filter %d for %pM\n",
-				 I40E_VLAN_ANY, netdev->dev_addr);
-			spin_unlock_bh(&vsi->mac_filter_list_lock);
-			return -ENOMEM;
-		}
-	}
+	struct i40e_mac_filter *f;
+	struct hlist_node *h;
+	int bkt;
 
-	if (!filter_count) {
-		list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
-			i40e_del_filter(vsi, f->macaddr, 0, is_vf, is_netdev);
-			add_f = i40e_add_filter(vsi, f->macaddr, I40E_VLAN_ANY,
-						is_vf, is_netdev);
-			if (!add_f) {
-				dev_info(&vsi->back->pdev->dev,
-					 "Could not add filter %d for %pM\n",
-					 I40E_VLAN_ANY, f->macaddr);
-				spin_unlock_bh(&vsi->mac_filter_list_lock);
-				return -ENOMEM;
-			}
-		}
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+		if (f->vlan == vid)
+			__i40e_del_filter(vsi, f);
 	}
+}
 
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+/**
+ * i40e_vsi_kill_vlan - Remove VSI membership for given VLAN
+ * @vsi: the VSI being configured
+ * @vid: VLAN id to be removed (0 = untagged only , -1 = any)
+ **/
+void i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)
+{
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	i40e_rm_vlan_all_mac(vsi, vid);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	/* schedule our worker thread which will take care of
 	 * applying the new filter changes
 	 */
 	i40e_service_event_schedule(vsi->back);
-	return 0;
 }
 
 /**
@@ -2542,7 +2655,7 @@ static int i40e_vlan_rx_add_vid(struct n
 	struct i40e_vsi *vsi = np->vsi;
 	int ret = 0;
 
-	if (vid > 4095)
+	if (vid >= VLAN_N_VID)
 		return -EINVAL;
 
 	/* If the network stack called us with vid = 0 then
@@ -2554,7 +2667,7 @@ static int i40e_vlan_rx_add_vid(struct n
 	if (vid)
 		ret = i40e_vsi_add_vlan(vsi, vid);
 
-	if (!ret && (vid < VLAN_N_VID))
+	if (!ret)
 		set_bit(vid, vsi->active_vlans);
 
 	return ret;
@@ -3322,6 +3435,33 @@ static irqreturn_t i40e_msix_clean_rings
 }
 
 /**
+ * i40e_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40e_irq_affinity_notify(struct irq_affinity_notify *notify,
+				     const cpumask_t *mask)
+{
+	struct i40e_q_vector *q_vector =
+		container_of(notify, struct i40e_q_vector, affinity_notify);
+
+	q_vector->affinity_mask = *mask;
+}
+
+/**
+ * i40e_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40e_irq_affinity_release(struct kref *ref) {}
+
+/**
  * i40e_vsi_request_irq_msix - Initialize MSI-X interrupts
  * @vsi: the VSI being configured
  * @basename: name for the vector
@@ -3336,10 +3476,13 @@ static int i40e_vsi_request_irq_msix(str
 	int rx_int_idx = 0;
 	int tx_int_idx = 0;
 	int vector, err;
+	int irq_num;
 
 	for (vector = 0; vector < q_vectors; vector++) {
 		struct i40e_q_vector *q_vector = vsi->q_vectors[vector];
 
+		irq_num = pf->msix_entries[base + vector].vector;
+
 		if (q_vector->tx.ring && q_vector->rx.ring) {
 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
 				 "%s-%s-%d", basename, "TxRx", rx_int_idx++);
@@ -3354,7 +3497,7 @@ static int i40e_vsi_request_irq_msix(str
 			/* skip this unused q_vector */
 			continue;
 		}
-		err = request_irq(pf->msix_entries[base + vector].vector,
+		err = request_irq(irq_num,
 				  vsi->irq_handler,
 				  0,
 				  q_vector->name,
@@ -3364,9 +3507,13 @@ static int i40e_vsi_request_irq_msix(str
 				 "MSIX request_irq failed, error: %d\n", err);
 			goto free_queue_irqs;
 		}
+
+		/* register for affinity change notifications */
+		q_vector->affinity_notify.notify = i40e_irq_affinity_notify;
+		q_vector->affinity_notify.release = i40e_irq_affinity_release;
+		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
 		/* assign the mask for this irq */
-		irq_set_affinity_hint(pf->msix_entries[base + vector].vector,
-				      &q_vector->affinity_mask);
+		irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
 	}
 
 	vsi->irqs_ready = true;
@@ -3375,10 +3522,10 @@ static int i40e_vsi_request_irq_msix(str
 free_queue_irqs:
 	while (vector) {
 		vector--;
-		irq_set_affinity_hint(pf->msix_entries[base + vector].vector,
-				      NULL);
-		free_irq(pf->msix_entries[base + vector].vector,
-			 &(vsi->q_vectors[vector]));
+		irq_num = pf->msix_entries[base + vector].vector;
+		irq_set_affinity_notifier(irq_num, NULL);
+		irq_set_affinity_hint(irq_num, NULL);
+		free_irq(irq_num, &vsi->q_vectors[vector]);
 	}
 	return err;
 }
@@ -3480,7 +3627,7 @@ static irqreturn_t i40e_intr(int irq, vo
 	    (ena_mask & I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK)) {
 		ena_mask &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
 		icr0 &= ~I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK;
-		dev_info(&pf->pdev->dev, "cleared PE_CRITERR\n");
+		dev_dbg(&pf->pdev->dev, "cleared PE_CRITERR\n");
 	}
 
 	/* only q0 is used in MSI/Legacy mode, and none are used in MSIX */
@@ -3973,30 +4120,36 @@ static int i40e_vsi_control_rx(struct i4
 }
 
 /**
- * i40e_vsi_control_rings - Start or stop a VSI's rings
+ * i40e_vsi_start_rings - Start a VSI's rings
  * @vsi: the VSI being configured
- * @enable: start or stop the rings
  **/
-int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool request)
+int i40e_vsi_start_rings(struct i40e_vsi *vsi)
 {
 	int ret = 0;
 
 	/* do rx first for enable and last for disable */
-	if (request) {
-		ret = i40e_vsi_control_rx(vsi, request);
-		if (ret)
-			return ret;
-		ret = i40e_vsi_control_tx(vsi, request);
-	} else {
-		/* Ignore return value, we need to shutdown whatever we can */
-		i40e_vsi_control_tx(vsi, request);
-		i40e_vsi_control_rx(vsi, request);
-	}
+	ret = i40e_vsi_control_rx(vsi, true);
+	if (ret)
+		return ret;
+	ret = i40e_vsi_control_tx(vsi, true);
 
 	return ret;
 }
 
 /**
+ * i40e_vsi_stop_rings - Stop a VSI's rings
+ * @vsi: the VSI being configured
+ **/
+void i40e_vsi_stop_rings(struct i40e_vsi *vsi)
+{
+	/* do rx first for enable and last for disable
+	 * Ignore return value, we need to shutdown whatever we can
+	 */
+	i40e_vsi_control_tx(vsi, false);
+	i40e_vsi_control_rx(vsi, false);
+}
+
+/**
  * i40e_vsi_free_irq - Free the irq association with the OS
  * @vsi: the VSI being configured
  **/
@@ -4017,19 +4170,23 @@ static void i40e_vsi_free_irq(struct i40
 
 		vsi->irqs_ready = false;
 		for (i = 0; i < vsi->num_q_vectors; i++) {
-			u16 vector = i + base;
+			int irq_num;
+			u16 vector;
+
+			vector = i + base;
+			irq_num = pf->msix_entries[vector].vector;
 
 			/* free only the irqs that were actually requested */
 			if (!vsi->q_vectors[i] ||
 			    !vsi->q_vectors[i]->num_ringpairs)
 				continue;
 
+			/* clear the affinity notifier in the IRQ descriptor */
+			irq_set_affinity_notifier(irq_num, NULL);
 			/* clear the affinity_mask in the IRQ descriptor */
-			irq_set_affinity_hint(pf->msix_entries[vector].vector,
-					      NULL);
-			synchronize_irq(pf->msix_entries[vector].vector);
-			free_irq(pf->msix_entries[vector].vector,
-				 vsi->q_vectors[i]);
+			irq_set_affinity_hint(irq_num, NULL);
+			synchronize_irq(irq_num);
+			free_irq(irq_num, vsi->q_vectors[i]);
 
 			/* Tear down the interrupt queue link list
 			 *
@@ -5116,12 +5273,16 @@ out:
  */
 void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
 {
+	enum i40e_aq_link_speed new_speed;
 	char *speed = "Unknown";
 	char *fc = "Unknown";
 
-	if (vsi->current_isup == isup)
+	new_speed = vsi->back->hw.phy.link_info.link_speed;
+
+	if ((vsi->current_isup == isup) && (vsi->current_speed == new_speed))
 		return;
 	vsi->current_isup = isup;
+	vsi->current_speed = new_speed;
 	if (!isup) {
 		netdev_info(vsi->netdev, "NIC Link is Down\n");
 		return;
@@ -5143,6 +5304,9 @@ void i40e_print_link_message(struct i40e
 	case I40E_LINK_SPEED_20GB:
 		speed = "20 G";
 		break;
+	case I40E_LINK_SPEED_25GB:
+		speed = "25 G";
+		break;
 	case I40E_LINK_SPEED_10GB:
 		speed = "10 G";
 		break;
@@ -5190,7 +5354,7 @@ static int i40e_up_complete(struct i40e_
 		i40e_configure_msi_and_legacy(vsi);
 
 	/* start rings */
-	err = i40e_vsi_control_rings(vsi, true);
+	err = i40e_vsi_start_rings(vsi);
 	if (err)
 		return err;
 
@@ -5287,7 +5451,7 @@ void i40e_down(struct i40e_vsi *vsi)
 		netif_tx_disable(vsi->netdev);
 	}
 	i40e_vsi_disable_irq(vsi);
-	i40e_vsi_control_rings(vsi, false);
+	i40e_vsi_stop_rings(vsi);
 	i40e_napi_disable_all(vsi);
 
 	for (i = 0; i < vsi->num_queue_pairs; i++) {
@@ -5833,19 +5997,6 @@ static void i40e_handle_lan_overflow_eve
 }
 
 /**
- * i40e_service_event_complete - Finish up the service event
- * @pf: board private structure
- **/
-static void i40e_service_event_complete(struct i40e_pf *pf)
-{
-	WARN_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state));
-
-	/* flush memory to make sure state is correct before next watchog */
-	smp_mb__before_atomic();
-	clear_bit(__I40E_SERVICE_SCHED, &pf->state);
-}
-
-/**
  * i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
  * @pf: board private structure
  **/
@@ -6670,7 +6821,6 @@ static int i40e_vsi_clear(struct i40e_vs
 static void i40e_fdir_sb_setup(struct i40e_pf *pf)
 {
 	struct i40e_vsi *vsi;
-	int i;
 
 	/* quick workaround for an NVM issue that leaves a critical register
 	 * uninitialized
@@ -6681,6 +6831,7 @@ static void i40e_fdir_sb_setup(struct i4
 			0xeacb7d61, 0xaa4f05b6, 0x9c5c89ed, 0xfc425ddb,
 			0xa4654832, 0xfc7461d4, 0x8f827619, 0xf5c63c21,
 			0x95b3a76d};
+		int i;
 
 		for (i = 0; i <= I40E_GLQF_HKEY_MAX_INDEX; i++)
 			wr32(&pf->hw, I40E_GLQF_HKEY(i), hkey[i]);
@@ -6690,13 +6841,7 @@ static void i40e_fdir_sb_setup(struct i4
 		return;
 
 	/* find existing VSI and see if it needs configuring */
-	vsi = NULL;
-	for (i = 0; i < pf->num_alloc_vsi; i++) {
-		if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
-			vsi = pf->vsi[i];
-			break;
-		}
-	}
+	vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);
 
 	/* create a new VSI if none exists */
 	if (!vsi) {
@@ -6718,15 +6863,12 @@ static void i40e_fdir_sb_setup(struct i4
  **/
 static void i40e_fdir_teardown(struct i40e_pf *pf)
 {
-	int i;
+	struct i40e_vsi *vsi;
 
 	i40e_fdir_filter_exit(pf);
-	for (i = 0; i < pf->num_alloc_vsi; i++) {
-		if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
-			i40e_vsi_release(pf->vsi[i]);
-			break;
-		}
-	}
+	vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);
+	if (vsi)
+		i40e_vsi_release(vsi);
 }
 
 /**
@@ -7163,10 +7305,12 @@ static void i40e_service_task(struct wor
 
 	/* don't bother with service tasks if a reset is in progress */
 	if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) {
-		i40e_service_event_complete(pf);
 		return;
 	}
 
+	if (test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
+		return;
+
 	i40e_detect_recover_hung(pf);
 	i40e_sync_filters_subtask(pf);
 	i40e_reset_subtask(pf);
@@ -7179,7 +7323,9 @@ static void i40e_service_task(struct wor
 	i40e_sync_udp_filters_subtask(pf);
 	i40e_clean_adminq_subtask(pf);
 
-	i40e_service_event_complete(pf);
+	/* flush memory to make sure state is correct before next watchdog */
+	smp_mb__before_atomic();
+	clear_bit(__I40E_SERVICE_SCHED, &pf->state);
 
 	/* If the tasks have taken longer than one timer cycle or there
 	 * is more work to be done, reschedule the service task now
@@ -7354,7 +7500,7 @@ static int i40e_vsi_mem_alloc(struct i40
 				pf->rss_table_size : 64;
 	vsi->netdev_registered = false;
 	vsi->work_limit = I40E_DEFAULT_IRQ_WORK;
-	INIT_LIST_HEAD(&vsi->mac_filter_list);
+	hash_init(vsi->mac_filter_hash);
 	vsi->irqs_ready = false;
 
 	ret = i40e_set_num_rings_in_vsi(vsi);
@@ -7369,7 +7515,7 @@ static int i40e_vsi_mem_alloc(struct i40
 	i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);
 
 	/* Initialize VSI lock */
-	spin_lock_init(&vsi->mac_filter_list_lock);
+	spin_lock_init(&vsi->mac_filter_hash_lock);
 	pf->vsi[vsi_idx] = vsi;
 	ret = vsi_idx;
 	goto unlock_pf;
@@ -8345,8 +8491,8 @@ int i40e_reconfig_rss_queues(struct i40e
 
 		i40e_pf_config_rss(pf);
 	}
-	dev_info(&pf->pdev->dev, "RSS count/HW max RSS count:  %d/%d\n",
-		 pf->alloc_rss_size, pf->rss_size_max);
+	dev_info(&pf->pdev->dev, "User requested queue count/HW max RSS count:  %d/%d\n",
+		 vsi->req_queue_pairs, pf->rss_size_max);
 	return pf->alloc_rss_size;
 }
 
@@ -8489,15 +8635,6 @@ static int i40e_sw_init(struct i40e_pf *
 	int err = 0;
 	int size;
 
-	pf->msg_enable = netif_msg_init(I40E_DEFAULT_MSG_ENABLE,
-				(NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK));
-	if (debug != -1 && debug != I40E_DEFAULT_MSG_ENABLE) {
-		if (I40E_DEBUG_USER & debug)
-			pf->hw.debug_mask = debug;
-		pf->msg_enable = netif_msg_init((debug & ~I40E_DEBUG_USER),
-						I40E_DEFAULT_MSG_ENABLE);
-	}
-
 	/* Set default capability flags */
 	pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
 		    I40E_FLAG_MSI_ENABLED     |
@@ -8605,7 +8742,8 @@ static int i40e_sw_init(struct i40e_pf *
 			     I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE |
 			     I40E_FLAG_NO_PCI_LINK_CHECK |
 			     I40E_FLAG_USE_SET_LLDP_MIB |
-			     I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
+			     I40E_FLAG_GENEVE_OFFLOAD_CAPABLE |
+			     I40E_FLAG_PTP_L4_CAPABLE;
 	} else if ((pf->hw.aq.api_maj_ver > 1) ||
 		   ((pf->hw.aq.api_maj_ver == 1) &&
 		    (pf->hw.aq.api_min_ver > 4))) {
@@ -9037,10 +9175,6 @@ static int i40e_ndo_bridge_getlink(struc
 				       0, 0, nlflags, filter_mask, NULL);
 }
 
-/* Hardware supports L4 tunnel length of 128B (=2^7) which includes
- * inner mac plus all inner ethertypes.
- */
-#define I40E_MAX_TUNNEL_HDR_LEN 128
 /**
  * i40e_features_check - Validate encapsulated packet conforms to limits
  * @skb: skb buff
@@ -9051,12 +9185,52 @@ static netdev_features_t i40e_features_c
 					     struct net_device *dev,
 					     netdev_features_t features)
 {
-	if (skb->encapsulation &&
-	    ((skb_inner_network_header(skb) - skb_transport_header(skb)) >
-	     I40E_MAX_TUNNEL_HDR_LEN))
-		return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+	size_t len;
+
+	/* No point in doing any of this if neither checksum nor GSO are
+	 * being requested for this frame.  We can rule out both by just
+	 * checking for CHECKSUM_PARTIAL
+	 */
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return features;
+
+	/* We cannot support GSO if the MSS is going to be less than
+	 * 64 bytes.  If it is then we need to drop support for GSO.
+	 */
+	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
+		features &= ~NETIF_F_GSO_MASK;
+
+	/* MACLEN can support at most 63 words */
+	len = skb_network_header(skb) - skb->data;
+	if (len & ~(63 * 2))
+		goto out_err;
+
+	/* IPLEN and EIPLEN can support at most 127 dwords */
+	len = skb_transport_header(skb) - skb_network_header(skb);
+	if (len & ~(127 * 4))
+		goto out_err;
+
+	if (skb->encapsulation) {
+		/* L4TUNLEN can support 127 words */
+		len = skb_inner_network_header(skb) - skb_transport_header(skb);
+		if (len & ~(127 * 2))
+			goto out_err;
+
+		/* IPLEN can support at most 127 dwords */
+		len = skb_inner_transport_header(skb) -
+		      skb_inner_network_header(skb);
+		if (len & ~(127 * 4))
+			goto out_err;
+	}
+
+	/* No need to validate L4LEN as TCP is the only protocol with a
+	 * a flexible value and we support all possible values supported
+	 * by TCP, which is at most 15 dwords
+	 */
 
 	return features;
+out_err:
+	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
 }
 
 static const struct net_device_ops i40e_netdev_ops = {
@@ -9109,6 +9283,7 @@ static int i40e_config_netdev(struct i40
 	struct i40e_hw *hw = &pf->hw;
 	struct i40e_netdev_priv *np;
 	struct net_device *netdev;
+	u8 broadcast[ETH_ALEN];
 	u8 mac_addr[ETH_ALEN];
 	int etherdev_size;
 
@@ -9169,20 +9344,38 @@ static int i40e_config_netdev(struct i40
 		 * which must be replaced by a normal filter.
 		 */
 		i40e_rm_default_mac_filter(vsi, mac_addr);
-		spin_lock_bh(&vsi->mac_filter_list_lock);
-		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, true);
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
+		spin_lock_bh(&vsi->mac_filter_hash_lock);
+		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY);
+		spin_unlock_bh(&vsi->mac_filter_hash_lock);
 	} else {
 		/* relate the VSI_VMDQ name to the VSI_MAIN name */
 		snprintf(netdev->name, IFNAMSIZ, "%sv%%d",
 			 pf->vsi[pf->lan_vsi]->netdev->name);
 		random_ether_addr(mac_addr);
 
-		spin_lock_bh(&vsi->mac_filter_list_lock);
-		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY, false, false);
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
+		spin_lock_bh(&vsi->mac_filter_hash_lock);
+		i40e_add_filter(vsi, mac_addr, I40E_VLAN_ANY);
+		spin_unlock_bh(&vsi->mac_filter_hash_lock);
 	}
 
+	/* Add the broadcast filter so that we initially will receive
+	 * broadcast packets. Note that when a new VLAN is first added the
+	 * driver will convert all filters marked I40E_VLAN_ANY into VLAN
+	 * specific filters as part of transitioning into "vlan" operation.
+	 * When more VLANs are added, the driver will copy each existing MAC
+	 * filter and add it for the new VLAN.
+	 *
+	 * Broadcast filters are handled specially by
+	 * i40e_sync_filters_subtask, as the driver must to set the broadcast
+	 * promiscuous bit instead of adding this directly as a MAC/VLAN
+	 * filter. The subtask will update the correct broadcast promiscuous
+	 * bits as VLANs become active or inactive.
+	 */
+	eth_broadcast_addr(broadcast);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	i40e_add_filter(vsi, broadcast, I40E_VLAN_ANY);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
 	ether_addr_copy(netdev->dev_addr, mac_addr);
 	ether_addr_copy(netdev->perm_addr, mac_addr);
 
@@ -9198,6 +9391,11 @@ static int i40e_config_netdev(struct i40
 	i40e_fcoe_config_netdev(netdev, vsi);
 #endif
 
+	/* MTU range: 68 - 9706 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = I40E_MAX_RXBUFFER -
+			  (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN);
+
 	return 0;
 }
 
@@ -9260,11 +9458,12 @@ int i40e_is_vsi_uplink_mode_veb(struct i
 static int i40e_add_vsi(struct i40e_vsi *vsi)
 {
 	int ret = -ENODEV;
-	i40e_status aq_ret = 0;
 	struct i40e_pf *pf = vsi->back;
 	struct i40e_hw *hw = &pf->hw;
 	struct i40e_vsi_context ctxt;
-	struct i40e_mac_filter *f, *ftmp;
+	struct i40e_mac_filter *f;
+	struct hlist_node *h;
+	int bkt;
 
 	u8 enabled_tc = 0x1; /* TC0 enabled */
 	int f_count = 0;
@@ -9448,28 +9647,16 @@ static int i40e_add_vsi(struct i40e_vsi
 		vsi->seid = ctxt.seid;
 		vsi->id = ctxt.vsi_number;
 	}
-	/* Except FDIR VSI, for all othet VSI set the broadcast filter */
-	if (vsi->type != I40E_VSI_FDIR) {
-		aq_ret = i40e_aq_set_vsi_broadcast(hw, vsi->seid, true, NULL);
-		if (aq_ret) {
-			ret = i40e_aq_rc_to_posix(aq_ret,
-						  hw->aq.asq_last_status);
-			dev_info(&pf->pdev->dev,
-				 "set brdcast promisc failed, err %s, aq_err %s\n",
-				 i40e_stat_str(hw, aq_ret),
-				 i40e_aq_str(hw, hw->aq.asq_last_status));
-		}
-	}
 
 	vsi->active_filters = 0;
 	clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
-	spin_lock_bh(&vsi->mac_filter_list_lock);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
 	/* If macvlan filters already exist, force them to get loaded */
-	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
 		f->state = I40E_FILTER_NEW;
 		f_count++;
 	}
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	if (f_count) {
 		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -9499,11 +9686,12 @@ err:
  **/
 int i40e_vsi_release(struct i40e_vsi *vsi)
 {
-	struct i40e_mac_filter *f, *ftmp;
+	struct i40e_mac_filter *f;
+	struct hlist_node *h;
 	struct i40e_veb *veb = NULL;
 	struct i40e_pf *pf;
 	u16 uplink_seid;
-	int i, n;
+	int i, n, bkt;
 
 	pf = vsi->back;
 
@@ -9533,11 +9721,19 @@ int i40e_vsi_release(struct i40e_vsi *vs
 		i40e_vsi_disable_irq(vsi);
 	}
 
-	spin_lock_bh(&vsi->mac_filter_list_lock);
-	list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
-		i40e_del_filter(vsi, f->macaddr, f->vlan,
-				f->is_vf, f->is_netdev);
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+
+	/* clear the sync flag on all filters */
+	if (vsi->netdev) {
+		__dev_uc_unsync(vsi->netdev, NULL);
+		__dev_mc_unsync(vsi->netdev, NULL);
+	}
+
+	/* make sure any remaining filters are marked for deletion */
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist)
+		__i40e_del_filter(vsi, f);
+
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	i40e_sync_vsi_filters(vsi);
 
@@ -10806,10 +11002,12 @@ static int i40e_probe(struct pci_dev *pd
 	mutex_init(&hw->aq.asq_mutex);
 	mutex_init(&hw->aq.arq_mutex);
 
-	if (debug != -1) {
-		pf->msg_enable = pf->hw.debug_mask;
-		pf->msg_enable = debug;
-	}
+	pf->msg_enable = netif_msg_init(debug,
+					NETIF_MSG_DRV |
+					NETIF_MSG_PROBE |
+					NETIF_MSG_LINK);
+	if (debug < -1)
+		pf->hw.debug_mask = debug;
 
 	/* do a special CORER for clearing PXE mode once at init */
 	if (hw->revision_id == 0 &&
@@ -10951,7 +11149,7 @@ static int i40e_probe(struct pci_dev *pd
 	err = i40e_init_pf_dcb(pf);
 	if (err) {
 		dev_info(&pdev->dev, "DCB init failed %d, disabled\n", err);
-		pf->flags &= ~(I40E_FLAG_DCB_CAPABLE & I40E_FLAG_DCB_ENABLED);
+		pf->flags &= ~(I40E_FLAG_DCB_CAPABLE | I40E_FLAG_DCB_ENABLED);
 		/* Continue without DCB enabled */
 	}
 #endif /* CONFIG_I40E_DCB */
@@ -11209,7 +11407,6 @@ static int i40e_probe(struct pci_dev *pd
 		dev_dbg(&pf->pdev->dev, "get supported phy types ret =  %s last_status =  %s\n",
 			i40e_stat_str(&pf->hw, err),
 			i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
-	pf->hw.phy.phy_types = le32_to_cpu(abilities.phy_type);
 
 	/* Add a filter to drop all Flow control frames from any VSI from being
 	 * transmitted. By doing so we stop a malicious VF from sending out
@@ -11221,9 +11418,10 @@ static int i40e_probe(struct pci_dev *pd
 						       pf->main_vsi_seid);
 
 	if ((pf->hw.device_id == I40E_DEV_ID_10G_BASE_T) ||
-	    (pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4))
-		pf->flags |= I40E_FLAG_HAVE_10GBASET_PHY;
-
+		(pf->hw.device_id == I40E_DEV_ID_10G_BASE_T4))
+		pf->flags |= I40E_FLAG_PHY_CONTROLS_LEDS;
+	if (pf->hw.device_id == I40E_DEV_ID_SFP_I_X722)
+		pf->flags |= I40E_FLAG_HAVE_CRT_RETIMER;
 	/* print a string summarizing features */
 	i40e_print_features(pf);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_nvm.c	2017-02-12 16:03:20.000000000 -0500
@@ -722,9 +722,20 @@ i40e_status i40e_nvmupd_command(struct i
 			*((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
 		}
 
+		/* Clear error status on read */
+		if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR)
+			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+
 		return 0;
 	}
 
+	/* Clear status even it is not read and log */
+	if (hw->nvmupd_state == I40E_NVMUPD_STATE_ERROR) {
+		i40e_debug(hw, I40E_DEBUG_NVM,
+			   "Clearing I40E_NVMUPD_STATE_ERROR state without reading\n");
+		hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
+	}
+
 	switch (hw->nvmupd_state) {
 	case I40E_NVMUPD_STATE_INIT:
 		status = i40e_nvmupd_state_init(hw, cmd, bytes, perrno);
@@ -1074,6 +1085,11 @@ void i40e_nvmupd_check_wait_event(struct
 		}
 		hw->nvm_wait_opcode = 0;
 
+		if (hw->aq.arq_last_status) {
+			hw->nvmupd_state = I40E_NVMUPD_STATE_ERROR;
+			return;
+		}
+
 		switch (hw->nvmupd_state) {
 		case I40E_NVMUPD_STATE_INIT_WAIT:
 			hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_prototype.h	2017-02-12 16:03:20.000000000 -0500
@@ -144,6 +144,9 @@ enum i40e_status_code i40e_aq_set_vsi_uc
 							 u16 seid, bool enable,
 							 u16 vid,
 				struct i40e_asq_cmd_details *cmd_details);
+i40e_status i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
+				u16 seid, bool enable, u16 vid,
+				struct i40e_asq_cmd_details *cmd_details);
 i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
 				u16 seid, bool enable,
 				struct i40e_asq_cmd_details *cmd_details);
@@ -362,10 +365,18 @@ i40e_status i40e_aq_rx_ctl_write_registe
 				u32 reg_addr, u32 reg_val,
 				struct i40e_asq_cmd_details *cmd_details);
 void i40e_write_rx_ctl(struct i40e_hw *hw, u32 reg_addr, u32 reg_val);
-i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
-				   u16 reg, u8 phy_addr, u16 *value);
-i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
-				    u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register_clause22(struct i40e_hw *hw,
+					    u16 reg, u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register_clause22(struct i40e_hw *hw,
+					     u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
+				u8 page, u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+				   u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+				    u8 phy_addr, u16 value);
 u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
 i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
 				    u32 time, u32 interval);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_ptp.c	2017-02-12 16:03:20.000000000 -0500
@@ -159,16 +159,15 @@ static int i40e_ptp_adjtime(struct ptp_c
 {
 	struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
 	struct timespec64 now, then;
-	unsigned long flags;
 
 	then = ns_to_timespec64(delta);
-	spin_lock_irqsave(&pf->tmreg_lock, flags);
+	mutex_lock(&pf->tmreg_lock);
 
 	i40e_ptp_read(pf, &now);
 	now = timespec64_add(now, then);
 	i40e_ptp_write(pf, (const struct timespec64 *)&now);
 
-	spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+	mutex_unlock(&pf->tmreg_lock);
 
 	return 0;
 }
@@ -184,11 +183,10 @@ static int i40e_ptp_adjtime(struct ptp_c
 static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
 {
 	struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
-	unsigned long flags;
 
-	spin_lock_irqsave(&pf->tmreg_lock, flags);
+	mutex_lock(&pf->tmreg_lock);
 	i40e_ptp_read(pf, ts);
-	spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+	mutex_unlock(&pf->tmreg_lock);
 
 	return 0;
 }
@@ -205,11 +203,10 @@ static int i40e_ptp_settime(struct ptp_c
 			    const struct timespec64 *ts)
 {
 	struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
-	unsigned long flags;
 
-	spin_lock_irqsave(&pf->tmreg_lock, flags);
+	mutex_lock(&pf->tmreg_lock);
 	i40e_ptp_write(pf, ts);
-	spin_unlock_irqrestore(&pf->tmreg_lock, flags);
+	mutex_unlock(&pf->tmreg_lock);
 
 	return 0;
 }
@@ -230,6 +227,47 @@ static int i40e_ptp_feature_enable(struc
 }
 
 /**
+ * i40e_ptp_update_latch_events - Read I40E_PRTTSYN_STAT_1 and latch events
+ * @pf: the PF data structure
+ *
+ * This function reads I40E_PRTTSYN_STAT_1 and updates the corresponding timers
+ * for noticed latch events. This allows the driver to keep track of the first
+ * time a latch event was noticed which will be used to help clear out Rx
+ * timestamps for packets that got dropped or lost.
+ *
+ * This function will return the current value of I40E_PRTTSYN_STAT_1 and is
+ * expected to be called only while under the ptp_rx_lock.
+ **/
+static u32 i40e_ptp_get_rx_events(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = &pf->hw;
+	u32 prttsyn_stat, new_latch_events;
+	int  i;
+
+	prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+	new_latch_events = prttsyn_stat & ~pf->latch_event_flags;
+
+	/* Update the jiffies time for any newly latched timestamp. This
+	 * ensures that we store the time that we first discovered a timestamp
+	 * was latched by the hardware. The service task will later determine
+	 * if we should free the latch and drop that timestamp should too much
+	 * time pass. This flow ensures that we only update jiffies for new
+	 * events latched since the last time we checked, and not all events
+	 * currently latched, so that the service task accounting remains
+	 * accurate.
+	 */
+	for (i = 0; i < 4; i++) {
+		if (new_latch_events & BIT(i))
+			pf->latch_events[i] = jiffies;
+	}
+
+	/* Finally, we store the current status of the Rx timestamp latches */
+	pf->latch_event_flags = prttsyn_stat;
+
+	return prttsyn_stat;
+}
+
+/**
  * i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
  * @vsi: The VSI with the rings relevant to 1588
  *
@@ -242,10 +280,7 @@ void i40e_ptp_rx_hang(struct i40e_vsi *v
 {
 	struct i40e_pf *pf = vsi->back;
 	struct i40e_hw *hw = &pf->hw;
-	struct i40e_ring *rx_ring;
-	unsigned long rx_event;
-	u32 prttsyn_stat;
-	int n;
+	int i;
 
 	/* Since we cannot turn off the Rx timestamp logic if the device is
 	 * configured for Tx timestamping, we check if Rx timestamping is
@@ -255,42 +290,30 @@ void i40e_ptp_rx_hang(struct i40e_vsi *v
 	if (!(pf->flags & I40E_FLAG_PTP) || !pf->ptp_rx)
 		return;
 
-	prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+	spin_lock_bh(&pf->ptp_rx_lock);
 
-	/* Unless all four receive timestamp registers are latched, we are not
-	 * concerned about a possible PTP Rx hang, so just update the timeout
-	 * counter and exit.
-	 */
-	if (!(prttsyn_stat & ((I40E_PRTTSYN_STAT_1_RXT0_MASK <<
-			       I40E_PRTTSYN_STAT_1_RXT0_SHIFT) |
-			      (I40E_PRTTSYN_STAT_1_RXT1_MASK <<
-			       I40E_PRTTSYN_STAT_1_RXT1_SHIFT) |
-			      (I40E_PRTTSYN_STAT_1_RXT2_MASK <<
-			       I40E_PRTTSYN_STAT_1_RXT2_SHIFT) |
-			      (I40E_PRTTSYN_STAT_1_RXT3_MASK <<
-			       I40E_PRTTSYN_STAT_1_RXT3_SHIFT)))) {
-		pf->last_rx_ptp_check = jiffies;
-		return;
-	}
+	/* Update current latch times for Rx events */
+	i40e_ptp_get_rx_events(pf);
 
-	/* Determine the most recent watchdog or rx_timestamp event. */
-	rx_event = pf->last_rx_ptp_check;
-	for (n = 0; n < vsi->num_queue_pairs; n++) {
-		rx_ring = vsi->rx_rings[n];
-		if (time_after(rx_ring->last_rx_timestamp, rx_event))
-			rx_event = rx_ring->last_rx_timestamp;
+	/* Check all the currently latched Rx events and see whether they have
+	 * been latched for over a second. It is assumed that any timestamp
+	 * should have been cleared within this time, or else it was captured
+	 * for a dropped frame that the driver never received. Thus, we will
+	 * clear any timestamp that has been latched for over 1 second.
+	 */
+	for (i = 0; i < 4; i++) {
+		if ((pf->latch_event_flags & BIT(i)) &&
+		    time_is_before_jiffies(pf->latch_events[i] + HZ)) {
+			rd32(hw, I40E_PRTTSYN_RXTIME_H(i));
+			pf->latch_event_flags &= ~BIT(i);
+			pf->rx_hwtstamp_cleared++;
+			dev_warn(&pf->pdev->dev,
+				 "Clearing a missed Rx timestamp event for RXTIME[%d]\n",
+				 i);
+		}
 	}
 
-	/* Only need to read the high RXSTMP register to clear the lock */
-	if (time_is_before_jiffies(rx_event + 5 * HZ)) {
-		rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
-		rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
-		rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
-		rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
-		pf->last_rx_ptp_check = jiffies;
-		pf->rx_hwtstamp_cleared++;
-		WARN_ONCE(1, "Detected Rx timestamp register hang\n");
-	}
+	spin_unlock_bh(&pf->ptp_rx_lock);
 }
 
 /**
@@ -353,14 +376,25 @@ void i40e_ptp_rx_hwtstamp(struct i40e_pf
 
 	hw = &pf->hw;
 
-	prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
+	spin_lock_bh(&pf->ptp_rx_lock);
 
-	if (!(prttsyn_stat & BIT(index)))
+	/* Get current Rx events and update latch times */
+	prttsyn_stat = i40e_ptp_get_rx_events(pf);
+
+	/* TODO: Should we warn about missing Rx timestamp event? */
+	if (!(prttsyn_stat & BIT(index))) {
+		spin_unlock_bh(&pf->ptp_rx_lock);
 		return;
+	}
+
+	/* Clear the latched event since we're about to read its register */
+	pf->latch_event_flags &= ~BIT(index);
 
 	lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index));
 	hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index));
 
+	spin_unlock_bh(&pf->ptp_rx_lock);
+
 	ns = (((u64)hi) << 32) | lo;
 
 	i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns);
@@ -487,6 +521,8 @@ static int i40e_ptp_set_timestamp_mode(s
 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
 	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+		if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
+			return -ERANGE;
 		pf->ptp_rx = true;
 		tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK |
 			   I40E_PRTTSYN_CTL1_TSYNTYPE_V1 |
@@ -494,19 +530,26 @@ static int i40e_ptp_set_timestamp_mode(s
 		config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
-	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
-	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
-	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+		if (!(pf->flags & I40E_FLAG_PTP_L4_CAPABLE))
+			return -ERANGE;
+		/* fall through */
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
 		pf->ptp_rx = true;
 		tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK |
-			   I40E_PRTTSYN_CTL1_TSYNTYPE_V2 |
-			   I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
-		config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+			   I40E_PRTTSYN_CTL1_TSYNTYPE_V2;
+		if (pf->flags & I40E_FLAG_PTP_L4_CAPABLE) {
+			tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
+			config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+		} else {
+			config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
+		}
 		break;
 	case HWTSTAMP_FILTER_ALL:
 	default:
@@ -514,12 +557,15 @@ static int i40e_ptp_set_timestamp_mode(s
 	}
 
 	/* Clear out all 1588-related registers to clear and unlatch them. */
+	spin_lock_bh(&pf->ptp_rx_lock);
 	rd32(hw, I40E_PRTTSYN_STAT_0);
 	rd32(hw, I40E_PRTTSYN_TXTIME_H);
 	rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
 	rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
 	rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
 	rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
+	pf->latch_event_flags = 0;
+	spin_unlock_bh(&pf->ptp_rx_lock);
 
 	/* Enable/disable the Tx timestamp interrupt based on user input. */
 	regval = rd32(hw, I40E_PRTTSYN_CTL0);
@@ -658,10 +704,8 @@ void i40e_ptp_init(struct i40e_pf *pf)
 		return;
 	}
 
-	/* we have to initialize the lock first, since we can't control
-	 * when the user will enter the PHC device entry points
-	 */
-	spin_lock_init(&pf->tmreg_lock);
+	mutex_init(&pf->tmreg_lock);
+	spin_lock_init(&pf->ptp_rx_lock);
 
 	/* ensure we have a clock device */
 	err = i40e_ptp_create_clock(pf);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.c	2017-02-12 16:03:20.000000000 -0500
@@ -122,14 +122,10 @@ static int i40e_program_fdir_filter(stru
 	struct device *dev;
 	dma_addr_t dma;
 	u32 td_cmd = 0;
-	u16 delay = 0;
 	u16 i;
 
 	/* find existing FDIR VSI */
-	vsi = NULL;
-	for (i = 0; i < pf->num_alloc_vsi; i++)
-		if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR)
-			vsi = pf->vsi[i];
+	vsi = i40e_find_vsi_by_type(pf, I40E_VSI_FDIR);
 	if (!vsi)
 		return -ENOENT;
 
@@ -137,15 +133,11 @@ static int i40e_program_fdir_filter(stru
 	dev = tx_ring->dev;
 
 	/* we need two descriptors to add/del a filter and we can wait */
-	do {
-		if (I40E_DESC_UNUSED(tx_ring) > 1)
-			break;
+	for (i = I40E_FD_CLEAN_DELAY; I40E_DESC_UNUSED(tx_ring) < 2; i--) {
+		if (!i)
+			return -EAGAIN;
 		msleep_interruptible(1);
-		delay++;
-	} while (delay < I40E_FD_CLEAN_DELAY);
-
-	if (!(I40E_DESC_UNUSED(tx_ring) > 1))
-		return -EAGAIN;
+	}
 
 	dma = dma_map_single(dev, raw_packet,
 			     I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE);
@@ -335,22 +327,6 @@ static int i40e_add_del_fdir_tcpv4(struc
 	return err ? -EOPNOTSUPP : 0;
 }
 
-/**
- * i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for
- * a specific flow spec
- * @vsi: pointer to the targeted VSI
- * @fd_data: the flow director data required for the FDir descriptor
- * @add: true adds a filter, false removes it
- *
- * Returns 0 if the filters were successfully added or removed
- **/
-static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
-				    struct i40e_fdir_filter *fd_data,
-				    bool add)
-{
-	return -EOPNOTSUPP;
-}
-
 #define I40E_IP_DUMMY_PACKET_LEN 34
 /**
  * i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for
@@ -433,12 +409,6 @@ int i40e_add_del_fdir(struct i40e_vsi *v
 	case UDP_V4_FLOW:
 		ret = i40e_add_del_fdir_udpv4(vsi, input, add);
 		break;
-	case SCTP_V4_FLOW:
-		ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
-		break;
-	case IPV4_FLOW:
-		ret = i40e_add_del_fdir_ipv4(vsi, input, add);
-		break;
 	case IP_USER_FLOW:
 		switch (input->ip4_proto) {
 		case IPPROTO_TCP:
@@ -447,15 +417,16 @@ int i40e_add_del_fdir(struct i40e_vsi *v
 		case IPPROTO_UDP:
 			ret = i40e_add_del_fdir_udpv4(vsi, input, add);
 			break;
-		case IPPROTO_SCTP:
-			ret = i40e_add_del_fdir_sctpv4(vsi, input, add);
-			break;
-		default:
+		case IPPROTO_IP:
 			ret = i40e_add_del_fdir_ipv4(vsi, input, add);
 			break;
+		default:
+			/* We cannot support masking based on protocol */
+			goto unsupported_flow;
 		}
 		break;
 	default:
+unsupported_flow:
 		dev_info(&pf->pdev->dev, "Could not specify spec type %d\n",
 			 input->flow_type);
 		ret = -EINVAL;
@@ -645,7 +616,7 @@ u32 i40e_get_tx_pending(struct i40e_ring
 	return 0;
 }
 
-#define WB_STRIDE 0x3
+#define WB_STRIDE 4
 
 /**
  * i40e_clean_tx_irq - Reclaim resources after transmit completes
@@ -761,7 +732,7 @@ static bool i40e_clean_tx_irq(struct i40
 		unsigned int j = i40e_get_tx_pending(tx_ring, false);
 
 		if (budget &&
-		    ((j / (WB_STRIDE + 1)) == 0) && (j != 0) &&
+		    ((j / WB_STRIDE) == 0) && (j > 0) &&
 		    !test_bit(__I40E_DOWN, &vsi->state) &&
 		    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
 			tx_ring->arm_wb = true;
@@ -1246,7 +1217,6 @@ bool i40e_alloc_rx_buffers(struct i40e_r
 		 * because each write-back erases this info.
 		 */
 		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
-		rx_desc->read.hdr_addr = 0;
 
 		rx_desc++;
 		bi++;
@@ -1437,13 +1407,12 @@ void i40e_process_skb_fields(struct i40e
 	u64 qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
 	u32 rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
 			I40E_RXD_QW1_STATUS_SHIFT;
-	u32 rsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
+	u32 tsynvalid = rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK;
+	u32 tsyn = (rx_status & I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
 		   I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT;
 
-	if (unlikely(rsyn)) {
-		i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, rsyn);
-		rx_ring->last_rx_timestamp = jiffies;
-	}
+	if (unlikely(tsynvalid))
+		i40e_ptp_rx_hwtstamp(rx_ring->vsi->back, skb, tsyn);
 
 	i40e_rx_hash(rx_ring, rx_desc, skb, rx_ptype);
 
@@ -1767,7 +1736,6 @@ static int i40e_clean_rx_irq(struct i40e
 	while (likely(total_rx_packets < budget)) {
 		union i40e_rx_desc *rx_desc;
 		struct sk_buff *skb;
-		u32 rx_status;
 		u16 vlan_tag;
 		u8 rx_ptype;
 		u64 qword;
@@ -1781,21 +1749,13 @@ static int i40e_clean_rx_irq(struct i40e
 
 		rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-			   I40E_RXD_QW1_PTYPE_SHIFT;
-		rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
-			    I40E_RXD_QW1_STATUS_SHIFT;
-
-		if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
-			break;
-
 		/* status_error_len will always be zero for unused descriptors
 		 * because it's cleared in cleanup, and overlaps with hdr_addr
 		 * which is always zero because packet split isn't used, if the
 		 * hardware wrote DD then it will be non-zero
 		 */
-		if (!rx_desc->wb.qword1.status_error_len)
+		if (!i40e_test_staterr(rx_desc,
+				       BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
 			break;
 
 		/* This memory barrier is needed to keep us from reading
@@ -1829,6 +1789,10 @@ static int i40e_clean_rx_irq(struct i40e
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
 
+		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+			   I40E_RXD_QW1_PTYPE_SHIFT;
+
 		/* populate checksum, VLAN, and protocol */
 		i40e_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
@@ -2025,12 +1989,25 @@ int i40e_napi_poll(struct napi_struct *n
 
 	/* If work not completed, return budget and polling will return */
 	if (!clean_complete) {
+		const cpumask_t *aff_mask = &q_vector->affinity_mask;
+		int cpu_id = smp_processor_id();
+
+		/* It is possible that the interrupt affinity has changed but,
+		 * if the cpu is pegged at 100%, polling will never exit while
+		 * traffic continues and the interrupt will be stuck on this
+		 * cpu.  We check to make sure affinity is correct before we
+		 * continue to poll, otherwise we must stop polling so the
+		 * interrupt can move to the correct cpu.
+		 */
+		if (likely(cpumask_test_cpu(cpu_id, aff_mask) ||
+			   !(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))) {
 tx_only:
-		if (arm_wb) {
-			q_vector->tx.ring[0].tx_stats.tx_force_wb++;
-			i40e_enable_wb_on_itr(vsi, q_vector);
+			if (arm_wb) {
+				q_vector->tx.ring[0].tx_stats.tx_force_wb++;
+				i40e_enable_wb_on_itr(vsi, q_vector);
+			}
+			return budget;
 		}
-		return budget;
 	}
 
 	if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
@@ -2038,12 +2015,19 @@ tx_only:
 
 	/* Work is done so exit the polling mode and re-enable the interrupt */
 	napi_complete_done(napi, work_done);
-	if (vsi->back->flags & I40E_FLAG_MSIX_ENABLED) {
-		i40e_update_enable_itr(vsi, q_vector);
-	} else { /* Legacy mode */
+
+	/* If we're prematurely stopping polling to fix the interrupt
+	 * affinity we want to make sure polling starts back up so we
+	 * issue a call to i40e_force_wb which triggers a SW interrupt.
+	 */
+	if (!clean_complete)
+		i40e_force_wb(vsi, q_vector);
+	else if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED))
 		i40e_irq_dynamic_enable_icr0(vsi->back, false);
-	}
-	return 0;
+	else
+		i40e_update_enable_itr(vsi, q_vector);
+
+	return min(work_done, budget - 1);
 }
 
 /**
@@ -2716,9 +2700,7 @@ static inline void i40e_tx_map(struct i4
 	u32 td_tag = 0;
 	dma_addr_t dma;
 	u16 gso_segs;
-	u16 desc_count = 0;
-	bool tail_bump = true;
-	bool do_rs = false;
+	u16 desc_count = 1;
 
 	if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
 		td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -2801,8 +2783,7 @@ static inline void i40e_tx_map(struct i4
 		tx_bi = &tx_ring->tx_bi[i];
 	}
 
-	/* set next_to_watch value indicating a packet is present */
-	first->next_to_watch = tx_desc;
+	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
 
 	i++;
 	if (i == tx_ring->count)
@@ -2810,66 +2791,72 @@ static inline void i40e_tx_map(struct i4
 
 	tx_ring->next_to_use = i;
 
-	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
 	i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
+	/* write last descriptor with EOP bit */
+	td_cmd |= I40E_TX_DESC_CMD_EOP;
+
+	/* We can OR these values together as they both are checked against
+	 * 4 below and at this point desc_count will be used as a boolean value
+	 * after this if/else block.
+	 */
+	desc_count |= ++tx_ring->packet_stride;
+
 	/* Algorithm to optimize tail and RS bit setting:
-	 * if xmit_more is supported
-	 *	if xmit_more is true
-	 *		do not update tail and do not mark RS bit.
-	 *	if xmit_more is false and last xmit_more was false
-	 *		if every packet spanned less than 4 desc
-	 *			then set RS bit on 4th packet and update tail
-	 *			on every packet
-	 *		else
-	 *			update tail and set RS bit on every packet.
-	 *	if xmit_more is false and last_xmit_more was true
-	 *		update tail and set RS bit.
+	 * if queue is stopped
+	 *	mark RS bit
+	 *	reset packet counter
+	 * else if xmit_more is supported and is true
+	 *	advance packet counter to 4
+	 *	reset desc_count to 0
 	 *
-	 * Optimization: wmb to be issued only in case of tail update.
-	 * Also optimize the Descriptor WB path for RS bit with the same
-	 * algorithm.
+	 * if desc_count >= 4
+	 *	mark RS bit
+	 *	reset packet counter
+	 * if desc_count > 0
+	 *	update tail
 	 *
-	 * Note: If there are less than 4 packets
+	 * Note: If there are less than 4 descriptors
 	 * pending and interrupts were disabled the service task will
 	 * trigger a force WB.
 	 */
-	if (skb->xmit_more  &&
-	    !netif_xmit_stopped(txring_txq(tx_ring))) {
-		tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
-		tail_bump = false;
-	} else if (!skb->xmit_more &&
-		   !netif_xmit_stopped(txring_txq(tx_ring)) &&
-		   (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
-		   (tx_ring->packet_stride < WB_STRIDE) &&
-		   (desc_count < WB_STRIDE)) {
-		tx_ring->packet_stride++;
-	} else {
+	if (netif_xmit_stopped(txring_txq(tx_ring))) {
+		goto do_rs;
+	} else if (skb->xmit_more) {
+		/* set stride to arm on next packet and reset desc_count */
+		tx_ring->packet_stride = WB_STRIDE;
+		desc_count = 0;
+	} else if (desc_count >= WB_STRIDE) {
+do_rs:
+		/* write last descriptor with RS bit set */
+		td_cmd |= I40E_TX_DESC_CMD_RS;
 		tx_ring->packet_stride = 0;
-		tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
-		do_rs = true;
 	}
-	if (do_rs)
-		tx_ring->packet_stride = 0;
 
 	tx_desc->cmd_type_offset_bsz =
-			build_ctob(td_cmd, td_offset, size, td_tag) |
-			cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
-						  I40E_TX_DESC_CMD_EOP) <<
-						  I40E_TXD_QW1_CMD_SHIFT);
+			build_ctob(td_cmd, td_offset, size, td_tag);
+
+	/* Force memory writes to complete before letting h/w know there
+	 * are new descriptors to fetch.
+	 *
+	 * We also use this memory barrier to make certain all of the
+	 * status bits have been updated before next_to_watch is written.
+	 */
+	wmb();
+
+	/* set next_to_watch value indicating a packet is present */
+	first->next_to_watch = tx_desc;
 
 	/* notify HW of packet */
-	if (!tail_bump) {
-		prefetchw(tx_desc + 1);
-	} else {
-		/* 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 (desc_count) {
 		writel(i, 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();
 	}
+
 	return;
 
 dma_error:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_txrx.h	2017-02-12 16:03:20.000000000 -0500
@@ -173,26 +173,37 @@ static inline bool i40e_test_staterr(uni
 #define I40E_MAX_DATA_PER_TXD_ALIGNED \
 	(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))
 
-/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is
- * the value I40E_MAX_DATA_PER_TXD_ALIGNED.  It is needed due to the fact
- * that 12K is not a power of 2 and division is expensive.  It is used to
- * approximate the number of descriptors used per linear buffer.  Note
- * that this will overestimate in some cases as it doesn't account for the
- * fact that we will add up to 4K - 1 in aligning the 12K buffer, however
- * the error should not impact things much as large buffers usually mean
- * we will use fewer descriptors then there are frags in an skb.
+/**
+ * i40e_txd_use_count  - estimate the number of descriptors needed for Tx
+ * @size: transmit request size in bytes
+ *
+ * Due to hardware alignment restrictions (4K alignment), we need to
+ * assume that we can have no more than 12K of data per descriptor, even
+ * though each descriptor can take up to 16K - 1 bytes of aligned memory.
+ * Thus, we need to divide by 12K. But division is slow! Instead,
+ * we decompose the operation into shifts and one relatively cheap
+ * multiply operation.
+ *
+ * To divide by 12K, we first divide by 4K, then divide by 3:
+ *     To divide by 4K, shift right by 12 bits
+ *     To divide by 3, multiply by 85, then divide by 256
+ *     (Divide by 256 is done by shifting right by 8 bits)
+ * Finally, we add one to round up. Because 256 isn't an exact multiple of
+ * 3, we'll underestimate near each multiple of 12K. This is actually more
+ * accurate as we have 4K - 1 of wiggle room that we can fit into the last
+ * segment.  For our purposes this is accurate out to 1M which is orders of
+ * magnitude greater than our largest possible GSO size.
+ *
+ * This would then be implemented as:
+ *     return (((size >> 12) * 85) >> 8) + 1;
+ *
+ * Since multiplication and division are commutative, we can reorder
+ * operations into:
+ *     return ((size * 85) >> 20) + 1;
  */
 static inline unsigned int i40e_txd_use_count(unsigned int size)
 {
-	const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED;
-	const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max;
-	unsigned int adjust = ~(u32)0;
-
-	/* if we rounded up on the reciprocal pull down the adjustment */
-	if ((max * reciprocal) > adjust)
-		adjust = ~(u32)(reciprocal - 1);
-
-	return (u32)((((u64)size * reciprocal) + adjust) >> 32);
+	return ((size * 85) >> 20) + 1;
 }
 
 /* Tx Descriptors needed, worst case */
@@ -307,15 +318,12 @@ struct i40e_ring {
 	u8 atr_sample_rate;
 	u8 atr_count;
 
-	unsigned long last_rx_timestamp;
-
 	bool ring_active;		/* is ring online or not */
 	bool arm_wb;		/* do something to arm write back */
 	u8 packet_stride;
 
 	u16 flags;
 #define I40E_TXR_FLAGS_WB_ON_ITR	BIT(0)
-#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
 
 	/* stats structs */
 	struct i40e_queue_stats	stats;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_type.h	2017-02-12 16:03:20.000000000 -0500
@@ -90,14 +90,23 @@ enum i40e_debug_mask {
 	I40E_DEBUG_ALL			= 0xFFFFFFFF
 };
 
-#define I40E_MDIO_STCODE                0
-#define I40E_MDIO_OPCODE_ADDRESS        0
-#define I40E_MDIO_OPCODE_WRITE          I40E_MASK(1, \
+#define I40E_MDIO_CLAUSE22_STCODE_MASK	I40E_MASK(1, \
+						  I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_MDIO_CLAUSE22_OPCODE_WRITE_MASK	I40E_MASK(1, \
 						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_READ_INC_ADDR  I40E_MASK(2, \
+#define I40E_MDIO_CLAUSE22_OPCODE_READ_MASK	I40E_MASK(2, \
 						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
-#define I40E_MDIO_OPCODE_READ           I40E_MASK(3, \
+
+#define I40E_MDIO_CLAUSE45_STCODE_MASK	I40E_MASK(0, \
+						  I40E_GLGEN_MSCA_STCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_ADDRESS_MASK	I40E_MASK(0, \
 						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_WRITE_MASK	I40E_MASK(1, \
+						  I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_READ_INC_ADDR_MASK	I40E_MASK(2, \
+						I40E_GLGEN_MSCA_OPCODE_SHIFT)
+#define I40E_MDIO_CLAUSE45_OPCODE_READ_MASK	I40E_MASK(3, \
+						I40E_GLGEN_MSCA_OPCODE_SHIFT)
 
 #define I40E_PHY_COM_REG_PAGE                   0x1E
 #define I40E_PHY_LED_LINK_MODE_MASK             0xF0
@@ -204,47 +213,59 @@ struct i40e_link_status {
 #define I40E_MODULE_TYPE_1000BASE_T	0x08
 };
 
-enum i40e_aq_capabilities_phy_type {
-	I40E_CAP_PHY_TYPE_SGMII		  = BIT(I40E_PHY_TYPE_SGMII),
-	I40E_CAP_PHY_TYPE_1000BASE_KX	  = BIT(I40E_PHY_TYPE_1000BASE_KX),
-	I40E_CAP_PHY_TYPE_10GBASE_KX4	  = BIT(I40E_PHY_TYPE_10GBASE_KX4),
-	I40E_CAP_PHY_TYPE_10GBASE_KR	  = BIT(I40E_PHY_TYPE_10GBASE_KR),
-	I40E_CAP_PHY_TYPE_40GBASE_KR4	  = BIT(I40E_PHY_TYPE_40GBASE_KR4),
-	I40E_CAP_PHY_TYPE_XAUI		  = BIT(I40E_PHY_TYPE_XAUI),
-	I40E_CAP_PHY_TYPE_XFI		  = BIT(I40E_PHY_TYPE_XFI),
-	I40E_CAP_PHY_TYPE_SFI		  = BIT(I40E_PHY_TYPE_SFI),
-	I40E_CAP_PHY_TYPE_XLAUI		  = BIT(I40E_PHY_TYPE_XLAUI),
-	I40E_CAP_PHY_TYPE_XLPPI		  = BIT(I40E_PHY_TYPE_XLPPI),
-	I40E_CAP_PHY_TYPE_40GBASE_CR4_CU  = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU),
-	I40E_CAP_PHY_TYPE_10GBASE_CR1_CU  = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU),
-	I40E_CAP_PHY_TYPE_10GBASE_AOC	  = BIT(I40E_PHY_TYPE_10GBASE_AOC),
-	I40E_CAP_PHY_TYPE_40GBASE_AOC	  = BIT(I40E_PHY_TYPE_40GBASE_AOC),
-	I40E_CAP_PHY_TYPE_100BASE_TX	  = BIT(I40E_PHY_TYPE_100BASE_TX),
-	I40E_CAP_PHY_TYPE_1000BASE_T	  = BIT(I40E_PHY_TYPE_1000BASE_T),
-	I40E_CAP_PHY_TYPE_10GBASE_T	  = BIT(I40E_PHY_TYPE_10GBASE_T),
-	I40E_CAP_PHY_TYPE_10GBASE_SR	  = BIT(I40E_PHY_TYPE_10GBASE_SR),
-	I40E_CAP_PHY_TYPE_10GBASE_LR	  = BIT(I40E_PHY_TYPE_10GBASE_LR),
-	I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU),
-	I40E_CAP_PHY_TYPE_10GBASE_CR1	  = BIT(I40E_PHY_TYPE_10GBASE_CR1),
-	I40E_CAP_PHY_TYPE_40GBASE_CR4	  = BIT(I40E_PHY_TYPE_40GBASE_CR4),
-	I40E_CAP_PHY_TYPE_40GBASE_SR4	  = BIT(I40E_PHY_TYPE_40GBASE_SR4),
-	I40E_CAP_PHY_TYPE_40GBASE_LR4	  = BIT(I40E_PHY_TYPE_40GBASE_LR4),
-	I40E_CAP_PHY_TYPE_1000BASE_SX	  = BIT(I40E_PHY_TYPE_1000BASE_SX),
-	I40E_CAP_PHY_TYPE_1000BASE_LX	  = BIT(I40E_PHY_TYPE_1000BASE_LX),
-	I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL =
-					 BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL),
-	I40E_CAP_PHY_TYPE_20GBASE_KR2	  = BIT(I40E_PHY_TYPE_20GBASE_KR2)
-};
-
 struct i40e_phy_info {
 	struct i40e_link_status link_info;
 	struct i40e_link_status link_info_old;
 	bool get_link_info;
 	enum i40e_media_type media_type;
 	/* all the phy types the NVM is capable of */
-	enum i40e_aq_capabilities_phy_type phy_types;
+	u64 phy_types;
 };
 
+#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII)
+#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX)
+#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4)
+#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR)
+#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4)
+#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI)
+#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI)
+#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI)
+#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI)
+#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR)
+#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR)
+#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4)
+#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX)
+#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \
+				BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL)
+#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2)
+/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some
+ * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit
+ * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So,
+ * a shift is needed to adjust for this with values larger than 31. The
+ * only affected values are I40E_PHY_TYPE_25GBASE_*.
+ */
+#define I40E_PHY_TYPE_OFFSET 1
+#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \
+					     I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \
+					     I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \
+					     I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
+					     I40E_PHY_TYPE_OFFSET)
 #define I40E_HW_CAP_MAX_GPIO			30
 /* Capabilities of a PF or a VF or the whole device */
 struct i40e_hw_capabilities {
@@ -254,6 +275,10 @@ struct i40e_hw_capabilities {
 #define I40E_NVM_IMAGE_TYPE_UDP_CLOUD	0x3
 
 	u32  management_mode;
+	u32  mng_protocols_over_mctp;
+#define I40E_MNG_PROTOCOL_PLDM		0x2
+#define I40E_MNG_PROTOCOL_OEM_COMMANDS	0x4
+#define I40E_MNG_PROTOCOL_NCSI		0x8
 	u32  npar_enable;
 	u32  os2bmc;
 	u32  valid_functions;
@@ -366,6 +391,7 @@ enum i40e_nvmupd_state {
 	I40E_NVMUPD_STATE_WRITING,
 	I40E_NVMUPD_STATE_INIT_WAIT,
 	I40E_NVMUPD_STATE_WRITE_WAIT,
+	I40E_NVMUPD_STATE_ERROR
 };
 
 /* nvm_access definition and its masks/shifts need to be accessible to
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl.h	2017-02-12 16:03:20.000000000 -0500
@@ -165,6 +165,10 @@ struct i40e_virtchnl_vsi_resource {
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000
 #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM	0X00100000
 
+#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
+				    I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
+				    I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
 struct i40e_virtchnl_vf_resource {
 	u16 num_vsis;
 	u16 num_queue_pairs;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c	2017-02-12 16:03:20.000000000 -0500
@@ -674,6 +674,7 @@ static int i40e_alloc_vsi_res(struct i40
 	}
 	if (type == I40E_VSI_SRIOV) {
 		u64 hena = i40e_pf_get_default_rss_hena(pf);
+		u8 broadcast[ETH_ALEN];
 
 		vf->lan_vsi_idx = vsi->idx;
 		vf->lan_vsi_id = vsi->id;
@@ -686,17 +687,23 @@ static int i40e_alloc_vsi_res(struct i40
 		if (vf->port_vlan_id)
 			i40e_vsi_add_pvid(vsi, vf->port_vlan_id);
 
-		spin_lock_bh(&vsi->mac_filter_list_lock);
+		spin_lock_bh(&vsi->mac_filter_hash_lock);
 		if (is_valid_ether_addr(vf->default_lan_addr.addr)) {
 			f = i40e_add_filter(vsi, vf->default_lan_addr.addr,
-				       vf->port_vlan_id ? vf->port_vlan_id : -1,
-				       true, false);
+				       vf->port_vlan_id ?
+				       vf->port_vlan_id : -1);
 			if (!f)
 				dev_info(&pf->pdev->dev,
 					 "Could not add MAC filter %pM for VF %d\n",
 					vf->default_lan_addr.addr, vf->vf_id);
 		}
-		spin_unlock_bh(&vsi->mac_filter_list_lock);
+		eth_broadcast_addr(broadcast);
+		f = i40e_add_filter(vsi, broadcast,
+				    vf->port_vlan_id ? vf->port_vlan_id : -1);
+		if (!f)
+			dev_info(&pf->pdev->dev,
+				 "Could not allocate VF broadcast filter\n");
+		spin_unlock_bh(&vsi->mac_filter_hash_lock);
 		i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id),
 				  (u32)hena);
 		i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(1, vf->vf_id),
@@ -811,6 +818,7 @@ static void i40e_free_vf_res(struct i40e
 		i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]);
 		vf->lan_vsi_idx = 0;
 		vf->lan_vsi_id = 0;
+		vf->num_mac = 0;
 	}
 	msix_vf = pf->hw.func_caps.num_msix_vectors_vf;
 
@@ -990,7 +998,7 @@ void i40e_reset_vf(struct i40e_vf *vf, b
 	if (vf->lan_vsi_idx == 0)
 		goto complete_reset;
 
-	i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false);
+	i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
 complete_reset:
 	/* reallocate VF resources to reset the VSI state */
 	i40e_free_vf_res(vf);
@@ -1031,8 +1039,7 @@ void i40e_free_vfs(struct i40e_pf *pf)
 	i40e_notify_client_of_vf_enable(pf, 0);
 	for (i = 0; i < pf->num_alloc_vfs; i++)
 		if (test_bit(I40E_VF_STAT_INIT, &pf->vf[i].vf_states))
-			i40e_vsi_control_rings(pf->vsi[pf->vf[i].lan_vsi_idx],
-					       false);
+			i40e_vsi_stop_rings(pf->vsi[pf->vf[i].lan_vsi_idx]);
 
 	/* Disable IOV before freeing resources. This lets any VF drivers
 	 * running in the host get themselves cleaned up before we yank
@@ -1449,9 +1456,9 @@ static void i40e_vc_reset_vf_msg(struct
 static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
 {
 	struct i40e_mac_filter *f;
-	int num_vlans = 0;
+	int num_vlans = 0, bkt;
 
-	list_for_each_entry(f, &vsi->mac_filter_list, list) {
+	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
 		if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID)
 			num_vlans++;
 	}
@@ -1481,6 +1488,7 @@ static int i40e_vc_config_promiscuous_mo
 	struct i40e_vsi *vsi;
 	bool alluni = false;
 	int aq_err = 0;
+	int bkt;
 
 	vsi = i40e_find_vsi_from_id(pf, info->vsi_id);
 	if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
@@ -1507,7 +1515,7 @@ static int i40e_vc_config_promiscuous_mo
 							    vf->port_vlan_id,
 							    NULL);
 	} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) {
-		list_for_each_entry(f, &vsi->mac_filter_list, list) {
+		hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
 			if (f->vlan < 0 || f->vlan > I40E_MAX_VLANID)
 				continue;
 			aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw,
@@ -1535,7 +1543,7 @@ static int i40e_vc_config_promiscuous_mo
 				vf->vf_id,
 				i40e_stat_str(&pf->hw, aq_ret),
 				i40e_aq_str(&pf->hw, aq_err));
-			goto error_param_int;
+			goto error_param;
 		}
 	}
 
@@ -1557,7 +1565,7 @@ static int i40e_vc_config_promiscuous_mo
 							    vf->port_vlan_id,
 							    NULL);
 	} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) {
-		list_for_each_entry(f, &vsi->mac_filter_list, list) {
+		hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
 			aq_ret = 0;
 			if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID) {
 				aq_ret =
@@ -1580,15 +1588,16 @@ static int i40e_vc_config_promiscuous_mo
 							     allmulti, NULL,
 							     true);
 		aq_err = pf->hw.aq.asq_last_status;
-		if (aq_ret)
+		if (aq_ret) {
 			dev_err(&pf->pdev->dev,
 				"VF %d failed to set unicast promiscuous mode %8.8x err %s aq_err %s\n",
 				vf->vf_id, info->flags,
 				i40e_stat_str(&pf->hw, aq_ret),
 				i40e_aq_str(&pf->hw, aq_err));
+			goto error_param;
+		}
 	}
 
-error_param_int:
 	if (!aq_ret) {
 		dev_info(&pf->pdev->dev,
 			 "VF %d successfully set unicast promiscuous mode\n",
@@ -1757,7 +1766,7 @@ static int i40e_vc_enable_queues_msg(str
 		goto error_param;
 	}
 
-	if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], true))
+	if (i40e_vsi_start_rings(pf->vsi[vf->lan_vsi_idx]))
 		aq_ret = I40E_ERR_TIMEOUT;
 error_param:
 	/* send the response to the VF */
@@ -1796,8 +1805,7 @@ static int i40e_vc_disable_queues_msg(st
 		goto error_param;
 	}
 
-	if (i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_idx], false))
-		aq_ret = I40E_ERR_TIMEOUT;
+	i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
 
 error_param:
 	/* send the response to the VF */
@@ -1927,20 +1935,18 @@ static int i40e_vc_add_mac_addr_msg(stru
 	/* Lock once, because all function inside for loop accesses VSI's
 	 * MAC filter list which needs to be protected using same lock.
 	 */
-	spin_lock_bh(&vsi->mac_filter_list_lock);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
 
 	/* add new addresses to the list */
 	for (i = 0; i < al->num_elements; i++) {
 		struct i40e_mac_filter *f;
 
-		f = i40e_find_mac(vsi, al->list[i].addr, true, false);
+		f = i40e_find_mac(vsi, al->list[i].addr);
 		if (!f) {
 			if (i40e_is_vsi_in_vlan(vsi))
-				f = i40e_put_mac_in_vlan(vsi, al->list[i].addr,
-							 true, false);
+				f = i40e_put_mac_in_vlan(vsi, al->list[i].addr);
 			else
-				f = i40e_add_filter(vsi, al->list[i].addr, -1,
-						    true, false);
+				f = i40e_add_filter(vsi, al->list[i].addr, -1);
 		}
 
 		if (!f) {
@@ -1948,13 +1954,13 @@ static int i40e_vc_add_mac_addr_msg(stru
 				"Unable to add MAC filter %pM for VF %d\n",
 				 al->list[i].addr, vf->vf_id);
 			ret = I40E_ERR_PARAM;
-			spin_unlock_bh(&vsi->mac_filter_list_lock);
+			spin_unlock_bh(&vsi->mac_filter_hash_lock);
 			goto error_param;
 		} else {
 			vf->num_mac++;
 		}
 	}
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	/* program the updated filter list */
 	ret = i40e_sync_vsi_filters(vsi);
@@ -2003,18 +2009,18 @@ static int i40e_vc_del_mac_addr_msg(stru
 	}
 	vsi = pf->vsi[vf->lan_vsi_idx];
 
-	spin_lock_bh(&vsi->mac_filter_list_lock);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
 	/* delete addresses from the list */
 	for (i = 0; i < al->num_elements; i++)
-		if (i40e_del_mac_all_vlan(vsi, al->list[i].addr, true, false)) {
+		if (i40e_del_mac_all_vlan(vsi, al->list[i].addr)) {
 			ret = I40E_ERR_INVALID_MAC_ADDR;
-			spin_unlock_bh(&vsi->mac_filter_list_lock);
+			spin_unlock_bh(&vsi->mac_filter_hash_lock);
 			goto error_param;
 		} else {
 			vf->num_mac--;
 		}
 
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	/* program the updated filter list */
 	ret = i40e_sync_vsi_filters(vsi);
@@ -2139,9 +2145,8 @@ static int i40e_vc_remove_vlan_msg(struc
 	}
 
 	for (i = 0; i < vfl->num_elements; i++) {
-		int ret = i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]);
-		if (!ret)
-			vf->num_vlan--;
+		i40e_vsi_kill_vlan(vsi, vfl->vlan_id[i]);
+		vf->num_vlan--;
 
 		if (test_bit(I40E_VF_STAT_UC_PROMISC, &vf->vf_states))
 			i40e_aq_set_vsi_uc_promisc_on_vlan(&pf->hw, vsi->seid,
@@ -2153,11 +2158,6 @@ static int i40e_vc_remove_vlan_msg(struc
 							   false,
 							   vfl->vlan_id[i],
 							   NULL);
-
-		if (ret)
-			dev_err(&pf->pdev->dev,
-				"Unable to delete VLAN filter %d for VF %d, error %d\n",
-				vfl->vlan_id[i], vf->vf_id, ret);
 	}
 
 error_param:
@@ -2689,6 +2689,7 @@ int i40e_ndo_set_vf_mac(struct net_devic
 	struct i40e_mac_filter *f;
 	struct i40e_vf *vf;
 	int ret = 0;
+	int bkt;
 
 	/* validate the request */
 	if (vf_id >= pf->num_alloc_vfs) {
@@ -2715,23 +2716,22 @@ int i40e_ndo_set_vf_mac(struct net_devic
 	}
 
 	/* Lock once because below invoked function add/del_filter requires
-	 * mac_filter_list_lock to be held
+	 * mac_filter_hash_lock to be held
 	 */
-	spin_lock_bh(&vsi->mac_filter_list_lock);
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
 
 	/* delete the temporary mac address */
 	if (!is_zero_ether_addr(vf->default_lan_addr.addr))
 		i40e_del_filter(vsi, vf->default_lan_addr.addr,
-				vf->port_vlan_id ? vf->port_vlan_id : -1,
-				true, false);
+				vf->port_vlan_id ? vf->port_vlan_id : -1);
 
 	/* Delete all the filters for this VSI - we're going to kill it
 	 * anyway.
 	 */
-	list_for_each_entry(f, &vsi->mac_filter_list, list)
-		i40e_del_filter(vsi, f->macaddr, f->vlan, true, false);
+	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist)
+		i40e_del_filter(vsi, f->macaddr, f->vlan);
 
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
 	dev_info(&pf->pdev->dev, "Setting MAC %pM on VF %d\n", mac, vf_id);
 	/* program mac filter */
@@ -2766,7 +2766,6 @@ int i40e_ndo_set_vf_port_vlan(struct net
 	u16 vlanprio = vlan_id | (qos << I40E_VLAN_PRIORITY_SHIFT);
 	struct i40e_netdev_priv *np = netdev_priv(netdev);
 	struct i40e_pf *pf = np->vsi->back;
-	bool is_vsi_in_vlan = false;
 	struct i40e_vsi *vsi;
 	struct i40e_vf *vf;
 	int ret = 0;
@@ -2803,11 +2802,10 @@ int i40e_ndo_set_vf_port_vlan(struct net
 		/* duplicate request, so just return success */
 		goto error_pvid;
 
-	spin_lock_bh(&vsi->mac_filter_list_lock);
-	is_vsi_in_vlan = i40e_is_vsi_in_vlan(vsi);
-	spin_unlock_bh(&vsi->mac_filter_list_lock);
+	/* Locked once because multiple functions below iterate list */
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
 
-	if (le16_to_cpu(vsi->info.pvid) == 0 && is_vsi_in_vlan) {
+	if (le16_to_cpu(vsi->info.pvid) == 0 && i40e_is_vsi_in_vlan(vsi)) {
 		dev_err(&pf->pdev->dev,
 			"VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",
 			vf_id);
@@ -2830,19 +2828,23 @@ int i40e_ndo_set_vf_port_vlan(struct net
 	 */
 	if ((!(vlan_id || qos) ||
 	    vlanprio != le16_to_cpu(vsi->info.pvid)) &&
-	    vsi->info.pvid)
-		ret = i40e_vsi_add_vlan(vsi, I40E_VLAN_ANY);
-
-	if (vsi->info.pvid) {
-		/* kill old VLAN */
-		ret = i40e_vsi_kill_vlan(vsi, (le16_to_cpu(vsi->info.pvid) &
-					       VLAN_VID_MASK));
+	    vsi->info.pvid) {
+		ret = i40e_add_vlan_all_mac(vsi, I40E_VLAN_ANY);
 		if (ret) {
 			dev_info(&vsi->back->pdev->dev,
-				 "remove VLAN failed, ret=%d, aq_err=%d\n",
-				 ret, pf->hw.aq.asq_last_status);
+				 "add VF VLAN failed, ret=%d aq_err=%d\n", ret,
+				 vsi->back->hw.aq.asq_last_status);
+			spin_unlock_bh(&vsi->mac_filter_hash_lock);
+			goto error_pvid;
 		}
 	}
+
+	if (vsi->info.pvid) {
+		/* remove all filters on the old VLAN */
+		i40e_rm_vlan_all_mac(vsi, (le16_to_cpu(vsi->info.pvid) &
+					   VLAN_VID_MASK));
+	}
+
 	if (vlan_id || qos)
 		ret = i40e_vsi_add_pvid(vsi, vlanprio);
 	else
@@ -2852,24 +2854,30 @@ int i40e_ndo_set_vf_port_vlan(struct net
 		dev_info(&pf->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
 			 vlan_id, qos, vf_id);
 
-		/* add new VLAN filter */
-		ret = i40e_vsi_add_vlan(vsi, vlan_id);
+		/* add new VLAN filter for each MAC */
+		ret = i40e_add_vlan_all_mac(vsi, vlan_id);
 		if (ret) {
 			dev_info(&vsi->back->pdev->dev,
 				 "add VF VLAN failed, ret=%d aq_err=%d\n", ret,
 				 vsi->back->hw.aq.asq_last_status);
+			spin_unlock_bh(&vsi->mac_filter_hash_lock);
 			goto error_pvid;
 		}
-		/* Kill non-vlan MAC filters - ignore error return since
-		 * there might not be any non-vlan MAC filters.
-		 */
-		i40e_vsi_kill_vlan(vsi, I40E_VLAN_ANY);
+
+		/* remove the previously added non-VLAN MAC filters */
+		i40e_rm_vlan_all_mac(vsi, I40E_VLAN_ANY);
 	}
 
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+	/* Schedule the worker thread to take care of applying changes */
+	i40e_service_event_schedule(vsi->back);
+
 	if (ret) {
 		dev_err(&pf->pdev->dev, "Unable to update VF vsi context\n");
 		goto error_pvid;
 	}
+
 	/* The Port VLAN needs to be saved across resets the same as the
 	 * default LAN MAC address.
 	 */
@@ -2926,6 +2934,9 @@ int i40e_ndo_set_vf_bw(struct net_device
 	case I40E_LINK_SPEED_40GB:
 		speed = 40000;
 		break;
+	case I40E_LINK_SPEED_25GB:
+		speed = 25000;
+		break;
 	case I40E_LINK_SPEED_20GB:
 		speed = 20000;
 		break;
@@ -2940,7 +2951,7 @@ int i40e_ndo_set_vf_bw(struct net_device
 	}
 
 	if (max_tx_rate > speed) {
-		dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.",
+		dev_err(&pf->pdev->dev, "Invalid max tx rate %d specified for VF %d.\n",
 			max_tx_rate, vf->vf_id);
 		ret = -EINVAL;
 		goto error;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq.c	2017-02-12 16:03:20.000000000 -0500
@@ -912,11 +912,11 @@ i40e_status i40evf_clean_arq_element(str
 	desc = I40E_ADMINQ_DESC(hw->aq.arq, ntc);
 	desc_idx = ntc;
 
+	hw->aq.arq_last_status =
+		(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
 	flags = le16_to_cpu(desc->flags);
 	if (flags & I40E_AQ_FLAG_ERR) {
 		ret_code = I40E_ERR_ADMIN_QUEUE_ERROR;
-		hw->aq.arq_last_status =
-			(enum i40e_admin_queue_err)le16_to_cpu(desc->retval);
 		i40e_debug(hw,
 			   I40E_DEBUG_AQ_MESSAGE,
 			   "AQRX: Event received with error 0x%X.\n",
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h	2017-02-12 16:03:20.000000000 -0500
@@ -1639,6 +1639,10 @@ enum i40e_aq_phy_type {
 	I40E_PHY_TYPE_1000BASE_LX		= 0x1C,
 	I40E_PHY_TYPE_1000BASE_T_OPTICAL	= 0x1D,
 	I40E_PHY_TYPE_20GBASE_KR2		= 0x1E,
+	I40E_PHY_TYPE_25GBASE_KR		= 0x1F,
+	I40E_PHY_TYPE_25GBASE_CR		= 0x20,
+	I40E_PHY_TYPE_25GBASE_SR		= 0x21,
+	I40E_PHY_TYPE_25GBASE_LR		= 0x22,
 	I40E_PHY_TYPE_MAX
 };
 
@@ -1647,6 +1651,7 @@ enum i40e_aq_phy_type {
 #define I40E_LINK_SPEED_10GB_SHIFT	0x3
 #define I40E_LINK_SPEED_40GB_SHIFT	0x4
 #define I40E_LINK_SPEED_20GB_SHIFT	0x5
+#define I40E_LINK_SPEED_25GB_SHIFT	0x6
 
 enum i40e_aq_link_speed {
 	I40E_LINK_SPEED_UNKNOWN	= 0,
@@ -1654,7 +1659,8 @@ enum i40e_aq_link_speed {
 	I40E_LINK_SPEED_1GB	= BIT(I40E_LINK_SPEED_1000MB_SHIFT),
 	I40E_LINK_SPEED_10GB	= BIT(I40E_LINK_SPEED_10GB_SHIFT),
 	I40E_LINK_SPEED_40GB	= BIT(I40E_LINK_SPEED_40GB_SHIFT),
-	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT)
+	I40E_LINK_SPEED_20GB	= BIT(I40E_LINK_SPEED_20GB_SHIFT),
+	I40E_LINK_SPEED_25GB	= BIT(I40E_LINK_SPEED_25GB_SHIFT),
 };
 
 struct i40e_aqc_module_desc {
@@ -1677,6 +1683,8 @@ struct i40e_aq_get_phy_abilities_resp {
 #define I40E_AQ_PHY_LINK_ENABLED	0x08
 #define I40E_AQ_PHY_AN_ENABLED		0x10
 #define I40E_AQ_PHY_FLAG_MODULE_QUAL	0x20
+#define I40E_AQ_PHY_FEC_ABILITY_KR	0x40
+#define I40E_AQ_PHY_FEC_ABILITY_RS	0x80
 	__le16	eee_capability;
 #define I40E_AQ_EEE_100BASE_TX		0x0002
 #define I40E_AQ_EEE_1000BASE_T		0x0004
@@ -1687,7 +1695,22 @@ struct i40e_aq_get_phy_abilities_resp {
 	__le32	eeer_val;
 	u8	d3_lpan;
 #define I40E_AQ_SET_PHY_D3_LPAN_ENA	0x01
-	u8	reserved[3];
+	u8	phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08
+	u8	fec_cfg_curr_mod_ext_info;
+#define I40E_AQ_ENABLE_FEC_KR		0x01
+#define I40E_AQ_ENABLE_FEC_RS		0x02
+#define I40E_AQ_REQUEST_FEC_KR		0x04
+#define I40E_AQ_REQUEST_FEC_RS		0x08
+#define I40E_AQ_ENABLE_FEC_AUTO		0x10
+#define I40E_AQ_FEC
+#define I40E_AQ_MODULE_TYPE_EXT_MASK	0xE0
+#define I40E_AQ_MODULE_TYPE_EXT_SHIFT	5
+
+	u8	ext_comp_code;
 	u8	phy_id[4];
 	u8	module_type[3];
 	u8	qualified_module_count;
@@ -1709,7 +1732,20 @@ struct i40e_aq_set_phy_config { /* same
 	__le16	eee_capability;
 	__le32	eeer;
 	u8	low_power_ctrl;
-	u8	reserved[3];
+	u8	phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR	0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR	0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR	0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR	0x08
+	u8	fec_config;
+#define I40E_AQ_SET_FEC_ABILITY_KR	BIT(0)
+#define I40E_AQ_SET_FEC_ABILITY_RS	BIT(1)
+#define I40E_AQ_SET_FEC_REQUEST_KR	BIT(2)
+#define I40E_AQ_SET_FEC_REQUEST_RS	BIT(3)
+#define I40E_AQ_SET_FEC_AUTO		BIT(4)
+#define I40E_AQ_PHY_FEC_CONFIG_SHIFT	0x0
+#define I40E_AQ_PHY_FEC_CONFIG_MASK	(0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
+	u8	reserved;
 };
 
 I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1789,9 +1825,18 @@ struct i40e_aqc_get_link_status {
 #define I40E_AQ_LINK_TX_DRAINED		0x01
 #define I40E_AQ_LINK_TX_FLUSHED		0x03
 #define I40E_AQ_LINK_FORCED_40G		0x10
+/* 25G Error Codes */
+#define I40E_AQ_25G_NO_ERR		0X00
+#define I40E_AQ_25G_NOT_PRESENT		0X01
+#define I40E_AQ_25G_NVM_CRC_ERR		0X02
+#define I40E_AQ_25G_SBUS_UCODE_ERR	0X03
+#define I40E_AQ_25G_SERDES_UCODE_ERR	0X04
+#define I40E_AQ_25G_NIMB_UCODE_ERR	0X05
 	u8	loopback; /* use defines from i40e_aqc_set_lb_mode */
 	__le16	max_frame_size;
 	u8	config;
+#define I40E_AQ_CONFIG_FEC_KR_ENA	0x01
+#define I40E_AQ_CONFIG_FEC_RS_ENA	0x02
 #define I40E_AQ_CONFIG_CRC_ENA		0x04
 #define I40E_AQ_CONFIG_PACING_MASK	0x78
 	u8	external_power_ability;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_common.c	2017-02-12 16:03:20.000000000 -0500
@@ -53,6 +53,8 @@ i40e_status i40e_set_mac_type(struct i40
 		case I40E_DEV_ID_10G_BASE_T4:
 		case I40E_DEV_ID_20G_KR2:
 		case I40E_DEV_ID_20G_KR2_A:
+		case I40E_DEV_ID_25G_B:
+		case I40E_DEV_ID_25G_SFP28:
 			hw->mac.type = I40E_MAC_XL710;
 			break;
 		case I40E_DEV_ID_SFP_X722:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_devids.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_devids.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_devids.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_devids.h	2017-02-12 16:03:20.000000000 -0500
@@ -39,6 +39,8 @@
 #define I40E_DEV_ID_20G_KR2		0x1587
 #define I40E_DEV_ID_20G_KR2_A		0x1588
 #define I40E_DEV_ID_10G_BASE_T4		0x1589
+#define I40E_DEV_ID_25G_B		0x158A
+#define I40E_DEV_ID_25G_SFP28		0x158B
 #define I40E_DEV_ID_VF			0x154C
 #define I40E_DEV_ID_VF_HV		0x1571
 #define I40E_DEV_ID_SFP_X722		0x37D0
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_prototype.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_prototype.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_prototype.h	2017-02-12 16:03:20.000000000 -0500
@@ -115,6 +115,10 @@ i40e_status i40e_read_phy_register(struc
 				   u16 reg, u8 phy_addr, u16 *value);
 i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
 				    u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+				   u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
+				    u8 phy_addr, u16 value);
 u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
 i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
 				    u32 time, u32 interval);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.c	2017-02-12 16:03:20.000000000 -0500
@@ -150,7 +150,7 @@ u32 i40evf_get_tx_pending(struct i40e_ri
 	return 0;
 }
 
-#define WB_STRIDE 0x3
+#define WB_STRIDE 4
 
 /**
  * i40e_clean_tx_irq - Reclaim resources after transmit completes
@@ -266,7 +266,7 @@ static bool i40e_clean_tx_irq(struct i40
 		unsigned int j = i40evf_get_tx_pending(tx_ring, false);
 
 		if (budget &&
-		    ((j / (WB_STRIDE + 1)) == 0) && (j > 0) &&
+		    ((j / WB_STRIDE) == 0) && (j > 0) &&
 		    !test_bit(__I40E_DOWN, &vsi->state) &&
 		    (I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
 			tx_ring->arm_wb = true;
@@ -705,7 +705,6 @@ bool i40evf_alloc_rx_buffers(struct i40e
 		 * because each write-back erases this info.
 		 */
 		rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
-		rx_desc->read.hdr_addr = 0;
 
 		rx_desc++;
 		bi++;
@@ -1209,7 +1208,6 @@ static int i40e_clean_rx_irq(struct i40e
 	while (likely(total_rx_packets < budget)) {
 		union i40e_rx_desc *rx_desc;
 		struct sk_buff *skb;
-		u32 rx_status;
 		u16 vlan_tag;
 		u8 rx_ptype;
 		u64 qword;
@@ -1223,21 +1221,13 @@ static int i40e_clean_rx_irq(struct i40e
 
 		rx_desc = I40E_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
-		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
-			   I40E_RXD_QW1_PTYPE_SHIFT;
-		rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >>
-			    I40E_RXD_QW1_STATUS_SHIFT;
-
-		if (!(rx_status & BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
-			break;
-
 		/* status_error_len will always be zero for unused descriptors
 		 * because it's cleared in cleanup, and overlaps with hdr_addr
 		 * which is always zero because packet split isn't used, if the
 		 * hardware wrote DD then it will be non-zero
 		 */
-		if (!rx_desc->wb.qword1.status_error_len)
+		if (!i40e_test_staterr(rx_desc,
+				       BIT(I40E_RX_DESC_STATUS_DD_SHIFT)))
 			break;
 
 		/* This memory barrier is needed to keep us from reading
@@ -1271,6 +1261,10 @@ static int i40e_clean_rx_irq(struct i40e
 		/* probably a little skewed due to removing CRC */
 		total_rx_bytes += skb->len;
 
+		qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
+		rx_ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >>
+			   I40E_RXD_QW1_PTYPE_SHIFT;
+
 		/* populate checksum, VLAN, and protocol */
 		i40evf_process_skb_fields(rx_ring, rx_desc, skb, rx_ptype);
 
@@ -1461,12 +1455,24 @@ int i40evf_napi_poll(struct napi_struct
 
 	/* If work not completed, return budget and polling will return */
 	if (!clean_complete) {
+		const cpumask_t *aff_mask = &q_vector->affinity_mask;
+		int cpu_id = smp_processor_id();
+
+		/* It is possible that the interrupt affinity has changed but,
+		 * if the cpu is pegged at 100%, polling will never exit while
+		 * traffic continues and the interrupt will be stuck on this
+		 * cpu.  We check to make sure affinity is correct before we
+		 * continue to poll, otherwise we must stop polling so the
+		 * interrupt can move to the correct cpu.
+		 */
+		if (likely(cpumask_test_cpu(cpu_id, aff_mask))) {
 tx_only:
-		if (arm_wb) {
-			q_vector->tx.ring[0].tx_stats.tx_force_wb++;
-			i40e_enable_wb_on_itr(vsi, q_vector);
+			if (arm_wb) {
+				q_vector->tx.ring[0].tx_stats.tx_force_wb++;
+				i40e_enable_wb_on_itr(vsi, q_vector);
+			}
+			return budget;
 		}
-		return budget;
 	}
 
 	if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
@@ -1474,8 +1480,17 @@ tx_only:
 
 	/* Work is done so exit the polling mode and re-enable the interrupt */
 	napi_complete_done(napi, work_done);
-	i40e_update_enable_itr(vsi, q_vector);
-	return 0;
+
+	/* If we're prematurely stopping polling to fix the interrupt
+	 * affinity we want to make sure polling starts back up so we
+	 * issue a call to i40evf_force_wb which triggers a SW interrupt.
+	 */
+	if (!clean_complete)
+		i40evf_force_wb(vsi, q_vector);
+	else
+		i40e_update_enable_itr(vsi, q_vector);
+
+	return min(work_done, budget - 1);
 }
 
 /**
@@ -1935,9 +1950,7 @@ static inline void i40evf_tx_map(struct
 	u32 td_tag = 0;
 	dma_addr_t dma;
 	u16 gso_segs;
-	u16 desc_count = 0;
-	bool tail_bump = true;
-	bool do_rs = false;
+	u16 desc_count = 1;
 
 	if (tx_flags & I40E_TX_FLAGS_HW_VLAN) {
 		td_cmd |= I40E_TX_DESC_CMD_IL2TAG1;
@@ -2020,8 +2033,7 @@ static inline void i40evf_tx_map(struct
 		tx_bi = &tx_ring->tx_bi[i];
 	}
 
-	/* set next_to_watch value indicating a packet is present */
-	first->next_to_watch = tx_desc;
+	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
 
 	i++;
 	if (i == tx_ring->count)
@@ -2029,66 +2041,72 @@ static inline void i40evf_tx_map(struct
 
 	tx_ring->next_to_use = i;
 
-	netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
 	i40e_maybe_stop_tx(tx_ring, DESC_NEEDED);
 
+	/* write last descriptor with EOP bit */
+	td_cmd |= I40E_TX_DESC_CMD_EOP;
+
+	/* We can OR these values together as they both are checked against
+	 * 4 below and at this point desc_count will be used as a boolean value
+	 * after this if/else block.
+	 */
+	desc_count |= ++tx_ring->packet_stride;
+
 	/* Algorithm to optimize tail and RS bit setting:
-	 * if xmit_more is supported
-	 *	if xmit_more is true
-	 *		do not update tail and do not mark RS bit.
-	 *	if xmit_more is false and last xmit_more was false
-	 *		if every packet spanned less than 4 desc
-	 *			then set RS bit on 4th packet and update tail
-	 *			on every packet
-	 *		else
-	 *			update tail and set RS bit on every packet.
-	 *	if xmit_more is false and last_xmit_more was true
-	 *		update tail and set RS bit.
+	 * if queue is stopped
+	 *	mark RS bit
+	 *	reset packet counter
+	 * else if xmit_more is supported and is true
+	 *	advance packet counter to 4
+	 *	reset desc_count to 0
 	 *
-	 * Optimization: wmb to be issued only in case of tail update.
-	 * Also optimize the Descriptor WB path for RS bit with the same
-	 * algorithm.
+	 * if desc_count >= 4
+	 *	mark RS bit
+	 *	reset packet counter
+	 * if desc_count > 0
+	 *	update tail
 	 *
-	 * Note: If there are less than 4 packets
+	 * Note: If there are less than 4 descriptors
 	 * pending and interrupts were disabled the service task will
 	 * trigger a force WB.
 	 */
-	if (skb->xmit_more  &&
-	    !netif_xmit_stopped(txring_txq(tx_ring))) {
-		tx_ring->flags |= I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
-		tail_bump = false;
-	} else if (!skb->xmit_more &&
-		   !netif_xmit_stopped(txring_txq(tx_ring)) &&
-		   (!(tx_ring->flags & I40E_TXR_FLAGS_LAST_XMIT_MORE_SET)) &&
-		   (tx_ring->packet_stride < WB_STRIDE) &&
-		   (desc_count < WB_STRIDE)) {
-		tx_ring->packet_stride++;
-	} else {
+	if (netif_xmit_stopped(txring_txq(tx_ring))) {
+		goto do_rs;
+	} else if (skb->xmit_more) {
+		/* set stride to arm on next packet and reset desc_count */
+		tx_ring->packet_stride = WB_STRIDE;
+		desc_count = 0;
+	} else if (desc_count >= WB_STRIDE) {
+do_rs:
+		/* write last descriptor with RS bit set */
+		td_cmd |= I40E_TX_DESC_CMD_RS;
 		tx_ring->packet_stride = 0;
-		tx_ring->flags &= ~I40E_TXR_FLAGS_LAST_XMIT_MORE_SET;
-		do_rs = true;
 	}
-	if (do_rs)
-		tx_ring->packet_stride = 0;
 
 	tx_desc->cmd_type_offset_bsz =
-			build_ctob(td_cmd, td_offset, size, td_tag) |
-			cpu_to_le64((u64)(do_rs ? I40E_TXD_CMD :
-						  I40E_TX_DESC_CMD_EOP) <<
-						  I40E_TXD_QW1_CMD_SHIFT);
+			build_ctob(td_cmd, td_offset, size, td_tag);
+
+	/* Force memory writes to complete before letting h/w know there
+	 * are new descriptors to fetch.
+	 *
+	 * We also use this memory barrier to make certain all of the
+	 * status bits have been updated before next_to_watch is written.
+	 */
+	wmb();
+
+	/* set next_to_watch value indicating a packet is present */
+	first->next_to_watch = tx_desc;
 
 	/* notify HW of packet */
-	if (!tail_bump) {
-		prefetchw(tx_desc + 1);
-	} else {
-		/* 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 (desc_count) {
 		writel(i, 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();
 	}
+
 	return;
 
 dma_error:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_txrx.h	2017-02-12 16:03:20.000000000 -0500
@@ -173,26 +173,37 @@ static inline bool i40e_test_staterr(uni
 #define I40E_MAX_DATA_PER_TXD_ALIGNED \
 	(I40E_MAX_DATA_PER_TXD & ~(I40E_MAX_READ_REQ_SIZE - 1))
 
-/* This ugly bit of math is equivalent to DIV_ROUNDUP(size, X) where X is
- * the value I40E_MAX_DATA_PER_TXD_ALIGNED.  It is needed due to the fact
- * that 12K is not a power of 2 and division is expensive.  It is used to
- * approximate the number of descriptors used per linear buffer.  Note
- * that this will overestimate in some cases as it doesn't account for the
- * fact that we will add up to 4K - 1 in aligning the 12K buffer, however
- * the error should not impact things much as large buffers usually mean
- * we will use fewer descriptors then there are frags in an skb.
+/**
+ * i40e_txd_use_count  - estimate the number of descriptors needed for Tx
+ * @size: transmit request size in bytes
+ *
+ * Due to hardware alignment restrictions (4K alignment), we need to
+ * assume that we can have no more than 12K of data per descriptor, even
+ * though each descriptor can take up to 16K - 1 bytes of aligned memory.
+ * Thus, we need to divide by 12K. But division is slow! Instead,
+ * we decompose the operation into shifts and one relatively cheap
+ * multiply operation.
+ *
+ * To divide by 12K, we first divide by 4K, then divide by 3:
+ *     To divide by 4K, shift right by 12 bits
+ *     To divide by 3, multiply by 85, then divide by 256
+ *     (Divide by 256 is done by shifting right by 8 bits)
+ * Finally, we add one to round up. Because 256 isn't an exact multiple of
+ * 3, we'll underestimate near each multiple of 12K. This is actually more
+ * accurate as we have 4K - 1 of wiggle room that we can fit into the last
+ * segment.  For our purposes this is accurate out to 1M which is orders of
+ * magnitude greater than our largest possible GSO size.
+ *
+ * This would then be implemented as:
+ *     return (((size >> 12) * 85) >> 8) + 1;
+ *
+ * Since multiplication and division are commutative, we can reorder
+ * operations into:
+ *     return ((size * 85) >> 20) + 1;
  */
 static inline unsigned int i40e_txd_use_count(unsigned int size)
 {
-	const unsigned int max = I40E_MAX_DATA_PER_TXD_ALIGNED;
-	const unsigned int reciprocal = ((1ull << 32) - 1 + (max / 2)) / max;
-	unsigned int adjust = ~(u32)0;
-
-	/* if we rounded up on the reciprocal pull down the adjustment */
-	if ((max * reciprocal) > adjust)
-		adjust = ~(u32)(reciprocal - 1);
-
-	return (u32)((((u64)size * reciprocal) + adjust) >> 32);
+	return ((size * 85) >> 20) + 1;
 }
 
 /* Tx Descriptors needed, worst case */
@@ -309,7 +320,6 @@ struct i40e_ring {
 	bool ring_active;		/* is ring online or not */
 	bool arm_wb;		/* do something to arm write back */
 	u8 packet_stride;
-#define I40E_TXR_FLAGS_LAST_XMIT_MORE_SET BIT(2)
 
 	u16 flags;
 #define I40E_TXR_FLAGS_WB_ON_ITR	BIT(0)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_type.h	2017-02-12 16:03:20.000000000 -0500
@@ -187,47 +187,59 @@ struct i40e_link_status {
 #define I40E_MODULE_TYPE_1000BASE_T	0x08
 };
 
-enum i40e_aq_capabilities_phy_type {
-	I40E_CAP_PHY_TYPE_SGMII		  = BIT(I40E_PHY_TYPE_SGMII),
-	I40E_CAP_PHY_TYPE_1000BASE_KX	  = BIT(I40E_PHY_TYPE_1000BASE_KX),
-	I40E_CAP_PHY_TYPE_10GBASE_KX4	  = BIT(I40E_PHY_TYPE_10GBASE_KX4),
-	I40E_CAP_PHY_TYPE_10GBASE_KR	  = BIT(I40E_PHY_TYPE_10GBASE_KR),
-	I40E_CAP_PHY_TYPE_40GBASE_KR4	  = BIT(I40E_PHY_TYPE_40GBASE_KR4),
-	I40E_CAP_PHY_TYPE_XAUI		  = BIT(I40E_PHY_TYPE_XAUI),
-	I40E_CAP_PHY_TYPE_XFI		  = BIT(I40E_PHY_TYPE_XFI),
-	I40E_CAP_PHY_TYPE_SFI		  = BIT(I40E_PHY_TYPE_SFI),
-	I40E_CAP_PHY_TYPE_XLAUI		  = BIT(I40E_PHY_TYPE_XLAUI),
-	I40E_CAP_PHY_TYPE_XLPPI		  = BIT(I40E_PHY_TYPE_XLPPI),
-	I40E_CAP_PHY_TYPE_40GBASE_CR4_CU  = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU),
-	I40E_CAP_PHY_TYPE_10GBASE_CR1_CU  = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU),
-	I40E_CAP_PHY_TYPE_10GBASE_AOC	  = BIT(I40E_PHY_TYPE_10GBASE_AOC),
-	I40E_CAP_PHY_TYPE_40GBASE_AOC	  = BIT(I40E_PHY_TYPE_40GBASE_AOC),
-	I40E_CAP_PHY_TYPE_100BASE_TX	  = BIT(I40E_PHY_TYPE_100BASE_TX),
-	I40E_CAP_PHY_TYPE_1000BASE_T	  = BIT(I40E_PHY_TYPE_1000BASE_T),
-	I40E_CAP_PHY_TYPE_10GBASE_T	  = BIT(I40E_PHY_TYPE_10GBASE_T),
-	I40E_CAP_PHY_TYPE_10GBASE_SR	  = BIT(I40E_PHY_TYPE_10GBASE_SR),
-	I40E_CAP_PHY_TYPE_10GBASE_LR	  = BIT(I40E_PHY_TYPE_10GBASE_LR),
-	I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU),
-	I40E_CAP_PHY_TYPE_10GBASE_CR1	  = BIT(I40E_PHY_TYPE_10GBASE_CR1),
-	I40E_CAP_PHY_TYPE_40GBASE_CR4	  = BIT(I40E_PHY_TYPE_40GBASE_CR4),
-	I40E_CAP_PHY_TYPE_40GBASE_SR4	  = BIT(I40E_PHY_TYPE_40GBASE_SR4),
-	I40E_CAP_PHY_TYPE_40GBASE_LR4	  = BIT(I40E_PHY_TYPE_40GBASE_LR4),
-	I40E_CAP_PHY_TYPE_1000BASE_SX	  = BIT(I40E_PHY_TYPE_1000BASE_SX),
-	I40E_CAP_PHY_TYPE_1000BASE_LX	  = BIT(I40E_PHY_TYPE_1000BASE_LX),
-	I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL =
-					 BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL),
-	I40E_CAP_PHY_TYPE_20GBASE_KR2	  = BIT(I40E_PHY_TYPE_20GBASE_KR2)
-};
-
 struct i40e_phy_info {
 	struct i40e_link_status link_info;
 	struct i40e_link_status link_info_old;
 	bool get_link_info;
 	enum i40e_media_type media_type;
 	/* all the phy types the NVM is capable of */
-	enum i40e_aq_capabilities_phy_type phy_types;
+	u64 phy_types;
 };
 
+#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII)
+#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX)
+#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4)
+#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR)
+#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4)
+#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI)
+#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI)
+#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI)
+#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI)
+#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR)
+#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR)
+#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4)
+#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX)
+#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \
+				BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL)
+#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2)
+/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some
+ * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit
+ * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So,
+ * a shift is needed to adjust for this with values larger than 31. The
+ * only affected values are I40E_PHY_TYPE_25GBASE_*.
+ */
+#define I40E_PHY_TYPE_OFFSET 1
+#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \
+					     I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \
+					     I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \
+					     I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
+					     I40E_PHY_TYPE_OFFSET)
 #define I40E_HW_CAP_MAX_GPIO			30
 /* Capabilities of a PF or a VF or the whole device */
 struct i40e_hw_capabilities {
@@ -237,6 +249,10 @@ struct i40e_hw_capabilities {
 #define I40E_NVM_IMAGE_TYPE_UDP_CLOUD	0x3
 
 	u32  management_mode;
+	u32  mng_protocols_over_mctp;
+#define I40E_MNG_PROTOCOL_PLDM		0x2
+#define I40E_MNG_PROTOCOL_OEM_COMMANDS	0x4
+#define I40E_MNG_PROTOCOL_NCSI		0x8
 	u32  npar_enable;
 	u32  os2bmc;
 	u32  valid_functions;
@@ -348,6 +364,7 @@ enum i40e_nvmupd_state {
 	I40E_NVMUPD_STATE_WRITING,
 	I40E_NVMUPD_STATE_INIT_WAIT,
 	I40E_NVMUPD_STATE_WRITE_WAIT,
+	I40E_NVMUPD_STATE_ERROR
 };
 
 /* nvm_access definition and its masks/shifts need to be accessible to
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -85,6 +85,14 @@ static int i40evf_get_settings(struct ne
 	case I40E_LINK_SPEED_40GB:
 		ethtool_cmd_speed_set(ecmd, SPEED_40000);
 		break;
+	case I40E_LINK_SPEED_25GB:
+#ifdef SPEED_25000
+		ethtool_cmd_speed_set(ecmd, SPEED_25000);
+#else
+		netdev_info(netdev,
+			    "Speed is 25G, display not supported by this version of ethtool.\n");
+#endif
+		break;
 	case I40E_LINK_SPEED_20GB:
 		ethtool_cmd_speed_set(ecmd, SPEED_20000);
 		break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf.h	2017-02-12 16:03:20.000000000 -0500
@@ -107,7 +107,8 @@ struct i40e_q_vector {
 	int v_idx;	/* vector index in list */
 	char name[IFNAMSIZ + 9];
 	bool arm_wb_state;
-	cpumask_var_t affinity_mask;
+	cpumask_t affinity_mask;
+	struct irq_affinity_notify affinity_notify;
 };
 
 /* Helper macros to switch between ints/sec and what the register uses.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@ static const char i40evf_driver_string[]
 
 #define DRV_VERSION_MAJOR 1
 #define DRV_VERSION_MINOR 6
-#define DRV_VERSION_BUILD 16
+#define DRV_VERSION_BUILD 25
 #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
 	     __stringify(DRV_VERSION_MINOR) "." \
 	     __stringify(DRV_VERSION_BUILD) \
@@ -207,6 +207,9 @@ static void i40evf_misc_irq_disable(stru
 {
 	struct i40e_hw *hw = &adapter->hw;
 
+	if (!adapter->msix_entries)
+		return;
+
 	wr32(hw, I40E_VFINT_DYN_CTL01, 0);
 
 	/* read flush */
@@ -496,6 +499,33 @@ static void i40evf_netpoll(struct net_de
 
 #endif
 /**
+ * i40evf_irq_affinity_notify - Callback for affinity changes
+ * @notify: context as to what irq was changed
+ * @mask: the new affinity mask
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * so that we may register to receive changes to the irq affinity masks.
+ **/
+static void i40evf_irq_affinity_notify(struct irq_affinity_notify *notify,
+				       const cpumask_t *mask)
+{
+	struct i40e_q_vector *q_vector =
+		container_of(notify, struct i40e_q_vector, affinity_notify);
+
+	q_vector->affinity_mask = *mask;
+}
+
+/**
+ * i40evf_irq_affinity_release - Callback for affinity notifier release
+ * @ref: internal core kernel usage
+ *
+ * This is a callback function used by the irq_set_affinity_notifier function
+ * to inform the current notification subscriber that they will no longer
+ * receive notifications.
+ **/
+static void i40evf_irq_affinity_release(struct kref *ref) {}
+
+/**
  * i40evf_request_traffic_irqs - Initialize MSI-X interrupts
  * @adapter: board private structure
  *
@@ -507,6 +537,7 @@ i40evf_request_traffic_irqs(struct i40ev
 {
 	int vector, err, q_vectors;
 	int rx_int_idx = 0, tx_int_idx = 0;
+	int irq_num;
 
 	i40evf_irq_disable(adapter);
 	/* Decrement for Other and TCP Timer vectors */
@@ -514,6 +545,7 @@ i40evf_request_traffic_irqs(struct i40ev
 
 	for (vector = 0; vector < q_vectors; vector++) {
 		struct i40e_q_vector *q_vector = &adapter->q_vectors[vector];
+		irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
 
 		if (q_vector->tx.ring && q_vector->rx.ring) {
 			snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -532,21 +564,23 @@ i40evf_request_traffic_irqs(struct i40ev
 			/* skip this unused q_vector */
 			continue;
 		}
-		err = request_irq(
-			adapter->msix_entries[vector + NONQ_VECS].vector,
-			i40evf_msix_clean_rings,
-			0,
-			q_vector->name,
-			q_vector);
+		err = request_irq(irq_num,
+				  i40evf_msix_clean_rings,
+				  0,
+				  q_vector->name,
+				  q_vector);
 		if (err) {
 			dev_info(&adapter->pdev->dev,
 				 "Request_irq failed, error: %d\n", err);
 			goto free_queue_irqs;
 		}
+		/* register for affinity change notifications */
+		q_vector->affinity_notify.notify = i40evf_irq_affinity_notify;
+		q_vector->affinity_notify.release =
+						   i40evf_irq_affinity_release;
+		irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
 		/* assign the mask for this irq */
-		irq_set_affinity_hint(
-			adapter->msix_entries[vector + NONQ_VECS].vector,
-			q_vector->affinity_mask);
+		irq_set_affinity_hint(irq_num, &q_vector->affinity_mask);
 	}
 
 	return 0;
@@ -554,11 +588,10 @@ i40evf_request_traffic_irqs(struct i40ev
 free_queue_irqs:
 	while (vector) {
 		vector--;
-		irq_set_affinity_hint(
-			adapter->msix_entries[vector + NONQ_VECS].vector,
-			NULL);
-		free_irq(adapter->msix_entries[vector + NONQ_VECS].vector,
-			 &adapter->q_vectors[vector]);
+		irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+		irq_set_affinity_notifier(irq_num, NULL);
+		irq_set_affinity_hint(irq_num, NULL);
+		free_irq(irq_num, &adapter->q_vectors[vector]);
 	}
 	return err;
 }
@@ -599,16 +632,18 @@ static int i40evf_request_misc_irq(struc
  **/
 static void i40evf_free_traffic_irqs(struct i40evf_adapter *adapter)
 {
-	int i;
-	int q_vectors;
+	int vector, irq_num, q_vectors;
+
+	if (!adapter->msix_entries)
+		return;
 
 	q_vectors = adapter->num_msix_vectors - NONQ_VECS;
 
-	for (i = 0; i < q_vectors; i++) {
-		irq_set_affinity_hint(adapter->msix_entries[i+1].vector,
-				      NULL);
-		free_irq(adapter->msix_entries[i+1].vector,
-			 &adapter->q_vectors[i]);
+	for (vector = 0; vector < q_vectors; vector++) {
+		irq_num = adapter->msix_entries[vector + NONQ_VECS].vector;
+		irq_set_affinity_notifier(irq_num, NULL);
+		irq_set_affinity_hint(irq_num, NULL);
+		free_irq(irq_num, &adapter->q_vectors[vector]);
 	}
 }
 
@@ -622,6 +657,9 @@ static void i40evf_free_misc_irq(struct
 {
 	struct net_device *netdev = adapter->netdev;
 
+	if (!adapter->msix_entries)
+		return;
+
 	free_irq(adapter->msix_entries[0].vector, netdev);
 }
 
@@ -1396,6 +1434,9 @@ static void i40evf_free_q_vectors(struct
 	int q_idx, num_q_vectors;
 	int napi_vectors;
 
+	if (!adapter->q_vectors)
+		return;
+
 	num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
 	napi_vectors = adapter->num_active_queues;
 
@@ -1405,6 +1446,7 @@ static void i40evf_free_q_vectors(struct
 			netif_napi_del(&q_vector->napi);
 	}
 	kfree(adapter->q_vectors);
+	adapter->q_vectors = NULL;
 }
 
 /**
@@ -1414,6 +1456,9 @@ static void i40evf_free_q_vectors(struct
  **/
 void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter)
 {
+	if (!adapter->msix_entries)
+		return;
+
 	pci_disable_msix(adapter->pdev);
 	kfree(adapter->msix_entries);
 	adapter->msix_entries = NULL;
@@ -1664,6 +1709,49 @@ restart_watchdog:
 	schedule_work(&adapter->adminq_task);
 }
 
+static void i40evf_disable_vf(struct i40evf_adapter *adapter)
+{
+	struct i40evf_mac_filter *f, *ftmp;
+	struct i40evf_vlan_filter *fv, *fvtmp;
+
+	adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
+
+	if (netif_running(adapter->netdev)) {
+		set_bit(__I40E_DOWN, &adapter->vsi.state);
+		netif_carrier_off(adapter->netdev);
+		netif_tx_disable(adapter->netdev);
+		adapter->link_up = false;
+		i40evf_napi_disable_all(adapter);
+		i40evf_irq_disable(adapter);
+		i40evf_free_traffic_irqs(adapter);
+		i40evf_free_all_tx_resources(adapter);
+		i40evf_free_all_rx_resources(adapter);
+	}
+
+	/* Delete all of the filters, both MAC and VLAN. */
+	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+		list_del(&f->list);
+		kfree(f);
+	}
+
+	list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list, list) {
+		list_del(&fv->list);
+		kfree(fv);
+	}
+
+	i40evf_free_misc_irq(adapter);
+	i40evf_reset_interrupt_capability(adapter);
+	i40evf_free_queues(adapter);
+	i40evf_free_q_vectors(adapter);
+	kfree(adapter->vf_res);
+	i40evf_shutdown_adminq(&adapter->hw);
+	adapter->netdev->flags &= ~IFF_UP;
+	clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
+	adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
+	adapter->state = __I40EVF_DOWN;
+	dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
+}
+
 #define I40EVF_RESET_WAIT_MS 10
 #define I40EVF_RESET_WAIT_COUNT 500
 /**
@@ -1717,60 +1805,21 @@ static void i40evf_reset_task(struct wor
 
 	/* wait until the reset is complete and the PF is responding to us */
 	for (i = 0; i < I40EVF_RESET_WAIT_COUNT; i++) {
+		/* sleep first to make sure a minimum wait time is met */
+		msleep(I40EVF_RESET_WAIT_MS);
+
 		reg_val = rd32(hw, I40E_VFGEN_RSTAT) &
 			  I40E_VFGEN_RSTAT_VFR_STATE_MASK;
 		if (reg_val == I40E_VFR_VFACTIVE)
 			break;
-		msleep(I40EVF_RESET_WAIT_MS);
 	}
+
 	pci_set_master(adapter->pdev);
-	/* extra wait to make sure minimum wait is met */
-	msleep(I40EVF_RESET_WAIT_MS);
-	if (i == I40EVF_RESET_WAIT_COUNT) {
-		struct i40evf_mac_filter *ftmp;
-		struct i40evf_vlan_filter *fv, *fvtmp;
 
-		/* reset never finished */
+	if (i == I40EVF_RESET_WAIT_COUNT) {
 		dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
 			reg_val);
-		adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
-
-		if (netif_running(adapter->netdev)) {
-			set_bit(__I40E_DOWN, &adapter->vsi.state);
-			netif_carrier_off(netdev);
-			netif_tx_disable(netdev);
-			adapter->link_up = false;
-			i40evf_napi_disable_all(adapter);
-			i40evf_irq_disable(adapter);
-			i40evf_free_traffic_irqs(adapter);
-			i40evf_free_all_tx_resources(adapter);
-			i40evf_free_all_rx_resources(adapter);
-		}
-
-		/* Delete all of the filters, both MAC and VLAN. */
-		list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list,
-					 list) {
-			list_del(&f->list);
-			kfree(f);
-		}
-
-		list_for_each_entry_safe(fv, fvtmp, &adapter->vlan_filter_list,
-					 list) {
-			list_del(&fv->list);
-			kfree(fv);
-		}
-
-		i40evf_free_misc_irq(adapter);
-		i40evf_reset_interrupt_capability(adapter);
-		i40evf_free_queues(adapter);
-		i40evf_free_q_vectors(adapter);
-		kfree(adapter->vf_res);
-		i40evf_shutdown_adminq(hw);
-		adapter->netdev->flags &= ~IFF_UP;
-		clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
-		adapter->flags &= ~I40EVF_FLAG_RESET_PENDING;
-		adapter->state = __I40EVF_DOWN;
-		dev_info(&adapter->pdev->dev, "Reset task did not complete, VF disabled\n");
+		i40evf_disable_vf(adapter);
 		return; /* Do not attempt to reinit. It's dead, Jim. */
 	}
 
@@ -2133,10 +2182,6 @@ static struct net_device_stats *i40evf_g
 static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct i40evf_adapter *adapter = netdev_priv(netdev);
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
-	if ((new_mtu < 68) || (max_frame > I40E_MAX_RXBUFFER))
-		return -EINVAL;
 
 	netdev->mtu = new_mtu;
 	adapter->flags |= I40EVF_FLAG_RESET_NEEDED;
@@ -2145,6 +2190,64 @@ static int i40evf_change_mtu(struct net_
 	return 0;
 }
 
+/**
+ * i40evf_features_check - Validate encapsulated packet conforms to limits
+ * @skb: skb buff
+ * @netdev: This physical port's netdev
+ * @features: Offload features that the stack believes apply
+ **/
+static netdev_features_t i40evf_features_check(struct sk_buff *skb,
+					       struct net_device *dev,
+					       netdev_features_t features)
+{
+	size_t len;
+
+	/* No point in doing any of this if neither checksum nor GSO are
+	 * being requested for this frame.  We can rule out both by just
+	 * checking for CHECKSUM_PARTIAL
+	 */
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return features;
+
+	/* We cannot support GSO if the MSS is going to be less than
+	 * 64 bytes.  If it is then we need to drop support for GSO.
+	 */
+	if (skb_is_gso(skb) && (skb_shinfo(skb)->gso_size < 64))
+		features &= ~NETIF_F_GSO_MASK;
+
+	/* MACLEN can support at most 63 words */
+	len = skb_network_header(skb) - skb->data;
+	if (len & ~(63 * 2))
+		goto out_err;
+
+	/* IPLEN and EIPLEN can support at most 127 dwords */
+	len = skb_transport_header(skb) - skb_network_header(skb);
+	if (len & ~(127 * 4))
+		goto out_err;
+
+	if (skb->encapsulation) {
+		/* L4TUNLEN can support 127 words */
+		len = skb_inner_network_header(skb) - skb_transport_header(skb);
+		if (len & ~(127 * 2))
+			goto out_err;
+
+		/* IPLEN can support at most 127 dwords */
+		len = skb_inner_transport_header(skb) -
+		      skb_inner_network_header(skb);
+		if (len & ~(127 * 4))
+			goto out_err;
+	}
+
+	/* No need to validate L4LEN as TCP is the only protocol with a
+	 * a flexible value and we support all possible values supported
+	 * by TCP, which is at most 15 dwords
+	 */
+
+	return features;
+out_err:
+	return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+}
+
 #define I40EVF_VLAN_FEATURES (NETIF_F_HW_VLAN_CTAG_TX |\
 			      NETIF_F_HW_VLAN_CTAG_RX |\
 			      NETIF_F_HW_VLAN_CTAG_FILTER)
@@ -2179,6 +2282,7 @@ static const struct net_device_ops i40ev
 	.ndo_tx_timeout		= i40evf_tx_timeout,
 	.ndo_vlan_rx_add_vid	= i40evf_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= i40evf_vlan_rx_kill_vid,
+	.ndo_features_check	= i40evf_features_check,
 	.ndo_fix_features	= i40evf_fix_features,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= i40evf_netpoll,
@@ -2424,6 +2528,10 @@ static void i40evf_init_task(struct work
 	i40evf_set_ethtool_ops(netdev);
 	netdev->watchdog_timeo = 5 * HZ;
 
+	/* MTU range: 68 - 9710 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = I40E_MAX_RXBUFFER - (ETH_HLEN + ETH_FCS_LEN);
+
 	if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
 		dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n",
 			 adapter->hw.mac.addr);
@@ -2764,12 +2872,10 @@ static void i40evf_remove(struct pci_dev
 		msleep(50);
 	}
 
-	if (adapter->msix_entries) {
-		i40evf_misc_irq_disable(adapter);
-		i40evf_free_misc_irq(adapter);
-		i40evf_reset_interrupt_capability(adapter);
-		i40evf_free_q_vectors(adapter);
-	}
+	i40evf_misc_irq_disable(adapter);
+	i40evf_free_misc_irq(adapter);
+	i40evf_reset_interrupt_capability(adapter);
+	i40evf_free_q_vectors(adapter);
 
 	if (adapter->watchdog_timer.function)
 		del_timer_sync(&adapter->watchdog_timer);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c	2017-02-12 16:03:20.000000000 -0500
@@ -836,6 +836,9 @@ static void i40evf_print_link_message(st
 	case I40E_LINK_SPEED_40GB:
 		speed = "40 G";
 		break;
+	case I40E_LINK_SPEED_25GB:
+		speed = "25 G";
+		break;
 	case I40E_LINK_SPEED_20GB:
 		speed = "20 G";
 		break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/i40evf/i40e_virtchnl.h	2017-02-12 16:03:20.000000000 -0500
@@ -162,6 +162,10 @@ struct i40e_virtchnl_vsi_resource {
 #define I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF		0X00080000
 #define I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM	0X00100000
 
+#define I40E_VF_BASE_MODE_OFFLOADS (I40E_VIRTCHNL_VF_OFFLOAD_L2 | \
+				    I40E_VIRTCHNL_VF_OFFLOAD_VLAN | \
+				    I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
+
 struct i40e_virtchnl_vf_resource {
 	u16 num_vsis;
 	u16 num_queue_pairs;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/e1000_defines.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/e1000_defines.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/e1000_defines.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/e1000_defines.h	2017-02-12 16:03:20.000000000 -0500
@@ -357,7 +357,8 @@
 #define ETHERNET_IEEE_VLAN_TYPE 0x8100  /* 802.3ac packet */
 
 /* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
-#define MAX_JUMBO_FRAME_SIZE	0x2600
+#define MAX_JUMBO_FRAME_SIZE		0x2600
+#define MAX_STD_JUMBO_FRAME_SIZE	9216
 
 /* PBA constants */
 #define E1000_PBA_34K 0x0022
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/igb.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/igb.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/igb.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/igb.h	2017-02-12 16:03:20.000000000 -0500
@@ -210,7 +210,12 @@ struct igb_tx_buffer {
 struct igb_rx_buffer {
 	dma_addr_t dma;
 	struct page *page;
-	unsigned int page_offset;
+#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
+	__u32 page_offset;
+#else
+	__u16 page_offset;
+#endif
+	__u16 pagecnt_bias;
 };
 
 struct igb_tx_queue_stats {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/igb_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/igb_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/igb_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/igb_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -2468,6 +2468,10 @@ static int igb_probe(struct pci_dev *pde
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
+	/* MTU range: 68 - 9216 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
+
 	adapter->en_mng_pt = igb_enable_mng_pass_thru(hw);
 
 	/* before reading the NVM, reset the controller to put the device in a
@@ -3943,11 +3947,23 @@ static void igb_clean_rx_ring(struct igb
 		if (!buffer_info->page)
 			continue;
 
-		dma_unmap_page(rx_ring->dev,
-			       buffer_info->dma,
-			       PAGE_SIZE,
-			       DMA_FROM_DEVICE);
-		__free_page(buffer_info->page);
+		/* Invalidate cache lines that may have been written to by
+		 * device so that we avoid corrupting memory.
+		 */
+		dma_sync_single_range_for_cpu(rx_ring->dev,
+					      buffer_info->dma,
+					      buffer_info->page_offset,
+					      IGB_RX_BUFSZ,
+					      DMA_FROM_DEVICE);
+
+		/* free resources associated with mapping */
+		dma_unmap_page_attrs(rx_ring->dev,
+				     buffer_info->dma,
+				     PAGE_SIZE,
+				     DMA_FROM_DEVICE,
+				     DMA_ATTR_SKIP_CPU_SYNC);
+		__page_frag_cache_drain(buffer_info->page,
+					buffer_info->pagecnt_bias);
 
 		buffer_info->page = NULL;
 	}
@@ -5412,17 +5428,6 @@ static int igb_change_mtu(struct net_dev
 	struct pci_dev *pdev = adapter->pdev;
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 
-	if ((new_mtu < 68) || (max_frame > MAX_JUMBO_FRAME_SIZE)) {
-		dev_err(&pdev->dev, "Invalid MTU setting\n");
-		return -EINVAL;
-	}
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9238
-	if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
-		dev_err(&pdev->dev, "MTU > 9216 not supported.\n");
-		return -EINVAL;
-	}
-
 	/* adjust max frame to be at least the size of a standard frame */
 	if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
 		max_frame = ETH_FRAME_LEN + ETH_FCS_LEN;
@@ -6819,12 +6824,6 @@ static void igb_reuse_rx_page(struct igb
 
 	/* transfer page from old buffer to new buffer */
 	*new_buff = *old_buff;
-
-	/* sync the buffer for use by the device */
-	dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma,
-					 old_buff->page_offset,
-					 IGB_RX_BUFSZ,
-					 DMA_FROM_DEVICE);
 }
 
 static inline bool igb_page_is_reserved(struct page *page)
@@ -6836,13 +6835,15 @@ static bool igb_can_reuse_rx_page(struct
 				  struct page *page,
 				  unsigned int truesize)
 {
+	unsigned int pagecnt_bias = rx_buffer->pagecnt_bias--;
+
 	/* avoid re-using remote pages */
 	if (unlikely(igb_page_is_reserved(page)))
 		return false;
 
 #if (PAGE_SIZE < 8192)
 	/* if we are only owner of page we can reuse it */
-	if (unlikely(page_count(page) != 1))
+	if (unlikely(page_ref_count(page) != pagecnt_bias))
 		return false;
 
 	/* flip page offset to other buffer */
@@ -6855,10 +6856,14 @@ static bool igb_can_reuse_rx_page(struct
 		return false;
 #endif
 
-	/* Even if we own the page, we are not allowed to use atomic_set()
-	 * This would break get_page_unless_zero() users.
+	/* If we have drained the page fragment pool we need to update
+	 * the pagecnt_bias and page count so that we fully restock the
+	 * number of references the driver holds.
 	 */
-	page_ref_inc(page);
+	if (unlikely(pagecnt_bias == 1)) {
+		page_ref_add(page, USHRT_MAX);
+		rx_buffer->pagecnt_bias = USHRT_MAX;
+	}
 
 	return true;
 }
@@ -6910,7 +6915,6 @@ static bool igb_add_rx_frag(struct igb_r
 			return true;
 
 		/* this page cannot be reused so discard it */
-		__free_page(page);
 		return false;
 	}
 
@@ -6945,6 +6949,13 @@ static struct sk_buff *igb_fetch_rx_buff
 	page = rx_buffer->page;
 	prefetchw(page);
 
+	/* we are reusing so sync this buffer for CPU use */
+	dma_sync_single_range_for_cpu(rx_ring->dev,
+				      rx_buffer->dma,
+				      rx_buffer->page_offset,
+				      size,
+				      DMA_FROM_DEVICE);
+
 	if (likely(!skb)) {
 		void *page_addr = page_address(page) +
 				  rx_buffer->page_offset;
@@ -6969,21 +6980,18 @@ static struct sk_buff *igb_fetch_rx_buff
 		prefetchw(skb->data);
 	}
 
-	/* we are reusing so sync this buffer for CPU use */
-	dma_sync_single_range_for_cpu(rx_ring->dev,
-				      rx_buffer->dma,
-				      rx_buffer->page_offset,
-				      size,
-				      DMA_FROM_DEVICE);
-
 	/* pull page into skb */
 	if (igb_add_rx_frag(rx_ring, rx_buffer, size, rx_desc, skb)) {
 		/* hand second half of page back to the ring */
 		igb_reuse_rx_page(rx_ring, rx_buffer);
 	} else {
-		/* we are not reusing the buffer so unmap it */
-		dma_unmap_page(rx_ring->dev, rx_buffer->dma,
-			       PAGE_SIZE, DMA_FROM_DEVICE);
+		/* We are not reusing the buffer so unmap it and free
+		 * any references we are holding to it
+		 */
+		dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma,
+				     PAGE_SIZE, DMA_FROM_DEVICE,
+				     DMA_ATTR_SKIP_CPU_SYNC);
+		__page_frag_cache_drain(page, rx_buffer->pagecnt_bias);
 	}
 
 	/* clear contents of rx_buffer */
@@ -7241,7 +7249,8 @@ static bool igb_alloc_mapped_page(struct
 	}
 
 	/* map page for use */
-	dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+	dma = dma_map_page_attrs(rx_ring->dev, page, 0, PAGE_SIZE,
+				 DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
 
 	/* if mapping failed free memory back to system since
 	 * there isn't much point in holding memory we can't use
@@ -7256,6 +7265,7 @@ static bool igb_alloc_mapped_page(struct
 	bi->dma = dma;
 	bi->page = page;
 	bi->page_offset = 0;
+	bi->pagecnt_bias = 1;
 
 	return true;
 }
@@ -7282,6 +7292,12 @@ void igb_alloc_rx_buffers(struct igb_rin
 		if (!igb_alloc_mapped_page(rx_ring, bi))
 			break;
 
+		/* sync the buffer for use by the device */
+		dma_sync_single_range_for_device(rx_ring->dev, bi->dma,
+						 bi->page_offset,
+						 IGB_RX_BUFSZ,
+						 DMA_FROM_DEVICE);
+
 		/* Refresh the desc even if buffer_addrs didn't change
 		 * because each write-back erases this info.
 		 */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/igb_ptp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/igb_ptp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/igb/igb_ptp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igb/igb_ptp.c	2017-02-12 16:03:20.000000000 -0500
@@ -77,7 +77,7 @@
 static void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
 
 /* SYSTIM read access for the 82576 */
-static cycle_t igb_ptp_read_82576(const struct cyclecounter *cc)
+static u64 igb_ptp_read_82576(const struct cyclecounter *cc)
 {
 	struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
 	struct e1000_hw *hw = &igb->hw;
@@ -94,7 +94,7 @@ static cycle_t igb_ptp_read_82576(const
 }
 
 /* SYSTIM read access for the 82580 */
-static cycle_t igb_ptp_read_82580(const struct cyclecounter *cc)
+static u64 igb_ptp_read_82580(const struct cyclecounter *cc)
 {
 	struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
 	struct e1000_hw *hw = &igb->hw;
@@ -226,7 +226,7 @@ static int igb_ptp_adjfreq_82576(struct
 	return 0;
 }
 
-static int igb_ptp_adjfreq_82580(struct ptp_clock_info *ptp, s32 ppb)
+static int igb_ptp_adjfine_82580(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct igb_adapter *igb = container_of(ptp, struct igb_adapter,
 					       ptp_caps);
@@ -235,13 +235,13 @@ static int igb_ptp_adjfreq_82580(struct
 	u64 rate;
 	u32 inca;
 
-	if (ppb < 0) {
+	if (scaled_ppm < 0) {
 		neg_adj = 1;
-		ppb = -ppb;
+		scaled_ppm = -scaled_ppm;
 	}
-	rate = ppb;
-	rate <<= 26;
-	rate = div_u64(rate, 1953125);
+	rate = scaled_ppm;
+	rate <<= 13;
+	rate = div_u64(rate, 15625);
 
 	inca = rate & INCVALUE_MASK;
 	if (neg_adj)
@@ -1103,7 +1103,7 @@ void igb_ptp_init(struct igb_adapter *ad
 		adapter->ptp_caps.max_adj = 62499999;
 		adapter->ptp_caps.n_ext_ts = 0;
 		adapter->ptp_caps.pps = 0;
-		adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580;
+		adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580;
 		adapter->ptp_caps.adjtime = igb_ptp_adjtime_82576;
 		adapter->ptp_caps.gettime64 = igb_ptp_gettime_82576;
 		adapter->ptp_caps.settime64 = igb_ptp_settime_82576;
@@ -1131,7 +1131,7 @@ void igb_ptp_init(struct igb_adapter *ad
 		adapter->ptp_caps.n_pins = IGB_N_SDP;
 		adapter->ptp_caps.pps = 1;
 		adapter->ptp_caps.pin_config = adapter->sdp_config;
-		adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82580;
+		adapter->ptp_caps.adjfine = igb_ptp_adjfine_82580;
 		adapter->ptp_caps.adjtime = igb_ptp_adjtime_i210;
 		adapter->ptp_caps.gettime64 = igb_ptp_gettime_i210;
 		adapter->ptp_caps.settime64 = igb_ptp_settime_i210;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/igbvf/defines.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igbvf/defines.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/igbvf/defines.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igbvf/defines.h	2017-02-12 16:03:20.000000000 -0500
@@ -85,7 +85,8 @@
 #define E1000_TXD_CMD_DEXT	0x20000000 /* Desc extension (0 = legacy) */
 #define E1000_TXD_STAT_DD	0x00000001 /* Desc Done */
 
-#define MAX_JUMBO_FRAME_SIZE	0x3F00
+#define MAX_JUMBO_FRAME_SIZE		0x3F00
+#define MAX_STD_JUMBO_FRAME_SIZE	9216
 
 /* 802.1q VLAN Packet Size */
 #define VLAN_TAG_SIZE		4    /* 802.3ac tag (not DMA'd) */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/igbvf/netdev.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igbvf/netdev.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/igbvf/netdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/igbvf/netdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -2360,16 +2360,6 @@ static int igbvf_change_mtu(struct net_d
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
-	if (new_mtu < 68 || new_mtu > INT_MAX - ETH_HLEN - ETH_FCS_LEN ||
-	    max_frame > MAX_JUMBO_FRAME_SIZE)
-		return -EINVAL;
-
-#define MAX_STD_JUMBO_FRAME_SIZE 9234
-	if (max_frame > MAX_STD_JUMBO_FRAME_SIZE) {
-		dev_err(&adapter->pdev->dev, "MTU > 9216 not supported.\n");
-		return -EINVAL;
-	}
-
 	while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
 		usleep_range(1000, 2000);
 	/* igbvf_down has a dependency on max_frame_size */
@@ -2790,6 +2780,10 @@ static int igbvf_probe(struct pci_dev *p
 			    NETIF_F_HW_VLAN_CTAG_RX |
 			    NETIF_F_HW_VLAN_CTAG_TX;
 
+	/* MTU range: 68 - 9216 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
+
 	/*reset the controller to put the device in a known good state */
 	err = hw->mac.ops.reset_hw(hw);
 	if (err) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -30,7 +30,7 @@
 
 #include "ixgb.h"
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #define IXGB_ALL_RAR_ENTRIES 16
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgb/ixgb_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -487,6 +487,10 @@ ixgb_probe(struct pci_dev *pdev, const s
 		netdev->vlan_features |= NETIF_F_HIGHDMA;
 	}
 
+	/* MTU range: 68 - 16114 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = IXGB_MAX_JUMBO_FRAME_SIZE - ETH_HLEN;
+
 	/* make sure the EEPROM is good */
 
 	if (!ixgb_validate_eeprom_checksum(&adapter->hw)) {
@@ -1619,18 +1623,6 @@ ixgb_change_mtu(struct net_device *netde
 {
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 	int max_frame = new_mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
-	int old_max_frame = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
-
-	/* MTU < 68 is an error for IPv4 traffic, just don't allow it */
-	if ((new_mtu < 68) ||
-	    (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
-		netif_err(adapter, probe, adapter->netdev,
-			  "Invalid MTU setting %d\n", new_mtu);
-		return -EINVAL;
-	}
-
-	if (old_max_frame == max_frame)
-		return 0;
 
 	if (netif_running(netdev))
 		ixgb_down(adapter, true);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c	2017-02-12 16:03:20.000000000 -0500
@@ -367,7 +367,7 @@ static s32 ixgbe_fc_enable_82598(struct
 	}
 
 	/* Negotiate the fc mode to use */
-	ixgbe_fc_autoneg(hw);
+	hw->mac.ops.fc_autoneg(hw);
 
 	/* Disable any previous flow control settings */
 	fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
@@ -1179,6 +1179,7 @@ static const struct ixgbe_mac_operations
 	.get_link_capabilities	= &ixgbe_get_link_capabilities_82598,
 	.led_on			= &ixgbe_led_on_generic,
 	.led_off		= &ixgbe_led_off_generic,
+	.init_led_link_act	= ixgbe_init_led_link_act_generic,
 	.blink_led_start	= &ixgbe_blink_led_start_generic,
 	.blink_led_stop		= &ixgbe_blink_led_stop_generic,
 	.set_rar		= &ixgbe_set_rar_generic,
@@ -1193,6 +1194,7 @@ static const struct ixgbe_mac_operations
 	.set_vfta		= &ixgbe_set_vfta_82598,
 	.fc_enable		= &ixgbe_fc_enable_82598,
 	.setup_fc		= ixgbe_setup_fc_generic,
+	.fc_autoneg		= ixgbe_fc_autoneg,
 	.set_fw_drv_ver         = NULL,
 	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
 	.release_swfw_sync      = &ixgbe_release_swfw_sync,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c	2017-02-12 16:03:20.000000000 -0500
@@ -2204,6 +2204,7 @@ static const struct ixgbe_mac_operations
 	.get_link_capabilities  = &ixgbe_get_link_capabilities_82599,
 	.led_on                 = &ixgbe_led_on_generic,
 	.led_off                = &ixgbe_led_off_generic,
+	.init_led_link_act	= ixgbe_init_led_link_act_generic,
 	.blink_led_start        = &ixgbe_blink_led_start_generic,
 	.blink_led_stop         = &ixgbe_blink_led_stop_generic,
 	.set_rar                = &ixgbe_set_rar_generic,
@@ -2219,6 +2220,7 @@ static const struct ixgbe_mac_operations
 	.set_vfta               = &ixgbe_set_vfta_generic,
 	.fc_enable              = &ixgbe_fc_enable_generic,
 	.setup_fc		= ixgbe_setup_fc_generic,
+	.fc_autoneg		= ixgbe_fc_autoneg,
 	.set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,
 	.init_uta_tables        = &ixgbe_init_uta_tables_generic,
 	.setup_sfp              = &ixgbe_setup_sfp_modules_82599,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c	2017-02-12 16:03:20.000000000 -0500
@@ -298,10 +298,12 @@ s32 ixgbe_start_hw_generic(struct ixgbe_
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
 	IXGBE_WRITE_FLUSH(hw);
 
-	/* Setup flow control */
-	ret_val = hw->mac.ops.setup_fc(hw);
-	if (ret_val)
-		return ret_val;
+	/* Setup flow control if method for doing so */
+	if (hw->mac.ops.setup_fc) {
+		ret_val = hw->mac.ops.setup_fc(hw);
+		if (ret_val)
+			return ret_val;
+	}
 
 	/* Cashe bit indicating need for crosstalk fix */
 	switch (hw->mac.type) {
@@ -390,6 +392,9 @@ s32 ixgbe_init_hw_generic(struct ixgbe_h
 		status = hw->mac.ops.start_hw(hw);
 	}
 
+	/* Initialize the LED link active for LED blink support */
+	hw->mac.ops.init_led_link_act(hw);
+
 	return status;
 }
 
@@ -773,6 +778,49 @@ s32 ixgbe_stop_adapter_generic(struct ix
 }
 
 /**
+ *  ixgbe_init_led_link_act_generic - Store the LED index link/activity.
+ *  @hw: pointer to hardware structure
+ *
+ *  Store the index for the link active LED. This will be used to support
+ *  blinking the LED.
+ **/
+s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw)
+{
+	struct ixgbe_mac_info *mac = &hw->mac;
+	u32 led_reg, led_mode;
+	u16 i;
+
+	led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+	/* Get LED link active from the LEDCTL register */
+	for (i = 0; i < 4; i++) {
+		led_mode = led_reg >> IXGBE_LED_MODE_SHIFT(i);
+
+		if ((led_mode & IXGBE_LED_MODE_MASK_BASE) ==
+		    IXGBE_LED_LINK_ACTIVE) {
+			mac->led_link_act = i;
+			return 0;
+		}
+	}
+
+	/* If LEDCTL register does not have the LED link active set, then use
+	 * known MAC defaults.
+	 */
+	switch (hw->mac.type) {
+	case ixgbe_mac_x550em_a:
+		mac->led_link_act = 0;
+		break;
+	case ixgbe_mac_X550EM_x:
+		mac->led_link_act = 1;
+		break;
+	default:
+		mac->led_link_act = 2;
+	}
+
+	return 0;
+}
+
+/**
  *  ixgbe_led_on_generic - Turns on the software controllable LEDs.
  *  @hw: pointer to hardware structure
  *  @index: led number to turn on
@@ -2127,7 +2175,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
 	}
 
 	/* Negotiate the fc mode to use */
-	ixgbe_fc_autoneg(hw);
+	hw->mac.ops.fc_autoneg(hw);
 
 	/* Disable any previous flow control settings */
 	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
@@ -2231,8 +2279,8 @@ s32 ixgbe_fc_enable_generic(struct ixgbe
  *  Find the intersection between advertised settings and link partner's
  *  advertised settings
  **/
-static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
-			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
+s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+		       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
 {
 	if ((!(adv_reg)) ||  (!(lp_reg)))
 		return IXGBE_ERR_FC_NOT_NEGOTIATED;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h	2017-02-12 16:03:20.000000000 -0500
@@ -49,6 +49,7 @@ s32 ixgbe_stop_adapter_generic(struct ix
 
 s32 ixgbe_led_on_generic(struct ixgbe_hw *hw, u32 index);
 s32 ixgbe_led_off_generic(struct ixgbe_hw *hw, u32 index);
+s32 ixgbe_init_led_link_act_generic(struct ixgbe_hw *hw);
 
 s32 ixgbe_init_eeprom_params_generic(struct ixgbe_hw *hw);
 s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -2225,11 +2225,11 @@ static int ixgbe_set_phys_id(struct net_
 		return 2;
 
 	case ETHTOOL_ID_ON:
-		hw->mac.ops.led_on(hw, hw->bus.func);
+		hw->mac.ops.led_on(hw, hw->mac.led_link_act);
 		break;
 
 	case ETHTOOL_ID_OFF:
-		hw->mac.ops.led_off(hw, hw->bus.func);
+		hw->mac.ops.led_off(hw, hw->mac.led_link_act);
 		break;
 
 	case ETHTOOL_ID_INACTIVE:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe.h	2017-02-12 16:03:20.000000000 -0500
@@ -1027,4 +1027,6 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct
 				  struct ixgbe_ring *tx_ring);
 u32 ixgbe_rss_indir_tbl_entries(struct ixgbe_adapter *adapter);
 void ixgbe_store_reta(struct ixgbe_adapter *adapter);
+s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+		       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
 #endif /* _IXGBE_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,6 +54,7 @@
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
 #include <net/tc_act/tc_mirred.h>
+#include <net/vxlan.h>
 
 #include "ixgbe.h"
 #include "ixgbe_common.h"
@@ -3070,6 +3071,9 @@ static void ixgbe_free_irq(struct ixgbe_
 		return;
 	}
 
+	if (!adapter->msix_entries)
+		return;
+
 	for (vector = 0; vector < adapter->num_q_vectors; vector++) {
 		struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
 		struct msix_entry *entry = &adapter->msix_entries[vector];
@@ -5012,24 +5016,23 @@ fwd_queue_err:
 	return err;
 }
 
-static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+static int ixgbe_upper_dev_walk(struct net_device *upper, void *data)
 {
-	struct net_device *upper;
-	struct list_head *iter;
-	int err;
-
-	netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-		if (netif_is_macvlan(upper)) {
-			struct macvlan_dev *dfwd = netdev_priv(upper);
-			struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
+	if (netif_is_macvlan(upper)) {
+		struct macvlan_dev *dfwd = netdev_priv(upper);
+		struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
 
-			if (dfwd->fwd_priv) {
-				err = ixgbe_fwd_ring_up(upper, vadapter);
-				if (err)
-					continue;
-			}
-		}
+		if (dfwd->fwd_priv)
+			ixgbe_fwd_ring_up(upper, vadapter);
 	}
+
+	return 0;
+}
+
+static void ixgbe_configure_dfwd(struct ixgbe_adapter *adapter)
+{
+	netdev_walk_all_upper_dev_rcu(adapter->netdev,
+				      ixgbe_upper_dev_walk, NULL);
 }
 
 static void ixgbe_configure(struct ixgbe_adapter *adapter)
@@ -5448,12 +5451,25 @@ static void ixgbe_fdir_filter_exit(struc
 	spin_unlock(&adapter->fdir_perfect_lock);
 }
 
+static int ixgbe_disable_macvlan(struct net_device *upper, void *data)
+{
+	if (netif_is_macvlan(upper)) {
+		struct macvlan_dev *vlan = netdev_priv(upper);
+
+		if (vlan->fwd_priv) {
+			netif_tx_stop_all_queues(upper);
+			netif_carrier_off(upper);
+			netif_tx_disable(upper);
+		}
+	}
+
+	return 0;
+}
+
 void ixgbe_down(struct ixgbe_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
-	struct net_device *upper;
-	struct list_head *iter;
 	int i;
 
 	/* signal that we are down to the interrupt handler */
@@ -5477,17 +5493,8 @@ void ixgbe_down(struct ixgbe_adapter *ad
 	netif_tx_disable(netdev);
 
 	/* disable any upper devices */
-	netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-		if (netif_is_macvlan(upper)) {
-			struct macvlan_dev *vlan = netdev_priv(upper);
-
-			if (vlan->fwd_priv) {
-				netif_tx_stop_all_queues(upper);
-				netif_carrier_off(upper);
-				netif_tx_disable(upper);
-			}
-		}
-	}
+	netdev_walk_all_upper_dev_rcu(adapter->netdev,
+				      ixgbe_disable_macvlan, NULL);
 
 	ixgbe_irq_disable(adapter);
 
@@ -5618,7 +5625,8 @@ static void ixgbe_init_dcb(struct ixgbe_
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  **/
-static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
+static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
+			 const struct ixgbe_info *ii)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
@@ -5634,6 +5642,9 @@ static int ixgbe_sw_init(struct ixgbe_ad
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_device_id = pdev->subsystem_device;
 
+	/* get_invariants needs the device IDs */
+	ii->get_invariants(hw);
+
 	/* Set common capability flags and settings */
 	rss = min_t(int, ixgbe_max_rss_indices(adapter), num_online_cpus());
 	adapter->ring_feature[RING_F_RSS].limit = rss;
@@ -6049,11 +6060,6 @@ static void ixgbe_free_all_rx_resources(
 static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-
-	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
-		return -EINVAL;
 
 	/*
 	 * For 82599EB we cannot allow legacy VFs to enable their receive
@@ -6062,7 +6068,7 @@ static int ixgbe_change_mtu(struct net_d
 	 */
 	if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
 	    (adapter->hw.mac.type == ixgbe_mac_82599EB) &&
-	    (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+	    (new_mtu > ETH_DATA_LEN))
 		e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
 
 	e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
@@ -6728,6 +6734,18 @@ static void ixgbe_update_default_up(stru
 #endif
 }
 
+static int ixgbe_enable_macvlan(struct net_device *upper, void *data)
+{
+	if (netif_is_macvlan(upper)) {
+		struct macvlan_dev *vlan = netdev_priv(upper);
+
+		if (vlan->fwd_priv)
+			netif_tx_wake_all_queues(upper);
+	}
+
+	return 0;
+}
+
 /**
  * ixgbe_watchdog_link_is_up - update netif_carrier status and
  *                             print link up message
@@ -6737,8 +6755,6 @@ static void ixgbe_watchdog_link_is_up(st
 {
 	struct net_device *netdev = adapter->netdev;
 	struct ixgbe_hw *hw = &adapter->hw;
-	struct net_device *upper;
-	struct list_head *iter;
 	u32 link_speed = adapter->link_speed;
 	const char *speed_str;
 	bool flow_rx, flow_tx;
@@ -6809,14 +6825,8 @@ static void ixgbe_watchdog_link_is_up(st
 
 	/* enable any upper devices */
 	rtnl_lock();
-	netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-		if (netif_is_macvlan(upper)) {
-			struct macvlan_dev *vlan = netdev_priv(upper);
-
-			if (vlan->fwd_priv)
-				netif_tx_wake_all_queues(upper);
-		}
-	}
+	netdev_walk_all_upper_dev_rcu(adapter->netdev,
+				      ixgbe_enable_macvlan, NULL);
 	rtnl_unlock();
 
 	/* update the default user priority for VFs */
@@ -7655,11 +7665,17 @@ static void ixgbe_atr(struct ixgbe_ring
 	/* snag network header to get L4 type and address */
 	skb = first->skb;
 	hdr.network = skb_network_header(skb);
+	if (unlikely(hdr.network <= skb->data))
+		return;
 	if (skb->encapsulation &&
 	    first->protocol == htons(ETH_P_IP) &&
-	    hdr.ipv4->protocol != IPPROTO_UDP) {
+	    hdr.ipv4->protocol == IPPROTO_UDP) {
 		struct ixgbe_adapter *adapter = q_vector->adapter;
 
+		if (unlikely(skb_tail_pointer(skb) < hdr.network +
+			     VXLAN_HEADROOM))
+			return;
+
 		/* verify the port is recognized as VXLAN */
 		if (adapter->vxlan_port &&
 		    udp_hdr(skb)->dest == adapter->vxlan_port)
@@ -7670,6 +7686,12 @@ static void ixgbe_atr(struct ixgbe_ring
 			hdr.network = skb_inner_network_header(skb);
 	}
 
+	/* Make sure we have at least [minimum IPv4 header + TCP]
+	 * or [IPv6 header] bytes
+	 */
+	if (unlikely(skb_tail_pointer(skb) < hdr.network + 40))
+		return;
+
 	/* Currently only IPv4/IPv6 with TCP is supported */
 	switch (hdr.ipv4->version) {
 	case IPVERSION:
@@ -7689,6 +7711,10 @@ static void ixgbe_atr(struct ixgbe_ring
 	if (l4_proto != IPPROTO_TCP)
 		return;
 
+	if (unlikely(skb_tail_pointer(skb) < hdr.network +
+		     hlen + sizeof(struct tcphdr)))
+		return;
+
 	th = (struct tcphdr *)(hdr.network + hlen);
 
 	/* skip this packet since the socket is closing */
@@ -8354,12 +8380,38 @@ static int ixgbe_configure_clsu32_del_hn
 }
 
 #ifdef CONFIG_NET_CLS_ACT
+struct upper_walk_data {
+	struct ixgbe_adapter *adapter;
+	u64 action;
+	int ifindex;
+	u8 queue;
+};
+
+static int get_macvlan_queue(struct net_device *upper, void *_data)
+{
+	if (netif_is_macvlan(upper)) {
+		struct macvlan_dev *dfwd = netdev_priv(upper);
+		struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
+		struct upper_walk_data *data = _data;
+		struct ixgbe_adapter *adapter = data->adapter;
+		int ifindex = data->ifindex;
+
+		if (vadapter && vadapter->netdev->ifindex == ifindex) {
+			data->queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
+			data->action = data->queue;
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
 static int handle_redirect_action(struct ixgbe_adapter *adapter, int ifindex,
 				  u8 *queue, u64 *action)
 {
 	unsigned int num_vfs = adapter->num_vfs, vf;
+	struct upper_walk_data data;
 	struct net_device *upper;
-	struct list_head *iter;
 
 	/* redirect to a SRIOV VF */
 	for (vf = 0; vf < num_vfs; ++vf) {
@@ -8377,17 +8429,16 @@ static int handle_redirect_action(struct
 	}
 
 	/* redirect to a offloaded macvlan netdev */
-	netdev_for_each_all_upper_dev_rcu(adapter->netdev, upper, iter) {
-		if (netif_is_macvlan(upper)) {
-			struct macvlan_dev *dfwd = netdev_priv(upper);
-			struct ixgbe_fwd_adapter *vadapter = dfwd->fwd_priv;
+	data.adapter = adapter;
+	data.ifindex = ifindex;
+	data.action = 0;
+	data.queue = 0;
+	if (netdev_walk_all_upper_dev_rcu(adapter->netdev,
+					  get_macvlan_queue, &data)) {
+		*action = data.action;
+		*queue = data.queue;
 
-			if (vadapter && vadapter->netdev->ifindex == ifindex) {
-				*queue = adapter->rx_ring[vadapter->rx_base_queue]->reg_idx;
-				*action = *queue;
-				return 0;
-			}
-		}
+		return 0;
 	}
 
 	return -EINVAL;
@@ -8414,7 +8465,7 @@ static int parse_tc_actions(struct ixgbe
 		}
 
 		/* Redirect to a VF or a offloaded macvlan */
-		if (is_tcf_mirred_redirect(a)) {
+		if (is_tcf_mirred_egress_redirect(a)) {
 			int ifindex = tcf_mirred_ifindex(a);
 
 			err = handle_redirect_action(adapter, ifindex, queue,
@@ -9481,6 +9532,8 @@ static int ixgbe_probe(struct pci_dev *p
 	hw->mac.ops   = *ii->mac_ops;
 	hw->mac.type  = ii->mac;
 	hw->mvals     = ii->mvals;
+	if (ii->link_ops)
+		hw->link.ops  = *ii->link_ops;
 
 	/* EEPROM */
 	hw->eeprom.ops = *ii->eeprom_ops;
@@ -9504,10 +9557,8 @@ static int ixgbe_probe(struct pci_dev *p
 	hw->phy.mdio.mdio_read = ixgbe_mdio_read;
 	hw->phy.mdio.mdio_write = ixgbe_mdio_write;
 
-	ii->get_invariants(hw);
-
 	/* setup the private structure */
-	err = ixgbe_sw_init(adapter);
+	err = ixgbe_sw_init(adapter, ii);
 	if (err)
 		goto err_sw_init;
 
@@ -9616,6 +9667,10 @@ skip_sriov:
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 	netdev->priv_flags |= IFF_SUPP_NOFCS;
 
+	/* MTU range: 68 - 9710 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN);
+
 #ifdef CONFIG_IXGBE_DCB
 	if (adapter->flags & IXGBE_FLAG_DCB_CAPABLE)
 		netdev->dcbnl_ops = &dcbnl_ops;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c	2017-02-12 16:03:20.000000000 -0500
@@ -109,8 +109,8 @@ static u8 ixgbe_ones_comp_byte_add(u8 ad
  *
  *  Returns an error code on error.
  */
-static s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
-					       u16 reg, u16 *val, bool lock)
+s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
+					u16 reg, u16 *val, bool lock)
 {
 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
 	int max_retry = 10;
@@ -178,36 +178,6 @@ fail:
 }
 
 /**
- *  ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
- *  @hw: pointer to the hardware structure
- *  @addr: I2C bus address to read from
- *  @reg: I2C device register to read from
- *  @val: pointer to location to receive read value
- *
- *  Returns an error code on error.
- */
-s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
-				    u16 reg, u16 *val)
-{
-	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
-}
-
-/**
- *  ixgbe_read_i2c_combined_generic_unlocked - Unlocked I2C read combined
- *  @hw: pointer to the hardware structure
- *  @addr: I2C bus address to read from
- *  @reg: I2C device register to read from
- *  @val: pointer to location to receive read value
- *
- *  Returns an error code on error.
- */
-s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
-					     u16 reg, u16 *val)
-{
-	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
-}
-
-/**
  *  ixgbe_write_i2c_combined_generic_int - Perform I2C write combined operation
  *  @hw: pointer to the hardware structure
  *  @addr: I2C bus address to write to
@@ -217,8 +187,8 @@ s32 ixgbe_read_i2c_combined_generic_unlo
  *
  *  Returns an error code on error.
  */
-static s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
-						u16 reg, u16 val, bool lock)
+s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *hw, u8 addr,
+					 u16 reg, u16 val, bool lock)
 {
 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
 	int max_retry = 1;
@@ -273,33 +243,39 @@ fail:
 }
 
 /**
- *  ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
- *  @hw: pointer to the hardware structure
- *  @addr: I2C bus address to write to
- *  @reg: I2C device register to write to
- *  @val: value to write
+ *  ixgbe_probe_phy - Probe a single address for a PHY
+ *  @hw: pointer to hardware structure
+ *  @phy_addr: PHY address to probe
  *
- *  Returns an error code on error.
- */
-s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
-				     u8 addr, u16 reg, u16 val)
+ *  Returns true if PHY found
+ **/
+static bool ixgbe_probe_phy(struct ixgbe_hw *hw, u16 phy_addr)
 {
-	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
-}
+	u16 ext_ability = 0;
 
-/**
- *  ixgbe_write_i2c_combined_generic_unlocked - Unlocked I2C write combined
- *  @hw: pointer to the hardware structure
- *  @addr: I2C bus address to write to
- *  @reg: I2C device register to write to
- *  @val: value to write
- *
- *  Returns an error code on error.
- */
-s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
-					      u8 addr, u16 reg, u16 val)
-{
-	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
+	hw->phy.mdio.prtad = phy_addr;
+	if (mdio45_probe(&hw->phy.mdio, phy_addr) != 0)
+		return false;
+
+	if (ixgbe_get_phy_id(hw))
+		return false;
+
+	hw->phy.type = ixgbe_get_phy_type_from_id(hw->phy.id);
+
+	if (hw->phy.type == ixgbe_phy_unknown) {
+		hw->phy.ops.read_reg(hw,
+				     MDIO_PMA_EXTABLE,
+				     MDIO_MMD_PMAPMD,
+				     &ext_ability);
+		if (ext_ability &
+		    (MDIO_PMA_EXTABLE_10GBT |
+		     MDIO_PMA_EXTABLE_1000BT))
+			hw->phy.type = ixgbe_phy_cu_unknown;
+		else
+			hw->phy.type = ixgbe_phy_generic;
+	}
+
+	return true;
 }
 
 /**
@@ -311,7 +287,7 @@ s32 ixgbe_write_i2c_combined_generic_unl
 s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 {
 	u32 phy_addr;
-	u16 ext_ability = 0;
+	u32 status = IXGBE_ERR_PHY_ADDR_INVALID;
 
 	if (!hw->phy.phy_semaphore_mask) {
 		if (hw->bus.lan_id)
@@ -320,37 +296,34 @@ s32 ixgbe_identify_phy_generic(struct ix
 			hw->phy.phy_semaphore_mask = IXGBE_GSSR_PHY0_SM;
 	}
 
-	if (hw->phy.type == ixgbe_phy_unknown) {
-		for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
-			hw->phy.mdio.prtad = phy_addr;
-			if (mdio45_probe(&hw->phy.mdio, phy_addr) == 0) {
-				ixgbe_get_phy_id(hw);
-				hw->phy.type =
-					ixgbe_get_phy_type_from_id(hw->phy.id);
+	if (hw->phy.type != ixgbe_phy_unknown)
+		return 0;
 
-				if (hw->phy.type == ixgbe_phy_unknown) {
-					hw->phy.ops.read_reg(hw,
-							     MDIO_PMA_EXTABLE,
-							     MDIO_MMD_PMAPMD,
-							     &ext_ability);
-					if (ext_ability &
-					    (MDIO_PMA_EXTABLE_10GBT |
-					     MDIO_PMA_EXTABLE_1000BT))
-						hw->phy.type =
-							 ixgbe_phy_cu_unknown;
-					else
-						hw->phy.type =
-							 ixgbe_phy_generic;
-				}
+	if (hw->phy.nw_mng_if_sel) {
+		phy_addr = (hw->phy.nw_mng_if_sel &
+			    IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD) >>
+			   IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT;
+		if (ixgbe_probe_phy(hw, phy_addr))
+			return 0;
+		else
+			return IXGBE_ERR_PHY_ADDR_INVALID;
+	}
 
-				return 0;
-			}
+	for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
+		if (ixgbe_probe_phy(hw, phy_addr)) {
+			status = 0;
+			break;
 		}
-		/* indicate no PHY found */
-		hw->phy.mdio.prtad = MDIO_PRTAD_NONE;
-		return IXGBE_ERR_PHY_ADDR_INVALID;
 	}
-	return 0;
+
+	/* Certain media types do not have a phy so an address will not
+	 * be found and the code will take this path.  Caller has to
+	 * decide if it is an error or not.
+	 */
+	if (status)
+		hw->phy.mdio.prtad = MDIO_PRTAD_NONE;
+
+	return status;
 }
 
 /**
@@ -416,7 +389,8 @@ static enum ixgbe_phy_type ixgbe_get_phy
 	case TN1010_PHY_ID:
 		phy_type = ixgbe_phy_tn;
 		break;
-	case X550_PHY_ID:
+	case X550_PHY_ID2:
+	case X550_PHY_ID3:
 	case X540_PHY_ID:
 		phy_type = ixgbe_phy_aq;
 		break;
@@ -427,6 +401,7 @@ static enum ixgbe_phy_type ixgbe_get_phy
 		phy_type = ixgbe_phy_nl;
 		break;
 	case X557_PHY_ID:
+	case X557_PHY_ID2:
 		phy_type = ixgbe_phy_x550em_ext_t;
 		break;
 	default:
@@ -477,8 +452,7 @@ s32 ixgbe_reset_phy_generic(struct ixgbe
 	 */
 	for (i = 0; i < 30; i++) {
 		msleep(100);
-		hw->phy.ops.read_reg(hw, MDIO_CTRL1,
-				     MDIO_MMD_PHYXS, &ctrl);
+		hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS, &ctrl);
 		if (!(ctrl & MDIO_CTRL1_RESET)) {
 			udelay(2);
 			break;
@@ -705,53 +679,52 @@ s32 ixgbe_setup_phy_link_generic(struct
 
 	ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
 
-	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
-		/* Set or unset auto-negotiation 10G advertisement */
-		hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
-				     MDIO_MMD_AN,
-				     &autoneg_reg);
+	/* Set or unset auto-negotiation 10G advertisement */
+	hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, &autoneg_reg);
 
-		autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
-		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
-			autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
+	autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
+	if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) &&
+	    (speed & IXGBE_LINK_SPEED_10GB_FULL))
+		autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
 
-		hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL,
-				      MDIO_MMD_AN,
-				      autoneg_reg);
-	}
+	hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, MDIO_MMD_AN, autoneg_reg);
 
-	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
-		/* Set or unset auto-negotiation 1G advertisement */
-		hw->phy.ops.read_reg(hw,
-				     IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
-				     MDIO_MMD_AN,
-				     &autoneg_reg);
+	hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+			     MDIO_MMD_AN, &autoneg_reg);
 
-		autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
-		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
-			autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
+	if (hw->mac.type == ixgbe_mac_X550) {
+		/* Set or unset auto-negotiation 5G advertisement */
+		autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE;
+		if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) &&
+		    (speed & IXGBE_LINK_SPEED_5GB_FULL))
+			autoneg_reg |= IXGBE_MII_5GBASE_T_ADVERTISE;
 
-		hw->phy.ops.write_reg(hw,
-				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
-				      MDIO_MMD_AN,
-				      autoneg_reg);
+		/* Set or unset auto-negotiation 2.5G advertisement */
+		autoneg_reg &= ~IXGBE_MII_2_5GBASE_T_ADVERTISE;
+		if ((hw->phy.autoneg_advertised &
+		     IXGBE_LINK_SPEED_2_5GB_FULL) &&
+		    (speed & IXGBE_LINK_SPEED_2_5GB_FULL))
+			autoneg_reg |= IXGBE_MII_2_5GBASE_T_ADVERTISE;
 	}
 
-	if (speed & IXGBE_LINK_SPEED_100_FULL) {
-		/* Set or unset auto-negotiation 100M advertisement */
-		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
-				     MDIO_MMD_AN,
-				     &autoneg_reg);
+	/* Set or unset auto-negotiation 1G advertisement */
+	autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
+	if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) &&
+	    (speed & IXGBE_LINK_SPEED_1GB_FULL))
+		autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
 
-		autoneg_reg &= ~(ADVERTISE_100FULL |
-				 ADVERTISE_100HALF);
-		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
-			autoneg_reg |= ADVERTISE_100FULL;
+	hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+			      MDIO_MMD_AN, autoneg_reg);
 
-		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
-				      MDIO_MMD_AN,
-				      autoneg_reg);
-	}
+	/* Set or unset auto-negotiation 100M advertisement */
+	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg);
+
+	autoneg_reg &= ~(ADVERTISE_100FULL | ADVERTISE_100HALF);
+	if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) &&
+	    (speed & IXGBE_LINK_SPEED_100_FULL))
+		autoneg_reg |= ADVERTISE_100FULL;
+
+	hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg);
 
 	/* Blocked by MNG FW so don't reset PHY */
 	if (ixgbe_check_reset_blocked(hw))
@@ -830,6 +803,7 @@ static s32 ixgbe_get_copper_speeds_suppo
 		hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
 		break;
 	case ixgbe_mac_X550EM_x:
+	case ixgbe_mac_x550em_a:
 		hw->phy.speeds_supported &= ~IXGBE_LINK_SPEED_100_FULL;
 		break;
 	default:
@@ -2396,9 +2370,7 @@ s32 ixgbe_set_copper_phy_power(struct ix
 	if (!on && ixgbe_mng_present(hw))
 		return 0;
 
-	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
-				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
-				      &reg);
+	status = hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, &reg);
 	if (status)
 		return status;
 
@@ -2410,8 +2382,6 @@ s32 ixgbe_set_copper_phy_power(struct ix
 		reg |= IXGBE_MDIO_PHY_SET_LOW_POWER_MODE;
 	}
 
-	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL,
-				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
-				       reg);
+	status = hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_VEND1, reg);
 	return status;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h	2017-02-12 16:03:20.000000000 -0500
@@ -195,12 +195,8 @@ s32 ixgbe_read_i2c_sff8472_generic(struc
 				   u8 *sff8472_data);
 s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
 				   u8 eeprom_data);
-s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
-				    u16 reg, u16 *val);
-s32 ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
-					     u16 reg, u16 *val);
-s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
-				     u16 reg, u16 val);
-s32 ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
-					      u16 reg, u16 val);
+s32 ixgbe_read_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
+					u16 *val, bool lock);
+s32 ixgbe_write_i2c_combined_generic_int(struct ixgbe_hw *, u8 addr, u16 reg,
+					 u16 val, bool lock);
 #endif /* _IXGBE_PHY_H_ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c	2017-02-12 16:03:20.000000000 -0500
@@ -245,7 +245,7 @@ static void ixgbe_ptp_setup_sdp_x540(str
  * result of SYSTIME is 32bits of "billions of cycles" and 32 bits of
  * "cycles", rather than seconds and nanoseconds.
  */
-static cycle_t ixgbe_ptp_read_X550(const struct cyclecounter *hw_cc)
+static u64 ixgbe_ptp_read_X550(const struct cyclecounter *hw_cc)
 {
 	struct ixgbe_adapter *adapter =
 			container_of(hw_cc, struct ixgbe_adapter, hw_cc);
@@ -282,7 +282,7 @@ static cycle_t ixgbe_ptp_read_X550(const
  * cyclecounter structure used to construct a ns counter from the
  * arbitrary fixed point registers
  */
-static cycle_t ixgbe_ptp_read_82599(const struct cyclecounter *cc)
+static u64 ixgbe_ptp_read_82599(const struct cyclecounter *cc)
 {
 	struct ixgbe_adapter *adapter =
 		container_of(cc, struct ixgbe_adapter, hw_cc);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h	2017-02-12 16:03:20.000000000 -0500
@@ -874,19 +874,13 @@ struct ixgbe_thermal_sensor_data {
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_1GB	0x4 /* 1Gb/s */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STATUS_10GB	0x6 /* 10Gb/s */
 
-#define IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG	0x20	/* 10G Control Reg */
 #define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400	/* 1G Provisioning 1 */
 #define IXGBE_MII_AUTONEG_XNP_TX_REG		0x17	/* 1G XNP Transmit */
-#define IXGBE_MII_AUTONEG_ADVERTISE_REG		0x10	/* 100M Advertisement */
-#define IXGBE_MII_10GBASE_T_ADVERTISE		0x1000	/* full duplex, bit:12*/
 #define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX	0x4000	/* full duplex, bit:14*/
 #define IXGBE_MII_1GBASE_T_ADVERTISE		0x8000	/* full duplex, bit:15*/
 #define IXGBE_MII_2_5GBASE_T_ADVERTISE		0x0400
 #define IXGBE_MII_5GBASE_T_ADVERTISE		0x0800
-#define IXGBE_MII_100BASE_T_ADVERTISE		0x0100	/* full duplex, bit:8 */
-#define IXGBE_MII_100BASE_T_ADVERTISE_HALF	0x0080	/* half duplex, bit:7 */
 #define IXGBE_MII_RESTART			0x200
-#define IXGBE_MII_AUTONEG_COMPLETE		0x20
 #define IXGBE_MII_AUTONEG_LINK_UP		0x04
 #define IXGBE_MII_AUTONEG_REG			0x0
 
@@ -1320,30 +1314,20 @@ struct ixgbe_thermal_sensor_data {
 /* MDIO definitions */
 
 #define IXGBE_MDIO_ZERO_DEV_TYPE		0x0
-#define IXGBE_MDIO_PMA_PMD_DEV_TYPE		0x1
 #define IXGBE_MDIO_PCS_DEV_TYPE		0x3
-#define IXGBE_MDIO_PHY_XS_DEV_TYPE		0x4
-#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE		0x7
-#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE	0x1E   /* Device 30 */
 #define IXGBE_TWINAX_DEV			1
 
 #define IXGBE_MDIO_COMMAND_TIMEOUT     100 /* PHY Timeout for 1 GB mode */
 
-#define IXGBE_MDIO_VENDOR_SPECIFIC_1_CONTROL      0x0    /* VS1 Control Reg */
-#define IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS       0x1    /* VS1 Status Reg */
 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS  0x0008 /* 1 = Link Up */
 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS 0x0010 /* 0 - 10G, 1 - 1G */
 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_10G_SPEED    0x0018
 #define IXGBE_MDIO_VENDOR_SPECIFIC_1_1G_SPEED     0x0010
 
-#define IXGBE_MDIO_AUTO_NEG_CONTROL	0x0 /* AUTO_NEG Control Reg */
-#define IXGBE_MDIO_AUTO_NEG_STATUS	0x1 /* AUTO_NEG Status Reg */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_STAT	0xC800 /* AUTO_NEG Vendor Status Reg */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM  0xCC00 /* AUTO_NEG Vendor TX Reg */
 #define IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2 0xCC01 /* AUTO_NEG Vendor Tx Reg */
 #define IXGBE_MDIO_AUTO_NEG_VEN_LSC	0x1 /* AUTO_NEG Vendor Tx LSC */
-#define IXGBE_MDIO_AUTO_NEG_ADVT	0x10 /* AUTO_NEG Advt Reg */
-#define IXGBE_MDIO_AUTO_NEG_LP		0x13 /* AUTO_NEG LP Status Reg */
 #define IXGBE_MDIO_AUTO_NEG_EEE_ADVT	0x3C /* AUTO_NEG EEE Advt Reg */
 
 #define IXGBE_MDIO_PHY_SET_LOW_POWER_MODE	 0x0800 /* Set low power mode */
@@ -1393,8 +1377,10 @@ struct ixgbe_thermal_sensor_data {
 #define TN1010_PHY_ID    0x00A19410
 #define TNX_FW_REV       0xB
 #define X540_PHY_ID      0x01540200
-#define X550_PHY_ID      0x01540220
+#define X550_PHY_ID2	0x01540223
+#define X550_PHY_ID3	0x01540221
 #define X557_PHY_ID      0x01540240
+#define X557_PHY_ID2	0x01540250
 #define QT2022_PHY_ID    0x0043A400
 #define ATH_PHY_ID       0x03429050
 #define AQ_FW_REV        0x20
@@ -3352,6 +3338,7 @@ struct ixgbe_mac_operations {
 	s32 (*led_off)(struct ixgbe_hw *, u32);
 	s32 (*blink_led_start)(struct ixgbe_hw *, u32);
 	s32 (*blink_led_stop)(struct ixgbe_hw *, u32);
+	s32 (*init_led_link_act)(struct ixgbe_hw *);
 
 	/* RAR, Multicast, VLAN */
 	s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32);
@@ -3372,6 +3359,7 @@ struct ixgbe_mac_operations {
 	/* Flow Control */
 	s32 (*fc_enable)(struct ixgbe_hw *);
 	s32 (*setup_fc)(struct ixgbe_hw *);
+	void (*fc_autoneg)(struct ixgbe_hw *);
 
 	/* Manageability interface */
 	s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
@@ -3410,16 +3398,28 @@ struct ixgbe_phy_operations {
 	s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *);
 	s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
 	s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
-	s32 (*read_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val);
-	s32 (*write_i2c_combined)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
 	s32 (*check_overtemp)(struct ixgbe_hw *);
 	s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
 	s32 (*enter_lplu)(struct ixgbe_hw *);
 	s32 (*handle_lasi)(struct ixgbe_hw *hw);
-	s32 (*read_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
-					  u16 *value);
-	s32 (*write_i2c_combined_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
-					   u16 value);
+	s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
+				      u8 *value);
+	s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
+				       u8 value);
+};
+
+struct ixgbe_link_operations {
+	s32 (*read_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 *val);
+	s32 (*read_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+				  u16 *val);
+	s32 (*write_link)(struct ixgbe_hw *, u8 addr, u16 reg, u16 val);
+	s32 (*write_link_unlocked)(struct ixgbe_hw *, u8 addr, u16 reg,
+				   u16 val);
+};
+
+struct ixgbe_link_info {
+	struct ixgbe_link_operations ops;
+	u8 addr;
 };
 
 struct ixgbe_eeprom_info {
@@ -3462,6 +3462,7 @@ struct ixgbe_mac_info {
 	u8				san_mac_rar_index;
 	struct ixgbe_thermal_sensor_data  thermal_sensor_data;
 	bool				set_lben;
+	u8				led_link_act;
 };
 
 struct ixgbe_phy_info {
@@ -3523,6 +3524,7 @@ struct ixgbe_hw {
 	struct ixgbe_addr_filter_info	addr_ctrl;
 	struct ixgbe_fc_info		fc;
 	struct ixgbe_phy_info		phy;
+	struct ixgbe_link_info		link;
 	struct ixgbe_eeprom_info	eeprom;
 	struct ixgbe_bus_info		bus;
 	struct ixgbe_mbx_info		mbx;
@@ -3546,6 +3548,7 @@ struct ixgbe_info {
 	const struct ixgbe_eeprom_operations	*eeprom_ops;
 	const struct ixgbe_phy_operations	*phy_ops;
 	const struct ixgbe_mbx_operations	*mbx_ops;
+	const struct ixgbe_link_operations	*link_ops;
 	const u32			*mvals;
 };
 
@@ -3593,17 +3596,35 @@ struct ixgbe_info {
 #define IXGBE_FUSES0_REV_MASK		(3u << 6)
 
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL(P)	((P) ? 0x8010 : 0x4010)
+#define IXGBE_KRM_LINK_S1(P)		((P) ? 0x8200 : 0x4200)
 #define IXGBE_KRM_LINK_CTRL_1(P)	((P) ? 0x820C : 0x420C)
 #define IXGBE_KRM_AN_CNTL_1(P)		((P) ? 0x822C : 0x422C)
 #define IXGBE_KRM_AN_CNTL_8(P)		((P) ? 0x8248 : 0x4248)
 #define IXGBE_KRM_SGMII_CTRL(P)		((P) ? 0x82A0 : 0x42A0)
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH(P)	((P) ? 0x836C : 0x436C)
 #define IXGBE_KRM_DSP_TXFFE_STATE_4(P)	((P) ? 0x8634 : 0x4634)
 #define IXGBE_KRM_DSP_TXFFE_STATE_5(P)	((P) ? 0x8638 : 0x4638)
 #define IXGBE_KRM_RX_TRN_LINKUP_CTRL(P)	((P) ? 0x8B00 : 0x4B00)
 #define IXGBE_KRM_PMD_DFX_BURNIN(P)	((P) ? 0x8E00 : 0x4E00)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20(P)	((P) ? 0x9054 : 0x5054)
 #define IXGBE_KRM_TX_COEFF_CTRL_1(P)	((P) ? 0x9520 : 0x5520)
 #define IXGBE_KRM_RX_ANA_CTL(P)		((P) ? 0x9A00 : 0x5A00)
 
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA		~(0x3 << 20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR		BIT(20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_LR		(0x2 << 20)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN		BIT(25)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN		BIT(26)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN		BIT(27)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10M		~(0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_100M		BIT(28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G		(0x2 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G		(0x3 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN		(0x4 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_2_5G		(0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK		(0x7 << 28)
+#define IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART	BIT(31)
+
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_32B		BIT(9)
 #define IXGBE_KRM_PORT_CAR_GEN_CTRL_NELB_KRPCS		BIT(11)
 
@@ -3618,6 +3639,7 @@ struct ixgbe_info {
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KR		BIT(18)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KX		BIT(24)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_EEE_CAP_KR		BIT(26)
+#define IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE		BIT(28)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE		BIT(29)
 #define IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART		BIT(31)
 
@@ -3627,6 +3649,8 @@ struct ixgbe_info {
 #define IXGBE_KRM_AN_CNTL_8_LINEAR			BIT(0)
 #define IXGBE_KRM_AN_CNTL_8_LIMITING			BIT(1)
 
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE		BIT(10)
+#define IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE		BIT(11)
 #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_100_D	BIT(12)
 #define IXGBE_KRM_SGMII_CTRL_MAC_TAR_FORCE_10_D		BIT(19)
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c	2017-02-12 16:03:20.000000000 -0500
@@ -851,6 +851,7 @@ static const struct ixgbe_mac_operations
 	.get_link_capabilities  = &ixgbe_get_copper_link_capabilities_generic,
 	.led_on                 = &ixgbe_led_on_generic,
 	.led_off                = &ixgbe_led_off_generic,
+	.init_led_link_act	= ixgbe_init_led_link_act_generic,
 	.blink_led_start        = &ixgbe_blink_led_start_X540,
 	.blink_led_stop         = &ixgbe_blink_led_stop_X540,
 	.set_rar                = &ixgbe_set_rar_generic,
@@ -866,6 +867,7 @@ static const struct ixgbe_mac_operations
 	.set_vfta               = &ixgbe_set_vfta_generic,
 	.fc_enable              = &ixgbe_fc_enable_generic,
 	.setup_fc		= ixgbe_setup_fc_generic,
+	.fc_autoneg		= ixgbe_fc_autoneg,
 	.set_fw_drv_ver         = &ixgbe_set_fw_drv_ver_generic,
 	.init_uta_tables        = &ixgbe_init_uta_tables_generic,
 	.setup_sfp              = NULL,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c	2017-02-12 16:03:20.000000000 -0500
@@ -28,11 +28,31 @@
 
 static s32 ixgbe_setup_kr_speed_x550em(struct ixgbe_hw *, ixgbe_link_speed);
 static s32 ixgbe_setup_fc_x550em(struct ixgbe_hw *);
+static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *);
+static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *);
+static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *);
 
 static s32 ixgbe_get_invariants_X550_x(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
 	struct ixgbe_phy_info *phy = &hw->phy;
+	struct ixgbe_link_info *link = &hw->link;
+
+	/* Start with X540 invariants, since so simular */
+	ixgbe_get_invariants_X540(hw);
+
+	if (mac->ops.get_media_type(hw) != ixgbe_media_type_copper)
+		phy->ops.set_phy_power = NULL;
+
+	link->addr = IXGBE_CS4227;
+
+	return 0;
+}
+
+static s32 ixgbe_get_invariants_X550_a(struct ixgbe_hw *hw)
+{
+	struct ixgbe_mac_info *mac = &hw->mac;
+	struct ixgbe_phy_info *phy = &hw->phy;
 
 	/* Start with X540 invariants, since so simular */
 	ixgbe_get_invariants_X540(hw);
@@ -69,8 +89,7 @@ static void ixgbe_setup_mux_ctl(struct i
  */
 static s32 ixgbe_read_cs4227(struct ixgbe_hw *hw, u16 reg, u16 *value)
 {
-	return hw->phy.ops.read_i2c_combined_unlocked(hw, IXGBE_CS4227, reg,
-						      value);
+	return hw->link.ops.read_link_unlocked(hw, hw->link.addr, reg, value);
 }
 
 /**
@@ -83,8 +102,7 @@ static s32 ixgbe_read_cs4227(struct ixgb
  */
 static s32 ixgbe_write_cs4227(struct ixgbe_hw *hw, u16 reg, u16 value)
 {
-	return hw->phy.ops.write_i2c_combined_unlocked(hw, IXGBE_CS4227, reg,
-						       value);
+	return hw->link.ops.write_link_unlocked(hw, hw->link.addr, reg, value);
 }
 
 /**
@@ -322,6 +340,68 @@ static s32 ixgbe_write_phy_reg_x550em(st
 	return IXGBE_NOT_IMPLEMENTED;
 }
 
+/**
+ * ixgbe_read_i2c_combined_generic - Perform I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ **/
+static s32 ixgbe_read_i2c_combined_generic(struct ixgbe_hw *hw, u8 addr,
+					   u16 reg, u16 *val)
+{
+	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, true);
+}
+
+/**
+ * ixgbe_read_i2c_combined_generic_unlocked - Do I2C read combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to read from
+ * @reg: I2C device register to read from
+ * @val: pointer to location to receive read value
+ *
+ * Returns an error code on error.
+ **/
+static s32
+ixgbe_read_i2c_combined_generic_unlocked(struct ixgbe_hw *hw, u8 addr,
+					 u16 reg, u16 *val)
+{
+	return ixgbe_read_i2c_combined_generic_int(hw, addr, reg, val, false);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic - Perform I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ **/
+static s32 ixgbe_write_i2c_combined_generic(struct ixgbe_hw *hw,
+					    u8 addr, u16 reg, u16 val)
+{
+	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, true);
+}
+
+/**
+ * ixgbe_write_i2c_combined_generic_unlocked - Do I2C write combined operation
+ * @hw: pointer to the hardware structure
+ * @addr: I2C bus address to write to
+ * @reg: I2C device register to write to
+ * @val: value to write
+ *
+ * Returns an error code on error.
+ **/
+static s32
+ixgbe_write_i2c_combined_generic_unlocked(struct ixgbe_hw *hw,
+					  u8 addr, u16 reg, u16 val)
+{
+	return ixgbe_write_i2c_combined_generic_int(hw, addr, reg, val, false);
+}
+
 /** ixgbe_init_eeprom_params_X550 - Initialize EEPROM params
  *  @hw: pointer to hardware structure
  *
@@ -1128,47 +1208,17 @@ out:
 	return ret;
 }
 
-/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
+/**
+ *  ixgbe_setup_ixfi_x550em_x - MAC specific iXFI configuration
  *  @hw: pointer to hardware structure
- *  @speed: the link speed to force
  *
- *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
- *  internal and external PHY at a specific speed, without autonegotiation.
+ *  iXfI configuration needed for ixgbe_mac_X550EM_x devices.
  **/
-static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+static s32 ixgbe_setup_ixfi_x550em_x(struct ixgbe_hw *hw)
 {
 	s32 status;
 	u32 reg_val;
 
-	/* Disable AN and force speed to 10G Serial. */
-	status = ixgbe_read_iosf_sb_reg_x550(hw,
-					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
-	if (status)
-		return status;
-
-	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
-	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
-
-	/* Select forced link speed for internal PHY. */
-	switch (*speed) {
-	case IXGBE_LINK_SPEED_10GB_FULL:
-		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
-		break;
-	case IXGBE_LINK_SPEED_1GB_FULL:
-		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
-		break;
-	default:
-		/* Other link speeds are not supported by internal KR PHY. */
-		return IXGBE_ERR_LINK_SETUP;
-	}
-
-	status = ixgbe_write_iosf_sb_reg_x550(hw,
-				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
-	if (status)
-		return status;
-
 	/* Disable training protocol FSM. */
 	status = ixgbe_read_iosf_sb_reg_x550(hw,
 				IXGBE_KRM_RX_TRN_LINKUP_CTRL(hw->bus.lan_id),
@@ -1228,20 +1278,106 @@ static s32 ixgbe_setup_ixfi_x550em(struc
 	status = ixgbe_write_iosf_sb_reg_x550(hw,
 				IXGBE_KRM_TX_COEFF_CTRL_1(hw->bus.lan_id),
 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
-	if (status)
+	return status;
+}
+
+/**
+ *  ixgbe_restart_an_internal_phy_x550em - restart autonegotiation for the
+ *  internal PHY
+ *  @hw: pointer to hardware structure
+ **/
+static s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
+{
+	s32 status;
+	u32 link_ctrl;
+
+	/* Restart auto-negotiation. */
+	status = hw->mac.ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &link_ctrl);
+
+	if (status) {
+		hw_dbg(hw, "Auto-negotiation did not complete\n");
 		return status;
+	}
 
-	/* Toggle port SW reset by AN reset. */
-	status = ixgbe_read_iosf_sb_reg_x550(hw,
+	link_ctrl |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+	status = hw->mac.ops.write_iosf_sb_reg(hw,
 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+				IXGBE_SB_IOSF_TARGET_KR_PHY, link_ctrl);
+
+	if (hw->mac.type == ixgbe_mac_x550em_a) {
+		u32 flx_mask_st20;
+
+		/* Indicate to FW that AN restart has been asserted */
+		status = hw->mac.ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_mask_st20);
+
+		if (status) {
+			hw_dbg(hw, "Auto-negotiation did not complete\n");
+			return status;
+		}
+
+		flx_mask_st20 |= IXGBE_KRM_PMD_FLX_MASK_ST20_FW_AN_RESTART;
+		status = hw->mac.ops.write_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_mask_st20);
+	}
+
+	return status;
+}
+
+/** ixgbe_setup_ixfi_x550em - Configure the KR PHY for iXFI mode.
+ *  @hw: pointer to hardware structure
+ *  @speed: the link speed to force
+ *
+ *  Configures the integrated KR PHY to use iXFI mode. Used to connect an
+ *  internal and external PHY at a specific speed, without autonegotiation.
+ **/
+static s32 ixgbe_setup_ixfi_x550em(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+{
+	s32 status;
+	u32 reg_val;
+
+	/* Disable AN and force speed to 10G Serial. */
+	status = ixgbe_read_iosf_sb_reg_x550(hw,
+					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+					IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
 	if (status)
 		return status;
 
-	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_AN_ENABLE;
+	reg_val &= ~IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_MASK;
+
+	/* Select forced link speed for internal PHY. */
+	switch (*speed) {
+	case IXGBE_LINK_SPEED_10GB_FULL:
+		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_10G;
+		break;
+	case IXGBE_LINK_SPEED_1GB_FULL:
+		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_FORCE_SPEED_1G;
+		break;
+	default:
+		/* Other link speeds are not supported by internal KR PHY. */
+		return IXGBE_ERR_LINK_SETUP;
+	}
+
 	status = ixgbe_write_iosf_sb_reg_x550(hw,
 				IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
 				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+	if (status)
+		return status;
+
+	/* Additional configuration needed for x550em_x */
+	if (hw->mac.type == ixgbe_mac_X550EM_x) {
+		status = ixgbe_setup_ixfi_x550em_x(hw);
+		if (status)
+			return status;
+	}
+
+	/* Toggle port SW reset by AN reset. */
+	status = ixgbe_restart_an_internal_phy_x550em(hw);
 
 	return status;
 }
@@ -1292,7 +1428,7 @@ ixgbe_setup_mac_link_sfp_x550em(struct i
 				__always_unused bool autoneg_wait_to_complete)
 {
 	s32 status;
-	u16 slice, value;
+	u16 reg_slice, reg_val;
 	bool setup_linear = false;
 
 	/* Check if SFP module is supported and linear */
@@ -1308,71 +1444,68 @@ ixgbe_setup_mac_link_sfp_x550em(struct i
 	if (status)
 		return status;
 
-	if (!(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE)) {
-		/* Configure CS4227 LINE side to 10G SR. */
-		slice = IXGBE_CS4227_LINE_SPARE22_MSB + (hw->bus.lan_id << 12);
-		value = IXGBE_CS4227_SPEED_10G;
-		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227,
-							  slice, value);
-		if (status)
-			goto i2c_err;
+	/* Configure internal PHY for KR/KX. */
+	ixgbe_setup_kr_speed_x550em(hw, speed);
 
-		slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
-		value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
-		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227,
-							  slice, value);
-		if (status)
-			goto i2c_err;
+	/* Configure CS4227 LINE side to proper mode. */
+	reg_slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
+	if (setup_linear)
+		reg_val = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 0x1;
+	else
+		reg_val = (IXGBE_CS4227_EDC_MODE_SR << 1) | 0x1;
 
-		/* Configure CS4227 for HOST connection rate then type. */
-		slice = IXGBE_CS4227_HOST_SPARE22_MSB + (hw->bus.lan_id << 12);
-		value = speed & IXGBE_LINK_SPEED_10GB_FULL ?
-			IXGBE_CS4227_SPEED_10G : IXGBE_CS4227_SPEED_1G;
-		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227,
-							  slice, value);
-		if (status)
-			goto i2c_err;
+	status = hw->link.ops.write_link(hw, hw->link.addr, reg_slice,
+					 reg_val);
 
-		slice = IXGBE_CS4227_HOST_SPARE24_LSB + (hw->bus.lan_id << 12);
-		if (setup_linear)
-			value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
-		else
-			value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
-		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227,
-							  slice, value);
-		if (status)
-			goto i2c_err;
+	return status;
+}
 
-		/* Setup XFI internal link. */
-		status = ixgbe_setup_ixfi_x550em(hw, &speed);
-		if (status) {
-			hw_dbg(hw, "setup_ixfi failed with %d\n", status);
-			return status;
-		}
-	} else {
-		/* Configure internal PHY for KR/KX. */
-		status = ixgbe_setup_kr_speed_x550em(hw, speed);
-		if (status) {
-			hw_dbg(hw, "setup_kr_speed failed with %d\n", status);
-			return status;
-		}
+/**
+ * ixgbe_setup_sfi_x550a - Configure the internal PHY for native SFI mode
+ * @hw: pointer to hardware structure
+ * @speed: the link speed to force
+ *
+ * Configures the integrated PHY for native SFI mode. Used to connect the
+ * internal PHY directly to an SFP cage, without autonegotiation.
+ **/
+static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
+{
+	struct ixgbe_mac_info *mac = &hw->mac;
+	s32 status;
+	u32 reg_val;
 
-		/* Configure CS4227 LINE side to proper mode. */
-		slice = IXGBE_CS4227_LINE_SPARE24_LSB + (hw->bus.lan_id << 12);
-		if (setup_linear)
-			value = (IXGBE_CS4227_EDC_MODE_CX1 << 1) | 1;
-		else
-			value = (IXGBE_CS4227_EDC_MODE_SR << 1) | 1;
-		status = ixgbe_write_i2c_combined_generic(hw, IXGBE_CS4227,
-							  slice, value);
-		if (status)
-			goto i2c_err;
+	/* Disable all AN and force speed to 10G Serial. */
+	status = mac->ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+	if (status)
+		return status;
+
+	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+	reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+
+	/* Select forced link speed for internal PHY. */
+	switch (*speed) {
+	case IXGBE_LINK_SPEED_10GB_FULL:
+		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_10G;
+		break;
+	case IXGBE_LINK_SPEED_1GB_FULL:
+		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
+		break;
+	default:
+		/* Other link speeds are not supported by internal PHY. */
+		return IXGBE_ERR_LINK_SETUP;
 	}
 
-	return 0;
+	status = mac->ops.write_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+	/* Toggle port SW reset by AN reset. */
+	status = ixgbe_restart_an_internal_phy_x550em(hw);
 
-i2c_err:
-	hw_dbg(hw, "combined i2c access failed with %d\n", status);
 	return status;
 }
 
@@ -1388,45 +1521,39 @@ ixgbe_setup_mac_link_sfp_n(struct ixgbe_
 {
 	bool setup_linear = false;
 	u32 reg_phy_int;
-	s32 rc;
+	s32 ret_val;
 
 	/* Check if SFP module is supported and linear */
-	rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
+	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
 
 	/* If no SFP module present, then return success. Return success since
 	 * SFP not present error is not excepted in the setup MAC link flow.
 	 */
-	if (rc == IXGBE_ERR_SFP_NOT_PRESENT)
+	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
 		return 0;
 
-	if (!rc)
-		return rc;
+	if (!ret_val)
+		return ret_val;
 
-	/* Configure internal PHY for native SFI */
-	rc = hw->mac.ops.read_iosf_sb_reg(hw,
-					  IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
-					  IXGBE_SB_IOSF_TARGET_KR_PHY,
-					  &reg_phy_int);
-	if (rc)
-		return rc;
+	/* Configure internal PHY for native SFI based on module type */
+	ret_val = hw->mac.ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_phy_int);
+	if (!ret_val)
+		return ret_val;
 
-	if (setup_linear) {
-		reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LIMITING;
-		reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LINEAR;
-	} else {
-		reg_phy_int |= IXGBE_KRM_AN_CNTL_8_LIMITING;
-		reg_phy_int &= ~IXGBE_KRM_AN_CNTL_8_LINEAR;
-	}
+	reg_phy_int &= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA;
+	if (!setup_linear)
+		reg_phy_int |= IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR;
 
-	rc = hw->mac.ops.write_iosf_sb_reg(hw,
-					   IXGBE_KRM_AN_CNTL_8(hw->bus.lan_id),
-					   IXGBE_SB_IOSF_TARGET_KR_PHY,
-					   reg_phy_int);
-	if (rc)
-		return rc;
+	ret_val = hw->mac.ops.write_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_phy_int);
+	if (!ret_val)
+		return ret_val;
 
-	/* Setup XFI/SFI internal link */
-	return ixgbe_setup_ixfi_x550em(hw, &speed);
+	/* Setup SFI internal link. */
+	return ixgbe_setup_sfi_x550a(hw, &speed);
 }
 
 /**
@@ -1442,19 +1569,19 @@ ixgbe_setup_mac_link_sfp_x550a(struct ix
 	u32 reg_slice, slice_offset;
 	bool setup_linear = false;
 	u16 reg_phy_ext;
-	s32 rc;
+	s32 ret_val;
 
 	/* Check if SFP module is supported and linear */
-	rc = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
+	ret_val = ixgbe_supported_sfp_modules_X550em(hw, &setup_linear);
 
 	/* If no SFP module present, then return success. Return success since
 	 * SFP not present error is not excepted in the setup MAC link flow.
 	 */
-	if (rc == IXGBE_ERR_SFP_NOT_PRESENT)
+	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
 		return 0;
 
-	if (!rc)
-		return rc;
+	if (!ret_val)
+		return ret_val;
 
 	/* Configure internal PHY for KR/KX. */
 	ixgbe_setup_kr_speed_x550em(hw, speed);
@@ -1463,10 +1590,10 @@ ixgbe_setup_mac_link_sfp_x550a(struct ix
 		return IXGBE_ERR_PHY_ADDR_INVALID;
 
 	/* Get external PHY device id */
-	rc = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
+	ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_GLOBAL_ID_MSB,
 				  IXGBE_MDIO_ZERO_DEV_TYPE, &reg_phy_ext);
-	if (rc)
-		return rc;
+	if (ret_val)
+		return ret_val;
 
 	/* When configuring quad port CS4223, the MAC instance is part
 	 * of the slice offset.
@@ -1538,7 +1665,7 @@ static s32 ixgbe_check_link_t_X550em(str
 				     bool link_up_wait_to_complete)
 {
 	u32 status;
-	u16 autoneg_status;
+	u16 i, autoneg_status;
 
 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
 		return IXGBE_ERR_CONFIG;
@@ -1550,14 +1677,18 @@ static s32 ixgbe_check_link_t_X550em(str
 	if (status || !(*link_up))
 		return status;
 
-	 /* MAC link is up, so check external PHY link.
-	  * Read this twice back to back to indicate current status.
-	  */
-	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
-				      &autoneg_status);
-	if (status)
-		return status;
+	/* MAC link is up, so check external PHY link.
+	 * Link status is latching low, and can only be used to detect link
+	 * drop, and not the current status of the link without performing
+	 * back-to-back reads.
+	 */
+	for (i = 0; i < 2; i++) {
+		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
+					      &autoneg_status);
+
+		if (status)
+			return status;
+	}
 
 	/* If external PHY link is not up, then indicate link not up */
 	if (!(autoneg_status & IXGBE_MDIO_AUTO_NEG_LINK_STATUS))
@@ -1575,7 +1706,7 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, _
 		  __always_unused bool autoneg_wait_to_complete)
 {
 	struct ixgbe_mac_info *mac = &hw->mac;
-	u32 lval, sval;
+	u32 lval, sval, flx_val;
 	s32 rc;
 
 	rc = mac->ops.read_iosf_sb_reg(hw,
@@ -1609,14 +1740,55 @@ ixgbe_setup_sgmii(struct ixgbe_hw *hw, _
 	if (rc)
 		return rc;
 
-	lval |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+	rc = mac->ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
+	if (rc)
+		return rc;
+
+	rc = mac->ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &flx_val);
+	if (rc)
+		return rc;
+
+	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_1G;
+	flx_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+	flx_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+
 	rc = mac->ops.write_iosf_sb_reg(hw,
-					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
-					IXGBE_SB_IOSF_TARGET_KR_PHY, lval);
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, flx_val);
+	if (rc)
+		return rc;
 
+	rc = ixgbe_restart_an_internal_phy_x550em(hw);
 	return rc;
 }
 
+/** ixgbe_init_mac_link_ops_X550em_a - Init mac link function pointers
+ *  @hw: pointer to hardware structure
+ **/
+static void ixgbe_init_mac_link_ops_X550em_a(struct ixgbe_hw *hw)
+{
+	struct ixgbe_mac_info *mac = &hw->mac;
+
+	switch (mac->ops.get_media_type(hw)) {
+	case ixgbe_media_type_fiber:
+		mac->ops.setup_fc = NULL;
+		mac->ops.fc_autoneg = ixgbe_fc_autoneg_fiber_x550em_a;
+		break;
+	case ixgbe_media_type_backplane:
+		mac->ops.fc_autoneg = ixgbe_fc_autoneg_backplane_x550em_a;
+		mac->ops.setup_fc = ixgbe_setup_fc_backplane_x550em_a;
+		break;
+	default:
+		break;
+	}
+}
+
 /** ixgbe_init_mac_link_ops_X550em - init mac link function pointers
  *  @hw: pointer to hardware structure
  **/
@@ -1664,6 +1836,10 @@ static void ixgbe_init_mac_link_ops_X550
 	default:
 		break;
 	}
+
+	/* Additional modification for X550em_a devices */
+	if (hw->mac.type == ixgbe_mac_x550em_a)
+		ixgbe_init_mac_link_ops_X550em_a(hw);
 }
 
 /** ixgbe_setup_sfp_modules_X550em - Setup SFP module
@@ -1740,7 +1916,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(s
 
 	/* Vendor alarm triggered */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
-				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				      MDIO_MMD_VEND1,
 				      &reg);
 
 	if (status || !(reg & IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN))
@@ -1748,7 +1924,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(s
 
 	/* Vendor Auto-Neg alarm triggered or Global alarm 1 triggered */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_FLAG,
-				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				      MDIO_MMD_VEND1,
 				      &reg);
 
 	if (status || !(reg & (IXGBE_MDIO_GLOBAL_AN_VEN_ALM_INT_EN |
@@ -1757,7 +1933,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(s
 
 	/* Global alarm triggered */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_ALARM_1,
-				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				      MDIO_MMD_VEND1,
 				      &reg);
 
 	if (status)
@@ -1772,7 +1948,7 @@ static s32 ixgbe_get_lasi_ext_t_x550em(s
 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
 		/*  device fault alarm triggered */
 		status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_FAULT_MSG,
-					  IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+					  MDIO_MMD_VEND1,
 					  &reg);
 		if (status)
 			return status;
@@ -1787,14 +1963,14 @@ static s32 ixgbe_get_lasi_ext_t_x550em(s
 
 	/* Vendor alarm 2 triggered */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_CHIP_STD_INT_FLAG,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+				      MDIO_MMD_AN, &reg);
 
 	if (status || !(reg & IXGBE_MDIO_GLOBAL_STD_ALM2_INT))
 		return status;
 
 	/* link connect/disconnect event occurred */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM2,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+				      MDIO_MMD_AN, &reg);
 
 	if (status)
 		return status;
@@ -1826,20 +2002,20 @@ static s32 ixgbe_enable_lasi_ext_t_x550e
 
 	/* Enable link status change alarm */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &reg);
+				      MDIO_MMD_AN, &reg);
 	if (status)
 		return status;
 
 	reg |= IXGBE_MDIO_PMA_TX_VEN_LASI_INT_EN;
 
 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_PMA_TX_VEN_LASI_INT_MASK,
-				       IXGBE_MDIO_AUTO_NEG_DEV_TYPE, reg);
+				       MDIO_MMD_AN, reg);
 	if (status)
 		return status;
 
 	/* Enable high temperature failure and global fault alarms */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
-				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				      MDIO_MMD_VEND1,
 				      &reg);
 	if (status)
 		return status;
@@ -1848,14 +2024,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550e
 		IXGBE_MDIO_GLOBAL_INT_DEV_FAULT_EN);
 
 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_MASK,
-				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				       MDIO_MMD_VEND1,
 				       reg);
 	if (status)
 		return status;
 
 	/* Enable vendor Auto-Neg alarm and Global Interrupt Mask 1 alarm */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
-				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				      MDIO_MMD_VEND1,
 				      &reg);
 	if (status)
 		return status;
@@ -1864,14 +2040,14 @@ static s32 ixgbe_enable_lasi_ext_t_x550e
 		IXGBE_MDIO_GLOBAL_ALARM_1_INT);
 
 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_VEN_MASK,
-				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				       MDIO_MMD_VEND1,
 				       reg);
 	if (status)
 		return status;
 
 	/* Enable chip-wide vendor alarm */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
-				      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				      MDIO_MMD_VEND1,
 				      &reg);
 	if (status)
 		return status;
@@ -1879,7 +2055,7 @@ static s32 ixgbe_enable_lasi_ext_t_x550e
 	reg |= IXGBE_MDIO_GLOBAL_VEN_ALM_INT_EN;
 
 	status = hw->phy.ops.write_reg(hw, IXGBE_MDIO_GLOBAL_INT_CHIP_STD_MASK,
-				       IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+				       MDIO_MMD_VEND1,
 				       reg);
 
 	return status;
@@ -1945,13 +2121,31 @@ static s32 ixgbe_setup_kr_speed_x550em(s
 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
 		reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_CAP_KX;
 
-	/* Restart auto-negotiation. */
-	reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
 	status = hw->mac.ops.write_iosf_sb_reg(hw,
 					IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
 					IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
 
-	return status;
+	if (hw->mac.type == ixgbe_mac_x550em_a) {
+		/* Set lane mode  to KR auto negotiation */
+		status = hw->mac.ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+
+		if (status)
+			return status;
+
+		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_MASK;
+		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_SPEED_AN;
+		reg_val |= IXGBE_KRM_PMD_FLX_MASK_ST20_AN_EN;
+		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_AN37_EN;
+		reg_val &= ~IXGBE_KRM_PMD_FLX_MASK_ST20_SGMII_EN;
+
+		status = hw->mac.ops.write_iosf_sb_reg(hw,
+				IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+	}
+
+	return ixgbe_restart_an_internal_phy_x550em(hw);
 }
 
 /** ixgbe_setup_kx4_x550em - Configure the KX4 PHY.
@@ -2020,14 +2214,12 @@ static s32 ixgbe_ext_phy_t_x550em_get_li
 	*link_up = false;
 
 	/* read this twice back to back to indicate current status */
-	ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-				   IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
 				   &autoneg_status);
 	if (ret)
 		return ret;
 
-	ret = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_STATUS,
-				   IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+	ret = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
 				   &autoneg_status);
 	if (ret)
 		return ret;
@@ -2073,7 +2265,7 @@ static s32 ixgbe_setup_internal_phy_t_x5
 		return 0;
 
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+				      MDIO_MMD_AN,
 				      &speed);
 	if (status)
 		return status;
@@ -2134,10 +2326,10 @@ static s32 ixgbe_led_on_t_x550em(struct
 
 	/* To turn on the LED, set mode to ON. */
 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
-			     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
+			     MDIO_MMD_VEND1, &phy_data);
 	phy_data |= IXGBE_X557_LED_MANUAL_SET_MASK;
 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
-			      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
+			      MDIO_MMD_VEND1, phy_data);
 
 	return 0;
 }
@@ -2156,10 +2348,10 @@ static s32 ixgbe_led_off_t_x550em(struct
 
 	/* To turn on the LED, set mode to ON. */
 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
-			     IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, &phy_data);
+			     MDIO_MMD_VEND1, &phy_data);
 	phy_data &= ~IXGBE_X557_LED_MANUAL_SET_MASK;
 	hw->phy.ops.write_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
-			      IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE, phy_data);
+			      MDIO_MMD_VEND1, phy_data);
 
 	return 0;
 }
@@ -2180,7 +2372,7 @@ static s32 ixgbe_get_lcd_t_x550em(struct
 	*lcd_speed = IXGBE_LINK_SPEED_UNKNOWN;
 
 	status = hw->phy.ops.read_reg(hw, IXGBE_AUTO_NEG_LP_STATUS,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+				      MDIO_MMD_AN,
 				      &an_lp_status);
 	if (status)
 		return status;
@@ -2281,6 +2473,90 @@ static s32 ixgbe_setup_fc_x550em(struct
 	return rc;
 }
 
+/**
+ *  ixgbe_fc_autoneg_backplane_x550em_a - Enable flow control IEEE clause 37
+ *  @hw: pointer to hardware structure
+ **/
+static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
+{
+	u32 link_s1, lp_an_page_low, an_cntl_1;
+	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+	ixgbe_link_speed speed;
+	bool link_up;
+
+	/* AN should have completed when the cable was plugged in.
+	 * Look for reasons to bail out.  Bail out if:
+	 * - FC autoneg is disabled, or if
+	 * - link is not up.
+	 */
+	if (hw->fc.disable_fc_autoneg) {
+		hw_err(hw, "Flow control autoneg is disabled");
+		goto out;
+	}
+
+	hw->mac.ops.check_link(hw, &speed, &link_up, false);
+	if (!link_up) {
+		hw_err(hw, "The link is down");
+		goto out;
+	}
+
+	/* Check at auto-negotiation has completed */
+	status = hw->mac.ops.read_iosf_sb_reg(hw,
+					IXGBE_KRM_LINK_S1(hw->bus.lan_id),
+					IXGBE_SB_IOSF_TARGET_KR_PHY, &link_s1);
+
+	if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
+		hw_dbg(hw, "Auto-Negotiation did not complete\n");
+		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+		goto out;
+	}
+
+	/* Read the 10g AN autoc and LP ability registers and resolve
+	 * local flow control settings accordingly
+	 */
+	status = hw->mac.ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl_1);
+
+	if (status) {
+		hw_dbg(hw, "Auto-Negotiation did not complete\n");
+		goto out;
+	}
+
+	status = hw->mac.ops.read_iosf_sb_reg(hw,
+				IXGBE_KRM_LP_BASE_PAGE_HIGH(hw->bus.lan_id),
+				IXGBE_SB_IOSF_TARGET_KR_PHY, &lp_an_page_low);
+
+	if (status) {
+		hw_dbg(hw, "Auto-Negotiation did not complete\n");
+		goto out;
+	}
+
+	status = ixgbe_negotiate_fc(hw, an_cntl_1, lp_an_page_low,
+				    IXGBE_KRM_AN_CNTL_1_SYM_PAUSE,
+				    IXGBE_KRM_AN_CNTL_1_ASM_PAUSE,
+				    IXGBE_KRM_LP_BASE_PAGE_HIGH_SYM_PAUSE,
+				    IXGBE_KRM_LP_BASE_PAGE_HIGH_ASM_PAUSE);
+
+out:
+	if (!status) {
+		hw->fc.fc_was_autonegged = true;
+	} else {
+		hw->fc.fc_was_autonegged = false;
+		hw->fc.current_mode = hw->fc.requested_mode;
+	}
+}
+
+/**
+ *  ixgbe_fc_autoneg_fiber_x550em_a - passthrough FC settings
+ *  @hw: pointer to hardware structure
+ **/
+static void ixgbe_fc_autoneg_fiber_x550em_a(struct ixgbe_hw *hw)
+{
+	hw->fc.fc_was_autonegged = false;
+	hw->fc.current_mode = hw->fc.requested_mode;
+}
+
 /** ixgbe_enter_lplu_x550em - Transition to low power states
  *  @hw: pointer to hardware structure
  *
@@ -2327,7 +2603,7 @@ static s32 ixgbe_enter_lplu_t_x550em(str
 		return ixgbe_set_copper_phy_power(hw, false);
 
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_STAT,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+				      MDIO_MMD_AN,
 				      &speed);
 	if (status)
 		return status;
@@ -2349,20 +2625,20 @@ static s32 ixgbe_enter_lplu_t_x550em(str
 
 	/* Clear AN completed indication */
 	status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_VENDOR_TX_ALARM,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+				      MDIO_MMD_AN,
 				      &autoneg_reg);
 	if (status)
 		return status;
 
-	status = hw->phy.ops.read_reg(hw, IXGBE_MII_10GBASE_T_AUTONEG_CTRL_REG,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+	status = hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
+				      MDIO_MMD_AN,
 				      &an_10g_cntl_reg);
 	if (status)
 		return status;
 
 	status = hw->phy.ops.read_reg(hw,
 				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
-				      IXGBE_MDIO_AUTO_NEG_DEV_TYPE,
+				      MDIO_MMD_AN,
 				      &autoneg_reg);
 	if (status)
 		return status;
@@ -2520,7 +2796,7 @@ static s32 ixgbe_init_ext_t_x550em(struc
 
 	status = hw->phy.ops.read_reg(hw,
 				      IXGBE_MDIO_TX_VENDOR_ALARMS_3,
-				      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+				      MDIO_MMD_PMAPMD,
 				      &reg);
 	if (status)
 		return status;
@@ -2531,7 +2807,7 @@ static s32 ixgbe_init_ext_t_x550em(struc
 	if (reg & IXGBE_MDIO_TX_VENDOR_ALARMS_3_RST_MASK) {
 		status = hw->phy.ops.read_reg(hw,
 					IXGBE_MDIO_GLOBAL_RES_PR_10,
-					IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+					MDIO_MMD_VEND1,
 					&reg);
 		if (status)
 			return status;
@@ -2540,7 +2816,7 @@ static s32 ixgbe_init_ext_t_x550em(struc
 
 		status = hw->phy.ops.write_reg(hw,
 					IXGBE_MDIO_GLOBAL_RES_PR_10,
-					IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+					MDIO_MMD_VEND1,
 					reg);
 		if (status)
 			return status;
@@ -2729,6 +3005,90 @@ static void ixgbe_set_source_address_pru
 }
 
 /**
+ *  ixgbe_setup_fc_backplane_x550em_a - Set up flow control
+ *  @hw: pointer to hardware structure
+ *
+ *  Called at init time to set up flow control.
+ **/
+static s32 ixgbe_setup_fc_backplane_x550em_a(struct ixgbe_hw *hw)
+{
+	s32 status = 0;
+	u32 an_cntl = 0;
+
+	/* Validate the requested mode */
+	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+	}
+
+	if (hw->fc.requested_mode == ixgbe_fc_default)
+		hw->fc.requested_mode = ixgbe_fc_full;
+
+	/* Set up the 1G and 10G flow control advertisement registers so the
+	 * HW will be able to do FC autoneg once the cable is plugged in.  If
+	 * we link at 10G, the 1G advertisement is harmless and vice versa.
+	 */
+	status = hw->mac.ops.read_iosf_sb_reg(hw,
+					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+					IXGBE_SB_IOSF_TARGET_KR_PHY, &an_cntl);
+
+	if (status) {
+		hw_dbg(hw, "Auto-Negotiation did not complete\n");
+		return status;
+	}
+
+	/* The possible values of fc.requested_mode are:
+	 * 0: Flow control is completely disabled
+	 * 1: Rx flow control is enabled (we can receive pause frames,
+	 *    but not send pause frames).
+	 * 2: Tx flow control is enabled (we can send pause frames but
+	 *    we do not support receiving pause frames).
+	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
+	 * other: Invalid.
+	 */
+	switch (hw->fc.requested_mode) {
+	case ixgbe_fc_none:
+		/* Flow control completely disabled by software override. */
+		an_cntl &= ~(IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
+			     IXGBE_KRM_AN_CNTL_1_ASM_PAUSE);
+		break;
+	case ixgbe_fc_tx_pause:
+		/* Tx Flow control is enabled, and Rx Flow control is
+		 * disabled by software override.
+		 */
+		an_cntl |= IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
+		an_cntl &= ~IXGBE_KRM_AN_CNTL_1_SYM_PAUSE;
+		break;
+	case ixgbe_fc_rx_pause:
+		/* Rx Flow control is enabled and Tx Flow control is
+		 * disabled by software override. Since there really
+		 * isn't a way to advertise that we are capable of RX
+		 * Pause ONLY, we will advertise that we support both
+		 * symmetric and asymmetric Rx PAUSE, as such we fall
+		 * through to the fc_full statement.  Later, we will
+		 * disable the adapter's ability to send PAUSE frames.
+		 */
+	case ixgbe_fc_full:
+		/* Flow control (both Rx and Tx) is enabled by SW override. */
+		an_cntl |= IXGBE_KRM_AN_CNTL_1_SYM_PAUSE |
+			   IXGBE_KRM_AN_CNTL_1_ASM_PAUSE;
+		break;
+	default:
+		hw_err(hw, "Flow control param set incorrectly\n");
+		return IXGBE_ERR_CONFIG;
+	}
+
+	status = hw->mac.ops.write_iosf_sb_reg(hw,
+					IXGBE_KRM_AN_CNTL_1(hw->bus.lan_id),
+					IXGBE_SB_IOSF_TARGET_KR_PHY, an_cntl);
+
+	/* Restart auto-negotiation. */
+	status = ixgbe_restart_an_internal_phy_x550em(hw);
+
+	return status;
+}
+
+/**
  * ixgbe_set_mux - Set mux for port 1 access with CS4227
  * @hw: pointer to hardware structure
  * @state: set mux if 1, clear if 0
@@ -2934,6 +3294,7 @@ static const struct ixgbe_mac_operations
 	X550_COMMON_MAC
 	.led_on			= ixgbe_led_on_generic,
 	.led_off		= ixgbe_led_off_generic,
+	.init_led_link_act	= ixgbe_init_led_link_act_generic,
 	.reset_hw		= &ixgbe_reset_hw_X540,
 	.get_media_type		= &ixgbe_get_media_type_X540,
 	.get_san_mac_addr	= &ixgbe_get_san_mac_addr_generic,
@@ -2948,12 +3309,14 @@ static const struct ixgbe_mac_operations
 	.prot_autoc_read	= prot_autoc_read_generic,
 	.prot_autoc_write	= prot_autoc_write_generic,
 	.setup_fc		= ixgbe_setup_fc_generic,
+	.fc_autoneg		= ixgbe_fc_autoneg,
 };
 
 static const struct ixgbe_mac_operations mac_ops_X550EM_x = {
 	X550_COMMON_MAC
 	.led_on			= ixgbe_led_on_t_x550em,
 	.led_off		= ixgbe_led_off_t_x550em,
+	.init_led_link_act	= ixgbe_init_led_link_act_generic,
 	.reset_hw		= &ixgbe_reset_hw_X550em,
 	.get_media_type		= &ixgbe_get_media_type_X550em,
 	.get_san_mac_addr	= NULL,
@@ -2966,6 +3329,7 @@ static const struct ixgbe_mac_operations
 	.release_swfw_sync	= &ixgbe_release_swfw_sync_X550em,
 	.init_swfw_sync		= &ixgbe_init_swfw_sync_X540,
 	.setup_fc		= NULL, /* defined later */
+	.fc_autoneg		= ixgbe_fc_autoneg,
 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550,
 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550,
 };
@@ -2974,6 +3338,7 @@ static struct ixgbe_mac_operations mac_o
 	X550_COMMON_MAC
 	.led_on			= ixgbe_led_on_t_x550em,
 	.led_off		= ixgbe_led_off_t_x550em,
+	.init_led_link_act	= ixgbe_init_led_link_act_generic,
 	.reset_hw		= ixgbe_reset_hw_X550em,
 	.get_media_type		= ixgbe_get_media_type_X550em,
 	.get_san_mac_addr	= NULL,
@@ -2985,6 +3350,7 @@ static struct ixgbe_mac_operations mac_o
 	.acquire_swfw_sync	= ixgbe_acquire_swfw_sync_x550em_a,
 	.release_swfw_sync	= ixgbe_release_swfw_sync_x550em_a,
 	.setup_fc		= ixgbe_setup_fc_x550em,
+	.fc_autoneg		= ixgbe_fc_autoneg,
 	.read_iosf_sb_reg	= ixgbe_read_iosf_sb_reg_x550a,
 	.write_iosf_sb_reg	= ixgbe_write_iosf_sb_reg_x550a,
 };
@@ -3036,11 +3402,6 @@ static const struct ixgbe_phy_operations
 	.identify		= &ixgbe_identify_phy_x550em,
 	.read_reg		= &ixgbe_read_phy_reg_generic,
 	.write_reg		= &ixgbe_write_phy_reg_generic,
-	.read_i2c_combined	= &ixgbe_read_i2c_combined_generic,
-	.write_i2c_combined	= &ixgbe_write_i2c_combined_generic,
-	.read_i2c_combined_unlocked = &ixgbe_read_i2c_combined_generic_unlocked,
-	.write_i2c_combined_unlocked =
-				     &ixgbe_write_i2c_combined_generic_unlocked,
 };
 
 static const struct ixgbe_phy_operations phy_ops_x550em_a = {
@@ -3053,6 +3414,13 @@ static const struct ixgbe_phy_operations
 	.write_reg_mdi		= &ixgbe_write_phy_reg_mdi,
 };
 
+static const struct ixgbe_link_operations link_ops_x550em_x = {
+	.read_link		= &ixgbe_read_i2c_combined_generic,
+	.read_link_unlocked	= &ixgbe_read_i2c_combined_generic_unlocked,
+	.write_link		= &ixgbe_write_i2c_combined_generic,
+	.write_link_unlocked	= &ixgbe_write_i2c_combined_generic_unlocked,
+};
+
 static const u32 ixgbe_mvals_X550[IXGBE_MVALS_IDX_LIMIT] = {
 	IXGBE_MVALS_INIT(X550)
 };
@@ -3083,11 +3451,12 @@ const struct ixgbe_info ixgbe_X550EM_x_i
 	.phy_ops		= &phy_ops_X550EM_x,
 	.mbx_ops		= &mbx_ops_generic,
 	.mvals			= ixgbe_mvals_X550EM_x,
+	.link_ops		= &link_ops_x550em_x,
 };
 
 const struct ixgbe_info ixgbe_x550em_a_info = {
 	.mac			= ixgbe_mac_x550em_a,
-	.get_invariants		= &ixgbe_get_invariants_X550_x,
+	.get_invariants		= &ixgbe_get_invariants_X550_a,
 	.mac_ops		= &mac_ops_x550em_a,
 	.eeprom_ops		= &eeprom_ops_X550EM_x,
 	.phy_ops		= &phy_ops_x550em_a,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -1498,6 +1498,9 @@ static void ixgbevf_free_irq(struct ixgb
 {
 	int i, q_vectors;
 
+	if (!adapter->msix_entries)
+		return;
+
 	q_vectors = adapter->num_msix_vectors;
 	i = q_vectors - 1;
 
@@ -2552,6 +2555,9 @@ static void ixgbevf_free_q_vectors(struc
  **/
 static void ixgbevf_reset_interrupt_capability(struct ixgbevf_adapter *adapter)
 {
+	if (!adapter->msix_entries)
+		return;
+
 	pci_disable_msix(adapter->pdev);
 	kfree(adapter->msix_entries);
 	adapter->msix_entries = NULL;
@@ -3746,24 +3752,8 @@ static int ixgbevf_change_mtu(struct net
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
 	struct ixgbe_hw *hw = &adapter->hw;
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
-	int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
 	int ret;
 
-	switch (adapter->hw.api_version) {
-	case ixgbe_mbox_api_11:
-	case ixgbe_mbox_api_12:
-		max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
-		break;
-	default:
-		if (adapter->hw.mac.type != ixgbe_mac_82599_vf)
-			max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
-		break;
-	}
-
-	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > max_possible_frame))
-		return -EINVAL;
-
 	spin_lock_bh(&adapter->mbx_lock);
 	/* notify the PF of our intent to use this size of frame */
 	ret = hw->mac.ops.set_rlpml(hw, max_frame);
@@ -3814,11 +3804,10 @@ static int ixgbevf_suspend(struct pci_de
 		ixgbevf_free_irq(adapter);
 		ixgbevf_free_all_tx_resources(adapter);
 		ixgbevf_free_all_rx_resources(adapter);
+		ixgbevf_clear_interrupt_scheme(adapter);
 		rtnl_unlock();
 	}
 
-	ixgbevf_clear_interrupt_scheme(adapter);
-
 #ifdef CONFIG_PM
 	retval = pci_save_state(pdev);
 	if (retval)
@@ -4108,6 +4097,23 @@ static int ixgbevf_probe(struct pci_dev
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
+	/* MTU range: 68 - 1504 or 9710 */
+	netdev->min_mtu = ETH_MIN_MTU;
+	switch (adapter->hw.api_version) {
+	case ixgbe_mbox_api_11:
+	case ixgbe_mbox_api_12:
+		netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE -
+				  (ETH_HLEN + ETH_FCS_LEN);
+		break;
+	default:
+		if (adapter->hw.mac.type != ixgbe_mac_82599_vf)
+			netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE -
+					  (ETH_HLEN + ETH_FCS_LEN);
+		else
+			netdev->max_mtu = ETH_DATA_LEN + ETH_FCS_LEN;
+		break;
+	}
+
 	if (IXGBE_REMOVED(hw->hw_addr)) {
 		err = -EIO;
 		goto err_sw_init;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/intel/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/intel/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/intel/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -58,7 +58,7 @@ config E1000E
 	tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
 	depends on PCI && (!SPARC32 || BROKEN)
 	select CRC32
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	---help---
 	  This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
 	  ethernet family of adapters. For PCI or PCI-X e1000 adapters,
@@ -83,7 +83,7 @@ config E1000E_HWTS
 config IGB
 	tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
 	depends on PCI
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	select I2C
 	select I2C_ALGOBIT
 	---help---
@@ -156,7 +156,7 @@ config IXGBE
 	tristate "Intel(R) 10GbE PCI Express adapters support"
 	depends on PCI
 	select MDIO
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	---help---
 	  This driver supports Intel(R) 10GbE PCI Express family of
 	  adapters.  For more information on how to identify your adapter, go
@@ -213,7 +213,7 @@ config IXGBEVF
 
 config I40E
 	tristate "Intel(R) Ethernet Controller XL710 Family support"
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	depends on PCI
 	---help---
 	  This driver supports Intel(R) Ethernet Controller XL710 Family of
@@ -264,7 +264,7 @@ config FM10K
 	tristate "Intel(R) FM10000 Ethernet Switch Host Interface Support"
 	default n
 	depends on PCI_MSI
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	---help---
 	  This driver supports Intel(R) FM10000 Ethernet Switch Host
 	  Interface.  For more information on how to identify your adapter,
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/jme.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/jme.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/jme.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/jme.c	2017-02-12 16:03:20.000000000 -0500
@@ -2357,14 +2357,6 @@ jme_change_mtu(struct net_device *netdev
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
 
-	if (new_mtu == jme->old_mtu)
-		return 0;
-
-	if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
-		((new_mtu) < IPV6_MIN_MTU))
-		return -EINVAL;
-
-
 	netdev->mtu = new_mtu;
 	netdev_update_features(netdev);
 
@@ -3063,6 +3055,10 @@ jme_init_one(struct pci_dev *pdev,
 	if (using_dac)
 		netdev->features	|=	NETIF_F_HIGHDMA;
 
+	/* MTU range: 1280 - 9202*/
+	netdev->min_mtu = IPV6_MIN_MTU;
+	netdev->max_mtu = MAX_ETHERNET_JUMBO_PACKET_SIZE - ETH_HLEN;
+
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 	pci_set_drvdata(pdev, netdev);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -21,6 +21,7 @@ source "drivers/net/ethernet/3com/Kconfi
 source "drivers/net/ethernet/adaptec/Kconfig"
 source "drivers/net/ethernet/aeroflex/Kconfig"
 source "drivers/net/ethernet/agere/Kconfig"
+source "drivers/net/ethernet/alacritech/Kconfig"
 source "drivers/net/ethernet/allwinner/Kconfig"
 source "drivers/net/ethernet/alteon/Kconfig"
 source "drivers/net/ethernet/altera/Kconfig"
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/korina.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/korina.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/korina.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/korina.c	2017-02-12 16:03:20.000000000 -0500
@@ -900,10 +900,10 @@ static void korina_restart_task(struct w
 				DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
 				&lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
+	korina_free_ring(dev);
+
 	if (korina_init(dev) < 0) {
 		printk(KERN_ERR "%s: cannot restart device\n", dev->name);
 		return;
@@ -1064,12 +1064,12 @@ static int korina_close(struct net_devic
 	tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
 	writel(tmp, &lp->rx_dma_regs->dmasm);
 
-	korina_free_ring(dev);
-
 	napi_disable(&lp->napi);
 
 	cancel_work_sync(&lp->restart_task);
 
+	korina_free_ring(dev);
+
 	free_irq(lp->rx_irq, dev);
 	free_irq(lp->tx_irq, dev);
 	free_irq(lp->ovr_irq, dev);
@@ -1085,7 +1085,6 @@ static const struct net_device_ops korin
 	.ndo_set_rx_mode	= korina_multicast_list,
 	.ndo_tx_timeout		= korina_tx_timeout,
 	.ndo_do_ioctl		= korina_ioctl,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address	= eth_mac_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/lantiq_etop.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/lantiq_etop.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/lantiq_etop.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/lantiq_etop.c	2017-02-12 16:03:20.000000000 -0500
@@ -303,15 +303,9 @@ ltq_etop_get_drvinfo(struct net_device *
 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
-static int
-ltq_etop_nway_reset(struct net_device *dev)
-{
-	return phy_start_aneg(dev->phydev);
-}
-
 static const struct ethtool_ops ltq_etop_ethtool_ops = {
 	.get_drvinfo = ltq_etop_get_drvinfo,
-	.nway_reset = ltq_etop_nway_reset,
+	.nway_reset = phy_ethtool_nway_reset,
 	.get_link_ksettings = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings = phy_ethtool_set_link_ksettings,
 };
@@ -519,18 +513,16 @@ ltq_etop_tx(struct sk_buff *skb, struct
 static int
 ltq_etop_change_mtu(struct net_device *dev, int new_mtu)
 {
-	int ret = eth_change_mtu(dev, new_mtu);
+	struct ltq_etop_priv *priv = netdev_priv(dev);
+	unsigned long flags;
 
-	if (!ret) {
-		struct ltq_etop_priv *priv = netdev_priv(dev);
-		unsigned long flags;
+	dev->mtu = new_mtu;
 
-		spin_lock_irqsave(&priv->lock, flags);
-		ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
-			LTQ_ETOP_IGPLEN);
-		spin_unlock_irqrestore(&priv->lock, flags);
-	}
-	return ret;
+	spin_lock_irqsave(&priv->lock, flags);
+	ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu, LTQ_ETOP_IGPLEN);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
 }
 
 static int
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -7,6 +7,7 @@ obj-$(CONFIG_NET_VENDOR_8390) += 8390/
 obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
 obj-$(CONFIG_GRETH) += aeroflex/
 obj-$(CONFIG_NET_VENDOR_AGERE) += agere/
+obj-$(CONFIG_NET_VENDOR_ALACRITECH) += alacritech/
 obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
 obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
 obj-$(CONFIG_ALTERA_TSE) += altera/
@@ -75,6 +76,7 @@ obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
 obj-$(CONFIG_NET_VENDOR_SILAN) += silan/
 obj-$(CONFIG_NET_VENDOR_SIS) += sis/
 obj-$(CONFIG_SFC) += sfc/
+obj-$(CONFIG_SFC_FALCON) += sfc/falcon/
 obj-$(CONFIG_NET_VENDOR_SGI) += sgi/
 obj-$(CONFIG_NET_VENDOR_SMSC) += smsc/
 obj-$(CONFIG_NET_VENDOR_STMICRO) += stmicro/
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -5,7 +5,7 @@
 config NET_VENDOR_MARVELL
 	bool "Marvell devices"
 	default y
-	depends on PCI || CPU_PXA168 || MV64X60 || PPC32 || PLAT_ORION || INET
+	depends on PCI || CPU_PXA168 || MV64X60 || PPC32 || PLAT_ORION || INET || COMPILE_TEST
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y.
 
@@ -18,7 +18,8 @@ if NET_VENDOR_MARVELL
 
 config MV643XX_ETH
 	tristate "Marvell Discovery (643XX) and Orion ethernet support"
-	depends on (MV64X60 || PPC32 || PLAT_ORION) && INET
+	depends on (MV64X60 || PPC32 || PLAT_ORION || COMPILE_TEST) && INET
+	depends on HAS_DMA
 	select PHYLIB
 	select MVMDIO
 	---help---
@@ -43,6 +44,7 @@ config MVMDIO
 config MVNETA_BM_ENABLE
 	tristate "Marvell Armada 38x/XP network interface BM support"
 	depends on MVNETA
+	depends on !64BIT
 	---help---
 	  This driver supports auxiliary block of the network
 	  interface units in the Marvell ARMADA XP and ARMADA 38x SoC
@@ -54,13 +56,15 @@ config MVNETA_BM_ENABLE
 	  buffer management.
 
 config MVNETA
-	tristate "Marvell Armada 370/38x/XP network interface support"
-	depends on PLAT_ORION
+	tristate "Marvell Armada 370/38x/XP/37xx network interface support"
+	depends on ARCH_MVEBU || COMPILE_TEST
+	depends on HAS_DMA
 	select MVMDIO
 	select FIXED_PHY
 	---help---
 	  This driver supports the network interface units in the
-	  Marvell ARMADA XP, ARMADA 370 and ARMADA 38x SoC family.
+	  Marvell ARMADA XP, ARMADA 370, ARMADA 38x and
+	  ARMADA 37xx SoC family.
 
 	  Note that this driver is distinct from the mv643xx_eth
 	  driver, which should be used for the older Marvell SoCs
@@ -68,16 +72,20 @@ config MVNETA
 
 config MVNETA_BM
 	tristate
+	depends on !64BIT
 	default y if MVNETA=y && MVNETA_BM_ENABLE!=n
 	default MVNETA_BM_ENABLE
 	select HWBM
+	select GENERIC_ALLOCATOR
 	help
 	  MVNETA_BM must not be 'm' if MVNETA=y, so this symbol ensures
 	  that all dependencies are met.
 
 config MVPP2
 	tristate "Marvell Armada 375 network interface support"
-	depends on MACH_ARMADA_375
+	depends on MACH_ARMADA_375 || COMPILE_TEST
+	depends on HAS_DMA
+	depends on !64BIT
 	select MVMDIO
 	---help---
 	  This driver supports the network interface units in the
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/mv643xx_eth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/mv643xx_eth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/mv643xx_eth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/mv643xx_eth.c	2017-02-12 16:03:20.000000000 -0500
@@ -384,8 +384,6 @@ struct mv643xx_eth_private {
 
 	struct net_device *dev;
 
-	struct phy_device *phy;
-
 	struct timer_list mib_counters_timer;
 	spinlock_t mib_counters_lock;
 	struct mib_counters mib_counters;
@@ -1236,7 +1234,7 @@ static void mv643xx_eth_adjust_link(stru
 		     DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
 		     DISABLE_AUTO_NEG_FOR_DUPLEX;
 
-	if (mp->phy->autoneg == AUTONEG_ENABLE) {
+	if (dev->phydev->autoneg == AUTONEG_ENABLE) {
 		/* enable auto negotiation */
 		pscr &= ~autoneg_disable;
 		goto out_write;
@@ -1244,7 +1242,7 @@ static void mv643xx_eth_adjust_link(stru
 
 	pscr |= autoneg_disable;
 
-	if (mp->phy->speed == SPEED_1000) {
+	if (dev->phydev->speed == SPEED_1000) {
 		/* force gigabit, half duplex not supported */
 		pscr |= SET_GMII_SPEED_TO_1000;
 		pscr |= SET_FULL_DUPLEX_MODE;
@@ -1253,12 +1251,12 @@ static void mv643xx_eth_adjust_link(stru
 
 	pscr &= ~SET_GMII_SPEED_TO_1000;
 
-	if (mp->phy->speed == SPEED_100)
+	if (dev->phydev->speed == SPEED_100)
 		pscr |= SET_MII_SPEED_TO_100;
 	else
 		pscr &= ~SET_MII_SPEED_TO_100;
 
-	if (mp->phy->duplex == DUPLEX_FULL)
+	if (dev->phydev->duplex == DUPLEX_FULL)
 		pscr |= SET_FULL_DUPLEX_MODE;
 	else
 		pscr &= ~SET_FULL_DUPLEX_MODE;
@@ -1499,55 +1497,69 @@ static const struct mv643xx_eth_stats mv
 };
 
 static int
-mv643xx_eth_get_settings_phy(struct mv643xx_eth_private *mp,
-			     struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings_phy(struct mv643xx_eth_private *mp,
+				   struct ethtool_link_ksettings *cmd)
 {
+	struct net_device *dev = mp->dev;
 	int err;
+	u32 supported, advertising;
 
-	err = phy_read_status(mp->phy);
+	err = phy_read_status(dev->phydev);
 	if (err == 0)
-		err = phy_ethtool_gset(mp->phy, cmd);
+		err = phy_ethtool_ksettings_get(dev->phydev, cmd);
 
 	/*
 	 * The MAC does not support 1000baseT_Half.
 	 */
-	cmd->supported &= ~SUPPORTED_1000baseT_Half;
-	cmd->advertising &= ~ADVERTISED_1000baseT_Half;
+	ethtool_convert_link_mode_to_legacy_u32(&supported,
+						cmd->link_modes.supported);
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						cmd->link_modes.advertising);
+	supported &= ~SUPPORTED_1000baseT_Half;
+	advertising &= ~ADVERTISED_1000baseT_Half;
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return err;
 }
 
 static int
-mv643xx_eth_get_settings_phyless(struct mv643xx_eth_private *mp,
-				 struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings_phyless(struct mv643xx_eth_private *mp,
+				       struct ethtool_link_ksettings *cmd)
 {
 	u32 port_status;
+	u32 supported, advertising;
 
 	port_status = rdlp(mp, PORT_STATUS);
 
-	cmd->supported = SUPPORTED_MII;
-	cmd->advertising = ADVERTISED_MII;
+	supported = SUPPORTED_MII;
+	advertising = ADVERTISED_MII;
 	switch (port_status & PORT_SPEED_MASK) {
 	case PORT_SPEED_10:
-		ethtool_cmd_speed_set(cmd, SPEED_10);
+		cmd->base.speed = SPEED_10;
 		break;
 	case PORT_SPEED_100:
-		ethtool_cmd_speed_set(cmd, SPEED_100);
+		cmd->base.speed = SPEED_100;
 		break;
 	case PORT_SPEED_1000:
-		ethtool_cmd_speed_set(cmd, SPEED_1000);
+		cmd->base.speed = SPEED_1000;
 		break;
 	default:
-		cmd->speed = -1;
+		cmd->base.speed = -1;
 		break;
 	}
-	cmd->duplex = (port_status & FULL_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
-	cmd->port = PORT_MII;
-	cmd->phy_address = 0;
-	cmd->transceiver = XCVR_INTERNAL;
-	cmd->autoneg = AUTONEG_DISABLE;
-	cmd->maxtxpkt = 1;
-	cmd->maxrxpkt = 1;
+	cmd->base.duplex = (port_status & FULL_DUPLEX) ?
+		DUPLEX_FULL : DUPLEX_HALF;
+	cmd->base.port = PORT_MII;
+	cmd->base.phy_address = 0;
+	cmd->base.autoneg = AUTONEG_DISABLE;
+
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
+						supported);
+	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
+						advertising);
 
 	return 0;
 }
@@ -1555,23 +1567,21 @@ mv643xx_eth_get_settings_phyless(struct
 static void
 mv643xx_eth_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct mv643xx_eth_private *mp = netdev_priv(dev);
 	wol->supported = 0;
 	wol->wolopts = 0;
-	if (mp->phy)
-		phy_ethtool_get_wol(mp->phy, wol);
+	if (dev->phydev)
+		phy_ethtool_get_wol(dev->phydev, wol);
 }
 
 static int
 mv643xx_eth_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct mv643xx_eth_private *mp = netdev_priv(dev);
 	int err;
 
-	if (mp->phy == NULL)
+	if (!dev->phydev)
 		return -EOPNOTSUPP;
 
-	err = phy_ethtool_set_wol(mp->phy, wol);
+	err = phy_ethtool_set_wol(dev->phydev, wol);
 	/* Given that mv643xx_eth works without the marvell-specific PHY driver,
 	 * this debugging hint is useful to have.
 	 */
@@ -1581,31 +1591,38 @@ mv643xx_eth_set_wol(struct net_device *d
 }
 
 static int
-mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+mv643xx_eth_get_link_ksettings(struct net_device *dev,
+			       struct ethtool_link_ksettings *cmd)
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
 
-	if (mp->phy != NULL)
-		return mv643xx_eth_get_settings_phy(mp, cmd);
+	if (dev->phydev)
+		return mv643xx_eth_get_link_ksettings_phy(mp, cmd);
 	else
-		return mv643xx_eth_get_settings_phyless(mp, cmd);
+		return mv643xx_eth_get_link_ksettings_phyless(mp, cmd);
 }
 
 static int
-mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+mv643xx_eth_set_link_ksettings(struct net_device *dev,
+			       const struct ethtool_link_ksettings *cmd)
 {
-	struct mv643xx_eth_private *mp = netdev_priv(dev);
+	struct ethtool_link_ksettings c = *cmd;
+	u32 advertising;
 	int ret;
 
-	if (mp->phy == NULL)
+	if (!dev->phydev)
 		return -EINVAL;
 
 	/*
 	 * The MAC does not support 1000baseT_Half.
 	 */
-	cmd->advertising &= ~ADVERTISED_1000baseT_Half;
+	ethtool_convert_link_mode_to_legacy_u32(&advertising,
+						c.link_modes.advertising);
+	advertising &= ~ADVERTISED_1000baseT_Half;
+	ethtool_convert_legacy_u32_to_link_mode(c.link_modes.advertising,
+						advertising);
 
-	ret = phy_ethtool_sset(mp->phy, cmd);
+	ret = phy_ethtool_ksettings_set(dev->phydev, &c);
 	if (!ret)
 		mv643xx_eth_adjust_link(dev);
 	return ret;
@@ -1622,16 +1639,6 @@ static void mv643xx_eth_get_drvinfo(stru
 	strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
 }
 
-static int mv643xx_eth_nway_reset(struct net_device *dev)
-{
-	struct mv643xx_eth_private *mp = netdev_priv(dev);
-
-	if (mp->phy == NULL)
-		return -EINVAL;
-
-	return genphy_restart_aneg(mp->phy);
-}
-
 static int
 mv643xx_eth_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
 {
@@ -1754,10 +1761,8 @@ static int mv643xx_eth_get_sset_count(st
 }
 
 static const struct ethtool_ops mv643xx_eth_ethtool_ops = {
-	.get_settings		= mv643xx_eth_get_settings,
-	.set_settings		= mv643xx_eth_set_settings,
 	.get_drvinfo		= mv643xx_eth_get_drvinfo,
-	.nway_reset		= mv643xx_eth_nway_reset,
+	.nway_reset		= phy_ethtool_nway_reset,
 	.get_link		= ethtool_op_get_link,
 	.get_coalesce		= mv643xx_eth_get_coalesce,
 	.set_coalesce		= mv643xx_eth_set_coalesce,
@@ -1769,6 +1774,8 @@ static const struct ethtool_ops mv643xx_
 	.get_ts_info		= ethtool_op_get_ts_info,
 	.get_wol                = mv643xx_eth_get_wol,
 	.set_wol                = mv643xx_eth_set_wol,
+	.get_link_ksettings	= mv643xx_eth_get_link_ksettings,
+	.set_link_ksettings	= mv643xx_eth_set_link_ksettings,
 };
 
 
@@ -2328,19 +2335,21 @@ static inline void oom_timer_wrapper(uns
 
 static void port_start(struct mv643xx_eth_private *mp)
 {
+	struct net_device *dev = mp->dev;
 	u32 pscr;
 	int i;
 
 	/*
 	 * Perform PHY reset, if there is a PHY.
 	 */
-	if (mp->phy != NULL) {
-		struct ethtool_cmd cmd;
+	if (dev->phydev) {
+		struct ethtool_link_ksettings cmd;
 
-		mv643xx_eth_get_settings(mp->dev, &cmd);
-		phy_init_hw(mp->phy);
-		mv643xx_eth_set_settings(mp->dev, &cmd);
-		phy_start(mp->phy);
+		mv643xx_eth_get_link_ksettings(dev, &cmd);
+		phy_init_hw(dev->phydev);
+		mv643xx_eth_set_link_ksettings(
+			dev, (const struct ethtool_link_ksettings *)&cmd);
+		phy_start(dev->phydev);
 	}
 
 	/*
@@ -2352,7 +2361,7 @@ static void port_start(struct mv643xx_et
 	wrlp(mp, PORT_SERIAL_CONTROL, pscr);
 
 	pscr |= DO_NOT_FORCE_LINK_FAIL;
-	if (mp->phy == NULL)
+	if (!dev->phydev)
 		pscr |= FORCE_LINK_PASS;
 	wrlp(mp, PORT_SERIAL_CONTROL, pscr);
 
@@ -2536,8 +2545,8 @@ static int mv643xx_eth_stop(struct net_d
 	del_timer_sync(&mp->rx_oom);
 
 	netif_carrier_off(dev);
-	if (mp->phy)
-		phy_stop(mp->phy);
+	if (dev->phydev)
+		phy_stop(dev->phydev);
 	free_irq(dev->irq, dev);
 
 	port_reset(mp);
@@ -2555,13 +2564,12 @@ static int mv643xx_eth_stop(struct net_d
 
 static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct mv643xx_eth_private *mp = netdev_priv(dev);
 	int ret;
 
-	if (mp->phy == NULL)
+	if (!dev->phydev)
 		return -ENOTSUPP;
 
-	ret = phy_mii_ioctl(mp->phy, ifr, cmd);
+	ret = phy_mii_ioctl(dev->phydev, ifr, cmd);
 	if (!ret)
 		mv643xx_eth_adjust_link(dev);
 	return ret;
@@ -2571,9 +2579,6 @@ static int mv643xx_eth_change_mtu(struct
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
 
-	if (new_mtu < 64 || new_mtu > 9500)
-		return -EINVAL;
-
 	dev->mtu = new_mtu;
 	mv643xx_eth_recalc_skb_size(mp);
 	tx_set_rate(mp, 1000000000, 16777216);
@@ -2708,7 +2713,7 @@ static const struct of_device_id mv643xx
 MODULE_DEVICE_TABLE(of, mv643xx_eth_shared_ids);
 #endif
 
-#if defined(CONFIG_OF) && !defined(CONFIG_MV64X60)
+#if defined(CONFIG_OF_IRQ) && !defined(CONFIG_MV64X60)
 #define mv643xx_eth_property(_np, _name, _v)				\
 	do {								\
 		u32 tmp;						\
@@ -3024,7 +3029,8 @@ static struct phy_device *phy_scan(struc
 
 static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex)
 {
-	struct phy_device *phy = mp->phy;
+	struct net_device *dev = mp->dev;
+	struct phy_device *phy = dev->phydev;
 
 	if (speed == 0) {
 		phy->autoneg = AUTONEG_ENABLE;
@@ -3042,6 +3048,7 @@ static void phy_init(struct mv643xx_eth_
 
 static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
 {
+	struct net_device *dev = mp->dev;
 	u32 pscr;
 
 	pscr = rdlp(mp, PORT_SERIAL_CONTROL);
@@ -3051,7 +3058,7 @@ static void init_pscr(struct mv643xx_eth
 	}
 
 	pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED;
-	if (mp->phy == NULL) {
+	if (!dev->phydev) {
 		pscr |= DISABLE_AUTO_NEG_SPEED_GMII;
 		if (speed == SPEED_1000)
 			pscr |= SET_GMII_SPEED_TO_1000;
@@ -3090,6 +3097,7 @@ static int mv643xx_eth_probe(struct plat
 	struct mv643xx_eth_platform_data *pd;
 	struct mv643xx_eth_private *mp;
 	struct net_device *dev;
+	struct phy_device *phydev = NULL;
 	struct resource *res;
 	int err;
 
@@ -3146,18 +3154,18 @@ static int mv643xx_eth_probe(struct plat
 
 	err = 0;
 	if (pd->phy_node) {
-		mp->phy = of_phy_connect(mp->dev, pd->phy_node,
-					 mv643xx_eth_adjust_link, 0,
-					 get_phy_mode(mp));
-		if (!mp->phy)
+		phydev = of_phy_connect(mp->dev, pd->phy_node,
+					mv643xx_eth_adjust_link, 0,
+					get_phy_mode(mp));
+		if (!phydev)
 			err = -ENODEV;
 		else
-			phy_addr_set(mp, mp->phy->mdio.addr);
+			phy_addr_set(mp, phydev->mdio.addr);
 	} else if (pd->phy_addr != MV643XX_ETH_PHY_NONE) {
-		mp->phy = phy_scan(mp, pd->phy_addr);
+		phydev = phy_scan(mp, pd->phy_addr);
 
-		if (IS_ERR(mp->phy))
-			err = PTR_ERR(mp->phy);
+		if (IS_ERR(phydev))
+			err = PTR_ERR(phydev);
 		else
 			phy_init(mp, pd->speed, pd->duplex);
 	}
@@ -3206,6 +3214,10 @@ static int mv643xx_eth_probe(struct plat
 	dev->priv_flags |= IFF_UNICAST_FLT;
 	dev->gso_max_segs = MV643XX_MAX_TSO_SEGS;
 
+	/* MTU range: 64 - 9500 */
+	dev->min_mtu = 64;
+	dev->max_mtu = 9500;
+
 	if (mp->shared->win_protect)
 		wrl(mp, WINDOW_PROTECT(mp->port_num), mp->shared->win_protect);
 
@@ -3239,10 +3251,11 @@ out:
 static int mv643xx_eth_remove(struct platform_device *pdev)
 {
 	struct mv643xx_eth_private *mp = platform_get_drvdata(pdev);
+	struct net_device *dev = mp->dev;
 
 	unregister_netdev(mp->dev);
-	if (mp->phy != NULL)
-		phy_disconnect(mp->phy);
+	if (dev->phydev)
+		phy_disconnect(dev->phydev);
 	cancel_work_sync(&mp->tx_timeout_task);
 
 	if (!IS_ERR(mp->clk))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/mvneta.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/mvneta.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/mvneta.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/mvneta.c	2017-02-12 16:03:20.000000000 -0500
@@ -296,6 +296,12 @@
 /* descriptor aligned size */
 #define MVNETA_DESC_ALIGNED_SIZE	32
 
+/* Number of bytes to be taken into account by HW when putting incoming data
+ * to the buffers. It is needed in case NET_SKB_PAD exceeds maximum packet
+ * offset supported in MVNETA_RXQ_CONFIG_REG(q) registers.
+ */
+#define MVNETA_RX_PKT_OFFSET_CORRECTION		64
+
 #define MVNETA_RX_PKT_SIZE(mtu) \
 	ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \
 	      ETH_HLEN + ETH_FCS_LEN,			     \
@@ -391,6 +397,9 @@ struct mvneta_port {
 	spinlock_t lock;
 	bool is_stopped;
 
+	u32 cause_rx_tx;
+	struct napi_struct napi;
+
 	/* Core clock */
 	struct clk *clk;
 	/* AXI clock */
@@ -416,6 +425,10 @@ struct mvneta_port {
 	u64 ethtool_stats[ARRAY_SIZE(mvneta_statistics)];
 
 	u32 indir[MVNETA_RSS_LU_TABLE_SIZE];
+
+	/* Flags for special SoC configurations */
+	bool neta_armada3700;
+	u16 rx_offset_correction;
 };
 
 /* The mvneta_tx_desc and mvneta_rx_desc structures describe the
@@ -561,6 +574,9 @@ struct mvneta_rx_queue {
 	u32 pkts_coal;
 	u32 time_coal;
 
+	/* Virtual address of the RX buffer */
+	void  **buf_virt_addr;
+
 	/* Virtual address of the RX DMA descriptors array */
 	struct mvneta_rx_desc *descs;
 
@@ -955,14 +971,9 @@ static int mvneta_mbus_io_win_set(struct
 	return 0;
 }
 
-/* Assign and initialize pools for port. In case of fail
- * buffer manager will remain disabled for current port.
- */
-static int mvneta_bm_port_init(struct platform_device *pdev,
-			       struct mvneta_port *pp)
+static  int mvneta_bm_port_mbus_init(struct mvneta_port *pp)
 {
-	struct device_node *dn = pdev->dev.of_node;
-	u32 long_pool_id, short_pool_id, wsize;
+	u32 wsize;
 	u8 target, attr;
 	int err;
 
@@ -981,6 +992,25 @@ static int mvneta_bm_port_init(struct pl
 		netdev_info(pp->dev, "fail to configure mbus window to BM\n");
 		return err;
 	}
+	return 0;
+}
+
+/* Assign and initialize pools for port. In case of fail
+ * buffer manager will remain disabled for current port.
+ */
+static int mvneta_bm_port_init(struct platform_device *pdev,
+			       struct mvneta_port *pp)
+{
+	struct device_node *dn = pdev->dev.of_node;
+	u32 long_pool_id, short_pool_id;
+
+	if (!pp->neta_armada3700) {
+		int ret;
+
+		ret = mvneta_bm_port_mbus_init(pp);
+		if (ret)
+			return ret;
+	}
 
 	if (of_property_read_u32(dn, "bm,pool-long", &long_pool_id)) {
 		netdev_info(pp->dev, "missing long pool id\n");
@@ -1349,22 +1379,27 @@ static void mvneta_defaults_set(struct m
 	for_each_present_cpu(cpu) {
 		int rxq_map = 0, txq_map = 0;
 		int rxq, txq;
+		if (!pp->neta_armada3700) {
+			for (rxq = 0; rxq < rxq_number; rxq++)
+				if ((rxq % max_cpu) == cpu)
+					rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
 
-		for (rxq = 0; rxq < rxq_number; rxq++)
-			if ((rxq % max_cpu) == cpu)
-				rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
+			for (txq = 0; txq < txq_number; txq++)
+				if ((txq % max_cpu) == cpu)
+					txq_map |= MVNETA_CPU_TXQ_ACCESS(txq);
 
-		for (txq = 0; txq < txq_number; txq++)
-			if ((txq % max_cpu) == cpu)
-				txq_map |= MVNETA_CPU_TXQ_ACCESS(txq);
+			/* With only one TX queue we configure a special case
+			 * which will allow to get all the irq on a single
+			 * CPU
+			 */
+			if (txq_number == 1)
+				txq_map = (cpu == pp->rxq_def) ?
+					MVNETA_CPU_TXQ_ACCESS(1) : 0;
 
-		/* With only one TX queue we configure a special case
-		 * which will allow to get all the irq on a single
-		 * CPU
-		 */
-		if (txq_number == 1)
-			txq_map = (cpu == pp->rxq_def) ?
-				MVNETA_CPU_TXQ_ACCESS(1) : 0;
+		} else {
+			txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
+			rxq_map = MVNETA_CPU_RXQ_ACCESS_ALL_MASK;
+		}
 
 		mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map);
 	}
@@ -1573,10 +1608,14 @@ static void mvneta_tx_done_pkts_coal_set
 
 /* Handle rx descriptor fill by setting buf_cookie and buf_phys_addr */
 static void mvneta_rx_desc_fill(struct mvneta_rx_desc *rx_desc,
-				u32 phys_addr, u32 cookie)
+				u32 phys_addr, void *virt_addr,
+				struct mvneta_rx_queue *rxq)
 {
-	rx_desc->buf_cookie = cookie;
+	int i;
+
 	rx_desc->buf_phys_addr = phys_addr;
+	i = rx_desc - rxq->descs;
+	rxq->buf_virt_addr[i] = virt_addr;
 }
 
 /* Decrement sent descriptors counter */
@@ -1781,7 +1820,8 @@ EXPORT_SYMBOL_GPL(mvneta_frag_free);
 
 /* Refill processing for SW buffer management */
 static int mvneta_rx_refill(struct mvneta_port *pp,
-			    struct mvneta_rx_desc *rx_desc)
+			    struct mvneta_rx_desc *rx_desc,
+			    struct mvneta_rx_queue *rxq)
 
 {
 	dma_addr_t phys_addr;
@@ -1799,7 +1839,8 @@ static int mvneta_rx_refill(struct mvnet
 		return -ENOMEM;
 	}
 
-	mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)data);
+	phys_addr += pp->rx_offset_correction;
+	mvneta_rx_desc_fill(rx_desc, phys_addr, data, rxq);
 	return 0;
 }
 
@@ -1861,7 +1902,7 @@ static void mvneta_rxq_drop_pkts(struct
 
 	for (i = 0; i < rxq->size; i++) {
 		struct mvneta_rx_desc *rx_desc = rxq->descs + i;
-		void *data = (void *)rx_desc->buf_cookie;
+		void *data = rxq->buf_virt_addr[i];
 
 		dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
 				 MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
@@ -1894,12 +1935,13 @@ static int mvneta_rx_swbm(struct mvneta_
 		unsigned char *data;
 		dma_addr_t phys_addr;
 		u32 rx_status, frag_size;
-		int rx_bytes, err;
+		int rx_bytes, err, index;
 
 		rx_done++;
 		rx_status = rx_desc->status;
 		rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
-		data = (unsigned char *)rx_desc->buf_cookie;
+		index = rx_desc - rxq->descs;
+		data = rxq->buf_virt_addr[index];
 		phys_addr = rx_desc->buf_phys_addr;
 
 		if (!mvneta_rxq_desc_is_first_last(rx_status) ||
@@ -1918,7 +1960,7 @@ err_drop_frame:
 				goto err_drop_frame;
 
 			dma_sync_single_range_for_cpu(dev->dev.parent,
-						      rx_desc->buf_phys_addr,
+						      phys_addr,
 						      MVNETA_MH_SIZE + NET_SKB_PAD,
 						      rx_bytes,
 						      DMA_FROM_DEVICE);
@@ -1938,7 +1980,7 @@ err_drop_frame:
 		}
 
 		/* Refill processing */
-		err = mvneta_rx_refill(pp, rx_desc);
+		err = mvneta_rx_refill(pp, rx_desc, rxq);
 		if (err) {
 			netdev_err(dev, "Linux processing - Can't refill\n");
 			rxq->missed++;
@@ -2020,7 +2062,7 @@ static int mvneta_rx_hwbm(struct mvneta_
 		rx_done++;
 		rx_status = rx_desc->status;
 		rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
-		data = (unsigned char *)rx_desc->buf_cookie;
+		data = (u8 *)(uintptr_t)rx_desc->buf_cookie;
 		phys_addr = rx_desc->buf_phys_addr;
 		pool_id = MVNETA_RX_GET_BM_POOL_ID(rx_desc);
 		bm_pool = &pp->bm_priv->bm_pools[pool_id];
@@ -2610,6 +2652,17 @@ static void mvneta_set_rx_mode(struct ne
 /* Interrupt handling - the callback for request_irq() */
 static irqreturn_t mvneta_isr(int irq, void *dev_id)
 {
+	struct mvneta_port *pp = (struct mvneta_port *)dev_id;
+
+	mvreg_write(pp, MVNETA_INTR_NEW_MASK, 0);
+	napi_schedule(&pp->napi);
+
+	return IRQ_HANDLED;
+}
+
+/* Interrupt handling - the callback for request_percpu_irq() */
+static irqreturn_t mvneta_percpu_isr(int irq, void *dev_id)
+{
 	struct mvneta_pcpu_port *port = (struct mvneta_pcpu_port *)dev_id;
 
 	disable_percpu_irq(port->pp->dev->irq);
@@ -2657,7 +2710,7 @@ static int mvneta_poll(struct napi_struc
 	struct mvneta_pcpu_port *port = this_cpu_ptr(pp->ports);
 
 	if (!netif_running(pp->dev)) {
-		napi_complete(&port->napi);
+		napi_complete(napi);
 		return rx_done;
 	}
 
@@ -2686,7 +2739,8 @@ static int mvneta_poll(struct napi_struc
 	 */
 	rx_queue = fls(((cause_rx_tx >> 8) & 0xff));
 
-	cause_rx_tx |= port->cause_rx_tx;
+	cause_rx_tx |= pp->neta_armada3700 ? pp->cause_rx_tx :
+		port->cause_rx_tx;
 
 	if (rx_queue) {
 		rx_queue = rx_queue - 1;
@@ -2700,11 +2754,27 @@ static int mvneta_poll(struct napi_struc
 
 	if (budget > 0) {
 		cause_rx_tx = 0;
-		napi_complete(&port->napi);
-		enable_percpu_irq(pp->dev->irq, 0);
+		napi_complete(napi);
+
+		if (pp->neta_armada3700) {
+			unsigned long flags;
+
+			local_irq_save(flags);
+			mvreg_write(pp, MVNETA_INTR_NEW_MASK,
+				    MVNETA_RX_INTR_MASK(rxq_number) |
+				    MVNETA_TX_INTR_MASK(txq_number) |
+				    MVNETA_MISCINTR_INTR_MASK);
+			local_irq_restore(flags);
+		} else {
+			enable_percpu_irq(pp->dev->irq, 0);
+		}
 	}
 
-	port->cause_rx_tx = cause_rx_tx;
+	if (pp->neta_armada3700)
+		pp->cause_rx_tx = cause_rx_tx;
+	else
+		port->cause_rx_tx = cause_rx_tx;
+
 	return rx_done;
 }
 
@@ -2716,7 +2786,7 @@ static int mvneta_rxq_fill(struct mvneta
 
 	for (i = 0; i < num; i++) {
 		memset(rxq->descs + i, 0, sizeof(struct mvneta_rx_desc));
-		if (mvneta_rx_refill(pp, rxq->descs + i) != 0) {
+		if (mvneta_rx_refill(pp, rxq->descs + i, rxq) != 0) {
 			netdev_err(pp->dev, "%s:rxq %d, %d of %d buffs  filled\n",
 				__func__, rxq->id, i, num);
 			break;
@@ -2773,7 +2843,7 @@ static int mvneta_rxq_init(struct mvneta
 	mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), rxq->size);
 
 	/* Set Offset */
-	mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD);
+	mvneta_rxq_offset_set(pp, rxq, NET_SKB_PAD - pp->rx_offset_correction);
 
 	/* Set coalescing pkts and time */
 	mvneta_rx_pkts_coal_set(pp, rxq, rxq->pkts_coal);
@@ -2784,14 +2854,14 @@ static int mvneta_rxq_init(struct mvneta
 		mvneta_rxq_buf_size_set(pp, rxq,
 					MVNETA_RX_BUF_SIZE(pp->pkt_size));
 		mvneta_rxq_bm_disable(pp, rxq);
+		mvneta_rxq_fill(pp, rxq, rxq->size);
 	} else {
 		mvneta_rxq_bm_enable(pp, rxq);
 		mvneta_rxq_long_pool_set(pp, rxq);
 		mvneta_rxq_short_pool_set(pp, rxq);
+		mvneta_rxq_non_occup_desc_add(pp, rxq, rxq->size);
 	}
 
-	mvneta_rxq_fill(pp, rxq, rxq->size);
-
 	return 0;
 }
 
@@ -2974,11 +3044,16 @@ static void mvneta_start_dev(struct mvne
 	/* start the Rx/Tx activity */
 	mvneta_port_enable(pp);
 
-	/* Enable polling on the port */
-	for_each_online_cpu(cpu) {
-		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+	if (!pp->neta_armada3700) {
+		/* Enable polling on the port */
+		for_each_online_cpu(cpu) {
+			struct mvneta_pcpu_port *port =
+				per_cpu_ptr(pp->ports, cpu);
 
-		napi_enable(&port->napi);
+			napi_enable(&port->napi);
+		}
+	} else {
+		napi_enable(&pp->napi);
 	}
 
 	/* Unmask interrupts. It has to be done from each CPU */
@@ -3000,10 +3075,15 @@ static void mvneta_stop_dev(struct mvnet
 
 	phy_stop(ndev->phydev);
 
-	for_each_online_cpu(cpu) {
-		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+	if (!pp->neta_armada3700) {
+		for_each_online_cpu(cpu) {
+			struct mvneta_pcpu_port *port =
+				per_cpu_ptr(pp->ports, cpu);
 
-		napi_disable(&port->napi);
+			napi_disable(&port->napi);
+		}
+	} else {
+		napi_disable(&pp->napi);
 	}
 
 	netif_carrier_off(pp->dev);
@@ -3024,29 +3104,6 @@ static void mvneta_stop_dev(struct mvnet
 	mvneta_rx_reset(pp);
 }
 
-/* Return positive if MTU is valid */
-static int mvneta_check_mtu_valid(struct net_device *dev, int mtu)
-{
-	if (mtu < 68) {
-		netdev_err(dev, "cannot change mtu to less than 68\n");
-		return -EINVAL;
-	}
-
-	/* 9676 == 9700 - 20 and rounding to 8 */
-	if (mtu > 9676) {
-		netdev_info(dev, "Illegal MTU value %d, round to 9676\n", mtu);
-		mtu = 9676;
-	}
-
-	if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) {
-		netdev_info(dev, "Illegal MTU value %d, rounding to %d\n",
-			mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8));
-		mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8);
-	}
-
-	return mtu;
-}
-
 static void mvneta_percpu_enable(void *arg)
 {
 	struct mvneta_port *pp = arg;
@@ -3067,9 +3124,11 @@ static int mvneta_change_mtu(struct net_
 	struct mvneta_port *pp = netdev_priv(dev);
 	int ret;
 
-	mtu = mvneta_check_mtu_valid(dev, mtu);
-	if (mtu < 0)
-		return -EINVAL;
+	if (!IS_ALIGNED(MVNETA_RX_PKT_SIZE(mtu), 8)) {
+		netdev_info(dev, "Illegal MTU value %d, rounding to %d\n",
+			    mtu, ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8));
+		mtu = ALIGN(MVNETA_RX_PKT_SIZE(mtu), 8);
+	}
 
 	dev->mtu = mtu;
 
@@ -3434,31 +3493,37 @@ static int mvneta_open(struct net_device
 		goto err_cleanup_rxqs;
 
 	/* Connect to port interrupt line */
-	ret = request_percpu_irq(pp->dev->irq, mvneta_isr,
-				 MVNETA_DRIVER_NAME, pp->ports);
+	if (pp->neta_armada3700)
+		ret = request_irq(pp->dev->irq, mvneta_isr, 0,
+				  dev->name, pp);
+	else
+		ret = request_percpu_irq(pp->dev->irq, mvneta_percpu_isr,
+					 dev->name, pp->ports);
 	if (ret) {
 		netdev_err(pp->dev, "cannot request irq %d\n", pp->dev->irq);
 		goto err_cleanup_txqs;
 	}
 
-	/* Enable per-CPU interrupt on all the CPU to handle our RX
-	 * queue interrupts
-	 */
-	on_each_cpu(mvneta_percpu_enable, pp, true);
+	if (!pp->neta_armada3700) {
+		/* Enable per-CPU interrupt on all the CPU to handle our RX
+		 * queue interrupts
+		 */
+		on_each_cpu(mvneta_percpu_enable, pp, true);
 
-	pp->is_stopped = false;
-	/* Register a CPU notifier to handle the case where our CPU
-	 * might be taken offline.
-	 */
-	ret = cpuhp_state_add_instance_nocalls(online_hpstate,
-					       &pp->node_online);
-	if (ret)
-		goto err_free_irq;
+		pp->is_stopped = false;
+		/* Register a CPU notifier to handle the case where our CPU
+		 * might be taken offline.
+		 */
+		ret = cpuhp_state_add_instance_nocalls(online_hpstate,
+						       &pp->node_online);
+		if (ret)
+			goto err_free_irq;
 
-	ret = cpuhp_state_add_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
-					       &pp->node_dead);
-	if (ret)
-		goto err_free_online_hp;
+		ret = cpuhp_state_add_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+						       &pp->node_dead);
+		if (ret)
+			goto err_free_online_hp;
+	}
 
 	/* In default link is down */
 	netif_carrier_off(pp->dev);
@@ -3474,13 +3539,20 @@ static int mvneta_open(struct net_device
 	return 0;
 
 err_free_dead_hp:
-	cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
-					    &pp->node_dead);
+	if (!pp->neta_armada3700)
+		cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+						    &pp->node_dead);
 err_free_online_hp:
-	cpuhp_state_remove_instance_nocalls(online_hpstate, &pp->node_online);
+	if (!pp->neta_armada3700)
+		cpuhp_state_remove_instance_nocalls(online_hpstate,
+						    &pp->node_online);
 err_free_irq:
-	on_each_cpu(mvneta_percpu_disable, pp, true);
-	free_percpu_irq(pp->dev->irq, pp->ports);
+	if (pp->neta_armada3700) {
+		free_irq(pp->dev->irq, pp);
+	} else {
+		on_each_cpu(mvneta_percpu_disable, pp, true);
+		free_percpu_irq(pp->dev->irq, pp->ports);
+	}
 err_cleanup_txqs:
 	mvneta_cleanup_txqs(pp);
 err_cleanup_rxqs:
@@ -3493,23 +3565,31 @@ static int mvneta_stop(struct net_device
 {
 	struct mvneta_port *pp = netdev_priv(dev);
 
-	/* Inform that we are stopping so we don't want to setup the
-	 * driver for new CPUs in the notifiers. The code of the
-	 * notifier for CPU online is protected by the same spinlock,
-	 * so when we get the lock, the notifer work is done.
-	 */
-	spin_lock(&pp->lock);
-	pp->is_stopped = true;
-	spin_unlock(&pp->lock);
+	if (!pp->neta_armada3700) {
+		/* Inform that we are stopping so we don't want to setup the
+		 * driver for new CPUs in the notifiers. The code of the
+		 * notifier for CPU online is protected by the same spinlock,
+		 * so when we get the lock, the notifer work is done.
+		 */
+		spin_lock(&pp->lock);
+		pp->is_stopped = true;
+		spin_unlock(&pp->lock);
 
-	mvneta_stop_dev(pp);
-	mvneta_mdio_remove(pp);
+		mvneta_stop_dev(pp);
+		mvneta_mdio_remove(pp);
+
+		cpuhp_state_remove_instance_nocalls(online_hpstate,
+						    &pp->node_online);
+		cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
+						    &pp->node_dead);
+		on_each_cpu(mvneta_percpu_disable, pp, true);
+		free_percpu_irq(dev->irq, pp->ports);
+	} else {
+		mvneta_stop_dev(pp);
+		mvneta_mdio_remove(pp);
+		free_irq(dev->irq, pp);
+	}
 
-	cpuhp_state_remove_instance_nocalls(online_hpstate, &pp->node_online);
-	cpuhp_state_remove_instance_nocalls(CPUHP_NET_MVNETA_DEAD,
-					    &pp->node_dead);
-	on_each_cpu(mvneta_percpu_disable, pp, true);
-	free_percpu_irq(dev->irq, pp->ports);
 	mvneta_cleanup_rxqs(pp);
 	mvneta_cleanup_txqs(pp);
 
@@ -3788,6 +3868,11 @@ static int mvneta_ethtool_set_rxfh(struc
 				   const u8 *key, const u8 hfunc)
 {
 	struct mvneta_port *pp = netdev_priv(dev);
+
+	/* Current code for Armada 3700 doesn't support RSS features yet */
+	if (pp->neta_armada3700)
+		return -EOPNOTSUPP;
+
 	/* We require at least one supported parameter to be changed
 	 * and no change in any of the unsupported parameters
 	 */
@@ -3808,6 +3893,10 @@ static int mvneta_ethtool_get_rxfh(struc
 {
 	struct mvneta_port *pp = netdev_priv(dev);
 
+	/* Current code for Armada 3700 doesn't support RSS features yet */
+	if (pp->neta_armada3700)
+		return -EOPNOTSUPP;
+
 	if (hfunc)
 		*hfunc = ETH_RSS_HASH_TOP;
 
@@ -3832,6 +3921,7 @@ static const struct net_device_ops mvnet
 };
 
 const struct ethtool_ops mvneta_eth_tool_ops = {
+	.nway_reset	= phy_ethtool_nway_reset,
 	.get_link       = ethtool_op_get_link,
 	.set_coalesce   = mvneta_ethtool_set_coalesce,
 	.get_coalesce   = mvneta_ethtool_get_coalesce,
@@ -3885,6 +3975,11 @@ static int mvneta_init(struct device *de
 		rxq->size = pp->rx_ring_size;
 		rxq->pkts_coal = MVNETA_RX_COAL_PKTS;
 		rxq->time_coal = MVNETA_RX_COAL_USEC;
+		rxq->buf_virt_addr = devm_kmalloc(pp->dev->dev.parent,
+						  rxq->size * sizeof(void *),
+						  GFP_KERNEL);
+		if (!rxq->buf_virt_addr)
+			return -ENOMEM;
 	}
 
 	return 0;
@@ -3909,16 +4004,29 @@ static void mvneta_conf_mbus_windows(str
 	win_enable = 0x3f;
 	win_protect = 0;
 
-	for (i = 0; i < dram->num_cs; i++) {
-		const struct mbus_dram_window *cs = dram->cs + i;
-		mvreg_write(pp, MVNETA_WIN_BASE(i), (cs->base & 0xffff0000) |
-			    (cs->mbus_attr << 8) | dram->mbus_dram_target_id);
+	if (dram) {
+		for (i = 0; i < dram->num_cs; i++) {
+			const struct mbus_dram_window *cs = dram->cs + i;
 
-		mvreg_write(pp, MVNETA_WIN_SIZE(i),
-			    (cs->size - 1) & 0xffff0000);
+			mvreg_write(pp, MVNETA_WIN_BASE(i),
+				    (cs->base & 0xffff0000) |
+				    (cs->mbus_attr << 8) |
+				    dram->mbus_dram_target_id);
 
-		win_enable &= ~(1 << i);
-		win_protect |= 3 << (2 * i);
+			mvreg_write(pp, MVNETA_WIN_SIZE(i),
+				    (cs->size - 1) & 0xffff0000);
+
+			win_enable &= ~(1 << i);
+			win_protect |= 3 << (2 * i);
+		}
+	} else {
+		/* For Armada3700 open default 4GB Mbus window, leaving
+		 * arbitration of target/attribute to a different layer
+		 * of configuration.
+		 */
+		mvreg_write(pp, MVNETA_WIN_SIZE(0), 0xffff0000);
+		win_enable &= ~BIT(0);
+		win_protect = 3;
 	}
 
 	mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, win_enable);
@@ -4039,8 +4147,19 @@ static int mvneta_probe(struct platform_
 
 	pp->rxq_def = rxq_def;
 
+	/* Set RX packet offset correction for platforms, whose
+	 * NET_SKB_PAD, exceeds 64B. It should be 64B for 64-bit
+	 * platforms and 0B for 32-bit ones.
+	 */
+	pp->rx_offset_correction =
+		max(0, NET_SKB_PAD - MVNETA_RX_PKT_OFFSET_CORRECTION);
+
 	pp->indir[0] = rxq_def;
 
+	/* Get special SoC configurations */
+	if (of_device_is_compatible(dn, "marvell,armada-3700-neta"))
+		pp->neta_armada3700 = true;
+
 	pp->clk = devm_clk_get(&pdev->dev, "core");
 	if (IS_ERR(pp->clk))
 		pp->clk = devm_clk_get(&pdev->dev, NULL);
@@ -4108,7 +4227,11 @@ static int mvneta_probe(struct platform_
 	pp->tx_csum_limit = tx_csum_limit;
 
 	dram_target_info = mv_mbus_dram_info();
-	if (dram_target_info)
+	/* Armada3700 requires setting default configuration of Mbus
+	 * windows, however without using filled mbus_dram_target_info
+	 * structure.
+	 */
+	if (dram_target_info || pp->neta_armada3700)
 		mvneta_conf_mbus_windows(pp, dram_target_info);
 
 	pp->tx_ring_size = MVNETA_MAX_TXD;
@@ -4141,11 +4264,20 @@ static int mvneta_probe(struct platform_
 		goto err_netdev;
 	}
 
-	for_each_present_cpu(cpu) {
-		struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
+	/* Armada3700 network controller does not support per-cpu
+	 * operation, so only single NAPI should be initialized.
+	 */
+	if (pp->neta_armada3700) {
+		netif_napi_add(dev, &pp->napi, mvneta_poll, NAPI_POLL_WEIGHT);
+	} else {
+		for_each_present_cpu(cpu) {
+			struct mvneta_pcpu_port *port =
+				per_cpu_ptr(pp->ports, cpu);
 
-		netif_napi_add(dev, &port->napi, mvneta_poll, NAPI_POLL_WEIGHT);
-		port->pp = pp;
+			netif_napi_add(dev, &port->napi, mvneta_poll,
+				       NAPI_POLL_WEIGHT);
+			port->pp = pp;
+		}
 	}
 
 	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
@@ -4154,6 +4286,11 @@ static int mvneta_probe(struct platform_
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 	dev->gso_max_segs = MVNETA_MAX_TSO_SEGS;
 
+	/* MTU range: 68 - 9676 */
+	dev->min_mtu = ETH_MIN_MTU;
+	/* 9676 == 9700 - 20 and rounding to 8 */
+	dev->max_mtu = 9676;
+
 	err = register_netdev(dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register\n");
@@ -4230,6 +4367,7 @@ static int mvneta_remove(struct platform
 static const struct of_device_id mvneta_match[] = {
 	{ .compatible = "marvell,armada-370-neta" },
 	{ .compatible = "marvell,armada-xp-neta" },
+	{ .compatible = "marvell,armada-3700-neta" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, mvneta_match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/mvpp2.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/mvpp2.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/mvpp2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/mvpp2.c	2017-02-12 16:03:20.000000000 -0500
@@ -770,6 +770,17 @@ struct mvpp2_rx_desc {
 	u32 reserved8;
 };
 
+struct mvpp2_txq_pcpu_buf {
+	/* Transmitted SKB */
+	struct sk_buff *skb;
+
+	/* Physical address of transmitted buffer */
+	dma_addr_t phys;
+
+	/* Size transmitted */
+	size_t size;
+};
+
 /* Per-CPU Tx queue control */
 struct mvpp2_txq_pcpu {
 	int cpu;
@@ -785,11 +796,8 @@ struct mvpp2_txq_pcpu {
 	/* Number of Tx DMA descriptors reserved for each CPU */
 	int reserved_num;
 
-	/* Array of transmitted skb */
-	struct sk_buff **tx_skb;
-
-	/* Array of transmitted buffers' physical addresses */
-	dma_addr_t *tx_buffs;
+	/* Infos about transmitted buffers */
+	struct mvpp2_txq_pcpu_buf *buffs;
 
 	/* Index of last TX DMA descriptor that was inserted */
 	int txq_put_index;
@@ -979,10 +987,11 @@ static void mvpp2_txq_inc_put(struct mvp
 			      struct sk_buff *skb,
 			      struct mvpp2_tx_desc *tx_desc)
 {
-	txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
-	if (skb)
-		txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] =
-							 tx_desc->buf_phys_addr;
+	struct mvpp2_txq_pcpu_buf *tx_buf =
+		txq_pcpu->buffs + txq_pcpu->txq_put_index;
+	tx_buf->skb = skb;
+	tx_buf->size = tx_desc->data_size;
+	tx_buf->phys = tx_desc->buf_phys_addr;
 	txq_pcpu->txq_put_index++;
 	if (txq_pcpu->txq_put_index == txq_pcpu->size)
 		txq_pcpu->txq_put_index = 0;
@@ -4401,17 +4410,16 @@ static void mvpp2_txq_bufs_free(struct m
 	int i;
 
 	for (i = 0; i < num; i++) {
-		dma_addr_t buf_phys_addr =
-				    txq_pcpu->tx_buffs[txq_pcpu->txq_get_index];
-		struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
+		struct mvpp2_txq_pcpu_buf *tx_buf =
+			txq_pcpu->buffs + txq_pcpu->txq_get_index;
 
 		mvpp2_txq_inc_get(txq_pcpu);
 
-		dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
-				 skb_headlen(skb), DMA_TO_DEVICE);
-		if (!skb)
+		dma_unmap_single(port->dev->dev.parent, tx_buf->phys,
+				 tx_buf->size, DMA_TO_DEVICE);
+		if (!tx_buf->skb)
 			continue;
-		dev_kfree_skb_any(skb);
+		dev_kfree_skb_any(tx_buf->skb);
 	}
 }
 
@@ -4651,15 +4659,10 @@ static int mvpp2_txq_init(struct mvpp2_p
 	for_each_present_cpu(cpu) {
 		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
 		txq_pcpu->size = txq->size;
-		txq_pcpu->tx_skb = kmalloc(txq_pcpu->size *
-					   sizeof(*txq_pcpu->tx_skb),
-					   GFP_KERNEL);
-		if (!txq_pcpu->tx_skb)
-			goto error;
-
-		txq_pcpu->tx_buffs = kmalloc(txq_pcpu->size *
-					     sizeof(dma_addr_t), GFP_KERNEL);
-		if (!txq_pcpu->tx_buffs)
+		txq_pcpu->buffs = kmalloc(txq_pcpu->size *
+					  sizeof(struct mvpp2_txq_pcpu_buf),
+					  GFP_KERNEL);
+		if (!txq_pcpu->buffs)
 			goto error;
 
 		txq_pcpu->count = 0;
@@ -4673,8 +4676,7 @@ static int mvpp2_txq_init(struct mvpp2_p
 error:
 	for_each_present_cpu(cpu) {
 		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
-		kfree(txq_pcpu->tx_skb);
-		kfree(txq_pcpu->tx_buffs);
+		kfree(txq_pcpu->buffs);
 	}
 
 	dma_free_coherent(port->dev->dev.parent,
@@ -4693,8 +4695,7 @@ static void mvpp2_txq_deinit(struct mvpp
 
 	for_each_present_cpu(cpu) {
 		txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
-		kfree(txq_pcpu->tx_skb);
-		kfree(txq_pcpu->tx_buffs);
+		kfree(txq_pcpu->buffs);
 	}
 
 	if (txq->descs)
@@ -4912,7 +4913,7 @@ static void mvpp2_timer_set(struct mvpp2
 
 	if (!port_pcpu->timer_scheduled) {
 		port_pcpu->timer_scheduled = true;
-		interval = ktime_set(0, MVPP2_TXDONE_HRTIMER_PERIOD_NS);
+		interval = MVPP2_TXDONE_HRTIMER_PERIOD_NS;
 		hrtimer_start(&port_pcpu->tx_done_timer, interval,
 			      HRTIMER_MODE_REL_PINNED);
 	}
@@ -5453,29 +5454,6 @@ static void mvpp2_stop_dev(struct mvpp2_
 	phy_stop(ndev->phydev);
 }
 
-/* Return positive if MTU is valid */
-static inline int mvpp2_check_mtu_valid(struct net_device *dev, int mtu)
-{
-	if (mtu < 68) {
-		netdev_err(dev, "cannot change mtu to less than 68\n");
-		return -EINVAL;
-	}
-
-	/* 9676 == 9700 - 20 and rounding to 8 */
-	if (mtu > 9676) {
-		netdev_info(dev, "illegal MTU value %d, round to 9676\n", mtu);
-		mtu = 9676;
-	}
-
-	if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
-		netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu,
-			    ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8));
-		mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
-	}
-
-	return mtu;
-}
-
 static int mvpp2_check_ringparam_valid(struct net_device *dev,
 				       struct ethtool_ringparam *ring)
 {
@@ -5717,10 +5695,10 @@ static int mvpp2_change_mtu(struct net_d
 	struct mvpp2_port *port = netdev_priv(dev);
 	int err;
 
-	mtu = mvpp2_check_mtu_valid(dev, mtu);
-	if (mtu < 0) {
-		err = mtu;
-		goto error;
+	if (!IS_ALIGNED(MVPP2_RX_PKT_SIZE(mtu), 8)) {
+		netdev_info(dev, "illegal MTU value %d, round to %d\n", mtu,
+			    ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8));
+		mtu = ALIGN(MVPP2_RX_PKT_SIZE(mtu), 8);
 	}
 
 	if (!netif_running(dev)) {
@@ -5946,6 +5924,7 @@ static const struct net_device_ops mvpp2
 };
 
 static const struct ethtool_ops mvpp2_eth_tool_ops = {
+	.nway_reset	= phy_ethtool_nway_reset,
 	.get_link	= ethtool_op_get_link,
 	.set_coalesce	= mvpp2_ethtool_set_coalesce,
 	.get_coalesce	= mvpp2_ethtool_get_coalesce,
@@ -6212,6 +6191,11 @@ static int mvpp2_port_probe(struct platf
 	dev->hw_features |= features | NETIF_F_RXCSUM | NETIF_F_GRO;
 	dev->vlan_features |= features;
 
+	/* MTU range: 68 - 9676 */
+	dev->min_mtu = ETH_MIN_MTU;
+	/* 9676 == 9700 - 20 and rounding to 8 */
+	dev->max_mtu = 9676;
+
 	err = register_netdev(dev);
 	if (err < 0) {
 		dev_err(&pdev->dev, "failed to register netdev\n");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/pxa168_eth.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/pxa168_eth.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/pxa168_eth.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/pxa168_eth.c	2017-02-12 16:03:20.000000000 -0500
@@ -1209,9 +1209,6 @@ static int pxa168_eth_change_mtu(struct
 	int retval;
 	struct pxa168_eth_private *pep = netdev_priv(dev);
 
-	if ((mtu > 9500) || (mtu < 68))
-		return -EINVAL;
-
 	dev->mtu = mtu;
 	retval = set_port_config_ext(pep);
 
@@ -1396,6 +1393,7 @@ static void pxa168_get_drvinfo(struct ne
 
 static const struct ethtool_ops pxa168_ethtool_ops = {
 	.get_drvinfo	= pxa168_get_drvinfo,
+	.nway_reset	= phy_ethtool_nway_reset,
 	.get_link	= ethtool_op_get_link,
 	.get_ts_info	= ethtool_op_get_ts_info,
 	.get_link_ksettings = pxa168_get_link_ksettings,
@@ -1459,6 +1457,10 @@ static int pxa168_eth_probe(struct platf
 	dev->base_addr = 0;
 	dev->ethtool_ops = &pxa168_ethtool_ops;
 
+	/* MTU range: 68 - 9500 */
+	dev->min_mtu = ETH_MIN_MTU;
+	dev->max_mtu = 9500;
+
 	INIT_WORK(&pep->tx_timeout_task, pxa168_eth_tx_timeout_task);
 
 	if (pdev->dev.of_node)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/skge.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/skge.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/skge.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/skge.c	2017-02-12 16:03:20.000000000 -0500
@@ -1048,7 +1048,7 @@ static const char *skge_pause(enum pause
 static void skge_link_up(struct skge_port *skge)
 {
 	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
-		    LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
+		    LED_BLK_OFF|LED_SYNC_OFF|LED_REG_ON);
 
 	netif_carrier_on(skge->netdev);
 	netif_wake_queue(skge->netdev);
@@ -1062,7 +1062,7 @@ static void skge_link_up(struct skge_por
 
 static void skge_link_down(struct skge_port *skge)
 {
-	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF);
 	netif_carrier_off(skge->netdev);
 	netif_stop_queue(skge->netdev);
 
@@ -2668,7 +2668,7 @@ static int skge_down(struct net_device *
 	if (hw->ports == 1)
 		free_irq(hw->pdev->irq, hw);
 
-	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+	skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_REG_OFF);
 	if (is_genesis(hw))
 		genesis_stop(skge);
 	else
@@ -2900,9 +2900,6 @@ static int skge_change_mtu(struct net_de
 {
 	int err;
 
-	if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
-		return -EINVAL;
-
 	if (!netif_running(dev)) {
 		dev->mtu = new_mtu;
 		return 0;
@@ -3857,6 +3854,10 @@ static struct net_device *skge_devinit(s
 	dev->watchdog_timeo = TX_WATCHDOG;
 	dev->irq = hw->pdev->irq;
 
+	/* MTU range: 60 - 9000 */
+	dev->min_mtu = ETH_ZLEN;
+	dev->max_mtu = ETH_JUMBO_MTU;
+
 	if (highmem)
 		dev->features |= NETIF_F_HIGHDMA;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/skge.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/skge.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/skge.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/skge.h	2017-02-12 16:03:20.000000000 -0500
@@ -662,8 +662,8 @@ enum {
 	LED_BLK_OFF	= 1<<4,	/* Link LED Blinking Off */
 	LED_SYNC_ON	= 1<<3,	/* Use Sync Wire to switch LED */
 	LED_SYNC_OFF	= 1<<2,	/* Disable Sync Wire Input */
-	LED_ON	= 1<<1,	/* switch LED on */
-	LED_OFF	= 1<<0,	/* switch LED off */
+	LED_REG_ON	= 1<<1,	/* switch LED on */
+	LED_REG_OFF	= 1<<0,	/* switch LED off */
 };
 
 /* Receive GMAC FIFO (YUKON) */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/marvell/sky2.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/sky2.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/marvell/sky2.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/marvell/sky2.c	2017-02-12 16:03:20.000000000 -0500
@@ -2398,16 +2398,6 @@ static int sky2_change_mtu(struct net_de
 	u16 ctl, mode;
 	u32 imask;
 
-	/* MTU size outside the spec */
-	if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
-		return -EINVAL;
-
-	/* MTU > 1500 on yukon FE and FE+ not allowed */
-	if (new_mtu > ETH_DATA_LEN &&
-	    (hw->chip_id == CHIP_ID_YUKON_FE ||
-	     hw->chip_id == CHIP_ID_YUKON_FE_P))
-		return -EINVAL;
-
 	if (!netif_running(dev)) {
 		dev->mtu = new_mtu;
 		netdev_update_features(dev);
@@ -4808,6 +4798,14 @@ static struct net_device *sky2_init_netd
 
 	dev->features |= dev->hw_features;
 
+	/* MTU range: 60 - 1500 or 9000 */
+	dev->min_mtu = ETH_ZLEN;
+	if (hw->chip_id == CHIP_ID_YUKON_FE ||
+	    hw->chip_id == CHIP_ID_YUKON_FE_P)
+		dev->max_mtu = ETH_DATA_LEN;
+	else
+		dev->max_mtu = ETH_JUMBO_MTU;
+
 	/* try to get mac address in the following order:
 	 * 1) from device tree data
 	 * 2) from internal registers set by bootloader
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mediatek/mtk_eth_soc.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mediatek/mtk_eth_soc.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mediatek/mtk_eth_soc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mediatek/mtk_eth_soc.c	2017-02-12 16:03:20.000000000 -0500
@@ -845,7 +845,7 @@ static int mtk_start_xmit(struct sk_buff
 drop:
 	spin_unlock(&eth->page_lock);
 	stats->tx_dropped++;
-	dev_kfree_skb(skb);
+	dev_kfree_skb_any(skb);
 	return NETDEV_TX_OK;
 }
 
@@ -2247,7 +2247,6 @@ static const struct net_device_ops mtk_n
 	.ndo_set_mac_address	= mtk_set_mac_address,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= mtk_do_ioctl,
-	.ndo_change_mtu		= eth_change_mtu,
 	.ndo_tx_timeout		= mtk_tx_timeout,
 	.ndo_get_stats64        = mtk_get_stats64,
 	.ndo_fix_features	= mtk_fix_features,
@@ -2518,7 +2517,7 @@ static int mtk_remove(struct platform_de
 }
 
 const struct of_device_id of_mtk_match[] = {
-	{ .compatible = "mediatek,mt7623-eth" },
+	{ .compatible = "mediatek,mt2701-eth" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, of_mtk_match);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/catas.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/catas.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/catas.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/catas.c	2017-02-12 16:03:20.000000000 -0500
@@ -158,7 +158,7 @@ static int mlx4_reset_slave(struct mlx4_
 	return -ETIMEDOUT;
 }
 
-static int mlx4_comm_internal_err(u32 slave_read)
+int mlx4_comm_internal_err(u32 slave_read)
 {
 	return (u32)COMM_CHAN_EVENT_INTERNAL_ERR ==
 		(slave_read & (u32)COMM_CHAN_EVENT_INTERNAL_ERR) ? 1 : 0;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -2679,15 +2679,13 @@ struct mlx4_cmd_mailbox *mlx4_alloc_cmd_
 	if (!mailbox)
 		return ERR_PTR(-ENOMEM);
 
-	mailbox->buf = pci_pool_alloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL,
-				      &mailbox->dma);
+	mailbox->buf = pci_pool_zalloc(mlx4_priv(dev)->cmd.pool, GFP_KERNEL,
+				       &mailbox->dma);
 	if (!mailbox->buf) {
 		kfree(mailbox);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
-
 	return mailbox;
 }
 EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/cq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/cq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/cq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/cq.c	2017-02-12 16:03:20.000000000 -0500
@@ -101,13 +101,19 @@ void mlx4_cq_completion(struct mlx4_dev
 {
 	struct mlx4_cq *cq;
 
+	rcu_read_lock();
 	cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
 			       cqn & (dev->caps.num_cqs - 1));
+	rcu_read_unlock();
+
 	if (!cq) {
 		mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn);
 		return;
 	}
 
+	/* Acessing the CQ outside of rcu_read_lock is safe, because
+	 * the CQ is freed only after interrupt handling is completed.
+	 */
 	++cq->arm_sn;
 
 	cq->comp(cq);
@@ -118,23 +124,19 @@ void mlx4_cq_event(struct mlx4_dev *dev,
 	struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
 	struct mlx4_cq *cq;
 
-	spin_lock(&cq_table->lock);
-
+	rcu_read_lock();
 	cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
-	if (cq)
-		atomic_inc(&cq->refcount);
-
-	spin_unlock(&cq_table->lock);
+	rcu_read_unlock();
 
 	if (!cq) {
-		mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
+		mlx4_dbg(dev, "Async event for bogus CQ %08x\n", cqn);
 		return;
 	}
 
+	/* Acessing the CQ outside of rcu_read_lock is safe, because
+	 * the CQ is freed only after interrupt handling is completed.
+	 */
 	cq->event(cq, event_type);
-
-	if (atomic_dec_and_test(&cq->refcount))
-		complete(&cq->free);
 }
 
 static int mlx4_SW2HW_CQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
@@ -301,9 +303,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev,
 	if (err)
 		return err;
 
-	spin_lock_irq(&cq_table->lock);
+	spin_lock(&cq_table->lock);
 	err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
-	spin_unlock_irq(&cq_table->lock);
+	spin_unlock(&cq_table->lock);
 	if (err)
 		goto err_icm;
 
@@ -349,9 +351,9 @@ int mlx4_cq_alloc(struct mlx4_dev *dev,
 	return 0;
 
 err_radix:
-	spin_lock_irq(&cq_table->lock);
+	spin_lock(&cq_table->lock);
 	radix_tree_delete(&cq_table->tree, cq->cqn);
-	spin_unlock_irq(&cq_table->lock);
+	spin_unlock(&cq_table->lock);
 
 err_icm:
 	mlx4_cq_free_icm(dev, cq->cqn);
@@ -370,15 +372,15 @@ void mlx4_cq_free(struct mlx4_dev *dev,
 	if (err)
 		mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
 
+	spin_lock(&cq_table->lock);
+	radix_tree_delete(&cq_table->tree, cq->cqn);
+	spin_unlock(&cq_table->lock);
+
 	synchronize_irq(priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq);
 	if (priv->eq_table.eq[MLX4_CQ_TO_EQ_VECTOR(cq->vector)].irq !=
 	    priv->eq_table.eq[MLX4_EQ_ASYNC].irq)
 		synchronize_irq(priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
 
-	spin_lock_irq(&cq_table->lock);
-	radix_tree_delete(&cq_table->tree, cq->cqn);
-	spin_unlock_irq(&cq_table->lock);
-
 	if (atomic_dec_and_test(&cq->refcount))
 		complete(&cq->free);
 	wait_for_completion(&cq->free);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_clock.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@
 
 /* mlx4_en_read_clock - read raw cycle counter (to be used by time counter)
  */
-static cycle_t mlx4_en_read_clock(const struct cyclecounter *tc)
+static u64 mlx4_en_read_clock(const struct cyclecounter *tc)
 {
 	struct mlx4_en_dev *mdev =
 		container_of(tc, struct mlx4_en_dev, cycles);
@@ -245,13 +245,9 @@ static u32 freq_to_shift(u16 freq)
 {
 	u32 freq_khz = freq * 1000;
 	u64 max_val_cycles = freq_khz * 1000 * MLX4_EN_WRAP_AROUND_SEC;
-	u64 tmp_rounded =
-		roundup_pow_of_two(max_val_cycles) > max_val_cycles ?
-		roundup_pow_of_two(max_val_cycles) - 1 : UINT_MAX;
-	u64 max_val_cycles_rounded = is_power_of_2(max_val_cycles + 1) ?
-		max_val_cycles : tmp_rounded;
+	u64 max_val_cycles_rounded = 1ULL << fls64(max_val_cycles - 1);
 	/* calculate max possible multiplier in order to fit in 64bit */
-	u64 max_mul = div_u64(0xffffffffffffffffULL, max_val_cycles_rounded);
+	u64 max_mul = div64_u64(ULLONG_MAX, max_val_cycles_rounded);
 
 	/* This comes from the reverse of clocksource_khz2mult */
 	return ilog2(div_u64(max_mul * freq_khz, 1000000));
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_cq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_cq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_cq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_cq.c	2017-02-12 16:03:20.000000000 -0500
@@ -65,7 +65,7 @@ int mlx4_en_create_cq(struct mlx4_en_pri
 	cq->buf_size = cq->size * mdev->dev->caps.cqe_size;
 
 	cq->ring = ring;
-	cq->is_tx = mode;
+	cq->type = mode;
 	cq->vector = mdev->dev->caps.num_comp_vectors;
 
 	/* Allocate HW buffers on provided NUMA node.
@@ -104,7 +104,7 @@ int mlx4_en_activate_cq(struct mlx4_en_p
 	*cq->mcq.arm_db    = 0;
 	memset(cq->buf, 0, cq->buf_size);
 
-	if (cq->is_tx == RX) {
+	if (cq->type == RX) {
 		if (!mlx4_is_eq_vector_valid(mdev->dev, priv->port,
 					     cq->vector)) {
 			cq->vector = cpumask_first(priv->rx_ring[cq->ring]->affinity_mask);
@@ -127,25 +127,17 @@ int mlx4_en_activate_cq(struct mlx4_en_p
 		/* For TX we use the same irq per
 		ring we assigned for the RX    */
 		struct mlx4_en_cq *rx_cq;
-		int xdp_index;
 
-		/* The xdp tx irq must align with the rx ring that forwards to
-		 * it, so reindex these from 0. This should only happen when
-		 * tx_ring_num is not a multiple of rx_ring_num.
-		 */
-		xdp_index = (priv->xdp_ring_num - priv->tx_ring_num) + cq_idx;
-		if (xdp_index >= 0)
-			cq_idx = xdp_index;
 		cq_idx = cq_idx % priv->rx_ring_num;
 		rx_cq = priv->rx_cq[cq_idx];
 		cq->vector = rx_cq->vector;
 	}
 
-	if (!cq->is_tx)
+	if (cq->type == RX)
 		cq->size = priv->rx_ring[cq->ring]->actual_size;
 
-	if ((cq->is_tx && priv->hwtstamp_config.tx_type) ||
-	    (!cq->is_tx && priv->hwtstamp_config.rx_filter))
+	if ((cq->type != RX && priv->hwtstamp_config.tx_type) ||
+	    (cq->type == RX && priv->hwtstamp_config.rx_filter))
 		timestamp_en = 1;
 
 	err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt,
@@ -154,10 +146,10 @@ int mlx4_en_activate_cq(struct mlx4_en_p
 	if (err)
 		goto free_eq;
 
-	cq->mcq.comp  = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
+	cq->mcq.comp  = cq->type != RX ? mlx4_en_tx_irq : mlx4_en_rx_irq;
 	cq->mcq.event = mlx4_en_cq_event;
 
-	if (cq->is_tx)
+	if (cq->type != RX)
 		netif_tx_napi_add(cq->dev, &cq->napi, mlx4_en_poll_tx_cq,
 				  NAPI_POLL_WEIGHT);
 	else
@@ -181,7 +173,7 @@ void mlx4_en_destroy_cq(struct mlx4_en_p
 
 	mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
 	if (mlx4_is_eq_vector_valid(mdev->dev, priv->port, cq->vector) &&
-	    cq->is_tx == RX)
+	    cq->type == RX)
 		mlx4_release_eq(priv->mdev->dev, cq->vector);
 	cq->vector = 0;
 	cq->buf_size = 0;
@@ -193,10 +185,6 @@ void mlx4_en_destroy_cq(struct mlx4_en_p
 void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
 {
 	napi_disable(&cq->napi);
-	if (!cq->is_tx) {
-		napi_hash_del(&cq->napi);
-		synchronize_rcu();
-	}
 	netif_napi_del(&cq->napi);
 
 	mlx4_cq_free(priv->mdev->dev, &cq->mcq);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,16 +49,19 @@
 
 static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
 {
-	int i;
+	int i, t;
 	int err = 0;
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		priv->tx_cq[i]->moder_cnt = priv->tx_frames;
-		priv->tx_cq[i]->moder_time = priv->tx_usecs;
-		if (priv->port_up) {
-			err = mlx4_en_set_cq_moder(priv, priv->tx_cq[i]);
-			if (err)
-				return err;
+	for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		for (i = 0; i < priv->tx_ring_num[t]; i++) {
+			priv->tx_cq[t][i]->moder_cnt = priv->tx_frames;
+			priv->tx_cq[t][i]->moder_time = priv->tx_usecs;
+			if (priv->port_up) {
+				err = mlx4_en_set_cq_moder(priv,
+							   priv->tx_cq[t][i]);
+				if (err)
+					return err;
+			}
 		}
 	}
 
@@ -192,6 +195,10 @@ static const char main_strings[][ETH_GST
 	"tx_prio_7_packets", "tx_prio_7_bytes",
 	"tx_novlan_packets", "tx_novlan_bytes",
 
+	/* xdp statistics */
+	"rx_xdp_drop",
+	"rx_xdp_tx",
+	"rx_xdp_tx_full",
 };
 
 static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
@@ -336,8 +343,8 @@ static int mlx4_en_get_sset_count(struct
 	switch (sset) {
 	case ETH_SS_STATS:
 		return bitmap_iterator_count(&it) +
-			(priv->tx_ring_num * 2) +
-			(priv->rx_ring_num * 3);
+			(priv->tx_ring_num[TX] * 2) +
+			(priv->rx_ring_num * (3 + NUM_XDP_STATS));
 	case ETH_SS_TEST:
 		return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
 					& MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
@@ -360,6 +367,8 @@ static void mlx4_en_get_ethtool_stats(st
 
 	spin_lock_bh(&priv->stats_lock);
 
+	mlx4_en_fold_software_stats(dev);
+
 	for (i = 0; i < NUM_MAIN_STATS; i++, bitmap_iterator_inc(&it))
 		if (bitmap_iterator_test(&it))
 			data[index++] = ((unsigned long *)&dev->stats)[i];
@@ -397,14 +406,21 @@ static void mlx4_en_get_ethtool_stats(st
 		if (bitmap_iterator_test(&it))
 			data[index++] = ((unsigned long *)&priv->pkstats)[i];
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		data[index++] = priv->tx_ring[i]->packets;
-		data[index++] = priv->tx_ring[i]->bytes;
+	for (i = 0; i < NUM_XDP_STATS; i++, bitmap_iterator_inc(&it))
+		if (bitmap_iterator_test(&it))
+			data[index++] = ((unsigned long *)&priv->xdp_stats)[i];
+
+	for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+		data[index++] = priv->tx_ring[TX][i]->packets;
+		data[index++] = priv->tx_ring[TX][i]->bytes;
 	}
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		data[index++] = priv->rx_ring[i]->packets;
 		data[index++] = priv->rx_ring[i]->bytes;
 		data[index++] = priv->rx_ring[i]->dropped;
+		data[index++] = priv->rx_ring[i]->xdp_drop;
+		data[index++] = priv->rx_ring[i]->xdp_tx;
+		data[index++] = priv->rx_ring[i]->xdp_tx_full;
 	}
 	spin_unlock_bh(&priv->stats_lock);
 
@@ -467,7 +483,13 @@ static void mlx4_en_get_strings(struct n
 				strcpy(data + (index++) * ETH_GSTRING_LEN,
 				       main_strings[strings]);
 
-		for (i = 0; i < priv->tx_ring_num; i++) {
+		for (i = 0; i < NUM_XDP_STATS; i++, strings++,
+		     bitmap_iterator_inc(&it))
+			if (bitmap_iterator_test(&it))
+				strcpy(data + (index++) * ETH_GSTRING_LEN,
+				       main_strings[strings]);
+
+		for (i = 0; i < priv->tx_ring_num[TX]; i++) {
 			sprintf(data + (index++) * ETH_GSTRING_LEN,
 				"tx%d_packets", i);
 			sprintf(data + (index++) * ETH_GSTRING_LEN,
@@ -480,6 +502,12 @@ static void mlx4_en_get_strings(struct n
 				"rx%d_bytes", i);
 			sprintf(data + (index++) * ETH_GSTRING_LEN,
 				"rx%d_dropped", i);
+			sprintf(data + (index++) * ETH_GSTRING_LEN,
+				"rx%d_xdp_drop", i);
+			sprintf(data + (index++) * ETH_GSTRING_LEN,
+				"rx%d_xdp_tx", i);
+			sprintf(data + (index++) * ETH_GSTRING_LEN,
+				"rx%d_xdp_tx_full", i);
 		}
 		break;
 	case ETH_SS_PRIV_FLAGS:
@@ -1060,7 +1088,7 @@ static int mlx4_en_set_ringparam(struct
 
 	if (rx_size == (priv->port_up ? priv->rx_ring[0]->actual_size :
 					priv->rx_ring[0]->size) &&
-	    tx_size == priv->tx_ring[0]->size)
+	    tx_size == priv->tx_ring[TX][0]->size)
 		return 0;
 
 	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
@@ -1071,7 +1099,7 @@ static int mlx4_en_set_ringparam(struct
 	memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
 	new_prof.tx_ring_size = tx_size;
 	new_prof.rx_ring_size = rx_size;
-	err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+	err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
 	if (err)
 		goto out;
 
@@ -1105,7 +1133,7 @@ static void mlx4_en_get_ringparam(struct
 	param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
 	param->rx_pending = priv->port_up ?
 		priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size;
-	param->tx_pending = priv->tx_ring[0]->size;
+	param->tx_pending = priv->tx_ring[TX][0]->size;
 }
 
 static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
@@ -1704,13 +1732,11 @@ static void mlx4_en_get_channels(struct
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 
-	memset(channel, 0, sizeof(*channel));
-
 	channel->max_rx = MAX_RX_RINGS;
 	channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;
 
 	channel->rx_count = priv->rx_ring_num;
-	channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP;
+	channel->tx_count = priv->tx_ring_num[TX] / MLX4_EN_NUM_UP;
 }
 
 static int mlx4_en_set_channels(struct net_device *dev,
@@ -1721,31 +1747,34 @@ static int mlx4_en_set_channels(struct n
 	struct mlx4_en_port_profile new_prof;
 	struct mlx4_en_priv *tmp;
 	int port_up = 0;
+	int xdp_count;
 	int err = 0;
 
-	if (channel->other_count || channel->combined_count ||
-	    channel->tx_count > MLX4_EN_MAX_TX_RING_P_UP ||
-	    channel->rx_count > MAX_RX_RINGS ||
-	    !channel->tx_count || !channel->rx_count)
-		return -EINVAL;
-
-	if (channel->tx_count * MLX4_EN_NUM_UP <= priv->xdp_ring_num) {
-		en_err(priv, "Minimum %d tx channels required with XDP on\n",
-		       priv->xdp_ring_num / MLX4_EN_NUM_UP + 1);
+	if (!channel->tx_count || !channel->rx_count)
 		return -EINVAL;
-	}
 
 	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
 	if (!tmp)
 		return -ENOMEM;
 
 	mutex_lock(&mdev->state_lock);
+	xdp_count = priv->tx_ring_num[TX_XDP] ? channel->rx_count : 0;
+	if (channel->tx_count * MLX4_EN_NUM_UP + xdp_count > MAX_TX_RINGS) {
+		err = -EINVAL;
+		en_err(priv,
+		       "Total number of TX and XDP rings (%d) exceeds the maximum supported (%d)\n",
+		       channel->tx_count * MLX4_EN_NUM_UP + xdp_count,
+		       MAX_TX_RINGS);
+		goto out;
+	}
+
 	memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
 	new_prof.num_tx_rings_p_up = channel->tx_count;
-	new_prof.tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP;
+	new_prof.tx_ring_num[TX] = channel->tx_count * MLX4_EN_NUM_UP;
+	new_prof.tx_ring_num[TX_XDP] = xdp_count;
 	new_prof.rx_ring_num = channel->rx_count;
 
-	err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+	err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
 	if (err)
 		goto out;
 
@@ -1756,14 +1785,13 @@ static int mlx4_en_set_channels(struct n
 
 	mlx4_en_safe_replace_resources(priv, tmp);
 
-	netif_set_real_num_tx_queues(dev, priv->tx_ring_num -
-							priv->xdp_ring_num);
+	netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
 	netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
 
 	if (dev->num_tc)
 		mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);
 
-	en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num);
+	en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num[TX]);
 	en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);
 
 	if (port_up) {
@@ -1774,8 +1802,8 @@ static int mlx4_en_set_channels(struct n
 
 	err = mlx4_en_moderation_update(priv);
 out:
-	kfree(tmp);
 	mutex_unlock(&mdev->state_lock);
+	kfree(tmp);
 	return err;
 }
 
@@ -1823,11 +1851,15 @@ static int mlx4_en_set_priv_flags(struct
 	int ret = 0;
 
 	if (bf_enabled_new != bf_enabled_old) {
+		int t;
+
 		if (bf_enabled_new) {
 			bool bf_supported = true;
 
-			for (i = 0; i < priv->tx_ring_num; i++)
-				bf_supported &= priv->tx_ring[i]->bf_alloced;
+			for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
+				for (i = 0; i < priv->tx_ring_num[t]; i++)
+					bf_supported &=
+						priv->tx_ring[t][i]->bf_alloced;
 
 			if (!bf_supported) {
 				en_err(priv, "BlueFlame is not supported\n");
@@ -1839,8 +1871,10 @@ static int mlx4_en_set_priv_flags(struct
 			priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
 		}
 
-		for (i = 0; i < priv->tx_ring_num; i++)
-			priv->tx_ring[i]->bf_enabled = bf_enabled_new;
+		for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
+			for (i = 0; i < priv->tx_ring_num[t]; i++)
+				priv->tx_ring[t][i]->bf_enabled =
+					bf_enabled_new;
 
 		en_info(priv, "BlueFlame %s\n",
 			bf_enabled_new ?  "Enabled" : "Disabled");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -169,7 +169,7 @@ static int mlx4_en_get_profile(struct ml
 		params->prof[i].tx_ppp = pfctx;
 		params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
 		params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
-		params->prof[i].tx_ring_num = params->num_tx_rings_p_up *
+		params->prof[i].tx_ring_num[TX] = params->num_tx_rings_p_up *
 			MLX4_EN_NUM_UP;
 		params->prof[i].rss_rings = 0;
 		params->prof[i].inline_thold = inline_thold;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_netdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -51,6 +51,9 @@
 #include "mlx4_en.h"
 #include "en_port.h"
 
+#define MLX4_EN_MAX_XDP_MTU ((int)(PAGE_SIZE - ETH_HLEN - (2 * VLAN_HLEN) - \
+				   XDP_PACKET_HEADROOM))
+
 int mlx4_en_setup_tc(struct net_device *dev, u8 up)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -1217,8 +1220,8 @@ static void mlx4_en_netpoll(struct net_d
 	struct mlx4_en_cq *cq;
 	int i;
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		cq = priv->tx_cq[i];
+	for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+		cq = priv->tx_cq[TX][i];
 		napi_schedule(&cq->napi);
 	}
 }
@@ -1302,12 +1305,14 @@ static void mlx4_en_tx_timeout(struct ne
 	if (netif_msg_timer(priv))
 		en_warn(priv, "Tx timeout called on port:%d\n", priv->port);
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
+	for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+		struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX][i];
+
 		if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, i)))
 			continue;
 		en_warn(priv, "TX timeout on queue: %d, QP: 0x%x, CQ: 0x%x, Cons: 0x%x, Prod: 0x%x\n",
-			i, priv->tx_ring[i]->qpn, priv->tx_ring[i]->cqn,
-			priv->tx_ring[i]->cons, priv->tx_ring[i]->prod);
+			i, tx_ring->qpn, tx_ring->sp_cqn,
+			tx_ring->cons, tx_ring->prod);
 	}
 
 	priv->port_stats.tx_timeout++;
@@ -1322,6 +1327,7 @@ mlx4_en_get_stats64(struct net_device *d
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 
 	spin_lock_bh(&priv->stats_lock);
+	mlx4_en_fold_software_stats(dev);
 	netdev_stats_to_stats64(stats, &dev->stats);
 	spin_unlock_bh(&priv->stats_lock);
 
@@ -1331,7 +1337,7 @@ mlx4_en_get_stats64(struct net_device *d
 static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
 {
 	struct mlx4_en_cq *cq;
-	int i;
+	int i, t;
 
 	/* If we haven't received a specific coalescing setting
 	 * (module param), we set the moderation parameters as follows:
@@ -1356,10 +1362,12 @@ static void mlx4_en_set_default_moderati
 		priv->last_moder_bytes[i] = 0;
 	}
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		cq = priv->tx_cq[i];
-		cq->moder_cnt = priv->tx_frames;
-		cq->moder_time = priv->tx_usecs;
+	for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		for (i = 0; i < priv->tx_ring_num[t]; i++) {
+			cq = priv->tx_cq[t][i];
+			cq->moder_cnt = priv->tx_frames;
+			cq->moder_time = priv->tx_usecs;
+		}
 	}
 
 	/* Reset auto-moderation params */
@@ -1390,10 +1398,8 @@ static void mlx4_en_auto_moderation(stru
 		return;
 
 	for (ring = 0; ring < priv->rx_ring_num; ring++) {
-		spin_lock_bh(&priv->stats_lock);
-		rx_packets = priv->rx_ring[ring]->packets;
-		rx_bytes = priv->rx_ring[ring]->bytes;
-		spin_unlock_bh(&priv->stats_lock);
+		rx_packets = READ_ONCE(priv->rx_ring[ring]->packets);
+		rx_bytes = READ_ONCE(priv->rx_ring[ring]->bytes);
 
 		rx_pkt_diff = ((unsigned long) (rx_packets -
 				priv->last_moder_packets[ring]));
@@ -1529,19 +1535,13 @@ static void mlx4_en_free_affinity_hint(s
 static void mlx4_en_init_recycle_ring(struct mlx4_en_priv *priv,
 				      int tx_ring_idx)
 {
-	struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[tx_ring_idx];
-	int rr_index;
+	struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX_XDP][tx_ring_idx];
+	int rr_index = tx_ring_idx;
 
-	rr_index = (priv->xdp_ring_num - priv->tx_ring_num) + tx_ring_idx;
-	if (rr_index >= 0) {
-		tx_ring->free_tx_desc = mlx4_en_recycle_tx_desc;
-		tx_ring->recycle_ring = priv->rx_ring[rr_index];
-		en_dbg(DRV, priv,
-		       "Set tx_ring[%d]->recycle_ring = rx_ring[%d]\n",
-		       tx_ring_idx, rr_index);
-	} else {
-		tx_ring->recycle_ring = NULL;
-	}
+	tx_ring->free_tx_desc = mlx4_en_recycle_tx_desc;
+	tx_ring->recycle_ring = priv->rx_ring[rr_index];
+	en_dbg(DRV, priv, "Set tx_ring[%d][%d]->recycle_ring = rx_ring[%d]\n",
+	       TX_XDP, tx_ring_idx, rr_index);
 }
 
 int mlx4_en_start_port(struct net_device *dev)
@@ -1551,9 +1551,8 @@ int mlx4_en_start_port(struct net_device
 	struct mlx4_en_cq *cq;
 	struct mlx4_en_tx_ring *tx_ring;
 	int rx_index = 0;
-	int tx_index = 0;
 	int err = 0;
-	int i;
+	int i, t;
 	int j;
 	u8 mc_list[16] = {0};
 
@@ -1638,43 +1637,52 @@ int mlx4_en_start_port(struct net_device
 		goto rss_err;
 
 	/* Configure tx cq's and rings */
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		/* Configure cq */
-		cq = priv->tx_cq[i];
-		err = mlx4_en_activate_cq(priv, cq, i);
-		if (err) {
-			en_err(priv, "Failed allocating Tx CQ\n");
-			goto tx_err;
-		}
-		err = mlx4_en_set_cq_moder(priv, cq);
-		if (err) {
-			en_err(priv, "Failed setting cq moderation parameters\n");
-			mlx4_en_deactivate_cq(priv, cq);
-			goto tx_err;
-		}
-		en_dbg(DRV, priv, "Resetting index of collapsed CQ:%d to -1\n", i);
-		cq->buf->wqe_index = cpu_to_be16(0xffff);
+	for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		u8 num_tx_rings_p_up = t == TX ?
+			priv->num_tx_rings_p_up : priv->tx_ring_num[t];
 
-		/* Configure ring */
-		tx_ring = priv->tx_ring[i];
-		err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
-			i / priv->num_tx_rings_p_up);
-		if (err) {
-			en_err(priv, "Failed allocating Tx ring\n");
-			mlx4_en_deactivate_cq(priv, cq);
-			goto tx_err;
-		}
-		tx_ring->tx_queue = netdev_get_tx_queue(dev, i);
+		for (i = 0; i < priv->tx_ring_num[t]; i++) {
+			/* Configure cq */
+			cq = priv->tx_cq[t][i];
+			err = mlx4_en_activate_cq(priv, cq, i);
+			if (err) {
+				en_err(priv, "Failed allocating Tx CQ\n");
+				goto tx_err;
+			}
+			err = mlx4_en_set_cq_moder(priv, cq);
+			if (err) {
+				en_err(priv, "Failed setting cq moderation parameters\n");
+				mlx4_en_deactivate_cq(priv, cq);
+				goto tx_err;
+			}
+			en_dbg(DRV, priv,
+			       "Resetting index of collapsed CQ:%d to -1\n", i);
+			cq->buf->wqe_index = cpu_to_be16(0xffff);
 
-		mlx4_en_init_recycle_ring(priv, i);
+			/* Configure ring */
+			tx_ring = priv->tx_ring[t][i];
+			err = mlx4_en_activate_tx_ring(priv, tx_ring,
+						       cq->mcq.cqn,
+						       i / num_tx_rings_p_up);
+			if (err) {
+				en_err(priv, "Failed allocating Tx ring\n");
+				mlx4_en_deactivate_cq(priv, cq);
+				goto tx_err;
+			}
+			if (t != TX_XDP) {
+				tx_ring->tx_queue = netdev_get_tx_queue(dev, i);
+				tx_ring->recycle_ring = NULL;
+			} else {
+				mlx4_en_init_recycle_ring(priv, i);
+			}
 
-		/* Arm CQ for TX completions */
-		mlx4_en_arm_cq(priv, cq);
+			/* Arm CQ for TX completions */
+			mlx4_en_arm_cq(priv, cq);
 
-		/* Set initial ownership of all Tx TXBBs to SW (1) */
-		for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
-			*((u32 *) (tx_ring->buf + j)) = 0xffffffff;
-		++tx_index;
+			/* Set initial ownership of all Tx TXBBs to SW (1) */
+			for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
+				*((u32 *)(tx_ring->buf + j)) = 0xffffffff;
+		}
 	}
 
 	/* Configure port */
@@ -1740,8 +1748,11 @@ int mlx4_en_start_port(struct net_device
 	/* Process all completions if exist to prevent
 	 * the queues freezing if they are full
 	 */
-	for (i = 0; i < priv->rx_ring_num; i++)
+	for (i = 0; i < priv->rx_ring_num; i++) {
+		local_bh_disable();
 		napi_schedule(&priv->rx_cq[i]->napi);
+		local_bh_enable();
+	}
 
 	netif_tx_start_all_queues(dev);
 	netif_device_attach(dev);
@@ -1749,9 +1760,18 @@ int mlx4_en_start_port(struct net_device
 	return 0;
 
 tx_err:
-	while (tx_index--) {
-		mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[tx_index]);
-		mlx4_en_deactivate_cq(priv, priv->tx_cq[tx_index]);
+	if (t == MLX4_EN_NUM_TX_TYPES) {
+		t--;
+		i = priv->tx_ring_num[t];
+	}
+	while (t >= 0) {
+		while (i--) {
+			mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[t][i]);
+			mlx4_en_deactivate_cq(priv, priv->tx_cq[t][i]);
+		}
+		if (!t--)
+			break;
+		i = priv->tx_ring_num[t];
 	}
 	mlx4_en_destroy_drop_qp(priv);
 rss_err:
@@ -1776,7 +1796,7 @@ void mlx4_en_stop_port(struct net_device
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct mlx4_en_mc_list *mclist, *tmp;
 	struct ethtool_flow_id *flow, *tmp_flow;
-	int i;
+	int i, t;
 	u8 mc_list[16] = {0};
 
 	if (!priv->port_up) {
@@ -1796,8 +1816,12 @@ void mlx4_en_stop_port(struct net_device
 
 	netif_tx_disable(dev);
 
+	spin_lock_bh(&priv->stats_lock);
+	mlx4_en_fold_software_stats(dev);
 	/* Set port as not active */
 	priv->port_up = false;
+	spin_unlock_bh(&priv->stats_lock);
+
 	priv->counter_index = MLX4_SINK_COUNTER_INDEX(mdev->dev);
 
 	/* Promsicuous mode */
@@ -1862,14 +1886,17 @@ void mlx4_en_stop_port(struct net_device
 	mlx4_en_destroy_drop_qp(priv);
 
 	/* Free TX Rings */
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[i]);
-		mlx4_en_deactivate_cq(priv, priv->tx_cq[i]);
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		for (i = 0; i < priv->tx_ring_num[t]; i++) {
+			mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[t][i]);
+			mlx4_en_deactivate_cq(priv, priv->tx_cq[t][i]);
+		}
 	}
 	msleep(10);
 
-	for (i = 0; i < priv->tx_ring_num; i++)
-		mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
+		for (i = 0; i < priv->tx_ring_num[t]; i++)
+			mlx4_en_free_tx_buf(dev, priv->tx_ring[t][i]);
 
 	if (mdev->dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
 		mlx4_en_delete_rss_steer_rules(priv);
@@ -1918,6 +1945,7 @@ static void mlx4_en_clear_stats(struct n
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
+	struct mlx4_en_tx_ring **tx_ring;
 	int i;
 
 	if (!mlx4_is_slave(mdev->dev))
@@ -1935,15 +1963,16 @@ static void mlx4_en_clear_stats(struct n
 	       sizeof(priv->tx_priority_flowstats));
 	memset(&priv->pf_stats, 0, sizeof(priv->pf_stats));
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		priv->tx_ring[i]->bytes = 0;
-		priv->tx_ring[i]->packets = 0;
-		priv->tx_ring[i]->tx_csum = 0;
-		priv->tx_ring[i]->tx_dropped = 0;
-		priv->tx_ring[i]->queue_stopped = 0;
-		priv->tx_ring[i]->wake_queue = 0;
-		priv->tx_ring[i]->tso_packets = 0;
-		priv->tx_ring[i]->xmit_more = 0;
+	tx_ring = priv->tx_ring[TX];
+	for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+		tx_ring[i]->bytes = 0;
+		tx_ring[i]->packets = 0;
+		tx_ring[i]->tx_csum = 0;
+		tx_ring[i]->tx_dropped = 0;
+		tx_ring[i]->queue_stopped = 0;
+		tx_ring[i]->wake_queue = 0;
+		tx_ring[i]->tso_packets = 0;
+		tx_ring[i]->xmit_more = 0;
 	}
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		priv->rx_ring[i]->bytes = 0;
@@ -1999,17 +2028,22 @@ static int mlx4_en_close(struct net_devi
 
 static void mlx4_en_free_resources(struct mlx4_en_priv *priv)
 {
-	int i;
+	int i, t;
 
 #ifdef CONFIG_RFS_ACCEL
 	priv->dev->rx_cpu_rmap = NULL;
 #endif
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		if (priv->tx_ring && priv->tx_ring[i])
-			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
-		if (priv->tx_cq && priv->tx_cq[i])
-			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		for (i = 0; i < priv->tx_ring_num[t]; i++) {
+			if (priv->tx_ring[t] && priv->tx_ring[t][i])
+				mlx4_en_destroy_tx_ring(priv,
+							&priv->tx_ring[t][i]);
+			if (priv->tx_cq[t] && priv->tx_cq[t][i])
+				mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]);
+		}
+		kfree(priv->tx_ring[t]);
+		kfree(priv->tx_cq[t]);
 	}
 
 	for (i = 0; i < priv->rx_ring_num; i++) {
@@ -2025,20 +2059,22 @@ static void mlx4_en_free_resources(struc
 static int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
 {
 	struct mlx4_en_port_profile *prof = priv->prof;
-	int i;
+	int i, t;
 	int node;
 
 	/* Create tx Rings */
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		node = cpu_to_node(i % num_online_cpus());
-		if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
-				      prof->tx_ring_size, i, TX, node))
-			goto err;
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		for (i = 0; i < priv->tx_ring_num[t]; i++) {
+			node = cpu_to_node(i % num_online_cpus());
+			if (mlx4_en_create_cq(priv, &priv->tx_cq[t][i],
+					      prof->tx_ring_size, i, t, node))
+				goto err;
 
-		if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
-					   prof->tx_ring_size, TXBB_SIZE,
-					   node, i))
-			goto err;
+			if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[t][i],
+						   prof->tx_ring_size,
+						   TXBB_SIZE, node, i))
+				goto err;
+		}
 	}
 
 	/* Create rx Rings */
@@ -2070,11 +2106,14 @@ err:
 		if (priv->rx_cq[i])
 			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
 	}
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		if (priv->tx_ring[i])
-			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
-		if (priv->tx_cq[i])
-			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		for (i = 0; i < priv->tx_ring_num[t]; i++) {
+			if (priv->tx_ring[t][i])
+				mlx4_en_destroy_tx_ring(priv,
+							&priv->tx_ring[t][i]);
+			if (priv->tx_cq[t][i])
+				mlx4_en_destroy_cq(priv, &priv->tx_cq[t][i]);
+		}
 	}
 	return -ENOMEM;
 }
@@ -2084,10 +2123,11 @@ static int mlx4_en_copy_priv(struct mlx4
 			     struct mlx4_en_priv *src,
 			     struct mlx4_en_port_profile *prof)
 {
+	int t;
+
 	memcpy(&dst->hwtstamp_config, &prof->hwtstamp_config,
 	       sizeof(dst->hwtstamp_config));
 	dst->num_tx_rings_p_up = src->mdev->profile.num_tx_rings_p_up;
-	dst->tx_ring_num = prof->tx_ring_num;
 	dst->rx_ring_num = prof->rx_ring_num;
 	dst->flags = prof->flags;
 	dst->mdev = src->mdev;
@@ -2097,50 +2137,90 @@ static int mlx4_en_copy_priv(struct mlx4
 	dst->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
 					 DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
 
-	dst->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring *) * MAX_TX_RINGS,
-				GFP_KERNEL);
-	if (!dst->tx_ring)
-		return -ENOMEM;
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		dst->tx_ring_num[t] = prof->tx_ring_num[t];
+		if (!dst->tx_ring_num[t])
+			continue;
 
-	dst->tx_cq = kzalloc(sizeof(struct mlx4_en_cq *) * MAX_TX_RINGS,
-			      GFP_KERNEL);
-	if (!dst->tx_cq) {
-		kfree(dst->tx_ring);
-		return -ENOMEM;
+		dst->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) *
+					  MAX_TX_RINGS, GFP_KERNEL);
+		if (!dst->tx_ring[t])
+			goto err_free_tx;
+
+		dst->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
+					MAX_TX_RINGS, GFP_KERNEL);
+		if (!dst->tx_cq[t]) {
+			kfree(dst->tx_ring[t]);
+			goto err_free_tx;
+		}
 	}
+
 	return 0;
+
+err_free_tx:
+	while (t--) {
+		kfree(dst->tx_ring[t]);
+		kfree(dst->tx_cq[t]);
+	}
+	return -ENOMEM;
 }
 
 static void mlx4_en_update_priv(struct mlx4_en_priv *dst,
 				struct mlx4_en_priv *src)
 {
+	int t;
 	memcpy(dst->rx_ring, src->rx_ring,
 	       sizeof(struct mlx4_en_rx_ring *) * src->rx_ring_num);
 	memcpy(dst->rx_cq, src->rx_cq,
 	       sizeof(struct mlx4_en_cq *) * src->rx_ring_num);
 	memcpy(&dst->hwtstamp_config, &src->hwtstamp_config,
 	       sizeof(dst->hwtstamp_config));
-	dst->tx_ring_num = src->tx_ring_num;
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		dst->tx_ring_num[t] = src->tx_ring_num[t];
+		dst->tx_ring[t] = src->tx_ring[t];
+		dst->tx_cq[t] = src->tx_cq[t];
+	}
 	dst->rx_ring_num = src->rx_ring_num;
-	dst->tx_ring = src->tx_ring;
-	dst->tx_cq = src->tx_cq;
 	memcpy(dst->prof, src->prof, sizeof(struct mlx4_en_port_profile));
 }
 
 int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
 				struct mlx4_en_priv *tmp,
-				struct mlx4_en_port_profile *prof)
+				struct mlx4_en_port_profile *prof,
+				bool carry_xdp_prog)
 {
+	struct bpf_prog *xdp_prog;
+	int i, t;
+
 	mlx4_en_copy_priv(tmp, priv, prof);
 
 	if (mlx4_en_alloc_resources(tmp)) {
 		en_warn(priv,
 			"%s: Resource allocation failed, using previous configuration\n",
 			__func__);
-		kfree(tmp->tx_ring);
-		kfree(tmp->tx_cq);
+		for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+			kfree(tmp->tx_ring[t]);
+			kfree(tmp->tx_cq[t]);
+		}
 		return -ENOMEM;
 	}
+
+	/* All rx_rings has the same xdp_prog.  Pick the first one. */
+	xdp_prog = rcu_dereference_protected(
+		priv->rx_ring[0]->xdp_prog,
+		lockdep_is_held(&priv->mdev->state_lock));
+
+	if (xdp_prog && carry_xdp_prog) {
+		xdp_prog = bpf_prog_add(xdp_prog, tmp->rx_ring_num);
+		if (IS_ERR(xdp_prog)) {
+			mlx4_en_free_resources(tmp);
+			return PTR_ERR(xdp_prog);
+		}
+		for (i = 0; i < tmp->rx_ring_num; i++)
+			rcu_assign_pointer(tmp->rx_ring[i]->xdp_prog,
+					   xdp_prog);
+	}
+
 	return 0;
 }
 
@@ -2188,12 +2268,22 @@ void mlx4_en_destroy_netdev(struct net_d
 	mlx4_en_free_resources(priv);
 	mutex_unlock(&mdev->state_lock);
 
-	kfree(priv->tx_ring);
-	kfree(priv->tx_cq);
-
 	free_netdev(dev);
 }
 
+static bool mlx4_en_check_xdp_mtu(struct net_device *dev, int mtu)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+
+	if (mtu > MLX4_EN_MAX_XDP_MTU) {
+		en_err(priv, "mtu:%d > max:%d when XDP prog is attached\n",
+		       mtu, MLX4_EN_MAX_XDP_MTU);
+		return false;
+	}
+
+	return true;
+}
+
 static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -2203,15 +2293,10 @@ static int mlx4_en_change_mtu(struct net
 	en_dbg(DRV, priv, "Change MTU called - current:%d new:%d\n",
 		 dev->mtu, new_mtu);
 
-	if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
-		en_err(priv, "Bad MTU size:%d.\n", new_mtu);
-		return -EPERM;
-	}
-	if (priv->xdp_ring_num && MLX4_EN_EFF_MTU(new_mtu) > FRAG_SZ0) {
-		en_err(priv, "MTU size:%d requires frags but XDP running\n",
-		       new_mtu);
+	if (priv->tx_ring_num[TX_XDP] &&
+	    !mlx4_en_check_xdp_mtu(dev, new_mtu))
 		return -EOPNOTSUPP;
-	}
+
 	dev->mtu = new_mtu;
 
 	if (netif_running(dev)) {
@@ -2598,7 +2683,7 @@ static netdev_features_t mlx4_en_feature
 static int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
-	struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[queue_index];
+	struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[TX][queue_index];
 	struct mlx4_update_qp_params params;
 	int err;
 
@@ -2626,18 +2711,21 @@ static int mlx4_xdp_set(struct net_devic
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
+	struct mlx4_en_port_profile new_prof;
 	struct bpf_prog *old_prog;
+	struct mlx4_en_priv *tmp;
+	int tx_changed = 0;
 	int xdp_ring_num;
 	int port_up = 0;
 	int err;
 	int i;
 
-	xdp_ring_num = prog ? ALIGN(priv->rx_ring_num, MLX4_EN_NUM_UP) : 0;
+	xdp_ring_num = prog ? priv->rx_ring_num : 0;
 
 	/* No need to reconfigure buffers when simply swapping the
 	 * program for a new one.
 	 */
-	if (priv->xdp_ring_num == xdp_ring_num) {
+	if (priv->tx_ring_num[TX_XDP] == xdp_ring_num) {
 		if (prog) {
 			prog = bpf_prog_add(prog, priv->rx_ring_num - 1);
 			if (IS_ERR(prog))
@@ -2656,33 +2744,47 @@ static int mlx4_xdp_set(struct net_devic
 		return 0;
 	}
 
-	if (priv->num_frags > 1) {
-		en_err(priv, "Cannot set XDP if MTU requires multiple frags\n");
+	if (!mlx4_en_check_xdp_mtu(dev, dev->mtu))
 		return -EOPNOTSUPP;
-	}
 
-	if (priv->tx_ring_num < xdp_ring_num + MLX4_EN_NUM_UP) {
-		en_err(priv,
-		       "Minimum %d tx channels required to run XDP\n",
-		       (xdp_ring_num + MLX4_EN_NUM_UP) / MLX4_EN_NUM_UP);
-		return -EINVAL;
-	}
+	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+	if (!tmp)
+		return -ENOMEM;
 
 	if (prog) {
 		prog = bpf_prog_add(prog, priv->rx_ring_num - 1);
-		if (IS_ERR(prog))
-			return PTR_ERR(prog);
+		if (IS_ERR(prog)) {
+			err = PTR_ERR(prog);
+			goto out;
+		}
 	}
 
 	mutex_lock(&mdev->state_lock);
+	memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
+	new_prof.tx_ring_num[TX_XDP] = xdp_ring_num;
+
+	if (priv->tx_ring_num[TX] + xdp_ring_num > MAX_TX_RINGS) {
+		tx_changed = 1;
+		new_prof.tx_ring_num[TX] =
+			MAX_TX_RINGS - ALIGN(xdp_ring_num, MLX4_EN_NUM_UP);
+		en_warn(priv, "Reducing the number of TX rings, to not exceed the max total rings number.\n");
+	}
+
+	err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, false);
+	if (err) {
+		if (prog)
+			bpf_prog_sub(prog, priv->rx_ring_num - 1);
+		goto unlock_out;
+	}
+
 	if (priv->port_up) {
 		port_up = 1;
 		mlx4_en_stop_port(dev, 1);
 	}
 
-	priv->xdp_ring_num = xdp_ring_num;
-	netif_set_real_num_tx_queues(dev, priv->tx_ring_num -
-							priv->xdp_ring_num);
+	mlx4_en_safe_replace_resources(priv, tmp);
+	if (tx_changed)
+		netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
 
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		old_prog = rcu_dereference_protected(
@@ -2702,15 +2804,18 @@ static int mlx4_xdp_set(struct net_devic
 		}
 	}
 
+unlock_out:
 	mutex_unlock(&mdev->state_lock);
-	return 0;
+out:
+	kfree(tmp);
+	return err;
 }
 
 static bool mlx4_xdp_attached(struct net_device *dev)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 
-	return !!priv->xdp_ring_num;
+	return !!priv->tx_ring_num[TX_XDP];
 }
 
 static int mlx4_xdp(struct net_device *dev, struct netdev_xdp *xdp)
@@ -3047,6 +3152,10 @@ void mlx4_en_set_stats_bitmap(struct mlx
 
 	if (!mlx4_is_slave(dev))
 		bitmap_set(stats_bitmap->bitmap, last_i, NUM_PKT_STATS);
+	last_i += NUM_PKT_STATS;
+
+	bitmap_set(stats_bitmap->bitmap, last_i, NUM_XDP_STATS);
+	last_i += NUM_XDP_STATS;
 }
 
 int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
@@ -3054,7 +3163,7 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 {
 	struct net_device *dev;
 	struct mlx4_en_priv *priv;
-	int i;
+	int i, t;
 	int err;
 
 	dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
@@ -3062,7 +3171,7 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 	if (dev == NULL)
 		return -ENOMEM;
 
-	netif_set_real_num_tx_queues(dev, prof->tx_ring_num);
+	netif_set_real_num_tx_queues(dev, prof->tx_ring_num[TX]);
 	netif_set_real_num_rx_queues(dev, prof->rx_ring_num);
 
 	SET_NETDEV_DEV(dev, &mdev->dev->persist->pdev->dev);
@@ -3099,21 +3208,27 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 	priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
 			MLX4_WQE_CTRL_SOLICITED);
 	priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
-	priv->tx_ring_num = prof->tx_ring_num;
 	priv->tx_work_limit = MLX4_EN_DEFAULT_TX_WORK;
 	netdev_rss_key_fill(priv->rss_key, sizeof(priv->rss_key));
 
-	priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring *) * MAX_TX_RINGS,
-				GFP_KERNEL);
-	if (!priv->tx_ring) {
-		err = -ENOMEM;
-		goto out;
-	}
-	priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq *) * MAX_TX_RINGS,
-			      GFP_KERNEL);
-	if (!priv->tx_cq) {
-		err = -ENOMEM;
-		goto out;
+	for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++) {
+		priv->tx_ring_num[t] = prof->tx_ring_num[t];
+		if (!priv->tx_ring_num[t])
+			continue;
+
+		priv->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) *
+					   MAX_TX_RINGS, GFP_KERNEL);
+		if (!priv->tx_ring[t]) {
+			err = -ENOMEM;
+			goto err_free_tx;
+		}
+		priv->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
+					 MAX_TX_RINGS, GFP_KERNEL);
+		if (!priv->tx_cq[t]) {
+			kfree(priv->tx_ring[t]);
+			err = -ENOMEM;
+			goto out;
+		}
 	}
 	priv->rx_ring_num = prof->rx_ring_num;
 	priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
@@ -3196,7 +3311,7 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 	else
 		dev->netdev_ops = &mlx4_netdev_ops;
 	dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
-	netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
+	netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
 	netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
 
 	dev->ethtool_ops = &mlx4_en_ethtool_ops;
@@ -3286,13 +3401,17 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 		dev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
 	}
 
+	/* MTU range: 46 - hw-specific max */
+	dev->min_mtu = MLX4_EN_MIN_MTU;
+	dev->max_mtu = priv->max_mtu;
+
 	mdev->pndev[port] = dev;
 	mdev->upper[port] = NULL;
 
 	netif_carrier_off(dev);
 	mlx4_en_set_default_moderation(priv);
 
-	en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
+	en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num[TX]);
 	en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
 
 	mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
@@ -3352,6 +3471,11 @@ int mlx4_en_init_netdev(struct mlx4_en_d
 
 	return 0;
 
+err_free_tx:
+	while (t--) {
+		kfree(priv->tx_ring[t]);
+		kfree(priv->tx_cq[t]);
+	}
 out:
 	mlx4_en_destroy_netdev(dev);
 	return err;
@@ -3390,7 +3514,7 @@ int mlx4_en_reset_config(struct net_devi
 	memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
 	memcpy(&new_prof.hwtstamp_config, &ts_config, sizeof(ts_config));
 
-	err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
+	err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof, true);
 	if (err)
 		goto out;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_port.c	2017-02-12 16:03:20.000000000 -0500
@@ -147,6 +147,39 @@ static unsigned long en_stats_adder(__be
 	return ret;
 }
 
+void mlx4_en_fold_software_stats(struct net_device *dev)
+{
+	struct mlx4_en_priv *priv = netdev_priv(dev);
+	struct mlx4_en_dev *mdev = priv->mdev;
+	unsigned long packets, bytes;
+	int i;
+
+	if (!priv->port_up || mlx4_is_master(mdev->dev))
+		return;
+
+	packets = 0;
+	bytes = 0;
+	for (i = 0; i < priv->rx_ring_num; i++) {
+		const struct mlx4_en_rx_ring *ring = priv->rx_ring[i];
+
+		packets += READ_ONCE(ring->packets);
+		bytes   += READ_ONCE(ring->bytes);
+	}
+	dev->stats.rx_packets = packets;
+	dev->stats.rx_bytes = bytes;
+
+	packets = 0;
+	bytes = 0;
+	for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+		const struct mlx4_en_tx_ring *ring = priv->tx_ring[TX][i];
+
+		packets += READ_ONCE(ring->packets);
+		bytes   += READ_ONCE(ring->bytes);
+	}
+	dev->stats.tx_packets = packets;
+	dev->stats.tx_bytes = bytes;
+}
+
 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
 {
 	struct mlx4_counter tmp_counter_stats;
@@ -159,6 +192,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_e
 	u64 in_mod = reset << 8 | port;
 	int err;
 	int i, counter_index;
+	unsigned long sw_tx_dropped = 0;
 	unsigned long sw_rx_dropped = 0;
 
 	mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
@@ -174,40 +208,42 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_e
 
 	spin_lock_bh(&priv->stats_lock);
 
-	stats->rx_packets = 0;
-	stats->rx_bytes = 0;
+	mlx4_en_fold_software_stats(dev);
+
 	priv->port_stats.rx_chksum_good = 0;
 	priv->port_stats.rx_chksum_none = 0;
 	priv->port_stats.rx_chksum_complete = 0;
+	priv->xdp_stats.rx_xdp_drop    = 0;
+	priv->xdp_stats.rx_xdp_tx      = 0;
+	priv->xdp_stats.rx_xdp_tx_full = 0;
 	for (i = 0; i < priv->rx_ring_num; i++) {
-		stats->rx_packets += priv->rx_ring[i]->packets;
-		stats->rx_bytes += priv->rx_ring[i]->bytes;
-		sw_rx_dropped += priv->rx_ring[i]->dropped;
-		priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok;
-		priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none;
-		priv->port_stats.rx_chksum_complete += priv->rx_ring[i]->csum_complete;
+		const struct mlx4_en_rx_ring *ring = priv->rx_ring[i];
+
+		sw_rx_dropped			+= READ_ONCE(ring->dropped);
+		priv->port_stats.rx_chksum_good += READ_ONCE(ring->csum_ok);
+		priv->port_stats.rx_chksum_none += READ_ONCE(ring->csum_none);
+		priv->port_stats.rx_chksum_complete += READ_ONCE(ring->csum_complete);
+		priv->xdp_stats.rx_xdp_drop	+= READ_ONCE(ring->xdp_drop);
+		priv->xdp_stats.rx_xdp_tx	+= READ_ONCE(ring->xdp_tx);
+		priv->xdp_stats.rx_xdp_tx_full	+= READ_ONCE(ring->xdp_tx_full);
 	}
-	stats->tx_packets = 0;
-	stats->tx_bytes = 0;
-	stats->tx_dropped = 0;
 	priv->port_stats.tx_chksum_offload = 0;
 	priv->port_stats.queue_stopped = 0;
 	priv->port_stats.wake_queue = 0;
 	priv->port_stats.tso_packets = 0;
 	priv->port_stats.xmit_more = 0;
 
-	for (i = 0; i < priv->tx_ring_num; i++) {
-		const struct mlx4_en_tx_ring *ring = priv->tx_ring[i];
+	for (i = 0; i < priv->tx_ring_num[TX]; i++) {
+		const struct mlx4_en_tx_ring *ring = priv->tx_ring[TX][i];
 
-		stats->tx_packets += ring->packets;
-		stats->tx_bytes += ring->bytes;
-		stats->tx_dropped += ring->tx_dropped;
-		priv->port_stats.tx_chksum_offload += ring->tx_csum;
-		priv->port_stats.queue_stopped     += ring->queue_stopped;
-		priv->port_stats.wake_queue        += ring->wake_queue;
-		priv->port_stats.tso_packets       += ring->tso_packets;
-		priv->port_stats.xmit_more         += ring->xmit_more;
+		sw_tx_dropped			   += READ_ONCE(ring->tx_dropped);
+		priv->port_stats.tx_chksum_offload += READ_ONCE(ring->tx_csum);
+		priv->port_stats.queue_stopped     += READ_ONCE(ring->queue_stopped);
+		priv->port_stats.wake_queue        += READ_ONCE(ring->wake_queue);
+		priv->port_stats.tso_packets       += READ_ONCE(ring->tso_packets);
+		priv->port_stats.xmit_more         += READ_ONCE(ring->xmit_more);
 	}
+
 	if (mlx4_is_master(mdev->dev)) {
 		stats->rx_packets = en_stats_adder(&mlx4_en_stats->RTOT_prio_0,
 						   &mlx4_en_stats->RTOT_prio_1,
@@ -245,7 +281,8 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_e
 	stats->rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
 	stats->rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
 	stats->rx_fifo_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
-	stats->tx_dropped += be32_to_cpu(mlx4_en_stats->TDROP);
+	stats->tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP) +
+			    sw_tx_dropped;
 
 	/* RX stats */
 	priv->pkstats.rx_multicast_packets = stats->multicast;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_rx.c	2017-02-12 16:03:20.000000000 -0500
@@ -96,7 +96,6 @@ static int mlx4_en_alloc_frags(struct ml
 	struct mlx4_en_rx_alloc page_alloc[MLX4_EN_MAX_RX_FRAGS];
 	const struct mlx4_en_frag_info *frag_info;
 	struct page *page;
-	dma_addr_t dma;
 	int i;
 
 	for (i = 0; i < priv->num_frags; i++) {
@@ -115,9 +114,10 @@ static int mlx4_en_alloc_frags(struct ml
 
 	for (i = 0; i < priv->num_frags; i++) {
 		frags[i] = ring_alloc[i];
-		dma = ring_alloc[i].dma + ring_alloc[i].page_offset;
+		frags[i].page_offset += priv->frag_info[i].rx_headroom;
+		rx_desc->data[i].addr = cpu_to_be64(frags[i].dma +
+						    frags[i].page_offset);
 		ring_alloc[i] = page_alloc[i];
-		rx_desc->data[i].addr = cpu_to_be64(dma);
 	}
 
 	return 0;
@@ -250,7 +250,8 @@ static int mlx4_en_prepare_rx_desc(struc
 
 	if (ring->page_cache.index > 0) {
 		frags[0] = ring->page_cache.buf[--ring->page_cache.index];
-		rx_desc->data[0].addr = cpu_to_be64(frags[0].dma);
+		rx_desc->data[0].addr = cpu_to_be64(frags[0].dma +
+						    frags[0].page_offset);
 		return 0;
 	}
 
@@ -444,8 +445,14 @@ int mlx4_en_activate_rx_rings(struct mlx
 		ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn;
 
 		ring->stride = stride;
-		if (ring->stride <= TXBB_SIZE)
+		if (ring->stride <= TXBB_SIZE) {
+			/* Stamp first unused send wqe */
+			__be32 *ptr = (__be32 *)ring->buf;
+			__be32 stamp = cpu_to_be32(1 << STAMP_SHIFT);
+			*ptr = stamp;
+			/* Move pointer to start of rx section */
 			ring->buf += TXBB_SIZE;
+		}
 
 		ring->log_stride = ffs(ring->stride) - 1;
 		ring->buf_size = ring->size * ring->stride;
@@ -507,8 +514,11 @@ void mlx4_en_recover_from_oom(struct mlx
 		return;
 
 	for (ring = 0; ring < priv->rx_ring_num; ring++) {
-		if (mlx4_en_is_ring_empty(priv->rx_ring[ring]))
+		if (mlx4_en_is_ring_empty(priv->rx_ring[ring])) {
+			local_bh_disable();
 			napi_reschedule(&priv->rx_cq[ring]->napi);
+			local_bh_enable();
+		}
 	}
 }
 
@@ -688,18 +698,23 @@ out_loopback:
 	dev_kfree_skb_any(skb);
 }
 
-static void mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
-				     struct mlx4_en_rx_ring *ring)
+static bool mlx4_en_refill_rx_buffers(struct mlx4_en_priv *priv,
+				      struct mlx4_en_rx_ring *ring)
 {
-	int index = ring->prod & ring->size_mask;
+	u32 missing = ring->actual_size - (ring->prod - ring->cons);
 
-	while ((u32) (ring->prod - ring->cons) < ring->actual_size) {
-		if (mlx4_en_prepare_rx_desc(priv, ring, index,
+	/* Try to batch allocations, but not too much. */
+	if (missing < 8)
+		return false;
+	do {
+		if (mlx4_en_prepare_rx_desc(priv, ring,
+					    ring->prod & ring->size_mask,
 					    GFP_ATOMIC | __GFP_COLD))
 			break;
 		ring->prod++;
-		index = ring->prod & ring->size_mask;
-	}
+	} while (--missing);
+
+	return true;
 }
 
 /* When hardware doesn't strip the vlan, we need to calculate the checksum
@@ -788,7 +803,6 @@ int mlx4_en_process_rx_cq(struct net_dev
 	struct bpf_prog *xdp_prog;
 	int doorbell_pending;
 	struct sk_buff *skb;
-	int tx_index;
 	int index;
 	int nr;
 	unsigned int length;
@@ -808,7 +822,6 @@ int mlx4_en_process_rx_cq(struct net_dev
 	rcu_read_lock();
 	xdp_prog = rcu_dereference(ring->xdp_prog);
 	doorbell_pending = 0;
-	tx_index = (priv->tx_ring_num - priv->xdp_ring_num) + cq->ring;
 
 	/* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
 	 * descriptor offset can be deduced from the CQE index instead of
@@ -877,8 +890,6 @@ int mlx4_en_process_rx_cq(struct net_dev
 		 */
 		length = be32_to_cpu(cqe->byte_cnt);
 		length -= ring->fcs_del;
-		ring->bytes += length;
-		ring->packets++;
 		l2_tunnel = (dev->hw_enc_features & NETIF_F_RXCSUM) &&
 			(cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_L2_TUNNEL));
 
@@ -888,6 +899,7 @@ int mlx4_en_process_rx_cq(struct net_dev
 		if (xdp_prog) {
 			struct xdp_buff xdp;
 			dma_addr_t dma;
+			void *orig_data;
 			u32 act;
 
 			dma = be64_to_cpu(rx_desc->data[0].addr);
@@ -895,31 +907,43 @@ int mlx4_en_process_rx_cq(struct net_dev
 						priv->frag_info[0].frag_size,
 						DMA_FROM_DEVICE);
 
-			xdp.data = page_address(frags[0].page) +
-							frags[0].page_offset;
+			xdp.data_hard_start = page_address(frags[0].page);
+			xdp.data = xdp.data_hard_start + frags[0].page_offset;
 			xdp.data_end = xdp.data + length;
+			orig_data = xdp.data;
 
 			act = bpf_prog_run_xdp(xdp_prog, &xdp);
+
+			if (xdp.data != orig_data) {
+				length = xdp.data_end - xdp.data;
+				frags[0].page_offset = xdp.data -
+					xdp.data_hard_start;
+			}
+
 			switch (act) {
 			case XDP_PASS:
 				break;
 			case XDP_TX:
-				if (likely(!mlx4_en_xmit_frame(frags, dev,
-							length, tx_index,
+				if (likely(!mlx4_en_xmit_frame(ring, frags, dev,
+							length, cq->ring,
 							&doorbell_pending)))
 					goto consumed;
-				goto xdp_drop; /* Drop on xmit failure */
+				goto xdp_drop_no_cnt; /* Drop on xmit failure */
 			default:
 				bpf_warn_invalid_xdp_action(act);
 			case XDP_ABORTED:
 			case XDP_DROP:
-xdp_drop:
+				ring->xdp_drop++;
+xdp_drop_no_cnt:
 				if (likely(mlx4_en_rx_recycle(ring, frags)))
 					goto consumed;
 				goto next;
 			}
 		}
 
+		ring->bytes += length;
+		ring->packets++;
+
 		if (likely(dev->features & NETIF_F_RXCSUM)) {
 			if (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
 						      MLX4_CQE_STATUS_UDP)) {
@@ -1081,15 +1105,20 @@ consumed:
 
 out:
 	rcu_read_unlock();
-	if (doorbell_pending)
-		mlx4_en_xmit_doorbell(priv->tx_ring[tx_index]);
 
+	if (polled) {
+		if (doorbell_pending)
+			mlx4_en_xmit_doorbell(priv->tx_ring[TX_XDP][cq->ring]);
+
+		mlx4_cq_set_ci(&cq->mcq);
+		wmb(); /* ensure HW sees CQ consumer before we post new buffers */
+		ring->cons = cq->mcq.cons_index;
+	}
 	AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
-	mlx4_cq_set_ci(&cq->mcq);
-	wmb(); /* ensure HW sees CQ consumer before we post new buffers */
-	ring->cons = cq->mcq.cons_index;
-	mlx4_en_refill_rx_buffers(priv, ring);
-	mlx4_en_update_rx_prod_db(ring);
+
+	if (mlx4_en_refill_rx_buffers(priv, ring))
+		mlx4_en_update_rx_prod_db(ring);
+
 	return polled;
 }
 
@@ -1131,14 +1160,17 @@ int mlx4_en_poll_rx_cq(struct napi_struc
 			return budget;
 
 		/* Current cpu is not according to smp_irq_affinity -
-		 * probably affinity changed. need to stop this NAPI
-		 * poll, and restart it on the right CPU
+		 * probably affinity changed. Need to stop this NAPI
+		 * poll, and restart it on the right CPU.
+		 * Try to avoid returning a too small value (like 0),
+		 * to not fool net_rx_action() and its netdev_budget
 		 */
-		done = 0;
+		if (done)
+			done--;
 	}
 	/* Done for now */
-	napi_complete_done(napi, done);
-	mlx4_en_arm_cq(priv, cq);
+	if (napi_complete_done(napi, done))
+		mlx4_en_arm_cq(priv, cq);
 	return done;
 }
 
@@ -1151,37 +1183,41 @@ static const int frag_sizes[] = {
 
 void mlx4_en_calc_rx_buf(struct net_device *dev)
 {
-	enum dma_data_direction dma_dir = PCI_DMA_FROMDEVICE;
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	int eff_mtu = MLX4_EN_EFF_MTU(dev->mtu);
-	int order = MLX4_EN_ALLOC_PREFER_ORDER;
-	u32 align = SMP_CACHE_BYTES;
-	int buf_size = 0;
 	int i = 0;
 
 	/* bpf requires buffers to be set up as 1 packet per page.
 	 * This only works when num_frags == 1.
 	 */
-	if (priv->xdp_ring_num) {
-		dma_dir = PCI_DMA_BIDIRECTIONAL;
-		/* This will gain efficient xdp frame recycling at the expense
-		 * of more costly truesize accounting
+	if (priv->tx_ring_num[TX_XDP]) {
+		priv->frag_info[0].order = 0;
+		priv->frag_info[0].frag_size = eff_mtu;
+		priv->frag_info[0].frag_prefix_size = 0;
+		/* This will gain efficient xdp frame recycling at the
+		 * expense of more costly truesize accounting
 		 */
-		align = PAGE_SIZE;
-		order = 0;
-	}
+		priv->frag_info[0].frag_stride = PAGE_SIZE;
+		priv->frag_info[0].dma_dir = PCI_DMA_BIDIRECTIONAL;
+		priv->frag_info[0].rx_headroom = XDP_PACKET_HEADROOM;
+		i = 1;
+	} else {
+		int buf_size = 0;
 
-	while (buf_size < eff_mtu) {
-		priv->frag_info[i].order = order;
-		priv->frag_info[i].frag_size =
-			(eff_mtu > buf_size + frag_sizes[i]) ?
-				frag_sizes[i] : eff_mtu - buf_size;
-		priv->frag_info[i].frag_prefix_size = buf_size;
-		priv->frag_info[i].frag_stride =
-				ALIGN(priv->frag_info[i].frag_size, align);
-		priv->frag_info[i].dma_dir = dma_dir;
-		buf_size += priv->frag_info[i].frag_size;
-		i++;
+		while (buf_size < eff_mtu) {
+			priv->frag_info[i].order = MLX4_EN_ALLOC_PREFER_ORDER;
+			priv->frag_info[i].frag_size =
+				(eff_mtu > buf_size + frag_sizes[i]) ?
+					frag_sizes[i] : eff_mtu - buf_size;
+			priv->frag_info[i].frag_prefix_size = buf_size;
+			priv->frag_info[i].frag_stride =
+				ALIGN(priv->frag_info[i].frag_size,
+				      SMP_CACHE_BYTES);
+			priv->frag_info[i].dma_dir = PCI_DMA_FROMDEVICE;
+			priv->frag_info[i].rx_headroom = 0;
+			buf_size += priv->frag_info[i].frag_size;
+			i++;
+		}
 	}
 
 	priv->num_frags = i;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_selftest.c	2017-02-12 16:03:20.000000000 -0500
@@ -68,7 +68,7 @@ static int mlx4_en_test_loopback_xmit(st
 	memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);
 	eth_zero_addr(ethh->h_source);
 	ethh->h_proto = htons(ETH_P_ARP);
-	skb_set_mac_header(skb, 0);
+	skb_reset_mac_header(skb);
 	for (i = 0; i < packet_size; ++i)	/* fill our packet */
 		packet[i] = (unsigned char)(i & 0xff);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/en_tx.c	2017-02-12 16:03:20.000000000 -0500
@@ -66,7 +66,7 @@ int mlx4_en_create_tx_ring(struct mlx4_e
 
 	ring->size = size;
 	ring->size_mask = size - 1;
-	ring->stride = stride;
+	ring->sp_stride = stride;
 	ring->full_size = ring->size - HEADROOM - MAX_DESC_TXBBS;
 
 	tmp = size * sizeof(struct mlx4_en_tx_info);
@@ -90,22 +90,22 @@ int mlx4_en_create_tx_ring(struct mlx4_e
 			goto err_info;
 		}
 	}
-	ring->buf_size = ALIGN(size * ring->stride, MLX4_EN_PAGE_SIZE);
+	ring->buf_size = ALIGN(size * ring->sp_stride, MLX4_EN_PAGE_SIZE);
 
 	/* Allocate HW buffers on provided NUMA node */
 	set_dev_node(&mdev->dev->persist->pdev->dev, node);
-	err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+	err = mlx4_alloc_hwq_res(mdev->dev, &ring->sp_wqres, ring->buf_size);
 	set_dev_node(&mdev->dev->persist->pdev->dev, mdev->dev->numa_node);
 	if (err) {
 		en_err(priv, "Failed allocating hwq resources\n");
 		goto err_bounce;
 	}
 
-	ring->buf = ring->wqres.buf.direct.buf;
+	ring->buf = ring->sp_wqres.buf.direct.buf;
 
 	en_dbg(DRV, priv, "Allocated TX ring (addr:%p) - buf:%p size:%d buf_size:%d dma:%llx\n",
 	       ring, ring->buf, ring->size, ring->buf_size,
-	       (unsigned long long) ring->wqres.buf.direct.map);
+	       (unsigned long long) ring->sp_wqres.buf.direct.map);
 
 	err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn,
 				    MLX4_RESERVE_ETH_BF_QP);
@@ -114,12 +114,12 @@ int mlx4_en_create_tx_ring(struct mlx4_e
 		goto err_hwq_res;
 	}
 
-	err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp, GFP_KERNEL);
+	err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->sp_qp, GFP_KERNEL);
 	if (err) {
 		en_err(priv, "Failed allocating qp %d\n", ring->qpn);
 		goto err_reserve;
 	}
-	ring->qp.event = mlx4_en_sqp_event;
+	ring->sp_qp.event = mlx4_en_sqp_event;
 
 	err = mlx4_bf_alloc(mdev->dev, &ring->bf, node);
 	if (err) {
@@ -141,7 +141,7 @@ int mlx4_en_create_tx_ring(struct mlx4_e
 	if (queue_index < priv->num_tx_rings_p_up)
 		cpumask_set_cpu(cpumask_local_spread(queue_index,
 						     priv->mdev->dev->numa_node),
-				&ring->affinity_mask);
+				&ring->sp_affinity_mask);
 
 	*pring = ring;
 	return 0;
@@ -149,7 +149,7 @@ int mlx4_en_create_tx_ring(struct mlx4_e
 err_reserve:
 	mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
 err_hwq_res:
-	mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+	mlx4_free_hwq_res(mdev->dev, &ring->sp_wqres, ring->buf_size);
 err_bounce:
 	kfree(ring->bounce_buf);
 	ring->bounce_buf = NULL;
@@ -171,10 +171,10 @@ void mlx4_en_destroy_tx_ring(struct mlx4
 
 	if (ring->bf_alloced)
 		mlx4_bf_free(mdev->dev, &ring->bf);
-	mlx4_qp_remove(mdev->dev, &ring->qp);
-	mlx4_qp_free(mdev->dev, &ring->qp);
+	mlx4_qp_remove(mdev->dev, &ring->sp_qp);
+	mlx4_qp_free(mdev->dev, &ring->sp_qp);
 	mlx4_qp_release_range(priv->mdev->dev, ring->qpn, 1);
-	mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+	mlx4_free_hwq_res(mdev->dev, &ring->sp_wqres, ring->buf_size);
 	kfree(ring->bounce_buf);
 	ring->bounce_buf = NULL;
 	kvfree(ring->tx_info);
@@ -190,7 +190,7 @@ int mlx4_en_activate_tx_ring(struct mlx4
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int err;
 
-	ring->cqn = cq;
+	ring->sp_cqn = cq;
 	ring->prod = 0;
 	ring->cons = 0xffffffff;
 	ring->last_nr_txbb = 1;
@@ -198,21 +198,21 @@ int mlx4_en_activate_tx_ring(struct mlx4
 	memset(ring->buf, 0, ring->buf_size);
 	ring->free_tx_desc = mlx4_en_free_tx_desc;
 
-	ring->qp_state = MLX4_QP_STATE_RST;
-	ring->doorbell_qpn = cpu_to_be32(ring->qp.qpn << 8);
+	ring->sp_qp_state = MLX4_QP_STATE_RST;
+	ring->doorbell_qpn = cpu_to_be32(ring->sp_qp.qpn << 8);
 	ring->mr_key = cpu_to_be32(mdev->mr.key);
 
-	mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
-				ring->cqn, user_prio, &ring->context);
+	mlx4_en_fill_qp_context(priv, ring->size, ring->sp_stride, 1, 0, ring->qpn,
+				ring->sp_cqn, user_prio, &ring->sp_context);
 	if (ring->bf_alloced)
-		ring->context.usr_page =
+		ring->sp_context.usr_page =
 			cpu_to_be32(mlx4_to_hw_uar_index(mdev->dev,
 							 ring->bf.uar->index));
 
-	err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
-			       &ring->qp, &ring->qp_state);
-	if (!cpumask_empty(&ring->affinity_mask))
-		netif_set_xps_queue(priv->dev, &ring->affinity_mask,
+	err = mlx4_qp_to_ready(mdev->dev, &ring->sp_wqres.mtt, &ring->sp_context,
+			       &ring->sp_qp, &ring->sp_qp_state);
+	if (!cpumask_empty(&ring->sp_affinity_mask))
+		netif_set_xps_queue(priv->dev, &ring->sp_affinity_mask,
 				    ring->queue_index);
 
 	return err;
@@ -223,8 +223,8 @@ void mlx4_en_deactivate_tx_ring(struct m
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
 
-	mlx4_qp_modify(mdev->dev, NULL, ring->qp_state,
-		       MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
+	mlx4_qp_modify(mdev->dev, NULL, ring->sp_qp_state,
+		       MLX4_QP_STATE_RST, NULL, 0, 0, &ring->sp_qp);
 }
 
 static inline bool mlx4_en_is_tx_ring_full(struct mlx4_en_tx_ring *ring)
@@ -354,7 +354,7 @@ u32 mlx4_en_recycle_tx_desc(struct mlx4_
 	struct mlx4_en_rx_alloc frame = {
 		.page = tx_info->page,
 		.dma = tx_info->map0_dma,
-		.page_offset = 0,
+		.page_offset = XDP_PACKET_HEADROOM,
 		.page_size = PAGE_SIZE,
 	};
 
@@ -392,7 +392,8 @@ int mlx4_en_free_tx_buf(struct net_devic
 		cnt++;
 	}
 
-	netdev_tx_reset_queue(ring->tx_queue);
+	if (ring->tx_queue)
+		netdev_tx_reset_queue(ring->tx_queue);
 
 	if (cnt)
 		en_dbg(DRV, priv, "Freed %d uncompleted tx descriptors\n", cnt);
@@ -405,7 +406,7 @@ static bool mlx4_en_process_tx_cq(struct
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_cq *mcq = &cq->mcq;
-	struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
+	struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->type][cq->ring];
 	struct mlx4_cqe *cqe;
 	u16 index;
 	u16 new_index, ring_index, stamp_index;
@@ -807,7 +808,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff
 	bool bf_ok;
 
 	tx_ind = skb_get_queue_mapping(skb);
-	ring = priv->tx_ring[tx_ind];
+	ring = priv->tx_ring[TX][tx_ind];
 
 	if (!priv->port_up)
 		goto tx_drop;
@@ -1078,7 +1079,8 @@ tx_drop:
 	return NETDEV_TX_OK;
 }
 
-netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
+netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_ring *rx_ring,
+			       struct mlx4_en_rx_alloc *frame,
 			       struct net_device *dev, unsigned int length,
 			       int tx_ind, int *doorbell_pending)
 {
@@ -1101,7 +1103,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct ml
 	BUILD_BUG_ON_MSG(ALIGN(CTRL_SIZE + DS_SIZE, TXBB_SIZE) != TXBB_SIZE,
 			 "mlx4_en_xmit_frame requires minimum size tx desc");
 
-	ring = priv->tx_ring[tx_ind];
+	ring = priv->tx_ring[TX_XDP][tx_ind];
 
 	if (!priv->port_up)
 		goto tx_drop;
@@ -1130,7 +1132,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct ml
 	tx_info->page = frame->page;
 	frame->page = NULL;
 	tx_info->map0_dma = dma;
-	tx_info->map0_byte_count = length;
+	tx_info->map0_byte_count = PAGE_SIZE;
 	tx_info->nr_txbb = nr_txbb;
 	tx_info->nr_bytes = max_t(unsigned int, length, ETH_ZLEN);
 	tx_info->data_offset = (void *)data - (void *)tx_desc;
@@ -1139,9 +1141,10 @@ netdev_tx_t mlx4_en_xmit_frame(struct ml
 	tx_info->linear = 1;
 	tx_info->inl = 0;
 
-	dma_sync_single_for_device(priv->ddev, dma, length, PCI_DMA_TODEVICE);
+	dma_sync_single_range_for_device(priv->ddev, dma, frame->page_offset,
+					 length, PCI_DMA_TODEVICE);
 
-	data->addr = cpu_to_be64(dma);
+	data->addr = cpu_to_be64(dma + frame->page_offset);
 	data->lkey = ring->mr_key;
 	dma_wmb();
 	data->byte_count = cpu_to_be32(length);
@@ -1153,8 +1156,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct ml
 		((ring->prod & ring->size) ?
 		 cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
 
-	ring->packets++;
-	ring->bytes += tx_info->nr_bytes;
+	rx_ring->xdp_tx++;
 	AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, length);
 
 	ring->prod += nr_txbb;
@@ -1178,7 +1180,7 @@ netdev_tx_t mlx4_en_xmit_frame(struct ml
 	return NETDEV_TX_OK;
 
 tx_drop_count:
-	ring->tx_dropped++;
+	rx_ring->xdp_tx_full++;
 tx_drop:
 	return NETDEV_TX_BUSY;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/eq.c	2017-02-12 16:03:20.000000000 -0500
@@ -554,8 +554,9 @@ static int mlx4_eq_int(struct mlx4_dev *
 			break;
 
 		case MLX4_EVENT_TYPE_SRQ_LIMIT:
-			mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
-				 __func__);
+			mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n",
+				 __func__, be32_to_cpu(eqe->event.srq.srqn),
+				 eq->eqn);
 		case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
 			if (mlx4_is_master(dev)) {
 				/* forward only to slave owning the SRQ */
@@ -570,15 +571,19 @@ static int mlx4_eq_int(struct mlx4_dev *
 						  eq->eqn, eq->cons_index, ret);
 					break;
 				}
-				mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
-					  __func__, slave,
-					  be32_to_cpu(eqe->event.srq.srqn),
-					  eqe->type, eqe->subtype);
+				if (eqe->type ==
+				    MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+					mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
+						  __func__, slave,
+						  be32_to_cpu(eqe->event.srq.srqn),
+						  eqe->type, eqe->subtype);
 
 				if (!ret && slave != dev->caps.function) {
-					mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
-						  __func__, eqe->type,
-						  eqe->subtype, slave);
+					if (eqe->type ==
+					    MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+						mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
+							  __func__, eqe->type,
+							  eqe->subtype, slave);
 					mlx4_slave_event(dev, slave, eqe);
 					break;
 				}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/icm.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/icm.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/icm.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/icm.c	2017-02-12 16:03:20.000000000 -0500
@@ -118,8 +118,13 @@ static int mlx4_alloc_icm_coherent(struc
 	if (!buf)
 		return -ENOMEM;
 
+	if (offset_in_page(buf)) {
+		dma_free_coherent(dev, PAGE_SIZE << order,
+				  buf, sg_dma_address(mem));
+		return -ENOMEM;
+	}
+
 	sg_set_buf(mem, buf, PAGE_SIZE << order);
-	BUG_ON(mem->offset);
 	sg_dma_len(mem) = PAGE_SIZE << order;
 	return 0;
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/intf.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/intf.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/intf.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/intf.c	2017-02-12 16:03:20.000000000 -0500
@@ -222,6 +222,18 @@ void mlx4_unregister_device(struct mlx4_
 		return;
 
 	mlx4_stop_catas_poll(dev);
+	if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
+	    mlx4_is_slave(dev)) {
+		/* In mlx4_remove_one on a VF */
+		u32 slave_read =
+			swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
+
+		if (mlx4_comm_internal_err(slave_read)) {
+			mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
+				 __func__);
+			mlx4_enter_error_state(dev->persist);
+		}
+	}
 	mutex_lock(&intf_mutex);
 
 	list_for_each_entry(intf, &intf_list, list)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -7,7 +7,7 @@ config MLX4_EN
 	depends on MAY_USE_DEVLINK
 	depends on PCI
 	select MLX4_CORE
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	---help---
 	  This driver supports Mellanox Technologies ConnectX Ethernet
 	  devices.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -42,6 +42,7 @@
 #include <linux/io-mapping.h>
 #include <linux/delay.h>
 #include <linux/kmod.h>
+#include <linux/etherdevice.h>
 #include <net/devlink.h>
 
 #include <linux/mlx4/device.h>
@@ -782,6 +783,23 @@ int mlx4_is_slave_active(struct mlx4_dev
 }
 EXPORT_SYMBOL(mlx4_is_slave_active);
 
+void mlx4_handle_eth_header_mcast_prio(struct mlx4_net_trans_rule_hw_ctrl *ctrl,
+				       struct _rule_hw *eth_header)
+{
+	if (is_multicast_ether_addr(eth_header->eth.dst_mac) ||
+	    is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
+		struct mlx4_net_trans_rule_hw_eth *eth =
+			(struct mlx4_net_trans_rule_hw_eth *)eth_header;
+		struct _rule_hw *next_rule = (struct _rule_hw *)(eth + 1);
+		bool last_rule = next_rule->size == 0 && next_rule->id == 0 &&
+			next_rule->rsvd == 0;
+
+		if (last_rule)
+			ctrl->prio = cpu_to_be16(MLX4_DOMAIN_NIC);
+	}
+}
+EXPORT_SYMBOL(mlx4_handle_eth_header_mcast_prio);
+
 static void slave_adjust_steering_mode(struct mlx4_dev *dev,
 				       struct mlx4_dev_cap *dev_cap,
 				       struct mlx4_init_hca_param *hca_param)
@@ -1823,10 +1841,10 @@ static void unmap_bf_area(struct mlx4_de
 		io_mapping_free(mlx4_priv(dev)->bf_mapping);
 }
 
-cycle_t mlx4_read_clock(struct mlx4_dev *dev)
+u64 mlx4_read_clock(struct mlx4_dev *dev)
 {
 	u32 clockhi, clocklo, clockhi1;
-	cycle_t cycles;
+	u64 cycles;
 	int i;
 	struct mlx4_priv *priv = mlx4_priv(dev);
 
@@ -4020,49 +4038,51 @@ int mlx4_restart_one(struct pci_dev *pde
 	return err;
 }
 
+#define MLX_SP(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_FORCE_SENSE_PORT }
+#define MLX_VF(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_IS_VF }
+#define MLX_GN(id) { PCI_VDEVICE(MELLANOX, id), 0 }
+
 static const struct pci_device_id mlx4_pci_table[] = {
-	/* MT25408 "Hermon" SDR */
-	{ PCI_VDEVICE(MELLANOX, 0x6340), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25408 "Hermon" DDR */
-	{ PCI_VDEVICE(MELLANOX, 0x634a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25408 "Hermon" QDR */
-	{ PCI_VDEVICE(MELLANOX, 0x6354), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25408 "Hermon" DDR PCIe gen2 */
-	{ PCI_VDEVICE(MELLANOX, 0x6732), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25408 "Hermon" QDR PCIe gen2 */
-	{ PCI_VDEVICE(MELLANOX, 0x673c), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25408 "Hermon" EN 10GigE */
-	{ PCI_VDEVICE(MELLANOX, 0x6368), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25408 "Hermon" EN 10GigE PCIe gen2 */
-	{ PCI_VDEVICE(MELLANOX, 0x6750), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25458 ConnectX EN 10GBASE-T 10GigE */
-	{ PCI_VDEVICE(MELLANOX, 0x6372), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
-	{ PCI_VDEVICE(MELLANOX, 0x675a), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT26468 ConnectX EN 10GigE PCIe gen2*/
-	{ PCI_VDEVICE(MELLANOX, 0x6764), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
-	{ PCI_VDEVICE(MELLANOX, 0x6746), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT26478 ConnectX2 40GigE PCIe gen2 */
-	{ PCI_VDEVICE(MELLANOX, 0x676e), MLX4_PCI_DEV_FORCE_SENSE_PORT },
-	/* MT25400 Family [ConnectX-2 Virtual Function] */
-	{ PCI_VDEVICE(MELLANOX, 0x1002), MLX4_PCI_DEV_IS_VF },
+	/* MT25408 "Hermon" */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_SDR),	/* SDR */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_DDR),	/* DDR */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_QDR),	/* QDR */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_DDR_GEN2), /* DDR Gen2 */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_QDR_GEN2),	/* QDR Gen2 */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_EN),	/* EN 10GigE */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_HERMON_EN_GEN2),  /* EN 10GigE Gen2 */
+	/* MT25458 ConnectX EN 10GBASE-T */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN),
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_T_GEN2),	/* Gen2 */
+	/* MT26468 ConnectX EN 10GigE PCIe Gen2*/
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_GEN2),
+	/* MT26438 ConnectX EN 40GigE PCIe Gen2 5GT/s */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX_EN_5_GEN2),
+	/* MT26478 ConnectX2 40GigE PCIe Gen2 */
+	MLX_SP(PCI_DEVICE_ID_MELLANOX_CONNECTX2),
+	/* MT25400 Family [ConnectX-2] */
+	MLX_VF(0x1002),					/* Virtual Function */
 	/* MT27500 Family [ConnectX-3] */
-	{ PCI_VDEVICE(MELLANOX, 0x1003), 0 },
-	/* MT27500 Family [ConnectX-3 Virtual Function] */
-	{ PCI_VDEVICE(MELLANOX, 0x1004), MLX4_PCI_DEV_IS_VF },
-	{ PCI_VDEVICE(MELLANOX, 0x1005), 0 }, /* MT27510 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x1006), 0 }, /* MT27511 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x1007), 0 }, /* MT27520 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x1008), 0 }, /* MT27521 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x1009), 0 }, /* MT27530 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x100a), 0 }, /* MT27531 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x100b), 0 }, /* MT27540 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x100c), 0 }, /* MT27541 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x100d), 0 }, /* MT27550 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x100e), 0 }, /* MT27551 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x100f), 0 }, /* MT27560 Family */
-	{ PCI_VDEVICE(MELLANOX, 0x1010), 0 }, /* MT27561 Family */
+	MLX_GN(PCI_DEVICE_ID_MELLANOX_CONNECTX3),
+	MLX_VF(0x1004),					/* Virtual Function */
+	MLX_GN(0x1005),					/* MT27510 Family */
+	MLX_GN(0x1006),					/* MT27511 Family */
+	MLX_GN(PCI_DEVICE_ID_MELLANOX_CONNECTX3_PRO),	/* MT27520 Family */
+	MLX_GN(0x1008),					/* MT27521 Family */
+	MLX_GN(0x1009),					/* MT27530 Family */
+	MLX_GN(0x100a),					/* MT27531 Family */
+	MLX_GN(0x100b),					/* MT27540 Family */
+	MLX_GN(0x100c),					/* MT27541 Family */
+	MLX_GN(0x100d),					/* MT27550 Family */
+	MLX_GN(0x100e),					/* MT27551 Family */
+	MLX_GN(0x100f),					/* MT27560 Family */
+	MLX_GN(0x1010),					/* MT27561 Family */
+
+	/*
+	 * See the mellanox_check_broken_intx_masking() quirk when
+	 * adding devices
+	 */
+
 	{ 0, }
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h	2017-02-12 16:03:20.000000000 -0500
@@ -207,8 +207,11 @@ enum {
  */
 
 enum cq_type {
-	RX = 0,
-	TX = 1,
+	/* keep tx types first */
+	TX,
+	TX_XDP,
+#define MLX4_EN_NUM_TX_TYPES (TX_XDP + 1)
+	RX,
 };
 
 
@@ -278,46 +281,50 @@ struct mlx4_en_tx_ring {
 	u32			last_nr_txbb;
 	u32			cons;
 	unsigned long		wake_queue;
+	struct netdev_queue	*tx_queue;
+	u32			(*free_tx_desc)(struct mlx4_en_priv *priv,
+						struct mlx4_en_tx_ring *ring,
+						int index, u8 owner,
+						u64 timestamp, int napi_mode);
+	struct mlx4_en_rx_ring	*recycle_ring;
 
 	/* cache line used and dirtied in mlx4_en_xmit() */
 	u32			prod ____cacheline_aligned_in_smp;
+	unsigned int		tx_dropped;
 	unsigned long		bytes;
 	unsigned long		packets;
 	unsigned long		tx_csum;
 	unsigned long		tso_packets;
 	unsigned long		xmit_more;
-	unsigned int		tx_dropped;
 	struct mlx4_bf		bf;
-	unsigned long		queue_stopped;
 
 	/* Following part should be mostly read */
-	cpumask_t		affinity_mask;
-	struct mlx4_qp		qp;
-	struct mlx4_hwq_resources wqres;
+	__be32			doorbell_qpn;
+	__be32			mr_key;
 	u32			size; /* number of TXBBs */
 	u32			size_mask;
-	u16			stride;
 	u32			full_size;
-	u16			cqn;	/* index of port CQ associated with this ring */
 	u32			buf_size;
-	__be32			doorbell_qpn;
-	__be32			mr_key;
 	void			*buf;
 	struct mlx4_en_tx_info	*tx_info;
-	struct mlx4_en_rx_ring	*recycle_ring;
-	u32			(*free_tx_desc)(struct mlx4_en_priv *priv,
-						struct mlx4_en_tx_ring *ring,
-						int index, u8 owner,
-						u64 timestamp, int napi_mode);
-	u8			*bounce_buf;
-	struct mlx4_qp_context	context;
 	int			qpn;
-	enum mlx4_qp_state	qp_state;
 	u8			queue_index;
 	bool			bf_enabled;
 	bool			bf_alloced;
-	struct netdev_queue	*tx_queue;
-	int			hwtstamp_tx_type;
+	u8			hwtstamp_tx_type;
+	u8			*bounce_buf;
+
+	/* Not used in fast path
+	 * Only queue_stopped might be used if BQL is not properly working.
+	 */
+	unsigned long		queue_stopped;
+	struct mlx4_hwq_resources sp_wqres;
+	struct mlx4_qp		sp_qp;
+	struct mlx4_qp_context	sp_context;
+	cpumask_t		sp_affinity_mask;
+	enum mlx4_qp_state	sp_qp_state;
+	u16			sp_stride;
+	u16			sp_cqn;	/* index of port CQ associated with this ring */
 } ____cacheline_aligned_in_smp;
 
 struct mlx4_en_rx_desc {
@@ -347,6 +354,9 @@ struct mlx4_en_rx_ring {
 	unsigned long csum_ok;
 	unsigned long csum_none;
 	unsigned long csum_complete;
+	unsigned long xdp_drop;
+	unsigned long xdp_tx;
+	unsigned long xdp_tx_full;
 	unsigned long dropped;
 	int hwtstamp_rx_filter;
 	cpumask_var_t affinity_mask;
@@ -361,7 +371,7 @@ struct mlx4_en_cq {
 	int size;
 	int buf_size;
 	int vector;
-	enum cq_type is_tx;
+	enum cq_type type;
 	u16 moder_time;
 	u16 moder_cnt;
 	struct mlx4_cqe *buf;
@@ -372,7 +382,7 @@ struct mlx4_en_cq {
 
 struct mlx4_en_port_profile {
 	u32 flags;
-	u32 tx_ring_num;
+	u32 tx_ring_num[MLX4_EN_NUM_TX_TYPES];
 	u32 rx_ring_num;
 	u32 tx_ring_size;
 	u32 rx_ring_size;
@@ -465,7 +475,8 @@ struct mlx4_en_frag_info {
 	u16 frag_prefix_size;
 	u32 frag_stride;
 	enum dma_data_direction dma_dir;
-	int order;
+	u16 order;
+	u16 rx_headroom;
 };
 
 #ifdef CONFIG_MLX4_EN_DCB
@@ -569,17 +580,16 @@ struct mlx4_en_priv {
 	u32 flags;
 	u8 num_tx_rings_p_up;
 	u32 tx_work_limit;
-	u32 tx_ring_num;
+	u32 tx_ring_num[MLX4_EN_NUM_TX_TYPES];
 	u32 rx_ring_num;
 	u32 rx_skb_size;
 	struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS];
 	u16 num_frags;
 	u16 log_rx_info;
-	int xdp_ring_num;
 
-	struct mlx4_en_tx_ring **tx_ring;
+	struct mlx4_en_tx_ring **tx_ring[MLX4_EN_NUM_TX_TYPES];
 	struct mlx4_en_rx_ring *rx_ring[MAX_RX_RINGS];
-	struct mlx4_en_cq **tx_cq;
+	struct mlx4_en_cq **tx_cq[MLX4_EN_NUM_TX_TYPES];
 	struct mlx4_en_cq *rx_cq[MAX_RX_RINGS];
 	struct mlx4_qp drop_qp;
 	struct work_struct rx_mode_task;
@@ -597,6 +607,7 @@ struct mlx4_en_priv {
 	struct mlx4_en_flow_stats_rx rx_flowstats;
 	struct mlx4_en_flow_stats_tx tx_flowstats;
 	struct mlx4_en_port_stats port_stats;
+	struct mlx4_en_xdp_stats xdp_stats;
 	struct mlx4_en_stats_bitmap stats_bitmap;
 	struct list_head mc_list;
 	struct list_head curr_list;
@@ -668,7 +679,8 @@ void mlx4_en_set_stats_bitmap(struct mlx
 
 int mlx4_en_try_alloc_resources(struct mlx4_en_priv *priv,
 				struct mlx4_en_priv *tmp,
-				struct mlx4_en_port_profile *prof);
+				struct mlx4_en_port_profile *prof,
+				bool carry_xdp_prog);
 void mlx4_en_safe_replace_resources(struct mlx4_en_priv *priv,
 				    struct mlx4_en_priv *tmp);
 
@@ -685,7 +697,8 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq)
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb,
 			 void *accel_priv, select_queue_fallback_t fallback);
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
-netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_alloc *frame,
+netdev_tx_t mlx4_en_xmit_frame(struct mlx4_en_rx_ring *rx_ring,
+			       struct mlx4_en_rx_alloc *frame,
 			       struct net_device *dev, unsigned int length,
 			       int tx_ind, int *doorbell_pending);
 void mlx4_en_xmit_doorbell(struct mlx4_en_tx_ring *ring);
@@ -744,6 +757,7 @@ void mlx4_en_rx_irq(struct mlx4_cq *mcq)
 int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
 int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv);
 
+void mlx4_en_fold_software_stats(struct net_device *dev);
 int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
 int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4.h	2017-02-12 16:03:20.000000000 -0500
@@ -1220,6 +1220,7 @@ void mlx4_qp_event(struct mlx4_dev *dev,
 void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
 
 void mlx4_enter_error_state(struct mlx4_dev_persistent *persist);
+int mlx4_comm_internal_err(u32 slave_read);
 
 int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
 		    enum mlx4_port_type *type);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/mlx4_stats.h	2017-02-12 16:03:20.000000000 -0500
@@ -55,6 +55,13 @@ struct mlx4_en_perf_stats {
 #define NUM_PERF_COUNTERS		6
 };
 
+struct mlx4_en_xdp_stats {
+	unsigned long rx_xdp_drop;
+	unsigned long rx_xdp_tx;
+	unsigned long rx_xdp_tx_full;
+#define NUM_XDP_STATS		3
+};
+
 #define NUM_MAIN_STATS	21
 
 #define MLX4_NUM_PRIORITIES	8
@@ -107,7 +114,8 @@ enum {
 };
 
 #define NUM_ALL_STATS	(NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + \
-			 NUM_FLOW_STATS + NUM_PERF_STATS + NUM_PF_STATS)
+			 NUM_FLOW_STATS + NUM_PERF_STATS + NUM_PF_STATS + \
+			 NUM_XDP_STATS)
 
 #define MLX4_FIND_NETDEV_STAT(n) (offsetof(struct net_device_stats, n) / \
 				  sizeof(((struct net_device_stats *)0)->n))
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c	2017-02-12 16:03:20.000000000 -0500
@@ -2980,6 +2980,9 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4
 		put_res(dev, slave, srqn, RES_SRQ);
 		qp->srq = srq;
 	}
+
+	/* Save param3 for dynamic changes from VST back to VGT */
+	qp->param3 = qpc->param3;
 	put_res(dev, slave, rcqn, RES_CQ);
 	put_res(dev, slave, mtt_base, RES_MTT);
 	res_end_move(dev, slave, RES_QP, qpn);
@@ -3772,7 +3775,6 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4
 	int qpn = vhcr->in_modifier & 0x7fffff;
 	struct res_qp *qp;
 	u8 orig_sched_queue;
-	__be32	orig_param3 = qpc->param3;
 	u8 orig_vlan_control = qpc->pri_path.vlan_control;
 	u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
 	u8 orig_pri_path_fl = qpc->pri_path.fl;
@@ -3814,7 +3816,6 @@ out:
 	 */
 	if (!err) {
 		qp->sched_queue = orig_sched_queue;
-		qp->param3	= orig_param3;
 		qp->vlan_control = orig_vlan_control;
 		qp->fvl_rx	=  orig_fvl_rx;
 		qp->pri_path_fl = orig_pri_path_fl;
@@ -4164,22 +4165,6 @@ static int validate_eth_header_mac(int s
 	return 0;
 }
 
-static void handle_eth_header_mcast_prio(struct mlx4_net_trans_rule_hw_ctrl *ctrl,
-					 struct _rule_hw *eth_header)
-{
-	if (is_multicast_ether_addr(eth_header->eth.dst_mac) ||
-	    is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
-		struct mlx4_net_trans_rule_hw_eth *eth =
-			(struct mlx4_net_trans_rule_hw_eth *)eth_header;
-		struct _rule_hw *next_rule = (struct _rule_hw *)(eth + 1);
-		bool last_rule = next_rule->size == 0 && next_rule->id == 0 &&
-			next_rule->rsvd == 0;
-
-		if (last_rule)
-			ctrl->prio = cpu_to_be16(MLX4_DOMAIN_NIC);
-	}
-}
-
 /*
  * In case of missing eth header, append eth header with a MAC address
  * assigned to the VF.
@@ -4363,10 +4348,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper
 	header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
 
 	if (header_id == MLX4_NET_TRANS_RULE_ID_ETH)
-		handle_eth_header_mcast_prio(ctrl, rule_header);
-
-	if (slave == dev->caps.function)
-		goto execute;
+		mlx4_handle_eth_header_mcast_prio(ctrl, rule_header);
 
 	switch (header_id) {
 	case MLX4_NET_TRANS_RULE_ID_ETH:
@@ -4394,7 +4376,6 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper
 		goto err_put_qp;
 	}
 
-execute:
 	err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
 			   vhcr->in_modifier, 0,
 			   MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
@@ -4473,6 +4454,7 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper
 	struct res_qp *rqp;
 	struct res_fs_rule *rrule;
 	u64 mirr_reg_id;
+	int qpn;
 
 	if (dev->caps.steering_mode !=
 	    MLX4_STEERING_MODE_DEVICE_MANAGED)
@@ -4489,10 +4471,11 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper
 	}
 	mirr_reg_id = rrule->mirr_rule_id;
 	kfree(rrule->mirr_mbox);
+	qpn = rrule->qpn;
 
 	/* Release the rule form busy state before removal */
 	put_res(dev, slave, vhcr->in_param, RES_FS_RULE);
-	err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp);
+	err = get_res(dev, slave, qpn, RES_QP, &rqp);
 	if (err)
 		return err;
 
@@ -4517,7 +4500,7 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper
 	if (!err)
 		atomic_dec(&rqp->ref_count);
 out:
-	put_res(dev, slave, rrule->qpn, RES_QP);
+	put_res(dev, slave, qpn, RES_QP);
 	return err;
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/alloc.c	2017-02-12 16:03:20.000000000 -0500
@@ -106,6 +106,63 @@ void mlx5_buf_free(struct mlx5_core_dev
 }
 EXPORT_SYMBOL_GPL(mlx5_buf_free);
 
+int mlx5_frag_buf_alloc_node(struct mlx5_core_dev *dev, int size,
+			     struct mlx5_frag_buf *buf, int node)
+{
+	int i;
+
+	buf->size = size;
+	buf->npages = 1 << get_order(size);
+	buf->page_shift = PAGE_SHIFT;
+	buf->frags = kcalloc(buf->npages, sizeof(struct mlx5_buf_list),
+			     GFP_KERNEL);
+	if (!buf->frags)
+		goto err_out;
+
+	for (i = 0; i < buf->npages; i++) {
+		struct mlx5_buf_list *frag = &buf->frags[i];
+		int frag_sz = min_t(int, size, PAGE_SIZE);
+
+		frag->buf = mlx5_dma_zalloc_coherent_node(dev, frag_sz,
+							  &frag->map, node);
+		if (!frag->buf)
+			goto err_free_buf;
+		if (frag->map & ((1 << buf->page_shift) - 1)) {
+			dma_free_coherent(&dev->pdev->dev, frag_sz,
+					  buf->frags[i].buf, buf->frags[i].map);
+			mlx5_core_warn(dev, "unexpected map alignment: %pad, page_shift=%d\n",
+				       &frag->map, buf->page_shift);
+			goto err_free_buf;
+		}
+		size -= frag_sz;
+	}
+
+	return 0;
+
+err_free_buf:
+	while (i--)
+		dma_free_coherent(&dev->pdev->dev, PAGE_SIZE, buf->frags[i].buf,
+				  buf->frags[i].map);
+	kfree(buf->frags);
+err_out:
+	return -ENOMEM;
+}
+
+void mlx5_frag_buf_free(struct mlx5_core_dev *dev, struct mlx5_frag_buf *buf)
+{
+	int size = buf->size;
+	int i;
+
+	for (i = 0; i < buf->npages; i++) {
+		int frag_sz = min_t(int, size, PAGE_SIZE);
+
+		dma_free_coherent(&dev->pdev->dev, frag_sz, buf->frags[i].buf,
+				  buf->frags[i].map);
+		size -= frag_sz;
+	}
+	kfree(buf->frags);
+}
+
 static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev,
 						 int node)
 {
@@ -230,3 +287,12 @@ void mlx5_fill_page_array(struct mlx5_bu
 	}
 }
 EXPORT_SYMBOL_GPL(mlx5_fill_page_array);
+
+void mlx5_fill_page_frag_array(struct mlx5_frag_buf *buf, __be64 *pas)
+{
+	int i;
+
+	for (i = 0; i < buf->npages; i++)
+		pas[i] = cpu_to_be64(buf->frags[i].map);
+}
+EXPORT_SYMBOL_GPL(mlx5_fill_page_frag_array);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -54,14 +54,6 @@ enum {
 };
 
 enum {
-	NUM_LONG_LISTS	  = 2,
-	NUM_MED_LISTS	  = 64,
-	LONG_LIST_SIZE	  = (2ULL * 1024 * 1024 * 1024 / PAGE_SIZE) * 8 + 16 +
-				MLX5_CMD_DATA_BLOCK_SIZE,
-	MED_LIST_SIZE	  = 16 + MLX5_CMD_DATA_BLOCK_SIZE,
-};
-
-enum {
 	MLX5_CMD_DELIVERY_STAT_OK			= 0x0,
 	MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR		= 0x1,
 	MLX5_CMD_DELIVERY_STAT_TOK_ERR			= 0x2,
@@ -313,6 +305,8 @@ static int mlx5_internal_err_ret_value(s
 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
 	case MLX5_CMD_OP_SET_FLOW_TABLE_ROOT:
 	case MLX5_CMD_OP_DEALLOC_ENCAP_HEADER:
+	case MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT:
+	case MLX5_CMD_OP_DESTROY_QOS_PARA_VPORT:
 		return MLX5_CMD_STAT_OK;
 
 	case MLX5_CMD_OP_QUERY_HCA_CAP:
@@ -414,11 +408,14 @@ static int mlx5_internal_err_ret_value(s
 	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
 	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
-
 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
 	case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
+	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
+	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
+	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
+	case MLX5_CMD_OP_CREATE_QOS_PARA_VPORT:
 		*status = MLX5_DRIVER_STATUS_ABORTED;
 		*synd = MLX5_DRIVER_SYND;
 		return -EIO;
@@ -575,6 +572,12 @@ const char *mlx5_command_str(int command
 	MLX5_COMMAND_STR_CASE(MODIFY_FLOW_TABLE);
 	MLX5_COMMAND_STR_CASE(ALLOC_ENCAP_HEADER);
 	MLX5_COMMAND_STR_CASE(DEALLOC_ENCAP_HEADER);
+	MLX5_COMMAND_STR_CASE(CREATE_SCHEDULING_ELEMENT);
+	MLX5_COMMAND_STR_CASE(DESTROY_SCHEDULING_ELEMENT);
+	MLX5_COMMAND_STR_CASE(QUERY_SCHEDULING_ELEMENT);
+	MLX5_COMMAND_STR_CASE(MODIFY_SCHEDULING_ELEMENT);
+	MLX5_COMMAND_STR_CASE(CREATE_QOS_PARA_VPORT);
+	MLX5_COMMAND_STR_CASE(DESTROY_QOS_PARA_VPORT);
 	default: return "unknown command opcode";
 	}
 }
@@ -1058,14 +1061,13 @@ static struct mlx5_cmd_mailbox *alloc_cm
 	if (!mailbox)
 		return ERR_PTR(-ENOMEM);
 
-	mailbox->buf = pci_pool_alloc(dev->cmd.pool, flags,
-				      &mailbox->dma);
+	mailbox->buf = pci_pool_zalloc(dev->cmd.pool, flags,
+				       &mailbox->dma);
 	if (!mailbox->buf) {
 		mlx5_core_dbg(dev, "failed allocation\n");
 		kfree(mailbox);
 		return ERR_PTR(-ENOMEM);
 	}
-	memset(mailbox->buf, 0, sizeof(struct mlx5_cmd_prot_block));
 	mailbox->next = NULL;
 
 	return mailbox;
@@ -1356,10 +1358,10 @@ static void free_msg(struct mlx5_core_de
 {
 	unsigned long flags;
 
-	if (msg->cache) {
-		spin_lock_irqsave(&msg->cache->lock, flags);
-		list_add_tail(&msg->list, &msg->cache->head);
-		spin_unlock_irqrestore(&msg->cache->lock, flags);
+	if (msg->parent) {
+		spin_lock_irqsave(&msg->parent->lock, flags);
+		list_add_tail(&msg->list, &msg->parent->head);
+		spin_unlock_irqrestore(&msg->parent->lock, flags);
 	} else {
 		mlx5_free_cmd_msg(dev, msg);
 	}
@@ -1456,30 +1458,37 @@ static struct mlx5_cmd_msg *alloc_msg(st
 				      gfp_t gfp)
 {
 	struct mlx5_cmd_msg *msg = ERR_PTR(-ENOMEM);
+	struct cmd_msg_cache *ch = NULL;
 	struct mlx5_cmd *cmd = &dev->cmd;
-	struct cache_ent *ent = NULL;
+	int i;
 
-	if (in_size > MED_LIST_SIZE && in_size <= LONG_LIST_SIZE)
-		ent = &cmd->cache.large;
-	else if (in_size > 16 && in_size <= MED_LIST_SIZE)
-		ent = &cmd->cache.med;
+	if (in_size <= 16)
+		goto cache_miss;
 
-	if (ent) {
-		spin_lock_irq(&ent->lock);
-		if (!list_empty(&ent->head)) {
-			msg = list_entry(ent->head.next, typeof(*msg), list);
-			/* For cached lists, we must explicitly state what is
-			 * the real size
-			 */
-			msg->len = in_size;
-			list_del(&msg->list);
+	for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) {
+		ch = &cmd->cache[i];
+		if (in_size > ch->max_inbox_size)
+			continue;
+		spin_lock_irq(&ch->lock);
+		if (list_empty(&ch->head)) {
+			spin_unlock_irq(&ch->lock);
+			continue;
 		}
-		spin_unlock_irq(&ent->lock);
+		msg = list_entry(ch->head.next, typeof(*msg), list);
+		/* For cached lists, we must explicitly state what is
+		 * the real size
+		 */
+		msg->len = in_size;
+		list_del(&msg->list);
+		spin_unlock_irq(&ch->lock);
+		break;
 	}
 
-	if (IS_ERR(msg))
-		msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0);
+	if (!IS_ERR(msg))
+		return msg;
 
+cache_miss:
+	msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0);
 	return msg;
 }
 
@@ -1577,58 +1586,56 @@ EXPORT_SYMBOL(mlx5_cmd_exec_cb);
 
 static void destroy_msg_cache(struct mlx5_core_dev *dev)
 {
-	struct mlx5_cmd *cmd = &dev->cmd;
+	struct cmd_msg_cache *ch;
 	struct mlx5_cmd_msg *msg;
 	struct mlx5_cmd_msg *n;
+	int i;
 
-	list_for_each_entry_safe(msg, n, &cmd->cache.large.head, list) {
-		list_del(&msg->list);
-		mlx5_free_cmd_msg(dev, msg);
-	}
-
-	list_for_each_entry_safe(msg, n, &cmd->cache.med.head, list) {
-		list_del(&msg->list);
-		mlx5_free_cmd_msg(dev, msg);
+	for (i = 0; i < MLX5_NUM_COMMAND_CACHES; i++) {
+		ch = &dev->cmd.cache[i];
+		list_for_each_entry_safe(msg, n, &ch->head, list) {
+			list_del(&msg->list);
+			mlx5_free_cmd_msg(dev, msg);
+		}
 	}
 }
 
-static int create_msg_cache(struct mlx5_core_dev *dev)
+static unsigned cmd_cache_num_ent[MLX5_NUM_COMMAND_CACHES] = {
+	512, 32, 16, 8, 2
+};
+
+static unsigned cmd_cache_ent_size[MLX5_NUM_COMMAND_CACHES] = {
+	16 + MLX5_CMD_DATA_BLOCK_SIZE,
+	16 + MLX5_CMD_DATA_BLOCK_SIZE * 2,
+	16 + MLX5_CMD_DATA_BLOCK_SIZE * 16,
+	16 + MLX5_CMD_DATA_BLOCK_SIZE * 256,
+	16 + MLX5_CMD_DATA_BLOCK_SIZE * 512,
+};
+
+static void create_msg_cache(struct mlx5_core_dev *dev)
 {
 	struct mlx5_cmd *cmd = &dev->cmd;
+	struct cmd_msg_cache *ch;
 	struct mlx5_cmd_msg *msg;
-	int err;
 	int i;
+	int k;
 
-	spin_lock_init(&cmd->cache.large.lock);
-	INIT_LIST_HEAD(&cmd->cache.large.head);
-	spin_lock_init(&cmd->cache.med.lock);
-	INIT_LIST_HEAD(&cmd->cache.med.head);
-
-	for (i = 0; i < NUM_LONG_LISTS; i++) {
-		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE, 0);
-		if (IS_ERR(msg)) {
-			err = PTR_ERR(msg);
-			goto ex_err;
-		}
-		msg->cache = &cmd->cache.large;
-		list_add_tail(&msg->list, &cmd->cache.large.head);
-	}
-
-	for (i = 0; i < NUM_MED_LISTS; i++) {
-		msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE, 0);
-		if (IS_ERR(msg)) {
-			err = PTR_ERR(msg);
-			goto ex_err;
+	/* Initialize and fill the caches with initial entries */
+	for (k = 0; k < MLX5_NUM_COMMAND_CACHES; k++) {
+		ch = &cmd->cache[k];
+		spin_lock_init(&ch->lock);
+		INIT_LIST_HEAD(&ch->head);
+		ch->num_ent = cmd_cache_num_ent[k];
+		ch->max_inbox_size = cmd_cache_ent_size[k];
+		for (i = 0; i < ch->num_ent; i++) {
+			msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL | __GFP_NOWARN,
+						 ch->max_inbox_size, 0);
+			if (IS_ERR(msg))
+				break;
+			msg->parent = ch;
+			list_add_tail(&msg->list, &ch->head);
 		}
-		msg->cache = &cmd->cache.med;
-		list_add_tail(&msg->list, &cmd->cache.med.head);
 	}
-
-	return 0;
-
-ex_err:
-	destroy_msg_cache(dev);
-	return err;
 }
 
 static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
@@ -1721,7 +1728,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *
 	if (cmd->cmdif_rev > CMD_IF_REV) {
 		dev_err(&dev->pdev->dev, "driver does not support command interface version. driver %d, firmware %d\n",
 			CMD_IF_REV, cmd->cmdif_rev);
-		err = -ENOTSUPP;
+		err = -EOPNOTSUPP;
 		goto err_free_page;
 	}
 
@@ -1751,11 +1758,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *
 
 	cmd->mode = CMD_MODE_POLLING;
 
-	err = create_msg_cache(dev);
-	if (err) {
-		dev_err(&dev->pdev->dev, "failed to create command cache\n");
-		goto err_free_page;
-	}
+	create_msg_cache(dev);
 
 	set_wqname(dev);
 	cmd->wq = create_singlethread_workqueue(cmd->wq_name);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ struct arfs_tuple {
 struct arfs_rule {
 	struct mlx5e_priv	*priv;
 	struct work_struct      arfs_work;
-	struct mlx5_flow_rule   *rule;
+	struct mlx5_flow_handle *rule;
 	struct hlist_node	hlist;
 	int			rxq;
 	/* Flow ID passed to ndo_rx_flow_steer */
@@ -104,7 +104,7 @@ static int arfs_disable(struct mlx5e_pri
 		tt = arfs_get_tt(i);
 		/* Modify ttc rules destination to bypass the aRFS tables*/
 		err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
-						   &dest);
+						   &dest, NULL);
 		if (err) {
 			netdev_err(priv->netdev,
 				   "%s: modify ttc destination failed\n",
@@ -137,7 +137,7 @@ int mlx5e_arfs_enable(struct mlx5e_priv
 		tt = arfs_get_tt(i);
 		/* Modify ttc rules destination to point on the aRFS FTs */
 		err = mlx5_modify_rule_destination(priv->fs.ttc.rules[tt],
-						   &dest);
+						   &dest, NULL);
 		if (err) {
 			netdev_err(priv->netdev,
 				   "%s: modify ttc destination failed err=%d\n",
@@ -151,7 +151,7 @@ int mlx5e_arfs_enable(struct mlx5e_priv
 
 static void arfs_destroy_table(struct arfs_table *arfs_t)
 {
-	mlx5_del_flow_rule(arfs_t->default_rule);
+	mlx5_del_flow_rules(arfs_t->default_rule);
 	mlx5e_destroy_flow_table(&arfs_t->ft);
 }
 
@@ -174,6 +174,11 @@ static int arfs_add_default_rule(struct
 				 enum arfs_type type)
 {
 	struct arfs_table *arfs_t = &priv->fs.arfs.arfs_tables[type];
+	struct mlx5_flow_act flow_act = {
+		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+		.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+		.encap_id = 0,
+	};
 	struct mlx5_flow_destination dest;
 	struct mlx5e_tir *tir = priv->indir_tir;
 	struct mlx5_flow_spec *spec;
@@ -205,10 +210,9 @@ static int arfs_add_default_rule(struct
 		goto out;
 	}
 
-	arfs_t->default_rule = mlx5_add_flow_rule(arfs_t->ft.t, spec,
-						  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-						  MLX5_FS_DEFAULT_FLOW_TAG,
-						  &dest);
+	arfs_t->default_rule = mlx5_add_flow_rules(arfs_t->ft.t, spec,
+						   &flow_act,
+						   &dest, 1);
 	if (IS_ERR(arfs_t->default_rule)) {
 		err = PTR_ERR(arfs_t->default_rule);
 		arfs_t->default_rule = NULL;
@@ -324,7 +328,7 @@ static int arfs_create_table(struct mlx5
 	int err;
 
 	ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
-				       MLX5E_ARFS_TABLE_SIZE, MLX5E_ARFS_FT_LEVEL);
+				       MLX5E_ARFS_TABLE_SIZE, MLX5E_ARFS_FT_LEVEL, 0);
 	if (IS_ERR(ft->t)) {
 		err = PTR_ERR(ft->t);
 		ft->t = NULL;
@@ -396,7 +400,7 @@ static void arfs_may_expire_flow(struct
 	spin_unlock_bh(&priv->fs.arfs.arfs_lock);
 	hlist_for_each_entry_safe(arfs_rule, htmp, &del_list, hlist) {
 		if (arfs_rule->rule)
-			mlx5_del_flow_rule(arfs_rule->rule);
+			mlx5_del_flow_rules(arfs_rule->rule);
 		hlist_del(&arfs_rule->hlist);
 		kfree(arfs_rule);
 	}
@@ -420,7 +424,7 @@ static void arfs_del_rules(struct mlx5e_
 	hlist_for_each_entry_safe(rule, htmp, &del_list, hlist) {
 		cancel_work_sync(&rule->arfs_work);
 		if (rule->rule)
-			mlx5_del_flow_rule(rule->rule);
+			mlx5_del_flow_rules(rule->rule);
 		hlist_del(&rule->hlist);
 		kfree(rule);
 	}
@@ -462,12 +466,17 @@ static struct arfs_table *arfs_get_table
 	return NULL;
 }
 
-static struct mlx5_flow_rule *arfs_add_rule(struct mlx5e_priv *priv,
-					    struct arfs_rule *arfs_rule)
+static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
+					      struct arfs_rule *arfs_rule)
 {
+	struct mlx5_flow_act flow_act = {
+		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+		.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+		.encap_id = 0,
+	};
 	struct mlx5e_arfs_tables *arfs = &priv->fs.arfs;
 	struct arfs_tuple *tuple = &arfs_rule->tuple;
-	struct mlx5_flow_rule *rule = NULL;
+	struct mlx5_flow_handle *rule = NULL;
 	struct mlx5_flow_destination dest;
 	struct arfs_table *arfs_table;
 	struct mlx5_flow_spec *spec;
@@ -544,9 +553,7 @@ static struct mlx5_flow_rule *arfs_add_r
 	}
 	dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
 	dest.tir_num = priv->direct_tir[arfs_rule->rxq].tirn;
-	rule = mlx5_add_flow_rule(ft, spec, MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				  MLX5_FS_DEFAULT_FLOW_TAG,
-				  &dest);
+	rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 	if (IS_ERR(rule)) {
 		err = PTR_ERR(rule);
 		netdev_err(priv->netdev, "%s: add rule(filter id=%d, rq idx=%d) failed, err=%d\n",
@@ -559,14 +566,14 @@ out:
 }
 
 static void arfs_modify_rule_rq(struct mlx5e_priv *priv,
-				struct mlx5_flow_rule *rule, u16 rxq)
+				struct mlx5_flow_handle *rule, u16 rxq)
 {
 	struct mlx5_flow_destination dst;
 	int err = 0;
 
 	dst.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
 	dst.tir_num = priv->direct_tir[rxq].tirn;
-	err =  mlx5_modify_rule_destination(rule, &dst);
+	err =  mlx5_modify_rule_destination(rule, &dst, NULL);
 	if (err)
 		netdev_warn(priv->netdev,
 			    "Failed to modfiy aRFS rule destination to rq=%d\n", rxq);
@@ -578,7 +585,7 @@ static void arfs_handle_work(struct work
 						   struct arfs_rule,
 						   arfs_work);
 	struct mlx5e_priv *priv = arfs_rule->priv;
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *rule;
 
 	mutex_lock(&priv->state_lock);
 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c	2017-02-12 16:03:20.000000000 -0500
@@ -49,7 +49,7 @@ void mlx5e_fill_hwstamp(struct mlx5e_tst
 	hwts->hwtstamp = ns_to_ktime(nsec);
 }
 
-static cycle_t mlx5e_read_internal_timer(const struct cyclecounter *cc)
+static u64 mlx5e_read_internal_timer(const struct cyclecounter *cc)
 {
 	struct mlx5e_tstamp *tstamp = container_of(cc, struct mlx5e_tstamp,
 						   cycles);
@@ -94,7 +94,7 @@ int mlx5e_hwstamp_set(struct net_device
 	switch (config.rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
 		/* Reset CQE compression to Admin default */
-		mlx5e_modify_rx_cqe_compression(priv, priv->params.rx_cqe_compress_admin);
+		mlx5e_modify_rx_cqe_compression(priv, priv->params.rx_cqe_compress_def);
 		break;
 	case HWTSTAMP_FILTER_ALL:
 	case HWTSTAMP_FILTER_SOME:
@@ -111,6 +111,7 @@ int mlx5e_hwstamp_set(struct net_device
 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
 		/* Disable CQE compression */
+		netdev_warn(dev, "Disabling cqe compression");
 		mlx5e_modify_rx_cqe_compression(priv, false);
 		config.rx_filter = HWTSTAMP_FILTER_ALL;
 		break;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_common.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_common.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_common.c	2017-02-12 16:03:20.000000000 -0500
@@ -137,7 +137,8 @@ void mlx5e_destroy_mdev_resources(struct
 	mlx5_unmap_free_uar(mdev, &res->cq_uar);
 }
 
-int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev)
+int mlx5e_refresh_tirs_self_loopback(struct mlx5_core_dev *mdev,
+				     bool enable_uc_lb)
 {
 	struct mlx5e_tir *tir;
 	void *in;
@@ -149,6 +150,10 @@ int mlx5e_refresh_tirs_self_loopback_ena
 	if (!in)
 		return -ENOMEM;
 
+	if (enable_uc_lb)
+		MLX5_SET(modify_tir_in, in, ctx.self_lb_block,
+			 MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST_);
+
 	MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);
 
 	list_for_each_entry(tir, &mdev->mlx5e_res.td.tirs_list, list) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c	2017-02-12 16:03:20.000000000 -0500
@@ -38,16 +38,77 @@
 #define MLX5E_100MB (100000)
 #define MLX5E_1GB   (1000000)
 
+#define MLX5E_CEE_STATE_UP    1
+#define MLX5E_CEE_STATE_DOWN  0
+
+/* If dcbx mode is non-host set the dcbx mode to host.
+ */
+static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
+				     enum mlx5_dcbx_oper_mode mode)
+{
+	struct mlx5_core_dev *mdev = priv->mdev;
+	u32 param[MLX5_ST_SZ_DW(dcbx_param)];
+	int err;
+
+	err = mlx5_query_port_dcbx_param(mdev, param);
+	if (err)
+		return err;
+
+	MLX5_SET(dcbx_param, param, version_admin, mode);
+	if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
+		MLX5_SET(dcbx_param, param, willing_admin, 1);
+
+	return mlx5_set_port_dcbx_param(mdev, param);
+}
+
+static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv)
+{
+	struct mlx5e_dcbx *dcbx = &priv->dcbx;
+	int err;
+
+	if (!MLX5_CAP_GEN(priv->mdev, dcbx))
+		return 0;
+
+	if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
+		return 0;
+
+	err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST);
+	if (err)
+		return err;
+
+	dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
+	return 0;
+}
+
 static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
 				   struct ieee_ets *ets)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+	int err = 0;
+	int i;
 
 	if (!MLX5_CAP_GEN(priv->mdev, ets))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
-	memcpy(ets, &priv->params.ets, sizeof(*ets));
-	return 0;
+	ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
+	for (i = 0; i < ets->ets_cap; i++) {
+		err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
+		if (err)
+			return err;
+	}
+
+	for (i = 0; i < ets->ets_cap; i++) {
+		err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
+		if (err)
+			return err;
+		if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
+			priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
+	}
+
+	memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
+
+	return err;
 }
 
 enum {
@@ -110,9 +171,6 @@ int mlx5e_dcbnl_ieee_setets_core(struct
 	int max_tc = mlx5_max_tc(mdev);
 	int err;
 
-	if (!MLX5_CAP_GEN(mdev, ets))
-		return -ENOTSUPP;
-
 	mlx5e_build_tc_group(ets, tc_group, max_tc);
 	mlx5e_build_tc_tx_bw(ets, tc_tx_bw, tc_group, max_tc);
 
@@ -124,7 +182,14 @@ int mlx5e_dcbnl_ieee_setets_core(struct
 	if (err)
 		return err;
 
-	return mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
+	err = mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
+
+	if (err)
+		return err;
+
+	memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
+
+	return err;
 }
 
 static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
@@ -170,6 +235,9 @@ static int mlx5e_dcbnl_ieee_setets(struc
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 	int err;
 
+	if (!MLX5_CAP_GEN(priv->mdev, ets))
+		return -EOPNOTSUPP;
+
 	err = mlx5e_dbcnl_validate_ets(netdev, ets);
 	if (err)
 		return err;
@@ -178,9 +246,6 @@ static int mlx5e_dcbnl_ieee_setets(struc
 	if (err)
 		return err;
 
-	memcpy(&priv->params.ets, ets, sizeof(*ets));
-	priv->params.ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
-
 	return 0;
 }
 
@@ -222,13 +287,39 @@ static int mlx5e_dcbnl_ieee_setpfc(struc
 
 static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
 {
-	return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
+	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct mlx5e_dcbx *dcbx = &priv->dcbx;
+	u8 mode = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_VER_CEE;
+
+	if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
+		mode |= DCB_CAP_DCBX_HOST;
+
+	return mode;
 }
 
 static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
 {
+	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct mlx5e_dcbx *dcbx = &priv->dcbx;
+
+	if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
+		if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
+			return 0;
+
+		/* set dcbx to fw controlled */
+		if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
+			dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
+			return 0;
+		}
+
+		return 1;
+	}
+
+	if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
+		return 1;
+
 	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
-	    (mode & DCB_CAP_DCBX_VER_CEE) ||
+	    !(mode & DCB_CAP_DCBX_VER_CEE) ||
 	    !(mode & DCB_CAP_DCBX_VER_IEEE) ||
 	    !(mode & DCB_CAP_DCBX_HOST))
 		return 1;
@@ -304,6 +395,289 @@ static int mlx5e_dcbnl_ieee_setmaxrate(s
 	return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
 }
 
+static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+	struct mlx5_core_dev *mdev = priv->mdev;
+	struct ieee_ets ets;
+	struct ieee_pfc pfc;
+	int err = -EOPNOTSUPP;
+	int i;
+
+	if (!MLX5_CAP_GEN(mdev, ets))
+		goto out;
+
+	memset(&ets, 0, sizeof(ets));
+	memset(&pfc, 0, sizeof(pfc));
+
+	ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
+	for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
+		ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i];
+		ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
+		ets.tc_tsa[i]   = IEEE_8021QAZ_TSA_ETS;
+		ets.prio_tc[i]  = cee_cfg->prio_to_pg_map[i];
+	}
+
+	err = mlx5e_dbcnl_validate_ets(netdev, &ets);
+	if (err) {
+		netdev_err(netdev,
+			   "%s, Failed to validate ETS: %d\n", __func__, err);
+		goto out;
+	}
+
+	err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+	if (err) {
+		netdev_err(netdev,
+			   "%s, Failed to set ETS: %d\n", __func__, err);
+		goto out;
+	}
+
+	/* Set PFC */
+	pfc.pfc_cap = mlx5_max_tc(mdev) + 1;
+	if (!cee_cfg->pfc_enable)
+		pfc.pfc_en = 0;
+	else
+		for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
+			pfc.pfc_en |= cee_cfg->pfc_setting[i] << i;
+
+	err = mlx5e_dcbnl_ieee_setpfc(netdev, &pfc);
+	if (err) {
+		netdev_err(netdev,
+			   "%s, Failed to set PFC: %d\n", __func__, err);
+		goto out;
+	}
+out:
+	return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
+}
+
+static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
+{
+	return MLX5E_CEE_STATE_UP;
+}
+
+static void mlx5e_dcbnl_getpermhwaddr(struct net_device *netdev,
+				      u8 *perm_addr)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+
+	if (!perm_addr)
+		return;
+
+	mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr);
+}
+
+static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev,
+				     int priority, u8 prio_type,
+				     u8 pgid, u8 bw_pct, u8 up_map)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+	if (priority >= CEE_DCBX_MAX_PRIO) {
+		netdev_err(netdev,
+			   "%s, priority is out of range\n", __func__);
+		return;
+	}
+
+	if (pgid >= CEE_DCBX_MAX_PGS) {
+		netdev_err(netdev,
+			   "%s, priority group is out of range\n", __func__);
+		return;
+	}
+
+	cee_cfg->prio_to_pg_map[priority] = pgid;
+}
+
+static void mlx5e_dcbnl_setpgbwgcfgtx(struct net_device *netdev,
+				      int pgid, u8 bw_pct)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+	if (pgid >= CEE_DCBX_MAX_PGS) {
+		netdev_err(netdev,
+			   "%s, priority group is out of range\n", __func__);
+		return;
+	}
+
+	cee_cfg->pg_bw_pct[pgid] = bw_pct;
+}
+
+static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
+				     int priority, u8 *prio_type,
+				     u8 *pgid, u8 *bw_pct, u8 *up_map)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+
+	if (!MLX5_CAP_GEN(priv->mdev, ets)) {
+		netdev_err(netdev, "%s, ets is not supported\n", __func__);
+		return;
+	}
+
+	if (priority >= CEE_DCBX_MAX_PRIO) {
+		netdev_err(netdev,
+			   "%s, priority is out of range\n", __func__);
+		return;
+	}
+
+	*prio_type = 0;
+	*bw_pct = 0;
+	*up_map = 0;
+
+	if (mlx5_query_port_prio_tc(mdev, priority, pgid))
+		*pgid = 0;
+}
+
+static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
+				      int pgid, u8 *bw_pct)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+
+	if (pgid >= CEE_DCBX_MAX_PGS) {
+		netdev_err(netdev,
+			   "%s, priority group is out of range\n", __func__);
+		return;
+	}
+
+	if (mlx5_query_port_tc_bw_alloc(mdev, pgid, bw_pct))
+		*bw_pct = 0;
+}
+
+static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
+				  int priority, u8 setting)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+	if (priority >= CEE_DCBX_MAX_PRIO) {
+		netdev_err(netdev,
+			   "%s, priority is out of range\n", __func__);
+		return;
+	}
+
+	if (setting > 1)
+		return;
+
+	cee_cfg->pfc_setting[priority] = setting;
+}
+
+static int
+mlx5e_dcbnl_get_priority_pfc(struct net_device *netdev,
+			     int priority, u8 *setting)
+{
+	struct ieee_pfc pfc;
+	int err;
+
+	err = mlx5e_dcbnl_ieee_getpfc(netdev, &pfc);
+
+	if (err)
+		*setting = 0;
+	else
+		*setting = (pfc.pfc_en >> priority) & 0x01;
+
+	return err;
+}
+
+static void mlx5e_dcbnl_getpfccfg(struct net_device *netdev,
+				  int priority, u8 *setting)
+{
+	if (priority >= CEE_DCBX_MAX_PRIO) {
+		netdev_err(netdev,
+			   "%s, priority is out of range\n", __func__);
+		return;
+	}
+
+	if (!setting)
+		return;
+
+	mlx5e_dcbnl_get_priority_pfc(netdev, priority, setting);
+}
+
+static u8 mlx5e_dcbnl_getcap(struct net_device *netdev,
+			     int capid, u8 *cap)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+	u8 rval = 0;
+
+	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 = 1 << mlx5_max_tc(mdev);
+		break;
+	case DCB_CAP_ATTR_PFC_TCS:
+		*cap = 1 << mlx5_max_tc(mdev);
+		break;
+	case DCB_CAP_ATTR_GSP:
+		*cap = false;
+		break;
+	case DCB_CAP_ATTR_BCN:
+		*cap = false;
+		break;
+	case DCB_CAP_ATTR_DCBX:
+		*cap = (DCB_CAP_DCBX_LLD_MANAGED |
+			DCB_CAP_DCBX_VER_CEE |
+			DCB_CAP_DCBX_STATIC);
+		break;
+	default:
+		*cap = 0;
+		rval = 1;
+		break;
+	}
+
+	return rval;
+}
+
+static int mlx5e_dcbnl_getnumtcs(struct net_device *netdev,
+				 int tcs_id, u8 *num)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+
+	switch (tcs_id) {
+	case DCB_NUMTCS_ATTR_PG:
+	case DCB_NUMTCS_ATTR_PFC:
+		*num = mlx5_max_tc(mdev) + 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static u8 mlx5e_dcbnl_getpfcstate(struct net_device *netdev)
+{
+	struct ieee_pfc pfc;
+
+	if (mlx5e_dcbnl_ieee_getpfc(netdev, &pfc))
+		return MLX5E_CEE_STATE_DOWN;
+
+	return pfc.pfc_en ? MLX5E_CEE_STATE_UP : MLX5E_CEE_STATE_DOWN;
+}
+
+static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+	if ((state != MLX5E_CEE_STATE_UP) && (state != MLX5E_CEE_STATE_DOWN))
+		return;
+
+	cee_cfg->pfc_enable = state;
+}
+
 const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
 	.ieee_getets	= mlx5e_dcbnl_ieee_getets,
 	.ieee_setets	= mlx5e_dcbnl_ieee_setets,
@@ -313,4 +687,73 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_
 	.ieee_setpfc	= mlx5e_dcbnl_ieee_setpfc,
 	.getdcbx	= mlx5e_dcbnl_getdcbx,
 	.setdcbx	= mlx5e_dcbnl_setdcbx,
+
+/* CEE interfaces */
+	.setall         = mlx5e_dcbnl_setall,
+	.getstate       = mlx5e_dcbnl_getstate,
+	.getpermhwaddr  = mlx5e_dcbnl_getpermhwaddr,
+
+	.setpgtccfgtx   = mlx5e_dcbnl_setpgtccfgtx,
+	.setpgbwgcfgtx  = mlx5e_dcbnl_setpgbwgcfgtx,
+	.getpgtccfgtx   = mlx5e_dcbnl_getpgtccfgtx,
+	.getpgbwgcfgtx  = mlx5e_dcbnl_getpgbwgcfgtx,
+
+	.setpfccfg      = mlx5e_dcbnl_setpfccfg,
+	.getpfccfg      = mlx5e_dcbnl_getpfccfg,
+	.getcap         = mlx5e_dcbnl_getcap,
+	.getnumtcs      = mlx5e_dcbnl_getnumtcs,
+	.getpfcstate    = mlx5e_dcbnl_getpfcstate,
+	.setpfcstate    = mlx5e_dcbnl_setpfcstate,
 };
+
+static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
+					enum mlx5_dcbx_oper_mode *mode)
+{
+	u32 out[MLX5_ST_SZ_DW(dcbx_param)];
+
+	*mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
+
+	if (!mlx5_query_port_dcbx_param(priv->mdev, out))
+		*mode = MLX5_GET(dcbx_param, out, version_oper);
+
+	/* From driver's point of view, we only care if the mode
+	 * is host (HOST) or non-host (AUTO)
+	 */
+	if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
+		*mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
+}
+
+static void mlx5e_ets_init(struct mlx5e_priv *priv)
+{
+	int i;
+	struct ieee_ets ets;
+
+	if (!MLX5_CAP_GEN(priv->mdev, ets))
+		return;
+
+	memset(&ets, 0, sizeof(ets));
+	ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
+	for (i = 0; i < ets.ets_cap; i++) {
+		ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
+		ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
+		ets.prio_tc[i] = i;
+	}
+
+	memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa));
+
+	/* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
+	ets.prio_tc[0] = 1;
+	ets.prio_tc[1] = 0;
+
+	mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+}
+
+void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
+{
+	struct mlx5e_dcbx *dcbx = &priv->dcbx;
+
+	if (MLX5_CAP_GEN(priv->mdev, dcbx))
+		mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
+
+	mlx5e_ets_init(priv);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -173,9 +173,14 @@ static int mlx5e_get_sset_count(struct n
 		       NUM_VPORT_COUNTERS + NUM_PPORT_COUNTERS +
 		       MLX5E_NUM_RQ_STATS(priv) +
 		       MLX5E_NUM_SQ_STATS(priv) +
-		       MLX5E_NUM_PFC_COUNTERS(priv);
+		       MLX5E_NUM_PFC_COUNTERS(priv) +
+		       ARRAY_SIZE(mlx5e_pme_status_desc) +
+		       ARRAY_SIZE(mlx5e_pme_error_desc);
+
 	case ETH_SS_PRIV_FLAGS:
 		return ARRAY_SIZE(mlx5e_priv_flags);
+	case ETH_SS_TEST:
+		return mlx5e_self_test_num(priv);
 	/* fallthrough */
 	default:
 		return -EOPNOTSUPP;
@@ -237,6 +242,13 @@ static void mlx5e_fill_stats_strings(str
 		}
 	}
 
+	/* port module event counters */
+	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_status_desc); i++)
+		strcpy(data + (idx++) * ETH_GSTRING_LEN, mlx5e_pme_status_desc[i].format);
+
+	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_error_desc); i++)
+		strcpy(data + (idx++) * ETH_GSTRING_LEN, mlx5e_pme_error_desc[i].format);
+
 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
 		return;
 
@@ -267,6 +279,9 @@ static void mlx5e_get_strings(struct net
 		break;
 
 	case ETH_SS_TEST:
+		for (i = 0; i < mlx5e_self_test_num(priv); i++)
+			strcpy(data + i * ETH_GSTRING_LEN,
+			       mlx5e_self_tests[i]);
 		break;
 
 	case ETH_SS_STATS:
@@ -279,6 +294,7 @@ static void mlx5e_get_ethtool_stats(stru
 				    struct ethtool_stats *stats, u64 *data)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct mlx5_priv *mlx5_priv;
 	int i, j, tc, prio, idx = 0;
 	unsigned long pfc_combined;
 
@@ -335,6 +351,16 @@ static void mlx5e_get_ethtool_stats(stru
 		}
 	}
 
+	/* port module event counters */
+	mlx5_priv =  &priv->mdev->priv;
+	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_status_desc); i++)
+		data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.status_counters,
+						   mlx5e_pme_status_desc, i);
+
+	for (i = 0; i < ARRAY_SIZE(mlx5e_pme_error_desc); i++)
+		data[idx++] = MLX5E_READ_CTR64_CPU(mlx5_priv->pme_stats.error_counters,
+						   mlx5e_pme_error_desc, i);
+
 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
 		return;
 
@@ -456,8 +482,7 @@ static int mlx5e_set_ringparam(struct ne
 		return -EINVAL;
 	}
 
-	num_mtts = MLX5E_REQUIRED_MTTS(priv->params.num_channels,
-				       rx_pending_wqes);
+	num_mtts = MLX5E_REQUIRED_MTTS(rx_pending_wqes);
 	if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ &&
 	    !MLX5E_VALID_NUM_MTTS(num_mtts)) {
 		netdev_info(dev, "%s: rx_pending (%d) request can't be satisfied, try to reduce.\n",
@@ -518,11 +543,9 @@ static int mlx5e_set_channels(struct net
 			      struct ethtool_channels *ch)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
-	int ncv = mlx5e_get_max_num_channels(priv->mdev);
 	unsigned int count = ch->combined_count;
 	bool arfs_enabled;
 	bool was_opened;
-	u32 num_mtts;
 	int err = 0;
 
 	if (!count) {
@@ -530,24 +553,6 @@ static int mlx5e_set_channels(struct net
 			    __func__);
 		return -EINVAL;
 	}
-	if (ch->rx_count || ch->tx_count) {
-		netdev_info(dev, "%s: separate rx/tx count not supported\n",
-			    __func__);
-		return -EINVAL;
-	}
-	if (count > ncv) {
-		netdev_info(dev, "%s: count (%d) > max (%d)\n",
-			    __func__, count, ncv);
-		return -EINVAL;
-	}
-
-	num_mtts = MLX5E_REQUIRED_MTTS(count, BIT(priv->params.log_rq_size));
-	if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ &&
-	    !MLX5E_VALID_NUM_MTTS(num_mtts)) {
-		netdev_info(dev, "%s: rx count (%d) request can't be satisfied, try to reduce.\n",
-			    __func__, count);
-		return -EINVAL;
-	}
 
 	if (priv->params.num_channels == count)
 		return 0;
@@ -590,7 +595,7 @@ static int mlx5e_get_coalesce(struct net
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
 	if (!MLX5_CAP_GEN(priv->mdev, cq_moderation))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	coal->rx_coalesce_usecs       = priv->params.rx_cq_moderation.usec;
 	coal->rx_max_coalesced_frames = priv->params.rx_cq_moderation.pkts;
@@ -615,7 +620,7 @@ static int mlx5e_set_coalesce(struct net
 	int i;
 
 	if (!MLX5_CAP_GEN(mdev, cq_moderation))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	mutex_lock(&priv->state_lock);
 
@@ -975,15 +980,18 @@ static int mlx5e_get_rxfh(struct net_dev
 
 static void mlx5e_modify_tirs_hash(struct mlx5e_priv *priv, void *in, int inlen)
 {
-	struct mlx5_core_dev *mdev = priv->mdev;
 	void *tirc = MLX5_ADDR_OF(modify_tir_in, in, ctx);
-	int i;
+	struct mlx5_core_dev *mdev = priv->mdev;
+	int ctxlen = MLX5_ST_SZ_BYTES(tirc);
+	int tt;
 
 	MLX5_SET(modify_tir_in, in, bitmask.hash, 1);
-	mlx5e_build_tir_ctx_hash(tirc, priv);
 
-	for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
-		mlx5_core_modify_tir(mdev, priv->indir_tir[i].tirn, in, inlen);
+	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
+		memset(tirc, 0, ctxlen);
+		mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
+		mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
+	}
 }
 
 static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
@@ -991,6 +999,7 @@ static int mlx5e_set_rxfh(struct net_dev
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
 	int inlen = MLX5_ST_SZ_BYTES(modify_tir_in);
+	bool hash_changed = false;
 	void *in;
 
 	if ((hfunc != ETH_RSS_HASH_NO_CHANGE) &&
@@ -1012,14 +1021,21 @@ static int mlx5e_set_rxfh(struct net_dev
 		mlx5e_redirect_rqt(priv, rqtn, MLX5E_INDIR_RQT_SIZE, 0);
 	}
 
-	if (key)
+	if (hfunc != ETH_RSS_HASH_NO_CHANGE &&
+	    hfunc != priv->params.rss_hfunc) {
+		priv->params.rss_hfunc = hfunc;
+		hash_changed = true;
+	}
+
+	if (key) {
 		memcpy(priv->params.toeplitz_hash_key, key,
 		       sizeof(priv->params.toeplitz_hash_key));
+		hash_changed = hash_changed ||
+			       priv->params.rss_hfunc == ETH_RSS_HASH_TOP;
+	}
 
-	if (hfunc != ETH_RSS_HASH_NO_CHANGE)
-		priv->params.rss_hfunc = hfunc;
-
-	mlx5e_modify_tirs_hash(priv, in, inlen);
+	if (hash_changed)
+		mlx5e_modify_tirs_hash(priv, in, inlen);
 
 	mutex_unlock(&priv->state_lock);
 
@@ -1291,7 +1307,7 @@ static int mlx5e_set_wol(struct net_devi
 	u32 mlx5_wol_mode;
 
 	if (!wol_supported)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	if (wol->wolopts & ~wol_supported)
 		return -EINVAL;
@@ -1421,7 +1437,7 @@ static int set_pflag_rx_cqe_based_moder(
 
 	if (rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE &&
 	    !MLX5_CAP_GEN(mdev, cq_period_start_from_cqe))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	if (!rx_mode_changed)
 		return 0;
@@ -1438,6 +1454,35 @@ static int set_pflag_rx_cqe_based_moder(
 	return err;
 }
 
+static int set_pflag_rx_cqe_compress(struct net_device *netdev,
+				     bool enable)
+{
+	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+	int err = 0;
+	bool reset;
+
+	if (!MLX5_CAP_GEN(mdev, cqe_compression))
+		return -EOPNOTSUPP;
+
+	if (enable && priv->tstamp.hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) {
+		netdev_err(netdev, "Can't enable cqe compression while timestamping is enabled.\n");
+		return -EINVAL;
+	}
+
+	reset = test_bit(MLX5E_STATE_OPENED, &priv->state);
+
+	if (reset)
+		mlx5e_close_locked(netdev);
+
+	MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, enable);
+	priv->params.rx_cqe_compress_def = enable;
+
+	if (reset)
+		err = mlx5e_open_locked(netdev);
+	return err;
+}
+
 static int mlx5e_handle_pflag(struct net_device *netdev,
 			      u32 wanted_flags,
 			      enum mlx5e_priv_flag flag,
@@ -1445,7 +1490,7 @@ static int mlx5e_handle_pflag(struct net
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 	bool enable = !!(wanted_flags & flag);
-	u32 changes = wanted_flags ^ priv->pflags;
+	u32 changes = wanted_flags ^ priv->params.pflags;
 	int err;
 
 	if (!(changes & flag))
@@ -1458,7 +1503,7 @@ static int mlx5e_handle_pflag(struct net
 		return err;
 	}
 
-	MLX5E_SET_PRIV_FLAG(priv, flag, enable);
+	MLX5E_SET_PFLAG(priv, flag, enable);
 	return 0;
 }
 
@@ -1468,20 +1513,26 @@ static int mlx5e_set_priv_flags(struct n
 	int err;
 
 	mutex_lock(&priv->state_lock);
-
 	err = mlx5e_handle_pflag(netdev, pflags,
 				 MLX5E_PFLAG_RX_CQE_BASED_MODER,
 				 set_pflag_rx_cqe_based_moder);
+	if (err)
+		goto out;
+
+	err = mlx5e_handle_pflag(netdev, pflags,
+				 MLX5E_PFLAG_RX_CQE_COMPRESS,
+				 set_pflag_rx_cqe_compress);
 
+out:
 	mutex_unlock(&priv->state_lock);
-	return err ? -EINVAL : 0;
+	return err;
 }
 
 static u32 mlx5e_get_priv_flags(struct net_device *netdev)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
-	return priv->pflags;
+	return priv->params.pflags;
 }
 
 static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
@@ -1535,5 +1586,6 @@ const struct ethtool_ops mlx5e_ethtool_o
 	.get_module_info   = mlx5e_get_module_info,
 	.get_module_eeprom = mlx5e_get_module_eeprom,
 	.get_priv_flags    = mlx5e_get_priv_flags,
-	.set_priv_flags    = mlx5e_set_priv_flags
+	.set_priv_flags    = mlx5e_set_priv_flags,
+	.self_test         = mlx5e_self_test,
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c	2017-02-12 16:03:20.000000000 -0500
@@ -158,9 +158,14 @@ static int __mlx5e_add_vlan_rule(struct
 				 enum mlx5e_vlan_rule_type rule_type,
 				 u16 vid, struct mlx5_flow_spec *spec)
 {
+	struct mlx5_flow_act flow_act = {
+		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+		.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+		.encap_id = 0,
+	};
 	struct mlx5_flow_table *ft = priv->fs.vlan.ft.t;
 	struct mlx5_flow_destination dest;
-	struct mlx5_flow_rule **rule_p;
+	struct mlx5_flow_handle **rule_p;
 	int err = 0;
 
 	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
@@ -187,10 +192,7 @@ static int __mlx5e_add_vlan_rule(struct
 		break;
 	}
 
-	*rule_p = mlx5_add_flow_rule(ft, spec,
-				     MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				     MLX5_FS_DEFAULT_FLOW_TAG,
-				     &dest);
+	*rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 
 	if (IS_ERR(*rule_p)) {
 		err = PTR_ERR(*rule_p);
@@ -229,20 +231,20 @@ static void mlx5e_del_vlan_rule(struct m
 	switch (rule_type) {
 	case MLX5E_VLAN_RULE_TYPE_UNTAGGED:
 		if (priv->fs.vlan.untagged_rule) {
-			mlx5_del_flow_rule(priv->fs.vlan.untagged_rule);
+			mlx5_del_flow_rules(priv->fs.vlan.untagged_rule);
 			priv->fs.vlan.untagged_rule = NULL;
 		}
 		break;
 	case MLX5E_VLAN_RULE_TYPE_ANY_VID:
 		if (priv->fs.vlan.any_vlan_rule) {
-			mlx5_del_flow_rule(priv->fs.vlan.any_vlan_rule);
+			mlx5_del_flow_rules(priv->fs.vlan.any_vlan_rule);
 			priv->fs.vlan.any_vlan_rule = NULL;
 		}
 		break;
 	case MLX5E_VLAN_RULE_TYPE_MATCH_VID:
 		mlx5e_vport_context_update_vlans(priv);
 		if (priv->fs.vlan.active_vlans_rule[vid]) {
-			mlx5_del_flow_rule(priv->fs.vlan.active_vlans_rule[vid]);
+			mlx5_del_flow_rules(priv->fs.vlan.active_vlans_rule[vid]);
 			priv->fs.vlan.active_vlans_rule[vid] = NULL;
 		}
 		mlx5e_vport_context_update_vlans(priv);
@@ -560,7 +562,7 @@ static void mlx5e_cleanup_ttc_rules(stru
 
 	for (i = 0; i < MLX5E_NUM_TT; i++) {
 		if (!IS_ERR_OR_NULL(ttc->rules[i])) {
-			mlx5_del_flow_rule(ttc->rules[i]);
+			mlx5_del_flow_rules(ttc->rules[i]);
 			ttc->rules[i] = NULL;
 		}
 	}
@@ -616,13 +618,19 @@ static struct {
 	},
 };
 
-static struct mlx5_flow_rule *mlx5e_generate_ttc_rule(struct mlx5e_priv *priv,
-						      struct mlx5_flow_table *ft,
-						      struct mlx5_flow_destination *dest,
-						      u16 etype,
-						      u8 proto)
+static struct mlx5_flow_handle *
+mlx5e_generate_ttc_rule(struct mlx5e_priv *priv,
+			struct mlx5_flow_table *ft,
+			struct mlx5_flow_destination *dest,
+			u16 etype,
+			u8 proto)
 {
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_act flow_act = {
+		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+		.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+		.encap_id = 0,
+	};
+	struct mlx5_flow_handle *rule;
 	struct mlx5_flow_spec *spec;
 	int err = 0;
 
@@ -643,10 +651,7 @@ static struct mlx5_flow_rule *mlx5e_gene
 		MLX5_SET(fte_match_param, spec->match_value, outer_headers.ethertype, etype);
 	}
 
-	rule = mlx5_add_flow_rule(ft, spec,
-				  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				  MLX5_FS_DEFAULT_FLOW_TAG,
-				  dest);
+	rule = mlx5_add_flow_rules(ft, spec, &flow_act, dest, 1);
 	if (IS_ERR(rule)) {
 		err = PTR_ERR(rule);
 		netdev_err(priv->netdev, "%s: add rule failed\n", __func__);
@@ -660,7 +665,7 @@ static int mlx5e_generate_ttc_table_rule
 {
 	struct mlx5_flow_destination dest;
 	struct mlx5e_ttc_table *ttc;
-	struct mlx5_flow_rule **rules;
+	struct mlx5_flow_handle **rules;
 	struct mlx5_flow_table *ft;
 	int tt;
 	int err;
@@ -776,7 +781,7 @@ static int mlx5e_create_ttc_table(struct
 	int err;
 
 	ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
-				       MLX5E_TTC_TABLE_SIZE, MLX5E_TTC_FT_LEVEL);
+				       MLX5E_TTC_TABLE_SIZE, MLX5E_TTC_FT_LEVEL, 0);
 	if (IS_ERR(ft->t)) {
 		err = PTR_ERR(ft->t);
 		ft->t = NULL;
@@ -801,7 +806,7 @@ static void mlx5e_del_l2_flow_rule(struc
 				   struct mlx5e_l2_rule *ai)
 {
 	if (!IS_ERR_OR_NULL(ai->rule)) {
-		mlx5_del_flow_rule(ai->rule);
+		mlx5_del_flow_rules(ai->rule);
 		ai->rule = NULL;
 	}
 }
@@ -809,6 +814,11 @@ static void mlx5e_del_l2_flow_rule(struc
 static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
 				  struct mlx5e_l2_rule *ai, int type)
 {
+	struct mlx5_flow_act flow_act = {
+		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
+		.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG,
+		.encap_id = 0,
+	};
 	struct mlx5_flow_table *ft = priv->fs.l2.ft.t;
 	struct mlx5_flow_destination dest;
 	struct mlx5_flow_spec *spec;
@@ -847,9 +857,7 @@ static int mlx5e_add_l2_flow_rule(struct
 		break;
 	}
 
-	ai->rule = mlx5_add_flow_rule(ft, spec,
-				      MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				      MLX5_FS_DEFAULT_FLOW_TAG, &dest);
+	ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 	if (IS_ERR(ai->rule)) {
 		netdev_err(priv->netdev, "%s: add l2 rule(mac:%pM) failed\n",
 			   __func__, mv_dmac);
@@ -947,7 +955,7 @@ static int mlx5e_create_l2_table(struct
 
 	ft->num_groups = 0;
 	ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
-				       MLX5E_L2_TABLE_SIZE, MLX5E_L2_FT_LEVEL);
+				       MLX5E_L2_TABLE_SIZE, MLX5E_L2_FT_LEVEL, 0);
 
 	if (IS_ERR(ft->t)) {
 		err = PTR_ERR(ft->t);
@@ -1037,7 +1045,7 @@ static int mlx5e_create_vlan_table(struc
 
 	ft->num_groups = 0;
 	ft->t = mlx5_create_flow_table(priv->fs.ns, MLX5E_NIC_PRIO,
-				       MLX5E_VLAN_TABLE_SIZE, MLX5E_VLAN_FT_LEVEL);
+				       MLX5E_VLAN_TABLE_SIZE, MLX5E_VLAN_FT_LEVEL, 0);
 
 	if (IS_ERR(ft->t)) {
 		err = PTR_ERR(ft->t);
@@ -1081,7 +1089,7 @@ int mlx5e_create_flow_steering(struct ml
 					       MLX5_FLOW_NAMESPACE_KERNEL);
 
 	if (!priv->fs.ns)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	err = mlx5e_arfs_create_tables(priv);
 	if (err) {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,7 +36,7 @@
 struct mlx5e_ethtool_rule {
 	struct list_head             list;
 	struct ethtool_rx_flow_spec  flow_spec;
-	struct mlx5_flow_rule        *rule;
+	struct mlx5_flow_handle	     *rule;
 	struct mlx5e_ethtool_table   *eth_ft;
 };
 
@@ -92,14 +92,14 @@ static struct mlx5e_ethtool_table *get_f
 	ns = mlx5_get_flow_namespace(priv->mdev,
 				     MLX5_FLOW_NAMESPACE_ETHTOOL);
 	if (!ns)
-		return ERR_PTR(-ENOTSUPP);
+		return ERR_PTR(-EOPNOTSUPP);
 
 	table_size = min_t(u32, BIT(MLX5_CAP_FLOWTABLE(priv->mdev,
 						       flow_table_properties_nic_receive.log_max_ft_size)),
 			   MLX5E_ETHTOOL_NUM_ENTRIES);
 	ft = mlx5_create_auto_grouped_flow_table(ns, prio,
 						 table_size,
-						 MLX5E_ETHTOOL_NUM_GROUPS, 0);
+						 MLX5E_ETHTOOL_NUM_GROUPS, 0, 0);
 	if (IS_ERR(ft))
 		return (void *)ft;
 
@@ -247,6 +247,7 @@ static int set_flow_attrs(u32 *match_c,
 	}
 	if (fs->flow_type & FLOW_MAC_EXT &&
 	    !is_zero_ether_addr(fs->m_ext.h_dest)) {
+		mask_spec(fs->m_ext.h_dest, fs->h_ext.h_dest, ETH_ALEN);
 		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4,
 					     outer_headers_c, dmac_47_16),
 				fs->m_ext.h_dest);
@@ -284,15 +285,16 @@ static bool outer_header_zero(u32 *match
 						  size - 1);
 }
 
-static struct mlx5_flow_rule *add_ethtool_flow_rule(struct mlx5e_priv *priv,
-						    struct mlx5_flow_table *ft,
-						    struct ethtool_rx_flow_spec *fs)
+static struct mlx5_flow_handle *
+add_ethtool_flow_rule(struct mlx5e_priv *priv,
+		      struct mlx5_flow_table *ft,
+		      struct ethtool_rx_flow_spec *fs)
 {
 	struct mlx5_flow_destination *dst = NULL;
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_spec *spec;
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *rule;
 	int err = 0;
-	u32 action;
 
 	spec = mlx5_vzalloc(sizeof(*spec));
 	if (!spec)
@@ -303,7 +305,7 @@ static struct mlx5_flow_rule *add_ethtoo
 		goto free;
 
 	if (fs->ring_cookie == RX_CLS_FLOW_DISC) {
-		action = MLX5_FLOW_CONTEXT_ACTION_DROP;
+		flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
 	} else {
 		dst = kzalloc(sizeof(*dst), GFP_KERNEL);
 		if (!dst) {
@@ -313,12 +315,12 @@ static struct mlx5_flow_rule *add_ethtoo
 
 		dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
 		dst->tir_num = priv->direct_tir[fs->ring_cookie].tirn;
-		action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+		flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 	}
 
 	spec->match_criteria_enable = (!outer_header_zero(spec->match_criteria));
-	rule = mlx5_add_flow_rule(ft, spec, action,
-				  MLX5_FS_DEFAULT_FLOW_TAG, dst);
+	flow_act.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
+	rule = mlx5_add_flow_rules(ft, spec, &flow_act, dst, 1);
 	if (IS_ERR(rule)) {
 		err = PTR_ERR(rule);
 		netdev_err(priv->netdev, "%s: failed to add ethtool steering rule: %d\n",
@@ -335,7 +337,7 @@ static void del_ethtool_rule(struct mlx5
 			     struct mlx5e_ethtool_rule *eth_rule)
 {
 	if (eth_rule->rule)
-		mlx5_del_flow_rule(eth_rule->rule);
+		mlx5_del_flow_rules(eth_rule->rule);
 	list_del(&eth_rule->list);
 	priv->fs.ethtool.tot_num_rules--;
 	put_flow_table(eth_rule->eth_ft);
@@ -475,7 +477,7 @@ int mlx5e_ethtool_flow_replace(struct ml
 {
 	struct mlx5e_ethtool_table *eth_ft;
 	struct mlx5e_ethtool_rule *eth_rule;
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *rule;
 	int num_tuples;
 	int err;
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en.h	2017-02-12 16:03:20.000000000 -0500
@@ -77,9 +77,9 @@
 						 MLX5_MPWRQ_WQE_PAGE_ORDER)
 
 #define MLX5_MTT_OCTW(npages) (ALIGN(npages, 8) / 2)
-#define MLX5E_REQUIRED_MTTS(rqs, wqes)\
-	(rqs * wqes * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8))
-#define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) <= U16_MAX)
+#define MLX5E_REQUIRED_MTTS(wqes)		\
+	(wqes * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8))
+#define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) - 1 <= U16_MAX)
 
 #define MLX5_UMR_ALIGN				(2048)
 #define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD	(128)
@@ -150,12 +150,6 @@ static inline int mlx5_max_log_rq_size(i
 	}
 }
 
-enum {
-	MLX5E_INLINE_MODE_L2,
-	MLX5E_INLINE_MODE_VPORT_CONTEXT,
-	MLX5_INLINE_MODE_NOT_REQUIRED,
-};
-
 struct mlx5e_tx_wqe {
 	struct mlx5_wqe_ctrl_seg ctrl;
 	struct mlx5_wqe_eth_seg  eth;
@@ -173,22 +167,28 @@ struct mlx5e_umr_wqe {
 	struct mlx5_wqe_data_seg       data;
 };
 
+extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
+
 static const char mlx5e_priv_flags[][ETH_GSTRING_LEN] = {
 	"rx_cqe_moder",
+	"rx_cqe_compress",
 };
 
 enum mlx5e_priv_flag {
 	MLX5E_PFLAG_RX_CQE_BASED_MODER = (1 << 0),
+	MLX5E_PFLAG_RX_CQE_COMPRESS = (1 << 1),
 };
 
-#define MLX5E_SET_PRIV_FLAG(priv, pflag, enable)    \
-	do {                                        \
-		if (enable)                         \
-			priv->pflags |= pflag;      \
-		else                                \
-			priv->pflags &= ~pflag;     \
+#define MLX5E_SET_PFLAG(priv, pflag, enable)			\
+	do {							\
+		if (enable)					\
+			(priv)->params.pflags |= (pflag);	\
+		else						\
+			(priv)->params.pflags &= ~(pflag);	\
 	} while (0)
 
+#define MLX5E_GET_PFLAG(priv, pflag) (!!((priv)->params.pflags & (pflag)))
+
 #ifdef CONFIG_MLX5_CORE_EN_DCB
 #define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */
 #endif
@@ -207,8 +207,7 @@ struct mlx5e_params {
 	u16 num_channels;
 	u8  num_tc;
 	u8  rx_cq_period_mode;
-	bool rx_cqe_compress_admin;
-	bool rx_cqe_compress;
+	bool rx_cqe_compress_def;
 	struct mlx5e_cq_moder rx_cq_moderation;
 	struct mlx5e_cq_moder tx_cq_moderation;
 	u16 min_rx_wqes;
@@ -220,13 +219,35 @@ struct mlx5e_params {
 	u8  toeplitz_hash_key[40];
 	u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
 	bool vlan_strip_disable;
-#ifdef CONFIG_MLX5_CORE_EN_DCB
-	struct ieee_ets ets;
-#endif
 	bool rx_am_enabled;
 	u32 lro_timeout;
+	u32 pflags;
 };
 
+#ifdef CONFIG_MLX5_CORE_EN_DCB
+struct mlx5e_cee_config {
+	/* bw pct for priority group */
+	u8                         pg_bw_pct[CEE_DCBX_MAX_PGS];
+	u8                         prio_to_pg_map[CEE_DCBX_MAX_PRIO];
+	bool                       pfc_setting[CEE_DCBX_MAX_PRIO];
+	bool                       pfc_enable;
+};
+
+enum {
+	MLX5_DCB_CHG_RESET,
+	MLX5_DCB_NO_CHG,
+	MLX5_DCB_CHG_NO_RESET,
+};
+
+struct mlx5e_dcbx {
+	enum mlx5_dcbx_oper_mode   mode;
+	struct mlx5e_cee_config    cee_cfg; /* pending configuration */
+
+	/* The only setting that cannot be read from FW */
+	u8                         tc_tsa[IEEE_8021QAZ_MAX_TCS];
+};
+#endif
+
 struct mlx5e_tstamp {
 	rwlock_t                   lock;
 	struct cyclecounter        cycles;
@@ -265,7 +286,7 @@ struct mlx5e_cq {
 	u16                        decmprs_wqe_counter;
 
 	/* control */
-	struct mlx5_wq_ctrl        wq_ctrl;
+	struct mlx5_frag_wq_ctrl   wq_ctrl;
 } ____cacheline_aligned_in_smp;
 
 struct mlx5e_rq;
@@ -326,7 +347,6 @@ struct mlx5e_rq {
 		struct {
 			struct mlx5e_mpw_info *info;
 			void                  *mtt_no_align;
-			u32                    mtt_offset;
 		} mpwqe;
 	};
 	struct {
@@ -361,6 +381,7 @@ struct mlx5e_rq {
 	u32                    rqn;
 	struct mlx5e_channel  *channel;
 	struct mlx5e_priv     *priv;
+	struct mlx5_core_mkey  umr_mkey;
 } ____cacheline_aligned_in_smp;
 
 struct mlx5e_umr_dma_info {
@@ -524,7 +545,7 @@ struct mlx5e_vxlan_db {
 
 struct mlx5e_l2_rule {
 	u8  addr[ETH_ALEN + 2];
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *rule;
 };
 
 struct mlx5e_flow_table {
@@ -545,10 +566,10 @@ struct mlx5e_tc_table {
 struct mlx5e_vlan_table {
 	struct mlx5e_flow_table		ft;
 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
-	struct mlx5_flow_rule	*active_vlans_rule[VLAN_N_VID];
-	struct mlx5_flow_rule	*untagged_rule;
-	struct mlx5_flow_rule	*any_vlan_rule;
-	bool          filter_disabled;
+	struct mlx5_flow_handle	*active_vlans_rule[VLAN_N_VID];
+	struct mlx5_flow_handle	*untagged_rule;
+	struct mlx5_flow_handle	*any_vlan_rule;
+	bool		filter_disabled;
 };
 
 struct mlx5e_l2_table {
@@ -566,14 +587,14 @@ struct mlx5e_l2_table {
 /* L3/L4 traffic type classifier */
 struct mlx5e_ttc_table {
 	struct mlx5e_flow_table  ft;
-	struct mlx5_flow_rule	 *rules[MLX5E_NUM_TT];
+	struct mlx5_flow_handle	 *rules[MLX5E_NUM_TT];
 };
 
 #define ARFS_HASH_SHIFT BITS_PER_BYTE
 #define ARFS_HASH_SIZE BIT(BITS_PER_BYTE)
 struct arfs_table {
 	struct mlx5e_flow_table  ft;
-	struct mlx5_flow_rule    *default_rule;
+	struct mlx5_flow_handle	 *default_rule;
 	struct hlist_head	 rules_hash[ARFS_HASH_SIZE];
 };
 
@@ -668,7 +689,6 @@ struct mlx5e_priv {
 
 	unsigned long              state;
 	struct mutex               state_lock; /* Protects Interface state */
-	struct mlx5_core_mkey      umr_mkey;
 	struct mlx5e_rq            drop_rq;
 
 	struct mlx5e_channel     **channel;
@@ -688,12 +708,15 @@ struct mlx5e_priv {
 	struct work_struct         tx_timeout_work;
 	struct delayed_work        update_stats_work;
 
-	u32                        pflags;
 	struct mlx5_core_dev      *mdev;
 	struct net_device         *netdev;
 	struct mlx5e_stats         stats;
 	struct mlx5e_tstamp        tstamp;
 	u16 q_counter;
+#ifdef CONFIG_MLX5_CORE_EN_DCB
+	struct mlx5e_dcbx          dcbx;
+#endif
+
 	const struct mlx5e_profile *profile;
 	void                      *ppriv;
 };
@@ -735,6 +758,9 @@ int mlx5e_create_flow_steering(struct ml
 void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
 void mlx5e_init_l2_addr(struct mlx5e_priv *priv);
 void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);
+int mlx5e_self_test_num(struct mlx5e_priv *priv);
+void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
+		     u64 *buf);
 int mlx5e_ethtool_get_flow(struct mlx5e_priv *priv, struct ethtool_rxnfc *info,
 			   int location);
 int mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv,
@@ -765,7 +791,8 @@ void mlx5e_disable_vlan_filter(struct ml
 int mlx5e_modify_rqs_vsd(struct mlx5e_priv *priv, bool vsd);
 
 int mlx5e_redirect_rqt(struct mlx5e_priv *priv, u32 rqtn, int sz, int ix);
-void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv);
+void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
+				    enum mlx5e_traffic_types tt);
 
 int mlx5e_open_locked(struct net_device *netdev);
 int mlx5e_close_locked(struct net_device *netdev);
@@ -811,8 +838,7 @@ static inline void mlx5e_cq_arm(struct m
 
 static inline u32 mlx5e_get_wqe_mtt_offset(struct mlx5e_rq *rq, u16 wqe_ix)
 {
-	return rq->mpwqe.mtt_offset +
-		wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8);
+	return wqe_ix * ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8);
 }
 
 static inline int mlx5e_get_max_num_channels(struct mlx5_core_dev *mdev)
@@ -825,6 +851,7 @@ extern const struct ethtool_ops mlx5e_et
 #ifdef CONFIG_MLX5_CORE_EN_DCB
 extern const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops;
 int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets);
+void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv);
 #endif
 
 #ifndef CONFIG_RFS_ACCEL
@@ -837,12 +864,12 @@ static inline void mlx5e_arfs_destroy_ta
 
 static inline int mlx5e_arfs_enable(struct mlx5e_priv *priv)
 {
-	return -ENOTSUPP;
+	return -EOPNOTSUPP;
 }
 
 static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv)
 {
-	return -ENOTSUPP;
+	return -EOPNOTSUPP;
 }
 #else
 int mlx5e_arfs_create_tables(struct mlx5e_priv *priv);
@@ -860,7 +887,8 @@ void mlx5e_destroy_tir(struct mlx5_core_
 		       struct mlx5e_tir *tir);
 int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev);
 void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev);
-int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev);
+int mlx5e_refresh_tirs_self_loopback(struct mlx5_core_dev *mdev,
+				     bool enable_uc_lb);
 
 struct mlx5_eswitch_rep;
 int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
@@ -874,6 +902,7 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e
 void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv);
 int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr);
 void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
+void mlx5e_update_hw_rep_counters(struct mlx5e_priv *priv);
 
 int mlx5e_create_direct_rqts(struct mlx5e_priv *priv);
 void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt);
@@ -890,8 +919,16 @@ struct net_device *mlx5e_create_netdev(s
 void mlx5e_destroy_netdev(struct mlx5_core_dev *mdev, struct mlx5e_priv *priv);
 int mlx5e_attach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
 void mlx5e_detach_netdev(struct mlx5_core_dev *mdev, struct net_device *netdev);
-struct rtnl_link_stats64 *
-mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
 u32 mlx5e_choose_lro_timeout(struct mlx5_core_dev *mdev, u32 wanted_timeout);
+void mlx5e_add_vxlan_port(struct net_device *netdev,
+			  struct udp_tunnel_info *ti);
+void mlx5e_del_vxlan_port(struct net_device *netdev,
+			  struct udp_tunnel_info *ti);
 
+int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
+			    void *sp);
+bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id);
+
+bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv);
+bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv);
 #endif /* __MLX5_EN_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_main.c	2017-02-12 16:03:20.000000000 -0500
@@ -84,7 +84,8 @@ static void mlx5e_set_rq_type_params(str
 	switch (priv->params.rq_wq_type) {
 	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
 		priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW;
-		priv->params.mpwqe_log_stride_sz = priv->params.rx_cqe_compress ?
+		priv->params.mpwqe_log_stride_sz =
+			MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS) ?
 			MLX5_MPWRQ_LOG_STRIDE_SIZE_CQE_COMPRESS :
 			MLX5_MPWRQ_LOG_STRIDE_SIZE;
 		priv->params.mpwqe_log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ -
@@ -101,7 +102,7 @@ static void mlx5e_set_rq_type_params(str
 		       priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ,
 		       BIT(priv->params.log_rq_size),
 		       BIT(priv->params.mpwqe_log_stride_sz),
-		       priv->params.rx_cqe_compress_admin);
+		       MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS));
 }
 
 static void mlx5e_set_rq_priv_params(struct mlx5e_priv *priv)
@@ -446,14 +447,50 @@ static void mlx5e_rq_free_mpwqe_info(str
 	kfree(rq->mpwqe.info);
 }
 
-static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
+static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv,
+				 u64 npages, u8 page_shift,
+				 struct mlx5_core_mkey *umr_mkey)
 {
-	struct mlx5_eswitch_rep *rep = (struct mlx5_eswitch_rep *)priv->ppriv;
+	struct mlx5_core_dev *mdev = priv->mdev;
+	int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
+	void *mkc;
+	u32 *in;
+	int err;
 
-	if (rep && rep->vport != FDB_UPLINK_VPORT)
-		return true;
+	if (!MLX5E_VALID_NUM_MTTS(npages))
+		return -EINVAL;
 
-	return false;
+	in = mlx5_vzalloc(inlen);
+	if (!in)
+		return -ENOMEM;
+
+	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
+
+	MLX5_SET(mkc, mkc, free, 1);
+	MLX5_SET(mkc, mkc, umr_en, 1);
+	MLX5_SET(mkc, mkc, lw, 1);
+	MLX5_SET(mkc, mkc, lr, 1);
+	MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
+
+	MLX5_SET(mkc, mkc, qpn, 0xffffff);
+	MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
+	MLX5_SET64(mkc, mkc, len, npages << page_shift);
+	MLX5_SET(mkc, mkc, translations_octword_size,
+		 MLX5_MTT_OCTW(npages));
+	MLX5_SET(mkc, mkc, log_page_size, page_shift);
+
+	err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
+
+	kvfree(in);
+	return err;
+}
+
+static int mlx5e_create_rq_umr_mkey(struct mlx5e_rq *rq)
+{
+	struct mlx5e_priv *priv = rq->priv;
+	u64 num_mtts = MLX5E_REQUIRED_MTTS(BIT(priv->params.log_rq_size));
+
+	return mlx5e_create_umr_mkey(priv, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
 }
 
 static int mlx5e_create_rq(struct mlx5e_channel *c,
@@ -489,7 +526,13 @@ static int mlx5e_create_rq(struct mlx5e_
 	rq->channel = c;
 	rq->ix      = c->ix;
 	rq->priv    = c->priv;
-	rq->xdp_prog = priv->xdp_prog;
+
+	rq->xdp_prog = priv->xdp_prog ? bpf_prog_inc(priv->xdp_prog) : NULL;
+	if (IS_ERR(rq->xdp_prog)) {
+		err = PTR_ERR(rq->xdp_prog);
+		rq->xdp_prog = NULL;
+		goto err_rq_wq_destroy;
+	}
 
 	rq->buff.map_dir = DMA_FROM_DEVICE;
 	if (rq->xdp_prog)
@@ -506,18 +549,20 @@ static int mlx5e_create_rq(struct mlx5e_
 		rq->alloc_wqe = mlx5e_alloc_rx_mpwqe;
 		rq->dealloc_wqe = mlx5e_dealloc_rx_mpwqe;
 
-		rq->mpwqe.mtt_offset = c->ix *
-			MLX5E_REQUIRED_MTTS(1, BIT(priv->params.log_rq_size));
-
 		rq->mpwqe_stride_sz = BIT(priv->params.mpwqe_log_stride_sz);
 		rq->mpwqe_num_strides = BIT(priv->params.mpwqe_log_num_strides);
 
 		rq->buff.wqe_sz = rq->mpwqe_stride_sz * rq->mpwqe_num_strides;
 		byte_count = rq->buff.wqe_sz;
-		rq->mkey_be = cpu_to_be32(c->priv->umr_mkey.key);
-		err = mlx5e_rq_alloc_mpwqe_info(rq, c);
+
+		err = mlx5e_create_rq_umr_mkey(rq);
 		if (err)
 			goto err_rq_wq_destroy;
+		rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);
+
+		err = mlx5e_rq_alloc_mpwqe_info(rq, c);
+		if (err)
+			goto err_destroy_umr_mkey;
 		break;
 	default: /* MLX5_WQ_TYPE_LINKED_LIST */
 		rq->dma_info = kzalloc_node(wq_sz * sizeof(*rq->dma_info),
@@ -566,12 +611,14 @@ static int mlx5e_create_rq(struct mlx5e_
 	rq->page_cache.head = 0;
 	rq->page_cache.tail = 0;
 
-	if (rq->xdp_prog)
-		bpf_prog_add(rq->xdp_prog, 1);
-
 	return 0;
 
+err_destroy_umr_mkey:
+	mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
+
 err_rq_wq_destroy:
+	if (rq->xdp_prog)
+		bpf_prog_put(rq->xdp_prog);
 	mlx5_wq_destroy(&rq->wq_ctrl);
 
 	return err;
@@ -587,6 +634,7 @@ static void mlx5e_destroy_rq(struct mlx5
 	switch (rq->wq_type) {
 	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
 		mlx5e_rq_free_mpwqe_info(rq);
+		mlx5_core_destroy_mkey(rq->priv->mdev, &rq->umr_mkey);
 		break;
 	default: /* MLX5_WQ_TYPE_LINKED_LIST */
 		kfree(rq->dma_info);
@@ -940,7 +988,7 @@ static int mlx5e_create_sq(struct mlx5e_
 	sq->bf_buf_size = (1 << MLX5_CAP_GEN(mdev, log_bf_reg_size)) / 2;
 	sq->max_inline  = param->max_inline;
 	sq->min_inline_mode =
-		MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5E_INLINE_MODE_VPORT_CONTEXT ?
+		MLX5_CAP_ETH(mdev, wqe_inline_mode) == MLX5_CAP_INLINE_MODE_VPORT_CONTEXT ?
 		param->min_inline_mode : 0;
 
 	err = mlx5e_alloc_sq_db(sq, cpu_to_node(c->cpu));
@@ -1184,7 +1232,7 @@ static int mlx5e_create_cq(struct mlx5e_
 
 static void mlx5e_destroy_cq(struct mlx5e_cq *cq)
 {
-	mlx5_wq_destroy(&cq->wq_ctrl);
+	mlx5_cqwq_destroy(&cq->wq_ctrl);
 }
 
 static int mlx5e_enable_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
@@ -1201,7 +1249,7 @@ static int mlx5e_enable_cq(struct mlx5e_
 	int err;
 
 	inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
-		sizeof(u64) * cq->wq_ctrl.buf.npages;
+		sizeof(u64) * cq->wq_ctrl.frag_buf.npages;
 	in = mlx5_vzalloc(inlen);
 	if (!in)
 		return -ENOMEM;
@@ -1210,15 +1258,15 @@ static int mlx5e_enable_cq(struct mlx5e_
 
 	memcpy(cqc, param->cqc, sizeof(param->cqc));
 
-	mlx5_fill_page_array(&cq->wq_ctrl.buf,
-			     (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
+	mlx5_fill_page_frag_array(&cq->wq_ctrl.frag_buf,
+				  (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
 
 	mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
 
 	MLX5_SET(cqc,   cqc, cq_period_mode, param->cq_period_mode);
 	MLX5_SET(cqc,   cqc, c_eqn,         eqn);
 	MLX5_SET(cqc,   cqc, uar_page,      mcq->uar->index);
-	MLX5_SET(cqc,   cqc, log_page_size, cq->wq_ctrl.buf.page_shift -
+	MLX5_SET(cqc,   cqc, log_page_size, cq->wq_ctrl.frag_buf.page_shift -
 					    MLX5_ADAPTER_PAGE_SHIFT);
 	MLX5_SET64(cqc, cqc, dbr_addr,      cq->wq_ctrl.db.dma);
 
@@ -1536,7 +1584,6 @@ err_close_icosq_cq:
 
 err_napi_del:
 	netif_napi_del(&c->napi);
-	napi_hash_del(&c->napi);
 	kfree(c);
 
 	return err;
@@ -1557,9 +1604,6 @@ static void mlx5e_close_channel(struct m
 	mlx5e_close_cq(&c->icosq.cq);
 	netif_napi_del(&c->napi);
 
-	napi_hash_del(&c->napi);
-	synchronize_rcu();
-
 	kfree(c);
 }
 
@@ -1652,7 +1696,7 @@ static void mlx5e_build_rx_cq_param(stru
 	}
 
 	MLX5_SET(cqc, cqc, log_cq_size, log_cq_size);
-	if (priv->params.rx_cqe_compress) {
+	if (MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
 		MLX5_SET(cqc, cqc, mini_cqe_res_format, MLX5_CQE_FORMAT_CSUM);
 		MLX5_SET(cqc, cqc, cqe_comp_en, 1);
 	}
@@ -1978,8 +2022,23 @@ static void mlx5e_build_tir_ctx_lro(void
 	MLX5_SET(tirc, tirc, lro_timeout_period_usecs, priv->params.lro_timeout);
 }
 
-void mlx5e_build_tir_ctx_hash(void *tirc, struct mlx5e_priv *priv)
+void mlx5e_build_indir_tir_ctx_hash(struct mlx5e_priv *priv, void *tirc,
+				    enum mlx5e_traffic_types tt)
 {
+	void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
+
+#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+				 MLX5_HASH_FIELD_SEL_DST_IP)
+
+#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+				 MLX5_HASH_FIELD_SEL_DST_IP   |\
+				 MLX5_HASH_FIELD_SEL_L4_SPORT |\
+				 MLX5_HASH_FIELD_SEL_L4_DPORT)
+
+#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
+				 MLX5_HASH_FIELD_SEL_DST_IP   |\
+				 MLX5_HASH_FIELD_SEL_IPSEC_SPI)
+
 	MLX5_SET(tirc, tirc, rx_hash_fn,
 		 mlx5e_rx_hash_fn(priv->params.rss_hfunc));
 	if (priv->params.rss_hfunc == ETH_RSS_HASH_TOP) {
@@ -1991,6 +2050,88 @@ void mlx5e_build_tir_ctx_hash(void *tirc
 		MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
 		memcpy(rss_key, priv->params.toeplitz_hash_key, len);
 	}
+
+	switch (tt) {
+	case MLX5E_TT_IPV4_TCP:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV4);
+		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+			 MLX5_L4_PROT_TYPE_TCP);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_L4PORTS);
+		break;
+
+	case MLX5E_TT_IPV6_TCP:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV6);
+		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+			 MLX5_L4_PROT_TYPE_TCP);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_L4PORTS);
+		break;
+
+	case MLX5E_TT_IPV4_UDP:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV4);
+		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+			 MLX5_L4_PROT_TYPE_UDP);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_L4PORTS);
+		break;
+
+	case MLX5E_TT_IPV6_UDP:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV6);
+		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
+			 MLX5_L4_PROT_TYPE_UDP);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_L4PORTS);
+		break;
+
+	case MLX5E_TT_IPV4_IPSEC_AH:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV4);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_IPSEC_SPI);
+		break;
+
+	case MLX5E_TT_IPV6_IPSEC_AH:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV6);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_IPSEC_SPI);
+		break;
+
+	case MLX5E_TT_IPV4_IPSEC_ESP:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV4);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_IPSEC_SPI);
+		break;
+
+	case MLX5E_TT_IPV6_IPSEC_ESP:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV6);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP_IPSEC_SPI);
+		break;
+
+	case MLX5E_TT_IPV4:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV4);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP);
+		break;
+
+	case MLX5E_TT_IPV6:
+		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
+			 MLX5_L3_PROT_TYPE_IPV6);
+		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
+			 MLX5_HASH_IP);
+		break;
+	default:
+		WARN_ONCE(true, "%s: bad traffic type!\n", __func__);
+	}
 }
 
 static int mlx5e_modify_tirs_lro(struct mlx5e_priv *priv)
@@ -2124,7 +2265,7 @@ int mlx5e_open_locked(struct net_device
 		goto err_clear_state_opened_flag;
 	}
 
-	err = mlx5e_refresh_tirs_self_loopback_enable(priv->mdev);
+	err = mlx5e_refresh_tirs_self_loopback(priv->mdev, false);
 	if (err) {
 		netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n",
 			   __func__, err);
@@ -2360,110 +2501,13 @@ void mlx5e_cleanup_nic_tx(struct mlx5e_p
 static void mlx5e_build_indir_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
 				      enum mlx5e_traffic_types tt)
 {
-	void *hfso = MLX5_ADDR_OF(tirc, tirc, rx_hash_field_selector_outer);
-
 	MLX5_SET(tirc, tirc, transport_domain, priv->mdev->mlx5e_res.td.tdn);
 
-#define MLX5_HASH_IP            (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-				 MLX5_HASH_FIELD_SEL_DST_IP)
-
-#define MLX5_HASH_IP_L4PORTS    (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-				 MLX5_HASH_FIELD_SEL_DST_IP   |\
-				 MLX5_HASH_FIELD_SEL_L4_SPORT |\
-				 MLX5_HASH_FIELD_SEL_L4_DPORT)
-
-#define MLX5_HASH_IP_IPSEC_SPI  (MLX5_HASH_FIELD_SEL_SRC_IP   |\
-				 MLX5_HASH_FIELD_SEL_DST_IP   |\
-				 MLX5_HASH_FIELD_SEL_IPSEC_SPI)
-
 	mlx5e_build_tir_ctx_lro(tirc, priv);
 
 	MLX5_SET(tirc, tirc, disp_type, MLX5_TIRC_DISP_TYPE_INDIRECT);
 	MLX5_SET(tirc, tirc, indirect_table, priv->indir_rqt.rqtn);
-	mlx5e_build_tir_ctx_hash(tirc, priv);
-
-	switch (tt) {
-	case MLX5E_TT_IPV4_TCP:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV4);
-		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-			 MLX5_L4_PROT_TYPE_TCP);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_L4PORTS);
-		break;
-
-	case MLX5E_TT_IPV6_TCP:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV6);
-		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-			 MLX5_L4_PROT_TYPE_TCP);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_L4PORTS);
-		break;
-
-	case MLX5E_TT_IPV4_UDP:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV4);
-		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-			 MLX5_L4_PROT_TYPE_UDP);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_L4PORTS);
-		break;
-
-	case MLX5E_TT_IPV6_UDP:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV6);
-		MLX5_SET(rx_hash_field_select, hfso, l4_prot_type,
-			 MLX5_L4_PROT_TYPE_UDP);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_L4PORTS);
-		break;
-
-	case MLX5E_TT_IPV4_IPSEC_AH:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV4);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_IPSEC_SPI);
-		break;
-
-	case MLX5E_TT_IPV6_IPSEC_AH:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV6);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_IPSEC_SPI);
-		break;
-
-	case MLX5E_TT_IPV4_IPSEC_ESP:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV4);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_IPSEC_SPI);
-		break;
-
-	case MLX5E_TT_IPV6_IPSEC_ESP:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV6);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP_IPSEC_SPI);
-		break;
-
-	case MLX5E_TT_IPV4:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV4);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP);
-		break;
-
-	case MLX5E_TT_IPV6:
-		MLX5_SET(rx_hash_field_select, hfso, l3_prot_type,
-			 MLX5_L3_PROT_TYPE_IPV6);
-		MLX5_SET(rx_hash_field_select, hfso, selected_fields,
-			 MLX5_HASH_IP);
-		break;
-	default:
-		WARN_ONCE(true,
-			  "mlx5e_build_indir_tir_ctx: bad traffic type!\n");
-	}
+	mlx5e_build_indir_tir_ctx_hash(priv, tirc, tt);
 }
 
 static void mlx5e_build_direct_tir_ctx(struct mlx5e_priv *priv, u32 *tirc,
@@ -2642,7 +2686,7 @@ mqprio:
 	return mlx5e_setup_tc(dev, tc->tc);
 }
 
-struct rtnl_link_stats64 *
+static struct rtnl_link_stats64 *
 mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
@@ -2650,13 +2694,20 @@ mlx5e_get_stats(struct net_device *dev,
 	struct mlx5e_vport_stats *vstats = &priv->stats.vport;
 	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
 
-	stats->rx_packets = sstats->rx_packets;
-	stats->rx_bytes   = sstats->rx_bytes;
-	stats->tx_packets = sstats->tx_packets;
-	stats->tx_bytes   = sstats->tx_bytes;
+	if (mlx5e_is_uplink_rep(priv)) {
+		stats->rx_packets = PPORT_802_3_GET(pstats, a_frames_received_ok);
+		stats->rx_bytes   = PPORT_802_3_GET(pstats, a_octets_received_ok);
+		stats->tx_packets = PPORT_802_3_GET(pstats, a_frames_transmitted_ok);
+		stats->tx_bytes   = PPORT_802_3_GET(pstats, a_octets_transmitted_ok);
+	} else {
+		stats->rx_packets = sstats->rx_packets;
+		stats->rx_bytes   = sstats->rx_bytes;
+		stats->tx_packets = sstats->tx_packets;
+		stats->tx_bytes   = sstats->tx_bytes;
+		stats->tx_dropped = sstats->tx_queue_dropped;
+	}
 
 	stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer;
-	stats->tx_dropped = sstats->tx_queue_dropped;
 
 	stats->rx_length_errors =
 		PPORT_802_3_GET(pstats, a_in_range_length_errors) +
@@ -2853,31 +2904,13 @@ static int mlx5e_set_features(struct net
 	return err ? -EINVAL : 0;
 }
 
-#define MXL5_HW_MIN_MTU 64
-#define MXL5E_MIN_MTU (MXL5_HW_MIN_MTU + ETH_FCS_LEN)
-
 static int mlx5e_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
-	struct mlx5_core_dev *mdev = priv->mdev;
 	bool was_opened;
-	u16 max_mtu;
-	u16 min_mtu;
 	int err = 0;
 	bool reset;
 
-	mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
-
-	max_mtu = MLX5E_HW2SW_MTU(max_mtu);
-	min_mtu = MLX5E_HW2SW_MTU(MXL5E_MIN_MTU);
-
-	if (new_mtu > max_mtu || new_mtu < min_mtu) {
-		netdev_err(netdev,
-			   "%s: Bad MTU (%d), valid range is: [%d..%d]\n",
-			   __func__, new_mtu, min_mtu, max_mtu);
-		return -EINVAL;
-	}
-
 	mutex_lock(&priv->state_lock);
 
 	reset = !priv->params.lro_en &&
@@ -2947,6 +2980,20 @@ static int mlx5e_set_vf_trust(struct net
 
 	return mlx5_eswitch_set_vport_trust(mdev->priv.eswitch, vf + 1, setting);
 }
+
+static int mlx5e_set_vf_rate(struct net_device *dev, int vf, int min_tx_rate,
+			     int max_tx_rate)
+{
+	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct mlx5_core_dev *mdev = priv->mdev;
+
+	if (min_tx_rate)
+		return -EOPNOTSUPP;
+
+	return mlx5_eswitch_set_vport_rate(mdev->priv.eswitch, vf + 1,
+					   max_tx_rate);
+}
+
 static int mlx5_vport_link2ifla(u8 esw_link)
 {
 	switch (esw_link) {
@@ -3003,8 +3050,8 @@ static int mlx5e_get_vf_stats(struct net
 					    vf_stats);
 }
 
-static void mlx5e_add_vxlan_port(struct net_device *netdev,
-				 struct udp_tunnel_info *ti)
+void mlx5e_add_vxlan_port(struct net_device *netdev,
+			  struct udp_tunnel_info *ti)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
@@ -3017,8 +3064,8 @@ static void mlx5e_add_vxlan_port(struct
 	mlx5e_vxlan_queue_work(priv, ti->sa_family, be16_to_cpu(ti->port), 1);
 }
 
-static void mlx5e_del_vxlan_port(struct net_device *netdev,
-				 struct udp_tunnel_info *ti)
+void mlx5e_del_vxlan_port(struct net_device *netdev,
+			  struct udp_tunnel_info *ti)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
@@ -3112,6 +3159,11 @@ static int mlx5e_xdp_set(struct net_devi
 	bool reset, was_opened;
 	int i;
 
+	if (prog && prog->xdp_adjust_head) {
+		netdev_err(netdev, "Does not support bpf_xdp_adjust_head()\n");
+		return -EOPNOTSUPP;
+	}
+
 	mutex_lock(&priv->state_lock);
 
 	if ((netdev->features & NETIF_F_LRO) && prog) {
@@ -3126,11 +3178,21 @@ static int mlx5e_xdp_set(struct net_devi
 
 	if (was_opened && reset)
 		mlx5e_close_locked(netdev);
+	if (was_opened && !reset) {
+		/* num_channels is invariant here, so we can take the
+		 * batched reference right upfront.
+		 */
+		prog = bpf_prog_add(prog, priv->params.num_channels);
+		if (IS_ERR(prog)) {
+			err = PTR_ERR(prog);
+			goto unlock;
+		}
+	}
 
-	/* exchange programs */
+	/* exchange programs, extra prog reference we got from caller
+	 * as long as we don't fail from this point onwards.
+	 */
 	old_prog = xchg(&priv->xdp_prog, prog);
-	if (prog)
-		bpf_prog_add(prog, 1);
 	if (old_prog)
 		bpf_prog_put(old_prog);
 
@@ -3146,7 +3208,6 @@ static int mlx5e_xdp_set(struct net_devi
 	/* exchanging programs w/o reset, we update ref counts on behalf
 	 * of the channels RQs here.
 	 */
-	bpf_prog_add(prog, priv->params.num_channels);
 	for (i = 0; i < priv->params.num_channels; i++) {
 		struct mlx5e_channel *c = priv->channel[i];
 
@@ -3254,6 +3315,7 @@ static const struct net_device_ops mlx5e
 	.ndo_set_vf_vlan         = mlx5e_set_vf_vlan,
 	.ndo_set_vf_spoofchk     = mlx5e_set_vf_spoofchk,
 	.ndo_set_vf_trust        = mlx5e_set_vf_trust,
+	.ndo_set_vf_rate         = mlx5e_set_vf_rate,
 	.ndo_get_vf_config       = mlx5e_get_vf_config,
 	.ndo_set_vf_link_state   = mlx5e_set_vf_link_state,
 	.ndo_get_vf_stats        = mlx5e_get_vf_stats,
@@ -3262,12 +3324,14 @@ static const struct net_device_ops mlx5e
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller     = mlx5e_netpoll,
 #endif
+	.ndo_has_offload_stats	 = mlx5e_has_offload_stats,
+	.ndo_get_offload_stats	 = mlx5e_get_offload_stats,
 };
 
 static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev)
 {
 	if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	if (!MLX5_CAP_GEN(mdev, eth_net_offloads) ||
 	    !MLX5_CAP_GEN(mdev, nic_flow_table) ||
 	    !MLX5_CAP_ETH(mdev, csum_cap) ||
@@ -3279,7 +3343,7 @@ static int mlx5e_check_required_hca_cap(
 			       < 3) {
 		mlx5_core_warn(mdev,
 			       "Not creating net device, some required device capabilities are missing\n");
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}
 	if (!MLX5_CAP_ETH(mdev, self_lb_en_modifiable))
 		mlx5_core_warn(mdev, "Self loop back prevention is not supported\n");
@@ -3298,24 +3362,6 @@ u16 mlx5e_get_max_inline_cap(struct mlx5
 	       2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/;
 }
 
-#ifdef CONFIG_MLX5_CORE_EN_DCB
-static void mlx5e_ets_init(struct mlx5e_priv *priv)
-{
-	int i;
-
-	priv->params.ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
-	for (i = 0; i < priv->params.ets.ets_cap; i++) {
-		priv->params.ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
-		priv->params.ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
-		priv->params.ets.prio_tc[i] = i;
-	}
-
-	/* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
-	priv->params.ets.prio_tc[0] = 1;
-	priv->params.ets.prio_tc[1] = 0;
-}
-#endif
-
 void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev,
 				   u32 *indirection_rqt, int len,
 				   int num_channels)
@@ -3390,14 +3436,13 @@ static void mlx5e_query_min_inline(struc
 				   u8 *min_inline_mode)
 {
 	switch (MLX5_CAP_ETH(mdev, wqe_inline_mode)) {
-	case MLX5E_INLINE_MODE_L2:
+	case MLX5_CAP_INLINE_MODE_L2:
 		*min_inline_mode = MLX5_INLINE_MODE_L2;
 		break;
-	case MLX5E_INLINE_MODE_VPORT_CONTEXT:
-		mlx5_query_nic_vport_min_inline(mdev,
-						min_inline_mode);
+	case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
+		mlx5_query_nic_vport_min_inline(mdev, 0, min_inline_mode);
 		break;
-	case MLX5_INLINE_MODE_NOT_REQUIRED:
+	case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
 		*min_inline_mode = MLX5_INLINE_MODE_NONE;
 		break;
 	}
@@ -3439,17 +3484,16 @@ static void mlx5e_build_nic_netdev_priv(
 	priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
 
 	/* set CQE compression */
-	priv->params.rx_cqe_compress_admin = false;
+	priv->params.rx_cqe_compress_def = false;
 	if (MLX5_CAP_GEN(mdev, cqe_compression) &&
 	    MLX5_CAP_GEN(mdev, vport_group_manager)) {
 		mlx5e_get_max_linkspeed(mdev, &link_speed);
 		mlx5e_get_pci_bw(mdev, &pci_bw);
 		mlx5_core_dbg(mdev, "Max link speed = %d, PCI BW = %d\n",
 			      link_speed, pci_bw);
-		priv->params.rx_cqe_compress_admin =
+		priv->params.rx_cqe_compress_def =
 			cqe_compress_heuristic(link_speed, pci_bw);
 	}
-	priv->params.rx_cqe_compress = priv->params.rx_cqe_compress_admin;
 
 	mlx5e_set_rq_priv_params(priv);
 	if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
@@ -3480,12 +3524,9 @@ static void mlx5e_build_nic_netdev_priv(
 		SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
 	/* Initialize pflags */
-	MLX5E_SET_PRIV_FLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
-			    priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
-
-#ifdef CONFIG_MLX5_CORE_EN_DCB
-	mlx5e_ets_init(priv);
-#endif
+	MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
+			priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
+	MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, priv->params.rx_cqe_compress_def);
 
 	mutex_init(&priv->state_lock);
 
@@ -3523,7 +3564,8 @@ static void mlx5e_build_nic_netdev(struc
 	if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
 		netdev->netdev_ops = &mlx5e_netdev_ops_sriov;
 #ifdef CONFIG_MLX5_CORE_EN_DCB
-		netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
+		if (MLX5_CAP_GEN(mdev, qos))
+			netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
 #endif
 	} else {
 		netdev->netdev_ops = &mlx5e_netdev_ops_basic;
@@ -3619,43 +3661,6 @@ static void mlx5e_destroy_q_counter(stru
 	mlx5_core_dealloc_q_counter(priv->mdev, priv->q_counter);
 }
 
-static int mlx5e_create_umr_mkey(struct mlx5e_priv *priv)
-{
-	struct mlx5_core_dev *mdev = priv->mdev;
-	u64 npages = MLX5E_REQUIRED_MTTS(priv->profile->max_nch(mdev),
-					 BIT(MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW));
-	int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
-	void *mkc;
-	u32 *in;
-	int err;
-
-	in = mlx5_vzalloc(inlen);
-	if (!in)
-		return -ENOMEM;
-
-	mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
-
-	npages = min_t(u32, ALIGN(U16_MAX, 4) * 2, npages);
-
-	MLX5_SET(mkc, mkc, free, 1);
-	MLX5_SET(mkc, mkc, umr_en, 1);
-	MLX5_SET(mkc, mkc, lw, 1);
-	MLX5_SET(mkc, mkc, lr, 1);
-	MLX5_SET(mkc, mkc, access_mode, MLX5_MKC_ACCESS_MODE_MTT);
-
-	MLX5_SET(mkc, mkc, qpn, 0xffffff);
-	MLX5_SET(mkc, mkc, pd, mdev->mlx5e_res.pdn);
-	MLX5_SET64(mkc, mkc, len, npages << PAGE_SHIFT);
-	MLX5_SET(mkc, mkc, translations_octword_size,
-		 MLX5_MTT_OCTW(npages));
-	MLX5_SET(mkc, mkc, log_page_size, PAGE_SHIFT);
-
-	err = mlx5_core_create_mkey(mdev, &priv->umr_mkey, in, inlen);
-
-	kvfree(in);
-	return err;
-}
-
 static void mlx5e_nic_init(struct mlx5_core_dev *mdev,
 			   struct net_device *netdev,
 			   const struct mlx5e_profile *profile,
@@ -3670,13 +3675,10 @@ static void mlx5e_nic_init(struct mlx5_c
 
 static void mlx5e_nic_cleanup(struct mlx5e_priv *priv)
 {
-	struct mlx5_core_dev *mdev = priv->mdev;
-	struct mlx5_eswitch *esw = mdev->priv.eswitch;
-
 	mlx5e_vxlan_cleanup(priv);
 
-	if (MLX5_CAP_GEN(mdev, vport_group_manager))
-		mlx5_eswitch_unregister_vport_rep(esw, 0);
+	if (priv->xdp_prog)
+		bpf_prog_put(priv->xdp_prog);
 }
 
 static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
@@ -3759,7 +3761,7 @@ static int mlx5e_init_nic_tx(struct mlx5
 	}
 
 #ifdef CONFIG_MLX5_CORE_EN_DCB
-	mlx5e_dcbnl_ieee_setets_core(priv, &priv->params.ets);
+	mlx5e_dcbnl_initialize(priv);
 #endif
 	return 0;
 }
@@ -3773,30 +3775,40 @@ static void mlx5e_nic_enable(struct mlx5
 
 	mlx5_lag_add(mdev, netdev);
 
-	if (mlx5e_vxlan_allowed(mdev)) {
-		rtnl_lock();
-		udp_tunnel_get_rx_info(netdev);
-		rtnl_unlock();
-	}
-
 	mlx5e_enable_async_events(priv);
-	queue_work(priv->wq, &priv->set_rx_mode_work);
 
 	if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
 		mlx5_query_nic_vport_mac_address(mdev, 0, rep.hw_id);
 		rep.load = mlx5e_nic_rep_load;
 		rep.unload = mlx5e_nic_rep_unload;
 		rep.vport = FDB_UPLINK_VPORT;
-		rep.priv_data = priv;
+		rep.netdev = netdev;
 		mlx5_eswitch_register_vport_rep(esw, 0, &rep);
 	}
+
+	if (netdev->reg_state != NETREG_REGISTERED)
+		return;
+
+	/* Device already registered: sync netdev system state */
+	if (mlx5e_vxlan_allowed(mdev)) {
+		rtnl_lock();
+		udp_tunnel_get_rx_info(netdev);
+		rtnl_unlock();
+	}
+
+	queue_work(priv->wq, &priv->set_rx_mode_work);
 }
 
 static void mlx5e_nic_disable(struct mlx5e_priv *priv)
 {
+	struct mlx5_core_dev *mdev = priv->mdev;
+	struct mlx5_eswitch *esw = mdev->priv.eswitch;
+
 	queue_work(priv->wq, &priv->set_rx_mode_work);
+	if (MLX5_CAP_GEN(mdev, vport_group_manager))
+		mlx5_eswitch_unregister_vport_rep(esw, 0);
 	mlx5e_disable_async_events(priv);
-	mlx5_lag_remove(priv->mdev);
+	mlx5_lag_remove(mdev);
 }
 
 static const struct mlx5e_profile mlx5e_nic_profile = {
@@ -3852,21 +3864,16 @@ int mlx5e_attach_netdev(struct mlx5_core
 {
 	const struct mlx5e_profile *profile;
 	struct mlx5e_priv *priv;
+	u16 max_mtu;
 	int err;
 
 	priv = netdev_priv(netdev);
 	profile = priv->profile;
 	clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
 
-	err = mlx5e_create_umr_mkey(priv);
-	if (err) {
-		mlx5_core_err(mdev, "create umr mkey failed, %d\n", err);
-		goto out;
-	}
-
 	err = profile->init_tx(priv);
 	if (err)
-		goto err_destroy_umr_mkey;
+		goto out;
 
 	err = mlx5e_open_drop_rq(priv);
 	if (err) {
@@ -3882,6 +3889,11 @@ int mlx5e_attach_netdev(struct mlx5_core
 
 	mlx5e_init_l2_addr(priv);
 
+	/* MTU range: 68 - hw-specific max */
+	netdev->min_mtu = ETH_MIN_MTU;
+	mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
+	netdev->max_mtu = MLX5E_HW2SW_MTU(max_mtu);
+
 	mlx5e_set_dev_port_mtu(netdev);
 
 	if (profile->enable)
@@ -3901,9 +3913,6 @@ err_close_drop_rq:
 err_cleanup_tx:
 	profile->cleanup_tx(priv);
 
-err_destroy_umr_mkey:
-	mlx5_core_destroy_mkey(mdev, &priv->umr_mkey);
-
 out:
 	return err;
 }
@@ -3937,10 +3946,6 @@ void mlx5e_detach_netdev(struct mlx5_cor
 	const struct mlx5e_profile *profile = priv->profile;
 
 	set_bit(MLX5E_STATE_DESTROYING, &priv->state);
-	if (profile->disable)
-		profile->disable(priv);
-
-	flush_workqueue(priv->wq);
 
 	rtnl_lock();
 	if (netif_running(netdev))
@@ -3948,11 +3953,14 @@ void mlx5e_detach_netdev(struct mlx5_cor
 	netif_device_detach(netdev);
 	rtnl_unlock();
 
+	if (profile->disable)
+		profile->disable(priv);
+	flush_workqueue(priv->wq);
+
 	mlx5e_destroy_q_counter(priv);
 	profile->cleanup_rx(priv);
 	mlx5e_close_drop_rq(priv);
 	profile->cleanup_tx(priv);
-	mlx5_core_destroy_mkey(priv->mdev, &priv->umr_mkey);
 	cancel_delayed_work_sync(&priv->update_stats_work);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c	2017-02-12 16:03:20.000000000 -0500
@@ -72,7 +72,29 @@ static void mlx5e_rep_get_strings(struct
 	}
 }
 
-static void mlx5e_update_sw_rep_counters(struct mlx5e_priv *priv)
+static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
+{
+	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+	struct mlx5_eswitch_rep *rep = priv->ppriv;
+	struct rtnl_link_stats64 *vport_stats;
+	struct ifla_vf_stats vf_stats;
+	int err;
+
+	err = mlx5_eswitch_get_vport_stats(esw, rep->vport, &vf_stats);
+	if (err) {
+		pr_warn("vport %d error %d reading stats\n", rep->vport, err);
+		return;
+	}
+
+	vport_stats = &priv->stats.vf_vport;
+	/* flip tx/rx as we are reporting the counters for the switch vport */
+	vport_stats->rx_packets = vf_stats.tx_packets;
+	vport_stats->rx_bytes   = vf_stats.tx_bytes;
+	vport_stats->tx_packets = vf_stats.rx_packets;
+	vport_stats->tx_bytes   = vf_stats.rx_bytes;
+}
+
+static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
 {
 	struct mlx5e_sw_stats *s = &priv->stats.sw;
 	struct mlx5e_rq_stats *rq_stats;
@@ -95,6 +117,12 @@ static void mlx5e_update_sw_rep_counters
 	}
 }
 
+static void mlx5e_rep_update_stats(struct mlx5e_priv *priv)
+{
+	mlx5e_rep_update_sw_counters(priv);
+	mlx5e_rep_update_hw_counters(priv);
+}
+
 static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
 					struct ethtool_stats *stats, u64 *data)
 {
@@ -106,7 +134,7 @@ static void mlx5e_rep_get_ethtool_stats(
 
 	mutex_lock(&priv->state_lock);
 	if (test_bit(MLX5E_STATE_OPENED, &priv->state))
-		mlx5e_update_sw_rep_counters(priv);
+		mlx5e_rep_update_sw_counters(priv);
 	mutex_unlock(&priv->state_lock);
 
 	for (i = 0; i < NUM_VPORT_REP_COUNTERS; i++)
@@ -180,7 +208,8 @@ int mlx5e_add_sqs_fwd_rules(struct mlx5e
 
 int mlx5e_nic_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
 {
-	struct mlx5e_priv *priv = rep->priv_data;
+	struct net_device *netdev = rep->netdev;
+	struct mlx5e_priv *priv = netdev_priv(netdev);
 
 	if (test_bit(MLX5E_STATE_OPENED, &priv->state))
 		return mlx5e_add_sqs_fwd_rules(priv);
@@ -198,7 +227,8 @@ void mlx5e_remove_sqs_fwd_rules(struct m
 void mlx5e_nic_rep_unload(struct mlx5_eswitch *esw,
 			  struct mlx5_eswitch_rep *rep)
 {
-	struct mlx5e_priv *priv = rep->priv_data;
+	struct net_device *netdev = rep->netdev;
+	struct mlx5e_priv *priv = netdev_priv(netdev);
 
 	if (test_bit(MLX5E_STATE_OPENED, &priv->state))
 		mlx5e_remove_sqs_fwd_rules(priv);
@@ -208,6 +238,35 @@ void mlx5e_nic_rep_unload(struct mlx5_es
 	mlx5e_tc_init(priv);
 }
 
+static int mlx5e_rep_open(struct net_device *dev)
+{
+	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct mlx5_eswitch_rep *rep = priv->ppriv;
+	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+	int err;
+
+	err = mlx5e_open(dev);
+	if (err)
+		return err;
+
+	err = mlx5_eswitch_set_vport_state(esw, rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_UP);
+	if (!err)
+		netif_carrier_on(dev);
+
+	return 0;
+}
+
+static int mlx5e_rep_close(struct net_device *dev)
+{
+	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct mlx5_eswitch_rep *rep = priv->ppriv;
+	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+	(void)mlx5_eswitch_set_vport_state(esw, rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
+
+	return mlx5e_close(dev);
+}
+
 static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
 					char *buf, size_t len)
 {
@@ -230,6 +289,14 @@ static int mlx5e_rep_ndo_setup_tc(struct
 	if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
 		return -EOPNOTSUPP;
 
+	if (tc->egress_dev) {
+		struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+		struct net_device *uplink_dev = mlx5_eswitch_get_uplink_netdev(esw);
+
+		return uplink_dev->netdev_ops->ndo_setup_tc(uplink_dev, handle,
+							    proto, tc);
+	}
+
 	switch (tc->type) {
 	case TC_SETUP_CLSFLOWER:
 		switch (tc->cls_flower->command) {
@@ -245,17 +312,92 @@ static int mlx5e_rep_ndo_setup_tc(struct
 	}
 }
 
+bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
+{
+	struct mlx5_eswitch_rep *rep = (struct mlx5_eswitch_rep *)priv->ppriv;
+	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+
+	if (rep && rep->vport == FDB_UPLINK_VPORT && esw->mode == SRIOV_OFFLOADS)
+		return true;
+
+	return false;
+}
+
+bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
+{
+	struct mlx5_eswitch_rep *rep = (struct mlx5_eswitch_rep *)priv->ppriv;
+
+	if (rep && rep->vport != FDB_UPLINK_VPORT)
+		return true;
+
+	return false;
+}
+
+bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
+{
+	struct mlx5e_priv *priv = netdev_priv(dev);
+
+	switch (attr_id) {
+	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+		if (mlx5e_is_vf_vport_rep(priv) || mlx5e_is_uplink_rep(priv))
+			return true;
+	}
+
+	return false;
+}
+
+static int
+mlx5e_get_sw_stats64(const struct net_device *dev,
+		     struct rtnl_link_stats64 *stats)
+{
+	struct mlx5e_priv *priv = netdev_priv(dev);
+	struct mlx5e_sw_stats *sstats = &priv->stats.sw;
+
+	stats->rx_packets = sstats->rx_packets;
+	stats->rx_bytes   = sstats->rx_bytes;
+	stats->tx_packets = sstats->tx_packets;
+	stats->tx_bytes   = sstats->tx_bytes;
+
+	stats->tx_dropped = sstats->tx_queue_dropped;
+
+	return 0;
+}
+
+int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
+			    void *sp)
+{
+	switch (attr_id) {
+	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
+		return mlx5e_get_sw_stats64(dev, sp);
+	}
+
+	return -EINVAL;
+}
+
+static struct rtnl_link_stats64 *
+mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+	struct mlx5e_priv *priv = netdev_priv(dev);
+
+	memcpy(stats, &priv->stats.vf_vport, sizeof(*stats));
+	return stats;
+}
+
 static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
 	.switchdev_port_attr_get	= mlx5e_attr_get,
 };
 
 static const struct net_device_ops mlx5e_netdev_ops_rep = {
-	.ndo_open                = mlx5e_open,
-	.ndo_stop                = mlx5e_close,
+	.ndo_open                = mlx5e_rep_open,
+	.ndo_stop                = mlx5e_rep_close,
 	.ndo_start_xmit          = mlx5e_xmit,
 	.ndo_get_phys_port_name  = mlx5e_rep_get_phys_port_name,
 	.ndo_setup_tc            = mlx5e_rep_ndo_setup_tc,
-	.ndo_get_stats64         = mlx5e_get_stats,
+	.ndo_get_stats64         = mlx5e_rep_get_stats,
+	.ndo_udp_tunnel_add      = mlx5e_add_vxlan_port,
+	.ndo_udp_tunnel_del      = mlx5e_del_vxlan_port,
+	.ndo_has_offload_stats	 = mlx5e_has_offload_stats,
+	.ndo_get_offload_stats	 = mlx5e_get_offload_stats,
 };
 
 static void mlx5e_build_rep_netdev_priv(struct mlx5_core_dev *mdev,
@@ -328,7 +470,7 @@ static int mlx5e_init_rep_rx(struct mlx5
 	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 	struct mlx5_eswitch_rep *rep = priv->ppriv;
 	struct mlx5_core_dev *mdev = priv->mdev;
-	struct mlx5_flow_rule *flow_rule;
+	struct mlx5_flow_handle *flow_rule;
 	int err;
 	int i;
 
@@ -360,7 +502,7 @@ static int mlx5e_init_rep_rx(struct mlx5
 	return 0;
 
 err_del_flow_rule:
-	mlx5_del_flow_rule(rep->vport_rx_rule);
+	mlx5_del_flow_rules(rep->vport_rx_rule);
 err_destroy_direct_tirs:
 	mlx5e_destroy_direct_tirs(priv);
 err_destroy_direct_rqts:
@@ -375,7 +517,7 @@ static void mlx5e_cleanup_rep_rx(struct
 	int i;
 
 	mlx5e_tc_cleanup(priv);
-	mlx5_del_flow_rule(rep->vport_rx_rule);
+	mlx5_del_flow_rules(rep->vport_rx_rule);
 	mlx5e_destroy_direct_tirs(priv);
 	for (i = 0; i < priv->params.num_channels; i++)
 		mlx5e_destroy_rqt(priv, &priv->direct_tir[i].rqt);
@@ -405,7 +547,7 @@ static struct mlx5e_profile mlx5e_rep_pr
 	.cleanup_rx		= mlx5e_cleanup_rep_rx,
 	.init_tx		= mlx5e_init_rep_tx,
 	.cleanup_tx		= mlx5e_cleanup_nic_tx,
-	.update_stats           = mlx5e_update_sw_rep_counters,
+	.update_stats           = mlx5e_rep_update_stats,
 	.max_nch		= mlx5e_get_rep_max_num_channels,
 	.max_tc			= 1,
 };
@@ -423,7 +565,7 @@ int mlx5e_vport_rep_load(struct mlx5_esw
 		return -EINVAL;
 	}
 
-	rep->priv_data = netdev_priv(netdev);
+	rep->netdev = netdev;
 
 	err = mlx5e_attach_netdev(esw->dev, netdev);
 	if (err) {
@@ -445,7 +587,7 @@ err_detach_netdev:
 	mlx5e_detach_netdev(esw->dev, netdev);
 
 err_destroy_netdev:
-	mlx5e_destroy_netdev(esw->dev, rep->priv_data);
+	mlx5e_destroy_netdev(esw->dev, netdev_priv(netdev));
 
 	return err;
 
@@ -454,10 +596,9 @@ err_destroy_netdev:
 void mlx5e_vport_rep_unload(struct mlx5_eswitch *esw,
 			    struct mlx5_eswitch_rep *rep)
 {
-	struct mlx5e_priv *priv = rep->priv_data;
-	struct net_device *netdev = priv->netdev;
+	struct net_device *netdev = rep->netdev;
 
 	unregister_netdev(netdev);
 	mlx5e_detach_netdev(esw->dev, netdev);
-	mlx5e_destroy_netdev(esw->dev, priv);
+	mlx5e_destroy_netdev(esw->dev, netdev_priv(netdev));
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c	2017-02-12 16:03:20.000000000 -0500
@@ -109,7 +109,6 @@ static bool mlx5e_am_on_top(struct mlx5e
 	switch (am->tune_state) {
 	case MLX5E_AM_PARKING_ON_TOP:
 	case MLX5E_AM_PARKING_TIRED:
-		WARN_ONCE(true, "mlx5e_am_on_top: PARKING\n");
 		return true;
 	case MLX5E_AM_GOING_RIGHT:
 		return (am->steps_left > 1) && (am->steps_right == 1);
@@ -123,7 +122,6 @@ static void mlx5e_am_turn(struct mlx5e_r
 	switch (am->tune_state) {
 	case MLX5E_AM_PARKING_ON_TOP:
 	case MLX5E_AM_PARKING_TIRED:
-		WARN_ONCE(true, "mlx5e_am_turn: PARKING\n");
 		break;
 	case MLX5E_AM_GOING_RIGHT:
 		am->tune_state = MLX5E_AM_GOING_LEFT;
@@ -144,7 +142,6 @@ static int mlx5e_am_step(struct mlx5e_rx
 	switch (am->tune_state) {
 	case MLX5E_AM_PARKING_ON_TOP:
 	case MLX5E_AM_PARKING_TIRED:
-		WARN_ONCE(true, "mlx5e_am_step: PARKING\n");
 		break;
 	case MLX5E_AM_GOING_RIGHT:
 		if (am->profile_ix == (MLX5E_PARAMS_AM_NUM_PROFILES - 1))
@@ -282,10 +279,8 @@ static void mlx5e_am_calc_stats(struct m
 	u32 delta_us = ktime_us_delta(end->time, start->time);
 	unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
 
-	if (!delta_us) {
-		WARN_ONCE(true, "mlx5e_am_calc_stats: delta_us=0\n");
+	if (!delta_us)
 		return;
-	}
 
 	curr_stats->ppms =            (npkts * USEC_PER_MSEC) / delta_us;
 	curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c	2017-02-12 16:03:20.000000000 -0500
@@ -164,14 +164,14 @@ void mlx5e_modify_rx_cqe_compression(str
 
 	mutex_lock(&priv->state_lock);
 
-	if (priv->params.rx_cqe_compress == val)
+	if (MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS) == val)
 		goto unlock;
 
 	was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
 	if (was_opened)
 		mlx5e_close_locked(priv->netdev);
 
-	priv->params.rx_cqe_compress = val;
+	MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, val);
 
 	if (was_opened)
 		mlx5e_open_locked(priv->netdev);
@@ -193,6 +193,9 @@ static inline bool mlx5e_rx_cache_put(st
 		return false;
 	}
 
+	if (unlikely(page_is_pfmemalloc(dma_info->page)))
+		return false;
+
 	cache->page_cache[cache->tail] = *dma_info;
 	cache->tail = tail_next;
 	return true;
@@ -737,10 +740,10 @@ static inline
 struct sk_buff *skb_from_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe,
 			     u16 wqe_counter, u32 cqe_bcnt)
 {
-	struct bpf_prog *xdp_prog = READ_ONCE(rq->xdp_prog);
 	struct mlx5e_dma_info *di;
 	struct sk_buff *skb;
 	void *va, *data;
+	bool consumed;
 
 	di             = &rq->dma_info[wqe_counter];
 	va             = page_address(di->page);
@@ -759,7 +762,11 @@ struct sk_buff *skb_from_cqe(struct mlx5
 		return NULL;
 	}
 
-	if (mlx5e_xdp_handle(rq, xdp_prog, di, data, cqe_bcnt))
+	rcu_read_lock();
+	consumed = mlx5e_xdp_handle(rq, READ_ONCE(rq->xdp_prog), di, data,
+				    cqe_bcnt);
+	rcu_read_unlock();
+	if (consumed)
 		return NULL; /* page/packet was consumed by XDP */
 
 	skb = build_skb(va, RQ_PAGE_SIZE(rq));
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies, Ltd.  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/ip.h>
+#include <linux/udp.h>
+#include <net/udp.h>
+#include "en.h"
+
+enum {
+	MLX5E_ST_LINK_STATE,
+	MLX5E_ST_LINK_SPEED,
+	MLX5E_ST_HEALTH_INFO,
+#ifdef CONFIG_INET
+	MLX5E_ST_LOOPBACK,
+#endif
+	MLX5E_ST_NUM,
+};
+
+const char mlx5e_self_tests[MLX5E_ST_NUM][ETH_GSTRING_LEN] = {
+	"Link Test",
+	"Speed Test",
+	"Health Test",
+#ifdef CONFIG_INET
+	"Loopback Test",
+#endif
+};
+
+int mlx5e_self_test_num(struct mlx5e_priv *priv)
+{
+	return ARRAY_SIZE(mlx5e_self_tests);
+}
+
+static int mlx5e_test_health_info(struct mlx5e_priv *priv)
+{
+	struct mlx5_core_health *health = &priv->mdev->priv.health;
+
+	return health->sick ? 1 : 0;
+}
+
+static int mlx5e_test_link_state(struct mlx5e_priv *priv)
+{
+	u8 port_state;
+
+	if (!netif_carrier_ok(priv->netdev))
+		return 1;
+
+	port_state = mlx5_query_vport_state(priv->mdev, MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT, 0);
+	return port_state == VPORT_STATE_UP ? 0 : 1;
+}
+
+static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
+{
+	u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+	u32 eth_proto_oper;
+	int i;
+
+	if (!netif_carrier_ok(priv->netdev))
+		return 1;
+
+	if (mlx5_query_port_ptys(priv->mdev, out, sizeof(out), MLX5_PTYS_EN, 1))
+		return 1;
+
+	eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
+	for (i = 0; i < MLX5E_LINK_MODES_NUMBER; i++) {
+		if (eth_proto_oper & MLX5E_PROT_MASK(i))
+			return 0;
+	}
+	return 1;
+}
+
+#ifdef CONFIG_INET
+/* loopback test */
+#define MLX5E_TEST_PKT_SIZE (MLX5_MPWRQ_SMALL_PACKET_THRESHOLD - NET_IP_ALIGN)
+static const char mlx5e_test_text[ETH_GSTRING_LEN] = "MLX5E SELF TEST";
+#define MLX5E_TEST_MAGIC 0x5AEED15C001ULL
+
+struct mlx5ehdr {
+	__be32 version;
+	__be64 magic;
+	char   text[ETH_GSTRING_LEN];
+};
+
+static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
+{
+	struct sk_buff *skb = NULL;
+	struct mlx5ehdr *mlxh;
+	struct ethhdr *ethh;
+	struct udphdr *udph;
+	struct iphdr *iph;
+	int datalen, iplen;
+
+	datalen = MLX5E_TEST_PKT_SIZE -
+		  (sizeof(*ethh) + sizeof(*iph) + sizeof(*udph));
+
+	skb = netdev_alloc_skb(priv->netdev, MLX5E_TEST_PKT_SIZE);
+	if (!skb) {
+		netdev_err(priv->netdev, "\tFailed to alloc loopback skb\n");
+		return NULL;
+	}
+
+	prefetchw(skb->data);
+	skb_reserve(skb, NET_IP_ALIGN);
+
+	/*  Reserve for ethernet and IP header  */
+	ethh = (struct ethhdr *)skb_push(skb, ETH_HLEN);
+	skb_reset_mac_header(skb);
+
+	skb_set_network_header(skb, skb->len);
+	iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
+
+	skb_set_transport_header(skb, skb->len);
+	udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
+
+	/* Fill ETH header */
+	ether_addr_copy(ethh->h_dest, priv->netdev->dev_addr);
+	eth_zero_addr(ethh->h_source);
+	ethh->h_proto = htons(ETH_P_IP);
+
+	/* Fill UDP header */
+	udph->source = htons(9);
+	udph->dest = htons(9); /* Discard Protocol */
+	udph->len = htons(datalen + sizeof(struct udphdr));
+	udph->check = 0;
+
+	/* Fill IP header */
+	iph->ihl = 5;
+	iph->ttl = 32;
+	iph->version = 4;
+	iph->protocol = IPPROTO_UDP;
+	iplen = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen;
+	iph->tot_len = htons(iplen);
+	iph->frag_off = 0;
+	iph->saddr = 0;
+	iph->daddr = 0;
+	iph->tos = 0;
+	iph->id = 0;
+	ip_send_check(iph);
+
+	/* Fill test header and data */
+	mlxh = (struct mlx5ehdr *)skb_put(skb, sizeof(*mlxh));
+	mlxh->version = 0;
+	mlxh->magic = cpu_to_be64(MLX5E_TEST_MAGIC);
+	strlcpy(mlxh->text, mlx5e_test_text, sizeof(mlxh->text));
+	datalen -= sizeof(*mlxh);
+	memset(skb_put(skb, datalen), 0, datalen);
+
+	skb->csum = 0;
+	skb->ip_summed = CHECKSUM_PARTIAL;
+	udp4_hwcsum(skb, iph->saddr, iph->daddr);
+
+	skb->protocol = htons(ETH_P_IP);
+	skb->pkt_type = PACKET_HOST;
+	skb->dev = priv->netdev;
+
+	return skb;
+}
+
+struct mlx5e_lbt_priv {
+	struct packet_type pt;
+	struct completion comp;
+	bool loopback_ok;
+};
+
+static int
+mlx5e_test_loopback_validate(struct sk_buff *skb,
+			     struct net_device *ndev,
+			     struct packet_type *pt,
+			     struct net_device *orig_ndev)
+{
+	struct mlx5e_lbt_priv *lbtp = pt->af_packet_priv;
+	struct mlx5ehdr *mlxh;
+	struct ethhdr *ethh;
+	struct udphdr *udph;
+	struct iphdr *iph;
+
+	/* We are only going to peek, no need to clone the SKB */
+	if (skb->protocol != htons(ETH_P_IP))
+		goto out;
+
+	if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb))
+		goto out;
+
+	ethh = (struct ethhdr *)skb_mac_header(skb);
+	if (!ether_addr_equal(ethh->h_dest, orig_ndev->dev_addr))
+		goto out;
+
+	iph = ip_hdr(skb);
+	if (iph->protocol != IPPROTO_UDP)
+		goto out;
+
+	udph = udp_hdr(skb);
+	if (udph->dest != htons(9))
+		goto out;
+
+	mlxh = (struct mlx5ehdr *)((char *)udph + sizeof(*udph));
+	if (mlxh->magic != cpu_to_be64(MLX5E_TEST_MAGIC))
+		goto out; /* so close ! */
+
+	/* bingo */
+	lbtp->loopback_ok = true;
+	complete(&lbtp->comp);
+out:
+	kfree_skb(skb);
+	return 0;
+}
+
+static int mlx5e_test_loopback_setup(struct mlx5e_priv *priv,
+				     struct mlx5e_lbt_priv *lbtp)
+{
+	int err = 0;
+
+	err = mlx5e_refresh_tirs_self_loopback(priv->mdev, true);
+	if (err) {
+		netdev_err(priv->netdev,
+			   "\tFailed to enable UC loopback err(%d)\n", err);
+		return err;
+	}
+
+	lbtp->loopback_ok = false;
+	init_completion(&lbtp->comp);
+
+	lbtp->pt.type = htons(ETH_P_ALL);
+	lbtp->pt.func = mlx5e_test_loopback_validate;
+	lbtp->pt.dev = priv->netdev;
+	lbtp->pt.af_packet_priv = lbtp;
+	dev_add_pack(&lbtp->pt);
+	return err;
+}
+
+static void mlx5e_test_loopback_cleanup(struct mlx5e_priv *priv,
+					struct mlx5e_lbt_priv *lbtp)
+{
+	dev_remove_pack(&lbtp->pt);
+	mlx5e_refresh_tirs_self_loopback(priv->mdev, false);
+}
+
+#define MLX5E_LB_VERIFY_TIMEOUT (msecs_to_jiffies(200))
+static int mlx5e_test_loopback(struct mlx5e_priv *priv)
+{
+	struct mlx5e_lbt_priv *lbtp;
+	struct sk_buff *skb = NULL;
+	int err;
+
+	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+		netdev_err(priv->netdev,
+			   "\tCan't perform loobpack test while device is down\n");
+		return -ENODEV;
+	}
+
+	lbtp = kzalloc(sizeof(*lbtp), GFP_KERNEL);
+	if (!lbtp)
+		return -ENOMEM;
+	lbtp->loopback_ok = false;
+
+	err = mlx5e_test_loopback_setup(priv, lbtp);
+	if (err)
+		goto out;
+
+	skb = mlx5e_test_get_udp_skb(priv);
+	if (!skb) {
+		err = -ENOMEM;
+		goto cleanup;
+	}
+
+	skb_set_queue_mapping(skb, 0);
+	err = dev_queue_xmit(skb);
+	if (err) {
+		netdev_err(priv->netdev,
+			   "\tFailed to xmit loopback packet err(%d)\n",
+			   err);
+		goto cleanup;
+	}
+
+	wait_for_completion_timeout(&lbtp->comp, MLX5E_LB_VERIFY_TIMEOUT);
+	err = !lbtp->loopback_ok;
+
+cleanup:
+	mlx5e_test_loopback_cleanup(priv, lbtp);
+out:
+	kfree(lbtp);
+	return err;
+}
+#endif
+
+static int (*mlx5e_st_func[MLX5E_ST_NUM])(struct mlx5e_priv *) = {
+	mlx5e_test_link_state,
+	mlx5e_test_link_speed,
+	mlx5e_test_health_info,
+#ifdef CONFIG_INET
+	mlx5e_test_loopback,
+#endif
+};
+
+void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
+		     u64 *buf)
+{
+	struct mlx5e_priv *priv = netdev_priv(ndev);
+	int i;
+
+	memset(buf, 0, sizeof(u64) * MLX5E_ST_NUM);
+
+	mutex_lock(&priv->state_lock);
+	netdev_info(ndev, "Self test begin..\n");
+
+	for (i = 0; i < MLX5E_ST_NUM; i++) {
+		netdev_info(ndev, "\t[%d] %s start..\n",
+			    i, mlx5e_self_tests[i]);
+		buf[i] = mlx5e_st_func[i](priv);
+		netdev_info(ndev, "\t[%d] %s end: result(%lld)\n",
+			    i, mlx5e_self_tests[i], buf[i]);
+	}
+
+	mutex_unlock(&priv->state_lock);
+
+	for (i = 0; i < MLX5E_ST_NUM; i++) {
+		if (buf[i]) {
+			etest->flags |= ETH_TEST_FL_FAILED;
+			break;
+		}
+	}
+	netdev_info(ndev, "Self test out: status flags(0x%x)\n",
+		    etest->flags);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h	2017-02-12 16:03:20.000000000 -0500
@@ -377,6 +377,24 @@ struct mlx5e_stats {
 	struct mlx5e_qcounter_stats qcnt;
 	struct mlx5e_vport_stats vport;
 	struct mlx5e_pport_stats pport;
+	struct rtnl_link_stats64 vf_vport;
+};
+
+static const struct counter_desc mlx5e_pme_status_desc[] = {
+	{ "module_plug", 0 },
+	{ "module_unplug", 8 },
+};
+
+static const struct counter_desc mlx5e_pme_error_desc[] = {
+	{ "module_pwr_budget_exd", 0 },  /* power budget exceed */
+	{ "module_long_range", 8 },      /* long range for non MLNX cable */
+	{ "module_bus_stuck", 16 },      /* bus stuck (I2C or data shorted) */
+	{ "module_no_eeprom", 24 },      /* no eeprom/retry time out */
+	{ "module_enforce_part", 32 },   /* enforce part number list */
+	{ "module_unknown_id", 40 },     /* unknown identifier */
+	{ "module_high_temp", 48 },      /* high temperature */
+	{ "module_bad_shorted", 56 },    /* bad or shorted cable/module */
+	{ "module_unknown_status", 64 },
 };
 
 #endif /* __MLX5_EN_STATS_H__ */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c	2017-02-12 16:03:20.000000000 -0500
@@ -31,6 +31,7 @@
  */
 
 #include <net/flow_dissector.h>
+#include <net/sch_generic.h>
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
 #include <net/tc_act/tc_skbedit.h>
@@ -40,28 +41,43 @@
 #include <net/switchdev.h>
 #include <net/tc_act/tc_mirred.h>
 #include <net/tc_act/tc_vlan.h>
+#include <net/tc_act/tc_tunnel_key.h>
+#include <net/vxlan.h>
 #include "en.h"
 #include "en_tc.h"
 #include "eswitch.h"
+#include "vxlan.h"
 
 struct mlx5e_tc_flow {
 	struct rhash_head	node;
 	u64			cookie;
-	struct mlx5_flow_rule	*rule;
+	struct mlx5_flow_handle *rule;
+	struct list_head	encap; /* flows sharing the same encap */
 	struct mlx5_esw_flow_attr *attr;
 };
 
+enum {
+	MLX5_HEADER_TYPE_VXLAN = 0x0,
+	MLX5_HEADER_TYPE_NVGRE = 0x1,
+};
+
 #define MLX5E_TC_TABLE_NUM_ENTRIES 1024
 #define MLX5E_TC_TABLE_NUM_GROUPS 4
 
-static struct mlx5_flow_rule *mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
-						    struct mlx5_flow_spec *spec,
-						    u32 action, u32 flow_tag)
+static struct mlx5_flow_handle *
+mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+		      struct mlx5_flow_spec *spec,
+		      u32 action, u32 flow_tag)
 {
 	struct mlx5_core_dev *dev = priv->mdev;
 	struct mlx5_flow_destination dest = { 0 };
+	struct mlx5_flow_act flow_act = {
+		.action = action,
+		.flow_tag = flow_tag,
+		.encap_id = 0,
+	};
 	struct mlx5_fc *counter = NULL;
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *rule;
 	bool table_created = false;
 
 	if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
@@ -82,7 +98,7 @@ static struct mlx5_flow_rule *mlx5e_tc_a
 							    MLX5E_TC_PRIO,
 							    MLX5E_TC_TABLE_NUM_ENTRIES,
 							    MLX5E_TC_TABLE_NUM_GROUPS,
-							    0);
+							    0, 0);
 		if (IS_ERR(priv->fs.tc.t)) {
 			netdev_err(priv->netdev,
 				   "Failed to create tc offload table\n");
@@ -94,9 +110,7 @@ static struct mlx5_flow_rule *mlx5e_tc_a
 	}
 
 	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
-	rule = mlx5_add_flow_rule(priv->fs.tc.t, spec,
-				  action, flow_tag,
-				  &dest);
+	rule = mlx5_add_flow_rules(priv->fs.tc.t, spec, &flow_act, &dest, 1);
 
 	if (IS_ERR(rule))
 		goto err_add_rule;
@@ -114,9 +128,10 @@ err_create_ft:
 	return rule;
 }
 
-static struct mlx5_flow_rule *mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
-						    struct mlx5_flow_spec *spec,
-						    struct mlx5_esw_flow_attr *attr)
+static struct mlx5_flow_handle *
+mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
+		      struct mlx5_flow_spec *spec,
+		      struct mlx5_esw_flow_attr *attr)
 {
 	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 	int err;
@@ -128,21 +143,45 @@ static struct mlx5_flow_rule *mlx5e_tc_a
 	return mlx5_eswitch_add_offloaded_rule(esw, spec, attr);
 }
 
+static void mlx5e_detach_encap(struct mlx5e_priv *priv,
+			       struct mlx5e_tc_flow *flow) {
+	struct list_head *next = flow->encap.next;
+
+	list_del(&flow->encap);
+	if (list_empty(next)) {
+		struct mlx5_encap_entry *e;
+
+		e = list_entry(next, struct mlx5_encap_entry, flows);
+		if (e->n) {
+			mlx5_encap_dealloc(priv->mdev, e->encap_id);
+			neigh_release(e->n);
+		}
+		hlist_del_rcu(&e->encap_hlist);
+		kfree(e);
+	}
+}
+
+/* we get here also when setting rule to the FW failed, etc. It means that the
+ * flow rule itself might not exist, but some offloading related to the actions
+ * should be cleaned.
+ */
 static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
-			      struct mlx5_flow_rule *rule,
-			      struct mlx5_esw_flow_attr *attr)
+			      struct mlx5e_tc_flow *flow)
 {
 	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 	struct mlx5_fc *counter = NULL;
 
-	counter = mlx5_flow_rule_counter(rule);
-
-	if (esw && esw->mode == SRIOV_OFFLOADS)
-		mlx5_eswitch_del_vlan_action(esw, attr);
-
-	mlx5_del_flow_rule(rule);
+	if (!IS_ERR(flow->rule)) {
+		counter = mlx5_flow_rule_counter(flow->rule);
+		mlx5_del_flow_rules(flow->rule);
+		mlx5_fc_destroy(priv->mdev, counter);
+	}
 
-	mlx5_fc_destroy(priv->mdev, counter);
+	if (esw && esw->mode == SRIOV_OFFLOADS) {
+		mlx5_eswitch_del_vlan_action(esw, flow->attr);
+		if (flow->attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
+			mlx5e_detach_encap(priv, flow);
+	}
 
 	if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) {
 		mlx5_destroy_flow_table(priv->fs.tc.t);
@@ -150,8 +189,136 @@ static void mlx5e_tc_del_flow(struct mlx
 	}
 }
 
-static int parse_cls_flower(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec,
-			    struct tc_cls_flower_offload *f)
+static void parse_vxlan_attr(struct mlx5_flow_spec *spec,
+			     struct tc_cls_flower_offload *f)
+{
+	void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+				       outer_headers);
+	void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+				       outer_headers);
+	void *misc_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+				    misc_parameters);
+	void *misc_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+				    misc_parameters);
+
+	MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_UDP);
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID)) {
+		struct flow_dissector_key_keyid *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ENC_KEYID,
+						  f->key);
+		struct flow_dissector_key_keyid *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ENC_KEYID,
+						  f->mask);
+		MLX5_SET(fte_match_set_misc, misc_c, vxlan_vni,
+			 be32_to_cpu(mask->keyid));
+		MLX5_SET(fte_match_set_misc, misc_v, vxlan_vni,
+			 be32_to_cpu(key->keyid));
+	}
+}
+
+static int parse_tunnel_attr(struct mlx5e_priv *priv,
+			     struct mlx5_flow_spec *spec,
+			     struct tc_cls_flower_offload *f)
+{
+	void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+				       outer_headers);
+	void *headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+				       outer_headers);
+
+	struct flow_dissector_key_control *enc_control =
+		skb_flow_dissector_target(f->dissector,
+					  FLOW_DISSECTOR_KEY_ENC_CONTROL,
+					  f->key);
+
+	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) {
+		struct flow_dissector_key_ports *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ENC_PORTS,
+						  f->key);
+		struct flow_dissector_key_ports *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ENC_PORTS,
+						  f->mask);
+
+		/* Full udp dst port must be given */
+		if (memchr_inv(&mask->dst, 0xff, sizeof(mask->dst)))
+			goto vxlan_match_offload_err;
+
+		if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->dst)) &&
+		    MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap))
+			parse_vxlan_attr(spec, f);
+		else {
+			netdev_warn(priv->netdev,
+				    "%d isn't an offloaded vxlan udp dport\n", be16_to_cpu(key->dst));
+			return -EOPNOTSUPP;
+		}
+
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+			 udp_dport, ntohs(mask->dst));
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+			 udp_dport, ntohs(key->dst));
+
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+			 udp_sport, ntohs(mask->src));
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+			 udp_sport, ntohs(key->src));
+	} else { /* udp dst port must be given */
+vxlan_match_offload_err:
+		netdev_warn(priv->netdev,
+			    "IP tunnel decap offload supported only for vxlan, must set UDP dport\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (enc_control->addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
+		struct flow_dissector_key_ipv4_addrs *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
+						  f->key);
+		struct flow_dissector_key_ipv4_addrs *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS,
+						  f->mask);
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+			 src_ipv4_src_ipv6.ipv4_layout.ipv4,
+			 ntohl(mask->src));
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+			 src_ipv4_src_ipv6.ipv4_layout.ipv4,
+			 ntohl(key->src));
+
+		MLX5_SET(fte_match_set_lyr_2_4, headers_c,
+			 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
+			 ntohl(mask->dst));
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v,
+			 dst_ipv4_dst_ipv6.ipv4_layout.ipv4,
+			 ntohl(key->dst));
+
+		MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, ETH_P_IP);
+	}
+
+	/* Enforce DMAC when offloading incoming tunneled flows.
+	 * Flow counters require a match on the DMAC.
+	 */
+	MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_47_16);
+	MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, dmac_15_0);
+	ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
+				     dmac_47_16), priv->netdev->dev_addr);
+
+	/* let software handle IP fragments */
+	MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
+
+	return 0;
+}
+
+static int __parse_cls_flower(struct mlx5e_priv *priv,
+			      struct mlx5_flow_spec *spec,
+			      struct tc_cls_flower_offload *f,
+			      u8 *min_inline)
 {
 	void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
 				       outer_headers);
@@ -160,6 +327,8 @@ static int parse_cls_flower(struct mlx5e
 	u16 addr_type = 0;
 	u8 ip_proto = 0;
 
+	*min_inline = MLX5_INLINE_MODE_L2;
+
 	if (f->dissector->used_keys &
 	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
 	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
@@ -167,18 +336,68 @@ static int parse_cls_flower(struct mlx5e
 	      BIT(FLOW_DISSECTOR_KEY_VLAN) |
 	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
 	      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
-	      BIT(FLOW_DISSECTOR_KEY_PORTS))) {
+	      BIT(FLOW_DISSECTOR_KEY_PORTS) |
+	      BIT(FLOW_DISSECTOR_KEY_ENC_KEYID) |
+	      BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
+	      BIT(FLOW_DISSECTOR_KEY_ENC_PORTS)	|
+	      BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
 		netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
 			    f->dissector->used_keys);
 		return -EOPNOTSUPP;
 	}
 
+	if ((dissector_uses_key(f->dissector,
+				FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) ||
+	     dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_KEYID) ||
+	     dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_PORTS)) &&
+	    dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ENC_CONTROL)) {
+		struct flow_dissector_key_control *key =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_ENC_CONTROL,
+						  f->key);
+		switch (key->addr_type) {
+		case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
+			if (parse_tunnel_attr(priv, spec, f))
+				return -EOPNOTSUPP;
+			break;
+		case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
+			netdev_warn(priv->netdev,
+				    "IPv6 tunnel decap offload isn't supported\n");
+		default:
+			return -EOPNOTSUPP;
+		}
+
+		/* In decap flow, header pointers should point to the inner
+		 * headers, outer header were already set by parse_tunnel_attr
+		 */
+		headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
+					 inner_headers);
+	}
+
 	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
 		struct flow_dissector_key_control *key =
 			skb_flow_dissector_target(f->dissector,
 						  FLOW_DISSECTOR_KEY_CONTROL,
 						  f->key);
+
+		struct flow_dissector_key_control *mask =
+			skb_flow_dissector_target(f->dissector,
+						  FLOW_DISSECTOR_KEY_CONTROL,
+						  f->mask);
 		addr_type = key->addr_type;
+
+		if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
+			MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
+			MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
+				 key->flags & FLOW_DIS_IS_FRAGMENT);
+
+			/* the HW doesn't need L3 inline to match on frag=no */
+			if (key->flags & FLOW_DIS_IS_FRAGMENT)
+				*min_inline = MLX5_INLINE_MODE_IP;
+		}
 	}
 
 	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
@@ -201,6 +420,9 @@ static int parse_cls_flower(struct mlx5e
 			 mask->ip_proto);
 		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
 			 key->ip_proto);
+
+		if (mask->ip_proto)
+			*min_inline = MLX5_INLINE_MODE_IP;
 	}
 
 	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
@@ -271,6 +493,9 @@ static int parse_cls_flower(struct mlx5e
 		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 				    dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
 		       &key->dst, sizeof(key->dst));
+
+		if (mask->src || mask->dst)
+			*min_inline = MLX5_INLINE_MODE_IP;
 	}
 
 	if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
@@ -296,6 +521,10 @@ static int parse_cls_flower(struct mlx5e
 		memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
 				    dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
 		       &key->dst, sizeof(key->dst));
+
+		if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY ||
+		    ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY)
+			*min_inline = MLX5_INLINE_MODE_IP;
 	}
 
 	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
@@ -336,11 +565,39 @@ static int parse_cls_flower(struct mlx5e
 				   "Only UDP and TCP transport are supported\n");
 			return -EINVAL;
 		}
+
+		if (mask->src || mask->dst)
+			*min_inline = MLX5_INLINE_MODE_TCP_UDP;
 	}
 
 	return 0;
 }
 
+static int parse_cls_flower(struct mlx5e_priv *priv,
+			    struct mlx5_flow_spec *spec,
+			    struct tc_cls_flower_offload *f)
+{
+	struct mlx5_core_dev *dev = priv->mdev;
+	struct mlx5_eswitch *esw = dev->priv.eswitch;
+	struct mlx5_eswitch_rep *rep = priv->ppriv;
+	u8 min_inline;
+	int err;
+
+	err = __parse_cls_flower(priv, spec, f, &min_inline);
+
+	if (!err && esw->mode == SRIOV_OFFLOADS &&
+	    rep->vport != FDB_UPLINK_VPORT) {
+		if (min_inline > esw->offloads.inline_mode) {
+			netdev_warn(priv->netdev,
+				    "Flow is not offloaded due to min inline setting, required %d actual %d\n",
+				    min_inline, esw->offloads.inline_mode);
+			return -EOPNOTSUPP;
+		}
+	}
+
+	return err;
+}
+
 static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
 				u32 *action, u32 *flow_tag)
 {
@@ -387,11 +644,258 @@ static int parse_tc_nic_actions(struct m
 	return 0;
 }
 
+static inline int cmp_encap_info(struct mlx5_encap_info *a,
+				 struct mlx5_encap_info *b)
+{
+	return memcmp(a, b, sizeof(*a));
+}
+
+static inline int hash_encap_info(struct mlx5_encap_info *info)
+{
+	return jhash(info, sizeof(*info), 0);
+}
+
+static int mlx5e_route_lookup_ipv4(struct mlx5e_priv *priv,
+				   struct net_device *mirred_dev,
+				   struct net_device **out_dev,
+				   struct flowi4 *fl4,
+				   struct neighbour **out_n,
+				   __be32 *saddr,
+				   int *out_ttl)
+{
+	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+	struct rtable *rt;
+	struct neighbour *n = NULL;
+	int ttl;
+
+#if IS_ENABLED(CONFIG_INET)
+	int ret;
+
+	rt = ip_route_output_key(dev_net(mirred_dev), fl4);
+	ret = PTR_ERR_OR_ZERO(rt);
+	if (ret)
+		return ret;
+#else
+	return -EOPNOTSUPP;
+#endif
+	/* if the egress device isn't on the same HW e-switch, we use the uplink */
+	if (!switchdev_port_same_parent_id(priv->netdev, rt->dst.dev))
+		*out_dev = mlx5_eswitch_get_uplink_netdev(esw);
+	else
+		*out_dev = rt->dst.dev;
+
+	ttl = ip4_dst_hoplimit(&rt->dst);
+	n = dst_neigh_lookup(&rt->dst, &fl4->daddr);
+	ip_rt_put(rt);
+	if (!n)
+		return -ENOMEM;
+
+	*out_n = n;
+	*saddr = fl4->saddr;
+	*out_ttl = ttl;
+
+	return 0;
+}
+
+static int gen_vxlan_header_ipv4(struct net_device *out_dev,
+				 char buf[],
+				 unsigned char h_dest[ETH_ALEN],
+				 int ttl,
+				 __be32 daddr,
+				 __be32 saddr,
+				 __be16 udp_dst_port,
+				 __be32 vx_vni)
+{
+	int encap_size = VXLAN_HLEN + sizeof(struct iphdr) + ETH_HLEN;
+	struct ethhdr *eth = (struct ethhdr *)buf;
+	struct iphdr  *ip = (struct iphdr *)((char *)eth + sizeof(struct ethhdr));
+	struct udphdr *udp = (struct udphdr *)((char *)ip + sizeof(struct iphdr));
+	struct vxlanhdr *vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr));
+
+	memset(buf, 0, encap_size);
+
+	ether_addr_copy(eth->h_dest, h_dest);
+	ether_addr_copy(eth->h_source, out_dev->dev_addr);
+	eth->h_proto = htons(ETH_P_IP);
+
+	ip->daddr = daddr;
+	ip->saddr = saddr;
+
+	ip->ttl = ttl;
+	ip->protocol = IPPROTO_UDP;
+	ip->version = 0x4;
+	ip->ihl = 0x5;
+
+	udp->dest = udp_dst_port;
+	vxh->vx_flags = VXLAN_HF_VNI;
+	vxh->vx_vni = vxlan_vni_field(vx_vni);
+
+	return encap_size;
+}
+
+static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
+					  struct net_device *mirred_dev,
+					  struct mlx5_encap_entry *e,
+					  struct net_device **out_dev)
+{
+	int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
+	struct neighbour *n = NULL;
+	struct flowi4 fl4 = {};
+	char *encap_header;
+	int encap_size;
+	__be32 saddr;
+	int ttl;
+	int err;
+
+	encap_header = kzalloc(max_encap_size, GFP_KERNEL);
+	if (!encap_header)
+		return -ENOMEM;
+
+	switch (e->tunnel_type) {
+	case MLX5_HEADER_TYPE_VXLAN:
+		fl4.flowi4_proto = IPPROTO_UDP;
+		fl4.fl4_dport = e->tun_info.tp_dst;
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+	fl4.daddr = e->tun_info.daddr;
+
+	err = mlx5e_route_lookup_ipv4(priv, mirred_dev, out_dev,
+				      &fl4, &n, &saddr, &ttl);
+	if (err)
+		goto out;
+
+	e->n = n;
+	e->out_dev = *out_dev;
+
+	if (!(n->nud_state & NUD_VALID)) {
+		pr_warn("%s: can't offload, neighbour to %pI4 invalid\n", __func__, &fl4.daddr);
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	neigh_ha_snapshot(e->h_dest, n, *out_dev);
+
+	switch (e->tunnel_type) {
+	case MLX5_HEADER_TYPE_VXLAN:
+		encap_size = gen_vxlan_header_ipv4(*out_dev, encap_header,
+						   e->h_dest, ttl,
+						   e->tun_info.daddr,
+						   saddr, e->tun_info.tp_dst,
+						   e->tun_info.tun_id);
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
+			       encap_size, encap_header, &e->encap_id);
+out:
+	if (err && n)
+		neigh_release(n);
+	kfree(encap_header);
+	return err;
+}
+
+static int mlx5e_attach_encap(struct mlx5e_priv *priv,
+			      struct ip_tunnel_info *tun_info,
+			      struct net_device *mirred_dev,
+			      struct mlx5_esw_flow_attr *attr)
+{
+	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+	unsigned short family = ip_tunnel_info_af(tun_info);
+	struct ip_tunnel_key *key = &tun_info->key;
+	struct mlx5_encap_info info;
+	struct mlx5_encap_entry *e;
+	struct net_device *out_dev;
+	uintptr_t hash_key;
+	bool found = false;
+	int tunnel_type;
+	int err;
+
+	/* udp dst port must be set */
+	if (!memchr_inv(&key->tp_dst, 0, sizeof(key->tp_dst)))
+		goto vxlan_encap_offload_err;
+
+	/* setting udp src port isn't supported */
+	if (memchr_inv(&key->tp_src, 0, sizeof(key->tp_src))) {
+vxlan_encap_offload_err:
+		netdev_warn(priv->netdev,
+			    "must set udp dst port and not set udp src port\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (mlx5e_vxlan_lookup_port(priv, be16_to_cpu(key->tp_dst)) &&
+	    MLX5_CAP_ESW(priv->mdev, vxlan_encap_decap)) {
+		info.tp_dst = key->tp_dst;
+		info.tun_id = tunnel_id_to_key32(key->tun_id);
+		tunnel_type = MLX5_HEADER_TYPE_VXLAN;
+	} else {
+		netdev_warn(priv->netdev,
+			    "%d isn't an offloaded vxlan udp dport\n", be16_to_cpu(key->tp_dst));
+		return -EOPNOTSUPP;
+	}
+
+	switch (family) {
+	case AF_INET:
+		info.daddr = key->u.ipv4.dst;
+		break;
+	case AF_INET6:
+		netdev_warn(priv->netdev,
+			    "IPv6 tunnel encap offload isn't supported\n");
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	hash_key = hash_encap_info(&info);
+
+	hash_for_each_possible_rcu(esw->offloads.encap_tbl, e,
+				   encap_hlist, hash_key) {
+		if (!cmp_encap_info(&e->tun_info, &info)) {
+			found = true;
+			break;
+		}
+	}
+
+	if (found) {
+		attr->encap = e;
+		return 0;
+	}
+
+	e = kzalloc(sizeof(*e), GFP_KERNEL);
+	if (!e)
+		return -ENOMEM;
+
+	e->tun_info = info;
+	e->tunnel_type = tunnel_type;
+	INIT_LIST_HEAD(&e->flows);
+
+	err = mlx5e_create_encap_header_ipv4(priv, mirred_dev, e, &out_dev);
+	if (err)
+		goto out_err;
+
+	attr->encap = e;
+	hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key);
+
+	return err;
+
+out_err:
+	kfree(e);
+	return err;
+}
+
 static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
-				struct mlx5_esw_flow_attr *attr)
+				struct mlx5e_tc_flow *flow)
 {
+	struct mlx5_esw_flow_attr *attr = flow->attr;
+	struct ip_tunnel_info *info = NULL;
 	const struct tc_action *a;
 	LIST_HEAD(actions);
+	bool encap = false;
+	int err;
 
 	if (tc_no_actions(exts))
 		return -EINVAL;
@@ -407,22 +911,44 @@ static int parse_tc_fdb_actions(struct m
 			continue;
 		}
 
-		if (is_tcf_mirred_redirect(a)) {
+		if (is_tcf_mirred_egress_redirect(a)) {
 			int ifindex = tcf_mirred_ifindex(a);
 			struct net_device *out_dev;
 			struct mlx5e_priv *out_priv;
 
 			out_dev = __dev_get_by_index(dev_net(priv->netdev), ifindex);
 
-			if (!switchdev_port_same_parent_id(priv->netdev, out_dev)) {
+			if (switchdev_port_same_parent_id(priv->netdev,
+							  out_dev)) {
+				attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+					MLX5_FLOW_CONTEXT_ACTION_COUNT;
+				out_priv = netdev_priv(out_dev);
+				attr->out_rep = out_priv->ppriv;
+			} else if (encap) {
+				err = mlx5e_attach_encap(priv, info,
+							 out_dev, attr);
+				if (err)
+					return err;
+				list_add(&flow->encap, &attr->encap->flows);
+				attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
+					MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
+					MLX5_FLOW_CONTEXT_ACTION_COUNT;
+				out_priv = netdev_priv(attr->encap->out_dev);
+				attr->out_rep = out_priv->ppriv;
+			} else {
 				pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
 				       priv->netdev->name, out_dev->name);
 				return -EINVAL;
 			}
+			continue;
+		}
 
-			attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-			out_priv = netdev_priv(out_dev);
-			attr->out_rep = out_priv->ppriv;
+		if (is_tcf_tunnel_set(a)) {
+			info = tcf_tunnel_info(a);
+			if (info)
+				encap = true;
+			else
+				return -EOPNOTSUPP;
 			continue;
 		}
 
@@ -439,6 +965,11 @@ static int parse_tc_fdb_actions(struct m
 			continue;
 		}
 
+		if (is_tcf_tunnel_release(a)) {
+			attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
+			continue;
+		}
+
 		return -EINVAL;
 	}
 	return 0;
@@ -453,25 +984,17 @@ int mlx5e_configure_flower(struct mlx5e_
 	u32 flow_tag, action;
 	struct mlx5e_tc_flow *flow;
 	struct mlx5_flow_spec *spec;
-	struct mlx5_flow_rule *old = NULL;
-	struct mlx5_esw_flow_attr *old_attr = NULL;
 	struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 
 	if (esw && esw->mode == SRIOV_OFFLOADS)
 		fdb_flow = true;
 
-	flow = rhashtable_lookup_fast(&tc->ht, &f->cookie,
-				      tc->ht_params);
-	if (flow) {
-		old = flow->rule;
-		old_attr = flow->attr;
-	} else {
-		if (fdb_flow)
-			flow = kzalloc(sizeof(*flow) + sizeof(struct mlx5_esw_flow_attr),
-				       GFP_KERNEL);
-		else
-			flow = kzalloc(sizeof(*flow), GFP_KERNEL);
-	}
+	if (fdb_flow)
+		flow = kzalloc(sizeof(*flow) +
+			       sizeof(struct mlx5_esw_flow_attr),
+			       GFP_KERNEL);
+	else
+		flow = kzalloc(sizeof(*flow), GFP_KERNEL);
 
 	spec = mlx5_vzalloc(sizeof(*spec));
 	if (!spec || !flow) {
@@ -487,7 +1010,7 @@ int mlx5e_configure_flower(struct mlx5e_
 
 	if (fdb_flow) {
 		flow->attr  = (struct mlx5_esw_flow_attr *)(flow + 1);
-		err = parse_tc_fdb_actions(priv, f->exts, flow->attr);
+		err = parse_tc_fdb_actions(priv, f->exts, flow);
 		if (err < 0)
 			goto err_free;
 		flow->rule = mlx5e_tc_add_fdb_flow(priv, spec, flow->attr);
@@ -500,7 +1023,7 @@ int mlx5e_configure_flower(struct mlx5e_
 
 	if (IS_ERR(flow->rule)) {
 		err = PTR_ERR(flow->rule);
-		goto err_free;
+		goto err_del_rule;
 	}
 
 	err = rhashtable_insert_fast(&tc->ht, &flow->node,
@@ -508,17 +1031,13 @@ int mlx5e_configure_flower(struct mlx5e_
 	if (err)
 		goto err_del_rule;
 
-	if (old)
-		mlx5e_tc_del_flow(priv, old, old_attr);
-
 	goto out;
 
 err_del_rule:
-	mlx5_del_flow_rule(flow->rule);
+	mlx5e_tc_del_flow(priv, flow);
 
 err_free:
-	if (!old)
-		kfree(flow);
+	kfree(flow);
 out:
 	kvfree(spec);
 	return err;
@@ -537,7 +1056,8 @@ int mlx5e_delete_flower(struct mlx5e_pri
 
 	rhashtable_remove_fast(&tc->ht, &flow->node, tc->ht_params);
 
-	mlx5e_tc_del_flow(priv, flow->rule, flow->attr);
+	mlx5e_tc_del_flow(priv, flow);
+
 
 	kfree(flow);
 
@@ -594,7 +1114,7 @@ static void _mlx5e_tc_del_flow(void *ptr
 	struct mlx5e_tc_flow *flow = ptr;
 	struct mlx5e_priv *priv = arg;
 
-	mlx5e_tc_del_flow(priv, flow->rule, flow->attr);
+	mlx5e_tc_del_flow(priv, flow);
 	kfree(flow);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eq.c	2017-02-12 16:03:20.000000000 -0500
@@ -139,6 +139,8 @@ static const char *eqe_type_str(u8 type)
 		return "MLX5_EVENT_TYPE_PORT_CHANGE";
 	case MLX5_EVENT_TYPE_GPIO_EVENT:
 		return "MLX5_EVENT_TYPE_GPIO_EVENT";
+	case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
+		return "MLX5_EVENT_TYPE_PORT_MODULE_EVENT";
 	case MLX5_EVENT_TYPE_REMOTE_CONFIG:
 		return "MLX5_EVENT_TYPE_REMOTE_CONFIG";
 	case MLX5_EVENT_TYPE_DB_BF_CONGESTION:
@@ -285,6 +287,11 @@ static int mlx5_eq_int(struct mlx5_core_
 			mlx5_eswitch_vport_event(dev->priv.eswitch, eqe);
 			break;
 #endif
+
+		case MLX5_EVENT_TYPE_PORT_MODULE_EVENT:
+			mlx5_port_module_event(dev, eqe);
+			break;
+
 		default:
 			mlx5_core_warn(dev, "Unhandled event 0x%x on EQ 0x%x\n",
 				       eqe->type, eq->eqn);
@@ -469,7 +476,7 @@ void mlx5_eq_cleanup(struct mlx5_core_de
 int mlx5_start_eqs(struct mlx5_core_dev *dev)
 {
 	struct mlx5_eq_table *table = &dev->priv.eq_table;
-	u32 async_event_mask = MLX5_ASYNC_EVENT_MASK;
+	u64 async_event_mask = MLX5_ASYNC_EVENT_MASK;
 	int err;
 
 	if (MLX5_CAP_GEN(dev, pg))
@@ -480,6 +487,11 @@ int mlx5_start_eqs(struct mlx5_core_dev
 	    mlx5_core_is_pf(dev))
 		async_event_mask |= (1ull << MLX5_EVENT_TYPE_NIC_VPORT_CHANGE);
 
+	if (MLX5_CAP_GEN(dev, port_module_event))
+		async_event_mask |= (1ull << MLX5_EVENT_TYPE_PORT_MODULE_EVENT);
+	else
+		mlx5_core_dbg(dev, "port_module_event is not set\n");
+
 	err = mlx5_create_map_eq(dev, &table->cmd_eq, MLX5_EQ_VEC_CMD,
 				 MLX5_NUM_CMD_EQE, 1ull << MLX5_EVENT_TYPE_CMD,
 				 "mlx5_cmd_eq", &dev->priv.uuari.uars[0]);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c	2017-02-12 16:03:20.000000000 -0500
@@ -56,7 +56,7 @@ struct esw_uc_addr {
 /* E-Switch MC FDB table hash node */
 struct esw_mc_addr { /* SRIOV only */
 	struct l2addr_node     node;
-	struct mlx5_flow_rule *uplink_rule; /* Forward to uplink rule */
+	struct mlx5_flow_handle *uplink_rule; /* Forward to uplink rule */
 	u32                    refcnt;
 };
 
@@ -65,7 +65,7 @@ struct vport_addr {
 	struct l2addr_node     node;
 	u8                     action;
 	u32                    vport;
-	struct mlx5_flow_rule *flow_rule; /* SRIOV only */
+	struct mlx5_flow_handle *flow_rule; /* SRIOV only */
 	/* A flag indicating that mac was added due to mc promiscuous vport */
 	bool mc_promisc;
 };
@@ -133,7 +133,7 @@ static int modify_esw_vport_cvlan(struct
 
 	if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
 	    !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
 		  vport, vlan, qos, set_flags);
@@ -237,13 +237,14 @@ static void del_l2_table_entry(struct ml
 }
 
 /* E-Switch FDB */
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
 __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule,
 			 u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
 {
 	int match_header = (is_zero_ether_addr(mac_c) ? 0 :
 			    MLX5_MATCH_OUTER_HEADERS);
-	struct mlx5_flow_rule *flow_rule = NULL;
+	struct mlx5_flow_handle *flow_rule = NULL;
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_destination dest;
 	struct mlx5_flow_spec *spec;
 	void *mv_misc = NULL;
@@ -285,10 +286,10 @@ __esw_fdb_set_vport_rule(struct mlx5_esw
 		  "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n",
 		  dmac_v, dmac_c, vport);
 	spec->match_criteria_enable = match_header;
+	flow_act.action =  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 	flow_rule =
-		mlx5_add_flow_rule(esw->fdb_table.fdb, spec,
-				   MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				   0, &dest);
+		mlx5_add_flow_rules(esw->fdb_table.fdb, spec,
+				    &flow_act, &dest, 1);
 	if (IS_ERR(flow_rule)) {
 		esw_warn(esw->dev,
 			 "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
@@ -300,7 +301,7 @@ __esw_fdb_set_vport_rule(struct mlx5_esw
 	return flow_rule;
 }
 
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
 esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u32 vport)
 {
 	u8 mac_c[ETH_ALEN];
@@ -309,7 +310,7 @@ esw_fdb_set_vport_rule(struct mlx5_eswit
 	return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac);
 }
 
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
 esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u32 vport)
 {
 	u8 mac_c[ETH_ALEN];
@@ -322,7 +323,7 @@ esw_fdb_set_vport_allmulti_rule(struct m
 	return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v);
 }
 
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
 esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u32 vport)
 {
 	u8 mac_c[ETH_ALEN];
@@ -352,7 +353,7 @@ static int esw_create_legacy_fdb_table(s
 	root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
 	if (!root_ns) {
 		esw_warn(dev, "Failed to get FDB flow namespace\n");
-		return -ENOMEM;
+		return -EOPNOTSUPP;
 	}
 
 	flow_group_in = mlx5_vzalloc(inlen);
@@ -361,7 +362,7 @@ static int esw_create_legacy_fdb_table(s
 	memset(flow_group_in, 0, inlen);
 
 	table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
-	fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0);
+	fdb = mlx5_create_flow_table(root_ns, 0, table_size, 0, 0);
 	if (IS_ERR(fdb)) {
 		err = PTR_ERR(fdb);
 		esw_warn(dev, "Failed to create FDB Table err %d\n", err);
@@ -515,7 +516,7 @@ static int esw_del_uc_addr(struct mlx5_e
 	del_l2_table_entry(esw->dev, esw_uc->table_index);
 
 	if (vaddr->flow_rule)
-		mlx5_del_flow_rule(vaddr->flow_rule);
+		mlx5_del_flow_rules(vaddr->flow_rule);
 	vaddr->flow_rule = NULL;
 
 	l2addr_hash_del(esw_uc);
@@ -562,7 +563,7 @@ static void update_allmulti_vports(struc
 		case MLX5_ACTION_DEL:
 			if (!iter_vaddr)
 				continue;
-			mlx5_del_flow_rule(iter_vaddr->flow_rule);
+			mlx5_del_flow_rules(iter_vaddr->flow_rule);
 			l2addr_hash_del(iter_vaddr);
 			break;
 		}
@@ -632,7 +633,7 @@ static int esw_del_mc_addr(struct mlx5_e
 		  esw_mc->uplink_rule);
 
 	if (vaddr->flow_rule)
-		mlx5_del_flow_rule(vaddr->flow_rule);
+		mlx5_del_flow_rules(vaddr->flow_rule);
 	vaddr->flow_rule = NULL;
 
 	/* If the multicast mac is added as a result of mc promiscuous vport,
@@ -645,7 +646,7 @@ static int esw_del_mc_addr(struct mlx5_e
 	update_allmulti_vports(esw, vaddr, esw_mc);
 
 	if (esw_mc->uplink_rule)
-		mlx5_del_flow_rule(esw_mc->uplink_rule);
+		mlx5_del_flow_rules(esw_mc->uplink_rule);
 
 	l2addr_hash_del(esw_mc);
 	return 0;
@@ -828,14 +829,14 @@ static void esw_apply_vport_rx_mode(stru
 								UPLINK_VPORT);
 		allmulti_addr->refcnt++;
 	} else if (vport->allmulti_rule) {
-		mlx5_del_flow_rule(vport->allmulti_rule);
+		mlx5_del_flow_rules(vport->allmulti_rule);
 		vport->allmulti_rule = NULL;
 
 		if (--allmulti_addr->refcnt > 0)
 			goto promisc;
 
 		if (allmulti_addr->uplink_rule)
-			mlx5_del_flow_rule(allmulti_addr->uplink_rule);
+			mlx5_del_flow_rules(allmulti_addr->uplink_rule);
 		allmulti_addr->uplink_rule = NULL;
 	}
 
@@ -847,7 +848,7 @@ promisc:
 		vport->promisc_rule = esw_fdb_set_vport_promisc_rule(esw,
 								     vport_num);
 	} else if (vport->promisc_rule) {
-		mlx5_del_flow_rule(vport->promisc_rule);
+		mlx5_del_flow_rules(vport->promisc_rule);
 		vport->promisc_rule = NULL;
 	}
 }
@@ -961,7 +962,7 @@ static int esw_vport_enable_egress_acl(s
 	root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_EGRESS);
 	if (!root_ns) {
 		esw_warn(dev, "Failed to get E-Switch egress flow namespace\n");
-		return -EIO;
+		return -EOPNOTSUPP;
 	}
 
 	flow_group_in = mlx5_vzalloc(inlen);
@@ -1018,10 +1019,10 @@ static void esw_vport_cleanup_egress_rul
 					   struct mlx5_vport *vport)
 {
 	if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan))
-		mlx5_del_flow_rule(vport->egress.allowed_vlan);
+		mlx5_del_flow_rules(vport->egress.allowed_vlan);
 
 	if (!IS_ERR_OR_NULL(vport->egress.drop_rule))
-		mlx5_del_flow_rule(vport->egress.drop_rule);
+		mlx5_del_flow_rules(vport->egress.drop_rule);
 
 	vport->egress.allowed_vlan = NULL;
 	vport->egress.drop_rule = NULL;
@@ -1078,7 +1079,7 @@ static int esw_vport_enable_ingress_acl(
 	root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS);
 	if (!root_ns) {
 		esw_warn(dev, "Failed to get E-Switch ingress flow namespace\n");
-		return -EIO;
+		return -EOPNOTSUPP;
 	}
 
 	flow_group_in = mlx5_vzalloc(inlen);
@@ -1179,10 +1180,10 @@ static void esw_vport_cleanup_ingress_ru
 					    struct mlx5_vport *vport)
 {
 	if (!IS_ERR_OR_NULL(vport->ingress.drop_rule))
-		mlx5_del_flow_rule(vport->ingress.drop_rule);
+		mlx5_del_flow_rules(vport->ingress.drop_rule);
 
 	if (!IS_ERR_OR_NULL(vport->ingress.allow_rule))
-		mlx5_del_flow_rule(vport->ingress.allow_rule);
+		mlx5_del_flow_rules(vport->ingress.allow_rule);
 
 	vport->ingress.drop_rule = NULL;
 	vport->ingress.allow_rule = NULL;
@@ -1212,6 +1213,7 @@ static void esw_vport_disable_ingress_ac
 static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
 				    struct mlx5_vport *vport)
 {
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_spec *spec;
 	int err = 0;
 	u8 *smac_v;
@@ -1264,10 +1266,10 @@ static int esw_vport_ingress_config(stru
 	}
 
 	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
 	vport->ingress.allow_rule =
-		mlx5_add_flow_rule(vport->ingress.acl, spec,
-				   MLX5_FLOW_CONTEXT_ACTION_ALLOW,
-				   0, NULL);
+		mlx5_add_flow_rules(vport->ingress.acl, spec,
+				    &flow_act, NULL, 0);
 	if (IS_ERR(vport->ingress.allow_rule)) {
 		err = PTR_ERR(vport->ingress.allow_rule);
 		esw_warn(esw->dev,
@@ -1278,10 +1280,10 @@ static int esw_vport_ingress_config(stru
 	}
 
 	memset(spec, 0, sizeof(*spec));
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
 	vport->ingress.drop_rule =
-		mlx5_add_flow_rule(vport->ingress.acl, spec,
-				   MLX5_FLOW_CONTEXT_ACTION_DROP,
-				   0, NULL);
+		mlx5_add_flow_rules(vport->ingress.acl, spec,
+				    &flow_act, NULL, 0);
 	if (IS_ERR(vport->ingress.drop_rule)) {
 		err = PTR_ERR(vport->ingress.drop_rule);
 		esw_warn(esw->dev,
@@ -1301,6 +1303,7 @@ out:
 static int esw_vport_egress_config(struct mlx5_eswitch *esw,
 				   struct mlx5_vport *vport)
 {
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_spec *spec;
 	int err = 0;
 
@@ -1338,10 +1341,10 @@ static int esw_vport_egress_config(struc
 	MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vport->info.vlan);
 
 	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
 	vport->egress.allowed_vlan =
-		mlx5_add_flow_rule(vport->egress.acl, spec,
-				   MLX5_FLOW_CONTEXT_ACTION_ALLOW,
-				   0, NULL);
+		mlx5_add_flow_rules(vport->egress.acl, spec,
+				    &flow_act, NULL, 0);
 	if (IS_ERR(vport->egress.allowed_vlan)) {
 		err = PTR_ERR(vport->egress.allowed_vlan);
 		esw_warn(esw->dev,
@@ -1353,10 +1356,10 @@ static int esw_vport_egress_config(struc
 
 	/* Drop others rule (star rule) */
 	memset(spec, 0, sizeof(*spec));
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
 	vport->egress.drop_rule =
-		mlx5_add_flow_rule(vport->egress.acl, spec,
-				   MLX5_FLOW_CONTEXT_ACTION_DROP,
-				   0, NULL);
+		mlx5_add_flow_rules(vport->egress.acl, spec,
+				    &flow_act, NULL, 0);
 	if (IS_ERR(vport->egress.drop_rule)) {
 		err = PTR_ERR(vport->egress.drop_rule);
 		esw_warn(esw->dev,
@@ -1369,6 +1372,147 @@ out:
 	return err;
 }
 
+/* Vport QoS management */
+static int esw_create_tsar(struct mlx5_eswitch *esw)
+{
+	u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
+	struct mlx5_core_dev *dev = esw->dev;
+	int err;
+
+	if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
+		return 0;
+
+	if (esw->qos.enabled)
+		return -EEXIST;
+
+	err = mlx5_create_scheduling_element_cmd(dev,
+						 SCHEDULING_HIERARCHY_E_SWITCH,
+						 &tsar_ctx,
+						 &esw->qos.root_tsar_id);
+	if (err) {
+		esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err);
+		return err;
+	}
+
+	esw->qos.enabled = true;
+	return 0;
+}
+
+static void esw_destroy_tsar(struct mlx5_eswitch *esw)
+{
+	int err;
+
+	if (!esw->qos.enabled)
+		return;
+
+	err = mlx5_destroy_scheduling_element_cmd(esw->dev,
+						  SCHEDULING_HIERARCHY_E_SWITCH,
+						  esw->qos.root_tsar_id);
+	if (err)
+		esw_warn(esw->dev, "E-Switch destroy TSAR failed (%d)\n", err);
+
+	esw->qos.enabled = false;
+}
+
+static int esw_vport_enable_qos(struct mlx5_eswitch *esw, int vport_num,
+				u32 initial_max_rate)
+{
+	u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
+	struct mlx5_vport *vport = &esw->vports[vport_num];
+	struct mlx5_core_dev *dev = esw->dev;
+	void *vport_elem;
+	int err = 0;
+
+	if (!esw->qos.enabled || !MLX5_CAP_GEN(dev, qos) ||
+	    !MLX5_CAP_QOS(dev, esw_scheduling))
+		return 0;
+
+	if (vport->qos.enabled)
+		return -EEXIST;
+
+	MLX5_SET(scheduling_context, &sched_ctx, element_type,
+		 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
+	vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx,
+				  element_attributes);
+	MLX5_SET(vport_element, vport_elem, vport_number, vport_num);
+	MLX5_SET(scheduling_context, &sched_ctx, parent_element_id,
+		 esw->qos.root_tsar_id);
+	MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
+		 initial_max_rate);
+
+	err = mlx5_create_scheduling_element_cmd(dev,
+						 SCHEDULING_HIERARCHY_E_SWITCH,
+						 &sched_ctx,
+						 &vport->qos.esw_tsar_ix);
+	if (err) {
+		esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
+			 vport_num, err);
+		return err;
+	}
+
+	vport->qos.enabled = true;
+	return 0;
+}
+
+static void esw_vport_disable_qos(struct mlx5_eswitch *esw, int vport_num)
+{
+	struct mlx5_vport *vport = &esw->vports[vport_num];
+	int err = 0;
+
+	if (!vport->qos.enabled)
+		return;
+
+	err = mlx5_destroy_scheduling_element_cmd(esw->dev,
+						  SCHEDULING_HIERARCHY_E_SWITCH,
+						  vport->qos.esw_tsar_ix);
+	if (err)
+		esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
+			 vport_num, err);
+
+	vport->qos.enabled = false;
+}
+
+static int esw_vport_qos_config(struct mlx5_eswitch *esw, int vport_num,
+				u32 max_rate)
+{
+	u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
+	struct mlx5_vport *vport = &esw->vports[vport_num];
+	struct mlx5_core_dev *dev = esw->dev;
+	void *vport_elem;
+	u32 bitmask = 0;
+	int err = 0;
+
+	if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
+		return -EOPNOTSUPP;
+
+	if (!vport->qos.enabled)
+		return -EIO;
+
+	MLX5_SET(scheduling_context, &sched_ctx, element_type,
+		 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
+	vport_elem = MLX5_ADDR_OF(scheduling_context, &sched_ctx,
+				  element_attributes);
+	MLX5_SET(vport_element, vport_elem, vport_number, vport_num);
+	MLX5_SET(scheduling_context, &sched_ctx, parent_element_id,
+		 esw->qos.root_tsar_id);
+	MLX5_SET(scheduling_context, &sched_ctx, max_average_bw,
+		 max_rate);
+	bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
+
+	err = mlx5_modify_scheduling_element_cmd(dev,
+						 SCHEDULING_HIERARCHY_E_SWITCH,
+						 &sched_ctx,
+						 vport->qos.esw_tsar_ix,
+						 bitmask);
+	if (err) {
+		esw_warn(esw->dev, "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
+			 vport_num, err);
+		return err;
+	}
+
+	return 0;
+}
+
 static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
 {
 	((u8 *)node_guid)[7] = mac[0];
@@ -1404,6 +1548,7 @@ static void esw_apply_vport_conf(struct
 		esw_vport_egress_config(esw, vport);
 	}
 }
+
 static void esw_enable_vport(struct mlx5_eswitch *esw, int vport_num,
 			     int enable_events)
 {
@@ -1417,6 +1562,10 @@ static void esw_enable_vport(struct mlx5
 	/* Restore old vport configuration */
 	esw_apply_vport_conf(esw, vport);
 
+	/* Attach vport to the eswitch rate limiter */
+	if (esw_vport_enable_qos(esw, vport_num, vport->info.max_rate))
+		esw_warn(esw->dev, "Failed to attach vport %d to eswitch rate limiter", vport_num);
+
 	/* Sync with current vport context */
 	vport->enabled_events = enable_events;
 	vport->enabled = true;
@@ -1455,7 +1604,7 @@ static void esw_disable_vport(struct mlx
 	 */
 	esw_vport_change_handle_locked(vport);
 	vport->enabled_events = 0;
-
+	esw_vport_disable_qos(esw, vport_num);
 	if (vport_num && esw->mode == SRIOV_LEGACY) {
 		mlx5_modify_vport_admin_state(esw->dev,
 					      MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
@@ -1481,7 +1630,7 @@ int mlx5_eswitch_enable_sriov(struct mlx
 	if (!MLX5_CAP_GEN(esw->dev, eswitch_flow_table) ||
 	    !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
 		esw_warn(esw->dev, "E-Switch FDB is not supported, aborting ...\n");
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}
 
 	if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
@@ -1501,6 +1650,10 @@ int mlx5_eswitch_enable_sriov(struct mlx
 	if (err)
 		goto abort;
 
+	err = esw_create_tsar(esw);
+	if (err)
+		esw_warn(esw->dev, "Failed to create eswitch TSAR");
+
 	enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : UC_ADDR_CHANGE;
 	for (i = 0; i <= nvfs; i++)
 		esw_enable_vport(esw, i, enabled_events);
@@ -1535,7 +1688,9 @@ void mlx5_eswitch_disable_sriov(struct m
 		esw_disable_vport(esw, i);
 
 	if (mc_promisc && mc_promisc->uplink_rule)
-		mlx5_del_flow_rule(mc_promisc->uplink_rule);
+		mlx5_del_flow_rules(mc_promisc->uplink_rule);
+
+	esw_destroy_tsar(esw);
 
 	if (esw->mode == SRIOV_LEGACY)
 		esw_destroy_legacy_fdb_table(esw);
@@ -1627,6 +1782,7 @@ int mlx5_eswitch_init(struct mlx5_core_d
 		goto abort;
 	}
 
+	hash_init(esw->offloads.encap_tbl);
 	mutex_init(&esw->state_lock);
 
 	for (vport_num = 0; vport_num < total_vports; vport_num++) {
@@ -1642,6 +1798,7 @@ int mlx5_eswitch_init(struct mlx5_core_d
 	esw->total_vports = total_vports;
 	esw->enabled_vports = 0;
 	esw->mode = SRIOV_NONE;
+	esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
 
 	dev->priv.eswitch = esw;
 	return 0;
@@ -1703,7 +1860,7 @@ int mlx5_eswitch_set_vport_mac(struct ml
 
 	if (!ESW_ALLOWED(esw))
 		return -EPERM;
-	if (!LEGAL_VPORT(esw, vport))
+	if (!LEGAL_VPORT(esw, vport) || is_multicast_ether_addr(mac))
 		return -EINVAL;
 
 	mutex_lock(&esw->state_lock);
@@ -1795,6 +1952,7 @@ int mlx5_eswitch_get_vport_config(struct
 	ivi->qos = evport->info.qos;
 	ivi->spoofchk = evport->info.spoofchk;
 	ivi->trusted = evport->info.trusted;
+	ivi->max_tx_rate = evport->info.max_rate;
 	mutex_unlock(&esw->state_lock);
 
 	return 0;
@@ -1888,6 +2046,27 @@ int mlx5_eswitch_set_vport_trust(struct
 	return 0;
 }
 
+int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw,
+				int vport, u32 max_rate)
+{
+	struct mlx5_vport *evport;
+	int err = 0;
+
+	if (!ESW_ALLOWED(esw))
+		return -EPERM;
+	if (!LEGAL_VPORT(esw, vport))
+		return -EINVAL;
+
+	mutex_lock(&esw->state_lock);
+	evport = &esw->vports[vport];
+	err = esw_vport_qos_config(esw, vport, max_rate);
+	if (!err)
+		evport->info.max_rate = max_rate;
+
+	mutex_unlock(&esw->state_lock);
+	return err;
+}
+
 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
 				 int vport,
 				 struct ifla_vf_stats *vf_stats)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h	2017-02-12 16:03:20.000000000 -0500
@@ -97,16 +97,16 @@ struct vport_ingress {
 	struct mlx5_flow_group *allow_spoofchk_only_grp;
 	struct mlx5_flow_group *allow_untagged_only_grp;
 	struct mlx5_flow_group *drop_grp;
-	struct mlx5_flow_rule  *allow_rule;
-	struct mlx5_flow_rule  *drop_rule;
+	struct mlx5_flow_handle  *allow_rule;
+	struct mlx5_flow_handle  *drop_rule;
 };
 
 struct vport_egress {
 	struct mlx5_flow_table *acl;
 	struct mlx5_flow_group *allowed_vlans_grp;
 	struct mlx5_flow_group *drop_grp;
-	struct mlx5_flow_rule  *allowed_vlan;
-	struct mlx5_flow_rule  *drop_rule;
+	struct mlx5_flow_handle  *allowed_vlan;
+	struct mlx5_flow_handle  *drop_rule;
 };
 
 struct mlx5_vport_info {
@@ -115,6 +115,7 @@ struct mlx5_vport_info {
 	u8                      qos;
 	u64                     node_guid;
 	int                     link_state;
+	u32                     max_rate;
 	bool                    spoofchk;
 	bool                    trusted;
 };
@@ -124,8 +125,8 @@ struct mlx5_vport {
 	int                     vport;
 	struct hlist_head       uc_list[MLX5_L2_ADDR_HASH_SIZE];
 	struct hlist_head       mc_list[MLX5_L2_ADDR_HASH_SIZE];
-	struct mlx5_flow_rule   *promisc_rule;
-	struct mlx5_flow_rule   *allmulti_rule;
+	struct mlx5_flow_handle *promisc_rule;
+	struct mlx5_flow_handle *allmulti_rule;
 	struct work_struct      vport_change_handler;
 
 	struct vport_ingress    ingress;
@@ -133,6 +134,11 @@ struct mlx5_vport {
 
 	struct mlx5_vport_info  info;
 
+	struct {
+		bool            enabled;
+		u32             esw_tsar_ix;
+	} qos;
+
 	bool                    enabled;
 	u16                     enabled_events;
 };
@@ -156,7 +162,7 @@ struct mlx5_eswitch_fdb {
 			struct mlx5_flow_table *fdb;
 			struct mlx5_flow_group *send_to_vport_grp;
 			struct mlx5_flow_group *miss_grp;
-			struct mlx5_flow_rule  *miss_rule;
+			struct mlx5_flow_handle *miss_rule;
 			int vlan_push_pop_refcount;
 		} offloads;
 	};
@@ -169,7 +175,7 @@ enum {
 };
 
 struct mlx5_esw_sq {
-	struct mlx5_flow_rule	*send_to_vport_rule;
+	struct mlx5_flow_handle	*send_to_vport_rule;
 	struct list_head	 list;
 };
 
@@ -180,9 +186,9 @@ struct mlx5_eswitch_rep {
 					 struct mlx5_eswitch_rep *rep);
 	u16		       vport;
 	u8		       hw_id[ETH_ALEN];
-	void		      *priv_data;
+	struct net_device      *netdev;
 
-	struct mlx5_flow_rule *vport_rx_rule;
+	struct mlx5_flow_handle *vport_rx_rule;
 	struct list_head       vport_sqs_list;
 	u16		       vlan;
 	u32		       vlan_refcount;
@@ -193,6 +199,8 @@ struct mlx5_esw_offload {
 	struct mlx5_flow_table *ft_offloads;
 	struct mlx5_flow_group *vport_rx_group;
 	struct mlx5_eswitch_rep *vport_reps;
+	DECLARE_HASHTABLE(encap_tbl, 8);
+	u8 inline_mode;
 };
 
 struct mlx5_eswitch {
@@ -209,6 +217,12 @@ struct mlx5_eswitch {
 	 */
 	struct mutex            state_lock;
 	struct esw_mc_addr      *mc_promisc;
+
+	struct {
+		bool            enabled;
+		u32             root_tsar_id;
+	} qos;
+
 	struct mlx5_esw_offload offloads;
 	int                     mode;
 };
@@ -234,6 +248,8 @@ int mlx5_eswitch_set_vport_spoofchk(stru
 				    int vport, bool spoofchk);
 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
 				 int vport_num, bool setting);
+int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw,
+				int vport, u32 max_rate);
 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
 				  int vport, struct ifla_vf_info *ivi);
 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
@@ -243,11 +259,11 @@ int mlx5_eswitch_get_vport_stats(struct
 struct mlx5_flow_spec;
 struct mlx5_esw_flow_attr;
 
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
 mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 				struct mlx5_flow_spec *spec,
 				struct mlx5_esw_flow_attr *attr);
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
 mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn);
 
 enum {
@@ -258,6 +274,24 @@ enum {
 #define MLX5_FLOW_CONTEXT_ACTION_VLAN_POP  0x40
 #define MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH 0x80
 
+struct mlx5_encap_info {
+	__be32 daddr;
+	__be32 tun_id;
+	__be16 tp_dst;
+};
+
+struct mlx5_encap_entry {
+	struct hlist_node encap_hlist;
+	struct list_head flows;
+	u32 encap_id;
+	struct neighbour *n;
+	struct mlx5_encap_info tun_info;
+	unsigned char h_dest[ETH_ALEN];	/* destination eth addr	*/
+
+	struct net_device *out_dev;
+	int tunnel_type;
+};
+
 struct mlx5_esw_flow_attr {
 	struct mlx5_eswitch_rep *in_rep;
 	struct mlx5_eswitch_rep *out_rep;
@@ -265,6 +299,7 @@ struct mlx5_esw_flow_attr {
 	int	action;
 	u16	vlan;
 	bool	vlan_handled;
+	struct mlx5_encap_entry *encap;
 };
 
 int mlx5_eswitch_sqs2vport_start(struct mlx5_eswitch *esw,
@@ -275,11 +310,15 @@ void mlx5_eswitch_sqs2vport_stop(struct
 
 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode);
 int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode);
+int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode);
+int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode);
+int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode);
 void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
 				     int vport_index,
 				     struct mlx5_eswitch_rep *rep);
 void mlx5_eswitch_unregister_vport_rep(struct mlx5_eswitch *esw,
 				       int vport_index);
+struct net_device *mlx5_eswitch_get_uplink_netdev(struct mlx5_eswitch *esw);
 
 int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
 				 struct mlx5_esw_flow_attr *attr);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c	2017-02-12 16:03:20.000000000 -0500
@@ -43,33 +43,36 @@ enum {
 	FDB_SLOW_PATH
 };
 
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
 mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 				struct mlx5_flow_spec *spec,
 				struct mlx5_esw_flow_attr *attr)
 {
-	struct mlx5_flow_destination dest = { 0 };
+	struct mlx5_flow_destination dest[2] = {};
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_fc *counter = NULL;
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *rule;
 	void *misc;
-	int action;
+	int i = 0;
 
 	if (esw->mode != SRIOV_OFFLOADS)
 		return ERR_PTR(-EOPNOTSUPP);
 
 	/* per flow vlan pop/push is emulated, don't set that into the firmware */
-	action = attr->action & ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH | MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
+	flow_act.action = attr->action & ~(MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH | MLX5_FLOW_CONTEXT_ACTION_VLAN_POP);
 
-	if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
-		dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
-		dest.vport_num = attr->out_rep->vport;
-		action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-	} else if (action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
+		dest[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
+		dest[i].vport_num = attr->out_rep->vport;
+		i++;
+	}
+	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
 		counter = mlx5_fc_create(esw->dev, true);
 		if (IS_ERR(counter))
 			return ERR_CAST(counter);
-		dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-		dest.counter = counter;
+		dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+		dest[i].counter = counter;
+		i++;
 	}
 
 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
@@ -80,10 +83,14 @@ mlx5_eswitch_add_offloaded_rule(struct m
 
 	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
 				      MLX5_MATCH_MISC_PARAMETERS;
+	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
+		spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
 
-	rule = mlx5_add_flow_rule((struct mlx5_flow_table *)esw->fdb_table.fdb,
-				  spec, action, 0, &dest);
+	if (attr->encap)
+		flow_act.encap_id = attr->encap->encap_id;
 
+	rule = mlx5_add_flow_rules((struct mlx5_flow_table *)esw->fdb_table.fdb,
+				   spec, &flow_act, dest, i);
 	if (IS_ERR(rule))
 		mlx5_fc_destroy(esw->dev, counter);
 
@@ -159,7 +166,7 @@ static int esw_add_vlan_action_check(str
 	return 0;
 
 out_notsupp:
-	return -ENOTSUPP;
+	return -EOPNOTSUPP;
 }
 
 int mlx5_eswitch_add_vlan_action(struct mlx5_eswitch *esw,
@@ -270,11 +277,12 @@ out:
 	return err;
 }
 
-static struct mlx5_flow_rule *
+static struct mlx5_flow_handle *
 mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *esw, int vport, u32 sqn)
 {
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_destination dest;
-	struct mlx5_flow_rule *flow_rule;
+	struct mlx5_flow_handle *flow_rule;
 	struct mlx5_flow_spec *spec;
 	void *misc;
 
@@ -296,10 +304,10 @@ mlx5_eswitch_add_send_to_vport_rule(stru
 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
 	dest.vport_num = vport;
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 
-	flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec,
-				       MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				       0, &dest);
+	flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec,
+					&flow_act, &dest, 1);
 	if (IS_ERR(flow_rule))
 		esw_warn(esw->dev, "FDB: Failed to add send to vport rule err %ld\n", PTR_ERR(flow_rule));
 out:
@@ -316,7 +324,7 @@ void mlx5_eswitch_sqs2vport_stop(struct
 		return;
 
 	list_for_each_entry_safe(esw_sq, tmp, &rep->vport_sqs_list, list) {
-		mlx5_del_flow_rule(esw_sq->send_to_vport_rule);
+		mlx5_del_flow_rules(esw_sq->send_to_vport_rule);
 		list_del(&esw_sq->list);
 		kfree(esw_sq);
 	}
@@ -326,7 +334,7 @@ int mlx5_eswitch_sqs2vport_start(struct
 				 struct mlx5_eswitch_rep *rep,
 				 u16 *sqns_array, int sqns_num)
 {
-	struct mlx5_flow_rule *flow_rule;
+	struct mlx5_flow_handle *flow_rule;
 	struct mlx5_esw_sq *esw_sq;
 	int err;
 	int i;
@@ -362,8 +370,9 @@ out_err:
 
 static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw)
 {
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_destination dest;
-	struct mlx5_flow_rule *flow_rule = NULL;
+	struct mlx5_flow_handle *flow_rule = NULL;
 	struct mlx5_flow_spec *spec;
 	int err = 0;
 
@@ -376,10 +385,10 @@ static int esw_add_fdb_miss_rule(struct
 
 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
 	dest.vport_num = 0;
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 
-	flow_rule = mlx5_add_flow_rule(esw->fdb_table.offloads.fdb, spec,
-				       MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				       0, &dest);
+	flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.fdb, spec,
+					&flow_act, &dest, 1);
 	if (IS_ERR(flow_rule)) {
 		err = PTR_ERR(flow_rule);
 		esw_warn(esw->dev,  "FDB: Failed to add miss flow rule err %d\n", err);
@@ -406,6 +415,7 @@ static int esw_create_offloads_fdb_table
 	u32 *flow_group_in;
 	void *match_criteria;
 	int table_size, ix, err = 0;
+	u32 flags = 0;
 
 	flow_group_in = mlx5_vzalloc(inlen);
 	if (!flow_group_in)
@@ -414,15 +424,21 @@ static int esw_create_offloads_fdb_table
 	root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
 	if (!root_ns) {
 		esw_warn(dev, "Failed to get FDB flow namespace\n");
+		err = -EOPNOTSUPP;
 		goto ns_err;
 	}
 
 	esw_debug(dev, "Create offloads FDB table, log_max_size(%d)\n",
 		  MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
 
+	if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) &&
+	    MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
+		flags |= MLX5_FLOW_TABLE_TUNNEL_EN;
+
 	fdb = mlx5_create_auto_grouped_flow_table(root_ns, FDB_FAST_PATH,
 						  ESW_OFFLOADS_NUM_ENTRIES,
-						  ESW_OFFLOADS_NUM_GROUPS, 0);
+						  ESW_OFFLOADS_NUM_GROUPS, 0,
+						  flags);
 	if (IS_ERR(fdb)) {
 		err = PTR_ERR(fdb);
 		esw_warn(dev, "Failed to create Fast path FDB Table err %d\n", err);
@@ -431,7 +447,7 @@ static int esw_create_offloads_fdb_table
 	esw->fdb_table.fdb = fdb;
 
 	table_size = nvports + MAX_PF_SQ + 1;
-	fdb = mlx5_create_flow_table(root_ns, FDB_SLOW_PATH, table_size, 0);
+	fdb = mlx5_create_flow_table(root_ns, FDB_SLOW_PATH, table_size, 0, 0);
 	if (IS_ERR(fdb)) {
 		err = PTR_ERR(fdb);
 		esw_warn(dev, "Failed to create slow path FDB Table err %d\n", err);
@@ -502,7 +518,7 @@ static void esw_destroy_offloads_fdb_tab
 		return;
 
 	esw_debug(esw->dev, "Destroy offloads FDB Table\n");
-	mlx5_del_flow_rule(esw->fdb_table.offloads.miss_rule);
+	mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule);
 	mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
 	mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
 
@@ -520,10 +536,10 @@ static int esw_create_offloads_table(str
 	ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_OFFLOADS);
 	if (!ns) {
 		esw_warn(esw->dev, "Failed to get offloads flow namespace\n");
-		return -ENOMEM;
+		return -EOPNOTSUPP;
 	}
 
-	ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0);
+	ft_offloads = mlx5_create_flow_table(ns, 0, dev->priv.sriov.num_vfs + 2, 0, 0);
 	if (IS_ERR(ft_offloads)) {
 		err = PTR_ERR(ft_offloads);
 		esw_warn(esw->dev, "Failed to create offloads table, err %d\n", err);
@@ -586,11 +602,12 @@ static void esw_destroy_vport_rx_group(s
 	mlx5_destroy_flow_group(esw->offloads.vport_rx_group);
 }
 
-struct mlx5_flow_rule *
+struct mlx5_flow_handle *
 mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, int vport, u32 tirn)
 {
+	struct mlx5_flow_act flow_act = {0};
 	struct mlx5_flow_destination dest;
-	struct mlx5_flow_rule *flow_rule;
+	struct mlx5_flow_handle *flow_rule;
 	struct mlx5_flow_spec *spec;
 	void *misc;
 
@@ -611,9 +628,9 @@ mlx5_eswitch_create_vport_rx_rule(struct
 	dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
 	dest.tir_num = tirn;
 
-	flow_rule = mlx5_add_flow_rule(esw->offloads.ft_offloads, spec,
-				       MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
-				       0, &dest);
+	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+	flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec,
+				       &flow_act, &dest, 1);
 	if (IS_ERR(flow_rule)) {
 		esw_warn(esw->dev, "fs offloads: Failed to add vport rx rule err %ld\n", PTR_ERR(flow_rule));
 		goto out;
@@ -639,7 +656,15 @@ static int esw_offloads_start(struct mlx
 		esw_warn(esw->dev, "Failed setting eswitch to offloads, err %d\n", err);
 		err1 = mlx5_eswitch_enable_sriov(esw, num_vfs, SRIOV_LEGACY);
 		if (err1)
-			esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err);
+			esw_warn(esw->dev, "Failed setting eswitch back to legacy, err %d\n", err1);
+	}
+	if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) {
+		if (mlx5_eswitch_inline_mode_get(esw,
+						 num_vfs,
+						 &esw->offloads.inline_mode)) {
+			esw->offloads.inline_mode = MLX5_INLINE_MODE_L2;
+			esw_warn(esw->dev, "Inline mode is different between vports\n");
+		}
 	}
 	return err;
 }
@@ -650,9 +675,14 @@ int esw_offloads_init(struct mlx5_eswitc
 	int vport;
 	int err;
 
+	/* disable PF RoCE so missed packets don't go through RoCE steering */
+	mlx5_dev_list_lock();
+	mlx5_remove_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
+	mlx5_dev_list_unlock();
+
 	err = esw_create_offloads_fdb_table(esw, nvports);
 	if (err)
-		return err;
+		goto create_fdb_err;
 
 	err = esw_create_offloads_table(esw);
 	if (err)
@@ -671,6 +701,7 @@ int esw_offloads_init(struct mlx5_eswitc
 		if (err)
 			goto err_reps;
 	}
+
 	return 0;
 
 err_reps:
@@ -687,6 +718,13 @@ create_fg_err:
 
 create_ft_err:
 	esw_destroy_offloads_fdb_table(esw);
+
+create_fdb_err:
+	/* enable back PF RoCE */
+	mlx5_dev_list_lock();
+	mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
+	mlx5_dev_list_unlock();
+
 	return err;
 }
 
@@ -703,6 +741,11 @@ static int esw_offloads_stop(struct mlx5
 			esw_warn(esw->dev, "Failed setting eswitch back to offloads, err %d\n", err);
 	}
 
+	/* enable back PF RoCE */
+	mlx5_dev_list_lock();
+	mlx5_add_dev_by_protocol(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
+	mlx5_dev_list_unlock();
+
 	return err;
 }
 
@@ -755,6 +798,50 @@ static int esw_mode_to_devlink(u16 mlx5_
 	return 0;
 }
 
+static int esw_inline_mode_from_devlink(u8 mode, u8 *mlx5_mode)
+{
+	switch (mode) {
+	case DEVLINK_ESWITCH_INLINE_MODE_NONE:
+		*mlx5_mode = MLX5_INLINE_MODE_NONE;
+		break;
+	case DEVLINK_ESWITCH_INLINE_MODE_LINK:
+		*mlx5_mode = MLX5_INLINE_MODE_L2;
+		break;
+	case DEVLINK_ESWITCH_INLINE_MODE_NETWORK:
+		*mlx5_mode = MLX5_INLINE_MODE_IP;
+		break;
+	case DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT:
+		*mlx5_mode = MLX5_INLINE_MODE_TCP_UDP;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int esw_inline_mode_to_devlink(u8 mlx5_mode, u8 *mode)
+{
+	switch (mlx5_mode) {
+	case MLX5_INLINE_MODE_NONE:
+		*mode = DEVLINK_ESWITCH_INLINE_MODE_NONE;
+		break;
+	case MLX5_INLINE_MODE_L2:
+		*mode = DEVLINK_ESWITCH_INLINE_MODE_LINK;
+		break;
+	case MLX5_INLINE_MODE_IP:
+		*mode = DEVLINK_ESWITCH_INLINE_MODE_NETWORK;
+		break;
+	case MLX5_INLINE_MODE_TCP_UDP:
+		*mode = DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode)
 {
 	struct mlx5_core_dev *dev;
@@ -799,6 +886,95 @@ int mlx5_devlink_eswitch_mode_get(struct
 	return esw_mode_to_devlink(dev->priv.eswitch->mode, mode);
 }
 
+int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
+{
+	struct mlx5_core_dev *dev = devlink_priv(devlink);
+	struct mlx5_eswitch *esw = dev->priv.eswitch;
+	int num_vports = esw->enabled_vports;
+	int err;
+	int vport;
+	u8 mlx5_mode;
+
+	if (!MLX5_CAP_GEN(dev, vport_group_manager))
+		return -EOPNOTSUPP;
+
+	if (esw->mode == SRIOV_NONE)
+		return -EOPNOTSUPP;
+
+	if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
+	    MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
+		return -EOPNOTSUPP;
+
+	err = esw_inline_mode_from_devlink(mode, &mlx5_mode);
+	if (err)
+		goto out;
+
+	for (vport = 1; vport < num_vports; vport++) {
+		err = mlx5_modify_nic_vport_min_inline(dev, vport, mlx5_mode);
+		if (err) {
+			esw_warn(dev, "Failed to set min inline on vport %d\n",
+				 vport);
+			goto revert_inline_mode;
+		}
+	}
+
+	esw->offloads.inline_mode = mlx5_mode;
+	return 0;
+
+revert_inline_mode:
+	while (--vport > 0)
+		mlx5_modify_nic_vport_min_inline(dev,
+						 vport,
+						 esw->offloads.inline_mode);
+out:
+	return err;
+}
+
+int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
+{
+	struct mlx5_core_dev *dev = devlink_priv(devlink);
+	struct mlx5_eswitch *esw = dev->priv.eswitch;
+
+	if (!MLX5_CAP_GEN(dev, vport_group_manager))
+		return -EOPNOTSUPP;
+
+	if (esw->mode == SRIOV_NONE)
+		return -EOPNOTSUPP;
+
+	if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
+	    MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
+		return -EOPNOTSUPP;
+
+	return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
+}
+
+int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode)
+{
+	struct mlx5_core_dev *dev = esw->dev;
+	int vport;
+	u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
+
+	if (!MLX5_CAP_GEN(dev, vport_group_manager))
+		return -EOPNOTSUPP;
+
+	if (esw->mode == SRIOV_NONE)
+		return -EOPNOTSUPP;
+
+	if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
+	    MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
+		return -EOPNOTSUPP;
+
+	for (vport = 1; vport <= nvfs; vport++) {
+		mlx5_query_nic_vport_min_inline(dev, vport, &mlx5_mode);
+		if (vport > 1 && prev_mlx5_mode != mlx5_mode)
+			return -EINVAL;
+		prev_mlx5_mode = mlx5_mode;
+	}
+
+	*mode = mlx5_mode;
+	return 0;
+}
+
 void mlx5_eswitch_register_vport_rep(struct mlx5_eswitch *esw,
 				     int vport_index,
 				     struct mlx5_eswitch_rep *__rep)
@@ -813,7 +989,7 @@ void mlx5_eswitch_register_vport_rep(str
 	rep->load   = __rep->load;
 	rep->unload = __rep->unload;
 	rep->vport  = __rep->vport;
-	rep->priv_data = __rep->priv_data;
+	rep->netdev = __rep->netdev;
 	ether_addr_copy(rep->hw_id, __rep->hw_id);
 
 	INIT_LIST_HEAD(&rep->vport_sqs_list);
@@ -833,3 +1009,13 @@ void mlx5_eswitch_unregister_vport_rep(s
 
 	rep->valid = false;
 }
+
+struct net_device *mlx5_eswitch_get_uplink_netdev(struct mlx5_eswitch *esw)
+{
+#define UPLINK_REP_INDEX 0
+	struct mlx5_esw_offload *offloads = &esw->offloads;
+	struct mlx5_eswitch_rep *rep;
+
+	rep = &offloads->vport_reps[UPLINK_REP_INDEX];
+	return rep->netdev;
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@
 #include "fs_core.h"
 #include "fs_cmd.h"
 #include "mlx5_core.h"
+#include "eswitch.h"
 
 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
 			    struct mlx5_flow_table *ft)
@@ -61,8 +62,9 @@ int mlx5_cmd_create_flow_table(struct ml
 			       enum fs_flow_table_op_mod op_mod,
 			       enum fs_flow_table_type type, unsigned int level,
 			       unsigned int log_size, struct mlx5_flow_table
-			       *next_ft, unsigned int *table_id)
+			       *next_ft, unsigned int *table_id, u32 flags)
 {
+	int en_encap_decap = !!(flags & MLX5_FLOW_TABLE_TUNNEL_EN);
 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)]   = {0};
 	int err;
@@ -78,6 +80,9 @@ int mlx5_cmd_create_flow_table(struct ml
 		MLX5_SET(create_flow_table_in, in, other_vport, 1);
 	}
 
+	MLX5_SET(create_flow_table_in, in, decap_en, en_encap_decap);
+	MLX5_SET(create_flow_table_in, in, encap_en, en_encap_decap);
+
 	switch (op_mod) {
 	case FS_FT_OP_MOD_NORMAL:
 		if (next_ft) {
@@ -243,6 +248,7 @@ static int mlx5_cmd_set_fte(struct mlx5_
 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
 	MLX5_SET(flow_context, in_flow_context, flow_tag, fte->flow_tag);
 	MLX5_SET(flow_context, in_flow_context, action, fte->action);
+	MLX5_SET(flow_context, in_flow_context, encap_id, fte->encap_id);
 	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
 				      match_value);
 	memcpy(in_match_value, &fte->val, MLX5_ST_SZ_BYTES(fte_match_param));
@@ -316,7 +322,7 @@ int mlx5_cmd_update_fte(struct mlx5_core
 						flow_table_properties_nic_receive.
 						flow_modify_en);
 	if (!atomic_mod_cap)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	opmod = 1;
 
 	return	mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, group_id, fte);
@@ -453,27 +459,32 @@ void mlx5_cmd_fc_bulk_get(struct mlx5_co
 	*bytes = MLX5_GET64(traffic_counter, stats, octets);
 }
 
-#define MAX_ENCAP_SIZE (128)
-
-int mlx5_cmd_alloc_encap(struct mlx5_core_dev *dev,
-			 int header_type,
-			 size_t size,
-			 void *encap_header,
-			 u32 *encap_id)
+int mlx5_encap_alloc(struct mlx5_core_dev *dev,
+		     int header_type,
+		     size_t size,
+		     void *encap_header,
+		     u32 *encap_id)
 {
+	int max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size);
 	u32 out[MLX5_ST_SZ_DW(alloc_encap_header_out)];
-	u32 in[MLX5_ST_SZ_DW(alloc_encap_header_in) +
-	      (MAX_ENCAP_SIZE / sizeof(u32))];
-	void *encap_header_in = MLX5_ADDR_OF(alloc_encap_header_in, in,
-					     encap_header);
-	void *header = MLX5_ADDR_OF(encap_header_in, encap_header_in,
-				    encap_header);
-	int inlen = header - (void *)in  + size;
+	void *encap_header_in;
+	void *header;
+	int inlen;
 	int err;
+	u32 *in;
 
-	if (size > MAX_ENCAP_SIZE)
+	if (size > MLX5_CAP_ESW(dev, max_encap_header_size))
 		return -EINVAL;
 
+	in = kzalloc(MLX5_ST_SZ_BYTES(alloc_encap_header_in) + max_encap_size,
+		     GFP_KERNEL);
+	if (!in)
+		return -ENOMEM;
+
+	encap_header_in = MLX5_ADDR_OF(alloc_encap_header_in, in, encap_header);
+	header = MLX5_ADDR_OF(encap_header_in, encap_header_in, encap_header);
+	inlen = header - (void *)in  + size;
+
 	memset(in, 0, inlen);
 	MLX5_SET(alloc_encap_header_in, in, opcode,
 		 MLX5_CMD_OP_ALLOC_ENCAP_HEADER);
@@ -485,10 +496,11 @@ int mlx5_cmd_alloc_encap(struct mlx5_cor
 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
 
 	*encap_id = MLX5_GET(alloc_encap_header_out, out, encap_id);
+	kfree(in);
 	return err;
 }
 
-void mlx5_cmd_dealloc_encap(struct mlx5_core_dev *dev, u32 encap_id)
+void mlx5_encap_dealloc(struct mlx5_core_dev *dev, u32 encap_id)
 {
 	u32 in[MLX5_ST_SZ_DW(dealloc_encap_header_in)];
 	u32 out[MLX5_ST_SZ_DW(dealloc_encap_header_out)];
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h	2017-02-12 16:03:20.000000000 -0500
@@ -38,7 +38,7 @@ int mlx5_cmd_create_flow_table(struct ml
 			       enum fs_flow_table_op_mod op_mod,
 			       enum fs_flow_table_type type, unsigned int level,
 			       unsigned int log_size, struct mlx5_flow_table
-			       *next_ft, unsigned int *table_id);
+			       *next_ft, unsigned int *table_id, u32 flags);
 
 int mlx5_cmd_destroy_flow_table(struct mlx5_core_dev *dev,
 				struct mlx5_flow_table *ft);
@@ -89,11 +89,4 @@ void mlx5_cmd_fc_bulk_get(struct mlx5_co
 			  struct mlx5_cmd_fc_bulk *b, u16 id,
 			  u64 *packets, u64 *bytes);
 
-int mlx5_cmd_alloc_encap(struct mlx5_core_dev *dev,
-			 int header_type,
-			 size_t size,
-			 void *encap_header,
-			 u32 *encap_id);
-void mlx5_cmd_dealloc_encap(struct mlx5_core_dev *dev, u32 encap_id);
-
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c	2017-02-12 16:03:20.000000000 -0500
@@ -153,6 +153,11 @@ static void del_rule(struct fs_node *nod
 static void del_flow_table(struct fs_node *node);
 static void del_flow_group(struct fs_node *node);
 static void del_fte(struct fs_node *node);
+static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+				struct mlx5_flow_destination *d2);
+static struct mlx5_flow_rule *
+find_flow_rule(struct fs_fte *fte,
+	       struct mlx5_flow_destination *dest);
 
 static void tree_init_node(struct fs_node *node,
 			   unsigned int refcount,
@@ -369,6 +374,7 @@ static void del_rule(struct fs_node *nod
 	struct mlx5_core_dev *dev = get_dev(node);
 	int match_len = MLX5_ST_SZ_BYTES(fte_match_param);
 	int err;
+	bool update_fte = false;
 
 	match_value = mlx5_vzalloc(match_len);
 	if (!match_value) {
@@ -387,13 +393,23 @@ static void del_rule(struct fs_node *nod
 		list_del(&rule->next_ft);
 		mutex_unlock(&rule->dest_attr.ft->lock);
 	}
+
+	if (rule->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER  &&
+	    --fte->dests_size) {
+		modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
+		fte->action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
+		update_fte = true;
+		goto out;
+	}
+
 	if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
 	    --fte->dests_size) {
 		modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST),
-		err = mlx5_cmd_update_fte(dev, ft,
-					  fg->id,
-					  modify_mask,
-					  fte);
+		update_fte = true;
+	}
+out:
+	if (update_fte && fte->dests_size) {
+		err = mlx5_cmd_update_fte(dev, ft, fg->id, modify_mask, fte);
 		if (err)
 			mlx5_core_warn(dev,
 				       "%s can't del rule fg id=%d fte_index=%d\n",
@@ -444,8 +460,7 @@ static void del_flow_group(struct fs_nod
 			       fg->id, ft->id);
 }
 
-static struct fs_fte *alloc_fte(u8 action,
-				u32 flow_tag,
+static struct fs_fte *alloc_fte(struct mlx5_flow_act *flow_act,
 				u32 *match_value,
 				unsigned int index)
 {
@@ -457,9 +472,10 @@ static struct fs_fte *alloc_fte(u8 actio
 
 	memcpy(fte->val, match_value, sizeof(fte->val));
 	fte->node.type =  FS_TYPE_FLOW_ENTRY;
-	fte->flow_tag = flow_tag;
+	fte->flow_tag = flow_act->flow_tag;
 	fte->index = index;
-	fte->action = action;
+	fte->action = flow_act->action;
+	fte->encap_id = flow_act->encap_id;
 
 	return fte;
 }
@@ -489,7 +505,8 @@ static struct mlx5_flow_group *alloc_flo
 
 static struct mlx5_flow_table *alloc_flow_table(int level, u16 vport, int max_fte,
 						enum fs_flow_table_type table_type,
-						enum fs_flow_table_op_mod op_mod)
+						enum fs_flow_table_op_mod op_mod,
+						u32 flags)
 {
 	struct mlx5_flow_table *ft;
 
@@ -503,6 +520,7 @@ static struct mlx5_flow_table *alloc_flo
 	ft->type = table_type;
 	ft->vport = vport;
 	ft->max_fte = max_fte;
+	ft->flags = flags;
 	INIT_LIST_HEAD(&ft->fwd_rules);
 	mutex_init(&ft->lock);
 
@@ -641,8 +659,8 @@ static int update_root_ft_create(struct
 	return err;
 }
 
-int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
-				 struct mlx5_flow_destination *dest)
+static int _mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
+					 struct mlx5_flow_destination *dest)
 {
 	struct mlx5_flow_table *ft;
 	struct mlx5_flow_group *fg;
@@ -667,6 +685,28 @@ int mlx5_modify_rule_destination(struct
 	return err;
 }
 
+int mlx5_modify_rule_destination(struct mlx5_flow_handle *handle,
+				 struct mlx5_flow_destination *new_dest,
+				 struct mlx5_flow_destination *old_dest)
+{
+	int i;
+
+	if (!old_dest) {
+		if (handle->num_rules != 1)
+			return -EINVAL;
+		return _mlx5_modify_rule_destination(handle->rule[0],
+						     new_dest);
+	}
+
+	for (i = 0; i < handle->num_rules; i++) {
+		if (mlx5_flow_dests_cmp(new_dest, &handle->rule[i]->dest_attr))
+			return _mlx5_modify_rule_destination(handle->rule[i],
+							     new_dest);
+	}
+
+	return -EINVAL;
+}
+
 /* Modify/set FWD rules that point on old_next_ft to point on new_next_ft  */
 static int connect_fwd_rules(struct mlx5_core_dev *dev,
 			     struct mlx5_flow_table *new_next_ft,
@@ -689,7 +729,7 @@ static int connect_fwd_rules(struct mlx5
 	list_splice_init(&old_next_ft->fwd_rules, &new_next_ft->fwd_rules);
 	mutex_unlock(&old_next_ft->lock);
 	list_for_each_entry(iter, &new_next_ft->fwd_rules, next_ft) {
-		err = mlx5_modify_rule_destination(iter, &dest);
+		err = _mlx5_modify_rule_destination(iter, &dest);
 		if (err)
 			pr_err("mlx5_core: failed to modify rule to point on flow table %d\n",
 			       new_next_ft->id);
@@ -739,7 +779,8 @@ static void list_add_flow_table(struct m
 static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
 							enum fs_flow_table_op_mod op_mod,
 							u16 vport, int prio,
-							int max_fte, u32 level)
+							int max_fte, u32 level,
+							u32 flags)
 {
 	struct mlx5_flow_table *next_ft = NULL;
 	struct mlx5_flow_table *ft;
@@ -772,7 +813,7 @@ static struct mlx5_flow_table *__mlx5_cr
 			      vport,
 			      max_fte ? roundup_pow_of_two(max_fte) : 0,
 			      root->table_type,
-			      op_mod);
+			      op_mod, flags);
 	if (!ft) {
 		err = -ENOMEM;
 		goto unlock_root;
@@ -782,7 +823,8 @@ static struct mlx5_flow_table *__mlx5_cr
 	log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
 	next_ft = find_next_chained_ft(fs_prio);
 	err = mlx5_cmd_create_flow_table(root->dev, ft->vport, ft->op_mod, ft->type,
-					 ft->level, log_table_sz, next_ft, &ft->id);
+					 ft->level, log_table_sz, next_ft, &ft->id,
+					 ft->flags);
 	if (err)
 		goto free_ft;
 
@@ -807,10 +849,11 @@ unlock_root:
 
 struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
 					       int prio, int max_fte,
-					       u32 level)
+					       u32 level,
+					       u32 flags)
 {
 	return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, 0, prio,
-					max_fte, level);
+					max_fte, level, flags);
 }
 
 struct mlx5_flow_table *mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns,
@@ -818,7 +861,7 @@ struct mlx5_flow_table *mlx5_create_vpor
 						     u32 level, u16 vport)
 {
 	return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_NORMAL, vport, prio,
-					max_fte, level);
+					max_fte, level, 0);
 }
 
 struct mlx5_flow_table *mlx5_create_lag_demux_flow_table(
@@ -826,7 +869,7 @@ struct mlx5_flow_table *mlx5_create_lag_
 					       int prio, u32 level)
 {
 	return __mlx5_create_flow_table(ns, FS_FT_OP_MOD_LAG_DEMUX, 0, prio, 0,
-					level);
+					level, 0);
 }
 EXPORT_SYMBOL(mlx5_create_lag_demux_flow_table);
 
@@ -834,14 +877,15 @@ struct mlx5_flow_table *mlx5_create_auto
 							    int prio,
 							    int num_flow_table_entries,
 							    int max_num_groups,
-							    u32 level)
+							    u32 level,
+							    u32 flags)
 {
 	struct mlx5_flow_table *ft;
 
 	if (max_num_groups > num_flow_table_entries)
 		return ERR_PTR(-EINVAL);
 
-	ft = mlx5_create_flow_table(ns, prio, num_flow_table_entries, level);
+	ft = mlx5_create_flow_table(ns, prio, num_flow_table_entries, level, flags);
 	if (IS_ERR(ft))
 		return ft;
 
@@ -918,55 +962,133 @@ static struct mlx5_flow_rule *alloc_rule
 	return rule;
 }
 
+static struct mlx5_flow_handle *alloc_handle(int num_rules)
+{
+	struct mlx5_flow_handle *handle;
+
+	handle = kzalloc(sizeof(*handle) + sizeof(handle->rule[0]) *
+			  num_rules, GFP_KERNEL);
+	if (!handle)
+		return NULL;
+
+	handle->num_rules = num_rules;
+
+	return handle;
+}
+
+static void destroy_flow_handle(struct fs_fte *fte,
+				struct mlx5_flow_handle *handle,
+				struct mlx5_flow_destination *dest,
+				int i)
+{
+	for (; --i >= 0;) {
+		if (atomic_dec_and_test(&handle->rule[i]->node.refcount)) {
+			fte->dests_size--;
+			list_del(&handle->rule[i]->node.list);
+			kfree(handle->rule[i]);
+		}
+	}
+	kfree(handle);
+}
+
+static struct mlx5_flow_handle *
+create_flow_handle(struct fs_fte *fte,
+		   struct mlx5_flow_destination *dest,
+		   int dest_num,
+		   int *modify_mask,
+		   bool *new_rule)
+{
+	struct mlx5_flow_handle *handle;
+	struct mlx5_flow_rule *rule = NULL;
+	static int count = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
+	static int dst = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
+	int type;
+	int i = 0;
+
+	handle = alloc_handle((dest_num) ? dest_num : 1);
+	if (!handle)
+		return ERR_PTR(-ENOMEM);
+
+	do {
+		if (dest) {
+			rule = find_flow_rule(fte, dest + i);
+			if (rule) {
+				atomic_inc(&rule->node.refcount);
+				goto rule_found;
+			}
+		}
+
+		*new_rule = true;
+		rule = alloc_rule(dest + i);
+		if (!rule)
+			goto free_rules;
+
+		/* Add dest to dests list- we need flow tables to be in the
+		 * end of the list for forward to next prio rules.
+		 */
+		tree_init_node(&rule->node, 1, del_rule);
+		if (dest &&
+		    dest[i].type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
+			list_add(&rule->node.list, &fte->node.children);
+		else
+			list_add_tail(&rule->node.list, &fte->node.children);
+		if (dest) {
+			fte->dests_size++;
+
+			type = dest[i].type ==
+				MLX5_FLOW_DESTINATION_TYPE_COUNTER;
+			*modify_mask |= type ? count : dst;
+		}
+rule_found:
+		handle->rule[i] = rule;
+	} while (++i < dest_num);
+
+	return handle;
+
+free_rules:
+	destroy_flow_handle(fte, handle, dest, i);
+	return ERR_PTR(-ENOMEM);
+}
+
 /* fte should not be deleted while calling this function */
-static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte,
-					   struct mlx5_flow_group *fg,
-					   struct mlx5_flow_destination *dest)
+static struct mlx5_flow_handle *
+add_rule_fte(struct fs_fte *fte,
+	     struct mlx5_flow_group *fg,
+	     struct mlx5_flow_destination *dest,
+	     int dest_num,
+	     bool update_action)
 {
+	struct mlx5_flow_handle *handle;
 	struct mlx5_flow_table *ft;
-	struct mlx5_flow_rule *rule;
 	int modify_mask = 0;
 	int err;
+	bool new_rule = false;
 
-	rule = alloc_rule(dest);
-	if (!rule)
-		return ERR_PTR(-ENOMEM);
-
-	fs_get_obj(ft, fg->node.parent);
-	/* Add dest to dests list- we need flow tables to be in the
-	 * end of the list for forward to next prio rules.
-	 */
-	tree_init_node(&rule->node, 1, del_rule);
-	if (dest && dest->type != MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE)
-		list_add(&rule->node.list, &fte->node.children);
-	else
-		list_add_tail(&rule->node.list, &fte->node.children);
-	if (dest) {
-		fte->dests_size++;
+	handle = create_flow_handle(fte, dest, dest_num, &modify_mask,
+				    &new_rule);
+	if (IS_ERR(handle) || !new_rule)
+		goto out;
 
-		modify_mask |= dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ?
-			BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS) :
-			BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
-	}
+	if (update_action)
+		modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
 
-	if (fte->dests_size == 1 || !dest)
+	fs_get_obj(ft, fg->node.parent);
+	if (!(fte->status & FS_FTE_STATUS_EXISTING))
 		err = mlx5_cmd_create_fte(get_dev(&ft->node),
 					  ft, fg->id, fte);
 	else
 		err = mlx5_cmd_update_fte(get_dev(&ft->node),
 					  ft, fg->id, modify_mask, fte);
 	if (err)
-		goto free_rule;
+		goto free_handle;
 
 	fte->status |= FS_FTE_STATUS_EXISTING;
 
-	return rule;
+out:
+	return handle;
 
-free_rule:
-	list_del(&rule->node.list);
-	kfree(rule);
-	if (dest)
-		fte->dests_size--;
+free_handle:
+	destroy_flow_handle(fte, handle, dest, handle->num_rules);
 	return ERR_PTR(err);
 }
 
@@ -995,15 +1117,14 @@ static unsigned int get_free_fte_index(s
 /* prev is output, prev->next = new_fte */
 static struct fs_fte *create_fte(struct mlx5_flow_group *fg,
 				 u32 *match_value,
-				 u8 action,
-				 u32 flow_tag,
+				 struct mlx5_flow_act *flow_act,
 				 struct list_head **prev)
 {
 	struct fs_fte *fte;
 	int index;
 
 	index = get_free_fte_index(fg, prev);
-	fte = alloc_fte(action, flow_tag, match_value, index);
+	fte = alloc_fte(flow_act, match_value, index);
 	if (IS_ERR(fte))
 		return fte;
 
@@ -1067,71 +1188,82 @@ out:
 	return fg;
 }
 
+static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+				struct mlx5_flow_destination *d2)
+{
+	if (d1->type == d2->type) {
+		if ((d1->type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
+		     d1->vport_num == d2->vport_num) ||
+		    (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
+		     d1->ft == d2->ft) ||
+		    (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
+		     d1->tir_num == d2->tir_num))
+			return true;
+	}
+
+	return false;
+}
+
 static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte,
 					     struct mlx5_flow_destination *dest)
 {
 	struct mlx5_flow_rule *rule;
 
 	list_for_each_entry(rule, &fte->node.children, node.list) {
-		if (rule->dest_attr.type == dest->type) {
-			if ((dest->type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
-			     dest->vport_num == rule->dest_attr.vport_num) ||
-			    (dest->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
-			     dest->ft == rule->dest_attr.ft) ||
-			    (dest->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
-			     dest->tir_num == rule->dest_attr.tir_num))
-				return rule;
-		}
+		if (mlx5_flow_dests_cmp(&rule->dest_attr, dest))
+			return rule;
 	}
 	return NULL;
 }
 
-static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg,
-					  u32 *match_value,
-					  u8 action,
-					  u32 flow_tag,
-					  struct mlx5_flow_destination *dest)
+static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
+					    u32 *match_value,
+					    struct mlx5_flow_act *flow_act,
+					    struct mlx5_flow_destination *dest,
+					    int dest_num)
 {
-	struct fs_fte *fte;
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *handle;
 	struct mlx5_flow_table *ft;
 	struct list_head *prev;
+	struct fs_fte *fte;
+	int i;
 
 	nested_lock_ref_node(&fg->node, FS_MUTEX_PARENT);
 	fs_for_each_fte(fte, fg) {
 		nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
 		if (compare_match_value(&fg->mask, match_value, &fte->val) &&
-		    action == fte->action && flow_tag == fte->flow_tag) {
-			rule = find_flow_rule(fte, dest);
-			if (rule) {
-				atomic_inc(&rule->node.refcount);
-				unlock_ref_node(&fte->node);
-				unlock_ref_node(&fg->node);
-				return rule;
+		    (flow_act->action & fte->action) &&
+		    flow_act->flow_tag == fte->flow_tag) {
+			int old_action = fte->action;
+
+			fte->action |= flow_act->action;
+			handle = add_rule_fte(fte, fg, dest, dest_num,
+					      old_action != flow_act->action);
+			if (IS_ERR(handle)) {
+				fte->action = old_action;
+				goto unlock_fte;
+			} else {
+				goto add_rules;
 			}
-			rule = add_rule_fte(fte, fg, dest);
-			unlock_ref_node(&fte->node);
-			if (IS_ERR(rule))
-				goto unlock_fg;
-			else
-				goto add_rule;
 		}
 		unlock_ref_node(&fte->node);
 	}
 	fs_get_obj(ft, fg->node.parent);
 	if (fg->num_ftes >= fg->max_ftes) {
-		rule = ERR_PTR(-ENOSPC);
+		handle = ERR_PTR(-ENOSPC);
 		goto unlock_fg;
 	}
 
-	fte = create_fte(fg, match_value, action, flow_tag, &prev);
+	fte = create_fte(fg, match_value, flow_act, &prev);
 	if (IS_ERR(fte)) {
-		rule = (void *)fte;
+		handle = (void *)fte;
 		goto unlock_fg;
 	}
 	tree_init_node(&fte->node, 0, del_fte);
-	rule = add_rule_fte(fte, fg, dest);
-	if (IS_ERR(rule)) {
+	nested_lock_ref_node(&fte->node, FS_MUTEX_CHILD);
+	handle = add_rule_fte(fte, fg, dest, dest_num, false);
+	if (IS_ERR(handle)) {
+		unlock_ref_node(&fte->node);
 		kfree(fte);
 		goto unlock_fg;
 	}
@@ -1140,19 +1272,24 @@ static struct mlx5_flow_rule *add_rule_f
 
 	tree_add_node(&fte->node, &fg->node);
 	list_add(&fte->node.list, prev);
-add_rule:
-	tree_add_node(&rule->node, &fte->node);
+add_rules:
+	for (i = 0; i < handle->num_rules; i++) {
+		if (atomic_read(&handle->rule[i]->node.refcount) == 1)
+			tree_add_node(&handle->rule[i]->node, &fte->node);
+	}
+unlock_fte:
+	unlock_ref_node(&fte->node);
 unlock_fg:
 	unlock_ref_node(&fg->node);
-	return rule;
+	return handle;
 }
 
-struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule)
+struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_handle *handle)
 {
 	struct mlx5_flow_rule *dst;
 	struct fs_fte *fte;
 
-	fs_get_obj(fte, rule->node.parent);
+	fs_get_obj(fte, handle->rule[0]->node.parent);
 
 	fs_for_each_dst(dst, fte) {
 		if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
@@ -1170,8 +1307,8 @@ static bool counter_is_valid(struct mlx5
 	if (!counter)
 		return false;
 
-	/* Hardware support counter for a drop action only */
-	return action == (MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT);
+	return (action & (MLX5_FLOW_CONTEXT_ACTION_DROP |
+			  MLX5_FLOW_CONTEXT_ACTION_FWD_DEST));
 }
 
 static bool dest_is_valid(struct mlx5_flow_destination *dest,
@@ -1191,18 +1328,22 @@ static bool dest_is_valid(struct mlx5_fl
 	return true;
 }
 
-static struct mlx5_flow_rule *
-_mlx5_add_flow_rule(struct mlx5_flow_table *ft,
-		   struct mlx5_flow_spec *spec,
-		    u32 action,
-		    u32 flow_tag,
-		    struct mlx5_flow_destination *dest)
+static struct mlx5_flow_handle *
+_mlx5_add_flow_rules(struct mlx5_flow_table *ft,
+		     struct mlx5_flow_spec *spec,
+		     struct mlx5_flow_act *flow_act,
+		     struct mlx5_flow_destination *dest,
+		     int dest_num)
+
 {
 	struct mlx5_flow_group *g;
-	struct mlx5_flow_rule *rule;
+	struct mlx5_flow_handle *rule;
+	int i;
 
-	if (!dest_is_valid(dest, action, ft))
-		return ERR_PTR(-EINVAL);
+	for (i = 0; i < dest_num; i++) {
+		if (!dest_is_valid(&dest[i], flow_act->action, ft))
+			return ERR_PTR(-EINVAL);
+	}
 
 	nested_lock_ref_node(&ft->node, FS_MUTEX_GRANDPARENT);
 	fs_for_each_fg(g, ft)
@@ -1211,7 +1352,7 @@ _mlx5_add_flow_rule(struct mlx5_flow_tab
 					   g->mask.match_criteria,
 					   spec->match_criteria)) {
 			rule = add_rule_fg(g, spec->match_value,
-					   action, flow_tag, dest);
+					   flow_act, dest, dest_num);
 			if (!IS_ERR(rule) || PTR_ERR(rule) != -ENOSPC)
 				goto unlock;
 		}
@@ -1223,8 +1364,7 @@ _mlx5_add_flow_rule(struct mlx5_flow_tab
 		goto unlock;
 	}
 
-	rule = add_rule_fg(g, spec->match_value,
-			   action, flow_tag, dest);
+	rule = add_rule_fg(g, spec->match_value, flow_act, dest, dest_num);
 	if (IS_ERR(rule)) {
 		/* Remove assumes refcount > 0 and autogroup creates a group
 		 * with a refcount = 0.
@@ -1245,22 +1385,22 @@ static bool fwd_next_prio_supported(stru
 		(MLX5_CAP_FLOWTABLE(get_dev(&ft->node), nic_rx_multi_path_tirs)));
 }
 
-struct mlx5_flow_rule *
-mlx5_add_flow_rule(struct mlx5_flow_table *ft,
-		   struct mlx5_flow_spec *spec,
-		   u32 action,
-		   u32 flow_tag,
-		   struct mlx5_flow_destination *dest)
+struct mlx5_flow_handle *
+mlx5_add_flow_rules(struct mlx5_flow_table *ft,
+		    struct mlx5_flow_spec *spec,
+		    struct mlx5_flow_act *flow_act,
+		    struct mlx5_flow_destination *dest,
+		    int dest_num)
 {
 	struct mlx5_flow_root_namespace *root = find_root(&ft->node);
 	struct mlx5_flow_destination gen_dest;
 	struct mlx5_flow_table *next_ft = NULL;
-	struct mlx5_flow_rule *rule = NULL;
-	u32 sw_action = action;
+	struct mlx5_flow_handle *handle = NULL;
+	u32 sw_action = flow_act->action;
 	struct fs_prio *prio;
 
 	fs_get_obj(prio, ft->node.parent);
-	if (action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
+	if (flow_act->action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
 		if (!fwd_next_prio_supported(ft))
 			return ERR_PTR(-EOPNOTSUPP);
 		if (dest)
@@ -1271,34 +1411,40 @@ mlx5_add_flow_rule(struct mlx5_flow_tabl
 			gen_dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
 			gen_dest.ft = next_ft;
 			dest = &gen_dest;
-			action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+			dest_num = 1;
+			flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 		} else {
 			mutex_unlock(&root->chain_lock);
 			return ERR_PTR(-EOPNOTSUPP);
 		}
 	}
 
-	rule = _mlx5_add_flow_rule(ft, spec, action, flow_tag, dest);
+	handle = _mlx5_add_flow_rules(ft, spec, flow_act, dest, dest_num);
 
 	if (sw_action == MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO) {
-		if (!IS_ERR_OR_NULL(rule) &&
-		    (list_empty(&rule->next_ft))) {
+		if (!IS_ERR_OR_NULL(handle) &&
+		    (list_empty(&handle->rule[0]->next_ft))) {
 			mutex_lock(&next_ft->lock);
-			list_add(&rule->next_ft, &next_ft->fwd_rules);
+			list_add(&handle->rule[0]->next_ft,
+				 &next_ft->fwd_rules);
 			mutex_unlock(&next_ft->lock);
-			rule->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
+			handle->rule[0]->sw_action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
 		}
 		mutex_unlock(&root->chain_lock);
 	}
-	return rule;
+	return handle;
 }
-EXPORT_SYMBOL(mlx5_add_flow_rule);
+EXPORT_SYMBOL(mlx5_add_flow_rules);
 
-void mlx5_del_flow_rule(struct mlx5_flow_rule *rule)
+void mlx5_del_flow_rules(struct mlx5_flow_handle *handle)
 {
-	tree_remove_node(&rule->node);
+	int i;
+
+	for (i = handle->num_rules - 1; i >= 0; i--)
+		tree_remove_node(&handle->rule[i]->node);
+	kfree(handle);
 }
-EXPORT_SYMBOL(mlx5_del_flow_rule);
+EXPORT_SYMBOL(mlx5_del_flow_rules);
 
 /* Assuming prio->node.children(flow tables) is sorted by level */
 static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
@@ -1676,9 +1822,9 @@ static int create_anchor_flow_table(stru
 	struct mlx5_flow_table *ft;
 
 	ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
-	if (!ns)
+	if (WARN_ON(!ns))
 		return -EINVAL;
-	ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL);
+	ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL, 0);
 	if (IS_ERR(ft)) {
 		mlx5_core_err(steering->dev, "Failed to create last anchor flow table");
 		return PTR_ERR(ft);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h	2017-02-12 16:03:20.000000000 -0500
@@ -94,6 +94,11 @@ struct mlx5_flow_rule {
 	u32					sw_action;
 };
 
+struct mlx5_flow_handle {
+	int num_rules;
+	struct mlx5_flow_rule *rule[];
+};
+
 /* Type of children is mlx5_flow_group */
 struct mlx5_flow_table {
 	struct fs_node			node;
@@ -112,6 +117,7 @@ struct mlx5_flow_table {
 	struct mutex			lock;
 	/* FWD rules that point on this flow table */
 	struct list_head		fwd_rules;
+	u32				flags;
 };
 
 struct mlx5_fc_cache {
@@ -145,6 +151,7 @@ struct fs_fte {
 	u32				flow_tag;
 	u32				index;
 	u32				action;
+	u32				encap_id;
 	enum fs_fte_status		status;
 	struct mlx5_fc			*counter;
 };
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c	2017-02-12 16:03:20.000000000 -0500
@@ -75,7 +75,7 @@ static void mlx5_fc_stats_insert(struct
 	struct rb_node *parent = NULL;
 
 	while (*new) {
-		struct mlx5_fc *this = container_of(*new, struct mlx5_fc, node);
+		struct mlx5_fc *this = rb_entry(*new, struct mlx5_fc, node);
 		int result = counter->id - this->id;
 
 		parent = *new;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -14,7 +14,7 @@ config MLX5_CORE
 config MLX5_CORE_EN
 	bool "Mellanox Technologies ConnectX-4 Ethernet support"
 	depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
-	select PTP_1588_CLOCK
+	imply PTP_1588_CLOCK
 	default n
 	---help---
 	  Ethernet support in Mellanox Technologies ConnectX-4 NIC.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/main.c	2017-02-12 16:03:20.000000000 -0500
@@ -174,6 +174,41 @@ static int wait_fw_init(struct mlx5_core
 	return err;
 }
 
+static void mlx5_set_driver_version(struct mlx5_core_dev *dev)
+{
+	int driver_ver_sz = MLX5_FLD_SZ_BYTES(set_driver_version_in,
+					      driver_version);
+	u8 in[MLX5_ST_SZ_BYTES(set_driver_version_in)] = {0};
+	u8 out[MLX5_ST_SZ_BYTES(set_driver_version_out)] = {0};
+	int remaining_size = driver_ver_sz;
+	char *string;
+
+	if (!MLX5_CAP_GEN(dev, driver_version))
+		return;
+
+	string = MLX5_ADDR_OF(set_driver_version_in, in, driver_version);
+
+	strncpy(string, "Linux", remaining_size);
+
+	remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+	strncat(string, ",", remaining_size);
+
+	remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+	strncat(string, DRIVER_NAME, remaining_size);
+
+	remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+	strncat(string, ",", remaining_size);
+
+	remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
+	strncat(string, DRIVER_VERSION, remaining_size);
+
+	/*Send the command*/
+	MLX5_SET(set_driver_version_in, in, opcode,
+		 MLX5_CMD_OP_SET_DRIVER_VERSION);
+
+	mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
 static int set_dma_caps(struct pci_dev *pdev)
 {
 	int err;
@@ -468,6 +503,13 @@ static int handle_hca_cap(struct mlx5_co
 	MLX5_SET(cmd_hca_cap, set_hca_cap, pkey_table_size,
 		 to_fw_pkey_sz(dev, 128));
 
+	/* Check log_max_qp from HCA caps to set in current profile */
+	if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < profile[prof_sel].log_max_qp) {
+		mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n",
+			       profile[prof_sel].log_max_qp,
+			       MLX5_CAP_GEN_MAX(dev, log_max_qp));
+		profile[prof_sel].log_max_qp = MLX5_CAP_GEN_MAX(dev, log_max_qp);
+	}
 	if (prof->mask & MLX5_PROF_MASK_QP_SIZE)
 		MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_qp,
 			 prof->log_max_qp);
@@ -522,7 +564,7 @@ int mlx5_core_disable_hca(struct mlx5_co
 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
 
-cycle_t mlx5_read_internal_timer(struct mlx5_core_dev *dev)
+u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev)
 {
 	u32 timer_h, timer_h1, timer_l;
 
@@ -532,7 +574,7 @@ cycle_t mlx5_read_internal_timer(struct
 	if (timer_h != timer_h1) /* wrap around */
 		timer_l = ioread32be(&dev->iseg->internal_timer_l);
 
-	return (cycle_t)timer_l | (cycle_t)timer_h1 << 32;
+	return (u64)timer_l | (u64)timer_h1 << 32;
 }
 
 static int mlx5_irq_set_affinity_hint(struct mlx5_core_dev *mdev, int i)
@@ -540,7 +582,6 @@ static int mlx5_irq_set_affinity_hint(st
 	struct mlx5_priv *priv  = &mdev->priv;
 	struct msix_entry *msix = priv->msix_arr;
 	int irq                 = msix[i + MLX5_EQ_VEC_COMP_BASE].vector;
-	int numa_node           = priv->numa_node;
 	int err;
 
 	if (!zalloc_cpumask_var(&priv->irq_info[i].mask, GFP_KERNEL)) {
@@ -548,7 +589,7 @@ static int mlx5_irq_set_affinity_hint(st
 		return -ENOMEM;
 	}
 
-	cpumask_set_cpu(cpumask_local_spread(i, numa_node),
+	cpumask_set_cpu(cpumask_local_spread(i, priv->numa_node),
 			priv->irq_info[i].mask);
 
 	err = irq_set_affinity_hint(irq, priv->irq_info[i].mask);
@@ -766,7 +807,7 @@ static int mlx5_core_set_issi(struct mlx
 		return 0;
 	}
 
-	return -ENOTSUPP;
+	return -EOPNOTSUPP;
 }
 
 
@@ -1017,6 +1058,8 @@ static int mlx5_load_one(struct mlx5_cor
 		goto err_pagealloc_stop;
 	}
 
+	mlx5_set_driver_version(dev);
+
 	mlx5_start_health_poll(dev);
 
 	err = mlx5_query_hca_caps(dev);
@@ -1152,6 +1195,9 @@ static int mlx5_unload_one(struct mlx5_c
 {
 	int err = 0;
 
+	if (cleanup)
+		mlx5_drain_health_wq(dev);
+
 	mutex_lock(&dev->intf_state_mutex);
 	if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
 		dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n",
@@ -1204,6 +1250,8 @@ static const struct devlink_ops mlx5_dev
 #ifdef CONFIG_MLX5_CORE_EN
 	.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
 	.eswitch_mode_get = mlx5_devlink_eswitch_mode_get,
+	.eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set,
+	.eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get,
 #endif
 };
 
@@ -1312,7 +1360,7 @@ static pci_ers_result_t mlx5_pci_err_det
 
 	mlx5_enter_error_state(dev);
 	mlx5_unload_one(dev, priv, false);
-	/* In case of kernel call save the pci state and drain health wq */
+	/* In case of kernel call save the pci state and drain the health wq */
 	if (state) {
 		pci_save_state(pdev);
 		mlx5_drain_health_wq(dev);
@@ -1419,6 +1467,7 @@ static const struct pci_device_id mlx5_c
 	{ PCI_VDEVICE(MELLANOX, 0x1017) },			/* ConnectX-5, PCIe 3.0 */
 	{ PCI_VDEVICE(MELLANOX, 0x1018), MLX5_PCI_DEV_IS_VF},	/* ConnectX-5 VF */
 	{ PCI_VDEVICE(MELLANOX, 0x1019) },			/* ConnectX-5, PCIe 4.0 */
+	{ PCI_VDEVICE(MELLANOX, 0x101a), MLX5_PCI_DEV_IS_VF},	/* ConnectX-5, PCIe 4.0 VF */
 	{ 0, }
 };
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -8,6 +8,6 @@ mlx5_core-y :=	main.o cmd.o debugfs.o fw
 mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \
 		en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \
 		en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \
-		en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o
+		en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o en_selftest.o
 
 mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) +=  en_dcbnl.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h	2017-02-12 16:03:20.000000000 -0500
@@ -86,6 +86,7 @@ int mlx5_cmd_init_hca(struct mlx5_core_d
 int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev);
 void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
 		     unsigned long param);
+void mlx5_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe);
 void mlx5_enter_error_state(struct mlx5_core_dev *dev);
 void mlx5_disable_device(struct mlx5_core_dev *dev);
 void mlx5_recover_device(struct mlx5_core_dev *dev);
@@ -97,8 +98,15 @@ int mlx5_core_sriov_configure(struct pci
 bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev);
 int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id);
 int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id);
+int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+				       void *context, u32 *element_id);
+int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+				       void *context, u32 element_id,
+				       u32 modify_bitmask);
+int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+					u32 element_id);
 int mlx5_wait_for_vf_pages(struct mlx5_core_dev *dev);
-cycle_t mlx5_read_internal_timer(struct mlx5_core_dev *dev);
+u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev);
 u32 mlx5_get_msix_vec(struct mlx5_core_dev *dev, int vecidx);
 struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn);
 void mlx5_cq_tasklet_cb(unsigned long data);
@@ -119,6 +127,12 @@ struct mlx5_core_dev *mlx5_get_next_phys
 void mlx5_dev_list_lock(void);
 void mlx5_dev_list_unlock(void);
 int mlx5_dev_list_trylock(void);
+int mlx5_encap_alloc(struct mlx5_core_dev *dev,
+		     int header_type,
+		     size_t size,
+		     void *encap_header,
+		     u32 *encap_id);
+void mlx5_encap_dealloc(struct mlx5_core_dev *dev, u32 encap_id);
 
 bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv);
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/port.c	2017-02-12 16:03:20.000000000 -0500
@@ -548,6 +548,26 @@ int mlx5_max_tc(struct mlx5_core_dev *md
 	return num_tc - 1;
 }
 
+int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out)
+{
+	u32 in[MLX5_ST_SZ_DW(dcbx_param)] = {0};
+
+	MLX5_SET(dcbx_param, in, port_number, 1);
+
+	return  mlx5_core_access_reg(mdev, in, sizeof(in), out,
+				    sizeof(in), MLX5_REG_DCBX_PARAM, 0, 0);
+}
+
+int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in)
+{
+	u32 out[MLX5_ST_SZ_DW(dcbx_param)];
+
+	MLX5_SET(dcbx_param, in, port_number, 1);
+
+	return mlx5_core_access_reg(mdev, in, sizeof(out), out,
+				    sizeof(out), MLX5_REG_DCBX_PARAM, 0, 1);
+}
+
 int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc)
 {
 	u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {0};
@@ -572,13 +592,35 @@ int mlx5_set_port_prio_tc(struct mlx5_co
 }
 EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
 
+int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
+			    u8 prio, u8 *tc)
+{
+	u32 in[MLX5_ST_SZ_DW(qtct_reg)];
+	u32 out[MLX5_ST_SZ_DW(qtct_reg)];
+	int err;
+
+	memset(in, 0, sizeof(in));
+	memset(out, 0, sizeof(out));
+
+	MLX5_SET(qtct_reg, in, port_number, 1);
+	MLX5_SET(qtct_reg, in, prio, prio);
+
+	err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
+				   sizeof(out), MLX5_REG_QTCT, 0, 0);
+	if (!err)
+		*tc = MLX5_GET(qtct_reg, out, tclass);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
+
 static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
 				   int inlen)
 {
 	u32 out[MLX5_ST_SZ_DW(qtct_reg)];
 
 	if (!MLX5_CAP_GEN(mdev, ets))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	return mlx5_core_access_reg(mdev, in, inlen, out, sizeof(out),
 				    MLX5_REG_QETCR, 0, 1);
@@ -590,7 +632,7 @@ static int mlx5_query_port_qetcr_reg(str
 	u32 in[MLX5_ST_SZ_DW(qtct_reg)];
 
 	if (!MLX5_CAP_GEN(mdev, ets))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	memset(in, 0, sizeof(in));
 	return mlx5_core_access_reg(mdev, in, sizeof(in), out, outlen,
@@ -625,6 +667,27 @@ int mlx5_set_port_tc_bw_alloc(struct mlx
 }
 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
 
+int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev,
+				u8 tc, u8 *bw_pct)
+{
+	u32 out[MLX5_ST_SZ_DW(qetc_reg)];
+	void *ets_tcn_conf;
+	int err;
+
+	err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
+	if (err)
+		return err;
+
+	ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
+				    tc_configuration[tc]);
+
+	*bw_pct = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
+			   bw_allocation);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
+
 int mlx5_modify_port_ets_rate_limit(struct mlx5_core_dev *mdev,
 				    u8 *max_bw_value,
 				    u8 *max_bw_units)
@@ -746,3 +809,60 @@ void mlx5_query_port_fcs(struct mlx5_cor
 	*supported = !!(MLX5_GET(pcmr_reg, out, fcs_cap));
 	*enabled = !!(MLX5_GET(pcmr_reg, out, fcs_chk));
 }
+
+static const char *mlx5_pme_status[MLX5_MODULE_STATUS_NUM] = {
+	"Cable plugged",   /* MLX5_MODULE_STATUS_PLUGGED    = 0x1 */
+	"Cable unplugged", /* MLX5_MODULE_STATUS_UNPLUGGED  = 0x2 */
+	"Cable error",     /* MLX5_MODULE_STATUS_ERROR      = 0x3 */
+};
+
+static const char *mlx5_pme_error[MLX5_MODULE_EVENT_ERROR_NUM] = {
+	"Power budget exceeded",
+	"Long Range for non MLNX cable",
+	"Bus stuck(I2C or data shorted)",
+	"No EEPROM/retry timeout",
+	"Enforce part number list",
+	"Unknown identifier",
+	"High Temperature",
+	"Bad or shorted cable/module",
+	"Unknown status",
+};
+
+void mlx5_port_module_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe)
+{
+	enum port_module_event_status_type module_status;
+	enum port_module_event_error_type error_type;
+	struct mlx5_eqe_port_module *module_event_eqe;
+	struct mlx5_priv *priv = &dev->priv;
+	u8 module_num;
+
+	module_event_eqe = &eqe->data.port_module;
+	module_num = module_event_eqe->module;
+	module_status = module_event_eqe->module_status &
+			PORT_MODULE_EVENT_MODULE_STATUS_MASK;
+	error_type = module_event_eqe->error_type &
+		     PORT_MODULE_EVENT_ERROR_TYPE_MASK;
+
+	if (module_status < MLX5_MODULE_STATUS_ERROR) {
+		priv->pme_stats.status_counters[module_status - 1]++;
+	} else if (module_status == MLX5_MODULE_STATUS_ERROR) {
+		if (error_type >= MLX5_MODULE_EVENT_ERROR_UNKNOWN)
+			/* Unknown error type */
+			error_type = MLX5_MODULE_EVENT_ERROR_UNKNOWN;
+		priv->pme_stats.error_counters[error_type]++;
+	}
+
+	if (!printk_ratelimit())
+		return;
+
+	if (module_status < MLX5_MODULE_STATUS_ERROR)
+		mlx5_core_info(dev,
+			       "Port module event: module %u, %s\n",
+			       module_num, mlx5_pme_status[module_status - 1]);
+
+	else if (module_status == MLX5_MODULE_STATUS_ERROR)
+		mlx5_core_info(dev,
+			       "Port module event[error]: module %u, %s, %s\n",
+			       module_num, mlx5_pme_status[module_status - 1],
+			       mlx5_pme_error[error_type]);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/rl.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/rl.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/rl.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/rl.c	2017-02-12 16:03:20.000000000 -0500
@@ -36,6 +36,71 @@
 #include <linux/mlx5/cmd.h>
 #include "mlx5_core.h"
 
+/* Scheduling element fw management */
+int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+				       void *ctx, u32 *element_id)
+{
+	u32 in[MLX5_ST_SZ_DW(create_scheduling_element_in)]  = {0};
+	u32 out[MLX5_ST_SZ_DW(create_scheduling_element_in)] = {0};
+	void *schedc;
+	int err;
+
+	schedc = MLX5_ADDR_OF(create_scheduling_element_in, in,
+			      scheduling_context);
+	MLX5_SET(create_scheduling_element_in, in, opcode,
+		 MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT);
+	MLX5_SET(create_scheduling_element_in, in, scheduling_hierarchy,
+		 hierarchy);
+	memcpy(schedc, ctx, MLX5_ST_SZ_BYTES(scheduling_context));
+
+	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+	if (err)
+		return err;
+
+	*element_id = MLX5_GET(create_scheduling_element_out, out,
+			       scheduling_element_id);
+	return 0;
+}
+
+int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+				       void *ctx, u32 element_id,
+				       u32 modify_bitmask)
+{
+	u32 in[MLX5_ST_SZ_DW(modify_scheduling_element_in)]  = {0};
+	u32 out[MLX5_ST_SZ_DW(modify_scheduling_element_in)] = {0};
+	void *schedc;
+
+	schedc = MLX5_ADDR_OF(modify_scheduling_element_in, in,
+			      scheduling_context);
+	MLX5_SET(modify_scheduling_element_in, in, opcode,
+		 MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT);
+	MLX5_SET(modify_scheduling_element_in, in, scheduling_element_id,
+		 element_id);
+	MLX5_SET(modify_scheduling_element_in, in, modify_bitmask,
+		 modify_bitmask);
+	MLX5_SET(modify_scheduling_element_in, in, scheduling_hierarchy,
+		 hierarchy);
+	memcpy(schedc, ctx, MLX5_ST_SZ_BYTES(scheduling_context));
+
+	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
+int mlx5_destroy_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+					u32 element_id)
+{
+	u32 in[MLX5_ST_SZ_DW(destroy_scheduling_element_in)]  = {0};
+	u32 out[MLX5_ST_SZ_DW(destroy_scheduling_element_in)] = {0};
+
+	MLX5_SET(destroy_scheduling_element_in, in, opcode,
+		 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
+	MLX5_SET(destroy_scheduling_element_in, in, scheduling_element_id,
+		 element_id);
+	MLX5_SET(destroy_scheduling_element_in, in, scheduling_hierarchy,
+		 hierarchy);
+
+	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
 /* Finds an entry where we can register the given rate
  * If the rate already exists, return the entry where it is registered,
  * otherwise return the first available entry.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/vport.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/vport.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/vport.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/vport.c	2017-02-12 16:03:20.000000000 -0500
@@ -113,15 +113,17 @@ static int mlx5_modify_nic_vport_context
 	return mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
 }
 
-void mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
-				     u8 *min_inline_mode)
+int mlx5_query_nic_vport_min_inline(struct mlx5_core_dev *mdev,
+				    u16 vport, u8 *min_inline)
 {
 	u32 out[MLX5_ST_SZ_DW(query_nic_vport_context_out)] = {0};
+	int err;
 
-	mlx5_query_nic_vport_context(mdev, 0, out, sizeof(out));
-
-	*min_inline_mode = MLX5_GET(query_nic_vport_context_out, out,
-				    nic_vport_context.min_wqe_inline_mode);
+	err = mlx5_query_nic_vport_context(mdev, vport, out, sizeof(out));
+	if (!err)
+		*min_inline = MLX5_GET(query_nic_vport_context_out, out,
+				       nic_vport_context.min_wqe_inline_mode);
+	return err;
 }
 EXPORT_SYMBOL_GPL(mlx5_query_nic_vport_min_inline);
 
@@ -530,7 +532,7 @@ int mlx5_modify_nic_vport_node_guid(stru
 	if (!MLX5_CAP_GEN(mdev, vport_group_manager))
 		return -EACCES;
 	if (!MLX5_CAP_ESW(mdev, nic_vport_node_guid_modify))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	in = mlx5_vzalloc(inlen);
 	if (!in)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.c	2017-02-12 16:03:20.000000000 -0500
@@ -101,13 +101,15 @@ err_db_free:
 
 int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 		     void *cqc, struct mlx5_cqwq *wq,
-		     struct mlx5_wq_ctrl *wq_ctrl)
+		     struct mlx5_frag_wq_ctrl *wq_ctrl)
 {
 	int err;
 
-	wq->log_stride = 6 + MLX5_GET(cqc, cqc, cqe_sz);
-	wq->log_sz = MLX5_GET(cqc, cqc, log_cq_size);
-	wq->sz_m1 = (1 << wq->log_sz) - 1;
+	wq->log_stride	= 6 + MLX5_GET(cqc, cqc, cqe_sz);
+	wq->log_sz	= MLX5_GET(cqc, cqc, log_cq_size);
+	wq->sz_m1	= (1 << wq->log_sz) - 1;
+	wq->log_frag_strides = PAGE_SHIFT - wq->log_stride;
+	wq->frag_sz_m1	= (1 << wq->log_frag_strides) - 1;
 
 	err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
 	if (err) {
@@ -115,14 +117,16 @@ int mlx5_cqwq_create(struct mlx5_core_de
 		return err;
 	}
 
-	err = mlx5_buf_alloc_node(mdev, mlx5_cqwq_get_byte_size(wq),
-				  &wq_ctrl->buf, param->buf_numa_node);
+	err = mlx5_frag_buf_alloc_node(mdev, mlx5_cqwq_get_byte_size(wq),
+				       &wq_ctrl->frag_buf,
+				       param->buf_numa_node);
 	if (err) {
-		mlx5_core_warn(mdev, "mlx5_buf_alloc_node() failed, %d\n", err);
+		mlx5_core_warn(mdev, "mlx5_frag_buf_alloc_node() failed, %d\n",
+			       err);
 		goto err_db_free;
 	}
 
-	wq->buf = wq_ctrl->buf.direct.buf;
+	wq->frag_buf = wq_ctrl->frag_buf;
 	wq->db  = wq_ctrl->db.db;
 
 	wq_ctrl->mdev = mdev;
@@ -184,3 +188,9 @@ void mlx5_wq_destroy(struct mlx5_wq_ctrl
 	mlx5_buf_free(wq_ctrl->mdev, &wq_ctrl->buf);
 	mlx5_db_free(wq_ctrl->mdev, &wq_ctrl->db);
 }
+
+void mlx5_cqwq_destroy(struct mlx5_frag_wq_ctrl *wq_ctrl)
+{
+	mlx5_frag_buf_free(wq_ctrl->mdev, &wq_ctrl->frag_buf);
+	mlx5_db_free(wq_ctrl->mdev, &wq_ctrl->db);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlx5/core/wq.h	2017-02-12 16:03:20.000000000 -0500
@@ -47,6 +47,12 @@ struct mlx5_wq_ctrl {
 	struct mlx5_db		db;
 };
 
+struct mlx5_frag_wq_ctrl {
+	struct mlx5_core_dev	*mdev;
+	struct mlx5_frag_buf	frag_buf;
+	struct mlx5_db		db;
+};
+
 struct mlx5_wq_cyc {
 	void			*buf;
 	__be32			*db;
@@ -55,12 +61,14 @@ struct mlx5_wq_cyc {
 };
 
 struct mlx5_cqwq {
-	void			*buf;
+	struct mlx5_frag_buf	frag_buf;
 	__be32			*db;
 	u32			sz_m1;
+	u32			frag_sz_m1;
 	u32			cc; /* consumer counter */
 	u8			log_sz;
 	u8			log_stride;
+	u8			log_frag_strides;
 };
 
 struct mlx5_wq_ll {
@@ -81,7 +89,7 @@ u32 mlx5_wq_cyc_get_size(struct mlx5_wq_
 
 int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 		     void *cqc, struct mlx5_cqwq *wq,
-		     struct mlx5_wq_ctrl *wq_ctrl);
+		     struct mlx5_frag_wq_ctrl *wq_ctrl);
 u32 mlx5_cqwq_get_size(struct mlx5_cqwq *wq);
 
 int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
@@ -90,6 +98,7 @@ int mlx5_wq_ll_create(struct mlx5_core_d
 u32 mlx5_wq_ll_get_size(struct mlx5_wq_ll *wq);
 
 void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl);
+void mlx5_cqwq_destroy(struct mlx5_frag_wq_ctrl *wq_ctrl);
 
 static inline u16 mlx5_wq_cyc_ctr2ix(struct mlx5_wq_cyc *wq, u16 ctr)
 {
@@ -116,7 +125,10 @@ static inline u32 mlx5_cqwq_get_ci(struc
 
 static inline void *mlx5_cqwq_get_wqe(struct mlx5_cqwq *wq, u32 ix)
 {
-	return wq->buf + (ix << wq->log_stride);
+	unsigned int frag = (ix >> wq->log_frag_strides);
+
+	return wq->frag_buf.frags[frag].buf +
+		((wq->frag_sz_m1 & ix) << wq->log_stride);
 }
 
 static inline u32 mlx5_cqwq_get_wrap_cnt(struct mlx5_cqwq *wq)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/cmd.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/cmd.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/cmd.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/cmd.h	2017-02-12 16:03:20.000000000 -0500
@@ -513,6 +513,11 @@ static inline int mlxsw_cmd_unmap_fa(str
  * are no more sources in the table, will return resource id 0xFFF to indicate
  * it.
  */
+
+#define MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID 0xffff
+#define MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES 100
+#define MLXSW_CMD_QUERY_RESOURCES_PER_QUERY 32
+
 static inline int mlxsw_cmd_query_resources(struct mlxsw_core *mlxsw_core,
 					    char *out_mbox, int index)
 {
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core.c	2017-02-12 16:03:20.000000000 -0500
@@ -67,6 +67,7 @@
 #include "trap.h"
 #include "emad.h"
 #include "reg.h"
+#include "resources.h"
 
 static LIST_HEAD(mlxsw_core_driver_list);
 static DEFINE_SPINLOCK(mlxsw_core_driver_list_lock);
@@ -76,6 +77,7 @@ static const char mlxsw_core_driver_name
 static struct dentry *mlxsw_core_dbg_root;
 
 static struct workqueue_struct *mlxsw_wq;
+static struct workqueue_struct *mlxsw_owq;
 
 struct mlxsw_core_pcpu_stats {
 	u64			trap_rx_packets[MLXSW_TRAP_ID_MAX];
@@ -89,6 +91,23 @@ struct mlxsw_core_pcpu_stats {
 	u32			port_rx_invalid;
 };
 
+struct mlxsw_core_port {
+	struct devlink_port devlink_port;
+	void *port_driver_priv;
+	u8 local_port;
+};
+
+void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
+{
+	return mlxsw_core_port->port_driver_priv;
+}
+EXPORT_SYMBOL(mlxsw_core_port_driver_priv);
+
+static bool mlxsw_core_port_check(struct mlxsw_core_port *mlxsw_core_port)
+{
+	return mlxsw_core_port->port_driver_priv != NULL;
+}
+
 struct mlxsw_core {
 	struct mlxsw_driver *driver;
 	const struct mlxsw_bus *bus;
@@ -111,8 +130,10 @@ struct mlxsw_core {
 	struct {
 		u8 *mapping; /* lag_id+port_index to local_port mapping */
 	} lag;
-	struct mlxsw_resources resources;
+	struct mlxsw_res res;
 	struct mlxsw_hwmon *hwmon;
+	struct mlxsw_thermal *thermal;
+	struct mlxsw_core_port ports[MLXSW_PORT_MAX_PORTS];
 	unsigned long driver_priv[0];
 	/* driver_priv has to be always the last item */
 };
@@ -552,33 +573,18 @@ free_skb:
 	dev_kfree_skb(skb);
 }
 
-static const struct mlxsw_rx_listener mlxsw_emad_rx_listener = {
-	.func = mlxsw_emad_rx_listener_func,
-	.local_port = MLXSW_PORT_DONT_CARE,
-	.trap_id = MLXSW_TRAP_ID_ETHEMAD,
-};
-
-static int mlxsw_emad_traps_set(struct mlxsw_core *mlxsw_core)
-{
-	char htgt_pl[MLXSW_REG_HTGT_LEN];
-	char hpkt_pl[MLXSW_REG_HPKT_LEN];
-	int err;
-
-	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD);
-	err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
-	if (err)
-		return err;
-
-	mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,
-			    MLXSW_TRAP_ID_ETHEMAD);
-	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
-}
+static const struct mlxsw_listener mlxsw_emad_rx_listener =
+	MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
+		  EMAD, DISCARD);
 
 static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
 {
 	u64 tid;
 	int err;
 
+	if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
+		return 0;
+
 	/* Set the upper 32 bits of the transaction ID field to a random
 	 * number. This allows us to discard EMADs addressed to other
 	 * devices.
@@ -590,39 +596,33 @@ static int mlxsw_emad_init(struct mlxsw_
 	INIT_LIST_HEAD(&mlxsw_core->emad.trans_list);
 	spin_lock_init(&mlxsw_core->emad.trans_list_lock);
 
-	err = mlxsw_core_rx_listener_register(mlxsw_core,
-					      &mlxsw_emad_rx_listener,
-					      mlxsw_core);
+	err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener,
+				       mlxsw_core);
 	if (err)
 		return err;
 
-	err = mlxsw_emad_traps_set(mlxsw_core);
+	err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core);
 	if (err)
 		goto err_emad_trap_set;
-
 	mlxsw_core->emad.use_emad = true;
 
 	return 0;
 
 err_emad_trap_set:
-	mlxsw_core_rx_listener_unregister(mlxsw_core,
-					  &mlxsw_emad_rx_listener,
-					  mlxsw_core);
+	mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
+				   mlxsw_core);
 	return err;
 }
 
 static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core)
 {
-	char hpkt_pl[MLXSW_REG_HPKT_LEN];
 
-	mlxsw_core->emad.use_emad = false;
-	mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD,
-			    MLXSW_TRAP_ID_ETHEMAD);
-	mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
+	if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX))
+		return;
 
-	mlxsw_core_rx_listener_unregister(mlxsw_core,
-					  &mlxsw_emad_rx_listener,
-					  mlxsw_core);
+	mlxsw_core->emad.use_emad = false;
+	mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
+				   mlxsw_core);
 }
 
 static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core,
@@ -822,17 +822,6 @@ static struct mlxsw_driver *mlxsw_core_d
 
 	spin_lock(&mlxsw_core_driver_list_lock);
 	mlxsw_driver = __driver_find(kind);
-	if (!mlxsw_driver) {
-		spin_unlock(&mlxsw_core_driver_list_lock);
-		request_module(MLXSW_MODULE_ALIAS_PREFIX "%s", kind);
-		spin_lock(&mlxsw_core_driver_list_lock);
-		mlxsw_driver = __driver_find(kind);
-	}
-	if (mlxsw_driver) {
-		if (!try_module_get(mlxsw_driver->owner))
-			mlxsw_driver = NULL;
-	}
-
 	spin_unlock(&mlxsw_core_driver_list_lock);
 	return mlxsw_driver;
 }
@@ -844,9 +833,6 @@ static void mlxsw_core_driver_put(const
 	spin_lock(&mlxsw_core_driver_list_lock);
 	mlxsw_driver = __driver_find(kind);
 	spin_unlock(&mlxsw_core_driver_list_lock);
-	if (!mlxsw_driver)
-		return;
-	module_put(mlxsw_driver->owner);
 }
 
 static int mlxsw_core_debugfs_init(struct mlxsw_core *mlxsw_core)
@@ -933,6 +919,21 @@ static void *__dl_port(struct devlink_po
 	return container_of(devlink_port, struct mlxsw_core_port, devlink_port);
 }
 
+static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port,
+				       enum devlink_port_type port_type)
+{
+	struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
+	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
+	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
+
+	if (!mlxsw_driver->port_type_set)
+		return -EOPNOTSUPP;
+
+	return mlxsw_driver->port_type_set(mlxsw_core,
+					   mlxsw_core_port->local_port,
+					   port_type);
+}
+
 static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
 					  unsigned int sb_index, u16 pool_index,
 					  u32 *p_threshold)
@@ -941,7 +942,8 @@ static int mlxsw_devlink_sb_port_pool_ge
 	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
 	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
 
-	if (!mlxsw_driver->sb_port_pool_get)
+	if (!mlxsw_driver->sb_port_pool_get ||
+	    !mlxsw_core_port_check(mlxsw_core_port))
 		return -EOPNOTSUPP;
 	return mlxsw_driver->sb_port_pool_get(mlxsw_core_port, sb_index,
 					      pool_index, p_threshold);
@@ -955,7 +957,8 @@ static int mlxsw_devlink_sb_port_pool_se
 	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
 	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
 
-	if (!mlxsw_driver->sb_port_pool_set)
+	if (!mlxsw_driver->sb_port_pool_set ||
+	    !mlxsw_core_port_check(mlxsw_core_port))
 		return -EOPNOTSUPP;
 	return mlxsw_driver->sb_port_pool_set(mlxsw_core_port, sb_index,
 					      pool_index, threshold);
@@ -971,7 +974,8 @@ mlxsw_devlink_sb_tc_pool_bind_get(struct
 	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
 	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
 
-	if (!mlxsw_driver->sb_tc_pool_bind_get)
+	if (!mlxsw_driver->sb_tc_pool_bind_get ||
+	    !mlxsw_core_port_check(mlxsw_core_port))
 		return -EOPNOTSUPP;
 	return mlxsw_driver->sb_tc_pool_bind_get(mlxsw_core_port, sb_index,
 						 tc_index, pool_type,
@@ -988,7 +992,8 @@ mlxsw_devlink_sb_tc_pool_bind_set(struct
 	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
 	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
 
-	if (!mlxsw_driver->sb_tc_pool_bind_set)
+	if (!mlxsw_driver->sb_tc_pool_bind_set ||
+	    !mlxsw_core_port_check(mlxsw_core_port))
 		return -EOPNOTSUPP;
 	return mlxsw_driver->sb_tc_pool_bind_set(mlxsw_core_port, sb_index,
 						 tc_index, pool_type,
@@ -1026,7 +1031,8 @@ mlxsw_devlink_sb_occ_port_pool_get(struc
 	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
 	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
 
-	if (!mlxsw_driver->sb_occ_port_pool_get)
+	if (!mlxsw_driver->sb_occ_port_pool_get ||
+	    !mlxsw_core_port_check(mlxsw_core_port))
 		return -EOPNOTSUPP;
 	return mlxsw_driver->sb_occ_port_pool_get(mlxsw_core_port, sb_index,
 						  pool_index, p_cur, p_max);
@@ -1042,7 +1048,8 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(st
 	struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
 	struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
 
-	if (!mlxsw_driver->sb_occ_tc_port_bind_get)
+	if (!mlxsw_driver->sb_occ_tc_port_bind_get ||
+	    !mlxsw_core_port_check(mlxsw_core_port))
 		return -EOPNOTSUPP;
 	return mlxsw_driver->sb_occ_tc_port_bind_get(mlxsw_core_port,
 						     sb_index, tc_index,
@@ -1050,6 +1057,7 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(st
 }
 
 static const struct devlink_ops mlxsw_devlink_ops = {
+	.port_type_set			= mlxsw_devlink_port_type_set,
 	.port_split			= mlxsw_devlink_port_split,
 	.port_unsplit			= mlxsw_devlink_port_unsplit,
 	.sb_pool_get			= mlxsw_devlink_sb_pool_get,
@@ -1101,14 +1109,15 @@ int mlxsw_core_bus_device_register(const
 	}
 
 	err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile,
-			      &mlxsw_core->resources);
+			      &mlxsw_core->res);
 	if (err)
 		goto err_bus_init;
 
-	if (mlxsw_core->resources.max_lag_valid &&
-	    mlxsw_core->resources.max_ports_in_lag_valid) {
-		alloc_size = sizeof(u8) * mlxsw_core->resources.max_lag *
-			mlxsw_core->resources.max_ports_in_lag;
+	if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
+	    MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
+		alloc_size = sizeof(u8) *
+			MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) *
+			MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS);
 		mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL);
 		if (!mlxsw_core->lag.mapping) {
 			err = -ENOMEM;
@@ -1128,9 +1137,16 @@ int mlxsw_core_bus_device_register(const
 	if (err)
 		goto err_hwmon_init;
 
-	err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info);
+	err = mlxsw_thermal_init(mlxsw_core, mlxsw_bus_info,
+				 &mlxsw_core->thermal);
 	if (err)
-		goto err_driver_init;
+		goto err_thermal_init;
+
+	if (mlxsw_driver->init) {
+		err = mlxsw_driver->init(mlxsw_core, mlxsw_bus_info);
+		if (err)
+			goto err_driver_init;
+	}
 
 	err = mlxsw_core_debugfs_init(mlxsw_core);
 	if (err)
@@ -1139,8 +1155,11 @@ int mlxsw_core_bus_device_register(const
 	return 0;
 
 err_debugfs_init:
-	mlxsw_core->driver->fini(mlxsw_core);
+	if (mlxsw_core->driver->fini)
+		mlxsw_core->driver->fini(mlxsw_core);
 err_driver_init:
+	mlxsw_thermal_fini(mlxsw_core->thermal);
+err_thermal_init:
 err_hwmon_init:
 	devlink_unregister(devlink);
 err_devlink_register:
@@ -1165,11 +1184,13 @@ void mlxsw_core_bus_device_unregister(st
 	struct devlink *devlink = priv_to_devlink(mlxsw_core);
 
 	mlxsw_core_debugfs_fini(mlxsw_core);
-	mlxsw_core->driver->fini(mlxsw_core);
+	if (mlxsw_core->driver->fini)
+		mlxsw_core->driver->fini(mlxsw_core);
+	mlxsw_thermal_fini(mlxsw_core->thermal);
 	devlink_unregister(devlink);
 	mlxsw_emad_fini(mlxsw_core);
-	mlxsw_core->bus->fini(mlxsw_core->bus_priv);
 	kfree(mlxsw_core->lag.mapping);
+	mlxsw_core->bus->fini(mlxsw_core->bus_priv);
 	free_percpu(mlxsw_core->pcpu_stats);
 	devlink_free(devlink);
 	mlxsw_core_driver_put(device_kind);
@@ -1346,6 +1367,75 @@ void mlxsw_core_event_listener_unregiste
 }
 EXPORT_SYMBOL(mlxsw_core_event_listener_unregister);
 
+static int mlxsw_core_listener_register(struct mlxsw_core *mlxsw_core,
+					const struct mlxsw_listener *listener,
+					void *priv)
+{
+	if (listener->is_event)
+		return mlxsw_core_event_listener_register(mlxsw_core,
+						&listener->u.event_listener,
+						priv);
+	else
+		return mlxsw_core_rx_listener_register(mlxsw_core,
+						&listener->u.rx_listener,
+						priv);
+}
+
+static void mlxsw_core_listener_unregister(struct mlxsw_core *mlxsw_core,
+				      const struct mlxsw_listener *listener,
+				      void *priv)
+{
+	if (listener->is_event)
+		mlxsw_core_event_listener_unregister(mlxsw_core,
+						     &listener->u.event_listener,
+						     priv);
+	else
+		mlxsw_core_rx_listener_unregister(mlxsw_core,
+						  &listener->u.rx_listener,
+						  priv);
+}
+
+int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
+			     const struct mlxsw_listener *listener, void *priv)
+{
+	char hpkt_pl[MLXSW_REG_HPKT_LEN];
+	int err;
+
+	err = mlxsw_core_listener_register(mlxsw_core, listener, priv);
+	if (err)
+		return err;
+
+	mlxsw_reg_hpkt_pack(hpkt_pl, listener->action, listener->trap_id,
+			    listener->trap_group, listener->is_ctrl);
+	err = mlxsw_reg_write(mlxsw_core,  MLXSW_REG(hpkt), hpkt_pl);
+	if (err)
+		goto err_trap_set;
+
+	return 0;
+
+err_trap_set:
+	mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
+	return err;
+}
+EXPORT_SYMBOL(mlxsw_core_trap_register);
+
+void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
+				const struct mlxsw_listener *listener,
+				void *priv)
+{
+	char hpkt_pl[MLXSW_REG_HPKT_LEN];
+
+	if (!listener->is_event) {
+		mlxsw_reg_hpkt_pack(hpkt_pl, listener->unreg_action,
+				    listener->trap_id, listener->trap_group,
+				    listener->is_ctrl);
+		mlxsw_reg_write(mlxsw_core, MLXSW_REG(hpkt), hpkt_pl);
+	}
+
+	mlxsw_core_listener_unregister(mlxsw_core, listener, priv);
+}
+EXPORT_SYMBOL(mlxsw_core_trap_unregister);
+
 static u64 mlxsw_core_tid_get(struct mlxsw_core *mlxsw_core)
 {
 	return atomic64_inc_return(&mlxsw_core->emad.tid);
@@ -1615,7 +1705,7 @@ EXPORT_SYMBOL(mlxsw_core_skb_receive);
 static int mlxsw_core_lag_mapping_index(struct mlxsw_core *mlxsw_core,
 					u16 lag_id, u8 port_index)
 {
-	return mlxsw_core->resources.max_ports_in_lag * lag_id +
+	return MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS) * lag_id +
 	       port_index;
 }
 
@@ -1644,7 +1734,7 @@ void mlxsw_core_lag_mapping_clear(struct
 {
 	int i;
 
-	for (i = 0; i < mlxsw_core->resources.max_ports_in_lag; i++) {
+	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS); i++) {
 		int index = mlxsw_core_lag_mapping_index(mlxsw_core,
 							 lag_id, i);
 
@@ -1654,34 +1744,97 @@ void mlxsw_core_lag_mapping_clear(struct
 }
 EXPORT_SYMBOL(mlxsw_core_lag_mapping_clear);
 
-struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core)
+bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
+			  enum mlxsw_res_id res_id)
 {
-	return &mlxsw_core->resources;
+	return mlxsw_res_valid(&mlxsw_core->res, res_id);
 }
-EXPORT_SYMBOL(mlxsw_core_resources_get);
+EXPORT_SYMBOL(mlxsw_core_res_valid);
 
-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
-			 struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
-			 struct net_device *dev, bool split, u32 split_group)
+u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
+		       enum mlxsw_res_id res_id)
+{
+	return mlxsw_res_get(&mlxsw_core->res, res_id);
+}
+EXPORT_SYMBOL(mlxsw_core_res_get);
+
+int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port)
 {
 	struct devlink *devlink = priv_to_devlink(mlxsw_core);
+	struct mlxsw_core_port *mlxsw_core_port =
+					&mlxsw_core->ports[local_port];
 	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+	int err;
 
-	if (split)
-		devlink_port_split_set(devlink_port, split_group);
-	devlink_port_type_eth_set(devlink_port, dev);
-	return devlink_port_register(devlink, devlink_port, local_port);
+	mlxsw_core_port->local_port = local_port;
+	err = devlink_port_register(devlink, devlink_port, local_port);
+	if (err)
+		memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
+	return err;
 }
 EXPORT_SYMBOL(mlxsw_core_port_init);
 
-void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port)
+void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port)
 {
+	struct mlxsw_core_port *mlxsw_core_port =
+					&mlxsw_core->ports[local_port];
 	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
 
 	devlink_port_unregister(devlink_port);
+	memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port));
 }
 EXPORT_SYMBOL(mlxsw_core_port_fini);
 
+void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+			     void *port_driver_priv, struct net_device *dev,
+			     bool split, u32 split_group)
+{
+	struct mlxsw_core_port *mlxsw_core_port =
+					&mlxsw_core->ports[local_port];
+	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+	mlxsw_core_port->port_driver_priv = port_driver_priv;
+	if (split)
+		devlink_port_split_set(devlink_port, split_group);
+	devlink_port_type_eth_set(devlink_port, dev);
+}
+EXPORT_SYMBOL(mlxsw_core_port_eth_set);
+
+void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+			    void *port_driver_priv)
+{
+	struct mlxsw_core_port *mlxsw_core_port =
+					&mlxsw_core->ports[local_port];
+	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+	mlxsw_core_port->port_driver_priv = port_driver_priv;
+	devlink_port_type_ib_set(devlink_port, NULL);
+}
+EXPORT_SYMBOL(mlxsw_core_port_ib_set);
+
+void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
+			   void *port_driver_priv)
+{
+	struct mlxsw_core_port *mlxsw_core_port =
+					&mlxsw_core->ports[local_port];
+	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+	mlxsw_core_port->port_driver_priv = port_driver_priv;
+	devlink_port_type_clear(devlink_port);
+}
+EXPORT_SYMBOL(mlxsw_core_port_clear);
+
+enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
+						u8 local_port)
+{
+	struct mlxsw_core_port *mlxsw_core_port =
+					&mlxsw_core->ports[local_port];
+	struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
+
+	return devlink_port->type;
+}
+EXPORT_SYMBOL(mlxsw_core_port_type_get);
+
 static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core,
 				    const char *buf, size_t size)
 {
@@ -1748,6 +1901,18 @@ int mlxsw_core_schedule_dw(struct delaye
 }
 EXPORT_SYMBOL(mlxsw_core_schedule_dw);
 
+int mlxsw_core_schedule_odw(struct delayed_work *dwork, unsigned long delay)
+{
+	return queue_delayed_work(mlxsw_owq, dwork, delay);
+}
+EXPORT_SYMBOL(mlxsw_core_schedule_odw);
+
+void mlxsw_core_flush_owq(void)
+{
+	flush_workqueue(mlxsw_owq);
+}
+EXPORT_SYMBOL(mlxsw_core_flush_owq);
+
 static int __init mlxsw_core_module_init(void)
 {
 	int err;
@@ -1755,6 +1920,12 @@ static int __init mlxsw_core_module_init
 	mlxsw_wq = alloc_workqueue(mlxsw_core_driver_name, WQ_MEM_RECLAIM, 0);
 	if (!mlxsw_wq)
 		return -ENOMEM;
+	mlxsw_owq = alloc_ordered_workqueue("%s_ordered", WQ_MEM_RECLAIM,
+					    mlxsw_core_driver_name);
+	if (!mlxsw_owq) {
+		err = -ENOMEM;
+		goto err_alloc_ordered_workqueue;
+	}
 	mlxsw_core_dbg_root = debugfs_create_dir(mlxsw_core_driver_name, NULL);
 	if (!mlxsw_core_dbg_root) {
 		err = -ENOMEM;
@@ -1763,6 +1934,8 @@ static int __init mlxsw_core_module_init
 	return 0;
 
 err_debugfs_create_dir:
+	destroy_workqueue(mlxsw_owq);
+err_alloc_ordered_workqueue:
 	destroy_workqueue(mlxsw_wq);
 	return err;
 }
@@ -1770,6 +1943,7 @@ err_debugfs_create_dir:
 static void __exit mlxsw_core_module_exit(void)
 {
 	debugfs_remove_recursive(mlxsw_core_dbg_root);
+	destroy_workqueue(mlxsw_owq);
 	destroy_workqueue(mlxsw_wq);
 }
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core.h	2017-02-12 16:03:20.000000000 -0500
@@ -48,17 +48,11 @@
 
 #include "trap.h"
 #include "reg.h"
-
 #include "cmd.h"
-
-#define MLXSW_MODULE_ALIAS_PREFIX "mlxsw-driver-"
-#define MODULE_MLXSW_DRIVER_ALIAS(kind)	\
-	MODULE_ALIAS(MLXSW_MODULE_ALIAS_PREFIX kind)
-
-#define MLXSW_DEVICE_KIND_SWITCHX2 "switchx2"
-#define MLXSW_DEVICE_KIND_SPECTRUM "spectrum"
+#include "resources.h"
 
 struct mlxsw_core;
+struct mlxsw_core_port;
 struct mlxsw_driver;
 struct mlxsw_bus;
 struct mlxsw_bus_info;
@@ -96,6 +90,50 @@ struct mlxsw_event_listener {
 	enum mlxsw_event_trap_id trap_id;
 };
 
+struct mlxsw_listener {
+	u16 trap_id;
+	union {
+		struct mlxsw_rx_listener rx_listener;
+		struct mlxsw_event_listener event_listener;
+	} u;
+	enum mlxsw_reg_hpkt_action action;
+	enum mlxsw_reg_hpkt_action unreg_action;
+	u8 trap_group;
+	bool is_ctrl; /* should go via control buffer or not */
+	bool is_event;
+};
+
+#define MLXSW_RXL(_func, _trap_id, _action, _is_ctrl, _trap_group,	\
+		  _unreg_action)					\
+	{								\
+		.trap_id = MLXSW_TRAP_ID_##_trap_id,			\
+		.u.rx_listener =					\
+		{							\
+			.func = _func,					\
+			.local_port = MLXSW_PORT_DONT_CARE,		\
+			.trap_id = MLXSW_TRAP_ID_##_trap_id,		\
+		},							\
+		.action = MLXSW_REG_HPKT_ACTION_##_action,		\
+		.unreg_action = MLXSW_REG_HPKT_ACTION_##_unreg_action,	\
+		.trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group,	\
+		.is_ctrl = _is_ctrl,					\
+		.is_event = false,					\
+	}
+
+#define MLXSW_EVENTL(_func, _trap_id, _trap_group)			\
+	{								\
+		.trap_id = MLXSW_TRAP_ID_##_trap_id,			\
+		.u.event_listener =					\
+		{							\
+			.func = _func,					\
+			.trap_id = MLXSW_TRAP_ID_##_trap_id,		\
+		},							\
+		.action = MLXSW_REG_HPKT_ACTION_TRAP_TO_CPU,		\
+		.trap_group = MLXSW_REG_HTGT_TRAP_GROUP_##_trap_group,	\
+		.is_ctrl = false,					\
+		.is_event = true,					\
+	}
+
 int mlxsw_core_rx_listener_register(struct mlxsw_core *mlxsw_core,
 				    const struct mlxsw_rx_listener *rxl,
 				    void *priv);
@@ -110,6 +148,13 @@ void mlxsw_core_event_listener_unregiste
 					  const struct mlxsw_event_listener *el,
 					  void *priv);
 
+int mlxsw_core_trap_register(struct mlxsw_core *mlxsw_core,
+			     const struct mlxsw_listener *listener,
+			     void *priv);
+void mlxsw_core_trap_unregister(struct mlxsw_core *mlxsw_core,
+				const struct mlxsw_listener *listener,
+				void *priv);
+
 typedef void mlxsw_reg_trans_cb_t(struct mlxsw_core *mlxsw_core, char *payload,
 				  size_t payload_len, unsigned long cb_priv);
 
@@ -148,25 +193,22 @@ u8 mlxsw_core_lag_mapping_get(struct mlx
 void mlxsw_core_lag_mapping_clear(struct mlxsw_core *mlxsw_core,
 				  u16 lag_id, u8 local_port);
 
-struct mlxsw_core_port {
-	struct devlink_port devlink_port;
-};
-
-static inline void *
-mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port)
-{
-	/* mlxsw_core_port is ensured to always be the first field in driver
-	 * port structure.
-	 */
-	return mlxsw_core_port;
-}
-
-int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core,
-			 struct mlxsw_core_port *mlxsw_core_port, u8 local_port,
-			 struct net_device *dev, bool split, u32 split_group);
-void mlxsw_core_port_fini(struct mlxsw_core_port *mlxsw_core_port);
+void *mlxsw_core_port_driver_priv(struct mlxsw_core_port *mlxsw_core_port);
+int mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u8 local_port);
+void mlxsw_core_port_fini(struct mlxsw_core *mlxsw_core, u8 local_port);
+void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+			     void *port_driver_priv, struct net_device *dev,
+			     bool split, u32 split_group);
+void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u8 local_port,
+			    void *port_driver_priv);
+void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u8 local_port,
+			   void *port_driver_priv);
+enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
+						u8 local_port);
 
 int mlxsw_core_schedule_dw(struct delayed_work *dwork, unsigned long delay);
+int mlxsw_core_schedule_odw(struct delayed_work *dwork, unsigned long delay);
+void mlxsw_core_flush_owq(void);
 
 #define MLXSW_CONFIG_PROFILE_SWID_COUNT 8
 
@@ -221,11 +263,13 @@ struct mlxsw_config_profile {
 struct mlxsw_driver {
 	struct list_head list;
 	const char *kind;
-	struct module *owner;
 	size_t priv_size;
 	int (*init)(struct mlxsw_core *mlxsw_core,
 		    const struct mlxsw_bus_info *mlxsw_bus_info);
 	void (*fini)(struct mlxsw_core *mlxsw_core);
+	int (*basic_trap_groups_set)(struct mlxsw_core *mlxsw_core);
+	int (*port_type_set)(struct mlxsw_core *mlxsw_core, u8 local_port,
+			     enum devlink_port_type new_type);
 	int (*port_split)(struct mlxsw_core *mlxsw_core, u8 local_port,
 			  unsigned int count);
 	int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u8 local_port);
@@ -266,45 +310,25 @@ struct mlxsw_driver {
 	const struct mlxsw_config_profile *profile;
 };
 
-struct mlxsw_resources {
-	u32	max_span_valid:1,
-		max_lag_valid:1,
-		max_ports_in_lag_valid:1,
-		kvd_size_valid:1,
-		kvd_single_min_size_valid:1,
-		kvd_double_min_size_valid:1,
-		max_virtual_routers_valid:1,
-		max_system_ports_valid:1,
-		max_vlan_groups_valid:1,
-		max_regions_valid:1,
-		max_rif_valid:1;
-	u8      max_span;
-	u8	max_lag;
-	u8	max_ports_in_lag;
-	u32	kvd_size;
-	u32	kvd_single_min_size;
-	u32	kvd_double_min_size;
-	u16     max_virtual_routers;
-	u16	max_system_ports;
-	u16	max_vlan_groups;
-	u16	max_regions;
-	u16	max_rif;
+bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
+			  enum mlxsw_res_id res_id);
 
-	/* Internal resources.
-	 * Determined by the SW, not queried from the HW.
-	 */
-	u32	kvd_single_size;
-	u32	kvd_double_size;
-	u32	kvd_linear_size;
-};
+#define MLXSW_CORE_RES_VALID(res, short_res_id)			\
+	mlxsw_core_res_valid(res, MLXSW_RES_ID_##short_res_id)
 
-struct mlxsw_resources *mlxsw_core_resources_get(struct mlxsw_core *mlxsw_core);
+u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
+		       enum mlxsw_res_id res_id);
+
+#define MLXSW_CORE_RES_GET(res, short_res_id)			\
+	mlxsw_core_res_get(res, MLXSW_RES_ID_##short_res_id)
+
+#define MLXSW_BUS_F_TXRX	BIT(0)
 
 struct mlxsw_bus {
 	const char *kind;
 	int (*init)(void *bus_priv, struct mlxsw_core *mlxsw_core,
 		    const struct mlxsw_config_profile *profile,
-		    struct mlxsw_resources *resources);
+		    struct mlxsw_res *res);
 	void (*fini)(void *bus_priv);
 	bool (*skb_transmit_busy)(void *bus_priv,
 				  const struct mlxsw_tx_info *tx_info);
@@ -315,6 +339,7 @@ struct mlxsw_bus {
 			char *in_mbox, size_t in_mbox_size,
 			char *out_mbox, size_t out_mbox_size,
 			u8 *p_status);
+	u8 features;
 };
 
 struct mlxsw_bus_info {
@@ -349,5 +374,29 @@ static inline int mlxsw_hwmon_init(struc
 }
 
 #endif
+
+struct mlxsw_thermal;
+
+#ifdef CONFIG_MLXSW_CORE_THERMAL
+
+int mlxsw_thermal_init(struct mlxsw_core *mlxsw_core,
+		       const struct mlxsw_bus_info *mlxsw_bus_info,
+		       struct mlxsw_thermal **p_thermal);
+void mlxsw_thermal_fini(struct mlxsw_thermal *thermal);
+
+#else
+
+static inline int mlxsw_thermal_init(struct mlxsw_core *mlxsw_core,
+				     const struct mlxsw_bus_info *mlxsw_bus_info,
+				     struct mlxsw_thermal **p_thermal)
+{
+	return 0;
+}
+
+static inline void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
+{
+}
+
+#endif
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c	2017-02-12 16:03:20.000000000 -0500
@@ -262,7 +262,7 @@ static void mlxsw_hwmon_attr_add(struct
 
 static int mlxsw_hwmon_temp_init(struct mlxsw_hwmon *mlxsw_hwmon)
 {
-	char mtcap_pl[MLXSW_REG_MTCAP_LEN];
+	char mtcap_pl[MLXSW_REG_MTCAP_LEN] = {0};
 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
 	u8 sensor_count;
 	int i;
@@ -295,7 +295,7 @@ static int mlxsw_hwmon_temp_init(struct
 
 static int mlxsw_hwmon_fans_init(struct mlxsw_hwmon *mlxsw_hwmon)
 {
-	char mfcr_pl[MLXSW_REG_MFCR_LEN];
+	char mfcr_pl[MLXSW_REG_MFCR_LEN] = {0};
 	enum mlxsw_reg_mfcr_pwm_frequency freq;
 	unsigned int type_index;
 	unsigned int num;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,442 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+ * Copyright (c) 2016 Ivan Vecera <cera@cera.cz>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/thermal.h>
+#include <linux/err.h>
+
+#include "core.h"
+
+#define MLXSW_THERMAL_POLL_INT	1000	/* ms */
+#define MLXSW_THERMAL_MAX_TEMP	110000	/* 110C */
+#define MLXSW_THERMAL_MAX_STATE	10
+#define MLXSW_THERMAL_MAX_DUTY	255
+
+struct mlxsw_thermal_trip {
+	int	type;
+	int	temp;
+	int	min_state;
+	int	max_state;
+};
+
+static const struct mlxsw_thermal_trip default_thermal_trips[] = {
+	{	/* In range - 0-40% PWM */
+		.type		= THERMAL_TRIP_ACTIVE,
+		.temp		= 75000,
+		.min_state	= 0,
+		.max_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
+	},
+	{	/* High - 40-100% PWM */
+		.type		= THERMAL_TRIP_ACTIVE,
+		.temp		= 80000,
+		.min_state	= (4 * MLXSW_THERMAL_MAX_STATE) / 10,
+		.max_state	= MLXSW_THERMAL_MAX_STATE,
+	},
+	{
+		/* Very high - 100% PWM */
+		.type		= THERMAL_TRIP_ACTIVE,
+		.temp		= 85000,
+		.min_state	= MLXSW_THERMAL_MAX_STATE,
+		.max_state	= MLXSW_THERMAL_MAX_STATE,
+	},
+	{	/* Warning */
+		.type		= THERMAL_TRIP_HOT,
+		.temp		= 105000,
+		.min_state	= MLXSW_THERMAL_MAX_STATE,
+		.max_state	= MLXSW_THERMAL_MAX_STATE,
+	},
+	{	/* Critical - soft poweroff */
+		.type		= THERMAL_TRIP_CRITICAL,
+		.temp		= MLXSW_THERMAL_MAX_TEMP,
+		.min_state	= MLXSW_THERMAL_MAX_STATE,
+		.max_state	= MLXSW_THERMAL_MAX_STATE,
+	}
+};
+
+#define MLXSW_THERMAL_NUM_TRIPS	ARRAY_SIZE(default_thermal_trips)
+
+/* Make sure all trips are writable */
+#define MLXSW_THERMAL_TRIP_MASK	(BIT(MLXSW_THERMAL_NUM_TRIPS) - 1)
+
+struct mlxsw_thermal {
+	struct mlxsw_core *core;
+	const struct mlxsw_bus_info *bus_info;
+	struct thermal_zone_device *tzdev;
+	struct thermal_cooling_device *cdevs[MLXSW_MFCR_PWMS_MAX];
+	struct mlxsw_thermal_trip trips[MLXSW_THERMAL_NUM_TRIPS];
+	enum thermal_device_mode mode;
+};
+
+static inline u8 mlxsw_state_to_duty(int state)
+{
+	return DIV_ROUND_CLOSEST(state * MLXSW_THERMAL_MAX_DUTY,
+				 MLXSW_THERMAL_MAX_STATE);
+}
+
+static inline int mlxsw_duty_to_state(u8 duty)
+{
+	return DIV_ROUND_CLOSEST(duty * MLXSW_THERMAL_MAX_STATE,
+				 MLXSW_THERMAL_MAX_DUTY);
+}
+
+static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
+					struct thermal_cooling_device *cdev)
+{
+	int i;
+
+	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
+		if (thermal->cdevs[i] == cdev)
+			return i;
+
+	return -ENODEV;
+}
+
+static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
+			      struct thermal_cooling_device *cdev)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+	struct device *dev = thermal->bus_info->dev;
+	int i, err;
+
+	/* If the cooling device is one of ours bind it */
+	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
+		return 0;
+
+	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
+		const struct mlxsw_thermal_trip *trip = &thermal->trips[i];
+
+		err = thermal_zone_bind_cooling_device(tzdev, i, cdev,
+						       trip->max_state,
+						       trip->min_state,
+						       THERMAL_WEIGHT_DEFAULT);
+		if (err < 0) {
+			dev_err(dev, "Failed to bind cooling device to trip %d\n", i);
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
+				struct thermal_cooling_device *cdev)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+	struct device *dev = thermal->bus_info->dev;
+	int i;
+	int err;
+
+	/* If the cooling device is our one unbind it */
+	if (mlxsw_get_cooling_device_idx(thermal, cdev) < 0)
+		return 0;
+
+	for (i = 0; i < MLXSW_THERMAL_NUM_TRIPS; i++) {
+		err = thermal_zone_unbind_cooling_device(tzdev, i, cdev);
+		if (err < 0) {
+			dev_err(dev, "Failed to unbind cooling device\n");
+			return err;
+		}
+	}
+	return 0;
+}
+
+static int mlxsw_thermal_get_mode(struct thermal_zone_device *tzdev,
+				  enum thermal_device_mode *mode)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+
+	*mode = thermal->mode;
+
+	return 0;
+}
+
+static int mlxsw_thermal_set_mode(struct thermal_zone_device *tzdev,
+				  enum thermal_device_mode mode)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+
+	mutex_lock(&tzdev->lock);
+
+	if (mode == THERMAL_DEVICE_ENABLED)
+		tzdev->polling_delay = MLXSW_THERMAL_POLL_INT;
+	else
+		tzdev->polling_delay = 0;
+
+	mutex_unlock(&tzdev->lock);
+
+	thermal->mode = mode;
+	thermal_zone_device_update(tzdev, THERMAL_EVENT_UNSPECIFIED);
+
+	return 0;
+}
+
+static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
+				  int *p_temp)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+	struct device *dev = thermal->bus_info->dev;
+	char mtmp_pl[MLXSW_REG_MTMP_LEN];
+	unsigned int temp;
+	int err;
+
+	mlxsw_reg_mtmp_pack(mtmp_pl, 0, false, false);
+
+	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
+	if (err) {
+		dev_err(dev, "Failed to query temp sensor\n");
+		return err;
+	}
+	mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
+
+	*p_temp = (int) temp;
+	return 0;
+}
+
+static int mlxsw_thermal_get_trip_type(struct thermal_zone_device *tzdev,
+				       int trip,
+				       enum thermal_trip_type *p_type)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+
+	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+		return -EINVAL;
+
+	*p_type = thermal->trips[trip].type;
+	return 0;
+}
+
+static int mlxsw_thermal_get_trip_temp(struct thermal_zone_device *tzdev,
+				       int trip, int *p_temp)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+
+	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+		return -EINVAL;
+
+	*p_temp = thermal->trips[trip].temp;
+	return 0;
+}
+
+static int mlxsw_thermal_set_trip_temp(struct thermal_zone_device *tzdev,
+				       int trip, int temp)
+{
+	struct mlxsw_thermal *thermal = tzdev->devdata;
+
+	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS ||
+	    temp > MLXSW_THERMAL_MAX_TEMP)
+		return -EINVAL;
+
+	thermal->trips[trip].temp = temp;
+	return 0;
+}
+
+static struct thermal_zone_device_ops mlxsw_thermal_ops = {
+	.bind = mlxsw_thermal_bind,
+	.unbind = mlxsw_thermal_unbind,
+	.get_mode = mlxsw_thermal_get_mode,
+	.set_mode = mlxsw_thermal_set_mode,
+	.get_temp = mlxsw_thermal_get_temp,
+	.get_trip_type	= mlxsw_thermal_get_trip_type,
+	.get_trip_temp	= mlxsw_thermal_get_trip_temp,
+	.set_trip_temp	= mlxsw_thermal_set_trip_temp,
+};
+
+static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
+				       unsigned long *p_state)
+{
+	*p_state = MLXSW_THERMAL_MAX_STATE;
+	return 0;
+}
+
+static int mlxsw_thermal_get_cur_state(struct thermal_cooling_device *cdev,
+				       unsigned long *p_state)
+
+{
+	struct mlxsw_thermal *thermal = cdev->devdata;
+	struct device *dev = thermal->bus_info->dev;
+	char mfsc_pl[MLXSW_REG_MFSC_LEN];
+	int err, idx;
+	u8 duty;
+
+	idx = mlxsw_get_cooling_device_idx(thermal, cdev);
+	if (idx < 0)
+		return idx;
+
+	mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
+	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
+	if (err) {
+		dev_err(dev, "Failed to query PWM duty\n");
+		return err;
+	}
+
+	duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
+	*p_state = mlxsw_duty_to_state(duty);
+	return 0;
+}
+
+static int mlxsw_thermal_set_cur_state(struct thermal_cooling_device *cdev,
+				       unsigned long state)
+
+{
+	struct mlxsw_thermal *thermal = cdev->devdata;
+	struct device *dev = thermal->bus_info->dev;
+	char mfsc_pl[MLXSW_REG_MFSC_LEN];
+	int err, idx;
+
+	idx = mlxsw_get_cooling_device_idx(thermal, cdev);
+	if (idx < 0)
+		return idx;
+
+	mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
+	err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
+	if (err) {
+		dev_err(dev, "Failed to write PWM duty\n");
+		return err;
+	}
+	return 0;
+}
+
+static const struct thermal_cooling_device_ops mlxsw_cooling_ops = {
+	.get_max_state	= mlxsw_thermal_get_max_state,
+	.get_cur_state	= mlxsw_thermal_get_cur_state,
+	.set_cur_state	= mlxsw_thermal_set_cur_state,
+};
+
+int mlxsw_thermal_init(struct mlxsw_core *core,
+		       const struct mlxsw_bus_info *bus_info,
+		       struct mlxsw_thermal **p_thermal)
+{
+	char mfcr_pl[MLXSW_REG_MFCR_LEN] = { 0 };
+	enum mlxsw_reg_mfcr_pwm_frequency freq;
+	struct device *dev = bus_info->dev;
+	struct mlxsw_thermal *thermal;
+	u16 tacho_active;
+	u8 pwm_active;
+	int err, i;
+
+	thermal = devm_kzalloc(dev, sizeof(*thermal),
+			       GFP_KERNEL);
+	if (!thermal)
+		return -ENOMEM;
+
+	thermal->core = core;
+	thermal->bus_info = bus_info;
+	memcpy(thermal->trips, default_thermal_trips, sizeof(thermal->trips));
+
+	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfcr), mfcr_pl);
+	if (err) {
+		dev_err(dev, "Failed to probe PWMs\n");
+		goto err_free_thermal;
+	}
+	mlxsw_reg_mfcr_unpack(mfcr_pl, &freq, &tacho_active, &pwm_active);
+
+	for (i = 0; i < MLXSW_MFCR_TACHOS_MAX; i++) {
+		if (tacho_active & BIT(i)) {
+			char mfsl_pl[MLXSW_REG_MFSL_LEN];
+
+			mlxsw_reg_mfsl_pack(mfsl_pl, i, 0, 0);
+
+			/* We need to query the register to preserve maximum */
+			err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsl),
+					      mfsl_pl);
+			if (err)
+				goto err_free_thermal;
+
+			/* set the minimal RPMs to 0 */
+			mlxsw_reg_mfsl_tach_min_set(mfsl_pl, 0);
+			err = mlxsw_reg_write(thermal->core, MLXSW_REG(mfsl),
+					      mfsl_pl);
+			if (err)
+				goto err_free_thermal;
+		}
+	}
+	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
+		if (pwm_active & BIT(i)) {
+			struct thermal_cooling_device *cdev;
+
+			cdev = thermal_cooling_device_register("Fan", thermal,
+							&mlxsw_cooling_ops);
+			if (IS_ERR(cdev)) {
+				err = PTR_ERR(cdev);
+				dev_err(dev, "Failed to register cooling device\n");
+				goto err_unreg_cdevs;
+			}
+			thermal->cdevs[i] = cdev;
+		}
+	}
+
+	thermal->tzdev = thermal_zone_device_register("mlxsw",
+						      MLXSW_THERMAL_NUM_TRIPS,
+						      MLXSW_THERMAL_TRIP_MASK,
+						      thermal,
+						      &mlxsw_thermal_ops,
+						      NULL, 0,
+						      MLXSW_THERMAL_POLL_INT);
+	if (IS_ERR(thermal->tzdev)) {
+		err = PTR_ERR(thermal->tzdev);
+		dev_err(dev, "Failed to register thermal zone\n");
+		goto err_unreg_cdevs;
+	}
+
+	thermal->mode = THERMAL_DEVICE_ENABLED;
+	*p_thermal = thermal;
+	return 0;
+err_unreg_cdevs:
+	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++)
+		if (thermal->cdevs[i])
+			thermal_cooling_device_unregister(thermal->cdevs[i]);
+err_free_thermal:
+	devm_kfree(dev, thermal);
+	return err;
+}
+
+void mlxsw_thermal_fini(struct mlxsw_thermal *thermal)
+{
+	int i;
+
+	if (thermal->tzdev) {
+		thermal_zone_device_unregister(thermal->tzdev);
+		thermal->tzdev = NULL;
+	}
+
+	for (i = 0; i < MLXSW_MFCR_PWMS_MAX; i++) {
+		if (thermal->cdevs[i]) {
+			thermal_cooling_device_unregister(thermal->cdevs[i]);
+			thermal->cdevs[i] = NULL;
+		}
+	}
+
+	devm_kfree(thermal->bus_info->dev, thermal);
+}
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,582 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/i2c.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include "cmd.h"
+#include "core.h"
+#include "i2c.h"
+
+static const char mlxsw_i2c_driver_name[] = "mlxsw_i2c";
+
+#define MLXSW_I2C_CIR2_BASE		0x72000
+#define MLXSW_I2C_CIR_STATUS_OFF	0x18
+#define MLXSW_I2C_CIR2_OFF_STATUS	(MLXSW_I2C_CIR2_BASE + \
+					 MLXSW_I2C_CIR_STATUS_OFF)
+#define MLXSW_I2C_OPMOD_SHIFT		12
+#define MLXSW_I2C_GO_BIT_SHIFT		23
+#define MLXSW_I2C_CIR_CTRL_STATUS_SHIFT	24
+#define MLXSW_I2C_GO_BIT		BIT(MLXSW_I2C_GO_BIT_SHIFT)
+#define MLXSW_I2C_GO_OPMODE		BIT(MLXSW_I2C_OPMOD_SHIFT)
+#define MLXSW_I2C_SET_IMM_CMD		(MLXSW_I2C_GO_OPMODE | \
+					 MLXSW_CMD_OPCODE_QUERY_FW)
+#define MLXSW_I2C_PUSH_IMM_CMD		(MLXSW_I2C_GO_BIT | \
+					 MLXSW_I2C_SET_IMM_CMD)
+#define MLXSW_I2C_SET_CMD		(MLXSW_CMD_OPCODE_ACCESS_REG)
+#define MLXSW_I2C_PUSH_CMD		(MLXSW_I2C_GO_BIT | MLXSW_I2C_SET_CMD)
+#define MLXSW_I2C_TLV_HDR_SIZE		0x10
+#define MLXSW_I2C_ADDR_WIDTH		4
+#define MLXSW_I2C_PUSH_CMD_SIZE		(MLXSW_I2C_ADDR_WIDTH + 4)
+#define MLXSW_I2C_READ_SEMA_SIZE	4
+#define MLXSW_I2C_PREP_SIZE		(MLXSW_I2C_ADDR_WIDTH + 28)
+#define MLXSW_I2C_MBOX_SIZE		20
+#define MLXSW_I2C_MBOX_OUT_PARAM_OFF	12
+#define MLXSW_I2C_MAX_BUFF_SIZE		32
+#define MLXSW_I2C_MBOX_OFFSET_BITS	20
+#define MLXSW_I2C_MBOX_SIZE_BITS	12
+#define MLXSW_I2C_ADDR_BUF_SIZE		4
+#define MLXSW_I2C_BLK_MAX		32
+#define MLXSW_I2C_RETRY			5
+#define MLXSW_I2C_TIMEOUT_MSECS		5000
+
+/**
+ * struct mlxsw_i2c - device private data:
+ * @cmd.mb_size_in: input mailbox size;
+ * @cmd.mb_off_in: input mailbox offset in register space;
+ * @cmd.mb_size_out: output mailbox size;
+ * @cmd.mb_off_out: output mailbox offset in register space;
+ * @cmd.lock: command execution lock;
+ * @dev: I2C device;
+ * @core: switch core pointer;
+ * @bus_info: bus info block;
+ */
+struct mlxsw_i2c {
+	struct {
+		u32 mb_size_in;
+		u32 mb_off_in;
+		u32 mb_size_out;
+		u32 mb_off_out;
+		struct mutex lock;
+	} cmd;
+	struct device *dev;
+	struct mlxsw_core *core;
+	struct mlxsw_bus_info bus_info;
+};
+
+#define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) {	\
+	{ .addr = (_client)->addr,				\
+	  .buf = (_addr_buf),					\
+	  .len = MLXSW_I2C_ADDR_BUF_SIZE,			\
+	  .flags = 0 },						\
+	{ .addr = (_client)->addr,				\
+	  .buf = (_buf),					\
+	  .len = (_len),					\
+	  .flags = I2C_M_RD } }
+
+#define MLXSW_I2C_WRITE_MSG(_client, _buf, _len)		\
+	{ .addr = (_client)->addr,				\
+	  .buf = (u8 *)(_buf),					\
+	  .len = (_len),					\
+	  .flags = 0 }
+
+/* Routine converts in and out mail boxes offset and size. */
+static inline void
+mlxsw_i2c_convert_mbox(struct mlxsw_i2c *mlxsw_i2c, u8 *buf)
+{
+	u32 tmp;
+
+	/* Local in/out mailboxes: 20 bits for offset, 12 for size */
+	tmp = be32_to_cpup((__be32 *) buf);
+	mlxsw_i2c->cmd.mb_off_in = tmp &
+				   GENMASK(MLXSW_I2C_MBOX_OFFSET_BITS - 1, 0);
+	mlxsw_i2c->cmd.mb_size_in = (tmp & GENMASK(31,
+					MLXSW_I2C_MBOX_OFFSET_BITS)) >>
+					MLXSW_I2C_MBOX_OFFSET_BITS;
+
+	tmp = be32_to_cpup((__be32 *) (buf + MLXSW_I2C_ADDR_WIDTH));
+	mlxsw_i2c->cmd.mb_off_out = tmp &
+				    GENMASK(MLXSW_I2C_MBOX_OFFSET_BITS - 1, 0);
+	mlxsw_i2c->cmd.mb_size_out = (tmp & GENMASK(31,
+					MLXSW_I2C_MBOX_OFFSET_BITS)) >>
+					MLXSW_I2C_MBOX_OFFSET_BITS;
+}
+
+/* Routine obtains register size from mail box buffer. */
+static inline int mlxsw_i2c_get_reg_size(u8 *in_mbox)
+{
+	u16  tmp = be16_to_cpup((__be16 *) (in_mbox + MLXSW_I2C_TLV_HDR_SIZE));
+
+	return (tmp & 0x7ff) * 4 + MLXSW_I2C_TLV_HDR_SIZE;
+}
+
+/* Routine sets I2C device internal offset in the transaction buffer. */
+static inline void mlxsw_i2c_set_slave_addr(u8 *buf, u32 off)
+{
+	__be32 *val = (__be32 *) buf;
+
+	*val = htonl(off);
+}
+
+/* Routine waits until go bit is cleared. */
+static int mlxsw_i2c_wait_go_bit(struct i2c_client *client,
+				 struct mlxsw_i2c *mlxsw_i2c, u8 *p_status)
+{
+	u8 addr_buf[MLXSW_I2C_ADDR_BUF_SIZE];
+	u8 buf[MLXSW_I2C_READ_SEMA_SIZE];
+	int len = MLXSW_I2C_READ_SEMA_SIZE;
+	struct i2c_msg read_sema[] =
+		MLXSW_I2C_READ_MSG(client, addr_buf, buf, len);
+	bool wait_done = false;
+	unsigned long end;
+	int i = 0, err;
+
+	mlxsw_i2c_set_slave_addr(addr_buf, MLXSW_I2C_CIR2_OFF_STATUS);
+
+	end = jiffies + msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
+	do {
+		u32 ctrl;
+
+		err = i2c_transfer(client->adapter, read_sema,
+				   ARRAY_SIZE(read_sema));
+
+		ctrl = be32_to_cpu(*(__be32 *) buf);
+		if (err == ARRAY_SIZE(read_sema)) {
+			if (!(ctrl & MLXSW_I2C_GO_BIT)) {
+				wait_done = true;
+				*p_status = ctrl >>
+					    MLXSW_I2C_CIR_CTRL_STATUS_SHIFT;
+				break;
+			}
+		}
+		cond_resched();
+	} while ((time_before(jiffies, end)) || (i++ < MLXSW_I2C_RETRY));
+
+	if (wait_done) {
+		if (*p_status)
+			err = -EIO;
+	} else {
+		return -ETIMEDOUT;
+	}
+
+	return err > 0 ? 0 : err;
+}
+
+/* Routine posts a command to ASIC though mail box. */
+static int mlxsw_i2c_write_cmd(struct i2c_client *client,
+			       struct mlxsw_i2c *mlxsw_i2c,
+			       int immediate)
+{
+	__be32 push_cmd_buf[MLXSW_I2C_PUSH_CMD_SIZE / 4] = {
+		0, cpu_to_be32(MLXSW_I2C_PUSH_IMM_CMD)
+	};
+	__be32 prep_cmd_buf[MLXSW_I2C_PREP_SIZE / 4] = {
+		0, 0, 0, 0, 0, 0,
+		cpu_to_be32(client->adapter->nr & 0xffff),
+		cpu_to_be32(MLXSW_I2C_SET_IMM_CMD)
+	};
+	struct i2c_msg push_cmd =
+		MLXSW_I2C_WRITE_MSG(client, push_cmd_buf,
+				    MLXSW_I2C_PUSH_CMD_SIZE);
+	struct i2c_msg prep_cmd =
+		MLXSW_I2C_WRITE_MSG(client, prep_cmd_buf, MLXSW_I2C_PREP_SIZE);
+	int err;
+
+	if (!immediate) {
+		push_cmd_buf[1] = cpu_to_be32(MLXSW_I2C_PUSH_CMD);
+		prep_cmd_buf[7] = cpu_to_be32(MLXSW_I2C_SET_CMD);
+	}
+	mlxsw_i2c_set_slave_addr((u8 *)prep_cmd_buf,
+				 MLXSW_I2C_CIR2_BASE);
+	mlxsw_i2c_set_slave_addr((u8 *)push_cmd_buf,
+				 MLXSW_I2C_CIR2_OFF_STATUS);
+
+	/* Prepare Command Interface Register for transaction */
+	err = i2c_transfer(client->adapter, &prep_cmd, 1);
+	if (err < 0)
+		return err;
+	else if (err != 1)
+		return -EIO;
+
+	/* Write out Command Interface Register GO bit to push transaction */
+	err = i2c_transfer(client->adapter, &push_cmd, 1);
+	if (err < 0)
+		return err;
+	else if (err != 1)
+		return -EIO;
+
+	return 0;
+}
+
+/* Routine obtains mail box offsets from ASIC register space. */
+static int mlxsw_i2c_get_mbox(struct i2c_client *client,
+			      struct mlxsw_i2c *mlxsw_i2c)
+{
+	u8 addr_buf[MLXSW_I2C_ADDR_BUF_SIZE];
+	u8 buf[MLXSW_I2C_MBOX_SIZE];
+	struct i2c_msg mbox_cmd[] =
+		MLXSW_I2C_READ_MSG(client, addr_buf, buf, MLXSW_I2C_MBOX_SIZE);
+	int err;
+
+	/* Read mail boxes offsets. */
+	mlxsw_i2c_set_slave_addr(addr_buf, MLXSW_I2C_CIR2_BASE);
+	err = i2c_transfer(client->adapter, mbox_cmd, 2);
+	if (err != 2) {
+		dev_err(&client->dev, "Could not obtain mail boxes\n");
+		if (!err)
+			return -EIO;
+		else
+			return err;
+	}
+
+	/* Convert mail boxes. */
+	mlxsw_i2c_convert_mbox(mlxsw_i2c, &buf[MLXSW_I2C_MBOX_OUT_PARAM_OFF]);
+
+	return err;
+}
+
+/* Routine sends I2C write transaction to ASIC device. */
+static int
+mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
+		u8 *p_status)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
+	unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
+	u8 tran_buf[MLXSW_I2C_MAX_BUFF_SIZE + MLXSW_I2C_ADDR_BUF_SIZE];
+	int off = mlxsw_i2c->cmd.mb_off_in, chunk_size, i, j;
+	unsigned long end;
+	struct i2c_msg write_tran =
+		MLXSW_I2C_WRITE_MSG(client, tran_buf, MLXSW_I2C_PUSH_CMD_SIZE);
+	int err;
+
+	for (i = 0; i < num; i++) {
+		chunk_size = (in_mbox_size > MLXSW_I2C_BLK_MAX) ?
+			     MLXSW_I2C_BLK_MAX : in_mbox_size;
+		write_tran.len = MLXSW_I2C_ADDR_WIDTH + chunk_size;
+		mlxsw_i2c_set_slave_addr(tran_buf, off);
+		memcpy(&tran_buf[MLXSW_I2C_ADDR_BUF_SIZE], in_mbox +
+		       chunk_size * i, chunk_size);
+
+		j = 0;
+		end = jiffies + timeout;
+		do {
+			err = i2c_transfer(client->adapter, &write_tran, 1);
+			if (err == 1)
+				break;
+
+			cond_resched();
+		} while ((time_before(jiffies, end)) ||
+			 (j++ < MLXSW_I2C_RETRY));
+
+		if (err != 1) {
+			if (!err)
+				err = -EIO;
+			return err;
+		}
+
+		off += chunk_size;
+		in_mbox_size -= chunk_size;
+	}
+
+	/* Prepare and write out Command Interface Register for transaction. */
+	err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 0);
+	if (err) {
+		dev_err(&client->dev, "Could not start transaction");
+		return -EIO;
+	}
+
+	/* Wait until go bit is cleared. */
+	err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, p_status);
+	if (err) {
+		dev_err(&client->dev, "HW semaphore is not released");
+		return err;
+	}
+
+	/* Validate transaction completion status. */
+	if (*p_status) {
+		dev_err(&client->dev, "Bad transaction completion status %x\n",
+			*p_status);
+		return -EIO;
+	}
+
+	return err > 0 ? 0 : err;
+}
+
+/* Routine executes I2C command. */
+static int
+mlxsw_i2c_cmd(struct device *dev, size_t in_mbox_size, u8 *in_mbox,
+	      size_t out_mbox_size, u8 *out_mbox, u8 *status)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
+	unsigned long timeout = msecs_to_jiffies(MLXSW_I2C_TIMEOUT_MSECS);
+	u8 tran_buf[MLXSW_I2C_ADDR_BUF_SIZE];
+	int num, chunk_size, reg_size, i, j;
+	int off = mlxsw_i2c->cmd.mb_off_out;
+	unsigned long end;
+	struct i2c_msg read_tran[] =
+		MLXSW_I2C_READ_MSG(client, tran_buf, NULL, 0);
+	int err;
+
+	WARN_ON(in_mbox_size % sizeof(u32) || out_mbox_size % sizeof(u32));
+
+	reg_size = mlxsw_i2c_get_reg_size(in_mbox);
+	num = reg_size / MLXSW_I2C_BLK_MAX;
+	if (reg_size % MLXSW_I2C_BLK_MAX)
+		num++;
+
+	if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
+		dev_err(&client->dev, "Could not acquire lock");
+		return -EINVAL;
+	}
+
+	err = mlxsw_i2c_write(dev, reg_size, in_mbox, num, status);
+	if (err)
+		goto cmd_fail;
+
+	/* No out mailbox is case of write transaction. */
+	if (!out_mbox) {
+		mutex_unlock(&mlxsw_i2c->cmd.lock);
+		return 0;
+	}
+
+	/* Send read transaction to get output mailbox content. */
+	read_tran[1].buf = out_mbox;
+	for (i = 0; i < num; i++) {
+		chunk_size = (reg_size > MLXSW_I2C_BLK_MAX) ?
+			     MLXSW_I2C_BLK_MAX : reg_size;
+		read_tran[1].len = chunk_size;
+		mlxsw_i2c_set_slave_addr(tran_buf, off);
+
+		j = 0;
+		end = jiffies + timeout;
+		do {
+			err = i2c_transfer(client->adapter, read_tran,
+					   ARRAY_SIZE(read_tran));
+			if (err == ARRAY_SIZE(read_tran))
+				break;
+
+			cond_resched();
+		} while ((time_before(jiffies, end)) ||
+			 (j++ < MLXSW_I2C_RETRY));
+
+		if (err != ARRAY_SIZE(read_tran)) {
+			if (!err)
+				err = -EIO;
+
+			goto cmd_fail;
+		}
+
+		off += chunk_size;
+		reg_size -= chunk_size;
+		read_tran[1].buf += chunk_size;
+	}
+
+	mutex_unlock(&mlxsw_i2c->cmd.lock);
+
+	return 0;
+
+cmd_fail:
+	mutex_unlock(&mlxsw_i2c->cmd.lock);
+	return err;
+}
+
+static int mlxsw_i2c_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
+			      u32 in_mod, bool out_mbox_direct,
+			      char *in_mbox, size_t in_mbox_size,
+			      char *out_mbox, size_t out_mbox_size,
+			      u8 *status)
+{
+	struct mlxsw_i2c *mlxsw_i2c = bus_priv;
+
+	return mlxsw_i2c_cmd(mlxsw_i2c->dev, in_mbox_size, in_mbox,
+			     out_mbox_size, out_mbox, status);
+}
+
+static bool mlxsw_i2c_skb_transmit_busy(void *bus_priv,
+					const struct mlxsw_tx_info *tx_info)
+{
+	return false;
+}
+
+static int mlxsw_i2c_skb_transmit(void *bus_priv, struct sk_buff *skb,
+				  const struct mlxsw_tx_info *tx_info)
+{
+	return 0;
+}
+
+static int
+mlxsw_i2c_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
+	       const struct mlxsw_config_profile *profile,
+	       struct mlxsw_res *resources)
+{
+	struct mlxsw_i2c *mlxsw_i2c = bus_priv;
+
+	mlxsw_i2c->core = mlxsw_core;
+
+	return 0;
+}
+
+static void mlxsw_i2c_fini(void *bus_priv)
+{
+	struct mlxsw_i2c *mlxsw_i2c = bus_priv;
+
+	mlxsw_i2c->core = NULL;
+}
+
+static const struct mlxsw_bus mlxsw_i2c_bus = {
+	.kind			= "i2c",
+	.init			= mlxsw_i2c_init,
+	.fini			= mlxsw_i2c_fini,
+	.skb_transmit_busy	= mlxsw_i2c_skb_transmit_busy,
+	.skb_transmit		= mlxsw_i2c_skb_transmit,
+	.cmd_exec		= mlxsw_i2c_cmd_exec,
+};
+
+static int mlxsw_i2c_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct mlxsw_i2c *mlxsw_i2c;
+	u8 status;
+	int err;
+
+	mlxsw_i2c = devm_kzalloc(&client->dev, sizeof(*mlxsw_i2c), GFP_KERNEL);
+	if (!mlxsw_i2c)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, mlxsw_i2c);
+	mutex_init(&mlxsw_i2c->cmd.lock);
+
+	/* In order to use mailboxes through the i2c, special area is reserved
+	 * on the i2c address space that can be used for input and output
+	 * mailboxes. Such mailboxes are called local mailboxes. When using a
+	 * local mailbox, software should specify 0 as the Input/Output
+	 * parameters. The location of the Local Mailbox addresses on the i2c
+	 * space can be retrieved through the QUERY_FW command.
+	 * For this purpose QUERY_FW is to be issued with opcode modifier equal
+	 * 0x01. For such command the output parameter is an immediate value.
+	 * Here QUERY_FW command is invoked for ASIC probing and for getting
+	 * local mailboxes addresses from immedate output parameters.
+	 */
+
+	/* Prepare and write out Command Interface Register for transaction */
+	err = mlxsw_i2c_write_cmd(client, mlxsw_i2c, 1);
+	if (err) {
+		dev_err(&client->dev, "Could not start transaction");
+		goto errout;
+	}
+
+	/* Wait until go bit is cleared. */
+	err = mlxsw_i2c_wait_go_bit(client, mlxsw_i2c, &status);
+	if (err) {
+		dev_err(&client->dev, "HW semaphore is not released");
+		goto errout;
+	}
+
+	/* Validate transaction completion status. */
+	if (status) {
+		dev_err(&client->dev, "Bad transaction completion status %x\n",
+			status);
+		err = -EIO;
+		goto errout;
+	}
+
+	/* Get mailbox offsets. */
+	err = mlxsw_i2c_get_mbox(client, mlxsw_i2c);
+	if (err < 0) {
+		dev_err(&client->dev, "Fail to get mailboxes\n");
+		goto errout;
+	}
+
+	dev_info(&client->dev, "%s mb size=%x off=0x%08x out mb size=%x off=0x%08x\n",
+		 id->name, mlxsw_i2c->cmd.mb_size_in,
+		 mlxsw_i2c->cmd.mb_off_in, mlxsw_i2c->cmd.mb_size_out,
+		 mlxsw_i2c->cmd.mb_off_out);
+
+	/* Register device bus. */
+	mlxsw_i2c->bus_info.device_kind = id->name;
+	mlxsw_i2c->bus_info.device_name = client->name;
+	mlxsw_i2c->bus_info.dev = &client->dev;
+	mlxsw_i2c->dev = &client->dev;
+
+	err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
+					     &mlxsw_i2c_bus, mlxsw_i2c);
+	if (err) {
+		dev_err(&client->dev, "Fail to register core bus\n");
+		return err;
+	}
+
+	return 0;
+
+errout:
+	i2c_set_clientdata(client, NULL);
+
+	return err;
+}
+
+static int mlxsw_i2c_remove(struct i2c_client *client)
+{
+	struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
+
+	mlxsw_core_bus_device_unregister(mlxsw_i2c->core);
+	mutex_destroy(&mlxsw_i2c->cmd.lock);
+
+	return 0;
+}
+
+int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
+{
+	i2c_driver->probe = mlxsw_i2c_probe;
+	i2c_driver->remove = mlxsw_i2c_remove;
+	return i2c_add_driver(i2c_driver);
+}
+EXPORT_SYMBOL(mlxsw_i2c_driver_register);
+
+void mlxsw_i2c_driver_unregister(struct i2c_driver *i2c_driver)
+{
+	i2c_del_driver(i2c_driver);
+}
+EXPORT_SYMBOL(mlxsw_i2c_driver_unregister);
+
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox switch I2C interface driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/i2c.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,60 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/i2c.h
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MLXSW_I2C_H
+#define _MLXSW_I2C_H
+
+#include <linux/i2c.h>
+
+#if IS_ENABLED(CONFIG_MLXSW_I2C)
+
+int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver);
+void mlxsw_i2c_driver_unregister(struct i2c_driver *i2c_driver);
+
+#else
+
+static inline int
+mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver)
+{
+	return -ENODEV;
+}
+
+static inline void
+mlxsw_i2c_driver_unregister(struct i2c_driver *i2c_driver)
+{
+}
+
+#endif
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/ib.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/ib.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/ib.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/ib.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,39 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/ib.h
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Elad Raz <eladr@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _MLXSW_IB_H
+#define _MLXSW_IB_H
+
+#define MLXSW_IB_DEFAULT_MTU 4096
+
+#endif /* _MLXSW_IB_H */
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/item.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/item.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/item.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/item.h	2017-02-12 16:03:20.000000000 -0500
@@ -55,7 +55,7 @@ struct mlxsw_item {
 };
 
 static inline unsigned int
-__mlxsw_item_offset(struct mlxsw_item *item, unsigned short index,
+__mlxsw_item_offset(const struct mlxsw_item *item, unsigned short index,
 		    size_t typesize)
 {
 	BUG_ON(index && !item->step);
@@ -72,7 +72,8 @@ __mlxsw_item_offset(struct mlxsw_item *i
 		typesize);
 }
 
-static inline u16 __mlxsw_item_get16(char *buf, struct mlxsw_item *item,
+static inline u16 __mlxsw_item_get16(const char *buf,
+				     const struct mlxsw_item *item,
 				     unsigned short index)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u16));
@@ -87,7 +88,7 @@ static inline u16 __mlxsw_item_get16(cha
 	return tmp;
 }
 
-static inline void __mlxsw_item_set16(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set16(char *buf, const struct mlxsw_item *item,
 				      unsigned short index, u16 val)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index,
@@ -105,7 +106,8 @@ static inline void __mlxsw_item_set16(ch
 	b[offset] = cpu_to_be16(tmp);
 }
 
-static inline u32 __mlxsw_item_get32(char *buf, struct mlxsw_item *item,
+static inline u32 __mlxsw_item_get32(const char *buf,
+				     const struct mlxsw_item *item,
 				     unsigned short index)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u32));
@@ -120,7 +122,7 @@ static inline u32 __mlxsw_item_get32(cha
 	return tmp;
 }
 
-static inline void __mlxsw_item_set32(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set32(char *buf, const struct mlxsw_item *item,
 				      unsigned short index, u32 val)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index,
@@ -138,7 +140,8 @@ static inline void __mlxsw_item_set32(ch
 	b[offset] = cpu_to_be32(tmp);
 }
 
-static inline u64 __mlxsw_item_get64(char *buf, struct mlxsw_item *item,
+static inline u64 __mlxsw_item_get64(const char *buf,
+				     const struct mlxsw_item *item,
 				     unsigned short index)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
@@ -153,7 +156,7 @@ static inline u64 __mlxsw_item_get64(cha
 	return tmp;
 }
 
-static inline void __mlxsw_item_set64(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_set64(char *buf, const struct mlxsw_item *item,
 				      unsigned short index, u64 val)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(u64));
@@ -170,8 +173,8 @@ static inline void __mlxsw_item_set64(ch
 	b[offset] = cpu_to_be64(tmp);
 }
 
-static inline void __mlxsw_item_memcpy_from(char *buf, char *dst,
-					    struct mlxsw_item *item,
+static inline void __mlxsw_item_memcpy_from(const char *buf, char *dst,
+					    const struct mlxsw_item *item,
 					    unsigned short index)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
@@ -180,7 +183,7 @@ static inline void __mlxsw_item_memcpy_f
 }
 
 static inline void __mlxsw_item_memcpy_to(char *buf, const char *src,
-					  struct mlxsw_item *item,
+					  const struct mlxsw_item *item,
 					  unsigned short index)
 {
 	unsigned int offset = __mlxsw_item_offset(item, index, sizeof(char));
@@ -189,7 +192,8 @@ static inline void __mlxsw_item_memcpy_t
 }
 
 static inline u16
-__mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
+__mlxsw_item_bit_array_offset(const struct mlxsw_item *item,
+			      u16 index, u8 *shift)
 {
 	u16 max_index, be_index;
 	u16 offset;		/* byte offset inside the array */
@@ -212,7 +216,8 @@ __mlxsw_item_bit_array_offset(struct mlx
 	return item->offset + offset;
 }
 
-static inline u8 __mlxsw_item_bit_array_get(char *buf, struct mlxsw_item *item,
+static inline u8 __mlxsw_item_bit_array_get(const char *buf,
+					    const struct mlxsw_item *item,
 					    u16 index)
 {
 	u8 shift, tmp;
@@ -224,7 +229,8 @@ static inline u8 __mlxsw_item_bit_array_
 	return tmp;
 }
 
-static inline void __mlxsw_item_bit_array_set(char *buf, struct mlxsw_item *item,
+static inline void __mlxsw_item_bit_array_set(char *buf,
+					      const struct mlxsw_item *item,
 					      u16 index, u8 val)
 {
 	u8 shift, tmp;
@@ -254,7 +260,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.size = {.bits = _sizebits,},						\
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
-static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)		\
+static inline u16 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)	\
 {										\
 	return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\
 }										\
@@ -275,7 +281,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
 static inline u16								\
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)	\
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
 {										\
 	return __mlxsw_item_get16(buf, &__ITEM_NAME(_type, _cname, _iname),	\
 				  index);					\
@@ -295,7 +301,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.size = {.bits = _sizebits,},						\
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
-static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)		\
+static inline u32 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)	\
 {										\
 	return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\
 }										\
@@ -316,7 +322,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
 static inline u32								\
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)	\
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
 {										\
 	return __mlxsw_item_get32(buf, &__ITEM_NAME(_type, _cname, _iname),	\
 				  index);					\
@@ -336,7 +342,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.size = {.bits = _sizebits,},						\
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
-static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(char *buf)		\
+static inline u64 mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf)	\
 {										\
 	return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname), 0);	\
 }										\
@@ -357,7 +363,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
 static inline u64								\
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, unsigned short index)	\
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, unsigned short index)\
 {										\
 	return __mlxsw_item_get64(buf, &__ITEM_NAME(_type, _cname, _iname),	\
 				  index);					\
@@ -377,7 +383,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
 static inline void								\
-mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf, char *dst)		\
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf, char *dst)	\
 {										\
 	__mlxsw_item_memcpy_from(buf, dst,					\
 				 &__ITEM_NAME(_type, _cname, _iname), 0);	\
@@ -399,7 +405,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
 static inline void								\
-mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(char *buf,			\
+mlxsw_##_type##_##_cname##_##_iname##_memcpy_from(const char *buf,		\
 						  unsigned short index,		\
 						  char *dst)			\
 {										\
@@ -424,7 +430,7 @@ static struct mlxsw_item __ITEM_NAME(_ty
 	.name = #_type "_" #_cname "_" #_iname,					\
 };										\
 static inline u8								\
-mlxsw_##_type##_##_cname##_##_iname##_get(char *buf, u16 index)			\
+mlxsw_##_type##_##_cname##_##_iname##_get(const char *buf, u16 index)		\
 {										\
 	return __mlxsw_item_bit_array_get(buf,					\
 					  &__ITEM_NAME(_type, _cname, _iname),	\
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/Kconfig linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/Kconfig
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/Kconfig	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/Kconfig	2017-02-12 16:03:20.000000000 -0500
@@ -19,6 +19,15 @@ config MLXSW_CORE_HWMON
 	---help---
 	  Say Y here if you want to expose HWMON interface on mlxsw devices.
 
+config MLXSW_CORE_THERMAL
+	bool "Thermal zone support for Mellanox Technologies Switch ASICs"
+	depends on MLXSW_CORE && THERMAL
+	depends on !(MLXSW_CORE=y && THERMAL=m)
+	default y
+	---help---
+	 Say Y here if you want to automatically control fans speed according
+	 ambient temperature reported by ASIC.
+
 config MLXSW_PCI
 	tristate "PCI bus implementation for Mellanox Technologies Switch ASICs"
 	depends on PCI && HAS_DMA && HAS_IOMEM && MLXSW_CORE
@@ -29,9 +38,30 @@ config MLXSW_PCI
 	  To compile this driver as a module, choose M here: the
 	  module will be called mlxsw_pci.
 
+config MLXSW_I2C
+	tristate "I2C bus implementation for Mellanox Technologies Switch ASICs"
+	depends on I2C && MLXSW_CORE
+	default m
+	---help---
+	  This is I2C bus implementation for Mellanox Technologies Switch ASICs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mlxsw_i2c.
+
+config MLXSW_SWITCHIB
+	tristate "Mellanox Technologies SwitchIB and SwitchIB-2 support"
+	depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV
+	default m
+	---help---
+	  This driver supports Mellanox Technologies SwitchIB and SwitchIB-2
+	  Infiniband Switch ASICs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mlxsw_switchib.
+
 config MLXSW_SWITCHX2
 	tristate "Mellanox Technologies SwitchX-2 support"
-	depends on MLXSW_CORE && NET_SWITCHDEV
+	depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV
 	default m
 	---help---
 	  This driver supports Mellanox Technologies SwitchX-2 Ethernet
@@ -42,7 +72,7 @@ config MLXSW_SWITCHX2
 
 config MLXSW_SPECTRUM
 	tristate "Mellanox Technologies Spectrum support"
-	depends on MLXSW_CORE && NET_SWITCHDEV && VLAN_8021Q
+	depends on MLXSW_CORE && MLXSW_PCI && NET_SWITCHDEV && VLAN_8021Q
 	default m
 	---help---
 	  This driver supports Mellanox Technologies Spectrum Ethernet
@@ -58,3 +88,14 @@ config MLXSW_SPECTRUM_DCB
 	---help---
 	  Say Y here if you want to use Data Center Bridging (DCB) in the
 	  driver.
+
+config MLXSW_MINIMAL
+	tristate "Mellanox Technologies minimal I2C support"
+	depends on MLXSW_CORE && MLXSW_I2C
+	default m
+	---help---
+	  This driver supports I2C access for Mellanox Technologies Switch
+	  ASICs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mlxsw_minimal.
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/Makefile linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/Makefile
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/Makefile	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/Makefile	2017-02-12 16:03:20.000000000 -0500
@@ -1,8 +1,13 @@
 obj-$(CONFIG_MLXSW_CORE)	+= mlxsw_core.o
 mlxsw_core-objs			:= core.o
 mlxsw_core-$(CONFIG_MLXSW_CORE_HWMON) += core_hwmon.o
+mlxsw_core-$(CONFIG_MLXSW_CORE_THERMAL) += core_thermal.o
 obj-$(CONFIG_MLXSW_PCI)		+= mlxsw_pci.o
 mlxsw_pci-objs			:= pci.o
+obj-$(CONFIG_MLXSW_I2C)		+= mlxsw_i2c.o
+mlxsw_i2c-objs			:= i2c.o
+obj-$(CONFIG_MLXSW_SWITCHIB)	+= mlxsw_switchib.o
+mlxsw_switchib-objs		:= switchib.o
 obj-$(CONFIG_MLXSW_SWITCHX2)	+= mlxsw_switchx2.o
 mlxsw_switchx2-objs		:= switchx2.o
 obj-$(CONFIG_MLXSW_SPECTRUM)	+= mlxsw_spectrum.o
@@ -10,3 +15,5 @@ mlxsw_spectrum-objs		:= spectrum.o spect
 				   spectrum_switchdev.o spectrum_router.o \
 				   spectrum_kvdl.o
 mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB)	+= spectrum_dcb.o
+obj-$(CONFIG_MLXSW_MINIMAL)	+= mlxsw_minimal.o
+mlxsw_minimal-objs		:= minimal.o
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/minimal.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/minimal.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/minimal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/minimal.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,97 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/minimal.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Vadim Pasternak <vadimp@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/types.h>
+
+#include "core.h"
+#include "i2c.h"
+
+static const char mlxsw_minimal_driver_name[] = "mlxsw_minimal";
+
+static const struct mlxsw_config_profile mlxsw_minimal_config_profile;
+
+static struct mlxsw_driver mlxsw_minimal_driver = {
+	.kind		= mlxsw_minimal_driver_name,
+	.priv_size	= 1,
+	.profile	= &mlxsw_minimal_config_profile,
+};
+
+static const struct i2c_device_id mlxsw_minimal_i2c_id[] = {
+	{ "mlxsw_minimal", 0},
+	{ },
+};
+
+static struct i2c_driver mlxsw_minimal_i2c_driver = {
+	.driver.name = "mlxsw_minimal",
+	.class = I2C_CLASS_HWMON,
+	.id_table = mlxsw_minimal_i2c_id,
+};
+
+static int __init mlxsw_minimal_module_init(void)
+{
+	int err;
+
+	err = mlxsw_core_driver_register(&mlxsw_minimal_driver);
+	if (err)
+		return err;
+
+	err = mlxsw_i2c_driver_register(&mlxsw_minimal_i2c_driver);
+	if (err)
+		goto err_i2c_driver_register;
+
+	return 0;
+
+err_i2c_driver_register:
+	mlxsw_core_driver_unregister(&mlxsw_minimal_driver);
+
+	return err;
+}
+
+static void __exit mlxsw_minimal_module_exit(void)
+{
+	mlxsw_i2c_driver_unregister(&mlxsw_minimal_i2c_driver);
+	mlxsw_core_driver_unregister(&mlxsw_minimal_driver);
+}
+
+module_init(mlxsw_minimal_module_init);
+module_exit(mlxsw_minimal_module_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
+MODULE_DESCRIPTION("Mellanox minimal driver");
+MODULE_DEVICE_TABLE(i2c, mlxsw_minimal_i2c_id);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.c	2017-02-12 16:03:20.000000000 -0500
@@ -48,33 +48,17 @@
 #include <linux/seq_file.h>
 #include <linux/string.h>
 
+#include "pci_hw.h"
 #include "pci.h"
 #include "core.h"
 #include "cmd.h"
 #include "port.h"
+#include "resources.h"
 
 static const char mlxsw_pci_driver_name[] = "mlxsw_pci";
 
-static const struct pci_device_id mlxsw_pci_id_table[] = {
-	{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHX2), 0},
-	{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
-	{0, }
-};
-
 static struct dentry *mlxsw_pci_dbg_root;
 
-static const char *mlxsw_pci_device_kind_get(const struct pci_device_id *id)
-{
-	switch (id->device) {
-	case PCI_DEVICE_ID_MELLANOX_SWITCHX2:
-		return MLXSW_DEVICE_KIND_SWITCHX2;
-	case PCI_DEVICE_ID_MELLANOX_SPECTRUM:
-		return MLXSW_DEVICE_KIND_SPECTRUM;
-	default:
-		BUG();
-	}
-}
-
 #define mlxsw_pci_write32(mlxsw_pci, reg, val) \
 	iowrite32be(val, (mlxsw_pci)->hw_addr + (MLXSW_PCI_ ## reg))
 #define mlxsw_pci_read32(mlxsw_pci, reg) \
@@ -238,8 +222,9 @@ static bool mlxsw_pci_elem_hw_owned(stru
 	return owner_bit != !!(q->consumer_counter & q->count);
 }
 
-static char *mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q,
-					 u32 (*get_elem_owner_func)(char *))
+static char *
+mlxsw_pci_queue_sw_elem_get(struct mlxsw_pci_queue *q,
+			    u32 (*get_elem_owner_func)(const char *))
 {
 	struct mlxsw_pci_queue_elem_info *elem_info;
 	char *elem;
@@ -1154,76 +1139,8 @@ mlxsw_pci_config_profile_swid_config(str
 	mlxsw_cmd_mbox_config_profile_swid_config_mask_set(mbox, index, mask);
 }
 
-#define MLXSW_RESOURCES_TABLE_END_ID 0xffff
-#define MLXSW_MAX_SPAN_ID 0x2420
-#define MLXSW_MAX_LAG_ID 0x2520
-#define MLXSW_MAX_PORTS_IN_LAG_ID 0x2521
-#define MLXSW_KVD_SIZE_ID 0x1001
-#define MLXSW_KVD_SINGLE_MIN_SIZE_ID 0x1002
-#define MLXSW_KVD_DOUBLE_MIN_SIZE_ID 0x1003
-#define MLXSW_MAX_VIRTUAL_ROUTERS_ID 0x2C01
-#define MLXSW_MAX_SYSTEM_PORT_ID 0x2502
-#define MLXSW_MAX_VLAN_GROUPS_ID 0x2906
-#define MLXSW_MAX_REGIONS_ID 0x2901
-#define MLXSW_MAX_RIF_ID 0x2C02
-#define MLXSW_RESOURCES_QUERY_MAX_QUERIES 100
-#define MLXSW_RESOURCES_PER_QUERY 32
-
-static void mlxsw_pci_resources_query_parse(int id, u64 val,
-					    struct mlxsw_resources *resources)
-{
-	switch (id) {
-	case MLXSW_MAX_SPAN_ID:
-		resources->max_span = val;
-		resources->max_span_valid = 1;
-		break;
-	case MLXSW_MAX_LAG_ID:
-		resources->max_lag = val;
-		resources->max_lag_valid = 1;
-		break;
-	case MLXSW_MAX_PORTS_IN_LAG_ID:
-		resources->max_ports_in_lag = val;
-		resources->max_ports_in_lag_valid = 1;
-		break;
-	case MLXSW_KVD_SIZE_ID:
-		resources->kvd_size = val;
-		resources->kvd_size_valid = 1;
-		break;
-	case MLXSW_KVD_SINGLE_MIN_SIZE_ID:
-		resources->kvd_single_min_size = val;
-		resources->kvd_single_min_size_valid = 1;
-		break;
-	case MLXSW_KVD_DOUBLE_MIN_SIZE_ID:
-		resources->kvd_double_min_size = val;
-		resources->kvd_double_min_size_valid = 1;
-		break;
-	case MLXSW_MAX_VIRTUAL_ROUTERS_ID:
-		resources->max_virtual_routers = val;
-		resources->max_virtual_routers_valid = 1;
-		break;
-	case MLXSW_MAX_SYSTEM_PORT_ID:
-		resources->max_system_ports = val;
-		resources->max_system_ports_valid = 1;
-		break;
-	case MLXSW_MAX_VLAN_GROUPS_ID:
-		resources->max_vlan_groups = val;
-		resources->max_vlan_groups_valid = 1;
-		break;
-	case MLXSW_MAX_REGIONS_ID:
-		resources->max_regions = val;
-		resources->max_regions_valid = 1;
-		break;
-	case MLXSW_MAX_RIF_ID:
-		resources->max_rif = val;
-		resources->max_rif_valid = 1;
-		break;
-	default:
-		break;
-	}
-}
-
 static int mlxsw_pci_resources_query(struct mlxsw_pci *mlxsw_pci, char *mbox,
-				     struct mlxsw_resources *resources,
+				     struct mlxsw_res *res,
 				     u8 query_enabled)
 {
 	int index, i;
@@ -1237,19 +1154,20 @@ static int mlxsw_pci_resources_query(str
 
 	mlxsw_cmd_mbox_zero(mbox);
 
-	for (index = 0; index < MLXSW_RESOURCES_QUERY_MAX_QUERIES; index++) {
+	for (index = 0; index < MLXSW_CMD_QUERY_RESOURCES_MAX_QUERIES;
+	     index++) {
 		err = mlxsw_cmd_query_resources(mlxsw_pci->core, mbox, index);
 		if (err)
 			return err;
 
-		for (i = 0; i < MLXSW_RESOURCES_PER_QUERY; i++) {
+		for (i = 0; i < MLXSW_CMD_QUERY_RESOURCES_PER_QUERY; i++) {
 			id = mlxsw_cmd_mbox_query_resource_id_get(mbox, i);
 			data = mlxsw_cmd_mbox_query_resource_data_get(mbox, i);
 
-			if (id == MLXSW_RESOURCES_TABLE_END_ID)
+			if (id == MLXSW_CMD_QUERY_RESOURCES_TABLE_END_ID)
 				return 0;
 
-			mlxsw_pci_resources_query_parse(id, data, resources);
+			mlxsw_res_parse(res, id, data);
 		}
 	}
 
@@ -1259,13 +1177,14 @@ static int mlxsw_pci_resources_query(str
 	return -EIO;
 }
 
-static int mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile,
-					   struct mlxsw_resources *resources)
+static int
+mlxsw_pci_profile_get_kvd_sizes(const struct mlxsw_config_profile *profile,
+				struct mlxsw_res *res)
 {
-	u32 singles_size, doubles_size, linear_size;
+	u32 single_size, double_size, linear_size;
 
-	if (!resources->kvd_single_min_size_valid ||
-	    !resources->kvd_double_min_size_valid ||
+	if (!MLXSW_RES_VALID(res, KVD_SINGLE_MIN_SIZE) ||
+	    !MLXSW_RES_VALID(res, KVD_DOUBLE_MIN_SIZE) ||
 	    !profile->used_kvd_split_data)
 		return -EIO;
 
@@ -1277,31 +1196,31 @@ static int mlxsw_pci_profile_get_kvd_siz
 	 * Both sizes must be a multiplications of the
 	 * granularity from the profile.
 	 */
-	doubles_size = (resources->kvd_size - linear_size);
-	doubles_size *= profile->kvd_hash_double_parts;
-	doubles_size /= (profile->kvd_hash_double_parts +
-			 profile->kvd_hash_single_parts);
-	doubles_size /= profile->kvd_hash_granularity;
-	doubles_size *= profile->kvd_hash_granularity;
-	singles_size = resources->kvd_size - doubles_size -
-		       linear_size;
+	double_size = MLXSW_RES_GET(res, KVD_SIZE) - linear_size;
+	double_size *= profile->kvd_hash_double_parts;
+	double_size /= profile->kvd_hash_double_parts +
+		       profile->kvd_hash_single_parts;
+	double_size /= profile->kvd_hash_granularity;
+	double_size *= profile->kvd_hash_granularity;
+	single_size = MLXSW_RES_GET(res, KVD_SIZE) - double_size -
+		      linear_size;
 
 	/* Check results are legal. */
-	if (singles_size < resources->kvd_single_min_size ||
-	    doubles_size < resources->kvd_double_min_size ||
-	    resources->kvd_size < linear_size)
+	if (single_size < MLXSW_RES_GET(res, KVD_SINGLE_MIN_SIZE) ||
+	    double_size < MLXSW_RES_GET(res, KVD_DOUBLE_MIN_SIZE) ||
+	    MLXSW_RES_GET(res, KVD_SIZE) < linear_size)
 		return -EIO;
 
-	resources->kvd_single_size = singles_size;
-	resources->kvd_double_size = doubles_size;
-	resources->kvd_linear_size = linear_size;
+	MLXSW_RES_SET(res, KVD_SINGLE_SIZE, single_size);
+	MLXSW_RES_SET(res, KVD_DOUBLE_SIZE, double_size);
+	MLXSW_RES_SET(res, KVD_LINEAR_SIZE, linear_size);
 
 	return 0;
 }
 
 static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
 				    const struct mlxsw_config_profile *profile,
-				    struct mlxsw_resources *resources)
+				    struct mlxsw_res *res)
 {
 	int i;
 	int err;
@@ -1390,22 +1309,22 @@ static int mlxsw_pci_config_profile(stru
 		mlxsw_cmd_mbox_config_profile_adaptive_routing_group_cap_set(
 			mbox, profile->adaptive_routing_group_cap);
 	}
-	if (resources->kvd_size_valid) {
-		err = mlxsw_pci_profile_get_kvd_sizes(profile, resources);
+	if (MLXSW_RES_VALID(res, KVD_SIZE)) {
+		err = mlxsw_pci_profile_get_kvd_sizes(profile, res);
 		if (err)
 			return err;
 
 		mlxsw_cmd_mbox_config_profile_set_kvd_linear_size_set(mbox, 1);
 		mlxsw_cmd_mbox_config_profile_kvd_linear_size_set(mbox,
-						resources->kvd_linear_size);
+					MLXSW_RES_GET(res, KVD_LINEAR_SIZE));
 		mlxsw_cmd_mbox_config_profile_set_kvd_hash_single_size_set(mbox,
 									   1);
 		mlxsw_cmd_mbox_config_profile_kvd_hash_single_size_set(mbox,
-						resources->kvd_single_size);
+					MLXSW_RES_GET(res, KVD_SINGLE_SIZE));
 		mlxsw_cmd_mbox_config_profile_set_kvd_hash_double_size_set(
 								mbox, 1);
 		mlxsw_cmd_mbox_config_profile_kvd_hash_double_size_set(mbox,
-						resources->kvd_double_size);
+					MLXSW_RES_GET(res, KVD_DOUBLE_SIZE));
 	}
 
 	for (i = 0; i < MLXSW_CONFIG_PROFILE_SWID_COUNT; i++)
@@ -1543,7 +1462,7 @@ static void mlxsw_pci_mbox_free(struct m
 
 static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
 			  const struct mlxsw_config_profile *profile,
-			  struct mlxsw_resources *resources)
+			  struct mlxsw_res *res)
 {
 	struct mlxsw_pci *mlxsw_pci = bus_priv;
 	struct pci_dev *pdev = mlxsw_pci->pdev;
@@ -1602,12 +1521,12 @@ static int mlxsw_pci_init(void *bus_priv
 	if (err)
 		goto err_boardinfo;
 
-	err = mlxsw_pci_resources_query(mlxsw_pci, mbox, resources,
+	err = mlxsw_pci_resources_query(mlxsw_pci, mbox, res,
 					profile->resource_query_enable);
 	if (err)
 		goto err_query_resources;
 
-	err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, resources);
+	err = mlxsw_pci_config_profile(mlxsw_pci, mbox, profile, res);
 	if (err)
 		goto err_config_profile;
 
@@ -1617,7 +1536,7 @@ static int mlxsw_pci_init(void *bus_priv
 
 	err = request_irq(mlxsw_pci->msix_entry.vector,
 			  mlxsw_pci_eq_irq_handler, 0,
-			  mlxsw_pci_driver_name, mlxsw_pci);
+			  mlxsw_pci->bus_info.device_kind, mlxsw_pci);
 	if (err) {
 		dev_err(&pdev->dev, "IRQ request failed\n");
 		goto err_request_eq_irq;
@@ -1836,6 +1755,7 @@ static const struct mlxsw_bus mlxsw_pci_
 	.skb_transmit_busy	= mlxsw_pci_skb_transmit_busy,
 	.skb_transmit		= mlxsw_pci_skb_transmit,
 	.cmd_exec		= mlxsw_pci_cmd_exec,
+	.features		= MLXSW_BUS_F_TXRX,
 };
 
 static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
@@ -1863,6 +1783,7 @@ static int mlxsw_pci_sw_reset(struct mlx
 
 static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+	const char *driver_name = pdev->driver->name;
 	struct mlxsw_pci *mlxsw_pci;
 	int err;
 
@@ -1876,7 +1797,7 @@ static int mlxsw_pci_probe(struct pci_de
 		goto err_pci_enable_device;
 	}
 
-	err = pci_request_regions(pdev, mlxsw_pci_driver_name);
+	err = pci_request_regions(pdev, driver_name);
 	if (err) {
 		dev_err(&pdev->dev, "pci_request_regions failed\n");
 		goto err_pci_request_regions;
@@ -1927,7 +1848,7 @@ static int mlxsw_pci_probe(struct pci_de
 		goto err_msix_init;
 	}
 
-	mlxsw_pci->bus_info.device_kind = mlxsw_pci_device_kind_get(id);
+	mlxsw_pci->bus_info.device_kind = driver_name;
 	mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
 	mlxsw_pci->bus_info.dev = &pdev->dev;
 
@@ -1979,33 +1900,30 @@ static void mlxsw_pci_remove(struct pci_
 	kfree(mlxsw_pci);
 }
 
-static struct pci_driver mlxsw_pci_driver = {
-	.name		= mlxsw_pci_driver_name,
-	.id_table	= mlxsw_pci_id_table,
-	.probe		= mlxsw_pci_probe,
-	.remove		= mlxsw_pci_remove,
-};
+int mlxsw_pci_driver_register(struct pci_driver *pci_driver)
+{
+	pci_driver->probe = mlxsw_pci_probe;
+	pci_driver->remove = mlxsw_pci_remove;
+	return pci_register_driver(pci_driver);
+}
+EXPORT_SYMBOL(mlxsw_pci_driver_register);
 
-static int __init mlxsw_pci_module_init(void)
+void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver)
 {
-	int err;
+	pci_unregister_driver(pci_driver);
+}
+EXPORT_SYMBOL(mlxsw_pci_driver_unregister);
 
+static int __init mlxsw_pci_module_init(void)
+{
 	mlxsw_pci_dbg_root = debugfs_create_dir(mlxsw_pci_driver_name, NULL);
 	if (!mlxsw_pci_dbg_root)
 		return -ENOMEM;
-	err = pci_register_driver(&mlxsw_pci_driver);
-	if (err)
-		goto err_register_driver;
 	return 0;
-
-err_register_driver:
-	debugfs_remove_recursive(mlxsw_pci_dbg_root);
-	return err;
 }
 
 static void __exit mlxsw_pci_module_exit(void)
 {
-	pci_unregister_driver(&mlxsw_pci_driver);
 	debugfs_remove_recursive(mlxsw_pci_dbg_root);
 }
 
@@ -2015,4 +1933,3 @@ module_exit(mlxsw_pci_module_exit);
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox switch PCI interface driver");
-MODULE_DEVICE_TABLE(pci, mlxsw_pci_id_table);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/pci.h	2017-02-12 16:03:20.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * drivers/net/ethernet/mellanox/mlxsw/pci.h
- * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2015 Jiri Pirko <jiri@mellanox.com>
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -35,197 +35,31 @@
 #ifndef _MLXSW_PCI_H
 #define _MLXSW_PCI_H
 
-#include <linux/bitops.h>
-
-#include "item.h"
-
-#define PCI_DEVICE_ID_MELLANOX_SWITCHX2	0xc738
-#define PCI_DEVICE_ID_MELLANOX_SPECTRUM	0xcb84
-#define MLXSW_PCI_BAR0_SIZE		(1024 * 1024) /* 1MB */
-#define MLXSW_PCI_PAGE_SIZE		4096
-
-#define MLXSW_PCI_CIR_BASE			0x71000
-#define MLXSW_PCI_CIR_IN_PARAM_HI		MLXSW_PCI_CIR_BASE
-#define MLXSW_PCI_CIR_IN_PARAM_LO		(MLXSW_PCI_CIR_BASE + 0x04)
-#define MLXSW_PCI_CIR_IN_MODIFIER		(MLXSW_PCI_CIR_BASE + 0x08)
-#define MLXSW_PCI_CIR_OUT_PARAM_HI		(MLXSW_PCI_CIR_BASE + 0x0C)
-#define MLXSW_PCI_CIR_OUT_PARAM_LO		(MLXSW_PCI_CIR_BASE + 0x10)
-#define MLXSW_PCI_CIR_TOKEN			(MLXSW_PCI_CIR_BASE + 0x14)
-#define MLXSW_PCI_CIR_CTRL			(MLXSW_PCI_CIR_BASE + 0x18)
-#define MLXSW_PCI_CIR_CTRL_GO_BIT		BIT(23)
-#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT		BIT(22)
-#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT	12
-#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT		24
-#define MLXSW_PCI_CIR_TIMEOUT_MSECS		1000
-
-#define MLXSW_PCI_SW_RESET			0xF0010
-#define MLXSW_PCI_SW_RESET_RST_BIT		BIT(0)
-#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS	5000
-#define MLXSW_PCI_FW_READY			0xA1844
-#define MLXSW_PCI_FW_READY_MASK			0xFF
-#define MLXSW_PCI_FW_READY_MAGIC		0x5E
-
-#define MLXSW_PCI_DOORBELL_SDQ_OFFSET		0x000
-#define MLXSW_PCI_DOORBELL_RDQ_OFFSET		0x200
-#define MLXSW_PCI_DOORBELL_CQ_OFFSET		0x400
-#define MLXSW_PCI_DOORBELL_EQ_OFFSET		0x600
-#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET	0x800
-#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET	0xA00
-
-#define MLXSW_PCI_DOORBELL(offset, type_offset, num)	\
-	((offset) + (type_offset) + (num) * 4)
-
-#define MLXSW_PCI_CQS_MAX	96
-#define MLXSW_PCI_EQS_COUNT	2
-#define MLXSW_PCI_EQ_ASYNC_NUM	0
-#define MLXSW_PCI_EQ_COMP_NUM	1
-
-#define MLXSW_PCI_AQ_PAGES	8
-#define MLXSW_PCI_AQ_SIZE	(MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES)
-#define MLXSW_PCI_WQE_SIZE	32 /* 32 bytes per element */
-#define MLXSW_PCI_CQE_SIZE	16 /* 16 bytes per element */
-#define MLXSW_PCI_EQE_SIZE	16 /* 16 bytes per element */
-#define MLXSW_PCI_WQE_COUNT	(MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
-#define MLXSW_PCI_CQE_COUNT	(MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE)
-#define MLXSW_PCI_EQE_COUNT	(MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE)
-#define MLXSW_PCI_EQE_UPDATE_COUNT	0x80
-
-#define MLXSW_PCI_WQE_SG_ENTRIES	3
-#define MLXSW_PCI_WQE_TYPE_ETHERNET	0xA
-
-/* pci_wqe_c
- * If set it indicates that a completion should be reported upon
- * execution of this descriptor.
- */
-MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1);
-
-/* pci_wqe_lp
- * Local Processing, set if packet should be processed by the local
- * switch hardware:
- * For Ethernet EMAD (Direct Route and non Direct Route) -
- * must be set if packet destination is local device
- * For InfiniBand CTL - must be set if packet destination is local device
- * Otherwise it must be clear
- * Local Process packets must not exceed the size of 2K (including payload
- * and headers).
- */
-MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1);
-
-/* pci_wqe_type
- * Packet type.
- */
-MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4);
-
-/* pci_wqe_byte_count
- * Size of i-th scatter/gather entry, 0 if entry is unused.
- */
-MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false);
-
-/* pci_wqe_address
- * Physical address of i-th scatter/gather entry.
- * Gather Entries must be 2Byte aligned.
- */
-MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false);
-
-/* pci_cqe_lag
- * Packet arrives from a port which is a LAG
- */
-MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1);
-
-/* pci_cqe_system_port/lag_id
- * When lag=0: System port on which the packet was received
- * When lag=1:
- * bits [15:4] LAG ID on which the packet was received
- * bits [3:0] sub_port on which the packet was received
- */
-MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16);
-MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12);
-MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4);
-
-/* pci_cqe_wqe_counter
- * WQE count of the WQEs completed on the associated dqn
- */
-MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16);
-
-/* pci_cqe_byte_count
- * Byte count of received packets including additional two
- * Reserved Bytes that are append to the end of the frame.
- * Reserved for Send CQE.
- */
-MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14);
-
-/* pci_cqe_trap_id
- * Trap ID that captured the packet.
- */
-MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8);
-
-/* pci_cqe_crc
- * Length include CRC. Indicates the length field includes
- * the packet's CRC.
- */
-MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1);
-
-/* pci_cqe_e
- * CQE with Error.
- */
-MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1);
-
-/* pci_cqe_sr
- * 1 - Send Queue
- * 0 - Receive Queue
- */
-MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1);
-
-/* pci_cqe_dqn
- * Descriptor Queue (DQ) Number.
- */
-MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5);
-
-/* pci_cqe_owner
- * Ownership bit.
- */
-MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1);
-
-/* pci_eqe_event_type
- * Event type.
- */
-MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8);
-#define MLXSW_PCI_EQE_EVENT_TYPE_COMP	0x00
-#define MLXSW_PCI_EQE_EVENT_TYPE_CMD	0x0A
+#include <linux/pci.h>
 
-/* pci_eqe_event_sub_type
- * Event type.
- */
-MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8);
+#define PCI_DEVICE_ID_MELLANOX_SWITCHX2		0xc738
+#define PCI_DEVICE_ID_MELLANOX_SPECTRUM		0xcb84
+#define PCI_DEVICE_ID_MELLANOX_SWITCHIB		0xcb20
+#define PCI_DEVICE_ID_MELLANOX_SWITCHIB2	0xcf08
 
-/* pci_eqe_cqn
- * Completion Queue that triggeret this EQE.
- */
-MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7);
+#if IS_ENABLED(CONFIG_MLXSW_PCI)
 
-/* pci_eqe_owner
- * Ownership bit.
- */
-MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
+int mlxsw_pci_driver_register(struct pci_driver *pci_driver);
+void mlxsw_pci_driver_unregister(struct pci_driver *pci_driver);
 
-/* pci_eqe_cmd_token
- * Command completion event - token
- */
-MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
+#else
 
-/* pci_eqe_cmd_status
- * Command completion event - status
- */
-MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
+static inline int
+mlxsw_pci_driver_register(struct pci_driver *pci_driver)
+{
+	return 0;
+}
 
-/* pci_eqe_cmd_out_param_h
- * Command completion event - output parameter - higher part
- */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
+static inline void
+mlxsw_pci_driver_unregister(struct pci_driver *pci_driver)
+{
+}
 
-/* pci_eqe_cmd_out_param_l
- * Command completion event - output parameter - lower part
- */
-MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
+#endif
 
 #endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,229 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/pci_hw.h
+ * Copyright (c) 2015-2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015-2016 Jiri Pirko <jiri@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MLXSW_PCI_HW_H
+#define _MLXSW_PCI_HW_H
+
+#include <linux/bitops.h>
+
+#include "item.h"
+
+#define MLXSW_PCI_BAR0_SIZE		(1024 * 1024) /* 1MB */
+#define MLXSW_PCI_PAGE_SIZE		4096
+
+#define MLXSW_PCI_CIR_BASE			0x71000
+#define MLXSW_PCI_CIR_IN_PARAM_HI		MLXSW_PCI_CIR_BASE
+#define MLXSW_PCI_CIR_IN_PARAM_LO		(MLXSW_PCI_CIR_BASE + 0x04)
+#define MLXSW_PCI_CIR_IN_MODIFIER		(MLXSW_PCI_CIR_BASE + 0x08)
+#define MLXSW_PCI_CIR_OUT_PARAM_HI		(MLXSW_PCI_CIR_BASE + 0x0C)
+#define MLXSW_PCI_CIR_OUT_PARAM_LO		(MLXSW_PCI_CIR_BASE + 0x10)
+#define MLXSW_PCI_CIR_TOKEN			(MLXSW_PCI_CIR_BASE + 0x14)
+#define MLXSW_PCI_CIR_CTRL			(MLXSW_PCI_CIR_BASE + 0x18)
+#define MLXSW_PCI_CIR_CTRL_GO_BIT		BIT(23)
+#define MLXSW_PCI_CIR_CTRL_EVREQ_BIT		BIT(22)
+#define MLXSW_PCI_CIR_CTRL_OPCODE_MOD_SHIFT	12
+#define MLXSW_PCI_CIR_CTRL_STATUS_SHIFT		24
+#define MLXSW_PCI_CIR_TIMEOUT_MSECS		1000
+
+#define MLXSW_PCI_SW_RESET			0xF0010
+#define MLXSW_PCI_SW_RESET_RST_BIT		BIT(0)
+#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS	5000
+#define MLXSW_PCI_FW_READY			0xA1844
+#define MLXSW_PCI_FW_READY_MASK			0xFFFF
+#define MLXSW_PCI_FW_READY_MAGIC		0x5E
+
+#define MLXSW_PCI_DOORBELL_SDQ_OFFSET		0x000
+#define MLXSW_PCI_DOORBELL_RDQ_OFFSET		0x200
+#define MLXSW_PCI_DOORBELL_CQ_OFFSET		0x400
+#define MLXSW_PCI_DOORBELL_EQ_OFFSET		0x600
+#define MLXSW_PCI_DOORBELL_ARM_CQ_OFFSET	0x800
+#define MLXSW_PCI_DOORBELL_ARM_EQ_OFFSET	0xA00
+
+#define MLXSW_PCI_DOORBELL(offset, type_offset, num)	\
+	((offset) + (type_offset) + (num) * 4)
+
+#define MLXSW_PCI_CQS_MAX	96
+#define MLXSW_PCI_EQS_COUNT	2
+#define MLXSW_PCI_EQ_ASYNC_NUM	0
+#define MLXSW_PCI_EQ_COMP_NUM	1
+
+#define MLXSW_PCI_AQ_PAGES	8
+#define MLXSW_PCI_AQ_SIZE	(MLXSW_PCI_PAGE_SIZE * MLXSW_PCI_AQ_PAGES)
+#define MLXSW_PCI_WQE_SIZE	32 /* 32 bytes per element */
+#define MLXSW_PCI_CQE_SIZE	16 /* 16 bytes per element */
+#define MLXSW_PCI_EQE_SIZE	16 /* 16 bytes per element */
+#define MLXSW_PCI_WQE_COUNT	(MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
+#define MLXSW_PCI_CQE_COUNT	(MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE_SIZE)
+#define MLXSW_PCI_EQE_COUNT	(MLXSW_PCI_AQ_SIZE / MLXSW_PCI_EQE_SIZE)
+#define MLXSW_PCI_EQE_UPDATE_COUNT	0x80
+
+#define MLXSW_PCI_WQE_SG_ENTRIES	3
+#define MLXSW_PCI_WQE_TYPE_ETHERNET	0xA
+
+/* pci_wqe_c
+ * If set it indicates that a completion should be reported upon
+ * execution of this descriptor.
+ */
+MLXSW_ITEM32(pci, wqe, c, 0x00, 31, 1);
+
+/* pci_wqe_lp
+ * Local Processing, set if packet should be processed by the local
+ * switch hardware:
+ * For Ethernet EMAD (Direct Route and non Direct Route) -
+ * must be set if packet destination is local device
+ * For InfiniBand CTL - must be set if packet destination is local device
+ * Otherwise it must be clear
+ * Local Process packets must not exceed the size of 2K (including payload
+ * and headers).
+ */
+MLXSW_ITEM32(pci, wqe, lp, 0x00, 30, 1);
+
+/* pci_wqe_type
+ * Packet type.
+ */
+MLXSW_ITEM32(pci, wqe, type, 0x00, 23, 4);
+
+/* pci_wqe_byte_count
+ * Size of i-th scatter/gather entry, 0 if entry is unused.
+ */
+MLXSW_ITEM16_INDEXED(pci, wqe, byte_count, 0x02, 0, 14, 0x02, 0x00, false);
+
+/* pci_wqe_address
+ * Physical address of i-th scatter/gather entry.
+ * Gather Entries must be 2Byte aligned.
+ */
+MLXSW_ITEM64_INDEXED(pci, wqe, address, 0x08, 0, 64, 0x8, 0x0, false);
+
+/* pci_cqe_lag
+ * Packet arrives from a port which is a LAG
+ */
+MLXSW_ITEM32(pci, cqe, lag, 0x00, 23, 1);
+
+/* pci_cqe_system_port/lag_id
+ * When lag=0: System port on which the packet was received
+ * When lag=1:
+ * bits [15:4] LAG ID on which the packet was received
+ * bits [3:0] sub_port on which the packet was received
+ */
+MLXSW_ITEM32(pci, cqe, system_port, 0x00, 0, 16);
+MLXSW_ITEM32(pci, cqe, lag_id, 0x00, 4, 12);
+MLXSW_ITEM32(pci, cqe, lag_port_index, 0x00, 0, 4);
+
+/* pci_cqe_wqe_counter
+ * WQE count of the WQEs completed on the associated dqn
+ */
+MLXSW_ITEM32(pci, cqe, wqe_counter, 0x04, 16, 16);
+
+/* pci_cqe_byte_count
+ * Byte count of received packets including additional two
+ * Reserved Bytes that are append to the end of the frame.
+ * Reserved for Send CQE.
+ */
+MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14);
+
+/* pci_cqe_trap_id
+ * Trap ID that captured the packet.
+ */
+MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 8);
+
+/* pci_cqe_crc
+ * Length include CRC. Indicates the length field includes
+ * the packet's CRC.
+ */
+MLXSW_ITEM32(pci, cqe, crc, 0x0C, 8, 1);
+
+/* pci_cqe_e
+ * CQE with Error.
+ */
+MLXSW_ITEM32(pci, cqe, e, 0x0C, 7, 1);
+
+/* pci_cqe_sr
+ * 1 - Send Queue
+ * 0 - Receive Queue
+ */
+MLXSW_ITEM32(pci, cqe, sr, 0x0C, 6, 1);
+
+/* pci_cqe_dqn
+ * Descriptor Queue (DQ) Number.
+ */
+MLXSW_ITEM32(pci, cqe, dqn, 0x0C, 1, 5);
+
+/* pci_cqe_owner
+ * Ownership bit.
+ */
+MLXSW_ITEM32(pci, cqe, owner, 0x0C, 0, 1);
+
+/* pci_eqe_event_type
+ * Event type.
+ */
+MLXSW_ITEM32(pci, eqe, event_type, 0x0C, 24, 8);
+#define MLXSW_PCI_EQE_EVENT_TYPE_COMP	0x00
+#define MLXSW_PCI_EQE_EVENT_TYPE_CMD	0x0A
+
+/* pci_eqe_event_sub_type
+ * Event type.
+ */
+MLXSW_ITEM32(pci, eqe, event_sub_type, 0x0C, 16, 8);
+
+/* pci_eqe_cqn
+ * Completion Queue that triggeret this EQE.
+ */
+MLXSW_ITEM32(pci, eqe, cqn, 0x0C, 8, 7);
+
+/* pci_eqe_owner
+ * Ownership bit.
+ */
+MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
+
+/* pci_eqe_cmd_token
+ * Command completion event - token
+ */
+MLXSW_ITEM32(pci, eqe, cmd_token, 0x00, 16, 16);
+
+/* pci_eqe_cmd_status
+ * Command completion event - status
+ */
+MLXSW_ITEM32(pci, eqe, cmd_status, 0x00, 0, 8);
+
+/* pci_eqe_cmd_out_param_h
+ * Command completion event - output parameter - higher part
+ */
+MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x04, 0, 32);
+
+/* pci_eqe_cmd_out_param_l
+ * Command completion event - output parameter - lower part
+ */
+MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x08, 0, 32);
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/port.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/port.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/port.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/port.h	2017-02-12 16:03:20.000000000 -0500
@@ -44,6 +44,7 @@
 
 #define MLXSW_PORT_SWID_DISABLED_PORT	255
 #define MLXSW_PORT_SWID_ALL_SWIDS	254
+#define MLXSW_PORT_SWID_TYPE_IB		1
 #define MLXSW_PORT_SWID_TYPE_ETH	2
 
 #define MLXSW_PORT_MID			0xd000
@@ -51,6 +52,9 @@
 #define MLXSW_PORT_MAX_PHY_PORTS	0x40
 #define MLXSW_PORT_MAX_PORTS		(MLXSW_PORT_MAX_PHY_PORTS + 1)
 
+#define MLXSW_PORT_MAX_IB_PHY_PORTS	36
+#define MLXSW_PORT_MAX_IB_PORTS		(MLXSW_PORT_MAX_IB_PHY_PORTS + 1)
+
 #define MLXSW_PORT_DEVID_BITS_OFFSET	10
 #define MLXSW_PORT_PHY_BITS_OFFSET	4
 #define MLXSW_PORT_PHY_BITS_MASK	(MLXSW_PORT_MAX_PHY_PORTS - 1)
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/reg.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/reg.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/reg.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/reg.h	2017-02-12 16:03:20.000000000 -0500
@@ -48,8 +48,16 @@
 struct mlxsw_reg_info {
 	u16 id;
 	u16 len; /* In u8 */
+	const char *name;
 };
 
+#define MLXSW_REG_DEFINE(_name, _id, _len)				\
+static const struct mlxsw_reg_info mlxsw_reg_##_name = {		\
+	.id = _id,							\
+	.len = _len,							\
+	.name = #_name,							\
+}
+
 #define MLXSW_REG(type) (&mlxsw_reg_##type)
 #define MLXSW_REG_LEN(type) MLXSW_REG(type)->len
 #define MLXSW_REG_ZERO(type, payload) memset(payload, 0, MLXSW_REG(type)->len)
@@ -61,10 +69,7 @@ struct mlxsw_reg_info {
 #define MLXSW_REG_SGCR_ID 0x2000
 #define MLXSW_REG_SGCR_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_sgcr = {
-	.id = MLXSW_REG_SGCR_ID,
-	.len = MLXSW_REG_SGCR_LEN,
-};
+MLXSW_REG_DEFINE(sgcr, MLXSW_REG_SGCR_ID, MLXSW_REG_SGCR_LEN);
 
 /* reg_sgcr_llb
  * Link Local Broadcast (Default=0)
@@ -87,10 +92,7 @@ static inline void mlxsw_reg_sgcr_pack(c
 #define MLXSW_REG_SPAD_ID 0x2002
 #define MLXSW_REG_SPAD_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_spad = {
-	.id = MLXSW_REG_SPAD_ID,
-	.len = MLXSW_REG_SPAD_LEN,
-};
+MLXSW_REG_DEFINE(spad, MLXSW_REG_SPAD_ID, MLXSW_REG_SPAD_LEN);
 
 /* reg_spad_base_mac
  * Base MAC address for the switch partitions.
@@ -109,10 +111,7 @@ MLXSW_ITEM_BUF(reg, spad, base_mac, 0x02
 #define MLXSW_REG_SMID_ID 0x2007
 #define MLXSW_REG_SMID_LEN 0x240
 
-static const struct mlxsw_reg_info mlxsw_reg_smid = {
-	.id = MLXSW_REG_SMID_ID,
-	.len = MLXSW_REG_SMID_LEN,
-};
+MLXSW_REG_DEFINE(smid, MLXSW_REG_SMID_ID, MLXSW_REG_SMID_LEN);
 
 /* reg_smid_swid
  * Switch partition ID.
@@ -156,10 +155,7 @@ static inline void mlxsw_reg_smid_pack(c
 #define MLXSW_REG_SSPR_ID 0x2008
 #define MLXSW_REG_SSPR_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_sspr = {
-	.id = MLXSW_REG_SSPR_ID,
-	.len = MLXSW_REG_SSPR_LEN,
-};
+MLXSW_REG_DEFINE(sspr, MLXSW_REG_SSPR_ID, MLXSW_REG_SSPR_LEN);
 
 /* reg_sspr_m
  * Master - if set, then the record describes the master system port.
@@ -215,10 +211,7 @@ static inline void mlxsw_reg_sspr_pack(c
 #define MLXSW_REG_SFDAT_ID 0x2009
 #define MLXSW_REG_SFDAT_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_sfdat = {
-	.id = MLXSW_REG_SFDAT_ID,
-	.len = MLXSW_REG_SFDAT_LEN,
-};
+MLXSW_REG_DEFINE(sfdat, MLXSW_REG_SFDAT_ID, MLXSW_REG_SFDAT_LEN);
 
 /* reg_sfdat_swid
  * Switch partition ID.
@@ -256,10 +249,7 @@ static inline void mlxsw_reg_sfdat_pack(
 #define MLXSW_REG_SFD_LEN (MLXSW_REG_SFD_BASE_LEN +	\
 			   MLXSW_REG_SFD_REC_LEN * MLXSW_REG_SFD_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_sfd = {
-	.id = MLXSW_REG_SFD_ID,
-	.len = MLXSW_REG_SFD_LEN,
-};
+MLXSW_REG_DEFINE(sfd, MLXSW_REG_SFD_ID, MLXSW_REG_SFD_LEN);
 
 /* reg_sfd_swid
  * Switch partition ID for queries. Reserved on Write.
@@ -580,10 +570,7 @@ mlxsw_reg_sfd_mc_pack(char *payload, int
 #define MLXSW_REG_SFN_LEN (MLXSW_REG_SFN_BASE_LEN +	\
 			   MLXSW_REG_SFN_REC_LEN * MLXSW_REG_SFN_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_sfn = {
-	.id = MLXSW_REG_SFN_ID,
-	.len = MLXSW_REG_SFN_LEN,
-};
+MLXSW_REG_DEFINE(sfn, MLXSW_REG_SFN_ID, MLXSW_REG_SFN_LEN);
 
 /* reg_sfn_swid
  * Switch partition ID.
@@ -701,10 +688,7 @@ static inline void mlxsw_reg_sfn_mac_lag
 #define MLXSW_REG_SPMS_ID 0x200D
 #define MLXSW_REG_SPMS_LEN 0x404
 
-static const struct mlxsw_reg_info mlxsw_reg_spms = {
-	.id = MLXSW_REG_SPMS_ID,
-	.len = MLXSW_REG_SPMS_LEN,
-};
+MLXSW_REG_DEFINE(spms, MLXSW_REG_SPMS_ID, MLXSW_REG_SPMS_LEN);
 
 /* reg_spms_local_port
  * Local port number.
@@ -748,10 +732,7 @@ static inline void mlxsw_reg_spms_vid_pa
 #define MLXSW_REG_SPVID_ID 0x200E
 #define MLXSW_REG_SPVID_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_spvid = {
-	.id = MLXSW_REG_SPVID_ID,
-	.len = MLXSW_REG_SPVID_LEN,
-};
+MLXSW_REG_DEFINE(spvid, MLXSW_REG_SPVID_ID, MLXSW_REG_SPVID_LEN);
 
 /* reg_spvid_local_port
  * Local port number.
@@ -792,10 +773,7 @@ static inline void mlxsw_reg_spvid_pack(
 #define MLXSW_REG_SPVM_LEN (MLXSW_REG_SPVM_BASE_LEN +	\
 		    MLXSW_REG_SPVM_REC_LEN * MLXSW_REG_SPVM_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_spvm = {
-	.id = MLXSW_REG_SPVM_ID,
-	.len = MLXSW_REG_SPVM_LEN,
-};
+MLXSW_REG_DEFINE(spvm, MLXSW_REG_SPVM_ID, MLXSW_REG_SPVM_LEN);
 
 /* reg_spvm_pt
  * Priority tagged. If this bit is set, packets forwarded to the port with
@@ -891,10 +869,7 @@ static inline void mlxsw_reg_spvm_pack(c
 #define MLXSW_REG_SPAFT_ID 0x2010
 #define MLXSW_REG_SPAFT_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_spaft = {
-	.id = MLXSW_REG_SPAFT_ID,
-	.len = MLXSW_REG_SPAFT_LEN,
-};
+MLXSW_REG_DEFINE(spaft, MLXSW_REG_SPAFT_ID, MLXSW_REG_SPAFT_LEN);
 
 /* reg_spaft_local_port
  * Local port number.
@@ -947,10 +922,7 @@ static inline void mlxsw_reg_spaft_pack(
 #define MLXSW_REG_SFGC_ID 0x2011
 #define MLXSW_REG_SFGC_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_sfgc = {
-	.id = MLXSW_REG_SFGC_ID,
-	.len = MLXSW_REG_SFGC_LEN,
-};
+MLXSW_REG_DEFINE(sfgc, MLXSW_REG_SFGC_ID, MLXSW_REG_SFGC_LEN);
 
 enum mlxsw_reg_sfgc_type {
 	MLXSW_REG_SFGC_TYPE_BROADCAST,
@@ -1045,10 +1017,7 @@ mlxsw_reg_sfgc_pack(char *payload, enum
 #define MLXSW_REG_SFTR_ID 0x2012
 #define MLXSW_REG_SFTR_LEN 0x420
 
-static const struct mlxsw_reg_info mlxsw_reg_sftr = {
-	.id = MLXSW_REG_SFTR_ID,
-	.len = MLXSW_REG_SFTR_LEN,
-};
+MLXSW_REG_DEFINE(sftr, MLXSW_REG_SFTR_ID, MLXSW_REG_SFTR_LEN);
 
 /* reg_sftr_swid
  * Switch partition ID with which to associate the port.
@@ -1118,10 +1087,7 @@ static inline void mlxsw_reg_sftr_pack(c
 #define MLXSW_REG_SFDF_ID 0x2013
 #define MLXSW_REG_SFDF_LEN 0x14
 
-static const struct mlxsw_reg_info mlxsw_reg_sfdf = {
-	.id = MLXSW_REG_SFDF_ID,
-	.len = MLXSW_REG_SFDF_LEN,
-};
+MLXSW_REG_DEFINE(sfdf, MLXSW_REG_SFDF_ID, MLXSW_REG_SFDF_LEN);
 
 /* reg_sfdf_swid
  * Switch partition ID.
@@ -1205,10 +1171,7 @@ MLXSW_ITEM32(reg, sfdf, lag_fid_lag_id,
 #define MLXSW_REG_SLDR_ID 0x2014
 #define MLXSW_REG_SLDR_LEN 0x0C /* counting in only one port in list */
 
-static const struct mlxsw_reg_info mlxsw_reg_sldr = {
-	.id = MLXSW_REG_SLDR_ID,
-	.len = MLXSW_REG_SLDR_LEN,
-};
+MLXSW_REG_DEFINE(sldr, MLXSW_REG_SLDR_ID, MLXSW_REG_SLDR_LEN);
 
 enum mlxsw_reg_sldr_op {
 	/* Indicates a creation of a new LAG-ID, lag_id must be valid */
@@ -1288,10 +1251,7 @@ static inline void mlxsw_reg_sldr_lag_re
 #define MLXSW_REG_SLCR_ID 0x2015
 #define MLXSW_REG_SLCR_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_slcr = {
-	.id = MLXSW_REG_SLCR_ID,
-	.len = MLXSW_REG_SLCR_LEN,
-};
+MLXSW_REG_DEFINE(slcr, MLXSW_REG_SLCR_ID, MLXSW_REG_SLCR_LEN);
 
 enum mlxsw_reg_slcr_pp {
 	/* Global Configuration (for all ports) */
@@ -1404,10 +1364,7 @@ static inline void mlxsw_reg_slcr_pack(c
 #define MLXSW_REG_SLCOR_ID 0x2016
 #define MLXSW_REG_SLCOR_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_slcor = {
-	.id = MLXSW_REG_SLCOR_ID,
-	.len = MLXSW_REG_SLCOR_LEN,
-};
+MLXSW_REG_DEFINE(slcor, MLXSW_REG_SLCOR_ID, MLXSW_REG_SLCOR_LEN);
 
 enum mlxsw_reg_slcor_col {
 	/* Port is added with collector disabled */
@@ -1490,10 +1447,7 @@ static inline void mlxsw_reg_slcor_col_d
 #define MLXSW_REG_SPMLR_ID 0x2018
 #define MLXSW_REG_SPMLR_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_spmlr = {
-	.id = MLXSW_REG_SPMLR_ID,
-	.len = MLXSW_REG_SPMLR_LEN,
-};
+MLXSW_REG_DEFINE(spmlr, MLXSW_REG_SPMLR_ID, MLXSW_REG_SPMLR_LEN);
 
 /* reg_spmlr_local_port
  * Local port number.
@@ -1544,10 +1498,7 @@ static inline void mlxsw_reg_spmlr_pack(
 #define MLXSW_REG_SVFA_ID 0x201C
 #define MLXSW_REG_SVFA_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_svfa = {
-	.id = MLXSW_REG_SVFA_ID,
-	.len = MLXSW_REG_SVFA_LEN,
-};
+MLXSW_REG_DEFINE(svfa, MLXSW_REG_SVFA_ID, MLXSW_REG_SVFA_LEN);
 
 /* reg_svfa_swid
  * Switch partition ID.
@@ -1636,10 +1587,7 @@ static inline void mlxsw_reg_svfa_pack(c
 #define MLXSW_REG_SVPE_ID 0x201E
 #define MLXSW_REG_SVPE_LEN 0x4
 
-static const struct mlxsw_reg_info mlxsw_reg_svpe = {
-	.id = MLXSW_REG_SVPE_ID,
-	.len = MLXSW_REG_SVPE_LEN,
-};
+MLXSW_REG_DEFINE(svpe, MLXSW_REG_SVPE_ID, MLXSW_REG_SVPE_LEN);
 
 /* reg_svpe_local_port
  * Local port number
@@ -1672,10 +1620,7 @@ static inline void mlxsw_reg_svpe_pack(c
 #define MLXSW_REG_SFMR_ID 0x201F
 #define MLXSW_REG_SFMR_LEN 0x18
 
-static const struct mlxsw_reg_info mlxsw_reg_sfmr = {
-	.id = MLXSW_REG_SFMR_ID,
-	.len = MLXSW_REG_SFMR_LEN,
-};
+MLXSW_REG_DEFINE(sfmr, MLXSW_REG_SFMR_ID, MLXSW_REG_SFMR_LEN);
 
 enum mlxsw_reg_sfmr_op {
 	MLXSW_REG_SFMR_OP_CREATE_FID,
@@ -1762,10 +1707,7 @@ static inline void mlxsw_reg_sfmr_pack(c
 			      MLXSW_REG_SPVMLR_REC_LEN * \
 			      MLXSW_REG_SPVMLR_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_spvmlr = {
-	.id = MLXSW_REG_SPVMLR_ID,
-	.len = MLXSW_REG_SPVMLR_LEN,
-};
+MLXSW_REG_DEFINE(spvmlr, MLXSW_REG_SPVMLR_ID, MLXSW_REG_SPVMLR_LEN);
 
 /* reg_spvmlr_local_port
  * Local ingress port.
@@ -1815,6 +1757,146 @@ static inline void mlxsw_reg_spvmlr_pack
 	}
 }
 
+/* QPCR - QoS Policer Configuration Register
+ * -----------------------------------------
+ * The QPCR register is used to create policers - that limit
+ * the rate of bytes or packets via some trap group.
+ */
+#define MLXSW_REG_QPCR_ID 0x4004
+#define MLXSW_REG_QPCR_LEN 0x28
+
+MLXSW_REG_DEFINE(qpcr, MLXSW_REG_QPCR_ID, MLXSW_REG_QPCR_LEN);
+
+enum mlxsw_reg_qpcr_g {
+	MLXSW_REG_QPCR_G_GLOBAL = 2,
+	MLXSW_REG_QPCR_G_STORM_CONTROL = 3,
+};
+
+/* reg_qpcr_g
+ * The policer type.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, qpcr, g, 0x00, 14, 2);
+
+/* reg_qpcr_pid
+ * Policer ID.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, qpcr, pid, 0x00, 0, 14);
+
+/* reg_qpcr_color_aware
+ * Is the policer aware of colors.
+ * Must be 0 (unaware) for cpu port.
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, color_aware, 0x04, 15, 1);
+
+/* reg_qpcr_bytes
+ * Is policer limit is for bytes per sec or packets per sec.
+ * 0 - packets
+ * 1 - bytes
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, bytes, 0x04, 14, 1);
+
+enum mlxsw_reg_qpcr_ir_units {
+	MLXSW_REG_QPCR_IR_UNITS_M,
+	MLXSW_REG_QPCR_IR_UNITS_K,
+};
+
+/* reg_qpcr_ir_units
+ * Policer's units for cir and eir fields (for bytes limits only)
+ * 1 - 10^3
+ * 0 - 10^6
+ * Access: OP
+ */
+MLXSW_ITEM32(reg, qpcr, ir_units, 0x04, 12, 1);
+
+enum mlxsw_reg_qpcr_rate_type {
+	MLXSW_REG_QPCR_RATE_TYPE_SINGLE = 1,
+	MLXSW_REG_QPCR_RATE_TYPE_DOUBLE = 2,
+};
+
+/* reg_qpcr_rate_type
+ * Policer can have one limit (single rate) or 2 limits with specific operation
+ * for packets that exceed the lower rate but not the upper one.
+ * (For cpu port must be single rate)
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, rate_type, 0x04, 8, 2);
+
+/* reg_qpc_cbs
+ * Policer's committed burst size.
+ * The policer is working with time slices of 50 nano sec. By default every
+ * slice is granted the proportionate share of the committed rate. If we want to
+ * allow a slice to exceed that share (while still keeping the rate per sec) we
+ * can allow burst. The burst size is between the default proportionate share
+ * (and no lower than 8) to 32Gb. (Even though giving a number higher than the
+ * committed rate will result in exceeding the rate). The burst size must be a
+ * log of 2 and will be determined by 2^cbs.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qpcr, cbs, 0x08, 24, 6);
+
+/* reg_qpcr_cir
+ * Policer's committed rate.
+ * The rate used for sungle rate, the lower rate for double rate.
+ * For bytes limits, the rate will be this value * the unit from ir_units.
+ * (Resolution error is up to 1%).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qpcr, cir, 0x0C, 0, 32);
+
+/* reg_qpcr_eir
+ * Policer's exceed rate.
+ * The higher rate for double rate, reserved for single rate.
+ * Lower rate for double rate policer.
+ * For bytes limits, the rate will be this value * the unit from ir_units.
+ * (Resolution error is up to 1%).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, qpcr, eir, 0x10, 0, 32);
+
+#define MLXSW_REG_QPCR_DOUBLE_RATE_ACTION 2
+
+/* reg_qpcr_exceed_action.
+ * What to do with packets between the 2 limits for double rate.
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, exceed_action, 0x14, 0, 4);
+
+enum mlxsw_reg_qpcr_action {
+	/* Discard */
+	MLXSW_REG_QPCR_ACTION_DISCARD = 1,
+	/* Forward and set color to red.
+	 * If the packet is intended to cpu port, it will be dropped.
+	 */
+	MLXSW_REG_QPCR_ACTION_FORWARD = 2,
+};
+
+/* reg_qpcr_violate_action
+ * What to do with packets that cross the cir limit (for single rate) or the eir
+ * limit (for double rate).
+ * Access: RW for unbounded policer. RO for bounded policer.
+ */
+MLXSW_ITEM32(reg, qpcr, violate_action, 0x18, 0, 4);
+
+static inline void mlxsw_reg_qpcr_pack(char *payload, u16 pid,
+				       enum mlxsw_reg_qpcr_ir_units ir_units,
+				       bool bytes, u32 cir, u16 cbs)
+{
+	MLXSW_REG_ZERO(qpcr, payload);
+	mlxsw_reg_qpcr_pid_set(payload, pid);
+	mlxsw_reg_qpcr_g_set(payload, MLXSW_REG_QPCR_G_GLOBAL);
+	mlxsw_reg_qpcr_rate_type_set(payload, MLXSW_REG_QPCR_RATE_TYPE_SINGLE);
+	mlxsw_reg_qpcr_violate_action_set(payload,
+					  MLXSW_REG_QPCR_ACTION_DISCARD);
+	mlxsw_reg_qpcr_cir_set(payload, cir);
+	mlxsw_reg_qpcr_ir_units_set(payload, ir_units);
+	mlxsw_reg_qpcr_bytes_set(payload, bytes);
+	mlxsw_reg_qpcr_cbs_set(payload, cbs);
+}
+
 /* QTCT - QoS Switch Traffic Class Table
  * -------------------------------------
  * Configures the mapping between the packet switch priority and the
@@ -1823,10 +1905,7 @@ static inline void mlxsw_reg_spvmlr_pack
 #define MLXSW_REG_QTCT_ID 0x400A
 #define MLXSW_REG_QTCT_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_qtct = {
-	.id = MLXSW_REG_QTCT_ID,
-	.len = MLXSW_REG_QTCT_LEN,
-};
+MLXSW_REG_DEFINE(qtct, MLXSW_REG_QTCT_ID, MLXSW_REG_QTCT_LEN);
 
 /* reg_qtct_local_port
  * Local port number.
@@ -1875,10 +1954,7 @@ static inline void mlxsw_reg_qtct_pack(c
 #define MLXSW_REG_QEEC_ID 0x400D
 #define MLXSW_REG_QEEC_LEN 0x1C
 
-static const struct mlxsw_reg_info mlxsw_reg_qeec = {
-	.id = MLXSW_REG_QEEC_ID,
-	.len = MLXSW_REG_QEEC_LEN,
-};
+MLXSW_REG_DEFINE(qeec, MLXSW_REG_QEEC_ID, MLXSW_REG_QEEC_LEN);
 
 /* reg_qeec_local_port
  * Local port number.
@@ -2000,10 +2076,7 @@ static inline void mlxsw_reg_qeec_pack(c
 #define MLXSW_REG_PMLP_ID 0x5002
 #define MLXSW_REG_PMLP_LEN 0x40
 
-static const struct mlxsw_reg_info mlxsw_reg_pmlp = {
-	.id = MLXSW_REG_PMLP_ID,
-	.len = MLXSW_REG_PMLP_LEN,
-};
+MLXSW_REG_DEFINE(pmlp, MLXSW_REG_PMLP_ID, MLXSW_REG_PMLP_LEN);
 
 /* reg_pmlp_rxtx
  * 0 - Tx value is used for both Tx and Rx.
@@ -2059,10 +2132,7 @@ static inline void mlxsw_reg_pmlp_pack(c
 #define MLXSW_REG_PMTU_ID 0x5003
 #define MLXSW_REG_PMTU_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_pmtu = {
-	.id = MLXSW_REG_PMTU_ID,
-	.len = MLXSW_REG_PMTU_LEN,
-};
+MLXSW_REG_DEFINE(pmtu, MLXSW_REG_PMTU_ID, MLXSW_REG_PMTU_LEN);
 
 /* reg_pmtu_local_port
  * Local port number.
@@ -2116,10 +2186,7 @@ static inline void mlxsw_reg_pmtu_pack(c
 #define MLXSW_REG_PTYS_ID 0x5004
 #define MLXSW_REG_PTYS_LEN 0x40
 
-static const struct mlxsw_reg_info mlxsw_reg_ptys = {
-	.id = MLXSW_REG_PTYS_ID,
-	.len = MLXSW_REG_PTYS_LEN,
-};
+MLXSW_REG_DEFINE(ptys, MLXSW_REG_PTYS_ID, MLXSW_REG_PTYS_LEN);
 
 /* reg_ptys_local_port
  * Local port number.
@@ -2127,6 +2194,7 @@ static const struct mlxsw_reg_info mlxsw
  */
 MLXSW_ITEM32(reg, ptys, local_port, 0x00, 16, 8);
 
+#define MLXSW_REG_PTYS_PROTO_MASK_IB	BIT(0)
 #define MLXSW_REG_PTYS_PROTO_MASK_ETH	BIT(2)
 
 /* reg_ptys_proto_mask
@@ -2185,18 +2253,61 @@ MLXSW_ITEM32(reg, ptys, an_status, 0x04,
  */
 MLXSW_ITEM32(reg, ptys, eth_proto_cap, 0x0C, 0, 32);
 
+/* reg_ptys_ib_link_width_cap
+ * IB port supported widths.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_link_width_cap, 0x10, 16, 16);
+
+#define MLXSW_REG_PTYS_IB_SPEED_SDR	BIT(0)
+#define MLXSW_REG_PTYS_IB_SPEED_DDR	BIT(1)
+#define MLXSW_REG_PTYS_IB_SPEED_QDR	BIT(2)
+#define MLXSW_REG_PTYS_IB_SPEED_FDR10	BIT(3)
+#define MLXSW_REG_PTYS_IB_SPEED_FDR	BIT(4)
+#define MLXSW_REG_PTYS_IB_SPEED_EDR	BIT(5)
+
+/* reg_ptys_ib_proto_cap
+ * IB port supported speeds and protocols.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_proto_cap, 0x10, 0, 16);
+
 /* reg_ptys_eth_proto_admin
  * Speed and protocol to set port to.
  * Access: RW
  */
 MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 0, 32);
 
+/* reg_ptys_ib_link_width_admin
+ * IB width to set port to.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, ptys, ib_link_width_admin, 0x1C, 16, 16);
+
+/* reg_ptys_ib_proto_admin
+ * IB speeds and protocols to set port to.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, ptys, ib_proto_admin, 0x1C, 0, 16);
+
 /* reg_ptys_eth_proto_oper
  * The current speed and protocol configured for the port.
  * Access: RO
  */
 MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32);
 
+/* reg_ptys_ib_link_width_oper
+ * The current IB width to set port to.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16);
+
+/* reg_ptys_ib_proto_oper
+ * The current IB speed and protocol.
+ * Access: RO
+ */
+MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16);
+
 /* reg_ptys_eth_proto_lp_advertise
  * The protocols that were advertised by the link partner during
  * autonegotiation.
@@ -2204,8 +2315,8 @@ MLXSW_ITEM32(reg, ptys, eth_proto_oper,
  */
 MLXSW_ITEM32(reg, ptys, eth_proto_lp_advertise, 0x30, 0, 32);
 
-static inline void mlxsw_reg_ptys_pack(char *payload, u8 local_port,
-				       u32 proto_admin)
+static inline void mlxsw_reg_ptys_eth_pack(char *payload, u8 local_port,
+					   u32 proto_admin)
 {
 	MLXSW_REG_ZERO(ptys, payload);
 	mlxsw_reg_ptys_local_port_set(payload, local_port);
@@ -2213,9 +2324,10 @@ static inline void mlxsw_reg_ptys_pack(c
 	mlxsw_reg_ptys_eth_proto_admin_set(payload, proto_admin);
 }
 
-static inline void mlxsw_reg_ptys_unpack(char *payload, u32 *p_eth_proto_cap,
-					 u32 *p_eth_proto_adm,
-					 u32 *p_eth_proto_oper)
+static inline void mlxsw_reg_ptys_eth_unpack(char *payload,
+					     u32 *p_eth_proto_cap,
+					     u32 *p_eth_proto_adm,
+					     u32 *p_eth_proto_oper)
 {
 	if (p_eth_proto_cap)
 		*p_eth_proto_cap = mlxsw_reg_ptys_eth_proto_cap_get(payload);
@@ -2225,6 +2337,33 @@ static inline void mlxsw_reg_ptys_unpack
 		*p_eth_proto_oper = mlxsw_reg_ptys_eth_proto_oper_get(payload);
 }
 
+static inline void mlxsw_reg_ptys_ib_pack(char *payload, u8 local_port,
+					  u16 proto_admin, u16 link_width)
+{
+	MLXSW_REG_ZERO(ptys, payload);
+	mlxsw_reg_ptys_local_port_set(payload, local_port);
+	mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_IB);
+	mlxsw_reg_ptys_ib_proto_admin_set(payload, proto_admin);
+	mlxsw_reg_ptys_ib_link_width_admin_set(payload, link_width);
+}
+
+static inline void mlxsw_reg_ptys_ib_unpack(char *payload, u16 *p_ib_proto_cap,
+					    u16 *p_ib_link_width_cap,
+					    u16 *p_ib_proto_oper,
+					    u16 *p_ib_link_width_oper)
+{
+	if (p_ib_proto_cap)
+		*p_ib_proto_cap = mlxsw_reg_ptys_ib_proto_cap_get(payload);
+	if (p_ib_link_width_cap)
+		*p_ib_link_width_cap =
+			mlxsw_reg_ptys_ib_link_width_cap_get(payload);
+	if (p_ib_proto_oper)
+		*p_ib_proto_oper = mlxsw_reg_ptys_ib_proto_oper_get(payload);
+	if (p_ib_link_width_oper)
+		*p_ib_link_width_oper =
+			mlxsw_reg_ptys_ib_link_width_oper_get(payload);
+}
+
 /* PPAD - Port Physical Address Register
  * -------------------------------------
  * The PPAD register configures the per port physical MAC address.
@@ -2232,10 +2371,7 @@ static inline void mlxsw_reg_ptys_unpack
 #define MLXSW_REG_PPAD_ID 0x5005
 #define MLXSW_REG_PPAD_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_ppad = {
-	.id = MLXSW_REG_PPAD_ID,
-	.len = MLXSW_REG_PPAD_LEN,
-};
+MLXSW_REG_DEFINE(ppad, MLXSW_REG_PPAD_ID, MLXSW_REG_PPAD_LEN);
 
 /* reg_ppad_single_base_mac
  * 0: base_mac, local port should be 0 and mac[7:0] is
@@ -2273,10 +2409,7 @@ static inline void mlxsw_reg_ppad_pack(c
 #define MLXSW_REG_PAOS_ID 0x5006
 #define MLXSW_REG_PAOS_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_paos = {
-	.id = MLXSW_REG_PAOS_ID,
-	.len = MLXSW_REG_PAOS_LEN,
-};
+MLXSW_REG_DEFINE(paos, MLXSW_REG_PAOS_ID, MLXSW_REG_PAOS_LEN);
 
 /* reg_paos_swid
  * Switch partition ID with which to associate the port.
@@ -2356,10 +2489,7 @@ static inline void mlxsw_reg_paos_pack(c
 #define MLXSW_REG_PFCC_ID 0x5007
 #define MLXSW_REG_PFCC_LEN 0x20
 
-static const struct mlxsw_reg_info mlxsw_reg_pfcc = {
-	.id = MLXSW_REG_PFCC_ID,
-	.len = MLXSW_REG_PFCC_LEN,
-};
+MLXSW_REG_DEFINE(pfcc, MLXSW_REG_PFCC_ID, MLXSW_REG_PFCC_LEN);
 
 /* reg_pfcc_local_port
  * Local port number.
@@ -2495,10 +2625,7 @@ static inline void mlxsw_reg_pfcc_pack(c
 #define MLXSW_REG_PPCNT_ID 0x5008
 #define MLXSW_REG_PPCNT_LEN 0x100
 
-static const struct mlxsw_reg_info mlxsw_reg_ppcnt = {
-	.id = MLXSW_REG_PPCNT_ID,
-	.len = MLXSW_REG_PPCNT_LEN,
-};
+MLXSW_REG_DEFINE(ppcnt, MLXSW_REG_PPCNT_ID, MLXSW_REG_PPCNT_LEN);
 
 /* reg_ppcnt_swid
  * For HCA: must be always 0.
@@ -2761,6 +2888,27 @@ static inline void mlxsw_reg_ppcnt_pack(
 	mlxsw_reg_ppcnt_prio_tc_set(payload, prio_tc);
 }
 
+/* PLIB - Port Local to InfiniBand Port
+ * ------------------------------------
+ * The PLIB register performs mapping from Local Port into InfiniBand Port.
+ */
+#define MLXSW_REG_PLIB_ID 0x500A
+#define MLXSW_REG_PLIB_LEN 0x10
+
+MLXSW_REG_DEFINE(plib, MLXSW_REG_PLIB_ID, MLXSW_REG_PLIB_LEN);
+
+/* reg_plib_local_port
+ * Local port number.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, plib, local_port, 0x00, 16, 8);
+
+/* reg_plib_ib_port
+ * InfiniBand port remapping for local_port.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, plib, ib_port, 0x00, 0, 8);
+
 /* PPTB - Port Prio To Buffer Register
  * -----------------------------------
  * Configures the switch priority to buffer table.
@@ -2768,10 +2916,7 @@ static inline void mlxsw_reg_ppcnt_pack(
 #define MLXSW_REG_PPTB_ID 0x500B
 #define MLXSW_REG_PPTB_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_pptb = {
-	.id = MLXSW_REG_PPTB_ID,
-	.len = MLXSW_REG_PPTB_LEN,
-};
+MLXSW_REG_DEFINE(pptb, MLXSW_REG_PPTB_ID, MLXSW_REG_PPTB_LEN);
 
 enum {
 	MLXSW_REG_PPTB_MM_UM,
@@ -2865,10 +3010,7 @@ static inline void mlxsw_reg_pptb_prio_t
 #define MLXSW_REG_PBMC_ID 0x500C
 #define MLXSW_REG_PBMC_LEN 0x6C
 
-static const struct mlxsw_reg_info mlxsw_reg_pbmc = {
-	.id = MLXSW_REG_PBMC_ID,
-	.len = MLXSW_REG_PBMC_LEN,
-};
+MLXSW_REG_DEFINE(pbmc, MLXSW_REG_PBMC_ID, MLXSW_REG_PBMC_LEN);
 
 /* reg_pbmc_local_port
  * Local port number.
@@ -2978,10 +3120,7 @@ static inline void mlxsw_reg_pbmc_lossle
 #define MLXSW_REG_PSPA_ID 0x500D
 #define MLXSW_REG_PSPA_LEN 0x8
 
-static const struct mlxsw_reg_info mlxsw_reg_pspa = {
-	.id = MLXSW_REG_PSPA_ID,
-	.len = MLXSW_REG_PSPA_LEN,
-};
+MLXSW_REG_DEFINE(pspa, MLXSW_REG_PSPA_ID, MLXSW_REG_PSPA_LEN);
 
 /* reg_pspa_swid
  * Switch partition ID.
@@ -3017,10 +3156,7 @@ static inline void mlxsw_reg_pspa_pack(c
 #define MLXSW_REG_HTGT_ID 0x7002
 #define MLXSW_REG_HTGT_LEN 0x100
 
-static const struct mlxsw_reg_info mlxsw_reg_htgt = {
-	.id = MLXSW_REG_HTGT_ID,
-	.len = MLXSW_REG_HTGT_LEN,
-};
+MLXSW_REG_DEFINE(htgt, MLXSW_REG_HTGT_ID, MLXSW_REG_HTGT_LEN);
 
 /* reg_htgt_swid
  * Switch partition ID.
@@ -3038,8 +3174,21 @@ MLXSW_ITEM32(reg, htgt, type, 0x00, 8, 4
 
 enum mlxsw_reg_htgt_trap_group {
 	MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
-	MLXSW_REG_HTGT_TRAP_GROUP_RX,
-	MLXSW_REG_HTGT_TRAP_GROUP_CTRL,
+	MLXSW_REG_HTGT_TRAP_GROUP_SX2_RX,
+	MLXSW_REG_HTGT_TRAP_GROUP_SX2_CTRL,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_STP,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT,
 };
 
 /* reg_htgt_trap_group
@@ -3061,6 +3210,8 @@ enum {
  */
 MLXSW_ITEM32(reg, htgt, pide, 0x04, 15, 1);
 
+#define MLXSW_REG_HTGT_INVALID_POLICER 0xff
+
 /* reg_htgt_pid
  * Policer ID for the trap group.
  * Access: RW
@@ -3086,6 +3237,8 @@ MLXSW_ITEM32(reg, htgt, mirror_action, 0
  */
 MLXSW_ITEM32(reg, htgt, mirroring_agent, 0x08, 0, 3);
 
+#define MLXSW_REG_HTGT_DEFAULT_PRIORITY 0
+
 /* reg_htgt_priority
  * Trap group priority.
  * In case a packet matches multiple classification rules, the packet will
@@ -3099,52 +3252,47 @@ MLXSW_ITEM32(reg, htgt, mirroring_agent,
  */
 MLXSW_ITEM32(reg, htgt, priority, 0x0C, 0, 4);
 
+#define MLXSW_REG_HTGT_DEFAULT_TC 7
+
 /* reg_htgt_local_path_cpu_tclass
  * CPU ingress traffic class for the trap group.
  * Access: RW
  */
 MLXSW_ITEM32(reg, htgt, local_path_cpu_tclass, 0x10, 16, 6);
 
-#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD	0x15
-#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX	0x14
-#define MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL	0x13
-
+enum mlxsw_reg_htgt_local_path_rdq {
+	MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_CTRL = 0x13,
+	MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_RX = 0x14,
+	MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SX2_EMAD = 0x15,
+	MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD = 0x15,
+};
 /* reg_htgt_local_path_rdq
  * Receive descriptor queue (RDQ) to use for the trap group.
  * Access: RW
  */
 MLXSW_ITEM32(reg, htgt, local_path_rdq, 0x10, 0, 6);
 
-static inline void mlxsw_reg_htgt_pack(char *payload,
-				       enum mlxsw_reg_htgt_trap_group group)
+static inline void mlxsw_reg_htgt_pack(char *payload, u8 group, u8 policer_id,
+				       u8 priority, u8 tc)
 {
-	u8 swid, rdq;
-
 	MLXSW_REG_ZERO(htgt, payload);
-	switch (group) {
-	case MLXSW_REG_HTGT_TRAP_GROUP_EMAD:
-		swid = MLXSW_PORT_SWID_ALL_SWIDS;
-		rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_EMAD;
-		break;
-	case MLXSW_REG_HTGT_TRAP_GROUP_RX:
-		swid = 0;
-		rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_RX;
-		break;
-	case MLXSW_REG_HTGT_TRAP_GROUP_CTRL:
-		swid = 0;
-		rdq = MLXSW_REG_HTGT_LOCAL_PATH_RDQ_CTRL;
-		break;
+
+	if (policer_id == MLXSW_REG_HTGT_INVALID_POLICER) {
+		mlxsw_reg_htgt_pide_set(payload,
+					MLXSW_REG_HTGT_POLICER_DISABLE);
+	} else {
+		mlxsw_reg_htgt_pide_set(payload,
+					MLXSW_REG_HTGT_POLICER_ENABLE);
+		mlxsw_reg_htgt_pid_set(payload, policer_id);
 	}
-	mlxsw_reg_htgt_swid_set(payload, swid);
+
 	mlxsw_reg_htgt_type_set(payload, MLXSW_REG_HTGT_PATH_TYPE_LOCAL);
 	mlxsw_reg_htgt_trap_group_set(payload, group);
-	mlxsw_reg_htgt_pide_set(payload, MLXSW_REG_HTGT_POLICER_DISABLE);
-	mlxsw_reg_htgt_pid_set(payload, 0);
 	mlxsw_reg_htgt_mirror_action_set(payload, MLXSW_REG_HTGT_TRAP_TO_CPU);
 	mlxsw_reg_htgt_mirroring_agent_set(payload, 0);
-	mlxsw_reg_htgt_priority_set(payload, 0);
-	mlxsw_reg_htgt_local_path_cpu_tclass_set(payload, 7);
-	mlxsw_reg_htgt_local_path_rdq_set(payload, rdq);
+	mlxsw_reg_htgt_priority_set(payload, priority);
+	mlxsw_reg_htgt_local_path_cpu_tclass_set(payload, tc);
+	mlxsw_reg_htgt_local_path_rdq_set(payload, group);
 }
 
 /* HPKT - Host Packet Trap
@@ -3154,10 +3302,7 @@ static inline void mlxsw_reg_htgt_pack(c
 #define MLXSW_REG_HPKT_ID 0x7003
 #define MLXSW_REG_HPKT_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_hpkt = {
-	.id = MLXSW_REG_HPKT_ID,
-	.len = MLXSW_REG_HPKT_LEN,
-};
+MLXSW_REG_DEFINE(hpkt, MLXSW_REG_HPKT_ID, MLXSW_REG_HPKT_LEN);
 
 enum {
 	MLXSW_REG_HPKT_ACK_NOT_REQUIRED,
@@ -3221,6 +3366,7 @@ enum {
 
 /* reg_hpkt_ctrl
  * Configure dedicated buffer resources for control packets.
+ * Ignored by SwitchX-2.
  * 0 - Keep factory defaults.
  * 1 - Do not use control buffer for this trap ID.
  * 2 - Use control buffer for this trap ID.
@@ -3228,25 +3374,18 @@ enum {
  */
 MLXSW_ITEM32(reg, hpkt, ctrl, 0x04, 16, 2);
 
-static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id)
+static inline void mlxsw_reg_hpkt_pack(char *payload, u8 action, u16 trap_id,
+				       enum mlxsw_reg_htgt_trap_group trap_group,
+				       bool is_ctrl)
 {
-	enum mlxsw_reg_htgt_trap_group trap_group;
-
 	MLXSW_REG_ZERO(hpkt, payload);
 	mlxsw_reg_hpkt_ack_set(payload, MLXSW_REG_HPKT_ACK_NOT_REQUIRED);
 	mlxsw_reg_hpkt_action_set(payload, action);
-	switch (trap_id) {
-	case MLXSW_TRAP_ID_ETHEMAD:
-	case MLXSW_TRAP_ID_PUDE:
-		trap_group = MLXSW_REG_HTGT_TRAP_GROUP_EMAD;
-		break;
-	default:
-		trap_group = MLXSW_REG_HTGT_TRAP_GROUP_RX;
-		break;
-	}
 	mlxsw_reg_hpkt_trap_group_set(payload, trap_group);
 	mlxsw_reg_hpkt_trap_id_set(payload, trap_id);
-	mlxsw_reg_hpkt_ctrl_set(payload, MLXSW_REG_HPKT_CTRL_PACKET_DEFAULT);
+	mlxsw_reg_hpkt_ctrl_set(payload, is_ctrl ?
+				MLXSW_REG_HPKT_CTRL_PACKET_USE_BUFFER :
+				MLXSW_REG_HPKT_CTRL_PACKET_NO_BUFFER);
 }
 
 /* RGCR - Router General Configuration Register
@@ -3256,10 +3395,7 @@ static inline void mlxsw_reg_hpkt_pack(c
 #define MLXSW_REG_RGCR_ID 0x8001
 #define MLXSW_REG_RGCR_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_rgcr = {
-	.id = MLXSW_REG_RGCR_ID,
-	.len = MLXSW_REG_RGCR_LEN,
-};
+MLXSW_REG_DEFINE(rgcr, MLXSW_REG_RGCR_ID, MLXSW_REG_RGCR_LEN);
 
 /* reg_rgcr_ipv4_en
  * IPv4 router enable.
@@ -3330,10 +3466,7 @@ static inline void mlxsw_reg_rgcr_pack(c
 #define MLXSW_REG_RITR_ID 0x8002
 #define MLXSW_REG_RITR_LEN 0x40
 
-static const struct mlxsw_reg_info mlxsw_reg_ritr = {
-	.id = MLXSW_REG_RITR_ID,
-	.len = MLXSW_REG_RITR_LEN,
-};
+MLXSW_REG_DEFINE(ritr, MLXSW_REG_RITR_ID, MLXSW_REG_RITR_LEN);
 
 /* reg_ritr_enable
  * Enables routing on the router interface.
@@ -3533,10 +3666,7 @@ static inline void mlxsw_reg_ritr_pack(c
 #define MLXSW_REG_RATR_ID 0x8008
 #define MLXSW_REG_RATR_LEN 0x2C
 
-static const struct mlxsw_reg_info mlxsw_reg_ratr = {
-	.id = MLXSW_REG_RATR_ID,
-	.len = MLXSW_REG_RATR_LEN,
-};
+MLXSW_REG_DEFINE(ratr, MLXSW_REG_RATR_ID, MLXSW_REG_RATR_LEN);
 
 enum mlxsw_reg_ratr_op {
 	/* Read */
@@ -3663,10 +3793,7 @@ static inline void mlxsw_reg_ratr_eth_en
 #define MLXSW_REG_RALTA_ID 0x8010
 #define MLXSW_REG_RALTA_LEN 0x04
 
-static const struct mlxsw_reg_info mlxsw_reg_ralta = {
-	.id = MLXSW_REG_RALTA_ID,
-	.len = MLXSW_REG_RALTA_LEN,
-};
+MLXSW_REG_DEFINE(ralta, MLXSW_REG_RALTA_ID, MLXSW_REG_RALTA_LEN);
 
 /* reg_ralta_op
  * opcode (valid for Write, must be 0 on Read)
@@ -3718,10 +3845,7 @@ static inline void mlxsw_reg_ralta_pack(
 #define MLXSW_REG_RALST_ID 0x8011
 #define MLXSW_REG_RALST_LEN 0x104
 
-static const struct mlxsw_reg_info mlxsw_reg_ralst = {
-	.id = MLXSW_REG_RALST_ID,
-	.len = MLXSW_REG_RALST_LEN,
-};
+MLXSW_REG_DEFINE(ralst, MLXSW_REG_RALST_ID, MLXSW_REG_RALST_LEN);
 
 /* reg_ralst_root_bin
  * The bin number of the root bin.
@@ -3788,10 +3912,7 @@ static inline void mlxsw_reg_ralst_bin_p
 #define MLXSW_REG_RALTB_ID 0x8012
 #define MLXSW_REG_RALTB_LEN 0x04
 
-static const struct mlxsw_reg_info mlxsw_reg_raltb = {
-	.id = MLXSW_REG_RALTB_ID,
-	.len = MLXSW_REG_RALTB_LEN,
-};
+MLXSW_REG_DEFINE(raltb, MLXSW_REG_RALTB_ID, MLXSW_REG_RALTB_LEN);
 
 /* reg_raltb_virtual_router
  * Virtual Router ID
@@ -3832,10 +3953,7 @@ static inline void mlxsw_reg_raltb_pack(
 #define MLXSW_REG_RALUE_ID 0x8013
 #define MLXSW_REG_RALUE_LEN 0x38
 
-static const struct mlxsw_reg_info mlxsw_reg_ralue = {
-	.id = MLXSW_REG_RALUE_ID,
-	.len = MLXSW_REG_RALUE_LEN,
-};
+MLXSW_REG_DEFINE(ralue, MLXSW_REG_RALUE_ID, MLXSW_REG_RALUE_LEN);
 
 /* reg_ralue_protocol
  * Protocol.
@@ -4095,10 +4213,7 @@ mlxsw_reg_ralue_act_ip2me_pack(char *pay
 #define MLXSW_REG_RAUHT_ID 0x8014
 #define MLXSW_REG_RAUHT_LEN 0x74
 
-static const struct mlxsw_reg_info mlxsw_reg_rauht = {
-	.id = MLXSW_REG_RAUHT_ID,
-	.len = MLXSW_REG_RAUHT_LEN,
-};
+MLXSW_REG_DEFINE(rauht, MLXSW_REG_RAUHT_ID, MLXSW_REG_RAUHT_LEN);
 
 enum mlxsw_reg_rauht_type {
 	MLXSW_REG_RAUHT_TYPE_IPV4,
@@ -4234,10 +4349,7 @@ static inline void mlxsw_reg_rauht_pack4
 #define MLXSW_REG_RALEU_ID 0x8015
 #define MLXSW_REG_RALEU_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_raleu = {
-	.id = MLXSW_REG_RALEU_ID,
-	.len = MLXSW_REG_RALEU_LEN,
-};
+MLXSW_REG_DEFINE(raleu, MLXSW_REG_RALEU_ID, MLXSW_REG_RALEU_LEN);
 
 /* reg_raleu_protocol
  * Protocol.
@@ -4309,10 +4421,7 @@ static inline void mlxsw_reg_raleu_pack(
 		MLXSW_REG_RAUHTD_REC_MAX_NUM * MLXSW_REG_RAUHTD_REC_LEN)
 #define MLXSW_REG_RAUHTD_IPV4_ENT_PER_REC 4
 
-static const struct mlxsw_reg_info mlxsw_reg_rauhtd = {
-	.id = MLXSW_REG_RAUHTD_ID,
-	.len = MLXSW_REG_RAUHTD_LEN,
-};
+MLXSW_REG_DEFINE(rauhtd, MLXSW_REG_RAUHTD_ID, MLXSW_REG_RAUHTD_LEN);
 
 #define MLXSW_REG_RAUHTD_FILTER_A BIT(0)
 #define MLXSW_REG_RAUHTD_FILTER_RIF BIT(3)
@@ -4444,10 +4553,7 @@ static inline void mlxsw_reg_rauhtd_ent_
 #define MLXSW_REG_MFCR_ID 0x9001
 #define MLXSW_REG_MFCR_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mfcr = {
-	.id = MLXSW_REG_MFCR_ID,
-	.len = MLXSW_REG_MFCR_LEN,
-};
+MLXSW_REG_DEFINE(mfcr, MLXSW_REG_MFCR_ID, MLXSW_REG_MFCR_LEN);
 
 enum mlxsw_reg_mfcr_pwm_frequency {
 	MLXSW_REG_MFCR_PWM_FEQ_11HZ = 0x00,
@@ -4464,7 +4570,7 @@ enum mlxsw_reg_mfcr_pwm_frequency {
  * Controls the frequency of the PWM signal.
  * Access: RW
  */
-MLXSW_ITEM32(reg, mfcr, pwm_frequency, 0x00, 0, 6);
+MLXSW_ITEM32(reg, mfcr, pwm_frequency, 0x00, 0, 7);
 
 #define MLXSW_MFCR_TACHOS_MAX 10
 
@@ -4507,10 +4613,7 @@ mlxsw_reg_mfcr_unpack(char *payload,
 #define MLXSW_REG_MFSC_ID 0x9002
 #define MLXSW_REG_MFSC_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mfsc = {
-	.id = MLXSW_REG_MFSC_ID,
-	.len = MLXSW_REG_MFSC_LEN,
-};
+MLXSW_REG_DEFINE(mfsc, MLXSW_REG_MFSC_ID, MLXSW_REG_MFSC_LEN);
 
 /* reg_mfsc_pwm
  * Fan pwm to control / monitor.
@@ -4541,10 +4644,7 @@ static inline void mlxsw_reg_mfsc_pack(c
 #define MLXSW_REG_MFSM_ID 0x9003
 #define MLXSW_REG_MFSM_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mfsm = {
-	.id = MLXSW_REG_MFSM_ID,
-	.len = MLXSW_REG_MFSM_LEN,
-};
+MLXSW_REG_DEFINE(mfsm, MLXSW_REG_MFSM_ID, MLXSW_REG_MFSM_LEN);
 
 /* reg_mfsm_tacho
  * Fan tachometer index.
@@ -4564,6 +4664,54 @@ static inline void mlxsw_reg_mfsm_pack(c
 	mlxsw_reg_mfsm_tacho_set(payload, tacho);
 }
 
+/* MFSL - Management Fan Speed Limit Register
+ * ------------------------------------------
+ * The Fan Speed Limit register is used to configure the fan speed
+ * event / interrupt notification mechanism. Fan speed threshold are
+ * defined for both under-speed and over-speed.
+ */
+#define MLXSW_REG_MFSL_ID 0x9004
+#define MLXSW_REG_MFSL_LEN 0x0C
+
+MLXSW_REG_DEFINE(mfsl, MLXSW_REG_MFSL_ID, MLXSW_REG_MFSL_LEN);
+
+/* reg_mfsl_tacho
+ * Fan tachometer index.
+ * Access: Index
+ */
+MLXSW_ITEM32(reg, mfsl, tacho, 0x00, 24, 4);
+
+/* reg_mfsl_tach_min
+ * Tachometer minimum value (minimum RPM).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mfsl, tach_min, 0x04, 0, 16);
+
+/* reg_mfsl_tach_max
+ * Tachometer maximum value (maximum RPM).
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mfsl, tach_max, 0x08, 0, 16);
+
+static inline void mlxsw_reg_mfsl_pack(char *payload, u8 tacho,
+				       u16 tach_min, u16 tach_max)
+{
+	MLXSW_REG_ZERO(mfsl, payload);
+	mlxsw_reg_mfsl_tacho_set(payload, tacho);
+	mlxsw_reg_mfsl_tach_min_set(payload, tach_min);
+	mlxsw_reg_mfsl_tach_max_set(payload, tach_max);
+}
+
+static inline void mlxsw_reg_mfsl_unpack(char *payload, u8 tacho,
+					 u16 *p_tach_min, u16 *p_tach_max)
+{
+	if (p_tach_min)
+		*p_tach_min = mlxsw_reg_mfsl_tach_min_get(payload);
+
+	if (p_tach_max)
+		*p_tach_max = mlxsw_reg_mfsl_tach_max_get(payload);
+}
+
 /* MTCAP - Management Temperature Capabilities
  * -------------------------------------------
  * This register exposes the capabilities of the device and
@@ -4572,10 +4720,7 @@ static inline void mlxsw_reg_mfsm_pack(c
 #define MLXSW_REG_MTCAP_ID 0x9009
 #define MLXSW_REG_MTCAP_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mtcap = {
-	.id = MLXSW_REG_MTCAP_ID,
-	.len = MLXSW_REG_MTCAP_LEN,
-};
+MLXSW_REG_DEFINE(mtcap, MLXSW_REG_MTCAP_ID, MLXSW_REG_MTCAP_LEN);
 
 /* reg_mtcap_sensor_count
  * Number of sensors supported by the device.
@@ -4593,10 +4738,7 @@ MLXSW_ITEM32(reg, mtcap, sensor_count, 0
 #define MLXSW_REG_MTMP_ID 0x900A
 #define MLXSW_REG_MTMP_LEN 0x20
 
-static const struct mlxsw_reg_info mlxsw_reg_mtmp = {
-	.id = MLXSW_REG_MTMP_ID,
-	.len = MLXSW_REG_MTMP_LEN,
-};
+MLXSW_REG_DEFINE(mtmp, MLXSW_REG_MTMP_ID, MLXSW_REG_MTMP_LEN);
 
 /* reg_mtmp_sensor_index
  * Sensors index to access.
@@ -4679,10 +4821,7 @@ static inline void mlxsw_reg_mtmp_unpack
 #define MLXSW_REG_MPAT_ID 0x901A
 #define MLXSW_REG_MPAT_LEN 0x78
 
-static const struct mlxsw_reg_info mlxsw_reg_mpat = {
-	.id = MLXSW_REG_MPAT_ID,
-	.len = MLXSW_REG_MPAT_LEN,
-};
+MLXSW_REG_DEFINE(mpat, MLXSW_REG_MPAT_ID, MLXSW_REG_MPAT_LEN);
 
 /* reg_mpat_pa_id
  * Port Analyzer ID.
@@ -4742,10 +4881,7 @@ static inline void mlxsw_reg_mpat_pack(c
 #define MLXSW_REG_MPAR_ID 0x901B
 #define MLXSW_REG_MPAR_LEN 0x08
 
-static const struct mlxsw_reg_info mlxsw_reg_mpar = {
-	.id = MLXSW_REG_MPAR_ID,
-	.len = MLXSW_REG_MPAR_LEN,
-};
+MLXSW_REG_DEFINE(mpar, MLXSW_REG_MPAR_ID, MLXSW_REG_MPAR_LEN);
 
 /* reg_mpar_local_port
  * The local port to mirror the packets from.
@@ -4795,10 +4931,7 @@ static inline void mlxsw_reg_mpar_pack(c
 #define MLXSW_REG_MLCR_ID 0x902B
 #define MLXSW_REG_MLCR_LEN 0x0C
 
-static const struct mlxsw_reg_info mlxsw_reg_mlcr = {
-	.id = MLXSW_REG_MLCR_ID,
-	.len = MLXSW_REG_MLCR_LEN,
-};
+MLXSW_REG_DEFINE(mlcr, MLXSW_REG_MLCR_ID, MLXSW_REG_MLCR_LEN);
 
 /* reg_mlcr_local_port
  * Local port number.
@@ -4839,10 +4972,7 @@ static inline void mlxsw_reg_mlcr_pack(c
 #define MLXSW_REG_SBPR_ID 0xB001
 #define MLXSW_REG_SBPR_LEN 0x14
 
-static const struct mlxsw_reg_info mlxsw_reg_sbpr = {
-	.id = MLXSW_REG_SBPR_ID,
-	.len = MLXSW_REG_SBPR_LEN,
-};
+MLXSW_REG_DEFINE(sbpr, MLXSW_REG_SBPR_ID, MLXSW_REG_SBPR_LEN);
 
 /* shared direstion enum for SBPR, SBCM, SBPM */
 enum mlxsw_reg_sbxx_dir {
@@ -4899,10 +5029,7 @@ static inline void mlxsw_reg_sbpr_pack(c
 #define MLXSW_REG_SBCM_ID 0xB002
 #define MLXSW_REG_SBCM_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_sbcm = {
-	.id = MLXSW_REG_SBCM_ID,
-	.len = MLXSW_REG_SBCM_LEN,
-};
+MLXSW_REG_DEFINE(sbcm, MLXSW_REG_SBCM_ID, MLXSW_REG_SBCM_LEN);
 
 /* reg_sbcm_local_port
  * Local port number.
@@ -4979,10 +5106,7 @@ static inline void mlxsw_reg_sbcm_pack(c
 #define MLXSW_REG_SBPM_ID 0xB003
 #define MLXSW_REG_SBPM_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_sbpm = {
-	.id = MLXSW_REG_SBPM_ID,
-	.len = MLXSW_REG_SBPM_LEN,
-};
+MLXSW_REG_DEFINE(sbpm, MLXSW_REG_SBPM_ID, MLXSW_REG_SBPM_LEN);
 
 /* reg_sbpm_local_port
  * Local port number.
@@ -5073,10 +5197,7 @@ static inline void mlxsw_reg_sbpm_unpack
 #define MLXSW_REG_SBMM_ID 0xB004
 #define MLXSW_REG_SBMM_LEN 0x28
 
-static const struct mlxsw_reg_info mlxsw_reg_sbmm = {
-	.id = MLXSW_REG_SBMM_ID,
-	.len = MLXSW_REG_SBMM_LEN,
-};
+MLXSW_REG_DEFINE(sbmm, MLXSW_REG_SBMM_ID, MLXSW_REG_SBMM_LEN);
 
 /* reg_sbmm_prio
  * Switch Priority.
@@ -5135,10 +5256,7 @@ static inline void mlxsw_reg_sbmm_pack(c
 			    MLXSW_REG_SBSR_REC_LEN *	\
 			    MLXSW_REG_SBSR_REC_MAX_COUNT)
 
-static const struct mlxsw_reg_info mlxsw_reg_sbsr = {
-	.id = MLXSW_REG_SBSR_ID,
-	.len = MLXSW_REG_SBSR_LEN,
-};
+MLXSW_REG_DEFINE(sbsr, MLXSW_REG_SBSR_ID, MLXSW_REG_SBSR_LEN);
 
 /* reg_sbsr_clr
  * Clear Max Buffer Occupancy. When this bit is set, the max_buff_occupancy
@@ -5228,10 +5346,7 @@ static inline void mlxsw_reg_sbsr_rec_un
 #define MLXSW_REG_SBIB_ID 0xB006
 #define MLXSW_REG_SBIB_LEN 0x10
 
-static const struct mlxsw_reg_info mlxsw_reg_sbib = {
-	.id = MLXSW_REG_SBIB_ID,
-	.len = MLXSW_REG_SBIB_LEN,
-};
+MLXSW_REG_DEFINE(sbib, MLXSW_REG_SBIB_ID, MLXSW_REG_SBIB_LEN);
 
 /* reg_sbib_local_port
  * Local port number
@@ -5256,132 +5371,83 @@ static inline void mlxsw_reg_sbib_pack(c
 	mlxsw_reg_sbib_buff_size_set(payload, buff_size);
 }
 
+static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
+	MLXSW_REG(sgcr),
+	MLXSW_REG(spad),
+	MLXSW_REG(smid),
+	MLXSW_REG(sspr),
+	MLXSW_REG(sfdat),
+	MLXSW_REG(sfd),
+	MLXSW_REG(sfn),
+	MLXSW_REG(spms),
+	MLXSW_REG(spvid),
+	MLXSW_REG(spvm),
+	MLXSW_REG(spaft),
+	MLXSW_REG(sfgc),
+	MLXSW_REG(sftr),
+	MLXSW_REG(sfdf),
+	MLXSW_REG(sldr),
+	MLXSW_REG(slcr),
+	MLXSW_REG(slcor),
+	MLXSW_REG(spmlr),
+	MLXSW_REG(svfa),
+	MLXSW_REG(svpe),
+	MLXSW_REG(sfmr),
+	MLXSW_REG(spvmlr),
+	MLXSW_REG(qpcr),
+	MLXSW_REG(qtct),
+	MLXSW_REG(qeec),
+	MLXSW_REG(pmlp),
+	MLXSW_REG(pmtu),
+	MLXSW_REG(ptys),
+	MLXSW_REG(ppad),
+	MLXSW_REG(paos),
+	MLXSW_REG(pfcc),
+	MLXSW_REG(ppcnt),
+	MLXSW_REG(plib),
+	MLXSW_REG(pptb),
+	MLXSW_REG(pbmc),
+	MLXSW_REG(pspa),
+	MLXSW_REG(htgt),
+	MLXSW_REG(hpkt),
+	MLXSW_REG(rgcr),
+	MLXSW_REG(ritr),
+	MLXSW_REG(ratr),
+	MLXSW_REG(ralta),
+	MLXSW_REG(ralst),
+	MLXSW_REG(raltb),
+	MLXSW_REG(ralue),
+	MLXSW_REG(rauht),
+	MLXSW_REG(raleu),
+	MLXSW_REG(rauhtd),
+	MLXSW_REG(mfcr),
+	MLXSW_REG(mfsc),
+	MLXSW_REG(mfsm),
+	MLXSW_REG(mfsl),
+	MLXSW_REG(mtcap),
+	MLXSW_REG(mtmp),
+	MLXSW_REG(mpat),
+	MLXSW_REG(mpar),
+	MLXSW_REG(mlcr),
+	MLXSW_REG(sbpr),
+	MLXSW_REG(sbcm),
+	MLXSW_REG(sbpm),
+	MLXSW_REG(sbmm),
+	MLXSW_REG(sbsr),
+	MLXSW_REG(sbib),
+};
+
 static inline const char *mlxsw_reg_id_str(u16 reg_id)
 {
-	switch (reg_id) {
-	case MLXSW_REG_SGCR_ID:
-		return "SGCR";
-	case MLXSW_REG_SPAD_ID:
-		return "SPAD";
-	case MLXSW_REG_SMID_ID:
-		return "SMID";
-	case MLXSW_REG_SSPR_ID:
-		return "SSPR";
-	case MLXSW_REG_SFDAT_ID:
-		return "SFDAT";
-	case MLXSW_REG_SFD_ID:
-		return "SFD";
-	case MLXSW_REG_SFN_ID:
-		return "SFN";
-	case MLXSW_REG_SPMS_ID:
-		return "SPMS";
-	case MLXSW_REG_SPVID_ID:
-		return "SPVID";
-	case MLXSW_REG_SPVM_ID:
-		return "SPVM";
-	case MLXSW_REG_SPAFT_ID:
-		return "SPAFT";
-	case MLXSW_REG_SFGC_ID:
-		return "SFGC";
-	case MLXSW_REG_SFTR_ID:
-		return "SFTR";
-	case MLXSW_REG_SFDF_ID:
-		return "SFDF";
-	case MLXSW_REG_SLDR_ID:
-		return "SLDR";
-	case MLXSW_REG_SLCR_ID:
-		return "SLCR";
-	case MLXSW_REG_SLCOR_ID:
-		return "SLCOR";
-	case MLXSW_REG_SPMLR_ID:
-		return "SPMLR";
-	case MLXSW_REG_SVFA_ID:
-		return "SVFA";
-	case MLXSW_REG_SVPE_ID:
-		return "SVPE";
-	case MLXSW_REG_SFMR_ID:
-		return "SFMR";
-	case MLXSW_REG_SPVMLR_ID:
-		return "SPVMLR";
-	case MLXSW_REG_QTCT_ID:
-		return "QTCT";
-	case MLXSW_REG_QEEC_ID:
-		return "QEEC";
-	case MLXSW_REG_PMLP_ID:
-		return "PMLP";
-	case MLXSW_REG_PMTU_ID:
-		return "PMTU";
-	case MLXSW_REG_PTYS_ID:
-		return "PTYS";
-	case MLXSW_REG_PPAD_ID:
-		return "PPAD";
-	case MLXSW_REG_PAOS_ID:
-		return "PAOS";
-	case MLXSW_REG_PFCC_ID:
-		return "PFCC";
-	case MLXSW_REG_PPCNT_ID:
-		return "PPCNT";
-	case MLXSW_REG_PPTB_ID:
-		return "PPTB";
-	case MLXSW_REG_PBMC_ID:
-		return "PBMC";
-	case MLXSW_REG_PSPA_ID:
-		return "PSPA";
-	case MLXSW_REG_HTGT_ID:
-		return "HTGT";
-	case MLXSW_REG_HPKT_ID:
-		return "HPKT";
-	case MLXSW_REG_RGCR_ID:
-		return "RGCR";
-	case MLXSW_REG_RITR_ID:
-		return "RITR";
-	case MLXSW_REG_RATR_ID:
-		return "RATR";
-	case MLXSW_REG_RALTA_ID:
-		return "RALTA";
-	case MLXSW_REG_RALST_ID:
-		return "RALST";
-	case MLXSW_REG_RALTB_ID:
-		return "RALTB";
-	case MLXSW_REG_RALUE_ID:
-		return "RALUE";
-	case MLXSW_REG_RAUHT_ID:
-		return "RAUHT";
-	case MLXSW_REG_RALEU_ID:
-		return "RALEU";
-	case MLXSW_REG_RAUHTD_ID:
-		return "RAUHTD";
-	case MLXSW_REG_MFCR_ID:
-		return "MFCR";
-	case MLXSW_REG_MFSC_ID:
-		return "MFSC";
-	case MLXSW_REG_MFSM_ID:
-		return "MFSM";
-	case MLXSW_REG_MTCAP_ID:
-		return "MTCAP";
-	case MLXSW_REG_MPAT_ID:
-		return "MPAT";
-	case MLXSW_REG_MPAR_ID:
-		return "MPAR";
-	case MLXSW_REG_MTMP_ID:
-		return "MTMP";
-	case MLXSW_REG_MLCR_ID:
-		return "MLCR";
-	case MLXSW_REG_SBPR_ID:
-		return "SBPR";
-	case MLXSW_REG_SBCM_ID:
-		return "SBCM";
-	case MLXSW_REG_SBPM_ID:
-		return "SBPM";
-	case MLXSW_REG_SBMM_ID:
-		return "SBMM";
-	case MLXSW_REG_SBSR_ID:
-		return "SBSR";
-	case MLXSW_REG_SBIB_ID:
-		return "SBIB";
-	default:
-		return "*UNKNOWN*";
+	const struct mlxsw_reg_info *reg_info;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mlxsw_reg_infos); i++) {
+		reg_info = mlxsw_reg_infos[i];
+		if (reg_info->id == reg_id)
+			return reg_info->name;
 	}
+	return "*UNKNOWN*";
 }
 
 /* PUDE - Port Up / Down Event
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/resources.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/resources.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/resources.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/resources.h	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,127 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/resources.h
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MLXSW_RESOURCES_H
+#define _MLXSW_RESOURCES_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+enum mlxsw_res_id {
+	MLXSW_RES_ID_KVD_SIZE,
+	MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE,
+	MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE,
+	MLXSW_RES_ID_MAX_TRAP_GROUPS,
+	MLXSW_RES_ID_MAX_SPAN,
+	MLXSW_RES_ID_MAX_SYSTEM_PORT,
+	MLXSW_RES_ID_MAX_LAG,
+	MLXSW_RES_ID_MAX_LAG_MEMBERS,
+	MLXSW_RES_ID_MAX_BUFFER_SIZE,
+	MLXSW_RES_ID_MAX_CPU_POLICERS,
+	MLXSW_RES_ID_MAX_VRS,
+	MLXSW_RES_ID_MAX_RIFS,
+
+	/* Internal resources.
+	 * Determined by the SW, not queried from the HW.
+	 */
+	MLXSW_RES_ID_KVD_SINGLE_SIZE,
+	MLXSW_RES_ID_KVD_DOUBLE_SIZE,
+	MLXSW_RES_ID_KVD_LINEAR_SIZE,
+
+	__MLXSW_RES_ID_MAX,
+};
+
+static u16 mlxsw_res_ids[] = {
+	[MLXSW_RES_ID_KVD_SIZE] = 0x1001,
+	[MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002,
+	[MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003,
+	[MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201,
+	[MLXSW_RES_ID_MAX_SPAN] = 0x2420,
+	[MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502,
+	[MLXSW_RES_ID_MAX_LAG] = 0x2520,
+	[MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521,
+	[MLXSW_RES_ID_MAX_BUFFER_SIZE] = 0x2802,	/* Bytes */
+	[MLXSW_RES_ID_MAX_CPU_POLICERS] = 0x2A13,
+	[MLXSW_RES_ID_MAX_VRS] = 0x2C01,
+	[MLXSW_RES_ID_MAX_RIFS] = 0x2C02,
+};
+
+struct mlxsw_res {
+	bool valid[__MLXSW_RES_ID_MAX];
+	u64 values[__MLXSW_RES_ID_MAX];
+};
+
+static inline bool mlxsw_res_valid(struct mlxsw_res *res,
+				   enum mlxsw_res_id res_id)
+{
+	return res->valid[res_id];
+}
+
+#define MLXSW_RES_VALID(res, short_res_id)			\
+	mlxsw_res_valid(res, MLXSW_RES_ID_##short_res_id)
+
+static inline u64 mlxsw_res_get(struct mlxsw_res *res,
+				enum mlxsw_res_id res_id)
+{
+	if (WARN_ON(!res->valid[res_id]))
+		return 0;
+	return res->values[res_id];
+}
+
+#define MLXSW_RES_GET(res, short_res_id)			\
+	mlxsw_res_get(res, MLXSW_RES_ID_##short_res_id)
+
+static inline void mlxsw_res_set(struct mlxsw_res *res,
+				 enum mlxsw_res_id res_id, u64 value)
+{
+	res->valid[res_id] = true;
+	res->values[res_id] = value;
+}
+
+#define MLXSW_RES_SET(res, short_res_id, value)			\
+	mlxsw_res_set(res, MLXSW_RES_ID_##short_res_id, value)
+
+static inline void mlxsw_res_parse(struct mlxsw_res *res, u16 id, u64 value)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mlxsw_res_ids); i++) {
+		if (mlxsw_res_ids[i] == id) {
+			mlxsw_res_set(res, i, value);
+			return;
+		}
+	}
+}
+
+#endif
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_buffers.c	2017-02-12 16:03:20.000000000 -0500
@@ -611,6 +611,9 @@ int mlxsw_sp_sb_pool_set(struct mlxsw_co
 	u32 pool_size = MLXSW_SP_BYTES_TO_CELLS(size);
 	enum mlxsw_reg_sbpr_mode mode;
 
+	if (size > MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_BUFFER_SIZE))
+		return -EINVAL;
+
 	mode = (enum mlxsw_reg_sbpr_mode) threshold_type;
 	return mlxsw_sp_sb_pr_write(mlxsw_sp, pool, dir, mode, pool_size);
 }
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.c	2017-02-12 16:03:20.000000000 -0500
@@ -37,6 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -53,12 +54,12 @@
 #include <linux/dcbnl.h>
 #include <linux/inetdevice.h>
 #include <net/switchdev.h>
-#include <generated/utsrelease.h>
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_mirred.h>
 #include <net/netevent.h>
 
 #include "spectrum.h"
+#include "pci.h"
 #include "core.h"
 #include "reg.h"
 #include "port.h"
@@ -156,7 +157,7 @@ static void mlxsw_sp_txhdr_construct(str
 
 static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
 {
-	char spad_pl[MLXSW_REG_SPAD_LEN];
+	char spad_pl[MLXSW_REG_SPAD_LEN] = {0};
 	int err;
 
 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(spad), spad_pl);
@@ -168,14 +169,13 @@ static int mlxsw_sp_base_mac_get(struct
 
 static int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	if (!resources->max_span_valid)
+	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_SPAN))
 		return -EIO;
 
-	mlxsw_sp->span.entries_count = resources->max_span;
+	mlxsw_sp->span.entries_count = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+							  MAX_SPAN);
 	mlxsw_sp->span.entries = kcalloc(mlxsw_sp->span.entries_count,
 					 sizeof(struct mlxsw_sp_span_entry),
 					 GFP_KERNEL);
@@ -684,6 +684,7 @@ static netdev_tx_t mlxsw_sp_port_xmit(st
 			dev_kfree_skb_any(skb_orig);
 			return NETDEV_TX_OK;
 		}
+		dev_consume_skb_any(skb_orig);
 	}
 
 	if (eth_skb_pad(skb)) {
@@ -857,7 +858,7 @@ mlxsw_sp_port_get_sw_stats64(const struc
 	return 0;
 }
 
-static bool mlxsw_sp_port_has_offload_stats(int attr_id)
+static bool mlxsw_sp_port_has_offload_stats(const struct net_device *dev, int attr_id)
 {
 	switch (attr_id) {
 	case IFLA_OFFLOAD_XSTATS_CPU_HIT:
@@ -1239,8 +1240,10 @@ static int mlxsw_sp_port_add_cls_matchal
 
 	tcf_exts_to_list(cls->exts, &actions);
 	list_for_each_entry(a, &actions, list) {
-		if (!is_tcf_mirred_mirror(a) || protocol != htons(ETH_P_ALL))
+		if (!is_tcf_mirred_egress_mirror(a) ||
+		    protocol != htons(ETH_P_ALL)) {
 			return -ENOTSUPP;
+		}
 
 		err = mlxsw_sp_port_add_cls_matchall_mirror(mlxsw_sp_port, cls,
 							    a, ingress);
@@ -1413,7 +1416,7 @@ err_port_pause_configure:
 
 struct mlxsw_sp_port_hw_stats {
 	char str[ETH_GSTRING_LEN];
-	u64 (*getter)(char *payload);
+	u64 (*getter)(const char *payload);
 };
 
 static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = {
@@ -1534,7 +1537,7 @@ static struct mlxsw_sp_port_hw_stats mlx
 
 #define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats)
 
-static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(char *ppcnt_pl)
+static u64 mlxsw_reg_ppcnt_tc_transmit_queue_bytes_get(const char *ppcnt_pl)
 {
 	u64 transmit_queue = mlxsw_reg_ppcnt_tc_transmit_queue_get(ppcnt_pl);
 
@@ -2002,12 +2005,12 @@ static int mlxsw_sp_port_get_link_ksetti
 	int err;
 
 	autoneg = mlxsw_sp_port->link.autoneg;
-	mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
+	mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
 	if (err)
 		return err;
-	mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
-			      &eth_proto_oper);
+	mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, &eth_proto_admin,
+				  &eth_proto_oper);
 
 	mlxsw_sp_port_get_link_supported(eth_proto_cap, cmd);
 
@@ -2036,11 +2039,11 @@ mlxsw_sp_port_set_link_ksettings(struct
 	bool autoneg;
 	int err;
 
-	mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
+	mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port, 0);
 	err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
 	if (err)
 		return err;
-	mlxsw_reg_ptys_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
+	mlxsw_reg_ptys_eth_unpack(ptys_pl, &eth_proto_cap, NULL, NULL);
 
 	autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
 	eth_proto_new = autoneg ?
@@ -2053,7 +2056,8 @@ mlxsw_sp_port_set_link_ksettings(struct
 		return -EINVAL;
 	}
 
-	mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port, eth_proto_new);
+	mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port,
+				eth_proto_new);
 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
 	if (err)
 		return err;
@@ -2091,8 +2095,8 @@ mlxsw_sp_port_speed_by_width_set(struct
 	u32 eth_proto_admin;
 
 	eth_proto_admin = mlxsw_sp_to_ptys_upper_speed(upper_speed);
-	mlxsw_reg_ptys_pack(ptys_pl, mlxsw_sp_port->local_port,
-			    eth_proto_admin);
+	mlxsw_reg_ptys_eth_pack(ptys_pl, mlxsw_sp_port->local_port,
+				eth_proto_admin);
 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
 }
 
@@ -2210,8 +2214,8 @@ static int mlxsw_sp_port_pvid_vport_dest
 	return mlxsw_sp_port_kill_vid(mlxsw_sp_port->dev, 0, 1);
 }
 
-static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
-				bool split, u8 module, u8 width, u8 lane)
+static int __mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+				  bool split, u8 module, u8 width, u8 lane)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port;
 	struct net_device *dev;
@@ -2221,6 +2225,7 @@ static int mlxsw_sp_port_create(struct m
 	dev = alloc_etherdev(sizeof(struct mlxsw_sp_port));
 	if (!dev)
 		return -ENOMEM;
+	SET_NETDEV_DEV(dev, mlxsw_sp->bus_info->dev);
 	mlxsw_sp_port = netdev_priv(dev);
 	mlxsw_sp_port->dev = dev;
 	mlxsw_sp_port->mlxsw_sp = mlxsw_sp;
@@ -2284,6 +2289,9 @@ static int mlxsw_sp_port_create(struct m
 			 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_TC;
 	dev->hw_features |= NETIF_F_HW_TC;
 
+	dev->min_mtu = 0;
+	dev->max_mtu = ETH_MAX_MTU;
+
 	/* Each packet needs to have a Tx header (metadata) on top all other
 	 * headers.
 	 */
@@ -2352,20 +2360,12 @@ static int mlxsw_sp_port_create(struct m
 		goto err_register_netdev;
 	}
 
-	err = mlxsw_core_port_init(mlxsw_sp->core, &mlxsw_sp_port->core_port,
-				   mlxsw_sp_port->local_port, dev,
-				   mlxsw_sp_port->split, module);
-	if (err) {
-		dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
-			mlxsw_sp_port->local_port);
-		goto err_core_port_init;
-	}
-
+	mlxsw_core_port_eth_set(mlxsw_sp->core, mlxsw_sp_port->local_port,
+				mlxsw_sp_port, dev, mlxsw_sp_port->split,
+				module);
 	mlxsw_core_schedule_dw(&mlxsw_sp_port->hw_stats.update_dw, 0);
 	return 0;
 
-err_core_port_init:
-	unregister_netdev(dev);
 err_register_netdev:
 	mlxsw_sp->ports[local_port] = NULL;
 	mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
@@ -2394,14 +2394,34 @@ err_port_active_vlans_alloc:
 	return err;
 }
 
-static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
+				bool split, u8 module, u8 width, u8 lane)
+{
+	int err;
+
+	err = mlxsw_core_port_init(mlxsw_sp->core, local_port);
+	if (err) {
+		dev_err(mlxsw_sp->bus_info->dev, "Port %d: Failed to init core port\n",
+			local_port);
+		return err;
+	}
+	err = __mlxsw_sp_port_create(mlxsw_sp, local_port, split,
+				     module, width, lane);
+	if (err)
+		goto err_port_create;
+	return 0;
+
+err_port_create:
+	mlxsw_core_port_fini(mlxsw_sp->core, local_port);
+	return err;
+}
+
+static void __mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
 
-	if (!mlxsw_sp_port)
-		return;
 	cancel_delayed_work_sync(&mlxsw_sp_port->hw_stats.update_dw);
-	mlxsw_core_port_fini(&mlxsw_sp_port->core_port);
+	mlxsw_core_port_clear(mlxsw_sp->core, local_port, mlxsw_sp);
 	unregister_netdev(mlxsw_sp_port->dev); /* This calls ndo_stop */
 	mlxsw_sp->ports[local_port] = NULL;
 	mlxsw_sp_port_switchdev_fini(mlxsw_sp_port);
@@ -2417,12 +2437,24 @@ static void mlxsw_sp_port_remove(struct
 	free_netdev(mlxsw_sp_port->dev);
 }
 
+static void mlxsw_sp_port_remove(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+{
+	__mlxsw_sp_port_remove(mlxsw_sp, local_port);
+	mlxsw_core_port_fini(mlxsw_sp->core, local_port);
+}
+
+static bool mlxsw_sp_port_created(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+{
+	return mlxsw_sp->ports[local_port] != NULL;
+}
+
 static void mlxsw_sp_ports_remove(struct mlxsw_sp *mlxsw_sp)
 {
 	int i;
 
 	for (i = 1; i < MLXSW_PORT_MAX_PORTS; i++)
-		mlxsw_sp_port_remove(mlxsw_sp, i);
+		if (mlxsw_sp_port_created(mlxsw_sp, i))
+			mlxsw_sp_port_remove(mlxsw_sp, i);
 	kfree(mlxsw_sp->ports);
 }
 
@@ -2446,8 +2478,8 @@ static int mlxsw_sp_ports_create(struct
 		if (!width)
 			continue;
 		mlxsw_sp->port_to_module[i] = module;
-		err = mlxsw_sp_port_create(mlxsw_sp, i, false, module, width,
-					   lane);
+		err = mlxsw_sp_port_create(mlxsw_sp, i, false,
+					   module, width, lane);
 		if (err)
 			goto err_port_create;
 	}
@@ -2456,7 +2488,8 @@ static int mlxsw_sp_ports_create(struct
 err_port_create:
 err_port_module_info_get:
 	for (i--; i >= 1; i--)
-		mlxsw_sp_port_remove(mlxsw_sp, i);
+		if (mlxsw_sp_port_created(mlxsw_sp, i))
+			mlxsw_sp_port_remove(mlxsw_sp, i);
 	kfree(mlxsw_sp->ports);
 	return err;
 }
@@ -2498,7 +2531,8 @@ static int mlxsw_sp_port_split_create(st
 
 err_port_create:
 	for (i--; i >= 0; i--)
-		mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+		if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
+			mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
 	i = count;
 err_port_swid_set:
 	for (i--; i >= 0; i--)
@@ -2588,7 +2622,8 @@ static int mlxsw_sp_port_split(struct ml
 	}
 
 	for (i = 0; i < count; i++)
-		mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+		if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
+			mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
 
 	err = mlxsw_sp_port_split_create(mlxsw_sp, base_port, module, count);
 	if (err) {
@@ -2633,7 +2668,8 @@ static int mlxsw_sp_port_unsplit(struct
 		base_port = base_port + 2;
 
 	for (i = 0; i < count; i++)
-		mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
+		if (mlxsw_sp_port_created(mlxsw_sp, base_port + i))
+			mlxsw_sp_port_remove(mlxsw_sp, base_port + i);
 
 	mlxsw_sp_port_unsplit_create(mlxsw_sp, base_port, count);
 
@@ -2663,54 +2699,8 @@ static void mlxsw_sp_pude_event_func(con
 	}
 }
 
-static struct mlxsw_event_listener mlxsw_sp_pude_event = {
-	.func = mlxsw_sp_pude_event_func,
-	.trap_id = MLXSW_TRAP_ID_PUDE,
-};
-
-static int mlxsw_sp_event_register(struct mlxsw_sp *mlxsw_sp,
-				   enum mlxsw_event_trap_id trap_id)
-{
-	struct mlxsw_event_listener *el;
-	char hpkt_pl[MLXSW_REG_HPKT_LEN];
-	int err;
-
-	switch (trap_id) {
-	case MLXSW_TRAP_ID_PUDE:
-		el = &mlxsw_sp_pude_event;
-		break;
-	}
-	err = mlxsw_core_event_listener_register(mlxsw_sp->core, el, mlxsw_sp);
-	if (err)
-		return err;
-
-	mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_FORWARD, trap_id);
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
-	if (err)
-		goto err_event_trap_set;
-
-	return 0;
-
-err_event_trap_set:
-	mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp);
-	return err;
-}
-
-static void mlxsw_sp_event_unregister(struct mlxsw_sp *mlxsw_sp,
-				      enum mlxsw_event_trap_id trap_id)
-{
-	struct mlxsw_event_listener *el;
-
-	switch (trap_id) {
-	case MLXSW_TRAP_ID_PUDE:
-		el = &mlxsw_sp_pude_event;
-		break;
-	}
-	mlxsw_core_event_listener_unregister(mlxsw_sp->core, el, mlxsw_sp);
-}
-
-static void mlxsw_sp_rx_listener_func(struct sk_buff *skb, u8 local_port,
-				      void *priv)
+static void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
+					      u8 local_port, void *priv)
 {
 	struct mlxsw_sp *mlxsw_sp = priv;
 	struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp->ports[local_port];
@@ -2738,107 +2728,212 @@ static void mlxsw_sp_rx_listener_mark_fu
 					   void *priv)
 {
 	skb->offload_fwd_mark = 1;
-	return mlxsw_sp_rx_listener_func(skb, local_port, priv);
+	return mlxsw_sp_rx_listener_no_mark_func(skb, local_port, priv);
 }
 
-#define MLXSW_SP_RXL(_func, _trap_id, _action)			\
-	{							\
-		.func = _func,					\
-		.local_port = MLXSW_PORT_DONT_CARE,		\
-		.trap_id = MLXSW_TRAP_ID_##_trap_id,		\
-		.action = MLXSW_REG_HPKT_ACTION_##_action,	\
-	}
+#define MLXSW_SP_RXL_NO_MARK(_trap_id, _action, _trap_group, _is_ctrl)	\
+	MLXSW_RXL(mlxsw_sp_rx_listener_no_mark_func, _trap_id, _action,	\
+		  _is_ctrl, SP_##_trap_group, DISCARD)
 
-static const struct mlxsw_rx_listener mlxsw_sp_rx_listener[] = {
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, FDB_MC, TRAP_TO_CPU),
-	/* Traps for specific L2 packet types, not trapped as FDB MC */
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, STP, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LACP, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, EAPOL, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LLDP, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MMRP, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MVRP, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, RPVST, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, DHCP, MIRROR_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, IGMP_QUERY, MIRROR_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V1_REPORT, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V2_REPORT, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V2_LEAVE, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IGMP_V3_REPORT, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, ARPBC, MIRROR_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, ARPUC, MIRROR_TO_CPU),
+#define MLXSW_SP_RXL_MARK(_trap_id, _action, _trap_group, _is_ctrl)	\
+	MLXSW_RXL(mlxsw_sp_rx_listener_mark_func, _trap_id, _action,	\
+		_is_ctrl, SP_##_trap_group, DISCARD)
+
+#define MLXSW_SP_EVENTL(_func, _trap_id)		\
+	MLXSW_EVENTL(_func, _trap_id, SP_EVENT)
+
+static const struct mlxsw_listener mlxsw_sp_listener[] = {
+	/* Events */
+	MLXSW_SP_EVENTL(mlxsw_sp_pude_event_func, PUDE),
+	/* L2 traps */
+	MLXSW_SP_RXL_NO_MARK(STP, TRAP_TO_CPU, STP, true),
+	MLXSW_SP_RXL_NO_MARK(LACP, TRAP_TO_CPU, LACP, true),
+	MLXSW_SP_RXL_NO_MARK(LLDP, TRAP_TO_CPU, LLDP, true),
+	MLXSW_SP_RXL_MARK(DHCP, MIRROR_TO_CPU, DHCP, false),
+	MLXSW_SP_RXL_MARK(IGMP_QUERY, MIRROR_TO_CPU, IGMP, false),
+	MLXSW_SP_RXL_NO_MARK(IGMP_V1_REPORT, TRAP_TO_CPU, IGMP, false),
+	MLXSW_SP_RXL_NO_MARK(IGMP_V2_REPORT, TRAP_TO_CPU, IGMP, false),
+	MLXSW_SP_RXL_NO_MARK(IGMP_V2_LEAVE, TRAP_TO_CPU, IGMP, false),
+	MLXSW_SP_RXL_NO_MARK(IGMP_V3_REPORT, TRAP_TO_CPU, IGMP, false),
+	MLXSW_SP_RXL_MARK(ARPBC, MIRROR_TO_CPU, ARP, false),
+	MLXSW_SP_RXL_MARK(ARPUC, MIRROR_TO_CPU, ARP, false),
 	/* L3 traps */
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, MTUERROR, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, TTLERROR, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, LBERROR, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_mark_func, OSPF, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, IP2ME, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, RTR_INGRESS0, TRAP_TO_CPU),
-	MLXSW_SP_RXL(mlxsw_sp_rx_listener_func, HOST_MISS_IPV4, TRAP_TO_CPU),
+	MLXSW_SP_RXL_NO_MARK(MTUERROR, TRAP_TO_CPU, ROUTER_EXP, false),
+	MLXSW_SP_RXL_NO_MARK(TTLERROR, TRAP_TO_CPU, ROUTER_EXP, false),
+	MLXSW_SP_RXL_NO_MARK(LBERROR, TRAP_TO_CPU, ROUTER_EXP, false),
+	MLXSW_SP_RXL_MARK(OSPF, TRAP_TO_CPU, OSPF, false),
+	MLXSW_SP_RXL_NO_MARK(IP2ME, TRAP_TO_CPU, IP2ME, false),
+	MLXSW_SP_RXL_NO_MARK(RTR_INGRESS0, TRAP_TO_CPU, REMOTE_ROUTE, false),
+	MLXSW_SP_RXL_NO_MARK(HOST_MISS_IPV4, TRAP_TO_CPU, ARP_MISS, false),
+	MLXSW_SP_RXL_NO_MARK(BGP_IPV4, TRAP_TO_CPU, BGP_IPV4, false),
 };
 
-static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
+static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
+{
+	char qpcr_pl[MLXSW_REG_QPCR_LEN];
+	enum mlxsw_reg_qpcr_ir_units ir_units;
+	int max_cpu_policers;
+	bool is_bytes;
+	u8 burst_size;
+	u32 rate;
+	int i, err;
+
+	if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS))
+		return -EIO;
+
+	max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
+
+	ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
+	for (i = 0; i < max_cpu_policers; i++) {
+		is_bytes = false;
+		switch (i) {
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
+			rate = 128;
+			burst_size = 7;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
+			rate = 16 * 1024;
+			burst_size = 10;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
+			rate = 1024;
+			burst_size = 7;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
+			is_bytes = true;
+			rate = 4 * 1024;
+			burst_size = 4;
+			break;
+		default:
+			continue;
+		}
+
+		mlxsw_reg_qpcr_pack(qpcr_pl, i, ir_units, is_bytes, rate,
+				    burst_size);
+		err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(qpcr), qpcr_pl);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
 {
 	char htgt_pl[MLXSW_REG_HTGT_LEN];
-	char hpkt_pl[MLXSW_REG_HPKT_LEN];
+	enum mlxsw_reg_htgt_trap_group i;
+	int max_cpu_policers;
+	int max_trap_groups;
+	u8 priority, tc;
+	u16 policer_id;
+	int err;
+
+	if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_TRAP_GROUPS))
+		return -EIO;
+
+	max_trap_groups = MLXSW_CORE_RES_GET(mlxsw_core, MAX_TRAP_GROUPS);
+	max_cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
+
+	for (i = 0; i < max_trap_groups; i++) {
+		policer_id = i;
+		switch (i) {
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_STP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
+			priority = 5;
+			tc = 5;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_BGP_IPV4:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_DHCP:
+			priority = 4;
+			tc = 4;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IGMP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME:
+			priority = 3;
+			tc = 3;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP:
+			priority = 2;
+			tc = 2;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ARP_MISS:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_ROUTER_EXP:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_REMOTE_ROUTE:
+			priority = 1;
+			tc = 1;
+			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_EVENT:
+			priority = MLXSW_REG_HTGT_DEFAULT_PRIORITY;
+			tc = MLXSW_REG_HTGT_DEFAULT_TC;
+			policer_id = MLXSW_REG_HTGT_INVALID_POLICER;
+			break;
+		default:
+			continue;
+		}
+
+		if (max_cpu_policers <= policer_id &&
+		    policer_id != MLXSW_REG_HTGT_INVALID_POLICER)
+			return -EIO;
+
+		mlxsw_reg_htgt_pack(htgt_pl, i, policer_id, priority, tc);
+		err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int mlxsw_sp_traps_init(struct mlxsw_sp *mlxsw_sp)
+{
 	int i;
 	int err;
 
-	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_RX);
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
+	err = mlxsw_sp_cpu_policers_set(mlxsw_sp->core);
 	if (err)
 		return err;
 
-	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_CTRL);
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(htgt), htgt_pl);
+	err = mlxsw_sp_trap_groups_set(mlxsw_sp->core);
 	if (err)
 		return err;
 
-	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) {
-		err = mlxsw_core_rx_listener_register(mlxsw_sp->core,
-						      &mlxsw_sp_rx_listener[i],
-						      mlxsw_sp);
+	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) {
+		err = mlxsw_core_trap_register(mlxsw_sp->core,
+					       &mlxsw_sp_listener[i],
+					       mlxsw_sp);
 		if (err)
-			goto err_rx_listener_register;
+			goto err_listener_register;
 
-		mlxsw_reg_hpkt_pack(hpkt_pl, mlxsw_sp_rx_listener[i].action,
-				    mlxsw_sp_rx_listener[i].trap_id);
-		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
-		if (err)
-			goto err_rx_trap_set;
 	}
 	return 0;
 
-err_rx_trap_set:
-	mlxsw_core_rx_listener_unregister(mlxsw_sp->core,
-					  &mlxsw_sp_rx_listener[i],
-					  mlxsw_sp);
-err_rx_listener_register:
+err_listener_register:
 	for (i--; i >= 0; i--) {
-		mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD,
-				    mlxsw_sp_rx_listener[i].trap_id);
-		mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
-
-		mlxsw_core_rx_listener_unregister(mlxsw_sp->core,
-						  &mlxsw_sp_rx_listener[i],
-						  mlxsw_sp);
+		mlxsw_core_trap_unregister(mlxsw_sp->core,
+					   &mlxsw_sp_listener[i],
+					   mlxsw_sp);
 	}
 	return err;
 }
 
 static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
 {
-	char hpkt_pl[MLXSW_REG_HPKT_LEN];
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_rx_listener); i++) {
-		mlxsw_reg_hpkt_pack(hpkt_pl, MLXSW_REG_HPKT_ACTION_DISCARD,
-				    mlxsw_sp_rx_listener[i].trap_id);
-		mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(hpkt), hpkt_pl);
-
-		mlxsw_core_rx_listener_unregister(mlxsw_sp->core,
-						  &mlxsw_sp_rx_listener[i],
-						  mlxsw_sp);
+	for (i = 0; i < ARRAY_SIZE(mlxsw_sp_listener); i++) {
+		mlxsw_core_trap_unregister(mlxsw_sp->core,
+					   &mlxsw_sp_listener[i],
+					   mlxsw_sp);
 	}
 }
 
@@ -2889,7 +2984,6 @@ static int mlxsw_sp_flood_init(struct ml
 
 static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	char slcr_pl[MLXSW_REG_SLCR_LEN];
 	int err;
 
@@ -2906,11 +3000,11 @@ static int mlxsw_sp_lag_init(struct mlxs
 	if (err)
 		return err;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	if (!(resources->max_lag_valid && resources->max_ports_in_lag_valid))
+	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) ||
+	    !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
 		return -EIO;
 
-	mlxsw_sp->lags = kcalloc(resources->max_lag,
+	mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG),
 				 sizeof(struct mlxsw_sp_upper),
 				 GFP_KERNEL);
 	if (!mlxsw_sp->lags)
@@ -2924,6 +3018,17 @@ static void mlxsw_sp_lag_fini(struct mlx
 	kfree(mlxsw_sp->lags);
 }
 
+static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
+{
+	char htgt_pl[MLXSW_REG_HTGT_LEN];
+
+	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
+			    MLXSW_REG_HTGT_INVALID_POLICER,
+			    MLXSW_REG_HTGT_DEFAULT_PRIORITY,
+			    MLXSW_REG_HTGT_DEFAULT_TC);
+	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
+}
+
 static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 			 const struct mlxsw_bus_info *mlxsw_bus_info)
 {
@@ -2942,16 +3047,10 @@ static int mlxsw_sp_init(struct mlxsw_co
 		return err;
 	}
 
-	err = mlxsw_sp_event_register(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
-	if (err) {
-		dev_err(mlxsw_sp->bus_info->dev, "Failed to register for PUDE events\n");
-		return err;
-	}
-
 	err = mlxsw_sp_traps_init(mlxsw_sp);
 	if (err) {
-		dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps for RX\n");
-		goto err_rx_listener_register;
+		dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps\n");
+		return err;
 	}
 
 	err = mlxsw_sp_flood_init(mlxsw_sp);
@@ -3011,8 +3110,6 @@ err_lag_init:
 err_buffers_init:
 err_flood_init:
 	mlxsw_sp_traps_fini(mlxsw_sp);
-err_rx_listener_register:
-	mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
 	return err;
 }
 
@@ -3027,7 +3124,6 @@ static void mlxsw_sp_fini(struct mlxsw_c
 	mlxsw_sp_lag_fini(mlxsw_sp);
 	mlxsw_sp_buffers_fini(mlxsw_sp);
 	mlxsw_sp_traps_fini(mlxsw_sp);
-	mlxsw_sp_event_unregister(mlxsw_sp, MLXSW_TRAP_ID_PUDE);
 	WARN_ON(!list_empty(&mlxsw_sp->vfids.list));
 	WARN_ON(!list_empty(&mlxsw_sp->fids));
 }
@@ -3065,11 +3161,11 @@ static struct mlxsw_config_profile mlxsw
 };
 
 static struct mlxsw_driver mlxsw_sp_driver = {
-	.kind				= MLXSW_DEVICE_KIND_SPECTRUM,
-	.owner				= THIS_MODULE,
+	.kind				= mlxsw_sp_driver_name,
 	.priv_size			= sizeof(struct mlxsw_sp),
 	.init				= mlxsw_sp_init,
 	.fini				= mlxsw_sp_fini,
+	.basic_trap_groups_set		= mlxsw_sp_basic_trap_groups_set,
 	.port_split			= mlxsw_sp_port_split,
 	.port_unsplit			= mlxsw_sp_port_unsplit,
 	.sb_pool_get			= mlxsw_sp_sb_pool_get,
@@ -3092,19 +3188,30 @@ static bool mlxsw_sp_port_dev_check(cons
 	return dev->netdev_ops == &mlxsw_sp_port_netdev_ops;
 }
 
+static int mlxsw_lower_dev_walk(struct net_device *lower_dev, void *data)
+{
+	struct mlxsw_sp_port **port = data;
+	int ret = 0;
+
+	if (mlxsw_sp_port_dev_check(lower_dev)) {
+		*port = netdev_priv(lower_dev);
+		ret = 1;
+	}
+
+	return ret;
+}
+
 static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev)
 {
-	struct net_device *lower_dev;
-	struct list_head *iter;
+	struct mlxsw_sp_port *port;
 
 	if (mlxsw_sp_port_dev_check(dev))
 		return netdev_priv(dev);
 
-	netdev_for_each_all_lower_dev(dev, lower_dev, iter) {
-		if (mlxsw_sp_port_dev_check(lower_dev))
-			return netdev_priv(lower_dev);
-	}
-	return NULL;
+	port = NULL;
+	netdev_walk_all_lower_dev(dev, mlxsw_lower_dev_walk, &port);
+
+	return port;
 }
 
 static struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev)
@@ -3117,17 +3224,15 @@ static struct mlxsw_sp *mlxsw_sp_lower_g
 
 static struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find_rcu(struct net_device *dev)
 {
-	struct net_device *lower_dev;
-	struct list_head *iter;
+	struct mlxsw_sp_port *port;
 
 	if (mlxsw_sp_port_dev_check(dev))
 		return netdev_priv(dev);
 
-	netdev_for_each_all_lower_dev_rcu(dev, lower_dev, iter) {
-		if (mlxsw_sp_port_dev_check(lower_dev))
-			return netdev_priv(lower_dev);
-	}
-	return NULL;
+	port = NULL;
+	netdev_walk_all_lower_dev_rcu(dev, mlxsw_lower_dev_walk, &port);
+
+	return port;
 }
 
 struct mlxsw_sp_port *mlxsw_sp_port_lower_dev_hold(struct net_device *dev)
@@ -3171,11 +3276,9 @@ static bool mlxsw_sp_rif_should_config(s
 
 static int mlxsw_sp_avail_rif_get(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_rif; i++)
+	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
 		if (!mlxsw_sp->rifs[i])
 			return i;
 
@@ -3698,14 +3801,15 @@ static bool mlxsw_sp_port_fdb_should_flu
 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 	u8 local_port = mlxsw_sp_port->local_port;
 	u16 lag_id = mlxsw_sp_port->lag_id;
-	struct mlxsw_resources *resources;
+	u64 max_lag_members;
 	int i, count = 0;
 
 	if (!mlxsw_sp_port->lagged)
 		return true;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_ports_in_lag; i++) {
+	max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+					     MAX_LAG_MEMBERS);
+	for (i = 0; i < max_lag_members; i++) {
 		struct mlxsw_sp_port *lag_port;
 
 		lag_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
@@ -3911,13 +4015,13 @@ static int mlxsw_sp_lag_index_get(struct
 				  struct net_device *lag_dev,
 				  u16 *p_lag_id)
 {
-	struct mlxsw_resources *resources;
 	struct mlxsw_sp_upper *lag;
 	int free_lag_id = -1;
+	u64 max_lag;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_lag; i++) {
+	max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG);
+	for (i = 0; i < max_lag; i++) {
 		lag = mlxsw_sp_lag_get(mlxsw_sp, i);
 		if (lag->ref_count) {
 			if (lag->dev == lag_dev) {
@@ -3951,11 +4055,12 @@ mlxsw_sp_master_lag_check(struct mlxsw_s
 static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp,
 				       u16 lag_id, u8 *p_port_index)
 {
-	struct mlxsw_resources *resources;
+	u64 max_lag_members;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_ports_in_lag; i++) {
+	max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+					     MAX_LAG_MEMBERS);
+	for (i = 0; i < max_lag_members; i++) {
 		if (!mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i)) {
 			*p_port_index = i;
 			return 0;
@@ -4652,6 +4757,16 @@ static struct notifier_block mlxsw_sp_ro
 	.notifier_call = mlxsw_sp_router_netevent_event,
 };
 
+static const struct pci_device_id mlxsw_sp_pci_id_table[] = {
+	{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0},
+	{0, },
+};
+
+static struct pci_driver mlxsw_sp_pci_driver = {
+	.name = mlxsw_sp_driver_name,
+	.id_table = mlxsw_sp_pci_id_table,
+};
+
 static int __init mlxsw_sp_module_init(void)
 {
 	int err;
@@ -4663,8 +4778,15 @@ static int __init mlxsw_sp_module_init(v
 	err = mlxsw_core_driver_register(&mlxsw_sp_driver);
 	if (err)
 		goto err_core_driver_register;
+
+	err = mlxsw_pci_driver_register(&mlxsw_sp_pci_driver);
+	if (err)
+		goto err_pci_driver_register;
+
 	return 0;
 
+err_pci_driver_register:
+	mlxsw_core_driver_unregister(&mlxsw_sp_driver);
 err_core_driver_register:
 	unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
 	unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
@@ -4674,6 +4796,7 @@ err_core_driver_register:
 
 static void __exit mlxsw_sp_module_exit(void)
 {
+	mlxsw_pci_driver_unregister(&mlxsw_sp_pci_driver);
 	mlxsw_core_driver_unregister(&mlxsw_sp_driver);
 	unregister_netevent_notifier(&mlxsw_sp_router_netevent_nb);
 	unregister_inetaddr_notifier(&mlxsw_sp_inetaddr_nb);
@@ -4686,4 +4809,4 @@ module_exit(mlxsw_sp_module_exit);
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox Spectrum driver");
-MODULE_MLXSW_DRIVER_ALIAS(MLXSW_DEVICE_KIND_SPECTRUM);
+MODULE_DEVICE_TABLE(pci, mlxsw_sp_pci_id_table);
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.h linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.h	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum.h	2017-02-12 16:03:20.000000000 -0500
@@ -316,7 +316,6 @@ struct mlxsw_sp_port_pcpu_stats {
 };
 
 struct mlxsw_sp_port {
-	struct mlxsw_core_port core_port; /* must be first */
 	struct net_device *dev;
 	struct mlxsw_sp_port_pcpu_stats __percpu *pcpu_stats;
 	struct mlxsw_sp *mlxsw_sp;
@@ -479,12 +478,9 @@ static inline struct mlxsw_sp_rif *
 mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp,
 			 const struct net_device *dev)
 {
-	struct mlxsw_resources *resources;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-
-	for (i = 0; i < resources->max_rif; i++)
+	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
 		if (mlxsw_sp->rifs[i] && mlxsw_sp->rifs[i]->dev == dev)
 			return mlxsw_sp->rifs[i];
 
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c	2017-02-12 16:03:20.000000000 -0500
@@ -382,12 +382,10 @@ static void mlxsw_sp_lpm_init(struct mlx
 
 static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	struct mlxsw_sp_vr *vr;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_virtual_routers; i++) {
+	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
 		vr = &mlxsw_sp->router.vrs[i];
 		if (!vr->used)
 			return vr;
@@ -429,14 +427,12 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_f
 					    u32 tb_id,
 					    enum mlxsw_sp_l3proto proto)
 {
-	struct mlxsw_resources *resources;
 	struct mlxsw_sp_vr *vr;
 	int i;
 
 	tb_id = mlxsw_sp_fix_tb_id(tb_id);
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_virtual_routers; i++) {
+	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
 		vr = &mlxsw_sp->router.vrs[i];
 		if (vr->used && vr->proto == proto && vr->tb_id == tb_id)
 			return vr;
@@ -572,21 +568,20 @@ static void mlxsw_sp_vr_put(struct mlxsw
 
 static int mlxsw_sp_vrs_init(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	struct mlxsw_sp_vr *vr;
+	u64 max_vrs;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	if (!resources->max_virtual_routers_valid)
+	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_VRS))
 		return -EIO;
 
-	mlxsw_sp->router.vrs = kcalloc(resources->max_virtual_routers,
-				       sizeof(struct mlxsw_sp_vr),
+	max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS);
+	mlxsw_sp->router.vrs = kcalloc(max_vrs, sizeof(struct mlxsw_sp_vr),
 				       GFP_KERNEL);
 	if (!mlxsw_sp->router.vrs)
 		return -ENOMEM;
 
-	for (i = 0; i < resources->max_virtual_routers; i++) {
+	for (i = 0; i < max_vrs; i++) {
 		vr = &mlxsw_sp->router.vrs[i];
 		vr->id = i;
 	}
@@ -598,6 +593,14 @@ static void mlxsw_sp_router_fib_flush(st
 
 static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
 {
+	/* At this stage we're guaranteed not to have new incoming
+	 * FIB notifications and the work queue is free from FIBs
+	 * sitting on top of mlxsw netdevs. However, we can still
+	 * have other FIBs queued. Flush the queue before flushing
+	 * the device's tables. No need for locks, as we're the only
+	 * writer.
+	 */
+	mlxsw_core_flush_owq();
 	mlxsw_sp_router_fib_flush(mlxsw_sp);
 	kfree(mlxsw_sp->router.vrs);
 }
@@ -939,7 +942,7 @@ static void mlxsw_sp_router_neigh_update
 	char rauht_pl[MLXSW_REG_RAUHT_LEN];
 	struct net_device *dev;
 	bool entry_connected;
-	u8 nud_state;
+	u8 nud_state, dead;
 	bool updating;
 	bool removing;
 	bool adding;
@@ -950,10 +953,11 @@ static void mlxsw_sp_router_neigh_update
 	dip = ntohl(*((__be32 *) n->primary_key));
 	memcpy(neigh_entry->ha, n->ha, sizeof(neigh_entry->ha));
 	nud_state = n->nud_state;
+	dead = n->dead;
 	dev = n->dev;
 	read_unlock_bh(&n->lock);
 
-	entry_connected = nud_state & NUD_VALID;
+	entry_connected = nud_state & NUD_VALID && !dead;
 	adding = (!neigh_entry->offloaded) && entry_connected;
 	updating = neigh_entry->offloaded && entry_connected;
 	removing = neigh_entry->offloaded && !entry_connected;
@@ -1168,7 +1172,8 @@ static int mlxsw_sp_nexthop_mac_update(s
 
 static int
 mlxsw_sp_nexthop_group_mac_update(struct mlxsw_sp *mlxsw_sp,
-				  struct mlxsw_sp_nexthop_group *nh_grp)
+				  struct mlxsw_sp_nexthop_group *nh_grp,
+				  bool reallocate)
 {
 	u32 adj_index = nh_grp->adj_index; /* base */
 	struct mlxsw_sp_nexthop *nh;
@@ -1183,7 +1188,7 @@ mlxsw_sp_nexthop_group_mac_update(struct
 			continue;
 		}
 
-		if (nh->update) {
+		if (nh->update || reallocate) {
 			err = mlxsw_sp_nexthop_mac_update(mlxsw_sp,
 							  adj_index, nh);
 			if (err)
@@ -1244,7 +1249,8 @@ mlxsw_sp_nexthop_group_refresh(struct ml
 		/* Nothing was added or removed, so no need to reallocate. Just
 		 * update MAC on existing adjacency indexes.
 		 */
-		err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+		err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp,
+							false);
 		if (err) {
 			dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
 			goto set_trap;
@@ -1272,7 +1278,7 @@ mlxsw_sp_nexthop_group_refresh(struct ml
 	nh_grp->adj_index_valid = 1;
 	nh_grp->adj_index = adj_index;
 	nh_grp->ecmp_size = ecmp_size;
-	err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+	err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp, true);
 	if (err) {
 		dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
 		goto set_trap;
@@ -1348,7 +1354,7 @@ static int mlxsw_sp_nexthop_init(struct
 	struct mlxsw_sp_neigh_entry *neigh_entry;
 	struct net_device *dev = fib_nh->nh_dev;
 	struct neighbour *n;
-	u8 nud_state;
+	u8 nud_state, dead;
 
 	/* Take a reference of neigh here ensuring that neigh would
 	 * not be detructed before the nexthop entry is finished.
@@ -1380,8 +1386,9 @@ static int mlxsw_sp_nexthop_init(struct
 	list_add_tail(&nh->neigh_list_node, &neigh_entry->nexthop_list);
 	read_lock_bh(&n->lock);
 	nud_state = n->nud_state;
+	dead = n->dead;
 	read_unlock_bh(&n->lock);
-	__mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID));
+	__mlxsw_sp_nexthop_neigh_update(nh, !(nud_state & NUD_VALID && !dead));
 
 	return 0;
 }
@@ -1391,6 +1398,7 @@ static void mlxsw_sp_nexthop_fini(struct
 {
 	struct mlxsw_sp_neigh_entry *neigh_entry = nh->neigh_entry;
 
+	__mlxsw_sp_nexthop_neigh_update(nh, true);
 	list_del(&nh->neigh_list_node);
 
 	/* If that is the last nexthop connected to that neigh, remove from
@@ -1449,6 +1457,8 @@ mlxsw_sp_nexthop_group_destroy(struct ml
 		nh = &nh_grp->nexthops[i];
 		mlxsw_sp_nexthop_fini(mlxsw_sp, nh);
 	}
+	mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh_grp);
+	WARN_ON_ONCE(nh_grp->adj_index_valid);
 	kfree(nh_grp);
 }
 
@@ -1872,14 +1882,12 @@ static int mlxsw_sp_router_set_abort_tra
 
 static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	struct mlxsw_sp_fib_entry *fib_entry;
 	struct mlxsw_sp_fib_entry *tmp;
 	struct mlxsw_sp_vr *vr;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_virtual_routers; i++) {
+	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
 		vr = &mlxsw_sp->router.vrs[i];
 
 		if (!vr->used)
@@ -1903,6 +1911,9 @@ static void mlxsw_sp_router_fib4_abort(s
 {
 	int err;
 
+	if (mlxsw_sp->router.aborted)
+		return;
+	dev_warn(mlxsw_sp->bus_info->dev, "FIB abort triggered. Note that FIB entries are no longer being offloaded to this device.\n");
 	mlxsw_sp_router_fib_flush(mlxsw_sp);
 	mlxsw_sp->router.aborted = true;
 	err = mlxsw_sp_router_set_abort_trap(mlxsw_sp);
@@ -1912,21 +1923,21 @@ static void mlxsw_sp_router_fib4_abort(s
 
 static int __mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	char rgcr_pl[MLXSW_REG_RGCR_LEN];
+	u64 max_rifs;
 	int err;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	if (!resources->max_rif_valid)
+	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_RIFS))
 		return -EIO;
 
-	mlxsw_sp->rifs = kcalloc(resources->max_rif,
-				 sizeof(struct mlxsw_sp_rif *), GFP_KERNEL);
+	max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS);
+	mlxsw_sp->rifs = kcalloc(max_rifs, sizeof(struct mlxsw_sp_rif *),
+				 GFP_KERNEL);
 	if (!mlxsw_sp->rifs)
 		return -ENOMEM;
 
 	mlxsw_reg_rgcr_pack(rgcr_pl, true);
-	mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, resources->max_rif);
+	mlxsw_reg_rgcr_max_router_interfaces_set(rgcr_pl, max_rifs);
 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
 	if (err)
 		goto err_rgcr_fail;
@@ -1940,47 +1951,101 @@ err_rgcr_fail:
 
 static void __mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp)
 {
-	struct mlxsw_resources *resources;
 	char rgcr_pl[MLXSW_REG_RGCR_LEN];
 	int i;
 
 	mlxsw_reg_rgcr_pack(rgcr_pl, false);
 	mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rgcr), rgcr_pl);
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_rif; i++)
+	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++)
 		WARN_ON_ONCE(mlxsw_sp->rifs[i]);
 
 	kfree(mlxsw_sp->rifs);
 }
 
-static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
-				     unsigned long event, void *ptr)
+struct mlxsw_sp_fib_event_work {
+	struct delayed_work dw;
+	struct fib_entry_notifier_info fen_info;
+	struct mlxsw_sp *mlxsw_sp;
+	unsigned long event;
+};
+
+static void mlxsw_sp_router_fib_event_work(struct work_struct *work)
 {
-	struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
-	struct fib_entry_notifier_info *fen_info = ptr;
+	struct mlxsw_sp_fib_event_work *fib_work =
+		container_of(work, struct mlxsw_sp_fib_event_work, dw.work);
+	struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
 	int err;
 
-	if (!net_eq(fen_info->info.net, &init_net))
-		return NOTIFY_DONE;
-
-	switch (event) {
+	/* Protect internal structures from changes */
+	rtnl_lock();
+	switch (fib_work->event) {
 	case FIB_EVENT_ENTRY_ADD:
-		err = mlxsw_sp_router_fib4_add(mlxsw_sp, fen_info);
+		err = mlxsw_sp_router_fib4_add(mlxsw_sp, &fib_work->fen_info);
 		if (err)
 			mlxsw_sp_router_fib4_abort(mlxsw_sp);
+		fib_info_put(fib_work->fen_info.fi);
 		break;
 	case FIB_EVENT_ENTRY_DEL:
-		mlxsw_sp_router_fib4_del(mlxsw_sp, fen_info);
+		mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info);
+		fib_info_put(fib_work->fen_info.fi);
 		break;
 	case FIB_EVENT_RULE_ADD: /* fall through */
 	case FIB_EVENT_RULE_DEL:
 		mlxsw_sp_router_fib4_abort(mlxsw_sp);
 		break;
 	}
+	rtnl_unlock();
+	kfree(fib_work);
+}
+
+/* Called with rcu_read_lock() */
+static int mlxsw_sp_router_fib_event(struct notifier_block *nb,
+				     unsigned long event, void *ptr)
+{
+	struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
+	struct mlxsw_sp_fib_event_work *fib_work;
+	struct fib_notifier_info *info = ptr;
+
+	if (!net_eq(info->net, &init_net))
+		return NOTIFY_DONE;
+
+	fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
+	if (WARN_ON(!fib_work))
+		return NOTIFY_BAD;
+
+	INIT_DELAYED_WORK(&fib_work->dw, mlxsw_sp_router_fib_event_work);
+	fib_work->mlxsw_sp = mlxsw_sp;
+	fib_work->event = event;
+
+	switch (event) {
+	case FIB_EVENT_ENTRY_ADD: /* fall through */
+	case FIB_EVENT_ENTRY_DEL:
+		memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info));
+		/* Take referece on fib_info to prevent it from being
+		 * freed while work is queued. Release it afterwards.
+		 */
+		fib_info_hold(fib_work->fen_info.fi);
+		break;
+	}
+
+	mlxsw_core_schedule_odw(&fib_work->dw, 0);
+
 	return NOTIFY_DONE;
 }
 
+static void mlxsw_sp_router_fib_dump_flush(struct notifier_block *nb)
+{
+	struct mlxsw_sp *mlxsw_sp = container_of(nb, struct mlxsw_sp, fib_nb);
+
+	/* Flush pending FIB notifications and then flush the device's
+	 * table before requesting another dump. The FIB notification
+	 * block is unregistered, so no need to take RTNL.
+	 */
+	mlxsw_core_flush_owq();
+	mlxsw_sp_router_fib_flush(mlxsw_sp);
+}
+
 int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp)
 {
 	int err;
@@ -1996,14 +2061,20 @@ int mlxsw_sp_router_init(struct mlxsw_sp
 	if (err)
 		goto err_vrs_init;
 
-	err =  mlxsw_sp_neigh_init(mlxsw_sp);
+	err = mlxsw_sp_neigh_init(mlxsw_sp);
 	if (err)
 		goto err_neigh_init;
 
 	mlxsw_sp->fib_nb.notifier_call = mlxsw_sp_router_fib_event;
-	register_fib_notifier(&mlxsw_sp->fib_nb);
+	err = register_fib_notifier(&mlxsw_sp->fib_nb,
+				    mlxsw_sp_router_fib_dump_flush);
+	if (err)
+		goto err_register_fib_notifier;
+
 	return 0;
 
+err_register_fib_notifier:
+	mlxsw_sp_neigh_fini(mlxsw_sp);
 err_neigh_init:
 	mlxsw_sp_vrs_fini(mlxsw_sp);
 err_vrs_init:
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c	2016-12-11 14:17:54.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c	2017-02-12 16:03:20.000000000 -0500
@@ -1196,11 +1196,12 @@ static struct mlxsw_sp_port *mlxsw_sp_la
 						   u16 lag_id)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port;
-	struct mlxsw_resources *resources;
+	u64 max_lag_members;
 	int i;
 
-	resources = mlxsw_core_resources_get(mlxsw_sp->core);
-	for (i = 0; i < resources->max_ports_in_lag; i++) {
+	max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+					     MAX_LAG_MEMBERS);
+	for (i = 0; i < max_lag_members; i++) {
 		mlxsw_sp_port = mlxsw_sp_port_lagged_get(mlxsw_sp, lag_id, i);
 		if (mlxsw_sp_port)
 			return mlxsw_sp_port;
diff -druNp --no-dereference linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/switchib.c linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/switchib.c
--- linux-libre-4.9-gnu/drivers/net/ethernet/mellanox/mlxsw/switchib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-4.10-rc8-gnu/drivers/net/ethernet/mellanox/mlxsw/switchib.c	2017-02-12 16:03:20.000000000 -0500
@@ -0,0 +1,605 @@
+/*
+ * drivers/net/ethernet/mellanox/mlxsw/switchib.c
+ * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2016 Elad Raz <eladr@mellanox.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the names of the copyright holders 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") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/skbuff.h>
+#include <linux/if_vlan.h>
+#include <net/switchdev.h>
+
+#include "pci.h"
+#include "core.h"
+#include "reg.h"
+#include "port.h"
+#include "trap.h"
+#include "txheader.h"
+#include "ib.h"
+
+static const char mlxsw_sib_driver_name[] = "mlxsw_switchib";
+static const char mlxsw_sib2_driver_name[] = "mlxsw_switchib2";
+
+struct mlxsw_sib_port;
+
+struct mlxsw_sib {
+	struct mlxsw_sib_port **ports;
+	struct mlxsw_core *core;
+	const struct mlxsw_bus_info *bus_info;
+};
+
+struct mlxsw_sib_port {
+	struct mlxsw_sib *mlxsw_sib;
+	u8 local_port;
+	struct {
+		u8 module;
+	} mapping;
+};
+
+/* tx_v1_hdr_version
+ * Tx header version.
+ * Must be set to 1.
+ */
+MLXSW_ITEM32(tx_v1, hdr, version, 0x00, 28, 4);
+
+/* tx_v1_hdr_ctl
+ * Packet control type.
+ * 0 - Ethernet control (e.g. EMADs, LACP)
+ * 1 - Ethernet data
+ */
+MLXSW_ITEM32(tx_v1, hdr, ctl, 0x00, 26, 2);
+
+/* tx_v1_hdr_proto
+ * Packet protocol type. Must be set to 1 (Ethernet).
+ */
+MLXSW_ITEM32(tx_v1, hdr, proto, 0x00, 21, 3);
+
+/* tx_v1_hdr_swid
+ * Switch partition ID. Must be set to 0.
+ */
+MLXSW_ITEM32(tx_v1, hdr, swid, 0x00, 12, 3);
+
+/* tx_v1_hdr_control_tclass
+ * Indicates if the packet should use the control TClass and not one
+ * of the data TClasses.
+ */
+MLXSW_ITEM32(tx_v1, hdr, control_tclass, 0x00, 6, 1);
+
+/* tx_v1_hdr_port_mid
+ * Destination local port for unicast packets.
+ * Destination multicast ID for multicast packets.
+ *
+ * Control packets are directed to a specific egress port, while data
+ * packets are transmitted through the CPU port (0) into the switch partition,
+ * where forwarding rules are applied.
+ */
+MLXSW_ITEM32(tx_v1, hdr, port_mid, 0x04, 16, 16);
+
+/* tx_v1_hdr_type
+ * 0 - Data packets
+ * 6 - Control packets
+ */
+MLXSW_ITEM32(tx_v1, hdr, type, 0x0C, 0, 4);
+
+static void
+mlxsw_sib_tx_v1_hdr_construct(struct sk_buff *skb,
+			      const struct mlxsw_tx_info *tx_info)
+{
+	char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
+
+	memset(txhdr, 0, MLXSW_TXHDR_LEN);
+
+	mlxsw_tx_v1_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1);
+	mlxsw_tx_v1_hdr_ctl_set(txhdr, MLXSW_TXHDR_ETH_CTL);
+	mlxsw_tx_v1_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
+	mlxsw_tx_v1_hdr_swid_set(txhdr, 0);
+	mlxsw_tx_v1_hdr_control_tclass_set(txhdr, 1);
+	mlxsw_tx_v1_hdr_port_mid_set(txhdr, tx_info->local_port);
+	mlxsw_tx_v1_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
+}
+
+static int
+mlxsw_sib_port_admin_status_set(struct mlxsw_sib_port *mlxsw_sib_port,
+				bool is_up)
+{
+	struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+	char paos_pl[MLXSW_REG_PAOS_LEN];
+
+	mlxsw_reg_paos_pack(paos_pl, mlxsw_sib_port->local_port,
+			    is_up ? MLXSW_PORT_ADMIN_STATUS_UP :
+			    MLXSW_PORT_ADMIN_STATUS_DOWN);
+	return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(paos), paos_pl);
+}
+
+static int mlxsw_sib_port_mtu_set(struct mlxsw_sib_port *mlxsw_sib_port,
+				  u16 mtu)
+{
+	struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+	char pmtu_pl[MLXSW_REG_PMTU_LEN];
+	int max_mtu;
+	int err;
+
+	mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, 0);
+	err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl);
+	if (err)
+		return err;
+	max_mtu = mlxsw_reg_pmtu_max_mtu_get(pmtu_pl);
+
+	if (mtu > max_mtu)
+		return -EINVAL;
+
+	mlxsw_reg_pmtu_pack(pmtu_pl, mlxsw_sib_port->local_port, mtu);
+	return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pmtu), pmtu_pl);
+}
+
+static int mlxsw_sib_port_set(struct mlxsw_sib_port *mlxsw_sib_port, u8 port)
+{
+	struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+	char plib_pl[MLXSW_REG_PLIB_LEN] = {0};
+	int err;
+
+	mlxsw_reg_plib_local_port_set(plib_pl, mlxsw_sib_port->local_port);
+	mlxsw_reg_plib_ib_port_set(plib_pl, port);
+	err = mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(plib), plib_pl);
+	return err;
+}
+
+static int mlxsw_sib_port_swid_set(struct mlxsw_sib_port *mlxsw_sib_port,
+				   u8 swid)
+{
+	struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+	char pspa_pl[MLXSW_REG_PSPA_LEN];
+
+	mlxsw_reg_pspa_pack(pspa_pl, swid, mlxsw_sib_port->local_port);
+	return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(pspa), pspa_pl);
+}
+
+static int mlxsw_sib_port_module_info_get(struct mlxsw_sib *mlxsw_sib,
+					  u8 local_port, u8 *p_module,
+					  u8 *p_width)
+{
+	char pmlp_pl[MLXSW_REG_PMLP_LEN];
+	int err;
+
+	mlxsw_reg_pmlp_pack(pmlp_pl, local_port);
+	err = mlxsw_reg_query(mlxsw_sib->core, MLXSW_REG(pmlp), pmlp_pl);
+	if (err)
+		return err;
+	*p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
+	*p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
+	return 0;
+}
+
+static int mlxsw_sib_port_speed_set(struct mlxsw_sib_port *mlxsw_sib_port,
+				    u16 speed, u16 width)
+{
+	struct mlxsw_sib *mlxsw_sib = mlxsw_sib_port->mlxsw_sib;
+	char ptys_pl[MLXSW_REG_PTYS_LEN];
+
+	mlxsw_reg_ptys_ib_pack(ptys_pl, mlxsw_sib_port->local_port, speed,
+			       width);
+	return mlxsw_reg_write(mlxsw_sib->core, MLXSW_REG(ptys), ptys_pl);
+}
+
+static bool mlxsw_sib_port_created(struct mlxsw_sib *mlxsw_sib, u8 local_port)
+{
+	return mlxsw_sib->ports[local_port] != NULL;
+}
+
+static int __mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port,
+				   u8 module, u8 width)
+{
+	struct mlxsw_sib_port *mlxsw_sib_port;
+	int err;
+
+	mlxsw_sib_port = kzalloc(sizeof(*mlxsw_sib_port), GFP_KERNEL);
+	if (!mlxsw_sib_port)
+		return -ENOMEM;
+	mlxsw_sib_port->mlxsw_sib = mlxsw_sib;
+	mlxsw_sib_port->local_port = local_port;
+	mlxsw_sib_port->mapping.module = module;
+
+	err = mlxsw_sib_port_swid_set(mlxsw_sib_port, 0);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set SWID\n",
+			mlxsw_sib_port->local_port);
+		goto err_port_swid_set;
+	}
+
+	/* Expose the IB port number as it's front panel name */
+	err = mlxsw_sib_port_set(mlxsw_sib_port, module + 1);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set IB port\n",
+			mlxsw_sib_port->local_port);
+		goto err_port_ib_set;
+	}
+
+	/* Supports all speeds from SDR to FDR (bitmask) and support bus width
+	 * of 1x, 2x and 4x (3 bits bitmask)
+	 */
+	err = mlxsw_sib_port_speed_set(mlxsw_sib_port,
+				       MLXSW_REG_PTYS_IB_SPEED_EDR - 1,
+				       BIT(3) - 1);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set speed\n",
+			mlxsw_sib_port->local_port);
+		goto err_port_speed_set;
+	}
+
+	/* Change to the maximum MTU the device supports, the SMA will take
+	 * care of the active MTU
+	 */
+	err = mlxsw_sib_port_mtu_set(mlxsw_sib_port, MLXSW_IB_DEFAULT_MTU);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to set MTU\n",
+			mlxsw_sib_port->local_port);
+		goto err_port_mtu_set;
+	}
+
+	err = mlxsw_sib_port_admin_status_set(mlxsw_sib_port, true);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to change admin state to UP\n",
+			mlxsw_sib_port->local_port);
+		goto err_port_admin_set;
+	}
+
+	mlxsw_core_port_ib_set(mlxsw_sib->core, mlxsw_sib_port->local_port,
+			       mlxsw_sib_port);
+	mlxsw_sib->ports[local_port] = mlxsw_sib_port;
+	return 0;
+
+err_port_admin_set:
+err_port_mtu_set:
+err_port_speed_set:
+err_port_ib_set:
+	mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT);
+err_port_swid_set:
+	kfree(mlxsw_sib_port);
+	return err;
+}
+
+static int mlxsw_sib_port_create(struct mlxsw_sib *mlxsw_sib, u8 local_port,
+				 u8 module, u8 width)
+{
+	int err;
+
+	err = mlxsw_core_port_init(mlxsw_sib->core, local_port);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Port %d: Failed to init core port\n",
+			local_port);
+		return err;
+	}
+	err = __mlxsw_sib_port_create(mlxsw_sib, local_port, module, width);
+	if (err)
+		goto err_port_create;
+
+	return 0;
+
+err_port_create:
+	mlxsw_core_port_fini(mlxsw_sib->core, local_port);
+	return err;
+}
+
+static void __mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port)
+{
+	struct mlxsw_sib_port *mlxsw_sib_port = mlxsw_sib->ports[local_port];
+
+	mlxsw_core_port_clear(mlxsw_sib->core, local_port, mlxsw_sib);
+	mlxsw_sib->ports[local_port] = NULL;
+	mlxsw_sib_port_admin_status_set(mlxsw_sib_port, false);
+	mlxsw_sib_port_swid_set(mlxsw_sib_port, MLXSW_PORT_SWID_DISABLED_PORT);
+	kfree(mlxsw_sib_port);
+}
+
+static void mlxsw_sib_port_remove(struct mlxsw_sib *mlxsw_sib, u8 local_port)
+{
+	__mlxsw_sib_port_remove(mlxsw_sib, local_port);
+	mlxsw_core_port_fini(mlxsw_sib->core, local_port);
+}
+
+static void mlxsw_sib_ports_remove(struct mlxsw_sib *mlxsw_sib)
+{
+	int i;
+
+	for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++)
+		if (mlxsw_sib_port_created(mlxsw_sib, i))
+			mlxsw_sib_port_remove(mlxsw_sib, i);
+	kfree(mlxsw_sib->ports);
+}
+
+static int mlxsw_sib_ports_create(struct mlxsw_sib *mlxsw_sib)
+{
+	size_t alloc_size;
+	u8 module, width;
+	int i;
+	int err;
+
+	alloc_size = sizeof(struct mlxsw_sib_port *) * MLXSW_PORT_MAX_IB_PORTS;
+	mlxsw_sib->ports = kzalloc(alloc_size, GFP_KERNEL);
+	if (!mlxsw_sib->ports)
+		return -ENOMEM;
+
+	for (i = 1; i < MLXSW_PORT_MAX_IB_PORTS; i++) {
+		err = mlxsw_sib_port_module_info_get(mlxsw_sib, i, &module,
+						     &width);
+		if (err)
+			goto err_port_module_info_get;
+		if (!width)
+			continue;
+		err = mlxsw_sib_port_create(mlxsw_sib, i, module, width);
+		if (err)
+			goto err_port_create;
+	}
+	return 0;
+
+err_port_create:
+err_port_module_info_get:
+	for (i--; i >= 1; i--)
+		if (mlxsw_sib_port_created(mlxsw_sib, i))
+			mlxsw_sib_port_remove(mlxsw_sib, i);
+	kfree(mlxsw_sib->ports);
+	return err;
+}
+
+static void
+mlxsw_sib_pude_ib_event_func(struct mlxsw_sib_port *mlxsw_sib_port,
+			     enum mlxsw_reg_pude_oper_status status)
+{
+	if (status == MLXSW_PORT_OPER_STATUS_UP)
+		pr_info("ib link for port %d - up\n",
+			mlxsw_sib_port->mapping.module + 1);
+	else
+		pr_info("ib link for port %d - down\n",
+			mlxsw_sib_port->mapping.module + 1);
+}
+
+static void mlxsw_sib_pude_event_func(const struct mlxsw_reg_info *reg,
+				      char *pude_pl, void *priv)
+{
+	struct mlxsw_sib *mlxsw_sib = priv;
+	struct mlxsw_sib_port *mlxsw_sib_port;
+	enum mlxsw_reg_pude_oper_status status;
+	u8 local_port;
+
+	local_port = mlxsw_reg_pude_local_port_get(pude_pl);
+	mlxsw_sib_port = mlxsw_sib->ports[local_port];
+	if (!mlxsw_sib_port) {
+		dev_warn(mlxsw_sib->bus_info->dev, "Port %d: Link event received for non-existent port\n",
+			 local_port);
+		return;
+	}
+
+	status = mlxsw_reg_pude_oper_status_get(pude_pl);
+	mlxsw_sib_pude_ib_event_func(mlxsw_sib_port, status);
+}
+
+static const struct mlxsw_listener mlxsw_sib_listener[] = {
+	MLXSW_EVENTL(mlxsw_sib_pude_event_func, PUDE, EMAD),
+};
+
+static int mlxsw_sib_taps_init(struct mlxsw_sib *mlxsw_sib)
+{
+	int i;
+	int err;
+
+	for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) {
+		err = mlxsw_core_trap_register(mlxsw_sib->core,
+					       &mlxsw_sib_listener[i],
+					       mlxsw_sib);
+		if (err)
+			goto err_rx_listener_register;
+	}
+
+	return 0;
+
+err_rx_listener_register:
+	for (i--; i >= 0; i--) {
+		mlxsw_core_trap_unregister(mlxsw_sib->core,
+					   &mlxsw_sib_listener[i],
+					   mlxsw_sib);
+	}
+
+	return err;
+}
+
+static void mlxsw_sib_traps_fini(struct mlxsw_sib *mlxsw_sib)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mlxsw_sib_listener); i++) {
+		mlxsw_core_trap_unregister(mlxsw_sib->core,
+					   &mlxsw_sib_listener[i], mlxsw_sib);
+	}
+}
+
+static int mlxsw_sib_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
+{
+	char htgt_pl[MLXSW_REG_HTGT_LEN];
+
+	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
+			    MLXSW_REG_HTGT_INVALID_POLICER,
+			    MLXSW_REG_HTGT_DEFAULT_PRIORITY,
+			    MLXSW_REG_HTGT_DEFAULT_TC);
+	mlxsw_reg_htgt_swid_set(htgt_pl, MLXSW_PORT_SWID_ALL_SWIDS);
+	mlxsw_reg_htgt_local_path_rdq_set(htgt_pl,
+					MLXSW_REG_HTGT_LOCAL_PATH_RDQ_SIB_EMAD);
+	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
+}
+
+static int mlxsw_sib_init(struct mlxsw_core *mlxsw_core,
+			  const struct mlxsw_bus_info *mlxsw_bus_info)
+{
+	struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core);
+	int err;
+
+	mlxsw_sib->core = mlxsw_core;
+	mlxsw_sib->bus_info = mlxsw_bus_info;
+
+	err = mlxsw_sib_ports_create(mlxsw_sib);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Failed to create ports\n");
+		return err;
+	}
+
+	err = mlxsw_sib_taps_init(mlxsw_sib);
+	if (err) {
+		dev_err(mlxsw_sib->bus_info->dev, "Failed to set traps\n");
+		goto err_traps_init_err;
+	}
+
+	return 0;
+
+err_traps_init_err:
+	mlxsw_sib_ports_remove(mlxsw_sib);
+	return err;
+}
+
+static void mlxsw_sib_fini(struct mlxsw_core *mlxsw_core)
+{
+	struct mlxsw_sib *mlxsw_sib = mlxsw_core_driver_priv(mlxsw_core);
+
+	mlxsw_sib_traps_fini(mlxsw_sib);
+	mlxsw_sib_ports_remove(mlxsw_sib);
+}
+
+static struct mlxsw_config_profile mlxsw_sib_config_profile = {
+	.used_max_system_port		= 1,
+	.max_system_port		= 48000,
+	.used_max_ib_mc			= 1,
+	.max_ib_mc			= 27,
+	.used_max_pkey			= 1,
+	.max_pkey			= 32,
+	.swid_config			= {
+		{
+			.used_type	= 1,
+			.type		= MLXSW_PORT_SWID_TYPE_IB,
+		}
+	},
+	.resource_query_enable		= 0,
+};
+
+static struct mlxsw_driver mlxsw_sib_driver = {
+	.kind			= mlxsw_sib_driver_name,
+	.priv_size		= sizeof(struct mlxsw_sib),
+	.init			= mlxsw_sib_init,
+	.fini			= mlxsw_sib_fini,
+	.basic_trap_groups_set	= mlxsw_sib_basic_trap_groups_set,
+	.txhdr_construct	= mlxsw_sib_tx_v1_hdr_construct,
+	.txhdr_len		= MLXSW_TXHDR_LEN,
+	.profile		= &mlxsw_sib_config_profile,
+};
+
+static struct mlxsw_driver mlxsw_sib2_driver = {
+	.kind			= mlxsw_sib2_driver_name,
+	.priv_size		= sizeof(struct mlxsw_sib),
+	.init			= mlxsw_sib_init,
+	.fini			= mlxsw_sib_fini,
+	.basic_trap_groups_set	= mlxsw_sib_basic_trap_groups_set,
+	.txhdr_construct	= mlxsw_sib_tx_v1_hdr_construct,
+	.txhdr_len		= MLXSW_TXHDR_LEN,
+	.profile		= &mlxsw_sib_config_profile,
+};
+
+static const struct pci_device_id mlxsw_sib_pci_id_table[] = {
+	{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB), 0},
+	{0, },
+};
+
+static struct pci_driver mlxsw_sib_pci_driver = {
+	.name = mlxsw_sib_driver_name,
+	.id_table = mlxsw_sib_pci_id_table,
+};
+
+static const struct pci_device_id mlxsw_sib2_pci_id_table[] = {
+	{PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SWITCHIB2), 0},
+	{0, },
+};
+
+static struct pci_driver mlxsw_sib2_pci_driver = {
+	.name = mlxsw_sib2_driver_name,
+	.id_table = mlxsw_sib2_pci_id_table,
+};
+
+static int __init mlxsw_sib_module_init(void)
+{
+	int err;
+
+	err = mlxsw_core_driver_register(&mlxsw_sib_driver);
+	if (err)
+		return err;
+
+	err = mlxsw_core_driver_register(&